From d62a17aedeb0eebdba98238874bb13d62c48dbf9 Mon Sep 17 00:00:00 2001 From: whitespace / reindent Date: Mon, 17 Jul 2017 14:03:14 +0200 Subject: [PATCH] *: reindent indent.py `git ls-files | pcregrep '\.[ch]$' | pcregrep -v '^(ldpd|babeld|nhrpd)/'` Signed-off-by: David Lamparter --- bgpd/bgp_advertise.c | 332 +- bgpd/bgp_advertise.h | 238 +- bgpd/bgp_aspath.c | 3336 ++-- bgpd/bgp_aspath.h | 142 +- bgpd/bgp_attr.c | 6017 ++++--- bgpd/bgp_attr.h | 382 +- bgpd/bgp_attr_evpn.c | 236 +- bgpd/bgp_attr_evpn.h | 31 +- bgpd/bgp_bfd.c | 933 +- bgpd/bgp_bfd.h | 23 +- bgpd/bgp_btoa.c | 485 +- bgpd/bgp_clist.c | 1866 ++- bgpd/bgp_clist.h | 158 +- bgpd/bgp_community.c | 992 +- bgpd/bgp_community.h | 67 +- bgpd/bgp_damp.c | 1125 +- bgpd/bgp_damp.h | 190 +- bgpd/bgp_debug.c | 3064 ++-- bgpd/bgp_debug.h | 48 +- bgpd/bgp_dump.c | 1307 +- bgpd/bgp_dump.h | 8 +- bgpd/bgp_ecommunity.c | 1370 +- bgpd/bgp_ecommunity.h | 128 +- bgpd/bgp_encap_tlv.c | 1528 +- bgpd/bgp_encap_tlv.h | 178 +- bgpd/bgp_encap_types.h | 202 +- bgpd/bgp_evpn.c | 4190 +++-- bgpd/bgp_evpn.h | 56 +- bgpd/bgp_evpn_private.h | 223 +- bgpd/bgp_evpn_vty.c | 3028 ++-- bgpd/bgp_evpn_vty.h | 7 +- bgpd/bgp_filter.c | 936 +- bgpd/bgp_filter.h | 18 +- bgpd/bgp_fsm.c | 2999 ++-- bgpd/bgp_fsm.h | 137 +- bgpd/bgp_label.c | 566 +- bgpd/bgp_label.h | 116 +- bgpd/bgp_lcommunity.c | 790 +- bgpd/bgp_lcommunity.h | 62 +- bgpd/bgp_main.c | 522 +- bgpd/bgp_memory.c | 164 +- bgpd/bgp_mpath.c | 1066 +- bgpd/bgp_mpath.h | 61 +- bgpd/bgp_mplsvpn.c | 1497 +- bgpd/bgp_mplsvpn.h | 79 +- bgpd/bgp_network.c | 1248 +- bgpd/bgp_network.h | 12 +- bgpd/bgp_nexthop.c | 745 +- bgpd/bgp_nexthop.h | 62 +- bgpd/bgp_nht.c | 1195 +- bgpd/bgp_nht.h | 8 +- bgpd/bgp_open.c | 2722 ++-- bgpd/bgp_open.h | 47 +- bgpd/bgp_packet.c | 4134 +++-- bgpd/bgp_packet.h | 44 +- bgpd/bgp_rd.c | 287 +- bgpd/bgp_rd.h | 44 +- bgpd/bgp_regex.c | 84 +- bgpd/bgp_regex.h | 10 +- bgpd/bgp_route.c | 18586 +++++++++++----------- bgpd/bgp_route.h | 571 +- bgpd/bgp_routemap.c | 5637 ++++--- bgpd/bgp_snmp.c | 1417 +- bgpd/bgp_table.c | 89 +- bgpd/bgp_table.h | 212 +- bgpd/bgp_updgrp.c | 2744 ++-- bgpd/bgp_updgrp.h | 705 +- bgpd/bgp_updgrp_adv.c | 1338 +- bgpd/bgp_updgrp_packet.c | 2025 +-- bgpd/bgp_vnc_types.h | 12 +- bgpd/bgp_vpn.c | 365 +- bgpd/bgp_vpn.h | 6 +- bgpd/bgp_vty.c | 18006 +++++++++++---------- bgpd/bgp_vty.h | 58 +- bgpd/bgp_zebra.c | 3676 +++-- bgpd/bgp_zebra.h | 71 +- bgpd/bgpd.c | 13657 ++++++++-------- bgpd/bgpd.h | 1691 +- bgpd/rfapi/bgp_rfapi_cfg.c | 7868 +++++---- bgpd/rfapi/bgp_rfapi_cfg.h | 451 +- bgpd/rfapi/rfapi.c | 6791 ++++---- bgpd/rfapi/rfapi.h | 568 +- bgpd/rfapi/rfapi_ap.c | 921 +- bgpd/rfapi/rfapi_ap.h | 48 +- bgpd/rfapi/rfapi_backend.h | 60 +- bgpd/rfapi/rfapi_descriptor_rfp_utils.c | 107 +- bgpd/rfapi/rfapi_descriptor_rfp_utils.h | 12 +- bgpd/rfapi/rfapi_encap_tlv.c | 1240 +- bgpd/rfapi/rfapi_encap_tlv.h | 21 +- bgpd/rfapi/rfapi_import.c | 8714 +++++----- bgpd/rfapi/rfapi_import.h | 281 +- bgpd/rfapi/rfapi_monitor.c | 2677 ++-- bgpd/rfapi/rfapi_monitor.h | 222 +- bgpd/rfapi/rfapi_nve_addr.c | 169 +- bgpd/rfapi/rfapi_nve_addr.h | 18 +- bgpd/rfapi/rfapi_private.h | 559 +- bgpd/rfapi/rfapi_rib.c | 4142 +++-- bgpd/rfapi/rfapi_rib.h | 184 +- bgpd/rfapi/rfapi_vty.c | 7594 +++++---- bgpd/rfapi/rfapi_vty.h | 188 +- bgpd/rfapi/vnc_debug.c | 174 +- bgpd/rfapi/vnc_debug.h | 5 +- bgpd/rfapi/vnc_export_bgp.c | 3660 +++-- bgpd/rfapi/vnc_export_bgp.h | 12 +- bgpd/rfapi/vnc_export_bgp_p.h | 104 +- bgpd/rfapi/vnc_export_table.c | 298 +- bgpd/rfapi/vnc_export_table.h | 62 +- bgpd/rfapi/vnc_import_bgp.c | 5455 ++++--- bgpd/rfapi/vnc_import_bgp.h | 82 +- bgpd/rfapi/vnc_import_bgp_p.h | 28 +- bgpd/rfapi/vnc_zebra.c | 1817 +-- bgpd/rfapi/vnc_zebra.h | 46 +- bgpd/rfp-example/librfp/rfp.h | 6 +- bgpd/rfp-example/librfp/rfp_example.c | 209 +- bgpd/rfp-example/librfp/rfp_internal.h | 2 +- bgpd/rfp-example/rfptest/rfptest.c | 9 +- bgpd/rfp-example/rfptest/rfptest.h | 2 +- defaults.h | 2 +- eigrpd/eigrp_const.h | 40 +- eigrpd/eigrp_dump.c | 777 +- eigrpd/eigrp_dump.h | 130 +- eigrpd/eigrp_filter.c | 380 +- eigrpd/eigrp_filter.h | 10 +- eigrpd/eigrp_fsm.c | 827 +- eigrpd/eigrp_fsm.h | 5 +- eigrpd/eigrp_hello.c | 944 +- eigrpd/eigrp_interface.c | 810 +- eigrpd/eigrp_interface.h | 59 +- eigrpd/eigrp_macros.h | 48 +- eigrpd/eigrp_main.c | 234 +- eigrpd/eigrp_memory.c | 26 +- eigrpd/eigrp_memory.h | 2 +- eigrpd/eigrp_neighbor.c | 435 +- eigrpd/eigrp_neighbor.h | 14 +- eigrpd/eigrp_network.c | 697 +- eigrpd/eigrp_network.h | 29 +- eigrpd/eigrp_packet.c | 2244 ++- eigrpd/eigrp_packet.h | 172 +- eigrpd/eigrp_query.c | 324 +- eigrpd/eigrp_reply.c | 372 +- eigrpd/eigrp_routemap.c | 1427 +- eigrpd/eigrp_routemap.h | 12 +- eigrpd/eigrp_siaquery.c | 206 +- eigrpd/eigrp_siareply.c | 206 +- eigrpd/eigrp_snmp.c | 2391 +-- eigrpd/eigrp_snmp.h | 2 +- eigrpd/eigrp_structs.h | 742 +- eigrpd/eigrp_topology.c | 692 +- eigrpd/eigrp_topology.h | 55 +- eigrpd/eigrp_update.c | 1887 +-- eigrpd/eigrp_vty.c | 1732 +- eigrpd/eigrp_vty.h | 7 +- eigrpd/eigrp_zebra.c | 748 +- eigrpd/eigrp_zebra.h | 12 +- eigrpd/eigrpd.c | 332 +- eigrpd/eigrpd.h | 14 +- fpm/fpm.h | 160 +- fpm/fpm_pb.h | 34 +- isisd/dict.c | 1901 +-- isisd/dict.h | 32 +- isisd/isis_adjacency.c | 882 +- isisd/isis_adjacency.h | 153 +- isisd/isis_bpf.c | 469 +- isisd/isis_circuit.c | 2366 ++- isisd/isis_circuit.h | 293 +- isisd/isis_common.h | 50 +- isisd/isis_constants.h | 28 +- isisd/isis_csm.c | 310 +- isisd/isis_csm.h | 19 +- isisd/isis_dlpi.c | 1007 +- isisd/isis_dr.c | 537 +- isisd/isis_dr.h | 39 +- isisd/isis_dynhn.c | 187 +- isisd/isis_dynhn.h | 37 +- isisd/isis_events.c | 374 +- isisd/isis_events.h | 33 +- isisd/isis_flags.c | 81 +- isisd/isis_flags.h | 61 +- isisd/isis_lsp.c | 5270 +++--- isisd/isis_lsp.h | 145 +- isisd/isis_main.c | 214 +- isisd/isis_memory.c | 38 +- isisd/isis_misc.c | 831 +- isisd/isis_misc.h | 65 +- isisd/isis_mt.c | 957 +- isisd/isis_mt.h | 127 +- isisd/isis_network.h | 26 +- isisd/isis_pdu.c | 5312 +++---- isisd/isis_pdu.h | 173 +- isisd/isis_pfpacket.c | 685 +- isisd/isis_redist.c | 1273 +- isisd/isis_redist.h | 42 +- isisd/isis_route.c | 988 +- isisd/isis_route.h | 65 +- isisd/isis_routemap.c | 264 +- isisd/isis_routemap.h | 12 +- isisd/isis_spf.c | 2375 ++- isisd/isis_spf.h | 101 +- isisd/isis_te.c | 2006 +-- isisd/isis_te.h | 249 +- isisd/isis_tlv.c | 2540 ++- isisd/isis_tlv.h | 254 +- isisd/isis_vty.c | 2190 ++- isisd/isis_zebra.c | 1093 +- isisd/isis_zebra.h | 22 +- isisd/isisd.c | 3240 ++-- isisd/isisd.h | 240 +- isisd/iso_checksum.c | 57 +- isisd/iso_checksum.h | 16 +- lib/agentx.c | 454 +- lib/bfd.c | 708 +- lib/bfd.h | 90 +- lib/bitfield.h | 109 +- lib/buffer.c | 754 +- lib/buffer.h | 59 +- lib/checksum.c | 148 +- lib/checksum.h | 3 +- lib/clippy.c | 35 +- lib/command.c | 3368 ++-- lib/command.h | 443 +- lib/command_graph.c | 737 +- lib/command_graph.h | 101 +- lib/command_match.c | 1444 +- lib/command_match.h | 51 +- lib/command_py.c | 152 +- lib/csv.c | 1155 +- lib/csv.h | 14 +- lib/distribute.c | 741 +- lib/distribute.h | 50 +- lib/event_counter.c | 37 +- lib/event_counter.h | 11 +- lib/fifo.h | 66 +- lib/filter.c | 2377 ++- lib/filter.h | 44 +- lib/frr_pthread.c | 155 +- lib/frr_pthread.h | 31 +- lib/frratomic.h | 105 +- lib/getopt.c | 1337 +- lib/getopt.h | 55 +- lib/getopt1.c | 189 +- lib/grammar_sandbox.c | 992 +- lib/grammar_sandbox_main.c | 40 +- lib/graph.c | 181 +- lib/graph.h | 36 +- lib/hash.c | 695 +- lib/hash.h | 104 +- lib/hook.c | 7 +- lib/hook.h | 100 +- lib/if.c | 1475 +- lib/if.h | 503 +- lib/if_rmap.c | 398 +- lib/if_rmap.h | 28 +- lib/imsg-buffer.c | 105 +- lib/imsg.c | 117 +- lib/imsg.h | 110 +- lib/ipaddr.h | 78 +- lib/jhash.c | 254 +- lib/jhash.h | 6 +- lib/json.c | 61 +- lib/json.h | 23 +- lib/keychain.c | 1307 +- lib/keychain.h | 41 +- lib/libfrr.c | 146 +- lib/libfrr.h | 35 +- lib/linklist.c | 404 +- lib/linklist.h | 145 +- lib/log.c | 1690 +- lib/log.h | 124 +- lib/log_int.h | 36 +- lib/md5.c | 502 +- lib/md5.h | 34 +- lib/memory.c | 19 +- lib/memory.h | 150 +- lib/memory_vty.c | 204 +- lib/memory_vty.h | 4 +- lib/module.c | 28 +- lib/module.h | 20 +- lib/monotime.h | 58 +- lib/mpls.h | 137 +- lib/network.c | 145 +- lib/network.h | 10 +- lib/nexthop.c | 337 +- lib/nexthop.h | 127 +- lib/ns.c | 575 +- lib/ns.h | 38 +- lib/openbsd-queue.h | 740 +- lib/openbsd-tree.c | 146 +- lib/openbsd-tree.h | 809 +- lib/pid_output.c | 79 +- lib/plist.c | 3024 ++-- lib/plist.h | 50 +- lib/plist_int.h | 58 +- lib/pqueue.c | 227 +- lib/pqueue.h | 31 +- lib/prefix.c | 1935 ++- lib/prefix.h | 309 +- lib/privs.c | 1409 +- lib/privs.h | 96 +- lib/ptm_lib.c | 800 +- lib/ptm_lib.h | 31 +- lib/qobj.c | 98 +- lib/qobj.h | 63 +- lib/queue.h | 892 +- lib/routemap.c | 4017 +++-- lib/routemap.h | 503 +- lib/sha256.c | 587 +- lib/sha256.h | 26 +- lib/sigevent.c | 460 +- lib/sigevent.h | 17 +- lib/skiplist.c | 880 +- lib/skiplist.h | 178 +- lib/smux.c | 2326 ++- lib/smux.h | 81 +- lib/snmp.c | 142 +- lib/sockopt.c | 908 +- lib/sockopt.h | 58 +- lib/sockunion.c | 1007 +- lib/sockunion.h | 82 +- lib/spf_backoff.c | 412 +- lib/spf_backoff.h | 16 +- lib/srcdest_table.c | 412 +- lib/srcdest_table.h | 48 +- lib/stream.c | 1654 +- lib/stream.h | 180 +- lib/strlcat.c | 63 +- lib/strlcpy.c | 44 +- lib/systemd.c | 107 +- lib/systemd.h | 7 +- lib/table.c | 1162 +- lib/table.h | 288 +- lib/termtable.c | 2 +- lib/termtable.h | 4 +- lib/thread.c | 2319 ++- lib/thread.h | 251 +- lib/vector.c | 196 +- lib/vector.h | 39 +- lib/vrf.c | 626 +- lib/vrf.h | 132 +- lib/vrf_int.h | 5 +- lib/vty.c | 4643 +++--- lib/vty.h | 289 +- lib/wheel.c | 165 +- lib/wheel.h | 45 +- lib/workqueue.c | 573 +- lib/workqueue.h | 153 +- lib/zassert.h | 13 +- lib/zclient.c | 3447 ++-- lib/zclient.h | 506 +- lib/zebra.h | 191 +- ospf6d/ospf6_abr.c | 1949 ++- ospf6d/ospf6_abr.h | 68 +- ospf6d/ospf6_area.c | 1360 +- ospf6d/ospf6_area.h | 120 +- ospf6d/ospf6_asbr.c | 1961 ++- ospf6d/ospf6_asbr.h | 97 +- ospf6d/ospf6_bfd.c | 505 +- ospf6d/ospf6_bfd.h | 25 +- ospf6d/ospf6_flood.c | 1727 +- ospf6d/ospf6_flood.h | 53 +- ospf6d/ospf6_interface.c | 2786 ++-- ospf6d/ospf6_interface.h | 171 +- ospf6d/ospf6_intra.c | 3141 ++-- ospf6d/ospf6_intra.h | 315 +- ospf6d/ospf6_lsa.c | 1342 +- ospf6d/ospf6_lsa.h | 314 +- ospf6d/ospf6_lsdb.c | 694 +- ospf6d/ospf6_lsdb.h | 102 +- ospf6d/ospf6_main.c | 240 +- ospf6d/ospf6_memory.c | 30 +- ospf6d/ospf6_message.c | 4507 +++--- ospf6d/ospf6_message.h | 128 +- ospf6d/ospf6_neighbor.c | 1455 +- ospf6d/ospf6_neighbor.h | 186 +- ospf6d/ospf6_network.c | 362 +- ospf6d/ospf6_network.h | 15 +- ospf6d/ospf6_proto.c | 77 +- ospf6d/ospf6_proto.h | 51 +- ospf6d/ospf6_route.c | 2610 ++- ospf6d/ospf6_route.h | 406 +- ospf6d/ospf6_snmp.c | 2125 +-- ospf6d/ospf6_spf.c | 1407 +- ospf6d/ospf6_spf.h | 169 +- ospf6d/ospf6_top.c | 1173 +- ospf6d/ospf6_top.h | 109 +- ospf6d/ospf6_zebra.c | 1354 +- ospf6d/ospf6_zebra.h | 54 +- ospf6d/ospf6d.c | 1645 +- ospf6d/ospf6d.h | 69 +- ospfclient/ospf_apiclient.c | 1036 +- ospfclient/ospf_apiclient.h | 127 +- ospfclient/ospfclient.c | 454 +- ospfd/ospf_abr.c | 3099 ++-- ospfd/ospf_abr.h | 98 +- ospfd/ospf_api.c | 846 +- ospfd/ospf_api.h | 331 +- ospfd/ospf_apiserver.c | 4053 +++-- ospfd/ospf_apiserver.h | 250 +- ospfd/ospf_asbr.c | 434 +- ospfd/ospf_asbr.h | 77 +- ospfd/ospf_ase.c | 1304 +- ospfd/ospf_ase.h | 30 +- ospfd/ospf_bfd.c | 544 +- ospfd/ospf_bfd.h | 30 +- ospfd/ospf_dump.c | 2497 ++- ospfd/ospf_dump.h | 73 +- ospfd/ospf_dump_api.c | 188 +- ospfd/ospf_dump_api.h | 4 +- ospfd/ospf_flood.c | 1610 +- ospfd/ospf_flood.h | 81 +- ospfd/ospf_ia.c | 1222 +- ospfd/ospf_ia.h | 24 +- ospfd/ospf_interface.c | 1875 ++- ospfd/ospf_interface.h | 463 +- ospfd/ospf_ism.c | 930 +- ospfd/ospf_ism.h | 80 +- ospfd/ospf_lsa.c | 6436 ++++---- ospfd/ospf_lsa.h | 369 +- ospfd/ospf_lsdb.c | 447 +- ospfd/ospf_lsdb.h | 72 +- ospfd/ospf_main.c | 258 +- ospfd/ospf_memory.c | 52 +- ospfd/ospf_neighbor.c | 741 +- ospfd/ospf_neighbor.h | 166 +- ospfd/ospf_network.c | 312 +- ospfd/ospf_network.h | 15 +- ospfd/ospf_nsm.c | 1369 +- ospfd/ospf_nsm.h | 38 +- ospfd/ospf_opaque.c | 3315 ++-- ospfd/ospf_opaque.h | 138 +- ospfd/ospf_packet.c | 7015 ++++---- ospfd/ospf_packet.h | 169 +- ospfd/ospf_ri.c | 2274 ++- ospfd/ospf_ri.h | 86 +- ospfd/ospf_route.c | 1631 +- ospfd/ospf_route.h | 165 +- ospfd/ospf_routemap.c | 723 +- ospfd/ospf_snmp.c | 4597 +++--- ospfd/ospf_spf.c | 2371 ++- ospfd/ospf_spf.h | 56 +- ospfd/ospf_te.c | 4262 +++-- ospfd/ospf_te.h | 407 +- ospfd/ospf_vty.c | 12939 +++++++-------- ospfd/ospf_vty.h | 58 +- ospfd/ospf_zebra.c | 2507 ++- ospfd/ospf_zebra.h | 76 +- ospfd/ospfd.c | 2691 ++-- ospfd/ospfd.h | 695 +- pimd/pim_assert.c | 1095 +- pimd/pim_assert.h | 23 +- pimd/pim_bfd.c | 474 +- pimd/pim_bfd.h | 24 +- pimd/pim_br.c | 99 +- pimd/pim_br.h | 8 +- pimd/pim_cmd.c | 10300 ++++++------ pimd/pim_hello.c | 878 +- pimd/pim_hello.h | 14 +- pimd/pim_iface.c | 2417 +-- pimd/pim_iface.h | 160 +- pimd/pim_ifchannel.c | 2254 +-- pimd/pim_ifchannel.h | 119 +- pimd/pim_igmp.c | 1807 +-- pimd/pim_igmp.h | 164 +- pimd/pim_igmp_join.h | 45 +- pimd/pim_igmpv2.c | 294 +- pimd/pim_igmpv2.h | 21 +- pimd/pim_igmpv3.c | 3451 ++-- pimd/pim_igmpv3.h | 59 +- pimd/pim_int.c | 20 +- pimd/pim_join.c | 918 +- pimd/pim_join.h | 10 +- pimd/pim_jp_agg.c | 495 +- pimd/pim_jp_agg.h | 40 +- pimd/pim_macro.c | 352 +- pimd/pim_macro.h | 3 +- pimd/pim_main.c | 162 +- pimd/pim_memory.c | 50 +- pimd/pim_mroute.c | 1568 +- pimd/pim_mroute.h | 68 +- pimd/pim_msdp.c | 2337 ++- pimd/pim_msdp.h | 270 +- pimd/pim_msdp_packet.c | 1128 +- pimd/pim_msdp_packet.h | 4 +- pimd/pim_msdp_socket.c | 366 +- pimd/pim_msg.c | 341 +- pimd/pim_msg.h | 86 +- pimd/pim_neighbor.c | 1297 +- pimd/pim_neighbor.h | 62 +- pimd/pim_nht.c | 1949 ++- pimd/pim_nht.h | 68 +- pimd/pim_oil.c | 784 +- pimd/pim_oil.h | 59 +- pimd/pim_pim.c | 1407 +- pimd/pim_pim.h | 26 +- pimd/pim_register.c | 617 +- pimd/pim_register.h | 22 +- pimd/pim_routemap.c | 56 +- pimd/pim_rp.c | 1640 +- pimd/pim_rp.h | 41 +- pimd/pim_rpf.c | 620 +- pimd/pim_rpf.h | 38 +- pimd/pim_signals.c | 51 +- pimd/pim_sock.c | 653 +- pimd/pim_sock.h | 17 +- pimd/pim_ssm.c | 190 +- pimd/pim_ssm.h | 26 +- pimd/pim_ssmpingd.c | 685 +- pimd/pim_ssmpingd.h | 10 +- pimd/pim_static.c | 598 +- pimd/pim_static.h | 20 +- pimd/pim_str.c | 84 +- pimd/pim_str.h | 10 +- pimd/pim_time.c | 158 +- pimd/pim_tlv.c | 1227 +- pimd/pim_tlv.h | 59 +- pimd/pim_upstream.c | 2515 ++- pimd/pim_upstream.h | 162 +- pimd/pim_util.c | 130 +- pimd/pim_util.h | 4 +- pimd/pim_version.c | 2 +- pimd/pim_version.h | 2 +- pimd/pim_vty.c | 537 +- pimd/pim_zebra.c | 1994 +-- pimd/pim_zebra.h | 6 +- pimd/pim_zlookup.c | 883 +- pimd/pim_zlookup.h | 19 +- pimd/pimd.c | 393 +- pimd/pimd.h | 97 +- pimd/test_igmpv3_join.c | 198 +- qpb/linear_allocator.h | 184 +- qpb/qpb.c | 1 - qpb/qpb.h | 404 +- qpb/qpb_allocator.c | 28 +- qpb/qpb_allocator.h | 55 +- ripd/rip_debug.c | 237 +- ripd/rip_debug.h | 4 +- ripd/rip_interface.c | 2409 ++- ripd/rip_interface.h | 20 +- ripd/rip_main.c | 197 +- ripd/rip_memory.c | 10 +- ripd/rip_offset.c | 545 +- ripd/rip_peer.c | 230 +- ripd/rip_routemap.c | 784 +- ripd/rip_snmp.c | 865 +- ripd/rip_zebra.c | 943 +- ripd/ripd.c | 6755 ++++---- ripd/ripd.h | 481 +- ripngd/ripng_debug.c | 240 +- ripngd/ripng_debug.h | 4 +- ripngd/ripng_interface.c | 1592 +- ripngd/ripng_main.c | 180 +- ripngd/ripng_memory.c | 10 +- ripngd/ripng_nexthop.c | 282 +- ripngd/ripng_nexthop.h | 35 +- ripngd/ripng_offset.c | 562 +- ripngd/ripng_peer.c | 231 +- ripngd/ripng_route.c | 215 +- ripngd/ripng_route.h | 47 +- ripngd/ripng_routemap.c | 498 +- ripngd/ripng_zebra.c | 758 +- ripngd/ripngd.c | 4676 +++--- ripngd/ripngd.h | 457 +- tests/bgpd/test_aspath.c | 2539 +-- tests/bgpd/test_capability.c | 1500 +- tests/bgpd/test_ecommunity.c | 197 +- tests/bgpd/test_mp_attr.c | 1758 +- tests/bgpd/test_mpath.c | 638 +- tests/helpers/c/main.c | 250 +- tests/helpers/c/prng.c | 103 +- tests/helpers/c/prng.h | 10 +- tests/helpers/c/tests.h | 4 +- tests/lib/cli/common_cli.c | 84 +- tests/lib/cli/common_cli.h | 22 +- tests/lib/cli/test_cli.c | 86 +- tests/lib/cli/test_commands.c | 575 +- tests/lib/test_buffer.c | 56 +- tests/lib/test_checksum.c | 692 +- tests/lib/test_heavy.c | 97 +- tests/lib/test_heavy_thread.c | 157 +- tests/lib/test_heavy_wq.c | 197 +- tests/lib/test_memory.c | 146 +- tests/lib/test_nexthop_iter.c | 421 +- tests/lib/test_privs.c | 192 +- tests/lib/test_segv.c | 33 +- tests/lib/test_sig.c | 66 +- tests/lib/test_srcdest_table.c | 641 +- tests/lib/test_stream.c | 79 +- tests/lib/test_table.c | 710 +- tests/lib/test_timer_correctness.c | 245 +- tests/lib/test_timer_performance.c | 122 +- tests/ospf6d/test_lsdb.c | 11 +- tests/test_lblmgr.c | 141 +- tools/cocci.h | 56 +- tools/permutations.c | 114 +- tools/start-stop-daemon.c | 561 +- vtysh/vtysh.c | 5211 +++--- vtysh/vtysh.h | 36 +- vtysh/vtysh_config.c | 678 +- vtysh/vtysh_main.c | 1006 +- vtysh/vtysh_user.c | 208 +- vtysh/vtysh_user.h | 6 +- watchfrr/watchfrr.c | 496 +- watchfrr/watchfrr.h | 2 +- watchfrr/watchfrr_vty.c | 22 +- zebra/client_main.c | 298 +- zebra/connected.c | 877 +- zebra/connected.h | 43 +- zebra/debug.c | 469 +- zebra/debug.h | 14 +- zebra/if_ioctl.c | 487 +- zebra/if_ioctl_solaris.c | 562 +- zebra/if_netlink.c | 1969 +-- zebra/if_netlink.h | 10 +- zebra/if_sysctl.c | 189 +- zebra/interface.c | 4302 +++-- zebra/interface.h | 421 +- zebra/ioctl.c | 706 +- zebra/ioctl.h | 32 +- zebra/ioctl_solaris.c | 572 +- zebra/ioctl_solaris.h | 4 +- zebra/ipforward.h | 12 +- zebra/ipforward_proc.c | 213 +- zebra/ipforward_solaris.c | 177 +- zebra/ipforward_sysctl.c | 215 +- zebra/irdp.h | 53 +- zebra/irdp_interface.c | 751 +- zebra/irdp_main.c | 440 +- zebra/irdp_packet.c | 550 +- zebra/kernel_netlink.c | 1274 +- zebra/kernel_netlink.h | 52 +- zebra/kernel_socket.c | 2046 +-- zebra/kernel_socket.h | 12 +- zebra/label_manager.c | 65 +- zebra/label_manager.h | 9 +- zebra/main.c | 421 +- zebra/redistribute.c | 1205 +- zebra/redistribute.h | 61 +- zebra/rib.h | 439 +- zebra/router-id.c | 349 +- zebra/rt.h | 53 +- zebra/rt_netlink.c | 4093 +++-- zebra/rt_netlink.h | 31 +- zebra/rt_socket.c | 600 +- zebra/rtadv.c | 2389 ++- zebra/rtadv.h | 73 +- zebra/rtread_getmsg.c | 171 +- zebra/rtread_netlink.c | 22 +- zebra/rtread_sysctl.c | 99 +- zebra/zebra_fpm.c | 2166 ++- zebra/zebra_fpm_dt.c | 353 +- zebra/zebra_fpm_netlink.c | 619 +- zebra/zebra_fpm_private.h | 36 +- zebra/zebra_fpm_protobuf.c | 459 +- zebra/zebra_l2.c | 232 +- zebra/zebra_l2.h | 71 +- zebra/zebra_l2_null.c | 34 +- zebra/zebra_memory.c | 14 +- zebra/zebra_mpls.c | 4393 +++-- zebra/zebra_mpls.h | 363 +- zebra/zebra_mpls_netlink.c | 89 +- zebra/zebra_mpls_null.c | 20 +- zebra/zebra_mpls_openbsd.c | 587 +- zebra/zebra_mpls_vty.c | 805 +- zebra/zebra_mroute.c | 48 +- zebra/zebra_mroute.h | 10 +- zebra/zebra_ns.c | 54 +- zebra/zebra_ns.h | 42 +- zebra/zebra_ptm.c | 1778 +-- zebra/zebra_ptm.h | 53 +- zebra/zebra_ptm_redistribute.c | 166 +- zebra/zebra_ptm_redistribute.h | 6 +- zebra/zebra_rib.c | 4604 +++--- zebra/zebra_rnh.c | 1610 +- zebra/zebra_rnh.h | 58 +- zebra/zebra_routemap.c | 1829 +-- zebra/zebra_routemap.h | 35 +- zebra/zebra_snmp.c | 879 +- zebra/zebra_static.c | 924 +- zebra/zebra_static.h | 166 +- zebra/zebra_vrf.c | 758 +- zebra/zebra_vrf.h | 161 +- zebra/zebra_vty.c | 4732 +++--- zebra/zebra_vxlan.c | 4848 +++--- zebra/zebra_vxlan.h | 129 +- zebra/zebra_vxlan_null.c | 146 +- zebra/zebra_vxlan_private.h | 138 +- zebra/zserv.c | 4917 +++--- zebra/zserv.h | 261 +- 687 files changed, 283496 insertions(+), 293385 deletions(-) diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c index c44e06773..c7c963151 100644 --- a/bgpd/bgp_advertise.c +++ b/bgpd/bgp_advertise.c @@ -43,249 +43,227 @@ /* BGP advertise attribute is used for pack same attribute update into one packet. To do that we maintain attribute hash in struct peer. */ -struct bgp_advertise_attr * -baa_new (void) +struct bgp_advertise_attr *baa_new(void) { - return (struct bgp_advertise_attr *) - XCALLOC (MTYPE_BGP_ADVERTISE_ATTR, sizeof (struct bgp_advertise_attr)); + return (struct bgp_advertise_attr *)XCALLOC( + MTYPE_BGP_ADVERTISE_ATTR, sizeof(struct bgp_advertise_attr)); } -static void -baa_free (struct bgp_advertise_attr *baa) +static void baa_free(struct bgp_advertise_attr *baa) { - XFREE (MTYPE_BGP_ADVERTISE_ATTR, baa); + XFREE(MTYPE_BGP_ADVERTISE_ATTR, baa); } -static void * -baa_hash_alloc (void *p) +static void *baa_hash_alloc(void *p) { - struct bgp_advertise_attr * ref = (struct bgp_advertise_attr *) p; - struct bgp_advertise_attr *baa; + struct bgp_advertise_attr *ref = (struct bgp_advertise_attr *)p; + struct bgp_advertise_attr *baa; - baa = baa_new (); - baa->attr = ref->attr; - return baa; + baa = baa_new(); + baa->attr = ref->attr; + return baa; } -unsigned int -baa_hash_key (void *p) +unsigned int baa_hash_key(void *p) { - struct bgp_advertise_attr * baa = (struct bgp_advertise_attr *) p; + struct bgp_advertise_attr *baa = (struct bgp_advertise_attr *)p; - return attrhash_key_make (baa->attr); + return attrhash_key_make(baa->attr); } -int -baa_hash_cmp (const void *p1, const void *p2) +int baa_hash_cmp(const void *p1, const void *p2) { - const struct bgp_advertise_attr * baa1 = p1; - const struct bgp_advertise_attr * baa2 = p2; + const struct bgp_advertise_attr *baa1 = p1; + const struct bgp_advertise_attr *baa2 = p2; - return attrhash_cmp (baa1->attr, baa2->attr); + return attrhash_cmp(baa1->attr, baa2->attr); } /* BGP update and withdraw information is stored in BGP advertise structure. This structure is referred from BGP adjacency information. */ -struct bgp_advertise * -bgp_advertise_new (void) +struct bgp_advertise *bgp_advertise_new(void) { - return (struct bgp_advertise *) - XCALLOC (MTYPE_BGP_ADVERTISE, sizeof (struct bgp_advertise)); + return (struct bgp_advertise *)XCALLOC(MTYPE_BGP_ADVERTISE, + sizeof(struct bgp_advertise)); } -void -bgp_advertise_free (struct bgp_advertise *adv) +void bgp_advertise_free(struct bgp_advertise *adv) { - if (adv->binfo) - bgp_info_unlock (adv->binfo); /* bgp_advertise bgp_info reference */ - XFREE (MTYPE_BGP_ADVERTISE, adv); + if (adv->binfo) + bgp_info_unlock( + adv->binfo); /* bgp_advertise bgp_info reference */ + XFREE(MTYPE_BGP_ADVERTISE, adv); } -void -bgp_advertise_add (struct bgp_advertise_attr *baa, - struct bgp_advertise *adv) +void bgp_advertise_add(struct bgp_advertise_attr *baa, + struct bgp_advertise *adv) { - adv->next = baa->adv; - if (baa->adv) - baa->adv->prev = adv; - baa->adv = adv; + adv->next = baa->adv; + if (baa->adv) + baa->adv->prev = adv; + baa->adv = adv; } -void -bgp_advertise_delete (struct bgp_advertise_attr *baa, - struct bgp_advertise *adv) +void bgp_advertise_delete(struct bgp_advertise_attr *baa, + struct bgp_advertise *adv) { - if (adv->next) - adv->next->prev = adv->prev; - if (adv->prev) - adv->prev->next = adv->next; - else - baa->adv = adv->next; + if (adv->next) + adv->next->prev = adv->prev; + if (adv->prev) + adv->prev->next = adv->next; + else + baa->adv = adv->next; } -struct bgp_advertise_attr * -bgp_advertise_intern (struct hash *hash, struct attr *attr) +struct bgp_advertise_attr *bgp_advertise_intern(struct hash *hash, + struct attr *attr) { - struct bgp_advertise_attr ref; - struct bgp_advertise_attr *baa; + struct bgp_advertise_attr ref; + struct bgp_advertise_attr *baa; - ref.attr = bgp_attr_intern (attr); - baa = (struct bgp_advertise_attr *) hash_get (hash, &ref, baa_hash_alloc); - baa->refcnt++; + ref.attr = bgp_attr_intern(attr); + baa = (struct bgp_advertise_attr *)hash_get(hash, &ref, baa_hash_alloc); + baa->refcnt++; - return baa; + return baa; } -void -bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa) +void bgp_advertise_unintern(struct hash *hash, struct bgp_advertise_attr *baa) { - if (baa->refcnt) - baa->refcnt--; - - if (baa->refcnt && baa->attr) - bgp_attr_unintern (&baa->attr); - else - { - if (baa->attr) - { - hash_release (hash, baa); - bgp_attr_unintern (&baa->attr); + if (baa->refcnt) + baa->refcnt--; + + if (baa->refcnt && baa->attr) + bgp_attr_unintern(&baa->attr); + else { + if (baa->attr) { + hash_release(hash, baa); + bgp_attr_unintern(&baa->attr); + } + baa_free(baa); } - baa_free (baa); - } } -int -bgp_adj_out_lookup (struct peer *peer, struct bgp_node *rn, - u_int32_t addpath_tx_id) +int bgp_adj_out_lookup(struct peer *peer, struct bgp_node *rn, + u_int32_t addpath_tx_id) { - struct bgp_adj_out *adj; - struct peer_af *paf; - afi_t afi; - safi_t safi; - int addpath_capable; - - for (adj = rn->adj_out; adj; adj = adj->next) - SUBGRP_FOREACH_PEER(adj->subgroup, paf) - if (paf->peer == peer) - { - afi = SUBGRP_AFI (adj->subgroup); - safi = SUBGRP_SAFI (adj->subgroup); - addpath_capable = bgp_addpath_encode_tx (peer, afi, safi); - - /* Match on a specific addpath_tx_id if we are using addpath for this - * peer and if an addpath_tx_id was specified */ - if (addpath_capable && addpath_tx_id && adj->addpath_tx_id != addpath_tx_id) - continue; - - return (adj->adv - ? (adj->adv->baa ? 1 : 0) - : (adj->attr ? 1 : 0)); + struct bgp_adj_out *adj; + struct peer_af *paf; + afi_t afi; + safi_t safi; + int addpath_capable; + + for (adj = rn->adj_out; adj; adj = adj->next) + SUBGRP_FOREACH_PEER(adj->subgroup, paf) + if (paf->peer == peer) { + afi = SUBGRP_AFI(adj->subgroup); + safi = SUBGRP_SAFI(adj->subgroup); + addpath_capable = bgp_addpath_encode_tx(peer, afi, safi); + + /* Match on a specific addpath_tx_id if we are using addpath for + * this + * peer and if an addpath_tx_id was specified */ + if (addpath_capable && addpath_tx_id + && adj->addpath_tx_id != addpath_tx_id) + continue; + + return (adj->adv ? (adj->adv->baa ? 1 : 0) + : (adj->attr ? 1 : 0)); } - return 0; + return 0; } -void -bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr, - u_int32_t addpath_id) +void bgp_adj_in_set(struct bgp_node *rn, struct peer *peer, struct attr *attr, + u_int32_t addpath_id) { - struct bgp_adj_in *adj; - - for (adj = rn->adj_in; adj; adj = adj->next) - { - if (adj->peer == peer && adj->addpath_rx_id == addpath_id) - { - if (adj->attr != attr) - { - bgp_attr_unintern (&adj->attr); - adj->attr = bgp_attr_intern (attr); - } - return; + struct bgp_adj_in *adj; + + for (adj = rn->adj_in; adj; adj = adj->next) { + if (adj->peer == peer && adj->addpath_rx_id == addpath_id) { + if (adj->attr != attr) { + bgp_attr_unintern(&adj->attr); + adj->attr = bgp_attr_intern(attr); + } + return; + } } - } - adj = XCALLOC (MTYPE_BGP_ADJ_IN, sizeof (struct bgp_adj_in)); - adj->peer = peer_lock (peer); /* adj_in peer reference */ - adj->attr = bgp_attr_intern (attr); - adj->addpath_rx_id = addpath_id; - BGP_ADJ_IN_ADD (rn, adj); - bgp_lock_node (rn); + adj = XCALLOC(MTYPE_BGP_ADJ_IN, sizeof(struct bgp_adj_in)); + adj->peer = peer_lock(peer); /* adj_in peer reference */ + adj->attr = bgp_attr_intern(attr); + adj->addpath_rx_id = addpath_id; + BGP_ADJ_IN_ADD(rn, adj); + bgp_lock_node(rn); } -void -bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai) +void bgp_adj_in_remove(struct bgp_node *rn, struct bgp_adj_in *bai) { - bgp_attr_unintern (&bai->attr); - BGP_ADJ_IN_DEL (rn, bai); - peer_unlock (bai->peer); /* adj_in peer reference */ - XFREE (MTYPE_BGP_ADJ_IN, bai); + bgp_attr_unintern(&bai->attr); + BGP_ADJ_IN_DEL(rn, bai); + peer_unlock(bai->peer); /* adj_in peer reference */ + XFREE(MTYPE_BGP_ADJ_IN, bai); } -int -bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer, - u_int32_t addpath_id) +int bgp_adj_in_unset(struct bgp_node *rn, struct peer *peer, + u_int32_t addpath_id) { - struct bgp_adj_in *adj; - struct bgp_adj_in *adj_next; + struct bgp_adj_in *adj; + struct bgp_adj_in *adj_next; - adj = rn->adj_in; + adj = rn->adj_in; - if (!adj) - return 0; + if (!adj) + return 0; - while (adj) - { - adj_next = adj->next; + while (adj) { + adj_next = adj->next; - if (adj->peer == peer && adj->addpath_rx_id == addpath_id) - { - bgp_adj_in_remove (rn, adj); - bgp_unlock_node (rn); - } + if (adj->peer == peer && adj->addpath_rx_id == addpath_id) { + bgp_adj_in_remove(rn, adj); + bgp_unlock_node(rn); + } - adj = adj_next; - } + adj = adj_next; + } - return 1; + return 1; } -void -bgp_sync_init (struct peer *peer) +void bgp_sync_init(struct peer *peer) { - afi_t afi; - safi_t safi; - struct bgp_synchronize *sync; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - sync = XCALLOC (MTYPE_BGP_SYNCHRONISE, - sizeof (struct bgp_synchronize)); - BGP_ADV_FIFO_INIT (&sync->update); - BGP_ADV_FIFO_INIT (&sync->withdraw); - BGP_ADV_FIFO_INIT (&sync->withdraw_low); - peer->sync[afi][safi] = sync; - peer->hash[afi][safi] = hash_create (baa_hash_key, baa_hash_cmp, NULL); - } + afi_t afi; + safi_t safi; + struct bgp_synchronize *sync; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + sync = XCALLOC(MTYPE_BGP_SYNCHRONISE, + sizeof(struct bgp_synchronize)); + BGP_ADV_FIFO_INIT(&sync->update); + BGP_ADV_FIFO_INIT(&sync->withdraw); + BGP_ADV_FIFO_INIT(&sync->withdraw_low); + peer->sync[afi][safi] = sync; + peer->hash[afi][safi] = + hash_create(baa_hash_key, baa_hash_cmp, NULL); + } } -void -bgp_sync_delete (struct peer *peer) +void bgp_sync_delete(struct peer *peer) { - afi_t afi; - safi_t safi; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - if (peer->sync[afi][safi]) - XFREE (MTYPE_BGP_SYNCHRONISE, peer->sync[afi][safi]); - peer->sync[afi][safi] = NULL; - - if (peer->hash[afi][safi]) - hash_free (peer->hash[afi][safi]); - peer->hash[afi][safi] = NULL; - } + afi_t afi; + safi_t safi; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + if (peer->sync[afi][safi]) + XFREE(MTYPE_BGP_SYNCHRONISE, + peer->sync[afi][safi]); + peer->sync[afi][safi] = NULL; + + if (peer->hash[afi][safi]) + hash_free(peer->hash[afi][safi]); + peer->hash[afi][safi] = NULL; + } } diff --git a/bgpd/bgp_advertise.h b/bgpd/bgp_advertise.h index 03a1ffcb9..3fdc6d8d2 100644 --- a/bgpd/bgp_advertise.h +++ b/bgpd/bgp_advertise.h @@ -26,172 +26,168 @@ struct update_subgroup; /* BGP advertise FIFO. */ -struct bgp_advertise_fifo -{ - struct bgp_advertise *next; - struct bgp_advertise *prev; - u_int32_t count; +struct bgp_advertise_fifo { + struct bgp_advertise *next; + struct bgp_advertise *prev; + u_int32_t count; }; /* BGP advertise attribute. */ -struct bgp_advertise_attr -{ - /* Head of advertisement pointer. */ - struct bgp_advertise *adv; +struct bgp_advertise_attr { + /* Head of advertisement pointer. */ + struct bgp_advertise *adv; - /* Reference counter. */ - unsigned long refcnt; + /* Reference counter. */ + unsigned long refcnt; - /* Attribute pointer to be announced. */ - struct attr *attr; + /* Attribute pointer to be announced. */ + struct attr *attr; }; -struct bgp_advertise -{ - /* FIFO for advertisement. */ - struct bgp_advertise_fifo fifo; +struct bgp_advertise { + /* FIFO for advertisement. */ + struct bgp_advertise_fifo fifo; - /* Link list for same attribute advertise. */ - struct bgp_advertise *next; - struct bgp_advertise *prev; + /* Link list for same attribute advertise. */ + struct bgp_advertise *next; + struct bgp_advertise *prev; - /* Prefix information. */ - struct bgp_node *rn; + /* Prefix information. */ + struct bgp_node *rn; - /* Reference pointer. */ - struct bgp_adj_out *adj; + /* Reference pointer. */ + struct bgp_adj_out *adj; - /* Advertisement attribute. */ - struct bgp_advertise_attr *baa; + /* Advertisement attribute. */ + struct bgp_advertise_attr *baa; - /* BGP info. */ - struct bgp_info *binfo; + /* BGP info. */ + struct bgp_info *binfo; }; /* BGP adjacency out. */ -struct bgp_adj_out -{ - /* Lined list pointer. */ - struct bgp_adj_out *next; - struct bgp_adj_out *prev; +struct bgp_adj_out { + /* Lined list pointer. */ + struct bgp_adj_out *next; + struct bgp_adj_out *prev; - /* Advertised subgroup. */ - struct update_subgroup *subgroup; + /* Advertised subgroup. */ + struct update_subgroup *subgroup; - /* Threading that makes the adj part of subgroup's adj queue */ - TAILQ_ENTRY(bgp_adj_out) subgrp_adj_train; + /* Threading that makes the adj part of subgroup's adj queue */ + TAILQ_ENTRY(bgp_adj_out) subgrp_adj_train; - /* Prefix information. */ - struct bgp_node *rn; + /* Prefix information. */ + struct bgp_node *rn; - u_int32_t addpath_tx_id; + u_int32_t addpath_tx_id; - /* Advertised attribute. */ - struct attr *attr; + /* Advertised attribute. */ + struct attr *attr; - /* Advertisement information. */ - struct bgp_advertise *adv; + /* Advertisement information. */ + struct bgp_advertise *adv; }; /* BGP adjacency in. */ -struct bgp_adj_in -{ - /* Linked list pointer. */ - struct bgp_adj_in *next; - struct bgp_adj_in *prev; +struct bgp_adj_in { + /* Linked list pointer. */ + struct bgp_adj_in *next; + struct bgp_adj_in *prev; - /* Received peer. */ - struct peer *peer; + /* Received peer. */ + struct peer *peer; - /* Received attribute. */ - struct attr *attr; + /* Received attribute. */ + struct attr *attr; - /* Addpath identifier */ - u_int32_t addpath_rx_id; + /* Addpath identifier */ + u_int32_t addpath_rx_id; }; /* BGP advertisement list. */ -struct bgp_synchronize -{ - struct bgp_advertise_fifo update; - struct bgp_advertise_fifo withdraw; - struct bgp_advertise_fifo withdraw_low; +struct bgp_synchronize { + struct bgp_advertise_fifo update; + struct bgp_advertise_fifo withdraw; + struct bgp_advertise_fifo withdraw_low; }; /* BGP adjacency linked list. */ -#define BGP_INFO_ADD(N,A,TYPE) \ - do { \ - (A)->prev = NULL; \ - (A)->next = (N)->TYPE; \ - if ((N)->TYPE) \ - (N)->TYPE->prev = (A); \ - (N)->TYPE = (A); \ - } while (0) - -#define BGP_INFO_DEL(N,A,TYPE) \ - do { \ - if ((A)->next) \ - (A)->next->prev = (A)->prev; \ - if ((A)->prev) \ - (A)->prev->next = (A)->next; \ - else \ - (N)->TYPE = (A)->next; \ - } while (0) +#define BGP_INFO_ADD(N, A, TYPE) \ + do { \ + (A)->prev = NULL; \ + (A)->next = (N)->TYPE; \ + if ((N)->TYPE) \ + (N)->TYPE->prev = (A); \ + (N)->TYPE = (A); \ + } while (0) + +#define BGP_INFO_DEL(N, A, TYPE) \ + do { \ + if ((A)->next) \ + (A)->next->prev = (A)->prev; \ + if ((A)->prev) \ + (A)->prev->next = (A)->next; \ + else \ + (N)->TYPE = (A)->next; \ + } while (0) #define BGP_ADJ_IN_ADD(N,A) BGP_INFO_ADD(N,A,adj_in) #define BGP_ADJ_IN_DEL(N,A) BGP_INFO_DEL(N,A,adj_in) #define BGP_ADJ_OUT_ADD(N,A) BGP_INFO_ADD(N,A,adj_out) #define BGP_ADJ_OUT_DEL(N,A) BGP_INFO_DEL(N,A,adj_out) -#define BGP_ADV_FIFO_ADD(F, N) \ - do { \ - FIFO_ADD((F), (N)); \ - (F)->count++; \ - } while (0) +#define BGP_ADV_FIFO_ADD(F, N) \ + do { \ + FIFO_ADD((F), (N)); \ + (F)->count++; \ + } while (0) -#define BGP_ADV_FIFO_DEL(F, N) \ - do { \ - FIFO_DEL((N)); \ - (F)->count--; \ - } while (0) +#define BGP_ADV_FIFO_DEL(F, N) \ + do { \ + FIFO_DEL((N)); \ + (F)->count--; \ + } while (0) -#define BGP_ADV_FIFO_INIT(F) \ - do { \ - FIFO_INIT((F)); \ - (F)->count = 0; \ - } while (0) +#define BGP_ADV_FIFO_INIT(F) \ + do { \ + FIFO_INIT((F)); \ + (F)->count = 0; \ + } while (0) -#define BGP_ADV_FIFO_COUNT(F) \ - (F)->count +#define BGP_ADV_FIFO_COUNT(F) (F)->count -#define BGP_ADV_FIFO_EMPTY(F) \ - (((struct bgp_advertise_fifo *)(F))->next == (struct bgp_advertise *)(F)) +#define BGP_ADV_FIFO_EMPTY(F) \ + (((struct bgp_advertise_fifo *)(F))->next \ + == (struct bgp_advertise *)(F)) -#define BGP_ADV_FIFO_HEAD(F) \ - ((((struct bgp_advertise_fifo *)(F))->next == (struct bgp_advertise *)(F)) \ - ? NULL : (F)->next) +#define BGP_ADV_FIFO_HEAD(F) \ + ((((struct bgp_advertise_fifo *)(F))->next \ + == (struct bgp_advertise *)(F)) \ + ? NULL \ + : (F)->next) /* Prototypes. */ -extern int bgp_adj_out_lookup (struct peer *, struct bgp_node *, u_int32_t); -extern void bgp_adj_in_set (struct bgp_node *, struct peer *, struct attr *, u_int32_t); -extern int bgp_adj_in_unset (struct bgp_node *, struct peer *, u_int32_t); -extern void bgp_adj_in_remove (struct bgp_node *, struct bgp_adj_in *); - -extern void bgp_sync_init (struct peer *); -extern void bgp_sync_delete (struct peer *); -extern unsigned int baa_hash_key (void *p); -extern int baa_hash_cmp (const void *p1, const void *p2); -extern void bgp_advertise_add (struct bgp_advertise_attr *baa, - struct bgp_advertise *adv); -extern struct bgp_advertise *bgp_advertise_new (void); -extern void bgp_advertise_free (struct bgp_advertise *adv); -extern struct bgp_advertise_attr * -bgp_advertise_intern (struct hash *hash, struct attr *attr); -extern struct bgp_advertise_attr *baa_new (void); -extern void -bgp_advertise_delete (struct bgp_advertise_attr *baa, - struct bgp_advertise *adv); -extern void -bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa); +extern int bgp_adj_out_lookup(struct peer *, struct bgp_node *, u_int32_t); +extern void bgp_adj_in_set(struct bgp_node *, struct peer *, struct attr *, + u_int32_t); +extern int bgp_adj_in_unset(struct bgp_node *, struct peer *, u_int32_t); +extern void bgp_adj_in_remove(struct bgp_node *, struct bgp_adj_in *); + +extern void bgp_sync_init(struct peer *); +extern void bgp_sync_delete(struct peer *); +extern unsigned int baa_hash_key(void *p); +extern int baa_hash_cmp(const void *p1, const void *p2); +extern void bgp_advertise_add(struct bgp_advertise_attr *baa, + struct bgp_advertise *adv); +extern struct bgp_advertise *bgp_advertise_new(void); +extern void bgp_advertise_free(struct bgp_advertise *adv); +extern struct bgp_advertise_attr *bgp_advertise_intern(struct hash *hash, + struct attr *attr); +extern struct bgp_advertise_attr *baa_new(void); +extern void bgp_advertise_delete(struct bgp_advertise_attr *baa, + struct bgp_advertise *adv); +extern void bgp_advertise_unintern(struct hash *hash, + struct bgp_advertise_attr *baa); #endif /* _QUAGGA_BGP_ADVERTISE_H */ diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index 47bbfd466..4e55c5f26 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -58,8 +58,8 @@ */ /* Calculated size in bytes of ASN segment data to hold N ASN's */ -#define ASSEGMENT_DATA_SIZE(N,S) \ - ((N) * ( (S) ? AS_VALUE_SIZE : AS16_VALUE_SIZE) ) +#define ASSEGMENT_DATA_SIZE(N, S) \ + ((N) * ((S) ? AS_VALUE_SIZE : AS16_VALUE_SIZE)) /* Calculated size of segment struct to hold N ASN's */ #define ASSEGMENT_SIZE(N,S) (AS_HEADER_SIZE + ASSEGMENT_DATA_SIZE (N,S)) @@ -69,21 +69,19 @@ /* AS_SEQUENCE segments can be packed together */ /* Can the types of X and Y be considered for packing? */ -#define ASSEGMENT_TYPES_PACKABLE(X,Y) \ - ( ((X)->type == (Y)->type) \ - && ((X)->type == AS_SEQUENCE)) +#define ASSEGMENT_TYPES_PACKABLE(X, Y) \ + (((X)->type == (Y)->type) && ((X)->type == AS_SEQUENCE)) /* Types and length of X,Y suitable for packing? */ -#define ASSEGMENTS_PACKABLE(X,Y) \ - ( ASSEGMENT_TYPES_PACKABLE( (X), (Y)) \ - && ( ((X)->length + (Y)->length) <= AS_SEGMENT_MAX ) ) +#define ASSEGMENTS_PACKABLE(X, Y) \ + (ASSEGMENT_TYPES_PACKABLE((X), (Y)) \ + && (((X)->length + (Y)->length) <= AS_SEGMENT_MAX)) -/* As segment header - the on-wire representation +/* As segment header - the on-wire representation * NOT the internal representation! */ -struct assegment_header -{ - u_char type; - u_char length; +struct assegment_header { + u_char type; + u_char length; }; /* Hash for aspath. This is the top level structure of AS path. */ @@ -93,165 +91,147 @@ static struct hash *ashash; static struct stream *snmp_stream; /* Callers are required to initialize the memory */ -static as_t * -assegment_data_new (int num) +static as_t *assegment_data_new(int num) { - return (XMALLOC (MTYPE_AS_SEG_DATA, ASSEGMENT_DATA_SIZE (num, 1))); + return (XMALLOC(MTYPE_AS_SEG_DATA, ASSEGMENT_DATA_SIZE(num, 1))); } -static void -assegment_data_free (as_t *asdata) +static void assegment_data_free(as_t *asdata) { - XFREE (MTYPE_AS_SEG_DATA, asdata); + XFREE(MTYPE_AS_SEG_DATA, asdata); } -const char *aspath_segment_type_str[] = { - "as-invalid", - "as-set", - "as-sequence", - "as-confed-sequence", - "as-confed-set" -}; +const char *aspath_segment_type_str[] = {"as-invalid", "as-set", "as-sequence", + "as-confed-sequence", "as-confed-set"}; /* Get a new segment. Note that 0 is an allowed length, * and will result in a segment with no allocated data segment. * the caller should immediately assign data to the segment, as the segment * otherwise is not generally valid */ -static struct assegment * -assegment_new (u_char type, u_short length) -{ - struct assegment *new; - - new = XCALLOC (MTYPE_AS_SEG, sizeof (struct assegment)); - - if (length) - new->as = assegment_data_new (length); - - new->length = length; - new->type = type; - - return new; -} - -static void -assegment_free (struct assegment *seg) -{ - if (!seg) - return; - - if (seg->as) - assegment_data_free (seg->as); - memset (seg, 0xfe, sizeof(struct assegment)); - XFREE (MTYPE_AS_SEG, seg); - - return; +static struct assegment *assegment_new(u_char type, u_short length) +{ + struct assegment *new; + + new = XCALLOC(MTYPE_AS_SEG, sizeof(struct assegment)); + + if (length) + new->as = assegment_data_new(length); + + new->length = length; + new->type = type; + + return new; +} + +static void assegment_free(struct assegment *seg) +{ + if (!seg) + return; + + if (seg->as) + assegment_data_free(seg->as); + memset(seg, 0xfe, sizeof(struct assegment)); + XFREE(MTYPE_AS_SEG, seg); + + return; } /* free entire chain of segments */ -static void -assegment_free_all (struct assegment *seg) +static void assegment_free_all(struct assegment *seg) { - struct assegment *prev; - - while (seg) - { - prev = seg; - seg = seg->next; - assegment_free (prev); - } + struct assegment *prev; + + while (seg) { + prev = seg; + seg = seg->next; + assegment_free(prev); + } } /* Duplicate just the given assegment and its data */ -static struct assegment * -assegment_dup (struct assegment *seg) +static struct assegment *assegment_dup(struct assegment *seg) { - struct assegment *new; - - new = assegment_new (seg->type, seg->length); - memcpy (new->as, seg->as, ASSEGMENT_DATA_SIZE (new->length, 1) ); - - return new; + struct assegment *new; + + new = assegment_new(seg->type, seg->length); + memcpy(new->as, seg->as, ASSEGMENT_DATA_SIZE(new->length, 1)); + + return new; } /* Duplicate entire chain of assegments, return the head */ -static struct assegment * -assegment_dup_all (struct assegment *seg) -{ - struct assegment *new = NULL; - struct assegment *head = NULL; - - while (seg) - { - if (head) - { - new->next = assegment_dup (seg); - new = new->next; - } - else - head = new = assegment_dup (seg); - - seg = seg->next; - } - return head; +static struct assegment *assegment_dup_all(struct assegment *seg) +{ + struct assegment *new = NULL; + struct assegment *head = NULL; + + while (seg) { + if (head) { + new->next = assegment_dup(seg); + new = new->next; + } else + head = new = assegment_dup(seg); + + seg = seg->next; + } + return head; } /* prepend the as number to given segment, given num of times */ -static struct assegment * -assegment_prepend_asns (struct assegment *seg, as_t asnum, int num) +static struct assegment *assegment_prepend_asns(struct assegment *seg, + as_t asnum, int num) { - as_t *newas; - int i; - - if (!num) - return seg; - - if (num >= AS_SEGMENT_MAX) - return seg; /* we don't do huge prepends */ - - if ((newas = assegment_data_new (seg->length + num)) == NULL) - return seg; + as_t *newas; + int i; - for (i = 0; i < num; i++) - newas[i] = asnum; + if (!num) + return seg; - memcpy (newas + num, seg->as, ASSEGMENT_DATA_SIZE (seg->length, 1)); - assegment_data_free (seg->as); - seg->as = newas; - seg->length += num; + if (num >= AS_SEGMENT_MAX) + return seg; /* we don't do huge prepends */ - return seg; + if ((newas = assegment_data_new(seg->length + num)) == NULL) + return seg; + + for (i = 0; i < num; i++) + newas[i] = asnum; + + memcpy(newas + num, seg->as, ASSEGMENT_DATA_SIZE(seg->length, 1)); + assegment_data_free(seg->as); + seg->as = newas; + seg->length += num; + + return seg; } /* append given array of as numbers to the segment */ -static struct assegment * -assegment_append_asns (struct assegment *seg, as_t *asnos, int num) +static struct assegment *assegment_append_asns(struct assegment *seg, + as_t *asnos, int num) { - as_t *newas; - - newas = XREALLOC (MTYPE_AS_SEG_DATA, seg->as, - ASSEGMENT_DATA_SIZE (seg->length + num, 1)); + as_t *newas; - if (newas) - { - seg->as = newas; - memcpy (seg->as + seg->length, asnos, ASSEGMENT_DATA_SIZE(num, 1)); - seg->length += num; - return seg; - } + newas = XREALLOC(MTYPE_AS_SEG_DATA, seg->as, + ASSEGMENT_DATA_SIZE(seg->length + num, 1)); + + if (newas) { + seg->as = newas; + memcpy(seg->as + seg->length, asnos, + ASSEGMENT_DATA_SIZE(num, 1)); + seg->length += num; + return seg; + } - assegment_free_all (seg); - return NULL; + assegment_free_all(seg); + return NULL; } -static int -int_cmp (const void *p1, const void *p2) +static int int_cmp(const void *p1, const void *p2) { - const as_t *as1 = p1; - const as_t *as2 = p2; - - return (*as1 == *as2) - ? 0 : ( (*as1 > *as2) ? 1 : -1); + const as_t *as1 = p1; + const as_t *as2 = p2; + + return (*as1 == *as2) ? 0 : ((*as1 > *as2) ? 1 : -1); } /* normalise the segment. @@ -260,203 +240,180 @@ int_cmp (const void *p1, const void *p2) * we want each distinct AS_PATHs to have the exact same internal * representation - eg, so that our hashing actually works.. */ -static struct assegment * -assegment_normalise (struct assegment *head) -{ - struct assegment *seg = head, *pin; - struct assegment *tmp; - - if (!head) - return head; - - while (seg) - { - pin = seg; - - /* Sort values SET segments, for determinism in paths to aid - * creation of hash values / path comparisons - * and because it helps other lesser implementations ;) - */ - if (seg->type == AS_SET || seg->type == AS_CONFED_SET) - { - int tail = 0; - int i; - - qsort (seg->as, seg->length, sizeof(as_t), int_cmp); - - /* weed out dupes */ - for (i=1; i < seg->length; i++) - { - if (seg->as[tail] == seg->as[i]) - continue; - - tail++; - if (tail < i) - seg->as[tail] = seg->as[i]; - } - /* seg->length can be 0.. */ - if (seg->length) - seg->length = tail + 1; +static struct assegment *assegment_normalise(struct assegment *head) +{ + struct assegment *seg = head, *pin; + struct assegment *tmp; + + if (!head) + return head; + + while (seg) { + pin = seg; + + /* Sort values SET segments, for determinism in paths to aid + * creation of hash values / path comparisons + * and because it helps other lesser implementations ;) + */ + if (seg->type == AS_SET || seg->type == AS_CONFED_SET) { + int tail = 0; + int i; + + qsort(seg->as, seg->length, sizeof(as_t), int_cmp); + + /* weed out dupes */ + for (i = 1; i < seg->length; i++) { + if (seg->as[tail] == seg->as[i]) + continue; + + tail++; + if (tail < i) + seg->as[tail] = seg->as[i]; + } + /* seg->length can be 0.. */ + if (seg->length) + seg->length = tail + 1; + } + + /* read ahead from the current, pinned segment while the + * segments + * are packable/mergeable. Append all following packable + * segments + * to the segment we have pinned and remove these appended + * segments. + */ + while (pin->next && ASSEGMENT_TYPES_PACKABLE(pin, pin->next)) { + tmp = pin->next; + seg = pin->next; + + /* append the next sequence to the pinned sequence */ + pin = assegment_append_asns(pin, seg->as, seg->length); + + /* bypass the next sequence */ + pin->next = seg->next; + + /* get rid of the now referenceless segment */ + assegment_free(tmp); + } + + seg = pin->next; } - - /* read ahead from the current, pinned segment while the segments - * are packable/mergeable. Append all following packable segments - * to the segment we have pinned and remove these appended - * segments. - */ - while (pin->next && ASSEGMENT_TYPES_PACKABLE(pin, pin->next)) - { - tmp = pin->next; - seg = pin->next; - - /* append the next sequence to the pinned sequence */ - pin = assegment_append_asns (pin, seg->as, seg->length); - - /* bypass the next sequence */ - pin->next = seg->next; - - /* get rid of the now referenceless segment */ - assegment_free (tmp); - - } - - seg = pin->next; - } - return head; -} - -static struct aspath * -aspath_new (void) -{ - return XCALLOC (MTYPE_AS_PATH, sizeof (struct aspath)); + return head; } -/* Free AS path structure. */ -void -aspath_free (struct aspath *aspath) +static struct aspath *aspath_new(void) { - if (!aspath) - return; - if (aspath->segments) - assegment_free_all (aspath->segments); - if (aspath->str) - XFREE (MTYPE_AS_STR, aspath->str); + return XCALLOC(MTYPE_AS_PATH, sizeof(struct aspath)); +} - if (aspath->json) - { - json_object_free(aspath->json); - aspath->json = NULL; - } +/* Free AS path structure. */ +void aspath_free(struct aspath *aspath) +{ + if (!aspath) + return; + if (aspath->segments) + assegment_free_all(aspath->segments); + if (aspath->str) + XFREE(MTYPE_AS_STR, aspath->str); + + if (aspath->json) { + json_object_free(aspath->json); + aspath->json = NULL; + } - XFREE (MTYPE_AS_PATH, aspath); + XFREE(MTYPE_AS_PATH, aspath); } /* Unintern aspath from AS path bucket. */ -void -aspath_unintern (struct aspath **aspath) +void aspath_unintern(struct aspath **aspath) { - struct aspath *ret; - struct aspath *asp = *aspath; - - if (asp->refcnt) - asp->refcnt--; + struct aspath *ret; + struct aspath *asp = *aspath; + + if (asp->refcnt) + asp->refcnt--; - if (asp->refcnt == 0) - { - /* This aspath must exist in aspath hash table. */ - ret = hash_release (ashash, asp); - assert (ret != NULL); - aspath_free (asp); - *aspath = NULL; - } + if (asp->refcnt == 0) { + /* This aspath must exist in aspath hash table. */ + ret = hash_release(ashash, asp); + assert(ret != NULL); + aspath_free(asp); + *aspath = NULL; + } } /* Return the start or end delimiters for a particular Segment type */ #define AS_SEG_START 0 #define AS_SEG_END 1 -static char -aspath_delimiter_char (u_char type, u_char which) -{ - int i; - struct - { - int type; - char start; - char end; - } aspath_delim_char [] = - { - { AS_SET, '{', '}' }, - { AS_CONFED_SET, '[', ']' }, - { AS_CONFED_SEQUENCE, '(', ')' }, - { 0 } - }; - - for (i = 0; aspath_delim_char[i].type != 0; i++) - { - if (aspath_delim_char[i].type == type) - { - if (which == AS_SEG_START) - return aspath_delim_char[i].start; - else if (which == AS_SEG_END) - return aspath_delim_char[i].end; +static char aspath_delimiter_char(u_char type, u_char which) +{ + int i; + struct { + int type; + char start; + char end; + } aspath_delim_char[] = {{AS_SET, '{', '}'}, + {AS_CONFED_SET, '[', ']'}, + {AS_CONFED_SEQUENCE, '(', ')'}, + {0}}; + + for (i = 0; aspath_delim_char[i].type != 0; i++) { + if (aspath_delim_char[i].type == type) { + if (which == AS_SEG_START) + return aspath_delim_char[i].start; + else if (which == AS_SEG_END) + return aspath_delim_char[i].end; + } } - } - return ' '; + return ' '; } /* countup asns from this segment and index onward */ -static int -assegment_count_asns (struct assegment *seg, int from) -{ - int count = 0; - while (seg) - { - if (!from) - count += seg->length; - else - { - count += (seg->length - from); - from = 0; - } - seg = seg->next; - } - return count; -} - -unsigned int -aspath_count_confeds (struct aspath *aspath) -{ - int count = 0; - struct assegment *seg = aspath->segments; - - while (seg) - { - if (seg->type == AS_CONFED_SEQUENCE) - count += seg->length; - else if (seg->type == AS_CONFED_SET) - count++; - - seg = seg->next; - } - return count; -} - -unsigned int -aspath_count_hops (const struct aspath *aspath) -{ - int count = 0; - struct assegment *seg = aspath->segments; - - while (seg) - { - if (seg->type == AS_SEQUENCE) - count += seg->length; - else if (seg->type == AS_SET) - count++; - - seg = seg->next; - } - return count; +static int assegment_count_asns(struct assegment *seg, int from) +{ + int count = 0; + while (seg) { + if (!from) + count += seg->length; + else { + count += (seg->length - from); + from = 0; + } + seg = seg->next; + } + return count; +} + +unsigned int aspath_count_confeds(struct aspath *aspath) +{ + int count = 0; + struct assegment *seg = aspath->segments; + + while (seg) { + if (seg->type == AS_CONFED_SEQUENCE) + count += seg->length; + else if (seg->type == AS_CONFED_SET) + count++; + + seg = seg->next; + } + return count; +} + +unsigned int aspath_count_hops(const struct aspath *aspath) +{ + int count = 0; + struct assegment *seg = aspath->segments; + + while (seg) { + if (seg->type == AS_SEQUENCE) + count += seg->length; + else if (seg->type == AS_SET) + count++; + + seg = seg->next; + } + return count; } /* Estimate size aspath /might/ take if encoded into an @@ -465,1074 +422,1025 @@ aspath_count_hops (const struct aspath *aspath) * This is a quick estimate, not definitive! aspath_put() * may return a different number!! */ -unsigned int -aspath_size (struct aspath *aspath) +unsigned int aspath_size(struct aspath *aspath) { - int size = 0; - struct assegment *seg = aspath->segments; - - while (seg) - { - size += ASSEGMENT_SIZE(seg->length, 1); - seg = seg->next; - } - return size; + int size = 0; + struct assegment *seg = aspath->segments; + + while (seg) { + size += ASSEGMENT_SIZE(seg->length, 1); + seg = seg->next; + } + return size; } /* Return highest public ASN in path */ -as_t -aspath_highest (struct aspath *aspath) -{ - struct assegment *seg = aspath->segments; - as_t highest = 0; - unsigned int i; - - while (seg) - { - for (i = 0; i < seg->length; i++) - if (seg->as[i] > highest && !BGP_AS_IS_PRIVATE(seg->as[i])) - highest = seg->as[i]; - seg = seg->next; - } - return highest; +as_t aspath_highest(struct aspath *aspath) +{ + struct assegment *seg = aspath->segments; + as_t highest = 0; + unsigned int i; + + while (seg) { + for (i = 0; i < seg->length; i++) + if (seg->as[i] > highest + && !BGP_AS_IS_PRIVATE(seg->as[i])) + highest = seg->as[i]; + seg = seg->next; + } + return highest; } /* Return the left-most ASN in path */ -as_t -aspath_leftmost (struct aspath *aspath) +as_t aspath_leftmost(struct aspath *aspath) { - struct assegment *seg = aspath->segments; - as_t leftmost = 0; + struct assegment *seg = aspath->segments; + as_t leftmost = 0; - if (seg && seg->length && seg->type == AS_SEQUENCE) - leftmost = seg->as[0]; + if (seg && seg->length && seg->type == AS_SEQUENCE) + leftmost = seg->as[0]; - return leftmost; + return leftmost; } /* Return 1 if there are any 4-byte ASes in the path */ -unsigned int -aspath_has_as4 (struct aspath *aspath) -{ - struct assegment *seg = aspath->segments; - unsigned int i; - - while (seg) - { - for (i = 0; i < seg->length; i++) - if (seg->as[i] > BGP_AS_MAX) - return 1; - seg = seg->next; - } - return 0; +unsigned int aspath_has_as4(struct aspath *aspath) +{ + struct assegment *seg = aspath->segments; + unsigned int i; + + while (seg) { + for (i = 0; i < seg->length; i++) + if (seg->as[i] > BGP_AS_MAX) + return 1; + seg = seg->next; + } + return 0; } /* Convert aspath structure to string expression. */ -static void -aspath_make_str_count (struct aspath *as) -{ - struct assegment *seg; - int str_size; - int len = 0; - char *str_buf; - json_object *jaspath_segments = NULL; - json_object *jseg = NULL; - json_object *jseg_list = NULL; - - as->json = json_object_new_object(); - jaspath_segments = json_object_new_array(); - - /* Empty aspath. */ - if (!as->segments) - { - json_object_string_add(as->json, "string", "Local"); - json_object_object_add(as->json, "segments", jaspath_segments); - json_object_int_add(as->json, "length", 0); - as->str = XMALLOC (MTYPE_AS_STR, 1); - as->str[0] = '\0'; - as->str_len = 0; - return; - } - - seg = as->segments; - - /* ASN takes 5 to 10 chars plus seperator, see below. - * If there is one differing segment type, we need an additional - * 2 chars for segment delimiters, and the final '\0'. - * Hopefully this is large enough to avoid hitting the realloc - * code below for most common sequences. - * - * This was changed to 10 after the well-known BGP assertion, which - * had hit some parts of the Internet in May of 2009. - */ +static void aspath_make_str_count(struct aspath *as) +{ + struct assegment *seg; + int str_size; + int len = 0; + char *str_buf; + json_object *jaspath_segments = NULL; + json_object *jseg = NULL; + json_object *jseg_list = NULL; + + as->json = json_object_new_object(); + jaspath_segments = json_object_new_array(); + + /* Empty aspath. */ + if (!as->segments) { + json_object_string_add(as->json, "string", "Local"); + json_object_object_add(as->json, "segments", jaspath_segments); + json_object_int_add(as->json, "length", 0); + as->str = XMALLOC(MTYPE_AS_STR, 1); + as->str[0] = '\0'; + as->str_len = 0; + return; + } + + seg = as->segments; + +/* ASN takes 5 to 10 chars plus seperator, see below. + * If there is one differing segment type, we need an additional + * 2 chars for segment delimiters, and the final '\0'. + * Hopefully this is large enough to avoid hitting the realloc + * code below for most common sequences. + * + * This was changed to 10 after the well-known BGP assertion, which + * had hit some parts of the Internet in May of 2009. + */ #define ASN_STR_LEN (10 + 1) - str_size = MAX (assegment_count_asns (seg, 0) * ASN_STR_LEN + 2 + 1, - ASPATH_STR_DEFAULT_LEN); - str_buf = XMALLOC (MTYPE_AS_STR, str_size); - - while (seg) - { - int i; - char seperator; - - /* Check AS type validity. Set seperator for segment */ - switch (seg->type) - { - case AS_SET: - case AS_CONFED_SET: - seperator = ','; - break; - case AS_SEQUENCE: - case AS_CONFED_SEQUENCE: - seperator = ' '; - break; - default: - XFREE (MTYPE_AS_STR, str_buf); - as->str = NULL; - as->str_len = 0; - json_object_free(as->json); - as->json = NULL; - return; - } - - /* We might need to increase str_buf, particularly if path has - * differing segments types, our initial guesstimate above will - * have been wrong. Need 10 chars for ASN, a seperator each and - * potentially two segment delimiters, plus a space between each - * segment and trailing zero. - * - * This definitely didn't work with the value of 5 bytes and - * 32-bit ASNs. - */ + str_size = MAX(assegment_count_asns(seg, 0) * ASN_STR_LEN + 2 + 1, + ASPATH_STR_DEFAULT_LEN); + str_buf = XMALLOC(MTYPE_AS_STR, str_size); + + while (seg) { + int i; + char seperator; + + /* Check AS type validity. Set seperator for segment */ + switch (seg->type) { + case AS_SET: + case AS_CONFED_SET: + seperator = ','; + break; + case AS_SEQUENCE: + case AS_CONFED_SEQUENCE: + seperator = ' '; + break; + default: + XFREE(MTYPE_AS_STR, str_buf); + as->str = NULL; + as->str_len = 0; + json_object_free(as->json); + as->json = NULL; + return; + } + +/* We might need to increase str_buf, particularly if path has + * differing segments types, our initial guesstimate above will + * have been wrong. Need 10 chars for ASN, a seperator each and + * potentially two segment delimiters, plus a space between each + * segment and trailing zero. + * + * This definitely didn't work with the value of 5 bytes and + * 32-bit ASNs. + */ #define SEGMENT_STR_LEN(X) (((X)->length * ASN_STR_LEN) + 2 + 1 + 1) - if ( (len + SEGMENT_STR_LEN(seg)) > str_size) - { - str_size = len + SEGMENT_STR_LEN(seg); - str_buf = XREALLOC (MTYPE_AS_STR, str_buf, str_size); - } + if ((len + SEGMENT_STR_LEN(seg)) > str_size) { + str_size = len + SEGMENT_STR_LEN(seg); + str_buf = XREALLOC(MTYPE_AS_STR, str_buf, str_size); + } #undef ASN_STR_LEN #undef SEGMENT_STR_LEN - - if (seg->type != AS_SEQUENCE) - len += snprintf (str_buf + len, str_size - len, - "%c", - aspath_delimiter_char (seg->type, AS_SEG_START)); - - jseg_list = json_object_new_array(); - - /* write out the ASNs, with their seperators, bar the last one*/ - for (i = 0; i < seg->length; i++) - { - json_object_array_add(jseg_list, json_object_new_int(seg->as[i])); - - len += snprintf (str_buf + len, str_size - len, "%u", seg->as[i]); - - if (i < (seg->length - 1)) - len += snprintf (str_buf + len, str_size - len, "%c", seperator); - } - - jseg = json_object_new_object(); - json_object_string_add(jseg, "type", aspath_segment_type_str[seg->type]); - json_object_object_add(jseg, "list", jseg_list); - json_object_array_add(jaspath_segments, jseg); - - if (seg->type != AS_SEQUENCE) - len += snprintf (str_buf + len, str_size - len, "%c", - aspath_delimiter_char (seg->type, AS_SEG_END)); - if (seg->next) - len += snprintf (str_buf + len, str_size - len, " "); - - seg = seg->next; - } - - assert (len < str_size); - - str_buf[len] = '\0'; - as->str = str_buf; - as->str_len = len; - - json_object_string_add(as->json, "string", str_buf); - json_object_object_add(as->json, "segments", jaspath_segments); - json_object_int_add(as->json, "length", aspath_count_hops (as)); - return; -} - -static void -aspath_str_update (struct aspath *as) -{ - if (as->str) - XFREE (MTYPE_AS_STR, as->str); - - if (as->json) - { - json_object_free(as->json); - as->json = NULL; - } - - aspath_make_str_count (as); + + if (seg->type != AS_SEQUENCE) + len += snprintf( + str_buf + len, str_size - len, "%c", + aspath_delimiter_char(seg->type, AS_SEG_START)); + + jseg_list = json_object_new_array(); + + /* write out the ASNs, with their seperators, bar the last one*/ + for (i = 0; i < seg->length; i++) { + json_object_array_add(jseg_list, + json_object_new_int(seg->as[i])); + + len += snprintf(str_buf + len, str_size - len, "%u", + seg->as[i]); + + if (i < (seg->length - 1)) + len += snprintf(str_buf + len, str_size - len, + "%c", seperator); + } + + jseg = json_object_new_object(); + json_object_string_add(jseg, "type", + aspath_segment_type_str[seg->type]); + json_object_object_add(jseg, "list", jseg_list); + json_object_array_add(jaspath_segments, jseg); + + if (seg->type != AS_SEQUENCE) + len += snprintf( + str_buf + len, str_size - len, "%c", + aspath_delimiter_char(seg->type, AS_SEG_END)); + if (seg->next) + len += snprintf(str_buf + len, str_size - len, " "); + + seg = seg->next; + } + + assert(len < str_size); + + str_buf[len] = '\0'; + as->str = str_buf; + as->str_len = len; + + json_object_string_add(as->json, "string", str_buf); + json_object_object_add(as->json, "segments", jaspath_segments); + json_object_int_add(as->json, "length", aspath_count_hops(as)); + return; +} + +static void aspath_str_update(struct aspath *as) +{ + if (as->str) + XFREE(MTYPE_AS_STR, as->str); + + if (as->json) { + json_object_free(as->json); + as->json = NULL; + } + + aspath_make_str_count(as); } /* Intern allocated AS path. */ -struct aspath * -aspath_intern (struct aspath *aspath) +struct aspath *aspath_intern(struct aspath *aspath) { - struct aspath *find; + struct aspath *find; - /* Assert this AS path structure is not interned and has the string - representation built. */ - assert (aspath->refcnt == 0); - assert (aspath->str); + /* Assert this AS path structure is not interned and has the string + representation built. */ + assert(aspath->refcnt == 0); + assert(aspath->str); - /* Check AS path hash. */ - find = hash_get (ashash, aspath, hash_alloc_intern); - if (find != aspath) - aspath_free (aspath); + /* Check AS path hash. */ + find = hash_get(ashash, aspath, hash_alloc_intern); + if (find != aspath) + aspath_free(aspath); - find->refcnt++; + find->refcnt++; - return find; + return find; } /* Duplicate aspath structure. Created same aspath structure but reference count and AS path string is cleared. */ -struct aspath * -aspath_dup (struct aspath *aspath) +struct aspath *aspath_dup(struct aspath *aspath) { - unsigned short buflen = aspath->str_len + 1; - struct aspath *new; + unsigned short buflen = aspath->str_len + 1; + struct aspath *new; - new = XCALLOC (MTYPE_AS_PATH, sizeof (struct aspath)); - new->json = NULL; + new = XCALLOC(MTYPE_AS_PATH, sizeof(struct aspath)); + new->json = NULL; - if (aspath->segments) - new->segments = assegment_dup_all (aspath->segments); + if (aspath->segments) + new->segments = assegment_dup_all(aspath->segments); - if (!aspath->str) - return new; + if (!aspath->str) + return new; - new->str = XMALLOC (MTYPE_AS_STR, buflen); - new->str_len = aspath->str_len; + new->str = XMALLOC(MTYPE_AS_STR, buflen); + new->str_len = aspath->str_len; - /* copy the string data */ - if (aspath->str_len > 0) - memcpy (new->str, aspath->str, buflen); - else - new->str[0] = '\0'; + /* copy the string data */ + if (aspath->str_len > 0) + memcpy(new->str, aspath->str, buflen); + else + new->str[0] = '\0'; - return new; + return new; } -static void * -aspath_hash_alloc (void *arg) +static void *aspath_hash_alloc(void *arg) { - const struct aspath *aspath = arg; - struct aspath *new; + const struct aspath *aspath = arg; + struct aspath *new; - /* Malformed AS path value. */ - assert (aspath->str); + /* Malformed AS path value. */ + assert(aspath->str); - /* New aspath structure is needed. */ - new = XMALLOC (MTYPE_AS_PATH, sizeof (struct aspath)); + /* New aspath structure is needed. */ + new = XMALLOC(MTYPE_AS_PATH, sizeof(struct aspath)); - /* Reuse segments and string representation */ - new->refcnt = 0; - new->segments = aspath->segments; - new->str = aspath->str; - new->str_len = aspath->str_len; - new->json = aspath->json; + /* Reuse segments and string representation */ + new->refcnt = 0; + new->segments = aspath->segments; + new->str = aspath->str; + new->str_len = aspath->str_len; + new->json = aspath->json; - return new; + return new; } /* parse as-segment byte stream in struct assegment */ -static int -assegments_parse (struct stream *s, size_t length, - struct assegment **result, int use32bit) -{ - struct assegment_header segh; - struct assegment *seg, *prev = NULL, *head = NULL; - size_t bytes = 0; - - /* empty aspath (ie iBGP or somesuch) */ - if (length == 0) - return 0; - - if (BGP_DEBUG (as4, AS4_SEGMENT)) - zlog_debug ("[AS4SEG] Parse aspath segment: got total byte length %lu", - (unsigned long) length); - /* basic checks */ - if ((STREAM_READABLE(s) < length) - || (STREAM_READABLE(s) < AS_HEADER_SIZE) - || (length % AS16_VALUE_SIZE )) - return -1; - - while (bytes < length) - { - int i; - size_t seg_size; - - if ((length - bytes) <= AS_HEADER_SIZE) - { - if (head) - assegment_free_all (head); - return -1; - } - - /* softly softly, get the header first on its own */ - segh.type = stream_getc (s); - segh.length = stream_getc (s); - - seg_size = ASSEGMENT_SIZE(segh.length, use32bit); - - if (BGP_DEBUG (as4, AS4_SEGMENT)) - zlog_debug ("[AS4SEG] Parse aspath segment: got type %d, length %d", - segh.type, segh.length); - - /* check it.. */ - if ( ((bytes + seg_size) > length) - /* 1771bis 4.3b: seg length contains one or more */ - || (segh.length == 0) - /* Paranoia in case someone changes type of segment length. - * Shift both values by 0x10 to make the comparison operate - * on more, than 8 bits (otherwise it's a warning, bug #564). - */ - || ((sizeof segh.length > 1) - && (0x10 + segh.length > 0x10 + AS_SEGMENT_MAX))) - { - if (head) - assegment_free_all (head); - return -1; - } - - switch (segh.type) - { - case AS_SEQUENCE: - case AS_SET: - case AS_CONFED_SEQUENCE: - case AS_CONFED_SET: - break; - default: - if (head) - assegment_free_all (head); - return -1; - } - - /* now its safe to trust lengths */ - seg = assegment_new (segh.type, segh.length); - - if (head) - prev->next = seg; - else /* it's the first segment */ - head = prev = seg; - - for (i = 0; i < segh.length; i++) - seg->as[i] = (use32bit) ? stream_getl (s) : stream_getw (s); - - bytes += seg_size; - - if (BGP_DEBUG (as4, AS4_SEGMENT)) - zlog_debug ("[AS4SEG] Parse aspath segment: Bytes now: %lu", - (unsigned long) bytes); - - prev = seg; - } - - *result = assegment_normalise (head); - return 0; +static int assegments_parse(struct stream *s, size_t length, + struct assegment **result, int use32bit) +{ + struct assegment_header segh; + struct assegment *seg, *prev = NULL, *head = NULL; + size_t bytes = 0; + + /* empty aspath (ie iBGP or somesuch) */ + if (length == 0) + return 0; + + if (BGP_DEBUG(as4, AS4_SEGMENT)) + zlog_debug( + "[AS4SEG] Parse aspath segment: got total byte length %lu", + (unsigned long)length); + /* basic checks */ + if ((STREAM_READABLE(s) < length) + || (STREAM_READABLE(s) < AS_HEADER_SIZE) + || (length % AS16_VALUE_SIZE)) + return -1; + + while (bytes < length) { + int i; + size_t seg_size; + + if ((length - bytes) <= AS_HEADER_SIZE) { + if (head) + assegment_free_all(head); + return -1; + } + + /* softly softly, get the header first on its own */ + segh.type = stream_getc(s); + segh.length = stream_getc(s); + + seg_size = ASSEGMENT_SIZE(segh.length, use32bit); + + if (BGP_DEBUG(as4, AS4_SEGMENT)) + zlog_debug( + "[AS4SEG] Parse aspath segment: got type %d, length %d", + segh.type, segh.length); + + /* check it.. */ + if (((bytes + seg_size) > length) + /* 1771bis 4.3b: seg length contains one or more */ + || (segh.length == 0) + /* Paranoia in case someone changes type of segment length. + * Shift both values by 0x10 to make the comparison operate + * on more, than 8 bits (otherwise it's a warning, bug + * #564). + */ + || ((sizeof segh.length > 1) + && (0x10 + segh.length > 0x10 + AS_SEGMENT_MAX))) { + if (head) + assegment_free_all(head); + return -1; + } + + switch (segh.type) { + case AS_SEQUENCE: + case AS_SET: + case AS_CONFED_SEQUENCE: + case AS_CONFED_SET: + break; + default: + if (head) + assegment_free_all(head); + return -1; + } + + /* now its safe to trust lengths */ + seg = assegment_new(segh.type, segh.length); + + if (head) + prev->next = seg; + else /* it's the first segment */ + head = prev = seg; + + for (i = 0; i < segh.length; i++) + seg->as[i] = + (use32bit) ? stream_getl(s) : stream_getw(s); + + bytes += seg_size; + + if (BGP_DEBUG(as4, AS4_SEGMENT)) + zlog_debug( + "[AS4SEG] Parse aspath segment: Bytes now: %lu", + (unsigned long)bytes); + + prev = seg; + } + + *result = assegment_normalise(head); + return 0; } /* AS path parse function. pnt is a pointer to byte stream and length is length of byte stream. If there is same AS path in the the AS - path hash then return it else make new AS path structure. - + path hash then return it else make new AS path structure. + On error NULL is returned. */ -struct aspath * -aspath_parse (struct stream *s, size_t length, int use32bit) -{ - struct aspath as; - struct aspath *find; - - /* If length is odd it's malformed AS path. */ - /* Nit-picking: if (use32bit == 0) it is malformed if odd, - * otherwise its malformed when length is larger than 2 and (length-2) - * is not dividable by 4. - * But... this time we're lazy - */ - if (length % AS16_VALUE_SIZE ) - return NULL; - - memset (&as, 0, sizeof (struct aspath)); - if (assegments_parse (s, length, &as.segments, use32bit) < 0) - return NULL; - - /* If already same aspath exist then return it. */ - find = hash_get (ashash, &as, aspath_hash_alloc); - - /* bug! should not happen, let the daemon crash below */ - assert (find); - - /* if the aspath was already hashed free temporary memory. */ - if (find->refcnt) - { - assegment_free_all (as.segments); - /* aspath_key_make() always updates the string */ - XFREE (MTYPE_AS_STR, as.str); - if (as.json) - { - json_object_free(as.json); - as.json = NULL; +struct aspath *aspath_parse(struct stream *s, size_t length, int use32bit) +{ + struct aspath as; + struct aspath *find; + + /* If length is odd it's malformed AS path. */ + /* Nit-picking: if (use32bit == 0) it is malformed if odd, + * otherwise its malformed when length is larger than 2 and (length-2) + * is not dividable by 4. + * But... this time we're lazy + */ + if (length % AS16_VALUE_SIZE) + return NULL; + + memset(&as, 0, sizeof(struct aspath)); + if (assegments_parse(s, length, &as.segments, use32bit) < 0) + return NULL; + + /* If already same aspath exist then return it. */ + find = hash_get(ashash, &as, aspath_hash_alloc); + + /* bug! should not happen, let the daemon crash below */ + assert(find); + + /* if the aspath was already hashed free temporary memory. */ + if (find->refcnt) { + assegment_free_all(as.segments); + /* aspath_key_make() always updates the string */ + XFREE(MTYPE_AS_STR, as.str); + if (as.json) { + json_object_free(as.json); + as.json = NULL; + } } - } - find->refcnt++; + find->refcnt++; - return find; + return find; } -static void -assegment_data_put (struct stream *s, as_t *as, int num, int use32bit) +static void assegment_data_put(struct stream *s, as_t *as, int num, + int use32bit) { - int i; - assert (num <= AS_SEGMENT_MAX); - - for (i = 0; i < num; i++) - if ( use32bit ) - stream_putl (s, as[i]); - else - { - if ( as[i] <= BGP_AS_MAX ) - stream_putw(s, as[i]); - else - stream_putw(s, BGP_AS_TRANS); - } + int i; + assert(num <= AS_SEGMENT_MAX); + + for (i = 0; i < num; i++) + if (use32bit) + stream_putl(s, as[i]); + else { + if (as[i] <= BGP_AS_MAX) + stream_putw(s, as[i]); + else + stream_putw(s, BGP_AS_TRANS); + } } -static size_t -assegment_header_put (struct stream *s, u_char type, int length) +static size_t assegment_header_put(struct stream *s, u_char type, int length) { - size_t lenp; - assert (length <= AS_SEGMENT_MAX); - stream_putc (s, type); - lenp = stream_get_endp (s); - stream_putc (s, length); - return lenp; + size_t lenp; + assert(length <= AS_SEGMENT_MAX); + stream_putc(s, type); + lenp = stream_get_endp(s); + stream_putc(s, length); + return lenp; } /* write aspath data to stream */ -size_t -aspath_put (struct stream *s, struct aspath *as, int use32bit ) -{ - struct assegment *seg = as->segments; - size_t bytes = 0; - - if (!seg || seg->length == 0) - return 0; - - if (seg) - { - /* - * Hey, what do we do when we have > STREAM_WRITABLE(s) here? - * At the moment, we would write out a partial aspath, and our peer - * will complain and drop the session :-/ - * - * The general assumption here is that many things tested will - * never happen. And, in real live, up to now, they have not. - */ - while (seg && (ASSEGMENT_LEN(seg, use32bit) <= STREAM_WRITEABLE(s))) - { - struct assegment *next = seg->next; - int written = 0; - int asns_packed = 0; - size_t lenp; - - /* Overlength segments have to be split up */ - while ( (seg->length - written) > AS_SEGMENT_MAX) - { - assegment_header_put (s, seg->type, AS_SEGMENT_MAX); - assegment_data_put (s, seg->as, AS_SEGMENT_MAX, use32bit); - written += AS_SEGMENT_MAX; - bytes += ASSEGMENT_SIZE (written, use32bit); - } - - /* write the final segment, probably is also the first */ - lenp = assegment_header_put (s, seg->type, seg->length - written); - assegment_data_put (s, (seg->as + written), seg->length - written, - use32bit); - - /* Sequence-type segments can be 'packed' together - * Case of a segment which was overlength and split up - * will be missed here, but that doesn't matter. - */ - while (next && ASSEGMENTS_PACKABLE (seg, next)) - { - /* NB: We should never normally get here given we - * normalise aspath data when parse them. However, better - * safe than sorry. We potentially could call - * assegment_normalise here instead, but it's cheaper and - * easier to do it on the fly here rather than go through - * the segment list twice every time we write out - * aspath's. - */ - - /* Next segment's data can fit in this one */ - assegment_data_put (s, next->as, next->length, use32bit); - - /* update the length of the segment header */ - stream_putc_at (s, lenp, seg->length - written + next->length); - asns_packed += next->length; - - next = next->next; - } - - bytes += ASSEGMENT_SIZE (seg->length - written + asns_packed, - use32bit); - seg = next; - } - } - return bytes; +size_t aspath_put(struct stream *s, struct aspath *as, int use32bit) +{ + struct assegment *seg = as->segments; + size_t bytes = 0; + + if (!seg || seg->length == 0) + return 0; + + if (seg) { + /* + * Hey, what do we do when we have > STREAM_WRITABLE(s) here? + * At the moment, we would write out a partial aspath, and our + * peer + * will complain and drop the session :-/ + * + * The general assumption here is that many things tested will + * never happen. And, in real live, up to now, they have not. + */ + while (seg && (ASSEGMENT_LEN(seg, use32bit) + <= STREAM_WRITEABLE(s))) { + struct assegment *next = seg->next; + int written = 0; + int asns_packed = 0; + size_t lenp; + + /* Overlength segments have to be split up */ + while ((seg->length - written) > AS_SEGMENT_MAX) { + assegment_header_put(s, seg->type, + AS_SEGMENT_MAX); + assegment_data_put(s, seg->as, AS_SEGMENT_MAX, + use32bit); + written += AS_SEGMENT_MAX; + bytes += ASSEGMENT_SIZE(written, use32bit); + } + + /* write the final segment, probably is also the first + */ + lenp = assegment_header_put(s, seg->type, + seg->length - written); + assegment_data_put(s, (seg->as + written), + seg->length - written, use32bit); + + /* Sequence-type segments can be 'packed' together + * Case of a segment which was overlength and split up + * will be missed here, but that doesn't matter. + */ + while (next && ASSEGMENTS_PACKABLE(seg, next)) { + /* NB: We should never normally get here given + * we + * normalise aspath data when parse them. + * However, better + * safe than sorry. We potentially could call + * assegment_normalise here instead, but it's + * cheaper and + * easier to do it on the fly here rather than + * go through + * the segment list twice every time we write + * out + * aspath's. + */ + + /* Next segment's data can fit in this one */ + assegment_data_put(s, next->as, next->length, + use32bit); + + /* update the length of the segment header */ + stream_putc_at(s, lenp, + seg->length - written + + next->length); + asns_packed += next->length; + + next = next->next; + } + + bytes += ASSEGMENT_SIZE( + seg->length - written + asns_packed, use32bit); + seg = next; + } + } + return bytes; } /* This is for SNMP BGP4PATHATTRASPATHSEGMENT * We have no way to manage the storage, so we use a static stream * wrapper around aspath_put. */ -u_char * -aspath_snmp_pathseg (struct aspath *as, size_t *varlen) +u_char *aspath_snmp_pathseg(struct aspath *as, size_t *varlen) { #define SNMP_PATHSEG_MAX 1024 - if (!snmp_stream) - snmp_stream = stream_new (SNMP_PATHSEG_MAX); - else - stream_reset (snmp_stream); - - if (!as) - { - *varlen = 0; - return NULL; - } - aspath_put (snmp_stream, as, 0); /* use 16 bit for now here */ - - *varlen = stream_get_endp (snmp_stream); - return stream_pnt(snmp_stream); -} - + if (!snmp_stream) + snmp_stream = stream_new(SNMP_PATHSEG_MAX); + else + stream_reset(snmp_stream); + + if (!as) { + *varlen = 0; + return NULL; + } + aspath_put(snmp_stream, as, 0); /* use 16 bit for now here */ + + *varlen = stream_get_endp(snmp_stream); + return stream_pnt(snmp_stream); +} + #define min(A,B) ((A) < (B) ? (A) : (B)) -static struct assegment * -aspath_aggregate_as_set_add (struct aspath *aspath, struct assegment *asset, - as_t as) -{ - int i; - - /* If this is first AS set member, create new as-set segment. */ - if (asset == NULL) - { - asset = assegment_new (AS_SET, 1); - if (! aspath->segments) - aspath->segments = asset; - else - { - struct assegment *seg = aspath->segments; - while (seg->next) - seg = seg->next; - seg->next = asset; - } - asset->type = AS_SET; - asset->length = 1; - asset->as[0] = as; - } - else - { - /* Check this AS value already exists or not. */ - for (i = 0; i < asset->length; i++) - if (asset->as[i] == as) - return asset; - - asset->length++; - asset->as = XREALLOC (MTYPE_AS_SEG_DATA, asset->as, - asset->length * AS_VALUE_SIZE); - asset->as[asset->length - 1] = as; - } - - - return asset; +static struct assegment *aspath_aggregate_as_set_add(struct aspath *aspath, + struct assegment *asset, + as_t as) +{ + int i; + + /* If this is first AS set member, create new as-set segment. */ + if (asset == NULL) { + asset = assegment_new(AS_SET, 1); + if (!aspath->segments) + aspath->segments = asset; + else { + struct assegment *seg = aspath->segments; + while (seg->next) + seg = seg->next; + seg->next = asset; + } + asset->type = AS_SET; + asset->length = 1; + asset->as[0] = as; + } else { + /* Check this AS value already exists or not. */ + for (i = 0; i < asset->length; i++) + if (asset->as[i] == as) + return asset; + + asset->length++; + asset->as = XREALLOC(MTYPE_AS_SEG_DATA, asset->as, + asset->length * AS_VALUE_SIZE); + asset->as[asset->length - 1] = as; + } + + + return asset; } /* Modify as1 using as2 for aggregation. */ -struct aspath * -aspath_aggregate (struct aspath *as1, struct aspath *as2) -{ - int i; - int minlen = 0; - int match = 0; - int from; - struct assegment *seg1 = as1->segments; - struct assegment *seg2 = as2->segments; - struct aspath *aspath = NULL; - struct assegment *asset = NULL; - struct assegment *prevseg = NULL; - - /* First of all check common leading sequence. */ - while (seg1 && seg2) - { - /* Check segment type. */ - if (seg1->type != seg2->type) - break; - - /* Minimum segment length. */ - minlen = min (seg1->length, seg2->length); - - for (match = 0; match < minlen; match++) - if (seg1->as[match] != seg2->as[match]) - break; - - if (match) - { - struct assegment *seg = assegment_new (seg1->type, 0); - - seg = assegment_append_asns (seg, seg1->as, match); - - if (! aspath) - { - aspath = aspath_new (); - aspath->segments = seg; - } - else - prevseg->next = seg; - - prevseg = seg; +struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2) +{ + int i; + int minlen = 0; + int match = 0; + int from; + struct assegment *seg1 = as1->segments; + struct assegment *seg2 = as2->segments; + struct aspath *aspath = NULL; + struct assegment *asset = NULL; + struct assegment *prevseg = NULL; + + /* First of all check common leading sequence. */ + while (seg1 && seg2) { + /* Check segment type. */ + if (seg1->type != seg2->type) + break; + + /* Minimum segment length. */ + minlen = min(seg1->length, seg2->length); + + for (match = 0; match < minlen; match++) + if (seg1->as[match] != seg2->as[match]) + break; + + if (match) { + struct assegment *seg = assegment_new(seg1->type, 0); + + seg = assegment_append_asns(seg, seg1->as, match); + + if (!aspath) { + aspath = aspath_new(); + aspath->segments = seg; + } else + prevseg->next = seg; + + prevseg = seg; + } + + if (match != minlen || match != seg1->length + || seg1->length != seg2->length) + break; + /* We are moving on to the next segment to reset match */ + else + match = 0; + + seg1 = seg1->next; + seg2 = seg2->next; + } + + if (!aspath) + aspath = aspath_new(); + + /* Make as-set using rest of all information. */ + from = match; + while (seg1) { + for (i = from; i < seg1->length; i++) + asset = aspath_aggregate_as_set_add(aspath, asset, + seg1->as[i]); + + from = 0; + seg1 = seg1->next; } - if (match != minlen || match != seg1->length - || seg1->length != seg2->length) - break; - /* We are moving on to the next segment to reset match */ - else - match = 0; - - seg1 = seg1->next; - seg2 = seg2->next; - } - - if (! aspath) - aspath = aspath_new(); - - /* Make as-set using rest of all information. */ - from = match; - while (seg1) - { - for (i = from; i < seg1->length; i++) - asset = aspath_aggregate_as_set_add (aspath, asset, seg1->as[i]); - - from = 0; - seg1 = seg1->next; - } - - from = match; - while (seg2) - { - for (i = from; i < seg2->length; i++) - asset = aspath_aggregate_as_set_add (aspath, asset, seg2->as[i]); - - from = 0; - seg2 = seg2->next; - } - - assegment_normalise (aspath->segments); - aspath_str_update (aspath); - return aspath; + from = match; + while (seg2) { + for (i = from; i < seg2->length; i++) + asset = aspath_aggregate_as_set_add(aspath, asset, + seg2->as[i]); + + from = 0; + seg2 = seg2->next; + } + + assegment_normalise(aspath->segments); + aspath_str_update(aspath); + return aspath; } /* When a BGP router receives an UPDATE with an MP_REACH_NLRI attribute, check the leftmost AS number in the AS_PATH attribute is - or not the peer's AS number. */ -int -aspath_firstas_check (struct aspath *aspath, as_t asno) + or not the peer's AS number. */ +int aspath_firstas_check(struct aspath *aspath, as_t asno) { - if ( (aspath == NULL) || (aspath->segments == NULL) ) - return 0; - - if (aspath->segments - && (aspath->segments->type == AS_SEQUENCE) - && (aspath->segments->as[0] == asno )) - return 1; + if ((aspath == NULL) || (aspath->segments == NULL)) + return 0; + + if (aspath->segments && (aspath->segments->type == AS_SEQUENCE) + && (aspath->segments->as[0] == asno)) + return 1; - return 0; + return 0; } -unsigned int -aspath_get_first_as (struct aspath *aspath) +unsigned int aspath_get_first_as(struct aspath *aspath) { - if (aspath == NULL || aspath->segments == NULL) - return 0; + if (aspath == NULL || aspath->segments == NULL) + return 0; - return aspath->segments->as[0]; + return aspath->segments->as[0]; } -unsigned int -aspath_get_last_as (struct aspath *aspath) +unsigned int aspath_get_last_as(struct aspath *aspath) { - int i; - unsigned int last_as = 0; - const struct assegment *seg; + int i; + unsigned int last_as = 0; + const struct assegment *seg; - if (aspath == NULL || aspath->segments == NULL) - return last_as; + if (aspath == NULL || aspath->segments == NULL) + return last_as; - seg = aspath->segments; + seg = aspath->segments; - while (seg) - { - if (seg->type == AS_SEQUENCE || seg->type == AS_CONFED_SEQUENCE) - for (i = 0; i < seg->length; i++) - last_as = seg->as[i]; - seg = seg->next; - } + while (seg) { + if (seg->type == AS_SEQUENCE || seg->type == AS_CONFED_SEQUENCE) + for (i = 0; i < seg->length; i++) + last_as = seg->as[i]; + seg = seg->next; + } - return last_as; + return last_as; } /* AS path loop check. If aspath contains asno then return >= 1. */ -int -aspath_loop_check (struct aspath *aspath, as_t asno) -{ - struct assegment *seg; - int count = 0; - - if ( (aspath == NULL) || (aspath->segments == NULL) ) - return 0; - - seg = aspath->segments; - - while (seg) - { - int i; - - for (i = 0; i < seg->length; i++) - if (seg->as[i] == asno) - count++; - - seg = seg->next; - } - return count; +int aspath_loop_check(struct aspath *aspath, as_t asno) +{ + struct assegment *seg; + int count = 0; + + if ((aspath == NULL) || (aspath->segments == NULL)) + return 0; + + seg = aspath->segments; + + while (seg) { + int i; + + for (i = 0; i < seg->length; i++) + if (seg->as[i] == asno) + count++; + + seg = seg->next; + } + return count; } /* When all of AS path is private AS return 1. */ -int -aspath_private_as_check (struct aspath *aspath) +int aspath_private_as_check(struct aspath *aspath) { - struct assegment *seg; + struct assegment *seg; - if ( !(aspath && aspath->segments) ) - return 0; + if (!(aspath && aspath->segments)) + return 0; - seg = aspath->segments; + seg = aspath->segments; - while (seg) - { - int i; + while (seg) { + int i; - for (i = 0; i < seg->length; i++) - { - if (!BGP_AS_IS_PRIVATE(seg->as[i])) - return 0; + for (i = 0; i < seg->length; i++) { + if (!BGP_AS_IS_PRIVATE(seg->as[i])) + return 0; + } + seg = seg->next; } - seg = seg->next; - } - return 1; + return 1; } /* Return True if the entire ASPATH consist of the specified ASN */ -int -aspath_single_asn_check (struct aspath *aspath, as_t asn) +int aspath_single_asn_check(struct aspath *aspath, as_t asn) { - struct assegment *seg; + struct assegment *seg; - if ( !(aspath && aspath->segments) ) - return 0; + if (!(aspath && aspath->segments)) + return 0; - seg = aspath->segments; + seg = aspath->segments; - while (seg) - { - int i; + while (seg) { + int i; - for (i = 0; i < seg->length; i++) - { - if (seg->as[i] != asn) - return 0; + for (i = 0; i < seg->length; i++) { + if (seg->as[i] != asn) + return 0; + } + seg = seg->next; } - seg = seg->next; - } - return 1; + return 1; } /* Replace all instances of the target ASN with our own ASN */ -struct aspath * -aspath_replace_specific_asn (struct aspath *aspath, as_t target_asn, - as_t our_asn) +struct aspath *aspath_replace_specific_asn(struct aspath *aspath, + as_t target_asn, as_t our_asn) { - struct aspath *new; - struct assegment *seg; + struct aspath *new; + struct assegment *seg; - new = aspath_dup(aspath); - seg = new->segments; + new = aspath_dup(aspath); + seg = new->segments; - while (seg) - { - int i; + while (seg) { + int i; - for (i = 0; i < seg->length; i++) - { - if (seg->as[i] == target_asn) - seg->as[i] = our_asn; + for (i = 0; i < seg->length; i++) { + if (seg->as[i] == target_asn) + seg->as[i] = our_asn; + } + seg = seg->next; } - seg = seg->next; - } - aspath_str_update(new); - return new; + aspath_str_update(new); + return new; } /* Replace all private ASNs with our own ASN */ -struct aspath * -aspath_replace_private_asns (struct aspath *aspath, as_t asn) +struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn) { - struct aspath *new; - struct assegment *seg; + struct aspath *new; + struct assegment *seg; - new = aspath_dup(aspath); - seg = new->segments; + new = aspath_dup(aspath); + seg = new->segments; - while (seg) - { - int i; + while (seg) { + int i; - for (i = 0; i < seg->length; i++) - { - if (BGP_AS_IS_PRIVATE(seg->as[i])) - seg->as[i] = asn; + for (i = 0; i < seg->length; i++) { + if (BGP_AS_IS_PRIVATE(seg->as[i])) + seg->as[i] = asn; + } + seg = seg->next; } - seg = seg->next; - } - aspath_str_update(new); - return new; + aspath_str_update(new); + return new; } /* Remove all private ASNs */ -struct aspath * -aspath_remove_private_asns (struct aspath *aspath) -{ - struct aspath *new; - struct assegment *seg; - struct assegment *new_seg; - struct assegment *last_new_seg; - int i; - int j; - int public = 0; - - new = XCALLOC (MTYPE_AS_PATH, sizeof (struct aspath)); - - new->json = NULL; - new_seg = NULL; - last_new_seg = NULL; - seg = aspath->segments; - while (seg) - { - public = 0; - for (i = 0; i < seg->length; i++) - { - // ASN is public - if (!BGP_AS_IS_PRIVATE(seg->as[i])) - { - public++; - } - } - - // The entire segment is private so skip it - if (!public) - { - seg = seg->next; - continue; - } - - // The entire segment is public so copy it - else if (public == seg->length) - { - new_seg = assegment_dup (seg); - } - - // The segment is a mix of public and private ASNs. Copy as many spots as - // there are public ASNs then come back and fill in only the public ASNs. - else - { - new_seg = assegment_new (seg->type, public); - j = 0; - for (i = 0; i < seg->length; i++) - { - // ASN is public - if (!BGP_AS_IS_PRIVATE(seg->as[i])) - { - new_seg->as[j] = seg->as[i]; - j++; - } - } - } - - // This is the first segment so set the aspath segments pointer to this one - if (!last_new_seg) - new->segments = new_seg; - else - last_new_seg->next = new_seg; - - last_new_seg = new_seg; - seg = seg->next; - } - - aspath_str_update(new); - return new; -} - -/* AS path confed check. If aspath contains confed set or sequence then return 1. */ -int -aspath_confed_check (struct aspath *aspath) -{ - struct assegment *seg; - - if ( !(aspath && aspath->segments) ) - return 0; - - seg = aspath->segments; - - while (seg) - { - if (seg->type == AS_CONFED_SET || seg->type == AS_CONFED_SEQUENCE) - return 1; - seg = seg->next; - } - return 0; +struct aspath *aspath_remove_private_asns(struct aspath *aspath) +{ + struct aspath *new; + struct assegment *seg; + struct assegment *new_seg; + struct assegment *last_new_seg; + int i; + int j; + int public = 0; + + new = XCALLOC(MTYPE_AS_PATH, sizeof(struct aspath)); + + new->json = NULL; + new_seg = NULL; + last_new_seg = NULL; + seg = aspath->segments; + while (seg) { + public + = 0; + for (i = 0; i < seg->length; i++) { + // ASN is public + if (!BGP_AS_IS_PRIVATE(seg->as[i])) { + public + ++; + } + } + + // The entire segment is private so skip it + if (!public) { + seg = seg->next; + continue; + } + + // The entire segment is public so copy it + else if (public == seg->length) { + new_seg = assegment_dup(seg); + } + + // The segment is a mix of public and private ASNs. Copy as many + // spots as + // there are public ASNs then come back and fill in only the + // public ASNs. + else { + new_seg = assegment_new(seg->type, public); + j = 0; + for (i = 0; i < seg->length; i++) { + // ASN is public + if (!BGP_AS_IS_PRIVATE(seg->as[i])) { + new_seg->as[j] = seg->as[i]; + j++; + } + } + } + + // This is the first segment so set the aspath segments pointer + // to this one + if (!last_new_seg) + new->segments = new_seg; + else + last_new_seg->next = new_seg; + + last_new_seg = new_seg; + seg = seg->next; + } + + aspath_str_update(new); + return new; +} + +/* AS path confed check. If aspath contains confed set or sequence then return + * 1. */ +int aspath_confed_check(struct aspath *aspath) +{ + struct assegment *seg; + + if (!(aspath && aspath->segments)) + return 0; + + seg = aspath->segments; + + while (seg) { + if (seg->type == AS_CONFED_SET + || seg->type == AS_CONFED_SEQUENCE) + return 1; + seg = seg->next; + } + return 0; } /* Leftmost AS path segment confed check. If leftmost AS segment is of type AS_CONFED_SEQUENCE or AS_CONFED_SET then return 1. */ -int -aspath_left_confed_check (struct aspath *aspath) +int aspath_left_confed_check(struct aspath *aspath) { - if ( !(aspath && aspath->segments) ) - return 0; + if (!(aspath && aspath->segments)) + return 0; - if ( (aspath->segments->type == AS_CONFED_SEQUENCE) - || (aspath->segments->type == AS_CONFED_SET) ) - return 1; + if ((aspath->segments->type == AS_CONFED_SEQUENCE) + || (aspath->segments->type == AS_CONFED_SET)) + return 1; - return 0; + return 0; } /* Merge as1 to as2. as2 should be uninterned aspath. */ -static struct aspath * -aspath_merge (struct aspath *as1, struct aspath *as2) +static struct aspath *aspath_merge(struct aspath *as1, struct aspath *as2) { - struct assegment *last, *new; + struct assegment *last, *new; - if (! as1 || ! as2) - return NULL; + if (!as1 || !as2) + return NULL; - last = new = assegment_dup_all (as1->segments); - - /* find the last valid segment */ - while (last && last->next) - last = last->next; - - last->next = as2->segments; - as2->segments = new; - aspath_str_update (as2); - return as2; + last = new = assegment_dup_all(as1->segments); + + /* find the last valid segment */ + while (last && last->next) + last = last->next; + + last->next = as2->segments; + as2->segments = new; + aspath_str_update(as2); + return as2; } /* Prepend as1 to as2. as2 should be uninterned aspath. */ -struct aspath * -aspath_prepend (struct aspath *as1, struct aspath *as2) -{ - struct assegment *seg1; - struct assegment *seg2; - - if (! as1 || ! as2) - return NULL; - - seg1 = as1->segments; - seg2 = as2->segments; - - /* If as2 is empty, only need to dupe as1's chain onto as2 */ - if (seg2 == NULL) - { - as2->segments = assegment_dup_all (as1->segments); - aspath_str_update (as2); - return as2; - } - - /* If as1 is empty AS, no prepending to do. */ - if (seg1 == NULL) - return as2; - - /* find the tail as1's segment chain. */ - while (seg1 && seg1->next) - seg1 = seg1->next; - - /* Delete any AS_CONFED_SEQUENCE segment from as2. */ - if (seg1->type == AS_SEQUENCE && seg2->type == AS_CONFED_SEQUENCE) - as2 = aspath_delete_confed_seq (as2); - - /* Compare last segment type of as1 and first segment type of as2. */ - if (seg1->type != seg2->type) - return aspath_merge (as1, as2); - - if (seg1->type == AS_SEQUENCE) - { - /* We have two chains of segments, as1->segments and seg2, - * and we have to attach them together, merging the attaching - * segments together into one. - * - * 1. dupe as1->segments onto head of as2 - * 2. merge seg2's asns onto last segment of this new chain - * 3. attach chain after seg2 - */ - - /* dupe as1 onto as2's head */ - seg1 = as2->segments = assegment_dup_all (as1->segments); - - /* refind the tail of as2, reusing seg1 */ - while (seg1 && seg1->next) - seg1 = seg1->next; - - /* merge the old head, seg2, into tail, seg1 */ - seg1 = assegment_append_asns (seg1, seg2->as, seg2->length); - - /* bypass the merged seg2, and attach any chain after it to - * chain descending from as2's head - */ - seg1->next = seg2->next; - - /* seg2 is now referenceless and useless*/ - assegment_free (seg2); - - /* we've now prepended as1's segment chain to as2, merging - * the inbetween AS_SEQUENCE of seg2 in the process - */ - aspath_str_update (as2); - return as2; - } - else - { - /* AS_SET merge code is needed at here. */ - return aspath_merge (as1, as2); - } - /* XXX: Ermmm, what if as1 has multiple segments?? */ - - /* Not reached */ +struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2) +{ + struct assegment *seg1; + struct assegment *seg2; + + if (!as1 || !as2) + return NULL; + + seg1 = as1->segments; + seg2 = as2->segments; + + /* If as2 is empty, only need to dupe as1's chain onto as2 */ + if (seg2 == NULL) { + as2->segments = assegment_dup_all(as1->segments); + aspath_str_update(as2); + return as2; + } + + /* If as1 is empty AS, no prepending to do. */ + if (seg1 == NULL) + return as2; + + /* find the tail as1's segment chain. */ + while (seg1 && seg1->next) + seg1 = seg1->next; + + /* Delete any AS_CONFED_SEQUENCE segment from as2. */ + if (seg1->type == AS_SEQUENCE && seg2->type == AS_CONFED_SEQUENCE) + as2 = aspath_delete_confed_seq(as2); + + /* Compare last segment type of as1 and first segment type of as2. */ + if (seg1->type != seg2->type) + return aspath_merge(as1, as2); + + if (seg1->type == AS_SEQUENCE) { + /* We have two chains of segments, as1->segments and seg2, + * and we have to attach them together, merging the attaching + * segments together into one. + * + * 1. dupe as1->segments onto head of as2 + * 2. merge seg2's asns onto last segment of this new chain + * 3. attach chain after seg2 + */ + + /* dupe as1 onto as2's head */ + seg1 = as2->segments = assegment_dup_all(as1->segments); + + /* refind the tail of as2, reusing seg1 */ + while (seg1 && seg1->next) + seg1 = seg1->next; + + /* merge the old head, seg2, into tail, seg1 */ + seg1 = assegment_append_asns(seg1, seg2->as, seg2->length); + + /* bypass the merged seg2, and attach any chain after it to + * chain descending from as2's head + */ + seg1->next = seg2->next; + + /* seg2 is now referenceless and useless*/ + assegment_free(seg2); + + /* we've now prepended as1's segment chain to as2, merging + * the inbetween AS_SEQUENCE of seg2 in the process + */ + aspath_str_update(as2); + return as2; + } else { + /* AS_SET merge code is needed at here. */ + return aspath_merge(as1, as2); + } + /* XXX: Ermmm, what if as1 has multiple segments?? */ + + /* Not reached */ } /* Iterate over AS_PATH segments and wipe all occurences of the @@ -1541,159 +1449,158 @@ aspath_prepend (struct aspath *as1, struct aspath *as2) * version of aspath_dup(), which allocates memory to hold the new * data, not the original. The new AS path is returned. */ -struct aspath * -aspath_filter_exclude (struct aspath * source, struct aspath * exclude_list) -{ - struct assegment * srcseg, * exclseg, * lastseg; - struct aspath * newpath; - - newpath = aspath_new(); - lastseg = NULL; - - for (srcseg = source->segments; srcseg; srcseg = srcseg->next) - { - unsigned i, y, newlen = 0, done = 0, skip_as; - struct assegment * newseg; - - /* Find out, how much ASns are we going to pick from this segment. - * We can't perform filtering right inline, because the size of - * the new segment isn't known at the moment yet. - */ - for (i = 0; i < srcseg->length; i++) - { - skip_as = 0; - for (exclseg = exclude_list->segments; exclseg && !skip_as; exclseg = exclseg->next) - for (y = 0; y < exclseg->length; y++) - if (srcseg->as[i] == exclseg->as[y]) - { - skip_as = 1; - // There's no sense in testing the rest of exclusion list, bail out. - break; - } - if (!skip_as) - newlen++; - } - /* newlen is now the number of ASns to copy */ - if (!newlen) - continue; - - /* Actual copying. Allocate memory and iterate once more, performing filtering. */ - newseg = assegment_new (srcseg->type, newlen); - for (i = 0; i < srcseg->length; i++) - { - skip_as = 0; - for (exclseg = exclude_list->segments; exclseg && !skip_as; exclseg = exclseg->next) - for (y = 0; y < exclseg->length; y++) - if (srcseg->as[i] == exclseg->as[y]) - { - skip_as = 1; - break; - } - if (skip_as) - continue; - newseg->as[done++] = srcseg->as[i]; - } - /* At his point newlen must be equal to done, and both must be positive. Append - * the filtered segment to the gross result. */ - if (!lastseg) - newpath->segments = newseg; - else - lastseg->next = newseg; - lastseg = newseg; - } - aspath_str_update (newpath); - /* We are happy returning even an empty AS_PATH, because the administrator - * might expect this very behaviour. There's a mean to avoid this, if necessary, - * by having a match rule against certain AS_PATH regexps in the route-map index. - */ - aspath_free (source); - return newpath; +struct aspath *aspath_filter_exclude(struct aspath *source, + struct aspath *exclude_list) +{ + struct assegment *srcseg, *exclseg, *lastseg; + struct aspath *newpath; + + newpath = aspath_new(); + lastseg = NULL; + + for (srcseg = source->segments; srcseg; srcseg = srcseg->next) { + unsigned i, y, newlen = 0, done = 0, skip_as; + struct assegment *newseg; + + /* Find out, how much ASns are we going to pick from this + * segment. + * We can't perform filtering right inline, because the size of + * the new segment isn't known at the moment yet. + */ + for (i = 0; i < srcseg->length; i++) { + skip_as = 0; + for (exclseg = exclude_list->segments; + exclseg && !skip_as; exclseg = exclseg->next) + for (y = 0; y < exclseg->length; y++) + if (srcseg->as[i] == exclseg->as[y]) { + skip_as = 1; + // There's no sense in testing + // the rest of exclusion list, + // bail out. + break; + } + if (!skip_as) + newlen++; + } + /* newlen is now the number of ASns to copy */ + if (!newlen) + continue; + + /* Actual copying. Allocate memory and iterate once more, + * performing filtering. */ + newseg = assegment_new(srcseg->type, newlen); + for (i = 0; i < srcseg->length; i++) { + skip_as = 0; + for (exclseg = exclude_list->segments; + exclseg && !skip_as; exclseg = exclseg->next) + for (y = 0; y < exclseg->length; y++) + if (srcseg->as[i] == exclseg->as[y]) { + skip_as = 1; + break; + } + if (skip_as) + continue; + newseg->as[done++] = srcseg->as[i]; + } + /* At his point newlen must be equal to done, and both must be + * positive. Append + * the filtered segment to the gross result. */ + if (!lastseg) + newpath->segments = newseg; + else + lastseg->next = newseg; + lastseg = newseg; + } + aspath_str_update(newpath); + /* We are happy returning even an empty AS_PATH, because the + * administrator + * might expect this very behaviour. There's a mean to avoid this, if + * necessary, + * by having a match rule against certain AS_PATH regexps in the + * route-map index. + */ + aspath_free(source); + return newpath; } /* Add specified AS to the leftmost of aspath. */ -static struct aspath * -aspath_add_asns (struct aspath *aspath, as_t asno, u_char type, unsigned num) -{ - struct assegment *assegment = aspath->segments; - unsigned i; - - if (assegment && assegment->type == type) - { - /* extend existing segment */ - aspath->segments = assegment_prepend_asns (aspath->segments, asno, num); - } - else - { - /* prepend with new segment */ - struct assegment *newsegment = assegment_new (type, num); - for (i = 0; i < num; i++) - newsegment->as[i] = asno; - - /* insert potentially replacing empty segment */ - if (assegment && assegment->length == 0) - { - newsegment->next = assegment->next; - assegment_free (assegment); +static struct aspath *aspath_add_asns(struct aspath *aspath, as_t asno, + u_char type, unsigned num) +{ + struct assegment *assegment = aspath->segments; + unsigned i; + + if (assegment && assegment->type == type) { + /* extend existing segment */ + aspath->segments = + assegment_prepend_asns(aspath->segments, asno, num); + } else { + /* prepend with new segment */ + struct assegment *newsegment = assegment_new(type, num); + for (i = 0; i < num; i++) + newsegment->as[i] = asno; + + /* insert potentially replacing empty segment */ + if (assegment && assegment->length == 0) { + newsegment->next = assegment->next; + assegment_free(assegment); + } else + newsegment->next = assegment; + aspath->segments = newsegment; } - else - newsegment->next = assegment; - aspath->segments = newsegment; - } - aspath_str_update (aspath); - return aspath; + aspath_str_update(aspath); + return aspath; } /* Add specified AS to the leftmost of aspath num times. */ -struct aspath * -aspath_add_seq_n (struct aspath *aspath, as_t asno, unsigned num) +struct aspath *aspath_add_seq_n(struct aspath *aspath, as_t asno, unsigned num) { - return aspath_add_asns (aspath, asno, AS_SEQUENCE, num); + return aspath_add_asns(aspath, asno, AS_SEQUENCE, num); } /* Add specified AS to the leftmost of aspath. */ -struct aspath * -aspath_add_seq (struct aspath *aspath, as_t asno) +struct aspath *aspath_add_seq(struct aspath *aspath, as_t asno) { - return aspath_add_asns (aspath, asno, AS_SEQUENCE, 1); + return aspath_add_asns(aspath, asno, AS_SEQUENCE, 1); } /* Compare leftmost AS value for MED check. If as1's leftmost AS and as2's leftmost AS is same return 1. */ -int -aspath_cmp_left (const struct aspath *aspath1, const struct aspath *aspath2) +int aspath_cmp_left(const struct aspath *aspath1, const struct aspath *aspath2) { - const struct assegment *seg1; - const struct assegment *seg2; + const struct assegment *seg1; + const struct assegment *seg2; + + if (!(aspath1 && aspath2)) + return 0; - if (!(aspath1 && aspath2)) - return 0; + seg1 = aspath1->segments; + seg2 = aspath2->segments; - seg1 = aspath1->segments; - seg2 = aspath2->segments; + /* If both paths are originated in this AS then we do want to compare + * MED */ + if (!seg1 && !seg2) + return 1; - /* If both paths are originated in this AS then we do want to compare MED */ - if (!seg1 && !seg2) - return 1; + /* find first non-confed segments for each */ + while (seg1 && ((seg1->type == AS_CONFED_SEQUENCE) + || (seg1->type == AS_CONFED_SET))) + seg1 = seg1->next; - /* find first non-confed segments for each */ - while (seg1 && ((seg1->type == AS_CONFED_SEQUENCE) - || (seg1->type == AS_CONFED_SET))) - seg1 = seg1->next; + while (seg2 && ((seg2->type == AS_CONFED_SEQUENCE) + || (seg2->type == AS_CONFED_SET))) + seg2 = seg2->next; - while (seg2 && ((seg2->type == AS_CONFED_SEQUENCE) - || (seg2->type == AS_CONFED_SET))) - seg2 = seg2->next; + /* Check as1's */ + if (!(seg1 && seg2 && (seg1->type == AS_SEQUENCE) + && (seg2->type == AS_SEQUENCE))) + return 0; - /* Check as1's */ - if (!(seg1 && seg2 - && (seg1->type == AS_SEQUENCE) && (seg2->type == AS_SEQUENCE))) - return 0; - - if (seg1->as[0] == seg2->as[0]) - return 1; + if (seg1->as[0] == seg2->as[0]) + return 1; - return 0; + return 0; } /* Truncate an aspath after a number of hops, and put the hops remaining @@ -1702,127 +1609,127 @@ aspath_cmp_left (const struct aspath *aspath1, const struct aspath *aspath2) * Returned aspath is a /new/ aspath, which should either by free'd or * interned by the caller, as desired. */ -struct aspath * -aspath_reconcile_as4 ( struct aspath *aspath, struct aspath *as4path) -{ - struct assegment *seg, *newseg, *prevseg = NULL; - struct aspath *newpath = NULL, *mergedpath; - int hops, cpasns = 0; - - if (!aspath) - return NULL; - - seg = aspath->segments; - - /* CONFEDs should get reconciled too.. */ - hops = (aspath_count_hops (aspath) + aspath_count_confeds (aspath)) - - aspath_count_hops (as4path); - - if (hops < 0) - { - if (BGP_DEBUG (as4, AS4)) - zlog_warn ("[AS4] Fewer hops in AS_PATH than NEW_AS_PATH"); - /* Something's gone wrong. The RFC says we should now ignore AS4_PATH, - * which is daft behaviour - it contains vital loop-detection - * information which must have been removed from AS_PATH. - */ - hops = aspath_count_hops (aspath); - } - - if (!hops) - { - newpath = aspath_dup (as4path); - aspath_str_update(newpath); - return newpath; - } - - if ( BGP_DEBUG(as4, AS4)) - zlog_debug("[AS4] got AS_PATH %s and AS4_PATH %s synthesizing now", - aspath->str, as4path->str); - - while (seg && hops > 0) - { - switch (seg->type) - { - case AS_SET: - case AS_CONFED_SET: - hops--; - cpasns = seg->length; - break; - case AS_CONFED_SEQUENCE: - /* Should never split a confed-sequence, if hop-count - * suggests we must then something's gone wrong somewhere. - * - * Most important goal is to preserve AS_PATHs prime function - * as loop-detector, so we fudge the numbers so that the entire - * confed-sequence is merged in. - */ - if (hops < seg->length) - { - if (BGP_DEBUG (as4, AS4)) - zlog_debug ("[AS4] AS4PATHmangle: AS_CONFED_SEQUENCE falls" - " across 2/4 ASN boundary somewhere, broken.."); - hops = seg->length; - } - /* fallthru */ - case AS_SEQUENCE: - cpasns = MIN(seg->length, hops); - hops -= seg->length; +struct aspath *aspath_reconcile_as4(struct aspath *aspath, + struct aspath *as4path) +{ + struct assegment *seg, *newseg, *prevseg = NULL; + struct aspath *newpath = NULL, *mergedpath; + int hops, cpasns = 0; + + if (!aspath) + return NULL; + + seg = aspath->segments; + + /* CONFEDs should get reconciled too.. */ + hops = (aspath_count_hops(aspath) + aspath_count_confeds(aspath)) + - aspath_count_hops(as4path); + + if (hops < 0) { + if (BGP_DEBUG(as4, AS4)) + zlog_warn( + "[AS4] Fewer hops in AS_PATH than NEW_AS_PATH"); + /* Something's gone wrong. The RFC says we should now ignore + * AS4_PATH, + * which is daft behaviour - it contains vital loop-detection + * information which must have been removed from AS_PATH. + */ + hops = aspath_count_hops(aspath); + } + + if (!hops) { + newpath = aspath_dup(as4path); + aspath_str_update(newpath); + return newpath; } - - assert (cpasns <= seg->length); - - newseg = assegment_new (seg->type, 0); - newseg = assegment_append_asns (newseg, seg->as, cpasns); - - if (!newpath) - { - newpath = aspath_new (); - newpath->segments = newseg; - } - else - prevseg->next = newseg; - - prevseg = newseg; - seg = seg->next; - } - - /* We may be able to join some segments here, and we must - * do this because... we want normalised aspaths in out hash - * and we do not want to stumble in aspath_put. - */ - mergedpath = aspath_merge (newpath, aspath_dup(as4path)); - aspath_free (newpath); - mergedpath->segments = assegment_normalise (mergedpath->segments); - aspath_str_update (mergedpath); - - if ( BGP_DEBUG(as4, AS4)) - zlog_debug ("[AS4] result of synthesizing is %s", - mergedpath->str); - - return mergedpath; + + if (BGP_DEBUG(as4, AS4)) + zlog_debug( + "[AS4] got AS_PATH %s and AS4_PATH %s synthesizing now", + aspath->str, as4path->str); + + while (seg && hops > 0) { + switch (seg->type) { + case AS_SET: + case AS_CONFED_SET: + hops--; + cpasns = seg->length; + break; + case AS_CONFED_SEQUENCE: + /* Should never split a confed-sequence, if hop-count + * suggests we must then something's gone wrong + * somewhere. + * + * Most important goal is to preserve AS_PATHs prime + * function + * as loop-detector, so we fudge the numbers so that the + * entire + * confed-sequence is merged in. + */ + if (hops < seg->length) { + if (BGP_DEBUG(as4, AS4)) + zlog_debug( + "[AS4] AS4PATHmangle: AS_CONFED_SEQUENCE falls" + " across 2/4 ASN boundary somewhere, broken.."); + hops = seg->length; + } + /* fallthru */ + case AS_SEQUENCE: + cpasns = MIN(seg->length, hops); + hops -= seg->length; + } + + assert(cpasns <= seg->length); + + newseg = assegment_new(seg->type, 0); + newseg = assegment_append_asns(newseg, seg->as, cpasns); + + if (!newpath) { + newpath = aspath_new(); + newpath->segments = newseg; + } else + prevseg->next = newseg; + + prevseg = newseg; + seg = seg->next; + } + + /* We may be able to join some segments here, and we must + * do this because... we want normalised aspaths in out hash + * and we do not want to stumble in aspath_put. + */ + mergedpath = aspath_merge(newpath, aspath_dup(as4path)); + aspath_free(newpath); + mergedpath->segments = assegment_normalise(mergedpath->segments); + aspath_str_update(mergedpath); + + if (BGP_DEBUG(as4, AS4)) + zlog_debug("[AS4] result of synthesizing is %s", + mergedpath->str); + + return mergedpath; } /* Compare leftmost AS value for MED check. If as1's leftmost AS and as2's leftmost AS is same return 1. (confederation as-path only). */ -int -aspath_cmp_left_confed (const struct aspath *aspath1, const struct aspath *aspath2) +int aspath_cmp_left_confed(const struct aspath *aspath1, + const struct aspath *aspath2) { - if (! (aspath1 && aspath2) ) - return 0; - - if ( !(aspath1->segments && aspath2->segments) ) - return 0; - - if ( (aspath1->segments->type != AS_CONFED_SEQUENCE) - || (aspath2->segments->type != AS_CONFED_SEQUENCE) ) - return 0; - - if (aspath1->segments->as[0] == aspath2->segments->as[0]) - return 1; + if (!(aspath1 && aspath2)) + return 0; - return 0; + if (!(aspath1->segments && aspath2->segments)) + return 0; + + if ((aspath1->segments->type != AS_CONFED_SEQUENCE) + || (aspath2->segments->type != AS_CONFED_SEQUENCE)) + return 0; + + if (aspath1->segments->as[0] == aspath2->segments->as[0]) + return 1; + + return 0; } /* Delete all AS_CONFED_SEQUENCE/SET segments from aspath. @@ -1833,111 +1740,100 @@ aspath_cmp_left_confed (const struct aspath *aspath1, const struct aspath *aspat * removed from the AS_PATH attribute, leaving the sanitized * AS_PATH attribute to be operated on by steps 2, 3 or 4. */ -struct aspath * -aspath_delete_confed_seq (struct aspath *aspath) +struct aspath *aspath_delete_confed_seq(struct aspath *aspath) { - struct assegment *seg, *prev, *next; - char removed_confed_segment; + struct assegment *seg, *prev, *next; + char removed_confed_segment; + + if (!(aspath && aspath->segments)) + return aspath; - if (!(aspath && aspath->segments)) - return aspath; + seg = aspath->segments; + removed_confed_segment = 0; + next = NULL; + prev = NULL; - seg = aspath->segments; - removed_confed_segment = 0; - next = NULL; - prev = NULL; - - while (seg) - { - next = seg->next; + while (seg) { + next = seg->next; - if (seg->type == AS_CONFED_SEQUENCE || seg->type == AS_CONFED_SET) - { - /* This is the first segment in the aspath */ - if (aspath->segments == seg) - aspath->segments = seg->next; - else - prev->next = seg->next; + if (seg->type == AS_CONFED_SEQUENCE + || seg->type == AS_CONFED_SET) { + /* This is the first segment in the aspath */ + if (aspath->segments == seg) + aspath->segments = seg->next; + else + prev->next = seg->next; - assegment_free (seg); - removed_confed_segment = 1; - } - else - prev = seg; + assegment_free(seg); + removed_confed_segment = 1; + } else + prev = seg; - seg = next; - } + seg = next; + } - if (removed_confed_segment) - aspath_str_update (aspath); + if (removed_confed_segment) + aspath_str_update(aspath); - return aspath; + return aspath; } /* Add new AS number to the leftmost part of the aspath as AS_CONFED_SEQUENCE. */ -struct aspath* -aspath_add_confed_seq (struct aspath *aspath, as_t asno) +struct aspath *aspath_add_confed_seq(struct aspath *aspath, as_t asno) { - return aspath_add_asns (aspath, asno, AS_CONFED_SEQUENCE, 1); + return aspath_add_asns(aspath, asno, AS_CONFED_SEQUENCE, 1); } /* Add new as value to as path structure. */ -static void -aspath_as_add (struct aspath *as, as_t asno) +static void aspath_as_add(struct aspath *as, as_t asno) { - struct assegment *seg = as->segments; + struct assegment *seg = as->segments; + + if (!seg) + return; - if (!seg) - return; - - /* Last segment search procedure. */ - while (seg->next) - seg = seg->next; + /* Last segment search procedure. */ + while (seg->next) + seg = seg->next; - assegment_append_asns (seg, &asno, 1); + assegment_append_asns(seg, &asno, 1); } /* Add new as segment to the as path. */ -static void -aspath_segment_add (struct aspath *as, int type) +static void aspath_segment_add(struct aspath *as, int type) { - struct assegment *seg = as->segments; - struct assegment *new = assegment_new (type, 0); + struct assegment *seg = as->segments; + struct assegment *new = assegment_new(type, 0); - if (seg) - { - while (seg->next) - seg = seg->next; - seg->next = new; - } - else - as->segments = new; + if (seg) { + while (seg->next) + seg = seg->next; + seg->next = new; + } else + as->segments = new; } -struct aspath * -aspath_empty (void) +struct aspath *aspath_empty(void) { - return aspath_parse (NULL, 0, 1); /* 32Bit ;-) */ + return aspath_parse(NULL, 0, 1); /* 32Bit ;-) */ } -struct aspath * -aspath_empty_get (void) +struct aspath *aspath_empty_get(void) { - struct aspath *aspath; + struct aspath *aspath; - aspath = aspath_new (); - aspath_make_str_count (aspath); - return aspath; + aspath = aspath_new(); + aspath_make_str_count(aspath); + return aspath; } -unsigned long -aspath_count (void) +unsigned long aspath_count(void) { - return ashash->count; -} + return ashash->count; +} -/* +/* Theoretically, one as path can have: One BGP packet size should be less than 4096. @@ -1947,246 +1843,230 @@ aspath_count (void) */ /* AS path string lexical token enum. */ -enum as_token -{ - as_token_asval, - as_token_set_start, - as_token_set_end, - as_token_confed_seq_start, - as_token_confed_seq_end, - as_token_confed_set_start, - as_token_confed_set_end, - as_token_unknown +enum as_token { + as_token_asval, + as_token_set_start, + as_token_set_end, + as_token_confed_seq_start, + as_token_confed_seq_end, + as_token_confed_set_start, + as_token_confed_set_end, + as_token_unknown }; /* Return next token and point for string parse. */ -static const char * -aspath_gettoken (const char *buf, enum as_token *token, u_long *asno) -{ - const char *p = buf; - - /* Skip seperators (space for sequences, ',' for sets). */ - while (isspace ((int) *p) || *p == ',') - p++; - - /* Check the end of the string and type specify characters - (e.g. {}()). */ - switch (*p) - { - case '\0': - return NULL; - case '{': - *token = as_token_set_start; - p++; - return p; - case '}': - *token = as_token_set_end; - p++; - return p; - case '(': - *token = as_token_confed_seq_start; - p++; - return p; - case ')': - *token = as_token_confed_seq_end; - p++; - return p; - case '[': - *token = as_token_confed_set_start; - p++; - return p; - case ']': - *token = as_token_confed_set_end; - p++; - return p; - } - - /* Check actual AS value. */ - if (isdigit ((int) *p)) - { - as_t asval; - - *token = as_token_asval; - asval = (*p - '0'); - p++; - - while (isdigit ((int) *p)) - { - asval *= 10; - asval += (*p - '0'); - p++; - } - *asno = asval; - return p; - } - - /* There is no match then return unknown token. */ - *token = as_token_unknown; - return p++; -} - -struct aspath * -aspath_str2aspath (const char *str) -{ - enum as_token token = as_token_unknown; - u_short as_type; - u_long asno = 0; - struct aspath *aspath; - int needtype; - - aspath = aspath_new (); - - /* We start default type as AS_SEQUENCE. */ - as_type = AS_SEQUENCE; - needtype = 1; - - while ((str = aspath_gettoken (str, &token, &asno)) != NULL) - { - switch (token) - { - case as_token_asval: - if (needtype) - { - aspath_segment_add (aspath, as_type); - needtype = 0; - } - aspath_as_add (aspath, asno); - break; - case as_token_set_start: - as_type = AS_SET; - aspath_segment_add (aspath, as_type); - needtype = 0; - break; - case as_token_set_end: - as_type = AS_SEQUENCE; - needtype = 1; - break; - case as_token_confed_seq_start: - as_type = AS_CONFED_SEQUENCE; - aspath_segment_add (aspath, as_type); - needtype = 0; - break; - case as_token_confed_seq_end: - as_type = AS_SEQUENCE; - needtype = 1; - break; - case as_token_confed_set_start: - as_type = AS_CONFED_SET; - aspath_segment_add (aspath, as_type); - needtype = 0; - break; - case as_token_confed_set_end: - as_type = AS_SEQUENCE; - needtype = 1; - break; - case as_token_unknown: - default: - aspath_free (aspath); - return NULL; +static const char *aspath_gettoken(const char *buf, enum as_token *token, + u_long *asno) +{ + const char *p = buf; + + /* Skip seperators (space for sequences, ',' for sets). */ + while (isspace((int)*p) || *p == ',') + p++; + + /* Check the end of the string and type specify characters + (e.g. {}()). */ + switch (*p) { + case '\0': + return NULL; + case '{': + *token = as_token_set_start; + p++; + return p; + case '}': + *token = as_token_set_end; + p++; + return p; + case '(': + *token = as_token_confed_seq_start; + p++; + return p; + case ')': + *token = as_token_confed_seq_end; + p++; + return p; + case '[': + *token = as_token_confed_set_start; + p++; + return p; + case ']': + *token = as_token_confed_set_end; + p++; + return p; + } + + /* Check actual AS value. */ + if (isdigit((int)*p)) { + as_t asval; + + *token = as_token_asval; + asval = (*p - '0'); + p++; + + while (isdigit((int)*p)) { + asval *= 10; + asval += (*p - '0'); + p++; + } + *asno = asval; + return p; } - } - aspath_make_str_count (aspath); + /* There is no match then return unknown token. */ + *token = as_token_unknown; + return p++; +} + +struct aspath *aspath_str2aspath(const char *str) +{ + enum as_token token = as_token_unknown; + u_short as_type; + u_long asno = 0; + struct aspath *aspath; + int needtype; + + aspath = aspath_new(); + + /* We start default type as AS_SEQUENCE. */ + as_type = AS_SEQUENCE; + needtype = 1; + + while ((str = aspath_gettoken(str, &token, &asno)) != NULL) { + switch (token) { + case as_token_asval: + if (needtype) { + aspath_segment_add(aspath, as_type); + needtype = 0; + } + aspath_as_add(aspath, asno); + break; + case as_token_set_start: + as_type = AS_SET; + aspath_segment_add(aspath, as_type); + needtype = 0; + break; + case as_token_set_end: + as_type = AS_SEQUENCE; + needtype = 1; + break; + case as_token_confed_seq_start: + as_type = AS_CONFED_SEQUENCE; + aspath_segment_add(aspath, as_type); + needtype = 0; + break; + case as_token_confed_seq_end: + as_type = AS_SEQUENCE; + needtype = 1; + break; + case as_token_confed_set_start: + as_type = AS_CONFED_SET; + aspath_segment_add(aspath, as_type); + needtype = 0; + break; + case as_token_confed_set_end: + as_type = AS_SEQUENCE; + needtype = 1; + break; + case as_token_unknown: + default: + aspath_free(aspath); + return NULL; + } + } + + aspath_make_str_count(aspath); - return aspath; + return aspath; } /* Make hash value by raw aspath data. */ -unsigned int -aspath_key_make (void *p) +unsigned int aspath_key_make(void *p) { - struct aspath *aspath = (struct aspath *) p; - unsigned int key = 0; + struct aspath *aspath = (struct aspath *)p; + unsigned int key = 0; - if (!aspath->str) - aspath_str_update (aspath); + if (!aspath->str) + aspath_str_update(aspath); - key = jhash (aspath->str, aspath->str_len, 2334325); + key = jhash(aspath->str, aspath->str_len, 2334325); - return key; + return key; } /* If two aspath have same value then return 1 else return 0 */ -int -aspath_cmp (const void *arg1, const void *arg2) -{ - const struct assegment *seg1 = ((const struct aspath *)arg1)->segments; - const struct assegment *seg2 = ((const struct aspath *)arg2)->segments; - - while (seg1 || seg2) - { - int i; - if ((!seg1 && seg2) || (seg1 && !seg2)) - return 0; - if (seg1->type != seg2->type) - return 0; - if (seg1->length != seg2->length) - return 0; - for (i = 0; i < seg1->length; i++) - if (seg1->as[i] != seg2->as[i]) - return 0; - seg1 = seg1->next; - seg2 = seg2->next; - } - return 1; +int aspath_cmp(const void *arg1, const void *arg2) +{ + const struct assegment *seg1 = ((const struct aspath *)arg1)->segments; + const struct assegment *seg2 = ((const struct aspath *)arg2)->segments; + + while (seg1 || seg2) { + int i; + if ((!seg1 && seg2) || (seg1 && !seg2)) + return 0; + if (seg1->type != seg2->type) + return 0; + if (seg1->length != seg2->length) + return 0; + for (i = 0; i < seg1->length; i++) + if (seg1->as[i] != seg2->as[i]) + return 0; + seg1 = seg1->next; + seg2 = seg2->next; + } + return 1; } /* AS path hash initialize. */ -void -aspath_init (void) +void aspath_init(void) { - ashash = hash_create_size (32768, aspath_key_make, aspath_cmp, NULL); + ashash = hash_create_size(32768, aspath_key_make, aspath_cmp, NULL); } -void -aspath_finish (void) +void aspath_finish(void) { - hash_clean (ashash, (void (*)(void *))aspath_free); - hash_free (ashash); - ashash = NULL; - - if (snmp_stream) - stream_free (snmp_stream); + hash_clean(ashash, (void (*)(void *))aspath_free); + hash_free(ashash); + ashash = NULL; + + if (snmp_stream) + stream_free(snmp_stream); } /* return and as path value */ -const char * -aspath_print (struct aspath *as) +const char *aspath_print(struct aspath *as) { - return (as ? as->str : NULL); + return (as ? as->str : NULL); } /* Printing functions */ /* Feed the AS_PATH to the vty; the suffix string follows it only in case * AS_PATH wasn't empty. */ -void -aspath_print_vty (struct vty *vty, const char *format, struct aspath *as, const char * suffix) +void aspath_print_vty(struct vty *vty, const char *format, struct aspath *as, + const char *suffix) { - assert (format); - vty_out (vty, format, as->str); - if (as->str_len && strlen (suffix)) - vty_out (vty, "%s", suffix); + assert(format); + vty_out(vty, format, as->str); + if (as->str_len && strlen(suffix)) + vty_out(vty, "%s", suffix); } -static void -aspath_show_all_iterator (struct hash_backet *backet, struct vty *vty) +static void aspath_show_all_iterator(struct hash_backet *backet, + struct vty *vty) { - struct aspath *as; + struct aspath *as; - as = (struct aspath *) backet->data; + as = (struct aspath *)backet->data; - vty_out (vty, "[%p:%u] (%ld) ", (void *)backet, backet->key, as->refcnt); - vty_out (vty, "%s\n", as->str); + vty_out(vty, "[%p:%u] (%ld) ", (void *)backet, backet->key, as->refcnt); + vty_out(vty, "%s\n", as->str); } /* Print all aspath and hash information. This function is used from `show [ip] bgp paths' command. */ -void -aspath_print_all_vty (struct vty *vty) +void aspath_print_all_vty(struct vty *vty) { - hash_iterate (ashash, - (void (*) (struct hash_backet *, void *)) - aspath_show_all_iterator, - vty); + hash_iterate(ashash, (void (*)(struct hash_backet *, + void *))aspath_show_all_iterator, + vty); } diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h index abf4c6ccf..f085cf3cb 100644 --- a/bgpd/bgp_aspath.h +++ b/bgpd/bgp_aspath.h @@ -43,87 +43,89 @@ /* Transition 16Bit AS as defined by IANA */ #define BGP_AS_TRANS 23456U -#define BGP_AS_IS_PRIVATE(ASN) \ - (((ASN) >= BGP_PRIVATE_AS_MIN && (ASN) <= BGP_PRIVATE_AS_MAX) || \ - ((ASN) >= BGP_PRIVATE_AS4_MIN && (ASN) <= BGP_PRIVATE_AS4_MAX)) +#define BGP_AS_IS_PRIVATE(ASN) \ + (((ASN) >= BGP_PRIVATE_AS_MIN && (ASN) <= BGP_PRIVATE_AS_MAX) \ + || ((ASN) >= BGP_PRIVATE_AS4_MIN && (ASN) <= BGP_PRIVATE_AS4_MAX)) /* AS_PATH segment data in abstracted form, no limit is placed on length */ -struct assegment -{ - struct assegment *next; - as_t *as; - u_short length; - u_char type; +struct assegment { + struct assegment *next; + as_t *as; + u_short length; + u_char type; }; /* AS path may be include some AsSegments. */ -struct aspath -{ - /* Reference count to this aspath. */ - unsigned long refcnt; - - /* segment data */ - struct assegment *segments; - - /* AS path as a json object */ - json_object *json; - - /* String expression of AS path. This string is used by vty output - and AS path regular expression match. */ - char *str; - unsigned short str_len; +struct aspath { + /* Reference count to this aspath. */ + unsigned long refcnt; + + /* segment data */ + struct assegment *segments; + + /* AS path as a json object */ + json_object *json; + + /* String expression of AS path. This string is used by vty output + and AS path regular expression match. */ + char *str; + unsigned short str_len; }; #define ASPATH_STR_DEFAULT_LEN 32 /* Prototypes. */ -extern void aspath_init (void); -extern void aspath_finish (void); -extern struct aspath *aspath_parse (struct stream *, size_t, int); -extern struct aspath *aspath_dup (struct aspath *); -extern struct aspath *aspath_aggregate (struct aspath *, struct aspath *); -extern struct aspath *aspath_prepend (struct aspath *, struct aspath *); -extern struct aspath *aspath_filter_exclude (struct aspath *, struct aspath *); -extern struct aspath *aspath_add_seq_n (struct aspath *, as_t, unsigned); -extern struct aspath *aspath_add_seq (struct aspath *, as_t); -extern struct aspath *aspath_add_confed_seq (struct aspath *, as_t); -extern int aspath_cmp (const void *, const void *); -extern int aspath_cmp_left (const struct aspath *, const struct aspath *); -extern int aspath_cmp_left_confed (const struct aspath *, const struct aspath *); -extern struct aspath *aspath_delete_confed_seq (struct aspath *); -extern struct aspath *aspath_empty (void); -extern struct aspath *aspath_empty_get (void); -extern struct aspath *aspath_str2aspath (const char *); -extern void aspath_free (struct aspath *); -extern struct aspath *aspath_intern (struct aspath *); -extern void aspath_unintern (struct aspath **); -extern const char *aspath_print (struct aspath *); -extern void aspath_print_vty (struct vty *, const char *, struct aspath *, const char *); -extern void aspath_print_all_vty (struct vty *); -extern unsigned int aspath_key_make (void *); -extern unsigned int aspath_get_first_as (struct aspath *); -extern unsigned int aspath_get_last_as (struct aspath *); -extern int aspath_loop_check (struct aspath *, as_t); -extern int aspath_private_as_check (struct aspath *); -extern int aspath_single_asn_check (struct aspath *, as_t asn); -extern struct aspath *aspath_replace_specific_asn (struct aspath *aspath, as_t target_asn, as_t our_asn); -extern struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn); -extern struct aspath *aspath_remove_private_asns (struct aspath *aspath); -extern int aspath_firstas_check (struct aspath *, as_t); -extern int aspath_confed_check (struct aspath *); -extern int aspath_left_confed_check (struct aspath *); -extern unsigned long aspath_count (void); -extern unsigned int aspath_count_hops (const struct aspath *); -extern unsigned int aspath_count_confeds (struct aspath *); -extern unsigned int aspath_size (struct aspath *); -extern as_t aspath_highest (struct aspath *); -extern as_t aspath_leftmost (struct aspath *); -extern size_t aspath_put (struct stream *, struct aspath *, int); - -extern struct aspath *aspath_reconcile_as4 (struct aspath *, struct aspath *); -extern unsigned int aspath_has_as4 (struct aspath *); +extern void aspath_init(void); +extern void aspath_finish(void); +extern struct aspath *aspath_parse(struct stream *, size_t, int); +extern struct aspath *aspath_dup(struct aspath *); +extern struct aspath *aspath_aggregate(struct aspath *, struct aspath *); +extern struct aspath *aspath_prepend(struct aspath *, struct aspath *); +extern struct aspath *aspath_filter_exclude(struct aspath *, struct aspath *); +extern struct aspath *aspath_add_seq_n(struct aspath *, as_t, unsigned); +extern struct aspath *aspath_add_seq(struct aspath *, as_t); +extern struct aspath *aspath_add_confed_seq(struct aspath *, as_t); +extern int aspath_cmp(const void *, const void *); +extern int aspath_cmp_left(const struct aspath *, const struct aspath *); +extern int aspath_cmp_left_confed(const struct aspath *, const struct aspath *); +extern struct aspath *aspath_delete_confed_seq(struct aspath *); +extern struct aspath *aspath_empty(void); +extern struct aspath *aspath_empty_get(void); +extern struct aspath *aspath_str2aspath(const char *); +extern void aspath_free(struct aspath *); +extern struct aspath *aspath_intern(struct aspath *); +extern void aspath_unintern(struct aspath **); +extern const char *aspath_print(struct aspath *); +extern void aspath_print_vty(struct vty *, const char *, struct aspath *, + const char *); +extern void aspath_print_all_vty(struct vty *); +extern unsigned int aspath_key_make(void *); +extern unsigned int aspath_get_first_as(struct aspath *); +extern unsigned int aspath_get_last_as(struct aspath *); +extern int aspath_loop_check(struct aspath *, as_t); +extern int aspath_private_as_check(struct aspath *); +extern int aspath_single_asn_check(struct aspath *, as_t asn); +extern struct aspath *aspath_replace_specific_asn(struct aspath *aspath, + as_t target_asn, + as_t our_asn); +extern struct aspath *aspath_replace_private_asns(struct aspath *aspath, + as_t asn); +extern struct aspath *aspath_remove_private_asns(struct aspath *aspath); +extern int aspath_firstas_check(struct aspath *, as_t); +extern int aspath_confed_check(struct aspath *); +extern int aspath_left_confed_check(struct aspath *); +extern unsigned long aspath_count(void); +extern unsigned int aspath_count_hops(const struct aspath *); +extern unsigned int aspath_count_confeds(struct aspath *); +extern unsigned int aspath_size(struct aspath *); +extern as_t aspath_highest(struct aspath *); +extern as_t aspath_leftmost(struct aspath *); +extern size_t aspath_put(struct stream *, struct aspath *, int); + +extern struct aspath *aspath_reconcile_as4(struct aspath *, struct aspath *); +extern unsigned int aspath_has_as4(struct aspath *); /* For SNMP BGP4PATHATTRASPATHSEGMENT, might be useful for debug */ -extern u_char *aspath_snmp_pathseg (struct aspath *, size_t *); +extern u_char *aspath_snmp_pathseg(struct aspath *, size_t *); #endif /* _QUAGGA_BGP_ASPATH_H */ diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index a22a7a5b4..79d215f1b 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -46,185 +46,169 @@ #include "bgpd/bgp_updgrp.h" #include "bgpd/bgp_encap_types.h" #if ENABLE_BGP_VNC -# include "bgpd/rfapi/bgp_rfapi_cfg.h" -# include "bgp_encap_types.h" -# include "bgp_vnc_types.h" +#include "bgpd/rfapi/bgp_rfapi_cfg.h" +#include "bgp_encap_types.h" +#include "bgp_vnc_types.h" #endif #include "bgp_encap_types.h" #include "bgp_evpn.h" /* Attribute strings for logging. */ -static const struct message attr_str [] = -{ - { BGP_ATTR_ORIGIN, "ORIGIN" }, - { BGP_ATTR_AS_PATH, "AS_PATH" }, - { BGP_ATTR_NEXT_HOP, "NEXT_HOP" }, - { BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" }, - { BGP_ATTR_LOCAL_PREF, "LOCAL_PREF" }, - { BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" }, - { BGP_ATTR_AGGREGATOR, "AGGREGATOR" }, - { BGP_ATTR_COMMUNITIES, "COMMUNITY" }, - { BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID" }, - { BGP_ATTR_CLUSTER_LIST, "CLUSTER_LIST" }, - { BGP_ATTR_DPA, "DPA" }, - { BGP_ATTR_ADVERTISER, "ADVERTISER"} , - { BGP_ATTR_RCID_PATH, "RCID_PATH" }, - { BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI" }, - { BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" }, - { BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES" }, - { BGP_ATTR_AS4_PATH, "AS4_PATH" }, - { BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR" }, - { BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT" }, - { BGP_ATTR_ENCAP, "ENCAP" }, +static const struct message attr_str[] = { + {BGP_ATTR_ORIGIN, "ORIGIN"}, + {BGP_ATTR_AS_PATH, "AS_PATH"}, + {BGP_ATTR_NEXT_HOP, "NEXT_HOP"}, + {BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC"}, + {BGP_ATTR_LOCAL_PREF, "LOCAL_PREF"}, + {BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE"}, + {BGP_ATTR_AGGREGATOR, "AGGREGATOR"}, + {BGP_ATTR_COMMUNITIES, "COMMUNITY"}, + {BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID"}, + {BGP_ATTR_CLUSTER_LIST, "CLUSTER_LIST"}, + {BGP_ATTR_DPA, "DPA"}, + {BGP_ATTR_ADVERTISER, "ADVERTISER"}, + {BGP_ATTR_RCID_PATH, "RCID_PATH"}, + {BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI"}, + {BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI"}, + {BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES"}, + {BGP_ATTR_AS4_PATH, "AS4_PATH"}, + {BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR"}, + {BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT"}, + {BGP_ATTR_ENCAP, "ENCAP"}, #if ENABLE_BGP_VNC - { BGP_ATTR_VNC, "VNC" }, + {BGP_ATTR_VNC, "VNC"}, #endif - { BGP_ATTR_LARGE_COMMUNITIES, "LARGE_COMMUNITY" }, - { BGP_ATTR_PREFIX_SID, "PREFIX_SID" }, - { 0 } -}; + {BGP_ATTR_LARGE_COMMUNITIES, "LARGE_COMMUNITY"}, + {BGP_ATTR_PREFIX_SID, "PREFIX_SID"}, + {0}}; static const struct message attr_flag_str[] = -{ - { BGP_ATTR_FLAG_OPTIONAL, "Optional" }, - { BGP_ATTR_FLAG_TRANS, "Transitive" }, - { BGP_ATTR_FLAG_PARTIAL, "Partial" }, - /* bgp_attr_flags_diagnose() relies on this bit being last in this list */ - { BGP_ATTR_FLAG_EXTLEN, "Extended Length" }, - { 0 } -}; + { + {BGP_ATTR_FLAG_OPTIONAL, "Optional"}, + {BGP_ATTR_FLAG_TRANS, "Transitive"}, + {BGP_ATTR_FLAG_PARTIAL, "Partial"}, + /* bgp_attr_flags_diagnose() relies on this bit being last in + this list */ + {BGP_ATTR_FLAG_EXTLEN, "Extended Length"}, + {0}}; static struct hash *cluster_hash; -static void * -cluster_hash_alloc (void *p) +static void *cluster_hash_alloc(void *p) { - const struct cluster_list *val = (const struct cluster_list *) p; - struct cluster_list *cluster; + const struct cluster_list *val = (const struct cluster_list *)p; + struct cluster_list *cluster; - cluster = XMALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list)); - cluster->length = val->length; + cluster = XMALLOC(MTYPE_CLUSTER, sizeof(struct cluster_list)); + cluster->length = val->length; - if (cluster->length) - { - cluster->list = XMALLOC (MTYPE_CLUSTER_VAL, val->length); - memcpy (cluster->list, val->list, val->length); - } - else - cluster->list = NULL; + if (cluster->length) { + cluster->list = XMALLOC(MTYPE_CLUSTER_VAL, val->length); + memcpy(cluster->list, val->list, val->length); + } else + cluster->list = NULL; - cluster->refcnt = 0; + cluster->refcnt = 0; - return cluster; + return cluster; } /* Cluster list related functions. */ -static struct cluster_list * -cluster_parse (struct in_addr * pnt, int length) +static struct cluster_list *cluster_parse(struct in_addr *pnt, int length) { - struct cluster_list tmp; - struct cluster_list *cluster; + struct cluster_list tmp; + struct cluster_list *cluster; - tmp.length = length; - tmp.list = pnt; + tmp.length = length; + tmp.list = pnt; - cluster = hash_get (cluster_hash, &tmp, cluster_hash_alloc); - cluster->refcnt++; - return cluster; + cluster = hash_get(cluster_hash, &tmp, cluster_hash_alloc); + cluster->refcnt++; + return cluster; } -int -cluster_loop_check (struct cluster_list *cluster, struct in_addr originator) +int cluster_loop_check(struct cluster_list *cluster, struct in_addr originator) { - int i; - - for (i = 0; i < cluster->length / 4; i++) - if (cluster->list[i].s_addr == originator.s_addr) - return 1; - return 0; + int i; + + for (i = 0; i < cluster->length / 4; i++) + if (cluster->list[i].s_addr == originator.s_addr) + return 1; + return 0; } -static unsigned int -cluster_hash_key_make (void *p) +static unsigned int cluster_hash_key_make(void *p) { - const struct cluster_list *cluster = p; + const struct cluster_list *cluster = p; - return jhash(cluster->list, cluster->length, 0); + return jhash(cluster->list, cluster->length, 0); } -static int -cluster_hash_cmp (const void *p1, const void *p2) +static int cluster_hash_cmp(const void *p1, const void *p2) { - const struct cluster_list * cluster1 = p1; - const struct cluster_list * cluster2 = p2; + const struct cluster_list *cluster1 = p1; + const struct cluster_list *cluster2 = p2; - return (cluster1->length == cluster2->length && - memcmp (cluster1->list, cluster2->list, cluster1->length) == 0); + return (cluster1->length == cluster2->length + && memcmp(cluster1->list, cluster2->list, cluster1->length) + == 0); } -static void -cluster_free (struct cluster_list *cluster) +static void cluster_free(struct cluster_list *cluster) { - if (cluster->list) - XFREE (MTYPE_CLUSTER_VAL, cluster->list); - XFREE (MTYPE_CLUSTER, cluster); + if (cluster->list) + XFREE(MTYPE_CLUSTER_VAL, cluster->list); + XFREE(MTYPE_CLUSTER, cluster); } -static struct cluster_list * -cluster_dup (struct cluster_list *cluster) +static struct cluster_list *cluster_dup(struct cluster_list *cluster) { - struct cluster_list *new; + struct cluster_list *new; + + new = XCALLOC(MTYPE_CLUSTER, sizeof(struct cluster_list)); + new->length = cluster->length; - new = XCALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list)); - new->length = cluster->length; + if (cluster->length) { + new->list = XMALLOC(MTYPE_CLUSTER_VAL, cluster->length); + memcpy(new->list, cluster->list, cluster->length); + } else + new->list = NULL; - if (cluster->length) - { - new->list = XMALLOC (MTYPE_CLUSTER_VAL, cluster->length); - memcpy (new->list, cluster->list, cluster->length); - } - else - new->list = NULL; - - return new; + return new; } -static struct cluster_list * -cluster_intern (struct cluster_list *cluster) +static struct cluster_list *cluster_intern(struct cluster_list *cluster) { - struct cluster_list *find; + struct cluster_list *find; - find = hash_get (cluster_hash, cluster, cluster_hash_alloc); - find->refcnt++; + find = hash_get(cluster_hash, cluster, cluster_hash_alloc); + find->refcnt++; - return find; + return find; } -void -cluster_unintern (struct cluster_list *cluster) +void cluster_unintern(struct cluster_list *cluster) { - if (cluster->refcnt) - cluster->refcnt--; + if (cluster->refcnt) + cluster->refcnt--; - if (cluster->refcnt == 0) - { - hash_release (cluster_hash, cluster); - cluster_free (cluster); - } + if (cluster->refcnt == 0) { + hash_release(cluster_hash, cluster); + cluster_free(cluster); + } } -static void -cluster_init (void) +static void cluster_init(void) { - cluster_hash = hash_create (cluster_hash_key_make, cluster_hash_cmp, NULL); + cluster_hash = + hash_create(cluster_hash_key_make, cluster_hash_cmp, NULL); } -static void -cluster_finish (void) +static void cluster_finish(void) { - hash_clean (cluster_hash, (void (*)(void *))cluster_free); - hash_free (cluster_hash); - cluster_hash = NULL; + hash_clean(cluster_hash, (void (*)(void *))cluster_free); + hash_free(cluster_hash); + cluster_hash = NULL; } static struct hash *encap_hash = NULL; @@ -232,56 +216,53 @@ static struct hash *encap_hash = NULL; static struct hash *vnc_hash = NULL; #endif -struct bgp_attr_encap_subtlv * -encap_tlv_dup(struct bgp_attr_encap_subtlv *orig) +struct bgp_attr_encap_subtlv *encap_tlv_dup(struct bgp_attr_encap_subtlv *orig) { - struct bgp_attr_encap_subtlv *new; - struct bgp_attr_encap_subtlv *tail; - struct bgp_attr_encap_subtlv *p; + struct bgp_attr_encap_subtlv *new; + struct bgp_attr_encap_subtlv *tail; + struct bgp_attr_encap_subtlv *p; - for (p = orig, tail = new = NULL; p; p = p->next) { - int size = sizeof(struct bgp_attr_encap_subtlv) - 1 + p->length; - if (tail) { - tail->next = XCALLOC(MTYPE_ENCAP_TLV, size); - tail = tail->next; - } else { - tail = new = XCALLOC(MTYPE_ENCAP_TLV, size); + for (p = orig, tail = new = NULL; p; p = p->next) { + int size = sizeof(struct bgp_attr_encap_subtlv) - 1 + p->length; + if (tail) { + tail->next = XCALLOC(MTYPE_ENCAP_TLV, size); + tail = tail->next; + } else { + tail = new = XCALLOC(MTYPE_ENCAP_TLV, size); + } + assert(tail); + memcpy(tail, p, size); + tail->next = NULL; } - assert(tail); - memcpy(tail, p, size); - tail->next = NULL; - } - return new; + return new; } -static void -encap_free(struct bgp_attr_encap_subtlv *p) +static void encap_free(struct bgp_attr_encap_subtlv *p) { - struct bgp_attr_encap_subtlv *next; - while (p) { - next = p->next; - p->next = NULL; - XFREE(MTYPE_ENCAP_TLV, p); - p = next; - } + struct bgp_attr_encap_subtlv *next; + while (p) { + next = p->next; + p->next = NULL; + XFREE(MTYPE_ENCAP_TLV, p); + p = next; + } } -void -bgp_attr_flush_encap(struct attr *attr) +void bgp_attr_flush_encap(struct attr *attr) { - if (!attr) - return; + if (!attr) + return; - if (attr->encap_subtlvs) { - encap_free(attr->encap_subtlvs); - attr->encap_subtlvs = NULL; - } + if (attr->encap_subtlvs) { + encap_free(attr->encap_subtlvs); + attr->encap_subtlvs = NULL; + } #if ENABLE_BGP_VNC - if (attr->vnc_subtlvs) { - encap_free(attr->vnc_subtlvs); - attr->vnc_subtlvs = NULL; - } + if (attr->vnc_subtlvs) { + encap_free(attr->vnc_subtlvs); + attr->vnc_subtlvs = NULL; + } #endif } @@ -293,240 +274,220 @@ bgp_attr_flush_encap(struct attr *attr) * * This algorithm could be made faster if needed */ -static int -encap_same(struct bgp_attr_encap_subtlv *h1, struct bgp_attr_encap_subtlv *h2) +static int encap_same(struct bgp_attr_encap_subtlv *h1, + struct bgp_attr_encap_subtlv *h2) { - struct bgp_attr_encap_subtlv *p; - struct bgp_attr_encap_subtlv *q; + struct bgp_attr_encap_subtlv *p; + struct bgp_attr_encap_subtlv *q; - if (h1 == h2) - return 1; - if (h1 == NULL || h2 == NULL) - return 0; + if (h1 == h2) + return 1; + if (h1 == NULL || h2 == NULL) + return 0; - for (p = h1; p; p = p->next) { - for (q = h2; q; q = q->next) { - if ((p->type == q->type) && - (p->length == q->length) && - !memcmp(p->value, q->value, p->length)) { + for (p = h1; p; p = p->next) { + for (q = h2; q; q = q->next) { + if ((p->type == q->type) && (p->length == q->length) + && !memcmp(p->value, q->value, p->length)) { - break; - } + break; + } + } + if (!q) + return 0; } - if (!q) - return 0; - } - for (p = h2; p; p = p->next) { - for (q = h1; q; q = q->next) { - if ((p->type == q->type) && - (p->length == q->length) && - !memcmp(p->value, q->value, p->length)) { + for (p = h2; p; p = p->next) { + for (q = h1; q; q = q->next) { + if ((p->type == q->type) && (p->length == q->length) + && !memcmp(p->value, q->value, p->length)) { - break; - } + break; + } + } + if (!q) + return 0; } - if (!q) - return 0; - } - return 1; + return 1; } -static void * -encap_hash_alloc (void *p) +static void *encap_hash_alloc(void *p) { - /* Encap structure is already allocated. */ - return p; + /* Encap structure is already allocated. */ + return p; } -typedef enum -{ - ENCAP_SUBTLV_TYPE, +typedef enum { + ENCAP_SUBTLV_TYPE, #if ENABLE_BGP_VNC - VNC_SUBTLV_TYPE + VNC_SUBTLV_TYPE #endif } encap_subtlv_type; static struct bgp_attr_encap_subtlv * -encap_intern (struct bgp_attr_encap_subtlv *encap, encap_subtlv_type type) +encap_intern(struct bgp_attr_encap_subtlv *encap, encap_subtlv_type type) { - struct bgp_attr_encap_subtlv *find; - struct hash *hash = encap_hash; + struct bgp_attr_encap_subtlv *find; + struct hash *hash = encap_hash; #if ENABLE_BGP_VNC - if (type == VNC_SUBTLV_TYPE) - hash = vnc_hash; + if (type == VNC_SUBTLV_TYPE) + hash = vnc_hash; #endif - find = hash_get (hash, encap, encap_hash_alloc); - if (find != encap) - encap_free (encap); - find->refcnt++; + find = hash_get(hash, encap, encap_hash_alloc); + if (find != encap) + encap_free(encap); + find->refcnt++; - return find; + return find; } -static void -encap_unintern (struct bgp_attr_encap_subtlv **encapp, encap_subtlv_type type) +static void encap_unintern(struct bgp_attr_encap_subtlv **encapp, + encap_subtlv_type type) { - struct bgp_attr_encap_subtlv *encap = *encapp; - if (encap->refcnt) - encap->refcnt--; + struct bgp_attr_encap_subtlv *encap = *encapp; + if (encap->refcnt) + encap->refcnt--; - if (encap->refcnt == 0) - { - struct hash *hash = encap_hash; + if (encap->refcnt == 0) { + struct hash *hash = encap_hash; #if ENABLE_BGP_VNC - if (type == VNC_SUBTLV_TYPE) - hash = vnc_hash; + if (type == VNC_SUBTLV_TYPE) + hash = vnc_hash; #endif - hash_release (hash, encap); - encap_free (encap); - *encapp = NULL; - } + hash_release(hash, encap); + encap_free(encap); + *encapp = NULL; + } } -static unsigned int -encap_hash_key_make (void *p) +static unsigned int encap_hash_key_make(void *p) { - const struct bgp_attr_encap_subtlv * encap = p; + const struct bgp_attr_encap_subtlv *encap = p; - return jhash(encap->value, encap->length, 0); + return jhash(encap->value, encap->length, 0); } -static int -encap_hash_cmp (const void *p1, const void *p2) +static int encap_hash_cmp(const void *p1, const void *p2) { - return encap_same((struct bgp_attr_encap_subtlv *)p1, - (struct bgp_attr_encap_subtlv *)p2); + return encap_same((struct bgp_attr_encap_subtlv *)p1, + (struct bgp_attr_encap_subtlv *)p2); } -static void -encap_init (void) +static void encap_init(void) { - encap_hash = hash_create (encap_hash_key_make, encap_hash_cmp, NULL); + encap_hash = hash_create(encap_hash_key_make, encap_hash_cmp, NULL); #if ENABLE_BGP_VNC - vnc_hash = hash_create (encap_hash_key_make, encap_hash_cmp, NULL); + vnc_hash = hash_create(encap_hash_key_make, encap_hash_cmp, NULL); #endif } -static void -encap_finish (void) +static void encap_finish(void) { - hash_clean (encap_hash, (void (*)(void *))encap_free); - hash_free (encap_hash); - encap_hash = NULL; + hash_clean(encap_hash, (void (*)(void *))encap_free); + hash_free(encap_hash); + encap_hash = NULL; #if ENABLE_BGP_VNC - hash_clean (vnc_hash, (void (*)(void *))encap_free); - hash_free (vnc_hash); - vnc_hash = NULL; + hash_clean(vnc_hash, (void (*)(void *))encap_free); + hash_free(vnc_hash); + vnc_hash = NULL; #endif } -static bool -overlay_index_same(const struct attr *a1, const struct attr *a2) +static bool overlay_index_same(const struct attr *a1, const struct attr *a2) { - if(!a1 && a2) - return false; - if(!a2 && a1) - return false; - if(!a1 && !a2) - return true; - return !memcmp(&(a1->evpn_overlay), &(a2->evpn_overlay), sizeof(struct overlay_index)); + if (!a1 && a2) + return false; + if (!a2 && a1) + return false; + if (!a1 && !a2) + return true; + return !memcmp(&(a1->evpn_overlay), &(a2->evpn_overlay), + sizeof(struct overlay_index)); } /* Unknown transit attribute. */ static struct hash *transit_hash; -static void -transit_free (struct transit *transit) +static void transit_free(struct transit *transit) { - if (transit->val) - XFREE (MTYPE_TRANSIT_VAL, transit->val); - XFREE (MTYPE_TRANSIT, transit); + if (transit->val) + XFREE(MTYPE_TRANSIT_VAL, transit->val); + XFREE(MTYPE_TRANSIT, transit); } -static struct transit * -transit_dup (struct transit *transit) +static struct transit *transit_dup(struct transit *transit) { - struct transit *new; + struct transit *new; - new = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit)); - new->length = transit->length; - if (new->length) - { - new->val = XMALLOC (MTYPE_TRANSIT_VAL, transit->length); - memcpy (new->val, transit->val, transit->length); - } - else - new->val = NULL; + new = XCALLOC(MTYPE_TRANSIT, sizeof(struct transit)); + new->length = transit->length; + if (new->length) { + new->val = XMALLOC(MTYPE_TRANSIT_VAL, transit->length); + memcpy(new->val, transit->val, transit->length); + } else + new->val = NULL; - return new; + return new; } -static void * -transit_hash_alloc (void *p) +static void *transit_hash_alloc(void *p) { - /* Transit structure is already allocated. */ - return p; + /* Transit structure is already allocated. */ + return p; } -static struct transit * -transit_intern (struct transit *transit) +static struct transit *transit_intern(struct transit *transit) { - struct transit *find; + struct transit *find; - find = hash_get (transit_hash, transit, transit_hash_alloc); - if (find != transit) - transit_free (transit); - find->refcnt++; + find = hash_get(transit_hash, transit, transit_hash_alloc); + if (find != transit) + transit_free(transit); + find->refcnt++; - return find; + return find; } -void -transit_unintern (struct transit *transit) +void transit_unintern(struct transit *transit) { - if (transit->refcnt) - transit->refcnt--; + if (transit->refcnt) + transit->refcnt--; - if (transit->refcnt == 0) - { - hash_release (transit_hash, transit); - transit_free (transit); - } + if (transit->refcnt == 0) { + hash_release(transit_hash, transit); + transit_free(transit); + } } -static unsigned int -transit_hash_key_make (void *p) +static unsigned int transit_hash_key_make(void *p) { - const struct transit * transit = p; + const struct transit *transit = p; - return jhash(transit->val, transit->length, 0); + return jhash(transit->val, transit->length, 0); } -static int -transit_hash_cmp (const void *p1, const void *p2) +static int transit_hash_cmp(const void *p1, const void *p2) { - const struct transit * transit1 = p1; - const struct transit * transit2 = p2; + const struct transit *transit1 = p1; + const struct transit *transit2 = p2; - return (transit1->length == transit2->length && - memcmp (transit1->val, transit2->val, transit1->length) == 0); + return (transit1->length == transit2->length + && memcmp(transit1->val, transit2->val, transit1->length) == 0); } -static void -transit_init (void) +static void transit_init(void) { - transit_hash = hash_create (transit_hash_key_make, transit_hash_cmp, NULL); + transit_hash = + hash_create(transit_hash_key_make, transit_hash_cmp, NULL); } -static void -transit_finish (void) +static void transit_finish(void) { - hash_clean (transit_hash, (void (*)(void *))transit_free); - hash_free (transit_hash); - transit_hash = NULL; + hash_clean(transit_hash, (void (*)(void *))transit_free); + hash_free(transit_hash); + transit_hash = NULL; } /* Attribute hash routines. */ @@ -536,295 +497,277 @@ static struct hash *attrhash; * Though, not so shallow that it doesn't copy the contents * of the attr_extra pointed to by 'extra' */ -void -bgp_attr_dup (struct attr *new, struct attr *orig) +void bgp_attr_dup(struct attr *new, struct attr *orig) { - *new = *orig; + *new = *orig; } -void -bgp_attr_deep_dup (struct attr *new, struct attr *orig) +void bgp_attr_deep_dup(struct attr *new, struct attr *orig) { - if (orig->aspath) - new->aspath = aspath_dup(orig->aspath); + if (orig->aspath) + new->aspath = aspath_dup(orig->aspath); - if (orig->community) - new->community = community_dup(orig->community); + if (orig->community) + new->community = community_dup(orig->community); - if (orig->ecommunity) - new->ecommunity = ecommunity_dup(orig->ecommunity); - if (orig->cluster) - new->cluster = cluster_dup(orig->cluster); - if (orig->transit) - new->transit = transit_dup(orig->transit); - if (orig->encap_subtlvs) - new->encap_subtlvs = encap_tlv_dup(orig->encap_subtlvs); + if (orig->ecommunity) + new->ecommunity = ecommunity_dup(orig->ecommunity); + if (orig->cluster) + new->cluster = cluster_dup(orig->cluster); + if (orig->transit) + new->transit = transit_dup(orig->transit); + if (orig->encap_subtlvs) + new->encap_subtlvs = encap_tlv_dup(orig->encap_subtlvs); #if ENABLE_BGP_VNC - if (orig->vnc_subtlvs) - new->vnc_subtlvs = encap_tlv_dup(orig->vnc_subtlvs); + if (orig->vnc_subtlvs) + new->vnc_subtlvs = encap_tlv_dup(orig->vnc_subtlvs); #endif } -void -bgp_attr_deep_free (struct attr *attr) +void bgp_attr_deep_free(struct attr *attr) { - if (attr->aspath) - aspath_free(attr->aspath); + if (attr->aspath) + aspath_free(attr->aspath); - if (attr->community) - community_free(attr->community); + if (attr->community) + community_free(attr->community); - if (attr->ecommunity) - ecommunity_free(&attr->ecommunity); - if (attr->cluster) - cluster_free(attr->cluster); - if (attr->transit) - transit_free(attr->transit); - if (attr->encap_subtlvs) - encap_free(attr->encap_subtlvs); + if (attr->ecommunity) + ecommunity_free(&attr->ecommunity); + if (attr->cluster) + cluster_free(attr->cluster); + if (attr->transit) + transit_free(attr->transit); + if (attr->encap_subtlvs) + encap_free(attr->encap_subtlvs); #if ENABLE_BGP_VNC - if (attr->vnc_subtlvs) - encap_free(attr->vnc_subtlvs); + if (attr->vnc_subtlvs) + encap_free(attr->vnc_subtlvs); #endif } -unsigned long int -attr_count (void) +unsigned long int attr_count(void) { - return attrhash->count; + return attrhash->count; } -unsigned long int -attr_unknown_count (void) +unsigned long int attr_unknown_count(void) { - return transit_hash->count; + return transit_hash->count; } -unsigned int -attrhash_key_make (void *p) +unsigned int attrhash_key_make(void *p) { - const struct attr *attr = (struct attr *) p; - uint32_t key = 0; + const struct attr *attr = (struct attr *)p; + uint32_t key = 0; #define MIX(val) key = jhash_1word(val, key) - MIX(attr->origin); - MIX(attr->nexthop.s_addr); - MIX(attr->med); - MIX(attr->local_pref); - - key += attr->origin; - key += attr->nexthop.s_addr; - key += attr->med; - key += attr->local_pref; - - MIX(attr->aggregator_as); - MIX(attr->aggregator_addr.s_addr); - MIX(attr->weight); - MIX(attr->mp_nexthop_global_in.s_addr); - MIX(attr->originator_id.s_addr); - MIX(attr->tag); - MIX(attr->label); - MIX(attr->label_index); - - if (attr->aspath) - MIX(aspath_key_make (attr->aspath)); - if (attr->community) - MIX(community_hash_make (attr->community)); - - if (attr->lcommunity) - MIX(lcommunity_hash_make (attr->lcommunity)); - if (attr->ecommunity) - MIX(ecommunity_hash_make (attr->ecommunity)); - if (attr->cluster) - MIX(cluster_hash_key_make (attr->cluster)); - if (attr->transit) - MIX(transit_hash_key_make (attr->transit)); - if (attr->encap_subtlvs) - MIX(encap_hash_key_make (attr->encap_subtlvs)); + MIX(attr->origin); + MIX(attr->nexthop.s_addr); + MIX(attr->med); + MIX(attr->local_pref); + + key += attr->origin; + key += attr->nexthop.s_addr; + key += attr->med; + key += attr->local_pref; + + MIX(attr->aggregator_as); + MIX(attr->aggregator_addr.s_addr); + MIX(attr->weight); + MIX(attr->mp_nexthop_global_in.s_addr); + MIX(attr->originator_id.s_addr); + MIX(attr->tag); + MIX(attr->label); + MIX(attr->label_index); + + if (attr->aspath) + MIX(aspath_key_make(attr->aspath)); + if (attr->community) + MIX(community_hash_make(attr->community)); + + if (attr->lcommunity) + MIX(lcommunity_hash_make(attr->lcommunity)); + if (attr->ecommunity) + MIX(ecommunity_hash_make(attr->ecommunity)); + if (attr->cluster) + MIX(cluster_hash_key_make(attr->cluster)); + if (attr->transit) + MIX(transit_hash_key_make(attr->transit)); + if (attr->encap_subtlvs) + MIX(encap_hash_key_make(attr->encap_subtlvs)); #if ENABLE_BGP_VNC - if (attr->vnc_subtlvs) - MIX(encap_hash_key_make (attr->vnc_subtlvs)); + if (attr->vnc_subtlvs) + MIX(encap_hash_key_make(attr->vnc_subtlvs)); #endif - MIX(attr->mp_nexthop_len); - key = jhash(attr->mp_nexthop_global.s6_addr, IPV6_MAX_BYTELEN, key); - key = jhash(attr->mp_nexthop_local.s6_addr, IPV6_MAX_BYTELEN, key); - - return key; -} - -int -attrhash_cmp (const void *p1, const void *p2) -{ - const struct attr * attr1 = p1; - const struct attr * attr2 = p2; - - if (attr1->flag == attr2->flag - && attr1->origin == attr2->origin - && attr1->nexthop.s_addr == attr2->nexthop.s_addr - && attr1->aspath == attr2->aspath - && attr1->community == attr2->community - && attr1->med == attr2->med - && attr1->local_pref == attr2->local_pref - && attr1->rmap_change_flags == attr2->rmap_change_flags) - { - if (attr1->aggregator_as == attr2->aggregator_as - && attr1->aggregator_addr.s_addr == attr2->aggregator_addr.s_addr - && attr1->weight == attr2->weight - && attr1->tag == attr2->tag - && attr1->label_index == attr2->label_index - && attr1->mp_nexthop_len == attr2->mp_nexthop_len - && IPV6_ADDR_SAME (&attr1->mp_nexthop_global, &attr2->mp_nexthop_global) - && IPV6_ADDR_SAME (&attr1->mp_nexthop_local, &attr2->mp_nexthop_local) - && IPV4_ADDR_SAME (&attr1->mp_nexthop_global_in, &attr2->mp_nexthop_global_in) - && attr1->ecommunity == attr2->ecommunity - && attr1->lcommunity == attr2->lcommunity - && attr1->cluster == attr2->cluster - && attr1->transit == attr2->transit - && (attr1->encap_tunneltype == attr2->encap_tunneltype) - && encap_same(attr1->encap_subtlvs, attr2->encap_subtlvs) + MIX(attr->mp_nexthop_len); + key = jhash(attr->mp_nexthop_global.s6_addr, IPV6_MAX_BYTELEN, key); + key = jhash(attr->mp_nexthop_local.s6_addr, IPV6_MAX_BYTELEN, key); + + return key; +} + +int attrhash_cmp(const void *p1, const void *p2) +{ + const struct attr *attr1 = p1; + const struct attr *attr2 = p2; + + if (attr1->flag == attr2->flag && attr1->origin == attr2->origin + && attr1->nexthop.s_addr == attr2->nexthop.s_addr + && attr1->aspath == attr2->aspath + && attr1->community == attr2->community && attr1->med == attr2->med + && attr1->local_pref == attr2->local_pref + && attr1->rmap_change_flags == attr2->rmap_change_flags) { + if (attr1->aggregator_as == attr2->aggregator_as + && attr1->aggregator_addr.s_addr + == attr2->aggregator_addr.s_addr + && attr1->weight == attr2->weight + && attr1->tag == attr2->tag + && attr1->label_index == attr2->label_index + && attr1->mp_nexthop_len == attr2->mp_nexthop_len + && IPV6_ADDR_SAME(&attr1->mp_nexthop_global, + &attr2->mp_nexthop_global) + && IPV6_ADDR_SAME(&attr1->mp_nexthop_local, + &attr2->mp_nexthop_local) + && IPV4_ADDR_SAME(&attr1->mp_nexthop_global_in, + &attr2->mp_nexthop_global_in) + && attr1->ecommunity == attr2->ecommunity + && attr1->lcommunity == attr2->lcommunity + && attr1->cluster == attr2->cluster + && attr1->transit == attr2->transit + && (attr1->encap_tunneltype == attr2->encap_tunneltype) + && encap_same(attr1->encap_subtlvs, attr2->encap_subtlvs) #if ENABLE_BGP_VNC - && encap_same(attr1->vnc_subtlvs, attr2->vnc_subtlvs) + && encap_same(attr1->vnc_subtlvs, attr2->vnc_subtlvs) #endif - && IPV4_ADDR_SAME (&attr1->originator_id, &attr2->originator_id) - && overlay_index_same(attr1, attr2)) - return 1; - } + && IPV4_ADDR_SAME(&attr1->originator_id, + &attr2->originator_id) + && overlay_index_same(attr1, attr2)) + return 1; + } - return 0; + return 0; } -static void -attrhash_init (void) +static void attrhash_init(void) { - attrhash = hash_create (attrhash_key_make, attrhash_cmp, "BGP Attributes"); + attrhash = + hash_create(attrhash_key_make, attrhash_cmp, "BGP Attributes"); } /* * special for hash_clean below */ -static void -attr_vfree (void *attr) +static void attr_vfree(void *attr) { - XFREE (MTYPE_ATTR, attr); + XFREE(MTYPE_ATTR, attr); } -static void -attrhash_finish (void) +static void attrhash_finish(void) { - hash_clean(attrhash, attr_vfree); - hash_free (attrhash); - attrhash = NULL; + hash_clean(attrhash, attr_vfree); + hash_free(attrhash); + attrhash = NULL; } -static void -attr_show_all_iterator (struct hash_backet *backet, struct vty *vty) +static void attr_show_all_iterator(struct hash_backet *backet, struct vty *vty) { - struct attr *attr = backet->data; + struct attr *attr = backet->data; - vty_out (vty, "attr[%ld] nexthop %s\n", attr->refcnt, - inet_ntoa(attr->nexthop)); + vty_out(vty, "attr[%ld] nexthop %s\n", attr->refcnt, + inet_ntoa(attr->nexthop)); } -void -attr_show_all (struct vty *vty) +void attr_show_all(struct vty *vty) { - hash_iterate (attrhash, - (void (*)(struct hash_backet *, void *)) - attr_show_all_iterator, - vty); + hash_iterate(attrhash, (void (*)(struct hash_backet *, + void *))attr_show_all_iterator, + vty); } -static void * -bgp_attr_hash_alloc (void *p) +static void *bgp_attr_hash_alloc(void *p) { - struct attr * val = (struct attr *) p; - struct attr *attr; + struct attr *val = (struct attr *)p; + struct attr *attr; - attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr)); - *attr = *val; - if (val->encap_subtlvs) { - val->encap_subtlvs = NULL; - } + attr = XMALLOC(MTYPE_ATTR, sizeof(struct attr)); + *attr = *val; + if (val->encap_subtlvs) { + val->encap_subtlvs = NULL; + } #if ENABLE_BGP_VNC - if (val->vnc_subtlvs) { - val->vnc_subtlvs = NULL; - } + if (val->vnc_subtlvs) { + val->vnc_subtlvs = NULL; + } #endif - attr->refcnt = 0; - return attr; + attr->refcnt = 0; + return attr; } /* Internet argument attribute. */ -struct attr * -bgp_attr_intern (struct attr *attr) -{ - struct attr *find; - - /* Intern referenced strucutre. */ - if (attr->aspath) - { - if (! attr->aspath->refcnt) - attr->aspath = aspath_intern (attr->aspath); - else - attr->aspath->refcnt++; - } - if (attr->community) - { - if (! attr->community->refcnt) - attr->community = community_intern (attr->community); - else - attr->community->refcnt++; - } - - if (attr->ecommunity) - { - if (! attr->ecommunity->refcnt) - attr->ecommunity = ecommunity_intern (attr->ecommunity); - else - attr->ecommunity->refcnt++; - } - if (attr->lcommunity) - { - if (! attr->lcommunity->refcnt) - attr->lcommunity = lcommunity_intern (attr->lcommunity); - else - attr->lcommunity->refcnt++; - } - if (attr->cluster) - { - if (! attr->cluster->refcnt) - attr->cluster = cluster_intern (attr->cluster); - else - attr->cluster->refcnt++; - } - if (attr->transit) - { - if (! attr->transit->refcnt) - attr->transit = transit_intern (attr->transit); - else - attr->transit->refcnt++; - } - if (attr->encap_subtlvs) - { - if (! attr->encap_subtlvs->refcnt) - attr->encap_subtlvs = encap_intern (attr->encap_subtlvs, ENCAP_SUBTLV_TYPE); - else - attr->encap_subtlvs->refcnt++; - } +struct attr *bgp_attr_intern(struct attr *attr) +{ + struct attr *find; + + /* Intern referenced strucutre. */ + if (attr->aspath) { + if (!attr->aspath->refcnt) + attr->aspath = aspath_intern(attr->aspath); + else + attr->aspath->refcnt++; + } + if (attr->community) { + if (!attr->community->refcnt) + attr->community = community_intern(attr->community); + else + attr->community->refcnt++; + } + + if (attr->ecommunity) { + if (!attr->ecommunity->refcnt) + attr->ecommunity = ecommunity_intern(attr->ecommunity); + else + attr->ecommunity->refcnt++; + } + if (attr->lcommunity) { + if (!attr->lcommunity->refcnt) + attr->lcommunity = lcommunity_intern(attr->lcommunity); + else + attr->lcommunity->refcnt++; + } + if (attr->cluster) { + if (!attr->cluster->refcnt) + attr->cluster = cluster_intern(attr->cluster); + else + attr->cluster->refcnt++; + } + if (attr->transit) { + if (!attr->transit->refcnt) + attr->transit = transit_intern(attr->transit); + else + attr->transit->refcnt++; + } + if (attr->encap_subtlvs) { + if (!attr->encap_subtlvs->refcnt) + attr->encap_subtlvs = encap_intern(attr->encap_subtlvs, + ENCAP_SUBTLV_TYPE); + else + attr->encap_subtlvs->refcnt++; + } #if ENABLE_BGP_VNC - if (attr->vnc_subtlvs) - { - if (! attr->vnc_subtlvs->refcnt) - attr->vnc_subtlvs = encap_intern (attr->vnc_subtlvs, VNC_SUBTLV_TYPE); - else - attr->vnc_subtlvs->refcnt++; - } + if (attr->vnc_subtlvs) { + if (!attr->vnc_subtlvs->refcnt) + attr->vnc_subtlvs = encap_intern(attr->vnc_subtlvs, + VNC_SUBTLV_TYPE); + else + attr->vnc_subtlvs->refcnt++; + } #endif - - find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc); - find->refcnt++; - return find; + find = (struct attr *)hash_get(attrhash, attr, bgp_attr_hash_alloc); + find->refcnt++; + + return find; } /** @@ -836,211 +779,197 @@ bgp_attr_intern (struct attr *attr) * after calling bgp_attr_refcount(). That would release the * reference and could result in a free() of the attr object. */ -struct attr * -bgp_attr_refcount (struct attr *attr) +struct attr *bgp_attr_refcount(struct attr *attr) { - /* Intern referenced strucutre. */ - if (attr->aspath) - attr->aspath->refcnt++; + /* Intern referenced strucutre. */ + if (attr->aspath) + attr->aspath->refcnt++; - if (attr->community) - attr->community->refcnt++; + if (attr->community) + attr->community->refcnt++; - if (attr->ecommunity) - attr->ecommunity->refcnt++; + if (attr->ecommunity) + attr->ecommunity->refcnt++; - if (attr->cluster) - attr->cluster->refcnt++; + if (attr->cluster) + attr->cluster->refcnt++; - if (attr->transit) - attr->transit->refcnt++; + if (attr->transit) + attr->transit->refcnt++; - if (attr->encap_subtlvs) - attr->encap_subtlvs->refcnt++; + if (attr->encap_subtlvs) + attr->encap_subtlvs->refcnt++; #if ENABLE_BGP_VNC - if (attr->vnc_subtlvs) - attr->vnc_subtlvs->refcnt++; + if (attr->vnc_subtlvs) + attr->vnc_subtlvs->refcnt++; #endif - attr->refcnt++; - return attr; + attr->refcnt++; + return attr; } /* Make network statement's attribute. */ -struct attr * -bgp_attr_default_set (struct attr *attr, u_char origin) +struct attr *bgp_attr_default_set(struct attr *attr, u_char origin) { - memset (attr, 0, sizeof (struct attr)); - - attr->origin = origin; - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN); - attr->aspath = aspath_empty (); - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH); - attr->weight = BGP_ATTR_DEFAULT_WEIGHT; - attr->tag = 0; - attr->label_index = BGP_INVALID_LABEL_INDEX; - attr->label = MPLS_INVALID_LABEL; - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP); - attr->mp_nexthop_len = IPV6_MAX_BYTELEN; + memset(attr, 0, sizeof(struct attr)); - return attr; + attr->origin = origin; + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN); + attr->aspath = aspath_empty(); + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH); + attr->weight = BGP_ATTR_DEFAULT_WEIGHT; + attr->tag = 0; + attr->label_index = BGP_INVALID_LABEL_INDEX; + attr->label = MPLS_INVALID_LABEL; + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); + attr->mp_nexthop_len = IPV6_MAX_BYTELEN; + + return attr; } /* Create the attributes for an aggregate */ -struct attr * -bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin, - struct aspath *aspath, - struct community *community, int as_set, - u_char atomic_aggregate) -{ - struct attr attr; - struct attr *new; - - memset (&attr, 0, sizeof (struct attr)); - - /* Origin attribute. */ - attr.origin = origin; - attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN); - - /* AS path attribute. */ - if (aspath) - attr.aspath = aspath_intern (aspath); - else - attr.aspath = aspath_empty (); - attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH); - - /* Next hop attribute. */ - attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP); - - if (community) - { - attr.community = community; - attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES); - } - - attr.label_index = BGP_INVALID_LABEL_INDEX; - attr.label = MPLS_INVALID_LABEL; - attr.weight = BGP_ATTR_DEFAULT_WEIGHT; - attr.mp_nexthop_len = IPV6_MAX_BYTELEN; - if (! as_set || atomic_aggregate) - attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE); - attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR); - if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION)) - attr.aggregator_as = bgp->confed_id; - else - attr.aggregator_as = bgp->as; - attr.aggregator_addr = bgp->router_id; - attr.label_index = BGP_INVALID_LABEL_INDEX; - attr.label = MPLS_INVALID_LABEL; - - new = bgp_attr_intern (&attr); - - aspath_unintern (&new->aspath); - return new; +struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, u_char origin, + struct aspath *aspath, + struct community *community, int as_set, + u_char atomic_aggregate) +{ + struct attr attr; + struct attr *new; + + memset(&attr, 0, sizeof(struct attr)); + + /* Origin attribute. */ + attr.origin = origin; + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN); + + /* AS path attribute. */ + if (aspath) + attr.aspath = aspath_intern(aspath); + else + attr.aspath = aspath_empty(); + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH); + + /* Next hop attribute. */ + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); + + if (community) { + attr.community = community; + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES); + } + + attr.label_index = BGP_INVALID_LABEL_INDEX; + attr.label = MPLS_INVALID_LABEL; + attr.weight = BGP_ATTR_DEFAULT_WEIGHT; + attr.mp_nexthop_len = IPV6_MAX_BYTELEN; + if (!as_set || atomic_aggregate) + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE); + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR); + if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) + attr.aggregator_as = bgp->confed_id; + else + attr.aggregator_as = bgp->as; + attr.aggregator_addr = bgp->router_id; + attr.label_index = BGP_INVALID_LABEL_INDEX; + attr.label = MPLS_INVALID_LABEL; + + new = bgp_attr_intern(&attr); + + aspath_unintern(&new->aspath); + return new; } /* Unintern just the sub-components of the attr, but not the attr */ -void -bgp_attr_unintern_sub (struct attr *attr) -{ - /* aspath refcount shoud be decrement. */ - if (attr->aspath) - aspath_unintern (&attr->aspath); - UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)); - - if (attr->community) - community_unintern (&attr->community); - UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)); - - if (attr->ecommunity) - ecommunity_unintern (&attr->ecommunity); - UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)); - - if (attr->lcommunity) - lcommunity_unintern (&attr->lcommunity); - UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES)); - - if (attr->cluster) - cluster_unintern (attr->cluster); - UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST)); - - if (attr->transit) - transit_unintern (attr->transit); - - if (attr->encap_subtlvs) - encap_unintern (&attr->encap_subtlvs, ENCAP_SUBTLV_TYPE); +void bgp_attr_unintern_sub(struct attr *attr) +{ + /* aspath refcount shoud be decrement. */ + if (attr->aspath) + aspath_unintern(&attr->aspath); + UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)); + + if (attr->community) + community_unintern(&attr->community); + UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)); + + if (attr->ecommunity) + ecommunity_unintern(&attr->ecommunity); + UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)); + + if (attr->lcommunity) + lcommunity_unintern(&attr->lcommunity); + UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)); + + if (attr->cluster) + cluster_unintern(attr->cluster); + UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)); + + if (attr->transit) + transit_unintern(attr->transit); + + if (attr->encap_subtlvs) + encap_unintern(&attr->encap_subtlvs, ENCAP_SUBTLV_TYPE); #if ENABLE_BGP_VNC - if (attr->vnc_subtlvs) - encap_unintern (&attr->vnc_subtlvs, VNC_SUBTLV_TYPE); + if (attr->vnc_subtlvs) + encap_unintern(&attr->vnc_subtlvs, VNC_SUBTLV_TYPE); #endif } /* Free bgp attribute and aspath. */ -void -bgp_attr_unintern (struct attr **pattr) -{ - struct attr *attr = *pattr; - struct attr *ret; - struct attr tmp; - - /* Decrement attribute reference. */ - attr->refcnt--; - - tmp = *attr; - - /* If reference becomes zero then free attribute object. */ - if (attr->refcnt == 0) - { - ret = hash_release (attrhash, attr); - assert (ret != NULL); - XFREE (MTYPE_ATTR, attr); - *pattr = NULL; - } - - bgp_attr_unintern_sub (&tmp); -} - -void -bgp_attr_flush (struct attr *attr) -{ - if (attr->aspath && ! attr->aspath->refcnt) - { - aspath_free (attr->aspath); - attr->aspath = NULL; - } - if (attr->community && ! attr->community->refcnt) - { - community_free (attr->community); - attr->community = NULL; - } - - if (attr->ecommunity && ! attr->ecommunity->refcnt) - ecommunity_free (&attr->ecommunity); - if (attr->lcommunity && ! attr->lcommunity->refcnt) - lcommunity_free (&attr->lcommunity); - if (attr->cluster && ! attr->cluster->refcnt) - { - cluster_free (attr->cluster); - attr->cluster = NULL; - } - if (attr->transit && ! attr->transit->refcnt) - { - transit_free (attr->transit); - attr->transit = NULL; - } - if (attr->encap_subtlvs && ! attr->encap_subtlvs->refcnt) - { - encap_free(attr->encap_subtlvs); - attr->encap_subtlvs = NULL; - } +void bgp_attr_unintern(struct attr **pattr) +{ + struct attr *attr = *pattr; + struct attr *ret; + struct attr tmp; + + /* Decrement attribute reference. */ + attr->refcnt--; + + tmp = *attr; + + /* If reference becomes zero then free attribute object. */ + if (attr->refcnt == 0) { + ret = hash_release(attrhash, attr); + assert(ret != NULL); + XFREE(MTYPE_ATTR, attr); + *pattr = NULL; + } + + bgp_attr_unintern_sub(&tmp); +} + +void bgp_attr_flush(struct attr *attr) +{ + if (attr->aspath && !attr->aspath->refcnt) { + aspath_free(attr->aspath); + attr->aspath = NULL; + } + if (attr->community && !attr->community->refcnt) { + community_free(attr->community); + attr->community = NULL; + } + + if (attr->ecommunity && !attr->ecommunity->refcnt) + ecommunity_free(&attr->ecommunity); + if (attr->lcommunity && !attr->lcommunity->refcnt) + lcommunity_free(&attr->lcommunity); + if (attr->cluster && !attr->cluster->refcnt) { + cluster_free(attr->cluster); + attr->cluster = NULL; + } + if (attr->transit && !attr->transit->refcnt) { + transit_free(attr->transit); + attr->transit = NULL; + } + if (attr->encap_subtlvs && !attr->encap_subtlvs->refcnt) { + encap_free(attr->encap_subtlvs); + attr->encap_subtlvs = NULL; + } #if ENABLE_BGP_VNC - if (attr->vnc_subtlvs && ! attr->vnc_subtlvs->refcnt) - { - encap_free(attr->vnc_subtlvs); - attr->vnc_subtlvs = NULL; - } + if (attr->vnc_subtlvs && !attr->vnc_subtlvs->refcnt) { + encap_free(attr->vnc_subtlvs); + attr->vnc_subtlvs = NULL; + } #endif } @@ -1050,74 +979,72 @@ bgp_attr_flush (struct attr *attr) * introduced by the sending neighbour. */ static bgp_attr_parse_ret_t -bgp_attr_malformed (struct bgp_attr_parser_args *args, u_char subcode, - bgp_size_t length) -{ - struct peer *const peer = args->peer; - const u_int8_t flags = args->flags; - /* startp and length must be special-cased, as whether or not to - * send the attribute data with the NOTIFY depends on the error, - * the caller therefore signals this with the seperate length argument - */ - u_char *notify_datap = (length > 0 ? args->startp : NULL); - - /* Only relax error handling for eBGP peers */ - if (peer->sort != BGP_PEER_EBGP) - { - bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode, - notify_datap, length); - return BGP_ATTR_PARSE_ERROR; - - } - - /* Adjust the stream getp to the end of the attribute, in case we can - * still proceed but the caller hasn't read all the attribute. - */ - stream_set_getp (BGP_INPUT (peer), - (args->startp - STREAM_DATA (BGP_INPUT (peer))) - + args->total); - - switch (args->type) { - /* where an attribute is relatively inconsequential, e.g. it does not - * affect route selection, and can be safely ignored, then any such - * attributes which are malformed should just be ignored and the route - * processed as normal. - */ - case BGP_ATTR_AS4_AGGREGATOR: - case BGP_ATTR_AGGREGATOR: - case BGP_ATTR_ATOMIC_AGGREGATE: - return BGP_ATTR_PARSE_PROCEED; - - /* Core attributes, particularly ones which may influence route - * selection, should always cause session resets - */ - case BGP_ATTR_ORIGIN: - case BGP_ATTR_AS_PATH: - case BGP_ATTR_NEXT_HOP: - case BGP_ATTR_MULTI_EXIT_DISC: - case BGP_ATTR_LOCAL_PREF: - case BGP_ATTR_COMMUNITIES: - case BGP_ATTR_ORIGINATOR_ID: - case BGP_ATTR_CLUSTER_LIST: - case BGP_ATTR_MP_REACH_NLRI: - case BGP_ATTR_MP_UNREACH_NLRI: - case BGP_ATTR_EXT_COMMUNITIES: - bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode, - notify_datap, length); - return BGP_ATTR_PARSE_ERROR; - } - - /* Partial optional attributes that are malformed should not cause - * the whole session to be reset. Instead treat it as a withdrawal - * of the routes, if possible. - */ - if (CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS) - && CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL) - && CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL)) - return BGP_ATTR_PARSE_WITHDRAW; - - /* default to reset */ - return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; +bgp_attr_malformed(struct bgp_attr_parser_args *args, u_char subcode, + bgp_size_t length) +{ + struct peer *const peer = args->peer; + const u_int8_t flags = args->flags; + /* startp and length must be special-cased, as whether or not to + * send the attribute data with the NOTIFY depends on the error, + * the caller therefore signals this with the seperate length argument + */ + u_char *notify_datap = (length > 0 ? args->startp : NULL); + + /* Only relax error handling for eBGP peers */ + if (peer->sort != BGP_PEER_EBGP) { + bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR, subcode, + notify_datap, length); + return BGP_ATTR_PARSE_ERROR; + } + + /* Adjust the stream getp to the end of the attribute, in case we can + * still proceed but the caller hasn't read all the attribute. + */ + stream_set_getp(BGP_INPUT(peer), + (args->startp - STREAM_DATA(BGP_INPUT(peer))) + + args->total); + + switch (args->type) { + /* where an attribute is relatively inconsequential, e.g. it does not + * affect route selection, and can be safely ignored, then any such + * attributes which are malformed should just be ignored and the route + * processed as normal. + */ + case BGP_ATTR_AS4_AGGREGATOR: + case BGP_ATTR_AGGREGATOR: + case BGP_ATTR_ATOMIC_AGGREGATE: + return BGP_ATTR_PARSE_PROCEED; + + /* Core attributes, particularly ones which may influence route + * selection, should always cause session resets + */ + case BGP_ATTR_ORIGIN: + case BGP_ATTR_AS_PATH: + case BGP_ATTR_NEXT_HOP: + case BGP_ATTR_MULTI_EXIT_DISC: + case BGP_ATTR_LOCAL_PREF: + case BGP_ATTR_COMMUNITIES: + case BGP_ATTR_ORIGINATOR_ID: + case BGP_ATTR_CLUSTER_LIST: + case BGP_ATTR_MP_REACH_NLRI: + case BGP_ATTR_MP_UNREACH_NLRI: + case BGP_ATTR_EXT_COMMUNITIES: + bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR, subcode, + notify_datap, length); + return BGP_ATTR_PARSE_ERROR; + } + + /* Partial optional attributes that are malformed should not cause + * the whole session to be reset. Instead treat it as a withdrawal + * of the routes, if possible. + */ + if (CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS) + && CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL) + && CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL)) + return BGP_ATTR_PARSE_WITHDRAW; + + /* default to reset */ + return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; } /* Find out what is wrong with the path attribute flag bits and log the error. @@ -1126,2504 +1053,2456 @@ bgp_attr_malformed (struct bgp_attr_parser_args *args, u_char subcode, being diagnosed is defined by RFC as either a "well-known" or an "optional, non-transitive" attribute. */ static void -bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args, - u_int8_t desired_flags /* how RFC says it must be */ -) -{ - u_char seen = 0, i; - u_char real_flags = args->flags; - const u_int8_t attr_code = args->type; - - desired_flags &= ~BGP_ATTR_FLAG_EXTLEN; - real_flags &= ~BGP_ATTR_FLAG_EXTLEN; - for (i = 0; i <= 2; i++) /* O,T,P, but not E */ - if - ( - CHECK_FLAG (desired_flags, attr_flag_str[i].key) != - CHECK_FLAG (real_flags, attr_flag_str[i].key) - ) - { - zlog_err ("%s attribute must%s be flagged as \"%s\"", - lookup_msg(attr_str, attr_code, NULL), - CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not", - attr_flag_str[i].str); - seen = 1; - } - if (!seen) - { - zlog_debug ("Strange, %s called for attr %s, but no problem found with flags" - " (real flags 0x%x, desired 0x%x)", - __func__, lookup_msg(attr_str, attr_code, NULL), - real_flags, desired_flags); - } +bgp_attr_flags_diagnose(struct bgp_attr_parser_args *args, + u_int8_t desired_flags /* how RFC says it must be */ + ) +{ + u_char seen = 0, i; + u_char real_flags = args->flags; + const u_int8_t attr_code = args->type; + + desired_flags &= ~BGP_ATTR_FLAG_EXTLEN; + real_flags &= ~BGP_ATTR_FLAG_EXTLEN; + for (i = 0; i <= 2; i++) /* O,T,P, but not E */ + if (CHECK_FLAG(desired_flags, attr_flag_str[i].key) + != CHECK_FLAG(real_flags, attr_flag_str[i].key)) { + zlog_err("%s attribute must%s be flagged as \"%s\"", + lookup_msg(attr_str, attr_code, NULL), + CHECK_FLAG(desired_flags, attr_flag_str[i].key) + ? "" + : " not", + attr_flag_str[i].str); + seen = 1; + } + if (!seen) { + zlog_debug( + "Strange, %s called for attr %s, but no problem found with flags" + " (real flags 0x%x, desired 0x%x)", + __func__, lookup_msg(attr_str, attr_code, NULL), + real_flags, desired_flags); + } } /* Required flags for attributes. EXTLEN will be masked off when testing, * as will PARTIAL for optional+transitive attributes. */ -const u_int8_t attr_flags_values [] = { - [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS, - [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS, - [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS, - [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL, - [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS, - [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS, - [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL, - [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL, - [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL, - [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL, - [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL, - [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL, - [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, - [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, - [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, - [BGP_ATTR_LARGE_COMMUNITIES]= BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, - [BGP_ATTR_PREFIX_SID] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, +const u_int8_t attr_flags_values[] = { + [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS, + [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS, + [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS, + [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL, + [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS, + [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS, + [BGP_ATTR_AGGREGATOR] = + BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL, + [BGP_ATTR_COMMUNITIES] = + BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL, + [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL, + [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL, + [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL, + [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL, + [BGP_ATTR_EXT_COMMUNITIES] = + BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, + [BGP_ATTR_AS4_PATH] = + BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, + [BGP_ATTR_AS4_AGGREGATOR] = + BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, + [BGP_ATTR_LARGE_COMMUNITIES] = + BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, + [BGP_ATTR_PREFIX_SID] = + BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, }; static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1; -static int -bgp_attr_flag_invalid (struct bgp_attr_parser_args *args) -{ - u_int8_t mask = BGP_ATTR_FLAG_EXTLEN; - const u_int8_t flags = args->flags; - const u_int8_t attr_code = args->type; - - /* there may be attributes we don't know about */ - if (attr_code > attr_flags_values_max) - return 0; - if (attr_flags_values[attr_code] == 0) - return 0; - - /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to - * 1." - */ - if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags) - && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags)) - { - zlog_err ("%s well-known attributes must have transitive flag set (%x)", - lookup_msg(attr_str, attr_code, NULL), flags); - return 1; - } - - /* "For well-known attributes and for optional non-transitive attributes, - * the Partial bit MUST be set to 0." - */ - if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL)) - { - if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)) - { - zlog_err ("%s well-known attribute " - "must NOT have the partial flag set (%x)", - lookup_msg(attr_str, attr_code, NULL), flags); - return 1; - } - if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL) - && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)) - { - zlog_err ("%s optional + transitive attribute " - "must NOT have the partial flag set (%x)", - lookup_msg(attr_str, attr_code, NULL), flags); - return 1; - } - } - - /* Optional transitive attributes may go through speakers that don't - * reocgnise them and set the Partial bit. - */ - if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL) - && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)) - SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL); - - if ((flags & ~mask) - == attr_flags_values[attr_code]) - return 0; - - bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]); - return 1; +static int bgp_attr_flag_invalid(struct bgp_attr_parser_args *args) +{ + u_int8_t mask = BGP_ATTR_FLAG_EXTLEN; + const u_int8_t flags = args->flags; + const u_int8_t attr_code = args->type; + + /* there may be attributes we don't know about */ + if (attr_code > attr_flags_values_max) + return 0; + if (attr_flags_values[attr_code] == 0) + return 0; + + /* RFC4271, "For well-known attributes, the Transitive bit MUST be set + * to + * 1." + */ + if (!CHECK_FLAG(BGP_ATTR_FLAG_OPTIONAL, flags) + && !CHECK_FLAG(BGP_ATTR_FLAG_TRANS, flags)) { + zlog_err( + "%s well-known attributes must have transitive flag set (%x)", + lookup_msg(attr_str, attr_code, NULL), flags); + return 1; + } + + /* "For well-known attributes and for optional non-transitive + * attributes, + * the Partial bit MUST be set to 0." + */ + if (CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL)) { + if (!CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)) { + zlog_err( + "%s well-known attribute " + "must NOT have the partial flag set (%x)", + lookup_msg(attr_str, attr_code, NULL), flags); + return 1; + } + if (CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL) + && !CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS)) { + zlog_err( + "%s optional + transitive attribute " + "must NOT have the partial flag set (%x)", + lookup_msg(attr_str, attr_code, NULL), flags); + return 1; + } + } + + /* Optional transitive attributes may go through speakers that don't + * reocgnise them and set the Partial bit. + */ + if (CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL) + && CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS)) + SET_FLAG(mask, BGP_ATTR_FLAG_PARTIAL); + + if ((flags & ~mask) == attr_flags_values[attr_code]) + return 0; + + bgp_attr_flags_diagnose(args, attr_flags_values[attr_code]); + return 1; } /* Get origin attribute of the update message. */ -static bgp_attr_parse_ret_t -bgp_attr_origin (struct bgp_attr_parser_args *args) -{ - struct peer *const peer = args->peer; - struct attr *const attr = args->attr; - const bgp_size_t length = args->length; - - /* If any recognized attribute has Attribute Length that conflicts - with the expected length (based on the attribute type code), then - the Error Subcode is set to Attribute Length Error. The Data - field contains the erroneous attribute (type, length and - value). */ - if (length != 1) - { - zlog_err ("Origin attribute length is not one %d", length); - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, - args->total); - } - - /* Fetch origin attribute. */ - attr->origin = stream_getc (BGP_INPUT (peer)); - - /* If the ORIGIN attribute has an undefined value, then the Error - Subcode is set to Invalid Origin Attribute. The Data field - contains the unrecognized attribute (type, length and value). */ - if ((attr->origin != BGP_ORIGIN_IGP) - && (attr->origin != BGP_ORIGIN_EGP) - && (attr->origin != BGP_ORIGIN_INCOMPLETE)) - { - zlog_err ("Origin attribute value is invalid %d", attr->origin); - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_INVAL_ORIGIN, - args->total); - } - - /* Set oring attribute flag. */ - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN); - - return 0; +static bgp_attr_parse_ret_t bgp_attr_origin(struct bgp_attr_parser_args *args) +{ + struct peer *const peer = args->peer; + struct attr *const attr = args->attr; + const bgp_size_t length = args->length; + + /* If any recognized attribute has Attribute Length that conflicts + with the expected length (based on the attribute type code), then + the Error Subcode is set to Attribute Length Error. The Data + field contains the erroneous attribute (type, length and + value). */ + if (length != 1) { + zlog_err("Origin attribute length is not one %d", length); + return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, + args->total); + } + + /* Fetch origin attribute. */ + attr->origin = stream_getc(BGP_INPUT(peer)); + + /* If the ORIGIN attribute has an undefined value, then the Error + Subcode is set to Invalid Origin Attribute. The Data field + contains the unrecognized attribute (type, length and value). */ + if ((attr->origin != BGP_ORIGIN_IGP) && (attr->origin != BGP_ORIGIN_EGP) + && (attr->origin != BGP_ORIGIN_INCOMPLETE)) { + zlog_err("Origin attribute value is invalid %d", attr->origin); + return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_INVAL_ORIGIN, + args->total); + } + + /* Set oring attribute flag. */ + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN); + + return 0; } /* Parse AS path information. This function is wrapper of aspath_parse. */ -static int -bgp_attr_aspath (struct bgp_attr_parser_args *args) -{ - struct attr *const attr = args->attr; - struct peer *const peer = args->peer; - const bgp_size_t length = args->length; - - /* - * peer with AS4 => will get 4Byte ASnums - * otherwise, will get 16 Bit - */ - attr->aspath = aspath_parse (peer->ibuf, length, - CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)); +static int bgp_attr_aspath(struct bgp_attr_parser_args *args) +{ + struct attr *const attr = args->attr; + struct peer *const peer = args->peer; + const bgp_size_t length = args->length; + + /* + * peer with AS4 => will get 4Byte ASnums + * otherwise, will get 16 Bit + */ + attr->aspath = aspath_parse(peer->ibuf, length, + CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)); + + /* In case of IBGP, length will be zero. */ + if (!attr->aspath) { + zlog_err("Malformed AS path from %s, length is %d", peer->host, + length); + return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, + 0); + } - /* In case of IBGP, length will be zero. */ - if (! attr->aspath) - { - zlog_err ("Malformed AS path from %s, length is %d", peer->host, length); - return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0); - } + /* Set aspath attribute flag. */ + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH); + + return BGP_ATTR_PARSE_PROCEED; +} + +static bgp_attr_parse_ret_t bgp_attr_aspath_check(struct peer *const peer, + struct attr *const attr) +{ + /* These checks were part of bgp_attr_aspath, but with + * as4 we should to check aspath things when + * aspath synthesizing with as4_path has already taken place. + * Otherwise we check ASPATH and use the synthesized thing, and that is + * not right. + * So do the checks later, i.e. here + */ + struct bgp *bgp = peer->bgp; + struct aspath *aspath; + + /* Confederation sanity check. */ + if ((peer->sort == BGP_PEER_CONFED + && !aspath_left_confed_check(attr->aspath)) + || (peer->sort == BGP_PEER_EBGP + && aspath_confed_check(attr->aspath))) { + zlog_err("Malformed AS path from %s", peer->host); + bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_MAL_AS_PATH); + return BGP_ATTR_PARSE_ERROR; + } - /* Set aspath attribute flag. */ - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH); + /* First AS check for EBGP. */ + if (bgp != NULL && bgp_flag_check(bgp, BGP_FLAG_ENFORCE_FIRST_AS)) { + if (peer->sort == BGP_PEER_EBGP + && !aspath_firstas_check(attr->aspath, peer->as)) { + zlog_err("%s incorrect first AS (must be %u)", + peer->host, peer->as); + bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_MAL_AS_PATH); + return BGP_ATTR_PARSE_ERROR; + } + } - return BGP_ATTR_PARSE_PROCEED; -} + /* local-as prepend */ + if (peer->change_local_as + && !CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)) { + aspath = aspath_dup(attr->aspath); + aspath = aspath_add_seq(aspath, peer->change_local_as); + aspath_unintern(&attr->aspath); + attr->aspath = aspath_intern(aspath); + } -static bgp_attr_parse_ret_t -bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr) -{ - /* These checks were part of bgp_attr_aspath, but with - * as4 we should to check aspath things when - * aspath synthesizing with as4_path has already taken place. - * Otherwise we check ASPATH and use the synthesized thing, and that is - * not right. - * So do the checks later, i.e. here - */ - struct bgp *bgp = peer->bgp; - struct aspath *aspath; - - /* Confederation sanity check. */ - if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) || - (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath))) - { - zlog_err ("Malformed AS path from %s", peer->host); - bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_MAL_AS_PATH); - return BGP_ATTR_PARSE_ERROR; - } - - /* First AS check for EBGP. */ - if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS)) - { - if (peer->sort == BGP_PEER_EBGP - && ! aspath_firstas_check (attr->aspath, peer->as)) - { - zlog_err ("%s incorrect first AS (must be %u)", peer->host, peer->as); - bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_MAL_AS_PATH); - return BGP_ATTR_PARSE_ERROR; - } - } - - /* local-as prepend */ - if (peer->change_local_as && - ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)) - { - aspath = aspath_dup (attr->aspath); - aspath = aspath_add_seq (aspath, peer->change_local_as); - aspath_unintern (&attr->aspath); - attr->aspath = aspath_intern (aspath); - } - - return BGP_ATTR_PARSE_PROCEED; + return BGP_ATTR_PARSE_PROCEED; } /* Parse AS4 path information. This function is another wrapper of aspath_parse. */ -static int -bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path) +static int bgp_attr_as4_path(struct bgp_attr_parser_args *args, + struct aspath **as4_path) { - struct peer *const peer = args->peer; - struct attr *const attr = args->attr; - const bgp_size_t length = args->length; - - *as4_path = aspath_parse (peer->ibuf, length, 1); + struct peer *const peer = args->peer; + struct attr *const attr = args->attr; + const bgp_size_t length = args->length; - /* In case of IBGP, length will be zero. */ - if (!*as4_path) - { - zlog_err ("Malformed AS4 path from %s, length is %d", peer->host, length); - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_MAL_AS_PATH, - 0); - } + *as4_path = aspath_parse(peer->ibuf, length, 1); - /* Set aspath attribute flag. */ - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH); + /* In case of IBGP, length will be zero. */ + if (!*as4_path) { + zlog_err("Malformed AS4 path from %s, length is %d", peer->host, + length); + return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, + 0); + } - return BGP_ATTR_PARSE_PROCEED; + /* Set aspath attribute flag. */ + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH); + + return BGP_ATTR_PARSE_PROCEED; } /* Nexthop attribute. */ -static bgp_attr_parse_ret_t -bgp_attr_nexthop (struct bgp_attr_parser_args *args) -{ - struct peer *const peer = args->peer; - struct attr *const attr = args->attr; - const bgp_size_t length = args->length; - - in_addr_t nexthop_h, nexthop_n; - - /* Check nexthop attribute length. */ - if (length != 4) - { - zlog_err ("Nexthop attribute length isn't four [%d]", length); - - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, - args->total); - } - - /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP - attribute must result in a NOTIFICATION message (this is implemented below). - At the same time, semantically incorrect NEXT_HOP is more likely to be just - logged locally (this is implemented somewhere else). The UPDATE message - gets ignored in any of these cases. */ - nexthop_n = stream_get_ipv4 (peer->ibuf); - nexthop_h = ntohl (nexthop_n); - if ((IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h)) - && !BGP_DEBUG (allow_martians, ALLOW_MARTIANS)) /* loopbacks may be used in testing */ - { - char buf[INET_ADDRSTRLEN]; - inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN); - zlog_err ("Martian nexthop %s", buf); - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP, - args->total); - } - - attr->nexthop.s_addr = nexthop_n; - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP); - - return BGP_ATTR_PARSE_PROCEED; +static bgp_attr_parse_ret_t bgp_attr_nexthop(struct bgp_attr_parser_args *args) +{ + struct peer *const peer = args->peer; + struct attr *const attr = args->attr; + const bgp_size_t length = args->length; + + in_addr_t nexthop_h, nexthop_n; + + /* Check nexthop attribute length. */ + if (length != 4) { + zlog_err("Nexthop attribute length isn't four [%d]", length); + + return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, + args->total); + } + + /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP + attribute must result in a NOTIFICATION message (this is implemented + below). + At the same time, semantically incorrect NEXT_HOP is more likely to + be just + logged locally (this is implemented somewhere else). The UPDATE + message + gets ignored in any of these cases. */ + nexthop_n = stream_get_ipv4(peer->ibuf); + nexthop_h = ntohl(nexthop_n); + if ((IPV4_NET0(nexthop_h) || IPV4_NET127(nexthop_h) + || IPV4_CLASS_DE(nexthop_h)) + && !BGP_DEBUG( + allow_martians, + ALLOW_MARTIANS)) /* loopbacks may be used in testing */ + { + char buf[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN); + zlog_err("Martian nexthop %s", buf); + return bgp_attr_malformed( + args, BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP, args->total); + } + + attr->nexthop.s_addr = nexthop_n; + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); + + return BGP_ATTR_PARSE_PROCEED; } /* MED atrribute. */ -static bgp_attr_parse_ret_t -bgp_attr_med (struct bgp_attr_parser_args *args) +static bgp_attr_parse_ret_t bgp_attr_med(struct bgp_attr_parser_args *args) { - struct peer *const peer = args->peer; - struct attr *const attr = args->attr; - const bgp_size_t length = args->length; - - /* Length check. */ - if (length != 4) - { - zlog_err ("MED attribute length isn't four [%d]", length); + struct peer *const peer = args->peer; + struct attr *const attr = args->attr; + const bgp_size_t length = args->length; - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, - args->total); - } + /* Length check. */ + if (length != 4) { + zlog_err("MED attribute length isn't four [%d]", length); - attr->med = stream_getl (peer->ibuf); + return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, + args->total); + } + + attr->med = stream_getl(peer->ibuf); - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); - return BGP_ATTR_PARSE_PROCEED; + return BGP_ATTR_PARSE_PROCEED; } /* Local preference attribute. */ static bgp_attr_parse_ret_t -bgp_attr_local_pref (struct bgp_attr_parser_args *args) -{ - struct peer *const peer = args->peer; - struct attr *const attr = args->attr; - const bgp_size_t length = args->length; - - /* Length check. */ - if (length != 4) - { - zlog_err ("LOCAL_PREF attribute length isn't 4 [%u]", length); - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, - args->total); - } - - /* If it is contained in an UPDATE message that is received from an - external peer, then this attribute MUST be ignored by the - receiving speaker. */ - if (peer->sort == BGP_PEER_EBGP) - { - stream_forward_getp (peer->ibuf, length); - return BGP_ATTR_PARSE_PROCEED; - } - - attr->local_pref = stream_getl (peer->ibuf); - - /* Set atomic aggregate flag. */ - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF); - - return BGP_ATTR_PARSE_PROCEED; +bgp_attr_local_pref(struct bgp_attr_parser_args *args) +{ + struct peer *const peer = args->peer; + struct attr *const attr = args->attr; + const bgp_size_t length = args->length; + + /* Length check. */ + if (length != 4) { + zlog_err("LOCAL_PREF attribute length isn't 4 [%u]", length); + return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, + args->total); + } + + /* If it is contained in an UPDATE message that is received from an + external peer, then this attribute MUST be ignored by the + receiving speaker. */ + if (peer->sort == BGP_PEER_EBGP) { + stream_forward_getp(peer->ibuf, length); + return BGP_ATTR_PARSE_PROCEED; + } + + attr->local_pref = stream_getl(peer->ibuf); + + /* Set atomic aggregate flag. */ + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF); + + return BGP_ATTR_PARSE_PROCEED; } /* Atomic aggregate. */ -static int -bgp_attr_atomic (struct bgp_attr_parser_args *args) +static int bgp_attr_atomic(struct bgp_attr_parser_args *args) { - struct attr *const attr = args->attr; - const bgp_size_t length = args->length; - - /* Length check. */ - if (length != 0) - { - zlog_err ("ATOMIC_AGGREGATE attribute length isn't 0 [%u]", length); - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, - args->total); - } + struct attr *const attr = args->attr; + const bgp_size_t length = args->length; + + /* Length check. */ + if (length != 0) { + zlog_err("ATOMIC_AGGREGATE attribute length isn't 0 [%u]", + length); + return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, + args->total); + } - /* Set atomic aggregate flag. */ - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE); + /* Set atomic aggregate flag. */ + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE); - return BGP_ATTR_PARSE_PROCEED; + return BGP_ATTR_PARSE_PROCEED; } /* Aggregator attribute */ -static int -bgp_attr_aggregator (struct bgp_attr_parser_args *args) -{ - struct peer *const peer = args->peer; - struct attr *const attr = args->attr; - const bgp_size_t length = args->length; - - int wantedlen = 6; - - /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */ - if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) - wantedlen = 8; - - if (length != wantedlen) - { - zlog_err ("AGGREGATOR attribute length isn't %u [%u]", wantedlen, length); - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, - args->total); - } - - if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) ) - attr->aggregator_as = stream_getl (peer->ibuf); - else - attr->aggregator_as = stream_getw (peer->ibuf); - attr->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf); - - /* Set atomic aggregate flag. */ - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR); - - return BGP_ATTR_PARSE_PROCEED; +static int bgp_attr_aggregator(struct bgp_attr_parser_args *args) +{ + struct peer *const peer = args->peer; + struct attr *const attr = args->attr; + const bgp_size_t length = args->length; + + int wantedlen = 6; + + /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */ + if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)) + wantedlen = 8; + + if (length != wantedlen) { + zlog_err("AGGREGATOR attribute length isn't %u [%u]", wantedlen, + length); + return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, + args->total); + } + + if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)) + attr->aggregator_as = stream_getl(peer->ibuf); + else + attr->aggregator_as = stream_getw(peer->ibuf); + attr->aggregator_addr.s_addr = stream_get_ipv4(peer->ibuf); + + /* Set atomic aggregate flag. */ + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR); + + return BGP_ATTR_PARSE_PROCEED; } /* New Aggregator attribute */ static bgp_attr_parse_ret_t -bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args, - as_t *as4_aggregator_as, - struct in_addr *as4_aggregator_addr) -{ - struct peer *const peer = args->peer; - struct attr *const attr = args->attr; - const bgp_size_t length = args->length; - - if (length != 8) - { - zlog_err ("New Aggregator length is not 8 [%d]", length); - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, - 0); - } - - *as4_aggregator_as = stream_getl (peer->ibuf); - as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf); - - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR); - - return BGP_ATTR_PARSE_PROCEED; +bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args, + as_t *as4_aggregator_as, + struct in_addr *as4_aggregator_addr) +{ + struct peer *const peer = args->peer; + struct attr *const attr = args->attr; + const bgp_size_t length = args->length; + + if (length != 8) { + zlog_err("New Aggregator length is not 8 [%d]", length); + return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, + 0); + } + + *as4_aggregator_as = stream_getl(peer->ibuf); + as4_aggregator_addr->s_addr = stream_get_ipv4(peer->ibuf); + + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR); + + return BGP_ATTR_PARSE_PROCEED; } /* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH. */ static bgp_attr_parse_ret_t -bgp_attr_munge_as4_attrs (struct peer *const peer, - struct attr *const attr, - struct aspath *as4_path, as_t as4_aggregator, - struct in_addr *as4_aggregator_addr) -{ - int ignore_as4_path = 0; - struct aspath *newpath; - - if (!attr->aspath) - { - /* NULL aspath shouldn't be possible as bgp_attr_parse should have - * checked that all well-known, mandatory attributes were present. - * - * Can only be a problem with peer itself - hard error - */ - return BGP_ATTR_PARSE_ERROR; - } - - if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) - { - /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR - * if given. - * It is worth a warning though, because the peer really - * should not send them - */ - if (BGP_DEBUG(as4, AS4)) - { - if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH))) - zlog_debug ("[AS4] %s %s AS4_PATH", - peer->host, "AS4 capable peer, yet it sent"); - - if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR))) - zlog_debug ("[AS4] %s %s AS4_AGGREGATOR", - peer->host, "AS4 capable peer, yet it sent"); - } - - return BGP_ATTR_PARSE_PROCEED; - } - - /* We have a asn16 peer. First, look for AS4_AGGREGATOR - * because that may override AS4_PATH - */ - if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) ) - { - if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) ) - { - /* received both. - * if the as_number in aggregator is not AS_TRANS, - * then AS4_AGGREGATOR and AS4_PATH shall be ignored - * and the Aggregator shall be taken as - * info on the aggregating node, and the AS_PATH - * shall be taken as the AS_PATH - * otherwise - * the Aggregator shall be ignored and the - * AS4_AGGREGATOR shall be taken as the - * Aggregating node and the AS_PATH is to be - * constructed "as in all other cases" - */ - if (attr->aggregator_as != BGP_AS_TRANS) - { - /* ignore */ - if ( BGP_DEBUG(as4, AS4)) - zlog_debug ("[AS4] %s BGP not AS4 capable peer" - " send AGGREGATOR != AS_TRANS and" - " AS4_AGGREGATOR, so ignore" - " AS4_AGGREGATOR and AS4_PATH", peer->host); - ignore_as4_path = 1; - } - else - { - /* "New_aggregator shall be taken as aggregator" */ - attr->aggregator_as = as4_aggregator; - attr->aggregator_addr.s_addr = as4_aggregator_addr->s_addr; - } - } - else - { - /* We received a AS4_AGGREGATOR but no AGGREGATOR. - * That is bogus - but reading the conditions - * we have to handle AS4_AGGREGATOR as if it were - * AGGREGATOR in that case - */ - if ( BGP_DEBUG(as4, AS4)) - zlog_debug ("[AS4] %s BGP not AS4 capable peer send" - " AS4_AGGREGATOR but no AGGREGATOR, will take" - " it as if AGGREGATOR with AS_TRANS had been there", peer->host); - attr->aggregator_as = as4_aggregator; - /* sweep it under the carpet and simulate a "good" AGGREGATOR */ - attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR)); - } - } - - /* need to reconcile NEW_AS_PATH and AS_PATH */ - if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH)))) - { - newpath = aspath_reconcile_as4 (attr->aspath, as4_path); - aspath_unintern (&attr->aspath); - attr->aspath = aspath_intern (newpath); - } - return BGP_ATTR_PARSE_PROCEED; +bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr, + struct aspath *as4_path, as_t as4_aggregator, + struct in_addr *as4_aggregator_addr) +{ + int ignore_as4_path = 0; + struct aspath *newpath; + + if (!attr->aspath) { + /* NULL aspath shouldn't be possible as bgp_attr_parse should + * have + * checked that all well-known, mandatory attributes were + * present. + * + * Can only be a problem with peer itself - hard error + */ + return BGP_ATTR_PARSE_ERROR; + } + + if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)) { + /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR + * if given. + * It is worth a warning though, because the peer really + * should not send them + */ + if (BGP_DEBUG(as4, AS4)) { + if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH))) + zlog_debug("[AS4] %s %s AS4_PATH", peer->host, + "AS4 capable peer, yet it sent"); + + if (attr->flag + & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR))) + zlog_debug("[AS4] %s %s AS4_AGGREGATOR", + peer->host, + "AS4 capable peer, yet it sent"); + } + + return BGP_ATTR_PARSE_PROCEED; + } + + /* We have a asn16 peer. First, look for AS4_AGGREGATOR + * because that may override AS4_PATH + */ + if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR))) { + if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) { + /* received both. + * if the as_number in aggregator is not AS_TRANS, + * then AS4_AGGREGATOR and AS4_PATH shall be ignored + * and the Aggregator shall be taken as + * info on the aggregating node, and the AS_PATH + * shall be taken as the AS_PATH + * otherwise + * the Aggregator shall be ignored and the + * AS4_AGGREGATOR shall be taken as the + * Aggregating node and the AS_PATH is to be + * constructed "as in all other cases" + */ + if (attr->aggregator_as != BGP_AS_TRANS) { + /* ignore */ + if (BGP_DEBUG(as4, AS4)) + zlog_debug( + "[AS4] %s BGP not AS4 capable peer" + " send AGGREGATOR != AS_TRANS and" + " AS4_AGGREGATOR, so ignore" + " AS4_AGGREGATOR and AS4_PATH", + peer->host); + ignore_as4_path = 1; + } else { + /* "New_aggregator shall be taken as aggregator" + */ + attr->aggregator_as = as4_aggregator; + attr->aggregator_addr.s_addr = + as4_aggregator_addr->s_addr; + } + } else { + /* We received a AS4_AGGREGATOR but no AGGREGATOR. + * That is bogus - but reading the conditions + * we have to handle AS4_AGGREGATOR as if it were + * AGGREGATOR in that case + */ + if (BGP_DEBUG(as4, AS4)) + zlog_debug( + "[AS4] %s BGP not AS4 capable peer send" + " AS4_AGGREGATOR but no AGGREGATOR, will take" + " it as if AGGREGATOR with AS_TRANS had been there", + peer->host); + attr->aggregator_as = as4_aggregator; + /* sweep it under the carpet and simulate a "good" + * AGGREGATOR */ + attr->flag |= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)); + } + } + + /* need to reconcile NEW_AS_PATH and AS_PATH */ + if (!ignore_as4_path + && (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))) { + newpath = aspath_reconcile_as4(attr->aspath, as4_path); + aspath_unintern(&attr->aspath); + attr->aspath = aspath_intern(newpath); + } + return BGP_ATTR_PARSE_PROCEED; } /* Community attribute. */ static bgp_attr_parse_ret_t -bgp_attr_community (struct bgp_attr_parser_args *args) -{ - struct peer *const peer = args->peer; - struct attr *const attr = args->attr; - const bgp_size_t length = args->length; - - if (length == 0) - { - attr->community = NULL; - return BGP_ATTR_PARSE_PROCEED; - } - - attr->community = - community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length); - - /* XXX: fix community_parse to use stream API and remove this */ - stream_forward_getp (peer->ibuf, length); - - if (!attr->community) - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, - args->total); - - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES); - - return BGP_ATTR_PARSE_PROCEED; +bgp_attr_community(struct bgp_attr_parser_args *args) +{ + struct peer *const peer = args->peer; + struct attr *const attr = args->attr; + const bgp_size_t length = args->length; + + if (length == 0) { + attr->community = NULL; + return BGP_ATTR_PARSE_PROCEED; + } + + attr->community = + community_parse((u_int32_t *)stream_pnt(peer->ibuf), length); + + /* XXX: fix community_parse to use stream API and remove this */ + stream_forward_getp(peer->ibuf, length); + + if (!attr->community) + return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, + args->total); + + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES); + + return BGP_ATTR_PARSE_PROCEED; } /* Originator ID attribute. */ static bgp_attr_parse_ret_t -bgp_attr_originator_id (struct bgp_attr_parser_args *args) +bgp_attr_originator_id(struct bgp_attr_parser_args *args) { - struct peer *const peer = args->peer; - struct attr *const attr = args->attr; - const bgp_size_t length = args->length; - - /* Length check. */ - if (length != 4) - { - zlog_err ("Bad originator ID length %d", length); + struct peer *const peer = args->peer; + struct attr *const attr = args->attr; + const bgp_size_t length = args->length; - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, - args->total); - } + /* Length check. */ + if (length != 4) { + zlog_err("Bad originator ID length %d", length); - attr->originator_id.s_addr = stream_get_ipv4 (peer->ibuf); + return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, + args->total); + } + + attr->originator_id.s_addr = stream_get_ipv4(peer->ibuf); - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID); + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID); - return BGP_ATTR_PARSE_PROCEED; + return BGP_ATTR_PARSE_PROCEED; } /* Cluster list attribute. */ static bgp_attr_parse_ret_t -bgp_attr_cluster_list (struct bgp_attr_parser_args *args) +bgp_attr_cluster_list(struct bgp_attr_parser_args *args) { - struct peer *const peer = args->peer; - struct attr *const attr = args->attr; - const bgp_size_t length = args->length; - - /* Check length. */ - if (length % 4) - { - zlog_err ("Bad cluster list length %d", length); + struct peer *const peer = args->peer; + struct attr *const attr = args->attr; + const bgp_size_t length = args->length; + + /* Check length. */ + if (length % 4) { + zlog_err("Bad cluster list length %d", length); - return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, - args->total); - } + return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, + args->total); + } + + attr->cluster = + cluster_parse((struct in_addr *)stream_pnt(peer->ibuf), length); - attr->cluster = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length); - - /* XXX: Fix cluster_parse to use stream API and then remove this */ - stream_forward_getp (peer->ibuf, length); + /* XXX: Fix cluster_parse to use stream API and then remove this */ + stream_forward_getp(peer->ibuf, length); - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST); + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST); - return BGP_ATTR_PARSE_PROCEED; + return BGP_ATTR_PARSE_PROCEED; } /* Multiprotocol reachability information parse. */ -int -bgp_mp_reach_parse (struct bgp_attr_parser_args *args, - struct bgp_nlri *mp_update) -{ - iana_afi_t pkt_afi; - afi_t afi; - safi_t pkt_safi, safi; - bgp_size_t nlri_len; - size_t start; - struct stream *s; - struct peer *const peer = args->peer; - struct attr *const attr = args->attr; - const bgp_size_t length = args->length; - - /* Set end of packet. */ - s = BGP_INPUT(peer); - start = stream_get_getp(s); - - /* safe to read statically sized header? */ +int bgp_mp_reach_parse(struct bgp_attr_parser_args *args, + struct bgp_nlri *mp_update) +{ + iana_afi_t pkt_afi; + afi_t afi; + safi_t pkt_safi, safi; + bgp_size_t nlri_len; + size_t start; + struct stream *s; + struct peer *const peer = args->peer; + struct attr *const attr = args->attr; + const bgp_size_t length = args->length; + + /* Set end of packet. */ + s = BGP_INPUT(peer); + start = stream_get_getp(s); + +/* safe to read statically sized header? */ #define BGP_MP_REACH_MIN_SIZE 5 #define LEN_LEFT (length - (stream_get_getp(s) - start)) - if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE)) - { - zlog_info ("%s: %s sent invalid length, %lu", - __func__, peer->host, (unsigned long)length); - return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; - } - - /* Load AFI, SAFI. */ - pkt_afi = stream_getw (s); - pkt_safi = stream_getc (s); - - /* Convert AFI, SAFI to internal values, check. */ - if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi)) - { - /* Log if AFI or SAFI is unrecognized. This is not an error unless - * the attribute is otherwise malformed. - */ - if (bgp_debug_update(peer, NULL, NULL, 0)) - zlog_debug ("%s: MP_REACH received AFI %u or SAFI %u is unrecognized", - peer->host, pkt_afi, pkt_safi); - return BGP_ATTR_PARSE_ERROR; - } - - /* Get nexthop length. */ - attr->mp_nexthop_len = stream_getc (s); - - if (LEN_LEFT < attr->mp_nexthop_len) - { - zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute", - __func__, peer->host, attr->mp_nexthop_len); - return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; - } - - /* Nexthop length check. */ - switch (attr->mp_nexthop_len) - { - case BGP_ATTR_NHLEN_IPV4: - stream_get (&attr->mp_nexthop_global_in, s, IPV4_MAX_BYTELEN); - /* Probably needed for RFC 2283 */ - if (attr->nexthop.s_addr == 0) - memcpy(&attr->nexthop.s_addr, &attr->mp_nexthop_global_in, IPV4_MAX_BYTELEN); - break; - case BGP_ATTR_NHLEN_VPNV4: - stream_getl (s); /* RD high */ - stream_getl (s); /* RD low */ - stream_get (&attr->mp_nexthop_global_in, s, IPV4_MAX_BYTELEN); - break; - case BGP_ATTR_NHLEN_IPV6_GLOBAL: - case BGP_ATTR_NHLEN_VPNV6_GLOBAL: - if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL) - { - stream_getl (s); /* RD high */ - stream_getl (s); /* RD low */ - } - stream_get (&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN); - break; - case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL: - case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL: - if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) - { - stream_getl (s); /* RD high */ - stream_getl (s); /* RD low */ - } - stream_get (&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN); - if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) - { - stream_getl (s); /* RD high */ - stream_getl (s); /* RD low */ - } - stream_get (&attr->mp_nexthop_local, s, IPV6_MAX_BYTELEN); - if (! IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_local)) + if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE)) { + zlog_info("%s: %s sent invalid length, %lu", __func__, + peer->host, (unsigned long)length); + return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; + } + + /* Load AFI, SAFI. */ + pkt_afi = stream_getw(s); + pkt_safi = stream_getc(s); + + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) { + /* Log if AFI or SAFI is unrecognized. This is not an error + * unless + * the attribute is otherwise malformed. + */ + if (bgp_debug_update(peer, NULL, NULL, 0)) + zlog_debug( + "%s: MP_REACH received AFI %u or SAFI %u is unrecognized", + peer->host, pkt_afi, pkt_safi); + return BGP_ATTR_PARSE_ERROR; + } + + /* Get nexthop length. */ + attr->mp_nexthop_len = stream_getc(s); + + if (LEN_LEFT < attr->mp_nexthop_len) { + zlog_info( + "%s: %s, MP nexthop length, %u, goes past end of attribute", + __func__, peer->host, attr->mp_nexthop_len); + return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; + } + + /* Nexthop length check. */ + switch (attr->mp_nexthop_len) { + case BGP_ATTR_NHLEN_IPV4: + stream_get(&attr->mp_nexthop_global_in, s, IPV4_MAX_BYTELEN); + /* Probably needed for RFC 2283 */ + if (attr->nexthop.s_addr == 0) + memcpy(&attr->nexthop.s_addr, + &attr->mp_nexthop_global_in, IPV4_MAX_BYTELEN); + break; + case BGP_ATTR_NHLEN_VPNV4: + stream_getl(s); /* RD high */ + stream_getl(s); /* RD low */ + stream_get(&attr->mp_nexthop_global_in, s, IPV4_MAX_BYTELEN); + break; + case BGP_ATTR_NHLEN_IPV6_GLOBAL: + case BGP_ATTR_NHLEN_VPNV6_GLOBAL: + if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL) { + stream_getl(s); /* RD high */ + stream_getl(s); /* RD low */ + } + stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN); + break; + case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL: + case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL: + if (attr->mp_nexthop_len + == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) { + stream_getl(s); /* RD high */ + stream_getl(s); /* RD low */ + } + stream_get(&attr->mp_nexthop_global, s, IPV6_MAX_BYTELEN); + if (attr->mp_nexthop_len + == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) { + stream_getl(s); /* RD high */ + stream_getl(s); /* RD low */ + } + stream_get(&attr->mp_nexthop_local, s, IPV6_MAX_BYTELEN); + if (!IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local)) { + char buf1[INET6_ADDRSTRLEN]; + char buf2[INET6_ADDRSTRLEN]; + + if (bgp_debug_update(peer, NULL, NULL, 1)) + zlog_debug( + "%s rcvd nexthops %s, %s -- ignoring non-LL value", + peer->host, + inet_ntop(AF_INET6, + &attr->mp_nexthop_global, + buf1, INET6_ADDRSTRLEN), + inet_ntop(AF_INET6, + &attr->mp_nexthop_local, buf2, + INET6_ADDRSTRLEN)); + + attr->mp_nexthop_len = IPV6_MAX_BYTELEN; + } + break; + default: + zlog_info("%s: (%s) Wrong multiprotocol next hop length: %d", + __func__, peer->host, attr->mp_nexthop_len); + return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; + } + + if (!LEN_LEFT) { + zlog_info("%s: (%s) Failed to read SNPA and NLRI(s)", __func__, + peer->host); + return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; + } + { - char buf1[INET6_ADDRSTRLEN]; - char buf2[INET6_ADDRSTRLEN]; - - if (bgp_debug_update(peer, NULL, NULL, 1)) - zlog_debug ("%s rcvd nexthops %s, %s -- ignoring non-LL value", - peer->host, - inet_ntop (AF_INET6, &attr->mp_nexthop_global, - buf1, INET6_ADDRSTRLEN), - inet_ntop (AF_INET6, &attr->mp_nexthop_local, - buf2, INET6_ADDRSTRLEN)); - - attr->mp_nexthop_len = IPV6_MAX_BYTELEN; - } - break; - default: - zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d", - __func__, peer->host, attr->mp_nexthop_len); - return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; - } - - if (!LEN_LEFT) - { - zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)", - __func__, peer->host); - return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; - } - - { - u_char val; - if ((val = stream_getc (s))) - zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field", - peer->host, val); - } - - /* must have nrli_len, what is left of the attribute */ - nlri_len = LEN_LEFT; - if ((!nlri_len) || (nlri_len > STREAM_READABLE(s))) - { - zlog_info ("%s: (%s) Failed to read NLRI", - __func__, peer->host); - return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; - } - - mp_update->afi = afi; - mp_update->safi = safi; - mp_update->nlri = stream_pnt (s); - mp_update->length = nlri_len; - - stream_forward_getp (s, nlri_len); - - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI); - - return BGP_ATTR_PARSE_PROCEED; + u_char val; + if ((val = stream_getc(s))) + zlog_warn( + "%s sent non-zero value, %u, for defunct SNPA-length field", + peer->host, val); + } + + /* must have nrli_len, what is left of the attribute */ + nlri_len = LEN_LEFT; + if ((!nlri_len) || (nlri_len > STREAM_READABLE(s))) { + zlog_info("%s: (%s) Failed to read NLRI", __func__, peer->host); + return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; + } + + mp_update->afi = afi; + mp_update->safi = safi; + mp_update->nlri = stream_pnt(s); + mp_update->length = nlri_len; + + stream_forward_getp(s, nlri_len); + + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI); + + return BGP_ATTR_PARSE_PROCEED; #undef LEN_LEFT } /* Multiprotocol unreachable parse */ -int -bgp_mp_unreach_parse (struct bgp_attr_parser_args *args, - struct bgp_nlri *mp_withdraw) -{ - struct stream *s; - iana_afi_t pkt_afi; - afi_t afi; - safi_t pkt_safi, safi; - u_int16_t withdraw_len; - struct peer *const peer = args->peer; - struct attr *const attr = args->attr; - const bgp_size_t length = args->length; - - s = peer->ibuf; - -#define BGP_MP_UNREACH_MIN_SIZE 3 - if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE)) - return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; - - pkt_afi = stream_getw (s); - pkt_safi = stream_getc (s); +int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args, + struct bgp_nlri *mp_withdraw) +{ + struct stream *s; + iana_afi_t pkt_afi; + afi_t afi; + safi_t pkt_safi, safi; + u_int16_t withdraw_len; + struct peer *const peer = args->peer; + struct attr *const attr = args->attr; + const bgp_size_t length = args->length; - /* Convert AFI, SAFI to internal values, check. */ - if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi)) - { - /* Log if AFI or SAFI is unrecognized. This is not an error unless - * the attribute is otherwise malformed. - */ - if (bgp_debug_update(peer, NULL, NULL, 0)) - zlog_debug ("%s: MP_UNREACH received AFI %u or SAFI %u is unrecognized", - peer->host, pkt_afi, pkt_safi); - return BGP_ATTR_PARSE_ERROR; - } + s = peer->ibuf; - withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE; +#define BGP_MP_UNREACH_MIN_SIZE 3 + if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE)) + return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; + + pkt_afi = stream_getw(s); + pkt_safi = stream_getc(s); + + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) { + /* Log if AFI or SAFI is unrecognized. This is not an error + * unless + * the attribute is otherwise malformed. + */ + if (bgp_debug_update(peer, NULL, NULL, 0)) + zlog_debug( + "%s: MP_UNREACH received AFI %u or SAFI %u is unrecognized", + peer->host, pkt_afi, pkt_safi); + return BGP_ATTR_PARSE_ERROR; + } - mp_withdraw->afi = afi; - mp_withdraw->safi = safi; - mp_withdraw->nlri = stream_pnt (s); - mp_withdraw->length = withdraw_len; + withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE; - stream_forward_getp (s, withdraw_len); + mp_withdraw->afi = afi; + mp_withdraw->safi = safi; + mp_withdraw->nlri = stream_pnt(s); + mp_withdraw->length = withdraw_len; - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI); + stream_forward_getp(s, withdraw_len); - return BGP_ATTR_PARSE_PROCEED; + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI); + + return BGP_ATTR_PARSE_PROCEED; } /* Large Community attribute. */ static bgp_attr_parse_ret_t -bgp_attr_large_community (struct bgp_attr_parser_args *args) -{ - struct peer *const peer = args->peer; - struct attr *const attr = args->attr; - const bgp_size_t length = args->length; - - /* - * Large community follows new attribute format. - */ - if (length == 0) - { - attr->lcommunity = NULL; - /* Empty extcomm doesn't seem to be invalid per se */ - return BGP_ATTR_PARSE_PROCEED; - } +bgp_attr_large_community(struct bgp_attr_parser_args *args) +{ + struct peer *const peer = args->peer; + struct attr *const attr = args->attr; + const bgp_size_t length = args->length; + + /* + * Large community follows new attribute format. + */ + if (length == 0) { + attr->lcommunity = NULL; + /* Empty extcomm doesn't seem to be invalid per se */ + return BGP_ATTR_PARSE_PROCEED; + } - attr->lcommunity = lcommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length); - /* XXX: fix ecommunity_parse to use stream API */ - stream_forward_getp (peer->ibuf, length); + attr->lcommunity = + lcommunity_parse((u_int8_t *)stream_pnt(peer->ibuf), length); + /* XXX: fix ecommunity_parse to use stream API */ + stream_forward_getp(peer->ibuf, length); - if (!attr->lcommunity) - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, - args->total); + if (!attr->lcommunity) + return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, + args->total); - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES); + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES); - return BGP_ATTR_PARSE_PROCEED; + return BGP_ATTR_PARSE_PROCEED; } /* Extended Community attribute. */ static bgp_attr_parse_ret_t -bgp_attr_ext_communities (struct bgp_attr_parser_args *args) -{ - struct peer *const peer = args->peer; - struct attr *const attr = args->attr; - const bgp_size_t length = args->length; - u_char sticky = 0; - - if (length == 0) - { - attr->ecommunity = NULL; - /* Empty extcomm doesn't seem to be invalid per se */ - return BGP_ATTR_PARSE_PROCEED; - } - - attr->ecommunity = ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length); - /* XXX: fix ecommunity_parse to use stream API */ - stream_forward_getp (peer->ibuf, length); - - if (!attr->ecommunity) - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, - args->total); - - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES); - - /* Extract MAC mobility sequence number, if any. */ - attr->mm_seqnum = bgp_attr_mac_mobility_seqnum (attr, &sticky); - attr->sticky = sticky; - - return BGP_ATTR_PARSE_PROCEED; +bgp_attr_ext_communities(struct bgp_attr_parser_args *args) +{ + struct peer *const peer = args->peer; + struct attr *const attr = args->attr; + const bgp_size_t length = args->length; + u_char sticky = 0; + + if (length == 0) { + attr->ecommunity = NULL; + /* Empty extcomm doesn't seem to be invalid per se */ + return BGP_ATTR_PARSE_PROCEED; + } + + attr->ecommunity = + ecommunity_parse((u_int8_t *)stream_pnt(peer->ibuf), length); + /* XXX: fix ecommunity_parse to use stream API */ + stream_forward_getp(peer->ibuf, length); + + if (!attr->ecommunity) + return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, + args->total); + + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES); + + /* Extract MAC mobility sequence number, if any. */ + attr->mm_seqnum = bgp_attr_mac_mobility_seqnum(attr, &sticky); + attr->sticky = sticky; + + return BGP_ATTR_PARSE_PROCEED; } /* Parse Tunnel Encap attribute in an UPDATE */ -static int -bgp_attr_encap( - uint8_t type, - struct peer *peer, /* IN */ - bgp_size_t length, /* IN: attr's length field */ - struct attr *attr, /* IN: caller already allocated */ - u_char flag, /* IN: attr's flags field */ - u_char *startp) -{ - bgp_size_t total; - struct bgp_attr_encap_subtlv *stlv_last = NULL; - uint16_t tunneltype = 0; - - total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3); - - if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS) - || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL)) - { - zlog_info ("Tunnel Encap attribute flag isn't optional and transitive %d", flag); - bgp_notify_send_with_data (peer, - BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, - startp, total); - return -1; - } - - if (BGP_ATTR_ENCAP == type) { - /* read outer TLV type and length */ - uint16_t tlv_length; - - if (length < 4) { - zlog_info ("Tunnel Encap attribute not long enough to contain outer T,L"); - bgp_notify_send_with_data(peer, - BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, - startp, total); - return -1; - } - tunneltype = stream_getw (BGP_INPUT (peer)); - tlv_length = stream_getw (BGP_INPUT (peer)); - length -= 4; - - if (tlv_length != length) { - zlog_info ("%s: tlv_length(%d) != length(%d)", - __func__, tlv_length, length); - } - } - - while (length >= 4) { - uint16_t subtype = 0; - uint16_t sublength = 0; - struct bgp_attr_encap_subtlv *tlv; - - if (BGP_ATTR_ENCAP == type) { - subtype = stream_getc (BGP_INPUT (peer)); - sublength = stream_getc (BGP_INPUT (peer)); - length -= 2; +static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */ + bgp_size_t length, /* IN: attr's length field */ + struct attr *attr, /* IN: caller already allocated */ + u_char flag, /* IN: attr's flags field */ + u_char *startp) +{ + bgp_size_t total; + struct bgp_attr_encap_subtlv *stlv_last = NULL; + uint16_t tunneltype = 0; + + total = length + (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3); + + if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS) + || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL)) { + zlog_info( + "Tunnel Encap attribute flag isn't optional and transitive %d", + flag); + bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, + startp, total); + return -1; + } + + if (BGP_ATTR_ENCAP == type) { + /* read outer TLV type and length */ + uint16_t tlv_length; + + if (length < 4) { + zlog_info( + "Tunnel Encap attribute not long enough to contain outer T,L"); + bgp_notify_send_with_data( + peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, startp, total); + return -1; + } + tunneltype = stream_getw(BGP_INPUT(peer)); + tlv_length = stream_getw(BGP_INPUT(peer)); + length -= 4; + + if (tlv_length != length) { + zlog_info("%s: tlv_length(%d) != length(%d)", __func__, + tlv_length, length); + } + } + + while (length >= 4) { + uint16_t subtype = 0; + uint16_t sublength = 0; + struct bgp_attr_encap_subtlv *tlv; + + if (BGP_ATTR_ENCAP == type) { + subtype = stream_getc(BGP_INPUT(peer)); + sublength = stream_getc(BGP_INPUT(peer)); + length -= 2; #if ENABLE_BGP_VNC - } else { - subtype = stream_getw (BGP_INPUT (peer)); - sublength = stream_getw (BGP_INPUT (peer)); - length -= 4; + } else { + subtype = stream_getw(BGP_INPUT(peer)); + sublength = stream_getw(BGP_INPUT(peer)); + length -= 4; #endif - } - - if (sublength > length) { - zlog_info ("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d", - sublength, length); - bgp_notify_send_with_data (peer, - BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, - startp, total); - return -1; - } - - /* alloc and copy sub-tlv */ - /* TBD make sure these are freed when attributes are released */ - tlv = XCALLOC (MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv)-1+sublength); - tlv->type = subtype; - tlv->length = sublength; - stream_get(tlv->value, peer->ibuf, sublength); - length -= sublength; - - /* attach tlv to encap chain */ - if (BGP_ATTR_ENCAP == type) { - for (stlv_last = attr->encap_subtlvs; stlv_last && stlv_last->next; - stlv_last = stlv_last->next); - if (stlv_last) { - stlv_last->next = tlv; - } else { - attr->encap_subtlvs = tlv; - } + } + + if (sublength > length) { + zlog_info( + "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d", + sublength, length); + bgp_notify_send_with_data( + peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, startp, total); + return -1; + } + + /* alloc and copy sub-tlv */ + /* TBD make sure these are freed when attributes are released */ + tlv = XCALLOC(MTYPE_ENCAP_TLV, + sizeof(struct bgp_attr_encap_subtlv) - 1 + + sublength); + tlv->type = subtype; + tlv->length = sublength; + stream_get(tlv->value, peer->ibuf, sublength); + length -= sublength; + + /* attach tlv to encap chain */ + if (BGP_ATTR_ENCAP == type) { + for (stlv_last = attr->encap_subtlvs; + stlv_last && stlv_last->next; + stlv_last = stlv_last->next) + ; + if (stlv_last) { + stlv_last->next = tlv; + } else { + attr->encap_subtlvs = tlv; + } #if ENABLE_BGP_VNC - } else { - for (stlv_last = attr->vnc_subtlvs; stlv_last && stlv_last->next; - stlv_last = stlv_last->next); - if (stlv_last) { - stlv_last->next = tlv; - } else { - attr->vnc_subtlvs = tlv; - } + } else { + for (stlv_last = attr->vnc_subtlvs; + stlv_last && stlv_last->next; + stlv_last = stlv_last->next) + ; + if (stlv_last) { + stlv_last->next = tlv; + } else { + attr->vnc_subtlvs = tlv; + } #endif - } - stlv_last->next = tlv; - } + } + stlv_last->next = tlv; + } - if (BGP_ATTR_ENCAP == type) { - attr->encap_tunneltype = tunneltype; - } + if (BGP_ATTR_ENCAP == type) { + attr->encap_tunneltype = tunneltype; + } - if (length) { - /* spurious leftover data */ - zlog_info ("Tunnel Encap attribute length is bad: %d leftover octets", length); - bgp_notify_send_with_data (peer, - BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, - startp, total); - return -1; - } + if (length) { + /* spurious leftover data */ + zlog_info( + "Tunnel Encap attribute length is bad: %d leftover octets", + length); + bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, + startp, total); + return -1; + } - return 0; + return 0; } /* Prefix SID attribute * draft-ietf-idr-bgp-prefix-sid-05 */ static bgp_attr_parse_ret_t -bgp_attr_prefix_sid (struct bgp_attr_parser_args *args, struct bgp_nlri *mp_update) -{ - struct peer *const peer = args->peer; - struct attr *const attr = args->attr; - int type; - int length; - u_int32_t label_index; - struct in6_addr ipv6_sid; - u_int32_t srgb_base; - u_int32_t srgb_range; - int srgb_count; - - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID); - - type = stream_getc (peer->ibuf); - length = stream_getw (peer->ibuf); - - if (type == BGP_PREFIX_SID_LABEL_INDEX) - { - if (length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) - { - zlog_err ("Prefix SID label index length is %d instead of %d", length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH); - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, - args->total); - } - - /* Ignore flags and reserved */ - stream_getc (peer->ibuf); - stream_getw (peer->ibuf); - - /* Fetch the label index and see if it is valid. */ - label_index = stream_getl (peer->ibuf); - if (label_index == BGP_INVALID_LABEL_INDEX) - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, - args->total); - - /* Store label index; subsequently, we'll check on address-family */ - attr->label_index = label_index; - - /* - * Ignore the Label index attribute unless received for labeled-unicast - * SAFI. - */ - if (!mp_update->length || mp_update->safi != SAFI_LABELED_UNICAST) - attr->label_index = BGP_INVALID_LABEL_INDEX; - } - - /* Placeholder code for the IPv6 SID type */ - else if (type == BGP_PREFIX_SID_IPV6) - { - if (length != BGP_PREFIX_SID_IPV6_LENGTH) - { - zlog_err ("Prefix SID IPv6 length is %d instead of %d", length, BGP_PREFIX_SID_IPV6_LENGTH); - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, - args->total); - } - - /* Ignore reserved */ - stream_getc (peer->ibuf); - stream_getw (peer->ibuf); - - stream_get (&ipv6_sid, peer->ibuf, 16); - } - - /* Placeholder code for the Originator SRGB type */ - else if (type == BGP_PREFIX_SID_ORIGINATOR_SRGB) - { - /* Ignore flags */ - stream_getw (peer->ibuf); - - length -= 2; - - if (length % BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH) - { - zlog_err ("Prefix SID Originator SRGB length is %d, it must be a multiple of %d ", - length, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH); - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, - args->total); - } - - srgb_count = length / BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH; - - for (int i = 0; i < srgb_count; i++) - { - stream_get (&srgb_base, peer->ibuf, 3); - stream_get (&srgb_range, peer->ibuf, 3); - } - } - - return BGP_ATTR_PARSE_PROCEED; +bgp_attr_prefix_sid(struct bgp_attr_parser_args *args, + struct bgp_nlri *mp_update) +{ + struct peer *const peer = args->peer; + struct attr *const attr = args->attr; + int type; + int length; + u_int32_t label_index; + struct in6_addr ipv6_sid; + u_int32_t srgb_base; + u_int32_t srgb_range; + int srgb_count; + + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID); + + type = stream_getc(peer->ibuf); + length = stream_getw(peer->ibuf); + + if (type == BGP_PREFIX_SID_LABEL_INDEX) { + if (length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) { + zlog_err( + "Prefix SID label index length is %d instead of %d", + length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH); + return bgp_attr_malformed( + args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, + args->total); + } + + /* Ignore flags and reserved */ + stream_getc(peer->ibuf); + stream_getw(peer->ibuf); + + /* Fetch the label index and see if it is valid. */ + label_index = stream_getl(peer->ibuf); + if (label_index == BGP_INVALID_LABEL_INDEX) + return bgp_attr_malformed( + args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, + args->total); + + /* Store label index; subsequently, we'll check on + * address-family */ + attr->label_index = label_index; + + /* + * Ignore the Label index attribute unless received for + * labeled-unicast + * SAFI. + */ + if (!mp_update->length + || mp_update->safi != SAFI_LABELED_UNICAST) + attr->label_index = BGP_INVALID_LABEL_INDEX; + } + + /* Placeholder code for the IPv6 SID type */ + else if (type == BGP_PREFIX_SID_IPV6) { + if (length != BGP_PREFIX_SID_IPV6_LENGTH) { + zlog_err("Prefix SID IPv6 length is %d instead of %d", + length, BGP_PREFIX_SID_IPV6_LENGTH); + return bgp_attr_malformed( + args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, + args->total); + } + + /* Ignore reserved */ + stream_getc(peer->ibuf); + stream_getw(peer->ibuf); + + stream_get(&ipv6_sid, peer->ibuf, 16); + } + + /* Placeholder code for the Originator SRGB type */ + else if (type == BGP_PREFIX_SID_ORIGINATOR_SRGB) { + /* Ignore flags */ + stream_getw(peer->ibuf); + + length -= 2; + + if (length % BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH) { + zlog_err( + "Prefix SID Originator SRGB length is %d, it must be a multiple of %d ", + length, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH); + return bgp_attr_malformed( + args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, + args->total); + } + + srgb_count = length / BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH; + + for (int i = 0; i < srgb_count; i++) { + stream_get(&srgb_base, peer->ibuf, 3); + stream_get(&srgb_range, peer->ibuf, 3); + } + } + + return BGP_ATTR_PARSE_PROCEED; } /* BGP unknown attribute treatment. */ -static bgp_attr_parse_ret_t -bgp_attr_unknown (struct bgp_attr_parser_args *args) -{ - bgp_size_t total = args->total; - struct transit *transit; - struct peer *const peer = args->peer; - struct attr *const attr = args->attr; - u_char *const startp = args->startp; - const u_char type = args->type; - const u_char flag = args->flags; - const bgp_size_t length = args->length; - - if (bgp_debug_update(peer, NULL, NULL, 1)) - zlog_debug ("%s Unknown attribute is received (type %d, length %d)", - peer->host, type, length); - - /* Forward read pointer of input stream. */ - stream_forward_getp (peer->ibuf, length); - - /* If any of the mandatory well-known attributes are not recognized, - then the Error Subcode is set to Unrecognized Well-known - Attribute. The Data field contains the unrecognized attribute - (type, length and value). */ - if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL)) - { - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_UNREC_ATTR, - args->total); - } - - /* Unrecognized non-transitive optional attributes must be quietly - ignored and not passed along to other BGP peers. */ - if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS)) - return BGP_ATTR_PARSE_PROCEED; - - /* If a path with recognized transitive optional attribute is - accepted and passed along to other BGP peers and the Partial bit - in the Attribute Flags octet is set to 1 by some previous AS, it - is not set back to 0 by the current AS. */ - SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL); - - /* Store transitive attribute to the end of attr->transit. */ - if (!attr->transit) - attr->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit)); - - transit = attr->transit; - - if (transit->val) - transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val, - transit->length + total); - else - transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total); - - memcpy (transit->val + transit->length, startp, total); - transit->length += total; - - return BGP_ATTR_PARSE_PROCEED; +static bgp_attr_parse_ret_t bgp_attr_unknown(struct bgp_attr_parser_args *args) +{ + bgp_size_t total = args->total; + struct transit *transit; + struct peer *const peer = args->peer; + struct attr *const attr = args->attr; + u_char *const startp = args->startp; + const u_char type = args->type; + const u_char flag = args->flags; + const bgp_size_t length = args->length; + + if (bgp_debug_update(peer, NULL, NULL, 1)) + zlog_debug( + "%s Unknown attribute is received (type %d, length %d)", + peer->host, type, length); + + /* Forward read pointer of input stream. */ + stream_forward_getp(peer->ibuf, length); + + /* If any of the mandatory well-known attributes are not recognized, + then the Error Subcode is set to Unrecognized Well-known + Attribute. The Data field contains the unrecognized attribute + (type, length and value). */ + if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL)) { + return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_UNREC_ATTR, + args->total); + } + + /* Unrecognized non-transitive optional attributes must be quietly + ignored and not passed along to other BGP peers. */ + if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS)) + return BGP_ATTR_PARSE_PROCEED; + + /* If a path with recognized transitive optional attribute is + accepted and passed along to other BGP peers and the Partial bit + in the Attribute Flags octet is set to 1 by some previous AS, it + is not set back to 0 by the current AS. */ + SET_FLAG(*startp, BGP_ATTR_FLAG_PARTIAL); + + /* Store transitive attribute to the end of attr->transit. */ + if (!attr->transit) + attr->transit = XCALLOC(MTYPE_TRANSIT, sizeof(struct transit)); + + transit = attr->transit; + + if (transit->val) + transit->val = XREALLOC(MTYPE_TRANSIT_VAL, transit->val, + transit->length + total); + else + transit->val = XMALLOC(MTYPE_TRANSIT_VAL, total); + + memcpy(transit->val + transit->length, startp, total); + transit->length += total; + + return BGP_ATTR_PARSE_PROCEED; } /* Well-known attribute check. */ -static int -bgp_attr_check (struct peer *peer, struct attr *attr) -{ - u_char type = 0; - - /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an - * empty UPDATE. */ - if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag) - return BGP_ATTR_PARSE_PROCEED; - - /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required - to carry any other path attributes.", though if MP_REACH_NLRI or NLRI - are present, it should. Check for any other attribute being present - instead. - */ - if (attr->flag == ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI)) - return BGP_ATTR_PARSE_PROCEED; - - if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN))) - type = BGP_ATTR_ORIGIN; - - if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))) - type = BGP_ATTR_AS_PATH; - - /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and - * NLRI is empty. We can't easily check NLRI empty here though. - */ - if (!CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)) - && !CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI))) - type = BGP_ATTR_NEXT_HOP; - - if (peer->sort == BGP_PEER_IBGP - && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))) - type = BGP_ATTR_LOCAL_PREF; - - if (type) - { - zlog_warn ("%s Missing well-known attribute %s.", peer->host, - lookup_msg(attr_str, type, NULL)); - bgp_notify_send_with_data (peer, - BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_MISS_ATTR, - &type, 1); - return BGP_ATTR_PARSE_ERROR; - } - return BGP_ATTR_PARSE_PROCEED; +static int bgp_attr_check(struct peer *peer, struct attr *attr) +{ + u_char type = 0; + + /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an + * empty UPDATE. */ + if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag) + return BGP_ATTR_PARSE_PROCEED; + + /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required + to carry any other path attributes.", though if MP_REACH_NLRI or NLRI + are present, it should. Check for any other attribute being present + instead. + */ + if (attr->flag == ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI)) + return BGP_ATTR_PARSE_PROCEED; + + if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN))) + type = BGP_ATTR_ORIGIN; + + if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))) + type = BGP_ATTR_AS_PATH; + + /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present + * and + * NLRI is empty. We can't easily check NLRI empty here though. + */ + if (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) + && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI))) + type = BGP_ATTR_NEXT_HOP; + + if (peer->sort == BGP_PEER_IBGP + && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) + type = BGP_ATTR_LOCAL_PREF; + + if (type) { + zlog_warn("%s Missing well-known attribute %s.", peer->host, + lookup_msg(attr_str, type, NULL)); + bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_MISS_ATTR, &type, + 1); + return BGP_ATTR_PARSE_ERROR; + } + return BGP_ATTR_PARSE_PROCEED; } /* Read attribute of update packet. This function is called from bgp_update_receive() in bgp_packet.c. */ -bgp_attr_parse_ret_t -bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, - struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw) -{ - int ret; - u_char flag = 0; - u_char type = 0; - bgp_size_t length; - u_char *startp, *endp; - u_char *attr_endp; - u_char seen[BGP_ATTR_BITMAP_SIZE]; - /* we need the as4_path only until we have synthesized the as_path with it */ - /* same goes for as4_aggregator */ - struct aspath *as4_path = NULL; - as_t as4_aggregator = 0; - struct in_addr as4_aggregator_addr = { .s_addr = 0 }; - - /* Initialize bitmap. */ - memset (seen, 0, BGP_ATTR_BITMAP_SIZE); - - /* End pointer of BGP attribute. */ - endp = BGP_INPUT_PNT (peer) + size; - - /* Get attributes to the end of attribute length. */ - while (BGP_INPUT_PNT (peer) < endp) - { - /* Check remaining length check.*/ - if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN) - { - /* XXX warning: long int format, int arg (arg 5) */ - zlog_warn ("%s: error BGP attribute length %lu is smaller than min len", - peer->host, - (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer)))); - - bgp_notify_send (peer, - BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); - return BGP_ATTR_PARSE_ERROR; - } - - /* Fetch attribute flag and type. */ - startp = BGP_INPUT_PNT (peer); - /* "The lower-order four bits of the Attribute Flags octet are - unused. They MUST be zero when sent and MUST be ignored when - received." */ - flag = 0xF0 & stream_getc (BGP_INPUT (peer)); - type = stream_getc (BGP_INPUT (peer)); - - /* Check whether Extended-Length applies and is in bounds */ - if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) - && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1))) - { - zlog_warn ("%s: Extended length set, but just %lu bytes of attr header", - peer->host, - (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer)))); - - bgp_notify_send (peer, - BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); - return BGP_ATTR_PARSE_ERROR; - } - - /* Check extended attribue length bit. */ - if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)) - length = stream_getw (BGP_INPUT (peer)); - else - length = stream_getc (BGP_INPUT (peer)); - - /* If any attribute appears more than once in the UPDATE - message, then the Error Subcode is set to Malformed Attribute - List. */ - - if (CHECK_BITMAP (seen, type)) - { - zlog_warn ("%s: error BGP attribute type %d appears twice in a message", - peer->host, type); +bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr, + bgp_size_t size, struct bgp_nlri *mp_update, + struct bgp_nlri *mp_withdraw) +{ + int ret; + u_char flag = 0; + u_char type = 0; + bgp_size_t length; + u_char *startp, *endp; + u_char *attr_endp; + u_char seen[BGP_ATTR_BITMAP_SIZE]; + /* we need the as4_path only until we have synthesized the as_path with + * it */ + /* same goes for as4_aggregator */ + struct aspath *as4_path = NULL; + as_t as4_aggregator = 0; + struct in_addr as4_aggregator_addr = {.s_addr = 0}; + + /* Initialize bitmap. */ + memset(seen, 0, BGP_ATTR_BITMAP_SIZE); + + /* End pointer of BGP attribute. */ + endp = BGP_INPUT_PNT(peer) + size; + + /* Get attributes to the end of attribute length. */ + while (BGP_INPUT_PNT(peer) < endp) { + /* Check remaining length check.*/ + if (endp - BGP_INPUT_PNT(peer) < BGP_ATTR_MIN_LEN) { + /* XXX warning: long int format, int arg (arg 5) */ + zlog_warn( + "%s: error BGP attribute length %lu is smaller than min len", + peer->host, + (unsigned long)(endp + - STREAM_PNT(BGP_INPUT(peer)))); + + bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); + return BGP_ATTR_PARSE_ERROR; + } - bgp_notify_send (peer, - BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_MAL_ATTR); - return BGP_ATTR_PARSE_ERROR; - } + /* Fetch attribute flag and type. */ + startp = BGP_INPUT_PNT(peer); + /* "The lower-order four bits of the Attribute Flags octet are + unused. They MUST be zero when sent and MUST be ignored when + received." */ + flag = 0xF0 & stream_getc(BGP_INPUT(peer)); + type = stream_getc(BGP_INPUT(peer)); + + /* Check whether Extended-Length applies and is in bounds */ + if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN) + && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1))) { + zlog_warn( + "%s: Extended length set, but just %lu bytes of attr header", + peer->host, + (unsigned long)(endp + - STREAM_PNT(BGP_INPUT(peer)))); + + bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); + return BGP_ATTR_PARSE_ERROR; + } - /* Set type to bitmap to check duplicate attribute. `type' is - unsigned char so it never overflow bitmap range. */ + /* Check extended attribue length bit. */ + if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN)) + length = stream_getw(BGP_INPUT(peer)); + else + length = stream_getc(BGP_INPUT(peer)); - SET_BITMAP (seen, type); + /* If any attribute appears more than once in the UPDATE + message, then the Error Subcode is set to Malformed Attribute + List. */ - /* Overflow check. */ - attr_endp = BGP_INPUT_PNT (peer) + length; + if (CHECK_BITMAP(seen, type)) { + zlog_warn( + "%s: error BGP attribute type %d appears twice in a message", + peer->host, type); - if (attr_endp > endp) - { - zlog_warn ("%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p", peer->host, type, length, size, attr_endp, endp); - bgp_notify_send_with_data (peer, - BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, - startp, attr_endp - startp); - return BGP_ATTR_PARSE_ERROR; - } - - struct bgp_attr_parser_args attr_args = { - .peer = peer, - .length = length, - .attr = attr, - .type = type, - .flags = flag, - .startp = startp, - .total = attr_endp - startp, - }; - - - /* If any recognized attribute has Attribute Flags that conflict - with the Attribute Type Code, then the Error Subcode is set to - Attribute Flags Error. The Data field contains the erroneous - attribute (type, length and value). */ - if (bgp_attr_flag_invalid (&attr_args)) - { - bgp_attr_parse_ret_t ret; - ret = bgp_attr_malformed (&attr_args, - BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, - attr_args.total); - if (ret == BGP_ATTR_PARSE_PROCEED) - continue; - return ret; - } - - /* OK check attribute and store it's value. */ - switch (type) - { - case BGP_ATTR_ORIGIN: - ret = bgp_attr_origin (&attr_args); - break; - case BGP_ATTR_AS_PATH: - ret = bgp_attr_aspath (&attr_args); - break; - case BGP_ATTR_AS4_PATH: - ret = bgp_attr_as4_path (&attr_args, &as4_path); - break; - case BGP_ATTR_NEXT_HOP: - ret = bgp_attr_nexthop (&attr_args); - break; - case BGP_ATTR_MULTI_EXIT_DISC: - ret = bgp_attr_med (&attr_args); - break; - case BGP_ATTR_LOCAL_PREF: - ret = bgp_attr_local_pref (&attr_args); - break; - case BGP_ATTR_ATOMIC_AGGREGATE: - ret = bgp_attr_atomic (&attr_args); - break; - case BGP_ATTR_AGGREGATOR: - ret = bgp_attr_aggregator (&attr_args); - break; - case BGP_ATTR_AS4_AGGREGATOR: - ret = bgp_attr_as4_aggregator (&attr_args, - &as4_aggregator, - &as4_aggregator_addr); - break; - case BGP_ATTR_COMMUNITIES: - ret = bgp_attr_community (&attr_args); - break; - case BGP_ATTR_LARGE_COMMUNITIES: - ret = bgp_attr_large_community (&attr_args); - break; - case BGP_ATTR_ORIGINATOR_ID: - ret = bgp_attr_originator_id (&attr_args); - break; - case BGP_ATTR_CLUSTER_LIST: - ret = bgp_attr_cluster_list (&attr_args); - break; - case BGP_ATTR_MP_REACH_NLRI: - ret = bgp_mp_reach_parse (&attr_args, mp_update); - break; - case BGP_ATTR_MP_UNREACH_NLRI: - ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw); - break; - case BGP_ATTR_EXT_COMMUNITIES: - ret = bgp_attr_ext_communities (&attr_args); - break; + bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_MAL_ATTR); + return BGP_ATTR_PARSE_ERROR; + } + + /* Set type to bitmap to check duplicate attribute. `type' is + unsigned char so it never overflow bitmap range. */ + + SET_BITMAP(seen, type); + + /* Overflow check. */ + attr_endp = BGP_INPUT_PNT(peer) + length; + + if (attr_endp > endp) { + zlog_warn( + "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p", + peer->host, type, length, size, attr_endp, + endp); + bgp_notify_send_with_data( + peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, startp, + attr_endp - startp); + return BGP_ATTR_PARSE_ERROR; + } + + struct bgp_attr_parser_args attr_args = { + .peer = peer, + .length = length, + .attr = attr, + .type = type, + .flags = flag, + .startp = startp, + .total = attr_endp - startp, + }; + + + /* If any recognized attribute has Attribute Flags that conflict + with the Attribute Type Code, then the Error Subcode is set + to + Attribute Flags Error. The Data field contains the erroneous + attribute (type, length and value). */ + if (bgp_attr_flag_invalid(&attr_args)) { + bgp_attr_parse_ret_t ret; + ret = bgp_attr_malformed( + &attr_args, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, + attr_args.total); + if (ret == BGP_ATTR_PARSE_PROCEED) + continue; + return ret; + } + + /* OK check attribute and store it's value. */ + switch (type) { + case BGP_ATTR_ORIGIN: + ret = bgp_attr_origin(&attr_args); + break; + case BGP_ATTR_AS_PATH: + ret = bgp_attr_aspath(&attr_args); + break; + case BGP_ATTR_AS4_PATH: + ret = bgp_attr_as4_path(&attr_args, &as4_path); + break; + case BGP_ATTR_NEXT_HOP: + ret = bgp_attr_nexthop(&attr_args); + break; + case BGP_ATTR_MULTI_EXIT_DISC: + ret = bgp_attr_med(&attr_args); + break; + case BGP_ATTR_LOCAL_PREF: + ret = bgp_attr_local_pref(&attr_args); + break; + case BGP_ATTR_ATOMIC_AGGREGATE: + ret = bgp_attr_atomic(&attr_args); + break; + case BGP_ATTR_AGGREGATOR: + ret = bgp_attr_aggregator(&attr_args); + break; + case BGP_ATTR_AS4_AGGREGATOR: + ret = bgp_attr_as4_aggregator(&attr_args, + &as4_aggregator, + &as4_aggregator_addr); + break; + case BGP_ATTR_COMMUNITIES: + ret = bgp_attr_community(&attr_args); + break; + case BGP_ATTR_LARGE_COMMUNITIES: + ret = bgp_attr_large_community(&attr_args); + break; + case BGP_ATTR_ORIGINATOR_ID: + ret = bgp_attr_originator_id(&attr_args); + break; + case BGP_ATTR_CLUSTER_LIST: + ret = bgp_attr_cluster_list(&attr_args); + break; + case BGP_ATTR_MP_REACH_NLRI: + ret = bgp_mp_reach_parse(&attr_args, mp_update); + break; + case BGP_ATTR_MP_UNREACH_NLRI: + ret = bgp_mp_unreach_parse(&attr_args, mp_withdraw); + break; + case BGP_ATTR_EXT_COMMUNITIES: + ret = bgp_attr_ext_communities(&attr_args); + break; #if ENABLE_BGP_VNC - case BGP_ATTR_VNC: + case BGP_ATTR_VNC: #endif - case BGP_ATTR_ENCAP: - ret = bgp_attr_encap (type, peer, length, attr, flag, startp); - break; - case BGP_ATTR_PREFIX_SID: - ret = bgp_attr_prefix_sid (&attr_args, mp_update); - break; - default: - ret = bgp_attr_unknown (&attr_args); - break; + case BGP_ATTR_ENCAP: + ret = bgp_attr_encap(type, peer, length, attr, flag, + startp); + break; + case BGP_ATTR_PREFIX_SID: + ret = bgp_attr_prefix_sid(&attr_args, mp_update); + break; + default: + ret = bgp_attr_unknown(&attr_args); + break; + } + + if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS) { + bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_MAL_ATTR); + ret = BGP_ATTR_PARSE_ERROR; + } + + /* If hard error occured immediately return to the caller. */ + if (ret == BGP_ATTR_PARSE_ERROR) { + zlog_warn("%s: Attribute %s, parse error", peer->host, + lookup_msg(attr_str, type, NULL)); + if (as4_path) + aspath_unintern(&as4_path); + return ret; + } + if (ret == BGP_ATTR_PARSE_WITHDRAW) { + + zlog_warn( + "%s: Attribute %s, parse error - treating as withdrawal", + peer->host, lookup_msg(attr_str, type, NULL)); + if (as4_path) + aspath_unintern(&as4_path); + return ret; + } + + /* Check the fetched length. */ + if (BGP_INPUT_PNT(peer) != attr_endp) { + zlog_warn("%s: BGP attribute %s, fetch error", + peer->host, lookup_msg(attr_str, type, NULL)); + bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); + if (as4_path) + aspath_unintern(&as4_path); + return BGP_ATTR_PARSE_ERROR; + } } - - if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS) - { - bgp_notify_send (peer, - BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_MAL_ATTR); - ret = BGP_ATTR_PARSE_ERROR; - } - - /* If hard error occured immediately return to the caller. */ - if (ret == BGP_ATTR_PARSE_ERROR) - { - zlog_warn ("%s: Attribute %s, parse error", - peer->host, - lookup_msg(attr_str, type, NULL)); - if (as4_path) - aspath_unintern (&as4_path); - return ret; - } - if (ret == BGP_ATTR_PARSE_WITHDRAW) - { - - zlog_warn ("%s: Attribute %s, parse error - treating as withdrawal", - peer->host, - lookup_msg(attr_str, type, NULL)); - if (as4_path) - aspath_unintern (&as4_path); - return ret; - } - - /* Check the fetched length. */ - if (BGP_INPUT_PNT (peer) != attr_endp) + + /* Check final read pointer is same as end pointer. */ + if (BGP_INPUT_PNT(peer) != endp) { + zlog_warn("%s: BGP attribute %s, length mismatch", peer->host, + lookup_msg(attr_str, type, NULL)); + bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); + if (as4_path) + aspath_unintern(&as4_path); + return BGP_ATTR_PARSE_ERROR; + } + + /* Check all mandatory well-known attributes are present */ { - zlog_warn ("%s: BGP attribute %s, fetch error", - peer->host, lookup_msg(attr_str, type, NULL)); - bgp_notify_send (peer, - BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); - if (as4_path) - aspath_unintern (&as4_path); - return BGP_ATTR_PARSE_ERROR; - } - } - - /* Check final read pointer is same as end pointer. */ - if (BGP_INPUT_PNT (peer) != endp) - { - zlog_warn ("%s: BGP attribute %s, length mismatch", - peer->host, lookup_msg(attr_str, type, NULL)); - bgp_notify_send (peer, - BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); - if (as4_path) - aspath_unintern (&as4_path); - return BGP_ATTR_PARSE_ERROR; - } - - /* Check all mandatory well-known attributes are present */ - { - bgp_attr_parse_ret_t ret; - if ((ret = bgp_attr_check (peer, attr)) < 0) - { - if (as4_path) - aspath_unintern (&as4_path); - return ret; - } - } - - /* - * At this place we can see whether we got AS4_PATH and/or - * AS4_AGGREGATOR from a 16Bit peer and act accordingly. - * We can not do this before we've read all attributes because - * the as4 handling does not say whether AS4_PATH has to be sent - * after AS_PATH or not - and when AS4_AGGREGATOR will be send - * in relationship to AGGREGATOR. - * So, to be defensive, we are not relying on any order and read - * all attributes first, including these 32bit ones, and now, - * afterwards, we look what and if something is to be done for as4. - * - * It is possible to not have AS_PATH, e.g. GR EoR and sole - * MP_UNREACH_NLRI. - */ - /* actually... this doesn't ever return failure currently, but - * better safe than sorry */ - if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)) - && bgp_attr_munge_as4_attrs (peer, attr, as4_path, - as4_aggregator, &as4_aggregator_addr)) - { - bgp_notify_send (peer, - BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_MAL_ATTR); - if (as4_path) - aspath_unintern (&as4_path); - return BGP_ATTR_PARSE_ERROR; - } - - /* At this stage, we have done all fiddling with as4, and the - * resulting info is in attr->aggregator resp. attr->aspath - * so we can chuck as4_aggregator and as4_path alltogether in - * order to save memory - */ - if (as4_path) - { - aspath_unintern (&as4_path); /* unintern - it is in the hash */ - /* The flag that we got this is still there, but that does not - * do any trouble - */ - } - /* - * The "rest" of the code does nothing with as4_aggregator. - * there is no memory attached specifically which is not part - * of the attr. - * so ignoring just means do nothing. - */ - /* - * Finally do the checks on the aspath we did not do yet - * because we waited for a potentially synthesized aspath. - */ - if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))) - { - ret = bgp_attr_aspath_check (peer, attr); - if (ret != BGP_ATTR_PARSE_PROCEED) - return ret; - } - /* Finally intern unknown attribute. */ - if (attr->transit) - attr->transit = transit_intern (attr->transit); - if (attr->encap_subtlvs) - attr->encap_subtlvs = encap_intern (attr->encap_subtlvs, ENCAP_SUBTLV_TYPE); + bgp_attr_parse_ret_t ret; + if ((ret = bgp_attr_check(peer, attr)) < 0) { + if (as4_path) + aspath_unintern(&as4_path); + return ret; + } + } + + /* + * At this place we can see whether we got AS4_PATH and/or + * AS4_AGGREGATOR from a 16Bit peer and act accordingly. + * We can not do this before we've read all attributes because + * the as4 handling does not say whether AS4_PATH has to be sent + * after AS_PATH or not - and when AS4_AGGREGATOR will be send + * in relationship to AGGREGATOR. + * So, to be defensive, we are not relying on any order and read + * all attributes first, including these 32bit ones, and now, + * afterwards, we look what and if something is to be done for as4. + * + * It is possible to not have AS_PATH, e.g. GR EoR and sole + * MP_UNREACH_NLRI. + */ + /* actually... this doesn't ever return failure currently, but + * better safe than sorry */ + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)) + && bgp_attr_munge_as4_attrs(peer, attr, as4_path, as4_aggregator, + &as4_aggregator_addr)) { + bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_MAL_ATTR); + if (as4_path) + aspath_unintern(&as4_path); + return BGP_ATTR_PARSE_ERROR; + } + + /* At this stage, we have done all fiddling with as4, and the + * resulting info is in attr->aggregator resp. attr->aspath + * so we can chuck as4_aggregator and as4_path alltogether in + * order to save memory + */ + if (as4_path) { + aspath_unintern(&as4_path); /* unintern - it is in the hash */ + /* The flag that we got this is still there, but that does not + * do any trouble + */ + } + /* + * The "rest" of the code does nothing with as4_aggregator. + * there is no memory attached specifically which is not part + * of the attr. + * so ignoring just means do nothing. + */ + /* + * Finally do the checks on the aspath we did not do yet + * because we waited for a potentially synthesized aspath. + */ + if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))) { + ret = bgp_attr_aspath_check(peer, attr); + if (ret != BGP_ATTR_PARSE_PROCEED) + return ret; + } + /* Finally intern unknown attribute. */ + if (attr->transit) + attr->transit = transit_intern(attr->transit); + if (attr->encap_subtlvs) + attr->encap_subtlvs = + encap_intern(attr->encap_subtlvs, ENCAP_SUBTLV_TYPE); #if ENABLE_BGP_VNC - if (attr->vnc_subtlvs) - attr->vnc_subtlvs = encap_intern (attr->vnc_subtlvs, VNC_SUBTLV_TYPE); + if (attr->vnc_subtlvs) + attr->vnc_subtlvs = + encap_intern(attr->vnc_subtlvs, VNC_SUBTLV_TYPE); #endif - return BGP_ATTR_PARSE_PROCEED; -} - -size_t -bgp_packet_mpattr_start (struct stream *s, struct peer *peer, - afi_t afi, safi_t safi, - struct bpacket_attr_vec_arr *vecarr, - struct attr *attr) -{ - size_t sizep; - iana_afi_t pkt_afi; - safi_t pkt_safi; - afi_t nh_afi; - - /* Set extended bit always to encode the attribute length as 2 bytes */ - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN); - stream_putc (s, BGP_ATTR_MP_REACH_NLRI); - sizep = stream_get_endp (s); - stream_putw (s, 0); /* Marker: Attribute length. */ - - - /* Convert AFI, SAFI to values for packet. */ - bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); - - stream_putw (s, pkt_afi); /* AFI */ - stream_putc (s, pkt_safi); /* SAFI */ - - /* Nexthop AFI */ - if (afi == AFI_IP && safi == SAFI_UNICAST) - { - nh_afi = peer_cap_enhe (peer, afi, safi) ? AFI_IP6 : AFI_IP; - } - else if (safi == SAFI_LABELED_UNICAST) - nh_afi = afi; - else - nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->mp_nexthop_len); - - /* Nexthop */ - bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr); - switch (nh_afi) - { - case AFI_IP: - switch (safi) - { - case SAFI_UNICAST: - case SAFI_MULTICAST: - case SAFI_LABELED_UNICAST: - stream_putc (s, 4); - stream_put_ipv4 (s, attr->nexthop.s_addr); - break; - case SAFI_MPLS_VPN: - stream_putc (s, 12); - stream_putl (s, 0); /* RD = 0, per RFC */ - stream_putl (s, 0); - stream_put (s, &attr->mp_nexthop_global_in, 4); - break; - case SAFI_ENCAP: - case SAFI_EVPN: - stream_putc (s, 4); - stream_put (s, &attr->mp_nexthop_global_in, 4); - break; + return BGP_ATTR_PARSE_PROCEED; +} + +size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi, + safi_t safi, struct bpacket_attr_vec_arr *vecarr, + struct attr *attr) +{ + size_t sizep; + iana_afi_t pkt_afi; + safi_t pkt_safi; + afi_t nh_afi; + + /* Set extended bit always to encode the attribute length as 2 bytes */ + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_EXTLEN); + stream_putc(s, BGP_ATTR_MP_REACH_NLRI); + sizep = stream_get_endp(s); + stream_putw(s, 0); /* Marker: Attribute length. */ + + + /* Convert AFI, SAFI to values for packet. */ + bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi); + + stream_putw(s, pkt_afi); /* AFI */ + stream_putc(s, pkt_safi); /* SAFI */ + + /* Nexthop AFI */ + if (afi == AFI_IP && safi == SAFI_UNICAST) { + nh_afi = peer_cap_enhe(peer, afi, safi) ? AFI_IP6 : AFI_IP; + } else if (safi == SAFI_LABELED_UNICAST) + nh_afi = afi; + else + nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->mp_nexthop_len); + + /* Nexthop */ + bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s, attr); + switch (nh_afi) { + case AFI_IP: + switch (safi) { + case SAFI_UNICAST: + case SAFI_MULTICAST: + case SAFI_LABELED_UNICAST: + stream_putc(s, 4); + stream_put_ipv4(s, attr->nexthop.s_addr); + break; + case SAFI_MPLS_VPN: + stream_putc(s, 12); + stream_putl(s, 0); /* RD = 0, per RFC */ + stream_putl(s, 0); + stream_put(s, &attr->mp_nexthop_global_in, 4); + break; + case SAFI_ENCAP: + case SAFI_EVPN: + stream_putc(s, 4); + stream_put(s, &attr->mp_nexthop_global_in, 4); + break; + default: + break; + } + break; + case AFI_IP6: + switch (safi) { + case SAFI_UNICAST: + case SAFI_MULTICAST: + case SAFI_LABELED_UNICAST: + case SAFI_EVPN: { + if (attr->mp_nexthop_len + == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) { + stream_putc(s, + BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL); + stream_put(s, &attr->mp_nexthop_global, + IPV6_MAX_BYTELEN); + stream_put(s, &attr->mp_nexthop_local, + IPV6_MAX_BYTELEN); + } else { + stream_putc(s, IPV6_MAX_BYTELEN); + stream_put(s, &attr->mp_nexthop_global, + IPV6_MAX_BYTELEN); + } + } break; + case SAFI_MPLS_VPN: { + if (attr->mp_nexthop_len + == BGP_ATTR_NHLEN_IPV6_GLOBAL) { + stream_putc(s, 24); + stream_putl(s, 0); /* RD = 0, per RFC */ + stream_putl(s, 0); + stream_put(s, &attr->mp_nexthop_global, + IPV6_MAX_BYTELEN); + } else if (attr->mp_nexthop_len + == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) { + stream_putc(s, 48); + stream_putl(s, 0); /* RD = 0, per RFC */ + stream_putl(s, 0); + stream_put(s, &attr->mp_nexthop_global, + IPV6_MAX_BYTELEN); + stream_putl(s, 0); /* RD = 0, per RFC */ + stream_putl(s, 0); + stream_put(s, &attr->mp_nexthop_local, + IPV6_MAX_BYTELEN); + } + } break; + case SAFI_ENCAP: + stream_putc(s, IPV6_MAX_BYTELEN); + stream_put(s, &attr->mp_nexthop_global, + IPV6_MAX_BYTELEN); + break; + default: + break; + } + break; default: - break; - } - break; - case AFI_IP6: - switch (safi) - { - case SAFI_UNICAST: - case SAFI_MULTICAST: - case SAFI_LABELED_UNICAST: - case SAFI_EVPN: - { - if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) { - stream_putc (s, BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL); - stream_put (s, &attr->mp_nexthop_global, IPV6_MAX_BYTELEN); - stream_put (s, &attr->mp_nexthop_local, IPV6_MAX_BYTELEN); - } else { - stream_putc (s, IPV6_MAX_BYTELEN); - stream_put (s, &attr->mp_nexthop_global, IPV6_MAX_BYTELEN); - } - } - break; - case SAFI_MPLS_VPN: - { - if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) { - stream_putc (s, 24); - stream_putl (s, 0); /* RD = 0, per RFC */ - stream_putl (s, 0); - stream_put (s, &attr->mp_nexthop_global, IPV6_MAX_BYTELEN); - } else if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) { - stream_putc (s, 48); - stream_putl (s, 0); /* RD = 0, per RFC */ - stream_putl (s, 0); - stream_put (s, &attr->mp_nexthop_global, IPV6_MAX_BYTELEN); - stream_putl (s, 0); /* RD = 0, per RFC */ - stream_putl (s, 0); - stream_put (s, &attr->mp_nexthop_local, IPV6_MAX_BYTELEN); - } - } - break; - case SAFI_ENCAP: - stream_putc (s, IPV6_MAX_BYTELEN); - stream_put (s, &attr->mp_nexthop_global, IPV6_MAX_BYTELEN); - break; - default: - break; - } - break; - default: - zlog_err ("Bad nexthop when sening to %s, AFI %u SAFI %u nhlen %d", - peer->host, afi, safi, attr->mp_nexthop_len); - break; - } - - /* SNPA */ - stream_putc (s, 0); - return sizep; -} - -void -bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi, - struct prefix *p, struct prefix_rd *prd, - mpls_label_t *label, int addpath_encode, - u_int32_t addpath_tx_id, struct attr *attr) -{ - if (safi == SAFI_MPLS_VPN) - { - if (addpath_encode) - stream_putl(s, addpath_tx_id); - /* Label, RD, Prefix write. */ - stream_putc (s, p->prefixlen + 88); - stream_put (s, label, BGP_LABEL_BYTES); - stream_put (s, prd->val, 8); - stream_put (s, &p->u.prefix, PSIZE (p->prefixlen)); - } - else if (afi == AFI_L2VPN && safi == SAFI_EVPN) - { - /* EVPN prefix - contents depend on type */ - bgp_evpn_encode_prefix (s, p, prd, label, attr, - addpath_encode, addpath_tx_id); - } - else if (safi == SAFI_LABELED_UNICAST) - { - /* Prefix write with label. */ - stream_put_labeled_prefix(s, p, label); - } - else - stream_put_prefix_addpath (s, p, addpath_encode, addpath_tx_id); -} - -size_t -bgp_packet_mpattr_prefix_size (afi_t afi, safi_t safi, struct prefix *p) -{ - int size = PSIZE (p->prefixlen); - if (safi == SAFI_MPLS_VPN) - size += 88; - else if (afi == AFI_L2VPN && safi == SAFI_EVPN) - size += 232; // TODO: Maximum possible for type-2, type-3 and type-5 - return size; + zlog_err( + "Bad nexthop when sening to %s, AFI %u SAFI %u nhlen %d", + peer->host, afi, safi, attr->mp_nexthop_len); + break; + } + + /* SNPA */ + stream_putc(s, 0); + return sizep; +} + +void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi, + struct prefix *p, struct prefix_rd *prd, + mpls_label_t *label, int addpath_encode, + u_int32_t addpath_tx_id, struct attr *attr) +{ + if (safi == SAFI_MPLS_VPN) { + if (addpath_encode) + stream_putl(s, addpath_tx_id); + /* Label, RD, Prefix write. */ + stream_putc(s, p->prefixlen + 88); + stream_put(s, label, BGP_LABEL_BYTES); + stream_put(s, prd->val, 8); + stream_put(s, &p->u.prefix, PSIZE(p->prefixlen)); + } else if (afi == AFI_L2VPN && safi == SAFI_EVPN) { + /* EVPN prefix - contents depend on type */ + bgp_evpn_encode_prefix(s, p, prd, label, attr, addpath_encode, + addpath_tx_id); + } else if (safi == SAFI_LABELED_UNICAST) { + /* Prefix write with label. */ + stream_put_labeled_prefix(s, p, label); + } else + stream_put_prefix_addpath(s, p, addpath_encode, addpath_tx_id); +} + +size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi, struct prefix *p) +{ + int size = PSIZE(p->prefixlen); + if (safi == SAFI_MPLS_VPN) + size += 88; + else if (afi == AFI_L2VPN && safi == SAFI_EVPN) + size += 232; // TODO: Maximum possible for type-2, type-3 and + // type-5 + return size; } /* * Encodes the tunnel encapsulation attribute, - * and with ENABLE_BGP_VNC the VNC attribute which uses + * and with ENABLE_BGP_VNC the VNC attribute which uses * almost the same TLV format */ -static void -bgp_packet_mpattr_tea( - struct bgp *bgp, - struct peer *peer, - struct stream *s, - struct attr *attr, - uint8_t attrtype) -{ - unsigned int attrlenfield = 0; - unsigned int attrhdrlen = 0; - struct bgp_attr_encap_subtlv *subtlvs; - struct bgp_attr_encap_subtlv *st; - const char *attrname; - - if (!attr || - (attrtype == BGP_ATTR_ENCAP && - (!attr->encap_tunneltype || - attr->encap_tunneltype == BGP_ENCAP_TYPE_MPLS))) - return; - - switch (attrtype) { +static void bgp_packet_mpattr_tea(struct bgp *bgp, struct peer *peer, + struct stream *s, struct attr *attr, + uint8_t attrtype) +{ + unsigned int attrlenfield = 0; + unsigned int attrhdrlen = 0; + struct bgp_attr_encap_subtlv *subtlvs; + struct bgp_attr_encap_subtlv *st; + const char *attrname; + + if (!attr || (attrtype == BGP_ATTR_ENCAP + && (!attr->encap_tunneltype + || attr->encap_tunneltype == BGP_ENCAP_TYPE_MPLS))) + return; + + switch (attrtype) { case BGP_ATTR_ENCAP: - attrname = "Tunnel Encap"; - subtlvs = attr->encap_subtlvs; - if (subtlvs == NULL) /* nothing to do */ - return; - /* - * The tunnel encap attr has an "outer" tlv. - * T = tunneltype, - * L = total length of subtlvs, - * V = concatenated subtlvs. - */ - attrlenfield = 2 + 2; /* T + L */ - attrhdrlen = 1 + 1; /* subTLV T + L */ - break; + attrname = "Tunnel Encap"; + subtlvs = attr->encap_subtlvs; + if (subtlvs == NULL) /* nothing to do */ + return; + /* + * The tunnel encap attr has an "outer" tlv. + * T = tunneltype, + * L = total length of subtlvs, + * V = concatenated subtlvs. + */ + attrlenfield = 2 + 2; /* T + L */ + attrhdrlen = 1 + 1; /* subTLV T + L */ + break; #if ENABLE_BGP_VNC case BGP_ATTR_VNC: - attrname = "VNC"; - subtlvs = attr->vnc_subtlvs; - if (subtlvs == NULL) /* nothing to do */ - return; - attrlenfield = 0; /* no outer T + L */ - attrhdrlen = 2 + 2; /* subTLV T + L */ - break; + attrname = "VNC"; + subtlvs = attr->vnc_subtlvs; + if (subtlvs == NULL) /* nothing to do */ + return; + attrlenfield = 0; /* no outer T + L */ + attrhdrlen = 2 + 2; /* subTLV T + L */ + break; #endif default: - assert(0); - } - - /* compute attr length */ - for (st = subtlvs; st; st = st->next) { - attrlenfield += (attrhdrlen + st->length); - } - - if (attrlenfield > 0xffff) { - zlog_info ("%s attribute is too long (length=%d), can't send it", - attrname, - attrlenfield); - return; - } - - if (attrlenfield > 0xff) { - /* 2-octet length field */ - stream_putc (s, - BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN); - stream_putc (s, attrtype); - stream_putw (s, attrlenfield & 0xffff); - } else { - /* 1-octet length field */ - stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL); - stream_putc (s, attrtype); - stream_putc (s, attrlenfield & 0xff); - } - - if (attrtype == BGP_ATTR_ENCAP) { - /* write outer T+L */ - stream_putw(s, attr->encap_tunneltype); - stream_putw(s, attrlenfield - 4); - } - - /* write each sub-tlv */ - for (st = subtlvs; st; st = st->next) { - if (attrtype == BGP_ATTR_ENCAP) { - stream_putc (s, st->type); - stream_putc (s, st->length); + assert(0); + } + + /* compute attr length */ + for (st = subtlvs; st; st = st->next) { + attrlenfield += (attrhdrlen + st->length); + } + + if (attrlenfield > 0xffff) { + zlog_info("%s attribute is too long (length=%d), can't send it", + attrname, attrlenfield); + return; + } + + if (attrlenfield > 0xff) { + /* 2-octet length field */ + stream_putc(s, + BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL + | BGP_ATTR_FLAG_EXTLEN); + stream_putc(s, attrtype); + stream_putw(s, attrlenfield & 0xffff); + } else { + /* 1-octet length field */ + stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL); + stream_putc(s, attrtype); + stream_putc(s, attrlenfield & 0xff); + } + + if (attrtype == BGP_ATTR_ENCAP) { + /* write outer T+L */ + stream_putw(s, attr->encap_tunneltype); + stream_putw(s, attrlenfield - 4); + } + + /* write each sub-tlv */ + for (st = subtlvs; st; st = st->next) { + if (attrtype == BGP_ATTR_ENCAP) { + stream_putc(s, st->type); + stream_putc(s, st->length); #if ENABLE_BGP_VNC - } else { - stream_putw (s, st->type); - stream_putw (s, st->length); + } else { + stream_putw(s, st->type); + stream_putw(s, st->length); #endif - } - stream_put (s, st->value, st->length); - } + } + stream_put(s, st->value, st->length); + } } -void -bgp_packet_mpattr_end (struct stream *s, size_t sizep) +void bgp_packet_mpattr_end(struct stream *s, size_t sizep) { - /* Set MP attribute length. Don't count the (2) bytes used to encode - the attr length */ - stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2); + /* Set MP attribute length. Don't count the (2) bytes used to encode + the attr length */ + stream_putw_at(s, sizep, (stream_get_endp(s) - sizep) - 2); } /* Make attribute packet. */ -bgp_size_t -bgp_packet_attribute (struct bgp *bgp, struct peer *peer, - struct stream *s, struct attr *attr, - struct bpacket_attr_vec_arr *vecarr, - struct prefix *p, afi_t afi, safi_t safi, - struct peer *from, struct prefix_rd *prd, mpls_label_t *label, - int addpath_encode, - u_int32_t addpath_tx_id) -{ - size_t cp; - size_t aspath_sizep; - struct aspath *aspath; - int send_as4_path = 0; - int send_as4_aggregator = 0; - int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0; - - if (! bgp) - bgp = peer->bgp; - - /* Remember current pointer. */ - cp = stream_get_endp (s); - - if (p && !((afi == AFI_IP && safi == SAFI_UNICAST) && - !peer_cap_enhe(peer, afi, safi))) - { - size_t mpattrlen_pos = 0; - - mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi, vecarr, attr); - bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label, - addpath_encode, addpath_tx_id, attr); - bgp_packet_mpattr_end(s, mpattrlen_pos); - } - - /* Origin attribute. */ - stream_putc (s, BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_ORIGIN); - stream_putc (s, 1); - stream_putc (s, attr->origin); - - /* AS path attribute. */ - - /* If remote-peer is EBGP */ - if (peer->sort == BGP_PEER_EBGP - && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED) - || attr->aspath->segments == NULL) - && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))) - { - aspath = aspath_dup (attr->aspath); - - /* Even though we may not be configured for confederations we may have - * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */ - aspath = aspath_delete_confed_seq (aspath); - - if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) - { - /* Stuff our path CONFED_ID on the front */ - aspath = aspath_add_seq (aspath, bgp->confed_id); +bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, + struct stream *s, struct attr *attr, + struct bpacket_attr_vec_arr *vecarr, + struct prefix *p, afi_t afi, safi_t safi, + struct peer *from, struct prefix_rd *prd, + mpls_label_t *label, int addpath_encode, + u_int32_t addpath_tx_id) +{ + size_t cp; + size_t aspath_sizep; + struct aspath *aspath; + int send_as4_path = 0; + int send_as4_aggregator = 0; + int use32bit = (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0; + + if (!bgp) + bgp = peer->bgp; + + /* Remember current pointer. */ + cp = stream_get_endp(s); + + if (p + && !((afi == AFI_IP && safi == SAFI_UNICAST) + && !peer_cap_enhe(peer, afi, safi))) { + size_t mpattrlen_pos = 0; + + mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi, + vecarr, attr); + bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label, + addpath_encode, addpath_tx_id, attr); + bgp_packet_mpattr_end(s, mpattrlen_pos); } - else - { - if (peer->change_local_as) { - /* If replace-as is specified, we only use the change_local_as when - advertising routes. */ - if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) { - aspath = aspath_add_seq (aspath, peer->local_as); - } - aspath = aspath_add_seq (aspath, peer->change_local_as); - } else { - aspath = aspath_add_seq (aspath, peer->local_as); - } - } - } - else if (peer->sort == BGP_PEER_CONFED) - { - /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */ - aspath = aspath_dup (attr->aspath); - aspath = aspath_add_confed_seq (aspath, peer->local_as); - } - else - aspath = attr->aspath; - - /* If peer is not AS4 capable, then: - * - send the created AS_PATH out as AS4_PATH (optional, transitive), - * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment - * types are in it (i.e. exclude them if they are there) - * AND do this only if there is at least one asnum > 65535 in the path! - * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change - * all ASnums > 65535 to BGP_AS_TRANS - */ - - stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); - stream_putc (s, BGP_ATTR_AS_PATH); - aspath_sizep = stream_get_endp (s); - stream_putw (s, 0); - stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit)); - - /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs - * in the path - */ - if (!use32bit && aspath_has_as4 (aspath)) - send_as4_path = 1; /* we'll do this later, at the correct place */ - - /* Nexthop attribute. */ - if (afi == AFI_IP && safi == SAFI_UNICAST && !peer_cap_enhe(peer, afi, safi)) - { - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)) - { - stream_putc (s, BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_NEXT_HOP); - bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr); - stream_putc (s, 4); - stream_put_ipv4 (s, attr->nexthop.s_addr); - } - else if (peer_cap_enhe(from, afi, safi)) - { - /* - * Likely this is the case when an IPv4 prefix was received with - * Extended Next-hop capability and now being advertised to - * non-ENHE peers. - * Setting the mandatory (ipv4) next-hop attribute here to enable - * implicit next-hop self with correct (ipv4 address family). - */ - stream_putc (s, BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_NEXT_HOP); - bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, NULL); - stream_putc (s, 4); - stream_put_ipv4 (s, 0); - } - } - - /* MED attribute. */ - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC) || - bgp->maxmed_active) - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); - stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC); - stream_putc (s, 4); - stream_putl (s, (bgp->maxmed_active ? bgp->maxmed_value : attr->med)); - } - - /* Local preference. */ - if (peer->sort == BGP_PEER_IBGP || - peer->sort == BGP_PEER_CONFED) - { - stream_putc (s, BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_LOCAL_PREF); - stream_putc (s, 4); - stream_putl (s, attr->local_pref); - } - - /* Atomic aggregate. */ - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE)) - { - stream_putc (s, BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE); - stream_putc (s, 0); - } - - /* Aggregator. */ - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR)) - { - /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */ - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_AGGREGATOR); - - if (use32bit) - { - /* AS4 capable peer */ - stream_putc (s, 8); - stream_putl (s, attr->aggregator_as); - } - else - { - /* 2-byte AS peer */ - stream_putc (s, 6); - - /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */ - if ( attr->aggregator_as > 65535 ) - { - stream_putw (s, BGP_AS_TRANS); - - /* we have to send AS4_AGGREGATOR, too. - * we'll do that later in order to send attributes in ascending - * order. - */ - send_as4_aggregator = 1; - } - else - stream_putw (s, (u_int16_t) attr->aggregator_as); - } - stream_put_ipv4 (s, attr->aggregator_addr.s_addr); - } - - /* Community attribute. */ - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY) - && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))) - { - if (attr->community->size * 4 > 255) - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); - stream_putc (s, BGP_ATTR_COMMUNITIES); - stream_putw (s, attr->community->size * 4); + + /* Origin attribute. */ + stream_putc(s, BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_ORIGIN); + stream_putc(s, 1); + stream_putc(s, attr->origin); + + /* AS path attribute. */ + + /* If remote-peer is EBGP */ + if (peer->sort == BGP_PEER_EBGP + && (!CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_AS_PATH_UNCHANGED) + || attr->aspath->segments == NULL) + && (!CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_RSERVER_CLIENT))) { + aspath = aspath_dup(attr->aspath); + + /* Even though we may not be configured for confederations we + * may have + * RXed an AS_PATH with AS_CONFED_SEQUENCE or AS_CONFED_SET */ + aspath = aspath_delete_confed_seq(aspath); + + if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) { + /* Stuff our path CONFED_ID on the front */ + aspath = aspath_add_seq(aspath, bgp->confed_id); + } else { + if (peer->change_local_as) { + /* If replace-as is specified, we only use the + change_local_as when + advertising routes. */ + if (!CHECK_FLAG( + peer->flags, + PEER_FLAG_LOCAL_AS_REPLACE_AS)) { + aspath = aspath_add_seq(aspath, + peer->local_as); + } + aspath = aspath_add_seq(aspath, + peer->change_local_as); + } else { + aspath = aspath_add_seq(aspath, peer->local_as); + } + } + } else if (peer->sort == BGP_PEER_CONFED) { + /* A confed member, so we need to do the AS_CONFED_SEQUENCE + * thing */ + aspath = aspath_dup(attr->aspath); + aspath = aspath_add_confed_seq(aspath, peer->local_as); + } else + aspath = attr->aspath; + + /* If peer is not AS4 capable, then: + * - send the created AS_PATH out as AS4_PATH (optional, transitive), + * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path + * segment + * types are in it (i.e. exclude them if they are there) + * AND do this only if there is at least one asnum > 65535 in the + * path! + * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and + * change + * all ASnums > 65535 to BGP_AS_TRANS + */ + + stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_EXTLEN); + stream_putc(s, BGP_ATTR_AS_PATH); + aspath_sizep = stream_get_endp(s); + stream_putw(s, 0); + stream_putw_at(s, aspath_sizep, aspath_put(s, aspath, use32bit)); + + /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs + * in the path + */ + if (!use32bit && aspath_has_as4(aspath)) + send_as4_path = + 1; /* we'll do this later, at the correct place */ + + /* Nexthop attribute. */ + if (afi == AFI_IP && safi == SAFI_UNICAST + && !peer_cap_enhe(peer, afi, safi)) { + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) { + stream_putc(s, BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_NEXT_HOP); + bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s, + attr); + stream_putc(s, 4); + stream_put_ipv4(s, attr->nexthop.s_addr); + } else if (peer_cap_enhe(from, afi, safi)) { + /* + * Likely this is the case when an IPv4 prefix was + * received with + * Extended Next-hop capability and now being advertised + * to + * non-ENHE peers. + * Setting the mandatory (ipv4) next-hop attribute here + * to enable + * implicit next-hop self with correct (ipv4 address + * family). + */ + stream_putc(s, BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_NEXT_HOP); + bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s, + NULL); + stream_putc(s, 4); + stream_put_ipv4(s, 0); + } } - else - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_COMMUNITIES); - stream_putc (s, attr->community->size * 4); - } - stream_put (s, attr->community->val, attr->community->size * 4); - } - - /* - * Large Community attribute. - */ - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY) - && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES))) - { - if (attr->lcommunity->size * 12 > 255) - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); - stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES); - stream_putw (s, attr->lcommunity->size * 12); - } - else - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES); - stream_putc (s, attr->lcommunity->size * 12); - } - stream_put (s, attr->lcommunity->val, attr->lcommunity->size * 12); - } - - /* Route Reflector. */ - if (peer->sort == BGP_PEER_IBGP - && from - && from->sort == BGP_PEER_IBGP) - { - /* Originator ID. */ - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); - stream_putc (s, BGP_ATTR_ORIGINATOR_ID); - stream_putc (s, 4); - - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) - stream_put_in_addr (s, &attr->originator_id); - else - stream_put_in_addr (s, &from->remote_id); - - /* Cluster list. */ - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); - stream_putc (s, BGP_ATTR_CLUSTER_LIST); - - if (attr->cluster) - { - stream_putc (s, attr->cluster->length + 4); - /* If this peer configuration's parent BGP has cluster_id. */ - if (bgp->config & BGP_CONFIG_CLUSTER_ID) - stream_put_in_addr (s, &bgp->cluster_id); - else - stream_put_in_addr (s, &bgp->router_id); - stream_put (s, attr->cluster->list, - attr->cluster->length); - } - else - { - stream_putc (s, 4); - /* If this peer configuration's parent BGP has cluster_id. */ - if (bgp->config & BGP_CONFIG_CLUSTER_ID) - stream_put_in_addr (s, &bgp->cluster_id); - else - stream_put_in_addr (s, &bgp->router_id); - } - } - - /* Extended Communities attribute. */ - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY) - && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES))) - { - if (peer->sort == BGP_PEER_IBGP - || peer->sort == BGP_PEER_CONFED) - { - if (attr->ecommunity->size * 8 > 255) - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); - stream_putc (s, BGP_ATTR_EXT_COMMUNITIES); - stream_putw (s, attr->ecommunity->size * 8); - } - else - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_EXT_COMMUNITIES); - stream_putc (s, attr->ecommunity->size * 8); - } - stream_put (s, attr->ecommunity->val, attr->ecommunity->size * 8); - } - else - { - u_int8_t *pnt; - int tbit; - int ecom_tr_size = 0; - int i; - - for (i = 0; i < attr->ecommunity->size; i++) - { - pnt = attr->ecommunity->val + (i * 8); - tbit = *pnt; - - if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE)) - continue; - - ecom_tr_size++; - } - - if (ecom_tr_size) - { - if (ecom_tr_size * 8 > 255) - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); - stream_putc (s, BGP_ATTR_EXT_COMMUNITIES); - stream_putw (s, ecom_tr_size * 8); + + /* MED attribute. */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC) + || bgp->maxmed_active) { + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL); + stream_putc(s, BGP_ATTR_MULTI_EXIT_DISC); + stream_putc(s, 4); + stream_putl(s, (bgp->maxmed_active ? bgp->maxmed_value + : attr->med)); + } + + /* Local preference. */ + if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED) { + stream_putc(s, BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_LOCAL_PREF); + stream_putc(s, 4); + stream_putl(s, attr->local_pref); + } + + /* Atomic aggregate. */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) { + stream_putc(s, BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_ATOMIC_AGGREGATE); + stream_putc(s, 0); + } + + /* Aggregator. */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)) { + /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */ + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_AGGREGATOR); + + if (use32bit) { + /* AS4 capable peer */ + stream_putc(s, 8); + stream_putl(s, attr->aggregator_as); + } else { + /* 2-byte AS peer */ + stream_putc(s, 6); + + /* Is ASN representable in 2-bytes? Or must AS_TRANS be + * used? */ + if (attr->aggregator_as > 65535) { + stream_putw(s, BGP_AS_TRANS); + + /* we have to send AS4_AGGREGATOR, too. + * we'll do that later in order to send + * attributes in ascending + * order. + */ + send_as4_aggregator = 1; + } else + stream_putw(s, (u_int16_t)attr->aggregator_as); + } + stream_put_ipv4(s, attr->aggregator_addr.s_addr); + } + + /* Community attribute. */ + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY) + && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) { + if (attr->community->size * 4 > 255) { + stream_putc(s, + BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS + | BGP_ATTR_FLAG_EXTLEN); + stream_putc(s, BGP_ATTR_COMMUNITIES); + stream_putw(s, attr->community->size * 4); + } else { + stream_putc(s, + BGP_ATTR_FLAG_OPTIONAL + | BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_COMMUNITIES); + stream_putc(s, attr->community->size * 4); } - else - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_EXT_COMMUNITIES); - stream_putc (s, ecom_tr_size * 8); + stream_put(s, attr->community->val, attr->community->size * 4); + } + + /* + * Large Community attribute. + */ + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_SEND_LARGE_COMMUNITY) + && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) { + if (attr->lcommunity->size * 12 > 255) { + stream_putc(s, + BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS + | BGP_ATTR_FLAG_EXTLEN); + stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES); + stream_putw(s, attr->lcommunity->size * 12); + } else { + stream_putc(s, + BGP_ATTR_FLAG_OPTIONAL + | BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES); + stream_putc(s, attr->lcommunity->size * 12); } + stream_put(s, attr->lcommunity->val, + attr->lcommunity->size * 12); + } - for (i = 0; i < attr->ecommunity->size; i++) - { - pnt = attr->ecommunity->val + (i * 8); - tbit = *pnt; + /* Route Reflector. */ + if (peer->sort == BGP_PEER_IBGP && from + && from->sort == BGP_PEER_IBGP) { + /* Originator ID. */ + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL); + stream_putc(s, BGP_ATTR_ORIGINATOR_ID); + stream_putc(s, 4); + + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) + stream_put_in_addr(s, &attr->originator_id); + else + stream_put_in_addr(s, &from->remote_id); + + /* Cluster list. */ + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL); + stream_putc(s, BGP_ATTR_CLUSTER_LIST); + + if (attr->cluster) { + stream_putc(s, attr->cluster->length + 4); + /* If this peer configuration's parent BGP has + * cluster_id. */ + if (bgp->config & BGP_CONFIG_CLUSTER_ID) + stream_put_in_addr(s, &bgp->cluster_id); + else + stream_put_in_addr(s, &bgp->router_id); + stream_put(s, attr->cluster->list, + attr->cluster->length); + } else { + stream_putc(s, 4); + /* If this peer configuration's parent BGP has + * cluster_id. */ + if (bgp->config & BGP_CONFIG_CLUSTER_ID) + stream_put_in_addr(s, &bgp->cluster_id); + else + stream_put_in_addr(s, &bgp->router_id); + } + } - if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE)) - continue; + /* Extended Communities attribute. */ + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY) + && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) { + if (peer->sort == BGP_PEER_IBGP + || peer->sort == BGP_PEER_CONFED) { + if (attr->ecommunity->size * 8 > 255) { + stream_putc(s, + BGP_ATTR_FLAG_OPTIONAL + | BGP_ATTR_FLAG_TRANS + | BGP_ATTR_FLAG_EXTLEN); + stream_putc(s, BGP_ATTR_EXT_COMMUNITIES); + stream_putw(s, attr->ecommunity->size * 8); + } else { + stream_putc(s, + BGP_ATTR_FLAG_OPTIONAL + | BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_EXT_COMMUNITIES); + stream_putc(s, attr->ecommunity->size * 8); + } + stream_put(s, attr->ecommunity->val, + attr->ecommunity->size * 8); + } else { + u_int8_t *pnt; + int tbit; + int ecom_tr_size = 0; + int i; + + for (i = 0; i < attr->ecommunity->size; i++) { + pnt = attr->ecommunity->val + (i * 8); + tbit = *pnt; + + if (CHECK_FLAG(tbit, + ECOMMUNITY_FLAG_NON_TRANSITIVE)) + continue; + + ecom_tr_size++; + } + + if (ecom_tr_size) { + if (ecom_tr_size * 8 > 255) { + stream_putc( + s, + BGP_ATTR_FLAG_OPTIONAL + | BGP_ATTR_FLAG_TRANS + | BGP_ATTR_FLAG_EXTLEN); + stream_putc(s, + BGP_ATTR_EXT_COMMUNITIES); + stream_putw(s, ecom_tr_size * 8); + } else { + stream_putc( + s, + BGP_ATTR_FLAG_OPTIONAL + | BGP_ATTR_FLAG_TRANS); + stream_putc(s, + BGP_ATTR_EXT_COMMUNITIES); + stream_putc(s, ecom_tr_size * 8); + } + + for (i = 0; i < attr->ecommunity->size; i++) { + pnt = attr->ecommunity->val + (i * 8); + tbit = *pnt; + + if (CHECK_FLAG( + tbit, + ECOMMUNITY_FLAG_NON_TRANSITIVE)) + continue; + + stream_put(s, pnt, 8); + } + } + } + } - stream_put (s, pnt, 8); + /* Label index attribute. */ + if (safi == SAFI_LABELED_UNICAST) { + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) { + u_int32_t label_index; + + label_index = attr->label_index; + + if (label_index != BGP_INVALID_LABEL_INDEX) { + stream_putc(s, + BGP_ATTR_FLAG_OPTIONAL + | BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_PREFIX_SID); + stream_putc(s, 10); + stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX); + stream_putw(s, + BGP_PREFIX_SID_LABEL_INDEX_LENGTH); + stream_putc(s, 0); // reserved + stream_putw(s, 0); // flags + stream_putl(s, label_index); + } } - } - } - } - - /* Label index attribute. */ - if (safi == SAFI_LABELED_UNICAST) - { - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID)) - { - u_int32_t label_index; - - label_index = attr->label_index; - - if (label_index != BGP_INVALID_LABEL_INDEX) - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_PREFIX_SID); - stream_putc (s, 10); - stream_putc (s, BGP_PREFIX_SID_LABEL_INDEX); - stream_putw (s, BGP_PREFIX_SID_LABEL_INDEX_LENGTH); - stream_putc (s, 0); // reserved - stream_putw (s, 0); // flags - stream_putl (s, label_index); - } - } - } - - if ( send_as4_path ) - { - /* If the peer is NOT As4 capable, AND */ - /* there are ASnums > 65535 in path THEN - * give out AS4_PATH */ - - /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET - * path segments! - * Hm, I wonder... confederation things *should* only be at - * the beginning of an aspath, right? Then we should use - * aspath_delete_confed_seq for this, because it is already - * there! (JK) - * Folks, talk to me: what is reasonable here!? - */ - aspath = aspath_delete_confed_seq (aspath); - - stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN); - stream_putc (s, BGP_ATTR_AS4_PATH); - aspath_sizep = stream_get_endp (s); - stream_putw (s, 0); - stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1)); - } - - if (aspath != attr->aspath) - aspath_free (aspath); - - if ( send_as4_aggregator ) - { - /* send AS4_AGGREGATOR, at this place */ - /* this section of code moved here in order to ensure the correct - * *ascending* order of attributes - */ - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_AS4_AGGREGATOR); - stream_putc (s, 8); - stream_putl (s, attr->aggregator_as); - stream_put_ipv4 (s, attr->aggregator_addr.s_addr); - } - - if (((afi == AFI_IP || afi == AFI_IP6) && - (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN)) || - (afi == AFI_L2VPN && safi == SAFI_EVPN)) - { - /* Tunnel Encap attribute */ - bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP); + } + + if (send_as4_path) { + /* If the peer is NOT As4 capable, AND */ + /* there are ASnums > 65535 in path THEN + * give out AS4_PATH */ + + /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET + * path segments! + * Hm, I wonder... confederation things *should* only be at + * the beginning of an aspath, right? Then we should use + * aspath_delete_confed_seq for this, because it is already + * there! (JK) + * Folks, talk to me: what is reasonable here!? + */ + aspath = aspath_delete_confed_seq(aspath); + + stream_putc(s, + BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL + | BGP_ATTR_FLAG_EXTLEN); + stream_putc(s, BGP_ATTR_AS4_PATH); + aspath_sizep = stream_get_endp(s); + stream_putw(s, 0); + stream_putw_at(s, aspath_sizep, aspath_put(s, aspath, 1)); + } + + if (aspath != attr->aspath) + aspath_free(aspath); + + if (send_as4_aggregator) { + /* send AS4_AGGREGATOR, at this place */ + /* this section of code moved here in order to ensure the + * correct + * *ascending* order of attributes + */ + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_AS4_AGGREGATOR); + stream_putc(s, 8); + stream_putl(s, attr->aggregator_as); + stream_put_ipv4(s, attr->aggregator_addr.s_addr); + } + + if (((afi == AFI_IP || afi == AFI_IP6) + && (safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN)) + || (afi == AFI_L2VPN && safi == SAFI_EVPN)) { + /* Tunnel Encap attribute */ + bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP); #if ENABLE_BGP_VNC - /* VNC attribute */ - bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_VNC); + /* VNC attribute */ + bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_VNC); #endif - } + } - /* Unknown transit attribute. */ - if (attr->transit) - stream_put (s, attr->transit->val, attr->transit->length); + /* Unknown transit attribute. */ + if (attr->transit) + stream_put(s, attr->transit->val, attr->transit->length); - /* Return total size of attribute. */ - return stream_get_endp (s) - cp; + /* Return total size of attribute. */ + return stream_get_endp(s) - cp; } -size_t -bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi) +size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi, safi_t safi) { - unsigned long attrlen_pnt; - iana_afi_t pkt_afi; - safi_t pkt_safi; + unsigned long attrlen_pnt; + iana_afi_t pkt_afi; + safi_t pkt_safi; - /* Set extended bit always to encode the attribute length as 2 bytes */ - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN); - stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI); + /* Set extended bit always to encode the attribute length as 2 bytes */ + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_EXTLEN); + stream_putc(s, BGP_ATTR_MP_UNREACH_NLRI); - attrlen_pnt = stream_get_endp (s); - stream_putw (s, 0); /* Length of this attribute. */ + attrlen_pnt = stream_get_endp(s); + stream_putw(s, 0); /* Length of this attribute. */ - /* Convert AFI, SAFI to values for packet. */ - bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); + /* Convert AFI, SAFI to values for packet. */ + bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi); - stream_putw (s, pkt_afi); - stream_putc (s, pkt_safi); + stream_putw(s, pkt_afi); + stream_putc(s, pkt_safi); - return attrlen_pnt; + return attrlen_pnt; } -void -bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p, - afi_t afi, safi_t safi, struct prefix_rd *prd, - mpls_label_t *label, int addpath_encode, - u_int32_t addpath_tx_id, struct attr *attr) +void bgp_packet_mpunreach_prefix(struct stream *s, struct prefix *p, afi_t afi, + safi_t safi, struct prefix_rd *prd, + mpls_label_t *label, int addpath_encode, + u_int32_t addpath_tx_id, struct attr *attr) { - u_char wlabel[3] = {0x80, 0x00, 0x00}; + u_char wlabel[3] = {0x80, 0x00, 0x00}; - if (safi == SAFI_LABELED_UNICAST) - label = (mpls_label_t *) wlabel; + if (safi == SAFI_LABELED_UNICAST) + label = (mpls_label_t *)wlabel; - return bgp_packet_mpattr_prefix (s, afi, safi, p, prd, - label, - addpath_encode, addpath_tx_id, attr); + return bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label, + addpath_encode, addpath_tx_id, attr); } -void -bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt) +void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt) { - bgp_packet_mpattr_end (s, attrlen_pnt); + bgp_packet_mpattr_end(s, attrlen_pnt); } /* Initialization of attribute. */ -void -bgp_attr_init (void) +void bgp_attr_init(void) { - aspath_init (); - attrhash_init (); - community_init (); - ecommunity_init (); - lcommunity_init (); - cluster_init (); - transit_init (); - encap_init (); + aspath_init(); + attrhash_init(); + community_init(); + ecommunity_init(); + lcommunity_init(); + cluster_init(); + transit_init(); + encap_init(); } -void -bgp_attr_finish (void) +void bgp_attr_finish(void) { - aspath_finish (); - attrhash_finish (); - community_finish (); - ecommunity_finish (); - lcommunity_finish (); - cluster_finish (); - transit_finish (); - encap_finish (); + aspath_finish(); + attrhash_finish(); + community_finish(); + ecommunity_finish(); + lcommunity_finish(); + cluster_finish(); + transit_finish(); + encap_finish(); } /* Make attribute packet. */ -void -bgp_dump_routes_attr (struct stream *s, struct attr *attr, - struct prefix *prefix) -{ - unsigned long cp; - unsigned long len; - size_t aspath_lenp; - struct aspath *aspath; - int addpath_encode = 0; - u_int32_t addpath_tx_id = 0; - - /* Remember current pointer. */ - cp = stream_get_endp (s); - - /* Place holder of length. */ - stream_putw (s, 0); - - /* Origin attribute. */ - stream_putc (s, BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_ORIGIN); - stream_putc (s, 1); - stream_putc (s, attr->origin); - - aspath = attr->aspath; - - stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); - stream_putc (s, BGP_ATTR_AS_PATH); - aspath_lenp = stream_get_endp (s); - stream_putw (s, 0); - - stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1)); - - /* Nexthop attribute. */ - /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */ - if(prefix != NULL && prefix->family != AF_INET6) - { - stream_putc (s, BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_NEXT_HOP); - stream_putc (s, 4); - stream_put_ipv4 (s, attr->nexthop.s_addr); - } - - /* MED attribute. */ - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); - stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC); - stream_putc (s, 4); - stream_putl (s, attr->med); - } - - /* Local preference. */ - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) - { - stream_putc (s, BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_LOCAL_PREF); - stream_putc (s, 4); - stream_putl (s, attr->local_pref); - } - - /* Atomic aggregate. */ - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE)) - { - stream_putc (s, BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE); - stream_putc (s, 0); - } - - /* Aggregator. */ - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR)) - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_AGGREGATOR); - stream_putc (s, 8); - stream_putl (s, attr->aggregator_as); - stream_put_ipv4 (s, attr->aggregator_addr.s_addr); - } - - /* Community attribute. */ - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)) - { - if (attr->community->size * 4 > 255) - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); - stream_putc (s, BGP_ATTR_COMMUNITIES); - stream_putw (s, attr->community->size * 4); +void bgp_dump_routes_attr(struct stream *s, struct attr *attr, + struct prefix *prefix) +{ + unsigned long cp; + unsigned long len; + size_t aspath_lenp; + struct aspath *aspath; + int addpath_encode = 0; + u_int32_t addpath_tx_id = 0; + + /* Remember current pointer. */ + cp = stream_get_endp(s); + + /* Place holder of length. */ + stream_putw(s, 0); + + /* Origin attribute. */ + stream_putc(s, BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_ORIGIN); + stream_putc(s, 1); + stream_putc(s, attr->origin); + + aspath = attr->aspath; + + stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_EXTLEN); + stream_putc(s, BGP_ATTR_AS_PATH); + aspath_lenp = stream_get_endp(s); + stream_putw(s, 0); + + stream_putw_at(s, aspath_lenp, aspath_put(s, aspath, 1)); + + /* Nexthop attribute. */ + /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */ + if (prefix != NULL && prefix->family != AF_INET6) { + stream_putc(s, BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_NEXT_HOP); + stream_putc(s, 4); + stream_put_ipv4(s, attr->nexthop.s_addr); } - else - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_COMMUNITIES); - stream_putc (s, attr->community->size * 4); - } - stream_put (s, attr->community->val, attr->community->size * 4); - } - - /* Large Community attribute. */ - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES)) - { - if (attr->lcommunity->size * 12 > 255) - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); - stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES); - stream_putw (s, attr->lcommunity->size * 12); - } - else - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES); - stream_putc (s, attr->lcommunity->size * 12); - } - - stream_put (s, attr->lcommunity->val, attr->lcommunity->size * 12); - } - - /* Add a MP_NLRI attribute to dump the IPv6 next hop */ - if (prefix != NULL && prefix->family == AF_INET6 && - (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL || - attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) ) - { - int sizep; - - stream_putc(s, BGP_ATTR_FLAG_OPTIONAL); - stream_putc(s, BGP_ATTR_MP_REACH_NLRI); - sizep = stream_get_endp (s); - - /* MP header */ - stream_putc (s, 0); /* Marker: Attribute length. */ - stream_putw(s, AFI_IP6); /* AFI */ - stream_putc(s, SAFI_UNICAST); /* SAFI */ - - /* Next hop */ - stream_putc(s, attr->mp_nexthop_len); - stream_put(s, &attr->mp_nexthop_global, IPV6_MAX_BYTELEN); - if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) - stream_put(s, &attr->mp_nexthop_local, IPV6_MAX_BYTELEN); - - /* SNPA */ - stream_putc(s, 0); - - /* Prefix */ - stream_put_prefix_addpath (s, prefix, addpath_encode, addpath_tx_id); - - /* Set MP attribute length. */ - stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1); - } - - /* Prefix SID */ - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID)) - { - if (attr->label_index != BGP_INVALID_LABEL_INDEX) - { - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_PREFIX_SID); - stream_putc (s, 10); - stream_putc (s, BGP_PREFIX_SID_LABEL_INDEX); - stream_putc (s, BGP_PREFIX_SID_LABEL_INDEX_LENGTH); - stream_putc (s, 0); // reserved - stream_putw (s, 0); // flags - stream_putl (s, attr->label_index); - } - } - - /* Return total size of attribute. */ - len = stream_get_endp (s) - cp - 2; - stream_putw_at (s, cp, len); + + /* MED attribute. */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) { + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL); + stream_putc(s, BGP_ATTR_MULTI_EXIT_DISC); + stream_putc(s, 4); + stream_putl(s, attr->med); + } + + /* Local preference. */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) { + stream_putc(s, BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_LOCAL_PREF); + stream_putc(s, 4); + stream_putl(s, attr->local_pref); + } + + /* Atomic aggregate. */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) { + stream_putc(s, BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_ATOMIC_AGGREGATE); + stream_putc(s, 0); + } + + /* Aggregator. */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)) { + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_AGGREGATOR); + stream_putc(s, 8); + stream_putl(s, attr->aggregator_as); + stream_put_ipv4(s, attr->aggregator_addr.s_addr); + } + + /* Community attribute. */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) { + if (attr->community->size * 4 > 255) { + stream_putc(s, + BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS + | BGP_ATTR_FLAG_EXTLEN); + stream_putc(s, BGP_ATTR_COMMUNITIES); + stream_putw(s, attr->community->size * 4); + } else { + stream_putc(s, + BGP_ATTR_FLAG_OPTIONAL + | BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_COMMUNITIES); + stream_putc(s, attr->community->size * 4); + } + stream_put(s, attr->community->val, attr->community->size * 4); + } + + /* Large Community attribute. */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) { + if (attr->lcommunity->size * 12 > 255) { + stream_putc(s, + BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS + | BGP_ATTR_FLAG_EXTLEN); + stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES); + stream_putw(s, attr->lcommunity->size * 12); + } else { + stream_putc(s, + BGP_ATTR_FLAG_OPTIONAL + | BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES); + stream_putc(s, attr->lcommunity->size * 12); + } + + stream_put(s, attr->lcommunity->val, + attr->lcommunity->size * 12); + } + + /* Add a MP_NLRI attribute to dump the IPv6 next hop */ + if (prefix != NULL && prefix->family == AF_INET6 + && (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL + || attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)) { + int sizep; + + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL); + stream_putc(s, BGP_ATTR_MP_REACH_NLRI); + sizep = stream_get_endp(s); + + /* MP header */ + stream_putc(s, 0); /* Marker: Attribute length. */ + stream_putw(s, AFI_IP6); /* AFI */ + stream_putc(s, SAFI_UNICAST); /* SAFI */ + + /* Next hop */ + stream_putc(s, attr->mp_nexthop_len); + stream_put(s, &attr->mp_nexthop_global, IPV6_MAX_BYTELEN); + if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) + stream_put(s, &attr->mp_nexthop_local, + IPV6_MAX_BYTELEN); + + /* SNPA */ + stream_putc(s, 0); + + /* Prefix */ + stream_put_prefix_addpath(s, prefix, addpath_encode, + addpath_tx_id); + + /* Set MP attribute length. */ + stream_putc_at(s, sizep, (stream_get_endp(s) - sizep) - 1); + } + + /* Prefix SID */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) { + if (attr->label_index != BGP_INVALID_LABEL_INDEX) { + stream_putc(s, + BGP_ATTR_FLAG_OPTIONAL + | BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_PREFIX_SID); + stream_putc(s, 10); + stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX); + stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX_LENGTH); + stream_putc(s, 0); // reserved + stream_putw(s, 0); // flags + stream_putl(s, attr->label_index); + } + } + + /* Return total size of attribute. */ + len = stream_get_endp(s) - cp - 2; + stream_putw_at(s, cp, len); } diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 99c6a6b79..324813c08 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -1,4 +1,4 @@ -/* BGP attributes. +/* BGP attributes. * Copyright (C) 1996, 97, 98 Kunihiro Ishiguro * * This file is part of GNU Zebra. @@ -27,15 +27,14 @@ /* Simple bit mapping. */ #define BITMAP_NBBY 8 -#define SET_BITMAP(MAP, NUM) \ - SET_FLAG (MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY)) +#define SET_BITMAP(MAP, NUM) \ + SET_FLAG(MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY)) -#define CHECK_BITMAP(MAP, NUM) \ - CHECK_FLAG (MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY)) +#define CHECK_BITMAP(MAP, NUM) \ + CHECK_FLAG(MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY)) #define BGP_MED_MAX UINT32_MAX - /* BGP Attribute type range. */ #define BGP_ATTR_TYPE_RANGE 256 #define BGP_ATTR_BITMAP_SIZE (BGP_ATTR_TYPE_RANGE / BITMAP_NBBY) @@ -68,12 +67,12 @@ #define BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH 6 struct bgp_attr_encap_subtlv { - struct bgp_attr_encap_subtlv *next; /* for chaining */ - /* Reference count of this attribute. */ - unsigned long refcnt; - uint16_t type; - uint16_t length; - uint8_t value[1]; /* will be extended */ + struct bgp_attr_encap_subtlv *next; /* for chaining */ + /* Reference count of this attribute. */ + unsigned long refcnt; + uint16_t type; + uint16_t length; + uint8_t value[1]; /* will be extended */ }; #if ENABLE_BGP_VNC @@ -81,110 +80,108 @@ struct bgp_attr_encap_subtlv { * old rfp<->rfapi representation */ struct bgp_tea_options { - struct bgp_tea_options *next; - uint8_t options_count; - uint16_t options_length; /* each TLV may be 256 in length */ - uint8_t type; - uint8_t length; - void *value; /* pointer to data */ + struct bgp_tea_options *next; + uint8_t options_count; + uint16_t options_length; /* each TLV may be 256 in length */ + uint8_t type; + uint8_t length; + void *value; /* pointer to data */ }; #endif /* Overlay Index Info */ -struct overlay_index -{ - struct eth_segment_id eth_s_id; - union gw_addr gw_ip; +struct overlay_index { + struct eth_segment_id eth_s_id; + union gw_addr gw_ip; }; /* BGP core attribute structure. */ -struct attr -{ - /* AS Path structure */ - struct aspath *aspath; - - /* Community structure */ - struct community *community; - - /* Reference count of this attribute. */ - unsigned long refcnt; - - /* Flag of attribute is set or not. */ - uint64_t flag; - - /* Apart from in6_addr, the remaining static attributes */ - struct in_addr nexthop; - u_int32_t med; - u_int32_t local_pref; - ifindex_t nh_ifindex; - - /* Path origin attribute */ - u_char origin; - - /* has the route-map changed any attribute? - Used on the peer outbound side. */ - u_int32_t rmap_change_flags; - - /* Multi-Protocol Nexthop, AFI IPv6 */ - struct in6_addr mp_nexthop_global; - struct in6_addr mp_nexthop_local; - - /* Extended Communities attribute. */ - struct ecommunity *ecommunity; - - /* Large Communities attribute. */ - struct lcommunity *lcommunity; - - /* Route-Reflector Cluster attribute */ - struct cluster_list *cluster; - - /* Unknown transitive attribute. */ - struct transit *transit; - - struct in_addr mp_nexthop_global_in; - - /* Aggregator Router ID attribute */ - struct in_addr aggregator_addr; - - /* Route Reflector Originator attribute */ - struct in_addr originator_id; - - /* Local weight, not actually an attribute */ - u_int32_t weight; - - /* Aggregator ASN */ - as_t aggregator_as; - - /* MP Nexthop length */ - u_char mp_nexthop_len; - - /* MP Nexthop preference */ - u_char mp_nexthop_prefer_global; - - /* Static MAC for EVPN */ - u_char sticky; - - /* route tag */ - route_tag_t tag; - - /* Label index */ - u_int32_t label_index; - - /* MPLS label */ - mpls_label_t label; - - uint16_t encap_tunneltype; /* grr */ - struct bgp_attr_encap_subtlv *encap_subtlvs; /* rfc5512 */ +struct attr { + /* AS Path structure */ + struct aspath *aspath; + + /* Community structure */ + struct community *community; + + /* Reference count of this attribute. */ + unsigned long refcnt; + + /* Flag of attribute is set or not. */ + uint64_t flag; + + /* Apart from in6_addr, the remaining static attributes */ + struct in_addr nexthop; + u_int32_t med; + u_int32_t local_pref; + ifindex_t nh_ifindex; + + /* Path origin attribute */ + u_char origin; + + /* has the route-map changed any attribute? + Used on the peer outbound side. */ + u_int32_t rmap_change_flags; + + /* Multi-Protocol Nexthop, AFI IPv6 */ + struct in6_addr mp_nexthop_global; + struct in6_addr mp_nexthop_local; + + /* Extended Communities attribute. */ + struct ecommunity *ecommunity; + + /* Large Communities attribute. */ + struct lcommunity *lcommunity; + + /* Route-Reflector Cluster attribute */ + struct cluster_list *cluster; + + /* Unknown transitive attribute. */ + struct transit *transit; + + struct in_addr mp_nexthop_global_in; + + /* Aggregator Router ID attribute */ + struct in_addr aggregator_addr; + + /* Route Reflector Originator attribute */ + struct in_addr originator_id; + + /* Local weight, not actually an attribute */ + u_int32_t weight; + + /* Aggregator ASN */ + as_t aggregator_as; + + /* MP Nexthop length */ + u_char mp_nexthop_len; + + /* MP Nexthop preference */ + u_char mp_nexthop_prefer_global; + + /* Static MAC for EVPN */ + u_char sticky; + + /* route tag */ + route_tag_t tag; + + /* Label index */ + u_int32_t label_index; + + /* MPLS label */ + mpls_label_t label; + + uint16_t encap_tunneltype; /* grr */ + struct bgp_attr_encap_subtlv *encap_subtlvs; /* rfc5512 */ #if ENABLE_BGP_VNC - struct bgp_attr_encap_subtlv *vnc_subtlvs; /* VNC-specific */ + struct bgp_attr_encap_subtlv *vnc_subtlvs; /* VNC-specific */ #endif - /* EVPN */ - struct overlay_index evpn_overlay; + /* EVPN */ + struct overlay_index evpn_overlay; - /* EVPN MAC Mobility sequence number, if any. */ - u_int32_t mm_seqnum; + /* EVPN MAC Mobility sequence number, if any. */ + u_int32_t mm_seqnum; }; /* rmap_change_flags definition */ @@ -197,97 +194,97 @@ struct attr #define BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED (1 << 6) /* Router Reflector related structure. */ -struct cluster_list -{ - unsigned long refcnt; - int length; - struct in_addr *list; +struct cluster_list { + unsigned long refcnt; + int length; + struct in_addr *list; }; /* Unknown transit attribute. */ -struct transit -{ - unsigned long refcnt; - int length; - u_char *val; +struct transit { + unsigned long refcnt; + int length; + u_char *val; }; #define ATTR_FLAG_BIT(X) (1ULL << ((X) - 1)) -#define BGP_CLUSTER_LIST_LENGTH(attr) \ - (((attr)->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) ? \ - (attr)->cluster->length : 0) +#define BGP_CLUSTER_LIST_LENGTH(attr) \ + (((attr)->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) \ + ? (attr)->cluster->length \ + : 0) typedef enum { - BGP_ATTR_PARSE_PROCEED = 0, - BGP_ATTR_PARSE_ERROR = -1, - BGP_ATTR_PARSE_WITHDRAW = -2, + BGP_ATTR_PARSE_PROCEED = 0, + BGP_ATTR_PARSE_ERROR = -1, + BGP_ATTR_PARSE_WITHDRAW = -2, - /* only used internally, send notify + convert to BGP_ATTR_PARSE_ERROR */ - BGP_ATTR_PARSE_ERROR_NOTIFYPLS = -3, + /* only used internally, send notify + convert to BGP_ATTR_PARSE_ERROR + */ + BGP_ATTR_PARSE_ERROR_NOTIFYPLS = -3, } bgp_attr_parse_ret_t; struct bpacket_attr_vec_arr; /* Prototypes. */ -extern void bgp_attr_init (void); -extern void bgp_attr_finish (void); -extern bgp_attr_parse_ret_t bgp_attr_parse (struct peer *, struct attr *, - bgp_size_t, struct bgp_nlri *, - struct bgp_nlri *); -extern void bgp_attr_dup (struct attr *, struct attr *); -extern void bgp_attr_deep_dup (struct attr *, struct attr *); -extern void bgp_attr_deep_free (struct attr *); -extern struct attr *bgp_attr_intern (struct attr *attr); -extern struct attr *bgp_attr_refcount (struct attr *attr); -extern void bgp_attr_unintern_sub (struct attr *); -extern void bgp_attr_unintern (struct attr **); -extern void bgp_attr_flush (struct attr *); -extern struct attr *bgp_attr_default_set (struct attr *attr, u_char); -extern struct attr *bgp_attr_aggregate_intern (struct bgp *, u_char, - struct aspath *, - struct community *, int as_set, u_char); -extern bgp_size_t bgp_packet_attribute (struct bgp *bgp, struct peer *, - struct stream *, struct attr *, - struct bpacket_attr_vec_arr *vecarr, - struct prefix *, afi_t, safi_t, - struct peer *, struct prefix_rd *, - mpls_label_t *, int, u_int32_t); -extern void bgp_dump_routes_attr (struct stream *, struct attr *, - struct prefix *); -extern int attrhash_cmp (const void *, const void *); -extern unsigned int attrhash_key_make (void *); -extern void attr_show_all (struct vty *); -extern unsigned long int attr_count (void); -extern unsigned long int attr_unknown_count (void); +extern void bgp_attr_init(void); +extern void bgp_attr_finish(void); +extern bgp_attr_parse_ret_t bgp_attr_parse(struct peer *, struct attr *, + bgp_size_t, struct bgp_nlri *, + struct bgp_nlri *); +extern void bgp_attr_dup(struct attr *, struct attr *); +extern void bgp_attr_deep_dup(struct attr *, struct attr *); +extern void bgp_attr_deep_free(struct attr *); +extern struct attr *bgp_attr_intern(struct attr *attr); +extern struct attr *bgp_attr_refcount(struct attr *attr); +extern void bgp_attr_unintern_sub(struct attr *); +extern void bgp_attr_unintern(struct attr **); +extern void bgp_attr_flush(struct attr *); +extern struct attr *bgp_attr_default_set(struct attr *attr, u_char); +extern struct attr *bgp_attr_aggregate_intern(struct bgp *, u_char, + struct aspath *, + struct community *, int as_set, + u_char); +extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *, + struct stream *, struct attr *, + struct bpacket_attr_vec_arr *vecarr, + struct prefix *, afi_t, safi_t, + struct peer *, struct prefix_rd *, + mpls_label_t *, int, u_int32_t); +extern void bgp_dump_routes_attr(struct stream *, struct attr *, + struct prefix *); +extern int attrhash_cmp(const void *, const void *); +extern unsigned int attrhash_key_make(void *); +extern void attr_show_all(struct vty *); +extern unsigned long int attr_count(void); +extern unsigned long int attr_unknown_count(void); /* Cluster list prototypes. */ -extern int cluster_loop_check (struct cluster_list *, struct in_addr); -extern void cluster_unintern (struct cluster_list *); +extern int cluster_loop_check(struct cluster_list *, struct in_addr); +extern void cluster_unintern(struct cluster_list *); /* Transit attribute prototypes. */ -void transit_unintern (struct transit *); +void transit_unintern(struct transit *); /* Below exported for unit-test purposes only */ struct bgp_attr_parser_args { - struct peer *peer; - bgp_size_t length; /* attribute data length; */ - bgp_size_t total; /* total length, inc header */ - struct attr *attr; - u_int8_t type; - u_int8_t flags; - u_char *startp; + struct peer *peer; + bgp_size_t length; /* attribute data length; */ + bgp_size_t total; /* total length, inc header */ + struct attr *attr; + u_int8_t type; + u_int8_t flags; + u_char *startp; }; -extern int bgp_mp_reach_parse (struct bgp_attr_parser_args *args, - struct bgp_nlri *); -extern int bgp_mp_unreach_parse (struct bgp_attr_parser_args *args, - struct bgp_nlri *); +extern int bgp_mp_reach_parse(struct bgp_attr_parser_args *args, + struct bgp_nlri *); +extern int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args, + struct bgp_nlri *); extern struct bgp_attr_encap_subtlv * encap_tlv_dup(struct bgp_attr_encap_subtlv *orig); -extern void -bgp_attr_flush_encap(struct attr *attr); +extern void bgp_attr_flush_encap(struct attr *attr); /** * Set of functions to encode MP_REACH_NLRI and MP_UNREACH_NLRI attributes. @@ -296,41 +293,44 @@ bgp_attr_flush_encap(struct attr *attr); * finally the _end() function. */ extern size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, - afi_t afi, safi_t safi, - struct bpacket_attr_vec_arr *vecarr, + afi_t afi, safi_t safi, + struct bpacket_attr_vec_arr *vecarr, struct attr *attr); extern void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi, struct prefix *p, struct prefix_rd *prd, mpls_label_t *label, int addpath_encode, - u_int32_t addpath_tx_id, - struct attr *); + u_int32_t addpath_tx_id, struct attr *); extern size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi, - struct prefix *p); + struct prefix *p); extern void bgp_packet_mpattr_end(struct stream *s, size_t sizep); -extern size_t bgp_packet_mpunreach_start (struct stream *s, afi_t afi, - safi_t safi); -extern void bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p, - afi_t afi, safi_t safi, struct prefix_rd *prd, - mpls_label_t *, int, u_int32_t, struct attr *); -extern void bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt); +extern size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi, + safi_t safi); +extern void bgp_packet_mpunreach_prefix(struct stream *s, struct prefix *p, + afi_t afi, safi_t safi, + struct prefix_rd *prd, mpls_label_t *, + int, u_int32_t, struct attr *); +extern void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt); -static inline int -bgp_rmap_nhop_changed(u_int32_t out_rmap_flags, u_int32_t in_rmap_flags) +static inline int bgp_rmap_nhop_changed(u_int32_t out_rmap_flags, + u_int32_t in_rmap_flags) { - return ((CHECK_FLAG(out_rmap_flags, BATTR_RMAP_NEXTHOP_PEER_ADDRESS) || - CHECK_FLAG(out_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED) || - CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV4_NHOP_CHANGED) || - CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED) || - CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED) || - CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_LL_NHOP_CHANGED) || - CHECK_FLAG(in_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED)) ? 1 : 0); + return ((CHECK_FLAG(out_rmap_flags, BATTR_RMAP_NEXTHOP_PEER_ADDRESS) + || CHECK_FLAG(out_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED) + || CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV4_NHOP_CHANGED) + || CHECK_FLAG(out_rmap_flags, + BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED) + || CHECK_FLAG(out_rmap_flags, + BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED) + || CHECK_FLAG(out_rmap_flags, BATTR_RMAP_IPV6_LL_NHOP_CHANGED) + || CHECK_FLAG(in_rmap_flags, BATTR_RMAP_NEXTHOP_UNCHANGED)) + ? 1 + : 0); } -static inline u_int32_t -mac_mobility_seqnum (struct attr *attr) +static inline u_int32_t mac_mobility_seqnum(struct attr *attr) { - return (attr) ? attr->mm_seqnum : 0; + return (attr) ? attr->mm_seqnum : 0; } #endif /* _QUAGGA_BGP_ATTR_H */ diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c index aa175bcf5..cd6b87b29 100644 --- a/bgpd/bgp_attr_evpn.c +++ b/bgpd/bgp_attr_evpn.c @@ -37,16 +37,16 @@ void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac) { - struct ecommunity_val routermac_ecom; - - memset(&routermac_ecom, 0, sizeof(struct ecommunity_val)); - routermac_ecom.val[0] = ECOMMUNITY_ENCODE_EVPN; - routermac_ecom.val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC; - memcpy(&routermac_ecom.val[2], routermac->octet, ETHER_ADDR_LEN); - if (!attr->ecommunity) - attr->ecommunity = ecommunity_new(); - ecommunity_add_val(attr->ecommunity, &routermac_ecom); - ecommunity_str (attr->ecommunity); + struct ecommunity_val routermac_ecom; + + memset(&routermac_ecom, 0, sizeof(struct ecommunity_val)); + routermac_ecom.val[0] = ECOMMUNITY_ENCODE_EVPN; + routermac_ecom.val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC; + memcpy(&routermac_ecom.val[2], routermac->octet, ETHER_ADDR_LEN); + if (!attr->ecommunity) + attr->ecommunity = ecommunity_new(); + ecommunity_add_val(attr->ecommunity, &routermac_ecom); + ecommunity_str(attr->ecommunity); } /* converts to an esi @@ -56,138 +56,136 @@ void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac) */ int str2esi(const char *str, struct eth_segment_id *id) { - unsigned int a[ESI_LEN]; - int i; - - if (!str) - return 0; - if (sscanf (str, "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x", - a + 0, a + 1, a + 2, a + 3, a + 4, a + 5, - a + 6, a + 7, a + 8, a + 9) != ESI_LEN) - { - /* error in incoming str length */ - return 0; - } - /* valid mac address */ - if (!id) - return 1; - for (i = 0; i < ESI_LEN; ++i) - id->val[i] = a[i] & 0xff; - return 1; + unsigned int a[ESI_LEN]; + int i; + + if (!str) + return 0; + if (sscanf(str, "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x", a + 0, a + 1, + a + 2, a + 3, a + 4, a + 5, a + 6, a + 7, a + 8, a + 9) + != ESI_LEN) { + /* error in incoming str length */ + return 0; + } + /* valid mac address */ + if (!id) + return 1; + for (i = 0; i < ESI_LEN; ++i) + id->val[i] = a[i] & 0xff; + return 1; } char *esi2str(struct eth_segment_id *id) { - char *ptr; - u_char *val; + char *ptr; + u_char *val; - if (!id) - return NULL; + if (!id) + return NULL; - val = id->val; - ptr = (char *)XMALLOC(MTYPE_TMP, (ESI_LEN * 2 + ESI_LEN - 1 + 1) * sizeof(char)); + val = id->val; + ptr = (char *)XMALLOC(MTYPE_TMP, + (ESI_LEN * 2 + ESI_LEN - 1 + 1) * sizeof(char)); - snprintf(ptr, (ESI_LEN * 2 + ESI_LEN - 1 + 1), - "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", - val[0], val[1], val[2], val[3], val[4], - val[5], val[6], val[7], val[8], val[9]); + snprintf(ptr, (ESI_LEN * 2 + ESI_LEN - 1 + 1), + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", val[0], + val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], + val[9]); - return ptr; + return ptr; } char *ecom_mac2str(char *ecom_mac) { - char *en; + char *en; - en = ecom_mac; - en += 2; + en = ecom_mac; + en += 2; - return prefix_mac2str((struct ethaddr *)en, NULL, 0); + return prefix_mac2str((struct ethaddr *)en, NULL, 0); } /* * Fetch and return the sequence number from MAC Mobility extended * community, if present, else 0. */ -u_int32_t -bgp_attr_mac_mobility_seqnum (struct attr *attr, u_char *sticky) +u_int32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, u_char *sticky) { - struct ecommunity *ecom; - int i; - u_char flags = 0; - - ecom = attr->ecommunity; - if (!ecom || !ecom->size) - return 0; - - /* If there is a MAC Mobility extended community, return its - * sequence number. - * TODO: RFC is silent on handling of multiple MAC mobility extended - * communities for the same route. We will bail out upon the first - * one. - */ - for (i = 0; i < ecom->size; i++) - { - u_char *pnt; - u_char type, sub_type; - u_int32_t seq_num; - - pnt = (ecom->val + (i * ECOMMUNITY_SIZE)); - type = *pnt++; - sub_type = *pnt++; - if (!(type == ECOMMUNITY_ENCODE_EVPN && - sub_type == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY)) - continue; - flags = *pnt++; - - if (flags & ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY) - *sticky = 1; - else - *sticky = 0; - - pnt++; - seq_num = (*pnt++ << 24); - seq_num |= (*pnt++ << 16); - seq_num |= (*pnt++ << 8); - seq_num |= (*pnt++); - - return seq_num; - } - - return 0; + struct ecommunity *ecom; + int i; + u_char flags = 0; + + ecom = attr->ecommunity; + if (!ecom || !ecom->size) + return 0; + + /* If there is a MAC Mobility extended community, return its + * sequence number. + * TODO: RFC is silent on handling of multiple MAC mobility extended + * communities for the same route. We will bail out upon the first + * one. + */ + for (i = 0; i < ecom->size; i++) { + u_char *pnt; + u_char type, sub_type; + u_int32_t seq_num; + + pnt = (ecom->val + (i * ECOMMUNITY_SIZE)); + type = *pnt++; + sub_type = *pnt++; + if (!(type == ECOMMUNITY_ENCODE_EVPN + && sub_type == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY)) + continue; + flags = *pnt++; + + if (flags & ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY) + *sticky = 1; + else + *sticky = 0; + + pnt++; + seq_num = (*pnt++ << 24); + seq_num |= (*pnt++ << 16); + seq_num |= (*pnt++ << 8); + seq_num |= (*pnt++); + + return seq_num; + } + + return 0; } /* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */ -extern int -bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag, struct prefix *dst) +extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag, + struct prefix *dst) { - struct evpn_addr *p_evpn_p; - struct prefix p2; - struct prefix *src = &p2; - - if (!dst || dst->family == 0) - return -1; - /* store initial prefix in src */ - prefix_copy(src, dst); - memset(dst, 0, sizeof(struct prefix)); - p_evpn_p = &(dst->u.prefix_evpn); - dst->family = AF_ETHERNET; - p_evpn_p->route_type = evpn_type; - if (evpn_type == BGP_EVPN_IP_PREFIX_ROUTE) { - p_evpn_p->eth_tag = eth_tag; - p_evpn_p->ip_prefix_length = p2.prefixlen; - if (src->family == AF_INET) { - SET_IPADDR_V4 (&p_evpn_p->ip); - memcpy(&p_evpn_p->ip.ipaddr_v4, &src->u.prefix4, - sizeof(struct in_addr)); - dst->prefixlen = (u_char) PREFIX_LEN_ROUTE_TYPE_5_IPV4; - } else { - SET_IPADDR_V6 (&p_evpn_p->ip); - memcpy(&p_evpn_p->ip.ipaddr_v6, &src->u.prefix6, - sizeof(struct in6_addr)); - dst->prefixlen = (u_char) PREFIX_LEN_ROUTE_TYPE_5_IPV6; - } - } else - return -1; - return 0; + struct evpn_addr *p_evpn_p; + struct prefix p2; + struct prefix *src = &p2; + + if (!dst || dst->family == 0) + return -1; + /* store initial prefix in src */ + prefix_copy(src, dst); + memset(dst, 0, sizeof(struct prefix)); + p_evpn_p = &(dst->u.prefix_evpn); + dst->family = AF_ETHERNET; + p_evpn_p->route_type = evpn_type; + if (evpn_type == BGP_EVPN_IP_PREFIX_ROUTE) { + p_evpn_p->eth_tag = eth_tag; + p_evpn_p->ip_prefix_length = p2.prefixlen; + if (src->family == AF_INET) { + SET_IPADDR_V4(&p_evpn_p->ip); + memcpy(&p_evpn_p->ip.ipaddr_v4, &src->u.prefix4, + sizeof(struct in_addr)); + dst->prefixlen = (u_char)PREFIX_LEN_ROUTE_TYPE_5_IPV4; + } else { + SET_IPADDR_V6(&p_evpn_p->ip); + memcpy(&p_evpn_p->ip.ipaddr_v6, &src->u.prefix6, + sizeof(struct in6_addr)); + dst->prefixlen = (u_char)PREFIX_LEN_ROUTE_TYPE_5_IPV6; + } + } else + return -1; + return 0; } diff --git a/bgpd/bgp_attr_evpn.h b/bgpd/bgp_attr_evpn.h index 26650ef8b..15d9e126e 100644 --- a/bgpd/bgp_attr_evpn.h +++ b/bgpd/bgp_attr_evpn.h @@ -29,7 +29,6 @@ #define ESI_TYPE_ROUTER 4 /* : */ #define ESI_TYPE_AS 5 /* : */ - #define MAX_ESI {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff} #define ESI_LEN 10 @@ -38,32 +37,30 @@ u_long eth_tag_id; struct attr; -struct eth_segment_id -{ - u_char val[ESI_LEN]; +struct eth_segment_id { + u_char val[ESI_LEN]; }; -union gw_addr -{ - struct in_addr ipv4; - struct in6_addr ipv6; +union gw_addr { + struct in_addr ipv4; + struct in6_addr ipv6; }; -struct bgp_route_evpn -{ - struct eth_segment_id eth_s_id; - union gw_addr gw_ip; +struct bgp_route_evpn { + struct eth_segment_id eth_s_id; + union gw_addr gw_ip; }; extern int str2esi(const char *str, struct eth_segment_id *id); extern char *esi2str(struct eth_segment_id *id); extern char *ecom_mac2str(char *ecom_mac); -extern void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac); +extern void bgp_add_routermac_ecom(struct attr *attr, + struct ethaddr *routermac); extern int bgp_build_evpn_prefix(int type, uint32_t eth_tag, - struct prefix *dst); + struct prefix *dst); -extern u_int32_t -bgp_attr_mac_mobility_seqnum (struct attr *attr, u_char *sticky); +extern u_int32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, + u_char *sticky); -#endif /* _QUAGGA_BGP_ATTR_EVPN_H */ +#endif /* _QUAGGA_BGP_ATTR_EVPN_H */ diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index bb0a0fc63..2e277bfa5 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -43,112 +43,110 @@ extern struct zclient *zclient; /* - * bgp_bfd_peer_group2peer_copy - Copy the BFD information from peer group template + * bgp_bfd_peer_group2peer_copy - Copy the BFD information from peer group + * template * to peer. */ -void -bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer) +void bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer) { - struct bfd_info *bfd_info; - struct bfd_info *conf_bfd_info; + struct bfd_info *bfd_info; + struct bfd_info *conf_bfd_info; - if (!conf->bfd_info) - return; + if (!conf->bfd_info) + return; - conf_bfd_info = (struct bfd_info *)conf->bfd_info; - if (!peer->bfd_info) - peer->bfd_info = bfd_info_create(); + conf_bfd_info = (struct bfd_info *)conf->bfd_info; + if (!peer->bfd_info) + peer->bfd_info = bfd_info_create(); - bfd_info = (struct bfd_info *)peer->bfd_info; + bfd_info = (struct bfd_info *)peer->bfd_info; - /* Copy BFD parameter values */ - bfd_info->required_min_rx = conf_bfd_info->required_min_rx; - bfd_info->desired_min_tx = conf_bfd_info->desired_min_tx; - bfd_info->detect_mult = conf_bfd_info->detect_mult; - bfd_info->type = conf_bfd_info->type; + /* Copy BFD parameter values */ + bfd_info->required_min_rx = conf_bfd_info->required_min_rx; + bfd_info->desired_min_tx = conf_bfd_info->desired_min_tx; + bfd_info->detect_mult = conf_bfd_info->detect_mult; + bfd_info->type = conf_bfd_info->type; } /* - * bgp_bfd_is_peer_multihop - returns whether BFD peer is multi-hop or single hop. + * bgp_bfd_is_peer_multihop - returns whether BFD peer is multi-hop or single + * hop. */ -int -bgp_bfd_is_peer_multihop(struct peer *peer) +int bgp_bfd_is_peer_multihop(struct peer *peer) { - struct bfd_info *bfd_info; + struct bfd_info *bfd_info; - bfd_info = (struct bfd_info *)peer->bfd_info; + bfd_info = (struct bfd_info *)peer->bfd_info; - if (!bfd_info) - return 0; + if (!bfd_info) + return 0; - if((bfd_info->type == BFD_TYPE_MULTIHOP) || - ((peer->sort == BGP_PEER_IBGP) && !peer->shared_network) || - is_ebgp_multihop_configured(peer)) - return 1; - else - return 0; + if ((bfd_info->type == BFD_TYPE_MULTIHOP) + || ((peer->sort == BGP_PEER_IBGP) && !peer->shared_network) + || is_ebgp_multihop_configured(peer)) + return 1; + else + return 0; } /* * bgp_bfd_peer_sendmsg - Format and send a Peer register/Unregister * command to Zebra to be forwarded to BFD */ -static void -bgp_bfd_peer_sendmsg (struct peer *peer, int command) +static void bgp_bfd_peer_sendmsg(struct peer *peer, int command) { - struct bfd_info *bfd_info; - vrf_id_t vrf_id = VRF_DEFAULT; - int multihop; - - bfd_info = (struct bfd_info *)peer->bfd_info; - - if (peer->bgp && (peer->bgp->inst_type == BGP_INSTANCE_TYPE_VRF)) - vrf_id = peer->bgp->vrf_id; - - if (command == ZEBRA_BFD_DEST_DEREGISTER) - { - multihop = CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP); - UNSET_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP); - } - else - { - multihop = bgp_bfd_is_peer_multihop(peer); - if ((command == ZEBRA_BFD_DEST_REGISTER) && multihop) - SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP); - } - - if (peer->su.sa.sa_family == AF_INET) - bfd_peer_sendmsg (zclient, bfd_info, AF_INET, - &peer->su.sin.sin_addr, - (peer->su_local) ? &peer->su_local->sin.sin_addr : NULL, - (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL, - peer->ttl, multihop, command, 1, vrf_id); - else if (peer->su.sa.sa_family == AF_INET6) - bfd_peer_sendmsg (zclient, bfd_info, AF_INET6, - &peer->su.sin6.sin6_addr, - (peer->su_local) ? &peer->su_local->sin6.sin6_addr : NULL, - (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL, - peer->ttl, multihop, command, 1, vrf_id); + struct bfd_info *bfd_info; + vrf_id_t vrf_id = VRF_DEFAULT; + int multihop; + + bfd_info = (struct bfd_info *)peer->bfd_info; + + if (peer->bgp && (peer->bgp->inst_type == BGP_INSTANCE_TYPE_VRF)) + vrf_id = peer->bgp->vrf_id; + + if (command == ZEBRA_BFD_DEST_DEREGISTER) { + multihop = + CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP); + UNSET_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP); + } else { + multihop = bgp_bfd_is_peer_multihop(peer); + if ((command == ZEBRA_BFD_DEST_REGISTER) && multihop) + SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP); + } + + if (peer->su.sa.sa_family == AF_INET) + bfd_peer_sendmsg( + zclient, bfd_info, AF_INET, &peer->su.sin.sin_addr, + (peer->su_local) ? &peer->su_local->sin.sin_addr : NULL, + (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL, + peer->ttl, multihop, command, 1, vrf_id); + else if (peer->su.sa.sa_family == AF_INET6) + bfd_peer_sendmsg( + zclient, bfd_info, AF_INET6, &peer->su.sin6.sin6_addr, + (peer->su_local) ? &peer->su_local->sin6.sin6_addr + : NULL, + (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL, + peer->ttl, multihop, command, 1, vrf_id); } /* * bgp_bfd_register_peer - register a peer with BFD through zebra * for monitoring the peer rechahability. */ -void -bgp_bfd_register_peer (struct peer *peer) +void bgp_bfd_register_peer(struct peer *peer) { - struct bfd_info *bfd_info; + struct bfd_info *bfd_info; - if (!peer->bfd_info) - return; - bfd_info = (struct bfd_info *)peer->bfd_info; + if (!peer->bfd_info) + return; + bfd_info = (struct bfd_info *)peer->bfd_info; - /* Check if BFD is enabled and peer has already been registered with BFD */ - if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) - return; + /* Check if BFD is enabled and peer has already been registered with BFD + */ + if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) + return; - bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER); + bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER); } /** @@ -156,138 +154,132 @@ bgp_bfd_register_peer (struct peer *peer) * for stopping the monitoring of the peer * rechahability. */ -void -bgp_bfd_deregister_peer (struct peer *peer) +void bgp_bfd_deregister_peer(struct peer *peer) { - struct bfd_info *bfd_info; + struct bfd_info *bfd_info; - if (!peer->bfd_info) - return; - bfd_info = (struct bfd_info *)peer->bfd_info; + if (!peer->bfd_info) + return; + bfd_info = (struct bfd_info *)peer->bfd_info; - /* Check if BFD is eanbled and peer has not been registered */ - if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) - return; + /* Check if BFD is eanbled and peer has not been registered */ + if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) + return; - bfd_info->status = BFD_STATUS_DOWN; - bfd_info->last_update = bgp_clock(); + bfd_info->status = BFD_STATUS_DOWN; + bfd_info->last_update = bgp_clock(); - bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER); + bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER); } /* * bgp_bfd_update_peer - update peer with BFD with new BFD paramters * through zebra. */ -static void -bgp_bfd_update_peer (struct peer *peer) +static void bgp_bfd_update_peer(struct peer *peer) { - struct bfd_info *bfd_info; + struct bfd_info *bfd_info; - if (!peer->bfd_info) - return; - bfd_info = (struct bfd_info *)peer->bfd_info; + if (!peer->bfd_info) + return; + bfd_info = (struct bfd_info *)peer->bfd_info; - /* Check if the peer has been registered with BFD*/ - if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) - return; + /* Check if the peer has been registered with BFD*/ + if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) + return; - bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_UPDATE); + bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_UPDATE); } /* * bgp_bfd_update_type - update session type with BFD through zebra. */ -static void -bgp_bfd_update_type (struct peer *peer) +static void bgp_bfd_update_type(struct peer *peer) { - struct bfd_info *bfd_info; - int multihop; - - if (!peer->bfd_info) - return; - bfd_info = (struct bfd_info *)peer->bfd_info; - - /* Check if the peer has been registered with BFD*/ - if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) - return; - - if (bfd_info->type == BFD_TYPE_NOT_CONFIGURED) - { - multihop = bgp_bfd_is_peer_multihop(peer); - if ((multihop && !CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP)) || - (!multihop && CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP))) - { - bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER); - bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER); - } - } - else - { - if ((bfd_info->type == BFD_TYPE_MULTIHOP && - !CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP)) || - (bfd_info->type == BFD_TYPE_SINGLEHOP && - CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP))) - { - bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER); - bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER); - } - } + struct bfd_info *bfd_info; + int multihop; + + if (!peer->bfd_info) + return; + bfd_info = (struct bfd_info *)peer->bfd_info; + + /* Check if the peer has been registered with BFD*/ + if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) + return; + + if (bfd_info->type == BFD_TYPE_NOT_CONFIGURED) { + multihop = bgp_bfd_is_peer_multihop(peer); + if ((multihop + && !CHECK_FLAG(bfd_info->flags, + BFD_FLAG_BFD_TYPE_MULTIHOP)) + || (!multihop && CHECK_FLAG(bfd_info->flags, + BFD_FLAG_BFD_TYPE_MULTIHOP))) { + bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER); + bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER); + } + } else { + if ((bfd_info->type == BFD_TYPE_MULTIHOP + && !CHECK_FLAG(bfd_info->flags, + BFD_FLAG_BFD_TYPE_MULTIHOP)) + || (bfd_info->type == BFD_TYPE_SINGLEHOP + && CHECK_FLAG(bfd_info->flags, + BFD_FLAG_BFD_TYPE_MULTIHOP))) { + bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER); + bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER); + } + } } /* * bgp_bfd_dest_replay - Replay all the peers that have BFD enabled * to zebra */ -static int -bgp_bfd_dest_replay (int command, struct zclient *client, zebra_size_t length, - vrf_id_t vrf_id) +static int bgp_bfd_dest_replay(int command, struct zclient *client, + zebra_size_t length, vrf_id_t vrf_id) { - struct listnode *mnode, *node, *nnode; - struct bgp *bgp; - struct peer *peer; + struct listnode *mnode, *node, *nnode; + struct bgp *bgp; + struct peer *peer; - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Zebra: BFD Dest replay request"); + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Zebra: BFD Dest replay request"); - /* Send the client registration */ - bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); + /* Send the client registration */ + bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); - /* Replay the peer, if BFD is enabled in BGP */ + /* Replay the peer, if BFD is enabled in BGP */ - for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp)) - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - bgp_bfd_update_peer(peer); - } + for (ALL_LIST_ELEMENTS_RO(bm->bgp, mnode, bgp)) + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + bgp_bfd_update_peer(peer); + } - return 0; + return 0; } /* * bgp_bfd_peer_status_update - Update the BFD status if it has changed. Bring - * down the peer if the BFD session went down from * up. + * down the peer if the BFD session went down from + * * up. */ -static void -bgp_bfd_peer_status_update (struct peer *peer, int status) +static void bgp_bfd_peer_status_update(struct peer *peer, int status) { - struct bfd_info *bfd_info; - int old_status; + struct bfd_info *bfd_info; + int old_status; - bfd_info = (struct bfd_info *)peer->bfd_info; + bfd_info = (struct bfd_info *)peer->bfd_info; - if (bfd_info->status == status) - return; + if (bfd_info->status == status) + return; - old_status = bfd_info->status; - bfd_info->status = status; - bfd_info->last_update = bgp_clock(); + old_status = bfd_info->status; + bfd_info->status = status; + bfd_info->last_update = bgp_clock(); - if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP)) - { - peer->last_reset = PEER_DOWN_BFD_DOWN; - BGP_EVENT_ADD (peer, BGP_Stop); - } + if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP)) { + peer->last_reset = PEER_DOWN_BFD_DOWN; + BGP_EVENT_ADD(peer, BGP_Stop); + } } /* @@ -295,258 +287,250 @@ bgp_bfd_peer_status_update (struct peer *peer, int status) * has changed and bring down the peer * connectivity if the BFD session went down. */ -static int -bgp_bfd_dest_update (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int bgp_bfd_dest_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - struct prefix dp; - struct prefix sp; - int status; - - ifp = bfd_get_peer_info (zclient->ibuf, &dp, &sp, &status, vrf_id); - - if (BGP_DEBUG (zebra, ZEBRA)) - { - char buf[2][PREFIX2STR_BUFFER]; - prefix2str(&dp, buf[0], sizeof(buf[0])); - if (ifp) - { - zlog_debug("Zebra: vrf %d interface %s bfd destination %s %s", - vrf_id, ifp->name, buf[0], bfd_get_status_str(status)); - } - else - { - prefix2str(&sp, buf[1], sizeof(buf[1])); - zlog_debug("Zebra: vrf %d source %s bfd destination %s %s", - vrf_id, buf[1], buf[0], bfd_get_status_str(status)); - } - } - - /* Bring the peer down if BFD is enabled in BGP */ - { - struct listnode *mnode, *node, *nnode; - struct bgp *bgp; - struct peer *peer; - - for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp)) - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (!peer->bfd_info) - continue; - - if ((dp.family == AF_INET) && (peer->su.sa.sa_family == AF_INET)) - { - if (dp.u.prefix4.s_addr != peer->su.sin.sin_addr.s_addr) - continue; - } - else if ((dp.family == AF_INET6) && - (peer->su.sa.sa_family == AF_INET6)) - { - if (memcmp(&dp.u.prefix6, &peer->su.sin6.sin6_addr, - sizeof (struct in6_addr))) - continue; - } - else - continue; - - if (ifp && (ifp == peer->nexthop.ifp)) - { - bgp_bfd_peer_status_update(peer, status); - } - else - { - if (!peer->su_local) - continue; - - if ((sp.family == AF_INET) && - (peer->su_local->sa.sa_family == AF_INET)) - { - if (sp.u.prefix4.s_addr != peer->su_local->sin.sin_addr.s_addr) - continue; - } - else if ((sp.family == AF_INET6) && - (peer->su_local->sa.sa_family == AF_INET6)) - { - if (memcmp(&sp.u.prefix6, &peer->su_local->sin6.sin6_addr, - sizeof (struct in6_addr))) - continue; - } - else - continue; - - if ((vrf_id != VRF_DEFAULT) && (peer->bgp->vrf_id != vrf_id)) - continue; - - bgp_bfd_peer_status_update(peer, status); - } - } - } - - return 0; + struct interface *ifp; + struct prefix dp; + struct prefix sp; + int status; + + ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status, vrf_id); + + if (BGP_DEBUG(zebra, ZEBRA)) { + char buf[2][PREFIX2STR_BUFFER]; + prefix2str(&dp, buf[0], sizeof(buf[0])); + if (ifp) { + zlog_debug( + "Zebra: vrf %d interface %s bfd destination %s %s", + vrf_id, ifp->name, buf[0], + bfd_get_status_str(status)); + } else { + prefix2str(&sp, buf[1], sizeof(buf[1])); + zlog_debug( + "Zebra: vrf %d source %s bfd destination %s %s", + vrf_id, buf[1], buf[0], + bfd_get_status_str(status)); + } + } + + /* Bring the peer down if BFD is enabled in BGP */ + { + struct listnode *mnode, *node, *nnode; + struct bgp *bgp; + struct peer *peer; + + for (ALL_LIST_ELEMENTS_RO(bm->bgp, mnode, bgp)) + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (!peer->bfd_info) + continue; + + if ((dp.family == AF_INET) + && (peer->su.sa.sa_family == AF_INET)) { + if (dp.u.prefix4.s_addr + != peer->su.sin.sin_addr.s_addr) + continue; + } else if ((dp.family == AF_INET6) + && (peer->su.sa.sa_family + == AF_INET6)) { + if (memcmp(&dp.u.prefix6, + &peer->su.sin6.sin6_addr, + sizeof(struct in6_addr))) + continue; + } else + continue; + + if (ifp && (ifp == peer->nexthop.ifp)) { + bgp_bfd_peer_status_update(peer, + status); + } else { + if (!peer->su_local) + continue; + + if ((sp.family == AF_INET) + && (peer->su_local->sa.sa_family + == AF_INET)) { + if (sp.u.prefix4.s_addr + != peer->su_local->sin + .sin_addr.s_addr) + continue; + } else if ((sp.family == AF_INET6) + && (peer->su_local->sa + .sa_family + == AF_INET6)) { + if (memcmp(&sp.u.prefix6, + &peer->su_local->sin6 + .sin6_addr, + sizeof(struct + in6_addr))) + continue; + } else + continue; + + if ((vrf_id != VRF_DEFAULT) + && (peer->bgp->vrf_id != vrf_id)) + continue; + + bgp_bfd_peer_status_update(peer, + status); + } + } + } + + return 0; } /* * bgp_bfd_peer_param_set - Set the configured BFD paramter values for peer. */ -static int -bgp_bfd_peer_param_set (struct peer *peer, u_int32_t min_rx, u_int32_t min_tx, - u_int8_t detect_mult, int defaults) +static int bgp_bfd_peer_param_set(struct peer *peer, u_int32_t min_rx, + u_int32_t min_tx, u_int8_t detect_mult, + int defaults) { - struct peer_group *group; - struct listnode *node, *nnode; - int command = 0; - - bfd_set_param((struct bfd_info **)&(peer->bfd_info), min_rx, min_tx, - detect_mult, defaults, &command); - - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - command = 0; - bfd_set_param((struct bfd_info **)&(peer->bfd_info), min_rx, min_tx, - detect_mult, defaults, &command); - - if ((peer->status == Established) && - (command == ZEBRA_BFD_DEST_REGISTER)) - bgp_bfd_register_peer(peer); - else if (command == ZEBRA_BFD_DEST_UPDATE) - bgp_bfd_update_peer(peer); - } - } - else - { - if ((peer->status == Established) && - (command == ZEBRA_BFD_DEST_REGISTER)) - bgp_bfd_register_peer(peer); - else if (command == ZEBRA_BFD_DEST_UPDATE) - bgp_bfd_update_peer(peer); - } - return 0; + struct peer_group *group; + struct listnode *node, *nnode; + int command = 0; + + bfd_set_param((struct bfd_info **)&(peer->bfd_info), min_rx, min_tx, + detect_mult, defaults, &command); + + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + command = 0; + bfd_set_param((struct bfd_info **)&(peer->bfd_info), + min_rx, min_tx, detect_mult, defaults, + &command); + + if ((peer->status == Established) + && (command == ZEBRA_BFD_DEST_REGISTER)) + bgp_bfd_register_peer(peer); + else if (command == ZEBRA_BFD_DEST_UPDATE) + bgp_bfd_update_peer(peer); + } + } else { + if ((peer->status == Established) + && (command == ZEBRA_BFD_DEST_REGISTER)) + bgp_bfd_register_peer(peer); + else if (command == ZEBRA_BFD_DEST_UPDATE) + bgp_bfd_update_peer(peer); + } + return 0; } /* - * bgp_bfd_peer_param_unset - Delete the configured BFD paramter values for peer. + * bgp_bfd_peer_param_unset - Delete the configured BFD paramter values for + * peer. */ -static int -bgp_bfd_peer_param_unset (struct peer *peer) +static int bgp_bfd_peer_param_unset(struct peer *peer) { - struct peer_group *group; - struct listnode *node, *nnode; - - if (!peer->bfd_info) - return 0; - - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - bfd_info_free(&(peer->bfd_info)); - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - bgp_bfd_deregister_peer(peer); - bfd_info_free(&(peer->bfd_info)); - } - } - else - { - bgp_bfd_deregister_peer(peer); - bfd_info_free(&(peer->bfd_info)); - } - return 0; + struct peer_group *group; + struct listnode *node, *nnode; + + if (!peer->bfd_info) + return 0; + + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + bfd_info_free(&(peer->bfd_info)); + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + bgp_bfd_deregister_peer(peer); + bfd_info_free(&(peer->bfd_info)); + } + } else { + bgp_bfd_deregister_peer(peer); + bfd_info_free(&(peer->bfd_info)); + } + return 0; } /* - * bgp_bfd_peer_param_type_set - set the BFD session type (multihop or singlehop) + * bgp_bfd_peer_param_type_set - set the BFD session type (multihop or + * singlehop) */ -static int -bgp_bfd_peer_param_type_set (struct peer *peer, enum bfd_sess_type type) +static int bgp_bfd_peer_param_type_set(struct peer *peer, + enum bfd_sess_type type) { - struct peer_group *group; - struct listnode *node, *nnode; - int command = 0; - struct bfd_info *bfd_info; - - if (!peer->bfd_info) - bfd_set_param((struct bfd_info **)&(peer->bfd_info), BFD_DEF_MIN_RX, - BFD_DEF_MIN_TX, BFD_DEF_DETECT_MULT, 1, &command); - - bfd_info = (struct bfd_info *)peer->bfd_info; - bfd_info->type = type; - - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - command = 0; - if (!peer->bfd_info) - bfd_set_param((struct bfd_info **)&(peer->bfd_info), - BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, - BFD_DEF_DETECT_MULT, 1, &command); - - bfd_info = (struct bfd_info *)peer->bfd_info; - bfd_info->type = type; - - if (peer->status == Established) - { - if (command == ZEBRA_BFD_DEST_REGISTER) - bgp_bfd_register_peer(peer); - else - bgp_bfd_update_type(peer); - } - } - } - else - { - if (peer->status == Established) - { - if (command == ZEBRA_BFD_DEST_REGISTER) - bgp_bfd_register_peer(peer); - else - bgp_bfd_update_type(peer); - } - } - - return 0; + struct peer_group *group; + struct listnode *node, *nnode; + int command = 0; + struct bfd_info *bfd_info; + + if (!peer->bfd_info) + bfd_set_param((struct bfd_info **)&(peer->bfd_info), + BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, + BFD_DEF_DETECT_MULT, 1, &command); + + bfd_info = (struct bfd_info *)peer->bfd_info; + bfd_info->type = type; + + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + command = 0; + if (!peer->bfd_info) + bfd_set_param( + (struct bfd_info **)&(peer->bfd_info), + BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, + BFD_DEF_DETECT_MULT, 1, &command); + + bfd_info = (struct bfd_info *)peer->bfd_info; + bfd_info->type = type; + + if (peer->status == Established) { + if (command == ZEBRA_BFD_DEST_REGISTER) + bgp_bfd_register_peer(peer); + else + bgp_bfd_update_type(peer); + } + } + } else { + if (peer->status == Established) { + if (command == ZEBRA_BFD_DEST_REGISTER) + bgp_bfd_register_peer(peer); + else + bgp_bfd_update_type(peer); + } + } + + return 0; } /* * bgp_bfd_peer_config_write - Write the peer BFD configuration. */ -void -bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr) +void bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr) { - struct bfd_info *bfd_info; + struct bfd_info *bfd_info; - if (!peer->bfd_info) - return; + if (!peer->bfd_info) + return; - bfd_info = (struct bfd_info *)peer->bfd_info; + bfd_info = (struct bfd_info *)peer->bfd_info; - if (CHECK_FLAG (bfd_info->flags, BFD_FLAG_PARAM_CFG)) - vty_out (vty, " neighbor %s bfd %d %d %d\n", addr, - bfd_info->detect_mult, bfd_info->required_min_rx, - bfd_info->desired_min_tx); + if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) + vty_out(vty, " neighbor %s bfd %d %d %d\n", addr, + bfd_info->detect_mult, bfd_info->required_min_rx, + bfd_info->desired_min_tx); - if (bfd_info->type != BFD_TYPE_NOT_CONFIGURED) - vty_out (vty, " neighbor %s bfd %s\n", addr, - (bfd_info->type == BFD_TYPE_MULTIHOP) ? "multihop" : "singlehop"); + if (bfd_info->type != BFD_TYPE_NOT_CONFIGURED) + vty_out(vty, " neighbor %s bfd %s\n", addr, + (bfd_info->type == BFD_TYPE_MULTIHOP) ? "multihop" + : "singlehop"); - if (!CHECK_FLAG (bfd_info->flags, BFD_FLAG_PARAM_CFG) && - (bfd_info->type == BFD_TYPE_NOT_CONFIGURED)) - vty_out (vty, " neighbor %s bfd\n", addr); + if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG) + && (bfd_info->type == BFD_TYPE_NOT_CONFIGURED)) + vty_out(vty, " neighbor %s bfd\n", addr); } /* * bgp_bfd_show_info - Show the peer BFD information. */ -void -bgp_bfd_show_info(struct vty *vty, struct peer *peer, u_char use_json, json_object *json_neigh) +void bgp_bfd_show_info(struct vty *vty, struct peer *peer, u_char use_json, + json_object *json_neigh) { - bfd_show_info(vty, (struct bfd_info *)peer->bfd_info, - bgp_bfd_is_peer_multihop(peer), 0, use_json, json_neigh); + bfd_show_info(vty, (struct bfd_info *)peer->bfd_info, + bgp_bfd_is_peer_multihop(peer), 0, use_json, json_neigh); } DEFUN (neighbor_bfd, @@ -556,21 +540,20 @@ DEFUN (neighbor_bfd, NEIGHBOR_ADDR_STR2 "Enables BFD support\n") { - int idx_peer = 1; - struct peer *peer; - int ret; + int idx_peer = 1; + struct peer *peer; + int ret; - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - ret = bgp_bfd_peer_param_set (peer, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, - BFD_DEF_DETECT_MULT, 1); - if (ret != 0) - return bgp_vty_return (vty, ret); - - return CMD_SUCCESS; + ret = bgp_bfd_peer_param_set(peer, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, + BFD_DEF_DETECT_MULT, 1); + if (ret != 0) + return bgp_vty_return(vty, ret); + return CMD_SUCCESS; } DEFUN (neighbor_bfd_param, @@ -583,30 +566,31 @@ DEFUN (neighbor_bfd_param, "Required min receive interval\n" "Desired min transmit interval\n") { - int idx_peer = 1; - int idx_number_1 = 3; - int idx_number_2 = 4; - int idx_number_3 = 5; - struct peer *peer; - u_int32_t rx_val; - u_int32_t tx_val; - u_int8_t dm_val; - int ret; - - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (!peer) - return CMD_WARNING_CONFIG_FAILED; - - if ((ret = bfd_validate_param (vty, argv[idx_number_1]->arg, argv[idx_number_2]->arg, argv[idx_number_3]->arg, &dm_val, - &rx_val, &tx_val)) != CMD_SUCCESS) - return ret; - - ret = bgp_bfd_peer_param_set (peer, rx_val, tx_val, dm_val, 0); - if (ret != 0) - return bgp_vty_return (vty, ret); - - return CMD_SUCCESS; - + int idx_peer = 1; + int idx_number_1 = 3; + int idx_number_2 = 4; + int idx_number_3 = 5; + struct peer *peer; + u_int32_t rx_val; + u_int32_t tx_val; + u_int8_t dm_val; + int ret; + + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; + + if ((ret = bfd_validate_param( + vty, argv[idx_number_1]->arg, argv[idx_number_2]->arg, + argv[idx_number_3]->arg, &dm_val, &rx_val, &tx_val)) + != CMD_SUCCESS) + return ret; + + ret = bgp_bfd_peer_param_set(peer, rx_val, tx_val, dm_val, 0); + if (ret != 0) + return bgp_vty_return(vty, ret); + + return CMD_SUCCESS; } DEFUN_HIDDEN (neighbor_bfd_type, @@ -618,28 +602,28 @@ DEFUN_HIDDEN (neighbor_bfd_type, "Multihop session\n" "Single hop session\n") { - int idx_peer = 1; - int idx_hop = 3; - struct peer *peer; - enum bfd_sess_type type; - int ret; - - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (!peer) - return CMD_WARNING_CONFIG_FAILED; - - if (strmatch(argv[idx_hop]->text, "singlehop")) - type = BFD_TYPE_SINGLEHOP; - else if (strmatch(argv[idx_hop]->text, "multihop")) - type = BFD_TYPE_MULTIHOP; - else - return CMD_WARNING_CONFIG_FAILED; - - ret = bgp_bfd_peer_param_type_set (peer, type); - if (ret != 0) - return bgp_vty_return (vty, ret); - - return CMD_SUCCESS; + int idx_peer = 1; + int idx_hop = 3; + struct peer *peer; + enum bfd_sess_type type; + int ret; + + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; + + if (strmatch(argv[idx_hop]->text, "singlehop")) + type = BFD_TYPE_SINGLEHOP; + else if (strmatch(argv[idx_hop]->text, "multihop")) + type = BFD_TYPE_MULTIHOP; + else + return CMD_WARNING_CONFIG_FAILED; + + ret = bgp_bfd_peer_param_type_set(peer, type); + if (ret != 0) + return bgp_vty_return(vty, ret); + + return CMD_SUCCESS; } DEFUN (no_neighbor_bfd, @@ -653,19 +637,19 @@ DEFUN (no_neighbor_bfd, "Required min receive interval\n" "Desired min transmit interval\n") { - int idx_peer = 2; - struct peer *peer; - int ret; + int idx_peer = 2; + struct peer *peer; + int ret; - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - ret = bgp_bfd_peer_param_unset(peer); - if (ret != 0) - return bgp_vty_return (vty, ret); + ret = bgp_bfd_peer_param_unset(peer); + if (ret != 0) + return bgp_vty_return(vty, ret); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -679,37 +663,36 @@ DEFUN_HIDDEN (no_neighbor_bfd_type, "Multihop session\n" "Singlehop session\n") { - int idx_peer = 2; - struct peer *peer; - int ret; + int idx_peer = 2; + struct peer *peer; + int ret; - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - if (!peer->bfd_info) - return 0; + if (!peer->bfd_info) + return 0; - ret = bgp_bfd_peer_param_type_set(peer, BFD_TYPE_NOT_CONFIGURED); - if (ret != 0) - return bgp_vty_return (vty, ret); + ret = bgp_bfd_peer_param_type_set(peer, BFD_TYPE_NOT_CONFIGURED); + if (ret != 0) + return bgp_vty_return(vty, ret); - return CMD_SUCCESS; + return CMD_SUCCESS; } -void -bgp_bfd_init(void) +void bgp_bfd_init(void) { - bfd_gbl_init(); - - /* Initialize BFD client functions */ - zclient->interface_bfd_dest_update = bgp_bfd_dest_update; - zclient->bfd_dest_replay = bgp_bfd_dest_replay; - - /* "neighbor bfd" commands. */ - install_element (BGP_NODE, &neighbor_bfd_cmd); - install_element (BGP_NODE, &neighbor_bfd_param_cmd); - install_element (BGP_NODE, &neighbor_bfd_type_cmd); - install_element (BGP_NODE, &no_neighbor_bfd_cmd); - install_element (BGP_NODE, &no_neighbor_bfd_type_cmd); + bfd_gbl_init(); + + /* Initialize BFD client functions */ + zclient->interface_bfd_dest_update = bgp_bfd_dest_update; + zclient->bfd_dest_replay = bgp_bfd_dest_replay; + + /* "neighbor bfd" commands. */ + install_element(BGP_NODE, &neighbor_bfd_cmd); + install_element(BGP_NODE, &neighbor_bfd_param_cmd); + install_element(BGP_NODE, &neighbor_bfd_type_cmd); + install_element(BGP_NODE, &no_neighbor_bfd_cmd); + install_element(BGP_NODE, &no_neighbor_bfd_type_cmd); } diff --git a/bgpd/bgp_bfd.h b/bgpd/bgp_bfd.h index e2c85af04..72d86596b 100644 --- a/bgpd/bgp_bfd.h +++ b/bgpd/bgp_bfd.h @@ -23,25 +23,20 @@ #ifndef _QUAGGA_BGP_BFD_H #define _QUAGGA_BGP_BFD_H -extern void -bgp_bfd_init(void); +extern void bgp_bfd_init(void); -extern void -bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer); +extern void bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer); -extern void -bgp_bfd_register_peer (struct peer *peer); +extern void bgp_bfd_register_peer(struct peer *peer); -extern void -bgp_bfd_deregister_peer (struct peer *peer); +extern void bgp_bfd_deregister_peer(struct peer *peer); -extern void -bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr); +extern void bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, + char *addr); -extern void -bgp_bfd_show_info(struct vty *vty, struct peer *peer, u_char use_json, json_object *json_neigh); +extern void bgp_bfd_show_info(struct vty *vty, struct peer *peer, + u_char use_json, json_object *json_neigh); -extern int -bgp_bfd_is_peer_multihop(struct peer *peer); +extern int bgp_bfd_is_peer_multihop(struct peer *peer); #endif /* _QUAGGA_BGP_BFD_H */ diff --git a/bgpd/bgp_btoa.c b/bgpd/bgp_btoa.c index be9344830..4faebb538 100644 --- a/bgpd/bgp_btoa.c +++ b/bgpd/bgp_btoa.c @@ -35,280 +35,255 @@ #include "bgpd/bgp_aspath.h" /* privileges */ -static zebra_capabilities_t _caps_p [] = -{ - ZCAP_BIND, - ZCAP_NET_RAW, - ZCAP_NET_ADMIN, +static zebra_capabilities_t _caps_p[] = { + ZCAP_BIND, ZCAP_NET_RAW, ZCAP_NET_ADMIN, }; -struct zebra_privs_t bgpd_privs = -{ +struct zebra_privs_t bgpd_privs = { #if defined(FRR_USER) && defined(FRR_GROUP) - .user = FRR_USER, - .group = FRR_GROUP, + .user = FRR_USER, + .group = FRR_GROUP, #endif #ifdef VTY_GROUP - .vty_group = VTY_GROUP, + .vty_group = VTY_GROUP, #endif - .caps_p = _caps_p, - .cap_num_p = array_size(_caps_p), - .cap_num_i = 0, + .caps_p = _caps_p, + .cap_num_p = array_size(_caps_p), + .cap_num_i = 0, }; enum MRT_MSG_TYPES { - MSG_NULL, - MSG_START, /* sender is starting up */ - MSG_DIE, /* receiver should shut down */ - MSG_I_AM_DEAD, /* sender is shutting down */ - MSG_PEER_DOWN, /* sender's peer is down */ - MSG_PROTOCOL_BGP, /* msg is a BGP packet */ - MSG_PROTOCOL_RIP, /* msg is a RIP packet */ - MSG_PROTOCOL_IDRP, /* msg is an IDRP packet */ - MSG_PROTOCOL_RIPNG, /* msg is a RIPNG packet */ - MSG_PROTOCOL_BGP4PLUS, /* msg is a BGP4+ packet */ - MSG_PROTOCOL_BGP4PLUS_01, /* msg is a BGP4+ (draft 01) packet */ - MSG_PROTOCOL_OSPF, /* msg is an OSPF packet */ - MSG_TABLE_DUMP /* routing table dump */ + MSG_NULL, + MSG_START, /* sender is starting up */ + MSG_DIE, /* receiver should shut down */ + MSG_I_AM_DEAD, /* sender is shutting down */ + MSG_PEER_DOWN, /* sender's peer is down */ + MSG_PROTOCOL_BGP, /* msg is a BGP packet */ + MSG_PROTOCOL_RIP, /* msg is a RIP packet */ + MSG_PROTOCOL_IDRP, /* msg is an IDRP packet */ + MSG_PROTOCOL_RIPNG, /* msg is a RIPNG packet */ + MSG_PROTOCOL_BGP4PLUS, /* msg is a BGP4+ packet */ + MSG_PROTOCOL_BGP4PLUS_01, /* msg is a BGP4+ (draft 01) packet */ + MSG_PROTOCOL_OSPF, /* msg is an OSPF packet */ + MSG_TABLE_DUMP /* routing table dump */ }; -static int -attr_parse (struct stream *s, u_int16_t len) +static int attr_parse(struct stream *s, u_int16_t len) { - u_int flag; - u_int type; - u_int16_t length; - u_int16_t lim; - - lim = s->getp + len; - - printf ("attr_parse s->getp %zd, len %d, lim %d\n", s->getp, len, lim); - - while (s->getp < lim) - { - flag = stream_getc (s); - type = stream_getc (s); - - if (flag & BGP_ATTR_FLAG_EXTLEN) - length = stream_getw (s); - else - length = stream_getc (s); - - printf ("FLAG: %d\n", flag); - printf ("TYPE: %d\n", type); - printf ("Len: %d\n", length); - - switch (type) - { - case BGP_ATTR_ORIGIN: - { - u_char origin; - origin = stream_getc (s); - printf ("ORIGIN: %d\n", origin); - } - break; - case BGP_ATTR_AS_PATH: - { - struct aspath *aspath; - - aspath = aspath_parse (s, length, 1); - printf ("ASPATH: %s\n", aspath->str); - aspath_free(aspath); - } - break; - case BGP_ATTR_NEXT_HOP: - { - struct in_addr nexthop; - nexthop.s_addr = stream_get_ipv4 (s); - printf ("NEXTHOP: %s\n", inet_ntoa (nexthop)); - } - break; - default: - stream_getw_from (s, length); - break; + u_int flag; + u_int type; + u_int16_t length; + u_int16_t lim; + + lim = s->getp + len; + + printf("attr_parse s->getp %zd, len %d, lim %d\n", s->getp, len, lim); + + while (s->getp < lim) { + flag = stream_getc(s); + type = stream_getc(s); + + if (flag & BGP_ATTR_FLAG_EXTLEN) + length = stream_getw(s); + else + length = stream_getc(s); + + printf("FLAG: %d\n", flag); + printf("TYPE: %d\n", type); + printf("Len: %d\n", length); + + switch (type) { + case BGP_ATTR_ORIGIN: { + u_char origin; + origin = stream_getc(s); + printf("ORIGIN: %d\n", origin); + } break; + case BGP_ATTR_AS_PATH: { + struct aspath *aspath; + + aspath = aspath_parse(s, length, 1); + printf("ASPATH: %s\n", aspath->str); + aspath_free(aspath); + } break; + case BGP_ATTR_NEXT_HOP: { + struct in_addr nexthop; + nexthop.s_addr = stream_get_ipv4(s); + printf("NEXTHOP: %s\n", inet_ntoa(nexthop)); + } break; + default: + stream_getw_from(s, length); + break; + } } - } - return 0; + return 0; } -int -main (int argc, char **argv) +int main(int argc, char **argv) { - int ret; - FILE *fp; - struct stream *s; - time_t now; - int type; - int subtype; - size_t len; - int source_as; - int dest_as; - ifindex_t ifindex; - int family; - struct in_addr sip; - struct in_addr dip; - u_int16_t viewno, seq_num; - struct prefix_ipv4 p; - - s = stream_new (10000); - - if (argc != 2) - { - fprintf (stderr, "Usage: %s FILENAME\n", argv[0]); - exit (1); - } - fp = fopen (argv[1], "r"); - if (!fp) - { - fprintf (stdout,"%% Can't open configuration file %s due to '%s'.\n", - argv[1], safe_strerror(errno)); - exit (1); - } - - while (1) - { - stream_reset (s); - - ret = fread (s->data, 12, 1, fp); - if (!ret || feof (fp)) - { - printf ("END OF FILE\n"); - break; + int ret; + FILE *fp; + struct stream *s; + time_t now; + int type; + int subtype; + size_t len; + int source_as; + int dest_as; + ifindex_t ifindex; + int family; + struct in_addr sip; + struct in_addr dip; + u_int16_t viewno, seq_num; + struct prefix_ipv4 p; + + s = stream_new(10000); + + if (argc != 2) { + fprintf(stderr, "Usage: %s FILENAME\n", argv[0]); + exit(1); } - if (ferror (fp)) - { - printf ("ERROR OF FREAD\n"); - break; + fp = fopen(argv[1], "r"); + if (!fp) { + fprintf(stdout, + "%% Can't open configuration file %s due to '%s'.\n", + argv[1], safe_strerror(errno)); + exit(1); } - /* Extract header. */ - now = stream_getl (s); - type = stream_getw (s); - subtype = stream_getw (s); - len = stream_getl (s); - - printf ("TIME: %s", ctime (&now)); - - /* printf ("TYPE: %d/%d\n", type, subtype); */ - - if (type == MSG_PROTOCOL_BGP4MP) - printf ("TYPE: BGP4MP"); - else if (type == MSG_PROTOCOL_BGP4MP_ET) - printf ("TYPE: BGP4MP_ET"); - else if (type == MSG_TABLE_DUMP) - printf ("TYPE: MSG_TABLE_DUMP"); - else - printf ("TYPE: Unknown %d", type); - - if (type == MSG_TABLE_DUMP) - switch (subtype) - { - case AFI_IP: - printf ("/AFI_IP\n"); - break; - case AFI_IP6: - printf ("/AFI_IP6\n"); - break; - default: - printf ("/UNKNOWN %d", subtype); - break; - } - else - { - switch (subtype) - { - case BGP4MP_STATE_CHANGE: - printf ("/CHANGE\n"); - break; - case BGP4MP_MESSAGE: - printf ("/MESSAGE\n"); - break; - case BGP4MP_ENTRY: - printf ("/ENTRY\n"); - break; - case BGP4MP_SNAPSHOT: - printf ("/SNAPSHOT\n"); - break; - default: - printf ("/UNKNOWN %d", subtype); - break; - } - } - - printf ("len: %zd\n", len); - - fread (s->data + 12, len, 1, fp); - if (feof (fp)) - { - printf ("ENDOF FILE 2\n"); - break; - } - if (ferror (fp)) - { - printf ("ERROR OF FREAD 2\n"); - break; - } - - /* printf ("now read %d\n", len); */ - - if (type == MSG_TABLE_DUMP) - { - u_char status; - time_t originated; - struct in_addr peer; - u_int16_t attrlen; - - viewno = stream_getw (s); - seq_num = stream_getw (s); - printf ("VIEW: %d\n", viewno); - printf ("SEQUENCE: %d\n", seq_num); - - /* start */ - while (s->getp < len - 16) - { - p.prefix.s_addr = stream_get_ipv4 (s); - p.prefixlen = stream_getc (s); - printf ("PREFIX: %s/%d\n", inet_ntoa (p.prefix), p.prefixlen); - - status = stream_getc (s); - originated = stream_getl (s); - peer.s_addr = stream_get_ipv4 (s); - source_as = stream_getw(s); - - printf ("FROM: %s AS%d\n", inet_ntoa (peer), source_as); - printf ("ORIGINATED: %s", ctime (&originated)); - - attrlen = stream_getw (s); - printf ("ATTRLEN: %d\n", attrlen); - - attr_parse (s, attrlen); - - printf ("STATUS: 0x%x\n", status); - } - } - else - { - source_as = stream_getw (s); - dest_as = stream_getw (s); - printf ("source_as: %d\n", source_as); - printf ("dest_as: %d\n", dest_as); - - ifindex = stream_getw (s); - family = stream_getw (s); - - printf ("ifindex: %d\n", ifindex); - printf ("family: %d\n", family); - - sip.s_addr = stream_get_ipv4 (s); - dip.s_addr = stream_get_ipv4 (s); - - printf ("saddr: %s\n", inet_ntoa (sip)); - printf ("daddr: %s\n", inet_ntoa (dip)); - - printf ("\n"); + while (1) { + stream_reset(s); + + ret = fread(s->data, 12, 1, fp); + if (!ret || feof(fp)) { + printf("END OF FILE\n"); + break; + } + if (ferror(fp)) { + printf("ERROR OF FREAD\n"); + break; + } + + /* Extract header. */ + now = stream_getl(s); + type = stream_getw(s); + subtype = stream_getw(s); + len = stream_getl(s); + + printf("TIME: %s", ctime(&now)); + + /* printf ("TYPE: %d/%d\n", type, subtype); */ + + if (type == MSG_PROTOCOL_BGP4MP) + printf("TYPE: BGP4MP"); + else if (type == MSG_PROTOCOL_BGP4MP_ET) + printf("TYPE: BGP4MP_ET"); + else if (type == MSG_TABLE_DUMP) + printf("TYPE: MSG_TABLE_DUMP"); + else + printf("TYPE: Unknown %d", type); + + if (type == MSG_TABLE_DUMP) + switch (subtype) { + case AFI_IP: + printf("/AFI_IP\n"); + break; + case AFI_IP6: + printf("/AFI_IP6\n"); + break; + default: + printf("/UNKNOWN %d", subtype); + break; + } + else { + switch (subtype) { + case BGP4MP_STATE_CHANGE: + printf("/CHANGE\n"); + break; + case BGP4MP_MESSAGE: + printf("/MESSAGE\n"); + break; + case BGP4MP_ENTRY: + printf("/ENTRY\n"); + break; + case BGP4MP_SNAPSHOT: + printf("/SNAPSHOT\n"); + break; + default: + printf("/UNKNOWN %d", subtype); + break; + } + } + + printf("len: %zd\n", len); + + fread(s->data + 12, len, 1, fp); + if (feof(fp)) { + printf("ENDOF FILE 2\n"); + break; + } + if (ferror(fp)) { + printf("ERROR OF FREAD 2\n"); + break; + } + + /* printf ("now read %d\n", len); */ + + if (type == MSG_TABLE_DUMP) { + u_char status; + time_t originated; + struct in_addr peer; + u_int16_t attrlen; + + viewno = stream_getw(s); + seq_num = stream_getw(s); + printf("VIEW: %d\n", viewno); + printf("SEQUENCE: %d\n", seq_num); + + /* start */ + while (s->getp < len - 16) { + p.prefix.s_addr = stream_get_ipv4(s); + p.prefixlen = stream_getc(s); + printf("PREFIX: %s/%d\n", inet_ntoa(p.prefix), + p.prefixlen); + + status = stream_getc(s); + originated = stream_getl(s); + peer.s_addr = stream_get_ipv4(s); + source_as = stream_getw(s); + + printf("FROM: %s AS%d\n", inet_ntoa(peer), + source_as); + printf("ORIGINATED: %s", ctime(&originated)); + + attrlen = stream_getw(s); + printf("ATTRLEN: %d\n", attrlen); + + attr_parse(s, attrlen); + + printf("STATUS: 0x%x\n", status); + } + } else { + source_as = stream_getw(s); + dest_as = stream_getw(s); + printf("source_as: %d\n", source_as); + printf("dest_as: %d\n", dest_as); + + ifindex = stream_getw(s); + family = stream_getw(s); + + printf("ifindex: %d\n", ifindex); + printf("family: %d\n", family); + + sip.s_addr = stream_get_ipv4(s); + dip.s_addr = stream_get_ipv4(s); + + printf("saddr: %s\n", inet_ntoa(sip)); + printf("daddr: %s\n", inet_ntoa(dip)); + + printf("\n"); + } } - } - fclose (fp); - return 0; + fclose(fp); + return 0; } diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c index a61d63bb8..13587b359 100644 --- a/bgpd/bgp_clist.c +++ b/bgpd/bgp_clist.c @@ -37,534 +37,512 @@ /* Lookup master structure for community-list or extcommunity-list. */ struct community_list_master * -community_list_master_lookup (struct community_list_handler *ch, int master) +community_list_master_lookup(struct community_list_handler *ch, int master) { - if (ch) - switch (master) - { - case COMMUNITY_LIST_MASTER: - return &ch->community_list; - case EXTCOMMUNITY_LIST_MASTER: - return &ch->extcommunity_list; - case LARGE_COMMUNITY_LIST_MASTER: - return &ch->lcommunity_list; - } - return NULL; + if (ch) + switch (master) { + case COMMUNITY_LIST_MASTER: + return &ch->community_list; + case EXTCOMMUNITY_LIST_MASTER: + return &ch->extcommunity_list; + case LARGE_COMMUNITY_LIST_MASTER: + return &ch->lcommunity_list; + } + return NULL; } /* Allocate a new community list entry. */ -static struct community_entry * -community_entry_new (void) +static struct community_entry *community_entry_new(void) { - return XCALLOC (MTYPE_COMMUNITY_LIST_ENTRY, sizeof (struct community_entry)); + return XCALLOC(MTYPE_COMMUNITY_LIST_ENTRY, + sizeof(struct community_entry)); } /* Free community list entry. */ -static void -community_entry_free (struct community_entry *entry) +static void community_entry_free(struct community_entry *entry) { - switch (entry->style) - { - case COMMUNITY_LIST_STANDARD: - if (entry->u.com) - community_free (entry->u.com); - break; - case LARGE_COMMUNITY_LIST_STANDARD: - if (entry->u.lcom) - lcommunity_free (&entry->u.lcom); - break; - case EXTCOMMUNITY_LIST_STANDARD: - /* In case of standard extcommunity-list, configuration string - is made by ecommunity_ecom2str(). */ - if (entry->config) - XFREE (MTYPE_ECOMMUNITY_STR, entry->config); - if (entry->u.ecom) - ecommunity_free (&entry->u.ecom); - break; - case COMMUNITY_LIST_EXPANDED: - case EXTCOMMUNITY_LIST_EXPANDED: - case LARGE_COMMUNITY_LIST_EXPANDED: - if (entry->config) - XFREE (MTYPE_COMMUNITY_LIST_CONFIG, entry->config); - if (entry->reg) - bgp_regex_free (entry->reg); - default: - break; - } - XFREE (MTYPE_COMMUNITY_LIST_ENTRY, entry); + switch (entry->style) { + case COMMUNITY_LIST_STANDARD: + if (entry->u.com) + community_free(entry->u.com); + break; + case LARGE_COMMUNITY_LIST_STANDARD: + if (entry->u.lcom) + lcommunity_free(&entry->u.lcom); + break; + case EXTCOMMUNITY_LIST_STANDARD: + /* In case of standard extcommunity-list, configuration string + is made by ecommunity_ecom2str(). */ + if (entry->config) + XFREE(MTYPE_ECOMMUNITY_STR, entry->config); + if (entry->u.ecom) + ecommunity_free(&entry->u.ecom); + break; + case COMMUNITY_LIST_EXPANDED: + case EXTCOMMUNITY_LIST_EXPANDED: + case LARGE_COMMUNITY_LIST_EXPANDED: + if (entry->config) + XFREE(MTYPE_COMMUNITY_LIST_CONFIG, entry->config); + if (entry->reg) + bgp_regex_free(entry->reg); + default: + break; + } + XFREE(MTYPE_COMMUNITY_LIST_ENTRY, entry); } /* Allocate a new community-list. */ -static struct community_list * -community_list_new (void) +static struct community_list *community_list_new(void) { - return XCALLOC (MTYPE_COMMUNITY_LIST, sizeof (struct community_list)); + return XCALLOC(MTYPE_COMMUNITY_LIST, sizeof(struct community_list)); } /* Free community-list. */ -static void -community_list_free (struct community_list *list) +static void community_list_free(struct community_list *list) { - if (list->name) - XFREE (MTYPE_COMMUNITY_LIST_NAME, list->name); - XFREE (MTYPE_COMMUNITY_LIST, list); + if (list->name) + XFREE(MTYPE_COMMUNITY_LIST_NAME, list->name); + XFREE(MTYPE_COMMUNITY_LIST, list); } static struct community_list * -community_list_insert (struct community_list_handler *ch, - const char *name, int master) +community_list_insert(struct community_list_handler *ch, const char *name, + int master) { - size_t i; - long number; - struct community_list *new; - struct community_list *point; - struct community_list_list *list; - struct community_list_master *cm; - - /* Lookup community-list master. */ - cm = community_list_master_lookup (ch, master); - if (!cm) - return NULL; + size_t i; + long number; + struct community_list *new; + struct community_list *point; + struct community_list_list *list; + struct community_list_master *cm; + + /* Lookup community-list master. */ + cm = community_list_master_lookup(ch, master); + if (!cm) + return NULL; + + /* Allocate new community_list and copy given name. */ + new = community_list_new(); + new->name = XSTRDUP(MTYPE_COMMUNITY_LIST_NAME, name); + + /* If name is made by all digit character. We treat it as + number. */ + for (number = 0, i = 0; i < strlen(name); i++) { + if (isdigit((int)name[i])) + number = (number * 10) + (name[i] - '0'); + else + break; + } - /* Allocate new community_list and copy given name. */ - new = community_list_new (); - new->name = XSTRDUP (MTYPE_COMMUNITY_LIST_NAME, name); + /* In case of name is all digit character */ + if (i == strlen(name)) { + new->sort = COMMUNITY_LIST_NUMBER; - /* If name is made by all digit character. We treat it as - number. */ - for (number = 0, i = 0; i < strlen (name); i++) - { - if (isdigit ((int) name[i])) - number = (number * 10) + (name[i] - '0'); - else - break; - } + /* Set access_list to number list. */ + list = &cm->num; - /* In case of name is all digit character */ - if (i == strlen (name)) - { - new->sort = COMMUNITY_LIST_NUMBER; + for (point = list->head; point; point = point->next) + if (atol(point->name) >= number) + break; + } else { + new->sort = COMMUNITY_LIST_STRING; - /* Set access_list to number list. */ - list = &cm->num; + /* Set access_list to string list. */ + list = &cm->str; - for (point = list->head; point; point = point->next) - if (atol (point->name) >= number) - break; - } - else - { - new->sort = COMMUNITY_LIST_STRING; - - /* Set access_list to string list. */ - list = &cm->str; - - /* Set point to insertion point. */ - for (point = list->head; point; point = point->next) - if (strcmp (point->name, name) >= 0) - break; - } + /* Set point to insertion point. */ + for (point = list->head; point; point = point->next) + if (strcmp(point->name, name) >= 0) + break; + } - /* Link to upper list. */ - new->parent = list; + /* Link to upper list. */ + new->parent = list; - /* In case of this is the first element of master. */ - if (list->head == NULL) - { - list->head = list->tail = new; - return new; - } + /* In case of this is the first element of master. */ + if (list->head == NULL) { + list->head = list->tail = new; + return new; + } - /* In case of insertion is made at the tail of access_list. */ - if (point == NULL) - { - new->prev = list->tail; - list->tail->next = new; - list->tail = new; - return new; - } + /* In case of insertion is made at the tail of access_list. */ + if (point == NULL) { + new->prev = list->tail; + list->tail->next = new; + list->tail = new; + return new; + } - /* In case of insertion is made at the head of access_list. */ - if (point == list->head) - { - new->next = list->head; - list->head->prev = new; - list->head = new; - return new; - } + /* In case of insertion is made at the head of access_list. */ + if (point == list->head) { + new->next = list->head; + list->head->prev = new; + list->head = new; + return new; + } - /* Insertion is made at middle of the access_list. */ - new->next = point; - new->prev = point->prev; + /* Insertion is made at middle of the access_list. */ + new->next = point; + new->prev = point->prev; - if (point->prev) - point->prev->next = new; - point->prev = new; + if (point->prev) + point->prev->next = new; + point->prev = new; - return new; + return new; } -struct community_list * -community_list_lookup (struct community_list_handler *ch, - const char *name, int master) +struct community_list *community_list_lookup(struct community_list_handler *ch, + const char *name, int master) { - struct community_list *list; - struct community_list_master *cm; + struct community_list *list; + struct community_list_master *cm; - if (!name) - return NULL; + if (!name) + return NULL; - cm = community_list_master_lookup (ch, master); - if (!cm) - return NULL; + cm = community_list_master_lookup(ch, master); + if (!cm) + return NULL; - for (list = cm->num.head; list; list = list->next) - if (strcmp (list->name, name) == 0) - return list; - for (list = cm->str.head; list; list = list->next) - if (strcmp (list->name, name) == 0) - return list; + for (list = cm->num.head; list; list = list->next) + if (strcmp(list->name, name) == 0) + return list; + for (list = cm->str.head; list; list = list->next) + if (strcmp(list->name, name) == 0) + return list; - return NULL; + return NULL; } static struct community_list * -community_list_get (struct community_list_handler *ch, - const char *name, int master) +community_list_get(struct community_list_handler *ch, const char *name, + int master) { - struct community_list *list; + struct community_list *list; - list = community_list_lookup (ch, name, master); - if (!list) - list = community_list_insert (ch, name, master); - return list; + list = community_list_lookup(ch, name, master); + if (!list) + list = community_list_insert(ch, name, master); + return list; } -static void -community_list_delete (struct community_list *list) +static void community_list_delete(struct community_list *list) { - struct community_list_list *clist; - struct community_entry *entry, *next; + struct community_list_list *clist; + struct community_entry *entry, *next; - for (entry = list->head; entry; entry = next) - { - next = entry->next; - community_entry_free (entry); - } + for (entry = list->head; entry; entry = next) { + next = entry->next; + community_entry_free(entry); + } - clist = list->parent; + clist = list->parent; - if (list->next) - list->next->prev = list->prev; - else - clist->tail = list->prev; + if (list->next) + list->next->prev = list->prev; + else + clist->tail = list->prev; - if (list->prev) - list->prev->next = list->next; - else - clist->head = list->next; + if (list->prev) + list->prev->next = list->next; + else + clist->head = list->next; - community_list_free (list); + community_list_free(list); } -static int -community_list_empty_p (struct community_list *list) +static int community_list_empty_p(struct community_list *list) { - return (list->head == NULL && list->tail == NULL) ? 1 : 0; + return (list->head == NULL && list->tail == NULL) ? 1 : 0; } /* Add community-list entry to the list. */ -static void -community_list_entry_add (struct community_list *list, - struct community_entry *entry) +static void community_list_entry_add(struct community_list *list, + struct community_entry *entry) { - entry->next = NULL; - entry->prev = list->tail; - - if (list->tail) - list->tail->next = entry; - else - list->head = entry; - list->tail = entry; + entry->next = NULL; + entry->prev = list->tail; + + if (list->tail) + list->tail->next = entry; + else + list->head = entry; + list->tail = entry; } /* Delete community-list entry from the list. */ -static void -community_list_entry_delete (struct community_list *list, - struct community_entry *entry, int style) +static void community_list_entry_delete(struct community_list *list, + struct community_entry *entry, + int style) { - if (entry->next) - entry->next->prev = entry->prev; - else - list->tail = entry->prev; + if (entry->next) + entry->next->prev = entry->prev; + else + list->tail = entry->prev; - if (entry->prev) - entry->prev->next = entry->next; - else - list->head = entry->next; + if (entry->prev) + entry->prev->next = entry->next; + else + list->head = entry->next; - community_entry_free (entry); + community_entry_free(entry); - if (community_list_empty_p (list)) - community_list_delete (list); + if (community_list_empty_p(list)) + community_list_delete(list); } /* Lookup community-list entry from the list. */ static struct community_entry * -community_list_entry_lookup (struct community_list *list, const void *arg, - int direct) +community_list_entry_lookup(struct community_list *list, const void *arg, + int direct) { - struct community_entry *entry; - - for (entry = list->head; entry; entry = entry->next) - { - switch (entry->style) - { - case COMMUNITY_LIST_STANDARD: - if (entry->direct == direct && community_cmp (entry->u.com, arg)) - return entry; - break; - case EXTCOMMUNITY_LIST_STANDARD: - if (entry->direct == direct && ecommunity_cmp (entry->u.ecom, arg)) - return entry; - break; - case LARGE_COMMUNITY_LIST_STANDARD: - if (entry->direct == direct && lcommunity_cmp (entry->u.lcom, arg)) - return entry; - break; - case COMMUNITY_LIST_EXPANDED: - case EXTCOMMUNITY_LIST_EXPANDED: - case LARGE_COMMUNITY_LIST_EXPANDED: - if (entry->direct == direct && strcmp (entry->config, arg) == 0) - return entry; - break; - default: - break; - } - } - return NULL; + struct community_entry *entry; + + for (entry = list->head; entry; entry = entry->next) { + switch (entry->style) { + case COMMUNITY_LIST_STANDARD: + if (entry->direct == direct + && community_cmp(entry->u.com, arg)) + return entry; + break; + case EXTCOMMUNITY_LIST_STANDARD: + if (entry->direct == direct + && ecommunity_cmp(entry->u.ecom, arg)) + return entry; + break; + case LARGE_COMMUNITY_LIST_STANDARD: + if (entry->direct == direct + && lcommunity_cmp(entry->u.lcom, arg)) + return entry; + break; + case COMMUNITY_LIST_EXPANDED: + case EXTCOMMUNITY_LIST_EXPANDED: + case LARGE_COMMUNITY_LIST_EXPANDED: + if (entry->direct == direct + && strcmp(entry->config, arg) == 0) + return entry; + break; + default: + break; + } + } + return NULL; } -static char * -community_str_get (struct community *com, int i) +static char *community_str_get(struct community *com, int i) { - int len; - u_int32_t comval; - u_int16_t as; - u_int16_t val; - char *str; - char *pnt; - - memcpy (&comval, com_nthval (com, i), sizeof (u_int32_t)); - comval = ntohl (comval); - - switch (comval) - { - case COMMUNITY_INTERNET: - len = strlen (" internet"); - break; - case COMMUNITY_NO_EXPORT: - len = strlen (" no-export"); - break; - case COMMUNITY_NO_ADVERTISE: - len = strlen (" no-advertise"); - break; - case COMMUNITY_LOCAL_AS: - len = strlen (" local-AS"); - break; - default: - len = strlen (" 65536:65535"); - break; - } - - /* Allocate memory. */ - str = pnt = XMALLOC (MTYPE_COMMUNITY_STR, len); + int len; + u_int32_t comval; + u_int16_t as; + u_int16_t val; + char *str; + char *pnt; + + memcpy(&comval, com_nthval(com, i), sizeof(u_int32_t)); + comval = ntohl(comval); + + switch (comval) { + case COMMUNITY_INTERNET: + len = strlen(" internet"); + break; + case COMMUNITY_NO_EXPORT: + len = strlen(" no-export"); + break; + case COMMUNITY_NO_ADVERTISE: + len = strlen(" no-advertise"); + break; + case COMMUNITY_LOCAL_AS: + len = strlen(" local-AS"); + break; + default: + len = strlen(" 65536:65535"); + break; + } - switch (comval) - { - case COMMUNITY_INTERNET: - strcpy (pnt, "internet"); - pnt += strlen ("internet"); - break; - case COMMUNITY_NO_EXPORT: - strcpy (pnt, "no-export"); - pnt += strlen ("no-export"); - break; - case COMMUNITY_NO_ADVERTISE: - strcpy (pnt, "no-advertise"); - pnt += strlen ("no-advertise"); - break; - case COMMUNITY_LOCAL_AS: - strcpy (pnt, "local-AS"); - pnt += strlen ("local-AS"); - break; - default: - as = (comval >> 16) & 0xFFFF; - val = comval & 0xFFFF; - sprintf (pnt, "%u:%d", as, val); - pnt += strlen (pnt); - break; - } + /* Allocate memory. */ + str = pnt = XMALLOC(MTYPE_COMMUNITY_STR, len); + + switch (comval) { + case COMMUNITY_INTERNET: + strcpy(pnt, "internet"); + pnt += strlen("internet"); + break; + case COMMUNITY_NO_EXPORT: + strcpy(pnt, "no-export"); + pnt += strlen("no-export"); + break; + case COMMUNITY_NO_ADVERTISE: + strcpy(pnt, "no-advertise"); + pnt += strlen("no-advertise"); + break; + case COMMUNITY_LOCAL_AS: + strcpy(pnt, "local-AS"); + pnt += strlen("local-AS"); + break; + default: + as = (comval >> 16) & 0xFFFF; + val = comval & 0xFFFF; + sprintf(pnt, "%u:%d", as, val); + pnt += strlen(pnt); + break; + } - *pnt = '\0'; + *pnt = '\0'; - return str; + return str; } /* Internal function to perform regular expression match for * a single community. */ -static int -community_regexp_include (regex_t * reg, struct community *com, int i) +static int community_regexp_include(regex_t *reg, struct community *com, int i) { - char *str; - int rv; + char *str; + int rv; - /* When there is no communities attribute it is treated as empty string. */ - if (com == NULL || com->size == 0) - str = XSTRDUP(MTYPE_COMMUNITY_STR, ""); - else - str = community_str_get (com, i); + /* When there is no communities attribute it is treated as empty string. + */ + if (com == NULL || com->size == 0) + str = XSTRDUP(MTYPE_COMMUNITY_STR, ""); + else + str = community_str_get(com, i); - /* Regular expression match. */ - rv = regexec (reg, str, 0, NULL, 0); + /* Regular expression match. */ + rv = regexec(reg, str, 0, NULL, 0); - XFREE(MTYPE_COMMUNITY_STR, str); + XFREE(MTYPE_COMMUNITY_STR, str); - if (rv == 0) - return 1; + if (rv == 0) + return 1; - /* No match. */ - return 0; + /* No match. */ + return 0; } /* Internal function to perform regular expression match for community attribute. */ -static int -community_regexp_match (struct community *com, regex_t * reg) +static int community_regexp_match(struct community *com, regex_t *reg) { - const char *str; + const char *str; - /* When there is no communities attribute it is treated as empty - string. */ - if (com == NULL || com->size == 0) - str = ""; - else - str = community_str (com); + /* When there is no communities attribute it is treated as empty + string. */ + if (com == NULL || com->size == 0) + str = ""; + else + str = community_str(com); - /* Regular expression match. */ - if (regexec (reg, str, 0, NULL, 0) == 0) - return 1; + /* Regular expression match. */ + if (regexec(reg, str, 0, NULL, 0) == 0) + return 1; - /* No match. */ - return 0; + /* No match. */ + return 0; } -static char * -lcommunity_str_get (struct lcommunity *lcom, int i) +static char *lcommunity_str_get(struct lcommunity *lcom, int i) { - struct lcommunity_val lcomval; - u_int32_t globaladmin; - u_int32_t localdata1; - u_int32_t localdata2; - char *str; - u_char *ptr; - char *pnt; - - ptr = lcom->val; - ptr += (i * LCOMMUNITY_SIZE); - - memcpy (&lcomval, ptr, LCOMMUNITY_SIZE); - - /* Allocate memory. 48 bytes taken off bgp_lcommunity.c */ - str = pnt = XMALLOC (MTYPE_LCOMMUNITY_STR, 48); - - ptr = (u_char *)lcomval.val; - globaladmin = (*ptr++ << 24); - globaladmin |= (*ptr++ << 16); - globaladmin |= (*ptr++ << 8); - globaladmin |= (*ptr++); - - localdata1 = (*ptr++ << 24); - localdata1 |= (*ptr++ << 16); - localdata1 |= (*ptr++ << 8); - localdata1 |= (*ptr++); - - localdata2 = (*ptr++ << 24); - localdata2 |= (*ptr++ << 16); - localdata2 |= (*ptr++ << 8); - localdata2 |= (*ptr++); - - sprintf (pnt, "%u:%u:%u", globaladmin, localdata1, localdata2); - pnt += strlen (pnt); - *pnt = '\0'; - - return str; + struct lcommunity_val lcomval; + u_int32_t globaladmin; + u_int32_t localdata1; + u_int32_t localdata2; + char *str; + u_char *ptr; + char *pnt; + + ptr = lcom->val; + ptr += (i * LCOMMUNITY_SIZE); + + memcpy(&lcomval, ptr, LCOMMUNITY_SIZE); + + /* Allocate memory. 48 bytes taken off bgp_lcommunity.c */ + str = pnt = XMALLOC(MTYPE_LCOMMUNITY_STR, 48); + + ptr = (u_char *)lcomval.val; + globaladmin = (*ptr++ << 24); + globaladmin |= (*ptr++ << 16); + globaladmin |= (*ptr++ << 8); + globaladmin |= (*ptr++); + + localdata1 = (*ptr++ << 24); + localdata1 |= (*ptr++ << 16); + localdata1 |= (*ptr++ << 8); + localdata1 |= (*ptr++); + + localdata2 = (*ptr++ << 24); + localdata2 |= (*ptr++ << 16); + localdata2 |= (*ptr++ << 8); + localdata2 |= (*ptr++); + + sprintf(pnt, "%u:%u:%u", globaladmin, localdata1, localdata2); + pnt += strlen(pnt); + *pnt = '\0'; + + return str; } /* Internal function to perform regular expression match for * a single community. */ -static int -lcommunity_regexp_include (regex_t * reg, struct lcommunity *lcom, int i) +static int lcommunity_regexp_include(regex_t *reg, struct lcommunity *lcom, + int i) { - char *str; - - /* When there is no communities attribute it is treated as empty string. */ - if (lcom == NULL || lcom->size == 0) - str = XSTRDUP (MTYPE_LCOMMUNITY_STR, ""); - else - str = lcommunity_str_get (lcom, i); - - /* Regular expression match. */ - if (regexec (reg, str, 0, NULL, 0) == 0) - { - XFREE (MTYPE_LCOMMUNITY_STR, str); - return 1; - } + char *str; + + /* When there is no communities attribute it is treated as empty string. + */ + if (lcom == NULL || lcom->size == 0) + str = XSTRDUP(MTYPE_LCOMMUNITY_STR, ""); + else + str = lcommunity_str_get(lcom, i); + + /* Regular expression match. */ + if (regexec(reg, str, 0, NULL, 0) == 0) { + XFREE(MTYPE_LCOMMUNITY_STR, str); + return 1; + } - XFREE (MTYPE_LCOMMUNITY_STR, str); - /* No match. */ - return 0; + XFREE(MTYPE_LCOMMUNITY_STR, str); + /* No match. */ + return 0; } -static int -lcommunity_regexp_match (struct lcommunity *com, regex_t * reg) +static int lcommunity_regexp_match(struct lcommunity *com, regex_t *reg) { - const char *str; + const char *str; - /* When there is no communities attribute it is treated as empty - string. */ - if (com == NULL || com->size == 0) - str = ""; - else - str = lcommunity_str (com); + /* When there is no communities attribute it is treated as empty + string. */ + if (com == NULL || com->size == 0) + str = ""; + else + str = lcommunity_str(com); - /* Regular expression match. */ - if (regexec (reg, str, 0, NULL, 0) == 0) - return 1; + /* Regular expression match. */ + if (regexec(reg, str, 0, NULL, 0) == 0) + return 1; - /* No match. */ - return 0; + /* No match. */ + return 0; } -static int -ecommunity_regexp_match (struct ecommunity *ecom, regex_t * reg) +static int ecommunity_regexp_match(struct ecommunity *ecom, regex_t *reg) { - const char *str; + const char *str; - /* When there is no communities attribute it is treated as empty - string. */ - if (ecom == NULL || ecom->size == 0) - str = ""; - else - str = ecommunity_str (ecom); + /* When there is no communities attribute it is treated as empty + string. */ + if (ecom == NULL || ecom->size == 0) + str = ""; + else + str = ecommunity_str(ecom); - /* Regular expression match. */ - if (regexec (reg, str, 0, NULL, 0) == 0) - return 1; + /* Regular expression match. */ + if (regexec(reg, str, 0, NULL, 0) == 0) + return 1; - /* No match. */ - return 0; + /* No match. */ + return 0; } #if 0 @@ -619,661 +597,607 @@ community_regexp_delete (struct community *com, regex_t * reg) /* When given community attribute matches to the community-list return 1 else return 0. */ -int -community_list_match (struct community *com, struct community_list *list) +int community_list_match(struct community *com, struct community_list *list) { - struct community_entry *entry; - - for (entry = list->head; entry; entry = entry->next) - { - if (entry->any) - return entry->direct == COMMUNITY_PERMIT ? 1 : 0; - - if (entry->style == COMMUNITY_LIST_STANDARD) - { - if (community_include (entry->u.com, COMMUNITY_INTERNET)) - return entry->direct == COMMUNITY_PERMIT ? 1 : 0; - - if (community_match (com, entry->u.com)) - return entry->direct == COMMUNITY_PERMIT ? 1 : 0; - } - else if (entry->style == COMMUNITY_LIST_EXPANDED) - { - if (community_regexp_match (com, entry->reg)) - return entry->direct == COMMUNITY_PERMIT ? 1 : 0; - } - } - return 0; + struct community_entry *entry; + + for (entry = list->head; entry; entry = entry->next) { + if (entry->any) + return entry->direct == COMMUNITY_PERMIT ? 1 : 0; + + if (entry->style == COMMUNITY_LIST_STANDARD) { + if (community_include(entry->u.com, COMMUNITY_INTERNET)) + return entry->direct == COMMUNITY_PERMIT ? 1 + : 0; + + if (community_match(com, entry->u.com)) + return entry->direct == COMMUNITY_PERMIT ? 1 + : 0; + } else if (entry->style == COMMUNITY_LIST_EXPANDED) { + if (community_regexp_match(com, entry->reg)) + return entry->direct == COMMUNITY_PERMIT ? 1 + : 0; + } + } + return 0; } -int -lcommunity_list_match (struct lcommunity *lcom, struct community_list *list) +int lcommunity_list_match(struct lcommunity *lcom, struct community_list *list) { - struct community_entry *entry; - - for (entry = list->head; entry; entry = entry->next) - { - if (entry->any) - return entry->direct == COMMUNITY_PERMIT ? 1 : 0; - - if (entry->style == LARGE_COMMUNITY_LIST_STANDARD) - { - if (lcommunity_match (lcom, entry->u.lcom)) - return entry->direct == COMMUNITY_PERMIT ? 1 : 0; - } - else if (entry->style == LARGE_COMMUNITY_LIST_EXPANDED) - { - if (lcommunity_regexp_match (lcom, entry->reg)) - return entry->direct == COMMUNITY_PERMIT ? 1 : 0; - } - } - return 0; + struct community_entry *entry; + + for (entry = list->head; entry; entry = entry->next) { + if (entry->any) + return entry->direct == COMMUNITY_PERMIT ? 1 : 0; + + if (entry->style == LARGE_COMMUNITY_LIST_STANDARD) { + if (lcommunity_match(lcom, entry->u.lcom)) + return entry->direct == COMMUNITY_PERMIT ? 1 + : 0; + } else if (entry->style == LARGE_COMMUNITY_LIST_EXPANDED) { + if (lcommunity_regexp_match(lcom, entry->reg)) + return entry->direct == COMMUNITY_PERMIT ? 1 + : 0; + } + } + return 0; } -int -ecommunity_list_match (struct ecommunity *ecom, struct community_list *list) +int ecommunity_list_match(struct ecommunity *ecom, struct community_list *list) { - struct community_entry *entry; - - for (entry = list->head; entry; entry = entry->next) - { - if (entry->any) - return entry->direct == COMMUNITY_PERMIT ? 1 : 0; - - if (entry->style == EXTCOMMUNITY_LIST_STANDARD) - { - if (ecommunity_match (ecom, entry->u.ecom)) - return entry->direct == COMMUNITY_PERMIT ? 1 : 0; - } - else if (entry->style == EXTCOMMUNITY_LIST_EXPANDED) - { - if (ecommunity_regexp_match (ecom, entry->reg)) - return entry->direct == COMMUNITY_PERMIT ? 1 : 0; - } - } - return 0; + struct community_entry *entry; + + for (entry = list->head; entry; entry = entry->next) { + if (entry->any) + return entry->direct == COMMUNITY_PERMIT ? 1 : 0; + + if (entry->style == EXTCOMMUNITY_LIST_STANDARD) { + if (ecommunity_match(ecom, entry->u.ecom)) + return entry->direct == COMMUNITY_PERMIT ? 1 + : 0; + } else if (entry->style == EXTCOMMUNITY_LIST_EXPANDED) { + if (ecommunity_regexp_match(ecom, entry->reg)) + return entry->direct == COMMUNITY_PERMIT ? 1 + : 0; + } + } + return 0; } /* Perform exact matching. In case of expanded community-list, do same thing as community_list_match(). */ -int -community_list_exact_match (struct community *com, - struct community_list *list) +int community_list_exact_match(struct community *com, + struct community_list *list) { - struct community_entry *entry; - - for (entry = list->head; entry; entry = entry->next) - { - if (entry->any) - return entry->direct == COMMUNITY_PERMIT ? 1 : 0; - - if (entry->style == COMMUNITY_LIST_STANDARD) - { - if (community_include (entry->u.com, COMMUNITY_INTERNET)) - return entry->direct == COMMUNITY_PERMIT ? 1 : 0; - - if (community_cmp (com, entry->u.com)) - return entry->direct == COMMUNITY_PERMIT ? 1 : 0; - } - else if (entry->style == COMMUNITY_LIST_EXPANDED) - { - if (community_regexp_match (com, entry->reg)) - return entry->direct == COMMUNITY_PERMIT ? 1 : 0; - } - } - return 0; + struct community_entry *entry; + + for (entry = list->head; entry; entry = entry->next) { + if (entry->any) + return entry->direct == COMMUNITY_PERMIT ? 1 : 0; + + if (entry->style == COMMUNITY_LIST_STANDARD) { + if (community_include(entry->u.com, COMMUNITY_INTERNET)) + return entry->direct == COMMUNITY_PERMIT ? 1 + : 0; + + if (community_cmp(com, entry->u.com)) + return entry->direct == COMMUNITY_PERMIT ? 1 + : 0; + } else if (entry->style == COMMUNITY_LIST_EXPANDED) { + if (community_regexp_match(com, entry->reg)) + return entry->direct == COMMUNITY_PERMIT ? 1 + : 0; + } + } + return 0; } /* Delete all permitted communities in the list from com. */ -struct community * -community_list_match_delete (struct community *com, - struct community_list *list) +struct community *community_list_match_delete(struct community *com, + struct community_list *list) { - struct community_entry *entry; - u_int32_t val; - u_int32_t com_index_to_delete[com->size]; - int delete_index = 0; - int i; - - /* Loop over each community value and evaluate each against the - * community-list. If we need to delete a community value add its index to - * com_index_to_delete. - */ - for (i = 0; i < com->size; i++) - { - val = community_val_get (com, i); + struct community_entry *entry; + u_int32_t val; + u_int32_t com_index_to_delete[com->size]; + int delete_index = 0; + int i; + + /* Loop over each community value and evaluate each against the + * community-list. If we need to delete a community value add its index + * to + * com_index_to_delete. + */ + for (i = 0; i < com->size; i++) { + val = community_val_get(com, i); + + for (entry = list->head; entry; entry = entry->next) { + if (entry->any) { + if (entry->direct == COMMUNITY_PERMIT) { + com_index_to_delete[delete_index] = i; + delete_index++; + } + break; + } + + else if ((entry->style == COMMUNITY_LIST_STANDARD) + && (community_include(entry->u.com, + COMMUNITY_INTERNET) + || community_include(entry->u.com, val))) { + if (entry->direct == COMMUNITY_PERMIT) { + com_index_to_delete[delete_index] = i; + delete_index++; + } + break; + } + + else if ((entry->style == COMMUNITY_LIST_EXPANDED) + && community_regexp_include(entry->reg, com, + i)) { + if (entry->direct == COMMUNITY_PERMIT) { + com_index_to_delete[delete_index] = i; + delete_index++; + } + break; + } + } + } - for (entry = list->head; entry; entry = entry->next) - { - if (entry->any) - { - if (entry->direct == COMMUNITY_PERMIT) - { - com_index_to_delete[delete_index] = i; - delete_index++; - } - break; - } - - else if ((entry->style == COMMUNITY_LIST_STANDARD) - && (community_include (entry->u.com, COMMUNITY_INTERNET) - || community_include (entry->u.com, val) )) - { - if (entry->direct == COMMUNITY_PERMIT) - { - com_index_to_delete[delete_index] = i; - delete_index++; - } - break; - } - - else if ((entry->style == COMMUNITY_LIST_EXPANDED) - && community_regexp_include (entry->reg, com, i)) - { - if (entry->direct == COMMUNITY_PERMIT) - { - com_index_to_delete[delete_index] = i; - delete_index++; - } - break; - } - } - } - - /* Delete all of the communities we flagged for deletion */ - for (i = delete_index-1; i >= 0; i--) - { - val = community_val_get (com, com_index_to_delete[i]); - community_del_val (com, &val); - } + /* Delete all of the communities we flagged for deletion */ + for (i = delete_index - 1; i >= 0; i--) { + val = community_val_get(com, com_index_to_delete[i]); + community_del_val(com, &val); + } - return com; + return com; } /* To avoid duplicated entry in the community-list, this function compares specified entry to existing entry. */ -static int -community_list_dup_check (struct community_list *list, - struct community_entry *new) +static int community_list_dup_check(struct community_list *list, + struct community_entry *new) { - struct community_entry *entry; - - for (entry = list->head; entry; entry = entry->next) - { - if (entry->style != new->style) - continue; - - if (entry->direct != new->direct) - continue; - - if (entry->any != new->any) - continue; - - if (entry->any) - return 1; - - switch (entry->style) - { - case COMMUNITY_LIST_STANDARD: - if (community_cmp (entry->u.com, new->u.com)) - return 1; - break; - case LARGE_COMMUNITY_LIST_STANDARD: - if (lcommunity_cmp (entry->u.lcom, new->u.lcom)) - return 1; - break; - case EXTCOMMUNITY_LIST_STANDARD: - if (ecommunity_cmp (entry->u.ecom, new->u.ecom)) - return 1; - break; - case COMMUNITY_LIST_EXPANDED: - case EXTCOMMUNITY_LIST_EXPANDED: - case LARGE_COMMUNITY_LIST_EXPANDED: - if (strcmp (entry->config, new->config) == 0) - return 1; - break; - default: - break; - } - } - return 0; + struct community_entry *entry; + + for (entry = list->head; entry; entry = entry->next) { + if (entry->style != new->style) + continue; + + if (entry->direct != new->direct) + continue; + + if (entry->any != new->any) + continue; + + if (entry->any) + return 1; + + switch (entry->style) { + case COMMUNITY_LIST_STANDARD: + if (community_cmp(entry->u.com, new->u.com)) + return 1; + break; + case LARGE_COMMUNITY_LIST_STANDARD: + if (lcommunity_cmp(entry->u.lcom, new->u.lcom)) + return 1; + break; + case EXTCOMMUNITY_LIST_STANDARD: + if (ecommunity_cmp(entry->u.ecom, new->u.ecom)) + return 1; + break; + case COMMUNITY_LIST_EXPANDED: + case EXTCOMMUNITY_LIST_EXPANDED: + case LARGE_COMMUNITY_LIST_EXPANDED: + if (strcmp(entry->config, new->config) == 0) + return 1; + break; + default: + break; + } + } + return 0; } /* Set community-list. */ -int -community_list_set (struct community_list_handler *ch, - const char *name, const char *str, int direct, int style) +int community_list_set(struct community_list_handler *ch, const char *name, + const char *str, int direct, int style) { - struct community_entry *entry = NULL; - struct community_list *list; - struct community *com = NULL; - regex_t *regex = NULL; - - /* Get community list. */ - list = community_list_get (ch, name, COMMUNITY_LIST_MASTER); - - /* When community-list already has entry, new entry should have same - style. If you want to have mixed style community-list, you can - comment out this check. */ - if (!community_list_empty_p (list)) - { - struct community_entry *first; - - first = list->head; - - if (style != first->style) - { - return (first->style == COMMUNITY_LIST_STANDARD - ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT - : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT); + struct community_entry *entry = NULL; + struct community_list *list; + struct community *com = NULL; + regex_t *regex = NULL; + + /* Get community list. */ + list = community_list_get(ch, name, COMMUNITY_LIST_MASTER); + + /* When community-list already has entry, new entry should have same + style. If you want to have mixed style community-list, you can + comment out this check. */ + if (!community_list_empty_p(list)) { + struct community_entry *first; + + first = list->head; + + if (style != first->style) { + return (first->style == COMMUNITY_LIST_STANDARD + ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT + : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT); + } } - } - if (str) - { - if (style == COMMUNITY_LIST_STANDARD) - com = community_str2com (str); - else - regex = bgp_regcomp (str); + if (str) { + if (style == COMMUNITY_LIST_STANDARD) + com = community_str2com(str); + else + regex = bgp_regcomp(str); - if (! com && ! regex) - return COMMUNITY_LIST_ERR_MALFORMED_VAL; - } + if (!com && !regex) + return COMMUNITY_LIST_ERR_MALFORMED_VAL; + } - entry = community_entry_new (); - entry->direct = direct; - entry->style = style; - entry->any = (str ? 0 : 1); - entry->u.com = com; - entry->reg = regex; - entry->config = (regex ? XSTRDUP (MTYPE_COMMUNITY_LIST_CONFIG, str) : NULL); - - /* Do not put duplicated community entry. */ - if (community_list_dup_check (list, entry)) - community_entry_free (entry); - else - { - community_list_entry_add (list, entry); - route_map_notify_dependencies(name, RMAP_EVENT_CLIST_ADDED); - } + entry = community_entry_new(); + entry->direct = direct; + entry->style = style; + entry->any = (str ? 0 : 1); + entry->u.com = com; + entry->reg = regex; + entry->config = + (regex ? XSTRDUP(MTYPE_COMMUNITY_LIST_CONFIG, str) : NULL); + + /* Do not put duplicated community entry. */ + if (community_list_dup_check(list, entry)) + community_entry_free(entry); + else { + community_list_entry_add(list, entry); + route_map_notify_dependencies(name, RMAP_EVENT_CLIST_ADDED); + } - return 0; + return 0; } /* Unset community-list */ -int -community_list_unset (struct community_list_handler *ch, - const char *name, const char *str, - int direct, int style, int delete_all) +int community_list_unset(struct community_list_handler *ch, const char *name, + const char *str, int direct, int style, int delete_all) { - struct community_entry *entry = NULL; - struct community_list *list; - struct community *com = NULL; - - /* Lookup community list. */ - list = community_list_lookup (ch, name, COMMUNITY_LIST_MASTER); - if (list == NULL) - return COMMUNITY_LIST_ERR_CANT_FIND_LIST; - - /* Delete all of entry belongs to this community-list. */ - if (delete_all) - { - community_list_delete (list); - route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED); - return 0; - } + struct community_entry *entry = NULL; + struct community_list *list; + struct community *com = NULL; + + /* Lookup community list. */ + list = community_list_lookup(ch, name, COMMUNITY_LIST_MASTER); + if (list == NULL) + return COMMUNITY_LIST_ERR_CANT_FIND_LIST; + + /* Delete all of entry belongs to this community-list. */ + if (delete_all) { + community_list_delete(list); + route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED); + return 0; + } - if (style == COMMUNITY_LIST_STANDARD) - { - if (str) - com = community_str2com (str); - } + if (style == COMMUNITY_LIST_STANDARD) { + if (str) + com = community_str2com(str); + } - if (com) - { - entry = community_list_entry_lookup (list, com, direct); - community_free (com); - } - else - entry = community_list_entry_lookup (list, str, direct); + if (com) { + entry = community_list_entry_lookup(list, com, direct); + community_free(com); + } else + entry = community_list_entry_lookup(list, str, direct); - if (!entry) - return COMMUNITY_LIST_ERR_CANT_FIND_LIST; + if (!entry) + return COMMUNITY_LIST_ERR_CANT_FIND_LIST; - community_list_entry_delete (list, entry, style); - route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED); + community_list_entry_delete(list, entry, style); + route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED); - return 0; + return 0; } /* Delete all permitted large communities in the list from com. */ -struct lcommunity * -lcommunity_list_match_delete (struct lcommunity *lcom, - struct community_list *list) +struct lcommunity *lcommunity_list_match_delete(struct lcommunity *lcom, + struct community_list *list) { - struct community_entry *entry; - u_int32_t com_index_to_delete[lcom->size]; - u_char *ptr; - int delete_index = 0; - int i; + struct community_entry *entry; + u_int32_t com_index_to_delete[lcom->size]; + u_char *ptr; + int delete_index = 0; + int i; + + /* Loop over each lcommunity value and evaluate each against the + * community-list. If we need to delete a community value add its index + * to + * com_index_to_delete. + */ + ptr = lcom->val; + for (i = 0; i < lcom->size; i++) { + ptr += (i * LCOMMUNITY_SIZE); + for (entry = list->head; entry; entry = entry->next) { + if (entry->any) { + if (entry->direct == COMMUNITY_PERMIT) { + com_index_to_delete[delete_index] = i; + delete_index++; + } + break; + } + + else if ((entry->style == LARGE_COMMUNITY_LIST_STANDARD) + && lcommunity_include(entry->u.lcom, ptr)) { + if (entry->direct == COMMUNITY_PERMIT) { + com_index_to_delete[delete_index] = i; + delete_index++; + } + break; + } + + else if ((entry->style == LARGE_COMMUNITY_LIST_STANDARD) + && lcommunity_regexp_include(entry->reg, lcom, + i)) { + if (entry->direct == COMMUNITY_PERMIT) { + com_index_to_delete[delete_index] = i; + delete_index++; + } + break; + } + } + } - /* Loop over each lcommunity value and evaluate each against the - * community-list. If we need to delete a community value add its index to - * com_index_to_delete. - */ - ptr = lcom->val; - for (i = 0; i < lcom->size; i++) - { - ptr += (i * LCOMMUNITY_SIZE); - for (entry = list->head; entry; entry = entry->next) - { - if (entry->any) - { - if (entry->direct == COMMUNITY_PERMIT) - { - com_index_to_delete[delete_index] = i; - delete_index++; - } - break; - } - - else if ((entry->style == LARGE_COMMUNITY_LIST_STANDARD) - && lcommunity_include (entry->u.lcom, ptr) ) - { - if (entry->direct == COMMUNITY_PERMIT) - { - com_index_to_delete[delete_index] = i; - delete_index++; - } - break; - } - - else if ((entry->style == LARGE_COMMUNITY_LIST_STANDARD) - && lcommunity_regexp_include (entry->reg, lcom, i)) - { - if (entry->direct == COMMUNITY_PERMIT) - { - com_index_to_delete[delete_index] = i; - delete_index++; - } - break; - } - } - } - - /* Delete all of the communities we flagged for deletion */ - ptr = lcom->val; - for (i = delete_index-1; i >= 0; i--) - { - ptr += (com_index_to_delete[i] * LCOMMUNITY_SIZE); - lcommunity_del_val (lcom, ptr); - } + /* Delete all of the communities we flagged for deletion */ + ptr = lcom->val; + for (i = delete_index - 1; i >= 0; i--) { + ptr += (com_index_to_delete[i] * LCOMMUNITY_SIZE); + lcommunity_del_val(lcom, ptr); + } - return lcom; + return lcom; } /* Set lcommunity-list. */ -int -lcommunity_list_set (struct community_list_handler *ch, - const char *name, const char *str, int direct, int style) +int lcommunity_list_set(struct community_list_handler *ch, const char *name, + const char *str, int direct, int style) { - struct community_entry *entry = NULL; - struct community_list *list; - struct lcommunity *lcom = NULL; - regex_t *regex = NULL; - - /* Get community list. */ - list = community_list_get (ch, name, LARGE_COMMUNITY_LIST_MASTER); - - /* When community-list already has entry, new entry should have same - style. If you want to have mixed style community-list, you can - comment out this check. */ - if (!community_list_empty_p (list)) - { - struct community_entry *first; - - first = list->head; + struct community_entry *entry = NULL; + struct community_list *list; + struct lcommunity *lcom = NULL; + regex_t *regex = NULL; + + /* Get community list. */ + list = community_list_get(ch, name, LARGE_COMMUNITY_LIST_MASTER); + + /* When community-list already has entry, new entry should have same + style. If you want to have mixed style community-list, you can + comment out this check. */ + if (!community_list_empty_p(list)) { + struct community_entry *first; + + first = list->head; + + if (style != first->style) { + return (first->style == COMMUNITY_LIST_STANDARD + ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT + : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT); + } + } - if (style != first->style) - { - return (first->style == COMMUNITY_LIST_STANDARD - ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT - : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT); - } - } + if (str) { + if (style == LARGE_COMMUNITY_LIST_STANDARD) + lcom = lcommunity_str2com(str); + else + regex = bgp_regcomp(str); - if (str) - { - if (style == LARGE_COMMUNITY_LIST_STANDARD) - lcom = lcommunity_str2com (str); - else - regex = bgp_regcomp (str); - - if (! lcom && ! regex) - return COMMUNITY_LIST_ERR_MALFORMED_VAL; - } + if (!lcom && !regex) + return COMMUNITY_LIST_ERR_MALFORMED_VAL; + } - entry = community_entry_new (); - entry->direct = direct; - entry->style = style; - entry->any = (str ? 0 : 1); - entry->u.lcom = lcom; - entry->reg = regex; - if (lcom) - entry->config = lcommunity_lcom2str (lcom, LCOMMUNITY_FORMAT_COMMUNITY_LIST); - else if (regex) - entry->config = XSTRDUP (MTYPE_COMMUNITY_LIST_CONFIG, str); - else - entry->config = NULL; - - /* Do not put duplicated community entry. */ - if (community_list_dup_check (list, entry)) - community_entry_free (entry); - else - community_list_entry_add (list, entry); - - return 0; + entry = community_entry_new(); + entry->direct = direct; + entry->style = style; + entry->any = (str ? 0 : 1); + entry->u.lcom = lcom; + entry->reg = regex; + if (lcom) + entry->config = lcommunity_lcom2str( + lcom, LCOMMUNITY_FORMAT_COMMUNITY_LIST); + else if (regex) + entry->config = XSTRDUP(MTYPE_COMMUNITY_LIST_CONFIG, str); + else + entry->config = NULL; + + /* Do not put duplicated community entry. */ + if (community_list_dup_check(list, entry)) + community_entry_free(entry); + else + community_list_entry_add(list, entry); + + return 0; } /* Unset community-list. When str is NULL, delete all of community-list entry belongs to the specified name. */ -int -lcommunity_list_unset (struct community_list_handler *ch, - const char *name, const char *str, - int direct, int style) +int lcommunity_list_unset(struct community_list_handler *ch, const char *name, + const char *str, int direct, int style) { - struct community_entry *entry = NULL; - struct community_list *list; - struct lcommunity *lcom = NULL; - regex_t *regex = NULL; - - /* Lookup community list. */ - list = community_list_lookup (ch, name, LARGE_COMMUNITY_LIST_MASTER); - if (list == NULL) - return COMMUNITY_LIST_ERR_CANT_FIND_LIST; - - /* Delete all of entry belongs to this community-list. */ - if (!str) - { - community_list_delete (list); - return 0; - } + struct community_entry *entry = NULL; + struct community_list *list; + struct lcommunity *lcom = NULL; + regex_t *regex = NULL; + + /* Lookup community list. */ + list = community_list_lookup(ch, name, LARGE_COMMUNITY_LIST_MASTER); + if (list == NULL) + return COMMUNITY_LIST_ERR_CANT_FIND_LIST; + + /* Delete all of entry belongs to this community-list. */ + if (!str) { + community_list_delete(list); + return 0; + } - if (style == LARGE_COMMUNITY_LIST_STANDARD) - lcom = lcommunity_str2com (str); - else - regex = bgp_regcomp (str); + if (style == LARGE_COMMUNITY_LIST_STANDARD) + lcom = lcommunity_str2com(str); + else + regex = bgp_regcomp(str); - if (! lcom && ! regex) - return COMMUNITY_LIST_ERR_MALFORMED_VAL; + if (!lcom && !regex) + return COMMUNITY_LIST_ERR_MALFORMED_VAL; - if (lcom) - entry = community_list_entry_lookup (list, lcom, direct); - else - entry = community_list_entry_lookup (list, str, direct); + if (lcom) + entry = community_list_entry_lookup(list, lcom, direct); + else + entry = community_list_entry_lookup(list, str, direct); - if (lcom) - lcommunity_free (&lcom); - if (regex) - bgp_regex_free (regex); + if (lcom) + lcommunity_free(&lcom); + if (regex) + bgp_regex_free(regex); - if (!entry) - return COMMUNITY_LIST_ERR_CANT_FIND_LIST; + if (!entry) + return COMMUNITY_LIST_ERR_CANT_FIND_LIST; - community_list_entry_delete (list, entry, style); + community_list_entry_delete(list, entry, style); - return 0; + return 0; } /* Set extcommunity-list. */ -int -extcommunity_list_set (struct community_list_handler *ch, - const char *name, const char *str, - int direct, int style) +int extcommunity_list_set(struct community_list_handler *ch, const char *name, + const char *str, int direct, int style) { - struct community_entry *entry = NULL; - struct community_list *list; - struct ecommunity *ecom = NULL; - regex_t *regex = NULL; + struct community_entry *entry = NULL; + struct community_list *list; + struct ecommunity *ecom = NULL; + regex_t *regex = NULL; - entry = NULL; + entry = NULL; - /* Get community list. */ - list = community_list_get (ch, name, EXTCOMMUNITY_LIST_MASTER); + /* Get community list. */ + list = community_list_get(ch, name, EXTCOMMUNITY_LIST_MASTER); - /* When community-list already has entry, new entry should have same - style. If you want to have mixed style community-list, you can - comment out this check. */ - if (!community_list_empty_p (list)) - { - struct community_entry *first; + /* When community-list already has entry, new entry should have same + style. If you want to have mixed style community-list, you can + comment out this check. */ + if (!community_list_empty_p(list)) { + struct community_entry *first; - first = list->head; + first = list->head; - if (style != first->style) - { - return (first->style == EXTCOMMUNITY_LIST_STANDARD - ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT - : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT); + if (style != first->style) { + return (first->style == EXTCOMMUNITY_LIST_STANDARD + ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT + : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT); + } } - } - if (style == EXTCOMMUNITY_LIST_STANDARD) - ecom = ecommunity_str2com (str, 0, 1); - else - regex = bgp_regcomp (str); - - if (! ecom && ! regex) - return COMMUNITY_LIST_ERR_MALFORMED_VAL; - - if (ecom) - ecom->str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_DISPLAY, 0); - - entry = community_entry_new (); - entry->direct = direct; - entry->style = style; - entry->any = (str ? 0 : 1); - if (ecom) - entry->config = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_COMMUNITY_LIST, 0); - else if (regex) - entry->config = XSTRDUP (MTYPE_COMMUNITY_LIST_CONFIG, str); - - entry->u.ecom = ecom; - entry->reg = regex; - - /* Do not put duplicated community entry. */ - if (community_list_dup_check (list, entry)) - community_entry_free (entry); - else - { - community_list_entry_add (list, entry); - route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_ADDED); - } + if (style == EXTCOMMUNITY_LIST_STANDARD) + ecom = ecommunity_str2com(str, 0, 1); + else + regex = bgp_regcomp(str); + + if (!ecom && !regex) + return COMMUNITY_LIST_ERR_MALFORMED_VAL; + + if (ecom) + ecom->str = + ecommunity_ecom2str(ecom, ECOMMUNITY_FORMAT_DISPLAY, 0); + + entry = community_entry_new(); + entry->direct = direct; + entry->style = style; + entry->any = (str ? 0 : 1); + if (ecom) + entry->config = ecommunity_ecom2str( + ecom, ECOMMUNITY_FORMAT_COMMUNITY_LIST, 0); + else if (regex) + entry->config = XSTRDUP(MTYPE_COMMUNITY_LIST_CONFIG, str); + + entry->u.ecom = ecom; + entry->reg = regex; + + /* Do not put duplicated community entry. */ + if (community_list_dup_check(list, entry)) + community_entry_free(entry); + else { + community_list_entry_add(list, entry); + route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_ADDED); + } - return 0; + return 0; } /* Unset extcommunity-list. When str is NULL, delete all of extcommunity-list entry belongs to the specified name. */ -int -extcommunity_list_unset (struct community_list_handler *ch, - const char *name, const char *str, - int direct, int style, int delete_all) +int extcommunity_list_unset(struct community_list_handler *ch, const char *name, + const char *str, int direct, int style, + int delete_all) { - struct community_entry *entry = NULL; - struct community_list *list; - struct ecommunity *ecom = NULL; - - /* Lookup extcommunity list. */ - list = community_list_lookup (ch, name, EXTCOMMUNITY_LIST_MASTER); - if (list == NULL) - return COMMUNITY_LIST_ERR_CANT_FIND_LIST; - - /* Delete all of entry belongs to this extcommunity-list. */ - if (delete_all) - { - community_list_delete (list); - route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED); - return 0; - } + struct community_entry *entry = NULL; + struct community_list *list; + struct ecommunity *ecom = NULL; + + /* Lookup extcommunity list. */ + list = community_list_lookup(ch, name, EXTCOMMUNITY_LIST_MASTER); + if (list == NULL) + return COMMUNITY_LIST_ERR_CANT_FIND_LIST; + + /* Delete all of entry belongs to this extcommunity-list. */ + if (delete_all) { + community_list_delete(list); + route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED); + return 0; + } - if (style == EXTCOMMUNITY_LIST_STANDARD) - { - if (str) - ecom = ecommunity_str2com (str, 0, 1); - } + if (style == EXTCOMMUNITY_LIST_STANDARD) { + if (str) + ecom = ecommunity_str2com(str, 0, 1); + } - if (ecom) - { - entry = community_list_entry_lookup (list, ecom, direct); - ecommunity_free (&ecom); - } - else - entry = community_list_entry_lookup (list, str, direct); + if (ecom) { + entry = community_list_entry_lookup(list, ecom, direct); + ecommunity_free(&ecom); + } else + entry = community_list_entry_lookup(list, str, direct); - if (!entry) - return COMMUNITY_LIST_ERR_CANT_FIND_LIST; + if (!entry) + return COMMUNITY_LIST_ERR_CANT_FIND_LIST; - community_list_entry_delete (list, entry, style); - route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED); + community_list_entry_delete(list, entry, style); + route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED); - return 0; + return 0; } /* Initializa community-list. Return community-list handler. */ -struct community_list_handler * -community_list_init (void) +struct community_list_handler *community_list_init(void) { - struct community_list_handler *ch; - ch = XCALLOC (MTYPE_COMMUNITY_LIST_HANDLER, - sizeof (struct community_list_handler)); - return ch; + struct community_list_handler *ch; + ch = XCALLOC(MTYPE_COMMUNITY_LIST_HANDLER, + sizeof(struct community_list_handler)); + return ch; } /* Terminate community-list. */ -void -community_list_terminate (struct community_list_handler *ch) +void community_list_terminate(struct community_list_handler *ch) { - struct community_list_master *cm; - struct community_list *list; - - cm = &ch->community_list; - while ((list = cm->num.head) != NULL) - community_list_delete (list); - while ((list = cm->str.head) != NULL) - community_list_delete (list); - - cm = &ch->lcommunity_list; - while ((list = cm->num.head) != NULL) - community_list_delete (list); - while ((list = cm->str.head) != NULL) - community_list_delete (list); - - cm = &ch->extcommunity_list; - while ((list = cm->num.head) != NULL) - community_list_delete (list); - while ((list = cm->str.head) != NULL) - community_list_delete (list); - - XFREE (MTYPE_COMMUNITY_LIST_HANDLER, ch); + struct community_list_master *cm; + struct community_list *list; + + cm = &ch->community_list; + while ((list = cm->num.head) != NULL) + community_list_delete(list); + while ((list = cm->str.head) != NULL) + community_list_delete(list); + + cm = &ch->lcommunity_list; + while ((list = cm->num.head) != NULL) + community_list_delete(list); + while ((list = cm->str.head) != NULL) + community_list_delete(list); + + cm = &ch->extcommunity_list; + while ((list = cm->num.head) != NULL) + community_list_delete(list); + while ((list = cm->str.head) != NULL) + community_list_delete(list); + + XFREE(MTYPE_COMMUNITY_LIST_HANDLER, ch); } diff --git a/bgpd/bgp_clist.h b/bgpd/bgp_clist.h index 114acde8f..c21654f39 100644 --- a/bgpd/bgp_clist.h +++ b/bgpd/bgp_clist.h @@ -43,82 +43,76 @@ #define LARGE_COMMUNITY_LIST_EXPANDED 5 /* Expanded Large community-list. */ /* Community-list. */ -struct community_list -{ - /* Name of the community-list. */ - char *name; +struct community_list { + /* Name of the community-list. */ + char *name; - /* String or number. */ - int sort; + /* String or number. */ + int sort; - /* Link to upper list. */ - struct community_list_list *parent; + /* Link to upper list. */ + struct community_list_list *parent; - /* Linked list for other community-list. */ - struct community_list *next; - struct community_list *prev; + /* Linked list for other community-list. */ + struct community_list *next; + struct community_list *prev; - /* Community-list entry in this community-list. */ - struct community_entry *head; - struct community_entry *tail; + /* Community-list entry in this community-list. */ + struct community_entry *head; + struct community_entry *tail; }; /* Each entry in community-list. */ -struct community_entry -{ - struct community_entry *next; - struct community_entry *prev; +struct community_entry { + struct community_entry *next; + struct community_entry *prev; - /* Permit or deny. */ - u_char direct; + /* Permit or deny. */ + u_char direct; - /* Standard or expanded. */ - u_char style; + /* Standard or expanded. */ + u_char style; - /* Any match. */ - u_char any; + /* Any match. */ + u_char any; - /* Community structure. */ - union - { - struct community *com; - struct ecommunity *ecom; - struct lcommunity *lcom; - } u; + /* Community structure. */ + union { + struct community *com; + struct ecommunity *ecom; + struct lcommunity *lcom; + } u; - /* Configuration string. */ - char *config; + /* Configuration string. */ + char *config; - /* Expanded community-list regular expression. */ - regex_t *reg; + /* Expanded community-list regular expression. */ + regex_t *reg; }; /* Linked list of community-list. */ -struct community_list_list -{ - struct community_list *head; - struct community_list *tail; +struct community_list_list { + struct community_list *head; + struct community_list *tail; }; /* Master structure of community-list and extcommunity-list. */ -struct community_list_master -{ - struct community_list_list num; - struct community_list_list str; +struct community_list_master { + struct community_list_list num; + struct community_list_list str; }; /* Community-list handler. community_list_init() returns this structure as handler. */ -struct community_list_handler -{ - /* Community-list. */ - struct community_list_master community_list; +struct community_list_handler { + /* Community-list. */ + struct community_list_master community_list; - /* Exteded community-list. */ - struct community_list_master extcommunity_list; + /* Exteded community-list. */ + struct community_list_master extcommunity_list; - /* Large community-list. */ - struct community_list_master lcommunity_list; + /* Large community-list. */ + struct community_list_master lcommunity_list; }; /* Error code of community-list. */ @@ -131,42 +125,42 @@ struct community_list_handler extern struct community_list_handler *bgp_clist; /* Prototypes. */ -extern struct community_list_handler *community_list_init (void); -extern void community_list_terminate (struct community_list_handler *); - -extern int community_list_set (struct community_list_handler *ch, +extern struct community_list_handler *community_list_init(void); +extern void community_list_terminate(struct community_list_handler *); + +extern int community_list_set(struct community_list_handler *ch, + const char *name, const char *str, int direct, + int style); +extern int community_list_unset(struct community_list_handler *ch, + const char *name, const char *str, int direct, + int style, int delete_all); +extern int extcommunity_list_set(struct community_list_handler *ch, + const char *name, const char *str, int direct, + int style); +extern int extcommunity_list_unset(struct community_list_handler *ch, + const char *name, const char *str, + int direct, int style, int delete_all); +extern int lcommunity_list_set(struct community_list_handler *ch, const char *name, const char *str, int direct, int style); -extern int community_list_unset (struct community_list_handler *ch, - const char *name, const char *str, - int direct, int style, int delete_all); -extern int extcommunity_list_set (struct community_list_handler *ch, - const char *name, const char *str, - int direct, int style); -extern int extcommunity_list_unset (struct community_list_handler *ch, - const char *name, const char *str, - int direct, int style, int delete_all); -extern int lcommunity_list_set (struct community_list_handler *ch, - const char *name, const char *str, - int direct, int style); -extern int lcommunity_list_unset (struct community_list_handler *ch, - const char *name, const char *str, - int direct, int style); +extern int lcommunity_list_unset(struct community_list_handler *ch, + const char *name, const char *str, int direct, + int style); extern struct community_list_master * -community_list_master_lookup (struct community_list_handler *, int); +community_list_master_lookup(struct community_list_handler *, int); extern struct community_list * -community_list_lookup (struct community_list_handler *, const char *, int); - -extern int community_list_match (struct community *, struct community_list *); -extern int ecommunity_list_match (struct ecommunity *, struct community_list *); -extern int lcommunity_list_match (struct lcommunity *, struct community_list *); -extern int community_list_exact_match (struct community *, - struct community_list *); -extern struct community * -community_list_match_delete (struct community *, struct community_list *); +community_list_lookup(struct community_list_handler *, const char *, int); + +extern int community_list_match(struct community *, struct community_list *); +extern int ecommunity_list_match(struct ecommunity *, struct community_list *); +extern int lcommunity_list_match(struct lcommunity *, struct community_list *); +extern int community_list_exact_match(struct community *, + struct community_list *); +extern struct community *community_list_match_delete(struct community *, + struct community_list *); extern struct lcommunity * -lcommunity_list_match_delete (struct lcommunity *lcom, - struct community_list *list); +lcommunity_list_match_delete(struct lcommunity *lcom, + struct community_list *list); #endif /* _QUAGGA_BGP_CLIST_H */ diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c index be4cdac0a..389d723e0 100644 --- a/bgpd/bgp_community.c +++ b/bgpd/bgp_community.c @@ -31,667 +31,615 @@ static struct hash *comhash; /* Allocate a new communities value. */ -static struct community * -community_new (void) +static struct community *community_new(void) { - return (struct community *) XCALLOC (MTYPE_COMMUNITY, - sizeof (struct community)); + return (struct community *)XCALLOC(MTYPE_COMMUNITY, + sizeof(struct community)); } /* Free communities value. */ -void -community_free (struct community *com) +void community_free(struct community *com) { - if (com->val) - XFREE (MTYPE_COMMUNITY_VAL, com->val); - if (com->str) - XFREE (MTYPE_COMMUNITY_STR, com->str); - - if (com->json) - { - json_object_free(com->json); - com->json = NULL; - } - - XFREE (MTYPE_COMMUNITY, com); + if (com->val) + XFREE(MTYPE_COMMUNITY_VAL, com->val); + if (com->str) + XFREE(MTYPE_COMMUNITY_STR, com->str); + + if (com->json) { + json_object_free(com->json); + com->json = NULL; + } + + XFREE(MTYPE_COMMUNITY, com); } /* Add one community value to the community. */ -static void -community_add_val (struct community *com, u_int32_t val) +static void community_add_val(struct community *com, u_int32_t val) { - com->size++; - if (com->val) - com->val = XREALLOC (MTYPE_COMMUNITY_VAL, com->val, com_length (com)); - else - com->val = XMALLOC (MTYPE_COMMUNITY_VAL, com_length (com)); - - val = htonl (val); - memcpy (com_lastval (com), &val, sizeof (u_int32_t)); + com->size++; + if (com->val) + com->val = XREALLOC(MTYPE_COMMUNITY_VAL, com->val, + com_length(com)); + else + com->val = XMALLOC(MTYPE_COMMUNITY_VAL, com_length(com)); + + val = htonl(val); + memcpy(com_lastval(com), &val, sizeof(u_int32_t)); } /* Delete one community. */ -void -community_del_val (struct community *com, u_int32_t *val) +void community_del_val(struct community *com, u_int32_t *val) { - int i = 0; - int c = 0; - - if (! com->val) - return; - - while (i < com->size) - { - if (memcmp (com->val + i, val, sizeof (u_int32_t)) == 0) - { - c = com->size -i -1; - - if (c > 0) - memmove (com->val + i, com->val + (i + 1), c * sizeof (*val)); - - com->size--; - - if (com->size > 0) - com->val = XREALLOC (MTYPE_COMMUNITY_VAL, com->val, - com_length (com)); - else - { - XFREE (MTYPE_COMMUNITY_VAL, com->val); - com->val = NULL; - } - return; + int i = 0; + int c = 0; + + if (!com->val) + return; + + while (i < com->size) { + if (memcmp(com->val + i, val, sizeof(u_int32_t)) == 0) { + c = com->size - i - 1; + + if (c > 0) + memmove(com->val + i, com->val + (i + 1), + c * sizeof(*val)); + + com->size--; + + if (com->size > 0) + com->val = XREALLOC(MTYPE_COMMUNITY_VAL, + com->val, com_length(com)); + else { + XFREE(MTYPE_COMMUNITY_VAL, com->val); + com->val = NULL; + } + return; + } + i++; } - i++; - } } /* Delete all communities listed in com2 from com1 */ -struct community * -community_delete (struct community *com1, struct community *com2) +struct community *community_delete(struct community *com1, + struct community *com2) { - int i = 0; + int i = 0; - while(i < com2->size) - { - community_del_val (com1, com2->val + i); - i++; - } + while (i < com2->size) { + community_del_val(com1, com2->val + i); + i++; + } - return com1; + return com1; } /* Callback function from qsort(). */ -static int -community_compare (const void *a1, const void *a2) +static int community_compare(const void *a1, const void *a2) { - u_int32_t v1; - u_int32_t v2; - - memcpy (&v1, a1, sizeof (u_int32_t)); - memcpy (&v2, a2, sizeof (u_int32_t)); - v1 = ntohl (v1); - v2 = ntohl (v2); - - if (v1 < v2) - return -1; - if (v1 > v2) - return 1; - return 0; + u_int32_t v1; + u_int32_t v2; + + memcpy(&v1, a1, sizeof(u_int32_t)); + memcpy(&v2, a2, sizeof(u_int32_t)); + v1 = ntohl(v1); + v2 = ntohl(v2); + + if (v1 < v2) + return -1; + if (v1 > v2) + return 1; + return 0; } -int -community_include (struct community *com, u_int32_t val) +int community_include(struct community *com, u_int32_t val) { - int i; + int i; - val = htonl (val); + val = htonl(val); - for (i = 0; i < com->size; i++) - if (memcmp (&val, com_nthval (com, i), sizeof (u_int32_t)) == 0) - return 1; + for (i = 0; i < com->size; i++) + if (memcmp(&val, com_nthval(com, i), sizeof(u_int32_t)) == 0) + return 1; - return 0; + return 0; } -u_int32_t -community_val_get (struct community *com, int i) +u_int32_t community_val_get(struct community *com, int i) { - u_char *p; - u_int32_t val; + u_char *p; + u_int32_t val; - p = (u_char *) com->val; - p += (i * 4); + p = (u_char *)com->val; + p += (i * 4); - memcpy (&val, p, sizeof (u_int32_t)); + memcpy(&val, p, sizeof(u_int32_t)); - return ntohl (val); + return ntohl(val); } /* Sort and uniq given community. */ -struct community * -community_uniq_sort (struct community *com) +struct community *community_uniq_sort(struct community *com) { - int i; - struct community *new; - u_int32_t val; - - if (! com) - return NULL; - - new = community_new ();; - new->json = NULL; - - for (i = 0; i < com->size; i++) - { - val = community_val_get (com, i); - - if (! community_include (new, val)) - community_add_val (new, val); - } - - qsort (new->val, new->size, sizeof (u_int32_t), community_compare); - - return new; + int i; + struct community *new; + u_int32_t val; + + if (!com) + return NULL; + + new = community_new(); + ; + new->json = NULL; + + for (i = 0; i < com->size; i++) { + val = community_val_get(com, i); + + if (!community_include(new, val)) + community_add_val(new, val); + } + + qsort(new->val, new->size, sizeof(u_int32_t), community_compare); + + return new; } /* Convert communities attribute to string. For Well-known communities value, below keyword is used. - 0x0 "internet" + 0x0 "internet" 0xFFFFFF01 "no-export" 0xFFFFFF02 "no-advertise" 0xFFFFFF03 "local-AS" For other values, "AS:VAL" format is used. */ -static void -set_community_string (struct community *com) +static void set_community_string(struct community *com) { - int i; - char *str; - char *pnt; - int len; - int first; - u_int32_t comval; - u_int16_t as; - u_int16_t val; - json_object *json_community_list = NULL; - json_object *json_string = NULL; - - if (!com) - return; - - com->json = json_object_new_object(); - json_community_list = json_object_new_array(); - - /* When communities attribute is empty. */ - if (com->size == 0) - { - str = XMALLOC (MTYPE_COMMUNITY_STR, 1); - str[0] = '\0'; - - json_object_string_add(com->json, "string", ""); - json_object_object_add(com->json, "list", json_community_list); - com->str = str; - return; - } - - /* Memory allocation is time consuming work. So we calculate - required string length first. */ - len = 0; - - for (i = 0; i < com->size; i++) - { - memcpy (&comval, com_nthval (com, i), sizeof (u_int32_t)); - comval = ntohl (comval); - - switch (comval) - { - case COMMUNITY_INTERNET: - len += strlen (" internet"); - break; - case COMMUNITY_NO_EXPORT: - len += strlen (" no-export"); - break; - case COMMUNITY_NO_ADVERTISE: - len += strlen (" no-advertise"); - break; - case COMMUNITY_LOCAL_AS: - len += strlen (" local-AS"); - break; - default: - len += strlen (" 65536:65535"); - break; + int i; + char *str; + char *pnt; + int len; + int first; + u_int32_t comval; + u_int16_t as; + u_int16_t val; + json_object *json_community_list = NULL; + json_object *json_string = NULL; + + if (!com) + return; + + com->json = json_object_new_object(); + json_community_list = json_object_new_array(); + + /* When communities attribute is empty. */ + if (com->size == 0) { + str = XMALLOC(MTYPE_COMMUNITY_STR, 1); + str[0] = '\0'; + + json_object_string_add(com->json, "string", ""); + json_object_object_add(com->json, "list", json_community_list); + com->str = str; + return; } - } - - /* Allocate memory. */ - str = pnt = XMALLOC (MTYPE_COMMUNITY_STR, len); - first = 1; - - /* Fill in string. */ - for (i = 0; i < com->size; i++) - { - memcpy (&comval, com_nthval (com, i), sizeof (u_int32_t)); - comval = ntohl (comval); - - if (first) - first = 0; - else - *pnt++ = ' '; - - switch (comval) - { - case COMMUNITY_INTERNET: - strcpy (pnt, "internet"); - pnt += strlen ("internet"); - json_string = json_object_new_string("internet"); - json_object_array_add(json_community_list, json_string); - break; - case COMMUNITY_NO_EXPORT: - strcpy (pnt, "no-export"); - pnt += strlen ("no-export"); - json_string = json_object_new_string("noExport"); - json_object_array_add(json_community_list, json_string); - break; - case COMMUNITY_NO_ADVERTISE: - strcpy (pnt, "no-advertise"); - pnt += strlen ("no-advertise"); - json_string = json_object_new_string("noAdvertise"); - json_object_array_add(json_community_list, json_string); - break; - case COMMUNITY_LOCAL_AS: - strcpy (pnt, "local-AS"); - pnt += strlen ("local-AS"); - json_string = json_object_new_string("localAs"); - json_object_array_add(json_community_list, json_string); - break; - default: - as = (comval >> 16) & 0xFFFF; - val = comval & 0xFFFF; - sprintf (pnt, "%u:%d", as, val); - json_string = json_object_new_string(pnt); - json_object_array_add(json_community_list, json_string); - pnt += strlen (pnt); - break; + + /* Memory allocation is time consuming work. So we calculate + required string length first. */ + len = 0; + + for (i = 0; i < com->size; i++) { + memcpy(&comval, com_nthval(com, i), sizeof(u_int32_t)); + comval = ntohl(comval); + + switch (comval) { + case COMMUNITY_INTERNET: + len += strlen(" internet"); + break; + case COMMUNITY_NO_EXPORT: + len += strlen(" no-export"); + break; + case COMMUNITY_NO_ADVERTISE: + len += strlen(" no-advertise"); + break; + case COMMUNITY_LOCAL_AS: + len += strlen(" local-AS"); + break; + default: + len += strlen(" 65536:65535"); + break; + } + } + + /* Allocate memory. */ + str = pnt = XMALLOC(MTYPE_COMMUNITY_STR, len); + first = 1; + + /* Fill in string. */ + for (i = 0; i < com->size; i++) { + memcpy(&comval, com_nthval(com, i), sizeof(u_int32_t)); + comval = ntohl(comval); + + if (first) + first = 0; + else + *pnt++ = ' '; + + switch (comval) { + case COMMUNITY_INTERNET: + strcpy(pnt, "internet"); + pnt += strlen("internet"); + json_string = json_object_new_string("internet"); + json_object_array_add(json_community_list, json_string); + break; + case COMMUNITY_NO_EXPORT: + strcpy(pnt, "no-export"); + pnt += strlen("no-export"); + json_string = json_object_new_string("noExport"); + json_object_array_add(json_community_list, json_string); + break; + case COMMUNITY_NO_ADVERTISE: + strcpy(pnt, "no-advertise"); + pnt += strlen("no-advertise"); + json_string = json_object_new_string("noAdvertise"); + json_object_array_add(json_community_list, json_string); + break; + case COMMUNITY_LOCAL_AS: + strcpy(pnt, "local-AS"); + pnt += strlen("local-AS"); + json_string = json_object_new_string("localAs"); + json_object_array_add(json_community_list, json_string); + break; + default: + as = (comval >> 16) & 0xFFFF; + val = comval & 0xFFFF; + sprintf(pnt, "%u:%d", as, val); + json_string = json_object_new_string(pnt); + json_object_array_add(json_community_list, json_string); + pnt += strlen(pnt); + break; + } } - } - *pnt = '\0'; + *pnt = '\0'; - json_object_string_add(com->json, "string", str); - json_object_object_add(com->json, "list", json_community_list); - com->str = str; + json_object_string_add(com->json, "string", str); + json_object_object_add(com->json, "list", json_community_list); + com->str = str; } /* Intern communities attribute. */ -struct community * -community_intern (struct community *com) +struct community *community_intern(struct community *com) { - struct community *find; + struct community *find; - /* Assert this community structure is not interned. */ - assert (com->refcnt == 0); + /* Assert this community structure is not interned. */ + assert(com->refcnt == 0); - /* Lookup community hash. */ - find = (struct community *) hash_get (comhash, com, hash_alloc_intern); + /* Lookup community hash. */ + find = (struct community *)hash_get(comhash, com, hash_alloc_intern); - /* Arguemnt com is allocated temporary. So when it is not used in - hash, it should be freed. */ - if (find != com) - community_free (com); + /* Arguemnt com is allocated temporary. So when it is not used in + hash, it should be freed. */ + if (find != com) + community_free(com); - /* Increment refrence counter. */ - find->refcnt++; + /* Increment refrence counter. */ + find->refcnt++; - /* Make string. */ - if (! find->str) - set_community_string (find); + /* Make string. */ + if (!find->str) + set_community_string(find); - return find; + return find; } /* Free community attribute. */ -void -community_unintern (struct community **com) +void community_unintern(struct community **com) { - struct community *ret; + struct community *ret; - if ((*com)->refcnt) - (*com)->refcnt--; + if ((*com)->refcnt) + (*com)->refcnt--; - /* Pull off from hash. */ - if ((*com)->refcnt == 0) - { - /* Community value com must exist in hash. */ - ret = (struct community *) hash_release (comhash, *com); - assert (ret != NULL); + /* Pull off from hash. */ + if ((*com)->refcnt == 0) { + /* Community value com must exist in hash. */ + ret = (struct community *)hash_release(comhash, *com); + assert(ret != NULL); - community_free (*com); - *com = NULL; - } + community_free(*com); + *com = NULL; + } } /* Create new community attribute. */ -struct community * -community_parse (u_int32_t *pnt, u_short length) +struct community *community_parse(u_int32_t *pnt, u_short length) { - struct community tmp; - struct community *new; + struct community tmp; + struct community *new; - /* If length is malformed return NULL. */ - if (length % 4) - return NULL; + /* If length is malformed return NULL. */ + if (length % 4) + return NULL; - /* Make temporary community for hash look up. */ - tmp.size = length / 4; - tmp.val = pnt; + /* Make temporary community for hash look up. */ + tmp.size = length / 4; + tmp.val = pnt; - new = community_uniq_sort (&tmp); + new = community_uniq_sort(&tmp); - return community_intern (new); + return community_intern(new); } -struct community * -community_dup (struct community *com) +struct community *community_dup(struct community *com) { - struct community *new; - - new = XCALLOC (MTYPE_COMMUNITY, sizeof (struct community)); - new->size = com->size; - if (new->size) - { - new->val = XMALLOC (MTYPE_COMMUNITY_VAL, com->size * 4); - memcpy (new->val, com->val, com->size * 4); - } - else - new->val = NULL; - return new; + struct community *new; + + new = XCALLOC(MTYPE_COMMUNITY, sizeof(struct community)); + new->size = com->size; + if (new->size) { + new->val = XMALLOC(MTYPE_COMMUNITY_VAL, com->size * 4); + memcpy(new->val, com->val, com->size * 4); + } else + new->val = NULL; + return new; } /* Retrun string representation of communities attribute. */ -char * -community_str (struct community *com) +char *community_str(struct community *com) { - if (!com) - return NULL; + if (!com) + return NULL; - if (! com->str) - set_community_string (com); - return com->str; + if (!com->str) + set_community_string(com); + return com->str; } /* Make hash value of community attribute. This function is used by hash package.*/ -unsigned int -community_hash_make (struct community *com) +unsigned int community_hash_make(struct community *com) { - unsigned char *pnt = (unsigned char *)com->val; - int size = com->size * 4; - unsigned int key = 0; - int c; - - for (c = 0; c < size; c += 4) - { - key += pnt[c]; - key += pnt[c + 1]; - key += pnt[c + 2]; - key += pnt[c + 3]; - } - - return key; + unsigned char *pnt = (unsigned char *)com->val; + int size = com->size * 4; + unsigned int key = 0; + int c; + + for (c = 0; c < size; c += 4) { + key += pnt[c]; + key += pnt[c + 1]; + key += pnt[c + 2]; + key += pnt[c + 3]; + } + + return key; } -int -community_match (const struct community *com1, const struct community *com2) +int community_match(const struct community *com1, const struct community *com2) { - int i = 0; - int j = 0; - - if (com1 == NULL && com2 == NULL) - return 1; - - if (com1 == NULL || com2 == NULL) - return 0; - - if (com1->size < com2->size) - return 0; - - /* Every community on com2 needs to be on com1 for this to match */ - while (i < com1->size && j < com2->size) - { - if (memcmp (com1->val + i, com2->val + j, sizeof (u_int32_t)) == 0) - j++; - i++; - } - - if (j == com2->size) - return 1; - else - return 0; + int i = 0; + int j = 0; + + if (com1 == NULL && com2 == NULL) + return 1; + + if (com1 == NULL || com2 == NULL) + return 0; + + if (com1->size < com2->size) + return 0; + + /* Every community on com2 needs to be on com1 for this to match */ + while (i < com1->size && j < com2->size) { + if (memcmp(com1->val + i, com2->val + j, sizeof(u_int32_t)) + == 0) + j++; + i++; + } + + if (j == com2->size) + return 1; + else + return 0; } /* If two aspath have same value then return 1 else return 0. This function is used by hash package. */ -int -community_cmp (const struct community *com1, const struct community *com2) +int community_cmp(const struct community *com1, const struct community *com2) { - if (com1 == NULL && com2 == NULL) - return 1; - if (com1 == NULL || com2 == NULL) - return 0; - - if (com1->size == com2->size) - if (memcmp (com1->val, com2->val, com1->size * 4) == 0) - return 1; - return 0; + if (com1 == NULL && com2 == NULL) + return 1; + if (com1 == NULL || com2 == NULL) + return 0; + + if (com1->size == com2->size) + if (memcmp(com1->val, com2->val, com1->size * 4) == 0) + return 1; + return 0; } /* Add com2 to the end of com1. */ -struct community * -community_merge (struct community *com1, struct community *com2) +struct community *community_merge(struct community *com1, + struct community *com2) { - if (com1->val) - com1->val = XREALLOC (MTYPE_COMMUNITY_VAL, com1->val, - (com1->size + com2->size) * 4); - else - com1->val = XMALLOC (MTYPE_COMMUNITY_VAL, (com1->size + com2->size) * 4); + if (com1->val) + com1->val = XREALLOC(MTYPE_COMMUNITY_VAL, com1->val, + (com1->size + com2->size) * 4); + else + com1->val = XMALLOC(MTYPE_COMMUNITY_VAL, + (com1->size + com2->size) * 4); - memcpy (com1->val + com1->size, com2->val, com2->size * 4); - com1->size += com2->size; + memcpy(com1->val + com1->size, com2->val, com2->size * 4); + com1->size += com2->size; - return com1; + return com1; } /* Community token enum. */ -enum community_token -{ - community_token_val, - community_token_no_export, - community_token_no_advertise, - community_token_local_as, - community_token_unknown +enum community_token { + community_token_val, + community_token_no_export, + community_token_no_advertise, + community_token_local_as, + community_token_unknown }; /* Get next community token from string. */ static const char * -community_gettoken (const char *buf, enum community_token *token, - u_int32_t *val) +community_gettoken(const char *buf, enum community_token *token, u_int32_t *val) { - const char *p = buf; - - /* Skip white space. */ - while (isspace ((int) *p)) - p++; - - /* Check the end of the line. */ - if (*p == '\0') - return NULL; - - /* Well known community string check. */ - if (isalpha ((int) *p)) - { - if (strncmp (p, "internet", strlen ("internet")) == 0) - { - *val = COMMUNITY_INTERNET; - *token = community_token_no_export; - p += strlen ("internet"); - return p; - } - if (strncmp (p, "no-export", strlen ("no-export")) == 0) - { - *val = COMMUNITY_NO_EXPORT; - *token = community_token_no_export; - p += strlen ("no-export"); - return p; - } - if (strncmp (p, "no-advertise", strlen ("no-advertise")) == 0) - { - *val = COMMUNITY_NO_ADVERTISE; - *token = community_token_no_advertise; - p += strlen ("no-advertise"); - return p; - } - if (strncmp (p, "local-AS", strlen ("local-AS")) == 0) - { - *val = COMMUNITY_LOCAL_AS; - *token = community_token_local_as; - p += strlen ("local-AS"); - return p; + const char *p = buf; + + /* Skip white space. */ + while (isspace((int)*p)) + p++; + + /* Check the end of the line. */ + if (*p == '\0') + return NULL; + + /* Well known community string check. */ + if (isalpha((int)*p)) { + if (strncmp(p, "internet", strlen("internet")) == 0) { + *val = COMMUNITY_INTERNET; + *token = community_token_no_export; + p += strlen("internet"); + return p; + } + if (strncmp(p, "no-export", strlen("no-export")) == 0) { + *val = COMMUNITY_NO_EXPORT; + *token = community_token_no_export; + p += strlen("no-export"); + return p; + } + if (strncmp(p, "no-advertise", strlen("no-advertise")) == 0) { + *val = COMMUNITY_NO_ADVERTISE; + *token = community_token_no_advertise; + p += strlen("no-advertise"); + return p; + } + if (strncmp(p, "local-AS", strlen("local-AS")) == 0) { + *val = COMMUNITY_LOCAL_AS; + *token = community_token_local_as; + p += strlen("local-AS"); + return p; + } + + /* Unknown string. */ + *token = community_token_unknown; + return NULL; } - /* Unknown string. */ - *token = community_token_unknown; - return NULL; - } - - /* Community value. */ - if (isdigit ((int) *p)) - { - int separator = 0; - int digit = 0; - u_int32_t community_low = 0; - u_int32_t community_high = 0; - - while (isdigit ((int) *p) || *p == ':') - { - if (*p == ':') - { - if (separator) - { - *token = community_token_unknown; - return NULL; + /* Community value. */ + if (isdigit((int)*p)) { + int separator = 0; + int digit = 0; + u_int32_t community_low = 0; + u_int32_t community_high = 0; + + while (isdigit((int)*p) || *p == ':') { + if (*p == ':') { + if (separator) { + *token = community_token_unknown; + return NULL; + } else { + separator = 1; + digit = 0; + + if (community_low > UINT16_MAX) { + *token = + community_token_unknown; + return NULL; + } + + community_high = community_low << 16; + community_low = 0; + } + } else { + digit = 1; + community_low *= 10; + community_low += (*p - '0'); + } + p++; } - else - { - separator = 1; - digit = 0; - - if (community_low > UINT16_MAX) - { - *token = community_token_unknown; - return NULL; - } - - community_high = community_low << 16; - community_low = 0; + if (!digit) { + *token = community_token_unknown; + return NULL; + } + + if (community_low > UINT16_MAX) { + *token = community_token_unknown; + return NULL; } - } - else - { - digit = 1; - community_low *= 10; - community_low += (*p - '0'); - } - p++; - } - if (! digit) - { - *token = community_token_unknown; - return NULL; - } - if (community_low > UINT16_MAX) - { - *token = community_token_unknown; - return NULL; - } - - *val = community_high + community_low; - *token = community_token_val; - return p; - } - *token = community_token_unknown; - return NULL; + *val = community_high + community_low; + *token = community_token_val; + return p; + } + *token = community_token_unknown; + return NULL; } /* convert string to community structure */ -struct community * -community_str2com (const char *str) +struct community *community_str2com(const char *str) { - struct community *com = NULL; - struct community *com_sort = NULL; - u_int32_t val = 0; - enum community_token token = community_token_unknown; - - do - { - str = community_gettoken (str, &token, &val); - - switch (token) - { - case community_token_val: - case community_token_no_export: - case community_token_no_advertise: - case community_token_local_as: - if (com == NULL) - { - com = community_new(); - com->json = NULL; - } - community_add_val (com, val); - break; - case community_token_unknown: - default: - if (com) - community_free (com); - return NULL; - } - } while (str); - - if (! com) - return NULL; + struct community *com = NULL; + struct community *com_sort = NULL; + u_int32_t val = 0; + enum community_token token = community_token_unknown; + + do { + str = community_gettoken(str, &token, &val); + + switch (token) { + case community_token_val: + case community_token_no_export: + case community_token_no_advertise: + case community_token_local_as: + if (com == NULL) { + com = community_new(); + com->json = NULL; + } + community_add_val(com, val); + break; + case community_token_unknown: + default: + if (com) + community_free(com); + return NULL; + } + } while (str); + + if (!com) + return NULL; - com_sort = community_uniq_sort (com); - community_free (com); + com_sort = community_uniq_sort(com); + community_free(com); - return com_sort; + return com_sort; } /* Return communities hash entry count. */ -unsigned long -community_count (void) +unsigned long community_count(void) { - return comhash->count; + return comhash->count; } /* Return communities hash. */ -struct hash * -community_hash (void) +struct hash *community_hash(void) { - return comhash; + return comhash; } /* Initialize comminity related hash. */ -void -community_init (void) +void community_init(void) { - comhash = hash_create ((unsigned int (*) (void *))community_hash_make, - (int (*) (const void *, const void *))community_cmp, NULL); + comhash = hash_create( + (unsigned int (*)(void *))community_hash_make, + (int (*)(const void *, const void *))community_cmp, NULL); } -void -community_finish (void) +void community_finish(void) { - hash_free (comhash); - comhash = NULL; + hash_free(comhash); + comhash = NULL; } diff --git a/bgpd/bgp_community.h b/bgpd/bgp_community.h index cda079c13..c59eebf2e 100644 --- a/bgpd/bgp_community.h +++ b/bgpd/bgp_community.h @@ -24,23 +24,22 @@ #include "lib/json.h" /* Communities attribute. */ -struct community -{ - /* Reference count of communities value. */ - unsigned long refcnt; +struct community { + /* Reference count of communities value. */ + unsigned long refcnt; - /* Communities value size. */ - int size; + /* Communities value size. */ + int size; - /* Communities value. */ - u_int32_t *val; + /* Communities value. */ + u_int32_t *val; - /* Communities as a json object */ - json_object *json; + /* Communities as a json object */ + json_object *json; - /* String of community attribute. This sring is used by vty output - and expanded community-list for regular expression match. */ - char *str; + /* String of community attribute. This sring is used by vty output + and expanded community-list for regular expression match. */ + char *str; }; /* Well-known communities value. */ @@ -56,25 +55,27 @@ struct community #define com_nthval(X,n) ((X)->val + (n)) /* Prototypes of communities attribute functions. */ -extern void community_init (void); -extern void community_finish (void); -extern void community_free (struct community *); -extern struct community *community_uniq_sort (struct community *); -extern struct community *community_parse (u_int32_t *, u_short); -extern struct community *community_intern (struct community *); -extern void community_unintern (struct community **); -extern char *community_str (struct community *); -extern unsigned int community_hash_make (struct community *); -extern struct community *community_str2com (const char *); -extern int community_match (const struct community *, const struct community *); -extern int community_cmp (const struct community *, const struct community *); -extern struct community *community_merge (struct community *, struct community *); -extern struct community *community_delete (struct community *, struct community *); -extern struct community *community_dup (struct community *); -extern int community_include (struct community *, u_int32_t); -extern void community_del_val (struct community *, u_int32_t *); -extern unsigned long community_count (void); -extern struct hash *community_hash (void); -extern u_int32_t community_val_get (struct community *com, int i); +extern void community_init(void); +extern void community_finish(void); +extern void community_free(struct community *); +extern struct community *community_uniq_sort(struct community *); +extern struct community *community_parse(u_int32_t *, u_short); +extern struct community *community_intern(struct community *); +extern void community_unintern(struct community **); +extern char *community_str(struct community *); +extern unsigned int community_hash_make(struct community *); +extern struct community *community_str2com(const char *); +extern int community_match(const struct community *, const struct community *); +extern int community_cmp(const struct community *, const struct community *); +extern struct community *community_merge(struct community *, + struct community *); +extern struct community *community_delete(struct community *, + struct community *); +extern struct community *community_dup(struct community *); +extern int community_include(struct community *, u_int32_t); +extern void community_del_val(struct community *, u_int32_t *); +extern unsigned long community_count(void); +extern struct hash *community_hash(void); +extern u_int32_t community_val_get(struct community *com, int i); #endif /* _QUAGGA_BGP_COMMUNITY_H */ diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c index d276de6eb..bd3ae27c0 100644 --- a/bgpd/bgp_damp.c +++ b/bgpd/bgp_damp.c @@ -33,7 +33,7 @@ #include "bgpd/bgp_damp.h" #include "bgpd/bgp_table.h" #include "bgpd/bgp_route.h" -#include "bgpd/bgp_attr.h" +#include "bgpd/bgp_attr.h" #include "bgpd/bgp_advertise.h" /* Global variable to access damping configuration */ @@ -46,672 +46,651 @@ static struct bgp_damp_config *damp = &bgp_damp_cfg; #define BGP_DAMP_LIST_DEL(N,A) BGP_INFO_DEL(N,A,no_reuse_list) /* Calculate reuse list index by penalty value. */ -static int -bgp_reuse_index (int penalty) +static int bgp_reuse_index(int penalty) { - unsigned int i; - int index; + unsigned int i; + int index; - i = (int)(((double) penalty / damp->reuse_limit - 1.0) * damp->scale_factor); - - if ( i >= damp->reuse_index_size ) - i = damp->reuse_index_size - 1; + i = (int)(((double)penalty / damp->reuse_limit - 1.0) + * damp->scale_factor); - index = damp->reuse_index[i] - damp->reuse_index[0]; + if (i >= damp->reuse_index_size) + i = damp->reuse_index_size - 1; - return (damp->reuse_offset + index) % damp->reuse_list_size; + index = damp->reuse_index[i] - damp->reuse_index[0]; + + return (damp->reuse_offset + index) % damp->reuse_list_size; } /* Add BGP dampening information to reuse list. */ -static void -bgp_reuse_list_add (struct bgp_damp_info *bdi) +static void bgp_reuse_list_add(struct bgp_damp_info *bdi) { - int index; + int index; - index = bdi->index = bgp_reuse_index (bdi->penalty); + index = bdi->index = bgp_reuse_index(bdi->penalty); - bdi->prev = NULL; - bdi->next = damp->reuse_list[index]; - if (damp->reuse_list[index]) - damp->reuse_list[index]->prev = bdi; - damp->reuse_list[index] = bdi; + bdi->prev = NULL; + bdi->next = damp->reuse_list[index]; + if (damp->reuse_list[index]) + damp->reuse_list[index]->prev = bdi; + damp->reuse_list[index] = bdi; } /* Delete BGP dampening information from reuse list. */ -static void -bgp_reuse_list_delete (struct bgp_damp_info *bdi) +static void bgp_reuse_list_delete(struct bgp_damp_info *bdi) { - if (bdi->next) - bdi->next->prev = bdi->prev; - if (bdi->prev) - bdi->prev->next = bdi->next; - else - damp->reuse_list[bdi->index] = bdi->next; -} + if (bdi->next) + bdi->next->prev = bdi->prev; + if (bdi->prev) + bdi->prev->next = bdi->next; + else + damp->reuse_list[bdi->index] = bdi->next; +} /* Return decayed penalty value. */ -int -bgp_damp_decay (time_t tdiff, int penalty) +int bgp_damp_decay(time_t tdiff, int penalty) { - unsigned int i; + unsigned int i; + + i = (int)((double)tdiff / DELTA_T); - i = (int) ((double) tdiff / DELTA_T); + if (i == 0) + return penalty; - if (i == 0) - return penalty; - - if (i >= damp->decay_array_size) - return 0; + if (i >= damp->decay_array_size) + return 0; - return (int) (penalty * damp->decay_array[i]); + return (int)(penalty * damp->decay_array[i]); } /* Handler of reuse timer event. Each route in the current reuse-list is evaluated. RFC2439 Section 4.8.7. */ -static int -bgp_reuse_timer (struct thread *t) +static int bgp_reuse_timer(struct thread *t) { - struct bgp_damp_info *bdi; - struct bgp_damp_info *next; - time_t t_now, t_diff; - - damp->t_reuse = NULL; - thread_add_timer(bm->master, bgp_reuse_timer, NULL, DELTA_REUSE, - &damp->t_reuse); - - t_now = bgp_clock (); - - /* 1. save a pointer to the current zeroth queue head and zero the - list head entry. */ - bdi = damp->reuse_list[damp->reuse_offset]; - damp->reuse_list[damp->reuse_offset] = NULL; - - /* 2. set offset = modulo reuse-list-size ( offset + 1 ), thereby - rotating the circular queue of list-heads. */ - damp->reuse_offset = (damp->reuse_offset + 1) % damp->reuse_list_size; - - /* 3. if ( the saved list head pointer is non-empty ) */ - for (; bdi; bdi = next) - { - struct bgp *bgp = bdi->binfo->peer->bgp; - - next = bdi->next; - - /* Set t-diff = t-now - t-updated. */ - t_diff = t_now - bdi->t_updated; - - /* Set figure-of-merit = figure-of-merit * decay-array-ok [t-diff] */ - bdi->penalty = bgp_damp_decay (t_diff, bdi->penalty); - - /* Set t-updated = t-now. */ - bdi->t_updated = t_now; - - /* if (figure-of-merit < reuse). */ - if (bdi->penalty < damp->reuse_limit) - { - /* Reuse the route. */ - bgp_info_unset_flag (bdi->rn, bdi->binfo, BGP_INFO_DAMPED); - bdi->suppress_time = 0; - - if (bdi->lastrecord == BGP_RECORD_UPDATE) - { - bgp_info_unset_flag (bdi->rn, bdi->binfo, BGP_INFO_HISTORY); - bgp_aggregate_increment (bgp, &bdi->rn->p, bdi->binfo, - bdi->afi, bdi->safi); - bgp_process (bgp, bdi->rn, bdi->afi, bdi->safi); - } - - if (bdi->penalty <= damp->reuse_limit / 2.0) - bgp_damp_info_free (bdi, 1); - else - BGP_DAMP_LIST_ADD (damp, bdi); + struct bgp_damp_info *bdi; + struct bgp_damp_info *next; + time_t t_now, t_diff; + + damp->t_reuse = NULL; + thread_add_timer(bm->master, bgp_reuse_timer, NULL, DELTA_REUSE, + &damp->t_reuse); + + t_now = bgp_clock(); + + /* 1. save a pointer to the current zeroth queue head and zero the + list head entry. */ + bdi = damp->reuse_list[damp->reuse_offset]; + damp->reuse_list[damp->reuse_offset] = NULL; + + /* 2. set offset = modulo reuse-list-size ( offset + 1 ), thereby + rotating the circular queue of list-heads. */ + damp->reuse_offset = (damp->reuse_offset + 1) % damp->reuse_list_size; + + /* 3. if ( the saved list head pointer is non-empty ) */ + for (; bdi; bdi = next) { + struct bgp *bgp = bdi->binfo->peer->bgp; + + next = bdi->next; + + /* Set t-diff = t-now - t-updated. */ + t_diff = t_now - bdi->t_updated; + + /* Set figure-of-merit = figure-of-merit * decay-array-ok + * [t-diff] */ + bdi->penalty = bgp_damp_decay(t_diff, bdi->penalty); + + /* Set t-updated = t-now. */ + bdi->t_updated = t_now; + + /* if (figure-of-merit < reuse). */ + if (bdi->penalty < damp->reuse_limit) { + /* Reuse the route. */ + bgp_info_unset_flag(bdi->rn, bdi->binfo, + BGP_INFO_DAMPED); + bdi->suppress_time = 0; + + if (bdi->lastrecord == BGP_RECORD_UPDATE) { + bgp_info_unset_flag(bdi->rn, bdi->binfo, + BGP_INFO_HISTORY); + bgp_aggregate_increment(bgp, &bdi->rn->p, + bdi->binfo, bdi->afi, + bdi->safi); + bgp_process(bgp, bdi->rn, bdi->afi, bdi->safi); + } + + if (bdi->penalty <= damp->reuse_limit / 2.0) + bgp_damp_info_free(bdi, 1); + else + BGP_DAMP_LIST_ADD(damp, bdi); + } else + /* Re-insert into another list (See RFC2439 Section + * 4.8.6). */ + bgp_reuse_list_add(bdi); } - else - /* Re-insert into another list (See RFC2439 Section 4.8.6). */ - bgp_reuse_list_add (bdi); - } - return 0; + return 0; } /* A route becomes unreachable (RFC2439 Section 4.8.2). */ -int -bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn, - afi_t afi, safi_t safi, int attr_change) +int bgp_damp_withdraw(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi, + safi_t safi, int attr_change) { - time_t t_now; - struct bgp_damp_info *bdi = NULL; - double last_penalty = 0; - - t_now = bgp_clock (); - - /* Processing Unreachable Messages. */ - if (binfo->extra) - bdi = binfo->extra->damp_info; - - if (bdi == NULL) - { - /* If there is no previous stability history. */ - - /* RFC2439 said: - 1. allocate a damping structure. - 2. set figure-of-merit = 1. - 3. withdraw the route. */ - - bdi = XCALLOC (MTYPE_BGP_DAMP_INFO, sizeof (struct bgp_damp_info)); - bdi->binfo = binfo; - bdi->rn = rn; - bdi->penalty = (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY); - bdi->flap = 1; - bdi->start_time = t_now; - bdi->suppress_time = 0; - bdi->index = -1; - bdi->afi = afi; - bdi->safi = safi; - (bgp_info_extra_get (binfo))->damp_info = bdi; - BGP_DAMP_LIST_ADD (damp, bdi); - } - else - { - last_penalty = bdi->penalty; - - /* 1. Set t-diff = t-now - t-updated. */ - bdi->penalty = - (bgp_damp_decay (t_now - bdi->t_updated, bdi->penalty) - + (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY)); - - if (bdi->penalty > damp->ceiling) - bdi->penalty = damp->ceiling; - - bdi->flap++; - } - - assert ((rn == bdi->rn) && (binfo == bdi->binfo)); - - bdi->lastrecord = BGP_RECORD_WITHDRAW; - bdi->t_updated = t_now; - - /* Make this route as historical status. */ - bgp_info_set_flag (rn, binfo, BGP_INFO_HISTORY); - - /* Remove the route from a reuse list if it is on one. */ - if (CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED)) - { - /* If decay rate isn't equal to 0, reinsert brn. */ - if (bdi->penalty != last_penalty) - { - bgp_reuse_list_delete (bdi); - bgp_reuse_list_add (bdi); + time_t t_now; + struct bgp_damp_info *bdi = NULL; + double last_penalty = 0; + + t_now = bgp_clock(); + + /* Processing Unreachable Messages. */ + if (binfo->extra) + bdi = binfo->extra->damp_info; + + if (bdi == NULL) { + /* If there is no previous stability history. */ + + /* RFC2439 said: + 1. allocate a damping structure. + 2. set figure-of-merit = 1. + 3. withdraw the route. */ + + bdi = XCALLOC(MTYPE_BGP_DAMP_INFO, + sizeof(struct bgp_damp_info)); + bdi->binfo = binfo; + bdi->rn = rn; + bdi->penalty = + (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY); + bdi->flap = 1; + bdi->start_time = t_now; + bdi->suppress_time = 0; + bdi->index = -1; + bdi->afi = afi; + bdi->safi = safi; + (bgp_info_extra_get(binfo))->damp_info = bdi; + BGP_DAMP_LIST_ADD(damp, bdi); + } else { + last_penalty = bdi->penalty; + + /* 1. Set t-diff = t-now - t-updated. */ + bdi->penalty = + (bgp_damp_decay(t_now - bdi->t_updated, bdi->penalty) + + (attr_change ? DEFAULT_PENALTY / 2 + : DEFAULT_PENALTY)); + + if (bdi->penalty > damp->ceiling) + bdi->penalty = damp->ceiling; + + bdi->flap++; + } + + assert((rn == bdi->rn) && (binfo == bdi->binfo)); + + bdi->lastrecord = BGP_RECORD_WITHDRAW; + bdi->t_updated = t_now; + + /* Make this route as historical status. */ + bgp_info_set_flag(rn, binfo, BGP_INFO_HISTORY); + + /* Remove the route from a reuse list if it is on one. */ + if (CHECK_FLAG(bdi->binfo->flags, BGP_INFO_DAMPED)) { + /* If decay rate isn't equal to 0, reinsert brn. */ + if (bdi->penalty != last_penalty) { + bgp_reuse_list_delete(bdi); + bgp_reuse_list_add(bdi); + } + return BGP_DAMP_SUPPRESSED; } - return BGP_DAMP_SUPPRESSED; - } - - /* If not suppressed before, do annonunce this withdraw and - insert into reuse_list. */ - if (bdi->penalty >= damp->suppress_value) - { - bgp_info_set_flag (rn, binfo, BGP_INFO_DAMPED); - bdi->suppress_time = t_now; - BGP_DAMP_LIST_DEL (damp, bdi); - bgp_reuse_list_add (bdi); - } - - return BGP_DAMP_USED; + + /* If not suppressed before, do annonunce this withdraw and + insert into reuse_list. */ + if (bdi->penalty >= damp->suppress_value) { + bgp_info_set_flag(rn, binfo, BGP_INFO_DAMPED); + bdi->suppress_time = t_now; + BGP_DAMP_LIST_DEL(damp, bdi); + bgp_reuse_list_add(bdi); + } + + return BGP_DAMP_USED; } -int -bgp_damp_update (struct bgp_info *binfo, struct bgp_node *rn, - afi_t afi, safi_t safi) +int bgp_damp_update(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi, + safi_t safi) { - time_t t_now; - struct bgp_damp_info *bdi; - int status; - - if (!binfo->extra || !((bdi = binfo->extra->damp_info))) - return BGP_DAMP_USED; - - t_now = bgp_clock (); - bgp_info_unset_flag (rn, binfo, BGP_INFO_HISTORY); - - bdi->lastrecord = BGP_RECORD_UPDATE; - bdi->penalty = bgp_damp_decay (t_now - bdi->t_updated, bdi->penalty); - - if (! CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED) - && (bdi->penalty < damp->suppress_value)) - status = BGP_DAMP_USED; - else if (CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED) - && (bdi->penalty < damp->reuse_limit) ) - { - bgp_info_unset_flag (rn, binfo, BGP_INFO_DAMPED); - bgp_reuse_list_delete (bdi); - BGP_DAMP_LIST_ADD (damp, bdi); - bdi->suppress_time = 0; - status = BGP_DAMP_USED; - } - else - status = BGP_DAMP_SUPPRESSED; - - if (bdi->penalty > damp->reuse_limit / 2.0) - bdi->t_updated = t_now; - else - bgp_damp_info_free (bdi, 0); - - return status; + time_t t_now; + struct bgp_damp_info *bdi; + int status; + + if (!binfo->extra || !((bdi = binfo->extra->damp_info))) + return BGP_DAMP_USED; + + t_now = bgp_clock(); + bgp_info_unset_flag(rn, binfo, BGP_INFO_HISTORY); + + bdi->lastrecord = BGP_RECORD_UPDATE; + bdi->penalty = bgp_damp_decay(t_now - bdi->t_updated, bdi->penalty); + + if (!CHECK_FLAG(bdi->binfo->flags, BGP_INFO_DAMPED) + && (bdi->penalty < damp->suppress_value)) + status = BGP_DAMP_USED; + else if (CHECK_FLAG(bdi->binfo->flags, BGP_INFO_DAMPED) + && (bdi->penalty < damp->reuse_limit)) { + bgp_info_unset_flag(rn, binfo, BGP_INFO_DAMPED); + bgp_reuse_list_delete(bdi); + BGP_DAMP_LIST_ADD(damp, bdi); + bdi->suppress_time = 0; + status = BGP_DAMP_USED; + } else + status = BGP_DAMP_SUPPRESSED; + + if (bdi->penalty > damp->reuse_limit / 2.0) + bdi->t_updated = t_now; + else + bgp_damp_info_free(bdi, 0); + + return status; } /* Remove dampening information and history route. */ -int -bgp_damp_scan (struct bgp_info *binfo, afi_t afi, safi_t safi) +int bgp_damp_scan(struct bgp_info *binfo, afi_t afi, safi_t safi) { - time_t t_now, t_diff; - struct bgp_damp_info *bdi; - - assert (binfo->extra && binfo->extra->damp_info); - - t_now = bgp_clock (); - bdi = binfo->extra->damp_info; - - if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)) - { - t_diff = t_now - bdi->suppress_time; - - if (t_diff >= damp->max_suppress_time) - { - bgp_info_unset_flag (bdi->rn, binfo, BGP_INFO_DAMPED); - bgp_reuse_list_delete (bdi); - BGP_DAMP_LIST_ADD (damp, bdi); - bdi->penalty = damp->reuse_limit; - bdi->suppress_time = 0; - bdi->t_updated = t_now; - - /* Need to announce UPDATE once this binfo is usable again. */ - if (bdi->lastrecord == BGP_RECORD_UPDATE) - return 1; - else - return 0; - } - } - else - { - t_diff = t_now - bdi->t_updated; - bdi->penalty = bgp_damp_decay (t_diff, bdi->penalty); - - if (bdi->penalty <= damp->reuse_limit / 2.0) - { - /* release the bdi, bdi->binfo. */ - bgp_damp_info_free (bdi, 1); - return 0; - } - else - bdi->t_updated = t_now; - } - return 0; + time_t t_now, t_diff; + struct bgp_damp_info *bdi; + + assert(binfo->extra && binfo->extra->damp_info); + + t_now = bgp_clock(); + bdi = binfo->extra->damp_info; + + if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)) { + t_diff = t_now - bdi->suppress_time; + + if (t_diff >= damp->max_suppress_time) { + bgp_info_unset_flag(bdi->rn, binfo, BGP_INFO_DAMPED); + bgp_reuse_list_delete(bdi); + BGP_DAMP_LIST_ADD(damp, bdi); + bdi->penalty = damp->reuse_limit; + bdi->suppress_time = 0; + bdi->t_updated = t_now; + + /* Need to announce UPDATE once this binfo is usable + * again. */ + if (bdi->lastrecord == BGP_RECORD_UPDATE) + return 1; + else + return 0; + } + } else { + t_diff = t_now - bdi->t_updated; + bdi->penalty = bgp_damp_decay(t_diff, bdi->penalty); + + if (bdi->penalty <= damp->reuse_limit / 2.0) { + /* release the bdi, bdi->binfo. */ + bgp_damp_info_free(bdi, 1); + return 0; + } else + bdi->t_updated = t_now; + } + return 0; } -void -bgp_damp_info_free (struct bgp_damp_info *bdi, int withdraw) +void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw) { - struct bgp_info *binfo; + struct bgp_info *binfo; + + if (!bdi) + return; - if (! bdi) - return; + binfo = bdi->binfo; + binfo->extra->damp_info = NULL; - binfo = bdi->binfo; - binfo->extra->damp_info = NULL; + if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)) + bgp_reuse_list_delete(bdi); + else + BGP_DAMP_LIST_DEL(damp, bdi); - if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)) - bgp_reuse_list_delete (bdi); - else - BGP_DAMP_LIST_DEL (damp, bdi); + bgp_info_unset_flag(bdi->rn, binfo, BGP_INFO_HISTORY | BGP_INFO_DAMPED); - bgp_info_unset_flag (bdi->rn, binfo, BGP_INFO_HISTORY|BGP_INFO_DAMPED); + if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw) + bgp_info_delete(bdi->rn, binfo); - if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw) - bgp_info_delete (bdi->rn, binfo); - - XFREE (MTYPE_BGP_DAMP_INFO, bdi); + XFREE(MTYPE_BGP_DAMP_INFO, bdi); } -static void -bgp_damp_parameter_set (int hlife, int reuse, int sup, int maxsup) +static void bgp_damp_parameter_set(int hlife, int reuse, int sup, int maxsup) { - double reuse_max_ratio; - unsigned int i; - double j; - - damp->suppress_value = sup; - damp->half_life = hlife; - damp->reuse_limit = reuse; - damp->max_suppress_time = maxsup; - - /* Initialize params per bgp_damp_config. */ - damp->reuse_index_size = REUSE_ARRAY_SIZE; - - damp->ceiling = (int)(damp->reuse_limit * (pow(2, (double)damp->max_suppress_time/damp->half_life))); - - /* Decay-array computations */ - damp->decay_array_size = ceil ((double) damp->max_suppress_time / DELTA_T); - damp->decay_array = XMALLOC (MTYPE_BGP_DAMP_ARRAY, - sizeof(double) * (damp->decay_array_size)); - damp->decay_array[0] = 1.0; - damp->decay_array[1] = exp ((1.0/((double)damp->half_life/DELTA_T)) * log(0.5)); - - /* Calculate decay values for all possible times */ - for (i = 2; i < damp->decay_array_size; i++) - damp->decay_array[i] = damp->decay_array[i-1] * damp->decay_array[1]; - - /* Reuse-list computations */ - i = ceil ((double)damp->max_suppress_time / DELTA_REUSE) + 1; - if (i > REUSE_LIST_SIZE || i == 0) - i = REUSE_LIST_SIZE; - damp->reuse_list_size = i; - - damp->reuse_list = XCALLOC (MTYPE_BGP_DAMP_ARRAY, - damp->reuse_list_size - * sizeof (struct bgp_reuse_node *)); - - /* Reuse-array computations */ - damp->reuse_index = XCALLOC (MTYPE_BGP_DAMP_ARRAY, - sizeof(int) * damp->reuse_index_size); - - reuse_max_ratio = (double)damp->ceiling/damp->reuse_limit; - j = (exp((double)damp->max_suppress_time/damp->half_life) * log10(2.0)); - if ( reuse_max_ratio > j && j != 0 ) - reuse_max_ratio = j; - - damp->scale_factor = (double)damp->reuse_index_size/(reuse_max_ratio - 1); - - for (i = 0; i < damp->reuse_index_size; i++) - { - damp->reuse_index[i] = - (int)(((double)damp->half_life / DELTA_REUSE) - * log10 (1.0 / (damp->reuse_limit * ( 1.0 + ((double)i/damp->scale_factor)))) / log10(0.5)); - } + double reuse_max_ratio; + unsigned int i; + double j; + + damp->suppress_value = sup; + damp->half_life = hlife; + damp->reuse_limit = reuse; + damp->max_suppress_time = maxsup; + + /* Initialize params per bgp_damp_config. */ + damp->reuse_index_size = REUSE_ARRAY_SIZE; + + damp->ceiling = + (int)(damp->reuse_limit * (pow(2, + (double)damp->max_suppress_time + / damp->half_life))); + + /* Decay-array computations */ + damp->decay_array_size = + ceil((double)damp->max_suppress_time / DELTA_T); + damp->decay_array = XMALLOC(MTYPE_BGP_DAMP_ARRAY, + sizeof(double) * (damp->decay_array_size)); + damp->decay_array[0] = 1.0; + damp->decay_array[1] = + exp((1.0 / ((double)damp->half_life / DELTA_T)) * log(0.5)); + + /* Calculate decay values for all possible times */ + for (i = 2; i < damp->decay_array_size; i++) + damp->decay_array[i] = + damp->decay_array[i - 1] * damp->decay_array[1]; + + /* Reuse-list computations */ + i = ceil((double)damp->max_suppress_time / DELTA_REUSE) + 1; + if (i > REUSE_LIST_SIZE || i == 0) + i = REUSE_LIST_SIZE; + damp->reuse_list_size = i; + + damp->reuse_list = XCALLOC(MTYPE_BGP_DAMP_ARRAY, + damp->reuse_list_size + * sizeof(struct bgp_reuse_node *)); + + /* Reuse-array computations */ + damp->reuse_index = XCALLOC(MTYPE_BGP_DAMP_ARRAY, + sizeof(int) * damp->reuse_index_size); + + reuse_max_ratio = (double)damp->ceiling / damp->reuse_limit; + j = (exp((double)damp->max_suppress_time / damp->half_life) + * log10(2.0)); + if (reuse_max_ratio > j && j != 0) + reuse_max_ratio = j; + + damp->scale_factor = + (double)damp->reuse_index_size / (reuse_max_ratio - 1); + + for (i = 0; i < damp->reuse_index_size; i++) { + damp->reuse_index[i] = + (int)(((double)damp->half_life / DELTA_REUSE) + * log10(1.0 / (damp->reuse_limit + * (1.0 + ((double)i + / damp->scale_factor)))) + / log10(0.5)); + } } -int -bgp_damp_enable (struct bgp *bgp, afi_t afi, safi_t safi, time_t half, - unsigned int reuse, unsigned int suppress, time_t max) +int bgp_damp_enable(struct bgp *bgp, afi_t afi, safi_t safi, time_t half, + unsigned int reuse, unsigned int suppress, time_t max) { - if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) - { - if (damp->half_life == half - && damp->reuse_limit == reuse - && damp->suppress_value == suppress - && damp->max_suppress_time == max) - return 0; - bgp_damp_disable (bgp, afi, safi); - } + if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) { + if (damp->half_life == half && damp->reuse_limit == reuse + && damp->suppress_value == suppress + && damp->max_suppress_time == max) + return 0; + bgp_damp_disable(bgp, afi, safi); + } - SET_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING); - bgp_damp_parameter_set (half, reuse, suppress, max); + SET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING); + bgp_damp_parameter_set(half, reuse, suppress, max); - /* Register reuse timer. */ - thread_add_timer(bm->master, bgp_reuse_timer, NULL, DELTA_REUSE, - &damp->t_reuse); + /* Register reuse timer. */ + thread_add_timer(bm->master, bgp_reuse_timer, NULL, DELTA_REUSE, + &damp->t_reuse); - return 0; + return 0; } -static void -bgp_damp_config_clean (struct bgp_damp_config *damp) +static void bgp_damp_config_clean(struct bgp_damp_config *damp) { - /* Free decay array */ - XFREE (MTYPE_BGP_DAMP_ARRAY, damp->decay_array); + /* Free decay array */ + XFREE(MTYPE_BGP_DAMP_ARRAY, damp->decay_array); - /* Free reuse index array */ - XFREE (MTYPE_BGP_DAMP_ARRAY, damp->reuse_index); + /* Free reuse index array */ + XFREE(MTYPE_BGP_DAMP_ARRAY, damp->reuse_index); - /* Free reuse list array. */ - XFREE (MTYPE_BGP_DAMP_ARRAY, damp->reuse_list); + /* Free reuse list array. */ + XFREE(MTYPE_BGP_DAMP_ARRAY, damp->reuse_list); } /* Clean all the bgp_damp_info stored in reuse_list. */ -void -bgp_damp_info_clean (void) +void bgp_damp_info_clean(void) { - unsigned int i; - struct bgp_damp_info *bdi, *next; + unsigned int i; + struct bgp_damp_info *bdi, *next; - damp->reuse_offset = 0; + damp->reuse_offset = 0; - for (i = 0; i < damp->reuse_list_size; i++) - { - if (! damp->reuse_list[i]) - continue; + for (i = 0; i < damp->reuse_list_size; i++) { + if (!damp->reuse_list[i]) + continue; - for (bdi = damp->reuse_list[i]; bdi; bdi = next) - { - next = bdi->next; - bgp_damp_info_free (bdi, 1); + for (bdi = damp->reuse_list[i]; bdi; bdi = next) { + next = bdi->next; + bgp_damp_info_free(bdi, 1); + } + damp->reuse_list[i] = NULL; } - damp->reuse_list[i] = NULL; - } - - for (bdi = damp->no_reuse_list; bdi; bdi = next) - { - next = bdi->next; - bgp_damp_info_free (bdi, 1); - } - damp->no_reuse_list = NULL; + + for (bdi = damp->no_reuse_list; bdi; bdi = next) { + next = bdi->next; + bgp_damp_info_free(bdi, 1); + } + damp->no_reuse_list = NULL; } -int -bgp_damp_disable (struct bgp *bgp, afi_t afi, safi_t safi) +int bgp_damp_disable(struct bgp *bgp, afi_t afi, safi_t safi) { - /* If it wasn't enabled, there's nothing to do. */ - if (! CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) - return 0; + /* If it wasn't enabled, there's nothing to do. */ + if (!CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) + return 0; - /* Cancel reuse thread. */ - if (damp->t_reuse ) - thread_cancel (damp->t_reuse); - damp->t_reuse = NULL; + /* Cancel reuse thread. */ + if (damp->t_reuse) + thread_cancel(damp->t_reuse); + damp->t_reuse = NULL; - /* Clean BGP dampening information. */ - bgp_damp_info_clean (); + /* Clean BGP dampening information. */ + bgp_damp_info_clean(); - /* Clear configuration */ - bgp_damp_config_clean (&bgp_damp_cfg); + /* Clear configuration */ + bgp_damp_config_clean(&bgp_damp_cfg); - UNSET_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING); - return 0; + UNSET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING); + return 0; } -void -bgp_config_write_damp (struct vty *vty) +void bgp_config_write_damp(struct vty *vty) { - if (bgp_damp_cfg.half_life == DEFAULT_HALF_LIFE*60 - && bgp_damp_cfg.reuse_limit == DEFAULT_REUSE - && bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS - && bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life*4) - vty_out (vty, " bgp dampening\n"); - else if (bgp_damp_cfg.half_life != DEFAULT_HALF_LIFE*60 - && bgp_damp_cfg.reuse_limit == DEFAULT_REUSE - && bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS - && bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life*4) - vty_out (vty, " bgp dampening %lld\n", - bgp_damp_cfg.half_life / 60LL); - else - vty_out (vty, " bgp dampening %lld %d %d %lld\n", - bgp_damp_cfg.half_life/60LL, - bgp_damp_cfg.reuse_limit, - bgp_damp_cfg.suppress_value, - bgp_damp_cfg.max_suppress_time / 60LL); + if (bgp_damp_cfg.half_life == DEFAULT_HALF_LIFE * 60 + && bgp_damp_cfg.reuse_limit == DEFAULT_REUSE + && bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS + && bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life * 4) + vty_out(vty, " bgp dampening\n"); + else if (bgp_damp_cfg.half_life != DEFAULT_HALF_LIFE * 60 + && bgp_damp_cfg.reuse_limit == DEFAULT_REUSE + && bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS + && bgp_damp_cfg.max_suppress_time + == bgp_damp_cfg.half_life * 4) + vty_out(vty, " bgp dampening %lld\n", + bgp_damp_cfg.half_life / 60LL); + else + vty_out(vty, " bgp dampening %lld %d %d %lld\n", + bgp_damp_cfg.half_life / 60LL, bgp_damp_cfg.reuse_limit, + bgp_damp_cfg.suppress_value, + bgp_damp_cfg.max_suppress_time / 60LL); } -static const char * -bgp_get_reuse_time (unsigned int penalty, char *buf, size_t len, u_char use_json, json_object *json) +static const char *bgp_get_reuse_time(unsigned int penalty, char *buf, + size_t len, u_char use_json, + json_object *json) { - time_t reuse_time = 0; - struct tm *tm = NULL; - int time_store = 0; + time_t reuse_time = 0; + struct tm *tm = NULL; + int time_store = 0; - if (penalty > damp->reuse_limit) - { - reuse_time = (int) (DELTA_T * ((log((double)damp->reuse_limit/penalty))/(log(damp->decay_array[1])))); + if (penalty > damp->reuse_limit) { + reuse_time = (int)(DELTA_T + * ((log((double)damp->reuse_limit / penalty)) + / (log(damp->decay_array[1])))); - if (reuse_time > damp->max_suppress_time) - reuse_time = damp->max_suppress_time; + if (reuse_time > damp->max_suppress_time) + reuse_time = damp->max_suppress_time; - tm = gmtime (&reuse_time); - } - else - reuse_time = 0; + tm = gmtime(&reuse_time); + } else + reuse_time = 0; - /* Making formatted timer strings. */ +/* Making formatted timer strings. */ #define ONE_DAY_SECOND 60*60*24 #define ONE_WEEK_SECOND 60*60*24*7 - if (reuse_time == 0) - { - if (use_json) - json_object_int_add(json, "reuseTimerMsecs", 0); - else - snprintf (buf, len, "00:00:00"); - } - else if (reuse_time < ONE_DAY_SECOND) - { - if (use_json) - { - time_store = (3600000 * tm->tm_hour) + (60000 * tm->tm_min) + (1000 * tm->tm_sec); - json_object_int_add(json, "reuseTimerMsecs", time_store); - } - else - snprintf (buf, len, "%02d:%02d:%02d", - tm->tm_hour, tm->tm_min, tm->tm_sec); - } - else if (reuse_time < ONE_WEEK_SECOND) - { - if (use_json) - { - time_store = (86400000 * tm->tm_yday) + (3600000 * tm->tm_hour) + (60000 * tm->tm_min) + (1000 * tm->tm_sec); - json_object_int_add(json, "reuseTimerMsecs", time_store); - } - else - snprintf (buf, len, "%dd%02dh%02dm", - tm->tm_yday, tm->tm_hour, tm->tm_min); - } - else - { - if (use_json) - { - time_store = (604800000 * tm->tm_yday/7) + (86400000 * (tm->tm_yday - ((tm->tm_yday/7) * 7))) + (3600000 * tm->tm_hour) + (60000 * tm->tm_min) + (1000 * tm->tm_sec); - json_object_int_add(json, "reuseTimerMsecs", time_store); - } - else - snprintf (buf, len, "%02dw%dd%02dh", - tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); - } - - return buf; + if (reuse_time == 0) { + if (use_json) + json_object_int_add(json, "reuseTimerMsecs", 0); + else + snprintf(buf, len, "00:00:00"); + } else if (reuse_time < ONE_DAY_SECOND) { + if (use_json) { + time_store = (3600000 * tm->tm_hour) + + (60000 * tm->tm_min) + + (1000 * tm->tm_sec); + json_object_int_add(json, "reuseTimerMsecs", + time_store); + } else + snprintf(buf, len, "%02d:%02d:%02d", tm->tm_hour, + tm->tm_min, tm->tm_sec); + } else if (reuse_time < ONE_WEEK_SECOND) { + if (use_json) { + time_store = (86400000 * tm->tm_yday) + + (3600000 * tm->tm_hour) + + (60000 * tm->tm_min) + + (1000 * tm->tm_sec); + json_object_int_add(json, "reuseTimerMsecs", + time_store); + } else + snprintf(buf, len, "%dd%02dh%02dm", tm->tm_yday, + tm->tm_hour, tm->tm_min); + } else { + if (use_json) { + time_store = + (604800000 * tm->tm_yday / 7) + + (86400000 + * (tm->tm_yday - ((tm->tm_yday / 7) * 7))) + + (3600000 * tm->tm_hour) + (60000 * tm->tm_min) + + (1000 * tm->tm_sec); + json_object_int_add(json, "reuseTimerMsecs", + time_store); + } else + snprintf(buf, len, "%02dw%dd%02dh", tm->tm_yday / 7, + tm->tm_yday - ((tm->tm_yday / 7) * 7), + tm->tm_hour); + } + + return buf; } - -void -bgp_damp_info_vty (struct vty *vty, struct bgp_info *binfo, - json_object *json_path) + +void bgp_damp_info_vty(struct vty *vty, struct bgp_info *binfo, + json_object *json_path) { - struct bgp_damp_info *bdi; - time_t t_now, t_diff; - char timebuf[BGP_UPTIME_LEN]; - int penalty; - - if (!binfo->extra) - return; - - /* BGP dampening information. */ - bdi = binfo->extra->damp_info; - - /* If dampening is not enabled or there is no dampening information, - return immediately. */ - if (! damp || ! bdi) - return; - - /* Calculate new penalty. */ - t_now = bgp_clock (); - t_diff = t_now - bdi->t_updated; - penalty = bgp_damp_decay (t_diff, bdi->penalty); - - if (json_path) - { - json_object_int_add(json_path, "dampeningPenalty", penalty); - json_object_int_add(json_path, "dampeningFlapCount", bdi->flap); - peer_uptime (bdi->start_time, timebuf, BGP_UPTIME_LEN, 1, json_path); - - if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED) - && ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) - bgp_get_reuse_time (penalty, timebuf, BGP_UPTIME_LEN, 1, json_path); - } - else - { - vty_out (vty, " Dampinfo: penalty %d, flapped %d times in %s", - penalty, bdi->flap, - peer_uptime (bdi->start_time, timebuf, BGP_UPTIME_LEN, 0, json_path)); - - if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED) - && ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) - vty_out (vty, ", reuse in %s", - bgp_get_reuse_time (penalty, timebuf, BGP_UPTIME_LEN, 0, json_path)); - - vty_out (vty, "\n"); - } + struct bgp_damp_info *bdi; + time_t t_now, t_diff; + char timebuf[BGP_UPTIME_LEN]; + int penalty; + + if (!binfo->extra) + return; + + /* BGP dampening information. */ + bdi = binfo->extra->damp_info; + + /* If dampening is not enabled or there is no dampening information, + return immediately. */ + if (!damp || !bdi) + return; + + /* Calculate new penalty. */ + t_now = bgp_clock(); + t_diff = t_now - bdi->t_updated; + penalty = bgp_damp_decay(t_diff, bdi->penalty); + + if (json_path) { + json_object_int_add(json_path, "dampeningPenalty", penalty); + json_object_int_add(json_path, "dampeningFlapCount", bdi->flap); + peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, 1, + json_path); + + if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED) + && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) + bgp_get_reuse_time(penalty, timebuf, BGP_UPTIME_LEN, 1, + json_path); + } else { + vty_out(vty, + " Dampinfo: penalty %d, flapped %d times in %s", + penalty, bdi->flap, + peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, 0, + json_path)); + + if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED) + && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) + vty_out(vty, ", reuse in %s", + bgp_get_reuse_time(penalty, timebuf, + BGP_UPTIME_LEN, 0, + json_path)); + + vty_out(vty, "\n"); + } } -const char * -bgp_damp_reuse_time_vty (struct vty *vty, struct bgp_info *binfo, - char *timebuf, size_t len, u_char use_json, json_object *json) +const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_info *binfo, + char *timebuf, size_t len, u_char use_json, + json_object *json) { - struct bgp_damp_info *bdi; - time_t t_now, t_diff; - int penalty; - - if (!binfo->extra) - return NULL; - - /* BGP dampening information. */ - bdi = binfo->extra->damp_info; - - /* If dampening is not enabled or there is no dampening information, - return immediately. */ - if (! damp || ! bdi) - return NULL; - - /* Calculate new penalty. */ - t_now = bgp_clock (); - t_diff = t_now - bdi->t_updated; - penalty = bgp_damp_decay (t_diff, bdi->penalty); - - return bgp_get_reuse_time (penalty, timebuf, len, use_json, json); + struct bgp_damp_info *bdi; + time_t t_now, t_diff; + int penalty; + + if (!binfo->extra) + return NULL; + + /* BGP dampening information. */ + bdi = binfo->extra->damp_info; + + /* If dampening is not enabled or there is no dampening information, + return immediately. */ + if (!damp || !bdi) + return NULL; + + /* Calculate new penalty. */ + t_now = bgp_clock(); + t_diff = t_now - bdi->t_updated; + penalty = bgp_damp_decay(t_diff, bdi->penalty); + + return bgp_get_reuse_time(penalty, timebuf, len, use_json, json); } -int -bgp_show_dampening_parameters (struct vty *vty, afi_t afi, safi_t safi) +int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi) { - struct bgp *bgp; - bgp = bgp_get_default(); - - if (bgp == NULL) - { - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING; - } - - if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) - { - vty_out (vty, "Half-life time: %lld min\n", - (long long)damp->half_life / 60); - vty_out (vty, "Reuse penalty: %d\n", - damp->reuse_limit); - vty_out (vty, "Suppress penalty: %d\n", - damp->suppress_value); - vty_out (vty, "Max suppress time: %lld min\n", - (long long)damp->max_suppress_time / 60); - vty_out (vty, "Max supress penalty: %u\n", - damp->ceiling); - vty_out (vty, "\n"); - } - else - vty_out (vty, "dampening not enabled for %s\n", - afi == AFI_IP ? "IPv4" : "IPv6"); - - return CMD_SUCCESS; + struct bgp *bgp; + bgp = bgp_get_default(); + + if (bgp == NULL) { + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING; + } + + if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) { + vty_out(vty, "Half-life time: %lld min\n", + (long long)damp->half_life / 60); + vty_out(vty, "Reuse penalty: %d\n", damp->reuse_limit); + vty_out(vty, "Suppress penalty: %d\n", damp->suppress_value); + vty_out(vty, "Max suppress time: %lld min\n", + (long long)damp->max_suppress_time / 60); + vty_out(vty, "Max supress penalty: %u\n", damp->ceiling); + vty_out(vty, "\n"); + } else + vty_out(vty, "dampening not enabled for %s\n", + afi == AFI_IP ? "IPv4" : "IPv6"); + + return CMD_SUCCESS; } diff --git a/bgpd/bgp_damp.h b/bgpd/bgp_damp.h index fe44d980b..1139ef839 100644 --- a/bgpd/bgp_damp.h +++ b/bgpd/bgp_damp.h @@ -22,92 +22,90 @@ #define _QUAGGA_BGP_DAMP_H /* Structure maintained on a per-route basis. */ -struct bgp_damp_info -{ - /* Doubly linked list. This information must be linked to - reuse_list or no_reuse_list. */ - struct bgp_damp_info *next; - struct bgp_damp_info *prev; - - /* Figure-of-merit. */ - unsigned int penalty; - - /* Number of flapping. */ - unsigned int flap; - - /* First flap time */ - time_t start_time; - - /* Last time penalty was updated. */ - time_t t_updated; - - /* Time of route start to be suppressed. */ - time_t suppress_time; - - /* Back reference to bgp_info. */ - struct bgp_info *binfo; - - /* Back reference to bgp_node. */ - struct bgp_node *rn; - - /* Current index in the reuse_list. */ - int index; - - /* Last time message type. */ - u_char lastrecord; +struct bgp_damp_info { + /* Doubly linked list. This information must be linked to + reuse_list or no_reuse_list. */ + struct bgp_damp_info *next; + struct bgp_damp_info *prev; + + /* Figure-of-merit. */ + unsigned int penalty; + + /* Number of flapping. */ + unsigned int flap; + + /* First flap time */ + time_t start_time; + + /* Last time penalty was updated. */ + time_t t_updated; + + /* Time of route start to be suppressed. */ + time_t suppress_time; + + /* Back reference to bgp_info. */ + struct bgp_info *binfo; + + /* Back reference to bgp_node. */ + struct bgp_node *rn; + + /* Current index in the reuse_list. */ + int index; + + /* Last time message type. */ + u_char lastrecord; #define BGP_RECORD_UPDATE 1U #define BGP_RECORD_WITHDRAW 2U - afi_t afi; - safi_t safi; + afi_t afi; + safi_t safi; }; /* Specified parameter set configuration. */ -struct bgp_damp_config -{ - /* Value over which routes suppressed. */ - unsigned int suppress_value; - - /* Value below which suppressed routes reused. */ - unsigned int reuse_limit; - - /* Max time a route can be suppressed. */ - time_t max_suppress_time; - - /* Time during which accumulated penalty reduces by half. */ - time_t half_life; - - /* Non-configurable parameters but fixed at implementation time. - * To change this values, init_bgp_damp() should be modified. - */ - time_t tmax; /* Max time previous instability retained */ - unsigned int reuse_list_size; /* Number of reuse lists */ - unsigned int reuse_index_size; /* Size of reuse index array */ - - /* Non-configurable parameters. Most of these are calculated from - * the configurable parameters above. - */ - unsigned int ceiling; /* Max value a penalty can attain */ - unsigned int decay_rate_per_tick; /* Calculated from half-life */ - unsigned int decay_array_size; /* Calculated using config parameters */ - double scale_factor; - unsigned int reuse_scale_factor; - - /* Decay array per-set based. */ - double *decay_array; - - /* Reuse index array per-set based. */ - int *reuse_index; - - /* Reuse list array per-set based. */ - struct bgp_damp_info **reuse_list; - int reuse_offset; - - /* All dampening information which is not on reuse list. */ - struct bgp_damp_info *no_reuse_list; - - /* Reuse timer thread per-set base. */ - struct thread* t_reuse; +struct bgp_damp_config { + /* Value over which routes suppressed. */ + unsigned int suppress_value; + + /* Value below which suppressed routes reused. */ + unsigned int reuse_limit; + + /* Max time a route can be suppressed. */ + time_t max_suppress_time; + + /* Time during which accumulated penalty reduces by half. */ + time_t half_life; + + /* Non-configurable parameters but fixed at implementation time. + * To change this values, init_bgp_damp() should be modified. + */ + time_t tmax; /* Max time previous instability retained */ + unsigned int reuse_list_size; /* Number of reuse lists */ + unsigned int reuse_index_size; /* Size of reuse index array */ + + /* Non-configurable parameters. Most of these are calculated from + * the configurable parameters above. + */ + unsigned int ceiling; /* Max value a penalty can attain */ + unsigned int decay_rate_per_tick; /* Calculated from half-life */ + unsigned int decay_array_size; /* Calculated using config parameters */ + double scale_factor; + unsigned int reuse_scale_factor; + + /* Decay array per-set based. */ + double *decay_array; + + /* Reuse index array per-set based. */ + int *reuse_index; + + /* Reuse list array per-set based. */ + struct bgp_damp_info **reuse_list; + int reuse_offset; + + /* All dampening information which is not on reuse list. */ + struct bgp_damp_info *no_reuse_list; + + /* Reuse timer thread per-set base. */ + struct thread *t_reuse; }; #define BGP_DAMP_NONE 0 @@ -129,20 +127,22 @@ struct bgp_damp_config #define REUSE_LIST_SIZE 256 #define REUSE_ARRAY_SIZE 1024 -extern int bgp_damp_enable (struct bgp *, afi_t, safi_t, time_t, unsigned int, - unsigned int, time_t); -extern int bgp_damp_disable (struct bgp *, afi_t, safi_t); -extern int bgp_damp_withdraw (struct bgp_info *, struct bgp_node *, - afi_t, safi_t, int); -extern int bgp_damp_update (struct bgp_info *, struct bgp_node *, afi_t, safi_t); -extern int bgp_damp_scan (struct bgp_info *, afi_t, safi_t); -extern void bgp_damp_info_free (struct bgp_damp_info *, int); -extern void bgp_damp_info_clean (void); -extern int bgp_damp_decay (time_t, int); -extern void bgp_config_write_damp (struct vty *); -extern void bgp_damp_info_vty (struct vty *, struct bgp_info *, json_object *json_path); -extern const char * bgp_damp_reuse_time_vty (struct vty *, struct bgp_info *, - char *, size_t, u_char, json_object *); -extern int bgp_show_dampening_parameters (struct vty *vty, afi_t, safi_t); +extern int bgp_damp_enable(struct bgp *, afi_t, safi_t, time_t, unsigned int, + unsigned int, time_t); +extern int bgp_damp_disable(struct bgp *, afi_t, safi_t); +extern int bgp_damp_withdraw(struct bgp_info *, struct bgp_node *, afi_t, + safi_t, int); +extern int bgp_damp_update(struct bgp_info *, struct bgp_node *, afi_t, safi_t); +extern int bgp_damp_scan(struct bgp_info *, afi_t, safi_t); +extern void bgp_damp_info_free(struct bgp_damp_info *, int); +extern void bgp_damp_info_clean(void); +extern int bgp_damp_decay(time_t, int); +extern void bgp_config_write_damp(struct vty *); +extern void bgp_damp_info_vty(struct vty *, struct bgp_info *, + json_object *json_path); +extern const char *bgp_damp_reuse_time_vty(struct vty *, struct bgp_info *, + char *, size_t, u_char, + json_object *); +extern int bgp_show_dampening_parameters(struct vty *vty, afi_t, safi_t); #endif /* _QUAGGA_BGP_DAMP_H */ diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index f9e67d96c..1e7567299 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -78,504 +78,465 @@ struct list *bgp_debug_bestpath_prefixes = NULL; struct list *bgp_debug_zebra_prefixes = NULL; /* messages for BGP-4 status */ -const struct message bgp_status_msg[] = -{ - { Idle, "Idle" }, - { Connect, "Connect" }, - { Active, "Active" }, - { OpenSent, "OpenSent" }, - { OpenConfirm, "OpenConfirm" }, - { Established, "Established" }, - { Clearing, "Clearing" }, - { Deleted, "Deleted" }, - { 0 } -}; +const struct message bgp_status_msg[] = {{Idle, "Idle"}, + {Connect, "Connect"}, + {Active, "Active"}, + {OpenSent, "OpenSent"}, + {OpenConfirm, "OpenConfirm"}, + {Established, "Established"}, + {Clearing, "Clearing"}, + {Deleted, "Deleted"}, + {0}}; /* BGP message type string. */ -const char *bgp_type_str[] = -{ - NULL, - "OPEN", - "UPDATE", - "NOTIFICATION", - "KEEPALIVE", - "ROUTE-REFRESH", - "CAPABILITY" -}; +const char *bgp_type_str[] = {NULL, "OPEN", "UPDATE", + "NOTIFICATION", "KEEPALIVE", "ROUTE-REFRESH", + "CAPABILITY"}; /* message for BGP-4 Notify */ -static const struct message bgp_notify_msg[] = -{ - { BGP_NOTIFY_HEADER_ERR, "Message Header Error"}, - { BGP_NOTIFY_OPEN_ERR, "OPEN Message Error"}, - { BGP_NOTIFY_UPDATE_ERR, "UPDATE Message Error"}, - { BGP_NOTIFY_HOLD_ERR, "Hold Timer Expired"}, - { BGP_NOTIFY_FSM_ERR, "Neighbor Events Error"}, - { BGP_NOTIFY_CEASE, "Cease"}, - { BGP_NOTIFY_CAPABILITY_ERR, "CAPABILITY Message Error"}, - { 0 } -}; - -static const struct message bgp_notify_head_msg[] = -{ - { BGP_NOTIFY_HEADER_NOT_SYNC, "/Connection Not Synchronized"}, - { BGP_NOTIFY_HEADER_BAD_MESLEN, "/Bad Message Length"}, - { BGP_NOTIFY_HEADER_BAD_MESTYPE, "/Bad Message Type"}, - { 0 } -}; - -static const struct message bgp_notify_open_msg[] = -{ - { BGP_NOTIFY_SUBCODE_UNSPECIFIC, "/Unspecific"}, - { BGP_NOTIFY_OPEN_UNSUP_VERSION, "/Unsupported Version Number" }, - { BGP_NOTIFY_OPEN_BAD_PEER_AS, "/Bad Peer AS"}, - { BGP_NOTIFY_OPEN_BAD_BGP_IDENT, "/Bad BGP Identifier"}, - { BGP_NOTIFY_OPEN_UNSUP_PARAM, "/Unsupported Optional Parameter"}, - { BGP_NOTIFY_OPEN_AUTH_FAILURE, "/Authentication Failure"}, - { BGP_NOTIFY_OPEN_UNACEP_HOLDTIME, "/Unacceptable Hold Time"}, - { BGP_NOTIFY_OPEN_UNSUP_CAPBL, "/Unsupported Capability"}, - { 0 } -}; - -static const struct message bgp_notify_update_msg[] = -{ - { BGP_NOTIFY_SUBCODE_UNSPECIFIC, "/Unspecific"}, - { BGP_NOTIFY_UPDATE_MAL_ATTR, "/Malformed Attribute List"}, - { BGP_NOTIFY_UPDATE_UNREC_ATTR, "/Unrecognized Well-known Attribute"}, - { BGP_NOTIFY_UPDATE_MISS_ATTR, "/Missing Well-known Attribute"}, - { BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, "/Attribute Flags Error"}, - { BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, "/Attribute Length Error"}, - { BGP_NOTIFY_UPDATE_INVAL_ORIGIN, "/Invalid ORIGIN Attribute"}, - { BGP_NOTIFY_UPDATE_AS_ROUTE_LOOP, "/AS Routing Loop"}, - { BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP, "/Invalid NEXT_HOP Attribute"}, - { BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, "/Optional Attribute Error"}, - { BGP_NOTIFY_UPDATE_INVAL_NETWORK, "/Invalid Network Field"}, - { BGP_NOTIFY_UPDATE_MAL_AS_PATH, "/Malformed AS_PATH"}, - { 0 } -}; - -static const struct message bgp_notify_cease_msg[] = -{ - { BGP_NOTIFY_SUBCODE_UNSPECIFIC, "/Unspecific"}, - { BGP_NOTIFY_CEASE_MAX_PREFIX, "/Maximum Number of Prefixes Reached"}, - { BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN, "/Administratively Shutdown"}, - { BGP_NOTIFY_CEASE_PEER_UNCONFIG, "/Peer Unconfigured"}, - { BGP_NOTIFY_CEASE_ADMIN_RESET, "/Administratively Reset"}, - { BGP_NOTIFY_CEASE_CONNECT_REJECT, "/Connection Rejected"}, - { BGP_NOTIFY_CEASE_CONFIG_CHANGE, "/Other Configuration Change"}, - { BGP_NOTIFY_CEASE_COLLISION_RESOLUTION, "/Connection collision resolution"}, - { BGP_NOTIFY_CEASE_OUT_OF_RESOURCE, "/Out of Resource"}, - { 0 } -}; - -static const struct message bgp_notify_capability_msg[] = -{ - { BGP_NOTIFY_SUBCODE_UNSPECIFIC, "/Unspecific"}, - { BGP_NOTIFY_CAPABILITY_INVALID_ACTION, "/Invalid Action Value" }, - { BGP_NOTIFY_CAPABILITY_INVALID_LENGTH, "/Invalid Capability Length"}, - { BGP_NOTIFY_CAPABILITY_MALFORMED_CODE, "/Malformed Capability Value"}, - { 0 } -}; +static const struct message bgp_notify_msg[] = { + {BGP_NOTIFY_HEADER_ERR, "Message Header Error"}, + {BGP_NOTIFY_OPEN_ERR, "OPEN Message Error"}, + {BGP_NOTIFY_UPDATE_ERR, "UPDATE Message Error"}, + {BGP_NOTIFY_HOLD_ERR, "Hold Timer Expired"}, + {BGP_NOTIFY_FSM_ERR, "Neighbor Events Error"}, + {BGP_NOTIFY_CEASE, "Cease"}, + {BGP_NOTIFY_CAPABILITY_ERR, "CAPABILITY Message Error"}, + {0}}; + +static const struct message bgp_notify_head_msg[] = { + {BGP_NOTIFY_HEADER_NOT_SYNC, "/Connection Not Synchronized"}, + {BGP_NOTIFY_HEADER_BAD_MESLEN, "/Bad Message Length"}, + {BGP_NOTIFY_HEADER_BAD_MESTYPE, "/Bad Message Type"}, + {0}}; + +static const struct message bgp_notify_open_msg[] = { + {BGP_NOTIFY_SUBCODE_UNSPECIFIC, "/Unspecific"}, + {BGP_NOTIFY_OPEN_UNSUP_VERSION, "/Unsupported Version Number"}, + {BGP_NOTIFY_OPEN_BAD_PEER_AS, "/Bad Peer AS"}, + {BGP_NOTIFY_OPEN_BAD_BGP_IDENT, "/Bad BGP Identifier"}, + {BGP_NOTIFY_OPEN_UNSUP_PARAM, "/Unsupported Optional Parameter"}, + {BGP_NOTIFY_OPEN_AUTH_FAILURE, "/Authentication Failure"}, + {BGP_NOTIFY_OPEN_UNACEP_HOLDTIME, "/Unacceptable Hold Time"}, + {BGP_NOTIFY_OPEN_UNSUP_CAPBL, "/Unsupported Capability"}, + {0}}; + +static const struct message bgp_notify_update_msg[] = { + {BGP_NOTIFY_SUBCODE_UNSPECIFIC, "/Unspecific"}, + {BGP_NOTIFY_UPDATE_MAL_ATTR, "/Malformed Attribute List"}, + {BGP_NOTIFY_UPDATE_UNREC_ATTR, "/Unrecognized Well-known Attribute"}, + {BGP_NOTIFY_UPDATE_MISS_ATTR, "/Missing Well-known Attribute"}, + {BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, "/Attribute Flags Error"}, + {BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, "/Attribute Length Error"}, + {BGP_NOTIFY_UPDATE_INVAL_ORIGIN, "/Invalid ORIGIN Attribute"}, + {BGP_NOTIFY_UPDATE_AS_ROUTE_LOOP, "/AS Routing Loop"}, + {BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP, "/Invalid NEXT_HOP Attribute"}, + {BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, "/Optional Attribute Error"}, + {BGP_NOTIFY_UPDATE_INVAL_NETWORK, "/Invalid Network Field"}, + {BGP_NOTIFY_UPDATE_MAL_AS_PATH, "/Malformed AS_PATH"}, + {0}}; + +static const struct message bgp_notify_cease_msg[] = { + {BGP_NOTIFY_SUBCODE_UNSPECIFIC, "/Unspecific"}, + {BGP_NOTIFY_CEASE_MAX_PREFIX, "/Maximum Number of Prefixes Reached"}, + {BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN, "/Administratively Shutdown"}, + {BGP_NOTIFY_CEASE_PEER_UNCONFIG, "/Peer Unconfigured"}, + {BGP_NOTIFY_CEASE_ADMIN_RESET, "/Administratively Reset"}, + {BGP_NOTIFY_CEASE_CONNECT_REJECT, "/Connection Rejected"}, + {BGP_NOTIFY_CEASE_CONFIG_CHANGE, "/Other Configuration Change"}, + {BGP_NOTIFY_CEASE_COLLISION_RESOLUTION, + "/Connection collision resolution"}, + {BGP_NOTIFY_CEASE_OUT_OF_RESOURCE, "/Out of Resource"}, + {0}}; + +static const struct message bgp_notify_capability_msg[] = { + {BGP_NOTIFY_SUBCODE_UNSPECIFIC, "/Unspecific"}, + {BGP_NOTIFY_CAPABILITY_INVALID_ACTION, "/Invalid Action Value"}, + {BGP_NOTIFY_CAPABILITY_INVALID_LENGTH, "/Invalid Capability Length"}, + {BGP_NOTIFY_CAPABILITY_MALFORMED_CODE, "/Malformed Capability Value"}, + {0}}; /* Origin strings. */ -const char *bgp_origin_str[] = {"i","e","?"}; -const char *bgp_origin_long_str[] = {"IGP","EGP","incomplete"}; +const char *bgp_origin_str[] = {"i", "e", "?"}; +const char *bgp_origin_long_str[] = {"IGP", "EGP", "incomplete"}; /* Given a string return a pointer the corresponding peer structure */ -static struct peer * -bgp_find_peer (struct vty *vty, const char *peer_str) +static struct peer *bgp_find_peer(struct vty *vty, const char *peer_str) { - struct bgp *bgp = VTY_GET_CONTEXT(bgp); - int ret; - union sockunion su; - struct peer *peer; - - if (!bgp) { - return NULL; - } - ret = str2sockunion (peer_str, &su); - - /* 'swpX' string */ - if (ret < 0) - { - peer = peer_lookup_by_conf_if (bgp, peer_str); - - if (!peer) - peer = peer_lookup_by_hostname (bgp, peer_str); - - return peer; - } - else - return peer_lookup (bgp, &su); + struct bgp *bgp = VTY_GET_CONTEXT(bgp); + int ret; + union sockunion su; + struct peer *peer; + + if (!bgp) { + return NULL; + } + ret = str2sockunion(peer_str, &su); + + /* 'swpX' string */ + if (ret < 0) { + peer = peer_lookup_by_conf_if(bgp, peer_str); + + if (!peer) + peer = peer_lookup_by_hostname(bgp, peer_str); + + return peer; + } else + return peer_lookup(bgp, &su); } -static void -bgp_debug_list_free(struct list *list) +static void bgp_debug_list_free(struct list *list) { - struct bgp_debug_filter *filter; - struct listnode *node, *nnode; + struct bgp_debug_filter *filter; + struct listnode *node, *nnode; - if (list) - for (ALL_LIST_ELEMENTS (list, node, nnode, filter)) - { - listnode_delete (list, filter); + if (list) + for (ALL_LIST_ELEMENTS(list, node, nnode, filter)) { + listnode_delete(list, filter); - if (filter->p) - prefix_free(filter->p); + if (filter->p) + prefix_free(filter->p); - if (filter->host) - XFREE (MTYPE_BGP_DEBUG_STR, filter->host); + if (filter->host) + XFREE(MTYPE_BGP_DEBUG_STR, filter->host); - XFREE (MTYPE_BGP_DEBUG_FILTER, filter); - } + XFREE(MTYPE_BGP_DEBUG_FILTER, filter); + } } /* Print the desc along with a list of peers/prefixes this debug is * enabled for */ -static void -bgp_debug_list_print (struct vty *vty, const char *desc, struct list *list) -{ - struct bgp_debug_filter *filter; - struct listnode *node, *nnode; - char buf[INET6_ADDRSTRLEN]; - - vty_out (vty, "%s", desc); - - if (list && !list_isempty(list)) - { - vty_out (vty, " for"); - for (ALL_LIST_ELEMENTS (list, node, nnode, filter)) - { - if (filter->host) - vty_out (vty, " %s", filter->host); - - if (filter->p) - vty_out (vty, " %s/%d", - inet_ntop (filter->p->family, &filter->p->u.prefix, buf, INET6_ADDRSTRLEN), - filter->p->prefixlen); - } - } - - vty_out (vty, "\n"); +static void bgp_debug_list_print(struct vty *vty, const char *desc, + struct list *list) +{ + struct bgp_debug_filter *filter; + struct listnode *node, *nnode; + char buf[INET6_ADDRSTRLEN]; + + vty_out(vty, "%s", desc); + + if (list && !list_isempty(list)) { + vty_out(vty, " for"); + for (ALL_LIST_ELEMENTS(list, node, nnode, filter)) { + if (filter->host) + vty_out(vty, " %s", filter->host); + + if (filter->p) + vty_out(vty, " %s/%d", + inet_ntop(filter->p->family, + &filter->p->u.prefix, buf, + INET6_ADDRSTRLEN), + filter->p->prefixlen); + } + } + + vty_out(vty, "\n"); } /* Print the command to enable the debug for each peer/prefix this debug is * enabled for */ -static int -bgp_debug_list_conf_print (struct vty *vty, const char *desc, struct list *list) -{ - struct bgp_debug_filter *filter; - struct listnode *node, *nnode; - char buf[INET6_ADDRSTRLEN]; - int write = 0; - - if (list && !list_isempty(list)) - { - for (ALL_LIST_ELEMENTS (list, node, nnode, filter)) - { - if (filter->host) - { - vty_out (vty, "%s %s\n", desc, filter->host); - write++; - } - - - if (filter->p) - { - vty_out (vty, "%s %s/%d\n", desc, - inet_ntop (filter->p->family, &filter->p->u.prefix, buf, INET6_ADDRSTRLEN), - filter->p->prefixlen); - write++; - } - } - } - - if (!write) - { - vty_out (vty, "%s\n", desc); - write++; - } - - return write; +static int bgp_debug_list_conf_print(struct vty *vty, const char *desc, + struct list *list) +{ + struct bgp_debug_filter *filter; + struct listnode *node, *nnode; + char buf[INET6_ADDRSTRLEN]; + int write = 0; + + if (list && !list_isempty(list)) { + for (ALL_LIST_ELEMENTS(list, node, nnode, filter)) { + if (filter->host) { + vty_out(vty, "%s %s\n", desc, filter->host); + write++; + } + + + if (filter->p) { + vty_out(vty, "%s %s/%d\n", desc, + inet_ntop(filter->p->family, + &filter->p->u.prefix, buf, + INET6_ADDRSTRLEN), + filter->p->prefixlen); + write++; + } + } + } + + if (!write) { + vty_out(vty, "%s\n", desc); + write++; + } + + return write; } -static void -bgp_debug_list_add_entry(struct list *list, const char *host, const struct prefix *p) +static void bgp_debug_list_add_entry(struct list *list, const char *host, + const struct prefix *p) { - struct bgp_debug_filter *filter; - - filter = XCALLOC (MTYPE_BGP_DEBUG_FILTER, sizeof (struct bgp_debug_filter)); - - if (host) - { - filter->host = XSTRDUP (MTYPE_BGP_DEBUG_STR, host); - filter->p = NULL; - } - else if (p) - { - filter->host = NULL; - filter->p = prefix_new(); - prefix_copy (filter->p, p); - } - - listnode_add(list, filter); + struct bgp_debug_filter *filter; + + filter = XCALLOC(MTYPE_BGP_DEBUG_FILTER, + sizeof(struct bgp_debug_filter)); + + if (host) { + filter->host = XSTRDUP(MTYPE_BGP_DEBUG_STR, host); + filter->p = NULL; + } else if (p) { + filter->host = NULL; + filter->p = prefix_new(); + prefix_copy(filter->p, p); + } + + listnode_add(list, filter); } -static int -bgp_debug_list_remove_entry(struct list *list, const char *host, struct prefix *p) -{ - struct bgp_debug_filter *filter; - struct listnode *node, *nnode; - - for (ALL_LIST_ELEMENTS (list, node, nnode, filter)) - { - if (host && strcmp (filter->host, host) == 0) - { - listnode_delete (list, filter); - XFREE (MTYPE_BGP_DEBUG_STR, filter->host); - XFREE (MTYPE_BGP_DEBUG_FILTER, filter); - return 1; - } - else if (p && filter->p->prefixlen == p->prefixlen && prefix_match(filter->p, p)) - { - listnode_delete (list, filter); - prefix_free (filter->p); - XFREE (MTYPE_BGP_DEBUG_FILTER, filter); - return 1; - } - } - - return 0; +static int bgp_debug_list_remove_entry(struct list *list, const char *host, + struct prefix *p) +{ + struct bgp_debug_filter *filter; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS(list, node, nnode, filter)) { + if (host && strcmp(filter->host, host) == 0) { + listnode_delete(list, filter); + XFREE(MTYPE_BGP_DEBUG_STR, filter->host); + XFREE(MTYPE_BGP_DEBUG_FILTER, filter); + return 1; + } else if (p && filter->p->prefixlen == p->prefixlen + && prefix_match(filter->p, p)) { + listnode_delete(list, filter); + prefix_free(filter->p); + XFREE(MTYPE_BGP_DEBUG_FILTER, filter); + return 1; + } + } + + return 0; } -static int -bgp_debug_list_has_entry(struct list *list, const char *host, const struct prefix *p) -{ - struct bgp_debug_filter *filter; - struct listnode *node, *nnode; - - for (ALL_LIST_ELEMENTS (list, node, nnode, filter)) - { - if (host) - { - if (strcmp (filter->host, host) == 0) - { - return 1; - } - } - else if (p) - { - if (filter->p->prefixlen == p->prefixlen && prefix_match(filter->p, p)) - { - return 1; - } - } - } - - return 0; +static int bgp_debug_list_has_entry(struct list *list, const char *host, + const struct prefix *p) +{ + struct bgp_debug_filter *filter; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS(list, node, nnode, filter)) { + if (host) { + if (strcmp(filter->host, host) == 0) { + return 1; + } + } else if (p) { + if (filter->p->prefixlen == p->prefixlen + && prefix_match(filter->p, p)) { + return 1; + } + } + } + + return 0; } -int -bgp_debug_peer_updout_enabled(char *host) +int bgp_debug_peer_updout_enabled(char *host) { - return (bgp_debug_list_has_entry(bgp_debug_update_out_peers, host, NULL)); + return (bgp_debug_list_has_entry(bgp_debug_update_out_peers, host, + NULL)); } /* Dump attribute. */ -int -bgp_dump_attr (struct attr *attr, char *buf, size_t size) +int bgp_dump_attr(struct attr *attr, char *buf, size_t size) { - char addrbuf[BUFSIZ]; - - if (! attr) - return 0; - - if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))) - snprintf (buf, size, "nexthop %s", inet_ntoa (attr->nexthop)); - - if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN))) - snprintf (buf + strlen (buf), size - strlen (buf), ", origin %s", - bgp_origin_str[attr->origin]); - - /* Add MP case. */ - if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL - || attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) - snprintf (buf + strlen (buf), size - strlen (buf), ", mp_nexthop %s", - inet_ntop (AF_INET6, &attr->mp_nexthop_global, - addrbuf, BUFSIZ)); - - if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) - snprintf (buf + strlen (buf), size - strlen (buf), "(%s)", - inet_ntop (AF_INET6, &attr->mp_nexthop_local, - addrbuf, BUFSIZ)); - - if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4) - snprintf (buf, size, "nexthop %s", inet_ntoa (attr->nexthop)); - - if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))) - snprintf (buf + strlen (buf), size - strlen (buf), ", localpref %u", - attr->local_pref); - - if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))) - snprintf (buf + strlen (buf), size - strlen (buf), ", metric %u", - attr->med); - - if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))) - snprintf (buf + strlen (buf), size - strlen (buf), ", community %s", - community_str (attr->community)); - - if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES))) - snprintf (buf + strlen (buf), size - strlen (buf), ", extcommunity %s", - ecommunity_str (attr->ecommunity)); - - if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))) - snprintf (buf + strlen (buf), size - strlen (buf), ", atomic-aggregate"); - - if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))) - snprintf (buf + strlen (buf), size - strlen (buf), ", aggregated by %u %s", - attr->aggregator_as, - inet_ntoa (attr->aggregator_addr)); - - if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID))) - snprintf (buf + strlen (buf), size - strlen (buf), ", originator %s", - inet_ntoa (attr->originator_id)); - - if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST))) - { - int i; - - snprintf (buf + strlen (buf), size - strlen (buf), ", clusterlist"); - for (i = 0; i < attr->cluster->length / 4; i++) - snprintf (buf + strlen (buf), size - strlen (buf), " %s", - inet_ntoa (attr->cluster->list[i])); - } - - if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))) - snprintf (buf + strlen (buf), size - strlen (buf), ", path %s", - aspath_print (attr->aspath)); - - if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID))) - { - if (attr->label_index != BGP_INVALID_LABEL_INDEX) - snprintf (buf + strlen (buf), size - strlen (buf), ", label-index %u", - attr->label_index); - } - - if (strlen (buf) > 1) - return 1; - else - return 0; -} + char addrbuf[BUFSIZ]; -const char * -bgp_notify_code_str (char code) -{ - return lookup_msg (bgp_notify_msg, code, "Unrecognized Error Code"); + if (!attr) + return 0; + + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))) + snprintf(buf, size, "nexthop %s", inet_ntoa(attr->nexthop)); + + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN))) + snprintf(buf + strlen(buf), size - strlen(buf), ", origin %s", + bgp_origin_str[attr->origin]); + + /* Add MP case. */ + if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL + || attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) + snprintf(buf + strlen(buf), size - strlen(buf), + ", mp_nexthop %s", + inet_ntop(AF_INET6, &attr->mp_nexthop_global, addrbuf, + BUFSIZ)); + + if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) + snprintf(buf + strlen(buf), size - strlen(buf), "(%s)", + inet_ntop(AF_INET6, &attr->mp_nexthop_local, addrbuf, + BUFSIZ)); + + if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4) + snprintf(buf, size, "nexthop %s", inet_ntoa(attr->nexthop)); + + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) + snprintf(buf + strlen(buf), size - strlen(buf), + ", localpref %u", attr->local_pref); + + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))) + snprintf(buf + strlen(buf), size - strlen(buf), ", metric %u", + attr->med); + + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) + snprintf(buf + strlen(buf), size - strlen(buf), + ", community %s", community_str(attr->community)); + + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) + snprintf(buf + strlen(buf), size - strlen(buf), + ", extcommunity %s", ecommunity_str(attr->ecommunity)); + + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))) + snprintf(buf + strlen(buf), size - strlen(buf), + ", atomic-aggregate"); + + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) + snprintf(buf + strlen(buf), size - strlen(buf), + ", aggregated by %u %s", attr->aggregator_as, + inet_ntoa(attr->aggregator_addr)); + + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))) + snprintf(buf + strlen(buf), size - strlen(buf), + ", originator %s", inet_ntoa(attr->originator_id)); + + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) { + int i; + + snprintf(buf + strlen(buf), size - strlen(buf), + ", clusterlist"); + for (i = 0; i < attr->cluster->length / 4; i++) + snprintf(buf + strlen(buf), size - strlen(buf), " %s", + inet_ntoa(attr->cluster->list[i])); + } + + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))) + snprintf(buf + strlen(buf), size - strlen(buf), ", path %s", + aspath_print(attr->aspath)); + + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID))) { + if (attr->label_index != BGP_INVALID_LABEL_INDEX) + snprintf(buf + strlen(buf), size - strlen(buf), + ", label-index %u", attr->label_index); + } + + if (strlen(buf) > 1) + return 1; + else + return 0; } -const char * -bgp_notify_subcode_str (char code, char subcode) +const char *bgp_notify_code_str(char code) { + return lookup_msg(bgp_notify_msg, code, "Unrecognized Error Code"); +} - switch (code) - { - case BGP_NOTIFY_HEADER_ERR: - return lookup_msg (bgp_notify_head_msg, subcode, - "Unrecognized Error Subcode"); - case BGP_NOTIFY_OPEN_ERR: - return lookup_msg (bgp_notify_open_msg, subcode, - "Unrecognized Error Subcode"); - case BGP_NOTIFY_UPDATE_ERR: - return lookup_msg (bgp_notify_update_msg, subcode, - "Unrecognized Error Subcode"); - case BGP_NOTIFY_HOLD_ERR: - break; - case BGP_NOTIFY_FSM_ERR: - break; - case BGP_NOTIFY_CEASE: - return lookup_msg (bgp_notify_cease_msg, subcode, - "Unrecognized Error Subcode"); - case BGP_NOTIFY_CAPABILITY_ERR: - return lookup_msg (bgp_notify_capability_msg, subcode, - "Unrecognized Error Subcode"); - } - return ""; +const char *bgp_notify_subcode_str(char code, char subcode) +{ + + switch (code) { + case BGP_NOTIFY_HEADER_ERR: + return lookup_msg(bgp_notify_head_msg, subcode, + "Unrecognized Error Subcode"); + case BGP_NOTIFY_OPEN_ERR: + return lookup_msg(bgp_notify_open_msg, subcode, + "Unrecognized Error Subcode"); + case BGP_NOTIFY_UPDATE_ERR: + return lookup_msg(bgp_notify_update_msg, subcode, + "Unrecognized Error Subcode"); + case BGP_NOTIFY_HOLD_ERR: + break; + case BGP_NOTIFY_FSM_ERR: + break; + case BGP_NOTIFY_CEASE: + return lookup_msg(bgp_notify_cease_msg, subcode, + "Unrecognized Error Subcode"); + case BGP_NOTIFY_CAPABILITY_ERR: + return lookup_msg(bgp_notify_capability_msg, subcode, + "Unrecognized Error Subcode"); + } + return ""; } /* extract notify admin reason if correctly present */ -const char * -bgp_notify_admin_message(char *buf, size_t bufsz, u_char *data, size_t datalen) +const char *bgp_notify_admin_message(char *buf, size_t bufsz, u_char *data, + size_t datalen) { - if (!data || datalen < 1) - return NULL; + if (!data || datalen < 1) + return NULL; - u_char len = data[0]; - if (len > 128 - || len > datalen - 1) - return NULL; + u_char len = data[0]; + if (len > 128 || len > datalen - 1) + return NULL; - return zlog_sanitize(buf, bufsz, data + 1, len); + return zlog_sanitize(buf, bufsz, data + 1, len); } /* dump notify packet */ -void -bgp_notify_print(struct peer *peer, struct bgp_notify *bgp_notify, - const char *direct) -{ - const char *subcode_str; - const char *code_str; - const char *msg_str = NULL; - char msg_buf[1024]; - - if (BGP_DEBUG (neighbor_events, NEIGHBOR_EVENTS) || bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES)) - { - code_str = bgp_notify_code_str(bgp_notify->code); - subcode_str = bgp_notify_subcode_str(bgp_notify->code, bgp_notify->subcode); - - if (bgp_notify->code == BGP_NOTIFY_CEASE - && (bgp_notify->subcode == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN - || bgp_notify->subcode == BGP_NOTIFY_CEASE_ADMIN_RESET)) - { - msg_str = bgp_notify_admin_message(msg_buf, sizeof(msg_buf), - bgp_notify->raw_data, bgp_notify->length); - } - - if (msg_str) - { - zlog_info ("%%NOTIFICATION: %s neighbor %s %d/%d (%s%s) \"%s\"", - strcmp (direct, "received") == 0 ? "received from" : "sent to", - peer->host, bgp_notify->code, bgp_notify->subcode, - code_str, subcode_str, msg_str); - } - else - { - msg_str = bgp_notify->data ? bgp_notify->data : ""; - zlog_info ("%%NOTIFICATION: %s neighbor %s %d/%d (%s%s) %d bytes %s", - strcmp (direct, "received") == 0 ? "received from" : "sent to", - peer->host, bgp_notify->code, bgp_notify->subcode, - code_str, subcode_str, bgp_notify->length, msg_str); - } - } +void bgp_notify_print(struct peer *peer, struct bgp_notify *bgp_notify, + const char *direct) +{ + const char *subcode_str; + const char *code_str; + const char *msg_str = NULL; + char msg_buf[1024]; + + if (BGP_DEBUG(neighbor_events, NEIGHBOR_EVENTS) + || bgp_flag_check(peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES)) { + code_str = bgp_notify_code_str(bgp_notify->code); + subcode_str = bgp_notify_subcode_str(bgp_notify->code, + bgp_notify->subcode); + + if (bgp_notify->code == BGP_NOTIFY_CEASE + && (bgp_notify->subcode == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN + || bgp_notify->subcode + == BGP_NOTIFY_CEASE_ADMIN_RESET)) { + msg_str = bgp_notify_admin_message( + msg_buf, sizeof(msg_buf), bgp_notify->raw_data, + bgp_notify->length); + } + + if (msg_str) { + zlog_info( + "%%NOTIFICATION: %s neighbor %s %d/%d (%s%s) \"%s\"", + strcmp(direct, "received") == 0 + ? "received from" + : "sent to", + peer->host, bgp_notify->code, + bgp_notify->subcode, code_str, subcode_str, + msg_str); + } else { + msg_str = bgp_notify->data ? bgp_notify->data : ""; + zlog_info( + "%%NOTIFICATION: %s neighbor %s %d/%d (%s%s) %d bytes %s", + strcmp(direct, "received") == 0 + ? "received from" + : "sent to", + peer->host, bgp_notify->code, + bgp_notify->subcode, code_str, subcode_str, + bgp_notify->length, msg_str); + } + } } -static void -bgp_debug_clear_updgrp_update_dbg(struct bgp *bgp) +static void bgp_debug_clear_updgrp_update_dbg(struct bgp *bgp) { - if (!bgp) - bgp = bgp_get_default(); - update_group_walk (bgp, update_group_clear_update_dbg, NULL); + if (!bgp) + bgp = bgp_get_default(); + update_group_walk(bgp, update_group_clear_update_dbg, NULL); } /* Debug option setting interface. */ unsigned long bgp_debug_option = 0; -int -debug (unsigned int option) +int debug(unsigned int option) { - return bgp_debug_option & option; + return bgp_debug_option & option; } DEFUN (debug_bgp_as4, @@ -585,14 +546,13 @@ DEFUN (debug_bgp_as4, BGP_STR "BGP AS4 actions\n") { - if (vty->node == CONFIG_NODE) - DEBUG_ON (as4, AS4); - else - { - TERM_DEBUG_ON (as4, AS4); - vty_out (vty, "BGP as4 debugging is on\n"); - } - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + DEBUG_ON(as4, AS4); + else { + TERM_DEBUG_ON(as4, AS4); + vty_out(vty, "BGP as4 debugging is on\n"); + } + return CMD_SUCCESS; } DEFUN (no_debug_bgp_as4, @@ -603,14 +563,13 @@ DEFUN (no_debug_bgp_as4, BGP_STR "BGP AS4 actions\n") { - if (vty->node == CONFIG_NODE) - DEBUG_OFF (as4, AS4); - else - { - TERM_DEBUG_OFF (as4, AS4); - vty_out (vty, "BGP as4 debugging is off\n"); - } - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + DEBUG_OFF(as4, AS4); + else { + TERM_DEBUG_OFF(as4, AS4); + vty_out(vty, "BGP as4 debugging is off\n"); + } + return CMD_SUCCESS; } DEFUN (debug_bgp_as4_segment, @@ -621,14 +580,13 @@ DEFUN (debug_bgp_as4_segment, "BGP AS4 actions\n" "BGP AS4 aspath segment handling\n") { - if (vty->node == CONFIG_NODE) - DEBUG_ON (as4, AS4_SEGMENT); - else - { - TERM_DEBUG_ON (as4, AS4_SEGMENT); - vty_out (vty, "BGP as4 segment debugging is on\n"); - } - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + DEBUG_ON(as4, AS4_SEGMENT); + else { + TERM_DEBUG_ON(as4, AS4_SEGMENT); + vty_out(vty, "BGP as4 segment debugging is on\n"); + } + return CMD_SUCCESS; } DEFUN (no_debug_bgp_as4_segment, @@ -640,14 +598,13 @@ DEFUN (no_debug_bgp_as4_segment, "BGP AS4 actions\n" "BGP AS4 aspath segment handling\n") { - if (vty->node == CONFIG_NODE) - DEBUG_OFF (as4, AS4_SEGMENT); - else - { - TERM_DEBUG_OFF (as4, AS4_SEGMENT); - vty_out (vty, "BGP as4 segment debugging is off\n"); - } - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + DEBUG_OFF(as4, AS4_SEGMENT); + else { + TERM_DEBUG_OFF(as4, AS4_SEGMENT); + vty_out(vty, "BGP as4 segment debugging is off\n"); + } + return CMD_SUCCESS; } /* debug bgp neighbor_events */ @@ -658,16 +615,15 @@ DEFUN (debug_bgp_neighbor_events, BGP_STR "BGP Neighbor Events\n") { - bgp_debug_list_free(bgp_debug_neighbor_events_peers); - - if (vty->node == CONFIG_NODE) - DEBUG_ON (neighbor_events, NEIGHBOR_EVENTS); - else - { - TERM_DEBUG_ON (neighbor_events, NEIGHBOR_EVENTS); - vty_out (vty, "BGP neighbor-events debugging is on\n"); - } - return CMD_SUCCESS; + bgp_debug_list_free(bgp_debug_neighbor_events_peers); + + if (vty->node == CONFIG_NODE) + DEBUG_ON(neighbor_events, NEIGHBOR_EVENTS); + else { + TERM_DEBUG_ON(neighbor_events, NEIGHBOR_EVENTS); + vty_out(vty, "BGP neighbor-events debugging is on\n"); + } + return CMD_SUCCESS; } DEFUN (debug_bgp_neighbor_events_peer, @@ -680,29 +636,30 @@ DEFUN (debug_bgp_neighbor_events_peer, "BGP IPv6 neighbor to debug\n" "BGP neighbor on interface to debug\n") { - int idx_peer = 3; - const char *host = argv[idx_peer]->arg; - - if (!bgp_debug_neighbor_events_peers) - bgp_debug_neighbor_events_peers = list_new (); - - if (bgp_debug_list_has_entry(bgp_debug_neighbor_events_peers, host, NULL)) - { - vty_out (vty, "BGP neighbor-events debugging is already enabled for %s\n", - host); - return CMD_SUCCESS; - } - - bgp_debug_list_add_entry(bgp_debug_neighbor_events_peers, host, NULL); - - if (vty->node == CONFIG_NODE) - DEBUG_ON (neighbor_events, NEIGHBOR_EVENTS); - else - { - TERM_DEBUG_ON (neighbor_events, NEIGHBOR_EVENTS); - vty_out (vty, "BGP neighbor-events debugging is on for %s\n", host); - } - return CMD_SUCCESS; + int idx_peer = 3; + const char *host = argv[idx_peer]->arg; + + if (!bgp_debug_neighbor_events_peers) + bgp_debug_neighbor_events_peers = list_new(); + + if (bgp_debug_list_has_entry(bgp_debug_neighbor_events_peers, host, + NULL)) { + vty_out(vty, + "BGP neighbor-events debugging is already enabled for %s\n", + host); + return CMD_SUCCESS; + } + + bgp_debug_list_add_entry(bgp_debug_neighbor_events_peers, host, NULL); + + if (vty->node == CONFIG_NODE) + DEBUG_ON(neighbor_events, NEIGHBOR_EVENTS); + else { + TERM_DEBUG_ON(neighbor_events, NEIGHBOR_EVENTS); + vty_out(vty, "BGP neighbor-events debugging is on for %s\n", + host); + } + return CMD_SUCCESS; } DEFUN (no_debug_bgp_neighbor_events, @@ -713,16 +670,15 @@ DEFUN (no_debug_bgp_neighbor_events, BGP_STR "Neighbor Events\n") { - bgp_debug_list_free(bgp_debug_neighbor_events_peers); - - if (vty->node == CONFIG_NODE) - DEBUG_OFF (neighbor_events, NEIGHBOR_EVENTS); - else - { - TERM_DEBUG_OFF (neighbor_events, NEIGHBOR_EVENTS); - vty_out (vty, "BGP neighbor-events debugging is off\n"); - } - return CMD_SUCCESS; + bgp_debug_list_free(bgp_debug_neighbor_events_peers); + + if (vty->node == CONFIG_NODE) + DEBUG_OFF(neighbor_events, NEIGHBOR_EVENTS); + else { + TERM_DEBUG_OFF(neighbor_events, NEIGHBOR_EVENTS); + vty_out(vty, "BGP neighbor-events debugging is off\n"); + } + return CMD_SUCCESS; } DEFUN (no_debug_bgp_neighbor_events_peer, @@ -736,30 +692,33 @@ DEFUN (no_debug_bgp_neighbor_events_peer, "BGP IPv6 neighbor to debug\n" "BGP neighbor on interface to debug\n") { - int idx_peer = 4; - int found_peer = 0; - const char *host = argv[idx_peer]->arg; - - if (bgp_debug_neighbor_events_peers && !list_isempty(bgp_debug_neighbor_events_peers)) - { - found_peer = bgp_debug_list_remove_entry(bgp_debug_neighbor_events_peers, host, NULL); - - if (list_isempty(bgp_debug_neighbor_events_peers)) - { - if (vty->node == CONFIG_NODE) - DEBUG_OFF (neighbor_events, NEIGHBOR_EVENTS); - else - TERM_DEBUG_OFF (neighbor_events, NEIGHBOR_EVENTS); - } - } - - if (found_peer) - vty_out (vty, "BGP neighbor-events debugging is off for %s\n", host); - else - vty_out (vty, "BGP neighbor-events debugging was not enabled for %s\n", - host); - - return CMD_SUCCESS; + int idx_peer = 4; + int found_peer = 0; + const char *host = argv[idx_peer]->arg; + + if (bgp_debug_neighbor_events_peers + && !list_isempty(bgp_debug_neighbor_events_peers)) { + found_peer = bgp_debug_list_remove_entry( + bgp_debug_neighbor_events_peers, host, NULL); + + if (list_isempty(bgp_debug_neighbor_events_peers)) { + if (vty->node == CONFIG_NODE) + DEBUG_OFF(neighbor_events, NEIGHBOR_EVENTS); + else + TERM_DEBUG_OFF(neighbor_events, + NEIGHBOR_EVENTS); + } + } + + if (found_peer) + vty_out(vty, "BGP neighbor-events debugging is off for %s\n", + host); + else + vty_out(vty, + "BGP neighbor-events debugging was not enabled for %s\n", + host); + + return CMD_SUCCESS; } /* debug bgp nht */ @@ -770,14 +729,13 @@ DEFUN (debug_bgp_nht, BGP_STR "BGP nexthop tracking events\n") { - if (vty->node == CONFIG_NODE) - DEBUG_ON (nht, NHT); - else - { - TERM_DEBUG_ON (nht, NHT); - vty_out (vty, "BGP nexthop tracking debugging is on\n"); - } - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + DEBUG_ON(nht, NHT); + else { + TERM_DEBUG_ON(nht, NHT); + vty_out(vty, "BGP nexthop tracking debugging is on\n"); + } + return CMD_SUCCESS; } DEFUN (no_debug_bgp_nht, @@ -788,14 +746,13 @@ DEFUN (no_debug_bgp_nht, BGP_STR "BGP nexthop tracking events\n") { - if (vty->node == CONFIG_NODE) - DEBUG_OFF (nht, NHT); - else - { - TERM_DEBUG_OFF (nht, NHT); - vty_out (vty, "BGP nexthop tracking debugging is off\n"); - } - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + DEBUG_OFF(nht, NHT); + else { + TERM_DEBUG_OFF(nht, NHT); + vty_out(vty, "BGP nexthop tracking debugging is off\n"); + } + return CMD_SUCCESS; } /* debug bgp keepalives */ @@ -806,16 +763,15 @@ DEFUN (debug_bgp_keepalive, BGP_STR "BGP keepalives\n") { - bgp_debug_list_free(bgp_debug_keepalive_peers); - - if (vty->node == CONFIG_NODE) - DEBUG_ON (keepalive, KEEPALIVE); - else - { - TERM_DEBUG_ON (keepalive, KEEPALIVE); - vty_out (vty, "BGP keepalives debugging is on\n"); - } - return CMD_SUCCESS; + bgp_debug_list_free(bgp_debug_keepalive_peers); + + if (vty->node == CONFIG_NODE) + DEBUG_ON(keepalive, KEEPALIVE); + else { + TERM_DEBUG_ON(keepalive, KEEPALIVE); + vty_out(vty, "BGP keepalives debugging is on\n"); + } + return CMD_SUCCESS; } DEFUN (debug_bgp_keepalive_peer, @@ -828,29 +784,28 @@ DEFUN (debug_bgp_keepalive_peer, "BGP IPv6 neighbor to debug\n" "BGP neighbor on interface to debug\n") { - int idx_peer = 3; - const char *host = argv[idx_peer]->arg; - - if (!bgp_debug_keepalive_peers) - bgp_debug_keepalive_peers = list_new (); - - if (bgp_debug_list_has_entry(bgp_debug_keepalive_peers, host, NULL)) - { - vty_out (vty, "BGP keepalive debugging is already enabled for %s\n", - host); - return CMD_SUCCESS; - } - - bgp_debug_list_add_entry(bgp_debug_keepalive_peers, host, NULL); - - if (vty->node == CONFIG_NODE) - DEBUG_ON (keepalive, KEEPALIVE); - else - { - TERM_DEBUG_ON (keepalive, KEEPALIVE); - vty_out (vty, "BGP keepalives debugging is on for %s\n", host); - } - return CMD_SUCCESS; + int idx_peer = 3; + const char *host = argv[idx_peer]->arg; + + if (!bgp_debug_keepalive_peers) + bgp_debug_keepalive_peers = list_new(); + + if (bgp_debug_list_has_entry(bgp_debug_keepalive_peers, host, NULL)) { + vty_out(vty, + "BGP keepalive debugging is already enabled for %s\n", + host); + return CMD_SUCCESS; + } + + bgp_debug_list_add_entry(bgp_debug_keepalive_peers, host, NULL); + + if (vty->node == CONFIG_NODE) + DEBUG_ON(keepalive, KEEPALIVE); + else { + TERM_DEBUG_ON(keepalive, KEEPALIVE); + vty_out(vty, "BGP keepalives debugging is on for %s\n", host); + } + return CMD_SUCCESS; } DEFUN (no_debug_bgp_keepalive, @@ -861,16 +816,15 @@ DEFUN (no_debug_bgp_keepalive, BGP_STR "BGP keepalives\n") { - bgp_debug_list_free(bgp_debug_keepalive_peers); - - if (vty->node == CONFIG_NODE) - DEBUG_OFF (keepalive, KEEPALIVE); - else - { - TERM_DEBUG_OFF (keepalive, KEEPALIVE); - vty_out (vty, "BGP keepalives debugging is off\n"); - } - return CMD_SUCCESS; + bgp_debug_list_free(bgp_debug_keepalive_peers); + + if (vty->node == CONFIG_NODE) + DEBUG_OFF(keepalive, KEEPALIVE); + else { + TERM_DEBUG_OFF(keepalive, KEEPALIVE); + vty_out(vty, "BGP keepalives debugging is off\n"); + } + return CMD_SUCCESS; } DEFUN (no_debug_bgp_keepalive_peer, @@ -884,29 +838,31 @@ DEFUN (no_debug_bgp_keepalive_peer, "BGP IPv6 neighbor to debug\n" "BGP neighbor on interface to debug\n") { - int idx_peer = 4; - int found_peer = 0; - const char *host = argv[idx_peer]->arg; - - if (bgp_debug_keepalive_peers && !list_isempty(bgp_debug_keepalive_peers)) - { - found_peer = bgp_debug_list_remove_entry(bgp_debug_keepalive_peers, host, NULL); - - if (list_isempty(bgp_debug_keepalive_peers)) - { - if (vty->node == CONFIG_NODE) - DEBUG_OFF (keepalive, KEEPALIVE); - else - TERM_DEBUG_OFF (keepalive, KEEPALIVE); - } - } - - if (found_peer) - vty_out (vty, "BGP keepalives debugging is off for %s\n", host); - else - vty_out (vty, "BGP keepalives debugging was not enabled for %s\n", host); - - return CMD_SUCCESS; + int idx_peer = 4; + int found_peer = 0; + const char *host = argv[idx_peer]->arg; + + if (bgp_debug_keepalive_peers + && !list_isempty(bgp_debug_keepalive_peers)) { + found_peer = bgp_debug_list_remove_entry( + bgp_debug_keepalive_peers, host, NULL); + + if (list_isempty(bgp_debug_keepalive_peers)) { + if (vty->node == CONFIG_NODE) + DEBUG_OFF(keepalive, KEEPALIVE); + else + TERM_DEBUG_OFF(keepalive, KEEPALIVE); + } + } + + if (found_peer) + vty_out(vty, "BGP keepalives debugging is off for %s\n", host); + else + vty_out(vty, + "BGP keepalives debugging was not enabled for %s\n", + host); + + return CMD_SUCCESS; } #ifndef VTYSH_EXTRACT_PL @@ -922,30 +878,29 @@ DEFPY (debug_bgp_bestpath_prefix, "BGP bestpath\n" "IPv4 prefix\n" "IPv6 prefix\n") - { - if (!bgp_debug_bestpath_prefixes) - bgp_debug_bestpath_prefixes = list_new (); - - if (bgp_debug_list_has_entry(bgp_debug_bestpath_prefixes, NULL, bestpath)) - { - vty_out (vty, "BGP bestpath debugging is already enabled for %s\n", bestpath_str); - return CMD_SUCCESS; - } - - bgp_debug_list_add_entry(bgp_debug_bestpath_prefixes, NULL, bestpath); - - if (vty->node == CONFIG_NODE) - { - DEBUG_ON (bestpath, BESTPATH); - } - else - { - TERM_DEBUG_ON (bestpath, BESTPATH); - vty_out (vty, "BGP bestpath debugging is on for %s\n", bestpath_str); - } - - return CMD_SUCCESS; + if (!bgp_debug_bestpath_prefixes) + bgp_debug_bestpath_prefixes = list_new(); + + if (bgp_debug_list_has_entry(bgp_debug_bestpath_prefixes, NULL, + bestpath)) { + vty_out(vty, + "BGP bestpath debugging is already enabled for %s\n", + bestpath_str); + return CMD_SUCCESS; + } + + bgp_debug_list_add_entry(bgp_debug_bestpath_prefixes, NULL, bestpath); + + if (vty->node == CONFIG_NODE) { + DEBUG_ON(bestpath, BESTPATH); + } else { + TERM_DEBUG_ON(bestpath, BESTPATH); + vty_out(vty, "BGP bestpath debugging is on for %s\n", + bestpath_str); + } + + return CMD_SUCCESS; } DEFUN (no_debug_bgp_bestpath_prefix, @@ -957,48 +912,44 @@ DEFUN (no_debug_bgp_bestpath_prefix, "BGP bestpath\n" "IPv4 prefix\n" "IPv6 prefix\n") - { - int idx_ipv4_ipv6_prefixlen = 4; - struct prefix *argv_p; - int found_prefix = 0; - int ret; - - argv_p = prefix_new(); - ret = str2prefix (argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); - if (!ret) - { - prefix_free(argv_p); - vty_out (vty, "%% Malformed Prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (bgp_debug_bestpath_prefixes && !list_isempty(bgp_debug_bestpath_prefixes)) - { - found_prefix = bgp_debug_list_remove_entry(bgp_debug_bestpath_prefixes, NULL, argv_p); - - if (list_isempty(bgp_debug_bestpath_prefixes)) - { - if (vty->node == CONFIG_NODE) - { - DEBUG_OFF (bestpath, BESTPATH); - } - else - { - TERM_DEBUG_OFF (bestpath, BESTPATH); - vty_out (vty, "BGP bestpath debugging (per prefix) is off\n"); - } - } - } - - if (found_prefix) - vty_out (vty, "BGP bestpath debugging is off for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); - else - vty_out (vty, "BGP bestpath debugging was not enabled for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); - - return CMD_SUCCESS; + int idx_ipv4_ipv6_prefixlen = 4; + struct prefix *argv_p; + int found_prefix = 0; + int ret; + + argv_p = prefix_new(); + ret = str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); + if (!ret) { + prefix_free(argv_p); + vty_out(vty, "%% Malformed Prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (bgp_debug_bestpath_prefixes + && !list_isempty(bgp_debug_bestpath_prefixes)) { + found_prefix = bgp_debug_list_remove_entry( + bgp_debug_bestpath_prefixes, NULL, argv_p); + + if (list_isempty(bgp_debug_bestpath_prefixes)) { + if (vty->node == CONFIG_NODE) { + DEBUG_OFF(bestpath, BESTPATH); + } else { + TERM_DEBUG_OFF(bestpath, BESTPATH); + vty_out(vty, + "BGP bestpath debugging (per prefix) is off\n"); + } + } + } + + if (found_prefix) + vty_out(vty, "BGP bestpath debugging is off for %s\n", + argv[idx_ipv4_ipv6_prefixlen]->arg); + else + vty_out(vty, "BGP bestpath debugging was not enabled for %s\n", + argv[idx_ipv4_ipv6_prefixlen]->arg); + + return CMD_SUCCESS; } DEFUN (no_debug_bgp_bestpath, @@ -1009,16 +960,15 @@ DEFUN (no_debug_bgp_bestpath, BGP_STR "BGP bestpath\n") { - bgp_debug_list_free(bgp_debug_bestpath_prefixes); - - if (vty->node == CONFIG_NODE) - DEBUG_OFF (bestpath, BESTPATH); - else - { - TERM_DEBUG_OFF (bestpath, BESTPATH); - vty_out (vty, "BGP bestpath debugging is off\n"); - } - return CMD_SUCCESS; + bgp_debug_list_free(bgp_debug_bestpath_prefixes); + + if (vty->node == CONFIG_NODE) + DEBUG_OFF(bestpath, BESTPATH); + else { + TERM_DEBUG_OFF(bestpath, BESTPATH); + vty_out(vty, "BGP bestpath debugging is off\n"); + } + return CMD_SUCCESS; } /* debug bgp updates */ @@ -1029,22 +979,19 @@ DEFUN (debug_bgp_update, BGP_STR "BGP updates\n") { - bgp_debug_list_free(bgp_debug_update_in_peers); - bgp_debug_list_free(bgp_debug_update_out_peers); - bgp_debug_list_free(bgp_debug_update_prefixes); - - if (vty->node == CONFIG_NODE) - { - DEBUG_ON (update, UPDATE_IN); - DEBUG_ON (update, UPDATE_OUT); - } - else - { - TERM_DEBUG_ON (update, UPDATE_IN); - TERM_DEBUG_ON (update, UPDATE_OUT); - vty_out (vty, "BGP updates debugging is on\n"); - } - return CMD_SUCCESS; + bgp_debug_list_free(bgp_debug_update_in_peers); + bgp_debug_list_free(bgp_debug_update_out_peers); + bgp_debug_list_free(bgp_debug_update_prefixes); + + if (vty->node == CONFIG_NODE) { + DEBUG_ON(update, UPDATE_IN); + DEBUG_ON(update, UPDATE_OUT); + } else { + TERM_DEBUG_ON(update, UPDATE_IN); + TERM_DEBUG_ON(update, UPDATE_OUT); + vty_out(vty, "BGP updates debugging is on\n"); + } + return CMD_SUCCESS; } DEFUN (debug_bgp_update_direct, @@ -1056,34 +1003,29 @@ DEFUN (debug_bgp_update_direct, "Inbound updates\n" "Outbound updates\n") { - int idx_in_out = 3; - - if (strncmp ("i", argv[idx_in_out]->arg, 1) == 0) - bgp_debug_list_free(bgp_debug_update_in_peers); - else - bgp_debug_list_free(bgp_debug_update_out_peers); - - if (vty->node == CONFIG_NODE) - { - if (strncmp ("i", argv[idx_in_out]->arg, 1) == 0) - DEBUG_ON (update, UPDATE_IN); - else - DEBUG_ON (update, UPDATE_OUT); - } - else - { - if (strncmp ("i", argv[idx_in_out]->arg, 1) == 0) - { - TERM_DEBUG_ON (update, UPDATE_IN); - vty_out (vty, "BGP updates debugging is on (inbound)\n"); - } - else - { - TERM_DEBUG_ON (update, UPDATE_OUT); - vty_out (vty, "BGP updates debugging is on (outbound)\n"); - } - } - return CMD_SUCCESS; + int idx_in_out = 3; + + if (strncmp("i", argv[idx_in_out]->arg, 1) == 0) + bgp_debug_list_free(bgp_debug_update_in_peers); + else + bgp_debug_list_free(bgp_debug_update_out_peers); + + if (vty->node == CONFIG_NODE) { + if (strncmp("i", argv[idx_in_out]->arg, 1) == 0) + DEBUG_ON(update, UPDATE_IN); + else + DEBUG_ON(update, UPDATE_OUT); + } else { + if (strncmp("i", argv[idx_in_out]->arg, 1) == 0) { + TERM_DEBUG_ON(update, UPDATE_IN); + vty_out(vty, "BGP updates debugging is on (inbound)\n"); + } else { + TERM_DEBUG_ON(update, UPDATE_OUT); + vty_out(vty, + "BGP updates debugging is on (outbound)\n"); + } + } + return CMD_SUCCESS; } DEFUN (debug_bgp_update_direct_peer, @@ -1098,92 +1040,87 @@ DEFUN (debug_bgp_update_direct_peer, "BGP IPv6 neighbor to debug\n" "BGP neighbor on interface to debug\n") { - int idx_in_out = 3; - int idx_peer = 4; - const char *host = argv[idx_peer]->arg; - int inbound; - - if (!bgp_debug_update_in_peers) - bgp_debug_update_in_peers = list_new (); - - if (!bgp_debug_update_out_peers) - bgp_debug_update_out_peers = list_new (); - - if (strncmp ("i", argv[idx_in_out]->arg, 1) == 0) - inbound = 1; - else - inbound = 0; - - if (inbound) - { - if (bgp_debug_list_has_entry(bgp_debug_update_in_peers, host, NULL)) - { - vty_out (vty, "BGP inbound update debugging is already enabled for %s\n", - host); - return CMD_SUCCESS; - } - } - - else - { - if (bgp_debug_list_has_entry(bgp_debug_update_out_peers, host, NULL)) - { - vty_out (vty, "BGP outbound update debugging is already enabled for %s\n", - host); - return CMD_SUCCESS; - } - } - - if (inbound) - bgp_debug_list_add_entry(bgp_debug_update_in_peers, host, NULL); - else - { - struct peer *peer; - struct peer_af *paf; - int afidx; - - bgp_debug_list_add_entry(bgp_debug_update_out_peers, host, NULL); - peer = bgp_find_peer (vty, host); - - if (peer) - { - for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) - { - paf = peer->peer_af_array[afidx]; - if (paf != NULL) - { - if (PAF_SUBGRP (paf)) - { - UPDGRP_PEER_DBG_EN(PAF_SUBGRP(paf)->update_group); - } - } - } - } - } - - if (vty->node == CONFIG_NODE) - { - if (inbound) - DEBUG_ON (update, UPDATE_IN); - else - DEBUG_ON (update, UPDATE_OUT); - } - else - { - if (inbound) - { - TERM_DEBUG_ON (update, UPDATE_IN); - vty_out (vty, "BGP updates debugging is on (inbound) for %s\n", - argv[idx_peer]->arg); - } - else - { - TERM_DEBUG_ON (update, UPDATE_OUT); - vty_out (vty, "BGP updates debugging is on (outbound) for %s\n", - argv[idx_peer]->arg); - } - } - return CMD_SUCCESS; + int idx_in_out = 3; + int idx_peer = 4; + const char *host = argv[idx_peer]->arg; + int inbound; + + if (!bgp_debug_update_in_peers) + bgp_debug_update_in_peers = list_new(); + + if (!bgp_debug_update_out_peers) + bgp_debug_update_out_peers = list_new(); + + if (strncmp("i", argv[idx_in_out]->arg, 1) == 0) + inbound = 1; + else + inbound = 0; + + if (inbound) { + if (bgp_debug_list_has_entry(bgp_debug_update_in_peers, host, + NULL)) { + vty_out(vty, + "BGP inbound update debugging is already enabled for %s\n", + host); + return CMD_SUCCESS; + } + } + + else { + if (bgp_debug_list_has_entry(bgp_debug_update_out_peers, host, + NULL)) { + vty_out(vty, + "BGP outbound update debugging is already enabled for %s\n", + host); + return CMD_SUCCESS; + } + } + + if (inbound) + bgp_debug_list_add_entry(bgp_debug_update_in_peers, host, NULL); + else { + struct peer *peer; + struct peer_af *paf; + int afidx; + + bgp_debug_list_add_entry(bgp_debug_update_out_peers, host, + NULL); + peer = bgp_find_peer(vty, host); + + if (peer) { + for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; + afidx++) { + paf = peer->peer_af_array[afidx]; + if (paf != NULL) { + if (PAF_SUBGRP(paf)) { + UPDGRP_PEER_DBG_EN( + PAF_SUBGRP(paf) + ->update_group); + } + } + } + } + } + + if (vty->node == CONFIG_NODE) { + if (inbound) + DEBUG_ON(update, UPDATE_IN); + else + DEBUG_ON(update, UPDATE_OUT); + } else { + if (inbound) { + TERM_DEBUG_ON(update, UPDATE_IN); + vty_out(vty, + "BGP updates debugging is on (inbound) for %s\n", + argv[idx_peer]->arg); + } else { + TERM_DEBUG_ON(update, UPDATE_OUT); + vty_out(vty, + "BGP updates debugging is on (outbound) for %s\n", + argv[idx_peer]->arg); + } + } + return CMD_SUCCESS; } DEFUN (no_debug_bgp_update_direct, @@ -1196,37 +1133,30 @@ DEFUN (no_debug_bgp_update_direct, "Inbound updates\n" "Outbound updates\n") { - int idx_in_out = 4; - if (strncmp ("i", argv[idx_in_out]->arg, 1) == 0) - { - bgp_debug_list_free(bgp_debug_update_in_peers); - - if (vty->node == CONFIG_NODE) - { - DEBUG_OFF (update, UPDATE_IN); - } - else - { - TERM_DEBUG_OFF (update, UPDATE_IN); - vty_out (vty, "BGP updates debugging is off (inbound)\n"); - } - } - else - { - bgp_debug_list_free(bgp_debug_update_out_peers); - - if (vty->node == CONFIG_NODE) - { - DEBUG_OFF (update, UPDATE_OUT); - } - else - { - TERM_DEBUG_OFF (update, UPDATE_OUT); - vty_out (vty, "BGP updates debugging is off (outbound)\n"); - } - } - - return CMD_SUCCESS; + int idx_in_out = 4; + if (strncmp("i", argv[idx_in_out]->arg, 1) == 0) { + bgp_debug_list_free(bgp_debug_update_in_peers); + + if (vty->node == CONFIG_NODE) { + DEBUG_OFF(update, UPDATE_IN); + } else { + TERM_DEBUG_OFF(update, UPDATE_IN); + vty_out(vty, + "BGP updates debugging is off (inbound)\n"); + } + } else { + bgp_debug_list_free(bgp_debug_update_out_peers); + + if (vty->node == CONFIG_NODE) { + DEBUG_OFF(update, UPDATE_OUT); + } else { + TERM_DEBUG_OFF(update, UPDATE_OUT); + vty_out(vty, + "BGP updates debugging is off (outbound)\n"); + } + } + + return CMD_SUCCESS; } DEFUN (no_debug_bgp_update_direct_peer, @@ -1242,86 +1172,87 @@ DEFUN (no_debug_bgp_update_direct_peer, "BGP IPv6 neighbor to debug\n" "BGP neighbor on interface to debug\n") { - int idx_in_out = 4; - int idx_peer = 5; - int inbound; - int found_peer = 0; - const char *host = argv[idx_peer]->arg; - - if (strncmp ("i", argv[idx_in_out]->arg, 1) == 0) - inbound = 1; - else - inbound = 0; - - if (inbound && bgp_debug_update_in_peers && - !list_isempty(bgp_debug_update_in_peers)) - { - found_peer = bgp_debug_list_remove_entry(bgp_debug_update_in_peers, host, NULL); - - if (list_isempty(bgp_debug_update_in_peers)) - { - if (vty->node == CONFIG_NODE) - DEBUG_OFF (update, UPDATE_IN); - else - { - TERM_DEBUG_OFF (update, UPDATE_IN); - vty_out (vty, "BGP updates debugging (inbound) is off\n"); - } - } - } - - if (!inbound && bgp_debug_update_out_peers && - !list_isempty(bgp_debug_update_out_peers)) - { - found_peer = bgp_debug_list_remove_entry(bgp_debug_update_out_peers, host, NULL); - - if (list_isempty(bgp_debug_update_out_peers)) - { - if (vty->node == CONFIG_NODE) - DEBUG_OFF (update, UPDATE_OUT); - else - { - TERM_DEBUG_OFF (update, UPDATE_OUT); - vty_out (vty, "BGP updates debugging (outbound) is off\n"); - } - } - - struct peer *peer; - struct peer_af *paf; - int afidx; - peer = bgp_find_peer (vty, host); - - if (peer) - { - for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) - { - paf = peer->peer_af_array[afidx]; - if (paf != NULL) - { - if (PAF_SUBGRP (paf)) - { - UPDGRP_PEER_DBG_DIS(PAF_SUBGRP(paf)->update_group); - } - } - } - } - } - - if (found_peer) - if (inbound) - vty_out (vty, "BGP updates debugging (inbound) is off for %s\n", host); - else - vty_out (vty, "BGP updates debugging (outbound) is off for %s\n", - host); - else - if (inbound) - vty_out (vty, "BGP updates debugging (inbound) was not enabled for %s\n", - host); - else - vty_out (vty, "BGP updates debugging (outbound) was not enabled for %s\n", - host); - - return CMD_SUCCESS; + int idx_in_out = 4; + int idx_peer = 5; + int inbound; + int found_peer = 0; + const char *host = argv[idx_peer]->arg; + + if (strncmp("i", argv[idx_in_out]->arg, 1) == 0) + inbound = 1; + else + inbound = 0; + + if (inbound && bgp_debug_update_in_peers + && !list_isempty(bgp_debug_update_in_peers)) { + found_peer = bgp_debug_list_remove_entry( + bgp_debug_update_in_peers, host, NULL); + + if (list_isempty(bgp_debug_update_in_peers)) { + if (vty->node == CONFIG_NODE) + DEBUG_OFF(update, UPDATE_IN); + else { + TERM_DEBUG_OFF(update, UPDATE_IN); + vty_out(vty, + "BGP updates debugging (inbound) is off\n"); + } + } + } + + if (!inbound && bgp_debug_update_out_peers + && !list_isempty(bgp_debug_update_out_peers)) { + found_peer = bgp_debug_list_remove_entry( + bgp_debug_update_out_peers, host, NULL); + + if (list_isempty(bgp_debug_update_out_peers)) { + if (vty->node == CONFIG_NODE) + DEBUG_OFF(update, UPDATE_OUT); + else { + TERM_DEBUG_OFF(update, UPDATE_OUT); + vty_out(vty, + "BGP updates debugging (outbound) is off\n"); + } + } + + struct peer *peer; + struct peer_af *paf; + int afidx; + peer = bgp_find_peer(vty, host); + + if (peer) { + for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; + afidx++) { + paf = peer->peer_af_array[afidx]; + if (paf != NULL) { + if (PAF_SUBGRP(paf)) { + UPDGRP_PEER_DBG_DIS( + PAF_SUBGRP(paf) + ->update_group); + } + } + } + } + } + + if (found_peer) + if (inbound) + vty_out(vty, + "BGP updates debugging (inbound) is off for %s\n", + host); + else + vty_out(vty, + "BGP updates debugging (outbound) is off for %s\n", + host); + else if (inbound) + vty_out(vty, + "BGP updates debugging (inbound) was not enabled for %s\n", + host); + else + vty_out(vty, + "BGP updates debugging (outbound) was not enabled for %s\n", + host); + + return CMD_SUCCESS; } DEFUN (debug_bgp_update_prefix, @@ -1333,46 +1264,41 @@ DEFUN (debug_bgp_update_prefix, "Specify a prefix to debug\n" "IPv4 prefix\n" "IPv6 prefix\n") - { - int idx_ipv4_ipv6_prefixlen = 4; - struct prefix *argv_p; - int ret; - - argv_p = prefix_new(); - ret = str2prefix (argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); - if (!ret) - { - prefix_free(argv_p); - vty_out (vty, "%% Malformed Prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - - if (!bgp_debug_update_prefixes) - bgp_debug_update_prefixes = list_new (); - - if (bgp_debug_list_has_entry(bgp_debug_update_prefixes, NULL, argv_p)) - { - vty_out (vty, "BGP updates debugging is already enabled for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); - return CMD_SUCCESS; - } - - bgp_debug_list_add_entry(bgp_debug_update_prefixes, NULL, argv_p); - - if (vty->node == CONFIG_NODE) - { - DEBUG_ON (update, UPDATE_PREFIX); - } - else - { - TERM_DEBUG_ON (update, UPDATE_PREFIX); - vty_out (vty, "BGP updates debugging is on for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); - } - - return CMD_SUCCESS; + int idx_ipv4_ipv6_prefixlen = 4; + struct prefix *argv_p; + int ret; + + argv_p = prefix_new(); + ret = str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); + if (!ret) { + prefix_free(argv_p); + vty_out(vty, "%% Malformed Prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + + if (!bgp_debug_update_prefixes) + bgp_debug_update_prefixes = list_new(); + + if (bgp_debug_list_has_entry(bgp_debug_update_prefixes, NULL, argv_p)) { + vty_out(vty, + "BGP updates debugging is already enabled for %s\n", + argv[idx_ipv4_ipv6_prefixlen]->arg); + return CMD_SUCCESS; + } + + bgp_debug_list_add_entry(bgp_debug_update_prefixes, NULL, argv_p); + + if (vty->node == CONFIG_NODE) { + DEBUG_ON(update, UPDATE_PREFIX); + } else { + TERM_DEBUG_ON(update, UPDATE_PREFIX); + vty_out(vty, "BGP updates debugging is on for %s\n", + argv[idx_ipv4_ipv6_prefixlen]->arg); + } + + return CMD_SUCCESS; } DEFUN (no_debug_bgp_update_prefix, @@ -1385,48 +1311,44 @@ DEFUN (no_debug_bgp_update_prefix, "Specify a prefix to debug\n" "IPv4 prefix\n" "IPv6 prefix\n") - { - int idx_ipv4_ipv6_prefixlen = 5; - struct prefix *argv_p; - int found_prefix = 0; - int ret; - - argv_p = prefix_new(); - ret = str2prefix (argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); - if (!ret) - { - prefix_free(argv_p); - vty_out (vty, "%% Malformed Prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (bgp_debug_update_prefixes && !list_isempty(bgp_debug_update_prefixes)) - { - found_prefix = bgp_debug_list_remove_entry(bgp_debug_update_prefixes, NULL, argv_p); - - if (list_isempty(bgp_debug_update_prefixes)) - { - if (vty->node == CONFIG_NODE) - { - DEBUG_OFF (update, UPDATE_PREFIX); - } - else - { - TERM_DEBUG_OFF (update, UPDATE_PREFIX); - vty_out (vty, "BGP updates debugging (per prefix) is off\n"); - } - } - } - - if (found_prefix) - vty_out (vty, "BGP updates debugging is off for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); - else - vty_out (vty, "BGP updates debugging was not enabled for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); - - return CMD_SUCCESS; + int idx_ipv4_ipv6_prefixlen = 5; + struct prefix *argv_p; + int found_prefix = 0; + int ret; + + argv_p = prefix_new(); + ret = str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); + if (!ret) { + prefix_free(argv_p); + vty_out(vty, "%% Malformed Prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (bgp_debug_update_prefixes + && !list_isempty(bgp_debug_update_prefixes)) { + found_prefix = bgp_debug_list_remove_entry( + bgp_debug_update_prefixes, NULL, argv_p); + + if (list_isempty(bgp_debug_update_prefixes)) { + if (vty->node == CONFIG_NODE) { + DEBUG_OFF(update, UPDATE_PREFIX); + } else { + TERM_DEBUG_OFF(update, UPDATE_PREFIX); + vty_out(vty, + "BGP updates debugging (per prefix) is off\n"); + } + } + } + + if (found_prefix) + vty_out(vty, "BGP updates debugging is off for %s\n", + argv[idx_ipv4_ipv6_prefixlen]->arg); + else + vty_out(vty, "BGP updates debugging was not enabled for %s\n", + argv[idx_ipv4_ipv6_prefixlen]->arg); + + return CMD_SUCCESS; } DEFUN (no_debug_bgp_update, @@ -1437,27 +1359,24 @@ DEFUN (no_debug_bgp_update, BGP_STR "BGP updates\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_debug_list_free(bgp_debug_update_in_peers); - bgp_debug_list_free(bgp_debug_update_out_peers); - bgp_debug_list_free(bgp_debug_update_prefixes); - - bgp_debug_clear_updgrp_update_dbg(bgp); - - if (vty->node == CONFIG_NODE) - { - DEBUG_OFF (update, UPDATE_IN); - DEBUG_OFF (update, UPDATE_OUT); - DEBUG_OFF (update, UPDATE_PREFIX); - } - else - { - TERM_DEBUG_OFF (update, UPDATE_IN); - TERM_DEBUG_OFF (update, UPDATE_OUT); - TERM_DEBUG_OFF (update, UPDATE_PREFIX); - vty_out (vty, "BGP updates debugging is off\n"); - } - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_debug_list_free(bgp_debug_update_in_peers); + bgp_debug_list_free(bgp_debug_update_out_peers); + bgp_debug_list_free(bgp_debug_update_prefixes); + + bgp_debug_clear_updgrp_update_dbg(bgp); + + if (vty->node == CONFIG_NODE) { + DEBUG_OFF(update, UPDATE_IN); + DEBUG_OFF(update, UPDATE_OUT); + DEBUG_OFF(update, UPDATE_PREFIX); + } else { + TERM_DEBUG_OFF(update, UPDATE_IN); + TERM_DEBUG_OFF(update, UPDATE_OUT); + TERM_DEBUG_OFF(update, UPDATE_PREFIX); + vty_out(vty, "BGP updates debugging is off\n"); + } + return CMD_SUCCESS; } /* debug bgp zebra */ @@ -1468,14 +1387,13 @@ DEFUN (debug_bgp_zebra, BGP_STR "BGP Zebra messages\n") { - if (vty->node == CONFIG_NODE) - DEBUG_ON (zebra, ZEBRA); - else - { - TERM_DEBUG_ON (zebra, ZEBRA); - vty_out (vty, "BGP zebra debugging is on\n"); - } - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + DEBUG_ON(zebra, ZEBRA); + else { + TERM_DEBUG_ON(zebra, ZEBRA); + vty_out(vty, "BGP zebra debugging is on\n"); + } + return CMD_SUCCESS; } DEFUN (debug_bgp_zebra_prefix, @@ -1487,43 +1405,39 @@ DEFUN (debug_bgp_zebra_prefix, "Specify a prefix to debug\n" "IPv4 prefix\n" "IPv6 prefix\n") - { - int idx_ipv4_ipv6_prefixlen = 4; - struct prefix *argv_p; - int ret; - - argv_p = prefix_new(); - ret = str2prefix (argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); - if (!ret) - { - prefix_free(argv_p); - vty_out (vty, "%% Malformed Prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (!bgp_debug_zebra_prefixes) - bgp_debug_zebra_prefixes = list_new(); - - if (bgp_debug_list_has_entry(bgp_debug_zebra_prefixes, NULL, argv_p)) - { - vty_out (vty, "BGP zebra debugging is already enabled for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); - return CMD_SUCCESS; - } - - bgp_debug_list_add_entry(bgp_debug_zebra_prefixes, NULL, argv_p); - - if (vty->node == CONFIG_NODE) - DEBUG_ON (zebra, ZEBRA); - else - { - TERM_DEBUG_ON (zebra, ZEBRA); - vty_out (vty, "BGP zebra debugging is on for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); - } - - return CMD_SUCCESS; + int idx_ipv4_ipv6_prefixlen = 4; + struct prefix *argv_p; + int ret; + + argv_p = prefix_new(); + ret = str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); + if (!ret) { + prefix_free(argv_p); + vty_out(vty, "%% Malformed Prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (!bgp_debug_zebra_prefixes) + bgp_debug_zebra_prefixes = list_new(); + + if (bgp_debug_list_has_entry(bgp_debug_zebra_prefixes, NULL, argv_p)) { + vty_out(vty, "BGP zebra debugging is already enabled for %s\n", + argv[idx_ipv4_ipv6_prefixlen]->arg); + return CMD_SUCCESS; + } + + bgp_debug_list_add_entry(bgp_debug_zebra_prefixes, NULL, argv_p); + + if (vty->node == CONFIG_NODE) + DEBUG_ON(zebra, ZEBRA); + else { + TERM_DEBUG_ON(zebra, ZEBRA); + vty_out(vty, "BGP zebra debugging is on for %s\n", + argv[idx_ipv4_ipv6_prefixlen]->arg); + } + + return CMD_SUCCESS; } DEFUN (no_debug_bgp_zebra, @@ -1534,16 +1448,15 @@ DEFUN (no_debug_bgp_zebra, BGP_STR "BGP Zebra messages\n") { - bgp_debug_list_free(bgp_debug_zebra_prefixes); - - if (vty->node == CONFIG_NODE) - DEBUG_OFF (zebra, ZEBRA); - else - { - TERM_DEBUG_OFF (zebra, ZEBRA); - vty_out (vty, "BGP zebra debugging is off\n"); - } - return CMD_SUCCESS; + bgp_debug_list_free(bgp_debug_zebra_prefixes); + + if (vty->node == CONFIG_NODE) + DEBUG_OFF(zebra, ZEBRA); + else { + TERM_DEBUG_OFF(zebra, ZEBRA); + vty_out(vty, "BGP zebra debugging is off\n"); + } + return CMD_SUCCESS; } DEFUN (no_debug_bgp_zebra_prefix, @@ -1556,46 +1469,43 @@ DEFUN (no_debug_bgp_zebra_prefix, "Specify a prefix to debug\n" "IPv4 prefix\n" "IPv6 prefix\n") - { - int idx_ipv4_ipv6_prefixlen = 5; - struct prefix *argv_p; - int found_prefix = 0; - int ret; - - argv_p = prefix_new(); - ret = str2prefix (argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); - if (!ret) - { - prefix_free(argv_p); - vty_out (vty, "%% Malformed Prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (bgp_debug_zebra_prefixes && !list_isempty(bgp_debug_zebra_prefixes)) - { - found_prefix = bgp_debug_list_remove_entry(bgp_debug_zebra_prefixes, NULL, argv_p); - - if (list_isempty(bgp_debug_zebra_prefixes)) - { - if (vty->node == CONFIG_NODE) - DEBUG_OFF (zebra, ZEBRA); - else - { - TERM_DEBUG_OFF (zebra, ZEBRA); - vty_out (vty, "BGP zebra debugging is off\n"); - } - } - } - - if (found_prefix) - vty_out (vty, "BGP zebra debugging is off for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); - else - vty_out (vty, "BGP zebra debugging was not enabled for %s\n", - argv[idx_ipv4_ipv6_prefixlen]->arg); - - return CMD_SUCCESS; + int idx_ipv4_ipv6_prefixlen = 5; + struct prefix *argv_p; + int found_prefix = 0; + int ret; + + argv_p = prefix_new(); + ret = str2prefix(argv[idx_ipv4_ipv6_prefixlen]->arg, argv_p); + if (!ret) { + prefix_free(argv_p); + vty_out(vty, "%% Malformed Prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (bgp_debug_zebra_prefixes + && !list_isempty(bgp_debug_zebra_prefixes)) { + found_prefix = bgp_debug_list_remove_entry( + bgp_debug_zebra_prefixes, NULL, argv_p); + + if (list_isempty(bgp_debug_zebra_prefixes)) { + if (vty->node == CONFIG_NODE) + DEBUG_OFF(zebra, ZEBRA); + else { + TERM_DEBUG_OFF(zebra, ZEBRA); + vty_out(vty, "BGP zebra debugging is off\n"); + } + } + } + + if (found_prefix) + vty_out(vty, "BGP zebra debugging is off for %s\n", + argv[idx_ipv4_ipv6_prefixlen]->arg); + else + vty_out(vty, "BGP zebra debugging was not enabled for %s\n", + argv[idx_ipv4_ipv6_prefixlen]->arg); + + return CMD_SUCCESS; } DEFUN (debug_bgp_allow_martians, @@ -1605,14 +1515,13 @@ DEFUN (debug_bgp_allow_martians, BGP_STR "BGP allow martian next hops\n") { - if (vty->node == CONFIG_NODE) - DEBUG_ON (allow_martians, ALLOW_MARTIANS); - else - { - TERM_DEBUG_ON (allow_martians, ALLOW_MARTIANS); - vty_out (vty, "BGP allow_martian next hop debugging is on\n"); - } - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + DEBUG_ON(allow_martians, ALLOW_MARTIANS); + else { + TERM_DEBUG_ON(allow_martians, ALLOW_MARTIANS); + vty_out(vty, "BGP allow_martian next hop debugging is on\n"); + } + return CMD_SUCCESS; } DEFUN (no_debug_bgp_allow_martians, @@ -1623,14 +1532,13 @@ DEFUN (no_debug_bgp_allow_martians, BGP_STR "BGP allow martian next hops\n") { - if (vty->node == CONFIG_NODE) - DEBUG_OFF (allow_martians, ALLOW_MARTIANS); - else - { - TERM_DEBUG_OFF (allow_martians, ALLOW_MARTIANS); - vty_out (vty, "BGP allow martian next hop debugging is off\n"); - } - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + DEBUG_OFF(allow_martians, ALLOW_MARTIANS); + else { + TERM_DEBUG_OFF(allow_martians, ALLOW_MARTIANS); + vty_out(vty, "BGP allow martian next hop debugging is off\n"); + } + return CMD_SUCCESS; } @@ -1642,14 +1550,13 @@ DEFUN (debug_bgp_update_groups, BGP_STR "BGP update-groups\n") { - if (vty->node == CONFIG_NODE) - DEBUG_ON (update_groups, UPDATE_GROUPS); - else - { - TERM_DEBUG_ON (update_groups, UPDATE_GROUPS); - vty_out (vty, "BGP update-groups debugging is on\n"); - } - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + DEBUG_ON(update_groups, UPDATE_GROUPS); + else { + TERM_DEBUG_ON(update_groups, UPDATE_GROUPS); + vty_out(vty, "BGP update-groups debugging is on\n"); + } + return CMD_SUCCESS; } DEFUN (no_debug_bgp_update_groups, @@ -1660,14 +1567,13 @@ DEFUN (no_debug_bgp_update_groups, BGP_STR "BGP update-groups\n") { - if (vty->node == CONFIG_NODE) - DEBUG_OFF (update_groups, UPDATE_GROUPS); - else - { - TERM_DEBUG_OFF (update_groups, UPDATE_GROUPS); - vty_out (vty, "BGP update-groups debugging is off\n"); - } - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + DEBUG_OFF(update_groups, UPDATE_GROUPS); + else { + TERM_DEBUG_OFF(update_groups, UPDATE_GROUPS); + vty_out(vty, "BGP update-groups debugging is off\n"); + } + return CMD_SUCCESS; } DEFUN (no_debug_bgp, @@ -1677,30 +1583,30 @@ DEFUN (no_debug_bgp, DEBUG_STR BGP_STR) { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_debug_list_free(bgp_debug_neighbor_events_peers); - bgp_debug_list_free(bgp_debug_keepalive_peers); - bgp_debug_list_free(bgp_debug_update_in_peers); - bgp_debug_list_free(bgp_debug_update_out_peers); - bgp_debug_list_free(bgp_debug_update_prefixes); - bgp_debug_list_free(bgp_debug_bestpath_prefixes); - bgp_debug_list_free(bgp_debug_zebra_prefixes); - - bgp_debug_clear_updgrp_update_dbg(bgp); - - TERM_DEBUG_OFF (keepalive, KEEPALIVE); - TERM_DEBUG_OFF (update, UPDATE_IN); - TERM_DEBUG_OFF (update, UPDATE_OUT); - TERM_DEBUG_OFF (update, UPDATE_PREFIX); - TERM_DEBUG_OFF (bestpath, BESTPATH); - TERM_DEBUG_OFF (as4, AS4); - TERM_DEBUG_OFF (as4, AS4_SEGMENT); - TERM_DEBUG_OFF (neighbor_events, NEIGHBOR_EVENTS); - TERM_DEBUG_OFF (zebra, ZEBRA); - TERM_DEBUG_OFF (allow_martians, ALLOW_MARTIANS); - vty_out (vty, "All possible debugging has been turned off\n"); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_debug_list_free(bgp_debug_neighbor_events_peers); + bgp_debug_list_free(bgp_debug_keepalive_peers); + bgp_debug_list_free(bgp_debug_update_in_peers); + bgp_debug_list_free(bgp_debug_update_out_peers); + bgp_debug_list_free(bgp_debug_update_prefixes); + bgp_debug_list_free(bgp_debug_bestpath_prefixes); + bgp_debug_list_free(bgp_debug_zebra_prefixes); + + bgp_debug_clear_updgrp_update_dbg(bgp); + + TERM_DEBUG_OFF(keepalive, KEEPALIVE); + TERM_DEBUG_OFF(update, UPDATE_IN); + TERM_DEBUG_OFF(update, UPDATE_OUT); + TERM_DEBUG_OFF(update, UPDATE_PREFIX); + TERM_DEBUG_OFF(bestpath, BESTPATH); + TERM_DEBUG_OFF(as4, AS4); + TERM_DEBUG_OFF(as4, AS4_SEGMENT); + TERM_DEBUG_OFF(neighbor_events, NEIGHBOR_EVENTS); + TERM_DEBUG_OFF(zebra, ZEBRA); + TERM_DEBUG_OFF(allow_martians, ALLOW_MARTIANS); + vty_out(vty, "All possible debugging has been turned off\n"); + + return CMD_SUCCESS; } DEFUN (show_debugging_bgp, @@ -1710,486 +1616,462 @@ DEFUN (show_debugging_bgp, DEBUG_STR BGP_STR) { - vty_out (vty, "BGP debugging status:\n"); + vty_out(vty, "BGP debugging status:\n"); - if (BGP_DEBUG (as4, AS4)) - vty_out (vty, " BGP as4 debugging is on\n"); + if (BGP_DEBUG(as4, AS4)) + vty_out(vty, " BGP as4 debugging is on\n"); - if (BGP_DEBUG (as4, AS4_SEGMENT)) - vty_out (vty, " BGP as4 aspath segment debugging is on\n"); + if (BGP_DEBUG(as4, AS4_SEGMENT)) + vty_out(vty, " BGP as4 aspath segment debugging is on\n"); - if (BGP_DEBUG (bestpath, BESTPATH)) - bgp_debug_list_print (vty, " BGP bestpath debugging is on", - bgp_debug_bestpath_prefixes); + if (BGP_DEBUG(bestpath, BESTPATH)) + bgp_debug_list_print(vty, " BGP bestpath debugging is on", + bgp_debug_bestpath_prefixes); - if (BGP_DEBUG (keepalive, KEEPALIVE)) - bgp_debug_list_print (vty, " BGP keepalives debugging is on", - bgp_debug_keepalive_peers); + if (BGP_DEBUG(keepalive, KEEPALIVE)) + bgp_debug_list_print(vty, " BGP keepalives debugging is on", + bgp_debug_keepalive_peers); - if (BGP_DEBUG (neighbor_events, NEIGHBOR_EVENTS)) - bgp_debug_list_print (vty, " BGP neighbor-events debugging is on", - bgp_debug_neighbor_events_peers); + if (BGP_DEBUG(neighbor_events, NEIGHBOR_EVENTS)) + bgp_debug_list_print(vty, + " BGP neighbor-events debugging is on", + bgp_debug_neighbor_events_peers); - if (BGP_DEBUG (nht, NHT)) - vty_out (vty, " BGP next-hop tracking debugging is on\n"); + if (BGP_DEBUG(nht, NHT)) + vty_out(vty, " BGP next-hop tracking debugging is on\n"); - if (BGP_DEBUG (update_groups, UPDATE_GROUPS)) - vty_out (vty, " BGP update-groups debugging is on\n"); + if (BGP_DEBUG(update_groups, UPDATE_GROUPS)) + vty_out(vty, " BGP update-groups debugging is on\n"); - if (BGP_DEBUG (update, UPDATE_PREFIX)) - bgp_debug_list_print (vty, " BGP updates debugging is on", - bgp_debug_update_prefixes); + if (BGP_DEBUG(update, UPDATE_PREFIX)) + bgp_debug_list_print(vty, " BGP updates debugging is on", + bgp_debug_update_prefixes); - if (BGP_DEBUG (update, UPDATE_IN)) - bgp_debug_list_print (vty, " BGP updates debugging is on (inbound)", - bgp_debug_update_in_peers); + if (BGP_DEBUG(update, UPDATE_IN)) + bgp_debug_list_print(vty, + " BGP updates debugging is on (inbound)", + bgp_debug_update_in_peers); - if (BGP_DEBUG (update, UPDATE_OUT)) - bgp_debug_list_print (vty, " BGP updates debugging is on (outbound)", - bgp_debug_update_out_peers); + if (BGP_DEBUG(update, UPDATE_OUT)) + bgp_debug_list_print(vty, + " BGP updates debugging is on (outbound)", + bgp_debug_update_out_peers); - if (BGP_DEBUG (zebra, ZEBRA)) - bgp_debug_list_print (vty, " BGP zebra debugging is on", - bgp_debug_zebra_prefixes); + if (BGP_DEBUG(zebra, ZEBRA)) + bgp_debug_list_print(vty, " BGP zebra debugging is on", + bgp_debug_zebra_prefixes); - if (BGP_DEBUG (allow_martians, ALLOW_MARTIANS)) - vty_out (vty, " BGP allow martian next hop debugging is on\n"); - vty_out (vty, "\n"); - return CMD_SUCCESS; + if (BGP_DEBUG(allow_martians, ALLOW_MARTIANS)) + vty_out(vty, " BGP allow martian next hop debugging is on\n"); + vty_out(vty, "\n"); + return CMD_SUCCESS; } /* return count of number of debug flags set */ -int -bgp_debug_count(void) +int bgp_debug_count(void) { - int ret = 0; - if (BGP_DEBUG (as4, AS4)) - ret++; + int ret = 0; + if (BGP_DEBUG(as4, AS4)) + ret++; - if (BGP_DEBUG (as4, AS4_SEGMENT)) - ret++; + if (BGP_DEBUG(as4, AS4_SEGMENT)) + ret++; - if (BGP_DEBUG (bestpath, BESTPATH)) - ret++; + if (BGP_DEBUG(bestpath, BESTPATH)) + ret++; - if (BGP_DEBUG (keepalive, KEEPALIVE)) - ret++; + if (BGP_DEBUG(keepalive, KEEPALIVE)) + ret++; - if (BGP_DEBUG (neighbor_events, NEIGHBOR_EVENTS)) - ret++; + if (BGP_DEBUG(neighbor_events, NEIGHBOR_EVENTS)) + ret++; - if (BGP_DEBUG (nht, NHT)) - ret++; + if (BGP_DEBUG(nht, NHT)) + ret++; - if (BGP_DEBUG (update_groups, UPDATE_GROUPS)) - ret++; + if (BGP_DEBUG(update_groups, UPDATE_GROUPS)) + ret++; - if (BGP_DEBUG (update, UPDATE_PREFIX)) - ret++; + if (BGP_DEBUG(update, UPDATE_PREFIX)) + ret++; - if (BGP_DEBUG (update, UPDATE_IN)) - ret++; + if (BGP_DEBUG(update, UPDATE_IN)) + ret++; - if (BGP_DEBUG (update, UPDATE_OUT)) - ret++; + if (BGP_DEBUG(update, UPDATE_OUT)) + ret++; - if (BGP_DEBUG (zebra, ZEBRA)) - ret++; + if (BGP_DEBUG(zebra, ZEBRA)) + ret++; - if (BGP_DEBUG (allow_martians, ALLOW_MARTIANS)) - ret++; + if (BGP_DEBUG(allow_martians, ALLOW_MARTIANS)) + ret++; - return ret; + return ret; } -static int -bgp_config_write_debug (struct vty *vty) +static int bgp_config_write_debug(struct vty *vty) { - int write = 0; - - if (CONF_BGP_DEBUG (as4, AS4)) - { - vty_out (vty, "debug bgp as4\n"); - write++; - } - - if (CONF_BGP_DEBUG (as4, AS4_SEGMENT)) - { - vty_out (vty, "debug bgp as4 segment\n"); - write++; - } - - if (CONF_BGP_DEBUG (bestpath, BESTPATH)) - { - write += bgp_debug_list_conf_print (vty, "debug bgp bestpath", - bgp_debug_bestpath_prefixes); - } - - if (CONF_BGP_DEBUG (keepalive, KEEPALIVE)) - { - write += bgp_debug_list_conf_print (vty, "debug bgp keepalives", - bgp_debug_keepalive_peers); - } - - if (CONF_BGP_DEBUG (neighbor_events, NEIGHBOR_EVENTS)) - { - write += bgp_debug_list_conf_print (vty, "debug bgp neighbor-events", - bgp_debug_neighbor_events_peers); - } - - if (CONF_BGP_DEBUG (nht, NHT)) - { - vty_out (vty, "debug bgp nht\n"); - write++; - } - - if (CONF_BGP_DEBUG (update_groups, UPDATE_GROUPS)) - { - vty_out (vty, "debug bgp update-groups\n"); - write++; - } - - if (CONF_BGP_DEBUG (update, UPDATE_PREFIX)) - { - write += bgp_debug_list_conf_print (vty, "debug bgp updates prefix", - bgp_debug_update_prefixes); - } - - if (CONF_BGP_DEBUG (update, UPDATE_IN)) - { - write += bgp_debug_list_conf_print (vty, "debug bgp updates in", - bgp_debug_update_in_peers); - } - - if (CONF_BGP_DEBUG (update, UPDATE_OUT)) - { - write += bgp_debug_list_conf_print (vty, "debug bgp updates out", - bgp_debug_update_out_peers); - } - - if (CONF_BGP_DEBUG (zebra, ZEBRA)) - { - if (!bgp_debug_zebra_prefixes || list_isempty(bgp_debug_zebra_prefixes)) - { - vty_out (vty, "debug bgp zebra\n"); - write++; - } - else - { - write += bgp_debug_list_conf_print (vty, "debug bgp zebra prefix", - bgp_debug_zebra_prefixes); - } - } - - if (CONF_BGP_DEBUG (allow_martians, ALLOW_MARTIANS)) - { - vty_out (vty, "debug bgp allow-martians\n"); - write++; - } - - return write; -} + int write = 0; -static struct cmd_node debug_node = -{ - DEBUG_NODE, - "", - 1 -}; + if (CONF_BGP_DEBUG(as4, AS4)) { + vty_out(vty, "debug bgp as4\n"); + write++; + } -void -bgp_debug_init (void) -{ - install_node (&debug_node, bgp_config_write_debug); - - install_element (ENABLE_NODE, &show_debugging_bgp_cmd); - - install_element (ENABLE_NODE, &debug_bgp_as4_cmd); - install_element (CONFIG_NODE, &debug_bgp_as4_cmd); - install_element (ENABLE_NODE, &debug_bgp_as4_segment_cmd); - install_element (CONFIG_NODE, &debug_bgp_as4_segment_cmd); - - install_element (ENABLE_NODE, &debug_bgp_neighbor_events_cmd); - install_element (CONFIG_NODE, &debug_bgp_neighbor_events_cmd); - install_element (ENABLE_NODE, &debug_bgp_nht_cmd); - install_element (CONFIG_NODE, &debug_bgp_nht_cmd); - install_element (ENABLE_NODE, &debug_bgp_keepalive_cmd); - install_element (CONFIG_NODE, &debug_bgp_keepalive_cmd); - install_element (ENABLE_NODE, &debug_bgp_update_cmd); - install_element (CONFIG_NODE, &debug_bgp_update_cmd); - install_element (ENABLE_NODE, &debug_bgp_zebra_cmd); - install_element (CONFIG_NODE, &debug_bgp_zebra_cmd); - install_element (ENABLE_NODE, &debug_bgp_allow_martians_cmd); - install_element (CONFIG_NODE, &debug_bgp_allow_martians_cmd); - install_element (ENABLE_NODE, &debug_bgp_update_groups_cmd); - install_element (CONFIG_NODE, &debug_bgp_update_groups_cmd); - install_element (ENABLE_NODE, &debug_bgp_bestpath_prefix_cmd); - install_element (CONFIG_NODE, &debug_bgp_bestpath_prefix_cmd); - - /* debug bgp updates (in|out) */ - install_element (ENABLE_NODE, &debug_bgp_update_direct_cmd); - install_element (CONFIG_NODE, &debug_bgp_update_direct_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_update_direct_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_update_direct_cmd); - - /* debug bgp updates (in|out) A.B.C.D */ - install_element (ENABLE_NODE, &debug_bgp_update_direct_peer_cmd); - install_element (CONFIG_NODE, &debug_bgp_update_direct_peer_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_update_direct_peer_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_update_direct_peer_cmd); - - /* debug bgp updates prefix A.B.C.D/M */ - install_element (ENABLE_NODE, &debug_bgp_update_prefix_cmd); - install_element (CONFIG_NODE, &debug_bgp_update_prefix_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_update_prefix_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_update_prefix_cmd); - - /* debug bgp zebra prefix A.B.C.D/M */ - install_element (ENABLE_NODE, &debug_bgp_zebra_prefix_cmd); - install_element (CONFIG_NODE, &debug_bgp_zebra_prefix_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_zebra_prefix_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_zebra_prefix_cmd); - - install_element (ENABLE_NODE, &no_debug_bgp_as4_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_as4_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_as4_segment_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_as4_segment_cmd); - - /* debug bgp neighbor-events A.B.C.D */ - install_element (ENABLE_NODE, &debug_bgp_neighbor_events_peer_cmd); - install_element (CONFIG_NODE, &debug_bgp_neighbor_events_peer_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_neighbor_events_peer_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_neighbor_events_peer_cmd); - - /* debug bgp keepalive A.B.C.D */ - install_element (ENABLE_NODE, &debug_bgp_keepalive_peer_cmd); - install_element (CONFIG_NODE, &debug_bgp_keepalive_peer_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_keepalive_peer_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_keepalive_peer_cmd); - - install_element (ENABLE_NODE, &no_debug_bgp_neighbor_events_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_neighbor_events_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_nht_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_nht_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_keepalive_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_keepalive_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_update_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_update_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_zebra_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_zebra_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_allow_martians_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_allow_martians_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_update_groups_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_update_groups_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_bestpath_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_bestpath_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_bestpath_prefix_cmd); - install_element (CONFIG_NODE, &no_debug_bgp_bestpath_prefix_cmd); -} + if (CONF_BGP_DEBUG(as4, AS4_SEGMENT)) { + vty_out(vty, "debug bgp as4 segment\n"); + write++; + } -/* Return true if this prefix is on the per_prefix_list of prefixes to debug - * for BGP_DEBUG_TYPE - */ -static int -bgp_debug_per_prefix (struct prefix *p, unsigned long term_bgp_debug_type, - unsigned int BGP_DEBUG_TYPE, struct list *per_prefix_list) -{ - struct bgp_debug_filter *filter; - struct listnode *node, *nnode; + if (CONF_BGP_DEBUG(bestpath, BESTPATH)) { + write += bgp_debug_list_conf_print(vty, "debug bgp bestpath", + bgp_debug_bestpath_prefixes); + } + + if (CONF_BGP_DEBUG(keepalive, KEEPALIVE)) { + write += bgp_debug_list_conf_print(vty, "debug bgp keepalives", + bgp_debug_keepalive_peers); + } + + if (CONF_BGP_DEBUG(neighbor_events, NEIGHBOR_EVENTS)) { + write += bgp_debug_list_conf_print( + vty, "debug bgp neighbor-events", + bgp_debug_neighbor_events_peers); + } + + if (CONF_BGP_DEBUG(nht, NHT)) { + vty_out(vty, "debug bgp nht\n"); + write++; + } + + if (CONF_BGP_DEBUG(update_groups, UPDATE_GROUPS)) { + vty_out(vty, "debug bgp update-groups\n"); + write++; + } + + if (CONF_BGP_DEBUG(update, UPDATE_PREFIX)) { + write += bgp_debug_list_conf_print(vty, + "debug bgp updates prefix", + bgp_debug_update_prefixes); + } + + if (CONF_BGP_DEBUG(update, UPDATE_IN)) { + write += bgp_debug_list_conf_print(vty, "debug bgp updates in", + bgp_debug_update_in_peers); + } + + if (CONF_BGP_DEBUG(update, UPDATE_OUT)) { + write += bgp_debug_list_conf_print(vty, "debug bgp updates out", + bgp_debug_update_out_peers); + } - if (term_bgp_debug_type & BGP_DEBUG_TYPE) - { - /* We are debugging all prefixes so return true */ - if (!per_prefix_list || list_isempty(per_prefix_list)) - return 1; + if (CONF_BGP_DEBUG(zebra, ZEBRA)) { + if (!bgp_debug_zebra_prefixes + || list_isempty(bgp_debug_zebra_prefixes)) { + vty_out(vty, "debug bgp zebra\n"); + write++; + } else { + write += bgp_debug_list_conf_print( + vty, "debug bgp zebra prefix", + bgp_debug_zebra_prefixes); + } + } - else - { - if (!p) - return 0; + if (CONF_BGP_DEBUG(allow_martians, ALLOW_MARTIANS)) { + vty_out(vty, "debug bgp allow-martians\n"); + write++; + } - for (ALL_LIST_ELEMENTS (per_prefix_list, node, nnode, filter)) - if (filter->p->prefixlen == p->prefixlen && prefix_match(filter->p, p)) - return 1; + return write; +} - return 0; - } - } +static struct cmd_node debug_node = {DEBUG_NODE, "", 1}; + +void bgp_debug_init(void) +{ + install_node(&debug_node, bgp_config_write_debug); + + install_element(ENABLE_NODE, &show_debugging_bgp_cmd); + + install_element(ENABLE_NODE, &debug_bgp_as4_cmd); + install_element(CONFIG_NODE, &debug_bgp_as4_cmd); + install_element(ENABLE_NODE, &debug_bgp_as4_segment_cmd); + install_element(CONFIG_NODE, &debug_bgp_as4_segment_cmd); + + install_element(ENABLE_NODE, &debug_bgp_neighbor_events_cmd); + install_element(CONFIG_NODE, &debug_bgp_neighbor_events_cmd); + install_element(ENABLE_NODE, &debug_bgp_nht_cmd); + install_element(CONFIG_NODE, &debug_bgp_nht_cmd); + install_element(ENABLE_NODE, &debug_bgp_keepalive_cmd); + install_element(CONFIG_NODE, &debug_bgp_keepalive_cmd); + install_element(ENABLE_NODE, &debug_bgp_update_cmd); + install_element(CONFIG_NODE, &debug_bgp_update_cmd); + install_element(ENABLE_NODE, &debug_bgp_zebra_cmd); + install_element(CONFIG_NODE, &debug_bgp_zebra_cmd); + install_element(ENABLE_NODE, &debug_bgp_allow_martians_cmd); + install_element(CONFIG_NODE, &debug_bgp_allow_martians_cmd); + install_element(ENABLE_NODE, &debug_bgp_update_groups_cmd); + install_element(CONFIG_NODE, &debug_bgp_update_groups_cmd); + install_element(ENABLE_NODE, &debug_bgp_bestpath_prefix_cmd); + install_element(CONFIG_NODE, &debug_bgp_bestpath_prefix_cmd); + + /* debug bgp updates (in|out) */ + install_element(ENABLE_NODE, &debug_bgp_update_direct_cmd); + install_element(CONFIG_NODE, &debug_bgp_update_direct_cmd); + install_element(ENABLE_NODE, &no_debug_bgp_update_direct_cmd); + install_element(CONFIG_NODE, &no_debug_bgp_update_direct_cmd); + + /* debug bgp updates (in|out) A.B.C.D */ + install_element(ENABLE_NODE, &debug_bgp_update_direct_peer_cmd); + install_element(CONFIG_NODE, &debug_bgp_update_direct_peer_cmd); + install_element(ENABLE_NODE, &no_debug_bgp_update_direct_peer_cmd); + install_element(CONFIG_NODE, &no_debug_bgp_update_direct_peer_cmd); + + /* debug bgp updates prefix A.B.C.D/M */ + install_element(ENABLE_NODE, &debug_bgp_update_prefix_cmd); + install_element(CONFIG_NODE, &debug_bgp_update_prefix_cmd); + install_element(ENABLE_NODE, &no_debug_bgp_update_prefix_cmd); + install_element(CONFIG_NODE, &no_debug_bgp_update_prefix_cmd); + + /* debug bgp zebra prefix A.B.C.D/M */ + install_element(ENABLE_NODE, &debug_bgp_zebra_prefix_cmd); + install_element(CONFIG_NODE, &debug_bgp_zebra_prefix_cmd); + install_element(ENABLE_NODE, &no_debug_bgp_zebra_prefix_cmd); + install_element(CONFIG_NODE, &no_debug_bgp_zebra_prefix_cmd); + + install_element(ENABLE_NODE, &no_debug_bgp_as4_cmd); + install_element(CONFIG_NODE, &no_debug_bgp_as4_cmd); + install_element(ENABLE_NODE, &no_debug_bgp_as4_segment_cmd); + install_element(CONFIG_NODE, &no_debug_bgp_as4_segment_cmd); + + /* debug bgp neighbor-events A.B.C.D */ + install_element(ENABLE_NODE, &debug_bgp_neighbor_events_peer_cmd); + install_element(CONFIG_NODE, &debug_bgp_neighbor_events_peer_cmd); + install_element(ENABLE_NODE, &no_debug_bgp_neighbor_events_peer_cmd); + install_element(CONFIG_NODE, &no_debug_bgp_neighbor_events_peer_cmd); + + /* debug bgp keepalive A.B.C.D */ + install_element(ENABLE_NODE, &debug_bgp_keepalive_peer_cmd); + install_element(CONFIG_NODE, &debug_bgp_keepalive_peer_cmd); + install_element(ENABLE_NODE, &no_debug_bgp_keepalive_peer_cmd); + install_element(CONFIG_NODE, &no_debug_bgp_keepalive_peer_cmd); + + install_element(ENABLE_NODE, &no_debug_bgp_neighbor_events_cmd); + install_element(CONFIG_NODE, &no_debug_bgp_neighbor_events_cmd); + install_element(ENABLE_NODE, &no_debug_bgp_nht_cmd); + install_element(CONFIG_NODE, &no_debug_bgp_nht_cmd); + install_element(ENABLE_NODE, &no_debug_bgp_keepalive_cmd); + install_element(CONFIG_NODE, &no_debug_bgp_keepalive_cmd); + install_element(ENABLE_NODE, &no_debug_bgp_update_cmd); + install_element(CONFIG_NODE, &no_debug_bgp_update_cmd); + install_element(ENABLE_NODE, &no_debug_bgp_zebra_cmd); + install_element(CONFIG_NODE, &no_debug_bgp_zebra_cmd); + install_element(ENABLE_NODE, &no_debug_bgp_allow_martians_cmd); + install_element(CONFIG_NODE, &no_debug_bgp_allow_martians_cmd); + install_element(ENABLE_NODE, &no_debug_bgp_update_groups_cmd); + install_element(CONFIG_NODE, &no_debug_bgp_update_groups_cmd); + install_element(ENABLE_NODE, &no_debug_bgp_cmd); + install_element(ENABLE_NODE, &no_debug_bgp_bestpath_cmd); + install_element(CONFIG_NODE, &no_debug_bgp_bestpath_cmd); + install_element(ENABLE_NODE, &no_debug_bgp_bestpath_prefix_cmd); + install_element(CONFIG_NODE, &no_debug_bgp_bestpath_prefix_cmd); +} - return 0; +/* Return true if this prefix is on the per_prefix_list of prefixes to debug + * for BGP_DEBUG_TYPE + */ +static int bgp_debug_per_prefix(struct prefix *p, + unsigned long term_bgp_debug_type, + unsigned int BGP_DEBUG_TYPE, + struct list *per_prefix_list) +{ + struct bgp_debug_filter *filter; + struct listnode *node, *nnode; + + if (term_bgp_debug_type & BGP_DEBUG_TYPE) { + /* We are debugging all prefixes so return true */ + if (!per_prefix_list || list_isempty(per_prefix_list)) + return 1; + + else { + if (!p) + return 0; + + for (ALL_LIST_ELEMENTS(per_prefix_list, node, nnode, + filter)) + if (filter->p->prefixlen == p->prefixlen + && prefix_match(filter->p, p)) + return 1; + + return 0; + } + } + + return 0; } /* Return true if this peer is on the per_peer_list of peers to debug * for BGP_DEBUG_TYPE */ -static int -bgp_debug_per_peer(char *host, unsigned long term_bgp_debug_type, - unsigned int BGP_DEBUG_TYPE, struct list *per_peer_list) +static int bgp_debug_per_peer(char *host, unsigned long term_bgp_debug_type, + unsigned int BGP_DEBUG_TYPE, + struct list *per_peer_list) { - struct bgp_debug_filter *filter; - struct listnode *node, *nnode; + struct bgp_debug_filter *filter; + struct listnode *node, *nnode; - if (term_bgp_debug_type & BGP_DEBUG_TYPE) - { - /* We are debugging all peers so return true */ - if (!per_peer_list || list_isempty(per_peer_list)) - return 1; + if (term_bgp_debug_type & BGP_DEBUG_TYPE) { + /* We are debugging all peers so return true */ + if (!per_peer_list || list_isempty(per_peer_list)) + return 1; - else - { - if (!host) - return 0; + else { + if (!host) + return 0; - for (ALL_LIST_ELEMENTS (per_peer_list, node, nnode, filter)) - if (strcmp (filter->host, host) == 0) - return 1; + for (ALL_LIST_ELEMENTS(per_peer_list, node, nnode, + filter)) + if (strcmp(filter->host, host) == 0) + return 1; - return 0; - } - } + return 0; + } + } - return 0; + return 0; } -int -bgp_debug_neighbor_events (struct peer *peer) +int bgp_debug_neighbor_events(struct peer *peer) { - char *host = NULL; + char *host = NULL; - if (peer) - host = peer->host; + if (peer) + host = peer->host; - return bgp_debug_per_peer (host, - term_bgp_debug_neighbor_events, - BGP_DEBUG_NEIGHBOR_EVENTS, - bgp_debug_neighbor_events_peers); + return bgp_debug_per_peer(host, term_bgp_debug_neighbor_events, + BGP_DEBUG_NEIGHBOR_EVENTS, + bgp_debug_neighbor_events_peers); } -int -bgp_debug_keepalive (struct peer *peer) +int bgp_debug_keepalive(struct peer *peer) { - char *host = NULL; + char *host = NULL; - if (peer) - host = peer->host; + if (peer) + host = peer->host; - return bgp_debug_per_peer (host, - term_bgp_debug_keepalive, - BGP_DEBUG_KEEPALIVE, - bgp_debug_keepalive_peers); + return bgp_debug_per_peer(host, term_bgp_debug_keepalive, + BGP_DEBUG_KEEPALIVE, + bgp_debug_keepalive_peers); } -int -bgp_debug_update (struct peer *peer, struct prefix *p, - struct update_group *updgrp, unsigned int inbound) +int bgp_debug_update(struct peer *peer, struct prefix *p, + struct update_group *updgrp, unsigned int inbound) { - char *host = NULL; - - if (peer) - host = peer->host; - - if (inbound) - { - if (bgp_debug_per_peer (host, term_bgp_debug_update, BGP_DEBUG_UPDATE_IN, - bgp_debug_update_in_peers)) - return 1; - } - - /* outbound */ - else - { - if (bgp_debug_per_peer (host, term_bgp_debug_update, - BGP_DEBUG_UPDATE_OUT, - bgp_debug_update_out_peers)) - return 1; - - /* Check if update debugging implicitly enabled for the group. */ - if (updgrp && UPDGRP_DBG_ON(updgrp)) - return 1; - } - - - if (BGP_DEBUG (update, UPDATE_PREFIX)) - { - if (bgp_debug_per_prefix (p, term_bgp_debug_update, - BGP_DEBUG_UPDATE_PREFIX, - bgp_debug_update_prefixes)) - return 1; - } - - return 0; + char *host = NULL; + + if (peer) + host = peer->host; + + if (inbound) { + if (bgp_debug_per_peer(host, term_bgp_debug_update, + BGP_DEBUG_UPDATE_IN, + bgp_debug_update_in_peers)) + return 1; + } + + /* outbound */ + else { + if (bgp_debug_per_peer(host, term_bgp_debug_update, + BGP_DEBUG_UPDATE_OUT, + bgp_debug_update_out_peers)) + return 1; + + /* Check if update debugging implicitly enabled for the group. + */ + if (updgrp && UPDGRP_DBG_ON(updgrp)) + return 1; + } + + + if (BGP_DEBUG(update, UPDATE_PREFIX)) { + if (bgp_debug_per_prefix(p, term_bgp_debug_update, + BGP_DEBUG_UPDATE_PREFIX, + bgp_debug_update_prefixes)) + return 1; + } + + return 0; } -int -bgp_debug_bestpath (struct prefix *p) +int bgp_debug_bestpath(struct prefix *p) { - if (BGP_DEBUG (bestpath, BESTPATH)) - { - if (bgp_debug_per_prefix (p, term_bgp_debug_bestpath, - BGP_DEBUG_BESTPATH, - bgp_debug_bestpath_prefixes)) - return 1; - } - - return 0; + if (BGP_DEBUG(bestpath, BESTPATH)) { + if (bgp_debug_per_prefix(p, term_bgp_debug_bestpath, + BGP_DEBUG_BESTPATH, + bgp_debug_bestpath_prefixes)) + return 1; + } + + return 0; } -int -bgp_debug_zebra (struct prefix *p) +int bgp_debug_zebra(struct prefix *p) { - if (BGP_DEBUG (zebra, ZEBRA)) - { - if (bgp_debug_per_prefix (p, term_bgp_debug_zebra, BGP_DEBUG_ZEBRA, - bgp_debug_zebra_prefixes)) - return 1; - } - - return 0; + if (BGP_DEBUG(zebra, ZEBRA)) { + if (bgp_debug_per_prefix(p, term_bgp_debug_zebra, + BGP_DEBUG_ZEBRA, + bgp_debug_zebra_prefixes)) + return 1; + } + + return 0; } -const char * -bgp_debug_rdpfxpath2str (afi_t afi, safi_t safi, - struct prefix_rd *prd, union prefixconstptr pu, - mpls_label_t *label, int addpath_valid, - u_int32_t addpath_id, char *str, int size) -{ - char rd_buf[RD_ADDRSTRLEN]; - char pfx_buf[PREFIX_STRLEN]; - char tag_buf[30]; - /* ' with addpath ID ' 17 - * max strlen of uint32 + 10 - * +/- (just in case) + 1 - * null terminator + 1 - * ============================ 29 */ - char pathid_buf[30]; - - if (size < BGP_PRD_PATH_STRLEN) - return NULL; - - /* Note: Path-id is created by default, but only included in update sometimes. */ - pathid_buf[0] = '\0'; - if (addpath_valid) - snprintf(pathid_buf, sizeof(pathid_buf), " with addpath ID %u", addpath_id); - - tag_buf[0] = '\0'; - if (bgp_labeled_safi (safi) && label) - { - u_int32_t label_value; - - label_value = decode_label (label); - sprintf (tag_buf, " label %u", label_value); - } - - if (prd) - snprintf (str, size, "RD %s %s%s%s", - prefix_rd2str(prd, rd_buf, sizeof (rd_buf)), - prefix2str (pu, pfx_buf, sizeof (pfx_buf)), - tag_buf, pathid_buf); - else - snprintf (str, size, "%s%s%s", - prefix2str (pu, pfx_buf, sizeof (pfx_buf)), - tag_buf, pathid_buf); - - return str; +const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi, + struct prefix_rd *prd, + union prefixconstptr pu, + mpls_label_t *label, int addpath_valid, + u_int32_t addpath_id, char *str, int size) +{ + char rd_buf[RD_ADDRSTRLEN]; + char pfx_buf[PREFIX_STRLEN]; + char tag_buf[30]; + /* ' with addpath ID ' 17 + * max strlen of uint32 + 10 + * +/- (just in case) + 1 + * null terminator + 1 + * ============================ 29 */ + char pathid_buf[30]; + + if (size < BGP_PRD_PATH_STRLEN) + return NULL; + + /* Note: Path-id is created by default, but only included in update + * sometimes. */ + pathid_buf[0] = '\0'; + if (addpath_valid) + snprintf(pathid_buf, sizeof(pathid_buf), " with addpath ID %u", + addpath_id); + + tag_buf[0] = '\0'; + if (bgp_labeled_safi(safi) && label) { + u_int32_t label_value; + + label_value = decode_label(label); + sprintf(tag_buf, " label %u", label_value); + } + + if (prd) + snprintf(str, size, "RD %s %s%s%s", + prefix_rd2str(prd, rd_buf, sizeof(rd_buf)), + prefix2str(pu, pfx_buf, sizeof(pfx_buf)), tag_buf, + pathid_buf); + else + snprintf(str, size, "%s%s%s", + prefix2str(pu, pfx_buf, sizeof(pfx_buf)), tag_buf, + pathid_buf); + + return str; } diff --git a/bgpd/bgp_debug.h b/bgpd/bgp_debug.h index 11ab4dbd6..5fe19b162 100644 --- a/bgpd/bgp_debug.h +++ b/bgpd/bgp_debug.h @@ -57,10 +57,10 @@ extern int Debug_Radix; #define DETAIL 6 /* Prototypes. */ -extern void bgp_debug_init (void); -extern void bgp_packet_dump (struct stream *); +extern void bgp_debug_init(void); +extern void bgp_packet_dump(struct stream *); -extern int debug (unsigned int option); +extern int debug(unsigned int option); extern unsigned long conf_bgp_debug_as4; extern unsigned long conf_bgp_debug_neighbor_events; @@ -92,10 +92,9 @@ extern struct list *bgp_debug_update_prefixes; extern struct list *bgp_debug_bestpath_prefixes; extern struct list *bgp_debug_zebra_prefixes; -struct bgp_debug_filter -{ - char *host; - struct prefix *p; +struct bgp_debug_filter { + char *host; + struct prefix *p; }; #define BGP_DEBUG_AS4 0x01 @@ -122,40 +121,41 @@ struct bgp_debug_filter #define TERM_DEBUG_ON(a, b) (term_bgp_debug_ ## a |= (BGP_DEBUG_ ## b)) #define TERM_DEBUG_OFF(a, b) (term_bgp_debug_ ## a &= ~(BGP_DEBUG_ ## b)) -#define DEBUG_ON(a, b) \ - do { \ - CONF_DEBUG_ON(a, b); \ - TERM_DEBUG_ON(a, b); \ - } while (0) -#define DEBUG_OFF(a, b) \ - do { \ - CONF_DEBUG_OFF(a, b); \ - TERM_DEBUG_OFF(a, b); \ - } while (0) +#define DEBUG_ON(a, b) \ + do { \ + CONF_DEBUG_ON(a, b); \ + TERM_DEBUG_ON(a, b); \ + } while (0) +#define DEBUG_OFF(a, b) \ + do { \ + CONF_DEBUG_OFF(a, b); \ + TERM_DEBUG_OFF(a, b); \ + } while (0) #define BGP_DEBUG(a, b) (term_bgp_debug_ ## a & BGP_DEBUG_ ## b) #define CONF_BGP_DEBUG(a, b) (conf_bgp_debug_ ## a & BGP_DEBUG_ ## b) extern const char *bgp_type_str[]; -extern int bgp_dump_attr (struct attr *, char *, size_t); +extern int bgp_dump_attr(struct attr *, char *, size_t); extern int bgp_debug_peer_updout_enabled(char *host); extern const char *bgp_notify_code_str(char); extern const char *bgp_notify_subcode_str(char, char); -extern void bgp_notify_print (struct peer *, struct bgp_notify *, const char *); +extern void bgp_notify_print(struct peer *, struct bgp_notify *, const char *); extern const struct message bgp_status_msg[]; extern int bgp_debug_neighbor_events(struct peer *peer); extern int bgp_debug_keepalive(struct peer *peer); extern int bgp_debug_update(struct peer *peer, struct prefix *p, - struct update_group *updgrp, unsigned int inbound); + struct update_group *updgrp, unsigned int inbound); extern int bgp_debug_bestpath(struct prefix *p); extern int bgp_debug_zebra(struct prefix *p); extern int bgp_debug_count(void); -extern const char *bgp_debug_rdpfxpath2str (afi_t, safi_t, struct prefix_rd *, - union prefixconstptr, mpls_label_t *, - int, u_int32_t, char *, int); -const char *bgp_notify_admin_message(char *buf, size_t bufsz, u_char *data, size_t datalen); +extern const char *bgp_debug_rdpfxpath2str(afi_t, safi_t, struct prefix_rd *, + union prefixconstptr, mpls_label_t *, + int, u_int32_t, char *, int); +const char *bgp_notify_admin_message(char *buf, size_t bufsz, u_char *data, + size_t datalen); #endif /* _QUAGGA_BGP_DEBUG_H */ diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c index 5b6b8e137..083136906 100644 --- a/bgpd/bgp_dump.c +++ b/bgpd/bgp_dump.c @@ -37,62 +37,56 @@ #include "bgpd/bgp_attr.h" #include "bgpd/bgp_dump.h" -enum bgp_dump_type -{ - BGP_DUMP_ALL, - BGP_DUMP_ALL_ET, - BGP_DUMP_UPDATES, - BGP_DUMP_UPDATES_ET, - BGP_DUMP_ROUTES +enum bgp_dump_type { + BGP_DUMP_ALL, + BGP_DUMP_ALL_ET, + BGP_DUMP_UPDATES, + BGP_DUMP_UPDATES_ET, + BGP_DUMP_ROUTES }; static const struct bgp_dump_type_map { - enum bgp_dump_type type; - const char *str; -} bgp_dump_type_map[] = - { - {BGP_DUMP_ALL, "all"}, - {BGP_DUMP_ALL_ET, "all-et"}, - {BGP_DUMP_UPDATES, "updates"}, - {BGP_DUMP_UPDATES_ET, "updates-et"}, - {BGP_DUMP_ROUTES, "routes-mrt"}, - {0, NULL}, - }; + enum bgp_dump_type type; + const char *str; +} bgp_dump_type_map[] = { + {BGP_DUMP_ALL, "all"}, {BGP_DUMP_ALL_ET, "all-et"}, + {BGP_DUMP_UPDATES, "updates"}, {BGP_DUMP_UPDATES_ET, "updates-et"}, + {BGP_DUMP_ROUTES, "routes-mrt"}, {0, NULL}, +}; enum MRT_MSG_TYPES { - MSG_NULL, - MSG_START, /* sender is starting up */ - MSG_DIE, /* receiver should shut down */ - MSG_I_AM_DEAD, /* sender is shutting down */ - MSG_PEER_DOWN, /* sender's peer is down */ - MSG_PROTOCOL_BGP, /* msg is a BGP packet */ - MSG_PROTOCOL_RIP, /* msg is a RIP packet */ - MSG_PROTOCOL_IDRP, /* msg is an IDRP packet */ - MSG_PROTOCOL_RIPNG, /* msg is a RIPNG packet */ - MSG_PROTOCOL_BGP4PLUS, /* msg is a BGP4+ packet */ - MSG_PROTOCOL_BGP4PLUS_01, /* msg is a BGP4+ (draft 01) packet */ - MSG_PROTOCOL_OSPF, /* msg is an OSPF packet */ - MSG_TABLE_DUMP, /* routing table dump */ - MSG_TABLE_DUMP_V2 /* routing table dump, version 2 */ + MSG_NULL, + MSG_START, /* sender is starting up */ + MSG_DIE, /* receiver should shut down */ + MSG_I_AM_DEAD, /* sender is shutting down */ + MSG_PEER_DOWN, /* sender's peer is down */ + MSG_PROTOCOL_BGP, /* msg is a BGP packet */ + MSG_PROTOCOL_RIP, /* msg is a RIP packet */ + MSG_PROTOCOL_IDRP, /* msg is an IDRP packet */ + MSG_PROTOCOL_RIPNG, /* msg is a RIPNG packet */ + MSG_PROTOCOL_BGP4PLUS, /* msg is a BGP4+ packet */ + MSG_PROTOCOL_BGP4PLUS_01, /* msg is a BGP4+ (draft 01) packet */ + MSG_PROTOCOL_OSPF, /* msg is an OSPF packet */ + MSG_TABLE_DUMP, /* routing table dump */ + MSG_TABLE_DUMP_V2 /* routing table dump, version 2 */ }; -struct bgp_dump -{ - enum bgp_dump_type type; +struct bgp_dump { + enum bgp_dump_type type; - char *filename; + char *filename; - FILE *fp; + FILE *fp; - unsigned int interval; + unsigned int interval; - char *interval_str; + char *interval_str; - struct thread *t_interval; + struct thread *t_interval; }; -static int bgp_dump_unset (struct bgp_dump *bgp_dump); -static int bgp_dump_interval_func (struct thread *); +static int bgp_dump_unset(struct bgp_dump *bgp_dump); +static int bgp_dump_interval_func(struct thread *); /* BGP packet dump output buffer. */ struct stream *bgp_dump_obuf; @@ -106,631 +100,594 @@ struct bgp_dump bgp_dump_updates; /* BGP dump structure for 'dump bgp routes' */ struct bgp_dump bgp_dump_routes; -static FILE * -bgp_dump_open_file (struct bgp_dump *bgp_dump) +static FILE *bgp_dump_open_file(struct bgp_dump *bgp_dump) { - int ret; - time_t clock; - struct tm *tm; - char fullpath[MAXPATHLEN]; - char realpath[MAXPATHLEN]; - mode_t oldumask; - - time (&clock); - tm = localtime (&clock); - - if (bgp_dump->filename[0] != DIRECTORY_SEP) - { - sprintf (fullpath, "%s/%s", vty_get_cwd (), bgp_dump->filename); - ret = strftime (realpath, MAXPATHLEN, fullpath, tm); - } - else - ret = strftime (realpath, MAXPATHLEN, bgp_dump->filename, tm); - - if (ret == 0) - { - zlog_warn ("bgp_dump_open_file: strftime error"); - return NULL; - } + int ret; + time_t clock; + struct tm *tm; + char fullpath[MAXPATHLEN]; + char realpath[MAXPATHLEN]; + mode_t oldumask; + + time(&clock); + tm = localtime(&clock); + + if (bgp_dump->filename[0] != DIRECTORY_SEP) { + sprintf(fullpath, "%s/%s", vty_get_cwd(), bgp_dump->filename); + ret = strftime(realpath, MAXPATHLEN, fullpath, tm); + } else + ret = strftime(realpath, MAXPATHLEN, bgp_dump->filename, tm); + + if (ret == 0) { + zlog_warn("bgp_dump_open_file: strftime error"); + return NULL; + } - if (bgp_dump->fp) - fclose (bgp_dump->fp); + if (bgp_dump->fp) + fclose(bgp_dump->fp); - oldumask = umask(0777 & ~LOGFILE_MASK); - bgp_dump->fp = fopen (realpath, "w"); + oldumask = umask(0777 & ~LOGFILE_MASK); + bgp_dump->fp = fopen(realpath, "w"); - if (bgp_dump->fp == NULL) - { - zlog_warn ("bgp_dump_open_file: %s: %s", realpath, strerror (errno)); - umask(oldumask); - return NULL; - } - umask(oldumask); + if (bgp_dump->fp == NULL) { + zlog_warn("bgp_dump_open_file: %s: %s", realpath, + strerror(errno)); + umask(oldumask); + return NULL; + } + umask(oldumask); - return bgp_dump->fp; + return bgp_dump->fp; } -static int -bgp_dump_interval_add (struct bgp_dump *bgp_dump, int interval) +static int bgp_dump_interval_add(struct bgp_dump *bgp_dump, int interval) { - int secs_into_day; - time_t t; - struct tm *tm; - - if (interval > 0) - { - /* Periodic dump every interval seconds */ - if ((interval < 86400) && ((86400 % interval) == 0)) - { - /* Dump at predictable times: if a day has a whole number of - * intervals, dump every interval seconds starting from midnight - */ - (void) time(&t); - tm = localtime(&t); - secs_into_day = tm->tm_sec + 60*tm->tm_min + 60*60*tm->tm_hour; - interval = interval - secs_into_day % interval; /* always > 0 */ + int secs_into_day; + time_t t; + struct tm *tm; + + if (interval > 0) { + /* Periodic dump every interval seconds */ + if ((interval < 86400) && ((86400 % interval) == 0)) { + /* Dump at predictable times: if a day has a whole + * number of + * intervals, dump every interval seconds starting from + * midnight + */ + (void)time(&t); + tm = localtime(&t); + secs_into_day = tm->tm_sec + 60 * tm->tm_min + + 60 * 60 * tm->tm_hour; + interval = interval + - secs_into_day % interval; /* always > 0 */ + } + bgp_dump->t_interval = NULL; + thread_add_timer(bm->master, bgp_dump_interval_func, bgp_dump, + interval, &bgp_dump->t_interval); + } else { + /* One-off dump: execute immediately, don't affect any scheduled + * dumps */ + bgp_dump->t_interval = NULL; + thread_add_event(bm->master, bgp_dump_interval_func, bgp_dump, + 0, &bgp_dump->t_interval); } - bgp_dump->t_interval = NULL; - thread_add_timer(bm->master, bgp_dump_interval_func, bgp_dump, interval, - &bgp_dump->t_interval); - } - else - { - /* One-off dump: execute immediately, don't affect any scheduled dumps */ - bgp_dump->t_interval = NULL; - thread_add_event(bm->master, bgp_dump_interval_func, bgp_dump, 0, - &bgp_dump->t_interval); - } - return 0; + return 0; } /* Dump common header. */ -static void -bgp_dump_header (struct stream *obuf, int type, int subtype, int dump_type) +static void bgp_dump_header(struct stream *obuf, int type, int subtype, + int dump_type) { - struct timeval clock; - long msecs; - time_t secs; + struct timeval clock; + long msecs; + time_t secs; - if ((dump_type == BGP_DUMP_ALL_ET || dump_type == BGP_DUMP_UPDATES_ET) - && type == MSG_PROTOCOL_BGP4MP) - type = MSG_PROTOCOL_BGP4MP_ET; + if ((dump_type == BGP_DUMP_ALL_ET || dump_type == BGP_DUMP_UPDATES_ET) + && type == MSG_PROTOCOL_BGP4MP) + type = MSG_PROTOCOL_BGP4MP_ET; - gettimeofday(&clock, NULL); + gettimeofday(&clock, NULL); - secs = clock.tv_sec; - msecs = clock.tv_usec; + secs = clock.tv_sec; + msecs = clock.tv_usec; - /* Put dump packet header. */ - stream_putl (obuf, secs); - stream_putw (obuf, type); - stream_putw (obuf, subtype); - stream_putl (obuf, 0); /* len */ + /* Put dump packet header. */ + stream_putl(obuf, secs); + stream_putw(obuf, type); + stream_putw(obuf, subtype); + stream_putl(obuf, 0); /* len */ - /* Adding microseconds for the MRT Extended Header */ - if (type == MSG_PROTOCOL_BGP4MP_ET) - stream_putl (obuf, msecs); + /* Adding microseconds for the MRT Extended Header */ + if (type == MSG_PROTOCOL_BGP4MP_ET) + stream_putl(obuf, msecs); } -static void -bgp_dump_set_size (struct stream *s, int type) +static void bgp_dump_set_size(struct stream *s, int type) { - /* - * The BGP_DUMP_HEADER_SIZE stay at 12 event when ET: - * "The Microsecond Timestamp is included in the computation - * of the Length field value." (RFC6396 2011) - */ - stream_putl_at (s, 8, stream_get_endp (s) - BGP_DUMP_HEADER_SIZE); + /* + * The BGP_DUMP_HEADER_SIZE stay at 12 event when ET: + * "The Microsecond Timestamp is included in the computation + * of the Length field value." (RFC6396 2011) + */ + stream_putl_at(s, 8, stream_get_endp(s) - BGP_DUMP_HEADER_SIZE); } -static void -bgp_dump_routes_index_table(struct bgp *bgp) +static void bgp_dump_routes_index_table(struct bgp *bgp) { - struct peer *peer; - struct listnode *node; - uint16_t peerno = 1; - struct stream *obuf; - - obuf = bgp_dump_obuf; - stream_reset (obuf); - - /* MRT header */ - bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_PEER_INDEX_TABLE, - BGP_DUMP_ROUTES); - - /* Collector BGP ID */ - stream_put_in_addr (obuf, &bgp->router_id); - - /* View name */ - if(bgp->name) - { - stream_putw (obuf, strlen(bgp->name)); - stream_put(obuf, bgp->name, strlen(bgp->name)); - } - else - { - stream_putw(obuf, 0); - } - - /* Peer count ( plus one extra internal peer ) */ - stream_putw (obuf, listcount(bgp->peer) + 1); - - /* Populate fake peer at index 0, for locally originated routes */ - /* Peer type (IPv4) */ - stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP); - /* Peer BGP ID (0.0.0.0) */ - stream_putl (obuf, 0); - /* Peer IP address (0.0.0.0) */ - stream_putl (obuf, 0); - /* Peer ASN (0) */ - stream_putl (obuf, 0); - - /* Walk down all peers */ - for(ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer)) - { + struct peer *peer; + struct listnode *node; + uint16_t peerno = 1; + struct stream *obuf; + + obuf = bgp_dump_obuf; + stream_reset(obuf); + + /* MRT header */ + bgp_dump_header(obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_PEER_INDEX_TABLE, + BGP_DUMP_ROUTES); + + /* Collector BGP ID */ + stream_put_in_addr(obuf, &bgp->router_id); + + /* View name */ + if (bgp->name) { + stream_putw(obuf, strlen(bgp->name)); + stream_put(obuf, bgp->name, strlen(bgp->name)); + } else { + stream_putw(obuf, 0); + } - /* Peer's type */ - if (sockunion_family(&peer->su) == AF_INET) - { - stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP); - } - else if (sockunion_family(&peer->su) == AF_INET6) - { - stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP6); - } - - /* Peer's BGP ID */ - stream_put_in_addr (obuf, &peer->remote_id); - - /* Peer's IP address */ - if (sockunion_family(&peer->su) == AF_INET) - { - stream_put_in_addr (obuf, &peer->su.sin.sin_addr); - } - else if (sockunion_family(&peer->su) == AF_INET6) - { - stream_write (obuf, (u_char *)&peer->su.sin6.sin6_addr, - IPV6_MAX_BYTELEN); - } - - /* Peer's AS number. */ - /* Note that, as this is an AS4 compliant quagga, the RIB is always AS4 */ - stream_putl (obuf, peer->as); - - /* Store the peer number for this peer */ - peer->table_dump_index = peerno; - peerno++; - } + /* Peer count ( plus one extra internal peer ) */ + stream_putw(obuf, listcount(bgp->peer) + 1); + + /* Populate fake peer at index 0, for locally originated routes */ + /* Peer type (IPv4) */ + stream_putc(obuf, + TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4 + + TABLE_DUMP_V2_PEER_INDEX_TABLE_IP); + /* Peer BGP ID (0.0.0.0) */ + stream_putl(obuf, 0); + /* Peer IP address (0.0.0.0) */ + stream_putl(obuf, 0); + /* Peer ASN (0) */ + stream_putl(obuf, 0); + + /* Walk down all peers */ + for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) { + + /* Peer's type */ + if (sockunion_family(&peer->su) == AF_INET) { + stream_putc( + obuf, + TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4 + + TABLE_DUMP_V2_PEER_INDEX_TABLE_IP); + } else if (sockunion_family(&peer->su) == AF_INET6) { + stream_putc( + obuf, + TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4 + + TABLE_DUMP_V2_PEER_INDEX_TABLE_IP6); + } + + /* Peer's BGP ID */ + stream_put_in_addr(obuf, &peer->remote_id); + + /* Peer's IP address */ + if (sockunion_family(&peer->su) == AF_INET) { + stream_put_in_addr(obuf, &peer->su.sin.sin_addr); + } else if (sockunion_family(&peer->su) == AF_INET6) { + stream_write(obuf, (u_char *)&peer->su.sin6.sin6_addr, + IPV6_MAX_BYTELEN); + } + + /* Peer's AS number. */ + /* Note that, as this is an AS4 compliant quagga, the RIB is + * always AS4 */ + stream_putl(obuf, peer->as); + + /* Store the peer number for this peer */ + peer->table_dump_index = peerno; + peerno++; + } - bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2); + bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2); - fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp); - fflush (bgp_dump_routes.fp); + fwrite(STREAM_DATA(obuf), stream_get_endp(obuf), 1, bgp_dump_routes.fp); + fflush(bgp_dump_routes.fp); } -static struct bgp_info * -bgp_dump_route_node_record (int afi, struct bgp_node *rn, - struct bgp_info *info, unsigned int seq) +static struct bgp_info *bgp_dump_route_node_record(int afi, struct bgp_node *rn, + struct bgp_info *info, + unsigned int seq) { - struct stream *obuf; - size_t sizep; - size_t endp; - - obuf = bgp_dump_obuf; - stream_reset (obuf); - - /* MRT header */ - if (afi == AFI_IP) - bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV4_UNICAST, - BGP_DUMP_ROUTES); - else if (afi == AFI_IP6) - bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV6_UNICAST, - BGP_DUMP_ROUTES); - - /* Sequence number */ - stream_putl (obuf, seq); - - /* Prefix length */ - stream_putc (obuf, rn->p.prefixlen); - - /* Prefix */ - if (afi == AFI_IP) - { - /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */ - stream_write (obuf, (u_char *)&rn->p.u.prefix4, (rn->p.prefixlen+7)/8); - } - else if (afi == AFI_IP6) - { - /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */ - stream_write (obuf, (u_char *)&rn->p.u.prefix6, (rn->p.prefixlen+7)/8); - } + struct stream *obuf; + size_t sizep; + size_t endp; + + obuf = bgp_dump_obuf; + stream_reset(obuf); + + /* MRT header */ + if (afi == AFI_IP) + bgp_dump_header(obuf, MSG_TABLE_DUMP_V2, + TABLE_DUMP_V2_RIB_IPV4_UNICAST, + BGP_DUMP_ROUTES); + else if (afi == AFI_IP6) + bgp_dump_header(obuf, MSG_TABLE_DUMP_V2, + TABLE_DUMP_V2_RIB_IPV6_UNICAST, + BGP_DUMP_ROUTES); + + /* Sequence number */ + stream_putl(obuf, seq); + + /* Prefix length */ + stream_putc(obuf, rn->p.prefixlen); + + /* Prefix */ + if (afi == AFI_IP) { + /* We'll dump only the useful bits (those not 0), but have to + * align on 8 bits */ + stream_write(obuf, (u_char *)&rn->p.u.prefix4, + (rn->p.prefixlen + 7) / 8); + } else if (afi == AFI_IP6) { + /* We'll dump only the useful bits (those not 0), but have to + * align on 8 bits */ + stream_write(obuf, (u_char *)&rn->p.u.prefix6, + (rn->p.prefixlen + 7) / 8); + } - /* Save where we are now, so we can overwride the entry count later */ - sizep = stream_get_endp (obuf); + /* Save where we are now, so we can overwride the entry count later */ + sizep = stream_get_endp(obuf); - /* Entry count */ - uint16_t entry_count = 0; + /* Entry count */ + uint16_t entry_count = 0; - /* Entry count, note that this is overwritten later */ - stream_putw (obuf, 0); + /* Entry count, note that this is overwritten later */ + stream_putw(obuf, 0); - endp = stream_get_endp (obuf); - for (; info; info = info->next) - { - size_t cur_endp; + endp = stream_get_endp(obuf); + for (; info; info = info->next) { + size_t cur_endp; - /* Peer index */ - stream_putw (obuf, info->peer->table_dump_index); + /* Peer index */ + stream_putw(obuf, info->peer->table_dump_index); - /* Originated */ - stream_putl (obuf, time(NULL) - (bgp_clock() - info->uptime)); + /* Originated */ + stream_putl(obuf, time(NULL) - (bgp_clock() - info->uptime)); - /* Dump attribute. */ - /* Skip prefix & AFI/SAFI for MP_NLRI */ - bgp_dump_routes_attr (obuf, info->attr, &rn->p); + /* Dump attribute. */ + /* Skip prefix & AFI/SAFI for MP_NLRI */ + bgp_dump_routes_attr(obuf, info->attr, &rn->p); - cur_endp = stream_get_endp (obuf); - if (cur_endp > BGP_MAX_PACKET_SIZE + BGP_DUMP_MSG_HEADER - + BGP_DUMP_HEADER_SIZE) - { - stream_set_endp (obuf, endp); - break; - } + cur_endp = stream_get_endp(obuf); + if (cur_endp > BGP_MAX_PACKET_SIZE + BGP_DUMP_MSG_HEADER + + BGP_DUMP_HEADER_SIZE) { + stream_set_endp(obuf, endp); + break; + } - entry_count++; - endp = cur_endp; - } + entry_count++; + endp = cur_endp; + } - /* Overwrite the entry count, now that we know the right number */ - stream_putw_at (obuf, sizep, entry_count); + /* Overwrite the entry count, now that we know the right number */ + stream_putw_at(obuf, sizep, entry_count); - bgp_dump_set_size (obuf, MSG_TABLE_DUMP_V2); - fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp); + bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2); + fwrite(STREAM_DATA(obuf), stream_get_endp(obuf), 1, bgp_dump_routes.fp); - return info; + return info; } /* Runs under child process. */ -static unsigned int -bgp_dump_routes_func (int afi, int first_run, unsigned int seq) +static unsigned int bgp_dump_routes_func(int afi, int first_run, + unsigned int seq) { - struct bgp_info *info; - struct bgp_node *rn; - struct bgp *bgp; - struct bgp_table *table; - - bgp = bgp_get_default (); - if (!bgp) - return seq; - - if (bgp_dump_routes.fp == NULL) - return seq; - - /* Note that bgp_dump_routes_index_table will do ipv4 and ipv6 peers, - so this should only be done on the first call to bgp_dump_routes_func. - ( this function will be called once for ipv4 and once for ipv6 ) */ - if (first_run) - bgp_dump_routes_index_table(bgp); - - /* Walk down each BGP route. */ - table = bgp->rib[afi][SAFI_UNICAST]; - - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - { - info = rn->info; - while (info) - { - info = bgp_dump_route_node_record (afi, rn, info, seq); - seq++; - } - } + struct bgp_info *info; + struct bgp_node *rn; + struct bgp *bgp; + struct bgp_table *table; + + bgp = bgp_get_default(); + if (!bgp) + return seq; + + if (bgp_dump_routes.fp == NULL) + return seq; + + /* Note that bgp_dump_routes_index_table will do ipv4 and ipv6 peers, + so this should only be done on the first call to + bgp_dump_routes_func. + ( this function will be called once for ipv4 and once for ipv6 ) */ + if (first_run) + bgp_dump_routes_index_table(bgp); + + /* Walk down each BGP route. */ + table = bgp->rib[afi][SAFI_UNICAST]; + + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { + info = rn->info; + while (info) { + info = bgp_dump_route_node_record(afi, rn, info, seq); + seq++; + } + } - fflush (bgp_dump_routes.fp); + fflush(bgp_dump_routes.fp); - return seq; + return seq; } -static int -bgp_dump_interval_func (struct thread *t) +static int bgp_dump_interval_func(struct thread *t) { - struct bgp_dump *bgp_dump; - bgp_dump = THREAD_ARG (t); - bgp_dump->t_interval = NULL; - - /* Reschedule dump even if file couldn't be opened this time... */ - if (bgp_dump_open_file (bgp_dump) != NULL) - { - /* In case of bgp_dump_routes, we need special route dump function. */ - if (bgp_dump->type == BGP_DUMP_ROUTES) - { - unsigned int seq = bgp_dump_routes_func (AFI_IP, 1, 0); - bgp_dump_routes_func (AFI_IP6, 0, seq); - /* Close the file now. For a RIB dump there's no point in leaving - * it open until the next scheduled dump starts. */ - fclose(bgp_dump->fp); bgp_dump->fp = NULL; + struct bgp_dump *bgp_dump; + bgp_dump = THREAD_ARG(t); + bgp_dump->t_interval = NULL; + + /* Reschedule dump even if file couldn't be opened this time... */ + if (bgp_dump_open_file(bgp_dump) != NULL) { + /* In case of bgp_dump_routes, we need special route dump + * function. */ + if (bgp_dump->type == BGP_DUMP_ROUTES) { + unsigned int seq = bgp_dump_routes_func(AFI_IP, 1, 0); + bgp_dump_routes_func(AFI_IP6, 0, seq); + /* Close the file now. For a RIB dump there's no point + * in leaving + * it open until the next scheduled dump starts. */ + fclose(bgp_dump->fp); + bgp_dump->fp = NULL; + } } - } - /* if interval is set reschedule */ - if (bgp_dump->interval > 0) - bgp_dump_interval_add (bgp_dump, bgp_dump->interval); + /* if interval is set reschedule */ + if (bgp_dump->interval > 0) + bgp_dump_interval_add(bgp_dump, bgp_dump->interval); - return 0; + return 0; } /* Dump common information. */ -static void -bgp_dump_common (struct stream *obuf, struct peer *peer, int forceas4) +static void bgp_dump_common(struct stream *obuf, struct peer *peer, + int forceas4) { - char empty[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - - /* Source AS number and Destination AS number. */ - if (forceas4 || CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) ) - { - stream_putl (obuf, peer->as); - stream_putl (obuf, peer->local_as); - } - else - { - stream_putw (obuf, peer->as); - stream_putw (obuf, peer->local_as); - } - - if (peer->su.sa.sa_family == AF_INET) - { - stream_putw (obuf, peer->ifindex); - stream_putw (obuf, AFI_IP); - - stream_put (obuf, &peer->su.sin.sin_addr, IPV4_MAX_BYTELEN); - - if (peer->su_local) - stream_put (obuf, &peer->su_local->sin.sin_addr, IPV4_MAX_BYTELEN); - else - stream_put (obuf, empty, IPV4_MAX_BYTELEN); - } - else if (peer->su.sa.sa_family == AF_INET6) - { - /* Interface Index and Address family. */ - stream_putw (obuf, peer->ifindex); - stream_putw (obuf, AFI_IP6); - - /* Source IP Address and Destination IP Address. */ - stream_put (obuf, &peer->su.sin6.sin6_addr, IPV6_MAX_BYTELEN); + char empty[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + /* Source AS number and Destination AS number. */ + if (forceas4 || CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)) { + stream_putl(obuf, peer->as); + stream_putl(obuf, peer->local_as); + } else { + stream_putw(obuf, peer->as); + stream_putw(obuf, peer->local_as); + } - if (peer->su_local) - stream_put (obuf, &peer->su_local->sin6.sin6_addr, IPV6_MAX_BYTELEN); - else - stream_put (obuf, empty, IPV6_MAX_BYTELEN); - } + if (peer->su.sa.sa_family == AF_INET) { + stream_putw(obuf, peer->ifindex); + stream_putw(obuf, AFI_IP); + + stream_put(obuf, &peer->su.sin.sin_addr, IPV4_MAX_BYTELEN); + + if (peer->su_local) + stream_put(obuf, &peer->su_local->sin.sin_addr, + IPV4_MAX_BYTELEN); + else + stream_put(obuf, empty, IPV4_MAX_BYTELEN); + } else if (peer->su.sa.sa_family == AF_INET6) { + /* Interface Index and Address family. */ + stream_putw(obuf, peer->ifindex); + stream_putw(obuf, AFI_IP6); + + /* Source IP Address and Destination IP Address. */ + stream_put(obuf, &peer->su.sin6.sin6_addr, IPV6_MAX_BYTELEN); + + if (peer->su_local) + stream_put(obuf, &peer->su_local->sin6.sin6_addr, + IPV6_MAX_BYTELEN); + else + stream_put(obuf, empty, IPV6_MAX_BYTELEN); + } } /* Dump BGP status change. */ -void -bgp_dump_state (struct peer *peer, int status_old, int status_new) +void bgp_dump_state(struct peer *peer, int status_old, int status_new) { - struct stream *obuf; + struct stream *obuf; - /* If dump file pointer is disabled return immediately. */ - if (bgp_dump_all.fp == NULL) - return; + /* If dump file pointer is disabled return immediately. */ + if (bgp_dump_all.fp == NULL) + return; - /* Make dump stream. */ - obuf = bgp_dump_obuf; - stream_reset (obuf); + /* Make dump stream. */ + obuf = bgp_dump_obuf; + stream_reset(obuf); - bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE_AS4, - bgp_dump_all.type); - bgp_dump_common (obuf, peer, 1);/* force this in as4speak*/ + bgp_dump_header(obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE_AS4, + bgp_dump_all.type); + bgp_dump_common(obuf, peer, 1); /* force this in as4speak*/ - stream_putw (obuf, status_old); - stream_putw (obuf, status_new); + stream_putw(obuf, status_old); + stream_putw(obuf, status_new); - /* Set length. */ - bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP); + /* Set length. */ + bgp_dump_set_size(obuf, MSG_PROTOCOL_BGP4MP); - /* Write to the stream. */ - fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_all.fp); - fflush (bgp_dump_all.fp); + /* Write to the stream. */ + fwrite(STREAM_DATA(obuf), stream_get_endp(obuf), 1, bgp_dump_all.fp); + fflush(bgp_dump_all.fp); } -static void -bgp_dump_packet_func (struct bgp_dump *bgp_dump, struct peer *peer, - struct stream *packet) +static void bgp_dump_packet_func(struct bgp_dump *bgp_dump, struct peer *peer, + struct stream *packet) { - struct stream *obuf; - - /* If dump file pointer is disabled return immediately. */ - if (bgp_dump->fp == NULL) - return; - - /* Make dump stream. */ - obuf = bgp_dump_obuf; - stream_reset (obuf); + struct stream *obuf; + + /* If dump file pointer is disabled return immediately. */ + if (bgp_dump->fp == NULL) + return; + + /* Make dump stream. */ + obuf = bgp_dump_obuf; + stream_reset(obuf); + + /* Dump header and common part. */ + if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)) { + bgp_dump_header(obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE_AS4, + bgp_dump->type); + } else { + bgp_dump_header(obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE, + bgp_dump->type); + } + bgp_dump_common(obuf, peer, 0); - /* Dump header and common part. */ - if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) ) - { - bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE_AS4, - bgp_dump->type); - } - else - { - bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE, - bgp_dump->type); - } - bgp_dump_common (obuf, peer, 0); + /* Packet contents. */ + stream_put(obuf, STREAM_DATA(packet), stream_get_endp(packet)); - /* Packet contents. */ - stream_put (obuf, STREAM_DATA (packet), stream_get_endp (packet)); - - /* Set length. */ - bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP); + /* Set length. */ + bgp_dump_set_size(obuf, MSG_PROTOCOL_BGP4MP); - /* Write to the stream. */ - fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump->fp); - fflush (bgp_dump->fp); + /* Write to the stream. */ + fwrite(STREAM_DATA(obuf), stream_get_endp(obuf), 1, bgp_dump->fp); + fflush(bgp_dump->fp); } /* Called from bgp_packet.c when BGP packet is received. */ -void -bgp_dump_packet (struct peer *peer, int type, struct stream *packet) +void bgp_dump_packet(struct peer *peer, int type, struct stream *packet) { - /* bgp_dump_all. */ - bgp_dump_packet_func (&bgp_dump_all, peer, packet); + /* bgp_dump_all. */ + bgp_dump_packet_func(&bgp_dump_all, peer, packet); - /* bgp_dump_updates. */ - if (type == BGP_MSG_UPDATE) - bgp_dump_packet_func (&bgp_dump_updates, peer, packet); + /* bgp_dump_updates. */ + if (type == BGP_MSG_UPDATE) + bgp_dump_packet_func(&bgp_dump_updates, peer, packet); } -static unsigned int -bgp_dump_parse_time (const char *str) +static unsigned int bgp_dump_parse_time(const char *str) { - int i; - int len; - int seen_h; - int seen_m; - int time; - unsigned int total; - - time = 0; - total = 0; - seen_h = 0; - seen_m = 0; - len = strlen (str); - - for (i = 0; i < len; i++) - { - if (isdigit ((int) str[i])) - { - time *= 10; - time += str[i] - '0'; + int i; + int len; + int seen_h; + int seen_m; + int time; + unsigned int total; + + time = 0; + total = 0; + seen_h = 0; + seen_m = 0; + len = strlen(str); + + for (i = 0; i < len; i++) { + if (isdigit((int)str[i])) { + time *= 10; + time += str[i] - '0'; + } else if (str[i] == 'H' || str[i] == 'h') { + if (seen_h) + return 0; + if (seen_m) + return 0; + total += time * 60 * 60; + time = 0; + seen_h = 1; + } else if (str[i] == 'M' || str[i] == 'm') { + if (seen_m) + return 0; + total += time * 60; + time = 0; + seen_m = 1; + } else + return 0; } - else if (str[i] == 'H' || str[i] == 'h') - { - if (seen_h) - return 0; - if (seen_m) - return 0; - total += time * 60 *60; - time = 0; - seen_h = 1; - } - else if (str[i] == 'M' || str[i] == 'm') - { - if (seen_m) - return 0; - total += time * 60; - time = 0; - seen_m = 1; - } - else - return 0; - } - return total + time; + return total + time; } -static int -bgp_dump_set (struct vty *vty, struct bgp_dump *bgp_dump, - enum bgp_dump_type type, const char *path, - const char *interval_str) +static int bgp_dump_set(struct vty *vty, struct bgp_dump *bgp_dump, + enum bgp_dump_type type, const char *path, + const char *interval_str) { - unsigned int interval; - - /* Don't schedule duplicate dumps if the dump command is given twice */ - if (bgp_dump->filename && strcmp(path, bgp_dump->filename) == 0 - && type == bgp_dump->type) - { - if (interval_str) - { - if (bgp_dump->interval_str && - strcmp(bgp_dump->interval_str, interval_str) == 0) - return CMD_SUCCESS; - } - else - { - if (!bgp_dump->interval_str) - return CMD_SUCCESS; - } - } - - /* Removing previous config */ - bgp_dump_unset(bgp_dump); - - if (interval_str) - { - /* Check interval string. */ - interval = bgp_dump_parse_time (interval_str); - if (interval == 0) - { - vty_out (vty, "Malformed interval string\n"); - return CMD_WARNING_CONFIG_FAILED; + unsigned int interval; + + /* Don't schedule duplicate dumps if the dump command is given twice */ + if (bgp_dump->filename && strcmp(path, bgp_dump->filename) == 0 + && type == bgp_dump->type) { + if (interval_str) { + if (bgp_dump->interval_str + && strcmp(bgp_dump->interval_str, interval_str) + == 0) + return CMD_SUCCESS; + } else { + if (!bgp_dump->interval_str) + return CMD_SUCCESS; + } } - /* Setting interval string */ - bgp_dump->interval_str = XSTRDUP(MTYPE_BGP_DUMP_STR, interval_str); - } - else - { - interval = 0; - } + /* Removing previous config */ + bgp_dump_unset(bgp_dump); + + if (interval_str) { + /* Check interval string. */ + interval = bgp_dump_parse_time(interval_str); + if (interval == 0) { + vty_out(vty, "Malformed interval string\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Setting interval string */ + bgp_dump->interval_str = + XSTRDUP(MTYPE_BGP_DUMP_STR, interval_str); + } else { + interval = 0; + } - /* Set type. */ - bgp_dump->type = type; + /* Set type. */ + bgp_dump->type = type; - /* Set interval */ - bgp_dump->interval = interval; + /* Set interval */ + bgp_dump->interval = interval; - /* Set file name. */ - bgp_dump->filename = XSTRDUP (MTYPE_BGP_DUMP_STR, path); + /* Set file name. */ + bgp_dump->filename = XSTRDUP(MTYPE_BGP_DUMP_STR, path); - /* Create interval thread. */ - bgp_dump_interval_add (bgp_dump, interval); + /* Create interval thread. */ + bgp_dump_interval_add(bgp_dump, interval); - /* This should be called when interval is expired. */ - bgp_dump_open_file (bgp_dump); + /* This should be called when interval is expired. */ + bgp_dump_open_file(bgp_dump); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -bgp_dump_unset (struct bgp_dump *bgp_dump) +static int bgp_dump_unset(struct bgp_dump *bgp_dump) { - /* Removing file name. */ - if (bgp_dump->filename) - { - XFREE(MTYPE_BGP_DUMP_STR, bgp_dump->filename); - bgp_dump->filename = NULL; - } + /* Removing file name. */ + if (bgp_dump->filename) { + XFREE(MTYPE_BGP_DUMP_STR, bgp_dump->filename); + bgp_dump->filename = NULL; + } - /* Closing file. */ - if (bgp_dump->fp) - { - fclose (bgp_dump->fp); - bgp_dump->fp = NULL; - } + /* Closing file. */ + if (bgp_dump->fp) { + fclose(bgp_dump->fp); + bgp_dump->fp = NULL; + } - /* Removing interval thread. */ - if (bgp_dump->t_interval) - { - thread_cancel (bgp_dump->t_interval); - bgp_dump->t_interval = NULL; - } + /* Removing interval thread. */ + if (bgp_dump->t_interval) { + thread_cancel(bgp_dump->t_interval); + bgp_dump->t_interval = NULL; + } - bgp_dump->interval = 0; + bgp_dump->interval = 0; - /* Removing interval string. */ - if (bgp_dump->interval_str) - { - XFREE(MTYPE_BGP_DUMP_STR, bgp_dump->interval_str); - bgp_dump->interval_str = NULL; - } - - return CMD_SUCCESS; + /* Removing interval string. */ + if (bgp_dump->interval_str) { + XFREE(MTYPE_BGP_DUMP_STR, bgp_dump->interval_str); + bgp_dump->interval_str = NULL; + } + + return CMD_SUCCESS; } DEFUN (dump_bgp_all, @@ -744,40 +701,39 @@ DEFUN (dump_bgp_all, "Output filename\n" "Interval of output\n") { - int idx_dump_routes = 2; - int idx_path = 3; - int idx_interval = 4; - int bgp_dump_type = 0; - const char *interval = NULL; - struct bgp_dump *bgp_dump_struct = NULL; - const struct bgp_dump_type_map *map = NULL; - - for (map = bgp_dump_type_map; map->str; map++) - if (strmatch(argv[idx_dump_routes]->text, map->str)) - bgp_dump_type = map->type; - - switch (bgp_dump_type) - { - case BGP_DUMP_ALL: - case BGP_DUMP_ALL_ET: - bgp_dump_struct = &bgp_dump_all; - break; - case BGP_DUMP_UPDATES: - case BGP_DUMP_UPDATES_ET: - bgp_dump_struct = &bgp_dump_updates; - break; - case BGP_DUMP_ROUTES: - default: - bgp_dump_struct = &bgp_dump_routes; - break; - } + int idx_dump_routes = 2; + int idx_path = 3; + int idx_interval = 4; + int bgp_dump_type = 0; + const char *interval = NULL; + struct bgp_dump *bgp_dump_struct = NULL; + const struct bgp_dump_type_map *map = NULL; + + for (map = bgp_dump_type_map; map->str; map++) + if (strmatch(argv[idx_dump_routes]->text, map->str)) + bgp_dump_type = map->type; + + switch (bgp_dump_type) { + case BGP_DUMP_ALL: + case BGP_DUMP_ALL_ET: + bgp_dump_struct = &bgp_dump_all; + break; + case BGP_DUMP_UPDATES: + case BGP_DUMP_UPDATES_ET: + bgp_dump_struct = &bgp_dump_updates; + break; + case BGP_DUMP_ROUTES: + default: + bgp_dump_struct = &bgp_dump_routes; + break; + } - /* When an interval is given */ - if (argc == idx_interval + 1) - interval = argv[idx_interval]->arg; + /* When an interval is given */ + if (argc == idx_interval + 1) + interval = argv[idx_interval]->arg; - return bgp_dump_set (vty, bgp_dump_struct, bgp_dump_type, - argv[idx_path]->arg, interval); + return bgp_dump_set(vty, bgp_dump_struct, bgp_dump_type, + argv[idx_path]->arg, interval); } DEFUN (no_dump_bgp_all, @@ -794,41 +750,35 @@ DEFUN (no_dump_bgp_all, "Output filename\n" "Interval of output\n") { - int idx_dump_routes = 3; - int bgp_dump_type = 0; - const struct bgp_dump_type_map *map = NULL; - struct bgp_dump *bgp_dump_struct = NULL; - - for (map = bgp_dump_type_map; map->str; map++) - if (strmatch(argv[idx_dump_routes]->text, map->str)) - bgp_dump_type = map->type; - - switch (bgp_dump_type) - { - case BGP_DUMP_ALL: - case BGP_DUMP_ALL_ET: - bgp_dump_struct = &bgp_dump_all; - break; - case BGP_DUMP_UPDATES: - case BGP_DUMP_UPDATES_ET: - bgp_dump_struct = &bgp_dump_updates; - break; - case BGP_DUMP_ROUTES: - default: - bgp_dump_struct = &bgp_dump_routes; - break; - } + int idx_dump_routes = 3; + int bgp_dump_type = 0; + const struct bgp_dump_type_map *map = NULL; + struct bgp_dump *bgp_dump_struct = NULL; + + for (map = bgp_dump_type_map; map->str; map++) + if (strmatch(argv[idx_dump_routes]->text, map->str)) + bgp_dump_type = map->type; + + switch (bgp_dump_type) { + case BGP_DUMP_ALL: + case BGP_DUMP_ALL_ET: + bgp_dump_struct = &bgp_dump_all; + break; + case BGP_DUMP_UPDATES: + case BGP_DUMP_UPDATES_ET: + bgp_dump_struct = &bgp_dump_updates; + break; + case BGP_DUMP_ROUTES: + default: + bgp_dump_struct = &bgp_dump_routes; + break; + } - return bgp_dump_unset (bgp_dump_struct); + return bgp_dump_unset(bgp_dump_struct); } /* BGP node structure. */ -static struct cmd_node bgp_dump_node = -{ - DUMP_NODE, - "", - 1 -}; +static struct cmd_node bgp_dump_node = {DUMP_NODE, "", 1}; #if 0 char * @@ -856,72 +806,69 @@ config_time2str (unsigned int interval) } #endif -static int -config_write_bgp_dump (struct vty *vty) +static int config_write_bgp_dump(struct vty *vty) { - if (bgp_dump_all.filename) - { - const char *type_str = "all"; - if (bgp_dump_all.type == BGP_DUMP_ALL_ET) - type_str = "all-et"; - - if (bgp_dump_all.interval_str) - vty_out (vty, "dump bgp %s %s %s\n", type_str, - bgp_dump_all.filename,bgp_dump_all.interval_str); - else - vty_out (vty, "dump bgp %s %s\n", type_str, - bgp_dump_all.filename); - } - if (bgp_dump_updates.filename) - { - const char *type_str = "updates"; - if (bgp_dump_updates.type == BGP_DUMP_UPDATES_ET) - type_str = "updates-et"; - - if (bgp_dump_updates.interval_str) - vty_out (vty, "dump bgp %s %s %s\n", type_str, - bgp_dump_updates.filename,bgp_dump_updates.interval_str); - else - vty_out (vty, "dump bgp %s %s\n", type_str, - bgp_dump_updates.filename); - } - if (bgp_dump_routes.filename) - { - if (bgp_dump_routes.interval_str) - vty_out (vty, "dump bgp routes-mrt %s %s\n", - bgp_dump_routes.filename,bgp_dump_routes.interval_str); - else - vty_out (vty, "dump bgp routes-mrt %s\n", - bgp_dump_routes.filename); - - } - return 0; + if (bgp_dump_all.filename) { + const char *type_str = "all"; + if (bgp_dump_all.type == BGP_DUMP_ALL_ET) + type_str = "all-et"; + + if (bgp_dump_all.interval_str) + vty_out(vty, "dump bgp %s %s %s\n", type_str, + bgp_dump_all.filename, + bgp_dump_all.interval_str); + else + vty_out(vty, "dump bgp %s %s\n", type_str, + bgp_dump_all.filename); + } + if (bgp_dump_updates.filename) { + const char *type_str = "updates"; + if (bgp_dump_updates.type == BGP_DUMP_UPDATES_ET) + type_str = "updates-et"; + + if (bgp_dump_updates.interval_str) + vty_out(vty, "dump bgp %s %s %s\n", type_str, + bgp_dump_updates.filename, + bgp_dump_updates.interval_str); + else + vty_out(vty, "dump bgp %s %s\n", type_str, + bgp_dump_updates.filename); + } + if (bgp_dump_routes.filename) { + if (bgp_dump_routes.interval_str) + vty_out(vty, "dump bgp routes-mrt %s %s\n", + bgp_dump_routes.filename, + bgp_dump_routes.interval_str); + else + vty_out(vty, "dump bgp routes-mrt %s\n", + bgp_dump_routes.filename); + } + return 0; } /* Initialize BGP packet dump functionality. */ -void -bgp_dump_init (void) +void bgp_dump_init(void) { - memset (&bgp_dump_all, 0, sizeof (struct bgp_dump)); - memset (&bgp_dump_updates, 0, sizeof (struct bgp_dump)); - memset (&bgp_dump_routes, 0, sizeof (struct bgp_dump)); + memset(&bgp_dump_all, 0, sizeof(struct bgp_dump)); + memset(&bgp_dump_updates, 0, sizeof(struct bgp_dump)); + memset(&bgp_dump_routes, 0, sizeof(struct bgp_dump)); - bgp_dump_obuf = stream_new ((BGP_MAX_PACKET_SIZE << 1) - + BGP_DUMP_MSG_HEADER + BGP_DUMP_HEADER_SIZE); + bgp_dump_obuf = + stream_new((BGP_MAX_PACKET_SIZE << 1) + BGP_DUMP_MSG_HEADER + + BGP_DUMP_HEADER_SIZE); - install_node (&bgp_dump_node, config_write_bgp_dump); + install_node(&bgp_dump_node, config_write_bgp_dump); - install_element (CONFIG_NODE, &dump_bgp_all_cmd); - install_element (CONFIG_NODE, &no_dump_bgp_all_cmd); + install_element(CONFIG_NODE, &dump_bgp_all_cmd); + install_element(CONFIG_NODE, &no_dump_bgp_all_cmd); } -void -bgp_dump_finish (void) +void bgp_dump_finish(void) { - bgp_dump_unset (&bgp_dump_all); - bgp_dump_unset (&bgp_dump_updates); - bgp_dump_unset (&bgp_dump_routes); + bgp_dump_unset(&bgp_dump_all); + bgp_dump_unset(&bgp_dump_updates); + bgp_dump_unset(&bgp_dump_routes); - stream_free (bgp_dump_obuf); - bgp_dump_obuf = NULL; + stream_free(bgp_dump_obuf); + bgp_dump_obuf = NULL; } diff --git a/bgpd/bgp_dump.h b/bgpd/bgp_dump.h index a54388fef..f73081b2e 100644 --- a/bgpd/bgp_dump.h +++ b/bgpd/bgp_dump.h @@ -49,9 +49,9 @@ #define TABLE_DUMP_V2_PEER_INDEX_TABLE_AS2 0 #define TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4 2 -extern void bgp_dump_init (void); -extern void bgp_dump_finish (void); -extern void bgp_dump_state (struct peer *, int, int); -extern void bgp_dump_packet (struct peer *, int, struct stream *); +extern void bgp_dump_init(void); +extern void bgp_dump_finish(void); +extern void bgp_dump_state(struct peer *, int, int); +extern void bgp_dump_packet(struct peer *, int, struct stream *); #endif /* _QUAGGA_BGP_DUMP_H */ diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index 934921434..7ac16896a 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -36,29 +36,26 @@ static struct hash *ecomhash; /* Allocate a new ecommunities. */ -struct ecommunity * -ecommunity_new (void) +struct ecommunity *ecommunity_new(void) { - return (struct ecommunity *) XCALLOC (MTYPE_ECOMMUNITY, - sizeof (struct ecommunity)); + return (struct ecommunity *)XCALLOC(MTYPE_ECOMMUNITY, + sizeof(struct ecommunity)); } /* Allocate ecommunities. */ -void -ecommunity_free (struct ecommunity **ecom) +void ecommunity_free(struct ecommunity **ecom) { - if ((*ecom)->val) - XFREE (MTYPE_ECOMMUNITY_VAL, (*ecom)->val); - if ((*ecom)->str) - XFREE (MTYPE_ECOMMUNITY_STR, (*ecom)->str); - XFREE (MTYPE_ECOMMUNITY, *ecom); - ecom = NULL; + if ((*ecom)->val) + XFREE(MTYPE_ECOMMUNITY_VAL, (*ecom)->val); + if ((*ecom)->str) + XFREE(MTYPE_ECOMMUNITY_STR, (*ecom)->str); + XFREE(MTYPE_ECOMMUNITY, *ecom); + ecom = NULL; } -static void -ecommunity_hash_free (struct ecommunity *ecom) +static void ecommunity_hash_free(struct ecommunity *ecom) { - ecommunity_free(&ecom); + ecommunity_free(&ecom); } @@ -67,465 +64,425 @@ ecommunity_hash_free (struct ecommunity *ecom) structure, we don't add the value. Newly added value is sorted by numerical order. When the value is added to the structure return 1 else return 0. */ -int -ecommunity_add_val (struct ecommunity *ecom, struct ecommunity_val *eval) +int ecommunity_add_val(struct ecommunity *ecom, struct ecommunity_val *eval) { - u_int8_t *p; - int ret; - int c; - - /* When this is fist value, just add it. */ - if (ecom->val == NULL) - { - ecom->size++; - ecom->val = XMALLOC (MTYPE_ECOMMUNITY_VAL, ecom_length (ecom)); - memcpy (ecom->val, eval->val, ECOMMUNITY_SIZE); - return 1; - } - - /* If the value already exists in the structure return 0. */ - c = 0; - for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) - { - ret = memcmp (p, eval->val, ECOMMUNITY_SIZE); - if (ret == 0) - return 0; - if (ret > 0) - break; - } - - /* Add the value to the structure with numerical sorting. */ - ecom->size++; - ecom->val = XREALLOC (MTYPE_ECOMMUNITY_VAL, ecom->val, ecom_length (ecom)); - - memmove (ecom->val + (c + 1) * ECOMMUNITY_SIZE, - ecom->val + c * ECOMMUNITY_SIZE, - (ecom->size - 1 - c) * ECOMMUNITY_SIZE); - memcpy (ecom->val + c * ECOMMUNITY_SIZE, eval->val, ECOMMUNITY_SIZE); - - return 1; + u_int8_t *p; + int ret; + int c; + + /* When this is fist value, just add it. */ + if (ecom->val == NULL) { + ecom->size++; + ecom->val = XMALLOC(MTYPE_ECOMMUNITY_VAL, ecom_length(ecom)); + memcpy(ecom->val, eval->val, ECOMMUNITY_SIZE); + return 1; + } + + /* If the value already exists in the structure return 0. */ + c = 0; + for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) { + ret = memcmp(p, eval->val, ECOMMUNITY_SIZE); + if (ret == 0) + return 0; + if (ret > 0) + break; + } + + /* Add the value to the structure with numerical sorting. */ + ecom->size++; + ecom->val = + XREALLOC(MTYPE_ECOMMUNITY_VAL, ecom->val, ecom_length(ecom)); + + memmove(ecom->val + (c + 1) * ECOMMUNITY_SIZE, + ecom->val + c * ECOMMUNITY_SIZE, + (ecom->size - 1 - c) * ECOMMUNITY_SIZE); + memcpy(ecom->val + c * ECOMMUNITY_SIZE, eval->val, ECOMMUNITY_SIZE); + + return 1; } /* This function takes pointer to Extended Communites strucutre then create a new Extended Communities structure by uniq and sort each Extended Communities value. */ -struct ecommunity * -ecommunity_uniq_sort (struct ecommunity *ecom) +struct ecommunity *ecommunity_uniq_sort(struct ecommunity *ecom) { - int i; - struct ecommunity *new; - struct ecommunity_val *eval; - - if (! ecom) - return NULL; - - new = ecommunity_new (); - - for (i = 0; i < ecom->size; i++) - { - eval = (struct ecommunity_val *) (ecom->val + (i * ECOMMUNITY_SIZE)); - ecommunity_add_val (new, eval); - } - return new; + int i; + struct ecommunity *new; + struct ecommunity_val *eval; + + if (!ecom) + return NULL; + + new = ecommunity_new(); + + for (i = 0; i < ecom->size; i++) { + eval = (struct ecommunity_val *)(ecom->val + + (i * ECOMMUNITY_SIZE)); + ecommunity_add_val(new, eval); + } + return new; } /* Parse Extended Communites Attribute in BGP packet. */ -struct ecommunity * -ecommunity_parse (u_int8_t *pnt, u_short length) +struct ecommunity *ecommunity_parse(u_int8_t *pnt, u_short length) { - struct ecommunity tmp; - struct ecommunity *new; + struct ecommunity tmp; + struct ecommunity *new; - /* Length check. */ - if (length % ECOMMUNITY_SIZE) - return NULL; + /* Length check. */ + if (length % ECOMMUNITY_SIZE) + return NULL; - /* Prepare tmporary structure for making a new Extended Communities - Attribute. */ - tmp.size = length / ECOMMUNITY_SIZE; - tmp.val = pnt; + /* Prepare tmporary structure for making a new Extended Communities + Attribute. */ + tmp.size = length / ECOMMUNITY_SIZE; + tmp.val = pnt; - /* Create a new Extended Communities Attribute by uniq and sort each - Extended Communities value */ - new = ecommunity_uniq_sort (&tmp); + /* Create a new Extended Communities Attribute by uniq and sort each + Extended Communities value */ + new = ecommunity_uniq_sort(&tmp); - return ecommunity_intern (new); + return ecommunity_intern(new); } /* Duplicate the Extended Communities Attribute structure. */ -struct ecommunity * -ecommunity_dup (struct ecommunity *ecom) +struct ecommunity *ecommunity_dup(struct ecommunity *ecom) { - struct ecommunity *new; - - new = XCALLOC (MTYPE_ECOMMUNITY, sizeof (struct ecommunity)); - new->size = ecom->size; - if (new->size) - { - new->val = XMALLOC (MTYPE_ECOMMUNITY_VAL, ecom->size * ECOMMUNITY_SIZE); - memcpy (new->val, ecom->val, ecom->size * ECOMMUNITY_SIZE); - } - else - new->val = NULL; - return new; + struct ecommunity *new; + + new = XCALLOC(MTYPE_ECOMMUNITY, sizeof(struct ecommunity)); + new->size = ecom->size; + if (new->size) { + new->val = XMALLOC(MTYPE_ECOMMUNITY_VAL, + ecom->size * ECOMMUNITY_SIZE); + memcpy(new->val, ecom->val, ecom->size * ECOMMUNITY_SIZE); + } else + new->val = NULL; + return new; } /* Retrun string representation of communities attribute. */ -char * -ecommunity_str (struct ecommunity *ecom) +char *ecommunity_str(struct ecommunity *ecom) { - if (! ecom->str) - ecom->str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_DISPLAY, 0); - return ecom->str; + if (!ecom->str) + ecom->str = + ecommunity_ecom2str(ecom, ECOMMUNITY_FORMAT_DISPLAY, 0); + return ecom->str; } /* Merge two Extended Communities Attribute structure. */ -struct ecommunity * -ecommunity_merge (struct ecommunity *ecom1, struct ecommunity *ecom2) +struct ecommunity *ecommunity_merge(struct ecommunity *ecom1, + struct ecommunity *ecom2) { - if (ecom1->val) - ecom1->val = XREALLOC (MTYPE_ECOMMUNITY_VAL, ecom1->val, - (ecom1->size + ecom2->size) * ECOMMUNITY_SIZE); - else - ecom1->val = XMALLOC (MTYPE_ECOMMUNITY_VAL, - (ecom1->size + ecom2->size) * ECOMMUNITY_SIZE); - - memcpy (ecom1->val + (ecom1->size * ECOMMUNITY_SIZE), - ecom2->val, ecom2->size * ECOMMUNITY_SIZE); - ecom1->size += ecom2->size; - - return ecom1; + if (ecom1->val) + ecom1->val = + XREALLOC(MTYPE_ECOMMUNITY_VAL, ecom1->val, + (ecom1->size + ecom2->size) * ECOMMUNITY_SIZE); + else + ecom1->val = + XMALLOC(MTYPE_ECOMMUNITY_VAL, + (ecom1->size + ecom2->size) * ECOMMUNITY_SIZE); + + memcpy(ecom1->val + (ecom1->size * ECOMMUNITY_SIZE), ecom2->val, + ecom2->size * ECOMMUNITY_SIZE); + ecom1->size += ecom2->size; + + return ecom1; } /* Intern Extended Communities Attribute. */ -struct ecommunity * -ecommunity_intern (struct ecommunity *ecom) +struct ecommunity *ecommunity_intern(struct ecommunity *ecom) { - struct ecommunity *find; + struct ecommunity *find; - assert (ecom->refcnt == 0); + assert(ecom->refcnt == 0); - find = (struct ecommunity *) hash_get (ecomhash, ecom, hash_alloc_intern); + find = (struct ecommunity *)hash_get(ecomhash, ecom, hash_alloc_intern); - if (find != ecom) - ecommunity_free (&ecom); + if (find != ecom) + ecommunity_free(&ecom); - find->refcnt++; + find->refcnt++; - if (! find->str) - find->str = ecommunity_ecom2str (find, ECOMMUNITY_FORMAT_DISPLAY, 0); + if (!find->str) + find->str = + ecommunity_ecom2str(find, ECOMMUNITY_FORMAT_DISPLAY, 0); - return find; + return find; } /* Unintern Extended Communities Attribute. */ -void -ecommunity_unintern (struct ecommunity **ecom) +void ecommunity_unintern(struct ecommunity **ecom) { - struct ecommunity *ret; - - if ((*ecom)->refcnt) - (*ecom)->refcnt--; - - /* Pull off from hash. */ - if ((*ecom)->refcnt == 0) - { - /* Extended community must be in the hash. */ - ret = (struct ecommunity *) hash_release (ecomhash, *ecom); - assert (ret != NULL); - - ecommunity_free (ecom); - } + struct ecommunity *ret; + + if ((*ecom)->refcnt) + (*ecom)->refcnt--; + + /* Pull off from hash. */ + if ((*ecom)->refcnt == 0) { + /* Extended community must be in the hash. */ + ret = (struct ecommunity *)hash_release(ecomhash, *ecom); + assert(ret != NULL); + + ecommunity_free(ecom); + } } /* Utinity function to make hash key. */ -unsigned int -ecommunity_hash_make (void *arg) +unsigned int ecommunity_hash_make(void *arg) { - const struct ecommunity *ecom = arg; - int size = ecom->size * ECOMMUNITY_SIZE; - u_int8_t *pnt = ecom->val; - unsigned int key = 0; - int c; - - for (c = 0; c < size; c += ECOMMUNITY_SIZE) - { - key += pnt[c]; - key += pnt[c + 1]; - key += pnt[c + 2]; - key += pnt[c + 3]; - key += pnt[c + 4]; - key += pnt[c + 5]; - key += pnt[c + 6]; - key += pnt[c + 7]; - } - - return key; + const struct ecommunity *ecom = arg; + int size = ecom->size * ECOMMUNITY_SIZE; + u_int8_t *pnt = ecom->val; + unsigned int key = 0; + int c; + + for (c = 0; c < size; c += ECOMMUNITY_SIZE) { + key += pnt[c]; + key += pnt[c + 1]; + key += pnt[c + 2]; + key += pnt[c + 3]; + key += pnt[c + 4]; + key += pnt[c + 5]; + key += pnt[c + 6]; + key += pnt[c + 7]; + } + + return key; } /* Compare two Extended Communities Attribute structure. */ -int -ecommunity_cmp (const void *arg1, const void *arg2) +int ecommunity_cmp(const void *arg1, const void *arg2) { - const struct ecommunity *ecom1 = arg1; - const struct ecommunity *ecom2 = arg2; + const struct ecommunity *ecom1 = arg1; + const struct ecommunity *ecom2 = arg2; + + if (ecom1 == NULL && ecom2 == NULL) + return 1; - if (ecom1 == NULL && ecom2 == NULL) - return 1; + if (ecom1 == NULL || ecom2 == NULL) + return 0; - if (ecom1 == NULL || ecom2 == NULL) - return 0; - - return (ecom1->size == ecom2->size - && memcmp (ecom1->val, ecom2->val, ecom1->size * ECOMMUNITY_SIZE) == 0); + return (ecom1->size == ecom2->size + && memcmp(ecom1->val, ecom2->val, ecom1->size * ECOMMUNITY_SIZE) + == 0); } /* Initialize Extended Comminities related hash. */ -void -ecommunity_init (void) +void ecommunity_init(void) { - ecomhash = hash_create (ecommunity_hash_make, ecommunity_cmp, NULL); + ecomhash = hash_create(ecommunity_hash_make, ecommunity_cmp, NULL); } -void -ecommunity_finish (void) +void ecommunity_finish(void) { - hash_clean (ecomhash, (void (*)(void *))ecommunity_hash_free); - hash_free (ecomhash); - ecomhash = NULL; + hash_clean(ecomhash, (void (*)(void *))ecommunity_hash_free); + hash_free(ecomhash); + ecomhash = NULL; } /* Extended Communities token enum. */ -enum ecommunity_token -{ - ecommunity_token_unknown = 0, - ecommunity_token_rt, - ecommunity_token_soo, - ecommunity_token_val, +enum ecommunity_token { + ecommunity_token_unknown = 0, + ecommunity_token_rt, + ecommunity_token_soo, + ecommunity_token_val, }; /* * Encode BGP extended community from passed values. Supports types * defined in RFC 4360 and well-known sub-types. */ -static int -ecommunity_encode (u_char type, u_char sub_type, int trans, - as_t as, struct in_addr ip, u_int32_t val, - struct ecommunity_val *eval) +static int ecommunity_encode(u_char type, u_char sub_type, int trans, as_t as, + struct in_addr ip, u_int32_t val, + struct ecommunity_val *eval) { - assert (eval); - if (type == ECOMMUNITY_ENCODE_AS) - { - if (as > BGP_AS_MAX) - return -1; - } - else if (type == ECOMMUNITY_ENCODE_IP - || type == ECOMMUNITY_ENCODE_AS4) - { - if (val > UINT16_MAX) - return -1; - } - - /* Fill in the values. */ - eval->val[0] = type; - if (!trans) - eval->val[0] |= ECOMMUNITY_FLAG_NON_TRANSITIVE; - eval->val[1] = sub_type; - if (type == ECOMMUNITY_ENCODE_AS) - { - eval->val[2] = (as >> 8) & 0xff; - eval->val[3] = as & 0xff; - eval->val[4] = (val >> 24) & 0xff; - eval->val[5] = (val >> 16) & 0xff; - eval->val[6] = (val >> 8) & 0xff; - eval->val[7] = val & 0xff; - } - else if (type == ECOMMUNITY_ENCODE_IP) - { - memcpy (&eval->val[2], &ip, sizeof (struct in_addr)); - eval->val[6] = (val >> 8) & 0xff; - eval->val[7] = val & 0xff; - } - else - { - eval->val[2] = (as >> 24) & 0xff; - eval->val[3] = (as >> 16) & 0xff; - eval->val[4] = (as >> 8) & 0xff; - eval->val[5] = as & 0xff; - eval->val[6] = (val >> 8) & 0xff; - eval->val[7] = val & 0xff; - } - - return 0; + assert(eval); + if (type == ECOMMUNITY_ENCODE_AS) { + if (as > BGP_AS_MAX) + return -1; + } else if (type == ECOMMUNITY_ENCODE_IP + || type == ECOMMUNITY_ENCODE_AS4) { + if (val > UINT16_MAX) + return -1; + } + + /* Fill in the values. */ + eval->val[0] = type; + if (!trans) + eval->val[0] |= ECOMMUNITY_FLAG_NON_TRANSITIVE; + eval->val[1] = sub_type; + if (type == ECOMMUNITY_ENCODE_AS) { + eval->val[2] = (as >> 8) & 0xff; + eval->val[3] = as & 0xff; + eval->val[4] = (val >> 24) & 0xff; + eval->val[5] = (val >> 16) & 0xff; + eval->val[6] = (val >> 8) & 0xff; + eval->val[7] = val & 0xff; + } else if (type == ECOMMUNITY_ENCODE_IP) { + memcpy(&eval->val[2], &ip, sizeof(struct in_addr)); + eval->val[6] = (val >> 8) & 0xff; + eval->val[7] = val & 0xff; + } else { + eval->val[2] = (as >> 24) & 0xff; + eval->val[3] = (as >> 16) & 0xff; + eval->val[4] = (as >> 8) & 0xff; + eval->val[5] = as & 0xff; + eval->val[6] = (val >> 8) & 0xff; + eval->val[7] = val & 0xff; + } + + return 0; } /* Get next Extended Communities token from the string. */ -static const char * -ecommunity_gettoken (const char *str, struct ecommunity_val *eval, - enum ecommunity_token *token) +static const char *ecommunity_gettoken(const char *str, + struct ecommunity_val *eval, + enum ecommunity_token *token) { - int ret; - int dot = 0; - int digit = 0; - int separator = 0; - const char *p = str; - char *endptr; - struct in_addr ip; - as_t as = 0; - u_int32_t val = 0; - u_char ecomm_type; - char buf[INET_ADDRSTRLEN + 1]; - - /* Skip white space. */ - while (isspace ((int) *p)) - { - p++; - str++; - } - - /* Check the end of the line. */ - if (*p == '\0') - return NULL; - - /* "rt" and "soo" keyword parse. */ - if (! isdigit ((int) *p)) - { - /* "rt" match check. */ - if (tolower ((int) *p) == 'r') - { - p++; - if (tolower ((int) *p) == 't') - { - p++; - *token = ecommunity_token_rt; - return p; - } - if (isspace ((int) *p) || *p == '\0') - { - *token = ecommunity_token_rt; - return p; - } - goto error; + int ret; + int dot = 0; + int digit = 0; + int separator = 0; + const char *p = str; + char *endptr; + struct in_addr ip; + as_t as = 0; + u_int32_t val = 0; + u_char ecomm_type; + char buf[INET_ADDRSTRLEN + 1]; + + /* Skip white space. */ + while (isspace((int)*p)) { + p++; + str++; } - /* "soo" match check. */ - else if (tolower ((int) *p) == 's') - { - p++; - if (tolower ((int) *p) == 'o') - { - p++; - if (tolower ((int) *p) == 'o') - { - p++; - *token = ecommunity_token_soo; - return p; + + /* Check the end of the line. */ + if (*p == '\0') + return NULL; + + /* "rt" and "soo" keyword parse. */ + if (!isdigit((int)*p)) { + /* "rt" match check. */ + if (tolower((int)*p) == 'r') { + p++; + if (tolower((int)*p) == 't') { + p++; + *token = ecommunity_token_rt; + return p; + } + if (isspace((int)*p) || *p == '\0') { + *token = ecommunity_token_rt; + return p; + } + goto error; } - if (isspace ((int) *p) || *p == '\0') - { - *token = ecommunity_token_soo; - return p; + /* "soo" match check. */ + else if (tolower((int)*p) == 's') { + p++; + if (tolower((int)*p) == 'o') { + p++; + if (tolower((int)*p) == 'o') { + p++; + *token = ecommunity_token_soo; + return p; + } + if (isspace((int)*p) || *p == '\0') { + *token = ecommunity_token_soo; + return p; + } + goto error; + } + if (isspace((int)*p) || *p == '\0') { + *token = ecommunity_token_soo; + return p; + } + goto error; } - goto error; - } - if (isspace ((int) *p) || *p == '\0') - { - *token = ecommunity_token_soo; - return p; - } - goto error; + goto error; } - goto error; - } - - /* What a mess, there are several possibilities: - * - * a) A.B.C.D:MN - * b) EF:OPQR - * c) GHJK:MN - * - * A.B.C.D: Four Byte IP - * EF: Two byte ASN - * GHJK: Four-byte ASN - * MN: Two byte value - * OPQR: Four byte value - * - */ - while (isdigit ((int) *p) || *p == ':' || *p == '.') - { - if (*p == ':') - { - if (separator) - goto error; - - separator = 1; - digit = 0; - - if ((p - str) > INET_ADDRSTRLEN) - goto error; - memset (buf, 0, INET_ADDRSTRLEN + 1); - memcpy (buf, str, p - str); - - if (dot) - { - /* Parsing A.B.C.D in: - * A.B.C.D:MN - */ - ret = inet_aton (buf, &ip); - if (ret == 0) - goto error; - } - else - { - /* ASN */ - as = strtoul (buf, &endptr, 10); - if (*endptr != '\0' || as == BGP_AS4_MAX) - goto error; - } - } - else if (*p == '.') - { - if (separator) - goto error; - dot++; - if (dot > 4) - goto error; - } - else - { - digit = 1; - - /* We're past the IP/ASN part */ - if (separator) - { - val *= 10; - val += (*p - '0'); - } + + /* What a mess, there are several possibilities: + * + * a) A.B.C.D:MN + * b) EF:OPQR + * c) GHJK:MN + * + * A.B.C.D: Four Byte IP + * EF: Two byte ASN + * GHJK: Four-byte ASN + * MN: Two byte value + * OPQR: Four byte value + * + */ + while (isdigit((int)*p) || *p == ':' || *p == '.') { + if (*p == ':') { + if (separator) + goto error; + + separator = 1; + digit = 0; + + if ((p - str) > INET_ADDRSTRLEN) + goto error; + memset(buf, 0, INET_ADDRSTRLEN + 1); + memcpy(buf, str, p - str); + + if (dot) { + /* Parsing A.B.C.D in: + * A.B.C.D:MN + */ + ret = inet_aton(buf, &ip); + if (ret == 0) + goto error; + } else { + /* ASN */ + as = strtoul(buf, &endptr, 10); + if (*endptr != '\0' || as == BGP_AS4_MAX) + goto error; + } + } else if (*p == '.') { + if (separator) + goto error; + dot++; + if (dot > 4) + goto error; + } else { + digit = 1; + + /* We're past the IP/ASN part */ + if (separator) { + val *= 10; + val += (*p - '0'); + } + } + p++; } - p++; - } - - /* Low digit part must be there. */ - if (!digit || !separator) - goto error; - - /* Encode result into extended community. */ - if (dot) - ecomm_type = ECOMMUNITY_ENCODE_IP; - else if (as > BGP_AS_MAX) - ecomm_type = ECOMMUNITY_ENCODE_AS4; - else - ecomm_type = ECOMMUNITY_ENCODE_AS; - if (ecommunity_encode (ecomm_type, 0, 1, as, ip, val, eval)) - goto error; - *token = ecommunity_token_val; - return p; - - error: - *token = ecommunity_token_unknown; - return p; + + /* Low digit part must be there. */ + if (!digit || !separator) + goto error; + + /* Encode result into extended community. */ + if (dot) + ecomm_type = ECOMMUNITY_ENCODE_IP; + else if (as > BGP_AS_MAX) + ecomm_type = ECOMMUNITY_ENCODE_AS4; + else + ecomm_type = ECOMMUNITY_ENCODE_AS; + if (ecommunity_encode(ecomm_type, 0, 1, as, ip, val, eval)) + goto error; + *token = ecommunity_token_val; + return p; + +error: + *token = ecommunity_token_unknown; + return p; } -/* Convert string to extended community attribute. +/* Convert string to extended community attribute. When type is already known, please specify both str and type. str should not include keyword such as "rt" and "soo". Type is @@ -535,12 +492,12 @@ ecommunity_gettoken (const char *str, struct ecommunity_val *eval, For example route-map's "set extcommunity" command case: "rt 100:1 100:2 100:3" -> str = "100:1 100:2 100:3" - type = ECOMMUNITY_ROUTE_TARGET - keyword_included = 0 + type = ECOMMUNITY_ROUTE_TARGET + keyword_included = 0 "soo 100:1" -> str = "100:1" - type = ECOMMUNITY_SITE_ORIGIN - keyword_included = 0 + type = ECOMMUNITY_SITE_ORIGIN + keyword_included = 0 When string includes keyword for each extended community value. Please specify keyword_included as non-zero value. @@ -548,155 +505,140 @@ ecommunity_gettoken (const char *str, struct ecommunity_val *eval, For example standard extcommunity-list case: "rt 100:1 rt 100:2 soo 100:1" -> str = "rt 100:1 rt 100:2 soo 100:1" - type = 0 - keyword_include = 1 + type = 0 + keyword_include = 1 */ -struct ecommunity * -ecommunity_str2com (const char *str, int type, int keyword_included) +struct ecommunity *ecommunity_str2com(const char *str, int type, + int keyword_included) { - struct ecommunity *ecom = NULL; - enum ecommunity_token token = ecommunity_token_unknown; - struct ecommunity_val eval; - int keyword = 0; - - while ((str = ecommunity_gettoken (str, &eval, &token))) - { - switch (token) - { - case ecommunity_token_rt: - case ecommunity_token_soo: - if (! keyword_included || keyword) - { - if (ecom) - ecommunity_free (&ecom); - return NULL; - } - keyword = 1; - - if (token == ecommunity_token_rt) - { - type = ECOMMUNITY_ROUTE_TARGET; - } - if (token == ecommunity_token_soo) - { - type = ECOMMUNITY_SITE_ORIGIN; - } - break; - case ecommunity_token_val: - if (keyword_included) - { - if (! keyword) - { - if (ecom) - ecommunity_free (&ecom); - return NULL; + struct ecommunity *ecom = NULL; + enum ecommunity_token token = ecommunity_token_unknown; + struct ecommunity_val eval; + int keyword = 0; + + while ((str = ecommunity_gettoken(str, &eval, &token))) { + switch (token) { + case ecommunity_token_rt: + case ecommunity_token_soo: + if (!keyword_included || keyword) { + if (ecom) + ecommunity_free(&ecom); + return NULL; + } + keyword = 1; + + if (token == ecommunity_token_rt) { + type = ECOMMUNITY_ROUTE_TARGET; + } + if (token == ecommunity_token_soo) { + type = ECOMMUNITY_SITE_ORIGIN; + } + break; + case ecommunity_token_val: + if (keyword_included) { + if (!keyword) { + if (ecom) + ecommunity_free(&ecom); + return NULL; + } + keyword = 0; + } + if (ecom == NULL) + ecom = ecommunity_new(); + eval.val[1] = type; + ecommunity_add_val(ecom, &eval); + break; + case ecommunity_token_unknown: + default: + if (ecom) + ecommunity_free(&ecom); + return NULL; } - keyword = 0; - } - if (ecom == NULL) - ecom = ecommunity_new (); - eval.val[1] = type; - ecommunity_add_val (ecom, &eval); - break; - case ecommunity_token_unknown: - default: - if (ecom) - ecommunity_free (&ecom); - return NULL; } - } - return ecom; + return ecom; } -static int -ecommunity_rt_soo_str (char *buf, u_int8_t *pnt, int type, - int sub_type, int format) +static int ecommunity_rt_soo_str(char *buf, u_int8_t *pnt, int type, + int sub_type, int format) { - int len = 0; - const char *prefix; - - /* For parse Extended Community attribute tupple. */ - struct ecommunity_as - { - as_t as; - u_int32_t val; - } eas; - - struct ecommunity_ip - { - struct in_addr ip; - u_int16_t val; - } eip; - - - /* Determine prefix for string, if any. */ - switch (format) - { - case ECOMMUNITY_FORMAT_COMMUNITY_LIST: - prefix = (sub_type == ECOMMUNITY_ROUTE_TARGET ? "rt " : "soo "); - break; - case ECOMMUNITY_FORMAT_DISPLAY: - prefix = (sub_type == ECOMMUNITY_ROUTE_TARGET ? "RT:" : "SoO:"); - break; - case ECOMMUNITY_FORMAT_ROUTE_MAP: - prefix = ""; - break; - default: - prefix = ""; - break; - } - - /* Put string into buffer. */ - if (type == ECOMMUNITY_ENCODE_AS4) - { - eas.as = (*pnt++ << 24); - eas.as |= (*pnt++ << 16); - eas.as |= (*pnt++ << 8); - eas.as |= (*pnt++); - eas.val = (*pnt++ << 8); - eas.val |= (*pnt++); - - len = sprintf (buf, "%s%u:%u", prefix, eas.as, eas.val); - } - else if (type == ECOMMUNITY_ENCODE_AS) - { - eas.as = (*pnt++ << 8); - eas.as |= (*pnt++); - - eas.val = (*pnt++ << 24); - eas.val |= (*pnt++ << 16); - eas.val |= (*pnt++ << 8); - eas.val |= (*pnt++); - - len = sprintf (buf, "%s%u:%u", prefix, eas.as, eas.val); - } - else if (type == ECOMMUNITY_ENCODE_IP) - { - memcpy (&eip.ip, pnt, 4); - pnt += 4; - eip.val = (*pnt++ << 8); - eip.val |= (*pnt++); - - len = sprintf (buf, "%s%s:%u", prefix, inet_ntoa (eip.ip), eip.val); - } - - return len; + int len = 0; + const char *prefix; + + /* For parse Extended Community attribute tupple. */ + struct ecommunity_as { + as_t as; + u_int32_t val; + } eas; + + struct ecommunity_ip { + struct in_addr ip; + u_int16_t val; + } eip; + + + /* Determine prefix for string, if any. */ + switch (format) { + case ECOMMUNITY_FORMAT_COMMUNITY_LIST: + prefix = (sub_type == ECOMMUNITY_ROUTE_TARGET ? "rt " : "soo "); + break; + case ECOMMUNITY_FORMAT_DISPLAY: + prefix = (sub_type == ECOMMUNITY_ROUTE_TARGET ? "RT:" : "SoO:"); + break; + case ECOMMUNITY_FORMAT_ROUTE_MAP: + prefix = ""; + break; + default: + prefix = ""; + break; + } + + /* Put string into buffer. */ + if (type == ECOMMUNITY_ENCODE_AS4) { + eas.as = (*pnt++ << 24); + eas.as |= (*pnt++ << 16); + eas.as |= (*pnt++ << 8); + eas.as |= (*pnt++); + eas.val = (*pnt++ << 8); + eas.val |= (*pnt++); + + len = sprintf(buf, "%s%u:%u", prefix, eas.as, eas.val); + } else if (type == ECOMMUNITY_ENCODE_AS) { + eas.as = (*pnt++ << 8); + eas.as |= (*pnt++); + + eas.val = (*pnt++ << 24); + eas.val |= (*pnt++ << 16); + eas.val |= (*pnt++ << 8); + eas.val |= (*pnt++); + + len = sprintf(buf, "%s%u:%u", prefix, eas.as, eas.val); + } else if (type == ECOMMUNITY_ENCODE_IP) { + memcpy(&eip.ip, pnt, 4); + pnt += 4; + eip.val = (*pnt++ << 8); + eip.val |= (*pnt++); + + len = sprintf(buf, "%s%s:%u", prefix, inet_ntoa(eip.ip), + eip.val); + } + + return len; } -/* Convert extended community attribute to string. +/* Convert extended community attribute to string. Due to historical reason of industry standard implementation, there are three types of format. route-map set extcommunity format - "rt 100:1 100:2" - "soo 100:3" + "rt 100:1 100:2" + "soo 100:3" extcommunity-list - "rt 100:1 rt 100:2 soo 100:3" + "rt 100:1 rt 100:2 soo 100:3" "show [ip] bgp" and extcommunity-list regular expression matching - "RT:100:1 RT:100:2 SoO:100:3" + "RT:100:1 RT:100:2 SoO:100:3" For each formath please use below definition for format: @@ -704,213 +646,201 @@ ecommunity_rt_soo_str (char *buf, u_int8_t *pnt, int type, ECOMMUNITY_FORMAT_COMMUNITY_LIST ECOMMUNITY_FORMAT_DISPLAY - Filter is added to display only ECOMMUNITY_ROUTE_TARGET in some cases. + Filter is added to display only ECOMMUNITY_ROUTE_TARGET in some cases. 0 value displays all */ -char * -ecommunity_ecom2str (struct ecommunity *ecom, int format, int filter) +char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter) { - int i; - u_int8_t *pnt; - int type = 0; - int sub_type = 0; + int i; + u_int8_t *pnt; + int type = 0; + int sub_type = 0; #define ECOMMUNITY_STR_DEFAULT_LEN 27 - int str_size; - int str_pnt; - char *str_buf; - int len = 0; - int first = 1; - - if (ecom->size == 0) - { - str_buf = XMALLOC (MTYPE_ECOMMUNITY_STR, 1); - str_buf[0] = '\0'; - return str_buf; - } - - /* Prepare buffer. */ - str_buf = XMALLOC (MTYPE_ECOMMUNITY_STR, ECOMMUNITY_STR_DEFAULT_LEN + 1); - str_size = ECOMMUNITY_STR_DEFAULT_LEN + 1; - str_buf[0] = '\0'; - str_pnt = 0; - - for (i = 0; i < ecom->size; i++) - { - int unk_ecom = 0; - - /* Make it sure size is enough. */ - while (str_pnt + ECOMMUNITY_STR_DEFAULT_LEN >= str_size) - { - str_size *= 2; - str_buf = XREALLOC (MTYPE_ECOMMUNITY_STR, str_buf, str_size); + int str_size; + int str_pnt; + char *str_buf; + int len = 0; + int first = 1; + + if (ecom->size == 0) { + str_buf = XMALLOC(MTYPE_ECOMMUNITY_STR, 1); + str_buf[0] = '\0'; + return str_buf; + } + + /* Prepare buffer. */ + str_buf = XMALLOC(MTYPE_ECOMMUNITY_STR, ECOMMUNITY_STR_DEFAULT_LEN + 1); + str_size = ECOMMUNITY_STR_DEFAULT_LEN + 1; + str_buf[0] = '\0'; + str_pnt = 0; + + for (i = 0; i < ecom->size; i++) { + int unk_ecom = 0; + + /* Make it sure size is enough. */ + while (str_pnt + ECOMMUNITY_STR_DEFAULT_LEN >= str_size) { + str_size *= 2; + str_buf = XREALLOC(MTYPE_ECOMMUNITY_STR, str_buf, + str_size); + } + + /* Space between each value. */ + if (!first) + str_buf[str_pnt++] = ' '; + + pnt = ecom->val + (i * 8); + + /* High-order octet of type. */ + type = *pnt++; + + if (type == ECOMMUNITY_ENCODE_AS || type == ECOMMUNITY_ENCODE_IP + || type == ECOMMUNITY_ENCODE_AS4) { + /* Low-order octet of type. */ + sub_type = *pnt++; + if (sub_type != ECOMMUNITY_ROUTE_TARGET + && sub_type != ECOMMUNITY_SITE_ORIGIN) + unk_ecom = 1; + else + len = ecommunity_rt_soo_str(str_buf + str_pnt, + pnt, type, sub_type, + format); + } else if (type == ECOMMUNITY_ENCODE_OPAQUE) { + if (filter == ECOMMUNITY_ROUTE_TARGET) + continue; + if (*pnt == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP) { + uint16_t tunneltype; + memcpy(&tunneltype, pnt + 5, 2); + tunneltype = ntohs(tunneltype); + len = sprintf(str_buf + str_pnt, "ET:%d", + tunneltype); + } else + unk_ecom = 1; + } else if (type == ECOMMUNITY_ENCODE_EVPN) { + if (filter == ECOMMUNITY_ROUTE_TARGET) + continue; + if (*pnt == ECOMMUNITY_SITE_ORIGIN) { + char macaddr[6]; + pnt++; + memcpy(&macaddr, pnt, 6); + len = sprintf( + str_buf + str_pnt, + "EVPN:%02x:%02x:%02x:%02x:%02x:%02x", + macaddr[0], macaddr[1], macaddr[2], + macaddr[3], macaddr[4], macaddr[5]); + } else if (*pnt + == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY) { + u_int32_t seqnum; + u_char flags = *++pnt; + + memcpy(&seqnum, pnt + 2, 4); + seqnum = ntohl(seqnum); + if (flags + & ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY) + len = sprintf(str_buf + str_pnt, + "MM:%u, sticky MAC", + seqnum); + else + len = sprintf(str_buf + str_pnt, + "MM:%u", seqnum); + } else + unk_ecom = 1; + } else + unk_ecom = 1; + + if (unk_ecom) + len = sprintf(str_buf + str_pnt, "?"); + + str_pnt += len; + first = 0; } - /* Space between each value. */ - if (! first) - str_buf[str_pnt++] = ' '; - - pnt = ecom->val + (i * 8); - - /* High-order octet of type. */ - type = *pnt++; - - if (type == ECOMMUNITY_ENCODE_AS || - type == ECOMMUNITY_ENCODE_IP || - type == ECOMMUNITY_ENCODE_AS4) - { - /* Low-order octet of type. */ - sub_type = *pnt++; - if (sub_type != ECOMMUNITY_ROUTE_TARGET && - sub_type != ECOMMUNITY_SITE_ORIGIN) - unk_ecom = 1; - else - len = ecommunity_rt_soo_str (str_buf + str_pnt, pnt, type, - sub_type, format); - } - else if (type == ECOMMUNITY_ENCODE_OPAQUE) - { - if (filter == ECOMMUNITY_ROUTE_TARGET) - continue; - if (*pnt == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP) - { - uint16_t tunneltype; - memcpy (&tunneltype, pnt + 5, 2); - tunneltype = ntohs(tunneltype); - len = sprintf (str_buf + str_pnt, "ET:%d", tunneltype); - } - else - unk_ecom = 1; - } - else if (type == ECOMMUNITY_ENCODE_EVPN) - { - if (filter == ECOMMUNITY_ROUTE_TARGET) - continue; - if (*pnt == ECOMMUNITY_SITE_ORIGIN) - { - char macaddr[6]; - pnt++; - memcpy(&macaddr, pnt, 6); - len = sprintf(str_buf + str_pnt, "EVPN:%02x:%02x:%02x:%02x:%02x:%02x", - macaddr[0], macaddr[1], macaddr[2], - macaddr[3], macaddr[4], macaddr[5]); - } - else if (*pnt == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY) - { - u_int32_t seqnum; - u_char flags = *++pnt; - - memcpy (&seqnum, pnt + 2, 4); - seqnum = ntohl(seqnum); - if (flags & ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY) - len = sprintf (str_buf + str_pnt, "MM:%u, sticky MAC", seqnum); - else - len = sprintf (str_buf + str_pnt, "MM:%u", seqnum); - } - else - unk_ecom = 1; - } - else - unk_ecom = 1; - - if (unk_ecom) - len = sprintf (str_buf + str_pnt, "?"); - - str_pnt += len; - first = 0; - } - - return str_buf; + return str_buf; } -int -ecommunity_match (const struct ecommunity *ecom1, - const struct ecommunity *ecom2) +int ecommunity_match(const struct ecommunity *ecom1, + const struct ecommunity *ecom2) { - int i = 0; - int j = 0; - - if (ecom1 == NULL && ecom2 == NULL) - return 1; - - if (ecom1 == NULL || ecom2 == NULL) - return 0; - - if (ecom1->size < ecom2->size) - return 0; - - /* Every community on com2 needs to be on com1 for this to match */ - while (i < ecom1->size && j < ecom2->size) - { - if (memcmp (ecom1->val + i * ECOMMUNITY_SIZE, - ecom2->val + j * ECOMMUNITY_SIZE, - ECOMMUNITY_SIZE) == 0) - j++; - i++; - } - - if (j == ecom2->size) - return 1; - else - return 0; + int i = 0; + int j = 0; + + if (ecom1 == NULL && ecom2 == NULL) + return 1; + + if (ecom1 == NULL || ecom2 == NULL) + return 0; + + if (ecom1->size < ecom2->size) + return 0; + + /* Every community on com2 needs to be on com1 for this to match */ + while (i < ecom1->size && j < ecom2->size) { + if (memcmp(ecom1->val + i * ECOMMUNITY_SIZE, + ecom2->val + j * ECOMMUNITY_SIZE, ECOMMUNITY_SIZE) + == 0) + j++; + i++; + } + + if (j == ecom2->size) + return 1; + else + return 0; } /* return first occurence of type */ -extern struct ecommunity_val *ecommunity_lookup (const struct ecommunity *ecom, uint8_t type, uint8_t subtype) +extern struct ecommunity_val *ecommunity_lookup(const struct ecommunity *ecom, + uint8_t type, uint8_t subtype) { - u_int8_t *p; - int c; - - /* If the value already exists in the structure return 0. */ - c = 0; - for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) - { - if(p == NULL) - { - continue; - } - if(p[0] == type && p[1] == subtype) - return (struct ecommunity_val *)p; - } - return NULL; + u_int8_t *p; + int c; + + /* If the value already exists in the structure return 0. */ + c = 0; + for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) { + if (p == NULL) { + continue; + } + if (p[0] == type && p[1] == subtype) + return (struct ecommunity_val *)p; + } + return NULL; } /* remove ext. community matching type and subtype * return 1 on success ( removed ), 0 otherwise (not present) */ -extern int ecommunity_strip (struct ecommunity *ecom, uint8_t type, uint8_t subtype) +extern int ecommunity_strip(struct ecommunity *ecom, uint8_t type, + uint8_t subtype) { - u_int8_t *p; - int c, found = 0; - /* When this is fist value, just add it. */ - if (ecom == NULL || ecom->val == NULL) - { - return 0; - } - - /* If the value already exists in the structure return 0. */ - c = 0; - for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) - { - if (p[0] == type && p[1] == subtype) - { - found = 1; - break; - } - } - if (found == 0) - return 0; - /* Strip The selected value */ - ecom->size--; - /* size is reduced. no memmove to do */ - p = XMALLOC (MTYPE_ECOMMUNITY_VAL, ecom->size * ECOMMUNITY_SIZE); - if (c != 0) - memcpy(p, ecom->val, c * ECOMMUNITY_SIZE); - if( (ecom->size - c) != 0) - memcpy(p + (c) * ECOMMUNITY_SIZE, - ecom->val + (c +1)* ECOMMUNITY_SIZE, - (ecom->size - c) * ECOMMUNITY_SIZE); - /* shift last ecommunities */ - XFREE (MTYPE_ECOMMUNITY, ecom->val); - ecom->val = p; - return 1; + u_int8_t *p; + int c, found = 0; + /* When this is fist value, just add it. */ + if (ecom == NULL || ecom->val == NULL) { + return 0; + } + + /* If the value already exists in the structure return 0. */ + c = 0; + for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) { + if (p[0] == type && p[1] == subtype) { + found = 1; + break; + } + } + if (found == 0) + return 0; + /* Strip The selected value */ + ecom->size--; + /* size is reduced. no memmove to do */ + p = XMALLOC(MTYPE_ECOMMUNITY_VAL, ecom->size * ECOMMUNITY_SIZE); + if (c != 0) + memcpy(p, ecom->val, c * ECOMMUNITY_SIZE); + if ((ecom->size - c) != 0) + memcpy(p + (c)*ECOMMUNITY_SIZE, + ecom->val + (c + 1) * ECOMMUNITY_SIZE, + (ecom->size - c) * ECOMMUNITY_SIZE); + /* shift last ecommunities */ + XFREE(MTYPE_ECOMMUNITY, ecom->val); + ecom->val = p; + return 1; } diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h index 9281c0d99..927b1370c 100644 --- a/bgpd/bgp_ecommunity.h +++ b/bgpd/bgp_ecommunity.h @@ -56,25 +56,23 @@ #define ECOMMUNITY_FLAG_NON_TRANSITIVE 0x40 /* Extended Communities attribute. */ -struct ecommunity -{ - /* Reference counter. */ - unsigned long refcnt; +struct ecommunity { + /* Reference counter. */ + unsigned long refcnt; - /* Size of Extended Communities attribute. */ - int size; + /* Size of Extended Communities attribute. */ + int size; - /* Extended Communities value. */ - u_int8_t *val; + /* Extended Communities value. */ + u_int8_t *val; - /* Human readable format string. */ - char *str; + /* Human readable format string. */ + char *str; }; /* Extended community value is eight octet. */ -struct ecommunity_val -{ - char val[ECOMMUNITY_SIZE]; +struct ecommunity_val { + char val[ECOMMUNITY_SIZE]; }; #define ecom_length(X) ((X)->size * ECOMMUNITY_SIZE) @@ -82,72 +80,74 @@ struct ecommunity_val /* * Encode BGP Route Target AS:nn. */ -static inline void -encode_route_target_as (as_t as, u_int32_t val, - struct ecommunity_val *eval) +static inline void encode_route_target_as(as_t as, u_int32_t val, + struct ecommunity_val *eval) { - eval->val[0] = ECOMMUNITY_ENCODE_AS; - eval->val[1] = ECOMMUNITY_ROUTE_TARGET; - eval->val[2] = (as >> 8) & 0xff; - eval->val[3] = as & 0xff; - eval->val[4] = (val >> 24) & 0xff; - eval->val[5] = (val >> 16) & 0xff; - eval->val[6] = (val >> 8) & 0xff; - eval->val[7] = val & 0xff; + eval->val[0] = ECOMMUNITY_ENCODE_AS; + eval->val[1] = ECOMMUNITY_ROUTE_TARGET; + eval->val[2] = (as >> 8) & 0xff; + eval->val[3] = as & 0xff; + eval->val[4] = (val >> 24) & 0xff; + eval->val[5] = (val >> 16) & 0xff; + eval->val[6] = (val >> 8) & 0xff; + eval->val[7] = val & 0xff; } /* * Encode BGP Route Target IP:nn. */ -static inline void -encode_route_target_ip (struct in_addr ip, u_int16_t val, - struct ecommunity_val *eval) +static inline void encode_route_target_ip(struct in_addr ip, u_int16_t val, + struct ecommunity_val *eval) { - eval->val[0] = ECOMMUNITY_ENCODE_IP; - eval->val[1] = ECOMMUNITY_ROUTE_TARGET; - memcpy (&eval->val[2], &ip, sizeof (struct in_addr)); - eval->val[6] = (val >> 8) & 0xff; - eval->val[7] = val & 0xff; + eval->val[0] = ECOMMUNITY_ENCODE_IP; + eval->val[1] = ECOMMUNITY_ROUTE_TARGET; + memcpy(&eval->val[2], &ip, sizeof(struct in_addr)); + eval->val[6] = (val >> 8) & 0xff; + eval->val[7] = val & 0xff; } /* * Encode BGP Route Target AS4:nn. */ -static inline void -encode_route_target_as4 (as_t as, u_int16_t val, - struct ecommunity_val *eval) +static inline void encode_route_target_as4(as_t as, u_int16_t val, + struct ecommunity_val *eval) { - eval->val[0] = ECOMMUNITY_ENCODE_AS4; - eval->val[1] = ECOMMUNITY_ROUTE_TARGET; - eval->val[2] = (as >> 24) & 0xff; - eval->val[3] = (as >> 16) & 0xff; - eval->val[4] = (as >> 8) & 0xff; - eval->val[5] = as & 0xff; - eval->val[6] = (val >> 8) & 0xff; - eval->val[7] = val & 0xff; + eval->val[0] = ECOMMUNITY_ENCODE_AS4; + eval->val[1] = ECOMMUNITY_ROUTE_TARGET; + eval->val[2] = (as >> 24) & 0xff; + eval->val[3] = (as >> 16) & 0xff; + eval->val[4] = (as >> 8) & 0xff; + eval->val[5] = as & 0xff; + eval->val[6] = (val >> 8) & 0xff; + eval->val[7] = val & 0xff; } -extern void ecommunity_init (void); -extern void ecommunity_finish (void); -extern void ecommunity_free (struct ecommunity **); -extern struct ecommunity *ecommunity_parse (u_int8_t *, u_short); -extern struct ecommunity *ecommunity_dup (struct ecommunity *); -extern struct ecommunity *ecommunity_merge (struct ecommunity *, struct ecommunity *); -extern struct ecommunity *ecommunity_uniq_sort (struct ecommunity *); -extern struct ecommunity *ecommunity_intern (struct ecommunity *); -extern int ecommunity_cmp (const void *, const void *); -extern void ecommunity_unintern (struct ecommunity **); -extern unsigned int ecommunity_hash_make (void *); -extern struct ecommunity *ecommunity_str2com (const char *, int, int); -extern char *ecommunity_ecom2str (struct ecommunity *, int, int); -extern int ecommunity_match (const struct ecommunity *, const struct ecommunity *); -extern char *ecommunity_str (struct ecommunity *); -extern struct ecommunity_val *ecommunity_lookup (const struct ecommunity *, uint8_t, uint8_t ); -extern int ecommunity_add_val (struct ecommunity *ecom, struct ecommunity_val *eval); +extern void ecommunity_init(void); +extern void ecommunity_finish(void); +extern void ecommunity_free(struct ecommunity **); +extern struct ecommunity *ecommunity_parse(u_int8_t *, u_short); +extern struct ecommunity *ecommunity_dup(struct ecommunity *); +extern struct ecommunity *ecommunity_merge(struct ecommunity *, + struct ecommunity *); +extern struct ecommunity *ecommunity_uniq_sort(struct ecommunity *); +extern struct ecommunity *ecommunity_intern(struct ecommunity *); +extern int ecommunity_cmp(const void *, const void *); +extern void ecommunity_unintern(struct ecommunity **); +extern unsigned int ecommunity_hash_make(void *); +extern struct ecommunity *ecommunity_str2com(const char *, int, int); +extern char *ecommunity_ecom2str(struct ecommunity *, int, int); +extern int ecommunity_match(const struct ecommunity *, + const struct ecommunity *); +extern char *ecommunity_str(struct ecommunity *); +extern struct ecommunity_val *ecommunity_lookup(const struct ecommunity *, + uint8_t, uint8_t); +extern int ecommunity_add_val(struct ecommunity *ecom, + struct ecommunity_val *eval); /* for vpn */ -extern struct ecommunity *ecommunity_new (void); -extern int ecommunity_add_val (struct ecommunity *, struct ecommunity_val *); -extern int ecommunity_strip (struct ecommunity *ecom, uint8_t type, uint8_t subtype); -extern struct ecommunity *ecommunity_new (void); +extern struct ecommunity *ecommunity_new(void); +extern int ecommunity_add_val(struct ecommunity *, struct ecommunity_val *); +extern int ecommunity_strip(struct ecommunity *ecom, uint8_t type, + uint8_t subtype); +extern struct ecommunity *ecommunity_new(void); #endif /* _QUAGGA_BGP_ECOMMUNITY_H */ diff --git a/bgpd/bgp_encap_tlv.c b/bgpd/bgp_encap_tlv.c index 89194980d..5c0cc40f1 100644 --- a/bgpd/bgp_encap_tlv.c +++ b/bgpd/bgp_encap_tlv.c @@ -34,194 +34,192 @@ ***********************************************************************/ /* rfc5512 4.1 */ -static struct bgp_attr_encap_subtlv * -subtlv_encode_encap_l2tpv3_over_ip( - struct bgp_tea_subtlv_encap_l2tpv3_over_ip *st) +static struct bgp_attr_encap_subtlv *subtlv_encode_encap_l2tpv3_over_ip( + struct bgp_tea_subtlv_encap_l2tpv3_over_ip *st) { - struct bgp_attr_encap_subtlv *new; - uint8_t *p; - int total = 4 + st->cookie_length; + struct bgp_attr_encap_subtlv *new; + uint8_t *p; + int total = 4 + st->cookie_length; - /* sanity check */ - assert(st->cookie_length <= sizeof(st->cookie)); - assert(total <= 0xff); + /* sanity check */ + assert(st->cookie_length <= sizeof(st->cookie)); + assert(total <= 0xff); - new = XCALLOC(MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv) - 1 + total); - assert(new); - new->type = BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION; - new->length = total; - p = new->value; + new = XCALLOC(MTYPE_ENCAP_TLV, + sizeof(struct bgp_attr_encap_subtlv) - 1 + total); + assert(new); + new->type = BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION; + new->length = total; + p = new->value; - *p++ = (st->sessionid & 0xff000000) >> 24; - *p++ = (st->sessionid & 0xff0000) >> 16; - *p++ = (st->sessionid & 0xff00) >> 8; - *p++ = (st->sessionid & 0xff); - memcpy(p, st->cookie, st->cookie_length); - return new; + *p++ = (st->sessionid & 0xff000000) >> 24; + *p++ = (st->sessionid & 0xff0000) >> 16; + *p++ = (st->sessionid & 0xff00) >> 8; + *p++ = (st->sessionid & 0xff); + memcpy(p, st->cookie, st->cookie_length); + return new; } /* rfc5512 4.1 */ static struct bgp_attr_encap_subtlv * -subtlv_encode_encap_gre( - struct bgp_tea_subtlv_encap_gre_key *st) +subtlv_encode_encap_gre(struct bgp_tea_subtlv_encap_gre_key *st) { - struct bgp_attr_encap_subtlv *new; - uint8_t *p; - int total = 4; + struct bgp_attr_encap_subtlv *new; + uint8_t *p; + int total = 4; - assert(total <= 0xff); + assert(total <= 0xff); - new = XCALLOC(MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv) - 1 + total); - assert(new); - new->type = BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION; - new->length = total; - p = new->value; + new = XCALLOC(MTYPE_ENCAP_TLV, + sizeof(struct bgp_attr_encap_subtlv) - 1 + total); + assert(new); + new->type = BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION; + new->length = total; + p = new->value; - *p++ = (st->gre_key & 0xff000000) >> 24; - *p++ = (st->gre_key & 0xff0000) >> 16; - *p++ = (st->gre_key & 0xff00) >> 8; - *p++ = (st->gre_key & 0xff); - return new; + *p++ = (st->gre_key & 0xff000000) >> 24; + *p++ = (st->gre_key & 0xff0000) >> 16; + *p++ = (st->gre_key & 0xff00) >> 8; + *p++ = (st->gre_key & 0xff); + return new; } static struct bgp_attr_encap_subtlv * -subtlv_encode_encap_pbb( - struct bgp_tea_subtlv_encap_pbb *st) -{ - struct bgp_attr_encap_subtlv *new; - uint8_t *p; - int total = 1 + 3 + 6 + 2; /* flags + isid + madaddr + vid */ - - assert(total <= 0xff); - - new = XCALLOC(MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv) - 1 + total); - assert(new); - new->type = BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION; - new->length = total; - p = new->value; - - *p++ = (st->flag_isid? 0x80: 0) | - (st->flag_vid? 0x40: 0) | - 0; - if (st->flag_isid) { - *p = (st->isid & 0xff0000) >> 16; - *(p+1) = (st->isid & 0xff00) >> 8; - *(p+2) = (st->isid & 0xff); - } - p += 3; - memcpy(p, st->macaddr, 6); - p += 6; - if (st->flag_vid) { - *p++ = (st->vid & 0xf00) >> 8; - *p++ = st->vid & 0xff; - } - return new; +subtlv_encode_encap_pbb(struct bgp_tea_subtlv_encap_pbb *st) +{ + struct bgp_attr_encap_subtlv *new; + uint8_t *p; + int total = 1 + 3 + 6 + 2; /* flags + isid + madaddr + vid */ + + assert(total <= 0xff); + + new = XCALLOC(MTYPE_ENCAP_TLV, + sizeof(struct bgp_attr_encap_subtlv) - 1 + total); + assert(new); + new->type = BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION; + new->length = total; + p = new->value; + + *p++ = (st->flag_isid ? 0x80 : 0) | (st->flag_vid ? 0x40 : 0) | 0; + if (st->flag_isid) { + *p = (st->isid & 0xff0000) >> 16; + *(p + 1) = (st->isid & 0xff00) >> 8; + *(p + 2) = (st->isid & 0xff); + } + p += 3; + memcpy(p, st->macaddr, 6); + p += 6; + if (st->flag_vid) { + *p++ = (st->vid & 0xf00) >> 8; + *p++ = st->vid & 0xff; + } + return new; } /* rfc5512 4.2 */ static struct bgp_attr_encap_subtlv * -subtlv_encode_proto_type( - struct bgp_tea_subtlv_proto_type *st) +subtlv_encode_proto_type(struct bgp_tea_subtlv_proto_type *st) { - struct bgp_attr_encap_subtlv *new; - uint8_t *p; - int total = 2; + struct bgp_attr_encap_subtlv *new; + uint8_t *p; + int total = 2; - assert(total <= 0xff); + assert(total <= 0xff); - new = XCALLOC(MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv) - 1 + total); - assert(new); - new->type = BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE; - new->length = total; - p = new->value; + new = XCALLOC(MTYPE_ENCAP_TLV, + sizeof(struct bgp_attr_encap_subtlv) - 1 + total); + assert(new); + new->type = BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE; + new->length = total; + p = new->value; - *p++ = (st->proto & 0xff00) >> 8; - *p++ = (st->proto & 0xff); - return new; + *p++ = (st->proto & 0xff00) >> 8; + *p++ = (st->proto & 0xff); + return new; } /* rfc5512 4.3 */ static struct bgp_attr_encap_subtlv * -subtlv_encode_color( - struct bgp_tea_subtlv_color *st) +subtlv_encode_color(struct bgp_tea_subtlv_color *st) { - struct bgp_attr_encap_subtlv *new; - uint8_t *p; - int total = 8; + struct bgp_attr_encap_subtlv *new; + uint8_t *p; + int total = 8; - assert(total <= 0xff); + assert(total <= 0xff); - new = XCALLOC(MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv) - 1 + total); - assert(new); - new->type = BGP_ENCAP_SUBTLV_TYPE_COLOR; - new->length = total; - p = new->value; + new = XCALLOC(MTYPE_ENCAP_TLV, + sizeof(struct bgp_attr_encap_subtlv) - 1 + total); + assert(new); + new->type = BGP_ENCAP_SUBTLV_TYPE_COLOR; + new->length = total; + p = new->value; - *p++ = 0x03; /* transitive*/ - *p++ = 0x0b; - *p++ = 0; /* reserved */ - *p++ = 0; /* reserved */ + *p++ = 0x03; /* transitive*/ + *p++ = 0x0b; + *p++ = 0; /* reserved */ + *p++ = 0; /* reserved */ - *p++ = (st->color & 0xff000000) >> 24; - *p++ = (st->color & 0xff0000) >> 16; - *p++ = (st->color & 0xff00) >> 8; - *p++ = (st->color & 0xff); + *p++ = (st->color & 0xff000000) >> 24; + *p++ = (st->color & 0xff0000) >> 16; + *p++ = (st->color & 0xff00) >> 8; + *p++ = (st->color & 0xff); - return new; + return new; } /* rfc 5566 4. */ static struct bgp_attr_encap_subtlv * -subtlv_encode_ipsec_ta( - struct bgp_tea_subtlv_ipsec_ta *st) +subtlv_encode_ipsec_ta(struct bgp_tea_subtlv_ipsec_ta *st) { - struct bgp_attr_encap_subtlv *new; - uint8_t *p; - int total = 2 + st->authenticator_length; + struct bgp_attr_encap_subtlv *new; + uint8_t *p; + int total = 2 + st->authenticator_length; - /* sanity check */ - assert(st->authenticator_length <= sizeof(st->value)); - assert(total <= 0xff); + /* sanity check */ + assert(st->authenticator_length <= sizeof(st->value)); + assert(total <= 0xff); - new = XCALLOC(MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv) - 1 + total); - assert(new); - new->type = BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA; - new->length = total; - p = new->value; + new = XCALLOC(MTYPE_ENCAP_TLV, + sizeof(struct bgp_attr_encap_subtlv) - 1 + total); + assert(new); + new->type = BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA; + new->length = total; + p = new->value; - *p++ = (st->authenticator_type & 0xff00) >> 8; - *p++ = st->authenticator_type & 0xff; - memcpy(p, st->value, st->authenticator_length); - return new; + *p++ = (st->authenticator_type & 0xff00) >> 8; + *p++ = st->authenticator_type & 0xff; + memcpy(p, st->value, st->authenticator_length); + return new; } /* draft-rosen-idr-tunnel-encaps 2.1 */ static struct bgp_attr_encap_subtlv * -subtlv_encode_remote_endpoint( - struct bgp_tea_subtlv_remote_endpoint *st) -{ - struct bgp_attr_encap_subtlv *new; - uint8_t *p; - - int total = (st->family==AF_INET?8:20); - - assert(total <= 0xff); - - new = XCALLOC(MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv) - 1 + total); - assert(new); - new->type = BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT; - new->length = total; - p = new->value; - if (st->family == AF_INET) { - memcpy (p, &(st->ip_address.v4.s_addr), 4); - p+=4; - } else { - assert (st->family == AF_INET6); - memcpy (p, &(st->ip_address.v6.s6_addr), 16); - p+=16; - } - memcpy (p, &(st->as4), 4); - return new; +subtlv_encode_remote_endpoint(struct bgp_tea_subtlv_remote_endpoint *st) +{ + struct bgp_attr_encap_subtlv *new; + uint8_t *p; + + int total = (st->family == AF_INET ? 8 : 20); + + assert(total <= 0xff); + + new = XCALLOC(MTYPE_ENCAP_TLV, + sizeof(struct bgp_attr_encap_subtlv) - 1 + total); + assert(new); + new->type = BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT; + new->length = total; + p = new->value; + if (st->family == AF_INET) { + memcpy(p, &(st->ip_address.v4.s_addr), 4); + p += 4; + } else { + assert(st->family == AF_INET6); + memcpy(p, &(st->ip_address.v6.s6_addr), 16); + p += 16; + } + memcpy(p, &(st->as4), 4); + return new; } /*********************************************************************** @@ -231,221 +229,230 @@ subtlv_encode_remote_endpoint( /* * requires "extra" and "last" to be defined in caller */ -#define ENC_SUBTLV(flag, function, field) do {\ - struct bgp_attr_encap_subtlv *new;\ - if (CHECK_FLAG(bet->valid_subtlvs, (flag))) {\ - new = function(&bet->field);\ - if (last) {\ - last->next = new;\ - } else {\ - attr->encap_subtlvs = new;\ - }\ - last = new;\ - }\ -} while (0) +#define ENC_SUBTLV(flag, function, field) \ + do { \ + struct bgp_attr_encap_subtlv *new; \ + if (CHECK_FLAG(bet->valid_subtlvs, (flag))) { \ + new = function(&bet->field); \ + if (last) { \ + last->next = new; \ + } else { \ + attr->encap_subtlvs = new; \ + } \ + last = new; \ + } \ + } while (0) -void -bgp_encap_type_l2tpv3overip_to_tlv( - struct bgp_encap_type_l2tpv3_over_ip *bet, /* input structure */ - struct attr *attr) +void bgp_encap_type_l2tpv3overip_to_tlv( + struct bgp_encap_type_l2tpv3_over_ip *bet, /* input structure */ + struct attr *attr) { - struct bgp_attr_encap_subtlv *last; + struct bgp_attr_encap_subtlv *last; - /* advance to last subtlv */ - for (last = attr->encap_subtlvs; last && last->next; last = last->next); + /* advance to last subtlv */ + for (last = attr->encap_subtlvs; last && last->next; last = last->next) + ; - attr->encap_tunneltype = BGP_ENCAP_TYPE_L2TPV3_OVER_IP; + attr->encap_tunneltype = BGP_ENCAP_TYPE_L2TPV3_OVER_IP; - assert(CHECK_FLAG(bet->valid_subtlvs, BGP_TEA_SUBTLV_ENCAP)); + assert(CHECK_FLAG(bet->valid_subtlvs, BGP_TEA_SUBTLV_ENCAP)); - ENC_SUBTLV(BGP_TEA_SUBTLV_ENCAP, subtlv_encode_encap_l2tpv3_over_ip, st_encap); - ENC_SUBTLV(BGP_TEA_SUBTLV_PROTO_TYPE, subtlv_encode_proto_type, st_proto); - ENC_SUBTLV(BGP_TEA_SUBTLV_COLOR, subtlv_encode_color, st_color); - ENC_SUBTLV(BGP_TEA_SUBTLV_REMOTE_ENDPOINT, subtlv_encode_remote_endpoint, st_endpoint); + ENC_SUBTLV(BGP_TEA_SUBTLV_ENCAP, subtlv_encode_encap_l2tpv3_over_ip, + st_encap); + ENC_SUBTLV(BGP_TEA_SUBTLV_PROTO_TYPE, subtlv_encode_proto_type, + st_proto); + ENC_SUBTLV(BGP_TEA_SUBTLV_COLOR, subtlv_encode_color, st_color); + ENC_SUBTLV(BGP_TEA_SUBTLV_REMOTE_ENDPOINT, + subtlv_encode_remote_endpoint, st_endpoint); } -void -bgp_encap_type_gre_to_tlv( - struct bgp_encap_type_gre *bet, /* input structure */ - struct attr *attr) +void bgp_encap_type_gre_to_tlv( + struct bgp_encap_type_gre *bet, /* input structure */ + struct attr *attr) { - struct bgp_attr_encap_subtlv *last; + struct bgp_attr_encap_subtlv *last; - /* advance to last subtlv */ - for (last = attr->encap_subtlvs; last && last->next; last = last->next); + /* advance to last subtlv */ + for (last = attr->encap_subtlvs; last && last->next; last = last->next) + ; - attr->encap_tunneltype = BGP_ENCAP_TYPE_GRE; + attr->encap_tunneltype = BGP_ENCAP_TYPE_GRE; - ENC_SUBTLV(BGP_TEA_SUBTLV_ENCAP, subtlv_encode_encap_gre, st_encap); - ENC_SUBTLV(BGP_TEA_SUBTLV_PROTO_TYPE, subtlv_encode_proto_type, st_proto); - ENC_SUBTLV(BGP_TEA_SUBTLV_COLOR, subtlv_encode_color, st_color); - ENC_SUBTLV(BGP_TEA_SUBTLV_REMOTE_ENDPOINT, subtlv_encode_remote_endpoint, st_endpoint); + ENC_SUBTLV(BGP_TEA_SUBTLV_ENCAP, subtlv_encode_encap_gre, st_encap); + ENC_SUBTLV(BGP_TEA_SUBTLV_PROTO_TYPE, subtlv_encode_proto_type, + st_proto); + ENC_SUBTLV(BGP_TEA_SUBTLV_COLOR, subtlv_encode_color, st_color); + ENC_SUBTLV(BGP_TEA_SUBTLV_REMOTE_ENDPOINT, + subtlv_encode_remote_endpoint, st_endpoint); } -void -bgp_encap_type_ip_in_ip_to_tlv( - struct bgp_encap_type_ip_in_ip *bet, /* input structure */ - struct attr *attr) +void bgp_encap_type_ip_in_ip_to_tlv( + struct bgp_encap_type_ip_in_ip *bet, /* input structure */ + struct attr *attr) { - struct bgp_attr_encap_subtlv *last; + struct bgp_attr_encap_subtlv *last; - /* advance to last subtlv */ - for (last = attr->encap_subtlvs; last && last->next; last = last->next); + /* advance to last subtlv */ + for (last = attr->encap_subtlvs; last && last->next; last = last->next) + ; - attr->encap_tunneltype = BGP_ENCAP_TYPE_IP_IN_IP; + attr->encap_tunneltype = BGP_ENCAP_TYPE_IP_IN_IP; - ENC_SUBTLV(BGP_TEA_SUBTLV_PROTO_TYPE, subtlv_encode_proto_type, st_proto); - ENC_SUBTLV(BGP_TEA_SUBTLV_COLOR, subtlv_encode_color, st_color); - ENC_SUBTLV(BGP_TEA_SUBTLV_REMOTE_ENDPOINT, subtlv_encode_remote_endpoint, st_endpoint); + ENC_SUBTLV(BGP_TEA_SUBTLV_PROTO_TYPE, subtlv_encode_proto_type, + st_proto); + ENC_SUBTLV(BGP_TEA_SUBTLV_COLOR, subtlv_encode_color, st_color); + ENC_SUBTLV(BGP_TEA_SUBTLV_REMOTE_ENDPOINT, + subtlv_encode_remote_endpoint, st_endpoint); } -void -bgp_encap_type_transmit_tunnel_endpoint( - struct bgp_encap_type_transmit_tunnel_endpoint *bet, /* input structure */ - struct attr *attr) +void bgp_encap_type_transmit_tunnel_endpoint( + struct bgp_encap_type_transmit_tunnel_endpoint + *bet, /* input structure */ + struct attr *attr) { - struct bgp_attr_encap_subtlv *last; + struct bgp_attr_encap_subtlv *last; - /* advance to last subtlv */ - for (last = attr->encap_subtlvs; last && last->next; last = last->next); + /* advance to last subtlv */ + for (last = attr->encap_subtlvs; last && last->next; last = last->next) + ; - attr->encap_tunneltype = BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT; + attr->encap_tunneltype = BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT; - /* no subtlvs for this type */ + /* no subtlvs for this type */ } -void -bgp_encap_type_ipsec_in_tunnel_mode_to_tlv( - struct bgp_encap_type_ipsec_in_tunnel_mode *bet, /* input structure */ - struct attr *attr) +void bgp_encap_type_ipsec_in_tunnel_mode_to_tlv( + struct bgp_encap_type_ipsec_in_tunnel_mode *bet, /* input structure */ + struct attr *attr) { - struct bgp_attr_encap_subtlv *last; + struct bgp_attr_encap_subtlv *last; - /* advance to last subtlv */ - for (last = attr->encap_subtlvs; last && last->next; last = last->next); + /* advance to last subtlv */ + for (last = attr->encap_subtlvs; last && last->next; last = last->next) + ; - attr->encap_tunneltype = BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE; + attr->encap_tunneltype = BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE; - ENC_SUBTLV(BGP_TEA_SUBTLV_IPSEC_TA, subtlv_encode_ipsec_ta, st_ipsec_ta); + ENC_SUBTLV(BGP_TEA_SUBTLV_IPSEC_TA, subtlv_encode_ipsec_ta, + st_ipsec_ta); } -void -bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode_to_tlv( - struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet, /* input structure */ - struct attr *attr) +void bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode_to_tlv( + struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode + *bet, /* input structure */ + struct attr *attr) { - struct bgp_attr_encap_subtlv *last; + struct bgp_attr_encap_subtlv *last; - /* advance to last subtlv */ - for (last = attr->encap_subtlvs; last && last->next; last = last->next); + /* advance to last subtlv */ + for (last = attr->encap_subtlvs; last && last->next; last = last->next) + ; - attr->encap_tunneltype = BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE; + attr->encap_tunneltype = + BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE; - ENC_SUBTLV(BGP_TEA_SUBTLV_IPSEC_TA, subtlv_encode_ipsec_ta, st_ipsec_ta); + ENC_SUBTLV(BGP_TEA_SUBTLV_IPSEC_TA, subtlv_encode_ipsec_ta, + st_ipsec_ta); } -void -bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode_to_tlv( - struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet, /* input structure */ - struct attr *attr) +void bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode_to_tlv( + struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode + *bet, /* input structure */ + struct attr *attr) { - struct bgp_attr_encap_subtlv *last; + struct bgp_attr_encap_subtlv *last; - /* advance to last subtlv */ - for (last = attr->encap_subtlvs; last && last->next; last = last->next); + /* advance to last subtlv */ + for (last = attr->encap_subtlvs; last && last->next; last = last->next) + ; - attr->encap_tunneltype = BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE; + attr->encap_tunneltype = + BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE; - ENC_SUBTLV(BGP_TEA_SUBTLV_IPSEC_TA, subtlv_encode_ipsec_ta, st_ipsec_ta); + ENC_SUBTLV(BGP_TEA_SUBTLV_IPSEC_TA, subtlv_encode_ipsec_ta, + st_ipsec_ta); } -void -bgp_encap_type_pbb_to_tlv( - struct bgp_encap_type_pbb *bet, /* input structure */ - struct attr *attr) +void bgp_encap_type_pbb_to_tlv( + struct bgp_encap_type_pbb *bet, /* input structure */ + struct attr *attr) { - struct bgp_attr_encap_subtlv *last; + struct bgp_attr_encap_subtlv *last; - /* advance to last subtlv */ - for (last = attr->encap_subtlvs; last && last->next; last = last->next); + /* advance to last subtlv */ + for (last = attr->encap_subtlvs; last && last->next; last = last->next) + ; - attr->encap_tunneltype = BGP_ENCAP_TYPE_PBB; + attr->encap_tunneltype = BGP_ENCAP_TYPE_PBB; - assert(CHECK_FLAG(bet->valid_subtlvs, BGP_TEA_SUBTLV_ENCAP)); - ENC_SUBTLV(BGP_TEA_SUBTLV_ENCAP, subtlv_encode_encap_pbb, st_encap); + assert(CHECK_FLAG(bet->valid_subtlvs, BGP_TEA_SUBTLV_ENCAP)); + ENC_SUBTLV(BGP_TEA_SUBTLV_ENCAP, subtlv_encode_encap_pbb, st_encap); } -void -bgp_encap_type_vxlan_to_tlv( - struct bgp_encap_type_vxlan *bet, /* input structure */ - struct attr *attr) +void bgp_encap_type_vxlan_to_tlv( + struct bgp_encap_type_vxlan *bet, /* input structure */ + struct attr *attr) { - struct bgp_attr_encap_subtlv *tlv; - uint32_t vnid; + struct bgp_attr_encap_subtlv *tlv; + uint32_t vnid; - attr->encap_tunneltype = BGP_ENCAP_TYPE_VXLAN; + attr->encap_tunneltype = BGP_ENCAP_TYPE_VXLAN; - if(bet == NULL ||!bet->vnid) - return; - if(attr->encap_subtlvs) - XFREE(MTYPE_ENCAP_TLV, attr->encap_subtlvs); - tlv = XCALLOC (MTYPE_ENCAP_TLV, sizeof(struct bgp_attr_encap_subtlv)-1+12); - tlv->type = 1; /* encapsulation type */ - tlv->length = 12; - if(bet->vnid) - { - vnid = htonl(bet->vnid | VXLAN_ENCAP_MASK_VNID_VALID); - memcpy(&tlv->value, &vnid, 4); - } - if(bet->mac_address) - { - char *ptr = (char *)&tlv->value + 4; - memcpy( ptr, bet->mac_address, 6); - } - attr->encap_subtlvs = tlv; - return; + if (bet == NULL || !bet->vnid) + return; + if (attr->encap_subtlvs) + XFREE(MTYPE_ENCAP_TLV, attr->encap_subtlvs); + tlv = XCALLOC(MTYPE_ENCAP_TLV, + sizeof(struct bgp_attr_encap_subtlv) - 1 + 12); + tlv->type = 1; /* encapsulation type */ + tlv->length = 12; + if (bet->vnid) { + vnid = htonl(bet->vnid | VXLAN_ENCAP_MASK_VNID_VALID); + memcpy(&tlv->value, &vnid, 4); + } + if (bet->mac_address) { + char *ptr = (char *)&tlv->value + 4; + memcpy(ptr, bet->mac_address, 6); + } + attr->encap_subtlvs = tlv; + return; } -void -bgp_encap_type_nvgre_to_tlv( - struct bgp_encap_type_nvgre *bet, /* input structure */ - struct attr *attr) +void bgp_encap_type_nvgre_to_tlv( + struct bgp_encap_type_nvgre *bet, /* input structure */ + struct attr *attr) { - attr->encap_tunneltype = BGP_ENCAP_TYPE_NVGRE; + attr->encap_tunneltype = BGP_ENCAP_TYPE_NVGRE; } -void -bgp_encap_type_mpls_to_tlv( - struct bgp_encap_type_mpls *bet, /* input structure */ - struct attr *attr) +void bgp_encap_type_mpls_to_tlv( + struct bgp_encap_type_mpls *bet, /* input structure */ + struct attr *attr) { - return; /* no encap attribute for MPLS */ + return; /* no encap attribute for MPLS */ } -void -bgp_encap_type_mpls_in_gre_to_tlv( - struct bgp_encap_type_mpls_in_gre *bet, /* input structure */ - struct attr *attr) +void bgp_encap_type_mpls_in_gre_to_tlv( + struct bgp_encap_type_mpls_in_gre *bet, /* input structure */ + struct attr *attr) { - attr->encap_tunneltype = BGP_ENCAP_TYPE_MPLS_IN_GRE; + attr->encap_tunneltype = BGP_ENCAP_TYPE_MPLS_IN_GRE; } -void -bgp_encap_type_vxlan_gpe_to_tlv( - struct bgp_encap_type_vxlan_gpe *bet, /* input structure */ - struct attr *attr) +void bgp_encap_type_vxlan_gpe_to_tlv( + struct bgp_encap_type_vxlan_gpe *bet, /* input structure */ + struct attr *attr) { - attr->encap_tunneltype = BGP_ENCAP_TYPE_VXLAN_GPE; + attr->encap_tunneltype = BGP_ENCAP_TYPE_VXLAN_GPE; } -void -bgp_encap_type_mpls_in_udp_to_tlv( - struct bgp_encap_type_mpls_in_udp *bet, /* input structure */ - struct attr *attr) +void bgp_encap_type_mpls_in_udp_to_tlv( + struct bgp_encap_type_mpls_in_udp *bet, /* input structure */ + struct attr *attr) { - attr->encap_tunneltype = BGP_ENCAP_TYPE_MPLS_IN_UDP; + attr->encap_tunneltype = BGP_ENCAP_TYPE_MPLS_IN_UDP; } @@ -453,564 +460,551 @@ bgp_encap_type_mpls_in_udp_to_tlv( * SUBTLV DECODE ***********************************************************************/ /* rfc5512 4.1 */ -static int -subtlv_decode_encap_l2tpv3_over_ip( - struct bgp_attr_encap_subtlv *subtlv, - struct bgp_tea_subtlv_encap_l2tpv3_over_ip *st) -{ - if (subtlv->length < 4) { - zlog_debug("%s, subtlv length %d is less than 4", - __func__, subtlv->length); - return -1; - } - - st->sessionid = (subtlv->value[0] << 24) | - (subtlv->value[1] << 16) | - (subtlv->value[2] << 8) | - subtlv->value[3]; - st->cookie_length = subtlv->length - 4; - if (st->cookie_length > sizeof(st->cookie)) { - zlog_debug("%s, subtlv length %d is greater than %d", - __func__, st->cookie_length, (int)sizeof(st->cookie)); - return -1; - } - memcpy(st->cookie, subtlv->value + 4, st->cookie_length); - return 0; +static int subtlv_decode_encap_l2tpv3_over_ip( + struct bgp_attr_encap_subtlv *subtlv, + struct bgp_tea_subtlv_encap_l2tpv3_over_ip *st) +{ + if (subtlv->length < 4) { + zlog_debug("%s, subtlv length %d is less than 4", __func__, + subtlv->length); + return -1; + } + + st->sessionid = (subtlv->value[0] << 24) | (subtlv->value[1] << 16) + | (subtlv->value[2] << 8) | subtlv->value[3]; + st->cookie_length = subtlv->length - 4; + if (st->cookie_length > sizeof(st->cookie)) { + zlog_debug("%s, subtlv length %d is greater than %d", __func__, + st->cookie_length, (int)sizeof(st->cookie)); + return -1; + } + memcpy(st->cookie, subtlv->value + 4, st->cookie_length); + return 0; } /* rfc5512 4.1 */ -static int -subtlv_decode_encap_gre( - struct bgp_attr_encap_subtlv *subtlv, - struct bgp_tea_subtlv_encap_gre_key *st) -{ - if (subtlv->length != 4) { - zlog_debug("%s, subtlv length %d does not equal 4", - __func__, subtlv->length); - return -1; - } - st->gre_key = (subtlv->value[0] << 24) | - (subtlv->value[1] << 16) | - (subtlv->value[2] << 8) | - subtlv->value[3]; - return 0; +static int subtlv_decode_encap_gre(struct bgp_attr_encap_subtlv *subtlv, + struct bgp_tea_subtlv_encap_gre_key *st) +{ + if (subtlv->length != 4) { + zlog_debug("%s, subtlv length %d does not equal 4", __func__, + subtlv->length); + return -1; + } + st->gre_key = (subtlv->value[0] << 24) | (subtlv->value[1] << 16) + | (subtlv->value[2] << 8) | subtlv->value[3]; + return 0; } -static int -subtlv_decode_encap_pbb( - struct bgp_attr_encap_subtlv *subtlv, - struct bgp_tea_subtlv_encap_pbb *st) -{ - if (subtlv->length != 1 + 3 + 6 + 2) { - zlog_debug("%s, subtlv length %d does not equal %d", - __func__, subtlv->length, 1 + 3 + 6 + 2); - return -1; - } - if (subtlv->value[0] & 0x80) { - st->flag_isid = 1; - st->isid = (subtlv->value[1] << 16) | - (subtlv->value[2] << 8) | - subtlv->value[3]; - } - if (subtlv->value[0] & 0x40) { - st->flag_vid = 1; - st->vid = ((subtlv->value[10] & 0x0f) << 8) | subtlv->value[11]; - } - memcpy(st->macaddr, subtlv->value + 4, 6); - return 0; +static int subtlv_decode_encap_pbb(struct bgp_attr_encap_subtlv *subtlv, + struct bgp_tea_subtlv_encap_pbb *st) +{ + if (subtlv->length != 1 + 3 + 6 + 2) { + zlog_debug("%s, subtlv length %d does not equal %d", __func__, + subtlv->length, 1 + 3 + 6 + 2); + return -1; + } + if (subtlv->value[0] & 0x80) { + st->flag_isid = 1; + st->isid = (subtlv->value[1] << 16) | (subtlv->value[2] << 8) + | subtlv->value[3]; + } + if (subtlv->value[0] & 0x40) { + st->flag_vid = 1; + st->vid = ((subtlv->value[10] & 0x0f) << 8) | subtlv->value[11]; + } + memcpy(st->macaddr, subtlv->value + 4, 6); + return 0; } /* rfc5512 4.2 */ -static int -subtlv_decode_proto_type( - struct bgp_attr_encap_subtlv *subtlv, - struct bgp_tea_subtlv_proto_type *st) +static int subtlv_decode_proto_type(struct bgp_attr_encap_subtlv *subtlv, + struct bgp_tea_subtlv_proto_type *st) { - if (subtlv->length != 2) { - zlog_debug("%s, subtlv length %d does not equal 2", - __func__, subtlv->length); - return -1; - } - st->proto = (subtlv->value[0] << 8) | subtlv->value[1]; - return 0; + if (subtlv->length != 2) { + zlog_debug("%s, subtlv length %d does not equal 2", __func__, + subtlv->length); + return -1; + } + st->proto = (subtlv->value[0] << 8) | subtlv->value[1]; + return 0; } /* rfc5512 4.3 */ -static int -subtlv_decode_color( - struct bgp_attr_encap_subtlv *subtlv, - struct bgp_tea_subtlv_color *st) -{ - if (subtlv->length != 8) { - zlog_debug("%s, subtlv length %d does not equal 8", - __func__, subtlv->length); - return -1; - } - if ((subtlv->value[0] != 0x03) || - (subtlv->value[1] != 0x0b) || - (subtlv->value[2] != 0) || - (subtlv->value[3] != 0)) { - zlog_debug("%s, subtlv value 1st 4 bytes are not 0x030b0000", __func__); - return -1; - } - st->color = (subtlv->value[4] << 24) | - (subtlv->value[5] << 16) | - (subtlv->value[6] << 8) | - subtlv->value[7]; - return 0; +static int subtlv_decode_color(struct bgp_attr_encap_subtlv *subtlv, + struct bgp_tea_subtlv_color *st) +{ + if (subtlv->length != 8) { + zlog_debug("%s, subtlv length %d does not equal 8", __func__, + subtlv->length); + return -1; + } + if ((subtlv->value[0] != 0x03) || (subtlv->value[1] != 0x0b) + || (subtlv->value[2] != 0) || (subtlv->value[3] != 0)) { + zlog_debug("%s, subtlv value 1st 4 bytes are not 0x030b0000", + __func__); + return -1; + } + st->color = (subtlv->value[4] << 24) | (subtlv->value[5] << 16) + | (subtlv->value[6] << 8) | subtlv->value[7]; + return 0; } /* rfc 5566 4. */ -static int -subtlv_decode_ipsec_ta( - struct bgp_attr_encap_subtlv *subtlv, - struct bgp_tea_subtlv_ipsec_ta *st) -{ - st->authenticator_length = subtlv->length - 2; - if (st->authenticator_length > sizeof(st->value)) { - zlog_debug("%s, authenticator length %d exceeds storage maximum %d", - __func__, st->authenticator_length, (int)sizeof(st->value)); - return -1; - } - st->authenticator_type = (subtlv->value[0] << 8) | subtlv->value[1]; - memcpy(st->value, subtlv->value + 2, st->authenticator_length); - return 0; +static int subtlv_decode_ipsec_ta(struct bgp_attr_encap_subtlv *subtlv, + struct bgp_tea_subtlv_ipsec_ta *st) +{ + st->authenticator_length = subtlv->length - 2; + if (st->authenticator_length > sizeof(st->value)) { + zlog_debug( + "%s, authenticator length %d exceeds storage maximum %d", + __func__, st->authenticator_length, + (int)sizeof(st->value)); + return -1; + } + st->authenticator_type = (subtlv->value[0] << 8) | subtlv->value[1]; + memcpy(st->value, subtlv->value + 2, st->authenticator_length); + return 0; } /* draft-rosen-idr-tunnel-encaps 2.1 */ static int -subtlv_decode_remote_endpoint( - struct bgp_attr_encap_subtlv *subtlv, - struct bgp_tea_subtlv_remote_endpoint *st) -{ - int i; - if (subtlv->length != 8 && subtlv->length != 20 ) { - zlog_debug("%s, subtlv length %d does not equal 8 or 20", - __func__, subtlv->length); - return -1; - } - if (subtlv->length == 8) { - st->family = AF_INET; - st->ip_address.v4.s_addr = ((subtlv->value[0] << 24) | - (subtlv->value[1] << 16) | - (subtlv->value[2] << 8) | - subtlv->value[3]); - } else { - st->family = AF_INET6; - memcpy (&(st->ip_address.v6.s6_addr), subtlv->value, 16); - } - i = subtlv->length - 4; - st->as4 = ((subtlv->value[i] << 24) | - (subtlv->value[i+1] << 16) | - (subtlv->value[i+2] << 8) | - subtlv->value[i+3]); - return 0; +subtlv_decode_remote_endpoint(struct bgp_attr_encap_subtlv *subtlv, + struct bgp_tea_subtlv_remote_endpoint *st) +{ + int i; + if (subtlv->length != 8 && subtlv->length != 20) { + zlog_debug("%s, subtlv length %d does not equal 8 or 20", + __func__, subtlv->length); + return -1; + } + if (subtlv->length == 8) { + st->family = AF_INET; + st->ip_address.v4.s_addr = + ((subtlv->value[0] << 24) | (subtlv->value[1] << 16) + | (subtlv->value[2] << 8) | subtlv->value[3]); + } else { + st->family = AF_INET6; + memcpy(&(st->ip_address.v6.s6_addr), subtlv->value, 16); + } + i = subtlv->length - 4; + st->as4 = ((subtlv->value[i] << 24) | (subtlv->value[i + 1] << 16) + | (subtlv->value[i + 2] << 8) | subtlv->value[i + 3]); + return 0; } /*********************************************************************** * TUNNEL TYPE-SPECIFIC TLV DECODE ***********************************************************************/ -int -tlv_to_bgp_encap_type_l2tpv3overip( - struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ - struct bgp_encap_type_l2tpv3_over_ip *bet) /* caller-allocated */ -{ - struct bgp_attr_encap_subtlv *st; - int rc = 0; - - for (st = stlv; st; st = st->next) { - switch (st->type) { - case BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION: - rc |= subtlv_decode_encap_l2tpv3_over_ip(st, &bet->st_encap); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_ENCAP); - break; - - case BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE: - rc |= subtlv_decode_proto_type(st, &bet->st_proto); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_PROTO_TYPE); - break; - - case BGP_ENCAP_SUBTLV_TYPE_COLOR: - rc |= subtlv_decode_color(st, &bet->st_color); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_COLOR); - break; - - case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: - rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); - break; - - default: - zlog_debug("%s: unexpected subtlv type %d", __func__, st->type); - rc |= -1; - break; +int tlv_to_bgp_encap_type_l2tpv3overip( + struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ + struct bgp_encap_type_l2tpv3_over_ip *bet) /* caller-allocated */ +{ + struct bgp_attr_encap_subtlv *st; + int rc = 0; + + for (st = stlv; st; st = st->next) { + switch (st->type) { + case BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION: + rc |= subtlv_decode_encap_l2tpv3_over_ip( + st, &bet->st_encap); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_ENCAP); + break; + + case BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE: + rc |= subtlv_decode_proto_type(st, &bet->st_proto); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_PROTO_TYPE); + break; + + case BGP_ENCAP_SUBTLV_TYPE_COLOR: + rc |= subtlv_decode_color(st, &bet->st_color); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_COLOR); + break; + + case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: + rc |= subtlv_decode_remote_endpoint(st, + &bet->st_endpoint); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); + break; + + default: + zlog_debug("%s: unexpected subtlv type %d", __func__, + st->type); + rc |= -1; + break; + } } - } - return rc; -} - -int -tlv_to_bgp_encap_type_gre( - struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ - struct bgp_encap_type_gre *bet) /* caller-allocated */ -{ - struct bgp_attr_encap_subtlv *st; - int rc = 0; - - for (st = stlv; st; st = st->next) { - switch (st->type) { - case BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION: - rc |= subtlv_decode_encap_gre(st, &bet->st_encap); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_ENCAP); - break; - - case BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE: - rc |= subtlv_decode_proto_type(st, &bet->st_proto); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_PROTO_TYPE); - break; - - case BGP_ENCAP_SUBTLV_TYPE_COLOR: - rc |= subtlv_decode_color(st, &bet->st_color); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_COLOR); - break; - - case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: - rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); - break; - - default: - zlog_debug("%s: unexpected subtlv type %d", __func__, st->type); - rc |= -1; - break; + return rc; +} + +int tlv_to_bgp_encap_type_gre( + struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ + struct bgp_encap_type_gre *bet) /* caller-allocated */ +{ + struct bgp_attr_encap_subtlv *st; + int rc = 0; + + for (st = stlv; st; st = st->next) { + switch (st->type) { + case BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION: + rc |= subtlv_decode_encap_gre(st, &bet->st_encap); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_ENCAP); + break; + + case BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE: + rc |= subtlv_decode_proto_type(st, &bet->st_proto); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_PROTO_TYPE); + break; + + case BGP_ENCAP_SUBTLV_TYPE_COLOR: + rc |= subtlv_decode_color(st, &bet->st_color); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_COLOR); + break; + + case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: + rc |= subtlv_decode_remote_endpoint(st, + &bet->st_endpoint); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); + break; + + default: + zlog_debug("%s: unexpected subtlv type %d", __func__, + st->type); + rc |= -1; + break; + } } - } - return rc; -} - -int -tlv_to_bgp_encap_type_ip_in_ip( - struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ - struct bgp_encap_type_ip_in_ip *bet) /* caller-allocated */ -{ - struct bgp_attr_encap_subtlv *st; - int rc = 0; - - for (st = stlv; st; st = st->next) { - switch (st->type) { - case BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE: - rc |= subtlv_decode_proto_type(st, &bet->st_proto); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_PROTO_TYPE); - break; - - case BGP_ENCAP_SUBTLV_TYPE_COLOR: - rc |= subtlv_decode_color(st, &bet->st_color); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_COLOR); - break; - - case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: - rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); - break; - - default: - zlog_debug("%s: unexpected subtlv type %d", __func__, st->type); - rc |= -1; - break; + return rc; +} + +int tlv_to_bgp_encap_type_ip_in_ip( + struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ + struct bgp_encap_type_ip_in_ip *bet) /* caller-allocated */ +{ + struct bgp_attr_encap_subtlv *st; + int rc = 0; + + for (st = stlv; st; st = st->next) { + switch (st->type) { + case BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE: + rc |= subtlv_decode_proto_type(st, &bet->st_proto); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_PROTO_TYPE); + break; + + case BGP_ENCAP_SUBTLV_TYPE_COLOR: + rc |= subtlv_decode_color(st, &bet->st_color); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_COLOR); + break; + + case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: + rc |= subtlv_decode_remote_endpoint(st, + &bet->st_endpoint); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); + break; + + default: + zlog_debug("%s: unexpected subtlv type %d", __func__, + st->type); + rc |= -1; + break; + } } - } - return rc; + return rc; } -int -tlv_to_bgp_encap_type_transmit_tunnel_endpoint( - struct bgp_attr_encap_subtlv *stlv, - struct bgp_encap_type_transmit_tunnel_endpoint *bet) +int tlv_to_bgp_encap_type_transmit_tunnel_endpoint( + struct bgp_attr_encap_subtlv *stlv, + struct bgp_encap_type_transmit_tunnel_endpoint *bet) { - struct bgp_attr_encap_subtlv *st; - int rc = 0; + struct bgp_attr_encap_subtlv *st; + int rc = 0; - for (st = stlv; st; st = st->next) { - switch (st->type) { + for (st = stlv; st; st = st->next) { + switch (st->type) { - case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: - rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); - break; + case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: + rc |= subtlv_decode_remote_endpoint(st, + &bet->st_endpoint); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); + break; - default: - zlog_debug("%s: unexpected subtlv type %d", __func__, st->type); - rc |= -1; - break; + default: + zlog_debug("%s: unexpected subtlv type %d", __func__, + st->type); + rc |= -1; + break; + } } - } - return rc; -} - -int -tlv_to_bgp_encap_type_ipsec_in_tunnel_mode( - struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ - struct bgp_encap_type_ipsec_in_tunnel_mode *bet) /* caller-allocated */ -{ - struct bgp_attr_encap_subtlv *st; - int rc = 0; - - for (st = stlv; st; st = st->next) { - switch (st->type) { - case BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA: - rc |= subtlv_decode_ipsec_ta(st, &bet->st_ipsec_ta); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_IPSEC_TA); - break; - - case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: - rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); - break; - - default: - zlog_debug("%s: unexpected subtlv type %d", __func__, st->type); - rc |= -1; - break; + return rc; +} + +int tlv_to_bgp_encap_type_ipsec_in_tunnel_mode( + struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ + struct bgp_encap_type_ipsec_in_tunnel_mode *bet) /* caller-allocated */ +{ + struct bgp_attr_encap_subtlv *st; + int rc = 0; + + for (st = stlv; st; st = st->next) { + switch (st->type) { + case BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA: + rc |= subtlv_decode_ipsec_ta(st, &bet->st_ipsec_ta); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_IPSEC_TA); + break; + + case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: + rc |= subtlv_decode_remote_endpoint(st, + &bet->st_endpoint); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); + break; + + default: + zlog_debug("%s: unexpected subtlv type %d", __func__, + st->type); + rc |= -1; + break; + } } - } - return rc; -} - -int -tlv_to_bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode( - struct bgp_attr_encap_subtlv *stlv, - struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet) -{ - struct bgp_attr_encap_subtlv *st; - int rc = 0; - - for (st = stlv; st; st = st->next) { - switch (st->type) { - case BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA: - rc |= subtlv_decode_ipsec_ta(st, &bet->st_ipsec_ta); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_IPSEC_TA); - break; - - case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: - rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); - break; - - default: - zlog_debug("%s: unexpected subtlv type %d", __func__, st->type); - rc |= -1; - break; + return rc; +} + +int tlv_to_bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode( + struct bgp_attr_encap_subtlv *stlv, + struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet) +{ + struct bgp_attr_encap_subtlv *st; + int rc = 0; + + for (st = stlv; st; st = st->next) { + switch (st->type) { + case BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA: + rc |= subtlv_decode_ipsec_ta(st, &bet->st_ipsec_ta); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_IPSEC_TA); + break; + + case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: + rc |= subtlv_decode_remote_endpoint(st, + &bet->st_endpoint); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); + break; + + default: + zlog_debug("%s: unexpected subtlv type %d", __func__, + st->type); + rc |= -1; + break; + } } - } - return rc; -} - -int -tlv_to_bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode( - struct bgp_attr_encap_subtlv *stlv, - struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet) -{ - struct bgp_attr_encap_subtlv *st; - int rc = 0; - - for (st = stlv; st; st = st->next) { - switch (st->type) { - case BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA: - rc |= subtlv_decode_ipsec_ta(st, &bet->st_ipsec_ta); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_IPSEC_TA); - break; - - case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: - rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); - break; - - default: - zlog_debug("%s: unexpected subtlv type %d", __func__, st->type); - rc |= -1; - break; + return rc; +} + +int tlv_to_bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode( + struct bgp_attr_encap_subtlv *stlv, + struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet) +{ + struct bgp_attr_encap_subtlv *st; + int rc = 0; + + for (st = stlv; st; st = st->next) { + switch (st->type) { + case BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA: + rc |= subtlv_decode_ipsec_ta(st, &bet->st_ipsec_ta); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_IPSEC_TA); + break; + + case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: + rc |= subtlv_decode_remote_endpoint(st, + &bet->st_endpoint); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); + break; + + default: + zlog_debug("%s: unexpected subtlv type %d", __func__, + st->type); + rc |= -1; + break; + } } - } - return rc; + return rc; } -int -tlv_to_bgp_encap_type_vxlan( - struct bgp_attr_encap_subtlv *stlv, - struct bgp_encap_type_vxlan *bet) +int tlv_to_bgp_encap_type_vxlan(struct bgp_attr_encap_subtlv *stlv, + struct bgp_encap_type_vxlan *bet) { - struct bgp_attr_encap_subtlv *st; - int rc = 0; + struct bgp_attr_encap_subtlv *st; + int rc = 0; - for (st = stlv; st; st = st->next) { - switch (st->type) { + for (st = stlv; st; st = st->next) { + switch (st->type) { - case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: - rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); - break; + case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: + rc |= subtlv_decode_remote_endpoint(st, + &bet->st_endpoint); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); + break; - default: - zlog_debug("%s: unexpected subtlv type %d", __func__, st->type); - rc |= -1; - break; + default: + zlog_debug("%s: unexpected subtlv type %d", __func__, + st->type); + rc |= -1; + break; + } } - } - return rc; + return rc; } -int -tlv_to_bgp_encap_type_nvgre( - struct bgp_attr_encap_subtlv *stlv, - struct bgp_encap_type_nvgre *bet) +int tlv_to_bgp_encap_type_nvgre(struct bgp_attr_encap_subtlv *stlv, + struct bgp_encap_type_nvgre *bet) { - struct bgp_attr_encap_subtlv *st; - int rc = 0; + struct bgp_attr_encap_subtlv *st; + int rc = 0; - for (st = stlv; st; st = st->next) { - switch (st->type) { + for (st = stlv; st; st = st->next) { + switch (st->type) { - case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: - rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); - break; + case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: + rc |= subtlv_decode_remote_endpoint(st, + &bet->st_endpoint); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); + break; - default: - zlog_debug("%s: unexpected subtlv type %d", __func__, st->type); - rc |= -1; - break; + default: + zlog_debug("%s: unexpected subtlv type %d", __func__, + st->type); + rc |= -1; + break; + } } - } - return rc; + return rc; } -int -tlv_to_bgp_encap_type_mpls( - struct bgp_attr_encap_subtlv *stlv, - struct bgp_encap_type_mpls *bet) +int tlv_to_bgp_encap_type_mpls(struct bgp_attr_encap_subtlv *stlv, + struct bgp_encap_type_mpls *bet) { - struct bgp_attr_encap_subtlv *st; - int rc = 0; + struct bgp_attr_encap_subtlv *st; + int rc = 0; - for (st = stlv; st; st = st->next) { - switch (st->type) { + for (st = stlv; st; st = st->next) { + switch (st->type) { - case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: - rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); - break; + case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: + rc |= subtlv_decode_remote_endpoint(st, + &bet->st_endpoint); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); + break; - default: - zlog_debug("%s: unexpected subtlv type %d", __func__, st->type); - rc |= -1; - break; + default: + zlog_debug("%s: unexpected subtlv type %d", __func__, + st->type); + rc |= -1; + break; + } } - } - return rc; + return rc; } -int -tlv_to_bgp_encap_type_mpls_in_gre( - struct bgp_attr_encap_subtlv *stlv, - struct bgp_encap_type_mpls_in_gre *bet) +int tlv_to_bgp_encap_type_mpls_in_gre(struct bgp_attr_encap_subtlv *stlv, + struct bgp_encap_type_mpls_in_gre *bet) { - struct bgp_attr_encap_subtlv *st; - int rc = 0; + struct bgp_attr_encap_subtlv *st; + int rc = 0; - for (st = stlv; st; st = st->next) { - switch (st->type) { + for (st = stlv; st; st = st->next) { + switch (st->type) { - case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: - rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); - break; + case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: + rc |= subtlv_decode_remote_endpoint(st, + &bet->st_endpoint); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); + break; - default: - zlog_debug("%s: unexpected subtlv type %d", __func__, st->type); - rc |= -1; - break; + default: + zlog_debug("%s: unexpected subtlv type %d", __func__, + st->type); + rc |= -1; + break; + } } - } - return rc; + return rc; } -int -tlv_to_bgp_encap_type_vxlan_gpe( - struct bgp_attr_encap_subtlv *stlv, - struct bgp_encap_type_vxlan_gpe *bet) +int tlv_to_bgp_encap_type_vxlan_gpe(struct bgp_attr_encap_subtlv *stlv, + struct bgp_encap_type_vxlan_gpe *bet) { - struct bgp_attr_encap_subtlv *st; - int rc = 0; + struct bgp_attr_encap_subtlv *st; + int rc = 0; - for (st = stlv; st; st = st->next) { - switch (st->type) { + for (st = stlv; st; st = st->next) { + switch (st->type) { - case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: - rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); - break; + case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: + rc |= subtlv_decode_remote_endpoint(st, + &bet->st_endpoint); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); + break; - default: - zlog_debug("%s: unexpected subtlv type %d", __func__, st->type); - rc |= -1; - break; + default: + zlog_debug("%s: unexpected subtlv type %d", __func__, + st->type); + rc |= -1; + break; + } } - } - return rc; + return rc; } -int -tlv_to_bgp_encap_type_mpls_in_udp( - struct bgp_attr_encap_subtlv *stlv, - struct bgp_encap_type_mpls_in_udp *bet) +int tlv_to_bgp_encap_type_mpls_in_udp(struct bgp_attr_encap_subtlv *stlv, + struct bgp_encap_type_mpls_in_udp *bet) { - struct bgp_attr_encap_subtlv *st; - int rc = 0; + struct bgp_attr_encap_subtlv *st; + int rc = 0; - for (st = stlv; st; st = st->next) { - switch (st->type) { + for (st = stlv; st; st = st->next) { + switch (st->type) { - case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: - rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); - break; + case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: + rc |= subtlv_decode_remote_endpoint(st, + &bet->st_endpoint); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); + break; - default: - zlog_debug("%s: unexpected subtlv type %d", __func__, st->type); - rc |= -1; - break; + default: + zlog_debug("%s: unexpected subtlv type %d", __func__, + st->type); + rc |= -1; + break; + } } - } - return rc; -} - -int -tlv_to_bgp_encap_type_pbb( - struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ - struct bgp_encap_type_pbb *bet) /* caller-allocated */ -{ - struct bgp_attr_encap_subtlv *st; - int rc = 0; - - for (st = stlv; st; st = st->next) { - switch (st->type) { - case BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION: - rc |= subtlv_decode_encap_pbb(st, &bet->st_encap); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_ENCAP); - break; - - case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: - rc |= subtlv_decode_remote_endpoint(st, &bet->st_endpoint); - SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); - break; - - default: - zlog_debug("%s: unexpected subtlv type %d", __func__, st->type); - rc |= -1; - break; + return rc; +} + +int tlv_to_bgp_encap_type_pbb( + struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ + struct bgp_encap_type_pbb *bet) /* caller-allocated */ +{ + struct bgp_attr_encap_subtlv *st; + int rc = 0; + + for (st = stlv; st; st = st->next) { + switch (st->type) { + case BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION: + rc |= subtlv_decode_encap_pbb(st, &bet->st_encap); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_ENCAP); + break; + + case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: + rc |= subtlv_decode_remote_endpoint(st, + &bet->st_endpoint); + SET_SUBTLV_FLAG(bet, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); + break; + + default: + zlog_debug("%s: unexpected subtlv type %d", __func__, + st->type); + rc |= -1; + break; + } } - } - return rc; + return rc; } - diff --git a/bgpd/bgp_encap_tlv.h b/bgpd/bgp_encap_tlv.h index 487762714..64f9a9c74 100644 --- a/bgpd/bgp_encap_tlv.h +++ b/bgpd/bgp_encap_tlv.h @@ -19,158 +19,116 @@ #ifndef _QUAGGA_BGP_ENCAP_TLV_H #define _QUAGGA_BGP_ENCAP_TLV_H - /*********************************************************************** * TUNNEL TYPE-SPECIFIC TLV ENCODE ***********************************************************************/ extern void -bgp_encap_type_l2tpv3overip_to_tlv( - struct bgp_encap_type_l2tpv3_over_ip *bet, - struct attr *attr); +bgp_encap_type_l2tpv3overip_to_tlv(struct bgp_encap_type_l2tpv3_over_ip *bet, + struct attr *attr); -extern void -bgp_encap_type_gre_to_tlv( - struct bgp_encap_type_gre *bet, - struct attr *attr); +extern void bgp_encap_type_gre_to_tlv(struct bgp_encap_type_gre *bet, + struct attr *attr); -extern void -bgp_encap_type_ip_in_ip_to_tlv( - struct bgp_encap_type_ip_in_ip *bet, - struct attr *attr); +extern void bgp_encap_type_ip_in_ip_to_tlv(struct bgp_encap_type_ip_in_ip *bet, + struct attr *attr); -extern void -bgp_encap_type_transmit_tunnel_endpoint( - struct bgp_encap_type_transmit_tunnel_endpoint *bet, - struct attr *attr); +extern void bgp_encap_type_transmit_tunnel_endpoint( + struct bgp_encap_type_transmit_tunnel_endpoint *bet, struct attr *attr); -extern void -bgp_encap_type_ipsec_in_tunnel_mode_to_tlv( - struct bgp_encap_type_ipsec_in_tunnel_mode *bet, - struct attr *attr); +extern void bgp_encap_type_ipsec_in_tunnel_mode_to_tlv( + struct bgp_encap_type_ipsec_in_tunnel_mode *bet, struct attr *attr); -extern void -bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode_to_tlv( - struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet, - struct attr *attr); +extern void bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode_to_tlv( + struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet, + struct attr *attr); -extern void -bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode_to_tlv( - struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet, - struct attr *attr); +extern void bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode_to_tlv( + struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet, + struct attr *attr); -extern void -bgp_encap_type_pbb_to_tlv( - struct bgp_encap_type_pbb *bet, - struct attr *attr); +extern void bgp_encap_type_pbb_to_tlv(struct bgp_encap_type_pbb *bet, + struct attr *attr); -extern void -bgp_encap_type_vxlan_to_tlv( - struct bgp_encap_type_vxlan *bet, - struct attr *attr); +extern void bgp_encap_type_vxlan_to_tlv(struct bgp_encap_type_vxlan *bet, + struct attr *attr); -extern void -bgp_encap_type_nvgre_to_tlv( - struct bgp_encap_type_nvgre *bet, - struct attr *attr); +extern void bgp_encap_type_nvgre_to_tlv(struct bgp_encap_type_nvgre *bet, + struct attr *attr); -extern void -bgp_encap_type_mpls_to_tlv( - struct bgp_encap_type_mpls *bet, - struct attr *attr); +extern void bgp_encap_type_mpls_to_tlv(struct bgp_encap_type_mpls *bet, + struct attr *attr); extern void -bgp_encap_type_mpls_in_gre_to_tlv( - struct bgp_encap_type_mpls_in_gre *bet, - struct attr *attr); +bgp_encap_type_mpls_in_gre_to_tlv(struct bgp_encap_type_mpls_in_gre *bet, + struct attr *attr); extern void -bgp_encap_type_vxlan_gpe_to_tlv( - struct bgp_encap_type_vxlan_gpe *bet, - struct attr *attr); +bgp_encap_type_vxlan_gpe_to_tlv(struct bgp_encap_type_vxlan_gpe *bet, + struct attr *attr); extern void -bgp_encap_type_mpls_in_udp_to_tlv( - struct bgp_encap_type_mpls_in_udp *bet, - struct attr *attr); +bgp_encap_type_mpls_in_udp_to_tlv(struct bgp_encap_type_mpls_in_udp *bet, + struct attr *attr); /*********************************************************************** * TUNNEL TYPE-SPECIFIC TLV DECODE ***********************************************************************/ -extern int -tlv_to_bgp_encap_type_l2tpv3overip( - struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ - struct bgp_encap_type_l2tpv3_over_ip *bet); /* caller-allocated */ +extern int tlv_to_bgp_encap_type_l2tpv3overip( + struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ + struct bgp_encap_type_l2tpv3_over_ip *bet); /* caller-allocated */ -extern int -tlv_to_bgp_encap_type_gre( - struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ - struct bgp_encap_type_gre *bet); /* caller-allocated */ +extern int tlv_to_bgp_encap_type_gre( + struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ + struct bgp_encap_type_gre *bet); /* caller-allocated */ -extern int -tlv_to_bgp_encap_type_ip_in_ip( - struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ - struct bgp_encap_type_ip_in_ip *bet); /* caller-allocated */ +extern int tlv_to_bgp_encap_type_ip_in_ip( + struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ + struct bgp_encap_type_ip_in_ip *bet); /* caller-allocated */ -extern int -tlv_to_bgp_encap_type_transmit_tunnel_endpoint( - struct bgp_attr_encap_subtlv *stlv, - struct bgp_encap_type_transmit_tunnel_endpoint *bet); +extern int tlv_to_bgp_encap_type_transmit_tunnel_endpoint( + struct bgp_attr_encap_subtlv *stlv, + struct bgp_encap_type_transmit_tunnel_endpoint *bet); -extern int -tlv_to_bgp_encap_type_ipsec_in_tunnel_mode( - struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ - struct bgp_encap_type_ipsec_in_tunnel_mode *bet); /* caller-allocated */ +extern int tlv_to_bgp_encap_type_ipsec_in_tunnel_mode( + struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ + struct bgp_encap_type_ipsec_in_tunnel_mode *bet); /* caller-allocated */ -extern int -tlv_to_bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode( - struct bgp_attr_encap_subtlv *stlv, - struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet); +extern int tlv_to_bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode( + struct bgp_attr_encap_subtlv *stlv, + struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet); -extern int -tlv_to_bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode( - struct bgp_attr_encap_subtlv *stlv, - struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet); +extern int tlv_to_bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode( + struct bgp_attr_encap_subtlv *stlv, + struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet); -extern int -tlv_to_bgp_encap_type_vxlan( - struct bgp_attr_encap_subtlv *stlv, - struct bgp_encap_type_vxlan *bet); +extern int tlv_to_bgp_encap_type_vxlan(struct bgp_attr_encap_subtlv *stlv, + struct bgp_encap_type_vxlan *bet); -extern int -tlv_to_bgp_encap_type_nvgre( - struct bgp_attr_encap_subtlv *stlv, - struct bgp_encap_type_nvgre *bet); +extern int tlv_to_bgp_encap_type_nvgre(struct bgp_attr_encap_subtlv *stlv, + struct bgp_encap_type_nvgre *bet); -extern int -tlv_to_bgp_encap_type_mpls( - struct bgp_attr_encap_subtlv *stlv, - struct bgp_encap_type_mpls *bet); +extern int tlv_to_bgp_encap_type_mpls(struct bgp_attr_encap_subtlv *stlv, + struct bgp_encap_type_mpls *bet); -extern int -tlv_to_bgp_encap_type_mpls( - struct bgp_attr_encap_subtlv *stlv, - struct bgp_encap_type_mpls *bet); +extern int tlv_to_bgp_encap_type_mpls(struct bgp_attr_encap_subtlv *stlv, + struct bgp_encap_type_mpls *bet); extern int -tlv_to_bgp_encap_type_mpls_in_gre( - struct bgp_attr_encap_subtlv *stlv, - struct bgp_encap_type_mpls_in_gre *bet); +tlv_to_bgp_encap_type_mpls_in_gre(struct bgp_attr_encap_subtlv *stlv, + struct bgp_encap_type_mpls_in_gre *bet); extern int -tlv_to_bgp_encap_type_vxlan_gpe( - struct bgp_attr_encap_subtlv *stlv, - struct bgp_encap_type_vxlan_gpe *bet); +tlv_to_bgp_encap_type_vxlan_gpe(struct bgp_attr_encap_subtlv *stlv, + struct bgp_encap_type_vxlan_gpe *bet); extern int -tlv_to_bgp_encap_type_mpls_in_udp( - struct bgp_attr_encap_subtlv *stlv, - struct bgp_encap_type_mpls_in_udp *bet); +tlv_to_bgp_encap_type_mpls_in_udp(struct bgp_attr_encap_subtlv *stlv, + struct bgp_encap_type_mpls_in_udp *bet); -extern int -tlv_to_bgp_encap_type_pbb( - struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ - struct bgp_encap_type_pbb *bet); /* caller-allocated */ +extern int tlv_to_bgp_encap_type_pbb( + struct bgp_attr_encap_subtlv *stlv, /* subtlv chain */ + struct bgp_encap_type_pbb *bet); /* caller-allocated */ #endif /* _QUAGGA_BGP_ENCAP_TLV_H */ diff --git a/bgpd/bgp_encap_types.h b/bgpd/bgp_encap_types.h index 03664fe7a..cf6f70cf5 100644 --- a/bgpd/bgp_encap_types.h +++ b/bgpd/bgp_encap_types.h @@ -21,70 +21,73 @@ #include "bgpd/bgp_ecommunity.h" -/* from http://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#tunnel-types */ +/* from + * http://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#tunnel-types + */ typedef enum { - BGP_ENCAP_TYPE_RESERVED=0, - BGP_ENCAP_TYPE_L2TPV3_OVER_IP=1, - BGP_ENCAP_TYPE_GRE=2, - BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT=3, - BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE=4, - BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE=5, - BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE=6, - BGP_ENCAP_TYPE_IP_IN_IP=7, - BGP_ENCAP_TYPE_VXLAN=8, - BGP_ENCAP_TYPE_NVGRE=9, - BGP_ENCAP_TYPE_MPLS=10, /* NOTE: Encap SAFI&Attribute not used */ - BGP_ENCAP_TYPE_MPLS_IN_GRE=11, - BGP_ENCAP_TYPE_VXLAN_GPE=12, - BGP_ENCAP_TYPE_MPLS_IN_UDP=13, - BGP_ENCAP_TYPE_PBB + BGP_ENCAP_TYPE_RESERVED = 0, + BGP_ENCAP_TYPE_L2TPV3_OVER_IP = 1, + BGP_ENCAP_TYPE_GRE = 2, + BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT = 3, + BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE = 4, + BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE = 5, + BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE = 6, + BGP_ENCAP_TYPE_IP_IN_IP = 7, + BGP_ENCAP_TYPE_VXLAN = 8, + BGP_ENCAP_TYPE_NVGRE = 9, + BGP_ENCAP_TYPE_MPLS = 10, /* NOTE: Encap SAFI&Attribute not used */ + BGP_ENCAP_TYPE_MPLS_IN_GRE = 11, + BGP_ENCAP_TYPE_VXLAN_GPE = 12, + BGP_ENCAP_TYPE_MPLS_IN_UDP = 13, + BGP_ENCAP_TYPE_PBB } bgp_encap_types; typedef enum { - BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION=1, - BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE=2, - BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA=3, - BGP_ENCAP_SUBTLV_TYPE_COLOR=4, - BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT=6 /* speculative, IANA assignment TBD */ + BGP_ENCAP_SUBTLV_TYPE_ENCAPSULATION = 1, + BGP_ENCAP_SUBTLV_TYPE_PROTO_TYPE = 2, + BGP_ENCAP_SUBTLV_TYPE_IPSEC_TA = 3, + BGP_ENCAP_SUBTLV_TYPE_COLOR = 4, + BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT = + 6 /* speculative, IANA assignment TBD */ } bgp_encap_subtlv_types; /* * Tunnel Encapsulation Attribute subtlvs */ struct bgp_tea_subtlv_encap_l2tpv3_over_ip { - uint32_t sessionid; - uint8_t cookie_length; - uint8_t cookie[8]; + uint32_t sessionid; + uint8_t cookie_length; + uint8_t cookie[8]; }; struct bgp_tea_subtlv_encap_gre_key { - uint32_t gre_key; + uint32_t gre_key; }; struct bgp_tea_subtlv_encap_pbb { - uint32_t flag_isid:1; - uint32_t flag_vid:1; - uint32_t isid:24; - uint16_t vid:12; - uint8_t macaddr[6]; + uint32_t flag_isid : 1; + uint32_t flag_vid : 1; + uint32_t isid : 24; + uint16_t vid : 12; + uint8_t macaddr[6]; }; struct bgp_tea_subtlv_proto_type { - uint16_t proto; /* ether-type */ + uint16_t proto; /* ether-type */ }; struct bgp_tea_subtlv_color { - uint32_t color; + uint32_t color; }; /* per draft-rosen-idr-tunnel-encaps */ struct bgp_tea_subtlv_remote_endpoint { - u_char family; /* IPv4 or IPv6 */ - union { - struct in_addr v4; - struct in6_addr v6; - } ip_address; - as_t as4; /* always 4 bytes */ + u_char family; /* IPv4 or IPv6 */ + union { + struct in_addr v4; + struct in6_addr v6; + } ip_address; + as_t as4; /* always 4 bytes */ }; /* @@ -94,9 +97,9 @@ struct bgp_tea_subtlv_remote_endpoint { #define BGP_ENCAP_SUBTLV_IPSEC_TA_SIZE 20 struct bgp_tea_subtlv_ipsec_ta { - uint16_t authenticator_type; /* only type 1 is supported so far */ - uint8_t authenticator_length; /* octets in value field */ - uint8_t value[BGP_ENCAP_SUBTLV_IPSEC_TA_SIZE]; + uint16_t authenticator_type; /* only type 1 is supported so far */ + uint8_t authenticator_length; /* octets in value field */ + uint8_t value[BGP_ENCAP_SUBTLV_IPSEC_TA_SIZE]; }; /* @@ -117,113 +120,112 @@ struct bgp_tea_subtlv_ipsec_ta { * Tunnel Type-specific APIs */ struct bgp_encap_type_reserved { - uint32_t valid_subtlvs; - struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ + uint32_t valid_subtlvs; + struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ }; struct bgp_encap_type_l2tpv3_over_ip { - uint32_t valid_subtlvs; - struct bgp_tea_subtlv_encap_l2tpv3_over_ip st_encap; - struct bgp_tea_subtlv_proto_type st_proto; /* optional */ - struct bgp_tea_subtlv_color st_color; /* optional */ - struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ + uint32_t valid_subtlvs; + struct bgp_tea_subtlv_encap_l2tpv3_over_ip st_encap; + struct bgp_tea_subtlv_proto_type st_proto; /* optional */ + struct bgp_tea_subtlv_color st_color; /* optional */ + struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ }; struct bgp_encap_type_gre { - uint32_t valid_subtlvs; - struct bgp_tea_subtlv_encap_gre_key st_encap; /* optional */ - struct bgp_tea_subtlv_proto_type st_proto; /* optional */ - struct bgp_tea_subtlv_color st_color; /* optional */ - struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ + uint32_t valid_subtlvs; + struct bgp_tea_subtlv_encap_gre_key st_encap; /* optional */ + struct bgp_tea_subtlv_proto_type st_proto; /* optional */ + struct bgp_tea_subtlv_color st_color; /* optional */ + struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ }; struct bgp_encap_type_ip_in_ip { - uint32_t valid_subtlvs; - struct bgp_tea_subtlv_proto_type st_proto; /* optional */ - struct bgp_tea_subtlv_color st_color; /* optional */ - struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ + uint32_t valid_subtlvs; + struct bgp_tea_subtlv_proto_type st_proto; /* optional */ + struct bgp_tea_subtlv_color st_color; /* optional */ + struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ }; struct bgp_encap_type_transmit_tunnel_endpoint { - uint32_t valid_subtlvs; - struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ - /* No subtlvs defined in spec? */ + uint32_t valid_subtlvs; + struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ + /* No subtlvs defined in spec? */ }; struct bgp_encap_type_ipsec_in_tunnel_mode { - uint32_t valid_subtlvs; - struct bgp_tea_subtlv_ipsec_ta st_ipsec_ta; /* optional */ - struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ + uint32_t valid_subtlvs; + struct bgp_tea_subtlv_ipsec_ta st_ipsec_ta; /* optional */ + struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ }; struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode { - uint32_t valid_subtlvs; - struct bgp_tea_subtlv_ipsec_ta st_ipsec_ta; /* optional */ - struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ + uint32_t valid_subtlvs; + struct bgp_tea_subtlv_ipsec_ta st_ipsec_ta; /* optional */ + struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ }; struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode { - uint32_t valid_subtlvs; - struct bgp_tea_subtlv_ipsec_ta st_ipsec_ta; /* optional */ - struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ + uint32_t valid_subtlvs; + struct bgp_tea_subtlv_ipsec_ta st_ipsec_ta; /* optional */ + struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ }; #define VXLAN_ENCAP_MASK_VNID_VALID 0x80000000 #define VXLAN_ENCAP_MASK_MAC_VALID 0x40000000 struct bgp_encap_type_vxlan { - uint32_t valid_subtlvs; - struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ - /* draft-ietf-idr-tunnel-encaps-02 */ - uint32_t vnid; /* does not include V and M bit */ - uint8_t *mac_address; /* optional */ + uint32_t valid_subtlvs; + struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ + /* draft-ietf-idr-tunnel-encaps-02 */ + uint32_t vnid; /* does not include V and M bit */ + uint8_t *mac_address; /* optional */ }; struct bgp_encap_type_nvgre { - uint32_t valid_subtlvs; - struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ - /* No subtlvs defined in spec? */ + uint32_t valid_subtlvs; + struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ + /* No subtlvs defined in spec? */ }; struct bgp_encap_type_mpls { - uint32_t valid_subtlvs; - struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ - /* No subtlvs defined in spec? */ + uint32_t valid_subtlvs; + struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ + /* No subtlvs defined in spec? */ }; struct bgp_encap_type_mpls_in_gre { - uint32_t valid_subtlvs; - struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ - /* No subtlvs defined in spec? */ + uint32_t valid_subtlvs; + struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ + /* No subtlvs defined in spec? */ }; struct bgp_encap_type_vxlan_gpe { - uint32_t valid_subtlvs; - struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ - /* No subtlvs defined in spec? */ + uint32_t valid_subtlvs; + struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ + /* No subtlvs defined in spec? */ }; struct bgp_encap_type_mpls_in_udp { - uint32_t valid_subtlvs; - struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ - /* No subtlvs defined in spec? */ + uint32_t valid_subtlvs; + struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ + /* No subtlvs defined in spec? */ }; struct bgp_encap_type_pbb { - uint32_t valid_subtlvs; - struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ - struct bgp_tea_subtlv_encap_pbb st_encap; + uint32_t valid_subtlvs; + struct bgp_tea_subtlv_remote_endpoint st_endpoint; /* optional */ + struct bgp_tea_subtlv_encap_pbb st_encap; }; -static inline void -encode_encap_extcomm (bgp_encap_types tnl_type, - struct ecommunity_val *eval) +static inline void encode_encap_extcomm(bgp_encap_types tnl_type, + struct ecommunity_val *eval) { - memset (eval, 0, sizeof (*eval)); - eval->val[0] = ECOMMUNITY_ENCODE_OPAQUE; - eval->val[1] = ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP; - eval->val[6] = ((tnl_type) >> 8) & 0xff; - eval->val[7] = (tnl_type) & 0xff; + memset(eval, 0, sizeof(*eval)); + eval->val[0] = ECOMMUNITY_ENCODE_OPAQUE; + eval->val[1] = ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP; + eval->val[6] = ((tnl_type) >> 8) & 0xff; + eval->val[7] = (tnl_type)&0xff; } #endif /* _QUAGGA_BGP_ENCAP_TYPES_H */ diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 46e97cc50..f0081e6d0 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -57,12 +57,10 @@ DEFINE_QOBJ_TYPE(bgpevpn) /* * Static function declarations */ -static void -delete_evpn_route_entry (struct bgp *bgp, struct bgpevpn *vpn, - afi_t afi, safi_t safi, struct bgp_node *rn, - struct bgp_info **ri); -static int -delete_all_vni_routes (struct bgp *bgp, struct bgpevpn *vpn); +static void delete_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, + afi_t afi, safi_t safi, struct bgp_node *rn, + struct bgp_info **ri); +static int delete_all_vni_routes(struct bgp *bgp, struct bgpevpn *vpn); /* * Private functions. @@ -71,241 +69,226 @@ delete_all_vni_routes (struct bgp *bgp, struct bgpevpn *vpn); /* * Make vni hash key. */ -static unsigned int -vni_hash_key_make(void *p) +static unsigned int vni_hash_key_make(void *p) { - struct bgpevpn *vpn = p; - return (jhash_1word(vpn->vni, 0)); + struct bgpevpn *vpn = p; + return (jhash_1word(vpn->vni, 0)); } /* * Comparison function for vni hash */ -static int -vni_hash_cmp (const void *p1, const void *p2) +static int vni_hash_cmp(const void *p1, const void *p2) { - const struct bgpevpn *vpn1 = p1; - const struct bgpevpn *vpn2 = p2; + const struct bgpevpn *vpn1 = p1; + const struct bgpevpn *vpn2 = p2; - if (!vpn1 && !vpn2) - return 1; - if (!vpn1 || !vpn2) - return 0; - return(vpn1->vni == vpn2->vni); + if (!vpn1 && !vpn2) + return 1; + if (!vpn1 || !vpn2) + return 0; + return (vpn1->vni == vpn2->vni); } /* * Make import route target hash key. */ -static unsigned int -import_rt_hash_key_make (void *p) +static unsigned int import_rt_hash_key_make(void *p) { - struct irt_node *irt = p; - char *pnt = irt->rt.val; - unsigned int key = 0; - int c=0; + struct irt_node *irt = p; + char *pnt = irt->rt.val; + unsigned int key = 0; + int c = 0; - key += pnt[c]; - key += pnt[c + 1]; - key += pnt[c + 2]; - key += pnt[c + 3]; - key += pnt[c + 4]; - key += pnt[c + 5]; - key += pnt[c + 6]; - key += pnt[c + 7]; + key += pnt[c]; + key += pnt[c + 1]; + key += pnt[c + 2]; + key += pnt[c + 3]; + key += pnt[c + 4]; + key += pnt[c + 5]; + key += pnt[c + 6]; + key += pnt[c + 7]; - return (key); + return (key); } /* * Comparison function for import rt hash */ -static int -import_rt_hash_cmp (const void *p1, const void *p2) +static int import_rt_hash_cmp(const void *p1, const void *p2) { - const struct irt_node *irt1 = p1; - const struct irt_node *irt2 = p2; + const struct irt_node *irt1 = p1; + const struct irt_node *irt2 = p2; - if (irt1 == NULL && irt2 == NULL) - return 1; + if (irt1 == NULL && irt2 == NULL) + return 1; - if (irt1 == NULL || irt2 == NULL) - return 0; + if (irt1 == NULL || irt2 == NULL) + return 0; - return(memcmp(irt1->rt.val, irt2->rt.val, ECOMMUNITY_SIZE) == 0); + return (memcmp(irt1->rt.val, irt2->rt.val, ECOMMUNITY_SIZE) == 0); } /* * Create a new import_rt */ -static struct irt_node * -import_rt_new (struct bgp *bgp, struct ecommunity_val *rt) +static struct irt_node *import_rt_new(struct bgp *bgp, + struct ecommunity_val *rt) { - struct irt_node *irt; + struct irt_node *irt; - if (!bgp) - return NULL; + if (!bgp) + return NULL; - irt = XCALLOC (MTYPE_BGP_EVPN_IMPORT_RT, sizeof (struct irt_node)); - if (!irt) - return NULL; + irt = XCALLOC(MTYPE_BGP_EVPN_IMPORT_RT, sizeof(struct irt_node)); + if (!irt) + return NULL; - irt->rt = *rt; - irt->vnis = list_new (); + irt->rt = *rt; + irt->vnis = list_new(); - /* Add to hash */ - if (!hash_get(bgp->import_rt_hash, irt, hash_alloc_intern)) - { - XFREE(MTYPE_BGP_EVPN_IMPORT_RT, irt); - return NULL; - } + /* Add to hash */ + if (!hash_get(bgp->import_rt_hash, irt, hash_alloc_intern)) { + XFREE(MTYPE_BGP_EVPN_IMPORT_RT, irt); + return NULL; + } - return irt; + return irt; } /* * Free the import rt node */ -static void -import_rt_free (struct bgp *bgp, struct irt_node *irt) +static void import_rt_free(struct bgp *bgp, struct irt_node *irt) { - hash_release(bgp->import_rt_hash, irt); - XFREE(MTYPE_BGP_EVPN_IMPORT_RT, irt); + hash_release(bgp->import_rt_hash, irt); + XFREE(MTYPE_BGP_EVPN_IMPORT_RT, irt); } /* * Function to lookup Import RT node - used to map a RT to set of * VNIs importing routes with that RT. */ -static struct irt_node * -lookup_import_rt (struct bgp *bgp, struct ecommunity_val *rt) +static struct irt_node *lookup_import_rt(struct bgp *bgp, + struct ecommunity_val *rt) { - struct irt_node *irt; - struct irt_node tmp; + struct irt_node *irt; + struct irt_node tmp; - memset(&tmp, 0, sizeof(struct irt_node)); - memcpy(&tmp.rt, rt, ECOMMUNITY_SIZE); - irt = hash_lookup(bgp->import_rt_hash, &tmp); - return irt; + memset(&tmp, 0, sizeof(struct irt_node)); + memcpy(&tmp.rt, rt, ECOMMUNITY_SIZE); + irt = hash_lookup(bgp->import_rt_hash, &tmp); + return irt; } /* * Is specified VNI present on the RT's list of "importing" VNIs? */ -static int -is_vni_present_in_irt_vnis (struct list *vnis, struct bgpevpn *vpn) +static int is_vni_present_in_irt_vnis(struct list *vnis, struct bgpevpn *vpn) { - struct listnode *node, *nnode; - struct bgpevpn *tmp_vpn; + struct listnode *node, *nnode; + struct bgpevpn *tmp_vpn; - for (ALL_LIST_ELEMENTS (vnis, node, nnode, tmp_vpn)) - { - if (tmp_vpn == vpn) - return 1; - } + for (ALL_LIST_ELEMENTS(vnis, node, nnode, tmp_vpn)) { + if (tmp_vpn == vpn) + return 1; + } - return 0; + return 0; } /* * Compare Route Targets. */ -static int -evpn_route_target_cmp (struct ecommunity *ecom1, struct ecommunity *ecom2) +static int evpn_route_target_cmp(struct ecommunity *ecom1, + struct ecommunity *ecom2) { - if (ecom1 && !ecom2) - return -1; + if (ecom1 && !ecom2) + return -1; - if (!ecom1 && ecom2) - return 1; + if (!ecom1 && ecom2) + return 1; - if (!ecom1 && !ecom2) - return 0; + if (!ecom1 && !ecom2) + return 0; - if (ecom1->str && !ecom2->str) - return -1; + if (ecom1->str && !ecom2->str) + return -1; - if (!ecom1->str && ecom2->str) - return 1; + if (!ecom1->str && ecom2->str) + return 1; - if (!ecom1->str && !ecom2->str) - return 0; + if (!ecom1->str && !ecom2->str) + return 0; - return strcmp(ecom1->str, ecom2->str); + return strcmp(ecom1->str, ecom2->str); } /* * Mask off global-admin field of specified extended community (RT), * just retain the local-admin field. */ -static inline void -mask_ecom_global_admin (struct ecommunity_val *dst, - struct ecommunity_val *src) +static inline void mask_ecom_global_admin(struct ecommunity_val *dst, + struct ecommunity_val *src) { - u_char type; + u_char type; - type = src->val[0]; - dst->val[0] = 0; - if (type == ECOMMUNITY_ENCODE_AS) - { - dst->val[2] = dst->val[3] = 0; - } - else if (type == ECOMMUNITY_ENCODE_AS4 || - type == ECOMMUNITY_ENCODE_IP) - { - dst->val[2] = dst->val[3] = 0; - dst->val[4] = dst->val[5] = 0; - } + type = src->val[0]; + dst->val[0] = 0; + if (type == ECOMMUNITY_ENCODE_AS) { + dst->val[2] = dst->val[3] = 0; + } else if (type == ECOMMUNITY_ENCODE_AS4 + || type == ECOMMUNITY_ENCODE_IP) { + dst->val[2] = dst->val[3] = 0; + dst->val[4] = dst->val[5] = 0; + } } /* * Map one RT to specified VNI. */ -static void -map_vni_to_rt (struct bgp *bgp, struct bgpevpn *vpn, - struct ecommunity_val *eval) +static void map_vni_to_rt(struct bgp *bgp, struct bgpevpn *vpn, + struct ecommunity_val *eval) { - struct irt_node *irt; - struct ecommunity_val eval_tmp; + struct irt_node *irt; + struct ecommunity_val eval_tmp; - /* If using "automatic" RT, we only care about the local-admin sub-field. - * This is to facilitate using VNI as the RT for EBGP peering too. - */ - memcpy (&eval_tmp, eval, ECOMMUNITY_SIZE); - if (!is_import_rt_configured (vpn)) - mask_ecom_global_admin (&eval_tmp, eval); + /* If using "automatic" RT, we only care about the local-admin + * sub-field. + * This is to facilitate using VNI as the RT for EBGP peering too. + */ + memcpy(&eval_tmp, eval, ECOMMUNITY_SIZE); + if (!is_import_rt_configured(vpn)) + mask_ecom_global_admin(&eval_tmp, eval); - irt = lookup_import_rt (bgp, &eval_tmp); - if (irt && irt->vnis) - if (is_vni_present_in_irt_vnis (irt->vnis, vpn)) - /* Already mapped. */ - return; + irt = lookup_import_rt(bgp, &eval_tmp); + if (irt && irt->vnis) + if (is_vni_present_in_irt_vnis(irt->vnis, vpn)) + /* Already mapped. */ + return; - if (!irt) - { - irt = import_rt_new (bgp, &eval_tmp); - assert (irt); - } + if (!irt) { + irt = import_rt_new(bgp, &eval_tmp); + assert(irt); + } - /* Add VNI to the hash list for this RT. */ - listnode_add (irt->vnis, vpn); + /* Add VNI to the hash list for this RT. */ + listnode_add(irt->vnis, vpn); } /* * Unmap specified VNI from specified RT. If there are no other * VNIs for this RT, then the RT hash is deleted. */ -static void -unmap_vni_from_rt (struct bgp *bgp, struct bgpevpn *vpn, - struct irt_node *irt) +static void unmap_vni_from_rt(struct bgp *bgp, struct bgpevpn *vpn, + struct irt_node *irt) { - /* Delete VNI from hash list for this RT. */ - listnode_delete (irt->vnis, vpn); - if (!listnode_head (irt->vnis)) - { - list_free (irt->vnis); - import_rt_free (bgp, irt); - } + /* Delete VNI from hash list for this RT. */ + listnode_delete(irt->vnis, vpn); + if (!listnode_head(irt->vnis)) { + list_free(irt->vnis); + import_rt_free(bgp, irt); + } } /* @@ -316,257 +299,253 @@ unmap_vni_from_rt (struct bgp *bgp, struct bgpevpn *vpn, * VNIs but the same across routers (in the same AS) for a particular * VNI. */ -static void -form_auto_rt (struct bgp *bgp, struct bgpevpn *vpn, - struct list *rtl) +static void form_auto_rt(struct bgp *bgp, struct bgpevpn *vpn, struct list *rtl) { - struct ecommunity_val eval; - struct ecommunity *ecomadd; + struct ecommunity_val eval; + struct ecommunity *ecomadd; - encode_route_target_as ((bgp->as & 0xFFFF), vpn->vni, &eval); + encode_route_target_as((bgp->as & 0xFFFF), vpn->vni, &eval); - ecomadd = ecommunity_new (); - ecommunity_add_val (ecomadd, &eval); - listnode_add_sort (rtl, ecomadd); + ecomadd = ecommunity_new(); + ecommunity_add_val(ecomadd, &eval); + listnode_add_sort(rtl, ecomadd); } /* * Derive RD and RT for a VNI automatically. Invoked at the time of * creation of a VNI. */ -static void -derive_rd_rt_for_vni (struct bgp *bgp, struct bgpevpn *vpn) +static void derive_rd_rt_for_vni(struct bgp *bgp, struct bgpevpn *vpn) { - bgp_evpn_derive_auto_rd (bgp, vpn); - bgp_evpn_derive_auto_rt_import (bgp, vpn); - bgp_evpn_derive_auto_rt_export (bgp, vpn); + bgp_evpn_derive_auto_rd(bgp, vpn); + bgp_evpn_derive_auto_rt_import(bgp, vpn); + bgp_evpn_derive_auto_rt_export(bgp, vpn); } /* * Add (update) or delete MACIP from zebra. */ -static int -bgp_zebra_send_remote_macip (struct bgp *bgp, struct bgpevpn *vpn, - struct prefix_evpn *p, - struct in_addr remote_vtep_ip, - int add, u_char sticky) -{ - struct stream *s; - int ipa_len; - char buf1[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; - char buf3[INET6_ADDRSTRLEN]; - - /* Check socket. */ - if (!zclient || zclient->sock < 0) - return 0; - - /* Don't try to register if Zebra doesn't know of this instance. */ - if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) - return 0; - - s = zclient->obuf; - stream_reset (s); - - zclient_create_header (s, add ? ZEBRA_REMOTE_MACIP_ADD : ZEBRA_REMOTE_MACIP_DEL, - bgp->vrf_id); - stream_putl(s, vpn->vni); - stream_put (s, &p->prefix.mac.octet, ETHER_ADDR_LEN); /* Mac Addr */ - /* IP address length and IP address, if any. */ - if (IS_EVPN_PREFIX_IPADDR_NONE(p)) - stream_putl(s, 0); - else - { - ipa_len = IS_EVPN_PREFIX_IPADDR_V4(p) ? - IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN; - stream_putl(s, ipa_len); - stream_put (s, &p->prefix.ip.ip.addr, ipa_len); - } - stream_put_in_addr(s, &remote_vtep_ip); - - /* TX MAC sticky status */ - if (add) - stream_putc (s, sticky); - - stream_putw_at (s, 0, stream_get_endp (s)); - - if (bgp_debug_zebra (NULL)) - zlog_debug("Tx %s MACIP, VNI %u %sMAC %s IP %s remote VTEP %s", - add ? "ADD" : "DEL", vpn->vni, - sticky ? "sticky " : "", - prefix_mac2str (&p->prefix.mac, buf1, sizeof(buf1)), - ipaddr2str (&p->prefix.ip, buf3, sizeof(buf3)), - inet_ntop(AF_INET, &remote_vtep_ip, buf2, sizeof(buf2))); - - return zclient_send_message(zclient); +static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, + struct prefix_evpn *p, + struct in_addr remote_vtep_ip, int add, + u_char sticky) +{ + struct stream *s; + int ipa_len; + char buf1[ETHER_ADDR_STRLEN]; + char buf2[INET6_ADDRSTRLEN]; + char buf3[INET6_ADDRSTRLEN]; + + /* Check socket. */ + if (!zclient || zclient->sock < 0) + return 0; + + /* Don't try to register if Zebra doesn't know of this instance. */ + if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + return 0; + + s = zclient->obuf; + stream_reset(s); + + zclient_create_header( + s, add ? ZEBRA_REMOTE_MACIP_ADD : ZEBRA_REMOTE_MACIP_DEL, + bgp->vrf_id); + stream_putl(s, vpn->vni); + stream_put(s, &p->prefix.mac.octet, ETHER_ADDR_LEN); /* Mac Addr */ + /* IP address length and IP address, if any. */ + if (IS_EVPN_PREFIX_IPADDR_NONE(p)) + stream_putl(s, 0); + else { + ipa_len = IS_EVPN_PREFIX_IPADDR_V4(p) ? IPV4_MAX_BYTELEN + : IPV6_MAX_BYTELEN; + stream_putl(s, ipa_len); + stream_put(s, &p->prefix.ip.ip.addr, ipa_len); + } + stream_put_in_addr(s, &remote_vtep_ip); + + /* TX MAC sticky status */ + if (add) + stream_putc(s, sticky); + + stream_putw_at(s, 0, stream_get_endp(s)); + + if (bgp_debug_zebra(NULL)) + zlog_debug("Tx %s MACIP, VNI %u %sMAC %s IP %s remote VTEP %s", + add ? "ADD" : "DEL", vpn->vni, + sticky ? "sticky " : "", + prefix_mac2str(&p->prefix.mac, buf1, sizeof(buf1)), + ipaddr2str(&p->prefix.ip, buf3, sizeof(buf3)), + inet_ntop(AF_INET, &remote_vtep_ip, buf2, + sizeof(buf2))); + + return zclient_send_message(zclient); } /* * Add (update) or delete remote VTEP from zebra. */ -static int -bgp_zebra_send_remote_vtep (struct bgp *bgp, struct bgpevpn *vpn, - struct prefix_evpn *p, int add) +static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn, + struct prefix_evpn *p, int add) { - struct stream *s; + struct stream *s; - /* Check socket. */ - if (!zclient || zclient->sock < 0) - return 0; + /* Check socket. */ + if (!zclient || zclient->sock < 0) + return 0; - /* Don't try to register if Zebra doesn't know of this instance. */ - if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) - return 0; + /* Don't try to register if Zebra doesn't know of this instance. */ + if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + return 0; - s = zclient->obuf; - stream_reset (s); + s = zclient->obuf; + stream_reset(s); - zclient_create_header (s, add ? ZEBRA_REMOTE_VTEP_ADD : ZEBRA_REMOTE_VTEP_DEL, - bgp->vrf_id); - stream_putl(s, vpn->vni); - if (IS_EVPN_PREFIX_IPADDR_V4(p)) - stream_put_in_addr(s, &p->prefix.ip.ipaddr_v4); - else if (IS_EVPN_PREFIX_IPADDR_V6(p)) - { - zlog_err ("Bad remote IP when trying to %s remote VTEP for VNI %u", - add ? "ADD" : "DEL", vpn->vni); - return -1; - } + zclient_create_header( + s, add ? ZEBRA_REMOTE_VTEP_ADD : ZEBRA_REMOTE_VTEP_DEL, + bgp->vrf_id); + stream_putl(s, vpn->vni); + if (IS_EVPN_PREFIX_IPADDR_V4(p)) + stream_put_in_addr(s, &p->prefix.ip.ipaddr_v4); + else if (IS_EVPN_PREFIX_IPADDR_V6(p)) { + zlog_err( + "Bad remote IP when trying to %s remote VTEP for VNI %u", + add ? "ADD" : "DEL", vpn->vni); + return -1; + } - stream_putw_at (s, 0, stream_get_endp (s)); + stream_putw_at(s, 0, stream_get_endp(s)); - if (bgp_debug_zebra (NULL)) - zlog_debug("Tx %s Remote VTEP, VNI %u remote VTEP %s", - add ? "ADD" : "DEL", vpn->vni, - inet_ntoa (p->prefix.ip.ipaddr_v4)); + if (bgp_debug_zebra(NULL)) + zlog_debug("Tx %s Remote VTEP, VNI %u remote VTEP %s", + add ? "ADD" : "DEL", vpn->vni, + inet_ntoa(p->prefix.ip.ipaddr_v4)); - return zclient_send_message(zclient); + return zclient_send_message(zclient); } /* * Build extended communities for EVPN route. RT and ENCAP are * applicable to all routes. */ -static void -build_evpn_route_extcomm (struct bgpevpn *vpn, struct attr *attr) +static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr) { - struct ecommunity ecom_encap; - struct ecommunity ecom_sticky; - struct ecommunity_val eval; - struct ecommunity_val eval_sticky; - bgp_encap_types tnl_type; - struct listnode *node, *nnode; - struct ecommunity *ecom; - u_int32_t seqnum; + struct ecommunity ecom_encap; + struct ecommunity ecom_sticky; + struct ecommunity_val eval; + struct ecommunity_val eval_sticky; + bgp_encap_types tnl_type; + struct listnode *node, *nnode; + struct ecommunity *ecom; + u_int32_t seqnum; - /* Encap */ - tnl_type = BGP_ENCAP_TYPE_VXLAN; - memset (&ecom_encap, 0, sizeof (ecom_encap)); - encode_encap_extcomm (tnl_type, &eval); - ecom_encap.size = 1; - ecom_encap.val = (u_int8_t *)eval.val; + /* Encap */ + tnl_type = BGP_ENCAP_TYPE_VXLAN; + memset(&ecom_encap, 0, sizeof(ecom_encap)); + encode_encap_extcomm(tnl_type, &eval); + ecom_encap.size = 1; + ecom_encap.val = (u_int8_t *)eval.val; - /* Add Encap */ - attr->ecommunity = ecommunity_dup (&ecom_encap); + /* Add Encap */ + attr->ecommunity = ecommunity_dup(&ecom_encap); - /* Add the export RTs */ - for (ALL_LIST_ELEMENTS (vpn->export_rtl, node, nnode, ecom)) - attr->ecommunity = ecommunity_merge (attr->ecommunity, ecom); + /* Add the export RTs */ + for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) + attr->ecommunity = ecommunity_merge(attr->ecommunity, ecom); - if (attr->sticky) - { - seqnum = 0; - memset (&ecom_sticky, 0, sizeof (ecom_sticky)); - encode_mac_mobility_extcomm(1, seqnum, &eval_sticky); - ecom_sticky.size = 1; - ecom_sticky.val = (u_int8_t *)eval_sticky.val; - attr->ecommunity = ecommunity_merge (attr->ecommunity, &ecom_sticky); - } + if (attr->sticky) { + seqnum = 0; + memset(&ecom_sticky, 0, sizeof(ecom_sticky)); + encode_mac_mobility_extcomm(1, seqnum, &eval_sticky); + ecom_sticky.size = 1; + ecom_sticky.val = (u_int8_t *)eval_sticky.val; + attr->ecommunity = + ecommunity_merge(attr->ecommunity, &ecom_sticky); + } - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES); + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES); } /* * Add MAC mobility extended community to attribute. */ -static void -add_mac_mobility_to_attr (u_int32_t seq_num, struct attr *attr) -{ - struct ecommunity ecom_tmp; - struct ecommunity_val eval; - struct ecommunity *ecom_mm; - int i; - u_int8_t *pnt; - int type = 0; - int sub_type = 0; - - /* Build MM */ - encode_mac_mobility_extcomm (0, seq_num, &eval); - - /* Find current MM ecommunity */ - ecom_mm = NULL; - - if (attr->ecommunity) - { - for (i = 0; i < attr->ecommunity->size; i++) - { - pnt = attr->ecommunity->val + (i * 8); - type = *pnt++; - sub_type = *pnt++; - - if (type == ECOMMUNITY_ENCODE_EVPN && sub_type == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY) - { - ecom_mm = (struct ecommunity*) attr->ecommunity->val + (i * 8); - break; - } - } - } - - /* Update the existing MM ecommunity */ - if (ecom_mm) - { - memcpy(ecom_mm->val, eval.val, sizeof(char) * ECOMMUNITY_SIZE); - } - /* Add MM to existing */ - else - { - memset (&ecom_tmp, 0, sizeof (ecom_tmp)); - ecom_tmp.size = 1; - ecom_tmp.val = (u_int8_t *)eval.val; - - attr->ecommunity = ecommunity_merge (attr->ecommunity, &ecom_tmp); - } +static void add_mac_mobility_to_attr(u_int32_t seq_num, struct attr *attr) +{ + struct ecommunity ecom_tmp; + struct ecommunity_val eval; + struct ecommunity *ecom_mm; + int i; + u_int8_t *pnt; + int type = 0; + int sub_type = 0; + + /* Build MM */ + encode_mac_mobility_extcomm(0, seq_num, &eval); + + /* Find current MM ecommunity */ + ecom_mm = NULL; + + if (attr->ecommunity) { + for (i = 0; i < attr->ecommunity->size; i++) { + pnt = attr->ecommunity->val + (i * 8); + type = *pnt++; + sub_type = *pnt++; + + if (type == ECOMMUNITY_ENCODE_EVPN + && sub_type + == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY) { + ecom_mm = (struct ecommunity *) + attr->ecommunity->val + + (i * 8); + break; + } + } + } + + /* Update the existing MM ecommunity */ + if (ecom_mm) { + memcpy(ecom_mm->val, eval.val, sizeof(char) * ECOMMUNITY_SIZE); + } + /* Add MM to existing */ + else { + memset(&ecom_tmp, 0, sizeof(ecom_tmp)); + ecom_tmp.size = 1; + ecom_tmp.val = (u_int8_t *)eval.val; + + attr->ecommunity = + ecommunity_merge(attr->ecommunity, &ecom_tmp); + } } /* Install EVPN route into zebra. */ -static int -evpn_zebra_install (struct bgp *bgp, struct bgpevpn *vpn, - struct prefix_evpn *p, struct in_addr remote_vtep_ip, - u_char sticky) +static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn, + struct prefix_evpn *p, + struct in_addr remote_vtep_ip, u_char sticky) { - int ret; + int ret; - if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) - ret = bgp_zebra_send_remote_macip (bgp, vpn, p, remote_vtep_ip, 1, sticky); - else - ret = bgp_zebra_send_remote_vtep (bgp, vpn, p, 1); + if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) + ret = bgp_zebra_send_remote_macip(bgp, vpn, p, remote_vtep_ip, + 1, sticky); + else + ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, 1); - return ret; + return ret; } /* Uninstall EVPN route from zebra. */ -static int -evpn_zebra_uninstall (struct bgp *bgp, struct bgpevpn *vpn, - struct prefix_evpn *p, struct in_addr remote_vtep_ip) +static int evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn, + struct prefix_evpn *p, + struct in_addr remote_vtep_ip) { - int ret; + int ret; - if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) - ret = bgp_zebra_send_remote_macip (bgp, vpn, p, remote_vtep_ip, 0, 0); - else - ret = bgp_zebra_send_remote_vtep (bgp, vpn, p, 0); + if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) + ret = bgp_zebra_send_remote_macip(bgp, vpn, p, remote_vtep_ip, + 0, 0); + else + ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, 0); - return ret; + return ret; } /* @@ -574,600 +553,583 @@ evpn_zebra_uninstall (struct bgp *bgp, struct bgpevpn *vpn, * by a "remote" best route. The prior route has to be deleted and withdrawn * from peers. */ -static void -evpn_delete_old_local_route (struct bgp *bgp, struct bgpevpn *vpn, - struct bgp_node *rn, struct bgp_info *old_local) +static void evpn_delete_old_local_route(struct bgp *bgp, struct bgpevpn *vpn, + struct bgp_node *rn, + struct bgp_info *old_local) { - struct bgp_node *global_rn; - struct bgp_info *ri; - afi_t afi = AFI_L2VPN; - safi_t safi = SAFI_EVPN; + struct bgp_node *global_rn; + struct bgp_info *ri; + afi_t afi = AFI_L2VPN; + safi_t safi = SAFI_EVPN; - /* Locate route node in the global EVPN routing table. Note that - * this table is a 2-level tree (RD-level + Prefix-level) similar to - * L3VPN routes. - */ - global_rn = bgp_afi_node_lookup (bgp->rib[afi][safi], afi, safi, - (struct prefix *)&rn->p, &vpn->prd); - if (global_rn) - { - /* Delete route entry in the global EVPN table. */ - delete_evpn_route_entry (bgp, vpn, afi, safi, global_rn, &ri); + /* Locate route node in the global EVPN routing table. Note that + * this table is a 2-level tree (RD-level + Prefix-level) similar to + * L3VPN routes. + */ + global_rn = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi, + (struct prefix *)&rn->p, &vpn->prd); + if (global_rn) { + /* Delete route entry in the global EVPN table. */ + delete_evpn_route_entry(bgp, vpn, afi, safi, global_rn, &ri); - /* Schedule for processing - withdraws to peers happen from - * this table. - */ - if (ri) - bgp_process (bgp, global_rn, afi, safi); - bgp_unlock_node (global_rn); - } + /* Schedule for processing - withdraws to peers happen from + * this table. + */ + if (ri) + bgp_process(bgp, global_rn, afi, safi); + bgp_unlock_node(global_rn); + } - /* Delete route entry in the VNI route table, caller to remove. */ - bgp_info_delete (rn, old_local); + /* Delete route entry in the VNI route table, caller to remove. */ + bgp_info_delete(rn, old_local); } /* * Calculate the best path for an EVPN route. Install/update best path in zebra, * if appropriate. */ -static int -evpn_route_select_install (struct bgp *bgp, struct bgpevpn *vpn, - struct bgp_node *rn) -{ - struct bgp_info *old_select, *new_select; - struct bgp_info_pair old_and_new; - afi_t afi = AFI_L2VPN; - safi_t safi = SAFI_EVPN; - int ret = 0; - - /* Compute the best path. */ - bgp_best_selection (bgp, rn, &bgp->maxpaths[afi][safi], - &old_and_new, afi, safi); - old_select = old_and_new.old; - new_select = old_and_new.new; - - /* If the best path hasn't changed - see if there is still something to update - * to zebra RIB. - */ - if (old_select && old_select == new_select && - old_select->type == ZEBRA_ROUTE_BGP && - old_select->sub_type == BGP_ROUTE_NORMAL && - !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR) && - !CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED) && - !bgp->addpath_tx_used[afi][safi]) - { - if (bgp_zebra_has_route_changed (rn, old_select)) - ret = evpn_zebra_install (bgp, vpn, (struct prefix_evpn *)&rn->p, - old_select->attr->nexthop, - old_select->attr->sticky); - UNSET_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG); - bgp_zebra_clear_route_change_flags (rn); - return ret; - } - - /* If the user did a "clear" this flag will be set */ - UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR); - - /* bestpath has changed; update relevant fields and install or uninstall - * into the zebra RIB. - */ - if (old_select || new_select) - bgp_bump_version(rn); - - if (old_select) - bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED); - if (new_select) - { - bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED); - bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED); - UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG); - } - - if (new_select - && new_select->type == ZEBRA_ROUTE_BGP - && new_select->sub_type == BGP_ROUTE_NORMAL) - { - ret = evpn_zebra_install (bgp, vpn, (struct prefix_evpn *) &rn->p, - new_select->attr->nexthop, - new_select->attr->sticky); - /* If an old best existed and it was a "local" route, the only reason - * it would be supplanted is due to MAC mobility procedures. So, we - * need to do an implicit delete and withdraw that route from peers. - */ - if (old_select - && old_select->peer == bgp->peer_self - && old_select->type == ZEBRA_ROUTE_BGP - && old_select->sub_type == BGP_ROUTE_STATIC) - evpn_delete_old_local_route (bgp, vpn, rn, old_select); - } - else - { - if (old_select - && old_select->type == ZEBRA_ROUTE_BGP - && old_select->sub_type == BGP_ROUTE_NORMAL) - ret = evpn_zebra_uninstall (bgp, vpn, (struct prefix_evpn *) &rn->p, - old_select->attr->nexthop); - } - - /* Clear any route change flags. */ - bgp_zebra_clear_route_change_flags (rn); - - /* Reap old select bgp_info, if it has been removed */ - if (old_select && CHECK_FLAG (old_select->flags, BGP_INFO_REMOVED)) - bgp_info_reap (rn, old_select); - - return ret; +static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, + struct bgp_node *rn) +{ + struct bgp_info *old_select, *new_select; + struct bgp_info_pair old_and_new; + afi_t afi = AFI_L2VPN; + safi_t safi = SAFI_EVPN; + int ret = 0; + + /* Compute the best path. */ + bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new, + afi, safi); + old_select = old_and_new.old; + new_select = old_and_new.new; + + /* If the best path hasn't changed - see if there is still something to + * update + * to zebra RIB. + */ + if (old_select && old_select == new_select + && old_select->type == ZEBRA_ROUTE_BGP + && old_select->sub_type == BGP_ROUTE_NORMAL + && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR) + && !CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED) + && !bgp->addpath_tx_used[afi][safi]) { + if (bgp_zebra_has_route_changed(rn, old_select)) + ret = evpn_zebra_install(bgp, vpn, + (struct prefix_evpn *)&rn->p, + old_select->attr->nexthop, + old_select->attr->sticky); + UNSET_FLAG(old_select->flags, BGP_INFO_MULTIPATH_CHG); + bgp_zebra_clear_route_change_flags(rn); + return ret; + } + + /* If the user did a "clear" this flag will be set */ + UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR); + + /* bestpath has changed; update relevant fields and install or uninstall + * into the zebra RIB. + */ + if (old_select || new_select) + bgp_bump_version(rn); + + if (old_select) + bgp_info_unset_flag(rn, old_select, BGP_INFO_SELECTED); + if (new_select) { + bgp_info_set_flag(rn, new_select, BGP_INFO_SELECTED); + bgp_info_unset_flag(rn, new_select, BGP_INFO_ATTR_CHANGED); + UNSET_FLAG(new_select->flags, BGP_INFO_MULTIPATH_CHG); + } + + if (new_select && new_select->type == ZEBRA_ROUTE_BGP + && new_select->sub_type == BGP_ROUTE_NORMAL) { + ret = evpn_zebra_install(bgp, vpn, (struct prefix_evpn *)&rn->p, + new_select->attr->nexthop, + new_select->attr->sticky); + /* If an old best existed and it was a "local" route, the only + * reason + * it would be supplanted is due to MAC mobility procedures. So, + * we + * need to do an implicit delete and withdraw that route from + * peers. + */ + if (old_select && old_select->peer == bgp->peer_self + && old_select->type == ZEBRA_ROUTE_BGP + && old_select->sub_type == BGP_ROUTE_STATIC) + evpn_delete_old_local_route(bgp, vpn, rn, old_select); + } else { + if (old_select && old_select->type == ZEBRA_ROUTE_BGP + && old_select->sub_type == BGP_ROUTE_NORMAL) + ret = evpn_zebra_uninstall(bgp, vpn, + (struct prefix_evpn *)&rn->p, + old_select->attr->nexthop); + } + + /* Clear any route change flags. */ + bgp_zebra_clear_route_change_flags(rn); + + /* Reap old select bgp_info, if it has been removed */ + if (old_select && CHECK_FLAG(old_select->flags, BGP_INFO_REMOVED)) + bgp_info_reap(rn, old_select); + + return ret; } /* * Return true if the local ri for this rn has sticky set */ -static int -evpn_route_is_sticky (struct bgp *bgp, struct bgp_node *rn) +static int evpn_route_is_sticky(struct bgp *bgp, struct bgp_node *rn) { - struct bgp_info *tmp_ri; - struct bgp_info *local_ri; + struct bgp_info *tmp_ri; + struct bgp_info *local_ri; - local_ri = NULL; - for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) - { - if (tmp_ri->peer == bgp->peer_self - && tmp_ri->type == ZEBRA_ROUTE_BGP - && tmp_ri->sub_type == BGP_ROUTE_STATIC) - local_ri = tmp_ri; - } + local_ri = NULL; + for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) { + if (tmp_ri->peer == bgp->peer_self + && tmp_ri->type == ZEBRA_ROUTE_BGP + && tmp_ri->sub_type == BGP_ROUTE_STATIC) + local_ri = tmp_ri; + } - if (!local_ri) - return 0; + if (!local_ri) + return 0; - return local_ri->attr->sticky; + return local_ri->attr->sticky; } /* * Create or update EVPN route entry. This could be in the VNI route table * or the global route table. */ -static int -update_evpn_route_entry (struct bgp *bgp, struct bgpevpn *vpn, afi_t afi, - safi_t safi, struct bgp_node *rn, struct attr *attr, - int add, int vni_table, struct bgp_info **ri) -{ - struct bgp_info *tmp_ri; - struct bgp_info *local_ri, *remote_ri; - struct attr *attr_new; - mpls_label_t label = MPLS_INVALID_LABEL; - int route_change = 1; - u_char sticky = 0; - - *ri = NULL; - - /* See if this is an update of an existing route, or a new add. Also, - * identify if already known from remote, and if so, the one with the - * highest sequence number; this is only when adding to the VNI routing - * table. - */ - local_ri = remote_ri = NULL; - for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) - { - if (tmp_ri->peer == bgp->peer_self - && tmp_ri->type == ZEBRA_ROUTE_BGP - && tmp_ri->sub_type == BGP_ROUTE_STATIC) - local_ri = tmp_ri; - if (vni_table) - { - if (tmp_ri->type == ZEBRA_ROUTE_BGP - && tmp_ri->sub_type == BGP_ROUTE_NORMAL - && CHECK_FLAG (tmp_ri->flags, BGP_INFO_VALID)) - { - if (!remote_ri) - remote_ri = tmp_ri; - else if (mac_mobility_seqnum (tmp_ri->attr) > - mac_mobility_seqnum (remote_ri->attr)) - remote_ri = tmp_ri; - } - } - } - - /* If route doesn't exist already, create a new one, if told to. - * Otherwise act based on whether the attributes of the route have - * changed or not. - */ - if (!local_ri && !add) - return 0; - - if (!local_ri) - { - /* When learnt locally for the first time but already known from - * remote, we have to initiate appropriate MAC mobility steps. This - * is applicable when updating the VNI routing table. - */ - if (remote_ri) - { - u_int32_t cur_seqnum; - - /* Add MM extended community to route. */ - cur_seqnum = mac_mobility_seqnum (remote_ri->attr); - add_mac_mobility_to_attr (cur_seqnum + 1, attr); - } - - /* Add (or update) attribute to hash. */ - attr_new = bgp_attr_intern (attr); - - /* Extract MAC mobility sequence number, if any. */ - attr_new->mm_seqnum = bgp_attr_mac_mobility_seqnum (attr_new, &sticky); - attr_new->sticky = sticky; - - /* Create new route with its attribute. */ - tmp_ri = info_make (ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, - bgp->peer_self, attr_new, rn); - SET_FLAG (tmp_ri->flags, BGP_INFO_VALID); - bgp_info_extra_get(tmp_ri); - - /* The VNI goes into the 'label' field of the route */ - vni2label (vpn->vni, &label); - - memcpy (&tmp_ri->extra->label, &label, BGP_LABEL_BYTES); - bgp_info_add (rn, tmp_ri); - } - else - { - tmp_ri = local_ri; - if (attrhash_cmp (tmp_ri->attr, attr) && - !CHECK_FLAG(tmp_ri->flags, BGP_INFO_REMOVED)) - route_change = 0; - else - { - /* The attribute has changed. */ - /* Add (or update) attribute to hash. */ - attr_new = bgp_attr_intern (attr); - bgp_info_set_flag (rn, tmp_ri, BGP_INFO_ATTR_CHANGED); - - /* Restore route, if needed. */ - if (CHECK_FLAG(tmp_ri->flags, BGP_INFO_REMOVED)) - bgp_info_restore(rn, tmp_ri); - - /* Unintern existing, set to new. */ - bgp_attr_unintern (&tmp_ri->attr); - tmp_ri->attr = attr_new; - tmp_ri->uptime = bgp_clock (); - } - } - - /* Return back the route entry. */ - *ri = tmp_ri; - return route_change; +static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, + afi_t afi, safi_t safi, struct bgp_node *rn, + struct attr *attr, int add, int vni_table, + struct bgp_info **ri) +{ + struct bgp_info *tmp_ri; + struct bgp_info *local_ri, *remote_ri; + struct attr *attr_new; + mpls_label_t label = MPLS_INVALID_LABEL; + int route_change = 1; + u_char sticky = 0; + + *ri = NULL; + + /* See if this is an update of an existing route, or a new add. Also, + * identify if already known from remote, and if so, the one with the + * highest sequence number; this is only when adding to the VNI routing + * table. + */ + local_ri = remote_ri = NULL; + for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) { + if (tmp_ri->peer == bgp->peer_self + && tmp_ri->type == ZEBRA_ROUTE_BGP + && tmp_ri->sub_type == BGP_ROUTE_STATIC) + local_ri = tmp_ri; + if (vni_table) { + if (tmp_ri->type == ZEBRA_ROUTE_BGP + && tmp_ri->sub_type == BGP_ROUTE_NORMAL + && CHECK_FLAG(tmp_ri->flags, BGP_INFO_VALID)) { + if (!remote_ri) + remote_ri = tmp_ri; + else if (mac_mobility_seqnum(tmp_ri->attr) + > mac_mobility_seqnum(remote_ri->attr)) + remote_ri = tmp_ri; + } + } + } + + /* If route doesn't exist already, create a new one, if told to. + * Otherwise act based on whether the attributes of the route have + * changed or not. + */ + if (!local_ri && !add) + return 0; + + if (!local_ri) { + /* When learnt locally for the first time but already known from + * remote, we have to initiate appropriate MAC mobility steps. + * This + * is applicable when updating the VNI routing table. + */ + if (remote_ri) { + u_int32_t cur_seqnum; + + /* Add MM extended community to route. */ + cur_seqnum = mac_mobility_seqnum(remote_ri->attr); + add_mac_mobility_to_attr(cur_seqnum + 1, attr); + } + + /* Add (or update) attribute to hash. */ + attr_new = bgp_attr_intern(attr); + + /* Extract MAC mobility sequence number, if any. */ + attr_new->mm_seqnum = + bgp_attr_mac_mobility_seqnum(attr_new, &sticky); + attr_new->sticky = sticky; + + /* Create new route with its attribute. */ + tmp_ri = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, + bgp->peer_self, attr_new, rn); + SET_FLAG(tmp_ri->flags, BGP_INFO_VALID); + bgp_info_extra_get(tmp_ri); + + /* The VNI goes into the 'label' field of the route */ + vni2label(vpn->vni, &label); + + memcpy(&tmp_ri->extra->label, &label, BGP_LABEL_BYTES); + bgp_info_add(rn, tmp_ri); + } else { + tmp_ri = local_ri; + if (attrhash_cmp(tmp_ri->attr, attr) + && !CHECK_FLAG(tmp_ri->flags, BGP_INFO_REMOVED)) + route_change = 0; + else { + /* The attribute has changed. */ + /* Add (or update) attribute to hash. */ + attr_new = bgp_attr_intern(attr); + bgp_info_set_flag(rn, tmp_ri, BGP_INFO_ATTR_CHANGED); + + /* Restore route, if needed. */ + if (CHECK_FLAG(tmp_ri->flags, BGP_INFO_REMOVED)) + bgp_info_restore(rn, tmp_ri); + + /* Unintern existing, set to new. */ + bgp_attr_unintern(&tmp_ri->attr); + tmp_ri->attr = attr_new; + tmp_ri->uptime = bgp_clock(); + } + } + + /* Return back the route entry. */ + *ri = tmp_ri; + return route_change; } /* * Create or update EVPN route (of type based on prefix) for specified VNI * and schedule for processing. */ -static int -update_evpn_route (struct bgp *bgp, struct bgpevpn *vpn, - struct prefix_evpn *p, u_char sticky) +static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, + struct prefix_evpn *p, u_char sticky) { - struct bgp_node *rn; - struct attr attr; - struct attr *attr_new; - struct bgp_info *ri; - afi_t afi = AFI_L2VPN; - safi_t safi = SAFI_EVPN; - int route_change; + struct bgp_node *rn; + struct attr attr; + struct attr *attr_new; + struct bgp_info *ri; + afi_t afi = AFI_L2VPN; + safi_t safi = SAFI_EVPN; + int route_change; - memset (&attr, 0, sizeof (struct attr)); + memset(&attr, 0, sizeof(struct attr)); - /* Build path-attribute for this route. */ - bgp_attr_default_set (&attr, BGP_ORIGIN_IGP); - attr.nexthop = vpn->originator_ip; - attr.mp_nexthop_global_in = vpn->originator_ip; - attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; - attr.sticky = sticky; + /* Build path-attribute for this route. */ + bgp_attr_default_set(&attr, BGP_ORIGIN_IGP); + attr.nexthop = vpn->originator_ip; + attr.mp_nexthop_global_in = vpn->originator_ip; + attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; + attr.sticky = sticky; - /* Set up RT and ENCAP extended community. */ - build_evpn_route_extcomm (vpn, &attr); + /* Set up RT and ENCAP extended community. */ + build_evpn_route_extcomm(vpn, &attr); - /* First, create (or fetch) route node within the VNI. */ - /* NOTE: There is no RD here. */ - rn = bgp_node_get (vpn->route_table, (struct prefix *)p); + /* First, create (or fetch) route node within the VNI. */ + /* NOTE: There is no RD here. */ + rn = bgp_node_get(vpn->route_table, (struct prefix *)p); - /* Create or update route entry. */ - route_change = update_evpn_route_entry (bgp, vpn, afi, safi, - rn, &attr, 1, 1, &ri); - assert (ri); - attr_new = ri->attr; + /* Create or update route entry. */ + route_change = update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr, + 1, 1, &ri); + assert(ri); + attr_new = ri->attr; - /* Perform route selection; this is just to set the flags correctly - * as local route in the VNI always wins. - */ - evpn_route_select_install (bgp, vpn, rn); - bgp_unlock_node (rn); + /* Perform route selection; this is just to set the flags correctly + * as local route in the VNI always wins. + */ + evpn_route_select_install(bgp, vpn, rn); + bgp_unlock_node(rn); - /* If this is a new route or some attribute has changed, export the - * route to the global table. The route will be advertised to peers - * from there. Note that this table is a 2-level tree (RD-level + - * Prefix-level) similar to L3VPN routes. - */ - if (route_change) - { - struct bgp_info *global_ri; + /* If this is a new route or some attribute has changed, export the + * route to the global table. The route will be advertised to peers + * from there. Note that this table is a 2-level tree (RD-level + + * Prefix-level) similar to L3VPN routes. + */ + if (route_change) { + struct bgp_info *global_ri; - rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, - (struct prefix *)p, &vpn->prd); - update_evpn_route_entry (bgp, vpn, afi, safi, rn, - attr_new, 1, 0, &global_ri); + rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, + (struct prefix *)p, &vpn->prd); + update_evpn_route_entry(bgp, vpn, afi, safi, rn, attr_new, 1, 0, + &global_ri); - /* Schedule for processing and unlock node. */ - bgp_process (bgp, rn, afi, safi); - bgp_unlock_node (rn); - } + /* Schedule for processing and unlock node. */ + bgp_process(bgp, rn, afi, safi); + bgp_unlock_node(rn); + } - /* Unintern temporary. */ - aspath_unintern (&attr.aspath); + /* Unintern temporary. */ + aspath_unintern(&attr.aspath); - return 0; + return 0; } /* * Delete EVPN route entry. This could be in the VNI route table * or the global route table. */ -static void -delete_evpn_route_entry (struct bgp *bgp, struct bgpevpn *vpn, - afi_t afi, safi_t safi, struct bgp_node *rn, - struct bgp_info **ri) +static void delete_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, + afi_t afi, safi_t safi, struct bgp_node *rn, + struct bgp_info **ri) { - struct bgp_info *tmp_ri; + struct bgp_info *tmp_ri; - *ri = NULL; + *ri = NULL; - /* Now, find matching route. */ - for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) - if (tmp_ri->peer == bgp->peer_self - && tmp_ri->type == ZEBRA_ROUTE_BGP - && tmp_ri->sub_type == BGP_ROUTE_STATIC) - break; + /* Now, find matching route. */ + for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) + if (tmp_ri->peer == bgp->peer_self + && tmp_ri->type == ZEBRA_ROUTE_BGP + && tmp_ri->sub_type == BGP_ROUTE_STATIC) + break; - *ri = tmp_ri; + *ri = tmp_ri; - /* Mark route for delete. */ - if (tmp_ri) - bgp_info_delete (rn, tmp_ri); + /* Mark route for delete. */ + if (tmp_ri) + bgp_info_delete(rn, tmp_ri); } /* * Delete EVPN route (of type based on prefix) for specified VNI and * schedule for processing. */ -static int -delete_evpn_route (struct bgp *bgp, struct bgpevpn *vpn, - struct prefix_evpn *p) -{ - struct bgp_node *rn, *global_rn; - struct bgp_info *ri; - afi_t afi = AFI_L2VPN; - safi_t safi = SAFI_EVPN; - - /* First, locate the route node within the VNI. If it doesn't exist, there - * is nothing further to do. - */ - /* NOTE: There is no RD here. */ - rn = bgp_node_lookup (vpn->route_table, (struct prefix *)p); - if (!rn) - return 0; - - /* Next, locate route node in the global EVPN routing table. Note that - * this table is a 2-level tree (RD-level + Prefix-level) similar to - * L3VPN routes. - */ - global_rn = bgp_afi_node_lookup (bgp->rib[afi][safi], afi, safi, - (struct prefix *)p, &vpn->prd); - if (global_rn) - { - /* Delete route entry in the global EVPN table. */ - delete_evpn_route_entry (bgp, vpn, afi, safi, global_rn, &ri); - - /* Schedule for processing - withdraws to peers happen from - * this table. - */ - if (ri) - bgp_process (bgp, global_rn, afi, safi); - bgp_unlock_node (global_rn); - } - - /* Delete route entry in the VNI route table. This can just be removed. */ - delete_evpn_route_entry (bgp, vpn, afi, safi, rn, &ri); - if (ri) - bgp_info_reap (rn, ri); - bgp_unlock_node (rn); - - return 0; +static int delete_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, + struct prefix_evpn *p) +{ + struct bgp_node *rn, *global_rn; + struct bgp_info *ri; + afi_t afi = AFI_L2VPN; + safi_t safi = SAFI_EVPN; + + /* First, locate the route node within the VNI. If it doesn't exist, + * there + * is nothing further to do. + */ + /* NOTE: There is no RD here. */ + rn = bgp_node_lookup(vpn->route_table, (struct prefix *)p); + if (!rn) + return 0; + + /* Next, locate route node in the global EVPN routing table. Note that + * this table is a 2-level tree (RD-level + Prefix-level) similar to + * L3VPN routes. + */ + global_rn = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi, + (struct prefix *)p, &vpn->prd); + if (global_rn) { + /* Delete route entry in the global EVPN table. */ + delete_evpn_route_entry(bgp, vpn, afi, safi, global_rn, &ri); + + /* Schedule for processing - withdraws to peers happen from + * this table. + */ + if (ri) + bgp_process(bgp, global_rn, afi, safi); + bgp_unlock_node(global_rn); + } + + /* Delete route entry in the VNI route table. This can just be removed. + */ + delete_evpn_route_entry(bgp, vpn, afi, safi, rn, &ri); + if (ri) + bgp_info_reap(rn, ri); + bgp_unlock_node(rn); + + return 0; } /* * Update all type-2 (MACIP) local routes for this VNI - these should also * be scheduled for advertise to peers. */ -static int -update_all_type2_routes (struct bgp *bgp, struct bgpevpn *vpn) -{ - afi_t afi; - safi_t safi; - struct bgp_node *rn; - struct bgp_info *ri; - struct attr attr; - struct attr attr_sticky; - struct attr *attr_new; - - afi = AFI_L2VPN; - safi = SAFI_EVPN; - memset (&attr, 0, sizeof (struct attr)); - memset (&attr_sticky, 0, sizeof (struct attr)); - - /* Build path-attribute - all type-2 routes for this VNI will share the - * same path attribute. - */ - bgp_attr_default_set (&attr, BGP_ORIGIN_IGP); - bgp_attr_default_set (&attr_sticky, BGP_ORIGIN_IGP); - attr.nexthop = vpn->originator_ip; - attr.mp_nexthop_global_in = vpn->originator_ip; - attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; - attr_sticky.nexthop = vpn->originator_ip; - attr_sticky.mp_nexthop_global_in = vpn->originator_ip; - attr_sticky.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; - attr_sticky.sticky = 1; - - /* Set up RT, ENCAP and sticky MAC extended community. */ - build_evpn_route_extcomm (vpn, &attr); - build_evpn_route_extcomm (vpn, &attr_sticky); - - /* Walk this VNI's route table and update local type-2 routes. For any - * routes updated, update corresponding entry in the global table too. - */ - for (rn = bgp_table_top (vpn->route_table); rn; rn = bgp_route_next (rn)) - { - struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; - struct bgp_node *rd_rn; - struct bgp_info *global_ri; - - if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) - continue; - - if (evpn_route_is_sticky (bgp, rn)) - update_evpn_route_entry (bgp, vpn, afi, safi, rn, &attr_sticky, 0, 1, &ri); - else - update_evpn_route_entry (bgp, vpn, afi, safi, rn, &attr, 0, 1, &ri); - - /* If a local route exists for this prefix, we need to update - * the global routing table too. - */ - if (!ri) - continue; - - /* Perform route selection; this is just to set the flags correctly - * as local route in the VNI always wins. - */ - evpn_route_select_install (bgp, vpn, rn); - - attr_new = ri->attr; - - /* Update route in global routing table. */ - rd_rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, - (struct prefix *)evp, &vpn->prd); - assert (rd_rn); - update_evpn_route_entry (bgp, vpn, afi, safi, rd_rn, - attr_new, 0, 0, &global_ri); - - /* Schedule for processing and unlock node. */ - bgp_process (bgp, rd_rn, afi, safi); - bgp_unlock_node (rd_rn); - } - - /* Unintern temporary. */ - aspath_unintern (&attr.aspath); - aspath_unintern (&attr_sticky.aspath); - - return 0; +static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) +{ + afi_t afi; + safi_t safi; + struct bgp_node *rn; + struct bgp_info *ri; + struct attr attr; + struct attr attr_sticky; + struct attr *attr_new; + + afi = AFI_L2VPN; + safi = SAFI_EVPN; + memset(&attr, 0, sizeof(struct attr)); + memset(&attr_sticky, 0, sizeof(struct attr)); + + /* Build path-attribute - all type-2 routes for this VNI will share the + * same path attribute. + */ + bgp_attr_default_set(&attr, BGP_ORIGIN_IGP); + bgp_attr_default_set(&attr_sticky, BGP_ORIGIN_IGP); + attr.nexthop = vpn->originator_ip; + attr.mp_nexthop_global_in = vpn->originator_ip; + attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; + attr_sticky.nexthop = vpn->originator_ip; + attr_sticky.mp_nexthop_global_in = vpn->originator_ip; + attr_sticky.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; + attr_sticky.sticky = 1; + + /* Set up RT, ENCAP and sticky MAC extended community. */ + build_evpn_route_extcomm(vpn, &attr); + build_evpn_route_extcomm(vpn, &attr_sticky); + + /* Walk this VNI's route table and update local type-2 routes. For any + * routes updated, update corresponding entry in the global table too. + */ + for (rn = bgp_table_top(vpn->route_table); rn; + rn = bgp_route_next(rn)) { + struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; + struct bgp_node *rd_rn; + struct bgp_info *global_ri; + + if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) + continue; + + if (evpn_route_is_sticky(bgp, rn)) + update_evpn_route_entry(bgp, vpn, afi, safi, rn, + &attr_sticky, 0, 1, &ri); + else + update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr, + 0, 1, &ri); + + /* If a local route exists for this prefix, we need to update + * the global routing table too. + */ + if (!ri) + continue; + + /* Perform route selection; this is just to set the flags + * correctly + * as local route in the VNI always wins. + */ + evpn_route_select_install(bgp, vpn, rn); + + attr_new = ri->attr; + + /* Update route in global routing table. */ + rd_rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, + (struct prefix *)evp, &vpn->prd); + assert(rd_rn); + update_evpn_route_entry(bgp, vpn, afi, safi, rd_rn, attr_new, 0, + 0, &global_ri); + + /* Schedule for processing and unlock node. */ + bgp_process(bgp, rd_rn, afi, safi); + bgp_unlock_node(rd_rn); + } + + /* Unintern temporary. */ + aspath_unintern(&attr.aspath); + aspath_unintern(&attr_sticky.aspath); + + return 0; } /* * Delete all type-2 (MACIP) local routes for this VNI - only from the * global routing table. These are also scheduled for withdraw from peers. */ -static int -delete_global_type2_routes (struct bgp *bgp, struct bgpevpn *vpn) +static int delete_global_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) { - afi_t afi; - safi_t safi; - struct bgp_node *rdrn, *rn; - struct bgp_table *table; - struct bgp_info *ri; + afi_t afi; + safi_t safi; + struct bgp_node *rdrn, *rn; + struct bgp_table *table; + struct bgp_info *ri; - afi = AFI_L2VPN; - safi = SAFI_EVPN; + afi = AFI_L2VPN; + safi = SAFI_EVPN; - rdrn = bgp_node_lookup (bgp->rib[afi][safi], (struct prefix *) &vpn->prd); - if (rdrn && rdrn->info) - { - table = (struct bgp_table *)rdrn->info; - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - { - struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; + rdrn = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)&vpn->prd); + if (rdrn && rdrn->info) { + table = (struct bgp_table *)rdrn->info; + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { + struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; - if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) - continue; + if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) + continue; - delete_evpn_route_entry (bgp, vpn, afi, safi, rn, &ri); - if (ri) - bgp_process (bgp, rn, afi, safi); - } - } + delete_evpn_route_entry(bgp, vpn, afi, safi, rn, &ri); + if (ri) + bgp_process(bgp, rn, afi, safi); + } + } - /* Unlock RD node. */ - if (rdrn) - bgp_unlock_node (rdrn); + /* Unlock RD node. */ + if (rdrn) + bgp_unlock_node(rdrn); - return 0; + return 0; } /* * Delete all type-2 (MACIP) local routes for this VNI - from the global * table as well as the per-VNI route table. */ -static int -delete_all_type2_routes (struct bgp *bgp, struct bgpevpn *vpn) +static int delete_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) { - afi_t afi; - safi_t safi; - struct bgp_node *rn; - struct bgp_info *ri; + afi_t afi; + safi_t safi; + struct bgp_node *rn; + struct bgp_info *ri; - afi = AFI_L2VPN; - safi = SAFI_EVPN; + afi = AFI_L2VPN; + safi = SAFI_EVPN; - /* First, walk the global route table for this VNI's type-2 local routes. - * EVPN routes are a 2-level table, first get the RD table. - */ - delete_global_type2_routes (bgp, vpn); + /* First, walk the global route table for this VNI's type-2 local + * routes. + * EVPN routes are a 2-level table, first get the RD table. + */ + delete_global_type2_routes(bgp, vpn); - /* Next, walk this VNI's route table and delete local type-2 routes. */ - for (rn = bgp_table_top (vpn->route_table); rn; rn = bgp_route_next (rn)) - { - struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; + /* Next, walk this VNI's route table and delete local type-2 routes. */ + for (rn = bgp_table_top(vpn->route_table); rn; + rn = bgp_route_next(rn)) { + struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; - if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) - continue; + if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) + continue; - delete_evpn_route_entry (bgp, vpn, afi, safi, rn, &ri); + delete_evpn_route_entry(bgp, vpn, afi, safi, rn, &ri); - /* Route entry in local table gets deleted immediately. */ - if (ri) - bgp_info_reap (rn, ri); - } + /* Route entry in local table gets deleted immediately. */ + if (ri) + bgp_info_reap(rn, ri); + } - return 0; + return 0; } /* * Delete all routes in the per-VNI route table. */ -static int -delete_all_vni_routes (struct bgp *bgp, struct bgpevpn *vpn) +static int delete_all_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) { - struct bgp_node *rn; - struct bgp_info *ri, *nextri; + struct bgp_node *rn; + struct bgp_info *ri, *nextri; - /* Walk this VNI's route table and delete all routes. */ - for (rn = bgp_table_top (vpn->route_table); rn; rn = bgp_route_next (rn)) - { - for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1); ri = nextri) - { - bgp_info_delete (rn, ri); - bgp_info_reap (rn, ri); - } - } + /* Walk this VNI's route table and delete all routes. */ + for (rn = bgp_table_top(vpn->route_table); rn; + rn = bgp_route_next(rn)) { + for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1); + ri = nextri) { + bgp_info_delete(rn, ri); + bgp_info_reap(rn, ri); + } + } - return 0; + return 0; } /* @@ -1176,21 +1138,20 @@ delete_all_vni_routes (struct bgp *bgp, struct bgpevpn *vpn) * situations need the route in the per-VNI table as well as the global * table to be updated (as attributes change). */ -static int -update_routes_for_vni (struct bgp *bgp, struct bgpevpn *vpn) +static int update_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) { - int ret; - struct prefix_evpn p; + int ret; + struct prefix_evpn p; - /* Update and advertise the type-3 route (only one) followed by the - * locally learnt type-2 routes (MACIP) - for this VNI. - */ - build_evpn_type3_prefix (&p, vpn->originator_ip); - ret = update_evpn_route (bgp, vpn, &p, 0); - if (ret) - return ret; + /* Update and advertise the type-3 route (only one) followed by the + * locally learnt type-2 routes (MACIP) - for this VNI. + */ + build_evpn_type3_prefix(&p, vpn->originator_ip); + ret = update_evpn_route(bgp, vpn, &p, 0); + if (ret) + return ret; - return update_all_type2_routes (bgp, vpn); + return update_all_type2_routes(bgp, vpn); } /* @@ -1199,289 +1160,291 @@ update_routes_for_vni (struct bgp *bgp, struct bgpevpn *vpn) * the per-VNI table. Invoked upon the VNI being deleted or EVPN * (advertise-all-vni) being disabled. */ -static int -delete_routes_for_vni (struct bgp *bgp, struct bgpevpn *vpn) +static int delete_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) { - int ret; - struct prefix_evpn p; + int ret; + struct prefix_evpn p; - /* Delete and withdraw locally learnt type-2 routes (MACIP) - * followed by type-3 routes (only one) - for this VNI. - */ - ret = delete_all_type2_routes (bgp, vpn); - if (ret) - return ret; + /* Delete and withdraw locally learnt type-2 routes (MACIP) + * followed by type-3 routes (only one) - for this VNI. + */ + ret = delete_all_type2_routes(bgp, vpn); + if (ret) + return ret; - build_evpn_type3_prefix (&p, vpn->originator_ip); - ret = delete_evpn_route (bgp, vpn, &p); - if (ret) - return ret; + build_evpn_type3_prefix(&p, vpn->originator_ip); + ret = delete_evpn_route(bgp, vpn, &p); + if (ret) + return ret; - /* Delete all routes from the per-VNI table. */ - return delete_all_vni_routes (bgp, vpn); + /* Delete all routes from the per-VNI table. */ + return delete_all_vni_routes(bgp, vpn); } /* * There is a tunnel endpoint IP address change for this VNI, * need to re-advertise routes with the new nexthop. */ -static int -handle_tunnel_ip_change (struct bgp *bgp, struct bgpevpn *vpn, - struct in_addr originator_ip) +static int handle_tunnel_ip_change(struct bgp *bgp, struct bgpevpn *vpn, + struct in_addr originator_ip) { - struct prefix_evpn p; + struct prefix_evpn p; - /* Need to withdraw type-3 route as the originator IP is part - * of the key. - */ - build_evpn_type3_prefix (&p, vpn->originator_ip); - delete_evpn_route (bgp, vpn, &p); + /* Need to withdraw type-3 route as the originator IP is part + * of the key. + */ + build_evpn_type3_prefix(&p, vpn->originator_ip); + delete_evpn_route(bgp, vpn, &p); - /* Update the tunnel IP and re-advertise all routes for this VNI. */ - vpn->originator_ip = originator_ip; - return update_routes_for_vni (bgp, vpn); + /* Update the tunnel IP and re-advertise all routes for this VNI. */ + vpn->originator_ip = originator_ip; + return update_routes_for_vni(bgp, vpn); } /* * Install route entry into the VNI routing table and invoke route selection. */ -static int -install_evpn_route_entry (struct bgp *bgp, struct bgpevpn *vpn, - struct prefix_evpn *p, struct bgp_info *parent_ri) -{ - struct bgp_node *rn; - struct bgp_info *ri; - struct attr *attr_new; - int ret; - - /* Create (or fetch) route within the VNI. */ - /* NOTE: There is no RD here. */ - rn = bgp_node_get (vpn->route_table, (struct prefix *)p); - - /* Check if route entry is already present. */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->extra && - (struct bgp_info *)ri->extra->parent == parent_ri) - break; - - if (!ri) - { - /* Add (or update) attribute to hash. */ - attr_new = bgp_attr_intern (parent_ri->attr); - - /* Create new route with its attribute. */ - ri = info_make (parent_ri->type, parent_ri->sub_type, 0, - parent_ri->peer, attr_new, rn); - SET_FLAG (ri->flags, BGP_INFO_VALID); - bgp_info_extra_get(ri); - ri->extra->parent = parent_ri; - if (parent_ri->extra) - memcpy (&ri->extra->label, &parent_ri->extra->label, BGP_LABEL_BYTES); - bgp_info_add (rn, ri); - } - else - { - if (attrhash_cmp (ri->attr, parent_ri->attr) && - !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) - { - bgp_unlock_node (rn); - return 0; - } - /* The attribute has changed. */ - /* Add (or update) attribute to hash. */ - attr_new = bgp_attr_intern (parent_ri->attr); - - /* Restore route, if needed. */ - if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) - bgp_info_restore(rn, ri); - - /* Mark if nexthop has changed. */ - if (!IPV4_ADDR_SAME (&ri->attr->nexthop, &attr_new->nexthop)) - SET_FLAG(ri->flags, BGP_INFO_IGP_CHANGED); - - /* Unintern existing, set to new. */ - bgp_attr_unintern (&ri->attr); - ri->attr = attr_new; - ri->uptime = bgp_clock (); - } - - /* Perform route selection and update zebra, if required. */ - ret = evpn_route_select_install (bgp, vpn, rn); - - return ret; +static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, + struct prefix_evpn *p, + struct bgp_info *parent_ri) +{ + struct bgp_node *rn; + struct bgp_info *ri; + struct attr *attr_new; + int ret; + + /* Create (or fetch) route within the VNI. */ + /* NOTE: There is no RD here. */ + rn = bgp_node_get(vpn->route_table, (struct prefix *)p); + + /* Check if route entry is already present. */ + for (ri = rn->info; ri; ri = ri->next) + if (ri->extra + && (struct bgp_info *)ri->extra->parent == parent_ri) + break; + + if (!ri) { + /* Add (or update) attribute to hash. */ + attr_new = bgp_attr_intern(parent_ri->attr); + + /* Create new route with its attribute. */ + ri = info_make(parent_ri->type, parent_ri->sub_type, 0, + parent_ri->peer, attr_new, rn); + SET_FLAG(ri->flags, BGP_INFO_VALID); + bgp_info_extra_get(ri); + ri->extra->parent = parent_ri; + if (parent_ri->extra) + memcpy(&ri->extra->label, &parent_ri->extra->label, + BGP_LABEL_BYTES); + bgp_info_add(rn, ri); + } else { + if (attrhash_cmp(ri->attr, parent_ri->attr) + && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { + bgp_unlock_node(rn); + return 0; + } + /* The attribute has changed. */ + /* Add (or update) attribute to hash. */ + attr_new = bgp_attr_intern(parent_ri->attr); + + /* Restore route, if needed. */ + if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) + bgp_info_restore(rn, ri); + + /* Mark if nexthop has changed. */ + if (!IPV4_ADDR_SAME(&ri->attr->nexthop, &attr_new->nexthop)) + SET_FLAG(ri->flags, BGP_INFO_IGP_CHANGED); + + /* Unintern existing, set to new. */ + bgp_attr_unintern(&ri->attr); + ri->attr = attr_new; + ri->uptime = bgp_clock(); + } + + /* Perform route selection and update zebra, if required. */ + ret = evpn_route_select_install(bgp, vpn, rn); + + return ret; } /* * Uninstall route entry from the VNI routing table and send message * to zebra, if appropriate. */ -static int -uninstall_evpn_route_entry (struct bgp *bgp, struct bgpevpn *vpn, - struct prefix_evpn *p, struct bgp_info *parent_ri) +static int uninstall_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, + struct prefix_evpn *p, + struct bgp_info *parent_ri) { - struct bgp_node *rn; - struct bgp_info *ri; - int ret; + struct bgp_node *rn; + struct bgp_info *ri; + int ret; - /* Locate route within the VNI. */ - /* NOTE: There is no RD here. */ - rn = bgp_node_lookup (vpn->route_table, (struct prefix *)p); - if (!rn) - return 0; + /* Locate route within the VNI. */ + /* NOTE: There is no RD here. */ + rn = bgp_node_lookup(vpn->route_table, (struct prefix *)p); + if (!rn) + return 0; - /* Find matching route entry. */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->extra && - (struct bgp_info *)ri->extra->parent == parent_ri) - break; + /* Find matching route entry. */ + for (ri = rn->info; ri; ri = ri->next) + if (ri->extra + && (struct bgp_info *)ri->extra->parent == parent_ri) + break; - if (!ri) - return 0; + if (!ri) + return 0; - /* Mark entry for deletion */ - bgp_info_delete (rn, ri); + /* Mark entry for deletion */ + bgp_info_delete(rn, ri); - /* Perform route selection and update zebra, if required. */ - ret = evpn_route_select_install (bgp, vpn, rn); + /* Perform route selection and update zebra, if required. */ + ret = evpn_route_select_install(bgp, vpn, rn); - /* Unlock route node. */ - bgp_unlock_node (rn); + /* Unlock route node. */ + bgp_unlock_node(rn); - return ret; + return ret; } /* * Given a route entry and a VNI, see if this route entry should be * imported into the VNI i.e., RTs match. */ -static int -is_route_matching_for_vni (struct bgp *bgp, struct bgpevpn *vpn, - struct bgp_info *ri) -{ - struct attr *attr = ri->attr; - struct ecommunity *ecom; - int i; - - assert (attr); - /* Route should have valid RT to be even considered. */ - if (!(attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES))) - return 0; - - ecom = attr->ecommunity; - if (!ecom || !ecom->size) - return 0; - - /* For each extended community RT, see if it matches this VNI. If any RT - * matches, we're done. - */ - for (i = 0; i < ecom->size; i++) - { - u_char *pnt; - u_char type, sub_type; - struct ecommunity_val *eval; - struct ecommunity_val eval_tmp; - struct irt_node *irt; - - /* Only deal with RTs */ - pnt = (ecom->val + (i * ECOMMUNITY_SIZE)); - eval = (struct ecommunity_val *) (ecom->val + (i * ECOMMUNITY_SIZE)); - type = *pnt++; - sub_type = *pnt++; - if (sub_type != ECOMMUNITY_ROUTE_TARGET) - continue; - - /* See if this RT matches specified VNIs import RTs */ - irt = lookup_import_rt (bgp, eval); - if (irt && irt->vnis) - if (is_vni_present_in_irt_vnis (irt->vnis, vpn)) - return 1; - - /* Also check for non-exact match. In this, we mask out the AS and - * only check on the local-admin sub-field. This is to facilitate using - * VNI as the RT for EBGP peering too. - */ - irt = NULL; - if (type == ECOMMUNITY_ENCODE_AS || - type == ECOMMUNITY_ENCODE_AS4 || - type == ECOMMUNITY_ENCODE_IP) - { - memcpy (&eval_tmp, eval, ECOMMUNITY_SIZE); - mask_ecom_global_admin (&eval_tmp, eval); - irt = lookup_import_rt (bgp, &eval_tmp); - } - if (irt && irt->vnis) - if (is_vni_present_in_irt_vnis (irt->vnis, vpn)) - return 1; - } - - return 0; +static int is_route_matching_for_vni(struct bgp *bgp, struct bgpevpn *vpn, + struct bgp_info *ri) +{ + struct attr *attr = ri->attr; + struct ecommunity *ecom; + int i; + + assert(attr); + /* Route should have valid RT to be even considered. */ + if (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) + return 0; + + ecom = attr->ecommunity; + if (!ecom || !ecom->size) + return 0; + + /* For each extended community RT, see if it matches this VNI. If any RT + * matches, we're done. + */ + for (i = 0; i < ecom->size; i++) { + u_char *pnt; + u_char type, sub_type; + struct ecommunity_val *eval; + struct ecommunity_val eval_tmp; + struct irt_node *irt; + + /* Only deal with RTs */ + pnt = (ecom->val + (i * ECOMMUNITY_SIZE)); + eval = (struct ecommunity_val *)(ecom->val + + (i * ECOMMUNITY_SIZE)); + type = *pnt++; + sub_type = *pnt++; + if (sub_type != ECOMMUNITY_ROUTE_TARGET) + continue; + + /* See if this RT matches specified VNIs import RTs */ + irt = lookup_import_rt(bgp, eval); + if (irt && irt->vnis) + if (is_vni_present_in_irt_vnis(irt->vnis, vpn)) + return 1; + + /* Also check for non-exact match. In this, we mask out the AS + * and + * only check on the local-admin sub-field. This is to + * facilitate using + * VNI as the RT for EBGP peering too. + */ + irt = NULL; + if (type == ECOMMUNITY_ENCODE_AS + || type == ECOMMUNITY_ENCODE_AS4 + || type == ECOMMUNITY_ENCODE_IP) { + memcpy(&eval_tmp, eval, ECOMMUNITY_SIZE); + mask_ecom_global_admin(&eval_tmp, eval); + irt = lookup_import_rt(bgp, &eval_tmp); + } + if (irt && irt->vnis) + if (is_vni_present_in_irt_vnis(irt->vnis, vpn)) + return 1; + } + + return 0; } /* * Install or uninstall routes of specified type that are appropriate for this * particular VNI. */ -static int -install_uninstall_routes_for_vni (struct bgp *bgp, struct bgpevpn *vpn, - bgp_evpn_route_type rtype, int install) -{ - afi_t afi; - safi_t safi; - struct bgp_node *rd_rn, *rn; - struct bgp_table *table; - struct bgp_info *ri; - int ret; - - afi = AFI_L2VPN; - safi = SAFI_EVPN; - - /* Walk entire global routing table and evaluate routes which could be - * imported into this VPN. Note that we cannot just look at the routes for - * the VNI's RD - remote routes applicable for this VNI could have any RD. - */ - /* EVPN routes are a 2-level table. */ - for (rd_rn = bgp_table_top(bgp->rib[afi][safi]); rd_rn; rd_rn = bgp_route_next (rd_rn)) - { - table = (struct bgp_table *)(rd_rn->info); - if (!table) - continue; - - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - { - struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; - - if (evp->prefix.route_type != rtype) - continue; - - for (ri = rn->info; ri; ri = ri->next) - { - /* Consider "valid" remote routes applicable for this VNI. */ - if (!(CHECK_FLAG (ri->flags, BGP_INFO_VALID) - && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_NORMAL)) - continue; - - if (is_route_matching_for_vni (bgp, vpn, ri)) - { - if (install) - ret = install_evpn_route_entry (bgp, vpn, evp, ri); - else - ret = uninstall_evpn_route_entry (bgp, vpn, evp, ri); - - if (ret) - { - zlog_err ("%u: Failed to %s EVPN %s route in VNI %u", - bgp->vrf_id, install ? "install" : "uninstall", - rtype == BGP_EVPN_MAC_IP_ROUTE ? \ - "MACIP" : "IMET", vpn->vni); - return ret; - } - } - } - } - } - - return 0; +static int install_uninstall_routes_for_vni(struct bgp *bgp, + struct bgpevpn *vpn, + bgp_evpn_route_type rtype, + int install) +{ + afi_t afi; + safi_t safi; + struct bgp_node *rd_rn, *rn; + struct bgp_table *table; + struct bgp_info *ri; + int ret; + + afi = AFI_L2VPN; + safi = SAFI_EVPN; + + /* Walk entire global routing table and evaluate routes which could be + * imported into this VPN. Note that we cannot just look at the routes + * for + * the VNI's RD - remote routes applicable for this VNI could have any + * RD. + */ + /* EVPN routes are a 2-level table. */ + for (rd_rn = bgp_table_top(bgp->rib[afi][safi]); rd_rn; + rd_rn = bgp_route_next(rd_rn)) { + table = (struct bgp_table *)(rd_rn->info); + if (!table) + continue; + + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { + struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; + + if (evp->prefix.route_type != rtype) + continue; + + for (ri = rn->info; ri; ri = ri->next) { + /* Consider "valid" remote routes applicable for + * this VNI. */ + if (!(CHECK_FLAG(ri->flags, BGP_INFO_VALID) + && ri->type == ZEBRA_ROUTE_BGP + && ri->sub_type == BGP_ROUTE_NORMAL)) + continue; + + if (is_route_matching_for_vni(bgp, vpn, ri)) { + if (install) + ret = install_evpn_route_entry( + bgp, vpn, evp, ri); + else + ret = uninstall_evpn_route_entry( + bgp, vpn, evp, ri); + + if (ret) { + zlog_err( + "%u: Failed to %s EVPN %s route in VNI %u", + bgp->vrf_id, + install ? "install" + : "uninstall", + rtype == BGP_EVPN_MAC_IP_ROUTE + ? "MACIP" + : "IMET", + vpn->vni); + return ret; + } + } + } + } + } + + return 0; } /* @@ -1489,148 +1452,151 @@ install_uninstall_routes_for_vni (struct bgp *bgp, struct bgpevpn *vpn, * routing table. This is invoked when a VNI becomes "live" or its Import * RT is changed. */ -static int -install_routes_for_vni (struct bgp *bgp, struct bgpevpn *vpn) +static int install_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) { - int ret; + int ret; - /* Install type-3 routes followed by type-2 routes - the ones applicable - * for this VNI. - */ - ret = install_uninstall_routes_for_vni (bgp, vpn, BGP_EVPN_IMET_ROUTE, 1); - if (ret) - return ret; + /* Install type-3 routes followed by type-2 routes - the ones applicable + * for this VNI. + */ + ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_IMET_ROUTE, + 1); + if (ret) + return ret; - return install_uninstall_routes_for_vni (bgp, vpn, BGP_EVPN_MAC_IP_ROUTE, 1); + return install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_MAC_IP_ROUTE, + 1); } /* * Uninstall any existing remote routes for this VNI. One scenario in which * this is invoked is upon an import RT change. */ -static int -uninstall_routes_for_vni (struct bgp *bgp, struct bgpevpn *vpn) +static int uninstall_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) { - int ret; + int ret; - /* Uninstall type-2 routes followed by type-3 routes - the ones applicable - * for this VNI. - */ - ret = install_uninstall_routes_for_vni (bgp, vpn, BGP_EVPN_MAC_IP_ROUTE, 0); - if (ret) - return ret; + /* Uninstall type-2 routes followed by type-3 routes - the ones + * applicable + * for this VNI. + */ + ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_MAC_IP_ROUTE, + 0); + if (ret) + return ret; - return install_uninstall_routes_for_vni (bgp, vpn, BGP_EVPN_IMET_ROUTE, 0); + return install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_IMET_ROUTE, + 0); } /* * Install or uninstall route in matching VNIs (list). */ -static int -install_uninstall_route_in_vnis (struct bgp *bgp, afi_t afi, safi_t safi, - struct prefix_evpn *evp, struct bgp_info *ri, - struct list *vnis, int install) +static int install_uninstall_route_in_vnis(struct bgp *bgp, afi_t afi, + safi_t safi, struct prefix_evpn *evp, + struct bgp_info *ri, + struct list *vnis, int install) { - struct bgpevpn *vpn; - struct listnode *node, *nnode; + struct bgpevpn *vpn; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (vnis, node, nnode, vpn)) - { - int ret; + for (ALL_LIST_ELEMENTS(vnis, node, nnode, vpn)) { + int ret; - if (!is_vni_live (vpn)) - continue; + if (!is_vni_live(vpn)) + continue; - if (install) - ret = install_evpn_route_entry (bgp, vpn, evp, ri); - else - ret = uninstall_evpn_route_entry (bgp, vpn, evp, ri); + if (install) + ret = install_evpn_route_entry(bgp, vpn, evp, ri); + else + ret = uninstall_evpn_route_entry(bgp, vpn, evp, ri); - if (ret) - { - zlog_err ("%u: Failed to %s EVPN %s route in VNI %u", - bgp->vrf_id, install ? "install" : "uninstall", - evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE ? \ - "MACIP" : "IMET", vpn->vni); - return ret; - } - } + if (ret) { + zlog_err("%u: Failed to %s EVPN %s route in VNI %u", + bgp->vrf_id, install ? "install" : "uninstall", + evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE + ? "MACIP" + : "IMET", + vpn->vni); + return ret; + } + } - return 0; + return 0; } /* * Install or uninstall route for appropriate VNIs. */ -static int -install_uninstall_evpn_route (struct bgp *bgp, afi_t afi, safi_t safi, - struct prefix *p, struct bgp_info *ri, - int import) -{ - struct prefix_evpn *evp = (struct prefix_evpn *)p; - struct attr *attr = ri->attr; - struct ecommunity *ecom; - int i; - - assert (attr); - - /* Only type-2 and type-3 routes go into a L2 VNI. */ - if (!(evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE || - evp->prefix.route_type == BGP_EVPN_IMET_ROUTE)) - return 0; - - /* If we don't have Route Target, nothing much to do. */ - if (!(attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES))) - return 0; - - ecom = attr->ecommunity; - if (!ecom || !ecom->size) - return -1; - - /* For each extended community RT, see which VNIs match and import - * the route into matching VNIs. - */ - for (i = 0; i < ecom->size; i++) - { - u_char *pnt; - u_char type, sub_type; - struct ecommunity_val *eval; - struct ecommunity_val eval_tmp; - struct irt_node *irt; - - /* Only deal with RTs */ - pnt = (ecom->val + (i * ECOMMUNITY_SIZE)); - eval = (struct ecommunity_val *) (ecom->val + (i * ECOMMUNITY_SIZE)); - type = *pnt++; - sub_type = *pnt++; - if (sub_type != ECOMMUNITY_ROUTE_TARGET) - continue; - - /* Are we interested in this RT? */ - irt = lookup_import_rt (bgp, eval); - if (irt && irt->vnis) - install_uninstall_route_in_vnis (bgp, afi, safi, evp, - ri, irt->vnis, import); - - /* Also check for non-exact match. In this, we mask out the AS and - * only check on the local-admin sub-field. This is to facilitate using - * VNI as the RT for EBGP peering too. - */ - irt = NULL; - if (type == ECOMMUNITY_ENCODE_AS || - type == ECOMMUNITY_ENCODE_AS4 || - type == ECOMMUNITY_ENCODE_IP) - { - memcpy (&eval_tmp, eval, ECOMMUNITY_SIZE); - mask_ecom_global_admin (&eval_tmp, eval); - irt = lookup_import_rt (bgp, &eval_tmp); - } - if (irt && irt->vnis) - install_uninstall_route_in_vnis (bgp, afi, safi, evp, - ri, irt->vnis, import); - } - - return 0; +static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi, + struct prefix *p, struct bgp_info *ri, + int import) +{ + struct prefix_evpn *evp = (struct prefix_evpn *)p; + struct attr *attr = ri->attr; + struct ecommunity *ecom; + int i; + + assert(attr); + + /* Only type-2 and type-3 routes go into a L2 VNI. */ + if (!(evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE + || evp->prefix.route_type == BGP_EVPN_IMET_ROUTE)) + return 0; + + /* If we don't have Route Target, nothing much to do. */ + if (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) + return 0; + + ecom = attr->ecommunity; + if (!ecom || !ecom->size) + return -1; + + /* For each extended community RT, see which VNIs match and import + * the route into matching VNIs. + */ + for (i = 0; i < ecom->size; i++) { + u_char *pnt; + u_char type, sub_type; + struct ecommunity_val *eval; + struct ecommunity_val eval_tmp; + struct irt_node *irt; + + /* Only deal with RTs */ + pnt = (ecom->val + (i * ECOMMUNITY_SIZE)); + eval = (struct ecommunity_val *)(ecom->val + + (i * ECOMMUNITY_SIZE)); + type = *pnt++; + sub_type = *pnt++; + if (sub_type != ECOMMUNITY_ROUTE_TARGET) + continue; + + /* Are we interested in this RT? */ + irt = lookup_import_rt(bgp, eval); + if (irt && irt->vnis) + install_uninstall_route_in_vnis(bgp, afi, safi, evp, ri, + irt->vnis, import); + + /* Also check for non-exact match. In this, we mask out the AS + * and + * only check on the local-admin sub-field. This is to + * facilitate using + * VNI as the RT for EBGP peering too. + */ + irt = NULL; + if (type == ECOMMUNITY_ENCODE_AS + || type == ECOMMUNITY_ENCODE_AS4 + || type == ECOMMUNITY_ENCODE_IP) { + memcpy(&eval_tmp, eval, ECOMMUNITY_SIZE); + mask_ecom_global_admin(&eval_tmp, eval); + irt = lookup_import_rt(bgp, &eval_tmp); + } + if (irt && irt->vnis) + install_uninstall_route_in_vnis(bgp, afi, safi, evp, ri, + irt->vnis, import); + } + + return 0; } /* @@ -1638,118 +1604,114 @@ install_uninstall_evpn_route (struct bgp *bgp, afi_t afi, safi_t safi, * change. Note that the processing is done only on the global route table * using routes that already exist in the per-VNI table. */ -static int -update_advertise_vni_routes (struct bgp *bgp, struct bgpevpn *vpn) -{ - struct prefix_evpn p; - struct bgp_node *rn, *global_rn; - struct bgp_info *ri, *global_ri; - struct attr *attr; - afi_t afi = AFI_L2VPN; - safi_t safi = SAFI_EVPN; - - /* Locate type-3 route for VNI in the per-VNI table and use its - * attributes to create and advertise the type-3 route for this VNI - * in the global table. - */ - build_evpn_type3_prefix (&p, vpn->originator_ip); - rn = bgp_node_lookup (vpn->route_table, (struct prefix *)&p); - if (!rn) /* unexpected */ - return 0; - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self - && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_STATIC) - break; - if (!ri) /* unexpected */ - return 0; - attr = ri->attr; - - global_rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, - (struct prefix *)&p, &vpn->prd); - update_evpn_route_entry (bgp, vpn, afi, safi, global_rn, - attr, 1, 0, &ri); - - /* Schedule for processing and unlock node. */ - bgp_process (bgp, global_rn, afi, safi); - bgp_unlock_node (global_rn); - - /* Now, walk this VNI's route table and use the route and its attribute - * to create and schedule route in global table. - */ - for (rn = bgp_table_top (vpn->route_table); rn; rn = bgp_route_next (rn)) - { - struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; - - /* Identify MAC-IP local routes. */ - if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) - continue; - - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self - && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_STATIC) - break; - if (!ri) - continue; - - /* Create route in global routing table using this route entry's - * attribute. - */ - attr = ri->attr; - global_rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, - (struct prefix *)evp, &vpn->prd); - assert (global_rn); - update_evpn_route_entry (bgp, vpn, afi, safi, global_rn, - attr, 1, 0, &global_ri); - - /* Schedule for processing and unlock node. */ - bgp_process (bgp, global_rn, afi, safi); - bgp_unlock_node (global_rn); - } - - return 0; +static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) +{ + struct prefix_evpn p; + struct bgp_node *rn, *global_rn; + struct bgp_info *ri, *global_ri; + struct attr *attr; + afi_t afi = AFI_L2VPN; + safi_t safi = SAFI_EVPN; + + /* Locate type-3 route for VNI in the per-VNI table and use its + * attributes to create and advertise the type-3 route for this VNI + * in the global table. + */ + build_evpn_type3_prefix(&p, vpn->originator_ip); + rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p); + if (!rn) /* unexpected */ + return 0; + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP + && ri->sub_type == BGP_ROUTE_STATIC) + break; + if (!ri) /* unexpected */ + return 0; + attr = ri->attr; + + global_rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, + (struct prefix *)&p, &vpn->prd); + update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, 1, 0, + &ri); + + /* Schedule for processing and unlock node. */ + bgp_process(bgp, global_rn, afi, safi); + bgp_unlock_node(global_rn); + + /* Now, walk this VNI's route table and use the route and its attribute + * to create and schedule route in global table. + */ + for (rn = bgp_table_top(vpn->route_table); rn; + rn = bgp_route_next(rn)) { + struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; + + /* Identify MAC-IP local routes. */ + if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) + continue; + + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == bgp->peer_self + && ri->type == ZEBRA_ROUTE_BGP + && ri->sub_type == BGP_ROUTE_STATIC) + break; + if (!ri) + continue; + + /* Create route in global routing table using this route entry's + * attribute. + */ + attr = ri->attr; + global_rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, + (struct prefix *)evp, &vpn->prd); + assert(global_rn); + update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, 1, + 0, &global_ri); + + /* Schedule for processing and unlock node. */ + bgp_process(bgp, global_rn, afi, safi); + bgp_unlock_node(global_rn); + } + + return 0; } /* * Delete (and withdraw) local routes for a VNI - only from the global * table. Invoked upon router-id change. */ -static int -delete_withdraw_vni_routes (struct bgp *bgp, struct bgpevpn *vpn) +static int delete_withdraw_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) { - int ret; - struct prefix_evpn p; - struct bgp_node *global_rn; - struct bgp_info *ri; - afi_t afi = AFI_L2VPN; - safi_t safi = SAFI_EVPN; + int ret; + struct prefix_evpn p; + struct bgp_node *global_rn; + struct bgp_info *ri; + afi_t afi = AFI_L2VPN; + safi_t safi = SAFI_EVPN; - /* Delete and withdraw locally learnt type-2 routes (MACIP) - * for this VNI - from the global table. - */ - ret = delete_global_type2_routes (bgp, vpn); - if (ret) - return ret; + /* Delete and withdraw locally learnt type-2 routes (MACIP) + * for this VNI - from the global table. + */ + ret = delete_global_type2_routes(bgp, vpn); + if (ret) + return ret; - /* Remove type-3 route for this VNI from global table. */ - build_evpn_type3_prefix (&p, vpn->originator_ip); - global_rn = bgp_afi_node_lookup (bgp->rib[afi][safi], afi, safi, - (struct prefix *)&p, &vpn->prd); - if (global_rn) - { - /* Delete route entry in the global EVPN table. */ - delete_evpn_route_entry (bgp, vpn, afi, safi, global_rn, &ri); + /* Remove type-3 route for this VNI from global table. */ + build_evpn_type3_prefix(&p, vpn->originator_ip); + global_rn = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi, + (struct prefix *)&p, &vpn->prd); + if (global_rn) { + /* Delete route entry in the global EVPN table. */ + delete_evpn_route_entry(bgp, vpn, afi, safi, global_rn, &ri); - /* Schedule for processing - withdraws to peers happen from - * this table. - */ - if (ri) - bgp_process (bgp, global_rn, afi, safi); - bgp_unlock_node (global_rn); - } + /* Schedule for processing - withdraws to peers happen from + * this table. + */ + if (ri) + bgp_process(bgp, global_rn, afi, safi); + bgp_unlock_node(global_rn); + } - return 0; + return 0; } /* @@ -1758,26 +1720,23 @@ delete_withdraw_vni_routes (struct bgp *bgp, struct bgpevpn *vpn) * router-id. The routes in the per-VNI table are used to create routes in * the global table and schedule them. */ -static void -update_router_id_vni (struct hash_backet *backet, struct bgp *bgp) +static void update_router_id_vni(struct hash_backet *backet, struct bgp *bgp) { - struct bgpevpn *vpn; + struct bgpevpn *vpn; - vpn = (struct bgpevpn *) backet->data; + vpn = (struct bgpevpn *)backet->data; - if (!vpn) - { - zlog_warn ("%s: VNI hash entry for VNI not found", - __FUNCTION__); - return; - } + if (!vpn) { + zlog_warn("%s: VNI hash entry for VNI not found", __FUNCTION__); + return; + } - /* Skip VNIs with configured RD. */ - if (is_rd_configured (vpn)) - return; + /* Skip VNIs with configured RD. */ + if (is_rd_configured(vpn)) + return; - bgp_evpn_derive_auto_rd (bgp, vpn); - update_advertise_vni_routes (bgp, vpn); + bgp_evpn_derive_auto_rd(bgp, vpn); + update_advertise_vni_routes(bgp, vpn); } /* @@ -1786,365 +1745,349 @@ update_router_id_vni (struct hash_backet *backet, struct bgp *bgp) * the router-id and is done only on the global route table, the routes * are needed in the per-VNI table to re-advertise with new router id. */ -static void -withdraw_router_id_vni (struct hash_backet *backet, struct bgp *bgp) +static void withdraw_router_id_vni(struct hash_backet *backet, struct bgp *bgp) { - struct bgpevpn *vpn; + struct bgpevpn *vpn; - vpn = (struct bgpevpn *) backet->data; + vpn = (struct bgpevpn *)backet->data; - if (!vpn) - { - zlog_warn ("%s: VNI hash entry for VNI not found", - __FUNCTION__); - return; - } + if (!vpn) { + zlog_warn("%s: VNI hash entry for VNI not found", __FUNCTION__); + return; + } - /* Skip VNIs with configured RD. */ - if (is_rd_configured (vpn)) - return; + /* Skip VNIs with configured RD. */ + if (is_rd_configured(vpn)) + return; - delete_withdraw_vni_routes (bgp, vpn); + delete_withdraw_vni_routes(bgp, vpn); } /* * Process received EVPN type-2 route (advertise or withdraw). */ -static int -process_type2_route (struct peer *peer, afi_t afi, safi_t safi, - struct attr *attr, u_char *pfx, int psize, - u_int32_t addpath_id) -{ - struct prefix_rd prd; - struct prefix_evpn p; - u_char ipaddr_len; - u_char macaddr_len; - mpls_label_t *label_pnt; - int ret; - - /* Type-2 route should be either 33, 37 or 49 bytes or an - * additional 3 bytes if there is a second label (VNI): - * RD (8), ESI (10), Eth Tag (4), MAC Addr Len (1), - * MAC Addr (6), IP len (1), IP (0, 4 or 16), - * MPLS Lbl1 (3), MPLS Lbl2 (0 or 3) - */ - if (psize != 33 && psize != 37 && psize != 49 && - psize != 36 && psize != 40 && psize != 52) - { - zlog_err ("%u:%s - Rx EVPN Type-2 NLRI with invalid length %d", - peer->bgp->vrf_id, peer->host, psize); - return -1; - } - - /* Make prefix_rd */ - prd.family = AF_UNSPEC; - prd.prefixlen = 64; - memcpy (&prd.val, pfx, 8); - pfx += 8; - - /* Make EVPN prefix. */ - memset (&p, 0, sizeof (struct prefix_evpn)); - p.family = AF_ETHERNET; - p.prefixlen = EVPN_TYPE_2_ROUTE_PREFIXLEN; - p.prefix.route_type = BGP_EVPN_MAC_IP_ROUTE; - - /* Skip over Ethernet Seg Identifier for now. */ - pfx += 10; - - /* Skip over Ethernet Tag for now. */ - pfx += 4; - - /* Get the MAC Addr len */ - macaddr_len = *pfx++; - - /* Get the MAC Addr */ - if (macaddr_len == (ETHER_ADDR_LEN * 8)) - { - memcpy (&p.prefix.mac.octet, pfx, ETHER_ADDR_LEN); - pfx += ETHER_ADDR_LEN; - } - else - { - zlog_err ("%u:%s - Rx EVPN Type-2 NLRI with unsupported MAC address length %d", - peer->bgp->vrf_id, peer->host, macaddr_len); - return -1; - } - - - /* Get the IP. */ - ipaddr_len = *pfx++; - if (ipaddr_len != 0 && - ipaddr_len != IPV4_MAX_BITLEN && - ipaddr_len != IPV6_MAX_BITLEN) - { - zlog_err ("%u:%s - Rx EVPN Type-2 NLRI with unsupported IP address length %d", - peer->bgp->vrf_id, peer->host, ipaddr_len); - return -1; - } - - if (ipaddr_len) - { - ipaddr_len /= 8; /* Convert to bytes. */ - p.prefix.ip.ipa_type = (ipaddr_len == IPV4_MAX_BYTELEN) ? - IPADDR_V4 : IPADDR_V6; - memcpy (&p.prefix.ip.ip.addr, pfx, ipaddr_len); - } - pfx += ipaddr_len; - - /* Get the VNI (in MPLS label field). */ - /* Note: We ignore the second VNI, if any. */ - label_pnt = (mpls_label_t *) pfx; - - /* Process the route. */ - if (attr) - ret = bgp_update (peer, (struct prefix *)&p, addpath_id, attr, afi, safi, - ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, label_pnt, 0, NULL); - else - ret = bgp_withdraw (peer, (struct prefix *)&p, addpath_id, attr, afi, safi, - ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, label_pnt, NULL); - return ret; +static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi, + struct attr *attr, u_char *pfx, int psize, + u_int32_t addpath_id) +{ + struct prefix_rd prd; + struct prefix_evpn p; + u_char ipaddr_len; + u_char macaddr_len; + mpls_label_t *label_pnt; + int ret; + + /* Type-2 route should be either 33, 37 or 49 bytes or an + * additional 3 bytes if there is a second label (VNI): + * RD (8), ESI (10), Eth Tag (4), MAC Addr Len (1), + * MAC Addr (6), IP len (1), IP (0, 4 or 16), + * MPLS Lbl1 (3), MPLS Lbl2 (0 or 3) + */ + if (psize != 33 && psize != 37 && psize != 49 && psize != 36 + && psize != 40 && psize != 52) { + zlog_err("%u:%s - Rx EVPN Type-2 NLRI with invalid length %d", + peer->bgp->vrf_id, peer->host, psize); + return -1; + } + + /* Make prefix_rd */ + prd.family = AF_UNSPEC; + prd.prefixlen = 64; + memcpy(&prd.val, pfx, 8); + pfx += 8; + + /* Make EVPN prefix. */ + memset(&p, 0, sizeof(struct prefix_evpn)); + p.family = AF_ETHERNET; + p.prefixlen = EVPN_TYPE_2_ROUTE_PREFIXLEN; + p.prefix.route_type = BGP_EVPN_MAC_IP_ROUTE; + + /* Skip over Ethernet Seg Identifier for now. */ + pfx += 10; + + /* Skip over Ethernet Tag for now. */ + pfx += 4; + + /* Get the MAC Addr len */ + macaddr_len = *pfx++; + + /* Get the MAC Addr */ + if (macaddr_len == (ETHER_ADDR_LEN * 8)) { + memcpy(&p.prefix.mac.octet, pfx, ETHER_ADDR_LEN); + pfx += ETHER_ADDR_LEN; + } else { + zlog_err( + "%u:%s - Rx EVPN Type-2 NLRI with unsupported MAC address length %d", + peer->bgp->vrf_id, peer->host, macaddr_len); + return -1; + } + + + /* Get the IP. */ + ipaddr_len = *pfx++; + if (ipaddr_len != 0 && ipaddr_len != IPV4_MAX_BITLEN + && ipaddr_len != IPV6_MAX_BITLEN) { + zlog_err( + "%u:%s - Rx EVPN Type-2 NLRI with unsupported IP address length %d", + peer->bgp->vrf_id, peer->host, ipaddr_len); + return -1; + } + + if (ipaddr_len) { + ipaddr_len /= 8; /* Convert to bytes. */ + p.prefix.ip.ipa_type = (ipaddr_len == IPV4_MAX_BYTELEN) + ? IPADDR_V4 + : IPADDR_V6; + memcpy(&p.prefix.ip.ip.addr, pfx, ipaddr_len); + } + pfx += ipaddr_len; + + /* Get the VNI (in MPLS label field). */ + /* Note: We ignore the second VNI, if any. */ + label_pnt = (mpls_label_t *)pfx; + + /* Process the route. */ + if (attr) + ret = bgp_update(peer, (struct prefix *)&p, addpath_id, attr, + afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, + &prd, label_pnt, 0, NULL); + else + ret = bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr, + afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, + &prd, label_pnt, NULL); + return ret; } /* * Process received EVPN type-3 route (advertise or withdraw). */ -static int -process_type3_route (struct peer *peer, afi_t afi, safi_t safi, - struct attr *attr, u_char *pfx, int psize, - u_int32_t addpath_id) -{ - struct prefix_rd prd; - struct prefix_evpn p; - u_char ipaddr_len; - int ret; - - /* Type-3 route should be either 17 or 29 bytes: RD (8), Eth Tag (4), - * IP len (1) and IP (4 or 16). - */ - if (psize != 17 && psize != 29) - { - zlog_err ("%u:%s - Rx EVPN Type-3 NLRI with invalid length %d", - peer->bgp->vrf_id, peer->host, psize); - return -1; - } - - /* Make prefix_rd */ - prd.family = AF_UNSPEC; - prd.prefixlen = 64; - memcpy (&prd.val, pfx, 8); - pfx += 8; - - /* Make EVPN prefix. */ - memset (&p, 0, sizeof (struct prefix_evpn)); - p.family = AF_ETHERNET; - p.prefixlen = EVPN_TYPE_3_ROUTE_PREFIXLEN; - p.prefix.route_type = BGP_EVPN_IMET_ROUTE; - - /* Skip over Ethernet Tag for now. */ - pfx += 4; - - /* Get the IP. */ - ipaddr_len = *pfx++; - if (ipaddr_len == IPV4_MAX_BITLEN) - { - p.prefix.ip.ipa_type = IPADDR_V4; - memcpy (&p.prefix.ip.ip.addr, pfx, IPV4_MAX_BYTELEN); - } - else - { - zlog_err ("%u:%s - Rx EVPN Type-3 NLRI with unsupported IP address length %d", - peer->bgp->vrf_id, peer->host, ipaddr_len); - return -1; - } - - /* Process the route. */ - if (attr) - ret = bgp_update (peer, (struct prefix *)&p, addpath_id, attr, afi, safi, - ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0, NULL); - else - ret = bgp_withdraw (peer, (struct prefix *)&p, addpath_id, attr, afi, safi, - ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, NULL); - return ret; +static int process_type3_route(struct peer *peer, afi_t afi, safi_t safi, + struct attr *attr, u_char *pfx, int psize, + u_int32_t addpath_id) +{ + struct prefix_rd prd; + struct prefix_evpn p; + u_char ipaddr_len; + int ret; + + /* Type-3 route should be either 17 or 29 bytes: RD (8), Eth Tag (4), + * IP len (1) and IP (4 or 16). + */ + if (psize != 17 && psize != 29) { + zlog_err("%u:%s - Rx EVPN Type-3 NLRI with invalid length %d", + peer->bgp->vrf_id, peer->host, psize); + return -1; + } + + /* Make prefix_rd */ + prd.family = AF_UNSPEC; + prd.prefixlen = 64; + memcpy(&prd.val, pfx, 8); + pfx += 8; + + /* Make EVPN prefix. */ + memset(&p, 0, sizeof(struct prefix_evpn)); + p.family = AF_ETHERNET; + p.prefixlen = EVPN_TYPE_3_ROUTE_PREFIXLEN; + p.prefix.route_type = BGP_EVPN_IMET_ROUTE; + + /* Skip over Ethernet Tag for now. */ + pfx += 4; + + /* Get the IP. */ + ipaddr_len = *pfx++; + if (ipaddr_len == IPV4_MAX_BITLEN) { + p.prefix.ip.ipa_type = IPADDR_V4; + memcpy(&p.prefix.ip.ip.addr, pfx, IPV4_MAX_BYTELEN); + } else { + zlog_err( + "%u:%s - Rx EVPN Type-3 NLRI with unsupported IP address length %d", + peer->bgp->vrf_id, peer->host, ipaddr_len); + return -1; + } + + /* Process the route. */ + if (attr) + ret = bgp_update(peer, (struct prefix *)&p, addpath_id, attr, + afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, + &prd, NULL, 0, NULL); + else + ret = bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr, + afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, + &prd, NULL, NULL); + return ret; } /* * Process received EVPN type-5 route (advertise or withdraw). */ -static int -process_type5_route (struct peer *peer, afi_t afi, safi_t safi, - struct attr *attr, u_char *pfx, int psize, - u_int32_t addpath_id, int withdraw) -{ - struct prefix_rd prd; - struct prefix_evpn p; - struct bgp_route_evpn evpn; - u_char ippfx_len; - u_int32_t eth_tag; - mpls_label_t *label_pnt; - int ret; - - /* Type-5 route should be 34 or 58 bytes: - * RD (8), ESI (10), Eth Tag (4), IP len (1), IP (4 or 16), - * GW (4 or 16) and VNI (3). - * Note that the IP and GW should both be IPv4 or both IPv6. - */ - if (psize != 34 && psize != 58) - { - zlog_err ("%u:%s - Rx EVPN Type-5 NLRI with invalid length %d", - peer->bgp->vrf_id, peer->host, psize); - return -1; - } - - /* Make prefix_rd */ - prd.family = AF_UNSPEC; - prd.prefixlen = 64; - memcpy (&prd.val, pfx, 8); - pfx += 8; - - /* Make EVPN prefix. */ - memset (&p, 0, sizeof (struct prefix_evpn)); - p.family = AF_ETHERNET; - p.prefix.route_type = BGP_EVPN_IP_PREFIX_ROUTE; - - /* Additional information outside of prefix - ESI and GW IP */ - memset(&evpn, 0, sizeof(evpn)); - - /* Fetch ESI */ - memcpy (&evpn.eth_s_id.val, pfx, 10); - pfx += 10; - - /* Fetch Ethernet Tag. */ - memcpy (ð_tag, pfx, 4); - p.prefix.eth_tag = ntohl (eth_tag); - pfx += 4; - - /* Fetch IP prefix length. */ - ippfx_len = *pfx++; - if (ippfx_len > IPV6_MAX_BITLEN) - { - zlog_err ("%u:%s - Rx EVPN Type-5 NLRI with invalid IP Prefix length %d", - peer->bgp->vrf_id, peer->host, ippfx_len); - return -1; - } - p.prefix.ip_prefix_length = ippfx_len; - - /* Determine IPv4 or IPv6 prefix */ - /* Since the address and GW are from the same family, this just becomes - * a simple check on the total size. - */ - if (psize == 34) - { - SET_IPADDR_V4 (&p.prefix.ip); - memcpy (&p.prefix.ip.ipaddr_v4, pfx, 4); - pfx += 4; - memcpy (&evpn.gw_ip.ipv4, pfx, 4); - pfx += 4; - p.prefixlen = PREFIX_LEN_ROUTE_TYPE_5_IPV4; - } - else - { - SET_IPADDR_V6 (&p.prefix.ip); - memcpy (&p.prefix.ip.ipaddr_v6, pfx, 16); - pfx += 16; - memcpy (&evpn.gw_ip.ipv6, pfx, 16); - pfx += 16; - p.prefixlen = PREFIX_LEN_ROUTE_TYPE_5_IPV6; - } - - label_pnt = (mpls_label_t *) pfx; - - /* Process the route. */ - if (!withdraw) - ret = bgp_update (peer, (struct prefix *)&p, addpath_id, attr, afi, safi, - ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, label_pnt, 0, &evpn); - else - ret = bgp_withdraw (peer, (struct prefix *)&p, addpath_id, attr, afi, safi, - ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, label_pnt, &evpn); - - return ret; -} - -static void -evpn_mpattr_encode_type5 (struct stream *s, struct prefix *p, - struct prefix_rd *prd, mpls_label_t * label, - struct attr *attr) -{ - int len; - char temp[16]; - struct evpn_addr *p_evpn_p; - - memset(&temp, 0, 16); - if (p->family != AF_ETHERNET) - return; - p_evpn_p = &(p->u.prefix_evpn); - - if (IS_IPADDR_V4(&p_evpn_p->ip)) - len = 8; /* ipv4 */ - else - len = 32; /* ipv6 */ - stream_putc(s, BGP_EVPN_IP_PREFIX_ROUTE); - /* Prefix contains RD, ESI, EthTag, IP length, IP, GWIP and VNI */ - stream_putc(s, 8 + 10 + 4 + 1 + len + 3); - stream_put(s, prd->val, 8); - if (attr && attr) - stream_put(s, &(attr->evpn_overlay.eth_s_id), 10); - else - stream_put(s, &temp, 10); - stream_putl(s, p_evpn_p->eth_tag); - stream_putc(s, p_evpn_p->ip_prefix_length); - if (IS_IPADDR_V4(&p_evpn_p->ip)) - stream_put_ipv4(s, p_evpn_p->ip.ipaddr_v4.s_addr); - else - stream_put(s, &p_evpn_p->ip.ipaddr_v6, 16); - if (attr && attr) - { - if (IS_IPADDR_V4(&p_evpn_p->ip)) - stream_put_ipv4(s, attr->evpn_overlay.gw_ip.ipv4. s_addr); - else - stream_put(s, &(attr->evpn_overlay.gw_ip.ipv6), 16); - } - else - { - if (IS_IPADDR_V4(&p_evpn_p->ip)) - stream_put_ipv4(s, 0); - else - stream_put(s, &temp, 16); - } - - if (label) - stream_put(s, label, 3); - else - stream_put3(s, 0); +static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi, + struct attr *attr, u_char *pfx, int psize, + u_int32_t addpath_id, int withdraw) +{ + struct prefix_rd prd; + struct prefix_evpn p; + struct bgp_route_evpn evpn; + u_char ippfx_len; + u_int32_t eth_tag; + mpls_label_t *label_pnt; + int ret; + + /* Type-5 route should be 34 or 58 bytes: + * RD (8), ESI (10), Eth Tag (4), IP len (1), IP (4 or 16), + * GW (4 or 16) and VNI (3). + * Note that the IP and GW should both be IPv4 or both IPv6. + */ + if (psize != 34 && psize != 58) { + zlog_err("%u:%s - Rx EVPN Type-5 NLRI with invalid length %d", + peer->bgp->vrf_id, peer->host, psize); + return -1; + } + + /* Make prefix_rd */ + prd.family = AF_UNSPEC; + prd.prefixlen = 64; + memcpy(&prd.val, pfx, 8); + pfx += 8; + + /* Make EVPN prefix. */ + memset(&p, 0, sizeof(struct prefix_evpn)); + p.family = AF_ETHERNET; + p.prefix.route_type = BGP_EVPN_IP_PREFIX_ROUTE; + + /* Additional information outside of prefix - ESI and GW IP */ + memset(&evpn, 0, sizeof(evpn)); + + /* Fetch ESI */ + memcpy(&evpn.eth_s_id.val, pfx, 10); + pfx += 10; + + /* Fetch Ethernet Tag. */ + memcpy(ð_tag, pfx, 4); + p.prefix.eth_tag = ntohl(eth_tag); + pfx += 4; + + /* Fetch IP prefix length. */ + ippfx_len = *pfx++; + if (ippfx_len > IPV6_MAX_BITLEN) { + zlog_err( + "%u:%s - Rx EVPN Type-5 NLRI with invalid IP Prefix length %d", + peer->bgp->vrf_id, peer->host, ippfx_len); + return -1; + } + p.prefix.ip_prefix_length = ippfx_len; + + /* Determine IPv4 or IPv6 prefix */ + /* Since the address and GW are from the same family, this just becomes + * a simple check on the total size. + */ + if (psize == 34) { + SET_IPADDR_V4(&p.prefix.ip); + memcpy(&p.prefix.ip.ipaddr_v4, pfx, 4); + pfx += 4; + memcpy(&evpn.gw_ip.ipv4, pfx, 4); + pfx += 4; + p.prefixlen = PREFIX_LEN_ROUTE_TYPE_5_IPV4; + } else { + SET_IPADDR_V6(&p.prefix.ip); + memcpy(&p.prefix.ip.ipaddr_v6, pfx, 16); + pfx += 16; + memcpy(&evpn.gw_ip.ipv6, pfx, 16); + pfx += 16; + p.prefixlen = PREFIX_LEN_ROUTE_TYPE_5_IPV6; + } + + label_pnt = (mpls_label_t *)pfx; + + /* Process the route. */ + if (!withdraw) + ret = bgp_update(peer, (struct prefix *)&p, addpath_id, attr, + afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, + &prd, label_pnt, 0, &evpn); + else + ret = bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr, + afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, + &prd, label_pnt, &evpn); + + return ret; +} + +static void evpn_mpattr_encode_type5(struct stream *s, struct prefix *p, + struct prefix_rd *prd, mpls_label_t *label, + struct attr *attr) +{ + int len; + char temp[16]; + struct evpn_addr *p_evpn_p; + + memset(&temp, 0, 16); + if (p->family != AF_ETHERNET) + return; + p_evpn_p = &(p->u.prefix_evpn); + + if (IS_IPADDR_V4(&p_evpn_p->ip)) + len = 8; /* ipv4 */ + else + len = 32; /* ipv6 */ + stream_putc(s, BGP_EVPN_IP_PREFIX_ROUTE); + /* Prefix contains RD, ESI, EthTag, IP length, IP, GWIP and VNI */ + stream_putc(s, 8 + 10 + 4 + 1 + len + 3); + stream_put(s, prd->val, 8); + if (attr && attr) + stream_put(s, &(attr->evpn_overlay.eth_s_id), 10); + else + stream_put(s, &temp, 10); + stream_putl(s, p_evpn_p->eth_tag); + stream_putc(s, p_evpn_p->ip_prefix_length); + if (IS_IPADDR_V4(&p_evpn_p->ip)) + stream_put_ipv4(s, p_evpn_p->ip.ipaddr_v4.s_addr); + else + stream_put(s, &p_evpn_p->ip.ipaddr_v6, 16); + if (attr && attr) { + if (IS_IPADDR_V4(&p_evpn_p->ip)) + stream_put_ipv4(s, + attr->evpn_overlay.gw_ip.ipv4.s_addr); + else + stream_put(s, &(attr->evpn_overlay.gw_ip.ipv6), 16); + } else { + if (IS_IPADDR_V4(&p_evpn_p->ip)) + stream_put_ipv4(s, 0); + else + stream_put(s, &temp, 16); + } + + if (label) + stream_put(s, label, 3); + else + stream_put3(s, 0); } /* * Cleanup specific VNI upon EVPN (advertise-all-vni) being disabled. */ -static void -cleanup_vni_on_disable (struct hash_backet *backet, struct bgp *bgp) +static void cleanup_vni_on_disable(struct hash_backet *backet, struct bgp *bgp) { - struct bgpevpn *vpn = (struct bgpevpn *) backet->data; + struct bgpevpn *vpn = (struct bgpevpn *)backet->data; - /* Remove EVPN routes and schedule for processing. */ - delete_routes_for_vni (bgp, vpn); + /* Remove EVPN routes and schedule for processing. */ + delete_routes_for_vni(bgp, vpn); - /* Clear "live" flag and see if hash needs to be freed. */ - UNSET_FLAG (vpn->flags, VNI_FLAG_LIVE); - if (!is_vni_configured (vpn)) - bgp_evpn_free (bgp, vpn); + /* Clear "live" flag and see if hash needs to be freed. */ + UNSET_FLAG(vpn->flags, VNI_FLAG_LIVE); + if (!is_vni_configured(vpn)) + bgp_evpn_free(bgp, vpn); } /* * Free a VNI entry; iterator function called during cleanup. */ -static void -free_vni_entry (struct hash_backet *backet, struct bgp *bgp) +static void free_vni_entry(struct hash_backet *backet, struct bgp *bgp) { - struct bgpevpn *vpn; + struct bgpevpn *vpn; - vpn = (struct bgpevpn *) backet->data; - delete_all_vni_routes (bgp, vpn); - bgp_evpn_free(bgp, vpn); + vpn = (struct bgpevpn *)backet->data; + delete_all_vni_routes(bgp, vpn); + bgp_evpn_free(bgp, vpn); } @@ -2159,26 +2102,26 @@ free_vni_entry (struct hash_backet *backet, struct bgp *bgp) * local routes for all VNIs being deleted and withdrawn and the next * will result in the routes being re-advertised. */ -void -bgp_evpn_handle_router_id_update (struct bgp *bgp, int withdraw) +void bgp_evpn_handle_router_id_update(struct bgp *bgp, int withdraw) { - if (withdraw) - hash_iterate (bgp->vnihash, - (void (*) (struct hash_backet *, void *)) - withdraw_router_id_vni, bgp); - else - hash_iterate (bgp->vnihash, - (void (*) (struct hash_backet *, void *)) - update_router_id_vni, bgp); + if (withdraw) + hash_iterate(bgp->vnihash, + (void (*)(struct hash_backet *, + void *))withdraw_router_id_vni, + bgp); + else + hash_iterate(bgp->vnihash, + (void (*)(struct hash_backet *, + void *))update_router_id_vni, + bgp); } /* * Handle change to export RT - update and advertise local routes. */ -int -bgp_evpn_handle_export_rt_change (struct bgp *bgp, struct bgpevpn *vpn) +int bgp_evpn_handle_export_rt_change(struct bgp *bgp, struct bgpevpn *vpn) { - return update_routes_for_vni (bgp, vpn); + return update_routes_for_vni(bgp, vpn); } /* @@ -2188,254 +2131,242 @@ bgp_evpn_handle_export_rt_change (struct bgp *bgp, struct bgpevpn *vpn) * of this VNI being deleted and withdrawn and the next will result * in the routes being re-advertised. */ -void -bgp_evpn_handle_rd_change (struct bgp *bgp, struct bgpevpn *vpn, - int withdraw) +void bgp_evpn_handle_rd_change(struct bgp *bgp, struct bgpevpn *vpn, + int withdraw) { - if (withdraw) - delete_withdraw_vni_routes (bgp, vpn); - else - update_advertise_vni_routes (bgp, vpn); + if (withdraw) + delete_withdraw_vni_routes(bgp, vpn); + else + update_advertise_vni_routes(bgp, vpn); } /* * Install routes for this VNI. Invoked upon change to Import RT. */ -int -bgp_evpn_install_routes (struct bgp *bgp, struct bgpevpn *vpn) +int bgp_evpn_install_routes(struct bgp *bgp, struct bgpevpn *vpn) { - return install_routes_for_vni (bgp, vpn); + return install_routes_for_vni(bgp, vpn); } /* * Uninstall all routes installed for this VNI. Invoked upon change * to Import RT. */ -int -bgp_evpn_uninstall_routes (struct bgp *bgp, struct bgpevpn *vpn) +int bgp_evpn_uninstall_routes(struct bgp *bgp, struct bgpevpn *vpn) { - return uninstall_routes_for_vni (bgp, vpn); + return uninstall_routes_for_vni(bgp, vpn); } /* * Function to display "tag" in route as a VNI. */ -char * -bgp_evpn_label2str (mpls_label_t *label, char *buf, int len) +char *bgp_evpn_label2str(mpls_label_t *label, char *buf, int len) { - vni_t vni; + vni_t vni; - vni = label2vni (label); - snprintf (buf, len, "%u", vni); - return buf; + vni = label2vni(label); + snprintf(buf, len, "%u", vni); + return buf; } /* * Function to convert evpn route to string. * NOTE: We don't use prefix2str as the output here is a bit different. */ -char * -bgp_evpn_route2str (struct prefix_evpn *p, char *buf, int len) -{ - char buf1[ETHER_ADDR_STRLEN]; - char buf2[PREFIX2STR_BUFFER]; - - if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) - { - snprintf (buf, len, "[%d]:[0]:[%d]:[%s]", - p->prefix.route_type, IS_EVPN_PREFIX_IPADDR_V4(p) ? \ - IPV4_MAX_BITLEN : IPV6_MAX_BITLEN, - inet_ntoa(p->prefix.ip.ipaddr_v4)); - } - else if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) - { - if (IS_EVPN_PREFIX_IPADDR_NONE(p)) - snprintf (buf, len, "[%d]:[0]:[0]:[%d]:[%s]", - p->prefix.route_type, 8*ETHER_ADDR_LEN, - prefix_mac2str (&p->prefix.mac, buf1, sizeof(buf1))); - else - { - u_char family; - - family = IS_EVPN_PREFIX_IPADDR_V4(p) ? \ - AF_INET : AF_INET6; - snprintf (buf, len, "[%d]:[0]:[0]:[%d]:[%s]:[%d]:[%s]", - p->prefix.route_type, 8*ETHER_ADDR_LEN, - prefix_mac2str (&p->prefix.mac, buf1, sizeof(buf1)), - family == AF_INET ? IPV4_MAX_BITLEN : IPV6_MAX_BITLEN, - inet_ntop (family, &p->prefix.ip.ip.addr, - buf2, PREFIX2STR_BUFFER)); - } - } - else - { - /* Currently, this is to cater to other AF_ETHERNET code. */ - } - - return(buf); +char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len) +{ + char buf1[ETHER_ADDR_STRLEN]; + char buf2[PREFIX2STR_BUFFER]; + + if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) { + snprintf(buf, len, "[%d]:[0]:[%d]:[%s]", p->prefix.route_type, + IS_EVPN_PREFIX_IPADDR_V4(p) ? IPV4_MAX_BITLEN + : IPV6_MAX_BITLEN, + inet_ntoa(p->prefix.ip.ipaddr_v4)); + } else if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) { + if (IS_EVPN_PREFIX_IPADDR_NONE(p)) + snprintf(buf, len, "[%d]:[0]:[0]:[%d]:[%s]", + p->prefix.route_type, 8 * ETHER_ADDR_LEN, + prefix_mac2str(&p->prefix.mac, buf1, + sizeof(buf1))); + else { + u_char family; + + family = IS_EVPN_PREFIX_IPADDR_V4(p) ? AF_INET + : AF_INET6; + snprintf(buf, len, "[%d]:[0]:[0]:[%d]:[%s]:[%d]:[%s]", + p->prefix.route_type, 8 * ETHER_ADDR_LEN, + prefix_mac2str(&p->prefix.mac, buf1, + sizeof(buf1)), + family == AF_INET ? IPV4_MAX_BITLEN + : IPV6_MAX_BITLEN, + inet_ntop(family, &p->prefix.ip.ip.addr, buf2, + PREFIX2STR_BUFFER)); + } + } else { + /* Currently, this is to cater to other AF_ETHERNET code. */ + } + + return (buf); } /* * Encode EVPN prefix in Update (MP_REACH) */ -void -bgp_evpn_encode_prefix (struct stream *s, struct prefix *p, - struct prefix_rd *prd, mpls_label_t *label, - struct attr *attr, int addpath_encode, - u_int32_t addpath_tx_id) -{ - struct prefix_evpn *evp = (struct prefix_evpn *)p; - int ipa_len = 0; - - if (addpath_encode) - stream_putl (s, addpath_tx_id); - - /* Route type */ - stream_putc (s, evp->prefix.route_type); - - switch (evp->prefix.route_type) - { - case BGP_EVPN_MAC_IP_ROUTE: - if (IS_EVPN_PREFIX_IPADDR_V4(evp)) - ipa_len = IPV4_MAX_BYTELEN; - else if (IS_EVPN_PREFIX_IPADDR_V6(evp)) - ipa_len = IPV6_MAX_BYTELEN; - stream_putc (s, 33 + ipa_len); // 1 VNI - stream_put (s, prd->val, 8); /* RD */ - stream_put (s, 0, 10); /* ESI */ - stream_putl (s, 0); /* Ethernet Tag ID */ - stream_putc (s, 8*ETHER_ADDR_LEN); /* Mac Addr Len - bits */ - stream_put (s, evp->prefix.mac.octet, 6); /* Mac Addr */ - stream_putc (s, 8*ipa_len); /* IP address Length */ - if (ipa_len) - stream_put (s, &evp->prefix.ip.ip.addr, ipa_len); /* IP */ - stream_put (s, label, BGP_LABEL_BYTES); /* VNI is contained in 'tag' */ - break; - - case BGP_EVPN_IMET_ROUTE: - stream_putc (s, 17); // TODO: length - assumes IPv4 address - stream_put (s, prd->val, 8); /* RD */ - stream_putl (s, 0); /* Ethernet Tag ID */ - stream_putc (s, IPV4_MAX_BITLEN); /* IP address Length - bits */ - /* Originating Router's IP Addr */ - stream_put_in_addr (s, &evp->prefix.ip.ipaddr_v4); - break; - - case BGP_EVPN_IP_PREFIX_ROUTE: - /* TODO: AddPath support. */ - evpn_mpattr_encode_type5 (s, p, prd, label, attr); - break; - - default: - break; - } -} - -int -bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr, - struct bgp_nlri *packet, int withdraw) -{ - u_char *pnt; - u_char *lim; - afi_t afi; - safi_t safi; - u_int32_t addpath_id; - int addpath_encoded; - int psize = 0; - u_char rtype; - u_char rlen; - struct prefix p; - - /* Check peer status. */ - if (peer->status != Established) - { - zlog_err ("%u:%s - EVPN update received in state %d", - peer->bgp->vrf_id, peer->host, peer->status); - return -1; - } - - /* Start processing the NLRI - there may be multiple in the MP_REACH */ - pnt = packet->nlri; - lim = pnt + packet->length; - afi = packet->afi; - safi = packet->safi; - addpath_id = 0; - - addpath_encoded = (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) && - CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV)); - - for (; pnt < lim; pnt += psize) - { - /* Clear prefix structure. */ - memset (&p, 0, sizeof (struct prefix)); - - /* Deal with path-id if AddPath is supported. */ - if (addpath_encoded) - { - /* When packet overflow occurs return immediately. */ - if (pnt + BGP_ADDPATH_ID_LEN > lim) - return -1; - - addpath_id = ntohl(*((uint32_t*) pnt)); - pnt += BGP_ADDPATH_ID_LEN; - } - - /* All EVPN NLRI types start with type and length. */ - if (pnt + 2 > lim) - return -1; - - rtype = *pnt++; - psize = rlen = *pnt++; - - /* When packet overflow occur return immediately. */ - if (pnt + psize > lim) - return -1; - - switch (rtype) - { - case BGP_EVPN_MAC_IP_ROUTE: - if (process_type2_route (peer, afi, safi, - withdraw ? NULL : attr, - pnt, psize, addpath_id)) - { - zlog_err ("%u:%s - Error in processing EVPN type-2 NLRI size %d", - peer->bgp->vrf_id, peer->host, psize); - return -1; - } - break; - - case BGP_EVPN_IMET_ROUTE: - if (process_type3_route (peer, afi, safi, - withdraw ? NULL : attr, - pnt, psize, addpath_id)) - { - zlog_err ("%u:%s - Error in processing EVPN type-3 NLRI size %d", - peer->bgp->vrf_id, peer->host, psize); - return -1; - } - break; - - case BGP_EVPN_IP_PREFIX_ROUTE: - if (process_type5_route (peer, afi, safi, attr, - pnt, psize, addpath_id, withdraw)) - { - zlog_err ("%u:%s - Error in processing EVPN type-5 NLRI size %d", - peer->bgp->vrf_id, peer->host, psize); - return -1; - } - break; - - default: - break; - } - - } - - /* Packet length consistency check. */ - if (pnt != lim) - return -1; - - return 0; +void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p, + struct prefix_rd *prd, mpls_label_t *label, + struct attr *attr, int addpath_encode, + u_int32_t addpath_tx_id) +{ + struct prefix_evpn *evp = (struct prefix_evpn *)p; + int ipa_len = 0; + + if (addpath_encode) + stream_putl(s, addpath_tx_id); + + /* Route type */ + stream_putc(s, evp->prefix.route_type); + + switch (evp->prefix.route_type) { + case BGP_EVPN_MAC_IP_ROUTE: + if (IS_EVPN_PREFIX_IPADDR_V4(evp)) + ipa_len = IPV4_MAX_BYTELEN; + else if (IS_EVPN_PREFIX_IPADDR_V6(evp)) + ipa_len = IPV6_MAX_BYTELEN; + stream_putc(s, 33 + ipa_len); // 1 VNI + stream_put(s, prd->val, 8); /* RD */ + stream_put(s, 0, 10); /* ESI */ + stream_putl(s, 0); /* Ethernet Tag ID */ + stream_putc(s, 8 * ETHER_ADDR_LEN); /* Mac Addr Len - bits */ + stream_put(s, evp->prefix.mac.octet, 6); /* Mac Addr */ + stream_putc(s, 8 * ipa_len); /* IP address Length */ + if (ipa_len) + stream_put(s, &evp->prefix.ip.ip.addr, + ipa_len); /* IP */ + stream_put(s, label, + BGP_LABEL_BYTES); /* VNI is contained in 'tag' */ + break; + + case BGP_EVPN_IMET_ROUTE: + stream_putc(s, 17); // TODO: length - assumes IPv4 address + stream_put(s, prd->val, 8); /* RD */ + stream_putl(s, 0); /* Ethernet Tag ID */ + stream_putc(s, IPV4_MAX_BITLEN); /* IP address Length - bits */ + /* Originating Router's IP Addr */ + stream_put_in_addr(s, &evp->prefix.ip.ipaddr_v4); + break; + + case BGP_EVPN_IP_PREFIX_ROUTE: + /* TODO: AddPath support. */ + evpn_mpattr_encode_type5(s, p, prd, label, attr); + break; + + default: + break; + } +} + +int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr, + struct bgp_nlri *packet, int withdraw) +{ + u_char *pnt; + u_char *lim; + afi_t afi; + safi_t safi; + u_int32_t addpath_id; + int addpath_encoded; + int psize = 0; + u_char rtype; + u_char rlen; + struct prefix p; + + /* Check peer status. */ + if (peer->status != Established) { + zlog_err("%u:%s - EVPN update received in state %d", + peer->bgp->vrf_id, peer->host, peer->status); + return -1; + } + + /* Start processing the NLRI - there may be multiple in the MP_REACH */ + pnt = packet->nlri; + lim = pnt + packet->length; + afi = packet->afi; + safi = packet->safi; + addpath_id = 0; + + addpath_encoded = + (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) + && CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ADDPATH_AF_TX_RCV)); + + for (; pnt < lim; pnt += psize) { + /* Clear prefix structure. */ + memset(&p, 0, sizeof(struct prefix)); + + /* Deal with path-id if AddPath is supported. */ + if (addpath_encoded) { + /* When packet overflow occurs return immediately. */ + if (pnt + BGP_ADDPATH_ID_LEN > lim) + return -1; + + addpath_id = ntohl(*((uint32_t *)pnt)); + pnt += BGP_ADDPATH_ID_LEN; + } + + /* All EVPN NLRI types start with type and length. */ + if (pnt + 2 > lim) + return -1; + + rtype = *pnt++; + psize = rlen = *pnt++; + + /* When packet overflow occur return immediately. */ + if (pnt + psize > lim) + return -1; + + switch (rtype) { + case BGP_EVPN_MAC_IP_ROUTE: + if (process_type2_route(peer, afi, safi, + withdraw ? NULL : attr, pnt, + psize, addpath_id)) { + zlog_err( + "%u:%s - Error in processing EVPN type-2 NLRI size %d", + peer->bgp->vrf_id, peer->host, psize); + return -1; + } + break; + + case BGP_EVPN_IMET_ROUTE: + if (process_type3_route(peer, afi, safi, + withdraw ? NULL : attr, pnt, + psize, addpath_id)) { + zlog_err( + "%u:%s - Error in processing EVPN type-3 NLRI size %d", + peer->bgp->vrf_id, peer->host, psize); + return -1; + } + break; + + case BGP_EVPN_IP_PREFIX_ROUTE: + if (process_type5_route(peer, afi, safi, attr, pnt, + psize, addpath_id, withdraw)) { + zlog_err( + "%u:%s - Error in processing EVPN type-5 NLRI size %d", + peer->bgp->vrf_id, peer->host, psize); + return -1; + } + break; + + default: + break; + } + } + + /* Packet length consistency check. */ + if (pnt != lim) + return -1; + + return 0; } @@ -2443,150 +2374,145 @@ bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr, * Map the RTs (configured or automatically derived) of a VNI to the VNI. * The mapping will be used during route processing. */ -void -bgp_evpn_map_vni_to_its_rts (struct bgp *bgp, struct bgpevpn *vpn) +void bgp_evpn_map_vni_to_its_rts(struct bgp *bgp, struct bgpevpn *vpn) { - int i; - struct ecommunity_val *eval; - struct listnode *node, *nnode; - struct ecommunity *ecom; + int i; + struct ecommunity_val *eval; + struct listnode *node, *nnode; + struct ecommunity *ecom; - for (ALL_LIST_ELEMENTS (vpn->import_rtl, node, nnode, ecom)) - { - for (i = 0; i < ecom->size; i++) - { - eval = (struct ecommunity_val *) (ecom->val + (i * ECOMMUNITY_SIZE)); - map_vni_to_rt (bgp, vpn, eval); - } - } + for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) { + for (i = 0; i < ecom->size; i++) { + eval = (struct ecommunity_val *)(ecom->val + + (i + * ECOMMUNITY_SIZE)); + map_vni_to_rt(bgp, vpn, eval); + } + } } /* * Unmap the RTs (configured or automatically derived) of a VNI from the VNI. */ -void -bgp_evpn_unmap_vni_from_its_rts (struct bgp *bgp, struct bgpevpn *vpn) +void bgp_evpn_unmap_vni_from_its_rts(struct bgp *bgp, struct bgpevpn *vpn) { - int i; - struct ecommunity_val *eval; - struct listnode *node, *nnode; - struct ecommunity *ecom; + int i; + struct ecommunity_val *eval; + struct listnode *node, *nnode; + struct ecommunity *ecom; - for (ALL_LIST_ELEMENTS (vpn->import_rtl, node, nnode, ecom)) - { - for (i = 0; i < ecom->size; i++) - { - struct irt_node *irt; - struct ecommunity_val eval_tmp; + for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) { + for (i = 0; i < ecom->size; i++) { + struct irt_node *irt; + struct ecommunity_val eval_tmp; - eval = (struct ecommunity_val *) (ecom->val + (i * ECOMMUNITY_SIZE)); - /* If using "automatic" RT, we only care about the local-admin sub-field. - * This is to facilitate using VNI as the RT for EBGP peering too. - */ - memcpy (&eval_tmp, eval, ECOMMUNITY_SIZE); - if (!is_import_rt_configured (vpn)) - mask_ecom_global_admin (&eval_tmp, eval); + eval = (struct ecommunity_val *)(ecom->val + + (i + * ECOMMUNITY_SIZE)); + /* If using "automatic" RT, we only care about the + * local-admin sub-field. + * This is to facilitate using VNI as the RT for EBGP + * peering too. + */ + memcpy(&eval_tmp, eval, ECOMMUNITY_SIZE); + if (!is_import_rt_configured(vpn)) + mask_ecom_global_admin(&eval_tmp, eval); - irt = lookup_import_rt (bgp, &eval_tmp); - if (irt) - unmap_vni_from_rt (bgp, vpn, irt); - } - } + irt = lookup_import_rt(bgp, &eval_tmp); + if (irt) + unmap_vni_from_rt(bgp, vpn, irt); + } + } } /* * Derive Import RT automatically for VNI and map VNI to RT. * The mapping will be used during route processing. */ -void -bgp_evpn_derive_auto_rt_import (struct bgp *bgp, struct bgpevpn *vpn) +void bgp_evpn_derive_auto_rt_import(struct bgp *bgp, struct bgpevpn *vpn) { - form_auto_rt (bgp, vpn, vpn->import_rtl); - UNSET_FLAG (vpn->flags, VNI_FLAG_IMPRT_CFGD); + form_auto_rt(bgp, vpn, vpn->import_rtl); + UNSET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD); - /* Map RT to VNI */ - bgp_evpn_map_vni_to_its_rts (bgp, vpn); + /* Map RT to VNI */ + bgp_evpn_map_vni_to_its_rts(bgp, vpn); } /* * Derive Export RT automatically for VNI. */ -void -bgp_evpn_derive_auto_rt_export (struct bgp *bgp, struct bgpevpn *vpn) +void bgp_evpn_derive_auto_rt_export(struct bgp *bgp, struct bgpevpn *vpn) { - form_auto_rt (bgp, vpn, vpn->export_rtl); - UNSET_FLAG (vpn->flags, VNI_FLAG_EXPRT_CFGD); + form_auto_rt(bgp, vpn, vpn->export_rtl); + UNSET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD); } /* * Derive RD automatically for VNI using passed information - it * is of the form RouterId:unique-id-for-vni. */ -void -bgp_evpn_derive_auto_rd (struct bgp *bgp, struct bgpevpn *vpn) +void bgp_evpn_derive_auto_rd(struct bgp *bgp, struct bgpevpn *vpn) { - char buf[100]; + char buf[100]; - vpn->prd.family = AF_UNSPEC; - vpn->prd.prefixlen = 64; - sprintf (buf, "%s:%hu", inet_ntoa (bgp->router_id), vpn->rd_id); - str2prefix_rd (buf, &vpn->prd); - UNSET_FLAG (vpn->flags, VNI_FLAG_RD_CFGD); + vpn->prd.family = AF_UNSPEC; + vpn->prd.prefixlen = 64; + sprintf(buf, "%s:%hu", inet_ntoa(bgp->router_id), vpn->rd_id); + str2prefix_rd(buf, &vpn->prd); + UNSET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD); } /* * Lookup VNI. */ -struct bgpevpn * -bgp_evpn_lookup_vni (struct bgp *bgp, vni_t vni) +struct bgpevpn *bgp_evpn_lookup_vni(struct bgp *bgp, vni_t vni) { - struct bgpevpn *vpn; - struct bgpevpn tmp; + struct bgpevpn *vpn; + struct bgpevpn tmp; - memset(&tmp, 0, sizeof(struct bgpevpn)); - tmp.vni = vni; - vpn = hash_lookup (bgp->vnihash, &tmp); - return vpn; + memset(&tmp, 0, sizeof(struct bgpevpn)); + tmp.vni = vni; + vpn = hash_lookup(bgp->vnihash, &tmp); + return vpn; } /* * Create a new vpn - invoked upon configuration or zebra notification. */ -struct bgpevpn * -bgp_evpn_new (struct bgp *bgp, vni_t vni, struct in_addr originator_ip) +struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni, + struct in_addr originator_ip) { - struct bgpevpn *vpn; + struct bgpevpn *vpn; - if (!bgp) - return NULL; + if (!bgp) + return NULL; - vpn = XCALLOC (MTYPE_BGP_EVPN, sizeof (struct bgpevpn)); - if (!vpn) - return NULL; + vpn = XCALLOC(MTYPE_BGP_EVPN, sizeof(struct bgpevpn)); + if (!vpn) + return NULL; - /* Set values - RD and RT set to defaults. */ - vpn->vni = vni; - vpn->originator_ip = originator_ip; + /* Set values - RD and RT set to defaults. */ + vpn->vni = vni; + vpn->originator_ip = originator_ip; - /* Initialize route-target import and export lists */ - vpn->import_rtl = list_new (); - vpn->import_rtl->cmp = (int (*)(void *, void *)) evpn_route_target_cmp; - vpn->export_rtl = list_new (); - vpn->export_rtl->cmp = (int (*)(void *, void *)) evpn_route_target_cmp; - bf_assign_index(bgp->rd_idspace, vpn->rd_id); - derive_rd_rt_for_vni (bgp, vpn); + /* Initialize route-target import and export lists */ + vpn->import_rtl = list_new(); + vpn->import_rtl->cmp = (int (*)(void *, void *))evpn_route_target_cmp; + vpn->export_rtl = list_new(); + vpn->export_rtl->cmp = (int (*)(void *, void *))evpn_route_target_cmp; + bf_assign_index(bgp->rd_idspace, vpn->rd_id); + derive_rd_rt_for_vni(bgp, vpn); - /* Initialize EVPN route table. */ - vpn->route_table = bgp_table_init (AFI_L2VPN, SAFI_EVPN); + /* Initialize EVPN route table. */ + vpn->route_table = bgp_table_init(AFI_L2VPN, SAFI_EVPN); - /* Add to hash */ - if (!hash_get(bgp->vnihash, vpn, hash_alloc_intern)) - { - XFREE(MTYPE_BGP_EVPN, vpn); - return NULL; - } - QOBJ_REG (vpn, bgpevpn); - return vpn; + /* Add to hash */ + if (!hash_get(bgp->vnihash, vpn, hash_alloc_intern)) { + XFREE(MTYPE_BGP_EVPN, vpn); + return NULL; + } + QOBJ_REG(vpn, bgpevpn); + return vpn; } /* @@ -2595,243 +2521,225 @@ bgp_evpn_new (struct bgp *bgp, vni_t vni, struct in_addr originator_ip) * This just frees appropriate memory, caller should have taken other * needed actions. */ -void -bgp_evpn_free (struct bgp *bgp, struct bgpevpn *vpn) +void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn) { - bgp_table_unlock (vpn->route_table); - bgp_evpn_unmap_vni_from_its_rts (bgp, vpn); - list_delete (vpn->import_rtl); - list_delete (vpn->export_rtl); - vpn->import_rtl = NULL; - vpn->export_rtl = NULL; - bf_release_index(bgp->rd_idspace, vpn->rd_id); - hash_release (bgp->vnihash, vpn); - QOBJ_UNREG (vpn); - XFREE(MTYPE_BGP_EVPN, vpn); + bgp_table_unlock(vpn->route_table); + bgp_evpn_unmap_vni_from_its_rts(bgp, vpn); + list_delete(vpn->import_rtl); + list_delete(vpn->export_rtl); + vpn->import_rtl = NULL; + vpn->export_rtl = NULL; + bf_release_index(bgp->rd_idspace, vpn->rd_id); + hash_release(bgp->vnihash, vpn); + QOBJ_UNREG(vpn); + XFREE(MTYPE_BGP_EVPN, vpn); } /* * Import route into matching VNI(s). */ -int -bgp_evpn_import_route (struct bgp *bgp, afi_t afi, safi_t safi, - struct prefix *p, struct bgp_info *ri) +int bgp_evpn_import_route(struct bgp *bgp, afi_t afi, safi_t safi, + struct prefix *p, struct bgp_info *ri) { - return install_uninstall_evpn_route (bgp, afi, safi, p, ri, 1); + return install_uninstall_evpn_route(bgp, afi, safi, p, ri, 1); } /* * Unimport route from matching VNI(s). */ -int -bgp_evpn_unimport_route (struct bgp *bgp, afi_t afi, safi_t safi, - struct prefix *p, struct bgp_info *ri) +int bgp_evpn_unimport_route(struct bgp *bgp, afi_t afi, safi_t safi, + struct prefix *p, struct bgp_info *ri) { - return install_uninstall_evpn_route (bgp, afi, safi, p, ri, 0); + return install_uninstall_evpn_route(bgp, afi, safi, p, ri, 0); } /* * Handle del of a local MACIP. */ -int -bgp_evpn_local_macip_del (struct bgp *bgp, vni_t vni, - struct ethaddr *mac, struct ipaddr *ip) +int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni, struct ethaddr *mac, + struct ipaddr *ip) { - struct bgpevpn *vpn; - struct prefix_evpn p; + struct bgpevpn *vpn; + struct prefix_evpn p; - if (!bgp->vnihash) - { - zlog_err ("%u: VNI hash not created", bgp->vrf_id); - return -1; - } + if (!bgp->vnihash) { + zlog_err("%u: VNI hash not created", bgp->vrf_id); + return -1; + } - /* Lookup VNI hash - should exist. */ - vpn = bgp_evpn_lookup_vni (bgp, vni); - if (!vpn || !is_vni_live (vpn)) - { - zlog_warn ("%u: VNI hash entry for VNI %u %s at MACIP DEL", - bgp->vrf_id, vni, vpn ? "not live" : "not found"); - return -1; - } + /* Lookup VNI hash - should exist. */ + vpn = bgp_evpn_lookup_vni(bgp, vni); + if (!vpn || !is_vni_live(vpn)) { + zlog_warn("%u: VNI hash entry for VNI %u %s at MACIP DEL", + bgp->vrf_id, vni, vpn ? "not live" : "not found"); + return -1; + } - /* Remove EVPN type-2 route and schedule for processing. */ - build_evpn_type2_prefix (&p, mac, ip); - delete_evpn_route (bgp, vpn, &p); + /* Remove EVPN type-2 route and schedule for processing. */ + build_evpn_type2_prefix(&p, mac, ip); + delete_evpn_route(bgp, vpn, &p); - return 0; + return 0; } /* * Handle add of a local MACIP. */ -int -bgp_evpn_local_macip_add (struct bgp *bgp, vni_t vni, - struct ethaddr *mac, struct ipaddr *ip, - u_char sticky) +int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, struct ethaddr *mac, + struct ipaddr *ip, u_char sticky) { - struct bgpevpn *vpn; - struct prefix_evpn p; + struct bgpevpn *vpn; + struct prefix_evpn p; - if (!bgp->vnihash) - { - zlog_err ("%u: VNI hash not created", bgp->vrf_id); - return -1; - } + if (!bgp->vnihash) { + zlog_err("%u: VNI hash not created", bgp->vrf_id); + return -1; + } - /* Lookup VNI hash - should exist. */ - vpn = bgp_evpn_lookup_vni (bgp, vni); - if (!vpn || !is_vni_live (vpn)) - { - zlog_warn ("%u: VNI hash entry for VNI %u %s at MACIP ADD", - bgp->vrf_id, vni, vpn ? "not live" : "not found"); - return -1; - } + /* Lookup VNI hash - should exist. */ + vpn = bgp_evpn_lookup_vni(bgp, vni); + if (!vpn || !is_vni_live(vpn)) { + zlog_warn("%u: VNI hash entry for VNI %u %s at MACIP ADD", + bgp->vrf_id, vni, vpn ? "not live" : "not found"); + return -1; + } - /* Create EVPN type-2 route and schedule for processing. */ - build_evpn_type2_prefix (&p, mac, ip); - if (update_evpn_route (bgp, vpn, &p, sticky)) - { - char buf[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; + /* Create EVPN type-2 route and schedule for processing. */ + build_evpn_type2_prefix(&p, mac, ip); + if (update_evpn_route(bgp, vpn, &p, sticky)) { + char buf[ETHER_ADDR_STRLEN]; + char buf2[INET6_ADDRSTRLEN]; - zlog_err ("%u:Failed to create Type-2 route, VNI %u %sMAC %s IP %s", - bgp->vrf_id, vpn->vni, - sticky ? "sticky" : "", - prefix_mac2str (mac, buf, sizeof (buf)), - ipaddr2str (ip, buf2, sizeof(buf2))); - return -1; - } + zlog_err( + "%u:Failed to create Type-2 route, VNI %u %sMAC %s IP %s", + bgp->vrf_id, vpn->vni, sticky ? "sticky" : "", + prefix_mac2str(mac, buf, sizeof(buf)), + ipaddr2str(ip, buf2, sizeof(buf2))); + return -1; + } - return 0; + return 0; } /* * Handle del of a local VNI. */ -int -bgp_evpn_local_vni_del (struct bgp *bgp, vni_t vni) +int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni) { - struct bgpevpn *vpn; + struct bgpevpn *vpn; - if (!bgp->vnihash) - { - zlog_err ("%u: VNI hash not created", bgp->vrf_id); - return -1; - } + if (!bgp->vnihash) { + zlog_err("%u: VNI hash not created", bgp->vrf_id); + return -1; + } - /* Locate VNI hash */ - vpn = bgp_evpn_lookup_vni (bgp, vni); - if (!vpn) - { - zlog_warn ("%u: VNI hash entry for VNI %u not found at DEL", - bgp->vrf_id, vni); - return 0; - } + /* Locate VNI hash */ + vpn = bgp_evpn_lookup_vni(bgp, vni); + if (!vpn) { + zlog_warn("%u: VNI hash entry for VNI %u not found at DEL", + bgp->vrf_id, vni); + return 0; + } - /* Remove all local EVPN routes and schedule for processing (to - * withdraw from peers). - */ - delete_routes_for_vni (bgp, vpn); + /* Remove all local EVPN routes and schedule for processing (to + * withdraw from peers). + */ + delete_routes_for_vni(bgp, vpn); - /* Clear "live" flag and see if hash needs to be freed. */ - UNSET_FLAG (vpn->flags, VNI_FLAG_LIVE); - if (!is_vni_configured (vpn)) - bgp_evpn_free (bgp, vpn); + /* Clear "live" flag and see if hash needs to be freed. */ + UNSET_FLAG(vpn->flags, VNI_FLAG_LIVE); + if (!is_vni_configured(vpn)) + bgp_evpn_free(bgp, vpn); - return 0; + return 0; } /* * Handle add (or update) of a local VNI. The only VNI change we care * about is change to local-tunnel-ip. */ -int -bgp_evpn_local_vni_add (struct bgp *bgp, vni_t vni, struct in_addr originator_ip) -{ - struct bgpevpn *vpn; - struct prefix_evpn p; - - if (!bgp->vnihash) - { - zlog_err ("%u: VNI hash not created", bgp->vrf_id); - return -1; - } - - /* Lookup VNI. If present and no change, exit. */ - vpn = bgp_evpn_lookup_vni (bgp, vni); - if (vpn && is_vni_live (vpn)) - { - if (IPV4_ADDR_SAME (&vpn->originator_ip, &originator_ip)) - /* Probably some other param has changed that we don't care about. */ - return 0; - - /* Local tunnel endpoint IP address has changed */ - return handle_tunnel_ip_change (bgp, vpn, originator_ip); - } - - /* Create or update as appropriate. */ - if (!vpn) - { - vpn = bgp_evpn_new (bgp, vni, originator_ip); - if (!vpn) - { - zlog_err ("%u: Failed to allocate VNI entry for VNI %u - at Add", - bgp->vrf_id, vni); - return -1; - } - } - - /* Mark as "live" */ - SET_FLAG (vpn->flags, VNI_FLAG_LIVE); - - /* Create EVPN type-3 route and schedule for processing. */ - build_evpn_type3_prefix (&p, vpn->originator_ip); - if (update_evpn_route (bgp, vpn, &p, 0)) - { - zlog_err ("%u: Type3 route creation failure for VNI %u", - bgp->vrf_id, vni); - return -1; - } - - /* If we have learnt and retained remote routes (VTEPs, MACs) for this VNI, - * install them. - */ - install_routes_for_vni (bgp, vpn); - - return 0; +int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni, + struct in_addr originator_ip) +{ + struct bgpevpn *vpn; + struct prefix_evpn p; + + if (!bgp->vnihash) { + zlog_err("%u: VNI hash not created", bgp->vrf_id); + return -1; + } + + /* Lookup VNI. If present and no change, exit. */ + vpn = bgp_evpn_lookup_vni(bgp, vni); + if (vpn && is_vni_live(vpn)) { + if (IPV4_ADDR_SAME(&vpn->originator_ip, &originator_ip)) + /* Probably some other param has changed that we don't + * care about. */ + return 0; + + /* Local tunnel endpoint IP address has changed */ + return handle_tunnel_ip_change(bgp, vpn, originator_ip); + } + + /* Create or update as appropriate. */ + if (!vpn) { + vpn = bgp_evpn_new(bgp, vni, originator_ip); + if (!vpn) { + zlog_err( + "%u: Failed to allocate VNI entry for VNI %u - at Add", + bgp->vrf_id, vni); + return -1; + } + } + + /* Mark as "live" */ + SET_FLAG(vpn->flags, VNI_FLAG_LIVE); + + /* Create EVPN type-3 route and schedule for processing. */ + build_evpn_type3_prefix(&p, vpn->originator_ip); + if (update_evpn_route(bgp, vpn, &p, 0)) { + zlog_err("%u: Type3 route creation failure for VNI %u", + bgp->vrf_id, vni); + return -1; + } + + /* If we have learnt and retained remote routes (VTEPs, MACs) for this + * VNI, + * install them. + */ + install_routes_for_vni(bgp, vpn); + + return 0; } /* * Cleanup EVPN information on disable - Need to delete and withdraw * EVPN routes from peers. */ -void -bgp_evpn_cleanup_on_disable (struct bgp *bgp) +void bgp_evpn_cleanup_on_disable(struct bgp *bgp) { - hash_iterate (bgp->vnihash, - (void (*) (struct hash_backet *, void *)) - cleanup_vni_on_disable, bgp); + hash_iterate(bgp->vnihash, (void (*)(struct hash_backet *, + void *))cleanup_vni_on_disable, + bgp); } /* * Cleanup EVPN information - invoked at the time of bgpd exit or when the * BGP instance (default) is being freed. */ -void -bgp_evpn_cleanup (struct bgp *bgp) +void bgp_evpn_cleanup(struct bgp *bgp) { - if (bgp->vnihash) - hash_iterate (bgp->vnihash, - (void (*) (struct hash_backet *, void *)) - free_vni_entry, bgp); - if (bgp->import_rt_hash) - hash_free (bgp->import_rt_hash); - bgp->import_rt_hash = NULL; - if (bgp->vnihash) - hash_free (bgp->vnihash); - bgp->vnihash = NULL; - bf_free (bgp->rd_idspace); + if (bgp->vnihash) + hash_iterate(bgp->vnihash, (void (*)(struct hash_backet *, + void *))free_vni_entry, + bgp); + if (bgp->import_rt_hash) + hash_free(bgp->import_rt_hash); + bgp->import_rt_hash = NULL; + if (bgp->vnihash) + hash_free(bgp->vnihash); + bgp->vnihash = NULL; + bf_free(bgp->rd_idspace); } /* @@ -2841,16 +2749,14 @@ bgp_evpn_cleanup (struct bgp *bgp) * hash for RT to VNI * unique rd id space for auto derivation of RD for VNIs */ -void -bgp_evpn_init (struct bgp *bgp) -{ - bgp->vnihash = hash_create (vni_hash_key_make, - vni_hash_cmp, - "BGP VNI Hash"); - bgp->import_rt_hash = hash_create (import_rt_hash_key_make, - import_rt_hash_cmp, - "BGP Import RT Hash"); - bf_init (bgp->rd_idspace, UINT16_MAX); - /*assign 0th index in the bitfield, so that we start with id 1*/ - bf_assign_zero_index (bgp->rd_idspace); +void bgp_evpn_init(struct bgp *bgp) +{ + bgp->vnihash = + hash_create(vni_hash_key_make, vni_hash_cmp, "BGP VNI Hash"); + bgp->import_rt_hash = + hash_create(import_rt_hash_key_make, import_rt_hash_cmp, + "BGP Import RT Hash"); + bf_init(bgp->rd_idspace, UINT16_MAX); + /*assign 0th index in the bitfield, so that we start with id 1*/ + bf_assign_zero_index(bgp->rd_idspace); } diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index 610710d84..f4c7e68a5 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -25,41 +25,29 @@ #define EVPN_ROUTE_STRLEN 200 /* Must be >> MAC + IPv6 strings. */ -extern void -bgp_evpn_handle_router_id_update (struct bgp *bgp, int withdraw); -extern char * -bgp_evpn_label2str (mpls_label_t *label, char *buf, int len); -extern char * -bgp_evpn_route2str (struct prefix_evpn *p, char *buf, int len); -extern void -bgp_evpn_encode_prefix (struct stream *s, struct prefix *p, - struct prefix_rd *prd, mpls_label_t *label, - struct attr *attr, int addpath_encode, - u_int32_t addpath_tx_id); +extern void bgp_evpn_handle_router_id_update(struct bgp *bgp, int withdraw); +extern char *bgp_evpn_label2str(mpls_label_t *label, char *buf, int len); +extern char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len); +extern void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p, + struct prefix_rd *prd, mpls_label_t *label, + struct attr *attr, int addpath_encode, + u_int32_t addpath_tx_id); extern int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr, struct bgp_nlri *packet, int withdraw); -extern int -bgp_evpn_import_route (struct bgp *bgp, afi_t afi, safi_t safi, - struct prefix *p, struct bgp_info *ri); -extern int -bgp_evpn_unimport_route (struct bgp *bgp, afi_t afi, safi_t safi, - struct prefix *p, struct bgp_info *ri); -extern int -bgp_evpn_local_macip_del (struct bgp *bgp, vni_t vni, - struct ethaddr *mac, struct ipaddr *ip); -extern int -bgp_evpn_local_macip_add (struct bgp *bgp, vni_t vni, - struct ethaddr *mac, struct ipaddr *ip, - u_char sticky); -extern int -bgp_evpn_local_vni_del (struct bgp *bgp, vni_t vni); -extern int -bgp_evpn_local_vni_add (struct bgp *bgp, vni_t vni, struct in_addr originator_ip); -extern void -bgp_evpn_cleanup_on_disable (struct bgp *bgp); -extern void -bgp_evpn_cleanup (struct bgp *bgp); -extern void -bgp_evpn_init (struct bgp *bgp); +extern int bgp_evpn_import_route(struct bgp *bgp, afi_t afi, safi_t safi, + struct prefix *p, struct bgp_info *ri); +extern int bgp_evpn_unimport_route(struct bgp *bgp, afi_t afi, safi_t safi, + struct prefix *p, struct bgp_info *ri); +extern int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni, + struct ethaddr *mac, struct ipaddr *ip); +extern int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, + struct ethaddr *mac, struct ipaddr *ip, + u_char sticky); +extern int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni); +extern int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni, + struct in_addr originator_ip); +extern void bgp_evpn_cleanup_on_disable(struct bgp *bgp); +extern void bgp_evpn_cleanup(struct bgp *bgp); +extern void bgp_evpn_init(struct bgp *bgp); #endif /* _QUAGGA_BGP_EVPN_H */ diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h index cd40fa9f0..816a7df98 100644 --- a/bgpd/bgp_evpn_private.h +++ b/bgpd/bgp_evpn_private.h @@ -33,13 +33,12 @@ #define EVPN_TYPE_3_ROUTE_PREFIXLEN 224 /* EVPN route types. */ -typedef enum -{ - BGP_EVPN_AD_ROUTE = 1, /* Ethernet Auto-Discovery (A-D) route */ - BGP_EVPN_MAC_IP_ROUTE, /* MAC/IP Advertisement route */ - BGP_EVPN_IMET_ROUTE, /* Inclusive Multicast Ethernet Tag route */ - BGP_EVPN_ES_ROUTE, /* Ethernet Segment route */ - BGP_EVPN_IP_PREFIX_ROUTE, /* IP Prefix route */ +typedef enum { + BGP_EVPN_AD_ROUTE = 1, /* Ethernet Auto-Discovery (A-D) route */ + BGP_EVPN_MAC_IP_ROUTE, /* MAC/IP Advertisement route */ + BGP_EVPN_IMET_ROUTE, /* Inclusive Multicast Ethernet Tag route */ + BGP_EVPN_ES_ROUTE, /* Ethernet Segment route */ + BGP_EVPN_IP_PREFIX_ROUTE, /* IP Prefix route */ } bgp_evpn_route_type; /* @@ -50,33 +49,32 @@ typedef enum * on the system (through interaction with zebra) as well as pre-configured * VNIs (which need to be defined in the system to become "live"). */ -struct bgpevpn -{ - vni_t vni; - u_int32_t flags; +struct bgpevpn { + vni_t vni; + u_int32_t flags; #define VNI_FLAG_CFGD 0x1 /* VNI is user configured */ #define VNI_FLAG_LIVE 0x2 /* VNI is "live" */ #define VNI_FLAG_RD_CFGD 0x4 /* RD is user configured. */ #define VNI_FLAG_IMPRT_CFGD 0x8 /* Import RT is user configured */ #define VNI_FLAG_EXPRT_CFGD 0x10 /* Export RT is user configured */ - /* Id for deriving the RD automatically for this VNI */ - u_int16_t rd_id; + /* Id for deriving the RD automatically for this VNI */ + u_int16_t rd_id; - /* RD for this VNI. */ - struct prefix_rd prd; + /* RD for this VNI. */ + struct prefix_rd prd; - /* Route type 3 field */ - struct in_addr originator_ip; + /* Route type 3 field */ + struct in_addr originator_ip; - /* Import and Export RTs. */ - struct list *import_rtl; - struct list *export_rtl; + /* Import and Export RTs. */ + struct list *import_rtl; + struct list *export_rtl; - /* Route table for EVPN routes for this VNI. */ - struct bgp_table *route_table; + /* Route table for EVPN routes for this VNI. */ + struct bgp_table *route_table; - QOBJ_FIELDS + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(bgpevpn) @@ -85,148 +83,131 @@ DECLARE_QOBJ_TYPE(bgpevpn) * The Import RTs of all VNIs are maintained in a hash table with each * RT linking to all VNIs that will import routes matching this RT. */ -struct irt_node -{ - /* RT */ - struct ecommunity_val rt; +struct irt_node { + /* RT */ + struct ecommunity_val rt; - /* List of VNIs importing routes matching this RT. */ - struct list *vnis; + /* List of VNIs importing routes matching this RT. */ + struct list *vnis; }; #define RT_TYPE_IMPORT 1 #define RT_TYPE_EXPORT 2 #define RT_TYPE_BOTH 3 -static inline int -is_vni_configured (struct bgpevpn *vpn) +static inline int is_vni_configured(struct bgpevpn *vpn) { - return (CHECK_FLAG (vpn->flags, VNI_FLAG_CFGD)); + return (CHECK_FLAG(vpn->flags, VNI_FLAG_CFGD)); } -static inline int -is_vni_live (struct bgpevpn *vpn) +static inline int is_vni_live(struct bgpevpn *vpn) { - return (CHECK_FLAG (vpn->flags, VNI_FLAG_LIVE)); + return (CHECK_FLAG(vpn->flags, VNI_FLAG_LIVE)); } -static inline int -is_rd_configured (struct bgpevpn *vpn) +static inline int is_rd_configured(struct bgpevpn *vpn) { - return (CHECK_FLAG (vpn->flags, VNI_FLAG_RD_CFGD)); + return (CHECK_FLAG(vpn->flags, VNI_FLAG_RD_CFGD)); } -static inline int -bgp_evpn_rd_matches_existing (struct bgpevpn *vpn, struct prefix_rd *prd) +static inline int bgp_evpn_rd_matches_existing(struct bgpevpn *vpn, + struct prefix_rd *prd) { - return(memcmp (&vpn->prd.val, prd->val, ECOMMUNITY_SIZE) == 0); + return (memcmp(&vpn->prd.val, prd->val, ECOMMUNITY_SIZE) == 0); } -static inline int -is_import_rt_configured (struct bgpevpn *vpn) +static inline int is_import_rt_configured(struct bgpevpn *vpn) { - return (CHECK_FLAG (vpn->flags, VNI_FLAG_IMPRT_CFGD)); + return (CHECK_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD)); } -static inline int -is_export_rt_configured (struct bgpevpn *vpn) +static inline int is_export_rt_configured(struct bgpevpn *vpn) { - return (CHECK_FLAG (vpn->flags, VNI_FLAG_EXPRT_CFGD)); + return (CHECK_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD)); } -static inline int -is_vni_param_configured (struct bgpevpn *vpn) +static inline int is_vni_param_configured(struct bgpevpn *vpn) { - return (is_rd_configured (vpn) || - is_import_rt_configured (vpn) || - is_export_rt_configured (vpn)); + return (is_rd_configured(vpn) || is_import_rt_configured(vpn) + || is_export_rt_configured(vpn)); } -static inline void -vni2label (vni_t vni, mpls_label_t *label) +static inline void vni2label(vni_t vni, mpls_label_t *label) { - u_char *tag = (u_char *) label; - tag[0] = (vni >> 16) & 0xFF; - tag[1] = (vni >> 8) & 0xFF; - tag[2] = vni & 0xFF; + u_char *tag = (u_char *)label; + tag[0] = (vni >> 16) & 0xFF; + tag[1] = (vni >> 8) & 0xFF; + tag[2] = vni & 0xFF; } -static inline vni_t -label2vni (mpls_label_t *label) +static inline vni_t label2vni(mpls_label_t *label) { - u_char *tag = (u_char *) label; - vni_t vni; + u_char *tag = (u_char *)label; + vni_t vni; - vni = ((u_int32_t) *tag++ << 16); - vni |= (u_int32_t) *tag++ << 8; - vni |= (u_int32_t) (*tag & 0xFF); + vni = ((u_int32_t)*tag++ << 16); + vni |= (u_int32_t)*tag++ << 8; + vni |= (u_int32_t)(*tag & 0xFF); - return vni; + return vni; } -static inline void -encode_mac_mobility_extcomm (int static_mac, u_int32_t seq, - struct ecommunity_val *eval) +static inline void encode_mac_mobility_extcomm(int static_mac, u_int32_t seq, + struct ecommunity_val *eval) { - memset (eval, 0, sizeof (*eval)); - eval->val[0] = ECOMMUNITY_ENCODE_EVPN; - eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY; - if (static_mac) - eval->val[2] = ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY; - eval->val[4] = (seq >> 24) & 0xff; - eval->val[5] = (seq >> 16) & 0xff; - eval->val[6] = (seq >> 8) & 0xff; - eval->val[7] = seq & 0xff; + memset(eval, 0, sizeof(*eval)); + eval->val[0] = ECOMMUNITY_ENCODE_EVPN; + eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY; + if (static_mac) + eval->val[2] = ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY; + eval->val[4] = (seq >> 24) & 0xff; + eval->val[5] = (seq >> 16) & 0xff; + eval->val[6] = (seq >> 8) & 0xff; + eval->val[7] = seq & 0xff; } -static inline void -build_evpn_type2_prefix (struct prefix_evpn *p, struct ethaddr *mac, - struct ipaddr *ip) +static inline void build_evpn_type2_prefix(struct prefix_evpn *p, + struct ethaddr *mac, + struct ipaddr *ip) { - memset (p, 0, sizeof (struct prefix_evpn)); - p->family = AF_ETHERNET; - p->prefixlen = EVPN_TYPE_2_ROUTE_PREFIXLEN; - p->prefix.route_type = BGP_EVPN_MAC_IP_ROUTE; - memcpy(&p->prefix.mac.octet, mac->octet, ETHER_ADDR_LEN); - p->prefix.ip.ipa_type = IPADDR_NONE; - if (ip) - memcpy(&p->prefix.ip, ip, sizeof (*ip)); + memset(p, 0, sizeof(struct prefix_evpn)); + p->family = AF_ETHERNET; + p->prefixlen = EVPN_TYPE_2_ROUTE_PREFIXLEN; + p->prefix.route_type = BGP_EVPN_MAC_IP_ROUTE; + memcpy(&p->prefix.mac.octet, mac->octet, ETHER_ADDR_LEN); + p->prefix.ip.ipa_type = IPADDR_NONE; + if (ip) + memcpy(&p->prefix.ip, ip, sizeof(*ip)); } -static inline void -build_evpn_type3_prefix (struct prefix_evpn *p, struct in_addr originator_ip) +static inline void build_evpn_type3_prefix(struct prefix_evpn *p, + struct in_addr originator_ip) { - memset (p, 0, sizeof (struct prefix_evpn)); - p->family = AF_ETHERNET; - p->prefixlen = EVPN_TYPE_3_ROUTE_PREFIXLEN; - p->prefix.route_type = BGP_EVPN_IMET_ROUTE; - p->prefix.ip.ipa_type = IPADDR_V4; - p->prefix.ip.ipaddr_v4 = originator_ip; + memset(p, 0, sizeof(struct prefix_evpn)); + p->family = AF_ETHERNET; + p->prefixlen = EVPN_TYPE_3_ROUTE_PREFIXLEN; + p->prefix.route_type = BGP_EVPN_IMET_ROUTE; + p->prefix.ip.ipa_type = IPADDR_V4; + p->prefix.ip.ipaddr_v4 = originator_ip; } -extern int -bgp_evpn_handle_export_rt_change (struct bgp *bgp, struct bgpevpn *vpn); -extern void -bgp_evpn_handle_rd_change (struct bgp *bgp, struct bgpevpn *vpn, int withdraw); -extern int -bgp_evpn_install_routes (struct bgp *bgp, struct bgpevpn *vpn); -extern int -bgp_evpn_uninstall_routes (struct bgp *bgp, struct bgpevpn *vpn); -extern void -bgp_evpn_map_vni_to_its_rts (struct bgp *bgp, struct bgpevpn *vpn); -extern void -bgp_evpn_unmap_vni_from_its_rts (struct bgp *bgp, struct bgpevpn *vpn); -extern void -bgp_evpn_derive_auto_rt_import (struct bgp *bgp, struct bgpevpn *vpn); -extern void -bgp_evpn_derive_auto_rt_export (struct bgp *bgp, struct bgpevpn *vpn); -extern void -bgp_evpn_derive_auto_rd (struct bgp *bgp, struct bgpevpn *vpn); -extern struct bgpevpn * -bgp_evpn_lookup_vni (struct bgp *bgp, vni_t vni); -extern struct bgpevpn * -bgp_evpn_new (struct bgp *bgp, vni_t vni, struct in_addr originator_ip); -extern void -bgp_evpn_free (struct bgp *bgp, struct bgpevpn *vpn); +extern int bgp_evpn_handle_export_rt_change(struct bgp *bgp, + struct bgpevpn *vpn); +extern void bgp_evpn_handle_rd_change(struct bgp *bgp, struct bgpevpn *vpn, + int withdraw); +extern int bgp_evpn_install_routes(struct bgp *bgp, struct bgpevpn *vpn); +extern int bgp_evpn_uninstall_routes(struct bgp *bgp, struct bgpevpn *vpn); +extern void bgp_evpn_map_vni_to_its_rts(struct bgp *bgp, struct bgpevpn *vpn); +extern void bgp_evpn_unmap_vni_from_its_rts(struct bgp *bgp, + struct bgpevpn *vpn); +extern void bgp_evpn_derive_auto_rt_import(struct bgp *bgp, + struct bgpevpn *vpn); +extern void bgp_evpn_derive_auto_rt_export(struct bgp *bgp, + struct bgpevpn *vpn); +extern void bgp_evpn_derive_auto_rd(struct bgp *bgp, struct bgpevpn *vpn); +extern struct bgpevpn *bgp_evpn_lookup_vni(struct bgp *bgp, vni_t vni); +extern struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni, + struct in_addr originator_ip); +extern void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn); #endif /* _BGP_EVPN_PRIVATE_H */ diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index b5a58f014..4b39ee862 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -42,305 +42,289 @@ /* * Context for VNI hash walk - used by callbacks. */ -struct vni_walk_ctx -{ - struct bgp *bgp; - struct vty *vty; - struct in_addr vtep_ip; +struct vni_walk_ctx { + struct bgp *bgp; + struct vty *vty; + struct in_addr vtep_ip; }; -struct evpn_config_write -{ - int write; - struct vty *vty; +struct evpn_config_write { + int write; + struct vty *vty; }; -#if defined (HAVE_CUMULUS) -static void -display_import_rt (struct vty *vty, struct irt_node *irt) +#if defined(HAVE_CUMULUS) +static void display_import_rt(struct vty *vty, struct irt_node *irt) +{ + u_char *pnt; + u_char type, sub_type; + struct ecommunity_as { + as_t as; + u_int32_t val; + } eas; + struct ecommunity_ip { + struct in_addr ip; + u_int16_t val; + } eip; + struct listnode *node, *nnode; + struct bgpevpn *tmp_vpn; + + + /* TODO: This needs to go into a function */ + + pnt = (u_char *)&irt->rt.val; + type = *pnt++; + sub_type = *pnt++; + if (sub_type != ECOMMUNITY_ROUTE_TARGET) + return; + + switch (type) { + case ECOMMUNITY_ENCODE_AS: + eas.as = (*pnt++ << 8); + eas.as |= (*pnt++); + + eas.val = (*pnt++ << 24); + eas.val |= (*pnt++ << 16); + eas.val |= (*pnt++ << 8); + eas.val |= (*pnt++); + + vty_out(vty, "Route-target: %u:%u", eas.as, eas.val); + break; + + case ECOMMUNITY_ENCODE_IP: + memcpy(&eip.ip, pnt, 4); + pnt += 4; + eip.val = (*pnt++ << 8); + eip.val |= (*pnt++); + + vty_out(vty, "Route-target: %s:%u", inet_ntoa(eip.ip), eip.val); + break; + + case ECOMMUNITY_ENCODE_AS4: + eas.as = (*pnt++ << 24); + eas.as |= (*pnt++ << 16); + eas.as |= (*pnt++ << 8); + eas.as |= (*pnt++); + + eas.val = (*pnt++ << 8); + eas.val |= (*pnt++); + + vty_out(vty, "Route-target: %u:%u", eas.as, eas.val); + break; + + default: + return; + } + + vty_out(vty, "\n"); + vty_out(vty, "List of VNIs importing routes with this route-target:\n"); + + for (ALL_LIST_ELEMENTS(irt->vnis, node, nnode, tmp_vpn)) + vty_out(vty, " %u\n", tmp_vpn->vni); +} + +static void show_import_rt_entry(struct hash_backet *backet, struct vty *vty) { - u_char *pnt; - u_char type, sub_type; - struct ecommunity_as - { - as_t as; - u_int32_t val; - } eas; - struct ecommunity_ip - { - struct in_addr ip; - u_int16_t val; - } eip; - struct listnode *node, *nnode; - struct bgpevpn *tmp_vpn; + struct irt_node *irt = (struct irt_node *)backet->data; + display_import_rt(vty, irt); +} +static void bgp_evpn_show_route_rd_header(struct vty *vty, + struct bgp_node *rd_rn) +{ + u_int16_t type; + struct rd_as rd_as; + struct rd_ip rd_ip; + u_char *pnt; - /* TODO: This needs to go into a function */ + pnt = rd_rn->p.u.val; - pnt = (u_char *)&irt->rt.val; - type = *pnt++; - sub_type = *pnt++; - if (sub_type != ECOMMUNITY_ROUTE_TARGET) - return; + /* Decode RD type. */ + type = decode_rd_type(pnt); - switch (type) - { - case ECOMMUNITY_ENCODE_AS: - eas.as = (*pnt++ << 8); - eas.as |= (*pnt++); + vty_out(vty, "Route Distinguisher: "); - eas.val = (*pnt++ << 24); - eas.val |= (*pnt++ << 16); - eas.val |= (*pnt++ << 8); - eas.val |= (*pnt++); + switch (type) { + case RD_TYPE_AS: + decode_rd_as(pnt + 2, &rd_as); + vty_out(vty, "%u:%d", rd_as.as, rd_as.val); + break; - vty_out (vty, "Route-target: %u:%u", eas.as, eas.val); - break; + case RD_TYPE_IP: + decode_rd_ip(pnt + 2, &rd_ip); + vty_out(vty, "%s:%d", inet_ntoa(rd_ip.ip), rd_ip.val); + break; - case ECOMMUNITY_ENCODE_IP: - memcpy (&eip.ip, pnt, 4); - pnt += 4; - eip.val = (*pnt++ << 8); - eip.val |= (*pnt++); + default: + vty_out(vty, "Unknown RD type"); + break; + } + + vty_out(vty, "\n"); +} + +static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp) +{ + char ri_header[] = + " Network Next Hop Metric LocPrf Weight Path\n"; - vty_out (vty, "Route-target: %s:%u", - inet_ntoa (eip.ip), eip.val); - break; + vty_out(vty, "BGP table version is 0, local router ID is %s\n", + inet_ntoa(bgp->router_id)); + vty_out(vty, + "Status codes: s suppressed, d damped, h history, " + "* valid, > best, i - internal\n"); + vty_out(vty, "Origin codes: i - IGP, e - EGP, ? - incomplete\n"); + vty_out(vty, + "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n"); + vty_out(vty, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n\n"); + vty_out(vty, "%s", ri_header); +} - case ECOMMUNITY_ENCODE_AS4: - eas.as = (*pnt++ << 24); - eas.as |= (*pnt++ << 16); - eas.as |= (*pnt++ << 8); - eas.as |= (*pnt++); +static void display_vni(struct vty *vty, struct bgpevpn *vpn) +{ + char buf1[INET6_ADDRSTRLEN]; + char *ecom_str; + struct listnode *node, *nnode; + struct ecommunity *ecom; - eas.val = (*pnt++ << 8); - eas.val |= (*pnt++); + vty_out(vty, "VNI: %d", vpn->vni); + if (is_vni_live(vpn)) + vty_out(vty, " (known to the kernel)"); + vty_out(vty, "\n"); - vty_out (vty, "Route-target: %u:%u", eas.as, eas.val); - break; - - default: - return; - } + vty_out(vty, " RD: %s\n", + prefix_rd2str(&vpn->prd, buf1, RD_ADDRSTRLEN)); + vty_out(vty, " Originator IP: %s\n", inet_ntoa(vpn->originator_ip)); - vty_out (vty, "\n"); - vty_out (vty, "List of VNIs importing routes with this route-target:\n"); + vty_out(vty, " Import Route Target:\n"); + for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) { + ecom_str = ecommunity_ecom2str(ecom, + ECOMMUNITY_FORMAT_ROUTE_MAP, 0); + vty_out(vty, " %s\n", ecom_str); + XFREE(MTYPE_ECOMMUNITY_STR, ecom_str); + } - for (ALL_LIST_ELEMENTS (irt->vnis, node, nnode, tmp_vpn)) - vty_out (vty, " %u\n", tmp_vpn->vni); + vty_out(vty, " Export Route Target:\n"); + for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) { + ecom_str = ecommunity_ecom2str(ecom, + ECOMMUNITY_FORMAT_ROUTE_MAP, 0); + vty_out(vty, " %s\n", ecom_str); + XFREE(MTYPE_ECOMMUNITY_STR, ecom_str); + } } - -static void -show_import_rt_entry (struct hash_backet *backet, struct vty *vty) + +static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type, + struct vty *vty, struct in_addr vtep_ip) { - struct irt_node *irt = (struct irt_node *) backet->data; - display_import_rt (vty, irt); + struct bgp_node *rn; + struct bgp_info *ri; + int header = 1; + u_int32_t prefix_cnt, path_cnt; + + prefix_cnt = path_cnt = 0; + + for (rn = bgp_table_top(vpn->route_table); rn; + rn = bgp_route_next(rn)) { + struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; + + if (type && evp->prefix.route_type != type) + continue; + + if (rn->info) { + /* Overall header/legend displayed once. */ + if (header) { + bgp_evpn_show_route_header(vty, bgp); + header = 0; + } + + prefix_cnt++; + } + + /* For EVPN, the prefix is displayed for each path (to fit in + * with code that already exists). + */ + for (ri = rn->info; ri; ri = ri->next) { + if (vtep_ip.s_addr + && !IPV4_ADDR_SAME(&(vtep_ip), + &(ri->attr->nexthop))) + continue; + + path_cnt++; + route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN, NULL); + } + } + + if (prefix_cnt == 0) + vty_out(vty, "No EVPN prefixes %sexist for this VNI\n", + type ? "(of requested type) " : ""); + else + vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n", + prefix_cnt, path_cnt, + type ? " (of requested type)" : ""); } -static void -bgp_evpn_show_route_rd_header (struct vty *vty, struct bgp_node *rd_rn) +static void show_vni_routes_hash(struct hash_backet *backet, void *arg) { - u_int16_t type; - struct rd_as rd_as; - struct rd_ip rd_ip; - u_char *pnt; + struct bgpevpn *vpn = (struct bgpevpn *)backet->data; + struct vni_walk_ctx *wctx = arg; + struct vty *vty = wctx->vty; - pnt = rd_rn->p.u.val; - - /* Decode RD type. */ - type = decode_rd_type (pnt); - - vty_out (vty, "Route Distinguisher: "); - - switch (type) - { - case RD_TYPE_AS: - decode_rd_as (pnt + 2, &rd_as); - vty_out (vty, "%u:%d", rd_as.as, rd_as.val); - break; - - case RD_TYPE_IP: - decode_rd_ip (pnt + 2, &rd_ip); - vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val); - break; - - default: - vty_out (vty, "Unknown RD type"); - break; - } - - vty_out (vty, "\n"); -} - -static void -bgp_evpn_show_route_header (struct vty *vty, struct bgp *bgp) -{ - char ri_header[] = " Network Next Hop Metric LocPrf Weight Path\n"; - - vty_out (vty, "BGP table version is 0, local router ID is %s\n", - inet_ntoa (bgp->router_id)); - vty_out (vty, "Status codes: s suppressed, d damped, h history, " - "* valid, > best, i - internal\n"); - vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete\n"); - vty_out (vty, "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n"); - vty_out (vty, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n\n"); - vty_out (vty, "%s", ri_header); + vty_out(vty, "\nVNI: %d\n\n", vpn->vni); + show_vni_routes(wctx->bgp, vpn, 0, wctx->vty, wctx->vtep_ip); } -static void -display_vni (struct vty *vty, struct bgpevpn *vpn) +static void show_vni_entry(struct hash_backet *backet, struct vty *vty) { - char buf1[INET6_ADDRSTRLEN]; - char *ecom_str; - struct listnode *node, *nnode; - struct ecommunity *ecom; + struct bgpevpn *vpn = (struct bgpevpn *)backet->data; + char buf1[10]; + char buf2[INET6_ADDRSTRLEN]; + char rt_buf[25]; + char *ecom_str; + struct listnode *node, *nnode; + struct ecommunity *ecom; - vty_out (vty, "VNI: %d", vpn->vni); - if (is_vni_live (vpn)) - vty_out (vty, " (known to the kernel)"); - vty_out (vty, "\n"); + buf1[0] = '\0'; + if (is_vni_live(vpn)) + sprintf(buf1, "*"); - vty_out (vty, " RD: %s\n", - prefix_rd2str (&vpn->prd, buf1, RD_ADDRSTRLEN)); - vty_out (vty, " Originator IP: %s\n", - inet_ntoa(vpn->originator_ip)); + vty_out(vty, "%-1s %-10u %-15s %-21s", buf1, vpn->vni, + inet_ntoa(vpn->originator_ip), + prefix_rd2str(&vpn->prd, buf2, RD_ADDRSTRLEN)); - vty_out (vty, " Import Route Target:\n"); - for (ALL_LIST_ELEMENTS (vpn->import_rtl, node, nnode, ecom)) - { - ecom_str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); - vty_out (vty, " %s\n", ecom_str); - XFREE (MTYPE_ECOMMUNITY_STR, ecom_str); - } + for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) { + ecom_str = ecommunity_ecom2str(ecom, + ECOMMUNITY_FORMAT_ROUTE_MAP, 0); - vty_out (vty, " Export Route Target:\n"); - for (ALL_LIST_ELEMENTS (vpn->export_rtl, node, nnode, ecom)) - { - ecom_str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); - vty_out (vty, " %s\n", ecom_str); - XFREE (MTYPE_ECOMMUNITY_STR, ecom_str); - } -} + if (listcount(vpn->import_rtl) > 1) + sprintf(rt_buf, "%s, ...", ecom_str); + else + sprintf(rt_buf, "%s", ecom_str); + vty_out(vty, " %-25s", rt_buf); -static void -show_vni_routes (struct bgp *bgp, struct bgpevpn *vpn, int type, - struct vty *vty, struct in_addr vtep_ip) -{ - struct bgp_node *rn; - struct bgp_info *ri; - int header = 1; - u_int32_t prefix_cnt, path_cnt; - - prefix_cnt = path_cnt = 0; - - for (rn = bgp_table_top (vpn->route_table); rn; rn = bgp_route_next (rn)) - { - struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; - - if (type && - evp->prefix.route_type != type) - continue; - - if (rn->info) - { - /* Overall header/legend displayed once. */ - if (header) - { - bgp_evpn_show_route_header (vty, bgp); - header = 0; - } - - prefix_cnt++; - } - - /* For EVPN, the prefix is displayed for each path (to fit in - * with code that already exists). - */ - for (ri = rn->info; ri; ri = ri->next) - { - if (vtep_ip.s_addr && - !IPV4_ADDR_SAME(&(vtep_ip), &(ri->attr->nexthop))) - continue; - - path_cnt++; - route_vty_out (vty, &rn->p, ri, 0, SAFI_EVPN, NULL); - } - } - - if (prefix_cnt == 0) - vty_out (vty, "No EVPN prefixes %sexist for this VNI\n", - type ? "(of requested type) " : ""); - else - vty_out (vty, "\nDisplayed %u prefixes (%u paths)%s\n", - prefix_cnt, path_cnt, - type ? " (of requested type)" : ""); -} - -static void -show_vni_routes_hash (struct hash_backet *backet, void *arg) -{ - struct bgpevpn *vpn = (struct bgpevpn *) backet->data; - struct vni_walk_ctx *wctx = arg; - struct vty *vty = wctx->vty; - - vty_out (vty, "\nVNI: %d\n\n", vpn->vni); - show_vni_routes (wctx->bgp, vpn, 0, wctx->vty, wctx->vtep_ip); -} - -static void -show_vni_entry (struct hash_backet *backet, struct vty *vty) -{ - struct bgpevpn *vpn = (struct bgpevpn *) backet->data; - char buf1[10]; - char buf2[INET6_ADDRSTRLEN]; - char rt_buf[25]; - char *ecom_str; - struct listnode *node, *nnode; - struct ecommunity *ecom; - - buf1[0] = '\0'; - if (is_vni_live (vpn)) - sprintf (buf1, "*"); - - vty_out(vty, "%-1s %-10u %-15s %-21s", - buf1, vpn->vni, inet_ntoa(vpn->originator_ip), - prefix_rd2str (&vpn->prd, buf2, RD_ADDRSTRLEN)); - - for (ALL_LIST_ELEMENTS (vpn->import_rtl, node, nnode, ecom)) - { - ecom_str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); - - if (listcount(vpn->import_rtl) > 1) - sprintf (rt_buf, "%s, ...", ecom_str); - else - sprintf (rt_buf, "%s", ecom_str); - vty_out (vty, " %-25s", rt_buf); - - XFREE (MTYPE_ECOMMUNITY_STR, ecom_str); - break; - } - - for (ALL_LIST_ELEMENTS (vpn->export_rtl, node, nnode, ecom)) - { - ecom_str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); - - if (listcount(vpn->export_rtl) > 1) - sprintf (rt_buf, "%s, ...", ecom_str); - else - sprintf (rt_buf, "%s", ecom_str); - vty_out (vty, " %-25s", rt_buf); - - XFREE (MTYPE_ECOMMUNITY_STR, ecom_str); - break; - } - vty_out (vty, "\n"); + XFREE(MTYPE_ECOMMUNITY_STR, ecom_str); + break; + } + + for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) { + ecom_str = ecommunity_ecom2str(ecom, + ECOMMUNITY_FORMAT_ROUTE_MAP, 0); + + if (listcount(vpn->export_rtl) > 1) + sprintf(rt_buf, "%s, ...", ecom_str); + else + sprintf(rt_buf, "%s", ecom_str); + vty_out(vty, " %-25s", rt_buf); + + XFREE(MTYPE_ECOMMUNITY_STR, ecom_str); + break; + } + vty_out(vty, "\n"); } #endif /* HAVE_CUMULUS */ -static int -bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd, - enum bgp_show_type type, void *output_arg, int option, - u_char use_json) +static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd, + enum bgp_show_type type, void *output_arg, + int option, u_char use_json) { afi_t afi = AFI_L2VPN; struct bgp *bgp; @@ -362,7 +346,7 @@ bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd, bgp = bgp_get_default(); if (bgp == NULL) { if (!use_json) - vty_out (vty,"No BGP process is configured\n"); + vty_out(vty, "No BGP process is configured\n"); return CMD_WARNING; } @@ -387,7 +371,7 @@ bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd, for (rn = bgp_table_top(bgp->rib[afi][SAFI_EVPN]); rn; rn = bgp_route_next(rn)) { if (use_json) - continue; /* XXX json TODO */ + continue; /* XXX json TODO */ if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0) continue; @@ -401,54 +385,57 @@ bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd, total_count++; if (type == bgp_show_type_neighbor) { union sockunion *su = - output_arg; + output_arg; if (ri->peer->su_remote == NULL - || !sockunion_same(ri-> - peer-> - su_remote, - su)) + || !sockunion_same( + ri->peer->su_remote, + su)) continue; } if (header == 0) { if (use_json) { - if (option == - SHOW_DISPLAY_TAGS) { - json_object_int_add - (json, - "bgpTableVersion", - 0); - json_object_string_add - (json, - "bgpLocalRouterId", - inet_ntoa - (bgp-> - router_id)); - json_object_object_add - (json, - "bgpStatusCodes", - json_scode); - json_object_object_add - (json, - "bgpOriginCodes", - json_ocode); + if (option + == SHOW_DISPLAY_TAGS) { + json_object_int_add( + json, + "bgpTableVersion", + 0); + json_object_string_add( + json, + "bgpLocalRouterId", + inet_ntoa( + bgp->router_id)); + json_object_object_add( + json, + "bgpStatusCodes", + json_scode); + json_object_object_add( + json, + "bgpOriginCodes", + json_ocode); } } else { - if (option == - SHOW_DISPLAY_TAGS) - vty_out(vty, V4_HEADER_TAG); - else if (option == - SHOW_DISPLAY_OVERLAY) - vty_out(vty, V4_HEADER_OVERLAY); + if (option + == SHOW_DISPLAY_TAGS) + vty_out(vty, + V4_HEADER_TAG); + else if ( + option + == SHOW_DISPLAY_OVERLAY) + vty_out(vty, + V4_HEADER_OVERLAY); else { - vty_out (vty, + vty_out(vty, "BGP table version is 0, local router ID is %s\n", - inet_ntoa(bgp->router_id)); - vty_out (vty, + inet_ntoa( + bgp->router_id)); + vty_out(vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n"); - vty_out (vty, + vty_out(vty, "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n"); - vty_out(vty, V4_HEADER); + vty_out(vty, + V4_HEADER); } } header = 0; @@ -476,73 +463,60 @@ bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd, if (use_json) { char buffer[BUFSIZ]; if (type == RD_TYPE_AS - || type == - RD_TYPE_AS4) + || type == RD_TYPE_AS4) sprintf(buffer, "%u:%d", - rd_as. - as, - rd_as. - val); - else if (type == - RD_TYPE_IP) + rd_as.as, + rd_as.val); + else if (type + == RD_TYPE_IP) sprintf(buffer, "%s:%d", - inet_ntoa - (rd_ip. - ip), - rd_ip. - val); - json_object_string_add - (json_nroute, - "routeDistinguisher", - buffer); + inet_ntoa( + rd_ip.ip), + rd_ip.val); + json_object_string_add( + json_nroute, + "routeDistinguisher", + buffer); } else { vty_out(vty, "Route Distinguisher: "); if (type == RD_TYPE_AS) vty_out(vty, "as2 %u:%d", - rd_as. - as, - rd_as. - val); - else if (type == - RD_TYPE_AS4) + rd_as.as, + rd_as.val); + else if (type + == RD_TYPE_AS4) vty_out(vty, "as4 %u:%d", - rd_as. - as, - rd_as. - val); - else if (type == - RD_TYPE_IP) + rd_as.as, + rd_as.val); + else if (type + == RD_TYPE_IP) vty_out(vty, "ip %s:%d", - inet_ntoa - (rd_ip. - ip), - rd_ip. - val); - vty_out (vty, "\n\n"); + inet_ntoa( + rd_ip.ip), + rd_ip.val); + vty_out(vty, "\n\n"); } rd_header = 0; } if (use_json) json_array = - json_object_new_array(); + json_object_new_array(); else json_array = NULL; if (option == SHOW_DISPLAY_TAGS) - route_vty_out_tag(vty, &rm->p, - ri, 0, - SAFI_EVPN, - json_array); + route_vty_out_tag( + vty, &rm->p, ri, 0, + SAFI_EVPN, json_array); else if (option == SHOW_DISPLAY_OVERLAY) - route_vty_out_overlay(vty, - &rm->p, - ri, 0, - json_array); + route_vty_out_overlay( + vty, &rm->p, ri, 0, + json_array); else route_vty_out(vty, &rm->p, ri, 0, SAFI_EVPN, @@ -553,10 +527,10 @@ bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd, } } if (output_count == 0) - vty_out (vty, "No prefixes displayed, %ld exist\n", - total_count); + vty_out(vty, "No prefixes displayed, %ld exist\n", total_count); else - vty_out (vty, "\nDisplayed %ld out of %ld total prefixes\n", output_count, total_count); + vty_out(vty, "\nDisplayed %ld out of %ld total prefixes\n", + output_count, total_count); return CMD_SUCCESS; } @@ -584,11 +558,11 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd, int ret; struct prefix_rd prd; - argv_find (argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community); + argv_find(argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community); ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd); if (!ret) { - vty_out (vty, "%% Malformed Route Distinguisher\n"); + vty_out(vty, "%% Malformed Route Distinguisher\n"); return CMD_WARNING; } return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL, 0, @@ -625,11 +599,11 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags, int ret; struct prefix_rd prd; - argv_find (argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community); + argv_find(argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community); ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd); if (!ret) { - vty_out (vty, "%% Malformed Route Distinguisher\n"); + vty_out(vty, "%% Malformed Route Distinguisher\n"); return CMD_WARNING; } return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL, 1, @@ -655,7 +629,7 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes, int ret; u_char uj = use_json(argc, argv); - argv_find (argv, argc, "A.B.C.D", &idx_ipv4); + argv_find(argv, argc, "A.B.C.D", &idx_ipv4); ret = str2sockunion(argv[idx_ipv4]->arg, &su); if (ret < 0) { @@ -664,11 +638,11 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes, json_no = json_object_new_object(); json_object_string_add(json_no, "warning", "Malformed address"); - vty_out (vty, "%s\n", + vty_out(vty, "%s\n", json_object_to_json_string(json_no)); json_object_free(json_no); } else - vty_out (vty, "Malformed address: %s\n", + vty_out(vty, "Malformed address: %s\n", argv[idx_ipv4]->arg); return CMD_WARNING; } @@ -678,14 +652,14 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes, if (uj) { json_object *json_no = NULL; json_no = json_object_new_object(); - json_object_string_add(json_no, "warning", - "No such neighbor or address family"); - vty_out (vty, "%s\n", + json_object_string_add( + json_no, "warning", + "No such neighbor or address family"); + vty_out(vty, "%s\n", json_object_to_json_string(json_no)); json_object_free(json_no); } else - vty_out (vty, - "%% No such neighbor or address family\n"); + vty_out(vty, "%% No such neighbor or address family\n"); return CMD_WARNING; } @@ -715,8 +689,8 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes, struct prefix_rd prd; u_char uj = use_json(argc, argv); - argv_find (argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community); - argv_find (argv, argc, "A.B.C.D", &idx_ipv4); + argv_find(argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community); + argv_find(argv, argc, "A.B.C.D", &idx_ipv4); ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd); if (!ret) { @@ -725,11 +699,11 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes, json_no = json_object_new_object(); json_object_string_add(json_no, "warning", "Malformed Route Distinguisher"); - vty_out (vty, "%s\n", + vty_out(vty, "%s\n", json_object_to_json_string(json_no)); json_object_free(json_no); } else - vty_out (vty,"%% Malformed Route Distinguisher\n"); + vty_out(vty, "%% Malformed Route Distinguisher\n"); return CMD_WARNING; } @@ -740,11 +714,11 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes, json_no = json_object_new_object(); json_object_string_add(json_no, "warning", "Malformed address"); - vty_out (vty, "%s\n", + vty_out(vty, "%s\n", json_object_to_json_string(json_no)); json_object_free(json_no); } else - vty_out (vty, "Malformed address: %s\n", + vty_out(vty, "Malformed address: %s\n", argv[idx_ext_community]->arg); return CMD_WARNING; } @@ -754,14 +728,14 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes, if (uj) { json_object *json_no = NULL; json_no = json_object_new_object(); - json_object_string_add(json_no, "warning", - "No such neighbor or address family"); - vty_out (vty, "%s\n", + json_object_string_add( + json_no, "warning", + "No such neighbor or address family"); + vty_out(vty, "%s\n", json_object_to_json_string(json_no)); json_object_free(json_no); } else - vty_out (vty, - "%% No such neighbor or address family\n"); + vty_out(vty, "%% No such neighbor or address family\n"); return CMD_WARNING; } @@ -788,7 +762,7 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes, union sockunion su; u_char uj = use_json(argc, argv); - argv_find (argv, argc, "A.B.C.D", &idx_ipv4); + argv_find(argv, argc, "A.B.C.D", &idx_ipv4); ret = str2sockunion(argv[idx_ipv4]->arg, &su); if (ret < 0) { @@ -797,11 +771,11 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes, json_no = json_object_new_object(); json_object_string_add(json_no, "warning", "Malformed address"); - vty_out (vty, "%s\n", + vty_out(vty, "%s\n", json_object_to_json_string(json_no)); json_object_free(json_no); } else - vty_out (vty, "Malformed address: %s\n", + vty_out(vty, "Malformed address: %s\n", argv[idx_ipv4]->arg); return CMD_WARNING; } @@ -810,14 +784,14 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes, if (uj) { json_object *json_no = NULL; json_no = json_object_new_object(); - json_object_string_add(json_no, "warning", - "No such neighbor or address family"); - vty_out (vty, "%s\n", + json_object_string_add( + json_no, "warning", + "No such neighbor or address family"); + vty_out(vty, "%s\n", json_object_to_json_string(json_no)); json_object_free(json_no); } else - vty_out (vty, - "%% No such neighbor or address family\n"); + vty_out(vty, "%% No such neighbor or address family\n"); return CMD_WARNING; } @@ -846,8 +820,8 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes, union sockunion su; u_char uj = use_json(argc, argv); - argv_find (argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community); - argv_find (argv, argc, "A.B.C.D", &idx_ipv4); + argv_find(argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community); + argv_find(argv, argc, "A.B.C.D", &idx_ipv4); ret = str2sockunion(argv[idx_ipv4]->arg, &su); if (ret < 0) { @@ -856,11 +830,11 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes, json_no = json_object_new_object(); json_object_string_add(json_no, "warning", "Malformed address"); - vty_out (vty, "%s\n", + vty_out(vty, "%s\n", json_object_to_json_string(json_no)); json_object_free(json_no); } else - vty_out (vty, "Malformed address: %s\n", + vty_out(vty, "Malformed address: %s\n", argv[idx_ext_community]->arg); return CMD_WARNING; } @@ -869,14 +843,14 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes, if (uj) { json_object *json_no = NULL; json_no = json_object_new_object(); - json_object_string_add(json_no, "warning", - "No such neighbor or address family"); - vty_out (vty, "%s\n", + json_object_string_add( + json_no, "warning", + "No such neighbor or address family"); + vty_out(vty, "%s\n", json_object_to_json_string(json_no)); json_object_free(json_no); } else - vty_out (vty, - "%% No such neighbor or address family\n"); + vty_out(vty, "%% No such neighbor or address family\n"); return CMD_WARNING; } @@ -887,11 +861,11 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes, json_no = json_object_new_object(); json_object_string_add(json_no, "warning", "Malformed Route Distinguisher"); - vty_out (vty, "%s\n", + vty_out(vty, "%s\n", json_object_to_json_string(json_no)); json_object_free(json_no); } else - vty_out (vty,"%% Malformed Route Distinguisher\n"); + vty_out(vty, "%% Malformed Route Distinguisher\n"); return CMD_WARNING; } @@ -910,8 +884,8 @@ DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay, "Display BGP Overlay Information for prefixes\n") { return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL, - SHOW_DISPLAY_OVERLAY, use_json(argc, - argv)); + SHOW_DISPLAY_OVERLAY, + use_json(argc, argv)); } DEFUN(show_ip_bgp_evpn_rd_overlay, @@ -930,16 +904,16 @@ DEFUN(show_ip_bgp_evpn_rd_overlay, int ret; struct prefix_rd prd; - argv_find (argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community); + argv_find(argv, argc, "ASN:nn_or_IP-address:nn", &idx_ext_community); ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd); if (!ret) { - vty_out (vty, "%% Malformed Route Distinguisher\n"); + vty_out(vty, "%% Malformed Route Distinguisher\n"); return CMD_WARNING; } return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL, - SHOW_DISPLAY_OVERLAY, use_json(argc, - argv)); + SHOW_DISPLAY_OVERLAY, + use_json(argc, argv)); } /* For testing purpose, static route of MPLS-VPN. */ @@ -973,14 +947,13 @@ DEFUN(evpnrt5_network, int idx_ethtag = 5; int idx_routermac = 13; int idx_rmap = 15; - return bgp_static_set_safi(AFI_L2VPN, SAFI_EVPN, vty, - argv[idx_ipv4_prefixlen]->arg, - argv[idx_ext_community]->arg, - argv[idx_word]->arg, - argv[idx_rmap] ? argv[idx_gwip]->arg : NULL, - BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg, - argv[idx_gwip]->arg, argv[idx_ethtag]->arg, - argv[idx_routermac]->arg); + return bgp_static_set_safi( + AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg, + argv[idx_ext_community]->arg, argv[idx_word]->arg, + argv[idx_rmap] ? argv[idx_gwip]->arg : NULL, + BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg, + argv[idx_gwip]->arg, argv[idx_ethtag]->arg, + argv[idx_routermac]->arg); } /* For testing purpose, static route of MPLS-VPN. */ @@ -1007,147 +980,135 @@ DEFUN(no_evpnrt5_network, int idx_ethtag = 6; int idx_esi = 10; int idx_gwip = 12; - return bgp_static_unset_safi(AFI_L2VPN, SAFI_EVPN, vty, - argv[idx_ipv4_prefixlen]->arg, - argv[idx_ext_community]->arg, - argv[idx_label]->arg, BGP_EVPN_IP_PREFIX_ROUTE, - argv[idx_esi]->arg, argv[idx_gwip]->arg, - argv[idx_ethtag]->arg); + return bgp_static_unset_safi( + AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg, + argv[idx_ext_community]->arg, argv[idx_label]->arg, + BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg, + argv[idx_gwip]->arg, argv[idx_ethtag]->arg); } #if defined(HAVE_CUMULUS) -static void -evpn_rt_delete_auto (struct bgp *bgp, struct bgpevpn *vpn, struct list *rtl) +static void evpn_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn, + struct list *rtl) { - struct listnode *node, *nnode, *node_to_del; - struct ecommunity *ecom, *ecom_auto; - struct ecommunity_val eval; + struct listnode *node, *nnode, *node_to_del; + struct ecommunity *ecom, *ecom_auto; + struct ecommunity_val eval; - encode_route_target_as ((bgp->as & 0xFFFF), vpn->vni, &eval); + encode_route_target_as((bgp->as & 0xFFFF), vpn->vni, &eval); - ecom_auto = ecommunity_new (); - ecommunity_add_val (ecom_auto, &eval); - node_to_del = NULL; + ecom_auto = ecommunity_new(); + ecommunity_add_val(ecom_auto, &eval); + node_to_del = NULL; - for (ALL_LIST_ELEMENTS (rtl, node, nnode, ecom)) - { - if (ecommunity_match (ecom, ecom_auto)) - { - ecommunity_free (&ecom); - node_to_del = node; - } - } + for (ALL_LIST_ELEMENTS(rtl, node, nnode, ecom)) { + if (ecommunity_match(ecom, ecom_auto)) { + ecommunity_free(&ecom); + node_to_del = node; + } + } - if (node_to_del) - list_delete_node(rtl, node_to_del); + if (node_to_del) + list_delete_node(rtl, node_to_del); - ecommunity_free(&ecom_auto); + ecommunity_free(&ecom_auto); } -static void -evpn_import_rt_delete_auto (struct bgp *bgp, struct bgpevpn *vpn) +static void evpn_import_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn) { - evpn_rt_delete_auto (bgp, vpn, vpn->import_rtl); + evpn_rt_delete_auto(bgp, vpn, vpn->import_rtl); } -static void -evpn_export_rt_delete_auto (struct bgp *bgp, struct bgpevpn *vpn) +static void evpn_export_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn) { - evpn_rt_delete_auto (bgp, vpn, vpn->export_rtl); + evpn_rt_delete_auto(bgp, vpn, vpn->export_rtl); } /* * Configure the Import RTs for a VNI (vty handler). Caller expected to * check that this is a change. */ -static void -evpn_configure_import_rt (struct bgp *bgp, struct bgpevpn *vpn, - struct ecommunity *ecomadd) +static void evpn_configure_import_rt(struct bgp *bgp, struct bgpevpn *vpn, + struct ecommunity *ecomadd) { - /* If the VNI is "live", we need to uninstall routes using the current - * import RT(s) first before we update the import RT, and subsequently - * install routes. - */ - if (is_vni_live (vpn)) - bgp_evpn_uninstall_routes (bgp, vpn); + /* If the VNI is "live", we need to uninstall routes using the current + * import RT(s) first before we update the import RT, and subsequently + * install routes. + */ + if (is_vni_live(vpn)) + bgp_evpn_uninstall_routes(bgp, vpn); - /* Cleanup the RT to VNI mapping and get rid of existing import RT. */ - bgp_evpn_unmap_vni_from_its_rts (bgp, vpn); + /* Cleanup the RT to VNI mapping and get rid of existing import RT. */ + bgp_evpn_unmap_vni_from_its_rts(bgp, vpn); - /* If the auto route-target is in use we must remove it */ - evpn_import_rt_delete_auto(bgp, vpn); + /* If the auto route-target is in use we must remove it */ + evpn_import_rt_delete_auto(bgp, vpn); - /* Add new RT and rebuild the RT to VNI mapping */ - listnode_add_sort (vpn->import_rtl, ecomadd); + /* Add new RT and rebuild the RT to VNI mapping */ + listnode_add_sort(vpn->import_rtl, ecomadd); - SET_FLAG (vpn->flags, VNI_FLAG_IMPRT_CFGD); - bgp_evpn_map_vni_to_its_rts (bgp, vpn); + SET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD); + bgp_evpn_map_vni_to_its_rts(bgp, vpn); - /* Install routes that match new import RT */ - if (is_vni_live (vpn)) - bgp_evpn_install_routes (bgp, vpn); + /* Install routes that match new import RT */ + if (is_vni_live(vpn)) + bgp_evpn_install_routes(bgp, vpn); } /* * Unconfigure Import RT(s) for a VNI (vty handler). */ -static void -evpn_unconfigure_import_rt (struct bgp *bgp, struct bgpevpn *vpn, - struct ecommunity *ecomdel) -{ - struct listnode *node, *nnode, *node_to_del; - struct ecommunity *ecom; - - /* Along the lines of "configure" except we have to reset to the - * automatic value. - */ - if (is_vni_live (vpn)) - bgp_evpn_uninstall_routes (bgp, vpn); - - /* Cleanup the RT to VNI mapping and get rid of existing import RT. */ - bgp_evpn_unmap_vni_from_its_rts (bgp, vpn); - - /* Delete all import RTs */ - if (ecomdel == NULL) - { - for (ALL_LIST_ELEMENTS (vpn->import_rtl, node, nnode, ecom)) - ecommunity_free (&ecom); - - list_delete_all_node(vpn->import_rtl); - } - - /* Delete a specific import RT */ - else - { - node_to_del = NULL; - - for (ALL_LIST_ELEMENTS (vpn->import_rtl, node, nnode, ecom)) - { - if (ecommunity_match (ecom, ecomdel)) - { - ecommunity_free (&ecom); - node_to_del = node; - break; - } - } - - if (node_to_del) - list_delete_node(vpn->import_rtl, node_to_del); - } - - /* Reset to auto RT - this also rebuilds the RT to VNI mapping */ - if (list_isempty(vpn->import_rtl)) - { - UNSET_FLAG (vpn->flags, VNI_FLAG_IMPRT_CFGD); - bgp_evpn_derive_auto_rt_import (bgp, vpn); - } - /* Rebuild the RT to VNI mapping */ - else - bgp_evpn_map_vni_to_its_rts (bgp, vpn); - - /* Install routes that match new import RT */ - if (is_vni_live (vpn)) - bgp_evpn_install_routes (bgp, vpn); +static void evpn_unconfigure_import_rt(struct bgp *bgp, struct bgpevpn *vpn, + struct ecommunity *ecomdel) +{ + struct listnode *node, *nnode, *node_to_del; + struct ecommunity *ecom; + + /* Along the lines of "configure" except we have to reset to the + * automatic value. + */ + if (is_vni_live(vpn)) + bgp_evpn_uninstall_routes(bgp, vpn); + + /* Cleanup the RT to VNI mapping and get rid of existing import RT. */ + bgp_evpn_unmap_vni_from_its_rts(bgp, vpn); + + /* Delete all import RTs */ + if (ecomdel == NULL) { + for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) + ecommunity_free(&ecom); + + list_delete_all_node(vpn->import_rtl); + } + + /* Delete a specific import RT */ + else { + node_to_del = NULL; + + for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) { + if (ecommunity_match(ecom, ecomdel)) { + ecommunity_free(&ecom); + node_to_del = node; + break; + } + } + + if (node_to_del) + list_delete_node(vpn->import_rtl, node_to_del); + } + + /* Reset to auto RT - this also rebuilds the RT to VNI mapping */ + if (list_isempty(vpn->import_rtl)) { + UNSET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD); + bgp_evpn_derive_auto_rt_import(bgp, vpn); + } + /* Rebuild the RT to VNI mapping */ + else + bgp_evpn_map_vni_to_its_rts(bgp, vpn); + + /* Install routes that match new import RT */ + if (is_vni_live(vpn)) + bgp_evpn_install_routes(bgp, vpn); } /* @@ -1156,137 +1117,126 @@ evpn_unconfigure_import_rt (struct bgp *bgp, struct bgpevpn *vpn, * allowed for a VNI and any change to configuration is implemented as * a "replace" (similar to other configuration). */ -static void -evpn_configure_export_rt (struct bgp *bgp, struct bgpevpn *vpn, - struct ecommunity *ecomadd) +static void evpn_configure_export_rt(struct bgp *bgp, struct bgpevpn *vpn, + struct ecommunity *ecomadd) { - /* If the auto route-target is in use we must remove it */ - evpn_export_rt_delete_auto (bgp, vpn); + /* If the auto route-target is in use we must remove it */ + evpn_export_rt_delete_auto(bgp, vpn); - listnode_add_sort (vpn->export_rtl, ecomadd); - SET_FLAG (vpn->flags, VNI_FLAG_EXPRT_CFGD); + listnode_add_sort(vpn->export_rtl, ecomadd); + SET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD); - if (is_vni_live (vpn)) - bgp_evpn_handle_export_rt_change (bgp, vpn); + if (is_vni_live(vpn)) + bgp_evpn_handle_export_rt_change(bgp, vpn); } /* * Unconfigure the Export RT for a VNI (vty handler) */ -static void -evpn_unconfigure_export_rt (struct bgp *bgp, struct bgpevpn *vpn, - struct ecommunity *ecomdel) -{ - struct listnode *node, *nnode, *node_to_del; - struct ecommunity *ecom; - - /* Delete all export RTs */ - if (ecomdel == NULL) - { - /* Reset to default and process all routes. */ - for (ALL_LIST_ELEMENTS (vpn->export_rtl, node, nnode, ecom)) - ecommunity_free (&ecom); - - list_delete_all_node(vpn->export_rtl); - } - - /* Delete a specific export RT */ - else - { - node_to_del = NULL; - - for (ALL_LIST_ELEMENTS (vpn->export_rtl, node, nnode, ecom)) - { - if (ecommunity_match (ecom, ecomdel)) - { - ecommunity_free (&ecom); - node_to_del = node; - break; - } - } - - if (node_to_del) - list_delete_node(vpn->export_rtl, node_to_del); - } - - if (list_isempty(vpn->export_rtl)) - { - UNSET_FLAG (vpn->flags, VNI_FLAG_EXPRT_CFGD); - bgp_evpn_derive_auto_rt_export (bgp, vpn); - } - - if (is_vni_live (vpn)) - bgp_evpn_handle_export_rt_change (bgp, vpn); +static void evpn_unconfigure_export_rt(struct bgp *bgp, struct bgpevpn *vpn, + struct ecommunity *ecomdel) +{ + struct listnode *node, *nnode, *node_to_del; + struct ecommunity *ecom; + + /* Delete all export RTs */ + if (ecomdel == NULL) { + /* Reset to default and process all routes. */ + for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) + ecommunity_free(&ecom); + + list_delete_all_node(vpn->export_rtl); + } + + /* Delete a specific export RT */ + else { + node_to_del = NULL; + + for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) { + if (ecommunity_match(ecom, ecomdel)) { + ecommunity_free(&ecom); + node_to_del = node; + break; + } + } + + if (node_to_del) + list_delete_node(vpn->export_rtl, node_to_del); + } + + if (list_isempty(vpn->export_rtl)) { + UNSET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD); + bgp_evpn_derive_auto_rt_export(bgp, vpn); + } + + if (is_vni_live(vpn)) + bgp_evpn_handle_export_rt_change(bgp, vpn); } /* * Configure RD for a VNI (vty handler) */ -static void -evpn_configure_rd (struct bgp *bgp, struct bgpevpn *vpn, - struct prefix_rd *rd) +static void evpn_configure_rd(struct bgp *bgp, struct bgpevpn *vpn, + struct prefix_rd *rd) { - /* If the VNI is "live", we need to delete and withdraw this VNI's - * local routes with the prior RD first. Then, after updating RD, - * need to re-advertise. - */ - if (is_vni_live (vpn)) - bgp_evpn_handle_rd_change (bgp, vpn, 1); + /* If the VNI is "live", we need to delete and withdraw this VNI's + * local routes with the prior RD first. Then, after updating RD, + * need to re-advertise. + */ + if (is_vni_live(vpn)) + bgp_evpn_handle_rd_change(bgp, vpn, 1); - /* update RD */ - memcpy(&vpn->prd, rd, sizeof (struct prefix_rd)); - SET_FLAG (vpn->flags, VNI_FLAG_RD_CFGD); + /* update RD */ + memcpy(&vpn->prd, rd, sizeof(struct prefix_rd)); + SET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD); - if (is_vni_live (vpn)) - bgp_evpn_handle_rd_change (bgp, vpn, 0); + if (is_vni_live(vpn)) + bgp_evpn_handle_rd_change(bgp, vpn, 0); } /* * Unconfigure RD for a VNI (vty handler) */ -static void -evpn_unconfigure_rd (struct bgp *bgp, struct bgpevpn *vpn) +static void evpn_unconfigure_rd(struct bgp *bgp, struct bgpevpn *vpn) { - /* If the VNI is "live", we need to delete and withdraw this VNI's - * local routes with the prior RD first. Then, after resetting RD - * to automatic value, need to re-advertise. - */ - if (is_vni_live (vpn)) - bgp_evpn_handle_rd_change (bgp, vpn, 1); + /* If the VNI is "live", we need to delete and withdraw this VNI's + * local routes with the prior RD first. Then, after resetting RD + * to automatic value, need to re-advertise. + */ + if (is_vni_live(vpn)) + bgp_evpn_handle_rd_change(bgp, vpn, 1); - /* reset RD to default */ - bgp_evpn_derive_auto_rd (bgp, vpn); + /* reset RD to default */ + bgp_evpn_derive_auto_rd(bgp, vpn); - if (is_vni_live (vpn)) - bgp_evpn_handle_rd_change (bgp, vpn, 0); + if (is_vni_live(vpn)) + bgp_evpn_handle_rd_change(bgp, vpn, 0); } /* * Create VNI, if not already present (VTY handler). Mark as configured. */ -static struct bgpevpn * -evpn_create_update_vni (struct bgp *bgp, vni_t vni) +static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni) { - struct bgpevpn *vpn; + struct bgpevpn *vpn; - if (!bgp->vnihash) - return NULL; + if (!bgp->vnihash) + return NULL; - vpn = bgp_evpn_lookup_vni (bgp, vni); - if (!vpn) - { - vpn = bgp_evpn_new (bgp, vni, bgp->router_id); - if (!vpn) - { - zlog_err ("%u: Failed to allocate VNI entry for VNI %u - at Config", - bgp->vrf_id, vni); - return NULL; - } - } + vpn = bgp_evpn_lookup_vni(bgp, vni); + if (!vpn) { + vpn = bgp_evpn_new(bgp, vni, bgp->router_id); + if (!vpn) { + zlog_err( + "%u: Failed to allocate VNI entry for VNI %u - at Config", + bgp->vrf_id, vni); + return NULL; + } + } - /* Mark as configured. */ - SET_FLAG (vpn->flags, VNI_FLAG_CFGD); - return vpn; + /* Mark as configured. */ + SET_FLAG(vpn->flags, VNI_FLAG_CFGD); + return vpn; } /* @@ -1296,166 +1246,154 @@ evpn_create_update_vni (struct bgp *bgp, vni_t vni) * appropriate action) and the VNI marked as unconfigured; the * VNI will continue to exist, purely as a "learnt" entity. */ -static int -evpn_delete_vni (struct bgp *bgp, struct bgpevpn *vpn) +static int evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn) { - assert (bgp->vnihash); + assert(bgp->vnihash); - if (!is_vni_live (vpn)) - { - bgp_evpn_free (bgp, vpn); - return 0; - } + if (!is_vni_live(vpn)) { + bgp_evpn_free(bgp, vpn); + return 0; + } - /* We need to take the unconfigure action for each parameter of this VNI - * that is configured. Some optimization is possible, but not worth the - * additional code for an operation that should be pretty rare. - */ - UNSET_FLAG (vpn->flags, VNI_FLAG_CFGD); + /* We need to take the unconfigure action for each parameter of this VNI + * that is configured. Some optimization is possible, but not worth the + * additional code for an operation that should be pretty rare. + */ + UNSET_FLAG(vpn->flags, VNI_FLAG_CFGD); - /* First, deal with the export side - RD and export RT changes. */ - if (is_rd_configured (vpn)) - evpn_unconfigure_rd (bgp, vpn); - if (is_export_rt_configured (vpn)) - evpn_unconfigure_export_rt (bgp, vpn, NULL); + /* First, deal with the export side - RD and export RT changes. */ + if (is_rd_configured(vpn)) + evpn_unconfigure_rd(bgp, vpn); + if (is_export_rt_configured(vpn)) + evpn_unconfigure_export_rt(bgp, vpn, NULL); - /* Next, deal with the import side. */ - if (is_import_rt_configured (vpn)) - evpn_unconfigure_import_rt (bgp, vpn, NULL); + /* Next, deal with the import side. */ + if (is_import_rt_configured(vpn)) + evpn_unconfigure_import_rt(bgp, vpn, NULL); - return 0; + return 0; } /* * Display import RT mapping to VNIs (vty handler) */ -static void -evpn_show_import_rts (struct vty *vty, struct bgp *bgp) +static void evpn_show_import_rts(struct vty *vty, struct bgp *bgp) { - hash_iterate (bgp->import_rt_hash, - (void (*) (struct hash_backet *, void *)) - show_import_rt_entry, vty); + hash_iterate( + bgp->import_rt_hash, + (void (*)(struct hash_backet *, void *))show_import_rt_entry, + vty); } /* * Display EVPN routes for all VNIs - vty handler. */ -static void -evpn_show_routes_vni_all (struct vty *vty, struct bgp *bgp, struct in_addr vtep_ip) +static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp, + struct in_addr vtep_ip) { - u_int32_t num_vnis; - struct vni_walk_ctx wctx; + u_int32_t num_vnis; + struct vni_walk_ctx wctx; - num_vnis = hashcount(bgp->vnihash); - if (!num_vnis) - return; - memset (&wctx, 0, sizeof (struct vni_walk_ctx)); - wctx.bgp = bgp; - wctx.vty = vty; - wctx.vtep_ip = vtep_ip; - hash_iterate (bgp->vnihash, - (void (*) (struct hash_backet *, void *)) - show_vni_routes_hash, &wctx); + num_vnis = hashcount(bgp->vnihash); + if (!num_vnis) + return; + memset(&wctx, 0, sizeof(struct vni_walk_ctx)); + wctx.bgp = bgp; + wctx.vty = vty; + wctx.vtep_ip = vtep_ip; + hash_iterate(bgp->vnihash, (void (*)(struct hash_backet *, + void *))show_vni_routes_hash, + &wctx); } /* * Display EVPN routes for a VNI -- for specific type-3 route (vty handler). */ -static void -evpn_show_route_vni_multicast (struct vty *vty, struct bgp *bgp, - vni_t vni, struct in_addr orig_ip) -{ - struct bgpevpn *vpn; - struct prefix_evpn p; - struct bgp_node *rn; - struct bgp_info *ri; - u_int32_t path_cnt = 0; - afi_t afi; - safi_t safi; - - afi = AFI_L2VPN; - safi = SAFI_EVPN; - - /* Locate VNI. */ - vpn = bgp_evpn_lookup_vni (bgp, vni); - if (!vpn) - { - vty_out (vty, "VNI not found\n"); - return; - } - - /* See if route exists. */ - build_evpn_type3_prefix (&p, orig_ip); - rn = bgp_node_lookup (vpn->route_table, (struct prefix *)&p); - if (!rn || !rn->info) - { - vty_out (vty, "%% Network not in table\n"); - return; - } - - /* Prefix and num paths displayed once per prefix. */ - route_vty_out_detail_header (vty, bgp, rn, NULL, afi, safi, NULL); - - /* Display each path for this prefix. */ - for (ri = rn->info; ri; ri = ri->next) - { - route_vty_out_detail (vty, bgp, &rn->p, ri, afi, safi, NULL); - path_cnt++; - } - - vty_out (vty, "\nDisplayed %u paths for requested prefix\n", - path_cnt); +static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp, + vni_t vni, struct in_addr orig_ip) +{ + struct bgpevpn *vpn; + struct prefix_evpn p; + struct bgp_node *rn; + struct bgp_info *ri; + u_int32_t path_cnt = 0; + afi_t afi; + safi_t safi; + + afi = AFI_L2VPN; + safi = SAFI_EVPN; + + /* Locate VNI. */ + vpn = bgp_evpn_lookup_vni(bgp, vni); + if (!vpn) { + vty_out(vty, "VNI not found\n"); + return; + } + + /* See if route exists. */ + build_evpn_type3_prefix(&p, orig_ip); + rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p); + if (!rn || !rn->info) { + vty_out(vty, "%% Network not in table\n"); + return; + } + + /* Prefix and num paths displayed once per prefix. */ + route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, NULL); + + /* Display each path for this prefix. */ + for (ri = rn->info; ri; ri = ri->next) { + route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi, NULL); + path_cnt++; + } + + vty_out(vty, "\nDisplayed %u paths for requested prefix\n", path_cnt); } /* * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler). * By definition, only matching type-2 route will be displayed. */ -static void -evpn_show_route_vni_macip (struct vty *vty, struct bgp *bgp, - vni_t vni, struct ethaddr *mac, - struct ipaddr *ip) -{ - struct bgpevpn *vpn; - struct prefix_evpn p; - struct bgp_node *rn; - struct bgp_info *ri; - u_int32_t path_cnt = 0; - afi_t afi; - safi_t safi; - - afi = AFI_L2VPN; - safi = SAFI_EVPN; - - /* Locate VNI. */ - vpn = bgp_evpn_lookup_vni (bgp, vni); - if (!vpn) - { - vty_out (vty, "VNI not found\n"); - return; - } - - /* See if route exists. Look for both non-sticky and sticky. */ - build_evpn_type2_prefix (&p, mac, ip); - rn = bgp_node_lookup (vpn->route_table, (struct prefix *)&p); - if (!rn || !rn->info) - { - vty_out (vty, "%% Network not in table\n"); - return; - } - - /* Prefix and num paths displayed once per prefix. */ - route_vty_out_detail_header (vty, bgp, rn, NULL, afi, safi, NULL); - - /* Display each path for this prefix. */ - for (ri = rn->info; ri; ri = ri->next) - { - route_vty_out_detail (vty, bgp, &rn->p, ri, afi, safi, NULL); - path_cnt++; - } - - vty_out (vty, "\nDisplayed %u paths for requested prefix\n", - path_cnt); +static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp, + vni_t vni, struct ethaddr *mac, + struct ipaddr *ip) +{ + struct bgpevpn *vpn; + struct prefix_evpn p; + struct bgp_node *rn; + struct bgp_info *ri; + u_int32_t path_cnt = 0; + afi_t afi; + safi_t safi; + + afi = AFI_L2VPN; + safi = SAFI_EVPN; + + /* Locate VNI. */ + vpn = bgp_evpn_lookup_vni(bgp, vni); + if (!vpn) { + vty_out(vty, "VNI not found\n"); + return; + } + + /* See if route exists. Look for both non-sticky and sticky. */ + build_evpn_type2_prefix(&p, mac, ip); + rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p); + if (!rn || !rn->info) { + vty_out(vty, "%% Network not in table\n"); + return; + } + + /* Prefix and num paths displayed once per prefix. */ + route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, NULL); + + /* Display each path for this prefix. */ + for (ri = rn->info; ri; ri = ri->next) { + route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi, NULL); + path_cnt++; + } + + vty_out(vty, "\nDisplayed %u paths for requested prefix\n", path_cnt); } /* @@ -1463,22 +1401,20 @@ evpn_show_route_vni_macip (struct vty *vty, struct bgp *bgp, * If 'type' is non-zero, only routes matching that type are shown. * If the vtep_ip is non zero, only routes behind that vtep are shown */ -static void -evpn_show_routes_vni (struct vty *vty, struct bgp *bgp, - vni_t vni, int type, struct in_addr vtep_ip) +static void evpn_show_routes_vni(struct vty *vty, struct bgp *bgp, vni_t vni, + int type, struct in_addr vtep_ip) { - struct bgpevpn *vpn; + struct bgpevpn *vpn; - /* Locate VNI. */ - vpn = bgp_evpn_lookup_vni (bgp, vni); - if (!vpn) - { - vty_out (vty, "VNI not found\n"); - return; - } + /* Locate VNI. */ + vpn = bgp_evpn_lookup_vni(bgp, vni); + if (!vpn) { + vty_out(vty, "VNI not found\n"); + return; + } - /* Walk this VNI's route table and display appropriate routes. */ - show_vni_routes (bgp, vpn, type, vty, vtep_ip); + /* Walk this VNI's route table and display appropriate routes. */ + show_vni_routes(bgp, vpn, type, vty, vtep_ip); } /* @@ -1486,321 +1422,305 @@ evpn_show_routes_vni (struct vty *vty, struct bgp *bgp, * IP (vty handler). By definition, only matching type-2 route will be * displayed. */ -static void -evpn_show_route_rd_macip (struct vty *vty, struct bgp *bgp, - struct prefix_rd *prd, struct ethaddr *mac, - struct ipaddr *ip) -{ - struct prefix_evpn p; - struct bgp_node *rn; - struct bgp_info *ri; - afi_t afi; - safi_t safi; - u_int32_t path_cnt = 0; - - afi = AFI_L2VPN; - safi = SAFI_EVPN; - - /* See if route exists. Look for both non-sticky and sticky. */ - build_evpn_type2_prefix (&p, mac, ip); - rn = bgp_afi_node_lookup (bgp->rib[afi][safi], afi, safi, - (struct prefix *)&p, prd); - if (!rn || !rn->info) - { - vty_out (vty, "%% Network not in table\n"); - return; - } - - /* Prefix and num paths displayed once per prefix. */ - route_vty_out_detail_header (vty, bgp, rn, prd, afi, safi, NULL); - - /* Display each path for this prefix. */ - for (ri = rn->info; ri; ri = ri->next) - { - route_vty_out_detail (vty, bgp, &rn->p, ri, afi, safi, NULL); - path_cnt++; - } - - vty_out (vty, "\nDisplayed %u paths for requested prefix\n", - path_cnt); +static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp, + struct prefix_rd *prd, struct ethaddr *mac, + struct ipaddr *ip) +{ + struct prefix_evpn p; + struct bgp_node *rn; + struct bgp_info *ri; + afi_t afi; + safi_t safi; + u_int32_t path_cnt = 0; + + afi = AFI_L2VPN; + safi = SAFI_EVPN; + + /* See if route exists. Look for both non-sticky and sticky. */ + build_evpn_type2_prefix(&p, mac, ip); + rn = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi, + (struct prefix *)&p, prd); + if (!rn || !rn->info) { + vty_out(vty, "%% Network not in table\n"); + return; + } + + /* Prefix and num paths displayed once per prefix. */ + route_vty_out_detail_header(vty, bgp, rn, prd, afi, safi, NULL); + + /* Display each path for this prefix. */ + for (ri = rn->info; ri; ri = ri->next) { + route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi, NULL); + path_cnt++; + } + + vty_out(vty, "\nDisplayed %u paths for requested prefix\n", path_cnt); } /* * Display BGP EVPN routing table -- for specific RD (vty handler) * If 'type' is non-zero, only routes matching that type are shown. */ -static void -evpn_show_route_rd (struct vty *vty, struct bgp *bgp, - struct prefix_rd *prd, int type) -{ - struct bgp_node *rd_rn; - struct bgp_table *table; - struct bgp_node *rn; - struct bgp_info *ri; - int rd_header = 1; - afi_t afi; - safi_t safi; - u_int32_t prefix_cnt, path_cnt; - - afi = AFI_L2VPN; - safi = SAFI_EVPN; - prefix_cnt = path_cnt = 0; - - rd_rn = bgp_node_lookup (bgp->rib[afi][safi], (struct prefix *) prd); - if (!rd_rn) - return; - table = (struct bgp_table *)rd_rn->info; - if (table == NULL) - return; - - /* Display all prefixes with this RD. */ - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - { - struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; - - if (type && - evp->prefix.route_type != type) - continue; - - if (rn->info) - { - /* RD header and legend - once overall. */ - if (rd_header) - { - vty_out (vty, "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:" - "[MAC]\n"); - vty_out (vty, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:" - "[OrigIP]\n\n"); - rd_header = 0; - } - - /* Prefix and num paths displayed once per prefix. */ - route_vty_out_detail_header (vty, bgp, rn, prd, afi, safi, NULL); - - prefix_cnt++; - } - - /* Display each path for this prefix. */ - for (ri = rn->info; ri; ri = ri->next) - { - route_vty_out_detail (vty, bgp, &rn->p, ri, afi, safi, NULL); - path_cnt++; - } - } - - if (prefix_cnt == 0) - vty_out (vty, "No prefixes exist with this RD%s\n", - type ? " (of requested type)" : ""); - else - vty_out (vty, "\nDisplayed %u prefixes (%u paths) with this RD%s\n", - prefix_cnt, path_cnt, - type ? " (of requested type)" : ""); +static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp, + struct prefix_rd *prd, int type) +{ + struct bgp_node *rd_rn; + struct bgp_table *table; + struct bgp_node *rn; + struct bgp_info *ri; + int rd_header = 1; + afi_t afi; + safi_t safi; + u_int32_t prefix_cnt, path_cnt; + + afi = AFI_L2VPN; + safi = SAFI_EVPN; + prefix_cnt = path_cnt = 0; + + rd_rn = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)prd); + if (!rd_rn) + return; + table = (struct bgp_table *)rd_rn->info; + if (table == NULL) + return; + + /* Display all prefixes with this RD. */ + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { + struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; + + if (type && evp->prefix.route_type != type) + continue; + + if (rn->info) { + /* RD header and legend - once overall. */ + if (rd_header) { + vty_out(vty, + "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:" + "[MAC]\n"); + vty_out(vty, + "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:" + "[OrigIP]\n\n"); + rd_header = 0; + } + + /* Prefix and num paths displayed once per prefix. */ + route_vty_out_detail_header(vty, bgp, rn, prd, afi, + safi, NULL); + + prefix_cnt++; + } + + /* Display each path for this prefix. */ + for (ri = rn->info; ri; ri = ri->next) { + route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi, + NULL); + path_cnt++; + } + } + + if (prefix_cnt == 0) + vty_out(vty, "No prefixes exist with this RD%s\n", + type ? " (of requested type)" : ""); + else + vty_out(vty, + "\nDisplayed %u prefixes (%u paths) with this RD%s\n", + prefix_cnt, path_cnt, + type ? " (of requested type)" : ""); } /* * Display BGP EVPN routing table - all routes (vty handler). * If 'type' is non-zero, only routes matching that type are shown. */ -static void -evpn_show_all_routes (struct vty *vty, struct bgp *bgp, int type) -{ - struct bgp_node *rd_rn; - struct bgp_table *table; - struct bgp_node *rn; - struct bgp_info *ri; - int header = 1; - int rd_header; - afi_t afi; - safi_t safi; - u_int32_t prefix_cnt, path_cnt; - - afi = AFI_L2VPN; - safi = SAFI_EVPN; - prefix_cnt = path_cnt = 0; - - /* EVPN routing table is a 2-level table with the first level being - * the RD. - */ - for (rd_rn = bgp_table_top (bgp->rib[afi][safi]); rd_rn; - rd_rn = bgp_route_next (rd_rn)) - { - table = (struct bgp_table *)rd_rn->info; - if (table == NULL) - continue; - - rd_header = 1; - - /* Display all prefixes for an RD */ - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - { - struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; - - if (type && - evp->prefix.route_type != type) - continue; - - if (rn->info) - { - /* Overall header/legend displayed once. */ - if (header) - { - bgp_evpn_show_route_header (vty, bgp); - header = 0; - } - - /* RD header - per RD. */ - if (rd_header) - { - bgp_evpn_show_route_rd_header (vty, rd_rn); - rd_header = 0; - } - - prefix_cnt++; - } - - /* For EVPN, the prefix is displayed for each path (to fit in - * with code that already exists). - */ - for (ri = rn->info; ri; ri = ri->next) - { - path_cnt++; - route_vty_out (vty, &rn->p, ri, 0, SAFI_EVPN, NULL); - } - } - } - - if (prefix_cnt == 0) - vty_out (vty, "No EVPN prefixes %sexist\n", - type ? "(of requested type) " : ""); - else - vty_out (vty, "\nDisplayed %u prefixes (%u paths)%s\n", - prefix_cnt, path_cnt, - type ? " (of requested type)" : ""); +static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type) +{ + struct bgp_node *rd_rn; + struct bgp_table *table; + struct bgp_node *rn; + struct bgp_info *ri; + int header = 1; + int rd_header; + afi_t afi; + safi_t safi; + u_int32_t prefix_cnt, path_cnt; + + afi = AFI_L2VPN; + safi = SAFI_EVPN; + prefix_cnt = path_cnt = 0; + + /* EVPN routing table is a 2-level table with the first level being + * the RD. + */ + for (rd_rn = bgp_table_top(bgp->rib[afi][safi]); rd_rn; + rd_rn = bgp_route_next(rd_rn)) { + table = (struct bgp_table *)rd_rn->info; + if (table == NULL) + continue; + + rd_header = 1; + + /* Display all prefixes for an RD */ + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { + struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; + + if (type && evp->prefix.route_type != type) + continue; + + if (rn->info) { + /* Overall header/legend displayed once. */ + if (header) { + bgp_evpn_show_route_header(vty, bgp); + header = 0; + } + + /* RD header - per RD. */ + if (rd_header) { + bgp_evpn_show_route_rd_header(vty, + rd_rn); + rd_header = 0; + } + + prefix_cnt++; + } + + /* For EVPN, the prefix is displayed for each path (to + * fit in + * with code that already exists). + */ + for (ri = rn->info; ri; ri = ri->next) { + path_cnt++; + route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN, + NULL); + } + } + } + + if (prefix_cnt == 0) + vty_out(vty, "No EVPN prefixes %sexist\n", + type ? "(of requested type) " : ""); + else + vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n", + prefix_cnt, path_cnt, + type ? " (of requested type)" : ""); } /* * Display specified VNI (vty handler) */ -static void -evpn_show_vni (struct vty *vty, struct bgp *bgp, vni_t vni) +static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni) { - struct bgpevpn *vpn; + struct bgpevpn *vpn; - vpn = bgp_evpn_lookup_vni (bgp, vni); - if (!vpn) - { - vty_out (vty, "VNI not found\n"); - return; - } + vpn = bgp_evpn_lookup_vni(bgp, vni); + if (!vpn) { + vty_out(vty, "VNI not found\n"); + return; + } - display_vni (vty, vpn); + display_vni(vty, vpn); } /* * Display a VNI (upon user query). */ -static void -evpn_show_all_vnis (struct vty *vty, struct bgp *bgp) +static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp) { - u_int32_t num_vnis; + u_int32_t num_vnis; - num_vnis = hashcount(bgp->vnihash); - if (!num_vnis) - return; - vty_out(vty, "Number of VNIs: %u\n", num_vnis); - vty_out(vty, "Flags: * - Kernel \n"); - vty_out(vty, " %-10s %-15s %-21s %-25s %-25s\n", - "VNI", "Orig IP", "RD", "Import RT", "Export RT"); - hash_iterate (bgp->vnihash, - (void (*) (struct hash_backet *, void *)) - show_vni_entry, vty); + num_vnis = hashcount(bgp->vnihash); + if (!num_vnis) + return; + vty_out(vty, "Number of VNIs: %u\n", num_vnis); + vty_out(vty, "Flags: * - Kernel \n"); + vty_out(vty, " %-10s %-15s %-21s %-25s %-25s\n", "VNI", "Orig IP", + "RD", "Import RT", "Export RT"); + hash_iterate(bgp->vnihash, + (void (*)(struct hash_backet *, void *))show_vni_entry, + vty); } /* * EVPN (VNI advertisement) enabled. Register with zebra. */ -static void -evpn_set_advertise_all_vni (struct bgp *bgp) +static void evpn_set_advertise_all_vni(struct bgp *bgp) { - bgp->advertise_all_vni = 1; - bgp_zebra_advertise_all_vni (bgp, bgp->advertise_all_vni); + bgp->advertise_all_vni = 1; + bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni); } /* * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI * cache, EVPN routes (delete and withdraw from peers). */ -static void -evpn_unset_advertise_all_vni (struct bgp *bgp) +static void evpn_unset_advertise_all_vni(struct bgp *bgp) { - bgp->advertise_all_vni = 0; - bgp_zebra_advertise_all_vni (bgp, bgp->advertise_all_vni); - bgp_evpn_cleanup_on_disable (bgp); + bgp->advertise_all_vni = 0; + bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni); + bgp_evpn_cleanup_on_disable(bgp); } #endif /* HAVE_CUMULUS */ -static void -write_vni_config (struct vty *vty, struct bgpevpn *vpn, int *write) -{ - char buf1[INET6_ADDRSTRLEN]; - afi_t afi = AFI_L2VPN; - safi_t safi = SAFI_EVPN; - char *ecom_str; - struct listnode *node, *nnode; - struct ecommunity *ecom; - - if (is_vni_configured (vpn)) - { - bgp_config_write_family_header (vty, afi, safi, write); - vty_out (vty, " vni %d\n", vpn->vni); - if (is_rd_configured (vpn)) - vty_out (vty, " rd %s\n", - prefix_rd2str (&vpn->prd, buf1, RD_ADDRSTRLEN)); - - if (is_import_rt_configured (vpn)) - { - for (ALL_LIST_ELEMENTS (vpn->import_rtl, node, nnode, ecom)) - { - ecom_str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); - vty_out (vty, " route-target import %s\n", ecom_str); - XFREE (MTYPE_ECOMMUNITY_STR, ecom_str); - } - } - - if (is_export_rt_configured (vpn)) - { - for (ALL_LIST_ELEMENTS (vpn->export_rtl, node, nnode, ecom)) - { - ecom_str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); - vty_out (vty, " route-target export %s\n", ecom_str); - XFREE (MTYPE_ECOMMUNITY_STR, ecom_str); - } - } - - vty_out (vty, " exit-vni\n"); - } -} - -static void -write_vni_config_for_entry (struct hash_backet *backet, - struct evpn_config_write *cfg) -{ - struct bgpevpn *vpn = (struct bgpevpn *) backet->data; - write_vni_config (cfg->vty, vpn, &cfg->write); -} - -#if defined (HAVE_CUMULUS) +static void write_vni_config(struct vty *vty, struct bgpevpn *vpn, int *write) +{ + char buf1[INET6_ADDRSTRLEN]; + afi_t afi = AFI_L2VPN; + safi_t safi = SAFI_EVPN; + char *ecom_str; + struct listnode *node, *nnode; + struct ecommunity *ecom; + + if (is_vni_configured(vpn)) { + bgp_config_write_family_header(vty, afi, safi, write); + vty_out(vty, " vni %d\n", vpn->vni); + if (is_rd_configured(vpn)) + vty_out(vty, " rd %s\n", + prefix_rd2str(&vpn->prd, buf1, RD_ADDRSTRLEN)); + + if (is_import_rt_configured(vpn)) { + for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, + ecom)) { + ecom_str = ecommunity_ecom2str( + ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); + vty_out(vty, " route-target import %s\n", + ecom_str); + XFREE(MTYPE_ECOMMUNITY_STR, ecom_str); + } + } + + if (is_export_rt_configured(vpn)) { + for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, + ecom)) { + ecom_str = ecommunity_ecom2str( + ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); + vty_out(vty, " route-target export %s\n", + ecom_str); + XFREE(MTYPE_ECOMMUNITY_STR, ecom_str); + } + } + + vty_out(vty, " exit-vni\n"); + } +} + +static void write_vni_config_for_entry(struct hash_backet *backet, + struct evpn_config_write *cfg) +{ + struct bgpevpn *vpn = (struct bgpevpn *)backet->data; + write_vni_config(cfg->vty, vpn, &cfg->write); +} + +#if defined(HAVE_CUMULUS) DEFUN (bgp_evpn_advertise_all_vni, bgp_evpn_advertise_all_vni_cmd, "advertise-all-vni", "Advertise All local VNIs\n") { - struct bgp *bgp = VTY_GET_CONTEXT(bgp); + struct bgp *bgp = VTY_GET_CONTEXT(bgp); - if (!bgp) - return CMD_WARNING; - evpn_set_advertise_all_vni (bgp); - return CMD_SUCCESS; + if (!bgp) + return CMD_WARNING; + evpn_set_advertise_all_vni(bgp); + return CMD_SUCCESS; } DEFUN (no_bgp_evpn_advertise_all_vni, @@ -1809,12 +1729,12 @@ DEFUN (no_bgp_evpn_advertise_all_vni, NO_STR "Advertise All local VNIs\n") { - struct bgp *bgp = VTY_GET_CONTEXT(bgp); + struct bgp *bgp = VTY_GET_CONTEXT(bgp); - if (!bgp) - return CMD_WARNING; - evpn_unset_advertise_all_vni (bgp); - return CMD_SUCCESS; + if (!bgp) + return CMD_WARNING; + evpn_unset_advertise_all_vni(bgp); + return CMD_SUCCESS; } DEFUN (show_bgp_evpn_vni, @@ -1825,17 +1745,17 @@ DEFUN (show_bgp_evpn_vni, EVPN_HELP_STR "Show VNI\n") { - struct bgp *bgp; + struct bgp *bgp; - bgp = bgp_get_default(); - if (!bgp) - return CMD_WARNING; + bgp = bgp_get_default(); + if (!bgp) + return CMD_WARNING; - vty_out (vty, "Advertise All VNI flag: %s\n", - bgp->advertise_all_vni? "Enabled" : "Disabled"); + vty_out(vty, "Advertise All VNI flag: %s\n", + bgp->advertise_all_vni ? "Enabled" : "Disabled"); - evpn_show_all_vnis (vty, bgp); - return CMD_SUCCESS; + evpn_show_all_vnis(vty, bgp); + return CMD_SUCCESS; } DEFUN (show_bgp_evpn_vni_num, @@ -1847,17 +1767,17 @@ DEFUN (show_bgp_evpn_vni_num, "Show VNI\n" "VNI number\n") { - vni_t vni; - struct bgp *bgp; + vni_t vni; + struct bgp *bgp; - bgp = bgp_get_default(); - if (!bgp) - return CMD_WARNING; + bgp = bgp_get_default(); + if (!bgp) + return CMD_WARNING; - vni = strtoul(argv[4]->arg, NULL, 10); + vni = strtoul(argv[4]->arg, NULL, 10); - evpn_show_vni (vty, bgp, vni); - return CMD_SUCCESS; + evpn_show_vni(vty, bgp, vni); + return CMD_SUCCESS; } /* `show bgp evpn summary' commands. */ @@ -1870,8 +1790,8 @@ DEFUN (show_bgp_evpn_summary, "Summary of BGP neighbor status\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - return bgp_show_summary_vty (vty, NULL, AFI_L2VPN, SAFI_EVPN, uj); + u_char uj = use_json(argc, argv); + return bgp_show_summary_vty(vty, NULL, AFI_L2VPN, SAFI_EVPN, uj); } /* Show bgp evpn route */ @@ -1886,25 +1806,24 @@ DEFUN (show_bgp_evpn_route, "MAC-IP (Type-2) route\n" "Multicast (Type-3) route\n") { - struct bgp *bgp; - int type = 0; + struct bgp *bgp; + int type = 0; - bgp = bgp_get_default(); - if (!bgp) - return CMD_WARNING; + bgp = bgp_get_default(); + if (!bgp) + return CMD_WARNING; - if (argc == 6) - { - if (strncmp (argv[5]->arg, "ma", 2) == 0) - type = BGP_EVPN_MAC_IP_ROUTE; - else if (strncmp (argv[5]->arg, "mu", 2) == 0) - type = BGP_EVPN_IMET_ROUTE; - else - return CMD_WARNING; - } + if (argc == 6) { + if (strncmp(argv[5]->arg, "ma", 2) == 0) + type = BGP_EVPN_MAC_IP_ROUTE; + else if (strncmp(argv[5]->arg, "mu", 2) == 0) + type = BGP_EVPN_IMET_ROUTE; + else + return CMD_WARNING; + } - evpn_show_all_routes (vty, bgp, type); - return CMD_SUCCESS; + evpn_show_all_routes(vty, bgp, type); + return CMD_SUCCESS; } DEFUN (show_bgp_evpn_route_rd, @@ -1920,34 +1839,32 @@ DEFUN (show_bgp_evpn_route_rd, "MAC-IP (Type-2) route\n" "Multicast (Type-3) route\n") { - struct bgp *bgp; - int ret; - struct prefix_rd prd; - int type = 0; + struct bgp *bgp; + int ret; + struct prefix_rd prd; + int type = 0; - bgp = bgp_get_default(); - if (!bgp) - return CMD_WARNING; + bgp = bgp_get_default(); + if (!bgp) + return CMD_WARNING; - ret = str2prefix_rd (argv[5]->arg, &prd); - if (! ret) - { - vty_out (vty, "%% Malformed Route Distinguisher\n"); - return CMD_WARNING; - } + ret = str2prefix_rd(argv[5]->arg, &prd); + if (!ret) { + vty_out(vty, "%% Malformed Route Distinguisher\n"); + return CMD_WARNING; + } - if (argc == 8) - { - if (strncmp (argv[7]->arg, "ma", 2) == 0) - type = BGP_EVPN_MAC_IP_ROUTE; - else if (strncmp (argv[7]->arg, "mu", 2) == 0) - type = BGP_EVPN_IMET_ROUTE; - else - return CMD_WARNING; - } + if (argc == 8) { + if (strncmp(argv[7]->arg, "ma", 2) == 0) + type = BGP_EVPN_MAC_IP_ROUTE; + else if (strncmp(argv[7]->arg, "mu", 2) == 0) + type = BGP_EVPN_IMET_ROUTE; + else + return CMD_WARNING; + } - evpn_show_route_rd (vty, bgp, &prd, type); - return CMD_SUCCESS; + evpn_show_route_rd(vty, bgp, &prd, type); + return CMD_SUCCESS; } DEFUN (show_bgp_evpn_route_rd_macip, @@ -1964,39 +1881,35 @@ DEFUN (show_bgp_evpn_route_rd_macip, "IP\n" "IP address (IPv4 or IPv6)\n") { - struct bgp *bgp; - int ret; - struct prefix_rd prd; - struct ethaddr mac; - struct ipaddr ip; - - bgp = bgp_get_default(); - if (!bgp) - return CMD_WARNING; - - ret = str2prefix_rd (argv[5]->arg, &prd); - if (! ret) - { - vty_out (vty, "%% Malformed Route Distinguisher\n"); - return CMD_WARNING; - } - if (!prefix_str2mac (argv[7]->arg, &mac)) - { - vty_out (vty, "%% Malformed MAC address\n"); - return CMD_WARNING; - } - memset (&ip, 0, sizeof (ip)); - if (argc == 10 && argv[9]->arg != NULL) - { - if (str2ipaddr (argv[9]->arg, &ip) != 0) - { - vty_out (vty, "%% Malformed IP address\n"); - return CMD_WARNING; - } - } - - evpn_show_route_rd_macip (vty, bgp, &prd, &mac, &ip); - return CMD_SUCCESS; + struct bgp *bgp; + int ret; + struct prefix_rd prd; + struct ethaddr mac; + struct ipaddr ip; + + bgp = bgp_get_default(); + if (!bgp) + return CMD_WARNING; + + ret = str2prefix_rd(argv[5]->arg, &prd); + if (!ret) { + vty_out(vty, "%% Malformed Route Distinguisher\n"); + return CMD_WARNING; + } + if (!prefix_str2mac(argv[7]->arg, &mac)) { + vty_out(vty, "%% Malformed MAC address\n"); + return CMD_WARNING; + } + memset(&ip, 0, sizeof(ip)); + if (argc == 10 && argv[9]->arg != NULL) { + if (str2ipaddr(argv[9]->arg, &ip) != 0) { + vty_out(vty, "%% Malformed IP address\n"); + return CMD_WARNING; + } + } + + evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip); + return CMD_SUCCESS; } DEFUN (show_bgp_evpn_route_vni, @@ -2014,44 +1927,38 @@ DEFUN (show_bgp_evpn_route_vni, "Remote VTEP\n" "Remote VTEP IP address\n") { - vni_t vni; - struct bgp *bgp; - struct in_addr vtep_ip; - int type = 0; - - bgp = bgp_get_default(); - if (!bgp) - return CMD_WARNING; - - vtep_ip.s_addr = 0; - - vni = strtoul(argv[5]->arg, NULL, 10); - - if (argc == 8 && argv[6]->arg) - { - if (strncmp (argv[6]->arg, "type", 4) == 0) - { - if (strncmp (argv[7]->arg, "ma", 2) == 0) - type = BGP_EVPN_MAC_IP_ROUTE; - else if (strncmp (argv[7]->arg, "mu", 2) == 0) - type = BGP_EVPN_IMET_ROUTE; - else - return CMD_WARNING; - } - else if (strncmp (argv[6]->arg, "vtep", 4) == 0) - { - if (!inet_aton (argv[7]->arg, &vtep_ip)) - { - vty_out (vty, "%% Malformed VTEP IP address\n"); - return CMD_WARNING; - } - } - else - return CMD_WARNING; - } - - evpn_show_routes_vni (vty, bgp, vni, type, vtep_ip); - return CMD_SUCCESS; + vni_t vni; + struct bgp *bgp; + struct in_addr vtep_ip; + int type = 0; + + bgp = bgp_get_default(); + if (!bgp) + return CMD_WARNING; + + vtep_ip.s_addr = 0; + + vni = strtoul(argv[5]->arg, NULL, 10); + + if (argc == 8 && argv[6]->arg) { + if (strncmp(argv[6]->arg, "type", 4) == 0) { + if (strncmp(argv[7]->arg, "ma", 2) == 0) + type = BGP_EVPN_MAC_IP_ROUTE; + else if (strncmp(argv[7]->arg, "mu", 2) == 0) + type = BGP_EVPN_IMET_ROUTE; + else + return CMD_WARNING; + } else if (strncmp(argv[6]->arg, "vtep", 4) == 0) { + if (!inet_aton(argv[7]->arg, &vtep_ip)) { + vty_out(vty, "%% Malformed VTEP IP address\n"); + return CMD_WARNING; + } + } else + return CMD_WARNING; + } + + evpn_show_routes_vni(vty, bgp, vni, type, vtep_ip); + return CMD_SUCCESS; } DEFUN (show_bgp_evpn_route_vni_macip, @@ -2068,33 +1975,30 @@ DEFUN (show_bgp_evpn_route_vni_macip, "IP\n" "IP address (IPv4 or IPv6)\n") { - vni_t vni; - struct bgp *bgp; - struct ethaddr mac; - struct ipaddr ip; - - bgp = bgp_get_default(); - if (!bgp) - return CMD_WARNING; - - vni = strtoul(argv[5]->arg, NULL, 10); - if (!prefix_str2mac (argv[7]->arg, &mac)) - { - vty_out (vty, "%% Malformed MAC address\n"); - return CMD_WARNING; - } - memset (&ip, 0, sizeof (ip)); - if (argc == 10 && argv[9]->arg != NULL) - { - if (str2ipaddr (argv[9]->arg, &ip) != 0) - { - vty_out (vty, "%% Malformed IP address\n"); - return CMD_WARNING; - } - } - - evpn_show_route_vni_macip (vty, bgp, vni, &mac, &ip); - return CMD_SUCCESS; + vni_t vni; + struct bgp *bgp; + struct ethaddr mac; + struct ipaddr ip; + + bgp = bgp_get_default(); + if (!bgp) + return CMD_WARNING; + + vni = strtoul(argv[5]->arg, NULL, 10); + if (!prefix_str2mac(argv[7]->arg, &mac)) { + vty_out(vty, "%% Malformed MAC address\n"); + return CMD_WARNING; + } + memset(&ip, 0, sizeof(ip)); + if (argc == 10 && argv[9]->arg != NULL) { + if (str2ipaddr(argv[9]->arg, &ip) != 0) { + vty_out(vty, "%% Malformed IP address\n"); + return CMD_WARNING; + } + } + + evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip); + return CMD_SUCCESS; } DEFUN (show_bgp_evpn_route_vni_multicast, @@ -2109,25 +2013,24 @@ DEFUN (show_bgp_evpn_route_vni_multicast, "Multicast (Type-3) route\n" "Originating Router IP address\n") { - vni_t vni; - struct bgp *bgp; - int ret; - struct in_addr orig_ip; + vni_t vni; + struct bgp *bgp; + int ret; + struct in_addr orig_ip; - bgp = bgp_get_default(); - if (!bgp) - return CMD_WARNING; + bgp = bgp_get_default(); + if (!bgp) + return CMD_WARNING; - vni = strtoul(argv[5]->arg, NULL, 10); - ret = inet_aton (argv[7]->arg, &orig_ip); - if (!ret) - { - vty_out (vty, "%% Malformed Originating Router IP address\n"); - return CMD_WARNING; - } + vni = strtoul(argv[5]->arg, NULL, 10); + ret = inet_aton(argv[7]->arg, &orig_ip); + if (!ret) { + vty_out(vty, "%% Malformed Originating Router IP address\n"); + return CMD_WARNING; + } - evpn_show_route_vni_multicast (vty, bgp, vni, orig_ip); - return CMD_SUCCESS; + evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip); + return CMD_SUCCESS; } DEFUN (show_bgp_evpn_route_vni_all, @@ -2142,25 +2045,23 @@ DEFUN (show_bgp_evpn_route_vni_all, "Remote VTEP\n" "Remote VTEP IP address\n") { - struct bgp *bgp; - struct in_addr vtep_ip; + struct bgp *bgp; + struct in_addr vtep_ip; - bgp = bgp_get_default(); - if (!bgp) - return CMD_WARNING; + bgp = bgp_get_default(); + if (!bgp) + return CMD_WARNING; - vtep_ip.s_addr = 0; - if (argc == 8 && argv[7]->arg) - { - if (!inet_aton (argv[7]->arg, &vtep_ip)) - { - vty_out (vty, "%% Malformed VTEP IP address\n"); - return CMD_WARNING; - } - } + vtep_ip.s_addr = 0; + if (argc == 8 && argv[7]->arg) { + if (!inet_aton(argv[7]->arg, &vtep_ip)) { + vty_out(vty, "%% Malformed VTEP IP address\n"); + return CMD_WARNING; + } + } - evpn_show_routes_vni_all (vty, bgp, vtep_ip); - return CMD_SUCCESS; + evpn_show_routes_vni_all(vty, bgp, vtep_ip); + return CMD_SUCCESS; } DEFUN (show_bgp_evpn_import_rt, @@ -2171,14 +2072,14 @@ DEFUN (show_bgp_evpn_import_rt, "Address family modifier\n" "Show import route target\n") { - struct bgp *bgp; + struct bgp *bgp; - bgp = bgp_get_default(); - if (!bgp) - return CMD_WARNING; + bgp = bgp_get_default(); + if (!bgp) + return CMD_WARNING; - evpn_show_import_rts (vty, bgp); - return CMD_SUCCESS; + evpn_show_import_rts(vty, bgp); + return CMD_SUCCESS; } DEFUN_NOSH (bgp_evpn_vni, @@ -2187,25 +2088,24 @@ DEFUN_NOSH (bgp_evpn_vni, "VXLAN Network Identifier\n" "VNI number\n") { - vni_t vni; - struct bgp *bgp = VTY_GET_CONTEXT(bgp); - struct bgpevpn *vpn; + vni_t vni; + struct bgp *bgp = VTY_GET_CONTEXT(bgp); + struct bgpevpn *vpn; - if (!bgp) - return CMD_WARNING; + if (!bgp) + return CMD_WARNING; - vni = strtoul(argv[1]->arg, NULL, 10); + vni = strtoul(argv[1]->arg, NULL, 10); - /* Create VNI, or mark as configured. */ - vpn = evpn_create_update_vni (bgp, vni); - if (!vpn) - { - vty_out (vty, "%% Failed to create VNI \n"); - return CMD_WARNING; - } + /* Create VNI, or mark as configured. */ + vpn = evpn_create_update_vni(bgp, vni); + if (!vpn) { + vty_out(vty, "%% Failed to create VNI \n"); + return CMD_WARNING; + } - VTY_PUSH_CONTEXT_SUB (BGP_EVPN_VNI_NODE, vpn); - return CMD_SUCCESS; + VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE, vpn); + return CMD_SUCCESS; } DEFUN (no_bgp_evpn_vni, @@ -2215,30 +2115,28 @@ DEFUN (no_bgp_evpn_vni, "VXLAN Network Identifier\n" "VNI number\n") { - vni_t vni; - struct bgp *bgp = VTY_GET_CONTEXT(bgp); - struct bgpevpn *vpn; + vni_t vni; + struct bgp *bgp = VTY_GET_CONTEXT(bgp); + struct bgpevpn *vpn; - if (!bgp) - return CMD_WARNING; + if (!bgp) + return CMD_WARNING; - vni = strtoul(argv[2]->arg, NULL, 10); + vni = strtoul(argv[2]->arg, NULL, 10); - /* Check if we should disallow. */ - vpn = bgp_evpn_lookup_vni (bgp, vni); - if (!vpn) - { - vty_out (vty, "%% Specified VNI does not exist\n"); - return CMD_WARNING; - } - if (!is_vni_configured (vpn)) - { - vty_out (vty, "%% Specified VNI is not configured\n"); - return CMD_WARNING; - } + /* Check if we should disallow. */ + vpn = bgp_evpn_lookup_vni(bgp, vni); + if (!vpn) { + vty_out(vty, "%% Specified VNI does not exist\n"); + return CMD_WARNING; + } + if (!is_vni_configured(vpn)) { + vty_out(vty, "%% Specified VNI is not configured\n"); + return CMD_WARNING; + } - evpn_delete_vni (bgp, vpn); - return CMD_SUCCESS; + evpn_delete_vni(bgp, vpn); + return CMD_SUCCESS; } DEFUN_NOSH (exit_vni, @@ -2246,9 +2144,9 @@ DEFUN_NOSH (exit_vni, "exit-vni", "Exit from VNI mode\n") { - if (vty->node == BGP_EVPN_VNI_NODE) - vty->node = BGP_EVPN_NODE; - return CMD_SUCCESS; + if (vty->node == BGP_EVPN_VNI_NODE) + vty->node = BGP_EVPN_NODE; + return CMD_SUCCESS; } DEFUN (bgp_evpn_vni_rd, @@ -2257,28 +2155,27 @@ DEFUN (bgp_evpn_vni_rd, "Route Distinguisher\n" "ASN:XX or A.B.C.D:XX\n") { - struct prefix_rd prd; - struct bgp *bgp = VTY_GET_CONTEXT(bgp); - VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn); - int ret; + struct prefix_rd prd; + struct bgp *bgp = VTY_GET_CONTEXT(bgp); + VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn); + int ret; - if (!bgp || !vpn) - return CMD_WARNING; + if (!bgp || !vpn) + return CMD_WARNING; - ret = str2prefix_rd (argv[1]->arg, &prd); - if (! ret) - { - vty_out (vty, "%% Malformed Route Distinguisher\n"); - return CMD_WARNING; - } + ret = str2prefix_rd(argv[1]->arg, &prd); + if (!ret) { + vty_out(vty, "%% Malformed Route Distinguisher\n"); + return CMD_WARNING; + } - /* If same as existing value, there is nothing more to do. */ - if (bgp_evpn_rd_matches_existing (vpn, &prd)) - return CMD_SUCCESS; + /* If same as existing value, there is nothing more to do. */ + if (bgp_evpn_rd_matches_existing(vpn, &prd)) + return CMD_SUCCESS; - /* Configure or update the RD. */ - evpn_configure_rd (bgp, vpn, &prd); - return CMD_SUCCESS; + /* Configure or update the RD. */ + evpn_configure_rd(bgp, vpn, &prd); + return CMD_SUCCESS; } DEFUN (no_bgp_evpn_vni_rd, @@ -2288,36 +2185,34 @@ DEFUN (no_bgp_evpn_vni_rd, "Route Distinguisher\n" "ASN:XX or A.B.C.D:XX\n") { - struct prefix_rd prd; - struct bgp *bgp = VTY_GET_CONTEXT(bgp); - VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn); - int ret; + struct prefix_rd prd; + struct bgp *bgp = VTY_GET_CONTEXT(bgp); + VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn); + int ret; - if (!bgp || !vpn) - return CMD_WARNING; + if (!bgp || !vpn) + return CMD_WARNING; - ret = str2prefix_rd (argv[2]->arg, &prd); - if (! ret) - { - vty_out (vty, "%% Malformed Route Distinguisher\n"); - return CMD_WARNING; - } + ret = str2prefix_rd(argv[2]->arg, &prd); + if (!ret) { + vty_out(vty, "%% Malformed Route Distinguisher\n"); + return CMD_WARNING; + } - /* Check if we should disallow. */ - if (!is_rd_configured (vpn)) - { - vty_out (vty, "%% RD is not configured for this VNI\n"); - return CMD_WARNING; - } + /* Check if we should disallow. */ + if (!is_rd_configured(vpn)) { + vty_out(vty, "%% RD is not configured for this VNI\n"); + return CMD_WARNING; + } - if (!bgp_evpn_rd_matches_existing(vpn, &prd)) - { - vty_out (vty, "%% RD specified does not match configuration for this VNI\n"); - return CMD_WARNING; - } + if (!bgp_evpn_rd_matches_existing(vpn, &prd)) { + vty_out(vty, + "%% RD specified does not match configuration for this VNI\n"); + return CMD_WARNING; + } - evpn_unconfigure_rd (bgp, vpn); - return CMD_SUCCESS; + evpn_unconfigure_rd(bgp, vpn); + return CMD_SUCCESS; } DEFUN (no_bgp_evpn_vni_rd_without_val, @@ -2326,41 +2221,38 @@ DEFUN (no_bgp_evpn_vni_rd_without_val, NO_STR "Route Distinguisher\n") { - struct bgp *bgp = VTY_GET_CONTEXT(bgp); - VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn); + struct bgp *bgp = VTY_GET_CONTEXT(bgp); + VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn); - if (!bgp || !vpn) - return CMD_WARNING; + if (!bgp || !vpn) + return CMD_WARNING; - /* Check if we should disallow. */ - if (!is_rd_configured (vpn)) - { - vty_out (vty, "%% RD is not configured for this VNI\n"); - return CMD_WARNING; - } + /* Check if we should disallow. */ + if (!is_rd_configured(vpn)) { + vty_out(vty, "%% RD is not configured for this VNI\n"); + return CMD_WARNING; + } - evpn_unconfigure_rd (bgp, vpn); - return CMD_SUCCESS; + evpn_unconfigure_rd(bgp, vpn); + return CMD_SUCCESS; } /* * Loop over all extended-communities in the route-target list rtl and * return 1 if we find ecomtarget */ -static int -bgp_evpn_rt_matches_existing (struct list *rtl, - struct ecommunity *ecomtarget) +static int bgp_evpn_rt_matches_existing(struct list *rtl, + struct ecommunity *ecomtarget) { - struct listnode *node, *nnode; - struct ecommunity *ecom; + struct listnode *node, *nnode; + struct ecommunity *ecom; - for (ALL_LIST_ELEMENTS (rtl, node, nnode, ecom)) - { - if (ecommunity_match (ecom, ecomtarget)) - return 1; - } + for (ALL_LIST_ELEMENTS(rtl, node, nnode, ecom)) { + if (ecommunity_match(ecom, ecomtarget)) + return 1; + } - return 0; + return 0; } @@ -2373,61 +2265,56 @@ DEFUN (bgp_evpn_vni_rt, "export\n" "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n") { - struct bgp *bgp = VTY_GET_CONTEXT(bgp); - VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn); - int rt_type; - struct ecommunity *ecomadd = NULL; - - if (!bgp || !vpn) - return CMD_WARNING; - - if (!strcmp (argv[1]->arg, "import")) - rt_type = RT_TYPE_IMPORT; - else if (!strcmp (argv[1]->arg, "export")) - rt_type = RT_TYPE_EXPORT; - else if (!strcmp (argv[1]->arg, "both")) - rt_type = RT_TYPE_BOTH; - else - { - vty_out (vty, "%% Invalid Route Target type\n"); - return CMD_WARNING; - } - - /* Add/update the import route-target */ - if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) - { - ecomadd = ecommunity_str2com (argv[2]->arg, - ECOMMUNITY_ROUTE_TARGET, 0); - ecommunity_str(ecomadd); - if (!ecomadd) - { - vty_out (vty, "%% Malformed Route Target list\n"); - return CMD_WARNING; - } - - /* Do nothing if we already have this import route-target */ - if (! bgp_evpn_rt_matches_existing (vpn->import_rtl, ecomadd)) - evpn_configure_import_rt (bgp, vpn, ecomadd); - } - - /* Add/update the export route-target */ - if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) - { - ecomadd = ecommunity_str2com (argv[2]->arg, - ECOMMUNITY_ROUTE_TARGET, 0); - ecommunity_str(ecomadd); - if (!ecomadd) - { - vty_out (vty, "%% Malformed Route Target list\n"); - return CMD_WARNING; - } - - /* Do nothing if we already have this export route-target */ - if (! bgp_evpn_rt_matches_existing (vpn->export_rtl, ecomadd)) - evpn_configure_export_rt (bgp, vpn, ecomadd); - } - - return CMD_SUCCESS; + struct bgp *bgp = VTY_GET_CONTEXT(bgp); + VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn); + int rt_type; + struct ecommunity *ecomadd = NULL; + + if (!bgp || !vpn) + return CMD_WARNING; + + if (!strcmp(argv[1]->arg, "import")) + rt_type = RT_TYPE_IMPORT; + else if (!strcmp(argv[1]->arg, "export")) + rt_type = RT_TYPE_EXPORT; + else if (!strcmp(argv[1]->arg, "both")) + rt_type = RT_TYPE_BOTH; + else { + vty_out(vty, "%% Invalid Route Target type\n"); + return CMD_WARNING; + } + + /* Add/update the import route-target */ + if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) { + ecomadd = ecommunity_str2com(argv[2]->arg, + ECOMMUNITY_ROUTE_TARGET, 0); + ecommunity_str(ecomadd); + if (!ecomadd) { + vty_out(vty, "%% Malformed Route Target list\n"); + return CMD_WARNING; + } + + /* Do nothing if we already have this import route-target */ + if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd)) + evpn_configure_import_rt(bgp, vpn, ecomadd); + } + + /* Add/update the export route-target */ + if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) { + ecomadd = ecommunity_str2com(argv[2]->arg, + ECOMMUNITY_ROUTE_TARGET, 0); + ecommunity_str(ecomadd); + if (!ecomadd) { + vty_out(vty, "%% Malformed Route Target list\n"); + return CMD_WARNING; + } + + /* Do nothing if we already have this export route-target */ + if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd)) + evpn_configure_export_rt(bgp, vpn, ecomadd); + } + + return CMD_SUCCESS; } DEFUN (no_bgp_evpn_vni_rt, @@ -2440,103 +2327,90 @@ DEFUN (no_bgp_evpn_vni_rt, "export\n" "ASN:XX or A.B.C.D:XX\n") { - struct bgp *bgp = VTY_GET_CONTEXT(bgp); - VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn); - int rt_type, found_ecomdel; - struct ecommunity *ecomdel = NULL; - - if (!bgp || !vpn) - return CMD_WARNING; - - if (!strcmp (argv[2]->arg, "import")) - rt_type = RT_TYPE_IMPORT; - else if (!strcmp (argv[2]->arg, "export")) - rt_type = RT_TYPE_EXPORT; - else if (!strcmp (argv[2]->arg, "both")) - rt_type = RT_TYPE_BOTH; - else - { - vty_out (vty, "%% Invalid Route Target type\n"); - return CMD_WARNING; - } - - /* The user did "no route-target import", check to see if there are any - * import route-targets configured. */ - if (rt_type == RT_TYPE_IMPORT) - { - if (!is_import_rt_configured (vpn)) - { - vty_out (vty, "%% Import RT is not configured for this VNI\n"); - return CMD_WARNING; - } - } - else if (rt_type == RT_TYPE_EXPORT) - { - if (!is_export_rt_configured (vpn)) - { - vty_out (vty, "%% Export RT is not configured for this VNI\n"); - return CMD_WARNING; - } - } - else if (rt_type == RT_TYPE_BOTH) - { - if (!is_import_rt_configured (vpn) && !is_export_rt_configured (vpn)) - { - vty_out (vty, "%% Import/Export RT is not configured for this VNI\n"); - return CMD_WARNING; - } - } - - ecomdel = ecommunity_str2com (argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0); - ecommunity_str(ecomdel); - if (!ecomdel) - { - vty_out (vty, "%% Malformed Route Target list\n"); - return CMD_WARNING; - } - - if (rt_type == RT_TYPE_IMPORT) - { - if (!bgp_evpn_rt_matches_existing (vpn->import_rtl, ecomdel)) - { - vty_out (vty, "%% RT specified does not match configuration for this VNI\n"); - return CMD_WARNING; - } - evpn_unconfigure_import_rt (bgp, vpn, ecomdel); - } - else if (rt_type == RT_TYPE_EXPORT) - { - if (!bgp_evpn_rt_matches_existing (vpn->export_rtl, ecomdel)) - { - vty_out (vty, "%% RT specified does not match configuration for this VNI\n"); - return CMD_WARNING; - } - evpn_unconfigure_export_rt (bgp, vpn, ecomdel); - } - else if (rt_type == RT_TYPE_BOTH) - { - found_ecomdel = 0; - - if (bgp_evpn_rt_matches_existing (vpn->import_rtl, ecomdel)) - { - evpn_unconfigure_import_rt (bgp, vpn, ecomdel); - found_ecomdel = 1; - } - - if (bgp_evpn_rt_matches_existing (vpn->export_rtl, ecomdel)) - { - evpn_unconfigure_export_rt (bgp, vpn, ecomdel); - found_ecomdel = 1; - } - - if (! found_ecomdel) - { - vty_out (vty, "%% RT specified does not match configuration for this VNI\n"); - return CMD_WARNING; - } - } - - return CMD_SUCCESS; + struct bgp *bgp = VTY_GET_CONTEXT(bgp); + VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn); + int rt_type, found_ecomdel; + struct ecommunity *ecomdel = NULL; + + if (!bgp || !vpn) + return CMD_WARNING; + + if (!strcmp(argv[2]->arg, "import")) + rt_type = RT_TYPE_IMPORT; + else if (!strcmp(argv[2]->arg, "export")) + rt_type = RT_TYPE_EXPORT; + else if (!strcmp(argv[2]->arg, "both")) + rt_type = RT_TYPE_BOTH; + else { + vty_out(vty, "%% Invalid Route Target type\n"); + return CMD_WARNING; + } + + /* The user did "no route-target import", check to see if there are any + * import route-targets configured. */ + if (rt_type == RT_TYPE_IMPORT) { + if (!is_import_rt_configured(vpn)) { + vty_out(vty, + "%% Import RT is not configured for this VNI\n"); + return CMD_WARNING; + } + } else if (rt_type == RT_TYPE_EXPORT) { + if (!is_export_rt_configured(vpn)) { + vty_out(vty, + "%% Export RT is not configured for this VNI\n"); + return CMD_WARNING; + } + } else if (rt_type == RT_TYPE_BOTH) { + if (!is_import_rt_configured(vpn) + && !is_export_rt_configured(vpn)) { + vty_out(vty, + "%% Import/Export RT is not configured for this VNI\n"); + return CMD_WARNING; + } + } + + ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0); + ecommunity_str(ecomdel); + if (!ecomdel) { + vty_out(vty, "%% Malformed Route Target list\n"); + return CMD_WARNING; + } + + if (rt_type == RT_TYPE_IMPORT) { + if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) { + vty_out(vty, + "%% RT specified does not match configuration for this VNI\n"); + return CMD_WARNING; + } + evpn_unconfigure_import_rt(bgp, vpn, ecomdel); + } else if (rt_type == RT_TYPE_EXPORT) { + if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) { + vty_out(vty, + "%% RT specified does not match configuration for this VNI\n"); + return CMD_WARNING; + } + evpn_unconfigure_export_rt(bgp, vpn, ecomdel); + } else if (rt_type == RT_TYPE_BOTH) { + found_ecomdel = 0; + + if (bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) { + evpn_unconfigure_import_rt(bgp, vpn, ecomdel); + found_ecomdel = 1; + } + + if (bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) { + evpn_unconfigure_export_rt(bgp, vpn, ecomdel); + found_ecomdel = 1; + } + + if (!found_ecomdel) { + vty_out(vty, + "%% RT specified does not match configuration for this VNI\n"); + return CMD_WARNING; + } + } + + return CMD_SUCCESS; } DEFUN (no_bgp_evpn_vni_rt_without_val, @@ -2547,120 +2421,114 @@ DEFUN (no_bgp_evpn_vni_rt_without_val, "import\n" "export\n") { - struct bgp *bgp = VTY_GET_CONTEXT(bgp); - VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn); - int rt_type; - - if (!bgp || !vpn) - return CMD_WARNING; - - if (!strcmp (argv[2]->arg, "import")) - { - rt_type = RT_TYPE_IMPORT; - } - else if (!strcmp (argv[2]->arg, "export")) - { - rt_type = RT_TYPE_EXPORT; - } - else - { - vty_out (vty, "%% Invalid Route Target type\n"); - return CMD_WARNING; - } - - /* Check if we should disallow. */ - if (rt_type == RT_TYPE_IMPORT) - { - if (!is_import_rt_configured (vpn)) - { - vty_out (vty, "%% Import RT is not configured for this VNI\n"); - return CMD_WARNING; - } - } - else - { - if (!is_export_rt_configured (vpn)) - { - vty_out (vty, "%% Export RT is not configured for this VNI\n"); - return CMD_WARNING; - } - } - - /* Unconfigure the RT. */ - if (rt_type == RT_TYPE_IMPORT) - evpn_unconfigure_import_rt (bgp, vpn, NULL); - else - evpn_unconfigure_export_rt (bgp, vpn, NULL); - return CMD_SUCCESS; + struct bgp *bgp = VTY_GET_CONTEXT(bgp); + VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn); + int rt_type; + + if (!bgp || !vpn) + return CMD_WARNING; + + if (!strcmp(argv[2]->arg, "import")) { + rt_type = RT_TYPE_IMPORT; + } else if (!strcmp(argv[2]->arg, "export")) { + rt_type = RT_TYPE_EXPORT; + } else { + vty_out(vty, "%% Invalid Route Target type\n"); + return CMD_WARNING; + } + + /* Check if we should disallow. */ + if (rt_type == RT_TYPE_IMPORT) { + if (!is_import_rt_configured(vpn)) { + vty_out(vty, + "%% Import RT is not configured for this VNI\n"); + return CMD_WARNING; + } + } else { + if (!is_export_rt_configured(vpn)) { + vty_out(vty, + "%% Export RT is not configured for this VNI\n"); + return CMD_WARNING; + } + } + + /* Unconfigure the RT. */ + if (rt_type == RT_TYPE_IMPORT) + evpn_unconfigure_import_rt(bgp, vpn, NULL); + else + evpn_unconfigure_export_rt(bgp, vpn, NULL); + return CMD_SUCCESS; } #endif /* * Output EVPN configuration information. */ -void -bgp_config_write_evpn_info (struct vty *vty, struct bgp *bgp, afi_t afi, - safi_t safi, int *write) -{ - struct evpn_config_write cfg; - - if (bgp->vnihash) - { - cfg.write = *write; - cfg.vty = vty; - hash_iterate (bgp->vnihash, - (void (*) (struct hash_backet *, void *)) - write_vni_config_for_entry, &cfg); - *write = cfg.write; - } +void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi, int *write) +{ + struct evpn_config_write cfg; + + if (bgp->vnihash) { + cfg.write = *write; + cfg.vty = vty; + hash_iterate(bgp->vnihash, + (void (*)(struct hash_backet *, + void *))write_vni_config_for_entry, + &cfg); + *write = cfg.write; + } - if (bgp->advertise_all_vni) - { - bgp_config_write_family_header (vty, afi, safi, write); - vty_out (vty, " advertise-all-vni\n"); - } + if (bgp->advertise_all_vni) { + bgp_config_write_family_header(vty, afi, safi, write); + vty_out(vty, " advertise-all-vni\n"); + } } void bgp_ethernetvpn_init(void) { - install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd); - install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd); - install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd); - install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd); - install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd); - install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd); - install_element(VIEW_NODE, - &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd); - install_element(VIEW_NODE, - &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd); - install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd); - install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd); - install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd); - install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd); + install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd); + install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd); + install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd); + install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd); + install_element(VIEW_NODE, + &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd); + install_element(VIEW_NODE, + &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd); + install_element( + VIEW_NODE, + &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd); + install_element( + VIEW_NODE, + &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd); + install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd); + install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd); + install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd); + install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd); #if defined(HAVE_CUMULUS) - install_element (BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd); - install_element (BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd); - - /* "show bgp evpn" commands. */ - install_element (VIEW_NODE, &show_bgp_evpn_vni_cmd); - install_element (VIEW_NODE, &show_bgp_evpn_vni_num_cmd); - install_element (VIEW_NODE, &show_bgp_evpn_summary_cmd); - install_element (VIEW_NODE, &show_bgp_evpn_route_cmd); - install_element (VIEW_NODE, &show_bgp_evpn_route_rd_cmd); - install_element (VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd); - install_element (VIEW_NODE, &show_bgp_evpn_route_vni_cmd); - install_element (VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd); - install_element (VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd); - install_element (VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd); - install_element (VIEW_NODE, &show_bgp_evpn_import_rt_cmd); - - install_element (BGP_EVPN_NODE, &bgp_evpn_vni_cmd); - install_element (BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd); - install_element (BGP_EVPN_VNI_NODE, &exit_vni_cmd); - install_element (BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd); - install_element (BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd); - install_element (BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd); - install_element (BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd); - install_element (BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd); - install_element (BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd); + install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd); + install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd); + + /* "show bgp evpn" commands. */ + install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd); + install_element(VIEW_NODE, &show_bgp_evpn_vni_num_cmd); + install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd); + install_element(VIEW_NODE, &show_bgp_evpn_route_cmd); + install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd); + install_element(VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd); + install_element(VIEW_NODE, &show_bgp_evpn_route_vni_cmd); + install_element(VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd); + install_element(VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd); + install_element(VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd); + install_element(VIEW_NODE, &show_bgp_evpn_import_rt_cmd); + + install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd); + install_element(BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd); + install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd); + install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd); + install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd); + install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd); + install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd); + install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd); + install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd); #endif } diff --git a/bgpd/bgp_evpn_vty.h b/bgpd/bgp_evpn_vty.h index 4c8f63c2f..3bc24593f 100644 --- a/bgpd/bgp_evpn_vty.h +++ b/bgpd/bgp_evpn_vty.h @@ -21,12 +21,11 @@ #ifndef _FRR_BGP_EVPN_VTY_H #define _FRR_BGP_EVPN_VTY_H -extern void -bgp_config_write_evpn_info (struct vty *vty, struct bgp *bgp, afi_t afi, - safi_t safi, int *write); +extern void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, + afi_t afi, safi_t safi, int *write); extern void bgp_ethernetvpn_init(void); #define L2VPN_HELP_STR "Layer 2 Virtual Private Network\n" #define EVPN_HELP_STR "Ethernet Virtual Private Network\n" -#endif /* _QUAGGA_BGP_EVPN_VTY_H */ +#endif /* _QUAGGA_BGP_EVPN_VTY_H */ diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c index a61321b0e..6e1a1b6d6 100644 --- a/bgpd/bgp_filter.c +++ b/bgpd/bgp_filter.c @@ -33,397 +33,362 @@ #include "bgpd/bgp_filter.h" /* List of AS filter list. */ -struct as_list_list -{ - struct as_list *head; - struct as_list *tail; +struct as_list_list { + struct as_list *head; + struct as_list *tail; }; /* AS path filter master. */ -struct as_list_master -{ - /* List of access_list which name is number. */ - struct as_list_list num; +struct as_list_master { + /* List of access_list which name is number. */ + struct as_list_list num; - /* List of access_list which name is string. */ - struct as_list_list str; + /* List of access_list which name is string. */ + struct as_list_list str; - /* Hook function which is executed when new access_list is added. */ - void (*add_hook) (char *); + /* Hook function which is executed when new access_list is added. */ + void (*add_hook)(char *); - /* Hook function which is executed when access_list is deleted. */ - void (*delete_hook) (const char *); + /* Hook function which is executed when access_list is deleted. */ + void (*delete_hook)(const char *); }; /* Element of AS path filter. */ -struct as_filter -{ - struct as_filter *next; - struct as_filter *prev; +struct as_filter { + struct as_filter *next; + struct as_filter *prev; - enum as_filter_type type; + enum as_filter_type type; - regex_t *reg; - char *reg_str; + regex_t *reg; + char *reg_str; }; /* AS path filter list. */ -struct as_list -{ - char *name; +struct as_list { + char *name; - enum access_type type; + enum access_type type; - struct as_list *next; - struct as_list *prev; + struct as_list *next; + struct as_list *prev; - struct as_filter *head; - struct as_filter *tail; + struct as_filter *head; + struct as_filter *tail; }; /* ip as-path access-list 10 permit AS1. */ -static struct as_list_master as_list_master = -{ - {NULL, NULL}, - {NULL, NULL}, - NULL, - NULL -}; +static struct as_list_master as_list_master = {{NULL, NULL}, + {NULL, NULL}, + NULL, + NULL}; /* Allocate new AS filter. */ -static struct as_filter * -as_filter_new (void) +static struct as_filter *as_filter_new(void) { - return XCALLOC (MTYPE_AS_FILTER, sizeof (struct as_filter)); + return XCALLOC(MTYPE_AS_FILTER, sizeof(struct as_filter)); } /* Free allocated AS filter. */ -static void -as_filter_free (struct as_filter *asfilter) +static void as_filter_free(struct as_filter *asfilter) { - if (asfilter->reg) - bgp_regex_free (asfilter->reg); - if (asfilter->reg_str) - XFREE (MTYPE_AS_FILTER_STR, asfilter->reg_str); - XFREE (MTYPE_AS_FILTER, asfilter); + if (asfilter->reg) + bgp_regex_free(asfilter->reg); + if (asfilter->reg_str) + XFREE(MTYPE_AS_FILTER_STR, asfilter->reg_str); + XFREE(MTYPE_AS_FILTER, asfilter); } /* Make new AS filter. */ -static struct as_filter * -as_filter_make (regex_t *reg, const char *reg_str, enum as_filter_type type) +static struct as_filter *as_filter_make(regex_t *reg, const char *reg_str, + enum as_filter_type type) { - struct as_filter *asfilter; + struct as_filter *asfilter; - asfilter = as_filter_new (); - asfilter->reg = reg; - asfilter->type = type; - asfilter->reg_str = XSTRDUP (MTYPE_AS_FILTER_STR, reg_str); + asfilter = as_filter_new(); + asfilter->reg = reg; + asfilter->type = type; + asfilter->reg_str = XSTRDUP(MTYPE_AS_FILTER_STR, reg_str); - return asfilter; + return asfilter; } -static struct as_filter * -as_filter_lookup (struct as_list *aslist, const char *reg_str, - enum as_filter_type type) +static struct as_filter *as_filter_lookup(struct as_list *aslist, + const char *reg_str, + enum as_filter_type type) { - struct as_filter *asfilter; + struct as_filter *asfilter; - for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) - if (strcmp (reg_str, asfilter->reg_str) == 0) - return asfilter; - return NULL; + for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) + if (strcmp(reg_str, asfilter->reg_str) == 0) + return asfilter; + return NULL; } -static void -as_list_filter_add (struct as_list *aslist, struct as_filter *asfilter) +static void as_list_filter_add(struct as_list *aslist, + struct as_filter *asfilter) { - asfilter->next = NULL; - asfilter->prev = aslist->tail; + asfilter->next = NULL; + asfilter->prev = aslist->tail; - if (aslist->tail) - aslist->tail->next = asfilter; - else - aslist->head = asfilter; - aslist->tail = asfilter; - - /* Run hook function. */ - if (as_list_master.add_hook) - (*as_list_master.add_hook) (aslist->name); + if (aslist->tail) + aslist->tail->next = asfilter; + else + aslist->head = asfilter; + aslist->tail = asfilter; + /* Run hook function. */ + if (as_list_master.add_hook) + (*as_list_master.add_hook)(aslist->name); } /* Lookup as_list from list of as_list by name. */ -struct as_list * -as_list_lookup (const char *name) +struct as_list *as_list_lookup(const char *name) { - struct as_list *aslist; + struct as_list *aslist; - if (name == NULL) - return NULL; + if (name == NULL) + return NULL; - for (aslist = as_list_master.num.head; aslist; aslist = aslist->next) - if (strcmp (aslist->name, name) == 0) - return aslist; + for (aslist = as_list_master.num.head; aslist; aslist = aslist->next) + if (strcmp(aslist->name, name) == 0) + return aslist; - for (aslist = as_list_master.str.head; aslist; aslist = aslist->next) - if (strcmp (aslist->name, name) == 0) - return aslist; + for (aslist = as_list_master.str.head; aslist; aslist = aslist->next) + if (strcmp(aslist->name, name) == 0) + return aslist; - return NULL; + return NULL; } -static struct as_list * -as_list_new (void) +static struct as_list *as_list_new(void) { - return XCALLOC (MTYPE_AS_LIST, sizeof (struct as_list)); + return XCALLOC(MTYPE_AS_LIST, sizeof(struct as_list)); } -static void -as_list_free (struct as_list *aslist) +static void as_list_free(struct as_list *aslist) { - if (aslist->name) - { - XFREE(MTYPE_AS_STR, aslist->name); - aslist->name = NULL; - } - XFREE (MTYPE_AS_LIST, aslist); + if (aslist->name) { + XFREE(MTYPE_AS_STR, aslist->name); + aslist->name = NULL; + } + XFREE(MTYPE_AS_LIST, aslist); } /* Insert new AS list to list of as_list. Each as_list is sorted by the name. */ -static struct as_list * -as_list_insert (const char *name) -{ - size_t i; - long number; - struct as_list *aslist; - struct as_list *point; - struct as_list_list *list; - - /* Allocate new access_list and copy given name. */ - aslist = as_list_new (); - aslist->name = XSTRDUP(MTYPE_AS_STR, name); - assert (aslist->name); - - /* If name is made by all digit character. We treat it as - number. */ - for (number = 0, i = 0; i < strlen (name); i++) - { - if (isdigit ((int) name[i])) - number = (number * 10) + (name[i] - '0'); - else - break; - } - - /* In case of name is all digit character */ - if (i == strlen (name)) - { - aslist->type = ACCESS_TYPE_NUMBER; - - /* Set access_list to number list. */ - list = &as_list_master.num; - - for (point = list->head; point; point = point->next) - if (atol (point->name) >= number) - break; - } - else - { - aslist->type = ACCESS_TYPE_STRING; - - /* Set access_list to string list. */ - list = &as_list_master.str; - - /* Set point to insertion point. */ - for (point = list->head; point; point = point->next) - if (strcmp (point->name, name) >= 0) - break; - } - - /* In case of this is the first element of master. */ - if (list->head == NULL) - { - list->head = list->tail = aslist; - return aslist; - } - - /* In case of insertion is made at the tail of access_list. */ - if (point == NULL) - { - aslist->prev = list->tail; - list->tail->next = aslist; - list->tail = aslist; - return aslist; - } - - /* In case of insertion is made at the head of access_list. */ - if (point == list->head) - { - aslist->next = list->head; - list->head->prev = aslist; - list->head = aslist; - return aslist; - } - - /* Insertion is made at middle of the access_list. */ - aslist->next = point; - aslist->prev = point->prev; - - if (point->prev) - point->prev->next = aslist; - point->prev = aslist; - - return aslist; +static struct as_list *as_list_insert(const char *name) +{ + size_t i; + long number; + struct as_list *aslist; + struct as_list *point; + struct as_list_list *list; + + /* Allocate new access_list and copy given name. */ + aslist = as_list_new(); + aslist->name = XSTRDUP(MTYPE_AS_STR, name); + assert(aslist->name); + + /* If name is made by all digit character. We treat it as + number. */ + for (number = 0, i = 0; i < strlen(name); i++) { + if (isdigit((int)name[i])) + number = (number * 10) + (name[i] - '0'); + else + break; + } + + /* In case of name is all digit character */ + if (i == strlen(name)) { + aslist->type = ACCESS_TYPE_NUMBER; + + /* Set access_list to number list. */ + list = &as_list_master.num; + + for (point = list->head; point; point = point->next) + if (atol(point->name) >= number) + break; + } else { + aslist->type = ACCESS_TYPE_STRING; + + /* Set access_list to string list. */ + list = &as_list_master.str; + + /* Set point to insertion point. */ + for (point = list->head; point; point = point->next) + if (strcmp(point->name, name) >= 0) + break; + } + + /* In case of this is the first element of master. */ + if (list->head == NULL) { + list->head = list->tail = aslist; + return aslist; + } + + /* In case of insertion is made at the tail of access_list. */ + if (point == NULL) { + aslist->prev = list->tail; + list->tail->next = aslist; + list->tail = aslist; + return aslist; + } + + /* In case of insertion is made at the head of access_list. */ + if (point == list->head) { + aslist->next = list->head; + list->head->prev = aslist; + list->head = aslist; + return aslist; + } + + /* Insertion is made at middle of the access_list. */ + aslist->next = point; + aslist->prev = point->prev; + + if (point->prev) + point->prev->next = aslist; + point->prev = aslist; + + return aslist; } -static struct as_list * -as_list_get (const char *name) +static struct as_list *as_list_get(const char *name) { - struct as_list *aslist; + struct as_list *aslist; - aslist = as_list_lookup (name); - if (aslist == NULL) - aslist = as_list_insert (name); + aslist = as_list_lookup(name); + if (aslist == NULL) + aslist = as_list_insert(name); - return aslist; + return aslist; } -static const char * -filter_type_str (enum as_filter_type type) +static const char *filter_type_str(enum as_filter_type type) { - switch (type) - { - case AS_FILTER_PERMIT: - return "permit"; - case AS_FILTER_DENY: - return "deny"; - default: - return ""; - } + switch (type) { + case AS_FILTER_PERMIT: + return "permit"; + case AS_FILTER_DENY: + return "deny"; + default: + return ""; + } } -static void -as_list_delete (struct as_list *aslist) +static void as_list_delete(struct as_list *aslist) { - struct as_list_list *list; - struct as_filter *filter, *next; - - for (filter = aslist->head; filter; filter = next) - { - next = filter->next; - as_filter_free (filter); - } - - if (aslist->type == ACCESS_TYPE_NUMBER) - list = &as_list_master.num; - else - list = &as_list_master.str; - - if (aslist->next) - aslist->next->prev = aslist->prev; - else - list->tail = aslist->prev; - - if (aslist->prev) - aslist->prev->next = aslist->next; - else - list->head = aslist->next; - - as_list_free (aslist); + struct as_list_list *list; + struct as_filter *filter, *next; + + for (filter = aslist->head; filter; filter = next) { + next = filter->next; + as_filter_free(filter); + } + + if (aslist->type == ACCESS_TYPE_NUMBER) + list = &as_list_master.num; + else + list = &as_list_master.str; + + if (aslist->next) + aslist->next->prev = aslist->prev; + else + list->tail = aslist->prev; + + if (aslist->prev) + aslist->prev->next = aslist->next; + else + list->head = aslist->next; + + as_list_free(aslist); } -static int -as_list_empty (struct as_list *aslist) +static int as_list_empty(struct as_list *aslist) { - if (aslist->head == NULL && aslist->tail == NULL) - return 1; - else - return 0; + if (aslist->head == NULL && aslist->tail == NULL) + return 1; + else + return 0; } -static void -as_list_filter_delete (struct as_list *aslist, struct as_filter *asfilter) +static void as_list_filter_delete(struct as_list *aslist, + struct as_filter *asfilter) { - char *name = XSTRDUP(MTYPE_AS_STR, aslist->name); + char *name = XSTRDUP(MTYPE_AS_STR, aslist->name); - if (asfilter->next) - asfilter->next->prev = asfilter->prev; - else - aslist->tail = asfilter->prev; + if (asfilter->next) + asfilter->next->prev = asfilter->prev; + else + aslist->tail = asfilter->prev; - if (asfilter->prev) - asfilter->prev->next = asfilter->next; - else - aslist->head = asfilter->next; + if (asfilter->prev) + asfilter->prev->next = asfilter->next; + else + aslist->head = asfilter->next; - as_filter_free (asfilter); + as_filter_free(asfilter); - /* If access_list becomes empty delete it from access_master. */ - if (as_list_empty (aslist)) - as_list_delete (aslist); + /* If access_list becomes empty delete it from access_master. */ + if (as_list_empty(aslist)) + as_list_delete(aslist); - /* Run hook function. */ - if (as_list_master.delete_hook) - (*as_list_master.delete_hook) (name); - if (name) - XFREE(MTYPE_AS_STR, name); + /* Run hook function. */ + if (as_list_master.delete_hook) + (*as_list_master.delete_hook)(name); + if (name) + XFREE(MTYPE_AS_STR, name); } -static int -as_filter_match (struct as_filter *asfilter, struct aspath *aspath) +static int as_filter_match(struct as_filter *asfilter, struct aspath *aspath) { - if (bgp_regexec (asfilter->reg, aspath) != REG_NOMATCH) - return 1; - return 0; + if (bgp_regexec(asfilter->reg, aspath) != REG_NOMATCH) + return 1; + return 0; } /* Apply AS path filter to AS. */ -enum as_filter_type -as_list_apply (struct as_list *aslist, void *object) +enum as_filter_type as_list_apply(struct as_list *aslist, void *object) { - struct as_filter *asfilter; - struct aspath *aspath; + struct as_filter *asfilter; + struct aspath *aspath; - aspath = (struct aspath *) object; + aspath = (struct aspath *)object; - if (aslist == NULL) - return AS_FILTER_DENY; + if (aslist == NULL) + return AS_FILTER_DENY; - for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) - { - if (as_filter_match (asfilter, aspath)) - return asfilter->type; - } - return AS_FILTER_DENY; + for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) { + if (as_filter_match(asfilter, aspath)) + return asfilter->type; + } + return AS_FILTER_DENY; } /* Add hook function. */ -void -as_list_add_hook (void (*func) (char *)) +void as_list_add_hook(void (*func)(char *)) { - as_list_master.add_hook = func; + as_list_master.add_hook = func; } /* Delete hook function. */ -void -as_list_delete_hook (void (*func) (const char *)) +void as_list_delete_hook(void (*func)(const char *)) { - as_list_master.delete_hook = func; + as_list_master.delete_hook = func; } -static int -as_list_dup_check (struct as_list *aslist, struct as_filter *new) +static int as_list_dup_check(struct as_list *aslist, struct as_filter *new) { - struct as_filter *asfilter; - - for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) - { - if (asfilter->type == new->type - && strcmp (asfilter->reg_str, new->reg_str) == 0) - return 1; - } - return 0; + struct as_filter *asfilter; + + for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) { + if (asfilter->type == new->type + && strcmp(asfilter->reg_str, new->reg_str) == 0) + return 1; + } + return 0; } DEFUN (ip_as_path, @@ -437,45 +402,46 @@ DEFUN (ip_as_path, "Specify packets to forward\n" "A regular-expression to match the BGP AS paths\n") { - int idx = 0; - enum as_filter_type type; - struct as_filter *asfilter; - struct as_list *aslist; - regex_t *regex; - char *regstr; - - /* Retrieve access list name */ - char *alname = argv_find (argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL; - - /* Check the filter type. */ - type = argv_find (argv, argc, "deny", &idx) ? AS_FILTER_DENY : AS_FILTER_PERMIT; - - /* Check AS path regex. */ - argv_find (argv, argc, "LINE", &idx); - regstr = argv_concat(argv, argc, idx); - - regex = bgp_regcomp (regstr); - if (!regex) - { - vty_out (vty, "can't compile regexp %s\n", regstr); - XFREE (MTYPE_TMP, regstr); - return CMD_WARNING_CONFIG_FAILED; - } - - asfilter = as_filter_make (regex, regstr, type); - - XFREE (MTYPE_TMP, regstr); - - /* Install new filter to the access_list. */ - aslist = as_list_get (alname); - - /* Duplicate insertion check. */; - if (as_list_dup_check (aslist, asfilter)) - as_filter_free (asfilter); - else - as_list_filter_add (aslist, asfilter); - - return CMD_SUCCESS; + int idx = 0; + enum as_filter_type type; + struct as_filter *asfilter; + struct as_list *aslist; + regex_t *regex; + char *regstr; + + /* Retrieve access list name */ + char *alname = + argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL; + + /* Check the filter type. */ + type = argv_find(argv, argc, "deny", &idx) ? AS_FILTER_DENY + : AS_FILTER_PERMIT; + + /* Check AS path regex. */ + argv_find(argv, argc, "LINE", &idx); + regstr = argv_concat(argv, argc, idx); + + regex = bgp_regcomp(regstr); + if (!regex) { + vty_out(vty, "can't compile regexp %s\n", regstr); + XFREE(MTYPE_TMP, regstr); + return CMD_WARNING_CONFIG_FAILED; + } + + asfilter = as_filter_make(regex, regstr, type); + + XFREE(MTYPE_TMP, regstr); + + /* Install new filter to the access_list. */ + aslist = as_list_get(alname); + + /* Duplicate insertion check. */; + if (as_list_dup_check(aslist, asfilter)) + as_filter_free(asfilter); + else + as_list_filter_add(aslist, asfilter); + + return CMD_SUCCESS; } DEFUN (no_ip_as_path, @@ -490,61 +456,59 @@ DEFUN (no_ip_as_path, "Specify packets to forward\n" "A regular-expression to match the BGP AS paths\n") { - int idx = 0; - enum as_filter_type type; - struct as_filter *asfilter; - struct as_list *aslist; - char *regstr; - regex_t *regex; - - char *aslistname = argv_find (argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL; - - /* Lookup AS list from AS path list. */ - aslist = as_list_lookup (aslistname); - if (aslist == NULL) - { - vty_out (vty, "ip as-path access-list %s doesn't exist\n",aslistname); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check the filter type. */ - if (argv_find (argv, argc, "permit", &idx)) - type = AS_FILTER_PERMIT; - else if (argv_find (argv, argc, "deny", &idx)) - type = AS_FILTER_DENY; - else - { - vty_out (vty, "filter type must be [permit|deny]\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Compile AS path. */ - argv_find (argv, argc, "LINE", &idx); - regstr = argv_concat(argv, argc, idx); - - regex = bgp_regcomp (regstr); - if (!regex) - { - vty_out (vty, "can't compile regexp %s\n", regstr); - XFREE (MTYPE_TMP, regstr); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Lookup asfilter. */ - asfilter = as_filter_lookup (aslist, regstr, type); - - XFREE (MTYPE_TMP, regstr); - bgp_regex_free (regex); - - if (asfilter == NULL) - { - vty_out (vty, "\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - as_list_filter_delete (aslist, asfilter); - - return CMD_SUCCESS; + int idx = 0; + enum as_filter_type type; + struct as_filter *asfilter; + struct as_list *aslist; + char *regstr; + regex_t *regex; + + char *aslistname = + argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL; + + /* Lookup AS list from AS path list. */ + aslist = as_list_lookup(aslistname); + if (aslist == NULL) { + vty_out(vty, "ip as-path access-list %s doesn't exist\n", + aslistname); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Check the filter type. */ + if (argv_find(argv, argc, "permit", &idx)) + type = AS_FILTER_PERMIT; + else if (argv_find(argv, argc, "deny", &idx)) + type = AS_FILTER_DENY; + else { + vty_out(vty, "filter type must be [permit|deny]\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Compile AS path. */ + argv_find(argv, argc, "LINE", &idx); + regstr = argv_concat(argv, argc, idx); + + regex = bgp_regcomp(regstr); + if (!regex) { + vty_out(vty, "can't compile regexp %s\n", regstr); + XFREE(MTYPE_TMP, regstr); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Lookup asfilter. */ + asfilter = as_filter_lookup(aslist, regstr, type); + + XFREE(MTYPE_TMP, regstr); + bgp_regex_free(regex); + + if (asfilter == NULL) { + vty_out(vty, "\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + as_list_filter_delete(aslist, asfilter); + + return CMD_SUCCESS; } DEFUN (no_ip_as_path_all, @@ -556,67 +520,63 @@ DEFUN (no_ip_as_path_all, "Specify an access list name\n" "Regular expression access list name\n") { - int idx_word = 4; - struct as_list *aslist; + int idx_word = 4; + struct as_list *aslist; - aslist = as_list_lookup (argv[idx_word]->arg); - if (aslist == NULL) - { - vty_out (vty, "ip as-path access-list %s doesn't exist\n", - argv[idx_word]->arg); - return CMD_WARNING_CONFIG_FAILED; - } + aslist = as_list_lookup(argv[idx_word]->arg); + if (aslist == NULL) { + vty_out(vty, "ip as-path access-list %s doesn't exist\n", + argv[idx_word]->arg); + return CMD_WARNING_CONFIG_FAILED; + } - as_list_delete (aslist); + as_list_delete(aslist); - /* Run hook function. */ - if (as_list_master.delete_hook) - (*as_list_master.delete_hook) (argv[idx_word]->arg); + /* Run hook function. */ + if (as_list_master.delete_hook) + (*as_list_master.delete_hook)(argv[idx_word]->arg); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static void -as_list_show (struct vty *vty, struct as_list *aslist) +static void as_list_show(struct vty *vty, struct as_list *aslist) { - struct as_filter *asfilter; + struct as_filter *asfilter; - vty_out (vty, "AS path access list %s\n", aslist->name); + vty_out(vty, "AS path access list %s\n", aslist->name); - for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) - { - vty_out (vty, " %s %s\n", filter_type_str (asfilter->type), - asfilter->reg_str); - } + for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) { + vty_out(vty, " %s %s\n", filter_type_str(asfilter->type), + asfilter->reg_str); + } } -static void -as_list_show_all (struct vty *vty) +static void as_list_show_all(struct vty *vty) { - struct as_list *aslist; - struct as_filter *asfilter; + struct as_list *aslist; + struct as_filter *asfilter; - for (aslist = as_list_master.num.head; aslist; aslist = aslist->next) - { - vty_out (vty, "AS path access list %s\n", aslist->name); + for (aslist = as_list_master.num.head; aslist; aslist = aslist->next) { + vty_out(vty, "AS path access list %s\n", aslist->name); - for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) - { - vty_out (vty, " %s %s\n", filter_type_str (asfilter->type), - asfilter->reg_str); + for (asfilter = aslist->head; asfilter; + asfilter = asfilter->next) { + vty_out(vty, " %s %s\n", + filter_type_str(asfilter->type), + asfilter->reg_str); + } } - } - for (aslist = as_list_master.str.head; aslist; aslist = aslist->next) - { - vty_out (vty, "AS path access list %s\n", aslist->name); + for (aslist = as_list_master.str.head; aslist; aslist = aslist->next) { + vty_out(vty, "AS path access list %s\n", aslist->name); - for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) - { - vty_out (vty, " %s %s\n", filter_type_str (asfilter->type), - asfilter->reg_str); + for (asfilter = aslist->head; asfilter; + asfilter = asfilter->next) { + vty_out(vty, " %s %s\n", + filter_type_str(asfilter->type), + asfilter->reg_str); + } } - } } DEFUN (show_ip_as_path_access_list, @@ -627,14 +587,14 @@ DEFUN (show_ip_as_path_access_list, "List AS path access lists\n" "AS path access list name\n") { - int idx_word = 3; - struct as_list *aslist; + int idx_word = 3; + struct as_list *aslist; - aslist = as_list_lookup (argv[idx_word]->arg); - if (aslist) - as_list_show (vty, aslist); + aslist = as_list_lookup(argv[idx_word]->arg); + if (aslist) + as_list_show(vty, aslist); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_as_path_access_list_all, @@ -644,79 +604,69 @@ DEFUN (show_ip_as_path_access_list_all, IP_STR "List AS path access lists\n") { - as_list_show_all (vty); - return CMD_SUCCESS; + as_list_show_all(vty); + return CMD_SUCCESS; } -static int -config_write_as_list (struct vty *vty) -{ - struct as_list *aslist; - struct as_filter *asfilter; - int write = 0; - - for (aslist = as_list_master.num.head; aslist; aslist = aslist->next) - for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) - { - vty_out (vty, "ip as-path access-list %s %s %s\n", - aslist->name, filter_type_str (asfilter->type), - asfilter->reg_str); - write++; - } - - for (aslist = as_list_master.str.head; aslist; aslist = aslist->next) - for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) - { - vty_out (vty, "ip as-path access-list %s %s %s\n", - aslist->name, filter_type_str (asfilter->type), - asfilter->reg_str); - write++; - } - return write; +static int config_write_as_list(struct vty *vty) +{ + struct as_list *aslist; + struct as_filter *asfilter; + int write = 0; + + for (aslist = as_list_master.num.head; aslist; aslist = aslist->next) + for (asfilter = aslist->head; asfilter; + asfilter = asfilter->next) { + vty_out(vty, "ip as-path access-list %s %s %s\n", + aslist->name, filter_type_str(asfilter->type), + asfilter->reg_str); + write++; + } + + for (aslist = as_list_master.str.head; aslist; aslist = aslist->next) + for (asfilter = aslist->head; asfilter; + asfilter = asfilter->next) { + vty_out(vty, "ip as-path access-list %s %s %s\n", + aslist->name, filter_type_str(asfilter->type), + asfilter->reg_str); + write++; + } + return write; } -static struct cmd_node as_list_node = -{ - AS_LIST_NODE, - "", - 1 -}; +static struct cmd_node as_list_node = {AS_LIST_NODE, "", 1}; /* Register functions. */ -void -bgp_filter_init (void) +void bgp_filter_init(void) { - install_node (&as_list_node, config_write_as_list); + install_node(&as_list_node, config_write_as_list); - install_element (CONFIG_NODE, &ip_as_path_cmd); - install_element (CONFIG_NODE, &no_ip_as_path_cmd); - install_element (CONFIG_NODE, &no_ip_as_path_all_cmd); + install_element(CONFIG_NODE, &ip_as_path_cmd); + install_element(CONFIG_NODE, &no_ip_as_path_cmd); + install_element(CONFIG_NODE, &no_ip_as_path_all_cmd); - install_element (VIEW_NODE, &show_ip_as_path_access_list_cmd); - install_element (VIEW_NODE, &show_ip_as_path_access_list_all_cmd); + install_element(VIEW_NODE, &show_ip_as_path_access_list_cmd); + install_element(VIEW_NODE, &show_ip_as_path_access_list_all_cmd); } -void -bgp_filter_reset (void) +void bgp_filter_reset(void) { - struct as_list *aslist; - struct as_list *next; - - for (aslist = as_list_master.num.head; aslist; aslist = next) - { - next = aslist->next; - as_list_delete (aslist); - } - - for (aslist = as_list_master.str.head; aslist; aslist = next) - { - next = aslist->next; - as_list_delete (aslist); - } - - assert (as_list_master.num.head == NULL); - assert (as_list_master.num.tail == NULL); - - assert (as_list_master.str.head == NULL); - assert (as_list_master.str.tail == NULL); + struct as_list *aslist; + struct as_list *next; + + for (aslist = as_list_master.num.head; aslist; aslist = next) { + next = aslist->next; + as_list_delete(aslist); + } + + for (aslist = as_list_master.str.head; aslist; aslist = next) { + next = aslist->next; + as_list_delete(aslist); + } + + assert(as_list_master.num.head == NULL); + assert(as_list_master.num.tail == NULL); + + assert(as_list_master.str.head == NULL); + assert(as_list_master.str.tail == NULL); } diff --git a/bgpd/bgp_filter.h b/bgpd/bgp_filter.h index e3ce7a1c1..e54372f8e 100644 --- a/bgpd/bgp_filter.h +++ b/bgpd/bgp_filter.h @@ -21,19 +21,15 @@ #ifndef _QUAGGA_BGP_FILTER_H #define _QUAGGA_BGP_FILTER_H -enum as_filter_type -{ - AS_FILTER_DENY, - AS_FILTER_PERMIT -}; +enum as_filter_type { AS_FILTER_DENY, AS_FILTER_PERMIT }; -extern void bgp_filter_init (void); -extern void bgp_filter_reset (void); +extern void bgp_filter_init(void); +extern void bgp_filter_reset(void); -extern enum as_filter_type as_list_apply (struct as_list *, void *); +extern enum as_filter_type as_list_apply(struct as_list *, void *); -extern struct as_list *as_list_lookup (const char *); -extern void as_list_add_hook (void (*func) (char *)); -extern void as_list_delete_hook (void (*func) (const char *)); +extern struct as_list *as_list_lookup(const char *); +extern void as_list_add_hook(void (*func)(char *)); +extern void as_list_delete_hook(void (*func)(const char *)); #endif /* _QUAGGA_BGP_FILTER_H */ diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 3610e6309..cf1cb1868 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -1,4 +1,4 @@ -/* BGP-4 Finite State Machine +/* BGP-4 Finite State Machine * From RFC1771 [A Border Gateway Protocol 4 (BGP-4)] * Copyright (C) 1996, 97, 98 Kunihiro Ishiguro * @@ -50,29 +50,28 @@ #include "bgpd/bgp_bfd.h" #include "bgpd/bgp_memory.h" -DEFINE_HOOK(peer_backward_transition, (struct peer *peer), (peer)) -DEFINE_HOOK(peer_established, (struct peer *peer), (peer)) +DEFINE_HOOK(peer_backward_transition, (struct peer * peer), (peer)) +DEFINE_HOOK(peer_established, (struct peer * peer), (peer)) /* Definition of display strings corresponding to FSM events. This should be * kept consistent with the events defined in bgpd.h */ -static const char *bgp_event_str[] = -{ - NULL, - "BGP_Start", - "BGP_Stop", - "TCP_connection_open", - "TCP_connection_closed", - "TCP_connection_open_failed", - "TCP_fatal_error", - "ConnectRetry_timer_expired", - "Hold_Timer_expired", - "KeepAlive_timer_expired", - "Receive_OPEN_message", - "Receive_KEEPALIVE_message", - "Receive_UPDATE_message", - "Receive_NOTIFICATION_message", - "Clearing_Completed", +static const char *bgp_event_str[] = { + NULL, + "BGP_Start", + "BGP_Stop", + "TCP_connection_open", + "TCP_connection_closed", + "TCP_connection_open_failed", + "TCP_fatal_error", + "ConnectRetry_timer_expired", + "Hold_Timer_expired", + "KeepAlive_timer_expired", + "Receive_OPEN_message", + "Receive_KEEPALIVE_message", + "Receive_UPDATE_message", + "Receive_NOTIFICATION_message", + "Clearing_Completed", }; /* BGP FSM (finite state machine) has three types of functions. Type @@ -81,1069 +80,1034 @@ static const char *bgp_event_str[] = function. */ /* BGP event function. */ -int bgp_event (struct thread *); +int bgp_event(struct thread *); /* BGP thread functions. */ -static int bgp_start_timer (struct thread *); -static int bgp_connect_timer (struct thread *); -static int bgp_holdtime_timer (struct thread *); -static int bgp_keepalive_timer (struct thread *); +static int bgp_start_timer(struct thread *); +static int bgp_connect_timer(struct thread *); +static int bgp_holdtime_timer(struct thread *); +static int bgp_keepalive_timer(struct thread *); /* BGP FSM functions. */ -static int bgp_start (struct peer *); +static int bgp_start(struct peer *); -static void -peer_xfer_stats (struct peer *peer_dst, struct peer *peer_src) +static void peer_xfer_stats(struct peer *peer_dst, struct peer *peer_src) { - /* Copy stats over. These are only the pre-established state stats */ - peer_dst->open_in += peer_src->open_in; - peer_dst->open_out += peer_src->open_out; - peer_dst->keepalive_in += peer_src->keepalive_in; - peer_dst->keepalive_out += peer_src->keepalive_out; - peer_dst->notify_in += peer_src->notify_in; - peer_dst->notify_out += peer_src->notify_out; - peer_dst->dynamic_cap_in += peer_src->dynamic_cap_in; - peer_dst->dynamic_cap_out += peer_src->dynamic_cap_out; + /* Copy stats over. These are only the pre-established state stats */ + peer_dst->open_in += peer_src->open_in; + peer_dst->open_out += peer_src->open_out; + peer_dst->keepalive_in += peer_src->keepalive_in; + peer_dst->keepalive_out += peer_src->keepalive_out; + peer_dst->notify_in += peer_src->notify_in; + peer_dst->notify_out += peer_src->notify_out; + peer_dst->dynamic_cap_in += peer_src->dynamic_cap_in; + peer_dst->dynamic_cap_out += peer_src->dynamic_cap_out; } -static struct peer * -peer_xfer_conn(struct peer *from_peer) +static struct peer *peer_xfer_conn(struct peer *from_peer) { - struct peer *peer; - afi_t afi; - safi_t safi; - int fd; - int status, pstatus; - unsigned char last_evt, last_maj_evt; - - assert(from_peer != NULL); - - peer = from_peer->doppelganger; - - if (!peer || !CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) - return from_peer; - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s: peer transfer %p fd %d -> %p fd %d)", from_peer->host, - from_peer, from_peer->fd, peer, peer->fd); - - BGP_WRITE_OFF(peer->t_write); - BGP_READ_OFF(peer->t_read); - BGP_WRITE_OFF(from_peer->t_write); - BGP_READ_OFF(from_peer->t_read); - - BGP_TIMER_OFF(peer->t_routeadv); - BGP_TIMER_OFF(from_peer->t_routeadv); - - fd = peer->fd; - peer->fd = from_peer->fd; - from_peer->fd = fd; - stream_reset(peer->ibuf); - stream_fifo_clean(peer->obuf); - stream_fifo_clean(from_peer->obuf); - - peer->as = from_peer->as; - peer->v_holdtime = from_peer->v_holdtime; - peer->v_keepalive = from_peer->v_keepalive; - peer->routeadv = from_peer->routeadv; - peer->v_routeadv = from_peer->v_routeadv; - peer->v_gr_restart = from_peer->v_gr_restart; - peer->cap = from_peer->cap; - status = peer->status; - pstatus = peer->ostatus; - last_evt = peer->last_event; - last_maj_evt = peer->last_major_event; - peer->status = from_peer->status; - peer->ostatus = from_peer->ostatus; - peer->last_event = from_peer->last_event; - peer->last_major_event = from_peer->last_major_event; - from_peer->status = status; - from_peer->ostatus = pstatus; - from_peer->last_event = last_evt; - from_peer->last_major_event = last_maj_evt; - peer->remote_id = from_peer->remote_id; - - if (from_peer->hostname != NULL) - { - if (peer->hostname) - { - XFREE(MTYPE_BGP_PEER_HOST, peer->hostname); - peer->hostname = NULL; - } - - peer->hostname = from_peer->hostname; - from_peer->hostname = NULL; - } - - if (from_peer->domainname != NULL) - { - if (peer->domainname) - { - XFREE(MTYPE_BGP_PEER_HOST, peer->domainname); - peer->domainname= NULL; - } - - peer->domainname = from_peer->domainname; - from_peer->domainname = NULL; - } - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - peer->af_flags[afi][safi] = from_peer->af_flags[afi][safi]; - peer->af_sflags[afi][safi] = from_peer->af_sflags[afi][safi]; - peer->af_cap[afi][safi] = from_peer->af_cap[afi][safi]; - peer->afc_nego[afi][safi] = from_peer->afc_nego[afi][safi]; - peer->afc_adv[afi][safi] = from_peer->afc_adv[afi][safi]; - peer->afc_recv[afi][safi] = from_peer->afc_recv[afi][safi]; - peer->orf_plist[afi][safi] = from_peer->orf_plist[afi][safi]; - } - - if (bgp_getsockname(peer) < 0) - { - zlog_err ("%%bgp_getsockname() failed for %s peer %s fd %d (from_peer fd %d)", - (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER) ? "accept" : ""), - peer->host, peer->fd, from_peer->fd); - bgp_stop(peer); - bgp_stop(from_peer); - return NULL; - } - if (from_peer->status > Active) - { - if (bgp_getsockname(from_peer) < 0) - { - zlog_err ("%%bgp_getsockname() failed for %s from_peer %s fd %d (peer fd %d)", - (CHECK_FLAG (from_peer->sflags, PEER_STATUS_ACCEPT_PEER) ? "accept" : ""), - from_peer->host, from_peer->fd, peer->fd); - bgp_stop(from_peer); - from_peer = NULL; - } - } - - BGP_READ_ON(peer->t_read, bgp_read, peer->fd); - BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd); - - if (from_peer) - peer_xfer_stats(peer, from_peer); - - return(peer); + struct peer *peer; + afi_t afi; + safi_t safi; + int fd; + int status, pstatus; + unsigned char last_evt, last_maj_evt; + + assert(from_peer != NULL); + + peer = from_peer->doppelganger; + + if (!peer || !CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) + return from_peer; + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s: peer transfer %p fd %d -> %p fd %d)", + from_peer->host, from_peer, from_peer->fd, peer, + peer->fd); + + BGP_WRITE_OFF(peer->t_write); + BGP_READ_OFF(peer->t_read); + BGP_WRITE_OFF(from_peer->t_write); + BGP_READ_OFF(from_peer->t_read); + + BGP_TIMER_OFF(peer->t_routeadv); + BGP_TIMER_OFF(from_peer->t_routeadv); + + fd = peer->fd; + peer->fd = from_peer->fd; + from_peer->fd = fd; + stream_reset(peer->ibuf); + stream_fifo_clean(peer->obuf); + stream_fifo_clean(from_peer->obuf); + + peer->as = from_peer->as; + peer->v_holdtime = from_peer->v_holdtime; + peer->v_keepalive = from_peer->v_keepalive; + peer->routeadv = from_peer->routeadv; + peer->v_routeadv = from_peer->v_routeadv; + peer->v_gr_restart = from_peer->v_gr_restart; + peer->cap = from_peer->cap; + status = peer->status; + pstatus = peer->ostatus; + last_evt = peer->last_event; + last_maj_evt = peer->last_major_event; + peer->status = from_peer->status; + peer->ostatus = from_peer->ostatus; + peer->last_event = from_peer->last_event; + peer->last_major_event = from_peer->last_major_event; + from_peer->status = status; + from_peer->ostatus = pstatus; + from_peer->last_event = last_evt; + from_peer->last_major_event = last_maj_evt; + peer->remote_id = from_peer->remote_id; + + if (from_peer->hostname != NULL) { + if (peer->hostname) { + XFREE(MTYPE_BGP_PEER_HOST, peer->hostname); + peer->hostname = NULL; + } + + peer->hostname = from_peer->hostname; + from_peer->hostname = NULL; + } + + if (from_peer->domainname != NULL) { + if (peer->domainname) { + XFREE(MTYPE_BGP_PEER_HOST, peer->domainname); + peer->domainname = NULL; + } + + peer->domainname = from_peer->domainname; + from_peer->domainname = NULL; + } + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + peer->af_flags[afi][safi] = + from_peer->af_flags[afi][safi]; + peer->af_sflags[afi][safi] = + from_peer->af_sflags[afi][safi]; + peer->af_cap[afi][safi] = from_peer->af_cap[afi][safi]; + peer->afc_nego[afi][safi] = + from_peer->afc_nego[afi][safi]; + peer->afc_adv[afi][safi] = + from_peer->afc_adv[afi][safi]; + peer->afc_recv[afi][safi] = + from_peer->afc_recv[afi][safi]; + peer->orf_plist[afi][safi] = + from_peer->orf_plist[afi][safi]; + } + + if (bgp_getsockname(peer) < 0) { + zlog_err( + "%%bgp_getsockname() failed for %s peer %s fd %d (from_peer fd %d)", + (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER) + ? "accept" + : ""), + peer->host, peer->fd, from_peer->fd); + bgp_stop(peer); + bgp_stop(from_peer); + return NULL; + } + if (from_peer->status > Active) { + if (bgp_getsockname(from_peer) < 0) { + zlog_err( + "%%bgp_getsockname() failed for %s from_peer %s fd %d (peer fd %d)", + (CHECK_FLAG(from_peer->sflags, + PEER_STATUS_ACCEPT_PEER) + ? "accept" + : ""), + from_peer->host, from_peer->fd, peer->fd); + bgp_stop(from_peer); + from_peer = NULL; + } + } + + BGP_READ_ON(peer->t_read, bgp_read, peer->fd); + BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd); + + if (from_peer) + peer_xfer_stats(peer, from_peer); + + return (peer); } /* Hook function called after bgp event is occered. And vty's neighbor command invoke this function after making neighbor structure. */ -void -bgp_timer_set (struct peer *peer) +void bgp_timer_set(struct peer *peer) { - switch (peer->status) - { - case Idle: - /* First entry point of peer's finite state machine. In Idle - status start timer is on unless peer is shutdown or peer is - inactive. All other timer must be turned off */ - if (BGP_PEER_START_SUPPRESSED (peer) || ! peer_active (peer)) - { - BGP_TIMER_OFF (peer->t_start); - } - else - { - BGP_TIMER_ON (peer->t_start, bgp_start_timer, - peer->v_start); - } - BGP_TIMER_OFF (peer->t_connect); - BGP_TIMER_OFF (peer->t_holdtime); - BGP_TIMER_OFF (peer->t_keepalive); - BGP_TIMER_OFF (peer->t_routeadv); - break; - - case Connect: - /* After start timer is expired, the peer moves to Connect - status. Make sure start timer is off and connect timer is - on. */ - BGP_TIMER_OFF (peer->t_start); - BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, peer->v_connect); - BGP_TIMER_OFF (peer->t_holdtime); - BGP_TIMER_OFF (peer->t_keepalive); - BGP_TIMER_OFF (peer->t_routeadv); - break; - - case Active: - /* Active is waiting connection from remote peer. And if - connect timer is expired, change status to Connect. */ - BGP_TIMER_OFF (peer->t_start); - /* If peer is passive mode, do not set connect timer. */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE) - || CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT)) - { - BGP_TIMER_OFF (peer->t_connect); + switch (peer->status) { + case Idle: + /* First entry point of peer's finite state machine. In Idle + status start timer is on unless peer is shutdown or peer is + inactive. All other timer must be turned off */ + if (BGP_PEER_START_SUPPRESSED(peer) || !peer_active(peer)) { + BGP_TIMER_OFF(peer->t_start); + } else { + BGP_TIMER_ON(peer->t_start, bgp_start_timer, + peer->v_start); + } + BGP_TIMER_OFF(peer->t_connect); + BGP_TIMER_OFF(peer->t_holdtime); + BGP_TIMER_OFF(peer->t_keepalive); + BGP_TIMER_OFF(peer->t_routeadv); + break; + + case Connect: + /* After start timer is expired, the peer moves to Connect + status. Make sure start timer is off and connect timer is + on. */ + BGP_TIMER_OFF(peer->t_start); + BGP_TIMER_ON(peer->t_connect, bgp_connect_timer, + peer->v_connect); + BGP_TIMER_OFF(peer->t_holdtime); + BGP_TIMER_OFF(peer->t_keepalive); + BGP_TIMER_OFF(peer->t_routeadv); + break; + + case Active: + /* Active is waiting connection from remote peer. And if + connect timer is expired, change status to Connect. */ + BGP_TIMER_OFF(peer->t_start); + /* If peer is passive mode, do not set connect timer. */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSIVE) + || CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) { + BGP_TIMER_OFF(peer->t_connect); + } else { + BGP_TIMER_ON(peer->t_connect, bgp_connect_timer, + peer->v_connect); + } + BGP_TIMER_OFF(peer->t_holdtime); + BGP_TIMER_OFF(peer->t_keepalive); + BGP_TIMER_OFF(peer->t_routeadv); + break; + + case OpenSent: + /* OpenSent status. */ + BGP_TIMER_OFF(peer->t_start); + BGP_TIMER_OFF(peer->t_connect); + if (peer->v_holdtime != 0) { + BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer, + peer->v_holdtime); + } else { + BGP_TIMER_OFF(peer->t_holdtime); + } + BGP_TIMER_OFF(peer->t_keepalive); + BGP_TIMER_OFF(peer->t_routeadv); + break; + + case OpenConfirm: + /* OpenConfirm status. */ + BGP_TIMER_OFF(peer->t_start); + BGP_TIMER_OFF(peer->t_connect); + + /* If the negotiated Hold Time value is zero, then the Hold Time + timer and KeepAlive timers are not started. */ + if (peer->v_holdtime == 0) { + BGP_TIMER_OFF(peer->t_holdtime); + BGP_TIMER_OFF(peer->t_keepalive); + } else { + BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer, + peer->v_holdtime); + BGP_TIMER_ON(peer->t_keepalive, bgp_keepalive_timer, + peer->v_keepalive); + } + BGP_TIMER_OFF(peer->t_routeadv); + break; + + case Established: + /* In Established status start and connect timer is turned + off. */ + BGP_TIMER_OFF(peer->t_start); + BGP_TIMER_OFF(peer->t_connect); + + /* Same as OpenConfirm, if holdtime is zero then both holdtime + and keepalive must be turned off. */ + if (peer->v_holdtime == 0) { + BGP_TIMER_OFF(peer->t_holdtime); + BGP_TIMER_OFF(peer->t_keepalive); + } else { + BGP_TIMER_ON(peer->t_holdtime, bgp_holdtime_timer, + peer->v_holdtime); + BGP_TIMER_ON(peer->t_keepalive, bgp_keepalive_timer, + peer->v_keepalive); + } + break; + case Deleted: + BGP_TIMER_OFF(peer->t_gr_restart); + BGP_TIMER_OFF(peer->t_gr_stale); + BGP_TIMER_OFF(peer->t_pmax_restart); + /* fallthru */ + case Clearing: + BGP_TIMER_OFF(peer->t_start); + BGP_TIMER_OFF(peer->t_connect); + BGP_TIMER_OFF(peer->t_holdtime); + BGP_TIMER_OFF(peer->t_keepalive); + BGP_TIMER_OFF(peer->t_routeadv); + break; } - else - { - BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, peer->v_connect); - } - BGP_TIMER_OFF (peer->t_holdtime); - BGP_TIMER_OFF (peer->t_keepalive); - BGP_TIMER_OFF (peer->t_routeadv); - break; - - case OpenSent: - /* OpenSent status. */ - BGP_TIMER_OFF (peer->t_start); - BGP_TIMER_OFF (peer->t_connect); - if (peer->v_holdtime != 0) - { - BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer, - peer->v_holdtime); - } - else - { - BGP_TIMER_OFF (peer->t_holdtime); - } - BGP_TIMER_OFF (peer->t_keepalive); - BGP_TIMER_OFF (peer->t_routeadv); - break; - - case OpenConfirm: - /* OpenConfirm status. */ - BGP_TIMER_OFF (peer->t_start); - BGP_TIMER_OFF (peer->t_connect); - - /* If the negotiated Hold Time value is zero, then the Hold Time - timer and KeepAlive timers are not started. */ - if (peer->v_holdtime == 0) - { - BGP_TIMER_OFF (peer->t_holdtime); - BGP_TIMER_OFF (peer->t_keepalive); - } - else - { - BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer, - peer->v_holdtime); - BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer, - peer->v_keepalive); - } - BGP_TIMER_OFF (peer->t_routeadv); - break; - - case Established: - /* In Established status start and connect timer is turned - off. */ - BGP_TIMER_OFF (peer->t_start); - BGP_TIMER_OFF (peer->t_connect); - - /* Same as OpenConfirm, if holdtime is zero then both holdtime - and keepalive must be turned off. */ - if (peer->v_holdtime == 0) - { - BGP_TIMER_OFF (peer->t_holdtime); - BGP_TIMER_OFF (peer->t_keepalive); - } - else - { - BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer, - peer->v_holdtime); - BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer, - peer->v_keepalive); - } - break; - case Deleted: - BGP_TIMER_OFF (peer->t_gr_restart); - BGP_TIMER_OFF (peer->t_gr_stale); - BGP_TIMER_OFF (peer->t_pmax_restart); - /* fallthru */ - case Clearing: - BGP_TIMER_OFF (peer->t_start); - BGP_TIMER_OFF (peer->t_connect); - BGP_TIMER_OFF (peer->t_holdtime); - BGP_TIMER_OFF (peer->t_keepalive); - BGP_TIMER_OFF (peer->t_routeadv); - break; - } } /* BGP start timer. This function set BGP_Start event to thread value and process event. */ -static int -bgp_start_timer (struct thread *thread) +static int bgp_start_timer(struct thread *thread) { - struct peer *peer; + struct peer *peer; - peer = THREAD_ARG (thread); - peer->t_start = NULL; + peer = THREAD_ARG(thread); + peer->t_start = NULL; - if (bgp_debug_neighbor_events(peer)) - zlog_debug("%s [FSM] Timer (start timer expire).", peer->host); + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s [FSM] Timer (start timer expire).", peer->host); - THREAD_VAL (thread) = BGP_Start; - bgp_event (thread); /* bgp_event unlocks peer */ + THREAD_VAL(thread) = BGP_Start; + bgp_event(thread); /* bgp_event unlocks peer */ - return 0; + return 0; } /* BGP connect retry timer. */ -static int -bgp_connect_timer (struct thread *thread) +static int bgp_connect_timer(struct thread *thread) { - struct peer *peer; - int ret; - - peer = THREAD_ARG (thread); - peer->t_connect = NULL; - - if (bgp_debug_neighbor_events(peer)) - zlog_debug("%s [FSM] Timer (connect timer expire)", peer->host); - - if (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) - { - bgp_stop(peer); - ret = -1; - } - else - { - THREAD_VAL (thread) = ConnectRetry_timer_expired; - bgp_event (thread); /* bgp_event unlocks peer */ - ret = 0; - } - - return ret; + struct peer *peer; + int ret; + + peer = THREAD_ARG(thread); + peer->t_connect = NULL; + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s [FSM] Timer (connect timer expire)", peer->host); + + if (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) { + bgp_stop(peer); + ret = -1; + } else { + THREAD_VAL(thread) = ConnectRetry_timer_expired; + bgp_event(thread); /* bgp_event unlocks peer */ + ret = 0; + } + + return ret; } /* BGP holdtime timer. */ -static int -bgp_holdtime_timer (struct thread *thread) +static int bgp_holdtime_timer(struct thread *thread) { - struct peer *peer; + struct peer *peer; - peer = THREAD_ARG (thread); - peer->t_holdtime = NULL; + peer = THREAD_ARG(thread); + peer->t_holdtime = NULL; - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s [FSM] Timer (holdtime timer expire)", peer->host); + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s [FSM] Timer (holdtime timer expire)", + peer->host); - THREAD_VAL (thread) = Hold_Timer_expired; - bgp_event (thread); /* bgp_event unlocks peer */ + THREAD_VAL(thread) = Hold_Timer_expired; + bgp_event(thread); /* bgp_event unlocks peer */ - return 0; + return 0; } /* BGP keepalive fire ! */ -static int -bgp_keepalive_timer (struct thread *thread) +static int bgp_keepalive_timer(struct thread *thread) { - struct peer *peer; + struct peer *peer; - peer = THREAD_ARG (thread); - peer->t_keepalive = NULL; + peer = THREAD_ARG(thread); + peer->t_keepalive = NULL; - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s [FSM] Timer (keepalive timer expire)", peer->host); + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s [FSM] Timer (keepalive timer expire)", + peer->host); - THREAD_VAL (thread) = KeepAlive_timer_expired; - bgp_event (thread); /* bgp_event unlocks peer */ + THREAD_VAL(thread) = KeepAlive_timer_expired; + bgp_event(thread); /* bgp_event unlocks peer */ - return 0; + return 0; } -int -bgp_routeadv_timer (struct thread *thread) +int bgp_routeadv_timer(struct thread *thread) { - struct peer *peer; + struct peer *peer; - peer = THREAD_ARG (thread); - peer->t_routeadv = NULL; + peer = THREAD_ARG(thread); + peer->t_routeadv = NULL; - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s [FSM] Timer (routeadv timer expire)", peer->host); + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s [FSM] Timer (routeadv timer expire)", + peer->host); - peer->synctime = bgp_clock (); + peer->synctime = bgp_clock(); - BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); + BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd); - /* MRAI timer will be started again when FIFO is built, no need to - * do it here. - */ - return 0; + /* MRAI timer will be started again when FIFO is built, no need to + * do it here. + */ + return 0; } /* BGP Peer Down Cause */ -const char *peer_down_str[] = +const char *peer_down_str[] = {"", + "Router ID changed", + "Remote AS changed", + "Local AS change", + "Cluster ID changed", + "Confederation identifier changed", + "Confederation peer changed", + "RR client config change", + "RS client config change", + "Update source change", + "Address family activated", + "Admin. shutdown", + "User reset", + "BGP Notification received", + "BGP Notification send", + "Peer closed the session", + "Neighbor deleted", + "Peer-group add member", + "Peer-group delete member", + "Capability changed", + "Passive config change", + "Multihop config change", + "NSF peer closed the session", + "Intf peering v6only config change", + "BFD down received", + "Interface down", + "Neighbor address lost"}; + +static int bgp_graceful_restart_timer_expire(struct thread *thread) { - "", - "Router ID changed", - "Remote AS changed", - "Local AS change", - "Cluster ID changed", - "Confederation identifier changed", - "Confederation peer changed", - "RR client config change", - "RS client config change", - "Update source change", - "Address family activated", - "Admin. shutdown", - "User reset", - "BGP Notification received", - "BGP Notification send", - "Peer closed the session", - "Neighbor deleted", - "Peer-group add member", - "Peer-group delete member", - "Capability changed", - "Passive config change", - "Multihop config change", - "NSF peer closed the session", - "Intf peering v6only config change", - "BFD down received", - "Interface down", - "Neighbor address lost" -}; - -static int -bgp_graceful_restart_timer_expire (struct thread *thread) -{ - struct peer *peer; - afi_t afi; - safi_t safi; - - peer = THREAD_ARG (thread); - peer->t_gr_restart = NULL; - - /* NSF delete stale route */ - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_4 ; safi++) - if (peer->nsf[afi][safi]) - bgp_clear_stale_route (peer, afi, safi); - - UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT); - BGP_TIMER_OFF (peer->t_gr_stale); - - if (bgp_debug_neighbor_events(peer)) - { - zlog_debug ("%s graceful restart timer expired", peer->host); - zlog_debug ("%s graceful restart stalepath timer stopped", peer->host); - } + struct peer *peer; + afi_t afi; + safi_t safi; + + peer = THREAD_ARG(thread); + peer->t_gr_restart = NULL; + + /* NSF delete stale route */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_RESERVED_4; safi++) + if (peer->nsf[afi][safi]) + bgp_clear_stale_route(peer, afi, safi); + + UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT); + BGP_TIMER_OFF(peer->t_gr_stale); + + if (bgp_debug_neighbor_events(peer)) { + zlog_debug("%s graceful restart timer expired", peer->host); + zlog_debug("%s graceful restart stalepath timer stopped", + peer->host); + } - bgp_timer_set (peer); + bgp_timer_set(peer); - return 0; + return 0; } -static int -bgp_graceful_stale_timer_expire (struct thread *thread) +static int bgp_graceful_stale_timer_expire(struct thread *thread) { - struct peer *peer; - afi_t afi; - safi_t safi; + struct peer *peer; + afi_t afi; + safi_t safi; - peer = THREAD_ARG (thread); - peer->t_gr_stale = NULL; + peer = THREAD_ARG(thread); + peer->t_gr_stale = NULL; - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s graceful restart stalepath timer expired", peer->host); + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s graceful restart stalepath timer expired", + peer->host); - /* NSF delete stale route */ - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_4 ; safi++) - if (peer->nsf[afi][safi]) - bgp_clear_stale_route (peer, afi, safi); + /* NSF delete stale route */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_RESERVED_4; safi++) + if (peer->nsf[afi][safi]) + bgp_clear_stale_route(peer, afi, safi); - return 0; + return 0; } -static int -bgp_update_delay_applicable (struct bgp *bgp) +static int bgp_update_delay_applicable(struct bgp *bgp) { - /* update_delay_over flag should be reset (set to 0) for any new - applicability of the update-delay during BGP process lifetime. - And it should be set after an occurence of the update-delay is over)*/ - if (!bgp->update_delay_over) - return 1; - - return 0; + /* update_delay_over flag should be reset (set to 0) for any new + applicability of the update-delay during BGP process lifetime. + And it should be set after an occurence of the update-delay is + over)*/ + if (!bgp->update_delay_over) + return 1; + + return 0; } -int -bgp_update_delay_active (struct bgp *bgp) +int bgp_update_delay_active(struct bgp *bgp) { - if (bgp->t_update_delay) - return 1; + if (bgp->t_update_delay) + return 1; - return 0; + return 0; } -int -bgp_update_delay_configured (struct bgp *bgp) +int bgp_update_delay_configured(struct bgp *bgp) { - if (bgp->v_update_delay) - return 1; + if (bgp->v_update_delay) + return 1; - return 0; + return 0; } /* Do the post-processing needed when bgp comes out of the read-only mode on ending the update delay. */ -void -bgp_update_delay_end (struct bgp *bgp) +void bgp_update_delay_end(struct bgp *bgp) { - THREAD_TIMER_OFF (bgp->t_update_delay); - THREAD_TIMER_OFF (bgp->t_establish_wait); - - /* Reset update-delay related state */ - bgp->update_delay_over = 1; - bgp->established = 0; - bgp->restarted_peers = 0; - bgp->implicit_eors = 0; - bgp->explicit_eors = 0; - - quagga_timestamp(3, bgp->update_delay_end_time, - sizeof(bgp->update_delay_end_time)); - - /* - * Add an end-of-initial-update marker to the main process queues so that - * the route advertisement timer for the peers can be started. Also set - * the zebra and peer update hold flags. These flags are used to achieve - * three stages in the update-delay post processing: - * 1. Finish best-path selection for all the prefixes held on the queues. - * (routes in BGP are updated, and peers sync queues are populated too) - * 2. As the eoiu mark is reached in the bgp process routine, ship all the - * routes to zebra. With that zebra should see updates from BGP close - * to each other. - * 3. Unblock the peer update writes. With that peer update packing with - * the prefixes should be at its maximum. - */ - bgp_add_eoiu_mark(bgp); - bgp->main_zebra_update_hold = 1; - bgp->main_peers_update_hold = 1; - - /* Resume the queue processing. This should trigger the event that would take - care of processing any work that was queued during the read-only mode. */ - work_queue_unplug(bm->process_main_queue); + THREAD_TIMER_OFF(bgp->t_update_delay); + THREAD_TIMER_OFF(bgp->t_establish_wait); + + /* Reset update-delay related state */ + bgp->update_delay_over = 1; + bgp->established = 0; + bgp->restarted_peers = 0; + bgp->implicit_eors = 0; + bgp->explicit_eors = 0; + + quagga_timestamp(3, bgp->update_delay_end_time, + sizeof(bgp->update_delay_end_time)); + + /* + * Add an end-of-initial-update marker to the main process queues so + * that + * the route advertisement timer for the peers can be started. Also set + * the zebra and peer update hold flags. These flags are used to achieve + * three stages in the update-delay post processing: + * 1. Finish best-path selection for all the prefixes held on the + * queues. + * (routes in BGP are updated, and peers sync queues are populated + * too) + * 2. As the eoiu mark is reached in the bgp process routine, ship all + * the + * routes to zebra. With that zebra should see updates from BGP + * close + * to each other. + * 3. Unblock the peer update writes. With that peer update packing + * with + * the prefixes should be at its maximum. + */ + bgp_add_eoiu_mark(bgp); + bgp->main_zebra_update_hold = 1; + bgp->main_peers_update_hold = 1; + + /* Resume the queue processing. This should trigger the event that would + take + care of processing any work that was queued during the read-only + mode. */ + work_queue_unplug(bm->process_main_queue); } /** * see bgp_fsm.h */ -void -bgp_start_routeadv (struct bgp *bgp) +void bgp_start_routeadv(struct bgp *bgp) { - struct listnode *node, *nnode; - struct peer *peer; + struct listnode *node, *nnode; + struct peer *peer; - zlog_info("bgp_start_routeadv(), update hold status %d", - bgp->main_peers_update_hold); + zlog_info("bgp_start_routeadv(), update hold status %d", + bgp->main_peers_update_hold); - if (bgp->main_peers_update_hold) - return; + if (bgp->main_peers_update_hold) + return; - quagga_timestamp(3, bgp->update_delay_peers_resume_time, - sizeof(bgp->update_delay_peers_resume_time)); + quagga_timestamp(3, bgp->update_delay_peers_resume_time, + sizeof(bgp->update_delay_peers_resume_time)); - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->status != Established) - continue; - BGP_TIMER_OFF(peer->t_routeadv); - BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0); - } + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (peer->status != Established) + continue; + BGP_TIMER_OFF(peer->t_routeadv); + BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0); + } } /** * see bgp_fsm.h */ -void -bgp_adjust_routeadv (struct peer *peer) +void bgp_adjust_routeadv(struct peer *peer) { - time_t nowtime = bgp_clock(); - double diff; - unsigned long remain; - - /* Bypass checks for special case of MRAI being 0 */ - if (peer->v_routeadv == 0) - { - /* Stop existing timer, just in case it is running for a different - * duration and schedule write thread immediately. - */ - if (peer->t_routeadv) - BGP_TIMER_OFF(peer->t_routeadv); - - peer->synctime = bgp_clock (); - BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); - return; - } - - - /* - * CASE I: - * If the last update was written more than MRAI back, expire the timer - * instantly so that we can send the update out sooner. - * - * <------- MRAI ---------> - * |-----------------|-----------------------| - * <------------- m ------------> - * ^ ^ ^ - * | | | - * | | current time - * | timer start - * last write - * - * m > MRAI - */ - diff = difftime(nowtime, peer->last_update); - if (diff > (double) peer->v_routeadv) - { - BGP_TIMER_OFF(peer->t_routeadv); - BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0); - return; - } - - /* - * CASE II: - * - Find when to expire the MRAI timer. - * If MRAI timer is not active, assume we can start it now. - * - * <------- MRAI ---------> - * |------------|-----------------------| - * <-------- m ----------><----- r -----> - * ^ ^ ^ - * | | | - * | | current time - * | timer start - * last write - * - * (MRAI - m) < r - */ - if (peer->t_routeadv) - remain = thread_timer_remain_second(peer->t_routeadv); - else - remain = peer->v_routeadv; - diff = peer->v_routeadv - diff; - if (diff <= (double) remain) - { - BGP_TIMER_OFF(peer->t_routeadv); - BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, diff); - } + time_t nowtime = bgp_clock(); + double diff; + unsigned long remain; + + /* Bypass checks for special case of MRAI being 0 */ + if (peer->v_routeadv == 0) { + /* Stop existing timer, just in case it is running for a + * different + * duration and schedule write thread immediately. + */ + if (peer->t_routeadv) + BGP_TIMER_OFF(peer->t_routeadv); + + peer->synctime = bgp_clock(); + BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd); + return; + } + + + /* + * CASE I: + * If the last update was written more than MRAI back, expire the timer + * instantly so that we can send the update out sooner. + * + * <------- MRAI ---------> + * |-----------------|-----------------------| + * <------------- m ------------> + * ^ ^ ^ + * | | | + * | | current time + * | timer start + * last write + * + * m > MRAI + */ + diff = difftime(nowtime, peer->last_update); + if (diff > (double)peer->v_routeadv) { + BGP_TIMER_OFF(peer->t_routeadv); + BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0); + return; + } + + /* + * CASE II: + * - Find when to expire the MRAI timer. + * If MRAI timer is not active, assume we can start it now. + * + * <------- MRAI ---------> + * |------------|-----------------------| + * <-------- m ----------><----- r -----> + * ^ ^ ^ + * | | | + * | | current time + * | timer start + * last write + * + * (MRAI - m) < r + */ + if (peer->t_routeadv) + remain = thread_timer_remain_second(peer->t_routeadv); + else + remain = peer->v_routeadv; + diff = peer->v_routeadv - diff; + if (diff <= (double)remain) { + BGP_TIMER_OFF(peer->t_routeadv); + BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, diff); + } } -static int -bgp_maxmed_onstartup_applicable (struct bgp *bgp) +static int bgp_maxmed_onstartup_applicable(struct bgp *bgp) { - if (!bgp->maxmed_onstartup_over) - return 1; + if (!bgp->maxmed_onstartup_over) + return 1; - return 0; + return 0; } -int -bgp_maxmed_onstartup_configured (struct bgp *bgp) +int bgp_maxmed_onstartup_configured(struct bgp *bgp) { - if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED) - return 1; + if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED) + return 1; - return 0; + return 0; } -int -bgp_maxmed_onstartup_active (struct bgp *bgp) +int bgp_maxmed_onstartup_active(struct bgp *bgp) { - if (bgp->t_maxmed_onstartup) - return 1; + if (bgp->t_maxmed_onstartup) + return 1; - return 0; + return 0; } -void -bgp_maxmed_update (struct bgp *bgp) +void bgp_maxmed_update(struct bgp *bgp) { - u_char maxmed_active; - u_int32_t maxmed_value; - - if (bgp->v_maxmed_admin) - { - maxmed_active = 1; - maxmed_value = bgp->maxmed_admin_value; - } - else if (bgp->t_maxmed_onstartup) - { - maxmed_active = 1; - maxmed_value = bgp->maxmed_onstartup_value; - } - else - { - maxmed_active = 0; - maxmed_value = BGP_MAXMED_VALUE_DEFAULT; - } - - if (bgp->maxmed_active != maxmed_active || - bgp->maxmed_value != maxmed_value) - { - bgp->maxmed_active = maxmed_active; - bgp->maxmed_value = maxmed_value; - - update_group_announce(bgp); - } + u_char maxmed_active; + u_int32_t maxmed_value; + + if (bgp->v_maxmed_admin) { + maxmed_active = 1; + maxmed_value = bgp->maxmed_admin_value; + } else if (bgp->t_maxmed_onstartup) { + maxmed_active = 1; + maxmed_value = bgp->maxmed_onstartup_value; + } else { + maxmed_active = 0; + maxmed_value = BGP_MAXMED_VALUE_DEFAULT; + } + + if (bgp->maxmed_active != maxmed_active + || bgp->maxmed_value != maxmed_value) { + bgp->maxmed_active = maxmed_active; + bgp->maxmed_value = maxmed_value; + + update_group_announce(bgp); + } } /* The maxmed onstartup timer expiry callback. */ -static int -bgp_maxmed_onstartup_timer (struct thread *thread) +static int bgp_maxmed_onstartup_timer(struct thread *thread) { - struct bgp *bgp; + struct bgp *bgp; - zlog_info ("Max med on startup ended - timer expired."); + zlog_info("Max med on startup ended - timer expired."); - bgp = THREAD_ARG (thread); - THREAD_TIMER_OFF (bgp->t_maxmed_onstartup); - bgp->maxmed_onstartup_over = 1; + bgp = THREAD_ARG(thread); + THREAD_TIMER_OFF(bgp->t_maxmed_onstartup); + bgp->maxmed_onstartup_over = 1; - bgp_maxmed_update(bgp); + bgp_maxmed_update(bgp); - return 0; + return 0; } -static void -bgp_maxmed_onstartup_begin (struct bgp *bgp) +static void bgp_maxmed_onstartup_begin(struct bgp *bgp) { - /* Applicable only once in the process lifetime on the startup */ - if (bgp->maxmed_onstartup_over) - return; + /* Applicable only once in the process lifetime on the startup */ + if (bgp->maxmed_onstartup_over) + return; - zlog_info ("Begin maxmed onstartup mode - timer %d seconds", - bgp->v_maxmed_onstartup); + zlog_info("Begin maxmed onstartup mode - timer %d seconds", + bgp->v_maxmed_onstartup); - thread_add_timer(bm->master, bgp_maxmed_onstartup_timer, bgp, - bgp->v_maxmed_onstartup, &bgp->t_maxmed_onstartup); + thread_add_timer(bm->master, bgp_maxmed_onstartup_timer, bgp, + bgp->v_maxmed_onstartup, &bgp->t_maxmed_onstartup); - if (!bgp->v_maxmed_admin) - { - bgp->maxmed_active = 1; - bgp->maxmed_value = bgp->maxmed_onstartup_value; - } + if (!bgp->v_maxmed_admin) { + bgp->maxmed_active = 1; + bgp->maxmed_value = bgp->maxmed_onstartup_value; + } - /* Route announce to all peers should happen after this in bgp_establish() */ + /* Route announce to all peers should happen after this in + * bgp_establish() */ } -static void -bgp_maxmed_onstartup_process_status_change(struct peer *peer) +static void bgp_maxmed_onstartup_process_status_change(struct peer *peer) { - if (peer->status == Established && !peer->bgp->established) - { - bgp_maxmed_onstartup_begin(peer->bgp); - } + if (peer->status == Established && !peer->bgp->established) { + bgp_maxmed_onstartup_begin(peer->bgp); + } } /* The update delay timer expiry callback. */ -static int -bgp_update_delay_timer (struct thread *thread) +static int bgp_update_delay_timer(struct thread *thread) { - struct bgp *bgp; + struct bgp *bgp; - zlog_info ("Update delay ended - timer expired."); + zlog_info("Update delay ended - timer expired."); - bgp = THREAD_ARG (thread); - THREAD_TIMER_OFF (bgp->t_update_delay); - bgp_update_delay_end(bgp); + bgp = THREAD_ARG(thread); + THREAD_TIMER_OFF(bgp->t_update_delay); + bgp_update_delay_end(bgp); - return 0; + return 0; } /* The establish wait timer expiry callback. */ -static int -bgp_establish_wait_timer (struct thread *thread) +static int bgp_establish_wait_timer(struct thread *thread) { - struct bgp *bgp; + struct bgp *bgp; - zlog_info ("Establish wait - timer expired."); + zlog_info("Establish wait - timer expired."); - bgp = THREAD_ARG (thread); - THREAD_TIMER_OFF (bgp->t_establish_wait); - bgp_check_update_delay(bgp); + bgp = THREAD_ARG(thread); + THREAD_TIMER_OFF(bgp->t_establish_wait); + bgp_check_update_delay(bgp); - return 0; + return 0; } /* Steps to begin the update delay: - initialize queues if needed - stop the queue processing - start the timer */ -static void -bgp_update_delay_begin (struct bgp *bgp) +static void bgp_update_delay_begin(struct bgp *bgp) { - struct listnode *node, *nnode; - struct peer *peer; + struct listnode *node, *nnode; + struct peer *peer; - /* Stop the processing of queued work. Enqueue shall continue */ - work_queue_plug(bm->process_main_queue); + /* Stop the processing of queued work. Enqueue shall continue */ + work_queue_plug(bm->process_main_queue); - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - peer->update_delay_over = 0; + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) + peer->update_delay_over = 0; - /* Start the update-delay timer */ - thread_add_timer(bm->master, bgp_update_delay_timer, bgp, - bgp->v_update_delay, &bgp->t_update_delay); + /* Start the update-delay timer */ + thread_add_timer(bm->master, bgp_update_delay_timer, bgp, + bgp->v_update_delay, &bgp->t_update_delay); - if (bgp->v_establish_wait != bgp->v_update_delay) - thread_add_timer(bm->master, bgp_establish_wait_timer, bgp, - bgp->v_establish_wait, &bgp->t_establish_wait); + if (bgp->v_establish_wait != bgp->v_update_delay) + thread_add_timer(bm->master, bgp_establish_wait_timer, bgp, + bgp->v_establish_wait, &bgp->t_establish_wait); - quagga_timestamp(3, bgp->update_delay_begin_time, - sizeof(bgp->update_delay_begin_time)); + quagga_timestamp(3, bgp->update_delay_begin_time, + sizeof(bgp->update_delay_begin_time)); } -static void -bgp_update_delay_process_status_change(struct peer *peer) +static void bgp_update_delay_process_status_change(struct peer *peer) { - if (peer->status == Established) - { - if (!peer->bgp->established++) - { - bgp_update_delay_begin(peer->bgp); - zlog_info ("Begin read-only mode - update-delay timer %d seconds", - peer->bgp->v_update_delay); - } - if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV)) - bgp_update_restarted_peers(peer); - } - if (peer->ostatus == Established && bgp_update_delay_active(peer->bgp)) - { - /* Adjust the update-delay state to account for this flap. - NOTE: Intentionally skipping adjusting implicit_eors or explicit_eors - counters. Extra sanity check in bgp_check_update_delay() should - be enough to take care of any additive discrepancy in bgp eor - counters */ - peer->bgp->established--; - peer->update_delay_over = 0; - } + if (peer->status == Established) { + if (!peer->bgp->established++) { + bgp_update_delay_begin(peer->bgp); + zlog_info( + "Begin read-only mode - update-delay timer %d seconds", + peer->bgp->v_update_delay); + } + if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_BIT_RCV)) + bgp_update_restarted_peers(peer); + } + if (peer->ostatus == Established + && bgp_update_delay_active(peer->bgp)) { + /* Adjust the update-delay state to account for this flap. + NOTE: Intentionally skipping adjusting implicit_eors or + explicit_eors + counters. Extra sanity check in bgp_check_update_delay() + should + be enough to take care of any additive discrepancy in bgp eor + counters */ + peer->bgp->established--; + peer->update_delay_over = 0; + } } /* Called after event occured, this function change status and reset read/write and timer thread. */ -void -bgp_fsm_change_status (struct peer *peer, int status) +void bgp_fsm_change_status(struct peer *peer, int status) { - bgp_dump_state (peer, peer->status, status); - - /* Transition into Clearing or Deleted must /always/ clear all routes.. - * (and must do so before actually changing into Deleted.. - */ - if (status >= Clearing) - { - bgp_clear_route_all (peer); - - /* If no route was queued for the clear-node processing, generate the - * completion event here. This is needed because if there are no routes - * to trigger the background clear-node thread, the event won't get - * generated and the peer would be stuck in Clearing. Note that this - * event is for the peer and helps the peer transition out of Clearing - * state; it should not be generated per (AFI,SAFI). The event is - * directly posted here without calling clear_node_complete() as we - * shouldn't do an extra unlock. This event will get processed after - * the state change that happens below, so peer will be in Clearing - * (or Deleted). - */ - if (!work_queue_is_scheduled (peer->clear_node_queue)) - BGP_EVENT_ADD (peer, Clearing_Completed); - } - - /* Preserve old status and change into new status. */ - peer->ostatus = peer->status; - peer->status = status; - - /* Save event that caused status change. */ - peer->last_major_event = peer->cur_event; - - if (status == Established) - UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER); - - /* If max-med processing is applicable, do the necessary. */ - if (status == Established) - { - if (bgp_maxmed_onstartup_configured(peer->bgp) && - bgp_maxmed_onstartup_applicable(peer->bgp)) - bgp_maxmed_onstartup_process_status_change(peer); - else - peer->bgp->maxmed_onstartup_over = 1; - } - - /* If update-delay processing is applicable, do the necessary. */ - if (bgp_update_delay_configured(peer->bgp) && - bgp_update_delay_applicable(peer->bgp)) - bgp_update_delay_process_status_change(peer); - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s went from %s to %s", - peer->host, - lookup_msg(bgp_status_msg, peer->ostatus, NULL), - lookup_msg(bgp_status_msg, peer->status, NULL)); + bgp_dump_state(peer, peer->status, status); + + /* Transition into Clearing or Deleted must /always/ clear all routes.. + * (and must do so before actually changing into Deleted.. + */ + if (status >= Clearing) { + bgp_clear_route_all(peer); + + /* If no route was queued for the clear-node processing, + * generate the + * completion event here. This is needed because if there are no + * routes + * to trigger the background clear-node thread, the event won't + * get + * generated and the peer would be stuck in Clearing. Note that + * this + * event is for the peer and helps the peer transition out of + * Clearing + * state; it should not be generated per (AFI,SAFI). The event + * is + * directly posted here without calling clear_node_complete() as + * we + * shouldn't do an extra unlock. This event will get processed + * after + * the state change that happens below, so peer will be in + * Clearing + * (or Deleted). + */ + if (!work_queue_is_scheduled(peer->clear_node_queue)) + BGP_EVENT_ADD(peer, Clearing_Completed); + } + + /* Preserve old status and change into new status. */ + peer->ostatus = peer->status; + peer->status = status; + + /* Save event that caused status change. */ + peer->last_major_event = peer->cur_event; + + if (status == Established) + UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER); + + /* If max-med processing is applicable, do the necessary. */ + if (status == Established) { + if (bgp_maxmed_onstartup_configured(peer->bgp) + && bgp_maxmed_onstartup_applicable(peer->bgp)) + bgp_maxmed_onstartup_process_status_change(peer); + else + peer->bgp->maxmed_onstartup_over = 1; + } + + /* If update-delay processing is applicable, do the necessary. */ + if (bgp_update_delay_configured(peer->bgp) + && bgp_update_delay_applicable(peer->bgp)) + bgp_update_delay_process_status_change(peer); + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s went from %s to %s", peer->host, + lookup_msg(bgp_status_msg, peer->ostatus, NULL), + lookup_msg(bgp_status_msg, peer->status, NULL)); } /* Flush the event queue and ensure the peer is shut down */ -static int -bgp_clearing_completed (struct peer *peer) +static int bgp_clearing_completed(struct peer *peer) { - int rc = bgp_stop(peer); + int rc = bgp_stop(peer); - if (rc >= 0) - BGP_EVENT_FLUSH (peer); + if (rc >= 0) + BGP_EVENT_FLUSH(peer); - return rc; + return rc; } /* Administrative BGP peer stop event. */ /* May be called multiple times for the same peer */ -int -bgp_stop (struct peer *peer) +int bgp_stop(struct peer *peer) { - afi_t afi; - safi_t safi; - char orf_name[BUFSIZ]; - int ret = 0; - - if (peer_dynamic_neighbor(peer) && - !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s (dynamic neighbor) deleted", peer->host); - peer_delete (peer); - return -1; - } - - /* Can't do this in Clearing; events are used for state transitions */ - if (peer->status != Clearing) - { - /* Delete all existing events of the peer */ - BGP_EVENT_FLUSH (peer); - } - - /* Increment Dropped count. */ - if (peer->status == Established) - { - peer->dropped++; - - /* bgp log-neighbor-changes of neighbor Down */ - if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES)) - { - struct vrf *vrf = vrf_lookup_by_id (peer->bgp->vrf_id); - zlog_info ("%%ADJCHANGE: neighbor %s(%s) in vrf %s Down %s", - peer->host, - (peer->hostname) ? peer->hostname : "Unknown", - vrf ? ((vrf->vrf_id != VRF_DEFAULT) ? vrf->name : "Default") : "", - peer_down_str [(int) peer->last_reset]); + afi_t afi; + safi_t safi; + char orf_name[BUFSIZ]; + int ret = 0; + + if (peer_dynamic_neighbor(peer) + && !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s (dynamic neighbor) deleted", peer->host); + peer_delete(peer); + return -1; } - /* graceful restart */ - if (peer->t_gr_stale) - { - BGP_TIMER_OFF (peer->t_gr_stale); - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s graceful restart stalepath timer stopped", peer->host); + /* Can't do this in Clearing; events are used for state transitions */ + if (peer->status != Clearing) { + /* Delete all existing events of the peer */ + BGP_EVENT_FLUSH(peer); } - if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT)) - { - if (bgp_debug_neighbor_events(peer)) - { - zlog_debug ("%s graceful restart timer started for %d sec", - peer->host, peer->v_gr_restart); - zlog_debug ("%s graceful restart stalepath timer started for %d sec", - peer->host, peer->bgp->stalepath_time); - } - BGP_TIMER_ON (peer->t_gr_restart, bgp_graceful_restart_timer_expire, - peer->v_gr_restart); - BGP_TIMER_ON (peer->t_gr_stale, bgp_graceful_stale_timer_expire, - peer->bgp->stalepath_time); + + /* Increment Dropped count. */ + if (peer->status == Established) { + peer->dropped++; + + /* bgp log-neighbor-changes of neighbor Down */ + if (bgp_flag_check(peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES)) { + struct vrf *vrf = vrf_lookup_by_id(peer->bgp->vrf_id); + zlog_info( + "%%ADJCHANGE: neighbor %s(%s) in vrf %s Down %s", + peer->host, + (peer->hostname) ? peer->hostname : "Unknown", + vrf ? ((vrf->vrf_id != VRF_DEFAULT) ? vrf->name + : "Default") + : "", + peer_down_str[(int)peer->last_reset]); + } + + /* graceful restart */ + if (peer->t_gr_stale) { + BGP_TIMER_OFF(peer->t_gr_stale); + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s graceful restart stalepath timer stopped", + peer->host); + } + if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) { + if (bgp_debug_neighbor_events(peer)) { + zlog_debug( + "%s graceful restart timer started for %d sec", + peer->host, peer->v_gr_restart); + zlog_debug( + "%s graceful restart stalepath timer started for %d sec", + peer->host, peer->bgp->stalepath_time); + } + BGP_TIMER_ON(peer->t_gr_restart, + bgp_graceful_restart_timer_expire, + peer->v_gr_restart); + BGP_TIMER_ON(peer->t_gr_stale, + bgp_graceful_stale_timer_expire, + peer->bgp->stalepath_time); + } else { + UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; + safi < SAFI_RESERVED_4; safi++) + peer->nsf[afi][safi] = 0; + } + + /* set last reset time */ + peer->resettime = peer->uptime = bgp_clock(); + + if (BGP_DEBUG(update_groups, UPDATE_GROUPS)) + zlog_debug("%s remove from all update group", + peer->host); + update_group_remove_peer_afs(peer); + + hook_call(peer_backward_transition, peer); + + /* Reset peer synctime */ + peer->synctime = 0; + + bgp_bfd_deregister_peer(peer); } - else - { - UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE); - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_4 ; safi++) - peer->nsf[afi][safi] = 0; + /* Stop read and write threads when exists. */ + BGP_READ_OFF(peer->t_read); + BGP_WRITE_OFF(peer->t_write); + + /* Stop all timers. */ + BGP_TIMER_OFF(peer->t_start); + BGP_TIMER_OFF(peer->t_connect); + BGP_TIMER_OFF(peer->t_holdtime); + BGP_TIMER_OFF(peer->t_keepalive); + BGP_TIMER_OFF(peer->t_routeadv); + + /* Stream reset. */ + peer->packet_size = 0; + + /* Clear input and output buffer. */ + if (peer->ibuf) + stream_reset(peer->ibuf); + if (peer->work) + stream_reset(peer->work); + if (peer->obuf) + stream_fifo_clean(peer->obuf); + + /* Close of file descriptor. */ + if (peer->fd >= 0) { + close(peer->fd); + peer->fd = -1; } - /* set last reset time */ - peer->resettime = peer->uptime = bgp_clock (); - - if (BGP_DEBUG (update_groups, UPDATE_GROUPS)) - zlog_debug ("%s remove from all update group", peer->host); - update_group_remove_peer_afs(peer); - - hook_call(peer_backward_transition, peer); - - /* Reset peer synctime */ - peer->synctime = 0; - - bgp_bfd_deregister_peer(peer); - } - - /* Stop read and write threads when exists. */ - BGP_READ_OFF (peer->t_read); - BGP_WRITE_OFF (peer->t_write); - - /* Stop all timers. */ - BGP_TIMER_OFF (peer->t_start); - BGP_TIMER_OFF (peer->t_connect); - BGP_TIMER_OFF (peer->t_holdtime); - BGP_TIMER_OFF (peer->t_keepalive); - BGP_TIMER_OFF (peer->t_routeadv); - - /* Stream reset. */ - peer->packet_size = 0; - - /* Clear input and output buffer. */ - if (peer->ibuf) - stream_reset (peer->ibuf); - if (peer->work) - stream_reset (peer->work); - if (peer->obuf) - stream_fifo_clean (peer->obuf); - - /* Close of file descriptor. */ - if (peer->fd >= 0) - { - close (peer->fd); - peer->fd = -1; - } - - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - /* Reset all negotiated variables */ - peer->afc_nego[afi][safi] = 0; - peer->afc_adv[afi][safi] = 0; - peer->afc_recv[afi][safi] = 0; - - /* peer address family capability flags*/ - peer->af_cap[afi][safi] = 0; - - /* peer address family status flags*/ - peer->af_sflags[afi][safi] = 0; - - /* Received ORF prefix-filter */ - peer->orf_plist[afi][safi] = NULL; - - if ((peer->status == OpenConfirm) || (peer->status == Established)) { - /* ORF received prefix-filter pnt */ - sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi); - prefix_bgp_orf_remove_all (afi, orf_name); + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + /* Reset all negotiated variables */ + peer->afc_nego[afi][safi] = 0; + peer->afc_adv[afi][safi] = 0; + peer->afc_recv[afi][safi] = 0; + + /* peer address family capability flags*/ + peer->af_cap[afi][safi] = 0; + + /* peer address family status flags*/ + peer->af_sflags[afi][safi] = 0; + + /* Received ORF prefix-filter */ + peer->orf_plist[afi][safi] = NULL; + + if ((peer->status == OpenConfirm) + || (peer->status == Established)) { + /* ORF received prefix-filter pnt */ + sprintf(orf_name, "%s.%d.%d", peer->host, afi, + safi); + prefix_bgp_orf_remove_all(afi, orf_name); + } + } + + /* Reset keepalive and holdtime */ + if (CHECK_FLAG(peer->config, PEER_CONFIG_TIMER)) { + peer->v_keepalive = peer->keepalive; + peer->v_holdtime = peer->holdtime; + } else { + peer->v_keepalive = peer->bgp->default_keepalive; + peer->v_holdtime = peer->bgp->default_holdtime; } - } - - /* Reset keepalive and holdtime */ - if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)) - { - peer->v_keepalive = peer->keepalive; - peer->v_holdtime = peer->holdtime; - } - else - { - peer->v_keepalive = peer->bgp->default_keepalive; - peer->v_holdtime = peer->bgp->default_holdtime; - } - - peer->update_time = 0; - - /* Until we are sure that there is no problem about prefix count - this should be commented out.*/ + + peer->update_time = 0; + +/* Until we are sure that there is no problem about prefix count + this should be commented out.*/ #if 0 /* Reset prefix count */ peer->pcount[AFI_IP][SAFI_UNICAST] = 0; @@ -1155,731 +1119,722 @@ bgp_stop (struct peer *peer) peer->pcount[AFI_IP6][SAFI_LABELED_UNICAST] = 0; #endif /* 0 */ - if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE) && - !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) - { - peer_delete(peer); - ret = -1; - } - else - { - bgp_peer_conf_if_to_su_update(peer); - } - - return ret; + if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE) + && !(CHECK_FLAG(peer->flags, PEER_FLAG_DELETE))) { + peer_delete(peer); + ret = -1; + } else { + bgp_peer_conf_if_to_su_update(peer); + } + + return ret; } /* BGP peer is stoped by the error. */ -static int -bgp_stop_with_error (struct peer *peer) +static int bgp_stop_with_error(struct peer *peer) { - /* Double start timer. */ - peer->v_start *= 2; - - /* Overflow check. */ - if (peer->v_start >= (60 * 2)) - peer->v_start = (60 * 2); - - if (peer_dynamic_neighbor(peer)) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s (dynamic neighbor) deleted", peer->host); - peer_delete (peer); - return -1; - } - - return(bgp_stop (peer)); + /* Double start timer. */ + peer->v_start *= 2; + + /* Overflow check. */ + if (peer->v_start >= (60 * 2)) + peer->v_start = (60 * 2); + + if (peer_dynamic_neighbor(peer)) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s (dynamic neighbor) deleted", peer->host); + peer_delete(peer); + return -1; + } + + return (bgp_stop(peer)); } /* something went wrong, send notify and tear down */ -static int -bgp_stop_with_notify (struct peer *peer, u_char code, u_char sub_code) +static int bgp_stop_with_notify(struct peer *peer, u_char code, u_char sub_code) { - /* Send notify to remote peer */ - bgp_notify_send (peer, code, sub_code); - - if (peer_dynamic_neighbor(peer)) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s (dynamic neighbor) deleted", peer->host); - peer_delete (peer); - return -1; - } + /* Send notify to remote peer */ + bgp_notify_send(peer, code, sub_code); + + if (peer_dynamic_neighbor(peer)) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s (dynamic neighbor) deleted", peer->host); + peer_delete(peer); + return -1; + } - /* Clear start timer value to default. */ - peer->v_start = BGP_INIT_START_TIMER; + /* Clear start timer value to default. */ + peer->v_start = BGP_INIT_START_TIMER; - return(bgp_stop(peer)); + return (bgp_stop(peer)); } /* TCP connection open. Next we send open message to remote peer. And add read thread for reading open message. */ -static int -bgp_connect_success (struct peer *peer) +static int bgp_connect_success(struct peer *peer) { - if (peer->fd < 0) - { - zlog_err ("bgp_connect_success peer's fd is negative value %d", - peer->fd); - bgp_stop(peer); - return -1; - } - - if (bgp_getsockname (peer) < 0) - { - zlog_err ("%s: bgp_getsockname(): failed for peer %s, fd %d", __FUNCTION__, - peer->host, peer->fd); - bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, 0); /* internal error */ - return -1; - } - - BGP_READ_ON (peer->t_read, bgp_read, peer->fd); - - if (bgp_debug_neighbor_events(peer)) - { - char buf1[SU_ADDRSTRLEN]; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) - zlog_debug ("%s open active, local address %s", peer->host, - sockunion2str (peer->su_local, buf1, SU_ADDRSTRLEN)); - else - zlog_debug ("%s passive open", peer->host); - } - - bgp_open_send (peer); - - return 0; + if (peer->fd < 0) { + zlog_err("bgp_connect_success peer's fd is negative value %d", + peer->fd); + bgp_stop(peer); + return -1; + } + + if (bgp_getsockname(peer) < 0) { + zlog_err("%s: bgp_getsockname(): failed for peer %s, fd %d", + __FUNCTION__, peer->host, peer->fd); + bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, + 0); /* internal error */ + return -1; + } + + BGP_READ_ON(peer->t_read, bgp_read, peer->fd); + + if (bgp_debug_neighbor_events(peer)) { + char buf1[SU_ADDRSTRLEN]; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) + zlog_debug("%s open active, local address %s", + peer->host, + sockunion2str(peer->su_local, buf1, + SU_ADDRSTRLEN)); + else + zlog_debug("%s passive open", peer->host); + } + + bgp_open_send(peer); + + return 0; } /* TCP connect fail */ -static int -bgp_connect_fail (struct peer *peer) +static int bgp_connect_fail(struct peer *peer) { - if (peer_dynamic_neighbor(peer)) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s (dynamic neighbor) deleted", peer->host); - peer_delete (peer); - return -1; - } - - return (bgp_stop (peer)); + if (peer_dynamic_neighbor(peer)) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s (dynamic neighbor) deleted", peer->host); + peer_delete(peer); + return -1; + } + + return (bgp_stop(peer)); } /* This function is the first starting point of all BGP connection. It try to connect to remote peer with non-blocking IO. */ -int -bgp_start (struct peer *peer) +int bgp_start(struct peer *peer) { - int status; - int connected = 0; - - bgp_peer_conf_if_to_su_update(peer); - - if (peer->su.sa.sa_family == AF_UNSPEC) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s [FSM] Unable to get neighbor's IP address, waiting...", - peer->host); - return -1; - } - - if (BGP_PEER_START_SUPPRESSED (peer)) - { - if (bgp_debug_neighbor_events(peer)) - zlog_err ("%s [FSM] Trying to start suppressed peer" - " - this is never supposed to happen!", peer->host); - return -1; - } - - /* Scrub some information that might be left over from a previous, - * session - */ - /* Connection information. */ - if (peer->su_local) - { - sockunion_free (peer->su_local); - peer->su_local = NULL; - } - - if (peer->su_remote) - { - sockunion_free (peer->su_remote); - peer->su_remote = NULL; - } - - /* Clear remote router-id. */ - peer->remote_id.s_addr = 0; - - /* Clear peer capability flag. */ - peer->cap = 0; - - /* If the peer is passive mode, force to move to Active mode. */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE)) - { - BGP_EVENT_ADD (peer, TCP_connection_open_failed); - return 0; - } - - /* Register to be notified on peer up */ - if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 && - ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) - && ! bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) - connected = 1; - else - connected = 0; - - if (!bgp_find_or_add_nexthop(peer->bgp, family2afi(peer->su.sa.sa_family), - NULL, peer, connected)) - { -#if defined (HAVE_CUMULUS) - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s [FSM] Waiting for NHT", peer->host); - - BGP_EVENT_ADD(peer, TCP_connection_open_failed); - return 0; + int status; + int connected = 0; + + bgp_peer_conf_if_to_su_update(peer); + + if (peer->su.sa.sa_family == AF_UNSPEC) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s [FSM] Unable to get neighbor's IP address, waiting...", + peer->host); + return -1; + } + + if (BGP_PEER_START_SUPPRESSED(peer)) { + if (bgp_debug_neighbor_events(peer)) + zlog_err( + "%s [FSM] Trying to start suppressed peer" + " - this is never supposed to happen!", + peer->host); + return -1; + } + + /* Scrub some information that might be left over from a previous, + * session + */ + /* Connection information. */ + if (peer->su_local) { + sockunion_free(peer->su_local); + peer->su_local = NULL; + } + + if (peer->su_remote) { + sockunion_free(peer->su_remote); + peer->su_remote = NULL; + } + + /* Clear remote router-id. */ + peer->remote_id.s_addr = 0; + + /* Clear peer capability flag. */ + peer->cap = 0; + + /* If the peer is passive mode, force to move to Active mode. */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSIVE)) { + BGP_EVENT_ADD(peer, TCP_connection_open_failed); + return 0; + } + + /* Register to be notified on peer up */ + if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 + && !CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) + && !bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) + connected = 1; + else + connected = 0; + + if (!bgp_find_or_add_nexthop(peer->bgp, + family2afi(peer->su.sa.sa_family), NULL, + peer, connected)) { +#if defined(HAVE_CUMULUS) + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s [FSM] Waiting for NHT", peer->host); + + BGP_EVENT_ADD(peer, TCP_connection_open_failed); + return 0; #endif - } - - status = bgp_connect (peer); - - switch (status) - { - case connect_error: - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s [FSM] Connect error", peer->host); - BGP_EVENT_ADD (peer, TCP_connection_open_failed); - break; - case connect_success: - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s [FSM] Connect immediately success, fd %d", - peer->host, peer->fd); - BGP_EVENT_ADD (peer, TCP_connection_open); - break; - case connect_in_progress: - /* To check nonblocking connect, we wait until socket is - readable or writable. */ - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s [FSM] Non blocking connect waiting result, fd %d", - peer->host, peer->fd); - if (peer->fd < 0) - { - zlog_err ("bgp_start peer's fd is negative value %d", - peer->fd); - return -1; } - BGP_READ_ON (peer->t_read, bgp_read, peer->fd); - BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); - break; - } - return 0; + + status = bgp_connect(peer); + + switch (status) { + case connect_error: + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s [FSM] Connect error", peer->host); + BGP_EVENT_ADD(peer, TCP_connection_open_failed); + break; + case connect_success: + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s [FSM] Connect immediately success, fd %d", + peer->host, peer->fd); + BGP_EVENT_ADD(peer, TCP_connection_open); + break; + case connect_in_progress: + /* To check nonblocking connect, we wait until socket is + readable or writable. */ + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s [FSM] Non blocking connect waiting result, fd %d", + peer->host, peer->fd); + if (peer->fd < 0) { + zlog_err("bgp_start peer's fd is negative value %d", + peer->fd); + return -1; + } + BGP_READ_ON(peer->t_read, bgp_read, peer->fd); + BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd); + break; + } + return 0; } /* Connect retry timer is expired when the peer status is Connect. */ -static int -bgp_reconnect (struct peer *peer) +static int bgp_reconnect(struct peer *peer) { - if (bgp_stop (peer) < 0) - return -1; + if (bgp_stop(peer) < 0) + return -1; - bgp_start (peer); - return 0; + bgp_start(peer); + return 0; } -static int -bgp_fsm_open (struct peer *peer) +static int bgp_fsm_open(struct peer *peer) { - /* Send keepalive and make keepalive timer */ - bgp_keepalive_send (peer); + /* Send keepalive and make keepalive timer */ + bgp_keepalive_send(peer); - /* Reset holdtimer value. */ - BGP_TIMER_OFF (peer->t_holdtime); + /* Reset holdtimer value. */ + BGP_TIMER_OFF(peer->t_holdtime); - return 0; + return 0; } /* Keepalive send to peer. */ -static int -bgp_fsm_keepalive_expire (struct peer *peer) +static int bgp_fsm_keepalive_expire(struct peer *peer) { - bgp_keepalive_send (peer); - return 0; + bgp_keepalive_send(peer); + return 0; } /* FSM error, unexpected event. This is error of BGP connection. So cut the peer and change to Idle status. */ -static int -bgp_fsm_event_error (struct peer *peer) +static int bgp_fsm_event_error(struct peer *peer) { - zlog_err ("%s [FSM] unexpected packet received in state %s", - peer->host, lookup_msg(bgp_status_msg, peer->status, NULL)); + zlog_err("%s [FSM] unexpected packet received in state %s", peer->host, + lookup_msg(bgp_status_msg, peer->status, NULL)); - return bgp_stop_with_notify (peer, BGP_NOTIFY_FSM_ERR, 0); + return bgp_stop_with_notify(peer, BGP_NOTIFY_FSM_ERR, 0); } /* Hold timer expire. This is error of BGP connection. So cut the peer and change to Idle status. */ -static int -bgp_fsm_holdtime_expire (struct peer *peer) +static int bgp_fsm_holdtime_expire(struct peer *peer) { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s [FSM] Hold timer expire", peer->host); + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s [FSM] Hold timer expire", peer->host); - return bgp_stop_with_notify (peer, BGP_NOTIFY_HOLD_ERR, 0); + return bgp_stop_with_notify(peer, BGP_NOTIFY_HOLD_ERR, 0); } /* Status goes to Established. Send keepalive packet then make first update information. */ -static int -bgp_establish (struct peer *peer) +static int bgp_establish(struct peer *peer) { - afi_t afi; - safi_t safi; - int nsf_af_count = 0; - int ret = 0; - struct peer *other; - - other = peer->doppelganger; - peer = peer_xfer_conn(peer); - if (!peer) - { - zlog_err ("%%Neighbor failed in xfer_conn"); - return -1; - } - - if (other == peer) - ret = 1; /* bgp_establish specific code when xfer_conn happens. */ - - /* Reset capability open status flag. */ - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN)) - SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN); - - /* Clear start timer value to default. */ - peer->v_start = BGP_INIT_START_TIMER; - - /* Increment established count. */ - peer->established++; - bgp_fsm_change_status (peer, Established); - - /* bgp log-neighbor-changes of neighbor Up */ - if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES)) - { - struct vrf *vrf = vrf_lookup_by_id (peer->bgp->vrf_id); - zlog_info ("%%ADJCHANGE: neighbor %s(%s) in vrf %s Up", - peer->host, - (peer->hostname) ? peer->hostname : "Unknown", - vrf ? ((vrf->vrf_id != VRF_DEFAULT ) ? vrf->name : "Default") : ""); - } - /* assign update-group/subgroup */ - update_group_adjust_peer_afs(peer); - - /* graceful restart */ - UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT); - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_4 ; safi++) - { - if (peer->afc_nego[afi][safi] - && CHECK_FLAG (peer->cap, PEER_CAP_RESTART_ADV) - && CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV)) - { - if (peer->nsf[afi][safi] - && ! CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV)) - bgp_clear_stale_route (peer, afi, safi); - - peer->nsf[afi][safi] = 1; - nsf_af_count++; - } - else - { - if (peer->nsf[afi][safi]) - bgp_clear_stale_route (peer, afi, safi); - peer->nsf[afi][safi] = 0; - } - } - - if (nsf_af_count) - SET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE); - else - { - UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE); - if (peer->t_gr_stale) - { - BGP_TIMER_OFF (peer->t_gr_stale); - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s graceful restart stalepath timer stopped", peer->host); + afi_t afi; + safi_t safi; + int nsf_af_count = 0; + int ret = 0; + struct peer *other; + + other = peer->doppelganger; + peer = peer_xfer_conn(peer); + if (!peer) { + zlog_err("%%Neighbor failed in xfer_conn"); + return -1; } - } - if (peer->t_gr_restart) - { - BGP_TIMER_OFF (peer->t_gr_restart); - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s graceful restart timer stopped", peer->host); - } + if (other == peer) + ret = + 1; /* bgp_establish specific code when xfer_conn + happens. */ + + /* Reset capability open status flag. */ + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN)) + SET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN); + + /* Clear start timer value to default. */ + peer->v_start = BGP_INIT_START_TIMER; + + /* Increment established count. */ + peer->established++; + bgp_fsm_change_status(peer, Established); + + /* bgp log-neighbor-changes of neighbor Up */ + if (bgp_flag_check(peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES)) { + struct vrf *vrf = vrf_lookup_by_id(peer->bgp->vrf_id); + zlog_info("%%ADJCHANGE: neighbor %s(%s) in vrf %s Up", + peer->host, + (peer->hostname) ? peer->hostname : "Unknown", + vrf ? ((vrf->vrf_id != VRF_DEFAULT) ? vrf->name + : "Default") + : ""); + } + /* assign update-group/subgroup */ + update_group_adjust_peer_afs(peer); + + /* graceful restart */ + UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT); + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_RESERVED_4; safi++) { + if (peer->afc_nego[afi][safi] + && CHECK_FLAG(peer->cap, PEER_CAP_RESTART_ADV) + && CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_RESTART_AF_RCV)) { + if (peer->nsf[afi][safi] + && !CHECK_FLAG( + peer->af_cap[afi][safi], + PEER_CAP_RESTART_AF_PRESERVE_RCV)) + bgp_clear_stale_route(peer, afi, safi); + + peer->nsf[afi][safi] = 1; + nsf_af_count++; + } else { + if (peer->nsf[afi][safi]) + bgp_clear_stale_route(peer, afi, safi); + peer->nsf[afi][safi] = 0; + } + } + + if (nsf_af_count) + SET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE); + else { + UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE); + if (peer->t_gr_stale) { + BGP_TIMER_OFF(peer->t_gr_stale); + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s graceful restart stalepath timer stopped", + peer->host); + } + } - hook_call(peer_established, peer); + if (peer->t_gr_restart) { + BGP_TIMER_OFF(peer->t_gr_restart); + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s graceful restart timer stopped", + peer->host); + } - /* Reset uptime, send keepalive, send current table. */ - peer->uptime = bgp_clock (); + hook_call(peer_established, peer); + + /* Reset uptime, send keepalive, send current table. */ + peer->uptime = bgp_clock(); + + /* Send route-refresh when ORF is enabled */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + if (CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_SM_ADV)) { + if (CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_RCV)) + bgp_route_refresh_send( + peer, afi, safi, + ORF_TYPE_PREFIX, + REFRESH_IMMEDIATE, 0); + else if ( + CHECK_FLAG( + peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_OLD_RCV)) + bgp_route_refresh_send( + peer, afi, safi, + ORF_TYPE_PREFIX_OLD, + REFRESH_IMMEDIATE, 0); + } + + /* First update is deferred until ORF or ROUTE-REFRESH is received */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + if (CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_ADV)) + if (CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_SM_RCV) + || CHECK_FLAG( + peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_SM_OLD_RCV)) + SET_FLAG(peer->af_sflags[afi][safi], + PEER_STATUS_ORF_WAIT_REFRESH); + + bgp_announce_peer(peer); + + /* Start the route advertisement timer to send updates to the peer - if + * BGP + * is not in read-only mode. If it is, the timer will be started at the + * end + * of read-only mode. + */ + if (!bgp_update_delay_active(peer->bgp)) { + BGP_TIMER_OFF(peer->t_routeadv); + BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0); + } - /* Send route-refresh when ORF is enabled */ - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)) - { - if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)) - bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX, - REFRESH_IMMEDIATE, 0); - else if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)) - bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX_OLD, - REFRESH_IMMEDIATE, 0); + if (peer->doppelganger && (peer->doppelganger->status != Deleted)) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "[Event] Deleting stub connection for peer %s", + peer->host); + + if (peer->doppelganger->status > Active) + bgp_notify_send(peer->doppelganger, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); + else + peer_delete(peer->doppelganger); } - /* First update is deferred until ORF or ROUTE-REFRESH is received */ - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)) - if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV) - || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV)) - SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH); - - bgp_announce_peer (peer); - - /* Start the route advertisement timer to send updates to the peer - if BGP - * is not in read-only mode. If it is, the timer will be started at the end - * of read-only mode. - */ - if (!bgp_update_delay_active(peer->bgp)) - { - BGP_TIMER_OFF(peer->t_routeadv); - BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 0); - } - - if (peer->doppelganger && (peer->doppelganger->status != Deleted)) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug("[Event] Deleting stub connection for peer %s", peer->host); - - if (peer->doppelganger->status > Active) - bgp_notify_send (peer->doppelganger, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); - else - peer_delete(peer->doppelganger); - } - - bgp_bfd_register_peer(peer); - return ret; + bgp_bfd_register_peer(peer); + return ret; } /* Keepalive packet is received. */ -static int -bgp_fsm_keepalive (struct peer *peer) +static int bgp_fsm_keepalive(struct peer *peer) { - bgp_update_implicit_eors(peer); + bgp_update_implicit_eors(peer); - /* peer count update */ - peer->keepalive_in++; + /* peer count update */ + peer->keepalive_in++; - BGP_TIMER_OFF (peer->t_holdtime); - return 0; + BGP_TIMER_OFF(peer->t_holdtime); + return 0; } /* Update packet is received. */ -static int -bgp_fsm_update (struct peer *peer) +static int bgp_fsm_update(struct peer *peer) { - BGP_TIMER_OFF (peer->t_holdtime); - return 0; + BGP_TIMER_OFF(peer->t_holdtime); + return 0; } /* This is empty event. */ -static int -bgp_ignore (struct peer *peer) +static int bgp_ignore(struct peer *peer) { - zlog_err ("%s [FSM] Ignoring event %s in state %s, prior events %s, %s, fd %d", - peer->host, bgp_event_str[peer->cur_event], - lookup_msg(bgp_status_msg, peer->status, NULL), - bgp_event_str[peer->last_event], - bgp_event_str[peer->last_major_event], peer->fd); - return 0; + zlog_err( + "%s [FSM] Ignoring event %s in state %s, prior events %s, %s, fd %d", + peer->host, bgp_event_str[peer->cur_event], + lookup_msg(bgp_status_msg, peer->status, NULL), + bgp_event_str[peer->last_event], + bgp_event_str[peer->last_major_event], peer->fd); + return 0; } /* This is to handle unexpected events.. */ -static int -bgp_fsm_exeption (struct peer *peer) +static int bgp_fsm_exeption(struct peer *peer) { - zlog_err ("%s [FSM] Unexpected event %s in state %s, prior events %s, %s, fd %d", - peer->host, bgp_event_str[peer->cur_event], - lookup_msg(bgp_status_msg, peer->status, NULL), - bgp_event_str[peer->last_event], - bgp_event_str[peer->last_major_event], peer->fd); - return(bgp_stop (peer)); + zlog_err( + "%s [FSM] Unexpected event %s in state %s, prior events %s, %s, fd %d", + peer->host, bgp_event_str[peer->cur_event], + lookup_msg(bgp_status_msg, peer->status, NULL), + bgp_event_str[peer->last_event], + bgp_event_str[peer->last_major_event], peer->fd); + return (bgp_stop(peer)); } -void -bgp_fsm_nht_update(struct peer *peer, int valid) +void bgp_fsm_nht_update(struct peer *peer, int valid) { - if (!peer) - return; - - switch (peer->status) - { - case Idle: - if (valid) - BGP_EVENT_ADD(peer, BGP_Start); - break; - case Connect: - if (!valid) - { - BGP_TIMER_OFF(peer->t_connect); - BGP_EVENT_ADD(peer, TCP_fatal_error); + if (!peer) + return; + + switch (peer->status) { + case Idle: + if (valid) + BGP_EVENT_ADD(peer, BGP_Start); + break; + case Connect: + if (!valid) { + BGP_TIMER_OFF(peer->t_connect); + BGP_EVENT_ADD(peer, TCP_fatal_error); + } + break; + case Active: + if (valid) { + BGP_TIMER_OFF(peer->t_connect); + BGP_EVENT_ADD(peer, ConnectRetry_timer_expired); + } + break; + case OpenSent: + case OpenConfirm: + case Established: + if (!valid && (peer->gtsm_hops == 1)) + BGP_EVENT_ADD(peer, TCP_fatal_error); + case Clearing: + case Deleted: + default: + break; } - break; - case Active: - if (valid) - { - BGP_TIMER_OFF(peer->t_connect); - BGP_EVENT_ADD(peer, ConnectRetry_timer_expired); - } - break; - case OpenSent: - case OpenConfirm: - case Established: - if (!valid && (peer->gtsm_hops == 1)) - BGP_EVENT_ADD(peer, TCP_fatal_error); - case Clearing: - case Deleted: - default: - break; - } } /* Finite State Machine structure */ static const struct { - int (*func) (struct peer *); - int next_state; -} FSM [BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] = -{ - { - /* Idle state: In Idle state, all events other than BGP_Start is - ignored. With BGP_Start event, finite state machine calls - bgp_start(). */ - {bgp_start, Connect}, /* BGP_Start */ - {bgp_stop, Idle}, /* BGP_Stop */ - {bgp_stop, Idle}, /* TCP_connection_open */ - {bgp_stop, Idle}, /* TCP_connection_closed */ - {bgp_ignore, Idle}, /* TCP_connection_open_failed */ - {bgp_stop, Idle}, /* TCP_fatal_error */ - {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */ - {bgp_ignore, Idle}, /* Hold_Timer_expired */ - {bgp_ignore, Idle}, /* KeepAlive_timer_expired */ - {bgp_ignore, Idle}, /* Receive_OPEN_message */ - {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */ - {bgp_ignore, Idle}, /* Receive_UPDATE_message */ - {bgp_ignore, Idle}, /* Receive_NOTIFICATION_message */ - {bgp_ignore, Idle}, /* Clearing_Completed */ - }, - { - /* Connect */ - {bgp_ignore, Connect}, /* BGP_Start */ - {bgp_stop, Idle}, /* BGP_Stop */ - {bgp_connect_success, OpenSent}, /* TCP_connection_open */ - {bgp_stop, Idle}, /* TCP_connection_closed */ - {bgp_connect_fail, Active}, /* TCP_connection_open_failed */ - {bgp_connect_fail, Idle}, /* TCP_fatal_error */ - {bgp_reconnect, Connect}, /* ConnectRetry_timer_expired */ - {bgp_fsm_exeption, Idle}, /* Hold_Timer_expired */ - {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */ - {bgp_fsm_exeption, Idle}, /* Receive_OPEN_message */ - {bgp_fsm_exeption, Idle}, /* Receive_KEEPALIVE_message */ - {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */ - {bgp_stop, Idle}, /* Receive_NOTIFICATION_message */ - {bgp_fsm_exeption, Idle}, /* Clearing_Completed */ - }, - { - /* Active, */ - {bgp_ignore, Active}, /* BGP_Start */ - {bgp_stop, Idle}, /* BGP_Stop */ - {bgp_connect_success, OpenSent}, /* TCP_connection_open */ - {bgp_stop, Idle}, /* TCP_connection_closed */ - {bgp_ignore, Active}, /* TCP_connection_open_failed */ - {bgp_fsm_exeption, Idle}, /* TCP_fatal_error */ - {bgp_start, Connect}, /* ConnectRetry_timer_expired */ - {bgp_fsm_exeption, Idle}, /* Hold_Timer_expired */ - {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */ - {bgp_fsm_exeption, Idle}, /* Receive_OPEN_message */ - {bgp_fsm_exeption, Idle}, /* Receive_KEEPALIVE_message */ - {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */ - {bgp_fsm_exeption, Idle}, /* Receive_NOTIFICATION_message */ - {bgp_fsm_exeption, Idle}, /* Clearing_Completed */ - }, - { - /* OpenSent, */ - {bgp_ignore, OpenSent}, /* BGP_Start */ - {bgp_stop, Idle}, /* BGP_Stop */ - {bgp_stop, Active}, /* TCP_connection_open */ - {bgp_stop, Active}, /* TCP_connection_closed */ - {bgp_stop, Active}, /* TCP_connection_open_failed */ - {bgp_stop, Active}, /* TCP_fatal_error */ - {bgp_fsm_exeption, Idle}, /* ConnectRetry_timer_expired */ - {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */ - {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */ - {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */ - {bgp_fsm_event_error, Idle}, /* Receive_KEEPALIVE_message */ - {bgp_fsm_event_error, Idle}, /* Receive_UPDATE_message */ - {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */ - {bgp_fsm_exeption, Idle}, /* Clearing_Completed */ - }, - { - /* OpenConfirm, */ - {bgp_ignore, OpenConfirm}, /* BGP_Start */ - {bgp_stop, Idle}, /* BGP_Stop */ - {bgp_stop, Idle}, /* TCP_connection_open */ - {bgp_stop, Idle}, /* TCP_connection_closed */ - {bgp_stop, Idle}, /* TCP_connection_open_failed */ - {bgp_stop, Idle}, /* TCP_fatal_error */ - {bgp_fsm_exeption, Idle}, /* ConnectRetry_timer_expired */ - {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */ - {bgp_ignore, OpenConfirm}, /* KeepAlive_timer_expired */ - {bgp_fsm_exeption, Idle}, /* Receive_OPEN_message */ - {bgp_establish, Established}, /* Receive_KEEPALIVE_message */ - {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */ - {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */ - {bgp_fsm_exeption, Idle}, /* Clearing_Completed */ - }, - { - /* Established, */ - {bgp_ignore, Established}, /* BGP_Start */ - {bgp_stop, Clearing}, /* BGP_Stop */ - {bgp_stop, Clearing}, /* TCP_connection_open */ - {bgp_stop, Clearing}, /* TCP_connection_closed */ - {bgp_stop, Clearing}, /* TCP_connection_open_failed */ - {bgp_stop, Clearing}, /* TCP_fatal_error */ - {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */ - {bgp_fsm_holdtime_expire, Clearing}, /* Hold_Timer_expired */ - {bgp_fsm_keepalive_expire, Established}, /* KeepAlive_timer_expired */ - {bgp_stop, Clearing}, /* Receive_OPEN_message */ - {bgp_fsm_keepalive, Established}, /* Receive_KEEPALIVE_message */ - {bgp_fsm_update, Established}, /* Receive_UPDATE_message */ - {bgp_stop_with_error, Clearing}, /* Receive_NOTIFICATION_message */ - {bgp_fsm_exeption, Idle}, /* Clearing_Completed */ - }, - { - /* Clearing, */ - {bgp_ignore, Clearing}, /* BGP_Start */ - {bgp_stop, Clearing}, /* BGP_Stop */ - {bgp_stop, Clearing}, /* TCP_connection_open */ - {bgp_stop, Clearing}, /* TCP_connection_closed */ - {bgp_stop, Clearing}, /* TCP_connection_open_failed */ - {bgp_stop, Clearing}, /* TCP_fatal_error */ - {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */ - {bgp_stop, Clearing}, /* Hold_Timer_expired */ - {bgp_stop, Clearing}, /* KeepAlive_timer_expired */ - {bgp_stop, Clearing}, /* Receive_OPEN_message */ - {bgp_stop, Clearing}, /* Receive_KEEPALIVE_message */ - {bgp_stop, Clearing}, /* Receive_UPDATE_message */ - {bgp_stop, Clearing}, /* Receive_NOTIFICATION_message */ - {bgp_clearing_completed, Idle}, /* Clearing_Completed */ - }, - { - /* Deleted, */ - {bgp_ignore, Deleted}, /* BGP_Start */ - {bgp_ignore, Deleted}, /* BGP_Stop */ - {bgp_ignore, Deleted}, /* TCP_connection_open */ - {bgp_ignore, Deleted}, /* TCP_connection_closed */ - {bgp_ignore, Deleted}, /* TCP_connection_open_failed */ - {bgp_ignore, Deleted}, /* TCP_fatal_error */ - {bgp_ignore, Deleted}, /* ConnectRetry_timer_expired */ - {bgp_ignore, Deleted}, /* Hold_Timer_expired */ - {bgp_ignore, Deleted}, /* KeepAlive_timer_expired */ - {bgp_ignore, Deleted}, /* Receive_OPEN_message */ - {bgp_ignore, Deleted}, /* Receive_KEEPALIVE_message */ - {bgp_ignore, Deleted}, /* Receive_UPDATE_message */ - {bgp_ignore, Deleted}, /* Receive_NOTIFICATION_message */ - {bgp_ignore, Deleted}, /* Clearing_Completed */ - }, + int (*func)(struct peer *); + int next_state; +} FSM[BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] = { + { + /* Idle state: In Idle state, all events other than BGP_Start is + ignored. With BGP_Start event, finite state machine calls + bgp_start(). */ + {bgp_start, Connect}, /* BGP_Start */ + {bgp_stop, Idle}, /* BGP_Stop */ + {bgp_stop, Idle}, /* TCP_connection_open */ + {bgp_stop, Idle}, /* TCP_connection_closed */ + {bgp_ignore, Idle}, /* TCP_connection_open_failed */ + {bgp_stop, Idle}, /* TCP_fatal_error */ + {bgp_ignore, Idle}, /* ConnectRetry_timer_expired */ + {bgp_ignore, Idle}, /* Hold_Timer_expired */ + {bgp_ignore, Idle}, /* KeepAlive_timer_expired */ + {bgp_ignore, Idle}, /* Receive_OPEN_message */ + {bgp_ignore, Idle}, /* Receive_KEEPALIVE_message */ + {bgp_ignore, Idle}, /* Receive_UPDATE_message */ + {bgp_ignore, Idle}, /* Receive_NOTIFICATION_message */ + {bgp_ignore, Idle}, /* Clearing_Completed */ + }, + { + /* Connect */ + {bgp_ignore, Connect}, /* BGP_Start */ + {bgp_stop, Idle}, /* BGP_Stop */ + {bgp_connect_success, OpenSent}, /* TCP_connection_open */ + {bgp_stop, Idle}, /* TCP_connection_closed */ + {bgp_connect_fail, Active}, /* TCP_connection_open_failed */ + {bgp_connect_fail, Idle}, /* TCP_fatal_error */ + {bgp_reconnect, Connect}, /* ConnectRetry_timer_expired */ + {bgp_fsm_exeption, Idle}, /* Hold_Timer_expired */ + {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */ + {bgp_fsm_exeption, Idle}, /* Receive_OPEN_message */ + {bgp_fsm_exeption, Idle}, /* Receive_KEEPALIVE_message */ + {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */ + {bgp_stop, Idle}, /* Receive_NOTIFICATION_message */ + {bgp_fsm_exeption, Idle}, /* Clearing_Completed */ + }, + { + /* Active, */ + {bgp_ignore, Active}, /* BGP_Start */ + {bgp_stop, Idle}, /* BGP_Stop */ + {bgp_connect_success, OpenSent}, /* TCP_connection_open */ + {bgp_stop, Idle}, /* TCP_connection_closed */ + {bgp_ignore, Active}, /* TCP_connection_open_failed */ + {bgp_fsm_exeption, Idle}, /* TCP_fatal_error */ + {bgp_start, Connect}, /* ConnectRetry_timer_expired */ + {bgp_fsm_exeption, Idle}, /* Hold_Timer_expired */ + {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */ + {bgp_fsm_exeption, Idle}, /* Receive_OPEN_message */ + {bgp_fsm_exeption, Idle}, /* Receive_KEEPALIVE_message */ + {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */ + {bgp_fsm_exeption, Idle}, /* Receive_NOTIFICATION_message */ + {bgp_fsm_exeption, Idle}, /* Clearing_Completed */ + }, + { + /* OpenSent, */ + {bgp_ignore, OpenSent}, /* BGP_Start */ + {bgp_stop, Idle}, /* BGP_Stop */ + {bgp_stop, Active}, /* TCP_connection_open */ + {bgp_stop, Active}, /* TCP_connection_closed */ + {bgp_stop, Active}, /* TCP_connection_open_failed */ + {bgp_stop, Active}, /* TCP_fatal_error */ + {bgp_fsm_exeption, Idle}, /* ConnectRetry_timer_expired */ + {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */ + {bgp_fsm_exeption, Idle}, /* KeepAlive_timer_expired */ + {bgp_fsm_open, OpenConfirm}, /* Receive_OPEN_message */ + {bgp_fsm_event_error, Idle}, /* Receive_KEEPALIVE_message */ + {bgp_fsm_event_error, Idle}, /* Receive_UPDATE_message */ + {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */ + {bgp_fsm_exeption, Idle}, /* Clearing_Completed */ + }, + { + /* OpenConfirm, */ + {bgp_ignore, OpenConfirm}, /* BGP_Start */ + {bgp_stop, Idle}, /* BGP_Stop */ + {bgp_stop, Idle}, /* TCP_connection_open */ + {bgp_stop, Idle}, /* TCP_connection_closed */ + {bgp_stop, Idle}, /* TCP_connection_open_failed */ + {bgp_stop, Idle}, /* TCP_fatal_error */ + {bgp_fsm_exeption, Idle}, /* ConnectRetry_timer_expired */ + {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired */ + {bgp_ignore, OpenConfirm}, /* KeepAlive_timer_expired */ + {bgp_fsm_exeption, Idle}, /* Receive_OPEN_message */ + {bgp_establish, Established}, /* Receive_KEEPALIVE_message */ + {bgp_fsm_exeption, Idle}, /* Receive_UPDATE_message */ + {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */ + {bgp_fsm_exeption, Idle}, /* Clearing_Completed */ + }, + { + /* Established, */ + {bgp_ignore, Established}, /* BGP_Start */ + {bgp_stop, Clearing}, /* BGP_Stop */ + {bgp_stop, Clearing}, /* TCP_connection_open */ + {bgp_stop, Clearing}, /* TCP_connection_closed */ + {bgp_stop, Clearing}, /* TCP_connection_open_failed */ + {bgp_stop, Clearing}, /* TCP_fatal_error */ + {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */ + {bgp_fsm_holdtime_expire, Clearing}, /* Hold_Timer_expired */ + {bgp_fsm_keepalive_expire, + Established}, /* KeepAlive_timer_expired */ + {bgp_stop, Clearing}, /* Receive_OPEN_message */ + {bgp_fsm_keepalive, + Established}, /* Receive_KEEPALIVE_message */ + {bgp_fsm_update, Established}, /* Receive_UPDATE_message */ + {bgp_stop_with_error, + Clearing}, /* Receive_NOTIFICATION_message */ + {bgp_fsm_exeption, Idle}, /* Clearing_Completed */ + }, + { + /* Clearing, */ + {bgp_ignore, Clearing}, /* BGP_Start */ + {bgp_stop, Clearing}, /* BGP_Stop */ + {bgp_stop, Clearing}, /* TCP_connection_open */ + {bgp_stop, Clearing}, /* TCP_connection_closed */ + {bgp_stop, Clearing}, /* TCP_connection_open_failed */ + {bgp_stop, Clearing}, /* TCP_fatal_error */ + {bgp_stop, Clearing}, /* ConnectRetry_timer_expired */ + {bgp_stop, Clearing}, /* Hold_Timer_expired */ + {bgp_stop, Clearing}, /* KeepAlive_timer_expired */ + {bgp_stop, Clearing}, /* Receive_OPEN_message */ + {bgp_stop, Clearing}, /* Receive_KEEPALIVE_message */ + {bgp_stop, Clearing}, /* Receive_UPDATE_message */ + {bgp_stop, Clearing}, /* Receive_NOTIFICATION_message */ + {bgp_clearing_completed, Idle}, /* Clearing_Completed */ + }, + { + /* Deleted, */ + {bgp_ignore, Deleted}, /* BGP_Start */ + {bgp_ignore, Deleted}, /* BGP_Stop */ + {bgp_ignore, Deleted}, /* TCP_connection_open */ + {bgp_ignore, Deleted}, /* TCP_connection_closed */ + {bgp_ignore, Deleted}, /* TCP_connection_open_failed */ + {bgp_ignore, Deleted}, /* TCP_fatal_error */ + {bgp_ignore, Deleted}, /* ConnectRetry_timer_expired */ + {bgp_ignore, Deleted}, /* Hold_Timer_expired */ + {bgp_ignore, Deleted}, /* KeepAlive_timer_expired */ + {bgp_ignore, Deleted}, /* Receive_OPEN_message */ + {bgp_ignore, Deleted}, /* Receive_KEEPALIVE_message */ + {bgp_ignore, Deleted}, /* Receive_UPDATE_message */ + {bgp_ignore, Deleted}, /* Receive_NOTIFICATION_message */ + {bgp_ignore, Deleted}, /* Clearing_Completed */ + }, }; /* Execute event process. */ -int -bgp_event (struct thread *thread) +int bgp_event(struct thread *thread) { - int event; - struct peer *peer; - int ret; + int event; + struct peer *peer; + int ret; - peer = THREAD_ARG (thread); - event = THREAD_VAL (thread); + peer = THREAD_ARG(thread); + event = THREAD_VAL(thread); - ret = bgp_event_update(peer, event); + ret = bgp_event_update(peer, event); - return (ret); + return (ret); } -int -bgp_event_update (struct peer *peer, int event) +int bgp_event_update(struct peer *peer, int event) { - int next; - int ret = 0; - struct peer *other; - int passive_conn = 0; - int dyn_nbr; - - other = peer->doppelganger; - passive_conn = (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) ? 1 : 0; - dyn_nbr = peer_dynamic_neighbor(peer); - - /* Logging this event. */ - next = FSM [peer->status -1][event - 1].next_state; - - if (bgp_debug_neighbor_events(peer) && peer->status != next) - zlog_debug ("%s [FSM] %s (%s->%s), fd %d", peer->host, - bgp_event_str[event], - lookup_msg(bgp_status_msg, peer->status, NULL), - lookup_msg(bgp_status_msg, next, NULL), peer->fd); - - peer->last_event = peer->cur_event; - peer->cur_event = event; - - /* Call function. */ - if (FSM [peer->status -1][event - 1].func) - ret = (*(FSM [peer->status - 1][event - 1].func))(peer); - - /* When function do not want proceed next job return -1. */ - if (ret >= 0) - { - if (ret == 1 && next == Established) - { - /* The case when doppelganger swap accurred in bgp_establish. - Update the peer pointer accordingly */ - peer = other; - } - - /* If status is changed. */ - if (next != peer->status) - bgp_fsm_change_status (peer, next); - - /* Make sure timer is set. */ - bgp_timer_set (peer); - - } - else if (!dyn_nbr && !passive_conn && peer->bgp) - { - /* If we got a return value of -1, that means there was an error, restart - * the FSM. If the peer structure was deleted - */ - zlog_err ("%s [FSM] Failure handling event %s in state %s, " - "prior events %s, %s, fd %d", - peer->host, bgp_event_str[peer->cur_event], - lookup_msg(bgp_status_msg, peer->status, NULL), - bgp_event_str[peer->last_event], - bgp_event_str[peer->last_major_event], peer->fd); - bgp_stop (peer); - bgp_fsm_change_status(peer, Idle); - bgp_timer_set(peer); - } - return ret; + int next; + int ret = 0; + struct peer *other; + int passive_conn = 0; + int dyn_nbr; + + other = peer->doppelganger; + passive_conn = + (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) ? 1 : 0; + dyn_nbr = peer_dynamic_neighbor(peer); + + /* Logging this event. */ + next = FSM[peer->status - 1][event - 1].next_state; + + if (bgp_debug_neighbor_events(peer) && peer->status != next) + zlog_debug("%s [FSM] %s (%s->%s), fd %d", peer->host, + bgp_event_str[event], + lookup_msg(bgp_status_msg, peer->status, NULL), + lookup_msg(bgp_status_msg, next, NULL), peer->fd); + + peer->last_event = peer->cur_event; + peer->cur_event = event; + + /* Call function. */ + if (FSM[peer->status - 1][event - 1].func) + ret = (*(FSM[peer->status - 1][event - 1].func))(peer); + + /* When function do not want proceed next job return -1. */ + if (ret >= 0) { + if (ret == 1 && next == Established) { + /* The case when doppelganger swap accurred in + bgp_establish. + Update the peer pointer accordingly */ + peer = other; + } + + /* If status is changed. */ + if (next != peer->status) + bgp_fsm_change_status(peer, next); + + /* Make sure timer is set. */ + bgp_timer_set(peer); + + } else if (!dyn_nbr && !passive_conn && peer->bgp) { + /* If we got a return value of -1, that means there was an + * error, restart + * the FSM. If the peer structure was deleted + */ + zlog_err( + "%s [FSM] Failure handling event %s in state %s, " + "prior events %s, %s, fd %d", + peer->host, bgp_event_str[peer->cur_event], + lookup_msg(bgp_status_msg, peer->status, NULL), + bgp_event_str[peer->last_event], + bgp_event_str[peer->last_major_event], peer->fd); + bgp_stop(peer); + bgp_fsm_change_status(peer, Idle); + bgp_timer_set(peer); + } + return ret; } diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h index 33cba868e..51d5d7aaa 100644 --- a/bgpd/bgp_fsm.h +++ b/bgpd/bgp_fsm.h @@ -1,4 +1,4 @@ -/* BGP-4 Finite State Machine +/* BGP-4 Finite State Machine * From RFC1771 [A Border Gateway Protocol 4 (BGP-4)] * Copyright (C) 1998 Kunihiro Ishiguro * @@ -23,82 +23,83 @@ #define _QUAGGA_BGP_FSM_H /* Macro for BGP read, write and timer thread. */ -#define BGP_READ_ON(T,F,V) \ - do { \ - if ((peer->status != Deleted)) \ - thread_add_read (bm->master,(F),peer,(V),&(T)); \ - } while (0) - -#define BGP_READ_OFF(T) \ - do { \ - if (T) \ - THREAD_READ_OFF(T); \ - } while (0) - -#define BGP_WRITE_ON(T,F,V) \ - do { \ - if ((peer)->status != Deleted) \ - thread_add_write (bm->master,(F),(peer),(V),&(T)); \ - } while (0) - -#define BGP_PEER_WRITE_ON(T,F,V, peer) \ - do { \ - if ((peer)->status != Deleted) \ - thread_add_write (bm->master,(F),(peer),(V),&(T)); \ - } while (0) - -#define BGP_WRITE_OFF(T) \ - do { \ - if (T) \ - THREAD_WRITE_OFF(T); \ - } while (0) - -#define BGP_TIMER_ON(T,F,V) \ - do { \ - if ((peer->status != Deleted)) \ - thread_add_timer (bm->master,(F),peer,(V),&(T)); \ - } while (0) - -#define BGP_TIMER_OFF(T) \ - do { \ - if (T) \ - THREAD_TIMER_OFF(T); \ - } while (0) - -#define BGP_EVENT_ADD(P,E) \ - do { \ - if ((P)->status != Deleted) \ - thread_add_event (bm->master, bgp_event, (P), (E), NULL); \ - } while (0) - -#define BGP_EVENT_FLUSH(P) \ - do { \ - assert (peer); \ - thread_cancel_event (bm->master, (P)); \ - } while (0) +#define BGP_READ_ON(T, F, V) \ + do { \ + if ((peer->status != Deleted)) \ + thread_add_read(bm->master, (F), peer, (V), &(T)); \ + } while (0) + +#define BGP_READ_OFF(T) \ + do { \ + if (T) \ + THREAD_READ_OFF(T); \ + } while (0) + +#define BGP_WRITE_ON(T, F, V) \ + do { \ + if ((peer)->status != Deleted) \ + thread_add_write(bm->master, (F), (peer), (V), &(T)); \ + } while (0) + +#define BGP_PEER_WRITE_ON(T, F, V, peer) \ + do { \ + if ((peer)->status != Deleted) \ + thread_add_write(bm->master, (F), (peer), (V), &(T)); \ + } while (0) + +#define BGP_WRITE_OFF(T) \ + do { \ + if (T) \ + THREAD_WRITE_OFF(T); \ + } while (0) + +#define BGP_TIMER_ON(T, F, V) \ + do { \ + if ((peer->status != Deleted)) \ + thread_add_timer(bm->master, (F), peer, (V), &(T)); \ + } while (0) + +#define BGP_TIMER_OFF(T) \ + do { \ + if (T) \ + THREAD_TIMER_OFF(T); \ + } while (0) + +#define BGP_EVENT_ADD(P, E) \ + do { \ + if ((P)->status != Deleted) \ + thread_add_event(bm->master, bgp_event, (P), (E), \ + NULL); \ + } while (0) + +#define BGP_EVENT_FLUSH(P) \ + do { \ + assert(peer); \ + thread_cancel_event(bm->master, (P)); \ + } while (0) #define BGP_MSEC_JITTER 10 /* Prototypes. */ extern void bgp_fsm_nht_update(struct peer *, int valid); -extern int bgp_event (struct thread *); -extern int bgp_event_update (struct peer *, int event); -extern int bgp_stop (struct peer *peer); -extern void bgp_timer_set (struct peer *); -extern int bgp_routeadv_timer (struct thread *); -extern void bgp_fsm_change_status (struct peer *peer, int status); +extern int bgp_event(struct thread *); +extern int bgp_event_update(struct peer *, int event); +extern int bgp_stop(struct peer *peer); +extern void bgp_timer_set(struct peer *); +extern int bgp_routeadv_timer(struct thread *); +extern void bgp_fsm_change_status(struct peer *peer, int status); extern const char *peer_down_str[]; -extern void bgp_update_delay_end (struct bgp *); -extern void bgp_maxmed_update (struct bgp *); -extern int bgp_maxmed_onstartup_configured (struct bgp *); -extern int bgp_maxmed_onstartup_active (struct bgp *); +extern void bgp_update_delay_end(struct bgp *); +extern void bgp_maxmed_update(struct bgp *); +extern int bgp_maxmed_onstartup_configured(struct bgp *); +extern int bgp_maxmed_onstartup_active(struct bgp *); /** * Start the route advertisement timer (that honors MRAI) for all the * peers. Typically called at the end of initial convergence, coming * out of read-only mode. */ -extern void bgp_start_routeadv (struct bgp *); +extern void bgp_start_routeadv(struct bgp *); /** * See if the route advertisement timer needs to be adjusted for a @@ -107,10 +108,10 @@ extern void bgp_start_routeadv (struct bgp *); * timer to expire to send the new set of prefixes. It should fire * instantly and updates should go out sooner. */ -extern void bgp_adjust_routeadv (struct peer *); +extern void bgp_adjust_routeadv(struct peer *); #include "hook.h" -DECLARE_HOOK(peer_backward_transition, (struct peer *peer), (peer)) -DECLARE_HOOK(peer_established, (struct peer *peer), (peer)) +DECLARE_HOOK(peer_backward_transition, (struct peer * peer), (peer)) +DECLARE_HOOK(peer_established, (struct peer * peer), (peer)) #endif /* _QUAGGA_BGP_FSM_H */ diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c index 27533a581..ad7411990 100644 --- a/bgpd/bgp_label.c +++ b/bgpd/bgp_label.c @@ -41,309 +41,301 @@ extern struct zclient *zclient; -int -bgp_parse_fec_update (void) +int bgp_parse_fec_update(void) { - struct stream *s; - struct bgp_node *rn; - struct bgp *bgp; - struct bgp_table *table; - struct prefix p; - u_int32_t label; - afi_t afi; - safi_t safi; - - s = zclient->ibuf; - - memset(&p, 0, sizeof(struct prefix)); - p.family = stream_getw(s); - p.prefixlen = stream_getc(s); - stream_get(&p.u.prefix, s, PSIZE(p.prefixlen)); - label = stream_getl(s); - - /* hack for the bgp instance & SAFI = have to send/receive it */ - afi = family2afi(p.family); - safi = SAFI_UNICAST; - bgp = bgp_get_default(); - if (!bgp) - { - zlog_debug("no default bgp instance"); - return -1; - } - - table = bgp->rib[afi][safi]; - if (!table) - { - zlog_debug("no %u unicast table", p.family); - return -1; - } - rn = bgp_node_lookup(table, &p); - if (!rn) - { - zlog_debug("no node for the prefix"); - return -1; - } - - /* treat it as implicit withdraw - the label is invalid */ - if (label == MPLS_INVALID_LABEL) - bgp_unset_valid_label(&rn->local_label); - else - { - label_ntop(label, 1, &rn->local_label); - bgp_set_valid_label(&rn->local_label); - } - SET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED); - bgp_unlock_node (rn); - bgp_process (bgp, rn, afi, safi); - return 1; + struct stream *s; + struct bgp_node *rn; + struct bgp *bgp; + struct bgp_table *table; + struct prefix p; + u_int32_t label; + afi_t afi; + safi_t safi; + + s = zclient->ibuf; + + memset(&p, 0, sizeof(struct prefix)); + p.family = stream_getw(s); + p.prefixlen = stream_getc(s); + stream_get(&p.u.prefix, s, PSIZE(p.prefixlen)); + label = stream_getl(s); + + /* hack for the bgp instance & SAFI = have to send/receive it */ + afi = family2afi(p.family); + safi = SAFI_UNICAST; + bgp = bgp_get_default(); + if (!bgp) { + zlog_debug("no default bgp instance"); + return -1; + } + + table = bgp->rib[afi][safi]; + if (!table) { + zlog_debug("no %u unicast table", p.family); + return -1; + } + rn = bgp_node_lookup(table, &p); + if (!rn) { + zlog_debug("no node for the prefix"); + return -1; + } + + /* treat it as implicit withdraw - the label is invalid */ + if (label == MPLS_INVALID_LABEL) + bgp_unset_valid_label(&rn->local_label); + else { + label_ntop(label, 1, &rn->local_label); + bgp_set_valid_label(&rn->local_label); + } + SET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED); + bgp_unlock_node(rn); + bgp_process(bgp, rn, afi, safi); + return 1; } -mpls_label_t -bgp_adv_label (struct bgp_node *rn, struct bgp_info *ri, struct peer *to, - afi_t afi, safi_t safi) +mpls_label_t bgp_adv_label(struct bgp_node *rn, struct bgp_info *ri, + struct peer *to, afi_t afi, safi_t safi) { - struct peer *from; - mpls_label_t remote_label; - int reflect; + struct peer *from; + mpls_label_t remote_label; + int reflect; - if (!rn || !ri || !to) - return MPLS_INVALID_LABEL; + if (!rn || !ri || !to) + return MPLS_INVALID_LABEL; - remote_label = ri->extra ? ri->extra->label : MPLS_INVALID_LABEL; - from = ri->peer; - reflect = ((from->sort == BGP_PEER_IBGP) && (to->sort == BGP_PEER_IBGP)); + remote_label = ri->extra ? ri->extra->label : MPLS_INVALID_LABEL; + from = ri->peer; + reflect = + ((from->sort == BGP_PEER_IBGP) && (to->sort == BGP_PEER_IBGP)); - if (reflect && !CHECK_FLAG(to->af_flags[afi][safi], - PEER_FLAG_FORCE_NEXTHOP_SELF)) - return remote_label; + if (reflect + && !CHECK_FLAG(to->af_flags[afi][safi], + PEER_FLAG_FORCE_NEXTHOP_SELF)) + return remote_label; - if (CHECK_FLAG(to->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) - return remote_label; + if (CHECK_FLAG(to->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) + return remote_label; - return rn->local_label; + return rn->local_label; } -void -bgp_reg_dereg_for_label (struct bgp_node *rn, struct bgp_info *ri, - int reg) +void bgp_reg_dereg_for_label(struct bgp_node *rn, struct bgp_info *ri, int reg) { - struct stream *s; - struct prefix *p; - int command; - u_int16_t flags = 0; - size_t flags_pos = 0; - - /* Check socket. */ - if (!zclient || zclient->sock < 0) - return; - - p = &(rn->p); - s = zclient->obuf; - stream_reset (s); - command = (reg) ? ZEBRA_FEC_REGISTER : ZEBRA_FEC_UNREGISTER; - zclient_create_header (s, command, VRF_DEFAULT); - flags_pos = stream_get_endp (s); /* save position of 'flags' */ - stream_putw(s, flags); /* initial flags */ - stream_putw(s, PREFIX_FAMILY(p)); - stream_put_prefix(s, p); - if (reg) - { - assert (ri); - if (ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID)) - { - if (ri->attr->label_index != BGP_INVALID_LABEL_INDEX) - { - flags |= ZEBRA_FEC_REGISTER_LABEL_INDEX; - stream_putl (s, ri->attr->label_index); - } - } - SET_FLAG (rn->flags, BGP_NODE_REGISTERED_FOR_LABEL); - } - else - UNSET_FLAG (rn->flags, BGP_NODE_REGISTERED_FOR_LABEL); - - /* Set length and flags */ - stream_putw_at (s, 0, stream_get_endp (s)); - stream_putw_at (s, flags_pos, flags); - - zclient_send_message(zclient); + struct stream *s; + struct prefix *p; + int command; + u_int16_t flags = 0; + size_t flags_pos = 0; + + /* Check socket. */ + if (!zclient || zclient->sock < 0) + return; + + p = &(rn->p); + s = zclient->obuf; + stream_reset(s); + command = (reg) ? ZEBRA_FEC_REGISTER : ZEBRA_FEC_UNREGISTER; + zclient_create_header(s, command, VRF_DEFAULT); + flags_pos = stream_get_endp(s); /* save position of 'flags' */ + stream_putw(s, flags); /* initial flags */ + stream_putw(s, PREFIX_FAMILY(p)); + stream_put_prefix(s, p); + if (reg) { + assert(ri); + if (ri->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) { + if (ri->attr->label_index != BGP_INVALID_LABEL_INDEX) { + flags |= ZEBRA_FEC_REGISTER_LABEL_INDEX; + stream_putl(s, ri->attr->label_index); + } + } + SET_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL); + } else + UNSET_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL); + + /* Set length and flags */ + stream_putw_at(s, 0, stream_get_endp(s)); + stream_putw_at(s, flags_pos, flags); + + zclient_send_message(zclient); } -static int -bgp_nlri_get_labels (struct peer *peer, u_char *pnt, u_char plen, mpls_label_t *label) +static int bgp_nlri_get_labels(struct peer *peer, u_char *pnt, u_char plen, + mpls_label_t *label) { - u_char *data = pnt; - u_char *lim = pnt + plen; - u_char llen = 0; - u_char label_depth = 0; - - for (; data < lim; data += BGP_LABEL_BYTES) - { - memcpy(label, data, BGP_LABEL_BYTES); - llen += BGP_LABEL_BYTES; - - bgp_set_valid_label(label); - label_depth += 1; - - if (bgp_is_withdraw_label(label) || label_bos(label)) - break; - } - - /* If we RX multiple labels we will end up keeping only the last - * one. We do not yet support a label stack greater than 1. */ - if (label_depth > 1) - zlog_warn("%s rcvd UPDATE with label stack %d deep", - peer->host, label_depth); - - if (!(bgp_is_withdraw_label(label) || label_bos(label))) - zlog_warn("%s rcvd UPDATE with invalid label stack - no bottom of stack", - peer->host); - - return llen; + u_char *data = pnt; + u_char *lim = pnt + plen; + u_char llen = 0; + u_char label_depth = 0; + + for (; data < lim; data += BGP_LABEL_BYTES) { + memcpy(label, data, BGP_LABEL_BYTES); + llen += BGP_LABEL_BYTES; + + bgp_set_valid_label(label); + label_depth += 1; + + if (bgp_is_withdraw_label(label) || label_bos(label)) + break; + } + + /* If we RX multiple labels we will end up keeping only the last + * one. We do not yet support a label stack greater than 1. */ + if (label_depth > 1) + zlog_warn("%s rcvd UPDATE with label stack %d deep", peer->host, + label_depth); + + if (!(bgp_is_withdraw_label(label) || label_bos(label))) + zlog_warn( + "%s rcvd UPDATE with invalid label stack - no bottom of stack", + peer->host); + + return llen; } -int -bgp_nlri_parse_label (struct peer *peer, struct attr *attr, - struct bgp_nlri *packet) +int bgp_nlri_parse_label(struct peer *peer, struct attr *attr, + struct bgp_nlri *packet) { - u_char *pnt; - u_char *lim; - struct prefix p; - int psize = 0; - int prefixlen; - afi_t afi; - safi_t safi; - int addpath_encoded; - u_int32_t addpath_id; - mpls_label_t label = MPLS_INVALID_LABEL; - u_char llen; - - /* Check peer status. */ - if (peer->status != Established) - return 0; - - pnt = packet->nlri; - lim = pnt + packet->length; - afi = packet->afi; - safi = packet->safi; - addpath_id = 0; - - addpath_encoded = (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) && - CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV)); - - for (; pnt < lim; pnt += psize) - { - /* Clear prefix structure. */ - memset (&p, 0, sizeof (struct prefix)); - llen = 0; - - if (addpath_encoded) - { - - /* When packet overflow occurs return immediately. */ - if (pnt + BGP_ADDPATH_ID_LEN > lim) - return -1; - - addpath_id = ntohl(*((uint32_t*) pnt)); - pnt += BGP_ADDPATH_ID_LEN; - } - - /* Fetch prefix length. */ - prefixlen = *pnt++; - p.family = afi2family (packet->afi); - psize = PSIZE (prefixlen); - - /* sanity check against packet data */ - if ((pnt + psize) > lim) - { - zlog_err ("%s [Error] Update packet error / L-U (prefix length %d exceeds packet size %u)", - peer->host, - prefixlen, (uint)(lim-pnt)); - return -1; - } - - /* Fill in the labels */ - llen = bgp_nlri_get_labels(peer, pnt, psize, &label); - p.prefixlen = prefixlen - BSIZE(llen); - - /* There needs to be at least one label */ - if (prefixlen < 24) - { - zlog_err ("%s [Error] Update packet error" - " (wrong label length %d)", - peer->host, prefixlen); - bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_INVAL_NETWORK); - return -1; - } - - if ((afi == AFI_IP && p.prefixlen > 32) - || (afi == AFI_IP6 && p.prefixlen > 128)) - return -1; - - /* Fetch prefix from NLRI packet */ - memcpy (&p.u.prefix, pnt + llen, psize - llen); - - /* Check address. */ - if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) - { - if (IN_CLASSD (ntohl (p.u.prefix4.s_addr))) - { - /* From RFC4271 Section 6.3: - * - * If a prefix in the NLRI field is semantically incorrect - * (e.g., an unexpected multicast IP address), an error SHOULD - * be logged locally, and the prefix SHOULD be ignored. - */ - zlog_err ("%s: IPv4 labeled-unicast NLRI is multicast address %s, ignoring", - peer->host, inet_ntoa (p.u.prefix4)); - continue; - } - } - - /* Check address. */ - if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) - { - if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6)) - { - char buf[BUFSIZ]; - - zlog_err ("%s: IPv6 labeled-unicast NLRI is link-local address %s, ignoring", - peer->host, inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ)); - - continue; - } - - if (IN6_IS_ADDR_MULTICAST (&p.u.prefix6)) - { - char buf[BUFSIZ]; - - zlog_err ("%s: IPv6 unicast NLRI is multicast address %s, ignoring", - peer->host, inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ)); - - continue; - } - } - - if (attr) - { - bgp_update (peer, &p, addpath_id, attr, packet->afi, SAFI_UNICAST, - ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, &label, 0, NULL); - } - else - { - bgp_withdraw (peer, &p, addpath_id, attr, packet->afi, SAFI_UNICAST, - ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, &label, NULL); - } - } - - /* Packet length consistency check. */ - if (pnt != lim) - { - zlog_err ("%s [Error] Update packet error / L-U (%zu data remaining after parsing)", - peer->host, lim - pnt); - return -1; - } - - return 0; + u_char *pnt; + u_char *lim; + struct prefix p; + int psize = 0; + int prefixlen; + afi_t afi; + safi_t safi; + int addpath_encoded; + u_int32_t addpath_id; + mpls_label_t label = MPLS_INVALID_LABEL; + u_char llen; + + /* Check peer status. */ + if (peer->status != Established) + return 0; + + pnt = packet->nlri; + lim = pnt + packet->length; + afi = packet->afi; + safi = packet->safi; + addpath_id = 0; + + addpath_encoded = + (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) + && CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ADDPATH_AF_TX_RCV)); + + for (; pnt < lim; pnt += psize) { + /* Clear prefix structure. */ + memset(&p, 0, sizeof(struct prefix)); + llen = 0; + + if (addpath_encoded) { + + /* When packet overflow occurs return immediately. */ + if (pnt + BGP_ADDPATH_ID_LEN > lim) + return -1; + + addpath_id = ntohl(*((uint32_t *)pnt)); + pnt += BGP_ADDPATH_ID_LEN; + } + + /* Fetch prefix length. */ + prefixlen = *pnt++; + p.family = afi2family(packet->afi); + psize = PSIZE(prefixlen); + + /* sanity check against packet data */ + if ((pnt + psize) > lim) { + zlog_err( + "%s [Error] Update packet error / L-U (prefix length %d exceeds packet size %u)", + peer->host, prefixlen, (uint)(lim - pnt)); + return -1; + } + + /* Fill in the labels */ + llen = bgp_nlri_get_labels(peer, pnt, psize, &label); + p.prefixlen = prefixlen - BSIZE(llen); + + /* There needs to be at least one label */ + if (prefixlen < 24) { + zlog_err( + "%s [Error] Update packet error" + " (wrong label length %d)", + peer->host, prefixlen); + bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_INVAL_NETWORK); + return -1; + } + + if ((afi == AFI_IP && p.prefixlen > 32) + || (afi == AFI_IP6 && p.prefixlen > 128)) + return -1; + + /* Fetch prefix from NLRI packet */ + memcpy(&p.u.prefix, pnt + llen, psize - llen); + + /* Check address. */ + if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) { + if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) { + /* From RFC4271 Section 6.3: + * + * If a prefix in the NLRI field is semantically + * incorrect + * (e.g., an unexpected multicast IP address), + * an error SHOULD + * be logged locally, and the prefix SHOULD be + * ignored. + */ + zlog_err( + "%s: IPv4 labeled-unicast NLRI is multicast address %s, ignoring", + peer->host, inet_ntoa(p.u.prefix4)); + continue; + } + } + + /* Check address. */ + if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) { + if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) { + char buf[BUFSIZ]; + + zlog_err( + "%s: IPv6 labeled-unicast NLRI is link-local address %s, ignoring", + peer->host, + inet_ntop(AF_INET6, &p.u.prefix6, buf, + BUFSIZ)); + + continue; + } + + if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) { + char buf[BUFSIZ]; + + zlog_err( + "%s: IPv6 unicast NLRI is multicast address %s, ignoring", + peer->host, + inet_ntop(AF_INET6, &p.u.prefix6, buf, + BUFSIZ)); + + continue; + } + } + + if (attr) { + bgp_update(peer, &p, addpath_id, attr, packet->afi, + SAFI_UNICAST, ZEBRA_ROUTE_BGP, + BGP_ROUTE_NORMAL, NULL, &label, 0, NULL); + } else { + bgp_withdraw(peer, &p, addpath_id, attr, packet->afi, + SAFI_UNICAST, ZEBRA_ROUTE_BGP, + BGP_ROUTE_NORMAL, NULL, &label, NULL); + } + } + + /* Packet length consistency check. */ + if (pnt != lim) { + zlog_err( + "%s [Error] Update packet error / L-U (%zu data remaining after parsing)", + peer->host, lim - pnt); + return -1; + } + + return 0; } diff --git a/bgpd/bgp_label.h b/bgpd/bgp_label.h index a0994d68a..0b5eaa712 100644 --- a/bgpd/bgp_label.h +++ b/bgpd/bgp_label.h @@ -29,103 +29,95 @@ struct bgp_node; struct bgp_info; struct peer; -extern void bgp_reg_dereg_for_label (struct bgp_node *rn, struct bgp_info *ri, - int reg); +extern void bgp_reg_dereg_for_label(struct bgp_node *rn, struct bgp_info *ri, + int reg); extern int bgp_parse_fec_update(void); extern mpls_label_t bgp_adv_label(struct bgp_node *rn, struct bgp_info *ri, - struct peer *to, afi_t afi, safi_t safi); + struct peer *to, afi_t afi, safi_t safi); -extern int bgp_nlri_parse_label (struct peer *peer, struct attr *attr, - struct bgp_nlri *packet); +extern int bgp_nlri_parse_label(struct peer *peer, struct attr *attr, + struct bgp_nlri *packet); -static inline int -bgp_labeled_safi (safi_t safi) +static inline int bgp_labeled_safi(safi_t safi) { - /* NOTE: This API really says a label (tag) MAY be present. Not all EVPN - * routes will have a label. - */ - if ((safi == SAFI_LABELED_UNICAST) || (safi == SAFI_MPLS_VPN) || - (safi == SAFI_EVPN)) - return 1; - return 0; + /* NOTE: This API really says a label (tag) MAY be present. Not all EVPN + * routes will have a label. + */ + if ((safi == SAFI_LABELED_UNICAST) || (safi == SAFI_MPLS_VPN) + || (safi == SAFI_EVPN)) + return 1; + return 0; } -static inline int -bgp_is_withdraw_label (mpls_label_t *label) +static inline int bgp_is_withdraw_label(mpls_label_t *label) { - u_char *pkt = (u_char *) label; - - /* The check on pkt[2] for 0x00 or 0x02 is in case bgp_set_valid_label() - * was called on the withdraw label */ - if ((pkt[0] == 0x80) && (pkt[1] == 0x00) && ((pkt[2] == 0x00) || (pkt[2] == 0x02))) - return 1; - return 0; + u_char *pkt = (u_char *)label; + + /* The check on pkt[2] for 0x00 or 0x02 is in case bgp_set_valid_label() + * was called on the withdraw label */ + if ((pkt[0] == 0x80) && (pkt[1] == 0x00) + && ((pkt[2] == 0x00) || (pkt[2] == 0x02))) + return 1; + return 0; } -static inline int -bgp_is_valid_label (mpls_label_t *label) +static inline int bgp_is_valid_label(mpls_label_t *label) { - u_char *t= (u_char *) label; - if (!t) - return 0; - return (t[2] & 0x02); + u_char *t = (u_char *)label; + if (!t) + return 0; + return (t[2] & 0x02); } -static inline void -bgp_set_valid_label (mpls_label_t *label) +static inline void bgp_set_valid_label(mpls_label_t *label) { - u_char *t= (u_char *) label; - if (t) - t[2] |= 0x02; + u_char *t = (u_char *)label; + if (t) + t[2] |= 0x02; } -static inline void -bgp_unset_valid_label (mpls_label_t *label) +static inline void bgp_unset_valid_label(mpls_label_t *label) { - u_char *t= (u_char *) label; - if (t) - t[2] &= ~0x02; + u_char *t = (u_char *)label; + if (t) + t[2] &= ~0x02; } -static inline void -bgp_register_for_label (struct bgp_node *rn, struct bgp_info *ri) +static inline void bgp_register_for_label(struct bgp_node *rn, + struct bgp_info *ri) { - bgp_reg_dereg_for_label (rn, ri, 1); + bgp_reg_dereg_for_label(rn, ri, 1); } -static inline void -bgp_unregister_for_label (struct bgp_node *rn) +static inline void bgp_unregister_for_label(struct bgp_node *rn) { - bgp_reg_dereg_for_label (rn, NULL, 0); + bgp_reg_dereg_for_label(rn, NULL, 0); } /* Label stream to value */ -static inline u_int32_t -label_pton (mpls_label_t *label) +static inline u_int32_t label_pton(mpls_label_t *label) { - u_char *t= (u_char *) label; - return ((((unsigned int) t[0]) << 12) | (((unsigned int) t[1]) << 4) | - ((unsigned int) ((t[2] & 0xF0) >> 4))); + u_char *t = (u_char *)label; + return ((((unsigned int)t[0]) << 12) | (((unsigned int)t[1]) << 4) + | ((unsigned int)((t[2] & 0xF0) >> 4))); } /* Encode label values */ -static inline void -label_ntop (u_int32_t l, int bos, mpls_label_t *label) +static inline void label_ntop(u_int32_t l, int bos, mpls_label_t *label) { - u_char *t= (u_char *) label; - t[0] = ((l & 0x000FF000) >> 12); - t[1] = ((l & 0x00000FF0) >> 4); - t[2] = ((l & 0x0000000F) << 4); - if (bos) - t[2] |= 0x01; + u_char *t = (u_char *)label; + t[0] = ((l & 0x000FF000) >> 12); + t[1] = ((l & 0x00000FF0) >> 4); + t[2] = ((l & 0x0000000F) << 4); + if (bos) + t[2] |= 0x01; } /* Return BOS value of label stream */ -static inline u_char -label_bos (mpls_label_t *label) +static inline u_char label_bos(mpls_label_t *label) { - u_char *t= (u_char *) label; - return (t[2] & 0x01); + u_char *t = (u_char *)label; + return (t[2] & 0x01); }; #endif /* _BGP_LABEL_H */ diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c index 23c19f70c..f4393c1b2 100644 --- a/bgpd/bgp_lcommunity.c +++ b/bgpd/bgp_lcommunity.c @@ -34,29 +34,26 @@ static struct hash *lcomhash; /* Allocate a new lcommunities. */ -static struct lcommunity * -lcommunity_new (void) +static struct lcommunity *lcommunity_new(void) { - return (struct lcommunity *) XCALLOC (MTYPE_LCOMMUNITY, - sizeof (struct lcommunity)); + return (struct lcommunity *)XCALLOC(MTYPE_LCOMMUNITY, + sizeof(struct lcommunity)); } /* Allocate lcommunities. */ -void -lcommunity_free (struct lcommunity **lcom) +void lcommunity_free(struct lcommunity **lcom) { - if ((*lcom)->val) - XFREE (MTYPE_LCOMMUNITY_VAL, (*lcom)->val); - if ((*lcom)->str) - XFREE (MTYPE_LCOMMUNITY_STR, (*lcom)->str); - XFREE (MTYPE_LCOMMUNITY, *lcom); - lcom = NULL; + if ((*lcom)->val) + XFREE(MTYPE_LCOMMUNITY_VAL, (*lcom)->val); + if ((*lcom)->str) + XFREE(MTYPE_LCOMMUNITY_STR, (*lcom)->str); + XFREE(MTYPE_LCOMMUNITY, *lcom); + lcom = NULL; } -static void -lcommunity_hash_free (struct lcommunity *lcom) +static void lcommunity_hash_free(struct lcommunity *lcom) { - lcommunity_free (&lcom); + lcommunity_free(&lcom); } /* Add a new Large Communities value to Large Communities @@ -64,329 +61,308 @@ lcommunity_hash_free (struct lcommunity *lcom) structure, we don't add the value. Newly added value is sorted by numerical order. When the value is added to the structure return 1 else return 0. */ -static int -lcommunity_add_val (struct lcommunity *lcom, struct lcommunity_val *lval) +static int lcommunity_add_val(struct lcommunity *lcom, + struct lcommunity_val *lval) { - u_int8_t *p; - int ret; - int c; - - /* When this is fist value, just add it. */ - if (lcom->val == NULL) - { - lcom->size++; - lcom->val = XMALLOC (MTYPE_LCOMMUNITY_VAL, lcom_length (lcom)); - memcpy (lcom->val, lval->val, LCOMMUNITY_SIZE); - return 1; - } - - /* If the value already exists in the structure return 0. */ - c = 0; - for (p = lcom->val; c < lcom->size; p += LCOMMUNITY_SIZE, c++) - { - ret = memcmp (p, lval->val, LCOMMUNITY_SIZE); - if (ret == 0) - return 0; - if (ret > 0) - break; - } - - /* Add the value to the structure with numerical sorting. */ - lcom->size++; - lcom->val = XREALLOC (MTYPE_LCOMMUNITY_VAL, lcom->val, lcom_length (lcom)); - - memmove (lcom->val + (c + 1) * LCOMMUNITY_SIZE, - lcom->val + c * LCOMMUNITY_SIZE, - (lcom->size - 1 - c) * LCOMMUNITY_SIZE); - memcpy (lcom->val + c * LCOMMUNITY_SIZE, lval->val, LCOMMUNITY_SIZE); - - return 1; + u_int8_t *p; + int ret; + int c; + + /* When this is fist value, just add it. */ + if (lcom->val == NULL) { + lcom->size++; + lcom->val = XMALLOC(MTYPE_LCOMMUNITY_VAL, lcom_length(lcom)); + memcpy(lcom->val, lval->val, LCOMMUNITY_SIZE); + return 1; + } + + /* If the value already exists in the structure return 0. */ + c = 0; + for (p = lcom->val; c < lcom->size; p += LCOMMUNITY_SIZE, c++) { + ret = memcmp(p, lval->val, LCOMMUNITY_SIZE); + if (ret == 0) + return 0; + if (ret > 0) + break; + } + + /* Add the value to the structure with numerical sorting. */ + lcom->size++; + lcom->val = + XREALLOC(MTYPE_LCOMMUNITY_VAL, lcom->val, lcom_length(lcom)); + + memmove(lcom->val + (c + 1) * LCOMMUNITY_SIZE, + lcom->val + c * LCOMMUNITY_SIZE, + (lcom->size - 1 - c) * LCOMMUNITY_SIZE); + memcpy(lcom->val + c * LCOMMUNITY_SIZE, lval->val, LCOMMUNITY_SIZE); + + return 1; } /* This function takes pointer to Large Communites strucutre then create a new Large Communities structure by uniq and sort each Large Communities value. */ -struct lcommunity * -lcommunity_uniq_sort (struct lcommunity *lcom) +struct lcommunity *lcommunity_uniq_sort(struct lcommunity *lcom) { - int i; - struct lcommunity *new; - struct lcommunity_val *lval; + int i; + struct lcommunity *new; + struct lcommunity_val *lval; - if (! lcom) - return NULL; + if (!lcom) + return NULL; - new = lcommunity_new (); + new = lcommunity_new(); - for (i = 0; i < lcom->size; i++) - { - lval = (struct lcommunity_val *) (lcom->val + (i * LCOMMUNITY_SIZE)); - lcommunity_add_val (new, lval); - } - return new; + for (i = 0; i < lcom->size; i++) { + lval = (struct lcommunity_val *)(lcom->val + + (i * LCOMMUNITY_SIZE)); + lcommunity_add_val(new, lval); + } + return new; } /* Parse Large Communites Attribute in BGP packet. */ -struct lcommunity * -lcommunity_parse (u_int8_t *pnt, u_short length) +struct lcommunity *lcommunity_parse(u_int8_t *pnt, u_short length) { - struct lcommunity tmp; - struct lcommunity *new; + struct lcommunity tmp; + struct lcommunity *new; - /* Length check. */ - if (length % LCOMMUNITY_SIZE) - return NULL; + /* Length check. */ + if (length % LCOMMUNITY_SIZE) + return NULL; - /* Prepare tmporary structure for making a new Large Communities - Attribute. */ - tmp.size = length / LCOMMUNITY_SIZE; - tmp.val = pnt; + /* Prepare tmporary structure for making a new Large Communities + Attribute. */ + tmp.size = length / LCOMMUNITY_SIZE; + tmp.val = pnt; - /* Create a new Large Communities Attribute by uniq and sort each - Large Communities value */ - new = lcommunity_uniq_sort (&tmp); + /* Create a new Large Communities Attribute by uniq and sort each + Large Communities value */ + new = lcommunity_uniq_sort(&tmp); - return lcommunity_intern (new); + return lcommunity_intern(new); } /* Duplicate the Large Communities Attribute structure. */ -struct lcommunity * -lcommunity_dup (struct lcommunity *lcom) +struct lcommunity *lcommunity_dup(struct lcommunity *lcom) { - struct lcommunity *new; - - new = XCALLOC (MTYPE_LCOMMUNITY, sizeof (struct lcommunity)); - new->size = lcom->size; - if (new->size) - { - new->val = XMALLOC (MTYPE_LCOMMUNITY_VAL, lcom->size * LCOMMUNITY_SIZE); - memcpy (new->val, lcom->val, lcom->size * LCOMMUNITY_SIZE); - } - else - new->val = NULL; - return new; + struct lcommunity *new; + + new = XCALLOC(MTYPE_LCOMMUNITY, sizeof(struct lcommunity)); + new->size = lcom->size; + if (new->size) { + new->val = XMALLOC(MTYPE_LCOMMUNITY_VAL, + lcom->size * LCOMMUNITY_SIZE); + memcpy(new->val, lcom->val, lcom->size * LCOMMUNITY_SIZE); + } else + new->val = NULL; + return new; } /* Retrun string representation of communities attribute. */ -char * -lcommunity_str (struct lcommunity *lcom) +char *lcommunity_str(struct lcommunity *lcom) { - if (! lcom->str) - lcom->str = lcommunity_lcom2str (lcom, LCOMMUNITY_FORMAT_DISPLAY); - return lcom->str; + if (!lcom->str) + lcom->str = + lcommunity_lcom2str(lcom, LCOMMUNITY_FORMAT_DISPLAY); + return lcom->str; } /* Merge two Large Communities Attribute structure. */ -struct lcommunity * -lcommunity_merge (struct lcommunity *lcom1, struct lcommunity *lcom2) +struct lcommunity *lcommunity_merge(struct lcommunity *lcom1, + struct lcommunity *lcom2) { - if (lcom1->val) - lcom1->val = XREALLOC (MTYPE_LCOMMUNITY_VAL, lcom1->val, - (lcom1->size + lcom2->size) * LCOMMUNITY_SIZE); - else - lcom1->val = XMALLOC (MTYPE_LCOMMUNITY_VAL, - (lcom1->size + lcom2->size) * LCOMMUNITY_SIZE); - - memcpy (lcom1->val + (lcom1->size * LCOMMUNITY_SIZE), - lcom2->val, lcom2->size * LCOMMUNITY_SIZE); - lcom1->size += lcom2->size; - - return lcom1; + if (lcom1->val) + lcom1->val = + XREALLOC(MTYPE_LCOMMUNITY_VAL, lcom1->val, + (lcom1->size + lcom2->size) * LCOMMUNITY_SIZE); + else + lcom1->val = + XMALLOC(MTYPE_LCOMMUNITY_VAL, + (lcom1->size + lcom2->size) * LCOMMUNITY_SIZE); + + memcpy(lcom1->val + (lcom1->size * LCOMMUNITY_SIZE), lcom2->val, + lcom2->size * LCOMMUNITY_SIZE); + lcom1->size += lcom2->size; + + return lcom1; } /* Intern Large Communities Attribute. */ -struct lcommunity * -lcommunity_intern (struct lcommunity *lcom) +struct lcommunity *lcommunity_intern(struct lcommunity *lcom) { - struct lcommunity *find; + struct lcommunity *find; - assert (lcom->refcnt == 0); + assert(lcom->refcnt == 0); - find = (struct lcommunity *) hash_get (lcomhash, lcom, hash_alloc_intern); + find = (struct lcommunity *)hash_get(lcomhash, lcom, hash_alloc_intern); - if (find != lcom) - lcommunity_free (&lcom); + if (find != lcom) + lcommunity_free(&lcom); - find->refcnt++; + find->refcnt++; - if (! find->str) - find->str = lcommunity_lcom2str (find, LCOMMUNITY_FORMAT_DISPLAY); + if (!find->str) + find->str = + lcommunity_lcom2str(find, LCOMMUNITY_FORMAT_DISPLAY); - return find; + return find; } /* Unintern Large Communities Attribute. */ -void -lcommunity_unintern (struct lcommunity **lcom) +void lcommunity_unintern(struct lcommunity **lcom) { - struct lcommunity *ret; + struct lcommunity *ret; - if ((*lcom)->refcnt) - (*lcom)->refcnt--; + if ((*lcom)->refcnt) + (*lcom)->refcnt--; - /* Pull off from hash. */ - if ((*lcom)->refcnt == 0) - { - /* Large community must be in the hash. */ - ret = (struct lcommunity *) hash_release (lcomhash, *lcom); - assert (ret != NULL); + /* Pull off from hash. */ + if ((*lcom)->refcnt == 0) { + /* Large community must be in the hash. */ + ret = (struct lcommunity *)hash_release(lcomhash, *lcom); + assert(ret != NULL); - lcommunity_free (lcom); - } + lcommunity_free(lcom); + } } /* Utility function to make hash key. */ -unsigned int -lcommunity_hash_make (void *arg) +unsigned int lcommunity_hash_make(void *arg) { - const struct lcommunity *lcom = arg; - int size = lcom->size * LCOMMUNITY_SIZE; - u_int8_t *pnt = lcom->val; - unsigned int key = 0; - int c; - - for (c = 0; c < size; c += LCOMMUNITY_SIZE) - { - key += pnt[c]; - key += pnt[c + 1]; - key += pnt[c + 2]; - key += pnt[c + 3]; - key += pnt[c + 4]; - key += pnt[c + 5]; - key += pnt[c + 6]; - key += pnt[c + 7]; - key += pnt[c + 8]; - key += pnt[c + 9]; - key += pnt[c + 10]; - key += pnt[c + 11]; - } - - return key; + const struct lcommunity *lcom = arg; + int size = lcom->size * LCOMMUNITY_SIZE; + u_int8_t *pnt = lcom->val; + unsigned int key = 0; + int c; + + for (c = 0; c < size; c += LCOMMUNITY_SIZE) { + key += pnt[c]; + key += pnt[c + 1]; + key += pnt[c + 2]; + key += pnt[c + 3]; + key += pnt[c + 4]; + key += pnt[c + 5]; + key += pnt[c + 6]; + key += pnt[c + 7]; + key += pnt[c + 8]; + key += pnt[c + 9]; + key += pnt[c + 10]; + key += pnt[c + 11]; + } + + return key; } /* Compare two Large Communities Attribute structure. */ -int -lcommunity_cmp (const void *arg1, const void *arg2) +int lcommunity_cmp(const void *arg1, const void *arg2) { - const struct lcommunity *lcom1 = arg1; - const struct lcommunity *lcom2 = arg2; + const struct lcommunity *lcom1 = arg1; + const struct lcommunity *lcom2 = arg2; - return (lcom1->size == lcom2->size - && memcmp (lcom1->val, lcom2->val, lcom1->size * LCOMMUNITY_SIZE) == 0); + return (lcom1->size == lcom2->size + && memcmp(lcom1->val, lcom2->val, lcom1->size * LCOMMUNITY_SIZE) + == 0); } /* Return communities hash. */ -struct hash * -lcommunity_hash (void) +struct hash *lcommunity_hash(void) { - return lcomhash; + return lcomhash; } /* Initialize Large Comminities related hash. */ -void -lcommunity_init (void) +void lcommunity_init(void) { - lcomhash = hash_create (lcommunity_hash_make, lcommunity_cmp, NULL); + lcomhash = hash_create(lcommunity_hash_make, lcommunity_cmp, NULL); } -void -lcommunity_finish (void) +void lcommunity_finish(void) { - hash_clean (lcomhash, (void (*)(void *))lcommunity_hash_free); - hash_free (lcomhash); - lcomhash = NULL; + hash_clean(lcomhash, (void (*)(void *))lcommunity_hash_free); + hash_free(lcomhash); + lcomhash = NULL; } /* Large Communities token enum. */ -enum lcommunity_token -{ - lcommunity_token_unknown = 0, - lcommunity_token_val, +enum lcommunity_token { + lcommunity_token_unknown = 0, + lcommunity_token_val, }; /* Get next Large Communities token from the string. */ -static const char * -lcommunity_gettoken (const char *str, struct lcommunity_val *lval, - enum lcommunity_token *token) +static const char *lcommunity_gettoken(const char *str, + struct lcommunity_val *lval, + enum lcommunity_token *token) { - const char *p = str; - - /* Skip white space. */ - while (isspace ((int) *p)) - { - p++; - str++; - } - - /* Check the end of the line. */ - if (*p == '\0') - return NULL; - - /* Community value. */ - if (isdigit ((int) *p)) - { - int separator = 0; - int digit = 0; - u_int32_t globaladmin = 0; - u_int32_t localdata1 = 0; - u_int32_t localdata2 = 0; - - while (isdigit ((int) *p) || *p == ':') - { - if (*p == ':') - { - if (separator == 2) - { - *token = lcommunity_token_unknown; - return NULL; + const char *p = str; + + /* Skip white space. */ + while (isspace((int)*p)) { + p++; + str++; + } + + /* Check the end of the line. */ + if (*p == '\0') + return NULL; + + /* Community value. */ + if (isdigit((int)*p)) { + int separator = 0; + int digit = 0; + u_int32_t globaladmin = 0; + u_int32_t localdata1 = 0; + u_int32_t localdata2 = 0; + + while (isdigit((int)*p) || *p == ':') { + if (*p == ':') { + if (separator == 2) { + *token = lcommunity_token_unknown; + return NULL; + } else { + separator++; + digit = 0; + if (separator == 1) { + globaladmin = localdata2; + } else { + localdata1 = localdata2; + } + localdata2 = 0; + } + } else { + digit = 1; + localdata2 *= 10; + localdata2 += (*p - '0'); + } + p++; } - else - { - separator++; - digit = 0; - if (separator == 1) { - globaladmin = localdata2; - } else { - localdata1 = localdata2; - } - localdata2 = 0; + if (!digit) { + *token = lcommunity_token_unknown; + return NULL; } - } - else - { - digit = 1; - localdata2 *= 10; - localdata2 += (*p - '0'); - } - p++; - } - if (! digit) - { - *token = lcommunity_token_unknown; - return NULL; - } - /* - * Copy the large comm. - */ - lval->val[0] = (globaladmin >> 24) & 0xff; - lval->val[1] = (globaladmin >> 16) & 0xff; - lval->val[2] = (globaladmin >> 8) & 0xff; - lval->val[3] = globaladmin & 0xff; - lval->val[4] = (localdata1 >> 24) & 0xff; - lval->val[5] = (localdata1 >> 16) & 0xff; - lval->val[6] = (localdata1 >> 8) & 0xff; - lval->val[7] = localdata1 & 0xff; - lval->val[8] = (localdata2 >> 24) & 0xff; - lval->val[9] = (localdata2 >> 16) & 0xff; - lval->val[10] = (localdata2 >> 8) & 0xff; - lval->val[11] = localdata2 & 0xff; - - *token = lcommunity_token_val; - return p; - } - *token = lcommunity_token_unknown; - return p; + /* + * Copy the large comm. + */ + lval->val[0] = (globaladmin >> 24) & 0xff; + lval->val[1] = (globaladmin >> 16) & 0xff; + lval->val[2] = (globaladmin >> 8) & 0xff; + lval->val[3] = globaladmin & 0xff; + lval->val[4] = (localdata1 >> 24) & 0xff; + lval->val[5] = (localdata1 >> 16) & 0xff; + lval->val[6] = (localdata1 >> 8) & 0xff; + lval->val[7] = localdata1 & 0xff; + lval->val[8] = (localdata2 >> 24) & 0xff; + lval->val[9] = (localdata2 >> 16) & 0xff; + lval->val[10] = (localdata2 >> 8) & 0xff; + lval->val[11] = localdata2 & 0xff; + + *token = lcommunity_token_val; + return p; + } + *token = lcommunity_token_unknown; + return p; } /* @@ -396,174 +372,168 @@ lcommunity_gettoken (const char *str, struct lcommunity_val *lval, When string includes keyword for each large community value. Please specify keyword_included as non-zero value. */ -struct lcommunity * -lcommunity_str2com (const char *str) +struct lcommunity *lcommunity_str2com(const char *str) { - struct lcommunity *lcom = NULL; - enum lcommunity_token token = lcommunity_token_unknown; - struct lcommunity_val lval; - - while ((str = lcommunity_gettoken (str, &lval, &token))) - { - switch (token) - { - case lcommunity_token_val: - if (lcom == NULL) - lcom = lcommunity_new (); - lcommunity_add_val (lcom, &lval); - break; - case lcommunity_token_unknown: - default: - if (lcom) - lcommunity_free (&lcom); - return NULL; - } - } - return lcom; + struct lcommunity *lcom = NULL; + enum lcommunity_token token = lcommunity_token_unknown; + struct lcommunity_val lval; + + while ((str = lcommunity_gettoken(str, &lval, &token))) { + switch (token) { + case lcommunity_token_val: + if (lcom == NULL) + lcom = lcommunity_new(); + lcommunity_add_val(lcom, &lval); + break; + case lcommunity_token_unknown: + default: + if (lcom) + lcommunity_free(&lcom); + return NULL; + } + } + return lcom; } -int -lcommunity_include (struct lcommunity *lcom, u_char *ptr) +int lcommunity_include(struct lcommunity *lcom, u_char *ptr) { - int i; - u_char *lcom_ptr; - - lcom_ptr = lcom->val; - for (i = 0; i < lcom->size; i++) { - lcom_ptr += (i * LCOMMUNITY_SIZE); - if (memcmp (ptr, lcom_ptr, LCOMMUNITY_SIZE) == 0) - return 1; - } - return 0; + int i; + u_char *lcom_ptr; + + lcom_ptr = lcom->val; + for (i = 0; i < lcom->size; i++) { + lcom_ptr += (i * LCOMMUNITY_SIZE); + if (memcmp(ptr, lcom_ptr, LCOMMUNITY_SIZE) == 0) + return 1; + } + return 0; } /* Convert large community attribute to string. The large coms will be in 65535:65531:0 format. */ -char * -lcommunity_lcom2str (struct lcommunity *lcom, int format) +char *lcommunity_lcom2str(struct lcommunity *lcom, int format) { - int i; - u_int8_t *pnt; + int i; + u_int8_t *pnt; #define LCOMMUNITY_STR_DEFAULT_LEN 40 - int str_size; - int str_pnt; - char *str_buf; - int len = 0; - int first = 1; - u_int32_t globaladmin, localdata1, localdata2; - - if (lcom->size == 0) - { - str_buf = XMALLOC (MTYPE_LCOMMUNITY_STR, 1); - str_buf[0] = '\0'; - return str_buf; - } - - /* Prepare buffer. */ - str_buf = XMALLOC (MTYPE_LCOMMUNITY_STR, LCOMMUNITY_STR_DEFAULT_LEN + 1); - str_size = LCOMMUNITY_STR_DEFAULT_LEN + 1; - str_pnt = 0; - - for (i = 0; i < lcom->size; i++) - { - /* Make it sure size is enough. */ - while (str_pnt + LCOMMUNITY_STR_DEFAULT_LEN >= str_size) - { - str_size *= 2; - str_buf = XREALLOC (MTYPE_LCOMMUNITY_STR, str_buf, str_size); + int str_size; + int str_pnt; + char *str_buf; + int len = 0; + int first = 1; + u_int32_t globaladmin, localdata1, localdata2; + + if (lcom->size == 0) { + str_buf = XMALLOC(MTYPE_LCOMMUNITY_STR, 1); + str_buf[0] = '\0'; + return str_buf; } - /* Space between each value. */ - if (! first) - str_buf[str_pnt++] = ' '; - - pnt = lcom->val + (i * 12); - - globaladmin = (*pnt++ << 24); - globaladmin |= (*pnt++ << 16); - globaladmin |= (*pnt++ << 8); - globaladmin |= (*pnt++); - - localdata1 = (*pnt++ << 24); - localdata1 |= (*pnt++ << 16); - localdata1 |= (*pnt++ << 8); - localdata1 |= (*pnt++); - - localdata2 = (*pnt++ << 24); - localdata2 |= (*pnt++ << 16); - localdata2 |= (*pnt++ << 8); - localdata2 |= (*pnt++); - - len = sprintf( str_buf + str_pnt, "%u:%u:%u", globaladmin, - localdata1, localdata2); - str_pnt += len; - first = 0; - } - return str_buf; + /* Prepare buffer. */ + str_buf = XMALLOC(MTYPE_LCOMMUNITY_STR, LCOMMUNITY_STR_DEFAULT_LEN + 1); + str_size = LCOMMUNITY_STR_DEFAULT_LEN + 1; + str_pnt = 0; + + for (i = 0; i < lcom->size; i++) { + /* Make it sure size is enough. */ + while (str_pnt + LCOMMUNITY_STR_DEFAULT_LEN >= str_size) { + str_size *= 2; + str_buf = XREALLOC(MTYPE_LCOMMUNITY_STR, str_buf, + str_size); + } + + /* Space between each value. */ + if (!first) + str_buf[str_pnt++] = ' '; + + pnt = lcom->val + (i * 12); + + globaladmin = (*pnt++ << 24); + globaladmin |= (*pnt++ << 16); + globaladmin |= (*pnt++ << 8); + globaladmin |= (*pnt++); + + localdata1 = (*pnt++ << 24); + localdata1 |= (*pnt++ << 16); + localdata1 |= (*pnt++ << 8); + localdata1 |= (*pnt++); + + localdata2 = (*pnt++ << 24); + localdata2 |= (*pnt++ << 16); + localdata2 |= (*pnt++ << 8); + localdata2 |= (*pnt++); + + len = sprintf(str_buf + str_pnt, "%u:%u:%u", globaladmin, + localdata1, localdata2); + str_pnt += len; + first = 0; + } + return str_buf; } -int -lcommunity_match (const struct lcommunity *lcom1, - const struct lcommunity *lcom2) +int lcommunity_match(const struct lcommunity *lcom1, + const struct lcommunity *lcom2) { - int i = 0; - int j = 0; - - if (lcom1 == NULL && lcom2 == NULL) - return 1; - - if (lcom1 == NULL || lcom2 == NULL) - return 0; - - if (lcom1->size < lcom2->size) - return 0; - - /* Every community on com2 needs to be on com1 for this to match */ - while (i < lcom1->size && j < lcom2->size) - { - if (memcmp (lcom1->val + (i*12), lcom2->val + (j*12), LCOMMUNITY_SIZE) == 0) - j++; - i++; - } - - if (j == lcom2->size) - return 1; - else - return 0; + int i = 0; + int j = 0; + + if (lcom1 == NULL && lcom2 == NULL) + return 1; + + if (lcom1 == NULL || lcom2 == NULL) + return 0; + + if (lcom1->size < lcom2->size) + return 0; + + /* Every community on com2 needs to be on com1 for this to match */ + while (i < lcom1->size && j < lcom2->size) { + if (memcmp(lcom1->val + (i * 12), lcom2->val + (j * 12), + LCOMMUNITY_SIZE) + == 0) + j++; + i++; + } + + if (j == lcom2->size) + return 1; + else + return 0; } /* Delete one lcommunity. */ -void -lcommunity_del_val (struct lcommunity *lcom, u_char *ptr) +void lcommunity_del_val(struct lcommunity *lcom, u_char *ptr) { - int i = 0; - int c = 0; - - if (! lcom->val) - return; - - while (i < lcom->size) - { - if (memcmp (lcom->val + i*LCOMMUNITY_SIZE, ptr, LCOMMUNITY_SIZE) == 0) - { - c = lcom->size -i -1; - - if (c > 0) - memmove (lcom->val + i*LCOMMUNITY_SIZE, lcom->val + (i + 1)*LCOMMUNITY_SIZE, c * LCOMMUNITY_SIZE); - - lcom->size--; - - if (lcom->size > 0) - lcom->val = XREALLOC (MTYPE_COMMUNITY_VAL, lcom->val, - lcom_length (lcom)); - else - { - XFREE (MTYPE_COMMUNITY_VAL, lcom->val); - lcom->val = NULL; - } - return; + int i = 0; + int c = 0; + + if (!lcom->val) + return; + + while (i < lcom->size) { + if (memcmp(lcom->val + i * LCOMMUNITY_SIZE, ptr, + LCOMMUNITY_SIZE) + == 0) { + c = lcom->size - i - 1; + + if (c > 0) + memmove(lcom->val + i * LCOMMUNITY_SIZE, + lcom->val + (i + 1) * LCOMMUNITY_SIZE, + c * LCOMMUNITY_SIZE); + + lcom->size--; + + if (lcom->size > 0) + lcom->val = + XREALLOC(MTYPE_COMMUNITY_VAL, lcom->val, + lcom_length(lcom)); + else { + XFREE(MTYPE_COMMUNITY_VAL, lcom->val); + lcom->val = NULL; + } + return; + } + i++; } - i++; - } } diff --git a/bgpd/bgp_lcommunity.h b/bgpd/bgp_lcommunity.h index e401c8d8f..1a3304e71 100644 --- a/bgpd/bgp_lcommunity.h +++ b/bgpd/bgp_lcommunity.h @@ -30,45 +30,45 @@ #define LCOMMUNITY_SIZE 12 /* Large Communities attribute. */ -struct lcommunity -{ - /* Reference counter. */ - unsigned long refcnt; +struct lcommunity { + /* Reference counter. */ + unsigned long refcnt; - /* Size of Extended Communities attribute. */ - int size; + /* Size of Extended Communities attribute. */ + int size; - /* Extended Communities value. */ - u_int8_t *val; + /* Extended Communities value. */ + u_int8_t *val; - /* Human readable format string. */ - char *str; + /* Human readable format string. */ + char *str; }; /* Extended community value is eight octet. */ -struct lcommunity_val -{ - char val[LCOMMUNITY_SIZE]; +struct lcommunity_val { + char val[LCOMMUNITY_SIZE]; }; #define lcom_length(X) ((X)->size * LCOMMUNITY_SIZE) -extern void lcommunity_init (void); -extern void lcommunity_finish (void); -extern void lcommunity_free (struct lcommunity **); -extern struct lcommunity *lcommunity_parse (u_int8_t *, u_short); -extern struct lcommunity *lcommunity_dup (struct lcommunity *); -extern struct lcommunity *lcommunity_merge (struct lcommunity *, struct lcommunity *); -extern struct lcommunity *lcommunity_uniq_sort (struct lcommunity *); -extern struct lcommunity *lcommunity_intern (struct lcommunity *); -extern int lcommunity_cmp (const void *, const void *); -extern void lcommunity_unintern (struct lcommunity **); -extern unsigned int lcommunity_hash_make (void *); -extern struct hash *lcommunity_hash (void); -extern struct lcommunity *lcommunity_str2com (const char *); -extern char *lcommunity_lcom2str (struct lcommunity *, int); -extern int lcommunity_match (const struct lcommunity *, const struct lcommunity *); -extern char *lcommunity_str (struct lcommunity *); -extern int lcommunity_include (struct lcommunity *lcom, u_char *ptr); -extern void lcommunity_del_val (struct lcommunity *lcom, u_char *ptr); +extern void lcommunity_init(void); +extern void lcommunity_finish(void); +extern void lcommunity_free(struct lcommunity **); +extern struct lcommunity *lcommunity_parse(u_int8_t *, u_short); +extern struct lcommunity *lcommunity_dup(struct lcommunity *); +extern struct lcommunity *lcommunity_merge(struct lcommunity *, + struct lcommunity *); +extern struct lcommunity *lcommunity_uniq_sort(struct lcommunity *); +extern struct lcommunity *lcommunity_intern(struct lcommunity *); +extern int lcommunity_cmp(const void *, const void *); +extern void lcommunity_unintern(struct lcommunity **); +extern unsigned int lcommunity_hash_make(void *); +extern struct hash *lcommunity_hash(void); +extern struct lcommunity *lcommunity_str2com(const char *); +extern char *lcommunity_lcom2str(struct lcommunity *, int); +extern int lcommunity_match(const struct lcommunity *, + const struct lcommunity *); +extern char *lcommunity_str(struct lcommunity *); +extern int lcommunity_include(struct lcommunity *lcom, u_char *ptr); +extern void lcommunity_del_val(struct lcommunity *lcom, u_char *ptr); #endif /* _QUAGGA_BGP_LCOMMUNITY_H */ diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 7841d510b..25a562ed6 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -60,112 +60,101 @@ #endif /* bgpd options, we use GNU getopt library. */ -static const struct option longopts[] = -{ - { "bgp_port", required_argument, NULL, 'p'}, - { "listenon", required_argument, NULL, 'l'}, - { "retain", no_argument, NULL, 'r'}, - { "no_kernel", no_argument, NULL, 'n'}, - { "skip_runas", no_argument, NULL, 'S'}, - { "ecmp", required_argument, NULL, 'e'}, - { 0 } -}; +static const struct option longopts[] = { + {"bgp_port", required_argument, NULL, 'p'}, + {"listenon", required_argument, NULL, 'l'}, + {"retain", no_argument, NULL, 'r'}, + {"no_kernel", no_argument, NULL, 'n'}, + {"skip_runas", no_argument, NULL, 'S'}, + {"ecmp", required_argument, NULL, 'e'}, + {0}}; /* signal definitions */ -void sighup (void); -void sigint (void); -void sigusr1 (void); +void sighup(void); +void sigint(void); +void sigusr1(void); -static void bgp_exit (int); -static void bgp_vrf_terminate (void); +static void bgp_exit(int); +static void bgp_vrf_terminate(void); -static struct quagga_signal_t bgp_signals[] = -{ - { - .signal = SIGHUP, - .handler = &sighup, - }, - { - .signal = SIGUSR1, - .handler = &sigusr1, - }, - { - .signal = SIGINT, - .handler = &sigint, - }, - { - .signal = SIGTERM, - .handler = &sigint, - }, +static struct quagga_signal_t bgp_signals[] = { + { + .signal = SIGHUP, + .handler = &sighup, + }, + { + .signal = SIGUSR1, + .handler = &sigusr1, + }, + { + .signal = SIGINT, + .handler = &sigint, + }, + { + .signal = SIGTERM, + .handler = &sigint, + }, }; /* Route retain mode flag. */ static int retain_mode = 0; /* privileges */ -static zebra_capabilities_t _caps_p [] = -{ - ZCAP_BIND, - ZCAP_NET_RAW, - ZCAP_NET_ADMIN, +static zebra_capabilities_t _caps_p[] = { + ZCAP_BIND, ZCAP_NET_RAW, ZCAP_NET_ADMIN, }; -struct zebra_privs_t bgpd_privs = -{ +struct zebra_privs_t bgpd_privs = { #if defined(FRR_USER) && defined(FRR_GROUP) - .user = FRR_USER, - .group = FRR_GROUP, + .user = FRR_USER, + .group = FRR_GROUP, #endif #ifdef VTY_GROUP - .vty_group = VTY_GROUP, + .vty_group = VTY_GROUP, #endif - .caps_p = _caps_p, - .cap_num_p = array_size(_caps_p), - .cap_num_i = 0, + .caps_p = _caps_p, + .cap_num_p = array_size(_caps_p), + .cap_num_i = 0, }; static struct frr_daemon_info bgpd_di; /* SIGHUP handler. */ -void -sighup (void) +void sighup(void) { - zlog_info ("SIGHUP received"); + zlog_info("SIGHUP received"); - /* Terminate all thread. */ - bgp_terminate (); - bgp_reset (); - zlog_info ("bgpd restarting!"); + /* Terminate all thread. */ + bgp_terminate(); + bgp_reset(); + zlog_info("bgpd restarting!"); - /* Reload config file. */ - vty_read_config (bgpd_di.config_file, config_default); + /* Reload config file. */ + vty_read_config(bgpd_di.config_file, config_default); - /* Try to return to normal operation. */ + /* Try to return to normal operation. */ } /* SIGINT handler. */ -__attribute__((__noreturn__)) void -sigint (void) +__attribute__((__noreturn__)) void sigint(void) { - zlog_notice ("Terminating on signal"); + zlog_notice("Terminating on signal"); - if (! retain_mode) - { - bgp_terminate (); - if (bgpd_privs.user) /* NULL if skip_runas flag set */ - zprivs_terminate (&bgpd_privs); - } + if (!retain_mode) { + bgp_terminate(); + if (bgpd_privs.user) /* NULL if skip_runas flag set */ + zprivs_terminate(&bgpd_privs); + } - bgp_exit (0); + bgp_exit(0); - exit (0); + exit(0); } /* SIGUSR1 handler. */ -void -sigusr1 (void) +void sigusr1(void) { - zlog_rotate(); + zlog_rotate(); } /* @@ -175,265 +164,250 @@ sigusr1 (void) Zebra route removal and protocol teardown are not meant to be done here. For example, "retain_mode" may be set. */ -static __attribute__((__noreturn__)) void -bgp_exit (int status) +static __attribute__((__noreturn__)) void bgp_exit(int status) { - struct bgp *bgp; - struct listnode *node, *nnode; + struct bgp *bgp; + struct listnode *node, *nnode; - /* it only makes sense for this to be called on a clean exit */ - assert (status == 0); + /* it only makes sense for this to be called on a clean exit */ + assert(status == 0); - bfd_gbl_exit(); + bfd_gbl_exit(); - bgp_close(); + bgp_close(); - if (retain_mode) - if_add_hook (IF_DELETE_HOOK, NULL); + if (retain_mode) + if_add_hook(IF_DELETE_HOOK, NULL); - /* reverse bgp_master_init */ - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - bgp_delete (bgp); + /* reverse bgp_master_init */ + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) + bgp_delete(bgp); - /* reverse bgp_dump_init */ - bgp_dump_finish (); + /* reverse bgp_dump_init */ + bgp_dump_finish(); - /* reverse bgp_route_init */ - bgp_route_finish (); + /* reverse bgp_route_init */ + bgp_route_finish(); - /* cleanup route maps */ - bgp_route_map_terminate(); + /* cleanup route maps */ + bgp_route_map_terminate(); - /* reverse bgp_attr_init */ - bgp_attr_finish (); + /* reverse bgp_attr_init */ + bgp_attr_finish(); - /* reverse access_list_init */ - access_list_add_hook (NULL); - access_list_delete_hook (NULL); - access_list_reset (); + /* reverse access_list_init */ + access_list_add_hook(NULL); + access_list_delete_hook(NULL); + access_list_reset(); - /* reverse bgp_filter_init */ - as_list_add_hook (NULL); - as_list_delete_hook (NULL); - bgp_filter_reset (); + /* reverse bgp_filter_init */ + as_list_add_hook(NULL); + as_list_delete_hook(NULL); + bgp_filter_reset(); - /* reverse prefix_list_init */ - prefix_list_add_hook (NULL); - prefix_list_delete_hook (NULL); - prefix_list_reset (); + /* reverse prefix_list_init */ + prefix_list_add_hook(NULL); + prefix_list_delete_hook(NULL); + prefix_list_reset(); - /* reverse community_list_init */ - community_list_terminate (bgp_clist); + /* reverse community_list_init */ + community_list_terminate(bgp_clist); - bgp_vrf_terminate (); - cmd_terminate (); - vty_terminate (); + bgp_vrf_terminate(); + cmd_terminate(); + vty_terminate(); #if ENABLE_BGP_VNC - vnc_zebra_destroy(); + vnc_zebra_destroy(); #endif - bgp_zebra_destroy(); + bgp_zebra_destroy(); - /* reverse bgp_master_init */ - if (bm->master) - thread_master_free (bm->master); + /* reverse bgp_master_init */ + if (bm->master) + thread_master_free(bm->master); - closezlog (); + closezlog(); - list_delete (bm->bgp); - memset (bm, 0, sizeof (*bm)); + list_delete(bm->bgp); + memset(bm, 0, sizeof(*bm)); - if (bgp_debug_count()) - log_memstats_stderr ("bgpd"); - exit (status); + if (bgp_debug_count()) + log_memstats_stderr("bgpd"); + exit(status); } -static int -bgp_vrf_new (struct vrf *vrf) +static int bgp_vrf_new(struct vrf *vrf) { - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug ("VRF Created: %s(%d)", vrf->name, vrf->vrf_id); + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("VRF Created: %s(%d)", vrf->name, vrf->vrf_id); - return 0; + return 0; } -static int -bgp_vrf_delete (struct vrf *vrf) +static int bgp_vrf_delete(struct vrf *vrf) { - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug ("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id); + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id); - return 0; + return 0; } -static int -bgp_vrf_enable (struct vrf *vrf) +static int bgp_vrf_enable(struct vrf *vrf) { - struct bgp *bgp; - vrf_id_t old_vrf_id; - - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("VRF enable add %s id %d", vrf->name, vrf->vrf_id); - - bgp = bgp_lookup_by_name (vrf->name); - if (bgp) - { - old_vrf_id = bgp->vrf_id; - /* We have instance configured, link to VRF and make it "up". */ - bgp_vrf_link (bgp, vrf); - - /* Update any redistribute vrf bitmaps if the vrf_id changed */ - if (old_vrf_id != bgp->vrf_id) - bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id); - bgp_instance_up (bgp); - } - - return 0; + struct bgp *bgp; + vrf_id_t old_vrf_id; + + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("VRF enable add %s id %d", vrf->name, vrf->vrf_id); + + bgp = bgp_lookup_by_name(vrf->name); + if (bgp) { + old_vrf_id = bgp->vrf_id; + /* We have instance configured, link to VRF and make it "up". */ + bgp_vrf_link(bgp, vrf); + + /* Update any redistribute vrf bitmaps if the vrf_id changed */ + if (old_vrf_id != bgp->vrf_id) + bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id); + bgp_instance_up(bgp); + } + + return 0; } -static int -bgp_vrf_disable (struct vrf *vrf) +static int bgp_vrf_disable(struct vrf *vrf) { - struct bgp *bgp; - vrf_id_t old_vrf_id; - - if (vrf->vrf_id == VRF_DEFAULT) - return 0; - - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("VRF disable %s id %d", vrf->name, vrf->vrf_id); - - bgp = bgp_lookup_by_name (vrf->name); - if (bgp) - { - old_vrf_id = bgp->vrf_id; - /* We have instance configured, unlink from VRF and make it "down". */ - bgp_vrf_unlink (bgp, vrf); - /* Update any redistribute vrf bitmaps if the vrf_id changed */ - if (old_vrf_id != bgp->vrf_id) - bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id); - bgp_instance_down (bgp); - } - - /* Note: This is a callback, the VRF will be deleted by the caller. */ - return 0; + struct bgp *bgp; + vrf_id_t old_vrf_id; + + if (vrf->vrf_id == VRF_DEFAULT) + return 0; + + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("VRF disable %s id %d", vrf->name, vrf->vrf_id); + + bgp = bgp_lookup_by_name(vrf->name); + if (bgp) { + old_vrf_id = bgp->vrf_id; + /* We have instance configured, unlink from VRF and make it + * "down". */ + bgp_vrf_unlink(bgp, vrf); + /* Update any redistribute vrf bitmaps if the vrf_id changed */ + if (old_vrf_id != bgp->vrf_id) + bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id); + bgp_instance_down(bgp); + } + + /* Note: This is a callback, the VRF will be deleted by the caller. */ + return 0; } -static void -bgp_vrf_init (void) +static void bgp_vrf_init(void) { - vrf_init (bgp_vrf_new, - bgp_vrf_enable, - bgp_vrf_disable, - bgp_vrf_delete); + vrf_init(bgp_vrf_new, bgp_vrf_enable, bgp_vrf_disable, bgp_vrf_delete); } -static void -bgp_vrf_terminate (void) +static void bgp_vrf_terminate(void) { - vrf_terminate (); + vrf_terminate(); } -FRR_DAEMON_INFO(bgpd, BGP, - .vty_port = BGP_VTY_PORT, +FRR_DAEMON_INFO(bgpd, BGP, .vty_port = BGP_VTY_PORT, - .proghelp = "Implementation of the BGP routing protocol.", + .proghelp = "Implementation of the BGP routing protocol.", - .signals = bgp_signals, - .n_signals = array_size(bgp_signals), + .signals = bgp_signals, .n_signals = array_size(bgp_signals), - .privs = &bgpd_privs, -) + .privs = &bgpd_privs, ) /* Main routine of bgpd. Treatment of argument and start bgp finite state machine is handled at here. */ -int -main (int argc, char **argv) +int main(int argc, char **argv) { - int opt; - int tmp_port; - - int bgp_port = BGP_PORT_DEFAULT; - char *bgp_address = NULL; - int no_fib_flag = 0; - int skip_runas = 0; - - frr_preinit(&bgpd_di, argc, argv); - frr_opt_add("p:l:rne:", longopts, - " -p, --bgp_port Set bgp protocol's port number\n" - " -l, --listenon Listen on specified address (implies -n)\n" - " -r, --retain When program terminates, retain added route by bgpd.\n" - " -n, --no_kernel Do not install route to kernel.\n" - " -S, --skip_runas Skip capabilities checks, and changing user and group IDs.\n" - " -e, --ecmp Specify ECMP to use.\n"); - - /* Command line argument treatment. */ - while (1) - { - opt = frr_getopt (argc, argv, 0); - - if (opt == EOF) - break; - - switch (opt) - { - case 0: - break; - case 'p': - tmp_port = atoi (optarg); - if (tmp_port <= 0 || tmp_port > 0xffff) - bgp_port = BGP_PORT_DEFAULT; - else - bgp_port = tmp_port; - break; - case 'e': - multipath_num = atoi (optarg); - if (multipath_num > MULTIPATH_NUM || multipath_num <= 0) - { - zlog_err ("Multipath Number specified must be less than %d and greater than 0", MULTIPATH_NUM); - return 1; - } - break; - case 'r': - retain_mode = 1; - break; - case 'l': - bgp_address = optarg; - /* listenon implies -n */ - /* fallthru */ - case 'n': - no_fib_flag = 1; - break; - case 'S': - skip_runas = 1; - break; - default: - frr_help_exit (1); - break; + int opt; + int tmp_port; + + int bgp_port = BGP_PORT_DEFAULT; + char *bgp_address = NULL; + int no_fib_flag = 0; + int skip_runas = 0; + + frr_preinit(&bgpd_di, argc, argv); + frr_opt_add( + "p:l:rne:", longopts, + " -p, --bgp_port Set bgp protocol's port number\n" + " -l, --listenon Listen on specified address (implies -n)\n" + " -r, --retain When program terminates, retain added route by bgpd.\n" + " -n, --no_kernel Do not install route to kernel.\n" + " -S, --skip_runas Skip capabilities checks, and changing user and group IDs.\n" + " -e, --ecmp Specify ECMP to use.\n"); + + /* Command line argument treatment. */ + while (1) { + opt = frr_getopt(argc, argv, 0); + + if (opt == EOF) + break; + + switch (opt) { + case 0: + break; + case 'p': + tmp_port = atoi(optarg); + if (tmp_port <= 0 || tmp_port > 0xffff) + bgp_port = BGP_PORT_DEFAULT; + else + bgp_port = tmp_port; + break; + case 'e': + multipath_num = atoi(optarg); + if (multipath_num > MULTIPATH_NUM + || multipath_num <= 0) { + zlog_err( + "Multipath Number specified must be less than %d and greater than 0", + MULTIPATH_NUM); + return 1; + } + break; + case 'r': + retain_mode = 1; + break; + case 'l': + bgp_address = optarg; + /* listenon implies -n */ + /* fallthru */ + case 'n': + no_fib_flag = 1; + break; + case 'S': + skip_runas = 1; + break; + default: + frr_help_exit(1); + break; + } } - } - if (skip_runas) - memset (&bgpd_privs, 0, sizeof (bgpd_privs)); + if (skip_runas) + memset(&bgpd_privs, 0, sizeof(bgpd_privs)); - /* BGP master init. */ - bgp_master_init (frr_init ()); - bm->port = bgp_port; - bm->address = bgp_address; - if (no_fib_flag) - bgp_option_set (BGP_OPT_NO_FIB); + /* BGP master init. */ + bgp_master_init(frr_init()); + bm->port = bgp_port; + bm->address = bgp_address; + if (no_fib_flag) + bgp_option_set(BGP_OPT_NO_FIB); - /* Initializations. */ - bgp_vrf_init (); + /* Initializations. */ + bgp_vrf_init(); - /* BGP related initialization. */ - bgp_init (); + /* BGP related initialization. */ + bgp_init(); - snprintf (bgpd_di.startinfo, sizeof (bgpd_di.startinfo), ", bgp@%s:%d", - (bm->address ? bm->address : ""), - bm->port); + snprintf(bgpd_di.startinfo, sizeof(bgpd_di.startinfo), ", bgp@%s:%d", + (bm->address ? bm->address : ""), bm->port); - frr_config_fork (); - frr_run (bm->master); + frr_config_fork(); + frr_run(bm->master); - /* Not reached. */ - return (0); + /* Not reached. */ + return (0); } diff --git a/bgpd/bgp_memory.c b/bgpd/bgp_memory.c index 6da9ff868..3df40fa87 100644 --- a/bgpd/bgp_memory.c +++ b/bgpd/bgp_memory.c @@ -29,91 +29,91 @@ * files they're used in */ DEFINE_MGROUP(BGPD, "bgpd") -DEFINE_MTYPE(BGPD, BGP, "BGP instance") -DEFINE_MTYPE(BGPD, BGP_LISTENER, "BGP listen socket details") -DEFINE_MTYPE(BGPD, BGP_PEER, "BGP peer") -DEFINE_MTYPE(BGPD, BGP_PEER_HOST, "BGP peer hostname") -DEFINE_MTYPE(BGPD, BGP_PEER_IFNAME, "BGP peer ifname") -DEFINE_MTYPE(BGPD, PEER_GROUP, "Peer group") -DEFINE_MTYPE(BGPD, PEER_GROUP_HOST, "BGP Peer group hostname") -DEFINE_MTYPE(BGPD, PEER_DESC, "Peer description") -DEFINE_MTYPE(BGPD, PEER_PASSWORD, "Peer password string") -DEFINE_MTYPE(BGPD, BGP_PEER_AF, "BGP peer af") -DEFINE_MTYPE(BGPD, BGP_UPDGRP, "BGP update group") -DEFINE_MTYPE(BGPD, BGP_UPD_SUBGRP, "BGP update subgroup") -DEFINE_MTYPE(BGPD, BGP_PACKET, "BGP packet") -DEFINE_MTYPE(BGPD, ATTR, "BGP attribute") -DEFINE_MTYPE(BGPD, AS_PATH, "BGP aspath") -DEFINE_MTYPE(BGPD, AS_SEG, "BGP aspath seg") -DEFINE_MTYPE(BGPD, AS_SEG_DATA, "BGP aspath segment data") -DEFINE_MTYPE(BGPD, AS_STR, "BGP aspath str") - -DEFINE_MTYPE(BGPD, BGP_TABLE, "BGP table") -DEFINE_MTYPE(BGPD, BGP_NODE, "BGP node") -DEFINE_MTYPE(BGPD, BGP_ROUTE, "BGP route") -DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA, "BGP ancillary route info") -DEFINE_MTYPE(BGPD, BGP_CONN, "BGP connected") -DEFINE_MTYPE(BGPD, BGP_STATIC, "BGP static") -DEFINE_MTYPE(BGPD, BGP_ADVERTISE_ATTR, "BGP adv attr") -DEFINE_MTYPE(BGPD, BGP_ADVERTISE, "BGP adv") -DEFINE_MTYPE(BGPD, BGP_SYNCHRONISE, "BGP synchronise") -DEFINE_MTYPE(BGPD, BGP_ADJ_IN, "BGP adj in") -DEFINE_MTYPE(BGPD, BGP_ADJ_OUT, "BGP adj out") -DEFINE_MTYPE(BGPD, BGP_MPATH_INFO, "BGP multipath info") - -DEFINE_MTYPE(BGPD, AS_LIST, "BGP AS list") -DEFINE_MTYPE(BGPD, AS_FILTER, "BGP AS filter") -DEFINE_MTYPE(BGPD, AS_FILTER_STR, "BGP AS filter str") - -DEFINE_MTYPE(BGPD, COMMUNITY, "community") -DEFINE_MTYPE(BGPD, COMMUNITY_VAL, "community val") -DEFINE_MTYPE(BGPD, COMMUNITY_STR, "community str") - -DEFINE_MTYPE(BGPD, ECOMMUNITY, "extcommunity") -DEFINE_MTYPE(BGPD, ECOMMUNITY_VAL, "extcommunity val") -DEFINE_MTYPE(BGPD, ECOMMUNITY_STR, "extcommunity str") - -DEFINE_MTYPE(BGPD, COMMUNITY_LIST, "community-list") -DEFINE_MTYPE(BGPD, COMMUNITY_LIST_NAME, "community-list name") -DEFINE_MTYPE(BGPD, COMMUNITY_LIST_ENTRY, "community-list entry") -DEFINE_MTYPE(BGPD, COMMUNITY_LIST_CONFIG, "community-list config") -DEFINE_MTYPE(BGPD, COMMUNITY_LIST_HANDLER, "community-list handler") - -DEFINE_MTYPE(BGPD, CLUSTER, "Cluster list") -DEFINE_MTYPE(BGPD, CLUSTER_VAL, "Cluster list val") - -DEFINE_MTYPE(BGPD, BGP_PROCESS_QUEUE, "BGP Process queue") -DEFINE_MTYPE(BGPD, BGP_CLEAR_NODE_QUEUE, "BGP node clear queue") - -DEFINE_MTYPE(BGPD, TRANSIT, "BGP transit attr") -DEFINE_MTYPE(BGPD, TRANSIT_VAL, "BGP transit val") - -DEFINE_MTYPE(BGPD, BGP_DEBUG_FILTER, "BGP debug filter") -DEFINE_MTYPE(BGPD, BGP_DEBUG_STR, "BGP debug filter string") - -DEFINE_MTYPE(BGPD, BGP_DISTANCE, "BGP distance") -DEFINE_MTYPE(BGPD, BGP_NEXTHOP_CACHE, "BGP nexthop") -DEFINE_MTYPE(BGPD, BGP_CONFED_LIST, "BGP confed list") -DEFINE_MTYPE(BGPD, PEER_UPDATE_SOURCE, "BGP peer update interface") -DEFINE_MTYPE(BGPD, PEER_CONF_IF, "BGP peer config interface") -DEFINE_MTYPE(BGPD, BGP_DAMP_INFO, "Dampening info") -DEFINE_MTYPE(BGPD, BGP_DAMP_ARRAY, "BGP Dampening array") -DEFINE_MTYPE(BGPD, BGP_REGEXP, "BGP regexp") -DEFINE_MTYPE(BGPD, BGP_AGGREGATE, "BGP aggregate") -DEFINE_MTYPE(BGPD, BGP_ADDR, "BGP own address") - -DEFINE_MTYPE(BGPD, BGP_REDIST, "BGP redistribution") -DEFINE_MTYPE(BGPD, BGP_FILTER_NAME, "BGP Filter Information") -DEFINE_MTYPE(BGPD, BGP_DUMP_STR, "BGP Dump String Information") -DEFINE_MTYPE(BGPD, ENCAP_TLV, "ENCAP TLV") - -DEFINE_MTYPE(BGPD, BGP_TEA_OPTIONS, "BGP TEA Options") +DEFINE_MTYPE(BGPD, BGP, "BGP instance") +DEFINE_MTYPE(BGPD, BGP_LISTENER, "BGP listen socket details") +DEFINE_MTYPE(BGPD, BGP_PEER, "BGP peer") +DEFINE_MTYPE(BGPD, BGP_PEER_HOST, "BGP peer hostname") +DEFINE_MTYPE(BGPD, BGP_PEER_IFNAME, "BGP peer ifname") +DEFINE_MTYPE(BGPD, PEER_GROUP, "Peer group") +DEFINE_MTYPE(BGPD, PEER_GROUP_HOST, "BGP Peer group hostname") +DEFINE_MTYPE(BGPD, PEER_DESC, "Peer description") +DEFINE_MTYPE(BGPD, PEER_PASSWORD, "Peer password string") +DEFINE_MTYPE(BGPD, BGP_PEER_AF, "BGP peer af") +DEFINE_MTYPE(BGPD, BGP_UPDGRP, "BGP update group") +DEFINE_MTYPE(BGPD, BGP_UPD_SUBGRP, "BGP update subgroup") +DEFINE_MTYPE(BGPD, BGP_PACKET, "BGP packet") +DEFINE_MTYPE(BGPD, ATTR, "BGP attribute") +DEFINE_MTYPE(BGPD, AS_PATH, "BGP aspath") +DEFINE_MTYPE(BGPD, AS_SEG, "BGP aspath seg") +DEFINE_MTYPE(BGPD, AS_SEG_DATA, "BGP aspath segment data") +DEFINE_MTYPE(BGPD, AS_STR, "BGP aspath str") + +DEFINE_MTYPE(BGPD, BGP_TABLE, "BGP table") +DEFINE_MTYPE(BGPD, BGP_NODE, "BGP node") +DEFINE_MTYPE(BGPD, BGP_ROUTE, "BGP route") +DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA, "BGP ancillary route info") +DEFINE_MTYPE(BGPD, BGP_CONN, "BGP connected") +DEFINE_MTYPE(BGPD, BGP_STATIC, "BGP static") +DEFINE_MTYPE(BGPD, BGP_ADVERTISE_ATTR, "BGP adv attr") +DEFINE_MTYPE(BGPD, BGP_ADVERTISE, "BGP adv") +DEFINE_MTYPE(BGPD, BGP_SYNCHRONISE, "BGP synchronise") +DEFINE_MTYPE(BGPD, BGP_ADJ_IN, "BGP adj in") +DEFINE_MTYPE(BGPD, BGP_ADJ_OUT, "BGP adj out") +DEFINE_MTYPE(BGPD, BGP_MPATH_INFO, "BGP multipath info") + +DEFINE_MTYPE(BGPD, AS_LIST, "BGP AS list") +DEFINE_MTYPE(BGPD, AS_FILTER, "BGP AS filter") +DEFINE_MTYPE(BGPD, AS_FILTER_STR, "BGP AS filter str") + +DEFINE_MTYPE(BGPD, COMMUNITY, "community") +DEFINE_MTYPE(BGPD, COMMUNITY_VAL, "community val") +DEFINE_MTYPE(BGPD, COMMUNITY_STR, "community str") + +DEFINE_MTYPE(BGPD, ECOMMUNITY, "extcommunity") +DEFINE_MTYPE(BGPD, ECOMMUNITY_VAL, "extcommunity val") +DEFINE_MTYPE(BGPD, ECOMMUNITY_STR, "extcommunity str") + +DEFINE_MTYPE(BGPD, COMMUNITY_LIST, "community-list") +DEFINE_MTYPE(BGPD, COMMUNITY_LIST_NAME, "community-list name") +DEFINE_MTYPE(BGPD, COMMUNITY_LIST_ENTRY, "community-list entry") +DEFINE_MTYPE(BGPD, COMMUNITY_LIST_CONFIG, "community-list config") +DEFINE_MTYPE(BGPD, COMMUNITY_LIST_HANDLER, "community-list handler") + +DEFINE_MTYPE(BGPD, CLUSTER, "Cluster list") +DEFINE_MTYPE(BGPD, CLUSTER_VAL, "Cluster list val") + +DEFINE_MTYPE(BGPD, BGP_PROCESS_QUEUE, "BGP Process queue") +DEFINE_MTYPE(BGPD, BGP_CLEAR_NODE_QUEUE, "BGP node clear queue") + +DEFINE_MTYPE(BGPD, TRANSIT, "BGP transit attr") +DEFINE_MTYPE(BGPD, TRANSIT_VAL, "BGP transit val") + +DEFINE_MTYPE(BGPD, BGP_DEBUG_FILTER, "BGP debug filter") +DEFINE_MTYPE(BGPD, BGP_DEBUG_STR, "BGP debug filter string") + +DEFINE_MTYPE(BGPD, BGP_DISTANCE, "BGP distance") +DEFINE_MTYPE(BGPD, BGP_NEXTHOP_CACHE, "BGP nexthop") +DEFINE_MTYPE(BGPD, BGP_CONFED_LIST, "BGP confed list") +DEFINE_MTYPE(BGPD, PEER_UPDATE_SOURCE, "BGP peer update interface") +DEFINE_MTYPE(BGPD, PEER_CONF_IF, "BGP peer config interface") +DEFINE_MTYPE(BGPD, BGP_DAMP_INFO, "Dampening info") +DEFINE_MTYPE(BGPD, BGP_DAMP_ARRAY, "BGP Dampening array") +DEFINE_MTYPE(BGPD, BGP_REGEXP, "BGP regexp") +DEFINE_MTYPE(BGPD, BGP_AGGREGATE, "BGP aggregate") +DEFINE_MTYPE(BGPD, BGP_ADDR, "BGP own address") + +DEFINE_MTYPE(BGPD, BGP_REDIST, "BGP redistribution") +DEFINE_MTYPE(BGPD, BGP_FILTER_NAME, "BGP Filter Information") +DEFINE_MTYPE(BGPD, BGP_DUMP_STR, "BGP Dump String Information") +DEFINE_MTYPE(BGPD, ENCAP_TLV, "ENCAP TLV") + +DEFINE_MTYPE(BGPD, BGP_TEA_OPTIONS, "BGP TEA Options") DEFINE_MTYPE(BGPD, BGP_TEA_OPTIONS_VALUE, "BGP TEA Options Value") DEFINE_MTYPE(BGPD, LCOMMUNITY, "Large Community") DEFINE_MTYPE(BGPD, LCOMMUNITY_STR, "Large Community display string") DEFINE_MTYPE(BGPD, LCOMMUNITY_VAL, "Large Community value") -DEFINE_MTYPE(BGPD, BGP_EVPN, "BGP EVPN Information") -DEFINE_MTYPE(BGPD, BGP_EVPN_IMPORT_RT, "BGP EVPN Import RT") -DEFINE_MTYPE(BGPD, BGP_EVPN_MACIP, "BGP EVPN MAC IP") +DEFINE_MTYPE(BGPD, BGP_EVPN, "BGP EVPN Information") +DEFINE_MTYPE(BGPD, BGP_EVPN_IMPORT_RT, "BGP EVPN Import RT") +DEFINE_MTYPE(BGPD, BGP_EVPN_MACIP, "BGP EVPN MAC IP") diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c index 7ea5c9e77..6dc6dc676 100644 --- a/bgpd/bgp_mpath.c +++ b/bgpd/bgp_mpath.c @@ -45,27 +45,25 @@ * * Record maximum-paths configuration for BGP instance */ -int -bgp_maximum_paths_set (struct bgp *bgp, afi_t afi, safi_t safi, - int peertype, u_int16_t maxpaths, u_int16_t options) +int bgp_maximum_paths_set(struct bgp *bgp, afi_t afi, safi_t safi, int peertype, + u_int16_t maxpaths, u_int16_t options) { - if (!bgp || (afi >= AFI_MAX) || (safi >= SAFI_MAX)) - return -1; - - switch (peertype) - { - case BGP_PEER_IBGP: - bgp->maxpaths[afi][safi].maxpaths_ibgp = maxpaths; - bgp->maxpaths[afi][safi].ibgp_flags |= options; - break; - case BGP_PEER_EBGP: - bgp->maxpaths[afi][safi].maxpaths_ebgp = maxpaths; - break; - default: - return -1; - } - - return 0; + if (!bgp || (afi >= AFI_MAX) || (safi >= SAFI_MAX)) + return -1; + + switch (peertype) { + case BGP_PEER_IBGP: + bgp->maxpaths[afi][safi].maxpaths_ibgp = maxpaths; + bgp->maxpaths[afi][safi].ibgp_flags |= options; + break; + case BGP_PEER_EBGP: + bgp->maxpaths[afi][safi].maxpaths_ebgp = maxpaths; + break; + default: + return -1; + } + + return 0; } /* @@ -73,27 +71,25 @@ bgp_maximum_paths_set (struct bgp *bgp, afi_t afi, safi_t safi, * * Remove maximum-paths configuration from BGP instance */ -int -bgp_maximum_paths_unset (struct bgp *bgp, afi_t afi, safi_t safi, - int peertype) +int bgp_maximum_paths_unset(struct bgp *bgp, afi_t afi, safi_t safi, + int peertype) { - if (!bgp || (afi >= AFI_MAX) || (safi >= SAFI_MAX)) - return -1; - - switch (peertype) - { - case BGP_PEER_IBGP: - bgp->maxpaths[afi][safi].maxpaths_ibgp = multipath_num; - bgp->maxpaths[afi][safi].ibgp_flags = 0; - break; - case BGP_PEER_EBGP: - bgp->maxpaths[afi][safi].maxpaths_ebgp = multipath_num; - break; - default: - return -1; - } - - return 0; + if (!bgp || (afi >= AFI_MAX) || (safi >= SAFI_MAX)) + return -1; + + switch (peertype) { + case BGP_PEER_IBGP: + bgp->maxpaths[afi][safi].maxpaths_ibgp = multipath_num; + bgp->maxpaths[afi][safi].ibgp_flags = 0; + break; + case BGP_PEER_EBGP: + bgp->maxpaths[afi][safi].maxpaths_ebgp = multipath_num; + break; + default: + return -1; + } + + return 0; } /* @@ -103,57 +99,58 @@ bgp_maximum_paths_unset (struct bgp *bgp, afi_t afi, safi_t safi, * or greater than zero if bi1 is respectively less than, equal to, * or greater than bi2. */ -int -bgp_info_nexthop_cmp (struct bgp_info *bi1, struct bgp_info *bi2) +int bgp_info_nexthop_cmp(struct bgp_info *bi1, struct bgp_info *bi2) { - int compare; - - compare = IPV4_ADDR_CMP (&bi1->attr->nexthop, &bi2->attr->nexthop); - if (!compare) - { - if (bi1->attr->mp_nexthop_len == bi2->attr->mp_nexthop_len) - { - switch (bi1->attr->mp_nexthop_len) - { - case BGP_ATTR_NHLEN_IPV4: - case BGP_ATTR_NHLEN_VPNV4: - compare = IPV4_ADDR_CMP (&bi1->attr->mp_nexthop_global_in, - &bi2->attr->mp_nexthop_global_in); - break; - case BGP_ATTR_NHLEN_IPV6_GLOBAL: - case BGP_ATTR_NHLEN_VPNV6_GLOBAL: - compare = IPV6_ADDR_CMP (&bi1->attr->mp_nexthop_global, - &bi2->attr->mp_nexthop_global); - break; - case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL: - compare = IPV6_ADDR_CMP (&bi1->attr->mp_nexthop_global, - &bi2->attr->mp_nexthop_global); - if (!compare) - compare = IPV6_ADDR_CMP (&bi1->attr->mp_nexthop_local, - &bi2->attr->mp_nexthop_local); - break; - } - } - - /* This can happen if one IPv6 peer sends you global and link-local - * nexthops but another IPv6 peer only sends you global - */ - else if (bi1->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL || - bi1->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) - { - compare = IPV6_ADDR_CMP (&bi1->attr->mp_nexthop_global, - &bi2->attr->mp_nexthop_global); - if (!compare) - { - if (bi1->attr->mp_nexthop_len < bi2->attr->mp_nexthop_len) - compare = -1; - else - compare = 1; - } - } - } - - return compare; + int compare; + + compare = IPV4_ADDR_CMP(&bi1->attr->nexthop, &bi2->attr->nexthop); + if (!compare) { + if (bi1->attr->mp_nexthop_len == bi2->attr->mp_nexthop_len) { + switch (bi1->attr->mp_nexthop_len) { + case BGP_ATTR_NHLEN_IPV4: + case BGP_ATTR_NHLEN_VPNV4: + compare = IPV4_ADDR_CMP( + &bi1->attr->mp_nexthop_global_in, + &bi2->attr->mp_nexthop_global_in); + break; + case BGP_ATTR_NHLEN_IPV6_GLOBAL: + case BGP_ATTR_NHLEN_VPNV6_GLOBAL: + compare = IPV6_ADDR_CMP( + &bi1->attr->mp_nexthop_global, + &bi2->attr->mp_nexthop_global); + break; + case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL: + compare = IPV6_ADDR_CMP( + &bi1->attr->mp_nexthop_global, + &bi2->attr->mp_nexthop_global); + if (!compare) + compare = IPV6_ADDR_CMP( + &bi1->attr->mp_nexthop_local, + &bi2->attr->mp_nexthop_local); + break; + } + } + + /* This can happen if one IPv6 peer sends you global and + * link-local + * nexthops but another IPv6 peer only sends you global + */ + else if (bi1->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL + || bi1->attr->mp_nexthop_len + == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) { + compare = IPV6_ADDR_CMP(&bi1->attr->mp_nexthop_global, + &bi2->attr->mp_nexthop_global); + if (!compare) { + if (bi1->attr->mp_nexthop_len + < bi2->attr->mp_nexthop_len) + compare = -1; + else + compare = 1; + } + } + } + + return compare; } /* @@ -168,30 +165,29 @@ bgp_info_nexthop_cmp (struct bgp_info *bi1, struct bgp_info *bi2) * The order of paths is determined first by received nexthop, and then * by peer address if the nexthops are the same. */ -static int -bgp_info_mpath_cmp (void *val1, void *val2) +static int bgp_info_mpath_cmp(void *val1, void *val2) { - struct bgp_info *bi1, *bi2; - int compare; - - bi1 = val1; - bi2 = val2; - - compare = bgp_info_nexthop_cmp (bi1, bi2); - - if (!compare) - { - if (!bi1->peer->su_remote && !bi2->peer->su_remote) - compare = 0; - else if (!bi1->peer->su_remote) - compare = 1; - else if (!bi2->peer->su_remote) - compare = -1; - else - compare = sockunion_cmp (bi1->peer->su_remote, bi2->peer->su_remote); - } - - return compare; + struct bgp_info *bi1, *bi2; + int compare; + + bi1 = val1; + bi2 = val2; + + compare = bgp_info_nexthop_cmp(bi1, bi2); + + if (!compare) { + if (!bi1->peer->su_remote && !bi2->peer->su_remote) + compare = 0; + else if (!bi1->peer->su_remote) + compare = 1; + else if (!bi2->peer->su_remote) + compare = -1; + else + compare = sockunion_cmp(bi1->peer->su_remote, + bi2->peer->su_remote); + } + + return compare; } /* @@ -200,12 +196,11 @@ bgp_info_mpath_cmp (void *val1, void *val2) * Initialize the mp_list, which holds the list of multipaths * selected by bgp_best_selection */ -void -bgp_mp_list_init (struct list *mp_list) +void bgp_mp_list_init(struct list *mp_list) { - assert (mp_list); - memset (mp_list, 0, sizeof (struct list)); - mp_list->cmp = bgp_info_mpath_cmp; + assert(mp_list); + memset(mp_list, 0, sizeof(struct list)); + mp_list->cmp = bgp_info_mpath_cmp; } /* @@ -213,11 +208,10 @@ bgp_mp_list_init (struct list *mp_list) * * Clears all entries out of the mp_list */ -void -bgp_mp_list_clear (struct list *mp_list) +void bgp_mp_list_clear(struct list *mp_list) { - assert (mp_list); - list_delete_all_node (mp_list); + assert(mp_list); + list_delete_all_node(mp_list); } /* @@ -225,11 +219,10 @@ bgp_mp_list_clear (struct list *mp_list) * * Adds a multipath entry to the mp_list */ -void -bgp_mp_list_add (struct list *mp_list, struct bgp_info *mpinfo) +void bgp_mp_list_add(struct list *mp_list, struct bgp_info *mpinfo) { - assert (mp_list && mpinfo); - listnode_add_sort (mp_list, mpinfo); + assert(mp_list && mpinfo); + listnode_add_sort(mp_list, mpinfo); } /* @@ -237,12 +230,12 @@ bgp_mp_list_add (struct list *mp_list, struct bgp_info *mpinfo) * * Allocate and zero memory for a new bgp_info_mpath element */ -static struct bgp_info_mpath * -bgp_info_mpath_new (void) +static struct bgp_info_mpath *bgp_info_mpath_new(void) { - struct bgp_info_mpath *new_mpath; - new_mpath = XCALLOC (MTYPE_BGP_MPATH_INFO, sizeof (struct bgp_info_mpath)); - return new_mpath; + struct bgp_info_mpath *new_mpath; + new_mpath = + XCALLOC(MTYPE_BGP_MPATH_INFO, sizeof(struct bgp_info_mpath)); + return new_mpath; } /* @@ -250,16 +243,14 @@ bgp_info_mpath_new (void) * * Release resources for a bgp_info_mpath element and zero out pointer */ -void -bgp_info_mpath_free (struct bgp_info_mpath **mpath) +void bgp_info_mpath_free(struct bgp_info_mpath **mpath) { - if (mpath && *mpath) - { - if ((*mpath)->mp_attr) - bgp_attr_unintern (&(*mpath)->mp_attr); - XFREE (MTYPE_BGP_MPATH_INFO, *mpath); - *mpath = NULL; - } + if (mpath && *mpath) { + if ((*mpath)->mp_attr) + bgp_attr_unintern(&(*mpath)->mp_attr); + XFREE(MTYPE_BGP_MPATH_INFO, *mpath); + *mpath = NULL; + } } /* @@ -268,19 +259,17 @@ bgp_info_mpath_free (struct bgp_info_mpath **mpath) * Fetch the mpath element for the given bgp_info. Used for * doing lazy allocation. */ -static struct bgp_info_mpath * -bgp_info_mpath_get (struct bgp_info *binfo) +static struct bgp_info_mpath *bgp_info_mpath_get(struct bgp_info *binfo) { - struct bgp_info_mpath *mpath; - if (!binfo->mpath) - { - mpath = bgp_info_mpath_new(); - if (!mpath) - return NULL; - binfo->mpath = mpath; - mpath->mp_info = binfo; - } - return binfo->mpath; + struct bgp_info_mpath *mpath; + if (!binfo->mpath) { + mpath = bgp_info_mpath_new(); + if (!mpath) + return NULL; + binfo->mpath = mpath; + mpath->mp_info = binfo; + } + return binfo->mpath; } /* @@ -289,23 +278,23 @@ bgp_info_mpath_get (struct bgp_info *binfo) * Enqueue a path onto the multipath list given the previous multipath * list entry */ -static void -bgp_info_mpath_enqueue (struct bgp_info *prev_info, struct bgp_info *binfo) +static void bgp_info_mpath_enqueue(struct bgp_info *prev_info, + struct bgp_info *binfo) { - struct bgp_info_mpath *prev, *mpath; + struct bgp_info_mpath *prev, *mpath; - prev = bgp_info_mpath_get (prev_info); - mpath = bgp_info_mpath_get (binfo); - if (!prev || !mpath) - return; + prev = bgp_info_mpath_get(prev_info); + mpath = bgp_info_mpath_get(binfo); + if (!prev || !mpath) + return; - mpath->mp_next = prev->mp_next; - mpath->mp_prev = prev; - if (prev->mp_next) - prev->mp_next->mp_prev = mpath; - prev->mp_next = mpath; + mpath->mp_next = prev->mp_next; + mpath->mp_prev = prev; + if (prev->mp_next) + prev->mp_next->mp_prev = mpath; + prev->mp_next = mpath; - SET_FLAG (binfo->flags, BGP_INFO_MULTIPATH); + SET_FLAG(binfo->flags, BGP_INFO_MULTIPATH); } /* @@ -313,18 +302,17 @@ bgp_info_mpath_enqueue (struct bgp_info *prev_info, struct bgp_info *binfo) * * Remove a path from the multipath list */ -void -bgp_info_mpath_dequeue (struct bgp_info *binfo) +void bgp_info_mpath_dequeue(struct bgp_info *binfo) { - struct bgp_info_mpath *mpath = binfo->mpath; - if (!mpath) - return; - if (mpath->mp_prev) - mpath->mp_prev->mp_next = mpath->mp_next; - if (mpath->mp_next) - mpath->mp_next->mp_prev = mpath->mp_prev; - mpath->mp_next = mpath->mp_prev = NULL; - UNSET_FLAG (binfo->flags, BGP_INFO_MULTIPATH); + struct bgp_info_mpath *mpath = binfo->mpath; + if (!mpath) + return; + if (mpath->mp_prev) + mpath->mp_prev->mp_next = mpath->mp_next; + if (mpath->mp_next) + mpath->mp_next->mp_prev = mpath->mp_prev; + mpath->mp_next = mpath->mp_prev = NULL; + UNSET_FLAG(binfo->flags, BGP_INFO_MULTIPATH); } /* @@ -332,12 +320,11 @@ bgp_info_mpath_dequeue (struct bgp_info *binfo) * * Given a bgp_info, return the next multipath entry */ -struct bgp_info * -bgp_info_mpath_next (struct bgp_info *binfo) +struct bgp_info *bgp_info_mpath_next(struct bgp_info *binfo) { - if (!binfo->mpath || !binfo->mpath->mp_next) - return NULL; - return binfo->mpath->mp_next->mp_info; + if (!binfo->mpath || !binfo->mpath->mp_next) + return NULL; + return binfo->mpath->mp_next->mp_info; } /* @@ -345,10 +332,9 @@ bgp_info_mpath_next (struct bgp_info *binfo) * * Given bestpath bgp_info, return the first multipath entry. */ -struct bgp_info * -bgp_info_mpath_first (struct bgp_info *binfo) +struct bgp_info *bgp_info_mpath_first(struct bgp_info *binfo) { - return bgp_info_mpath_next (binfo); + return bgp_info_mpath_next(binfo); } /* @@ -356,12 +342,11 @@ bgp_info_mpath_first (struct bgp_info *binfo) * * Given the bestpath bgp_info, return the number of multipath entries */ -u_int32_t -bgp_info_mpath_count (struct bgp_info *binfo) +u_int32_t bgp_info_mpath_count(struct bgp_info *binfo) { - if (!binfo->mpath) - return 0; - return binfo->mpath->mp_count; + if (!binfo->mpath) + return 0; + return binfo->mpath->mp_count; } /* @@ -369,16 +354,15 @@ bgp_info_mpath_count (struct bgp_info *binfo) * * Sets the count of multipaths into bestpath's mpath element */ -static void -bgp_info_mpath_count_set (struct bgp_info *binfo, u_int32_t count) +static void bgp_info_mpath_count_set(struct bgp_info *binfo, u_int32_t count) { - struct bgp_info_mpath *mpath; - if (!count && !binfo->mpath) - return; - mpath = bgp_info_mpath_get (binfo); - if (!mpath) - return; - mpath->mp_count = count; + struct bgp_info_mpath *mpath; + if (!count && !binfo->mpath) + return; + mpath = bgp_info_mpath_get(binfo); + if (!mpath) + return; + mpath->mp_count = count; } /* @@ -387,12 +371,11 @@ bgp_info_mpath_count_set (struct bgp_info *binfo, u_int32_t count) * Given bestpath bgp_info, return aggregated attribute set used * for advertising the multipath route */ -struct attr * -bgp_info_mpath_attr (struct bgp_info *binfo) +struct attr *bgp_info_mpath_attr(struct bgp_info *binfo) { - if (!binfo->mpath) - return NULL; - return binfo->mpath->mp_attr; + if (!binfo->mpath) + return NULL; + return binfo->mpath->mp_attr; } /* @@ -400,16 +383,15 @@ bgp_info_mpath_attr (struct bgp_info *binfo) * * Sets the aggregated attribute into bestpath's mpath element */ -static void -bgp_info_mpath_attr_set (struct bgp_info *binfo, struct attr *attr) +static void bgp_info_mpath_attr_set(struct bgp_info *binfo, struct attr *attr) { - struct bgp_info_mpath *mpath; - if (!attr && !binfo->mpath) - return; - mpath = bgp_info_mpath_get (binfo); - if (!mpath) - return; - mpath->mp_attr = attr; + struct bgp_info_mpath *mpath; + if (!attr && !binfo->mpath) + return; + mpath = bgp_info_mpath_get(binfo); + if (!mpath) + return; + mpath->mp_attr = attr; } /* @@ -418,196 +400,210 @@ bgp_info_mpath_attr_set (struct bgp_info *binfo, struct attr *attr) * Compare and sync up the multipath list with the mp_list generated by * bgp_best_selection */ -void -bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, - struct bgp_info *old_best, struct list *mp_list, - struct bgp_maxpaths_cfg *mpath_cfg) +void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best, + struct bgp_info *old_best, struct list *mp_list, + struct bgp_maxpaths_cfg *mpath_cfg) { - u_int16_t maxpaths, mpath_count, old_mpath_count; - struct listnode *mp_node, *mp_next_node; - struct bgp_info *cur_mpath, *new_mpath, *next_mpath, *prev_mpath; - int mpath_changed, debug; - char pfx_buf[PREFIX2STR_BUFFER], nh_buf[2][INET6_ADDRSTRLEN]; - char path_buf[PATH_ADDPATH_STR_BUFFER]; - - mpath_changed = 0; - maxpaths = multipath_num; - mpath_count = 0; - cur_mpath = NULL; - old_mpath_count = 0; - prev_mpath = new_best; - mp_node = listhead (mp_list); - debug = bgp_debug_bestpath(&rn->p); - - if (debug) - prefix2str (&rn->p, pfx_buf, sizeof (pfx_buf)); - - if (new_best) - { - mpath_count++; - if (new_best != old_best) - bgp_info_mpath_dequeue (new_best); - maxpaths = (new_best->peer->sort == BGP_PEER_IBGP) ? - mpath_cfg->maxpaths_ibgp : mpath_cfg->maxpaths_ebgp; - } - - if (old_best) - { - cur_mpath = bgp_info_mpath_first (old_best); - old_mpath_count = bgp_info_mpath_count (old_best); - bgp_info_mpath_count_set (old_best, 0); - bgp_info_mpath_dequeue (old_best); - } - - if (debug) - zlog_debug("%s: starting mpath update, newbest %s num candidates %d old-mpath-count %d", - pfx_buf, new_best ? new_best->peer->host : "NONE", - listcount (mp_list), old_mpath_count); - - /* - * We perform an ordered walk through both lists in parallel. - * The reason for the ordered walk is that if there are paths - * that were previously multipaths and are still multipaths, the walk - * should encounter them in both lists at the same time. Otherwise - * there will be paths that are in one list or another, and we - * will deal with these separately. - * - * Note that new_best might be somewhere in the mp_list, so we need - * to skip over it - */ - while (mp_node || cur_mpath) - { - struct bgp_info *tmp_info; - - /* - * We can bail out of this loop if all existing paths on the - * multipath list have been visited (for cleanup purposes) and - * the maxpath requirement is fulfulled - */ - if (!cur_mpath && (mpath_count >= maxpaths)) - break; - - mp_next_node = mp_node ? listnextnode (mp_node) : NULL; - next_mpath = cur_mpath ? bgp_info_mpath_next (cur_mpath) : NULL; - tmp_info = mp_node ? listgetdata (mp_node) : NULL; - - if (debug) - zlog_debug("%s: comparing candidate %s with existing mpath %s", - pfx_buf, tmp_info ? tmp_info->peer->host : "NONE", - cur_mpath ? cur_mpath->peer->host : "NONE"); - - /* - * If equal, the path was a multipath and is still a multipath. - * Insert onto new multipath list if maxpaths allows. - */ - if (mp_node && (listgetdata (mp_node) == cur_mpath)) - { - list_delete_node (mp_list, mp_node); - bgp_info_mpath_dequeue (cur_mpath); - if ((mpath_count < maxpaths) && - bgp_info_nexthop_cmp (prev_mpath, cur_mpath)) - { - bgp_info_mpath_enqueue (prev_mpath, cur_mpath); - prev_mpath = cur_mpath; - mpath_count++; - if (debug) - { - bgp_info_path_with_addpath_rx_str(cur_mpath, path_buf); - zlog_debug("%s: %s is still multipath, cur count %d", - pfx_buf, path_buf, mpath_count); - } - } - else - { - mpath_changed = 1; - if (debug) - { - bgp_info_path_with_addpath_rx_str(cur_mpath, path_buf); - zlog_debug ("%s: remove mpath %s nexthop %s, cur count %d", - pfx_buf, path_buf, - inet_ntop (AF_INET, &cur_mpath->attr->nexthop, - nh_buf[0], sizeof (nh_buf[0])), - mpath_count); - } - } - mp_node = mp_next_node; - cur_mpath = next_mpath; - continue; - } - - if (cur_mpath && (!mp_node || - (bgp_info_mpath_cmp (cur_mpath, - listgetdata (mp_node)) < 0))) - { - /* - * If here, we have an old multipath and either the mp_list - * is finished or the next mp_node points to a later - * multipath, so we need to purge this path from the - * multipath list - */ - bgp_info_mpath_dequeue (cur_mpath); - mpath_changed = 1; - if (debug) - { - bgp_info_path_with_addpath_rx_str(cur_mpath, path_buf); - zlog_debug ("%s: remove mpath %s nexthop %s, cur count %d", - pfx_buf, path_buf, - inet_ntop (AF_INET, &cur_mpath->attr->nexthop, - nh_buf[0], sizeof (nh_buf[0])), - mpath_count); - } - cur_mpath = next_mpath; - } - else - { - /* - * If here, we have a path on the mp_list that was not previously - * a multipath (due to non-equivalance or maxpaths exceeded), - * or the matching multipath is sorted later in the multipath - * list. Before we enqueue the path on the new multipath list, - * make sure its not on the old_best multipath list or referenced - * via next_mpath: - * - If next_mpath points to this new path, update next_mpath to - * point to the multipath after this one - * - Dequeue the path from the multipath list just to make sure - */ - new_mpath = listgetdata (mp_node); - list_delete_node (mp_list, mp_node); - if ((mpath_count < maxpaths) && (new_mpath != new_best) && - bgp_info_nexthop_cmp (prev_mpath, new_mpath)) - { - if (new_mpath == next_mpath) - bgp_info_mpath_next (new_mpath); - bgp_info_mpath_dequeue (new_mpath); - - bgp_info_mpath_enqueue (prev_mpath, new_mpath); - prev_mpath = new_mpath; - mpath_changed = 1; - mpath_count++; - if (debug) - { - bgp_info_path_with_addpath_rx_str(new_mpath, path_buf); - zlog_debug ("%s: add mpath %s nexthop %s, cur count %d", - pfx_buf, path_buf, - inet_ntop (AF_INET, &new_mpath->attr->nexthop, - nh_buf[0], sizeof (nh_buf[0])), - mpath_count); - } - } - mp_node = mp_next_node; - } - } - - if (new_best) - { - if (debug) - zlog_debug("%s: New mpath count (incl newbest) %d mpath-change %s", - pfx_buf, mpath_count, mpath_changed ? "YES" : "NO"); - - bgp_info_mpath_count_set (new_best, mpath_count-1); - if (mpath_changed || (bgp_info_mpath_count (new_best) != old_mpath_count)) - SET_FLAG (new_best->flags, BGP_INFO_MULTIPATH_CHG); - } + u_int16_t maxpaths, mpath_count, old_mpath_count; + struct listnode *mp_node, *mp_next_node; + struct bgp_info *cur_mpath, *new_mpath, *next_mpath, *prev_mpath; + int mpath_changed, debug; + char pfx_buf[PREFIX2STR_BUFFER], nh_buf[2][INET6_ADDRSTRLEN]; + char path_buf[PATH_ADDPATH_STR_BUFFER]; + + mpath_changed = 0; + maxpaths = multipath_num; + mpath_count = 0; + cur_mpath = NULL; + old_mpath_count = 0; + prev_mpath = new_best; + mp_node = listhead(mp_list); + debug = bgp_debug_bestpath(&rn->p); + + if (debug) + prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf)); + + if (new_best) { + mpath_count++; + if (new_best != old_best) + bgp_info_mpath_dequeue(new_best); + maxpaths = (new_best->peer->sort == BGP_PEER_IBGP) + ? mpath_cfg->maxpaths_ibgp + : mpath_cfg->maxpaths_ebgp; + } + + if (old_best) { + cur_mpath = bgp_info_mpath_first(old_best); + old_mpath_count = bgp_info_mpath_count(old_best); + bgp_info_mpath_count_set(old_best, 0); + bgp_info_mpath_dequeue(old_best); + } + + if (debug) + zlog_debug( + "%s: starting mpath update, newbest %s num candidates %d old-mpath-count %d", + pfx_buf, new_best ? new_best->peer->host : "NONE", + listcount(mp_list), old_mpath_count); + + /* + * We perform an ordered walk through both lists in parallel. + * The reason for the ordered walk is that if there are paths + * that were previously multipaths and are still multipaths, the walk + * should encounter them in both lists at the same time. Otherwise + * there will be paths that are in one list or another, and we + * will deal with these separately. + * + * Note that new_best might be somewhere in the mp_list, so we need + * to skip over it + */ + while (mp_node || cur_mpath) { + struct bgp_info *tmp_info; + + /* + * We can bail out of this loop if all existing paths on the + * multipath list have been visited (for cleanup purposes) and + * the maxpath requirement is fulfulled + */ + if (!cur_mpath && (mpath_count >= maxpaths)) + break; + + mp_next_node = mp_node ? listnextnode(mp_node) : NULL; + next_mpath = cur_mpath ? bgp_info_mpath_next(cur_mpath) : NULL; + tmp_info = mp_node ? listgetdata(mp_node) : NULL; + + if (debug) + zlog_debug( + "%s: comparing candidate %s with existing mpath %s", + pfx_buf, + tmp_info ? tmp_info->peer->host : "NONE", + cur_mpath ? cur_mpath->peer->host : "NONE"); + + /* + * If equal, the path was a multipath and is still a multipath. + * Insert onto new multipath list if maxpaths allows. + */ + if (mp_node && (listgetdata(mp_node) == cur_mpath)) { + list_delete_node(mp_list, mp_node); + bgp_info_mpath_dequeue(cur_mpath); + if ((mpath_count < maxpaths) + && bgp_info_nexthop_cmp(prev_mpath, cur_mpath)) { + bgp_info_mpath_enqueue(prev_mpath, cur_mpath); + prev_mpath = cur_mpath; + mpath_count++; + if (debug) { + bgp_info_path_with_addpath_rx_str( + cur_mpath, path_buf); + zlog_debug( + "%s: %s is still multipath, cur count %d", + pfx_buf, path_buf, mpath_count); + } + } else { + mpath_changed = 1; + if (debug) { + bgp_info_path_with_addpath_rx_str( + cur_mpath, path_buf); + zlog_debug( + "%s: remove mpath %s nexthop %s, cur count %d", + pfx_buf, path_buf, + inet_ntop(AF_INET, + &cur_mpath->attr + ->nexthop, + nh_buf[0], + sizeof(nh_buf[0])), + mpath_count); + } + } + mp_node = mp_next_node; + cur_mpath = next_mpath; + continue; + } + + if (cur_mpath + && (!mp_node + || (bgp_info_mpath_cmp(cur_mpath, listgetdata(mp_node)) + < 0))) { + /* + * If here, we have an old multipath and either the + * mp_list + * is finished or the next mp_node points to a later + * multipath, so we need to purge this path from the + * multipath list + */ + bgp_info_mpath_dequeue(cur_mpath); + mpath_changed = 1; + if (debug) { + bgp_info_path_with_addpath_rx_str(cur_mpath, + path_buf); + zlog_debug( + "%s: remove mpath %s nexthop %s, cur count %d", + pfx_buf, path_buf, + inet_ntop(AF_INET, + &cur_mpath->attr->nexthop, + nh_buf[0], sizeof(nh_buf[0])), + mpath_count); + } + cur_mpath = next_mpath; + } else { + /* + * If here, we have a path on the mp_list that was not + * previously + * a multipath (due to non-equivalance or maxpaths + * exceeded), + * or the matching multipath is sorted later in the + * multipath + * list. Before we enqueue the path on the new multipath + * list, + * make sure its not on the old_best multipath list or + * referenced + * via next_mpath: + * - If next_mpath points to this new path, update + * next_mpath to + * point to the multipath after this one + * - Dequeue the path from the multipath list just to + * make sure + */ + new_mpath = listgetdata(mp_node); + list_delete_node(mp_list, mp_node); + if ((mpath_count < maxpaths) && (new_mpath != new_best) + && bgp_info_nexthop_cmp(prev_mpath, new_mpath)) { + if (new_mpath == next_mpath) + bgp_info_mpath_next(new_mpath); + bgp_info_mpath_dequeue(new_mpath); + + bgp_info_mpath_enqueue(prev_mpath, new_mpath); + prev_mpath = new_mpath; + mpath_changed = 1; + mpath_count++; + if (debug) { + bgp_info_path_with_addpath_rx_str( + new_mpath, path_buf); + zlog_debug( + "%s: add mpath %s nexthop %s, cur count %d", + pfx_buf, path_buf, + inet_ntop(AF_INET, + &new_mpath->attr + ->nexthop, + nh_buf[0], + sizeof(nh_buf[0])), + mpath_count); + } + } + mp_node = mp_next_node; + } + } + + if (new_best) { + if (debug) + zlog_debug( + "%s: New mpath count (incl newbest) %d mpath-change %s", + pfx_buf, mpath_count, + mpath_changed ? "YES" : "NO"); + + bgp_info_mpath_count_set(new_best, mpath_count - 1); + if (mpath_changed + || (bgp_info_mpath_count(new_best) != old_mpath_count)) + SET_FLAG(new_best->flags, BGP_INFO_MULTIPATH_CHG); + } } /* @@ -616,23 +612,22 @@ bgp_info_mpath_update (struct bgp_node *rn, struct bgp_info *new_best, * Clean up multipath information for BGP_INFO_DMED_SELECTED path that * is not selected as best path */ -void -bgp_mp_dmed_deselect (struct bgp_info *dmed_best) +void bgp_mp_dmed_deselect(struct bgp_info *dmed_best) { - struct bgp_info *mpinfo, *mpnext; + struct bgp_info *mpinfo, *mpnext; - if (!dmed_best) - return; + if (!dmed_best) + return; - for (mpinfo = bgp_info_mpath_first (dmed_best); mpinfo; mpinfo = mpnext) - { - mpnext = bgp_info_mpath_next (mpinfo); - bgp_info_mpath_dequeue (mpinfo); - } + for (mpinfo = bgp_info_mpath_first(dmed_best); mpinfo; + mpinfo = mpnext) { + mpnext = bgp_info_mpath_next(mpinfo); + bgp_info_mpath_dequeue(mpinfo); + } - bgp_info_mpath_count_set (dmed_best, 0); - UNSET_FLAG (dmed_best->flags, BGP_INFO_MULTIPATH_CHG); - assert (bgp_info_mpath_first (dmed_best) == 0); + bgp_info_mpath_count_set(dmed_best, 0); + UNSET_FLAG(dmed_best->flags, BGP_INFO_MULTIPATH_CHG); + assert(bgp_info_mpath_first(dmed_best) == 0); } /* @@ -647,129 +642,124 @@ bgp_mp_dmed_deselect (struct bgp_info *dmed_best) * is no change in multipath selection and no attribute change in * any multipath. */ -void -bgp_info_mpath_aggregate_update (struct bgp_info *new_best, - struct bgp_info *old_best) +void bgp_info_mpath_aggregate_update(struct bgp_info *new_best, + struct bgp_info *old_best) { - struct bgp_info *mpinfo; - struct aspath *aspath; - struct aspath *asmerge; - struct attr *new_attr, *old_attr; - u_char origin; - struct community *community, *commerge; - struct ecommunity *ecomm, *ecommerge; - struct lcommunity *lcomm, *lcommerge; - struct attr attr = { 0 }; - - if (old_best && (old_best != new_best) && - (old_attr = bgp_info_mpath_attr (old_best))) - { - bgp_attr_unintern (&old_attr); - bgp_info_mpath_attr_set (old_best, NULL); - } - - if (!new_best) - return; - - if (!bgp_info_mpath_count (new_best)) - { - if ((new_attr = bgp_info_mpath_attr (new_best))) - { - bgp_attr_unintern (&new_attr); - bgp_info_mpath_attr_set (new_best, NULL); - SET_FLAG (new_best->flags, BGP_INFO_ATTR_CHANGED); - } - return; - } - - bgp_attr_dup (&attr, new_best->attr); - - if (new_best->peer && - bgp_flag_check (new_best->peer->bgp, BGP_FLAG_MULTIPATH_RELAX_AS_SET)) - { - - /* aggregate attribute from multipath constituents */ - aspath = aspath_dup (attr.aspath); - origin = attr.origin; - community = attr.community ? community_dup (attr.community) : NULL; - ecomm = (attr.ecommunity) ? ecommunity_dup (attr.ecommunity) : NULL; - lcomm = (attr.lcommunity) ? lcommunity_dup (attr.lcommunity) : NULL; - - for (mpinfo = bgp_info_mpath_first (new_best); mpinfo; - mpinfo = bgp_info_mpath_next (mpinfo)) - { - asmerge = aspath_aggregate (aspath, mpinfo->attr->aspath); - aspath_free (aspath); - aspath = asmerge; - - if (origin < mpinfo->attr->origin) - origin = mpinfo->attr->origin; - - if (mpinfo->attr->community) - { - if (community) - { - commerge = community_merge (community, mpinfo->attr->community); - community = community_uniq_sort (commerge); - community_free (commerge); - } - else - community = community_dup (mpinfo->attr->community); - } - - if (mpinfo->attr->ecommunity) - { - if (ecomm) - { - ecommerge = ecommunity_merge (ecomm, mpinfo->attr->ecommunity); - ecomm = ecommunity_uniq_sort (ecommerge); - ecommunity_free (&ecommerge); - } - else - ecomm = ecommunity_dup (mpinfo->attr->ecommunity); - } - if (mpinfo->attr->lcommunity) - { - if (lcomm) - { - lcommerge = lcommunity_merge (lcomm, mpinfo->attr->lcommunity); - lcomm = lcommunity_uniq_sort (lcommerge); - lcommunity_free (&lcommerge); - } - else - lcomm = lcommunity_dup (mpinfo->attr->lcommunity); - } - } - - attr.aspath = aspath; - attr.origin = origin; - if (community) - { - attr.community = community; - attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES); - } - if (ecomm) - { - attr.ecommunity = ecomm; - attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES); - } - - /* Zap multipath attr nexthop so we set nexthop to self */ - attr.nexthop.s_addr = 0; - memset (&attr.mp_nexthop_global, 0, sizeof (struct in6_addr)); - - /* TODO: should we set ATOMIC_AGGREGATE and AGGREGATOR? */ - } - - new_attr = bgp_attr_intern (&attr); - - if (new_attr != bgp_info_mpath_attr (new_best)) - { - if ((old_attr = bgp_info_mpath_attr (new_best))) - bgp_attr_unintern (&old_attr); - bgp_info_mpath_attr_set (new_best, new_attr); - SET_FLAG (new_best->flags, BGP_INFO_ATTR_CHANGED); - } - else - bgp_attr_unintern (&new_attr); + struct bgp_info *mpinfo; + struct aspath *aspath; + struct aspath *asmerge; + struct attr *new_attr, *old_attr; + u_char origin; + struct community *community, *commerge; + struct ecommunity *ecomm, *ecommerge; + struct lcommunity *lcomm, *lcommerge; + struct attr attr = {0}; + + if (old_best && (old_best != new_best) + && (old_attr = bgp_info_mpath_attr(old_best))) { + bgp_attr_unintern(&old_attr); + bgp_info_mpath_attr_set(old_best, NULL); + } + + if (!new_best) + return; + + if (!bgp_info_mpath_count(new_best)) { + if ((new_attr = bgp_info_mpath_attr(new_best))) { + bgp_attr_unintern(&new_attr); + bgp_info_mpath_attr_set(new_best, NULL); + SET_FLAG(new_best->flags, BGP_INFO_ATTR_CHANGED); + } + return; + } + + bgp_attr_dup(&attr, new_best->attr); + + if (new_best->peer && bgp_flag_check(new_best->peer->bgp, + BGP_FLAG_MULTIPATH_RELAX_AS_SET)) { + + /* aggregate attribute from multipath constituents */ + aspath = aspath_dup(attr.aspath); + origin = attr.origin; + community = + attr.community ? community_dup(attr.community) : NULL; + ecomm = (attr.ecommunity) ? ecommunity_dup(attr.ecommunity) + : NULL; + lcomm = (attr.lcommunity) ? lcommunity_dup(attr.lcommunity) + : NULL; + + for (mpinfo = bgp_info_mpath_first(new_best); mpinfo; + mpinfo = bgp_info_mpath_next(mpinfo)) { + asmerge = + aspath_aggregate(aspath, mpinfo->attr->aspath); + aspath_free(aspath); + aspath = asmerge; + + if (origin < mpinfo->attr->origin) + origin = mpinfo->attr->origin; + + if (mpinfo->attr->community) { + if (community) { + commerge = community_merge( + community, + mpinfo->attr->community); + community = + community_uniq_sort(commerge); + community_free(commerge); + } else + community = community_dup( + mpinfo->attr->community); + } + + if (mpinfo->attr->ecommunity) { + if (ecomm) { + ecommerge = ecommunity_merge( + ecomm, + mpinfo->attr->ecommunity); + ecomm = ecommunity_uniq_sort(ecommerge); + ecommunity_free(&ecommerge); + } else + ecomm = ecommunity_dup( + mpinfo->attr->ecommunity); + } + if (mpinfo->attr->lcommunity) { + if (lcomm) { + lcommerge = lcommunity_merge( + lcomm, + mpinfo->attr->lcommunity); + lcomm = lcommunity_uniq_sort(lcommerge); + lcommunity_free(&lcommerge); + } else + lcomm = lcommunity_dup( + mpinfo->attr->lcommunity); + } + } + + attr.aspath = aspath; + attr.origin = origin; + if (community) { + attr.community = community; + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES); + } + if (ecomm) { + attr.ecommunity = ecomm; + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES); + } + + /* Zap multipath attr nexthop so we set nexthop to self */ + attr.nexthop.s_addr = 0; + memset(&attr.mp_nexthop_global, 0, sizeof(struct in6_addr)); + + /* TODO: should we set ATOMIC_AGGREGATE and AGGREGATOR? */ + } + + new_attr = bgp_attr_intern(&attr); + + if (new_attr != bgp_info_mpath_attr(new_best)) { + if ((old_attr = bgp_info_mpath_attr(new_best))) + bgp_attr_unintern(&old_attr); + bgp_info_mpath_attr_set(new_best, new_attr); + SET_FLAG(new_best->flags, BGP_INFO_ATTR_CHANGED); + } else + bgp_attr_unintern(&new_attr); } diff --git a/bgpd/bgp_mpath.h b/bgpd/bgp_mpath.h index 316dda3ec..48af14eb7 100644 --- a/bgpd/bgp_mpath.h +++ b/bgpd/bgp_mpath.h @@ -25,53 +25,52 @@ /* Supplemental information linked to bgp_info for keeping track of * multipath selections, lazily allocated to save memory */ -struct bgp_info_mpath -{ - /* Points to the first multipath (on bestpath) or the next multipath */ - struct bgp_info_mpath *mp_next; +struct bgp_info_mpath { + /* Points to the first multipath (on bestpath) or the next multipath */ + struct bgp_info_mpath *mp_next; - /* Points to the previous multipath or NULL on bestpath */ - struct bgp_info_mpath *mp_prev; + /* Points to the previous multipath or NULL on bestpath */ + struct bgp_info_mpath *mp_prev; - /* Points to bgp_info associated with this multipath info */ - struct bgp_info *mp_info; + /* Points to bgp_info associated with this multipath info */ + struct bgp_info *mp_info; - /* When attached to best path, the number of selected multipaths */ - u_int32_t mp_count; + /* When attached to best path, the number of selected multipaths */ + u_int32_t mp_count; - /* Aggregated attribute for advertising multipath route */ - struct attr *mp_attr; + /* Aggregated attribute for advertising multipath route */ + struct attr *mp_attr; }; /* Functions to support maximum-paths configuration */ -extern int bgp_maximum_paths_set (struct bgp *, afi_t, safi_t, int, u_int16_t, - u_int16_t); -extern int bgp_maximum_paths_unset (struct bgp *, afi_t, safi_t, int); +extern int bgp_maximum_paths_set(struct bgp *, afi_t, safi_t, int, u_int16_t, + u_int16_t); +extern int bgp_maximum_paths_unset(struct bgp *, afi_t, safi_t, int); /* Functions used by bgp_best_selection to record current * multipath selections */ -extern int bgp_info_nexthop_cmp (struct bgp_info *bi1, struct bgp_info *bi2); -extern void bgp_mp_list_init (struct list *); -extern void bgp_mp_list_clear (struct list *); -extern void bgp_mp_list_add (struct list *, struct bgp_info *); -extern void bgp_mp_dmed_deselect (struct bgp_info *); -extern void bgp_info_mpath_update (struct bgp_node *, struct bgp_info *, - struct bgp_info *, struct list *, - struct bgp_maxpaths_cfg *); -extern void bgp_info_mpath_aggregate_update (struct bgp_info *, - struct bgp_info *); +extern int bgp_info_nexthop_cmp(struct bgp_info *bi1, struct bgp_info *bi2); +extern void bgp_mp_list_init(struct list *); +extern void bgp_mp_list_clear(struct list *); +extern void bgp_mp_list_add(struct list *, struct bgp_info *); +extern void bgp_mp_dmed_deselect(struct bgp_info *); +extern void bgp_info_mpath_update(struct bgp_node *, struct bgp_info *, + struct bgp_info *, struct list *, + struct bgp_maxpaths_cfg *); +extern void bgp_info_mpath_aggregate_update(struct bgp_info *, + struct bgp_info *); /* Unlink and free multipath information associated with a bgp_info */ -extern void bgp_info_mpath_dequeue (struct bgp_info *); -extern void bgp_info_mpath_free (struct bgp_info_mpath **); +extern void bgp_info_mpath_dequeue(struct bgp_info *); +extern void bgp_info_mpath_free(struct bgp_info_mpath **); /* Walk list of multipaths associated with a best path */ -extern struct bgp_info *bgp_info_mpath_first (struct bgp_info *); -extern struct bgp_info *bgp_info_mpath_next (struct bgp_info *); +extern struct bgp_info *bgp_info_mpath_first(struct bgp_info *); +extern struct bgp_info *bgp_info_mpath_next(struct bgp_info *); /* Accessors for multipath information */ -extern u_int32_t bgp_info_mpath_count (struct bgp_info *); -extern struct attr *bgp_info_mpath_attr (struct bgp_info *); +extern u_int32_t bgp_info_mpath_count(struct bgp_info *); +extern struct attr *bgp_info_mpath_attr(struct bgp_info *); #endif /* _QUAGGA_BGP_MPATH_H */ diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 3a8398d8a..5d2966d1a 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -43,200 +43,193 @@ #include "bgpd/rfapi/rfapi_backend.h" #endif -extern int -argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc, int *index, afi_t *afi) +extern int argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc, + int *index, afi_t *afi) { - int ret = 0; - if (argv_find (argv, argc, "vpnv4", index)) - { - ret = 1; - if (afi) - *afi = AFI_IP; - } - else if (argv_find (argv, argc, "vpnv6", index)) - { - ret = 1; - if (afi) - *afi = AFI_IP6; - } - return ret; + int ret = 0; + if (argv_find(argv, argc, "vpnv4", index)) { + ret = 1; + if (afi) + *afi = AFI_IP; + } else if (argv_find(argv, argc, "vpnv6", index)) { + ret = 1; + if (afi) + *afi = AFI_IP6; + } + return ret; } -u_int32_t -decode_label (mpls_label_t *label_pnt) +u_int32_t decode_label(mpls_label_t *label_pnt) { - u_int32_t l; - u_char *pnt = (u_char *) label_pnt; + u_int32_t l; + u_char *pnt = (u_char *)label_pnt; - l = ((u_int32_t) *pnt++ << 12); - l |= (u_int32_t) *pnt++ << 4; - l |= (u_int32_t) ((*pnt & 0xf0) >> 4); - return l; + l = ((u_int32_t)*pnt++ << 12); + l |= (u_int32_t)*pnt++ << 4; + l |= (u_int32_t)((*pnt & 0xf0) >> 4); + return l; } -void -encode_label(mpls_label_t label, - mpls_label_t *label_pnt) +void encode_label(mpls_label_t label, mpls_label_t *label_pnt) { - u_char *pnt = (u_char *) label_pnt; - if (pnt == NULL) - return; - *pnt++ = (label>>12) & 0xff; - *pnt++ = (label>>4) & 0xff; - *pnt++ = ((label<<4)+1) & 0xff; /* S=1 */ + u_char *pnt = (u_char *)label_pnt; + if (pnt == NULL) + return; + *pnt++ = (label >> 12) & 0xff; + *pnt++ = (label >> 4) & 0xff; + *pnt++ = ((label << 4) + 1) & 0xff; /* S=1 */ } -int -bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr, - struct bgp_nlri *packet) +int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr, + struct bgp_nlri *packet) { - u_char *pnt; - u_char *lim; - struct prefix p; - int psize = 0; - int prefixlen; - u_int16_t type; - struct rd_as rd_as; - struct rd_ip rd_ip; - struct prefix_rd prd; - mpls_label_t label; - afi_t afi; - safi_t safi; - int addpath_encoded; - u_int32_t addpath_id; - - /* Check peer status. */ - if (peer->status != Established) - return 0; - - /* Make prefix_rd */ - prd.family = AF_UNSPEC; - prd.prefixlen = 64; - - pnt = packet->nlri; - lim = pnt + packet->length; - afi = packet->afi; - safi = packet->safi; - addpath_id = 0; - - addpath_encoded = (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) && - CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV)); + u_char *pnt; + u_char *lim; + struct prefix p; + int psize = 0; + int prefixlen; + u_int16_t type; + struct rd_as rd_as; + struct rd_ip rd_ip; + struct prefix_rd prd; + mpls_label_t label; + afi_t afi; + safi_t safi; + int addpath_encoded; + u_int32_t addpath_id; + + /* Check peer status. */ + if (peer->status != Established) + return 0; + + /* Make prefix_rd */ + prd.family = AF_UNSPEC; + prd.prefixlen = 64; + + pnt = packet->nlri; + lim = pnt + packet->length; + afi = packet->afi; + safi = packet->safi; + addpath_id = 0; + + addpath_encoded = + (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) + && CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ADDPATH_AF_TX_RCV)); #define VPN_PREFIXLEN_MIN_BYTES (3 + 8) /* label + RD */ - for (; pnt < lim; pnt += psize) - { - /* Clear prefix structure. */ - memset (&p, 0, sizeof (struct prefix)); - - if (addpath_encoded) - { - - /* When packet overflow occurs return immediately. */ - if (pnt + BGP_ADDPATH_ID_LEN > lim) - return -1; - - addpath_id = ntohl(*((uint32_t*) pnt)); - pnt += BGP_ADDPATH_ID_LEN; - } - - /* Fetch prefix length. */ - prefixlen = *pnt++; - p.family = afi2family (packet->afi); - psize = PSIZE (prefixlen); - - if (prefixlen < VPN_PREFIXLEN_MIN_BYTES*8) - { - zlog_err ("%s [Error] Update packet error / VPN (prefix length %d less than VPN min length)", - peer->host, prefixlen); - return -1; - } - - /* sanity check against packet data */ - if ((pnt + psize) > lim) - { - zlog_err ("%s [Error] Update packet error / VPN (prefix length %d exceeds packet size %u)", - peer->host, - prefixlen, (uint)(lim-pnt)); - return -1; - } - - /* sanity check against storage for the IP address portion */ - if ((psize - VPN_PREFIXLEN_MIN_BYTES) > (ssize_t) sizeof(p.u)) - { - zlog_err ("%s [Error] Update packet error / VPN (psize %d exceeds storage size %zu)", - peer->host, - prefixlen - VPN_PREFIXLEN_MIN_BYTES*8, sizeof(p.u)); - return -1; - } - - /* Sanity check against max bitlen of the address family */ - if ((psize - VPN_PREFIXLEN_MIN_BYTES) > prefix_blen (&p)) - { - zlog_err ("%s [Error] Update packet error / VPN (psize %d exceeds family (%u) max byte len %u)", - peer->host, - prefixlen - VPN_PREFIXLEN_MIN_BYTES*8, - p.family, prefix_blen (&p)); - return -1; - } - - /* Copy label to prefix. */ - memcpy(&label, pnt, BGP_LABEL_BYTES); - bgp_set_valid_label(&label); - - /* Copy routing distinguisher to rd. */ - memcpy (&prd.val, pnt + BGP_LABEL_BYTES, 8); - - /* Decode RD type. */ - type = decode_rd_type (pnt + BGP_LABEL_BYTES); - - switch (type) - { - case RD_TYPE_AS: - decode_rd_as (pnt + 5, &rd_as); - break; - - case RD_TYPE_AS4: - decode_rd_as4 (pnt + 5, &rd_as); - break; - - case RD_TYPE_IP: - decode_rd_ip (pnt + 5, &rd_ip); - break; + for (; pnt < lim; pnt += psize) { + /* Clear prefix structure. */ + memset(&p, 0, sizeof(struct prefix)); + + if (addpath_encoded) { + + /* When packet overflow occurs return immediately. */ + if (pnt + BGP_ADDPATH_ID_LEN > lim) + return -1; + + addpath_id = ntohl(*((uint32_t *)pnt)); + pnt += BGP_ADDPATH_ID_LEN; + } + + /* Fetch prefix length. */ + prefixlen = *pnt++; + p.family = afi2family(packet->afi); + psize = PSIZE(prefixlen); + + if (prefixlen < VPN_PREFIXLEN_MIN_BYTES * 8) { + zlog_err( + "%s [Error] Update packet error / VPN (prefix length %d less than VPN min length)", + peer->host, prefixlen); + return -1; + } + + /* sanity check against packet data */ + if ((pnt + psize) > lim) { + zlog_err( + "%s [Error] Update packet error / VPN (prefix length %d exceeds packet size %u)", + peer->host, prefixlen, (uint)(lim - pnt)); + return -1; + } + + /* sanity check against storage for the IP address portion */ + if ((psize - VPN_PREFIXLEN_MIN_BYTES) > (ssize_t)sizeof(p.u)) { + zlog_err( + "%s [Error] Update packet error / VPN (psize %d exceeds storage size %zu)", + peer->host, + prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8, + sizeof(p.u)); + return -1; + } + + /* Sanity check against max bitlen of the address family */ + if ((psize - VPN_PREFIXLEN_MIN_BYTES) > prefix_blen(&p)) { + zlog_err( + "%s [Error] Update packet error / VPN (psize %d exceeds family (%u) max byte len %u)", + peer->host, + prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8, + p.family, prefix_blen(&p)); + return -1; + } + + /* Copy label to prefix. */ + memcpy(&label, pnt, BGP_LABEL_BYTES); + bgp_set_valid_label(&label); + + /* Copy routing distinguisher to rd. */ + memcpy(&prd.val, pnt + BGP_LABEL_BYTES, 8); + + /* Decode RD type. */ + type = decode_rd_type(pnt + BGP_LABEL_BYTES); + + switch (type) { + case RD_TYPE_AS: + decode_rd_as(pnt + 5, &rd_as); + break; + + case RD_TYPE_AS4: + decode_rd_as4(pnt + 5, &rd_as); + break; + + case RD_TYPE_IP: + decode_rd_ip(pnt + 5, &rd_ip); + break; #if ENABLE_BGP_VNC - case RD_TYPE_VNC_ETH: - break; + case RD_TYPE_VNC_ETH: + break; #endif - default: - zlog_err ("Unknown RD type %d", type); - break; /* just report */ - } - - p.prefixlen = prefixlen - VPN_PREFIXLEN_MIN_BYTES*8;/* exclude label & RD */ - memcpy (&p.u.prefix, pnt + VPN_PREFIXLEN_MIN_BYTES, - psize - VPN_PREFIXLEN_MIN_BYTES); - - if (attr) - { - bgp_update (peer, &p, addpath_id, attr, packet->afi, SAFI_MPLS_VPN, - ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, &label, 0, NULL); - } - else - { - bgp_withdraw (peer, &p, addpath_id, attr, packet->afi, SAFI_MPLS_VPN, - ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, &label, NULL); - } - } - /* Packet length consistency check. */ - if (pnt != lim) - { - zlog_err ("%s [Error] Update packet error / VPN (%zu data remaining after parsing)", - peer->host, lim - pnt); - return -1; - } - - return 0; + default: + zlog_err("Unknown RD type %d", type); + break; /* just report */ + } + + p.prefixlen = + prefixlen + - VPN_PREFIXLEN_MIN_BYTES * 8; /* exclude label & RD */ + memcpy(&p.u.prefix, pnt + VPN_PREFIXLEN_MIN_BYTES, + psize - VPN_PREFIXLEN_MIN_BYTES); + + if (attr) { + bgp_update(peer, &p, addpath_id, attr, packet->afi, + SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP, + BGP_ROUTE_NORMAL, &prd, &label, 0, NULL); + } else { + bgp_withdraw(peer, &p, addpath_id, attr, packet->afi, + SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP, + BGP_ROUTE_NORMAL, &prd, &label, NULL); + } + } + /* Packet length consistency check. */ + if (pnt != lim) { + zlog_err( + "%s [Error] Update packet error / VPN (%zu data remaining after parsing)", + peer->host, lim - pnt); + return -1; + } + + return 0; #undef VPN_PREFIXLEN_MIN_BYTES } @@ -252,11 +245,13 @@ DEFUN (vpnv4_network, "VPN NLRI label (tag)\n" "Label value\n") { - int idx_ipv4_prefixlen = 1; - int idx_ext_community = 3; - int idx_label = 5; - return bgp_static_set_safi (AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg, - argv[idx_label]->arg, NULL, 0, NULL, NULL, NULL, NULL); + int idx_ipv4_prefixlen = 1; + int idx_ext_community = 3; + int idx_label = 5; + return bgp_static_set_safi( + AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, + argv[idx_ext_community]->arg, argv[idx_label]->arg, NULL, 0, + NULL, NULL, NULL, NULL); } DEFUN (vpnv4_network_route_map, @@ -272,12 +267,14 @@ DEFUN (vpnv4_network_route_map, "route map\n" "route map name\n") { - int idx_ipv4_prefixlen = 1; - int idx_ext_community = 3; - int idx_label = 5; - int idx_word_2 = 7; - return bgp_static_set_safi (AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg, argv[idx_label]->arg, - argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL); + int idx_ipv4_prefixlen = 1; + int idx_ext_community = 3; + int idx_label = 5; + int idx_word_2 = 7; + return bgp_static_set_safi( + AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, + argv[idx_ext_community]->arg, argv[idx_label]->arg, + argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL); } /* For testing purpose, static route of MPLS-VPN. */ @@ -293,12 +290,13 @@ DEFUN (no_vpnv4_network, "VPN NLRI label (tag)\n" "Label value\n") { - int idx_ipv4_prefixlen = 2; - int idx_ext_community = 4; - int idx_label = 6; - return bgp_static_unset_safi (AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, - argv[idx_ext_community]->arg, argv[idx_label]->arg, - 0, NULL, NULL, NULL); + int idx_ipv4_prefixlen = 2; + int idx_ext_community = 4; + int idx_label = 6; + return bgp_static_unset_safi(AFI_IP, SAFI_MPLS_VPN, vty, + argv[idx_ipv4_prefixlen]->arg, + argv[idx_ext_community]->arg, + argv[idx_label]->arg, 0, NULL, NULL, NULL); } DEFUN (vpnv6_network, @@ -314,14 +312,20 @@ DEFUN (vpnv6_network, "route map\n" "route map name\n") { - int idx_ipv6_prefix = 1; - int idx_ext_community = 3; - int idx_label = 5; - int idx_word_2 = 7; - if (argc == 8) - return bgp_static_set_safi (AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_label]->arg, argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL); - else - return bgp_static_set_safi (AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_label]->arg, NULL, 0, NULL, NULL, NULL, NULL); + int idx_ipv6_prefix = 1; + int idx_ext_community = 3; + int idx_label = 5; + int idx_word_2 = 7; + if (argc == 8) + return bgp_static_set_safi( + AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, + argv[idx_ext_community]->arg, argv[idx_label]->arg, + argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL); + else + return bgp_static_set_safi( + AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, + argv[idx_ext_community]->arg, argv[idx_label]->arg, + NULL, 0, NULL, NULL, NULL, NULL); } /* For testing purpose, static route of MPLS-VPN. */ @@ -337,225 +341,291 @@ DEFUN (no_vpnv6_network, "VPN NLRI label (tag)\n" "Label value\n") { - int idx_ipv6_prefix = 2; - int idx_ext_community = 4; - int idx_label = 6; - return bgp_static_unset_safi (AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_label]->arg, 0, NULL, NULL, NULL); + int idx_ipv6_prefix = 2; + int idx_ext_community = 4; + int idx_label = 6; + return bgp_static_unset_safi(AFI_IP6, SAFI_MPLS_VPN, vty, + argv[idx_ipv6_prefix]->arg, + argv[idx_ext_community]->arg, + argv[idx_label]->arg, 0, NULL, NULL, NULL); } -int -bgp_show_mpls_vpn (struct vty *vty, afi_t afi, struct prefix_rd *prd, - enum bgp_show_type type, void *output_arg, int tags, u_char use_json) +int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd, + enum bgp_show_type type, void *output_arg, int tags, + u_char use_json) { - struct bgp *bgp; - struct bgp_table *table; - struct bgp_node *rn; - struct bgp_node *rm; - struct bgp_info *ri; - int rd_header; - int header = 1; - unsigned long output_count = 0; - unsigned long total_count = 0; - json_object *json = NULL; - json_object *json_mroute = NULL; - json_object *json_nroute = NULL; - json_object *json_array = NULL; - json_object *json_scode = NULL; - json_object *json_ocode = NULL; - - bgp = bgp_get_default (); - if (bgp == NULL) - { - if (!use_json) - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING; - } - - if (use_json) - { - json_scode = json_object_new_object(); - json_ocode = json_object_new_object(); - json = json_object_new_object(); - json_mroute = json_object_new_object(); - json_nroute = json_object_new_object(); - - json_object_string_add(json_scode, "suppressed", "s"); - json_object_string_add(json_scode, "damped", "d"); - json_object_string_add(json_scode, "history", "h"); - json_object_string_add(json_scode, "valid", "*"); - json_object_string_add(json_scode, "best", ">"); - json_object_string_add(json_scode, "internal", "i"); - - json_object_string_add(json_ocode, "igp", "i"); - json_object_string_add(json_ocode, "egp", "e"); - json_object_string_add(json_ocode, "incomplete", "?"); - } - - if ((afi != AFI_IP) && (afi != AFI_IP6)) - { - vty_out (vty, "Afi %d not supported\n", afi); - return CMD_WARNING; - } - - for (rn = bgp_table_top (bgp->rib[afi][SAFI_MPLS_VPN]); rn; rn = bgp_route_next (rn)) - { - if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0) - continue; - - if ((table = rn->info) != NULL) - { - rd_header = 1; - - for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm)) - { - total_count++; - if (use_json) - json_array = json_object_new_array(); - else - json_array = NULL; - - for (ri = rm->info; ri; ri = ri->next) - { - if (type == bgp_show_type_neighbor) - { - union sockunion *su = output_arg; - - if (ri->peer->su_remote == NULL || ! sockunion_same(ri->peer->su_remote, su)) - continue; - } - if (header) - { - if (use_json) - { - if (!tags) - { - json_object_int_add(json, "bgpTableVersion", 0); - json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id)); - json_object_object_add(json, "bgpStatusCodes", json_scode); - json_object_object_add(json, "bgpOriginCodes", json_ocode); - } - } - else - { - if (tags) - vty_out (vty, V4_HEADER_TAG); - else - { - vty_out (vty, "BGP table version is 0, local router ID is %s\n", - inet_ntoa(bgp->router_id)); - vty_out (vty, - "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n"); - vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n"); - vty_out (vty, V4_HEADER); - } - } - header = 0; - } - - if (rd_header) - { - u_int16_t type; - struct rd_as rd_as; - struct rd_ip rd_ip = {0}; + struct bgp *bgp; + struct bgp_table *table; + struct bgp_node *rn; + struct bgp_node *rm; + struct bgp_info *ri; + int rd_header; + int header = 1; + unsigned long output_count = 0; + unsigned long total_count = 0; + json_object *json = NULL; + json_object *json_mroute = NULL; + json_object *json_nroute = NULL; + json_object *json_array = NULL; + json_object *json_scode = NULL; + json_object *json_ocode = NULL; + + bgp = bgp_get_default(); + if (bgp == NULL) { + if (!use_json) + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING; + } + + if (use_json) { + json_scode = json_object_new_object(); + json_ocode = json_object_new_object(); + json = json_object_new_object(); + json_mroute = json_object_new_object(); + json_nroute = json_object_new_object(); + + json_object_string_add(json_scode, "suppressed", "s"); + json_object_string_add(json_scode, "damped", "d"); + json_object_string_add(json_scode, "history", "h"); + json_object_string_add(json_scode, "valid", "*"); + json_object_string_add(json_scode, "best", ">"); + json_object_string_add(json_scode, "internal", "i"); + + json_object_string_add(json_ocode, "igp", "i"); + json_object_string_add(json_ocode, "egp", "e"); + json_object_string_add(json_ocode, "incomplete", "?"); + } + + if ((afi != AFI_IP) && (afi != AFI_IP6)) { + vty_out(vty, "Afi %d not supported\n", afi); + return CMD_WARNING; + } + + for (rn = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); rn; + rn = bgp_route_next(rn)) { + if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0) + continue; + + if ((table = rn->info) != NULL) { + rd_header = 1; + + for (rm = bgp_table_top(table); rm; + rm = bgp_route_next(rm)) { + total_count++; + if (use_json) + json_array = json_object_new_array(); + else + json_array = NULL; + + for (ri = rm->info; ri; ri = ri->next) { + if (type == bgp_show_type_neighbor) { + union sockunion *su = + output_arg; + + if (ri->peer->su_remote == NULL + || !sockunion_same( + ri->peer->su_remote, + su)) + continue; + } + if (header) { + if (use_json) { + if (!tags) { + json_object_int_add( + json, + "bgpTableVersion", + 0); + json_object_string_add( + json, + "bgpLocalRouterId", + inet_ntoa( + bgp->router_id)); + json_object_object_add( + json, + "bgpStatusCodes", + json_scode); + json_object_object_add( + json, + "bgpOriginCodes", + json_ocode); + } + } else { + if (tags) + vty_out(vty, + V4_HEADER_TAG); + else { + vty_out(vty, + "BGP table version is 0, local router ID is %s\n", + inet_ntoa( + bgp->router_id)); + vty_out(vty, + "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n"); + vty_out(vty, + "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n"); + vty_out(vty, + V4_HEADER); + } + } + header = 0; + } + + if (rd_header) { + u_int16_t type; + struct rd_as rd_as; + struct rd_ip rd_ip = {0}; #if ENABLE_BGP_VNC - struct rd_vnc_eth rd_vnc_eth = {0}; + struct rd_vnc_eth rd_vnc_eth = { + 0}; #endif - u_char *pnt; - - pnt = rn->p.u.val; - - /* Decode RD type. */ - type = decode_rd_type (pnt); - /* Decode RD value. */ - if (type == RD_TYPE_AS) - decode_rd_as (pnt + 2, &rd_as); - else if (type == RD_TYPE_AS4) - decode_rd_as4 (pnt + 2, &rd_as); - else if (type == RD_TYPE_IP) - decode_rd_ip (pnt + 2, &rd_ip); + u_char *pnt; + + pnt = rn->p.u.val; + + /* Decode RD type. */ + type = decode_rd_type(pnt); + /* Decode RD value. */ + if (type == RD_TYPE_AS) + decode_rd_as(pnt + 2, + &rd_as); + else if (type == RD_TYPE_AS4) + decode_rd_as4(pnt + 2, + &rd_as); + else if (type == RD_TYPE_IP) + decode_rd_ip(pnt + 2, + &rd_ip); #if ENABLE_BGP_VNC - else if (type == RD_TYPE_VNC_ETH) - decode_rd_vnc_eth (pnt, &rd_vnc_eth); + else if (type + == RD_TYPE_VNC_ETH) + decode_rd_vnc_eth( + pnt, + &rd_vnc_eth); #endif - if (use_json) - { - char buffer[BUFSIZ]; - if (type == RD_TYPE_AS || type == RD_TYPE_AS4) - sprintf (buffer, "%u:%d", rd_as.as, rd_as.val); - else if (type == RD_TYPE_IP) - sprintf (buffer, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val); - json_object_string_add(json_nroute, "routeDistinguisher", buffer); - } - else - { - vty_out (vty, "Route Distinguisher: "); - - if (type == RD_TYPE_AS || type == RD_TYPE_AS4) - vty_out (vty, "%u:%d", rd_as.as, rd_as.val); - else if (type == RD_TYPE_IP) - vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val); + if (use_json) { + char buffer[BUFSIZ]; + if (type == RD_TYPE_AS + || type == RD_TYPE_AS4) + sprintf(buffer, + "%u:%d", + rd_as.as, + rd_as.val); + else if (type + == RD_TYPE_IP) + sprintf(buffer, + "%s:%d", + inet_ntoa( + rd_ip.ip), + rd_ip.val); + json_object_string_add( + json_nroute, + "routeDistinguisher", + buffer); + } else { + vty_out(vty, + "Route Distinguisher: "); + + if (type == RD_TYPE_AS + || type == RD_TYPE_AS4) + vty_out(vty, + "%u:%d", + rd_as.as, + rd_as.val); + else if (type + == RD_TYPE_IP) + vty_out(vty, + "%s:%d", + inet_ntoa( + rd_ip.ip), + rd_ip.val); #if ENABLE_BGP_VNC - else if (type == RD_TYPE_VNC_ETH) - vty_out (vty, "%u:%02x:%02x:%02x:%02x:%02x:%02x", - rd_vnc_eth.local_nve_id, - rd_vnc_eth.macaddr.octet[0], - rd_vnc_eth.macaddr.octet[1], - rd_vnc_eth.macaddr.octet[2], - rd_vnc_eth.macaddr.octet[3], - rd_vnc_eth.macaddr.octet[4], - rd_vnc_eth.macaddr.octet[5]); + else if ( + type + == RD_TYPE_VNC_ETH) + vty_out(vty, + "%u:%02x:%02x:%02x:%02x:%02x:%02x", + rd_vnc_eth + .local_nve_id, + rd_vnc_eth + .macaddr + .octet[0], + rd_vnc_eth + .macaddr + .octet[1], + rd_vnc_eth + .macaddr + .octet[2], + rd_vnc_eth + .macaddr + .octet[3], + rd_vnc_eth + .macaddr + .octet[4], + rd_vnc_eth + .macaddr + .octet[5]); #endif - vty_out (vty, "\n"); - } - rd_header = 0; - } - if (tags) - route_vty_out_tag (vty, &rm->p, ri, 0, SAFI_MPLS_VPN, json_array); - else - route_vty_out (vty, &rm->p, ri, 0, SAFI_MPLS_VPN, json_array); - output_count++; - } - - if (use_json) - { - struct prefix *p; - char buf_a[BUFSIZ]; - char buf_b[BUFSIZ]; - p = &rm->p; - sprintf(buf_a, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf_b, BUFSIZ), p->prefixlen); - json_object_object_add(json_mroute, buf_a, json_array); - } - } - - if (use_json) - { - struct prefix *p; - char buf_a[BUFSIZ]; - char buf_b[BUFSIZ]; - p = &rn->p; - sprintf(buf_a, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf_b, BUFSIZ), p->prefixlen); - json_object_object_add(json_nroute, buf_a, json_mroute); - } - } - } - - if (use_json) - { - json_object_object_add(json, "routes", json_nroute); - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - { - if (output_count == 0) - vty_out (vty, "No prefixes displayed, %ld exist\n", total_count); - else - vty_out (vty, "\nDisplayed %ld routes and %ld total paths\n", output_count, total_count); - } - - return CMD_SUCCESS; + vty_out(vty, "\n"); + } + rd_header = 0; + } + if (tags) + route_vty_out_tag(vty, &rm->p, + ri, 0, + SAFI_MPLS_VPN, + json_array); + else + route_vty_out(vty, &rm->p, ri, + 0, SAFI_MPLS_VPN, + json_array); + output_count++; + } + + if (use_json) { + struct prefix *p; + char buf_a[BUFSIZ]; + char buf_b[BUFSIZ]; + p = &rm->p; + sprintf(buf_a, "%s/%d", + inet_ntop(p->family, + &p->u.prefix, buf_b, + BUFSIZ), + p->prefixlen); + json_object_object_add( + json_mroute, buf_a, json_array); + } + } + + if (use_json) { + struct prefix *p; + char buf_a[BUFSIZ]; + char buf_b[BUFSIZ]; + p = &rn->p; + sprintf(buf_a, "%s/%d", + inet_ntop(p->family, &p->u.prefix, + buf_b, BUFSIZ), + p->prefixlen); + json_object_object_add(json_nroute, buf_a, + json_mroute); + } + } + } + + if (use_json) { + json_object_object_add(json, "routes", json_nroute); + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else { + if (output_count == 0) + vty_out(vty, "No prefixes displayed, %ld exist\n", + total_count); + else + vty_out(vty, + "\nDisplayed %ld routes and %ld total paths\n", + output_count, total_count); + } + + return CMD_SUCCESS; } DEFUN (show_bgp_ip_vpn_all_rd, @@ -570,30 +640,30 @@ DEFUN (show_bgp_ip_vpn_all_rd, "VPN Route Distinguisher\n" JSON_STR) { - int idx_rd = 5; - int ret; - struct prefix_rd prd; - afi_t afi; - int idx = 0; - - if (argv_find_and_parse_afi (argv, argc, &idx, &afi)) - { - if (argc >= 7 && argv[idx_rd]->arg) - { - ret = str2prefix_rd (argv[idx_rd]->arg, &prd); - if (! ret) - { - vty_out (vty, "%% Malformed Route Distinguisher\n"); - return CMD_WARNING; - } - return bgp_show_mpls_vpn (vty, afi, &prd, bgp_show_type_normal, NULL, 0, use_json (argc, argv)); - } - else - { - return bgp_show_mpls_vpn (vty, afi, NULL, bgp_show_type_normal, NULL, 0, use_json (argc, argv)); - } - } - return CMD_SUCCESS; + int idx_rd = 5; + int ret; + struct prefix_rd prd; + afi_t afi; + int idx = 0; + + if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) { + if (argc >= 7 && argv[idx_rd]->arg) { + ret = str2prefix_rd(argv[idx_rd]->arg, &prd); + if (!ret) { + vty_out(vty, + "%% Malformed Route Distinguisher\n"); + return CMD_WARNING; + } + return bgp_show_mpls_vpn(vty, afi, &prd, + bgp_show_type_normal, NULL, 0, + use_json(argc, argv)); + } else { + return bgp_show_mpls_vpn(vty, afi, NULL, + bgp_show_type_normal, NULL, 0, + use_json(argc, argv)); + } + } + return CMD_SUCCESS; } DEFUN (show_ip_bgp_vpn_rd, @@ -607,24 +677,23 @@ DEFUN (show_ip_bgp_vpn_rd, "Display information for a route distinguisher\n" "VPN Route Distinguisher\n") { - int idx_ext_community = argc-1; - int ret; - struct prefix_rd prd; - afi_t afi; - int idx = 0; - - if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi)) - { - ret = str2prefix_rd (argv[idx_ext_community]->arg, &prd); - if (! ret) - { - vty_out (vty, "%% Malformed Route Distinguisher\n"); - return CMD_WARNING; - } - return bgp_show_mpls_vpn (vty, afi, &prd, bgp_show_type_normal, NULL, 0, 0); - } - return CMD_SUCCESS; - } + int idx_ext_community = argc - 1; + int ret; + struct prefix_rd prd; + afi_t afi; + int idx = 0; + + if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) { + ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd); + if (!ret) { + vty_out(vty, "%% Malformed Route Distinguisher\n"); + return CMD_WARNING; + } + return bgp_show_mpls_vpn(vty, afi, &prd, bgp_show_type_normal, + NULL, 0, 0); + } + return CMD_SUCCESS; +} #ifdef KEEP_OLD_VPN_COMMANDS DEFUN (show_ip_bgp_vpn_all, @@ -635,12 +704,13 @@ DEFUN (show_ip_bgp_vpn_all, BGP_STR BGP_VPNVX_HELP_STR) { - afi_t afi; - int idx = 0; + afi_t afi; + int idx = 0; - if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi)) - return bgp_show_mpls_vpn (vty, afi, NULL, bgp_show_type_normal, NULL, 0, 0); - return CMD_SUCCESS; + if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) + return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal, + NULL, 0, 0); + return CMD_SUCCESS; } DEFUN (show_ip_bgp_vpn_all_tags, @@ -653,12 +723,13 @@ DEFUN (show_ip_bgp_vpn_all_tags, "Display information about all VPNv4/VPNV6 NLRIs\n" "Display BGP tags for prefixes\n") { - afi_t afi; - int idx = 0; + afi_t afi; + int idx = 0; - if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi)) - return bgp_show_mpls_vpn (vty, afi, NULL, bgp_show_type_normal, NULL, 1, 0); - return CMD_SUCCESS; + if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) + return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal, + NULL, 1, 0); + return CMD_SUCCESS; } DEFUN (show_ip_bgp_vpn_rd_tags, @@ -672,23 +743,22 @@ DEFUN (show_ip_bgp_vpn_rd_tags, "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n") { - int idx_ext_community = 5; - int ret; - struct prefix_rd prd; - afi_t afi; - int idx = 0; - - if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi)) - { - ret = str2prefix_rd (argv[idx_ext_community]->arg, &prd); - if (! ret) - { - vty_out (vty, "%% Malformed Route Distinguisher\n"); - return CMD_WARNING; - } - return bgp_show_mpls_vpn (vty, afi, &prd, bgp_show_type_normal, NULL, 1, 0); - } - return CMD_SUCCESS; + int idx_ext_community = 5; + int ret; + struct prefix_rd prd; + afi_t afi; + int idx = 0; + + if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) { + ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd); + if (!ret) { + vty_out(vty, "%% Malformed Route Distinguisher\n"); + return CMD_WARNING; + } + return bgp_show_mpls_vpn(vty, afi, &prd, bgp_show_type_normal, + NULL, 1, 0); + } + return CMD_SUCCESS; } DEFUN (show_ip_bgp_vpn_all_neighbor_routes, @@ -704,51 +774,52 @@ DEFUN (show_ip_bgp_vpn_all_neighbor_routes, "Display routes learned from neighbor\n" JSON_STR) { - int idx_ipv4 = 6; - union sockunion su; - struct peer *peer; - int ret; - u_char uj = use_json(argc, argv); - afi_t afi; - int idx = 0; - - if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi)) - { - ret = str2sockunion (argv[idx_ipv4]->arg, &su); - if (ret < 0) - { - if (uj) - { - json_object *json_no = NULL; - json_no = json_object_new_object(); - json_object_string_add(json_no, "warning", "Malformed address"); - vty_out (vty, "%s\n", json_object_to_json_string(json_no)); - json_object_free(json_no); - } - else - vty_out (vty, "Malformed address: %s\n", argv[idx_ipv4]->arg); - return CMD_WARNING; - } - - peer = peer_lookup (NULL, &su); - if (! peer || ! peer->afc[afi][SAFI_MPLS_VPN]) - { - if (uj) - { - json_object *json_no = NULL; - json_no = json_object_new_object(); - json_object_string_add(json_no, "warning", "No such neighbor or address family"); - vty_out (vty, "%s\n", json_object_to_json_string(json_no)); - json_object_free(json_no); - } - else - vty_out (vty, "%% No such neighbor or address family\n"); - return CMD_WARNING; - } - - return bgp_show_mpls_vpn (vty, afi, NULL, bgp_show_type_neighbor, &su, 0, uj); - } - return CMD_SUCCESS; + int idx_ipv4 = 6; + union sockunion su; + struct peer *peer; + int ret; + u_char uj = use_json(argc, argv); + afi_t afi; + int idx = 0; + + if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) { + ret = str2sockunion(argv[idx_ipv4]->arg, &su); + if (ret < 0) { + if (uj) { + json_object *json_no = NULL; + json_no = json_object_new_object(); + json_object_string_add(json_no, "warning", + "Malformed address"); + vty_out(vty, "%s\n", + json_object_to_json_string(json_no)); + json_object_free(json_no); + } else + vty_out(vty, "Malformed address: %s\n", + argv[idx_ipv4]->arg); + return CMD_WARNING; + } + + peer = peer_lookup(NULL, &su); + if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) { + if (uj) { + json_object *json_no = NULL; + json_no = json_object_new_object(); + json_object_string_add( + json_no, "warning", + "No such neighbor or address family"); + vty_out(vty, "%s\n", + json_object_to_json_string(json_no)); + json_object_free(json_no); + } else + vty_out(vty, + "%% No such neighbor or address family\n"); + return CMD_WARNING; + } + + return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_neighbor, + &su, 0, uj); + } + return CMD_SUCCESS; } DEFUN (show_ip_bgp_vpn_rd_neighbor_routes, @@ -765,70 +836,71 @@ DEFUN (show_ip_bgp_vpn_rd_neighbor_routes, "Display routes learned from neighbor\n" JSON_STR) { - int idx_ext_community = 5; - int idx_ipv4 = 7; - int ret; - union sockunion su; - struct peer *peer; - struct prefix_rd prd; - u_char uj = use_json(argc, argv); - afi_t afi; - int idx = 0; - - if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi)) - { - ret = str2prefix_rd (argv[idx_ext_community]->arg, &prd); - if (! ret) - { - if (uj) - { - json_object *json_no = NULL; - json_no = json_object_new_object(); - json_object_string_add(json_no, "warning", "Malformed Route Distinguisher"); - vty_out (vty, "%s\n", json_object_to_json_string(json_no)); - json_object_free(json_no); - } - else - vty_out (vty, "%% Malformed Route Distinguisher\n"); - return CMD_WARNING; - } - - ret = str2sockunion (argv[idx_ipv4]->arg, &su); - if (ret < 0) - { - if (uj) - { - json_object *json_no = NULL; - json_no = json_object_new_object(); - json_object_string_add(json_no, "warning", "Malformed address"); - vty_out (vty, "%s\n", json_object_to_json_string(json_no)); - json_object_free(json_no); - } - else - vty_out (vty, "Malformed address: %s\n", - argv[idx_ext_community]->arg); - return CMD_WARNING; - } - - peer = peer_lookup (NULL, &su); - if (! peer || ! peer->afc[afi][SAFI_MPLS_VPN]) - { - if (uj) - { - json_object *json_no = NULL; - json_no = json_object_new_object(); - json_object_string_add(json_no, "warning", "No such neighbor or address family"); - vty_out (vty, "%s\n", json_object_to_json_string(json_no)); - json_object_free(json_no); - } - else - vty_out (vty, "%% No such neighbor or address family\n"); - return CMD_WARNING; - } - - return bgp_show_mpls_vpn (vty, afi, &prd, bgp_show_type_neighbor, &su, 0, uj); - } - return CMD_SUCCESS; + int idx_ext_community = 5; + int idx_ipv4 = 7; + int ret; + union sockunion su; + struct peer *peer; + struct prefix_rd prd; + u_char uj = use_json(argc, argv); + afi_t afi; + int idx = 0; + + if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) { + ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd); + if (!ret) { + if (uj) { + json_object *json_no = NULL; + json_no = json_object_new_object(); + json_object_string_add( + json_no, "warning", + "Malformed Route Distinguisher"); + vty_out(vty, "%s\n", + json_object_to_json_string(json_no)); + json_object_free(json_no); + } else + vty_out(vty, + "%% Malformed Route Distinguisher\n"); + return CMD_WARNING; + } + + ret = str2sockunion(argv[idx_ipv4]->arg, &su); + if (ret < 0) { + if (uj) { + json_object *json_no = NULL; + json_no = json_object_new_object(); + json_object_string_add(json_no, "warning", + "Malformed address"); + vty_out(vty, "%s\n", + json_object_to_json_string(json_no)); + json_object_free(json_no); + } else + vty_out(vty, "Malformed address: %s\n", + argv[idx_ext_community]->arg); + return CMD_WARNING; + } + + peer = peer_lookup(NULL, &su); + if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) { + if (uj) { + json_object *json_no = NULL; + json_no = json_object_new_object(); + json_object_string_add( + json_no, "warning", + "No such neighbor or address family"); + vty_out(vty, "%s\n", + json_object_to_json_string(json_no)); + json_object_free(json_no); + } else + vty_out(vty, + "%% No such neighbor or address family\n"); + return CMD_WARNING; + } + + return bgp_show_mpls_vpn(vty, afi, &prd, bgp_show_type_neighbor, + &su, 0, uj); + } + return CMD_SUCCESS; } DEFUN (show_ip_bgp_vpn_all_neighbor_advertised_routes, @@ -844,49 +916,50 @@ DEFUN (show_ip_bgp_vpn_all_neighbor_advertised_routes, "Display the routes advertised to a BGP neighbor\n" JSON_STR) { - int idx_ipv4 = 6; - int ret; - struct peer *peer; - union sockunion su; - u_char uj = use_json(argc, argv); - afi_t afi; - int idx = 0; - - if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi)) - { - ret = str2sockunion (argv[idx_ipv4]->arg, &su); - if (ret < 0) - { - if (uj) - { - json_object *json_no = NULL; - json_no = json_object_new_object(); - json_object_string_add(json_no, "warning", "Malformed address"); - vty_out (vty, "%s\n", json_object_to_json_string(json_no)); - json_object_free(json_no); - } - else - vty_out (vty, "Malformed address: %s\n", argv[idx_ipv4]->arg); - return CMD_WARNING; - } - peer = peer_lookup (NULL, &su); - if (! peer || ! peer->afc[afi][SAFI_MPLS_VPN]) - { - if (uj) - { - json_object *json_no = NULL; - json_no = json_object_new_object(); - json_object_string_add(json_no, "warning", "No such neighbor or address family"); - vty_out (vty, "%s\n", json_object_to_json_string(json_no)); - json_object_free(json_no); - } - else - vty_out (vty, "%% No such neighbor or address family\n"); - return CMD_WARNING; - } - return show_adj_route_vpn (vty, peer, NULL, AFI_IP, SAFI_MPLS_VPN, uj); - } - return CMD_SUCCESS; + int idx_ipv4 = 6; + int ret; + struct peer *peer; + union sockunion su; + u_char uj = use_json(argc, argv); + afi_t afi; + int idx = 0; + + if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) { + ret = str2sockunion(argv[idx_ipv4]->arg, &su); + if (ret < 0) { + if (uj) { + json_object *json_no = NULL; + json_no = json_object_new_object(); + json_object_string_add(json_no, "warning", + "Malformed address"); + vty_out(vty, "%s\n", + json_object_to_json_string(json_no)); + json_object_free(json_no); + } else + vty_out(vty, "Malformed address: %s\n", + argv[idx_ipv4]->arg); + return CMD_WARNING; + } + peer = peer_lookup(NULL, &su); + if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) { + if (uj) { + json_object *json_no = NULL; + json_no = json_object_new_object(); + json_object_string_add( + json_no, "warning", + "No such neighbor or address family"); + vty_out(vty, "%s\n", + json_object_to_json_string(json_no)); + json_object_free(json_no); + } else + vty_out(vty, + "%% No such neighbor or address family\n"); + return CMD_WARNING; + } + return show_adj_route_vpn(vty, peer, NULL, AFI_IP, + SAFI_MPLS_VPN, uj); + } + return CMD_SUCCESS; } DEFUN (show_ip_bgp_vpn_rd_neighbor_advertised_routes, @@ -903,91 +976,93 @@ DEFUN (show_ip_bgp_vpn_rd_neighbor_advertised_routes, "Display the routes advertised to a BGP neighbor\n" JSON_STR) { - int idx_ext_community = 5; - int idx_ipv4 = 7; - int ret; - struct peer *peer; - struct prefix_rd prd; - union sockunion su; - u_char uj = use_json(argc, argv); - afi_t afi; - int idx = 0; - - if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi)) - { - ret = str2sockunion (argv[idx_ipv4]->arg, &su); - if (ret < 0) - { - if (uj) - { - json_object *json_no = NULL; - json_no = json_object_new_object(); - json_object_string_add(json_no, "warning", "Malformed address"); - vty_out (vty, "%s\n", json_object_to_json_string(json_no)); - json_object_free(json_no); - } - else - vty_out (vty, "Malformed address: %s\n", - argv[idx_ext_community]->arg); - return CMD_WARNING; - } - peer = peer_lookup (NULL, &su); - if (! peer || ! peer->afc[afi][SAFI_MPLS_VPN]) - { - if (uj) - { - json_object *json_no = NULL; - json_no = json_object_new_object(); - json_object_string_add(json_no, "warning", "No such neighbor or address family"); - vty_out (vty, "%s\n", json_object_to_json_string(json_no)); - json_object_free(json_no); - } - else - vty_out (vty, "%% No such neighbor or address family\n"); - return CMD_WARNING; - } - - ret = str2prefix_rd (argv[idx_ext_community]->arg, &prd); - if (! ret) - { - if (uj) - { - json_object *json_no = NULL; - json_no = json_object_new_object(); - json_object_string_add(json_no, "warning", "Malformed Route Distinguisher"); - vty_out (vty, "%s\n", json_object_to_json_string(json_no)); - json_object_free(json_no); - } - else - vty_out (vty, "%% Malformed Route Distinguisher\n"); - return CMD_WARNING; - } - - return show_adj_route_vpn (vty, peer, &prd, AFI_IP, SAFI_MPLS_VPN, uj); - } - return CMD_SUCCESS; + int idx_ext_community = 5; + int idx_ipv4 = 7; + int ret; + struct peer *peer; + struct prefix_rd prd; + union sockunion su; + u_char uj = use_json(argc, argv); + afi_t afi; + int idx = 0; + + if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) { + ret = str2sockunion(argv[idx_ipv4]->arg, &su); + if (ret < 0) { + if (uj) { + json_object *json_no = NULL; + json_no = json_object_new_object(); + json_object_string_add(json_no, "warning", + "Malformed address"); + vty_out(vty, "%s\n", + json_object_to_json_string(json_no)); + json_object_free(json_no); + } else + vty_out(vty, "Malformed address: %s\n", + argv[idx_ext_community]->arg); + return CMD_WARNING; + } + peer = peer_lookup(NULL, &su); + if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) { + if (uj) { + json_object *json_no = NULL; + json_no = json_object_new_object(); + json_object_string_add( + json_no, "warning", + "No such neighbor or address family"); + vty_out(vty, "%s\n", + json_object_to_json_string(json_no)); + json_object_free(json_no); + } else + vty_out(vty, + "%% No such neighbor or address family\n"); + return CMD_WARNING; + } + + ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd); + if (!ret) { + if (uj) { + json_object *json_no = NULL; + json_no = json_object_new_object(); + json_object_string_add( + json_no, "warning", + "Malformed Route Distinguisher"); + vty_out(vty, "%s\n", + json_object_to_json_string(json_no)); + json_object_free(json_no); + } else + vty_out(vty, + "%% Malformed Route Distinguisher\n"); + return CMD_WARNING; + } + + return show_adj_route_vpn(vty, peer, &prd, AFI_IP, + SAFI_MPLS_VPN, uj); + } + return CMD_SUCCESS; } #endif /* KEEP_OLD_VPN_COMMANDS */ -void -bgp_mplsvpn_init (void) +void bgp_mplsvpn_init(void) { - install_element (BGP_VPNV4_NODE, &vpnv4_network_cmd); - install_element (BGP_VPNV4_NODE, &vpnv4_network_route_map_cmd); - install_element (BGP_VPNV4_NODE, &no_vpnv4_network_cmd); + install_element(BGP_VPNV4_NODE, &vpnv4_network_cmd); + install_element(BGP_VPNV4_NODE, &vpnv4_network_route_map_cmd); + install_element(BGP_VPNV4_NODE, &no_vpnv4_network_cmd); - install_element (BGP_VPNV6_NODE, &vpnv6_network_cmd); - install_element (BGP_VPNV6_NODE, &no_vpnv6_network_cmd); + install_element(BGP_VPNV6_NODE, &vpnv6_network_cmd); + install_element(BGP_VPNV6_NODE, &no_vpnv6_network_cmd); - install_element (VIEW_NODE, &show_bgp_ip_vpn_all_rd_cmd); - install_element (VIEW_NODE, &show_ip_bgp_vpn_rd_cmd); + install_element(VIEW_NODE, &show_bgp_ip_vpn_all_rd_cmd); + install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_cmd); #ifdef KEEP_OLD_VPN_COMMANDS - install_element (VIEW_NODE, &show_ip_bgp_vpn_all_cmd); - install_element (VIEW_NODE, &show_ip_bgp_vpn_all_tags_cmd); - install_element (VIEW_NODE, &show_ip_bgp_vpn_rd_tags_cmd); - install_element (VIEW_NODE, &show_ip_bgp_vpn_all_neighbor_routes_cmd); - install_element (VIEW_NODE, &show_ip_bgp_vpn_rd_neighbor_routes_cmd); - install_element (VIEW_NODE, &show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd); - install_element (VIEW_NODE, &show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd); + install_element(VIEW_NODE, &show_ip_bgp_vpn_all_cmd); + install_element(VIEW_NODE, &show_ip_bgp_vpn_all_tags_cmd); + install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_tags_cmd); + install_element(VIEW_NODE, &show_ip_bgp_vpn_all_neighbor_routes_cmd); + install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_neighbor_routes_cmd); + install_element(VIEW_NODE, + &show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd); + install_element(VIEW_NODE, + &show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd); #endif /* KEEP_OLD_VPN_COMMANDS */ } diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index 8d4f5f806..3b37aadbf 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -25,55 +25,54 @@ #include "bgpd/bgp_rd.h" #ifdef MPLS_LABEL_MAX -# undef MPLS_LABEL_MAX +#undef MPLS_LABEL_MAX #endif typedef enum { - MPLS_LABEL_IPV4_EXPLICIT_NULL = 0, /* [RFC3032] */ - MPLS_LABEL_ROUTER_ALERT = 1, /* [RFC3032] */ - MPLS_LABEL_IPV6_EXPLICIT_NULL = 2, /* [RFC3032] */ - MPLS_LABEL_IMPLICIT_NULL = 3, /* [RFC3032] */ - MPLS_LABEL_UNASSIGNED4 = 4, - MPLS_LABEL_UNASSIGNED5 = 5, - MPLS_LABEL_UNASSIGNED6 = 6, - MPLS_LABEL_ELI = 7, /* Entropy Indicator [RFC6790] */ - MPLS_LABEL_UNASSIGNED8 = 8, - MPLS_LABEL_UNASSIGNED9 = 9, - MPLS_LABEL_UNASSIGNED10 = 10, - MPLS_LABEL_UNASSIGNED11 = 11, - MPLS_LABEL_GAL = 13, /* [RFC5586] */ - MPLS_LABEL_OAM_ALERT = 14, /* [RFC3429] */ - MPLS_LABEL_EXTENSION = 15, /* [RFC7274] */ - MPLS_LABEL_MAX = 1048575, - MPLS_LABEL_ILLEGAL = 0xFFFFFFFF /* for internal use only */ + MPLS_LABEL_IPV4_EXPLICIT_NULL = 0, /* [RFC3032] */ + MPLS_LABEL_ROUTER_ALERT = 1, /* [RFC3032] */ + MPLS_LABEL_IPV6_EXPLICIT_NULL = 2, /* [RFC3032] */ + MPLS_LABEL_IMPLICIT_NULL = 3, /* [RFC3032] */ + MPLS_LABEL_UNASSIGNED4 = 4, + MPLS_LABEL_UNASSIGNED5 = 5, + MPLS_LABEL_UNASSIGNED6 = 6, + MPLS_LABEL_ELI = 7, /* Entropy Indicator [RFC6790] */ + MPLS_LABEL_UNASSIGNED8 = 8, + MPLS_LABEL_UNASSIGNED9 = 9, + MPLS_LABEL_UNASSIGNED10 = 10, + MPLS_LABEL_UNASSIGNED11 = 11, + MPLS_LABEL_GAL = 13, /* [RFC5586] */ + MPLS_LABEL_OAM_ALERT = 14, /* [RFC3429] */ + MPLS_LABEL_EXTENSION = 15, /* [RFC7274] */ + MPLS_LABEL_MAX = 1048575, + MPLS_LABEL_ILLEGAL = 0xFFFFFFFF /* for internal use only */ } mpls_special_label_t; -#define MPLS_LABEL_IS_SPECIAL(label) \ - ((label) <= MPLS_LABEL_EXTENSION) -#define MPLS_LABEL_IS_NULL(label) \ - ((label) == MPLS_LABEL_IPV4_EXPLICIT_NULL || \ - (label) == MPLS_LABEL_IPV6_EXPLICIT_NULL || \ - (label) == MPLS_LABEL_IMPLICIT_NULL) +#define MPLS_LABEL_IS_SPECIAL(label) ((label) <= MPLS_LABEL_EXTENSION) +#define MPLS_LABEL_IS_NULL(label) \ + ((label) == MPLS_LABEL_IPV4_EXPLICIT_NULL \ + || (label) == MPLS_LABEL_IPV6_EXPLICIT_NULL \ + || (label) == MPLS_LABEL_IMPLICIT_NULL) -#define BGP_VPNVX_HELP_STR \ - "Address Family\n" \ - "Address Family\n" +#define BGP_VPNVX_HELP_STR \ + "Address Family\n" \ + "Address Family\n" -#define V4_HEADER \ - " Network Next Hop Metric LocPrf Weight Path\n" -#define V4_HEADER_TAG \ - " Network Next Hop In tag/Out tag\n" -#define V4_HEADER_OVERLAY \ - " Network Next Hop EthTag Overlay Index RouterMac\n" +#define V4_HEADER \ + " Network Next Hop Metric LocPrf Weight Path\n" +#define V4_HEADER_TAG " Network Next Hop In tag/Out tag\n" +#define V4_HEADER_OVERLAY \ + " Network Next Hop EthTag Overlay Index RouterMac\n" -extern void bgp_mplsvpn_init (void); -extern int bgp_nlri_parse_vpn (struct peer *, struct attr *, struct bgp_nlri *); -extern u_int32_t decode_label (mpls_label_t *); +extern void bgp_mplsvpn_init(void); +extern int bgp_nlri_parse_vpn(struct peer *, struct attr *, struct bgp_nlri *); +extern u_int32_t decode_label(mpls_label_t *); extern void encode_label(mpls_label_t, mpls_label_t *); -extern int -argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc, int *index, afi_t *afi); -extern int bgp_show_mpls_vpn (struct vty *vty, afi_t afi, struct prefix_rd *prd, - enum bgp_show_type type, void *output_arg, int tags, u_char use_json); +extern int argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc, + int *index, afi_t *afi); +extern int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd, + enum bgp_show_type type, void *output_arg, + int tags, u_char use_json); #endif /* _QUAGGA_BGP_MPLSVPN_H */ diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 70da5e176..70299ea45 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -47,156 +47,149 @@ extern struct zebra_privs_t bgpd_privs; static int bgp_bind(struct peer *); /* BGP listening socket. */ -struct bgp_listener -{ - int fd; - union sockunion su; - struct thread *thread; +struct bgp_listener { + int fd; + union sockunion su; + struct thread *thread; }; /* * Set MD5 key for the socket, for the given IPv4 peer address. * If the password is NULL or zero-length, the option will be disabled. */ -static int -bgp_md5_set_socket (int socket, union sockunion *su, const char *password) +static int bgp_md5_set_socket(int socket, union sockunion *su, + const char *password) { - int ret = -1; - int en = ENOSYS; + int ret = -1; + int en = ENOSYS; #if HAVE_DECL_TCP_MD5SIG - union sockunion su2; + union sockunion su2; #endif /* HAVE_TCP_MD5SIG */ - - assert (socket >= 0); - -#if HAVE_DECL_TCP_MD5SIG - /* Ensure there is no extraneous port information. */ - memcpy (&su2, su, sizeof (union sockunion)); - if (su2.sa.sa_family == AF_INET) - su2.sin.sin_port = 0; - else - su2.sin6.sin6_port = 0; - ret = sockopt_tcp_signature (socket, &su2, password); - en = errno; + + assert(socket >= 0); + +#if HAVE_DECL_TCP_MD5SIG + /* Ensure there is no extraneous port information. */ + memcpy(&su2, su, sizeof(union sockunion)); + if (su2.sa.sa_family == AF_INET) + su2.sin.sin_port = 0; + else + su2.sin6.sin6_port = 0; + ret = sockopt_tcp_signature(socket, &su2, password); + en = errno; #endif /* HAVE_TCP_MD5SIG */ - - if (ret < 0) - zlog_warn ("can't set TCP_MD5SIG option on socket %d: %s", socket, safe_strerror (en)); - return ret; + if (ret < 0) + zlog_warn("can't set TCP_MD5SIG option on socket %d: %s", + socket, safe_strerror(en)); + + return ret; } /* Helper for bgp_connect */ -static int -bgp_md5_set_connect (int socket, union sockunion *su, const char *password) +static int bgp_md5_set_connect(int socket, union sockunion *su, + const char *password) { - int ret = -1; - -#if HAVE_DECL_TCP_MD5SIG - if ( bgpd_privs.change (ZPRIVS_RAISE) ) - { - zlog_err ("%s: could not raise privs", __func__); - return ret; - } - - ret = bgp_md5_set_socket (socket, su, password); - - if (bgpd_privs.change (ZPRIVS_LOWER) ) - zlog_err ("%s: could not lower privs", __func__); + int ret = -1; + +#if HAVE_DECL_TCP_MD5SIG + if (bgpd_privs.change(ZPRIVS_RAISE)) { + zlog_err("%s: could not raise privs", __func__); + return ret; + } + + ret = bgp_md5_set_socket(socket, su, password); + + if (bgpd_privs.change(ZPRIVS_LOWER)) + zlog_err("%s: could not lower privs", __func__); #endif /* HAVE_TCP_MD5SIG */ - - return ret; + + return ret; } -static int -bgp_md5_set_password (struct peer *peer, const char *password) +static int bgp_md5_set_password(struct peer *peer, const char *password) { - struct listnode *node; - int ret = 0; - struct bgp_listener *listener; - - if ( bgpd_privs.change (ZPRIVS_RAISE) ) - { - zlog_err ("%s: could not raise privs", __func__); - return -1; - } - - /* Set or unset the password on the listen socket(s). Outbound connections - * are taken care of in bgp_connect() below. - */ - for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, listener)) - if (listener->su.sa.sa_family == peer->su.sa.sa_family) - { - ret = bgp_md5_set_socket (listener->fd, &peer->su, password); - break; - } - - if (bgpd_privs.change (ZPRIVS_LOWER) ) - zlog_err ("%s: could not lower privs", __func__); - - return ret; + struct listnode *node; + int ret = 0; + struct bgp_listener *listener; + + if (bgpd_privs.change(ZPRIVS_RAISE)) { + zlog_err("%s: could not raise privs", __func__); + return -1; + } + + /* Set or unset the password on the listen socket(s). Outbound + * connections + * are taken care of in bgp_connect() below. + */ + for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, listener)) + if (listener->su.sa.sa_family == peer->su.sa.sa_family) { + ret = bgp_md5_set_socket(listener->fd, &peer->su, + password); + break; + } + + if (bgpd_privs.change(ZPRIVS_LOWER)) + zlog_err("%s: could not lower privs", __func__); + + return ret; } -int -bgp_md5_set (struct peer *peer) +int bgp_md5_set(struct peer *peer) { - /* Set the password from listen socket. */ - return bgp_md5_set_password (peer, peer->password); + /* Set the password from listen socket. */ + return bgp_md5_set_password(peer, peer->password); } -int -bgp_md5_unset (struct peer *peer) +int bgp_md5_unset(struct peer *peer) { - /* Unset the password from listen socket. */ - return bgp_md5_set_password (peer, NULL); + /* Unset the password from listen socket. */ + return bgp_md5_set_password(peer, NULL); } -int -bgp_set_socket_ttl (struct peer *peer, int bgp_sock) +int bgp_set_socket_ttl(struct peer *peer, int bgp_sock) { - char buf[INET_ADDRSTRLEN]; - int ret = 0; - - /* In case of peer is EBGP, we should set TTL for this connection. */ - if (!peer->gtsm_hops && (peer_sort (peer) == BGP_PEER_EBGP)) - { - ret = sockopt_ttl (peer->su.sa.sa_family, bgp_sock, peer->ttl); - if (ret) - { - zlog_err ("%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d", - __func__, - inet_ntop (AF_INET, &peer->remote_id, buf, sizeof(buf)), - errno); - return ret; - } - } - else if (peer->gtsm_hops) - { - /* On Linux, setting minttl without setting ttl seems to mess with the - outgoing ttl. Therefore setting both. - */ - ret = sockopt_ttl (peer->su.sa.sa_family, bgp_sock, MAXTTL); - if (ret) - { - zlog_err ("%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d", - __func__, - inet_ntop (AF_INET, &peer->remote_id, buf, sizeof(buf)), - errno); - return ret; - } - ret = sockopt_minttl (peer->su.sa.sa_family, bgp_sock, - MAXTTL + 1 - peer->gtsm_hops); - if (ret) - { - zlog_err ("%s: Can't set MinTTL on peer (rtrid %s) socket, err = %d", - __func__, - inet_ntop (AF_INET, &peer->remote_id, buf, sizeof(buf)), - errno); - return ret; - } - } - - return ret; + char buf[INET_ADDRSTRLEN]; + int ret = 0; + + /* In case of peer is EBGP, we should set TTL for this connection. */ + if (!peer->gtsm_hops && (peer_sort(peer) == BGP_PEER_EBGP)) { + ret = sockopt_ttl(peer->su.sa.sa_family, bgp_sock, peer->ttl); + if (ret) { + zlog_err( + "%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d", + __func__, inet_ntop(AF_INET, &peer->remote_id, + buf, sizeof(buf)), + errno); + return ret; + } + } else if (peer->gtsm_hops) { + /* On Linux, setting minttl without setting ttl seems to mess + with the + outgoing ttl. Therefore setting both. + */ + ret = sockopt_ttl(peer->su.sa.sa_family, bgp_sock, MAXTTL); + if (ret) { + zlog_err( + "%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d", + __func__, inet_ntop(AF_INET, &peer->remote_id, + buf, sizeof(buf)), + errno); + return ret; + } + ret = sockopt_minttl(peer->su.sa.sa_family, bgp_sock, + MAXTTL + 1 - peer->gtsm_hops); + if (ret) { + zlog_err( + "%s: Can't set MinTTL on peer (rtrid %s) socket, err = %d", + __func__, inet_ntop(AF_INET, &peer->remote_id, + buf, sizeof(buf)), + errno); + return ret; + } + } + + return ret; } /* @@ -206,585 +199,566 @@ bgp_set_socket_ttl (struct peer *peer, int bgp_sock) * which the incoming connection is bound to. This could either be a VRF * or it could be an interface, which in turn determines the VRF. */ -static int -bgp_get_instance_for_inc_conn (int sock, struct bgp **bgp_inst) +static int bgp_get_instance_for_inc_conn(int sock, struct bgp **bgp_inst) { #ifndef SO_BINDTODEVICE - /* only Linux has SO_BINDTODEVICE, but we're in Linux-specific code here - * anyway since the assumption is that the interface name returned by - * getsockopt() is useful in identifying the VRF, particularly with Linux's - * VRF l3master device. The whole mechanism is specific to Linux, so... - * when other platforms add VRF support, this will need handling here as - * well. (or, some restructuring) */ - *bgp_inst = bgp_get_default (); - return !*bgp_inst; + /* only Linux has SO_BINDTODEVICE, but we're in Linux-specific code here + * anyway since the assumption is that the interface name returned by + * getsockopt() is useful in identifying the VRF, particularly with + * Linux's + * VRF l3master device. The whole mechanism is specific to Linux, so... + * when other platforms add VRF support, this will need handling here as + * well. (or, some restructuring) */ + *bgp_inst = bgp_get_default(); + return !*bgp_inst; #else - char name[VRF_NAMSIZ + 1]; - socklen_t name_len = VRF_NAMSIZ; - struct bgp *bgp; - int rc; - struct listnode *node, *nnode; - - *bgp_inst = NULL; - name[0] = '\0'; - rc = getsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, name, &name_len); - if (rc != 0) - { -#if defined (HAVE_CUMULUS) - zlog_err ("[Error] BGP SO_BINDTODEVICE get failed (%s), sock %d", - safe_strerror (errno), sock); - return -1; + char name[VRF_NAMSIZ + 1]; + socklen_t name_len = VRF_NAMSIZ; + struct bgp *bgp; + int rc; + struct listnode *node, *nnode; + + *bgp_inst = NULL; + name[0] = '\0'; + rc = getsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, name, &name_len); + if (rc != 0) { +#if defined(HAVE_CUMULUS) + zlog_err("[Error] BGP SO_BINDTODEVICE get failed (%s), sock %d", + safe_strerror(errno), sock); + return -1; #endif - } - - if (!strlen(name)) - { - *bgp_inst = bgp_get_default (); - return 0; /* default instance. */ - } - - /* First try match to instance; if that fails, check for interfaces. */ - bgp = bgp_lookup_by_name (name); - if (bgp) - { - if (!bgp->vrf_id) // unexpected - return -1; - *bgp_inst = bgp; - return 0; - } - - /* TODO - This will be optimized once interfaces move into the NS */ - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - { - struct interface *ifp; - - if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) - continue; - - ifp = if_lookup_by_name (name, bgp->vrf_id); - if (ifp) - { - *bgp_inst = bgp; - return 0; - } - } - - /* We didn't match to either an instance or an interface. */ - return -1; + } + + if (!strlen(name)) { + *bgp_inst = bgp_get_default(); + return 0; /* default instance. */ + } + + /* First try match to instance; if that fails, check for interfaces. */ + bgp = bgp_lookup_by_name(name); + if (bgp) { + if (!bgp->vrf_id) // unexpected + return -1; + *bgp_inst = bgp; + return 0; + } + + /* TODO - This will be optimized once interfaces move into the NS */ + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) { + struct interface *ifp; + + if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) + continue; + + ifp = if_lookup_by_name(name, bgp->vrf_id); + if (ifp) { + *bgp_inst = bgp; + return 0; + } + } + + /* We didn't match to either an instance or an interface. */ + return -1; #endif } /* Accept bgp connection. */ -static int -bgp_accept (struct thread *thread) +static int bgp_accept(struct thread *thread) { - int bgp_sock; - int accept_sock; - union sockunion su; - struct bgp_listener *listener = THREAD_ARG(thread); - struct peer *peer; - struct peer *peer1; - char buf[SU_ADDRSTRLEN]; - struct bgp *bgp = NULL; - - sockunion_init (&su); - - /* Register accept thread. */ - accept_sock = THREAD_FD (thread); - if (accept_sock < 0) - { - zlog_err ("accept_sock is nevative value %d", accept_sock); - return -1; - } - listener->thread = NULL; - thread_add_read(bm->master, bgp_accept, listener, accept_sock, - &listener->thread); - - /* Accept client connection. */ - bgp_sock = sockunion_accept (accept_sock, &su); - if (bgp_sock < 0) - { - zlog_err ("[Error] BGP socket accept failed (%s)", safe_strerror (errno)); - return -1; - } - set_nonblocking (bgp_sock); - - /* Obtain BGP instance this connection is meant for. */ - if (bgp_get_instance_for_inc_conn (bgp_sock, &bgp)) - { - if (bgp_debug_neighbor_events(NULL)) - zlog_debug ("[Event] Could not get instance for incoming conn from %s", - inet_sutop (&su, buf)); - close (bgp_sock); - return -1; - } - - /* Set socket send buffer size */ - setsockopt_so_sendbuf (bgp_sock, BGP_SOCKET_SNDBUF_SIZE); - - /* Check remote IP address */ - peer1 = peer_lookup (bgp, &su); - - if (! peer1) - { - peer1 = peer_lookup_dynamic_neighbor (bgp, &su); - if (peer1) - { - /* Dynamic neighbor has been created, let it proceed */ - peer1->fd = bgp_sock; - bgp_fsm_change_status(peer1, Active); - BGP_TIMER_OFF(peer1->t_start); /* created in peer_create() */ - - if (peer_active (peer1)) - BGP_EVENT_ADD (peer1, TCP_connection_open); - - return 0; - } - } - - if (! peer1) - { - if (bgp_debug_neighbor_events(NULL)) - { - zlog_debug ("[Event] %s connection rejected - not configured" - " and not valid for dynamic", - inet_sutop (&su, buf)); - } - close (bgp_sock); - return -1; - } - - if (CHECK_FLAG(peer1->flags, PEER_FLAG_SHUTDOWN)) - { - if (bgp_debug_neighbor_events(peer1)) - zlog_debug ("[Event] connection from %s rejected due to admin shutdown", - inet_sutop (&su, buf)); - close (bgp_sock); - return -1; - } - - /* - * Do not accept incoming connections in Clearing state. This can result - * in incorect state transitions - e.g., the connection goes back to - * Established and then the Clearing_Completed event is generated. Also, - * block incoming connection in Deleted state. - */ - if (peer1->status == Clearing || peer1->status == Deleted) - { - if (bgp_debug_neighbor_events(peer1)) - zlog_debug("[Event] Closing incoming conn for %s (%p) state %d", - peer1->host, peer1, peer1->status); - close (bgp_sock); - return -1; - } - - /* Check that at least one AF is activated for the peer. */ - if (!peer_active (peer1)) - { - if (bgp_debug_neighbor_events(peer1)) - zlog_debug ("%s - incoming conn rejected - no AF activated for peer", - peer1->host); - close (bgp_sock); - return -1; - } - - if (bgp_debug_neighbor_events(peer1)) - zlog_debug ("[Event] BGP connection from host %s fd %d", - inet_sutop (&su, buf), bgp_sock); - - if (peer1->doppelganger) - { - /* We have an existing connection. Kill the existing one and run - with this one. - */ - if (bgp_debug_neighbor_events(peer1)) - zlog_debug ("[Event] New active connection from peer %s, Killing" - " previous active connection", peer1->host); - peer_delete(peer1->doppelganger); - } - - if (bgp_set_socket_ttl (peer1, bgp_sock) < 0) - if (bgp_debug_neighbor_events(peer1)) - zlog_debug ("[Event] Unable to set min/max TTL on peer %s, Continuing", - peer1->host); - - peer = peer_create (&su, peer1->conf_if, peer1->bgp, peer1->local_as, - peer1->as, peer1->as_type, 0, 0, NULL); - peer->su = su; - hash_release(peer->bgp->peerhash, peer); - hash_get(peer->bgp->peerhash, peer, hash_alloc_intern); - - peer_xfer_config(peer, peer1); - UNSET_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE); - - peer->doppelganger = peer1; - peer1->doppelganger = peer; - peer->fd = bgp_sock; - bgp_bind(peer); - bgp_fsm_change_status(peer, Active); - BGP_TIMER_OFF(peer->t_start); /* created in peer_create() */ - - SET_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER); - - /* Make dummy peer until read Open packet. */ - if (peer1->status == Established && - CHECK_FLAG (peer1->sflags, PEER_STATUS_NSF_MODE)) - { - /* If we have an existing established connection with graceful restart - * capability announced with one or more address families, then drop - * existing established connection and move state to connect. - */ - peer1->last_reset = PEER_DOWN_NSF_CLOSE_SESSION; - SET_FLAG (peer1->sflags, PEER_STATUS_NSF_WAIT); - bgp_event_update(peer1, TCP_connection_closed); - } - - if (peer_active (peer)) - { - BGP_EVENT_ADD (peer, TCP_connection_open); - } - - return 0; + int bgp_sock; + int accept_sock; + union sockunion su; + struct bgp_listener *listener = THREAD_ARG(thread); + struct peer *peer; + struct peer *peer1; + char buf[SU_ADDRSTRLEN]; + struct bgp *bgp = NULL; + + sockunion_init(&su); + + /* Register accept thread. */ + accept_sock = THREAD_FD(thread); + if (accept_sock < 0) { + zlog_err("accept_sock is nevative value %d", accept_sock); + return -1; + } + listener->thread = NULL; + thread_add_read(bm->master, bgp_accept, listener, accept_sock, + &listener->thread); + + /* Accept client connection. */ + bgp_sock = sockunion_accept(accept_sock, &su); + if (bgp_sock < 0) { + zlog_err("[Error] BGP socket accept failed (%s)", + safe_strerror(errno)); + return -1; + } + set_nonblocking(bgp_sock); + + /* Obtain BGP instance this connection is meant for. */ + if (bgp_get_instance_for_inc_conn(bgp_sock, &bgp)) { + if (bgp_debug_neighbor_events(NULL)) + zlog_debug( + "[Event] Could not get instance for incoming conn from %s", + inet_sutop(&su, buf)); + close(bgp_sock); + return -1; + } + + /* Set socket send buffer size */ + setsockopt_so_sendbuf(bgp_sock, BGP_SOCKET_SNDBUF_SIZE); + + /* Check remote IP address */ + peer1 = peer_lookup(bgp, &su); + + if (!peer1) { + peer1 = peer_lookup_dynamic_neighbor(bgp, &su); + if (peer1) { + /* Dynamic neighbor has been created, let it proceed */ + peer1->fd = bgp_sock; + bgp_fsm_change_status(peer1, Active); + BGP_TIMER_OFF( + peer1->t_start); /* created in peer_create() */ + + if (peer_active(peer1)) + BGP_EVENT_ADD(peer1, TCP_connection_open); + + return 0; + } + } + + if (!peer1) { + if (bgp_debug_neighbor_events(NULL)) { + zlog_debug( + "[Event] %s connection rejected - not configured" + " and not valid for dynamic", + inet_sutop(&su, buf)); + } + close(bgp_sock); + return -1; + } + + if (CHECK_FLAG(peer1->flags, PEER_FLAG_SHUTDOWN)) { + if (bgp_debug_neighbor_events(peer1)) + zlog_debug( + "[Event] connection from %s rejected due to admin shutdown", + inet_sutop(&su, buf)); + close(bgp_sock); + return -1; + } + + /* + * Do not accept incoming connections in Clearing state. This can result + * in incorect state transitions - e.g., the connection goes back to + * Established and then the Clearing_Completed event is generated. Also, + * block incoming connection in Deleted state. + */ + if (peer1->status == Clearing || peer1->status == Deleted) { + if (bgp_debug_neighbor_events(peer1)) + zlog_debug( + "[Event] Closing incoming conn for %s (%p) state %d", + peer1->host, peer1, peer1->status); + close(bgp_sock); + return -1; + } + + /* Check that at least one AF is activated for the peer. */ + if (!peer_active(peer1)) { + if (bgp_debug_neighbor_events(peer1)) + zlog_debug( + "%s - incoming conn rejected - no AF activated for peer", + peer1->host); + close(bgp_sock); + return -1; + } + + if (bgp_debug_neighbor_events(peer1)) + zlog_debug("[Event] BGP connection from host %s fd %d", + inet_sutop(&su, buf), bgp_sock); + + if (peer1->doppelganger) { + /* We have an existing connection. Kill the existing one and run + with this one. + */ + if (bgp_debug_neighbor_events(peer1)) + zlog_debug( + "[Event] New active connection from peer %s, Killing" + " previous active connection", + peer1->host); + peer_delete(peer1->doppelganger); + } + + if (bgp_set_socket_ttl(peer1, bgp_sock) < 0) + if (bgp_debug_neighbor_events(peer1)) + zlog_debug( + "[Event] Unable to set min/max TTL on peer %s, Continuing", + peer1->host); + + peer = peer_create(&su, peer1->conf_if, peer1->bgp, peer1->local_as, + peer1->as, peer1->as_type, 0, 0, NULL); + peer->su = su; + hash_release(peer->bgp->peerhash, peer); + hash_get(peer->bgp->peerhash, peer, hash_alloc_intern); + + peer_xfer_config(peer, peer1); + UNSET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); + + peer->doppelganger = peer1; + peer1->doppelganger = peer; + peer->fd = bgp_sock; + bgp_bind(peer); + bgp_fsm_change_status(peer, Active); + BGP_TIMER_OFF(peer->t_start); /* created in peer_create() */ + + SET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER); + + /* Make dummy peer until read Open packet. */ + if (peer1->status == Established + && CHECK_FLAG(peer1->sflags, PEER_STATUS_NSF_MODE)) { + /* If we have an existing established connection with graceful + * restart + * capability announced with one or more address families, then + * drop + * existing established connection and move state to connect. + */ + peer1->last_reset = PEER_DOWN_NSF_CLOSE_SESSION; + SET_FLAG(peer1->sflags, PEER_STATUS_NSF_WAIT); + bgp_event_update(peer1, TCP_connection_closed); + } + + if (peer_active(peer)) { + BGP_EVENT_ADD(peer, TCP_connection_open); + } + + return 0; } /* BGP socket bind. */ -static int -bgp_bind (struct peer *peer) +static int bgp_bind(struct peer *peer) { #ifdef SO_BINDTODEVICE - int ret; - int myerrno; - char *name = NULL; - - /* If not bound to an interface or part of a VRF, we don't care. */ - if (!peer->bgp->vrf_id && ! peer->ifname && !peer->conf_if) - return 0; - - if (peer->su.sa.sa_family != AF_INET && - peer->su.sa.sa_family != AF_INET6) - return 0; // unexpected - - /* For IPv6 peering, interface (unnumbered or link-local with interface) - * takes precedence over VRF. For IPv4 peering, explicit interface or - * VRF are the situations to bind. - */ - if (peer->su.sa.sa_family == AF_INET6) - name = (peer->conf_if ? peer->conf_if : \ - (peer->ifname ? peer->ifname : peer->bgp->name)); - else - name = peer->ifname ? peer->ifname : peer->bgp->name; - - if (!name) - return 0; - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Binding to interface %s", peer->host, name); - - if ( bgpd_privs.change (ZPRIVS_RAISE) ) - zlog_err ("bgp_bind: could not raise privs"); - - ret = setsockopt (peer->fd, SOL_SOCKET, SO_BINDTODEVICE, - name, strlen(name)); - myerrno = errno; - - if (bgpd_privs.change (ZPRIVS_LOWER) ) - zlog_err ("bgp_bind: could not lower privs"); - - if (ret < 0) - { - if (bgp_debug_neighbor_events (peer)) - zlog_debug ("bind to interface %s failed, errno=%d", name, myerrno); - return ret; - } + int ret; + int myerrno; + char *name = NULL; + + /* If not bound to an interface or part of a VRF, we don't care. */ + if (!peer->bgp->vrf_id && !peer->ifname && !peer->conf_if) + return 0; + + if (peer->su.sa.sa_family != AF_INET + && peer->su.sa.sa_family != AF_INET6) + return 0; // unexpected + + /* For IPv6 peering, interface (unnumbered or link-local with interface) + * takes precedence over VRF. For IPv4 peering, explicit interface or + * VRF are the situations to bind. + */ + if (peer->su.sa.sa_family == AF_INET6) + name = (peer->conf_if ? peer->conf_if + : (peer->ifname ? peer->ifname + : peer->bgp->name)); + else + name = peer->ifname ? peer->ifname : peer->bgp->name; + + if (!name) + return 0; + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s Binding to interface %s", peer->host, name); + + if (bgpd_privs.change(ZPRIVS_RAISE)) + zlog_err("bgp_bind: could not raise privs"); + + ret = setsockopt(peer->fd, SOL_SOCKET, SO_BINDTODEVICE, name, + strlen(name)); + myerrno = errno; + + if (bgpd_privs.change(ZPRIVS_LOWER)) + zlog_err("bgp_bind: could not lower privs"); + + if (ret < 0) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug("bind to interface %s failed, errno=%d", + name, myerrno); + return ret; + } #endif /* SO_BINDTODEVICE */ - return 0; + return 0; } -static int -bgp_update_address (struct interface *ifp, const union sockunion *dst, - union sockunion *addr) +static int bgp_update_address(struct interface *ifp, const union sockunion *dst, + union sockunion *addr) { - struct prefix *p, *sel, d; - struct connected *connected; - struct listnode *node; - int common; - - sockunion2hostprefix (dst, &d); - sel = NULL; - common = -1; - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) - { - p = connected->address; - if (p->family != d.family) - continue; - if (prefix_common_bits (p, &d) > common) - { - sel = p; - common = prefix_common_bits (sel, &d); - } - } - - if (!sel) - return 1; - - prefix2sockunion (sel, addr); - return 0; + struct prefix *p, *sel, d; + struct connected *connected; + struct listnode *node; + int common; + + sockunion2hostprefix(dst, &d); + sel = NULL; + common = -1; + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { + p = connected->address; + if (p->family != d.family) + continue; + if (prefix_common_bits(p, &d) > common) { + sel = p; + common = prefix_common_bits(sel, &d); + } + } + + if (!sel) + return 1; + + prefix2sockunion(sel, addr); + return 0; } /* Update source selection. */ -static int -bgp_update_source (struct peer *peer) +static int bgp_update_source(struct peer *peer) { - struct interface *ifp; - union sockunion addr; - int ret = 0; + struct interface *ifp; + union sockunion addr; + int ret = 0; - sockunion_init (&addr); + sockunion_init(&addr); - /* Source is specified with interface name. */ - if (peer->update_if) - { - ifp = if_lookup_by_name (peer->update_if, peer->bgp->vrf_id); - if (! ifp) - return -1; + /* Source is specified with interface name. */ + if (peer->update_if) { + ifp = if_lookup_by_name(peer->update_if, peer->bgp->vrf_id); + if (!ifp) + return -1; - if (bgp_update_address (ifp, &peer->su, &addr)) - return -1; + if (bgp_update_address(ifp, &peer->su, &addr)) + return -1; - ret = sockunion_bind (peer->fd, &addr, 0, &addr); - } + ret = sockunion_bind(peer->fd, &addr, 0, &addr); + } - /* Source is specified with IP address. */ - if (peer->update_source) - ret = sockunion_bind (peer->fd, peer->update_source, 0, peer->update_source); + /* Source is specified with IP address. */ + if (peer->update_source) + ret = sockunion_bind(peer->fd, peer->update_source, 0, + peer->update_source); - return ret; + return ret; } #define DATAPLANE_MARK 254 /* main table ID */ /* BGP try to connect to the peer. */ -int -bgp_connect (struct peer *peer) +int bgp_connect(struct peer *peer) { - ifindex_t ifindex = 0; - - if (peer->conf_if && BGP_PEER_SU_UNSPEC(peer)) - { - zlog_debug("Peer address not learnt: Returning from connect"); - return 0; - } - /* Make socket for the peer. */ - peer->fd = sockunion_socket (&peer->su); - if (peer->fd < 0) - return -1; - - set_nonblocking (peer->fd); - - /* Set socket send buffer size */ - setsockopt_so_sendbuf (peer->fd, BGP_SOCKET_SNDBUF_SIZE); - - if (bgp_set_socket_ttl (peer, peer->fd) < 0) - return -1; - - sockopt_reuseaddr (peer->fd); - sockopt_reuseport (peer->fd); - if (sockopt_mark_default(peer->fd, DATAPLANE_MARK, &bgpd_privs) < 0) - zlog_warn("Unable to set mark on FD for peer %s, err=%s", peer->host, - safe_strerror(errno)); - + ifindex_t ifindex = 0; + + if (peer->conf_if && BGP_PEER_SU_UNSPEC(peer)) { + zlog_debug("Peer address not learnt: Returning from connect"); + return 0; + } + /* Make socket for the peer. */ + peer->fd = sockunion_socket(&peer->su); + if (peer->fd < 0) + return -1; + + set_nonblocking(peer->fd); + + /* Set socket send buffer size */ + setsockopt_so_sendbuf(peer->fd, BGP_SOCKET_SNDBUF_SIZE); + + if (bgp_set_socket_ttl(peer, peer->fd) < 0) + return -1; + + sockopt_reuseaddr(peer->fd); + sockopt_reuseport(peer->fd); + if (sockopt_mark_default(peer->fd, DATAPLANE_MARK, &bgpd_privs) < 0) + zlog_warn("Unable to set mark on FD for peer %s, err=%s", + peer->host, safe_strerror(errno)); + #ifdef IPTOS_PREC_INTERNETCONTROL - if (bgpd_privs.change (ZPRIVS_RAISE)) - zlog_err ("%s: could not raise privs", __func__); - if (sockunion_family (&peer->su) == AF_INET) - setsockopt_ipv4_tos (peer->fd, IPTOS_PREC_INTERNETCONTROL); - else if (sockunion_family (&peer->su) == AF_INET6) - setsockopt_ipv6_tclass (peer->fd, IPTOS_PREC_INTERNETCONTROL); - if (bgpd_privs.change (ZPRIVS_LOWER)) - zlog_err ("%s: could not lower privs", __func__); + if (bgpd_privs.change(ZPRIVS_RAISE)) + zlog_err("%s: could not raise privs", __func__); + if (sockunion_family(&peer->su) == AF_INET) + setsockopt_ipv4_tos(peer->fd, IPTOS_PREC_INTERNETCONTROL); + else if (sockunion_family(&peer->su) == AF_INET6) + setsockopt_ipv6_tclass(peer->fd, IPTOS_PREC_INTERNETCONTROL); + if (bgpd_privs.change(ZPRIVS_LOWER)) + zlog_err("%s: could not lower privs", __func__); #endif - if (peer->password) - bgp_md5_set_connect (peer->fd, &peer->su, peer->password); + if (peer->password) + bgp_md5_set_connect(peer->fd, &peer->su, peer->password); - /* Bind socket. */ - bgp_bind (peer); + /* Bind socket. */ + bgp_bind(peer); - /* Update source bind. */ - if (bgp_update_source (peer) < 0) - { - return connect_error; - } + /* Update source bind. */ + if (bgp_update_source(peer) < 0) { + return connect_error; + } - if (peer->conf_if || peer->ifname) - ifindex = ifname2ifindex (peer->conf_if ? peer->conf_if : peer->ifname, peer->bgp->vrf_id); + if (peer->conf_if || peer->ifname) + ifindex = ifname2ifindex(peer->conf_if ? peer->conf_if + : peer->ifname, + peer->bgp->vrf_id); - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s [Event] Connect start to %s fd %d", - peer->host, peer->host, peer->fd); + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s [Event] Connect start to %s fd %d", peer->host, + peer->host, peer->fd); - /* Connect to the remote peer. */ - return sockunion_connect (peer->fd, &peer->su, htons (peer->port), ifindex); + /* Connect to the remote peer. */ + return sockunion_connect(peer->fd, &peer->su, htons(peer->port), + ifindex); } /* After TCP connection is established. Get local address and port. */ -int -bgp_getsockname (struct peer *peer) +int bgp_getsockname(struct peer *peer) { - if (peer->su_local) - { - sockunion_free (peer->su_local); - peer->su_local = NULL; - } - - if (peer->su_remote) - { - sockunion_free (peer->su_remote); - peer->su_remote = NULL; - } - - peer->su_local = sockunion_getsockname (peer->fd); - if (!peer->su_local) return -1; - peer->su_remote = sockunion_getpeername (peer->fd); - if (!peer->su_remote) return -1; - - if (bgp_nexthop_set (peer->su_local, peer->su_remote, - &peer->nexthop, peer)) - { -#if defined (HAVE_CUMULUS) - zlog_err ("%s: nexthop_set failed, resetting connection - intf %p", - peer->host, peer->nexthop.ifp); - return -1; + if (peer->su_local) { + sockunion_free(peer->su_local); + peer->su_local = NULL; + } + + if (peer->su_remote) { + sockunion_free(peer->su_remote); + peer->su_remote = NULL; + } + + peer->su_local = sockunion_getsockname(peer->fd); + if (!peer->su_local) + return -1; + peer->su_remote = sockunion_getpeername(peer->fd); + if (!peer->su_remote) + return -1; + + if (bgp_nexthop_set(peer->su_local, peer->su_remote, &peer->nexthop, + peer)) { +#if defined(HAVE_CUMULUS) + zlog_err( + "%s: nexthop_set failed, resetting connection - intf %p", + peer->host, peer->nexthop.ifp); + return -1; #endif - } + } - return 0; + return 0; } -static int -bgp_listener (int sock, struct sockaddr *sa, socklen_t salen) +static int bgp_listener(int sock, struct sockaddr *sa, socklen_t salen) { - struct bgp_listener *listener; - int ret, en; + struct bgp_listener *listener; + int ret, en; - sockopt_reuseaddr (sock); - sockopt_reuseport (sock); + sockopt_reuseaddr(sock); + sockopt_reuseport(sock); - if (bgpd_privs.change (ZPRIVS_RAISE)) - zlog_err ("%s: could not raise privs", __func__); + if (bgpd_privs.change(ZPRIVS_RAISE)) + zlog_err("%s: could not raise privs", __func__); #ifdef IPTOS_PREC_INTERNETCONTROL - if (sa->sa_family == AF_INET) - setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL); - else if (sa->sa_family == AF_INET6) - setsockopt_ipv6_tclass (sock, IPTOS_PREC_INTERNETCONTROL); + if (sa->sa_family == AF_INET) + setsockopt_ipv4_tos(sock, IPTOS_PREC_INTERNETCONTROL); + else if (sa->sa_family == AF_INET6) + setsockopt_ipv6_tclass(sock, IPTOS_PREC_INTERNETCONTROL); #endif - sockopt_v6only (sa->sa_family, sock); - - ret = bind (sock, sa, salen); - en = errno; - if (bgpd_privs.change (ZPRIVS_LOWER)) - zlog_err ("%s: could not lower privs", __func__); - - if (ret < 0) - { - zlog_err ("bind: %s", safe_strerror (en)); - return ret; - } - - ret = listen (sock, 3); - if (ret < 0) - { - zlog_err ("listen: %s", safe_strerror (errno)); - return ret; - } - - listener = XMALLOC (MTYPE_BGP_LISTENER, sizeof(*listener)); - listener->fd = sock; - memcpy(&listener->su, sa, salen); - listener->thread = NULL; - thread_add_read(bm->master, bgp_accept, listener, sock, &listener->thread); - listnode_add (bm->listen_sockets, listener); - - return 0; + sockopt_v6only(sa->sa_family, sock); + + ret = bind(sock, sa, salen); + en = errno; + if (bgpd_privs.change(ZPRIVS_LOWER)) + zlog_err("%s: could not lower privs", __func__); + + if (ret < 0) { + zlog_err("bind: %s", safe_strerror(en)); + return ret; + } + + ret = listen(sock, 3); + if (ret < 0) { + zlog_err("listen: %s", safe_strerror(errno)); + return ret; + } + + listener = XMALLOC(MTYPE_BGP_LISTENER, sizeof(*listener)); + listener->fd = sock; + memcpy(&listener->su, sa, salen); + listener->thread = NULL; + thread_add_read(bm->master, bgp_accept, listener, sock, + &listener->thread); + listnode_add(bm->listen_sockets, listener); + + return 0; } /* IPv6 supported version of BGP server socket setup. */ -int -bgp_socket (unsigned short port, const char *address) +int bgp_socket(unsigned short port, const char *address) { - struct addrinfo *ainfo; - struct addrinfo *ainfo_save; - static const struct addrinfo req = { - .ai_family = AF_UNSPEC, - .ai_flags = AI_PASSIVE, - .ai_socktype = SOCK_STREAM, - }; - int ret, count; - char port_str[BUFSIZ]; - - snprintf (port_str, sizeof(port_str), "%d", port); - port_str[sizeof (port_str) - 1] = '\0'; - - ret = getaddrinfo (address, port_str, &req, &ainfo_save); - if (ret != 0) - { - zlog_err ("getaddrinfo: %s", gai_strerror (ret)); - return -1; - } - - count = 0; - for (ainfo = ainfo_save; ainfo; ainfo = ainfo->ai_next) - { - int sock; - - if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6) - continue; - - sock = socket (ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol); - if (sock < 0) - { - zlog_err ("socket: %s", safe_strerror (errno)); - continue; - } - - /* if we intend to implement ttl-security, this socket needs ttl=255 */ - sockopt_ttl (ainfo->ai_family, sock, MAXTTL); - - ret = bgp_listener (sock, ainfo->ai_addr, ainfo->ai_addrlen); - if (ret == 0) - ++count; - else - close(sock); - } - freeaddrinfo (ainfo_save); - if (count == 0) - { - zlog_err ("%s: no usable addresses", __func__); - return -1; - } - - return 0; + struct addrinfo *ainfo; + struct addrinfo *ainfo_save; + static const struct addrinfo req = { + .ai_family = AF_UNSPEC, + .ai_flags = AI_PASSIVE, + .ai_socktype = SOCK_STREAM, + }; + int ret, count; + char port_str[BUFSIZ]; + + snprintf(port_str, sizeof(port_str), "%d", port); + port_str[sizeof(port_str) - 1] = '\0'; + + ret = getaddrinfo(address, port_str, &req, &ainfo_save); + if (ret != 0) { + zlog_err("getaddrinfo: %s", gai_strerror(ret)); + return -1; + } + + count = 0; + for (ainfo = ainfo_save; ainfo; ainfo = ainfo->ai_next) { + int sock; + + if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6) + continue; + + sock = socket(ainfo->ai_family, ainfo->ai_socktype, + ainfo->ai_protocol); + if (sock < 0) { + zlog_err("socket: %s", safe_strerror(errno)); + continue; + } + + /* if we intend to implement ttl-security, this socket needs + * ttl=255 */ + sockopt_ttl(ainfo->ai_family, sock, MAXTTL); + + ret = bgp_listener(sock, ainfo->ai_addr, ainfo->ai_addrlen); + if (ret == 0) + ++count; + else + close(sock); + } + freeaddrinfo(ainfo_save); + if (count == 0) { + zlog_err("%s: no usable addresses", __func__); + return -1; + } + + return 0; } -void -bgp_close (void) +void bgp_close(void) { - struct listnode *node, *next; - struct bgp_listener *listener; - - if (bm->listen_sockets == NULL) - return; - - for (ALL_LIST_ELEMENTS (bm->listen_sockets, node, next, listener)) - { - thread_cancel (listener->thread); - close (listener->fd); - listnode_delete (bm->listen_sockets, listener); - XFREE (MTYPE_BGP_LISTENER, listener); - } + struct listnode *node, *next; + struct bgp_listener *listener; + + if (bm->listen_sockets == NULL) + return; + + for (ALL_LIST_ELEMENTS(bm->listen_sockets, node, next, listener)) { + thread_cancel(listener->thread); + close(listener->fd); + listnode_delete(bm->listen_sockets, listener); + XFREE(MTYPE_BGP_LISTENER, listener); + } } diff --git a/bgpd/bgp_network.h b/bgpd/bgp_network.h index 56938b437..75ff1305c 100644 --- a/bgpd/bgp_network.h +++ b/bgpd/bgp_network.h @@ -23,13 +23,13 @@ #define BGP_SOCKET_SNDBUF_SIZE 65536 -extern int bgp_socket (unsigned short, const char *); -extern void bgp_close (void); -extern int bgp_connect (struct peer *); -extern int bgp_getsockname (struct peer *); +extern int bgp_socket(unsigned short, const char *); +extern void bgp_close(void); +extern int bgp_connect(struct peer *); +extern int bgp_getsockname(struct peer *); -extern int bgp_md5_set (struct peer *); -extern int bgp_md5_unset (struct peer *); +extern int bgp_md5_set(struct peer *); +extern int bgp_md5_unset(struct peer *); extern int bgp_set_socket_ttl(struct peer *, int fd); #endif /* _QUAGGA_BGP_NETWORK_H */ diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 148fba2d4..63a84684b 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -45,443 +45,445 @@ #include "bgpd/bgp_fsm.h" #include "bgpd/bgp_vty.h" #include "zebra/rib.h" -#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */ +#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */ -char * -bnc_str (struct bgp_nexthop_cache *bnc, char *buf, int size) +char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size) { - prefix2str(&(bnc->node->p), buf, size); - return buf; + prefix2str(&(bnc->node->p), buf, size); + return buf; } -void -bnc_nexthop_free (struct bgp_nexthop_cache *bnc) +void bnc_nexthop_free(struct bgp_nexthop_cache *bnc) { - nexthops_free(bnc->nexthop); + nexthops_free(bnc->nexthop); } -struct bgp_nexthop_cache * -bnc_new (void) +struct bgp_nexthop_cache *bnc_new(void) { - struct bgp_nexthop_cache *bnc; + struct bgp_nexthop_cache *bnc; - bnc = XCALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache)); - LIST_INIT(&(bnc->paths)); - return bnc; + bnc = XCALLOC(MTYPE_BGP_NEXTHOP_CACHE, + sizeof(struct bgp_nexthop_cache)); + LIST_INIT(&(bnc->paths)); + return bnc; } -void -bnc_free (struct bgp_nexthop_cache *bnc) +void bnc_free(struct bgp_nexthop_cache *bnc) { - bnc_nexthop_free (bnc); - XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc); + bnc_nexthop_free(bnc); + XFREE(MTYPE_BGP_NEXTHOP_CACHE, bnc); } /* Reset and free all BGP nexthop cache. */ -static void -bgp_nexthop_cache_reset (struct bgp_table *table) +static void bgp_nexthop_cache_reset(struct bgp_table *table) { - struct bgp_node *rn; - struct bgp_nexthop_cache *bnc; - - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - if ((bnc = rn->info) != NULL) - { - bnc_free (bnc); - rn->info = NULL; - bgp_unlock_node (rn); - } + struct bgp_node *rn; + struct bgp_nexthop_cache *bnc; + + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) + if ((bnc = rn->info) != NULL) { + bnc_free(bnc); + rn->info = NULL; + bgp_unlock_node(rn); + } } /* BGP own address structure */ -struct bgp_addr -{ - struct in_addr addr; - int refcnt; +struct bgp_addr { + struct in_addr addr; + int refcnt; }; -static void * -bgp_address_hash_alloc (void *p) +static void *bgp_address_hash_alloc(void *p) { - const struct in_addr *val = (const struct in_addr *)p; - struct bgp_addr *addr; + const struct in_addr *val = (const struct in_addr *)p; + struct bgp_addr *addr; - addr = XMALLOC (MTYPE_BGP_ADDR, sizeof (struct bgp_addr)); - addr->refcnt = 0; - addr->addr.s_addr = val->s_addr; + addr = XMALLOC(MTYPE_BGP_ADDR, sizeof(struct bgp_addr)); + addr->refcnt = 0; + addr->addr.s_addr = val->s_addr; - return addr; + return addr; } -static void -bgp_address_hash_free (void *addr) +static void bgp_address_hash_free(void *addr) { - XFREE (MTYPE_BGP_ADDR, addr); + XFREE(MTYPE_BGP_ADDR, addr); } -static unsigned int -bgp_address_hash_key_make (void *p) +static unsigned int bgp_address_hash_key_make(void *p) { - const struct bgp_addr *addr = p; + const struct bgp_addr *addr = p; - return jhash_1word(addr->addr.s_addr, 0); + return jhash_1word(addr->addr.s_addr, 0); } -static int -bgp_address_hash_cmp (const void *p1, const void *p2) +static int bgp_address_hash_cmp(const void *p1, const void *p2) { - const struct bgp_addr *addr1 = p1; - const struct bgp_addr *addr2 = p2; + const struct bgp_addr *addr1 = p1; + const struct bgp_addr *addr2 = p2; - return addr1->addr.s_addr == addr2->addr.s_addr; + return addr1->addr.s_addr == addr2->addr.s_addr; } -void -bgp_address_init (struct bgp *bgp) +void bgp_address_init(struct bgp *bgp) { - bgp->address_hash = hash_create (bgp_address_hash_key_make, - bgp_address_hash_cmp, NULL); + bgp->address_hash = hash_create(bgp_address_hash_key_make, + bgp_address_hash_cmp, NULL); } -void -bgp_address_destroy (struct bgp *bgp) +void bgp_address_destroy(struct bgp *bgp) { - if (bgp->address_hash == NULL) - return; - hash_clean(bgp->address_hash, bgp_address_hash_free); - hash_free(bgp->address_hash); - bgp->address_hash = NULL; + if (bgp->address_hash == NULL) + return; + hash_clean(bgp->address_hash, bgp_address_hash_free); + hash_free(bgp->address_hash); + bgp->address_hash = NULL; } -static void -bgp_address_add (struct bgp *bgp, struct prefix *p) +static void bgp_address_add(struct bgp *bgp, struct prefix *p) { - struct bgp_addr tmp; - struct bgp_addr *addr; + struct bgp_addr tmp; + struct bgp_addr *addr; - tmp.addr = p->u.prefix4; + tmp.addr = p->u.prefix4; - addr = hash_get (bgp->address_hash, &tmp, bgp_address_hash_alloc); - if (!addr) - return; + addr = hash_get(bgp->address_hash, &tmp, bgp_address_hash_alloc); + if (!addr) + return; - addr->refcnt++; + addr->refcnt++; } -static void -bgp_address_del (struct bgp *bgp, struct prefix *p) +static void bgp_address_del(struct bgp *bgp, struct prefix *p) { - struct bgp_addr tmp; - struct bgp_addr *addr; + struct bgp_addr tmp; + struct bgp_addr *addr; - tmp.addr = p->u.prefix4; + tmp.addr = p->u.prefix4; - addr = hash_lookup (bgp->address_hash, &tmp); - /* may have been deleted earlier by bgp_interface_down() */ - if (addr == NULL) - return; + addr = hash_lookup(bgp->address_hash, &tmp); + /* may have been deleted earlier by bgp_interface_down() */ + if (addr == NULL) + return; - addr->refcnt--; + addr->refcnt--; - if (addr->refcnt == 0) - { - hash_release (bgp->address_hash, addr); - XFREE (MTYPE_BGP_ADDR, addr); - } + if (addr->refcnt == 0) { + hash_release(bgp->address_hash, addr); + XFREE(MTYPE_BGP_ADDR, addr); + } } -struct bgp_connected_ref -{ - unsigned int refcnt; +struct bgp_connected_ref { + unsigned int refcnt; }; -void -bgp_connected_add (struct bgp *bgp, struct connected *ifc) +void bgp_connected_add(struct bgp *bgp, struct connected *ifc) { - struct prefix p; - struct prefix *addr; - struct bgp_node *rn; - struct bgp_connected_ref *bc; - struct listnode *node, *nnode; - struct peer *peer; - - addr = ifc->address; - - p = *(CONNECTED_PREFIX(ifc)); - if (addr->family == AF_INET) - { - apply_mask_ipv4 ((struct prefix_ipv4 *) &p); - - if (prefix_ipv4_any ((struct prefix_ipv4 *) &p)) - return; - - bgp_address_add (bgp, addr); - - rn = bgp_node_get (bgp->connected_table[AFI_IP], (struct prefix *) &p); - if (rn->info) - { - bc = rn->info; - bc->refcnt++; - } - else - { - bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref)); - bc->refcnt = 1; - rn->info = bc; - } + struct prefix p; + struct prefix *addr; + struct bgp_node *rn; + struct bgp_connected_ref *bc; + struct listnode *node, *nnode; + struct peer *peer; + + addr = ifc->address; + + p = *(CONNECTED_PREFIX(ifc)); + if (addr->family == AF_INET) { + apply_mask_ipv4((struct prefix_ipv4 *)&p); + + if (prefix_ipv4_any((struct prefix_ipv4 *)&p)) + return; + + bgp_address_add(bgp, addr); + + rn = bgp_node_get(bgp->connected_table[AFI_IP], + (struct prefix *)&p); + if (rn->info) { + bc = rn->info; + bc->refcnt++; + } else { + bc = XCALLOC(MTYPE_BGP_CONN, + sizeof(struct bgp_connected_ref)); + bc->refcnt = 1; + rn->info = bc; + } - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0) && - peer->status != Established && - !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) - { - if (peer_active(peer)) - BGP_EVENT_ADD (peer, BGP_Stop); - BGP_EVENT_ADD (peer, BGP_Start); - } - } - } - else if (addr->family == AF_INET6) - { - apply_mask_ipv6 ((struct prefix_ipv6 *) &p); - - if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) - return; - - if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6)) - return; - - rn = bgp_node_get (bgp->connected_table[AFI_IP6], (struct prefix *) &p); - if (rn->info) - { - bc = rn->info; - bc->refcnt++; - } - else - { - bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref)); - bc->refcnt = 1; - rn->info = bc; + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (peer->conf_if + && (strcmp(peer->conf_if, ifc->ifp->name) == 0) + && peer->status != Established + && !CHECK_FLAG(peer->flags, + PEER_FLAG_IFPEER_V6ONLY)) { + if (peer_active(peer)) + BGP_EVENT_ADD(peer, BGP_Stop); + BGP_EVENT_ADD(peer, BGP_Start); + } + } + } else if (addr->family == AF_INET6) { + apply_mask_ipv6((struct prefix_ipv6 *)&p); + + if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6)) + return; + + if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) + return; + + rn = bgp_node_get(bgp->connected_table[AFI_IP6], + (struct prefix *)&p); + if (rn->info) { + bc = rn->info; + bc->refcnt++; + } else { + bc = XCALLOC(MTYPE_BGP_CONN, + sizeof(struct bgp_connected_ref)); + bc->refcnt = 1; + rn->info = bc; + } } - } } -void -bgp_connected_delete (struct bgp *bgp, struct connected *ifc) +void bgp_connected_delete(struct bgp *bgp, struct connected *ifc) { - struct prefix p; - struct prefix *addr; - struct bgp_node *rn; - struct bgp_connected_ref *bc; + struct prefix p; + struct prefix *addr; + struct bgp_node *rn; + struct bgp_connected_ref *bc; - addr = ifc->address; + addr = ifc->address; - p = *(CONNECTED_PREFIX(ifc)); - if (addr->family == AF_INET) - { - apply_mask_ipv4 ((struct prefix_ipv4 *) &p); + p = *(CONNECTED_PREFIX(ifc)); + if (addr->family == AF_INET) { + apply_mask_ipv4((struct prefix_ipv4 *)&p); - if (prefix_ipv4_any ((struct prefix_ipv4 *) &p)) - return; + if (prefix_ipv4_any((struct prefix_ipv4 *)&p)) + return; - bgp_address_del (bgp, addr); + bgp_address_del(bgp, addr); - rn = bgp_node_lookup (bgp->connected_table[AFI_IP], &p); - if (! rn) - return; + rn = bgp_node_lookup(bgp->connected_table[AFI_IP], &p); + if (!rn) + return; - bc = rn->info; - bc->refcnt--; - if (bc->refcnt == 0) - { - XFREE (MTYPE_BGP_CONN, bc); - rn->info = NULL; - } - bgp_unlock_node (rn); - bgp_unlock_node (rn); - } - else if (addr->family == AF_INET6) - { - apply_mask_ipv6 ((struct prefix_ipv6 *) &p); - - if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) - return; - - if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6)) - return; - - rn = bgp_node_lookup (bgp->connected_table[AFI_IP6], (struct prefix *) &p); - if (! rn) - return; - - bc = rn->info; - bc->refcnt--; - if (bc->refcnt == 0) - { - XFREE (MTYPE_BGP_CONN, bc); - rn->info = NULL; + bc = rn->info; + bc->refcnt--; + if (bc->refcnt == 0) { + XFREE(MTYPE_BGP_CONN, bc); + rn->info = NULL; + } + bgp_unlock_node(rn); + bgp_unlock_node(rn); + } else if (addr->family == AF_INET6) { + apply_mask_ipv6((struct prefix_ipv6 *)&p); + + if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6)) + return; + + if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) + return; + + rn = bgp_node_lookup(bgp->connected_table[AFI_IP6], + (struct prefix *)&p); + if (!rn) + return; + + bc = rn->info; + bc->refcnt--; + if (bc->refcnt == 0) { + XFREE(MTYPE_BGP_CONN, bc); + rn->info = NULL; + } + bgp_unlock_node(rn); + bgp_unlock_node(rn); } - bgp_unlock_node (rn); - bgp_unlock_node (rn); - } } -int -bgp_nexthop_self (struct bgp *bgp, struct in_addr nh_addr) +int bgp_nexthop_self(struct bgp *bgp, struct in_addr nh_addr) { - struct bgp_addr tmp, *addr; + struct bgp_addr tmp, *addr; - tmp.addr = nh_addr; + tmp.addr = nh_addr; - addr = hash_lookup (bgp->address_hash, &tmp); - if (addr) - return 1; + addr = hash_lookup(bgp->address_hash, &tmp); + if (addr) + return 1; - return 0; + return 0; } -int -bgp_multiaccess_check_v4 (struct in_addr nexthop, struct peer *peer) +int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer) { - struct bgp_node *rn1; - struct bgp_node *rn2; - struct prefix p; - int ret; - - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - p.u.prefix4 = nexthop; - - rn1 = bgp_node_match (peer->bgp->connected_table[AFI_IP], &p); - if (!rn1) - return 0; - - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - p.u.prefix4 = peer->su.sin.sin_addr; - - rn2 = bgp_node_match (peer->bgp->connected_table[AFI_IP], &p); - if (!rn2) - { - bgp_unlock_node(rn1); - return 0; - } + struct bgp_node *rn1; + struct bgp_node *rn2; + struct prefix p; + int ret; + + p.family = AF_INET; + p.prefixlen = IPV4_MAX_BITLEN; + p.u.prefix4 = nexthop; + + rn1 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p); + if (!rn1) + return 0; + + p.family = AF_INET; + p.prefixlen = IPV4_MAX_BITLEN; + p.u.prefix4 = peer->su.sin.sin_addr; + + rn2 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p); + if (!rn2) { + bgp_unlock_node(rn1); + return 0; + } - ret = (rn1 == rn2) ? 1 : 0; + ret = (rn1 == rn2) ? 1 : 0; - bgp_unlock_node(rn1); - bgp_unlock_node(rn2); + bgp_unlock_node(rn1); + bgp_unlock_node(rn2); - return (ret); + return (ret); } -static void -bgp_show_nexthops (struct vty *vty, struct bgp *bgp, int detail) +static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail) { - struct bgp_node *rn; - struct bgp_nexthop_cache *bnc; - char buf[PREFIX2STR_BUFFER]; - struct nexthop *nexthop; - time_t tbuf; - afi_t afi; - - vty_out (vty, "Current BGP nexthop cache:\n"); - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - { - if (!bgp->nexthop_cache_table[afi]) - continue; - - for (rn = bgp_table_top (bgp->nexthop_cache_table[afi]); rn; rn = bgp_route_next (rn)) - { - if ((bnc = rn->info) != NULL) - { - if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) - { - vty_out (vty, " %s valid [IGP metric %d], #paths %d\n", - inet_ntop (rn->p.family, &rn->p.u.prefix, buf, sizeof (buf)), - bnc->metric, bnc->path_count); - if (detail) - for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next) - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV6: - vty_out (vty, " gate %s\n", - inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, sizeof(buf))); - break; - case NEXTHOP_TYPE_IPV6_IFINDEX: - vty_out (vty, " gate %s, if %s\n", - inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, - sizeof (buf)), - ifindex2ifname(nexthop->ifindex, bgp->vrf_id)); - break; - case NEXTHOP_TYPE_IPV4: - vty_out (vty, " gate %s\n", - inet_ntop(AF_INET, &nexthop->gate.ipv4, buf, sizeof(buf))); - break; - case NEXTHOP_TYPE_IFINDEX: - vty_out (vty, " if %s\n", - ifindex2ifname(nexthop->ifindex, bgp->vrf_id)); - break; - case NEXTHOP_TYPE_IPV4_IFINDEX: - vty_out (vty, " gate %s, if %s\n", - inet_ntop(AF_INET, &nexthop->gate.ipv4, buf, - sizeof (buf)), - ifindex2ifname(nexthop->ifindex, bgp->vrf_id)); - break; - default: - vty_out (vty, " invalid nexthop type %u\n", - nexthop->type); + struct bgp_node *rn; + struct bgp_nexthop_cache *bnc; + char buf[PREFIX2STR_BUFFER]; + struct nexthop *nexthop; + time_t tbuf; + afi_t afi; + + vty_out(vty, "Current BGP nexthop cache:\n"); + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + if (!bgp->nexthop_cache_table[afi]) + continue; + + for (rn = bgp_table_top(bgp->nexthop_cache_table[afi]); rn; + rn = bgp_route_next(rn)) { + if ((bnc = rn->info) != NULL) { + if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) { + vty_out(vty, + " %s valid [IGP metric %d], #paths %d\n", + inet_ntop(rn->p.family, + &rn->p.u.prefix, buf, + sizeof(buf)), + bnc->metric, bnc->path_count); + if (detail) + for (nexthop = bnc->nexthop; + nexthop; + nexthop = nexthop->next) + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV6: + vty_out(vty, + " gate %s\n", + inet_ntop( + AF_INET6, + &nexthop->gate + .ipv6, + buf, + sizeof(buf))); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + vty_out(vty, + " gate %s, if %s\n", + inet_ntop( + AF_INET6, + &nexthop->gate + .ipv6, + buf, + sizeof(buf)), + ifindex2ifname( + nexthop->ifindex, + bgp->vrf_id)); + break; + case NEXTHOP_TYPE_IPV4: + vty_out(vty, + " gate %s\n", + inet_ntop( + AF_INET, + &nexthop->gate + .ipv4, + buf, + sizeof(buf))); + break; + case NEXTHOP_TYPE_IFINDEX: + vty_out(vty, + " if %s\n", + ifindex2ifname( + nexthop->ifindex, + bgp->vrf_id)); + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + vty_out(vty, + " gate %s, if %s\n", + inet_ntop( + AF_INET, + &nexthop->gate + .ipv4, + buf, + sizeof(buf)), + ifindex2ifname( + nexthop->ifindex, + bgp->vrf_id)); + break; + default: + vty_out(vty, + " invalid nexthop type %u\n", + nexthop->type); + } + } else { + vty_out(vty, " %s invalid\n", + inet_ntop(rn->p.family, + &rn->p.u.prefix, buf, + sizeof(buf))); + if (CHECK_FLAG(bnc->flags, + BGP_NEXTHOP_CONNECTED)) + vty_out(vty, + " Must be Connected\n"); + } + tbuf = time(NULL) + - (bgp_clock() - bnc->last_update); + vty_out(vty, " Last update: %s", ctime(&tbuf)); + vty_out(vty, "\n"); } } - else - { - vty_out (vty, " %s invalid\n", - inet_ntop(rn->p.family, &rn->p.u.prefix, buf, sizeof(buf))); - if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) - vty_out (vty, " Must be Connected\n"); - } - tbuf = time(NULL) - (bgp_clock() - bnc->last_update); - vty_out (vty, " Last update: %s", ctime(&tbuf)); - vty_out (vty, "\n"); - } } - } } -static int -show_ip_bgp_nexthop_table (struct vty *vty, const char *name, int detail) +static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name, + int detail) { - struct bgp *bgp; - - if (name) - bgp = bgp_lookup_by_name (name); - else - bgp = bgp_get_default (); - if (!bgp) - { - vty_out (vty, "%% No such BGP instance exist\n"); - return CMD_WARNING; - } + struct bgp *bgp; + + if (name) + bgp = bgp_lookup_by_name(name); + else + bgp = bgp_get_default(); + if (!bgp) { + vty_out(vty, "%% No such BGP instance exist\n"); + return CMD_WARNING; + } - bgp_show_nexthops (vty, bgp, detail); + bgp_show_nexthops(vty, bgp, detail); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static void -bgp_show_all_instances_nexthops_vty (struct vty *vty) +static void bgp_show_all_instances_nexthops_vty(struct vty *vty) { - struct listnode *node, *nnode; - struct bgp *bgp; - - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - { - vty_out (vty, "\nInstance %s:\n", - (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) ? "Default" : bgp->name); - bgp_show_nexthops (vty, bgp, 0); - } + struct listnode *node, *nnode; + struct bgp *bgp; + + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) { + vty_out(vty, "\nInstance %s:\n", + (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) + ? "Default" + : bgp->name); + bgp_show_nexthops(vty, bgp, 0); + } } DEFUN (show_ip_bgp_nexthop, @@ -494,10 +496,10 @@ DEFUN (show_ip_bgp_nexthop, "BGP nexthop table\n" "Show detailed information\n") { - int idx = 0; - char *vrf = argv_find (argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL; - int detail = argv_find (argv, argc, "detail", &idx) ? 1 : 0; - return show_ip_bgp_nexthop_table (vty, vrf, detail); + int idx = 0; + char *vrf = argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL; + int detail = argv_find(argv, argc, "detail", &idx) ? 1 : 0; + return show_ip_bgp_nexthop_table(vty, vrf, detail); } DEFUN (show_ip_bgp_instance_all_nexthop, @@ -509,46 +511,43 @@ DEFUN (show_ip_bgp_instance_all_nexthop, BGP_INSTANCE_ALL_HELP_STR "BGP nexthop table\n") { - bgp_show_all_instances_nexthops_vty (vty); - return CMD_SUCCESS; + bgp_show_all_instances_nexthops_vty(vty); + return CMD_SUCCESS; } -void -bgp_scan_init (struct bgp *bgp) +void bgp_scan_init(struct bgp *bgp) { - afi_t afi; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - bgp->nexthop_cache_table[afi] = bgp_table_init (afi, SAFI_UNICAST); - bgp->connected_table[afi] = bgp_table_init (afi, SAFI_UNICAST); - bgp->import_check_table[afi] = bgp_table_init (afi, SAFI_UNICAST); - } + afi_t afi; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + bgp->nexthop_cache_table[afi] = + bgp_table_init(afi, SAFI_UNICAST); + bgp->connected_table[afi] = bgp_table_init(afi, SAFI_UNICAST); + bgp->import_check_table[afi] = + bgp_table_init(afi, SAFI_UNICAST); + } } -void -bgp_scan_vty_init (void) +void bgp_scan_vty_init(void) { - install_element (VIEW_NODE, &show_ip_bgp_nexthop_cmd); - install_element (VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd); + install_element(VIEW_NODE, &show_ip_bgp_nexthop_cmd); + install_element(VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd); } -void -bgp_scan_finish (struct bgp *bgp) +void bgp_scan_finish(struct bgp *bgp) { - afi_t afi; + afi_t afi; - for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - /* Only the current one needs to be reset. */ - bgp_nexthop_cache_reset (bgp->nexthop_cache_table[afi]); - bgp_table_unlock (bgp->nexthop_cache_table[afi]); - bgp->nexthop_cache_table[afi] = NULL; + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + /* Only the current one needs to be reset. */ + bgp_nexthop_cache_reset(bgp->nexthop_cache_table[afi]); + bgp_table_unlock(bgp->nexthop_cache_table[afi]); + bgp->nexthop_cache_table[afi] = NULL; - bgp_table_unlock (bgp->connected_table[afi]); - bgp->connected_table[afi] = NULL; + bgp_table_unlock(bgp->connected_table[afi]); + bgp->connected_table[afi] = NULL; - bgp_table_unlock (bgp->import_check_table[afi]); - bgp->import_check_table[afi] = NULL; - } + bgp_table_unlock(bgp->import_check_table[afi]); + bgp->import_check_table[afi] = NULL; + } } diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h index 3aa20a9d5..37dad577c 100644 --- a/bgpd/bgp_nexthop.h +++ b/bgpd/bgp_nexthop.h @@ -25,28 +25,26 @@ #include "queue.h" #include "prefix.h" -#define NEXTHOP_FAMILY(nexthop_len) ( \ - ((nexthop_len) == 4 || \ - (nexthop_len) == 12 ? AF_INET : \ - ((nexthop_len) == 16 || \ - (nexthop_len) == 24 || \ - (nexthop_len) == 48 ? AF_INET6 : \ - AF_UNSPEC)) \ -) +#define NEXTHOP_FAMILY(nexthop_len) \ + (((nexthop_len) == 4 || (nexthop_len) == 12 \ + ? AF_INET \ + : ((nexthop_len) == 16 || (nexthop_len) == 24 \ + || (nexthop_len) == 48 \ + ? AF_INET6 \ + : AF_UNSPEC))) #define BGP_MP_NEXTHOP_FAMILY NEXTHOP_FAMILY /* BGP nexthop cache value structure. */ -struct bgp_nexthop_cache -{ - /* IGP route's metric. */ - u_int32_t metric; +struct bgp_nexthop_cache { + /* IGP route's metric. */ + u_int32_t metric; - /* Nexthop number and nexthop linked list.*/ - u_char nexthop_num; - struct nexthop *nexthop; - time_t last_update; - u_int16_t flags; + /* Nexthop number and nexthop linked list.*/ + u_char nexthop_num; + struct nexthop *nexthop; + time_t last_update; + u_int16_t flags; #define BGP_NEXTHOP_VALID (1 << 0) #define BGP_NEXTHOP_REGISTERED (1 << 1) @@ -55,26 +53,26 @@ struct bgp_nexthop_cache #define BGP_STATIC_ROUTE (1 << 4) #define BGP_STATIC_ROUTE_EXACT_MATCH (1 << 5) - u_int16_t change_flags; + u_int16_t change_flags; #define BGP_NEXTHOP_CHANGED (1 << 0) #define BGP_NEXTHOP_METRIC_CHANGED (1 << 1) #define BGP_NEXTHOP_CONNECTED_CHANGED (1 << 2) - struct bgp_node *node; - void *nht_info; /* In BGP, peer session */ - LIST_HEAD(path_list, bgp_info) paths; - unsigned int path_count; - struct bgp *bgp; + struct bgp_node *node; + void *nht_info; /* In BGP, peer session */ + LIST_HEAD(path_list, bgp_info) paths; + unsigned int path_count; + struct bgp *bgp; }; -extern int bgp_nexthop_lookup (afi_t, struct peer *peer, struct bgp_info *, - int *, int *); -extern void bgp_connected_add (struct bgp *bgp, struct connected *c); -extern void bgp_connected_delete (struct bgp *bgp, struct connected *c); -extern int bgp_multiaccess_check_v4 (struct in_addr, struct peer *); -extern int bgp_config_write_scan_time (struct vty *); -extern int bgp_nexthop_self (struct bgp *, struct in_addr); +extern int bgp_nexthop_lookup(afi_t, struct peer *peer, struct bgp_info *, + int *, int *); +extern void bgp_connected_add(struct bgp *bgp, struct connected *c); +extern void bgp_connected_delete(struct bgp *bgp, struct connected *c); +extern int bgp_multiaccess_check_v4(struct in_addr, struct peer *); +extern int bgp_config_write_scan_time(struct vty *); +extern int bgp_nexthop_self(struct bgp *, struct in_addr); extern struct bgp_nexthop_cache *bnc_new(void); extern void bnc_free(struct bgp_nexthop_cache *bnc); extern void bnc_nexthop_free(struct bgp_nexthop_cache *bnc); @@ -82,7 +80,7 @@ extern char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size); extern void bgp_scan_init(struct bgp *bgp); extern void bgp_scan_finish(struct bgp *bgp); extern void bgp_scan_vty_init(void); -extern void bgp_address_init (struct bgp *bgp); -extern void bgp_address_destroy (struct bgp *bgp); +extern void bgp_address_init(struct bgp *bgp); +extern void bgp_address_destroy(struct bgp *bgp); #endif /* _QUAGGA_BGP_NEXTHOP_H */ diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 3feb42246..3a7a60b14 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -45,7 +45,7 @@ extern struct zclient *zclient; static void register_zebra_rnh(struct bgp_nexthop_cache *bnc, - int is_bgp_static_route); + int is_bgp_static_route); static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc, int is_bgp_static_route); static void evaluate_paths(struct bgp_nexthop_cache *bnc); @@ -53,511 +53,484 @@ static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p); static void path_nh_map(struct bgp_info *path, struct bgp_nexthop_cache *bnc, int keep); -static int -bgp_isvalid_nexthop (struct bgp_nexthop_cache *bnc) +static int bgp_isvalid_nexthop(struct bgp_nexthop_cache *bnc) { - return (bgp_zebra_num_connects() == 0 || - (bnc && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))); + return (bgp_zebra_num_connects() == 0 + || (bnc && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))); } -int -bgp_find_nexthop (struct bgp_info *path, int connected) +int bgp_find_nexthop(struct bgp_info *path, int connected) { - struct bgp_nexthop_cache *bnc = path->nexthop; + struct bgp_nexthop_cache *bnc = path->nexthop; - if (!bnc) - return 0; + if (!bnc) + return 0; - /* - * We are cheating here. Views have no associated underlying - * ability to detect nexthops. So when we have a view - * just tell everyone the nexthop is valid - */ - if (path->peer && path->peer->bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) - return 1; + /* + * We are cheating here. Views have no associated underlying + * ability to detect nexthops. So when we have a view + * just tell everyone the nexthop is valid + */ + if (path->peer && path->peer->bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) + return 1; - if (connected && !(CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))) - return 0; + if (connected && !(CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))) + return 0; - return (bgp_isvalid_nexthop(bnc)); + return (bgp_isvalid_nexthop(bnc)); } -static void -bgp_unlink_nexthop_check (struct bgp_nexthop_cache *bnc) +static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc) { - if (LIST_EMPTY(&(bnc->paths)) && !bnc->nht_info) - { - if (BGP_DEBUG(nht, NHT)) - { - char buf[PREFIX2STR_BUFFER]; - zlog_debug("bgp_unlink_nexthop: freeing bnc %s", - bnc_str(bnc, buf, PREFIX2STR_BUFFER)); + if (LIST_EMPTY(&(bnc->paths)) && !bnc->nht_info) { + if (BGP_DEBUG(nht, NHT)) { + char buf[PREFIX2STR_BUFFER]; + zlog_debug("bgp_unlink_nexthop: freeing bnc %s", + bnc_str(bnc, buf, PREFIX2STR_BUFFER)); + } + unregister_zebra_rnh(bnc, + CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE)); + bnc->node->info = NULL; + bgp_unlock_node(bnc->node); + bnc->node = NULL; + bnc_free(bnc); } - unregister_zebra_rnh(bnc, CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE)); - bnc->node->info = NULL; - bgp_unlock_node(bnc->node); - bnc->node = NULL; - bnc_free(bnc); - } } -void -bgp_unlink_nexthop (struct bgp_info *path) +void bgp_unlink_nexthop(struct bgp_info *path) { - struct bgp_nexthop_cache *bnc = path->nexthop; + struct bgp_nexthop_cache *bnc = path->nexthop; + + if (!bnc) + return; - if (!bnc) - return; + path_nh_map(path, NULL, 0); - path_nh_map(path, NULL, 0); - - bgp_unlink_nexthop_check (bnc); + bgp_unlink_nexthop_check(bnc); } -void -bgp_unlink_nexthop_by_peer (struct peer *peer) +void bgp_unlink_nexthop_by_peer(struct peer *peer) { - struct prefix p; - struct bgp_node *rn; - struct bgp_nexthop_cache *bnc; - afi_t afi = family2afi(peer->su.sa.sa_family); - - if (! sockunion2hostprefix (&peer->su, &p)) - return; - - rn = bgp_node_get (peer->bgp->nexthop_cache_table[afi], &p); - - if (!rn->info) - return; - - bnc = rn->info; - - /* cleanup the peer reference */ - bnc->nht_info = NULL; - - bgp_unlink_nexthop_check (bnc); + struct prefix p; + struct bgp_node *rn; + struct bgp_nexthop_cache *bnc; + afi_t afi = family2afi(peer->su.sa.sa_family); + + if (!sockunion2hostprefix(&peer->su, &p)) + return; + + rn = bgp_node_get(peer->bgp->nexthop_cache_table[afi], &p); + + if (!rn->info) + return; + + bnc = rn->info; + + /* cleanup the peer reference */ + bnc->nht_info = NULL; + + bgp_unlink_nexthop_check(bnc); } -int -bgp_find_or_add_nexthop (struct bgp *bgp, afi_t afi, struct bgp_info *ri, - struct peer *peer, int connected) +int bgp_find_or_add_nexthop(struct bgp *bgp, afi_t afi, struct bgp_info *ri, + struct peer *peer, int connected) { - struct bgp_node *rn; - struct bgp_nexthop_cache *bnc; - struct prefix p; - int is_bgp_static_route = 0; - - if (ri) - { - is_bgp_static_route = ((ri->type == ZEBRA_ROUTE_BGP) && - (ri->sub_type == BGP_ROUTE_STATIC)) ? 1 : 0; - - /* Since Extended Next-hop Encoding (RFC5549) support, we want to derive - address-family from the next-hop. */ - if (!is_bgp_static_route) - afi = BGP_ATTR_NEXTHOP_AFI_IP6(ri->attr) ? AFI_IP6 : AFI_IP; - - /* This will return TRUE if the global IPv6 NH is a link local addr */ - if (make_prefix(afi, ri, &p) < 0) - return 1; - } - else if (peer) - { - /* Don't register link local NH */ - if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&peer->su.sin6.sin6_addr)) - return 1; - - if (! sockunion2hostprefix (&peer->su, &p)) - { - if (BGP_DEBUG(nht, NHT)) - { - zlog_debug("%s: Attempting to register with unknown AFI %d (not %d or %d)", - __FUNCTION__, afi, AFI_IP, AFI_IP6); - } - return 0; + struct bgp_node *rn; + struct bgp_nexthop_cache *bnc; + struct prefix p; + int is_bgp_static_route = 0; + + if (ri) { + is_bgp_static_route = ((ri->type == ZEBRA_ROUTE_BGP) + && (ri->sub_type == BGP_ROUTE_STATIC)) + ? 1 + : 0; + + /* Since Extended Next-hop Encoding (RFC5549) support, we want + to derive + address-family from the next-hop. */ + if (!is_bgp_static_route) + afi = BGP_ATTR_NEXTHOP_AFI_IP6(ri->attr) ? AFI_IP6 + : AFI_IP; + + /* This will return TRUE if the global IPv6 NH is a link local + * addr */ + if (make_prefix(afi, ri, &p) < 0) + return 1; + } else if (peer) { + /* Don't register link local NH */ + if (afi == AFI_IP6 + && IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr)) + return 1; + + if (!sockunion2hostprefix(&peer->su, &p)) { + if (BGP_DEBUG(nht, NHT)) { + zlog_debug( + "%s: Attempting to register with unknown AFI %d (not %d or %d)", + __FUNCTION__, afi, AFI_IP, AFI_IP6); + } + return 0; + } + } else + return 0; + + if (is_bgp_static_route) + rn = bgp_node_get(bgp->import_check_table[afi], &p); + else + rn = bgp_node_get(bgp->nexthop_cache_table[afi], &p); + + if (!rn->info) { + bnc = bnc_new(); + rn->info = bnc; + bnc->node = rn; + bnc->bgp = bgp; + bgp_lock_node(rn); + if (BGP_DEBUG(nht, NHT)) { + char buf[PREFIX2STR_BUFFER]; + + zlog_debug("Allocated bnc %s peer %p", + bnc_str(bnc, buf, PREFIX2STR_BUFFER), peer); + } } - } - else - return 0; - - if (is_bgp_static_route) - rn = bgp_node_get (bgp->import_check_table[afi], &p); - else - rn = bgp_node_get (bgp->nexthop_cache_table[afi], &p); - - if (!rn->info) - { - bnc = bnc_new(); - rn->info = bnc; - bnc->node = rn; - bnc->bgp = bgp; - bgp_lock_node(rn); - if (BGP_DEBUG(nht, NHT)) - { - char buf[PREFIX2STR_BUFFER]; - - zlog_debug("Allocated bnc %s peer %p", - bnc_str(bnc, buf, PREFIX2STR_BUFFER), peer); - } - } - - bnc = rn->info; - bgp_unlock_node (rn); - if (is_bgp_static_route) - { - SET_FLAG(bnc->flags, BGP_STATIC_ROUTE); - - /* If we're toggling the type, re-register */ - if ((bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)) && - !CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)) - { - SET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH); - UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); - UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID); + + bnc = rn->info; + bgp_unlock_node(rn); + if (is_bgp_static_route) { + SET_FLAG(bnc->flags, BGP_STATIC_ROUTE); + + /* If we're toggling the type, re-register */ + if ((bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)) + && !CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)) { + SET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH); + UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); + UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID); + } else if ((!bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)) + && CHECK_FLAG(bnc->flags, + BGP_STATIC_ROUTE_EXACT_MATCH)) { + UNSET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH); + UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); + UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID); + } } - else if ((!bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)) && - CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)) - { - UNSET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH); - UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); - UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID); + /* When nexthop is already known, but now requires 'connected' + * resolution, + * re-register it. The reverse scenario where the nexthop currently + * requires + * 'connected' resolution does not need a re-register (i.e., we treat + * 'connected-required' as an override) except in the scenario where + * this + * is actually a case of tracking a peer for connectivity (e.g., after + * disable connected-check). + * NOTE: We don't track the number of paths separately for 'connected- + * required' vs 'connected-not-required' as this change is not a common + * scenario. + */ + else if (connected && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) { + SET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED); + UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); + UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID); + } else if (peer && !connected + && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) { + UNSET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED); + UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); + UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID); } - } - /* When nexthop is already known, but now requires 'connected' resolution, - * re-register it. The reverse scenario where the nexthop currently requires - * 'connected' resolution does not need a re-register (i.e., we treat - * 'connected-required' as an override) except in the scenario where this - * is actually a case of tracking a peer for connectivity (e.g., after - * disable connected-check). - * NOTE: We don't track the number of paths separately for 'connected- - * required' vs 'connected-not-required' as this change is not a common - * scenario. - */ - else if (connected && ! CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) - { - SET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED); - UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); - UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID); - } - else if (peer && !connected && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) - { - UNSET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED); - UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); - UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID); - } - if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) - { - bnc->flags |= BGP_NEXTHOP_REGISTERED; - bnc->flags |= BGP_NEXTHOP_VALID; - } - else if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED)) - register_zebra_rnh(bnc, is_bgp_static_route); - if (ri && ri->nexthop != bnc) - { - /* Unlink from existing nexthop cache, if any. This will also free - * the nexthop cache entry, if appropriate. - */ - bgp_unlink_nexthop (ri); - - path_nh_map(ri, bnc, 1); /* updates NHT ri list reference */ - - if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric) - (bgp_info_extra_get(ri))->igpmetric = bnc->metric; - else if (ri->extra) - ri->extra->igpmetric = 0; - } - else if (peer) - bnc->nht_info = (void *)peer; /* NHT peer reference */ - - /* - * We are cheating here. Views have no associated underlying - * ability to detect nexthops. So when we have a view - * just tell everyone the nexthop is valid - */ - if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) - return 1; - else - return (bgp_isvalid_nexthop(bnc)); + if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) { + bnc->flags |= BGP_NEXTHOP_REGISTERED; + bnc->flags |= BGP_NEXTHOP_VALID; + } else if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED)) + register_zebra_rnh(bnc, is_bgp_static_route); + if (ri && ri->nexthop != bnc) { + /* Unlink from existing nexthop cache, if any. This will also + * free + * the nexthop cache entry, if appropriate. + */ + bgp_unlink_nexthop(ri); + + path_nh_map(ri, bnc, 1); /* updates NHT ri list reference */ + + if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric) + (bgp_info_extra_get(ri))->igpmetric = bnc->metric; + else if (ri->extra) + ri->extra->igpmetric = 0; + } else if (peer) + bnc->nht_info = (void *)peer; /* NHT peer reference */ + + /* + * We are cheating here. Views have no associated underlying + * ability to detect nexthops. So when we have a view + * just tell everyone the nexthop is valid + */ + if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) + return 1; + else + return (bgp_isvalid_nexthop(bnc)); } -void -bgp_delete_connected_nexthop (afi_t afi, struct peer *peer) +void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer) { - struct bgp_node *rn; - struct bgp_nexthop_cache *bnc; - struct prefix p; - - if (!peer) - return; - - /* We don't register link local address for NHT */ - if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&peer->su.sin6.sin6_addr)) - return; - - if (! sockunion2hostprefix (&peer->su, &p)) - return; - - rn = bgp_node_lookup(peer->bgp->nexthop_cache_table[family2afi(p.family)], &p); - if (!rn || !rn->info) - { - if (BGP_DEBUG(nht, NHT)) - zlog_debug("Cannot find connected NHT node for peer %s", peer->host); - if (rn) - bgp_unlock_node (rn); - return; - } - - bnc = rn->info; - bgp_unlock_node(rn); - - if (bnc->nht_info != peer) - { - if (BGP_DEBUG(nht, NHT)) - zlog_debug("Connected NHT %p node for peer %s points to %p", - bnc, peer->host, bnc->nht_info); - return; - } - - bnc->nht_info = NULL; - - if (LIST_EMPTY(&(bnc->paths))) - { - if (BGP_DEBUG(nht, NHT)) - zlog_debug("Freeing connected NHT node %p for peer %s", - bnc, peer->host); - unregister_zebra_rnh(bnc, 0); - bnc->node->info = NULL; - bgp_unlock_node(bnc->node); - bnc_free(bnc); - } + struct bgp_node *rn; + struct bgp_nexthop_cache *bnc; + struct prefix p; + + if (!peer) + return; + + /* We don't register link local address for NHT */ + if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr)) + return; + + if (!sockunion2hostprefix(&peer->su, &p)) + return; + + rn = bgp_node_lookup( + peer->bgp->nexthop_cache_table[family2afi(p.family)], &p); + if (!rn || !rn->info) { + if (BGP_DEBUG(nht, NHT)) + zlog_debug("Cannot find connected NHT node for peer %s", + peer->host); + if (rn) + bgp_unlock_node(rn); + return; + } + + bnc = rn->info; + bgp_unlock_node(rn); + + if (bnc->nht_info != peer) { + if (BGP_DEBUG(nht, NHT)) + zlog_debug( + "Connected NHT %p node for peer %s points to %p", + bnc, peer->host, bnc->nht_info); + return; + } + + bnc->nht_info = NULL; + + if (LIST_EMPTY(&(bnc->paths))) { + if (BGP_DEBUG(nht, NHT)) + zlog_debug("Freeing connected NHT node %p for peer %s", + bnc, peer->host); + unregister_zebra_rnh(bnc, 0); + bnc->node->info = NULL; + bgp_unlock_node(bnc->node); + bnc_free(bnc); + } } -void -bgp_parse_nexthop_update (int command, vrf_id_t vrf_id) +void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id) { - struct stream *s; - struct bgp_node *rn = NULL; - struct bgp_nexthop_cache *bnc; - struct nexthop *nexthop; - struct nexthop *oldnh; - struct nexthop *nhlist_head = NULL; - struct nexthop *nhlist_tail = NULL; - uint32_t metric; - u_char nexthop_num; - struct prefix p; - int i; - struct bgp *bgp; - - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - { - zlog_err("parse nexthop update: instance not found for vrf_id %d", vrf_id); - return; - } - - s = zclient->ibuf; - - memset(&p, 0, sizeof(struct prefix)); - p.family = stream_getw(s); - p.prefixlen = stream_getc(s); - switch (p.family) - { - case AF_INET: - p.u.prefix4.s_addr = stream_get_ipv4 (s); - break; - case AF_INET6: - stream_get(&p.u.prefix6, s, 16); - break; - default: - break; - } - - if (command == ZEBRA_NEXTHOP_UPDATE) - rn = bgp_node_lookup(bgp->nexthop_cache_table[family2afi(p.family)], &p); - else if (command == ZEBRA_IMPORT_CHECK_UPDATE) - rn = bgp_node_lookup(bgp->import_check_table[family2afi(p.family)], &p); - - if (!rn || !rn->info) - { - if (BGP_DEBUG(nht, NHT)) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str(&p, buf, sizeof(buf)); - zlog_debug("parse nexthop update(%s): rn not found", buf); + struct stream *s; + struct bgp_node *rn = NULL; + struct bgp_nexthop_cache *bnc; + struct nexthop *nexthop; + struct nexthop *oldnh; + struct nexthop *nhlist_head = NULL; + struct nexthop *nhlist_tail = NULL; + uint32_t metric; + u_char nexthop_num; + struct prefix p; + int i; + struct bgp *bgp; + + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) { + zlog_err( + "parse nexthop update: instance not found for vrf_id %d", + vrf_id); + return; } - if (rn) - bgp_unlock_node (rn); - return; - } - - bnc = rn->info; - bgp_unlock_node (rn); - bnc->last_update = bgp_clock(); - bnc->change_flags = 0; - stream_getc (s); // Distance but not currently used - metric = stream_getl (s); - nexthop_num = stream_getc (s); - - /* debug print the input */ - if (BGP_DEBUG(nht, NHT)) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str(&p, buf, sizeof (buf)); - zlog_debug("%d: Rcvd NH update %s - metric %d/%d #nhops %d/%d flags 0x%x", - vrf_id, buf, metric, bnc->metric, nexthop_num, bnc->nexthop_num, - bnc->flags); - } - - if (metric != bnc->metric) - bnc->change_flags |= BGP_NEXTHOP_METRIC_CHANGED; - - if(nexthop_num != bnc->nexthop_num) - bnc->change_flags |= BGP_NEXTHOP_CHANGED; - - if (nexthop_num) - { - /* notify bgp fsm if nbr ip goes from invalid->valid */ - if (!bnc->nexthop_num) - UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED); - - bnc->flags |= BGP_NEXTHOP_VALID; - bnc->metric = metric; - bnc->nexthop_num = nexthop_num; - - for (i = 0; i < nexthop_num; i++) - { - nexthop = nexthop_new(); - nexthop->type = stream_getc (s); - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); - nexthop->ifindex = stream_getl (s); - break; - case NEXTHOP_TYPE_IFINDEX: - nexthop->ifindex = stream_getl (s); - break; - case NEXTHOP_TYPE_IPV4_IFINDEX: - nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); - nexthop->ifindex = stream_getl (s); - break; - case NEXTHOP_TYPE_IPV6: - stream_get (&nexthop->gate.ipv6, s, 16); - nexthop->ifindex = stream_getl (s); - break; - case NEXTHOP_TYPE_IPV6_IFINDEX: - stream_get (&nexthop->gate.ipv6, s, 16); - nexthop->ifindex = stream_getl (s); - break; - default: - /* do nothing */ - break; - } - - if (BGP_DEBUG(nht, NHT)) - { - char buf[NEXTHOP_STRLEN]; - zlog_debug(" nhop via %s", - nexthop2str (nexthop, buf, sizeof (buf))); - } - - if (nhlist_tail) - { - nhlist_tail->next = nexthop; - nhlist_tail = nexthop; - } - else - { - nhlist_tail = nexthop; - nhlist_head = nexthop; - } - - /* No need to evaluate the nexthop if we have already determined - * that there has been a change. - */ - if (bnc->change_flags & BGP_NEXTHOP_CHANGED) - continue; - - for (oldnh = bnc->nexthop; oldnh; oldnh = oldnh->next) - if (nexthop_same_no_recurse(oldnh, nexthop)) - break; - - if (!oldnh) - bnc->change_flags |= BGP_NEXTHOP_CHANGED; + + s = zclient->ibuf; + + memset(&p, 0, sizeof(struct prefix)); + p.family = stream_getw(s); + p.prefixlen = stream_getc(s); + switch (p.family) { + case AF_INET: + p.u.prefix4.s_addr = stream_get_ipv4(s); + break; + case AF_INET6: + stream_get(&p.u.prefix6, s, 16); + break; + default: + break; + } + + if (command == ZEBRA_NEXTHOP_UPDATE) + rn = bgp_node_lookup( + bgp->nexthop_cache_table[family2afi(p.family)], &p); + else if (command == ZEBRA_IMPORT_CHECK_UPDATE) + rn = bgp_node_lookup( + bgp->import_check_table[family2afi(p.family)], &p); + + if (!rn || !rn->info) { + if (BGP_DEBUG(nht, NHT)) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&p, buf, sizeof(buf)); + zlog_debug("parse nexthop update(%s): rn not found", + buf); + } + if (rn) + bgp_unlock_node(rn); + return; } - bnc_nexthop_free(bnc); - bnc->nexthop = nhlist_head; - } - else - { - bnc->flags &= ~BGP_NEXTHOP_VALID; - bnc->nexthop_num = nexthop_num; - - /* notify bgp fsm if nbr ip goes from valid->invalid */ - UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED); - - bnc_nexthop_free(bnc); - bnc->nexthop = NULL; - } - - evaluate_paths(bnc); + + bnc = rn->info; + bgp_unlock_node(rn); + bnc->last_update = bgp_clock(); + bnc->change_flags = 0; + stream_getc(s); // Distance but not currently used + metric = stream_getl(s); + nexthop_num = stream_getc(s); + + /* debug print the input */ + if (BGP_DEBUG(nht, NHT)) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&p, buf, sizeof(buf)); + zlog_debug( + "%d: Rcvd NH update %s - metric %d/%d #nhops %d/%d flags 0x%x", + vrf_id, buf, metric, bnc->metric, nexthop_num, + bnc->nexthop_num, bnc->flags); + } + + if (metric != bnc->metric) + bnc->change_flags |= BGP_NEXTHOP_METRIC_CHANGED; + + if (nexthop_num != bnc->nexthop_num) + bnc->change_flags |= BGP_NEXTHOP_CHANGED; + + if (nexthop_num) { + /* notify bgp fsm if nbr ip goes from invalid->valid */ + if (!bnc->nexthop_num) + UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED); + + bnc->flags |= BGP_NEXTHOP_VALID; + bnc->metric = metric; + bnc->nexthop_num = nexthop_num; + + for (i = 0; i < nexthop_num; i++) { + nexthop = nexthop_new(); + nexthop->type = stream_getc(s); + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + nexthop->gate.ipv4.s_addr = stream_get_ipv4(s); + nexthop->ifindex = stream_getl(s); + break; + case NEXTHOP_TYPE_IFINDEX: + nexthop->ifindex = stream_getl(s); + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + nexthop->gate.ipv4.s_addr = stream_get_ipv4(s); + nexthop->ifindex = stream_getl(s); + break; + case NEXTHOP_TYPE_IPV6: + stream_get(&nexthop->gate.ipv6, s, 16); + nexthop->ifindex = stream_getl(s); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + stream_get(&nexthop->gate.ipv6, s, 16); + nexthop->ifindex = stream_getl(s); + break; + default: + /* do nothing */ + break; + } + + if (BGP_DEBUG(nht, NHT)) { + char buf[NEXTHOP_STRLEN]; + zlog_debug( + " nhop via %s", + nexthop2str(nexthop, buf, sizeof(buf))); + } + + if (nhlist_tail) { + nhlist_tail->next = nexthop; + nhlist_tail = nexthop; + } else { + nhlist_tail = nexthop; + nhlist_head = nexthop; + } + + /* No need to evaluate the nexthop if we have already + * determined + * that there has been a change. + */ + if (bnc->change_flags & BGP_NEXTHOP_CHANGED) + continue; + + for (oldnh = bnc->nexthop; oldnh; oldnh = oldnh->next) + if (nexthop_same_no_recurse(oldnh, nexthop)) + break; + + if (!oldnh) + bnc->change_flags |= BGP_NEXTHOP_CHANGED; + } + bnc_nexthop_free(bnc); + bnc->nexthop = nhlist_head; + } else { + bnc->flags &= ~BGP_NEXTHOP_VALID; + bnc->nexthop_num = nexthop_num; + + /* notify bgp fsm if nbr ip goes from valid->invalid */ + UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED); + + bnc_nexthop_free(bnc); + bnc->nexthop = NULL; + } + + evaluate_paths(bnc); } /** * make_prefix - make a prefix structure from the path (essentially * path's node. */ -static int -make_prefix (int afi, struct bgp_info *ri, struct prefix *p) +static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p) { - int is_bgp_static = ((ri->type == ZEBRA_ROUTE_BGP) && - (ri->sub_type == BGP_ROUTE_STATIC)) ? 1 : 0; - - memset (p, 0, sizeof (struct prefix)); - switch (afi) - { - case AFI_IP: - p->family = AF_INET; - if (is_bgp_static) - { - p->u.prefix4 = ri->net->p.u.prefix4; - p->prefixlen = ri->net->p.prefixlen; - } - else - { - p->u.prefix4 = ri->attr->nexthop; - p->prefixlen = IPV4_MAX_BITLEN; - } - break; - case AFI_IP6: - /* We don't register link local NH */ - if (ri->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL - || IN6_IS_ADDR_LINKLOCAL (&ri->attr->mp_nexthop_global)) - return -1; - - p->family = AF_INET6; - - if (is_bgp_static) - { - p->u.prefix6 = ri->net->p.u.prefix6; - p->prefixlen = ri->net->p.prefixlen; - } - else - { - p->u.prefix6 = ri->attr->mp_nexthop_global; - p->prefixlen = IPV6_MAX_BITLEN; - } - break; - default: - if (BGP_DEBUG(nht, NHT)) - { - zlog_debug("%s: Attempting to make prefix with unknown AFI %d (not %d or %d)", - __FUNCTION__, afi, AFI_IP, AFI_IP6); + int is_bgp_static = ((ri->type == ZEBRA_ROUTE_BGP) + && (ri->sub_type == BGP_ROUTE_STATIC)) + ? 1 + : 0; + + memset(p, 0, sizeof(struct prefix)); + switch (afi) { + case AFI_IP: + p->family = AF_INET; + if (is_bgp_static) { + p->u.prefix4 = ri->net->p.u.prefix4; + p->prefixlen = ri->net->p.prefixlen; + } else { + p->u.prefix4 = ri->attr->nexthop; + p->prefixlen = IPV4_MAX_BITLEN; + } + break; + case AFI_IP6: + /* We don't register link local NH */ + if (ri->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL + || IN6_IS_ADDR_LINKLOCAL(&ri->attr->mp_nexthop_global)) + return -1; + + p->family = AF_INET6; + + if (is_bgp_static) { + p->u.prefix6 = ri->net->p.u.prefix6; + p->prefixlen = ri->net->p.prefixlen; + } else { + p->u.prefix6 = ri->attr->mp_nexthop_global; + p->prefixlen = IPV6_MAX_BITLEN; + } + break; + default: + if (BGP_DEBUG(nht, NHT)) { + zlog_debug( + "%s: Attempting to make prefix with unknown AFI %d (not %d or %d)", + __FUNCTION__, afi, AFI_IP, AFI_IP6); + } + break; } - break; - } - return 0; + return 0; } /** @@ -569,58 +542,56 @@ make_prefix (int afi, struct bgp_info *ri, struct prefix *p) * RETURNS: * void. */ -static void -sendmsg_zebra_rnh (struct bgp_nexthop_cache *bnc, int command) +static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command) { - struct stream *s; - struct prefix *p; - int ret; - - /* Check socket. */ - if (!zclient || zclient->sock < 0) - return; - - /* Don't try to register if Zebra doesn't know of this instance. */ - if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bnc->bgp)) - return; - - p = &(bnc->node->p); - s = zclient->obuf; - stream_reset (s); - zclient_create_header (s, command, bnc->bgp->vrf_id); - if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED) || - CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)) - stream_putc(s, 1); - else - stream_putc(s, 0); - - stream_putw(s, PREFIX_FAMILY(p)); - stream_putc(s, p->prefixlen); - switch (PREFIX_FAMILY(p)) - { - case AF_INET: - stream_put_in_addr (s, &p->u.prefix4); - break; - case AF_INET6: - stream_put(s, &(p->u.prefix6), 16); - break; - default: - break; - } - stream_putw_at (s, 0, stream_get_endp (s)); - - ret = zclient_send_message(zclient); - /* TBD: handle the failure */ - if (ret < 0) - zlog_warn("sendmsg_nexthop: zclient_send_message() failed"); - - if ((command == ZEBRA_NEXTHOP_REGISTER) || - (command == ZEBRA_IMPORT_ROUTE_REGISTER)) - SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); - else if ((command == ZEBRA_NEXTHOP_UNREGISTER) || - (command == ZEBRA_IMPORT_ROUTE_UNREGISTER)) - UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); - return; + struct stream *s; + struct prefix *p; + int ret; + + /* Check socket. */ + if (!zclient || zclient->sock < 0) + return; + + /* Don't try to register if Zebra doesn't know of this instance. */ + if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bnc->bgp)) + return; + + p = &(bnc->node->p); + s = zclient->obuf; + stream_reset(s); + zclient_create_header(s, command, bnc->bgp->vrf_id); + if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED) + || CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)) + stream_putc(s, 1); + else + stream_putc(s, 0); + + stream_putw(s, PREFIX_FAMILY(p)); + stream_putc(s, p->prefixlen); + switch (PREFIX_FAMILY(p)) { + case AF_INET: + stream_put_in_addr(s, &p->u.prefix4); + break; + case AF_INET6: + stream_put(s, &(p->u.prefix6), 16); + break; + default: + break; + } + stream_putw_at(s, 0, stream_get_endp(s)); + + ret = zclient_send_message(zclient); + /* TBD: handle the failure */ + if (ret < 0) + zlog_warn("sendmsg_nexthop: zclient_send_message() failed"); + + if ((command == ZEBRA_NEXTHOP_REGISTER) + || (command == ZEBRA_IMPORT_ROUTE_REGISTER)) + SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); + else if ((command == ZEBRA_NEXTHOP_UNREGISTER) + || (command == ZEBRA_IMPORT_ROUTE_UNREGISTER)) + UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); + return; } /** @@ -631,16 +602,16 @@ sendmsg_zebra_rnh (struct bgp_nexthop_cache *bnc, int command) * RETURNS: * void. */ -static void -register_zebra_rnh (struct bgp_nexthop_cache *bnc, int is_bgp_import_route) +static void register_zebra_rnh(struct bgp_nexthop_cache *bnc, + int is_bgp_import_route) { - /* Check if we have already registered */ - if (bnc->flags & BGP_NEXTHOP_REGISTERED) - return; - if (is_bgp_import_route) - sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_REGISTER); - else - sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_REGISTER); + /* Check if we have already registered */ + if (bnc->flags & BGP_NEXTHOP_REGISTERED) + return; + if (is_bgp_import_route) + sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_REGISTER); + else + sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_REGISTER); } /** @@ -650,17 +621,17 @@ register_zebra_rnh (struct bgp_nexthop_cache *bnc, int is_bgp_import_route) * RETURNS: * void. */ -static void -unregister_zebra_rnh (struct bgp_nexthop_cache *bnc, int is_bgp_import_route) +static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc, + int is_bgp_import_route) { - /* Check if we have already registered */ - if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED)) - return; - - if (is_bgp_import_route) - sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_UNREGISTER); - else - sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_UNREGISTER); + /* Check if we have already registered */ + if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED)) + return; + + if (is_bgp_import_route) + sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_UNREGISTER); + else + sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_UNREGISTER); } /** @@ -670,78 +641,76 @@ unregister_zebra_rnh (struct bgp_nexthop_cache *bnc, int is_bgp_import_route) * RETURNS: * void. */ -static void -evaluate_paths (struct bgp_nexthop_cache *bnc) +static void evaluate_paths(struct bgp_nexthop_cache *bnc) { - struct bgp_node *rn; - struct bgp_info *path; - struct bgp *bgp = bnc->bgp; - int afi; - struct peer *peer = (struct peer *)bnc->nht_info; - struct bgp_table *table; - safi_t safi; - - if (BGP_DEBUG(nht, NHT)) - { - char buf[PREFIX2STR_BUFFER]; - bnc_str(bnc, buf, PREFIX2STR_BUFFER); - zlog_debug("NH update for %s - flags 0x%x chgflags 0x%x - evaluate paths", - buf, bnc->flags, bnc->change_flags); - } - - LIST_FOREACH(path, &(bnc->paths), nh_thread) - { - if (!(path->type == ZEBRA_ROUTE_BGP && - ((path->sub_type == BGP_ROUTE_NORMAL) || - (path->sub_type == BGP_ROUTE_STATIC)))) - continue; - - rn = path->net; - assert (rn && bgp_node_table (rn)); - afi = family2afi(rn->p.family); - table = bgp_node_table (rn); - safi = table->safi; - - /* Path becomes valid/invalid depending on whether the nexthop - * reachable/unreachable. - */ - if ((CHECK_FLAG(path->flags, BGP_INFO_VALID) ? 1 : 0) != - (bgp_isvalid_nexthop(bnc) ? 1 : 0)) - { - if (CHECK_FLAG (path->flags, BGP_INFO_VALID)) - { - bgp_aggregate_decrement (bgp, &rn->p, path, afi, safi); - bgp_info_unset_flag (rn, path, BGP_INFO_VALID); - } - else - { - bgp_info_set_flag (rn, path, BGP_INFO_VALID); - bgp_aggregate_increment (bgp, &rn->p, path, afi, safi); - } + struct bgp_node *rn; + struct bgp_info *path; + struct bgp *bgp = bnc->bgp; + int afi; + struct peer *peer = (struct peer *)bnc->nht_info; + struct bgp_table *table; + safi_t safi; + + if (BGP_DEBUG(nht, NHT)) { + char buf[PREFIX2STR_BUFFER]; + bnc_str(bnc, buf, PREFIX2STR_BUFFER); + zlog_debug( + "NH update for %s - flags 0x%x chgflags 0x%x - evaluate paths", + buf, bnc->flags, bnc->change_flags); } - /* Copy the metric to the path. Will be used for bestpath computation */ - if (bgp_isvalid_nexthop(bnc) && bnc->metric) - (bgp_info_extra_get(path))->igpmetric = bnc->metric; - else if (path->extra) - path->extra->igpmetric = 0; - - if (CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED) || - CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED)) - SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED); - - bgp_process(bgp, rn, afi, safi); - } + LIST_FOREACH(path, &(bnc->paths), nh_thread) + { + if (!(path->type == ZEBRA_ROUTE_BGP + && ((path->sub_type == BGP_ROUTE_NORMAL) + || (path->sub_type == BGP_ROUTE_STATIC)))) + continue; + + rn = path->net; + assert(rn && bgp_node_table(rn)); + afi = family2afi(rn->p.family); + table = bgp_node_table(rn); + safi = table->safi; + + /* Path becomes valid/invalid depending on whether the nexthop + * reachable/unreachable. + */ + if ((CHECK_FLAG(path->flags, BGP_INFO_VALID) ? 1 : 0) + != (bgp_isvalid_nexthop(bnc) ? 1 : 0)) { + if (CHECK_FLAG(path->flags, BGP_INFO_VALID)) { + bgp_aggregate_decrement(bgp, &rn->p, path, afi, + safi); + bgp_info_unset_flag(rn, path, BGP_INFO_VALID); + } else { + bgp_info_set_flag(rn, path, BGP_INFO_VALID); + bgp_aggregate_increment(bgp, &rn->p, path, afi, + safi); + } + } + + /* Copy the metric to the path. Will be used for bestpath + * computation */ + if (bgp_isvalid_nexthop(bnc) && bnc->metric) + (bgp_info_extra_get(path))->igpmetric = bnc->metric; + else if (path->extra) + path->extra->igpmetric = 0; + + if (CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED) + || CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED)) + SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED); + + bgp_process(bgp, rn, afi, safi); + } - if (peer && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED)) - { - if (BGP_DEBUG(nht, NHT)) - zlog_debug("%s: Updating peer (%s) status with NHT", __FUNCTION__, peer->host); - bgp_fsm_nht_update(peer, bgp_isvalid_nexthop(bnc)); - SET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED); - } + if (peer && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED)) { + if (BGP_DEBUG(nht, NHT)) + zlog_debug("%s: Updating peer (%s) status with NHT", + __FUNCTION__, peer->host); + bgp_fsm_nht_update(peer, bgp_isvalid_nexthop(bnc)); + SET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED); + } - RESET_FLAG(bnc->change_flags); + RESET_FLAG(bnc->change_flags); } /** @@ -752,19 +721,17 @@ evaluate_paths (struct bgp_nexthop_cache *bnc) * make - if set, make the association. if unset, just break the existing * association. */ -static void -path_nh_map (struct bgp_info *path, struct bgp_nexthop_cache *bnc, int make) +static void path_nh_map(struct bgp_info *path, struct bgp_nexthop_cache *bnc, + int make) { - if (path->nexthop) - { - LIST_REMOVE(path, nh_thread); - path->nexthop->path_count--; - path->nexthop = NULL; - } - if (make) - { - LIST_INSERT_HEAD(&(bnc->paths), path, nh_thread); - path->nexthop = bnc; - path->nexthop->path_count++; - } + if (path->nexthop) { + LIST_REMOVE(path, nh_thread); + path->nexthop->path_count--; + path->nexthop = NULL; + } + if (make) { + LIST_INSERT_HEAD(&(bnc->paths), path, nh_thread); + path->nexthop = bnc; + path->nexthop->path_count++; + } } diff --git a/bgpd/bgp_nht.h b/bgpd/bgp_nht.h index 3497dc856..f649bb225 100644 --- a/bgpd/bgp_nht.h +++ b/bgpd/bgp_nht.h @@ -45,8 +45,8 @@ extern int bgp_find_nexthop(struct bgp_info *p, int connected); * peer - The BGP peer associated with this NHT * connected - True if NH MUST be a connected route */ -extern int bgp_find_or_add_nexthop(struct bgp *bgp, afi_t a, - struct bgp_info *p, struct peer *peer, int connected); +extern int bgp_find_or_add_nexthop(struct bgp *bgp, afi_t a, struct bgp_info *p, + struct peer *peer, int connected); /** * bgp_unlink_nexthop() - Unlink the nexthop object from the path structure. @@ -54,7 +54,7 @@ extern int bgp_find_or_add_nexthop(struct bgp *bgp, afi_t a, * p - path structure. */ extern void bgp_unlink_nexthop(struct bgp_info *p); -void bgp_unlink_nexthop_by_peer (struct peer *); +void bgp_unlink_nexthop_by_peer(struct peer *); /** * bgp_delete_connected_nexthop() - Reset the 'peer' pointer for a connected @@ -64,6 +64,6 @@ void bgp_unlink_nexthop_by_peer (struct peer *); * afi - afi: AFI_IP or AF_IP6 * peer - Ptr to peer */ -extern void bgp_delete_connected_nexthop (afi_t afi, struct peer *peer); +extern void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer); #endif /* _BGP_NHT_H */ diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index d6ed441df..b18a4b7c4 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -51,690 +51,711 @@ Next, if we send capability to the peer we want to set my capabilty inforation at each peer. */ -void -bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, json_object *json_neigh) +void bgp_capability_vty_out(struct vty *vty, struct peer *peer, u_char use_json, + json_object *json_neigh) { - char *pnt; - char *end; - struct capability_mp_data mpc; - struct capability_header *hdr; - json_object *json_cap = NULL; - - if (use_json) - json_cap = json_object_new_object(); - - pnt = peer->notify.data; - end = pnt + peer->notify.length; - - while (pnt < end) - { - if (pnt + sizeof (struct capability_mp_data) + 2 > end) - return; - - hdr = (struct capability_header *)pnt; - if (pnt + hdr->length + 2 > end) - return; - - memcpy (&mpc, pnt + 2, sizeof(struct capability_mp_data)); - - if (hdr->code == CAPABILITY_CODE_MP) - { - afi_t afi; - safi_t safi; - - bgp_map_afi_safi_iana2int (ntohs(mpc.afi), mpc.safi, &afi, &safi); - if (use_json) - { - switch (afi) - { - case AFI_IP: - json_object_string_add(json_cap, "capabilityErrorMultiProtocolAfi", "IPv4"); - break; - case AFI_IP6: - json_object_string_add(json_cap, "capabilityErrorMultiProtocolAfi", "IPv6"); - break; - case AFI_L2VPN: - json_object_string_add(json_cap, "capabilityErrorMultiProtocolAfi", "L2VPN"); - break; - default: - json_object_int_add(json_cap, "capabilityErrorMultiProtocolAfiUnknown", ntohs (mpc.afi)); - break; - } - switch (safi) - { - case SAFI_UNICAST: - json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "unicast"); - break; - case SAFI_MULTICAST: - json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "multicast"); - break; - case SAFI_LABELED_UNICAST: - json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "labeled-unicast"); - break; - case SAFI_MPLS_VPN: - json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "MPLS-labeled VPN"); - break; - case SAFI_ENCAP: - json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "encap"); - break; - case SAFI_EVPN: - json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "EVPN"); - break; - default: - json_object_int_add(json_cap, "capabilityErrorMultiProtocolSafiUnknown", mpc.safi); - break; - } - } - else - { - vty_out (vty, " Capability error for: Multi protocol "); - switch (afi) - { - case AFI_IP: - vty_out (vty, "AFI IPv4, "); - break; - case AFI_IP6: - vty_out (vty, "AFI IPv6, "); - break; - case AFI_L2VPN: - vty_out (vty, "AFI L2VPN, "); - break; - default: - vty_out (vty, "AFI Unknown %d, ", ntohs (mpc.afi)); - break; - } - switch (safi) - { - case SAFI_UNICAST: - vty_out (vty, "SAFI Unicast"); - break; - case SAFI_MULTICAST: - vty_out (vty, "SAFI Multicast"); - break; - case SAFI_LABELED_UNICAST: - vty_out (vty, "SAFI Labeled-unicast"); - break; - case SAFI_MPLS_VPN: - vty_out (vty, "SAFI MPLS-labeled VPN"); - break; - case SAFI_ENCAP: - vty_out (vty, "SAFI ENCAP"); - break; - case SAFI_EVPN: - vty_out (vty, "SAFI EVPN"); - break; - default: - vty_out (vty, "SAFI Unknown %d ", mpc.safi); - break; - } - vty_out (vty, "\n"); - } - } - else if (hdr->code >= 128) - { - if (use_json) - json_object_int_add(json_cap, "capabilityErrorVendorSpecificCapabilityCode", hdr->code); - else - vty_out (vty, " Capability error: vendor specific capability code %d", - hdr->code); - } - else - { - if (use_json) - json_object_int_add(json_cap, "capabilityErrorUnknownCapabilityCode", hdr->code); - else - vty_out (vty, " Capability error: unknown capability code %d", - hdr->code); - } - pnt += hdr->length + 2; - } - if (use_json) - json_object_object_add(json_neigh, "capabilityErrors", json_cap); + char *pnt; + char *end; + struct capability_mp_data mpc; + struct capability_header *hdr; + json_object *json_cap = NULL; + + if (use_json) + json_cap = json_object_new_object(); + + pnt = peer->notify.data; + end = pnt + peer->notify.length; + + while (pnt < end) { + if (pnt + sizeof(struct capability_mp_data) + 2 > end) + return; + + hdr = (struct capability_header *)pnt; + if (pnt + hdr->length + 2 > end) + return; + + memcpy(&mpc, pnt + 2, sizeof(struct capability_mp_data)); + + if (hdr->code == CAPABILITY_CODE_MP) { + afi_t afi; + safi_t safi; + + bgp_map_afi_safi_iana2int(ntohs(mpc.afi), mpc.safi, + &afi, &safi); + if (use_json) { + switch (afi) { + case AFI_IP: + json_object_string_add( + json_cap, + "capabilityErrorMultiProtocolAfi", + "IPv4"); + break; + case AFI_IP6: + json_object_string_add( + json_cap, + "capabilityErrorMultiProtocolAfi", + "IPv6"); + break; + case AFI_L2VPN: + json_object_string_add( + json_cap, + "capabilityErrorMultiProtocolAfi", + "L2VPN"); + break; + default: + json_object_int_add( + json_cap, + "capabilityErrorMultiProtocolAfiUnknown", + ntohs(mpc.afi)); + break; + } + switch (safi) { + case SAFI_UNICAST: + json_object_string_add( + json_cap, + "capabilityErrorMultiProtocolSafi", + "unicast"); + break; + case SAFI_MULTICAST: + json_object_string_add( + json_cap, + "capabilityErrorMultiProtocolSafi", + "multicast"); + break; + case SAFI_LABELED_UNICAST: + json_object_string_add( + json_cap, + "capabilityErrorMultiProtocolSafi", + "labeled-unicast"); + break; + case SAFI_MPLS_VPN: + json_object_string_add( + json_cap, + "capabilityErrorMultiProtocolSafi", + "MPLS-labeled VPN"); + break; + case SAFI_ENCAP: + json_object_string_add( + json_cap, + "capabilityErrorMultiProtocolSafi", + "encap"); + break; + case SAFI_EVPN: + json_object_string_add( + json_cap, + "capabilityErrorMultiProtocolSafi", + "EVPN"); + break; + default: + json_object_int_add( + json_cap, + "capabilityErrorMultiProtocolSafiUnknown", + mpc.safi); + break; + } + } else { + vty_out(vty, + " Capability error for: Multi protocol "); + switch (afi) { + case AFI_IP: + vty_out(vty, "AFI IPv4, "); + break; + case AFI_IP6: + vty_out(vty, "AFI IPv6, "); + break; + case AFI_L2VPN: + vty_out(vty, "AFI L2VPN, "); + break; + default: + vty_out(vty, "AFI Unknown %d, ", + ntohs(mpc.afi)); + break; + } + switch (safi) { + case SAFI_UNICAST: + vty_out(vty, "SAFI Unicast"); + break; + case SAFI_MULTICAST: + vty_out(vty, "SAFI Multicast"); + break; + case SAFI_LABELED_UNICAST: + vty_out(vty, "SAFI Labeled-unicast"); + break; + case SAFI_MPLS_VPN: + vty_out(vty, "SAFI MPLS-labeled VPN"); + break; + case SAFI_ENCAP: + vty_out(vty, "SAFI ENCAP"); + break; + case SAFI_EVPN: + vty_out(vty, "SAFI EVPN"); + break; + default: + vty_out(vty, "SAFI Unknown %d ", + mpc.safi); + break; + } + vty_out(vty, "\n"); + } + } else if (hdr->code >= 128) { + if (use_json) + json_object_int_add( + json_cap, + "capabilityErrorVendorSpecificCapabilityCode", + hdr->code); + else + vty_out(vty, + " Capability error: vendor specific capability code %d", + hdr->code); + } else { + if (use_json) + json_object_int_add( + json_cap, + "capabilityErrorUnknownCapabilityCode", + hdr->code); + else + vty_out(vty, + " Capability error: unknown capability code %d", + hdr->code); + } + pnt += hdr->length + 2; + } + if (use_json) + json_object_object_add(json_neigh, "capabilityErrors", + json_cap); } -static void -bgp_capability_mp_data (struct stream *s, struct capability_mp_data *mpc) +static void bgp_capability_mp_data(struct stream *s, + struct capability_mp_data *mpc) { - mpc->afi = stream_getw (s); - mpc->reserved = stream_getc (s); - mpc->safi = stream_getc (s); + mpc->afi = stream_getw(s); + mpc->reserved = stream_getc(s); + mpc->safi = stream_getc(s); } /* Set negotiated capability value. */ -static int -bgp_capability_mp (struct peer *peer, struct capability_header *hdr) +static int bgp_capability_mp(struct peer *peer, struct capability_header *hdr) { - struct capability_mp_data mpc; - struct stream *s = BGP_INPUT (peer); - afi_t afi; - safi_t safi; - - /* Verify length is 4 */ - if (hdr->length != 4) - { - zlog_warn("MP Cap: Received invalid length %d, non-multiple of 4", - hdr->length); - return -1; - } - - bgp_capability_mp_data (s, &mpc); - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u", - peer->host, mpc.afi, mpc.safi); - - /* Convert AFI, SAFI to internal values, check. */ - if (bgp_map_afi_safi_iana2int (mpc.afi, mpc.safi, &afi, &safi)) - return -1; - - /* Now safi remapped, and afi/safi are valid array indices */ - peer->afc_recv[afi][safi] = 1; - - if (peer->afc[afi][safi]) - peer->afc_nego[afi][safi] = 1; - else - return -1; - - return 0; + struct capability_mp_data mpc; + struct stream *s = BGP_INPUT(peer); + afi_t afi; + safi_t safi; + + /* Verify length is 4 */ + if (hdr->length != 4) { + zlog_warn( + "MP Cap: Received invalid length %d, non-multiple of 4", + hdr->length); + return -1; + } + + bgp_capability_mp_data(s, &mpc); + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s OPEN has MP_EXT CAP for afi/safi: %u/%u", + peer->host, mpc.afi, mpc.safi); + + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_iana2int(mpc.afi, mpc.safi, &afi, &safi)) + return -1; + + /* Now safi remapped, and afi/safi are valid array indices */ + peer->afc_recv[afi][safi] = 1; + + if (peer->afc[afi][safi]) + peer->afc_nego[afi][safi] = 1; + else + return -1; + + return 0; } -static void -bgp_capability_orf_not_support (struct peer *peer, iana_afi_t afi, safi_t safi, - u_char type, u_char mode) +static void bgp_capability_orf_not_support(struct peer *peer, iana_afi_t afi, + safi_t safi, u_char type, + u_char mode) { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Addr-family %d/%d has ORF type/mode %d/%d not supported", - peer->host, afi, safi, type, mode); + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Addr-family %d/%d has ORF type/mode %d/%d not supported", + peer->host, afi, safi, type, mode); } -static const struct message orf_type_str[] = -{ - { ORF_TYPE_PREFIX, "Prefixlist" }, - { ORF_TYPE_PREFIX_OLD, "Prefixlist (old)" }, - { 0 } -}; +static const struct message orf_type_str[] = { + {ORF_TYPE_PREFIX, "Prefixlist"}, + {ORF_TYPE_PREFIX_OLD, "Prefixlist (old)"}, + {0}}; -static const struct message orf_mode_str[] = -{ - { ORF_MODE_RECEIVE, "Receive" }, - { ORF_MODE_SEND, "Send" }, - { ORF_MODE_BOTH, "Both" }, - { 0 } -}; +static const struct message orf_mode_str[] = {{ORF_MODE_RECEIVE, "Receive"}, + {ORF_MODE_SEND, "Send"}, + {ORF_MODE_BOTH, "Both"}, + {0}}; -static int -bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr) +static int bgp_capability_orf_entry(struct peer *peer, + struct capability_header *hdr) { - struct stream *s = BGP_INPUT (peer); - struct capability_mp_data mpc; - u_char num; - iana_afi_t pkt_afi; - afi_t afi; - safi_t pkt_safi, safi; - u_char type; - u_char mode; - u_int16_t sm_cap = 0; /* capability send-mode receive */ - u_int16_t rm_cap = 0; /* capability receive-mode receive */ - int i; - - /* ORF Entry header */ - bgp_capability_mp_data (s, &mpc); - num = stream_getc (s); - pkt_afi = mpc.afi; - pkt_safi = mpc.safi; - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u", - peer->host, mpc.afi, mpc.safi); - - /* Convert AFI, SAFI to internal values, check. */ - if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi)) - { - zlog_info ("%s Addr-family %d/%d not supported." - " Ignoring the ORF capability", - peer->host, pkt_afi, pkt_safi); - return 0; - } - - mpc.afi = pkt_afi; - mpc.safi = safi; - - /* validate number field */ - if (CAPABILITY_CODE_ORF_LEN + (num * 2) > hdr->length) - { - zlog_info ("%s ORF Capability entry length error," - " Cap length %u, num %u", - peer->host, hdr->length, num); - bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); - return -1; - } - - for (i = 0 ; i < num ; i++) - { - type = stream_getc(s); - mode = stream_getc(s); - - /* ORF Mode error check */ - switch (mode) - { - case ORF_MODE_BOTH: - case ORF_MODE_SEND: - case ORF_MODE_RECEIVE: - break; - default: - bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode); - continue; + struct stream *s = BGP_INPUT(peer); + struct capability_mp_data mpc; + u_char num; + iana_afi_t pkt_afi; + afi_t afi; + safi_t pkt_safi, safi; + u_char type; + u_char mode; + u_int16_t sm_cap = 0; /* capability send-mode receive */ + u_int16_t rm_cap = 0; /* capability receive-mode receive */ + int i; + + /* ORF Entry header */ + bgp_capability_mp_data(s, &mpc); + num = stream_getc(s); + pkt_afi = mpc.afi; + pkt_safi = mpc.safi; + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s ORF Cap entry for afi/safi: %u/%u", peer->host, + mpc.afi, mpc.safi); + + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) { + zlog_info( + "%s Addr-family %d/%d not supported." + " Ignoring the ORF capability", + peer->host, pkt_afi, pkt_safi); + return 0; } - /* ORF Type and afi/safi error checks */ - /* capcode versus type */ - switch (hdr->code) - { - case CAPABILITY_CODE_ORF: - switch (type) - { - case ORF_TYPE_PREFIX: - break; - default: - bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode); - continue; - } - break; - case CAPABILITY_CODE_ORF_OLD: - switch (type) - { - case ORF_TYPE_PREFIX_OLD: - break; - default: - bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode); - continue; - } - break; - default: - bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode); - continue; - } - - /* AFI vs SAFI */ - if (!((afi == AFI_IP && safi == SAFI_UNICAST) - || (afi == AFI_IP && safi == SAFI_MULTICAST) - || (afi == AFI_IP6 && safi == SAFI_UNICAST))) - { - bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode); - continue; - } - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s OPEN has %s ORF capability" - " as %s for afi/safi: %d/%d", - peer->host, lookup_msg(orf_type_str, type, NULL), - lookup_msg(orf_mode_str, mode, NULL), - pkt_afi, pkt_safi); - - if (hdr->code == CAPABILITY_CODE_ORF) - { - sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV; - rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV; - } - else if (hdr->code == CAPABILITY_CODE_ORF_OLD) - { - sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV; - rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV; - } - else - { - bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode); - continue; + + mpc.afi = pkt_afi; + mpc.safi = safi; + + /* validate number field */ + if (CAPABILITY_CODE_ORF_LEN + (num * 2) > hdr->length) { + zlog_info( + "%s ORF Capability entry length error," + " Cap length %u, num %u", + peer->host, hdr->length, num); + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_MALFORMED_ATTR); + return -1; } - switch (mode) - { - case ORF_MODE_BOTH: - SET_FLAG (peer->af_cap[afi][safi], sm_cap); - SET_FLAG (peer->af_cap[afi][safi], rm_cap); - break; - case ORF_MODE_SEND: - SET_FLAG (peer->af_cap[afi][safi], sm_cap); - break; - case ORF_MODE_RECEIVE: - SET_FLAG (peer->af_cap[afi][safi], rm_cap); - break; + for (i = 0; i < num; i++) { + type = stream_getc(s); + mode = stream_getc(s); + + /* ORF Mode error check */ + switch (mode) { + case ORF_MODE_BOTH: + case ORF_MODE_SEND: + case ORF_MODE_RECEIVE: + break; + default: + bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi, + type, mode); + continue; + } + /* ORF Type and afi/safi error checks */ + /* capcode versus type */ + switch (hdr->code) { + case CAPABILITY_CODE_ORF: + switch (type) { + case ORF_TYPE_PREFIX: + break; + default: + bgp_capability_orf_not_support( + peer, pkt_afi, pkt_safi, type, mode); + continue; + } + break; + case CAPABILITY_CODE_ORF_OLD: + switch (type) { + case ORF_TYPE_PREFIX_OLD: + break; + default: + bgp_capability_orf_not_support( + peer, pkt_afi, pkt_safi, type, mode); + continue; + } + break; + default: + bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi, + type, mode); + continue; + } + + /* AFI vs SAFI */ + if (!((afi == AFI_IP && safi == SAFI_UNICAST) + || (afi == AFI_IP && safi == SAFI_MULTICAST) + || (afi == AFI_IP6 && safi == SAFI_UNICAST))) { + bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi, + type, mode); + continue; + } + + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s OPEN has %s ORF capability" + " as %s for afi/safi: %d/%d", + peer->host, + lookup_msg(orf_type_str, type, NULL), + lookup_msg(orf_mode_str, mode, NULL), pkt_afi, + pkt_safi); + + if (hdr->code == CAPABILITY_CODE_ORF) { + sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV; + rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV; + } else if (hdr->code == CAPABILITY_CODE_ORF_OLD) { + sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV; + rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV; + } else { + bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi, + type, mode); + continue; + } + + switch (mode) { + case ORF_MODE_BOTH: + SET_FLAG(peer->af_cap[afi][safi], sm_cap); + SET_FLAG(peer->af_cap[afi][safi], rm_cap); + break; + case ORF_MODE_SEND: + SET_FLAG(peer->af_cap[afi][safi], sm_cap); + break; + case ORF_MODE_RECEIVE: + SET_FLAG(peer->af_cap[afi][safi], rm_cap); + break; + } } - } - return 0; + return 0; } -static int -bgp_capability_restart (struct peer *peer, struct capability_header *caphdr) +static int bgp_capability_restart(struct peer *peer, + struct capability_header *caphdr) { - struct stream *s = BGP_INPUT (peer); - u_int16_t restart_flag_time; - size_t end = stream_get_getp (s) + caphdr->length; - - /* Verify length is a multiple of 4 */ - if ((caphdr->length-2) % 4) - { - zlog_warn("Restart Cap: Received invalid length %d, non-multiple of 4", - caphdr->length); - return -1; - } - - SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV); - restart_flag_time = stream_getw(s); - if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT)) - SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV); - - UNSET_FLAG (restart_flag_time, 0xF000); - peer->v_gr_restart = restart_flag_time; - - if (bgp_debug_neighbor_events(peer)) - { - zlog_debug ("%s OPEN has Graceful Restart capability", peer->host); - zlog_debug ("%s Peer has%srestarted. Restart Time : %d", - peer->host, - CHECK_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV) ? " " - : " not ", - peer->v_gr_restart); - } - - while (stream_get_getp (s) + 4 <= end) - { - afi_t afi; - safi_t safi; - iana_afi_t pkt_afi = stream_getw (s); - safi_t pkt_safi = stream_getc (s); - u_char flag = stream_getc (s); - - /* Convert AFI, SAFI to internal values, check. */ - if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi)) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported." - " Ignore the Graceful Restart capability for this AFI/SAFI", - peer->host, pkt_afi, pkt_safi); - } - else if (!peer->afc[afi][safi]) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled." - " Ignore the Graceful Restart capability", - peer->host, pkt_afi, pkt_safi); - } - else - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Address family %s is%spreserved", peer->host, - afi_safi_print (afi, safi), - CHECK_FLAG (peer->af_cap[afi][safi], - PEER_CAP_RESTART_AF_PRESERVE_RCV) - ? " " : " not "); - - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV); - if (CHECK_FLAG (flag, RESTART_F_BIT)) - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV); - - } - } - return 0; + struct stream *s = BGP_INPUT(peer); + u_int16_t restart_flag_time; + size_t end = stream_get_getp(s) + caphdr->length; + + /* Verify length is a multiple of 4 */ + if ((caphdr->length - 2) % 4) { + zlog_warn( + "Restart Cap: Received invalid length %d, non-multiple of 4", + caphdr->length); + return -1; + } + + SET_FLAG(peer->cap, PEER_CAP_RESTART_RCV); + restart_flag_time = stream_getw(s); + if (CHECK_FLAG(restart_flag_time, RESTART_R_BIT)) + SET_FLAG(peer->cap, PEER_CAP_RESTART_BIT_RCV); + + UNSET_FLAG(restart_flag_time, 0xF000); + peer->v_gr_restart = restart_flag_time; + + if (bgp_debug_neighbor_events(peer)) { + zlog_debug("%s OPEN has Graceful Restart capability", + peer->host); + zlog_debug("%s Peer has%srestarted. Restart Time : %d", + peer->host, + CHECK_FLAG(peer->cap, PEER_CAP_RESTART_BIT_RCV) + ? " " + : " not ", + peer->v_gr_restart); + } + + while (stream_get_getp(s) + 4 <= end) { + afi_t afi; + safi_t safi; + iana_afi_t pkt_afi = stream_getw(s); + safi_t pkt_safi = stream_getc(s); + u_char flag = stream_getc(s); + + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Addr-family %d/%d(afi/safi) not supported." + " Ignore the Graceful Restart capability for this AFI/SAFI", + peer->host, pkt_afi, pkt_safi); + } else if (!peer->afc[afi][safi]) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Addr-family %d/%d(afi/safi) not enabled." + " Ignore the Graceful Restart capability", + peer->host, pkt_afi, pkt_safi); + } else { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Address family %s is%spreserved", + peer->host, afi_safi_print(afi, safi), + CHECK_FLAG( + peer->af_cap[afi][safi], + PEER_CAP_RESTART_AF_PRESERVE_RCV) + ? " " + : " not "); + + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_RESTART_AF_RCV); + if (CHECK_FLAG(flag, RESTART_F_BIT)) + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_RESTART_AF_PRESERVE_RCV); + } + } + return 0; } /* Unlike other capability parsing routines, this one returns 0 on error */ -static as_t -bgp_capability_as4 (struct peer *peer, struct capability_header *hdr) +static as_t bgp_capability_as4(struct peer *peer, struct capability_header *hdr) { - SET_FLAG (peer->cap, PEER_CAP_AS4_RCV); - - if (hdr->length != CAPABILITY_CODE_AS4_LEN) - { - zlog_err ("%s AS4 capability has incorrect data length %d", - peer->host, hdr->length); - return 0; - } - - as_t as4 = stream_getl (BGP_INPUT(peer)); - - if (BGP_DEBUG (as4, AS4)) - zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u", - peer->host, as4); - return as4; + SET_FLAG(peer->cap, PEER_CAP_AS4_RCV); + + if (hdr->length != CAPABILITY_CODE_AS4_LEN) { + zlog_err("%s AS4 capability has incorrect data length %d", + peer->host, hdr->length); + return 0; + } + + as_t as4 = stream_getl(BGP_INPUT(peer)); + + if (BGP_DEBUG(as4, AS4)) + zlog_debug( + "%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u", + peer->host, as4); + return as4; } -static int -bgp_capability_addpath (struct peer *peer, struct capability_header *hdr) +static int bgp_capability_addpath(struct peer *peer, + struct capability_header *hdr) { - struct stream *s = BGP_INPUT (peer); - size_t end = stream_get_getp (s) + hdr->length; - - SET_FLAG (peer->cap, PEER_CAP_ADDPATH_RCV); - - /* Verify length is a multiple of 4 */ - if (hdr->length % 4) - { - zlog_warn("Add Path: Received invalid length %d, non-multiple of 4", - hdr->length); - return -1; - } - - while (stream_get_getp (s) + 4 <= end) - { - afi_t afi; - safi_t safi; - iana_afi_t pkt_afi = stream_getw (s); - safi_t pkt_safi = stream_getc (s); - u_char send_receive = stream_getc (s); - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s OPEN has AddPath CAP for afi/safi: %u/%u%s%s", - peer->host, pkt_afi, pkt_safi, - (send_receive & BGP_ADDPATH_RX) ? ", receive" : "", - (send_receive & BGP_ADDPATH_TX) ? ", transmit" : ""); - - /* Convert AFI, SAFI to internal values, check. */ - if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi)) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported." - " Ignore the Addpath Attribute for this AFI/SAFI", - peer->host, pkt_afi, pkt_safi); - continue; - } - else if (!peer->afc[afi][safi]) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled." - " Ignore the AddPath capability for this AFI/SAFI", - peer->host, pkt_afi, pkt_safi); - continue; - } - - if (send_receive & BGP_ADDPATH_RX) - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_RCV); - - if (send_receive & BGP_ADDPATH_TX) - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV); - } - - return 0; + struct stream *s = BGP_INPUT(peer); + size_t end = stream_get_getp(s) + hdr->length; + + SET_FLAG(peer->cap, PEER_CAP_ADDPATH_RCV); + + /* Verify length is a multiple of 4 */ + if (hdr->length % 4) { + zlog_warn( + "Add Path: Received invalid length %d, non-multiple of 4", + hdr->length); + return -1; + } + + while (stream_get_getp(s) + 4 <= end) { + afi_t afi; + safi_t safi; + iana_afi_t pkt_afi = stream_getw(s); + safi_t pkt_safi = stream_getc(s); + u_char send_receive = stream_getc(s); + + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s OPEN has AddPath CAP for afi/safi: %u/%u%s%s", + peer->host, pkt_afi, pkt_safi, + (send_receive & BGP_ADDPATH_RX) ? ", receive" + : "", + (send_receive & BGP_ADDPATH_TX) ? ", transmit" + : ""); + + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Addr-family %d/%d(afi/safi) not supported." + " Ignore the Addpath Attribute for this AFI/SAFI", + peer->host, pkt_afi, pkt_safi); + continue; + } else if (!peer->afc[afi][safi]) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Addr-family %d/%d(afi/safi) not enabled." + " Ignore the AddPath capability for this AFI/SAFI", + peer->host, pkt_afi, pkt_safi); + continue; + } + + if (send_receive & BGP_ADDPATH_RX) + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ADDPATH_AF_RX_RCV); + + if (send_receive & BGP_ADDPATH_TX) + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ADDPATH_AF_TX_RCV); + } + + return 0; } -static int -bgp_capability_enhe (struct peer *peer, struct capability_header *hdr) +static int bgp_capability_enhe(struct peer *peer, struct capability_header *hdr) { - struct stream *s = BGP_INPUT (peer); - size_t end = stream_get_getp (s) + hdr->length; - - /* Verify length is a multiple of 4 */ - if (hdr->length % 6) - { - zlog_warn("Extended NH: Received invalid length %d, non-multiple of 6", - hdr->length); - return -1; - } - - while (stream_get_getp (s) + 6 <= end) - { - iana_afi_t pkt_afi = stream_getw (s); - afi_t afi; - safi_t safi, pkt_safi = stream_getw (s); - iana_afi_t pkt_nh_afi = stream_getw (s); - afi_t nh_afi; - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Received with afi/safi/next-hop afi: %u/%u/%u", - peer->host, pkt_afi, pkt_safi, pkt_nh_afi); - - /* Convert AFI, SAFI to internal values, check. */ - if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi)) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported." - " Ignore the ENHE Attribute for this AFI/SAFI", - peer->host, pkt_afi, pkt_safi); - continue; - } - - /* RFC 5549 specifies use of this capability only for IPv4 AFI, with - * the Nexthop AFI being IPv6. A future spec may introduce other - * possibilities, so we ignore other values with a log. Also, only - * SAFI_UNICAST and SAFI_LABELED_UNICAST are currently supported (and expected). - */ - nh_afi = afi_iana2int (pkt_nh_afi); - - if (afi != AFI_IP || nh_afi != AFI_IP6 || !(safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) - { - zlog_warn ("%s Unexpected afi/safi/next-hop afi: %u/%u/%u " - "in Extended Next-hop capability, ignoring", - peer->host, pkt_afi, pkt_safi, pkt_nh_afi); - continue; - } - - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_RCV); - - if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_ADV)) - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_NEGO); - } - - SET_FLAG (peer->cap, PEER_CAP_ENHE_RCV); - - return 0; + struct stream *s = BGP_INPUT(peer); + size_t end = stream_get_getp(s) + hdr->length; + + /* Verify length is a multiple of 4 */ + if (hdr->length % 6) { + zlog_warn( + "Extended NH: Received invalid length %d, non-multiple of 6", + hdr->length); + return -1; + } + + while (stream_get_getp(s) + 6 <= end) { + iana_afi_t pkt_afi = stream_getw(s); + afi_t afi; + safi_t safi, pkt_safi = stream_getw(s); + iana_afi_t pkt_nh_afi = stream_getw(s); + afi_t nh_afi; + + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Received with afi/safi/next-hop afi: %u/%u/%u", + peer->host, pkt_afi, pkt_safi, pkt_nh_afi); + + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Addr-family %d/%d(afi/safi) not supported." + " Ignore the ENHE Attribute for this AFI/SAFI", + peer->host, pkt_afi, pkt_safi); + continue; + } + + /* RFC 5549 specifies use of this capability only for IPv4 AFI, + * with + * the Nexthop AFI being IPv6. A future spec may introduce other + * possibilities, so we ignore other values with a log. Also, + * only + * SAFI_UNICAST and SAFI_LABELED_UNICAST are currently supported + * (and expected). + */ + nh_afi = afi_iana2int(pkt_nh_afi); + + if (afi != AFI_IP || nh_afi != AFI_IP6 + || !(safi == SAFI_UNICAST + || safi == SAFI_LABELED_UNICAST)) { + zlog_warn( + "%s Unexpected afi/safi/next-hop afi: %u/%u/%u " + "in Extended Next-hop capability, ignoring", + peer->host, pkt_afi, pkt_safi, pkt_nh_afi); + continue; + } + + SET_FLAG(peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_RCV); + + if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_ADV)) + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ENHE_AF_NEGO); + } + + SET_FLAG(peer->cap, PEER_CAP_ENHE_RCV); + + return 0; } -static int -bgp_capability_hostname (struct peer *peer, struct capability_header *hdr) +static int bgp_capability_hostname(struct peer *peer, + struct capability_header *hdr) { - struct stream *s = BGP_INPUT (peer); - char str[BGP_MAX_HOSTNAME+1]; - size_t end = stream_get_getp (s) + hdr->length; - u_char len; - - SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_RCV); - - len = stream_getc(s); - if (stream_get_getp(s) + len > end) - { - zlog_warn("%s: Received malformed hostname capability from peer %s", - __FUNCTION__, peer->host); - return -1; - } - - if (len > BGP_MAX_HOSTNAME) - { - stream_get(str, s, BGP_MAX_HOSTNAME); - stream_forward_getp(s, len-BGP_MAX_HOSTNAME); - len = BGP_MAX_HOSTNAME; /* to set the '\0' below */ - } - else if (len) - stream_get(str, s, len); - - if (len) - { - str[len] = '\0'; - - if (peer->hostname != NULL) - { - XFREE(MTYPE_BGP_PEER_HOST, peer->hostname); - peer->hostname = NULL; - } - - if (peer->domainname != NULL) - { - XFREE(MTYPE_BGP_PEER_HOST, peer->domainname); - peer->domainname = NULL; - } - - peer->hostname = XSTRDUP(MTYPE_BGP_PEER_HOST, str); - } - - if (stream_get_getp(s) +1 > end) - { - zlog_warn("%s: Received invalid domain name len (hostname capability) from peer %s", - __FUNCTION__, peer->host); - return -1; - } - - len = stream_getc(s); - if (stream_get_getp(s) + len > end) - { - zlog_warn("%s: Received runt domain name (hostname capability) from peer %s", - __FUNCTION__, peer->host); - return -1; - } - - if (len > BGP_MAX_HOSTNAME) - { - stream_get(str, s, BGP_MAX_HOSTNAME); - stream_forward_getp(s, len-BGP_MAX_HOSTNAME); - len = BGP_MAX_HOSTNAME; /* to set the '\0' below */ - } - else if (len) - stream_get(str, s, len); - - if (len) - { - str[len] = '\0'; - peer->domainname = XSTRDUP(MTYPE_BGP_PEER_HOST, str); - } - - if (bgp_debug_neighbor_events(peer)) - { - zlog_debug("%s received hostname %s, domainname %s", - peer->host, peer->hostname, peer->domainname); - } - - return 0; + struct stream *s = BGP_INPUT(peer); + char str[BGP_MAX_HOSTNAME + 1]; + size_t end = stream_get_getp(s) + hdr->length; + u_char len; + + SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_RCV); + + len = stream_getc(s); + if (stream_get_getp(s) + len > end) { + zlog_warn( + "%s: Received malformed hostname capability from peer %s", + __FUNCTION__, peer->host); + return -1; + } + + if (len > BGP_MAX_HOSTNAME) { + stream_get(str, s, BGP_MAX_HOSTNAME); + stream_forward_getp(s, len - BGP_MAX_HOSTNAME); + len = BGP_MAX_HOSTNAME; /* to set the '\0' below */ + } else if (len) + stream_get(str, s, len); + + if (len) { + str[len] = '\0'; + + if (peer->hostname != NULL) { + XFREE(MTYPE_BGP_PEER_HOST, peer->hostname); + peer->hostname = NULL; + } + + if (peer->domainname != NULL) { + XFREE(MTYPE_BGP_PEER_HOST, peer->domainname); + peer->domainname = NULL; + } + + peer->hostname = XSTRDUP(MTYPE_BGP_PEER_HOST, str); + } + + if (stream_get_getp(s) + 1 > end) { + zlog_warn( + "%s: Received invalid domain name len (hostname capability) from peer %s", + __FUNCTION__, peer->host); + return -1; + } + + len = stream_getc(s); + if (stream_get_getp(s) + len > end) { + zlog_warn( + "%s: Received runt domain name (hostname capability) from peer %s", + __FUNCTION__, peer->host); + return -1; + } + + if (len > BGP_MAX_HOSTNAME) { + stream_get(str, s, BGP_MAX_HOSTNAME); + stream_forward_getp(s, len - BGP_MAX_HOSTNAME); + len = BGP_MAX_HOSTNAME; /* to set the '\0' below */ + } else if (len) + stream_get(str, s, len); + + if (len) { + str[len] = '\0'; + peer->domainname = XSTRDUP(MTYPE_BGP_PEER_HOST, str); + } + + if (bgp_debug_neighbor_events(peer)) { + zlog_debug("%s received hostname %s, domainname %s", peer->host, + peer->hostname, peer->domainname); + } + + return 0; } - static const struct message capcode_str[] = -{ - { CAPABILITY_CODE_MP, "MultiProtocol Extensions" }, - { CAPABILITY_CODE_REFRESH, "Route Refresh" }, - { CAPABILITY_CODE_ORF, "Cooperative Route Filtering" }, - { CAPABILITY_CODE_RESTART, "Graceful Restart" }, - { CAPABILITY_CODE_AS4, "4-octet AS number" }, - { CAPABILITY_CODE_ADDPATH, "AddPath" }, - { CAPABILITY_CODE_DYNAMIC, "Dynamic" }, - { CAPABILITY_CODE_ENHE, "Extended Next Hop Encoding" }, - { CAPABILITY_CODE_DYNAMIC_OLD, "Dynamic (Old)" }, - { CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)" }, - { CAPABILITY_CODE_ORF_OLD, "ORF (Old)" }, - { CAPABILITY_CODE_FQDN, "FQDN" }, - { 0 } -}; +static const struct message capcode_str[] = { + {CAPABILITY_CODE_MP, "MultiProtocol Extensions"}, + {CAPABILITY_CODE_REFRESH, "Route Refresh"}, + {CAPABILITY_CODE_ORF, "Cooperative Route Filtering"}, + {CAPABILITY_CODE_RESTART, "Graceful Restart"}, + {CAPABILITY_CODE_AS4, "4-octet AS number"}, + {CAPABILITY_CODE_ADDPATH, "AddPath"}, + {CAPABILITY_CODE_DYNAMIC, "Dynamic"}, + {CAPABILITY_CODE_ENHE, "Extended Next Hop Encoding"}, + {CAPABILITY_CODE_DYNAMIC_OLD, "Dynamic (Old)"}, + {CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)"}, + {CAPABILITY_CODE_ORF_OLD, "ORF (Old)"}, + {CAPABILITY_CODE_FQDN, "FQDN"}, + {0}}; /* Minimum sizes for length field of each cap (so not inc. the header) */ -static const size_t cap_minsizes[] = -{ - [CAPABILITY_CODE_MP] = CAPABILITY_CODE_MP_LEN, - [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN, - [CAPABILITY_CODE_ORF] = CAPABILITY_CODE_ORF_LEN, - [CAPABILITY_CODE_RESTART] = CAPABILITY_CODE_RESTART_LEN, - [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN, - [CAPABILITY_CODE_ADDPATH] = CAPABILITY_CODE_ADDPATH_LEN, - [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN, - [CAPABILITY_CODE_DYNAMIC_OLD] = CAPABILITY_CODE_DYNAMIC_LEN, - [CAPABILITY_CODE_ENHE] = CAPABILITY_CODE_ENHE_LEN, - [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN, - [CAPABILITY_CODE_ORF_OLD] = CAPABILITY_CODE_ORF_LEN, - [CAPABILITY_CODE_FQDN] = CAPABILITY_CODE_MIN_FQDN_LEN, +static const size_t cap_minsizes[] = { + [CAPABILITY_CODE_MP] = CAPABILITY_CODE_MP_LEN, + [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN, + [CAPABILITY_CODE_ORF] = CAPABILITY_CODE_ORF_LEN, + [CAPABILITY_CODE_RESTART] = CAPABILITY_CODE_RESTART_LEN, + [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN, + [CAPABILITY_CODE_ADDPATH] = CAPABILITY_CODE_ADDPATH_LEN, + [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN, + [CAPABILITY_CODE_DYNAMIC_OLD] = CAPABILITY_CODE_DYNAMIC_LEN, + [CAPABILITY_CODE_ENHE] = CAPABILITY_CODE_ENHE_LEN, + [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN, + [CAPABILITY_CODE_ORF_OLD] = CAPABILITY_CODE_ORF_LEN, + [CAPABILITY_CODE_FQDN] = CAPABILITY_CODE_MIN_FQDN_LEN, }; /* value the capability must be a multiple of. @@ -742,20 +763,19 @@ static const size_t cap_minsizes[] = * Other capabilities whose data doesn't fall on convenient boundaries for this * table should be set to 1. */ -static const size_t cap_modsizes[] = -{ - [CAPABILITY_CODE_MP] = 4, - [CAPABILITY_CODE_REFRESH] = 1, - [CAPABILITY_CODE_ORF] = 1, - [CAPABILITY_CODE_RESTART] = 1, - [CAPABILITY_CODE_AS4] = 4, - [CAPABILITY_CODE_ADDPATH] = 4, - [CAPABILITY_CODE_DYNAMIC] = 1, - [CAPABILITY_CODE_DYNAMIC_OLD] = 1, - [CAPABILITY_CODE_ENHE] = 6, - [CAPABILITY_CODE_REFRESH_OLD] = 1, - [CAPABILITY_CODE_ORF_OLD] = 1, - [CAPABILITY_CODE_FQDN] = 1, +static const size_t cap_modsizes[] = { + [CAPABILITY_CODE_MP] = 4, + [CAPABILITY_CODE_REFRESH] = 1, + [CAPABILITY_CODE_ORF] = 1, + [CAPABILITY_CODE_RESTART] = 1, + [CAPABILITY_CODE_AS4] = 4, + [CAPABILITY_CODE_ADDPATH] = 4, + [CAPABILITY_CODE_DYNAMIC] = 1, + [CAPABILITY_CODE_DYNAMIC_OLD] = 1, + [CAPABILITY_CODE_ENHE] = 6, + [CAPABILITY_CODE_REFRESH_OLD] = 1, + [CAPABILITY_CODE_ORF_OLD] = 1, + [CAPABILITY_CODE_FQDN] = 1, }; /** @@ -765,281 +785,276 @@ static const size_t cap_modsizes[] = * @param[out] mp_capability Set to 1 on return iff one or more Multiprotocol * capabilities were encountered. */ -static int -bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability, - u_char **error) +static int bgp_capability_parse(struct peer *peer, size_t length, + int *mp_capability, u_char **error) { - int ret; - struct stream *s = BGP_INPUT (peer); - size_t end = stream_get_getp (s) + length; - - assert (STREAM_READABLE (s) >= length); - - while (stream_get_getp (s) < end) - { - size_t start; - u_char *sp = stream_pnt (s); - struct capability_header caphdr; - - ret = 0; - /* We need at least capability code and capability length. */ - if (stream_get_getp(s) + 2 > end) - { - zlog_info ("%s Capability length error (< header)", peer->host); - bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); - return -1; - } - - caphdr.code = stream_getc (s); - caphdr.length = stream_getc (s); - start = stream_get_getp (s); - - /* Capability length check sanity check. */ - if (start + caphdr.length > end) - { - zlog_info ("%s Capability length error (< length)", peer->host); - bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); - return -1; + int ret; + struct stream *s = BGP_INPUT(peer); + size_t end = stream_get_getp(s) + length; + + assert(STREAM_READABLE(s) >= length); + + while (stream_get_getp(s) < end) { + size_t start; + u_char *sp = stream_pnt(s); + struct capability_header caphdr; + + ret = 0; + /* We need at least capability code and capability length. */ + if (stream_get_getp(s) + 2 > end) { + zlog_info("%s Capability length error (< header)", + peer->host); + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_MALFORMED_ATTR); + return -1; + } + + caphdr.code = stream_getc(s); + caphdr.length = stream_getc(s); + start = stream_get_getp(s); + + /* Capability length check sanity check. */ + if (start + caphdr.length > end) { + zlog_info("%s Capability length error (< length)", + peer->host); + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_MALFORMED_ATTR); + return -1; + } + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s OPEN has %s capability (%u), length %u", + peer->host, + lookup_msg(capcode_str, caphdr.code, NULL), + caphdr.code, caphdr.length); + + /* Length sanity check, type-specific, for known capabilities */ + switch (caphdr.code) { + case CAPABILITY_CODE_MP: + case CAPABILITY_CODE_REFRESH: + case CAPABILITY_CODE_REFRESH_OLD: + case CAPABILITY_CODE_ORF: + case CAPABILITY_CODE_ORF_OLD: + case CAPABILITY_CODE_RESTART: + case CAPABILITY_CODE_AS4: + case CAPABILITY_CODE_ADDPATH: + case CAPABILITY_CODE_DYNAMIC: + case CAPABILITY_CODE_DYNAMIC_OLD: + case CAPABILITY_CODE_ENHE: + case CAPABILITY_CODE_FQDN: + /* Check length. */ + if (caphdr.length < cap_minsizes[caphdr.code]) { + zlog_info( + "%s %s Capability length error: got %u," + " expected at least %u", + peer->host, + lookup_msg(capcode_str, caphdr.code, + NULL), + caphdr.length, + (unsigned)cap_minsizes[caphdr.code]); + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_MALFORMED_ATTR); + return -1; + } + if (caphdr.length + && caphdr.length % cap_modsizes[caphdr.code] != 0) { + zlog_info( + "%s %s Capability length error: got %u," + " expected a multiple of %u", + peer->host, + lookup_msg(capcode_str, caphdr.code, + NULL), + caphdr.length, + (unsigned)cap_modsizes[caphdr.code]); + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_MALFORMED_ATTR); + return -1; + } + /* we deliberately ignore unknown codes, see below */ + default: + break; + } + + switch (caphdr.code) { + case CAPABILITY_CODE_MP: { + *mp_capability = 1; + + /* Ignore capability when override-capability is set. */ + if (!CHECK_FLAG(peer->flags, + PEER_FLAG_OVERRIDE_CAPABILITY)) { + /* Set negotiated value. */ + ret = bgp_capability_mp(peer, &caphdr); + + /* Unsupported Capability. */ + if (ret < 0) { + /* Store return data. */ + memcpy(*error, sp, caphdr.length + 2); + *error += caphdr.length + 2; + } + ret = 0; /* Don't return error for this */ + } + } break; + case CAPABILITY_CODE_REFRESH: + case CAPABILITY_CODE_REFRESH_OLD: { + /* BGP refresh capability */ + if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD) + SET_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV); + else + SET_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV); + } break; + case CAPABILITY_CODE_ORF: + case CAPABILITY_CODE_ORF_OLD: + ret = bgp_capability_orf_entry(peer, &caphdr); + break; + case CAPABILITY_CODE_RESTART: + ret = bgp_capability_restart(peer, &caphdr); + break; + case CAPABILITY_CODE_DYNAMIC: + case CAPABILITY_CODE_DYNAMIC_OLD: + SET_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV); + break; + case CAPABILITY_CODE_AS4: + /* Already handled as a special-case parsing of the + * capabilities + * at the beginning of OPEN processing. So we care not a + * jot + * for the value really, only error case. + */ + if (!bgp_capability_as4(peer, &caphdr)) + ret = -1; + break; + case CAPABILITY_CODE_ADDPATH: + ret = bgp_capability_addpath(peer, &caphdr); + break; + case CAPABILITY_CODE_ENHE: + ret = bgp_capability_enhe(peer, &caphdr); + break; + case CAPABILITY_CODE_FQDN: + ret = bgp_capability_hostname(peer, &caphdr); + break; + default: + if (caphdr.code > 128) { + /* We don't send Notification for unknown vendor + specific + capabilities. It seems reasonable for now... + */ + zlog_warn("%s Vendor specific capability %d", + peer->host, caphdr.code); + } else { + zlog_warn( + "%s unrecognized capability code: %d - ignored", + peer->host, caphdr.code); + memcpy(*error, sp, caphdr.length + 2); + *error += caphdr.length + 2; + } + } + + if (ret < 0) { + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_MALFORMED_ATTR); + return -1; + } + if (stream_get_getp(s) != (start + caphdr.length)) { + if (stream_get_getp(s) > (start + caphdr.length)) + zlog_warn( + "%s Cap-parser for %s read past cap-length, %u!", + peer->host, + lookup_msg(capcode_str, caphdr.code, + NULL), + caphdr.length); + stream_set_getp(s, start + caphdr.length); + } } - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s OPEN has %s capability (%u), length %u", - peer->host, - lookup_msg(capcode_str, caphdr.code, NULL), - caphdr.code, caphdr.length); - - /* Length sanity check, type-specific, for known capabilities */ - switch (caphdr.code) - { - case CAPABILITY_CODE_MP: - case CAPABILITY_CODE_REFRESH: - case CAPABILITY_CODE_REFRESH_OLD: - case CAPABILITY_CODE_ORF: - case CAPABILITY_CODE_ORF_OLD: - case CAPABILITY_CODE_RESTART: - case CAPABILITY_CODE_AS4: - case CAPABILITY_CODE_ADDPATH: - case CAPABILITY_CODE_DYNAMIC: - case CAPABILITY_CODE_DYNAMIC_OLD: - case CAPABILITY_CODE_ENHE: - case CAPABILITY_CODE_FQDN: - /* Check length. */ - if (caphdr.length < cap_minsizes[caphdr.code]) - { - zlog_info ("%s %s Capability length error: got %u," - " expected at least %u", - peer->host, - lookup_msg(capcode_str, caphdr.code, NULL), - caphdr.length, - (unsigned) cap_minsizes[caphdr.code]); - bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); - return -1; - } - if (caphdr.length - && caphdr.length % cap_modsizes[caphdr.code] != 0) - { - zlog_info ("%s %s Capability length error: got %u," - " expected a multiple of %u", - peer->host, - lookup_msg(capcode_str, caphdr.code, NULL), - caphdr.length, - (unsigned) cap_modsizes[caphdr.code]); - bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_MALFORMED_ATTR); - return -1; - } - /* we deliberately ignore unknown codes, see below */ - default: - break; - } - - switch (caphdr.code) - { - case CAPABILITY_CODE_MP: - { - *mp_capability = 1; - - /* Ignore capability when override-capability is set. */ - if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) - { - /* Set negotiated value. */ - ret = bgp_capability_mp (peer, &caphdr); - - /* Unsupported Capability. */ - if (ret < 0) - { - /* Store return data. */ - memcpy (*error, sp, caphdr.length + 2); - *error += caphdr.length + 2; - } - ret = 0; /* Don't return error for this */ - } - } - break; - case CAPABILITY_CODE_REFRESH: - case CAPABILITY_CODE_REFRESH_OLD: - { - /* BGP refresh capability */ - if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD) - SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV); - else - SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV); - } - break; - case CAPABILITY_CODE_ORF: - case CAPABILITY_CODE_ORF_OLD: - ret = bgp_capability_orf_entry (peer, &caphdr); - break; - case CAPABILITY_CODE_RESTART: - ret = bgp_capability_restart (peer, &caphdr); - break; - case CAPABILITY_CODE_DYNAMIC: - case CAPABILITY_CODE_DYNAMIC_OLD: - SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV); - break; - case CAPABILITY_CODE_AS4: - /* Already handled as a special-case parsing of the capabilities - * at the beginning of OPEN processing. So we care not a jot - * for the value really, only error case. - */ - if (!bgp_capability_as4 (peer, &caphdr)) - ret = -1; - break; - case CAPABILITY_CODE_ADDPATH: - ret = bgp_capability_addpath (peer, &caphdr); - break; - case CAPABILITY_CODE_ENHE: - ret = bgp_capability_enhe (peer, &caphdr); - break; - case CAPABILITY_CODE_FQDN: - ret = bgp_capability_hostname (peer, &caphdr); - break; - default: - if (caphdr.code > 128) - { - /* We don't send Notification for unknown vendor specific - capabilities. It seems reasonable for now... */ - zlog_warn ("%s Vendor specific capability %d", - peer->host, caphdr.code); - } - else - { - zlog_warn ("%s unrecognized capability code: %d - ignored", - peer->host, caphdr.code); - memcpy (*error, sp, caphdr.length + 2); - *error += caphdr.length + 2; - } - } - - if (ret < 0) - { - bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); - return -1; - } - if (stream_get_getp(s) != (start + caphdr.length)) - { - if (stream_get_getp(s) > (start + caphdr.length)) - zlog_warn ("%s Cap-parser for %s read past cap-length, %u!", - peer->host, lookup_msg(capcode_str, caphdr.code, NULL), - caphdr.length); - stream_set_getp (s, start + caphdr.length); - } - } - return 0; + return 0; } -static int -bgp_auth_parse (struct peer *peer, size_t length) +static int bgp_auth_parse(struct peer *peer, size_t length) { - bgp_notify_send (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_AUTH_FAILURE); - return -1; + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_AUTH_FAILURE); + return -1; } -static int -strict_capability_same (struct peer *peer) +static int strict_capability_same(struct peer *peer) { - int i, j; + int i, j; - for (i = AFI_IP; i < AFI_MAX; i++) - for (j = SAFI_UNICAST; j < SAFI_MAX; j++) - if (peer->afc[i][j] != peer->afc_nego[i][j]) - return 0; - return 1; + for (i = AFI_IP; i < AFI_MAX; i++) + for (j = SAFI_UNICAST; j < SAFI_MAX; j++) + if (peer->afc[i][j] != peer->afc_nego[i][j]) + return 0; + return 1; } /* peek into option, stores ASN to *as4 if the AS4 capability was found. * Returns 0 if no as4 found, as4cap value otherwise. */ -as_t -peek_for_as4_capability (struct peer *peer, u_char length) +as_t peek_for_as4_capability(struct peer *peer, u_char length) { - struct stream *s = BGP_INPUT (peer); - size_t orig_getp = stream_get_getp (s); - size_t end = orig_getp + length; - as_t as4 = 0; - - if (BGP_DEBUG (as4, AS4)) - zlog_info ("%s [AS4] rcv OPEN w/ OPTION parameter len: %u," - " peeking for as4", - peer->host, length); - /* the error cases we DONT handle, we ONLY try to read as4 out of - * correctly formatted options. - */ - while (stream_get_getp(s) < end) - { - u_char opt_type; - u_char opt_length; - - /* Check the length. */ - if (stream_get_getp (s) + 2 > end) - goto end; - - /* Fetch option type and length. */ - opt_type = stream_getc (s); - opt_length = stream_getc (s); - - /* Option length check. */ - if (stream_get_getp (s) + opt_length > end) - goto end; - - if (opt_type == BGP_OPEN_OPT_CAP) - { - unsigned long capd_start = stream_get_getp (s); - unsigned long capd_end = capd_start + opt_length; - - assert (capd_end <= end); - - while (stream_get_getp (s) < capd_end) - { - struct capability_header hdr; - - if (stream_get_getp (s) + 2 > capd_end) - goto end; - - hdr.code = stream_getc (s); - hdr.length = stream_getc (s); - - if ((stream_get_getp(s) + hdr.length) > capd_end) - goto end; - - if (hdr.code == CAPABILITY_CODE_AS4) - { - if (BGP_DEBUG (as4, AS4)) - zlog_info ("[AS4] found AS4 capability, about to parse"); - as4 = bgp_capability_as4 (peer, &hdr); - - goto end; - } - stream_forward_getp (s, hdr.length); - } + struct stream *s = BGP_INPUT(peer); + size_t orig_getp = stream_get_getp(s); + size_t end = orig_getp + length; + as_t as4 = 0; + + if (BGP_DEBUG(as4, AS4)) + zlog_info( + "%s [AS4] rcv OPEN w/ OPTION parameter len: %u," + " peeking for as4", + peer->host, length); + /* the error cases we DONT handle, we ONLY try to read as4 out of + * correctly formatted options. + */ + while (stream_get_getp(s) < end) { + u_char opt_type; + u_char opt_length; + + /* Check the length. */ + if (stream_get_getp(s) + 2 > end) + goto end; + + /* Fetch option type and length. */ + opt_type = stream_getc(s); + opt_length = stream_getc(s); + + /* Option length check. */ + if (stream_get_getp(s) + opt_length > end) + goto end; + + if (opt_type == BGP_OPEN_OPT_CAP) { + unsigned long capd_start = stream_get_getp(s); + unsigned long capd_end = capd_start + opt_length; + + assert(capd_end <= end); + + while (stream_get_getp(s) < capd_end) { + struct capability_header hdr; + + if (stream_get_getp(s) + 2 > capd_end) + goto end; + + hdr.code = stream_getc(s); + hdr.length = stream_getc(s); + + if ((stream_get_getp(s) + hdr.length) + > capd_end) + goto end; + + if (hdr.code == CAPABILITY_CODE_AS4) { + if (BGP_DEBUG(as4, AS4)) + zlog_info( + "[AS4] found AS4 capability, about to parse"); + as4 = bgp_capability_as4(peer, &hdr); + + goto end; + } + stream_forward_getp(s, hdr.length); + } + } } - } end: - stream_set_getp (s, orig_getp); - return as4; + stream_set_getp(s, orig_getp); + return as4; } /** @@ -1047,461 +1062,476 @@ end: * * @param[out] mp_capability @see bgp_capability_parse() for semantics. */ -int -bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability) +int bgp_open_option_parse(struct peer *peer, u_char length, int *mp_capability) { - int ret = 0; - u_char *error; - u_char error_data[BGP_MAX_PACKET_SIZE]; - struct stream *s = BGP_INPUT(peer); - size_t end = stream_get_getp (s) + length; - - error = error_data; - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u", - peer->host, length); - - while (stream_get_getp(s) < end) - { - u_char opt_type; - u_char opt_length; - - /* Must have at least an OPEN option header */ - if (STREAM_READABLE(s) < 2) - { - zlog_info ("%s Option length error", peer->host); - bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); - return -1; - } - - /* Fetch option type and length. */ - opt_type = stream_getc (s); - opt_length = stream_getc (s); - - /* Option length check. */ - if (STREAM_READABLE (s) < opt_length) - { - zlog_info ("%s Option length error", peer->host); - bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); - return -1; + int ret = 0; + u_char *error; + u_char error_data[BGP_MAX_PACKET_SIZE]; + struct stream *s = BGP_INPUT(peer); + size_t end = stream_get_getp(s) + length; + + error = error_data; + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s rcv OPEN w/ OPTION parameter len: %u", + peer->host, length); + + while (stream_get_getp(s) < end) { + u_char opt_type; + u_char opt_length; + + /* Must have at least an OPEN option header */ + if (STREAM_READABLE(s) < 2) { + zlog_info("%s Option length error", peer->host); + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_MALFORMED_ATTR); + return -1; + } + + /* Fetch option type and length. */ + opt_type = stream_getc(s); + opt_length = stream_getc(s); + + /* Option length check. */ + if (STREAM_READABLE(s) < opt_length) { + zlog_info("%s Option length error", peer->host); + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_MALFORMED_ATTR); + return -1; + } + + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s rcvd OPEN w/ optional parameter type %u (%s) len %u", + peer->host, opt_type, + opt_type == BGP_OPEN_OPT_AUTH + ? "Authentication" + : opt_type == BGP_OPEN_OPT_CAP + ? "Capability" + : "Unknown", + opt_length); + + switch (opt_type) { + case BGP_OPEN_OPT_AUTH: + ret = bgp_auth_parse(peer, opt_length); + break; + case BGP_OPEN_OPT_CAP: + ret = bgp_capability_parse(peer, opt_length, + mp_capability, &error); + break; + default: + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_UNSUP_PARAM); + ret = -1; + break; + } + + /* Parse error. To accumulate all unsupported capability codes, + bgp_capability_parse does not return -1 when encounter + unsupported capability code. To detect that, please check + error and erro_data pointer, like below. */ + if (ret < 0) + return -1; } - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u", - peer->host, opt_type, - opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" : - opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown", - opt_length); - - switch (opt_type) - { - case BGP_OPEN_OPT_AUTH: - ret = bgp_auth_parse (peer, opt_length); - break; - case BGP_OPEN_OPT_CAP: - ret = bgp_capability_parse (peer, opt_length, mp_capability, &error); - break; - default: - bgp_notify_send (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_UNSUP_PARAM); - ret = -1; - break; + /* All OPEN option is parsed. Check capability when strict compare + flag is enabled.*/ + if (CHECK_FLAG(peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) { + /* If Unsupported Capability exists. */ + if (error != error_data) { + bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_UNSUP_CAPBL, + error_data, + error - error_data); + return -1; + } + + /* Check local capability does not negotiated with remote + peer. */ + if (!strict_capability_same(peer)) { + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_UNSUP_CAPBL); + return -1; + } } - /* Parse error. To accumulate all unsupported capability codes, - bgp_capability_parse does not return -1 when encounter - unsupported capability code. To detect that, please check - error and erro_data pointer, like below. */ - if (ret < 0) - return -1; - } - - /* All OPEN option is parsed. Check capability when strict compare - flag is enabled.*/ - if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) - { - /* If Unsupported Capability exists. */ - if (error != error_data) - { - bgp_notify_send_with_data (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_UNSUP_CAPBL, - error_data, error - error_data); - return -1; + /* Check there are no common AFI/SAFIs and send Unsupported Capability + error. */ + if (*mp_capability + && !CHECK_FLAG(peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) { + if (!peer->afc_nego[AFI_IP][SAFI_UNICAST] + && !peer->afc_nego[AFI_IP][SAFI_MULTICAST] + && !peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST] + && !peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] + && !peer->afc_nego[AFI_IP][SAFI_ENCAP] + && !peer->afc_nego[AFI_IP6][SAFI_UNICAST] + && !peer->afc_nego[AFI_IP6][SAFI_MULTICAST] + && !peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST] + && !peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN] + && !peer->afc_nego[AFI_IP6][SAFI_ENCAP] + && !peer->afc_nego[AFI_L2VPN][SAFI_EVPN]) { + zlog_err( + "%s [Error] Configured AFI/SAFIs do not " + "overlap with received MP capabilities", + peer->host); + + if (error != error_data) + bgp_notify_send_with_data( + peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_UNSUP_CAPBL, error_data, + error - error_data); + else + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_UNSUP_CAPBL); + return -1; + } } - - /* Check local capability does not negotiated with remote - peer. */ - if (! strict_capability_same (peer)) - { - bgp_notify_send (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_UNSUP_CAPBL); - return -1; - } - } - - /* Check there are no common AFI/SAFIs and send Unsupported Capability - error. */ - if (*mp_capability && - ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) - { - if (! peer->afc_nego[AFI_IP][SAFI_UNICAST] - && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST] - && ! peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST] - && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] - && ! peer->afc_nego[AFI_IP][SAFI_ENCAP] - && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST] - && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST] - && ! peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST] - && ! peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN] - && ! peer->afc_nego[AFI_IP6][SAFI_ENCAP] - && ! peer->afc_nego[AFI_L2VPN][SAFI_EVPN]) - { - zlog_err ("%s [Error] Configured AFI/SAFIs do not " - "overlap with received MP capabilities", - peer->host); - - if (error != error_data) - bgp_notify_send_with_data (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_UNSUP_CAPBL, - error_data, error - error_data); - else - bgp_notify_send (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_UNSUP_CAPBL); - return -1; - } - } - return 0; + return 0; } -static void -bgp_open_capability_orf (struct stream *s, struct peer *peer, - afi_t afi, safi_t safi, u_char code) +static void bgp_open_capability_orf(struct stream *s, struct peer *peer, + afi_t afi, safi_t safi, u_char code) { - u_char cap_len; - u_char orf_len; - unsigned long capp; - unsigned long orfp; - unsigned long numberp; - int number_of_orfs = 0; - iana_afi_t pkt_afi; - safi_t pkt_safi; - - /* Convert AFI, SAFI to values for packet. */ - bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); - - stream_putc (s, BGP_OPEN_OPT_CAP); - capp = stream_get_endp (s); /* Set Capability Len Pointer */ - stream_putc (s, 0); /* Capability Length */ - stream_putc (s, code); /* Capability Code */ - orfp = stream_get_endp (s); /* Set ORF Len Pointer */ - stream_putc (s, 0); /* ORF Length */ - stream_putw (s, pkt_afi); - stream_putc (s, 0); - stream_putc (s, pkt_safi); - numberp = stream_get_endp (s); /* Set Number Pointer */ - stream_putc (s, 0); /* Number of ORFs */ - - /* Address Prefix ORF */ - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM) - || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM)) - { - stream_putc (s, (code == CAPABILITY_CODE_ORF ? - ORF_TYPE_PREFIX : ORF_TYPE_PREFIX_OLD)); - - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM) - && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM)) - { - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV); - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV); - stream_putc (s, ORF_MODE_BOTH); - } - else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)) - { - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV); - stream_putc (s, ORF_MODE_SEND); - } - else - { - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV); - stream_putc (s, ORF_MODE_RECEIVE); + u_char cap_len; + u_char orf_len; + unsigned long capp; + unsigned long orfp; + unsigned long numberp; + int number_of_orfs = 0; + iana_afi_t pkt_afi; + safi_t pkt_safi; + + /* Convert AFI, SAFI to values for packet. */ + bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi); + + stream_putc(s, BGP_OPEN_OPT_CAP); + capp = stream_get_endp(s); /* Set Capability Len Pointer */ + stream_putc(s, 0); /* Capability Length */ + stream_putc(s, code); /* Capability Code */ + orfp = stream_get_endp(s); /* Set ORF Len Pointer */ + stream_putc(s, 0); /* ORF Length */ + stream_putw(s, pkt_afi); + stream_putc(s, 0); + stream_putc(s, pkt_safi); + numberp = stream_get_endp(s); /* Set Number Pointer */ + stream_putc(s, 0); /* Number of ORFs */ + + /* Address Prefix ORF */ + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM) + || CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM)) { + stream_putc(s, (code == CAPABILITY_CODE_ORF + ? ORF_TYPE_PREFIX + : ORF_TYPE_PREFIX_OLD)); + + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ORF_PREFIX_SM) + && CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ORF_PREFIX_RM)) { + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_SM_ADV); + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_ADV); + stream_putc(s, ORF_MODE_BOTH); + } else if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ORF_PREFIX_SM)) { + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_SM_ADV); + stream_putc(s, ORF_MODE_SEND); + } else { + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_ADV); + stream_putc(s, ORF_MODE_RECEIVE); + } + number_of_orfs++; } - number_of_orfs++; - } - /* Total Number of ORFs. */ - stream_putc_at (s, numberp, number_of_orfs); + /* Total Number of ORFs. */ + stream_putc_at(s, numberp, number_of_orfs); - /* Total ORF Len. */ - orf_len = stream_get_endp (s) - orfp - 1; - stream_putc_at (s, orfp, orf_len); + /* Total ORF Len. */ + orf_len = stream_get_endp(s) - orfp - 1; + stream_putc_at(s, orfp, orf_len); - /* Total Capability Len. */ - cap_len = stream_get_endp (s) - capp - 1; - stream_putc_at (s, capp, cap_len); + /* Total Capability Len. */ + cap_len = stream_get_endp(s) - capp - 1; + stream_putc_at(s, capp, cap_len); } /* Fill in capability open option to the packet. */ -void -bgp_open_capability (struct stream *s, struct peer *peer) +void bgp_open_capability(struct stream *s, struct peer *peer) { - u_char len; - unsigned long cp, capp, rcapp; - iana_afi_t pkt_afi; - afi_t afi; - safi_t safi, pkt_safi; - as_t local_as; - u_int32_t restart_time; - u_char afi_safi_count = 0; - struct utsname names; - int adv_addpath_tx = 0; - - /* Remember current pointer for Opt Parm Len. */ - cp = stream_get_endp (s); - - /* Opt Parm Len. */ - stream_putc (s, 0); - - /* Do not send capability. */ - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN) - || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY)) - return; - - /* MP capability for configured AFI, SAFI */ - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - if (peer->afc[afi][safi]) - { - /* Convert AFI, SAFI to values for packet. */ - bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); - - peer->afc_adv[afi][safi] = 1; - stream_putc (s, BGP_OPEN_OPT_CAP); - stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); - stream_putc (s, CAPABILITY_CODE_MP); - stream_putc (s, CAPABILITY_CODE_MP_LEN); - stream_putw (s, pkt_afi); - stream_putc (s, 0); - stream_putc (s, pkt_safi); - - /* Extended nexthop capability - currently supporting RFC-5549 for - * Link-Local peering only - */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE) && - peer->su.sa.sa_family == AF_INET6 && - IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr) && - afi == AFI_IP && - (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) - { - /* RFC 5549 Extended Next Hop Encoding */ - SET_FLAG (peer->cap, PEER_CAP_ENHE_ADV); - stream_putc (s, BGP_OPEN_OPT_CAP); - stream_putc (s, CAPABILITY_CODE_ENHE_LEN + 2); - stream_putc (s, CAPABILITY_CODE_ENHE); - stream_putc (s, CAPABILITY_CODE_ENHE_LEN); - - SET_FLAG (peer->af_cap[AFI_IP][safi], PEER_CAP_ENHE_AF_ADV); - stream_putw (s, pkt_afi); - stream_putw (s, pkt_safi); - stream_putw (s, afi_int2iana(AFI_IP6)); - - if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_RCV)) - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_NEGO); - } - } - } - - /* Route refresh. */ - SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV); - stream_putc (s, BGP_OPEN_OPT_CAP); - stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2); - stream_putc (s, CAPABILITY_CODE_REFRESH_OLD); - stream_putc (s, CAPABILITY_CODE_REFRESH_LEN); - stream_putc (s, BGP_OPEN_OPT_CAP); - stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2); - stream_putc (s, CAPABILITY_CODE_REFRESH); - stream_putc (s, CAPABILITY_CODE_REFRESH_LEN); - - /* AS4 */ - SET_FLAG (peer->cap, PEER_CAP_AS4_ADV); - stream_putc (s, BGP_OPEN_OPT_CAP); - stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2); - stream_putc (s, CAPABILITY_CODE_AS4); - stream_putc (s, CAPABILITY_CODE_AS4_LEN); - if ( peer->change_local_as ) - local_as = peer->change_local_as; - else - local_as = peer->local_as; - stream_putl (s, local_as ); - - /* AddPath */ - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - if (peer->afc[afi][safi]) - { - afi_safi_count++; - - /* Only advertise addpath TX if a feature that will use it is - * configured */ - if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS) || - CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) - adv_addpath_tx = 1; - } - - SET_FLAG (peer->cap, PEER_CAP_ADDPATH_ADV); - stream_putc (s, BGP_OPEN_OPT_CAP); - stream_putc (s, (CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count) + 2); - stream_putc (s, CAPABILITY_CODE_ADDPATH); - stream_putc (s, CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count); - - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - if (peer->afc[afi][safi]) - { - /* Convert AFI, SAFI to values for packet. */ - bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); - - stream_putw (s, pkt_afi); - stream_putc (s, pkt_safi); - - if (adv_addpath_tx) - { - stream_putc (s, BGP_ADDPATH_RX|BGP_ADDPATH_TX); - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV); - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_ADV); - } - else - { - stream_putc (s, BGP_ADDPATH_RX); - SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV); - UNSET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_ADV); - } - } - - /* ORF capability. */ - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM) - || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM)) - { - bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD); - bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF); + u_char len; + unsigned long cp, capp, rcapp; + iana_afi_t pkt_afi; + afi_t afi; + safi_t safi, pkt_safi; + as_t local_as; + u_int32_t restart_time; + u_char afi_safi_count = 0; + struct utsname names; + int adv_addpath_tx = 0; + + /* Remember current pointer for Opt Parm Len. */ + cp = stream_get_endp(s); + + /* Opt Parm Len. */ + stream_putc(s, 0); + + /* Do not send capability. */ + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN) + || CHECK_FLAG(peer->flags, PEER_FLAG_DONT_CAPABILITY)) + return; + + /* MP capability for configured AFI, SAFI */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + if (peer->afc[afi][safi]) { + /* Convert AFI, SAFI to values for packet. */ + bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, + &pkt_safi); + + peer->afc_adv[afi][safi] = 1; + stream_putc(s, BGP_OPEN_OPT_CAP); + stream_putc(s, CAPABILITY_CODE_MP_LEN + 2); + stream_putc(s, CAPABILITY_CODE_MP); + stream_putc(s, CAPABILITY_CODE_MP_LEN); + stream_putw(s, pkt_afi); + stream_putc(s, 0); + stream_putc(s, pkt_safi); + + /* Extended nexthop capability - currently + * supporting RFC-5549 for + * Link-Local peering only + */ + if (CHECK_FLAG(peer->flags, + PEER_FLAG_CAPABILITY_ENHE) + && peer->su.sa.sa_family == AF_INET6 + && IN6_IS_ADDR_LINKLOCAL( + &peer->su.sin6.sin6_addr) + && afi == AFI_IP + && (safi == SAFI_UNICAST + || safi == SAFI_LABELED_UNICAST)) { + /* RFC 5549 Extended Next Hop Encoding + */ + SET_FLAG(peer->cap, PEER_CAP_ENHE_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); + stream_putc(s, + CAPABILITY_CODE_ENHE_LEN + + 2); + stream_putc(s, CAPABILITY_CODE_ENHE); + stream_putc(s, + CAPABILITY_CODE_ENHE_LEN); + + SET_FLAG(peer->af_cap[AFI_IP][safi], + PEER_CAP_ENHE_AF_ADV); + stream_putw(s, pkt_afi); + stream_putw(s, pkt_safi); + stream_putw(s, afi_int2iana(AFI_IP6)); + + if (CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ENHE_AF_RCV)) + SET_FLAG( + peer->af_cap[afi][safi], + PEER_CAP_ENHE_AF_NEGO); + } + } + } + + /* Route refresh. */ + SET_FLAG(peer->cap, PEER_CAP_REFRESH_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); + stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2); + stream_putc(s, CAPABILITY_CODE_REFRESH_OLD); + stream_putc(s, CAPABILITY_CODE_REFRESH_LEN); + stream_putc(s, BGP_OPEN_OPT_CAP); + stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2); + stream_putc(s, CAPABILITY_CODE_REFRESH); + stream_putc(s, CAPABILITY_CODE_REFRESH_LEN); + + /* AS4 */ + SET_FLAG(peer->cap, PEER_CAP_AS4_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); + stream_putc(s, CAPABILITY_CODE_AS4_LEN + 2); + stream_putc(s, CAPABILITY_CODE_AS4); + stream_putc(s, CAPABILITY_CODE_AS4_LEN); + if (peer->change_local_as) + local_as = peer->change_local_as; + else + local_as = peer->local_as; + stream_putl(s, local_as); + + /* AddPath */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + if (peer->afc[afi][safi]) { + afi_safi_count++; + + /* Only advertise addpath TX if a feature that + * will use it is + * configured */ + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ADDPATH_TX_ALL_PATHS) + || CHECK_FLAG( + peer->af_flags[afi][safi], + PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) + adv_addpath_tx = 1; + } + + SET_FLAG(peer->cap, PEER_CAP_ADDPATH_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); + stream_putc(s, (CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count) + 2); + stream_putc(s, CAPABILITY_CODE_ADDPATH); + stream_putc(s, CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + if (peer->afc[afi][safi]) { + /* Convert AFI, SAFI to values for packet. */ + bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, + &pkt_safi); + + stream_putw(s, pkt_afi); + stream_putc(s, pkt_safi); + + if (adv_addpath_tx) { + stream_putc(s, + BGP_ADDPATH_RX + | BGP_ADDPATH_TX); + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ADDPATH_AF_RX_ADV); + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ADDPATH_AF_TX_ADV); + } else { + stream_putc(s, BGP_ADDPATH_RX); + SET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ADDPATH_AF_RX_ADV); + UNSET_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ADDPATH_AF_TX_ADV); + } + } + + /* ORF capability. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ORF_PREFIX_SM) + || CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ORF_PREFIX_RM)) { + bgp_open_capability_orf( + s, peer, afi, safi, + CAPABILITY_CODE_ORF_OLD); + bgp_open_capability_orf(s, peer, afi, safi, + CAPABILITY_CODE_ORF); + } + + /* Dynamic capability. */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) { + SET_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); + stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2); + stream_putc(s, CAPABILITY_CODE_DYNAMIC_OLD); + stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN); + stream_putc(s, BGP_OPEN_OPT_CAP); + stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2); + stream_putc(s, CAPABILITY_CODE_DYNAMIC); + stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN); } - /* Dynamic capability. */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) - { - SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV); - stream_putc (s, BGP_OPEN_OPT_CAP); - stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2); - stream_putc (s, CAPABILITY_CODE_DYNAMIC_OLD); - stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN); - stream_putc (s, BGP_OPEN_OPT_CAP); - stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2); - stream_putc (s, CAPABILITY_CODE_DYNAMIC); - stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN); - } - - /* Hostname capability */ - uname(&names); - if (names.nodename[0] != '\0') - { - SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV); - stream_putc (s, BGP_OPEN_OPT_CAP); - rcapp = stream_get_endp(s); /* Ptr to length placeholder */ - stream_putc(s, 0); /* dummy len for now */ - stream_putc (s, CAPABILITY_CODE_FQDN); - capp = stream_get_endp(s); - stream_putc(s, 0); /* dummy len for now */ - len = strlen(names.nodename); - if (len > BGP_MAX_HOSTNAME) - len = BGP_MAX_HOSTNAME; - - stream_putc(s, len); - stream_put(s, names.nodename, len); + /* Hostname capability */ + uname(&names); + if (names.nodename[0] != '\0') { + SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); + rcapp = stream_get_endp(s); /* Ptr to length placeholder */ + stream_putc(s, 0); /* dummy len for now */ + stream_putc(s, CAPABILITY_CODE_FQDN); + capp = stream_get_endp(s); + stream_putc(s, 0); /* dummy len for now */ + len = strlen(names.nodename); + if (len > BGP_MAX_HOSTNAME) + len = BGP_MAX_HOSTNAME; + + stream_putc(s, len); + stream_put(s, names.nodename, len); #ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME - if ((names.domainname[0] != '\0') && - (strcmp(names.domainname, "(none)") != 0)) - { - len = strlen(names.domainname); - if (len > BGP_MAX_HOSTNAME) - len = BGP_MAX_HOSTNAME; - - stream_putc(s, len); - stream_put(s, names.domainname, len); - } - else + if ((names.domainname[0] != '\0') + && (strcmp(names.domainname, "(none)") != 0)) { + len = strlen(names.domainname); + if (len > BGP_MAX_HOSTNAME) + len = BGP_MAX_HOSTNAME; + + stream_putc(s, len); + stream_put(s, names.domainname, len); + } else #endif - { - stream_putc(s, 0); /* 0 length */ - } + { + stream_putc(s, 0); /* 0 length */ + } - /* Set the lengths straight */ - len = stream_get_endp(s) - rcapp - 1; - stream_putc_at(s, rcapp, len); - len = stream_get_endp(s) - capp - 1; - stream_putc_at(s, capp, len); + /* Set the lengths straight */ + len = stream_get_endp(s) - rcapp - 1; + stream_putc_at(s, rcapp, len); + len = stream_get_endp(s) - capp - 1; + stream_putc_at(s, capp, len); - if (bgp_debug_neighbor_events(peer)) + if (bgp_debug_neighbor_events(peer)) #ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME - zlog_debug("%s Sending hostname cap with hn = %s, dn = %s", - peer->host, names.nodename, names.domainname); + zlog_debug( + "%s Sending hostname cap with hn = %s, dn = %s", + peer->host, names.nodename, names.domainname); #else - zlog_debug("%s Sending hostname cap with hn = %s", peer->host, - names.nodename); + zlog_debug("%s Sending hostname cap with hn = %s", + peer->host, names.nodename); #endif - } - - /* Sending base graceful-restart capability irrespective of the config */ - SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV); - stream_putc (s, BGP_OPEN_OPT_CAP); - capp = stream_get_endp (s); /* Set Capability Len Pointer */ - stream_putc (s, 0); /* Capability Length */ - stream_putc (s, CAPABILITY_CODE_RESTART); - rcapp = stream_get_endp (s); /* Set Restart Capability Len Pointer */ - stream_putc (s, 0); - restart_time = peer->bgp->restart_time; - if (peer->bgp->t_startup) - { - SET_FLAG (restart_time, RESTART_R_BIT); - SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_ADV); - } - stream_putw (s, restart_time); - - /* Send address-family specific graceful-restart capability only when GR config - is present */ - if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART)) - { - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - if (peer->afc[afi][safi]) - { - /* Convert AFI, SAFI to values for packet. */ - bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); - stream_putw (s, pkt_afi); - stream_putc (s, pkt_safi); - if (bgp_flag_check(peer->bgp, BGP_FLAG_GR_PRESERVE_FWD)) - stream_putc (s, RESTART_F_BIT); - else - stream_putc (s, 0); - } - } - - /* Total Graceful restart capability Len. */ - len = stream_get_endp (s) - rcapp - 1; - stream_putc_at (s, rcapp, len); - - /* Total Capability Len. */ - len = stream_get_endp (s) - capp - 1; - stream_putc_at (s, capp, len); - - /* Total Opt Parm Len. */ - len = stream_get_endp (s) - cp - 1; - stream_putc_at (s, cp, len); + } + + /* Sending base graceful-restart capability irrespective of the config + */ + SET_FLAG(peer->cap, PEER_CAP_RESTART_ADV); + stream_putc(s, BGP_OPEN_OPT_CAP); + capp = stream_get_endp(s); /* Set Capability Len Pointer */ + stream_putc(s, 0); /* Capability Length */ + stream_putc(s, CAPABILITY_CODE_RESTART); + rcapp = stream_get_endp(s); /* Set Restart Capability Len Pointer */ + stream_putc(s, 0); + restart_time = peer->bgp->restart_time; + if (peer->bgp->t_startup) { + SET_FLAG(restart_time, RESTART_R_BIT); + SET_FLAG(peer->cap, PEER_CAP_RESTART_BIT_ADV); + } + stream_putw(s, restart_time); + + /* Send address-family specific graceful-restart capability only when GR + config + is present */ + if (bgp_flag_check(peer->bgp, BGP_FLAG_GRACEFUL_RESTART)) { + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + if (peer->afc[afi][safi]) { + /* Convert AFI, SAFI to values for + * packet. */ + bgp_map_afi_safi_int2iana( + afi, safi, &pkt_afi, &pkt_safi); + stream_putw(s, pkt_afi); + stream_putc(s, pkt_safi); + if (bgp_flag_check( + peer->bgp, + BGP_FLAG_GR_PRESERVE_FWD)) + stream_putc(s, RESTART_F_BIT); + else + stream_putc(s, 0); + } + } + + /* Total Graceful restart capability Len. */ + len = stream_get_endp(s) - rcapp - 1; + stream_putc_at(s, rcapp, len); + + /* Total Capability Len. */ + len = stream_get_endp(s) - capp - 1; + stream_putc_at(s, capp, len); + + /* Total Opt Parm Len. */ + len = stream_get_endp(s) - cp - 1; + stream_putc_at(s, cp, len); } diff --git a/bgpd/bgp_open.h b/bgpd/bgp_open.h index 0b0d9023e..cbd32116b 100644 --- a/bgpd/bgp_open.h +++ b/bgpd/bgp_open.h @@ -22,36 +22,31 @@ #define _QUAGGA_BGP_OPEN_H /* Standard header for capability TLV */ -struct capability_header -{ - u_char code; - u_char length; +struct capability_header { + u_char code; + u_char length; }; /* Generic MP capability data */ -struct capability_mp_data -{ - iana_afi_t afi; - u_char reserved; - safi_t safi; +struct capability_mp_data { + iana_afi_t afi; + u_char reserved; + safi_t safi; }; -struct capability_as4 -{ - uint32_t as4; +struct capability_as4 { + uint32_t as4; }; -struct graceful_restart_af -{ - afi_t afi; - safi_t safi; - u_char flag; +struct graceful_restart_af { + afi_t afi; + safi_t safi; + u_char flag; }; -struct capability_gr -{ - u_int16_t restart_flag_time; - struct graceful_restart_af gr[]; +struct capability_gr { + u_int16_t restart_flag_time; + struct graceful_restart_af gr[]; }; /* Capability Code */ @@ -68,7 +63,6 @@ struct capability_gr #define CAPABILITY_CODE_REFRESH_OLD 128 /* Route Refresh Capability(cisco) */ #define CAPABILITY_CODE_ORF_OLD 130 /* Cooperative Route Filtering Capability(cisco) */ - /* Capability Length */ #define CAPABILITY_CODE_MP_LEN 4 #define CAPABILITY_CODE_REFRESH_LEN 0 @@ -99,9 +93,10 @@ struct capability_gr #define RESTART_R_BIT 0x8000 #define RESTART_F_BIT 0x80 -extern int bgp_open_option_parse (struct peer *, u_char, int *); -extern void bgp_open_capability (struct stream *, struct peer *); -extern void bgp_capability_vty_out (struct vty *, struct peer *, u_char, json_object *); -extern as_t peek_for_as4_capability (struct peer *, u_char); +extern int bgp_open_option_parse(struct peer *, u_char, int *); +extern void bgp_open_capability(struct stream *, struct peer *); +extern void bgp_capability_vty_out(struct vty *, struct peer *, u_char, + json_object *); +extern as_t peek_for_as4_capability(struct peer *, u_char); #endif /* _QUAGGA_BGP_OPEN_H */ diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 2b48b34e1..2860113d1 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -27,7 +27,7 @@ #include "command.h" #include "log.h" #include "memory.h" -#include "sockunion.h" /* for inet_ntop () */ +#include "sockunion.h" /* for inet_ntop () */ #include "sockopt.h" #include "linklist.h" #include "plist.h" @@ -56,2289 +56,2287 @@ #include "bgpd/bgp_label.h" /* Set up BGP packet marker and packet type. */ -int -bgp_packet_set_marker (struct stream *s, u_char type) +int bgp_packet_set_marker(struct stream *s, u_char type) { - int i; + int i; - /* Fill in marker. */ - for (i = 0; i < BGP_MARKER_SIZE; i++) - stream_putc (s, 0xff); + /* Fill in marker. */ + for (i = 0; i < BGP_MARKER_SIZE; i++) + stream_putc(s, 0xff); - /* Dummy total length. This field is should be filled in later on. */ - stream_putw (s, 0); + /* Dummy total length. This field is should be filled in later on. */ + stream_putw(s, 0); - /* BGP packet type. */ - stream_putc (s, type); + /* BGP packet type. */ + stream_putc(s, type); - /* Return current stream size. */ - return stream_get_endp (s); + /* Return current stream size. */ + return stream_get_endp(s); } /* Set BGP packet header size entry. If size is zero then use current stream size. */ -int -bgp_packet_set_size (struct stream *s) +int bgp_packet_set_size(struct stream *s) { - int cp; + int cp; - /* Preserve current pointer. */ - cp = stream_get_endp (s); - stream_putw_at (s, BGP_MARKER_SIZE, cp); + /* Preserve current pointer. */ + cp = stream_get_endp(s); + stream_putw_at(s, BGP_MARKER_SIZE, cp); - return cp; + return cp; } /* Add new packet to the peer. */ -void -bgp_packet_add (struct peer *peer, struct stream *s) +void bgp_packet_add(struct peer *peer, struct stream *s) { - /* Add packet to the end of list. */ - stream_fifo_push (peer->obuf, s); + /* Add packet to the end of list. */ + stream_fifo_push(peer->obuf, s); } /* Free first packet. */ -static void -bgp_packet_delete (struct peer *peer) +static void bgp_packet_delete(struct peer *peer) { - stream_free (stream_fifo_pop (peer->obuf)); + stream_free(stream_fifo_pop(peer->obuf)); } /* Check file descriptor whether connect is established. */ -int -bgp_connect_check (struct peer *peer, int change_state) +int bgp_connect_check(struct peer *peer, int change_state) { - int status; - socklen_t slen; - int ret; - - /* Anyway I have to reset read and write thread. */ - BGP_READ_OFF (peer->t_read); - BGP_WRITE_OFF (peer->t_write); - - /* Check file descriptor. */ - slen = sizeof (status); - ret = getsockopt(peer->fd, SOL_SOCKET, SO_ERROR, (void *) &status, &slen); - - /* If getsockopt is fail, this is fatal error. */ - if (ret < 0) - { - zlog_info ("can't get sockopt for nonblocking connect"); - BGP_EVENT_ADD (peer, TCP_fatal_error); - return -1; - } - - /* When status is 0 then TCP connection is established. */ - if (status == 0) - { - BGP_EVENT_ADD (peer, TCP_connection_open); - return 1; - } - else - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s [Event] Connect failed (%s)", - peer->host, safe_strerror (errno)); - if (change_state) - BGP_EVENT_ADD (peer, TCP_connection_open_failed); - return 0; - } + int status; + socklen_t slen; + int ret; + + /* Anyway I have to reset read and write thread. */ + BGP_READ_OFF(peer->t_read); + BGP_WRITE_OFF(peer->t_write); + + /* Check file descriptor. */ + slen = sizeof(status); + ret = getsockopt(peer->fd, SOL_SOCKET, SO_ERROR, (void *)&status, + &slen); + + /* If getsockopt is fail, this is fatal error. */ + if (ret < 0) { + zlog_info("can't get sockopt for nonblocking connect"); + BGP_EVENT_ADD(peer, TCP_fatal_error); + return -1; + } + + /* When status is 0 then TCP connection is established. */ + if (status == 0) { + BGP_EVENT_ADD(peer, TCP_connection_open); + return 1; + } else { + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s [Event] Connect failed (%s)", peer->host, + safe_strerror(errno)); + if (change_state) + BGP_EVENT_ADD(peer, TCP_connection_open_failed); + return 0; + } } -static struct stream * -bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi) +static struct stream *bgp_update_packet_eor(struct peer *peer, afi_t afi, + safi_t safi) { - struct stream *s; - iana_afi_t pkt_afi; - safi_t pkt_safi; - - if (DISABLE_BGP_ANNOUNCE) - return NULL; - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("send End-of-RIB for %s to %s", afi_safi_print (afi, safi), peer->host); - - s = stream_new (BGP_MAX_PACKET_SIZE); - - /* Make BGP update packet. */ - bgp_packet_set_marker (s, BGP_MSG_UPDATE); - - /* Unfeasible Routes Length */ - stream_putw (s, 0); - - if (afi == AFI_IP && safi == SAFI_UNICAST) - { - /* Total Path Attribute Length */ - stream_putw (s, 0); - } - else - { - /* Convert AFI, SAFI to values for packet. */ - bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); - - /* Total Path Attribute Length */ - stream_putw (s, 6); - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); - stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI); - stream_putc (s, 3); - stream_putw (s, pkt_afi); - stream_putc (s, pkt_safi); - } - - bgp_packet_set_size (s); - bgp_packet_add (peer, s); - return s; + struct stream *s; + iana_afi_t pkt_afi; + safi_t pkt_safi; + + if (DISABLE_BGP_ANNOUNCE) + return NULL; + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("send End-of-RIB for %s to %s", + afi_safi_print(afi, safi), peer->host); + + s = stream_new(BGP_MAX_PACKET_SIZE); + + /* Make BGP update packet. */ + bgp_packet_set_marker(s, BGP_MSG_UPDATE); + + /* Unfeasible Routes Length */ + stream_putw(s, 0); + + if (afi == AFI_IP && safi == SAFI_UNICAST) { + /* Total Path Attribute Length */ + stream_putw(s, 0); + } else { + /* Convert AFI, SAFI to values for packet. */ + bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi); + + /* Total Path Attribute Length */ + stream_putw(s, 6); + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL); + stream_putc(s, BGP_ATTR_MP_UNREACH_NLRI); + stream_putc(s, 3); + stream_putw(s, pkt_afi); + stream_putc(s, pkt_safi); + } + + bgp_packet_set_size(s); + bgp_packet_add(peer, s); + return s; } /* Get next packet to be written. */ -static struct stream * -bgp_write_packet (struct peer *peer) +static struct stream *bgp_write_packet(struct peer *peer) { - struct stream *s = NULL; - struct peer_af *paf; - struct bpacket *next_pkt; - afi_t afi; - safi_t safi; - - s = stream_fifo_head (peer->obuf); - if (s) - return s; - - /* - * The code beyond this part deals with update packets, proceed only - * if peer is Established and updates are not on hold (as part of - * update-delay post processing). - */ - if (peer->status != Established) - return NULL; - - if (peer->bgp && peer->bgp->main_peers_update_hold) - return NULL; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - paf = peer_af_find (peer, afi, safi); - if (!paf || !PAF_SUBGRP(paf)) - continue; - next_pkt = paf->next_pkt_to_send; - - /* Try to generate a packet for the peer if we are at the end of - * the list. Always try to push out WITHDRAWs first. */ - if (!next_pkt || !next_pkt->buffer) - { - next_pkt = subgroup_withdraw_packet(PAF_SUBGRP(paf)); - if (!next_pkt || !next_pkt->buffer) - subgroup_update_packet (PAF_SUBGRP(paf)); - next_pkt = paf->next_pkt_to_send; - } - - /* If we still don't have a packet to send to the peer, then - * try to find out out if we have to send eor or if not, skip to - * the next AFI, SAFI. - * Don't send the EOR prematurely... if the subgroup's coalesce - * timer is running, the adjacency-out structure is not created - * yet. + struct stream *s = NULL; + struct peer_af *paf; + struct bpacket *next_pkt; + afi_t afi; + safi_t safi; + + s = stream_fifo_head(peer->obuf); + if (s) + return s; + + /* + * The code beyond this part deals with update packets, proceed only + * if peer is Established and updates are not on hold (as part of + * update-delay post processing). */ - if (!next_pkt || !next_pkt->buffer) - { - if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV)) - { - if (!(PAF_SUBGRP(paf))->t_coalesce && - peer->afc_nego[afi][safi] && peer->synctime - && ! CHECK_FLAG (peer->af_sflags[afi][safi], - PEER_STATUS_EOR_SEND)) - { - SET_FLAG (peer->af_sflags[afi][safi], - PEER_STATUS_EOR_SEND); - return bgp_update_packet_eor (peer, afi, safi); - } - } - continue; - } - - - /* - * Found a packet template to send, overwrite packet with appropriate - * attributes from peer and advance peer - */ - s = bpacket_reformat_for_peer (next_pkt, paf); - bpacket_queue_advance_peer (paf); - return s; - } + if (peer->status != Established) + return NULL; + + if (peer->bgp && peer->bgp->main_peers_update_hold) + return NULL; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + paf = peer_af_find(peer, afi, safi); + if (!paf || !PAF_SUBGRP(paf)) + continue; + next_pkt = paf->next_pkt_to_send; + + /* Try to generate a packet for the peer if we are at + * the end of + * the list. Always try to push out WITHDRAWs first. */ + if (!next_pkt || !next_pkt->buffer) { + next_pkt = subgroup_withdraw_packet( + PAF_SUBGRP(paf)); + if (!next_pkt || !next_pkt->buffer) + subgroup_update_packet(PAF_SUBGRP(paf)); + next_pkt = paf->next_pkt_to_send; + } + + /* If we still don't have a packet to send to the peer, + * then + * try to find out out if we have to send eor or if not, + * skip to + * the next AFI, SAFI. + * Don't send the EOR prematurely... if the subgroup's + * coalesce + * timer is running, the adjacency-out structure is not + * created + * yet. + */ + if (!next_pkt || !next_pkt->buffer) { + if (CHECK_FLAG(peer->cap, + PEER_CAP_RESTART_RCV)) { + if (!(PAF_SUBGRP(paf))->t_coalesce + && peer->afc_nego[afi][safi] + && peer->synctime + && !CHECK_FLAG( + peer->af_sflags[afi] + [safi], + PEER_STATUS_EOR_SEND)) { + SET_FLAG(peer->af_sflags[afi] + [safi], + PEER_STATUS_EOR_SEND); + return bgp_update_packet_eor( + peer, afi, safi); + } + } + continue; + } + + + /* + * Found a packet template to send, overwrite packet + * with appropriate + * attributes from peer and advance peer + */ + s = bpacket_reformat_for_peer(next_pkt, paf); + bpacket_queue_advance_peer(paf); + return s; + } - return NULL; + return NULL; } /* The next action for the peer from a write perspective */ -static void -bgp_write_proceed_actions (struct peer *peer) +static void bgp_write_proceed_actions(struct peer *peer) { - afi_t afi; - safi_t safi; - struct peer_af *paf; - struct bpacket *next_pkt; - int fullq_found = 0; - struct update_subgroup *subgrp; - - if (stream_fifo_head (peer->obuf)) - { - BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); - return; - } - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - paf = peer_af_find (peer, afi, safi); - if (!paf) - continue; - subgrp = paf->subgroup; - if (!subgrp) - continue; - - next_pkt = paf->next_pkt_to_send; - if (next_pkt && next_pkt->buffer) - { - BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); - return; - } - - /* No packets readily available for AFI/SAFI, are there subgroup packets - * that need to be generated? */ - if (bpacket_queue_is_full(SUBGRP_INST(subgrp), - SUBGRP_PKTQ(subgrp))) - fullq_found = 1; - else if (subgroup_packets_to_build (subgrp)) - { - BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); - return; - } - - /* No packets to send, see if EOR is pending */ - if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV)) - { - if (!subgrp->t_coalesce && - peer->afc_nego[afi][safi] && - peer->synctime && - !CHECK_FLAG(peer->af_sflags[afi][safi], - PEER_STATUS_EOR_SEND) && - safi != SAFI_MPLS_VPN) - { - BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); - return; - } - - } - } - if (fullq_found) - { - BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); - return; - } + afi_t afi; + safi_t safi; + struct peer_af *paf; + struct bpacket *next_pkt; + int fullq_found = 0; + struct update_subgroup *subgrp; + + if (stream_fifo_head(peer->obuf)) { + BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd); + return; + } + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + paf = peer_af_find(peer, afi, safi); + if (!paf) + continue; + subgrp = paf->subgroup; + if (!subgrp) + continue; + + next_pkt = paf->next_pkt_to_send; + if (next_pkt && next_pkt->buffer) { + BGP_WRITE_ON(peer->t_write, bgp_write, + peer->fd); + return; + } + + /* No packets readily available for AFI/SAFI, are there + * subgroup packets + * that need to be generated? */ + if (bpacket_queue_is_full(SUBGRP_INST(subgrp), + SUBGRP_PKTQ(subgrp))) + fullq_found = 1; + else if (subgroup_packets_to_build(subgrp)) { + BGP_WRITE_ON(peer->t_write, bgp_write, + peer->fd); + return; + } + + /* No packets to send, see if EOR is pending */ + if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV)) { + if (!subgrp->t_coalesce + && peer->afc_nego[afi][safi] + && peer->synctime + && !CHECK_FLAG(peer->af_sflags[afi][safi], + PEER_STATUS_EOR_SEND) + && safi != SAFI_MPLS_VPN) { + BGP_WRITE_ON(peer->t_write, bgp_write, + peer->fd); + return; + } + } + } + if (fullq_found) { + BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd); + return; + } } /* Write packet to the peer. */ -int -bgp_write (struct thread *thread) +int bgp_write(struct thread *thread) { - struct peer *peer; - u_char type; - struct stream *s; - int num; - int update_last_write = 0; - unsigned int count = 0; - unsigned int oc = 0; - - /* Yes first of all get peer pointer. */ - peer = THREAD_ARG (thread); - peer->t_write = NULL; - - /* For non-blocking IO check. */ - if (peer->status == Connect) - { - bgp_connect_check (peer, 1); - return 0; - } - - s = bgp_write_packet (peer); - if (!s) - { - bgp_write_proceed_actions (peer); - return 0; - } - - sockopt_cork (peer->fd, 1); - - oc = peer->update_out; - - /* Nonblocking write until TCP output buffer is full. */ - do - { - int writenum; - - /* Number of bytes to be sent. */ - writenum = stream_get_endp (s) - stream_get_getp (s); - - /* Call write() system call. */ - num = write (peer->fd, STREAM_PNT (s), writenum); - if (num < 0) - { - /* write failed either retry needed or error */ - if (ERRNO_IO_RETRY(errno)) - break; - - BGP_EVENT_ADD (peer, TCP_fatal_error); - return 0; + struct peer *peer; + u_char type; + struct stream *s; + int num; + int update_last_write = 0; + unsigned int count = 0; + unsigned int oc = 0; + + /* Yes first of all get peer pointer. */ + peer = THREAD_ARG(thread); + peer->t_write = NULL; + + /* For non-blocking IO check. */ + if (peer->status == Connect) { + bgp_connect_check(peer, 1); + return 0; } - if (num != writenum) - { - /* Partial write */ - stream_forward_getp (s, num); - break; + s = bgp_write_packet(peer); + if (!s) { + bgp_write_proceed_actions(peer); + return 0; } - /* Retrieve BGP packet type. */ - stream_set_getp (s, BGP_MARKER_SIZE + 2); - type = stream_getc (s); + sockopt_cork(peer->fd, 1); - switch (type) - { - case BGP_MSG_OPEN: - peer->open_out++; - break; - case BGP_MSG_UPDATE: - peer->update_out++; - break; - case BGP_MSG_NOTIFY: - peer->notify_out++; - /* Double start timer. */ - peer->v_start *= 2; + oc = peer->update_out; - /* Overflow check. */ - if (peer->v_start >= (60 * 2)) - peer->v_start = (60 * 2); + /* Nonblocking write until TCP output buffer is full. */ + do { + int writenum; - /* Flush any existing events */ - BGP_EVENT_ADD (peer, BGP_Stop); - goto done; - - case BGP_MSG_KEEPALIVE: - peer->keepalive_out++; - break; - case BGP_MSG_ROUTE_REFRESH_NEW: - case BGP_MSG_ROUTE_REFRESH_OLD: - peer->refresh_out++; - break; - case BGP_MSG_CAPABILITY: - peer->dynamic_cap_out++; - break; - } + /* Number of bytes to be sent. */ + writenum = stream_get_endp(s) - stream_get_getp(s); - /* OK we send packet so delete it. */ - bgp_packet_delete (peer); - update_last_write = 1; - } - while (++count < peer->bgp->wpkt_quanta && - (s = bgp_write_packet (peer)) != NULL); + /* Call write() system call. */ + num = write(peer->fd, STREAM_PNT(s), writenum); + if (num < 0) { + /* write failed either retry needed or error */ + if (ERRNO_IO_RETRY(errno)) + break; - bgp_write_proceed_actions (peer); + BGP_EVENT_ADD(peer, TCP_fatal_error); + return 0; + } - done: - /* Update last_update if UPDATEs were written. */ - if (peer->update_out > oc) - peer->last_update = bgp_clock (); + if (num != writenum) { + /* Partial write */ + stream_forward_getp(s, num); + break; + } - /* If we TXed any flavor of packet update last_write */ - if (update_last_write) - peer->last_write = bgp_clock (); + /* Retrieve BGP packet type. */ + stream_set_getp(s, BGP_MARKER_SIZE + 2); + type = stream_getc(s); + + switch (type) { + case BGP_MSG_OPEN: + peer->open_out++; + break; + case BGP_MSG_UPDATE: + peer->update_out++; + break; + case BGP_MSG_NOTIFY: + peer->notify_out++; + /* Double start timer. */ + peer->v_start *= 2; + + /* Overflow check. */ + if (peer->v_start >= (60 * 2)) + peer->v_start = (60 * 2); + + /* Flush any existing events */ + BGP_EVENT_ADD(peer, BGP_Stop); + goto done; + + case BGP_MSG_KEEPALIVE: + peer->keepalive_out++; + break; + case BGP_MSG_ROUTE_REFRESH_NEW: + case BGP_MSG_ROUTE_REFRESH_OLD: + peer->refresh_out++; + break; + case BGP_MSG_CAPABILITY: + peer->dynamic_cap_out++; + break; + } - sockopt_cork (peer->fd, 0); - return 0; -} + /* OK we send packet so delete it. */ + bgp_packet_delete(peer); + update_last_write = 1; + } while (++count < peer->bgp->wpkt_quanta + && (s = bgp_write_packet(peer)) != NULL); -/* This is only for sending NOTIFICATION message to neighbor. */ -static int -bgp_write_notify (struct peer *peer) -{ - int ret, val; - u_char type; - struct stream *s; + bgp_write_proceed_actions(peer); - /* There should be at least one packet. */ - s = stream_fifo_head (peer->obuf); - if (!s) - return 0; - assert (stream_get_endp (s) >= BGP_HEADER_SIZE); +done: + /* Update last_update if UPDATEs were written. */ + if (peer->update_out > oc) + peer->last_update = bgp_clock(); - /* Stop collecting data within the socket */ - sockopt_cork (peer->fd, 0); + /* If we TXed any flavor of packet update last_write */ + if (update_last_write) + peer->last_write = bgp_clock(); - /* socket is in nonblocking mode, if we can't deliver the NOTIFY, well, - * we only care about getting a clean shutdown at this point. */ - ret = write (peer->fd, STREAM_DATA (s), stream_get_endp (s)); + sockopt_cork(peer->fd, 0); + return 0; +} - /* only connection reset/close gets counted as TCP_fatal_error, failure - * to write the entire NOTIFY doesn't get different FSM treatment */ - if (ret <= 0) - { - BGP_EVENT_ADD (peer, TCP_fatal_error); - return 0; - } +/* This is only for sending NOTIFICATION message to neighbor. */ +static int bgp_write_notify(struct peer *peer) +{ + int ret, val; + u_char type; + struct stream *s; + + /* There should be at least one packet. */ + s = stream_fifo_head(peer->obuf); + if (!s) + return 0; + assert(stream_get_endp(s) >= BGP_HEADER_SIZE); + + /* Stop collecting data within the socket */ + sockopt_cork(peer->fd, 0); + + /* socket is in nonblocking mode, if we can't deliver the NOTIFY, well, + * we only care about getting a clean shutdown at this point. */ + ret = write(peer->fd, STREAM_DATA(s), stream_get_endp(s)); + + /* only connection reset/close gets counted as TCP_fatal_error, failure + * to write the entire NOTIFY doesn't get different FSM treatment */ + if (ret <= 0) { + BGP_EVENT_ADD(peer, TCP_fatal_error); + return 0; + } - /* Disable Nagle, make NOTIFY packet go out right away */ - val = 1; - (void) setsockopt (peer->fd, IPPROTO_TCP, TCP_NODELAY, - (char *) &val, sizeof (val)); + /* Disable Nagle, make NOTIFY packet go out right away */ + val = 1; + (void)setsockopt(peer->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, + sizeof(val)); - /* Retrieve BGP packet type. */ - stream_set_getp (s, BGP_MARKER_SIZE + 2); - type = stream_getc (s); + /* Retrieve BGP packet type. */ + stream_set_getp(s, BGP_MARKER_SIZE + 2); + type = stream_getc(s); - assert (type == BGP_MSG_NOTIFY); + assert(type == BGP_MSG_NOTIFY); - /* Type should be notify. */ - peer->notify_out++; + /* Type should be notify. */ + peer->notify_out++; - /* Double start timer. */ - peer->v_start *= 2; + /* Double start timer. */ + peer->v_start *= 2; - /* Overflow check. */ - if (peer->v_start >= (60 * 2)) - peer->v_start = (60 * 2); + /* Overflow check. */ + if (peer->v_start >= (60 * 2)) + peer->v_start = (60 * 2); - /* Handle Graceful Restart case where the state changes to - Connect instead of Idle */ - BGP_EVENT_ADD (peer, BGP_Stop); + /* Handle Graceful Restart case where the state changes to + Connect instead of Idle */ + BGP_EVENT_ADD(peer, BGP_Stop); - return 0; + return 0; } /* Make keepalive packet and send it to the peer. */ -void -bgp_keepalive_send (struct peer *peer) +void bgp_keepalive_send(struct peer *peer) { - struct stream *s; + struct stream *s; + + s = stream_new(BGP_MAX_PACKET_SIZE); - s = stream_new (BGP_MAX_PACKET_SIZE); + /* Make keepalive packet. */ + bgp_packet_set_marker(s, BGP_MSG_KEEPALIVE); - /* Make keepalive packet. */ - bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE); + /* Set packet size. */ + (void)bgp_packet_set_size(s); - /* Set packet size. */ - (void)bgp_packet_set_size (s); + /* Dump packet if debug option is set. */ + /* bgp_packet_dump (s); */ - /* Dump packet if debug option is set. */ - /* bgp_packet_dump (s); */ - - if (bgp_debug_keepalive(peer)) - zlog_debug ("%s sending KEEPALIVE", peer->host); + if (bgp_debug_keepalive(peer)) + zlog_debug("%s sending KEEPALIVE", peer->host); - /* Add packet to the peer. */ - bgp_packet_add (peer, s); + /* Add packet to the peer. */ + bgp_packet_add(peer, s); - BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); + BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd); } /* Make open packet and send it to the peer. */ -void -bgp_open_send (struct peer *peer) +void bgp_open_send(struct peer *peer) { - struct stream *s; - u_int16_t send_holdtime; - as_t local_as; + struct stream *s; + u_int16_t send_holdtime; + as_t local_as; - if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)) - send_holdtime = peer->holdtime; - else - send_holdtime = peer->bgp->default_holdtime; + if (CHECK_FLAG(peer->config, PEER_CONFIG_TIMER)) + send_holdtime = peer->holdtime; + else + send_holdtime = peer->bgp->default_holdtime; - /* local-as Change */ - if (peer->change_local_as) - local_as = peer->change_local_as; - else - local_as = peer->local_as; + /* local-as Change */ + if (peer->change_local_as) + local_as = peer->change_local_as; + else + local_as = peer->local_as; - s = stream_new (BGP_MAX_PACKET_SIZE); + s = stream_new(BGP_MAX_PACKET_SIZE); - /* Make open packet. */ - bgp_packet_set_marker (s, BGP_MSG_OPEN); + /* Make open packet. */ + bgp_packet_set_marker(s, BGP_MSG_OPEN); - /* Set open packet values. */ - stream_putc (s, BGP_VERSION_4); /* BGP version */ - stream_putw (s, (local_as <= BGP_AS_MAX) ? (u_int16_t) local_as - : BGP_AS_TRANS); - stream_putw (s, send_holdtime); /* Hold Time */ - stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */ + /* Set open packet values. */ + stream_putc(s, BGP_VERSION_4); /* BGP version */ + stream_putw(s, + (local_as <= BGP_AS_MAX) ? (u_int16_t)local_as + : BGP_AS_TRANS); + stream_putw(s, send_holdtime); /* Hold Time */ + stream_put_in_addr(s, &peer->local_id); /* BGP Identifier */ - /* Set capability code. */ - bgp_open_capability (s, peer); + /* Set capability code. */ + bgp_open_capability(s, peer); - /* Set BGP packet length. */ - (void)bgp_packet_set_size (s); + /* Set BGP packet length. */ + (void)bgp_packet_set_size(s); - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s sending OPEN, version %d, my as %u, holdtime %d, id %s", - peer->host, BGP_VERSION_4, local_as, - send_holdtime, inet_ntoa (peer->local_id)); + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s sending OPEN, version %d, my as %u, holdtime %d, id %s", + peer->host, BGP_VERSION_4, local_as, send_holdtime, + inet_ntoa(peer->local_id)); - /* Dump packet if debug option is set. */ - /* bgp_packet_dump (s); */ + /* Dump packet if debug option is set. */ + /* bgp_packet_dump (s); */ - /* Add packet to the peer. */ - bgp_packet_add (peer, s); + /* Add packet to the peer. */ + bgp_packet_add(peer, s); - BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); + BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd); } /* Send BGP notify packet with data potion. */ -void -bgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code, - u_char *data, size_t datalen) +void bgp_notify_send_with_data(struct peer *peer, u_char code, u_char sub_code, + u_char *data, size_t datalen) { - struct stream *s; - int length; - - /* Allocate new stream. */ - s = stream_new (BGP_MAX_PACKET_SIZE); - - /* Make nitify packet. */ - bgp_packet_set_marker (s, BGP_MSG_NOTIFY); - - /* Set notify packet values. */ - stream_putc (s, code); /* BGP notify code */ - stream_putc (s, sub_code); /* BGP notify sub_code */ - - /* If notify data is present. */ - if (data) - stream_write (s, data, datalen); - - /* Set BGP packet length. */ - length = bgp_packet_set_size (s); - - /* Add packet to the peer. */ - stream_fifo_clean (peer->obuf); - bgp_packet_add (peer, s); - - /* For debug */ - { - struct bgp_notify bgp_notify; - int first = 0; - int i; - char c[4]; - - bgp_notify.code = code; - bgp_notify.subcode = sub_code; - bgp_notify.data = NULL; - bgp_notify.length = length - BGP_MSG_NOTIFY_MIN_SIZE; - bgp_notify.raw_data = data; - - peer->notify.code = bgp_notify.code; - peer->notify.subcode = bgp_notify.subcode; - - if (bgp_notify.length) - { - bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3); - for (i = 0; i < bgp_notify.length; i++) - if (first) - { - sprintf (c, " %02x", data[i]); - strcat (bgp_notify.data, c); - } - else - { - first = 1; - sprintf (c, "%02x", data[i]); - strcpy (bgp_notify.data, c); - } - } - bgp_notify_print (peer, &bgp_notify, "sending"); - - if (bgp_notify.data) - { - XFREE (MTYPE_TMP, bgp_notify.data); - bgp_notify.data = NULL; - bgp_notify.length = 0; - } - } - - /* peer reset cause */ - if (code == BGP_NOTIFY_CEASE) - { - if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET) - peer->last_reset = PEER_DOWN_USER_RESET; - else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN) - peer->last_reset = PEER_DOWN_USER_SHUTDOWN; - else - peer->last_reset = PEER_DOWN_NOTIFY_SEND; - } - else - peer->last_reset = PEER_DOWN_NOTIFY_SEND; - - /* Call immediately. */ - BGP_WRITE_OFF (peer->t_write); - - bgp_write_notify (peer); + struct stream *s; + int length; + + /* Allocate new stream. */ + s = stream_new(BGP_MAX_PACKET_SIZE); + + /* Make nitify packet. */ + bgp_packet_set_marker(s, BGP_MSG_NOTIFY); + + /* Set notify packet values. */ + stream_putc(s, code); /* BGP notify code */ + stream_putc(s, sub_code); /* BGP notify sub_code */ + + /* If notify data is present. */ + if (data) + stream_write(s, data, datalen); + + /* Set BGP packet length. */ + length = bgp_packet_set_size(s); + + /* Add packet to the peer. */ + stream_fifo_clean(peer->obuf); + bgp_packet_add(peer, s); + + /* For debug */ + { + struct bgp_notify bgp_notify; + int first = 0; + int i; + char c[4]; + + bgp_notify.code = code; + bgp_notify.subcode = sub_code; + bgp_notify.data = NULL; + bgp_notify.length = length - BGP_MSG_NOTIFY_MIN_SIZE; + bgp_notify.raw_data = data; + + peer->notify.code = bgp_notify.code; + peer->notify.subcode = bgp_notify.subcode; + + if (bgp_notify.length) { + bgp_notify.data = + XMALLOC(MTYPE_TMP, bgp_notify.length * 3); + for (i = 0; i < bgp_notify.length; i++) + if (first) { + sprintf(c, " %02x", data[i]); + strcat(bgp_notify.data, c); + } else { + first = 1; + sprintf(c, "%02x", data[i]); + strcpy(bgp_notify.data, c); + } + } + bgp_notify_print(peer, &bgp_notify, "sending"); + + if (bgp_notify.data) { + XFREE(MTYPE_TMP, bgp_notify.data); + bgp_notify.data = NULL; + bgp_notify.length = 0; + } + } + + /* peer reset cause */ + if (code == BGP_NOTIFY_CEASE) { + if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET) + peer->last_reset = PEER_DOWN_USER_RESET; + else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN) + peer->last_reset = PEER_DOWN_USER_SHUTDOWN; + else + peer->last_reset = PEER_DOWN_NOTIFY_SEND; + } else + peer->last_reset = PEER_DOWN_NOTIFY_SEND; + + /* Call immediately. */ + BGP_WRITE_OFF(peer->t_write); + + bgp_write_notify(peer); } /* Send BGP notify packet. */ -void -bgp_notify_send (struct peer *peer, u_char code, u_char sub_code) +void bgp_notify_send(struct peer *peer, u_char code, u_char sub_code) { - bgp_notify_send_with_data (peer, code, sub_code, NULL, 0); + bgp_notify_send_with_data(peer, code, sub_code, NULL, 0); } /* Send route refresh message to the peer. */ -void -bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi, - u_char orf_type, u_char when_to_refresh, int remove) +void bgp_route_refresh_send(struct peer *peer, afi_t afi, safi_t safi, + u_char orf_type, u_char when_to_refresh, int remove) { - struct stream *s; - struct bgp_filter *filter; - int orf_refresh = 0; - iana_afi_t pkt_afi; - safi_t pkt_safi; - - if (DISABLE_BGP_ANNOUNCE) - return; - - filter = &peer->filter[afi][safi]; - - /* Convert AFI, SAFI to values for packet. */ - bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); - - s = stream_new (BGP_MAX_PACKET_SIZE); - - /* Make BGP update packet. */ - if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV)) - bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_NEW); - else - bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_OLD); - - /* Encode Route Refresh message. */ - stream_putw (s, pkt_afi); - stream_putc (s, 0); - stream_putc (s, pkt_safi); - - if (orf_type == ORF_TYPE_PREFIX - || orf_type == ORF_TYPE_PREFIX_OLD) - if (remove || filter->plist[FILTER_IN].plist) - { - u_int16_t orf_len; - unsigned long orfp; - - orf_refresh = 1; - stream_putc (s, when_to_refresh); - stream_putc (s, orf_type); - orfp = stream_get_endp (s); - stream_putw (s, 0); - - if (remove) - { - UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND); - stream_putc (s, ORF_COMMON_PART_REMOVE_ALL); - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d", - peer->host, orf_type, - (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"), - pkt_afi, pkt_safi); - } + struct stream *s; + struct bgp_filter *filter; + int orf_refresh = 0; + iana_afi_t pkt_afi; + safi_t pkt_safi; + + if (DISABLE_BGP_ANNOUNCE) + return; + + filter = &peer->filter[afi][safi]; + + /* Convert AFI, SAFI to values for packet. */ + bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi); + + s = stream_new(BGP_MAX_PACKET_SIZE); + + /* Make BGP update packet. */ + if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV)) + bgp_packet_set_marker(s, BGP_MSG_ROUTE_REFRESH_NEW); else - { - SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND); - prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist, - ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT, - ORF_COMMON_PART_DENY); - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d", - peer->host, orf_type, - (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"), - pkt_afi, pkt_safi); - } - - /* Total ORF Entry Len. */ - orf_len = stream_get_endp (s) - orfp - 2; - stream_putw_at (s, orfp, orf_len); - } - - /* Set packet size. */ - (void)bgp_packet_set_size (s); - - if (bgp_debug_neighbor_events(peer)) - { - if (! orf_refresh) - zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d", - peer->host, pkt_afi, pkt_safi); - } - - /* Add packet to the peer. */ - bgp_packet_add (peer, s); - - BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); + bgp_packet_set_marker(s, BGP_MSG_ROUTE_REFRESH_OLD); + + /* Encode Route Refresh message. */ + stream_putw(s, pkt_afi); + stream_putc(s, 0); + stream_putc(s, pkt_safi); + + if (orf_type == ORF_TYPE_PREFIX || orf_type == ORF_TYPE_PREFIX_OLD) + if (remove || filter->plist[FILTER_IN].plist) { + u_int16_t orf_len; + unsigned long orfp; + + orf_refresh = 1; + stream_putc(s, when_to_refresh); + stream_putc(s, orf_type); + orfp = stream_get_endp(s); + stream_putw(s, 0); + + if (remove) { + UNSET_FLAG(peer->af_sflags[afi][safi], + PEER_STATUS_ORF_PREFIX_SEND); + stream_putc(s, ORF_COMMON_PART_REMOVE_ALL); + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d", + peer->host, orf_type, + (when_to_refresh == REFRESH_DEFER + ? "defer" + : "immediate"), + pkt_afi, pkt_safi); + } else { + SET_FLAG(peer->af_sflags[afi][safi], + PEER_STATUS_ORF_PREFIX_SEND); + prefix_bgp_orf_entry( + s, filter->plist[FILTER_IN].plist, + ORF_COMMON_PART_ADD, + ORF_COMMON_PART_PERMIT, + ORF_COMMON_PART_DENY); + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d", + peer->host, orf_type, + (when_to_refresh == REFRESH_DEFER + ? "defer" + : "immediate"), + pkt_afi, pkt_safi); + } + + /* Total ORF Entry Len. */ + orf_len = stream_get_endp(s) - orfp - 2; + stream_putw_at(s, orfp, orf_len); + } + + /* Set packet size. */ + (void)bgp_packet_set_size(s); + + if (bgp_debug_neighbor_events(peer)) { + if (!orf_refresh) + zlog_debug("%s sending REFRESH_REQ for afi/safi: %d/%d", + peer->host, pkt_afi, pkt_safi); + } + + /* Add packet to the peer. */ + bgp_packet_add(peer, s); + + BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd); } /* Send capability message to the peer. */ -void -bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi, - int capability_code, int action) +void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi, + int capability_code, int action) { - struct stream *s; - iana_afi_t pkt_afi; - safi_t pkt_safi; + struct stream *s; + iana_afi_t pkt_afi; + safi_t pkt_safi; + + /* Convert AFI, SAFI to values for packet. */ + bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi); + + s = stream_new(BGP_MAX_PACKET_SIZE); + + /* Make BGP update packet. */ + bgp_packet_set_marker(s, BGP_MSG_CAPABILITY); + + /* Encode MP_EXT capability. */ + if (capability_code == CAPABILITY_CODE_MP) { + stream_putc(s, action); + stream_putc(s, CAPABILITY_CODE_MP); + stream_putc(s, CAPABILITY_CODE_MP_LEN); + stream_putw(s, pkt_afi); + stream_putc(s, 0); + stream_putc(s, pkt_safi); + + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d", + peer->host, + action == CAPABILITY_ACTION_SET ? "Advertising" + : "Removing", + pkt_afi, pkt_safi); + } + + /* Set packet size. */ + (void)bgp_packet_set_size(s); - /* Convert AFI, SAFI to values for packet. */ - bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); + /* Add packet to the peer. */ + bgp_packet_add(peer, s); - s = stream_new (BGP_MAX_PACKET_SIZE); + BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd); +} - /* Make BGP update packet. */ - bgp_packet_set_marker (s, BGP_MSG_CAPABILITY); +/* RFC1771 6.8 Connection collision detection. */ +static int bgp_collision_detect(struct peer *new, struct in_addr remote_id) +{ + struct peer *peer; + + /* Upon receipt of an OPEN message, the local system must examine + all of its connections that are in the OpenConfirm state. A BGP + speaker may also examine connections in an OpenSent state if it + knows the BGP Identifier of the peer by means outside of the + protocol. If among these connections there is a connection to a + remote BGP speaker whose BGP Identifier equals the one in the + OPEN message, then the local system performs the following + collision resolution procedure: */ + + if ((peer = new->doppelganger) != NULL) { + /* Do not accept the new connection in Established or Clearing + * states. + * Note that a peer GR is handled by closing the existing + * connection + * upon receipt of new one. + */ + if (peer->status == Established || peer->status == Clearing) { + bgp_notify_send(new, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); + return (-1); + } else if ((peer->status == OpenConfirm) + || (peer->status == OpenSent)) { + /* 1. The BGP Identifier of the local system is compared + to + the BGP Identifier of the remote system (as specified + in + the OPEN message). */ + + if (ntohl(peer->local_id.s_addr) + < ntohl(remote_id.s_addr)) + if (!CHECK_FLAG(peer->sflags, + PEER_STATUS_ACCEPT_PEER)) { + /* 2. If the value of the local BGP + Identifier is less + than the remote one, the local system + closes BGP + connection that already exists (the + one that is + already in the OpenConfirm state), + and accepts BGP + connection initiated by the remote + system. */ + bgp_notify_send( + peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); + return 1; + } else { + bgp_notify_send( + new, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); + return -1; + } + else { + /* 3. Otherwise, the local system closes newly + created + BGP connection (the one associated with the + newly + received OPEN message), and continues to use + the + existing one (the one that is already in the + OpenConfirm state). */ + if (CHECK_FLAG(peer->sflags, + PEER_STATUS_ACCEPT_PEER)) { + bgp_notify_send( + peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); + return 1; + } else { + bgp_notify_send( + new, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); + return -1; + } + } + } + } + return 0; +} - /* Encode MP_EXT capability. */ - if (capability_code == CAPABILITY_CODE_MP) - { - stream_putc (s, action); - stream_putc (s, CAPABILITY_CODE_MP); - stream_putc (s, CAPABILITY_CODE_MP_LEN); - stream_putw (s, pkt_afi); - stream_putc (s, 0); - stream_putc (s, pkt_safi); +static int bgp_open_receive(struct peer *peer, bgp_size_t size) +{ + int ret; + u_char version; + u_char optlen; + u_int16_t holdtime; + u_int16_t send_holdtime; + as_t remote_as; + as_t as4 = 0; + struct in_addr remote_id; + int mp_capability; + u_int8_t notify_data_remote_as[2]; + u_int8_t notify_data_remote_as4[4]; + u_int8_t notify_data_remote_id[4]; + u_int16_t *holdtime_ptr; + + /* Parse open packet. */ + version = stream_getc(peer->ibuf); + memcpy(notify_data_remote_as, stream_pnt(peer->ibuf), 2); + remote_as = stream_getw(peer->ibuf); + holdtime_ptr = (u_int16_t *)stream_pnt(peer->ibuf); + holdtime = stream_getw(peer->ibuf); + memcpy(notify_data_remote_id, stream_pnt(peer->ibuf), 4); + remote_id.s_addr = stream_get_ipv4(peer->ibuf); + + /* Receive OPEN message log */ + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s rcv OPEN, version %d, remote-as (in open) %u," + " holdtime %d, id %s", + peer->host, version, remote_as, holdtime, + inet_ntoa(remote_id)); + + /* BEGIN to read the capability here, but dont do it yet */ + mp_capability = 0; + optlen = stream_getc(peer->ibuf); + + if (optlen != 0) { + /* If not enough bytes, it is an error. */ + if (STREAM_READABLE(peer->ibuf) < optlen) { + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_MALFORMED_ATTR); + return -1; + } - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d", - peer->host, action == CAPABILITY_ACTION_SET ? - "Advertising" : "Removing", pkt_afi, pkt_safi); - } + /* We need the as4 capability value *right now* because + * if it is there, we have not got the remote_as yet, and + * without + * that we do not know which peer is connecting to us now. + */ + as4 = peek_for_as4_capability(peer, optlen); + memcpy(notify_data_remote_as4, &as4, 4); + } - /* Set packet size. */ - (void)bgp_packet_set_size (s); + /* Just in case we have a silly peer who sends AS4 capability set to 0 + */ + if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV) && !as4) { + zlog_err("%s bad OPEN, got AS4 capability, but AS4 set to 0", + peer->host); + bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_BAD_PEER_AS, + notify_data_remote_as4, 4); + return -1; + } - /* Add packet to the peer. */ - bgp_packet_add (peer, s); + if (remote_as == BGP_AS_TRANS) { + /* Take the AS4 from the capability. We must have received the + * capability now! Otherwise we have a asn16 peer who uses + * BGP_AS_TRANS, for some unknown reason. + */ + if (as4 == BGP_AS_TRANS) { + zlog_err( + "%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed", + peer->host); + bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_BAD_PEER_AS, + notify_data_remote_as4, 4); + return -1; + } - BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); -} + if (!as4 && BGP_DEBUG(as4, AS4)) + zlog_debug( + "%s [AS4] OPEN remote_as is AS_TRANS, but no AS4." + " Odd, but proceeding.", + peer->host); + else if (as4 < BGP_AS_MAX && BGP_DEBUG(as4, AS4)) + zlog_debug( + "%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits " + "in 2-bytes, very odd peer.", + peer->host, as4); + if (as4) + remote_as = as4; + } else { + /* We may have a partner with AS4 who has an asno < BGP_AS_MAX + */ + /* If we have got the capability, peer->as4cap must match + * remote_as */ + if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV) + && as4 != remote_as) { + /* raise error, log this, close session */ + zlog_err( + "%s bad OPEN, got AS4 capability, but remote_as %u" + " mismatch with 16bit 'myasn' %u in open", + peer->host, as4, remote_as); + bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_BAD_PEER_AS, + notify_data_remote_as4, 4); + return -1; + } + } -/* RFC1771 6.8 Connection collision detection. */ -static int -bgp_collision_detect (struct peer *new, struct in_addr remote_id) -{ - struct peer *peer; - - /* Upon receipt of an OPEN message, the local system must examine - all of its connections that are in the OpenConfirm state. A BGP - speaker may also examine connections in an OpenSent state if it - knows the BGP Identifier of the peer by means outside of the - protocol. If among these connections there is a connection to a - remote BGP speaker whose BGP Identifier equals the one in the - OPEN message, then the local system performs the following - collision resolution procedure: */ - - if ((peer = new->doppelganger) != NULL) - { - /* Do not accept the new connection in Established or Clearing states. - * Note that a peer GR is handled by closing the existing connection - * upon receipt of new one. - */ - if (peer->status == Established || peer->status == Clearing) - { - bgp_notify_send (new, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); - return (-1); - } - else if ((peer->status == OpenConfirm) || (peer->status == OpenSent)) - { - /* 1. The BGP Identifier of the local system is compared to - the BGP Identifier of the remote system (as specified in - the OPEN message). */ - - if (ntohl (peer->local_id.s_addr) < ntohl (remote_id.s_addr)) - if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) - { - /* 2. If the value of the local BGP Identifier is less - than the remote one, the local system closes BGP - connection that already exists (the one that is - already in the OpenConfirm state), and accepts BGP - connection initiated by the remote system. */ - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); - return 1; - } - else - { - bgp_notify_send (new, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); + /* remote router-id check. */ + if (remote_id.s_addr == 0 || IPV4_CLASS_DE(ntohl(remote_id.s_addr)) + || ntohl(peer->local_id.s_addr) == ntohl(remote_id.s_addr)) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s bad OPEN, wrong router identifier %s", + peer->host, inet_ntoa(remote_id)); + bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_BAD_BGP_IDENT, + notify_data_remote_id, 4); + return -1; + } + + /* Set remote router-id */ + peer->remote_id = remote_id; + + /* Peer BGP version check. */ + if (version != BGP_VERSION_4) { + u_int16_t maxver = htons(BGP_VERSION_4); + /* XXX this reply may not be correct if version < 4 XXX */ + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s bad protocol version, remote requested %d, local request %d", + peer->host, version, BGP_VERSION_4); + /* Data must be in network byte order here */ + bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_UNSUP_VERSION, + (u_int8_t *)&maxver, 2); + return -1; + } + + /* Check neighbor as number. */ + if (peer->as_type == AS_UNSPECIFIED) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s bad OPEN, remote AS is unspecified currently", + peer->host); + bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_BAD_PEER_AS, + notify_data_remote_as, 2); return -1; - } - else - { - /* 3. Otherwise, the local system closes newly created - BGP connection (the one associated with the newly - received OPEN message), and continues to use the - existing one (the one that is already in the - OpenConfirm state). */ - if (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) - { - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); - return 1; + } else if (peer->as_type == AS_INTERNAL) { + if (remote_as != peer->bgp->as) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s bad OPEN, remote AS is %u, internal specified", + peer->host, remote_as); + bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_BAD_PEER_AS, + notify_data_remote_as, 2); + return -1; } - else - { - bgp_notify_send (new, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_COLLISION_RESOLUTION); - return -1; + peer->as = peer->local_as; + } else if (peer->as_type == AS_EXTERNAL) { + if (remote_as == peer->bgp->as) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s bad OPEN, remote AS is %u, external specified", + peer->host, remote_as); + bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_BAD_PEER_AS, + notify_data_remote_as, 2); + return -1; } - } + peer->as = remote_as; + } else if ((peer->as_type == AS_SPECIFIED) && (remote_as != peer->as)) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s bad OPEN, remote AS is %u, expected %u", + peer->host, remote_as, peer->as); + bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_BAD_PEER_AS, + notify_data_remote_as, 2); + return -1; } - } - return 0; -} -static int -bgp_open_receive (struct peer *peer, bgp_size_t size) -{ - int ret; - u_char version; - u_char optlen; - u_int16_t holdtime; - u_int16_t send_holdtime; - as_t remote_as; - as_t as4 = 0; - struct in_addr remote_id; - int mp_capability; - u_int8_t notify_data_remote_as[2]; - u_int8_t notify_data_remote_as4[4]; - u_int8_t notify_data_remote_id[4]; - u_int16_t *holdtime_ptr; - - /* Parse open packet. */ - version = stream_getc (peer->ibuf); - memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2); - remote_as = stream_getw (peer->ibuf); - holdtime_ptr = (u_int16_t *)stream_pnt (peer->ibuf); - holdtime = stream_getw (peer->ibuf); - memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4); - remote_id.s_addr = stream_get_ipv4 (peer->ibuf); - - /* Receive OPEN message log */ - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %u," - " holdtime %d, id %s", - peer->host, version, remote_as, holdtime, - inet_ntoa (remote_id)); - - /* BEGIN to read the capability here, but dont do it yet */ - mp_capability = 0; - optlen = stream_getc (peer->ibuf); - - if (optlen != 0) - { - /* If not enough bytes, it is an error. */ - if (STREAM_READABLE(peer->ibuf) < optlen) - { - bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_MALFORMED_ATTR); - return -1; - } - - /* We need the as4 capability value *right now* because - * if it is there, we have not got the remote_as yet, and without - * that we do not know which peer is connecting to us now. - */ - as4 = peek_for_as4_capability (peer, optlen); - memcpy (notify_data_remote_as4, &as4, 4); - } - - /* Just in case we have a silly peer who sends AS4 capability set to 0 */ - if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) && !as4) - { - zlog_err ("%s bad OPEN, got AS4 capability, but AS4 set to 0", - peer->host); - bgp_notify_send_with_data (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_BAD_PEER_AS, - notify_data_remote_as4, 4); - return -1; - } - - if (remote_as == BGP_AS_TRANS) - { - /* Take the AS4 from the capability. We must have received the - * capability now! Otherwise we have a asn16 peer who uses - * BGP_AS_TRANS, for some unknown reason. + /* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST + calculate the value of the Hold Timer by using the smaller of its + configured Hold Time and the Hold Time received in the OPEN message. + The Hold Time MUST be either zero or at least three seconds. An + implementation may reject connections on the basis of the Hold Time. */ - if (as4 == BGP_AS_TRANS) - { - zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed", - peer->host); - bgp_notify_send_with_data (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_BAD_PEER_AS, - notify_data_remote_as4, 4); - return -1; - } - - if (!as4 && BGP_DEBUG (as4, AS4)) - zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but no AS4." - " Odd, but proceeding.", peer->host); - else if (as4 < BGP_AS_MAX && BGP_DEBUG (as4, AS4)) - zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits " - "in 2-bytes, very odd peer.", peer->host, as4); - if (as4) - remote_as = as4; - } - else - { - /* We may have a partner with AS4 who has an asno < BGP_AS_MAX */ - /* If we have got the capability, peer->as4cap must match remote_as */ - if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) - && as4 != remote_as) - { - /* raise error, log this, close session */ - zlog_err ("%s bad OPEN, got AS4 capability, but remote_as %u" - " mismatch with 16bit 'myasn' %u in open", - peer->host, as4, remote_as); - bgp_notify_send_with_data (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_BAD_PEER_AS, - notify_data_remote_as4, 4); - return -1; + + if (holdtime < 3 && holdtime != 0) { + bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_UNACEP_HOLDTIME, + (u_char *)holdtime_ptr, 2); + return -1; } - } - - /* remote router-id check. */ - if (remote_id.s_addr == 0 - || IPV4_CLASS_DE (ntohl (remote_id.s_addr)) - || ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr)) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s bad OPEN, wrong router identifier %s", - peer->host, inet_ntoa (remote_id)); - bgp_notify_send_with_data (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_BAD_BGP_IDENT, - notify_data_remote_id, 4); - return -1; - } - - /* Set remote router-id */ - peer->remote_id = remote_id; - - /* Peer BGP version check. */ - if (version != BGP_VERSION_4) - { - u_int16_t maxver = htons(BGP_VERSION_4); - /* XXX this reply may not be correct if version < 4 XXX */ - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s bad protocol version, remote requested %d, local request %d", - peer->host, version, BGP_VERSION_4); - /* Data must be in network byte order here */ - bgp_notify_send_with_data (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_UNSUP_VERSION, - (u_int8_t *) &maxver, 2); - return -1; - } - - /* Check neighbor as number. */ - if (peer->as_type == AS_UNSPECIFIED) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug("%s bad OPEN, remote AS is unspecified currently", peer->host); - bgp_notify_send_with_data(peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_BAD_PEER_AS, - notify_data_remote_as, 2); - return -1; - } - else if (peer->as_type == AS_INTERNAL) - { - if (remote_as != peer->bgp->as) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s bad OPEN, remote AS is %u, internal specified", - peer->host, remote_as); - bgp_notify_send_with_data (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_BAD_PEER_AS, - notify_data_remote_as, 2); - return -1; + + /* From the rfc: A reasonable maximum time between KEEPALIVE messages + would be one third of the Hold Time interval. KEEPALIVE messages + MUST NOT be sent more frequently than one per second. An + implementation MAY adjust the rate at which it sends KEEPALIVE + messages as a function of the Hold Time interval. */ + + if (CHECK_FLAG(peer->config, PEER_CONFIG_TIMER)) + send_holdtime = peer->holdtime; + else + send_holdtime = peer->bgp->default_holdtime; + + if (holdtime < send_holdtime) + peer->v_holdtime = holdtime; + else + peer->v_holdtime = send_holdtime; + + if (CHECK_FLAG(peer->config, PEER_CONFIG_TIMER)) + peer->v_keepalive = peer->keepalive; + else + peer->v_keepalive = peer->v_holdtime / 3; + + /* Open option part parse. */ + if (optlen != 0) { + if ((ret = bgp_open_option_parse(peer, optlen, &mp_capability)) + < 0) + return ret; + } else { + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s rcvd OPEN w/ OPTION parameter len: 0", + peer->host); } - peer->as = peer->local_as; - } - else if (peer->as_type == AS_EXTERNAL) - { - if (remote_as == peer->bgp->as) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s bad OPEN, remote AS is %u, external specified", - peer->host, remote_as); - bgp_notify_send_with_data (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_BAD_PEER_AS, - notify_data_remote_as, 2); - return -1; + + /* + * Assume that the peer supports the locally configured set of + * AFI/SAFIs if the peer did not send us any Mulitiprotocol + * capabilities, or if 'override-capability' is configured. + */ + if (!mp_capability + || CHECK_FLAG(peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) { + peer->afc_nego[AFI_IP][SAFI_UNICAST] = + peer->afc[AFI_IP][SAFI_UNICAST]; + peer->afc_nego[AFI_IP][SAFI_MULTICAST] = + peer->afc[AFI_IP][SAFI_MULTICAST]; + peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST] = + peer->afc[AFI_IP][SAFI_LABELED_UNICAST]; + peer->afc_nego[AFI_IP6][SAFI_UNICAST] = + peer->afc[AFI_IP6][SAFI_UNICAST]; + peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = + peer->afc[AFI_IP6][SAFI_MULTICAST]; + peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST] = + peer->afc[AFI_IP6][SAFI_LABELED_UNICAST]; + peer->afc_nego[AFI_L2VPN][SAFI_EVPN] = + peer->afc[AFI_L2VPN][SAFI_EVPN]; } - peer->as = remote_as; - } - else if ((peer->as_type == AS_SPECIFIED) && (remote_as != peer->as)) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s bad OPEN, remote AS is %u, expected %u", - peer->host, remote_as, peer->as); - bgp_notify_send_with_data (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_BAD_PEER_AS, - notify_data_remote_as, 2); - return -1; - } - - /* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST - calculate the value of the Hold Timer by using the smaller of its - configured Hold Time and the Hold Time received in the OPEN message. - The Hold Time MUST be either zero or at least three seconds. An - implementation may reject connections on the basis of the Hold Time. */ - - if (holdtime < 3 && holdtime != 0) - { - bgp_notify_send_with_data (peer, - BGP_NOTIFY_OPEN_ERR, - BGP_NOTIFY_OPEN_UNACEP_HOLDTIME, - (u_char *)holdtime_ptr, 2); - return -1; - } - - /* From the rfc: A reasonable maximum time between KEEPALIVE messages - would be one third of the Hold Time interval. KEEPALIVE messages - MUST NOT be sent more frequently than one per second. An - implementation MAY adjust the rate at which it sends KEEPALIVE - messages as a function of the Hold Time interval. */ - - if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)) - send_holdtime = peer->holdtime; - else - send_holdtime = peer->bgp->default_holdtime; - - if (holdtime < send_holdtime) - peer->v_holdtime = holdtime; - else - peer->v_holdtime = send_holdtime; - - if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)) - peer->v_keepalive = peer->keepalive; - else - peer->v_keepalive = peer->v_holdtime / 3; - - /* Open option part parse. */ - if (optlen != 0) - { - if ((ret = bgp_open_option_parse (peer, optlen, &mp_capability)) < 0) - return ret; - } - else - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s rcvd OPEN w/ OPTION parameter len: 0", - peer->host); - } - - /* - * Assume that the peer supports the locally configured set of - * AFI/SAFIs if the peer did not send us any Mulitiprotocol - * capabilities, or if 'override-capability' is configured. - */ - if (! mp_capability || - CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) - { - peer->afc_nego[AFI_IP][SAFI_UNICAST] = peer->afc[AFI_IP][SAFI_UNICAST]; - peer->afc_nego[AFI_IP][SAFI_MULTICAST] = peer->afc[AFI_IP][SAFI_MULTICAST]; - peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST] = peer->afc[AFI_IP][SAFI_LABELED_UNICAST]; - peer->afc_nego[AFI_IP6][SAFI_UNICAST] = peer->afc[AFI_IP6][SAFI_UNICAST]; - peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST]; - peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST] = peer->afc[AFI_IP6][SAFI_LABELED_UNICAST]; - peer->afc_nego[AFI_L2VPN][SAFI_EVPN] = peer->afc[AFI_L2VPN][SAFI_EVPN]; - } - - /* When collision is detected and this peer is closed. Retrun - immidiately. */ - ret = bgp_collision_detect (peer, remote_id); - if (ret < 0) - return ret; - - /* Get sockname. */ - if ((ret = bgp_getsockname (peer)) < 0) - { - zlog_err("%s: bgp_getsockname() failed for peer: %s", __FUNCTION__, - peer->host); - return (ret); - } - - /* Verify valid local address present based on negotiated address-families. */ - if (peer->afc_nego[AFI_IP][SAFI_UNICAST] || - peer->afc_nego[AFI_IP][SAFI_MULTICAST] || - peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] || - peer->afc_nego[AFI_IP][SAFI_ENCAP]) - { - if (!peer->nexthop.v4.s_addr) - { -#if defined (HAVE_CUMULUS) - zlog_err ("%s: No local IPv4 addr resetting connection, fd %d", - peer->host, peer->fd); - bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_SUBCODE_UNSPECIFIC); - return -1; + + /* When collision is detected and this peer is closed. Retrun + immidiately. */ + ret = bgp_collision_detect(peer, remote_id); + if (ret < 0) + return ret; + + /* Get sockname. */ + if ((ret = bgp_getsockname(peer)) < 0) { + zlog_err("%s: bgp_getsockname() failed for peer: %s", + __FUNCTION__, peer->host); + return (ret); + } + + /* Verify valid local address present based on negotiated + * address-families. */ + if (peer->afc_nego[AFI_IP][SAFI_UNICAST] + || peer->afc_nego[AFI_IP][SAFI_MULTICAST] + || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] + || peer->afc_nego[AFI_IP][SAFI_ENCAP]) { + if (!peer->nexthop.v4.s_addr) { +#if defined(HAVE_CUMULUS) + zlog_err( + "%s: No local IPv4 addr resetting connection, fd %d", + peer->host, peer->fd); + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_SUBCODE_UNSPECIFIC); + return -1; #endif - } - } - if (peer->afc_nego[AFI_IP6][SAFI_UNICAST] || - peer->afc_nego[AFI_IP6][SAFI_MULTICAST] || - peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN] || - peer->afc_nego[AFI_IP6][SAFI_ENCAP]) - { - if (IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_global)) - { -#if defined (HAVE_CUMULUS) - zlog_err ("%s: No local IPv6 addr resetting connection, fd %d", - peer->host, peer->fd); - bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_SUBCODE_UNSPECIFIC); - return -1; + } + } + if (peer->afc_nego[AFI_IP6][SAFI_UNICAST] + || peer->afc_nego[AFI_IP6][SAFI_MULTICAST] + || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN] + || peer->afc_nego[AFI_IP6][SAFI_ENCAP]) { + if (IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_global)) { +#if defined(HAVE_CUMULUS) + zlog_err( + "%s: No local IPv6 addr resetting connection, fd %d", + peer->host, peer->fd); + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_SUBCODE_UNSPECIFIC); + return -1; #endif - } - } - peer->rtt = sockopt_tcp_rtt (peer->fd); - - if ((ret = bgp_event_update(peer, Receive_OPEN_message)) < 0) - { - zlog_err("%s: BGP event update failed for peer: %s", __FUNCTION__, - peer->host); - /* DD: bgp send notify and reset state */ - return (ret); - } - - peer->packet_size = 0; - if (peer->ibuf) - stream_reset (peer->ibuf); - - return 0; + } + } + peer->rtt = sockopt_tcp_rtt(peer->fd); + + if ((ret = bgp_event_update(peer, Receive_OPEN_message)) < 0) { + zlog_err("%s: BGP event update failed for peer: %s", + __FUNCTION__, peer->host); + /* DD: bgp send notify and reset state */ + return (ret); + } + + peer->packet_size = 0; + if (peer->ibuf) + stream_reset(peer->ibuf); + + return 0; } -/* Called when there is a change in the EOR(implicit or explicit) status of a peer. +/* Called when there is a change in the EOR(implicit or explicit) status of a + peer. Ends the update-delay if all expected peers are done with EORs. */ -void -bgp_check_update_delay(struct bgp *bgp) +void bgp_check_update_delay(struct bgp *bgp) { - struct listnode *node, *nnode; - struct peer *peer = NULL; - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("Checking update delay, T: %d R: %d I:%d E: %d", bgp->established, - bgp->restarted_peers, bgp->implicit_eors, bgp->explicit_eors); - - if (bgp->established <= - bgp->restarted_peers + bgp->implicit_eors + bgp->explicit_eors) - { - /* This is an extra sanity check to make sure we wait for all the - eligible configured peers. This check is performed if establish wait - timer is on, or establish wait option is not given with the - update-delay command */ - if (bgp->t_establish_wait || - (bgp->v_establish_wait == bgp->v_update_delay)) - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE) - && !CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN) - && !peer->update_delay_over) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug (" Peer %s pending, continuing read-only mode", - peer->host); - return; - } - } - - zlog_info ("Update delay ended, restarted: %d, EORs implicit: %d, explicit: %d", - bgp->restarted_peers, bgp->implicit_eors, bgp->explicit_eors); - bgp_update_delay_end(bgp); - } + struct listnode *node, *nnode; + struct peer *peer = NULL; + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("Checking update delay, T: %d R: %d I:%d E: %d", + bgp->established, bgp->restarted_peers, + bgp->implicit_eors, bgp->explicit_eors); + + if (bgp->established + <= bgp->restarted_peers + bgp->implicit_eors + bgp->explicit_eors) { + /* This is an extra sanity check to make sure we wait for all + the + eligible configured peers. This check is performed if + establish wait + timer is on, or establish wait option is not given with the + update-delay command */ + if (bgp->t_establish_wait + || (bgp->v_establish_wait == bgp->v_update_delay)) + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (CHECK_FLAG(peer->flags, + PEER_FLAG_CONFIG_NODE) + && !CHECK_FLAG(peer->flags, + PEER_FLAG_SHUTDOWN) + && !peer->update_delay_over) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + " Peer %s pending, continuing read-only mode", + peer->host); + return; + } + } + + zlog_info( + "Update delay ended, restarted: %d, EORs implicit: %d, explicit: %d", + bgp->restarted_peers, bgp->implicit_eors, + bgp->explicit_eors); + bgp_update_delay_end(bgp); + } } /* Called if peer is known to have restarted. The restart-state bit in Graceful-Restart capability is used for that */ -void -bgp_update_restarted_peers (struct peer *peer) +void bgp_update_restarted_peers(struct peer *peer) { - if (!bgp_update_delay_active(peer->bgp)) return; /* BGP update delay has ended */ - if (peer->update_delay_over) return; /* This peer has already been considered */ - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("Peer %s: Checking restarted", peer->host); - - if (peer->status == Established) - { - peer->update_delay_over = 1; - peer->bgp->restarted_peers++; - bgp_check_update_delay(peer->bgp); - } + if (!bgp_update_delay_active(peer->bgp)) + return; /* BGP update delay has ended */ + if (peer->update_delay_over) + return; /* This peer has already been considered */ + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("Peer %s: Checking restarted", peer->host); + + if (peer->status == Established) { + peer->update_delay_over = 1; + peer->bgp->restarted_peers++; + bgp_check_update_delay(peer->bgp); + } } /* Called as peer receives a keep-alive. Determines if this occurence can be taken as an implicit EOR for this peer. NOTE: The very first keep-alive after the Established state of a peer is - considered implicit EOR for the update-delay purposes */ -void -bgp_update_implicit_eors (struct peer *peer) + considered implicit EOR for the update-delay purposes */ +void bgp_update_implicit_eors(struct peer *peer) { - if (!bgp_update_delay_active(peer->bgp)) return; /* BGP update delay has ended */ - if (peer->update_delay_over) return; /* This peer has already been considered */ - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("Peer %s: Checking implicit EORs", peer->host); - - if (peer->status == Established) - { - peer->update_delay_over = 1; - peer->bgp->implicit_eors++; - bgp_check_update_delay(peer->bgp); - } + if (!bgp_update_delay_active(peer->bgp)) + return; /* BGP update delay has ended */ + if (peer->update_delay_over) + return; /* This peer has already been considered */ + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("Peer %s: Checking implicit EORs", peer->host); + + if (peer->status == Established) { + peer->update_delay_over = 1; + peer->bgp->implicit_eors++; + bgp_check_update_delay(peer->bgp); + } } /* Should be called only when there is a change in the EOR_RECEIVED status for any afi/safi on a peer */ -static void -bgp_update_explicit_eors (struct peer *peer) +static void bgp_update_explicit_eors(struct peer *peer) { - afi_t afi; - safi_t safi; - - if (!bgp_update_delay_active(peer->bgp)) return; /* BGP update delay has ended */ - if (peer->update_delay_over) return; /* This peer has already been considered */ - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("Peer %s: Checking explicit EORs", peer->host); - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - if (peer->afc_nego[afi][safi] && - !CHECK_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_EOR_RECEIVED)) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug (" afi %d safi %d didnt receive EOR", afi, safi); - return; - } - } - - peer->update_delay_over = 1; - peer->bgp->explicit_eors++; - bgp_check_update_delay(peer->bgp); + afi_t afi; + safi_t safi; + + if (!bgp_update_delay_active(peer->bgp)) + return; /* BGP update delay has ended */ + if (peer->update_delay_over) + return; /* This peer has already been considered */ + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("Peer %s: Checking explicit EORs", peer->host); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + if (peer->afc_nego[afi][safi] + && !CHECK_FLAG(peer->af_sflags[afi][safi], + PEER_STATUS_EOR_RECEIVED)) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + " afi %d safi %d didnt receive EOR", + afi, safi); + return; + } + } + + peer->update_delay_over = 1; + peer->bgp->explicit_eors++; + bgp_check_update_delay(peer->bgp); } -/* Frontend for NLRI parsing, to fan-out to AFI/SAFI specific parsers - * mp_withdraw, if set, is used to nullify attr structure on most of the calling safi function +/* Frontend for NLRI parsing, to fan-out to AFI/SAFI specific parsers + * mp_withdraw, if set, is used to nullify attr structure on most of the calling + * safi function * and for evpn, passed as parameter */ -int -bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet, int mp_withdraw) +int bgp_nlri_parse(struct peer *peer, struct attr *attr, + struct bgp_nlri *packet, int mp_withdraw) { - switch (packet->safi) - { - case SAFI_UNICAST: - case SAFI_MULTICAST: - return bgp_nlri_parse_ip (peer, mp_withdraw?NULL:attr, packet); - case SAFI_LABELED_UNICAST: - return bgp_nlri_parse_label (peer, mp_withdraw?NULL:attr, packet); - case SAFI_MPLS_VPN: - return bgp_nlri_parse_vpn (peer, mp_withdraw?NULL:attr, packet); - case SAFI_EVPN: - return bgp_nlri_parse_evpn (peer, attr, packet, mp_withdraw); - } - return -1; + switch (packet->safi) { + case SAFI_UNICAST: + case SAFI_MULTICAST: + return bgp_nlri_parse_ip(peer, mp_withdraw ? NULL : attr, + packet); + case SAFI_LABELED_UNICAST: + return bgp_nlri_parse_label(peer, mp_withdraw ? NULL : attr, + packet); + case SAFI_MPLS_VPN: + return bgp_nlri_parse_vpn(peer, mp_withdraw ? NULL : attr, + packet); + case SAFI_EVPN: + return bgp_nlri_parse_evpn(peer, attr, packet, mp_withdraw); + } + return -1; } /* Parse BGP Update packet and make attribute object. */ -static int -bgp_update_receive (struct peer *peer, bgp_size_t size) +static int bgp_update_receive(struct peer *peer, bgp_size_t size) { - int ret, nlri_ret; - u_char *end; - struct stream *s; - struct attr attr; - bgp_size_t attribute_len; - bgp_size_t update_len; - bgp_size_t withdraw_len; - - enum NLRI_TYPES { - NLRI_UPDATE, - NLRI_WITHDRAW, - NLRI_MP_UPDATE, - NLRI_MP_WITHDRAW, - NLRI_TYPE_MAX - }; - struct bgp_nlri nlris[NLRI_TYPE_MAX]; - - /* Status must be Established. */ - if (peer->status != Established) - { - zlog_err ("%s [FSM] Update packet received under status %s", - peer->host, lookup_msg(bgp_status_msg, peer->status, NULL)); - bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0); - return -1; - } - - /* Set initial values. */ - memset (&attr, 0, sizeof (struct attr)); - attr.label_index = BGP_INVALID_LABEL_INDEX; - attr.label = MPLS_INVALID_LABEL; - memset (&nlris, 0, sizeof (nlris)); - memset (peer->rcvd_attr_str, 0, BUFSIZ); - peer->rcvd_attr_printed = 0; - - s = peer->ibuf; - end = stream_pnt (s) + size; - - /* RFC1771 6.3 If the Unfeasible Routes Length or Total Attribute - Length is too large (i.e., if Unfeasible Routes Length + Total - Attribute Length + 23 exceeds the message Length), then the Error - Subcode is set to Malformed Attribute List. */ - if (stream_pnt (s) + 2 > end) - { - zlog_err ("%s [Error] Update packet error" - " (packet length is short for unfeasible length)", - peer->host); - bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_MAL_ATTR); - return -1; - } - - /* Unfeasible Route Length. */ - withdraw_len = stream_getw (s); - - /* Unfeasible Route Length check. */ - if (stream_pnt (s) + withdraw_len > end) - { - zlog_err ("%s [Error] Update packet error" - " (packet unfeasible length overflow %d)", - peer->host, withdraw_len); - bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_MAL_ATTR); - return -1; - } - - /* Unfeasible Route packet format check. */ - if (withdraw_len > 0) - { - nlris[NLRI_WITHDRAW].afi = AFI_IP; - nlris[NLRI_WITHDRAW].safi = SAFI_UNICAST; - nlris[NLRI_WITHDRAW].nlri = stream_pnt (s); - nlris[NLRI_WITHDRAW].length = withdraw_len; - stream_forward_getp (s, withdraw_len); - } - - /* Attribute total length check. */ - if (stream_pnt (s) + 2 > end) - { - zlog_warn ("%s [Error] Packet Error" - " (update packet is short for attribute length)", - peer->host); - bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_MAL_ATTR); - return -1; - } - - /* Fetch attribute total length. */ - attribute_len = stream_getw (s); - - /* Attribute length check. */ - if (stream_pnt (s) + attribute_len > end) - { - zlog_warn ("%s [Error] Packet Error" - " (update packet attribute length overflow %d)", - peer->host, attribute_len); - bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_MAL_ATTR); - return -1; - } - - /* Certain attribute parsing errors should not be considered bad enough - * to reset the session for, most particularly any partial/optional - * attributes that have 'tunneled' over speakers that don't understand - * them. Instead we withdraw only the prefix concerned. - * - * Complicates the flow a little though.. - */ - bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED; - /* This define morphs the update case into a withdraw when lower levels - * have signalled an error condition where this is best. - */ + int ret, nlri_ret; + u_char *end; + struct stream *s; + struct attr attr; + bgp_size_t attribute_len; + bgp_size_t update_len; + bgp_size_t withdraw_len; + + enum NLRI_TYPES { + NLRI_UPDATE, + NLRI_WITHDRAW, + NLRI_MP_UPDATE, + NLRI_MP_WITHDRAW, + NLRI_TYPE_MAX + }; + struct bgp_nlri nlris[NLRI_TYPE_MAX]; + + /* Status must be Established. */ + if (peer->status != Established) { + zlog_err("%s [FSM] Update packet received under status %s", + peer->host, + lookup_msg(bgp_status_msg, peer->status, NULL)); + bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, 0); + return -1; + } + + /* Set initial values. */ + memset(&attr, 0, sizeof(struct attr)); + attr.label_index = BGP_INVALID_LABEL_INDEX; + attr.label = MPLS_INVALID_LABEL; + memset(&nlris, 0, sizeof(nlris)); + memset(peer->rcvd_attr_str, 0, BUFSIZ); + peer->rcvd_attr_printed = 0; + + s = peer->ibuf; + end = stream_pnt(s) + size; + + /* RFC1771 6.3 If the Unfeasible Routes Length or Total Attribute + Length is too large (i.e., if Unfeasible Routes Length + Total + Attribute Length + 23 exceeds the message Length), then the Error + Subcode is set to Malformed Attribute List. */ + if (stream_pnt(s) + 2 > end) { + zlog_err( + "%s [Error] Update packet error" + " (packet length is short for unfeasible length)", + peer->host); + bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_MAL_ATTR); + return -1; + } + + /* Unfeasible Route Length. */ + withdraw_len = stream_getw(s); + + /* Unfeasible Route Length check. */ + if (stream_pnt(s) + withdraw_len > end) { + zlog_err( + "%s [Error] Update packet error" + " (packet unfeasible length overflow %d)", + peer->host, withdraw_len); + bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_MAL_ATTR); + return -1; + } + + /* Unfeasible Route packet format check. */ + if (withdraw_len > 0) { + nlris[NLRI_WITHDRAW].afi = AFI_IP; + nlris[NLRI_WITHDRAW].safi = SAFI_UNICAST; + nlris[NLRI_WITHDRAW].nlri = stream_pnt(s); + nlris[NLRI_WITHDRAW].length = withdraw_len; + stream_forward_getp(s, withdraw_len); + } + + /* Attribute total length check. */ + if (stream_pnt(s) + 2 > end) { + zlog_warn( + "%s [Error] Packet Error" + " (update packet is short for attribute length)", + peer->host); + bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_MAL_ATTR); + return -1; + } + + /* Fetch attribute total length. */ + attribute_len = stream_getw(s); + + /* Attribute length check. */ + if (stream_pnt(s) + attribute_len > end) { + zlog_warn( + "%s [Error] Packet Error" + " (update packet attribute length overflow %d)", + peer->host, attribute_len); + bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_MAL_ATTR); + return -1; + } + + /* Certain attribute parsing errors should not be considered bad enough + * to reset the session for, most particularly any partial/optional + * attributes that have 'tunneled' over speakers that don't understand + * them. Instead we withdraw only the prefix concerned. + * + * Complicates the flow a little though.. + */ + bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED; +/* This define morphs the update case into a withdraw when lower levels + * have signalled an error condition where this is best. + */ #define NLRI_ATTR_ARG (attr_parse_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL) - /* Parse attribute when it exists. */ - if (attribute_len) - { - attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len, - &nlris[NLRI_MP_UPDATE], &nlris[NLRI_MP_WITHDRAW]); - if (attr_parse_ret == BGP_ATTR_PARSE_ERROR) - { - bgp_attr_unintern_sub (&attr); - return -1; + /* Parse attribute when it exists. */ + if (attribute_len) { + attr_parse_ret = bgp_attr_parse(peer, &attr, attribute_len, + &nlris[NLRI_MP_UPDATE], + &nlris[NLRI_MP_WITHDRAW]); + if (attr_parse_ret == BGP_ATTR_PARSE_ERROR) { + bgp_attr_unintern_sub(&attr); + return -1; + } + } + + /* Logging the attribute. */ + if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW + || BGP_DEBUG(update, UPDATE_IN) + || BGP_DEBUG(update, UPDATE_PREFIX)) { + ret = bgp_dump_attr(&attr, peer->rcvd_attr_str, BUFSIZ); + + if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW) + zlog_err( + "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.", + peer->host); + + if (ret && bgp_debug_update(peer, NULL, NULL, 1)) { + zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host, + peer->rcvd_attr_str); + peer->rcvd_attr_printed = 1; + } + } + + /* Network Layer Reachability Information. */ + update_len = end - stream_pnt(s); + + if (update_len) { + /* Set NLRI portion to structure. */ + nlris[NLRI_UPDATE].afi = AFI_IP; + nlris[NLRI_UPDATE].safi = SAFI_UNICAST; + nlris[NLRI_UPDATE].nlri = stream_pnt(s); + nlris[NLRI_UPDATE].length = update_len; + stream_forward_getp(s, update_len); + } + + if (BGP_DEBUG(update, UPDATE_IN)) + zlog_debug("%s rcvd UPDATE wlen %d attrlen %d alen %d", + peer->host, withdraw_len, attribute_len, update_len); + + /* Parse any given NLRIs */ + for (int i = NLRI_UPDATE; i < NLRI_TYPE_MAX; i++) { + if (!nlris[i].nlri) + continue; + + /* NLRI is processed iff the peer if configured for the specific + * afi/safi */ + if (!peer->afc[nlris[i].afi][nlris[i].safi]) { + zlog_info( + "%s [Info] UPDATE for non-enabled AFI/SAFI %u/%u", + peer->host, nlris[i].afi, nlris[i].safi); + continue; + } + + /* EoR handled later */ + if (nlris[i].length == 0) + continue; + + switch (i) { + case NLRI_UPDATE: + case NLRI_MP_UPDATE: + nlri_ret = bgp_nlri_parse(peer, NLRI_ATTR_ARG, + &nlris[i], 0); + break; + case NLRI_WITHDRAW: + case NLRI_MP_WITHDRAW: + nlri_ret = bgp_nlri_parse(peer, &attr, &nlris[i], 1); + break; + default: + nlri_ret = -1; + } + + if (nlri_ret < 0) { + zlog_err("%s [Error] Error parsing NLRI", peer->host); + if (peer->status == Established) + bgp_notify_send( + peer, BGP_NOTIFY_UPDATE_ERR, + i <= NLRI_WITHDRAW + ? BGP_NOTIFY_UPDATE_INVAL_NETWORK + : BGP_NOTIFY_UPDATE_OPT_ATTR_ERR); + bgp_attr_unintern_sub(&attr); + return -1; + } + } + + /* EoR checks + * + * Non-MP IPv4/Unicast EoR is a completely empty UPDATE + * and MP EoR should have only an empty MP_UNREACH + */ + if (!update_len && !withdraw_len && nlris[NLRI_MP_UPDATE].length == 0) { + afi_t afi = 0; + safi_t safi; + + /* Non-MP IPv4/Unicast is a completely emtpy UPDATE - already + * checked + * update and withdraw NLRI lengths are 0. + */ + if (!attribute_len) { + afi = AFI_IP; + safi = SAFI_UNICAST; + } else if (attr.flag & ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI) + && nlris[NLRI_MP_WITHDRAW].length == 0) { + afi = nlris[NLRI_MP_WITHDRAW].afi; + safi = nlris[NLRI_MP_WITHDRAW].safi; + } + + if (afi && peer->afc[afi][safi]) { + /* End-of-RIB received */ + if (!CHECK_FLAG(peer->af_sflags[afi][safi], + PEER_STATUS_EOR_RECEIVED)) { + SET_FLAG(peer->af_sflags[afi][safi], + PEER_STATUS_EOR_RECEIVED); + bgp_update_explicit_eors(peer); + } + + /* NSF delete stale route */ + if (peer->nsf[afi][safi]) + bgp_clear_stale_route(peer, afi, safi); + + if (bgp_debug_neighbor_events(peer)) { + zlog_debug("rcvd End-of-RIB for %s from %s", + afi_safi_print(afi, safi), + peer->host); + } + } } - } - - /* Logging the attribute. */ - if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW || - BGP_DEBUG (update, UPDATE_IN) || - BGP_DEBUG (update, UPDATE_PREFIX)) - { - ret = bgp_dump_attr (&attr, peer->rcvd_attr_str, BUFSIZ); - - if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW) - zlog_err ("%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.", - peer->host); - - if (ret && bgp_debug_update(peer, NULL, NULL, 1)) - { - zlog_debug ("%s rcvd UPDATE w/ attr: %s", peer->host, peer->rcvd_attr_str); - peer->rcvd_attr_printed = 1; - } - } - - /* Network Layer Reachability Information. */ - update_len = end - stream_pnt (s); - - if (update_len) - { - /* Set NLRI portion to structure. */ - nlris[NLRI_UPDATE].afi = AFI_IP; - nlris[NLRI_UPDATE].safi = SAFI_UNICAST; - nlris[NLRI_UPDATE].nlri = stream_pnt (s); - nlris[NLRI_UPDATE].length = update_len; - stream_forward_getp (s, update_len); - } - - if (BGP_DEBUG (update, UPDATE_IN)) - zlog_debug("%s rcvd UPDATE wlen %d attrlen %d alen %d", - peer->host, withdraw_len, attribute_len, update_len); - - /* Parse any given NLRIs */ - for (int i = NLRI_UPDATE; i < NLRI_TYPE_MAX; i++) - { - if (!nlris[i].nlri) - continue; - - /* NLRI is processed iff the peer if configured for the specific afi/safi */ - if (!peer->afc[nlris[i].afi][nlris[i].safi]) - { - zlog_info ("%s [Info] UPDATE for non-enabled AFI/SAFI %u/%u", - peer->host, nlris[i].afi, nlris[i].safi); - continue; - } - - /* EoR handled later */ - if (nlris[i].length == 0) - continue; - - switch (i) - { - case NLRI_UPDATE: - case NLRI_MP_UPDATE: - nlri_ret = bgp_nlri_parse (peer, NLRI_ATTR_ARG, &nlris[i], 0); - break; - case NLRI_WITHDRAW: - case NLRI_MP_WITHDRAW: - nlri_ret = bgp_nlri_parse (peer, &attr, &nlris[i], 1); - break; - default: - nlri_ret = -1; - } - - if (nlri_ret < 0) - { - zlog_err("%s [Error] Error parsing NLRI", peer->host); - if (peer->status == Established) - bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, - i <= NLRI_WITHDRAW ? BGP_NOTIFY_UPDATE_INVAL_NETWORK - : BGP_NOTIFY_UPDATE_OPT_ATTR_ERR); - bgp_attr_unintern_sub (&attr); - return -1; - } - } - - /* EoR checks - * - * Non-MP IPv4/Unicast EoR is a completely empty UPDATE - * and MP EoR should have only an empty MP_UNREACH - */ - if (!update_len && !withdraw_len - && nlris[NLRI_MP_UPDATE].length == 0) - { - afi_t afi = 0; - safi_t safi; - - /* Non-MP IPv4/Unicast is a completely emtpy UPDATE - already checked - * update and withdraw NLRI lengths are 0. - */ - if (!attribute_len) - { - afi = AFI_IP; - safi = SAFI_UNICAST; - } - else if (attr.flag & ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI) - && nlris[NLRI_MP_WITHDRAW].length == 0) - { - afi = nlris[NLRI_MP_WITHDRAW].afi; - safi = nlris[NLRI_MP_WITHDRAW].safi; - } - - if (afi && peer->afc[afi][safi]) - { - /* End-of-RIB received */ - if (!CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_RECEIVED)) - { - SET_FLAG (peer->af_sflags[afi][safi], - PEER_STATUS_EOR_RECEIVED); - bgp_update_explicit_eors(peer); - } - - /* NSF delete stale route */ - if (peer->nsf[afi][safi]) - bgp_clear_stale_route (peer, afi, safi); - - if (bgp_debug_neighbor_events(peer)) - { - zlog_debug ("rcvd End-of-RIB for %s from %s", - afi_safi_print (afi, safi), peer->host); - } - } - } - - /* Everything is done. We unintern temporary structures which - interned in bgp_attr_parse(). */ - bgp_attr_unintern_sub (&attr); - - /* If peering is stopped due to some reason, do not generate BGP - event. */ - if (peer->status != Established) - return 0; - - /* Increment packet counter. */ - peer->update_in++; - peer->update_time = bgp_clock (); - - /* Rearm holdtime timer */ - BGP_TIMER_OFF (peer->t_holdtime); - bgp_timer_set (peer); - - return 0; + + /* Everything is done. We unintern temporary structures which + interned in bgp_attr_parse(). */ + bgp_attr_unintern_sub(&attr); + + /* If peering is stopped due to some reason, do not generate BGP + event. */ + if (peer->status != Established) + return 0; + + /* Increment packet counter. */ + peer->update_in++; + peer->update_time = bgp_clock(); + + /* Rearm holdtime timer */ + BGP_TIMER_OFF(peer->t_holdtime); + bgp_timer_set(peer); + + return 0; } /* Notify message treatment function. */ -static void -bgp_notify_receive (struct peer *peer, bgp_size_t size) +static void bgp_notify_receive(struct peer *peer, bgp_size_t size) { - struct bgp_notify bgp_notify; - - if (peer->notify.data) - { - XFREE (MTYPE_TMP, peer->notify.data); - peer->notify.data = NULL; - peer->notify.length = 0; - } - - bgp_notify.code = stream_getc (peer->ibuf); - bgp_notify.subcode = stream_getc (peer->ibuf); - bgp_notify.length = size - 2; - bgp_notify.data = NULL; - - /* Preserv notify code and sub code. */ - peer->notify.code = bgp_notify.code; - peer->notify.subcode = bgp_notify.subcode; - /* For further diagnostic record returned Data. */ - if (bgp_notify.length) - { - peer->notify.length = size - 2; - peer->notify.data = XMALLOC (MTYPE_TMP, size - 2); - memcpy (peer->notify.data, stream_pnt (peer->ibuf), size - 2); - } - - /* For debug */ - { - int i; - int first = 0; - char c[4]; - - if (bgp_notify.length) - { - bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3); - for (i = 0; i < bgp_notify.length; i++) - if (first) - { - sprintf (c, " %02x", stream_getc (peer->ibuf)); - strcat (bgp_notify.data, c); - } - else - { - first = 1; - sprintf (c, "%02x", stream_getc (peer->ibuf)); - strcpy (bgp_notify.data, c); - } - bgp_notify.raw_data = (u_char*)peer->notify.data; - } - - bgp_notify_print(peer, &bgp_notify, "received"); - if (bgp_notify.data) - { - XFREE (MTYPE_TMP, bgp_notify.data); - bgp_notify.data = NULL; - bgp_notify.length = 0; - } - } - - /* peer count update */ - peer->notify_in++; - - peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED; - - /* We have to check for Notify with Unsupported Optional Parameter. - in that case we fallback to open without the capability option. - But this done in bgp_stop. We just mark it here to avoid changing - the fsm tables. */ - if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR && - bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM ) - UNSET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN); - - BGP_EVENT_ADD (peer, Receive_NOTIFICATION_message); + struct bgp_notify bgp_notify; + + if (peer->notify.data) { + XFREE(MTYPE_TMP, peer->notify.data); + peer->notify.data = NULL; + peer->notify.length = 0; + } + + bgp_notify.code = stream_getc(peer->ibuf); + bgp_notify.subcode = stream_getc(peer->ibuf); + bgp_notify.length = size - 2; + bgp_notify.data = NULL; + + /* Preserv notify code and sub code. */ + peer->notify.code = bgp_notify.code; + peer->notify.subcode = bgp_notify.subcode; + /* For further diagnostic record returned Data. */ + if (bgp_notify.length) { + peer->notify.length = size - 2; + peer->notify.data = XMALLOC(MTYPE_TMP, size - 2); + memcpy(peer->notify.data, stream_pnt(peer->ibuf), size - 2); + } + + /* For debug */ + { + int i; + int first = 0; + char c[4]; + + if (bgp_notify.length) { + bgp_notify.data = + XMALLOC(MTYPE_TMP, bgp_notify.length * 3); + for (i = 0; i < bgp_notify.length; i++) + if (first) { + sprintf(c, " %02x", + stream_getc(peer->ibuf)); + strcat(bgp_notify.data, c); + } else { + first = 1; + sprintf(c, "%02x", + stream_getc(peer->ibuf)); + strcpy(bgp_notify.data, c); + } + bgp_notify.raw_data = (u_char *)peer->notify.data; + } + + bgp_notify_print(peer, &bgp_notify, "received"); + if (bgp_notify.data) { + XFREE(MTYPE_TMP, bgp_notify.data); + bgp_notify.data = NULL; + bgp_notify.length = 0; + } + } + + /* peer count update */ + peer->notify_in++; + + peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED; + + /* We have to check for Notify with Unsupported Optional Parameter. + in that case we fallback to open without the capability option. + But this done in bgp_stop. We just mark it here to avoid changing + the fsm tables. */ + if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR + && bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM) + UNSET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN); + + BGP_EVENT_ADD(peer, Receive_NOTIFICATION_message); } /* Keepalive treatment function -- get keepalive send keepalive */ -static void -bgp_keepalive_receive (struct peer *peer, bgp_size_t size) +static void bgp_keepalive_receive(struct peer *peer, bgp_size_t size) { - if (bgp_debug_keepalive(peer)) - zlog_debug ("%s KEEPALIVE rcvd", peer->host); - - BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message); + if (bgp_debug_keepalive(peer)) + zlog_debug("%s KEEPALIVE rcvd", peer->host); + + BGP_EVENT_ADD(peer, Receive_KEEPALIVE_message); } /* Route refresh message is received. */ -static void -bgp_route_refresh_receive (struct peer *peer, bgp_size_t size) +static void bgp_route_refresh_receive(struct peer *peer, bgp_size_t size) { - iana_afi_t pkt_afi; - afi_t afi; - safi_t pkt_safi, safi; - struct stream *s; - struct peer_af *paf; - struct update_group *updgrp; - struct peer *updgrp_peer; - - /* If peer does not have the capability, send notification. */ - if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV)) - { - zlog_err ("%s [Error] BGP route refresh is not enabled", - peer->host); - bgp_notify_send (peer, - BGP_NOTIFY_HEADER_ERR, - BGP_NOTIFY_HEADER_BAD_MESTYPE); - return; - } - - /* Status must be Established. */ - if (peer->status != Established) - { - zlog_err ("%s [Error] Route refresh packet received under status %s", - peer->host, lookup_msg(bgp_status_msg, peer->status, NULL)); - bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0); - return; - } - - s = peer->ibuf; - - /* Parse packet. */ - pkt_afi = stream_getw (s); - (void)stream_getc (s); - pkt_safi = stream_getc (s); - - if (bgp_debug_update(peer, NULL, NULL, 0)) - zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d", - peer->host, pkt_afi, pkt_safi); - - /* Convert AFI, SAFI to internal values and check. */ - if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi)) - { - zlog_info ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored", - peer->host, pkt_afi, pkt_safi); - return; - } - - if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) - { - u_char *end; - u_char when_to_refresh; - u_char orf_type; - u_int16_t orf_len; - - if (size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) < 5) - { - zlog_info ("%s ORF route refresh length error", peer->host); - bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); - return; - } - - when_to_refresh = stream_getc (s); - end = stream_pnt (s) + (size - 5); - - while ((stream_pnt (s) + 2) < end) - { - orf_type = stream_getc (s); - orf_len = stream_getw (s); - - /* orf_len in bounds? */ - if ((stream_pnt (s) + orf_len) > end) - break; /* XXX: Notify instead?? */ - if (orf_type == ORF_TYPE_PREFIX - || orf_type == ORF_TYPE_PREFIX_OLD) - { - uint8_t *p_pnt = stream_pnt (s); - uint8_t *p_end = stream_pnt (s) + orf_len; - struct orf_prefix orfp; - u_char common = 0; - u_int32_t seq; - int psize; - char name[BUFSIZ]; - int ret = CMD_SUCCESS; - - if (bgp_debug_neighbor_events(peer)) - { - zlog_debug ("%s rcvd Prefixlist ORF(%d) length %d", - peer->host, orf_type, orf_len); + iana_afi_t pkt_afi; + afi_t afi; + safi_t pkt_safi, safi; + struct stream *s; + struct peer_af *paf; + struct update_group *updgrp; + struct peer *updgrp_peer; + + /* If peer does not have the capability, send notification. */ + if (!CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_ADV)) { + zlog_err("%s [Error] BGP route refresh is not enabled", + peer->host); + bgp_notify_send(peer, BGP_NOTIFY_HEADER_ERR, + BGP_NOTIFY_HEADER_BAD_MESTYPE); + return; + } + + /* Status must be Established. */ + if (peer->status != Established) { + zlog_err( + "%s [Error] Route refresh packet received under status %s", + peer->host, + lookup_msg(bgp_status_msg, peer->status, NULL)); + bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, 0); + return; + } + + s = peer->ibuf; + + /* Parse packet. */ + pkt_afi = stream_getw(s); + (void)stream_getc(s); + pkt_safi = stream_getc(s); + + if (bgp_debug_update(peer, NULL, NULL, 0)) + zlog_debug("%s rcvd REFRESH_REQ for afi/safi: %d/%d", + peer->host, pkt_afi, pkt_safi); + + /* Convert AFI, SAFI to internal values and check. */ + if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) { + zlog_info( + "%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored", + peer->host, pkt_afi, pkt_safi); + return; + } + + if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) { + u_char *end; + u_char when_to_refresh; + u_char orf_type; + u_int16_t orf_len; + + if (size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) + < 5) { + zlog_info("%s ORF route refresh length error", + peer->host); + bgp_notify_send(peer, BGP_NOTIFY_CEASE, 0); + return; } - /* we're going to read at least 1 byte of common ORF header, - * and 7 bytes of ORF Address-filter entry from the stream - */ - if (orf_len < 7) - break; - - /* ORF prefix-list name */ - sprintf (name, "%s.%d.%d", peer->host, afi, safi); - - while (p_pnt < p_end) - { - /* If the ORF entry is malformed, want to read as much of it - * as possible without going beyond the bounds of the entry, - * to maximise debug information. - */ - int ok; - memset (&orfp, 0, sizeof (struct orf_prefix)); - common = *p_pnt++; - /* after ++: p_pnt <= p_end */ - if (common & ORF_COMMON_PART_REMOVE_ALL) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s rcvd Remove-All pfxlist ORF request", peer->host); - prefix_bgp_orf_remove_all (afi, name); - break; - } - ok = ((u_int32_t)(p_end - p_pnt) >= sizeof(u_int32_t)) ; - if (ok) - { - memcpy (&seq, p_pnt, sizeof (u_int32_t)); - p_pnt += sizeof (u_int32_t); - orfp.seq = ntohl (seq); - } - else - p_pnt = p_end ; - - if ((ok = (p_pnt < p_end))) - orfp.ge = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */ - if ((ok = (p_pnt < p_end))) - orfp.le = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */ - if ((ok = (p_pnt < p_end))) - orfp.p.prefixlen = *p_pnt++ ; - orfp.p.family = afi2family (afi); /* afi checked already */ - - psize = PSIZE (orfp.p.prefixlen); /* 0 if not ok */ - if (psize > prefix_blen(&orfp.p)) /* valid for family ? */ - { - ok = 0 ; - psize = prefix_blen(&orfp.p) ; - } - if (psize > (p_end - p_pnt)) /* valid for packet ? */ - { - ok = 0 ; - psize = p_end - p_pnt ; - } - - if (psize > 0) - memcpy (&orfp.p.u.prefix, p_pnt, psize); - p_pnt += psize; - - if (bgp_debug_neighbor_events(peer)) - { - char buf[INET6_BUFSIZ]; - - zlog_debug ("%s rcvd %s %s seq %u %s/%d ge %d le %d%s", - peer->host, - (common & ORF_COMMON_PART_REMOVE ? "Remove" : "Add"), - (common & ORF_COMMON_PART_DENY ? "deny" : "permit"), - orfp.seq, - inet_ntop (orfp.p.family, &orfp.p.u.prefix, buf, INET6_BUFSIZ), - orfp.p.prefixlen, orfp.ge, orfp.le, - ok ? "" : " MALFORMED"); - } - - if (ok) - ret = prefix_bgp_orf_set (name, afi, &orfp, - (common & ORF_COMMON_PART_DENY ? 0 : 1 ), - (common & ORF_COMMON_PART_REMOVE ? 0 : 1)); - - if (!ok || (ok && ret != CMD_SUCCESS)) - { - zlog_info ("%s Received misformatted prefixlist ORF." - " Remove All pfxlist", peer->host); - prefix_bgp_orf_remove_all (afi, name); - break; - } + when_to_refresh = stream_getc(s); + end = stream_pnt(s) + (size - 5); + + while ((stream_pnt(s) + 2) < end) { + orf_type = stream_getc(s); + orf_len = stream_getw(s); + + /* orf_len in bounds? */ + if ((stream_pnt(s) + orf_len) > end) + break; /* XXX: Notify instead?? */ + if (orf_type == ORF_TYPE_PREFIX + || orf_type == ORF_TYPE_PREFIX_OLD) { + uint8_t *p_pnt = stream_pnt(s); + uint8_t *p_end = stream_pnt(s) + orf_len; + struct orf_prefix orfp; + u_char common = 0; + u_int32_t seq; + int psize; + char name[BUFSIZ]; + int ret = CMD_SUCCESS; + + if (bgp_debug_neighbor_events(peer)) { + zlog_debug( + "%s rcvd Prefixlist ORF(%d) length %d", + peer->host, orf_type, orf_len); + } + + /* we're going to read at least 1 byte of common + * ORF header, + * and 7 bytes of ORF Address-filter entry from + * the stream + */ + if (orf_len < 7) + break; + + /* ORF prefix-list name */ + sprintf(name, "%s.%d.%d", peer->host, afi, + safi); + + while (p_pnt < p_end) { + /* If the ORF entry is malformed, want + * to read as much of it + * as possible without going beyond the + * bounds of the entry, + * to maximise debug information. + */ + int ok; + memset(&orfp, 0, + sizeof(struct orf_prefix)); + common = *p_pnt++; + /* after ++: p_pnt <= p_end */ + if (common + & ORF_COMMON_PART_REMOVE_ALL) { + if (bgp_debug_neighbor_events( + peer)) + zlog_debug( + "%s rcvd Remove-All pfxlist ORF request", + peer->host); + prefix_bgp_orf_remove_all(afi, + name); + break; + } + ok = ((u_int32_t)(p_end - p_pnt) + >= sizeof(u_int32_t)); + if (ok) { + memcpy(&seq, p_pnt, + sizeof(u_int32_t)); + p_pnt += sizeof(u_int32_t); + orfp.seq = ntohl(seq); + } else + p_pnt = p_end; + + if ((ok = (p_pnt < p_end))) + orfp.ge = + *p_pnt++; /* value + checked in + prefix_bgp_orf_set() + */ + if ((ok = (p_pnt < p_end))) + orfp.le = + *p_pnt++; /* value + checked in + prefix_bgp_orf_set() + */ + if ((ok = (p_pnt < p_end))) + orfp.p.prefixlen = *p_pnt++; + orfp.p.family = afi2family( + afi); /* afi checked already */ + + psize = PSIZE( + orfp.p.prefixlen); /* 0 if not + ok */ + if (psize + > prefix_blen( + &orfp.p)) /* valid for + family ? */ + { + ok = 0; + psize = prefix_blen(&orfp.p); + } + if (psize + > (p_end - p_pnt)) /* valid for + packet ? */ + { + ok = 0; + psize = p_end - p_pnt; + } + + if (psize > 0) + memcpy(&orfp.p.u.prefix, p_pnt, + psize); + p_pnt += psize; + + if (bgp_debug_neighbor_events(peer)) { + char buf[INET6_BUFSIZ]; + + zlog_debug( + "%s rcvd %s %s seq %u %s/%d ge %d le %d%s", + peer->host, + (common & ORF_COMMON_PART_REMOVE + ? "Remove" + : "Add"), + (common & ORF_COMMON_PART_DENY + ? "deny" + : "permit"), + orfp.seq, + inet_ntop( + orfp.p.family, + &orfp.p.u.prefix, + buf, + INET6_BUFSIZ), + orfp.p.prefixlen, + orfp.ge, orfp.le, + ok ? "" : " MALFORMED"); + } + + if (ok) + ret = prefix_bgp_orf_set( + name, afi, &orfp, + (common & ORF_COMMON_PART_DENY + ? 0 + : 1), + (common & ORF_COMMON_PART_REMOVE + ? 0 + : 1)); + + if (!ok || (ok && ret != CMD_SUCCESS)) { + zlog_info( + "%s Received misformatted prefixlist ORF." + " Remove All pfxlist", + peer->host); + prefix_bgp_orf_remove_all(afi, + name); + break; + } + } + + peer->orf_plist[afi][safi] = + prefix_bgp_orf_lookup(afi, name); + } + stream_forward_getp(s, orf_len); } + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s rcvd Refresh %s ORF request", peer->host, + when_to_refresh == REFRESH_DEFER + ? "Defer" + : "Immediate"); + if (when_to_refresh == REFRESH_DEFER) + return; + } - peer->orf_plist[afi][safi] = prefix_bgp_orf_lookup (afi, name); - } - stream_forward_getp (s, orf_len); + /* First update is deferred until ORF or ROUTE-REFRESH is received */ + if (CHECK_FLAG(peer->af_sflags[afi][safi], + PEER_STATUS_ORF_WAIT_REFRESH)) + UNSET_FLAG(peer->af_sflags[afi][safi], + PEER_STATUS_ORF_WAIT_REFRESH); + + paf = peer_af_find(peer, afi, safi); + if (paf && paf->subgroup) { + if (peer->orf_plist[afi][safi]) { + updgrp = PAF_UPDGRP(paf); + updgrp_peer = UPDGRP_PEER(updgrp); + updgrp_peer->orf_plist[afi][safi] = + peer->orf_plist[afi][safi]; + } + + /* If the peer is configured for default-originate clear the + * SUBGRP_STATUS_DEFAULT_ORIGINATE flag so that we will + * re-advertise the + * default + */ + if (CHECK_FLAG(paf->subgroup->sflags, + SUBGRP_STATUS_DEFAULT_ORIGINATE)) + UNSET_FLAG(paf->subgroup->sflags, + SUBGRP_STATUS_DEFAULT_ORIGINATE); } - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s rcvd Refresh %s ORF request", peer->host, - when_to_refresh == REFRESH_DEFER ? "Defer" : "Immediate"); - if (when_to_refresh == REFRESH_DEFER) - return; - } - - /* First update is deferred until ORF or ROUTE-REFRESH is received */ - if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH)) - UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH); - - paf = peer_af_find (peer, afi, safi); - if (paf && paf->subgroup) - { - if (peer->orf_plist[afi][safi]) - { - updgrp = PAF_UPDGRP(paf); - updgrp_peer = UPDGRP_PEER(updgrp); - updgrp_peer->orf_plist[afi][safi] = peer->orf_plist[afi][safi]; - } - - /* If the peer is configured for default-originate clear the - * SUBGRP_STATUS_DEFAULT_ORIGINATE flag so that we will re-advertise the - * default - */ - if (CHECK_FLAG (paf->subgroup->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) - UNSET_FLAG (paf->subgroup->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE); - } - - /* Perform route refreshment to the peer */ - bgp_announce_route (peer, afi, safi); + + /* Perform route refreshment to the peer */ + bgp_announce_route(peer, afi, safi); } -static int -bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length) +static int bgp_capability_msg_parse(struct peer *peer, u_char *pnt, + bgp_size_t length) { - u_char *end; - struct capability_mp_data mpc; - struct capability_header *hdr; - u_char action; - iana_afi_t pkt_afi; - afi_t afi; - safi_t pkt_safi, safi; - - end = pnt + length; - - while (pnt < end) - { - /* We need at least action, capability code and capability length. */ - if (pnt + 3 > end) - { - zlog_info ("%s Capability length error", peer->host); - bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); - return -1; - } - action = *pnt; - hdr = (struct capability_header *)(pnt + 1); - - /* Action value check. */ - if (action != CAPABILITY_ACTION_SET - && action != CAPABILITY_ACTION_UNSET) - { - zlog_info ("%s Capability Action Value error %d", - peer->host, action); - bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); - return -1; - } - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u", - peer->host, action, hdr->code, hdr->length); - - /* Capability length check. */ - if ((pnt + hdr->length + 3) > end) - { - zlog_info ("%s Capability length error", peer->host); - bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); - return -1; - } - - /* Fetch structure to the byte stream. */ - memcpy (&mpc, pnt + 3, sizeof (struct capability_mp_data)); - - /* We know MP Capability Code. */ - if (hdr->code == CAPABILITY_CODE_MP) - { - pkt_afi = ntohs (mpc.afi); - pkt_safi = mpc.safi; - - /* Ignore capability when override-capability is set. */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) - continue; - - /* Convert AFI, SAFI to internal values. */ - if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi)) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid " - "(%u/%u)", peer->host, pkt_afi, pkt_safi); - continue; - } - - /* Address family check. */ - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u", - peer->host, - action == CAPABILITY_ACTION_SET - ? "Advertising" : "Removing", - pkt_afi, pkt_safi); - - if (action == CAPABILITY_ACTION_SET) - { - peer->afc_recv[afi][safi] = 1; - if (peer->afc[afi][safi]) - { - peer->afc_nego[afi][safi] = 1; - bgp_announce_route (peer, afi, safi); - } - } - else - { - peer->afc_recv[afi][safi] = 0; - peer->afc_nego[afi][safi] = 0; - - if (peer_active_nego (peer)) - bgp_clear_route (peer, afi, safi); - else - BGP_EVENT_ADD (peer, BGP_Stop); - } - } - else - { - zlog_warn ("%s unrecognized capability code: %d - ignored", - peer->host, hdr->code); - } - pnt += hdr->length + 3; - } - return 0; + u_char *end; + struct capability_mp_data mpc; + struct capability_header *hdr; + u_char action; + iana_afi_t pkt_afi; + afi_t afi; + safi_t pkt_safi, safi; + + end = pnt + length; + + while (pnt < end) { + /* We need at least action, capability code and capability + * length. */ + if (pnt + 3 > end) { + zlog_info("%s Capability length error", peer->host); + bgp_notify_send(peer, BGP_NOTIFY_CEASE, 0); + return -1; + } + action = *pnt; + hdr = (struct capability_header *)(pnt + 1); + + /* Action value check. */ + if (action != CAPABILITY_ACTION_SET + && action != CAPABILITY_ACTION_UNSET) { + zlog_info("%s Capability Action Value error %d", + peer->host, action); + bgp_notify_send(peer, BGP_NOTIFY_CEASE, 0); + return -1; + } + + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s CAPABILITY has action: %d, code: %u, length %u", + peer->host, action, hdr->code, hdr->length); + + /* Capability length check. */ + if ((pnt + hdr->length + 3) > end) { + zlog_info("%s Capability length error", peer->host); + bgp_notify_send(peer, BGP_NOTIFY_CEASE, 0); + return -1; + } + + /* Fetch structure to the byte stream. */ + memcpy(&mpc, pnt + 3, sizeof(struct capability_mp_data)); + + /* We know MP Capability Code. */ + if (hdr->code == CAPABILITY_CODE_MP) { + pkt_afi = ntohs(mpc.afi); + pkt_safi = mpc.safi; + + /* Ignore capability when override-capability is set. */ + if (CHECK_FLAG(peer->flags, + PEER_FLAG_OVERRIDE_CAPABILITY)) + continue; + + /* Convert AFI, SAFI to internal values. */ + if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, + &safi)) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Dynamic Capability MP_EXT afi/safi invalid " + "(%u/%u)", + peer->host, pkt_afi, pkt_safi); + continue; + } + + /* Address family check. */ + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u", + peer->host, + action == CAPABILITY_ACTION_SET + ? "Advertising" + : "Removing", + pkt_afi, pkt_safi); + + if (action == CAPABILITY_ACTION_SET) { + peer->afc_recv[afi][safi] = 1; + if (peer->afc[afi][safi]) { + peer->afc_nego[afi][safi] = 1; + bgp_announce_route(peer, afi, safi); + } + } else { + peer->afc_recv[afi][safi] = 0; + peer->afc_nego[afi][safi] = 0; + + if (peer_active_nego(peer)) + bgp_clear_route(peer, afi, safi); + else + BGP_EVENT_ADD(peer, BGP_Stop); + } + } else { + zlog_warn( + "%s unrecognized capability code: %d - ignored", + peer->host, hdr->code); + } + pnt += hdr->length + 3; + } + return 0; } -/* Dynamic Capability is received. +/* Dynamic Capability is received. * * This is exported for unit-test purposes */ -int -bgp_capability_receive (struct peer *peer, bgp_size_t size) +int bgp_capability_receive(struct peer *peer, bgp_size_t size) { - u_char *pnt; - - /* Fetch pointer. */ - pnt = stream_pnt (peer->ibuf); - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s rcv CAPABILITY", peer->host); - - /* If peer does not have the capability, send notification. */ - if (! CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV)) - { - zlog_err ("%s [Error] BGP dynamic capability is not enabled", - peer->host); - bgp_notify_send (peer, - BGP_NOTIFY_HEADER_ERR, - BGP_NOTIFY_HEADER_BAD_MESTYPE); - return -1; - } - - /* Status must be Established. */ - if (peer->status != Established) - { - zlog_err ("%s [Error] Dynamic capability packet received under status %s", - peer->host, lookup_msg(bgp_status_msg, peer->status, NULL)); - bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0); - return -1; - } - - /* Parse packet. */ - return bgp_capability_msg_parse (peer, pnt, size); + u_char *pnt; + + /* Fetch pointer. */ + pnt = stream_pnt(peer->ibuf); + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s rcv CAPABILITY", peer->host); + + /* If peer does not have the capability, send notification. */ + if (!CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV)) { + zlog_err("%s [Error] BGP dynamic capability is not enabled", + peer->host); + bgp_notify_send(peer, BGP_NOTIFY_HEADER_ERR, + BGP_NOTIFY_HEADER_BAD_MESTYPE); + return -1; + } + + /* Status must be Established. */ + if (peer->status != Established) { + zlog_err( + "%s [Error] Dynamic capability packet received under status %s", + peer->host, + lookup_msg(bgp_status_msg, peer->status, NULL)); + bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, 0); + return -1; + } + + /* Parse packet. */ + return bgp_capability_msg_parse(peer, pnt, size); } /* BGP read utility function. */ -static int -bgp_read_packet (struct peer *peer) +static int bgp_read_packet(struct peer *peer) { - int nbytes; - int readsize; + int nbytes; + int readsize; - readsize = peer->packet_size - stream_get_endp (peer->ibuf); + readsize = peer->packet_size - stream_get_endp(peer->ibuf); - /* If size is zero then return. */ - if (! readsize) - return 0; + /* If size is zero then return. */ + if (!readsize) + return 0; - /* Read packet from fd. */ - nbytes = stream_read_try (peer->ibuf, peer->fd, readsize); + /* Read packet from fd. */ + nbytes = stream_read_try(peer->ibuf, peer->fd, readsize); - /* If read byte is smaller than zero then error occured. */ - if (nbytes < 0) - { - /* Transient error should retry */ - if (nbytes == -2) - return -1; + /* If read byte is smaller than zero then error occured. */ + if (nbytes < 0) { + /* Transient error should retry */ + if (nbytes == -2) + return -1; - zlog_err ("%s [Error] bgp_read_packet error: %s", - peer->host, safe_strerror (errno)); + zlog_err("%s [Error] bgp_read_packet error: %s", peer->host, + safe_strerror(errno)); - if (peer->status == Established) - { - if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE)) - { - peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION; - SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT); - } - else - peer->last_reset = PEER_DOWN_CLOSE_SESSION; - } + if (peer->status == Established) { + if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE)) { + peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION; + SET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT); + } else + peer->last_reset = PEER_DOWN_CLOSE_SESSION; + } - BGP_EVENT_ADD (peer, TCP_fatal_error); - return -1; - } + BGP_EVENT_ADD(peer, TCP_fatal_error); + return -1; + } - /* When read byte is zero : clear bgp peer and return */ - if (nbytes == 0) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s [Event] BGP connection closed fd %d", - peer->host, peer->fd); + /* When read byte is zero : clear bgp peer and return */ + if (nbytes == 0) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s [Event] BGP connection closed fd %d", + peer->host, peer->fd); + + if (peer->status == Established) { + if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE)) { + peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION; + SET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT); + } else + peer->last_reset = PEER_DOWN_CLOSE_SESSION; + } - if (peer->status == Established) - { - if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE)) - { - peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION; - SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT); - } - else - peer->last_reset = PEER_DOWN_CLOSE_SESSION; + BGP_EVENT_ADD(peer, TCP_connection_closed); + return -1; } - BGP_EVENT_ADD (peer, TCP_connection_closed); - return -1; - } - - /* We read partial packet. */ - if (stream_get_endp (peer->ibuf) != peer->packet_size) - return -1; + /* We read partial packet. */ + if (stream_get_endp(peer->ibuf) != peer->packet_size) + return -1; - return 0; + return 0; } /* Marker check. */ -static int -bgp_marker_all_one (struct stream *s, int length) +static int bgp_marker_all_one(struct stream *s, int length) { - int i; + int i; - for (i = 0; i < length; i++) - if (s->data[i] != 0xff) - return 0; + for (i = 0; i < length; i++) + if (s->data[i] != 0xff) + return 0; - return 1; + return 1; } /* Starting point of packet process function. */ -int -bgp_read (struct thread *thread) +int bgp_read(struct thread *thread) { - int ret; - u_char type = 0; - struct peer *peer; - bgp_size_t size; - char notify_data_length[2]; - u_int32_t notify_out; - - /* Yes first of all get peer pointer. */ - peer = THREAD_ARG (thread); - peer->t_read = NULL; - - /* Note notify_out so we can check later to see if we sent another one */ - notify_out = peer->notify_out; - - /* For non-blocking IO check. */ - if (peer->status == Connect) - { - bgp_connect_check (peer, 1); - goto done; - } - else - { - if (peer->fd < 0) - { - zlog_err ("bgp_read peer's fd is negative value %d", peer->fd); - return -1; + int ret; + u_char type = 0; + struct peer *peer; + bgp_size_t size; + char notify_data_length[2]; + u_int32_t notify_out; + + /* Yes first of all get peer pointer. */ + peer = THREAD_ARG(thread); + peer->t_read = NULL; + + /* Note notify_out so we can check later to see if we sent another one + */ + notify_out = peer->notify_out; + + /* For non-blocking IO check. */ + if (peer->status == Connect) { + bgp_connect_check(peer, 1); + goto done; + } else { + if (peer->fd < 0) { + zlog_err("bgp_read peer's fd is negative value %d", + peer->fd); + return -1; + } + BGP_READ_ON(peer->t_read, bgp_read, peer->fd); } - BGP_READ_ON (peer->t_read, bgp_read, peer->fd); - } - - /* Read packet header to determine type of the packet */ - if (peer->packet_size == 0) - peer->packet_size = BGP_HEADER_SIZE; - - if (stream_get_endp (peer->ibuf) < BGP_HEADER_SIZE) - { - ret = bgp_read_packet (peer); - - /* Header read error or partial read packet. */ - if (ret < 0) - goto done; - - /* Get size and type. */ - stream_forward_getp (peer->ibuf, BGP_MARKER_SIZE); - memcpy (notify_data_length, stream_pnt (peer->ibuf), 2); - size = stream_getw (peer->ibuf); - type = stream_getc (peer->ibuf); - - /* Marker check */ - if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE)) - && ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE)) - { - bgp_notify_send (peer, - BGP_NOTIFY_HEADER_ERR, - BGP_NOTIFY_HEADER_NOT_SYNC); - goto done; + + /* Read packet header to determine type of the packet */ + if (peer->packet_size == 0) + peer->packet_size = BGP_HEADER_SIZE; + + if (stream_get_endp(peer->ibuf) < BGP_HEADER_SIZE) { + ret = bgp_read_packet(peer); + + /* Header read error or partial read packet. */ + if (ret < 0) + goto done; + + /* Get size and type. */ + stream_forward_getp(peer->ibuf, BGP_MARKER_SIZE); + memcpy(notify_data_length, stream_pnt(peer->ibuf), 2); + size = stream_getw(peer->ibuf); + type = stream_getc(peer->ibuf); + + /* Marker check */ + if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE)) + && !bgp_marker_all_one(peer->ibuf, BGP_MARKER_SIZE)) { + bgp_notify_send(peer, BGP_NOTIFY_HEADER_ERR, + BGP_NOTIFY_HEADER_NOT_SYNC); + goto done; + } + + /* BGP type check. */ + if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE + && type != BGP_MSG_NOTIFY && type != BGP_MSG_KEEPALIVE + && type != BGP_MSG_ROUTE_REFRESH_NEW + && type != BGP_MSG_ROUTE_REFRESH_OLD + && type != BGP_MSG_CAPABILITY) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s unknown message type 0x%02x", + peer->host, type); + bgp_notify_send_with_data(peer, BGP_NOTIFY_HEADER_ERR, + BGP_NOTIFY_HEADER_BAD_MESTYPE, + &type, 1); + goto done; + } + /* Mimimum packet length check. */ + if ((size < BGP_HEADER_SIZE) || (size > BGP_MAX_PACKET_SIZE) + || (type == BGP_MSG_OPEN && size < BGP_MSG_OPEN_MIN_SIZE) + || (type == BGP_MSG_UPDATE + && size < BGP_MSG_UPDATE_MIN_SIZE) + || (type == BGP_MSG_NOTIFY + && size < BGP_MSG_NOTIFY_MIN_SIZE) + || (type == BGP_MSG_KEEPALIVE + && size != BGP_MSG_KEEPALIVE_MIN_SIZE) + || (type == BGP_MSG_ROUTE_REFRESH_NEW + && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE) + || (type == BGP_MSG_ROUTE_REFRESH_OLD + && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE) + || (type == BGP_MSG_CAPABILITY + && size < BGP_MSG_CAPABILITY_MIN_SIZE)) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s bad message length - %d for %s", + peer->host, size, + type == 128 + ? "ROUTE-REFRESH" + : bgp_type_str[(int)type]); + bgp_notify_send_with_data(peer, BGP_NOTIFY_HEADER_ERR, + BGP_NOTIFY_HEADER_BAD_MESLEN, + (u_char *)notify_data_length, + 2); + goto done; + } + + /* Adjust size to message length. */ + peer->packet_size = size; } - /* BGP type check. */ - if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE - && type != BGP_MSG_NOTIFY && type != BGP_MSG_KEEPALIVE - && type != BGP_MSG_ROUTE_REFRESH_NEW - && type != BGP_MSG_ROUTE_REFRESH_OLD - && type != BGP_MSG_CAPABILITY) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s unknown message type 0x%02x", - peer->host, type); - bgp_notify_send_with_data (peer, - BGP_NOTIFY_HEADER_ERR, - BGP_NOTIFY_HEADER_BAD_MESTYPE, - &type, 1); - goto done; + ret = bgp_read_packet(peer); + if (ret < 0) + goto done; + + /* Get size and type again. */ + (void)stream_getw_from(peer->ibuf, BGP_MARKER_SIZE); + type = stream_getc_from(peer->ibuf, BGP_MARKER_SIZE + 2); + + /* BGP packet dump function. */ + bgp_dump_packet(peer, type, peer->ibuf); + + size = (peer->packet_size - BGP_HEADER_SIZE); + + /* Read rest of the packet and call each sort of packet routine */ + switch (type) { + case BGP_MSG_OPEN: + peer->open_in++; + bgp_open_receive(peer, size); /* XXX return value ignored! */ + break; + case BGP_MSG_UPDATE: + peer->readtime = monotime(NULL); + bgp_update_receive(peer, size); + break; + case BGP_MSG_NOTIFY: + bgp_notify_receive(peer, size); + break; + case BGP_MSG_KEEPALIVE: + peer->readtime = monotime(NULL); + bgp_keepalive_receive(peer, size); + break; + case BGP_MSG_ROUTE_REFRESH_NEW: + case BGP_MSG_ROUTE_REFRESH_OLD: + peer->refresh_in++; + bgp_route_refresh_receive(peer, size); + break; + case BGP_MSG_CAPABILITY: + peer->dynamic_cap_in++; + bgp_capability_receive(peer, size); + break; } - /* Mimimum packet length check. */ - if ((size < BGP_HEADER_SIZE) - || (size > BGP_MAX_PACKET_SIZE) - || (type == BGP_MSG_OPEN && size < BGP_MSG_OPEN_MIN_SIZE) - || (type == BGP_MSG_UPDATE && size < BGP_MSG_UPDATE_MIN_SIZE) - || (type == BGP_MSG_NOTIFY && size < BGP_MSG_NOTIFY_MIN_SIZE) - || (type == BGP_MSG_KEEPALIVE && size != BGP_MSG_KEEPALIVE_MIN_SIZE) - || (type == BGP_MSG_ROUTE_REFRESH_NEW && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE) - || (type == BGP_MSG_ROUTE_REFRESH_OLD && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE) - || (type == BGP_MSG_CAPABILITY && size < BGP_MSG_CAPABILITY_MIN_SIZE)) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s bad message length - %d for %s", - peer->host, size, - type == 128 ? "ROUTE-REFRESH" : - bgp_type_str[(int) type]); - bgp_notify_send_with_data (peer, - BGP_NOTIFY_HEADER_ERR, - BGP_NOTIFY_HEADER_BAD_MESLEN, - (u_char *) notify_data_length, 2); - goto done; + + /* If reading this packet caused us to send a NOTIFICATION then store a + * copy + * of the packet for troubleshooting purposes + */ + if (notify_out < peer->notify_out) { + memcpy(peer->last_reset_cause, peer->ibuf->data, + peer->packet_size); + peer->last_reset_cause_size = peer->packet_size; + notify_out = peer->notify_out; + } + + /* Clear input buffer. */ + peer->packet_size = 0; + if (peer->ibuf) + stream_reset(peer->ibuf); + +done: + /* If reading this packet caused us to send a NOTIFICATION then store a + * copy + * of the packet for troubleshooting purposes + */ + if (notify_out < peer->notify_out) { + memcpy(peer->last_reset_cause, peer->ibuf->data, + peer->packet_size); + peer->last_reset_cause_size = peer->packet_size; } - /* Adjust size to message length. */ - peer->packet_size = size; - } - - ret = bgp_read_packet (peer); - if (ret < 0) - goto done; - - /* Get size and type again. */ - (void)stream_getw_from (peer->ibuf, BGP_MARKER_SIZE); - type = stream_getc_from (peer->ibuf, BGP_MARKER_SIZE + 2); - - /* BGP packet dump function. */ - bgp_dump_packet (peer, type, peer->ibuf); - - size = (peer->packet_size - BGP_HEADER_SIZE); - - /* Read rest of the packet and call each sort of packet routine */ - switch (type) - { - case BGP_MSG_OPEN: - peer->open_in++; - bgp_open_receive (peer, size); /* XXX return value ignored! */ - break; - case BGP_MSG_UPDATE: - peer->readtime = monotime (NULL); - bgp_update_receive (peer, size); - break; - case BGP_MSG_NOTIFY: - bgp_notify_receive (peer, size); - break; - case BGP_MSG_KEEPALIVE: - peer->readtime = monotime (NULL); - bgp_keepalive_receive (peer, size); - break; - case BGP_MSG_ROUTE_REFRESH_NEW: - case BGP_MSG_ROUTE_REFRESH_OLD: - peer->refresh_in++; - bgp_route_refresh_receive (peer, size); - break; - case BGP_MSG_CAPABILITY: - peer->dynamic_cap_in++; - bgp_capability_receive (peer, size); - break; - } - - /* If reading this packet caused us to send a NOTIFICATION then store a copy - * of the packet for troubleshooting purposes - */ - if (notify_out < peer->notify_out) - { - memcpy(peer->last_reset_cause, peer->ibuf->data, peer->packet_size); - peer->last_reset_cause_size = peer->packet_size; - notify_out = peer->notify_out; - } - - /* Clear input buffer. */ - peer->packet_size = 0; - if (peer->ibuf) - stream_reset (peer->ibuf); - - done: - /* If reading this packet caused us to send a NOTIFICATION then store a copy - * of the packet for troubleshooting purposes - */ - if (notify_out < peer->notify_out) - { - memcpy(peer->last_reset_cause, peer->ibuf->data, peer->packet_size); - peer->last_reset_cause_size = peer->packet_size; - } - - return 0; + return 0; } diff --git a/bgpd/bgp_packet.h b/bgpd/bgp_packet.h index f7beaf494..7bf498c37 100644 --- a/bgpd/bgp_packet.h +++ b/bgpd/bgp_packet.h @@ -38,31 +38,33 @@ #define ORF_COMMON_PART_DENY 0x20 /* Packet send and receive function prototypes. */ -extern int bgp_read (struct thread *); -extern int bgp_write (struct thread *); -extern int bgp_connect_check (struct peer *, int change_state); +extern int bgp_read(struct thread *); +extern int bgp_write(struct thread *); +extern int bgp_connect_check(struct peer *, int change_state); -extern void bgp_keepalive_send (struct peer *); -extern void bgp_open_send (struct peer *); -extern void bgp_notify_send (struct peer *, u_int8_t, u_int8_t); -extern void bgp_notify_send_with_data (struct peer *, u_int8_t, u_int8_t, - u_int8_t *, size_t); -extern void bgp_route_refresh_send (struct peer *, afi_t, safi_t, u_char, u_char, int); -extern void bgp_capability_send (struct peer *, afi_t, safi_t, int, int); -extern void bgp_default_update_send (struct peer *, struct attr *, - afi_t, safi_t, struct peer *); -extern void bgp_default_withdraw_send (struct peer *, afi_t, safi_t); +extern void bgp_keepalive_send(struct peer *); +extern void bgp_open_send(struct peer *); +extern void bgp_notify_send(struct peer *, u_int8_t, u_int8_t); +extern void bgp_notify_send_with_data(struct peer *, u_int8_t, u_int8_t, + u_int8_t *, size_t); +extern void bgp_route_refresh_send(struct peer *, afi_t, safi_t, u_char, u_char, + int); +extern void bgp_capability_send(struct peer *, afi_t, safi_t, int, int); +extern void bgp_default_update_send(struct peer *, struct attr *, afi_t, safi_t, + struct peer *); +extern void bgp_default_withdraw_send(struct peer *, afi_t, safi_t); -extern int bgp_capability_receive (struct peer *, bgp_size_t); +extern int bgp_capability_receive(struct peer *, bgp_size_t); -extern int bgp_nlri_parse (struct peer *, struct attr *, struct bgp_nlri *, int mp_withdraw); +extern int bgp_nlri_parse(struct peer *, struct attr *, struct bgp_nlri *, + int mp_withdraw); -extern void bgp_update_restarted_peers (struct peer *); -extern void bgp_update_implicit_eors (struct peer *); -extern void bgp_check_update_delay (struct bgp *); +extern void bgp_update_restarted_peers(struct peer *); +extern void bgp_update_implicit_eors(struct peer *); +extern void bgp_check_update_delay(struct bgp *); -extern int bgp_packet_set_marker (struct stream *s, u_char type); -extern int bgp_packet_set_size (struct stream *s); -extern void bgp_packet_add (struct peer *peer, struct stream *s); +extern int bgp_packet_set_marker(struct stream *s, u_char type); +extern int bgp_packet_set_size(struct stream *s); +extern void bgp_packet_add(struct peer *peer, struct stream *s); #endif /* _QUAGGA_BGP_PACKET_H */ diff --git a/bgpd/bgp_rd.c b/bgpd/bgp_rd.c index 03257a292..fd0169394 100644 --- a/bgpd/bgp_rd.c +++ b/bgpd/bgp_rd.c @@ -36,197 +36,174 @@ #include "bgpd/rfapi/rfapi_backend.h" #endif -u_int16_t -decode_rd_type (u_char *pnt) +u_int16_t decode_rd_type(u_char *pnt) { - u_int16_t v; + u_int16_t v; - v = ((u_int16_t) *pnt++ << 8); + v = ((u_int16_t)*pnt++ << 8); #if ENABLE_BGP_VNC - /* - * VNC L2 stores LHI in lower byte, so omit it - */ - if (v != RD_TYPE_VNC_ETH) - v |= (u_int16_t) *pnt; -#else /* duplicate code for clarity */ - v |= (u_int16_t) *pnt; + /* + * VNC L2 stores LHI in lower byte, so omit it + */ + if (v != RD_TYPE_VNC_ETH) + v |= (u_int16_t)*pnt; +#else /* duplicate code for clarity */ + v |= (u_int16_t)*pnt; #endif - return v; + return v; } -void -encode_rd_type (u_int16_t v, u_char *pnt) +void encode_rd_type(u_int16_t v, u_char *pnt) { - *((u_int16_t *)pnt) = htons(v); + *((u_int16_t *)pnt) = htons(v); } /* type == RD_TYPE_AS */ -void -decode_rd_as (u_char *pnt, struct rd_as *rd_as) +void decode_rd_as(u_char *pnt, struct rd_as *rd_as) { - rd_as->as = (u_int16_t) *pnt++ << 8; - rd_as->as |= (u_int16_t) *pnt++; + rd_as->as = (u_int16_t)*pnt++ << 8; + rd_as->as |= (u_int16_t)*pnt++; - rd_as->val = ((u_int32_t) *pnt++ << 24); - rd_as->val |= ((u_int32_t) *pnt++ << 16); - rd_as->val |= ((u_int32_t) *pnt++ << 8); - rd_as->val |= (u_int32_t) *pnt; + rd_as->val = ((u_int32_t)*pnt++ << 24); + rd_as->val |= ((u_int32_t)*pnt++ << 16); + rd_as->val |= ((u_int32_t)*pnt++ << 8); + rd_as->val |= (u_int32_t)*pnt; } /* type == RD_TYPE_AS4 */ -void -decode_rd_as4 (u_char *pnt, struct rd_as *rd_as) +void decode_rd_as4(u_char *pnt, struct rd_as *rd_as) { - rd_as->as = (u_int32_t) *pnt++ << 24; - rd_as->as |= (u_int32_t) *pnt++ << 16; - rd_as->as |= (u_int32_t) *pnt++ << 8; - rd_as->as |= (u_int32_t) *pnt++; + rd_as->as = (u_int32_t)*pnt++ << 24; + rd_as->as |= (u_int32_t)*pnt++ << 16; + rd_as->as |= (u_int32_t)*pnt++ << 8; + rd_as->as |= (u_int32_t)*pnt++; - rd_as->val = ((u_int16_t) *pnt++ << 8); - rd_as->val |= (u_int16_t) *pnt; + rd_as->val = ((u_int16_t)*pnt++ << 8); + rd_as->val |= (u_int16_t)*pnt; } /* type == RD_TYPE_IP */ -void -decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip) +void decode_rd_ip(u_char *pnt, struct rd_ip *rd_ip) { - memcpy (&rd_ip->ip, pnt, 4); - pnt += 4; + memcpy(&rd_ip->ip, pnt, 4); + pnt += 4; - rd_ip->val = ((u_int16_t) *pnt++ << 8); - rd_ip->val |= (u_int16_t) *pnt; + rd_ip->val = ((u_int16_t)*pnt++ << 8); + rd_ip->val |= (u_int16_t)*pnt; } #if ENABLE_BGP_VNC /* type == RD_TYPE_VNC_ETH */ -void -decode_rd_vnc_eth (u_char *pnt, struct rd_vnc_eth *rd_vnc_eth) +void decode_rd_vnc_eth(u_char *pnt, struct rd_vnc_eth *rd_vnc_eth) { - rd_vnc_eth->type = RD_TYPE_VNC_ETH; - rd_vnc_eth->local_nve_id = pnt[1]; - memcpy (rd_vnc_eth->macaddr.octet, pnt + 2, ETHER_ADDR_LEN); + rd_vnc_eth->type = RD_TYPE_VNC_ETH; + rd_vnc_eth->local_nve_id = pnt[1]; + memcpy(rd_vnc_eth->macaddr.octet, pnt + 2, ETHER_ADDR_LEN); } #endif -int -str2prefix_rd (const char *str, struct prefix_rd *prd) +int str2prefix_rd(const char *str, struct prefix_rd *prd) { - int ret; /* ret of called functions */ - int lret; /* local ret, of this func */ - char *p; - char *p2; - struct stream *s = NULL; - char *half = NULL; - struct in_addr addr; - - s = stream_new (8); - - prd->family = AF_UNSPEC; - prd->prefixlen = 64; - - lret = 0; - p = strchr (str, ':'); - if (! p) - goto out; - - if (! all_digit (p + 1)) - goto out; - - half = XMALLOC (MTYPE_TMP, (p - str) + 1); - memcpy (half, str, (p - str)); - half[p - str] = '\0'; - - p2 = strchr (str, '.'); - - if (! p2) - { - unsigned long as_val; - - if (! all_digit (half)) - goto out; - - as_val = atol(half); - if (as_val > 0xffff) - { - stream_putw (s, RD_TYPE_AS4); - stream_putl (s, as_val); - stream_putw (s, atol (p + 1)); - } - else - { - stream_putw (s, RD_TYPE_AS); - stream_putw (s, as_val); - stream_putl (s, atol (p + 1)); - } - } - else - { - ret = inet_aton (half, &addr); - if (! ret) - goto out; - - stream_putw (s, RD_TYPE_IP); - stream_put_in_addr (s, &addr); - stream_putw (s, atol (p + 1)); - } - memcpy (prd->val, s->data, 8); - lret = 1; + int ret; /* ret of called functions */ + int lret; /* local ret, of this func */ + char *p; + char *p2; + struct stream *s = NULL; + char *half = NULL; + struct in_addr addr; + + s = stream_new(8); + + prd->family = AF_UNSPEC; + prd->prefixlen = 64; + + lret = 0; + p = strchr(str, ':'); + if (!p) + goto out; + + if (!all_digit(p + 1)) + goto out; + + half = XMALLOC(MTYPE_TMP, (p - str) + 1); + memcpy(half, str, (p - str)); + half[p - str] = '\0'; + + p2 = strchr(str, '.'); + + if (!p2) { + unsigned long as_val; + + if (!all_digit(half)) + goto out; + + as_val = atol(half); + if (as_val > 0xffff) { + stream_putw(s, RD_TYPE_AS4); + stream_putl(s, as_val); + stream_putw(s, atol(p + 1)); + } else { + stream_putw(s, RD_TYPE_AS); + stream_putw(s, as_val); + stream_putl(s, atol(p + 1)); + } + } else { + ret = inet_aton(half, &addr); + if (!ret) + goto out; + + stream_putw(s, RD_TYPE_IP); + stream_put_in_addr(s, &addr); + stream_putw(s, atol(p + 1)); + } + memcpy(prd->val, s->data, 8); + lret = 1; out: - if (s) - stream_free (s); - if (half) - XFREE(MTYPE_TMP, half); - return lret; + if (s) + stream_free(s); + if (half) + XFREE(MTYPE_TMP, half); + return lret; } -char * -prefix_rd2str (struct prefix_rd *prd, char *buf, size_t size) +char *prefix_rd2str(struct prefix_rd *prd, char *buf, size_t size) { - u_char *pnt; - u_int16_t type; - struct rd_as rd_as; - struct rd_ip rd_ip; - - if (size < RD_ADDRSTRLEN) - return NULL; - - pnt = prd->val; - - type = decode_rd_type (pnt); - - if (type == RD_TYPE_AS) - { - decode_rd_as (pnt + 2, &rd_as); - snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val); - return buf; - } - else if (type == RD_TYPE_AS4) - { - decode_rd_as4 (pnt + 2, &rd_as); - snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val); - return buf; - } - else if (type == RD_TYPE_IP) - { - decode_rd_ip (pnt + 2, &rd_ip); - snprintf (buf, size, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val); - return buf; - } + u_char *pnt; + u_int16_t type; + struct rd_as rd_as; + struct rd_ip rd_ip; + + if (size < RD_ADDRSTRLEN) + return NULL; + + pnt = prd->val; + + type = decode_rd_type(pnt); + + if (type == RD_TYPE_AS) { + decode_rd_as(pnt + 2, &rd_as); + snprintf(buf, size, "%u:%d", rd_as.as, rd_as.val); + return buf; + } else if (type == RD_TYPE_AS4) { + decode_rd_as4(pnt + 2, &rd_as); + snprintf(buf, size, "%u:%d", rd_as.as, rd_as.val); + return buf; + } else if (type == RD_TYPE_IP) { + decode_rd_ip(pnt + 2, &rd_ip); + snprintf(buf, size, "%s:%d", inet_ntoa(rd_ip.ip), rd_ip.val); + return buf; + } #if ENABLE_BGP_VNC - else if (type == RD_TYPE_VNC_ETH) - { - snprintf(buf, size, "LHI:%d, %02x:%02x:%02x:%02x:%02x:%02x", - *(pnt+1), /* LHI */ - *(pnt+2), /* MAC[0] */ - *(pnt+3), - *(pnt+4), - *(pnt+5), - *(pnt+6), - *(pnt+7)); - - return buf; - } + else if (type == RD_TYPE_VNC_ETH) { + snprintf(buf, size, "LHI:%d, %02x:%02x:%02x:%02x:%02x:%02x", + *(pnt + 1), /* LHI */ + *(pnt + 2), /* MAC[0] */ + *(pnt + 3), *(pnt + 4), *(pnt + 5), *(pnt + 6), + *(pnt + 7)); + + return buf; + } #endif - return NULL; + return NULL; } diff --git a/bgpd/bgp_rd.h b/bgpd/bgp_rd.h index 2c7df9d74..cbc449ed4 100644 --- a/bgpd/bgp_rd.h +++ b/bgpd/bgp_rd.h @@ -34,41 +34,37 @@ #define RD_ADDRSTRLEN 28 -struct rd_as -{ - u_int16_t type; - as_t as; - u_int32_t val; +struct rd_as { + u_int16_t type; + as_t as; + u_int32_t val; }; -struct rd_ip -{ - u_int16_t type; - struct in_addr ip; - u_int16_t val; +struct rd_ip { + u_int16_t type; + struct in_addr ip; + u_int16_t val; }; #if ENABLE_BGP_VNC -struct rd_vnc_eth -{ - u_int16_t type; - uint8_t local_nve_id; - struct ethaddr macaddr; +struct rd_vnc_eth { + u_int16_t type; + uint8_t local_nve_id; + struct ethaddr macaddr; }; #endif -extern u_int16_t decode_rd_type (u_char *pnt); -extern void encode_rd_type (u_int16_t, u_char *); +extern u_int16_t decode_rd_type(u_char *pnt); +extern void encode_rd_type(u_int16_t, u_char *); -extern void decode_rd_as (u_char *pnt, struct rd_as *rd_as); -extern void decode_rd_as4 (u_char *pnt, struct rd_as *rd_as); -extern void decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip); +extern void decode_rd_as(u_char *pnt, struct rd_as *rd_as); +extern void decode_rd_as4(u_char *pnt, struct rd_as *rd_as); +extern void decode_rd_ip(u_char *pnt, struct rd_ip *rd_ip); #if ENABLE_BGP_VNC -extern void -decode_rd_vnc_eth (u_char *pnt, struct rd_vnc_eth *rd_vnc_eth); +extern void decode_rd_vnc_eth(u_char *pnt, struct rd_vnc_eth *rd_vnc_eth); #endif -extern int str2prefix_rd (const char *, struct prefix_rd *); -extern char *prefix_rd2str (struct prefix_rd *, char *, size_t); +extern int str2prefix_rd(const char *, struct prefix_rd *); +extern char *prefix_rd2str(struct prefix_rd *, char *, size_t); #endif /* _QUAGGA_BGP_RD_H */ diff --git a/bgpd/bgp_regex.c b/bgpd/bgp_regex.c index 3674a9b6d..606568402 100644 --- a/bgpd/bgp_regex.c +++ b/bgpd/bgp_regex.c @@ -31,65 +31,59 @@ #include "bgp_regex.h" /* Character `_' has special mean. It represents [,{}() ] and the - beginning of the line(^) and the end of the line ($). + beginning of the line(^) and the end of the line ($). (^|[,{}() ]|$) */ -regex_t * -bgp_regcomp (const char *regstr) +regex_t *bgp_regcomp(const char *regstr) { - /* Convert _ character to generic regular expression. */ - int i, j; - int len; - int magic = 0; - char *magic_str; - char magic_regexp[] = "(^|[,{}() ]|$)"; - int ret; - regex_t *regex; - - len = strlen (regstr); - for (i = 0; i < len; i++) - if (regstr[i] == '_') - magic++; - - magic_str = XMALLOC (MTYPE_TMP, len + (14 * magic) + 1); - - for (i = 0, j = 0; i < len; i++) - { - if (regstr[i] == '_') - { - memcpy (magic_str + j, magic_regexp, strlen (magic_regexp)); - j += strlen (magic_regexp); + /* Convert _ character to generic regular expression. */ + int i, j; + int len; + int magic = 0; + char *magic_str; + char magic_regexp[] = "(^|[,{}() ]|$)"; + int ret; + regex_t *regex; + + len = strlen(regstr); + for (i = 0; i < len; i++) + if (regstr[i] == '_') + magic++; + + magic_str = XMALLOC(MTYPE_TMP, len + (14 * magic) + 1); + + for (i = 0, j = 0; i < len; i++) { + if (regstr[i] == '_') { + memcpy(magic_str + j, magic_regexp, + strlen(magic_regexp)); + j += strlen(magic_regexp); + } else + magic_str[j++] = regstr[i]; } - else - magic_str[j++] = regstr[i]; - } - magic_str[j] = '\0'; + magic_str[j] = '\0'; - regex = XMALLOC (MTYPE_BGP_REGEXP, sizeof (regex_t)); + regex = XMALLOC(MTYPE_BGP_REGEXP, sizeof(regex_t)); - ret = regcomp (regex, magic_str, REG_EXTENDED|REG_NOSUB); + ret = regcomp(regex, magic_str, REG_EXTENDED | REG_NOSUB); - XFREE (MTYPE_TMP, magic_str); + XFREE(MTYPE_TMP, magic_str); - if (ret != 0) - { - XFREE (MTYPE_BGP_REGEXP, regex); - return NULL; - } + if (ret != 0) { + XFREE(MTYPE_BGP_REGEXP, regex); + return NULL; + } - return regex; + return regex; } -int -bgp_regexec (regex_t *regex, struct aspath *aspath) +int bgp_regexec(regex_t *regex, struct aspath *aspath) { - return regexec (regex, aspath->str, 0, NULL, 0); + return regexec(regex, aspath->str, 0, NULL, 0); } -void -bgp_regex_free (regex_t *regex) +void bgp_regex_free(regex_t *regex) { - regfree (regex); - XFREE (MTYPE_BGP_REGEXP, regex); + regfree(regex); + XFREE(MTYPE_BGP_REGEXP, regex); } diff --git a/bgpd/bgp_regex.h b/bgpd/bgp_regex.h index 68bff001c..43ebb9ac9 100644 --- a/bgpd/bgp_regex.h +++ b/bgpd/bgp_regex.h @@ -24,13 +24,13 @@ #include #ifdef HAVE_LIBPCREPOSIX -# include +#include #else -# include +#include #endif /* HAVE_LIBPCREPOSIX */ -extern void bgp_regex_free (regex_t *regex); -extern regex_t *bgp_regcomp (const char *str); -extern int bgp_regexec (regex_t *regex, struct aspath *aspath); +extern void bgp_regex_free(regex_t *regex); +extern regex_t *bgp_regcomp(const char *str); +extern int bgp_regexec(regex_t *regex, struct aspath *aspath); #endif /* _QUAGGA_BGP_REGEX_H */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index b535a4ea7..38ad7a6e0 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -78,150 +78,139 @@ extern const char *bgp_origin_str[]; extern const char *bgp_origin_long_str[]; -struct bgp_node * -bgp_afi_node_get (struct bgp_table *table, afi_t afi, safi_t safi, struct prefix *p, - struct prefix_rd *prd) -{ - struct bgp_node *rn; - struct bgp_node *prn = NULL; - - assert (table); - if (!table) - return NULL; - - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || - (safi == SAFI_EVPN)) - { - prn = bgp_node_get (table, (struct prefix *) prd); - - if (prn->info == NULL) - prn->info = bgp_table_init (afi, safi); - else - bgp_unlock_node (prn); - table = prn->info; - } +struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi, + safi_t safi, struct prefix *p, + struct prefix_rd *prd) +{ + struct bgp_node *rn; + struct bgp_node *prn = NULL; + + assert(table); + if (!table) + return NULL; + + if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) + || (safi == SAFI_EVPN)) { + prn = bgp_node_get(table, (struct prefix *)prd); + + if (prn->info == NULL) + prn->info = bgp_table_init(afi, safi); + else + bgp_unlock_node(prn); + table = prn->info; + } - rn = bgp_node_get (table, p); + rn = bgp_node_get(table, p); - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || - (safi == SAFI_EVPN)) - rn->prn = prn; + if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) + || (safi == SAFI_EVPN)) + rn->prn = prn; - return rn; + return rn; } -struct bgp_node * -bgp_afi_node_lookup (struct bgp_table *table, afi_t afi, safi_t safi, struct prefix *p, - struct prefix_rd *prd) +struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi, + safi_t safi, struct prefix *p, + struct prefix_rd *prd) { - struct bgp_node *rn; - struct bgp_node *prn = NULL; + struct bgp_node *rn; + struct bgp_node *prn = NULL; - if (!table) - return NULL; + if (!table) + return NULL; - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN)) - { - prn = bgp_node_lookup (table, (struct prefix *) prd); - if (!prn) - return NULL; + if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) + || (safi == SAFI_EVPN)) { + prn = bgp_node_lookup(table, (struct prefix *)prd); + if (!prn) + return NULL; - if (prn->info == NULL) - { - bgp_unlock_node (prn); - return NULL; - } + if (prn->info == NULL) { + bgp_unlock_node(prn); + return NULL; + } - table = prn->info; - } + table = prn->info; + } - rn = bgp_node_lookup (table, p); + rn = bgp_node_lookup(table, p); - return rn; + return rn; } /* Allocate bgp_info_extra */ -static struct bgp_info_extra * -bgp_info_extra_new (void) +static struct bgp_info_extra *bgp_info_extra_new(void) { - struct bgp_info_extra *new; - new = XCALLOC (MTYPE_BGP_ROUTE_EXTRA, sizeof (struct bgp_info_extra)); - new->label = MPLS_INVALID_LABEL; - return new; + struct bgp_info_extra *new; + new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA, sizeof(struct bgp_info_extra)); + new->label = MPLS_INVALID_LABEL; + return new; } -static void -bgp_info_extra_free (struct bgp_info_extra **extra) +static void bgp_info_extra_free(struct bgp_info_extra **extra) { - if (extra && *extra) - { - if ((*extra)->damp_info) - bgp_damp_info_free ((*extra)->damp_info, 0); - - (*extra)->damp_info = NULL; - - XFREE (MTYPE_BGP_ROUTE_EXTRA, *extra); - - *extra = NULL; - } + if (extra && *extra) { + if ((*extra)->damp_info) + bgp_damp_info_free((*extra)->damp_info, 0); + + (*extra)->damp_info = NULL; + + XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra); + + *extra = NULL; + } } /* Get bgp_info extra information for the given bgp_info, lazy allocated * if required. */ -struct bgp_info_extra * -bgp_info_extra_get (struct bgp_info *ri) +struct bgp_info_extra *bgp_info_extra_get(struct bgp_info *ri) { - if (!ri->extra) - ri->extra = bgp_info_extra_new(); - return ri->extra; + if (!ri->extra) + ri->extra = bgp_info_extra_new(); + return ri->extra; } /* Allocate new bgp info structure. */ -struct bgp_info * -bgp_info_new (void) +struct bgp_info *bgp_info_new(void) { - return XCALLOC (MTYPE_BGP_ROUTE, sizeof (struct bgp_info)); + return XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_info)); } /* Free bgp route information. */ -static void -bgp_info_free (struct bgp_info *binfo) +static void bgp_info_free(struct bgp_info *binfo) { - if (binfo->attr) - bgp_attr_unintern (&binfo->attr); + if (binfo->attr) + bgp_attr_unintern(&binfo->attr); - bgp_unlink_nexthop(binfo); - bgp_info_extra_free (&binfo->extra); - bgp_info_mpath_free (&binfo->mpath); + bgp_unlink_nexthop(binfo); + bgp_info_extra_free(&binfo->extra); + bgp_info_mpath_free(&binfo->mpath); - peer_unlock (binfo->peer); /* bgp_info peer reference */ + peer_unlock(binfo->peer); /* bgp_info peer reference */ - XFREE (MTYPE_BGP_ROUTE, binfo); + XFREE(MTYPE_BGP_ROUTE, binfo); } -struct bgp_info * -bgp_info_lock (struct bgp_info *binfo) +struct bgp_info *bgp_info_lock(struct bgp_info *binfo) { - binfo->lock++; - return binfo; + binfo->lock++; + return binfo; } -struct bgp_info * -bgp_info_unlock (struct bgp_info *binfo) +struct bgp_info *bgp_info_unlock(struct bgp_info *binfo) { - assert (binfo && binfo->lock > 0); - binfo->lock--; - - if (binfo->lock == 0) - { + assert(binfo && binfo->lock > 0); + binfo->lock--; + + if (binfo->lock == 0) { #if 0 zlog_debug ("%s: unlocked and freeing", __func__); zlog_backtrace (LOG_DEBUG); #endif - bgp_info_free (binfo); - return NULL; - } + bgp_info_free(binfo); + return NULL; + } #if 0 if (binfo->lock == 1) @@ -230,1717 +219,1742 @@ bgp_info_unlock (struct bgp_info *binfo) zlog_backtrace (LOG_DEBUG); } #endif - - return binfo; + + return binfo; } -void -bgp_info_add (struct bgp_node *rn, struct bgp_info *ri) +void bgp_info_add(struct bgp_node *rn, struct bgp_info *ri) { - struct bgp_info *top; + struct bgp_info *top; - top = rn->info; - - ri->next = rn->info; - ri->prev = NULL; - if (top) - top->prev = ri; - rn->info = ri; - - bgp_info_lock (ri); - bgp_lock_node (rn); - peer_lock (ri->peer); /* bgp_info peer reference */ + top = rn->info; + + ri->next = rn->info; + ri->prev = NULL; + if (top) + top->prev = ri; + rn->info = ri; + + bgp_info_lock(ri); + bgp_lock_node(rn); + peer_lock(ri->peer); /* bgp_info peer reference */ } -/* Do the actual removal of info from RIB, for use by bgp_process +/* Do the actual removal of info from RIB, for use by bgp_process completion callback *only* */ -void -bgp_info_reap (struct bgp_node *rn, struct bgp_info *ri) +void bgp_info_reap(struct bgp_node *rn, struct bgp_info *ri) { - if (ri->next) - ri->next->prev = ri->prev; - if (ri->prev) - ri->prev->next = ri->next; - else - rn->info = ri->next; - - bgp_info_mpath_dequeue (ri); - bgp_info_unlock (ri); - bgp_unlock_node (rn); + if (ri->next) + ri->next->prev = ri->prev; + if (ri->prev) + ri->prev->next = ri->next; + else + rn->info = ri->next; + + bgp_info_mpath_dequeue(ri); + bgp_info_unlock(ri); + bgp_unlock_node(rn); } -void -bgp_info_delete (struct bgp_node *rn, struct bgp_info *ri) +void bgp_info_delete(struct bgp_node *rn, struct bgp_info *ri) { - bgp_info_set_flag (rn, ri, BGP_INFO_REMOVED); - /* set of previous already took care of pcount */ - UNSET_FLAG (ri->flags, BGP_INFO_VALID); + bgp_info_set_flag(rn, ri, BGP_INFO_REMOVED); + /* set of previous already took care of pcount */ + UNSET_FLAG(ri->flags, BGP_INFO_VALID); } /* undo the effects of a previous call to bgp_info_delete; typically called when a route is deleted and then quickly re-added before the deletion has been processed */ -void -bgp_info_restore (struct bgp_node *rn, struct bgp_info *ri) +void bgp_info_restore(struct bgp_node *rn, struct bgp_info *ri) { - bgp_info_unset_flag (rn, ri, BGP_INFO_REMOVED); - /* unset of previous already took care of pcount */ - SET_FLAG (ri->flags, BGP_INFO_VALID); + bgp_info_unset_flag(rn, ri, BGP_INFO_REMOVED); + /* unset of previous already took care of pcount */ + SET_FLAG(ri->flags, BGP_INFO_VALID); } -/* Adjust pcount as required */ -static void -bgp_pcount_adjust (struct bgp_node *rn, struct bgp_info *ri) +/* Adjust pcount as required */ +static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_info *ri) { - struct bgp_table *table; + struct bgp_table *table; - assert (rn && bgp_node_table (rn)); - assert (ri && ri->peer && ri->peer->bgp); + assert(rn && bgp_node_table(rn)); + assert(ri && ri->peer && ri->peer->bgp); - table = bgp_node_table (rn); + table = bgp_node_table(rn); - if (ri->peer == ri->peer->bgp->peer_self) - return; - - if (!BGP_INFO_COUNTABLE (ri) - && CHECK_FLAG (ri->flags, BGP_INFO_COUNTED)) - { - - UNSET_FLAG (ri->flags, BGP_INFO_COUNTED); - - /* slight hack, but more robust against errors. */ - if (ri->peer->pcount[table->afi][table->safi]) - ri->peer->pcount[table->afi][table->safi]--; - else - { - zlog_warn ("%s: Asked to decrement 0 prefix count for peer %s", - __func__, ri->peer->host); - zlog_backtrace (LOG_WARNING); - zlog_warn ("%s: Please report to Quagga bugzilla", __func__); - } - } - else if (BGP_INFO_COUNTABLE (ri) - && !CHECK_FLAG (ri->flags, BGP_INFO_COUNTED)) - { - SET_FLAG (ri->flags, BGP_INFO_COUNTED); - ri->peer->pcount[table->afi][table->safi]++; - } + if (ri->peer == ri->peer->bgp->peer_self) + return; + + if (!BGP_INFO_COUNTABLE(ri) + && CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) { + + UNSET_FLAG(ri->flags, BGP_INFO_COUNTED); + + /* slight hack, but more robust against errors. */ + if (ri->peer->pcount[table->afi][table->safi]) + ri->peer->pcount[table->afi][table->safi]--; + else { + zlog_warn( + "%s: Asked to decrement 0 prefix count for peer %s", + __func__, ri->peer->host); + zlog_backtrace(LOG_WARNING); + zlog_warn("%s: Please report to Quagga bugzilla", + __func__); + } + } else if (BGP_INFO_COUNTABLE(ri) + && !CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) { + SET_FLAG(ri->flags, BGP_INFO_COUNTED); + ri->peer->pcount[table->afi][table->safi]++; + } } -static int -bgp_label_index_differs (struct bgp_info *ri1, struct bgp_info *ri2) +static int bgp_label_index_differs(struct bgp_info *ri1, struct bgp_info *ri2) { - return (!(ri1->attr->label_index == ri2->attr->label_index)); + return (!(ri1->attr->label_index == ri2->attr->label_index)); } /* Set/unset bgp_info flags, adjusting any other state as needed. * This is here primarily to keep prefix-count in check. */ -void -bgp_info_set_flag (struct bgp_node *rn, struct bgp_info *ri, u_int32_t flag) +void bgp_info_set_flag(struct bgp_node *rn, struct bgp_info *ri, u_int32_t flag) { - SET_FLAG (ri->flags, flag); - - /* early bath if we know it's not a flag that changes countability state */ - if (!CHECK_FLAG (flag, BGP_INFO_VALID|BGP_INFO_HISTORY|BGP_INFO_REMOVED)) - return; - - bgp_pcount_adjust (rn, ri); + SET_FLAG(ri->flags, flag); + + /* early bath if we know it's not a flag that changes countability state + */ + if (!CHECK_FLAG(flag, + BGP_INFO_VALID | BGP_INFO_HISTORY | BGP_INFO_REMOVED)) + return; + + bgp_pcount_adjust(rn, ri); } -void -bgp_info_unset_flag (struct bgp_node *rn, struct bgp_info *ri, u_int32_t flag) +void bgp_info_unset_flag(struct bgp_node *rn, struct bgp_info *ri, + u_int32_t flag) { - UNSET_FLAG (ri->flags, flag); - - /* early bath if we know it's not a flag that changes countability state */ - if (!CHECK_FLAG (flag, BGP_INFO_VALID|BGP_INFO_HISTORY|BGP_INFO_REMOVED)) - return; - - bgp_pcount_adjust (rn, ri); + UNSET_FLAG(ri->flags, flag); + + /* early bath if we know it's not a flag that changes countability state + */ + if (!CHECK_FLAG(flag, + BGP_INFO_VALID | BGP_INFO_HISTORY | BGP_INFO_REMOVED)) + return; + + bgp_pcount_adjust(rn, ri); } /* Get MED value. If MED value is missing and "bgp bestpath missing-as-worst" is specified, treat it as the worst value. */ -static u_int32_t -bgp_med_value (struct attr *attr, struct bgp *bgp) -{ - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) - return attr->med; - else - { - if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST)) - return BGP_MED_MAX; - else - return 0; - } +static u_int32_t bgp_med_value(struct attr *attr, struct bgp *bgp) +{ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) + return attr->med; + else { + if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST)) + return BGP_MED_MAX; + else + return 0; + } } -void -bgp_info_path_with_addpath_rx_str (struct bgp_info *ri, char *buf) +void bgp_info_path_with_addpath_rx_str(struct bgp_info *ri, char *buf) { - if (ri->addpath_rx_id) - sprintf(buf, "path %s (addpath rxid %d)", ri->peer->host, ri->addpath_rx_id); - else - sprintf(buf, "path %s", ri->peer->host); -} - -/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1. */ -static int -bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist, - int *paths_eq, struct bgp_maxpaths_cfg *mpath_cfg, int debug, - char *pfx_buf, afi_t afi, safi_t safi) -{ - struct attr *newattr, *existattr; - bgp_peer_sort_t new_sort; - bgp_peer_sort_t exist_sort; - u_int32_t new_pref; - u_int32_t exist_pref; - u_int32_t new_med; - u_int32_t exist_med; - u_int32_t new_weight; - u_int32_t exist_weight; - uint32_t newm, existm; - struct in_addr new_id; - struct in_addr exist_id; - int new_cluster; - int exist_cluster; - int internal_as_route; - int confed_as_route; - int ret; - char new_buf[PATH_ADDPATH_STR_BUFFER]; - char exist_buf[PATH_ADDPATH_STR_BUFFER]; - u_int32_t new_mm_seq; - u_int32_t exist_mm_seq; - - *paths_eq = 0; - - /* 0. Null check. */ - if (new == NULL) - { - if (debug) - zlog_debug("%s: new is NULL", pfx_buf); - return 0; - } + if (ri->addpath_rx_id) + sprintf(buf, "path %s (addpath rxid %d)", ri->peer->host, + ri->addpath_rx_id); + else + sprintf(buf, "path %s", ri->peer->host); +} - if (debug) - bgp_info_path_with_addpath_rx_str (new, new_buf); +/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1. + */ +static int bgp_info_cmp(struct bgp *bgp, struct bgp_info *new, + struct bgp_info *exist, int *paths_eq, + struct bgp_maxpaths_cfg *mpath_cfg, int debug, + char *pfx_buf, afi_t afi, safi_t safi) +{ + struct attr *newattr, *existattr; + bgp_peer_sort_t new_sort; + bgp_peer_sort_t exist_sort; + u_int32_t new_pref; + u_int32_t exist_pref; + u_int32_t new_med; + u_int32_t exist_med; + u_int32_t new_weight; + u_int32_t exist_weight; + uint32_t newm, existm; + struct in_addr new_id; + struct in_addr exist_id; + int new_cluster; + int exist_cluster; + int internal_as_route; + int confed_as_route; + int ret; + char new_buf[PATH_ADDPATH_STR_BUFFER]; + char exist_buf[PATH_ADDPATH_STR_BUFFER]; + u_int32_t new_mm_seq; + u_int32_t exist_mm_seq; + + *paths_eq = 0; + + /* 0. Null check. */ + if (new == NULL) { + if (debug) + zlog_debug("%s: new is NULL", pfx_buf); + return 0; + } - if (exist == NULL) - { - if (debug) - zlog_debug("%s: %s is the initial bestpath", pfx_buf, new_buf); - return 1; - } + if (debug) + bgp_info_path_with_addpath_rx_str(new, new_buf); - if (debug) - { - bgp_info_path_with_addpath_rx_str (exist, exist_buf); - zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x", - pfx_buf, new_buf, new->flags, exist_buf, exist->flags); - } + if (exist == NULL) { + if (debug) + zlog_debug("%s: %s is the initial bestpath", pfx_buf, + new_buf); + return 1; + } - newattr = new->attr; - existattr = exist->attr; + if (debug) { + bgp_info_path_with_addpath_rx_str(exist, exist_buf); + zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x", + pfx_buf, new_buf, new->flags, exist_buf, + exist->flags); + } - /* For EVPN routes, we cannot just go by local vs remote, we have to - * look at the MAC mobility sequence number, if present. - */ - if (safi == SAFI_EVPN) - { - /* This is an error condition described in RFC 7432 Section 15.2. The RFC - * states that in this scenario "the PE MUST alert the operator" but it - * does not state what other action to take. In order to provide some - * consistency in this scenario we are going to prefer the path with the - * sticky flag. - */ - if (newattr->sticky != existattr->sticky) - { - if (!debug) - { - prefix2str (&new->net->p, pfx_buf, sizeof (*pfx_buf) * PREFIX2STR_BUFFER); - bgp_info_path_with_addpath_rx_str (new, new_buf); - bgp_info_path_with_addpath_rx_str (exist, exist_buf); - } - - if (newattr->sticky && !existattr->sticky) - { - zlog_warn("%s: %s wins over %s due to sticky MAC flag", - pfx_buf, new_buf, exist_buf); - return 1; - } - - if (!newattr->sticky && existattr->sticky) - { - zlog_warn("%s: %s loses to %s due to sticky MAC flag", - pfx_buf, new_buf, exist_buf); - return 0; - } - } - - new_mm_seq = mac_mobility_seqnum (newattr); - exist_mm_seq = mac_mobility_seqnum (existattr); - - if (new_mm_seq > exist_mm_seq) - { - if (debug) - zlog_debug("%s: %s wins over %s due to MM seq %u > %u", - pfx_buf, new_buf, exist_buf, new_mm_seq, exist_mm_seq); - return 1; - } - - if (new_mm_seq < exist_mm_seq) - { - if (debug) - zlog_debug("%s: %s loses to %s due to MM seq %u < %u", - pfx_buf, new_buf, exist_buf, new_mm_seq, exist_mm_seq); - return 0; - } - } + newattr = new->attr; + existattr = exist->attr; + + /* For EVPN routes, we cannot just go by local vs remote, we have to + * look at the MAC mobility sequence number, if present. + */ + if (safi == SAFI_EVPN) { + /* This is an error condition described in RFC 7432 Section + * 15.2. The RFC + * states that in this scenario "the PE MUST alert the operator" + * but it + * does not state what other action to take. In order to provide + * some + * consistency in this scenario we are going to prefer the path + * with the + * sticky flag. + */ + if (newattr->sticky != existattr->sticky) { + if (!debug) { + prefix2str(&new->net->p, pfx_buf, + sizeof(*pfx_buf) + * PREFIX2STR_BUFFER); + bgp_info_path_with_addpath_rx_str(new, new_buf); + bgp_info_path_with_addpath_rx_str(exist, + exist_buf); + } + + if (newattr->sticky && !existattr->sticky) { + zlog_warn( + "%s: %s wins over %s due to sticky MAC flag", + pfx_buf, new_buf, exist_buf); + return 1; + } + + if (!newattr->sticky && existattr->sticky) { + zlog_warn( + "%s: %s loses to %s due to sticky MAC flag", + pfx_buf, new_buf, exist_buf); + return 0; + } + } - /* 1. Weight check. */ - new_weight = exist_weight = 0; + new_mm_seq = mac_mobility_seqnum(newattr); + exist_mm_seq = mac_mobility_seqnum(existattr); - new_weight = newattr->weight; - exist_weight = existattr->weight; + if (new_mm_seq > exist_mm_seq) { + if (debug) + zlog_debug( + "%s: %s wins over %s due to MM seq %u > %u", + pfx_buf, new_buf, exist_buf, new_mm_seq, + exist_mm_seq); + return 1; + } - if (new_weight > exist_weight) - { - if (debug) - zlog_debug("%s: %s wins over %s due to weight %d > %d", - pfx_buf, new_buf, exist_buf, new_weight, exist_weight); - return 1; - } + if (new_mm_seq < exist_mm_seq) { + if (debug) + zlog_debug( + "%s: %s loses to %s due to MM seq %u < %u", + pfx_buf, new_buf, exist_buf, new_mm_seq, + exist_mm_seq); + return 0; + } + } - if (new_weight < exist_weight) - { - if (debug) - zlog_debug("%s: %s loses to %s due to weight %d < %d", - pfx_buf, new_buf, exist_buf, new_weight, exist_weight); - return 0; - } + /* 1. Weight check. */ + new_weight = exist_weight = 0; - /* 2. Local preference check. */ - new_pref = exist_pref = bgp->default_local_pref; + new_weight = newattr->weight; + exist_weight = existattr->weight; - if (newattr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) - new_pref = newattr->local_pref; - if (existattr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) - exist_pref = existattr->local_pref; + if (new_weight > exist_weight) { + if (debug) + zlog_debug("%s: %s wins over %s due to weight %d > %d", + pfx_buf, new_buf, exist_buf, new_weight, + exist_weight); + return 1; + } - if (new_pref > exist_pref) - { - if (debug) - zlog_debug("%s: %s wins over %s due to localpref %d > %d", - pfx_buf, new_buf, exist_buf, new_pref, exist_pref); - return 1; - } + if (new_weight < exist_weight) { + if (debug) + zlog_debug("%s: %s loses to %s due to weight %d < %d", + pfx_buf, new_buf, exist_buf, new_weight, + exist_weight); + return 0; + } - if (new_pref < exist_pref) - { - if (debug) - zlog_debug("%s: %s loses to %s due to localpref %d < %d", - pfx_buf, new_buf, exist_buf, new_pref, exist_pref); - return 0; - } + /* 2. Local preference check. */ + new_pref = exist_pref = bgp->default_local_pref; + + if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) + new_pref = newattr->local_pref; + if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) + exist_pref = existattr->local_pref; + + if (new_pref > exist_pref) { + if (debug) + zlog_debug( + "%s: %s wins over %s due to localpref %d > %d", + pfx_buf, new_buf, exist_buf, new_pref, + exist_pref); + return 1; + } - /* 3. Local route check. We prefer: - * - BGP_ROUTE_STATIC - * - BGP_ROUTE_AGGREGATE - * - BGP_ROUTE_REDISTRIBUTE - */ - if (! (new->sub_type == BGP_ROUTE_NORMAL)) - { - if (debug) - zlog_debug("%s: %s wins over %s due to preferred BGP_ROUTE type", - pfx_buf, new_buf, exist_buf); - return 1; - } + if (new_pref < exist_pref) { + if (debug) + zlog_debug( + "%s: %s loses to %s due to localpref %d < %d", + pfx_buf, new_buf, exist_buf, new_pref, + exist_pref); + return 0; + } - if (! (exist->sub_type == BGP_ROUTE_NORMAL)) - { - if (debug) - zlog_debug("%s: %s loses to %s due to preferred BGP_ROUTE type", - pfx_buf, new_buf, exist_buf); - return 0; - } + /* 3. Local route check. We prefer: + * - BGP_ROUTE_STATIC + * - BGP_ROUTE_AGGREGATE + * - BGP_ROUTE_REDISTRIBUTE + */ + if (!(new->sub_type == BGP_ROUTE_NORMAL)) { + if (debug) + zlog_debug( + "%s: %s wins over %s due to preferred BGP_ROUTE type", + pfx_buf, new_buf, exist_buf); + return 1; + } - /* 4. AS path length check. */ - if (! bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE)) - { - int exist_hops = aspath_count_hops (existattr->aspath); - int exist_confeds = aspath_count_confeds (existattr->aspath); - - if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED)) - { - int aspath_hops; - - aspath_hops = aspath_count_hops (newattr->aspath); - aspath_hops += aspath_count_confeds (newattr->aspath); - - if ( aspath_hops < (exist_hops + exist_confeds)) - { - if (debug) - zlog_debug("%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d", - pfx_buf, new_buf, exist_buf, - aspath_hops, (exist_hops + exist_confeds)); - return 1; - } - - if ( aspath_hops > (exist_hops + exist_confeds)) - { - if (debug) - zlog_debug("%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d", - pfx_buf, new_buf, exist_buf, - aspath_hops, (exist_hops + exist_confeds)); - return 0; - } - } - else - { - int newhops = aspath_count_hops (newattr->aspath); - - if (newhops < exist_hops) - { - if (debug) - zlog_debug("%s: %s wins over %s due to aspath hopcount %d < %d", - pfx_buf, new_buf, exist_buf, newhops, exist_hops); - return 1; - } - - if (newhops > exist_hops) - { - if (debug) - zlog_debug("%s: %s loses to %s due to aspath hopcount %d > %d", - pfx_buf, new_buf, exist_buf, newhops, exist_hops); - return 0; - } + if (!(exist->sub_type == BGP_ROUTE_NORMAL)) { + if (debug) + zlog_debug( + "%s: %s loses to %s due to preferred BGP_ROUTE type", + pfx_buf, new_buf, exist_buf); + return 0; } - } - /* 5. Origin check. */ - if (newattr->origin < existattr->origin) - { - if (debug) - zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s", - pfx_buf, new_buf, exist_buf, - bgp_origin_long_str[newattr->origin], - bgp_origin_long_str[existattr->origin]); - return 1; - } + /* 4. AS path length check. */ + if (!bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE)) { + int exist_hops = aspath_count_hops(existattr->aspath); + int exist_confeds = aspath_count_confeds(existattr->aspath); + + if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED)) { + int aspath_hops; + + aspath_hops = aspath_count_hops(newattr->aspath); + aspath_hops += aspath_count_confeds(newattr->aspath); + + if (aspath_hops < (exist_hops + exist_confeds)) { + if (debug) + zlog_debug( + "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d", + pfx_buf, new_buf, exist_buf, + aspath_hops, + (exist_hops + exist_confeds)); + return 1; + } + + if (aspath_hops > (exist_hops + exist_confeds)) { + if (debug) + zlog_debug( + "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d", + pfx_buf, new_buf, exist_buf, + aspath_hops, + (exist_hops + exist_confeds)); + return 0; + } + } else { + int newhops = aspath_count_hops(newattr->aspath); + + if (newhops < exist_hops) { + if (debug) + zlog_debug( + "%s: %s wins over %s due to aspath hopcount %d < %d", + pfx_buf, new_buf, exist_buf, + newhops, exist_hops); + return 1; + } + + if (newhops > exist_hops) { + if (debug) + zlog_debug( + "%s: %s loses to %s due to aspath hopcount %d > %d", + pfx_buf, new_buf, exist_buf, + newhops, exist_hops); + return 0; + } + } + } - if (newattr->origin > existattr->origin) - { - if (debug) - zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s", - pfx_buf, new_buf, exist_buf, - bgp_origin_long_str[newattr->origin], - bgp_origin_long_str[existattr->origin]); - return 0; - } + /* 5. Origin check. */ + if (newattr->origin < existattr->origin) { + if (debug) + zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s", + pfx_buf, new_buf, exist_buf, + bgp_origin_long_str[newattr->origin], + bgp_origin_long_str[existattr->origin]); + return 1; + } - /* 6. MED check. */ - internal_as_route = (aspath_count_hops (newattr->aspath) == 0 - && aspath_count_hops (existattr->aspath) == 0); - confed_as_route = (aspath_count_confeds (newattr->aspath) > 0 - && aspath_count_confeds (existattr->aspath) > 0 - && aspath_count_hops (newattr->aspath) == 0 - && aspath_count_hops (existattr->aspath) == 0); - - if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED) - || (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED) - && confed_as_route) - || aspath_cmp_left (newattr->aspath, existattr->aspath) - || aspath_cmp_left_confed (newattr->aspath, existattr->aspath) - || internal_as_route) - { - new_med = bgp_med_value (new->attr, bgp); - exist_med = bgp_med_value (exist->attr, bgp); - - if (new_med < exist_med) - { - if (debug) - zlog_debug("%s: %s wins over %s due to MED %d < %d", - pfx_buf, new_buf, exist_buf, new_med, exist_med); - return 1; - } - - if (new_med > exist_med) - { - if (debug) - zlog_debug("%s: %s loses to %s due to MED %d > %d", - pfx_buf, new_buf, exist_buf, new_med, exist_med); - return 0; - } - } + if (newattr->origin > existattr->origin) { + if (debug) + zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s", + pfx_buf, new_buf, exist_buf, + bgp_origin_long_str[newattr->origin], + bgp_origin_long_str[existattr->origin]); + return 0; + } - /* 7. Peer type check. */ - new_sort = new->peer->sort; - exist_sort = exist->peer->sort; + /* 6. MED check. */ + internal_as_route = (aspath_count_hops(newattr->aspath) == 0 + && aspath_count_hops(existattr->aspath) == 0); + confed_as_route = (aspath_count_confeds(newattr->aspath) > 0 + && aspath_count_confeds(existattr->aspath) > 0 + && aspath_count_hops(newattr->aspath) == 0 + && aspath_count_hops(existattr->aspath) == 0); + + if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED) + || (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED) && confed_as_route) + || aspath_cmp_left(newattr->aspath, existattr->aspath) + || aspath_cmp_left_confed(newattr->aspath, existattr->aspath) + || internal_as_route) { + new_med = bgp_med_value(new->attr, bgp); + exist_med = bgp_med_value(exist->attr, bgp); + + if (new_med < exist_med) { + if (debug) + zlog_debug( + "%s: %s wins over %s due to MED %d < %d", + pfx_buf, new_buf, exist_buf, new_med, + exist_med); + return 1; + } - if (new_sort == BGP_PEER_EBGP - && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) - { - if (debug) - zlog_debug("%s: %s wins over %s due to eBGP peer > iBGP peer", - pfx_buf, new_buf, exist_buf); - return 1; - } + if (new_med > exist_med) { + if (debug) + zlog_debug( + "%s: %s loses to %s due to MED %d > %d", + pfx_buf, new_buf, exist_buf, new_med, + exist_med); + return 0; + } + } - if (exist_sort == BGP_PEER_EBGP - && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) - { - if (debug) - zlog_debug("%s: %s loses to %s due to iBGP peer < eBGP peer", - pfx_buf, new_buf, exist_buf); - return 0; - } + /* 7. Peer type check. */ + new_sort = new->peer->sort; + exist_sort = exist->peer->sort; + + if (new_sort == BGP_PEER_EBGP + && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) { + if (debug) + zlog_debug( + "%s: %s wins over %s due to eBGP peer > iBGP peer", + pfx_buf, new_buf, exist_buf); + return 1; + } - /* 8. IGP metric check. */ - newm = existm = 0; + if (exist_sort == BGP_PEER_EBGP + && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) { + if (debug) + zlog_debug( + "%s: %s loses to %s due to iBGP peer < eBGP peer", + pfx_buf, new_buf, exist_buf); + return 0; + } - if (new->extra) - newm = new->extra->igpmetric; - if (exist->extra) - existm = exist->extra->igpmetric; + /* 8. IGP metric check. */ + newm = existm = 0; - if (newm < existm) - { - if (debug) - zlog_debug("%s: %s wins over %s due to IGP metric %d < %d", - pfx_buf, new_buf, exist_buf, newm, existm); - ret = 1; - } + if (new->extra) + newm = new->extra->igpmetric; + if (exist->extra) + existm = exist->extra->igpmetric; - if (newm > existm) - { - if (debug) - zlog_debug("%s: %s loses to %s due to IGP metric %d > %d", - pfx_buf, new_buf, exist_buf, newm, existm); - ret = 0; - } + if (newm < existm) { + if (debug) + zlog_debug( + "%s: %s wins over %s due to IGP metric %d < %d", + pfx_buf, new_buf, exist_buf, newm, existm); + ret = 1; + } - /* 9. Same IGP metric. Compare the cluster list length as - representative of IGP hops metric. Rewrite the metric value - pair (newm, existm) with the cluster list length. Prefer the - path with smaller cluster list length. */ - if (newm == existm) - { - if (peer_sort (new->peer) == BGP_PEER_IBGP - && peer_sort (exist->peer) == BGP_PEER_IBGP - && (mpath_cfg == NULL || - CHECK_FLAG (mpath_cfg->ibgp_flags, - BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) - { - newm = BGP_CLUSTER_LIST_LENGTH(new->attr); - existm = BGP_CLUSTER_LIST_LENGTH(exist->attr); - - if (newm < existm) - { - if (debug) - zlog_debug("%s: %s wins over %s due to CLUSTER_LIST length %d < %d", - pfx_buf, new_buf, exist_buf, newm, existm); - ret = 1; - } - - if (newm > existm) - { - if (debug) - zlog_debug("%s: %s loses to %s due to CLUSTER_LIST length %d > %d", - pfx_buf, new_buf, exist_buf, newm, existm); - ret = 0; - } + if (newm > existm) { + if (debug) + zlog_debug( + "%s: %s loses to %s due to IGP metric %d > %d", + pfx_buf, new_buf, exist_buf, newm, existm); + ret = 0; } - } - /* 10. confed-external vs. confed-internal */ - if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) - { - if (new_sort == BGP_PEER_CONFED && exist_sort == BGP_PEER_IBGP) - { - if (debug) - zlog_debug("%s: %s wins over %s due to confed-external peer > confed-internal peer", - pfx_buf, new_buf, exist_buf); - return 1; - } - - if (exist_sort == BGP_PEER_CONFED && new_sort == BGP_PEER_IBGP) - { - if (debug) - zlog_debug("%s: %s loses to %s due to confed-internal peer < confed-external peer", - pfx_buf, new_buf, exist_buf); - return 0; - } - } + /* 9. Same IGP metric. Compare the cluster list length as + representative of IGP hops metric. Rewrite the metric value + pair (newm, existm) with the cluster list length. Prefer the + path with smaller cluster list length. */ + if (newm == existm) { + if (peer_sort(new->peer) == BGP_PEER_IBGP + && peer_sort(exist->peer) == BGP_PEER_IBGP + && (mpath_cfg == NULL + || CHECK_FLAG( + mpath_cfg->ibgp_flags, + BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) { + newm = BGP_CLUSTER_LIST_LENGTH(new->attr); + existm = BGP_CLUSTER_LIST_LENGTH(exist->attr); + + if (newm < existm) { + if (debug) + zlog_debug( + "%s: %s wins over %s due to CLUSTER_LIST length %d < %d", + pfx_buf, new_buf, exist_buf, + newm, existm); + ret = 1; + } + + if (newm > existm) { + if (debug) + zlog_debug( + "%s: %s loses to %s due to CLUSTER_LIST length %d > %d", + pfx_buf, new_buf, exist_buf, + newm, existm); + ret = 0; + } + } + } - /* 11. Maximum path check. */ - if (newm == existm) - { - /* If one path has a label but the other does not, do not treat - * them as equals for multipath - */ - if ((new->extra && bgp_is_valid_label(&new->extra->label)) != - (exist->extra && bgp_is_valid_label(&exist->extra->label))) - { - if (debug) - zlog_debug("%s: %s and %s cannot be multipath, one has a label while the other does not", - pfx_buf, new_buf, exist_buf); - } - else if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) - { - - /* - * For the two paths, all comparison steps till IGP metric - * have succeeded - including AS_PATH hop count. Since 'bgp - * bestpath as-path multipath-relax' knob is on, we don't need - * an exact match of AS_PATH. Thus, mark the paths are equal. - * That will trigger both these paths to get into the multipath - * array. - */ - *paths_eq = 1; - - if (debug) - zlog_debug("%s: %s and %s are equal via multipath-relax", - pfx_buf, new_buf, exist_buf); - } - else if (new->peer->sort == BGP_PEER_IBGP) - { - if (aspath_cmp (new->attr->aspath, exist->attr->aspath)) - { - *paths_eq = 1; - - if (debug) - zlog_debug("%s: %s and %s are equal via matching aspaths", - pfx_buf, new_buf, exist_buf); - } - } - else if (new->peer->as == exist->peer->as) - { - *paths_eq = 1; - - if (debug) - zlog_debug("%s: %s and %s are equal via same remote-as", - pfx_buf, new_buf, exist_buf); - } - } - else - { - /* - * TODO: If unequal cost ibgp multipath is enabled we can - * mark the paths as equal here instead of returning - */ - if (debug) - { - if (ret == 1) - zlog_debug("%s: %s wins over %s after IGP metric comparison", - pfx_buf, new_buf, exist_buf); - else - zlog_debug("%s: %s loses to %s after IGP metric comparison", - pfx_buf, new_buf, exist_buf); - } - return ret; - } + /* 10. confed-external vs. confed-internal */ + if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) { + if (new_sort == BGP_PEER_CONFED + && exist_sort == BGP_PEER_IBGP) { + if (debug) + zlog_debug( + "%s: %s wins over %s due to confed-external peer > confed-internal peer", + pfx_buf, new_buf, exist_buf); + return 1; + } - /* 12. If both paths are external, prefer the path that was received - first (the oldest one). This step minimizes route-flap, since a - newer path won't displace an older one, even if it was the - preferred route based on the additional decision criteria below. */ - if (! bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID) - && new_sort == BGP_PEER_EBGP - && exist_sort == BGP_PEER_EBGP) - { - if (CHECK_FLAG (new->flags, BGP_INFO_SELECTED)) - { - if (debug) - zlog_debug("%s: %s wins over %s due to oldest external", - pfx_buf, new_buf, exist_buf); - return 1; - } - - if (CHECK_FLAG (exist->flags, BGP_INFO_SELECTED)) - { - if (debug) - zlog_debug("%s: %s loses to %s due to oldest external", - pfx_buf, new_buf, exist_buf); - return 0; - } - } + if (exist_sort == BGP_PEER_CONFED + && new_sort == BGP_PEER_IBGP) { + if (debug) + zlog_debug( + "%s: %s loses to %s due to confed-internal peer < confed-external peer", + pfx_buf, new_buf, exist_buf); + return 0; + } + } - /* 13. Router-ID comparision. */ - /* If one of the paths is "stale", the corresponding peer router-id will - * be 0 and would always win over the other path. If originator id is - * used for the comparision, it will decide which path is better. - */ - if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) - new_id.s_addr = newattr->originator_id.s_addr; - else - new_id.s_addr = new->peer->remote_id.s_addr; - if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) - exist_id.s_addr = existattr->originator_id.s_addr; - else - exist_id.s_addr = exist->peer->remote_id.s_addr; + /* 11. Maximum path check. */ + if (newm == existm) { + /* If one path has a label but the other does not, do not treat + * them as equals for multipath + */ + if ((new->extra &&bgp_is_valid_label(&new->extra->label)) + != (exist->extra + && bgp_is_valid_label(&exist->extra->label))) { + if (debug) + zlog_debug( + "%s: %s and %s cannot be multipath, one has a label while the other does not", + pfx_buf, new_buf, exist_buf); + } else if (bgp_flag_check(bgp, + BGP_FLAG_ASPATH_MULTIPATH_RELAX)) { + + /* + * For the two paths, all comparison steps till IGP + * metric + * have succeeded - including AS_PATH hop count. Since + * 'bgp + * bestpath as-path multipath-relax' knob is on, we + * don't need + * an exact match of AS_PATH. Thus, mark the paths are + * equal. + * That will trigger both these paths to get into the + * multipath + * array. + */ + *paths_eq = 1; + + if (debug) + zlog_debug( + "%s: %s and %s are equal via multipath-relax", + pfx_buf, new_buf, exist_buf); + } else if (new->peer->sort == BGP_PEER_IBGP) { + if (aspath_cmp(new->attr->aspath, + exist->attr->aspath)) { + *paths_eq = 1; + + if (debug) + zlog_debug( + "%s: %s and %s are equal via matching aspaths", + pfx_buf, new_buf, exist_buf); + } + } else if (new->peer->as == exist->peer->as) { + *paths_eq = 1; + + if (debug) + zlog_debug( + "%s: %s and %s are equal via same remote-as", + pfx_buf, new_buf, exist_buf); + } + } else { + /* + * TODO: If unequal cost ibgp multipath is enabled we can + * mark the paths as equal here instead of returning + */ + if (debug) { + if (ret == 1) + zlog_debug( + "%s: %s wins over %s after IGP metric comparison", + pfx_buf, new_buf, exist_buf); + else + zlog_debug( + "%s: %s loses to %s after IGP metric comparison", + pfx_buf, new_buf, exist_buf); + } + return ret; + } - if (ntohl (new_id.s_addr) < ntohl (exist_id.s_addr)) - { - if (debug) - zlog_debug("%s: %s wins over %s due to Router-ID comparison", - pfx_buf, new_buf, exist_buf); - return 1; - } + /* 12. If both paths are external, prefer the path that was received + first (the oldest one). This step minimizes route-flap, since a + newer path won't displace an older one, even if it was the + preferred route based on the additional decision criteria below. */ + if (!bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID) + && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) { + if (CHECK_FLAG(new->flags, BGP_INFO_SELECTED)) { + if (debug) + zlog_debug( + "%s: %s wins over %s due to oldest external", + pfx_buf, new_buf, exist_buf); + return 1; + } - if (ntohl (new_id.s_addr) > ntohl (exist_id.s_addr)) - { - if (debug) - zlog_debug("%s: %s loses to %s due to Router-ID comparison", - pfx_buf, new_buf, exist_buf); - return 0; - } + if (CHECK_FLAG(exist->flags, BGP_INFO_SELECTED)) { + if (debug) + zlog_debug( + "%s: %s loses to %s due to oldest external", + pfx_buf, new_buf, exist_buf); + return 0; + } + } - /* 14. Cluster length comparision. */ - new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr); - exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr); + /* 13. Router-ID comparision. */ + /* If one of the paths is "stale", the corresponding peer router-id will + * be 0 and would always win over the other path. If originator id is + * used for the comparision, it will decide which path is better. + */ + if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) + new_id.s_addr = newattr->originator_id.s_addr; + else + new_id.s_addr = new->peer->remote_id.s_addr; + if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) + exist_id.s_addr = existattr->originator_id.s_addr; + else + exist_id.s_addr = exist->peer->remote_id.s_addr; + + if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) { + if (debug) + zlog_debug( + "%s: %s wins over %s due to Router-ID comparison", + pfx_buf, new_buf, exist_buf); + return 1; + } - if (new_cluster < exist_cluster) - { - if (debug) - zlog_debug("%s: %s wins over %s due to CLUSTER_LIST length %d < %d", - pfx_buf, new_buf, exist_buf, new_cluster, exist_cluster); - return 1; - } + if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) { + if (debug) + zlog_debug( + "%s: %s loses to %s due to Router-ID comparison", + pfx_buf, new_buf, exist_buf); + return 0; + } - if (new_cluster > exist_cluster) - { - if (debug) - zlog_debug("%s: %s loses to %s due to CLUSTER_LIST length %d > %d", - pfx_buf, new_buf, exist_buf, new_cluster, exist_cluster); - return 0; - } + /* 14. Cluster length comparision. */ + new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr); + exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr); + + if (new_cluster < exist_cluster) { + if (debug) + zlog_debug( + "%s: %s wins over %s due to CLUSTER_LIST length %d < %d", + pfx_buf, new_buf, exist_buf, new_cluster, + exist_cluster); + return 1; + } - /* 15. Neighbor address comparision. */ - /* Do this only if neither path is "stale" as stale paths do not have - * valid peer information (as the connection may or may not be up). - */ - if (CHECK_FLAG (exist->flags, BGP_INFO_STALE)) - { - if (debug) - zlog_debug("%s: %s wins over %s due to latter path being STALE", - pfx_buf, new_buf, exist_buf); - return 1; - } + if (new_cluster > exist_cluster) { + if (debug) + zlog_debug( + "%s: %s loses to %s due to CLUSTER_LIST length %d > %d", + pfx_buf, new_buf, exist_buf, new_cluster, + exist_cluster); + return 0; + } - if (CHECK_FLAG (new->flags, BGP_INFO_STALE)) - { - if (debug) - zlog_debug("%s: %s loses to %s due to former path being STALE", - pfx_buf, new_buf, exist_buf); - return 0; - } + /* 15. Neighbor address comparision. */ + /* Do this only if neither path is "stale" as stale paths do not have + * valid peer information (as the connection may or may not be up). + */ + if (CHECK_FLAG(exist->flags, BGP_INFO_STALE)) { + if (debug) + zlog_debug( + "%s: %s wins over %s due to latter path being STALE", + pfx_buf, new_buf, exist_buf); + return 1; + } - /* locally configured routes to advertise do not have su_remote */ - if (new->peer->su_remote == NULL) - return 0; - if (exist->peer->su_remote == NULL) - return 1; - - ret = sockunion_cmp (new->peer->su_remote, exist->peer->su_remote); + if (CHECK_FLAG(new->flags, BGP_INFO_STALE)) { + if (debug) + zlog_debug( + "%s: %s loses to %s due to former path being STALE", + pfx_buf, new_buf, exist_buf); + return 0; + } - if (ret == 1) - { - if (debug) - zlog_debug("%s: %s loses to %s due to Neighor IP comparison", - pfx_buf, new_buf, exist_buf); - return 0; - } + /* locally configured routes to advertise do not have su_remote */ + if (new->peer->su_remote == NULL) + return 0; + if (exist->peer->su_remote == NULL) + return 1; - if (ret == -1) - { - if (debug) - zlog_debug("%s: %s wins over %s due to Neighor IP comparison", - pfx_buf, new_buf, exist_buf); - return 1; - } + ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote); + + if (ret == 1) { + if (debug) + zlog_debug( + "%s: %s loses to %s due to Neighor IP comparison", + pfx_buf, new_buf, exist_buf); + return 0; + } + + if (ret == -1) { + if (debug) + zlog_debug( + "%s: %s wins over %s due to Neighor IP comparison", + pfx_buf, new_buf, exist_buf); + return 1; + } - if (debug) - zlog_debug("%s: %s wins over %s due to nothing left to compare", - pfx_buf, new_buf, exist_buf); + if (debug) + zlog_debug("%s: %s wins over %s due to nothing left to compare", + pfx_buf, new_buf, exist_buf); - return 1; + return 1; } /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist * is preferred, or 0 if they are the same (usually will only occur if - * multipath is enabled + * multipath is enabled * This version is compatible with */ -int -bgp_info_cmp_compatible (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist, - char *pfx_buf, afi_t afi, safi_t safi) -{ - int paths_eq; - int ret; - ret = bgp_info_cmp (bgp, new, exist, &paths_eq, NULL, 0, - pfx_buf, afi, safi); - - if (paths_eq) - ret = 0; - else - { - if (ret == 1) - ret = -1; - else - ret = 1; - } - return ret; +int bgp_info_cmp_compatible(struct bgp *bgp, struct bgp_info *new, + struct bgp_info *exist, char *pfx_buf, afi_t afi, + safi_t safi) +{ + int paths_eq; + int ret; + ret = bgp_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf, afi, + safi); + + if (paths_eq) + ret = 0; + else { + if (ret == 1) + ret = -1; + else + ret = 1; + } + return ret; } -static enum filter_type -bgp_input_filter (struct peer *peer, struct prefix *p, struct attr *attr, - afi_t afi, safi_t safi) +static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p, + struct attr *attr, afi_t afi, + safi_t safi) { - struct bgp_filter *filter; + struct bgp_filter *filter; - filter = &peer->filter[afi][safi]; + filter = &peer->filter[afi][safi]; -#define FILTER_EXIST_WARN(F,f,filter) \ - if (BGP_DEBUG (update, UPDATE_IN) \ - && !(F ## _IN (filter))) \ - zlog_warn ("%s: Could not find configured input %s-list %s!", \ - peer->host, #f, F ## _IN_NAME(filter)); - - if (DISTRIBUTE_IN_NAME (filter)) { - FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter); - - if (access_list_apply (DISTRIBUTE_IN (filter), p) == FILTER_DENY) - return FILTER_DENY; - } - - if (PREFIX_LIST_IN_NAME (filter)) { - FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter); - - if (prefix_list_apply (PREFIX_LIST_IN (filter), p) == PREFIX_DENY) - return FILTER_DENY; - } - - if (FILTER_LIST_IN_NAME (filter)) { - FILTER_EXIST_WARN(FILTER_LIST, as, filter); - - if (as_list_apply (FILTER_LIST_IN (filter), attr->aspath)== AS_FILTER_DENY) - return FILTER_DENY; - } - - return FILTER_PERMIT; +#define FILTER_EXIST_WARN(F, f, filter) \ + if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \ + zlog_warn("%s: Could not find configured input %s-list %s!", \ + peer->host, #f, F##_IN_NAME(filter)); + + if (DISTRIBUTE_IN_NAME(filter)) { + FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter); + + if (access_list_apply(DISTRIBUTE_IN(filter), p) == FILTER_DENY) + return FILTER_DENY; + } + + if (PREFIX_LIST_IN_NAME(filter)) { + FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter); + + if (prefix_list_apply(PREFIX_LIST_IN(filter), p) == PREFIX_DENY) + return FILTER_DENY; + } + + if (FILTER_LIST_IN_NAME(filter)) { + FILTER_EXIST_WARN(FILTER_LIST, as, filter); + + if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath) + == AS_FILTER_DENY) + return FILTER_DENY; + } + + return FILTER_PERMIT; #undef FILTER_EXIST_WARN } -static enum filter_type -bgp_output_filter (struct peer *peer, struct prefix *p, struct attr *attr, - afi_t afi, safi_t safi) +static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p, + struct attr *attr, afi_t afi, + safi_t safi) { - struct bgp_filter *filter; + struct bgp_filter *filter; + + filter = &peer->filter[afi][safi]; + +#define FILTER_EXIST_WARN(F, f, filter) \ + if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \ + zlog_warn("%s: Could not find configured output %s-list %s!", \ + peer->host, #f, F##_OUT_NAME(filter)); - filter = &peer->filter[afi][safi]; + if (DISTRIBUTE_OUT_NAME(filter)) { + FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter); -#define FILTER_EXIST_WARN(F,f,filter) \ - if (BGP_DEBUG (update, UPDATE_OUT) \ - && !(F ## _OUT (filter))) \ - zlog_warn ("%s: Could not find configured output %s-list %s!", \ - peer->host, #f, F ## _OUT_NAME(filter)); + if (access_list_apply(DISTRIBUTE_OUT(filter), p) == FILTER_DENY) + return FILTER_DENY; + } + + if (PREFIX_LIST_OUT_NAME(filter)) { + FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter); - if (DISTRIBUTE_OUT_NAME (filter)) { - FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter); - - if (access_list_apply (DISTRIBUTE_OUT (filter), p) == FILTER_DENY) - return FILTER_DENY; - } + if (prefix_list_apply(PREFIX_LIST_OUT(filter), p) + == PREFIX_DENY) + return FILTER_DENY; + } - if (PREFIX_LIST_OUT_NAME (filter)) { - FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter); - - if (prefix_list_apply (PREFIX_LIST_OUT (filter), p) == PREFIX_DENY) - return FILTER_DENY; - } + if (FILTER_LIST_OUT_NAME(filter)) { + FILTER_EXIST_WARN(FILTER_LIST, as, filter); - if (FILTER_LIST_OUT_NAME (filter)) { - FILTER_EXIST_WARN(FILTER_LIST, as, filter); - - if (as_list_apply (FILTER_LIST_OUT (filter), attr->aspath) == AS_FILTER_DENY) - return FILTER_DENY; - } + if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath) + == AS_FILTER_DENY) + return FILTER_DENY; + } - return FILTER_PERMIT; + return FILTER_PERMIT; #undef FILTER_EXIST_WARN } /* If community attribute includes no_export then return 1. */ -static int -bgp_community_filter (struct peer *peer, struct attr *attr) -{ - if (attr->community) - { - /* NO_ADVERTISE check. */ - if (community_include (attr->community, COMMUNITY_NO_ADVERTISE)) - return 1; - - /* NO_EXPORT check. */ - if (peer->sort == BGP_PEER_EBGP && - community_include (attr->community, COMMUNITY_NO_EXPORT)) - return 1; - - /* NO_EXPORT_SUBCONFED check. */ - if (peer->sort == BGP_PEER_EBGP - || peer->sort == BGP_PEER_CONFED) - if (community_include (attr->community, COMMUNITY_NO_EXPORT_SUBCONFED)) - return 1; - } - return 0; +static int bgp_community_filter(struct peer *peer, struct attr *attr) +{ + if (attr->community) { + /* NO_ADVERTISE check. */ + if (community_include(attr->community, COMMUNITY_NO_ADVERTISE)) + return 1; + + /* NO_EXPORT check. */ + if (peer->sort == BGP_PEER_EBGP + && community_include(attr->community, COMMUNITY_NO_EXPORT)) + return 1; + + /* NO_EXPORT_SUBCONFED check. */ + if (peer->sort == BGP_PEER_EBGP + || peer->sort == BGP_PEER_CONFED) + if (community_include(attr->community, + COMMUNITY_NO_EXPORT_SUBCONFED)) + return 1; + } + return 0; } /* Route reflection loop check. */ -static int -bgp_cluster_filter (struct peer *peer, struct attr *attr) +static int bgp_cluster_filter(struct peer *peer, struct attr *attr) { - struct in_addr cluster_id; + struct in_addr cluster_id; - if (attr->cluster) - { - if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID) - cluster_id = peer->bgp->cluster_id; - else - cluster_id = peer->bgp->router_id; - - if (cluster_loop_check (attr->cluster, cluster_id)) - return 1; - } - return 0; + if (attr->cluster) { + if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID) + cluster_id = peer->bgp->cluster_id; + else + cluster_id = peer->bgp->router_id; + + if (cluster_loop_check(attr->cluster, cluster_id)) + return 1; + } + return 0; } -static int -bgp_input_modifier (struct peer *peer, struct prefix *p, struct attr *attr, - afi_t afi, safi_t safi, const char *rmap_name) +static int bgp_input_modifier(struct peer *peer, struct prefix *p, + struct attr *attr, afi_t afi, safi_t safi, + const char *rmap_name) { - struct bgp_filter *filter; - struct bgp_info info; - route_map_result_t ret; - struct route_map *rmap = NULL; + struct bgp_filter *filter; + struct bgp_info info; + route_map_result_t ret; + struct route_map *rmap = NULL; - filter = &peer->filter[afi][safi]; + filter = &peer->filter[afi][safi]; - /* Apply default weight value. */ - if (peer->weight[afi][safi]) - attr->weight = peer->weight[afi][safi]; + /* Apply default weight value. */ + if (peer->weight[afi][safi]) + attr->weight = peer->weight[afi][safi]; - if (rmap_name) - { - rmap = route_map_lookup_by_name(rmap_name); + if (rmap_name) { + rmap = route_map_lookup_by_name(rmap_name); - if (rmap == NULL) - return RMAP_DENY; - } - else - { - if (ROUTE_MAP_IN_NAME(filter)) - { - rmap = ROUTE_MAP_IN (filter); + if (rmap == NULL) + return RMAP_DENY; + } else { + if (ROUTE_MAP_IN_NAME(filter)) { + rmap = ROUTE_MAP_IN(filter); - if (rmap == NULL) - return RMAP_DENY; - } - } + if (rmap == NULL) + return RMAP_DENY; + } + } - /* Route map apply. */ - if (rmap) - { - /* Duplicate current value to new strucutre for modification. */ - info.peer = peer; - info.attr = attr; + /* Route map apply. */ + if (rmap) { + /* Duplicate current value to new strucutre for modification. */ + info.peer = peer; + info.attr = attr; - SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN); + SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN); - /* Apply BGP route map to the attribute. */ - ret = route_map_apply (rmap, p, RMAP_BGP, &info); + /* Apply BGP route map to the attribute. */ + ret = route_map_apply(rmap, p, RMAP_BGP, &info); - peer->rmap_type = 0; + peer->rmap_type = 0; - if (ret == RMAP_DENYMATCH) - { - /* Free newly generated AS path and community by route-map. */ - bgp_attr_flush (attr); - return RMAP_DENY; + if (ret == RMAP_DENYMATCH) { + /* Free newly generated AS path and community by + * route-map. */ + bgp_attr_flush(attr); + return RMAP_DENY; + } } - } - return RMAP_PERMIT; + return RMAP_PERMIT; } -static int -bgp_output_modifier (struct peer *peer, struct prefix *p, struct attr *attr, - afi_t afi, safi_t safi, const char *rmap_name) +static int bgp_output_modifier(struct peer *peer, struct prefix *p, + struct attr *attr, afi_t afi, safi_t safi, + const char *rmap_name) { - struct bgp_filter *filter; - struct bgp_info info; - route_map_result_t ret; - struct route_map *rmap = NULL; + struct bgp_filter *filter; + struct bgp_info info; + route_map_result_t ret; + struct route_map *rmap = NULL; - filter = &peer->filter[afi][safi]; + filter = &peer->filter[afi][safi]; - /* Apply default weight value. */ - if (peer->weight[afi][safi]) - attr->weight = peer->weight[afi][safi]; + /* Apply default weight value. */ + if (peer->weight[afi][safi]) + attr->weight = peer->weight[afi][safi]; - if (rmap_name) - { - rmap = route_map_lookup_by_name(rmap_name); + if (rmap_name) { + rmap = route_map_lookup_by_name(rmap_name); - if (rmap == NULL) - return RMAP_DENY; - } - else - { - if (ROUTE_MAP_OUT_NAME(filter)) - { - rmap = ROUTE_MAP_OUT (filter); + if (rmap == NULL) + return RMAP_DENY; + } else { + if (ROUTE_MAP_OUT_NAME(filter)) { + rmap = ROUTE_MAP_OUT(filter); - if (rmap == NULL) - return RMAP_DENY; - } - } + if (rmap == NULL) + return RMAP_DENY; + } + } - /* Route map apply. */ - if (rmap) - { - /* Duplicate current value to new strucutre for modification. */ - info.peer = peer; - info.attr = attr; + /* Route map apply. */ + if (rmap) { + /* Duplicate current value to new strucutre for modification. */ + info.peer = peer; + info.attr = attr; - SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT); + SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT); - /* Apply BGP route map to the attribute. */ - ret = route_map_apply (rmap, p, RMAP_BGP, &info); + /* Apply BGP route map to the attribute. */ + ret = route_map_apply(rmap, p, RMAP_BGP, &info); - peer->rmap_type = 0; + peer->rmap_type = 0; - if (ret == RMAP_DENYMATCH) - /* caller has multiple error paths with bgp_attr_flush() */ - return RMAP_DENY; - } - return RMAP_PERMIT; + if (ret == RMAP_DENYMATCH) + /* caller has multiple error paths with bgp_attr_flush() + */ + return RMAP_DENY; + } + return RMAP_PERMIT; } /* If this is an EBGP peer with remove-private-AS */ -static void -bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi, - struct peer *peer, struct attr *attr) -{ - if (peer->sort == BGP_PEER_EBGP && - (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE) || - peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE) || - peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL) || - peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS))) - { - // Take action on the entire aspath - if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE) || - peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) - { - if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) - attr->aspath = aspath_replace_private_asns (attr->aspath, bgp->as); - - // The entire aspath consists of private ASNs so create an empty aspath - else if (aspath_private_as_check (attr->aspath)) - attr->aspath = aspath_empty_get (); - - // There are some public and some private ASNs, remove the private ASNs - else - attr->aspath = aspath_remove_private_asns (attr->aspath); - } - - // 'all' was not specified so the entire aspath must be private ASNs - // for us to do anything - else if (aspath_private_as_check (attr->aspath)) - { - if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) - attr->aspath = aspath_replace_private_asns (attr->aspath, bgp->as); - else - attr->aspath = aspath_empty_get (); - } - } +static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi, + struct peer *peer, struct attr *attr) +{ + if (peer->sort == BGP_PEER_EBGP + && (peer_af_flag_check(peer, afi, safi, + PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE) + || peer_af_flag_check(peer, afi, safi, + PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE) + || peer_af_flag_check(peer, afi, safi, + PEER_FLAG_REMOVE_PRIVATE_AS_ALL) + || peer_af_flag_check(peer, afi, safi, + PEER_FLAG_REMOVE_PRIVATE_AS))) { + // Take action on the entire aspath + if (peer_af_flag_check(peer, afi, safi, + PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE) + || peer_af_flag_check(peer, afi, safi, + PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) { + if (peer_af_flag_check( + peer, afi, safi, + PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) + attr->aspath = aspath_replace_private_asns( + attr->aspath, bgp->as); + + // The entire aspath consists of private ASNs so create + // an empty aspath + else if (aspath_private_as_check(attr->aspath)) + attr->aspath = aspath_empty_get(); + + // There are some public and some private ASNs, remove + // the private ASNs + else + attr->aspath = aspath_remove_private_asns( + attr->aspath); + } + + // 'all' was not specified so the entire aspath must be private + // ASNs + // for us to do anything + else if (aspath_private_as_check(attr->aspath)) { + if (peer_af_flag_check( + peer, afi, safi, + PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) + attr->aspath = aspath_replace_private_asns( + attr->aspath, bgp->as); + else + attr->aspath = aspath_empty_get(); + } + } } /* If this is an EBGP peer with as-override */ -static void -bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi, - struct peer *peer, struct attr *attr) +static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi, + struct peer *peer, struct attr *attr) +{ + if (peer->sort == BGP_PEER_EBGP + && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) { + if (aspath_single_asn_check(attr->aspath, peer->as)) + attr->aspath = aspath_replace_specific_asn( + attr->aspath, peer->as, bgp->as); + } +} + +static void subgroup_announce_reset_nhop(u_char family, struct attr *attr) { - if (peer->sort == BGP_PEER_EBGP && - peer_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) - { - if (aspath_single_asn_check (attr->aspath, peer->as)) - attr->aspath = aspath_replace_specific_asn (attr->aspath, peer->as, bgp->as); - } + if (family == AF_INET) + attr->nexthop.s_addr = 0; + if (family == AF_INET6) + memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN); } -static void -subgroup_announce_reset_nhop (u_char family, struct attr *attr) -{ - if (family == AF_INET) - attr->nexthop.s_addr = 0; - if (family == AF_INET6) - memset (&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN); -} - -int -subgroup_announce_check (struct bgp_node *rn, struct bgp_info *ri, - struct update_subgroup *subgrp, - struct prefix *p, struct attr *attr) -{ - struct bgp_filter *filter; - struct peer *from; - struct peer *peer; - struct peer *onlypeer; - struct bgp *bgp; - struct attr *riattr; - struct peer_af *paf; - char buf[PREFIX_STRLEN]; - int ret; - int transparent; - int reflect; - afi_t afi; - safi_t safi; - int samepeer_safe = 0; /* for synthetic mplsvpns routes */ - - if (DISABLE_BGP_ANNOUNCE) - return 0; - - afi = SUBGRP_AFI(subgrp); - safi = SUBGRP_SAFI(subgrp); - peer = SUBGRP_PEER(subgrp); - onlypeer = NULL; - if (CHECK_FLAG (peer->flags, PEER_FLAG_LONESOUL)) - onlypeer = SUBGRP_PFIRST(subgrp)->peer; - - from = ri->peer; - filter = &peer->filter[afi][safi]; - bgp = SUBGRP_INST(subgrp); - riattr = bgp_info_mpath_count (ri) ? bgp_info_mpath_attr (ri) : ri->attr; +int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, + struct update_subgroup *subgrp, struct prefix *p, + struct attr *attr) +{ + struct bgp_filter *filter; + struct peer *from; + struct peer *peer; + struct peer *onlypeer; + struct bgp *bgp; + struct attr *riattr; + struct peer_af *paf; + char buf[PREFIX_STRLEN]; + int ret; + int transparent; + int reflect; + afi_t afi; + safi_t safi; + int samepeer_safe = 0; /* for synthetic mplsvpns routes */ + + if (DISABLE_BGP_ANNOUNCE) + return 0; + + afi = SUBGRP_AFI(subgrp); + safi = SUBGRP_SAFI(subgrp); + peer = SUBGRP_PEER(subgrp); + onlypeer = NULL; + if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL)) + onlypeer = SUBGRP_PFIRST(subgrp)->peer; + + from = ri->peer; + filter = &peer->filter[afi][safi]; + bgp = SUBGRP_INST(subgrp); + riattr = bgp_info_mpath_count(ri) ? bgp_info_mpath_attr(ri) : ri->attr; #if ENABLE_BGP_VNC - if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN) && - ((ri->type == ZEBRA_ROUTE_BGP_DIRECT) || - (ri->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) { - - /* - * direct and direct_ext type routes originate internally even - * though they can have peer pointers that reference other systems - */ - prefix2str(p, buf, PREFIX_STRLEN); - zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe", __func__, buf); - samepeer_safe = 1; - } + if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN) + && ((ri->type == ZEBRA_ROUTE_BGP_DIRECT) + || (ri->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) { + + /* + * direct and direct_ext type routes originate internally even + * though they can have peer pointers that reference other + * systems + */ + prefix2str(p, buf, PREFIX_STRLEN); + zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe", + __func__, buf); + samepeer_safe = 1; + } #endif - /* With addpath we may be asked to TX all kinds of paths so make sure - * ri is valid */ - if (!CHECK_FLAG (ri->flags, BGP_INFO_VALID) || - CHECK_FLAG (ri->flags, BGP_INFO_HISTORY) || - CHECK_FLAG (ri->flags, BGP_INFO_REMOVED)) - { - return 0; - } + /* With addpath we may be asked to TX all kinds of paths so make sure + * ri is valid */ + if (!CHECK_FLAG(ri->flags, BGP_INFO_VALID) + || CHECK_FLAG(ri->flags, BGP_INFO_HISTORY) + || CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { + return 0; + } - /* If this is not the bestpath then check to see if there is an enabled addpath - * feature that requires us to advertise it */ - if (! CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) - { - if (! bgp_addpath_tx_path(peer, afi, safi, ri)) - { - return 0; - } - } + /* If this is not the bestpath then check to see if there is an enabled + * addpath + * feature that requires us to advertise it */ + if (!CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) { + if (!bgp_addpath_tx_path(peer, afi, safi, ri)) { + return 0; + } + } - /* Aggregate-address suppress check. */ - if (ri->extra && ri->extra->suppress) - if (! UNSUPPRESS_MAP_NAME (filter)) - { - return 0; - } + /* Aggregate-address suppress check. */ + if (ri->extra && ri->extra->suppress) + if (!UNSUPPRESS_MAP_NAME(filter)) { + return 0; + } - /* If it's labeled safi, make sure the route has a valid label. */ - if (safi == SAFI_LABELED_UNICAST) - { - mpls_label_t label = bgp_adv_label(rn, ri, peer, afi, safi); - if (!bgp_is_valid_label(&label)) - { - if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " %s/%d is filtered - no label (%p)", - subgrp->update_group->id, subgrp->id, - inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), - p->prefixlen, &label); - return 0; - } - } + /* If it's labeled safi, make sure the route has a valid label. */ + if (safi == SAFI_LABELED_UNICAST) { + mpls_label_t label = bgp_adv_label(rn, ri, peer, afi, safi); + if (!bgp_is_valid_label(&label)) { + if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) + zlog_debug("u%" PRIu64 ":s%" PRIu64 + " %s/%d is filtered - no label (%p)", + subgrp->update_group->id, subgrp->id, + inet_ntop(p->family, &p->u.prefix, + buf, SU_ADDRSTRLEN), + p->prefixlen, &label); + return 0; + } + } - /* Do not send back route to sender. */ - if (onlypeer && from == onlypeer) - { - return 0; - } + /* Do not send back route to sender. */ + if (onlypeer && from == onlypeer) { + return 0; + } - /* Do not send the default route in the BGP table if the neighbor is - * configured for default-originate */ - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)) - { - if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY) - return 0; - else if (p->family == AF_INET6 && p->prefixlen == 0) - return 0; - } + /* Do not send the default route in the BGP table if the neighbor is + * configured for default-originate */ + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_DEFAULT_ORIGINATE)) { + if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY) + return 0; + else if (p->family == AF_INET6 && p->prefixlen == 0) + return 0; + } - /* Transparency check. */ - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT) - && CHECK_FLAG (from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)) - transparent = 1; - else - transparent = 0; + /* Transparency check. */ + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT) + && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)) + transparent = 1; + else + transparent = 0; + + /* If community is not disabled check the no-export and local. */ + if (!transparent && bgp_community_filter(peer, riattr)) { + if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) + zlog_debug( + "subgrpannouncecheck: community filter check fail"); + return 0; + } - /* If community is not disabled check the no-export and local. */ - if (! transparent && bgp_community_filter (peer, riattr)) - { - if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) - zlog_debug ("subgrpannouncecheck: community filter check fail"); - return 0; - } + /* If the attribute has originator-id and it is same as remote + peer's id. */ + if (onlypeer && riattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID) + && (IPV4_ADDR_SAME(&onlypeer->remote_id, &riattr->originator_id))) { + if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) + zlog_debug( + "%s [Update:SEND] %s originator-id is same as " + "remote router-id", + onlypeer->host, + prefix2str(p, buf, sizeof(buf))); + return 0; + } - /* If the attribute has originator-id and it is same as remote - peer's id. */ - if (onlypeer && - riattr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID) && - (IPV4_ADDR_SAME (&onlypeer->remote_id, &riattr->originator_id))) - { - if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) - zlog_debug ("%s [Update:SEND] %s originator-id is same as " - "remote router-id", - onlypeer->host, prefix2str (p, buf, sizeof (buf))); - return 0; - } - - /* ORF prefix-list filter check */ - if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) - && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV) - || CHECK_FLAG (peer->af_cap[afi][safi], - PEER_CAP_ORF_PREFIX_SM_OLD_RCV))) - if (peer->orf_plist[afi][safi]) - { - if (prefix_list_apply (peer->orf_plist[afi][safi], p) == PREFIX_DENY) - { - if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) - zlog_debug ("%s [Update:SEND] %s is filtered via ORF", - peer->host, prefix2str (p, buf, sizeof (buf))); - return 0; - } - } - - /* Output filter check. */ - if (bgp_output_filter (peer, p, riattr, afi, safi) == FILTER_DENY) - { - if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) - zlog_debug ("%s [Update:SEND] %s is filtered", - peer->host, prefix2str (p, buf, sizeof (buf))); - return 0; - } + /* ORF prefix-list filter check */ + if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) + && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV) + || CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_SM_OLD_RCV))) + if (peer->orf_plist[afi][safi]) { + if (prefix_list_apply(peer->orf_plist[afi][safi], p) + == PREFIX_DENY) { + if (bgp_debug_update(NULL, p, + subgrp->update_group, 0)) + zlog_debug( + "%s [Update:SEND] %s is filtered via ORF", + peer->host, + prefix2str(p, buf, + sizeof(buf))); + return 0; + } + } + + /* Output filter check. */ + if (bgp_output_filter(peer, p, riattr, afi, safi) == FILTER_DENY) { + if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) + zlog_debug("%s [Update:SEND] %s is filtered", + peer->host, prefix2str(p, buf, sizeof(buf))); + return 0; + } #ifdef BGP_SEND_ASPATH_CHECK - /* AS path loop check. */ - if (onlypeer && aspath_loop_check (riattr->aspath, onlypeer->as)) - { - if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) - zlog_debug ("%s [Update:SEND] suppress announcement to peer AS %u " - "that is part of AS path.", - onlypeer->host, onlypeer->as); - return 0; - } + /* AS path loop check. */ + if (onlypeer && aspath_loop_check(riattr->aspath, onlypeer->as)) { + if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) + zlog_debug( + "%s [Update:SEND] suppress announcement to peer AS %u " + "that is part of AS path.", + onlypeer->host, onlypeer->as); + return 0; + } #endif /* BGP_SEND_ASPATH_CHECK */ - /* If we're a CONFED we need to loop check the CONFED ID too */ - if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) - { - if (aspath_loop_check(riattr->aspath, bgp->confed_id)) - { - if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) - zlog_debug ("%s [Update:SEND] suppress announcement to peer AS %u" - " is AS path.", - peer->host, - bgp->confed_id); - return 0; + /* If we're a CONFED we need to loop check the CONFED ID too */ + if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) { + if (aspath_loop_check(riattr->aspath, bgp->confed_id)) { + if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) + zlog_debug( + "%s [Update:SEND] suppress announcement to peer AS %u" + " is AS path.", + peer->host, bgp->confed_id); + return 0; + } } - } - /* Route-Reflect check. */ - if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP) - reflect = 1; - else - reflect = 0; + /* Route-Reflect check. */ + if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP) + reflect = 1; + else + reflect = 0; + + /* IBGP reflection check. */ + if (reflect && !samepeer_safe) { + /* A route from a Client peer. */ + if (CHECK_FLAG(from->af_flags[afi][safi], + PEER_FLAG_REFLECTOR_CLIENT)) { + /* Reflect to all the Non-Client peers and also to the + Client peers other than the originator. Originator + check + is already done. So there is noting to do. */ + /* no bgp client-to-client reflection check. */ + if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT)) + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_REFLECTOR_CLIENT)) + return 0; + } else { + /* A route from a Non-client peer. Reflect to all other + clients. */ + if (!CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_REFLECTOR_CLIENT)) + return 0; + } + } - /* IBGP reflection check. */ - if (reflect && !samepeer_safe) - { - /* A route from a Client peer. */ - if (CHECK_FLAG (from->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) - { - /* Reflect to all the Non-Client peers and also to the - Client peers other than the originator. Originator check - is already done. So there is noting to do. */ - /* no bgp client-to-client reflection check. */ - if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT)) - if (CHECK_FLAG (peer->af_flags[afi][safi], - PEER_FLAG_REFLECTOR_CLIENT)) - return 0; - } - else - { - /* A route from a Non-client peer. Reflect to all other - clients. */ - if (! CHECK_FLAG (peer->af_flags[afi][safi], - PEER_FLAG_REFLECTOR_CLIENT)) - return 0; + /* For modify attribute, copy it to temporary structure. */ + bgp_attr_dup(attr, riattr); + + /* If local-preference is not set. */ + if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED) + && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) { + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF); + attr->local_pref = bgp->default_local_pref; } - } - /* For modify attribute, copy it to temporary structure. */ - bgp_attr_dup (attr, riattr); + /* If originator-id is not set and the route is to be reflected, + set the originator id */ + if (reflect + && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) { + IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id)); + SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID); + } - /* If local-preference is not set. */ - if ((peer->sort == BGP_PEER_IBGP - || peer->sort == BGP_PEER_CONFED) - && (! (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))) - { - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF); - attr->local_pref = bgp->default_local_pref; - } + /* Remove MED if its an EBGP peer - will get overwritten by route-maps + */ + if (peer->sort == BGP_PEER_EBGP + && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) { + if (from != bgp->peer_self && !transparent + && !CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MED_UNCHANGED)) + attr->flag &= + ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)); + } - /* If originator-id is not set and the route is to be reflected, - set the originator id */ - if (reflect && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) - { - IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id)); - SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID); - } + /* Since the nexthop attribute can vary per peer, it is not explicitly + * set + * in announce check, only certain flags and length (or number of + * nexthops + * -- for IPv6/MP_REACH) are set here in order to guide the update + * formation + * code in setting the nexthop(s) on a per peer basis in + * reformat_peer(). + * Typically, the source nexthop in the attribute is preserved but in + * the + * scenarios where we know it will always be overwritten, we reset the + * nexthop to "0" in an attempt to achieve better Update packing. An + * example of this is when a prefix from each of 2 IBGP peers needs to + * be + * announced to an EBGP peer (and they have the same attributes barring + * their nexthop). + */ + if (reflect) + SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED); + +#define NEXTHOP_IS_V6 \ + ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \ + && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \ + || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \ + && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN)) + + /* IPv6/MP starts with 1 nexthop. The link-local address is passed only + * if + * the peer (group) is configured to receive link-local nexthop + * unchanged + * and it is available in the prefix OR we're not reflecting the route + * and + * the peer (group) to whom we're going to announce is on a shared + * network + * and this is either a self-originated route or the peer is EBGP. + */ + if (NEXTHOP_IS_V6) { + attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; + if ((CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED) + && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local)) + || (!reflect && peer->shared_network + && (from == bgp->peer_self + || peer->sort == BGP_PEER_EBGP))) { + attr->mp_nexthop_len = + BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; + } - /* Remove MED if its an EBGP peer - will get overwritten by route-maps */ - if (peer->sort == BGP_PEER_EBGP - && attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) - { - if (from != bgp->peer_self && ! transparent - && ! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) - attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)); - } + /* Clear off link-local nexthop in source, whenever it is not + * needed to + * ensure more prefixes share the same attribute for + * announcement. + */ + if (!(CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED))) + memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN); + } - /* Since the nexthop attribute can vary per peer, it is not explicitly set - * in announce check, only certain flags and length (or number of nexthops - * -- for IPv6/MP_REACH) are set here in order to guide the update formation - * code in setting the nexthop(s) on a per peer basis in reformat_peer(). - * Typically, the source nexthop in the attribute is preserved but in the - * scenarios where we know it will always be overwritten, we reset the - * nexthop to "0" in an attempt to achieve better Update packing. An - * example of this is when a prefix from each of 2 IBGP peers needs to be - * announced to an EBGP peer (and they have the same attributes barring - * their nexthop). - */ - if (reflect) - SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED); - -#define NEXTHOP_IS_V6 (\ - (safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN &&\ - (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) || \ - ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) &&\ - attr->mp_nexthop_len >= IPV6_MAX_BYTELEN)) - - /* IPv6/MP starts with 1 nexthop. The link-local address is passed only if - * the peer (group) is configured to receive link-local nexthop unchanged - * and it is available in the prefix OR we're not reflecting the route and - * the peer (group) to whom we're going to announce is on a shared network - * and this is either a self-originated route or the peer is EBGP. - */ - if (NEXTHOP_IS_V6) - { - attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; - if ((CHECK_FLAG (peer->af_flags[afi][safi], - PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED) && - IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_local)) || - (!reflect && peer->shared_network && - (from == bgp->peer_self || peer->sort == BGP_PEER_EBGP))) - { - attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; - } - - /* Clear off link-local nexthop in source, whenever it is not needed to - * ensure more prefixes share the same attribute for announcement. - */ - if (!(CHECK_FLAG (peer->af_flags[afi][safi], - PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED))) - memset (&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN); - } + bgp_peer_remove_private_as(bgp, afi, safi, peer, attr); + bgp_peer_as_override(bgp, afi, safi, peer, attr); + + /* Route map & unsuppress-map apply. */ + if (ROUTE_MAP_OUT_NAME(filter) || (ri->extra && ri->extra->suppress)) { + struct bgp_info info; + struct attr dummy_attr; + + info.peer = peer; + info.attr = attr; + /* don't confuse inbound and outbound setting */ + RESET_FLAG(attr->rmap_change_flags); + + /* + * The route reflector is not allowed to modify the attributes + * of the reflected IBGP routes unless explicitly allowed. + */ + if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP) + && !bgp_flag_check(bgp, + BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) { + bgp_attr_dup(&dummy_attr, attr); + info.attr = &dummy_attr; + } - bgp_peer_remove_private_as(bgp, afi, safi, peer, attr); - bgp_peer_as_override(bgp, afi, safi, peer, attr); + SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT); - /* Route map & unsuppress-map apply. */ - if (ROUTE_MAP_OUT_NAME (filter) - || (ri->extra && ri->extra->suppress) ) - { - struct bgp_info info; - struct attr dummy_attr; - - info.peer = peer; - info.attr = attr; - /* don't confuse inbound and outbound setting */ - RESET_FLAG(attr->rmap_change_flags); - - /* - * The route reflector is not allowed to modify the attributes - * of the reflected IBGP routes unless explicitly allowed. - */ - if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP) - && !bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) - { - bgp_attr_dup (&dummy_attr, attr); - info.attr = &dummy_attr; - } - - SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT); - - if (ri->extra && ri->extra->suppress) - ret = route_map_apply (UNSUPPRESS_MAP (filter), p, RMAP_BGP, &info); - else - ret = route_map_apply (ROUTE_MAP_OUT (filter), p, RMAP_BGP, &info); - - peer->rmap_type = 0; - - if (ret == RMAP_DENYMATCH) - { - bgp_attr_flush (attr); - return 0; + if (ri->extra && ri->extra->suppress) + ret = route_map_apply(UNSUPPRESS_MAP(filter), p, + RMAP_BGP, &info); + else + ret = route_map_apply(ROUTE_MAP_OUT(filter), p, + RMAP_BGP, &info); + + peer->rmap_type = 0; + + if (ret == RMAP_DENYMATCH) { + bgp_attr_flush(attr); + return 0; + } } - } - /* After route-map has been applied, we check to see if the nexthop to - * be carried in the attribute (that is used for the announcement) can - * be cleared off or not. We do this in all cases where we would be - * setting the nexthop to "ourselves". For IPv6, we only need to consider - * the global nexthop here; the link-local nexthop would have been cleared - * already, and if not, it is required by the update formation code. - * Also see earlier comments in this function. - */ - /* - * If route-map has performed some operation on the nexthop or the peer - * configuration says to pass it unchanged, we cannot reset the nexthop - * here, so only attempt to do it if these aren't true. Note that the - * route-map handler itself might have cleared the nexthop, if for example, - * it is configured as 'peer-address'. - */ - if (!bgp_rmap_nhop_changed(attr->rmap_change_flags, - riattr->rmap_change_flags) && - !transparent && - !CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) - { - /* We can reset the nexthop, if setting (or forcing) it to 'self' */ - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF) || - CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_FORCE_NEXTHOP_SELF)) - { - if (!reflect || - CHECK_FLAG (peer->af_flags[afi][safi], - PEER_FLAG_FORCE_NEXTHOP_SELF)) - subgroup_announce_reset_nhop ((peer_cap_enhe(peer, afi, safi) ? - AF_INET6 : p->family), attr); - } - else if (peer->sort == BGP_PEER_EBGP) - { - /* Can also reset the nexthop if announcing to EBGP, but only if - * no peer in the subgroup is on a shared subnet. - * Note: 3rd party nexthop currently implemented for IPv4 only. - */ - SUBGRP_FOREACH_PEER (subgrp, paf) - { - if (bgp_multiaccess_check_v4 (riattr->nexthop, paf->peer)) - break; - } - if (!paf) - subgroup_announce_reset_nhop ((peer_cap_enhe(peer, afi, safi) ? AF_INET6 : p->family), attr); - } - /* If IPv6/MP and nexthop does not have any override and happens to - * be a link-local address, reset it so that we don't pass along the - * source's link-local IPv6 address to recipients who may not be on - * the same interface. - */ - if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) - { - if (IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_global)) - subgroup_announce_reset_nhop (AF_INET6, attr); - } - } + /* After route-map has been applied, we check to see if the nexthop to + * be carried in the attribute (that is used for the announcement) can + * be cleared off or not. We do this in all cases where we would be + * setting the nexthop to "ourselves". For IPv6, we only need to + * consider + * the global nexthop here; the link-local nexthop would have been + * cleared + * already, and if not, it is required by the update formation code. + * Also see earlier comments in this function. + */ + /* + * If route-map has performed some operation on the nexthop or the peer + * configuration says to pass it unchanged, we cannot reset the nexthop + * here, so only attempt to do it if these aren't true. Note that the + * route-map handler itself might have cleared the nexthop, if for + * example, + * it is configured as 'peer-address'. + */ + if (!bgp_rmap_nhop_changed(attr->rmap_change_flags, + riattr->rmap_change_flags) + && !transparent + && !CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_NEXTHOP_UNCHANGED)) { + /* We can reset the nexthop, if setting (or forcing) it to + * 'self' */ + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_NEXTHOP_SELF) + || CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_FORCE_NEXTHOP_SELF)) { + if (!reflect + || CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_FORCE_NEXTHOP_SELF)) + subgroup_announce_reset_nhop( + (peer_cap_enhe(peer, afi, safi) + ? AF_INET6 + : p->family), + attr); + } else if (peer->sort == BGP_PEER_EBGP) { + /* Can also reset the nexthop if announcing to EBGP, but + * only if + * no peer in the subgroup is on a shared subnet. + * Note: 3rd party nexthop currently implemented for + * IPv4 only. + */ + SUBGRP_FOREACH_PEER(subgrp, paf) + { + if (bgp_multiaccess_check_v4(riattr->nexthop, + paf->peer)) + break; + } + if (!paf) + subgroup_announce_reset_nhop( + (peer_cap_enhe(peer, afi, safi) + ? AF_INET6 + : p->family), + attr); + } + /* If IPv6/MP and nexthop does not have any override and happens + * to + * be a link-local address, reset it so that we don't pass along + * the + * source's link-local IPv6 address to recipients who may not be + * on + * the same interface. + */ + if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) { + if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) + subgroup_announce_reset_nhop(AF_INET6, attr); + } + } - return 1; + return 1; } -void -bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, - struct bgp_maxpaths_cfg *mpath_cfg, - struct bgp_info_pair *result, - afi_t afi, safi_t safi) -{ - struct bgp_info *new_select; - struct bgp_info *old_select; - struct bgp_info *ri; - struct bgp_info *ri1; - struct bgp_info *ri2; - struct bgp_info *nextri = NULL; - int paths_eq, do_mpath, debug; - struct list mp_list; - char pfx_buf[PREFIX2STR_BUFFER]; - char path_buf[PATH_ADDPATH_STR_BUFFER]; +void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, + struct bgp_maxpaths_cfg *mpath_cfg, + struct bgp_info_pair *result, afi_t afi, safi_t safi) +{ + struct bgp_info *new_select; + struct bgp_info *old_select; + struct bgp_info *ri; + struct bgp_info *ri1; + struct bgp_info *ri2; + struct bgp_info *nextri = NULL; + int paths_eq, do_mpath, debug; + struct list mp_list; + char pfx_buf[PREFIX2STR_BUFFER]; + char path_buf[PATH_ADDPATH_STR_BUFFER]; + + bgp_mp_list_init(&mp_list); + do_mpath = + (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1); + + debug = bgp_debug_bestpath(&rn->p); + + if (debug) + prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf)); + + /* bgp deterministic-med */ + new_select = NULL; + if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) { + + /* Clear BGP_INFO_DMED_SELECTED for all paths */ + for (ri1 = rn->info; ri1; ri1 = ri1->next) + bgp_info_unset_flag(rn, ri1, BGP_INFO_DMED_SELECTED); + + for (ri1 = rn->info; ri1; ri1 = ri1->next) { + if (CHECK_FLAG(ri1->flags, BGP_INFO_DMED_CHECK)) + continue; + if (BGP_INFO_HOLDDOWN(ri1)) + continue; + if (ri1->peer && ri1->peer != bgp->peer_self) + if (ri1->peer->status != Established) + continue; + + new_select = ri1; + if (ri1->next) { + for (ri2 = ri1->next; ri2; ri2 = ri2->next) { + if (CHECK_FLAG(ri2->flags, + BGP_INFO_DMED_CHECK)) + continue; + if (BGP_INFO_HOLDDOWN(ri2)) + continue; + if (ri2->peer + && ri2->peer != bgp->peer_self + && !CHECK_FLAG( + ri2->peer->sflags, + PEER_STATUS_NSF_WAIT)) + if (ri2->peer->status + != Established) + continue; + + if (aspath_cmp_left(ri1->attr->aspath, + ri2->attr->aspath) + || aspath_cmp_left_confed( + ri1->attr->aspath, + ri2->attr->aspath)) { + if (bgp_info_cmp(bgp, ri2, + new_select, + &paths_eq, + mpath_cfg, + debug, pfx_buf, + afi, safi)) { + bgp_info_unset_flag( + rn, new_select, + BGP_INFO_DMED_SELECTED); + new_select = ri2; + } + + bgp_info_set_flag( + rn, ri2, + BGP_INFO_DMED_CHECK); + } + } + } + bgp_info_set_flag(rn, new_select, BGP_INFO_DMED_CHECK); + bgp_info_set_flag(rn, new_select, + BGP_INFO_DMED_SELECTED); + + if (debug) { + bgp_info_path_with_addpath_rx_str(new_select, + path_buf); + zlog_debug("%s: %s is the bestpath from AS %d", + pfx_buf, path_buf, + aspath_get_first_as( + new_select->attr->aspath)); + } + } + } - bgp_mp_list_init (&mp_list); - do_mpath = (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1); + /* Check old selected route and new selected route. */ + old_select = NULL; + new_select = NULL; + for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1); + ri = nextri) { + if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) + old_select = ri; + + if (BGP_INFO_HOLDDOWN(ri)) { + /* reap REMOVED routes, if needs be + * selected route must stay for a while longer though + */ + if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED) + && (ri != old_select)) + bgp_info_reap(rn, ri); + + continue; + } - debug = bgp_debug_bestpath(&rn->p); + if (ri->peer && ri->peer != bgp->peer_self + && !CHECK_FLAG(ri->peer->sflags, PEER_STATUS_NSF_WAIT)) + if (ri->peer->status != Established) + continue; - if (debug) - prefix2str (&rn->p, pfx_buf, sizeof (pfx_buf)); + if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED) + && (!CHECK_FLAG(ri->flags, BGP_INFO_DMED_SELECTED))) { + bgp_info_unset_flag(rn, ri, BGP_INFO_DMED_CHECK); + continue; + } - /* bgp deterministic-med */ - new_select = NULL; - if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)) - { + bgp_info_unset_flag(rn, ri, BGP_INFO_DMED_CHECK); - /* Clear BGP_INFO_DMED_SELECTED for all paths */ - for (ri1 = rn->info; ri1; ri1 = ri1->next) - bgp_info_unset_flag (rn, ri1, BGP_INFO_DMED_SELECTED); - - for (ri1 = rn->info; ri1; ri1 = ri1->next) - { - if (CHECK_FLAG (ri1->flags, BGP_INFO_DMED_CHECK)) - continue; - if (BGP_INFO_HOLDDOWN (ri1)) - continue; - if (ri1->peer && ri1->peer != bgp->peer_self) - if (ri1->peer->status != Established) - continue; - - new_select = ri1; - if (ri1->next) - { - for (ri2 = ri1->next; ri2; ri2 = ri2->next) - { - if (CHECK_FLAG (ri2->flags, BGP_INFO_DMED_CHECK)) - continue; - if (BGP_INFO_HOLDDOWN (ri2)) - continue; - if (ri2->peer && - ri2->peer != bgp->peer_self && - !CHECK_FLAG (ri2->peer->sflags, PEER_STATUS_NSF_WAIT)) - if (ri2->peer->status != Established) - continue; - - if (aspath_cmp_left (ri1->attr->aspath, ri2->attr->aspath) - || aspath_cmp_left_confed (ri1->attr->aspath, - ri2->attr->aspath)) - { - if (bgp_info_cmp (bgp, ri2, new_select, &paths_eq, - mpath_cfg, debug, pfx_buf, afi, safi)) - { - bgp_info_unset_flag (rn, new_select, BGP_INFO_DMED_SELECTED); - new_select = ri2; - } - - bgp_info_set_flag (rn, ri2, BGP_INFO_DMED_CHECK); - } - } - } - bgp_info_set_flag (rn, new_select, BGP_INFO_DMED_CHECK); - bgp_info_set_flag (rn, new_select, BGP_INFO_DMED_SELECTED); - - if (debug) - { - bgp_info_path_with_addpath_rx_str (new_select, path_buf); - zlog_debug("%s: %s is the bestpath from AS %d", - pfx_buf, path_buf, aspath_get_first_as(new_select->attr->aspath)); - } - } - } + if (bgp_info_cmp(bgp, ri, new_select, &paths_eq, mpath_cfg, + debug, pfx_buf, afi, safi)) { + new_select = ri; + } + } - /* Check old selected route and new selected route. */ - old_select = NULL; - new_select = NULL; - for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1); ri = nextri) - { - if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) - old_select = ri; - - if (BGP_INFO_HOLDDOWN (ri)) - { - /* reap REMOVED routes, if needs be - * selected route must stay for a while longer though - */ - if (CHECK_FLAG (ri->flags, BGP_INFO_REMOVED) - && (ri != old_select)) - bgp_info_reap (rn, ri); - - continue; - } - - if (ri->peer && - ri->peer != bgp->peer_self && - !CHECK_FLAG (ri->peer->sflags, PEER_STATUS_NSF_WAIT)) - if (ri->peer->status != Established) - continue; - - if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED) - && (! CHECK_FLAG (ri->flags, BGP_INFO_DMED_SELECTED))) - { - bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_CHECK); - continue; - } - - bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_CHECK); - - if (bgp_info_cmp (bgp, ri, new_select, &paths_eq, mpath_cfg, - debug, pfx_buf, afi, safi)) - { - new_select = ri; + /* Now that we know which path is the bestpath see if any of the other + * paths + * qualify as multipaths + */ + if (debug) { + if (new_select) + bgp_info_path_with_addpath_rx_str(new_select, path_buf); + else + sprintf(path_buf, "NONE"); + zlog_debug( + "%s: After path selection, newbest is %s oldbest was %s", + pfx_buf, path_buf, + old_select ? old_select->peer->host : "NONE"); } - } - - /* Now that we know which path is the bestpath see if any of the other paths - * qualify as multipaths - */ - if (debug) - { - if (new_select) - bgp_info_path_with_addpath_rx_str (new_select, path_buf); - else - sprintf (path_buf, "NONE"); - zlog_debug("%s: After path selection, newbest is %s oldbest was %s", - pfx_buf, path_buf, - old_select ? old_select->peer->host : "NONE"); - } - if (do_mpath && new_select) - { - for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1); ri = nextri) - { - - if (debug) - bgp_info_path_with_addpath_rx_str (ri, path_buf); - - if (ri == new_select) - { - if (debug) - zlog_debug("%s: %s is the bestpath, add to the multipath list", - pfx_buf, path_buf); - bgp_mp_list_add (&mp_list, ri); - continue; - } - - if (BGP_INFO_HOLDDOWN (ri)) - continue; - - if (ri->peer && - ri->peer != bgp->peer_self && - !CHECK_FLAG (ri->peer->sflags, PEER_STATUS_NSF_WAIT)) - if (ri->peer->status != Established) - continue; - - if (!bgp_info_nexthop_cmp (ri, new_select)) - { - if (debug) - zlog_debug("%s: %s has the same nexthop as the bestpath, skip it", - pfx_buf, path_buf); - continue; - } - - bgp_info_cmp (bgp, ri, new_select, &paths_eq, mpath_cfg, - debug, pfx_buf, afi, safi); - - if (paths_eq) - { - if (debug) - zlog_debug("%s: %s is equivalent to the bestpath, add to the multipath list", - pfx_buf, path_buf); - bgp_mp_list_add (&mp_list, ri); - } - } - } + if (do_mpath && new_select) { + for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1); + ri = nextri) { + + if (debug) + bgp_info_path_with_addpath_rx_str(ri, path_buf); + + if (ri == new_select) { + if (debug) + zlog_debug( + "%s: %s is the bestpath, add to the multipath list", + pfx_buf, path_buf); + bgp_mp_list_add(&mp_list, ri); + continue; + } + + if (BGP_INFO_HOLDDOWN(ri)) + continue; + + if (ri->peer && ri->peer != bgp->peer_self + && !CHECK_FLAG(ri->peer->sflags, + PEER_STATUS_NSF_WAIT)) + if (ri->peer->status != Established) + continue; + + if (!bgp_info_nexthop_cmp(ri, new_select)) { + if (debug) + zlog_debug( + "%s: %s has the same nexthop as the bestpath, skip it", + pfx_buf, path_buf); + continue; + } + + bgp_info_cmp(bgp, ri, new_select, &paths_eq, mpath_cfg, + debug, pfx_buf, afi, safi); + + if (paths_eq) { + if (debug) + zlog_debug( + "%s: %s is equivalent to the bestpath, add to the multipath list", + pfx_buf, path_buf); + bgp_mp_list_add(&mp_list, ri); + } + } + } - bgp_info_mpath_update (rn, new_select, old_select, &mp_list, mpath_cfg); - bgp_info_mpath_aggregate_update (new_select, old_select); - bgp_mp_list_clear (&mp_list); + bgp_info_mpath_update(rn, new_select, old_select, &mp_list, mpath_cfg); + bgp_info_mpath_aggregate_update(new_select, old_select); + bgp_mp_list_clear(&mp_list); - result->old = old_select; - result->new = new_select; + result->old = old_select; + result->new = new_select; - return; + return; } /* * A new route/change in bestpath of an existing route. Evaluate the path * for advertisement to the subgroup. */ -int -subgroup_process_announce_selected (struct update_subgroup *subgrp, - struct bgp_info *selected, - struct bgp_node *rn, - u_int32_t addpath_tx_id) -{ - struct prefix *p; - struct peer *onlypeer; - struct attr attr; - afi_t afi; - safi_t safi; - - p = &rn->p; - afi = SUBGRP_AFI(subgrp); - safi = SUBGRP_SAFI(subgrp); - onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? - (SUBGRP_PFIRST(subgrp))->peer : NULL); - - /* First update is deferred until ORF or ROUTE-REFRESH is received */ - if (onlypeer && CHECK_FLAG (onlypeer->af_sflags[afi][safi], - PEER_STATUS_ORF_WAIT_REFRESH)) - return 0; - - memset(&attr, 0, sizeof(struct attr)); - /* It's initialized in bgp_announce_check() */ - - /* Announcement to the subgroup. If the route is filtered withdraw it. */ - if (selected) - { - if (subgroup_announce_check(rn, selected, subgrp, p, &attr)) - bgp_adj_out_set_subgroup(rn, subgrp, &attr, selected); - else - bgp_adj_out_unset_subgroup(rn, subgrp, 1, selected->addpath_tx_id); - } +int subgroup_process_announce_selected(struct update_subgroup *subgrp, + struct bgp_info *selected, + struct bgp_node *rn, + u_int32_t addpath_tx_id) +{ + struct prefix *p; + struct peer *onlypeer; + struct attr attr; + afi_t afi; + safi_t safi; - /* If selected is NULL we must withdraw the path using addpath_tx_id */ - else - { - bgp_adj_out_unset_subgroup(rn, subgrp, 1, addpath_tx_id); - } + p = &rn->p; + afi = SUBGRP_AFI(subgrp); + safi = SUBGRP_SAFI(subgrp); + onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer + : NULL); + + /* First update is deferred until ORF or ROUTE-REFRESH is received */ + if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi], + PEER_STATUS_ORF_WAIT_REFRESH)) + return 0; + + memset(&attr, 0, sizeof(struct attr)); + /* It's initialized in bgp_announce_check() */ + + /* Announcement to the subgroup. If the route is filtered withdraw it. + */ + if (selected) { + if (subgroup_announce_check(rn, selected, subgrp, p, &attr)) + bgp_adj_out_set_subgroup(rn, subgrp, &attr, selected); + else + bgp_adj_out_unset_subgroup(rn, subgrp, 1, + selected->addpath_tx_id); + } + + /* If selected is NULL we must withdraw the path using addpath_tx_id */ + else { + bgp_adj_out_unset_subgroup(rn, subgrp, 1, addpath_tx_id); + } - return 0; + return 0; } /* * Clear IGP changed flag and attribute changed flag for a route (all paths). * This is called at the end of route processing. */ -void -bgp_zebra_clear_route_change_flags (struct bgp_node *rn) +void bgp_zebra_clear_route_change_flags(struct bgp_node *rn) { - struct bgp_info *ri; + struct bgp_info *ri; - for (ri = rn->info; ri; ri = ri->next) - { - if (BGP_INFO_HOLDDOWN (ri)) - continue; - UNSET_FLAG (ri->flags, BGP_INFO_IGP_CHANGED); - UNSET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED); - } + for (ri = rn->info; ri; ri = ri->next) { + if (BGP_INFO_HOLDDOWN(ri)) + continue; + UNSET_FLAG(ri->flags, BGP_INFO_IGP_CHANGED); + UNSET_FLAG(ri->flags, BGP_INFO_ATTR_CHANGED); + } } /* @@ -1948,1299 +1962,1293 @@ bgp_zebra_clear_route_change_flags (struct bgp_node *rn) * if the route selection returns the same best route as earlier - to * determine if we need to update zebra or not. */ -int -bgp_zebra_has_route_changed (struct bgp_node *rn, struct bgp_info *selected) -{ - struct bgp_info *mpinfo; - - /* If this is multipath, check all selected paths for any nexthop change or - * attribute change. Some attribute changes (e.g., community) aren't of - * relevance to the RIB, but we'll update zebra to ensure we handle the - * case of BGP nexthop change. This is the behavior when the best path has - * an attribute change anyway. - */ - if (CHECK_FLAG (selected->flags, BGP_INFO_IGP_CHANGED) || - CHECK_FLAG (selected->flags, BGP_INFO_MULTIPATH_CHG)) - return 1; - - /* If this is multipath, check all selected paths for any nexthop change */ - for (mpinfo = bgp_info_mpath_first (selected); mpinfo; - mpinfo = bgp_info_mpath_next (mpinfo)) - { - if (CHECK_FLAG (mpinfo->flags, BGP_INFO_IGP_CHANGED) - || CHECK_FLAG (mpinfo->flags, BGP_INFO_ATTR_CHANGED)) - return 1; - } +int bgp_zebra_has_route_changed(struct bgp_node *rn, struct bgp_info *selected) +{ + struct bgp_info *mpinfo; + + /* If this is multipath, check all selected paths for any nexthop change + * or + * attribute change. Some attribute changes (e.g., community) aren't of + * relevance to the RIB, but we'll update zebra to ensure we handle the + * case of BGP nexthop change. This is the behavior when the best path + * has + * an attribute change anyway. + */ + if (CHECK_FLAG(selected->flags, BGP_INFO_IGP_CHANGED) + || CHECK_FLAG(selected->flags, BGP_INFO_MULTIPATH_CHG)) + return 1; + + /* If this is multipath, check all selected paths for any nexthop change + */ + for (mpinfo = bgp_info_mpath_first(selected); mpinfo; + mpinfo = bgp_info_mpath_next(mpinfo)) { + if (CHECK_FLAG(mpinfo->flags, BGP_INFO_IGP_CHANGED) + || CHECK_FLAG(mpinfo->flags, BGP_INFO_ATTR_CHANGED)) + return 1; + } - /* Nothing has changed from the RIB's perspective. */ - return 0; + /* Nothing has changed from the RIB's perspective. */ + return 0; } -struct bgp_process_queue -{ - struct bgp *bgp; - struct bgp_node *rn; - afi_t afi; - safi_t safi; +struct bgp_process_queue { + struct bgp *bgp; + struct bgp_node *rn; + afi_t afi; + safi_t safi; }; -static wq_item_status -bgp_process_main (struct work_queue *wq, void *data) -{ - struct bgp_process_queue *pq = data; - struct bgp *bgp = pq->bgp; - struct bgp_node *rn = pq->rn; - afi_t afi = pq->afi; - safi_t safi = pq->safi; - struct prefix *p = &rn->p; - struct bgp_info *new_select; - struct bgp_info *old_select; - struct bgp_info_pair old_and_new; - - /* Is it end of initial update? (after startup) */ - if (!rn) - { - quagga_timestamp(3, bgp->update_delay_zebra_resume_time, - sizeof(bgp->update_delay_zebra_resume_time)); - - bgp->main_zebra_update_hold = 0; - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - if (bgp_fibupd_safi(safi)) - bgp_zebra_announce_table(bgp, afi, safi); - } - bgp->main_peers_update_hold = 0; - - bgp_start_routeadv(bgp); - return WQ_SUCCESS; - } +static wq_item_status bgp_process_main(struct work_queue *wq, void *data) +{ + struct bgp_process_queue *pq = data; + struct bgp *bgp = pq->bgp; + struct bgp_node *rn = pq->rn; + afi_t afi = pq->afi; + safi_t safi = pq->safi; + struct prefix *p = &rn->p; + struct bgp_info *new_select; + struct bgp_info *old_select; + struct bgp_info_pair old_and_new; + + /* Is it end of initial update? (after startup) */ + if (!rn) { + quagga_timestamp(3, bgp->update_delay_zebra_resume_time, + sizeof(bgp->update_delay_zebra_resume_time)); + + bgp->main_zebra_update_hold = 0; + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + if (bgp_fibupd_safi(safi)) + bgp_zebra_announce_table(bgp, afi, + safi); + } + bgp->main_peers_update_hold = 0; + + bgp_start_routeadv(bgp); + return WQ_SUCCESS; + } - /* Best path selection. */ - bgp_best_selection (bgp, rn, &bgp->maxpaths[afi][safi], - &old_and_new, afi, safi); - old_select = old_and_new.old; - new_select = old_and_new.new; - - /* Do we need to allocate or free labels? - * Right now, since we only deal with per-prefix labels, it is not necessary - * to do this upon changes to best path except of the label index changes. - */ - if (safi == SAFI_UNICAST) - { - if (new_select) - { - if (!old_select || - bgp_label_index_differs (new_select, old_select) || - new_select->sub_type != old_select->sub_type) - { - if (new_select->sub_type == BGP_ROUTE_STATIC && - new_select->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID) && - new_select->attr->label_index != BGP_INVALID_LABEL_INDEX) - { - if (CHECK_FLAG (rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) - bgp_unregister_for_label (rn); - label_ntop (MPLS_IMP_NULL_LABEL, 1, &rn->local_label); - bgp_set_valid_label(&rn->local_label); - } - else - bgp_register_for_label (rn, new_select); - } - } - else if (CHECK_FLAG (rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) - bgp_unregister_for_label (rn); - } + /* Best path selection. */ + bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new, + afi, safi); + old_select = old_and_new.old; + new_select = old_and_new.new; + + /* Do we need to allocate or free labels? + * Right now, since we only deal with per-prefix labels, it is not + * necessary + * to do this upon changes to best path except of the label index + * changes. + */ + if (safi == SAFI_UNICAST) { + if (new_select) { + if (!old_select + || bgp_label_index_differs(new_select, old_select) + || new_select->sub_type != old_select->sub_type) { + if (new_select->sub_type == BGP_ROUTE_STATIC + && new_select->attr->flag + & ATTR_FLAG_BIT( + BGP_ATTR_PREFIX_SID) + && new_select->attr->label_index + != BGP_INVALID_LABEL_INDEX) { + if (CHECK_FLAG( + rn->flags, + BGP_NODE_REGISTERED_FOR_LABEL)) + bgp_unregister_for_label(rn); + label_ntop(MPLS_IMP_NULL_LABEL, 1, + &rn->local_label); + bgp_set_valid_label(&rn->local_label); + } else + bgp_register_for_label(rn, new_select); + } + } else if (CHECK_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL)) + bgp_unregister_for_label(rn); + } - /* If best route remains the same and this is not due to user-initiated - * clear, see exactly what needs to be done. - */ + /* If best route remains the same and this is not due to user-initiated + * clear, see exactly what needs to be done. + */ - if (old_select && old_select == new_select && - !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR) && - !CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED) && - !bgp->addpath_tx_used[afi][safi]) - { - if (bgp_zebra_has_route_changed (rn, old_select)) - { + if (old_select && old_select == new_select + && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR) + && !CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED) + && !bgp->addpath_tx_used[afi][safi]) { + if (bgp_zebra_has_route_changed(rn, old_select)) { #if ENABLE_BGP_VNC - vnc_import_bgp_add_route(bgp, p, old_select); - vnc_import_bgp_exterior_add_route(bgp, p, old_select); + vnc_import_bgp_add_route(bgp, p, old_select); + vnc_import_bgp_exterior_add_route(bgp, p, old_select); #endif - if (bgp_fibupd_safi(safi) && - !bgp->name && - !bgp_option_check (BGP_OPT_NO_FIB) && - new_select->type == ZEBRA_ROUTE_BGP && - new_select->sub_type == BGP_ROUTE_NORMAL) - bgp_zebra_announce (rn, p, old_select, bgp, afi, safi); - } - UNSET_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG); - bgp_zebra_clear_route_change_flags (rn); - - /* If there is a change of interest to peers, reannounce the route. */ - if (CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED) || - CHECK_FLAG (rn->flags, BGP_NODE_LABEL_CHANGED)) - { - group_announce_route(bgp, afi, safi, rn, new_select); - - /* unicast routes must also be annouced to labeled-unicast update-groups */ - if (safi == SAFI_UNICAST) - group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, rn, new_select); - - UNSET_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED); - UNSET_FLAG (rn->flags, BGP_NODE_LABEL_CHANGED); - } - - UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED); - return WQ_SUCCESS; - } + if (bgp_fibupd_safi(safi) && !bgp->name + && !bgp_option_check(BGP_OPT_NO_FIB) + && new_select->type == ZEBRA_ROUTE_BGP + && new_select->sub_type == BGP_ROUTE_NORMAL) + bgp_zebra_announce(rn, p, old_select, bgp, afi, + safi); + } + UNSET_FLAG(old_select->flags, BGP_INFO_MULTIPATH_CHG); + bgp_zebra_clear_route_change_flags(rn); + + /* If there is a change of interest to peers, reannounce the + * route. */ + if (CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED) + || CHECK_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED)) { + group_announce_route(bgp, afi, safi, rn, new_select); + + /* unicast routes must also be annouced to + * labeled-unicast update-groups */ + if (safi == SAFI_UNICAST) + group_announce_route(bgp, afi, + SAFI_LABELED_UNICAST, rn, + new_select); + + UNSET_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED); + UNSET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED); + } - /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set */ - UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR); + UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED); + return WQ_SUCCESS; + } - /* bestpath has changed; bump version */ - if (old_select || new_select) - { - bgp_bump_version(rn); - - if (!bgp->t_rmap_def_originate_eval) - { - bgp_lock (bgp); - thread_add_timer(bm->master, - update_group_refresh_default_originate_route_map, - bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER, - &bgp->t_rmap_def_originate_eval); - } - } + /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set + */ + UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR); + + /* bestpath has changed; bump version */ + if (old_select || new_select) { + bgp_bump_version(rn); + + if (!bgp->t_rmap_def_originate_eval) { + bgp_lock(bgp); + thread_add_timer( + bm->master, + update_group_refresh_default_originate_route_map, + bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER, + &bgp->t_rmap_def_originate_eval); + } + } - if (old_select) - bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED); - if (new_select) - { - bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED); - bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED); - UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG); - } + if (old_select) + bgp_info_unset_flag(rn, old_select, BGP_INFO_SELECTED); + if (new_select) { + bgp_info_set_flag(rn, new_select, BGP_INFO_SELECTED); + bgp_info_unset_flag(rn, new_select, BGP_INFO_ATTR_CHANGED); + UNSET_FLAG(new_select->flags, BGP_INFO_MULTIPATH_CHG); + } #if ENABLE_BGP_VNC - if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { - if (old_select != new_select) { - if (old_select) { - vnc_import_bgp_exterior_del_route(bgp, p, old_select); - vnc_import_bgp_del_route(bgp, p, old_select); - } - if (new_select) { - vnc_import_bgp_exterior_add_route(bgp, p, new_select); - vnc_import_bgp_add_route(bgp, p, new_select); - } - } - } + if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { + if (old_select != new_select) { + if (old_select) { + vnc_import_bgp_exterior_del_route(bgp, p, + old_select); + vnc_import_bgp_del_route(bgp, p, old_select); + } + if (new_select) { + vnc_import_bgp_exterior_add_route(bgp, p, + new_select); + vnc_import_bgp_add_route(bgp, p, new_select); + } + } + } #endif - group_announce_route(bgp, afi, safi, rn, new_select); - - /* unicast routes must also be annouced to labeled-unicast update-groups */ - if (safi == SAFI_UNICAST) - group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, rn, new_select); - - /* FIB update. */ - if (bgp_fibupd_safi(safi) && - (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW) && - !bgp_option_check (BGP_OPT_NO_FIB)) - { - if (new_select - && new_select->type == ZEBRA_ROUTE_BGP - && (new_select->sub_type == BGP_ROUTE_NORMAL || - new_select->sub_type == BGP_ROUTE_AGGREGATE)) - bgp_zebra_announce (rn, p, new_select, bgp, afi, safi); - else - { - /* Withdraw the route from the kernel. */ - if (old_select - && old_select->type == ZEBRA_ROUTE_BGP - && (old_select->sub_type == BGP_ROUTE_NORMAL || - old_select->sub_type == BGP_ROUTE_AGGREGATE)) - bgp_zebra_withdraw (p, old_select, safi); + group_announce_route(bgp, afi, safi, rn, new_select); + + /* unicast routes must also be annouced to labeled-unicast update-groups + */ + if (safi == SAFI_UNICAST) + group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, rn, + new_select); + + /* FIB update. */ + if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW) + && !bgp_option_check(BGP_OPT_NO_FIB)) { + if (new_select && new_select->type == ZEBRA_ROUTE_BGP + && (new_select->sub_type == BGP_ROUTE_NORMAL + || new_select->sub_type == BGP_ROUTE_AGGREGATE)) + bgp_zebra_announce(rn, p, new_select, bgp, afi, safi); + else { + /* Withdraw the route from the kernel. */ + if (old_select && old_select->type == ZEBRA_ROUTE_BGP + && (old_select->sub_type == BGP_ROUTE_NORMAL + || old_select->sub_type == BGP_ROUTE_AGGREGATE)) + bgp_zebra_withdraw(p, old_select, safi); + } } - } - /* Clear any route change flags. */ - bgp_zebra_clear_route_change_flags (rn); + /* Clear any route change flags. */ + bgp_zebra_clear_route_change_flags(rn); - /* Reap old select bgp_info, if it has been removed */ - if (old_select && CHECK_FLAG (old_select->flags, BGP_INFO_REMOVED)) - bgp_info_reap (rn, old_select); - - UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED); - return WQ_SUCCESS; + /* Reap old select bgp_info, if it has been removed */ + if (old_select && CHECK_FLAG(old_select->flags, BGP_INFO_REMOVED)) + bgp_info_reap(rn, old_select); + + UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED); + return WQ_SUCCESS; } -static void -bgp_processq_del (struct work_queue *wq, void *data) +static void bgp_processq_del(struct work_queue *wq, void *data) { - struct bgp_process_queue *pq = data; - struct bgp_table *table; + struct bgp_process_queue *pq = data; + struct bgp_table *table; - bgp_unlock (pq->bgp); - if (pq->rn) - { - table = bgp_node_table (pq->rn); - bgp_unlock_node (pq->rn); - bgp_table_unlock (table); - } - XFREE (MTYPE_BGP_PROCESS_QUEUE, pq); + bgp_unlock(pq->bgp); + if (pq->rn) { + table = bgp_node_table(pq->rn); + bgp_unlock_node(pq->rn); + bgp_table_unlock(table); + } + XFREE(MTYPE_BGP_PROCESS_QUEUE, pq); } -void -bgp_process_queue_init (void) +void bgp_process_queue_init(void) { - if (!bm->process_main_queue) - { - bm->process_main_queue - = work_queue_new (bm->master, "process_main_queue"); - - if ( !bm->process_main_queue) - { - zlog_err ("%s: Failed to allocate work queue", __func__); - exit (1); - } - } - - bm->process_main_queue->spec.workfunc = &bgp_process_main; - bm->process_main_queue->spec.del_item_data = &bgp_processq_del; - bm->process_main_queue->spec.max_retries = 0; - bm->process_main_queue->spec.hold = 50; - /* Use a higher yield value of 50ms for main queue processing */ - bm->process_main_queue->spec.yield = 50 * 1000L; + if (!bm->process_main_queue) { + bm->process_main_queue = + work_queue_new(bm->master, "process_main_queue"); + + if (!bm->process_main_queue) { + zlog_err("%s: Failed to allocate work queue", __func__); + exit(1); + } + } + + bm->process_main_queue->spec.workfunc = &bgp_process_main; + bm->process_main_queue->spec.del_item_data = &bgp_processq_del; + bm->process_main_queue->spec.max_retries = 0; + bm->process_main_queue->spec.hold = 50; + /* Use a higher yield value of 50ms for main queue processing */ + bm->process_main_queue->spec.yield = 50 * 1000L; } -void -bgp_process (struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi) +void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi) { - struct bgp_process_queue *pqnode; - - /* already scheduled for processing? */ - if (CHECK_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED)) - return; + struct bgp_process_queue *pqnode; - if (bm->process_main_queue == NULL) - return; + /* already scheduled for processing? */ + if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED)) + return; - pqnode = XCALLOC (MTYPE_BGP_PROCESS_QUEUE, - sizeof (struct bgp_process_queue)); - if (!pqnode) - return; + if (bm->process_main_queue == NULL) + return; + + pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE, + sizeof(struct bgp_process_queue)); + if (!pqnode) + return; - /* all unlocked in bgp_processq_del */ - bgp_table_lock (bgp_node_table (rn)); - pqnode->rn = bgp_lock_node (rn); - pqnode->bgp = bgp; - bgp_lock (bgp); - pqnode->afi = afi; - pqnode->safi = safi; - work_queue_add (bm->process_main_queue, pqnode); - SET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED); - return; + /* all unlocked in bgp_processq_del */ + bgp_table_lock(bgp_node_table(rn)); + pqnode->rn = bgp_lock_node(rn); + pqnode->bgp = bgp; + bgp_lock(bgp); + pqnode->afi = afi; + pqnode->safi = safi; + work_queue_add(bm->process_main_queue, pqnode); + SET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED); + return; } -void -bgp_add_eoiu_mark (struct bgp *bgp) +void bgp_add_eoiu_mark(struct bgp *bgp) { - struct bgp_process_queue *pqnode; + struct bgp_process_queue *pqnode; - if (bm->process_main_queue == NULL) - return; + if (bm->process_main_queue == NULL) + return; - pqnode = XCALLOC (MTYPE_BGP_PROCESS_QUEUE, - sizeof (struct bgp_process_queue)); - if (!pqnode) - return; + pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE, + sizeof(struct bgp_process_queue)); + if (!pqnode) + return; - pqnode->rn = NULL; - pqnode->bgp = bgp; - bgp_lock (bgp); - work_queue_add (bm->process_main_queue, pqnode); + pqnode->rn = NULL; + pqnode->bgp = bgp; + bgp_lock(bgp); + work_queue_add(bm->process_main_queue, pqnode); } -static int -bgp_maximum_prefix_restart_timer (struct thread *thread) +static int bgp_maximum_prefix_restart_timer(struct thread *thread) { - struct peer *peer; + struct peer *peer; - peer = THREAD_ARG (thread); - peer->t_pmax_restart = NULL; + peer = THREAD_ARG(thread); + peer->t_pmax_restart = NULL; - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Maximum-prefix restart timer expired, restore peering", - peer->host); + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Maximum-prefix restart timer expired, restore peering", + peer->host); - peer_clear (peer, NULL); + peer_clear(peer, NULL); - return 0; + return 0; } -int -bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi, - safi_t safi, int always) +int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi, + int always) { - iana_afi_t pkt_afi; - safi_t pkt_safi; + iana_afi_t pkt_afi; + safi_t pkt_safi; - if (!CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) - return 0; + if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) + return 0; - if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) - { - if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT) - && ! always) - return 0; - - zlog_info ("%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, " - "limit %ld", afi_safi_print (afi, safi), peer->host, - peer->pcount[afi][safi], peer->pmax[afi][safi]); - SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT); - - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)) - return 0; - - /* Convert AFI, SAFI to values for packet. */ - pkt_afi = afi_int2iana (afi); - pkt_safi = safi_int2iana (safi); - { - u_int8_t ndata[7]; - - ndata[0] = (pkt_afi >> 8); - ndata[1] = pkt_afi; - ndata[2] = pkt_safi; - ndata[3] = (peer->pmax[afi][safi] >> 24); - ndata[4] = (peer->pmax[afi][safi] >> 16); - ndata[5] = (peer->pmax[afi][safi] >> 8); - ndata[6] = (peer->pmax[afi][safi]); - - SET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW); - bgp_notify_send_with_data (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_MAX_PREFIX, ndata, 7); - } - - /* Dynamic peers will just close their connection. */ - if (peer_dynamic_neighbor (peer)) - return 1; - - /* restart timer start */ - if (peer->pmax_restart[afi][safi]) - { - peer->v_pmax_restart = peer->pmax_restart[afi][safi] * 60; - - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Maximum-prefix restart timer started for %d secs", - peer->host, peer->v_pmax_restart); - - BGP_TIMER_ON (peer->t_pmax_restart, bgp_maximum_prefix_restart_timer, - peer->v_pmax_restart); - } - - return 1; - } - else - UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT); + if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) { + if (CHECK_FLAG(peer->af_sflags[afi][safi], + PEER_STATUS_PREFIX_LIMIT) + && !always) + return 0; - if (peer->pcount[afi][safi] > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) - { - if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD) - && ! always) - return 0; - - zlog_info ("%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld", - afi_safi_print (afi, safi), peer->host, peer->pcount[afi][safi], - peer->pmax[afi][safi]); - SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD); - } - else - UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD); - return 0; + zlog_info( + "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, " + "limit %ld", + afi_safi_print(afi, safi), peer->host, + peer->pcount[afi][safi], peer->pmax[afi][safi]); + SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT); + + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING)) + return 0; + + /* Convert AFI, SAFI to values for packet. */ + pkt_afi = afi_int2iana(afi); + pkt_safi = safi_int2iana(safi); + { + u_int8_t ndata[7]; + + ndata[0] = (pkt_afi >> 8); + ndata[1] = pkt_afi; + ndata[2] = pkt_safi; + ndata[3] = (peer->pmax[afi][safi] >> 24); + ndata[4] = (peer->pmax[afi][safi] >> 16); + ndata[5] = (peer->pmax[afi][safi] >> 8); + ndata[6] = (peer->pmax[afi][safi]); + + SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW); + bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_MAX_PREFIX, + ndata, 7); + } + + /* Dynamic peers will just close their connection. */ + if (peer_dynamic_neighbor(peer)) + return 1; + + /* restart timer start */ + if (peer->pmax_restart[afi][safi]) { + peer->v_pmax_restart = + peer->pmax_restart[afi][safi] * 60; + + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Maximum-prefix restart timer started for %d secs", + peer->host, peer->v_pmax_restart); + + BGP_TIMER_ON(peer->t_pmax_restart, + bgp_maximum_prefix_restart_timer, + peer->v_pmax_restart); + } + + return 1; + } else + UNSET_FLAG(peer->af_sflags[afi][safi], + PEER_STATUS_PREFIX_LIMIT); + + if (peer->pcount[afi][safi] + > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) { + if (CHECK_FLAG(peer->af_sflags[afi][safi], + PEER_STATUS_PREFIX_THRESHOLD) + && !always) + return 0; + + zlog_info( + "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld", + afi_safi_print(afi, safi), peer->host, + peer->pcount[afi][safi], peer->pmax[afi][safi]); + SET_FLAG(peer->af_sflags[afi][safi], + PEER_STATUS_PREFIX_THRESHOLD); + } else + UNSET_FLAG(peer->af_sflags[afi][safi], + PEER_STATUS_PREFIX_THRESHOLD); + return 0; } /* Unconditionally remove the route from the RIB, without taking * damping into consideration (eg, because the session went down) */ -static void -bgp_rib_remove (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer, - afi_t afi, safi_t safi) +static void bgp_rib_remove(struct bgp_node *rn, struct bgp_info *ri, + struct peer *peer, afi_t afi, safi_t safi) { - bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi); - - if (!CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) - bgp_info_delete (rn, ri); /* keep historical info */ - - bgp_process (peer->bgp, rn, afi, safi); -} - -static void -bgp_rib_withdraw (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer, - afi_t afi, safi_t safi, struct prefix_rd *prd) -{ - int status = BGP_DAMP_NONE; - - /* apply dampening, if result is suppressed, we'll be retaining - * the bgp_info in the RIB for historical reference. - */ - if (CHECK_FLAG (peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) - && peer->sort == BGP_PEER_EBGP) - if ( (status = bgp_damp_withdraw (ri, rn, afi, safi, 0)) - == BGP_DAMP_SUPPRESSED) - { - bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi); - return; - } - + bgp_aggregate_decrement(peer->bgp, &rn->p, ri, afi, safi); + + if (!CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) + bgp_info_delete(rn, ri); /* keep historical info */ + + bgp_process(peer->bgp, rn, afi, safi); +} + +static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_info *ri, + struct peer *peer, afi_t afi, safi_t safi, + struct prefix_rd *prd) +{ + int status = BGP_DAMP_NONE; + + /* apply dampening, if result is suppressed, we'll be retaining + * the bgp_info in the RIB for historical reference. + */ + if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) + && peer->sort == BGP_PEER_EBGP) + if ((status = bgp_damp_withdraw(ri, rn, afi, safi, 0)) + == BGP_DAMP_SUPPRESSED) { + bgp_aggregate_decrement(peer->bgp, &rn->p, ri, afi, + safi); + return; + } + #if ENABLE_BGP_VNC - if (safi == SAFI_MPLS_VPN) { - struct bgp_node *prn = NULL; - struct bgp_table *table = NULL; - - prn = bgp_node_get(peer->bgp->rib[afi][safi], (struct prefix *) prd); - if (prn->info) { - table = (struct bgp_table *)(prn->info); - - vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( - peer->bgp, - prd, - table, - &rn->p, - ri); - } - bgp_unlock_node(prn); - } - if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { - if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) { + if (safi == SAFI_MPLS_VPN) { + struct bgp_node *prn = NULL; + struct bgp_table *table = NULL; + + prn = bgp_node_get(peer->bgp->rib[afi][safi], + (struct prefix *)prd); + if (prn->info) { + table = (struct bgp_table *)(prn->info); + + vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( + peer->bgp, prd, table, &rn->p, ri); + } + bgp_unlock_node(prn); + } + if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { + if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) { - vnc_import_bgp_del_route(peer->bgp, &rn->p, ri); - vnc_import_bgp_exterior_del_route(peer->bgp, &rn->p, ri); + vnc_import_bgp_del_route(peer->bgp, &rn->p, ri); + vnc_import_bgp_exterior_del_route(peer->bgp, &rn->p, + ri); + } } - } -#endif +#endif - /* If this is an EVPN route, process for un-import. */ - if (safi == SAFI_EVPN) - bgp_evpn_unimport_route (peer->bgp, afi, safi, &rn->p, ri); + /* If this is an EVPN route, process for un-import. */ + if (safi == SAFI_EVPN) + bgp_evpn_unimport_route(peer->bgp, afi, safi, &rn->p, ri); - bgp_rib_remove (rn, ri, peer, afi, safi); + bgp_rib_remove(rn, ri, peer, afi, safi); } -struct bgp_info * -info_make (int type, int sub_type, u_short instance, struct peer *peer, - struct attr *attr, struct bgp_node *rn) +struct bgp_info *info_make(int type, int sub_type, u_short instance, + struct peer *peer, struct attr *attr, + struct bgp_node *rn) { - struct bgp_info *new; + struct bgp_info *new; - /* Make new BGP info. */ - new = XCALLOC (MTYPE_BGP_ROUTE, sizeof (struct bgp_info)); - new->type = type; - new->instance = instance; - new->sub_type = sub_type; - new->peer = peer; - new->attr = attr; - new->uptime = bgp_clock (); - new->net = rn; - new->addpath_tx_id = ++peer->bgp->addpath_tx_id; - return new; + /* Make new BGP info. */ + new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_info)); + new->type = type; + new->instance = instance; + new->sub_type = sub_type; + new->peer = peer; + new->attr = attr; + new->uptime = bgp_clock(); + new->net = rn; + new->addpath_tx_id = ++peer->bgp->addpath_tx_id; + return new; } -static void -overlay_index_update(struct attr *attr, struct eth_segment_id *eth_s_id, union gw_addr *gw_ip) +static void overlay_index_update(struct attr *attr, + struct eth_segment_id *eth_s_id, + union gw_addr *gw_ip) { - if(!attr) - return; + if (!attr) + return; - if(eth_s_id == NULL) - { - memset(&(attr->evpn_overlay.eth_s_id),0, sizeof(struct eth_segment_id)); - } - else - { - memcpy(&(attr->evpn_overlay.eth_s_id), eth_s_id, sizeof(struct eth_segment_id)); - } - if(gw_ip == NULL) - { - memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr)); - } - else - { - memcpy(&(attr->evpn_overlay.gw_ip),gw_ip, sizeof(union gw_addr)); - } + if (eth_s_id == NULL) { + memset(&(attr->evpn_overlay.eth_s_id), 0, + sizeof(struct eth_segment_id)); + } else { + memcpy(&(attr->evpn_overlay.eth_s_id), eth_s_id, + sizeof(struct eth_segment_id)); + } + if (gw_ip == NULL) { + memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr)); + } else { + memcpy(&(attr->evpn_overlay.gw_ip), gw_ip, + sizeof(union gw_addr)); + } } -static bool -overlay_index_equal(afi_t afi, struct bgp_info *info, struct eth_segment_id *eth_s_id, union gw_addr *gw_ip) -{ - struct eth_segment_id *info_eth_s_id, *info_eth_s_id_remote; - union gw_addr *info_gw_ip, *info_gw_ip_remote; - char temp[16]; - - if(afi != AFI_L2VPN) - return true; - if (!info->attr) - { - memset(&temp, 0, 16); - info_eth_s_id = (struct eth_segment_id *)&temp; - info_gw_ip = (union gw_addr *)&temp; - if(eth_s_id == NULL && gw_ip == NULL) - return true; - } - else - { - info_eth_s_id = &(info->attr->evpn_overlay.eth_s_id); - info_gw_ip = &(info->attr->evpn_overlay.gw_ip); - } - if(gw_ip == NULL) - info_gw_ip_remote = (union gw_addr *)&temp; - else - info_gw_ip_remote = gw_ip; - if(eth_s_id == NULL) - info_eth_s_id_remote = (struct eth_segment_id *)&temp; - else - info_eth_s_id_remote = eth_s_id; - if(!memcmp(info_gw_ip, info_gw_ip_remote, sizeof(union gw_addr))) - return false; - return !memcmp(info_eth_s_id, info_eth_s_id_remote, sizeof(struct eth_segment_id)); +static bool overlay_index_equal(afi_t afi, struct bgp_info *info, + struct eth_segment_id *eth_s_id, + union gw_addr *gw_ip) +{ + struct eth_segment_id *info_eth_s_id, *info_eth_s_id_remote; + union gw_addr *info_gw_ip, *info_gw_ip_remote; + char temp[16]; + + if (afi != AFI_L2VPN) + return true; + if (!info->attr) { + memset(&temp, 0, 16); + info_eth_s_id = (struct eth_segment_id *)&temp; + info_gw_ip = (union gw_addr *)&temp; + if (eth_s_id == NULL && gw_ip == NULL) + return true; + } else { + info_eth_s_id = &(info->attr->evpn_overlay.eth_s_id); + info_gw_ip = &(info->attr->evpn_overlay.gw_ip); + } + if (gw_ip == NULL) + info_gw_ip_remote = (union gw_addr *)&temp; + else + info_gw_ip_remote = gw_ip; + if (eth_s_id == NULL) + info_eth_s_id_remote = (struct eth_segment_id *)&temp; + else + info_eth_s_id_remote = eth_s_id; + if (!memcmp(info_gw_ip, info_gw_ip_remote, sizeof(union gw_addr))) + return false; + return !memcmp(info_eth_s_id, info_eth_s_id_remote, + sizeof(struct eth_segment_id)); } /* Check if received nexthop is valid or not. */ -static int -bgp_update_martian_nexthop (struct bgp *bgp, afi_t afi, safi_t safi, struct attr *attr) -{ - int ret = 0; - - /* Only validated for unicast and multicast currently. */ - /* Also valid for EVPN where the nexthop is an IP address. */ - if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN) - return 0; - - /* If NEXT_HOP is present, validate it. */ - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)) - { - if (attr->nexthop.s_addr == 0 || - IPV4_CLASS_DE (ntohl (attr->nexthop.s_addr)) || - bgp_nexthop_self (bgp, attr->nexthop)) - return 1; - } +static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi, + struct attr *attr) +{ + int ret = 0; + + /* Only validated for unicast and multicast currently. */ + /* Also valid for EVPN where the nexthop is an IP address. */ + if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN) + return 0; + + /* If NEXT_HOP is present, validate it. */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) { + if (attr->nexthop.s_addr == 0 + || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr)) + || bgp_nexthop_self(bgp, attr->nexthop)) + return 1; + } - /* If MP_NEXTHOP is present, validate it. */ - /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop; - * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if - * it is not an IPv6 link-local address. - */ - if (attr->mp_nexthop_len) - { - switch (attr->mp_nexthop_len) - { - case BGP_ATTR_NHLEN_IPV4: - case BGP_ATTR_NHLEN_VPNV4: - ret = (attr->mp_nexthop_global_in.s_addr == 0 || - IPV4_CLASS_DE (ntohl (attr->mp_nexthop_global_in.s_addr)) || - bgp_nexthop_self (bgp, attr->mp_nexthop_global_in)); - break; - - case BGP_ATTR_NHLEN_IPV6_GLOBAL: - case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL: - case BGP_ATTR_NHLEN_VPNV6_GLOBAL: - ret = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global) || - IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global) || - IN6_IS_ADDR_MULTICAST(&attr->mp_nexthop_global)); - break; - - default: - ret = 1; - break; - } - } + /* If MP_NEXTHOP is present, validate it. */ + /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop; + * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if + * it is not an IPv6 link-local address. + */ + if (attr->mp_nexthop_len) { + switch (attr->mp_nexthop_len) { + case BGP_ATTR_NHLEN_IPV4: + case BGP_ATTR_NHLEN_VPNV4: + ret = (attr->mp_nexthop_global_in.s_addr == 0 + || IPV4_CLASS_DE(ntohl( + attr->mp_nexthop_global_in.s_addr)) + || bgp_nexthop_self(bgp, + attr->mp_nexthop_global_in)); + break; + + case BGP_ATTR_NHLEN_IPV6_GLOBAL: + case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL: + case BGP_ATTR_NHLEN_VPNV6_GLOBAL: + ret = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global) + || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global) + || IN6_IS_ADDR_MULTICAST( + &attr->mp_nexthop_global)); + break; + + default: + ret = 1; + break; + } + } - return ret; -} - -int -bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id, - struct attr *attr, afi_t afi, safi_t safi, int type, - int sub_type, struct prefix_rd *prd, mpls_label_t *label, - int soft_reconfig, struct bgp_route_evpn* evpn) -{ - int ret; - int aspath_loop_count = 0; - struct bgp_node *rn; - struct bgp *bgp; - struct attr new_attr; - struct attr *attr_new; - struct bgp_info *ri; - struct bgp_info *new; - const char *reason; - char pfx_buf[BGP_PRD_PATH_STRLEN]; - char label_buf[20]; - int connected = 0; - int do_loop_check = 1; - int has_valid_label = 0; + return ret; +} + +int bgp_update(struct peer *peer, struct prefix *p, u_int32_t addpath_id, + struct attr *attr, afi_t afi, safi_t safi, int type, + int sub_type, struct prefix_rd *prd, mpls_label_t *label, + int soft_reconfig, struct bgp_route_evpn *evpn) +{ + int ret; + int aspath_loop_count = 0; + struct bgp_node *rn; + struct bgp *bgp; + struct attr new_attr; + struct attr *attr_new; + struct bgp_info *ri; + struct bgp_info *new; + const char *reason; + char pfx_buf[BGP_PRD_PATH_STRLEN]; + char label_buf[20]; + int connected = 0; + int do_loop_check = 1; + int has_valid_label = 0; #if ENABLE_BGP_VNC - int vnc_implicit_withdraw = 0; + int vnc_implicit_withdraw = 0; #endif - int same_attr=0; + int same_attr = 0; - memset (&new_attr, 0, sizeof(struct attr)); - new_attr.label_index = BGP_INVALID_LABEL_INDEX; - new_attr.label = MPLS_INVALID_LABEL; + memset(&new_attr, 0, sizeof(struct attr)); + new_attr.label_index = BGP_INVALID_LABEL_INDEX; + new_attr.label = MPLS_INVALID_LABEL; - bgp = peer->bgp; - rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd); - has_valid_label = bgp_is_valid_label(label); + bgp = peer->bgp; + rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd); + has_valid_label = bgp_is_valid_label(label); - if (has_valid_label) - sprintf (label_buf, "label %u", label_pton(label)); - - /* When peer's soft reconfiguration enabled. Record input packet in - Adj-RIBs-In. */ - if (! soft_reconfig && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) - && peer != bgp->peer_self) - bgp_adj_in_set (rn, peer, attr, addpath_id); - - /* Check previously received route. */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type && - ri->addpath_rx_id == addpath_id) - break; - - /* AS path local-as loop check. */ - if (peer->change_local_as) - { - if (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)) - aspath_loop_count = 1; + if (has_valid_label) + sprintf(label_buf, "label %u", label_pton(label)); - if (aspath_loop_check (attr->aspath, peer->change_local_as) > aspath_loop_count) - { - reason = "as-path contains our own AS;"; - goto filtered; + /* When peer's soft reconfiguration enabled. Record input packet in + Adj-RIBs-In. */ + if (!soft_reconfig + && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) + && peer != bgp->peer_self) + bgp_adj_in_set(rn, peer, attr, addpath_id); + + /* Check previously received route. */ + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == peer && ri->type == type + && ri->sub_type == sub_type + && ri->addpath_rx_id == addpath_id) + break; + + /* AS path local-as loop check. */ + if (peer->change_local_as) { + if (!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)) + aspath_loop_count = 1; + + if (aspath_loop_check(attr->aspath, peer->change_local_as) + > aspath_loop_count) { + reason = "as-path contains our own AS;"; + goto filtered; + } } - } - /* If the peer is configured for "allowas-in origin" and the last ASN in the - * as-path is our ASN then we do not need to call aspath_loop_check - */ - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) - if (aspath_get_last_as(attr->aspath) == bgp->as) - do_loop_check = 0; + /* If the peer is configured for "allowas-in origin" and the last ASN in + * the + * as-path is our ASN then we do not need to call aspath_loop_check + */ + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) + if (aspath_get_last_as(attr->aspath) == bgp->as) + do_loop_check = 0; + + /* AS path loop check. */ + if (do_loop_check) { + if (aspath_loop_check(attr->aspath, bgp->as) + > peer->allowas_in[afi][safi] + || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) + && aspath_loop_check(attr->aspath, bgp->confed_id) + > peer->allowas_in[afi][safi])) { + reason = "as-path contains our own AS;"; + goto filtered; + } + } - /* AS path loop check. */ - if (do_loop_check) - { - if (aspath_loop_check (attr->aspath, bgp->as) > peer->allowas_in[afi][safi] - || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) - && aspath_loop_check(attr->aspath, bgp->confed_id) > peer->allowas_in[afi][safi])) - { - reason = "as-path contains our own AS;"; - goto filtered; - } - } + /* Route reflector originator ID check. */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID) + && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) { + reason = "originator is us;"; + goto filtered; + } - /* Route reflector originator ID check. */ - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID) - && IPV4_ADDR_SAME (&bgp->router_id, &attr->originator_id)) - { - reason = "originator is us;"; - goto filtered; - } + /* Route reflector cluster ID check. */ + if (bgp_cluster_filter(peer, attr)) { + reason = "reflected from the same cluster;"; + goto filtered; + } - /* Route reflector cluster ID check. */ - if (bgp_cluster_filter (peer, attr)) - { - reason = "reflected from the same cluster;"; - goto filtered; - } + /* Apply incoming filter. */ + if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) { + reason = "filter;"; + goto filtered; + } - /* Apply incoming filter. */ - if (bgp_input_filter (peer, p, attr, afi, safi) == FILTER_DENY) - { - reason = "filter;"; - goto filtered; - } + bgp_attr_dup(&new_attr, attr); + + /* Apply incoming route-map. + * NB: new_attr may now contain newly allocated values from route-map + * "set" + * commands, so we need bgp_attr_flush in the error paths, until we + * intern + * the attr (which takes over the memory references) */ + if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL) + == RMAP_DENY) { + reason = "route-map;"; + bgp_attr_flush(&new_attr); + goto filtered; + } - bgp_attr_dup (&new_attr, attr); + /* next hop check. */ + if (bgp_update_martian_nexthop(bgp, afi, safi, &new_attr)) { + reason = "martian or self next-hop;"; + bgp_attr_flush(&new_attr); + goto filtered; + } - /* Apply incoming route-map. - * NB: new_attr may now contain newly allocated values from route-map "set" - * commands, so we need bgp_attr_flush in the error paths, until we intern - * the attr (which takes over the memory references) */ - if (bgp_input_modifier (peer, p, &new_attr, afi, safi, NULL) == RMAP_DENY) - { - reason = "route-map;"; - bgp_attr_flush (&new_attr); - goto filtered; - } + attr_new = bgp_attr_intern(&new_attr); + + /* If the update is implicit withdraw. */ + if (ri) { + ri->uptime = bgp_clock(); + same_attr = attrhash_cmp(ri->attr, attr_new); + + /* Same attribute comes in. */ + if (!CHECK_FLAG(ri->flags, BGP_INFO_REMOVED) + && attrhash_cmp(ri->attr, attr_new) + && (!has_valid_label + || memcmp(&(bgp_info_extra_get(ri))->label, label, + BGP_LABEL_BYTES) + == 0) + && (overlay_index_equal( + afi, ri, evpn == NULL ? NULL : &evpn->eth_s_id, + evpn == NULL ? NULL : &evpn->gw_ip))) { + if (CHECK_FLAG(bgp->af_flags[afi][safi], + BGP_CONFIG_DAMPENING) + && peer->sort == BGP_PEER_EBGP + && CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) { + if (bgp_debug_update(peer, p, NULL, 1)) { + bgp_debug_rdpfxpath2str( + afi, safi, prd, p, label, + addpath_id ? 1 : 0, addpath_id, + pfx_buf, sizeof(pfx_buf)); + zlog_debug("%s rcvd %s", peer->host, + pfx_buf); + } + + if (bgp_damp_update(ri, rn, afi, safi) + != BGP_DAMP_SUPPRESSED) { + bgp_aggregate_increment(bgp, p, ri, afi, + safi); + bgp_process(bgp, rn, afi, safi); + } + } else /* Duplicate - odd */ + { + if (bgp_debug_update(peer, p, NULL, 1)) { + if (!peer->rcvd_attr_printed) { + zlog_debug( + "%s rcvd UPDATE w/ attr: %s", + peer->host, + peer->rcvd_attr_str); + peer->rcvd_attr_printed = 1; + } + + bgp_debug_rdpfxpath2str( + afi, safi, prd, p, label, + addpath_id ? 1 : 0, addpath_id, + pfx_buf, sizeof(pfx_buf)); + zlog_debug( + "%s rcvd %s...duplicate ignored", + peer->host, pfx_buf); + } + + /* graceful restart STALE flag unset. */ + if (CHECK_FLAG(ri->flags, BGP_INFO_STALE)) { + bgp_info_unset_flag(rn, ri, + BGP_INFO_STALE); + bgp_process(bgp, rn, afi, safi); + } + } + + bgp_unlock_node(rn); + bgp_attr_unintern(&attr_new); + + return 0; + } - /* next hop check. */ - if (bgp_update_martian_nexthop (bgp, afi, safi, &new_attr)) - { - reason = "martian or self next-hop;"; - bgp_attr_flush (&new_attr); - goto filtered; - } + /* Withdraw/Announce before we fully processed the withdraw */ + if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { + if (bgp_debug_update(peer, p, NULL, 1)) { + bgp_debug_rdpfxpath2str( + afi, safi, prd, p, label, + addpath_id ? 1 : 0, addpath_id, pfx_buf, + sizeof(pfx_buf)); + zlog_debug( + "%s rcvd %s, flapped quicker than processing", + peer->host, pfx_buf); + } + + bgp_info_restore(rn, ri); + } - attr_new = bgp_attr_intern (&new_attr); + /* Received Logging. */ + if (bgp_debug_update(peer, p, NULL, 1)) { + bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, + addpath_id ? 1 : 0, addpath_id, + pfx_buf, sizeof(pfx_buf)); + zlog_debug("%s rcvd %s", peer->host, pfx_buf); + } - /* If the update is implicit withdraw. */ - if (ri) - { - ri->uptime = bgp_clock (); - same_attr = attrhash_cmp (ri->attr, attr_new); - - /* Same attribute comes in. */ - if (!CHECK_FLAG (ri->flags, BGP_INFO_REMOVED) - && attrhash_cmp (ri->attr, attr_new) - && (!has_valid_label || - memcmp (&(bgp_info_extra_get (ri))->label, label, BGP_LABEL_BYTES) == 0) - && (overlay_index_equal(afi, ri, evpn==NULL?NULL:&evpn->eth_s_id, - evpn==NULL?NULL:&evpn->gw_ip))) - { - if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) - && peer->sort == BGP_PEER_EBGP - && CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) - { - if (bgp_debug_update(peer, p, NULL, 1)) - { - bgp_debug_rdpfxpath2str (afi, safi, prd, p, label, - addpath_id ? 1 : 0, addpath_id, - pfx_buf, sizeof (pfx_buf)); - zlog_debug ("%s rcvd %s", peer->host, pfx_buf); - } - - if (bgp_damp_update (ri, rn, afi, safi) != BGP_DAMP_SUPPRESSED) - { - bgp_aggregate_increment (bgp, p, ri, afi, safi); - bgp_process (bgp, rn, afi, safi); - } - } - else /* Duplicate - odd */ - { - if (bgp_debug_update(peer, p, NULL, 1)) - { - if (!peer->rcvd_attr_printed) - { - zlog_debug ("%s rcvd UPDATE w/ attr: %s", peer->host, peer->rcvd_attr_str); - peer->rcvd_attr_printed = 1; - } - - bgp_debug_rdpfxpath2str (afi, safi, prd, p, label, - addpath_id ? 1 : 0, addpath_id, - pfx_buf, sizeof (pfx_buf)); - zlog_debug ("%s rcvd %s...duplicate ignored", - peer->host, pfx_buf); - } - - /* graceful restart STALE flag unset. */ - if (CHECK_FLAG (ri->flags, BGP_INFO_STALE)) - { - bgp_info_unset_flag (rn, ri, BGP_INFO_STALE); - bgp_process (bgp, rn, afi, safi); - } - } - - bgp_unlock_node (rn); - bgp_attr_unintern (&attr_new); - - return 0; - } - - /* Withdraw/Announce before we fully processed the withdraw */ - if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) - { - if (bgp_debug_update(peer, p, NULL, 1)) - { - bgp_debug_rdpfxpath2str (afi, safi, prd, p, label, - addpath_id ? 1 : 0, addpath_id, - pfx_buf, sizeof (pfx_buf)); - zlog_debug ("%s rcvd %s, flapped quicker than processing", - peer->host, pfx_buf); - } - - bgp_info_restore (rn, ri); - } - - /* Received Logging. */ - if (bgp_debug_update(peer, p, NULL, 1)) - { - bgp_debug_rdpfxpath2str (afi, safi, prd, p, label, - addpath_id ? 1 : 0, addpath_id, - pfx_buf, sizeof (pfx_buf)); - zlog_debug ("%s rcvd %s", peer->host, pfx_buf); - } - - /* graceful restart STALE flag unset. */ - if (CHECK_FLAG (ri->flags, BGP_INFO_STALE)) - bgp_info_unset_flag (rn, ri, BGP_INFO_STALE); - - /* The attribute is changed. */ - bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); - - /* implicit withdraw, decrement aggregate and pcount here. - * only if update is accepted, they'll increment below. - */ - bgp_aggregate_decrement (bgp, p, ri, afi, safi); - - /* Update bgp route dampening information. */ - if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) - && peer->sort == BGP_PEER_EBGP) - { - /* This is implicit withdraw so we should update dampening - information. */ - if (! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) - bgp_damp_withdraw (ri, rn, afi, safi, 1); - } + /* graceful restart STALE flag unset. */ + if (CHECK_FLAG(ri->flags, BGP_INFO_STALE)) + bgp_info_unset_flag(rn, ri, BGP_INFO_STALE); + + /* The attribute is changed. */ + bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED); + + /* implicit withdraw, decrement aggregate and pcount here. + * only if update is accepted, they'll increment below. + */ + bgp_aggregate_decrement(bgp, p, ri, afi, safi); + + /* Update bgp route dampening information. */ + if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) + && peer->sort == BGP_PEER_EBGP) { + /* This is implicit withdraw so we should update + dampening + information. */ + if (!CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) + bgp_damp_withdraw(ri, rn, afi, safi, 1); + } #if ENABLE_BGP_VNC - if (safi == SAFI_MPLS_VPN) { - struct bgp_node *prn = NULL; - struct bgp_table *table = NULL; - - prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *) prd); - if (prn->info) { - table = (struct bgp_table *)(prn->info); - - vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( - bgp, - prd, - table, - p, - ri); - } - bgp_unlock_node(prn); - } - if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { - if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) { - /* - * Implicit withdraw case. - */ - ++vnc_implicit_withdraw; - vnc_import_bgp_del_route(bgp, p, ri); - vnc_import_bgp_exterior_del_route(bgp, p, ri); - } - } + if (safi == SAFI_MPLS_VPN) { + struct bgp_node *prn = NULL; + struct bgp_table *table = NULL; + + prn = bgp_node_get(bgp->rib[afi][safi], + (struct prefix *)prd); + if (prn->info) { + table = (struct bgp_table *)(prn->info); + + vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( + bgp, prd, table, p, ri); + } + bgp_unlock_node(prn); + } + if ((afi == AFI_IP || afi == AFI_IP6) + && (safi == SAFI_UNICAST)) { + if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) { + /* + * Implicit withdraw case. + */ + ++vnc_implicit_withdraw; + vnc_import_bgp_del_route(bgp, p, ri); + vnc_import_bgp_exterior_del_route(bgp, p, ri); + } + } #endif - /* Special handling for EVPN update of an existing route. If the - * extended community attribute has changed, we need to un-import - * the route using its existing extended community. It will be - * subsequently processed for import with the new extended community. - */ - if (safi == SAFI_EVPN && !same_attr) - { - if ((ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)) && - (attr_new->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES))) - { - int cmp; - - cmp = ecommunity_cmp (ri->attr->ecommunity, - attr_new->ecommunity); - if (!cmp) - { - if (bgp_debug_update(peer, p, NULL, 1)) - zlog_debug ("Change in EXT-COMM, existing %s new %s", - ecommunity_str (ri->attr->ecommunity), - ecommunity_str (attr_new->ecommunity)); - bgp_evpn_unimport_route (bgp, afi, safi, p, ri); - } - } - } - - /* Update to new attribute. */ - bgp_attr_unintern (&ri->attr); - ri->attr = attr_new; - - /* Update MPLS label */ - if (has_valid_label) - { - memcpy (&(bgp_info_extra_get (ri))->label, label, BGP_LABEL_BYTES); - bgp_set_valid_label(&(bgp_info_extra_get (ri))->label); - } + /* Special handling for EVPN update of an existing route. If the + * extended community attribute has changed, we need to + * un-import + * the route using its existing extended community. It will be + * subsequently processed for import with the new extended + * community. + */ + if (safi == SAFI_EVPN && !same_attr) { + if ((ri->attr->flag + & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) + && (attr_new->flag + & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) { + int cmp; + + cmp = ecommunity_cmp(ri->attr->ecommunity, + attr_new->ecommunity); + if (!cmp) { + if (bgp_debug_update(peer, p, NULL, 1)) + zlog_debug( + "Change in EXT-COMM, existing %s new %s", + ecommunity_str( + ri->attr->ecommunity), + ecommunity_str( + attr_new->ecommunity)); + bgp_evpn_unimport_route(bgp, afi, safi, + p, ri); + } + } + } -#if ENABLE_BGP_VNC - if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) - { - if (vnc_implicit_withdraw) - { - /* - * Add back the route with its new attributes (e.g., nexthop). - * The route is still selected, until the route selection - * queued by bgp_process actually runs. We have to make this - * update to the VNC side immediately to avoid racing against - * configuration changes (e.g., route-map changes) which - * trigger re-importation of the entire RIB. - */ - vnc_import_bgp_add_route(bgp, p, ri); - vnc_import_bgp_exterior_add_route(bgp, p, ri); - } - } -#endif - /* Update Overlay Index */ - if(afi == AFI_L2VPN) - { - overlay_index_update(ri->attr, evpn==NULL?NULL:&evpn->eth_s_id, - evpn==NULL?NULL:&evpn->gw_ip); - } - - /* Update bgp route dampening information. */ - if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) - && peer->sort == BGP_PEER_EBGP) - { - /* Now we do normal update dampening. */ - ret = bgp_damp_update (ri, rn, afi, safi); - if (ret == BGP_DAMP_SUPPRESSED) - { - bgp_unlock_node (rn); - return 0; - } - } - - /* Nexthop reachability check - for unicast and labeled-unicast.. */ - if ((afi == AFI_IP || afi == AFI_IP6) && - (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) - { - if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 && - ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) - && ! bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) - connected = 1; - else - connected = 0; - - if (bgp_find_or_add_nexthop (bgp, afi, ri, NULL, connected)) - bgp_info_set_flag (rn, ri, BGP_INFO_VALID); - else - { - if (BGP_DEBUG(nht, NHT)) - { - char buf1[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET, (const void *)&attr_new->nexthop, buf1, INET6_ADDRSTRLEN); - zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1); + /* Update to new attribute. */ + bgp_attr_unintern(&ri->attr); + ri->attr = attr_new; + + /* Update MPLS label */ + if (has_valid_label) { + memcpy(&(bgp_info_extra_get(ri))->label, label, + BGP_LABEL_BYTES); + bgp_set_valid_label(&(bgp_info_extra_get(ri))->label); } - bgp_info_unset_flag (rn, ri, BGP_INFO_VALID); - } - } - else - bgp_info_set_flag (rn, ri, BGP_INFO_VALID); #if ENABLE_BGP_VNC - if (safi == SAFI_MPLS_VPN) - { - struct bgp_node *prn = NULL; - struct bgp_table *table = NULL; - - prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *) prd); - if (prn->info) - { - table = (struct bgp_table *)(prn->info); - - vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( - bgp, - prd, - table, - p, - ri); - } - bgp_unlock_node(prn); - } + if ((afi == AFI_IP || afi == AFI_IP6) + && (safi == SAFI_UNICAST)) { + if (vnc_implicit_withdraw) { + /* + * Add back the route with its new attributes + * (e.g., nexthop). + * The route is still selected, until the route + * selection + * queued by bgp_process actually runs. We have + * to make this + * update to the VNC side immediately to avoid + * racing against + * configuration changes (e.g., route-map + * changes) which + * trigger re-importation of the entire RIB. + */ + vnc_import_bgp_add_route(bgp, p, ri); + vnc_import_bgp_exterior_add_route(bgp, p, ri); + } + } #endif + /* Update Overlay Index */ + if (afi == AFI_L2VPN) { + overlay_index_update( + ri->attr, evpn == NULL ? NULL : &evpn->eth_s_id, + evpn == NULL ? NULL : &evpn->gw_ip); + } - /* If this is an EVPN route and some attribute has changed, process - * route for import. If the extended community has changed, we would - * have done the un-import earlier and the import would result in the - * route getting injected into appropriate L2 VNIs. If it is just - * some other attribute change, the import will result in updating - * the attributes for the route in the VNI(s). - */ - if (safi == SAFI_EVPN && !same_attr) - bgp_evpn_import_route (bgp, afi, safi, p, ri); + /* Update bgp route dampening information. */ + if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) + && peer->sort == BGP_PEER_EBGP) { + /* Now we do normal update dampening. */ + ret = bgp_damp_update(ri, rn, afi, safi); + if (ret == BGP_DAMP_SUPPRESSED) { + bgp_unlock_node(rn); + return 0; + } + } - /* Process change. */ - bgp_aggregate_increment (bgp, p, ri, afi, safi); + /* Nexthop reachability check - for unicast and + * labeled-unicast.. */ + if ((afi == AFI_IP || afi == AFI_IP6) + && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) { + if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 + && !CHECK_FLAG(peer->flags, + PEER_FLAG_DISABLE_CONNECTED_CHECK) + && !bgp_flag_check( + bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) + connected = 1; + else + connected = 0; + + if (bgp_find_or_add_nexthop(bgp, afi, ri, NULL, + connected)) + bgp_info_set_flag(rn, ri, BGP_INFO_VALID); + else { + if (BGP_DEBUG(nht, NHT)) { + char buf1[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET, + (const void *)&attr_new + ->nexthop, + buf1, INET6_ADDRSTRLEN); + zlog_debug("%s(%s): NH unresolved", + __FUNCTION__, buf1); + } + bgp_info_unset_flag(rn, ri, BGP_INFO_VALID); + } + } else + bgp_info_set_flag(rn, ri, BGP_INFO_VALID); + +#if ENABLE_BGP_VNC + if (safi == SAFI_MPLS_VPN) { + struct bgp_node *prn = NULL; + struct bgp_table *table = NULL; + + prn = bgp_node_get(bgp->rib[afi][safi], + (struct prefix *)prd); + if (prn->info) { + table = (struct bgp_table *)(prn->info); + + vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( + bgp, prd, table, p, ri); + } + bgp_unlock_node(prn); + } +#endif - bgp_process (bgp, rn, afi, safi); - bgp_unlock_node (rn); + /* If this is an EVPN route and some attribute has changed, + * process + * route for import. If the extended community has changed, we + * would + * have done the un-import earlier and the import would result + * in the + * route getting injected into appropriate L2 VNIs. If it is + * just + * some other attribute change, the import will result in + * updating + * the attributes for the route in the VNI(s). + */ + if (safi == SAFI_EVPN && !same_attr) + bgp_evpn_import_route(bgp, afi, safi, p, ri); + + /* Process change. */ + bgp_aggregate_increment(bgp, p, ri, afi, safi); + + bgp_process(bgp, rn, afi, safi); + bgp_unlock_node(rn); #if ENABLE_BGP_VNC - if (SAFI_MPLS_VPN == safi) - { - mpls_label_t label_decoded = decode_label(label); + if (SAFI_MPLS_VPN == safi) { + mpls_label_t label_decoded = decode_label(label); - rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type, sub_type, - &label_decoded); - } - if (SAFI_ENCAP == safi) - { - rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type, sub_type, - NULL); - } + rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, + type, sub_type, &label_decoded); + } + if (SAFI_ENCAP == safi) { + rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, + type, sub_type, NULL); + } #endif - return 0; - } // End of implicit withdraw + return 0; + } // End of implicit withdraw - /* Received Logging. */ - if (bgp_debug_update(peer, p, NULL, 1)) - { - if (!peer->rcvd_attr_printed) - { - zlog_debug ("%s rcvd UPDATE w/ attr: %s", peer->host, peer->rcvd_attr_str); - peer->rcvd_attr_printed = 1; - } - - bgp_debug_rdpfxpath2str (afi, safi, prd, p, label, - addpath_id ? 1 : 0, addpath_id, - pfx_buf, sizeof (pfx_buf)); - zlog_debug ("%s rcvd %s", peer->host, pfx_buf); - } + /* Received Logging. */ + if (bgp_debug_update(peer, p, NULL, 1)) { + if (!peer->rcvd_attr_printed) { + zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host, + peer->rcvd_attr_str); + peer->rcvd_attr_printed = 1; + } - /* Make new BGP info. */ - new = info_make(type, sub_type, 0, peer, attr_new, rn); + bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, + addpath_id ? 1 : 0, addpath_id, pfx_buf, + sizeof(pfx_buf)); + zlog_debug("%s rcvd %s", peer->host, pfx_buf); + } - /* Update MPLS label */ - if (has_valid_label) - { - memcpy (&(bgp_info_extra_get (new))->label, label, BGP_LABEL_BYTES); - bgp_set_valid_label(&(bgp_info_extra_get (new))->label); - } + /* Make new BGP info. */ + new = info_make(type, sub_type, 0, peer, attr_new, rn); - /* Update Overlay Index */ - if(afi == AFI_L2VPN) - { - overlay_index_update(new->attr, evpn==NULL?NULL:&evpn->eth_s_id, - evpn==NULL?NULL:&evpn->gw_ip); - } - /* Nexthop reachability check. */ - if ((afi == AFI_IP || afi == AFI_IP6) && - (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) - { - if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 && - ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) - && ! bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) - connected = 1; - else - connected = 0; - - if (bgp_find_or_add_nexthop (bgp, afi, new, NULL, connected)) - bgp_info_set_flag (rn, new, BGP_INFO_VALID); - else - { - if (BGP_DEBUG(nht, NHT)) - { - char buf1[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET, (const void *)&attr_new->nexthop, buf1, INET6_ADDRSTRLEN); - zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1); - } - bgp_info_unset_flag (rn, new, BGP_INFO_VALID); + /* Update MPLS label */ + if (has_valid_label) { + memcpy(&(bgp_info_extra_get(new))->label, label, + BGP_LABEL_BYTES); + bgp_set_valid_label(&(bgp_info_extra_get(new))->label); } - } - else - bgp_info_set_flag (rn, new, BGP_INFO_VALID); - /* Addpath ID */ - new->addpath_rx_id = addpath_id; + /* Update Overlay Index */ + if (afi == AFI_L2VPN) { + overlay_index_update(new->attr, + evpn == NULL ? NULL : &evpn->eth_s_id, + evpn == NULL ? NULL : &evpn->gw_ip); + } + /* Nexthop reachability check. */ + if ((afi == AFI_IP || afi == AFI_IP6) + && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) { + if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 + && !CHECK_FLAG(peer->flags, + PEER_FLAG_DISABLE_CONNECTED_CHECK) + && !bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) + connected = 1; + else + connected = 0; + + if (bgp_find_or_add_nexthop(bgp, afi, new, NULL, connected)) + bgp_info_set_flag(rn, new, BGP_INFO_VALID); + else { + if (BGP_DEBUG(nht, NHT)) { + char buf1[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET, + (const void *)&attr_new->nexthop, + buf1, INET6_ADDRSTRLEN); + zlog_debug("%s(%s): NH unresolved", + __FUNCTION__, buf1); + } + bgp_info_unset_flag(rn, new, BGP_INFO_VALID); + } + } else + bgp_info_set_flag(rn, new, BGP_INFO_VALID); - /* Increment prefix */ - bgp_aggregate_increment (bgp, p, new, afi, safi); - - /* Register new BGP information. */ - bgp_info_add (rn, new); - - /* route_node_get lock */ - bgp_unlock_node (rn); + /* Addpath ID */ + new->addpath_rx_id = addpath_id; + + /* Increment prefix */ + bgp_aggregate_increment(bgp, p, new, afi, safi); + + /* Register new BGP information. */ + bgp_info_add(rn, new); + + /* route_node_get lock */ + bgp_unlock_node(rn); #if ENABLE_BGP_VNC - if (safi == SAFI_MPLS_VPN) - { - struct bgp_node *prn = NULL; - struct bgp_table *table = NULL; - - prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *) prd); - if (prn->info) - { - table = (struct bgp_table *)(prn->info); - - vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( - bgp, - prd, - table, - p, - new); - } - bgp_unlock_node(prn); - } + if (safi == SAFI_MPLS_VPN) { + struct bgp_node *prn = NULL; + struct bgp_table *table = NULL; + + prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd); + if (prn->info) { + table = (struct bgp_table *)(prn->info); + + vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( + bgp, prd, table, p, new); + } + bgp_unlock_node(prn); + } #endif - /* If maximum prefix count is configured and current prefix - count exeed it. */ - if (bgp_maximum_prefix_overflow (peer, afi, safi, 0)) - return -1; + /* If maximum prefix count is configured and current prefix + count exeed it. */ + if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) + return -1; - /* If this is an EVPN route, process for import. */ - if (safi == SAFI_EVPN) - bgp_evpn_import_route (bgp, afi, safi, p, new); + /* If this is an EVPN route, process for import. */ + if (safi == SAFI_EVPN) + bgp_evpn_import_route(bgp, afi, safi, p, new); - /* Process change. */ - bgp_process (bgp, rn, afi, safi); + /* Process change. */ + bgp_process(bgp, rn, afi, safi); #if ENABLE_BGP_VNC - if (SAFI_MPLS_VPN == safi) - { - mpls_label_t label_decoded = decode_label(label); + if (SAFI_MPLS_VPN == safi) { + mpls_label_t label_decoded = decode_label(label); - rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type, sub_type, - &label_decoded); - } - if (SAFI_ENCAP == safi) - { - rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type, sub_type, - NULL); - } + rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type, + sub_type, &label_decoded); + } + if (SAFI_ENCAP == safi) { + rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type, + sub_type, NULL); + } #endif - return 0; + return 0; - /* This BGP update is filtered. Log the reason then update BGP - entry. */ - filtered: - if (bgp_debug_update(peer, p, NULL, 1)) - { - if (!peer->rcvd_attr_printed) - { - zlog_debug ("%s rcvd UPDATE w/ attr: %s", peer->host, peer->rcvd_attr_str); - peer->rcvd_attr_printed = 1; - } - - bgp_debug_rdpfxpath2str (afi, safi, prd, p, label, - addpath_id ? 1 : 0, addpath_id, - pfx_buf, sizeof (pfx_buf)); - zlog_debug ("%s rcvd UPDATE about %s -- DENIED due to: %s", - peer->host, pfx_buf, reason); - } +/* This BGP update is filtered. Log the reason then update BGP + entry. */ +filtered: + if (bgp_debug_update(peer, p, NULL, 1)) { + if (!peer->rcvd_attr_printed) { + zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host, + peer->rcvd_attr_str); + peer->rcvd_attr_printed = 1; + } - if (ri) - { - /* If this is an EVPN route, un-import it as it is now filtered. */ - if (safi == SAFI_EVPN) - bgp_evpn_unimport_route (bgp, afi, safi, p, ri); + bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, + addpath_id ? 1 : 0, addpath_id, pfx_buf, + sizeof(pfx_buf)); + zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s", + peer->host, pfx_buf, reason); + } - bgp_rib_remove (rn, ri, peer, afi, safi); - } + if (ri) { + /* If this is an EVPN route, un-import it as it is now filtered. + */ + if (safi == SAFI_EVPN) + bgp_evpn_unimport_route(bgp, afi, safi, p, ri); - bgp_unlock_node (rn); + bgp_rib_remove(rn, ri, peer, afi, safi); + } + + bgp_unlock_node(rn); #if ENABLE_BGP_VNC - /* - * Filtered update is treated as an implicit withdrawal (see bgp_rib_remove() - * a few lines above) - */ - if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) - { - rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type, 0); - } + /* + * Filtered update is treated as an implicit withdrawal (see + * bgp_rib_remove() + * a few lines above) + */ + if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) { + rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type, + 0); + } #endif - return 0; + return 0; } -int -bgp_withdraw (struct peer *peer, struct prefix *p, u_int32_t addpath_id, - struct attr *attr, afi_t afi, safi_t safi, int type, int sub_type, - struct prefix_rd *prd, mpls_label_t *label, struct bgp_route_evpn *evpn) +int bgp_withdraw(struct peer *peer, struct prefix *p, u_int32_t addpath_id, + struct attr *attr, afi_t afi, safi_t safi, int type, + int sub_type, struct prefix_rd *prd, mpls_label_t *label, + struct bgp_route_evpn *evpn) { - struct bgp *bgp; - char pfx_buf[BGP_PRD_PATH_STRLEN]; - struct bgp_node *rn; - struct bgp_info *ri; + struct bgp *bgp; + char pfx_buf[BGP_PRD_PATH_STRLEN]; + struct bgp_node *rn; + struct bgp_info *ri; #if ENABLE_BGP_VNC - if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) - { - rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type, 0); - } + if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) { + rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type, + 0); + } #endif - bgp = peer->bgp; - - /* Lookup node. */ - rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd); - - /* If peer is soft reconfiguration enabled. Record input packet for - * further calculation. - * - * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all - * routes that are filtered. This tanks out Quagga RS pretty badly due to - * the iteration over all RS clients. - * Since we need to remove the entry from adj_in anyway, do that first and - * if there was no entry, we don't need to do anything more. - */ - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) - && peer != bgp->peer_self) - if (!bgp_adj_in_unset (rn, peer, addpath_id)) - { - if (bgp_debug_update (peer, p, NULL, 1)) - { - bgp_debug_rdpfxpath2str (afi, safi, prd, p, label, - addpath_id ? 1 : 0, addpath_id, - pfx_buf, sizeof (pfx_buf)); - zlog_debug ("%s withdrawing route %s not in adj-in", - peer->host, pfx_buf); - } - bgp_unlock_node (rn); - return 0; - } - - /* Lookup withdrawn route. */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type && - ri->addpath_rx_id == addpath_id) - break; - - /* Logging. */ - if (bgp_debug_update(peer, p, NULL, 1)) - { - bgp_debug_rdpfxpath2str (afi, safi, prd, p, label, - addpath_id ? 1 : 0, addpath_id, - pfx_buf, sizeof (pfx_buf)); - zlog_debug ("%s rcvd UPDATE about %s -- withdrawn", - peer->host, pfx_buf); - } + bgp = peer->bgp; + + /* Lookup node. */ + rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd); + + /* If peer is soft reconfiguration enabled. Record input packet for + * further calculation. + * + * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all + * routes that are filtered. This tanks out Quagga RS pretty badly due + * to + * the iteration over all RS clients. + * Since we need to remove the entry from adj_in anyway, do that first + * and + * if there was no entry, we don't need to do anything more. + */ + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) + && peer != bgp->peer_self) + if (!bgp_adj_in_unset(rn, peer, addpath_id)) { + if (bgp_debug_update(peer, p, NULL, 1)) { + bgp_debug_rdpfxpath2str( + afi, safi, prd, p, label, + addpath_id ? 1 : 0, addpath_id, pfx_buf, + sizeof(pfx_buf)); + zlog_debug( + "%s withdrawing route %s not in adj-in", + peer->host, pfx_buf); + } + bgp_unlock_node(rn); + return 0; + } - /* Withdraw specified route from routing table. */ - if (ri && ! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) - bgp_rib_withdraw (rn, ri, peer, afi, safi, prd); - else if (bgp_debug_update(peer, p, NULL, 1)) - { - bgp_debug_rdpfxpath2str (afi, safi, prd, p, label, - addpath_id ? 1 : 0, addpath_id, - pfx_buf, sizeof (pfx_buf)); - zlog_debug ("%s Can't find the route %s", - peer->host, pfx_buf); - } + /* Lookup withdrawn route. */ + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == peer && ri->type == type + && ri->sub_type == sub_type + && ri->addpath_rx_id == addpath_id) + break; + + /* Logging. */ + if (bgp_debug_update(peer, p, NULL, 1)) { + bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, + addpath_id ? 1 : 0, addpath_id, pfx_buf, + sizeof(pfx_buf)); + zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host, + pfx_buf); + } - /* Unlock bgp_node_get() lock. */ - bgp_unlock_node (rn); + /* Withdraw specified route from routing table. */ + if (ri && !CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) + bgp_rib_withdraw(rn, ri, peer, afi, safi, prd); + else if (bgp_debug_update(peer, p, NULL, 1)) { + bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, + addpath_id ? 1 : 0, addpath_id, pfx_buf, + sizeof(pfx_buf)); + zlog_debug("%s Can't find the route %s", peer->host, pfx_buf); + } - return 0; + /* Unlock bgp_node_get() lock. */ + bgp_unlock_node(rn); + + return 0; } -void -bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw) +void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi, + int withdraw) { - struct update_subgroup *subgrp; - subgrp = peer_subgroup(peer, afi, safi); - subgroup_default_originate(subgrp, withdraw); + struct update_subgroup *subgrp; + subgrp = peer_subgroup(peer, afi, safi); + subgroup_default_originate(subgrp, withdraw); } /* * bgp_stop_announce_route_timer */ -void -bgp_stop_announce_route_timer (struct peer_af *paf) +void bgp_stop_announce_route_timer(struct peer_af *paf) { - if (!paf->t_announce_route) - return; - - THREAD_TIMER_OFF (paf->t_announce_route); + if (!paf->t_announce_route) + return; + + THREAD_TIMER_OFF(paf->t_announce_route); } /* @@ -3249,23 +3257,22 @@ bgp_stop_announce_route_timer (struct peer_af *paf) * Callback that is invoked when the route announcement timer for a * peer_af expires. */ -static int -bgp_announce_route_timer_expired (struct thread *t) +static int bgp_announce_route_timer_expired(struct thread *t) { - struct peer_af *paf; - struct peer *peer; + struct peer_af *paf; + struct peer *peer; - paf = THREAD_ARG (t); - peer = paf->peer; + paf = THREAD_ARG(t); + peer = paf->peer; - if (peer->status != Established) - return 0; + if (peer->status != Established) + return 0; - if (!peer->afc_nego[paf->afi][paf->safi]) - return 0; + if (!peer->afc_nego[paf->afi][paf->safi]) + return 0; - peer_af_announce_route (paf, 1); - return 0; + peer_af_announce_route(paf, 1); + return 0; } /* @@ -3273,33 +3280,34 @@ bgp_announce_route_timer_expired (struct thread *t) * * *Triggers* announcement of routes of a given AFI/SAFI to a peer. */ -void -bgp_announce_route (struct peer *peer, afi_t afi, safi_t safi) -{ - struct peer_af *paf; - struct update_subgroup *subgrp; - - paf = peer_af_find (peer, afi, safi); - if (!paf) - return; - subgrp = PAF_SUBGRP(paf); - - /* - * Ignore if subgroup doesn't exist (implies AF is not negotiated) - * or a refresh has already been triggered. - */ - if (!subgrp || paf->t_announce_route) - return; - - /* - * Start a timer to stagger/delay the announce. This serves - * two purposes - announcement can potentially be combined for - * multiple peers and the announcement doesn't happen in the - * vty context. - */ - thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf, - (subgrp->peer_count == 1) ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS : BGP_ANNOUNCE_ROUTE_DELAY_MS, - &paf->t_announce_route); +void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi) +{ + struct peer_af *paf; + struct update_subgroup *subgrp; + + paf = peer_af_find(peer, afi, safi); + if (!paf) + return; + subgrp = PAF_SUBGRP(paf); + + /* + * Ignore if subgroup doesn't exist (implies AF is not negotiated) + * or a refresh has already been triggered. + */ + if (!subgrp || paf->t_announce_route) + return; + + /* + * Start a timer to stagger/delay the announce. This serves + * two purposes - announcement can potentially be combined for + * multiple peers and the announcement doesn't happen in the + * vty context. + */ + thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf, + (subgrp->peer_count == 1) + ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS + : BGP_ANNOUNCE_ROUTE_DELAY_MS, + &paf->t_announce_route); } /* @@ -3311,1385 +3319,1343 @@ bgp_announce_route (struct peer *peer, afi_t afi, safi_t safi) * The operation will result in splitting the peer from its existing * subgroups and putting it in new subgroups. */ -void -bgp_announce_route_all (struct peer *peer) +void bgp_announce_route_all(struct peer *peer) { - afi_t afi; - safi_t safi; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - bgp_announce_route (peer, afi, safi); + afi_t afi; + safi_t safi; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + bgp_announce_route(peer, afi, safi); } -static void -bgp_soft_reconfig_table (struct peer *peer, afi_t afi, safi_t safi, - struct bgp_table *table, struct prefix_rd *prd) +static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi, + struct bgp_table *table, + struct prefix_rd *prd) { - int ret; - struct bgp_node *rn; - struct bgp_adj_in *ain; + int ret; + struct bgp_node *rn; + struct bgp_adj_in *ain; - if (! table) - table = peer->bgp->rib[afi][safi]; + if (!table) + table = peer->bgp->rib[afi][safi]; - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - for (ain = rn->adj_in; ain; ain = ain->next) - { - if (ain->peer == peer) - { - struct bgp_info *ri = rn->info; - mpls_label_t label = (ri && ri->extra) ? ri->extra->label : MPLS_INVALID_LABEL; + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) + for (ain = rn->adj_in; ain; ain = ain->next) { + if (ain->peer == peer) { + struct bgp_info *ri = rn->info; + mpls_label_t label = + (ri && ri->extra) ? ri->extra->label + : MPLS_INVALID_LABEL; - ret = bgp_update (peer, &rn->p, ain->addpath_rx_id, ain->attr, - afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, - prd, &label, 1, NULL); + ret = bgp_update( + peer, &rn->p, ain->addpath_rx_id, + ain->attr, afi, safi, ZEBRA_ROUTE_BGP, + BGP_ROUTE_NORMAL, prd, &label, 1, NULL); - if (ret < 0) - { - bgp_unlock_node (rn); - return; - } - } - } + if (ret < 0) { + bgp_unlock_node(rn); + return; + } + } + } } -void -bgp_soft_reconfig_in (struct peer *peer, afi_t afi, safi_t safi) +void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi) { - struct bgp_node *rn; - struct bgp_table *table; + struct bgp_node *rn; + struct bgp_table *table; - if (peer->status != Established) - return; + if (peer->status != Established) + return; - if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP) && (safi != SAFI_EVPN)) - bgp_soft_reconfig_table (peer, afi, safi, NULL, NULL); - else - for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; - rn = bgp_route_next (rn)) - if ((table = rn->info) != NULL) - { - struct prefix_rd prd; - prd.family = AF_UNSPEC; - prd.prefixlen = 64; - memcpy(&prd.val, rn->p.u.val, 8); + if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP) + && (safi != SAFI_EVPN)) + bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL); + else + for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn; + rn = bgp_route_next(rn)) + if ((table = rn->info) != NULL) { + struct prefix_rd prd; + prd.family = AF_UNSPEC; + prd.prefixlen = 64; + memcpy(&prd.val, rn->p.u.val, 8); - bgp_soft_reconfig_table (peer, afi, safi, table, &prd); - } + bgp_soft_reconfig_table(peer, afi, safi, table, + &prd); + } } -struct bgp_clear_node_queue -{ - struct bgp_node *rn; +struct bgp_clear_node_queue { + struct bgp_node *rn; }; -static wq_item_status -bgp_clear_route_node (struct work_queue *wq, void *data) +static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data) { - struct bgp_clear_node_queue *cnq = data; - struct bgp_node *rn = cnq->rn; - struct peer *peer = wq->spec.data; - struct bgp_info *ri; - afi_t afi = bgp_node_table (rn)->afi; - safi_t safi = bgp_node_table (rn)->safi; - - assert (rn && peer); - - /* It is possible that we have multiple paths for a prefix from a peer - * if that peer is using AddPath. - */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == peer) - { - /* graceful restart STALE flag set. */ - if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT) - && peer->nsf[afi][safi] - && ! CHECK_FLAG (ri->flags, BGP_INFO_STALE) - && ! CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE)) - bgp_info_set_flag (rn, ri, BGP_INFO_STALE); - else - { - /* If this is an EVPN route, process for un-import. */ - if (safi == SAFI_EVPN) - bgp_evpn_unimport_route (peer->bgp, afi, safi, &rn->p, ri); - bgp_rib_remove (rn, ri, peer, afi, safi); - } - } - return WQ_SUCCESS; -} - -static void -bgp_clear_node_queue_del (struct work_queue *wq, void *data) -{ - struct bgp_clear_node_queue *cnq = data; - struct bgp_node *rn = cnq->rn; - struct bgp_table *table = bgp_node_table (rn); - - bgp_unlock_node (rn); - bgp_table_unlock (table); - XFREE (MTYPE_BGP_CLEAR_NODE_QUEUE, cnq); + struct bgp_clear_node_queue *cnq = data; + struct bgp_node *rn = cnq->rn; + struct peer *peer = wq->spec.data; + struct bgp_info *ri; + afi_t afi = bgp_node_table(rn)->afi; + safi_t safi = bgp_node_table(rn)->safi; + + assert(rn && peer); + + /* It is possible that we have multiple paths for a prefix from a peer + * if that peer is using AddPath. + */ + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == peer) { + /* graceful restart STALE flag set. */ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT) + && peer->nsf[afi][safi] + && !CHECK_FLAG(ri->flags, BGP_INFO_STALE) + && !CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE)) + bgp_info_set_flag(rn, ri, BGP_INFO_STALE); + else { + /* If this is an EVPN route, process for + * un-import. */ + if (safi == SAFI_EVPN) + bgp_evpn_unimport_route(peer->bgp, afi, + safi, &rn->p, + ri); + bgp_rib_remove(rn, ri, peer, afi, safi); + } + } + return WQ_SUCCESS; } -static void -bgp_clear_node_complete (struct work_queue *wq) +static void bgp_clear_node_queue_del(struct work_queue *wq, void *data) { - struct peer *peer = wq->spec.data; - - /* Tickle FSM to start moving again */ - BGP_EVENT_ADD (peer, Clearing_Completed); + struct bgp_clear_node_queue *cnq = data; + struct bgp_node *rn = cnq->rn; + struct bgp_table *table = bgp_node_table(rn); - peer_unlock (peer); /* bgp_clear_route */ + bgp_unlock_node(rn); + bgp_table_unlock(table); + XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq); } -static void -bgp_clear_node_queue_init (struct peer *peer) +static void bgp_clear_node_complete(struct work_queue *wq) { - char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")]; - - snprintf (wname, sizeof(wname), "clear %s", peer->host); -#undef CLEAR_QUEUE_NAME_LEN + struct peer *peer = wq->spec.data; - if ( (peer->clear_node_queue = work_queue_new (bm->master, wname)) == NULL) - { - zlog_err ("%s: Failed to allocate work queue", __func__); - exit (1); - } - peer->clear_node_queue->spec.hold = 10; - peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node; - peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del; - peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete; - peer->clear_node_queue->spec.max_retries = 0; - - /* we only 'lock' this peer reference when the queue is actually active */ - peer->clear_node_queue->spec.data = peer; + /* Tickle FSM to start moving again */ + BGP_EVENT_ADD(peer, Clearing_Completed); + + peer_unlock(peer); /* bgp_clear_route */ } -static void -bgp_clear_route_table (struct peer *peer, afi_t afi, safi_t safi, - struct bgp_table *table) +static void bgp_clear_node_queue_init(struct peer *peer) { - struct bgp_node *rn; - int force = bm->process_main_queue ? 0 : 1; - - if (! table) - table = peer->bgp->rib[afi][safi]; - - /* If still no table => afi/safi isn't configured at all or smth. */ - if (! table) - return; - - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - { - struct bgp_info *ri, *next; - struct bgp_adj_in *ain; - struct bgp_adj_in *ain_next; - - /* XXX:TODO: This is suboptimal, every non-empty route_node is - * queued for every clearing peer, regardless of whether it is - * relevant to the peer at hand. - * - * Overview: There are 3 different indices which need to be - * scrubbed, potentially, when a peer is removed: - * - * 1 peer's routes visible via the RIB (ie accepted routes) - * 2 peer's routes visible by the (optional) peer's adj-in index - * 3 other routes visible by the peer's adj-out index - * - * 3 there is no hurry in scrubbing, once the struct peer is - * removed from bgp->peer, we could just GC such deleted peer's - * adj-outs at our leisure. - * - * 1 and 2 must be 'scrubbed' in some way, at least made - * invisible via RIB index before peer session is allowed to be - * brought back up. So one needs to know when such a 'search' is - * complete. - * - * Ideally: - * - * - there'd be a single global queue or a single RIB walker - * - rather than tracking which route_nodes still need to be - * examined on a peer basis, we'd track which peers still - * aren't cleared - * - * Given that our per-peer prefix-counts now should be reliable, - * this may actually be achievable. It doesn't seem to be a huge - * problem at this time, - * - * It is possible that we have multiple paths for a prefix from a peer - * if that peer is using AddPath. - */ - ain = rn->adj_in; - while (ain) - { - ain_next = ain->next; - - if (ain->peer == peer) - { - bgp_adj_in_remove (rn, ain); - bgp_unlock_node (rn); - } - - ain = ain_next; - } - - for (ri = rn->info; ri; ri = next) - { - next = ri->next; - if (ri->peer != peer) - continue; - - if (force) - bgp_info_reap (rn, ri); - else - { - struct bgp_clear_node_queue *cnq; - - /* both unlocked in bgp_clear_node_queue_del */ - bgp_table_lock (bgp_node_table (rn)); - bgp_lock_node (rn); - cnq = XCALLOC (MTYPE_BGP_CLEAR_NODE_QUEUE, - sizeof (struct bgp_clear_node_queue)); - cnq->rn = rn; - work_queue_add (peer->clear_node_queue, cnq); - break; - } + char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")]; + + snprintf(wname, sizeof(wname), "clear %s", peer->host); +#undef CLEAR_QUEUE_NAME_LEN + + if ((peer->clear_node_queue = work_queue_new(bm->master, wname)) + == NULL) { + zlog_err("%s: Failed to allocate work queue", __func__); + exit(1); } - } - return; + peer->clear_node_queue->spec.hold = 10; + peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node; + peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del; + peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete; + peer->clear_node_queue->spec.max_retries = 0; + + /* we only 'lock' this peer reference when the queue is actually active + */ + peer->clear_node_queue->spec.data = peer; } -void -bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi) +static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi, + struct bgp_table *table) { - struct bgp_node *rn; - struct bgp_table *table; + struct bgp_node *rn; + int force = bm->process_main_queue ? 0 : 1; - if (peer->clear_node_queue == NULL) - bgp_clear_node_queue_init (peer); - - /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to - * Idle until it receives a Clearing_Completed event. This protects - * against peers which flap faster than we can we clear, which could - * lead to: - * - * a) race with routes from the new session being installed before - * clear_route_node visits the node (to delete the route of that - * peer) - * b) resource exhaustion, clear_route_node likely leads to an entry - * on the process_main queue. Fast-flapping could cause that queue - * to grow and grow. - */ - - /* lock peer in assumption that clear-node-queue will get nodes; if so, - * the unlock will happen upon work-queue completion; other wise, the - * unlock happens at the end of this function. - */ - if (!peer->clear_node_queue->thread) - peer_lock (peer); - - if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN) - bgp_clear_route_table (peer, afi, safi, NULL); - else - for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; - rn = bgp_route_next (rn)) - if ((table = rn->info) != NULL) - bgp_clear_route_table (peer, afi, safi, table); + if (!table) + table = peer->bgp->rib[afi][safi]; - /* unlock if no nodes got added to the clear-node-queue. */ - if (!peer->clear_node_queue->thread) - peer_unlock (peer); + /* If still no table => afi/safi isn't configured at all or smth. */ + if (!table) + return; + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { + struct bgp_info *ri, *next; + struct bgp_adj_in *ain; + struct bgp_adj_in *ain_next; + + /* XXX:TODO: This is suboptimal, every non-empty route_node is + * queued for every clearing peer, regardless of whether it is + * relevant to the peer at hand. + * + * Overview: There are 3 different indices which need to be + * scrubbed, potentially, when a peer is removed: + * + * 1 peer's routes visible via the RIB (ie accepted routes) + * 2 peer's routes visible by the (optional) peer's adj-in index + * 3 other routes visible by the peer's adj-out index + * + * 3 there is no hurry in scrubbing, once the struct peer is + * removed from bgp->peer, we could just GC such deleted peer's + * adj-outs at our leisure. + * + * 1 and 2 must be 'scrubbed' in some way, at least made + * invisible via RIB index before peer session is allowed to be + * brought back up. So one needs to know when such a 'search' is + * complete. + * + * Ideally: + * + * - there'd be a single global queue or a single RIB walker + * - rather than tracking which route_nodes still need to be + * examined on a peer basis, we'd track which peers still + * aren't cleared + * + * Given that our per-peer prefix-counts now should be reliable, + * this may actually be achievable. It doesn't seem to be a huge + * problem at this time, + * + * It is possible that we have multiple paths for a prefix from + * a peer + * if that peer is using AddPath. + */ + ain = rn->adj_in; + while (ain) { + ain_next = ain->next; + + if (ain->peer == peer) { + bgp_adj_in_remove(rn, ain); + bgp_unlock_node(rn); + } + + ain = ain_next; + } + + for (ri = rn->info; ri; ri = next) { + next = ri->next; + if (ri->peer != peer) + continue; + + if (force) + bgp_info_reap(rn, ri); + else { + struct bgp_clear_node_queue *cnq; + + /* both unlocked in bgp_clear_node_queue_del */ + bgp_table_lock(bgp_node_table(rn)); + bgp_lock_node(rn); + cnq = XCALLOC( + MTYPE_BGP_CLEAR_NODE_QUEUE, + sizeof(struct bgp_clear_node_queue)); + cnq->rn = rn; + work_queue_add(peer->clear_node_queue, cnq); + break; + } + } + } + return; +} + +void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi) +{ + struct bgp_node *rn; + struct bgp_table *table; + + if (peer->clear_node_queue == NULL) + bgp_clear_node_queue_init(peer); + + /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to + * Idle until it receives a Clearing_Completed event. This protects + * against peers which flap faster than we can we clear, which could + * lead to: + * + * a) race with routes from the new session being installed before + * clear_route_node visits the node (to delete the route of that + * peer) + * b) resource exhaustion, clear_route_node likely leads to an entry + * on the process_main queue. Fast-flapping could cause that queue + * to grow and grow. + */ + + /* lock peer in assumption that clear-node-queue will get nodes; if so, + * the unlock will happen upon work-queue completion; other wise, the + * unlock happens at the end of this function. + */ + if (!peer->clear_node_queue->thread) + peer_lock(peer); + + if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN) + bgp_clear_route_table(peer, afi, safi, NULL); + else + for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn; + rn = bgp_route_next(rn)) + if ((table = rn->info) != NULL) + bgp_clear_route_table(peer, afi, safi, table); + + /* unlock if no nodes got added to the clear-node-queue. */ + if (!peer->clear_node_queue->thread) + peer_unlock(peer); } - -void -bgp_clear_route_all (struct peer *peer) + +void bgp_clear_route_all(struct peer *peer) { - afi_t afi; - safi_t safi; + afi_t afi; + safi_t safi; - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - bgp_clear_route (peer, afi, safi); + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + bgp_clear_route(peer, afi, safi); #if ENABLE_BGP_VNC - rfapiProcessPeerDown(peer); + rfapiProcessPeerDown(peer); #endif } -void -bgp_clear_adj_in (struct peer *peer, afi_t afi, safi_t safi) +void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi) { - struct bgp_table *table; - struct bgp_node *rn; - struct bgp_adj_in *ain; - struct bgp_adj_in *ain_next; + struct bgp_table *table; + struct bgp_node *rn; + struct bgp_adj_in *ain; + struct bgp_adj_in *ain_next; - table = peer->bgp->rib[afi][safi]; + table = peer->bgp->rib[afi][safi]; - /* It is possible that we have multiple paths for a prefix from a peer - * if that peer is using AddPath. - */ - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - { - ain = rn->adj_in; + /* It is possible that we have multiple paths for a prefix from a peer + * if that peer is using AddPath. + */ + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { + ain = rn->adj_in; - while (ain) - { - ain_next = ain->next; + while (ain) { + ain_next = ain->next; - if (ain->peer == peer) - { - bgp_adj_in_remove (rn, ain); - bgp_unlock_node (rn); - } + if (ain->peer == peer) { + bgp_adj_in_remove(rn, ain); + bgp_unlock_node(rn); + } - ain = ain_next; - } - } + ain = ain_next; + } + } } -void -bgp_clear_stale_route (struct peer *peer, afi_t afi, safi_t safi) -{ - struct bgp_node *rn; - struct bgp_info *ri; - struct bgp_table *table; - - if ( safi == SAFI_MPLS_VPN) - { - for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; rn = bgp_route_next (rn)) - { - struct bgp_node *rm; - struct bgp_info *ri; - - /* look for neighbor in tables */ - if ((table = rn->info) != NULL) - { - for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm)) - for (ri = rm->info; ri; ri = ri->next) - if (ri->peer == peer) - { - if (CHECK_FLAG (ri->flags, BGP_INFO_STALE)) - bgp_rib_remove (rm, ri, peer, afi, safi); - break; - } - } - } - } - else - { - for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; rn = bgp_route_next (rn)) - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == peer) - { - if (CHECK_FLAG (ri->flags, BGP_INFO_STALE)) - bgp_rib_remove (rn, ri, peer, afi, safi); - break; - } - } +void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi) +{ + struct bgp_node *rn; + struct bgp_info *ri; + struct bgp_table *table; + + if (safi == SAFI_MPLS_VPN) { + for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn; + rn = bgp_route_next(rn)) { + struct bgp_node *rm; + struct bgp_info *ri; + + /* look for neighbor in tables */ + if ((table = rn->info) != NULL) { + for (rm = bgp_table_top(table); rm; + rm = bgp_route_next(rm)) + for (ri = rm->info; ri; ri = ri->next) + if (ri->peer == peer) { + if (CHECK_FLAG( + ri->flags, + BGP_INFO_STALE)) + bgp_rib_remove( + rm, ri, + peer, + afi, + safi); + break; + } + } + } + } else { + for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn; + rn = bgp_route_next(rn)) + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == peer) { + if (CHECK_FLAG(ri->flags, + BGP_INFO_STALE)) + bgp_rib_remove(rn, ri, peer, + afi, safi); + break; + } + } } -static void -bgp_cleanup_table(struct bgp_table *table, safi_t safi) +static void bgp_cleanup_table(struct bgp_table *table, safi_t safi) { - struct bgp_node *rn; - struct bgp_info *ri; - struct bgp_info *next; + struct bgp_node *rn; + struct bgp_info *ri; + struct bgp_info *next; - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - for (ri = rn->info; ri; ri = next) - { - next = ri->next; - if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) - && ri->type == ZEBRA_ROUTE_BGP - && (ri->sub_type == BGP_ROUTE_NORMAL || - ri->sub_type == BGP_ROUTE_AGGREGATE)) - { - if (bgp_fibupd_safi(safi)) - bgp_zebra_withdraw (&rn->p, ri, safi); - bgp_info_reap (rn, ri); - } - } + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) + for (ri = rn->info; ri; ri = next) { + next = ri->next; + if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED) + && ri->type == ZEBRA_ROUTE_BGP + && (ri->sub_type == BGP_ROUTE_NORMAL + || ri->sub_type == BGP_ROUTE_AGGREGATE)) { + if (bgp_fibupd_safi(safi)) + bgp_zebra_withdraw(&rn->p, ri, safi); + bgp_info_reap(rn, ri); + } + } } /* Delete all kernel routes. */ -void -bgp_cleanup_routes (struct bgp *bgp) -{ - afi_t afi; - struct bgp_node *rn; - - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - if (afi == AFI_L2VPN) - continue; - bgp_cleanup_table(bgp->rib[afi][SAFI_UNICAST], SAFI_UNICAST); - /* - * VPN and ENCAP and EVPN tables are two-level (RD is top level) - */ - if (afi != AFI_L2VPN) - { - safi_t safi; - safi = SAFI_MPLS_VPN; - for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; - rn = bgp_route_next (rn)) - { - if (rn->info) - { - bgp_cleanup_table((struct bgp_table *)(rn->info), safi); - bgp_table_finish ((struct bgp_table **)&(rn->info)); - rn->info = NULL; - bgp_unlock_node(rn); - } - } - safi = SAFI_ENCAP; - for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; - rn = bgp_route_next (rn)) - { - if (rn->info) - { - bgp_cleanup_table((struct bgp_table *)(rn->info), safi); - bgp_table_finish ((struct bgp_table **)&(rn->info)); - rn->info = NULL; - bgp_unlock_node(rn); - } - } +void bgp_cleanup_routes(struct bgp *bgp) +{ + afi_t afi; + struct bgp_node *rn; + + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + if (afi == AFI_L2VPN) + continue; + bgp_cleanup_table(bgp->rib[afi][SAFI_UNICAST], SAFI_UNICAST); + /* + * VPN and ENCAP and EVPN tables are two-level (RD is top level) + */ + if (afi != AFI_L2VPN) { + safi_t safi; + safi = SAFI_MPLS_VPN; + for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; + rn = bgp_route_next(rn)) { + if (rn->info) { + bgp_cleanup_table( + (struct bgp_table *)(rn->info), + safi); + bgp_table_finish((struct bgp_table **)&( + rn->info)); + rn->info = NULL; + bgp_unlock_node(rn); + } + } + safi = SAFI_ENCAP; + for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; + rn = bgp_route_next(rn)) { + if (rn->info) { + bgp_cleanup_table( + (struct bgp_table *)(rn->info), + safi); + bgp_table_finish((struct bgp_table **)&( + rn->info)); + rn->info = NULL; + bgp_unlock_node(rn); + } + } + } + } + for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn; + rn = bgp_route_next(rn)) { + if (rn->info) { + bgp_cleanup_table((struct bgp_table *)(rn->info), + SAFI_EVPN); + bgp_table_finish((struct bgp_table **)&(rn->info)); + rn->info = NULL; + bgp_unlock_node(rn); + } } - } - for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn; - rn = bgp_route_next (rn)) - { - if (rn->info) - { - bgp_cleanup_table((struct bgp_table *)(rn->info), SAFI_EVPN); - bgp_table_finish ((struct bgp_table **)&(rn->info)); - rn->info = NULL; - bgp_unlock_node(rn); - } - } } -void -bgp_reset (void) +void bgp_reset(void) { - vty_reset (); - bgp_zclient_reset (); - access_list_reset (); - prefix_list_reset (); + vty_reset(); + bgp_zclient_reset(); + access_list_reset(); + prefix_list_reset(); } -static int -bgp_addpath_encode_rx (struct peer *peer, afi_t afi, safi_t safi) +static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi) { - return (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) && - CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV)); + return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) + && CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ADDPATH_AF_TX_RCV)); } /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr value. */ -int -bgp_nlri_parse_ip (struct peer *peer, struct attr *attr, - struct bgp_nlri *packet) -{ - u_char *pnt; - u_char *lim; - struct prefix p; - int psize; - int ret; - afi_t afi; - safi_t safi; - int addpath_encoded; - u_int32_t addpath_id; - - /* Check peer status. */ - if (peer->status != Established) - return 0; - - pnt = packet->nlri; - lim = pnt + packet->length; - afi = packet->afi; - safi = packet->safi; - addpath_id = 0; - addpath_encoded = bgp_addpath_encode_rx (peer, afi, safi); - - /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for - syntactic validity. If the field is syntactically incorrect, - then the Error Subcode is set to Invalid Network Field. */ - for (; pnt < lim; pnt += psize) - { - /* Clear prefix structure. */ - memset (&p, 0, sizeof (struct prefix)); - - if (addpath_encoded) - { - - /* When packet overflow occurs return immediately. */ - if (pnt + BGP_ADDPATH_ID_LEN > lim) - return -1; - - addpath_id = ntohl(*((uint32_t*) pnt)); - pnt += BGP_ADDPATH_ID_LEN; - } - - /* Fetch prefix length. */ - p.prefixlen = *pnt++; - /* afi/safi validity already verified by caller, bgp_update_receive */ - p.family = afi2family (afi); - - /* Prefix length check. */ - if (p.prefixlen > prefix_blen (&p) * 8) - { - zlog_err("%s [Error] Update packet error (wrong perfix length %d for afi %u)", - peer->host, p.prefixlen, packet->afi); - return -1; - } - - /* Packet size overflow check. */ - psize = PSIZE (p.prefixlen); - - /* When packet overflow occur return immediately. */ - if (pnt + psize > lim) - { - zlog_err("%s [Error] Update packet error (prefix length %d overflows packet)", - peer->host, p.prefixlen); - return -1; - } - - /* Defensive coding, double-check the psize fits in a struct prefix */ - if (psize > (ssize_t) sizeof(p.u)) - { - zlog_err("%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)", - peer->host, p.prefixlen, sizeof(p.u)); - return -1; - } - - /* Fetch prefix from NLRI packet. */ - memcpy (&p.u.prefix, pnt, psize); - - /* Check address. */ - if (afi == AFI_IP && safi == SAFI_UNICAST) - { - if (IN_CLASSD (ntohl (p.u.prefix4.s_addr))) - { - /* From RFC4271 Section 6.3: - * - * If a prefix in the NLRI field is semantically incorrect - * (e.g., an unexpected multicast IP address), an error SHOULD - * be logged locally, and the prefix SHOULD be ignored. - */ - zlog_err ("%s: IPv4 unicast NLRI is multicast address %s, ignoring", - peer->host, inet_ntoa (p.u.prefix4)); - continue; - } - } - - /* Check address. */ - if (afi == AFI_IP6 && safi == SAFI_UNICAST) - { - if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6)) - { - char buf[BUFSIZ]; - - zlog_err ("%s: IPv6 unicast NLRI is link-local address %s, ignoring", - peer->host, inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ)); - - continue; - } - if (IN6_IS_ADDR_MULTICAST (&p.u.prefix6)) - { - char buf[BUFSIZ]; - - zlog_err ("%s: IPv6 unicast NLRI is multicast address %s, ignoring", - peer->host, inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ)); - - continue; - } - } - - /* Normal process. */ - if (attr) - ret = bgp_update (peer, &p, addpath_id, attr, afi, safi, - ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL, 0, NULL); - else - ret = bgp_withdraw (peer, &p, addpath_id, attr, afi, safi, - ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL, NULL); - - /* Address family configuration mismatch or maximum-prefix count - overflow. */ - if (ret < 0) - return -1; - } +int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr, + struct bgp_nlri *packet) +{ + u_char *pnt; + u_char *lim; + struct prefix p; + int psize; + int ret; + afi_t afi; + safi_t safi; + int addpath_encoded; + u_int32_t addpath_id; + + /* Check peer status. */ + if (peer->status != Established) + return 0; + + pnt = packet->nlri; + lim = pnt + packet->length; + afi = packet->afi; + safi = packet->safi; + addpath_id = 0; + addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi); + + /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for + syntactic validity. If the field is syntactically incorrect, + then the Error Subcode is set to Invalid Network Field. */ + for (; pnt < lim; pnt += psize) { + /* Clear prefix structure. */ + memset(&p, 0, sizeof(struct prefix)); + + if (addpath_encoded) { + + /* When packet overflow occurs return immediately. */ + if (pnt + BGP_ADDPATH_ID_LEN > lim) + return -1; + + addpath_id = ntohl(*((uint32_t *)pnt)); + pnt += BGP_ADDPATH_ID_LEN; + } - /* Packet length consistency check. */ - if (pnt != lim) - { - zlog_err ("%s [Error] Update packet error (prefix length mismatch with total length)", - peer->host); - return -1; - } + /* Fetch prefix length. */ + p.prefixlen = *pnt++; + /* afi/safi validity already verified by caller, + * bgp_update_receive */ + p.family = afi2family(afi); + + /* Prefix length check. */ + if (p.prefixlen > prefix_blen(&p) * 8) { + zlog_err( + "%s [Error] Update packet error (wrong perfix length %d for afi %u)", + peer->host, p.prefixlen, packet->afi); + return -1; + } - return 0; -} + /* Packet size overflow check. */ + psize = PSIZE(p.prefixlen); + + /* When packet overflow occur return immediately. */ + if (pnt + psize > lim) { + zlog_err( + "%s [Error] Update packet error (prefix length %d overflows packet)", + peer->host, p.prefixlen); + return -1; + } + + /* Defensive coding, double-check the psize fits in a struct + * prefix */ + if (psize > (ssize_t)sizeof(p.u)) { + zlog_err( + "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)", + peer->host, p.prefixlen, sizeof(p.u)); + return -1; + } + + /* Fetch prefix from NLRI packet. */ + memcpy(&p.u.prefix, pnt, psize); + + /* Check address. */ + if (afi == AFI_IP && safi == SAFI_UNICAST) { + if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) { + /* From RFC4271 Section 6.3: + * + * If a prefix in the NLRI field is semantically + * incorrect + * (e.g., an unexpected multicast IP address), + * an error SHOULD + * be logged locally, and the prefix SHOULD be + * ignored. + */ + zlog_err( + "%s: IPv4 unicast NLRI is multicast address %s, ignoring", + peer->host, inet_ntoa(p.u.prefix4)); + continue; + } + } + + /* Check address. */ + if (afi == AFI_IP6 && safi == SAFI_UNICAST) { + if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) { + char buf[BUFSIZ]; + + zlog_err( + "%s: IPv6 unicast NLRI is link-local address %s, ignoring", + peer->host, + inet_ntop(AF_INET6, &p.u.prefix6, buf, + BUFSIZ)); + + continue; + } + if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) { + char buf[BUFSIZ]; + + zlog_err( + "%s: IPv6 unicast NLRI is multicast address %s, ignoring", + peer->host, + inet_ntop(AF_INET6, &p.u.prefix6, buf, + BUFSIZ)); + + continue; + } + } + + /* Normal process. */ + if (attr) + ret = bgp_update(peer, &p, addpath_id, attr, afi, safi, + ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, + NULL, NULL, 0, NULL); + else + ret = bgp_withdraw(peer, &p, addpath_id, attr, afi, + safi, ZEBRA_ROUTE_BGP, + BGP_ROUTE_NORMAL, NULL, NULL, NULL); + + /* Address family configuration mismatch or maximum-prefix count + overflow. */ + if (ret < 0) + return -1; + } + + /* Packet length consistency check. */ + if (pnt != lim) { + zlog_err( + "%s [Error] Update packet error (prefix length mismatch with total length)", + peer->host); + return -1; + } -static struct bgp_static * -bgp_static_new (void) -{ - return XCALLOC (MTYPE_BGP_STATIC, sizeof (struct bgp_static)); + return 0; } -static void -bgp_static_free (struct bgp_static *bgp_static) +static struct bgp_static *bgp_static_new(void) { - if (bgp_static->rmap.name) - XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name); - if(bgp_static->eth_s_id) - XFREE(MTYPE_ATTR, bgp_static->eth_s_id); - XFREE (MTYPE_BGP_STATIC, bgp_static); + return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static)); } -void -bgp_static_update (struct bgp *bgp, struct prefix *p, - struct bgp_static *bgp_static, afi_t afi, safi_t safi) +static void bgp_static_free(struct bgp_static *bgp_static) { - struct bgp_node *rn; - struct bgp_info *ri; - struct bgp_info *new; - struct bgp_info info; - struct attr attr; - struct attr *attr_new; - int ret; + if (bgp_static->rmap.name) + XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name); + if (bgp_static->eth_s_id) + XFREE(MTYPE_ATTR, bgp_static->eth_s_id); + XFREE(MTYPE_BGP_STATIC, bgp_static); +} + +void bgp_static_update(struct bgp *bgp, struct prefix *p, + struct bgp_static *bgp_static, afi_t afi, safi_t safi) +{ + struct bgp_node *rn; + struct bgp_info *ri; + struct bgp_info *new; + struct bgp_info info; + struct attr attr; + struct attr *attr_new; + int ret; #if ENABLE_BGP_VNC - int vnc_implicit_withdraw = 0; + int vnc_implicit_withdraw = 0; #endif - assert (bgp_static); - if (!bgp_static) - return; + assert(bgp_static); + if (!bgp_static) + return; - rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, NULL); + rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL); - bgp_attr_default_set (&attr, BGP_ORIGIN_IGP); - - attr.nexthop = bgp_static->igpnexthop; - attr.med = bgp_static->igpmetric; - attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); + bgp_attr_default_set(&attr, BGP_ORIGIN_IGP); - if (bgp_static->atomic) - attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE); + attr.nexthop = bgp_static->igpnexthop; + attr.med = bgp_static->igpmetric; + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); - /* Store label index, if required. */ - if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) - { - attr.label_index = bgp_static->label_index; - attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID); - } + if (bgp_static->atomic) + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE); - /* Apply route-map. */ - if (bgp_static->rmap.name) - { - struct attr attr_tmp = attr; - info.peer = bgp->peer_self; - info.attr = &attr_tmp; + /* Store label index, if required. */ + if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) { + attr.label_index = bgp_static->label_index; + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID); + } - SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK); + /* Apply route-map. */ + if (bgp_static->rmap.name) { + struct attr attr_tmp = attr; + info.peer = bgp->peer_self; + info.attr = &attr_tmp; - ret = route_map_apply (bgp_static->rmap.map, p, RMAP_BGP, &info); + SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK); - bgp->peer_self->rmap_type = 0; + ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP, &info); - if (ret == RMAP_DENYMATCH) - { - /* Free uninterned attribute. */ - bgp_attr_flush (&attr_tmp); + bgp->peer_self->rmap_type = 0; - /* Unintern original. */ - aspath_unintern (&attr.aspath); - bgp_static_withdraw (bgp, p, afi, safi); - return; - } - attr_new = bgp_attr_intern (&attr_tmp); - } - else - attr_new = bgp_attr_intern (&attr); + if (ret == RMAP_DENYMATCH) { + /* Free uninterned attribute. */ + bgp_attr_flush(&attr_tmp); - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_STATIC) - break; + /* Unintern original. */ + aspath_unintern(&attr.aspath); + bgp_static_withdraw(bgp, p, afi, safi); + return; + } + attr_new = bgp_attr_intern(&attr_tmp); + } else + attr_new = bgp_attr_intern(&attr); - if (ri) - { - if (attrhash_cmp (ri->attr, attr_new) && - !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED) && - !bgp_flag_check(bgp, BGP_FLAG_FORCE_STATIC_PROCESS)) - { - bgp_unlock_node (rn); - bgp_attr_unintern (&attr_new); - aspath_unintern (&attr.aspath); - return; - } - else - { - /* The attribute is changed. */ - bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); - - /* Rewrite BGP route information. */ - if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) - bgp_info_restore(rn, ri); - else - bgp_aggregate_decrement (bgp, p, ri, afi, safi); + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP + && ri->sub_type == BGP_ROUTE_STATIC) + break; + + if (ri) { + if (attrhash_cmp(ri->attr, attr_new) + && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED) + && !bgp_flag_check(bgp, BGP_FLAG_FORCE_STATIC_PROCESS)) { + bgp_unlock_node(rn); + bgp_attr_unintern(&attr_new); + aspath_unintern(&attr.aspath); + return; + } else { + /* The attribute is changed. */ + bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED); + + /* Rewrite BGP route information. */ + if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) + bgp_info_restore(rn, ri); + else + bgp_aggregate_decrement(bgp, p, ri, afi, safi); #if ENABLE_BGP_VNC - if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) - { - if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) - { - /* - * Implicit withdraw case. - * We have to do this before ri is changed - */ - ++vnc_implicit_withdraw; - vnc_import_bgp_del_route(bgp, p, ri); - vnc_import_bgp_exterior_del_route(bgp, p, ri); - } - } + if ((afi == AFI_IP || afi == AFI_IP6) + && (safi == SAFI_UNICAST)) { + if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) { + /* + * Implicit withdraw case. + * We have to do this before ri is + * changed + */ + ++vnc_implicit_withdraw; + vnc_import_bgp_del_route(bgp, p, ri); + vnc_import_bgp_exterior_del_route( + bgp, p, ri); + } + } #endif - bgp_attr_unintern (&ri->attr); - ri->attr = attr_new; - ri->uptime = bgp_clock (); + bgp_attr_unintern(&ri->attr); + ri->attr = attr_new; + ri->uptime = bgp_clock(); #if ENABLE_BGP_VNC - if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) - { - if (vnc_implicit_withdraw) - { - vnc_import_bgp_add_route(bgp, p, ri); - vnc_import_bgp_exterior_add_route(bgp, p, ri); - } - } + if ((afi == AFI_IP || afi == AFI_IP6) + && (safi == SAFI_UNICAST)) { + if (vnc_implicit_withdraw) { + vnc_import_bgp_add_route(bgp, p, ri); + vnc_import_bgp_exterior_add_route( + bgp, p, ri); + } + } #endif - /* Nexthop reachability check. */ - if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK) && - (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) - { - if (bgp_find_or_add_nexthop (bgp, afi, ri, NULL, 0)) - bgp_info_set_flag (rn, ri, BGP_INFO_VALID); - else - { - if (BGP_DEBUG(nht, NHT)) - { - char buf1[INET6_ADDRSTRLEN]; - inet_ntop(p->family, &p->u.prefix, buf1, - INET6_ADDRSTRLEN); - zlog_debug("%s(%s): Route not in table, not advertising", - __FUNCTION__, buf1); - } - bgp_info_unset_flag (rn, ri, BGP_INFO_VALID); - } - } - else - { - /* Delete the NHT structure if any, if we're toggling between - * enabling/disabling import check. We deregister the route - * from NHT to avoid overloading NHT and the process interaction - */ - bgp_unlink_nexthop(ri); - bgp_info_set_flag (rn, ri, BGP_INFO_VALID); - } - /* Process change. */ - bgp_aggregate_increment (bgp, p, ri, afi, safi); - bgp_process (bgp, rn, afi, safi); - bgp_unlock_node (rn); - aspath_unintern (&attr.aspath); - return; + /* Nexthop reachability check. */ + if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK) + && (safi == SAFI_UNICAST + || safi == SAFI_LABELED_UNICAST)) { + if (bgp_find_or_add_nexthop(bgp, afi, ri, NULL, + 0)) + bgp_info_set_flag(rn, ri, + BGP_INFO_VALID); + else { + if (BGP_DEBUG(nht, NHT)) { + char buf1[INET6_ADDRSTRLEN]; + inet_ntop(p->family, + &p->u.prefix, buf1, + INET6_ADDRSTRLEN); + zlog_debug( + "%s(%s): Route not in table, not advertising", + __FUNCTION__, buf1); + } + bgp_info_unset_flag(rn, ri, + BGP_INFO_VALID); + } + } else { + /* Delete the NHT structure if any, if we're + * toggling between + * enabling/disabling import check. We + * deregister the route + * from NHT to avoid overloading NHT and the + * process interaction + */ + bgp_unlink_nexthop(ri); + bgp_info_set_flag(rn, ri, BGP_INFO_VALID); + } + /* Process change. */ + bgp_aggregate_increment(bgp, p, ri, afi, safi); + bgp_process(bgp, rn, afi, safi); + bgp_unlock_node(rn); + aspath_unintern(&attr.aspath); + return; + } } - } - /* Make new BGP info. */ - new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self, attr_new, - rn); - /* Nexthop reachability check. */ - if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK) && - (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) - { - if (bgp_find_or_add_nexthop (bgp, afi, new, NULL, 0)) - bgp_info_set_flag (rn, new, BGP_INFO_VALID); - else - { - if (BGP_DEBUG(nht, NHT)) - { - char buf1[INET6_ADDRSTRLEN]; - inet_ntop(p->family, &p->u.prefix, buf1, - INET6_ADDRSTRLEN); - zlog_debug("%s(%s): Route not in table, not advertising", - __FUNCTION__, buf1); - } - bgp_info_unset_flag (rn, new, BGP_INFO_VALID); + /* Make new BGP info. */ + new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self, + attr_new, rn); + /* Nexthop reachability check. */ + if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK) + && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) { + if (bgp_find_or_add_nexthop(bgp, afi, new, NULL, 0)) + bgp_info_set_flag(rn, new, BGP_INFO_VALID); + else { + if (BGP_DEBUG(nht, NHT)) { + char buf1[INET6_ADDRSTRLEN]; + inet_ntop(p->family, &p->u.prefix, buf1, + INET6_ADDRSTRLEN); + zlog_debug( + "%s(%s): Route not in table, not advertising", + __FUNCTION__, buf1); + } + bgp_info_unset_flag(rn, new, BGP_INFO_VALID); + } + } else { + /* Delete the NHT structure if any, if we're toggling between + * enabling/disabling import check. We deregister the route + * from NHT to avoid overloading NHT and the process interaction + */ + bgp_unlink_nexthop(new); + + bgp_info_set_flag(rn, new, BGP_INFO_VALID); } - } - else - { - /* Delete the NHT structure if any, if we're toggling between - * enabling/disabling import check. We deregister the route - * from NHT to avoid overloading NHT and the process interaction - */ - bgp_unlink_nexthop(new); - bgp_info_set_flag (rn, new, BGP_INFO_VALID); - } + /* Aggregate address increment. */ + bgp_aggregate_increment(bgp, p, new, afi, safi); - /* Aggregate address increment. */ - bgp_aggregate_increment (bgp, p, new, afi, safi); - - /* Register new BGP information. */ - bgp_info_add (rn, new); - - /* route_node_get lock */ - bgp_unlock_node (rn); - - /* Process change. */ - bgp_process (bgp, rn, afi, safi); + /* Register new BGP information. */ + bgp_info_add(rn, new); - /* Unintern original. */ - aspath_unintern (&attr.aspath); + /* route_node_get lock */ + bgp_unlock_node(rn); + + /* Process change. */ + bgp_process(bgp, rn, afi, safi); + + /* Unintern original. */ + aspath_unintern(&attr.aspath); } -void -bgp_static_withdraw (struct bgp *bgp, struct prefix *p, afi_t afi, - safi_t safi) +void bgp_static_withdraw(struct bgp *bgp, struct prefix *p, afi_t afi, + safi_t safi) { - struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_node *rn; + struct bgp_info *ri; - rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, NULL); + rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL); - /* Check selected route and self inserted route. */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self - && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_STATIC) - break; - - /* Withdraw static BGP route from routing table. */ - if (ri) - { - bgp_aggregate_decrement (bgp, p, ri, afi, safi); - bgp_unlink_nexthop(ri); - bgp_info_delete (rn, ri); - bgp_process (bgp, rn, afi, safi); - } + /* Check selected route and self inserted route. */ + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP + && ri->sub_type == BGP_ROUTE_STATIC) + break; + + /* Withdraw static BGP route from routing table. */ + if (ri) { + bgp_aggregate_decrement(bgp, p, ri, afi, safi); + bgp_unlink_nexthop(ri); + bgp_info_delete(rn, ri); + bgp_process(bgp, rn, afi, safi); + } - /* Unlock bgp_node_lookup. */ - bgp_unlock_node (rn); + /* Unlock bgp_node_lookup. */ + bgp_unlock_node(rn); } /* * Used for SAFI_MPLS_VPN and SAFI_ENCAP */ -static void -bgp_static_withdraw_safi (struct bgp *bgp, struct prefix *p, afi_t afi, - safi_t safi, struct prefix_rd *prd) +static void bgp_static_withdraw_safi(struct bgp *bgp, struct prefix *p, + afi_t afi, safi_t safi, + struct prefix_rd *prd) { - struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_node *rn; + struct bgp_info *ri; - rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd); + rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd); - /* Check selected route and self inserted route. */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self - && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_STATIC) - break; + /* Check selected route and self inserted route. */ + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP + && ri->sub_type == BGP_ROUTE_STATIC) + break; - /* Withdraw static BGP route from routing table. */ - if (ri) - { + /* Withdraw static BGP route from routing table. */ + if (ri) { #if ENABLE_BGP_VNC - rfapiProcessWithdraw( - ri->peer, - NULL, - p, - prd, - ri->attr, - afi, - safi, - ri->type, - 1); /* Kill, since it is an administrative change */ + rfapiProcessWithdraw( + ri->peer, NULL, p, prd, ri->attr, afi, safi, ri->type, + 1); /* Kill, since it is an administrative change */ #endif - bgp_aggregate_decrement (bgp, p, ri, afi, safi); - bgp_info_delete (rn, ri); - bgp_process (bgp, rn, afi, safi); - } + bgp_aggregate_decrement(bgp, p, ri, afi, safi); + bgp_info_delete(rn, ri); + bgp_process(bgp, rn, afi, safi); + } - /* Unlock bgp_node_lookup. */ - bgp_unlock_node (rn); + /* Unlock bgp_node_lookup. */ + bgp_unlock_node(rn); } -static void -bgp_static_update_safi (struct bgp *bgp, struct prefix *p, - struct bgp_static *bgp_static, afi_t afi, safi_t safi) +static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p, + struct bgp_static *bgp_static, afi_t afi, + safi_t safi) { - struct bgp_node *rn; - struct bgp_info *new; - struct attr *attr_new; - struct attr attr = { 0 }; - struct bgp_info *ri; + struct bgp_node *rn; + struct bgp_info *new; + struct attr *attr_new; + struct attr attr = {0}; + struct bgp_info *ri; #if ENABLE_BGP_VNC - mpls_label_t label = 0; + mpls_label_t label = 0; #endif - union gw_addr add; - - assert (bgp_static); + union gw_addr add; - rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, &bgp_static->prd); + assert(bgp_static); - bgp_attr_default_set (&attr, BGP_ORIGIN_IGP); + rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, + &bgp_static->prd); - attr.nexthop = bgp_static->igpnexthop; - attr.med = bgp_static->igpmetric; - attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); + bgp_attr_default_set(&attr, BGP_ORIGIN_IGP); - if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) - { - if (afi == AFI_IP) - { - attr.mp_nexthop_global_in = bgp_static->igpnexthop; - attr.mp_nexthop_len = IPV4_MAX_BYTELEN; - } - } - if(afi == AFI_L2VPN) - { - if (bgp_static->gatewayIp.family == AF_INET) - add.ipv4.s_addr = bgp_static->gatewayIp.u.prefix4.s_addr; - else if (bgp_static->gatewayIp.family == AF_INET6) - memcpy( &(add.ipv6), &(bgp_static->gatewayIp.u.prefix6), sizeof (struct in6_addr)); - overlay_index_update(&attr, bgp_static->eth_s_id, &add); - if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) - { - struct bgp_encap_type_vxlan bet; - memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan)); - bet.vnid = p->u.prefix_evpn.eth_tag; - bgp_encap_type_vxlan_to_tlv(&bet, &attr); - } - if (bgp_static->router_mac) - { - bgp_add_routermac_ecom (&attr, bgp_static->router_mac); - } - } - /* Apply route-map. */ - if (bgp_static->rmap.name) - { - struct attr attr_tmp = attr; - struct bgp_info info; - int ret; + attr.nexthop = bgp_static->igpnexthop; + attr.med = bgp_static->igpmetric; + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); - info.peer = bgp->peer_self; - info.attr = &attr_tmp; + if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN) + || (safi == SAFI_ENCAP)) { + if (afi == AFI_IP) { + attr.mp_nexthop_global_in = bgp_static->igpnexthop; + attr.mp_nexthop_len = IPV4_MAX_BYTELEN; + } + } + if (afi == AFI_L2VPN) { + if (bgp_static->gatewayIp.family == AF_INET) + add.ipv4.s_addr = + bgp_static->gatewayIp.u.prefix4.s_addr; + else if (bgp_static->gatewayIp.family == AF_INET6) + memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6), + sizeof(struct in6_addr)); + overlay_index_update(&attr, bgp_static->eth_s_id, &add); + if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) { + struct bgp_encap_type_vxlan bet; + memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan)); + bet.vnid = p->u.prefix_evpn.eth_tag; + bgp_encap_type_vxlan_to_tlv(&bet, &attr); + } + if (bgp_static->router_mac) { + bgp_add_routermac_ecom(&attr, bgp_static->router_mac); + } + } + /* Apply route-map. */ + if (bgp_static->rmap.name) { + struct attr attr_tmp = attr; + struct bgp_info info; + int ret; - SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK); + info.peer = bgp->peer_self; + info.attr = &attr_tmp; - ret = route_map_apply (bgp_static->rmap.map, p, RMAP_BGP, &info); + SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK); - bgp->peer_self->rmap_type = 0; + ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP, &info); - if (ret == RMAP_DENYMATCH) - { - /* Free uninterned attribute. */ - bgp_attr_flush (&attr_tmp); + bgp->peer_self->rmap_type = 0; - /* Unintern original. */ - aspath_unintern (&attr.aspath); - bgp_static_withdraw_safi (bgp, p, afi, safi, &bgp_static->prd); - return; - } + if (ret == RMAP_DENYMATCH) { + /* Free uninterned attribute. */ + bgp_attr_flush(&attr_tmp); - attr_new = bgp_attr_intern (&attr_tmp); - } - else - { - attr_new = bgp_attr_intern (&attr); - } + /* Unintern original. */ + aspath_unintern(&attr.aspath); + bgp_static_withdraw_safi(bgp, p, afi, safi, + &bgp_static->prd); + return; + } - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_STATIC) - break; + attr_new = bgp_attr_intern(&attr_tmp); + } else { + attr_new = bgp_attr_intern(&attr); + } - if (ri) - { - union gw_addr add; - memset(&add, 0, sizeof(union gw_addr)); - if (attrhash_cmp (ri->attr, attr_new) && - overlay_index_equal(afi, ri, bgp_static->eth_s_id, &add) && - !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) - { - bgp_unlock_node (rn); - bgp_attr_unintern (&attr_new); - aspath_unintern (&attr.aspath); - return; - } - else - { - /* The attribute is changed. */ - bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); - - /* Rewrite BGP route information. */ - if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) - bgp_info_restore(rn, ri); - else - bgp_aggregate_decrement (bgp, p, ri, afi, safi); - bgp_attr_unintern (&ri->attr); - ri->attr = attr_new; - ri->uptime = bgp_clock (); + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP + && ri->sub_type == BGP_ROUTE_STATIC) + break; + + if (ri) { + union gw_addr add; + memset(&add, 0, sizeof(union gw_addr)); + if (attrhash_cmp(ri->attr, attr_new) + && overlay_index_equal(afi, ri, bgp_static->eth_s_id, &add) + && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { + bgp_unlock_node(rn); + bgp_attr_unintern(&attr_new); + aspath_unintern(&attr.aspath); + return; + } else { + /* The attribute is changed. */ + bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED); + + /* Rewrite BGP route information. */ + if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) + bgp_info_restore(rn, ri); + else + bgp_aggregate_decrement(bgp, p, ri, afi, safi); + bgp_attr_unintern(&ri->attr); + ri->attr = attr_new; + ri->uptime = bgp_clock(); #if ENABLE_BGP_VNC - if (ri->extra) - label = decode_label (&ri->extra->label); + if (ri->extra) + label = decode_label(&ri->extra->label); #endif - /* Process change. */ - bgp_aggregate_increment (bgp, p, ri, afi, safi); - bgp_process (bgp, rn, afi, safi); + /* Process change. */ + bgp_aggregate_increment(bgp, p, ri, afi, safi); + bgp_process(bgp, rn, afi, safi); #if ENABLE_BGP_VNC - rfapiProcessUpdate(ri->peer, NULL, p, &bgp_static->prd, - ri->attr, afi, safi, - ri->type, ri->sub_type, &label); + rfapiProcessUpdate(ri->peer, NULL, p, &bgp_static->prd, + ri->attr, afi, safi, ri->type, + ri->sub_type, &label); #endif - bgp_unlock_node (rn); - aspath_unintern (&attr.aspath); - return; - } - } + bgp_unlock_node(rn); + aspath_unintern(&attr.aspath); + return; + } + } - /* Make new BGP info. */ - new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self, attr_new, - rn); - SET_FLAG (new->flags, BGP_INFO_VALID); - new->extra = bgp_info_extra_new(); - new->extra->label = bgp_static->label; + /* Make new BGP info. */ + new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self, + attr_new, rn); + SET_FLAG(new->flags, BGP_INFO_VALID); + new->extra = bgp_info_extra_new(); + new->extra->label = bgp_static->label; #if ENABLE_BGP_VNC - label = decode_label (&bgp_static->label); + label = decode_label(&bgp_static->label); #endif - /* Aggregate address increment. */ - bgp_aggregate_increment (bgp, p, new, afi, safi); + /* Aggregate address increment. */ + bgp_aggregate_increment(bgp, p, new, afi, safi); - /* Register new BGP information. */ - bgp_info_add (rn, new); - /* route_node_get lock */ - bgp_unlock_node (rn); + /* Register new BGP information. */ + bgp_info_add(rn, new); + /* route_node_get lock */ + bgp_unlock_node(rn); - /* Process change. */ - bgp_process (bgp, rn, afi, safi); + /* Process change. */ + bgp_process(bgp, rn, afi, safi); #if ENABLE_BGP_VNC - rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, - new->attr, afi, safi, - new->type, new->sub_type, &label); + rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi, + safi, new->type, new->sub_type, &label); #endif - /* Unintern original. */ - aspath_unintern (&attr.aspath); + /* Unintern original. */ + aspath_unintern(&attr.aspath); } /* Configure static BGP network. When user don't run zebra, static route should be installed as valid. */ -static int -bgp_static_set (struct vty *vty, const char *ip_str, - afi_t afi, safi_t safi, const char *rmap, int backdoor, - u_int32_t label_index) -{ - VTY_DECLVAR_CONTEXT(bgp, bgp); - int ret; - struct prefix p; - struct bgp_static *bgp_static; - struct bgp_node *rn; - u_char need_update = 0; - - /* Convert IP prefix string to struct prefix. */ - ret = str2prefix (ip_str, &p); - if (! ret) - { - vty_out (vty, "%% Malformed prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6)) - { - vty_out (vty,"%% Malformed prefix (link-local address)\n"); - return CMD_WARNING_CONFIG_FAILED; - } +static int bgp_static_set(struct vty *vty, const char *ip_str, afi_t afi, + safi_t safi, const char *rmap, int backdoor, + u_int32_t label_index) +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + int ret; + struct prefix p; + struct bgp_static *bgp_static; + struct bgp_node *rn; + u_char need_update = 0; + + /* Convert IP prefix string to struct prefix. */ + ret = str2prefix(ip_str, &p); + if (!ret) { + vty_out(vty, "%% Malformed prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) { + vty_out(vty, "%% Malformed prefix (link-local address)\n"); + return CMD_WARNING_CONFIG_FAILED; + } - apply_mask (&p); + apply_mask(&p); - /* Set BGP static route configuration. */ - rn = bgp_node_get (bgp->route[afi][safi], &p); + /* Set BGP static route configuration. */ + rn = bgp_node_get(bgp->route[afi][safi], &p); - if (rn->info) - { - /* Configuration change. */ - bgp_static = rn->info; - - /* Label index cannot be changed. */ - if (bgp_static->label_index != label_index) - { - vty_out (vty, "%% Label index cannot be changed\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check previous routes are installed into BGP. */ - if (bgp_static->valid && bgp_static->backdoor != backdoor) - need_update = 1; - - bgp_static->backdoor = backdoor; - - if (rmap) - { - if (bgp_static->rmap.name) - XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name); - bgp_static->rmap.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); - bgp_static->rmap.map = route_map_lookup_by_name (rmap); - } - else - { - if (bgp_static->rmap.name) - XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name); - bgp_static->rmap.name = NULL; - bgp_static->rmap.map = NULL; - bgp_static->valid = 0; - } - bgp_unlock_node (rn); - } - else - { - /* New configuration. */ - bgp_static = bgp_static_new (); - bgp_static->backdoor = backdoor; - bgp_static->valid = 0; - bgp_static->igpmetric = 0; - bgp_static->igpnexthop.s_addr = 0; - bgp_static->label_index = label_index; - - if (rmap) - { - if (bgp_static->rmap.name) - XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name); - bgp_static->rmap.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); - bgp_static->rmap.map = route_map_lookup_by_name (rmap); - } - rn->info = bgp_static; - } + if (rn->info) { + /* Configuration change. */ + bgp_static = rn->info; + + /* Label index cannot be changed. */ + if (bgp_static->label_index != label_index) { + vty_out(vty, "%% Label index cannot be changed\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Check previous routes are installed into BGP. */ + if (bgp_static->valid && bgp_static->backdoor != backdoor) + need_update = 1; + + bgp_static->backdoor = backdoor; + + if (rmap) { + if (bgp_static->rmap.name) + XFREE(MTYPE_ROUTE_MAP_NAME, + bgp_static->rmap.name); + bgp_static->rmap.name = + XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); + bgp_static->rmap.map = route_map_lookup_by_name(rmap); + } else { + if (bgp_static->rmap.name) + XFREE(MTYPE_ROUTE_MAP_NAME, + bgp_static->rmap.name); + bgp_static->rmap.name = NULL; + bgp_static->rmap.map = NULL; + bgp_static->valid = 0; + } + bgp_unlock_node(rn); + } else { + /* New configuration. */ + bgp_static = bgp_static_new(); + bgp_static->backdoor = backdoor; + bgp_static->valid = 0; + bgp_static->igpmetric = 0; + bgp_static->igpnexthop.s_addr = 0; + bgp_static->label_index = label_index; + + if (rmap) { + if (bgp_static->rmap.name) + XFREE(MTYPE_ROUTE_MAP_NAME, + bgp_static->rmap.name); + bgp_static->rmap.name = + XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); + bgp_static->rmap.map = route_map_lookup_by_name(rmap); + } + rn->info = bgp_static; + } - bgp_static->valid = 1; - if (need_update) - bgp_static_withdraw (bgp, &p, afi, safi); + bgp_static->valid = 1; + if (need_update) + bgp_static_withdraw(bgp, &p, afi, safi); - if (! bgp_static->backdoor) - bgp_static_update (bgp, &p, bgp_static, afi, safi); + if (!bgp_static->backdoor) + bgp_static_update(bgp, &p, bgp_static, afi, safi); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Configure static BGP network. */ -static int -bgp_static_unset (struct vty *vty, const char *ip_str, - afi_t afi, safi_t safi) -{ - VTY_DECLVAR_CONTEXT(bgp, bgp); - int ret; - struct prefix p; - struct bgp_static *bgp_static; - struct bgp_node *rn; - - /* Convert IP prefix string to struct prefix. */ - ret = str2prefix (ip_str, &p); - if (! ret) - { - vty_out (vty, "%% Malformed prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6)) - { - vty_out (vty,"%% Malformed prefix (link-local address)\n"); - return CMD_WARNING_CONFIG_FAILED; - } +static int bgp_static_unset(struct vty *vty, const char *ip_str, afi_t afi, + safi_t safi) +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + int ret; + struct prefix p; + struct bgp_static *bgp_static; + struct bgp_node *rn; + + /* Convert IP prefix string to struct prefix. */ + ret = str2prefix(ip_str, &p); + if (!ret) { + vty_out(vty, "%% Malformed prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) { + vty_out(vty, "%% Malformed prefix (link-local address)\n"); + return CMD_WARNING_CONFIG_FAILED; + } - apply_mask (&p); + apply_mask(&p); - rn = bgp_node_lookup (bgp->route[afi][safi], &p); - if (! rn) - { - vty_out (vty,"%% Can't find specified static route configuration.\n"); - return CMD_WARNING_CONFIG_FAILED; - } + rn = bgp_node_lookup(bgp->route[afi][safi], &p); + if (!rn) { + vty_out(vty, + "%% Can't find specified static route configuration.\n"); + return CMD_WARNING_CONFIG_FAILED; + } - bgp_static = rn->info; - - /* Update BGP RIB. */ - if (! bgp_static->backdoor) - bgp_static_withdraw (bgp, &p, afi, safi); - - /* Clear configuration. */ - bgp_static_free (bgp_static); - rn->info = NULL; - bgp_unlock_node (rn); - bgp_unlock_node (rn); - - return CMD_SUCCESS; -} - -void -bgp_static_add (struct bgp *bgp) -{ - afi_t afi; - safi_t safi; - struct bgp_node *rn; - struct bgp_node *rm; - struct bgp_table *table; - struct bgp_static *bgp_static; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn)) - if (rn->info != NULL) - { - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN)) - { - table = rn->info; - - for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm)) - { - bgp_static = rm->info; - bgp_static_update_safi (bgp, &rm->p, bgp_static, afi, safi); - } - } - else - { - bgp_static_update (bgp, &rn->p, rn->info, afi, safi); - } - } + bgp_static = rn->info; + + /* Update BGP RIB. */ + if (!bgp_static->backdoor) + bgp_static_withdraw(bgp, &p, afi, safi); + + /* Clear configuration. */ + bgp_static_free(bgp_static); + rn->info = NULL; + bgp_unlock_node(rn); + bgp_unlock_node(rn); + + return CMD_SUCCESS; +} + +void bgp_static_add(struct bgp *bgp) +{ + afi_t afi; + safi_t safi; + struct bgp_node *rn; + struct bgp_node *rm; + struct bgp_table *table; + struct bgp_static *bgp_static; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + for (rn = bgp_table_top(bgp->route[afi][safi]); rn; + rn = bgp_route_next(rn)) + if (rn->info != NULL) { + if ((safi == SAFI_MPLS_VPN) + || (safi == SAFI_ENCAP) + || (safi == SAFI_EVPN)) { + table = rn->info; + + for (rm = bgp_table_top(table); + rm; + rm = bgp_route_next(rm)) { + bgp_static = rm->info; + bgp_static_update_safi( + bgp, &rm->p, + bgp_static, afi, + safi); + } + } else { + bgp_static_update(bgp, &rn->p, + rn->info, afi, + safi); + } + } } /* Called from bgp_delete(). Delete all static routes from the BGP instance. */ -void -bgp_static_delete (struct bgp *bgp) -{ - afi_t afi; - safi_t safi; - struct bgp_node *rn; - struct bgp_node *rm; - struct bgp_table *table; - struct bgp_static *bgp_static; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn)) - if (rn->info != NULL) - { - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN)) - { - table = rn->info; - - for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm)) - { - bgp_static = rm->info; - bgp_static_withdraw_safi (bgp, &rm->p, - AFI_IP, safi, - (struct prefix_rd *)&rn->p); - bgp_static_free (bgp_static); - rn->info = NULL; - bgp_unlock_node (rn); - } - } - else - { - bgp_static = rn->info; - bgp_static_withdraw (bgp, &rn->p, afi, safi); - bgp_static_free (bgp_static); - rn->info = NULL; - bgp_unlock_node (rn); - } - } -} - -void -bgp_static_redo_import_check (struct bgp *bgp) -{ - afi_t afi; - safi_t safi; - struct bgp_node *rn; - struct bgp_node *rm; - struct bgp_table *table; - struct bgp_static *bgp_static; - - /* Use this flag to force reprocessing of the route */ - bgp_flag_set(bgp, BGP_FLAG_FORCE_STATIC_PROCESS); - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn)) - if (rn->info != NULL) - { - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN)) - { - table = rn->info; - - for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm)) - { - bgp_static = rm->info; - bgp_static_update_safi (bgp, &rm->p, bgp_static, afi, safi); - } - } - else - { - bgp_static = rn->info; - bgp_static_update (bgp, &rn->p, bgp_static, afi, safi); - } - } - bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS); -} - -static void -bgp_purge_af_static_redist_routes (struct bgp *bgp, afi_t afi, safi_t safi) -{ - struct bgp_table *table; - struct bgp_node *rn; - struct bgp_info *ri; - - table = bgp->rib[afi][safi]; - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - { - for (ri = rn->info; ri; ri = ri->next) - { - if (ri->peer == bgp->peer_self && - ((ri->type == ZEBRA_ROUTE_BGP && - ri->sub_type == BGP_ROUTE_STATIC) || - (ri->type != ZEBRA_ROUTE_BGP && - ri->sub_type == BGP_ROUTE_REDISTRIBUTE))) - { - bgp_aggregate_decrement (bgp, &rn->p, ri, afi, safi); - bgp_unlink_nexthop(ri); - bgp_info_delete (rn, ri); - bgp_process (bgp, rn, afi, safi); - } - } - } +void bgp_static_delete(struct bgp *bgp) +{ + afi_t afi; + safi_t safi; + struct bgp_node *rn; + struct bgp_node *rm; + struct bgp_table *table; + struct bgp_static *bgp_static; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + for (rn = bgp_table_top(bgp->route[afi][safi]); rn; + rn = bgp_route_next(rn)) + if (rn->info != NULL) { + if ((safi == SAFI_MPLS_VPN) + || (safi == SAFI_ENCAP) + || (safi == SAFI_EVPN)) { + table = rn->info; + + for (rm = bgp_table_top(table); + rm; + rm = bgp_route_next(rm)) { + bgp_static = rm->info; + bgp_static_withdraw_safi( + bgp, &rm->p, + AFI_IP, safi, + (struct + prefix_rd *)&rn + ->p); + bgp_static_free( + bgp_static); + rn->info = NULL; + bgp_unlock_node(rn); + } + } else { + bgp_static = rn->info; + bgp_static_withdraw(bgp, &rn->p, + afi, safi); + bgp_static_free(bgp_static); + rn->info = NULL; + bgp_unlock_node(rn); + } + } +} + +void bgp_static_redo_import_check(struct bgp *bgp) +{ + afi_t afi; + safi_t safi; + struct bgp_node *rn; + struct bgp_node *rm; + struct bgp_table *table; + struct bgp_static *bgp_static; + + /* Use this flag to force reprocessing of the route */ + bgp_flag_set(bgp, BGP_FLAG_FORCE_STATIC_PROCESS); + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + for (rn = bgp_table_top(bgp->route[afi][safi]); rn; + rn = bgp_route_next(rn)) + if (rn->info != NULL) { + if ((safi == SAFI_MPLS_VPN) + || (safi == SAFI_ENCAP) + || (safi == SAFI_EVPN)) { + table = rn->info; + + for (rm = bgp_table_top(table); + rm; + rm = bgp_route_next(rm)) { + bgp_static = rm->info; + bgp_static_update_safi( + bgp, &rm->p, + bgp_static, afi, + safi); + } + } else { + bgp_static = rn->info; + bgp_static_update(bgp, &rn->p, + bgp_static, + afi, safi); + } + } + bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS); +} + +static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi, + safi_t safi) +{ + struct bgp_table *table; + struct bgp_node *rn; + struct bgp_info *ri; + + table = bgp->rib[afi][safi]; + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { + for (ri = rn->info; ri; ri = ri->next) { + if (ri->peer == bgp->peer_self + && ((ri->type == ZEBRA_ROUTE_BGP + && ri->sub_type == BGP_ROUTE_STATIC) + || (ri->type != ZEBRA_ROUTE_BGP + && ri->sub_type + == BGP_ROUTE_REDISTRIBUTE))) { + bgp_aggregate_decrement(bgp, &rn->p, ri, afi, + safi); + bgp_unlink_nexthop(ri); + bgp_info_delete(rn, ri); + bgp_process(bgp, rn, afi, safi); + } + } + } } /* * Purge all networks and redistributed routes from routing table. * Invoked upon the instance going down. */ -void -bgp_purge_static_redist_routes (struct bgp *bgp) +void bgp_purge_static_redist_routes(struct bgp *bgp) { - afi_t afi; - safi_t safi; + afi_t afi; + safi_t safi; - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - bgp_purge_af_static_redist_routes (bgp, afi, safi); + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + bgp_purge_af_static_redist_routes(bgp, afi, safi); } /* @@ -4697,271 +4663,251 @@ bgp_purge_static_redist_routes (struct bgp *bgp) * Currently this is used to set static routes for VPN and ENCAP. * I think it can probably be factored with bgp_static_set. */ -int -bgp_static_set_safi (afi_t afi, safi_t safi, struct vty *vty, const char *ip_str, - const char *rd_str, const char *label_str, - const char *rmap_str, int evpn_type, const char *esi, const char *gwip, - const char *ethtag, const char *routermac) -{ - VTY_DECLVAR_CONTEXT(bgp, bgp); - int ret; - struct prefix p; - struct prefix_rd prd; - struct bgp_node *prn; - struct bgp_node *rn; - struct bgp_table *table; - struct bgp_static *bgp_static; - mpls_label_t label = MPLS_INVALID_LABEL; - struct prefix gw_ip; - - /* validate ip prefix */ - ret = str2prefix (ip_str, &p); - if (! ret) - { - vty_out (vty, "%% Malformed prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - apply_mask (&p); - if ( (afi == AFI_L2VPN) && - (bgp_build_evpn_prefix ( evpn_type, ethtag!=NULL?atol(ethtag):0, &p))) - { - vty_out (vty, "%% L2VPN prefix could not be forged\n"); - return CMD_WARNING_CONFIG_FAILED; - } +int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty, + const char *ip_str, const char *rd_str, + const char *label_str, const char *rmap_str, + int evpn_type, const char *esi, const char *gwip, + const char *ethtag, const char *routermac) +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + int ret; + struct prefix p; + struct prefix_rd prd; + struct bgp_node *prn; + struct bgp_node *rn; + struct bgp_table *table; + struct bgp_static *bgp_static; + mpls_label_t label = MPLS_INVALID_LABEL; + struct prefix gw_ip; + + /* validate ip prefix */ + ret = str2prefix(ip_str, &p); + if (!ret) { + vty_out(vty, "%% Malformed prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + apply_mask(&p); + if ((afi == AFI_L2VPN) + && (bgp_build_evpn_prefix(evpn_type, + ethtag != NULL ? atol(ethtag) : 0, &p))) { + vty_out(vty, "%% L2VPN prefix could not be forged\n"); + return CMD_WARNING_CONFIG_FAILED; + } - ret = str2prefix_rd (rd_str, &prd); - if (! ret) - { - vty_out (vty, "%% Malformed rd\n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = str2prefix_rd(rd_str, &prd); + if (!ret) { + vty_out(vty, "%% Malformed rd\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (label_str) - { - unsigned long label_val; - label_val = strtoul(label_str, NULL, 10); - encode_label (label_val, &label); - } + if (label_str) { + unsigned long label_val; + label_val = strtoul(label_str, NULL, 10); + encode_label(label_val, &label); + } - if (safi == SAFI_EVPN) - { - if( esi && str2esi (esi, NULL) == 0) - { - vty_out (vty, "%% Malformed ESI\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if( routermac && prefix_str2mac (routermac, NULL) == 0) - { - vty_out (vty, "%% Malformed Router MAC\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (gwip) - { - memset (&gw_ip, 0, sizeof (struct prefix)); - ret = str2prefix (gwip, &gw_ip); - if (! ret) - { - vty_out (vty, "%% Malformed GatewayIp\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if((gw_ip.family == AF_INET && - IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn *)&p)) || - (gw_ip.family == AF_INET6 && - IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)&p))) - { - vty_out (vty, "%% GatewayIp family differs with IP prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - } - prn = bgp_node_get (bgp->route[afi][safi], - (struct prefix *)&prd); - if (prn->info == NULL) - prn->info = bgp_table_init (afi, safi); - else - bgp_unlock_node (prn); - table = prn->info; + if (safi == SAFI_EVPN) { + if (esi && str2esi(esi, NULL) == 0) { + vty_out(vty, "%% Malformed ESI\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (routermac && prefix_str2mac(routermac, NULL) == 0) { + vty_out(vty, "%% Malformed Router MAC\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (gwip) { + memset(&gw_ip, 0, sizeof(struct prefix)); + ret = str2prefix(gwip, &gw_ip); + if (!ret) { + vty_out(vty, "%% Malformed GatewayIp\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if ((gw_ip.family == AF_INET + && IS_EVPN_PREFIX_IPADDR_V6( + (struct prefix_evpn *)&p)) + || (gw_ip.family == AF_INET6 + && IS_EVPN_PREFIX_IPADDR_V4( + (struct prefix_evpn *)&p))) { + vty_out(vty, + "%% GatewayIp family differs with IP prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + } + prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd); + if (prn->info == NULL) + prn->info = bgp_table_init(afi, safi); + else + bgp_unlock_node(prn); + table = prn->info; + + rn = bgp_node_get(table, &p); + + if (rn->info) { + vty_out(vty, "%% Same network configuration exists\n"); + bgp_unlock_node(rn); + } else { + /* New configuration. */ + bgp_static = bgp_static_new(); + bgp_static->backdoor = 0; + bgp_static->valid = 0; + bgp_static->igpmetric = 0; + bgp_static->igpnexthop.s_addr = 0; + bgp_static->label = label; + bgp_static->prd = prd; + + if (rmap_str) { + if (bgp_static->rmap.name) + XFREE(MTYPE_ROUTE_MAP_NAME, + bgp_static->rmap.name); + bgp_static->rmap.name = + XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str); + bgp_static->rmap.map = + route_map_lookup_by_name(rmap_str); + } - rn = bgp_node_get (table, &p); + if (safi == SAFI_EVPN) { + if (esi) { + bgp_static->eth_s_id = + XCALLOC(MTYPE_ATTR, + sizeof(struct eth_segment_id)); + str2esi(esi, bgp_static->eth_s_id); + } + if (routermac) { + bgp_static->router_mac = + XCALLOC(MTYPE_ATTR, ETHER_ADDR_LEN + 1); + prefix_str2mac(routermac, + bgp_static->router_mac); + } + if (gwip) + prefix_copy(&bgp_static->gatewayIp, &gw_ip); + } + rn->info = bgp_static; - if (rn->info) - { - vty_out (vty, "%% Same network configuration exists\n"); - bgp_unlock_node (rn); - } - else - { - /* New configuration. */ - bgp_static = bgp_static_new (); - bgp_static->backdoor = 0; - bgp_static->valid = 0; - bgp_static->igpmetric = 0; - bgp_static->igpnexthop.s_addr = 0; - bgp_static->label = label; - bgp_static->prd = prd; - - if (rmap_str) - { - if (bgp_static->rmap.name) - XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name); - bgp_static->rmap.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str); - bgp_static->rmap.map = route_map_lookup_by_name (rmap_str); - } - - if (safi == SAFI_EVPN) - { - if(esi) - { - bgp_static->eth_s_id = XCALLOC (MTYPE_ATTR, sizeof(struct eth_segment_id)); - str2esi (esi, bgp_static->eth_s_id); - } - if( routermac) - { - bgp_static->router_mac = XCALLOC (MTYPE_ATTR, ETHER_ADDR_LEN+1); - prefix_str2mac (routermac, bgp_static->router_mac); - } - if (gwip) - prefix_copy (&bgp_static->gatewayIp, &gw_ip); - } - rn->info = bgp_static; - - bgp_static->valid = 1; - bgp_static_update_safi (bgp, &p, bgp_static, afi, safi); - } + bgp_static->valid = 1; + bgp_static_update_safi(bgp, &p, bgp_static, afi, safi); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Configure static BGP network. */ -int -bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty, const char *ip_str, - const char *rd_str, const char *label_str, - int evpn_type, const char *esi, const char *gwip, const char *ethtag) -{ - VTY_DECLVAR_CONTEXT(bgp, bgp); - int ret; - struct prefix p; - struct prefix_rd prd; - struct bgp_node *prn; - struct bgp_node *rn; - struct bgp_table *table; - struct bgp_static *bgp_static; - mpls_label_t label = MPLS_INVALID_LABEL; - - /* Convert IP prefix string to struct prefix. */ - ret = str2prefix (ip_str, &p); - if (! ret) - { - vty_out (vty, "%% Malformed prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - apply_mask (&p); - if ( (afi == AFI_L2VPN) && - (bgp_build_evpn_prefix ( evpn_type, ethtag!=NULL?atol(ethtag):0, &p))) - { - vty_out (vty, "%% L2VPN prefix could not be forged\n"); - return CMD_WARNING_CONFIG_FAILED; - } - ret = str2prefix_rd (rd_str, &prd); - if (! ret) - { - vty_out (vty, "%% Malformed rd\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (label_str) - { - unsigned long label_val; - label_val = strtoul(label_str, NULL, 10); - encode_label (label_val, &label); - } - - prn = bgp_node_get (bgp->route[afi][safi], - (struct prefix *)&prd); - if (prn->info == NULL) - prn->info = bgp_table_init (afi, safi); - else - bgp_unlock_node (prn); - table = prn->info; - - rn = bgp_node_lookup (table, &p); +int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty, + const char *ip_str, const char *rd_str, + const char *label_str, int evpn_type, const char *esi, + const char *gwip, const char *ethtag) +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + int ret; + struct prefix p; + struct prefix_rd prd; + struct bgp_node *prn; + struct bgp_node *rn; + struct bgp_table *table; + struct bgp_static *bgp_static; + mpls_label_t label = MPLS_INVALID_LABEL; + + /* Convert IP prefix string to struct prefix. */ + ret = str2prefix(ip_str, &p); + if (!ret) { + vty_out(vty, "%% Malformed prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + apply_mask(&p); + if ((afi == AFI_L2VPN) + && (bgp_build_evpn_prefix(evpn_type, + ethtag != NULL ? atol(ethtag) : 0, &p))) { + vty_out(vty, "%% L2VPN prefix could not be forged\n"); + return CMD_WARNING_CONFIG_FAILED; + } + ret = str2prefix_rd(rd_str, &prd); + if (!ret) { + vty_out(vty, "%% Malformed rd\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (rn) - { - bgp_static_withdraw_safi (bgp, &p, afi, safi, &prd); + if (label_str) { + unsigned long label_val; + label_val = strtoul(label_str, NULL, 10); + encode_label(label_val, &label); + } - bgp_static = rn->info; - bgp_static_free (bgp_static); - rn->info = NULL; - bgp_unlock_node (rn); - bgp_unlock_node (rn); - } - else - vty_out (vty, "%% Can't find the route\n"); + prn = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd); + if (prn->info == NULL) + prn->info = bgp_table_init(afi, safi); + else + bgp_unlock_node(prn); + table = prn->info; - return CMD_SUCCESS; -} + rn = bgp_node_lookup(table, &p); -static int -bgp_table_map_set (struct vty *vty, afi_t afi, safi_t safi, - const char *rmap_name) -{ - VTY_DECLVAR_CONTEXT(bgp, bgp); - struct bgp_rmap *rmap; + if (rn) { + bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd); - rmap = &bgp->table_map[afi][safi]; - if (rmap_name) - { - if (rmap->name) - XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name); - rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name); - rmap->map = route_map_lookup_by_name (rmap_name); - } - else - { - if (rmap->name) - XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name); - rmap->name = NULL; - rmap->map = NULL; - } + bgp_static = rn->info; + bgp_static_free(bgp_static); + rn->info = NULL; + bgp_unlock_node(rn); + bgp_unlock_node(rn); + } else + vty_out(vty, "%% Can't find the route\n"); + + return CMD_SUCCESS; +} + +static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi, + const char *rmap_name) +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + struct bgp_rmap *rmap; + + rmap = &bgp->table_map[afi][safi]; + if (rmap_name) { + if (rmap->name) + XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name); + rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name); + rmap->map = route_map_lookup_by_name(rmap_name); + } else { + if (rmap->name) + XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name); + rmap->name = NULL; + rmap->map = NULL; + } - if (bgp_fibupd_safi(safi)) - bgp_zebra_announce_table(bgp, afi, safi); + if (bgp_fibupd_safi(safi)) + bgp_zebra_announce_table(bgp, afi, safi); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -bgp_table_map_unset (struct vty *vty, afi_t afi, safi_t safi, - const char *rmap_name) +static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi, + const char *rmap_name) { - VTY_DECLVAR_CONTEXT(bgp, bgp); - struct bgp_rmap *rmap; + VTY_DECLVAR_CONTEXT(bgp, bgp); + struct bgp_rmap *rmap; - rmap = &bgp->table_map[afi][safi]; - if (rmap->name) - XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name); - rmap->name = NULL; - rmap->map = NULL; + rmap = &bgp->table_map[afi][safi]; + if (rmap->name) + XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name); + rmap->name = NULL; + rmap->map = NULL; - if (bgp_fibupd_safi(safi)) - bgp_zebra_announce_table(bgp, afi, safi); + if (bgp_fibupd_safi(safi)) + bgp_zebra_announce_table(bgp, afi, safi); - return CMD_SUCCESS; + return CMD_SUCCESS; } -int -bgp_config_write_table_map (struct vty *vty, struct bgp *bgp, afi_t afi, - safi_t safi, int *write) +int bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi, int *write) { - if (bgp->table_map[afi][safi].name) - { - bgp_config_write_family_header (vty, afi, safi, write); - vty_out (vty, " table-map %s\n", - bgp->table_map[afi][safi].name); - } + if (bgp->table_map[afi][safi].name) { + bgp_config_write_family_header(vty, afi, safi, write); + vty_out(vty, " table-map %s\n", + bgp->table_map[afi][safi].name); + } - return 0; + return 0; } DEFUN (bgp_table_map, @@ -4970,9 +4916,9 @@ DEFUN (bgp_table_map, "BGP table to RIB route download filter\n" "Name of the route map\n") { - int idx_word = 1; - return bgp_table_map_set (vty, - bgp_node_afi (vty), bgp_node_safi (vty), argv[idx_word]->arg); + int idx_word = 1; + return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty), + argv[idx_word]->arg); } DEFUN (no_bgp_table_map, no_bgp_table_map_cmd, @@ -4981,9 +4927,9 @@ DEFUN (no_bgp_table_map, "BGP table to RIB route download filter\n" "Name of the route map\n") { - int idx_word = 2; - return bgp_table_map_unset (vty, - bgp_node_afi (vty), bgp_node_safi (vty), argv[idx_word]->arg); + int idx_word = 2; + return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty), + argv[idx_word]->arg); } DEFUN (bgp_network, @@ -4992,10 +4938,10 @@ DEFUN (bgp_network, "Specify a network to announce via BGP\n" "IPv4 prefix\n") { - int idx_ipv4_prefixlen = 1; - return bgp_static_set (vty, argv[idx_ipv4_prefixlen]->arg, - AFI_IP, bgp_node_safi (vty), NULL, 0, - BGP_INVALID_LABEL_INDEX); + int idx_ipv4_prefixlen = 1; + return bgp_static_set(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP, + bgp_node_safi(vty), NULL, 0, + BGP_INVALID_LABEL_INDEX); } DEFUN (bgp_network_route_map, @@ -5006,11 +4952,11 @@ DEFUN (bgp_network_route_map, "Route-map to modify the attributes\n" "Name of the route map\n") { - int idx_ipv4_prefixlen = 1; - int idx_word = 3; - return bgp_static_set (vty, argv[idx_ipv4_prefixlen]->arg, - AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0, - BGP_INVALID_LABEL_INDEX); + int idx_ipv4_prefixlen = 1; + int idx_word = 3; + return bgp_static_set(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP, + bgp_node_safi(vty), argv[idx_word]->arg, 0, + BGP_INVALID_LABEL_INDEX); } DEFUN (bgp_network_backdoor, @@ -5020,9 +4966,9 @@ DEFUN (bgp_network_backdoor, "IPv4 prefix\n" "Specify a BGP backdoor route\n") { - int idx_ipv4_prefixlen = 1; - return bgp_static_set (vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP, SAFI_UNICAST, - NULL, 1, BGP_INVALID_LABEL_INDEX); + int idx_ipv4_prefixlen = 1; + return bgp_static_set(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP, + SAFI_UNICAST, NULL, 1, BGP_INVALID_LABEL_INDEX); } DEFUN (bgp_network_mask, @@ -5033,20 +4979,20 @@ DEFUN (bgp_network_mask, "Network mask\n" "Network mask\n") { - int idx_ipv4 = 1; - int idx_ipv4_2 = 3; - int ret; - char prefix_str[BUFSIZ]; - - ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, prefix_str); - if (! ret) - { - vty_out (vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } + int idx_ipv4 = 1; + int idx_ipv4_2 = 3; + int ret; + char prefix_str[BUFSIZ]; + + ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, + prefix_str); + if (!ret) { + vty_out(vty, "%% Inconsistent address and mask\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return bgp_static_set (vty, prefix_str, - AFI_IP, bgp_node_safi (vty), NULL, 0, BGP_INVALID_LABEL_INDEX); + return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), NULL, + 0, BGP_INVALID_LABEL_INDEX); } DEFUN (bgp_network_mask_route_map, @@ -5059,21 +5005,21 @@ DEFUN (bgp_network_mask_route_map, "Route-map to modify the attributes\n" "Name of the route map\n") { - int idx_ipv4 = 1; - int idx_ipv4_2 = 3; - int idx_word = 5; - int ret; - char prefix_str[BUFSIZ]; - - ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, prefix_str); - if (! ret) - { - vty_out (vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } + int idx_ipv4 = 1; + int idx_ipv4_2 = 3; + int idx_word = 5; + int ret; + char prefix_str[BUFSIZ]; + + ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, + prefix_str); + if (!ret) { + vty_out(vty, "%% Inconsistent address and mask\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return bgp_static_set (vty, prefix_str, - AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0, BGP_INVALID_LABEL_INDEX); + return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), + argv[idx_word]->arg, 0, BGP_INVALID_LABEL_INDEX); } DEFUN (bgp_network_mask_backdoor, @@ -5085,21 +5031,20 @@ DEFUN (bgp_network_mask_backdoor, "Network mask\n" "Specify a BGP backdoor route\n") { - int idx_ipv4 = 1; - int idx_ipv4_2 = 3; - int ret; - char prefix_str[BUFSIZ]; - - ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, prefix_str); - if (! ret) - { - vty_out (vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } + int idx_ipv4 = 1; + int idx_ipv4_2 = 3; + int ret; + char prefix_str[BUFSIZ]; + + ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, + prefix_str); + if (!ret) { + vty_out(vty, "%% Inconsistent address and mask\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return bgp_static_set (vty, prefix_str, AFI_IP, SAFI_UNICAST, - NULL, 1, - BGP_INVALID_LABEL_INDEX); + return bgp_static_set(vty, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 1, + BGP_INVALID_LABEL_INDEX); } DEFUN (bgp_network_mask_natural, @@ -5108,20 +5053,18 @@ DEFUN (bgp_network_mask_natural, "Specify a network to announce via BGP\n" "Network number\n") { - int idx_ipv4 = 1; - int ret; - char prefix_str[BUFSIZ]; + int idx_ipv4 = 1; + int ret; + char prefix_str[BUFSIZ]; - ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, NULL, prefix_str); - if (! ret) - { - vty_out (vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str); + if (!ret) { + vty_out(vty, "%% Inconsistent address and mask\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return bgp_static_set (vty, prefix_str, - AFI_IP, bgp_node_safi (vty), NULL, 0, - BGP_INVALID_LABEL_INDEX); + return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), NULL, + 0, BGP_INVALID_LABEL_INDEX); } DEFUN (bgp_network_mask_natural_route_map, @@ -5132,21 +5075,19 @@ DEFUN (bgp_network_mask_natural_route_map, "Route-map to modify the attributes\n" "Name of the route map\n") { - int idx_ipv4 = 1; - int idx_word = 3; - int ret; - char prefix_str[BUFSIZ]; + int idx_ipv4 = 1; + int idx_word = 3; + int ret; + char prefix_str[BUFSIZ]; - ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, NULL, prefix_str); - if (! ret) - { - vty_out (vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str); + if (!ret) { + vty_out(vty, "%% Inconsistent address and mask\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return bgp_static_set (vty, prefix_str, - AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0, - BGP_INVALID_LABEL_INDEX); + return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), + argv[idx_word]->arg, 0, BGP_INVALID_LABEL_INDEX); } DEFUN (bgp_network_mask_natural_backdoor, @@ -5156,19 +5097,18 @@ DEFUN (bgp_network_mask_natural_backdoor, "Network number\n" "Specify a BGP backdoor route\n") { - int idx_ipv4 = 1; - int ret; - char prefix_str[BUFSIZ]; + int idx_ipv4 = 1; + int ret; + char prefix_str[BUFSIZ]; - ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, NULL, prefix_str); - if (! ret) - { - vty_out (vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str); + if (!ret) { + vty_out(vty, "%% Inconsistent address and mask\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return bgp_static_set (vty, prefix_str, AFI_IP, SAFI_UNICAST, - NULL, 1, BGP_INVALID_LABEL_INDEX); + return bgp_static_set(vty, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 1, + BGP_INVALID_LABEL_INDEX); } DEFUN (bgp_network_label_index, @@ -5179,11 +5119,11 @@ DEFUN (bgp_network_label_index, "Label index to associate with the prefix\n" "Label index value\n") { - u_int32_t label_index; + u_int32_t label_index; - label_index = strtoul(argv[3]->arg, NULL, 10); - return bgp_static_set (vty, argv[1]->arg, - AFI_IP, bgp_node_safi (vty), NULL, 0, label_index); + label_index = strtoul(argv[3]->arg, NULL, 10); + return bgp_static_set(vty, argv[1]->arg, AFI_IP, bgp_node_safi(vty), + NULL, 0, label_index); } DEFUN (bgp_network_label_index_route_map, @@ -5196,11 +5136,11 @@ DEFUN (bgp_network_label_index_route_map, "Route-map to modify the attributes\n" "Name of the route map\n") { - u_int32_t label_index; + u_int32_t label_index; - label_index = strtoul(argv[3]->arg, NULL, 10); - return bgp_static_set (vty, argv[1]->arg, - AFI_IP, bgp_node_safi (vty), argv[5]->arg, 0, label_index); + label_index = strtoul(argv[3]->arg, NULL, 10); + return bgp_static_set(vty, argv[1]->arg, AFI_IP, bgp_node_safi(vty), + argv[5]->arg, 0, label_index); } DEFUN (no_bgp_network, @@ -5213,9 +5153,9 @@ DEFUN (no_bgp_network, "Route-map to modify the attributes\n" "Name of the route map\n") { - int idx_ipv4_prefixlen = 2; - return bgp_static_unset (vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP, - bgp_node_safi (vty)); + int idx_ipv4_prefixlen = 2; + return bgp_static_unset(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP, + bgp_node_safi(vty)); } DEFUN (no_bgp_network_mask, @@ -5230,20 +5170,19 @@ DEFUN (no_bgp_network_mask, "Route-map to modify the attributes\n" "Name of the route map\n") { - int idx_ipv4 = 2; - int idx_ipv4_2 = 4; - int ret; - char prefix_str[BUFSIZ]; + int idx_ipv4 = 2; + int idx_ipv4_2 = 4; + int ret; + char prefix_str[BUFSIZ]; - ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, prefix_str); - if (! ret) - { - vty_out (vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, + prefix_str); + if (!ret) { + vty_out(vty, "%% Inconsistent address and mask\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return bgp_static_unset (vty, prefix_str, AFI_IP, - bgp_node_safi (vty)); + return bgp_static_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty)); } DEFUN (no_bgp_network_mask_natural, @@ -5256,40 +5195,34 @@ DEFUN (no_bgp_network_mask_natural, "Route-map to modify the attributes\n" "Name of the route map\n") { - int idx_ipv4 = 2; - int ret; - char prefix_str[BUFSIZ]; + int idx_ipv4 = 2; + int ret; + char prefix_str[BUFSIZ]; - ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, NULL, prefix_str); - if (! ret) - { - vty_out (vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str); + if (!ret) { + vty_out(vty, "%% Inconsistent address and mask\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return bgp_static_unset (vty, prefix_str, AFI_IP, - bgp_node_safi (vty)); + return bgp_static_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty)); } -ALIAS (no_bgp_network, - no_bgp_network_label_index_cmd, - "no network A.B.C.D/M label-index (0-1048560)", - NO_STR - "Specify a network to announce via BGP\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Label index to associate with the prefix\n" - "Label index value\n") +ALIAS(no_bgp_network, no_bgp_network_label_index_cmd, + "no network A.B.C.D/M label-index (0-1048560)", NO_STR + "Specify a network to announce via BGP\n" + "IP prefix /, e.g., 35.0.0.0/8\n" + "Label index to associate with the prefix\n" + "Label index value\n") -ALIAS (no_bgp_network, - no_bgp_network_label_index_route_map_cmd, - "no network A.B.C.D/M label-index (0-1048560) route-map WORD", - NO_STR - "Specify a network to announce via BGP\n" - "IP prefix\n" - "Label index to associate with the prefix\n" - "Label index value\n" - "Route-map to modify the attributes\n" - "Name of the route map\n") +ALIAS(no_bgp_network, no_bgp_network_label_index_route_map_cmd, + "no network A.B.C.D/M label-index (0-1048560) route-map WORD", NO_STR + "Specify a network to announce via BGP\n" + "IP prefix\n" + "Label index to associate with the prefix\n" + "Label index value\n" + "Route-map to modify the attributes\n" + "Name of the route map\n") DEFUN (ipv6_bgp_network, ipv6_bgp_network_cmd, @@ -5297,10 +5230,10 @@ DEFUN (ipv6_bgp_network, "Specify a network to announce via BGP\n" "IPv6 prefix\n") { - int idx_ipv6_prefixlen = 1; - return bgp_static_set (vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, bgp_node_safi(vty), - NULL, 0, - BGP_INVALID_LABEL_INDEX); + int idx_ipv6_prefixlen = 1; + return bgp_static_set(vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, + bgp_node_safi(vty), NULL, 0, + BGP_INVALID_LABEL_INDEX); } DEFUN (ipv6_bgp_network_route_map, @@ -5311,11 +5244,11 @@ DEFUN (ipv6_bgp_network_route_map, "Route-map to modify the attributes\n" "Name of the route map\n") { - int idx_ipv6_prefixlen = 1; - int idx_word = 3; - return bgp_static_set (vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, - bgp_node_safi (vty), argv[idx_word]->arg, 0, - BGP_INVALID_LABEL_INDEX); + int idx_ipv6_prefixlen = 1; + int idx_word = 3; + return bgp_static_set(vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, + bgp_node_safi(vty), argv[idx_word]->arg, 0, + BGP_INVALID_LABEL_INDEX); } DEFUN (ipv6_bgp_network_label_index, @@ -5326,11 +5259,11 @@ DEFUN (ipv6_bgp_network_label_index, "Label index to associate with the prefix\n" "Label index value\n") { - u_int32_t label_index; + u_int32_t label_index; - label_index = strtoul(argv[3]->arg, NULL, 10); - return bgp_static_set (vty, argv[1]->arg, - AFI_IP6, bgp_node_safi (vty), NULL, 0, label_index); + label_index = strtoul(argv[3]->arg, NULL, 10); + return bgp_static_set(vty, argv[1]->arg, AFI_IP6, bgp_node_safi(vty), + NULL, 0, label_index); } DEFUN (ipv6_bgp_network_label_index_route_map, @@ -5343,11 +5276,11 @@ DEFUN (ipv6_bgp_network_label_index_route_map, "Route-map to modify the attributes\n" "Name of the route map\n") { - u_int32_t label_index; + u_int32_t label_index; - label_index = strtoul(argv[3]->arg, NULL, 10); - return bgp_static_set (vty, argv[1]->arg, - AFI_IP6, bgp_node_safi (vty), argv[5]->arg, 0, label_index); + label_index = strtoul(argv[3]->arg, NULL, 10); + return bgp_static_set(vty, argv[1]->arg, AFI_IP6, bgp_node_safi(vty), + argv[5]->arg, 0, label_index); } DEFUN (no_ipv6_bgp_network, @@ -5359,29 +5292,26 @@ DEFUN (no_ipv6_bgp_network, "Route-map to modify the attributes\n" "Name of the route map\n") { - int idx_ipv6_prefixlen = 2; - return bgp_static_unset (vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, bgp_node_safi(vty)); + int idx_ipv6_prefixlen = 2; + return bgp_static_unset(vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, + bgp_node_safi(vty)); } -ALIAS (no_ipv6_bgp_network, - no_ipv6_bgp_network_label_index_cmd, - "no network X:X::X:X/M label-index (0-1048560)", - NO_STR - "Specify a network to announce via BGP\n" - "IPv6 prefix /\n" - "Label index to associate with the prefix\n" - "Label index value\n") +ALIAS(no_ipv6_bgp_network, no_ipv6_bgp_network_label_index_cmd, + "no network X:X::X:X/M label-index (0-1048560)", NO_STR + "Specify a network to announce via BGP\n" + "IPv6 prefix /\n" + "Label index to associate with the prefix\n" + "Label index value\n") -ALIAS (no_ipv6_bgp_network, - no_ipv6_bgp_network_label_index_route_map_cmd, - "no network X:X::X:X/M label-index (0-1048560) route-map WORD", - NO_STR - "Specify a network to announce via BGP\n" - "IPv6 prefix\n" - "Label index to associate with the prefix\n" - "Label index value\n" - "Route-map to modify the attributes\n" - "Name of the route map\n") +ALIAS(no_ipv6_bgp_network, no_ipv6_bgp_network_label_index_route_map_cmd, + "no network X:X::X:X/M label-index (0-1048560) route-map WORD", NO_STR + "Specify a network to announce via BGP\n" + "IPv6 prefix\n" + "Label index to associate with the prefix\n" + "Label index value\n" + "Route-map to modify the attributes\n" + "Name of the route map\n") /* Aggreagete address: @@ -5393,592 +5323,586 @@ ALIAS (no_ipv6_bgp_network, suppress-map Conditionally filter more specific routes from updates */ -struct bgp_aggregate -{ - /* Summary-only flag. */ - u_char summary_only; +struct bgp_aggregate { + /* Summary-only flag. */ + u_char summary_only; - /* AS set generation. */ - u_char as_set; + /* AS set generation. */ + u_char as_set; - /* Route-map for aggregated route. */ - struct route_map *map; + /* Route-map for aggregated route. */ + struct route_map *map; - /* Suppress-count. */ - unsigned long count; + /* Suppress-count. */ + unsigned long count; - /* SAFI configuration. */ - safi_t safi; + /* SAFI configuration. */ + safi_t safi; }; -static struct bgp_aggregate * -bgp_aggregate_new (void) +static struct bgp_aggregate *bgp_aggregate_new(void) { - return XCALLOC (MTYPE_BGP_AGGREGATE, sizeof (struct bgp_aggregate)); + return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate)); } -static void -bgp_aggregate_free (struct bgp_aggregate *aggregate) +static void bgp_aggregate_free(struct bgp_aggregate *aggregate) { - XFREE (MTYPE_BGP_AGGREGATE, aggregate); -} + XFREE(MTYPE_BGP_AGGREGATE, aggregate); +} /* Update an aggregate as routes are added/removed from the BGP table */ -static void -bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew, - afi_t afi, safi_t safi, struct bgp_info *del, - struct bgp_aggregate *aggregate) -{ - struct bgp_table *table; - struct bgp_node *top; - struct bgp_node *rn; - u_char origin; - struct aspath *aspath = NULL; - struct aspath *asmerge = NULL; - struct community *community = NULL; - struct community *commerge = NULL; +static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, + struct bgp_info *rinew, afi_t afi, safi_t safi, + struct bgp_info *del, + struct bgp_aggregate *aggregate) +{ + struct bgp_table *table; + struct bgp_node *top; + struct bgp_node *rn; + u_char origin; + struct aspath *aspath = NULL; + struct aspath *asmerge = NULL; + struct community *community = NULL; + struct community *commerge = NULL; #if defined(AGGREGATE_NEXTHOP_CHECK) - struct in_addr nexthop; - u_int32_t med = 0; + struct in_addr nexthop; + u_int32_t med = 0; #endif - struct bgp_info *ri; - struct bgp_info *new; - int first = 1; - unsigned long match = 0; - u_char atomic_aggregate = 0; - - /* Record adding route's nexthop and med. */ - if (rinew) - { + struct bgp_info *ri; + struct bgp_info *new; + int first = 1; + unsigned long match = 0; + u_char atomic_aggregate = 0; + + /* Record adding route's nexthop and med. */ + if (rinew) { #if defined(AGGREGATE_NEXTHOP_CHECK) - nexthop = rinew->attr->nexthop; - med = rinew->attr->med; + nexthop = rinew->attr->nexthop; + med = rinew->attr->med; #endif - } - - /* ORIGIN attribute: If at least one route among routes that are - aggregated has ORIGIN with the value INCOMPLETE, then the - aggregated route must have the ORIGIN attribute with the value - INCOMPLETE. Otherwise, if at least one route among routes that - are aggregated has ORIGIN with the value EGP, then the aggregated - route must have the origin attribute with the value EGP. In all - other case the value of the ORIGIN attribute of the aggregated - route is INTERNAL. */ - origin = BGP_ORIGIN_IGP; - - table = bgp->rib[afi][safi]; - - top = bgp_node_get (table, p); - for (rn = bgp_node_get (table, p); rn; rn = bgp_route_next_until (rn, top)) - if (rn->p.prefixlen > p->prefixlen) - { - match = 0; + } - for (ri = rn->info; ri; ri = ri->next) - { - if (BGP_INFO_HOLDDOWN (ri)) - continue; + /* ORIGIN attribute: If at least one route among routes that are + aggregated has ORIGIN with the value INCOMPLETE, then the + aggregated route must have the ORIGIN attribute with the value + INCOMPLETE. Otherwise, if at least one route among routes that + are aggregated has ORIGIN with the value EGP, then the aggregated + route must have the origin attribute with the value EGP. In all + other case the value of the ORIGIN attribute of the aggregated + route is INTERNAL. */ + origin = BGP_ORIGIN_IGP; - if (del && ri == del) - continue; + table = bgp->rib[afi][safi]; - if (! rinew && first) - { + top = bgp_node_get(table, p); + for (rn = bgp_node_get(table, p); rn; + rn = bgp_route_next_until(rn, top)) + if (rn->p.prefixlen > p->prefixlen) { + match = 0; + + for (ri = rn->info; ri; ri = ri->next) { + if (BGP_INFO_HOLDDOWN(ri)) + continue; + + if (del && ri == del) + continue; + + if (!rinew && first) { #if defined(AGGREGATE_NEXTHOP_CHECK) - nexthop = ri->attr->nexthop; - med = ri->attr->med; + nexthop = ri->attr->nexthop; + med = ri->attr->med; #endif - first = 0; - } + first = 0; + } #ifdef AGGREGATE_NEXTHOP_CHECK - if (! IPV4_ADDR_SAME (&ri->attr->nexthop, &nexthop) - || ri->attr->med != med) - { - if (aspath) - aspath_free (aspath); - if (community) - community_free (community); - bgp_unlock_node (rn); - bgp_unlock_node (top); - return; - } + if (!IPV4_ADDR_SAME(&ri->attr->nexthop, + &nexthop) + || ri->attr->med != med) { + if (aspath) + aspath_free(aspath); + if (community) + community_free(community); + bgp_unlock_node(rn); + bgp_unlock_node(top); + return; + } #endif /* AGGREGATE_NEXTHOP_CHECK */ - if (ri->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) - atomic_aggregate = 1; - - if (ri->sub_type != BGP_ROUTE_AGGREGATE) - { - if (aggregate->summary_only) - { - (bgp_info_extra_get (ri))->suppress++; - bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); - match++; - } + if (ri->attr->flag + & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) + atomic_aggregate = 1; + + if (ri->sub_type != BGP_ROUTE_AGGREGATE) { + if (aggregate->summary_only) { + (bgp_info_extra_get(ri)) + ->suppress++; + bgp_info_set_flag( + rn, ri, + BGP_INFO_ATTR_CHANGED); + match++; + } + + aggregate->count++; + + if (origin < ri->attr->origin) + origin = ri->attr->origin; + + if (aggregate->as_set) { + if (aspath) { + asmerge = aspath_aggregate( + aspath, + ri->attr->aspath); + aspath_free(aspath); + aspath = asmerge; + } else + aspath = aspath_dup( + ri->attr->aspath); + + if (ri->attr->community) { + if (community) { + commerge = community_merge( + community, + ri->attr->community); + community = community_uniq_sort( + commerge); + community_free( + commerge); + } else + community = community_dup( + ri->attr->community); + } + } + } + } + if (match) + bgp_process(bgp, rn, afi, safi); + } + bgp_unlock_node(top); + if (rinew) { aggregate->count++; - if (origin < ri->attr->origin) - origin = ri->attr->origin; - - if (aggregate->as_set) - { - if (aspath) - { - asmerge = aspath_aggregate (aspath, ri->attr->aspath); - aspath_free (aspath); - aspath = asmerge; - } - else - aspath = aspath_dup (ri->attr->aspath); - - if (ri->attr->community) - { - if (community) - { - commerge = community_merge (community, - ri->attr->community); - community = community_uniq_sort (commerge); - community_free (commerge); - } - else - community = community_dup (ri->attr->community); - } - } - } - } - if (match) - bgp_process (bgp, rn, afi, safi); - } - bgp_unlock_node (top); - - if (rinew) - { - aggregate->count++; - - if (aggregate->summary_only) - (bgp_info_extra_get (rinew))->suppress++; - - if (origin < rinew->attr->origin) - origin = rinew->attr->origin; - - if (aggregate->as_set) - { - if (aspath) - { - asmerge = aspath_aggregate (aspath, rinew->attr->aspath); - aspath_free (aspath); - aspath = asmerge; - } - else - aspath = aspath_dup (rinew->attr->aspath); - - if (rinew->attr->community) - { - if (community) - { - commerge = community_merge (community, - rinew->attr->community); - community = community_uniq_sort (commerge); - community_free (commerge); + if (aggregate->summary_only) + (bgp_info_extra_get(rinew))->suppress++; + + if (origin < rinew->attr->origin) + origin = rinew->attr->origin; + + if (aggregate->as_set) { + if (aspath) { + asmerge = aspath_aggregate(aspath, + rinew->attr->aspath); + aspath_free(aspath); + aspath = asmerge; + } else + aspath = aspath_dup(rinew->attr->aspath); + + if (rinew->attr->community) { + if (community) { + commerge = community_merge( + community, + rinew->attr->community); + community = + community_uniq_sort(commerge); + community_free(commerge); + } else + community = community_dup( + rinew->attr->community); + } } - else - community = community_dup (rinew->attr->community); - } } - } - if (aggregate->count > 0) - { - rn = bgp_node_get (table, p); - new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self, - bgp_attr_aggregate_intern(bgp, origin, aspath, community, - aggregate->as_set, - atomic_aggregate), rn); - SET_FLAG (new->flags, BGP_INFO_VALID); - - bgp_info_add (rn, new); - bgp_unlock_node (rn); - bgp_process (bgp, rn, afi, safi); - } - else - { - if (aspath) - aspath_free (aspath); - if (community) - community_free (community); - } + if (aggregate->count > 0) { + rn = bgp_node_get(table, p); + new = info_make( + ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self, + bgp_attr_aggregate_intern(bgp, origin, aspath, + community, aggregate->as_set, + atomic_aggregate), + rn); + SET_FLAG(new->flags, BGP_INFO_VALID); + + bgp_info_add(rn, new); + bgp_unlock_node(rn); + bgp_process(bgp, rn, afi, safi); + } else { + if (aspath) + aspath_free(aspath); + if (community) + community_free(community); + } } -void bgp_aggregate_delete (struct bgp *, struct prefix *, afi_t, safi_t, - struct bgp_aggregate *); +void bgp_aggregate_delete(struct bgp *, struct prefix *, afi_t, safi_t, + struct bgp_aggregate *); -void -bgp_aggregate_increment (struct bgp *bgp, struct prefix *p, - struct bgp_info *ri, afi_t afi, safi_t safi) +void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p, + struct bgp_info *ri, afi_t afi, safi_t safi) { - struct bgp_node *child; - struct bgp_node *rn; - struct bgp_aggregate *aggregate; - struct bgp_table *table; + struct bgp_node *child; + struct bgp_node *rn; + struct bgp_aggregate *aggregate; + struct bgp_table *table; - /* MPLS-VPN aggregation is not yet supported. */ - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN)) - return; + /* MPLS-VPN aggregation is not yet supported. */ + if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) + || (safi == SAFI_EVPN)) + return; - table = bgp->aggregate[afi][safi]; + table = bgp->aggregate[afi][safi]; - /* No aggregates configured. */ - if (bgp_table_top_nolock (table) == NULL) - return; + /* No aggregates configured. */ + if (bgp_table_top_nolock(table) == NULL) + return; - if (p->prefixlen == 0) - return; + if (p->prefixlen == 0) + return; - if (BGP_INFO_HOLDDOWN (ri)) - return; + if (BGP_INFO_HOLDDOWN(ri)) + return; - child = bgp_node_get (table, p); + child = bgp_node_get(table, p); - /* Aggregate address configuration check. */ - for (rn = child; rn; rn = bgp_node_parent_nolock (rn)) - if ((aggregate = rn->info) != NULL && rn->p.prefixlen < p->prefixlen) - { - bgp_aggregate_delete (bgp, &rn->p, afi, safi, aggregate); - bgp_aggregate_route (bgp, &rn->p, ri, afi, safi, NULL, aggregate); - } - bgp_unlock_node (child); + /* Aggregate address configuration check. */ + for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) + if ((aggregate = rn->info) != NULL + && rn->p.prefixlen < p->prefixlen) { + bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate); + bgp_aggregate_route(bgp, &rn->p, ri, afi, safi, NULL, + aggregate); + } + bgp_unlock_node(child); } -void -bgp_aggregate_decrement (struct bgp *bgp, struct prefix *p, - struct bgp_info *del, afi_t afi, safi_t safi) +void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p, + struct bgp_info *del, afi_t afi, safi_t safi) { - struct bgp_node *child; - struct bgp_node *rn; - struct bgp_aggregate *aggregate; - struct bgp_table *table; - - /* MPLS-VPN aggregation is not yet supported. */ - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN)) - return; + struct bgp_node *child; + struct bgp_node *rn; + struct bgp_aggregate *aggregate; + struct bgp_table *table; - table = bgp->aggregate[afi][safi]; - - /* No aggregates configured. */ - if (bgp_table_top_nolock (table) == NULL) - return; + /* MPLS-VPN aggregation is not yet supported. */ + if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) + || (safi == SAFI_EVPN)) + return; - if (p->prefixlen == 0) - return; + table = bgp->aggregate[afi][safi]; - child = bgp_node_get (table, p); + /* No aggregates configured. */ + if (bgp_table_top_nolock(table) == NULL) + return; - /* Aggregate address configuration check. */ - for (rn = child; rn; rn = bgp_node_parent_nolock (rn)) - if ((aggregate = rn->info) != NULL && rn->p.prefixlen < p->prefixlen) - { - bgp_aggregate_delete (bgp, &rn->p, afi, safi, aggregate); - bgp_aggregate_route (bgp, &rn->p, NULL, afi, safi, del, aggregate); - } - bgp_unlock_node (child); -} + if (p->prefixlen == 0) + return; -/* Called via bgp_aggregate_set when the user configures aggregate-address */ -static void -bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi, - struct bgp_aggregate *aggregate) -{ - struct bgp_table *table; - struct bgp_node *top; - struct bgp_node *rn; - struct bgp_info *new; - struct bgp_info *ri; - unsigned long match; - u_char origin = BGP_ORIGIN_IGP; - struct aspath *aspath = NULL; - struct aspath *asmerge = NULL; - struct community *community = NULL; - struct community *commerge = NULL; - u_char atomic_aggregate = 0; - - table = bgp->rib[afi][safi]; - - /* Sanity check. */ - if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN) - return; - if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN) - return; - - /* If routes exists below this node, generate aggregate routes. */ - top = bgp_node_get (table, p); - for (rn = bgp_node_get (table, p); rn; rn = bgp_route_next_until (rn, top)) - if (rn->p.prefixlen > p->prefixlen) - { - match = 0; + child = bgp_node_get(table, p); - for (ri = rn->info; ri; ri = ri->next) - { - if (BGP_INFO_HOLDDOWN (ri)) - continue; + /* Aggregate address configuration check. */ + for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) + if ((aggregate = rn->info) != NULL + && rn->p.prefixlen < p->prefixlen) { + bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate); + bgp_aggregate_route(bgp, &rn->p, NULL, afi, safi, del, + aggregate); + } + bgp_unlock_node(child); +} - if (ri->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) - atomic_aggregate = 1; +/* Called via bgp_aggregate_set when the user configures aggregate-address */ +static void bgp_aggregate_add(struct bgp *bgp, struct prefix *p, afi_t afi, + safi_t safi, struct bgp_aggregate *aggregate) +{ + struct bgp_table *table; + struct bgp_node *top; + struct bgp_node *rn; + struct bgp_info *new; + struct bgp_info *ri; + unsigned long match; + u_char origin = BGP_ORIGIN_IGP; + struct aspath *aspath = NULL; + struct aspath *asmerge = NULL; + struct community *community = NULL; + struct community *commerge = NULL; + u_char atomic_aggregate = 0; + + table = bgp->rib[afi][safi]; + + /* Sanity check. */ + if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN) + return; + if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN) + return; - if (ri->sub_type != BGP_ROUTE_AGGREGATE) - { - /* summary-only aggregate route suppress aggregated - route announcement. */ - if (aggregate->summary_only) - { - (bgp_info_extra_get (ri))->suppress++; - bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); - match++; - } - - /* If at least one route among routes that are aggregated has - * ORIGIN with the value INCOMPLETE, then the aggregated route - * MUST have the ORIGIN attribute with the value INCOMPLETE. - * Otherwise, if at least one route among routes that are - * aggregated has ORIGIN with the value EGP, then the aggregated - * route MUST have the ORIGIN attribute with the value EGP. - */ - if (origin < ri->attr->origin) - origin = ri->attr->origin; - - /* as-set aggregate route generate origin, as path, - community aggregation. */ - if (aggregate->as_set) - { - if (aspath) - { - asmerge = aspath_aggregate (aspath, ri->attr->aspath); - aspath_free (aspath); - aspath = asmerge; - } - else - aspath = aspath_dup (ri->attr->aspath); - - if (ri->attr->community) - { - if (community) - { - commerge = community_merge (community, - ri->attr->community); - community = community_uniq_sort (commerge); - community_free (commerge); - } - else - community = community_dup (ri->attr->community); - } - } - aggregate->count++; - } - } - - /* If this node is suppressed, process the change. */ - if (match) - bgp_process (bgp, rn, afi, safi); - } - bgp_unlock_node (top); - - /* Add aggregate route to BGP table. */ - if (aggregate->count) - { - rn = bgp_node_get (table, p); - new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self, - bgp_attr_aggregate_intern(bgp, origin, aspath, community, - aggregate->as_set, - atomic_aggregate), rn); - SET_FLAG (new->flags, BGP_INFO_VALID); - - bgp_info_add (rn, new); - bgp_unlock_node (rn); - - /* Process change. */ - bgp_process (bgp, rn, afi, safi); - } - else - { - if (aspath) - aspath_free (aspath); - if (community) - community_free (community); - } + /* If routes exists below this node, generate aggregate routes. */ + top = bgp_node_get(table, p); + for (rn = bgp_node_get(table, p); rn; + rn = bgp_route_next_until(rn, top)) + if (rn->p.prefixlen > p->prefixlen) { + match = 0; + + for (ri = rn->info; ri; ri = ri->next) { + if (BGP_INFO_HOLDDOWN(ri)) + continue; + + if (ri->attr->flag + & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) + atomic_aggregate = 1; + + if (ri->sub_type != BGP_ROUTE_AGGREGATE) { + /* summary-only aggregate route suppress + aggregated + route announcement. */ + if (aggregate->summary_only) { + (bgp_info_extra_get(ri)) + ->suppress++; + bgp_info_set_flag( + rn, ri, + BGP_INFO_ATTR_CHANGED); + match++; + } + + /* If at least one route among routes + * that are aggregated has + * ORIGIN with the value INCOMPLETE, + * then the aggregated route + * MUST have the ORIGIN attribute with + * the value INCOMPLETE. + * Otherwise, if at least one route + * among routes that are + * aggregated has ORIGIN with the value + * EGP, then the aggregated + * route MUST have the ORIGIN attribute + * with the value EGP. + */ + if (origin < ri->attr->origin) + origin = ri->attr->origin; + + /* as-set aggregate route generate + origin, as path, + community aggregation. */ + if (aggregate->as_set) { + if (aspath) { + asmerge = aspath_aggregate( + aspath, + ri->attr->aspath); + aspath_free(aspath); + aspath = asmerge; + } else + aspath = aspath_dup( + ri->attr->aspath); + + if (ri->attr->community) { + if (community) { + commerge = community_merge( + community, + ri->attr->community); + community = community_uniq_sort( + commerge); + community_free( + commerge); + } else + community = community_dup( + ri->attr->community); + } + } + aggregate->count++; + } + } + + /* If this node is suppressed, process the change. */ + if (match) + bgp_process(bgp, rn, afi, safi); + } + bgp_unlock_node(top); + + /* Add aggregate route to BGP table. */ + if (aggregate->count) { + rn = bgp_node_get(table, p); + new = info_make( + ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self, + bgp_attr_aggregate_intern(bgp, origin, aspath, + community, aggregate->as_set, + atomic_aggregate), + rn); + SET_FLAG(new->flags, BGP_INFO_VALID); + + bgp_info_add(rn, new); + bgp_unlock_node(rn); + + /* Process change. */ + bgp_process(bgp, rn, afi, safi); + } else { + if (aspath) + aspath_free(aspath); + if (community) + community_free(community); + } } -void -bgp_aggregate_delete (struct bgp *bgp, struct prefix *p, afi_t afi, - safi_t safi, struct bgp_aggregate *aggregate) +void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi, + safi_t safi, struct bgp_aggregate *aggregate) { - struct bgp_table *table; - struct bgp_node *top; - struct bgp_node *rn; - struct bgp_info *ri; - unsigned long match; + struct bgp_table *table; + struct bgp_node *top; + struct bgp_node *rn; + struct bgp_info *ri; + unsigned long match; - table = bgp->rib[afi][safi]; + table = bgp->rib[afi][safi]; - if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN) - return; - if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN) - return; + if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN) + return; + if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN) + return; + + /* If routes exists below this node, generate aggregate routes. */ + top = bgp_node_get(table, p); + for (rn = bgp_node_get(table, p); rn; + rn = bgp_route_next_until(rn, top)) + if (rn->p.prefixlen > p->prefixlen) { + match = 0; + + for (ri = rn->info; ri; ri = ri->next) { + if (BGP_INFO_HOLDDOWN(ri)) + continue; + + if (ri->sub_type != BGP_ROUTE_AGGREGATE) { + if (aggregate->summary_only + && ri->extra) { + ri->extra->suppress--; + + if (ri->extra->suppress == 0) { + bgp_info_set_flag( + rn, ri, + BGP_INFO_ATTR_CHANGED); + match++; + } + } + aggregate->count--; + } + } + + /* If this node was suppressed, process the change. */ + if (match) + bgp_process(bgp, rn, afi, safi); + } + bgp_unlock_node(top); - /* If routes exists below this node, generate aggregate routes. */ - top = bgp_node_get (table, p); - for (rn = bgp_node_get (table, p); rn; rn = bgp_route_next_until (rn, top)) - if (rn->p.prefixlen > p->prefixlen) - { - match = 0; + /* Delete aggregate route from BGP table. */ + rn = bgp_node_get(table, p); for (ri = rn->info; ri; ri = ri->next) - { - if (BGP_INFO_HOLDDOWN (ri)) - continue; - - if (ri->sub_type != BGP_ROUTE_AGGREGATE) - { - if (aggregate->summary_only && ri->extra) - { - ri->extra->suppress--; - - if (ri->extra->suppress == 0) - { - bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); - match++; - } - } - aggregate->count--; - } - } - - /* If this node was suppressed, process the change. */ - if (match) - bgp_process (bgp, rn, afi, safi); - } - bgp_unlock_node (top); - - /* Delete aggregate route from BGP table. */ - rn = bgp_node_get (table, p); - - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self - && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_AGGREGATE) - break; - - /* Withdraw static BGP route from routing table. */ - if (ri) - { - bgp_info_delete (rn, ri); - bgp_process (bgp, rn, afi, safi); - } + if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP + && ri->sub_type == BGP_ROUTE_AGGREGATE) + break; + + /* Withdraw static BGP route from routing table. */ + if (ri) { + bgp_info_delete(rn, ri); + bgp_process(bgp, rn, afi, safi); + } - /* Unlock bgp_node_lookup. */ - bgp_unlock_node (rn); + /* Unlock bgp_node_lookup. */ + bgp_unlock_node(rn); } /* Aggregate route attribute. */ #define AGGREGATE_SUMMARY_ONLY 1 #define AGGREGATE_AS_SET 1 -static int -bgp_aggregate_unset (struct vty *vty, const char *prefix_str, - afi_t afi, safi_t safi) +static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str, + afi_t afi, safi_t safi) { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int ret; - struct prefix p; - struct bgp_node *rn; - struct bgp_aggregate *aggregate; - - /* Convert string to prefix structure. */ - ret = str2prefix (prefix_str, &p); - if (!ret) - { - vty_out (vty, "Malformed prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - apply_mask (&p); - - /* Old configuration check. */ - rn = bgp_node_lookup (bgp->aggregate[afi][safi], &p); - if (! rn) - { - vty_out (vty,"%% There is no aggregate-address configuration.\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - aggregate = rn->info; - if (aggregate->safi == SAFI_UNICAST) - bgp_aggregate_delete (bgp, &p, afi, SAFI_UNICAST, aggregate); - if (aggregate->safi == SAFI_LABELED_UNICAST) - bgp_aggregate_delete (bgp, &p, afi, SAFI_LABELED_UNICAST, aggregate); - if (aggregate->safi == SAFI_MULTICAST) - bgp_aggregate_delete (bgp, &p, afi, SAFI_MULTICAST, aggregate); - - /* Unlock aggregate address configuration. */ - rn->info = NULL; - bgp_aggregate_free (aggregate); - bgp_unlock_node (rn); - bgp_unlock_node (rn); - - return CMD_SUCCESS; -} - -static int -bgp_aggregate_set (struct vty *vty, const char *prefix_str, - afi_t afi, safi_t safi, - u_char summary_only, u_char as_set) -{ - VTY_DECLVAR_CONTEXT(bgp, bgp); - int ret; - struct prefix p; - struct bgp_node *rn; - struct bgp_aggregate *aggregate; - - /* Convert string to prefix structure. */ - ret = str2prefix (prefix_str, &p); - if (!ret) - { - vty_out (vty, "Malformed prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - apply_mask (&p); + VTY_DECLVAR_CONTEXT(bgp, bgp); + int ret; + struct prefix p; + struct bgp_node *rn; + struct bgp_aggregate *aggregate; - /* Old configuration check. */ - rn = bgp_node_get (bgp->aggregate[afi][safi], &p); + /* Convert string to prefix structure. */ + ret = str2prefix(prefix_str, &p); + if (!ret) { + vty_out(vty, "Malformed prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + apply_mask(&p); + + /* Old configuration check. */ + rn = bgp_node_lookup(bgp->aggregate[afi][safi], &p); + if (!rn) { + vty_out(vty, + "%% There is no aggregate-address configuration.\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (rn->info) - { - vty_out (vty, "There is already same aggregate network.\n"); - /* try to remove the old entry */ - ret = bgp_aggregate_unset (vty, prefix_str, afi, safi); - if (ret) - { - vty_out (vty, "Error deleting aggregate.\n"); - bgp_unlock_node (rn); - return CMD_WARNING_CONFIG_FAILED; - } - } + aggregate = rn->info; + if (aggregate->safi == SAFI_UNICAST) + bgp_aggregate_delete(bgp, &p, afi, SAFI_UNICAST, aggregate); + if (aggregate->safi == SAFI_LABELED_UNICAST) + bgp_aggregate_delete(bgp, &p, afi, SAFI_LABELED_UNICAST, + aggregate); + if (aggregate->safi == SAFI_MULTICAST) + bgp_aggregate_delete(bgp, &p, afi, SAFI_MULTICAST, aggregate); + + /* Unlock aggregate address configuration. */ + rn->info = NULL; + bgp_aggregate_free(aggregate); + bgp_unlock_node(rn); + bgp_unlock_node(rn); + + return CMD_SUCCESS; +} + +static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi, + safi_t safi, u_char summary_only, u_char as_set) +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + int ret; + struct prefix p; + struct bgp_node *rn; + struct bgp_aggregate *aggregate; + + /* Convert string to prefix structure. */ + ret = str2prefix(prefix_str, &p); + if (!ret) { + vty_out(vty, "Malformed prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + apply_mask(&p); + + /* Old configuration check. */ + rn = bgp_node_get(bgp->aggregate[afi][safi], &p); + + if (rn->info) { + vty_out(vty, "There is already same aggregate network.\n"); + /* try to remove the old entry */ + ret = bgp_aggregate_unset(vty, prefix_str, afi, safi); + if (ret) { + vty_out(vty, "Error deleting aggregate.\n"); + bgp_unlock_node(rn); + return CMD_WARNING_CONFIG_FAILED; + } + } - /* Make aggregate address structure. */ - aggregate = bgp_aggregate_new (); - aggregate->summary_only = summary_only; - aggregate->as_set = as_set; - aggregate->safi = safi; - rn->info = aggregate; + /* Make aggregate address structure. */ + aggregate = bgp_aggregate_new(); + aggregate->summary_only = summary_only; + aggregate->as_set = as_set; + aggregate->safi = safi; + rn->info = aggregate; - /* Aggregate address insert into BGP routing table. */ - if (safi == SAFI_UNICAST) - bgp_aggregate_add (bgp, &p, afi, SAFI_UNICAST, aggregate); - if (safi == SAFI_LABELED_UNICAST) - bgp_aggregate_add (bgp, &p, afi, SAFI_LABELED_UNICAST, aggregate); - if (safi == SAFI_MULTICAST) - bgp_aggregate_add (bgp, &p, afi, SAFI_MULTICAST, aggregate); + /* Aggregate address insert into BGP routing table. */ + if (safi == SAFI_UNICAST) + bgp_aggregate_add(bgp, &p, afi, SAFI_UNICAST, aggregate); + if (safi == SAFI_LABELED_UNICAST) + bgp_aggregate_add(bgp, &p, afi, SAFI_LABELED_UNICAST, + aggregate); + if (safi == SAFI_MULTICAST) + bgp_aggregate_add(bgp, &p, afi, SAFI_MULTICAST, aggregate); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (aggregate_address, @@ -5991,14 +5915,18 @@ DEFUN (aggregate_address, "Filter more specific routes from updates\n" "Generate AS set path information\n") { - int idx = 0; - argv_find (argv, argc, "A.B.C.D/M", &idx); - char *prefix = argv[idx]->arg; - int as_set = argv_find (argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0; - idx = 0; - int summary_only = argv_find (argv, argc, "summary-only", &idx) ? AGGREGATE_SUMMARY_ONLY : 0; + int idx = 0; + argv_find(argv, argc, "A.B.C.D/M", &idx); + char *prefix = argv[idx]->arg; + int as_set = + argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0; + idx = 0; + int summary_only = argv_find(argv, argc, "summary-only", &idx) + ? AGGREGATE_SUMMARY_ONLY + : 0; - return bgp_aggregate_set (vty, prefix, AFI_IP, bgp_node_safi (vty), summary_only, as_set); + return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty), + summary_only, as_set); } DEFUN (aggregate_address_mask, @@ -6012,24 +5940,27 @@ DEFUN (aggregate_address_mask, "Filter more specific routes from updates\n" "Generate AS set path information\n") { - int idx = 0; - argv_find (argv, argc, "A.B.C.D", &idx); - char *prefix = argv[idx]->arg; - char *mask = argv[idx+1]->arg; - int as_set = argv_find (argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0; - idx = 0; - int summary_only = argv_find (argv, argc, "summary-only", &idx) ? AGGREGATE_SUMMARY_ONLY : 0; - - char prefix_str[BUFSIZ]; - int ret = netmask_str2prefix_str (prefix, mask, prefix_str); - - if (! ret) - { - vty_out (vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } + int idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + char *prefix = argv[idx]->arg; + char *mask = argv[idx + 1]->arg; + int as_set = + argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0; + idx = 0; + int summary_only = argv_find(argv, argc, "summary-only", &idx) + ? AGGREGATE_SUMMARY_ONLY + : 0; + + char prefix_str[BUFSIZ]; + int ret = netmask_str2prefix_str(prefix, mask, prefix_str); + + if (!ret) { + vty_out(vty, "%% Inconsistent address and mask\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return bgp_aggregate_set (vty, prefix_str, AFI_IP, bgp_node_safi (vty), summary_only, as_set); + return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), + summary_only, as_set); } DEFUN (no_aggregate_address, @@ -6043,10 +5974,10 @@ DEFUN (no_aggregate_address, "Filter more specific routes from updates\n" "Generate AS set path information\n") { - int idx = 0; - argv_find (argv, argc, "A.B.C.D/M", &idx); - char *prefix = argv[idx]->arg; - return bgp_aggregate_unset (vty, prefix, AFI_IP, bgp_node_safi (vty)); + int idx = 0; + argv_find(argv, argc, "A.B.C.D/M", &idx); + char *prefix = argv[idx]->arg; + return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty)); } DEFUN (no_aggregate_address_mask, @@ -6061,21 +5992,20 @@ DEFUN (no_aggregate_address_mask, "Filter more specific routes from updates\n" "Generate AS set path information\n") { - int idx = 0; - argv_find (argv, argc, "A.B.C.D", &idx); - char *prefix = argv[idx]->arg; - char *mask = argv[idx+1]->arg; + int idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + char *prefix = argv[idx]->arg; + char *mask = argv[idx + 1]->arg; - char prefix_str[BUFSIZ]; - int ret = netmask_str2prefix_str (prefix, mask, prefix_str); + char prefix_str[BUFSIZ]; + int ret = netmask_str2prefix_str(prefix, mask, prefix_str); - if (! ret) - { - vty_out (vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!ret) { + vty_out(vty, "%% Inconsistent address and mask\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return bgp_aggregate_unset (vty, prefix_str, AFI_IP, bgp_node_safi (vty)); + return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty)); } DEFUN (ipv6_aggregate_address, @@ -6085,11 +6015,14 @@ DEFUN (ipv6_aggregate_address, "Aggregate prefix\n" "Filter more specific routes from updates\n") { - int idx = 0; - argv_find (argv, argc, "X:X::X:X/M", &idx); - char *prefix = argv[idx]->arg; - int sum_only = argv_find (argv, argc, "summary-only", &idx) ? AGGREGATE_SUMMARY_ONLY : 0; - return bgp_aggregate_set (vty, prefix, AFI_IP6, SAFI_UNICAST, sum_only, 0); + int idx = 0; + argv_find(argv, argc, "X:X::X:X/M", &idx); + char *prefix = argv[idx]->arg; + int sum_only = argv_find(argv, argc, "summary-only", &idx) + ? AGGREGATE_SUMMARY_ONLY + : 0; + return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, sum_only, + 0); } DEFUN (no_ipv6_aggregate_address, @@ -6100,2549 +6033,2655 @@ DEFUN (no_ipv6_aggregate_address, "Aggregate prefix\n" "Filter more specific routes from updates\n") { - int idx = 0; - argv_find (argv, argc, "X:X::X:X/M", &idx); - char *prefix = argv[idx]->arg; - return bgp_aggregate_unset (vty, prefix, AFI_IP6, SAFI_UNICAST); + int idx = 0; + argv_find(argv, argc, "X:X::X:X/M", &idx); + char *prefix = argv[idx]->arg; + return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST); } /* Redistribute route treatment. */ -void -bgp_redistribute_add (struct bgp *bgp, struct prefix *p, const struct in_addr *nexthop, - const struct in6_addr *nexthop6, unsigned int ifindex, - u_int32_t metric, u_char type, u_short instance, route_tag_t tag) -{ - struct bgp_info *new; - struct bgp_info *bi; - struct bgp_info info; - struct bgp_node *bn; - struct attr attr; - struct attr *new_attr; - afi_t afi; - int ret; - struct bgp_redist *red; - - /* Make default attribute. */ - bgp_attr_default_set (&attr, BGP_ORIGIN_INCOMPLETE); - if (nexthop) - attr.nexthop = *nexthop; - attr.nh_ifindex = ifindex; - - if (nexthop6) - { - attr.mp_nexthop_global = *nexthop6; - attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; - } +void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, + const struct in_addr *nexthop, + const struct in6_addr *nexthop6, unsigned int ifindex, + u_int32_t metric, u_char type, u_short instance, + route_tag_t tag) +{ + struct bgp_info *new; + struct bgp_info *bi; + struct bgp_info info; + struct bgp_node *bn; + struct attr attr; + struct attr *new_attr; + afi_t afi; + int ret; + struct bgp_redist *red; + + /* Make default attribute. */ + bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE); + if (nexthop) + attr.nexthop = *nexthop; + attr.nh_ifindex = ifindex; + + if (nexthop6) { + attr.mp_nexthop_global = *nexthop6; + attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; + } - attr.med = metric; - attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); - attr.tag = tag; + attr.med = metric; + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); + attr.tag = tag; - afi = family2afi (p->family); + afi = family2afi(p->family); - red = bgp_redist_lookup(bgp, afi, type, instance); - if (red) - { - struct attr attr_new; - - /* Copy attribute for modification. */ - bgp_attr_dup (&attr_new, &attr); - - if (red->redist_metric_flag) - attr_new.med = red->redist_metric; - - /* Apply route-map. */ - if (red->rmap.name) - { - info.peer = bgp->peer_self; - info.attr = &attr_new; - - SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE); - - ret = route_map_apply (red->rmap.map, p, RMAP_BGP, &info); - - bgp->peer_self->rmap_type = 0; - - if (ret == RMAP_DENYMATCH) - { - /* Free uninterned attribute. */ - bgp_attr_flush (&attr_new); - - /* Unintern original. */ - aspath_unintern (&attr.aspath); - bgp_redistribute_delete (bgp, p, type, instance); - return; - } - } - - bn = bgp_afi_node_get (bgp->rib[afi][SAFI_UNICAST], - afi, SAFI_UNICAST, p, NULL); - - new_attr = bgp_attr_intern (&attr_new); - - for (bi = bn->info; bi; bi = bi->next) - if (bi->peer == bgp->peer_self - && bi->sub_type == BGP_ROUTE_REDISTRIBUTE) - break; - - if (bi) - { - /* Ensure the (source route) type is updated. */ - bi->type = type; - if (attrhash_cmp (bi->attr, new_attr) && - !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) - { - bgp_attr_unintern (&new_attr); - aspath_unintern (&attr.aspath); - bgp_unlock_node (bn); - return; - } - else - { - /* The attribute is changed. */ - bgp_info_set_flag (bn, bi, BGP_INFO_ATTR_CHANGED); - - /* Rewrite BGP route information. */ - if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) - bgp_info_restore(bn, bi); - else - bgp_aggregate_decrement (bgp, p, bi, afi, SAFI_UNICAST); - bgp_attr_unintern (&bi->attr); - bi->attr = new_attr; - bi->uptime = bgp_clock (); - - /* Process change. */ - bgp_aggregate_increment (bgp, p, bi, afi, SAFI_UNICAST); - bgp_process (bgp, bn, afi, SAFI_UNICAST); - bgp_unlock_node (bn); - aspath_unintern (&attr.aspath); - return; - } - } - - new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance, bgp->peer_self, - new_attr, bn); - SET_FLAG (new->flags, BGP_INFO_VALID); - - bgp_aggregate_increment (bgp, p, new, afi, SAFI_UNICAST); - bgp_info_add (bn, new); - bgp_unlock_node (bn); - bgp_process (bgp, bn, afi, SAFI_UNICAST); - } + red = bgp_redist_lookup(bgp, afi, type, instance); + if (red) { + struct attr attr_new; - /* Unintern original. */ - aspath_unintern (&attr.aspath); -} + /* Copy attribute for modification. */ + bgp_attr_dup(&attr_new, &attr); -void -bgp_redistribute_delete (struct bgp *bgp, struct prefix *p, u_char type, u_short instance) -{ - afi_t afi; - struct bgp_node *rn; - struct bgp_info *ri; - struct bgp_redist *red; + if (red->redist_metric_flag) + attr_new.med = red->redist_metric; - afi = family2afi (p->family); + /* Apply route-map. */ + if (red->rmap.name) { + info.peer = bgp->peer_self; + info.attr = &attr_new; - red = bgp_redist_lookup(bgp, afi, type, instance); - if (red) - { - rn = bgp_afi_node_get (bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST, p, NULL); - - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self - && ri->type == type) - break; - - if (ri) - { - bgp_aggregate_decrement (bgp, p, ri, afi, SAFI_UNICAST); - bgp_info_delete (rn, ri); - bgp_process (bgp, rn, afi, SAFI_UNICAST); - } - bgp_unlock_node (rn); - } + SET_FLAG(bgp->peer_self->rmap_type, + PEER_RMAP_TYPE_REDISTRIBUTE); + + ret = route_map_apply(red->rmap.map, p, RMAP_BGP, + &info); + + bgp->peer_self->rmap_type = 0; + + if (ret == RMAP_DENYMATCH) { + /* Free uninterned attribute. */ + bgp_attr_flush(&attr_new); + + /* Unintern original. */ + aspath_unintern(&attr.aspath); + bgp_redistribute_delete(bgp, p, type, instance); + return; + } + } + + bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi, + SAFI_UNICAST, p, NULL); + + new_attr = bgp_attr_intern(&attr_new); + + for (bi = bn->info; bi; bi = bi->next) + if (bi->peer == bgp->peer_self + && bi->sub_type == BGP_ROUTE_REDISTRIBUTE) + break; + + if (bi) { + /* Ensure the (source route) type is updated. */ + bi->type = type; + if (attrhash_cmp(bi->attr, new_attr) + && !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) { + bgp_attr_unintern(&new_attr); + aspath_unintern(&attr.aspath); + bgp_unlock_node(bn); + return; + } else { + /* The attribute is changed. */ + bgp_info_set_flag(bn, bi, + BGP_INFO_ATTR_CHANGED); + + /* Rewrite BGP route information. */ + if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + bgp_info_restore(bn, bi); + else + bgp_aggregate_decrement(bgp, p, bi, afi, + SAFI_UNICAST); + bgp_attr_unintern(&bi->attr); + bi->attr = new_attr; + bi->uptime = bgp_clock(); + + /* Process change. */ + bgp_aggregate_increment(bgp, p, bi, afi, + SAFI_UNICAST); + bgp_process(bgp, bn, afi, SAFI_UNICAST); + bgp_unlock_node(bn); + aspath_unintern(&attr.aspath); + return; + } + } + + new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance, + bgp->peer_self, new_attr, bn); + SET_FLAG(new->flags, BGP_INFO_VALID); + + bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST); + bgp_info_add(bn, new); + bgp_unlock_node(bn); + bgp_process(bgp, bn, afi, SAFI_UNICAST); + } + + /* Unintern original. */ + aspath_unintern(&attr.aspath); } -/* Withdraw specified route type's route. */ -void -bgp_redistribute_withdraw (struct bgp *bgp, afi_t afi, int type, u_short instance) +void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, u_char type, + u_short instance) { - struct bgp_node *rn; - struct bgp_info *ri; - struct bgp_table *table; + afi_t afi; + struct bgp_node *rn; + struct bgp_info *ri; + struct bgp_redist *red; - table = bgp->rib[afi][SAFI_UNICAST]; + afi = family2afi(p->family); - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - { - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self - && ri->type == type - && ri->instance == instance) - break; - - if (ri) - { - bgp_aggregate_decrement (bgp, &rn->p, ri, afi, SAFI_UNICAST); - bgp_info_delete (rn, ri); - bgp_process (bgp, rn, afi, SAFI_UNICAST); + red = bgp_redist_lookup(bgp, afi, type, instance); + if (red) { + rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi, + SAFI_UNICAST, p, NULL); + + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == bgp->peer_self && ri->type == type) + break; + + if (ri) { + bgp_aggregate_decrement(bgp, p, ri, afi, SAFI_UNICAST); + bgp_info_delete(rn, ri); + bgp_process(bgp, rn, afi, SAFI_UNICAST); + } + bgp_unlock_node(rn); + } +} + +/* Withdraw specified route type's route. */ +void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type, + u_short instance) +{ + struct bgp_node *rn; + struct bgp_info *ri; + struct bgp_table *table; + + table = bgp->rib[afi][SAFI_UNICAST]; + + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == bgp->peer_self && ri->type == type + && ri->instance == instance) + break; + + if (ri) { + bgp_aggregate_decrement(bgp, &rn->p, ri, afi, + SAFI_UNICAST); + bgp_info_delete(rn, ri); + bgp_process(bgp, rn, afi, SAFI_UNICAST); + } } - } } /* Static function to display route. */ -static void -route_vty_out_route (struct prefix *p, struct vty *vty) +static void route_vty_out_route(struct prefix *p, struct vty *vty) { - int len; - u_int32_t destination; - char buf[BUFSIZ]; + int len; + u_int32_t destination; + char buf[BUFSIZ]; - if (p->family == AF_INET) - { - len = vty_out (vty, "%s", inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ)); - destination = ntohl (p->u.prefix4.s_addr); - - if ((IN_CLASSC (destination) && p->prefixlen == 24) - || (IN_CLASSB (destination) && p->prefixlen == 16) - || (IN_CLASSA (destination) && p->prefixlen == 8) - || p->u.prefix4.s_addr == 0) - { - /* When mask is natural, mask is not displayed. */ - } - else - len += vty_out (vty, "/%d", p->prefixlen); - } - else if (p->family == AF_ETHERNET) - { -#if defined (HAVE_CUMULUS) - len = vty_out (vty, "%s", - bgp_evpn_route2str((struct prefix_evpn *)p, buf, BUFSIZ)); + if (p->family == AF_INET) { + len = vty_out(vty, "%s", + inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ)); + destination = ntohl(p->u.prefix4.s_addr); + + if ((IN_CLASSC(destination) && p->prefixlen == 24) + || (IN_CLASSB(destination) && p->prefixlen == 16) + || (IN_CLASSA(destination) && p->prefixlen == 8) + || p->u.prefix4.s_addr == 0) { + /* When mask is natural, mask is not displayed. */ + } else + len += vty_out(vty, "/%d", p->prefixlen); + } else if (p->family == AF_ETHERNET) { +#if defined(HAVE_CUMULUS) + len = vty_out(vty, "%s", + bgp_evpn_route2str((struct prefix_evpn *)p, buf, + BUFSIZ)); #else - prefix2str(p, buf, PREFIX_STRLEN); - len = vty_out (vty, "%s", buf); + prefix2str(p, buf, PREFIX_STRLEN); + len = vty_out(vty, "%s", buf); #endif - } - else - len = vty_out (vty, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), - p->prefixlen); - - len = 17 - len; - if (len < 1) - vty_out (vty, "\n%*s", 20, " "); - else - vty_out (vty, "%*s", len, " "); + } else + len = vty_out(vty, "%s/%d", + inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), + p->prefixlen); + + len = 17 - len; + if (len < 1) + vty_out(vty, "\n%*s", 20, " "); + else + vty_out(vty, "%*s", len, " "); } -enum bgp_display_type -{ - normal_list, +enum bgp_display_type { + normal_list, }; /* Print the short form route status for a bgp_info */ -static void -route_vty_short_status_out (struct vty *vty, struct bgp_info *binfo, - json_object *json_path) +static void route_vty_short_status_out(struct vty *vty, struct bgp_info *binfo, + json_object *json_path) { - if (json_path) - { + if (json_path) { - /* Route status display. */ - if (CHECK_FLAG (binfo->flags, BGP_INFO_REMOVED)) - json_object_boolean_true_add(json_path, "removed"); + /* Route status display. */ + if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED)) + json_object_boolean_true_add(json_path, "removed"); - if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE)) - json_object_boolean_true_add(json_path, "stale"); + if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE)) + json_object_boolean_true_add(json_path, "stale"); - if (binfo->extra && binfo->extra->suppress) - json_object_boolean_true_add(json_path, "suppressed"); + if (binfo->extra && binfo->extra->suppress) + json_object_boolean_true_add(json_path, "suppressed"); - if (CHECK_FLAG (binfo->flags, BGP_INFO_VALID) && - ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) - json_object_boolean_true_add(json_path, "valid"); + if (CHECK_FLAG(binfo->flags, BGP_INFO_VALID) + && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) + json_object_boolean_true_add(json_path, "valid"); - /* Selected */ - if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) - json_object_boolean_true_add(json_path, "history"); + /* Selected */ + if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) + json_object_boolean_true_add(json_path, "history"); - if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)) - json_object_boolean_true_add(json_path, "damped"); + if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)) + json_object_boolean_true_add(json_path, "damped"); - if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED)) - json_object_boolean_true_add(json_path, "bestpath"); + if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)) + json_object_boolean_true_add(json_path, "bestpath"); - if (CHECK_FLAG (binfo->flags, BGP_INFO_MULTIPATH)) - json_object_boolean_true_add(json_path, "multipath"); + if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH)) + json_object_boolean_true_add(json_path, "multipath"); - /* Internal route. */ - if ((binfo->peer->as) && (binfo->peer->as == binfo->peer->local_as)) - json_object_string_add(json_path, "pathFrom", "internal"); - else - json_object_string_add(json_path, "pathFrom", "external"); + /* Internal route. */ + if ((binfo->peer->as) + && (binfo->peer->as == binfo->peer->local_as)) + json_object_string_add(json_path, "pathFrom", + "internal"); + else + json_object_string_add(json_path, "pathFrom", + "external"); - return; - } + return; + } - /* Route status display. */ - if (CHECK_FLAG (binfo->flags, BGP_INFO_REMOVED)) - vty_out (vty, "R"); - else if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE)) - vty_out (vty, "S"); - else if (binfo->extra && binfo->extra->suppress) - vty_out (vty, "s"); - else if (CHECK_FLAG (binfo->flags, BGP_INFO_VALID) && - ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) - vty_out (vty, "*"); - else - vty_out (vty, " "); - - /* Selected */ - if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) - vty_out (vty, "h"); - else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)) - vty_out (vty, "d"); - else if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED)) - vty_out (vty, ">"); - else if (CHECK_FLAG (binfo->flags, BGP_INFO_MULTIPATH)) - vty_out (vty, "="); - else - vty_out (vty, " "); + /* Route status display. */ + if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED)) + vty_out(vty, "R"); + else if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE)) + vty_out(vty, "S"); + else if (binfo->extra && binfo->extra->suppress) + vty_out(vty, "s"); + else if (CHECK_FLAG(binfo->flags, BGP_INFO_VALID) + && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) + vty_out(vty, "*"); + else + vty_out(vty, " "); + + /* Selected */ + if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) + vty_out(vty, "h"); + else if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)) + vty_out(vty, "d"); + else if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)) + vty_out(vty, ">"); + else if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH)) + vty_out(vty, "="); + else + vty_out(vty, " "); - /* Internal route. */ - if (binfo->peer && - (binfo->peer->as) && (binfo->peer->as == binfo->peer->local_as)) - vty_out (vty, "i"); - else - vty_out (vty, " "); + /* Internal route. */ + if (binfo->peer && (binfo->peer->as) + && (binfo->peer->as == binfo->peer->local_as)) + vty_out(vty, "i"); + else + vty_out(vty, " "); } /* called from terminal list command */ -void -route_vty_out (struct vty *vty, struct prefix *p, - struct bgp_info *binfo, int display, safi_t safi, - json_object *json_paths) -{ - struct attr *attr; - json_object *json_path = NULL; - json_object *json_nexthops = NULL; - json_object *json_nexthop_global = NULL; - json_object *json_nexthop_ll = NULL; +void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo, + int display, safi_t safi, json_object *json_paths) +{ + struct attr *attr; + json_object *json_path = NULL; + json_object *json_nexthops = NULL; + json_object *json_nexthop_global = NULL; + json_object *json_nexthop_ll = NULL; + + if (json_paths) + json_path = json_object_new_object(); + + /* short status lead text */ + route_vty_short_status_out(vty, binfo, json_path); + + if (!json_paths) { + /* print prefix and mask */ + if (!display) + route_vty_out_route(p, vty); + else + vty_out(vty, "%*s", 17, " "); + } - if (json_paths) - json_path = json_object_new_object(); + /* Print attribute */ + attr = binfo->attr; + if (attr) { + /* + * For ENCAP and EVPN routes, nexthop address family is not + * neccessarily the same as the prefix address family. + * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field + * EVPN routes are also exchanged with a MP nexthop. Currently, + * this + * is only IPv4, the value will be present in either + * attr->nexthop or + * attr->mp_nexthop_global_in + */ + if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) { + char buf[BUFSIZ]; + int af = NEXTHOP_FAMILY(attr->mp_nexthop_len); + + switch (af) { + case AF_INET: + vty_out(vty, "%s", + inet_ntop(af, + &attr->mp_nexthop_global_in, + buf, BUFSIZ)); + break; + case AF_INET6: + vty_out(vty, "%s", + inet_ntop(af, &attr->mp_nexthop_global, + buf, BUFSIZ)); + break; + default: + vty_out(vty, "?"); + break; + } + } else if (safi == SAFI_EVPN) { + if (json_paths) { + json_nexthop_global = json_object_new_object(); + + json_object_string_add( + json_nexthop_global, "ip", + inet_ntoa(attr->nexthop)); + json_object_string_add(json_nexthop_global, + "afi", "ipv4"); + json_object_boolean_true_add( + json_nexthop_global, "used"); + } else + vty_out(vty, "%-16s", inet_ntoa(attr->nexthop)); + } + /* IPv4 Next Hop */ + else if (p->family == AF_INET + && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) { + if (json_paths) { + json_nexthop_global = json_object_new_object(); + + if ((safi == SAFI_MPLS_VPN) + || (safi == SAFI_EVPN)) + json_object_string_add( + json_nexthop_global, "ip", + inet_ntoa( + attr->mp_nexthop_global_in)); + else + json_object_string_add( + json_nexthop_global, "ip", + inet_ntoa(attr->nexthop)); + + json_object_string_add(json_nexthop_global, + "afi", "ipv4"); + json_object_boolean_true_add( + json_nexthop_global, "used"); + } else { + if ((safi == SAFI_MPLS_VPN) + || (safi == SAFI_EVPN)) + vty_out(vty, "%-16s", + inet_ntoa( + attr->mp_nexthop_global_in)); + else + vty_out(vty, "%-16s", + inet_ntoa(attr->nexthop)); + } + } - /* short status lead text */ - route_vty_short_status_out (vty, binfo, json_path); + /* IPv6 Next Hop */ + else if (p->family == AF_INET6 + || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) { + int len; + char buf[BUFSIZ]; + + if (json_paths) { + json_nexthop_global = json_object_new_object(); + json_object_string_add( + json_nexthop_global, "ip", + inet_ntop(AF_INET6, + &attr->mp_nexthop_global, buf, + BUFSIZ)); + json_object_string_add(json_nexthop_global, + "afi", "ipv6"); + json_object_string_add(json_nexthop_global, + "scope", "global"); + + /* We display both LL & GL if both have been + * received */ + if ((attr->mp_nexthop_len == 32) + || (binfo->peer->conf_if)) { + json_nexthop_ll = + json_object_new_object(); + json_object_string_add( + json_nexthop_ll, "ip", + inet_ntop( + AF_INET6, + &attr->mp_nexthop_local, + buf, BUFSIZ)); + json_object_string_add(json_nexthop_ll, + "afi", "ipv6"); + json_object_string_add(json_nexthop_ll, + "scope", + "link-local"); + + if ((IPV6_ADDR_CMP( + &attr->mp_nexthop_global, + &attr->mp_nexthop_local) + != 0) + && !attr->mp_nexthop_prefer_global) + json_object_boolean_true_add( + json_nexthop_ll, + "used"); + else + json_object_boolean_true_add( + json_nexthop_global, + "used"); + } else + json_object_boolean_true_add( + json_nexthop_global, "used"); + } else { + /* Display LL if LL/Global both in table unless + * prefer-global is set */ + if (((attr->mp_nexthop_len == 32) + && !attr->mp_nexthop_prefer_global) + || (binfo->peer->conf_if)) { + if (binfo->peer->conf_if) { + len = vty_out( + vty, "%s", + binfo->peer->conf_if); + len = + 7 - len; /* len of IPv6 + addr + max + len of def + ifname */ + + if (len < 1) + vty_out(vty, "\n%*s", + 45, " "); + else + vty_out(vty, "%*s", len, + " "); + } else { + len = vty_out( + vty, "%s", + inet_ntop( + AF_INET6, + &attr->mp_nexthop_local, + buf, BUFSIZ)); + len = 16 - len; + + if (len < 1) + vty_out(vty, "\n%*s", + 36, " "); + else + vty_out(vty, "%*s", len, + " "); + } + } else { + len = vty_out( + vty, "%s", + inet_ntop( + AF_INET6, + &attr->mp_nexthop_global, + buf, BUFSIZ)); + len = 16 - len; + + if (len < 1) + vty_out(vty, "\n%*s", 36, " "); + else + vty_out(vty, "%*s", len, " "); + } + } + } - if (!json_paths) - { - /* print prefix and mask */ - if (! display) - route_vty_out_route (p, vty); - else - vty_out (vty, "%*s", 17, " "); - } + /* MED/Metric */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) + if (json_paths) + json_object_int_add(json_path, "med", + attr->med); + else + vty_out(vty, "%10u", attr->med); + else if (!json_paths) + vty_out(vty, " "); + + /* Local Pref */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) + if (json_paths) + json_object_int_add(json_path, "localpref", + attr->local_pref); + else + vty_out(vty, "%7u", attr->local_pref); + else if (!json_paths) + vty_out(vty, " "); + + if (json_paths) + json_object_int_add(json_path, "weight", attr->weight); + else + vty_out(vty, "%7u ", attr->weight); + + if (json_paths) { + char buf[BUFSIZ]; + json_object_string_add(json_path, "peerId", + sockunion2str(&binfo->peer->su, + buf, + SU_ADDRSTRLEN)); + } - /* Print attribute */ - attr = binfo->attr; - if (attr) - { - /* - * For ENCAP and EVPN routes, nexthop address family is not - * neccessarily the same as the prefix address family. - * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field - * EVPN routes are also exchanged with a MP nexthop. Currently, this - * is only IPv4, the value will be present in either attr->nexthop or - * attr->mp_nexthop_global_in - */ - if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) - { - char buf[BUFSIZ]; - int af = NEXTHOP_FAMILY(attr->mp_nexthop_len); - - switch (af) - { - case AF_INET: - vty_out (vty, "%s", inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ)); - break; - case AF_INET6: - vty_out (vty, "%s", inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ)); - break; - default: - vty_out(vty, "?"); - break; - } - } - else if (safi == SAFI_EVPN) - { - if (json_paths) - { - json_nexthop_global = json_object_new_object(); - - json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->nexthop)); - json_object_string_add(json_nexthop_global, "afi", "ipv4"); - json_object_boolean_true_add(json_nexthop_global, "used"); - } - else - vty_out (vty, "%-16s", inet_ntoa (attr->nexthop)); - } - /* IPv4 Next Hop */ - else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) - { - if (json_paths) - { - json_nexthop_global = json_object_new_object(); - - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN)) - json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->mp_nexthop_global_in)); - else - json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->nexthop)); - - json_object_string_add(json_nexthop_global, "afi", "ipv4"); - json_object_boolean_true_add(json_nexthop_global, "used"); - } - else - { - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN)) - vty_out (vty, "%-16s", - inet_ntoa (attr->mp_nexthop_global_in)); - else - vty_out (vty, "%-16s", inet_ntoa (attr->nexthop)); - } - } - - /* IPv6 Next Hop */ - else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) - { - int len; - char buf[BUFSIZ]; - - if (json_paths) - { - json_nexthop_global = json_object_new_object(); - json_object_string_add(json_nexthop_global, "ip", - inet_ntop (AF_INET6, - &attr->mp_nexthop_global, - buf, BUFSIZ)); - json_object_string_add(json_nexthop_global, "afi", "ipv6"); - json_object_string_add(json_nexthop_global, "scope", "global"); - - /* We display both LL & GL if both have been received */ - if ((attr->mp_nexthop_len == 32) || (binfo->peer->conf_if)) - { - json_nexthop_ll = json_object_new_object(); - json_object_string_add(json_nexthop_ll, "ip", - inet_ntop (AF_INET6, - &attr->mp_nexthop_local, - buf, BUFSIZ)); - json_object_string_add(json_nexthop_ll, "afi", "ipv6"); - json_object_string_add(json_nexthop_ll, "scope", "link-local"); - - if ((IPV6_ADDR_CMP (&attr->mp_nexthop_global, - &attr->mp_nexthop_local) != 0) && - !attr->mp_nexthop_prefer_global) - json_object_boolean_true_add(json_nexthop_ll, "used"); - else - json_object_boolean_true_add(json_nexthop_global, "used"); - } - else - json_object_boolean_true_add(json_nexthop_global, "used"); - } - else - { - /* Display LL if LL/Global both in table unless prefer-global is set */ - if (((attr->mp_nexthop_len == 32) && - !attr->mp_nexthop_prefer_global) || - (binfo->peer->conf_if)) - { - if (binfo->peer->conf_if) - { - len = vty_out (vty, "%s", - binfo->peer->conf_if); - len = 7 - len; /* len of IPv6 addr + max len of def ifname */ - - if (len < 1) - vty_out (vty, "\n%*s", 45, " "); - else - vty_out (vty, "%*s", len, " "); - } - else - { - len = vty_out (vty, "%s", - inet_ntop (AF_INET6, - &attr->mp_nexthop_local, - buf, BUFSIZ)); - len = 16 - len; - - if (len < 1) - vty_out (vty, "\n%*s", 36, " "); - else - vty_out (vty, "%*s", len, " "); - } - } - else - { - len = vty_out (vty, "%s", - inet_ntop (AF_INET6, - &attr->mp_nexthop_global, - buf, BUFSIZ)); - len = 16 - len; - - if (len < 1) - vty_out (vty, "\n%*s", 36, " "); - else - vty_out (vty, "%*s", len, " "); - } - } - } - - /* MED/Metric */ - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) - if (json_paths) - json_object_int_add(json_path, "med", attr->med); - else - vty_out (vty, "%10u", attr->med); - else - if (!json_paths) - vty_out (vty, " "); - - /* Local Pref */ - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) - if (json_paths) - json_object_int_add(json_path, "localpref", attr->local_pref); - else - vty_out (vty, "%7u", attr->local_pref); - else - if (!json_paths) - vty_out (vty, " "); - - if (json_paths) - json_object_int_add(json_path, "weight", attr->weight); - else - vty_out (vty, "%7u ", attr->weight); - - if (json_paths) { - char buf[BUFSIZ]; - json_object_string_add(json_path, "peerId", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN)); - } - - /* Print aspath */ - if (attr->aspath) - { - if (json_paths) - json_object_string_add(json_path, "aspath", attr->aspath->str); - else - aspath_print_vty (vty, "%s", attr->aspath, " "); - } - - /* Print origin */ - if (json_paths) - json_object_string_add(json_path, "origin", bgp_origin_long_str[attr->origin]); - else - vty_out (vty, "%s", bgp_origin_str[attr->origin]); - } - else - { - if (json_paths) - json_object_string_add(json_path, "alert", "No attributes"); - else - vty_out (vty, "No attributes to print\n"); - } + /* Print aspath */ + if (attr->aspath) { + if (json_paths) + json_object_string_add(json_path, "aspath", + attr->aspath->str); + else + aspath_print_vty(vty, "%s", attr->aspath, " "); + } - if (json_paths) - { - if (json_nexthop_global || json_nexthop_ll) - { - json_nexthops = json_object_new_array(); + /* Print origin */ + if (json_paths) + json_object_string_add( + json_path, "origin", + bgp_origin_long_str[attr->origin]); + else + vty_out(vty, "%s", bgp_origin_str[attr->origin]); + } else { + if (json_paths) + json_object_string_add(json_path, "alert", + "No attributes"); + else + vty_out(vty, "No attributes to print\n"); + } - if (json_nexthop_global) - json_object_array_add(json_nexthops, json_nexthop_global); + if (json_paths) { + if (json_nexthop_global || json_nexthop_ll) { + json_nexthops = json_object_new_array(); - if (json_nexthop_ll) - json_object_array_add(json_nexthops, json_nexthop_ll); + if (json_nexthop_global) + json_object_array_add(json_nexthops, + json_nexthop_global); - json_object_object_add(json_path, "nexthops", json_nexthops); - } + if (json_nexthop_ll) + json_object_array_add(json_nexthops, + json_nexthop_ll); - json_object_array_add(json_paths, json_path); - } - else - { - vty_out (vty, "\n"); + json_object_object_add(json_path, "nexthops", + json_nexthops); + } + + json_object_array_add(json_paths, json_path); + } else { + vty_out(vty, "\n"); #if ENABLE_BGP_VNC - /* prints an additional line, indented, with VNC info, if present */ - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) - rfapi_vty_out_vncinfo(vty, p, binfo, safi); + /* prints an additional line, indented, with VNC info, if + * present */ + if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) + rfapi_vty_out_vncinfo(vty, p, binfo, safi); #endif - } -} + } +} /* called from terminal list command */ -void -route_vty_out_tmp (struct vty *vty, struct prefix *p, struct attr *attr, safi_t safi, - u_char use_json, json_object *json_ar) -{ - json_object *json_status = NULL; - json_object *json_net = NULL; - char buff[BUFSIZ]; - /* Route status display. */ - if (use_json) - { - json_status = json_object_new_object(); - json_net = json_object_new_object(); - } - else - { - vty_out (vty, "*"); - vty_out (vty, ">"); - vty_out (vty, " "); - } +void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr, + safi_t safi, u_char use_json, json_object *json_ar) +{ + json_object *json_status = NULL; + json_object *json_net = NULL; + char buff[BUFSIZ]; + /* Route status display. */ + if (use_json) { + json_status = json_object_new_object(); + json_net = json_object_new_object(); + } else { + vty_out(vty, "*"); + vty_out(vty, ">"); + vty_out(vty, " "); + } - /* print prefix and mask */ - if (use_json) - json_object_string_add(json_net, "addrPrefix", inet_ntop (p->family, &p->u.prefix, buff, BUFSIZ)); - else - route_vty_out_route (p, vty); + /* print prefix and mask */ + if (use_json) + json_object_string_add( + json_net, "addrPrefix", + inet_ntop(p->family, &p->u.prefix, buff, BUFSIZ)); + else + route_vty_out_route(p, vty); + + /* Print attribute */ + if (attr) { + if (use_json) { + if (p->family == AF_INET + && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP + || safi == SAFI_EVPN + || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) { + if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP + || safi == SAFI_EVPN) + json_object_string_add( + json_net, "nextHop", + inet_ntoa( + attr->mp_nexthop_global_in)); + else + json_object_string_add( + json_net, "nextHop", + inet_ntoa(attr->nexthop)); + } else if (p->family == AF_INET6 + || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) { + char buf[BUFSIZ]; + + json_object_string_add( + json_net, "netHopGloabal", + inet_ntop(AF_INET6, + &attr->mp_nexthop_global, buf, + BUFSIZ)); + } + + if (attr->flag + & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) + json_object_int_add(json_net, "metric", + attr->med); + + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) + json_object_int_add(json_net, "localPref", + attr->local_pref); + + json_object_int_add(json_net, "weight", attr->weight); + + /* Print aspath */ + if (attr->aspath) + json_object_string_add(json_net, "asPath", + attr->aspath->str); + + /* Print origin */ + json_object_string_add(json_net, "bgpOriginCode", + bgp_origin_str[attr->origin]); + } else { + if (p->family == AF_INET + && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP + || safi == SAFI_EVPN + || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) { + if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP + || safi == SAFI_EVPN) + vty_out(vty, "%-16s", + inet_ntoa( + attr->mp_nexthop_global_in)); + else + vty_out(vty, "%-16s", + inet_ntoa(attr->nexthop)); + } else if (p->family == AF_INET6 + || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) { + int len; + char buf[BUFSIZ]; + + len = vty_out( + vty, "%s", + inet_ntop(AF_INET6, + &attr->mp_nexthop_global, buf, + BUFSIZ)); + len = 16 - len; + if (len < 1) + vty_out(vty, "\n%*s", 36, " "); + else + vty_out(vty, "%*s", len, " "); + } + if (attr->flag + & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) + vty_out(vty, "%10u", attr->med); + else + vty_out(vty, " "); - /* Print attribute */ - if (attr) - { - if (use_json) - { - if (p->family == AF_INET && - (safi == SAFI_MPLS_VPN || - safi == SAFI_ENCAP || - safi == SAFI_EVPN || - !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) - { - if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) - json_object_string_add(json_net, "nextHop", inet_ntoa (attr->mp_nexthop_global_in)); - else - json_object_string_add(json_net, "nextHop", inet_ntoa (attr->nexthop)); - } - else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) - { - char buf[BUFSIZ]; - - json_object_string_add(json_net, "netHopGloabal", inet_ntop (AF_INET6, &attr->mp_nexthop_global, - buf, BUFSIZ)); - } - - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) - json_object_int_add(json_net, "metric", attr->med); - - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) - json_object_int_add(json_net, "localPref", attr->local_pref); - - json_object_int_add(json_net, "weight", attr->weight); - - /* Print aspath */ - if (attr->aspath) - json_object_string_add(json_net, "asPath", attr->aspath->str); - - /* Print origin */ - json_object_string_add(json_net, "bgpOriginCode", bgp_origin_str[attr->origin]); - } - else - { - if (p->family == AF_INET && - (safi == SAFI_MPLS_VPN || - safi == SAFI_ENCAP || - safi == SAFI_EVPN || - !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) - { - if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) - vty_out (vty, "%-16s", - inet_ntoa (attr->mp_nexthop_global_in)); - else - vty_out (vty, "%-16s", inet_ntoa (attr->nexthop)); - } - else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) - { - int len; - char buf[BUFSIZ]; - - len = vty_out (vty, "%s", - inet_ntop (AF_INET6, &attr->mp_nexthop_global, - buf, BUFSIZ)); - len = 16 - len; - if (len < 1) - vty_out (vty, "\n%*s", 36, " "); - else - vty_out (vty, "%*s", len, " "); - } - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) - vty_out (vty, "%10u", attr->med); - else - vty_out (vty, " "); - - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) - vty_out (vty, "%7u", attr->local_pref); - else - vty_out (vty, " "); - - vty_out (vty, "%7u ", attr->weight); - - /* Print aspath */ - if (attr->aspath) - aspath_print_vty (vty, "%s", attr->aspath, " "); - - /* Print origin */ - vty_out (vty, "%s", bgp_origin_str[attr->origin]); - } - } - if (use_json) - { - json_object_boolean_true_add(json_status, "*"); - json_object_boolean_true_add(json_status, ">"); - json_object_object_add(json_net, "appliedStatusSymbols", json_status); - char buf_cut[BUFSIZ]; - json_object_object_add(json_ar, inet_ntop (p->family, &p->u.prefix, buf_cut, BUFSIZ), json_net); - } - else - vty_out (vty, "\n"); -} + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) + vty_out(vty, "%7u", attr->local_pref); + else + vty_out(vty, " "); + + vty_out(vty, "%7u ", attr->weight); + + /* Print aspath */ + if (attr->aspath) + aspath_print_vty(vty, "%s", attr->aspath, " "); + + /* Print origin */ + vty_out(vty, "%s", bgp_origin_str[attr->origin]); + } + } + if (use_json) { + json_object_boolean_true_add(json_status, "*"); + json_object_boolean_true_add(json_status, ">"); + json_object_object_add(json_net, "appliedStatusSymbols", + json_status); + char buf_cut[BUFSIZ]; + json_object_object_add( + json_ar, + inet_ntop(p->family, &p->u.prefix, buf_cut, BUFSIZ), + json_net); + } else + vty_out(vty, "\n"); +} + +void route_vty_out_tag(struct vty *vty, struct prefix *p, + struct bgp_info *binfo, int display, safi_t safi, + json_object *json) +{ + json_object *json_out = NULL; + struct attr *attr; + mpls_label_t label = MPLS_INVALID_LABEL; + + if (!binfo->extra) + return; + + if (json) + json_out = json_object_new_object(); + + /* short status lead text */ + route_vty_short_status_out(vty, binfo, json_out); + + /* print prefix and mask */ + if (json == NULL) { + if (!display) + route_vty_out_route(p, vty); + else + vty_out(vty, "%*s", 17, " "); + } + + /* Print attribute */ + attr = binfo->attr; + if (attr) { + if (((p->family == AF_INET) + && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) + || (safi == SAFI_EVPN && p->family == AF_ETHERNET + && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) + || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) { + if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP + || safi == SAFI_EVPN) { + if (json) + json_object_string_add( + json_out, "mpNexthopGlobalIn", + inet_ntoa( + attr->mp_nexthop_global_in)); + else + vty_out(vty, "%-16s", + inet_ntoa( + attr->mp_nexthop_global_in)); + } else { + if (json) + json_object_string_add( + json_out, "nexthop", + inet_ntoa(attr->nexthop)); + else + vty_out(vty, "%-16s", + inet_ntoa(attr->nexthop)); + } + } else if (((p->family == AF_INET6) + && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) + || (safi == SAFI_EVPN && p->family == AF_ETHERNET + && BGP_ATTR_NEXTHOP_AFI_IP6(attr)) + || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) { + char buf_a[BUFSIZ]; + char buf_b[BUFSIZ]; + char buf_c[BUFSIZ]; + if (attr->mp_nexthop_len + == BGP_ATTR_NHLEN_IPV6_GLOBAL) { + if (json) + json_object_string_add( + json_out, "mpNexthopGlobalIn", + inet_ntop( + AF_INET6, + &attr->mp_nexthop_global, + buf_a, BUFSIZ)); + else + vty_out(vty, "%s", + inet_ntop( + AF_INET6, + &attr->mp_nexthop_global, + buf_a, BUFSIZ)); + } else if (attr->mp_nexthop_len + == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) { + if (json) { + inet_ntop(AF_INET6, + &attr->mp_nexthop_global, + buf_a, BUFSIZ); + inet_ntop(AF_INET6, + &attr->mp_nexthop_local, + buf_b, BUFSIZ); + sprintf(buf_c, "%s(%s)", buf_a, buf_b); + json_object_string_add( + json_out, + "mpNexthopGlobalLocal", buf_c); + } else + vty_out(vty, "%s(%s)", + inet_ntop( + AF_INET6, + &attr->mp_nexthop_global, + buf_a, BUFSIZ), + inet_ntop( + AF_INET6, + &attr->mp_nexthop_local, + buf_b, BUFSIZ)); + } + } + } + + label = decode_label(&binfo->extra->label); + + if (bgp_is_valid_label(&label)) { + if (json) { + json_object_int_add(json_out, "notag", label); + json_object_array_add(json, json_out); + } else { + vty_out(vty, "notag/%d", label); + vty_out(vty, "\n"); + } + } +} -void -route_vty_out_tag (struct vty *vty, struct prefix *p, - struct bgp_info *binfo, int display, safi_t safi, json_object *json) +void route_vty_out_overlay(struct vty *vty, struct prefix *p, + struct bgp_info *binfo, int display, + json_object *json_paths) { - json_object *json_out = NULL; - struct attr *attr; - mpls_label_t label = MPLS_INVALID_LABEL; + struct attr *attr; + char buf[BUFSIZ]; + json_object *json_path = NULL; - if (!binfo->extra) - return; + if (json_paths) + json_path = json_object_new_object(); - if (json) - json_out = json_object_new_object(); - - /* short status lead text */ - route_vty_short_status_out (vty, binfo, json_out); - - /* print prefix and mask */ - if (json == NULL) - { - if (! display) - route_vty_out_route (p, vty); - else - vty_out (vty, "%*s", 17, " "); - } + if (!binfo->extra) + return; - /* Print attribute */ - attr = binfo->attr; - if (attr) - { - if (((p->family == AF_INET) && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) - || (safi == SAFI_EVPN && p->family == AF_ETHERNET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) - || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) - { - if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) - { - if (json) - json_object_string_add(json_out, "mpNexthopGlobalIn", inet_ntoa (attr->mp_nexthop_global_in)); - else - vty_out (vty, "%-16s", inet_ntoa (attr->mp_nexthop_global_in)); - } - else - { - if (json) - json_object_string_add(json_out, "nexthop", inet_ntoa (attr->nexthop)); - else - vty_out (vty, "%-16s", inet_ntoa (attr->nexthop)); - } - } - else if (((p->family == AF_INET6) && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) - || (safi == SAFI_EVPN && p->family == AF_ETHERNET && BGP_ATTR_NEXTHOP_AFI_IP6(attr)) - || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) - { - char buf_a[BUFSIZ]; - char buf_b[BUFSIZ]; - char buf_c[BUFSIZ]; - if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) - { - if (json) - json_object_string_add(json_out, "mpNexthopGlobalIn", - inet_ntop (AF_INET6, &attr->mp_nexthop_global, buf_a, BUFSIZ)); - else - vty_out (vty, "%s", - inet_ntop (AF_INET6, &attr->mp_nexthop_global, - buf_a, BUFSIZ)); - } - else if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) - { - if (json) - { - inet_ntop (AF_INET6, &attr->mp_nexthop_global, - buf_a, BUFSIZ); - inet_ntop (AF_INET6, &attr->mp_nexthop_local, - buf_b, BUFSIZ); - sprintf(buf_c, "%s(%s)", buf_a, buf_b); - json_object_string_add(json_out, "mpNexthopGlobalLocal", buf_c); - } - else - vty_out (vty, "%s(%s)", - inet_ntop (AF_INET6, &attr->mp_nexthop_global, - buf_a, BUFSIZ), - inet_ntop (AF_INET6, &attr->mp_nexthop_local, - buf_b, BUFSIZ)); - } + /* short status lead text */ + route_vty_short_status_out(vty, binfo, json_path); + /* print prefix and mask */ + if (!display) + route_vty_out_route(p, vty); + else + vty_out(vty, "%*s", 17, " "); + + /* Print attribute */ + attr = binfo->attr; + if (attr) { + char buf1[BUFSIZ]; + int af = NEXTHOP_FAMILY(attr->mp_nexthop_len); + + switch (af) { + case AF_INET: + vty_out(vty, "%-16s", + inet_ntop(af, &attr->mp_nexthop_global_in, buf, + BUFSIZ)); + break; + case AF_INET6: + vty_out(vty, "%s(%s)", + inet_ntop(af, &attr->mp_nexthop_global, buf, + BUFSIZ), + inet_ntop(af, &attr->mp_nexthop_local, buf1, + BUFSIZ)); + break; + default: + vty_out(vty, "?"); + } } - } - label = decode_label (&binfo->extra->label); + struct eth_segment_id *id = &(attr->evpn_overlay.eth_s_id); + char *str = esi2str(id); + vty_out(vty, "%s", str); + XFREE(MTYPE_TMP, str); + if (IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p)) { + vty_out(vty, "/%s", inet_ntoa(attr->evpn_overlay.gw_ip.ipv4)); + } else if (IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn *)p)) { + vty_out(vty, "/%s", + inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6), + buf, BUFSIZ)); + } + if (attr->ecommunity) { + char *mac = NULL; + struct ecommunity_val *routermac = ecommunity_lookup( + attr->ecommunity, ECOMMUNITY_ENCODE_EVPN, + ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC); + if (routermac) + mac = ecom_mac2str((char *)routermac->val); + if (mac) { + vty_out(vty, "/%s", (char *)mac); + XFREE(MTYPE_TMP, mac); + } + } + vty_out(vty, "\n"); +} - if (bgp_is_valid_label(&label)) - { - if (json) - { - json_object_int_add(json_out, "notag", label); - json_object_array_add(json, json_out); - } - else - { - vty_out (vty, "notag/%d", label); - vty_out (vty, "\n"); - } - } -} +/* dampening route */ +static void damp_route_vty_out(struct vty *vty, struct prefix *p, + struct bgp_info *binfo, int display, safi_t safi, + u_char use_json, json_object *json) +{ + struct attr *attr; + int len; + char timebuf[BGP_UPTIME_LEN]; + + /* short status lead text */ + route_vty_short_status_out(vty, binfo, json); + + /* print prefix and mask */ + if (!use_json) { + if (!display) + route_vty_out_route(p, vty); + else + vty_out(vty, "%*s", 17, " "); + } + + len = vty_out(vty, "%s", binfo->peer->host); + len = 17 - len; + if (len < 1) { + if (!use_json) + vty_out(vty, "\n%*s", 34, " "); + } else { + if (use_json) + json_object_int_add(json, "peerHost", len); + else + vty_out(vty, "%*s", len, " "); + } + + if (use_json) + bgp_damp_reuse_time_vty(vty, binfo, timebuf, BGP_UPTIME_LEN, + use_json, json); + else + vty_out(vty, "%s ", bgp_damp_reuse_time_vty(vty, binfo, timebuf, + BGP_UPTIME_LEN, + use_json, json)); + + /* Print attribute */ + attr = binfo->attr; + if (attr) { + /* Print aspath */ + if (attr->aspath) { + if (use_json) + json_object_string_add(json, "asPath", + attr->aspath->str); + else + aspath_print_vty(vty, "%s", attr->aspath, " "); + } + + /* Print origin */ + if (use_json) + json_object_string_add(json, "origin", + bgp_origin_str[attr->origin]); + else + vty_out(vty, "%s", bgp_origin_str[attr->origin]); + } + if (!use_json) + vty_out(vty, "\n"); +} -void -route_vty_out_overlay (struct vty *vty, struct prefix *p, - struct bgp_info *binfo, int display, json_object *json_paths) +/* flap route */ +static void flap_route_vty_out(struct vty *vty, struct prefix *p, + struct bgp_info *binfo, int display, safi_t safi, + u_char use_json, json_object *json) { - struct attr *attr; - char buf[BUFSIZ]; - json_object *json_path = NULL; + struct attr *attr; + struct bgp_damp_info *bdi; + char timebuf[BGP_UPTIME_LEN]; + int len; - if (json_paths) - json_path = json_object_new_object(); + if (!binfo->extra) + return; - if (!binfo->extra) - return; + bdi = binfo->extra->damp_info; - /* short status lead text */ - route_vty_short_status_out (vty, binfo, json_path); + /* short status lead text */ + route_vty_short_status_out(vty, binfo, json); - /* print prefix and mask */ - if (! display) - route_vty_out_route (p, vty); - else - vty_out (vty, "%*s", 17, " "); + /* print prefix and mask */ + if (!use_json) { + if (!display) + route_vty_out_route(p, vty); + else + vty_out(vty, "%*s", 17, " "); + } - /* Print attribute */ - attr = binfo->attr; - if (attr) - { - char buf1[BUFSIZ]; - int af = NEXTHOP_FAMILY(attr->mp_nexthop_len); - - switch (af) { - case AF_INET: - vty_out (vty, "%-16s", inet_ntop(af, - &attr->mp_nexthop_global_in, buf, BUFSIZ)); - break; - case AF_INET6: - vty_out (vty, "%s(%s)", - inet_ntop (af, - &attr->mp_nexthop_global, buf, BUFSIZ), - inet_ntop (af, - &attr->mp_nexthop_local, buf1, BUFSIZ)); - break; - default: - vty_out(vty, "?"); - } - } + len = vty_out(vty, "%s", binfo->peer->host); + len = 16 - len; + if (len < 1) { + if (!use_json) + vty_out(vty, "\n%*s", 33, " "); + } else { + if (use_json) + json_object_int_add(json, "peerHost", len); + else + vty_out(vty, "%*s", len, " "); + } - struct eth_segment_id *id = &(attr->evpn_overlay.eth_s_id); - char *str = esi2str(id); - vty_out (vty, "%s", str); - XFREE (MTYPE_TMP, str); - if (IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p)) - { - vty_out (vty, "/%s", inet_ntoa (attr->evpn_overlay.gw_ip.ipv4)); - } - else if (IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn *)p)) - { - vty_out (vty, "/%s", - inet_ntop (AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6), - buf, BUFSIZ)); - } - if(attr->ecommunity) - { - char *mac = NULL; - struct ecommunity_val *routermac = ecommunity_lookup (attr->ecommunity, - ECOMMUNITY_ENCODE_EVPN, - ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC); - if(routermac) - mac = ecom_mac2str((char *)routermac->val); - if(mac) - { - vty_out (vty, "/%s",(char *)mac); - XFREE(MTYPE_TMP, mac); - } - } - vty_out (vty, "\n"); + len = vty_out(vty, "%d", bdi->flap); + len = 5 - len; + if (len < 1) { + if (!use_json) + vty_out(vty, " "); + } else { + if (use_json) + json_object_int_add(json, "bdiFlap", len); + else + vty_out(vty, "%*s", len, " "); + } + + if (use_json) + peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json, + json); + else + vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf, + BGP_UPTIME_LEN, 0, NULL)); + + if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED) + && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) { + if (use_json) + bgp_damp_reuse_time_vty(vty, binfo, timebuf, + BGP_UPTIME_LEN, use_json, json); + else + vty_out(vty, "%s ", + bgp_damp_reuse_time_vty(vty, binfo, timebuf, + BGP_UPTIME_LEN, + use_json, json)); + } else { + if (!use_json) + vty_out(vty, "%*s ", 8, " "); + } + + /* Print attribute */ + attr = binfo->attr; + if (attr) { + /* Print aspath */ + if (attr->aspath) { + if (use_json) + json_object_string_add(json, "asPath", + attr->aspath->str); + else + aspath_print_vty(vty, "%s", attr->aspath, " "); + } + + /* Print origin */ + if (use_json) + json_object_string_add(json, "origin", + bgp_origin_str[attr->origin]); + else + vty_out(vty, "%s", bgp_origin_str[attr->origin]); + } + if (!use_json) + vty_out(vty, "\n"); +} + +static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer, + int *first, const char *header, + json_object *json_adv_to) +{ + char buf1[INET6_ADDRSTRLEN]; + json_object *json_peer = NULL; + + if (json_adv_to) { + /* 'advertised-to' is a dictionary of peers we have advertised + * this + * prefix too. The key is the peer's IP or swpX, the value is + * the + * hostname if we know it and "" if not. + */ + json_peer = json_object_new_object(); + + if (peer->hostname) + json_object_string_add(json_peer, "hostname", + peer->hostname); + + if (peer->conf_if) + json_object_object_add(json_adv_to, peer->conf_if, + json_peer); + else + json_object_object_add( + json_adv_to, + sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN), + json_peer); + } else { + if (*first) { + vty_out(vty, "%s", header); + *first = 0; + } + + if (peer->hostname + && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) { + if (peer->conf_if) + vty_out(vty, " %s(%s)", peer->hostname, + peer->conf_if); + else + vty_out(vty, " %s(%s)", peer->hostname, + sockunion2str(&peer->su, buf1, + SU_ADDRSTRLEN)); + } else { + if (peer->conf_if) + vty_out(vty, " %s", peer->conf_if); + else + vty_out(vty, " %s", + sockunion2str(&peer->su, buf1, + SU_ADDRSTRLEN)); + } + } } -/* dampening route */ -static void -damp_route_vty_out (struct vty *vty, struct prefix *p, struct bgp_info *binfo, - int display, safi_t safi, u_char use_json, json_object *json) -{ - struct attr *attr; - int len; - char timebuf[BGP_UPTIME_LEN]; +void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, + struct bgp_info *binfo, afi_t afi, safi_t safi, + json_object *json_paths) +{ + char buf[INET6_ADDRSTRLEN]; + char buf1[BUFSIZ]; +#if defined(HAVE_CUMULUS) + char buf2[EVPN_ROUTE_STRLEN]; +#endif + struct attr *attr; + int sockunion_vty_out(struct vty *, union sockunion *); + time_t tbuf; + json_object *json_bestpath = NULL; + json_object *json_cluster_list = NULL; + json_object *json_cluster_list_list = NULL; + json_object *json_ext_community = NULL; + json_object *json_last_update = NULL; + json_object *json_nexthop_global = NULL; + json_object *json_nexthop_ll = NULL; + json_object *json_nexthops = NULL; + json_object *json_path = NULL; + json_object *json_peer = NULL; + json_object *json_string = NULL; + json_object *json_adv_to = NULL; + int first = 0; + struct listnode *node, *nnode; + struct peer *peer; + int addpath_capable; + int has_adj; + unsigned int first_as; + + if (json_paths) { + json_path = json_object_new_object(); + json_peer = json_object_new_object(); + json_nexthop_global = json_object_new_object(); + } + +#if defined(HAVE_CUMULUS) + if (!json_paths && safi == SAFI_EVPN) { + char tag_buf[20]; + + bgp_evpn_route2str((struct prefix_evpn *)p, buf2, sizeof(buf2)); + vty_out(vty, " Route %s", buf2); + tag_buf[0] = '\0'; + if (binfo->extra) { + bgp_evpn_label2str(&binfo->extra->label, tag_buf, + sizeof(tag_buf)); + vty_out(vty, " VNI %s", tag_buf); + } + vty_out(vty, "\n"); + if (binfo->extra && binfo->extra->parent) { + struct bgp_info *parent_ri; + struct bgp_node *rn, *prn; + + parent_ri = (struct bgp_info *)binfo->extra->parent; + rn = parent_ri->net; + if (rn && rn->prn) { + prn = rn->prn; + vty_out(vty, " Imported from %s:%s\n", + prefix_rd2str( + (struct prefix_rd *)&prn->p, + buf1, RD_ADDRSTRLEN), + buf2); + } + } + } +#endif + + attr = binfo->attr; + + if (attr) { + /* Line1 display AS-path, Aggregator */ + if (attr->aspath) { + if (json_paths) { + json_object_lock(attr->aspath->json); + json_object_object_add(json_path, "aspath", + attr->aspath->json); + } else { + if (attr->aspath->segments) + aspath_print_vty(vty, " %s", + attr->aspath, ""); + else + vty_out(vty, " Local"); + } + } + + if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED)) { + if (json_paths) + json_object_boolean_true_add(json_path, + "removed"); + else + vty_out(vty, ", (removed)"); + } + + if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE)) { + if (json_paths) + json_object_boolean_true_add(json_path, + "stale"); + else + vty_out(vty, ", (stale)"); + } + + if (CHECK_FLAG(attr->flag, + ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) { + if (json_paths) { + json_object_int_add(json_path, "aggregatorAs", + attr->aggregator_as); + json_object_string_add( + json_path, "aggregatorId", + inet_ntoa(attr->aggregator_addr)); + } else { + vty_out(vty, ", (aggregated by %u %s)", + attr->aggregator_as, + inet_ntoa(attr->aggregator_addr)); + } + } + + if (CHECK_FLAG(binfo->peer->af_flags[afi][safi], + PEER_FLAG_REFLECTOR_CLIENT)) { + if (json_paths) + json_object_boolean_true_add( + json_path, "rxedFromRrClient"); + else + vty_out(vty, ", (Received from a RR-client)"); + } + + if (CHECK_FLAG(binfo->peer->af_flags[afi][safi], + PEER_FLAG_RSERVER_CLIENT)) { + if (json_paths) + json_object_boolean_true_add( + json_path, "rxedFromRsClient"); + else + vty_out(vty, ", (Received from a RS-client)"); + } + + if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) { + if (json_paths) + json_object_boolean_true_add( + json_path, "dampeningHistoryEntry"); + else + vty_out(vty, ", (history entry)"); + } else if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)) { + if (json_paths) + json_object_boolean_true_add( + json_path, "dampeningSuppressed"); + else + vty_out(vty, ", (suppressed due to dampening)"); + } + + if (!json_paths) + vty_out(vty, "\n"); + + /* Line2 display Next-hop, Neighbor, Router-id */ + /* Display the nexthop */ + if ((p->family == AF_INET || p->family == AF_ETHERNET) + && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP + || safi == SAFI_EVPN + || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) { + if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP + || safi == SAFI_EVPN) { + if (json_paths) + json_object_string_add( + json_nexthop_global, "ip", + inet_ntoa( + attr->mp_nexthop_global_in)); + else + vty_out(vty, " %s", + inet_ntoa( + attr->mp_nexthop_global_in)); + } else { + if (json_paths) + json_object_string_add( + json_nexthop_global, "ip", + inet_ntoa(attr->nexthop)); + else + vty_out(vty, " %s", + inet_ntoa(attr->nexthop)); + } + + if (json_paths) + json_object_string_add(json_nexthop_global, + "afi", "ipv4"); + } else { + if (json_paths) { + json_object_string_add( + json_nexthop_global, "ip", + inet_ntop(AF_INET6, + &attr->mp_nexthop_global, buf, + INET6_ADDRSTRLEN)); + json_object_string_add(json_nexthop_global, + "afi", "ipv6"); + json_object_string_add(json_nexthop_global, + "scope", "global"); + } else { + vty_out(vty, " %s", + inet_ntop(AF_INET6, + &attr->mp_nexthop_global, buf, + INET6_ADDRSTRLEN)); + } + } + + /* Display the IGP cost or 'inaccessible' */ + if (!CHECK_FLAG(binfo->flags, BGP_INFO_VALID)) { + if (json_paths) + json_object_boolean_false_add( + json_nexthop_global, "accessible"); + else + vty_out(vty, " (inaccessible)"); + } else { + if (binfo->extra && binfo->extra->igpmetric) { + if (json_paths) + json_object_int_add( + json_nexthop_global, "metric", + binfo->extra->igpmetric); + else + vty_out(vty, " (metric %u)", + binfo->extra->igpmetric); + } + + /* IGP cost is 0, display this only for json */ + else { + if (json_paths) + json_object_int_add(json_nexthop_global, + "metric", 0); + } + + if (json_paths) + json_object_boolean_true_add( + json_nexthop_global, "accessible"); + } + + /* Display peer "from" output */ + /* This path was originated locally */ + if (binfo->peer == bgp->peer_self) { + + if (safi == SAFI_EVPN + || (p->family == AF_INET + && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) { + if (json_paths) + json_object_string_add( + json_peer, "peerId", "0.0.0.0"); + else + vty_out(vty, " from 0.0.0.0 "); + } else { + if (json_paths) + json_object_string_add(json_peer, + "peerId", "::"); + else + vty_out(vty, " from :: "); + } + + if (json_paths) + json_object_string_add( + json_peer, "routerId", + inet_ntoa(bgp->router_id)); + else + vty_out(vty, "(%s)", inet_ntoa(bgp->router_id)); + } + + /* We RXed this path from one of our peers */ + else { + + if (json_paths) { + json_object_string_add( + json_peer, "peerId", + sockunion2str(&binfo->peer->su, buf, + SU_ADDRSTRLEN)); + json_object_string_add( + json_peer, "routerId", + inet_ntop(AF_INET, + &binfo->peer->remote_id, buf1, + BUFSIZ)); + + if (binfo->peer->hostname) + json_object_string_add( + json_peer, "hostname", + binfo->peer->hostname); + + if (binfo->peer->domainname) + json_object_string_add( + json_peer, "domainname", + binfo->peer->domainname); + + if (binfo->peer->conf_if) + json_object_string_add( + json_peer, "interface", + binfo->peer->conf_if); + } else { + if (binfo->peer->conf_if) { + if (binfo->peer->hostname + && bgp_flag_check( + binfo->peer->bgp, + BGP_FLAG_SHOW_HOSTNAME)) + vty_out(vty, " from %s(%s)", + binfo->peer->hostname, + binfo->peer->conf_if); + else + vty_out(vty, " from %s", + binfo->peer->conf_if); + } else { + if (binfo->peer->hostname + && bgp_flag_check( + binfo->peer->bgp, + BGP_FLAG_SHOW_HOSTNAME)) + vty_out(vty, " from %s(%s)", + binfo->peer->hostname, + binfo->peer->host); + else + vty_out(vty, " from %s", + sockunion2str( + &binfo->peer + ->su, + buf, + SU_ADDRSTRLEN)); + } + + if (attr->flag + & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) + vty_out(vty, " (%s)", + inet_ntoa(attr->originator_id)); + else + vty_out(vty, " (%s)", + inet_ntop( + AF_INET, + &binfo->peer->remote_id, + buf1, BUFSIZ)); + } + } + + if (!json_paths) + vty_out(vty, "\n"); + + /* display the link-local nexthop */ + if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) { + if (json_paths) { + json_nexthop_ll = json_object_new_object(); + json_object_string_add( + json_nexthop_ll, "ip", + inet_ntop(AF_INET6, + &attr->mp_nexthop_local, buf, + INET6_ADDRSTRLEN)); + json_object_string_add(json_nexthop_ll, "afi", + "ipv6"); + json_object_string_add(json_nexthop_ll, "scope", + "link-local"); + + json_object_boolean_true_add(json_nexthop_ll, + "accessible"); + + if (!attr->mp_nexthop_prefer_global) + json_object_boolean_true_add( + json_nexthop_ll, "used"); + else + json_object_boolean_true_add( + json_nexthop_global, "used"); + } else { + vty_out(vty, " (%s) %s\n", + inet_ntop(AF_INET6, + &attr->mp_nexthop_local, buf, + INET6_ADDRSTRLEN), + attr->mp_nexthop_prefer_global + ? "(prefer-global)" + : "(used)"); + } + } + /* If we do not have a link-local nexthop then we must flag the + global as "used" */ + else { + if (json_paths) + json_object_boolean_true_add( + json_nexthop_global, "used"); + } - /* short status lead text */ - route_vty_short_status_out (vty, binfo, json); - - /* print prefix and mask */ - if (!use_json) - { - if (! display) - route_vty_out_route (p, vty); - else - vty_out (vty, "%*s", 17, " "); - } + /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid, + * Int/Ext/Local, Atomic, best */ + if (json_paths) + json_object_string_add( + json_path, "origin", + bgp_origin_long_str[attr->origin]); + else + vty_out(vty, " Origin %s", + bgp_origin_long_str[attr->origin]); + + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) { + if (json_paths) + json_object_int_add(json_path, "med", + attr->med); + else + vty_out(vty, ", metric %u", attr->med); + } - len = vty_out (vty, "%s", binfo->peer->host); - len = 17 - len; - if (len < 1) - { - if (!use_json) - vty_out (vty, "\n%*s", 34, " "); - } - else - { - if (use_json) - json_object_int_add(json, "peerHost", len); - else - vty_out (vty, "%*s", len, " "); - } + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) { + if (json_paths) + json_object_int_add(json_path, "localpref", + attr->local_pref); + else + vty_out(vty, ", localpref %u", + attr->local_pref); + } else { + if (json_paths) + json_object_int_add(json_path, "localpref", + bgp->default_local_pref); + else + vty_out(vty, ", localpref %u", + bgp->default_local_pref); + } - if (use_json) - bgp_damp_reuse_time_vty (vty, binfo, timebuf, BGP_UPTIME_LEN, use_json, json); - else - vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo, timebuf, BGP_UPTIME_LEN, use_json, json)); + if (attr->weight != 0) { + if (json_paths) + json_object_int_add(json_path, "weight", + attr->weight); + else + vty_out(vty, ", weight %u", attr->weight); + } - /* Print attribute */ - attr = binfo->attr; - if (attr) - { - /* Print aspath */ - if (attr->aspath) - { - if (use_json) - json_object_string_add(json, "asPath", attr->aspath->str); - else - aspath_print_vty (vty, "%s", attr->aspath, " "); - } - - /* Print origin */ - if (use_json) - json_object_string_add(json, "origin", bgp_origin_str[attr->origin]); - else - vty_out (vty, "%s", bgp_origin_str[attr->origin]); - } - if (!use_json) - vty_out (vty, "\n"); -} + if (attr->tag != 0) { + if (json_paths) + json_object_int_add(json_path, "tag", + attr->tag); + else + vty_out(vty, ", tag %" ROUTE_TAG_PRI, + attr->tag); + } -/* flap route */ -static void -flap_route_vty_out (struct vty *vty, struct prefix *p, struct bgp_info *binfo, - int display, safi_t safi, u_char use_json, json_object *json) -{ - struct attr *attr; - struct bgp_damp_info *bdi; - char timebuf[BGP_UPTIME_LEN]; - int len; - - if (!binfo->extra) - return; - - bdi = binfo->extra->damp_info; + if (!CHECK_FLAG(binfo->flags, BGP_INFO_VALID)) { + if (json_paths) + json_object_boolean_false_add(json_path, + "valid"); + else + vty_out(vty, ", invalid"); + } else if (!CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) { + if (json_paths) + json_object_boolean_true_add(json_path, + "valid"); + else + vty_out(vty, ", valid"); + } - /* short status lead text */ - route_vty_short_status_out (vty, binfo, json); - - /* print prefix and mask */ - if (!use_json) - { - if (! display) - route_vty_out_route (p, vty); - else - vty_out (vty, "%*s", 17, " "); - } + if (binfo->peer != bgp->peer_self) { + if (binfo->peer->as == binfo->peer->local_as) { + if (CHECK_FLAG(bgp->config, + BGP_CONFIG_CONFEDERATION)) { + if (json_paths) + json_object_string_add( + json_peer, "type", + "confed-internal"); + else + vty_out(vty, + ", confed-internal"); + } else { + if (json_paths) + json_object_string_add( + json_peer, "type", + "internal"); + else + vty_out(vty, ", internal"); + } + } else { + if (bgp_confederation_peers_check( + bgp, binfo->peer->as)) { + if (json_paths) + json_object_string_add( + json_peer, "type", + "confed-external"); + else + vty_out(vty, + ", confed-external"); + } else { + if (json_paths) + json_object_string_add( + json_peer, "type", + "external"); + else + vty_out(vty, ", external"); + } + } + } else if (binfo->sub_type == BGP_ROUTE_AGGREGATE) { + if (json_paths) { + json_object_boolean_true_add(json_path, + "aggregated"); + json_object_boolean_true_add(json_path, + "local"); + } else { + vty_out(vty, ", aggregated, local"); + } + } else if (binfo->type != ZEBRA_ROUTE_BGP) { + if (json_paths) + json_object_boolean_true_add(json_path, + "sourced"); + else + vty_out(vty, ", sourced"); + } else { + if (json_paths) { + json_object_boolean_true_add(json_path, + "sourced"); + json_object_boolean_true_add(json_path, + "local"); + } else { + vty_out(vty, ", sourced, local"); + } + } - len = vty_out (vty, "%s", binfo->peer->host); - len = 16 - len; - if (len < 1) - { - if (!use_json) - vty_out (vty, "\n%*s", 33, " "); - } - else - { - if (use_json) - json_object_int_add(json, "peerHost", len); - else - vty_out (vty, "%*s", len, " "); - } + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) { + if (json_paths) + json_object_boolean_true_add(json_path, + "atomicAggregate"); + else + vty_out(vty, ", atomic-aggregate"); + } - len = vty_out (vty, "%d", bdi->flap); - len = 5 - len; - if (len < 1) - { - if (!use_json) - vty_out (vty, " "); - } - else - { - if (use_json) - json_object_int_add(json, "bdiFlap", len); - else - vty_out (vty, "%*s", len, " "); - } + if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH) + || (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED) + && bgp_info_mpath_count(binfo))) { + if (json_paths) + json_object_boolean_true_add(json_path, + "multipath"); + else + vty_out(vty, ", multipath"); + } - if (use_json) - peer_uptime (bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json, json); - else - vty_out (vty, "%s ", peer_uptime (bdi->start_time, - timebuf, BGP_UPTIME_LEN, 0, NULL)); + // Mark the bestpath(s) + if (CHECK_FLAG(binfo->flags, BGP_INFO_DMED_SELECTED)) { + first_as = aspath_get_first_as(attr->aspath); + + if (json_paths) { + if (!json_bestpath) + json_bestpath = + json_object_new_object(); + json_object_int_add(json_bestpath, + "bestpathFromAs", first_as); + } else { + if (first_as) + vty_out(vty, ", bestpath-from-AS %d", + first_as); + else + vty_out(vty, + ", bestpath-from-AS Local"); + } + } - if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED) - && ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) - { - if (use_json) - bgp_damp_reuse_time_vty (vty, binfo, timebuf, BGP_UPTIME_LEN, use_json, json); - else - vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo, timebuf, BGP_UPTIME_LEN, use_json, json)); - } - else - { - if (!use_json) - vty_out (vty, "%*s ", 8, " "); - } + if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)) { + if (json_paths) { + if (!json_bestpath) + json_bestpath = + json_object_new_object(); + json_object_boolean_true_add(json_bestpath, + "overall"); + } else + vty_out(vty, ", best"); + } - /* Print attribute */ - attr = binfo->attr; - if (attr) - { - /* Print aspath */ - if (attr->aspath) - { - if (use_json) - json_object_string_add(json, "asPath", attr->aspath->str); - else - aspath_print_vty (vty, "%s", attr->aspath, " "); - } - - /* Print origin */ - if (use_json) - json_object_string_add(json, "origin", bgp_origin_str[attr->origin]); - else - vty_out (vty, "%s", bgp_origin_str[attr->origin]); - } - if (!use_json) - vty_out (vty, "\n"); -} + if (json_bestpath) + json_object_object_add(json_path, "bestpath", + json_bestpath); + + if (!json_paths) + vty_out(vty, "\n"); + + /* Line 4 display Community */ + if (attr->community) { + if (json_paths) { + json_object_lock(attr->community->json); + json_object_object_add(json_path, "community", + attr->community->json); + } else { + vty_out(vty, " Community: %s\n", + attr->community->str); + } + } -static void -route_vty_out_advertised_to (struct vty *vty, struct peer *peer, int *first, - const char *header, json_object *json_adv_to) -{ - char buf1[INET6_ADDRSTRLEN]; - json_object *json_peer = NULL; + /* Line 5 display Extended-community */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) { + if (json_paths) { + json_ext_community = json_object_new_object(); + json_object_string_add(json_ext_community, + "string", + attr->ecommunity->str); + json_object_object_add(json_path, + "extendedCommunity", + json_ext_community); + } else { + vty_out(vty, " Extended Community: %s\n", + attr->ecommunity->str); + } + } - if (json_adv_to) - { - /* 'advertised-to' is a dictionary of peers we have advertised this - * prefix too. The key is the peer's IP or swpX, the value is the - * hostname if we know it and "" if not. - */ - json_peer = json_object_new_object(); - - if (peer->hostname) - json_object_string_add(json_peer, "hostname", peer->hostname); - - if (peer->conf_if) - json_object_object_add(json_adv_to, peer->conf_if, json_peer); - else - json_object_object_add(json_adv_to, - sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN), - json_peer); - } - else - { - if (*first) - { - vty_out (vty, "%s", header); - *first = 0; - } - - if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) - { - if (peer->conf_if) - vty_out (vty, " %s(%s)", peer->hostname, peer->conf_if); - else - vty_out (vty, " %s(%s)", peer->hostname, - sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN)); - } - else - { - if (peer->conf_if) - vty_out (vty, " %s", peer->conf_if); - else - vty_out (vty, " %s", sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN)); - } - } -} + /* Line 6 display Large community */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) + vty_out(vty, " Large Community: %s\n", + attr->lcommunity->str); + + /* Line 7 display Originator, Cluster-id */ + if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) + || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) { + if (attr->flag + & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) { + if (json_paths) + json_object_string_add( + json_path, "originatorId", + inet_ntoa(attr->originator_id)); + else + vty_out(vty, " Originator: %s", + inet_ntoa(attr->originator_id)); + } + + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) { + int i; + + if (json_paths) { + json_cluster_list = + json_object_new_object(); + json_cluster_list_list = + json_object_new_array(); + + for (i = 0; + i < attr->cluster->length / 4; + i++) { + json_string = json_object_new_string( + inet_ntoa( + attr->cluster->list + [i])); + json_object_array_add( + json_cluster_list_list, + json_string); + } + + /* struct cluster_list does not have + "str" variable like + * aspath and community do. Add this + someday if someone + * asks for it. + json_object_string_add(json_cluster_list, + "string", attr->cluster->str); + */ + json_object_object_add( + json_cluster_list, "list", + json_cluster_list_list); + json_object_object_add( + json_path, "clusterList", + json_cluster_list); + } else { + vty_out(vty, ", Cluster list: "); + + for (i = 0; + i < attr->cluster->length / 4; + i++) { + vty_out(vty, "%s ", + inet_ntoa( + attr->cluster->list + [i])); + } + } + } + + if (!json_paths) + vty_out(vty, "\n"); + } -void -route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, - struct bgp_info *binfo, afi_t afi, safi_t safi, - json_object *json_paths) -{ - char buf[INET6_ADDRSTRLEN]; - char buf1[BUFSIZ]; + if (binfo->extra && binfo->extra->damp_info) + bgp_damp_info_vty(vty, binfo, json_path); + +/* Remote Label */ #if defined(HAVE_CUMULUS) - char buf2[EVPN_ROUTE_STRLEN]; + if (binfo->extra && bgp_is_valid_label(&binfo->extra->label) + && safi != SAFI_EVPN) +#else + if (binfo->extra && bgp_is_valid_label(&binfo->extra->label)) #endif - struct attr *attr; - int sockunion_vty_out (struct vty *, union sockunion *); - time_t tbuf; - json_object *json_bestpath = NULL; - json_object *json_cluster_list = NULL; - json_object *json_cluster_list_list = NULL; - json_object *json_ext_community = NULL; - json_object *json_last_update = NULL; - json_object *json_nexthop_global = NULL; - json_object *json_nexthop_ll = NULL; - json_object *json_nexthops = NULL; - json_object *json_path = NULL; - json_object *json_peer = NULL; - json_object *json_string = NULL; - json_object *json_adv_to = NULL; - int first = 0; - struct listnode *node, *nnode; - struct peer *peer; - int addpath_capable; - int has_adj; - unsigned int first_as; - - if (json_paths) - { - json_path = json_object_new_object(); - json_peer = json_object_new_object(); - json_nexthop_global = json_object_new_object(); - } + { + mpls_label_t label = label_pton(&binfo->extra->label); + if (json_paths) + json_object_int_add(json_path, "remoteLabel", + label); + else + vty_out(vty, " Remote label: %d\n", label); + } -#if defined (HAVE_CUMULUS) - if (!json_paths && safi == SAFI_EVPN) - { - char tag_buf[20]; - - bgp_evpn_route2str ((struct prefix_evpn *)p, buf2, sizeof (buf2)); - vty_out (vty, " Route %s", buf2); - tag_buf[0] = '\0'; - if (binfo->extra) - { - bgp_evpn_label2str (&binfo->extra->label, tag_buf, sizeof (tag_buf)); - vty_out (vty, " VNI %s", tag_buf); - } - vty_out (vty, "\n"); - if (binfo->extra && binfo->extra->parent) - { - struct bgp_info *parent_ri; - struct bgp_node *rn, *prn; - - parent_ri = (struct bgp_info *)binfo->extra->parent; - rn = parent_ri->net; - if (rn && rn->prn) - { - prn = rn->prn; - vty_out (vty, " Imported from %s:%s\n", - prefix_rd2str ((struct prefix_rd *)&prn->p, - buf1, RD_ADDRSTRLEN), - buf2); - } - } - } -#endif + /* Label Index */ + if (attr->label_index != BGP_INVALID_LABEL_INDEX) { + if (json_paths) + json_object_int_add(json_path, "labelIndex", + attr->label_index); + else + vty_out(vty, " Label Index: %d\n", + attr->label_index); + } - attr = binfo->attr; + /* Line 8 display Addpath IDs */ + if (binfo->addpath_rx_id || binfo->addpath_tx_id) { + if (json_paths) { + json_object_int_add(json_path, "addpathRxId", + binfo->addpath_rx_id); + json_object_int_add(json_path, "addpathTxId", + binfo->addpath_tx_id); + } else { + vty_out(vty, " AddPath ID: RX %u, TX %u\n", + binfo->addpath_rx_id, + binfo->addpath_tx_id); + } + } - if (attr) - { - /* Line1 display AS-path, Aggregator */ - if (attr->aspath) - { - if (json_paths) - { - json_object_lock(attr->aspath->json); - json_object_object_add(json_path, "aspath", attr->aspath->json); - } - else - { - if (attr->aspath->segments) - aspath_print_vty (vty, " %s", attr->aspath, ""); - else - vty_out (vty, " Local"); - } - } - - if (CHECK_FLAG (binfo->flags, BGP_INFO_REMOVED)) - { - if (json_paths) - json_object_boolean_true_add(json_path, "removed"); - else - vty_out (vty, ", (removed)"); - } - - if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE)) - { - if (json_paths) - json_object_boolean_true_add(json_path, "stale"); - else - vty_out (vty, ", (stale)"); - } - - if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))) - { - if (json_paths) - { - json_object_int_add(json_path, "aggregatorAs", attr->aggregator_as); - json_object_string_add(json_path, "aggregatorId", inet_ntoa (attr->aggregator_addr)); - } - else - { - vty_out (vty, ", (aggregated by %u %s)", - attr->aggregator_as, - inet_ntoa (attr->aggregator_addr)); - } - } - - if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) - { - if (json_paths) - json_object_boolean_true_add(json_path, "rxedFromRrClient"); - else - vty_out (vty, ", (Received from a RR-client)"); - } - - if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)) - { - if (json_paths) - json_object_boolean_true_add(json_path, "rxedFromRsClient"); - else - vty_out (vty, ", (Received from a RS-client)"); - } - - if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) - { - if (json_paths) - json_object_boolean_true_add(json_path, "dampeningHistoryEntry"); - else - vty_out (vty, ", (history entry)"); - } - else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)) - { - if (json_paths) - json_object_boolean_true_add(json_path, "dampeningSuppressed"); - else - vty_out (vty, ", (suppressed due to dampening)"); - } - - if (!json_paths) - vty_out (vty, "\n"); - - /* Line2 display Next-hop, Neighbor, Router-id */ - /* Display the nexthop */ - if ((p->family == AF_INET || - p->family == AF_ETHERNET) && - (safi == SAFI_MPLS_VPN || - safi == SAFI_ENCAP || - safi == SAFI_EVPN || - !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) - { - if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) - { - if (json_paths) - json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->mp_nexthop_global_in)); - else - vty_out (vty, " %s", inet_ntoa (attr->mp_nexthop_global_in)); - } - else - { - if (json_paths) - json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->nexthop)); - else - vty_out (vty, " %s", inet_ntoa (attr->nexthop)); - } - - if (json_paths) - json_object_string_add(json_nexthop_global, "afi", "ipv4"); - } - else - { - if (json_paths) - { - json_object_string_add(json_nexthop_global, "ip", - inet_ntop (AF_INET6, &attr->mp_nexthop_global, - buf, INET6_ADDRSTRLEN)); - json_object_string_add(json_nexthop_global, "afi", "ipv6"); - json_object_string_add(json_nexthop_global, "scope", "global"); - } - else - { - vty_out (vty, " %s", - inet_ntop (AF_INET6, &attr->mp_nexthop_global, - buf, INET6_ADDRSTRLEN)); - } - } - - /* Display the IGP cost or 'inaccessible' */ - if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID)) - { - if (json_paths) - json_object_boolean_false_add(json_nexthop_global, "accessible"); - else - vty_out (vty, " (inaccessible)"); - } - else - { - if (binfo->extra && binfo->extra->igpmetric) - { - if (json_paths) - json_object_int_add(json_nexthop_global, "metric", binfo->extra->igpmetric); - else - vty_out (vty, " (metric %u)", binfo->extra->igpmetric); - } - - /* IGP cost is 0, display this only for json */ - else - { - if (json_paths) - json_object_int_add(json_nexthop_global, "metric", 0); - } - - if (json_paths) - json_object_boolean_true_add(json_nexthop_global, "accessible"); - } - - /* Display peer "from" output */ - /* This path was originated locally */ - if (binfo->peer == bgp->peer_self) - { - - if (safi == SAFI_EVPN || - (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) - { - if (json_paths) - json_object_string_add(json_peer, "peerId", "0.0.0.0"); - else - vty_out (vty, " from 0.0.0.0 "); - } - else - { - if (json_paths) - json_object_string_add(json_peer, "peerId", "::"); - else - vty_out (vty, " from :: "); - } - - if (json_paths) - json_object_string_add(json_peer, "routerId", inet_ntoa(bgp->router_id)); - else - vty_out (vty, "(%s)", inet_ntoa(bgp->router_id)); - } - - /* We RXed this path from one of our peers */ - else - { - - if (json_paths) - { - json_object_string_add(json_peer, "peerId", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN)); - json_object_string_add(json_peer, "routerId", inet_ntop (AF_INET, &binfo->peer->remote_id, buf1, BUFSIZ)); - - if (binfo->peer->hostname) - json_object_string_add(json_peer, "hostname", binfo->peer->hostname); - - if (binfo->peer->domainname) - json_object_string_add(json_peer, "domainname", binfo->peer->domainname); - - if (binfo->peer->conf_if) - json_object_string_add(json_peer, "interface", binfo->peer->conf_if); - } - else - { - if (binfo->peer->conf_if) - { - if (binfo->peer->hostname && - bgp_flag_check(binfo->peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) - vty_out (vty, " from %s(%s)", binfo->peer->hostname, - binfo->peer->conf_if); - else - vty_out (vty, " from %s", binfo->peer->conf_if); - } - else - { - if (binfo->peer->hostname && - bgp_flag_check(binfo->peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) - vty_out (vty, " from %s(%s)", binfo->peer->hostname, - binfo->peer->host); - else - vty_out (vty, " from %s", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN)); - } - - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) - vty_out (vty, " (%s)", inet_ntoa (attr->originator_id)); - else - vty_out (vty, " (%s)", inet_ntop (AF_INET, &binfo->peer->remote_id, buf1, BUFSIZ)); - } - } - - if (!json_paths) - vty_out (vty, "\n"); - - /* display the link-local nexthop */ - if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) - { - if (json_paths) - { - json_nexthop_ll = json_object_new_object(); - json_object_string_add(json_nexthop_ll, "ip", - inet_ntop (AF_INET6, &attr->mp_nexthop_local, - buf, INET6_ADDRSTRLEN)); - json_object_string_add(json_nexthop_ll, "afi", "ipv6"); - json_object_string_add(json_nexthop_ll, "scope", "link-local"); - - json_object_boolean_true_add(json_nexthop_ll, "accessible"); - - if (!attr->mp_nexthop_prefer_global) - json_object_boolean_true_add(json_nexthop_ll, "used"); - else - json_object_boolean_true_add(json_nexthop_global, "used"); - } - else - { - vty_out (vty, " (%s) %s\n", - inet_ntop (AF_INET6, &attr->mp_nexthop_local, - buf, INET6_ADDRSTRLEN), - attr->mp_nexthop_prefer_global ? "(prefer-global)" : "(used)"); - } - } - /* If we do not have a link-local nexthop then we must flag the global as "used" */ - else - { - if (json_paths) - json_object_boolean_true_add(json_nexthop_global, "used"); - } - - /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid, Int/Ext/Local, Atomic, best */ - if (json_paths) - json_object_string_add(json_path, "origin", bgp_origin_long_str[attr->origin]); - else - vty_out (vty, " Origin %s", bgp_origin_long_str[attr->origin]); - - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) - { - if (json_paths) - json_object_int_add(json_path, "med", attr->med); - else - vty_out (vty, ", metric %u", attr->med); - } - - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) - { - if (json_paths) - json_object_int_add(json_path, "localpref", attr->local_pref); - else - vty_out (vty, ", localpref %u", attr->local_pref); - } - else - { - if (json_paths) - json_object_int_add(json_path, "localpref", bgp->default_local_pref); - else - vty_out (vty, ", localpref %u", bgp->default_local_pref); - } - - if (attr->weight != 0) - { - if (json_paths) - json_object_int_add(json_path, "weight", attr->weight); - else - vty_out (vty, ", weight %u", attr->weight); - } - - if (attr->tag != 0) - { - if (json_paths) - json_object_int_add(json_path, "tag", attr->tag); - else - vty_out (vty, ", tag %"ROUTE_TAG_PRI, attr->tag); - } - - if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID)) - { - if (json_paths) - json_object_boolean_false_add(json_path, "valid"); - else - vty_out (vty, ", invalid"); - } - else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) - { - if (json_paths) - json_object_boolean_true_add(json_path, "valid"); - else - vty_out (vty, ", valid"); - } - - if (binfo->peer != bgp->peer_self) - { - if (binfo->peer->as == binfo->peer->local_as) - { - if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) - { - if (json_paths) - json_object_string_add(json_peer, "type", "confed-internal"); - else - vty_out (vty, ", confed-internal"); - } - else - { - if (json_paths) - json_object_string_add(json_peer, "type", "internal"); - else - vty_out (vty, ", internal"); - } - } - else - { - if (bgp_confederation_peers_check(bgp, binfo->peer->as)) - { - if (json_paths) - json_object_string_add(json_peer, "type", "confed-external"); - else - vty_out (vty, ", confed-external"); - } - else - { - if (json_paths) - json_object_string_add(json_peer, "type", "external"); - else - vty_out (vty, ", external"); - } - } - } - else if (binfo->sub_type == BGP_ROUTE_AGGREGATE) - { - if (json_paths) - { - json_object_boolean_true_add(json_path, "aggregated"); - json_object_boolean_true_add(json_path, "local"); - } - else - { - vty_out (vty, ", aggregated, local"); - } - } - else if (binfo->type != ZEBRA_ROUTE_BGP) - { - if (json_paths) - json_object_boolean_true_add(json_path, "sourced"); - else - vty_out (vty, ", sourced"); - } - else - { - if (json_paths) - { - json_object_boolean_true_add(json_path, "sourced"); - json_object_boolean_true_add(json_path, "local"); - } - else - { - vty_out (vty, ", sourced, local"); - } - } - - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) - { - if (json_paths) - json_object_boolean_true_add(json_path, "atomicAggregate"); - else - vty_out (vty, ", atomic-aggregate"); - } - - if (CHECK_FLAG (binfo->flags, BGP_INFO_MULTIPATH) || - (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED) && - bgp_info_mpath_count (binfo))) - { - if (json_paths) - json_object_boolean_true_add(json_path, "multipath"); - else - vty_out (vty, ", multipath"); - } - - // Mark the bestpath(s) - if (CHECK_FLAG (binfo->flags, BGP_INFO_DMED_SELECTED)) - { - first_as = aspath_get_first_as(attr->aspath); - - if (json_paths) - { - if (!json_bestpath) - json_bestpath = json_object_new_object(); - json_object_int_add(json_bestpath, "bestpathFromAs", first_as); - } - else - { - if (first_as) - vty_out (vty, ", bestpath-from-AS %d", first_as); - else - vty_out (vty, ", bestpath-from-AS Local"); - } - } - - if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED)) - { - if (json_paths) - { - if (!json_bestpath) - json_bestpath = json_object_new_object(); - json_object_boolean_true_add(json_bestpath, "overall"); - } - else - vty_out (vty, ", best"); - } - - if (json_bestpath) - json_object_object_add(json_path, "bestpath", json_bestpath); - - if (!json_paths) - vty_out (vty, "\n"); - - /* Line 4 display Community */ - if (attr->community) - { - if (json_paths) - { - json_object_lock(attr->community->json); - json_object_object_add(json_path, "community", attr->community->json); - } - else - { - vty_out (vty, " Community: %s\n",attr->community->str); - } - } - - /* Line 5 display Extended-community */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) - { - if (json_paths) - { - json_ext_community = json_object_new_object(); - json_object_string_add(json_ext_community, "string", attr->ecommunity->str); - json_object_object_add(json_path, "extendedCommunity", json_ext_community); - } - else - { - vty_out (vty, " Extended Community: %s\n", - attr->ecommunity->str); - } - } - - /* Line 6 display Large community */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) - vty_out (vty, " Large Community: %s\n", - attr->lcommunity->str); - - /* Line 7 display Originator, Cluster-id */ - if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) || - (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) - { - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) - { - if (json_paths) - json_object_string_add(json_path, "originatorId", inet_ntoa (attr->originator_id)); - else - vty_out (vty, " Originator: %s", - inet_ntoa (attr->originator_id)); - } - - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) - { - int i; - - if (json_paths) - { - json_cluster_list = json_object_new_object(); - json_cluster_list_list = json_object_new_array(); - - for (i = 0; i < attr->cluster->length / 4; i++) - { - json_string = json_object_new_string(inet_ntoa (attr->cluster->list[i])); - json_object_array_add(json_cluster_list_list, json_string); - } - - /* struct cluster_list does not have "str" variable like - * aspath and community do. Add this someday if someone - * asks for it. - json_object_string_add(json_cluster_list, "string", attr->cluster->str); - */ - json_object_object_add(json_cluster_list, "list", json_cluster_list_list); - json_object_object_add(json_path, "clusterList", json_cluster_list); - } - else - { - vty_out (vty, ", Cluster list: "); - - for (i = 0; i < attr->cluster->length / 4; i++) - { - vty_out (vty, "%s ", - inet_ntoa (attr->cluster->list[i])); - } - } - } - - if (!json_paths) - vty_out (vty, "\n"); - } - - if (binfo->extra && binfo->extra->damp_info) - bgp_damp_info_vty (vty, binfo, json_path); - - /* Remote Label */ -#if defined (HAVE_CUMULUS) - if (binfo->extra && bgp_is_valid_label(&binfo->extra->label) && safi != SAFI_EVPN) -#else - if (binfo->extra && bgp_is_valid_label(&binfo->extra->label)) -#endif - { - mpls_label_t label = label_pton(&binfo->extra->label); - if (json_paths) - json_object_int_add(json_path, "remoteLabel", label); - else - vty_out (vty, " Remote label: %d\n", label); - } - - /* Label Index */ - if (attr->label_index != BGP_INVALID_LABEL_INDEX) - { - if (json_paths) - json_object_int_add(json_path, "labelIndex", attr->label_index); - else - vty_out (vty, " Label Index: %d\n", - attr->label_index); - } - - /* Line 8 display Addpath IDs */ - if (binfo->addpath_rx_id || binfo->addpath_tx_id) - { - if (json_paths) - { - json_object_int_add(json_path, "addpathRxId", binfo->addpath_rx_id); - json_object_int_add(json_path, "addpathTxId", binfo->addpath_tx_id); - } - else - { - vty_out (vty, " AddPath ID: RX %u, TX %u\n", - binfo->addpath_rx_id,binfo->addpath_tx_id); - } - } - - /* If we used addpath to TX a non-bestpath we need to display - * "Advertised to" on a path-by-path basis */ - if (bgp->addpath_tx_used[afi][safi]) - { - first = 1; - - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - addpath_capable = bgp_addpath_encode_tx (peer, afi, safi); - has_adj = bgp_adj_out_lookup (peer, binfo->net, binfo->addpath_tx_id); - - if ((addpath_capable && has_adj) || - (!addpath_capable && has_adj && CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))) - { - if (json_path && !json_adv_to) - json_adv_to = json_object_new_object(); - - route_vty_out_advertised_to(vty, peer, &first, - " Advertised to:", - json_adv_to); - } - } - - if (json_path) - { - if (json_adv_to) - { - json_object_object_add(json_path, "advertisedTo", json_adv_to); - } - } - else - { - if (!first) - { - vty_out (vty, "\n"); - } - } - } - - /* Line 9 display Uptime */ - tbuf = time(NULL) - (bgp_clock() - binfo->uptime); - if (json_paths) - { - json_last_update = json_object_new_object(); - json_object_int_add(json_last_update, "epoch", tbuf); - json_object_string_add(json_last_update, "string", ctime(&tbuf)); - json_object_object_add(json_path, "lastUpdate", json_last_update); - } - else - vty_out (vty, " Last update: %s", ctime(&tbuf)); - } + /* If we used addpath to TX a non-bestpath we need to display + * "Advertised to" on a path-by-path basis */ + if (bgp->addpath_tx_used[afi][safi]) { + first = 1; + + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + addpath_capable = + bgp_addpath_encode_tx(peer, afi, safi); + has_adj = bgp_adj_out_lookup( + peer, binfo->net, binfo->addpath_tx_id); + + if ((addpath_capable && has_adj) + || (!addpath_capable && has_adj + && CHECK_FLAG(binfo->flags, + BGP_INFO_SELECTED))) { + if (json_path && !json_adv_to) + json_adv_to = + json_object_new_object(); + + route_vty_out_advertised_to( + vty, peer, &first, + " Advertised to:", + json_adv_to); + } + } + + if (json_path) { + if (json_adv_to) { + json_object_object_add(json_path, + "advertisedTo", + json_adv_to); + } + } else { + if (!first) { + vty_out(vty, "\n"); + } + } + } - /* We've constructed the json object for this path, add it to the json - * array of paths - */ - if (json_paths) - { - if (json_nexthop_global || json_nexthop_ll) - { - json_nexthops = json_object_new_array(); + /* Line 9 display Uptime */ + tbuf = time(NULL) - (bgp_clock() - binfo->uptime); + if (json_paths) { + json_last_update = json_object_new_object(); + json_object_int_add(json_last_update, "epoch", tbuf); + json_object_string_add(json_last_update, "string", + ctime(&tbuf)); + json_object_object_add(json_path, "lastUpdate", + json_last_update); + } else + vty_out(vty, " Last update: %s", ctime(&tbuf)); + } - if (json_nexthop_global) - json_object_array_add(json_nexthops, json_nexthop_global); + /* We've constructed the json object for this path, add it to the json + * array of paths + */ + if (json_paths) { + if (json_nexthop_global || json_nexthop_ll) { + json_nexthops = json_object_new_array(); - if (json_nexthop_ll) - json_object_array_add(json_nexthops, json_nexthop_ll); + if (json_nexthop_global) + json_object_array_add(json_nexthops, + json_nexthop_global); - json_object_object_add(json_path, "nexthops", json_nexthops); - } + if (json_nexthop_ll) + json_object_array_add(json_nexthops, + json_nexthop_ll); - json_object_object_add(json_path, "peer", json_peer); - json_object_array_add(json_paths, json_path); - } - else - vty_out (vty, "\n"); + json_object_object_add(json_path, "nexthops", + json_nexthops); + } + + json_object_object_add(json_path, "peer", json_peer); + json_object_array_add(json_paths, json_path); + } else + vty_out(vty, "\n"); } #define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path" #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n" #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n" -static int -bgp_show_prefix_list (struct vty *vty, struct bgp *bgp, - const char *prefix_list_str, afi_t afi, - safi_t safi, enum bgp_show_type type); -static int -bgp_show_filter_list (struct vty *vty, struct bgp *bgp, - const char *filter, afi_t afi, - safi_t safi, enum bgp_show_type type); -static int -bgp_show_route_map (struct vty *vty, struct bgp *bgp, - const char *rmap_str, afi_t afi, - safi_t safi, enum bgp_show_type type); -static int -bgp_show_community_list (struct vty *vty, struct bgp *bgp, - const char *com, int exact, - afi_t afi, safi_t safi); -static int -bgp_show_prefix_longer (struct vty *vty, struct bgp *bgp, - const char *prefix, afi_t afi, - safi_t safi, enum bgp_show_type type); -static int -bgp_show_regexp (struct vty *vty, const char *regstr, afi_t afi, - safi_t safi, enum bgp_show_type type); -static int -bgp_show_community (struct vty *vty, struct bgp *bgp, int argc, - struct cmd_token **argv, int exact, afi_t afi, safi_t safi); - -static int -bgp_show_table (struct vty *vty, struct bgp *bgp, struct bgp_table *table, - enum bgp_show_type type, void *output_arg, u_char use_json) -{ - struct bgp_info *ri; - struct bgp_node *rn; - int header = 1; - int display; - unsigned long output_count; - unsigned long total_count; - struct prefix *p; - char buf[BUFSIZ]; - char buf2[BUFSIZ]; - json_object *json_paths = NULL; - int first = 1; - - if (use_json) - { - vty_out (vty, "{ \"vrfId\": %d, \"vrfName\": \"%s\", \"tableVersion\": %" PRId64 ", \"routerId\": \"%s\", \"routes\": { ", - bgp->vrf_id == VRF_UNKNOWN ? -1 : bgp->vrf_id, - bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT ? "Default" : bgp->name, - table->version, inet_ntoa (bgp->router_id)); - json_paths = json_object_new_object(); - } +static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp, + const char *prefix_list_str, afi_t afi, + safi_t safi, enum bgp_show_type type); +static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp, + const char *filter, afi_t afi, safi_t safi, + enum bgp_show_type type); +static int bgp_show_route_map(struct vty *vty, struct bgp *bgp, + const char *rmap_str, afi_t afi, safi_t safi, + enum bgp_show_type type); +static int bgp_show_community_list(struct vty *vty, struct bgp *bgp, + const char *com, int exact, afi_t afi, + safi_t safi); +static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp, + const char *prefix, afi_t afi, safi_t safi, + enum bgp_show_type type); +static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi, + safi_t safi, enum bgp_show_type type); +static int bgp_show_community(struct vty *vty, struct bgp *bgp, int argc, + struct cmd_token **argv, int exact, afi_t afi, + safi_t safi); + +static int bgp_show_table(struct vty *vty, struct bgp *bgp, + struct bgp_table *table, enum bgp_show_type type, + void *output_arg, u_char use_json) +{ + struct bgp_info *ri; + struct bgp_node *rn; + int header = 1; + int display; + unsigned long output_count; + unsigned long total_count; + struct prefix *p; + char buf[BUFSIZ]; + char buf2[BUFSIZ]; + json_object *json_paths = NULL; + int first = 1; + + if (use_json) { + vty_out(vty, + "{ \"vrfId\": %d, \"vrfName\": \"%s\", \"tableVersion\": %" PRId64 + ", \"routerId\": \"%s\", \"routes\": { ", + bgp->vrf_id == VRF_UNKNOWN ? -1 : bgp->vrf_id, + bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT ? "Default" + : bgp->name, + table->version, inet_ntoa(bgp->router_id)); + json_paths = json_object_new_object(); + } - /* This is first entry point, so reset total line. */ - output_count = 0; - total_count = 0; - - /* Start processing of routes. */ - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - if (rn->info != NULL) - { - display = 0; - if (!first && use_json) - { - vty_out (vty, ","); - } - if (use_json) - json_paths = json_object_new_array(); - else - json_paths = NULL; - - for (ri = rn->info; ri; ri = ri->next) - { - total_count++; - if (type == bgp_show_type_flap_statistics - || type == bgp_show_type_flap_neighbor - || type == bgp_show_type_dampend_paths - || type == bgp_show_type_damp_neighbor) - { - if (!(ri->extra && ri->extra->damp_info)) - continue; - } - if (type == bgp_show_type_regexp) - { - regex_t *regex = output_arg; - - if (bgp_regexec (regex, ri->attr->aspath) == REG_NOMATCH) - continue; - } - if (type == bgp_show_type_prefix_list) - { - struct prefix_list *plist = output_arg; - - if (prefix_list_apply (plist, &rn->p) != PREFIX_PERMIT) - continue; - } - if (type == bgp_show_type_filter_list) - { - struct as_list *as_list = output_arg; - - if (as_list_apply (as_list, ri->attr->aspath) != AS_FILTER_PERMIT) - continue; - } - if (type == bgp_show_type_route_map) - { - struct route_map *rmap = output_arg; - struct bgp_info binfo; - struct attr dummy_attr; - int ret; - - bgp_attr_dup (&dummy_attr, ri->attr); - - binfo.peer = ri->peer; - binfo.attr = &dummy_attr; - - ret = route_map_apply (rmap, &rn->p, RMAP_BGP, &binfo); - if (ret == RMAP_DENYMATCH) - continue; - } - if (type == bgp_show_type_neighbor - || type == bgp_show_type_flap_neighbor - || type == bgp_show_type_damp_neighbor) - { - union sockunion *su = output_arg; - - if (ri->peer == NULL || - ri->peer->su_remote == NULL || ! sockunion_same(ri->peer->su_remote, su)) - continue; - } - if (type == bgp_show_type_cidr_only) - { - u_int32_t destination; - - destination = ntohl (rn->p.u.prefix4.s_addr); - if (IN_CLASSC (destination) && rn->p.prefixlen == 24) - continue; - if (IN_CLASSB (destination) && rn->p.prefixlen == 16) - continue; - if (IN_CLASSA (destination) && rn->p.prefixlen == 8) - continue; - } - if (type == bgp_show_type_prefix_longer) - { - struct prefix *p = output_arg; - - if (! prefix_match (p, &rn->p)) - continue; - } - if (type == bgp_show_type_community_all) - { - if (! ri->attr->community) - continue; - } - if (type == bgp_show_type_community) - { - struct community *com = output_arg; - - if (! ri->attr->community || - ! community_match (ri->attr->community, com)) - continue; - } - if (type == bgp_show_type_community_exact) - { - struct community *com = output_arg; - - if (! ri->attr->community || - ! community_cmp (ri->attr->community, com)) - continue; - } - if (type == bgp_show_type_community_list) - { - struct community_list *list = output_arg; - - if (! community_list_match (ri->attr->community, list)) - continue; - } - if (type == bgp_show_type_community_list_exact) - { - struct community_list *list = output_arg; - - if (! community_list_exact_match (ri->attr->community, list)) - continue; - } - if (type == bgp_show_type_lcommunity) - { - struct lcommunity *lcom = output_arg; - - if (! ri->attr->lcommunity || - ! lcommunity_match (ri->attr->lcommunity, lcom)) - continue; - } - if (type == bgp_show_type_lcommunity_list) - { - struct community_list *list = output_arg; - - if (! lcommunity_list_match (ri->attr->lcommunity, list)) - continue; - } - if (type == bgp_show_type_lcommunity_all) - { - if (! ri->attr->lcommunity) - continue; - } - if (type == bgp_show_type_dampend_paths - || type == bgp_show_type_damp_neighbor) - { - if (! CHECK_FLAG (ri->flags, BGP_INFO_DAMPED) - || CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) - continue; - } - - if (!use_json && header) - { - vty_out (vty, "BGP table version is %" PRIu64 ", local router ID is %s\n", table->version, - inet_ntoa(bgp->router_id)); - vty_out (vty, BGP_SHOW_SCODE_HEADER); - vty_out (vty, BGP_SHOW_OCODE_HEADER); - if (type == bgp_show_type_dampend_paths - || type == bgp_show_type_damp_neighbor) - vty_out (vty, BGP_SHOW_DAMP_HEADER); - else if (type == bgp_show_type_flap_statistics - || type == bgp_show_type_flap_neighbor) - vty_out (vty, BGP_SHOW_FLAP_HEADER); - else - vty_out (vty, BGP_SHOW_HEADER); - header = 0; - } - - if (type == bgp_show_type_dampend_paths - || type == bgp_show_type_damp_neighbor) - damp_route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST, use_json, json_paths); - else if (type == bgp_show_type_flap_statistics - || type == bgp_show_type_flap_neighbor) - flap_route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST, use_json, json_paths); - else - route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST, json_paths); - display++; - } - - if (display) - { - output_count++; - if (use_json) - { - p = &rn->p; - sprintf(buf2, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen); - vty_out (vty, "\"%s\": ", buf2); - vty_out (vty, "%s", json_object_to_json_string (json_paths)); - json_object_free (json_paths); - first = 0; - - } - } - } - - if (use_json) - { - json_object_free (json_paths); - vty_out (vty, " } }\n"); - } - else - { - /* No route is displayed */ - if (output_count == 0) - { - if (type == bgp_show_type_normal) - vty_out (vty, "No BGP prefixes displayed, %ld exist\n", - total_count); - } - else - vty_out (vty, "\nDisplayed %ld routes and %ld total paths\n", output_count, total_count); - } + /* This is first entry point, so reset total line. */ + output_count = 0; + total_count = 0; + + /* Start processing of routes. */ + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) + if (rn->info != NULL) { + display = 0; + if (!first && use_json) { + vty_out(vty, ","); + } + if (use_json) + json_paths = json_object_new_array(); + else + json_paths = NULL; + + for (ri = rn->info; ri; ri = ri->next) { + total_count++; + if (type == bgp_show_type_flap_statistics + || type == bgp_show_type_flap_neighbor + || type == bgp_show_type_dampend_paths + || type == bgp_show_type_damp_neighbor) { + if (!(ri->extra + && ri->extra->damp_info)) + continue; + } + if (type == bgp_show_type_regexp) { + regex_t *regex = output_arg; + + if (bgp_regexec(regex, ri->attr->aspath) + == REG_NOMATCH) + continue; + } + if (type == bgp_show_type_prefix_list) { + struct prefix_list *plist = output_arg; + + if (prefix_list_apply(plist, &rn->p) + != PREFIX_PERMIT) + continue; + } + if (type == bgp_show_type_filter_list) { + struct as_list *as_list = output_arg; + + if (as_list_apply(as_list, + ri->attr->aspath) + != AS_FILTER_PERMIT) + continue; + } + if (type == bgp_show_type_route_map) { + struct route_map *rmap = output_arg; + struct bgp_info binfo; + struct attr dummy_attr; + int ret; + + bgp_attr_dup(&dummy_attr, ri->attr); + + binfo.peer = ri->peer; + binfo.attr = &dummy_attr; + + ret = route_map_apply(rmap, &rn->p, + RMAP_BGP, &binfo); + if (ret == RMAP_DENYMATCH) + continue; + } + if (type == bgp_show_type_neighbor + || type == bgp_show_type_flap_neighbor + || type == bgp_show_type_damp_neighbor) { + union sockunion *su = output_arg; + + if (ri->peer == NULL + || ri->peer->su_remote == NULL + || !sockunion_same( + ri->peer->su_remote, su)) + continue; + } + if (type == bgp_show_type_cidr_only) { + u_int32_t destination; + + destination = + ntohl(rn->p.u.prefix4.s_addr); + if (IN_CLASSC(destination) + && rn->p.prefixlen == 24) + continue; + if (IN_CLASSB(destination) + && rn->p.prefixlen == 16) + continue; + if (IN_CLASSA(destination) + && rn->p.prefixlen == 8) + continue; + } + if (type == bgp_show_type_prefix_longer) { + struct prefix *p = output_arg; + + if (!prefix_match(p, &rn->p)) + continue; + } + if (type == bgp_show_type_community_all) { + if (!ri->attr->community) + continue; + } + if (type == bgp_show_type_community) { + struct community *com = output_arg; + + if (!ri->attr->community + || !community_match( + ri->attr->community, + com)) + continue; + } + if (type == bgp_show_type_community_exact) { + struct community *com = output_arg; + + if (!ri->attr->community + || !community_cmp( + ri->attr->community, + com)) + continue; + } + if (type == bgp_show_type_community_list) { + struct community_list *list = + output_arg; + + if (!community_list_match( + ri->attr->community, list)) + continue; + } + if (type + == bgp_show_type_community_list_exact) { + struct community_list *list = + output_arg; + + if (!community_list_exact_match( + ri->attr->community, list)) + continue; + } + if (type == bgp_show_type_lcommunity) { + struct lcommunity *lcom = output_arg; + + if (!ri->attr->lcommunity + || !lcommunity_match( + ri->attr->lcommunity, + lcom)) + continue; + } + if (type == bgp_show_type_lcommunity_list) { + struct community_list *list = + output_arg; + + if (!lcommunity_list_match( + ri->attr->lcommunity, list)) + continue; + } + if (type == bgp_show_type_lcommunity_all) { + if (!ri->attr->lcommunity) + continue; + } + if (type == bgp_show_type_dampend_paths + || type == bgp_show_type_damp_neighbor) { + if (!CHECK_FLAG(ri->flags, + BGP_INFO_DAMPED) + || CHECK_FLAG(ri->flags, + BGP_INFO_HISTORY)) + continue; + } + + if (!use_json && header) { + vty_out(vty, + "BGP table version is %" PRIu64 + ", local router ID is %s\n", + table->version, + inet_ntoa(bgp->router_id)); + vty_out(vty, BGP_SHOW_SCODE_HEADER); + vty_out(vty, BGP_SHOW_OCODE_HEADER); + if (type == bgp_show_type_dampend_paths + || type == bgp_show_type_damp_neighbor) + vty_out(vty, + BGP_SHOW_DAMP_HEADER); + else if ( + type == bgp_show_type_flap_statistics + || type == bgp_show_type_flap_neighbor) + vty_out(vty, + BGP_SHOW_FLAP_HEADER); + else + vty_out(vty, BGP_SHOW_HEADER); + header = 0; + } + + if (type == bgp_show_type_dampend_paths + || type == bgp_show_type_damp_neighbor) + damp_route_vty_out( + vty, &rn->p, ri, display, + SAFI_UNICAST, use_json, + json_paths); + else if (type == bgp_show_type_flap_statistics + || type == bgp_show_type_flap_neighbor) + flap_route_vty_out( + vty, &rn->p, ri, display, + SAFI_UNICAST, use_json, + json_paths); + else + route_vty_out(vty, &rn->p, ri, display, + SAFI_UNICAST, json_paths); + display++; + } + + if (display) { + output_count++; + if (use_json) { + p = &rn->p; + sprintf(buf2, "%s/%d", + inet_ntop(p->family, + &p->u.prefix, buf, + BUFSIZ), + p->prefixlen); + vty_out(vty, "\"%s\": ", buf2); + vty_out(vty, "%s", + json_object_to_json_string( + json_paths)); + json_object_free(json_paths); + first = 0; + } + } + } + + if (use_json) { + json_object_free(json_paths); + vty_out(vty, " } }\n"); + } else { + /* No route is displayed */ + if (output_count == 0) { + if (type == bgp_show_type_normal) + vty_out(vty, + "No BGP prefixes displayed, %ld exist\n", + total_count); + } else + vty_out(vty, + "\nDisplayed %ld routes and %ld total paths\n", + output_count, total_count); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -bgp_show (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, - enum bgp_show_type type, void *output_arg, u_char use_json) +static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, + enum bgp_show_type type, void *output_arg, u_char use_json) { - struct bgp_table *table; + struct bgp_table *table; - if (bgp == NULL) - { - bgp = bgp_get_default (); - } + if (bgp == NULL) { + bgp = bgp_get_default(); + } - if (bgp == NULL) - { - if (!use_json) - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING; - } + if (bgp == NULL) { + if (!use_json) + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING; + } - /* use MPLS and ENCAP specific shows until they are merged */ - if (safi == SAFI_MPLS_VPN) - { - return bgp_show_mpls_vpn(vty, afi, NULL, type, output_arg, - 0, use_json); - } - /* labeled-unicast routes live in the unicast table */ - else if (safi == SAFI_LABELED_UNICAST) - safi = SAFI_UNICAST; + /* use MPLS and ENCAP specific shows until they are merged */ + if (safi == SAFI_MPLS_VPN) { + return bgp_show_mpls_vpn(vty, afi, NULL, type, output_arg, 0, + use_json); + } + /* labeled-unicast routes live in the unicast table */ + else if (safi == SAFI_LABELED_UNICAST) + safi = SAFI_UNICAST; - table = bgp->rib[afi][safi]; + table = bgp->rib[afi][safi]; - return bgp_show_table (vty, bgp, table, type, output_arg, - use_json); + return bgp_show_table(vty, bgp, table, type, output_arg, use_json); } -static void -bgp_show_all_instances_routes_vty (struct vty *vty, afi_t afi, safi_t safi, - u_char use_json) +static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi, + safi_t safi, u_char use_json) { - struct listnode *node, *nnode; - struct bgp *bgp; - int is_first = 1; - - if (use_json) - vty_out (vty, "{\n"); + struct listnode *node, *nnode; + struct bgp *bgp; + int is_first = 1; - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - { - if (use_json) - { - if (! is_first) - vty_out (vty, ",\n"); - else - is_first = 0; - - vty_out(vty, "\"%s\":", (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - ? "Default" : bgp->name); - } - else - { - vty_out (vty, "\nInstance %s:\n", - (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) ? "Default" : bgp->name); - } - bgp_show (vty, bgp, afi, safi, bgp_show_type_normal, NULL, use_json); + if (use_json) + vty_out(vty, "{\n"); - } + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) { + if (use_json) { + if (!is_first) + vty_out(vty, ",\n"); + else + is_first = 0; + + vty_out(vty, "\"%s\":", + (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) + ? "Default" + : bgp->name); + } else { + vty_out(vty, "\nInstance %s:\n", + (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) + ? "Default" + : bgp->name); + } + bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL, + use_json); + } - if (use_json) - vty_out (vty, "}\n"); + if (use_json) + vty_out(vty, "}\n"); } /* Header of detailed BGP route information */ -void -route_vty_out_detail_header (struct vty *vty, struct bgp *bgp, - struct bgp_node *rn, - struct prefix_rd *prd, afi_t afi, safi_t safi, - json_object *json) -{ - struct bgp_info *ri; - struct prefix *p; - struct peer *peer; - struct listnode *node, *nnode; - char buf1[INET6_ADDRSTRLEN]; - char buf2[INET6_ADDRSTRLEN]; +void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp, + struct bgp_node *rn, struct prefix_rd *prd, + afi_t afi, safi_t safi, json_object *json) +{ + struct bgp_info *ri; + struct prefix *p; + struct peer *peer; + struct listnode *node, *nnode; + char buf1[INET6_ADDRSTRLEN]; + char buf2[INET6_ADDRSTRLEN]; #if defined(HAVE_CUMULUS) - char buf3[EVPN_ROUTE_STRLEN]; + char buf3[EVPN_ROUTE_STRLEN]; #endif - int count = 0; - int best = 0; - int suppress = 0; - int no_export = 0; - int no_advertise = 0; - int local_as = 0; - int first = 1; - int has_valid_label = 0; - mpls_label_t label = 0; - json_object *json_adv_to = NULL; - - p = &rn->p; - has_valid_label = bgp_is_valid_label(&rn->local_label); - - if (has_valid_label) - label = label_pton(&rn->local_label); - - if (json) - { - if (has_valid_label) - json_object_int_add(json, "localLabel", label); + int count = 0; + int best = 0; + int suppress = 0; + int no_export = 0; + int no_advertise = 0; + int local_as = 0; + int first = 1; + int has_valid_label = 0; + mpls_label_t label = 0; + json_object *json_adv_to = NULL; - json_object_string_add(json, "prefix", inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN)); - json_object_int_add(json, "prefixlen", p->prefixlen); - } - else - { -#if defined (HAVE_CUMULUS) - if (safi == SAFI_EVPN) - vty_out (vty, "BGP routing table entry for %s%s%s\n", - prd ? prefix_rd2str (prd, buf1, RD_ADDRSTRLEN) : "", - prd ? ":" : "", - bgp_evpn_route2str ((struct prefix_evpn *)p, - buf3, sizeof (buf3))); - else - vty_out (vty, "BGP routing table entry for %s%s%s/%d\n", - ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) ? - prefix_rd2str (prd, buf1, RD_ADDRSTRLEN) : ""), - safi == SAFI_MPLS_VPN ? ":" : "", - inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN), - p->prefixlen); + p = &rn->p; + has_valid_label = bgp_is_valid_label(&rn->local_label); + + if (has_valid_label) + label = label_pton(&rn->local_label); + + if (json) { + if (has_valid_label) + json_object_int_add(json, "localLabel", label); + + json_object_string_add(json, "prefix", + inet_ntop(p->family, &p->u.prefix, buf2, + INET6_ADDRSTRLEN)); + json_object_int_add(json, "prefixlen", p->prefixlen); + } else { +#if defined(HAVE_CUMULUS) + if (safi == SAFI_EVPN) + vty_out(vty, "BGP routing table entry for %s%s%s\n", + prd ? prefix_rd2str(prd, buf1, RD_ADDRSTRLEN) + : "", + prd ? ":" : "", + bgp_evpn_route2str((struct prefix_evpn *)p, + buf3, sizeof(buf3))); + else + vty_out(vty, "BGP routing table entry for %s%s%s/%d\n", + ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) + ? prefix_rd2str(prd, buf1, + RD_ADDRSTRLEN) + : ""), + safi == SAFI_MPLS_VPN ? ":" : "", + inet_ntop(p->family, &p->u.prefix, buf2, + INET6_ADDRSTRLEN), + p->prefixlen); #else - if (p->family == AF_ETHERNET) - prefix2str (p, buf2, INET6_ADDRSTRLEN); - else - inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN); - vty_out (vty, "BGP routing table entry for %s%s%s/%d\n", - ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) ? - prefix_rd2str (prd, buf1, RD_ADDRSTRLEN) : ""), - ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN)) ? ":" : "", - buf2, - p->prefixlen); + if (p->family == AF_ETHERNET) + prefix2str(p, buf2, INET6_ADDRSTRLEN); + else + inet_ntop(p->family, &p->u.prefix, buf2, + INET6_ADDRSTRLEN); + vty_out(vty, "BGP routing table entry for %s%s%s/%d\n", + ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP + || safi == SAFI_EVPN) + ? prefix_rd2str(prd, buf1, RD_ADDRSTRLEN) + : ""), + ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN)) ? ":" + : "", + buf2, p->prefixlen); #endif - if (has_valid_label) - vty_out (vty, "Local label: %d\n", label); -#if defined (HAVE_CUMULUS) - if (bgp_labeled_safi(safi) && safi != SAFI_EVPN) + if (has_valid_label) + vty_out(vty, "Local label: %d\n", label); +#if defined(HAVE_CUMULUS) + if (bgp_labeled_safi(safi) && safi != SAFI_EVPN) #else - if (bgp_labeled_safi(safi)) + if (bgp_labeled_safi(safi)) #endif - vty_out(vty, "not allocated\n"); - } + vty_out(vty, "not allocated\n"); + } - for (ri = rn->info; ri; ri = ri->next) - { - count++; - if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) - { - best = count; - if (ri->extra && ri->extra->suppress) - suppress = 1; - if (ri->attr->community != NULL) - { - if (community_include (ri->attr->community, COMMUNITY_NO_ADVERTISE)) - no_advertise = 1; - if (community_include (ri->attr->community, COMMUNITY_NO_EXPORT)) - no_export = 1; - if (community_include (ri->attr->community, COMMUNITY_LOCAL_AS)) - local_as = 1; - } + for (ri = rn->info; ri; ri = ri->next) { + count++; + if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) { + best = count; + if (ri->extra && ri->extra->suppress) + suppress = 1; + if (ri->attr->community != NULL) { + if (community_include(ri->attr->community, + COMMUNITY_NO_ADVERTISE)) + no_advertise = 1; + if (community_include(ri->attr->community, + COMMUNITY_NO_EXPORT)) + no_export = 1; + if (community_include(ri->attr->community, + COMMUNITY_LOCAL_AS)) + local_as = 1; + } + } } - } - if (!json) - { - vty_out (vty, "Paths: (%d available", count); - if (best) - { - vty_out (vty, ", best #%d", best); - if (safi == SAFI_UNICAST) - vty_out (vty, ", table %s", - (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - ? "Default-IP-Routing-Table" : bgp->name); - } - else - vty_out (vty, ", no best path"); - - if (no_advertise) - vty_out (vty, ", not advertised to any peer"); - else if (no_export) - vty_out (vty, ", not advertised to EBGP peer"); - else if (local_as) - vty_out (vty, ", not advertised outside local AS"); - - if (suppress) - vty_out (vty, ", Advertisements suppressed by an aggregate."); - vty_out (vty, ")\n"); - } + if (!json) { + vty_out(vty, "Paths: (%d available", count); + if (best) { + vty_out(vty, ", best #%d", best); + if (safi == SAFI_UNICAST) + vty_out(vty, ", table %s", + (bgp->inst_type + == BGP_INSTANCE_TYPE_DEFAULT) + ? "Default-IP-Routing-Table" + : bgp->name); + } else + vty_out(vty, ", no best path"); + + if (no_advertise) + vty_out(vty, ", not advertised to any peer"); + else if (no_export) + vty_out(vty, ", not advertised to EBGP peer"); + else if (local_as) + vty_out(vty, ", not advertised outside local AS"); + + if (suppress) + vty_out(vty, + ", Advertisements suppressed by an aggregate."); + vty_out(vty, ")\n"); + } - /* If we are not using addpath then we can display Advertised to and that will - * show what peers we advertised the bestpath to. If we are using addpath - * though then we must display Advertised to on a path-by-path basis. */ - if (!bgp->addpath_tx_used[afi][safi]) - { - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (bgp_adj_out_lookup (peer, rn, 0)) - { - if (json && !json_adv_to) - json_adv_to = json_object_new_object(); - - route_vty_out_advertised_to(vty, peer, &first, - " Advertised to non peer-group peers:\n ", - json_adv_to); - } - } - - if (json) - { - if (json_adv_to) - { - json_object_object_add(json, "advertisedTo", json_adv_to); - } - } - else - { - if (first) - vty_out (vty, " Not advertised to any peer"); - vty_out (vty, "\n"); - } - } + /* If we are not using addpath then we can display Advertised to and + * that will + * show what peers we advertised the bestpath to. If we are using + * addpath + * though then we must display Advertised to on a path-by-path basis. */ + if (!bgp->addpath_tx_used[afi][safi]) { + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (bgp_adj_out_lookup(peer, rn, 0)) { + if (json && !json_adv_to) + json_adv_to = json_object_new_object(); + + route_vty_out_advertised_to( + vty, peer, &first, + " Advertised to non peer-group peers:\n ", + json_adv_to); + } + } + + if (json) { + if (json_adv_to) { + json_object_object_add(json, "advertisedTo", + json_adv_to); + } + } else { + if (first) + vty_out(vty, " Not advertised to any peer"); + vty_out(vty, "\n"); + } + } } /* Display specified route of BGP table. */ -static int -bgp_show_route_in_table (struct vty *vty, struct bgp *bgp, - struct bgp_table *rib, const char *ip_str, - afi_t afi, safi_t safi, struct prefix_rd *prd, - int prefix_check, enum bgp_path_type pathtype, - u_char use_json) -{ - int ret; - int header; - int display = 0; - struct prefix match; - struct bgp_node *rn; - struct bgp_node *rm; - struct bgp_info *ri; - struct bgp_table *table; - json_object *json = NULL; - json_object *json_paths = NULL; - - /* Check IP address argument. */ - ret = str2prefix (ip_str, &match); - if (! ret) - { - vty_out (vty, "address is malformed\n"); - return CMD_WARNING; - } - - match.family = afi2family (afi); +static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp, + struct bgp_table *rib, const char *ip_str, + afi_t afi, safi_t safi, + struct prefix_rd *prd, int prefix_check, + enum bgp_path_type pathtype, u_char use_json) +{ + int ret; + int header; + int display = 0; + struct prefix match; + struct bgp_node *rn; + struct bgp_node *rm; + struct bgp_info *ri; + struct bgp_table *table; + json_object *json = NULL; + json_object *json_paths = NULL; + + /* Check IP address argument. */ + ret = str2prefix(ip_str, &match); + if (!ret) { + vty_out(vty, "address is malformed\n"); + return CMD_WARNING; + } - if (use_json) - { - json = json_object_new_object(); - json_paths = json_object_new_array(); - } + match.family = afi2family(afi); - if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) - { - for (rn = bgp_table_top (rib); rn; rn = bgp_route_next (rn)) - { - if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0) - continue; - - if ((table = rn->info) != NULL) - { - header = 1; - - if ((rm = bgp_node_match (table, &match)) != NULL) - { - if (prefix_check && rm->p.prefixlen != match.prefixlen) - { - bgp_unlock_node (rm); - continue; - } - - for (ri = rm->info; ri; ri = ri->next) - { - if (header) - { - route_vty_out_detail_header (vty, bgp, rm, (struct prefix_rd *)&rn->p, - AFI_IP, safi, json); - header = 0; - } - display++; - - if (pathtype == BGP_PATH_ALL || - (pathtype == BGP_PATH_BESTPATH && CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) || - (pathtype == BGP_PATH_MULTIPATH && - (CHECK_FLAG (ri->flags, BGP_INFO_MULTIPATH) || CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)))) - route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, safi, json_paths); - } - - bgp_unlock_node (rm); - } - } - } - } - else - { - header = 1; - - if ((rn = bgp_node_match (rib, &match)) != NULL) - { - if (! prefix_check || rn->p.prefixlen == match.prefixlen) - { - for (ri = rn->info; ri; ri = ri->next) - { - if (header) - { - route_vty_out_detail_header (vty, bgp, rn, NULL, afi, safi, json); - header = 0; - } - display++; - - if (pathtype == BGP_PATH_ALL || - (pathtype == BGP_PATH_BESTPATH && CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) || - (pathtype == BGP_PATH_MULTIPATH && - (CHECK_FLAG (ri->flags, BGP_INFO_MULTIPATH) || CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)))) - route_vty_out_detail (vty, bgp, &rn->p, ri, afi, safi, json_paths); - } - } - - bgp_unlock_node (rn); - } - } + if (use_json) { + json = json_object_new_object(); + json_paths = json_object_new_array(); + } - if (use_json) - { - if (display) - json_object_object_add(json, "paths", json_paths); + if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) { + for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) { + if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0) + continue; + + if ((table = rn->info) != NULL) { + header = 1; + + if ((rm = bgp_node_match(table, &match)) + != NULL) { + if (prefix_check + && rm->p.prefixlen + != match.prefixlen) { + bgp_unlock_node(rm); + continue; + } + + for (ri = rm->info; ri; ri = ri->next) { + if (header) { + route_vty_out_detail_header( + vty, bgp, rm, + (struct + prefix_rd *)&rn + ->p, + AFI_IP, safi, + json); + header = 0; + } + display++; + + if (pathtype == BGP_PATH_ALL + || (pathtype + == BGP_PATH_BESTPATH + && CHECK_FLAG( + ri->flags, + BGP_INFO_SELECTED)) + || (pathtype + == BGP_PATH_MULTIPATH + && (CHECK_FLAG( + ri->flags, + BGP_INFO_MULTIPATH) + || CHECK_FLAG( + ri->flags, + BGP_INFO_SELECTED)))) + route_vty_out_detail( + vty, bgp, + &rm->p, ri, + AFI_IP, safi, + json_paths); + } + + bgp_unlock_node(rm); + } + } + } + } else { + header = 1; + + if ((rn = bgp_node_match(rib, &match)) != NULL) { + if (!prefix_check + || rn->p.prefixlen == match.prefixlen) { + for (ri = rn->info; ri; ri = ri->next) { + if (header) { + route_vty_out_detail_header( + vty, bgp, rn, NULL, afi, + safi, json); + header = 0; + } + display++; + + if (pathtype == BGP_PATH_ALL + || (pathtype == BGP_PATH_BESTPATH + && CHECK_FLAG( + ri->flags, + BGP_INFO_SELECTED)) + || (pathtype == BGP_PATH_MULTIPATH + && (CHECK_FLAG( + ri->flags, + BGP_INFO_MULTIPATH) + || CHECK_FLAG( + ri->flags, + BGP_INFO_SELECTED)))) + route_vty_out_detail( + vty, bgp, &rn->p, ri, + afi, safi, json_paths); + } + } + + bgp_unlock_node(rn); + } + } - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - { - if (!display) - { - vty_out (vty, "%% Network not in table\n"); - return CMD_WARNING; - } - } + if (use_json) { + if (display) + json_object_object_add(json, "paths", json_paths); + + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else { + if (!display) { + vty_out(vty, "%% Network not in table\n"); + return CMD_WARNING; + } + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Display specified route of Main RIB */ -static int -bgp_show_route (struct vty *vty, struct bgp *bgp, const char *ip_str, - afi_t afi, safi_t safi, struct prefix_rd *prd, - int prefix_check, enum bgp_path_type pathtype, - u_char use_json) -{ - if (!bgp) - bgp = bgp_get_default (); - - /* labeled-unicast routes live in the unicast table */ - if (safi == SAFI_LABELED_UNICAST) - safi = SAFI_UNICAST; - - return bgp_show_route_in_table (vty, bgp, bgp->rib[afi][safi], ip_str, - afi, safi, prd, prefix_check, pathtype, - use_json); -} - -static int -bgp_show_lcommunity (struct vty *vty, struct bgp *bgp, int argc, - struct cmd_token **argv, afi_t afi, safi_t safi, u_char uj) -{ - struct lcommunity *lcom; - struct buffer *b; - int i; - char *str; - int first = 0; - - b = buffer_new (1024); - for (i = 0; i < argc; i++) - { - if (first) - buffer_putc (b, ' '); - else - { - if (strmatch (argv[i]->text, "AA:BB:CC")) - { - first = 1; - buffer_putstr (b, argv[i]->arg); - } - } - } - buffer_putc (b, '\0'); +static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str, + afi_t afi, safi_t safi, struct prefix_rd *prd, + int prefix_check, enum bgp_path_type pathtype, + u_char use_json) +{ + if (!bgp) + bgp = bgp_get_default(); + + /* labeled-unicast routes live in the unicast table */ + if (safi == SAFI_LABELED_UNICAST) + safi = SAFI_UNICAST; + + return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str, + afi, safi, prd, prefix_check, pathtype, + use_json); +} + +static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc, + struct cmd_token **argv, afi_t afi, safi_t safi, + u_char uj) +{ + struct lcommunity *lcom; + struct buffer *b; + int i; + char *str; + int first = 0; + + b = buffer_new(1024); + for (i = 0; i < argc; i++) { + if (first) + buffer_putc(b, ' '); + else { + if (strmatch(argv[i]->text, "AA:BB:CC")) { + first = 1; + buffer_putstr(b, argv[i]->arg); + } + } + } + buffer_putc(b, '\0'); - str = buffer_getstr (b); - buffer_free (b); + str = buffer_getstr(b); + buffer_free(b); - lcom = lcommunity_str2com (str); - XFREE (MTYPE_TMP, str); - if (! lcom) - { - vty_out (vty, "%% Large-community malformed\n"); - return CMD_WARNING; - } + lcom = lcommunity_str2com(str); + XFREE(MTYPE_TMP, str); + if (!lcom) { + vty_out(vty, "%% Large-community malformed\n"); + return CMD_WARNING; + } - return bgp_show (vty, bgp, afi, safi, bgp_show_type_lcommunity, lcom, uj); + return bgp_show(vty, bgp, afi, safi, bgp_show_type_lcommunity, lcom, + uj); } -static int -bgp_show_lcommunity_list (struct vty *vty, struct bgp *bgp, const char *lcom, - afi_t afi, safi_t safi, u_char uj) +static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp, + const char *lcom, afi_t afi, safi_t safi, + u_char uj) { - struct community_list *list; + struct community_list *list; - list = community_list_lookup (bgp_clist, lcom, LARGE_COMMUNITY_LIST_MASTER); - if (list == NULL) - { - vty_out (vty, "%% %s is not a valid large-community-list name\n",lcom); - return CMD_WARNING; - } + list = community_list_lookup(bgp_clist, lcom, + LARGE_COMMUNITY_LIST_MASTER); + if (list == NULL) { + vty_out(vty, "%% %s is not a valid large-community-list name\n", + lcom); + return CMD_WARNING; + } - return bgp_show (vty, bgp, afi, safi, bgp_show_type_lcommunity_list, list, uj); + return bgp_show(vty, bgp, afi, safi, bgp_show_type_lcommunity_list, + list, uj); } DEFUN (show_ip_bgp_large_community_list, @@ -8659,33 +8698,35 @@ DEFUN (show_ip_bgp_large_community_list, "large-community-list name\n" JSON_STR) { - char *vrf = NULL; - afi_t afi = AFI_IP6; - safi_t safi = SAFI_UNICAST; - int idx = 0; - - if (argv_find (argv, argc, "ip", &idx)) - afi = AFI_IP; - if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx)) - vrf = argv[++idx]->arg; - if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx)) - { - afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; - if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx)) - safi = bgp_vty_safi_from_str (argv[idx]->text); - } - - int uj = use_json (argc, argv); - - struct bgp *bgp = bgp_lookup_by_name (vrf); - if (bgp == NULL) - { - vty_out (vty, "Can't find BGP instance %s\n", vrf); - return CMD_WARNING; - } - - argv_find (argv, argc, "large-community-list", &idx); - return bgp_show_lcommunity_list (vty, bgp, argv[idx+1]->arg, afi, safi, uj); + char *vrf = NULL; + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; + int idx = 0; + + if (argv_find(argv, argc, "ip", &idx)) + afi = AFI_IP; + if (argv_find(argv, argc, "view", &idx) + || argv_find(argv, argc, "vrf", &idx)) + vrf = argv[++idx]->arg; + if (argv_find(argv, argc, "ipv4", &idx) + || argv_find(argv, argc, "ipv6", &idx)) { + afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; + if (argv_find(argv, argc, "unicast", &idx) + || argv_find(argv, argc, "multicast", &idx)) + safi = bgp_vty_safi_from_str(argv[idx]->text); + } + + int uj = use_json(argc, argv); + + struct bgp *bgp = bgp_lookup_by_name(vrf); + if (bgp == NULL) { + vty_out(vty, "Can't find BGP instance %s\n", vrf); + return CMD_WARNING; + } + + argv_find(argv, argc, "large-community-list", &idx); + return bgp_show_lcommunity_list(vty, bgp, argv[idx + 1]->arg, afi, safi, + uj); } DEFUN (show_ip_bgp_large_community, show_ip_bgp_large_community_cmd, @@ -8700,38 +8741,41 @@ DEFUN (show_ip_bgp_large_community, "List of large-community numbers\n" JSON_STR) { - char *vrf = NULL; - afi_t afi = AFI_IP6; - safi_t safi = SAFI_UNICAST; - int idx = 0; - - if (argv_find (argv, argc, "ip", &idx)) - afi = AFI_IP; - if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx)) - vrf = argv[++idx]->arg; - if (argv_find (argv, argc, "ipv4", &idx) || argv_find (argv, argc, "ipv6", &idx)) - { - afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; - if (argv_find (argv, argc, "unicast", &idx) || argv_find (argv, argc, "multicast", &idx)) - safi = bgp_vty_safi_from_str (argv[idx]->text); - } - - int uj = use_json (argc, argv); - - struct bgp *bgp = bgp_lookup_by_name (vrf); - if (bgp == NULL) - { - vty_out (vty, "Can't find BGP instance %s\n", vrf); - return CMD_WARNING; - } - - if (argv_find (argv, argc, "AA:BB:CC", &idx)) - return bgp_show_lcommunity (vty, bgp, argc, argv, afi, safi, uj); - else - return bgp_show (vty, bgp, afi, safi, bgp_show_type_lcommunity_all, NULL, uj); + char *vrf = NULL; + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; + int idx = 0; + + if (argv_find(argv, argc, "ip", &idx)) + afi = AFI_IP; + if (argv_find(argv, argc, "view", &idx) + || argv_find(argv, argc, "vrf", &idx)) + vrf = argv[++idx]->arg; + if (argv_find(argv, argc, "ipv4", &idx) + || argv_find(argv, argc, "ipv6", &idx)) { + afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP; + if (argv_find(argv, argc, "unicast", &idx) + || argv_find(argv, argc, "multicast", &idx)) + safi = bgp_vty_safi_from_str(argv[idx]->text); + } + + int uj = use_json(argc, argv); + + struct bgp *bgp = bgp_lookup_by_name(vrf); + if (bgp == NULL) { + vty_out(vty, "Can't find BGP instance %s\n", vrf); + return CMD_WARNING; + } + + if (argv_find(argv, argc, "AA:BB:CC", &idx)) + return bgp_show_lcommunity(vty, bgp, argc, argv, afi, safi, uj); + else + return bgp_show(vty, bgp, afi, safi, + bgp_show_type_lcommunity_all, NULL, uj); } -static int bgp_table_stats (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi); +static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi); /* BGP route print out function. */ DEFUN (show_ip_bgp, @@ -8783,76 +8827,88 @@ DEFUN (show_ip_bgp, "Display route and more specific routes\n" JSON_STR) { - afi_t afi = AFI_IP6; - safi_t safi = SAFI_UNICAST; - int exact_match = 0; - enum bgp_show_type sh_type = bgp_show_type_normal; - struct bgp *bgp = NULL; - int idx = 0; - - bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp); - if (!idx) - return CMD_WARNING; - - int uj = use_json (argc, argv); - if (uj) argc--; - - if (argv_find(argv, argc, "cidr-only", &idx)) - return bgp_show (vty, bgp, afi, safi, bgp_show_type_cidr_only, NULL, uj); - - if (argv_find(argv, argc, "dampening", &idx)) - { - if (argv_find (argv, argc, "dampened-paths", &idx)) - return bgp_show (vty, bgp, afi, safi, bgp_show_type_dampend_paths, NULL, uj); - else if (argv_find (argv, argc, "flap-statistics", &idx)) - return bgp_show (vty, bgp, afi, safi, bgp_show_type_flap_statistics, NULL, uj); - else if (argv_find (argv, argc, "parameters", &idx)) - return bgp_show_dampening_parameters (vty, afi, safi); - } - - if (argv_find(argv, argc, "prefix-list", &idx)) - return bgp_show_prefix_list (vty, bgp, argv[idx + 1]->arg, afi, safi, bgp_show_type_prefix_list); - - if (argv_find(argv, argc, "filter-list", &idx)) - return bgp_show_filter_list (vty, bgp, argv[idx + 1]->arg, afi, safi, bgp_show_type_filter_list); - - if (argv_find(argv, argc, "statistics", &idx)) - return bgp_table_stats (vty, bgp, afi, safi); - - if (argv_find(argv, argc, "route-map", &idx)) - return bgp_show_route_map (vty, bgp, argv[idx + 1]->arg, afi, safi, bgp_show_type_route_map); - - if (argv_find(argv, argc, "community", &idx)) - { - /* show a specific community */ - if (argv_find (argv, argc, "local-AS", &idx) || - argv_find (argv, argc, "no-advertise", &idx) || - argv_find (argv, argc, "no-export", &idx)) - { - if (argv_find (argv, argc, "exact_match", &idx)) - exact_match = 1; - return bgp_show_community (vty, bgp, argc, argv, exact_match, afi, safi); - } - /* show all communities */ - else - return bgp_show (vty, bgp, afi, safi, bgp_show_type_community_all, NULL, uj); - } + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; + int exact_match = 0; + enum bgp_show_type sh_type = bgp_show_type_normal; + struct bgp *bgp = NULL; + int idx = 0; + + bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, + &bgp); + if (!idx) + return CMD_WARNING; + + int uj = use_json(argc, argv); + if (uj) + argc--; + + if (argv_find(argv, argc, "cidr-only", &idx)) + return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only, + NULL, uj); + + if (argv_find(argv, argc, "dampening", &idx)) { + if (argv_find(argv, argc, "dampened-paths", &idx)) + return bgp_show(vty, bgp, afi, safi, + bgp_show_type_dampend_paths, NULL, uj); + else if (argv_find(argv, argc, "flap-statistics", &idx)) + return bgp_show(vty, bgp, afi, safi, + bgp_show_type_flap_statistics, NULL, + uj); + else if (argv_find(argv, argc, "parameters", &idx)) + return bgp_show_dampening_parameters(vty, afi, safi); + } - if (argv_find(argv, argc, "community-list", &idx)) - { - const char *clist_number_or_name = argv[++idx]->arg; - if (++idx < argc && strmatch (argv[idx]->text, "exact-match")) - exact_match = 1; - return bgp_show_community_list (vty, bgp, clist_number_or_name, exact_match, afi, safi); - } - /* prefix-longer */ - if (argv_find(argv, argc, "A.B.C.D/M", &idx) || argv_find(argv, argc, "X:X::X:X/M", &idx)) - return bgp_show_prefix_longer (vty, bgp, argv[idx]->arg, afi, safi, bgp_show_type_prefix_longer); + if (argv_find(argv, argc, "prefix-list", &idx)) + return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi, + safi, bgp_show_type_prefix_list); + + if (argv_find(argv, argc, "filter-list", &idx)) + return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi, + safi, bgp_show_type_filter_list); + + if (argv_find(argv, argc, "statistics", &idx)) + return bgp_table_stats(vty, bgp, afi, safi); + + if (argv_find(argv, argc, "route-map", &idx)) + return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi, + safi, bgp_show_type_route_map); + + if (argv_find(argv, argc, "community", &idx)) { + /* show a specific community */ + if (argv_find(argv, argc, "local-AS", &idx) + || argv_find(argv, argc, "no-advertise", &idx) + || argv_find(argv, argc, "no-export", &idx)) { + if (argv_find(argv, argc, "exact_match", &idx)) + exact_match = 1; + return bgp_show_community(vty, bgp, argc, argv, + exact_match, afi, safi); + } + /* show all communities */ + else + return bgp_show(vty, bgp, afi, safi, + bgp_show_type_community_all, NULL, uj); + } - if (safi == SAFI_MPLS_VPN) - return bgp_show_mpls_vpn (vty, afi, NULL, bgp_show_type_normal, NULL, 0, uj); - else - return bgp_show (vty, bgp, afi, safi, sh_type, NULL, uj); + if (argv_find(argv, argc, "community-list", &idx)) { + const char *clist_number_or_name = argv[++idx]->arg; + if (++idx < argc && strmatch(argv[idx]->text, "exact-match")) + exact_match = 1; + return bgp_show_community_list(vty, bgp, clist_number_or_name, + exact_match, afi, safi); + } + /* prefix-longer */ + if (argv_find(argv, argc, "A.B.C.D/M", &idx) + || argv_find(argv, argc, "X:X::X:X/M", &idx)) + return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi, + safi, + bgp_show_type_prefix_longer); + + if (safi == SAFI_MPLS_VPN) + return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal, + NULL, 0, uj); + else + return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj); } DEFUN (show_ip_bgp_route, @@ -8873,58 +8929,61 @@ DEFUN (show_ip_bgp_route, "Display only multipaths\n" JSON_STR) { - int prefix_check = 0; + int prefix_check = 0; - afi_t afi = AFI_IP6; - safi_t safi = SAFI_UNICAST; - char *prefix = NULL; - struct bgp *bgp = NULL; - enum bgp_path_type path_type; - u_char uj = use_json(argc, argv); + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; + char *prefix = NULL; + struct bgp *bgp = NULL; + enum bgp_path_type path_type; + u_char uj = use_json(argc, argv); - int idx = 0; + int idx = 0; - bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp); - if (!idx) - return CMD_WARNING; + bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, + &bgp); + if (!idx) + return CMD_WARNING; - if (!bgp) - { - vty_out (vty, - "Specified 'all' vrf's but this command currently only works per view/vrf\n"); - return CMD_WARNING; - } + if (!bgp) { + vty_out(vty, + "Specified 'all' vrf's but this command currently only works per view/vrf\n"); + return CMD_WARNING; + } - /* */ - if (argv_find (argv, argc, "A.B.C.D", &idx) || argv_find (argv, argc, "X:X::X:X", &idx)) - prefix_check = 0; - else if (argv_find (argv, argc, "A.B.C.D/M", &idx) || argv_find (argv, argc, "X:X::X:X/M", &idx)) - prefix_check = 1; - - if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN) && afi != AFI_IP6) - { - vty_out (vty, - "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n"); - return CMD_WARNING; - } - if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN) && afi != AFI_IP) - { - vty_out (vty, - "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n"); - return CMD_WARNING; - } - - prefix = argv[idx]->arg; - - /* [] */ - if (argv_find (argv, argc, "bestpath", &idx)) - path_type = BGP_PATH_BESTPATH; - else if (argv_find (argv, argc, "multipath", &idx)) - path_type = BGP_PATH_MULTIPATH; - else - path_type = BGP_PATH_ALL; + /* */ + if (argv_find(argv, argc, "A.B.C.D", &idx) + || argv_find(argv, argc, "X:X::X:X", &idx)) + prefix_check = 0; + else if (argv_find(argv, argc, "A.B.C.D/M", &idx) + || argv_find(argv, argc, "X:X::X:X/M", &idx)) + prefix_check = 1; + + if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN) + && afi != AFI_IP6) { + vty_out(vty, + "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n"); + return CMD_WARNING; + } + if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN) + && afi != AFI_IP) { + vty_out(vty, + "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n"); + return CMD_WARNING; + } + + prefix = argv[idx]->arg; + + /* [] */ + if (argv_find(argv, argc, "bestpath", &idx)) + path_type = BGP_PATH_BESTPATH; + else if (argv_find(argv, argc, "multipath", &idx)) + path_type = BGP_PATH_MULTIPATH; + else + path_type = BGP_PATH_ALL; - return bgp_show_route (vty, bgp, prefix, afi, safi, NULL, prefix_check, path_type, uj); + return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check, + path_type, uj); } DEFUN (show_ip_bgp_regexp, @@ -8939,23 +8998,25 @@ DEFUN (show_ip_bgp_regexp, "Display routes matching the AS path regular expression\n" "A regular-expression to match the BGP AS paths\n") { - afi_t afi = AFI_IP6; - safi_t safi = SAFI_UNICAST; - struct bgp *bgp = NULL; + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; + struct bgp *bgp = NULL; - int idx = 0; - bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp); - if (!idx) - return CMD_WARNING; + int idx = 0; + bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, + &bgp); + if (!idx) + return CMD_WARNING; - // get index of regex - argv_find (argv, argc, "regexp", &idx); - idx++; + // get index of regex + argv_find(argv, argc, "regexp", &idx); + idx++; - char *regstr = argv_concat (argv, argc, idx); - int rc = bgp_show_regexp (vty, (const char *) regstr, afi, safi, bgp_show_type_regexp); - XFREE (MTYPE_TMP, regstr); - return rc; + char *regstr = argv_concat(argv, argc, idx); + int rc = bgp_show_regexp(vty, (const char *)regstr, afi, safi, + bgp_show_type_regexp); + XFREE(MTYPE_TMP, regstr); + return rc; } DEFUN (show_ip_bgp_instance_all, @@ -8969,278 +9030,265 @@ DEFUN (show_ip_bgp_instance_all, BGP_SAFI_WITH_LABEL_HELP_STR JSON_STR) { - afi_t afi = AFI_IP; - safi_t safi = SAFI_UNICAST; - struct bgp *bgp = NULL; + afi_t afi = AFI_IP; + safi_t safi = SAFI_UNICAST; + struct bgp *bgp = NULL; - int idx = 0; - bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp); - if (!idx) - return CMD_WARNING; + int idx = 0; + bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, + &bgp); + if (!idx) + return CMD_WARNING; - int uj = use_json (argc, argv); - if (uj) argc--; + int uj = use_json(argc, argv); + if (uj) + argc--; - bgp_show_all_instances_routes_vty (vty, afi, safi, uj); - return CMD_SUCCESS; + bgp_show_all_instances_routes_vty(vty, afi, safi, uj); + return CMD_SUCCESS; } -static int -bgp_show_regexp (struct vty *vty, const char *regstr, afi_t afi, - safi_t safi, enum bgp_show_type type) +static int bgp_show_regexp(struct vty *vty, const char *regstr, afi_t afi, + safi_t safi, enum bgp_show_type type) { - regex_t *regex; - int rc; - - regex = bgp_regcomp (regstr); - if (! regex) - { - vty_out (vty, "Can't compile regexp %s\n", regstr); - return CMD_WARNING; - } - - rc = bgp_show (vty, NULL, afi, safi, type, regex, 0); - bgp_regex_free (regex); - return rc; -} - -static int -bgp_show_prefix_list (struct vty *vty, struct bgp *bgp, - const char *prefix_list_str, afi_t afi, - safi_t safi, enum bgp_show_type type) -{ - struct prefix_list *plist; + regex_t *regex; + int rc; - plist = prefix_list_lookup (afi, prefix_list_str); - if (plist == NULL) - { - vty_out (vty, "%% %s is not a valid prefix-list name\n", - prefix_list_str); - return CMD_WARNING; - } + regex = bgp_regcomp(regstr); + if (!regex) { + vty_out(vty, "Can't compile regexp %s\n", regstr); + return CMD_WARNING; + } - return bgp_show (vty, bgp, afi, safi, type, plist, 0); + rc = bgp_show(vty, NULL, afi, safi, type, regex, 0); + bgp_regex_free(regex); + return rc; } -static int -bgp_show_filter_list (struct vty *vty, struct bgp *bgp, - const char *filter, afi_t afi, - safi_t safi, enum bgp_show_type type) +static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp, + const char *prefix_list_str, afi_t afi, + safi_t safi, enum bgp_show_type type) { - struct as_list *as_list; + struct prefix_list *plist; - as_list = as_list_lookup (filter); - if (as_list == NULL) - { - vty_out (vty, "%% %s is not a valid AS-path access-list name\n", - filter); - return CMD_WARNING; - } + plist = prefix_list_lookup(afi, prefix_list_str); + if (plist == NULL) { + vty_out(vty, "%% %s is not a valid prefix-list name\n", + prefix_list_str); + return CMD_WARNING; + } - return bgp_show (vty, bgp, afi, safi, type, as_list, 0); + return bgp_show(vty, bgp, afi, safi, type, plist, 0); } -static int -bgp_show_route_map (struct vty *vty, struct bgp *bgp, - const char *rmap_str, afi_t afi, - safi_t safi, enum bgp_show_type type) +static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp, + const char *filter, afi_t afi, safi_t safi, + enum bgp_show_type type) { - struct route_map *rmap; + struct as_list *as_list; - rmap = route_map_lookup_by_name (rmap_str); - if (! rmap) - { - vty_out (vty, "%% %s is not a valid route-map name\n", - rmap_str); - return CMD_WARNING; - } + as_list = as_list_lookup(filter); + if (as_list == NULL) { + vty_out(vty, "%% %s is not a valid AS-path access-list name\n", + filter); + return CMD_WARNING; + } - return bgp_show (vty, bgp, afi, safi, type, rmap, 0); + return bgp_show(vty, bgp, afi, safi, type, as_list, 0); } -static int -bgp_show_community (struct vty *vty, struct bgp *bgp, int argc, - struct cmd_token **argv, int exact, afi_t afi, safi_t safi) +static int bgp_show_route_map(struct vty *vty, struct bgp *bgp, + const char *rmap_str, afi_t afi, safi_t safi, + enum bgp_show_type type) { - struct community *com; - struct buffer *b; - int i; - char *str; - int first = 0; - int ret = 0; + struct route_map *rmap; - b = buffer_new (1024); - for (i = 0; i < argc; i++) - { - if (first) - buffer_putc (b, ' '); - else - { - if (strmatch(argv[i]->text, "unicast") || strmatch(argv[i]->text, "multicast")) - continue; - first = 1; - } - - buffer_putstr (b, argv[i]->arg); - } - buffer_putc (b, '\0'); + rmap = route_map_lookup_by_name(rmap_str); + if (!rmap) { + vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str); + return CMD_WARNING; + } + + return bgp_show(vty, bgp, afi, safi, type, rmap, 0); +} + +static int bgp_show_community(struct vty *vty, struct bgp *bgp, int argc, + struct cmd_token **argv, int exact, afi_t afi, + safi_t safi) +{ + struct community *com; + struct buffer *b; + int i; + char *str; + int first = 0; + int ret = 0; + + b = buffer_new(1024); + for (i = 0; i < argc; i++) { + if (first) + buffer_putc(b, ' '); + else { + if (strmatch(argv[i]->text, "unicast") + || strmatch(argv[i]->text, "multicast")) + continue; + first = 1; + } - str = buffer_getstr (b); - buffer_free (b); + buffer_putstr(b, argv[i]->arg); + } + buffer_putc(b, '\0'); - com = community_str2com (str); - XFREE (MTYPE_TMP, str); - if (! com) - { - vty_out (vty, "%% Community malformed: \n"); - return CMD_WARNING; - } + str = buffer_getstr(b); + buffer_free(b); - ret = bgp_show (vty, bgp, afi, safi, - (exact ? bgp_show_type_community_exact : - bgp_show_type_community), com, 0); - community_free (com); + com = community_str2com(str); + XFREE(MTYPE_TMP, str); + if (!com) { + vty_out(vty, "%% Community malformed: \n"); + return CMD_WARNING; + } + + ret = bgp_show(vty, bgp, afi, safi, + (exact ? bgp_show_type_community_exact + : bgp_show_type_community), + com, 0); + community_free(com); - return ret; + return ret; } -static int -bgp_show_community_list (struct vty *vty, struct bgp *bgp, - const char *com, int exact, - afi_t afi, safi_t safi) +static int bgp_show_community_list(struct vty *vty, struct bgp *bgp, + const char *com, int exact, afi_t afi, + safi_t safi) { - struct community_list *list; + struct community_list *list; - list = community_list_lookup (bgp_clist, com, COMMUNITY_LIST_MASTER); - if (list == NULL) - { - vty_out (vty, "%% %s is not a valid community-list name\n",com); - return CMD_WARNING; - } + list = community_list_lookup(bgp_clist, com, COMMUNITY_LIST_MASTER); + if (list == NULL) { + vty_out(vty, "%% %s is not a valid community-list name\n", com); + return CMD_WARNING; + } - return bgp_show (vty, bgp, afi, safi, - (exact ? bgp_show_type_community_list_exact : - bgp_show_type_community_list), list, 0); + return bgp_show(vty, bgp, afi, safi, + (exact ? bgp_show_type_community_list_exact + : bgp_show_type_community_list), + list, 0); } -static int -bgp_show_prefix_longer (struct vty *vty, struct bgp *bgp, - const char *prefix, afi_t afi, - safi_t safi, enum bgp_show_type type) +static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp, + const char *prefix, afi_t afi, safi_t safi, + enum bgp_show_type type) { - int ret; - struct prefix *p; - - p = prefix_new(); + int ret; + struct prefix *p; - ret = str2prefix (prefix, p); - if (! ret) - { - vty_out (vty, "%% Malformed Prefix\n"); - return CMD_WARNING; - } + p = prefix_new(); - ret = bgp_show (vty, bgp, afi, safi, type, p, 0); - prefix_free(p); - return ret; -} + ret = str2prefix(prefix, p); + if (!ret) { + vty_out(vty, "%% Malformed Prefix\n"); + return CMD_WARNING; + } -static struct peer * -peer_lookup_in_view (struct vty *vty, struct bgp *bgp, - const char *ip_str, u_char use_json) -{ - int ret; - struct peer *peer; - union sockunion su; + ret = bgp_show(vty, bgp, afi, safi, type, p, 0); + prefix_free(p); + return ret; +} + +static struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp, + const char *ip_str, u_char use_json) +{ + int ret; + struct peer *peer; + union sockunion su; + + /* Get peer sockunion. */ + ret = str2sockunion(ip_str, &su); + if (ret < 0) { + peer = peer_lookup_by_conf_if(bgp, ip_str); + if (!peer) { + peer = peer_lookup_by_hostname(bgp, ip_str); + + if (!peer) { + if (use_json) { + json_object *json_no = NULL; + json_no = json_object_new_object(); + json_object_string_add( + json_no, + "malformedAddressOrName", + ip_str); + vty_out(vty, "%s\n", + json_object_to_json_string( + json_no)); + json_object_free(json_no); + } else + vty_out(vty, + "%% Malformed address or name: %s\n", + ip_str); + return NULL; + } + } + return peer; + } - /* Get peer sockunion. */ - ret = str2sockunion (ip_str, &su); - if (ret < 0) - { - peer = peer_lookup_by_conf_if (bgp, ip_str); - if (!peer) - { - peer = peer_lookup_by_hostname(bgp, ip_str); - - if (!peer) - { - if (use_json) - { - json_object *json_no = NULL; - json_no = json_object_new_object(); - json_object_string_add(json_no, "malformedAddressOrName", ip_str); - vty_out (vty, "%s\n", json_object_to_json_string(json_no)); - json_object_free(json_no); - } - else - vty_out (vty, "%% Malformed address or name: %s\n", ip_str); - return NULL; - } - } - return peer; - } + /* Peer structure lookup. */ + peer = peer_lookup(bgp, &su); + if (!peer) { + if (use_json) { + json_object *json_no = NULL; + json_no = json_object_new_object(); + json_object_string_add(json_no, "warning", + "No such neighbor"); + vty_out(vty, "%s\n", + json_object_to_json_string(json_no)); + json_object_free(json_no); + } else + vty_out(vty, "No such neighbor\n"); + return NULL; + } - /* Peer structure lookup. */ - peer = peer_lookup (bgp, &su); - if (! peer) - { - if (use_json) - { - json_object *json_no = NULL; - json_no = json_object_new_object(); - json_object_string_add(json_no, "warning","No such neighbor"); - vty_out (vty, "%s\n", json_object_to_json_string(json_no)); - json_object_free(json_no); - } - else - vty_out (vty, "No such neighbor\n"); - return NULL; - } - - return peer; -} - -enum bgp_stats -{ - BGP_STATS_MAXBITLEN = 0, - BGP_STATS_RIB, - BGP_STATS_PREFIXES, - BGP_STATS_TOTPLEN, - BGP_STATS_UNAGGREGATEABLE, - BGP_STATS_MAX_AGGREGATEABLE, - BGP_STATS_AGGREGATES, - BGP_STATS_SPACE, - BGP_STATS_ASPATH_COUNT, - BGP_STATS_ASPATH_MAXHOPS, - BGP_STATS_ASPATH_TOTHOPS, - BGP_STATS_ASPATH_MAXSIZE, - BGP_STATS_ASPATH_TOTSIZE, - BGP_STATS_ASN_HIGHEST, - BGP_STATS_MAX, + return peer; +} + +enum bgp_stats { + BGP_STATS_MAXBITLEN = 0, + BGP_STATS_RIB, + BGP_STATS_PREFIXES, + BGP_STATS_TOTPLEN, + BGP_STATS_UNAGGREGATEABLE, + BGP_STATS_MAX_AGGREGATEABLE, + BGP_STATS_AGGREGATES, + BGP_STATS_SPACE, + BGP_STATS_ASPATH_COUNT, + BGP_STATS_ASPATH_MAXHOPS, + BGP_STATS_ASPATH_TOTHOPS, + BGP_STATS_ASPATH_MAXSIZE, + BGP_STATS_ASPATH_TOTSIZE, + BGP_STATS_ASN_HIGHEST, + BGP_STATS_MAX, }; -static const char *table_stats_strs[] = -{ - [BGP_STATS_PREFIXES] = "Total Prefixes", - [BGP_STATS_TOTPLEN] = "Average prefix length", - [BGP_STATS_RIB] = "Total Advertisements", - [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes", - [BGP_STATS_MAX_AGGREGATEABLE] = "Maximum aggregateable prefixes", - [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements", - [BGP_STATS_SPACE] = "Address space advertised", - [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths", - [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)", - [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)", - [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)", - [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)", - [BGP_STATS_ASN_HIGHEST] = "Highest public ASN", - [BGP_STATS_MAX] = NULL, +static const char *table_stats_strs[] = { + [BGP_STATS_PREFIXES] = "Total Prefixes", + [BGP_STATS_TOTPLEN] = "Average prefix length", + [BGP_STATS_RIB] = "Total Advertisements", + [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes", + [BGP_STATS_MAX_AGGREGATEABLE] = + "Maximum aggregateable prefixes", + [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements", + [BGP_STATS_SPACE] = "Address space advertised", + [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths", + [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)", + [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)", + [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)", + [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)", + [BGP_STATS_ASN_HIGHEST] = "Highest public ASN", + [BGP_STATS_MAX] = NULL, }; -struct bgp_table_stats -{ - struct bgp_table *table; - unsigned long long counts[BGP_STATS_MAX]; +struct bgp_table_stats { + struct bgp_table *table; + unsigned long long counts[BGP_STATS_MAX]; }; #if 0 @@ -9259,43 +9307,40 @@ ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval) } #endif -static int -bgp_table_stats_walker (struct thread *t) +static int bgp_table_stats_walker(struct thread *t) { - struct bgp_node *rn; - struct bgp_node *top; - struct bgp_table_stats *ts = THREAD_ARG (t); - unsigned int space = 0; - - if (!(top = bgp_table_top (ts->table))) - return 0; + struct bgp_node *rn; + struct bgp_node *top; + struct bgp_table_stats *ts = THREAD_ARG(t); + unsigned int space = 0; - switch (top->p.family) - { - case AF_INET: - space = IPV4_MAX_BITLEN; - break; - case AF_INET6: - space = IPV6_MAX_BITLEN; - break; - } - - ts->counts[BGP_STATS_MAXBITLEN] = space; + if (!(top = bgp_table_top(ts->table))) + return 0; - for (rn = top; rn; rn = bgp_route_next (rn)) - { - struct bgp_info *ri; - struct bgp_node *prn = bgp_node_parent_nolock (rn); - unsigned int rinum = 0; - - if (rn == top) - continue; - - if (!rn->info) - continue; - - ts->counts[BGP_STATS_PREFIXES]++; - ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen; + switch (top->p.family) { + case AF_INET: + space = IPV4_MAX_BITLEN; + break; + case AF_INET6: + space = IPV6_MAX_BITLEN; + break; + } + + ts->counts[BGP_STATS_MAXBITLEN] = space; + + for (rn = top; rn; rn = bgp_route_next(rn)) { + struct bgp_info *ri; + struct bgp_node *prn = bgp_node_parent_nolock(rn); + unsigned int rinum = 0; + + if (rn == top) + continue; + + if (!rn->info) + continue; + + ts->counts[BGP_STATS_PREFIXES]++; + ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen; #if 0 ts->counts[BGP_STATS_AVGPLEN] @@ -9303,48 +9348,50 @@ bgp_table_stats_walker (struct thread *t) ts->counts[BGP_STATS_AVGPLEN], rn->p.prefixlen); #endif - - /* check if the prefix is included by any other announcements */ - while (prn && !prn->info) - prn = bgp_node_parent_nolock (prn); - - if (prn == NULL || prn == top) - { - ts->counts[BGP_STATS_UNAGGREGATEABLE]++; - /* announced address space */ - if (space) - ts->counts[BGP_STATS_SPACE] += 1 << (space - rn->p.prefixlen); - } - else if (prn->info) - ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++; - - for (ri = rn->info; ri; ri = ri->next) - { - rinum++; - ts->counts[BGP_STATS_RIB]++; - - if (ri->attr && - (CHECK_FLAG (ri->attr->flag, - ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE)))) - ts->counts[BGP_STATS_AGGREGATES]++; - - /* as-path stats */ - if (ri->attr && ri->attr->aspath) - { - unsigned int hops = aspath_count_hops (ri->attr->aspath); - unsigned int size = aspath_size (ri->attr->aspath); - as_t highest = aspath_highest (ri->attr->aspath); - - ts->counts[BGP_STATS_ASPATH_COUNT]++; - - if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS]) - ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops; - - if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE]) - ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size; - - ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops; - ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size; + + /* check if the prefix is included by any other announcements */ + while (prn && !prn->info) + prn = bgp_node_parent_nolock(prn); + + if (prn == NULL || prn == top) { + ts->counts[BGP_STATS_UNAGGREGATEABLE]++; + /* announced address space */ + if (space) + ts->counts[BGP_STATS_SPACE] += + 1 << (space - rn->p.prefixlen); + } else if (prn->info) + ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++; + + for (ri = rn->info; ri; ri = ri->next) { + rinum++; + ts->counts[BGP_STATS_RIB]++; + + if (ri->attr + && (CHECK_FLAG(ri->attr->flag, + ATTR_FLAG_BIT( + BGP_ATTR_ATOMIC_AGGREGATE)))) + ts->counts[BGP_STATS_AGGREGATES]++; + + /* as-path stats */ + if (ri->attr && ri->attr->aspath) { + unsigned int hops = + aspath_count_hops(ri->attr->aspath); + unsigned int size = + aspath_size(ri->attr->aspath); + as_t highest = aspath_highest(ri->attr->aspath); + + ts->counts[BGP_STATS_ASPATH_COUNT]++; + + if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS]) + ts->counts[BGP_STATS_ASPATH_MAXHOPS] = + hops; + + if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE]) + ts->counts[BGP_STATS_ASPATH_MAXSIZE] = + size; + + ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops; + ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size; #if 0 ts->counts[BGP_STATS_ASPATH_AVGHOPS] = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT], @@ -9355,45 +9402,42 @@ bgp_table_stats_walker (struct thread *t) ts->counts[BGP_STATS_ASPATH_AVGSIZE], size); #endif - if (highest > ts->counts[BGP_STATS_ASN_HIGHEST]) - ts->counts[BGP_STATS_ASN_HIGHEST] = highest; - } - } - } - return 0; + if (highest > ts->counts[BGP_STATS_ASN_HIGHEST]) + ts->counts[BGP_STATS_ASN_HIGHEST] = + highest; + } + } + } + return 0; } -static int -bgp_table_stats (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi) +static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi) { - struct bgp_table_stats ts; - unsigned int i; + struct bgp_table_stats ts; + unsigned int i; - if (!bgp->rib[afi][safi]) - { - vty_out (vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n", - afi, safi); - return CMD_WARNING; - } + if (!bgp->rib[afi][safi]) { + vty_out(vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n", + afi, safi); + return CMD_WARNING; + } - vty_out (vty, "BGP %s RIB statistics\n", - afi_safi_print (afi, safi)); + vty_out(vty, "BGP %s RIB statistics\n", afi_safi_print(afi, safi)); - /* labeled-unicast routes live in the unicast table */ - if (safi == SAFI_LABELED_UNICAST) - safi = SAFI_UNICAST; + /* labeled-unicast routes live in the unicast table */ + if (safi == SAFI_LABELED_UNICAST) + safi = SAFI_UNICAST; - memset (&ts, 0, sizeof (ts)); - ts.table = bgp->rib[afi][safi]; - thread_execute (bm->master, bgp_table_stats_walker, &ts, 0); + memset(&ts, 0, sizeof(ts)); + ts.table = bgp->rib[afi][safi]; + thread_execute(bm->master, bgp_table_stats_walker, &ts, 0); - for (i = 0; i < BGP_STATS_MAX; i++) - { - if (!table_stats_strs[i]) - continue; - - switch (i) - { + for (i = 0; i < BGP_STATS_MAX; i++) { + if (!table_stats_strs[i]) + continue; + + switch (i) { #if 0 case BGP_STATS_ASPATH_AVGHOPS: case BGP_STATS_ASPATH_AVGSIZE: @@ -9403,238 +9447,241 @@ bgp_table_stats (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi) (float)ts.counts[i] / (float)TALLY_SIGFIG); break; #endif - case BGP_STATS_ASPATH_TOTHOPS: - case BGP_STATS_ASPATH_TOTSIZE: - vty_out (vty, "%-30s: ", table_stats_strs[i]); - vty_out (vty, "%12.2f", - ts.counts[i] ? - (float)ts.counts[i] / - (float)ts.counts[BGP_STATS_ASPATH_COUNT] - : 0); - break; - case BGP_STATS_TOTPLEN: - vty_out (vty, "%-30s: ", table_stats_strs[i]); - vty_out (vty, "%12.2f", - ts.counts[i] ? - (float)ts.counts[i] / - (float)ts.counts[BGP_STATS_PREFIXES] - : 0); - break; - case BGP_STATS_SPACE: - vty_out (vty, "%-30s: ", table_stats_strs[i]); - vty_out (vty, "%12llu\n", ts.counts[i]); - if (ts.counts[BGP_STATS_MAXBITLEN] < 9) - break; - vty_out (vty, "%30s: ", "%% announced "); - vty_out (vty, "%12.2f\n", - 100 * (float)ts.counts[BGP_STATS_SPACE] / (float)((uint64_t)1UL << ts.counts[BGP_STATS_MAXBITLEN])); - vty_out (vty, "%30s: ", "/8 equivalent "); - vty_out (vty, "%12.2f\n", - (float)ts.counts[BGP_STATS_SPACE] / (float)(1UL << (ts.counts[BGP_STATS_MAXBITLEN] - 8))); - if (ts.counts[BGP_STATS_MAXBITLEN] < 25) - break; - vty_out (vty, "%30s: ", "/24 equivalent "); - vty_out (vty, "%12.2f", - (float)ts.counts[BGP_STATS_SPACE] / - (float)(1UL << (ts.counts[BGP_STATS_MAXBITLEN] - 24))); - break; - default: - vty_out (vty, "%-30s: ", table_stats_strs[i]); - vty_out (vty, "%12llu", ts.counts[i]); - } - - vty_out (vty, "\n"); - } - return CMD_SUCCESS; -} + case BGP_STATS_ASPATH_TOTHOPS: + case BGP_STATS_ASPATH_TOTSIZE: + vty_out(vty, "%-30s: ", table_stats_strs[i]); + vty_out(vty, "%12.2f", + ts.counts[i] + ? (float)ts.counts[i] + / (float)ts.counts + [BGP_STATS_ASPATH_COUNT] + : 0); + break; + case BGP_STATS_TOTPLEN: + vty_out(vty, "%-30s: ", table_stats_strs[i]); + vty_out(vty, "%12.2f", + ts.counts[i] + ? (float)ts.counts[i] + / (float)ts.counts + [BGP_STATS_PREFIXES] + : 0); + break; + case BGP_STATS_SPACE: + vty_out(vty, "%-30s: ", table_stats_strs[i]); + vty_out(vty, "%12llu\n", ts.counts[i]); + if (ts.counts[BGP_STATS_MAXBITLEN] < 9) + break; + vty_out(vty, "%30s: ", "%% announced "); + vty_out(vty, "%12.2f\n", + 100 * (float)ts.counts[BGP_STATS_SPACE] + / (float)((uint64_t)1UL + << ts.counts + [BGP_STATS_MAXBITLEN])); + vty_out(vty, "%30s: ", "/8 equivalent "); + vty_out(vty, "%12.2f\n", + (float)ts.counts[BGP_STATS_SPACE] + / (float)(1UL + << (ts.counts + [BGP_STATS_MAXBITLEN] + - 8))); + if (ts.counts[BGP_STATS_MAXBITLEN] < 25) + break; + vty_out(vty, "%30s: ", "/24 equivalent "); + vty_out(vty, "%12.2f", + (float)ts.counts[BGP_STATS_SPACE] + / (float)(1UL + << (ts.counts + [BGP_STATS_MAXBITLEN] + - 24))); + break; + default: + vty_out(vty, "%-30s: ", table_stats_strs[i]); + vty_out(vty, "%12llu", ts.counts[i]); + } -enum bgp_pcounts -{ - PCOUNT_ADJ_IN = 0, - PCOUNT_DAMPED, - PCOUNT_REMOVED, - PCOUNT_HISTORY, - PCOUNT_STALE, - PCOUNT_VALID, - PCOUNT_ALL, - PCOUNT_COUNTED, - PCOUNT_PFCNT, /* the figure we display to users */ - PCOUNT_MAX, + vty_out(vty, "\n"); + } + return CMD_SUCCESS; +} + +enum bgp_pcounts { + PCOUNT_ADJ_IN = 0, + PCOUNT_DAMPED, + PCOUNT_REMOVED, + PCOUNT_HISTORY, + PCOUNT_STALE, + PCOUNT_VALID, + PCOUNT_ALL, + PCOUNT_COUNTED, + PCOUNT_PFCNT, /* the figure we display to users */ + PCOUNT_MAX, }; -static const char *pcount_strs[] = -{ - [PCOUNT_ADJ_IN] = "Adj-in", - [PCOUNT_DAMPED] = "Damped", - [PCOUNT_REMOVED] = "Removed", - [PCOUNT_HISTORY] = "History", - [PCOUNT_STALE] = "Stale", - [PCOUNT_VALID] = "Valid", - [PCOUNT_ALL] = "All RIB", - [PCOUNT_COUNTED] = "PfxCt counted", - [PCOUNT_PFCNT] = "Useable", - [PCOUNT_MAX] = NULL, +static const char *pcount_strs[] = { + [PCOUNT_ADJ_IN] = "Adj-in", + [PCOUNT_DAMPED] = "Damped", + [PCOUNT_REMOVED] = "Removed", + [PCOUNT_HISTORY] = "History", + [PCOUNT_STALE] = "Stale", + [PCOUNT_VALID] = "Valid", + [PCOUNT_ALL] = "All RIB", + [PCOUNT_COUNTED] = "PfxCt counted", + [PCOUNT_PFCNT] = "Useable", + [PCOUNT_MAX] = NULL, }; -struct peer_pcounts -{ - unsigned int count[PCOUNT_MAX]; - const struct peer *peer; - const struct bgp_table *table; +struct peer_pcounts { + unsigned int count[PCOUNT_MAX]; + const struct peer *peer; + const struct bgp_table *table; }; -static int -bgp_peer_count_walker (struct thread *t) -{ - struct bgp_node *rn; - struct peer_pcounts *pc = THREAD_ARG (t); - const struct peer *peer = pc->peer; - - for (rn = bgp_table_top (pc->table); rn; rn = bgp_route_next (rn)) - { - struct bgp_adj_in *ain; - struct bgp_info *ri; - - for (ain = rn->adj_in; ain; ain = ain->next) - if (ain->peer == peer) - pc->count[PCOUNT_ADJ_IN]++; - - for (ri = rn->info; ri; ri = ri->next) - { - char buf[SU_ADDRSTRLEN]; - - if (ri->peer != peer) - continue; - - pc->count[PCOUNT_ALL]++; - - if (CHECK_FLAG (ri->flags, BGP_INFO_DAMPED)) - pc->count[PCOUNT_DAMPED]++; - if (CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) - pc->count[PCOUNT_HISTORY]++; - if (CHECK_FLAG (ri->flags, BGP_INFO_REMOVED)) - pc->count[PCOUNT_REMOVED]++; - if (CHECK_FLAG (ri->flags, BGP_INFO_STALE)) - pc->count[PCOUNT_STALE]++; - if (CHECK_FLAG (ri->flags, BGP_INFO_VALID)) - pc->count[PCOUNT_VALID]++; - if (!CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE)) - pc->count[PCOUNT_PFCNT]++; - - if (CHECK_FLAG (ri->flags, BGP_INFO_COUNTED)) - { - pc->count[PCOUNT_COUNTED]++; - if (CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE)) - zlog_warn ("%s [pcount] %s/%d is counted but flags 0x%x", - peer->host, - inet_ntop(rn->p.family, &rn->p.u.prefix, - buf, SU_ADDRSTRLEN), - rn->p.prefixlen, - ri->flags); - } - else - { - if (!CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE)) - zlog_warn ("%s [pcount] %s/%d not counted but flags 0x%x", - peer->host, - inet_ntop(rn->p.family, &rn->p.u.prefix, - buf, SU_ADDRSTRLEN), - rn->p.prefixlen, - ri->flags); - } - } - } - return 0; +static int bgp_peer_count_walker(struct thread *t) +{ + struct bgp_node *rn; + struct peer_pcounts *pc = THREAD_ARG(t); + const struct peer *peer = pc->peer; + + for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn)) { + struct bgp_adj_in *ain; + struct bgp_info *ri; + + for (ain = rn->adj_in; ain; ain = ain->next) + if (ain->peer == peer) + pc->count[PCOUNT_ADJ_IN]++; + + for (ri = rn->info; ri; ri = ri->next) { + char buf[SU_ADDRSTRLEN]; + + if (ri->peer != peer) + continue; + + pc->count[PCOUNT_ALL]++; + + if (CHECK_FLAG(ri->flags, BGP_INFO_DAMPED)) + pc->count[PCOUNT_DAMPED]++; + if (CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) + pc->count[PCOUNT_HISTORY]++; + if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) + pc->count[PCOUNT_REMOVED]++; + if (CHECK_FLAG(ri->flags, BGP_INFO_STALE)) + pc->count[PCOUNT_STALE]++; + if (CHECK_FLAG(ri->flags, BGP_INFO_VALID)) + pc->count[PCOUNT_VALID]++; + if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE)) + pc->count[PCOUNT_PFCNT]++; + + if (CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) { + pc->count[PCOUNT_COUNTED]++; + if (CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE)) + zlog_warn( + "%s [pcount] %s/%d is counted but flags 0x%x", + peer->host, + inet_ntop(rn->p.family, + &rn->p.u.prefix, buf, + SU_ADDRSTRLEN), + rn->p.prefixlen, ri->flags); + } else { + if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE)) + zlog_warn( + "%s [pcount] %s/%d not counted but flags 0x%x", + peer->host, + inet_ntop(rn->p.family, + &rn->p.u.prefix, buf, + SU_ADDRSTRLEN), + rn->p.prefixlen, ri->flags); + } + } + } + return 0; } -static int -bgp_peer_counts (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, u_char use_json) +static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi, + safi_t safi, u_char use_json) { - struct peer_pcounts pcounts = { .peer = peer }; - unsigned int i; - json_object *json = NULL; - json_object *json_loop = NULL; + struct peer_pcounts pcounts = {.peer = peer}; + unsigned int i; + json_object *json = NULL; + json_object *json_loop = NULL; - if (use_json) - { - json = json_object_new_object(); - json_loop = json_object_new_object(); - } - - if (!peer || !peer->bgp || !peer->afc[afi][safi] - || !peer->bgp->rib[afi][safi]) - { - if (use_json) - { - json_object_string_add(json, "warning", "No such neighbor or address family"); - vty_out (vty, "%s\n", json_object_to_json_string(json)); - json_object_free(json); - } - else - vty_out (vty, "%% No such neighbor or address family\n"); - - return CMD_WARNING; - } - - memset (&pcounts, 0, sizeof(pcounts)); - pcounts.peer = peer; - pcounts.table = peer->bgp->rib[afi][safi]; - - /* in-place call via thread subsystem so as to record execution time - * * stats for the thread-walk (i.e. ensure this can't be blamed on - * * on just vty_read()). - * */ - thread_execute (bm->master, bgp_peer_count_walker, &pcounts, 0); + if (use_json) { + json = json_object_new_object(); + json_loop = json_object_new_object(); + } - if (use_json) - { - json_object_string_add(json, "prefixCountsFor", peer->host); - json_object_string_add(json, "multiProtocol", afi_safi_print (afi, safi)); - json_object_int_add(json, "pfxCounter", peer->pcount[afi][safi]); - - for (i = 0; i < PCOUNT_MAX; i++) - json_object_int_add(json_loop, pcount_strs[i], pcounts.count[i]); - - json_object_object_add(json, "ribTableWalkCounters", json_loop); - - if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) - { - json_object_string_add(json, "pfxctDriftFor", peer->host); - json_object_string_add(json, "recommended", "Please report this bug, with the above command output"); - } - vty_out (vty, "%s\n", json_object_to_json_string(json)); - json_object_free(json); - } - else - { + if (!peer || !peer->bgp || !peer->afc[afi][safi] + || !peer->bgp->rib[afi][safi]) { + if (use_json) { + json_object_string_add( + json, "warning", + "No such neighbor or address family"); + vty_out(vty, "%s\n", json_object_to_json_string(json)); + json_object_free(json); + } else + vty_out(vty, "%% No such neighbor or address family\n"); + + return CMD_WARNING; + } - if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) - { - vty_out (vty, "Prefix counts for %s/%s, %s\n", - peer->hostname, peer->host,afi_safi_print(afi, safi)); - } - else - { - vty_out (vty, "Prefix counts for %s, %s\n", - peer->host, afi_safi_print(afi, safi)); - } - - vty_out (vty, "PfxCt: %ld\n", peer->pcount[afi][safi]); - vty_out (vty, "\nCounts from RIB table walk:\n\n"); - - for (i = 0; i < PCOUNT_MAX; i++) - vty_out (vty, "%20s: %-10d\n", pcount_strs[i], pcounts.count[i]); - - if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) - { - vty_out (vty, "%s [pcount] PfxCt drift!\n", - peer->host); - vty_out (vty, - "Please report this bug, with the above command output\n"); - } - } - - return CMD_SUCCESS; + memset(&pcounts, 0, sizeof(pcounts)); + pcounts.peer = peer; + pcounts.table = peer->bgp->rib[afi][safi]; + + /* in-place call via thread subsystem so as to record execution time + * * stats for the thread-walk (i.e. ensure this can't be blamed on + * * on just vty_read()). + * */ + thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0); + + if (use_json) { + json_object_string_add(json, "prefixCountsFor", peer->host); + json_object_string_add(json, "multiProtocol", + afi_safi_print(afi, safi)); + json_object_int_add(json, "pfxCounter", + peer->pcount[afi][safi]); + + for (i = 0; i < PCOUNT_MAX; i++) + json_object_int_add(json_loop, pcount_strs[i], + pcounts.count[i]); + + json_object_object_add(json, "ribTableWalkCounters", json_loop); + + if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) { + json_object_string_add(json, "pfxctDriftFor", + peer->host); + json_object_string_add( + json, "recommended", + "Please report this bug, with the above command output"); + } + vty_out(vty, "%s\n", json_object_to_json_string(json)); + json_object_free(json); + } else { + + if (peer->hostname + && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) { + vty_out(vty, "Prefix counts for %s/%s, %s\n", + peer->hostname, peer->host, + afi_safi_print(afi, safi)); + } else { + vty_out(vty, "Prefix counts for %s, %s\n", peer->host, + afi_safi_print(afi, safi)); + } + + vty_out(vty, "PfxCt: %ld\n", peer->pcount[afi][safi]); + vty_out(vty, "\nCounts from RIB table walk:\n\n"); + + for (i = 0; i < PCOUNT_MAX; i++) + vty_out(vty, "%20s: %-10d\n", pcount_strs[i], + pcounts.count[i]); + + if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) { + vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host); + vty_out(vty, + "Please report this bug, with the above command output\n"); + } + } + + return CMD_SUCCESS; } DEFUN (show_ip_bgp_instance_neighbor_prefix_counts, @@ -9654,25 +9701,27 @@ DEFUN (show_ip_bgp_instance_neighbor_prefix_counts, "Display detailed prefix count information\n" JSON_STR) { - afi_t afi = AFI_IP6; - safi_t safi = SAFI_UNICAST; - struct peer *peer; - int idx = 0; - struct bgp *bgp = NULL; + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; + struct peer *peer; + int idx = 0; + struct bgp *bgp = NULL; - bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp); - if (!idx) - return CMD_WARNING; + bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, + &bgp); + if (!idx) + return CMD_WARNING; - int uj = use_json (argc, argv); - if (uj) argc--; + int uj = use_json(argc, argv); + if (uj) + argc--; - argv_find (argv, argc, "neighbors", &idx); - peer = peer_lookup_in_view (vty, bgp, argv[idx+1]->arg, uj); - if (! peer) - return CMD_WARNING; + argv_find(argv, argc, "neighbors", &idx); + peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj); + if (!peer) + return CMD_WARNING; - return bgp_peer_counts (vty, peer, AFI_IP, SAFI_UNICAST, uj); + return bgp_peer_counts(vty, peer, AFI_IP, SAFI_UNICAST, uj); } #ifdef KEEP_OLD_VPN_COMMANDS @@ -9691,15 +9740,15 @@ DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts, "Display detailed prefix count information\n" JSON_STR) { - int idx_peer = 6; - struct peer *peer; - u_char uj = use_json(argc, argv); + int idx_peer = 6; + struct peer *peer; + u_char uj = use_json(argc, argv); - peer = peer_lookup_in_view (vty, NULL, argv[idx_peer]->arg, uj); - if (! peer) - return CMD_WARNING; - - return bgp_peer_counts (vty, peer, AFI_IP, SAFI_MPLS_VPN, uj); + peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj); + if (!peer) + return CMD_WARNING; + + return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj); } DEFUN (show_ip_bgp_vpn_all_route_prefix, @@ -9714,26 +9763,25 @@ DEFUN (show_ip_bgp_vpn_all_route_prefix, "Network in the BGP routing table to display\n" JSON_STR) { - int idx = 0; - char *network = NULL; - struct bgp *bgp = bgp_get_default(); - if (!bgp) - { - vty_out (vty, "Can't find default instance\n"); - return CMD_WARNING; - } + int idx = 0; + char *network = NULL; + struct bgp *bgp = bgp_get_default(); + if (!bgp) { + vty_out(vty, "Can't find default instance\n"); + return CMD_WARNING; + } - if (argv_find (argv, argc, "A.B.C.D", &idx)) - network = argv[idx]->arg; - else if (argv_find (argv, argc, "A.B.C.D/M", &idx)) - network = argv[idx]->arg; - else - { - vty_out (vty, "Unable to figure out Network\n"); - return CMD_WARNING; - } + if (argv_find(argv, argc, "A.B.C.D", &idx)) + network = argv[idx]->arg; + else if (argv_find(argv, argc, "A.B.C.D/M", &idx)) + network = argv[idx]->arg; + else { + vty_out(vty, "Unable to figure out Network\n"); + return CMD_WARNING; + } - return bgp_show_route (vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0, BGP_PATH_ALL, use_json(argc, argv)); + return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0, + BGP_PATH_ALL, use_json(argc, argv)); } #endif /* KEEP_OLD_VPN_COMMANDS */ @@ -9750,261 +9798,285 @@ DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix, "Network in the BGP routing table to display\n" JSON_STR) { - int idx = 0; - char *network = NULL; - - if (argv_find (argv, argc, "A.B.C.D", &idx)) - network = argv[idx]->arg; - else if (argv_find (argv, argc, "A.B.C.D/M", &idx)) - network = argv[idx]->arg; - else - { - vty_out (vty, "Unable to figure out Network\n"); - return CMD_WARNING; - } - return bgp_show_route (vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL, 0, BGP_PATH_ALL, use_json(argc, argv)); -} - - static void -show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, - int in, const char *rmap_name, u_char use_json, json_object *json) -{ - struct bgp_table *table; - struct bgp_adj_in *ain; - struct bgp_adj_out *adj; - unsigned long output_count; - unsigned long filtered_count; - struct bgp_node *rn; - int header1 = 1; - struct bgp *bgp; - int header2 = 1; - struct attr attr; - int ret; - struct update_subgroup *subgrp; - json_object *json_scode = NULL; - json_object *json_ocode = NULL; - json_object *json_ar = NULL; - struct peer_af *paf; - - if (use_json) - { - json_scode = json_object_new_object(); - json_ocode = json_object_new_object(); - json_ar = json_object_new_object(); - - json_object_string_add(json_scode, "suppressed", "s"); - json_object_string_add(json_scode, "damped", "d"); - json_object_string_add(json_scode, "history", "h"); - json_object_string_add(json_scode, "valid", "*"); - json_object_string_add(json_scode, "best", ">"); - json_object_string_add(json_scode, "multipath", "="); - json_object_string_add(json_scode, "internal", "i"); - json_object_string_add(json_scode, "ribFailure", "r"); - json_object_string_add(json_scode, "stale", "S"); - json_object_string_add(json_scode, "removed", "R"); - - json_object_string_add(json_ocode, "igp", "i"); - json_object_string_add(json_ocode, "egp", "e"); - json_object_string_add(json_ocode, "incomplete", "?"); - } - - bgp = peer->bgp; - - if (! bgp) - { - if (use_json) - { - json_object_string_add(json, "alert", "no BGP"); - vty_out (vty, "%s\n", json_object_to_json_string(json)); - json_object_free(json); - } - else - vty_out (vty, "%% No bgp\n"); - return; - } - - table = bgp->rib[afi][safi]; + int idx = 0; + char *network = NULL; - output_count = filtered_count = 0; - subgrp = peer_subgroup(peer, afi, safi); + if (argv_find(argv, argc, "A.B.C.D", &idx)) + network = argv[idx]->arg; + else if (argv_find(argv, argc, "A.B.C.D/M", &idx)) + network = argv[idx]->arg; + else { + vty_out(vty, "Unable to figure out Network\n"); + return CMD_WARNING; + } + return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL, 0, + BGP_PATH_ALL, use_json(argc, argv)); +} + +static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, + safi_t safi, int in, const char *rmap_name, + u_char use_json, json_object *json) +{ + struct bgp_table *table; + struct bgp_adj_in *ain; + struct bgp_adj_out *adj; + unsigned long output_count; + unsigned long filtered_count; + struct bgp_node *rn; + int header1 = 1; + struct bgp *bgp; + int header2 = 1; + struct attr attr; + int ret; + struct update_subgroup *subgrp; + json_object *json_scode = NULL; + json_object *json_ocode = NULL; + json_object *json_ar = NULL; + struct peer_af *paf; + + if (use_json) { + json_scode = json_object_new_object(); + json_ocode = json_object_new_object(); + json_ar = json_object_new_object(); + + json_object_string_add(json_scode, "suppressed", "s"); + json_object_string_add(json_scode, "damped", "d"); + json_object_string_add(json_scode, "history", "h"); + json_object_string_add(json_scode, "valid", "*"); + json_object_string_add(json_scode, "best", ">"); + json_object_string_add(json_scode, "multipath", "="); + json_object_string_add(json_scode, "internal", "i"); + json_object_string_add(json_scode, "ribFailure", "r"); + json_object_string_add(json_scode, "stale", "S"); + json_object_string_add(json_scode, "removed", "R"); + + json_object_string_add(json_ocode, "igp", "i"); + json_object_string_add(json_ocode, "egp", "e"); + json_object_string_add(json_ocode, "incomplete", "?"); + } - if (!in && subgrp && CHECK_FLAG (subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) - { - if (use_json) - { - json_object_int_add(json, "bgpTableVersion", table->version); - json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id)); - json_object_object_add(json, "bgpStatusCodes", json_scode); - json_object_object_add(json, "bgpOriginCodes", json_ocode); - json_object_string_add(json, "bgpOriginatingDefaultNetwork", "0.0.0.0"); - } - else - { - vty_out (vty, "BGP table version is %" PRIu64 ", local router ID is %s\n", table->version, - inet_ntoa(bgp->router_id)); - vty_out (vty, BGP_SHOW_SCODE_HEADER); - vty_out (vty, BGP_SHOW_OCODE_HEADER); - - vty_out (vty, "Originating default network 0.0.0.0\n\n"); - } - header1 = 0; - } + bgp = peer->bgp; - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - { - if (in) - { - for (ain = rn->adj_in; ain; ain = ain->next) - { - if (ain->peer == peer) - { - if (header1) - { - if (use_json) - { - json_object_int_add(json, "bgpTableVersion", 0); - json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id)); - json_object_object_add(json, "bgpStatusCodes", json_scode); - json_object_object_add(json, "bgpOriginCodes", json_ocode); - } - else - { - vty_out (vty, "BGP table version is 0, local router ID is %s\n", - inet_ntoa(bgp->router_id)); - vty_out (vty, BGP_SHOW_SCODE_HEADER); - vty_out (vty, BGP_SHOW_OCODE_HEADER); - } - header1 = 0; - } - if (header2) - { - if (!use_json) - vty_out (vty, BGP_SHOW_HEADER); - header2 = 0; - } - if (ain->attr) - { - bgp_attr_dup(&attr, ain->attr); - if (bgp_input_modifier(peer, &rn->p, &attr, afi, safi, rmap_name) != RMAP_DENY) - { - route_vty_out_tmp (vty, &rn->p, &attr, safi, use_json, json_ar); - output_count++; - } - else - filtered_count++; - } - } - } - } - else - { - for (adj = rn->adj_out; adj; adj = adj->next) - SUBGRP_FOREACH_PEER(adj->subgroup, paf) - if (paf->peer == peer) - { - if (header1) - { - if (use_json) - { - json_object_int_add(json, "bgpTableVersion", table->version); - json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id)); - json_object_object_add(json, "bgpStatusCodes", json_scode); - json_object_object_add(json, "bgpOriginCodes", json_ocode); - } - else - { - vty_out (vty, "BGP table version is %" PRIu64 ", local router ID is %s\n", table->version, - inet_ntoa(bgp->router_id)); - vty_out (vty, BGP_SHOW_SCODE_HEADER); - vty_out (vty, BGP_SHOW_OCODE_HEADER); - } - header1 = 0; - } - - if (header2) - { - if (!use_json) - vty_out (vty, BGP_SHOW_HEADER); - header2 = 0; - } - - if (adj->attr) - { - bgp_attr_dup(&attr, adj->attr); - ret = bgp_output_modifier(peer, &rn->p, &attr, afi, safi, rmap_name); - if (ret != RMAP_DENY) - { - route_vty_out_tmp (vty, &rn->p, &attr, safi, use_json, json_ar); - output_count++; - } - else - filtered_count++; - } - } - } - } - if (use_json) - json_object_object_add(json, "advertisedRoutes", json_ar); + if (!bgp) { + if (use_json) { + json_object_string_add(json, "alert", "no BGP"); + vty_out(vty, "%s\n", json_object_to_json_string(json)); + json_object_free(json); + } else + vty_out(vty, "%% No bgp\n"); + return; + } - if (output_count != 0) - { - if (use_json) - json_object_int_add(json, "totalPrefixCounter", output_count); - else - vty_out (vty, "\nTotal number of prefixes %ld\n", output_count); - } - if (use_json) - { - vty_out (vty, "%s\n", json_object_to_json_string(json)); - json_object_free(json); - } + table = bgp->rib[afi][safi]; + + output_count = filtered_count = 0; + subgrp = peer_subgroup(peer, afi, safi); + + if (!in && subgrp + && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) { + if (use_json) { + json_object_int_add(json, "bgpTableVersion", + table->version); + json_object_string_add(json, "bgpLocalRouterId", + inet_ntoa(bgp->router_id)); + json_object_object_add(json, "bgpStatusCodes", + json_scode); + json_object_object_add(json, "bgpOriginCodes", + json_ocode); + json_object_string_add(json, + "bgpOriginatingDefaultNetwork", + "0.0.0.0"); + } else { + vty_out(vty, "BGP table version is %" PRIu64 + ", local router ID is %s\n", + table->version, inet_ntoa(bgp->router_id)); + vty_out(vty, BGP_SHOW_SCODE_HEADER); + vty_out(vty, BGP_SHOW_OCODE_HEADER); + + vty_out(vty, "Originating default network 0.0.0.0\n\n"); + } + header1 = 0; + } + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { + if (in) { + for (ain = rn->adj_in; ain; ain = ain->next) { + if (ain->peer == peer) { + if (header1) { + if (use_json) { + json_object_int_add( + json, + "bgpTableVersion", + 0); + json_object_string_add( + json, + "bgpLocalRouterId", + inet_ntoa( + bgp->router_id)); + json_object_object_add( + json, + "bgpStatusCodes", + json_scode); + json_object_object_add( + json, + "bgpOriginCodes", + json_ocode); + } else { + vty_out(vty, + "BGP table version is 0, local router ID is %s\n", + inet_ntoa( + bgp->router_id)); + vty_out(vty, + BGP_SHOW_SCODE_HEADER); + vty_out(vty, + BGP_SHOW_OCODE_HEADER); + } + header1 = 0; + } + if (header2) { + if (!use_json) + vty_out(vty, + BGP_SHOW_HEADER); + header2 = 0; + } + if (ain->attr) { + bgp_attr_dup(&attr, ain->attr); + if (bgp_input_modifier( + peer, &rn->p, &attr, + afi, safi, + rmap_name) + != RMAP_DENY) { + route_vty_out_tmp( + vty, &rn->p, + &attr, safi, + use_json, + json_ar); + output_count++; + } else + filtered_count++; + } + } + } + } else { + for (adj = rn->adj_out; adj; adj = adj->next) + SUBGRP_FOREACH_PEER(adj->subgroup, paf) + if (paf->peer == peer) { + if (header1) { + if (use_json) { + json_object_int_add( + json, "bgpTableVersion", + table->version); + json_object_string_add( + json, + "bgpLocalRouterId", + inet_ntoa( + bgp->router_id)); + json_object_object_add( + json, "bgpStatusCodes", + json_scode); + json_object_object_add( + json, "bgpOriginCodes", + json_ocode); + } else { + vty_out(vty, + "BGP table version is %" PRIu64 + ", local router ID is %s\n", + table->version, + inet_ntoa( + bgp->router_id)); + vty_out(vty, + BGP_SHOW_SCODE_HEADER); + vty_out(vty, + BGP_SHOW_OCODE_HEADER); + } + header1 = 0; + } + + if (header2) { + if (!use_json) + vty_out(vty, BGP_SHOW_HEADER); + header2 = 0; + } + + if (adj->attr) { + bgp_attr_dup(&attr, adj->attr); + ret = bgp_output_modifier( + peer, &rn->p, &attr, afi, safi, + rmap_name); + if (ret != RMAP_DENY) { + route_vty_out_tmp(vty, &rn->p, + &attr, safi, + use_json, + json_ar); + output_count++; + } else + filtered_count++; + } + } + } + } + if (use_json) + json_object_object_add(json, "advertisedRoutes", json_ar); + + if (output_count != 0) { + if (use_json) + json_object_int_add(json, "totalPrefixCounter", + output_count); + else + vty_out(vty, "\nTotal number of prefixes %ld\n", + output_count); + } + if (use_json) { + vty_out(vty, "%s\n", json_object_to_json_string(json)); + json_object_free(json); + } } -static int -peer_adj_routes (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, - int in, const char *rmap_name, u_char use_json) +static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi, + safi_t safi, int in, const char *rmap_name, + u_char use_json) { - json_object *json = NULL; + json_object *json = NULL; - if (use_json) - json = json_object_new_object(); + if (use_json) + json = json_object_new_object(); - /* labeled-unicast routes live in the unicast table */ - if (safi == SAFI_LABELED_UNICAST) - safi = SAFI_UNICAST; + /* labeled-unicast routes live in the unicast table */ + if (safi == SAFI_LABELED_UNICAST) + safi = SAFI_UNICAST; - if (!peer || !peer->afc[afi][safi]) - { - if (use_json) - { - json_object_string_add(json, "warning", "No such neighbor or address family"); - vty_out (vty, "%s\n", json_object_to_json_string(json)); - json_object_free(json); - } - else - vty_out (vty, "%% No such neighbor or address family\n"); - - return CMD_WARNING; - } + if (!peer || !peer->afc[afi][safi]) { + if (use_json) { + json_object_string_add( + json, "warning", + "No such neighbor or address family"); + vty_out(vty, "%s\n", json_object_to_json_string(json)); + json_object_free(json); + } else + vty_out(vty, "%% No such neighbor or address family\n"); - if (in && !CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)) - { - if (use_json) - { - json_object_string_add(json, "warning", "Inbound soft reconfiguration not enabled"); - vty_out (vty, "%s\n", json_object_to_json_string(json)); - json_object_free(json); - } - else - vty_out (vty, "%% Inbound soft reconfiguration not enabled\n"); - - return CMD_WARNING; - } + return CMD_WARNING; + } + + if (in + && !CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_SOFT_RECONFIG)) { + if (use_json) { + json_object_string_add( + json, "warning", + "Inbound soft reconfiguration not enabled"); + vty_out(vty, "%s\n", json_object_to_json_string(json)); + json_object_free(json); + } else + vty_out(vty, + "%% Inbound soft reconfiguration not enabled\n"); + + return CMD_WARNING; + } - show_adj_route (vty, peer, afi, safi, in, rmap_name, use_json, json); + show_adj_route(vty, peer, afi, safi, in, rmap_name, use_json, json); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_bgp_instance_neighbor_advertised_route, @@ -10027,39 +10099,41 @@ DEFUN (show_ip_bgp_instance_neighbor_advertised_route, "Name of the route map\n" JSON_STR) { - afi_t afi = AFI_IP6; - safi_t safi = SAFI_UNICAST; - char *rmap_name = NULL; - char *peerstr = NULL; - int rcvd = 0; - struct bgp *bgp = NULL; - struct peer *peer; + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; + char *rmap_name = NULL; + char *peerstr = NULL; + int rcvd = 0; + struct bgp *bgp = NULL; + struct peer *peer; - int idx = 0; + int idx = 0; - bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp); - if (!idx) - return CMD_WARNING; + bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, + &bgp); + if (!idx) + return CMD_WARNING; - int uj = use_json (argc, argv); - if (uj) argc--; + int uj = use_json(argc, argv); + if (uj) + argc--; - /* neighbors */ - argv_find (argv, argc, "neighbors", &idx); - peerstr = argv[++idx]->arg; + /* neighbors */ + argv_find(argv, argc, "neighbors", &idx); + peerstr = argv[++idx]->arg; - peer = peer_lookup_in_view (vty, bgp, peerstr, uj); - if (! peer) - return CMD_WARNING; + peer = peer_lookup_in_view(vty, bgp, peerstr, uj); + if (!peer) + return CMD_WARNING; - if (argv_find (argv, argc, "received-routes", &idx)) - rcvd = 1; - if (argv_find (argv, argc, "advertised-routes", &idx)) - rcvd = 0; - if (argv_find (argv, argc, "route-map", &idx)) - rmap_name = argv[++idx]->arg; + if (argv_find(argv, argc, "received-routes", &idx)) + rcvd = 1; + if (argv_find(argv, argc, "advertised-routes", &idx)) + rcvd = 0; + if (argv_find(argv, argc, "route-map", &idx)) + rmap_name = argv[++idx]->arg; - return peer_adj_routes (vty, peer, afi, safi, rcvd, rmap_name, uj); + return peer_adj_routes(vty, peer, afi, safi, rcvd, rmap_name, uj); } DEFUN (show_ip_bgp_neighbor_received_prefix_filter, @@ -10079,100 +10153,95 @@ DEFUN (show_ip_bgp_neighbor_received_prefix_filter, "Display the prefixlist filter\n" JSON_STR) { - afi_t afi = AFI_IP6; - safi_t safi = SAFI_UNICAST; - char *peerstr = NULL; - - char name[BUFSIZ]; - union sockunion su; - struct peer *peer; - int count, ret; - - int idx = 0; - - /* show [ip] bgp */ - if (argv_find (argv, argc, "ip", &idx)) - afi = AFI_IP; - /* [ [unicast]] */ - if (argv_find (argv, argc, "ipv4", &idx)) - afi = AFI_IP; - if (argv_find (argv, argc, "ipv6", &idx)) - afi = AFI_IP6; - /* neighbors */ - argv_find (argv, argc, "neighbors", &idx); - peerstr = argv[++idx]->arg; - - u_char uj = use_json(argc, argv); - - ret = str2sockunion (peerstr, &su); - if (ret < 0) - { - peer = peer_lookup_by_conf_if (NULL, peerstr); - if (! peer) - { - if (uj) - vty_out (vty, "{}\n"); - else - vty_out (vty, "%% Malformed address or name: %s\n", peerstr); - return CMD_WARNING; - } - } - else - { - peer = peer_lookup (NULL, &su); - if (! peer) - { - if (uj) - vty_out (vty, "{}\n"); - else - vty_out (vty, "No peer\n"); - return CMD_WARNING; - } - } - - sprintf (name, "%s.%d.%d", peer->host, afi, safi); - count = prefix_bgp_show_prefix_list (NULL, afi, name, uj); - if (count) - { - if (!uj) - vty_out (vty, "Address Family: %s\n", afi_safi_print(afi, safi)); - prefix_bgp_show_prefix_list (vty, afi, name, uj); - } - else - { - if (uj) - vty_out (vty, "{}\n"); - else - vty_out (vty, "No functional output\n"); - } + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; + char *peerstr = NULL; + + char name[BUFSIZ]; + union sockunion su; + struct peer *peer; + int count, ret; + + int idx = 0; + + /* show [ip] bgp */ + if (argv_find(argv, argc, "ip", &idx)) + afi = AFI_IP; + /* [ [unicast]] */ + if (argv_find(argv, argc, "ipv4", &idx)) + afi = AFI_IP; + if (argv_find(argv, argc, "ipv6", &idx)) + afi = AFI_IP6; + /* neighbors */ + argv_find(argv, argc, "neighbors", &idx); + peerstr = argv[++idx]->arg; + + u_char uj = use_json(argc, argv); + + ret = str2sockunion(peerstr, &su); + if (ret < 0) { + peer = peer_lookup_by_conf_if(NULL, peerstr); + if (!peer) { + if (uj) + vty_out(vty, "{}\n"); + else + vty_out(vty, + "%% Malformed address or name: %s\n", + peerstr); + return CMD_WARNING; + } + } else { + peer = peer_lookup(NULL, &su); + if (!peer) { + if (uj) + vty_out(vty, "{}\n"); + else + vty_out(vty, "No peer\n"); + return CMD_WARNING; + } + } - return CMD_SUCCESS; -} + sprintf(name, "%s.%d.%d", peer->host, afi, safi); + count = prefix_bgp_show_prefix_list(NULL, afi, name, uj); + if (count) { + if (!uj) + vty_out(vty, "Address Family: %s\n", + afi_safi_print(afi, safi)); + prefix_bgp_show_prefix_list(vty, afi, name, uj); + } else { + if (uj) + vty_out(vty, "{}\n"); + else + vty_out(vty, "No functional output\n"); + } -static int -bgp_show_neighbor_route (struct vty *vty, struct peer *peer, afi_t afi, - safi_t safi, enum bgp_show_type type, u_char use_json) -{ - if (! peer || ! peer->afc[afi][safi]) - { - if (use_json) - { - json_object *json_no = NULL; - json_no = json_object_new_object(); - json_object_string_add(json_no, "warning", "No such neighbor or address family"); - vty_out (vty, "%s\n", json_object_to_json_string(json_no)); - json_object_free(json_no); - } - else - vty_out (vty, "%% No such neighbor or address family\n"); - return CMD_WARNING; - } + return CMD_SUCCESS; +} + +static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer, + afi_t afi, safi_t safi, + enum bgp_show_type type, u_char use_json) +{ + if (!peer || !peer->afc[afi][safi]) { + if (use_json) { + json_object *json_no = NULL; + json_no = json_object_new_object(); + json_object_string_add( + json_no, "warning", + "No such neighbor or address family"); + vty_out(vty, "%s\n", + json_object_to_json_string(json_no)); + json_object_free(json_no); + } else + vty_out(vty, "%% No such neighbor or address family\n"); + return CMD_WARNING; + } - /* labeled-unicast routes live in the unicast table */ - if (safi == SAFI_LABELED_UNICAST) - safi = SAFI_UNICAST; + /* labeled-unicast routes live in the unicast table */ + if (safi == SAFI_LABELED_UNICAST) + safi = SAFI_UNICAST; - return bgp_show (vty, peer->bgp, afi, safi, type, &peer->su, use_json); + return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json); } DEFUN (show_ip_bgp_neighbor_routes, @@ -10194,52 +10263,52 @@ DEFUN (show_ip_bgp_neighbor_routes, "Display routes learned from neighbor\n" JSON_STR) { - char *peerstr = NULL; - struct bgp *bgp = NULL; - afi_t afi = AFI_IP6; - safi_t safi = SAFI_UNICAST; - struct peer *peer; - enum bgp_show_type sh_type = bgp_show_type_neighbor; + char *peerstr = NULL; + struct bgp *bgp = NULL; + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; + struct peer *peer; + enum bgp_show_type sh_type = bgp_show_type_neighbor; - int idx = 0; + int idx = 0; - bgp_vty_find_and_parse_afi_safi_bgp (vty, argv, argc, &idx, &afi, &safi, &bgp); - if (!idx) - return CMD_WARNING; + bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, + &bgp); + if (!idx) + return CMD_WARNING; - int uj = use_json (argc, argv); - if (uj) argc--; + int uj = use_json(argc, argv); + if (uj) + argc--; - /* neighbors */ - argv_find (argv, argc, "neighbors", &idx); - peerstr = argv[++idx]->arg; + /* neighbors */ + argv_find(argv, argc, "neighbors", &idx); + peerstr = argv[++idx]->arg; - peer = peer_lookup_in_view (vty, bgp, peerstr, uj); - if (! peer) - { - vty_out (vty, "No such neighbor\n"); - return CMD_WARNING; - } + peer = peer_lookup_in_view(vty, bgp, peerstr, uj); + if (!peer) { + vty_out(vty, "No such neighbor\n"); + return CMD_WARNING; + } - if (argv_find (argv, argc, "flap-statistics", &idx)) - sh_type = bgp_show_type_flap_neighbor; - else if (argv_find (argv, argc, "dampened-routes", &idx)) - sh_type = bgp_show_type_damp_neighbor; - else if (argv_find (argv, argc, "routes", &idx)) - sh_type = bgp_show_type_neighbor; + if (argv_find(argv, argc, "flap-statistics", &idx)) + sh_type = bgp_show_type_flap_neighbor; + else if (argv_find(argv, argc, "dampened-routes", &idx)) + sh_type = bgp_show_type_damp_neighbor; + else if (argv_find(argv, argc, "routes", &idx)) + sh_type = bgp_show_type_neighbor; - return bgp_show_neighbor_route (vty, peer, afi, safi, sh_type, uj); + return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj); } struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX]; -struct bgp_distance -{ - /* Distance value for the IP source prefix. */ - u_char distance; +struct bgp_distance { + /* Distance value for the IP source prefix. */ + u_char distance; - /* Name of the access-list to be matched. */ - char *access_list; + /* Name of the access-list to be matched. */ + char *access_list; }; DEFUN (show_bgp_afi_vpn_rd_route, @@ -10255,197 +10324,179 @@ DEFUN (show_bgp_afi_vpn_rd_route, "Network in the BGP routing table to display\n" JSON_STR) { - int ret; - struct prefix_rd prd; - afi_t afi = AFI_MAX; - int idx = 0; + int ret; + struct prefix_rd prd; + afi_t afi = AFI_MAX; + int idx = 0; - argv_find_and_parse_afi (argv, argc, &idx, &afi); - ret = str2prefix_rd (argv[5]->arg, &prd); - if (! ret) - { - vty_out (vty, "%% Malformed Route Distinguisher\n"); - return CMD_WARNING; - } - return bgp_show_route (vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd, 0, BGP_PATH_ALL, use_json (argc, argv)); + argv_find_and_parse_afi(argv, argc, &idx, &afi); + ret = str2prefix_rd(argv[5]->arg, &prd); + if (!ret) { + vty_out(vty, "%% Malformed Route Distinguisher\n"); + return CMD_WARNING; + } + return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd, + 0, BGP_PATH_ALL, use_json(argc, argv)); } -static struct bgp_distance * -bgp_distance_new (void) +static struct bgp_distance *bgp_distance_new(void) { - return XCALLOC (MTYPE_BGP_DISTANCE, sizeof (struct bgp_distance)); + return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance)); } -static void -bgp_distance_free (struct bgp_distance *bdistance) +static void bgp_distance_free(struct bgp_distance *bdistance) { - XFREE (MTYPE_BGP_DISTANCE, bdistance); + XFREE(MTYPE_BGP_DISTANCE, bdistance); } -static int -bgp_distance_set (struct vty *vty, const char *distance_str, - const char *ip_str, const char *access_list_str) +static int bgp_distance_set(struct vty *vty, const char *distance_str, + const char *ip_str, const char *access_list_str) { - int ret; - afi_t afi; - safi_t safi; - struct prefix p; - u_char distance; - struct bgp_node *rn; - struct bgp_distance *bdistance; + int ret; + afi_t afi; + safi_t safi; + struct prefix p; + u_char distance; + struct bgp_node *rn; + struct bgp_distance *bdistance; - afi = bgp_node_afi (vty); - safi = bgp_node_safi (vty); + afi = bgp_node_afi(vty); + safi = bgp_node_safi(vty); - ret = str2prefix (ip_str, &p); - if (ret == 0) - { - vty_out (vty, "Malformed prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = str2prefix(ip_str, &p); + if (ret == 0) { + vty_out(vty, "Malformed prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } - distance = atoi (distance_str); + distance = atoi(distance_str); - /* Get BGP distance node. */ - rn = bgp_node_get (bgp_distance_table[afi][safi], (struct prefix *) &p); - if (rn->info) - { - bdistance = rn->info; - bgp_unlock_node (rn); - } - else - { - bdistance = bgp_distance_new (); - rn->info = bdistance; - } + /* Get BGP distance node. */ + rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p); + if (rn->info) { + bdistance = rn->info; + bgp_unlock_node(rn); + } else { + bdistance = bgp_distance_new(); + rn->info = bdistance; + } - /* Set distance value. */ - bdistance->distance = distance; + /* Set distance value. */ + bdistance->distance = distance; - /* Reset access-list configuration. */ - if (bdistance->access_list) - { - XFREE(MTYPE_AS_LIST, bdistance->access_list); - bdistance->access_list = NULL; - } - if (access_list_str) - bdistance->access_list = XSTRDUP(MTYPE_AS_LIST, access_list_str); + /* Reset access-list configuration. */ + if (bdistance->access_list) { + XFREE(MTYPE_AS_LIST, bdistance->access_list); + bdistance->access_list = NULL; + } + if (access_list_str) + bdistance->access_list = + XSTRDUP(MTYPE_AS_LIST, access_list_str); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -bgp_distance_unset (struct vty *vty, const char *distance_str, - const char *ip_str, const char *access_list_str) +static int bgp_distance_unset(struct vty *vty, const char *distance_str, + const char *ip_str, const char *access_list_str) { - int ret; - afi_t afi; - safi_t safi; - struct prefix p; - int distance; - struct bgp_node *rn; - struct bgp_distance *bdistance; + int ret; + afi_t afi; + safi_t safi; + struct prefix p; + int distance; + struct bgp_node *rn; + struct bgp_distance *bdistance; - afi = bgp_node_afi (vty); - safi = bgp_node_safi (vty); + afi = bgp_node_afi(vty); + safi = bgp_node_safi(vty); - ret = str2prefix (ip_str, &p); - if (ret == 0) - { - vty_out (vty, "Malformed prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = str2prefix(ip_str, &p); + if (ret == 0) { + vty_out(vty, "Malformed prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } - rn = bgp_node_lookup (bgp_distance_table[afi][safi], (struct prefix *)&p); - if (! rn) - { - vty_out (vty, "Can't find specified prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } + rn = bgp_node_lookup(bgp_distance_table[afi][safi], + (struct prefix *)&p); + if (!rn) { + vty_out(vty, "Can't find specified prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } - bdistance = rn->info; - distance = atoi(distance_str); + bdistance = rn->info; + distance = atoi(distance_str); - if (bdistance->distance != distance) - { - vty_out (vty, "Distance does not match configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (bdistance->distance != distance) { + vty_out(vty, "Distance does not match configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (bdistance->access_list) - XFREE(MTYPE_AS_LIST, bdistance->access_list); - bgp_distance_free (bdistance); + if (bdistance->access_list) + XFREE(MTYPE_AS_LIST, bdistance->access_list); + bgp_distance_free(bdistance); - rn->info = NULL; - bgp_unlock_node (rn); - bgp_unlock_node (rn); + rn->info = NULL; + bgp_unlock_node(rn); + bgp_unlock_node(rn); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Apply BGP information to distance method. */ -u_char -bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, afi_t afi, - safi_t safi, struct bgp *bgp) -{ - struct bgp_node *rn; - struct prefix q; - struct peer *peer; - struct bgp_distance *bdistance; - struct access_list *alist; - struct bgp_static *bgp_static; - - if (! bgp) - return 0; - - peer = rinfo->peer; - - /* Check source address. */ - sockunion2hostprefix (&peer->su, &q); - rn = bgp_node_match (bgp_distance_table[afi][safi], &q); - if (rn) - { - bdistance = rn->info; - bgp_unlock_node (rn); - - if (bdistance->access_list) - { - alist = access_list_lookup (afi, bdistance->access_list); - if (alist && access_list_apply (alist, p) == FILTER_PERMIT) - return bdistance->distance; +u_char bgp_distance_apply(struct prefix *p, struct bgp_info *rinfo, afi_t afi, + safi_t safi, struct bgp *bgp) +{ + struct bgp_node *rn; + struct prefix q; + struct peer *peer; + struct bgp_distance *bdistance; + struct access_list *alist; + struct bgp_static *bgp_static; + + if (!bgp) + return 0; + + peer = rinfo->peer; + + /* Check source address. */ + sockunion2hostprefix(&peer->su, &q); + rn = bgp_node_match(bgp_distance_table[afi][safi], &q); + if (rn) { + bdistance = rn->info; + bgp_unlock_node(rn); + + if (bdistance->access_list) { + alist = access_list_lookup(afi, bdistance->access_list); + if (alist + && access_list_apply(alist, p) == FILTER_PERMIT) + return bdistance->distance; + } else + return bdistance->distance; } - else - return bdistance->distance; - } - /* Backdoor check. */ - rn = bgp_node_lookup (bgp->route[afi][safi], p); - if (rn) - { - bgp_static = rn->info; - bgp_unlock_node (rn); + /* Backdoor check. */ + rn = bgp_node_lookup(bgp->route[afi][safi], p); + if (rn) { + bgp_static = rn->info; + bgp_unlock_node(rn); - if (bgp_static->backdoor) - { - if (bgp->distance_local[afi][safi]) - return bgp->distance_local[afi][safi]; - else - return ZEBRA_IBGP_DISTANCE_DEFAULT; + if (bgp_static->backdoor) { + if (bgp->distance_local[afi][safi]) + return bgp->distance_local[afi][safi]; + else + return ZEBRA_IBGP_DISTANCE_DEFAULT; + } } - } - if (peer->sort == BGP_PEER_EBGP) - { - if (bgp->distance_ebgp[afi][safi]) - return bgp->distance_ebgp[afi][safi]; - return ZEBRA_EBGP_DISTANCE_DEFAULT; - } - else - { - if (bgp->distance_ibgp[afi][safi]) - return bgp->distance_ibgp[afi][safi]; - return ZEBRA_IBGP_DISTANCE_DEFAULT; - } + if (peer->sort == BGP_PEER_EBGP) { + if (bgp->distance_ebgp[afi][safi]) + return bgp->distance_ebgp[afi][safi]; + return ZEBRA_EBGP_DISTANCE_DEFAULT; + } else { + if (bgp->distance_ibgp[afi][safi]) + return bgp->distance_ibgp[afi][safi]; + return ZEBRA_IBGP_DISTANCE_DEFAULT; + } } DEFUN (bgp_distance, @@ -10457,20 +10508,20 @@ DEFUN (bgp_distance, "Distance for routes internal to the AS\n" "Distance for local routes\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_number = 2; - int idx_number_2 = 3; - int idx_number_3 = 4; - afi_t afi; - safi_t safi; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_number = 2; + int idx_number_2 = 3; + int idx_number_3 = 4; + afi_t afi; + safi_t safi; - afi = bgp_node_afi (vty); - safi = bgp_node_safi (vty); + afi = bgp_node_afi(vty); + safi = bgp_node_safi(vty); - bgp->distance_ebgp[afi][safi] = atoi (argv[idx_number]->arg); - bgp->distance_ibgp[afi][safi] = atoi (argv[idx_number_2]->arg); - bgp->distance_local[afi][safi] = atoi (argv[idx_number_3]->arg); - return CMD_SUCCESS; + bgp->distance_ebgp[afi][safi] = atoi(argv[idx_number]->arg); + bgp->distance_ibgp[afi][safi] = atoi(argv[idx_number_2]->arg); + bgp->distance_local[afi][safi] = atoi(argv[idx_number_3]->arg); + return CMD_SUCCESS; } DEFUN (no_bgp_distance, @@ -10483,17 +10534,17 @@ DEFUN (no_bgp_distance, "Distance for routes internal to the AS\n" "Distance for local routes\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - afi_t afi; - safi_t safi; + VTY_DECLVAR_CONTEXT(bgp, bgp); + afi_t afi; + safi_t safi; - afi = bgp_node_afi (vty); - safi = bgp_node_safi (vty); + afi = bgp_node_afi(vty); + safi = bgp_node_safi(vty); - bgp->distance_ebgp[afi][safi] = 0; - bgp->distance_ibgp[afi][safi] = 0; - bgp->distance_local[afi][safi] = 0; - return CMD_SUCCESS; + bgp->distance_ebgp[afi][safi] = 0; + bgp->distance_ibgp[afi][safi] = 0; + bgp->distance_local[afi][safi] = 0; + return CMD_SUCCESS; } @@ -10504,10 +10555,11 @@ DEFUN (bgp_distance_source, "Administrative distance\n" "IP source prefix\n") { - int idx_number = 1; - int idx_ipv4_prefixlen = 2; - bgp_distance_set (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, NULL); - return CMD_SUCCESS; + int idx_number = 1; + int idx_ipv4_prefixlen = 2; + bgp_distance_set(vty, argv[idx_number]->arg, + argv[idx_ipv4_prefixlen]->arg, NULL); + return CMD_SUCCESS; } DEFUN (no_bgp_distance_source, @@ -10518,10 +10570,11 @@ DEFUN (no_bgp_distance_source, "Administrative distance\n" "IP source prefix\n") { - int idx_number = 2; - int idx_ipv4_prefixlen = 3; - bgp_distance_unset (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, NULL); - return CMD_SUCCESS; + int idx_number = 2; + int idx_ipv4_prefixlen = 3; + bgp_distance_unset(vty, argv[idx_number]->arg, + argv[idx_ipv4_prefixlen]->arg, NULL); + return CMD_SUCCESS; } DEFUN (bgp_distance_source_access_list, @@ -10532,11 +10585,12 @@ DEFUN (bgp_distance_source_access_list, "IP source prefix\n" "Access list name\n") { - int idx_number = 1; - int idx_ipv4_prefixlen = 2; - int idx_word = 3; - bgp_distance_set (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg); - return CMD_SUCCESS; + int idx_number = 1; + int idx_ipv4_prefixlen = 2; + int idx_word = 3; + bgp_distance_set(vty, argv[idx_number]->arg, + argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg); + return CMD_SUCCESS; } DEFUN (no_bgp_distance_source_access_list, @@ -10548,11 +10602,12 @@ DEFUN (no_bgp_distance_source_access_list, "IP source prefix\n" "Access list name\n") { - int idx_number = 2; - int idx_ipv4_prefixlen = 3; - int idx_word = 4; - bgp_distance_unset (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg); - return CMD_SUCCESS; + int idx_number = 2; + int idx_ipv4_prefixlen = 3; + int idx_word = 4; + bgp_distance_unset(vty, argv[idx_number]->arg, + argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg); + return CMD_SUCCESS; } DEFUN (ipv6_bgp_distance_source, @@ -10562,8 +10617,8 @@ DEFUN (ipv6_bgp_distance_source, "Administrative distance\n" "IP source prefix\n") { - bgp_distance_set (vty, argv[1]->arg, argv[2]->arg, NULL); - return CMD_SUCCESS; + bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL); + return CMD_SUCCESS; } DEFUN (no_ipv6_bgp_distance_source, @@ -10574,8 +10629,8 @@ DEFUN (no_ipv6_bgp_distance_source, "Administrative distance\n" "IP source prefix\n") { - bgp_distance_unset (vty, argv[2]->arg, argv[3]->arg, NULL); - return CMD_SUCCESS; + bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL); + return CMD_SUCCESS; } DEFUN (ipv6_bgp_distance_source_access_list, @@ -10586,8 +10641,8 @@ DEFUN (ipv6_bgp_distance_source_access_list, "IP source prefix\n" "Access list name\n") { - bgp_distance_set (vty, argv[1]->arg, argv[2]->arg, argv[3]->arg); - return CMD_SUCCESS; + bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg); + return CMD_SUCCESS; } DEFUN (no_ipv6_bgp_distance_source_access_list, @@ -10599,8 +10654,8 @@ DEFUN (no_ipv6_bgp_distance_source_access_list, "IP source prefix\n" "Access list name\n") { - bgp_distance_unset (vty, argv[2]->arg, argv[3]->arg, argv[4]->arg); - return CMD_SUCCESS; + bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg); + return CMD_SUCCESS; } DEFUN (bgp_damp_set, @@ -10613,37 +10668,34 @@ DEFUN (bgp_damp_set, "Value to start suppressing a route\n" "Maximum duration to suppress a stable route\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_half_life = 2; - int idx_reuse = 3; - int idx_suppress = 4; - int idx_max_suppress = 5; - int half = DEFAULT_HALF_LIFE * 60; - int reuse = DEFAULT_REUSE; - int suppress = DEFAULT_SUPPRESS; - int max = 4 * half; - - if (argc == 6) - { - half = atoi (argv[idx_half_life]->arg) * 60; - reuse = atoi (argv[idx_reuse]->arg); - suppress = atoi (argv[idx_suppress]->arg); - max = atoi (argv[idx_max_suppress]->arg) * 60; - } - else if (argc == 3) - { - half = atoi (argv[idx_half_life]->arg) * 60; - max = 4 * half; - } + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_half_life = 2; + int idx_reuse = 3; + int idx_suppress = 4; + int idx_max_suppress = 5; + int half = DEFAULT_HALF_LIFE * 60; + int reuse = DEFAULT_REUSE; + int suppress = DEFAULT_SUPPRESS; + int max = 4 * half; + + if (argc == 6) { + half = atoi(argv[idx_half_life]->arg) * 60; + reuse = atoi(argv[idx_reuse]->arg); + suppress = atoi(argv[idx_suppress]->arg); + max = atoi(argv[idx_max_suppress]->arg) * 60; + } else if (argc == 3) { + half = atoi(argv[idx_half_life]->arg) * 60; + max = 4 * half; + } - if (suppress < reuse) - { - vty_out (vty,"Suppress value cannot be less than reuse value \n"); - return 0; - } + if (suppress < reuse) { + vty_out(vty, + "Suppress value cannot be less than reuse value \n"); + return 0; + } - return bgp_damp_enable (bgp, bgp_node_afi (vty), bgp_node_safi (vty), - half, reuse, suppress, max); + return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half, + reuse, suppress, max); } DEFUN (bgp_damp_unset, @@ -10657,110 +10709,105 @@ DEFUN (bgp_damp_unset, "Value to start suppressing a route\n" "Maximum duration to suppress a stable route\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - return bgp_damp_disable (bgp, bgp_node_afi (vty), bgp_node_safi (vty)); + VTY_DECLVAR_CONTEXT(bgp, bgp); + return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty)); } /* Display specified route of BGP table. */ -static int -bgp_clear_damp_route (struct vty *vty, const char *view_name, - const char *ip_str, afi_t afi, safi_t safi, - struct prefix_rd *prd, int prefix_check) -{ - int ret; - struct prefix match; - struct bgp_node *rn; - struct bgp_node *rm; - struct bgp_info *ri; - struct bgp_info *ri_temp; - struct bgp *bgp; - struct bgp_table *table; - - /* BGP structure lookup. */ - if (view_name) - { - bgp = bgp_lookup_by_name (view_name); - if (bgp == NULL) - { - vty_out (vty, "%% Can't find BGP instance %s\n", view_name); - return CMD_WARNING; - } - } - else - { - bgp = bgp_get_default (); - if (bgp == NULL) - { - vty_out (vty, "%% No BGP process is configured\n"); - return CMD_WARNING; +static int bgp_clear_damp_route(struct vty *vty, const char *view_name, + const char *ip_str, afi_t afi, safi_t safi, + struct prefix_rd *prd, int prefix_check) +{ + int ret; + struct prefix match; + struct bgp_node *rn; + struct bgp_node *rm; + struct bgp_info *ri; + struct bgp_info *ri_temp; + struct bgp *bgp; + struct bgp_table *table; + + /* BGP structure lookup. */ + if (view_name) { + bgp = bgp_lookup_by_name(view_name); + if (bgp == NULL) { + vty_out(vty, "%% Can't find BGP instance %s\n", + view_name); + return CMD_WARNING; + } + } else { + bgp = bgp_get_default(); + if (bgp == NULL) { + vty_out(vty, "%% No BGP process is configured\n"); + return CMD_WARNING; + } } - } - - /* Check IP address argument. */ - ret = str2prefix (ip_str, &match); - if (! ret) - { - vty_out (vty, "%% address is malformed\n"); - return CMD_WARNING; - } - match.family = afi2family (afi); + /* Check IP address argument. */ + ret = str2prefix(ip_str, &match); + if (!ret) { + vty_out(vty, "%% address is malformed\n"); + return CMD_WARNING; + } - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN)) - { - for (rn = bgp_table_top (bgp->rib[AFI_IP][safi]); rn; rn = bgp_route_next (rn)) - { - if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0) - continue; - - if ((table = rn->info) != NULL) - if ((rm = bgp_node_match (table, &match)) != NULL) - { - if (! prefix_check || rm->p.prefixlen == match.prefixlen) - { - ri = rm->info; - while (ri) - { - if (ri->extra && ri->extra->damp_info) - { - ri_temp = ri->next; - bgp_damp_info_free (ri->extra->damp_info, 1); - ri = ri_temp; - } - else - ri = ri->next; - } - } - - bgp_unlock_node (rm); - } - } - } - else - { - if ((rn = bgp_node_match (bgp->rib[afi][safi], &match)) != NULL) - { - if (! prefix_check || rn->p.prefixlen == match.prefixlen) - { - ri = rn->info; - while (ri) - { - if (ri->extra && ri->extra->damp_info) - { - ri_temp = ri->next; - bgp_damp_info_free (ri->extra->damp_info, 1); - ri = ri_temp; - } - else - ri = ri->next; - } - } - - bgp_unlock_node (rn); - } - } + match.family = afi2family(afi); + + if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) + || (safi == SAFI_EVPN)) { + for (rn = bgp_table_top(bgp->rib[AFI_IP][safi]); rn; + rn = bgp_route_next(rn)) { + if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0) + continue; + + if ((table = rn->info) != NULL) + if ((rm = bgp_node_match(table, &match)) + != NULL) { + if (!prefix_check + || rm->p.prefixlen + == match.prefixlen) { + ri = rm->info; + while (ri) { + if (ri->extra + && ri->extra + ->damp_info) { + ri_temp = + ri->next; + bgp_damp_info_free( + ri->extra + ->damp_info, + 1); + ri = ri_temp; + } else + ri = ri->next; + } + } + + bgp_unlock_node(rm); + } + } + } else { + if ((rn = bgp_node_match(bgp->rib[afi][safi], &match)) + != NULL) { + if (!prefix_check + || rn->p.prefixlen == match.prefixlen) { + ri = rn->info; + while (ri) { + if (ri->extra && ri->extra->damp_info) { + ri_temp = ri->next; + bgp_damp_info_free( + ri->extra->damp_info, + 1); + ri = ri_temp; + } else + ri = ri->next; + } + } + + bgp_unlock_node(rn); + } + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (clear_ip_bgp_dampening, @@ -10771,8 +10818,8 @@ DEFUN (clear_ip_bgp_dampening, BGP_STR "Clear route flap dampening information\n") { - bgp_damp_info_clean (); - return CMD_SUCCESS; + bgp_damp_info_clean(); + return CMD_SUCCESS; } DEFUN (clear_ip_bgp_dampening_prefix, @@ -10784,9 +10831,9 @@ DEFUN (clear_ip_bgp_dampening_prefix, "Clear route flap dampening information\n" "IPv4 prefix\n") { - int idx_ipv4_prefixlen = 4; - return bgp_clear_damp_route (vty, NULL, argv[idx_ipv4_prefixlen]->arg, AFI_IP, - SAFI_UNICAST, NULL, 1); + int idx_ipv4_prefixlen = 4; + return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg, + AFI_IP, SAFI_UNICAST, NULL, 1); } DEFUN (clear_ip_bgp_dampening_address, @@ -10798,9 +10845,9 @@ DEFUN (clear_ip_bgp_dampening_address, "Clear route flap dampening information\n" "Network to clear damping information\n") { - int idx_ipv4 = 4; - return bgp_clear_damp_route (vty, NULL, argv[idx_ipv4]->arg, AFI_IP, - SAFI_UNICAST, NULL, 0); + int idx_ipv4 = 4; + return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP, + SAFI_UNICAST, NULL, 0); } DEFUN (clear_ip_bgp_dampening_address_mask, @@ -10813,442 +10860,477 @@ DEFUN (clear_ip_bgp_dampening_address_mask, "Network to clear damping information\n" "Network mask\n") { - int idx_ipv4 = 4; - int idx_ipv4_2 = 5; - int ret; - char prefix_str[BUFSIZ]; + int idx_ipv4 = 4; + int idx_ipv4_2 = 5; + int ret; + char prefix_str[BUFSIZ]; - ret = netmask_str2prefix_str (argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, prefix_str); - if (! ret) - { - vty_out (vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING; - } + ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, + prefix_str); + if (!ret) { + vty_out(vty, "%% Inconsistent address and mask\n"); + return CMD_WARNING; + } - return bgp_clear_damp_route (vty, NULL, prefix_str, AFI_IP, - SAFI_UNICAST, NULL, 0); + return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST, + NULL, 0); } /* also used for encap safi */ -static int -bgp_config_write_network_vpn (struct vty *vty, struct bgp *bgp, - afi_t afi, safi_t safi, int *write) -{ - struct bgp_node *prn; - struct bgp_node *rn; - struct bgp_table *table; - struct prefix *p; - struct prefix_rd *prd; - struct bgp_static *bgp_static; - mpls_label_t label; - char buf[SU_ADDRSTRLEN]; - char rdbuf[RD_ADDRSTRLEN]; - - /* Network configuration. */ - for (prn = bgp_table_top (bgp->route[afi][safi]); prn; prn = bgp_route_next (prn)) - if ((table = prn->info) != NULL) - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - if ((bgp_static = rn->info) != NULL) - { - p = &rn->p; - prd = (struct prefix_rd *) &prn->p; - - /* "address-family" display. */ - bgp_config_write_family_header (vty, afi, safi, write); - - /* "network" configuration display. */ - prefix_rd2str (prd, rdbuf, RD_ADDRSTRLEN); - label = decode_label (&bgp_static->label); - - vty_out (vty, " network %s/%d rd %s", - inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), - p->prefixlen, rdbuf); - if (safi == SAFI_MPLS_VPN) - vty_out (vty, " label %u", label); - - if (bgp_static->rmap.name) - vty_out (vty, " route-map %s", bgp_static->rmap.name); - else - { - if (bgp_static->backdoor) - vty_out (vty, " backdoor"); - } - vty_out (vty, "\n"); - } - return 0; -} - -static int -bgp_config_write_network_evpn (struct vty *vty, struct bgp *bgp, - afi_t afi, safi_t safi, int *write) -{ - struct bgp_node *prn; - struct bgp_node *rn; - struct bgp_table *table; - struct prefix *p; - struct prefix_rd *prd; - struct bgp_static *bgp_static; - char buf[PREFIX_STRLEN]; - char buf2[SU_ADDRSTRLEN]; - char rdbuf[RD_ADDRSTRLEN]; - - /* Network configuration. */ - for (prn = bgp_table_top (bgp->route[afi][safi]); prn; prn = bgp_route_next (prn)) - if ((table = prn->info) != NULL) - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - if ((bgp_static = rn->info) != NULL) - { - char *macrouter = NULL; - char *esi = NULL; - - if(bgp_static->router_mac) - macrouter = prefix_mac2str(bgp_static->router_mac, NULL, 0); - if(bgp_static->eth_s_id) - esi = esi2str(bgp_static->eth_s_id); - p = &rn->p; - prd = (struct prefix_rd *) &prn->p; - - /* "address-family" display. */ - bgp_config_write_family_header (vty, afi, safi, write); - - /* "network" configuration display. */ - prefix_rd2str (prd, rdbuf, RD_ADDRSTRLEN); - - inet_ntop (AF_INET, &bgp_static->igpnexthop, buf2, SU_ADDRSTRLEN); - - prefix2str (p, buf, sizeof (buf)), - vty_out (vty, " network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s", - buf, rdbuf, p->u.prefix_evpn.eth_tag, - decode_label (&bgp_static->label), esi, buf2 , macrouter); - vty_out (vty, "\n"); - if (macrouter) - XFREE (MTYPE_TMP, macrouter); - if (esi) - XFREE (MTYPE_TMP, esi); - } - return 0; +static int bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp, + afi_t afi, safi_t safi, int *write) +{ + struct bgp_node *prn; + struct bgp_node *rn; + struct bgp_table *table; + struct prefix *p; + struct prefix_rd *prd; + struct bgp_static *bgp_static; + mpls_label_t label; + char buf[SU_ADDRSTRLEN]; + char rdbuf[RD_ADDRSTRLEN]; + + /* Network configuration. */ + for (prn = bgp_table_top(bgp->route[afi][safi]); prn; + prn = bgp_route_next(prn)) + if ((table = prn->info) != NULL) + for (rn = bgp_table_top(table); rn; + rn = bgp_route_next(rn)) + if ((bgp_static = rn->info) != NULL) { + p = &rn->p; + prd = (struct prefix_rd *)&prn->p; + + /* "address-family" display. */ + bgp_config_write_family_header( + vty, afi, safi, write); + + /* "network" configuration display. */ + prefix_rd2str(prd, rdbuf, + RD_ADDRSTRLEN); + label = decode_label( + &bgp_static->label); + + vty_out(vty, " network %s/%d rd %s", + inet_ntop(p->family, + &p->u.prefix, buf, + SU_ADDRSTRLEN), + p->prefixlen, rdbuf); + if (safi == SAFI_MPLS_VPN) + vty_out(vty, " label %u", + label); + + if (bgp_static->rmap.name) + vty_out(vty, " route-map %s", + bgp_static->rmap.name); + else { + if (bgp_static->backdoor) + vty_out(vty, + " backdoor"); + } + vty_out(vty, "\n"); + } + return 0; +} + +static int bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp, + afi_t afi, safi_t safi, int *write) +{ + struct bgp_node *prn; + struct bgp_node *rn; + struct bgp_table *table; + struct prefix *p; + struct prefix_rd *prd; + struct bgp_static *bgp_static; + char buf[PREFIX_STRLEN]; + char buf2[SU_ADDRSTRLEN]; + char rdbuf[RD_ADDRSTRLEN]; + + /* Network configuration. */ + for (prn = bgp_table_top(bgp->route[afi][safi]); prn; + prn = bgp_route_next(prn)) + if ((table = prn->info) != NULL) + for (rn = bgp_table_top(table); rn; + rn = bgp_route_next(rn)) + if ((bgp_static = rn->info) != NULL) { + char *macrouter = NULL; + char *esi = NULL; + + if (bgp_static->router_mac) + macrouter = prefix_mac2str( + bgp_static->router_mac, + NULL, 0); + if (bgp_static->eth_s_id) + esi = esi2str( + bgp_static->eth_s_id); + p = &rn->p; + prd = (struct prefix_rd *)&prn->p; + + /* "address-family" display. */ + bgp_config_write_family_header( + vty, afi, safi, write); + + /* "network" configuration display. */ + prefix_rd2str(prd, rdbuf, + RD_ADDRSTRLEN); + + inet_ntop(AF_INET, + &bgp_static->igpnexthop, buf2, + SU_ADDRSTRLEN); + + prefix2str(p, buf, sizeof(buf)), + vty_out(vty, + " network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s", + buf, rdbuf, + p->u.prefix_evpn + .eth_tag, + decode_label( + &bgp_static + ->label), + esi, buf2, macrouter); + vty_out(vty, "\n"); + if (macrouter) + XFREE(MTYPE_TMP, macrouter); + if (esi) + XFREE(MTYPE_TMP, esi); + } + return 0; } /* Configuration of static route announcement and aggregate information. */ -int -bgp_config_write_network (struct vty *vty, struct bgp *bgp, - afi_t afi, safi_t safi, int *write) -{ - struct bgp_node *rn; - struct prefix *p; - struct bgp_static *bgp_static; - struct bgp_aggregate *bgp_aggregate; - char buf[SU_ADDRSTRLEN]; - - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) - return bgp_config_write_network_vpn (vty, bgp, afi, safi, write); - - if (afi == AFI_L2VPN && safi == SAFI_EVPN) - return bgp_config_write_network_evpn (vty, bgp, afi, safi, write); - - /* Network configuration. */ - for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn)) - if ((bgp_static = rn->info) != NULL) - { - p = &rn->p; - - /* "address-family" display. */ - bgp_config_write_family_header (vty, afi, safi, write); - - /* "network" configuration display. */ - if (bgp_option_check (BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) - { - u_int32_t destination; - struct in_addr netmask; - - destination = ntohl (p->u.prefix4.s_addr); - masklen2ip (p->prefixlen, &netmask); - vty_out (vty, " network %s", - inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN)); - - if ((IN_CLASSC (destination) && p->prefixlen == 24) - || (IN_CLASSB (destination) && p->prefixlen == 16) - || (IN_CLASSA (destination) && p->prefixlen == 8) - || p->u.prefix4.s_addr == 0) - { - /* Natural mask is not display. */ - } - else - vty_out (vty, " mask %s", inet_ntoa (netmask)); - } - else - { - vty_out (vty, " network %s/%d", - inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), - p->prefixlen); - } - - if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) - vty_out (vty, " label-index %u", bgp_static->label_index); - - if (bgp_static->rmap.name) - vty_out (vty, " route-map %s", bgp_static->rmap.name); - else - { - if (bgp_static->backdoor) - vty_out (vty, " backdoor"); - } - - vty_out (vty, "\n"); - } - - /* Aggregate-address configuration. */ - for (rn = bgp_table_top (bgp->aggregate[afi][safi]); rn; rn = bgp_route_next (rn)) - if ((bgp_aggregate = rn->info) != NULL) - { - p = &rn->p; - - /* "address-family" display. */ - bgp_config_write_family_header (vty, afi, safi, write); +int bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi, int *write) +{ + struct bgp_node *rn; + struct prefix *p; + struct bgp_static *bgp_static; + struct bgp_aggregate *bgp_aggregate; + char buf[SU_ADDRSTRLEN]; + + if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) + return bgp_config_write_network_vpn(vty, bgp, afi, safi, write); + + if (afi == AFI_L2VPN && safi == SAFI_EVPN) + return bgp_config_write_network_evpn(vty, bgp, afi, safi, + write); + + /* Network configuration. */ + for (rn = bgp_table_top(bgp->route[afi][safi]); rn; + rn = bgp_route_next(rn)) + if ((bgp_static = rn->info) != NULL) { + p = &rn->p; + + /* "address-family" display. */ + bgp_config_write_family_header(vty, afi, safi, write); + + /* "network" configuration display. */ + if (bgp_option_check(BGP_OPT_CONFIG_CISCO) + && afi == AFI_IP) { + u_int32_t destination; + struct in_addr netmask; + + destination = ntohl(p->u.prefix4.s_addr); + masklen2ip(p->prefixlen, &netmask); + vty_out(vty, " network %s", + inet_ntop(p->family, &p->u.prefix, buf, + SU_ADDRSTRLEN)); + + if ((IN_CLASSC(destination) + && p->prefixlen == 24) + || (IN_CLASSB(destination) + && p->prefixlen == 16) + || (IN_CLASSA(destination) + && p->prefixlen == 8) + || p->u.prefix4.s_addr == 0) { + /* Natural mask is not display. */ + } else + vty_out(vty, " mask %s", + inet_ntoa(netmask)); + } else { + vty_out(vty, " network %s/%d", + inet_ntop(p->family, &p->u.prefix, buf, + SU_ADDRSTRLEN), + p->prefixlen); + } + + if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) + vty_out(vty, " label-index %u", + bgp_static->label_index); + + if (bgp_static->rmap.name) + vty_out(vty, " route-map %s", + bgp_static->rmap.name); + else { + if (bgp_static->backdoor) + vty_out(vty, " backdoor"); + } + + vty_out(vty, "\n"); + } - if (bgp_option_check (BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) - { - struct in_addr netmask; + /* Aggregate-address configuration. */ + for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn; + rn = bgp_route_next(rn)) + if ((bgp_aggregate = rn->info) != NULL) { + p = &rn->p; + + /* "address-family" display. */ + bgp_config_write_family_header(vty, afi, safi, write); + + if (bgp_option_check(BGP_OPT_CONFIG_CISCO) + && afi == AFI_IP) { + struct in_addr netmask; + + masklen2ip(p->prefixlen, &netmask); + vty_out(vty, " aggregate-address %s %s", + inet_ntop(p->family, &p->u.prefix, buf, + SU_ADDRSTRLEN), + inet_ntoa(netmask)); + } else { + vty_out(vty, " aggregate-address %s/%d", + inet_ntop(p->family, &p->u.prefix, buf, + SU_ADDRSTRLEN), + p->prefixlen); + } + + if (bgp_aggregate->as_set) + vty_out(vty, " as-set"); + + if (bgp_aggregate->summary_only) + vty_out(vty, " summary-only"); + + vty_out(vty, "\n"); + } - masklen2ip (p->prefixlen, &netmask); - vty_out (vty, " aggregate-address %s %s", - inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), - inet_ntoa (netmask)); - } - else - { - vty_out (vty, " aggregate-address %s/%d", - inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), - p->prefixlen); - } - - if (bgp_aggregate->as_set) - vty_out (vty, " as-set"); - - if (bgp_aggregate->summary_only) - vty_out (vty, " summary-only"); - - vty_out (vty, "\n"); - } - - return 0; -} - -int -bgp_config_write_distance (struct vty *vty, struct bgp *bgp, afi_t afi, - safi_t safi, int *write) -{ - struct bgp_node *rn; - struct bgp_distance *bdistance; - - /* Distance configuration. */ - if (bgp->distance_ebgp[afi][safi] - && bgp->distance_ibgp[afi][safi] - && bgp->distance_local[afi][safi] - && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT - || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT - || bgp->distance_local[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT)) - { - bgp_config_write_family_header (vty, afi, safi, write); - vty_out (vty, " distance bgp %d %d %d\n", - bgp->distance_ebgp[afi][safi], bgp->distance_ibgp[afi][safi], - bgp->distance_local[afi][safi]); - } + return 0; +} - for (rn = bgp_table_top (bgp_distance_table[afi][safi]); rn; - rn = bgp_route_next (rn)) - if ((bdistance = rn->info) != NULL) - { - char buf[PREFIX_STRLEN]; +int bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi, int *write) +{ + struct bgp_node *rn; + struct bgp_distance *bdistance; + + /* Distance configuration. */ + if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi] + && bgp->distance_local[afi][safi] + && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT + || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT + || bgp->distance_local[afi][safi] + != ZEBRA_IBGP_DISTANCE_DEFAULT)) { + bgp_config_write_family_header(vty, afi, safi, write); + vty_out(vty, " distance bgp %d %d %d\n", + bgp->distance_ebgp[afi][safi], + bgp->distance_ibgp[afi][safi], + bgp->distance_local[afi][safi]); + } - bgp_config_write_family_header (vty, afi, safi, write); - vty_out (vty, " distance %d %s %s\n", bdistance->distance, - prefix2str (&rn->p, buf, sizeof (buf)), - bdistance->access_list ? bdistance->access_list : ""); - } + for (rn = bgp_table_top(bgp_distance_table[afi][safi]); rn; + rn = bgp_route_next(rn)) + if ((bdistance = rn->info) != NULL) { + char buf[PREFIX_STRLEN]; + + bgp_config_write_family_header(vty, afi, safi, write); + vty_out(vty, " distance %d %s %s\n", + bdistance->distance, + prefix2str(&rn->p, buf, sizeof(buf)), + bdistance->access_list ? bdistance->access_list + : ""); + } - return *write; + return *write; } /* Allocate routing table structure and install commands. */ -void -bgp_route_init (void) -{ - afi_t afi; - safi_t safi; - - /* Init BGP distance table. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - bgp_distance_table[afi][safi] = bgp_table_init (afi, safi); - - /* IPv4 BGP commands. */ - install_element (BGP_NODE, &bgp_table_map_cmd); - install_element (BGP_NODE, &bgp_network_cmd); - install_element (BGP_NODE, &bgp_network_mask_cmd); - install_element (BGP_NODE, &bgp_network_mask_natural_cmd); - install_element (BGP_NODE, &bgp_network_route_map_cmd); - install_element (BGP_NODE, &bgp_network_mask_route_map_cmd); - install_element (BGP_NODE, &bgp_network_mask_natural_route_map_cmd); - install_element (BGP_NODE, &bgp_network_backdoor_cmd); - install_element (BGP_NODE, &bgp_network_mask_backdoor_cmd); - install_element (BGP_NODE, &bgp_network_mask_natural_backdoor_cmd); - install_element (BGP_NODE, &no_bgp_table_map_cmd); - install_element (BGP_NODE, &no_bgp_network_cmd); - install_element (BGP_NODE, &no_bgp_network_mask_cmd); - install_element (BGP_NODE, &no_bgp_network_mask_natural_cmd); - - install_element (BGP_NODE, &aggregate_address_cmd); - install_element (BGP_NODE, &aggregate_address_mask_cmd); - install_element (BGP_NODE, &no_aggregate_address_cmd); - install_element (BGP_NODE, &no_aggregate_address_mask_cmd); - - /* IPv4 unicast configuration. */ - install_element (BGP_IPV4_NODE, &bgp_table_map_cmd); - install_element (BGP_IPV4_NODE, &bgp_network_cmd); - install_element (BGP_IPV4_NODE, &bgp_network_mask_cmd); - install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_cmd); - install_element (BGP_IPV4_NODE, &bgp_network_route_map_cmd); - install_element (BGP_IPV4_NODE, &bgp_network_mask_route_map_cmd); - install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_route_map_cmd); - install_element (BGP_IPV4_NODE, &bgp_network_label_index_cmd); - install_element (BGP_IPV4_NODE, &bgp_network_label_index_route_map_cmd); - install_element (BGP_IPV4_NODE, &no_bgp_network_label_index_cmd); - install_element (BGP_IPV4_NODE, &no_bgp_network_label_index_route_map_cmd); - install_element (BGP_IPV4_NODE, &no_bgp_table_map_cmd); - install_element (BGP_IPV4_NODE, &no_bgp_network_cmd); - install_element (BGP_IPV4_NODE, &no_bgp_network_mask_cmd); - install_element (BGP_IPV4_NODE, &no_bgp_network_mask_natural_cmd); - - install_element (BGP_IPV4_NODE, &aggregate_address_cmd); - install_element (BGP_IPV4_NODE, &aggregate_address_mask_cmd); - install_element (BGP_IPV4_NODE, &no_aggregate_address_cmd); - install_element (BGP_IPV4_NODE, &no_aggregate_address_mask_cmd); - - /* IPv4 multicast configuration. */ - install_element (BGP_IPV4M_NODE, &bgp_table_map_cmd); - install_element (BGP_IPV4M_NODE, &bgp_network_cmd); - install_element (BGP_IPV4M_NODE, &bgp_network_mask_cmd); - install_element (BGP_IPV4M_NODE, &bgp_network_mask_natural_cmd); - install_element (BGP_IPV4M_NODE, &bgp_network_route_map_cmd); - install_element (BGP_IPV4M_NODE, &bgp_network_mask_route_map_cmd); - install_element (BGP_IPV4M_NODE, &bgp_network_mask_natural_route_map_cmd); - install_element (BGP_IPV4M_NODE, &no_bgp_table_map_cmd); - install_element (BGP_IPV4M_NODE, &no_bgp_network_cmd); - install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_cmd); - install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_natural_cmd); - install_element (BGP_IPV4M_NODE, &aggregate_address_cmd); - install_element (BGP_IPV4M_NODE, &aggregate_address_mask_cmd); - install_element (BGP_IPV4M_NODE, &no_aggregate_address_cmd); - install_element (BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd); - - /* IPv4 labeled-unicast configuration. */ - install_element (VIEW_NODE, &show_ip_bgp_instance_all_cmd); - install_element (VIEW_NODE, &show_ip_bgp_cmd); - install_element (VIEW_NODE, &show_ip_bgp_route_cmd); - install_element (VIEW_NODE, &show_ip_bgp_regexp_cmd); - - install_element (VIEW_NODE, &show_ip_bgp_instance_neighbor_advertised_route_cmd); - install_element (VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd); - install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd); +void bgp_route_init(void) +{ + afi_t afi; + safi_t safi; + + /* Init BGP distance table. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + bgp_distance_table[afi][safi] = + bgp_table_init(afi, safi); + + /* IPv4 BGP commands. */ + install_element(BGP_NODE, &bgp_table_map_cmd); + install_element(BGP_NODE, &bgp_network_cmd); + install_element(BGP_NODE, &bgp_network_mask_cmd); + install_element(BGP_NODE, &bgp_network_mask_natural_cmd); + install_element(BGP_NODE, &bgp_network_route_map_cmd); + install_element(BGP_NODE, &bgp_network_mask_route_map_cmd); + install_element(BGP_NODE, &bgp_network_mask_natural_route_map_cmd); + install_element(BGP_NODE, &bgp_network_backdoor_cmd); + install_element(BGP_NODE, &bgp_network_mask_backdoor_cmd); + install_element(BGP_NODE, &bgp_network_mask_natural_backdoor_cmd); + install_element(BGP_NODE, &no_bgp_table_map_cmd); + install_element(BGP_NODE, &no_bgp_network_cmd); + install_element(BGP_NODE, &no_bgp_network_mask_cmd); + install_element(BGP_NODE, &no_bgp_network_mask_natural_cmd); + + install_element(BGP_NODE, &aggregate_address_cmd); + install_element(BGP_NODE, &aggregate_address_mask_cmd); + install_element(BGP_NODE, &no_aggregate_address_cmd); + install_element(BGP_NODE, &no_aggregate_address_mask_cmd); + + /* IPv4 unicast configuration. */ + install_element(BGP_IPV4_NODE, &bgp_table_map_cmd); + install_element(BGP_IPV4_NODE, &bgp_network_cmd); + install_element(BGP_IPV4_NODE, &bgp_network_mask_cmd); + install_element(BGP_IPV4_NODE, &bgp_network_mask_natural_cmd); + install_element(BGP_IPV4_NODE, &bgp_network_route_map_cmd); + install_element(BGP_IPV4_NODE, &bgp_network_mask_route_map_cmd); + install_element(BGP_IPV4_NODE, &bgp_network_mask_natural_route_map_cmd); + install_element(BGP_IPV4_NODE, &bgp_network_label_index_cmd); + install_element(BGP_IPV4_NODE, &bgp_network_label_index_route_map_cmd); + install_element(BGP_IPV4_NODE, &no_bgp_network_label_index_cmd); + install_element(BGP_IPV4_NODE, + &no_bgp_network_label_index_route_map_cmd); + install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd); + install_element(BGP_IPV4_NODE, &no_bgp_network_cmd); + install_element(BGP_IPV4_NODE, &no_bgp_network_mask_cmd); + install_element(BGP_IPV4_NODE, &no_bgp_network_mask_natural_cmd); + + install_element(BGP_IPV4_NODE, &aggregate_address_cmd); + install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd); + install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd); + install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd); + + /* IPv4 multicast configuration. */ + install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd); + install_element(BGP_IPV4M_NODE, &bgp_network_cmd); + install_element(BGP_IPV4M_NODE, &bgp_network_mask_cmd); + install_element(BGP_IPV4M_NODE, &bgp_network_mask_natural_cmd); + install_element(BGP_IPV4M_NODE, &bgp_network_route_map_cmd); + install_element(BGP_IPV4M_NODE, &bgp_network_mask_route_map_cmd); + install_element(BGP_IPV4M_NODE, + &bgp_network_mask_natural_route_map_cmd); + install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd); + install_element(BGP_IPV4M_NODE, &no_bgp_network_cmd); + install_element(BGP_IPV4M_NODE, &no_bgp_network_mask_cmd); + install_element(BGP_IPV4M_NODE, &no_bgp_network_mask_natural_cmd); + install_element(BGP_IPV4M_NODE, &aggregate_address_cmd); + install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd); + install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd); + install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd); + + /* IPv4 labeled-unicast configuration. */ + install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd); + install_element(VIEW_NODE, &show_ip_bgp_cmd); + install_element(VIEW_NODE, &show_ip_bgp_route_cmd); + install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd); + + install_element(VIEW_NODE, + &show_ip_bgp_instance_neighbor_advertised_route_cmd); + install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd); + install_element(VIEW_NODE, + &show_ip_bgp_neighbor_received_prefix_filter_cmd); #ifdef KEEP_OLD_VPN_COMMANDS - install_element (VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd); + install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd); #endif /* KEEP_OLD_VPN_COMMANDS */ - install_element (VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd); - install_element (VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd); - - /* BGP dampening clear commands */ - install_element (ENABLE_NODE, &clear_ip_bgp_dampening_cmd); - install_element (ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd); + install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd); + install_element(VIEW_NODE, + &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd); - install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd); - install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd); + /* BGP dampening clear commands */ + install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd); + install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd); - /* prefix count */ - install_element (ENABLE_NODE, &show_ip_bgp_instance_neighbor_prefix_counts_cmd); + install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd); + install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd); + + /* prefix count */ + install_element(ENABLE_NODE, + &show_ip_bgp_instance_neighbor_prefix_counts_cmd); #ifdef KEEP_OLD_VPN_COMMANDS - install_element (ENABLE_NODE, &show_ip_bgp_vpn_neighbor_prefix_counts_cmd); + install_element(ENABLE_NODE, + &show_ip_bgp_vpn_neighbor_prefix_counts_cmd); #endif /* KEEP_OLD_VPN_COMMANDS */ - /* New config IPv6 BGP commands. */ - install_element (BGP_IPV6_NODE, &bgp_table_map_cmd); - install_element (BGP_IPV6_NODE, &ipv6_bgp_network_cmd); - install_element (BGP_IPV6_NODE, &ipv6_bgp_network_route_map_cmd); - install_element (BGP_IPV6_NODE, &no_bgp_table_map_cmd); - install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_cmd); - install_element (BGP_IPV6_NODE, &ipv6_bgp_network_label_index_cmd); - install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_label_index_cmd); - install_element (BGP_IPV6_NODE, &ipv6_bgp_network_label_index_route_map_cmd); - install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_label_index_route_map_cmd); - - install_element (BGP_IPV6_NODE, &ipv6_aggregate_address_cmd); - install_element (BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd); - - install_element (BGP_IPV6M_NODE, &ipv6_bgp_network_cmd); - install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_network_cmd); - - install_element (BGP_IPV6L_NODE, &bgp_table_map_cmd); - install_element (BGP_IPV6L_NODE, &ipv6_bgp_network_cmd); - install_element (BGP_IPV6L_NODE, &ipv6_bgp_network_route_map_cmd); - install_element (BGP_IPV6L_NODE, &no_bgp_table_map_cmd); - install_element (BGP_IPV6L_NODE, &no_ipv6_bgp_network_cmd); - - install_element (BGP_NODE, &bgp_distance_cmd); - install_element (BGP_NODE, &no_bgp_distance_cmd); - install_element (BGP_NODE, &bgp_distance_source_cmd); - install_element (BGP_NODE, &no_bgp_distance_source_cmd); - install_element (BGP_NODE, &bgp_distance_source_access_list_cmd); - install_element (BGP_NODE, &no_bgp_distance_source_access_list_cmd); - install_element (BGP_IPV4_NODE, &bgp_distance_cmd); - install_element (BGP_IPV4_NODE, &no_bgp_distance_cmd); - install_element (BGP_IPV4_NODE, &bgp_distance_source_cmd); - install_element (BGP_IPV4_NODE, &no_bgp_distance_source_cmd); - install_element (BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd); - install_element (BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd); - install_element (BGP_IPV4M_NODE, &bgp_distance_cmd); - install_element (BGP_IPV4M_NODE, &no_bgp_distance_cmd); - install_element (BGP_IPV4M_NODE, &bgp_distance_source_cmd); - install_element (BGP_IPV4M_NODE, &no_bgp_distance_source_cmd); - install_element (BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd); - install_element (BGP_IPV4M_NODE, &no_bgp_distance_source_access_list_cmd); - install_element (BGP_IPV6_NODE, &bgp_distance_cmd); - install_element (BGP_IPV6_NODE, &no_bgp_distance_cmd); - install_element (BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd); - install_element (BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd); - install_element (BGP_IPV6_NODE, &ipv6_bgp_distance_source_access_list_cmd); - install_element (BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_access_list_cmd); - install_element (BGP_IPV6M_NODE, &bgp_distance_cmd); - install_element (BGP_IPV6M_NODE, &no_bgp_distance_cmd); - install_element (BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd); - install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd); - install_element (BGP_IPV6M_NODE, &ipv6_bgp_distance_source_access_list_cmd); - install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_access_list_cmd); - - install_element (BGP_NODE, &bgp_damp_set_cmd); - install_element (BGP_NODE, &bgp_damp_unset_cmd); - install_element (BGP_IPV4_NODE, &bgp_damp_set_cmd); - install_element (BGP_IPV4_NODE, &bgp_damp_unset_cmd); - - /* IPv4 Multicast Mode */ - install_element (BGP_IPV4M_NODE, &bgp_damp_set_cmd); - install_element (BGP_IPV4M_NODE, &bgp_damp_unset_cmd); - - /* Large Communities */ - install_element (VIEW_NODE, &show_ip_bgp_large_community_list_cmd); - install_element (VIEW_NODE, &show_ip_bgp_large_community_cmd); -} - -void -bgp_route_finish (void) -{ - afi_t afi; - safi_t safi; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - bgp_table_unlock (bgp_distance_table[afi][safi]); - bgp_distance_table[afi][safi] = NULL; - } + /* New config IPv6 BGP commands. */ + install_element(BGP_IPV6_NODE, &bgp_table_map_cmd); + install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd); + install_element(BGP_IPV6_NODE, &ipv6_bgp_network_route_map_cmd); + install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd); + install_element(BGP_IPV6_NODE, &no_ipv6_bgp_network_cmd); + install_element(BGP_IPV6_NODE, &ipv6_bgp_network_label_index_cmd); + install_element(BGP_IPV6_NODE, &no_ipv6_bgp_network_label_index_cmd); + install_element(BGP_IPV6_NODE, + &ipv6_bgp_network_label_index_route_map_cmd); + install_element(BGP_IPV6_NODE, + &no_ipv6_bgp_network_label_index_route_map_cmd); + + install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd); + install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd); + + install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd); + install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_network_cmd); + + install_element(BGP_IPV6L_NODE, &bgp_table_map_cmd); + install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd); + install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_route_map_cmd); + install_element(BGP_IPV6L_NODE, &no_bgp_table_map_cmd); + install_element(BGP_IPV6L_NODE, &no_ipv6_bgp_network_cmd); + + install_element(BGP_NODE, &bgp_distance_cmd); + install_element(BGP_NODE, &no_bgp_distance_cmd); + install_element(BGP_NODE, &bgp_distance_source_cmd); + install_element(BGP_NODE, &no_bgp_distance_source_cmd); + install_element(BGP_NODE, &bgp_distance_source_access_list_cmd); + install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd); + install_element(BGP_IPV4_NODE, &bgp_distance_cmd); + install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd); + install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd); + install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd); + install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd); + install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd); + install_element(BGP_IPV4M_NODE, &bgp_distance_cmd); + install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd); + install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd); + install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd); + install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd); + install_element(BGP_IPV4M_NODE, + &no_bgp_distance_source_access_list_cmd); + install_element(BGP_IPV6_NODE, &bgp_distance_cmd); + install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd); + install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd); + install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd); + install_element(BGP_IPV6_NODE, + &ipv6_bgp_distance_source_access_list_cmd); + install_element(BGP_IPV6_NODE, + &no_ipv6_bgp_distance_source_access_list_cmd); + install_element(BGP_IPV6M_NODE, &bgp_distance_cmd); + install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd); + install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd); + install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd); + install_element(BGP_IPV6M_NODE, + &ipv6_bgp_distance_source_access_list_cmd); + install_element(BGP_IPV6M_NODE, + &no_ipv6_bgp_distance_source_access_list_cmd); + + install_element(BGP_NODE, &bgp_damp_set_cmd); + install_element(BGP_NODE, &bgp_damp_unset_cmd); + install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd); + install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd); + + /* IPv4 Multicast Mode */ + install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd); + install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd); + + /* Large Communities */ + install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd); + install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd); +} + +void bgp_route_finish(void) +{ + afi_t afi; + safi_t safi; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + bgp_table_unlock(bgp_distance_table[afi][safi]); + bgp_distance_table[afi][safi] = NULL; + } } diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 907690381..1a1817bad 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -27,119 +27,125 @@ struct bgp_nexthop_cache; struct bgp_route_evpn; -enum bgp_show_type -{ - bgp_show_type_normal, - bgp_show_type_regexp, - bgp_show_type_prefix_list, - bgp_show_type_filter_list, - bgp_show_type_route_map, - bgp_show_type_neighbor, - bgp_show_type_cidr_only, - bgp_show_type_prefix_longer, - bgp_show_type_community_all, - bgp_show_type_community, - bgp_show_type_community_exact, - bgp_show_type_community_list, - bgp_show_type_community_list_exact, - bgp_show_type_lcommunity_all, - bgp_show_type_lcommunity, - bgp_show_type_lcommunity_list, - bgp_show_type_flap_statistics, - bgp_show_type_flap_neighbor, - bgp_show_type_dampend_paths, - bgp_show_type_damp_neighbor +enum bgp_show_type { + bgp_show_type_normal, + bgp_show_type_regexp, + bgp_show_type_prefix_list, + bgp_show_type_filter_list, + bgp_show_type_route_map, + bgp_show_type_neighbor, + bgp_show_type_cidr_only, + bgp_show_type_prefix_longer, + bgp_show_type_community_all, + bgp_show_type_community, + bgp_show_type_community_exact, + bgp_show_type_community_list, + bgp_show_type_community_list_exact, + bgp_show_type_lcommunity_all, + bgp_show_type_lcommunity, + bgp_show_type_lcommunity_list, + bgp_show_type_flap_statistics, + bgp_show_type_flap_neighbor, + bgp_show_type_dampend_paths, + bgp_show_type_damp_neighbor }; -#define BGP_SHOW_SCODE_HEADER "Status codes: s suppressed, d damped, "\ - "h history, * valid, > best, = multipath,\n"\ - " i internal, r RIB-failure, S Stale, R Removed\n" +#define BGP_SHOW_SCODE_HEADER \ + "Status codes: s suppressed, d damped, " \ + "h history, * valid, > best, = multipath,\n" \ + " i internal, r RIB-failure, S Stale, R Removed\n" #define BGP_SHOW_OCODE_HEADER "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n" #define BGP_SHOW_HEADER " Network Next Hop Metric LocPrf Weight Path\n" -/* Ancillary information to struct bgp_info, +/* Ancillary information to struct bgp_info, * used for uncommonly used data (aggregation, MPLS, etc.) * and lazily allocated to save memory. */ -struct bgp_info_extra -{ - /* Pointer to dampening structure. */ - struct bgp_damp_info *damp_info; +struct bgp_info_extra { + /* Pointer to dampening structure. */ + struct bgp_damp_info *damp_info; - /* This route is suppressed with aggregation. */ - int suppress; + /* This route is suppressed with aggregation. */ + int suppress; - /* Nexthop reachability check. */ - u_int32_t igpmetric; + /* Nexthop reachability check. */ + u_int32_t igpmetric; - /* MPLS label. */ - mpls_label_t label; + /* MPLS label. */ + mpls_label_t label; #if ENABLE_BGP_VNC - union { - - struct { - void *rfapi_handle; /* export: NVE advertising this route */ - struct list *local_nexthops; /* optional, for static routes */ - } export; - - struct { - struct thread *timer; - void *hme; /* encap monitor, if this is a VPN route */ - struct prefix_rd rd; /* import: route's route-distinguisher */ - u_char un_family; /* family of cached un address, 0 if unset */ - union { - struct in_addr addr4; - struct in6_addr addr6; - } un; /* cached un address */ - time_t create_time; - struct prefix aux_prefix; /* AFI_L2VPN: the IP addr, if family set */ - } import; - - } vnc; + union { + + struct { + void *rfapi_handle; /* export: NVE advertising this + route */ + struct list *local_nexthops; /* optional, for static + routes */ + } export; + + struct { + struct thread *timer; + void *hme; /* encap monitor, if this is a VPN route */ + struct prefix_rd + rd; /* import: route's route-distinguisher */ + u_char un_family; /* family of cached un address, 0 if + unset */ + union { + struct in_addr addr4; + struct in6_addr addr6; + } un; /* cached un address */ + time_t create_time; + struct + prefix + aux_prefix; /* AFI_L2VPN: the IP addr, + if family set */ + } import; + + } vnc; #endif - /* For imported routes into a VNI (or VRF), this points to the parent. */ - void *parent; + /* For imported routes into a VNI (or VRF), this points to the parent. + */ + void *parent; }; -struct bgp_info -{ - /* For linked list. */ - struct bgp_info *next; - struct bgp_info *prev; +struct bgp_info { + /* For linked list. */ + struct bgp_info *next; + struct bgp_info *prev; + + /* For nexthop linked list */ + LIST_ENTRY(bgp_info) nh_thread; + + /* Back pointer to the prefix node */ + struct bgp_node *net; + + /* Back pointer to the nexthop structure */ + struct bgp_nexthop_cache *nexthop; - /* For nexthop linked list */ - LIST_ENTRY(bgp_info) nh_thread; + /* Peer structure. */ + struct peer *peer; - /* Back pointer to the prefix node */ - struct bgp_node *net; + /* Attribute structure. */ + struct attr *attr; - /* Back pointer to the nexthop structure */ - struct bgp_nexthop_cache *nexthop; + /* Extra information */ + struct bgp_info_extra *extra; - /* Peer structure. */ - struct peer *peer; - /* Attribute structure. */ - struct attr *attr; - - /* Extra information */ - struct bgp_info_extra *extra; - + /* Multipath information */ + struct bgp_info_mpath *mpath; - /* Multipath information */ - struct bgp_info_mpath *mpath; + /* Uptime. */ + time_t uptime; - /* Uptime. */ - time_t uptime; + /* reference count */ + int lock; - /* reference count */ - int lock; - - /* BGP information status. */ - u_int16_t flags; + /* BGP information status. */ + u_int16_t flags; #define BGP_INFO_IGP_CHANGED (1 << 0) #define BGP_INFO_DAMPED (1 << 1) #define BGP_INFO_HISTORY (1 << 2) @@ -155,12 +161,12 @@ struct bgp_info #define BGP_INFO_MULTIPATH_CHG (1 << 12) #define BGP_INFO_RIB_ATTR_CHG (1 << 13) - /* BGP route type. This can be static, RIP, OSPF, BGP etc. */ - u_char type; + /* BGP route type. This can be static, RIP, OSPF, BGP etc. */ + u_char type; - /* When above type is BGP. This sub type specify BGP sub type - information. */ - u_char sub_type; + /* When above type is BGP. This sub type specify BGP sub type + information. */ + u_char sub_type; #define BGP_ROUTE_NORMAL 0 #define BGP_ROUTE_STATIC 1 #define BGP_ROUTE_AGGREGATE 2 @@ -169,85 +175,81 @@ struct bgp_info # define BGP_ROUTE_RFP 4 #endif - u_short instance; - - /* Addpath identifiers */ - u_int32_t addpath_rx_id; - u_int32_t addpath_tx_id; + u_short instance; + /* Addpath identifiers */ + u_int32_t addpath_rx_id; + u_int32_t addpath_tx_id; }; /* Structure used in BGP path selection */ -struct bgp_info_pair -{ - struct bgp_info *old; - struct bgp_info *new; +struct bgp_info_pair { + struct bgp_info *old; + struct bgp_info *new; }; /* BGP static route configuration. */ -struct bgp_static -{ - /* Backdoor configuration. */ - int backdoor; +struct bgp_static { + /* Backdoor configuration. */ + int backdoor; - /* Label index configuration; applies to LU prefixes. */ - u_int32_t label_index; + /* Label index configuration; applies to LU prefixes. */ + u_int32_t label_index; #define BGP_INVALID_LABEL_INDEX 0xFFFFFFFF - /* Import check status. */ - u_char valid; + /* Import check status. */ + u_char valid; - /* IGP metric. */ - u_int32_t igpmetric; + /* IGP metric. */ + u_int32_t igpmetric; - /* IGP nexthop. */ - struct in_addr igpnexthop; + /* IGP nexthop. */ + struct in_addr igpnexthop; - /* Atomic set reference count (ie cause of pathlimit) */ - u_int32_t atomic; - - /* BGP redistribute route-map. */ - struct - { - char *name; - struct route_map *map; - } rmap; + /* Atomic set reference count (ie cause of pathlimit) */ + u_int32_t atomic; - /* Route Distinguisher */ - struct prefix_rd prd; + /* BGP redistribute route-map. */ + struct { + char *name; + struct route_map *map; + } rmap; - /* MPLS label. */ - mpls_label_t label; + /* Route Distinguisher */ + struct prefix_rd prd; - /* EVPN */ - struct eth_segment_id *eth_s_id; - struct ethaddr *router_mac; - uint16_t encap_tunneltype; - struct prefix gatewayIp; + /* MPLS label. */ + mpls_label_t label; + + /* EVPN */ + struct eth_segment_id *eth_s_id; + struct ethaddr *router_mac; + uint16_t encap_tunneltype; + struct prefix gatewayIp; }; -#define BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen) \ - ((nhlen) < IPV4_MAX_BYTELEN ? 0 : \ - ((nhlen) < IPV6_MAX_BYTELEN ? AFI_IP : AFI_IP6)) +#define BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen) \ + ((nhlen) < IPV4_MAX_BYTELEN \ + ? 0 \ + : ((nhlen) < IPV6_MAX_BYTELEN ? AFI_IP : AFI_IP6)) -#define BGP_ATTR_NEXTHOP_AFI_IP6(attr) \ - (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)) && \ - ((attr)->mp_nexthop_len == 16 || \ - (attr)->mp_nexthop_len == 32)) -#define BGP_INFO_COUNTABLE(BI) \ - (! CHECK_FLAG ((BI)->flags, BGP_INFO_HISTORY) \ - && ! CHECK_FLAG ((BI)->flags, BGP_INFO_REMOVED)) +#define BGP_ATTR_NEXTHOP_AFI_IP6(attr) \ + (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) \ + && ((attr)->mp_nexthop_len == 16 || (attr)->mp_nexthop_len == 32)) +#define BGP_INFO_COUNTABLE(BI) \ + (!CHECK_FLAG((BI)->flags, BGP_INFO_HISTORY) \ + && !CHECK_FLAG((BI)->flags, BGP_INFO_REMOVED)) /* Flags which indicate a route is unuseable in some form */ -#define BGP_INFO_UNUSEABLE \ - (BGP_INFO_HISTORY|BGP_INFO_DAMPED|BGP_INFO_REMOVED) +#define BGP_INFO_UNUSEABLE \ + (BGP_INFO_HISTORY | BGP_INFO_DAMPED | BGP_INFO_REMOVED) /* Macro to check BGP information is alive or not. Sadly, * not equivalent to just checking previous, because of the * sense of the additional VALID flag. */ -#define BGP_INFO_HOLDDOWN(BI) \ - (! CHECK_FLAG ((BI)->flags, BGP_INFO_VALID) \ - || CHECK_FLAG ((BI)->flags, BGP_INFO_UNUSEABLE)) +#define BGP_INFO_HOLDDOWN(BI) \ + (!CHECK_FLAG((BI)->flags, BGP_INFO_VALID) \ + || CHECK_FLAG((BI)->flags, BGP_INFO_UNUSEABLE)) #define DISTRIBUTE_IN_NAME(F) ((F)->dlist[FILTER_IN].name) #define DISTRIBUTE_IN(F) ((F)->dlist[FILTER_IN].alist) @@ -275,168 +277,167 @@ struct bgp_static /* path PREFIX (addpath rxid NUMBER) */ #define PATH_ADDPATH_STR_BUFFER PREFIX2STR_BUFFER + 32 -enum bgp_path_type -{ - BGP_PATH_ALL, - BGP_PATH_BESTPATH, - BGP_PATH_MULTIPATH -}; +enum bgp_path_type { BGP_PATH_ALL, BGP_PATH_BESTPATH, BGP_PATH_MULTIPATH }; -static inline void -bgp_bump_version (struct bgp_node *node) +static inline void bgp_bump_version(struct bgp_node *node) { - node->version = bgp_table_next_version(bgp_node_table(node)); + node->version = bgp_table_next_version(bgp_node_table(node)); } -static inline int -bgp_fibupd_safi (safi_t safi) +static inline int bgp_fibupd_safi(safi_t safi) { - if (safi == SAFI_UNICAST || - safi == SAFI_MULTICAST || - safi == SAFI_LABELED_UNICAST) - return 1; - return 0; + if (safi == SAFI_UNICAST || safi == SAFI_MULTICAST + || safi == SAFI_LABELED_UNICAST) + return 1; + return 0; } /* Prototypes. */ -extern void bgp_process_queue_init (void); -extern void bgp_route_init (void); -extern void bgp_route_finish (void); -extern void bgp_cleanup_routes (struct bgp *); -extern void bgp_announce_route (struct peer *, afi_t, safi_t); +extern void bgp_process_queue_init(void); +extern void bgp_route_init(void); +extern void bgp_route_finish(void); +extern void bgp_cleanup_routes(struct bgp *); +extern void bgp_announce_route(struct peer *, afi_t, safi_t); extern void bgp_stop_announce_route_timer(struct peer_af *paf); -extern void bgp_announce_route_all (struct peer *); -extern void bgp_default_originate (struct peer *, afi_t, safi_t, int); -extern void bgp_soft_reconfig_in (struct peer *, afi_t, safi_t); -extern void bgp_clear_route (struct peer *, afi_t, safi_t); -extern void bgp_clear_route_all (struct peer *); -extern void bgp_clear_adj_in (struct peer *, afi_t, safi_t); -extern void bgp_clear_stale_route (struct peer *, afi_t, safi_t); - -extern struct bgp_node *bgp_afi_node_get (struct bgp_table *table, afi_t afi, - safi_t safi, struct prefix *p, - struct prefix_rd *prd); -extern struct bgp_info *bgp_info_lock (struct bgp_info *); -extern struct bgp_info *bgp_info_unlock (struct bgp_info *); -extern void bgp_info_add (struct bgp_node *rn, struct bgp_info *ri); -extern void bgp_info_reap (struct bgp_node *rn, struct bgp_info *ri); -extern void bgp_info_delete (struct bgp_node *rn, struct bgp_info *ri); -extern struct bgp_info_extra *bgp_info_extra_get (struct bgp_info *); -extern void bgp_info_set_flag (struct bgp_node *, struct bgp_info *, u_int32_t); -extern void bgp_info_unset_flag (struct bgp_node *, struct bgp_info *, u_int32_t); -extern void bgp_info_path_with_addpath_rx_str (struct bgp_info *ri, char *buf); - -extern int bgp_nlri_parse_ip (struct peer *, struct attr *, struct bgp_nlri *); - -extern int bgp_maximum_prefix_overflow (struct peer *, afi_t, safi_t, int); - -extern void bgp_redistribute_add (struct bgp *, struct prefix *, const struct in_addr *, - const struct in6_addr *, unsigned int ifindex, - u_int32_t, u_char, u_short, route_tag_t); -extern void bgp_redistribute_delete (struct bgp *, struct prefix *, u_char, u_short); -extern void bgp_redistribute_withdraw (struct bgp *, afi_t, int, u_short); - -extern void bgp_static_add (struct bgp *); -extern void bgp_static_delete (struct bgp *); -extern void bgp_static_redo_import_check (struct bgp *); -extern void bgp_purge_static_redist_routes (struct bgp *bgp); -extern void bgp_static_update (struct bgp *, struct prefix *, struct bgp_static *, - afi_t, safi_t); -extern void bgp_static_withdraw (struct bgp *, struct prefix *, afi_t, safi_t); - -extern int bgp_static_set_safi (afi_t afi, safi_t safi, struct vty *vty, const char *, - const char *, const char *, const char *, - int, const char *, const char *, const char *, const char *); - -extern int bgp_static_unset_safi (afi_t afi, safi_t safi, struct vty *, const char *, - const char *, const char *, - int, const char *, const char *, const char *); +extern void bgp_announce_route_all(struct peer *); +extern void bgp_default_originate(struct peer *, afi_t, safi_t, int); +extern void bgp_soft_reconfig_in(struct peer *, afi_t, safi_t); +extern void bgp_clear_route(struct peer *, afi_t, safi_t); +extern void bgp_clear_route_all(struct peer *); +extern void bgp_clear_adj_in(struct peer *, afi_t, safi_t); +extern void bgp_clear_stale_route(struct peer *, afi_t, safi_t); + +extern struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi, + safi_t safi, struct prefix *p, + struct prefix_rd *prd); +extern struct bgp_info *bgp_info_lock(struct bgp_info *); +extern struct bgp_info *bgp_info_unlock(struct bgp_info *); +extern void bgp_info_add(struct bgp_node *rn, struct bgp_info *ri); +extern void bgp_info_reap(struct bgp_node *rn, struct bgp_info *ri); +extern void bgp_info_delete(struct bgp_node *rn, struct bgp_info *ri); +extern struct bgp_info_extra *bgp_info_extra_get(struct bgp_info *); +extern void bgp_info_set_flag(struct bgp_node *, struct bgp_info *, u_int32_t); +extern void bgp_info_unset_flag(struct bgp_node *, struct bgp_info *, + u_int32_t); +extern void bgp_info_path_with_addpath_rx_str(struct bgp_info *ri, char *buf); + +extern int bgp_nlri_parse_ip(struct peer *, struct attr *, struct bgp_nlri *); + +extern int bgp_maximum_prefix_overflow(struct peer *, afi_t, safi_t, int); + +extern void bgp_redistribute_add(struct bgp *, struct prefix *, + const struct in_addr *, + const struct in6_addr *, unsigned int ifindex, + u_int32_t, u_char, u_short, route_tag_t); +extern void bgp_redistribute_delete(struct bgp *, struct prefix *, u_char, + u_short); +extern void bgp_redistribute_withdraw(struct bgp *, afi_t, int, u_short); + +extern void bgp_static_add(struct bgp *); +extern void bgp_static_delete(struct bgp *); +extern void bgp_static_redo_import_check(struct bgp *); +extern void bgp_purge_static_redist_routes(struct bgp *bgp); +extern void bgp_static_update(struct bgp *, struct prefix *, + struct bgp_static *, afi_t, safi_t); +extern void bgp_static_withdraw(struct bgp *, struct prefix *, afi_t, safi_t); + +extern int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty, + const char *, const char *, const char *, + const char *, int, const char *, const char *, + const char *, const char *); + +extern int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *, + const char *, const char *, const char *, int, + const char *, const char *, const char *); /* this is primarily for MPLS-VPN */ -extern int bgp_update (struct peer *, struct prefix *, u_int32_t, struct attr *, - afi_t, safi_t, int, int, struct prefix_rd *, - mpls_label_t *, int, struct bgp_route_evpn *); -extern int bgp_withdraw (struct peer *, struct prefix *, u_int32_t, struct attr *, - afi_t, safi_t, int, int, struct prefix_rd *, mpls_label_t *, - struct bgp_route_evpn *); +extern int bgp_update(struct peer *, struct prefix *, u_int32_t, struct attr *, + afi_t, safi_t, int, int, struct prefix_rd *, + mpls_label_t *, int, struct bgp_route_evpn *); +extern int bgp_withdraw(struct peer *, struct prefix *, u_int32_t, + struct attr *, afi_t, safi_t, int, int, + struct prefix_rd *, mpls_label_t *, + struct bgp_route_evpn *); /* for bgp_nexthop and bgp_damp */ -extern void bgp_process (struct bgp *, struct bgp_node *, afi_t, safi_t); +extern void bgp_process(struct bgp *, struct bgp_node *, afi_t, safi_t); /* * Add an end-of-initial-update marker to the process queue. This is just a * queue element with NULL bgp node. */ -extern void bgp_add_eoiu_mark (struct bgp *); -extern int bgp_config_write_table_map (struct vty *, struct bgp *, afi_t, safi_t, - int *); -extern int bgp_config_write_network (struct vty *, struct bgp *, afi_t, safi_t, int *); -extern int bgp_config_write_distance (struct vty *, struct bgp *, afi_t, safi_t, int *); - -extern void bgp_aggregate_increment (struct bgp *, struct prefix *, struct bgp_info *, - afi_t, safi_t); -extern void bgp_aggregate_decrement (struct bgp *, struct prefix *, struct bgp_info *, - afi_t, safi_t); - -extern u_char bgp_distance_apply (struct prefix *, struct bgp_info *, afi_t, safi_t, struct bgp *); - -extern afi_t bgp_node_afi (struct vty *); -extern safi_t bgp_node_safi (struct vty *); - -extern struct bgp_info * -info_make (int type, int sub_type, u_short instance, struct peer *peer, - struct attr *attr, struct bgp_node *rn); - -extern void route_vty_out (struct vty *, struct prefix *, struct bgp_info *, int, safi_t, json_object *); -extern void route_vty_out_tag (struct vty *, struct prefix *, struct bgp_info *, int, safi_t, json_object *); -extern void route_vty_out_tmp (struct vty *, struct prefix *, struct attr *, safi_t, u_char, json_object *); -extern void -route_vty_out_overlay (struct vty *vty, struct prefix *p, - struct bgp_info *binfo, int display, json_object *json); - -extern int -subgroup_process_announce_selected (struct update_subgroup *subgrp, - struct bgp_info *selected, - struct bgp_node *rn, - u_int32_t addpath_tx_id); +extern void bgp_add_eoiu_mark(struct bgp *); +extern int bgp_config_write_table_map(struct vty *, struct bgp *, afi_t, safi_t, + int *); +extern int bgp_config_write_network(struct vty *, struct bgp *, afi_t, safi_t, + int *); +extern int bgp_config_write_distance(struct vty *, struct bgp *, afi_t, safi_t, + int *); + +extern void bgp_aggregate_increment(struct bgp *, struct prefix *, + struct bgp_info *, afi_t, safi_t); +extern void bgp_aggregate_decrement(struct bgp *, struct prefix *, + struct bgp_info *, afi_t, safi_t); + +extern u_char bgp_distance_apply(struct prefix *, struct bgp_info *, afi_t, + safi_t, struct bgp *); + +extern afi_t bgp_node_afi(struct vty *); +extern safi_t bgp_node_safi(struct vty *); + +extern struct bgp_info *info_make(int type, int sub_type, u_short instance, + struct peer *peer, struct attr *attr, + struct bgp_node *rn); + +extern void route_vty_out(struct vty *, struct prefix *, struct bgp_info *, int, + safi_t, json_object *); +extern void route_vty_out_tag(struct vty *, struct prefix *, struct bgp_info *, + int, safi_t, json_object *); +extern void route_vty_out_tmp(struct vty *, struct prefix *, struct attr *, + safi_t, u_char, json_object *); +extern void route_vty_out_overlay(struct vty *vty, struct prefix *p, + struct bgp_info *binfo, int display, + json_object *json); + +extern int subgroup_process_announce_selected(struct update_subgroup *subgrp, + struct bgp_info *selected, + struct bgp_node *rn, + u_int32_t addpath_tx_id); extern int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, struct update_subgroup *subgrp, struct prefix *p, struct attr *attr); -extern void bgp_peer_clear_node_queue_drain_immediate (struct peer *peer); -extern void bgp_process_queues_drain_immediate (void); +extern void bgp_peer_clear_node_queue_drain_immediate(struct peer *peer); +extern void bgp_process_queues_drain_immediate(void); /* for encap/vpn */ -extern struct bgp_node * -bgp_afi_node_get (struct bgp_table *, afi_t , safi_t , struct prefix *, - struct prefix_rd *); -extern struct bgp_node * -bgp_afi_node_lookup (struct bgp_table *table, afi_t afi, safi_t safi, - struct prefix *p, struct prefix_rd *prd); -extern struct bgp_info *bgp_info_new (void); -extern void bgp_info_restore (struct bgp_node *, struct bgp_info *); - -extern int -bgp_info_cmp_compatible (struct bgp *, struct bgp_info *, struct bgp_info *, - char *pfx_buf, afi_t afi, safi_t safi); - -extern void -bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, - struct bgp_maxpaths_cfg *mpath_cfg, - struct bgp_info_pair *result, - afi_t afi, safi_t safi); -extern void bgp_zebra_clear_route_change_flags (struct bgp_node *rn); -extern int -bgp_zebra_has_route_changed (struct bgp_node *rn, struct bgp_info *selected); - -extern void -route_vty_out_detail_header (struct vty *vty, struct bgp *bgp, - struct bgp_node *rn, - struct prefix_rd *prd, afi_t afi, safi_t safi, - json_object *json); -extern void -route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, - struct bgp_info *binfo, afi_t afi, safi_t safi, - json_object *json_paths); +extern struct bgp_node *bgp_afi_node_get(struct bgp_table *, afi_t, safi_t, + struct prefix *, struct prefix_rd *); +extern struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi, + safi_t safi, struct prefix *p, + struct prefix_rd *prd); +extern struct bgp_info *bgp_info_new(void); +extern void bgp_info_restore(struct bgp_node *, struct bgp_info *); + +extern int bgp_info_cmp_compatible(struct bgp *, struct bgp_info *, + struct bgp_info *, char *pfx_buf, afi_t afi, + safi_t safi); + +extern void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, + struct bgp_maxpaths_cfg *mpath_cfg, + struct bgp_info_pair *result, afi_t afi, + safi_t safi); +extern void bgp_zebra_clear_route_change_flags(struct bgp_node *rn); +extern int bgp_zebra_has_route_changed(struct bgp_node *rn, + struct bgp_info *selected); + +extern void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp, + struct bgp_node *rn, + struct prefix_rd *prd, afi_t afi, + safi_t safi, json_object *json); +extern void route_vty_out_detail(struct vty *vty, struct bgp *bgp, + struct prefix *p, struct bgp_info *binfo, + afi_t afi, safi_t safi, + json_object *json_paths); #endif /* _QUAGGA_BGP_ROUTE_H */ diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index d08d04db4..285bb9a80 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -29,9 +29,9 @@ #include "memory.h" #include "log.h" #ifdef HAVE_LIBPCREPOSIX -# include +#include #else -# include +#include #endif /* HAVE_LIBPCREPOSIX */ #include "buffer.h" #include "sockunion.h" @@ -56,7 +56,7 @@ #include "bgpd/bgp_debug.h" #if ENABLE_BGP_VNC -# include "bgpd/rfapi/bgp_rfapi_cfg.h" +#include "bgpd/rfapi/bgp_rfapi_cfg.h" #endif /* Memo of route-map commands. @@ -111,2933 +111,2670 @@ o Local extensions */ - /* generic value manipulation to be shared in multiple rules */ +/* generic value manipulation to be shared in multiple rules */ #define RMAP_VALUE_SET 0 #define RMAP_VALUE_ADD 1 #define RMAP_VALUE_SUB 2 -struct rmap_value -{ - u_int8_t action; - u_int8_t variable; - u_int32_t value; +struct rmap_value { + u_int8_t action; + u_int8_t variable; + u_int32_t value; }; -static int -route_value_match (struct rmap_value *rv, u_int32_t value) -{ - if (rv->variable == 0 && value == rv->value) - return RMAP_MATCH; +static int route_value_match(struct rmap_value *rv, u_int32_t value) +{ + if (rv->variable == 0 && value == rv->value) + return RMAP_MATCH; - return RMAP_NOMATCH; + return RMAP_NOMATCH; } -static u_int32_t -route_value_adjust (struct rmap_value *rv, u_int32_t current, struct peer *peer) +static u_int32_t route_value_adjust(struct rmap_value *rv, u_int32_t current, + struct peer *peer) { - u_int32_t value; + u_int32_t value; - switch (rv->variable) - { - case 1: - value = peer->rtt; - break; - default: - value = rv->value; - break; - } + switch (rv->variable) { + case 1: + value = peer->rtt; + break; + default: + value = rv->value; + break; + } - switch (rv->action) - { - case RMAP_VALUE_ADD: - if (current > UINT32_MAX-value) - return UINT32_MAX; - return current + value; - case RMAP_VALUE_SUB: - if (current <= value) - return 0; - return current - value; - default: - return value; - } + switch (rv->action) { + case RMAP_VALUE_ADD: + if (current > UINT32_MAX - value) + return UINT32_MAX; + return current + value; + case RMAP_VALUE_SUB: + if (current <= value) + return 0; + return current - value; + default: + return value; + } } -static void * -route_value_compile (const char *arg) +static void *route_value_compile(const char *arg) { - u_int8_t action = RMAP_VALUE_SET, var = 0; - unsigned long larg = 0; - char *endptr = NULL; - struct rmap_value *rv; + u_int8_t action = RMAP_VALUE_SET, var = 0; + unsigned long larg = 0; + char *endptr = NULL; + struct rmap_value *rv; - if (arg[0] == '+') - { - action = RMAP_VALUE_ADD; - arg++; - } - else if (arg[0] == '-') - { - action = RMAP_VALUE_SUB; - arg++; - } + if (arg[0] == '+') { + action = RMAP_VALUE_ADD; + arg++; + } else if (arg[0] == '-') { + action = RMAP_VALUE_SUB; + arg++; + } - if (all_digit(arg)) - { - errno = 0; - larg = strtoul (arg, &endptr, 10); - if (*arg == 0 || *endptr != 0 || errno || larg > UINT32_MAX) - return NULL; - } - else - { - if (strcmp(arg, "rtt") == 0) - var = 1; - else - return NULL; - } + if (all_digit(arg)) { + errno = 0; + larg = strtoul(arg, &endptr, 10); + if (*arg == 0 || *endptr != 0 || errno || larg > UINT32_MAX) + return NULL; + } else { + if (strcmp(arg, "rtt") == 0) + var = 1; + else + return NULL; + } - rv = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value)); - if (!rv) - return NULL; + rv = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value)); + if (!rv) + return NULL; - rv->action = action; - rv->variable = var; - rv->value = larg; - return rv; + rv->action = action; + rv->variable = var; + rv->value = larg; + return rv; } -static void -route_value_free (void *rule) +static void route_value_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } - /* generic as path object to be shared in multiple rules */ +/* generic as path object to be shared in multiple rules */ -static void * -route_aspath_compile (const char *arg) +static void *route_aspath_compile(const char *arg) { - struct aspath *aspath; + struct aspath *aspath; - aspath = aspath_str2aspath (arg); - if (! aspath) - return NULL; - return aspath; + aspath = aspath_str2aspath(arg); + if (!aspath) + return NULL; + return aspath; } -static void -route_aspath_free (void *rule) +static void route_aspath_free(void *rule) { - struct aspath *aspath = rule; - aspath_free (aspath); + struct aspath *aspath = rule; + aspath_free(aspath); } - /* 'match peer (A.B.C.D|X:X::X:X)' */ +/* 'match peer (A.B.C.D|X:X::X:X)' */ /* Compares the peer specified in the 'match peer' clause with the peer received in bgp_info->peer. If it is the same, or if the peer structure received is a peer_group containing it, returns RMAP_MATCH. */ -static route_map_result_t -route_match_peer (void *rule, struct prefix *prefix, route_map_object_t type, - void *object) -{ - union sockunion *su; - union sockunion su_def = { .sin = { .sin_family = AF_INET, - .sin_addr.s_addr = INADDR_ANY } }; - struct peer_group *group; - struct peer *peer; - struct listnode *node, *nnode; - - if (type == RMAP_BGP) - { - su = rule; - peer = ((struct bgp_info *) object)->peer; - - if ( ! CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT) && - ! CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_EXPORT) ) - return RMAP_NOMATCH; - - /* If su='0.0.0.0' (command 'match peer local'), and it's a NETWORK, - REDISTRIBUTE or DEFAULT_GENERATED route => return RMAP_MATCH */ - if (sockunion_same (su, &su_def)) - { - int ret; - if ( CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_NETWORK) || - CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE) || - CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_DEFAULT)) - ret = RMAP_MATCH; - else - ret = RMAP_NOMATCH; - return ret; - } - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (sockunion_same (su, &peer->su)) - return RMAP_MATCH; - - return RMAP_NOMATCH; - } - else - { - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (sockunion_same (su, &peer->su)) - return RMAP_MATCH; - } - return RMAP_NOMATCH; - } - } - return RMAP_NOMATCH; -} - -static void * -route_match_peer_compile (const char *arg) -{ - union sockunion *su; - int ret; - - su = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (union sockunion)); - - ret = str2sockunion (strcmp(arg, "local") ? arg : "0.0.0.0", su); - if (ret < 0) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, su); - return NULL; - } - - return su; +static route_map_result_t route_match_peer(void *rule, struct prefix *prefix, + route_map_object_t type, + void *object) +{ + union sockunion *su; + union sockunion su_def = { + .sin = {.sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY}}; + struct peer_group *group; + struct peer *peer; + struct listnode *node, *nnode; + + if (type == RMAP_BGP) { + su = rule; + peer = ((struct bgp_info *)object)->peer; + + if (!CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT) + && !CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_EXPORT)) + return RMAP_NOMATCH; + + /* If su='0.0.0.0' (command 'match peer local'), and it's a + NETWORK, + REDISTRIBUTE or DEFAULT_GENERATED route => return RMAP_MATCH + */ + if (sockunion_same(su, &su_def)) { + int ret; + if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_NETWORK) + || CHECK_FLAG(peer->rmap_type, + PEER_RMAP_TYPE_REDISTRIBUTE) + || CHECK_FLAG(peer->rmap_type, + PEER_RMAP_TYPE_DEFAULT)) + ret = RMAP_MATCH; + else + ret = RMAP_NOMATCH; + return ret; + } + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (sockunion_same(su, &peer->su)) + return RMAP_MATCH; + + return RMAP_NOMATCH; + } else { + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, + peer)) { + if (sockunion_same(su, &peer->su)) + return RMAP_MATCH; + } + return RMAP_NOMATCH; + } + } + return RMAP_NOMATCH; +} + +static void *route_match_peer_compile(const char *arg) +{ + union sockunion *su; + int ret; + + su = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(union sockunion)); + + ret = str2sockunion(strcmp(arg, "local") ? arg : "0.0.0.0", su); + if (ret < 0) { + XFREE(MTYPE_ROUTE_MAP_COMPILED, su); + return NULL; + } + + return su; } /* Free route map's compiled `ip address' value. */ -static void -route_match_peer_free (void *rule) +static void route_match_peer_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip address matching. */ -struct route_map_rule_cmd route_match_peer_cmd = -{ - "peer", - route_match_peer, - route_match_peer_compile, - route_match_peer_free -}; +struct route_map_rule_cmd route_match_peer_cmd = {"peer", route_match_peer, + route_match_peer_compile, + route_match_peer_free}; /* `match ip address IP_ACCESS_LIST' */ /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t -route_match_ip_address (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct access_list *alist; - /* struct prefix_ipv4 match; */ - - if (type == RMAP_BGP) - { - alist = access_list_lookup (AFI_IP, (char *) rule); - if (alist == NULL) +static route_map_result_t route_match_ip_address(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct access_list *alist; + /* struct prefix_ipv4 match; */ + + if (type == RMAP_BGP) { + alist = access_list_lookup(AFI_IP, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; + + return (access_list_apply(alist, prefix) == FILTER_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } return RMAP_NOMATCH; - - return (access_list_apply (alist, prefix) == FILTER_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; } /* Route map `ip address' match statement. `arg' should be access-list name. */ -static void * -route_match_ip_address_compile (const char *arg) +static void *route_match_ip_address_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `ip address' value. */ -static void -route_match_ip_address_free (void *rule) +static void route_match_ip_address_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip address matching. */ -struct route_map_rule_cmd route_match_ip_address_cmd = -{ - "ip address", - route_match_ip_address, - route_match_ip_address_compile, - route_match_ip_address_free -}; +struct route_map_rule_cmd route_match_ip_address_cmd = { + "ip address", route_match_ip_address, route_match_ip_address_compile, + route_match_ip_address_free}; /* `match ip next-hop IP_ADDRESS' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_ip_next_hop (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct access_list *alist; - struct bgp_info *bgp_info; - struct prefix_ipv4 p; - - if (type == RMAP_BGP) - { - bgp_info = object; - p.family = AF_INET; - p.prefix = bgp_info->attr->nexthop; - p.prefixlen = IPV4_MAX_BITLEN; - - alist = access_list_lookup (AFI_IP, (char *) rule); - if (alist == NULL) +static route_map_result_t route_match_ip_next_hop(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct access_list *alist; + struct bgp_info *bgp_info; + struct prefix_ipv4 p; + + if (type == RMAP_BGP) { + bgp_info = object; + p.family = AF_INET; + p.prefix = bgp_info->attr->nexthop; + p.prefixlen = IPV4_MAX_BITLEN; + + alist = access_list_lookup(AFI_IP, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; + + return (access_list_apply(alist, &p) == FILTER_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } return RMAP_NOMATCH; - - return (access_list_apply (alist, &p) == FILTER_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; } /* Route map `ip next-hop' match statement. `arg' is access-list name. */ -static void * -route_match_ip_next_hop_compile (const char *arg) +static void *route_match_ip_next_hop_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `ip address' value. */ -static void -route_match_ip_next_hop_free (void *rule) +static void route_match_ip_next_hop_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip next-hop matching. */ -struct route_map_rule_cmd route_match_ip_next_hop_cmd = -{ - "ip next-hop", - route_match_ip_next_hop, - route_match_ip_next_hop_compile, - route_match_ip_next_hop_free -}; +struct route_map_rule_cmd route_match_ip_next_hop_cmd = { + "ip next-hop", route_match_ip_next_hop, route_match_ip_next_hop_compile, + route_match_ip_next_hop_free}; /* `match ip route-source ACCESS-LIST' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_ip_route_source (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct access_list *alist; - struct bgp_info *bgp_info; - struct peer *peer; - struct prefix_ipv4 p; - - if (type == RMAP_BGP) - { - bgp_info = object; - peer = bgp_info->peer; - - if (! peer || sockunion_family (&peer->su) != AF_INET) - return RMAP_NOMATCH; - - p.family = AF_INET; - p.prefix = peer->su.sin.sin_addr; - p.prefixlen = IPV4_MAX_BITLEN; - - alist = access_list_lookup (AFI_IP, (char *) rule); - if (alist == NULL) +static route_map_result_t route_match_ip_route_source(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct access_list *alist; + struct bgp_info *bgp_info; + struct peer *peer; + struct prefix_ipv4 p; + + if (type == RMAP_BGP) { + bgp_info = object; + peer = bgp_info->peer; + + if (!peer || sockunion_family(&peer->su) != AF_INET) + return RMAP_NOMATCH; + + p.family = AF_INET; + p.prefix = peer->su.sin.sin_addr; + p.prefixlen = IPV4_MAX_BITLEN; + + alist = access_list_lookup(AFI_IP, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; + + return (access_list_apply(alist, &p) == FILTER_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } return RMAP_NOMATCH; - - return (access_list_apply (alist, &p) == FILTER_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; } /* Route map `ip route-source' match statement. `arg' is access-list name. */ -static void * -route_match_ip_route_source_compile (const char *arg) +static void *route_match_ip_route_source_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `ip address' value. */ -static void -route_match_ip_route_source_free (void *rule) +static void route_match_ip_route_source_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip route-source matching. */ -struct route_map_rule_cmd route_match_ip_route_source_cmd = -{ - "ip route-source", - route_match_ip_route_source, - route_match_ip_route_source_compile, - route_match_ip_route_source_free -}; +struct route_map_rule_cmd route_match_ip_route_source_cmd = { + "ip route-source", route_match_ip_route_source, + route_match_ip_route_source_compile, route_match_ip_route_source_free}; /* `match ip address prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_address_prefix_list (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - struct prefix_list *plist; + struct prefix_list *plist; - if (type == RMAP_BGP) - { - plist = prefix_list_lookup (AFI_IP, (char *) rule); - if (plist == NULL) - return RMAP_NOMATCH; + if (type == RMAP_BGP) { + plist = prefix_list_lookup(AFI_IP, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; - return (prefix_list_apply (plist, prefix) == PREFIX_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; + return (prefix_list_apply(plist, prefix) == PREFIX_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } + return RMAP_NOMATCH; } -static void * -route_match_ip_address_prefix_list_compile (const char *arg) +static void *route_match_ip_address_prefix_list_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ip_address_prefix_list_free (void *rule) +static void route_match_ip_address_prefix_list_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = -{ - "ip address prefix-list", - route_match_ip_address_prefix_list, - route_match_ip_address_prefix_list_compile, - route_match_ip_address_prefix_list_free -}; +struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { + "ip address prefix-list", route_match_ip_address_prefix_list, + route_match_ip_address_prefix_list_compile, + route_match_ip_address_prefix_list_free}; /* `match ip next-hop prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - struct prefix_list *plist; - struct bgp_info *bgp_info; - struct prefix_ipv4 p; + struct prefix_list *plist; + struct bgp_info *bgp_info; + struct prefix_ipv4 p; - if (type == RMAP_BGP) - { - bgp_info = object; - p.family = AF_INET; - p.prefix = bgp_info->attr->nexthop; - p.prefixlen = IPV4_MAX_BITLEN; + if (type == RMAP_BGP) { + bgp_info = object; + p.family = AF_INET; + p.prefix = bgp_info->attr->nexthop; + p.prefixlen = IPV4_MAX_BITLEN; - plist = prefix_list_lookup (AFI_IP, (char *) rule); - if (plist == NULL) - return RMAP_NOMATCH; + plist = prefix_list_lookup(AFI_IP, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; - return (prefix_list_apply (plist, &p) == PREFIX_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; + return (prefix_list_apply(plist, &p) == PREFIX_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } + return RMAP_NOMATCH; } -static void * -route_match_ip_next_hop_prefix_list_compile (const char *arg) +static void *route_match_ip_next_hop_prefix_list_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ip_next_hop_prefix_list_free (void *rule) +static void route_match_ip_next_hop_prefix_list_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = -{ - "ip next-hop prefix-list", - route_match_ip_next_hop_prefix_list, - route_match_ip_next_hop_prefix_list_compile, - route_match_ip_next_hop_prefix_list_free -}; +struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = { + "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list, + route_match_ip_next_hop_prefix_list_compile, + route_match_ip_next_hop_prefix_list_free}; /* `match ip route-source prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_route_source_prefix_list (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_route_source_prefix_list(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - struct prefix_list *plist; - struct bgp_info *bgp_info; - struct peer *peer; - struct prefix_ipv4 p; + struct prefix_list *plist; + struct bgp_info *bgp_info; + struct peer *peer; + struct prefix_ipv4 p; - if (type == RMAP_BGP) - { - bgp_info = object; - peer = bgp_info->peer; + if (type == RMAP_BGP) { + bgp_info = object; + peer = bgp_info->peer; - if (! peer || sockunion_family (&peer->su) != AF_INET) - return RMAP_NOMATCH; + if (!peer || sockunion_family(&peer->su) != AF_INET) + return RMAP_NOMATCH; - p.family = AF_INET; - p.prefix = peer->su.sin.sin_addr; - p.prefixlen = IPV4_MAX_BITLEN; + p.family = AF_INET; + p.prefix = peer->su.sin.sin_addr; + p.prefixlen = IPV4_MAX_BITLEN; - plist = prefix_list_lookup (AFI_IP, (char *) rule); - if (plist == NULL) - return RMAP_NOMATCH; + plist = prefix_list_lookup(AFI_IP, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; - return (prefix_list_apply (plist, &p) == PREFIX_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; + return (prefix_list_apply(plist, &p) == PREFIX_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } + return RMAP_NOMATCH; } -static void * -route_match_ip_route_source_prefix_list_compile (const char *arg) +static void *route_match_ip_route_source_prefix_list_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ip_route_source_prefix_list_free (void *rule) +static void route_match_ip_route_source_prefix_list_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd = -{ - "ip route-source prefix-list", - route_match_ip_route_source_prefix_list, - route_match_ip_route_source_prefix_list_compile, - route_match_ip_route_source_prefix_list_free -}; +struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd = { + "ip route-source prefix-list", route_match_ip_route_source_prefix_list, + route_match_ip_route_source_prefix_list_compile, + route_match_ip_route_source_prefix_list_free}; /* `match local-preference LOCAL-PREF' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_local_pref (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - u_int32_t *local_pref; - struct bgp_info *bgp_info; - - if (type == RMAP_BGP) - { - local_pref = rule; - bgp_info = object; - - if (bgp_info->attr->local_pref == *local_pref) - return RMAP_MATCH; - else +static route_map_result_t route_match_local_pref(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + u_int32_t *local_pref; + struct bgp_info *bgp_info; + + if (type == RMAP_BGP) { + local_pref = rule; + bgp_info = object; + + if (bgp_info->attr->local_pref == *local_pref) + return RMAP_MATCH; + else + return RMAP_NOMATCH; + } return RMAP_NOMATCH; - } - return RMAP_NOMATCH; } /* Route map `match local-preference' match statement. `arg' is local-pref value */ -static void * -route_match_local_pref_compile (const char *arg) +static void *route_match_local_pref_compile(const char *arg) { - u_int32_t *local_pref; - char *endptr = NULL; - unsigned long tmpval; + u_int32_t *local_pref; + char *endptr = NULL; + unsigned long tmpval; - /* Locpref value shoud be integer. */ - if (! all_digit (arg)) - return NULL; + /* Locpref value shoud be integer. */ + if (!all_digit(arg)) + return NULL; - errno = 0; - tmpval = strtoul (arg, &endptr, 10); - if (*endptr != '\0' || errno || tmpval > UINT32_MAX) - return NULL; + errno = 0; + tmpval = strtoul(arg, &endptr, 10); + if (*endptr != '\0' || errno || tmpval > UINT32_MAX) + return NULL; - local_pref = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); + local_pref = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t)); - if (!local_pref) - return local_pref; + if (!local_pref) + return local_pref; - *local_pref = tmpval; - return local_pref; + *local_pref = tmpval; + return local_pref; } /* Free route map's compiled `match local-preference' value. */ -static void -route_match_local_pref_free (void *rule) +static void route_match_local_pref_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for metric matching. */ -struct route_map_rule_cmd route_match_local_pref_cmd = -{ - "local-preference", - route_match_local_pref, - route_match_local_pref_compile, - route_match_local_pref_free -}; +struct route_map_rule_cmd route_match_local_pref_cmd = { + "local-preference", route_match_local_pref, + route_match_local_pref_compile, route_match_local_pref_free}; /* `match metric METRIC' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_metric (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_metric(void *rule, struct prefix *prefix, + route_map_object_t type, + void *object) { - struct rmap_value *rv; - struct bgp_info *bgp_info; + struct rmap_value *rv; + struct bgp_info *bgp_info; - if (type == RMAP_BGP) - { - rv = rule; - bgp_info = object; - return route_value_match(rv, bgp_info->attr->med); - } - return RMAP_NOMATCH; + if (type == RMAP_BGP) { + rv = rule; + bgp_info = object; + return route_value_match(rv, bgp_info->attr->med); + } + return RMAP_NOMATCH; } /* Route map commands for metric matching. */ -struct route_map_rule_cmd route_match_metric_cmd = -{ - "metric", - route_match_metric, - route_value_compile, - route_value_free, +struct route_map_rule_cmd route_match_metric_cmd = { + "metric", route_match_metric, route_value_compile, route_value_free, }; /* `match as-path ASPATH' */ /* Match function for as-path match. I assume given object is */ -static route_map_result_t -route_match_aspath (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_aspath(void *rule, struct prefix *prefix, + route_map_object_t type, + void *object) { - struct as_list *as_list; - struct bgp_info *bgp_info; + struct as_list *as_list; + struct bgp_info *bgp_info; - if (type == RMAP_BGP) - { - as_list = as_list_lookup ((char *) rule); - if (as_list == NULL) - return RMAP_NOMATCH; + if (type == RMAP_BGP) { + as_list = as_list_lookup((char *)rule); + if (as_list == NULL) + return RMAP_NOMATCH; - bgp_info = object; + bgp_info = object; - /* Perform match. */ - return ((as_list_apply (as_list, bgp_info->attr->aspath) == AS_FILTER_DENY) ? RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; + /* Perform match. */ + return ((as_list_apply(as_list, bgp_info->attr->aspath) + == AS_FILTER_DENY) + ? RMAP_NOMATCH + : RMAP_MATCH); + } + return RMAP_NOMATCH; } /* Compile function for as-path match. */ -static void * -route_match_aspath_compile (const char *arg) +static void *route_match_aspath_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Compile function for as-path match. */ -static void -route_match_aspath_free (void *rule) +static void route_match_aspath_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for aspath matching. */ -struct route_map_rule_cmd route_match_aspath_cmd = -{ - "as-path", - route_match_aspath, - route_match_aspath_compile, - route_match_aspath_free -}; +struct route_map_rule_cmd route_match_aspath_cmd = { + "as-path", route_match_aspath, route_match_aspath_compile, + route_match_aspath_free}; /* `match community COMMUNIY' */ -struct rmap_community -{ - char *name; - int exact; +struct rmap_community { + char *name; + int exact; }; /* Match function for community match. */ -static route_map_result_t -route_match_community (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct community_list *list; - struct bgp_info *bgp_info; - struct rmap_community *rcom; - - if (type == RMAP_BGP) - { - bgp_info = object; - rcom = rule; - - list = community_list_lookup (bgp_clist, rcom->name, COMMUNITY_LIST_MASTER); - if (! list) - return RMAP_NOMATCH; - - if (rcom->exact) - { - if (community_list_exact_match (bgp_info->attr->community, list)) - return RMAP_MATCH; - } - else - { - if (community_list_match (bgp_info->attr->community, list)) - return RMAP_MATCH; +static route_map_result_t route_match_community(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct community_list *list; + struct bgp_info *bgp_info; + struct rmap_community *rcom; + + if (type == RMAP_BGP) { + bgp_info = object; + rcom = rule; + + list = community_list_lookup(bgp_clist, rcom->name, + COMMUNITY_LIST_MASTER); + if (!list) + return RMAP_NOMATCH; + + if (rcom->exact) { + if (community_list_exact_match( + bgp_info->attr->community, list)) + return RMAP_MATCH; + } else { + if (community_list_match(bgp_info->attr->community, + list)) + return RMAP_MATCH; + } } - } - return RMAP_NOMATCH; + return RMAP_NOMATCH; } /* Compile function for community match. */ -static void * -route_match_community_compile (const char *arg) -{ - struct rmap_community *rcom; - int len; - char *p; - - rcom = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_community)); - - p = strchr (arg, ' '); - if (p) - { - len = p - arg; - rcom->name = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1); - memcpy (rcom->name, arg, len); - rcom->exact = 1; - } - else - { - rcom->name = XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); - rcom->exact = 0; - } - return rcom; +static void *route_match_community_compile(const char *arg) +{ + struct rmap_community *rcom; + int len; + char *p; + + rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community)); + + p = strchr(arg, ' '); + if (p) { + len = p - arg; + rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1); + memcpy(rcom->name, arg, len); + rcom->exact = 1; + } else { + rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); + rcom->exact = 0; + } + return rcom; } /* Compile function for community match. */ -static void -route_match_community_free (void *rule) +static void route_match_community_free(void *rule) { - struct rmap_community *rcom = rule; + struct rmap_community *rcom = rule; - XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom->name); - XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom); } /* Route map commands for community matching. */ -struct route_map_rule_cmd route_match_community_cmd = -{ - "community", - route_match_community, - route_match_community_compile, - route_match_community_free -}; +struct route_map_rule_cmd route_match_community_cmd = { + "community", route_match_community, route_match_community_compile, + route_match_community_free}; /* Match function for lcommunity match. */ -static route_map_result_t -route_match_lcommunity (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct community_list *list; - struct bgp_info *bgp_info; - struct rmap_community *rcom; - - if (type == RMAP_BGP) - { - bgp_info = object; - rcom = rule; - - list = community_list_lookup (bgp_clist, rcom->name, - LARGE_COMMUNITY_LIST_MASTER); - if (! list) - return RMAP_NOMATCH; - - if (lcommunity_list_match (bgp_info->attr->lcommunity, list)) - return RMAP_MATCH; - - } - return RMAP_NOMATCH; +static route_map_result_t route_match_lcommunity(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct community_list *list; + struct bgp_info *bgp_info; + struct rmap_community *rcom; + + if (type == RMAP_BGP) { + bgp_info = object; + rcom = rule; + + list = community_list_lookup(bgp_clist, rcom->name, + LARGE_COMMUNITY_LIST_MASTER); + if (!list) + return RMAP_NOMATCH; + + if (lcommunity_list_match(bgp_info->attr->lcommunity, list)) + return RMAP_MATCH; + } + return RMAP_NOMATCH; } /* Compile function for community match. */ -static void * -route_match_lcommunity_compile (const char *arg) -{ - struct rmap_community *rcom; - int len; - char *p; - - rcom = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_community)); - - p = strchr (arg, ' '); - if (p) - { - len = p - arg; - rcom->name = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1); - memcpy (rcom->name, arg, len); - } - else - { - rcom->name = XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); - rcom->exact = 0; - } - return rcom; +static void *route_match_lcommunity_compile(const char *arg) +{ + struct rmap_community *rcom; + int len; + char *p; + + rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community)); + + p = strchr(arg, ' '); + if (p) { + len = p - arg; + rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1); + memcpy(rcom->name, arg, len); + } else { + rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); + rcom->exact = 0; + } + return rcom; } /* Compile function for community match. */ -static void -route_match_lcommunity_free (void *rule) +static void route_match_lcommunity_free(void *rule) { - struct rmap_community *rcom = rule; + struct rmap_community *rcom = rule; - XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom->name); - XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom); } /* Route map commands for community matching. */ -struct route_map_rule_cmd route_match_lcommunity_cmd = -{ - "large-community", - route_match_lcommunity, - route_match_lcommunity_compile, - route_match_lcommunity_free -}; +struct route_map_rule_cmd route_match_lcommunity_cmd = { + "large-community", route_match_lcommunity, + route_match_lcommunity_compile, route_match_lcommunity_free}; /* Match function for extcommunity match. */ -static route_map_result_t -route_match_ecommunity (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_ecommunity(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct community_list *list; - struct bgp_info *bgp_info; + struct community_list *list; + struct bgp_info *bgp_info; - if (type == RMAP_BGP) - { - bgp_info = object; + if (type == RMAP_BGP) { + bgp_info = object; - list = community_list_lookup (bgp_clist, (char *) rule, - EXTCOMMUNITY_LIST_MASTER); - if (! list) - return RMAP_NOMATCH; + list = community_list_lookup(bgp_clist, (char *)rule, + EXTCOMMUNITY_LIST_MASTER); + if (!list) + return RMAP_NOMATCH; - if (ecommunity_list_match (bgp_info->attr->ecommunity, list)) - return RMAP_MATCH; - } - return RMAP_NOMATCH; + if (ecommunity_list_match(bgp_info->attr->ecommunity, list)) + return RMAP_MATCH; + } + return RMAP_NOMATCH; } /* Compile function for extcommunity match. */ -static void * -route_match_ecommunity_compile (const char *arg) +static void *route_match_ecommunity_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Compile function for extcommunity match. */ -static void -route_match_ecommunity_free (void *rule) +static void route_match_ecommunity_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for community matching. */ -struct route_map_rule_cmd route_match_ecommunity_cmd = -{ - "extcommunity", - route_match_ecommunity, - route_match_ecommunity_compile, - route_match_ecommunity_free -}; +struct route_map_rule_cmd route_match_ecommunity_cmd = { + "extcommunity", route_match_ecommunity, route_match_ecommunity_compile, + route_match_ecommunity_free}; /* `match nlri` and `set nlri` are replaced by `address-family ipv4` and `address-family vpnv4'. */ /* `match origin' */ -static route_map_result_t -route_match_origin (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_origin(void *rule, struct prefix *prefix, + route_map_object_t type, + void *object) { - u_char *origin; - struct bgp_info *bgp_info; + u_char *origin; + struct bgp_info *bgp_info; - if (type == RMAP_BGP) - { - origin = rule; - bgp_info = object; + if (type == RMAP_BGP) { + origin = rule; + bgp_info = object; - if (bgp_info->attr->origin == *origin) - return RMAP_MATCH; - } + if (bgp_info->attr->origin == *origin) + return RMAP_MATCH; + } - return RMAP_NOMATCH; + return RMAP_NOMATCH; } -static void * -route_match_origin_compile (const char *arg) +static void *route_match_origin_compile(const char *arg) { - u_char *origin; + u_char *origin; - origin = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_char)); + origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_char)); - if (strcmp (arg, "igp") == 0) - *origin = 0; - else if (strcmp (arg, "egp") == 0) - *origin = 1; - else - *origin = 2; + if (strcmp(arg, "igp") == 0) + *origin = 0; + else if (strcmp(arg, "egp") == 0) + *origin = 1; + else + *origin = 2; - return origin; + return origin; } /* Free route map's compiled `ip address' value. */ -static void -route_match_origin_free (void *rule) +static void route_match_origin_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for origin matching. */ -struct route_map_rule_cmd route_match_origin_cmd = -{ - "origin", - route_match_origin, - route_match_origin_compile, - route_match_origin_free -}; +struct route_map_rule_cmd route_match_origin_cmd = { + "origin", route_match_origin, route_match_origin_compile, + route_match_origin_free}; /* match probability { */ -static route_map_result_t -route_match_probability (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - long r = random(); - - switch (*(long *) rule) - { - case 0: break; - case RAND_MAX: return RMAP_MATCH; - default: - if (r < *(long *) rule) - { - return RMAP_MATCH; - } - } +static route_map_result_t route_match_probability(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + long r = random(); + + switch (*(long *)rule) { + case 0: + break; + case RAND_MAX: + return RMAP_MATCH; + default: + if (r < *(long *)rule) { + return RMAP_MATCH; + } + } - return RMAP_NOMATCH; + return RMAP_NOMATCH; } -static void * -route_match_probability_compile (const char *arg) +static void *route_match_probability_compile(const char *arg) { - long *lobule; - unsigned perc; + long *lobule; + unsigned perc; - perc = atoi (arg); - lobule = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (long)); + perc = atoi(arg); + lobule = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(long)); - switch (perc) - { - case 0: *lobule = 0; break; - case 100: *lobule = RAND_MAX; break; - default: *lobule = RAND_MAX / 100 * perc; - } + switch (perc) { + case 0: + *lobule = 0; + break; + case 100: + *lobule = RAND_MAX; + break; + default: + *lobule = RAND_MAX / 100 * perc; + } - return lobule; + return lobule; } -static void -route_match_probability_free (void *rule) +static void route_match_probability_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -struct route_map_rule_cmd route_match_probability_cmd = -{ - "probability", - route_match_probability, - route_match_probability_compile, - route_match_probability_free -}; +struct route_map_rule_cmd route_match_probability_cmd = { + "probability", route_match_probability, route_match_probability_compile, + route_match_probability_free}; /* `match interface IFNAME' */ /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t -route_match_interface (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_interface(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct interface *ifp; - struct bgp_info *info; + struct interface *ifp; + struct bgp_info *info; - if (type == RMAP_BGP) - { - info = object; + if (type == RMAP_BGP) { + info = object; - if (!info || !info->attr) - return RMAP_NOMATCH; + if (!info || !info->attr) + return RMAP_NOMATCH; - ifp = if_lookup_by_name_all_vrf ((char *)rule); + ifp = if_lookup_by_name_all_vrf((char *)rule); - if (ifp == NULL || ifp->ifindex != info->attr->nh_ifindex) - return RMAP_NOMATCH; + if (ifp == NULL || ifp->ifindex != info->attr->nh_ifindex) + return RMAP_NOMATCH; - return RMAP_MATCH; - } - return RMAP_NOMATCH; + return RMAP_MATCH; + } + return RMAP_NOMATCH; } /* Route map `interface' match statement. `arg' should be interface name. */ -static void * -route_match_interface_compile (const char *arg) +static void *route_match_interface_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `interface' value. */ -static void -route_match_interface_free (void *rule) +static void route_match_interface_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip address matching. */ -struct route_map_rule_cmd route_match_interface_cmd = -{ - "interface", - route_match_interface, - route_match_interface_compile, - route_match_interface_free -}; +struct route_map_rule_cmd route_match_interface_cmd = { + "interface", route_match_interface, route_match_interface_compile, + route_match_interface_free}; /* } */ /* `set ip next-hop IP_ADDRESS' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_tag (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_tag(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - route_tag_t *tag; - struct bgp_info *bgp_info; + route_tag_t *tag; + struct bgp_info *bgp_info; - if (type == RMAP_BGP) - { - tag = rule; - bgp_info = object; + if (type == RMAP_BGP) { + tag = rule; + bgp_info = object; - return ((bgp_info->attr->tag == *tag)? RMAP_MATCH : RMAP_NOMATCH); - } + return ((bgp_info->attr->tag == *tag) ? RMAP_MATCH + : RMAP_NOMATCH); + } - return RMAP_NOMATCH; + return RMAP_NOMATCH; } /* Route map commands for tag matching. */ -static struct route_map_rule_cmd route_match_tag_cmd = -{ - "tag", - route_match_tag, - route_map_rule_tag_compile, - route_map_rule_tag_free, +static struct route_map_rule_cmd route_match_tag_cmd = { + "tag", route_match_tag, route_map_rule_tag_compile, + route_map_rule_tag_free, }; /* Set nexthop to object. ojbect must be pointer to struct attr. */ -struct rmap_ip_nexthop_set -{ - struct in_addr *address; - int peer_address; - int unchanged; +struct rmap_ip_nexthop_set { + struct in_addr *address; + int peer_address; + int unchanged; }; -static route_map_result_t -route_set_ip_nexthop (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct rmap_ip_nexthop_set *rins = rule; - struct bgp_info *bgp_info; - struct peer *peer; - - if (type == RMAP_BGP) - { - bgp_info = object; - peer = bgp_info->peer; - - if (rins->unchanged) - { - SET_FLAG(bgp_info->attr->rmap_change_flags, - BATTR_RMAP_NEXTHOP_UNCHANGED); - } - else if (rins->peer_address) - { - if ((CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN) || - CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) - && peer->su_remote - && sockunion_family (peer->su_remote) == AF_INET) - { - bgp_info->attr->nexthop.s_addr = sockunion2ip (peer->su_remote); - bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP); - } - else if (CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT)) - { - /* The next hop value will be set as part of packet rewrite. - * Set the flags here to indicate that rewrite needs to be done. - * Also, clear the value. - */ - SET_FLAG(bgp_info->attr->rmap_change_flags, - BATTR_RMAP_NEXTHOP_PEER_ADDRESS); - bgp_info->attr->nexthop.s_addr = 0; - } - } - else - { - /* Set next hop value. */ - bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP); - bgp_info->attr->nexthop = *rins->address; - SET_FLAG(bgp_info->attr->rmap_change_flags, - BATTR_RMAP_IPV4_NHOP_CHANGED); +static route_map_result_t route_set_ip_nexthop(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct rmap_ip_nexthop_set *rins = rule; + struct bgp_info *bgp_info; + struct peer *peer; + + if (type == RMAP_BGP) { + bgp_info = object; + peer = bgp_info->peer; + + if (rins->unchanged) { + SET_FLAG(bgp_info->attr->rmap_change_flags, + BATTR_RMAP_NEXTHOP_UNCHANGED); + } else if (rins->peer_address) { + if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN) + || CHECK_FLAG(peer->rmap_type, + PEER_RMAP_TYPE_IMPORT)) + && peer->su_remote + && sockunion_family(peer->su_remote) == AF_INET) { + bgp_info->attr->nexthop.s_addr = + sockunion2ip(peer->su_remote); + bgp_info->attr->flag |= + ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); + } else if (CHECK_FLAG(peer->rmap_type, + PEER_RMAP_TYPE_OUT)) { + /* The next hop value will be set as part of + * packet rewrite. + * Set the flags here to indicate that rewrite + * needs to be done. + * Also, clear the value. + */ + SET_FLAG(bgp_info->attr->rmap_change_flags, + BATTR_RMAP_NEXTHOP_PEER_ADDRESS); + bgp_info->attr->nexthop.s_addr = 0; + } + } else { + /* Set next hop value. */ + bgp_info->attr->flag |= + ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); + bgp_info->attr->nexthop = *rins->address; + SET_FLAG(bgp_info->attr->rmap_change_flags, + BATTR_RMAP_IPV4_NHOP_CHANGED); + } } - } - return RMAP_OKAY; + return RMAP_OKAY; } /* Route map `ip nexthop' compile function. Given string is converted to struct in_addr structure. */ -static void * -route_set_ip_nexthop_compile (const char *arg) -{ - struct rmap_ip_nexthop_set *rins; - struct in_addr *address = NULL; - int peer_address = 0; - int unchanged = 0; - int ret; - - if (strcmp (arg, "peer-address") == 0) - peer_address = 1; - else if (strcmp (arg, "unchanged") == 0) - unchanged = 1; - else - { - address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr)); - ret = inet_aton (arg, address); - - if (ret == 0) - { - XFREE (MTYPE_ROUTE_MAP_COMPILED, address); - return NULL; +static void *route_set_ip_nexthop_compile(const char *arg) +{ + struct rmap_ip_nexthop_set *rins; + struct in_addr *address = NULL; + int peer_address = 0; + int unchanged = 0; + int ret; + + if (strcmp(arg, "peer-address") == 0) + peer_address = 1; + else if (strcmp(arg, "unchanged") == 0) + unchanged = 1; + else { + address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, + sizeof(struct in_addr)); + ret = inet_aton(arg, address); + + if (ret == 0) { + XFREE(MTYPE_ROUTE_MAP_COMPILED, address); + return NULL; + } } - } - rins = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_ip_nexthop_set)); + rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, + sizeof(struct rmap_ip_nexthop_set)); - rins->address = address; - rins->peer_address = peer_address; - rins->unchanged = unchanged; + rins->address = address; + rins->peer_address = peer_address; + rins->unchanged = unchanged; - return rins; + return rins; } /* Free route map's compiled `ip nexthop' value. */ -static void -route_set_ip_nexthop_free (void *rule) +static void route_set_ip_nexthop_free(void *rule) { - struct rmap_ip_nexthop_set *rins = rule; + struct rmap_ip_nexthop_set *rins = rule; - if (rins->address) - XFREE (MTYPE_ROUTE_MAP_COMPILED, rins->address); + if (rins->address) + XFREE(MTYPE_ROUTE_MAP_COMPILED, rins->address); - XFREE (MTYPE_ROUTE_MAP_COMPILED, rins); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rins); } /* Route map commands for ip nexthop set. */ -struct route_map_rule_cmd route_set_ip_nexthop_cmd = -{ - "ip next-hop", - route_set_ip_nexthop, - route_set_ip_nexthop_compile, - route_set_ip_nexthop_free -}; +struct route_map_rule_cmd route_set_ip_nexthop_cmd = { + "ip next-hop", route_set_ip_nexthop, route_set_ip_nexthop_compile, + route_set_ip_nexthop_free}; /* `set local-preference LOCAL_PREF' */ /* Set local preference. */ -static route_map_result_t -route_set_local_pref (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct rmap_value *rv; - struct bgp_info *bgp_info; - u_int32_t locpref = 0; - - if (type == RMAP_BGP) - { - /* Fetch routemap's rule information. */ - rv = rule; - bgp_info = object; - - /* Set local preference value. */ - if (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) - locpref = bgp_info->attr->local_pref; - - bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF); - bgp_info->attr->local_pref = route_value_adjust(rv, locpref, bgp_info->peer); - } +static route_map_result_t route_set_local_pref(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct rmap_value *rv; + struct bgp_info *bgp_info; + u_int32_t locpref = 0; + + if (type == RMAP_BGP) { + /* Fetch routemap's rule information. */ + rv = rule; + bgp_info = object; + + /* Set local preference value. */ + if (bgp_info->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) + locpref = bgp_info->attr->local_pref; + + bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF); + bgp_info->attr->local_pref = + route_value_adjust(rv, locpref, bgp_info->peer); + } - return RMAP_OKAY; + return RMAP_OKAY; } /* Set local preference rule structure. */ -struct route_map_rule_cmd route_set_local_pref_cmd = -{ - "local-preference", - route_set_local_pref, - route_value_compile, - route_value_free, +struct route_map_rule_cmd route_set_local_pref_cmd = { + "local-preference", route_set_local_pref, route_value_compile, + route_value_free, }; /* `set weight WEIGHT' */ /* Set weight. */ -static route_map_result_t -route_set_weight (void *rule, struct prefix *prefix, route_map_object_t type, - void *object) +static route_map_result_t route_set_weight(void *rule, struct prefix *prefix, + route_map_object_t type, + void *object) { - struct rmap_value *rv; - struct bgp_info *bgp_info; + struct rmap_value *rv; + struct bgp_info *bgp_info; - if (type == RMAP_BGP) - { - /* Fetch routemap's rule information. */ - rv = rule; - bgp_info = object; + if (type == RMAP_BGP) { + /* Fetch routemap's rule information. */ + rv = rule; + bgp_info = object; - /* Set weight value. */ - bgp_info->attr->weight = route_value_adjust(rv, 0, bgp_info->peer); - } + /* Set weight value. */ + bgp_info->attr->weight = + route_value_adjust(rv, 0, bgp_info->peer); + } - return RMAP_OKAY; + return RMAP_OKAY; } /* Set local preference rule structure. */ -struct route_map_rule_cmd route_set_weight_cmd = -{ - "weight", - route_set_weight, - route_value_compile, - route_value_free, +struct route_map_rule_cmd route_set_weight_cmd = { + "weight", route_set_weight, route_value_compile, route_value_free, }; /* `set metric METRIC' */ /* Set metric to attribute. */ -static route_map_result_t -route_set_metric (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct rmap_value *rv; - struct bgp_info *bgp_info; - u_int32_t med = 0; - - if (type == RMAP_BGP) - { - /* Fetch routemap's rule information. */ - rv = rule; - bgp_info = object; - - if (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) - med = bgp_info->attr->med; - - bgp_info->attr->med = route_value_adjust(rv, med, bgp_info->peer); - bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); - } - return RMAP_OKAY; +static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct rmap_value *rv; + struct bgp_info *bgp_info; + u_int32_t med = 0; + + if (type == RMAP_BGP) { + /* Fetch routemap's rule information. */ + rv = rule; + bgp_info = object; + + if (bgp_info->attr->flag + & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) + med = bgp_info->attr->med; + + bgp_info->attr->med = + route_value_adjust(rv, med, bgp_info->peer); + bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); + } + return RMAP_OKAY; } /* Set metric rule structure. */ -struct route_map_rule_cmd route_set_metric_cmd = -{ - "metric", - route_set_metric, - route_value_compile, - route_value_free, +struct route_map_rule_cmd route_set_metric_cmd = { + "metric", route_set_metric, route_value_compile, route_value_free, }; /* `set as-path prepend ASPATH' */ /* For AS path prepend mechanism. */ -static route_map_result_t -route_set_aspath_prepend (void *rule, struct prefix *prefix, route_map_object_t type, void *object) -{ - struct aspath *aspath; - struct aspath *new; - struct bgp_info *binfo; - - if (type == RMAP_BGP) - { - binfo = object; - - if (binfo->attr->aspath->refcnt) - new = aspath_dup (binfo->attr->aspath); - else - new = binfo->attr->aspath; - - if ((uintptr_t)rule > 10) - { - aspath = rule; - aspath_prepend (aspath, new); - } - else - { - as_t as = aspath_leftmost(new); - if (!as) as = binfo->peer->as; - new = aspath_add_seq_n (new, as, (uintptr_t) rule); - } +static route_map_result_t route_set_aspath_prepend(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct aspath *aspath; + struct aspath *new; + struct bgp_info *binfo; + + if (type == RMAP_BGP) { + binfo = object; + + if (binfo->attr->aspath->refcnt) + new = aspath_dup(binfo->attr->aspath); + else + new = binfo->attr->aspath; + + if ((uintptr_t)rule > 10) { + aspath = rule; + aspath_prepend(aspath, new); + } else { + as_t as = aspath_leftmost(new); + if (!as) + as = binfo->peer->as; + new = aspath_add_seq_n(new, as, (uintptr_t)rule); + } - binfo->attr->aspath = new; - } + binfo->attr->aspath = new; + } - return RMAP_OKAY; + return RMAP_OKAY; } -static void * -route_set_aspath_prepend_compile (const char *arg) +static void *route_set_aspath_prepend_compile(const char *arg) { - unsigned int num; + unsigned int num; - if (sscanf(arg, "last-as %u", &num) == 1 && num > 0 && num <= 10) - return (void*)(uintptr_t)num; + if (sscanf(arg, "last-as %u", &num) == 1 && num > 0 && num <= 10) + return (void *)(uintptr_t)num; - return route_aspath_compile(arg); + return route_aspath_compile(arg); } -static void -route_set_aspath_prepend_free (void *rule) +static void route_set_aspath_prepend_free(void *rule) { - if ((uintptr_t)rule > 10) - route_aspath_free(rule); + if ((uintptr_t)rule > 10) + route_aspath_free(rule); } /* Set as-path prepend rule structure. */ -struct route_map_rule_cmd route_set_aspath_prepend_cmd = -{ - "as-path prepend", - route_set_aspath_prepend, - route_set_aspath_prepend_compile, - route_set_aspath_prepend_free, +struct route_map_rule_cmd route_set_aspath_prepend_cmd = { + "as-path prepend", route_set_aspath_prepend, + route_set_aspath_prepend_compile, route_set_aspath_prepend_free, }; /* `set as-path exclude ASn' */ /* For ASN exclude mechanism. - * Iterate over ASns requested and filter them from the given AS_PATH one by one. + * Iterate over ASns requested and filter them from the given AS_PATH one by + * one. * Make a deep copy of existing AS_PATH, but for the first ASn only. */ -static route_map_result_t -route_set_aspath_exclude (void *rule, struct prefix *dummy, route_map_object_t type, void *object) -{ - struct aspath * new_path, * exclude_path; - struct bgp_info *binfo; - - if (type == RMAP_BGP) - { - exclude_path = rule; - binfo = object; - if (binfo->attr->aspath->refcnt) - new_path = aspath_dup (binfo->attr->aspath); - else - new_path = binfo->attr->aspath; - binfo->attr->aspath = aspath_filter_exclude (new_path, exclude_path); - } - return RMAP_OKAY; +static route_map_result_t route_set_aspath_exclude(void *rule, + struct prefix *dummy, + route_map_object_t type, + void *object) +{ + struct aspath *new_path, *exclude_path; + struct bgp_info *binfo; + + if (type == RMAP_BGP) { + exclude_path = rule; + binfo = object; + if (binfo->attr->aspath->refcnt) + new_path = aspath_dup(binfo->attr->aspath); + else + new_path = binfo->attr->aspath; + binfo->attr->aspath = + aspath_filter_exclude(new_path, exclude_path); + } + return RMAP_OKAY; } /* Set ASn exlude rule structure. */ -struct route_map_rule_cmd route_set_aspath_exclude_cmd = -{ - "as-path exclude", - route_set_aspath_exclude, - route_aspath_compile, - route_aspath_free, +struct route_map_rule_cmd route_set_aspath_exclude_cmd = { + "as-path exclude", route_set_aspath_exclude, route_aspath_compile, + route_aspath_free, }; /* `set community COMMUNITY' */ -struct rmap_com_set -{ - struct community *com; - int additive; - int none; +struct rmap_com_set { + struct community *com; + int additive; + int none; }; /* For community set mechanism. */ -static route_map_result_t -route_set_community (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct rmap_com_set *rcs; - struct bgp_info *binfo; - struct attr *attr; - struct community *new = NULL; - struct community *old; - struct community *merge; - - if (type == RMAP_BGP) - { - rcs = rule; - binfo = object; - attr = binfo->attr; - old = attr->community; - - /* "none" case. */ - if (rcs->none) - { - attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)); - attr->community = NULL; - /* See the longer comment down below. */ - if (old && old->refcnt == 0) - community_free(old); - return RMAP_OKAY; - } +static route_map_result_t route_set_community(void *rule, struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct rmap_com_set *rcs; + struct bgp_info *binfo; + struct attr *attr; + struct community *new = NULL; + struct community *old; + struct community *merge; + + if (type == RMAP_BGP) { + rcs = rule; + binfo = object; + attr = binfo->attr; + old = attr->community; + + /* "none" case. */ + if (rcs->none) { + attr->flag &= ~(ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)); + attr->community = NULL; + /* See the longer comment down below. */ + if (old && old->refcnt == 0) + community_free(old); + return RMAP_OKAY; + } - /* "additive" case. */ - if (rcs->additive && old) - { - merge = community_merge (community_dup (old), rcs->com); - - /* HACK: if the old community is not intern'd, - * we should free it here, or all reference to it may be lost. - * Really need to cleanup attribute caching sometime. - */ - if (old->refcnt == 0) - community_free (old); - new = community_uniq_sort (merge); - community_free (merge); + /* "additive" case. */ + if (rcs->additive && old) { + merge = community_merge(community_dup(old), rcs->com); + + /* HACK: if the old community is not intern'd, + * we should free it here, or all reference to it may be + * lost. + * Really need to cleanup attribute caching sometime. + */ + if (old->refcnt == 0) + community_free(old); + new = community_uniq_sort(merge); + community_free(merge); + } else + new = community_dup(rcs->com); + + /* will be interned by caller if required */ + attr->community = new; + + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES); } - else - new = community_dup (rcs->com); - - /* will be interned by caller if required */ - attr->community = new; - - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES); - } - return RMAP_OKAY; + return RMAP_OKAY; } /* Compile function for set community. */ -static void * -route_set_community_compile (const char *arg) -{ - struct rmap_com_set *rcs; - struct community *com = NULL; - char *sp; - int additive = 0; - int none = 0; - - if (strcmp (arg, "none") == 0) - none = 1; - else - { - sp = strstr (arg, "additive"); - - if (sp && sp > arg) - { - /* "additive" keyworkd is included. */ - additive = 1; - *(sp - 1) = '\0'; - } +static void *route_set_community_compile(const char *arg) +{ + struct rmap_com_set *rcs; + struct community *com = NULL; + char *sp; + int additive = 0; + int none = 0; + + if (strcmp(arg, "none") == 0) + none = 1; + else { + sp = strstr(arg, "additive"); + + if (sp && sp > arg) { + /* "additive" keyworkd is included. */ + additive = 1; + *(sp - 1) = '\0'; + } - com = community_str2com (arg); + com = community_str2com(arg); - if (additive) - *(sp - 1) = ' '; + if (additive) + *(sp - 1) = ' '; - if (! com) - return NULL; - } + if (!com) + return NULL; + } - rcs = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_com_set)); - rcs->com = com; - rcs->additive = additive; - rcs->none = none; + rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set)); + rcs->com = com; + rcs->additive = additive; + rcs->none = none; - return rcs; + return rcs; } /* Free function for set community. */ -static void -route_set_community_free (void *rule) +static void route_set_community_free(void *rule) { - struct rmap_com_set *rcs = rule; + struct rmap_com_set *rcs = rule; - if (rcs->com) - community_free (rcs->com); - XFREE (MTYPE_ROUTE_MAP_COMPILED, rcs); + if (rcs->com) + community_free(rcs->com); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs); } /* Set community rule structure. */ -struct route_map_rule_cmd route_set_community_cmd = -{ - "community", - route_set_community, - route_set_community_compile, - route_set_community_free, +struct route_map_rule_cmd route_set_community_cmd = { + "community", route_set_community, route_set_community_compile, + route_set_community_free, }; /* `set community COMMUNITY' */ -struct rmap_lcom_set -{ - struct lcommunity *lcom; - int additive; - int none; +struct rmap_lcom_set { + struct lcommunity *lcom; + int additive; + int none; }; /* For lcommunity set mechanism. */ -static route_map_result_t -route_set_lcommunity (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct rmap_lcom_set *rcs; - struct bgp_info *binfo; - struct attr *attr; - struct lcommunity *new = NULL; - struct lcommunity *old; - struct lcommunity *merge; - - if (type == RMAP_BGP) - { - rcs = rule; - binfo = object; - attr = binfo->attr; - old = attr->lcommunity; - - /* "none" case. */ - if (rcs->none) - { - attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES)); - attr->lcommunity = NULL; - - /* See the longer comment down below. */ - if (old && old->refcnt == 0) - lcommunity_free(&old); - return RMAP_OKAY; - } - - if (rcs->additive && old) - { - merge = lcommunity_merge (lcommunity_dup (old), rcs->lcom); - - /* HACK: if the old large-community is not intern'd, - * we should free it here, or all reference to it may be lost. - * Really need to cleanup attribute caching sometime. - */ - if (old->refcnt == 0) - lcommunity_free (&old); - new = lcommunity_uniq_sort (merge); - lcommunity_free (&merge); - } - else - new = lcommunity_dup (rcs->lcom); - - /* will be intern()'d or attr_flush()'d by bgp_update_main() */ - attr->lcommunity = new; - - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES); - } - - return RMAP_OKAY; -} +static route_map_result_t route_set_lcommunity(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct rmap_lcom_set *rcs; + struct bgp_info *binfo; + struct attr *attr; + struct lcommunity *new = NULL; + struct lcommunity *old; + struct lcommunity *merge; + + if (type == RMAP_BGP) { + rcs = rule; + binfo = object; + attr = binfo->attr; + old = attr->lcommunity; + + /* "none" case. */ + if (rcs->none) { + attr->flag &= + ~(ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)); + attr->lcommunity = NULL; + + /* See the longer comment down below. */ + if (old && old->refcnt == 0) + lcommunity_free(&old); + return RMAP_OKAY; + } -/* Compile function for set community. */ -static void * -route_set_lcommunity_compile (const char *arg) -{ - struct rmap_lcom_set *rcs; - struct lcommunity *lcom = NULL; - char *sp; - int additive = 0; - int none = 0; + if (rcs->additive && old) { + merge = lcommunity_merge(lcommunity_dup(old), + rcs->lcom); + + /* HACK: if the old large-community is not intern'd, + * we should free it here, or all reference to it may be + * lost. + * Really need to cleanup attribute caching sometime. + */ + if (old->refcnt == 0) + lcommunity_free(&old); + new = lcommunity_uniq_sort(merge); + lcommunity_free(&merge); + } else + new = lcommunity_dup(rcs->lcom); + + /* will be intern()'d or attr_flush()'d by bgp_update_main() */ + attr->lcommunity = new; + + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES); + } - if (strcmp (arg, "none") == 0) - none = 1; - else - { - sp = strstr (arg, "additive"); + return RMAP_OKAY; +} - if (sp && sp > arg) - { - /* "additive" keyworkd is included. */ - additive = 1; - *(sp - 1) = '\0'; - } +/* Compile function for set community. */ +static void *route_set_lcommunity_compile(const char *arg) +{ + struct rmap_lcom_set *rcs; + struct lcommunity *lcom = NULL; + char *sp; + int additive = 0; + int none = 0; + + if (strcmp(arg, "none") == 0) + none = 1; + else { + sp = strstr(arg, "additive"); + + if (sp && sp > arg) { + /* "additive" keyworkd is included. */ + additive = 1; + *(sp - 1) = '\0'; + } - lcom = lcommunity_str2com (arg); + lcom = lcommunity_str2com(arg); - if (additive) - *(sp - 1) = ' '; + if (additive) + *(sp - 1) = ' '; - if (! lcom) - return NULL; - } + if (!lcom) + return NULL; + } - rcs = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_com_set)); - rcs->lcom = lcom; - rcs->additive = additive; - rcs->none = none; + rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set)); + rcs->lcom = lcom; + rcs->additive = additive; + rcs->none = none; - return rcs; + return rcs; } /* Free function for set lcommunity. */ -static void -route_set_lcommunity_free (void *rule) +static void route_set_lcommunity_free(void *rule) { - struct rmap_lcom_set *rcs = rule; + struct rmap_lcom_set *rcs = rule; - if (rcs->lcom) { - lcommunity_free (&rcs->lcom); - } - XFREE (MTYPE_ROUTE_MAP_COMPILED, rcs); + if (rcs->lcom) { + lcommunity_free(&rcs->lcom); + } + XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs); } /* Set community rule structure. */ -struct route_map_rule_cmd route_set_lcommunity_cmd = -{ - "large-community", - route_set_lcommunity, - route_set_lcommunity_compile, - route_set_lcommunity_free, +struct route_map_rule_cmd route_set_lcommunity_cmd = { + "large-community", route_set_lcommunity, route_set_lcommunity_compile, + route_set_lcommunity_free, }; /* `set large-comm-list (<1-99>|<100-500>|WORD) delete' */ /* For large community set mechanism. */ -static route_map_result_t -route_set_lcommunity_delete (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct community_list *list; - struct lcommunity *merge; - struct lcommunity *new; - struct lcommunity *old; - struct bgp_info *binfo; - - if (type == RMAP_BGP) - { - if (! rule) - return RMAP_OKAY; - - binfo = object; - list = community_list_lookup (bgp_clist, rule, - LARGE_COMMUNITY_LIST_MASTER); - old = binfo->attr->lcommunity; - - if (list && old) - { - merge = lcommunity_list_match_delete (lcommunity_dup (old), list); - new = lcommunity_uniq_sort (merge); - lcommunity_free (&merge); - - /* HACK: if the old community is not intern'd, - * we should free it here, or all reference to it may be lost. - * Really need to cleanup attribute caching sometime. - */ - if (old->refcnt == 0) - lcommunity_free (&old); - - if (new->size == 0) - { - binfo->attr->lcommunity = NULL; - binfo->attr->flag &= ~ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES); - lcommunity_free (&new); - } - else - { - binfo->attr->lcommunity = new; - binfo->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES); - } - } - } - - return RMAP_OKAY; +static route_map_result_t route_set_lcommunity_delete(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct community_list *list; + struct lcommunity *merge; + struct lcommunity *new; + struct lcommunity *old; + struct bgp_info *binfo; + + if (type == RMAP_BGP) { + if (!rule) + return RMAP_OKAY; + + binfo = object; + list = community_list_lookup(bgp_clist, rule, + LARGE_COMMUNITY_LIST_MASTER); + old = binfo->attr->lcommunity; + + if (list && old) { + merge = lcommunity_list_match_delete( + lcommunity_dup(old), list); + new = lcommunity_uniq_sort(merge); + lcommunity_free(&merge); + + /* HACK: if the old community is not intern'd, + * we should free it here, or all reference to it may be + * lost. + * Really need to cleanup attribute caching sometime. + */ + if (old->refcnt == 0) + lcommunity_free(&old); + + if (new->size == 0) { + binfo->attr->lcommunity = NULL; + binfo->attr->flag &= ~ATTR_FLAG_BIT( + BGP_ATTR_LARGE_COMMUNITIES); + lcommunity_free(&new); + } else { + binfo->attr->lcommunity = new; + binfo->attr->flag |= ATTR_FLAG_BIT( + BGP_ATTR_LARGE_COMMUNITIES); + } + } + } + + return RMAP_OKAY; } /* Compile function for set lcommunity. */ -static void * -route_set_lcommunity_delete_compile (const char *arg) +static void *route_set_lcommunity_delete_compile(const char *arg) { - char *p; - char *str; - int len; + char *p; + char *str; + int len; - p = strchr (arg, ' '); - if (p) - { - len = p - arg; - str = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1); - memcpy (str, arg, len); - } - else - str = NULL; + p = strchr(arg, ' '); + if (p) { + len = p - arg; + str = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1); + memcpy(str, arg, len); + } else + str = NULL; - return str; + return str; } /* Free function for set lcommunity. */ -static void -route_set_lcommunity_delete_free (void *rule) +static void route_set_lcommunity_delete_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Set lcommunity rule structure. */ -struct route_map_rule_cmd route_set_lcommunity_delete_cmd = -{ - "large-comm-list", - route_set_lcommunity_delete, - route_set_lcommunity_delete_compile, - route_set_lcommunity_delete_free, +struct route_map_rule_cmd route_set_lcommunity_delete_cmd = { + "large-comm-list", route_set_lcommunity_delete, + route_set_lcommunity_delete_compile, route_set_lcommunity_delete_free, }; /* `set comm-list (<1-99>|<100-500>|WORD) delete' */ /* For community set mechanism. */ -static route_map_result_t -route_set_community_delete (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct community_list *list; - struct community *merge; - struct community *new; - struct community *old; - struct bgp_info *binfo; - - if (type == RMAP_BGP) - { - if (! rule) - return RMAP_OKAY; - - binfo = object; - list = community_list_lookup (bgp_clist, rule, COMMUNITY_LIST_MASTER); - old = binfo->attr->community; - - if (list && old) - { - merge = community_list_match_delete (community_dup (old), list); - new = community_uniq_sort (merge); - community_free (merge); - - /* HACK: if the old community is not intern'd, - * we should free it here, or all reference to it may be lost. - * Really need to cleanup attribute caching sometime. - */ - if (old->refcnt == 0) - community_free (old); - - if (new->size == 0) - { - binfo->attr->community = NULL; - binfo->attr->flag &= ~ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES); - community_free (new); - } - else - { - binfo->attr->community = new; - binfo->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES); - } +static route_map_result_t route_set_community_delete(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct community_list *list; + struct community *merge; + struct community *new; + struct community *old; + struct bgp_info *binfo; + + if (type == RMAP_BGP) { + if (!rule) + return RMAP_OKAY; + + binfo = object; + list = community_list_lookup(bgp_clist, rule, + COMMUNITY_LIST_MASTER); + old = binfo->attr->community; + + if (list && old) { + merge = community_list_match_delete(community_dup(old), + list); + new = community_uniq_sort(merge); + community_free(merge); + + /* HACK: if the old community is not intern'd, + * we should free it here, or all reference to it may be + * lost. + * Really need to cleanup attribute caching sometime. + */ + if (old->refcnt == 0) + community_free(old); + + if (new->size == 0) { + binfo->attr->community = NULL; + binfo->attr->flag &= + ~ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES); + community_free(new); + } else { + binfo->attr->community = new; + binfo->attr->flag |= + ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES); + } + } } - } - return RMAP_OKAY; + return RMAP_OKAY; } /* Compile function for set community. */ -static void * -route_set_community_delete_compile (const char *arg) +static void *route_set_community_delete_compile(const char *arg) { - char *p; - char *str; - int len; + char *p; + char *str; + int len; - p = strchr (arg, ' '); - if (p) - { - len = p - arg; - str = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1); - memcpy (str, arg, len); - } - else - str = NULL; + p = strchr(arg, ' '); + if (p) { + len = p - arg; + str = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1); + memcpy(str, arg, len); + } else + str = NULL; - return str; + return str; } /* Free function for set community. */ -static void -route_set_community_delete_free (void *rule) +static void route_set_community_delete_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Set community rule structure. */ -struct route_map_rule_cmd route_set_community_delete_cmd = -{ - "comm-list", - route_set_community_delete, - route_set_community_delete_compile, - route_set_community_delete_free, +struct route_map_rule_cmd route_set_community_delete_cmd = { + "comm-list", route_set_community_delete, + route_set_community_delete_compile, route_set_community_delete_free, }; /* `set extcommunity rt COMMUNITY' */ /* For community set mechanism. Used by _rt and _soo. */ -static route_map_result_t -route_set_ecommunity (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct ecommunity *ecom; - struct ecommunity *new_ecom; - struct ecommunity *old_ecom; - struct bgp_info *bgp_info; - - if (type == RMAP_BGP) - { - ecom = rule; - bgp_info = object; - - if (! ecom) - return RMAP_OKAY; - - /* We assume additive for Extended Community. */ - old_ecom = bgp_info->attr->ecommunity; - - if (old_ecom) - { - new_ecom = ecommunity_merge (ecommunity_dup (old_ecom), ecom); - - /* old_ecom->refcnt = 1 => owned elsewhere, e.g. bgp_update_receive() - * ->refcnt = 0 => set by a previous route-map statement */ - if (!old_ecom->refcnt) - ecommunity_free (&old_ecom); +static route_map_result_t route_set_ecommunity(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct ecommunity *ecom; + struct ecommunity *new_ecom; + struct ecommunity *old_ecom; + struct bgp_info *bgp_info; + + if (type == RMAP_BGP) { + ecom = rule; + bgp_info = object; + + if (!ecom) + return RMAP_OKAY; + + /* We assume additive for Extended Community. */ + old_ecom = bgp_info->attr->ecommunity; + + if (old_ecom) { + new_ecom = ecommunity_merge(ecommunity_dup(old_ecom), + ecom); + + /* old_ecom->refcnt = 1 => owned elsewhere, e.g. + * bgp_update_receive() + * ->refcnt = 0 => set by a previous route-map + * statement */ + if (!old_ecom->refcnt) + ecommunity_free(&old_ecom); + } else + new_ecom = ecommunity_dup(ecom); + + /* will be intern()'d or attr_flush()'d by bgp_update_main() */ + bgp_info->attr->ecommunity = new_ecom; + + bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES); } - else - new_ecom = ecommunity_dup (ecom); - - /* will be intern()'d or attr_flush()'d by bgp_update_main() */ - bgp_info->attr->ecommunity = new_ecom; - - bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES); - } - return RMAP_OKAY; + return RMAP_OKAY; } /* Compile function for set community. */ -static void * -route_set_ecommunity_rt_compile (const char *arg) +static void *route_set_ecommunity_rt_compile(const char *arg) { - struct ecommunity *ecom; + struct ecommunity *ecom; - ecom = ecommunity_str2com (arg, ECOMMUNITY_ROUTE_TARGET, 0); - if (! ecom) - return NULL; - return ecommunity_intern (ecom); + ecom = ecommunity_str2com(arg, ECOMMUNITY_ROUTE_TARGET, 0); + if (!ecom) + return NULL; + return ecommunity_intern(ecom); } /* Free function for set community. Used by _rt and _soo */ -static void -route_set_ecommunity_free (void *rule) +static void route_set_ecommunity_free(void *rule) { - struct ecommunity *ecom = rule; - ecommunity_unintern (&ecom); + struct ecommunity *ecom = rule; + ecommunity_unintern(&ecom); } /* Set community rule structure. */ -struct route_map_rule_cmd route_set_ecommunity_rt_cmd = -{ - "extcommunity rt", - route_set_ecommunity, - route_set_ecommunity_rt_compile, - route_set_ecommunity_free, +struct route_map_rule_cmd route_set_ecommunity_rt_cmd = { + "extcommunity rt", route_set_ecommunity, + route_set_ecommunity_rt_compile, route_set_ecommunity_free, }; /* `set extcommunity soo COMMUNITY' */ /* Compile function for set community. */ -static void * -route_set_ecommunity_soo_compile (const char *arg) +static void *route_set_ecommunity_soo_compile(const char *arg) { - struct ecommunity *ecom; + struct ecommunity *ecom; - ecom = ecommunity_str2com (arg, ECOMMUNITY_SITE_ORIGIN, 0); - if (! ecom) - return NULL; + ecom = ecommunity_str2com(arg, ECOMMUNITY_SITE_ORIGIN, 0); + if (!ecom) + return NULL; - return ecommunity_intern (ecom); + return ecommunity_intern(ecom); } /* Set community rule structure. */ -struct route_map_rule_cmd route_set_ecommunity_soo_cmd = -{ - "extcommunity soo", - route_set_ecommunity, - route_set_ecommunity_soo_compile, - route_set_ecommunity_free, +struct route_map_rule_cmd route_set_ecommunity_soo_cmd = { + "extcommunity soo", route_set_ecommunity, + route_set_ecommunity_soo_compile, route_set_ecommunity_free, }; /* `set origin ORIGIN' */ /* For origin set. */ -static route_map_result_t -route_set_origin (void *rule, struct prefix *prefix, route_map_object_t type, void *object) +static route_map_result_t route_set_origin(void *rule, struct prefix *prefix, + route_map_object_t type, + void *object) { - u_char *origin; - struct bgp_info *bgp_info; + u_char *origin; + struct bgp_info *bgp_info; - if (type == RMAP_BGP) - { - origin = rule; - bgp_info = object; + if (type == RMAP_BGP) { + origin = rule; + bgp_info = object; - bgp_info->attr->origin = *origin; - } + bgp_info->attr->origin = *origin; + } - return RMAP_OKAY; + return RMAP_OKAY; } /* Compile function for origin set. */ -static void * -route_set_origin_compile (const char *arg) +static void *route_set_origin_compile(const char *arg) { - u_char *origin; + u_char *origin; - origin = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_char)); + origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_char)); - if (strcmp (arg, "igp") == 0) - *origin = 0; - else if (strcmp (arg, "egp") == 0) - *origin = 1; - else - *origin = 2; + if (strcmp(arg, "igp") == 0) + *origin = 0; + else if (strcmp(arg, "egp") == 0) + *origin = 1; + else + *origin = 2; - return origin; + return origin; } /* Compile function for origin set. */ -static void -route_set_origin_free (void *rule) +static void route_set_origin_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Set origin rule structure. */ -struct route_map_rule_cmd route_set_origin_cmd = -{ - "origin", - route_set_origin, - route_set_origin_compile, - route_set_origin_free, +struct route_map_rule_cmd route_set_origin_cmd = { + "origin", route_set_origin, route_set_origin_compile, + route_set_origin_free, }; /* `set atomic-aggregate' */ /* For atomic aggregate set. */ -static route_map_result_t -route_set_atomic_aggregate (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_atomic_aggregate(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct bgp_info *bgp_info; + struct bgp_info *bgp_info; - if (type == RMAP_BGP) - { - bgp_info = object; - bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE); - } + if (type == RMAP_BGP) { + bgp_info = object; + bgp_info->attr->flag |= + ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE); + } - return RMAP_OKAY; + return RMAP_OKAY; } /* Compile function for atomic aggregate. */ -static void * -route_set_atomic_aggregate_compile (const char *arg) +static void *route_set_atomic_aggregate_compile(const char *arg) { - return (void *)1; + return (void *)1; } /* Compile function for atomic aggregate. */ -static void -route_set_atomic_aggregate_free (void *rule) +static void route_set_atomic_aggregate_free(void *rule) { - return; + return; } /* Set atomic aggregate rule structure. */ -struct route_map_rule_cmd route_set_atomic_aggregate_cmd = -{ - "atomic-aggregate", - route_set_atomic_aggregate, - route_set_atomic_aggregate_compile, - route_set_atomic_aggregate_free, +struct route_map_rule_cmd route_set_atomic_aggregate_cmd = { + "atomic-aggregate", route_set_atomic_aggregate, + route_set_atomic_aggregate_compile, route_set_atomic_aggregate_free, }; /* `set aggregator as AS A.B.C.D' */ -struct aggregator -{ - as_t as; - struct in_addr address; +struct aggregator { + as_t as; + struct in_addr address; }; -static route_map_result_t -route_set_aggregator_as (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_aggregator_as(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct bgp_info *bgp_info; - struct aggregator *aggregator; + struct bgp_info *bgp_info; + struct aggregator *aggregator; - if (type == RMAP_BGP) - { - bgp_info = object; - aggregator = rule; + if (type == RMAP_BGP) { + bgp_info = object; + aggregator = rule; - bgp_info->attr->aggregator_as = aggregator->as; - bgp_info->attr->aggregator_addr = aggregator->address; - bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR); - } + bgp_info->attr->aggregator_as = aggregator->as; + bgp_info->attr->aggregator_addr = aggregator->address; + bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR); + } - return RMAP_OKAY; + return RMAP_OKAY; } -static void * -route_set_aggregator_as_compile (const char *arg) +static void *route_set_aggregator_as_compile(const char *arg) { - struct aggregator *aggregator; - char as[10]; - char address[20]; - int ret; + struct aggregator *aggregator; + char as[10]; + char address[20]; + int ret; - aggregator = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct aggregator)); - sscanf (arg, "%s %s", as, address); + aggregator = + XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct aggregator)); + sscanf(arg, "%s %s", as, address); - aggregator->as = strtoul (as, NULL, 10); - ret = inet_aton (address, &aggregator->address); - if (ret == 0) - { - XFREE (MTYPE_ROUTE_MAP_COMPILED, aggregator); - return NULL; - } - return aggregator; + aggregator->as = strtoul(as, NULL, 10); + ret = inet_aton(address, &aggregator->address); + if (ret == 0) { + XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator); + return NULL; + } + return aggregator; } -static void -route_set_aggregator_as_free (void *rule) +static void route_set_aggregator_as_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -struct route_map_rule_cmd route_set_aggregator_as_cmd = -{ - "aggregator as", - route_set_aggregator_as, - route_set_aggregator_as_compile, - route_set_aggregator_as_free, +struct route_map_rule_cmd route_set_aggregator_as_cmd = { + "aggregator as", route_set_aggregator_as, + route_set_aggregator_as_compile, route_set_aggregator_as_free, }; /* Set tag to object. object must be pointer to struct bgp_info */ -static route_map_result_t -route_set_tag (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_tag(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - route_tag_t *tag; - struct bgp_info *bgp_info; - - if (type == RMAP_BGP) - { - tag = rule; - bgp_info = object; + route_tag_t *tag; + struct bgp_info *bgp_info; - /* Set tag value */ - bgp_info->attr->tag=*tag; + if (type == RMAP_BGP) { + tag = rule; + bgp_info = object; - } + /* Set tag value */ + bgp_info->attr->tag = *tag; + } - return RMAP_OKAY; + return RMAP_OKAY; } /* Route map commands for tag set. */ -static struct route_map_rule_cmd route_set_tag_cmd = -{ - "tag", - route_set_tag, - route_map_rule_tag_compile, - route_map_rule_tag_free, +static struct route_map_rule_cmd route_set_tag_cmd = { + "tag", route_set_tag, route_map_rule_tag_compile, + route_map_rule_tag_free, }; /* Set label-index to object. object must be pointer to struct bgp_info */ -static route_map_result_t -route_set_label_index (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct rmap_value *rv; - struct bgp_info *bgp_info; - u_int32_t label_index; - - if (type == RMAP_BGP) - { - /* Fetch routemap's rule information. */ - rv = rule; - bgp_info = object; - - /* Set label-index value. */ - label_index = rv->value; - if (label_index) - { - bgp_info->attr->label_index = label_index; - bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID); - } - } +static route_map_result_t route_set_label_index(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct rmap_value *rv; + struct bgp_info *bgp_info; + u_int32_t label_index; + + if (type == RMAP_BGP) { + /* Fetch routemap's rule information. */ + rv = rule; + bgp_info = object; + + /* Set label-index value. */ + label_index = rv->value; + if (label_index) { + bgp_info->attr->label_index = label_index; + bgp_info->attr->flag |= + ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID); + } + } - return RMAP_OKAY; + return RMAP_OKAY; } /* Route map commands for label-index set. */ -static struct route_map_rule_cmd route_set_label_index_cmd = -{ - "label-index", - route_set_label_index, - route_value_compile, - route_value_free, +static struct route_map_rule_cmd route_set_label_index_cmd = { + "label-index", route_set_label_index, route_value_compile, + route_value_free, }; /* `match ipv6 address IP_ACCESS_LIST' */ -static route_map_result_t -route_match_ipv6_address (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_ipv6_address(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct access_list *alist; + struct access_list *alist; - if (type == RMAP_BGP) - { - alist = access_list_lookup (AFI_IP6, (char *) rule); - if (alist == NULL) - return RMAP_NOMATCH; + if (type == RMAP_BGP) { + alist = access_list_lookup(AFI_IP6, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; - return (access_list_apply (alist, prefix) == FILTER_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; + return (access_list_apply(alist, prefix) == FILTER_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } + return RMAP_NOMATCH; } -static void * -route_match_ipv6_address_compile (const char *arg) +static void *route_match_ipv6_address_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ipv6_address_free (void *rule) +static void route_match_ipv6_address_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip address matching. */ -struct route_map_rule_cmd route_match_ipv6_address_cmd = -{ - "ipv6 address", - route_match_ipv6_address, - route_match_ipv6_address_compile, - route_match_ipv6_address_free -}; +struct route_map_rule_cmd route_match_ipv6_address_cmd = { + "ipv6 address", route_match_ipv6_address, + route_match_ipv6_address_compile, route_match_ipv6_address_free}; /* `match ipv6 next-hop IP_ADDRESS' */ -static route_map_result_t -route_match_ipv6_next_hop (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_ipv6_next_hop(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct in6_addr *addr = rule; - struct bgp_info *bgp_info; + struct in6_addr *addr = rule; + struct bgp_info *bgp_info; - if (type == RMAP_BGP) - { - bgp_info = object; + if (type == RMAP_BGP) { + bgp_info = object; - if (IPV6_ADDR_SAME (&bgp_info->attr->mp_nexthop_global, addr)) - return RMAP_MATCH; + if (IPV6_ADDR_SAME(&bgp_info->attr->mp_nexthop_global, addr)) + return RMAP_MATCH; - if (bgp_info->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL && - IPV6_ADDR_SAME (&bgp_info->attr->mp_nexthop_local, rule)) - return RMAP_MATCH; + if (bgp_info->attr->mp_nexthop_len + == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL + && IPV6_ADDR_SAME(&bgp_info->attr->mp_nexthop_local, rule)) + return RMAP_MATCH; - return RMAP_NOMATCH; - } + return RMAP_NOMATCH; + } - return RMAP_NOMATCH; + return RMAP_NOMATCH; } -static void * -route_match_ipv6_next_hop_compile (const char *arg) +static void *route_match_ipv6_next_hop_compile(const char *arg) { - struct in6_addr *address; - int ret; + struct in6_addr *address; + int ret; - address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr)); + address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr)); - ret = inet_pton (AF_INET6, arg, address); - if (!ret) - { - XFREE (MTYPE_ROUTE_MAP_COMPILED, address); - return NULL; - } + ret = inet_pton(AF_INET6, arg, address); + if (!ret) { + XFREE(MTYPE_ROUTE_MAP_COMPILED, address); + return NULL; + } - return address; + return address; } -static void -route_match_ipv6_next_hop_free (void *rule) +static void route_match_ipv6_next_hop_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = -{ - "ipv6 next-hop", - route_match_ipv6_next_hop, - route_match_ipv6_next_hop_compile, - route_match_ipv6_next_hop_free -}; +struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = { + "ipv6 next-hop", route_match_ipv6_next_hop, + route_match_ipv6_next_hop_compile, route_match_ipv6_next_hop_free}; /* `match ipv6 address prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ipv6_address_prefix_list (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ipv6_address_prefix_list(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - struct prefix_list *plist; + struct prefix_list *plist; - if (type == RMAP_BGP) - { - plist = prefix_list_lookup (AFI_IP6, (char *) rule); - if (plist == NULL) - return RMAP_NOMATCH; + if (type == RMAP_BGP) { + plist = prefix_list_lookup(AFI_IP6, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; - return (prefix_list_apply (plist, prefix) == PREFIX_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; + return (prefix_list_apply(plist, prefix) == PREFIX_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } + return RMAP_NOMATCH; } -static void * -route_match_ipv6_address_prefix_list_compile (const char *arg) +static void *route_match_ipv6_address_prefix_list_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ipv6_address_prefix_list_free (void *rule) +static void route_match_ipv6_address_prefix_list_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = -{ - "ipv6 address prefix-list", - route_match_ipv6_address_prefix_list, - route_match_ipv6_address_prefix_list_compile, - route_match_ipv6_address_prefix_list_free -}; +struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = { + "ipv6 address prefix-list", route_match_ipv6_address_prefix_list, + route_match_ipv6_address_prefix_list_compile, + route_match_ipv6_address_prefix_list_free}; /* `set ipv6 nexthop global IP_ADDRESS' */ /* Set nexthop to object. ojbect must be pointer to struct attr. */ -static route_map_result_t -route_set_ipv6_nexthop_global (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_ipv6_nexthop_global(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct in6_addr *address; - struct bgp_info *bgp_info; + struct in6_addr *address; + struct bgp_info *bgp_info; - if (type == RMAP_BGP) - { - /* Fetch routemap's rule information. */ - address = rule; - bgp_info = object; + if (type == RMAP_BGP) { + /* Fetch routemap's rule information. */ + address = rule; + bgp_info = object; - /* Set next hop value. */ - bgp_info->attr->mp_nexthop_global = *address; + /* Set next hop value. */ + bgp_info->attr->mp_nexthop_global = *address; - /* Set nexthop length. */ - if (bgp_info->attr->mp_nexthop_len == 0) - bgp_info->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; + /* Set nexthop length. */ + if (bgp_info->attr->mp_nexthop_len == 0) + bgp_info->attr->mp_nexthop_len = + BGP_ATTR_NHLEN_IPV6_GLOBAL; - SET_FLAG(bgp_info->attr->rmap_change_flags, - BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED); - } + SET_FLAG(bgp_info->attr->rmap_change_flags, + BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED); + } - return RMAP_OKAY; + return RMAP_OKAY; } /* Route map `ip next-hop' compile function. Given string is converted to struct in_addr structure. */ -static void * -route_set_ipv6_nexthop_global_compile (const char *arg) +static void *route_set_ipv6_nexthop_global_compile(const char *arg) { - int ret; - struct in6_addr *address; + int ret; + struct in6_addr *address; - address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr)); + address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr)); - ret = inet_pton (AF_INET6, arg, address); + ret = inet_pton(AF_INET6, arg, address); - if (ret == 0) - { - XFREE (MTYPE_ROUTE_MAP_COMPILED, address); - return NULL; - } + if (ret == 0) { + XFREE(MTYPE_ROUTE_MAP_COMPILED, address); + return NULL; + } - return address; + return address; } /* Free route map's compiled `ip next-hop' value. */ -static void -route_set_ipv6_nexthop_global_free (void *rule) +static void route_set_ipv6_nexthop_global_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip nexthop set. */ -struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd = -{ - "ipv6 next-hop global", - route_set_ipv6_nexthop_global, - route_set_ipv6_nexthop_global_compile, - route_set_ipv6_nexthop_global_free -}; +struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd = { + "ipv6 next-hop global", route_set_ipv6_nexthop_global, + route_set_ipv6_nexthop_global_compile, + route_set_ipv6_nexthop_global_free}; /* Set next-hop preference value. */ static route_map_result_t -route_set_ipv6_nexthop_prefer_global (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct bgp_info *bgp_info; - struct peer *peer; - - if (type == RMAP_BGP) - { - /* Fetch routemap's rule information. */ - bgp_info = object; - peer = bgp_info->peer; - - if ((CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN) || - CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) - && peer->su_remote - && sockunion_family (peer->su_remote) == AF_INET6) - { - /* Set next hop preference to global */ - bgp_info->attr->mp_nexthop_prefer_global = TRUE; - SET_FLAG(bgp_info->attr->rmap_change_flags, - BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED); +route_set_ipv6_nexthop_prefer_global(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + struct bgp_info *bgp_info; + struct peer *peer; + + if (type == RMAP_BGP) { + /* Fetch routemap's rule information. */ + bgp_info = object; + peer = bgp_info->peer; + + if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN) + || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) + && peer->su_remote + && sockunion_family(peer->su_remote) == AF_INET6) { + /* Set next hop preference to global */ + bgp_info->attr->mp_nexthop_prefer_global = TRUE; + SET_FLAG(bgp_info->attr->rmap_change_flags, + BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED); + } else { + bgp_info->attr->mp_nexthop_prefer_global = FALSE; + SET_FLAG(bgp_info->attr->rmap_change_flags, + BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED); + } } - else - { - bgp_info->attr->mp_nexthop_prefer_global = FALSE; - SET_FLAG(bgp_info->attr->rmap_change_flags, - BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED); - } - } - return RMAP_OKAY; + return RMAP_OKAY; } -static void * -route_set_ipv6_nexthop_prefer_global_compile (const char *arg) +static void *route_set_ipv6_nexthop_prefer_global_compile(const char *arg) { - int *rins = NULL; + int *rins = NULL; - rins = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (int)); - *rins = 1; + rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int)); + *rins = 1; - return rins; + return rins; } /* Free route map's compiled `ip next-hop' value. */ -static void -route_set_ipv6_nexthop_prefer_global_free (void *rule) +static void route_set_ipv6_nexthop_prefer_global_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip nexthop set preferred. */ -struct route_map_rule_cmd route_set_ipv6_nexthop_prefer_global_cmd = -{ - "ipv6 next-hop prefer-global", - route_set_ipv6_nexthop_prefer_global, - route_set_ipv6_nexthop_prefer_global_compile, - route_set_ipv6_nexthop_prefer_global_free -}; +struct route_map_rule_cmd route_set_ipv6_nexthop_prefer_global_cmd = { + "ipv6 next-hop prefer-global", route_set_ipv6_nexthop_prefer_global, + route_set_ipv6_nexthop_prefer_global_compile, + route_set_ipv6_nexthop_prefer_global_free}; /* `set ipv6 nexthop local IP_ADDRESS' */ /* Set nexthop to object. ojbect must be pointer to struct attr. */ -static route_map_result_t -route_set_ipv6_nexthop_local (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct in6_addr *address; - struct bgp_info *bgp_info; - - if (type == RMAP_BGP) - { - /* Fetch routemap's rule information. */ - address = rule; - bgp_info = object; - - /* Set next hop value. */ - bgp_info->attr->mp_nexthop_local = *address; - - /* Set nexthop length. */ - if (bgp_info->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) - bgp_info->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; - - SET_FLAG(bgp_info->attr->rmap_change_flags, - BATTR_RMAP_IPV6_LL_NHOP_CHANGED); - } +static route_map_result_t route_set_ipv6_nexthop_local(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct in6_addr *address; + struct bgp_info *bgp_info; + + if (type == RMAP_BGP) { + /* Fetch routemap's rule information. */ + address = rule; + bgp_info = object; + + /* Set next hop value. */ + bgp_info->attr->mp_nexthop_local = *address; + + /* Set nexthop length. */ + if (bgp_info->attr->mp_nexthop_len + != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) + bgp_info->attr->mp_nexthop_len = + BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; + + SET_FLAG(bgp_info->attr->rmap_change_flags, + BATTR_RMAP_IPV6_LL_NHOP_CHANGED); + } - return RMAP_OKAY; + return RMAP_OKAY; } /* Route map `ip nexthop' compile function. Given string is converted to struct in_addr structure. */ -static void * -route_set_ipv6_nexthop_local_compile (const char *arg) +static void *route_set_ipv6_nexthop_local_compile(const char *arg) { - int ret; - struct in6_addr *address; + int ret; + struct in6_addr *address; - address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr)); + address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr)); - ret = inet_pton (AF_INET6, arg, address); + ret = inet_pton(AF_INET6, arg, address); - if (ret == 0) - { - XFREE (MTYPE_ROUTE_MAP_COMPILED, address); - return NULL; - } + if (ret == 0) { + XFREE(MTYPE_ROUTE_MAP_COMPILED, address); + return NULL; + } - return address; + return address; } /* Free route map's compiled `ip nexthop' value. */ -static void -route_set_ipv6_nexthop_local_free (void *rule) +static void route_set_ipv6_nexthop_local_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip nexthop set. */ -struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd = -{ - "ipv6 next-hop local", - route_set_ipv6_nexthop_local, - route_set_ipv6_nexthop_local_compile, - route_set_ipv6_nexthop_local_free -}; +struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd = { + "ipv6 next-hop local", route_set_ipv6_nexthop_local, + route_set_ipv6_nexthop_local_compile, + route_set_ipv6_nexthop_local_free}; /* `set ipv6 nexthop peer-address' */ /* Set nexthop to object. ojbect must be pointer to struct attr. */ -static route_map_result_t -route_set_ipv6_nexthop_peer (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct in6_addr peer_address; - struct bgp_info *bgp_info; - struct peer *peer; - - if (type == RMAP_BGP) - { - /* Fetch routemap's rule information. */ - bgp_info = object; - peer = bgp_info->peer; - - if ((CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN) || - CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) - && peer->su_remote - && sockunion_family (peer->su_remote) == AF_INET6) - { - peer_address = peer->su_remote->sin6.sin6_addr; - /* Set next hop value and length in attribute. */ - if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) - { - bgp_info->attr->mp_nexthop_local = peer_address; - if (bgp_info->attr->mp_nexthop_len != 32) - bgp_info->attr->mp_nexthop_len = 32; - } - else - { - bgp_info->attr->mp_nexthop_global = peer_address; - if (bgp_info->attr->mp_nexthop_len == 0) - bgp_info->attr->mp_nexthop_len = 16; - } - - } - else if (CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT)) - { - /* The next hop value will be set as part of packet rewrite. - * Set the flags here to indicate that rewrite needs to be done. - * Also, clear the value - we clear both global and link-local - * nexthops, whether we send one or both is determined elsewhere. - */ - SET_FLAG(bgp_info->attr->rmap_change_flags, - BATTR_RMAP_NEXTHOP_PEER_ADDRESS); - /* clear next hop value. */ - memset (&(bgp_info->attr->mp_nexthop_global), - 0, sizeof (struct in6_addr)); - memset (&(bgp_info->attr->mp_nexthop_local), - 0, sizeof (struct in6_addr)); +static route_map_result_t route_set_ipv6_nexthop_peer(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct in6_addr peer_address; + struct bgp_info *bgp_info; + struct peer *peer; + + if (type == RMAP_BGP) { + /* Fetch routemap's rule information. */ + bgp_info = object; + peer = bgp_info->peer; + + if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN) + || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) + && peer->su_remote + && sockunion_family(peer->su_remote) == AF_INET6) { + peer_address = peer->su_remote->sin6.sin6_addr; + /* Set next hop value and length in attribute. */ + if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) { + bgp_info->attr->mp_nexthop_local = peer_address; + if (bgp_info->attr->mp_nexthop_len != 32) + bgp_info->attr->mp_nexthop_len = 32; + } else { + bgp_info->attr->mp_nexthop_global = + peer_address; + if (bgp_info->attr->mp_nexthop_len == 0) + bgp_info->attr->mp_nexthop_len = 16; + } + + } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) { + /* The next hop value will be set as part of packet + * rewrite. + * Set the flags here to indicate that rewrite needs to + * be done. + * Also, clear the value - we clear both global and + * link-local + * nexthops, whether we send one or both is determined + * elsewhere. + */ + SET_FLAG(bgp_info->attr->rmap_change_flags, + BATTR_RMAP_NEXTHOP_PEER_ADDRESS); + /* clear next hop value. */ + memset(&(bgp_info->attr->mp_nexthop_global), 0, + sizeof(struct in6_addr)); + memset(&(bgp_info->attr->mp_nexthop_local), 0, + sizeof(struct in6_addr)); + } } - } - return RMAP_OKAY; + return RMAP_OKAY; } /* Route map `ip next-hop' compile function. Given string is converted to struct in_addr structure. */ -static void * -route_set_ipv6_nexthop_peer_compile (const char *arg) +static void *route_set_ipv6_nexthop_peer_compile(const char *arg) { - int *rins = NULL; + int *rins = NULL; - rins = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (int)); - *rins = 1; + rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int)); + *rins = 1; - return rins; + return rins; } /* Free route map's compiled `ip next-hop' value. */ -static void -route_set_ipv6_nexthop_peer_free (void *rule) +static void route_set_ipv6_nexthop_peer_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip nexthop set. */ -struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd = -{ - "ipv6 next-hop peer-address", - route_set_ipv6_nexthop_peer, - route_set_ipv6_nexthop_peer_compile, - route_set_ipv6_nexthop_peer_free -}; +struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd = { + "ipv6 next-hop peer-address", route_set_ipv6_nexthop_peer, + route_set_ipv6_nexthop_peer_compile, route_set_ipv6_nexthop_peer_free}; /* `set ipv4 vpn next-hop A.B.C.D' */ -static route_map_result_t -route_set_vpnv4_nexthop (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_vpnv4_nexthop(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct in_addr *address; - struct bgp_info *bgp_info; + struct in_addr *address; + struct bgp_info *bgp_info; - if (type == RMAP_BGP) - { - /* Fetch routemap's rule information. */ - address = rule; - bgp_info = object; + if (type == RMAP_BGP) { + /* Fetch routemap's rule information. */ + address = rule; + bgp_info = object; - /* Set next hop value. */ - bgp_info->attr->mp_nexthop_global_in = *address; - bgp_info->attr->mp_nexthop_len = 4; - } + /* Set next hop value. */ + bgp_info->attr->mp_nexthop_global_in = *address; + bgp_info->attr->mp_nexthop_len = 4; + } - return RMAP_OKAY; + return RMAP_OKAY; } -static void * -route_set_vpnv4_nexthop_compile (const char *arg) +static void *route_set_vpnv4_nexthop_compile(const char *arg) { - int ret; - struct in_addr *address; + int ret; + struct in_addr *address; - address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr)); + address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr)); - ret = inet_aton (arg, address); + ret = inet_aton(arg, address); - if (ret == 0) - { - XFREE (MTYPE_ROUTE_MAP_COMPILED, address); - return NULL; - } + if (ret == 0) { + XFREE(MTYPE_ROUTE_MAP_COMPILED, address); + return NULL; + } - return address; + return address; } /* `set ipv6 vpn next-hop A.B.C.D' */ -static route_map_result_t -route_set_vpnv6_nexthop (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_vpnv6_nexthop(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct in6_addr *address; - struct bgp_info *bgp_info; + struct in6_addr *address; + struct bgp_info *bgp_info; - if (type == RMAP_BGP) - { - /* Fetch routemap's rule information. */ - address = rule; - bgp_info = object; + if (type == RMAP_BGP) { + /* Fetch routemap's rule information. */ + address = rule; + bgp_info = object; - /* Set next hop value. */ - memcpy (&bgp_info->attr->mp_nexthop_global, address, sizeof(struct in6_addr)); - bgp_info->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL; - } + /* Set next hop value. */ + memcpy(&bgp_info->attr->mp_nexthop_global, address, + sizeof(struct in6_addr)); + bgp_info->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL; + } - return RMAP_OKAY; + return RMAP_OKAY; } -static void * -route_set_vpnv6_nexthop_compile (const char *arg) +static void *route_set_vpnv6_nexthop_compile(const char *arg) { - int ret; - struct in6_addr *address; + int ret; + struct in6_addr *address; - address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr)); - ret = inet_pton (AF_INET6, arg, address); + address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr)); + ret = inet_pton(AF_INET6, arg, address); - if (ret == 0) - { - XFREE (MTYPE_ROUTE_MAP_COMPILED, address); - return NULL; - } + if (ret == 0) { + XFREE(MTYPE_ROUTE_MAP_COMPILED, address); + return NULL; + } - return address; + return address; } -static void -route_set_vpn_nexthop_free (void *rule) +static void route_set_vpn_nexthop_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ipv4 next-hop set. */ -struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd = -{ - "ipv4 vpn next-hop", - route_set_vpnv4_nexthop, - route_set_vpnv4_nexthop_compile, - route_set_vpn_nexthop_free -}; +struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd = { + "ipv4 vpn next-hop", route_set_vpnv4_nexthop, + route_set_vpnv4_nexthop_compile, route_set_vpn_nexthop_free}; /* Route map commands for ipv6 next-hop set. */ -struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = -{ - "ipv6 vpn next-hop", - route_set_vpnv6_nexthop, - route_set_vpnv6_nexthop_compile, - route_set_vpn_nexthop_free -}; +struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = { + "ipv6 vpn next-hop", route_set_vpnv6_nexthop, + route_set_vpnv6_nexthop_compile, route_set_vpn_nexthop_free}; /* `set originator-id' */ /* For origin set. */ -static route_map_result_t -route_set_originator_id (void *rule, struct prefix *prefix, route_map_object_t type, void *object) +static route_map_result_t route_set_originator_id(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct in_addr *address; - struct bgp_info *bgp_info; + struct in_addr *address; + struct bgp_info *bgp_info; - if (type == RMAP_BGP) - { - address = rule; - bgp_info = object; + if (type == RMAP_BGP) { + address = rule; + bgp_info = object; - bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID); - bgp_info->attr->originator_id = *address; - } + bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID); + bgp_info->attr->originator_id = *address; + } - return RMAP_OKAY; + return RMAP_OKAY; } /* Compile function for originator-id set. */ -static void * -route_set_originator_id_compile (const char *arg) +static void *route_set_originator_id_compile(const char *arg) { - int ret; - struct in_addr *address; + int ret; + struct in_addr *address; - address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr)); + address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr)); - ret = inet_aton (arg, address); + ret = inet_aton(arg, address); - if (ret == 0) - { - XFREE (MTYPE_ROUTE_MAP_COMPILED, address); - return NULL; - } + if (ret == 0) { + XFREE(MTYPE_ROUTE_MAP_COMPILED, address); + return NULL; + } - return address; + return address; } /* Compile function for originator_id set. */ -static void -route_set_originator_id_free (void *rule) +static void route_set_originator_id_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Set originator-id rule structure. */ -struct route_map_rule_cmd route_set_originator_id_cmd = -{ - "originator-id", - route_set_originator_id, - route_set_originator_id_compile, - route_set_originator_id_free, +struct route_map_rule_cmd route_set_originator_id_cmd = { + "originator-id", route_set_originator_id, + route_set_originator_id_compile, route_set_originator_id_free, }; /* Add bgp route map rule. */ -static int -bgp_route_match_add (struct vty *vty, - const char *command, const char *arg, - route_map_event_t type) -{ - VTY_DECLVAR_CONTEXT(route_map_index, index); - int ret; - - ret = route_map_add_match (index, command, arg); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% BGP Can't find rule.\n"); - return CMD_WARNING_CONFIG_FAILED; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% BGP Argument is malformed.\n"); - return CMD_WARNING_CONFIG_FAILED; +static int bgp_route_match_add(struct vty *vty, const char *command, + const char *arg, route_map_event_t type) +{ + VTY_DECLVAR_CONTEXT(route_map_index, index); + int ret; + + ret = route_map_add_match(index, command, arg); + if (ret) { + switch (ret) { + case RMAP_RULE_MISSING: + vty_out(vty, "%% BGP Can't find rule.\n"); + return CMD_WARNING_CONFIG_FAILED; + case RMAP_COMPILE_ERROR: + vty_out(vty, "%% BGP Argument is malformed.\n"); + return CMD_WARNING_CONFIG_FAILED; + } } - } - if (type != RMAP_EVENT_MATCH_ADDED) - { - route_map_upd8_dependency (type, arg, index->map->name); - } + if (type != RMAP_EVENT_MATCH_ADDED) { + route_map_upd8_dependency(type, arg, index->map->name); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Delete bgp route map rule. */ -static int -bgp_route_match_delete (struct vty *vty, - const char *command, const char *arg, - route_map_event_t type) -{ - VTY_DECLVAR_CONTEXT(route_map_index, index); - int ret; - char *dep_name = NULL; - const char *tmpstr; - char *rmap_name = NULL; - - if (type != RMAP_EVENT_MATCH_DELETED) - { - /* ignore the mundane, the types without any dependency */ - if (arg == NULL) - { - if ((tmpstr = route_map_get_match_arg(index, command)) != NULL) - dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr); - } - else - { - dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg); +static int bgp_route_match_delete(struct vty *vty, const char *command, + const char *arg, route_map_event_t type) +{ + VTY_DECLVAR_CONTEXT(route_map_index, index); + int ret; + char *dep_name = NULL; + const char *tmpstr; + char *rmap_name = NULL; + + if (type != RMAP_EVENT_MATCH_DELETED) { + /* ignore the mundane, the types without any dependency */ + if (arg == NULL) { + if ((tmpstr = route_map_get_match_arg(index, command)) + != NULL) + dep_name = + XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr); + } else { + dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg); + } + rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name); } - rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name); - } - - ret = route_map_delete_match (index, command, dep_name); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% BGP Can't find rule.\n"); - break; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% BGP Argument is malformed.\n"); - break; + + ret = route_map_delete_match(index, command, dep_name); + if (ret) { + switch (ret) { + case RMAP_RULE_MISSING: + vty_out(vty, "%% BGP Can't find rule.\n"); + break; + case RMAP_COMPILE_ERROR: + vty_out(vty, "%% BGP Argument is malformed.\n"); + break; + } + if (dep_name) + XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); + if (rmap_name) + XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); + return CMD_WARNING_CONFIG_FAILED; } - if (dep_name) - XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); - if (rmap_name) - XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); - return CMD_WARNING_CONFIG_FAILED; - } - if (type != RMAP_EVENT_MATCH_DELETED && dep_name) - route_map_upd8_dependency(type, dep_name, rmap_name); + if (type != RMAP_EVENT_MATCH_DELETED && dep_name) + route_map_upd8_dependency(type, dep_name, rmap_name); - if (dep_name) - XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); - if (rmap_name) - XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); + if (dep_name) + XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); + if (rmap_name) + XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* * This is the workhorse routine for processing in/out routemap * modifications. */ -static void -bgp_route_map_process_peer (const char *rmap_name, struct route_map *map, - struct peer *peer, int afi, int safi, - int route_update) -{ - - int update; - struct bgp_filter *filter; - - if (!peer || !rmap_name) - return; - - filter = &peer->filter[afi][safi]; - /* - * in is for non-route-server clients, - * out is for all peers - */ - if (!CHECK_FLAG(peer->flags, PEER_FLAG_RSERVER_CLIENT)) - { - if (filter->map[RMAP_IN].name && - (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0)) - { - filter->map[RMAP_IN].map = map; - - if (route_update && peer->status == Established) - { - if (CHECK_FLAG (peer->af_flags[afi][safi], - PEER_FLAG_SOFT_RECONFIG)) - { - if (bgp_debug_update(peer, NULL, NULL, 1)) - zlog_debug("Processing route_map %s update on " - "peer %s (inbound, soft-reconfig)", - rmap_name, peer->host); - - bgp_soft_reconfig_in (peer, afi, safi); - } - else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV) - || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV)) - { - - if (bgp_debug_update(peer, NULL, NULL, 1)) - zlog_debug("Processing route_map %s update on " - "peer %s (inbound, route-refresh)", - rmap_name, peer->host); - bgp_route_refresh_send (peer, afi, safi, 0, 0, 0); +static void bgp_route_map_process_peer(const char *rmap_name, + struct route_map *map, struct peer *peer, + int afi, int safi, int route_update) +{ + + int update; + struct bgp_filter *filter; + + if (!peer || !rmap_name) + return; + + filter = &peer->filter[afi][safi]; + /* + * in is for non-route-server clients, + * out is for all peers + */ + if (!CHECK_FLAG(peer->flags, PEER_FLAG_RSERVER_CLIENT)) { + if (filter->map[RMAP_IN].name + && (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0)) { + filter->map[RMAP_IN].map = map; + + if (route_update && peer->status == Established) { + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_SOFT_RECONFIG)) { + if (bgp_debug_update(peer, NULL, NULL, + 1)) + zlog_debug( + "Processing route_map %s update on " + "peer %s (inbound, soft-reconfig)", + rmap_name, peer->host); + + bgp_soft_reconfig_in(peer, afi, safi); + } else if ( + CHECK_FLAG(peer->cap, + PEER_CAP_REFRESH_OLD_RCV) + || CHECK_FLAG( + peer->cap, + PEER_CAP_REFRESH_NEW_RCV)) { + + if (bgp_debug_update(peer, NULL, NULL, + 1)) + zlog_debug( + "Processing route_map %s update on " + "peer %s (inbound, route-refresh)", + rmap_name, peer->host); + bgp_route_refresh_send(peer, afi, safi, + 0, 0, 0); + } + } } - } } - } - - if (CHECK_FLAG(peer->flags, PEER_FLAG_RSERVER_CLIENT)) - { - update = 0; - - if (update && route_update && peer->status == Established) - { - if (CHECK_FLAG (peer->af_flags[afi][safi], - PEER_FLAG_SOFT_RECONFIG)) - { - if (bgp_debug_update(peer, NULL, NULL, 1)) - zlog_debug("Processing route_map %s update on " - "peer %s (import, soft-reconfig)", - rmap_name, peer->host); - - bgp_soft_reconfig_in (peer, afi, safi); - } - else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV) - || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV)) - { - if (bgp_debug_update(peer, NULL, NULL, 1)) - zlog_debug("Processing route_map %s update on " - "peer %s (import, route-refresh)", - rmap_name, peer->host); - bgp_route_refresh_send (peer, afi, safi, 0, 0, 0); - } - /* DD: Else, what else do we do ? Reset peer ? */ - } - } - - /* - * For outbound, unsuppress and default-originate map change (content or - * map created), merely update the "config" here, the actual route - * announcement happens at the group level. - */ - if (filter->map[RMAP_OUT].name && - (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0)) - filter->map[RMAP_OUT].map = map; - - if (filter->usmap.name && - (strcmp(rmap_name, filter->usmap.name) == 0)) - filter->usmap.map = map; - - if (peer->default_rmap[afi][safi].name && - (strcmp (rmap_name, peer->default_rmap[afi][safi].name) == 0)) - peer->default_rmap[afi][safi].map = map; -} - -static void -bgp_route_map_update_peer_group(const char *rmap_name, struct route_map *map, - struct bgp *bgp) -{ - struct peer_group *group; - struct listnode *node, *nnode; - struct bgp_filter *filter; - int afi, safi; - int direct; - - if (!bgp) - return; - - /* All the peers have been updated correctly already. This is - * just updating the placeholder data. No real update required. - */ - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - filter = &group->conf->filter[afi][safi]; - - for (direct = RMAP_IN; direct < RMAP_MAX; direct++) - { - if ((filter->map[direct].name) && - (strcmp(rmap_name, filter->map[direct].name) == 0)) - filter->map[direct].map = map; - } - - if (filter->usmap.name && - (strcmp(rmap_name, filter->usmap.name) == 0)) - filter->usmap.map = map; + + if (CHECK_FLAG(peer->flags, PEER_FLAG_RSERVER_CLIENT)) { + update = 0; + + if (update && route_update && peer->status == Established) { + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_SOFT_RECONFIG)) { + if (bgp_debug_update(peer, NULL, NULL, 1)) + zlog_debug( + "Processing route_map %s update on " + "peer %s (import, soft-reconfig)", + rmap_name, peer->host); + + bgp_soft_reconfig_in(peer, afi, safi); + } else if (CHECK_FLAG(peer->cap, + PEER_CAP_REFRESH_OLD_RCV) + || CHECK_FLAG(peer->cap, + PEER_CAP_REFRESH_NEW_RCV)) { + if (bgp_debug_update(peer, NULL, NULL, 1)) + zlog_debug( + "Processing route_map %s update on " + "peer %s (import, route-refresh)", + rmap_name, peer->host); + bgp_route_refresh_send(peer, afi, safi, 0, 0, + 0); + } + /* DD: Else, what else do we do ? Reset peer ? */ + } } + + /* + * For outbound, unsuppress and default-originate map change (content or + * map created), merely update the "config" here, the actual route + * announcement happens at the group level. + */ + if (filter->map[RMAP_OUT].name + && (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0)) + filter->map[RMAP_OUT].map = map; + + if (filter->usmap.name && (strcmp(rmap_name, filter->usmap.name) == 0)) + filter->usmap.map = map; + + if (peer->default_rmap[afi][safi].name + && (strcmp(rmap_name, peer->default_rmap[afi][safi].name) == 0)) + peer->default_rmap[afi][safi].map = map; +} + +static void bgp_route_map_update_peer_group(const char *rmap_name, + struct route_map *map, + struct bgp *bgp) +{ + struct peer_group *group; + struct listnode *node, *nnode; + struct bgp_filter *filter; + int afi, safi; + int direct; + + if (!bgp) + return; + + /* All the peers have been updated correctly already. This is + * just updating the placeholder data. No real update required. + */ + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + filter = &group->conf->filter[afi][safi]; + + for (direct = RMAP_IN; direct < RMAP_MAX; + direct++) { + if ((filter->map[direct].name) + && (strcmp(rmap_name, + filter->map[direct].name) + == 0)) + filter->map[direct].map = map; + } + + if (filter->usmap.name + && (strcmp(rmap_name, filter->usmap.name) + == 0)) + filter->usmap.map = map; + } } /* @@ -3047,203 +2784,214 @@ bgp_route_map_update_peer_group(const char *rmap_name, struct route_map *map, * called for each route-map and within this function we walk the list of peers, * network statements, etc looking to see if they use this route-map. */ -static void -bgp_route_map_process_update (struct bgp *bgp, const char *rmap_name, int route_update) -{ - int i; - afi_t afi; - safi_t safi; - struct peer *peer; - struct bgp_node *bn; - struct bgp_static *bgp_static; - struct listnode *node, *nnode; - struct route_map *map; - char buf[INET6_ADDRSTRLEN]; - - map = route_map_lookup_by_name (rmap_name); - - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - - /* Ignore dummy peer-group structure */ - if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) - continue; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - /* Ignore inactive AFI/SAFI */ - if (! peer->afc[afi][safi]) - continue; - - /* process in/out/import/export/default-orig route-maps */ - bgp_route_map_process_peer(rmap_name, map, peer, afi, safi, route_update); - } - } - - /* for outbound/default-orig route-maps, process for groups */ - update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name, - route_update, 0); - - /* update peer-group config (template) */ - bgp_route_map_update_peer_group(rmap_name, map, bgp); - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - /* For table route-map updates. */ - if (!bgp_fibupd_safi(safi)) - continue; - - if (bgp->table_map[afi][safi].name && - (strcmp(rmap_name, bgp->table_map[afi][safi].name) == 0)) - { - bgp->table_map[afi][safi].map = map; - - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Processing route_map %s update on " - "table map", rmap_name); - if (route_update) - bgp_zebra_announce_table(bgp, afi, safi); - } - - /* For network route-map updates. */ - for (bn = bgp_table_top (bgp->route[afi][safi]); bn; bn = bgp_route_next (bn)) - if ((bgp_static = bn->info) != NULL) - { - if (bgp_static->rmap.name && - (strcmp(rmap_name, bgp_static->rmap.name) == 0)) - { - bgp_static->rmap.map = map; - - if (route_update) - if (!bgp_static->backdoor) - { - if (bgp_debug_zebra(&bn->p)) - zlog_debug("Processing route_map %s update on " - "static route %s", rmap_name, - inet_ntop (bn->p.family, &bn->p.u.prefix, - buf, INET6_ADDRSTRLEN)); - bgp_static_update (bgp, &bn->p, bgp_static, afi, safi); - } - } - } - } - - /* For redistribute route-map updates. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - struct list *red_list; - struct listnode *node; - struct bgp_redist *red; - - red_list = bgp->redist[afi][i]; - if (!red_list) - continue; - - for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) - { - if (red->rmap.name && - (strcmp(rmap_name, red->rmap.name) == 0)) - { - red->rmap.map = map; - - if (route_update) - { - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Processing route_map %s update on " - "redistributed routes", rmap_name); - - bgp_redistribute_resend (bgp, afi, i, red->instance); - } - } - } - } -} - -static int -bgp_route_map_process_update_cb (char *rmap_name) -{ - struct listnode *node, *nnode; - struct bgp *bgp; - - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - bgp_route_map_process_update(bgp, rmap_name, 1); +static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name, + int route_update) +{ + int i; + afi_t afi; + safi_t safi; + struct peer *peer; + struct bgp_node *bn; + struct bgp_static *bgp_static; + struct listnode *node, *nnode; + struct route_map *map; + char buf[INET6_ADDRSTRLEN]; + + map = route_map_lookup_by_name(rmap_name); + + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + + /* Ignore dummy peer-group structure */ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + continue; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + /* Ignore inactive AFI/SAFI */ + if (!peer->afc[afi][safi]) + continue; + + /* process in/out/import/export/default-orig + * route-maps */ + bgp_route_map_process_peer(rmap_name, map, peer, + afi, safi, + route_update); + } + } + + /* for outbound/default-orig route-maps, process for groups */ + update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name, + route_update, 0); + + /* update peer-group config (template) */ + bgp_route_map_update_peer_group(rmap_name, map, bgp); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + /* For table route-map updates. */ + if (!bgp_fibupd_safi(safi)) + continue; + + if (bgp->table_map[afi][safi].name + && (strcmp(rmap_name, + bgp->table_map[afi][safi].name) + == 0)) { + bgp->table_map[afi][safi].map = map; + + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug( + "Processing route_map %s update on " + "table map", + rmap_name); + if (route_update) + bgp_zebra_announce_table(bgp, afi, + safi); + } + + /* For network route-map updates. */ + for (bn = bgp_table_top(bgp->route[afi][safi]); bn; + bn = bgp_route_next(bn)) + if ((bgp_static = bn->info) != NULL) { + if (bgp_static->rmap.name + && (strcmp(rmap_name, + bgp_static->rmap.name) + == 0)) { + bgp_static->rmap.map = map; + + if (route_update) + if (!bgp_static + ->backdoor) { + if (bgp_debug_zebra( + &bn->p)) + zlog_debug( + "Processing route_map %s update on " + "static route %s", + rmap_name, + inet_ntop( + bn->p.family, + &bn->p.u.prefix, + buf, + INET6_ADDRSTRLEN)); + bgp_static_update( + bgp, + &bn->p, + bgp_static, + afi, + safi); + } + } + } + } + + /* For redistribute route-map updates. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + struct list *red_list; + struct listnode *node; + struct bgp_redist *red; + + red_list = bgp->redist[afi][i]; + if (!red_list) + continue; + + for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { + if (red->rmap.name + && (strcmp(rmap_name, red->rmap.name) + == 0)) { + red->rmap.map = map; + + if (route_update) { + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug( + "Processing route_map %s update on " + "redistributed routes", + rmap_name); + + bgp_redistribute_resend( + bgp, afi, i, + red->instance); + } + } + } + } +} + +static int bgp_route_map_process_update_cb(char *rmap_name) +{ + struct listnode *node, *nnode; + struct bgp *bgp; + + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) + bgp_route_map_process_update(bgp, rmap_name, 1); #if ENABLE_BGP_VNC - zlog_debug("%s: calling vnc_routemap_update", __func__); - vnc_routemap_update(bgp, __func__); + zlog_debug("%s: calling vnc_routemap_update", __func__); + vnc_routemap_update(bgp, __func__); #endif - return 0; + return 0; } -int -bgp_route_map_update_timer(struct thread *thread) +int bgp_route_map_update_timer(struct thread *thread) { - bm->t_rmap_update = NULL; + bm->t_rmap_update = NULL; - route_map_walk_update_list(bgp_route_map_process_update_cb); + route_map_walk_update_list(bgp_route_map_process_update_cb); - return (0); + return (0); } -static void -bgp_route_map_mark_update (const char *rmap_name) +static void bgp_route_map_mark_update(const char *rmap_name) { - if (bm->t_rmap_update == NULL) - { - struct listnode *node, *nnode; - struct bgp *bgp; + if (bm->t_rmap_update == NULL) { + struct listnode *node, *nnode; + struct bgp *bgp; - /* rmap_update_timer of 0 means don't do route updates */ - if (bm->rmap_update_timer) - { - bm->t_rmap_update = NULL; - thread_add_timer(bm->master, bgp_route_map_update_timer, NULL, bm->rmap_update_timer, - &bm->t_rmap_update); + /* rmap_update_timer of 0 means don't do route updates */ + if (bm->rmap_update_timer) { + bm->t_rmap_update = NULL; + thread_add_timer(bm->master, bgp_route_map_update_timer, + NULL, bm->rmap_update_timer, + &bm->t_rmap_update); - /* Signal the groups that a route-map update event has started */ - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name, 1, 1); - } - else - { - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - bgp_route_map_process_update(bgp, rmap_name, 0); - #if ENABLE_BGP_VNC - zlog_debug("%s: calling vnc_routemap_update", __func__); - vnc_routemap_update(bgp, __func__); + /* Signal the groups that a route-map update event has + * started */ + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) + update_group_policy_update(bgp, + BGP_POLICY_ROUTE_MAP, + rmap_name, 1, 1); + } else { + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) + bgp_route_map_process_update(bgp, rmap_name, 0); +#if ENABLE_BGP_VNC + zlog_debug("%s: calling vnc_routemap_update", __func__); + vnc_routemap_update(bgp, __func__); #endif - } - } + } + } } -static void -bgp_route_map_add (const char *rmap_name) +static void bgp_route_map_add(const char *rmap_name) { - if (route_map_mark_updated(rmap_name, 0) == 0) - bgp_route_map_mark_update(rmap_name); + if (route_map_mark_updated(rmap_name, 0) == 0) + bgp_route_map_mark_update(rmap_name); - route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); } -static void -bgp_route_map_delete (const char *rmap_name) +static void bgp_route_map_delete(const char *rmap_name) { - if (route_map_mark_updated(rmap_name, 1) == 0) - bgp_route_map_mark_update(rmap_name); + if (route_map_mark_updated(rmap_name, 1) == 0) + bgp_route_map_mark_update(rmap_name); - route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED); + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED); } -static void -bgp_route_map_event (route_map_event_t event, const char *rmap_name) +static void bgp_route_map_event(route_map_event_t event, const char *rmap_name) { - if (route_map_mark_updated(rmap_name, 0) == 0) - bgp_route_map_mark_update(rmap_name); + if (route_map_mark_updated(rmap_name, 0) == 0) + bgp_route_map_mark_update(rmap_name); - route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); } @@ -3255,9 +3003,9 @@ DEFUN (match_peer, "IP address of peer\n" "IPv6 address of peer\n") { - int idx_ip = 2; - return bgp_route_match_add (vty, "peer", argv[idx_ip]->arg, - RMAP_EVENT_MATCH_ADDED); + int idx_ip = 2; + return bgp_route_match_add(vty, "peer", argv[idx_ip]->arg, + RMAP_EVENT_MATCH_ADDED); } DEFUN (match_peer_local, @@ -3267,8 +3015,8 @@ DEFUN (match_peer_local, "Match peer address\n" "Static or Redistributed routes\n") { - return bgp_route_match_add (vty, "peer", "local", - RMAP_EVENT_MATCH_DELETED); + return bgp_route_match_add(vty, "peer", "local", + RMAP_EVENT_MATCH_DELETED); } DEFUN (no_match_peer, @@ -3281,13 +3029,13 @@ DEFUN (no_match_peer, "IP address of peer\n" "IPv6 address of peer\n") { - int idx_peer = 3; + int idx_peer = 3; - if (argc <= idx_peer) - return bgp_route_match_delete (vty, "peer", NULL, - RMAP_EVENT_MATCH_DELETED); - return bgp_route_match_delete (vty, "peer", argv[idx_peer]->arg, - RMAP_EVENT_MATCH_DELETED); + if (argc <= idx_peer) + return bgp_route_match_delete(vty, "peer", NULL, + RMAP_EVENT_MATCH_DELETED); + return bgp_route_match_delete(vty, "peer", argv[idx_peer]->arg, + RMAP_EVENT_MATCH_DELETED); } @@ -3299,9 +3047,9 @@ DEFUN (match_probability, "Match portion of routes defined by percentage value\n" "Percentage of routes\n") { - int idx_number = 2; - return bgp_route_match_add (vty, "probability", argv[idx_number]->arg, - RMAP_EVENT_MATCH_ADDED); + int idx_number = 2; + return bgp_route_match_add(vty, "probability", argv[idx_number]->arg, + RMAP_EVENT_MATCH_ADDED); } @@ -3313,12 +3061,12 @@ DEFUN (no_match_probability, "Match portion of routes defined by percentage value\n" "Percentage of routes\n") { - int idx_number = 3; - if (argc <= idx_number) - return bgp_route_match_delete (vty, "probability", NULL, - RMAP_EVENT_MATCH_DELETED); - return bgp_route_match_delete (vty, "probability", argv[idx_number]->arg, - RMAP_EVENT_MATCH_DELETED); + int idx_number = 3; + if (argc <= idx_number) + return bgp_route_match_delete(vty, "probability", NULL, + RMAP_EVENT_MATCH_DELETED); + return bgp_route_match_delete(vty, "probability", argv[idx_number]->arg, + RMAP_EVENT_MATCH_DELETED); } @@ -3332,9 +3080,9 @@ DEFUN (match_ip_route_source, "IP access-list number (expanded range)\n" "IP standard access-list name\n") { - int idx_acl = 3; - return bgp_route_match_add (vty, "ip route-source", argv[idx_acl]->arg, - RMAP_EVENT_FILTER_ADDED); + int idx_acl = 3; + return bgp_route_match_add(vty, "ip route-source", argv[idx_acl]->arg, + RMAP_EVENT_FILTER_ADDED); } @@ -3349,12 +3097,13 @@ DEFUN (no_match_ip_route_source, "IP access-list number (expanded range)\n" "IP standard access-list name\n") { - int idx_number = 4; - if (argc <= idx_number) - return bgp_route_match_delete (vty, "ip route-source", - NULL, RMAP_EVENT_FILTER_DELETED); - return bgp_route_match_delete (vty, "ip route-source", - argv[idx_number]->arg, RMAP_EVENT_FILTER_DELETED); + int idx_number = 4; + if (argc <= idx_number) + return bgp_route_match_delete(vty, "ip route-source", NULL, + RMAP_EVENT_FILTER_DELETED); + return bgp_route_match_delete(vty, "ip route-source", + argv[idx_number]->arg, + RMAP_EVENT_FILTER_DELETED); } @@ -3367,9 +3116,9 @@ DEFUN (match_ip_route_source_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - int idx_word = 4; - return bgp_route_match_add (vty, "ip route-source prefix-list", - argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED); + int idx_word = 4; + return bgp_route_match_add(vty, "ip route-source prefix-list", + argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED); } @@ -3383,12 +3132,14 @@ DEFUN (no_match_ip_route_source_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - int idx_word = 5; - if (argc <= idx_word) - return bgp_route_match_delete (vty, "ip route-source prefix-list", - NULL, RMAP_EVENT_PLIST_DELETED); - return bgp_route_match_delete (vty, "ip route-source prefix-list", - argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED); + int idx_word = 5; + if (argc <= idx_word) + return bgp_route_match_delete(vty, + "ip route-source prefix-list", + NULL, RMAP_EVENT_PLIST_DELETED); + return bgp_route_match_delete(vty, "ip route-source prefix-list", + argv[idx_word]->arg, + RMAP_EVENT_PLIST_DELETED); } @@ -3399,9 +3150,10 @@ DEFUN (match_local_pref, "Match local-preference of route\n" "Metric value\n") { - int idx_number = 2; - return bgp_route_match_add (vty, "local-preference", argv[idx_number]->arg, - RMAP_EVENT_MATCH_ADDED); + int idx_number = 2; + return bgp_route_match_add(vty, "local-preference", + argv[idx_number]->arg, + RMAP_EVENT_MATCH_ADDED); } @@ -3413,13 +3165,13 @@ DEFUN (no_match_local_pref, "Match local preference of route\n" "Local preference value\n") { - int idx_localpref = 3; - if (argc <= idx_localpref) - return bgp_route_match_delete (vty, "local-preference", - NULL, RMAP_EVENT_MATCH_DELETED); - return bgp_route_match_delete (vty, "local-preference", - argv[idx_localpref]->arg, - RMAP_EVENT_MATCH_DELETED); + int idx_localpref = 3; + if (argc <= idx_localpref) + return bgp_route_match_delete(vty, "local-preference", NULL, + RMAP_EVENT_MATCH_DELETED); + return bgp_route_match_delete(vty, "local-preference", + argv[idx_localpref]->arg, + RMAP_EVENT_MATCH_DELETED); } @@ -3433,28 +3185,26 @@ DEFUN (match_community, "Community-list name\n" "Do exact matching of communities\n") { - int idx_comm_list = 2; - int ret; - char *argstr; + int idx_comm_list = 2; + int ret; + char *argstr; - if (argc == 4) - { - argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, - strlen (argv[idx_comm_list]->arg) + - strlen ("exact-match") + 2); + if (argc == 4) { + argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, + strlen(argv[idx_comm_list]->arg) + + strlen("exact-match") + 2); - sprintf (argstr, "%s exact-match", argv[idx_comm_list]->arg); - } - else - argstr = argv[idx_comm_list]->arg; + sprintf(argstr, "%s exact-match", argv[idx_comm_list]->arg); + } else + argstr = argv[idx_comm_list]->arg; - ret = bgp_route_match_add (vty, "community", argstr, - RMAP_EVENT_CLIST_ADDED); + ret = bgp_route_match_add(vty, "community", argstr, + RMAP_EVENT_CLIST_ADDED); - if (argstr != argv[idx_comm_list]->arg) - XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr); + if (argstr != argv[idx_comm_list]->arg) + XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr); - return ret; + return ret; } DEFUN (no_match_community, @@ -3468,8 +3218,8 @@ DEFUN (no_match_community, "Community-list name\n" "Do exact matching of communities\n") { - return bgp_route_match_delete (vty, "community", NULL, - RMAP_EVENT_CLIST_DELETED); + return bgp_route_match_delete(vty, "community", NULL, + RMAP_EVENT_CLIST_DELETED); } DEFUN (match_lcommunity, @@ -3481,8 +3231,8 @@ DEFUN (match_lcommunity, "Large Community-list number (expanded)\n" "Large Community-list name\n") { - return bgp_route_match_add (vty, "large-community", argv[2]->arg, - RMAP_EVENT_LLIST_ADDED); + return bgp_route_match_add(vty, "large-community", argv[2]->arg, + RMAP_EVENT_LLIST_ADDED); } DEFUN (no_match_lcommunity, @@ -3495,8 +3245,8 @@ DEFUN (no_match_lcommunity, "Large Community-list number (expanded)\n" "Large Community-list name\n") { - return bgp_route_match_delete (vty, "large-community", NULL, - RMAP_EVENT_LLIST_DELETED); + return bgp_route_match_delete(vty, "large-community", NULL, + RMAP_EVENT_LLIST_DELETED); } DEFUN (match_ecommunity, @@ -3508,9 +3258,10 @@ DEFUN (match_ecommunity, "Extended community-list number (expanded)\n" "Extended community-list name\n") { - int idx_comm_list = 2; - return bgp_route_match_add (vty, "extcommunity", argv[idx_comm_list]->arg, - RMAP_EVENT_ECLIST_ADDED); + int idx_comm_list = 2; + return bgp_route_match_add(vty, "extcommunity", + argv[idx_comm_list]->arg, + RMAP_EVENT_ECLIST_ADDED); } @@ -3524,8 +3275,8 @@ DEFUN (no_match_ecommunity, "Extended community-list number (expanded)\n" "Extended community-list name\n") { - return bgp_route_match_delete (vty, "extcommunity", NULL, - RMAP_EVENT_ECLIST_DELETED); + return bgp_route_match_delete(vty, "extcommunity", NULL, + RMAP_EVENT_ECLIST_DELETED); } @@ -3536,9 +3287,9 @@ DEFUN (match_aspath, "Match BGP AS path list\n" "AS path access-list name\n") { - int idx_word = 2; - return bgp_route_match_add (vty, "as-path", argv[idx_word]->arg, - RMAP_EVENT_ASLIST_ADDED); + int idx_word = 2; + return bgp_route_match_add(vty, "as-path", argv[idx_word]->arg, + RMAP_EVENT_ASLIST_ADDED); } @@ -3550,8 +3301,8 @@ DEFUN (no_match_aspath, "Match BGP AS path list\n" "AS path access-list name\n") { - return bgp_route_match_delete (vty, "as-path", NULL, - RMAP_EVENT_ASLIST_DELETED); + return bgp_route_match_delete(vty, "as-path", NULL, + RMAP_EVENT_ASLIST_DELETED); } @@ -3564,19 +3315,19 @@ DEFUN (match_origin, "local IGP\n" "unknown heritage\n") { - int idx_origin = 2; - if (strncmp (argv[idx_origin]->arg, "igp", 2) == 0) - return bgp_route_match_add (vty, "origin", "igp", - RMAP_EVENT_MATCH_ADDED); - if (strncmp (argv[idx_origin]->arg, "egp", 1) == 0) - return bgp_route_match_add (vty, "origin", "egp", - RMAP_EVENT_MATCH_ADDED); - if (strncmp (argv[idx_origin]->arg, "incomplete", 2) == 0) - return bgp_route_match_add (vty, "origin", "incomplete", - RMAP_EVENT_MATCH_ADDED); + int idx_origin = 2; + if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0) + return bgp_route_match_add(vty, "origin", "igp", + RMAP_EVENT_MATCH_ADDED); + if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0) + return bgp_route_match_add(vty, "origin", "egp", + RMAP_EVENT_MATCH_ADDED); + if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0) + return bgp_route_match_add(vty, "origin", "incomplete", + RMAP_EVENT_MATCH_ADDED); - vty_out (vty, "%% Invalid match origin type\n"); - return CMD_WARNING_CONFIG_FAILED; + vty_out(vty, "%% Invalid match origin type\n"); + return CMD_WARNING_CONFIG_FAILED; } @@ -3590,8 +3341,8 @@ DEFUN (no_match_origin, "local IGP\n" "unknown heritage\n") { - return bgp_route_match_delete (vty, "origin", NULL, - RMAP_EVENT_MATCH_DELETED); + return bgp_route_match_delete(vty, "origin", NULL, + RMAP_EVENT_MATCH_DELETED); } DEFUN (set_ip_nexthop_peer, @@ -3602,8 +3353,8 @@ DEFUN (set_ip_nexthop_peer, "Next hop address\n" "Use peer address (for BGP only)\n") { - return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "ip next-hop", "peer-address"); + return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "ip next-hop", "peer-address"); } DEFUN (set_ip_nexthop_unchanged, @@ -3614,8 +3365,8 @@ DEFUN (set_ip_nexthop_unchanged, "Next hop address\n" "Don't modify existing Next hop address\n") { - return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "ip next-hop", "unchanged"); + return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "ip next-hop", "unchanged"); } @@ -3626,9 +3377,9 @@ DEFUN (set_local_pref, "BGP local preference path attribute\n" "Preference value\n") { - int idx_number = 2; - return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "local-preference", argv[idx_number]->arg); + int idx_number = 2; + return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "local-preference", argv[idx_number]->arg); } @@ -3640,12 +3391,12 @@ DEFUN (no_set_local_pref, "BGP local preference path attribute\n" "Preference value\n") { - int idx_localpref = 3; - if (argc <= idx_localpref) - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "local-preference", NULL); - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "local-preference", argv[idx_localpref]->arg); + int idx_localpref = 3; + if (argc <= idx_localpref) + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "local-preference", NULL); + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "local-preference", argv[idx_localpref]->arg); } @@ -3656,9 +3407,9 @@ DEFUN (set_weight, "BGP weight for routing table\n" "Weight value\n") { - int idx_number = 2; - return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "weight", - argv[idx_number]->arg); + int idx_number = 2; + return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "weight", + argv[idx_number]->arg); } @@ -3670,12 +3421,12 @@ DEFUN (no_set_weight, "BGP weight for routing table\n" "Weight value\n") { - int idx_weight = 3; - if (argc <= idx_weight) - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "weight", NULL); - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), "weight", - argv[idx_weight]->arg); + int idx_weight = 3; + if (argc <= idx_weight) + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "weight", NULL); + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "weight", argv[idx_weight]->arg); } DEFUN (set_label_index, @@ -3685,9 +3436,9 @@ DEFUN (set_label_index, "Label index to associate with the prefix\n" "Label index value\n") { - int idx_number = 2; - return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "label-index", - argv[idx_number]->arg); + int idx_number = 2; + return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "label-index", argv[idx_number]->arg); } DEFUN (no_set_label_index, @@ -3698,12 +3449,12 @@ DEFUN (no_set_label_index, "Label index to associate with the prefix\n" "Label index value\n") { - int idx_label_index = 3; - if (argc <= idx_label_index) - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "label-index", NULL); - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), "label-index", - argv[idx_label_index]->arg); + int idx_label_index = 3; + if (argc <= idx_label_index) + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "label-index", NULL); + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "label-index", argv[idx_label_index]->arg); } DEFUN (set_aspath_prepend_asn, @@ -3714,16 +3465,16 @@ DEFUN (set_aspath_prepend_asn, "Prepend to the as-path\n" "AS number\n") { - int idx_asn = 3; - int ret; - char *str; + int idx_asn = 3; + int ret; + char *str; - str = argv_concat (argv, argc, idx_asn); - ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "as-path prepend", str); - XFREE (MTYPE_TMP, str); + str = argv_concat(argv, argc, idx_asn); + ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "as-path prepend", str); + XFREE(MTYPE_TMP, str); - return ret; + return ret; } DEFUN (set_aspath_prepend_lastas, @@ -3735,7 +3486,7 @@ DEFUN (set_aspath_prepend_lastas, "Use the peer's AS-number\n" "Number of times to insert\n") { - return set_aspath_prepend_asn (self, vty, argc, argv); + return set_aspath_prepend_asn(self, vty, argc, argv); } DEFUN (no_set_aspath_prepend, @@ -3747,15 +3498,15 @@ DEFUN (no_set_aspath_prepend, "Prepend to the as-path\n" "AS number\n") { - int idx_asn = 4; - int ret; - char *str; + int idx_asn = 4; + int ret; + char *str; - str = argv_concat (argv, argc, idx_asn); - ret = generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "as-path prepend", str); - XFREE (MTYPE_TMP, str); - return ret; + str = argv_concat(argv, argc, idx_asn); + ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "as-path prepend", str); + XFREE(MTYPE_TMP, str); + return ret; } @@ -3767,15 +3518,15 @@ DEFUN (set_aspath_exclude, "Exclude from the as-path\n" "AS number\n") { - int idx_asn = 3; - int ret; - char *str; + int idx_asn = 3; + int ret; + char *str; - str = argv_concat (argv, argc, idx_asn); - ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "as-path exclude", str); - XFREE (MTYPE_TMP, str); - return ret; + str = argv_concat(argv, argc, idx_asn); + ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "as-path exclude", str); + XFREE(MTYPE_TMP, str); + return ret; } DEFUN (no_set_aspath_exclude, @@ -3787,15 +3538,15 @@ DEFUN (no_set_aspath_exclude, "Exclude from the as-path\n" "AS number\n") { - int idx_asn = 4; - int ret; - char *str; + int idx_asn = 4; + int ret; + char *str; - str = argv_concat (argv, argc, idx_asn); - ret = generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "as-path exclude", str); - XFREE (MTYPE_TMP, str); - return ret; + str = argv_concat(argv, argc, idx_asn); + ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "as-path exclude", str); + XFREE(MTYPE_TMP, str); + return ret; } @@ -3806,93 +3557,90 @@ DEFUN (set_community, "BGP community attribute\n" COMMUNITY_VAL_STR) { - int idx_aa_nn = 2; - int i; - int first = 0; - int additive = 0; - struct buffer *b; - struct community *com = NULL; - char *str; - char *argstr; - int ret; - - b = buffer_new (1024); - - for (i = idx_aa_nn; i < argc; i++) - { - if (strncmp (argv[i]->arg, "additive", strlen (argv[i]->arg)) == 0) - { - additive = 1; - continue; - } - - if (first) - buffer_putc (b, ' '); - else - first = 1; - - if (strncmp (argv[i]->arg, "internet", strlen (argv[i]->arg)) == 0) - { - buffer_putstr (b, "internet"); - continue; - } - if (strncmp (argv[i]->arg, "local-AS", strlen (argv[i]->arg)) == 0) - { - buffer_putstr (b, "local-AS"); - continue; - } - if (strncmp (argv[i]->arg, "no-a", strlen ("no-a")) == 0 - && strncmp (argv[i]->arg, "no-advertise", strlen (argv[i]->arg)) == 0) - { - buffer_putstr (b, "no-advertise"); - continue; - } - if (strncmp (argv[i]->arg, "no-e", strlen ("no-e"))== 0 - && strncmp (argv[i]->arg, "no-export", strlen (argv[i]->arg)) == 0) - { - buffer_putstr (b, "no-export"); - continue; - } - buffer_putstr (b, argv[i]->arg); - } - buffer_putc (b, '\0'); - - /* Fetch result string then compile it to communities attribute. */ - str = buffer_getstr (b); - buffer_free (b); - - if (str) - { - com = community_str2com (str); - XFREE (MTYPE_TMP, str); - } - - /* Can't compile user input into communities attribute. */ - if (! com) - { - vty_out (vty, "%% Malformed communities attribute\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Set communites attribute string. */ - str = community_str (com); - - if (additive) - { - argstr = XCALLOC (MTYPE_TMP, strlen (str) + strlen (" additive") + 1); - strcpy (argstr, str); - strcpy (argstr + strlen (str), " additive"); - ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "community", argstr); - XFREE (MTYPE_TMP, argstr); - } - else - ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "community", str); - - community_free (com); - - return ret; + int idx_aa_nn = 2; + int i; + int first = 0; + int additive = 0; + struct buffer *b; + struct community *com = NULL; + char *str; + char *argstr; + int ret; + + b = buffer_new(1024); + + for (i = idx_aa_nn; i < argc; i++) { + if (strncmp(argv[i]->arg, "additive", strlen(argv[i]->arg)) + == 0) { + additive = 1; + continue; + } + + if (first) + buffer_putc(b, ' '); + else + first = 1; + + if (strncmp(argv[i]->arg, "internet", strlen(argv[i]->arg)) + == 0) { + buffer_putstr(b, "internet"); + continue; + } + if (strncmp(argv[i]->arg, "local-AS", strlen(argv[i]->arg)) + == 0) { + buffer_putstr(b, "local-AS"); + continue; + } + if (strncmp(argv[i]->arg, "no-a", strlen("no-a")) == 0 + && strncmp(argv[i]->arg, "no-advertise", + strlen(argv[i]->arg)) + == 0) { + buffer_putstr(b, "no-advertise"); + continue; + } + if (strncmp(argv[i]->arg, "no-e", strlen("no-e")) == 0 + && strncmp(argv[i]->arg, "no-export", strlen(argv[i]->arg)) + == 0) { + buffer_putstr(b, "no-export"); + continue; + } + buffer_putstr(b, argv[i]->arg); + } + buffer_putc(b, '\0'); + + /* Fetch result string then compile it to communities attribute. */ + str = buffer_getstr(b); + buffer_free(b); + + if (str) { + com = community_str2com(str); + XFREE(MTYPE_TMP, str); + } + + /* Can't compile user input into communities attribute. */ + if (!com) { + vty_out(vty, "%% Malformed communities attribute\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Set communites attribute string. */ + str = community_str(com); + + if (additive) { + argstr = XCALLOC(MTYPE_TMP, + strlen(str) + strlen(" additive") + 1); + strcpy(argstr, str); + strcpy(argstr + strlen(str), " additive"); + ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "community", argstr); + XFREE(MTYPE_TMP, argstr); + } else + ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "community", str); + + community_free(com); + + return ret; } DEFUN (set_community_none, @@ -3902,8 +3650,8 @@ DEFUN (set_community_none, "BGP community attribute\n" "No community attribute\n") { - return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "community", - "none"); + return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "community", "none"); } DEFUN (no_set_community, @@ -3914,12 +3662,11 @@ DEFUN (no_set_community, "BGP community attribute\n" COMMUNITY_VAL_STR) { - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "community", NULL); + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "community", NULL); } - DEFUN (set_community_delete, set_community_delete_cmd, "set comm-list <(1-99)|(100-500)|WORD> delete", @@ -3930,17 +3677,19 @@ DEFUN (set_community_delete, "Community-list name\n" "Delete matching communities\n") { - int idx_comm_list = 2; - char *str; + int idx_comm_list = 2; + char *str; - str = XCALLOC (MTYPE_TMP, strlen (argv[idx_comm_list]->arg) + strlen (" delete") + 1); - strcpy (str, argv[idx_comm_list]->arg); - strcpy (str + strlen (argv[idx_comm_list]->arg), " delete"); + str = XCALLOC(MTYPE_TMP, + strlen(argv[idx_comm_list]->arg) + strlen(" delete") + 1); + strcpy(str, argv[idx_comm_list]->arg); + strcpy(str + strlen(argv[idx_comm_list]->arg), " delete"); - generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "comm-list", str); + generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "comm-list", + str); - XFREE (MTYPE_TMP, str); - return CMD_SUCCESS; + XFREE(MTYPE_TMP, str); + return CMD_SUCCESS; } DEFUN (no_set_community_delete, @@ -3954,8 +3703,8 @@ DEFUN (no_set_community_delete, "Community-list name\n" "Delete matching communities\n") { - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "comm-list", NULL); + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "comm-list", NULL); } DEFUN (set_lcommunity, @@ -3965,14 +3714,15 @@ DEFUN (set_lcommunity, "BGP large community attribute\n" "Large Community number in aa:bb:cc format or additive\n") { - int ret; - char *str; + int ret; + char *str; - str = argv_concat (argv, argc, 2); - ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "large-community", str); - XFREE (MTYPE_TMP, str); + str = argv_concat(argv, argc, 2); + ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "large-community", str); + XFREE(MTYPE_TMP, str); - return ret; + return ret; } DEFUN (set_lcommunity_none, @@ -3982,8 +3732,8 @@ DEFUN (set_lcommunity_none, "BGP large community attribute\n" "No large community attribute\n") { - return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "large-community", "none"); + return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "large-community", "none"); } DEFUN (no_set_lcommunity, @@ -3994,8 +3744,8 @@ DEFUN (no_set_lcommunity, "BGP large community attribute\n" "No community attribute\n") { - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "large-community", NULL); + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "large-community", NULL); } DEFUN (no_set_lcommunity1, @@ -4006,8 +3756,8 @@ DEFUN (no_set_lcommunity1, "BGP large community attribute\n" "Large community in AA:BB:CC... format or additive\n") { - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "large-community", NULL); + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "large-community", NULL); } DEFUN (set_lcommunity_delete, @@ -4020,17 +3770,17 @@ DEFUN (set_lcommunity_delete, "Large Community-list name\n" "Delete matching large communities\n") { - char *str; + char *str; - str = XCALLOC (MTYPE_TMP, strlen (argv[2]->arg) + strlen (" delete") + 1); - strcpy (str, argv[2]->arg); - strcpy (str + strlen (argv[2]->arg), " delete"); + str = XCALLOC(MTYPE_TMP, strlen(argv[2]->arg) + strlen(" delete") + 1); + strcpy(str, argv[2]->arg); + strcpy(str + strlen(argv[2]->arg), " delete"); - generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "large-comm-list", str); + generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "large-comm-list", str); - XFREE (MTYPE_TMP, str); - return CMD_SUCCESS; + XFREE(MTYPE_TMP, str); + return CMD_SUCCESS; } DEFUN (no_set_lcommunity_delete, @@ -4044,8 +3794,8 @@ DEFUN (no_set_lcommunity_delete, "Large Community-list name\n" "Delete matching large communities\n") { - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "large-comm-list", NULL); + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "large-comm-list", NULL); } DEFUN (set_ecommunity_rt, @@ -4056,16 +3806,16 @@ DEFUN (set_ecommunity_rt, "Route Target extended community\n" "VPN extended community\n") { - int idx_asn_nn = 3; - int ret; - char *str; + int idx_asn_nn = 3; + int ret; + char *str; - str = argv_concat (argv, argc, idx_asn_nn); - ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "extcommunity rt", str); - XFREE (MTYPE_TMP, str); + str = argv_concat(argv, argc, idx_asn_nn); + ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "extcommunity rt", str); + XFREE(MTYPE_TMP, str); - return ret; + return ret; } DEFUN (no_set_ecommunity_rt, @@ -4077,8 +3827,8 @@ DEFUN (no_set_ecommunity_rt, "Route Target extended community\n" "VPN extended community\n") { - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "extcommunity rt", NULL); + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "extcommunity rt", NULL); } @@ -4090,15 +3840,15 @@ DEFUN (set_ecommunity_soo, "Site-of-Origin extended community\n" "VPN extended community\n") { - int idx_asn_nn = 3; - int ret; - char *str; + int idx_asn_nn = 3; + int ret; + char *str; - str = argv_concat (argv, argc, idx_asn_nn); - ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "extcommunity soo", str); - XFREE (MTYPE_TMP, str); - return ret; + str = argv_concat(argv, argc, idx_asn_nn); + ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "extcommunity soo", str); + XFREE(MTYPE_TMP, str); + return ret; } @@ -4111,8 +3861,8 @@ DEFUN (no_set_ecommunity_soo, "Site-of-Origin extended community\n" "VPN extended community\n") { - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "extcommunity soo", NULL); + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "extcommunity soo", NULL); } @@ -4125,19 +3875,19 @@ DEFUN (set_origin, "local IGP\n" "unknown heritage\n") { - int idx_origin = 2; - if (strncmp (argv[idx_origin]->arg, "igp", 2) == 0) - return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "origin", - "igp"); - if (strncmp (argv[idx_origin]->arg, "egp", 1) == 0) - return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "origin", - "egp"); - if (strncmp (argv[idx_origin]->arg, "incomplete", 2) == 0) - return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), "origin", - "incomplete"); + int idx_origin = 2; + if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0) + return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "origin", "igp"); + if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0) + return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "origin", "egp"); + if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0) + return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "origin", "incomplete"); - vty_out (vty, "%% Invalid set origin type\n"); - return CMD_WARNING_CONFIG_FAILED; + vty_out(vty, "%% Invalid set origin type\n"); + return CMD_WARNING_CONFIG_FAILED; } @@ -4151,8 +3901,8 @@ DEFUN (no_set_origin, "local IGP\n" "unknown heritage\n") { - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), "origin", - NULL); + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "origin", NULL); } @@ -4162,8 +3912,8 @@ DEFUN (set_atomic_aggregate, SET_STR "BGP atomic aggregate attribute\n" ) { - return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "atomic-aggregate", NULL); + return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "atomic-aggregate", NULL); } DEFUN (no_set_atomic_aggregate, @@ -4173,8 +3923,8 @@ DEFUN (no_set_atomic_aggregate, SET_STR "BGP atomic aggregate attribute\n" ) { - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "atomic-aggregate", NULL); + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "atomic-aggregate", NULL); } DEFUN (set_aggregator_as, @@ -4186,30 +3936,30 @@ DEFUN (set_aggregator_as, "AS number\n" "IP address of aggregator\n") { - int idx_number = 3; - int idx_ipv4 = 4; - int ret; - struct in_addr address; - char *argstr; + int idx_number = 3; + int idx_ipv4 = 4; + int ret; + struct in_addr address; + char *argstr; - ret = inet_aton (argv[idx_ipv4]->arg, &address); - if (ret == 0) - { - vty_out (vty, "Aggregator IP address is invalid\n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = inet_aton(argv[idx_ipv4]->arg, &address); + if (ret == 0) { + vty_out(vty, "Aggregator IP address is invalid\n"); + return CMD_WARNING_CONFIG_FAILED; + } - argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, - strlen (argv[idx_number]->arg) + strlen (argv[idx_ipv4]->arg) + 2); + argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, + strlen(argv[idx_number]->arg) + + strlen(argv[idx_ipv4]->arg) + 2); - sprintf (argstr, "%s %s", argv[idx_number]->arg, argv[idx_ipv4]->arg); + sprintf(argstr, "%s %s", argv[idx_number]->arg, argv[idx_ipv4]->arg); - ret = generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "aggregator as", argstr); + ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "aggregator as", argstr); - XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr); + XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr); - return ret; + return ret; } @@ -4223,34 +3973,34 @@ DEFUN (no_set_aggregator_as, "AS number\n" "IP address of aggregator\n") { - int idx_asn = 4; - int idx_ip = 5; - int ret; - struct in_addr address; - char *argstr; + int idx_asn = 4; + int idx_ip = 5; + int ret; + struct in_addr address; + char *argstr; - if (argc <= idx_asn) - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "aggregator as", NULL); + if (argc <= idx_asn) + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "aggregator as", NULL); - ret = inet_aton (argv[idx_ip]->arg, &address); - if (ret == 0) - { - vty_out (vty, "Aggregator IP address is invalid\n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = inet_aton(argv[idx_ip]->arg, &address); + if (ret == 0) { + vty_out(vty, "Aggregator IP address is invalid\n"); + return CMD_WARNING_CONFIG_FAILED; + } - argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, - strlen (argv[idx_asn]->arg) + strlen (argv[idx_ip]->arg) + 2); + argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, + strlen(argv[idx_asn]->arg) + strlen(argv[idx_ip]->arg) + + 2); - sprintf (argstr, "%s %s", argv[idx_asn]->arg, argv[idx_ip]->arg); + sprintf(argstr, "%s %s", argv[idx_asn]->arg, argv[idx_ip]->arg); - ret = generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "aggregator as", argstr); + ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "aggregator as", argstr); - XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr); + XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr); - return ret; + return ret; } DEFUN (match_ipv6_next_hop, @@ -4261,9 +4011,9 @@ DEFUN (match_ipv6_next_hop, "Match IPv6 next-hop address of route\n" "IPv6 address of next hop\n") { - int idx_ipv6 = 3; - return bgp_route_match_add (vty, "ipv6 next-hop", argv[idx_ipv6]->arg, - RMAP_EVENT_MATCH_ADDED); + int idx_ipv6 = 3; + return bgp_route_match_add(vty, "ipv6 next-hop", argv[idx_ipv6]->arg, + RMAP_EVENT_MATCH_ADDED); } DEFUN (no_match_ipv6_next_hop, @@ -4275,9 +4025,9 @@ DEFUN (no_match_ipv6_next_hop, "Match IPv6 next-hop address of route\n" "IPv6 address of next hop\n") { - int idx_ipv6 = 4; - return bgp_route_match_delete (vty, "ipv6 next-hop", argv[idx_ipv6]->arg, - RMAP_EVENT_MATCH_DELETED); + int idx_ipv6 = 4; + return bgp_route_match_delete(vty, "ipv6 next-hop", argv[idx_ipv6]->arg, + RMAP_EVENT_MATCH_DELETED); } @@ -4289,8 +4039,8 @@ DEFUN (set_ipv6_nexthop_peer, "Next hop address\n" "Use peer address (for BGP only)\n") { - return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "ipv6 next-hop peer-address", NULL); + return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "ipv6 next-hop peer-address", NULL); } DEFUN (no_set_ipv6_nexthop_peer, @@ -4302,8 +4052,8 @@ DEFUN (no_set_ipv6_nexthop_peer, "IPv6 next-hop address\n" "Use peer address (for BGP only)\n") { - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "ipv6 next-hop peer-address", NULL); + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "ipv6 next-hop peer-address", NULL); } DEFUN (set_ipv6_nexthop_prefer_global, @@ -4314,8 +4064,9 @@ DEFUN (set_ipv6_nexthop_prefer_global, "IPv6 next-hop address\n" "Prefer global over link-local if both exist\n") { - return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "ipv6 next-hop prefer-global", NULL);; + return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "ipv6 next-hop prefer-global", NULL); + ; } DEFUN (no_set_ipv6_nexthop_prefer_global, @@ -4327,8 +4078,8 @@ DEFUN (no_set_ipv6_nexthop_prefer_global, "IPv6 next-hop address\n" "Prefer global over link-local if both exist\n") { - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "ipv6 next-hop prefer-global", NULL); + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "ipv6 next-hop prefer-global", NULL); } DEFUN (set_ipv6_nexthop_global, @@ -4340,27 +4091,23 @@ DEFUN (set_ipv6_nexthop_global, "IPv6 global address\n" "IPv6 address of next hop\n") { - int idx_ipv6 = 4; - struct in6_addr addr; - int ret; + int idx_ipv6 = 4; + struct in6_addr addr; + int ret; - ret = inet_pton (AF_INET6, argv[idx_ipv6]->arg, &addr); - if (!ret) - { - vty_out (vty, "%% Malformed nexthop address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (IN6_IS_ADDR_UNSPECIFIED(&addr) || - IN6_IS_ADDR_LOOPBACK(&addr) || - IN6_IS_ADDR_MULTICAST(&addr) || - IN6_IS_ADDR_LINKLOCAL(&addr)) - { - vty_out (vty, "%% Invalid global nexthop address\n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = inet_pton(AF_INET6, argv[idx_ipv6]->arg, &addr); + if (!ret) { + vty_out(vty, "%% Malformed nexthop address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (IN6_IS_ADDR_UNSPECIFIED(&addr) || IN6_IS_ADDR_LOOPBACK(&addr) + || IN6_IS_ADDR_MULTICAST(&addr) || IN6_IS_ADDR_LINKLOCAL(&addr)) { + vty_out(vty, "%% Invalid global nexthop address\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "ipv6 next-hop global", argv[idx_ipv6]->arg); + return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "ipv6 next-hop global", argv[idx_ipv6]->arg); } @@ -4374,12 +4121,12 @@ DEFUN (no_set_ipv6_nexthop_global, "IPv6 global address\n" "IPv6 address of next hop\n") { - int idx_ipv6 = 5; - if (argc <= idx_ipv6) - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "ipv6 next-hop global", NULL); - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "ipv6 next-hop global", argv[idx_ipv6]->arg); + int idx_ipv6 = 5; + if (argc <= idx_ipv6) + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "ipv6 next-hop global", NULL); + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "ipv6 next-hop global", argv[idx_ipv6]->arg); } #ifdef KEEP_OLD_VPN_COMMANDS @@ -4394,20 +4141,21 @@ DEFUN (set_vpn_nexthop, "VPN next-hop address\n" "IPv6 address of next hop\n") { - int idx_ip = 3; - afi_t afi; - int idx = 0; - - if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi)) - { - if (afi == AFI_IP) - return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "ipv4 vpn next-hop", argv[idx_ip]->arg); - else - return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "ipv6 vpn next-hop", argv[idx_ip]->arg); - } - return CMD_SUCCESS; + int idx_ip = 3; + afi_t afi; + int idx = 0; + + if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) { + if (afi == AFI_IP) + return generic_set_add( + vty, VTY_GET_CONTEXT(route_map_index), + "ipv4 vpn next-hop", argv[idx_ip]->arg); + else + return generic_set_add( + vty, VTY_GET_CONTEXT(route_map_index), + "ipv6 vpn next-hop", argv[idx_ip]->arg); + } + return CMD_SUCCESS; } DEFUN (no_set_vpn_nexthop, @@ -4422,25 +4170,26 @@ DEFUN (no_set_vpn_nexthop, "VPN next-hop address\n" "IPv6 address of next hop\n") { - int idx_ip = 4; - char *arg; - afi_t afi; - int idx = 0; - - if (argc <= idx_ip) - arg = NULL; - else - arg = argv[idx_ip]->arg; - if (argv_find_and_parse_vpnvx (argv, argc, &idx, &afi)) - { - if (afi == AFI_IP) - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "ipv4 vpn next-hop", arg); - else - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "ipv6 vpn next-hop", argv[idx_ip]->arg); - } - return CMD_SUCCESS; + int idx_ip = 4; + char *arg; + afi_t afi; + int idx = 0; + + if (argc <= idx_ip) + arg = NULL; + else + arg = argv[idx_ip]->arg; + if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) { + if (afi == AFI_IP) + return generic_set_delete( + vty, VTY_GET_CONTEXT(route_map_index), + "ipv4 vpn next-hop", arg); + else + return generic_set_delete( + vty, VTY_GET_CONTEXT(route_map_index), + "ipv6 vpn next-hop", argv[idx_ip]->arg); + } + return CMD_SUCCESS; } #endif /* KEEP_OLD_VPN_COMMANDS */ @@ -4455,20 +4204,21 @@ DEFUN (set_ipx_vpn_nexthop, "IP address of next hop\n" "IPv6 address of next hop\n") { - int idx_ip = 4; - afi_t afi; - int idx = 0; - - if (argv_find_and_parse_afi (argv, argc, &idx, &afi)) - { - if (afi == AFI_IP) - return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "ipv4 vpn next-hop", argv[idx_ip]->arg); - else - return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "ipv6 vpn next-hop", argv[idx_ip]->arg); - } - return CMD_SUCCESS; + int idx_ip = 4; + afi_t afi; + int idx = 0; + + if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) { + if (afi == AFI_IP) + return generic_set_add( + vty, VTY_GET_CONTEXT(route_map_index), + "ipv4 vpn next-hop", argv[idx_ip]->arg); + else + return generic_set_add( + vty, VTY_GET_CONTEXT(route_map_index), + "ipv6 vpn next-hop", argv[idx_ip]->arg); + } + return CMD_SUCCESS; } DEFUN (no_set_ipx_vpn_nexthop, @@ -4483,25 +4233,26 @@ DEFUN (no_set_ipx_vpn_nexthop, "IP address of next hop\n" "IPv6 address of next hop\n") { - int idx_ip = 5; - char *arg; - afi_t afi; - int idx = 0; - - if (argc <= idx_ip) - arg = NULL; - else - arg = argv[idx_ip]->arg; - if (argv_find_and_parse_afi (argv, argc, &idx, &afi)) - { - if (afi == AFI_IP) - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "ipv4 vpn next-hop", arg); - else - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "ipv6 vpn next-hop", arg); - } - return CMD_SUCCESS; + int idx_ip = 5; + char *arg; + afi_t afi; + int idx = 0; + + if (argc <= idx_ip) + arg = NULL; + else + arg = argv[idx_ip]->arg; + if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) { + if (afi == AFI_IP) + return generic_set_delete( + vty, VTY_GET_CONTEXT(route_map_index), + "ipv4 vpn next-hop", arg); + else + return generic_set_delete( + vty, VTY_GET_CONTEXT(route_map_index), + "ipv6 vpn next-hop", arg); + } + return CMD_SUCCESS; } DEFUN (set_originator_id, @@ -4511,9 +4262,9 @@ DEFUN (set_originator_id, "BGP originator ID attribute\n" "IP address of originator\n") { - int idx_ipv4 = 2; - return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "originator-id", argv[idx_ipv4]->arg); + int idx_ipv4 = 2; + return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "originator-id", argv[idx_ipv4]->arg); } @@ -4525,196 +4276,194 @@ DEFUN (no_set_originator_id, "BGP originator ID attribute\n" "IP address of originator\n") { - int idx = 0; - char *arg = argv_find (argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL; + int idx = 0; + char *arg = + argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL; - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "originator-id", arg); + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "originator-id", arg); } /* Initialization of route map. */ -void -bgp_route_map_init (void) -{ - route_map_init (); - - route_map_add_hook (bgp_route_map_add); - route_map_delete_hook (bgp_route_map_delete); - route_map_event_hook (bgp_route_map_event); - - route_map_match_interface_hook (generic_match_add); - route_map_no_match_interface_hook (generic_match_delete); - - route_map_match_ip_address_hook (generic_match_add); - route_map_no_match_ip_address_hook (generic_match_delete); - - route_map_match_ip_address_prefix_list_hook (generic_match_add); - route_map_no_match_ip_address_prefix_list_hook (generic_match_delete); - - route_map_match_ip_next_hop_hook (generic_match_add); - route_map_no_match_ip_next_hop_hook (generic_match_delete); - - route_map_match_ip_next_hop_prefix_list_hook (generic_match_add); - route_map_no_match_ip_next_hop_prefix_list_hook (generic_match_delete); - - route_map_match_ipv6_address_hook (generic_match_add); - route_map_no_match_ipv6_address_hook (generic_match_delete); - - route_map_match_ipv6_address_prefix_list_hook (generic_match_add); - route_map_no_match_ipv6_address_prefix_list_hook (generic_match_delete); - - route_map_match_metric_hook (generic_match_add); - route_map_no_match_metric_hook (generic_match_delete); - - route_map_match_tag_hook (generic_match_add); - route_map_no_match_tag_hook (generic_match_delete); - - route_map_set_ip_nexthop_hook (generic_set_add); - route_map_no_set_ip_nexthop_hook (generic_set_delete); - - route_map_set_ipv6_nexthop_local_hook (generic_set_add); - route_map_no_set_ipv6_nexthop_local_hook (generic_set_delete); - - route_map_set_metric_hook (generic_set_add); - route_map_no_set_metric_hook (generic_set_delete); - - route_map_set_tag_hook (generic_set_add); - route_map_no_set_tag_hook (generic_set_delete); - - route_map_install_match (&route_match_peer_cmd); - route_map_install_match (&route_match_local_pref_cmd); - route_map_install_match (&route_match_ip_address_cmd); - route_map_install_match (&route_match_ip_next_hop_cmd); - route_map_install_match (&route_match_ip_route_source_cmd); - route_map_install_match (&route_match_ip_address_prefix_list_cmd); - route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd); - route_map_install_match (&route_match_ip_route_source_prefix_list_cmd); - route_map_install_match (&route_match_aspath_cmd); - route_map_install_match (&route_match_community_cmd); - route_map_install_match (&route_match_lcommunity_cmd); - route_map_install_match (&route_match_ecommunity_cmd); - route_map_install_match (&route_match_local_pref_cmd); - route_map_install_match (&route_match_metric_cmd); - route_map_install_match (&route_match_origin_cmd); - route_map_install_match (&route_match_probability_cmd); - route_map_install_match (&route_match_interface_cmd); - route_map_install_match (&route_match_tag_cmd); - - route_map_install_set (&route_set_ip_nexthop_cmd); - route_map_install_set (&route_set_local_pref_cmd); - route_map_install_set (&route_set_weight_cmd); - route_map_install_set (&route_set_label_index_cmd); - route_map_install_set (&route_set_metric_cmd); - route_map_install_set (&route_set_aspath_prepend_cmd); - route_map_install_set (&route_set_aspath_exclude_cmd); - route_map_install_set (&route_set_origin_cmd); - route_map_install_set (&route_set_atomic_aggregate_cmd); - route_map_install_set (&route_set_aggregator_as_cmd); - route_map_install_set (&route_set_community_cmd); - route_map_install_set (&route_set_community_delete_cmd); - route_map_install_set (&route_set_lcommunity_cmd); - route_map_install_set (&route_set_lcommunity_delete_cmd); - route_map_install_set (&route_set_vpnv4_nexthop_cmd); - route_map_install_set (&route_set_vpnv6_nexthop_cmd); - route_map_install_set (&route_set_originator_id_cmd); - route_map_install_set (&route_set_ecommunity_rt_cmd); - route_map_install_set (&route_set_ecommunity_soo_cmd); - route_map_install_set (&route_set_tag_cmd); - route_map_install_set (&route_set_label_index_cmd); - - install_element (RMAP_NODE, &match_peer_cmd); - install_element (RMAP_NODE, &match_peer_local_cmd); - install_element (RMAP_NODE, &no_match_peer_cmd); - install_element (RMAP_NODE, &match_ip_route_source_cmd); - install_element (RMAP_NODE, &no_match_ip_route_source_cmd); - install_element (RMAP_NODE, &match_ip_route_source_prefix_list_cmd); - install_element (RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd); - - install_element (RMAP_NODE, &match_aspath_cmd); - install_element (RMAP_NODE, &no_match_aspath_cmd); - install_element (RMAP_NODE, &match_local_pref_cmd); - install_element (RMAP_NODE, &no_match_local_pref_cmd); - install_element (RMAP_NODE, &match_community_cmd); - install_element (RMAP_NODE, &no_match_community_cmd); - install_element (RMAP_NODE, &match_lcommunity_cmd); - install_element (RMAP_NODE, &no_match_lcommunity_cmd); - install_element (RMAP_NODE, &match_ecommunity_cmd); - install_element (RMAP_NODE, &no_match_ecommunity_cmd); - install_element (RMAP_NODE, &match_origin_cmd); - install_element (RMAP_NODE, &no_match_origin_cmd); - install_element (RMAP_NODE, &match_probability_cmd); - install_element (RMAP_NODE, &no_match_probability_cmd); - - install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd); - install_element (RMAP_NODE, &set_ip_nexthop_unchanged_cmd); - install_element (RMAP_NODE, &set_local_pref_cmd); - install_element (RMAP_NODE, &no_set_local_pref_cmd); - install_element (RMAP_NODE, &set_weight_cmd); - install_element (RMAP_NODE, &set_label_index_cmd); - install_element (RMAP_NODE, &no_set_weight_cmd); - install_element (RMAP_NODE, &no_set_label_index_cmd); - install_element (RMAP_NODE, &set_aspath_prepend_asn_cmd); - install_element (RMAP_NODE, &set_aspath_prepend_lastas_cmd); - install_element (RMAP_NODE, &set_aspath_exclude_cmd); - install_element (RMAP_NODE, &no_set_aspath_prepend_cmd); - install_element (RMAP_NODE, &no_set_aspath_exclude_cmd); - install_element (RMAP_NODE, &set_origin_cmd); - install_element (RMAP_NODE, &no_set_origin_cmd); - install_element (RMAP_NODE, &set_atomic_aggregate_cmd); - install_element (RMAP_NODE, &no_set_atomic_aggregate_cmd); - install_element (RMAP_NODE, &set_aggregator_as_cmd); - install_element (RMAP_NODE, &no_set_aggregator_as_cmd); - install_element (RMAP_NODE, &set_community_cmd); - install_element (RMAP_NODE, &set_community_none_cmd); - install_element (RMAP_NODE, &no_set_community_cmd); - install_element (RMAP_NODE, &set_community_delete_cmd); - install_element (RMAP_NODE, &no_set_community_delete_cmd); - install_element (RMAP_NODE, &set_lcommunity_cmd); - install_element (RMAP_NODE, &set_lcommunity_none_cmd); - install_element (RMAP_NODE, &no_set_lcommunity_cmd); - install_element (RMAP_NODE, &no_set_lcommunity1_cmd); - install_element (RMAP_NODE, &set_lcommunity_delete_cmd); - install_element (RMAP_NODE, &no_set_lcommunity_delete_cmd); - install_element (RMAP_NODE, &set_ecommunity_rt_cmd); - install_element (RMAP_NODE, &no_set_ecommunity_rt_cmd); - install_element (RMAP_NODE, &set_ecommunity_soo_cmd); - install_element (RMAP_NODE, &no_set_ecommunity_soo_cmd); +void bgp_route_map_init(void) +{ + route_map_init(); + + route_map_add_hook(bgp_route_map_add); + route_map_delete_hook(bgp_route_map_delete); + route_map_event_hook(bgp_route_map_event); + + route_map_match_interface_hook(generic_match_add); + route_map_no_match_interface_hook(generic_match_delete); + + route_map_match_ip_address_hook(generic_match_add); + route_map_no_match_ip_address_hook(generic_match_delete); + + route_map_match_ip_address_prefix_list_hook(generic_match_add); + route_map_no_match_ip_address_prefix_list_hook(generic_match_delete); + + route_map_match_ip_next_hop_hook(generic_match_add); + route_map_no_match_ip_next_hop_hook(generic_match_delete); + + route_map_match_ip_next_hop_prefix_list_hook(generic_match_add); + route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete); + + route_map_match_ipv6_address_hook(generic_match_add); + route_map_no_match_ipv6_address_hook(generic_match_delete); + + route_map_match_ipv6_address_prefix_list_hook(generic_match_add); + route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete); + + route_map_match_metric_hook(generic_match_add); + route_map_no_match_metric_hook(generic_match_delete); + + route_map_match_tag_hook(generic_match_add); + route_map_no_match_tag_hook(generic_match_delete); + + route_map_set_ip_nexthop_hook(generic_set_add); + route_map_no_set_ip_nexthop_hook(generic_set_delete); + + route_map_set_ipv6_nexthop_local_hook(generic_set_add); + route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete); + + route_map_set_metric_hook(generic_set_add); + route_map_no_set_metric_hook(generic_set_delete); + + route_map_set_tag_hook(generic_set_add); + route_map_no_set_tag_hook(generic_set_delete); + + route_map_install_match(&route_match_peer_cmd); + route_map_install_match(&route_match_local_pref_cmd); + route_map_install_match(&route_match_ip_address_cmd); + route_map_install_match(&route_match_ip_next_hop_cmd); + route_map_install_match(&route_match_ip_route_source_cmd); + route_map_install_match(&route_match_ip_address_prefix_list_cmd); + route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd); + route_map_install_match(&route_match_ip_route_source_prefix_list_cmd); + route_map_install_match(&route_match_aspath_cmd); + route_map_install_match(&route_match_community_cmd); + route_map_install_match(&route_match_lcommunity_cmd); + route_map_install_match(&route_match_ecommunity_cmd); + route_map_install_match(&route_match_local_pref_cmd); + route_map_install_match(&route_match_metric_cmd); + route_map_install_match(&route_match_origin_cmd); + route_map_install_match(&route_match_probability_cmd); + route_map_install_match(&route_match_interface_cmd); + route_map_install_match(&route_match_tag_cmd); + + route_map_install_set(&route_set_ip_nexthop_cmd); + route_map_install_set(&route_set_local_pref_cmd); + route_map_install_set(&route_set_weight_cmd); + route_map_install_set(&route_set_label_index_cmd); + route_map_install_set(&route_set_metric_cmd); + route_map_install_set(&route_set_aspath_prepend_cmd); + route_map_install_set(&route_set_aspath_exclude_cmd); + route_map_install_set(&route_set_origin_cmd); + route_map_install_set(&route_set_atomic_aggregate_cmd); + route_map_install_set(&route_set_aggregator_as_cmd); + route_map_install_set(&route_set_community_cmd); + route_map_install_set(&route_set_community_delete_cmd); + route_map_install_set(&route_set_lcommunity_cmd); + route_map_install_set(&route_set_lcommunity_delete_cmd); + route_map_install_set(&route_set_vpnv4_nexthop_cmd); + route_map_install_set(&route_set_vpnv6_nexthop_cmd); + route_map_install_set(&route_set_originator_id_cmd); + route_map_install_set(&route_set_ecommunity_rt_cmd); + route_map_install_set(&route_set_ecommunity_soo_cmd); + route_map_install_set(&route_set_tag_cmd); + route_map_install_set(&route_set_label_index_cmd); + + install_element(RMAP_NODE, &match_peer_cmd); + install_element(RMAP_NODE, &match_peer_local_cmd); + install_element(RMAP_NODE, &no_match_peer_cmd); + install_element(RMAP_NODE, &match_ip_route_source_cmd); + install_element(RMAP_NODE, &no_match_ip_route_source_cmd); + install_element(RMAP_NODE, &match_ip_route_source_prefix_list_cmd); + install_element(RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd); + + install_element(RMAP_NODE, &match_aspath_cmd); + install_element(RMAP_NODE, &no_match_aspath_cmd); + install_element(RMAP_NODE, &match_local_pref_cmd); + install_element(RMAP_NODE, &no_match_local_pref_cmd); + install_element(RMAP_NODE, &match_community_cmd); + install_element(RMAP_NODE, &no_match_community_cmd); + install_element(RMAP_NODE, &match_lcommunity_cmd); + install_element(RMAP_NODE, &no_match_lcommunity_cmd); + install_element(RMAP_NODE, &match_ecommunity_cmd); + install_element(RMAP_NODE, &no_match_ecommunity_cmd); + install_element(RMAP_NODE, &match_origin_cmd); + install_element(RMAP_NODE, &no_match_origin_cmd); + install_element(RMAP_NODE, &match_probability_cmd); + install_element(RMAP_NODE, &no_match_probability_cmd); + + install_element(RMAP_NODE, &set_ip_nexthop_peer_cmd); + install_element(RMAP_NODE, &set_ip_nexthop_unchanged_cmd); + install_element(RMAP_NODE, &set_local_pref_cmd); + install_element(RMAP_NODE, &no_set_local_pref_cmd); + install_element(RMAP_NODE, &set_weight_cmd); + install_element(RMAP_NODE, &set_label_index_cmd); + install_element(RMAP_NODE, &no_set_weight_cmd); + install_element(RMAP_NODE, &no_set_label_index_cmd); + install_element(RMAP_NODE, &set_aspath_prepend_asn_cmd); + install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd); + install_element(RMAP_NODE, &set_aspath_exclude_cmd); + install_element(RMAP_NODE, &no_set_aspath_prepend_cmd); + install_element(RMAP_NODE, &no_set_aspath_exclude_cmd); + install_element(RMAP_NODE, &set_origin_cmd); + install_element(RMAP_NODE, &no_set_origin_cmd); + install_element(RMAP_NODE, &set_atomic_aggregate_cmd); + install_element(RMAP_NODE, &no_set_atomic_aggregate_cmd); + install_element(RMAP_NODE, &set_aggregator_as_cmd); + install_element(RMAP_NODE, &no_set_aggregator_as_cmd); + install_element(RMAP_NODE, &set_community_cmd); + install_element(RMAP_NODE, &set_community_none_cmd); + install_element(RMAP_NODE, &no_set_community_cmd); + install_element(RMAP_NODE, &set_community_delete_cmd); + install_element(RMAP_NODE, &no_set_community_delete_cmd); + install_element(RMAP_NODE, &set_lcommunity_cmd); + install_element(RMAP_NODE, &set_lcommunity_none_cmd); + install_element(RMAP_NODE, &no_set_lcommunity_cmd); + install_element(RMAP_NODE, &no_set_lcommunity1_cmd); + install_element(RMAP_NODE, &set_lcommunity_delete_cmd); + install_element(RMAP_NODE, &no_set_lcommunity_delete_cmd); + install_element(RMAP_NODE, &set_ecommunity_rt_cmd); + install_element(RMAP_NODE, &no_set_ecommunity_rt_cmd); + install_element(RMAP_NODE, &set_ecommunity_soo_cmd); + install_element(RMAP_NODE, &no_set_ecommunity_soo_cmd); #ifdef KEEP_OLD_VPN_COMMANDS - install_element (RMAP_NODE, &set_vpn_nexthop_cmd); - install_element (RMAP_NODE, &no_set_vpn_nexthop_cmd); + install_element(RMAP_NODE, &set_vpn_nexthop_cmd); + install_element(RMAP_NODE, &no_set_vpn_nexthop_cmd); #endif /* KEEP_OLD_VPN_COMMANDS */ - install_element (RMAP_NODE, &set_ipx_vpn_nexthop_cmd); - install_element (RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd); - install_element (RMAP_NODE, &set_originator_id_cmd); - install_element (RMAP_NODE, &no_set_originator_id_cmd); - - route_map_install_match (&route_match_ipv6_address_cmd); - route_map_install_match (&route_match_ipv6_next_hop_cmd); - route_map_install_match (&route_match_ipv6_address_prefix_list_cmd); - route_map_install_set (&route_set_ipv6_nexthop_global_cmd); - route_map_install_set (&route_set_ipv6_nexthop_prefer_global_cmd); - route_map_install_set (&route_set_ipv6_nexthop_local_cmd); - route_map_install_set (&route_set_ipv6_nexthop_peer_cmd); - - install_element (RMAP_NODE, &match_ipv6_next_hop_cmd); - install_element (RMAP_NODE, &no_match_ipv6_next_hop_cmd); - install_element (RMAP_NODE, &set_ipv6_nexthop_global_cmd); - install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_cmd); - install_element (RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd); - install_element (RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd); - install_element (RMAP_NODE, &set_ipv6_nexthop_peer_cmd); - install_element (RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd); -} - -void -bgp_route_map_terminate (void) -{ - /* ToDo: Cleanup all the used memory */ - - route_map_add_hook (NULL); - route_map_delete_hook (NULL); - route_map_event_hook (NULL); - route_map_finish(); - + install_element(RMAP_NODE, &set_ipx_vpn_nexthop_cmd); + install_element(RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd); + install_element(RMAP_NODE, &set_originator_id_cmd); + install_element(RMAP_NODE, &no_set_originator_id_cmd); + + route_map_install_match(&route_match_ipv6_address_cmd); + route_map_install_match(&route_match_ipv6_next_hop_cmd); + route_map_install_match(&route_match_ipv6_address_prefix_list_cmd); + route_map_install_set(&route_set_ipv6_nexthop_global_cmd); + route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd); + route_map_install_set(&route_set_ipv6_nexthop_local_cmd); + route_map_install_set(&route_set_ipv6_nexthop_peer_cmd); + + install_element(RMAP_NODE, &match_ipv6_next_hop_cmd); + install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd); + install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd); + install_element(RMAP_NODE, &no_set_ipv6_nexthop_global_cmd); + install_element(RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd); + install_element(RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd); + install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd); + install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd); +} + +void bgp_route_map_terminate(void) +{ + /* ToDo: Cleanup all the used memory */ + + route_map_add_hook(NULL); + route_map_delete_hook(NULL); + route_map_event_hook(NULL); + route_map_finish(); } diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c index c1a6ad589..8a9d61f30 100644 --- a/bgpd/bgp_snmp.c +++ b/bgpd/bgp_snmp.c @@ -118,785 +118,828 @@ SNMP_LOCAL_VARIABLES /* BGP-MIB instances. */ -static oid bgp_oid [] = { BGP4MIB }; -static oid bgp_trap_oid [] = { BGP4MIB, 0 }; +static oid bgp_oid[] = {BGP4MIB}; +static oid bgp_trap_oid[] = {BGP4MIB, 0}; /* IP address 0.0.0.0. */ -static struct in_addr bgp_empty_addr = { .s_addr = 0 }; +static struct in_addr bgp_empty_addr = {.s_addr = 0}; /* Hook functions. */ -static u_char *bgpVersion (struct variable *, oid [], size_t *, int, - size_t *, WriteMethod **); -static u_char *bgpLocalAs (struct variable *, oid [], size_t *, - int, size_t *, WriteMethod **); -static u_char *bgpPeerTable (struct variable *, oid [], size_t *, - int, size_t *, WriteMethod **); -static u_char *bgpRcvdPathAttrTable (struct variable *, oid [], size_t *, - int, size_t *, WriteMethod **); -static u_char *bgpIdentifier (struct variable *, oid [], size_t *, - int, size_t *, WriteMethod **); -static u_char *bgp4PathAttrTable (struct variable *, oid [], size_t *, - int, size_t *, WriteMethod **); +static u_char *bgpVersion(struct variable *, oid[], size_t *, int, size_t *, + WriteMethod **); +static u_char *bgpLocalAs(struct variable *, oid[], size_t *, int, size_t *, + WriteMethod **); +static u_char *bgpPeerTable(struct variable *, oid[], size_t *, int, size_t *, + WriteMethod **); +static u_char *bgpRcvdPathAttrTable(struct variable *, oid[], size_t *, int, + size_t *, WriteMethod **); +static u_char *bgpIdentifier(struct variable *, oid[], size_t *, int, size_t *, + WriteMethod **); +static u_char *bgp4PathAttrTable(struct variable *, oid[], size_t *, int, + size_t *, WriteMethod **); /* static u_char *bgpTraps (); */ -static struct variable bgp_variables[] = -{ - /* BGP version. */ - {BGPVERSION, OCTET_STRING, RONLY, bgpVersion, - 1, {1}}, - /* BGP local AS. */ - {BGPLOCALAS, INTEGER, RONLY, bgpLocalAs, - 1, {2}}, - /* BGP peer table. */ - {BGPPEERIDENTIFIER, IPADDRESS, RONLY, bgpPeerTable, - 3, {3, 1, 1}}, - {BGPPEERSTATE, INTEGER, RONLY, bgpPeerTable, - 3, {3, 1, 2}}, - {BGPPEERADMINSTATUS, INTEGER, RWRITE, bgpPeerTable, - 3, {3, 1, 3}}, - {BGPPEERNEGOTIATEDVERSION, INTEGER32, RONLY, bgpPeerTable, - 3, {3, 1, 4}}, - {BGPPEERLOCALADDR, IPADDRESS, RONLY, bgpPeerTable, - 3, {3, 1, 5}}, - {BGPPEERLOCALPORT, INTEGER, RONLY, bgpPeerTable, - 3, {3, 1, 6}}, - {BGPPEERREMOTEADDR, IPADDRESS, RONLY, bgpPeerTable, - 3, {3, 1, 7}}, - {BGPPEERREMOTEPORT, INTEGER, RONLY, bgpPeerTable, - 3, {3, 1, 8}}, - {BGPPEERREMOTEAS, INTEGER, RONLY, bgpPeerTable, - 3, {3, 1, 9}}, - {BGPPEERINUPDATES, COUNTER32, RONLY, bgpPeerTable, - 3, {3, 1, 10}}, - {BGPPEEROUTUPDATES, COUNTER32, RONLY, bgpPeerTable, - 3, {3, 1, 11}}, - {BGPPEERINTOTALMESSAGES, COUNTER32, RONLY, bgpPeerTable, - 3, {3, 1, 12}}, - {BGPPEEROUTTOTALMESSAGES, COUNTER32, RONLY, bgpPeerTable, - 3, {3, 1, 13}}, - {BGPPEERLASTERROR, OCTET_STRING, RONLY, bgpPeerTable, - 3, {3, 1, 14}}, - {BGPPEERFSMESTABLISHEDTRANSITIONS, COUNTER32, RONLY, bgpPeerTable, - 3, {3, 1, 15}}, - {BGPPEERFSMESTABLISHEDTIME, GAUGE32, RONLY, bgpPeerTable, - 3, {3, 1, 16}}, - {BGPPEERCONNECTRETRYINTERVAL, INTEGER, RWRITE, bgpPeerTable, - 3, {3, 1, 17}}, - {BGPPEERHOLDTIME, INTEGER, RONLY, bgpPeerTable, - 3, {3, 1, 18}}, - {BGPPEERKEEPALIVE, INTEGER, RONLY, bgpPeerTable, - 3, {3, 1, 19}}, - {BGPPEERHOLDTIMECONFIGURED, INTEGER, RWRITE, bgpPeerTable, - 3, {3, 1, 20}}, - {BGPPEERKEEPALIVECONFIGURED, INTEGER, RWRITE, bgpPeerTable, - 3, {3, 1, 21}}, - {BGPPEERMINROUTEADVERTISEMENTINTERVAL, INTEGER, RWRITE, bgpPeerTable, - 3, {3, 1, 23}}, - {BGPPEERINUPDATEELAPSEDTIME, GAUGE32, RONLY, bgpPeerTable, - 3, {3, 1, 24}}, - /* BGP identifier. */ - {BGPIDENTIFIER, IPADDRESS, RONLY, bgpIdentifier, - 1, {4}}, - /* BGP received path attribute table. */ - {BGPPATHATTRPEER, IPADDRESS, RONLY, bgpRcvdPathAttrTable, - 3, {5, 1, 1}}, - {BGPPATHATTRDESTNETWORK, IPADDRESS, RONLY, bgpRcvdPathAttrTable, - 3, {5, 1, 2}}, - {BGPPATHATTRORIGIN, INTEGER, RONLY, bgpRcvdPathAttrTable, - 3, {5, 1, 3}}, - {BGPPATHATTRASPATH, OCTET_STRING, RONLY, bgpRcvdPathAttrTable, - 3, {5, 1, 4}}, - {BGPPATHATTRNEXTHOP, IPADDRESS, RONLY, bgpRcvdPathAttrTable, - 3, {5, 1, 5}}, - {BGPPATHATTRINTERASMETRIC, INTEGER32, RONLY, bgpRcvdPathAttrTable, - 3, {5, 1, 6}}, - /* BGP-4 received path attribute table. */ - {BGP4PATHATTRPEER, IPADDRESS, RONLY, bgp4PathAttrTable, - 3, {6, 1, 1}}, - {BGP4PATHATTRIPADDRPREFIXLEN, INTEGER, RONLY, bgp4PathAttrTable, - 3, {6, 1, 2}}, - {BGP4PATHATTRIPADDRPREFIX, IPADDRESS, RONLY, bgp4PathAttrTable, - 3, {6, 1, 3}}, - {BGP4PATHATTRORIGIN, INTEGER, RONLY, bgp4PathAttrTable, - 3, {6, 1, 4}}, - {BGP4PATHATTRASPATHSEGMENT, OCTET_STRING, RONLY, bgp4PathAttrTable, - 3, {6, 1, 5}}, - {BGP4PATHATTRNEXTHOP, IPADDRESS, RONLY, bgp4PathAttrTable, - 3, {6, 1, 6}}, - {BGP4PATHATTRMULTIEXITDISC, INTEGER, RONLY, bgp4PathAttrTable, - 3, {6, 1, 7}}, - {BGP4PATHATTRLOCALPREF, INTEGER, RONLY, bgp4PathAttrTable, - 3, {6, 1, 8}}, - {BGP4PATHATTRATOMICAGGREGATE, INTEGER, RONLY, bgp4PathAttrTable, - 3, {6, 1, 9}}, - {BGP4PATHATTRAGGREGATORAS, INTEGER, RONLY, bgp4PathAttrTable, - 3, {6, 1, 10}}, - {BGP4PATHATTRAGGREGATORADDR, IPADDRESS, RONLY, bgp4PathAttrTable, - 3, {6, 1, 11}}, - {BGP4PATHATTRCALCLOCALPREF, INTEGER, RONLY, bgp4PathAttrTable, - 3, {6, 1, 12}}, - {BGP4PATHATTRBEST, INTEGER, RONLY, bgp4PathAttrTable, - 3, {6, 1, 13}}, - {BGP4PATHATTRUNKNOWN, OCTET_STRING, RONLY, bgp4PathAttrTable, - 3, {6, 1, 14}}, +static struct variable bgp_variables[] = { + /* BGP version. */ + {BGPVERSION, OCTET_STRING, RONLY, bgpVersion, 1, {1}}, + /* BGP local AS. */ + {BGPLOCALAS, INTEGER, RONLY, bgpLocalAs, 1, {2}}, + /* BGP peer table. */ + {BGPPEERIDENTIFIER, IPADDRESS, RONLY, bgpPeerTable, 3, {3, 1, 1}}, + {BGPPEERSTATE, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 2}}, + {BGPPEERADMINSTATUS, INTEGER, RWRITE, bgpPeerTable, 3, {3, 1, 3}}, + {BGPPEERNEGOTIATEDVERSION, + INTEGER32, + RONLY, + bgpPeerTable, + 3, + {3, 1, 4}}, + {BGPPEERLOCALADDR, IPADDRESS, RONLY, bgpPeerTable, 3, {3, 1, 5}}, + {BGPPEERLOCALPORT, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 6}}, + {BGPPEERREMOTEADDR, IPADDRESS, RONLY, bgpPeerTable, 3, {3, 1, 7}}, + {BGPPEERREMOTEPORT, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 8}}, + {BGPPEERREMOTEAS, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 9}}, + {BGPPEERINUPDATES, COUNTER32, RONLY, bgpPeerTable, 3, {3, 1, 10}}, + {BGPPEEROUTUPDATES, COUNTER32, RONLY, bgpPeerTable, 3, {3, 1, 11}}, + {BGPPEERINTOTALMESSAGES, COUNTER32, RONLY, bgpPeerTable, 3, {3, 1, 12}}, + {BGPPEEROUTTOTALMESSAGES, + COUNTER32, + RONLY, + bgpPeerTable, + 3, + {3, 1, 13}}, + {BGPPEERLASTERROR, OCTET_STRING, RONLY, bgpPeerTable, 3, {3, 1, 14}}, + {BGPPEERFSMESTABLISHEDTRANSITIONS, + COUNTER32, + RONLY, + bgpPeerTable, + 3, + {3, 1, 15}}, + {BGPPEERFSMESTABLISHEDTIME, + GAUGE32, + RONLY, + bgpPeerTable, + 3, + {3, 1, 16}}, + {BGPPEERCONNECTRETRYINTERVAL, + INTEGER, + RWRITE, + bgpPeerTable, + 3, + {3, 1, 17}}, + {BGPPEERHOLDTIME, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 18}}, + {BGPPEERKEEPALIVE, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 19}}, + {BGPPEERHOLDTIMECONFIGURED, + INTEGER, + RWRITE, + bgpPeerTable, + 3, + {3, 1, 20}}, + {BGPPEERKEEPALIVECONFIGURED, + INTEGER, + RWRITE, + bgpPeerTable, + 3, + {3, 1, 21}}, + {BGPPEERMINROUTEADVERTISEMENTINTERVAL, + INTEGER, + RWRITE, + bgpPeerTable, + 3, + {3, 1, 23}}, + {BGPPEERINUPDATEELAPSEDTIME, + GAUGE32, + RONLY, + bgpPeerTable, + 3, + {3, 1, 24}}, + /* BGP identifier. */ + {BGPIDENTIFIER, IPADDRESS, RONLY, bgpIdentifier, 1, {4}}, + /* BGP received path attribute table. */ + {BGPPATHATTRPEER, IPADDRESS, RONLY, bgpRcvdPathAttrTable, 3, {5, 1, 1}}, + {BGPPATHATTRDESTNETWORK, + IPADDRESS, + RONLY, + bgpRcvdPathAttrTable, + 3, + {5, 1, 2}}, + {BGPPATHATTRORIGIN, INTEGER, RONLY, bgpRcvdPathAttrTable, 3, {5, 1, 3}}, + {BGPPATHATTRASPATH, + OCTET_STRING, + RONLY, + bgpRcvdPathAttrTable, + 3, + {5, 1, 4}}, + {BGPPATHATTRNEXTHOP, + IPADDRESS, + RONLY, + bgpRcvdPathAttrTable, + 3, + {5, 1, 5}}, + {BGPPATHATTRINTERASMETRIC, + INTEGER32, + RONLY, + bgpRcvdPathAttrTable, + 3, + {5, 1, 6}}, + /* BGP-4 received path attribute table. */ + {BGP4PATHATTRPEER, IPADDRESS, RONLY, bgp4PathAttrTable, 3, {6, 1, 1}}, + {BGP4PATHATTRIPADDRPREFIXLEN, + INTEGER, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 2}}, + {BGP4PATHATTRIPADDRPREFIX, + IPADDRESS, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 3}}, + {BGP4PATHATTRORIGIN, INTEGER, RONLY, bgp4PathAttrTable, 3, {6, 1, 4}}, + {BGP4PATHATTRASPATHSEGMENT, + OCTET_STRING, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 5}}, + {BGP4PATHATTRNEXTHOP, + IPADDRESS, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 6}}, + {BGP4PATHATTRMULTIEXITDISC, + INTEGER, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 7}}, + {BGP4PATHATTRLOCALPREF, + INTEGER, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 8}}, + {BGP4PATHATTRATOMICAGGREGATE, + INTEGER, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 9}}, + {BGP4PATHATTRAGGREGATORAS, + INTEGER, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 10}}, + {BGP4PATHATTRAGGREGATORADDR, + IPADDRESS, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 11}}, + {BGP4PATHATTRCALCLOCALPREF, + INTEGER, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 12}}, + {BGP4PATHATTRBEST, INTEGER, RONLY, bgp4PathAttrTable, 3, {6, 1, 13}}, + {BGP4PATHATTRUNKNOWN, + OCTET_STRING, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 14}}, }; -static u_char * -bgpVersion (struct variable *v, oid name[], size_t *length, int exact, - size_t *var_len, WriteMethod **write_method) +static u_char *bgpVersion(struct variable *v, oid name[], size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - static u_char version; + static u_char version; - if (smux_header_generic(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; + if (smux_header_generic(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; - /* Retrun BGP version. Zebra bgpd only support version 4. */ - version = (0x80 >> (BGP_VERSION_4 - 1)); + /* Retrun BGP version. Zebra bgpd only support version 4. */ + version = (0x80 >> (BGP_VERSION_4 - 1)); - /* Return octet string length 1. */ - *var_len = 1; - return (u_char *)&version; + /* Return octet string length 1. */ + *var_len = 1; + return (u_char *)&version; } -static u_char * -bgpLocalAs (struct variable *v, oid name[], size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *bgpLocalAs(struct variable *v, oid name[], size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - struct bgp *bgp; + struct bgp *bgp; - if (smux_header_generic(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; + if (smux_header_generic(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; - /* Get BGP structure. */ - bgp = bgp_get_default (); - if (! bgp) - return NULL; + /* Get BGP structure. */ + bgp = bgp_get_default(); + if (!bgp) + return NULL; - return SNMP_INTEGER (bgp->as); + return SNMP_INTEGER(bgp->as); } -static struct peer * -peer_lookup_addr_ipv4 (struct in_addr *src) +static struct peer *peer_lookup_addr_ipv4(struct in_addr *src) { - struct bgp *bgp; - struct peer *peer; - struct listnode *node; - struct in_addr addr; - int ret; - - bgp = bgp_get_default (); - if (! bgp) - return NULL; - - for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer)) - { - ret = inet_pton (AF_INET, peer->host, &addr); - if (ret > 0) - { - if (IPV4_ADDR_SAME (&addr, src)) - return peer; + struct bgp *bgp; + struct peer *peer; + struct listnode *node; + struct in_addr addr; + int ret; + + bgp = bgp_get_default(); + if (!bgp) + return NULL; + + for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) { + ret = inet_pton(AF_INET, peer->host, &addr); + if (ret > 0) { + if (IPV4_ADDR_SAME(&addr, src)) + return peer; + } } - } - return NULL; + return NULL; } -static struct peer * -bgp_peer_lookup_next (struct in_addr *src) +static struct peer *bgp_peer_lookup_next(struct in_addr *src) { - struct bgp *bgp; - struct peer *peer; - struct listnode *node; - struct in_addr *p; - union sockunion su; - int ret; - - sockunion_init (&su); - - bgp = bgp_get_default (); - if (! bgp) - return NULL; - - for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer)) - { - ret = inet_pton (AF_INET, peer->host, &su.sin.sin_addr); - if (ret > 0) - { - p = &su.sin.sin_addr; - - if (ntohl (p->s_addr) > ntohl (src->s_addr)) - { - src->s_addr = p->s_addr; - return peer; - } + struct bgp *bgp; + struct peer *peer; + struct listnode *node; + struct in_addr *p; + union sockunion su; + int ret; + + sockunion_init(&su); + + bgp = bgp_get_default(); + if (!bgp) + return NULL; + + for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) { + ret = inet_pton(AF_INET, peer->host, &su.sin.sin_addr); + if (ret > 0) { + p = &su.sin.sin_addr; + + if (ntohl(p->s_addr) > ntohl(src->s_addr)) { + src->s_addr = p->s_addr; + return peer; + } + } } - } - return NULL; + return NULL; } /* 1.3.6.1.2.1.15.3.1.x = 10 */ #define PEERTAB_NAMELEN 10 -static struct peer * -bgpPeerTable_lookup (struct variable *v, oid name[], size_t *length, - struct in_addr *addr, int exact) +static struct peer *bgpPeerTable_lookup(struct variable *v, oid name[], + size_t *length, struct in_addr *addr, + int exact) { - struct peer *peer = NULL; - size_t namelen = v ? v->namelen : PEERTAB_NAMELEN; - int len; - - if (exact) - { - /* Check the length. */ - if (*length - namelen != sizeof (struct in_addr)) - return NULL; + struct peer *peer = NULL; + size_t namelen = v ? v->namelen : PEERTAB_NAMELEN; + int len; - oid2in_addr (name + namelen, IN_ADDR_SIZE, addr); - - peer = peer_lookup_addr_ipv4 (addr); - return peer; - } - else - { - len = *length - namelen; - if (len > 4) len = 4; - - oid2in_addr (name + namelen, len, addr); - - peer = bgp_peer_lookup_next (addr); - - if (peer == NULL) - return NULL; + if (exact) { + /* Check the length. */ + if (*length - namelen != sizeof(struct in_addr)) + return NULL; + + oid2in_addr(name + namelen, IN_ADDR_SIZE, addr); + + peer = peer_lookup_addr_ipv4(addr); + return peer; + } else { + len = *length - namelen; + if (len > 4) + len = 4; - oid_copy_addr (name + namelen, addr, sizeof (struct in_addr)); - *length = sizeof (struct in_addr) + namelen; + oid2in_addr(name + namelen, len, addr); - return peer; - } - return NULL; + peer = bgp_peer_lookup_next(addr); + + if (peer == NULL) + return NULL; + + oid_copy_addr(name + namelen, addr, sizeof(struct in_addr)); + *length = sizeof(struct in_addr) + namelen; + + return peer; + } + return NULL; } /* BGP write methods. */ -static int -write_bgpPeerTable (int action, u_char *var_val, - u_char var_val_type, size_t var_val_len, - u_char *statP, oid *name, size_t length) +static int write_bgpPeerTable(int action, u_char *var_val, u_char var_val_type, + size_t var_val_len, u_char *statP, oid *name, + size_t length) { - struct in_addr addr; - struct peer *peer; - long intval; + struct in_addr addr; + struct peer *peer; + long intval; - if (var_val_type != ASN_INTEGER) - { - return SNMP_ERR_WRONGTYPE; - } - if (var_val_len != sizeof (long)) - { - return SNMP_ERR_WRONGLENGTH; - } + if (var_val_type != ASN_INTEGER) { + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len != sizeof(long)) { + return SNMP_ERR_WRONGLENGTH; + } - intval = *(long *)var_val; + intval = *(long *)var_val; - memset (&addr, 0, sizeof (struct in_addr)); + memset(&addr, 0, sizeof(struct in_addr)); - peer = bgpPeerTable_lookup (NULL, name, &length, &addr, 1); - if (! peer) - return SNMP_ERR_NOSUCHNAME; + peer = bgpPeerTable_lookup(NULL, name, &length, &addr, 1); + if (!peer) + return SNMP_ERR_NOSUCHNAME; - if (action != SNMP_MSG_INTERNAL_SET_COMMIT) - return SNMP_ERR_NOERROR; + if (action != SNMP_MSG_INTERNAL_SET_COMMIT) + return SNMP_ERR_NOERROR; - zlog_info ("%s: SNMP write .%ld = %ld", - peer->host, (long)name[PEERTAB_NAMELEN - 1], intval); + zlog_info("%s: SNMP write .%ld = %ld", peer->host, + (long)name[PEERTAB_NAMELEN - 1], intval); - switch (name[PEERTAB_NAMELEN - 1]) - { - case BGPPEERADMINSTATUS: + switch (name[PEERTAB_NAMELEN - 1]) { + case BGPPEERADMINSTATUS: #define BGP_PeerAdmin_stop 1 #define BGP_PeerAdmin_start 2 - /* When the peer is established, */ - if (intval == BGP_PeerAdmin_stop) - BGP_EVENT_ADD (peer, BGP_Stop); - else if (intval == BGP_PeerAdmin_start) - ; /* Do nothing. */ - else - return SNMP_ERR_NOSUCHNAME; - break; - case BGPPEERCONNECTRETRYINTERVAL: - SET_FLAG (peer->config, PEER_CONFIG_CONNECT); - peer->connect = intval; - peer->v_connect = intval; - break; - case BGPPEERHOLDTIMECONFIGURED: - SET_FLAG (peer->config, PEER_CONFIG_TIMER); - peer->holdtime = intval; - peer->v_holdtime = intval; - break; - case BGPPEERKEEPALIVECONFIGURED: - SET_FLAG (peer->config, PEER_CONFIG_TIMER); - peer->keepalive = intval; - peer->v_keepalive = intval; - break; - case BGPPEERMINROUTEADVERTISEMENTINTERVAL: - peer->v_routeadv = intval; - break; - } - return SNMP_ERR_NOERROR; + /* When the peer is established, */ + if (intval == BGP_PeerAdmin_stop) + BGP_EVENT_ADD(peer, BGP_Stop); + else if (intval == BGP_PeerAdmin_start) + ; /* Do nothing. */ + else + return SNMP_ERR_NOSUCHNAME; + break; + case BGPPEERCONNECTRETRYINTERVAL: + SET_FLAG(peer->config, PEER_CONFIG_CONNECT); + peer->connect = intval; + peer->v_connect = intval; + break; + case BGPPEERHOLDTIMECONFIGURED: + SET_FLAG(peer->config, PEER_CONFIG_TIMER); + peer->holdtime = intval; + peer->v_holdtime = intval; + break; + case BGPPEERKEEPALIVECONFIGURED: + SET_FLAG(peer->config, PEER_CONFIG_TIMER); + peer->keepalive = intval; + peer->v_keepalive = intval; + break; + case BGPPEERMINROUTEADVERTISEMENTINTERVAL: + peer->v_routeadv = intval; + break; + } + return SNMP_ERR_NOERROR; } -static u_char * -bgpPeerTable (struct variable *v, oid name[], size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *bgpPeerTable(struct variable *v, oid name[], size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - static struct in_addr addr; - struct peer *peer; - - if (smux_header_table(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - memset (&addr, 0, sizeof (struct in_addr)); - - peer = bgpPeerTable_lookup (v, name, length, &addr, exact); - if (! peer) - return NULL; - - switch (v->magic) - { - case BGPPEERIDENTIFIER: - return SNMP_IPADDRESS (peer->remote_id); - break; - case BGPPEERSTATE: - return SNMP_INTEGER (peer->status); - break; - case BGPPEERADMINSTATUS: - *write_method = write_bgpPeerTable; + static struct in_addr addr; + struct peer *peer; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + memset(&addr, 0, sizeof(struct in_addr)); + + peer = bgpPeerTable_lookup(v, name, length, &addr, exact); + if (!peer) + return NULL; + + switch (v->magic) { + case BGPPEERIDENTIFIER: + return SNMP_IPADDRESS(peer->remote_id); + break; + case BGPPEERSTATE: + return SNMP_INTEGER(peer->status); + break; + case BGPPEERADMINSTATUS: + *write_method = write_bgpPeerTable; #define BGP_PeerAdmin_stop 1 #define BGP_PeerAdmin_start 2 - if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN)) - return SNMP_INTEGER (BGP_PeerAdmin_stop); - else - return SNMP_INTEGER (BGP_PeerAdmin_start); - break; - case BGPPEERNEGOTIATEDVERSION: - return SNMP_INTEGER (BGP_VERSION_4); - break; - case BGPPEERLOCALADDR: - if (peer->su_local) - return SNMP_IPADDRESS (peer->su_local->sin.sin_addr); - else - return SNMP_IPADDRESS (bgp_empty_addr); - break; - case BGPPEERLOCALPORT: - if (peer->su_local) - return SNMP_INTEGER (ntohs (peer->su_local->sin.sin_port)); - else - return SNMP_INTEGER (0); - break; - case BGPPEERREMOTEADDR: - if (peer->su_remote) - return SNMP_IPADDRESS (peer->su_remote->sin.sin_addr); - else - return SNMP_IPADDRESS (bgp_empty_addr); - break; - case BGPPEERREMOTEPORT: - if (peer->su_remote) - return SNMP_INTEGER (ntohs (peer->su_remote->sin.sin_port)); - else - return SNMP_INTEGER (0); - break; - case BGPPEERREMOTEAS: - return SNMP_INTEGER (peer->as); - break; - case BGPPEERINUPDATES: - return SNMP_INTEGER (peer->update_in); - break; - case BGPPEEROUTUPDATES: - return SNMP_INTEGER (peer->update_out); - break; - case BGPPEERINTOTALMESSAGES: - return SNMP_INTEGER (peer->open_in + peer->update_in - + peer->keepalive_in + peer->notify_in - + peer->refresh_in + peer->dynamic_cap_in); - break; - case BGPPEEROUTTOTALMESSAGES: - return SNMP_INTEGER (peer->open_out + peer->update_out - + peer->keepalive_out + peer->notify_out - + peer->refresh_out + peer->dynamic_cap_out); - break; - case BGPPEERLASTERROR: - { - static u_char lasterror[2]; - lasterror[0] = peer->notify.code; - lasterror[1] = peer->notify.subcode; - *var_len = 2; - return (u_char *)&lasterror; - } - break; - case BGPPEERFSMESTABLISHEDTRANSITIONS: - return SNMP_INTEGER (peer->established); - break; - case BGPPEERFSMESTABLISHEDTIME: - if (peer->uptime == 0) - return SNMP_INTEGER (0); - else - return SNMP_INTEGER (bgp_clock () - peer->uptime); - break; - case BGPPEERCONNECTRETRYINTERVAL: - *write_method = write_bgpPeerTable; - return SNMP_INTEGER (peer->v_connect); - break; - case BGPPEERHOLDTIME: - return SNMP_INTEGER (peer->v_holdtime); - break; - case BGPPEERKEEPALIVE: - return SNMP_INTEGER (peer->v_keepalive); - break; - case BGPPEERHOLDTIMECONFIGURED: - *write_method = write_bgpPeerTable; - if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)) - return SNMP_INTEGER (peer->holdtime); - else - return SNMP_INTEGER (peer->v_holdtime); - break; - case BGPPEERKEEPALIVECONFIGURED: - *write_method = write_bgpPeerTable; - if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)) - return SNMP_INTEGER (peer->keepalive); - else - return SNMP_INTEGER (peer->v_keepalive); - break; - case BGPPEERMINROUTEADVERTISEMENTINTERVAL: - *write_method = write_bgpPeerTable; - return SNMP_INTEGER (peer->v_routeadv); - break; - case BGPPEERINUPDATEELAPSEDTIME: - if (peer->update_time == 0) - return SNMP_INTEGER (0); - else - return SNMP_INTEGER (bgp_clock () - peer->update_time); - break; - default: - return NULL; - break; - } - return NULL; + if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) + return SNMP_INTEGER(BGP_PeerAdmin_stop); + else + return SNMP_INTEGER(BGP_PeerAdmin_start); + break; + case BGPPEERNEGOTIATEDVERSION: + return SNMP_INTEGER(BGP_VERSION_4); + break; + case BGPPEERLOCALADDR: + if (peer->su_local) + return SNMP_IPADDRESS(peer->su_local->sin.sin_addr); + else + return SNMP_IPADDRESS(bgp_empty_addr); + break; + case BGPPEERLOCALPORT: + if (peer->su_local) + return SNMP_INTEGER( + ntohs(peer->su_local->sin.sin_port)); + else + return SNMP_INTEGER(0); + break; + case BGPPEERREMOTEADDR: + if (peer->su_remote) + return SNMP_IPADDRESS(peer->su_remote->sin.sin_addr); + else + return SNMP_IPADDRESS(bgp_empty_addr); + break; + case BGPPEERREMOTEPORT: + if (peer->su_remote) + return SNMP_INTEGER( + ntohs(peer->su_remote->sin.sin_port)); + else + return SNMP_INTEGER(0); + break; + case BGPPEERREMOTEAS: + return SNMP_INTEGER(peer->as); + break; + case BGPPEERINUPDATES: + return SNMP_INTEGER(peer->update_in); + break; + case BGPPEEROUTUPDATES: + return SNMP_INTEGER(peer->update_out); + break; + case BGPPEERINTOTALMESSAGES: + return SNMP_INTEGER(peer->open_in + peer->update_in + + peer->keepalive_in + peer->notify_in + + peer->refresh_in + peer->dynamic_cap_in); + break; + case BGPPEEROUTTOTALMESSAGES: + return SNMP_INTEGER(peer->open_out + peer->update_out + + peer->keepalive_out + peer->notify_out + + peer->refresh_out + + peer->dynamic_cap_out); + break; + case BGPPEERLASTERROR: { + static u_char lasterror[2]; + lasterror[0] = peer->notify.code; + lasterror[1] = peer->notify.subcode; + *var_len = 2; + return (u_char *)&lasterror; + } break; + case BGPPEERFSMESTABLISHEDTRANSITIONS: + return SNMP_INTEGER(peer->established); + break; + case BGPPEERFSMESTABLISHEDTIME: + if (peer->uptime == 0) + return SNMP_INTEGER(0); + else + return SNMP_INTEGER(bgp_clock() - peer->uptime); + break; + case BGPPEERCONNECTRETRYINTERVAL: + *write_method = write_bgpPeerTable; + return SNMP_INTEGER(peer->v_connect); + break; + case BGPPEERHOLDTIME: + return SNMP_INTEGER(peer->v_holdtime); + break; + case BGPPEERKEEPALIVE: + return SNMP_INTEGER(peer->v_keepalive); + break; + case BGPPEERHOLDTIMECONFIGURED: + *write_method = write_bgpPeerTable; + if (CHECK_FLAG(peer->config, PEER_CONFIG_TIMER)) + return SNMP_INTEGER(peer->holdtime); + else + return SNMP_INTEGER(peer->v_holdtime); + break; + case BGPPEERKEEPALIVECONFIGURED: + *write_method = write_bgpPeerTable; + if (CHECK_FLAG(peer->config, PEER_CONFIG_TIMER)) + return SNMP_INTEGER(peer->keepalive); + else + return SNMP_INTEGER(peer->v_keepalive); + break; + case BGPPEERMINROUTEADVERTISEMENTINTERVAL: + *write_method = write_bgpPeerTable; + return SNMP_INTEGER(peer->v_routeadv); + break; + case BGPPEERINUPDATEELAPSEDTIME: + if (peer->update_time == 0) + return SNMP_INTEGER(0); + else + return SNMP_INTEGER(bgp_clock() - peer->update_time); + break; + default: + return NULL; + break; + } + return NULL; } -static u_char * -bgpIdentifier (struct variable *v, oid name[], size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *bgpIdentifier(struct variable *v, oid name[], size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - struct bgp *bgp; + struct bgp *bgp; - if (smux_header_generic(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; + if (smux_header_generic(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; - bgp = bgp_get_default (); - if (!bgp) - return NULL; + bgp = bgp_get_default(); + if (!bgp) + return NULL; - return SNMP_IPADDRESS (bgp->router_id); + return SNMP_IPADDRESS(bgp->router_id); } -static u_char * -bgpRcvdPathAttrTable (struct variable *v, oid name[], size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *bgpRcvdPathAttrTable(struct variable *v, oid name[], + size_t *length, int exact, size_t *var_len, + WriteMethod **write_method) { - /* Received Path Attribute Table. This table contains, one entry - per path to a network, path attributes received from all peers - running BGP version 3 or less. This table is obsolete, having - been replaced in functionality with the bgp4PathAttrTable. */ - return NULL; + /* Received Path Attribute Table. This table contains, one entry + per path to a network, path attributes received from all peers + running BGP version 3 or less. This table is obsolete, having + been replaced in functionality with the bgp4PathAttrTable. */ + return NULL; } -static struct bgp_info * -bgp4PathAttrLookup (struct variable *v, oid name[], size_t *length, - struct bgp *bgp, struct prefix_ipv4 *addr, int exact) +static struct bgp_info *bgp4PathAttrLookup(struct variable *v, oid name[], + size_t *length, struct bgp *bgp, + struct prefix_ipv4 *addr, int exact) { - oid *offset; - int offsetlen; - struct bgp_info *binfo; - struct bgp_info *min; - struct bgp_node *rn; - union sockunion su; - unsigned int len; - struct in_addr paddr; - - sockunion_init (&su); - -#define BGP_PATHATTR_ENTRY_OFFSET \ - (IN_ADDR_SIZE + 1 + IN_ADDR_SIZE) - - if (exact) - { - if (*length - v->namelen != BGP_PATHATTR_ENTRY_OFFSET) - return NULL; - - /* Set OID offset for prefix. */ - offset = name + v->namelen; - oid2in_addr (offset, IN_ADDR_SIZE, &addr->prefix); - offset += IN_ADDR_SIZE; - - /* Prefix length. */ - addr->prefixlen = *offset; - offset++; - - /* Peer address. */ - su.sin.sin_family = AF_INET; - oid2in_addr (offset, IN_ADDR_SIZE, &su.sin.sin_addr); - - /* Lookup node. */ - rn = bgp_node_lookup (bgp->rib[AFI_IP][SAFI_UNICAST], - (struct prefix *) addr); - if (rn) - { - bgp_unlock_node (rn); - - for (binfo = rn->info; binfo; binfo = binfo->next) - if (sockunion_same (&binfo->peer->su, &su)) - return binfo; - } - } - else - { - offset = name + v->namelen; - offsetlen = *length - v->namelen; - len = offsetlen; - - if (offsetlen == 0) - rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_UNICAST]); - else - { - if (len > IN_ADDR_SIZE) - len = IN_ADDR_SIZE; - - oid2in_addr (offset, len, &addr->prefix); - - offset += IN_ADDR_SIZE; - offsetlen -= IN_ADDR_SIZE; - - if (offsetlen > 0) - addr->prefixlen = *offset; - else - addr->prefixlen = len * 8; - - rn = bgp_node_get (bgp->rib[AFI_IP][SAFI_UNICAST], - (struct prefix *) addr); - - offset++; - offsetlen--; - } - - if (offsetlen > 0) - { - len = offsetlen; - if (len > IN_ADDR_SIZE) - len = IN_ADDR_SIZE; - - oid2in_addr (offset, len, &paddr); - } - else - paddr.s_addr = 0; + oid *offset; + int offsetlen; + struct bgp_info *binfo; + struct bgp_info *min; + struct bgp_node *rn; + union sockunion su; + unsigned int len; + struct in_addr paddr; + + sockunion_init(&su); + +#define BGP_PATHATTR_ENTRY_OFFSET (IN_ADDR_SIZE + 1 + IN_ADDR_SIZE) + + if (exact) { + if (*length - v->namelen != BGP_PATHATTR_ENTRY_OFFSET) + return NULL; + + /* Set OID offset for prefix. */ + offset = name + v->namelen; + oid2in_addr(offset, IN_ADDR_SIZE, &addr->prefix); + offset += IN_ADDR_SIZE; + + /* Prefix length. */ + addr->prefixlen = *offset; + offset++; + + /* Peer address. */ + su.sin.sin_family = AF_INET; + oid2in_addr(offset, IN_ADDR_SIZE, &su.sin.sin_addr); + + /* Lookup node. */ + rn = bgp_node_lookup(bgp->rib[AFI_IP][SAFI_UNICAST], + (struct prefix *)addr); + if (rn) { + bgp_unlock_node(rn); + + for (binfo = rn->info; binfo; binfo = binfo->next) + if (sockunion_same(&binfo->peer->su, &su)) + return binfo; + } + } else { + offset = name + v->namelen; + offsetlen = *length - v->namelen; + len = offsetlen; - if (! rn) - return NULL; + if (offsetlen == 0) + rn = bgp_table_top(bgp->rib[AFI_IP][SAFI_UNICAST]); + else { + if (len > IN_ADDR_SIZE) + len = IN_ADDR_SIZE; - do - { - min = NULL; - - for (binfo = rn->info; binfo; binfo = binfo->next) - { - if (binfo->peer->su.sin.sin_family == AF_INET - && ntohl (paddr.s_addr) - < ntohl (binfo->peer->su.sin.sin_addr.s_addr)) - { - if (min) - { - if (ntohl (binfo->peer->su.sin.sin_addr.s_addr) - < ntohl (min->peer->su.sin.sin_addr.s_addr)) - min = binfo; - } - else - min = binfo; - } - } + oid2in_addr(offset, len, &addr->prefix); - if (min) - { - *length = v->namelen + BGP_PATHATTR_ENTRY_OFFSET; + offset += IN_ADDR_SIZE; + offsetlen -= IN_ADDR_SIZE; - offset = name + v->namelen; - oid_copy_addr (offset, &rn->p.u.prefix4, IN_ADDR_SIZE); - offset += IN_ADDR_SIZE; - *offset = rn->p.prefixlen; - offset++; - oid_copy_addr (offset, &min->peer->su.sin.sin_addr, - IN_ADDR_SIZE); - addr->prefix = rn->p.u.prefix4; - addr->prefixlen = rn->p.prefixlen; + if (offsetlen > 0) + addr->prefixlen = *offset; + else + addr->prefixlen = len * 8; - bgp_unlock_node (rn); + rn = bgp_node_get(bgp->rib[AFI_IP][SAFI_UNICAST], + (struct prefix *)addr); - return min; - } + offset++; + offsetlen--; + } - paddr.s_addr = 0; + if (offsetlen > 0) { + len = offsetlen; + if (len > IN_ADDR_SIZE) + len = IN_ADDR_SIZE; + + oid2in_addr(offset, len, &paddr); + } else + paddr.s_addr = 0; + + if (!rn) + return NULL; + + do { + min = NULL; + + for (binfo = rn->info; binfo; binfo = binfo->next) { + if (binfo->peer->su.sin.sin_family == AF_INET + && ntohl(paddr.s_addr) + < ntohl(binfo->peer->su.sin + .sin_addr + .s_addr)) { + if (min) { + if (ntohl(binfo->peer->su.sin + .sin_addr + .s_addr) + < ntohl(min->peer->su.sin + .sin_addr + .s_addr)) + min = binfo; + } else + min = binfo; + } + } + + if (min) { + *length = + v->namelen + BGP_PATHATTR_ENTRY_OFFSET; + + offset = name + v->namelen; + oid_copy_addr(offset, &rn->p.u.prefix4, + IN_ADDR_SIZE); + offset += IN_ADDR_SIZE; + *offset = rn->p.prefixlen; + offset++; + oid_copy_addr(offset, + &min->peer->su.sin.sin_addr, + IN_ADDR_SIZE); + addr->prefix = rn->p.u.prefix4; + addr->prefixlen = rn->p.prefixlen; + + bgp_unlock_node(rn); + + return min; + } + + paddr.s_addr = 0; + } while ((rn = bgp_route_next(rn)) != NULL); } - while ((rn = bgp_route_next (rn)) != NULL); - } - return NULL; + return NULL; } -static u_char * -bgp4PathAttrTable (struct variable *v, oid name[], size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *bgp4PathAttrTable(struct variable *v, oid name[], size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - struct bgp *bgp; - struct bgp_info *binfo; - struct prefix_ipv4 addr; - - bgp = bgp_get_default (); - if (! bgp) - return NULL; - - if (smux_header_table(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - memset (&addr, 0, sizeof (struct prefix_ipv4)); - - binfo = bgp4PathAttrLookup (v, name, length, bgp, &addr, exact); - if (! binfo) - return NULL; - - switch (v->magic) - { - case BGP4PATHATTRPEER: /* 1 */ - return SNMP_IPADDRESS (binfo->peer->su.sin.sin_addr); - break; - case BGP4PATHATTRIPADDRPREFIXLEN: /* 2 */ - return SNMP_INTEGER (addr.prefixlen); - break; - case BGP4PATHATTRIPADDRPREFIX: /* 3 */ - return SNMP_IPADDRESS (addr.prefix); - break; - case BGP4PATHATTRORIGIN: /* 4 */ - return SNMP_INTEGER (binfo->attr->origin); - break; - case BGP4PATHATTRASPATHSEGMENT: /* 5 */ - return aspath_snmp_pathseg (binfo->attr->aspath, var_len); - break; - case BGP4PATHATTRNEXTHOP: /* 6 */ - return SNMP_IPADDRESS (binfo->attr->nexthop); - break; - case BGP4PATHATTRMULTIEXITDISC: /* 7 */ - return SNMP_INTEGER (binfo->attr->med); - break; - case BGP4PATHATTRLOCALPREF: /* 8 */ - return SNMP_INTEGER (binfo->attr->local_pref); - break; - case BGP4PATHATTRATOMICAGGREGATE: /* 9 */ - return SNMP_INTEGER (1); - break; - case BGP4PATHATTRAGGREGATORAS: /* 10 */ - return SNMP_INTEGER (binfo->attr->aggregator_as); - break; - case BGP4PATHATTRAGGREGATORADDR: /* 11 */ - return SNMP_IPADDRESS (binfo->attr->aggregator_addr); - break; - case BGP4PATHATTRCALCLOCALPREF: /* 12 */ - return SNMP_INTEGER (-1); - break; - case BGP4PATHATTRBEST: /* 13 */ + struct bgp *bgp; + struct bgp_info *binfo; + struct prefix_ipv4 addr; + + bgp = bgp_get_default(); + if (!bgp) + return NULL; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + memset(&addr, 0, sizeof(struct prefix_ipv4)); + + binfo = bgp4PathAttrLookup(v, name, length, bgp, &addr, exact); + if (!binfo) + return NULL; + + switch (v->magic) { + case BGP4PATHATTRPEER: /* 1 */ + return SNMP_IPADDRESS(binfo->peer->su.sin.sin_addr); + break; + case BGP4PATHATTRIPADDRPREFIXLEN: /* 2 */ + return SNMP_INTEGER(addr.prefixlen); + break; + case BGP4PATHATTRIPADDRPREFIX: /* 3 */ + return SNMP_IPADDRESS(addr.prefix); + break; + case BGP4PATHATTRORIGIN: /* 4 */ + return SNMP_INTEGER(binfo->attr->origin); + break; + case BGP4PATHATTRASPATHSEGMENT: /* 5 */ + return aspath_snmp_pathseg(binfo->attr->aspath, var_len); + break; + case BGP4PATHATTRNEXTHOP: /* 6 */ + return SNMP_IPADDRESS(binfo->attr->nexthop); + break; + case BGP4PATHATTRMULTIEXITDISC: /* 7 */ + return SNMP_INTEGER(binfo->attr->med); + break; + case BGP4PATHATTRLOCALPREF: /* 8 */ + return SNMP_INTEGER(binfo->attr->local_pref); + break; + case BGP4PATHATTRATOMICAGGREGATE: /* 9 */ + return SNMP_INTEGER(1); + break; + case BGP4PATHATTRAGGREGATORAS: /* 10 */ + return SNMP_INTEGER(binfo->attr->aggregator_as); + break; + case BGP4PATHATTRAGGREGATORADDR: /* 11 */ + return SNMP_IPADDRESS(binfo->attr->aggregator_addr); + break; + case BGP4PATHATTRCALCLOCALPREF: /* 12 */ + return SNMP_INTEGER(-1); + break; + case BGP4PATHATTRBEST: /* 13 */ + /* $FRR indent$ */ + /* clang-format off */ #define BGP4_PathAttrBest_false 1 #define BGP4_PathAttrBest_true 2 - if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED)) - return SNMP_INTEGER (BGP4_PathAttrBest_true); - else - return SNMP_INTEGER (BGP4_PathAttrBest_false); - break; - case BGP4PATHATTRUNKNOWN: /* 14 */ - *var_len = 0; - return NULL; - break; - } - return NULL; + if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)) + return SNMP_INTEGER(BGP4_PathAttrBest_true); + else + return SNMP_INTEGER(BGP4_PathAttrBest_false); + break; + case BGP4PATHATTRUNKNOWN: /* 14 */ + *var_len = 0; + return NULL; + break; + } + return NULL; } /* BGP Traps. */ -static struct trap_object bgpTrapList[] = -{ - {3, {3, 1, BGPPEERLASTERROR}}, - {3, {3, 1, BGPPEERSTATE}} -}; +static struct trap_object bgpTrapList[] = {{3, {3, 1, BGPPEERLASTERROR}}, + {3, {3, 1, BGPPEERSTATE}}}; -static int -bgpTrapEstablished (struct peer *peer) +static int bgpTrapEstablished(struct peer *peer) { - int ret; - struct in_addr addr; - oid index[sizeof (oid) * IN_ADDR_SIZE]; - - ret = inet_aton (peer->host, &addr); - if (ret == 0) - return 0; - - oid_copy_addr (index, &addr, IN_ADDR_SIZE); - - smux_trap (bgp_variables, sizeof bgp_variables / sizeof (struct variable), - bgp_trap_oid, sizeof bgp_trap_oid / sizeof (oid), - bgp_oid, sizeof bgp_oid / sizeof (oid), - index, IN_ADDR_SIZE, - bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object), - BGPESTABLISHED); - return 0; + int ret; + struct in_addr addr; + oid index[sizeof(oid) * IN_ADDR_SIZE]; + + ret = inet_aton(peer->host, &addr); + if (ret == 0) + return 0; + + oid_copy_addr(index, &addr, IN_ADDR_SIZE); + + smux_trap(bgp_variables, sizeof bgp_variables / sizeof(struct variable), + bgp_trap_oid, sizeof bgp_trap_oid / sizeof(oid), bgp_oid, + sizeof bgp_oid / sizeof(oid), index, IN_ADDR_SIZE, + bgpTrapList, sizeof bgpTrapList / sizeof(struct trap_object), + BGPESTABLISHED); + return 0; } -static int -bgpTrapBackwardTransition (struct peer *peer) +static int bgpTrapBackwardTransition(struct peer *peer) { - int ret; - struct in_addr addr; - oid index[sizeof (oid) * IN_ADDR_SIZE]; - - ret = inet_aton (peer->host, &addr); - if (ret == 0) - return 0; - - oid_copy_addr (index, &addr, IN_ADDR_SIZE); - - smux_trap (bgp_variables, sizeof bgp_variables / sizeof (struct variable), - bgp_trap_oid, sizeof bgp_trap_oid / sizeof (oid), - bgp_oid, sizeof bgp_oid / sizeof (oid), - index, IN_ADDR_SIZE, - bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object), - BGPBACKWARDTRANSITION); - return 0; + int ret; + struct in_addr addr; + oid index[sizeof(oid) * IN_ADDR_SIZE]; + + ret = inet_aton(peer->host, &addr); + if (ret == 0) + return 0; + + oid_copy_addr(index, &addr, IN_ADDR_SIZE); + + smux_trap(bgp_variables, sizeof bgp_variables / sizeof(struct variable), + bgp_trap_oid, sizeof bgp_trap_oid / sizeof(oid), bgp_oid, + sizeof bgp_oid / sizeof(oid), index, IN_ADDR_SIZE, + bgpTrapList, sizeof bgpTrapList / sizeof(struct trap_object), + BGPBACKWARDTRANSITION); + return 0; } -static int -bgp_snmp_init (struct thread_master *tm) +static int bgp_snmp_init(struct thread_master *tm) { - smux_init (tm); - REGISTER_MIB("mibII/bgp", bgp_variables, variable, bgp_oid); - return 0; + smux_init(tm); + REGISTER_MIB("mibII/bgp", bgp_variables, variable, bgp_oid); + return 0; } -static int -bgp_snmp_module_init (void) +static int bgp_snmp_module_init(void) { - hook_register(peer_established, bgpTrapEstablished); - hook_register(peer_backward_transition, bgpTrapBackwardTransition); - hook_register(frr_late_init, bgp_snmp_init); - return 0; + hook_register(peer_established, bgpTrapEstablished); + hook_register(peer_backward_transition, bgpTrapBackwardTransition); + hook_register(frr_late_init, bgp_snmp_init); + return 0; } -FRR_MODULE_SETUP( - .name = "bgpd_snmp", - .version = FRR_VERSION, - .description = "bgpd AgentX SNMP module", - .init = bgp_snmp_module_init -) +FRR_MODULE_SETUP(.name = "bgpd_snmp", .version = FRR_VERSION, + .description = "bgpd AgentX SNMP module", + .init = bgp_snmp_module_init) diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c index 642807e7a..261ab9f76 100644 --- a/bgpd/bgp_table.c +++ b/bgpd/bgp_table.c @@ -30,91 +30,82 @@ #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" -void -bgp_table_lock (struct bgp_table *rt) +void bgp_table_lock(struct bgp_table *rt) { - rt->lock++; + rt->lock++; } -void -bgp_table_unlock (struct bgp_table *rt) +void bgp_table_unlock(struct bgp_table *rt) { - assert (rt->lock > 0); - rt->lock--; + assert(rt->lock > 0); + rt->lock--; - if (rt->lock != 0) - { - return; - } + if (rt->lock != 0) { + return; + } - route_table_finish (rt->route_table); - rt->route_table = NULL; + route_table_finish(rt->route_table); + rt->route_table = NULL; - XFREE (MTYPE_BGP_TABLE, rt); + XFREE(MTYPE_BGP_TABLE, rt); } -void -bgp_table_finish (struct bgp_table **rt) +void bgp_table_finish(struct bgp_table **rt) { - if (*rt != NULL) - { - bgp_table_unlock(*rt); - *rt = NULL; - } + if (*rt != NULL) { + bgp_table_unlock(*rt); + *rt = NULL; + } } /* * bgp_node_create */ -static struct route_node * -bgp_node_create (route_table_delegate_t *delegate, struct route_table *table) +static struct route_node *bgp_node_create(route_table_delegate_t *delegate, + struct route_table *table) { - struct bgp_node *node; - node = XCALLOC (MTYPE_BGP_NODE, sizeof (struct bgp_node)); - return bgp_node_to_rnode (node); + struct bgp_node *node; + node = XCALLOC(MTYPE_BGP_NODE, sizeof(struct bgp_node)); + return bgp_node_to_rnode(node); } /* * bgp_node_destroy */ -static void -bgp_node_destroy (route_table_delegate_t *delegate, - struct route_table *table, struct route_node *node) +static void bgp_node_destroy(route_table_delegate_t *delegate, + struct route_table *table, struct route_node *node) { - struct bgp_node *bgp_node; - bgp_node = bgp_node_from_rnode (node); - XFREE (MTYPE_BGP_NODE, bgp_node); + struct bgp_node *bgp_node; + bgp_node = bgp_node_from_rnode(node); + XFREE(MTYPE_BGP_NODE, bgp_node); } /* * Function vector to customize the behavior of the route table * library for BGP route tables. */ -route_table_delegate_t bgp_table_delegate = { - .create_node = bgp_node_create, - .destroy_node = bgp_node_destroy -}; +route_table_delegate_t bgp_table_delegate = {.create_node = bgp_node_create, + .destroy_node = bgp_node_destroy}; /* * bgp_table_init */ -struct bgp_table * -bgp_table_init (afi_t afi, safi_t safi) +struct bgp_table *bgp_table_init(afi_t afi, safi_t safi) { - struct bgp_table *rt; + struct bgp_table *rt; - rt = XCALLOC (MTYPE_BGP_TABLE, sizeof (struct bgp_table)); + rt = XCALLOC(MTYPE_BGP_TABLE, sizeof(struct bgp_table)); - rt->route_table = route_table_init_with_delegate (&bgp_table_delegate); + rt->route_table = route_table_init_with_delegate(&bgp_table_delegate); - /* - * Set up back pointer to bgp_table. - */ - rt->route_table->info = rt; + /* + * Set up back pointer to bgp_table. + */ + rt->route_table->info = rt; - bgp_table_lock (rt); - rt->afi = afi; - rt->safi = safi; + bgp_table_lock(rt); + rt->afi = afi; + rt->safi = safi; - return rt; + return rt; } diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h index d11b70842..0d5706f7c 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h @@ -24,40 +24,38 @@ #include "mpls.h" #include "table.h" -struct bgp_table -{ - /* afi/safi of this table */ - afi_t afi; - safi_t safi; - - int lock; - - struct route_table *route_table; - uint64_t version; +struct bgp_table { + /* afi/safi of this table */ + afi_t afi; + safi_t safi; + + int lock; + + struct route_table *route_table; + uint64_t version; }; -struct bgp_node -{ - /* - * CAUTION - * - * These fields must be the very first fields in this structure. - * - * @see bgp_node_to_rnode - * @see bgp_node_from_rnode - */ - ROUTE_NODE_FIELDS +struct bgp_node { + /* + * CAUTION + * + * These fields must be the very first fields in this structure. + * + * @see bgp_node_to_rnode + * @see bgp_node_from_rnode + */ + ROUTE_NODE_FIELDS - struct bgp_adj_out *adj_out; + struct bgp_adj_out *adj_out; - struct bgp_adj_in *adj_in; + struct bgp_adj_in *adj_in; - struct bgp_node *prn; + struct bgp_node *prn; - mpls_label_t local_label; + mpls_label_t local_label; - uint64_t version; - u_char flags; + uint64_t version; + u_char flags; #define BGP_NODE_PROCESS_SCHEDULED (1 << 0) #define BGP_NODE_USER_CLEAR (1 << 1) #define BGP_NODE_LABEL_CHANGED (1 << 2) @@ -66,19 +64,18 @@ struct bgp_node /* * bgp_table_iter_t - * + * * Structure that holds state for iterating over a bgp table. */ -typedef struct bgp_table_iter_t_ -{ - struct bgp_table *table; - route_table_iter_t rt_iter; +typedef struct bgp_table_iter_t_ { + struct bgp_table *table; + route_table_iter_t rt_iter; } bgp_table_iter_t; -extern struct bgp_table *bgp_table_init (afi_t, safi_t); -extern void bgp_table_lock (struct bgp_table *); -extern void bgp_table_unlock (struct bgp_table *); -extern void bgp_table_finish (struct bgp_table **); +extern struct bgp_table *bgp_table_init(afi_t, safi_t); +extern void bgp_table_lock(struct bgp_table *); +extern void bgp_table_unlock(struct bgp_table *); +extern void bgp_table_finish(struct bgp_table **); /* @@ -86,10 +83,9 @@ extern void bgp_table_finish (struct bgp_table **); * * Returns the bgp_node structure corresponding to a route_node. */ -static inline struct bgp_node * -bgp_node_from_rnode (struct route_node *rnode) +static inline struct bgp_node *bgp_node_from_rnode(struct route_node *rnode) { - return (struct bgp_node *) rnode; + return (struct bgp_node *)rnode; } /* @@ -97,10 +93,9 @@ bgp_node_from_rnode (struct route_node *rnode) * * Returns the route_node structure corresponding to a bgp_node. */ -static inline struct route_node * -bgp_node_to_rnode (struct bgp_node *node) +static inline struct route_node *bgp_node_to_rnode(struct bgp_node *node) { - return (struct route_node *) node; + return (struct route_node *)node; } /* @@ -108,10 +103,9 @@ bgp_node_to_rnode (struct bgp_node *node) * * Returns the bgp_table that the given node is in. */ -static inline struct bgp_table * -bgp_node_table (struct bgp_node *node) +static inline struct bgp_table *bgp_node_table(struct bgp_node *node) { - return bgp_node_to_rnode (node)->table->info; + return bgp_node_to_rnode(node)->table->info; } /* @@ -119,19 +113,17 @@ bgp_node_table (struct bgp_node *node) * * Gets the parent node of the given node without locking it. */ -static inline struct bgp_node * -bgp_node_parent_nolock (struct bgp_node *node) +static inline struct bgp_node *bgp_node_parent_nolock(struct bgp_node *node) { - return bgp_node_from_rnode (node->parent); + return bgp_node_from_rnode(node->parent); } /* * bgp_unlock_node */ -static inline void -bgp_unlock_node (struct bgp_node *node) +static inline void bgp_unlock_node(struct bgp_node *node) { - route_unlock_node (bgp_node_to_rnode (node)); + route_unlock_node(bgp_node_to_rnode(node)); } /* @@ -142,183 +134,173 @@ bgp_unlock_node (struct bgp_node *node) * @see bgp_table_top */ static inline struct bgp_node * -bgp_table_top_nolock (const struct bgp_table *const table) +bgp_table_top_nolock(const struct bgp_table *const table) { - return bgp_node_from_rnode (table->route_table->top); + return bgp_node_from_rnode(table->route_table->top); } /* * bgp_table_top */ static inline struct bgp_node * -bgp_table_top (const struct bgp_table *const table) +bgp_table_top(const struct bgp_table *const table) { - return bgp_node_from_rnode (route_top (table->route_table)); + return bgp_node_from_rnode(route_top(table->route_table)); } /* * bgp_route_next */ -static inline struct bgp_node * -bgp_route_next (struct bgp_node *node) +static inline struct bgp_node *bgp_route_next(struct bgp_node *node) { - return bgp_node_from_rnode (route_next (bgp_node_to_rnode (node))); + return bgp_node_from_rnode(route_next(bgp_node_to_rnode(node))); } /* * bgp_route_next_until */ -static inline struct bgp_node * -bgp_route_next_until (struct bgp_node *node, struct bgp_node *limit) +static inline struct bgp_node *bgp_route_next_until(struct bgp_node *node, + struct bgp_node *limit) { - struct route_node *rnode; + struct route_node *rnode; - rnode = route_next_until (bgp_node_to_rnode (node), - bgp_node_to_rnode (limit)); - return bgp_node_from_rnode (rnode); + rnode = route_next_until(bgp_node_to_rnode(node), + bgp_node_to_rnode(limit)); + return bgp_node_from_rnode(rnode); } /* * bgp_node_get */ -static inline struct bgp_node * -bgp_node_get (struct bgp_table *const table, struct prefix *p) +static inline struct bgp_node *bgp_node_get(struct bgp_table *const table, + struct prefix *p) { - return bgp_node_from_rnode (route_node_get (table->route_table, p)); + return bgp_node_from_rnode(route_node_get(table->route_table, p)); } /* * bgp_node_lookup */ static inline struct bgp_node * -bgp_node_lookup (const struct bgp_table *const table, struct prefix *p) +bgp_node_lookup(const struct bgp_table *const table, struct prefix *p) { - return bgp_node_from_rnode (route_node_lookup (table->route_table, p)); + return bgp_node_from_rnode(route_node_lookup(table->route_table, p)); } /* * bgp_lock_node */ -static inline struct bgp_node * -bgp_lock_node (struct bgp_node *node) +static inline struct bgp_node *bgp_lock_node(struct bgp_node *node) { - return bgp_node_from_rnode (route_lock_node (bgp_node_to_rnode (node))); + return bgp_node_from_rnode(route_lock_node(bgp_node_to_rnode(node))); } /* * bgp_node_match */ -static inline struct bgp_node * -bgp_node_match (const struct bgp_table *table, struct prefix *p) +static inline struct bgp_node *bgp_node_match(const struct bgp_table *table, + struct prefix *p) { - return bgp_node_from_rnode (route_node_match (table->route_table, p)); + return bgp_node_from_rnode(route_node_match(table->route_table, p)); } /* * bgp_node_match_ipv4 */ static inline struct bgp_node * -bgp_node_match_ipv4 (const struct bgp_table *table, struct in_addr *addr) +bgp_node_match_ipv4(const struct bgp_table *table, struct in_addr *addr) { - return bgp_node_from_rnode (route_node_match_ipv4 (table->route_table, - addr)); + return bgp_node_from_rnode( + route_node_match_ipv4(table->route_table, addr)); } /* * bgp_node_match_ipv6 */ static inline struct bgp_node * -bgp_node_match_ipv6 (const struct bgp_table *table, struct in6_addr *addr) +bgp_node_match_ipv6(const struct bgp_table *table, struct in6_addr *addr) { - return bgp_node_from_rnode (route_node_match_ipv6 (table->route_table, - addr)); + return bgp_node_from_rnode( + route_node_match_ipv6(table->route_table, addr)); } -static inline unsigned long -bgp_table_count (const struct bgp_table *const table) +static inline unsigned long bgp_table_count(const struct bgp_table *const table) { - return route_table_count (table->route_table); + return route_table_count(table->route_table); } /* * bgp_table_get_next */ -static inline struct bgp_node * -bgp_table_get_next (const struct bgp_table *table, struct prefix *p) +static inline struct bgp_node *bgp_table_get_next(const struct bgp_table *table, + struct prefix *p) { - return bgp_node_from_rnode (route_table_get_next (table->route_table, p)); + return bgp_node_from_rnode(route_table_get_next(table->route_table, p)); } /* * bgp_table_iter_init */ -static inline void -bgp_table_iter_init (bgp_table_iter_t * iter, struct bgp_table *table) +static inline void bgp_table_iter_init(bgp_table_iter_t *iter, + struct bgp_table *table) { - bgp_table_lock (table); - iter->table = table; - route_table_iter_init (&iter->rt_iter, table->route_table); + bgp_table_lock(table); + iter->table = table; + route_table_iter_init(&iter->rt_iter, table->route_table); } /* * bgp_table_iter_next */ -static inline struct bgp_node * -bgp_table_iter_next (bgp_table_iter_t * iter) +static inline struct bgp_node *bgp_table_iter_next(bgp_table_iter_t *iter) { - return bgp_node_from_rnode (route_table_iter_next (&iter->rt_iter)); + return bgp_node_from_rnode(route_table_iter_next(&iter->rt_iter)); } /* * bgp_table_iter_cleanup */ -static inline void -bgp_table_iter_cleanup (bgp_table_iter_t * iter) +static inline void bgp_table_iter_cleanup(bgp_table_iter_t *iter) { - route_table_iter_cleanup (&iter->rt_iter); - bgp_table_unlock (iter->table); - iter->table = NULL; + route_table_iter_cleanup(&iter->rt_iter); + bgp_table_unlock(iter->table); + iter->table = NULL; } /* * bgp_table_iter_pause */ -static inline void -bgp_table_iter_pause (bgp_table_iter_t * iter) +static inline void bgp_table_iter_pause(bgp_table_iter_t *iter) { - route_table_iter_pause (&iter->rt_iter); + route_table_iter_pause(&iter->rt_iter); } /* * bgp_table_iter_is_done */ -static inline int -bgp_table_iter_is_done (bgp_table_iter_t * iter) +static inline int bgp_table_iter_is_done(bgp_table_iter_t *iter) { - return route_table_iter_is_done (&iter->rt_iter); + return route_table_iter_is_done(&iter->rt_iter); } /* * bgp_table_iter_started */ -static inline int -bgp_table_iter_started (bgp_table_iter_t * iter) +static inline int bgp_table_iter_started(bgp_table_iter_t *iter) { - return route_table_iter_started (&iter->rt_iter); + return route_table_iter_started(&iter->rt_iter); } /* This would benefit from a real atomic operation... * until then. */ -static inline uint64_t -bgp_table_next_version (struct bgp_table *table) +static inline uint64_t bgp_table_next_version(struct bgp_table *table) { - return ++table->version; + return ++table->version; } -static inline uint64_t -bgp_table_version (struct bgp_table *table) +static inline uint64_t bgp_table_version(struct bgp_table *table) { - return table->version; + return table->version; } #endif /* _QUAGGA_BGP_TABLE_H */ diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c index b8971dcd6..77e615715 100644 --- a/bgpd/bgp_updgrp.c +++ b/bgpd/bgp_updgrp.c @@ -64,61 +64,61 @@ * worry about its wrapping and about filling gaps. While at it, timestamp * the creation. */ -static void -update_group_checkin (struct update_group *updgrp) +static void update_group_checkin(struct update_group *updgrp) { - updgrp->id = ++bm->updgrp_idspace; - updgrp->uptime = bgp_clock (); + updgrp->id = ++bm->updgrp_idspace; + updgrp->uptime = bgp_clock(); } -static void -update_subgroup_checkin (struct update_subgroup *subgrp, - struct update_group *updgrp) +static void update_subgroup_checkin(struct update_subgroup *subgrp, + struct update_group *updgrp) { - subgrp->id = ++bm->subgrp_idspace; - subgrp->uptime = bgp_clock (); + subgrp->id = ++bm->subgrp_idspace; + subgrp->uptime = bgp_clock(); } -static void -sync_init (struct update_subgroup *subgrp) +static void sync_init(struct update_subgroup *subgrp) { - subgrp->sync = XCALLOC (MTYPE_BGP_SYNCHRONISE, - sizeof (struct bgp_synchronize)); - BGP_ADV_FIFO_INIT (&subgrp->sync->update); - BGP_ADV_FIFO_INIT (&subgrp->sync->withdraw); - BGP_ADV_FIFO_INIT (&subgrp->sync->withdraw_low); - subgrp->hash = hash_create (baa_hash_key, baa_hash_cmp, NULL); - - /* We use a larger buffer for subgrp->work in the event that: - * - We RX a BGP_UPDATE where the attributes alone are just - * under BGP_MAX_PACKET_SIZE - * - The user configures an outbound route-map that does many as-path - * prepends or adds many communities. At most they can have CMD_ARGC_MAX - * args in a route-map so there is a finite limit on how large they can - * make the attributes. - * - * Having a buffer with BGP_MAX_PACKET_SIZE_OVERFLOW allows us to avoid bounds - * checking for every single attribute as we construct an UPDATE. - */ - subgrp->work = stream_new (BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW); - subgrp->scratch = stream_new (BGP_MAX_PACKET_SIZE); + subgrp->sync = + XCALLOC(MTYPE_BGP_SYNCHRONISE, sizeof(struct bgp_synchronize)); + BGP_ADV_FIFO_INIT(&subgrp->sync->update); + BGP_ADV_FIFO_INIT(&subgrp->sync->withdraw); + BGP_ADV_FIFO_INIT(&subgrp->sync->withdraw_low); + subgrp->hash = hash_create(baa_hash_key, baa_hash_cmp, NULL); + + /* We use a larger buffer for subgrp->work in the event that: + * - We RX a BGP_UPDATE where the attributes alone are just + * under BGP_MAX_PACKET_SIZE + * - The user configures an outbound route-map that does many as-path + * prepends or adds many communities. At most they can have + * CMD_ARGC_MAX + * args in a route-map so there is a finite limit on how large they + * can + * make the attributes. + * + * Having a buffer with BGP_MAX_PACKET_SIZE_OVERFLOW allows us to avoid + * bounds + * checking for every single attribute as we construct an UPDATE. + */ + subgrp->work = + stream_new(BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW); + subgrp->scratch = stream_new(BGP_MAX_PACKET_SIZE); } -static void -sync_delete (struct update_subgroup *subgrp) +static void sync_delete(struct update_subgroup *subgrp) { - if (subgrp->sync) - XFREE (MTYPE_BGP_SYNCHRONISE, subgrp->sync); - subgrp->sync = NULL; - if (subgrp->hash) - hash_free (subgrp->hash); - subgrp->hash = NULL; - if (subgrp->work) - stream_free (subgrp->work); - subgrp->work = NULL; - if (subgrp->scratch) - stream_free (subgrp->scratch); - subgrp->scratch = NULL; + if (subgrp->sync) + XFREE(MTYPE_BGP_SYNCHRONISE, subgrp->sync); + subgrp->sync = NULL; + if (subgrp->hash) + hash_free(subgrp->hash); + subgrp->hash = NULL; + if (subgrp->work) + stream_free(subgrp->work); + subgrp->work = NULL; + if (subgrp->scratch) + stream_free(subgrp->scratch); + subgrp->scratch = NULL; } /** @@ -126,127 +126,127 @@ sync_delete (struct update_subgroup *subgrp) * * copy only those fields that are relevant to update group match */ -static void -conf_copy (struct peer *dst, struct peer *src, afi_t afi, safi_t safi) +static void conf_copy(struct peer *dst, struct peer *src, afi_t afi, + safi_t safi) { - struct bgp_filter *srcfilter; - struct bgp_filter *dstfilter; - - srcfilter = &src->filter[afi][safi]; - dstfilter = &dst->filter[afi][safi]; - - dst->bgp = src->bgp; - dst->sort = src->sort; - dst->as = src->as; - dst->v_routeadv = src->v_routeadv; - dst->flags = src->flags; - dst->af_flags[afi][safi] = src->af_flags[afi][safi]; - if (dst->host) - XFREE(MTYPE_BGP_PEER_HOST, dst->host); - - dst->host = XSTRDUP(MTYPE_BGP_PEER_HOST, src->host); - dst->cap = src->cap; - dst->af_cap[afi][safi] = src->af_cap[afi][safi]; - dst->afc_nego[afi][safi] = src->afc_nego[afi][safi]; - dst->orf_plist[afi][safi] = src->orf_plist[afi][safi]; - dst->local_as = src->local_as; - dst->change_local_as = src->change_local_as; - dst->shared_network = src->shared_network; - memcpy (&(dst->nexthop), &(src->nexthop), sizeof (struct bgp_nexthop)); - - dst->group = src->group; - - if (src->default_rmap[afi][safi].name) - { - dst->default_rmap[afi][safi].name = - XSTRDUP(MTYPE_ROUTE_MAP_NAME, src->default_rmap[afi][safi].name); - dst->default_rmap[afi][safi].map = src->default_rmap[afi][safi].map; - } - - if (DISTRIBUTE_OUT_NAME(srcfilter)) - { - DISTRIBUTE_OUT_NAME(dstfilter) = XSTRDUP(MTYPE_BGP_FILTER_NAME, DISTRIBUTE_OUT_NAME(srcfilter)); - DISTRIBUTE_OUT(dstfilter) = DISTRIBUTE_OUT(srcfilter); - } - - if (PREFIX_LIST_OUT_NAME(srcfilter)) - { - PREFIX_LIST_OUT_NAME(dstfilter) = XSTRDUP(MTYPE_BGP_FILTER_NAME, PREFIX_LIST_OUT_NAME(srcfilter)); - PREFIX_LIST_OUT(dstfilter) = PREFIX_LIST_OUT(srcfilter); - } - - if (FILTER_LIST_OUT_NAME(srcfilter)) - { - FILTER_LIST_OUT_NAME(dstfilter) = XSTRDUP(MTYPE_BGP_FILTER_NAME, FILTER_LIST_OUT_NAME(srcfilter)); - FILTER_LIST_OUT(dstfilter) = FILTER_LIST_OUT(srcfilter); - } - - if (ROUTE_MAP_OUT_NAME(srcfilter)) - { - ROUTE_MAP_OUT_NAME(dstfilter) = XSTRDUP(MTYPE_BGP_FILTER_NAME, ROUTE_MAP_OUT_NAME(srcfilter)); - ROUTE_MAP_OUT(dstfilter) = ROUTE_MAP_OUT(srcfilter); - } - - if (UNSUPPRESS_MAP_NAME(srcfilter)) - { - UNSUPPRESS_MAP_NAME(dstfilter) = XSTRDUP(MTYPE_BGP_FILTER_NAME, UNSUPPRESS_MAP_NAME(srcfilter)); - UNSUPPRESS_MAP(dstfilter) = UNSUPPRESS_MAP(srcfilter); - } + struct bgp_filter *srcfilter; + struct bgp_filter *dstfilter; + + srcfilter = &src->filter[afi][safi]; + dstfilter = &dst->filter[afi][safi]; + + dst->bgp = src->bgp; + dst->sort = src->sort; + dst->as = src->as; + dst->v_routeadv = src->v_routeadv; + dst->flags = src->flags; + dst->af_flags[afi][safi] = src->af_flags[afi][safi]; + if (dst->host) + XFREE(MTYPE_BGP_PEER_HOST, dst->host); + + dst->host = XSTRDUP(MTYPE_BGP_PEER_HOST, src->host); + dst->cap = src->cap; + dst->af_cap[afi][safi] = src->af_cap[afi][safi]; + dst->afc_nego[afi][safi] = src->afc_nego[afi][safi]; + dst->orf_plist[afi][safi] = src->orf_plist[afi][safi]; + dst->local_as = src->local_as; + dst->change_local_as = src->change_local_as; + dst->shared_network = src->shared_network; + memcpy(&(dst->nexthop), &(src->nexthop), sizeof(struct bgp_nexthop)); + + dst->group = src->group; + + if (src->default_rmap[afi][safi].name) { + dst->default_rmap[afi][safi].name = + XSTRDUP(MTYPE_ROUTE_MAP_NAME, + src->default_rmap[afi][safi].name); + dst->default_rmap[afi][safi].map = + src->default_rmap[afi][safi].map; + } + + if (DISTRIBUTE_OUT_NAME(srcfilter)) { + DISTRIBUTE_OUT_NAME(dstfilter) = XSTRDUP( + MTYPE_BGP_FILTER_NAME, DISTRIBUTE_OUT_NAME(srcfilter)); + DISTRIBUTE_OUT(dstfilter) = DISTRIBUTE_OUT(srcfilter); + } + + if (PREFIX_LIST_OUT_NAME(srcfilter)) { + PREFIX_LIST_OUT_NAME(dstfilter) = XSTRDUP( + MTYPE_BGP_FILTER_NAME, PREFIX_LIST_OUT_NAME(srcfilter)); + PREFIX_LIST_OUT(dstfilter) = PREFIX_LIST_OUT(srcfilter); + } + + if (FILTER_LIST_OUT_NAME(srcfilter)) { + FILTER_LIST_OUT_NAME(dstfilter) = XSTRDUP( + MTYPE_BGP_FILTER_NAME, FILTER_LIST_OUT_NAME(srcfilter)); + FILTER_LIST_OUT(dstfilter) = FILTER_LIST_OUT(srcfilter); + } + + if (ROUTE_MAP_OUT_NAME(srcfilter)) { + ROUTE_MAP_OUT_NAME(dstfilter) = XSTRDUP( + MTYPE_BGP_FILTER_NAME, ROUTE_MAP_OUT_NAME(srcfilter)); + ROUTE_MAP_OUT(dstfilter) = ROUTE_MAP_OUT(srcfilter); + } + + if (UNSUPPRESS_MAP_NAME(srcfilter)) { + UNSUPPRESS_MAP_NAME(dstfilter) = XSTRDUP( + MTYPE_BGP_FILTER_NAME, UNSUPPRESS_MAP_NAME(srcfilter)); + UNSUPPRESS_MAP(dstfilter) = UNSUPPRESS_MAP(srcfilter); + } } /** * since we did a bunch of XSTRDUP's in conf_copy, time to free them up */ -static void -conf_release (struct peer *src, afi_t afi, safi_t safi) +static void conf_release(struct peer *src, afi_t afi, safi_t safi) { - struct bgp_filter *srcfilter; + struct bgp_filter *srcfilter; - srcfilter = &src->filter[afi][safi]; + srcfilter = &src->filter[afi][safi]; - if (src->default_rmap[afi][safi].name) - XFREE(MTYPE_ROUTE_MAP_NAME, src->default_rmap[afi][safi].name); + if (src->default_rmap[afi][safi].name) + XFREE(MTYPE_ROUTE_MAP_NAME, src->default_rmap[afi][safi].name); - if (srcfilter->dlist[FILTER_OUT].name) - XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->dlist[FILTER_OUT].name); + if (srcfilter->dlist[FILTER_OUT].name) + XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->dlist[FILTER_OUT].name); - if (srcfilter->plist[FILTER_OUT].name) - XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->plist[FILTER_OUT].name); + if (srcfilter->plist[FILTER_OUT].name) + XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->plist[FILTER_OUT].name); - if (srcfilter->aslist[FILTER_OUT].name) - XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->aslist[FILTER_OUT].name); + if (srcfilter->aslist[FILTER_OUT].name) + XFREE(MTYPE_BGP_FILTER_NAME, + srcfilter->aslist[FILTER_OUT].name); - if (srcfilter->map[RMAP_OUT].name) - XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->map[RMAP_OUT].name); + if (srcfilter->map[RMAP_OUT].name) + XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->map[RMAP_OUT].name); - if (srcfilter->usmap.name) - XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->usmap.name); + if (srcfilter->usmap.name) + XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->usmap.name); - if (src->host) - XFREE(MTYPE_BGP_PEER_HOST, src->host); - src->host = NULL; + if (src->host) + XFREE(MTYPE_BGP_PEER_HOST, src->host); + src->host = NULL; } -static void -peer2_updgrp_copy (struct update_group *updgrp, struct peer_af *paf) +static void peer2_updgrp_copy(struct update_group *updgrp, struct peer_af *paf) { - struct peer *src; - struct peer *dst; + struct peer *src; + struct peer *dst; - if (!updgrp || !paf) - return; + if (!updgrp || !paf) + return; - src = paf->peer; - dst = updgrp->conf; - if (!src || !dst) - return; + src = paf->peer; + dst = updgrp->conf; + if (!src || !dst) + return; - updgrp->afi = paf->afi; - updgrp->safi = paf->safi; - updgrp->afid = paf->afid; - updgrp->bgp = src->bgp; + updgrp->afi = paf->afi; + updgrp->safi = paf->safi; + updgrp->afid = paf->afid; + updgrp->bgp = src->bgp; - conf_copy (dst, src, paf->afi, paf->safi); + conf_copy(dst, src, paf->afi, paf->safi); } /** @@ -255,18 +255,17 @@ peer2_updgrp_copy (struct update_group *updgrp, struct peer_af *paf) * - updgrp_hash_key_make - makes the key for update group search * - updgrp_hash_cmp - compare two update groups. */ -static void * -updgrp_hash_alloc (void *p) +static void *updgrp_hash_alloc(void *p) { - struct update_group *updgrp; - const struct update_group *in; - - in = (const struct update_group *)p; - updgrp = XCALLOC (MTYPE_BGP_UPDGRP, sizeof (struct update_group)); - memcpy (updgrp, in, sizeof (struct update_group)); - updgrp->conf = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer)); - conf_copy (updgrp->conf, in->conf, in->afi, in->safi); - return updgrp; + struct update_group *updgrp; + const struct update_group *in; + + in = (const struct update_group *)p; + updgrp = XCALLOC(MTYPE_BGP_UPDGRP, sizeof(struct update_group)); + memcpy(updgrp, in, sizeof(struct update_group)); + updgrp->conf = XCALLOC(MTYPE_BGP_PEER, sizeof(struct peer)); + conf_copy(updgrp->conf, in->conf, in->afi, in->safi); + return updgrp; } /** @@ -295,218 +294,229 @@ updgrp_hash_alloc (void *p) * 16. Local-as should match, if configured. * ) */ -static unsigned int -updgrp_hash_key_make (void *p) +static unsigned int updgrp_hash_key_make(void *p) { - const struct update_group *updgrp; - const struct peer *peer; - const struct bgp_filter *filter; - uint32_t flags; - uint32_t key; - afi_t afi; - safi_t safi; + const struct update_group *updgrp; + const struct peer *peer; + const struct bgp_filter *filter; + uint32_t flags; + uint32_t key; + afi_t afi; + safi_t safi; #define SEED1 999331 #define SEED2 2147483647 - updgrp = p; - peer = updgrp->conf; - afi = updgrp->afi; - safi = updgrp->safi; - flags = peer->af_flags[afi][safi]; - filter = &peer->filter[afi][safi]; - - key = 0; - - key = jhash_1word (peer->sort, key); /* EBGP or IBGP */ - key = jhash_1word ((peer->flags & PEER_UPDGRP_FLAGS), key); - key = jhash_1word ((flags & PEER_UPDGRP_AF_FLAGS), key); - key = jhash_1word ((peer->cap & PEER_UPDGRP_CAP_FLAGS), key); - key = jhash_1word ((peer->af_cap[afi][safi] & - PEER_UPDGRP_AF_CAP_FLAGS), key); - key = jhash_1word (peer->v_routeadv, key); - key = jhash_1word (peer->change_local_as, key); - - if (peer->group) - key = jhash_1word (jhash (peer->group->name, - strlen (peer->group->name), SEED1), key); - - if (filter->map[RMAP_OUT].name) - key = jhash_1word (jhash (filter->map[RMAP_OUT].name, - strlen (filter->map[RMAP_OUT].name), SEED1), - key); - - if (filter->dlist[FILTER_OUT].name) - key = jhash_1word (jhash (filter->dlist[FILTER_OUT].name, - strlen (filter->dlist[FILTER_OUT].name), SEED1), - key); - - if (filter->plist[FILTER_OUT].name) - key = jhash_1word (jhash (filter->plist[FILTER_OUT].name, - strlen (filter->plist[FILTER_OUT].name), SEED1), - key); - - if (filter->aslist[FILTER_OUT].name) - key = jhash_1word (jhash (filter->aslist[FILTER_OUT].name, - strlen (filter->aslist[FILTER_OUT].name), - SEED1), key); - - if (filter->usmap.name) - key = jhash_1word (jhash (filter->usmap.name, - strlen (filter->usmap.name), SEED1), key); - - if (peer->default_rmap[afi][safi].name) - key = jhash_1word (jhash (peer->default_rmap[afi][safi].name, - strlen (peer->default_rmap[afi][safi].name), - SEED1), key); - - /* If peer is on a shared network and is exchanging IPv6 prefixes, - * it needs to include link-local address. That's different from - * non-shared-network peers (nexthop encoded with 32 bytes vs 16 - * bytes). We create different update groups to take care of that. - */ - key = jhash_1word ((peer->shared_network && - peer_afi_active_nego (peer, AFI_IP6)), - key); - - /* - * There are certain peers that must get their own update-group: - * - lonesoul peers - * - peers that negotiated ORF - */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_LONESOUL) || - CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV) || - CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV)) - key = jhash_1word (jhash (peer->host, strlen (peer->host), SEED2), key); - - return key; + updgrp = p; + peer = updgrp->conf; + afi = updgrp->afi; + safi = updgrp->safi; + flags = peer->af_flags[afi][safi]; + filter = &peer->filter[afi][safi]; + + key = 0; + + key = jhash_1word(peer->sort, key); /* EBGP or IBGP */ + key = jhash_1word((peer->flags & PEER_UPDGRP_FLAGS), key); + key = jhash_1word((flags & PEER_UPDGRP_AF_FLAGS), key); + key = jhash_1word((peer->cap & PEER_UPDGRP_CAP_FLAGS), key); + key = jhash_1word((peer->af_cap[afi][safi] & PEER_UPDGRP_AF_CAP_FLAGS), + key); + key = jhash_1word(peer->v_routeadv, key); + key = jhash_1word(peer->change_local_as, key); + + if (peer->group) + key = jhash_1word(jhash(peer->group->name, + strlen(peer->group->name), SEED1), + key); + + if (filter->map[RMAP_OUT].name) + key = jhash_1word(jhash(filter->map[RMAP_OUT].name, + strlen(filter->map[RMAP_OUT].name), + SEED1), + key); + + if (filter->dlist[FILTER_OUT].name) + key = jhash_1word(jhash(filter->dlist[FILTER_OUT].name, + strlen(filter->dlist[FILTER_OUT].name), + SEED1), + key); + + if (filter->plist[FILTER_OUT].name) + key = jhash_1word(jhash(filter->plist[FILTER_OUT].name, + strlen(filter->plist[FILTER_OUT].name), + SEED1), + key); + + if (filter->aslist[FILTER_OUT].name) + key = jhash_1word(jhash(filter->aslist[FILTER_OUT].name, + strlen(filter->aslist[FILTER_OUT].name), + SEED1), + key); + + if (filter->usmap.name) + key = jhash_1word(jhash(filter->usmap.name, + strlen(filter->usmap.name), SEED1), + key); + + if (peer->default_rmap[afi][safi].name) + key = jhash_1word( + jhash(peer->default_rmap[afi][safi].name, + strlen(peer->default_rmap[afi][safi].name), + SEED1), + key); + + /* If peer is on a shared network and is exchanging IPv6 prefixes, + * it needs to include link-local address. That's different from + * non-shared-network peers (nexthop encoded with 32 bytes vs 16 + * bytes). We create different update groups to take care of that. + */ + key = jhash_1word( + (peer->shared_network && peer_afi_active_nego(peer, AFI_IP6)), + key); + + /* + * There are certain peers that must get their own update-group: + * - lonesoul peers + * - peers that negotiated ORF + */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL) + || CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV) + || CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_SM_OLD_RCV)) + key = jhash_1word(jhash(peer->host, strlen(peer->host), SEED2), + key); + + return key; } -static int -updgrp_hash_cmp (const void *p1, const void *p2) +static int updgrp_hash_cmp(const void *p1, const void *p2) { - const struct update_group *grp1; - const struct update_group *grp2; - const struct peer *pe1; - const struct peer *pe2; - uint32_t flags1; - uint32_t flags2; - const struct bgp_filter *fl1; - const struct bgp_filter *fl2; - afi_t afi; - safi_t safi; - - if (!p1 || !p2) - return 0; - - grp1 = p1; - grp2 = p2; - pe1 = grp1->conf; - pe2 = grp2->conf; - afi = grp1->afi; - safi = grp1->safi; - flags1 = pe1->af_flags[afi][safi]; - flags2 = pe2->af_flags[afi][safi]; - fl1 = &pe1->filter[afi][safi]; - fl2 = &pe2->filter[afi][safi]; - - /* put EBGP and IBGP peers in different update groups */ - if (pe1->sort != pe2->sort) - return 0; - - /* check peer flags */ - if ((pe1->flags & PEER_UPDGRP_FLAGS) != - (pe2->flags & PEER_UPDGRP_FLAGS)) - return 0; - - /* If there is 'local-as' configured, it should match. */ - if (pe1->change_local_as != pe2->change_local_as) - return 0; - - /* flags like route reflector client */ - if ((flags1 & PEER_UPDGRP_AF_FLAGS) != (flags2 & PEER_UPDGRP_AF_FLAGS)) - return 0; - - if ((pe1->cap & PEER_UPDGRP_CAP_FLAGS) != - (pe2->cap & PEER_UPDGRP_CAP_FLAGS)) - return 0; - - if ((pe1->af_cap[afi][safi] & PEER_UPDGRP_AF_CAP_FLAGS) != - (pe2->af_cap[afi][safi] & PEER_UPDGRP_AF_CAP_FLAGS)) - return 0; - - if (pe1->v_routeadv != pe2->v_routeadv) - return 0; - - if (pe1->group != pe2->group) - return 0; - - /* route-map names should be the same */ - if ((fl1->map[RMAP_OUT].name && !fl2->map[RMAP_OUT].name) || - (!fl1->map[RMAP_OUT].name && fl2->map[RMAP_OUT].name) || - (fl1->map[RMAP_OUT].name && fl2->map[RMAP_OUT].name && - strcmp (fl1->map[RMAP_OUT].name, fl2->map[RMAP_OUT].name))) - return 0; - - if ((fl1->dlist[FILTER_OUT].name && !fl2->dlist[FILTER_OUT].name) || - (!fl1->dlist[FILTER_OUT].name && fl2->dlist[FILTER_OUT].name) || - (fl1->dlist[FILTER_OUT].name && fl2->dlist[FILTER_OUT].name && - strcmp (fl1->dlist[FILTER_OUT].name, fl2->dlist[FILTER_OUT].name))) - return 0; - - if ((fl1->plist[FILTER_OUT].name && !fl2->plist[FILTER_OUT].name) || - (!fl1->plist[FILTER_OUT].name && fl2->plist[FILTER_OUT].name) || - (fl1->plist[FILTER_OUT].name && fl2->plist[FILTER_OUT].name && - strcmp (fl1->plist[FILTER_OUT].name, fl2->plist[FILTER_OUT].name))) - return 0; - - if ((fl1->aslist[FILTER_OUT].name && !fl2->aslist[FILTER_OUT].name) || - (!fl1->aslist[FILTER_OUT].name && fl2->aslist[FILTER_OUT].name) || - (fl1->aslist[FILTER_OUT].name && fl2->aslist[FILTER_OUT].name && - strcmp (fl1->aslist[FILTER_OUT].name, fl2->aslist[FILTER_OUT].name))) - return 0; - - if ((fl1->usmap.name && !fl2->usmap.name) || - (!fl1->usmap.name && fl2->usmap.name) || - (fl1->usmap.name && fl2->usmap.name && - strcmp (fl1->usmap.name, fl2->usmap.name))) - return 0; - - if ((pe1->default_rmap[afi][safi].name && - !pe2->default_rmap[afi][safi].name) || - (!pe1->default_rmap[afi][safi].name && - pe2->default_rmap[afi][safi].name) || - (pe1->default_rmap[afi][safi].name && - pe2->default_rmap[afi][safi].name && - strcmp (pe1->default_rmap[afi][safi].name, - pe2->default_rmap[afi][safi].name))) - return 0; - - if ((afi == AFI_IP6) && (pe1->shared_network != pe2->shared_network)) - return 0; - - if ((CHECK_FLAG (pe1->flags, PEER_FLAG_LONESOUL) || - CHECK_FLAG (pe1->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV) || - CHECK_FLAG (pe1->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV)) && - !sockunion_same (&pe1->su, &pe2->su)) - return 0; - - return 1; + const struct update_group *grp1; + const struct update_group *grp2; + const struct peer *pe1; + const struct peer *pe2; + uint32_t flags1; + uint32_t flags2; + const struct bgp_filter *fl1; + const struct bgp_filter *fl2; + afi_t afi; + safi_t safi; + + if (!p1 || !p2) + return 0; + + grp1 = p1; + grp2 = p2; + pe1 = grp1->conf; + pe2 = grp2->conf; + afi = grp1->afi; + safi = grp1->safi; + flags1 = pe1->af_flags[afi][safi]; + flags2 = pe2->af_flags[afi][safi]; + fl1 = &pe1->filter[afi][safi]; + fl2 = &pe2->filter[afi][safi]; + + /* put EBGP and IBGP peers in different update groups */ + if (pe1->sort != pe2->sort) + return 0; + + /* check peer flags */ + if ((pe1->flags & PEER_UPDGRP_FLAGS) + != (pe2->flags & PEER_UPDGRP_FLAGS)) + return 0; + + /* If there is 'local-as' configured, it should match. */ + if (pe1->change_local_as != pe2->change_local_as) + return 0; + + /* flags like route reflector client */ + if ((flags1 & PEER_UPDGRP_AF_FLAGS) != (flags2 & PEER_UPDGRP_AF_FLAGS)) + return 0; + + if ((pe1->cap & PEER_UPDGRP_CAP_FLAGS) + != (pe2->cap & PEER_UPDGRP_CAP_FLAGS)) + return 0; + + if ((pe1->af_cap[afi][safi] & PEER_UPDGRP_AF_CAP_FLAGS) + != (pe2->af_cap[afi][safi] & PEER_UPDGRP_AF_CAP_FLAGS)) + return 0; + + if (pe1->v_routeadv != pe2->v_routeadv) + return 0; + + if (pe1->group != pe2->group) + return 0; + + /* route-map names should be the same */ + if ((fl1->map[RMAP_OUT].name && !fl2->map[RMAP_OUT].name) + || (!fl1->map[RMAP_OUT].name && fl2->map[RMAP_OUT].name) + || (fl1->map[RMAP_OUT].name && fl2->map[RMAP_OUT].name + && strcmp(fl1->map[RMAP_OUT].name, fl2->map[RMAP_OUT].name))) + return 0; + + if ((fl1->dlist[FILTER_OUT].name && !fl2->dlist[FILTER_OUT].name) + || (!fl1->dlist[FILTER_OUT].name && fl2->dlist[FILTER_OUT].name) + || (fl1->dlist[FILTER_OUT].name && fl2->dlist[FILTER_OUT].name + && strcmp(fl1->dlist[FILTER_OUT].name, + fl2->dlist[FILTER_OUT].name))) + return 0; + + if ((fl1->plist[FILTER_OUT].name && !fl2->plist[FILTER_OUT].name) + || (!fl1->plist[FILTER_OUT].name && fl2->plist[FILTER_OUT].name) + || (fl1->plist[FILTER_OUT].name && fl2->plist[FILTER_OUT].name + && strcmp(fl1->plist[FILTER_OUT].name, + fl2->plist[FILTER_OUT].name))) + return 0; + + if ((fl1->aslist[FILTER_OUT].name && !fl2->aslist[FILTER_OUT].name) + || (!fl1->aslist[FILTER_OUT].name && fl2->aslist[FILTER_OUT].name) + || (fl1->aslist[FILTER_OUT].name && fl2->aslist[FILTER_OUT].name + && strcmp(fl1->aslist[FILTER_OUT].name, + fl2->aslist[FILTER_OUT].name))) + return 0; + + if ((fl1->usmap.name && !fl2->usmap.name) + || (!fl1->usmap.name && fl2->usmap.name) + || (fl1->usmap.name && fl2->usmap.name + && strcmp(fl1->usmap.name, fl2->usmap.name))) + return 0; + + if ((pe1->default_rmap[afi][safi].name + && !pe2->default_rmap[afi][safi].name) + || (!pe1->default_rmap[afi][safi].name + && pe2->default_rmap[afi][safi].name) + || (pe1->default_rmap[afi][safi].name + && pe2->default_rmap[afi][safi].name + && strcmp(pe1->default_rmap[afi][safi].name, + pe2->default_rmap[afi][safi].name))) + return 0; + + if ((afi == AFI_IP6) && (pe1->shared_network != pe2->shared_network)) + return 0; + + if ((CHECK_FLAG(pe1->flags, PEER_FLAG_LONESOUL) + || CHECK_FLAG(pe1->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV) + || CHECK_FLAG(pe1->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_SM_OLD_RCV)) + && !sockunion_same(&pe1->su, &pe2->su)) + return 0; + + return 1; } -static void -peer_lonesoul_or_not (struct peer *peer, int set) +static void peer_lonesoul_or_not(struct peer *peer, int set) { - /* no change in status? */ - if (set == (CHECK_FLAG (peer->flags, PEER_FLAG_LONESOUL) > 0)) - return; + /* no change in status? */ + if (set == (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL) > 0)) + return; - if (set) - SET_FLAG (peer->flags, PEER_FLAG_LONESOUL); - else - UNSET_FLAG (peer->flags, PEER_FLAG_LONESOUL); + if (set) + SET_FLAG(peer->flags, PEER_FLAG_LONESOUL); + else + UNSET_FLAG(peer->flags, PEER_FLAG_LONESOUL); - update_group_adjust_peer_afs (peer); + update_group_adjust_peer_afs(peer); } /* @@ -515,319 +525,310 @@ peer_lonesoul_or_not (struct peer *peer, int set) * Returns the total number of packets enqueued to a subgroup. */ static unsigned int -subgroup_total_packets_enqueued (struct update_subgroup *subgrp) +subgroup_total_packets_enqueued(struct update_subgroup *subgrp) { - struct bpacket *pkt; + struct bpacket *pkt; - pkt = bpacket_queue_last (SUBGRP_PKTQ (subgrp)); + pkt = bpacket_queue_last(SUBGRP_PKTQ(subgrp)); - return pkt->ver - 1; + return pkt->ver - 1; } -static int -update_group_show_walkcb (struct update_group *updgrp, void *arg) +static int update_group_show_walkcb(struct update_group *updgrp, void *arg) { - struct updwalk_context *ctx = arg; - struct vty *vty; - struct update_subgroup *subgrp; - struct peer_af *paf; - struct bgp_filter *filter; - int match = 0; - - if (!ctx) - return CMD_SUCCESS; - - if (ctx->subgrp_id) - { - UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) + struct updwalk_context *ctx = arg; + struct vty *vty; + struct update_subgroup *subgrp; + struct peer_af *paf; + struct bgp_filter *filter; + int match = 0; + + if (!ctx) + return CMD_SUCCESS; + + if (ctx->subgrp_id) { + UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) + { + if (ctx->subgrp_id && (ctx->subgrp_id != subgrp->id)) + continue; + else { + match = 1; + break; + } + } + } else { + match = 1; + } + + if (!match) { + /* Since this routine is invoked from a walk, we cannot signal + * any */ + /* error here, can only return. */ + return CMD_SUCCESS; + } + + vty = ctx->vty; + + vty_out(vty, "Update-group %" PRIu64 ":\n", updgrp->id); + vty_out(vty, " Created: %s", timestamp_string(updgrp->uptime)); + filter = &updgrp->conf->filter[updgrp->afi][updgrp->safi]; + if (filter->map[RMAP_OUT].name) + vty_out(vty, " Outgoing route map: %s%s\n", + filter->map[RMAP_OUT].map ? "X" : "", + filter->map[RMAP_OUT].name); + vty_out(vty, " MRAI value (seconds): %d\n", updgrp->conf->v_routeadv); + if (updgrp->conf->change_local_as) + vty_out(vty, " Local AS %u%s%s\n", + updgrp->conf->change_local_as, + CHECK_FLAG(updgrp->conf->flags, + PEER_FLAG_LOCAL_AS_NO_PREPEND) + ? " no-prepend" + : "", + CHECK_FLAG(updgrp->conf->flags, + PEER_FLAG_LOCAL_AS_REPLACE_AS) + ? " replace-as" + : ""); + + UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) { - if (ctx->subgrp_id && (ctx->subgrp_id != subgrp->id)) - continue; - else - { - match = 1; - break; - } + if (ctx->subgrp_id && (ctx->subgrp_id != subgrp->id)) + continue; + vty_out(vty, "\n"); + vty_out(vty, " Update-subgroup %" PRIu64 ":\n", subgrp->id); + vty_out(vty, " Created: %s", + timestamp_string(subgrp->uptime)); + + if (subgrp->split_from.update_group_id + || subgrp->split_from.subgroup_id) { + vty_out(vty, " Split from group id: %" PRIu64 "\n", + subgrp->split_from.update_group_id); + vty_out(vty, + " Split from subgroup id: %" PRIu64 "\n", + subgrp->split_from.subgroup_id); + } + + vty_out(vty, " Join events: %u\n", subgrp->join_events); + vty_out(vty, " Prune events: %u\n", subgrp->prune_events); + vty_out(vty, " Merge events: %u\n", subgrp->merge_events); + vty_out(vty, " Split events: %u\n", subgrp->split_events); + vty_out(vty, " Update group switch events: %u\n", + subgrp->updgrp_switch_events); + vty_out(vty, " Peer refreshes combined: %u\n", + subgrp->peer_refreshes_combined); + vty_out(vty, " Merge checks triggered: %u\n", + subgrp->merge_checks_triggered); + vty_out(vty, " Version: %" PRIu64 "\n", subgrp->version); + vty_out(vty, " Packet queue length: %d\n", + bpacket_queue_length(SUBGRP_PKTQ(subgrp))); + vty_out(vty, " Total packets enqueued: %u\n", + subgroup_total_packets_enqueued(subgrp)); + vty_out(vty, " Packet queue high watermark: %d\n", + bpacket_queue_hwm_length(SUBGRP_PKTQ(subgrp))); + vty_out(vty, " Adj-out list count: %u\n", subgrp->adj_count); + vty_out(vty, " Advertise list: %s\n", + advertise_list_is_empty(subgrp) ? "empty" + : "not empty"); + vty_out(vty, " Flags: %s\n", + CHECK_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH) + ? "R" + : ""); + if (subgrp->peer_count > 0) { + vty_out(vty, " Peers:\n"); + SUBGRP_FOREACH_PEER(subgrp, paf) + vty_out(vty, " - %s\n", paf->peer->host); + } } - } - else - { - match = 1; - } - - if (!match) - { - /* Since this routine is invoked from a walk, we cannot signal any */ - /* error here, can only return. */ - return CMD_SUCCESS; - } - - vty = ctx->vty; - - vty_out (vty, "Update-group %" PRIu64 ":\n", updgrp->id); - vty_out (vty, " Created: %s", timestamp_string (updgrp->uptime)); - filter = &updgrp->conf->filter[updgrp->afi][updgrp->safi]; - if (filter->map[RMAP_OUT].name) - vty_out (vty, " Outgoing route map: %s%s\n", - filter->map[RMAP_OUT].map ? "X" : "", - filter->map[RMAP_OUT].name); - vty_out (vty, " MRAI value (seconds): %d\n", - updgrp->conf->v_routeadv); - if (updgrp->conf->change_local_as) - vty_out (vty, " Local AS %u%s%s\n", - updgrp->conf->change_local_as, - CHECK_FLAG (updgrp->conf->flags, - PEER_FLAG_LOCAL_AS_NO_PREPEND) ? " no-prepend" : "", - CHECK_FLAG(updgrp->conf->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ? " replace-as" : ""); - - UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) - { - if (ctx->subgrp_id && (ctx->subgrp_id != subgrp->id)) - continue; - vty_out (vty, "\n"); - vty_out (vty, " Update-subgroup %" PRIu64 ":\n", subgrp->id); - vty_out (vty, " Created: %s", timestamp_string (subgrp->uptime)); - - if (subgrp->split_from.update_group_id || subgrp->split_from.subgroup_id) - { - vty_out (vty, " Split from group id: %" PRIu64 "\n", - subgrp->split_from.update_group_id); - vty_out (vty, " Split from subgroup id: %" PRIu64 "\n", - subgrp->split_from.subgroup_id); - } - - vty_out (vty, " Join events: %u\n", subgrp->join_events); - vty_out (vty, " Prune events: %u\n", - subgrp->prune_events); - vty_out (vty, " Merge events: %u\n", - subgrp->merge_events); - vty_out (vty, " Split events: %u\n", - subgrp->split_events); - vty_out (vty, " Update group switch events: %u\n", - subgrp->updgrp_switch_events); - vty_out (vty, " Peer refreshes combined: %u\n", - subgrp->peer_refreshes_combined); - vty_out (vty, " Merge checks triggered: %u\n", - subgrp->merge_checks_triggered); - vty_out (vty, " Version: %" PRIu64 "\n", subgrp->version); - vty_out (vty, " Packet queue length: %d\n", - bpacket_queue_length(SUBGRP_PKTQ(subgrp))); - vty_out (vty, " Total packets enqueued: %u\n", - subgroup_total_packets_enqueued(subgrp)); - vty_out (vty, " Packet queue high watermark: %d\n", - bpacket_queue_hwm_length(SUBGRP_PKTQ(subgrp))); - vty_out (vty, " Adj-out list count: %u\n", - subgrp->adj_count); - vty_out (vty, " Advertise list: %s\n", - advertise_list_is_empty(subgrp) ? "empty" : "not empty"); - vty_out (vty, " Flags: %s\n", - CHECK_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH) ? "R" : ""); - if (subgrp->peer_count > 0) - { - vty_out (vty, " Peers:\n"); - SUBGRP_FOREACH_PEER (subgrp, paf) - vty_out (vty, " - %s\n", paf->peer->host); - } - } - return UPDWALK_CONTINUE; + return UPDWALK_CONTINUE; } /* * Helper function to show the packet queue for each subgroup of update group. * Will be constrained to a particular subgroup id if id !=0 */ -static int -updgrp_show_packet_queue_walkcb (struct update_group *updgrp, void *arg) +static int updgrp_show_packet_queue_walkcb(struct update_group *updgrp, + void *arg) { - struct updwalk_context *ctx = arg; - struct update_subgroup *subgrp; - struct vty *vty; - - vty = ctx->vty; - UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) - { - if (ctx->subgrp_id && (ctx->subgrp_id != subgrp->id)) - continue; - vty_out (vty, "update group %" PRIu64 ", subgroup %" PRIu64 "\n", updgrp->id, - subgrp->id); - bpacket_queue_show_vty (SUBGRP_PKTQ (subgrp), vty); - } - return UPDWALK_CONTINUE; + struct updwalk_context *ctx = arg; + struct update_subgroup *subgrp; + struct vty *vty; + + vty = ctx->vty; + UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) + { + if (ctx->subgrp_id && (ctx->subgrp_id != subgrp->id)) + continue; + vty_out(vty, "update group %" PRIu64 ", subgroup %" PRIu64 "\n", + updgrp->id, subgrp->id); + bpacket_queue_show_vty(SUBGRP_PKTQ(subgrp), vty); + } + return UPDWALK_CONTINUE; } /* * Show the packet queue for each subgroup of update group. Will be * constrained to a particular subgroup id if id !=0 */ -void -update_group_show_packet_queue (struct bgp *bgp, afi_t afi, safi_t safi, - struct vty *vty, uint64_t id) +void update_group_show_packet_queue(struct bgp *bgp, afi_t afi, safi_t safi, + struct vty *vty, uint64_t id) { - struct updwalk_context ctx; - - memset (&ctx, 0, sizeof (ctx)); - ctx.vty = vty; - ctx.subgrp_id = id; - ctx.flags = 0; - update_group_af_walk (bgp, afi, safi, updgrp_show_packet_queue_walkcb, - &ctx); + struct updwalk_context ctx; + + memset(&ctx, 0, sizeof(ctx)); + ctx.vty = vty; + ctx.subgrp_id = id; + ctx.flags = 0; + update_group_af_walk(bgp, afi, safi, updgrp_show_packet_queue_walkcb, + &ctx); } -static struct update_group * -update_group_find (struct peer_af *paf) +static struct update_group *update_group_find(struct peer_af *paf) { - struct update_group *updgrp; - struct update_group tmp; - struct peer tmp_conf; + struct update_group *updgrp; + struct update_group tmp; + struct peer tmp_conf; - if (!peer_established (PAF_PEER (paf))) - return NULL; + if (!peer_established(PAF_PEER(paf))) + return NULL; - memset (&tmp, 0, sizeof (tmp)); - memset (&tmp_conf, 0, sizeof (tmp_conf)); - tmp.conf = &tmp_conf; - peer2_updgrp_copy (&tmp, paf); + memset(&tmp, 0, sizeof(tmp)); + memset(&tmp_conf, 0, sizeof(tmp_conf)); + tmp.conf = &tmp_conf; + peer2_updgrp_copy(&tmp, paf); - updgrp = hash_lookup (paf->peer->bgp->update_groups[paf->afid], &tmp); - conf_release (&tmp_conf, paf->afi, paf->safi); - return updgrp; + updgrp = hash_lookup(paf->peer->bgp->update_groups[paf->afid], &tmp); + conf_release(&tmp_conf, paf->afi, paf->safi); + return updgrp; } -static struct update_group * -update_group_create (struct peer_af *paf) +static struct update_group *update_group_create(struct peer_af *paf) { - struct update_group *updgrp; - struct update_group tmp; - struct peer tmp_conf; + struct update_group *updgrp; + struct update_group tmp; + struct peer tmp_conf; - memset (&tmp, 0, sizeof (tmp)); - memset (&tmp_conf, 0, sizeof (tmp_conf)); - tmp.conf = &tmp_conf; - peer2_updgrp_copy (&tmp, paf); + memset(&tmp, 0, sizeof(tmp)); + memset(&tmp_conf, 0, sizeof(tmp_conf)); + tmp.conf = &tmp_conf; + peer2_updgrp_copy(&tmp, paf); - updgrp = hash_get (paf->peer->bgp->update_groups[paf->afid], &tmp, - updgrp_hash_alloc); - if (!updgrp) - return NULL; - update_group_checkin (updgrp); + updgrp = hash_get(paf->peer->bgp->update_groups[paf->afid], &tmp, + updgrp_hash_alloc); + if (!updgrp) + return NULL; + update_group_checkin(updgrp); - if (BGP_DEBUG (update_groups, UPDATE_GROUPS)) - zlog_debug ("create update group %" PRIu64, updgrp->id); + if (BGP_DEBUG(update_groups, UPDATE_GROUPS)) + zlog_debug("create update group %" PRIu64, updgrp->id); - UPDGRP_GLOBAL_STAT (updgrp, updgrps_created) += 1; + UPDGRP_GLOBAL_STAT(updgrp, updgrps_created) += 1; - conf_release(&tmp_conf, paf->afi, paf->safi); - return updgrp; + conf_release(&tmp_conf, paf->afi, paf->safi); + return updgrp; } -static void -update_group_delete (struct update_group *updgrp) +static void update_group_delete(struct update_group *updgrp) { - if (BGP_DEBUG (update_groups, UPDATE_GROUPS)) - zlog_debug ("delete update group %" PRIu64, updgrp->id); + if (BGP_DEBUG(update_groups, UPDATE_GROUPS)) + zlog_debug("delete update group %" PRIu64, updgrp->id); - UPDGRP_GLOBAL_STAT (updgrp, updgrps_deleted) += 1; + UPDGRP_GLOBAL_STAT(updgrp, updgrps_deleted) += 1; - hash_release (updgrp->bgp->update_groups[updgrp->afid], updgrp); - conf_release (updgrp->conf, updgrp->afi, updgrp->safi); + hash_release(updgrp->bgp->update_groups[updgrp->afid], updgrp); + conf_release(updgrp->conf, updgrp->afi, updgrp->safi); - if (updgrp->conf->host) - XFREE(MTYPE_BGP_PEER_HOST, updgrp->conf->host); - updgrp->conf->host = NULL; + if (updgrp->conf->host) + XFREE(MTYPE_BGP_PEER_HOST, updgrp->conf->host); + updgrp->conf->host = NULL; - if (updgrp->conf->ifname) - XFREE(MTYPE_BGP_PEER_IFNAME, updgrp->conf->ifname); + if (updgrp->conf->ifname) + XFREE(MTYPE_BGP_PEER_IFNAME, updgrp->conf->ifname); - XFREE (MTYPE_BGP_PEER, updgrp->conf); - XFREE (MTYPE_BGP_UPDGRP, updgrp); + XFREE(MTYPE_BGP_PEER, updgrp->conf); + XFREE(MTYPE_BGP_UPDGRP, updgrp); } -static void -update_group_add_subgroup (struct update_group *updgrp, - struct update_subgroup *subgrp) +static void update_group_add_subgroup(struct update_group *updgrp, + struct update_subgroup *subgrp) { - if (!updgrp || !subgrp) - return; + if (!updgrp || !subgrp) + return; - LIST_INSERT_HEAD (&(updgrp->subgrps), subgrp, updgrp_train); - subgrp->update_group = updgrp; + LIST_INSERT_HEAD(&(updgrp->subgrps), subgrp, updgrp_train); + subgrp->update_group = updgrp; } -static void -update_group_remove_subgroup (struct update_group *updgrp, - struct update_subgroup *subgrp) +static void update_group_remove_subgroup(struct update_group *updgrp, + struct update_subgroup *subgrp) { - if (!updgrp || !subgrp) - return; + if (!updgrp || !subgrp) + return; - LIST_REMOVE (subgrp, updgrp_train); - subgrp->update_group = NULL; - if (LIST_EMPTY (&(updgrp->subgrps))) - update_group_delete (updgrp); + LIST_REMOVE(subgrp, updgrp_train); + subgrp->update_group = NULL; + if (LIST_EMPTY(&(updgrp->subgrps))) + update_group_delete(updgrp); } static struct update_subgroup * -update_subgroup_create (struct update_group *updgrp) +update_subgroup_create(struct update_group *updgrp) { - struct update_subgroup *subgrp; + struct update_subgroup *subgrp; - subgrp = XCALLOC (MTYPE_BGP_UPD_SUBGRP, sizeof (struct update_subgroup)); - update_subgroup_checkin (subgrp, updgrp); - subgrp->v_coalesce = (UPDGRP_INST (updgrp))->coalesce_time; - sync_init (subgrp); - bpacket_queue_init (SUBGRP_PKTQ (subgrp)); - bpacket_queue_add (SUBGRP_PKTQ (subgrp), NULL, NULL); - TAILQ_INIT (&(subgrp->adjq)); - if (BGP_DEBUG (update_groups, UPDATE_GROUPS)) - zlog_debug ("create subgroup u%" PRIu64 ":s%" PRIu64, - updgrp->id, subgrp->id); + subgrp = XCALLOC(MTYPE_BGP_UPD_SUBGRP, sizeof(struct update_subgroup)); + update_subgroup_checkin(subgrp, updgrp); + subgrp->v_coalesce = (UPDGRP_INST(updgrp))->coalesce_time; + sync_init(subgrp); + bpacket_queue_init(SUBGRP_PKTQ(subgrp)); + bpacket_queue_add(SUBGRP_PKTQ(subgrp), NULL, NULL); + TAILQ_INIT(&(subgrp->adjq)); + if (BGP_DEBUG(update_groups, UPDATE_GROUPS)) + zlog_debug("create subgroup u%" PRIu64 ":s%" PRIu64, updgrp->id, + subgrp->id); - update_group_add_subgroup (updgrp, subgrp); + update_group_add_subgroup(updgrp, subgrp); - UPDGRP_INCR_STAT (updgrp, subgrps_created); + UPDGRP_INCR_STAT(updgrp, subgrps_created); - return subgrp; + return subgrp; } -static void -update_subgroup_delete (struct update_subgroup *subgrp) +static void update_subgroup_delete(struct update_subgroup *subgrp) { - if (!subgrp) - return; + if (!subgrp) + return; - if (subgrp->update_group) - UPDGRP_INCR_STAT (subgrp->update_group, subgrps_deleted); + if (subgrp->update_group) + UPDGRP_INCR_STAT(subgrp->update_group, subgrps_deleted); - if (subgrp->t_merge_check) - THREAD_OFF (subgrp->t_merge_check); + if (subgrp->t_merge_check) + THREAD_OFF(subgrp->t_merge_check); - if (subgrp->t_coalesce) - THREAD_TIMER_OFF (subgrp->t_coalesce); + if (subgrp->t_coalesce) + THREAD_TIMER_OFF(subgrp->t_coalesce); - bpacket_queue_cleanup (SUBGRP_PKTQ (subgrp)); - subgroup_clear_table (subgrp); + bpacket_queue_cleanup(SUBGRP_PKTQ(subgrp)); + subgroup_clear_table(subgrp); - if (subgrp->t_coalesce) - THREAD_TIMER_OFF (subgrp->t_coalesce); - sync_delete (subgrp); + if (subgrp->t_coalesce) + THREAD_TIMER_OFF(subgrp->t_coalesce); + sync_delete(subgrp); - if (BGP_DEBUG (update_groups, UPDATE_GROUPS)) - zlog_debug ("delete subgroup u%" PRIu64 ":s%" PRIu64, - subgrp->update_group->id, subgrp->id); + if (BGP_DEBUG(update_groups, UPDATE_GROUPS)) + zlog_debug("delete subgroup u%" PRIu64 ":s%" PRIu64, + subgrp->update_group->id, subgrp->id); - update_group_remove_subgroup (subgrp->update_group, subgrp); + update_group_remove_subgroup(subgrp->update_group, subgrp); - XFREE (MTYPE_BGP_UPD_SUBGRP, subgrp); + XFREE(MTYPE_BGP_UPD_SUBGRP, subgrp); } -void -update_subgroup_inherit_info (struct update_subgroup *to, - struct update_subgroup *from) +void update_subgroup_inherit_info(struct update_subgroup *to, + struct update_subgroup *from) { - if (!to || !from) - return; + if (!to || !from) + return; - to->sflags = from->sflags; + to->sflags = from->sflags; } /* @@ -837,18 +838,17 @@ update_subgroup_inherit_info (struct update_subgroup *to, * * Returns TRUE if the subgroup was deleted. */ -static int -update_subgroup_check_delete (struct update_subgroup *subgrp) +static int update_subgroup_check_delete(struct update_subgroup *subgrp) { - if (!subgrp) - return 0; + if (!subgrp) + return 0; - if (!LIST_EMPTY (&(subgrp->peers))) - return 0; + if (!LIST_EMPTY(&(subgrp->peers))) + return 0; - update_subgroup_delete (subgrp); + update_subgroup_delete(subgrp); - return 1; + return 1; } /* @@ -857,45 +857,41 @@ update_subgroup_check_delete (struct update_subgroup *subgrp) * @param send_enqueued_packets If true all currently enqueued packets will * also be sent to the peer. */ -static void -update_subgroup_add_peer (struct update_subgroup *subgrp, struct peer_af *paf, - int send_enqueued_pkts) +static void update_subgroup_add_peer(struct update_subgroup *subgrp, + struct peer_af *paf, + int send_enqueued_pkts) { - struct bpacket *pkt; + struct bpacket *pkt; - if (!subgrp || !paf) - return; + if (!subgrp || !paf) + return; - LIST_INSERT_HEAD (&(subgrp->peers), paf, subgrp_train); - paf->subgroup = subgrp; - subgrp->peer_count++; + LIST_INSERT_HEAD(&(subgrp->peers), paf, subgrp_train); + paf->subgroup = subgrp; + subgrp->peer_count++; - if (bgp_debug_peer_updout_enabled(paf->peer->host)) - { - UPDGRP_PEER_DBG_EN(subgrp->update_group); - } + if (bgp_debug_peer_updout_enabled(paf->peer->host)) { + UPDGRP_PEER_DBG_EN(subgrp->update_group); + } - SUBGRP_INCR_STAT (subgrp, join_events); + SUBGRP_INCR_STAT(subgrp, join_events); - if (send_enqueued_pkts) - { - pkt = bpacket_queue_first (SUBGRP_PKTQ (subgrp)); - } - else - { + if (send_enqueued_pkts) { + pkt = bpacket_queue_first(SUBGRP_PKTQ(subgrp)); + } else { - /* - * Hang the peer off of the last, placeholder, packet in the - * queue. This means it won't see any of the packets that are - * currently the queue. - */ - pkt = bpacket_queue_last (SUBGRP_PKTQ (subgrp)); - assert (pkt->buffer == NULL); - } + /* + * Hang the peer off of the last, placeholder, packet in the + * queue. This means it won't see any of the packets that are + * currently the queue. + */ + pkt = bpacket_queue_last(SUBGRP_PKTQ(subgrp)); + assert(pkt->buffer == NULL); + } - bpacket_add_peer (pkt, paf); + bpacket_add_peer(pkt, paf); - bpacket_queue_sanity_check (SUBGRP_PKTQ (subgrp)); + bpacket_queue_sanity_check(SUBGRP_PKTQ(subgrp)); } /* @@ -907,82 +903,78 @@ update_subgroup_add_peer (struct update_subgroup *subgrp, struct peer_af *paf, * * @see update_subgroup_remove_peer */ -static void -update_subgroup_remove_peer_internal (struct update_subgroup *subgrp, - struct peer_af *paf) +static void update_subgroup_remove_peer_internal(struct update_subgroup *subgrp, + struct peer_af *paf) { - assert (subgrp && paf); + assert(subgrp && paf); - if (bgp_debug_peer_updout_enabled(paf->peer->host)) - { - UPDGRP_PEER_DBG_DIS(subgrp->update_group); - } + if (bgp_debug_peer_updout_enabled(paf->peer->host)) { + UPDGRP_PEER_DBG_DIS(subgrp->update_group); + } - bpacket_queue_remove_peer (paf); - LIST_REMOVE (paf, subgrp_train); - paf->subgroup = NULL; - subgrp->peer_count--; + bpacket_queue_remove_peer(paf); + LIST_REMOVE(paf, subgrp_train); + paf->subgroup = NULL; + subgrp->peer_count--; - SUBGRP_INCR_STAT (subgrp, prune_events); + SUBGRP_INCR_STAT(subgrp, prune_events); } /* * update_subgroup_remove_peer */ -void -update_subgroup_remove_peer (struct update_subgroup *subgrp, - struct peer_af *paf) +void update_subgroup_remove_peer(struct update_subgroup *subgrp, + struct peer_af *paf) { - if (!subgrp || !paf) - return; + if (!subgrp || !paf) + return; - update_subgroup_remove_peer_internal (subgrp, paf); + update_subgroup_remove_peer_internal(subgrp, paf); - if (update_subgroup_check_delete (subgrp)) - return; + if (update_subgroup_check_delete(subgrp)) + return; - /* - * The deletion of the peer may have caused some packets to be - * deleted from the subgroup packet queue. Check if the subgroup can - * be merged now. - */ - update_subgroup_check_merge (subgrp, "removed peer from subgroup"); + /* + * The deletion of the peer may have caused some packets to be + * deleted from the subgroup packet queue. Check if the subgroup can + * be merged now. + */ + update_subgroup_check_merge(subgrp, "removed peer from subgroup"); } -static struct update_subgroup * -update_subgroup_find (struct update_group *updgrp, struct peer_af *paf) +static struct update_subgroup *update_subgroup_find(struct update_group *updgrp, + struct peer_af *paf) { - struct update_subgroup *subgrp = NULL; - uint64_t version; - - if (paf->subgroup) - { - assert (0); - return NULL; - } - else - version = 0; - - if (!peer_established (PAF_PEER (paf))) - return NULL; - - UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) - { - if (subgrp->version != version || - CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) - continue; - - /* - * The version number is not meaningful on a subgroup that needs - * a refresh. - */ - if (update_subgroup_needs_refresh (subgrp)) - continue; - - break; - } - - return subgrp; + struct update_subgroup *subgrp = NULL; + uint64_t version; + + if (paf->subgroup) { + assert(0); + return NULL; + } else + version = 0; + + if (!peer_established(PAF_PEER(paf))) + return NULL; + + UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) + { + if (subgrp->version != version + || CHECK_FLAG(subgrp->sflags, + SUBGRP_STATUS_DEFAULT_ORIGINATE)) + continue; + + /* + * The version number is not meaningful on a subgroup that needs + * a refresh. + */ + if (update_subgroup_needs_refresh(subgrp)) + continue; + + break; + } + + return subgrp; } /* @@ -991,32 +983,31 @@ update_subgroup_find (struct update_group *updgrp, struct peer_af *paf) * Returns TRUE if this subgroup is in a state that allows it to be * merged into another subgroup. */ -static int -update_subgroup_ready_for_merge (struct update_subgroup *subgrp) +static int update_subgroup_ready_for_merge(struct update_subgroup *subgrp) { - /* - * Not ready if there are any encoded packets waiting to be written - * out to peers. - */ - if (!bpacket_queue_is_empty (SUBGRP_PKTQ (subgrp))) - return 0; - - /* - * Not ready if there enqueued updates waiting to be encoded. - */ - if (!advertise_list_is_empty (subgrp)) - return 0; - - /* - * Don't attempt to merge a subgroup that needs a refresh. For one, - * we can't determine if the adj_out of such a group matches that of - * another group. - */ - if (update_subgroup_needs_refresh (subgrp)) - return 0; - - return 1; + /* + * Not ready if there are any encoded packets waiting to be written + * out to peers. + */ + if (!bpacket_queue_is_empty(SUBGRP_PKTQ(subgrp))) + return 0; + + /* + * Not ready if there enqueued updates waiting to be encoded. + */ + if (!advertise_list_is_empty(subgrp)) + return 0; + + /* + * Don't attempt to merge a subgroup that needs a refresh. For one, + * we can't determine if the adj_out of such a group matches that of + * another group. + */ + if (update_subgroup_needs_refresh(subgrp)) + return 0; + + return 1; } /* @@ -1025,29 +1016,28 @@ update_subgroup_ready_for_merge (struct update_subgroup *subgrp) * Returns TRUE if the first subgroup can merge into the second * subgroup. */ -static int -update_subgroup_can_merge_into (struct update_subgroup *subgrp, - struct update_subgroup *target) +static int update_subgroup_can_merge_into(struct update_subgroup *subgrp, + struct update_subgroup *target) { - if (subgrp == target) - return 0; + if (subgrp == target) + return 0; - /* - * Both must have processed the BRIB to the same point in order to - * be merged. - */ - if (subgrp->version != target->version) - return 0; + /* + * Both must have processed the BRIB to the same point in order to + * be merged. + */ + if (subgrp->version != target->version) + return 0; - if (CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE) != - CHECK_FLAG(target->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) - return 0; + if (CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE) + != CHECK_FLAG(target->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) + return 0; - if (subgrp->adj_count != target->adj_count) - return 0; + if (subgrp->adj_count != target->adj_count) + return 0; - return update_subgroup_ready_for_merge (target); + return update_subgroup_ready_for_merge(target); } /* @@ -1055,44 +1045,47 @@ update_subgroup_can_merge_into (struct update_subgroup *subgrp, * * Merge the first subgroup into the second one. */ -static void -update_subgroup_merge (struct update_subgroup *subgrp, - struct update_subgroup *target, const char *reason) +static void update_subgroup_merge(struct update_subgroup *subgrp, + struct update_subgroup *target, + const char *reason) { - struct peer_af *paf; - int result; - int peer_count; + struct peer_af *paf; + int result; + int peer_count; - assert (subgrp->adj_count == target->adj_count); + assert(subgrp->adj_count == target->adj_count); - peer_count = subgrp->peer_count; + peer_count = subgrp->peer_count; - while (1) - { - paf = LIST_FIRST (&subgrp->peers); - if (!paf) - break; + while (1) { + paf = LIST_FIRST(&subgrp->peers); + if (!paf) + break; - update_subgroup_remove_peer_internal (subgrp, paf); + update_subgroup_remove_peer_internal(subgrp, paf); - /* - * Add the peer to the target subgroup, while making sure that - * any currently enqueued packets won't be sent to it. Enqueued - * packets could, for example, result in an unnecessary withdraw - * followed by an advertise. - */ - update_subgroup_add_peer (target, paf, 0); - } + /* + * Add the peer to the target subgroup, while making sure that + * any currently enqueued packets won't be sent to it. Enqueued + * packets could, for example, result in an unnecessary withdraw + * followed by an advertise. + */ + update_subgroup_add_peer(target, paf, 0); + } - SUBGRP_INCR_STAT (target, merge_events); + SUBGRP_INCR_STAT(target, merge_events); - if (BGP_DEBUG (update_groups, UPDATE_GROUPS)) - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " (%d peers) merged into u%" PRIu64 ":s%" PRIu64 ", " - "trigger: %s", subgrp->update_group->id, subgrp->id, peer_count, - target->update_group->id, target->id, reason ? reason : "unknown"); + if (BGP_DEBUG(update_groups, UPDATE_GROUPS)) + zlog_debug("u%" PRIu64 ":s%" PRIu64 + " (%d peers) merged into u%" PRIu64 ":s%" PRIu64 + ", " + "trigger: %s", + subgrp->update_group->id, subgrp->id, peer_count, + target->update_group->id, target->id, + reason ? reason : "unknown"); - result = update_subgroup_check_delete (subgrp); - assert (result); + result = update_subgroup_check_delete(subgrp); + assert(result); } /* @@ -1103,45 +1096,43 @@ update_subgroup_merge (struct update_subgroup *subgrp, * Returns TRUE if the subgroup has been merged. The subgroup pointer * should not be accessed in this case. */ -int -update_subgroup_check_merge (struct update_subgroup *subgrp, - const char *reason) +int update_subgroup_check_merge(struct update_subgroup *subgrp, + const char *reason) { - struct update_subgroup *target; + struct update_subgroup *target; - if (!update_subgroup_ready_for_merge (subgrp)) - return 0; + if (!update_subgroup_ready_for_merge(subgrp)) + return 0; - /* - * Look for a subgroup to merge into. - */ - UPDGRP_FOREACH_SUBGRP (subgrp->update_group, target) - { - if (update_subgroup_can_merge_into (subgrp, target)) - break; - } + /* + * Look for a subgroup to merge into. + */ + UPDGRP_FOREACH_SUBGRP(subgrp->update_group, target) + { + if (update_subgroup_can_merge_into(subgrp, target)) + break; + } - if (!target) - return 0; + if (!target) + return 0; - update_subgroup_merge (subgrp, target, reason); - return 1; + update_subgroup_merge(subgrp, target, reason); + return 1; } - /* - * update_subgroup_merge_check_thread_cb - */ -static int -update_subgroup_merge_check_thread_cb (struct thread *thread) +/* +* update_subgroup_merge_check_thread_cb +*/ +static int update_subgroup_merge_check_thread_cb(struct thread *thread) { - struct update_subgroup *subgrp; + struct update_subgroup *subgrp; - subgrp = THREAD_ARG (thread); + subgrp = THREAD_ARG(thread); - subgrp->t_merge_check = NULL; + subgrp->t_merge_check = NULL; - update_subgroup_check_merge (subgrp, "triggered merge check"); - return 0; + update_subgroup_check_merge(subgrp, "triggered merge check"); + return 0; } /* @@ -1154,23 +1145,22 @@ update_subgroup_merge_check_thread_cb (struct thread *thread) * * Returns TRUE if a merge check will be performed shortly. */ -int -update_subgroup_trigger_merge_check (struct update_subgroup *subgrp, - int force) +int update_subgroup_trigger_merge_check(struct update_subgroup *subgrp, + int force) { - if (subgrp->t_merge_check) - return 1; + if (subgrp->t_merge_check) + return 1; - if (!force && !update_subgroup_ready_for_merge (subgrp)) - return 0; + if (!force && !update_subgroup_ready_for_merge(subgrp)) + return 0; - subgrp->t_merge_check = NULL; - thread_add_timer_msec (bm->master, update_subgroup_merge_check_thread_cb, subgrp, - 0, &subgrp->t_merge_check); + subgrp->t_merge_check = NULL; + thread_add_timer_msec(bm->master, update_subgroup_merge_check_thread_cb, + subgrp, 0, &subgrp->t_merge_check); - SUBGRP_INCR_STAT (subgrp, merge_checks_triggered); + SUBGRP_INCR_STAT(subgrp, merge_checks_triggered); - return 1; + return 1; } /* @@ -1180,20 +1170,21 @@ update_subgroup_trigger_merge_check (struct update_subgroup *subgrp, * routes) from one subgroup to another. It assumes that the adj out * of the target subgroup is empty. */ -static void -update_subgroup_copy_adj_out (struct update_subgroup *source, - struct update_subgroup *dest) +static void update_subgroup_copy_adj_out(struct update_subgroup *source, + struct update_subgroup *dest) { - struct bgp_adj_out *aout, *aout_copy; - - SUBGRP_FOREACH_ADJ (source, aout) - { - /* - * Copy the adj out. - */ - aout_copy = bgp_adj_out_alloc (dest, aout->rn, aout->addpath_tx_id); - aout_copy->attr = aout->attr ? bgp_attr_refcount (aout->attr) : NULL; - } + struct bgp_adj_out *aout, *aout_copy; + + SUBGRP_FOREACH_ADJ(source, aout) + { + /* + * Copy the adj out. + */ + aout_copy = + bgp_adj_out_alloc(dest, aout->rn, aout->addpath_tx_id); + aout_copy->attr = + aout->attr ? bgp_attr_refcount(aout->attr) : NULL; + } } /* @@ -1204,121 +1195,114 @@ update_subgroup_copy_adj_out (struct update_subgroup *source, * * Returns the number of packets copied. */ -static int -update_subgroup_copy_packets (struct update_subgroup *dest, - struct bpacket *pkt) +static int update_subgroup_copy_packets(struct update_subgroup *dest, + struct bpacket *pkt) { - int count; - - count = 0; - while (pkt && pkt->buffer) - { - bpacket_queue_add (SUBGRP_PKTQ (dest), stream_dup (pkt->buffer), - &pkt->arr); - count++; - pkt = bpacket_next (pkt); - } + int count; + + count = 0; + while (pkt && pkt->buffer) { + bpacket_queue_add(SUBGRP_PKTQ(dest), stream_dup(pkt->buffer), + &pkt->arr); + count++; + pkt = bpacket_next(pkt); + } - bpacket_queue_sanity_check (SUBGRP_PKTQ (dest)); + bpacket_queue_sanity_check(SUBGRP_PKTQ(dest)); - return count; + return count; } -static int -updgrp_prefix_list_update (struct update_group *updgrp, const char *name) +static int updgrp_prefix_list_update(struct update_group *updgrp, + const char *name) { - struct peer *peer; - struct bgp_filter *filter; - - peer = UPDGRP_PEER (updgrp); - filter = &peer->filter[UPDGRP_AFI(updgrp)][UPDGRP_SAFI(updgrp)]; - - if (PREFIX_LIST_OUT_NAME(filter) && - (strcmp (name, PREFIX_LIST_OUT_NAME(filter)) == 0)) - { - PREFIX_LIST_OUT(filter) = - prefix_list_lookup (UPDGRP_AFI(updgrp), PREFIX_LIST_OUT_NAME(filter)); - return 1; - } - return 0; + struct peer *peer; + struct bgp_filter *filter; + + peer = UPDGRP_PEER(updgrp); + filter = &peer->filter[UPDGRP_AFI(updgrp)][UPDGRP_SAFI(updgrp)]; + + if (PREFIX_LIST_OUT_NAME(filter) + && (strcmp(name, PREFIX_LIST_OUT_NAME(filter)) == 0)) { + PREFIX_LIST_OUT(filter) = prefix_list_lookup( + UPDGRP_AFI(updgrp), PREFIX_LIST_OUT_NAME(filter)); + return 1; + } + return 0; } -static int -updgrp_filter_list_update (struct update_group *updgrp, const char *name) +static int updgrp_filter_list_update(struct update_group *updgrp, + const char *name) { - struct peer *peer; - struct bgp_filter *filter; - - peer = UPDGRP_PEER (updgrp); - filter = &peer->filter[UPDGRP_AFI(updgrp)][UPDGRP_SAFI(updgrp)]; - - if (FILTER_LIST_OUT_NAME(filter) && - (strcmp (name, FILTER_LIST_OUT_NAME(filter)) == 0)) - { - FILTER_LIST_OUT(filter) = as_list_lookup (FILTER_LIST_OUT_NAME(filter)); - return 1; - } - return 0; + struct peer *peer; + struct bgp_filter *filter; + + peer = UPDGRP_PEER(updgrp); + filter = &peer->filter[UPDGRP_AFI(updgrp)][UPDGRP_SAFI(updgrp)]; + + if (FILTER_LIST_OUT_NAME(filter) + && (strcmp(name, FILTER_LIST_OUT_NAME(filter)) == 0)) { + FILTER_LIST_OUT(filter) = + as_list_lookup(FILTER_LIST_OUT_NAME(filter)); + return 1; + } + return 0; } -static int -updgrp_distribute_list_update (struct update_group *updgrp, const char *name) +static int updgrp_distribute_list_update(struct update_group *updgrp, + const char *name) { - struct peer *peer; - struct bgp_filter *filter; - - peer = UPDGRP_PEER(updgrp); - filter = &peer->filter[UPDGRP_AFI(updgrp)][UPDGRP_SAFI(updgrp)]; - - if (DISTRIBUTE_OUT_NAME(filter) && - (strcmp (name, DISTRIBUTE_OUT_NAME(filter)) == 0)) - { - DISTRIBUTE_OUT(filter) = access_list_lookup(UPDGRP_AFI(updgrp), - DISTRIBUTE_OUT_NAME(filter)); - return 1; - } - return 0; + struct peer *peer; + struct bgp_filter *filter; + + peer = UPDGRP_PEER(updgrp); + filter = &peer->filter[UPDGRP_AFI(updgrp)][UPDGRP_SAFI(updgrp)]; + + if (DISTRIBUTE_OUT_NAME(filter) + && (strcmp(name, DISTRIBUTE_OUT_NAME(filter)) == 0)) { + DISTRIBUTE_OUT(filter) = access_list_lookup( + UPDGRP_AFI(updgrp), DISTRIBUTE_OUT_NAME(filter)); + return 1; + } + return 0; } -static int -updgrp_route_map_update (struct update_group *updgrp, const char *name, - int *def_rmap_changed) +static int updgrp_route_map_update(struct update_group *updgrp, + const char *name, int *def_rmap_changed) { - struct peer *peer; - struct bgp_filter *filter; - int changed = 0; - afi_t afi; - safi_t safi; - - peer = UPDGRP_PEER (updgrp); - afi = UPDGRP_AFI (updgrp); - safi = UPDGRP_SAFI (updgrp); - filter = &peer->filter[afi][safi]; - - if (ROUTE_MAP_OUT_NAME(filter) && - (strcmp (name, ROUTE_MAP_OUT_NAME(filter)) == 0)) - { - ROUTE_MAP_OUT(filter) = route_map_lookup_by_name (name); - - changed = 1; - } - - if (UNSUPPRESS_MAP_NAME(filter) && - (strcmp (name, UNSUPPRESS_MAP_NAME(filter)) == 0)) - { - UNSUPPRESS_MAP(filter) = route_map_lookup_by_name (name); - changed = 1; - } - - /* process default-originate route-map */ - if (peer->default_rmap[afi][safi].name && - (strcmp (name, peer->default_rmap[afi][safi].name) == 0)) - { - peer->default_rmap[afi][safi].map = route_map_lookup_by_name (name); - if (def_rmap_changed) - *def_rmap_changed = 1; - } - return changed; + struct peer *peer; + struct bgp_filter *filter; + int changed = 0; + afi_t afi; + safi_t safi; + + peer = UPDGRP_PEER(updgrp); + afi = UPDGRP_AFI(updgrp); + safi = UPDGRP_SAFI(updgrp); + filter = &peer->filter[afi][safi]; + + if (ROUTE_MAP_OUT_NAME(filter) + && (strcmp(name, ROUTE_MAP_OUT_NAME(filter)) == 0)) { + ROUTE_MAP_OUT(filter) = route_map_lookup_by_name(name); + + changed = 1; + } + + if (UNSUPPRESS_MAP_NAME(filter) + && (strcmp(name, UNSUPPRESS_MAP_NAME(filter)) == 0)) { + UNSUPPRESS_MAP(filter) = route_map_lookup_by_name(name); + changed = 1; + } + + /* process default-originate route-map */ + if (peer->default_rmap[afi][safi].name + && (strcmp(name, peer->default_rmap[afi][safi].name) == 0)) { + peer->default_rmap[afi][safi].map = + route_map_lookup_by_name(name); + if (def_rmap_changed) + *def_rmap_changed = 1; + } + return changed; } /* @@ -1328,97 +1312,103 @@ updgrp_route_map_update (struct update_group *updgrp, const char *name, * filter-list or prefix-list or distribute-list. * Trigger update generation accordingly. */ -static int -updgrp_policy_update_walkcb (struct update_group *updgrp, void *arg) +static int updgrp_policy_update_walkcb(struct update_group *updgrp, void *arg) { - struct updwalk_context *ctx = arg; - struct update_subgroup *subgrp; - int changed = 0; - int def_changed = 0; - - if (!updgrp || !ctx || !ctx->policy_name) - return UPDWALK_CONTINUE; - - switch (ctx->policy_type) { - case BGP_POLICY_ROUTE_MAP: - changed = updgrp_route_map_update(updgrp, ctx->policy_name, &def_changed); - break; - case BGP_POLICY_FILTER_LIST: - changed = updgrp_filter_list_update(updgrp, ctx->policy_name); - break; - case BGP_POLICY_PREFIX_LIST: - changed = updgrp_prefix_list_update(updgrp, ctx->policy_name); - break; - case BGP_POLICY_DISTRIBUTE_LIST: - changed = updgrp_distribute_list_update(updgrp, ctx->policy_name); - break; - default: - break; - } - - /* If not doing route update, return after updating "config" */ - if (!ctx->policy_route_update) - return UPDWALK_CONTINUE; - - /* If nothing has changed, return after updating "config" */ - if (!changed && !def_changed) - return UPDWALK_CONTINUE; - - /* - * If something has changed, at the beginning of a route-map modification - * event, mark each subgroup's needs-refresh bit. For one, it signals to - * whoever that the subgroup needs a refresh. Second, it prevents premature - * merge of this subgroup with another before a complete (outbound) refresh. - */ - if (ctx->policy_event_start_flag) - { - UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) - { - update_subgroup_set_needs_refresh(subgrp, 1); - } - return UPDWALK_CONTINUE; - } - - UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) - { - if (changed) - { - if (bgp_debug_update(NULL, NULL, updgrp, 0)) - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " announcing routes upon policy %s (type %d) change", - updgrp->id, subgrp->id, ctx->policy_name, ctx->policy_type); - subgroup_announce_route (subgrp); - } - if (def_changed) - { - if (bgp_debug_update(NULL, NULL, updgrp, 0)) - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " announcing default upon default routemap %s change", - updgrp->id, subgrp->id, ctx->policy_name); - subgroup_default_originate (subgrp, 0); - } - update_subgroup_set_needs_refresh(subgrp, 0); - } - return UPDWALK_CONTINUE; + struct updwalk_context *ctx = arg; + struct update_subgroup *subgrp; + int changed = 0; + int def_changed = 0; + + if (!updgrp || !ctx || !ctx->policy_name) + return UPDWALK_CONTINUE; + + switch (ctx->policy_type) { + case BGP_POLICY_ROUTE_MAP: + changed = updgrp_route_map_update(updgrp, ctx->policy_name, + &def_changed); + break; + case BGP_POLICY_FILTER_LIST: + changed = updgrp_filter_list_update(updgrp, ctx->policy_name); + break; + case BGP_POLICY_PREFIX_LIST: + changed = updgrp_prefix_list_update(updgrp, ctx->policy_name); + break; + case BGP_POLICY_DISTRIBUTE_LIST: + changed = + updgrp_distribute_list_update(updgrp, ctx->policy_name); + break; + default: + break; + } + + /* If not doing route update, return after updating "config" */ + if (!ctx->policy_route_update) + return UPDWALK_CONTINUE; + + /* If nothing has changed, return after updating "config" */ + if (!changed && !def_changed) + return UPDWALK_CONTINUE; + + /* + * If something has changed, at the beginning of a route-map + * modification + * event, mark each subgroup's needs-refresh bit. For one, it signals to + * whoever that the subgroup needs a refresh. Second, it prevents + * premature + * merge of this subgroup with another before a complete (outbound) + * refresh. + */ + if (ctx->policy_event_start_flag) { + UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) + { + update_subgroup_set_needs_refresh(subgrp, 1); + } + return UPDWALK_CONTINUE; + } + + UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) + { + if (changed) { + if (bgp_debug_update(NULL, NULL, updgrp, 0)) + zlog_debug( + "u%" PRIu64 ":s%" PRIu64 + " announcing routes upon policy %s (type %d) change", + updgrp->id, subgrp->id, + ctx->policy_name, ctx->policy_type); + subgroup_announce_route(subgrp); + } + if (def_changed) { + if (bgp_debug_update(NULL, NULL, updgrp, 0)) + zlog_debug( + "u%" PRIu64 ":s%" PRIu64 + " announcing default upon default routemap %s change", + updgrp->id, subgrp->id, + ctx->policy_name); + subgroup_default_originate(subgrp, 0); + } + update_subgroup_set_needs_refresh(subgrp, 0); + } + return UPDWALK_CONTINUE; } -static int -update_group_walkcb (struct hash_backet *backet, void *arg) +static int update_group_walkcb(struct hash_backet *backet, void *arg) { - struct update_group *updgrp = backet->data; - struct updwalk_context *wctx = arg; - int ret = (*wctx->cb) (updgrp, wctx->context); - return ret; + struct update_group *updgrp = backet->data; + struct updwalk_context *wctx = arg; + int ret = (*wctx->cb)(updgrp, wctx->context); + return ret; } -static int -update_group_periodic_merge_walkcb (struct update_group *updgrp, void *arg) +static int update_group_periodic_merge_walkcb(struct update_group *updgrp, + void *arg) { - struct update_subgroup *subgrp; - struct update_subgroup *tmp_subgrp; - const char *reason = arg; + struct update_subgroup *subgrp; + struct update_subgroup *tmp_subgrp; + const char *reason = arg; - UPDGRP_FOREACH_SUBGRP_SAFE (updgrp, subgrp, tmp_subgrp) - update_subgroup_check_merge (subgrp, reason); - return UPDWALK_CONTINUE; + UPDGRP_FOREACH_SUBGRP_SAFE(updgrp, subgrp, tmp_subgrp) + update_subgroup_check_merge(subgrp, reason); + return UPDWALK_CONTINUE; } /******************** @@ -1440,20 +1430,20 @@ update_group_periodic_merge_walkcb (struct update_group *updgrp, void *arg) * over multiple statements. Useful to set dirty flag on * update groups. */ -void -update_group_policy_update (struct bgp *bgp, bgp_policy_type_e ptype, - const char *pname, int route_update, int start_event) +void update_group_policy_update(struct bgp *bgp, bgp_policy_type_e ptype, + const char *pname, int route_update, + int start_event) { - struct updwalk_context ctx; + struct updwalk_context ctx; - memset (&ctx, 0, sizeof (ctx)); - ctx.policy_type = ptype; - ctx.policy_name = pname; - ctx.policy_route_update = route_update; - ctx.policy_event_start_flag = start_event; - ctx.flags = 0; + memset(&ctx, 0, sizeof(ctx)); + ctx.policy_type = ptype; + ctx.policy_name = pname; + ctx.policy_route_update = route_update; + ctx.policy_event_start_flag = start_event; + ctx.flags = 0; - update_group_walk (bgp, updgrp_policy_update_walkcb, &ctx); + update_group_walk(bgp, updgrp_policy_update_walkcb, &ctx); } /* @@ -1462,131 +1452,129 @@ update_group_policy_update (struct bgp *bgp, bgp_policy_type_e ptype, * Ensure that the given peer is in a subgroup of its own in the * specified update group. */ -void -update_subgroup_split_peer (struct peer_af *paf, struct update_group *updgrp) +void update_subgroup_split_peer(struct peer_af *paf, + struct update_group *updgrp) { - struct update_subgroup *old_subgrp, *subgrp; - uint64_t old_id; - - - old_subgrp = paf->subgroup; - - if (!updgrp) - updgrp = old_subgrp->update_group; - - /* - * If the peer is alone in its subgroup, reuse the existing - * subgroup. - */ - if (old_subgrp->peer_count == 1) - { - if (updgrp == old_subgrp->update_group) - return; + struct update_subgroup *old_subgrp, *subgrp; + uint64_t old_id; + + + old_subgrp = paf->subgroup; + + if (!updgrp) + updgrp = old_subgrp->update_group; + + /* + * If the peer is alone in its subgroup, reuse the existing + * subgroup. + */ + if (old_subgrp->peer_count == 1) { + if (updgrp == old_subgrp->update_group) + return; + + subgrp = old_subgrp; + old_id = old_subgrp->update_group->id; + + if (bgp_debug_peer_updout_enabled(paf->peer->host)) { + UPDGRP_PEER_DBG_DIS(old_subgrp->update_group); + } + + update_group_remove_subgroup(old_subgrp->update_group, + old_subgrp); + update_group_add_subgroup(updgrp, subgrp); + + if (bgp_debug_peer_updout_enabled(paf->peer->host)) { + UPDGRP_PEER_DBG_EN(updgrp); + } + if (BGP_DEBUG(update_groups, UPDATE_GROUPS)) + zlog_debug("u%" PRIu64 ":s%" PRIu64 + " peer %s moved to u%" PRIu64 ":s%" PRIu64, + old_id, subgrp->id, paf->peer->host, + updgrp->id, subgrp->id); + + /* + * The state of the subgroup (adj_out, advs, packet queue etc) + * is consistent internally, but may not be identical to other + * subgroups in the new update group even if the version number + * matches up. Make sure a full refresh is done before the + * subgroup is merged with another. + */ + update_subgroup_set_needs_refresh(subgrp, 1); + + SUBGRP_INCR_STAT(subgrp, updgrp_switch_events); + return; + } - subgrp = old_subgrp; - old_id = old_subgrp->update_group->id; - - if (bgp_debug_peer_updout_enabled(paf->peer->host)) - { - UPDGRP_PEER_DBG_DIS(old_subgrp->update_group); - } - - update_group_remove_subgroup (old_subgrp->update_group, old_subgrp); - update_group_add_subgroup (updgrp, subgrp); - - if (bgp_debug_peer_updout_enabled(paf->peer->host)) - { - UPDGRP_PEER_DBG_EN(updgrp); - } - if (BGP_DEBUG (update_groups, UPDATE_GROUPS)) - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " peer %s moved to u%" PRIu64 ":s%" PRIu64, - old_id, subgrp->id, paf->peer->host, updgrp->id, subgrp->id); - - /* - * The state of the subgroup (adj_out, advs, packet queue etc) - * is consistent internally, but may not be identical to other - * subgroups in the new update group even if the version number - * matches up. Make sure a full refresh is done before the - * subgroup is merged with another. - */ - update_subgroup_set_needs_refresh (subgrp, 1); - - SUBGRP_INCR_STAT (subgrp, updgrp_switch_events); - return; - } - - /* - * Create a new subgroup under the specified update group, and copy - * over relevant state to it. - */ - subgrp = update_subgroup_create (updgrp); - update_subgroup_inherit_info (subgrp, old_subgrp); - - subgrp->split_from.update_group_id = old_subgrp->update_group->id; - subgrp->split_from.subgroup_id = old_subgrp->id; - - /* - * Copy out relevant state from the old subgroup. - */ - update_subgroup_copy_adj_out (paf->subgroup, subgrp); - update_subgroup_copy_packets (subgrp, paf->next_pkt_to_send); - - if (BGP_DEBUG (update_groups, UPDATE_GROUPS)) - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " peer %s split and moved into u%" PRIu64 ":s%" PRIu64, - paf->subgroup->update_group->id, paf->subgroup->id, - paf->peer->host, updgrp->id, subgrp->id); - - SUBGRP_INCR_STAT (paf->subgroup, split_events); - - /* - * Since queued advs were left behind, this new subgroup needs a - * refresh. - */ - update_subgroup_set_needs_refresh (subgrp, 1); - - /* - * Remove peer from old subgroup, and add it to the new one. - */ - update_subgroup_remove_peer (paf->subgroup, paf); - - update_subgroup_add_peer (subgrp, paf, 1); + /* + * Create a new subgroup under the specified update group, and copy + * over relevant state to it. + */ + subgrp = update_subgroup_create(updgrp); + update_subgroup_inherit_info(subgrp, old_subgrp); + + subgrp->split_from.update_group_id = old_subgrp->update_group->id; + subgrp->split_from.subgroup_id = old_subgrp->id; + + /* + * Copy out relevant state from the old subgroup. + */ + update_subgroup_copy_adj_out(paf->subgroup, subgrp); + update_subgroup_copy_packets(subgrp, paf->next_pkt_to_send); + + if (BGP_DEBUG(update_groups, UPDATE_GROUPS)) + zlog_debug("u%" PRIu64 ":s%" PRIu64 + " peer %s split and moved into u%" PRIu64 + ":s%" PRIu64, + paf->subgroup->update_group->id, paf->subgroup->id, + paf->peer->host, updgrp->id, subgrp->id); + + SUBGRP_INCR_STAT(paf->subgroup, split_events); + + /* + * Since queued advs were left behind, this new subgroup needs a + * refresh. + */ + update_subgroup_set_needs_refresh(subgrp, 1); + + /* + * Remove peer from old subgroup, and add it to the new one. + */ + update_subgroup_remove_peer(paf->subgroup, paf); + + update_subgroup_add_peer(subgrp, paf, 1); } -void -update_bgp_group_init (struct bgp *bgp) +void update_bgp_group_init(struct bgp *bgp) { - int afid; + int afid; - AF_FOREACH (afid) - bgp->update_groups[afid] = hash_create (updgrp_hash_key_make, - updgrp_hash_cmp, NULL); + AF_FOREACH(afid) + bgp->update_groups[afid] = + hash_create(updgrp_hash_key_make, updgrp_hash_cmp, NULL); } -void -update_bgp_group_free (struct bgp *bgp) +void update_bgp_group_free(struct bgp *bgp) { - int afid; - - AF_FOREACH (afid) - { - if (bgp->update_groups[afid]) - { - hash_free(bgp->update_groups[afid]); - bgp->update_groups[afid] = NULL; - } - } + int afid; + + AF_FOREACH(afid) + { + if (bgp->update_groups[afid]) { + hash_free(bgp->update_groups[afid]); + bgp->update_groups[afid] = NULL; + } + } } -void -update_group_show (struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, - uint64_t subgrp_id) +void update_group_show(struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, + uint64_t subgrp_id) { - struct updwalk_context ctx; - memset (&ctx, 0, sizeof (ctx)); - ctx.vty = vty; - ctx.subgrp_id = subgrp_id; + struct updwalk_context ctx; + memset(&ctx, 0, sizeof(ctx)); + ctx.vty = vty; + ctx.subgrp_id = subgrp_id; - update_group_af_walk (bgp, afi, safi, update_group_show_walkcb, &ctx); + update_group_af_walk(bgp, afi, safi, update_group_show_walkcb, &ctx); } /* @@ -1594,229 +1582,209 @@ update_group_show (struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, * * Show global statistics about update groups. */ -void -update_group_show_stats (struct bgp *bgp, struct vty *vty) +void update_group_show_stats(struct bgp *bgp, struct vty *vty) { - vty_out (vty, "Update groups created: %u\n", - bgp->update_group_stats.updgrps_created); - vty_out (vty, "Update groups deleted: %u\n", - bgp->update_group_stats.updgrps_deleted); - vty_out (vty, "Update subgroups created: %u\n", - bgp->update_group_stats.subgrps_created); - vty_out (vty, "Update subgroups deleted: %u\n", - bgp->update_group_stats.subgrps_deleted); - vty_out (vty, "Join events: %u\n", - bgp->update_group_stats.join_events); - vty_out (vty, "Prune events: %u\n", - bgp->update_group_stats.prune_events); - vty_out (vty, "Merge events: %u\n", - bgp->update_group_stats.merge_events); - vty_out (vty, "Split events: %u\n", - bgp->update_group_stats.split_events); - vty_out (vty, "Update group switch events: %u\n", - bgp->update_group_stats.updgrp_switch_events); - vty_out (vty, "Peer route refreshes combined: %u\n", - bgp->update_group_stats.peer_refreshes_combined); - vty_out (vty, "Merge checks triggered: %u\n", - bgp->update_group_stats.merge_checks_triggered); + vty_out(vty, "Update groups created: %u\n", + bgp->update_group_stats.updgrps_created); + vty_out(vty, "Update groups deleted: %u\n", + bgp->update_group_stats.updgrps_deleted); + vty_out(vty, "Update subgroups created: %u\n", + bgp->update_group_stats.subgrps_created); + vty_out(vty, "Update subgroups deleted: %u\n", + bgp->update_group_stats.subgrps_deleted); + vty_out(vty, "Join events: %u\n", bgp->update_group_stats.join_events); + vty_out(vty, "Prune events: %u\n", + bgp->update_group_stats.prune_events); + vty_out(vty, "Merge events: %u\n", + bgp->update_group_stats.merge_events); + vty_out(vty, "Split events: %u\n", + bgp->update_group_stats.split_events); + vty_out(vty, "Update group switch events: %u\n", + bgp->update_group_stats.updgrp_switch_events); + vty_out(vty, "Peer route refreshes combined: %u\n", + bgp->update_group_stats.peer_refreshes_combined); + vty_out(vty, "Merge checks triggered: %u\n", + bgp->update_group_stats.merge_checks_triggered); } /* * update_group_adjust_peer */ -void -update_group_adjust_peer (struct peer_af *paf) +void update_group_adjust_peer(struct peer_af *paf) { - struct update_group *updgrp; - struct update_subgroup *subgrp, *old_subgrp; - struct peer *peer; - - if (!paf) - return; - - peer = PAF_PEER (paf); - if (!peer_established (peer)) - { - return; - } - - if (!CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)) - { - return; - } - - if (!peer->afc_nego[paf->afi][paf->safi]) - { - return; - } - - updgrp = update_group_find (paf); - if (!updgrp) - { - updgrp = update_group_create (paf); - if (!updgrp) - { - zlog_err ("couldn't create update group for peer %s", - paf->peer->host); - return; + struct update_group *updgrp; + struct update_subgroup *subgrp, *old_subgrp; + struct peer *peer; + + if (!paf) + return; + + peer = PAF_PEER(paf); + if (!peer_established(peer)) { + return; + } + + if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) { + return; } - } - old_subgrp = paf->subgroup; + if (!peer->afc_nego[paf->afi][paf->safi]) { + return; + } - if (old_subgrp) - { + updgrp = update_group_find(paf); + if (!updgrp) { + updgrp = update_group_create(paf); + if (!updgrp) { + zlog_err("couldn't create update group for peer %s", + paf->peer->host); + return; + } + } - /* - * If the update group of the peer is unchanged, the peer can stay - * in its existing subgroup and we're done. - */ - if (old_subgrp->update_group == updgrp) - return; + old_subgrp = paf->subgroup; - /* - * The peer is switching between update groups. Put it in its - * own subgroup under the new update group. - */ - update_subgroup_split_peer (paf, updgrp); - return; - } - - subgrp = update_subgroup_find (updgrp, paf); - if (!subgrp) - { - subgrp = update_subgroup_create (updgrp); - if (!subgrp) - return; - } + if (old_subgrp) { - update_subgroup_add_peer (subgrp, paf, 1); - if (BGP_DEBUG (update_groups, UPDATE_GROUPS)) - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " add peer %s", - updgrp->id, subgrp->id, paf->peer->host); + /* + * If the update group of the peer is unchanged, the peer can + * stay + * in its existing subgroup and we're done. + */ + if (old_subgrp->update_group == updgrp) + return; + + /* + * The peer is switching between update groups. Put it in its + * own subgroup under the new update group. + */ + update_subgroup_split_peer(paf, updgrp); + return; + } + + subgrp = update_subgroup_find(updgrp, paf); + if (!subgrp) { + subgrp = update_subgroup_create(updgrp); + if (!subgrp) + return; + } - return; + update_subgroup_add_peer(subgrp, paf, 1); + if (BGP_DEBUG(update_groups, UPDATE_GROUPS)) + zlog_debug("u%" PRIu64 ":s%" PRIu64 " add peer %s", updgrp->id, + subgrp->id, paf->peer->host); + + return; } -int -update_group_adjust_soloness (struct peer *peer, int set) +int update_group_adjust_soloness(struct peer *peer, int set) { - struct peer_group *group; - struct listnode *node, *nnode; - - if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_lonesoul_or_not (peer, set); - if (peer->status == Established) - bgp_announce_route_all (peer); - } - else - { - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - peer_lonesoul_or_not (peer, set); - if (peer->status == Established) - bgp_announce_route_all (peer); - } - } - return 0; + struct peer_group *group; + struct listnode *node, *nnode; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_lonesoul_or_not(peer, set); + if (peer->status == Established) + bgp_announce_route_all(peer); + } else { + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + peer_lonesoul_or_not(peer, set); + if (peer->status == Established) + bgp_announce_route_all(peer); + } + } + return 0; } /* * update_subgroup_rib */ -struct bgp_table * -update_subgroup_rib (struct update_subgroup *subgrp) +struct bgp_table *update_subgroup_rib(struct update_subgroup *subgrp) { - struct bgp *bgp; + struct bgp *bgp; - bgp = SUBGRP_INST (subgrp); - if (!bgp) - return NULL; + bgp = SUBGRP_INST(subgrp); + if (!bgp) + return NULL; - return bgp->rib[SUBGRP_AFI (subgrp)][SUBGRP_SAFI (subgrp)]; + return bgp->rib[SUBGRP_AFI(subgrp)][SUBGRP_SAFI(subgrp)]; } -void -update_group_af_walk (struct bgp *bgp, afi_t afi, safi_t safi, - updgrp_walkcb cb, void *ctx) +void update_group_af_walk(struct bgp *bgp, afi_t afi, safi_t safi, + updgrp_walkcb cb, void *ctx) { - struct updwalk_context wctx; - int afid; + struct updwalk_context wctx; + int afid; - if (!bgp) - return; - afid = afindex (afi, safi); - if (afid >= BGP_AF_MAX) - return; + if (!bgp) + return; + afid = afindex(afi, safi); + if (afid >= BGP_AF_MAX) + return; - memset (&wctx, 0, sizeof (wctx)); - wctx.cb = cb; - wctx.context = ctx; + memset(&wctx, 0, sizeof(wctx)); + wctx.cb = cb; + wctx.context = ctx; - if (bgp->update_groups[afid]) - hash_walk (bgp->update_groups[afid], update_group_walkcb, &wctx); + if (bgp->update_groups[afid]) + hash_walk(bgp->update_groups[afid], update_group_walkcb, &wctx); } -void -update_group_walk (struct bgp *bgp, updgrp_walkcb cb, void *ctx) +void update_group_walk(struct bgp *bgp, updgrp_walkcb cb, void *ctx) { - afi_t afi; - safi_t safi; + afi_t afi; + safi_t safi; - FOREACH_AFI_SAFI (afi, safi) - { - update_group_af_walk (bgp, afi, safi, cb, ctx); - } + FOREACH_AFI_SAFI(afi, safi) + { + update_group_af_walk(bgp, afi, safi, cb, ctx); + } } -void -update_group_periodic_merge (struct bgp *bgp) +void update_group_periodic_merge(struct bgp *bgp) { - char reason[] = "periodic merge check"; + char reason[] = "periodic merge check"; - update_group_walk (bgp, update_group_periodic_merge_walkcb, - (void *) reason); + update_group_walk(bgp, update_group_periodic_merge_walkcb, + (void *)reason); } static int update_group_default_originate_route_map_walkcb(struct update_group *updgrp, - void *arg) + void *arg) { - struct update_subgroup *subgrp; - struct peer *peer; - afi_t afi; - safi_t safi; - - UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) - { - peer = SUBGRP_PEER (subgrp); - afi = SUBGRP_AFI (subgrp); - safi = SUBGRP_SAFI (subgrp); - - if (peer->default_rmap[afi][safi].name) - { - subgroup_default_originate (subgrp, 0); - } - } - - return UPDWALK_CONTINUE; + struct update_subgroup *subgrp; + struct peer *peer; + afi_t afi; + safi_t safi; + + UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) + { + peer = SUBGRP_PEER(subgrp); + afi = SUBGRP_AFI(subgrp); + safi = SUBGRP_SAFI(subgrp); + + if (peer->default_rmap[afi][safi].name) { + subgroup_default_originate(subgrp, 0); + } + } + + return UPDWALK_CONTINUE; } -int -update_group_refresh_default_originate_route_map (struct thread *thread) +int update_group_refresh_default_originate_route_map(struct thread *thread) { - struct bgp *bgp; - char reason[] = "refresh default-originate route-map"; + struct bgp *bgp; + char reason[] = "refresh default-originate route-map"; - bgp = THREAD_ARG(thread); - update_group_walk (bgp, update_group_default_originate_route_map_walkcb, - reason); - THREAD_TIMER_OFF (bgp->t_rmap_def_originate_eval); - bgp_unlock(bgp); + bgp = THREAD_ARG(thread); + update_group_walk(bgp, update_group_default_originate_route_map_walkcb, + reason); + THREAD_TIMER_OFF(bgp->t_rmap_def_originate_eval); + bgp_unlock(bgp); - return(0); + return (0); } /* @@ -1831,132 +1799,130 @@ update_group_refresh_default_originate_route_map (struct thread *thread) * For now, the 'combine' option has an effect only if all peers in * the subgroup have a route announcement pending. */ -void -peer_af_announce_route (struct peer_af *paf, int combine) +void peer_af_announce_route(struct peer_af *paf, int combine) { - struct update_subgroup *subgrp; - struct peer_af *cur_paf; - int all_pending; - - subgrp = paf->subgroup; - all_pending = 0; - - if (combine) - { - /* - * If there are other peers in the old subgroup that also need - * routes to be announced, pull them into the peer's new - * subgroup. - * Combine route announcement with other peers if possible. - * - * For now, we combine only if all peers in the subgroup have an - * announcement pending. - */ - all_pending = 1; - - SUBGRP_FOREACH_PEER (subgrp, cur_paf) - { - if (cur_paf == paf) - continue; - - if (cur_paf->t_announce_route) - continue; - - all_pending = 0; - break; + struct update_subgroup *subgrp; + struct peer_af *cur_paf; + int all_pending; + + subgrp = paf->subgroup; + all_pending = 0; + + if (combine) { + /* + * If there are other peers in the old subgroup that also need + * routes to be announced, pull them into the peer's new + * subgroup. + * Combine route announcement with other peers if possible. + * + * For now, we combine only if all peers in the subgroup have an + * announcement pending. + */ + all_pending = 1; + + SUBGRP_FOREACH_PEER(subgrp, cur_paf) + { + if (cur_paf == paf) + continue; + + if (cur_paf->t_announce_route) + continue; + + all_pending = 0; + break; + } + } + /* + * Announce to the peer alone if we were not asked to combine peers, + * or if some peers don't have a route annoucement pending. + */ + if (!combine || !all_pending) { + update_subgroup_split_peer(paf, NULL); + if (!paf->subgroup) + return; + + if (bgp_debug_update(paf->peer, NULL, subgrp->update_group, 0)) + zlog_debug("u%" PRIu64 ":s%" PRIu64 + " %s announcing routes", + subgrp->update_group->id, subgrp->id, + paf->peer->host); + + subgroup_announce_route(paf->subgroup); + return; } - } - /* - * Announce to the peer alone if we were not asked to combine peers, - * or if some peers don't have a route annoucement pending. - */ - if (!combine || !all_pending) - { - update_subgroup_split_peer (paf, NULL); - if (!paf->subgroup) - return; - - if (bgp_debug_update(paf->peer, NULL, subgrp->update_group, 0)) - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " %s announcing routes", - subgrp->update_group->id, subgrp->id, paf->peer->host); - - subgroup_announce_route (paf->subgroup); - return; - } - /* - * We will announce routes the entire subgroup. - * - * First stop refresh timers on all the other peers. - */ - SUBGRP_FOREACH_PEER (subgrp, cur_paf) - { - if (cur_paf == paf) - continue; + /* + * We will announce routes the entire subgroup. + * + * First stop refresh timers on all the other peers. + */ + SUBGRP_FOREACH_PEER(subgrp, cur_paf) + { + if (cur_paf == paf) + continue; - bgp_stop_announce_route_timer (cur_paf); - } + bgp_stop_announce_route_timer(cur_paf); + } - if (bgp_debug_update(paf->peer, NULL, subgrp->update_group, 0)) - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " announcing routes to %s, combined into %d peers", - subgrp->update_group->id, subgrp->id, - paf->peer->host, subgrp->peer_count); + if (bgp_debug_update(paf->peer, NULL, subgrp->update_group, 0)) + zlog_debug("u%" PRIu64 ":s%" PRIu64 + " announcing routes to %s, combined into %d peers", + subgrp->update_group->id, subgrp->id, + paf->peer->host, subgrp->peer_count); - subgroup_announce_route (subgrp); + subgroup_announce_route(subgrp); - SUBGRP_INCR_STAT_BY (subgrp, peer_refreshes_combined, - subgrp->peer_count - 1); + SUBGRP_INCR_STAT_BY(subgrp, peer_refreshes_combined, + subgrp->peer_count - 1); } -void -subgroup_trigger_write (struct update_subgroup *subgrp) +void subgroup_trigger_write(struct update_subgroup *subgrp) { - struct peer_af *paf; + struct peer_af *paf; #if 0 if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0)) zlog_debug("u%llu:s%llu scheduling write thread for peers", subgrp->update_group->id, subgrp->id); #endif - SUBGRP_FOREACH_PEER (subgrp, paf) - { - if (paf->peer->status == Established) - { - BGP_PEER_WRITE_ON (paf->peer->t_write, bgp_write, paf->peer->fd, - paf->peer); - } - } + SUBGRP_FOREACH_PEER(subgrp, paf) + { + if (paf->peer->status == Established) { + BGP_PEER_WRITE_ON(paf->peer->t_write, bgp_write, + paf->peer->fd, paf->peer); + } + } } -int -update_group_clear_update_dbg (struct update_group *updgrp, void *arg) +int update_group_clear_update_dbg(struct update_group *updgrp, void *arg) { - UPDGRP_PEER_DBG_OFF(updgrp); - return UPDWALK_CONTINUE; + UPDGRP_PEER_DBG_OFF(updgrp); + return UPDWALK_CONTINUE; } /* Return true if we should addpath encode NLRI to this peer */ -int -bgp_addpath_encode_tx (struct peer *peer, afi_t afi, safi_t safi) +int bgp_addpath_encode_tx(struct peer *peer, afi_t afi, safi_t safi) { - return (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_ADV) && - CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_RCV)); + return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_ADV) + && CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ADDPATH_AF_RX_RCV)); } /* * Return true if this is a path we should advertise due to a * configured addpath-tx knob */ -int -bgp_addpath_tx_path (struct peer *peer, afi_t afi, safi_t safi, - struct bgp_info *ri) +int bgp_addpath_tx_path(struct peer *peer, afi_t afi, safi_t safi, + struct bgp_info *ri) { - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS)) - return 1; + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ADDPATH_TX_ALL_PATHS)) + return 1; - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS) && - CHECK_FLAG (ri->flags, BGP_INFO_DMED_SELECTED)) - return 1; + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS) + && CHECK_FLAG(ri->flags, BGP_INFO_DMED_SELECTED)) + return 1; - return 0; + return 0; } diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h index 87b85adae..52a21679b 100644 --- a/bgpd/bgp_updgrp.h +++ b/bgpd/bgp_updgrp.h @@ -31,46 +31,34 @@ #define BGP_DEFAULT_SUBGROUP_COALESCE_TIME 200 -#define PEER_UPDGRP_FLAGS (PEER_FLAG_LOCAL_AS_NO_PREPEND | \ - PEER_FLAG_LOCAL_AS_REPLACE_AS) - -#define PEER_UPDGRP_AF_FLAGS (PEER_FLAG_SEND_COMMUNITY | \ - PEER_FLAG_SEND_EXT_COMMUNITY | \ - PEER_FLAG_DEFAULT_ORIGINATE | \ - PEER_FLAG_REFLECTOR_CLIENT | \ - PEER_FLAG_RSERVER_CLIENT | \ - PEER_FLAG_NEXTHOP_SELF | \ - PEER_FLAG_NEXTHOP_UNCHANGED | \ - PEER_FLAG_FORCE_NEXTHOP_SELF | \ - PEER_FLAG_AS_PATH_UNCHANGED | \ - PEER_FLAG_MED_UNCHANGED | \ - PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED | \ - PEER_FLAG_REMOVE_PRIVATE_AS | \ - PEER_FLAG_REMOVE_PRIVATE_AS_ALL | \ - PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE | \ - PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE | \ - PEER_FLAG_ADDPATH_TX_ALL_PATHS | \ - PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS | \ - PEER_FLAG_AS_OVERRIDE) +#define PEER_UPDGRP_FLAGS \ + (PEER_FLAG_LOCAL_AS_NO_PREPEND | PEER_FLAG_LOCAL_AS_REPLACE_AS) + +#define PEER_UPDGRP_AF_FLAGS \ + (PEER_FLAG_SEND_COMMUNITY | PEER_FLAG_SEND_EXT_COMMUNITY \ + | PEER_FLAG_DEFAULT_ORIGINATE | PEER_FLAG_REFLECTOR_CLIENT \ + | PEER_FLAG_RSERVER_CLIENT | PEER_FLAG_NEXTHOP_SELF \ + | PEER_FLAG_NEXTHOP_UNCHANGED | PEER_FLAG_FORCE_NEXTHOP_SELF \ + | PEER_FLAG_AS_PATH_UNCHANGED | PEER_FLAG_MED_UNCHANGED \ + | PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED | PEER_FLAG_REMOVE_PRIVATE_AS \ + | PEER_FLAG_REMOVE_PRIVATE_AS_ALL \ + | PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE \ + | PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE \ + | PEER_FLAG_ADDPATH_TX_ALL_PATHS \ + | PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS | PEER_FLAG_AS_OVERRIDE) #define PEER_UPDGRP_CAP_FLAGS (PEER_CAP_AS4_RCV) -#define PEER_UPDGRP_AF_CAP_FLAGS (PEER_CAP_ORF_PREFIX_SM_RCV | \ - PEER_CAP_ORF_PREFIX_SM_OLD_RCV |\ - PEER_CAP_ADDPATH_AF_TX_ADV |\ - PEER_CAP_ADDPATH_AF_RX_RCV |\ - PEER_CAP_ENHE_AF_NEGO) +#define PEER_UPDGRP_AF_CAP_FLAGS \ + (PEER_CAP_ORF_PREFIX_SM_RCV | PEER_CAP_ORF_PREFIX_SM_OLD_RCV \ + | PEER_CAP_ADDPATH_AF_TX_ADV | PEER_CAP_ADDPATH_AF_RX_RCV \ + | PEER_CAP_ENHE_AF_NEGO) -typedef enum -{ - BGP_ATTR_VEC_NH = 0, - BGP_ATTR_VEC_MAX -} bpacket_attr_vec_type; +typedef enum { BGP_ATTR_VEC_NH = 0, BGP_ATTR_VEC_MAX } bpacket_attr_vec_type; -typedef struct -{ - u_int32_t flags; - unsigned long offset; +typedef struct { + u_int32_t flags; + unsigned long offset; } bpacket_attr_vec; #define BPKT_ATTRVEC_FLAGS_UPDATED (1 << 0) @@ -81,28 +69,25 @@ typedef struct #define BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED (1 << 5) #define BPKT_ATTRVEC_FLAGS_RMAP_IPV6_LNH_CHANGED (1 << 6) -typedef struct bpacket_attr_vec_arr -{ - bpacket_attr_vec entries[BGP_ATTR_VEC_MAX]; +typedef struct bpacket_attr_vec_arr { + bpacket_attr_vec entries[BGP_ATTR_VEC_MAX]; } bpacket_attr_vec_arr; -struct bpacket -{ - /* for being part of an update subgroup's message list */ - TAILQ_ENTRY (bpacket) pkt_train; +struct bpacket { + /* for being part of an update subgroup's message list */ + TAILQ_ENTRY(bpacket) pkt_train; - /* list of peers (well, peer_afs) that the packet needs to be sent to */ - LIST_HEAD (pkt_peer_list, peer_af) peers; + /* list of peers (well, peer_afs) that the packet needs to be sent to */ + LIST_HEAD(pkt_peer_list, peer_af) peers; - struct stream *buffer; - bpacket_attr_vec_arr arr; + struct stream *buffer; + bpacket_attr_vec_arr arr; - unsigned int ver; + unsigned int ver; }; -struct bpacket_queue -{ - TAILQ_HEAD (pkt_queue, bpacket) pkts; +struct bpacket_queue { + TAILQ_HEAD(pkt_queue, bpacket) pkts; #if 0 /* A dummy packet that is used to thread all peers that have @@ -110,149 +95,146 @@ struct bpacket_queue struct bpacket sentinel; #endif - unsigned int conf_max_count; - unsigned int curr_count; - unsigned int hwm_count; - unsigned int max_count_reached_count; + unsigned int conf_max_count; + unsigned int curr_count; + unsigned int hwm_count; + unsigned int max_count_reached_count; }; -struct update_group -{ - /* back pointer to the BGP instance */ - struct bgp *bgp; +struct update_group { + /* back pointer to the BGP instance */ + struct bgp *bgp; - /* list of subgroups that belong to the update group */ - LIST_HEAD (subgrp_list, update_subgroup) subgrps; + /* list of subgroups that belong to the update group */ + LIST_HEAD(subgrp_list, update_subgroup) subgrps; - /* lazy way to store configuration common to all peers - hash function will compute from this data */ - struct peer *conf; + /* lazy way to store configuration common to all peers + hash function will compute from this data */ + struct peer *conf; - afi_t afi; - safi_t safi; - int afid; + afi_t afi; + safi_t safi; + int afid; - uint64_t id; - time_t uptime; + uint64_t id; + time_t uptime; - u_int32_t join_events; - u_int32_t prune_events; - u_int32_t merge_events; - u_int32_t updgrp_switch_events; - u_int32_t peer_refreshes_combined; - u_int32_t adj_count; - u_int32_t split_events; - u_int32_t merge_checks_triggered; + u_int32_t join_events; + u_int32_t prune_events; + u_int32_t merge_events; + u_int32_t updgrp_switch_events; + u_int32_t peer_refreshes_combined; + u_int32_t adj_count; + u_int32_t split_events; + u_int32_t merge_checks_triggered; - u_int32_t subgrps_created; - u_int32_t subgrps_deleted; + u_int32_t subgrps_created; + u_int32_t subgrps_deleted; - u_int32_t num_dbg_en_peers; + u_int32_t num_dbg_en_peers; }; /* * Shorthand for a global statistics counter. */ -#define UPDGRP_GLOBAL_STAT(updgrp, stat) \ - ((updgrp)->bgp->update_group_stats.stat) +#define UPDGRP_GLOBAL_STAT(updgrp, stat) \ + ((updgrp)->bgp->update_group_stats.stat) /* * Add the given value to a counter on an update group and the bgp * instance. */ -#define UPDGRP_INCR_STAT_BY(updgrp, stat, value) \ - do { \ - (updgrp)->stat += (value); \ - UPDGRP_GLOBAL_STAT(updgrp, stat) += (value); \ - } while (0) +#define UPDGRP_INCR_STAT_BY(updgrp, stat, value) \ + do { \ + (updgrp)->stat += (value); \ + UPDGRP_GLOBAL_STAT(updgrp, stat) += (value); \ + } while (0) /* * Increment a counter on a update group and its parent structures. */ -#define UPDGRP_INCR_STAT(subgrp, stat) \ - UPDGRP_INCR_STAT_BY(subgrp, stat, 1) +#define UPDGRP_INCR_STAT(subgrp, stat) UPDGRP_INCR_STAT_BY(subgrp, stat, 1) -struct update_subgroup -{ - /* back pointer to the parent update group */ - struct update_group *update_group; +struct update_subgroup { + /* back pointer to the parent update group */ + struct update_group *update_group; - /* list of peers that belong to the subgroup */ - LIST_HEAD (peer_list, peer_af) peers; - int peer_count; + /* list of peers that belong to the subgroup */ + LIST_HEAD(peer_list, peer_af) peers; + int peer_count; - /* for being part of an update group's subgroup list */ - LIST_ENTRY (update_subgroup) updgrp_train; + /* for being part of an update group's subgroup list */ + LIST_ENTRY(update_subgroup) updgrp_train; - struct bpacket_queue pkt_queue; + struct bpacket_queue pkt_queue; - /* - * List of adj-out structures for this subgroup. - * It essentially represents the snapshot of every prefix that - * has been advertised to the members of the subgroup - */ - TAILQ_HEAD (adjout_queue, bgp_adj_out) adjq; + /* + * List of adj-out structures for this subgroup. + * It essentially represents the snapshot of every prefix that + * has been advertised to the members of the subgroup + */ + TAILQ_HEAD(adjout_queue, bgp_adj_out) adjq; - /* packet buffer for update generation */ - struct stream *work; + /* packet buffer for update generation */ + struct stream *work; - /* We use a separate stream to encode MP_REACH_NLRI for efficient - * NLRI packing. peer->work stores all the other attributes. The - * actual packet is then constructed by concatenating the two. - */ - struct stream *scratch; + /* We use a separate stream to encode MP_REACH_NLRI for efficient + * NLRI packing. peer->work stores all the other attributes. The + * actual packet is then constructed by concatenating the two. + */ + struct stream *scratch; - /* synchronization list and time */ - struct bgp_synchronize *sync; + /* synchronization list and time */ + struct bgp_synchronize *sync; - /* send prefix count */ - unsigned long scount; + /* send prefix count */ + unsigned long scount; - /* announcement attribute hash */ - struct hash *hash; + /* announcement attribute hash */ + struct hash *hash; - struct thread *t_coalesce; - u_int32_t v_coalesce; + struct thread *t_coalesce; + u_int32_t v_coalesce; - struct thread *t_merge_check; + struct thread *t_merge_check; - /* table version that the subgroup has caught up to. */ - uint64_t version; + /* table version that the subgroup has caught up to. */ + uint64_t version; - /* version maintained to record adj changes */ - uint64_t adj_version; + /* version maintained to record adj changes */ + uint64_t adj_version; - time_t uptime; + time_t uptime; - /* - * Identifying information about the subgroup that this subgroup was split - * from, if any. - */ - struct - { - uint64_t update_group_id; - uint64_t subgroup_id; - } split_from; + /* + * Identifying information about the subgroup that this subgroup was + * split + * from, if any. + */ + struct { + uint64_t update_group_id; + uint64_t subgroup_id; + } split_from; - u_int32_t join_events; - u_int32_t prune_events; + u_int32_t join_events; + u_int32_t prune_events; - /* - * This is bumped up when another subgroup merges into this one. - */ - u_int32_t merge_events; - u_int32_t updgrp_switch_events; - u_int32_t peer_refreshes_combined; - u_int32_t adj_count; - u_int32_t split_events; - u_int32_t merge_checks_triggered; + /* + * This is bumped up when another subgroup merges into this one. + */ + u_int32_t merge_events; + u_int32_t updgrp_switch_events; + u_int32_t peer_refreshes_combined; + u_int32_t adj_count; + u_int32_t split_events; + u_int32_t merge_checks_triggered; - uint64_t id; + uint64_t id; - u_int16_t sflags; + u_int16_t sflags; - /* Subgroup flags, see below */ - u_int16_t flags; + /* Subgroup flags, see below */ + u_int16_t flags; }; /* @@ -267,43 +249,41 @@ struct update_subgroup * Add the given value to the specified counter on a subgroup and its * parent structures. */ -#define SUBGRP_INCR_STAT_BY(subgrp, stat, value) \ - do { \ - (subgrp)->stat += (value); \ - if ((subgrp)->update_group) \ - UPDGRP_INCR_STAT_BY((subgrp)->update_group, stat, value); \ - } while (0) +#define SUBGRP_INCR_STAT_BY(subgrp, stat, value) \ + do { \ + (subgrp)->stat += (value); \ + if ((subgrp)->update_group) \ + UPDGRP_INCR_STAT_BY((subgrp)->update_group, stat, \ + value); \ + } while (0) /* * Increment a counter on a subgroup and its parent structures. */ -#define SUBGRP_INCR_STAT(subgrp, stat) \ - SUBGRP_INCR_STAT_BY(subgrp, stat, 1) +#define SUBGRP_INCR_STAT(subgrp, stat) SUBGRP_INCR_STAT_BY(subgrp, stat, 1) /* * Decrement a counter on a subgroup and its parent structures. */ -#define SUBGRP_DECR_STAT(subgrp, stat) \ - SUBGRP_INCR_STAT_BY(subgrp, stat, -1) +#define SUBGRP_DECR_STAT(subgrp, stat) SUBGRP_INCR_STAT_BY(subgrp, stat, -1) -typedef int (*updgrp_walkcb) (struct update_group * updgrp, void *ctx); +typedef int (*updgrp_walkcb)(struct update_group *updgrp, void *ctx); /* really a private structure */ -struct updwalk_context -{ - struct vty *vty; - struct bgp_node *rn; - struct bgp_info *ri; - uint64_t updgrp_id; - uint64_t subgrp_id; - bgp_policy_type_e policy_type; - const char *policy_name; - int policy_event_start_flag; - int policy_route_update; - updgrp_walkcb cb; - void *context; - u_int8_t flags; +struct updwalk_context { + struct vty *vty; + struct bgp_node *rn; + struct bgp_info *ri; + uint64_t updgrp_id; + uint64_t subgrp_id; + bgp_policy_type_e policy_type; + const char *policy_name; + int policy_event_start_flag; + int policy_route_update; + updgrp_walkcb cb; + void *context; + u_int8_t flags; #define UPDWALK_FLAGS_ADVQUEUE (1 << 0) #define UPDWALK_FLAGS_ADVERTISED (1 << 1) @@ -321,8 +301,7 @@ struct updwalk_context #define UPDGRP_AFI(u) ((u)->afi) #define UPDGRP_SAFI(u) ((u)->safi) #define UPDGRP_INST(u) ((u)->bgp) -#define UPDGRP_AFFLAGS(u) \ - ((u)->conf->af_flags[UPDGRP_AFI(u)][UPDGRP_SAFI(u)]) +#define UPDGRP_AFFLAGS(u) ((u)->conf->af_flags[UPDGRP_AFI(u)][UPDGRP_SAFI(u)]) #define UPDGRP_DBG_ON(u) ((u)->num_dbg_en_peers) #define UPDGRP_PEER_DBG_EN(u) (((u)->num_dbg_en_peers)++) #define UPDGRP_PEER_DBG_DIS(u) (((u)->num_dbg_en_peers)--) @@ -341,149 +320,137 @@ struct updwalk_context /* * Walk all subgroups in an update group. */ -#define UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) \ - LIST_FOREACH(subgrp, &((updgrp)->subgrps), updgrp_train) +#define UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) \ + LIST_FOREACH(subgrp, &((updgrp)->subgrps), updgrp_train) -#define UPDGRP_FOREACH_SUBGRP_SAFE(updgrp, subgrp, tmp_subgrp) \ - LIST_FOREACH_SAFE(subgrp, &((updgrp)->subgrps), updgrp_train, tmp_subgrp) +#define UPDGRP_FOREACH_SUBGRP_SAFE(updgrp, subgrp, tmp_subgrp) \ + LIST_FOREACH_SAFE(subgrp, &((updgrp)->subgrps), updgrp_train, \ + tmp_subgrp) -#define SUBGRP_FOREACH_PEER(subgrp, paf) \ - LIST_FOREACH(paf, &(subgrp->peers), subgrp_train) +#define SUBGRP_FOREACH_PEER(subgrp, paf) \ + LIST_FOREACH(paf, &(subgrp->peers), subgrp_train) -#define SUBGRP_FOREACH_PEER_SAFE(subgrp, paf, temp_paf) \ - LIST_FOREACH_SAFE(paf, &(subgrp->peers), subgrp_train, temp_paf) +#define SUBGRP_FOREACH_PEER_SAFE(subgrp, paf, temp_paf) \ + LIST_FOREACH_SAFE(paf, &(subgrp->peers), subgrp_train, temp_paf) -#define SUBGRP_FOREACH_ADJ(subgrp, adj) \ - TAILQ_FOREACH(adj, &(subgrp->adjq), subgrp_adj_train) +#define SUBGRP_FOREACH_ADJ(subgrp, adj) \ + TAILQ_FOREACH(adj, &(subgrp->adjq), subgrp_adj_train) -#define SUBGRP_FOREACH_ADJ_SAFE(subgrp, adj, adj_temp) \ - TAILQ_FOREACH_SAFE(adj, &(subgrp->adjq), subgrp_adj_train, adj_temp) +#define SUBGRP_FOREACH_ADJ_SAFE(subgrp, adj, adj_temp) \ + TAILQ_FOREACH_SAFE(adj, &(subgrp->adjq), subgrp_adj_train, adj_temp) /* Prototypes. */ /* bgp_updgrp.c */ -extern void update_bgp_group_init (struct bgp *); -extern void udpate_bgp_group_free (struct bgp *); - -extern void -update_group_show (struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, uint64_t subgrp_id); -extern void update_group_show_stats (struct bgp *bgp, struct vty *vty); -extern void update_group_adjust_peer (struct peer_af *paf); -extern int update_group_adjust_soloness (struct peer *peer, int set); - -extern void -update_subgroup_remove_peer (struct update_subgroup *, struct peer_af *); -extern struct bgp_table *update_subgroup_rib (struct update_subgroup *); -extern void -update_subgroup_split_peer (struct peer_af *, struct update_group *); -extern int -update_subgroup_check_merge (struct update_subgroup *, const char *); +extern void update_bgp_group_init(struct bgp *); +extern void udpate_bgp_group_free(struct bgp *); + +extern void update_group_show(struct bgp *bgp, afi_t afi, safi_t safi, + struct vty *vty, uint64_t subgrp_id); +extern void update_group_show_stats(struct bgp *bgp, struct vty *vty); +extern void update_group_adjust_peer(struct peer_af *paf); +extern int update_group_adjust_soloness(struct peer *peer, int set); + +extern void update_subgroup_remove_peer(struct update_subgroup *, + struct peer_af *); +extern struct bgp_table *update_subgroup_rib(struct update_subgroup *); +extern void update_subgroup_split_peer(struct peer_af *, struct update_group *); +extern int update_subgroup_check_merge(struct update_subgroup *, const char *); +extern int update_subgroup_trigger_merge_check(struct update_subgroup *, + int force); +extern void update_group_policy_update(struct bgp *bgp, bgp_policy_type_e ptype, + const char *pname, int route_update, + int start_event); +extern void update_group_af_walk(struct bgp *bgp, afi_t afi, safi_t safi, + updgrp_walkcb cb, void *ctx); +extern void update_group_walk(struct bgp *bgp, updgrp_walkcb cb, void *ctx); +extern void update_group_periodic_merge(struct bgp *bgp); extern int -update_subgroup_trigger_merge_check (struct update_subgroup *, - int force); -extern void update_group_policy_update (struct bgp *bgp, - bgp_policy_type_e ptype, const char *pname, - int route_update, int start_event); -extern void update_group_af_walk (struct bgp *bgp, afi_t afi, safi_t safi, - updgrp_walkcb cb, void *ctx); -extern void update_group_walk (struct bgp *bgp, updgrp_walkcb cb, void *ctx); -extern void update_group_periodic_merge (struct bgp *bgp); -extern int update_group_refresh_default_originate_route_map (struct thread *thread); -extern void update_group_start_advtimer (struct bgp *bgp); - -extern void update_subgroup_inherit_info (struct update_subgroup *to, - struct update_subgroup *from); +update_group_refresh_default_originate_route_map(struct thread *thread); +extern void update_group_start_advtimer(struct bgp *bgp); + +extern void update_subgroup_inherit_info(struct update_subgroup *to, + struct update_subgroup *from); /* bgp_updgrp_packet.c */ -extern struct bpacket *bpacket_alloc (void); -extern void bpacket_free (struct bpacket *pkt); -extern void bpacket_queue_init (struct bpacket_queue *q); -extern void bpacket_queue_cleanup (struct bpacket_queue *q); -extern void bpacket_queue_sanity_check (struct bpacket_queue *q); -extern struct bpacket *bpacket_queue_add (struct bpacket_queue *q, - struct stream *s, - struct bpacket_attr_vec_arr - *vecarr); -struct bpacket *bpacket_queue_remove (struct bpacket_queue *q); -extern struct bpacket *bpacket_queue_first (struct bpacket_queue *q); -struct bpacket *bpacket_queue_last (struct bpacket_queue *q); -unsigned int bpacket_queue_length (struct bpacket_queue *q); -unsigned int bpacket_queue_hwm_length (struct bpacket_queue *q); -int bpacket_queue_is_full (struct bgp *bgp, struct bpacket_queue *q); -extern void bpacket_queue_advance_peer (struct peer_af *paf); -extern void bpacket_queue_remove_peer (struct peer_af *paf); -extern void bpacket_add_peer (struct bpacket *pkt, struct peer_af *paf); -unsigned int bpacket_queue_virtual_length (struct peer_af *paf); -extern void bpacket_queue_show_vty (struct bpacket_queue *q, struct vty *vty); -int subgroup_packets_to_build (struct update_subgroup *subgrp); -extern struct bpacket *subgroup_update_packet (struct update_subgroup *s); -extern struct bpacket *subgroup_withdraw_packet (struct update_subgroup *s); -extern struct stream *bpacket_reformat_for_peer (struct bpacket *pkt, - struct peer_af *paf); -extern void bpacket_attr_vec_arr_reset (struct bpacket_attr_vec_arr *vecarr); -extern void bpacket_attr_vec_arr_set_vec (struct bpacket_attr_vec_arr *vecarr, - bpacket_attr_vec_type type, - struct stream *s, - struct attr *attr); -extern void -subgroup_default_update_packet (struct update_subgroup *subgrp, - struct attr *attr, struct peer *from); -extern void subgroup_default_withdraw_packet (struct update_subgroup *subgrp); +extern struct bpacket *bpacket_alloc(void); +extern void bpacket_free(struct bpacket *pkt); +extern void bpacket_queue_init(struct bpacket_queue *q); +extern void bpacket_queue_cleanup(struct bpacket_queue *q); +extern void bpacket_queue_sanity_check(struct bpacket_queue *q); +extern struct bpacket *bpacket_queue_add(struct bpacket_queue *q, + struct stream *s, + struct bpacket_attr_vec_arr *vecarr); +struct bpacket *bpacket_queue_remove(struct bpacket_queue *q); +extern struct bpacket *bpacket_queue_first(struct bpacket_queue *q); +struct bpacket *bpacket_queue_last(struct bpacket_queue *q); +unsigned int bpacket_queue_length(struct bpacket_queue *q); +unsigned int bpacket_queue_hwm_length(struct bpacket_queue *q); +int bpacket_queue_is_full(struct bgp *bgp, struct bpacket_queue *q); +extern void bpacket_queue_advance_peer(struct peer_af *paf); +extern void bpacket_queue_remove_peer(struct peer_af *paf); +extern void bpacket_add_peer(struct bpacket *pkt, struct peer_af *paf); +unsigned int bpacket_queue_virtual_length(struct peer_af *paf); +extern void bpacket_queue_show_vty(struct bpacket_queue *q, struct vty *vty); +int subgroup_packets_to_build(struct update_subgroup *subgrp); +extern struct bpacket *subgroup_update_packet(struct update_subgroup *s); +extern struct bpacket *subgroup_withdraw_packet(struct update_subgroup *s); +extern struct stream *bpacket_reformat_for_peer(struct bpacket *pkt, + struct peer_af *paf); +extern void bpacket_attr_vec_arr_reset(struct bpacket_attr_vec_arr *vecarr); +extern void bpacket_attr_vec_arr_set_vec(struct bpacket_attr_vec_arr *vecarr, + bpacket_attr_vec_type type, + struct stream *s, struct attr *attr); +extern void subgroup_default_update_packet(struct update_subgroup *subgrp, + struct attr *attr, + struct peer *from); +extern void subgroup_default_withdraw_packet(struct update_subgroup *subgrp); /* bgp_updgrp_adv.c */ -extern struct bgp_advertise *bgp_advertise_clean_subgroup (struct - update_subgroup - *subgrp, - struct bgp_adj_out - *adj); -extern void update_group_show_adj_queue (struct bgp *bgp, afi_t afi, +extern struct bgp_advertise * +bgp_advertise_clean_subgroup(struct update_subgroup *subgrp, + struct bgp_adj_out *adj); +extern void update_group_show_adj_queue(struct bgp *bgp, afi_t afi, safi_t safi, + struct vty *vty, uint64_t id); +extern void update_group_show_advertised(struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty, uint64_t id); -extern void update_group_show_advertised (struct bgp *bgp, afi_t afi, - safi_t safi, struct vty *vty, - uint64_t id); -extern void update_group_show_packet_queue (struct bgp *bgp, afi_t afi, - safi_t safi, struct vty *vty, - uint64_t id); -extern void subgroup_announce_route (struct update_subgroup *subgrp); -extern void subgroup_announce_all (struct update_subgroup *subgrp); - -extern void -subgroup_default_originate (struct update_subgroup *subgrp, int withdraw); -extern void -group_announce_route (struct bgp *bgp, afi_t afi, safi_t safi, - struct bgp_node *rn, struct bgp_info *ri); -extern void subgroup_clear_table (struct update_subgroup *subgrp); -extern void update_group_announce (struct bgp *bgp); -extern void update_group_announce_rrclients (struct bgp *bgp); -extern void peer_af_announce_route (struct peer_af *paf, int combine); -extern struct bgp_adj_out *bgp_adj_out_alloc (struct update_subgroup *subgrp, - struct bgp_node *rn, - u_int32_t addpath_tx_id); -extern void bgp_adj_out_remove_subgroup (struct bgp_node *rn, - struct bgp_adj_out *adj, - struct update_subgroup *subgrp); -extern void -bgp_adj_out_set_subgroup (struct bgp_node *rn, - struct update_subgroup *subgrp, - struct attr *attr, struct bgp_info *binfo); -extern void -bgp_adj_out_unset_subgroup (struct bgp_node *rn, - struct update_subgroup *subgrp, - char withdraw, - u_int32_t addpath_tx_id); -void -subgroup_announce_table (struct update_subgroup *subgrp, - struct bgp_table *table); -extern void -subgroup_trigger_write (struct update_subgroup *subgrp); - -extern int -update_group_clear_update_dbg (struct update_group *updgrp, void *arg); +extern void update_group_show_packet_queue(struct bgp *bgp, afi_t afi, + safi_t safi, struct vty *vty, + uint64_t id); +extern void subgroup_announce_route(struct update_subgroup *subgrp); +extern void subgroup_announce_all(struct update_subgroup *subgrp); + +extern void subgroup_default_originate(struct update_subgroup *subgrp, + int withdraw); +extern void group_announce_route(struct bgp *bgp, afi_t afi, safi_t safi, + struct bgp_node *rn, struct bgp_info *ri); +extern void subgroup_clear_table(struct update_subgroup *subgrp); +extern void update_group_announce(struct bgp *bgp); +extern void update_group_announce_rrclients(struct bgp *bgp); +extern void peer_af_announce_route(struct peer_af *paf, int combine); +extern struct bgp_adj_out *bgp_adj_out_alloc(struct update_subgroup *subgrp, + struct bgp_node *rn, + u_int32_t addpath_tx_id); +extern void bgp_adj_out_remove_subgroup(struct bgp_node *rn, + struct bgp_adj_out *adj, + struct update_subgroup *subgrp); +extern void bgp_adj_out_set_subgroup(struct bgp_node *rn, + struct update_subgroup *subgrp, + struct attr *attr, struct bgp_info *binfo); +extern void bgp_adj_out_unset_subgroup(struct bgp_node *rn, + struct update_subgroup *subgrp, + char withdraw, u_int32_t addpath_tx_id); +void subgroup_announce_table(struct update_subgroup *subgrp, + struct bgp_table *table); +extern void subgroup_trigger_write(struct update_subgroup *subgrp); + +extern int update_group_clear_update_dbg(struct update_group *updgrp, + void *arg); extern void update_bgp_group_free(struct bgp *bgp); -extern int bgp_addpath_encode_tx (struct peer *peer, afi_t afi, safi_t safi); -extern int bgp_addpath_tx_path (struct peer *peer, afi_t afi, safi_t safi, - struct bgp_info *ri); +extern int bgp_addpath_encode_tx(struct peer *peer, afi_t afi, safi_t safi); +extern int bgp_addpath_tx_path(struct peer *peer, afi_t afi, safi_t safi, + struct bgp_info *ri); /* * Inline functions @@ -492,18 +459,17 @@ extern int bgp_addpath_tx_path (struct peer *peer, afi_t afi, safi_t safi, /* * bpacket_queue_is_empty */ -static inline int -bpacket_queue_is_empty (struct bpacket_queue *queue) +static inline int bpacket_queue_is_empty(struct bpacket_queue *queue) { - /* - * The packet queue is empty if it only contains a sentinel. - */ - if (queue->curr_count != 1) - return 0; + /* + * The packet queue is empty if it only contains a sentinel. + */ + if (queue->curr_count != 1) + return 0; - assert (bpacket_queue_first (queue)->buffer == NULL); - return 1; + assert(bpacket_queue_first(queue)->buffer == NULL); + return 1; } /* @@ -511,10 +477,9 @@ bpacket_queue_is_empty (struct bpacket_queue *queue) * * Returns the packet after the given packet in a bpacket queue. */ -static inline struct bpacket * -bpacket_next (struct bpacket *pkt) +static inline struct bpacket *bpacket_next(struct bpacket *pkt) { - return TAILQ_NEXT (pkt, pkt_train); + return TAILQ_NEXT(pkt, pkt_train); } /* @@ -522,18 +487,16 @@ bpacket_next (struct bpacket *pkt) * * Adjust all peer_af structures for the given peer. */ -static inline void -update_group_adjust_peer_afs (struct peer *peer) +static inline void update_group_adjust_peer_afs(struct peer *peer) { - struct peer_af *paf; - int afidx; - - for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) - { - paf = peer->peer_af_array[afidx]; - if (paf != NULL) - update_group_adjust_peer (paf); - } + struct peer_af *paf; + int afidx; + + for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) { + paf = peer->peer_af_array[afidx]; + if (paf != NULL) + update_group_adjust_peer(paf); + } } /* @@ -541,53 +504,51 @@ update_group_adjust_peer_afs (struct peer *peer) * * Remove all peer_af structures for the given peer from their subgroups. */ -static inline void -update_group_remove_peer_afs (struct peer *peer) +static inline void update_group_remove_peer_afs(struct peer *peer) { - struct peer_af *paf; - int afidx; - - for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) - { - paf = peer->peer_af_array[afidx]; - if (paf != NULL) - update_subgroup_remove_peer (PAF_SUBGRP (paf), paf); - } + struct peer_af *paf; + int afidx; + + for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) { + paf = peer->peer_af_array[afidx]; + if (paf != NULL) + update_subgroup_remove_peer(PAF_SUBGRP(paf), paf); + } } /* * update_subgroup_needs_refresh */ static inline int -update_subgroup_needs_refresh (const struct update_subgroup *subgrp) +update_subgroup_needs_refresh(const struct update_subgroup *subgrp) { - if (CHECK_FLAG (subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH)) - return 1; - else - return 0; + if (CHECK_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH)) + return 1; + else + return 0; } /* * update_subgroup_set_needs_refresh */ static inline void -update_subgroup_set_needs_refresh (struct update_subgroup *subgrp, int value) +update_subgroup_set_needs_refresh(struct update_subgroup *subgrp, int value) { - if (value) - SET_FLAG (subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH); - else - UNSET_FLAG (subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH); + if (value) + SET_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH); + else + UNSET_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH); } -static inline struct update_subgroup * -peer_subgroup (struct peer *peer, afi_t afi, safi_t safi) +static inline struct update_subgroup *peer_subgroup(struct peer *peer, + afi_t afi, safi_t safi) { - struct peer_af *paf; + struct peer_af *paf; - paf = peer_af_find (peer, afi, safi); - if (paf) - return PAF_SUBGRP (paf); - return NULL; + paf = peer_af_find(peer, afi, safi); + if (paf) + return PAF_SUBGRP(paf); + return NULL; } /* @@ -595,34 +556,30 @@ peer_subgroup (struct peer *peer, afi_t afi, safi_t safi) * * Adjust all peer_af structures for the given peer. */ -static inline void -bgp_announce_peer (struct peer *peer) +static inline void bgp_announce_peer(struct peer *peer) { - struct peer_af *paf; - int afidx; - - for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) - { - paf = peer->peer_af_array[afidx]; - if (paf != NULL) - subgroup_announce_all (PAF_SUBGRP (paf)); - } + struct peer_af *paf; + int afidx; + + for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) { + paf = peer->peer_af_array[afidx]; + if (paf != NULL) + subgroup_announce_all(PAF_SUBGRP(paf)); + } } /** * advertise_list_is_empty */ -static inline int -advertise_list_is_empty (struct update_subgroup *subgrp) +static inline int advertise_list_is_empty(struct update_subgroup *subgrp) { - if (!BGP_ADV_FIFO_EMPTY (&subgrp->sync->update) || - !BGP_ADV_FIFO_EMPTY (&subgrp->sync->withdraw) || - !BGP_ADV_FIFO_EMPTY (&subgrp->sync->withdraw_low)) - { - return 0; - } - - return 1; + if (!BGP_ADV_FIFO_EMPTY(&subgrp->sync->update) + || !BGP_ADV_FIFO_EMPTY(&subgrp->sync->withdraw) + || !BGP_ADV_FIFO_EMPTY(&subgrp->sync->withdraw_low)) { + return 0; + } + + return 1; } #endif /* _QUAGGA_BGP_UPDGRP_H */ diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index 5019830c0..0a33fa5ed 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -55,306 +55,306 @@ * PRIVATE FUNCTIONS ********************/ -static inline struct bgp_adj_out * -adj_lookup (struct bgp_node *rn, struct update_subgroup *subgrp, - u_int32_t addpath_tx_id) +static inline struct bgp_adj_out *adj_lookup(struct bgp_node *rn, + struct update_subgroup *subgrp, + u_int32_t addpath_tx_id) { - struct bgp_adj_out *adj; - struct peer *peer; - afi_t afi; - safi_t safi; - int addpath_capable; - - if (!rn || !subgrp) - return NULL; - - peer = SUBGRP_PEER (subgrp); - afi = SUBGRP_AFI (subgrp); - safi = SUBGRP_SAFI (subgrp); - addpath_capable = bgp_addpath_encode_tx (peer, afi, safi); - - /* update-groups that do not support addpath will pass 0 for - * addpath_tx_id so do not both matching against it */ - for (adj = rn->adj_out; adj; adj = adj->next) - { - if (adj->subgroup == subgrp) - { - if (addpath_capable) - { - if (adj->addpath_tx_id == addpath_tx_id) - { - break; - } - } - else - { - break; - } - } - } - - return adj; -} + struct bgp_adj_out *adj; + struct peer *peer; + afi_t afi; + safi_t safi; + int addpath_capable; + + if (!rn || !subgrp) + return NULL; + + peer = SUBGRP_PEER(subgrp); + afi = SUBGRP_AFI(subgrp); + safi = SUBGRP_SAFI(subgrp); + addpath_capable = bgp_addpath_encode_tx(peer, afi, safi); + + /* update-groups that do not support addpath will pass 0 for + * addpath_tx_id so do not both matching against it */ + for (adj = rn->adj_out; adj; adj = adj->next) { + if (adj->subgroup == subgrp) { + if (addpath_capable) { + if (adj->addpath_tx_id == addpath_tx_id) { + break; + } + } else { + break; + } + } + } -static void -adj_free (struct bgp_adj_out *adj) -{ - TAILQ_REMOVE (&(adj->subgroup->adjq), adj, subgrp_adj_train); - SUBGRP_DECR_STAT (adj->subgroup, adj_count); - XFREE (MTYPE_BGP_ADJ_OUT, adj); + return adj; } -static int -group_announce_route_walkcb (struct update_group *updgrp, void *arg) +static void adj_free(struct bgp_adj_out *adj) { - struct updwalk_context *ctx = arg; - struct update_subgroup *subgrp; - struct bgp_info *ri; - afi_t afi; - safi_t safi; - struct peer *peer; - struct bgp_adj_out *adj, *adj_next; - int addpath_capable; - - afi = UPDGRP_AFI (updgrp); - safi = UPDGRP_SAFI (updgrp); - peer = UPDGRP_PEER (updgrp); - addpath_capable = bgp_addpath_encode_tx (peer, afi, safi); - - UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) - { - - /* - * Skip the subgroups that have coalesce timer running. We will - * walk the entire prefix table for those subgroups when the - * coalesce timer fires. - */ - if (!subgrp->t_coalesce) - { - /* An update-group that uses addpath */ - if (addpath_capable) - { - /* Look through all of the paths we have advertised for this rn and - * send a withdraw for the ones that are no longer present */ - for (adj = ctx->rn->adj_out; adj; adj = adj_next) - { - adj_next = adj->next; - - if (adj->subgroup == subgrp) - { - for (ri = ctx->rn->info; ri; ri = ri->next) - { - if (ri->addpath_tx_id == adj->addpath_tx_id) - { - break; - } - } - - if (!ri) - { - subgroup_process_announce_selected (subgrp, NULL, ctx->rn, adj->addpath_tx_id); - } - } - } - - for (ri = ctx->rn->info; ri; ri = ri->next) - { - /* Skip the bestpath for now */ - if (ri == ctx->ri) - continue; - - subgroup_process_announce_selected (subgrp, ri, ctx->rn, ri->addpath_tx_id); - } - - /* Process the bestpath last so the "show [ip] bgp neighbor x.x.x.x advertised" - * output shows the attributes from the bestpath */ - if (ctx->ri) - subgroup_process_announce_selected (subgrp, ctx->ri, ctx->rn, ctx->ri->addpath_tx_id); - } - - /* An update-group that does not use addpath */ - else - { - if (ctx->ri) - { - subgroup_process_announce_selected (subgrp, ctx->ri, ctx->rn, ctx->ri->addpath_tx_id); - } - else - { - /* Find the addpath_tx_id of the path we had advertised and - * send a withdraw */ - for (adj = ctx->rn->adj_out; adj; adj = adj_next) - { - adj_next = adj->next; - - if (adj->subgroup == subgrp) - { - subgroup_process_announce_selected (subgrp, NULL, ctx->rn, adj->addpath_tx_id); - } - } - } - } - } - } - - return UPDWALK_CONTINUE; + TAILQ_REMOVE(&(adj->subgroup->adjq), adj, subgrp_adj_train); + SUBGRP_DECR_STAT(adj->subgroup, adj_count); + XFREE(MTYPE_BGP_ADJ_OUT, adj); } -static void -subgrp_show_adjq_vty (struct update_subgroup *subgrp, struct vty *vty, - u_int8_t flags) +static int group_announce_route_walkcb(struct update_group *updgrp, void *arg) { - struct bgp_table *table; - struct bgp_adj_out *adj; - unsigned long output_count; - struct bgp_node *rn; - int header1 = 1; - struct bgp *bgp; - int header2 = 1; - - bgp = SUBGRP_INST (subgrp); - if (!bgp) - return; + struct updwalk_context *ctx = arg; + struct update_subgroup *subgrp; + struct bgp_info *ri; + afi_t afi; + safi_t safi; + struct peer *peer; + struct bgp_adj_out *adj, *adj_next; + int addpath_capable; + + afi = UPDGRP_AFI(updgrp); + safi = UPDGRP_SAFI(updgrp); + peer = UPDGRP_PEER(updgrp); + addpath_capable = bgp_addpath_encode_tx(peer, afi, safi); + + UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) + { - table = bgp->rib[SUBGRP_AFI (subgrp)][SUBGRP_SAFI (subgrp)]; + /* + * Skip the subgroups that have coalesce timer running. We will + * walk the entire prefix table for those subgroups when the + * coalesce timer fires. + */ + if (!subgrp->t_coalesce) { + /* An update-group that uses addpath */ + if (addpath_capable) { + /* Look through all of the paths we have + * advertised for this rn and + * send a withdraw for the ones that are no + * longer present */ + for (adj = ctx->rn->adj_out; adj; + adj = adj_next) { + adj_next = adj->next; + + if (adj->subgroup == subgrp) { + for (ri = ctx->rn->info; ri; + ri = ri->next) { + if (ri->addpath_tx_id + == adj->addpath_tx_id) { + break; + } + } + + if (!ri) { + subgroup_process_announce_selected( + subgrp, NULL, + ctx->rn, + adj->addpath_tx_id); + } + } + } + + for (ri = ctx->rn->info; ri; ri = ri->next) { + /* Skip the bestpath for now */ + if (ri == ctx->ri) + continue; + + subgroup_process_announce_selected( + subgrp, ri, ctx->rn, + ri->addpath_tx_id); + } + + /* Process the bestpath last so the "show [ip] + * bgp neighbor x.x.x.x advertised" + * output shows the attributes from the bestpath + */ + if (ctx->ri) + subgroup_process_announce_selected( + subgrp, ctx->ri, ctx->rn, + ctx->ri->addpath_tx_id); + } + + /* An update-group that does not use addpath */ + else { + if (ctx->ri) { + subgroup_process_announce_selected( + subgrp, ctx->ri, ctx->rn, + ctx->ri->addpath_tx_id); + } else { + /* Find the addpath_tx_id of the path we + * had advertised and + * send a withdraw */ + for (adj = ctx->rn->adj_out; adj; + adj = adj_next) { + adj_next = adj->next; + + if (adj->subgroup == subgrp) { + subgroup_process_announce_selected( + subgrp, NULL, + ctx->rn, + adj->addpath_tx_id); + } + } + } + } + } + } - output_count = 0; + return UPDWALK_CONTINUE; +} - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - for (adj = rn->adj_out; adj; adj = adj->next) - if (adj->subgroup == subgrp) - { - if (header1) - { - vty_out (vty, - "BGP table version is %" PRIu64 ", local router ID is %s\n", - table->version,inet_ntoa(bgp->router_id)); - vty_out (vty, BGP_SHOW_SCODE_HEADER); - vty_out (vty, BGP_SHOW_OCODE_HEADER); - header1 = 0; - } - if (header2) - { - vty_out (vty, BGP_SHOW_HEADER); - header2 = 0; - } - if ((flags & UPDWALK_FLAGS_ADVQUEUE) && adj->adv && adj->adv->baa) - { - route_vty_out_tmp (vty, &rn->p, adj->adv->baa->attr, SUBGRP_SAFI (subgrp), 0, NULL); - output_count++; - } - if ((flags & UPDWALK_FLAGS_ADVERTISED) && adj->attr) - { - route_vty_out_tmp (vty, &rn->p, adj->attr, SUBGRP_SAFI (subgrp), 0, NULL); - output_count++; - } - } - if (output_count != 0) - vty_out (vty, "\nTotal number of prefixes %ld\n", output_count); +static void subgrp_show_adjq_vty(struct update_subgroup *subgrp, + struct vty *vty, u_int8_t flags) +{ + struct bgp_table *table; + struct bgp_adj_out *adj; + unsigned long output_count; + struct bgp_node *rn; + int header1 = 1; + struct bgp *bgp; + int header2 = 1; + + bgp = SUBGRP_INST(subgrp); + if (!bgp) + return; + + table = bgp->rib[SUBGRP_AFI(subgrp)][SUBGRP_SAFI(subgrp)]; + + output_count = 0; + + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) + for (adj = rn->adj_out; adj; adj = adj->next) + if (adj->subgroup == subgrp) { + if (header1) { + vty_out(vty, + "BGP table version is %" PRIu64 + ", local router ID is %s\n", + table->version, + inet_ntoa(bgp->router_id)); + vty_out(vty, BGP_SHOW_SCODE_HEADER); + vty_out(vty, BGP_SHOW_OCODE_HEADER); + header1 = 0; + } + if (header2) { + vty_out(vty, BGP_SHOW_HEADER); + header2 = 0; + } + if ((flags & UPDWALK_FLAGS_ADVQUEUE) && adj->adv + && adj->adv->baa) { + route_vty_out_tmp(vty, &rn->p, + adj->adv->baa->attr, + SUBGRP_SAFI(subgrp), + 0, NULL); + output_count++; + } + if ((flags & UPDWALK_FLAGS_ADVERTISED) + && adj->attr) { + route_vty_out_tmp( + vty, &rn->p, adj->attr, + SUBGRP_SAFI(subgrp), 0, NULL); + output_count++; + } + } + if (output_count != 0) + vty_out(vty, "\nTotal number of prefixes %ld\n", output_count); } -static int -updgrp_show_adj_walkcb (struct update_group *updgrp, void *arg) +static int updgrp_show_adj_walkcb(struct update_group *updgrp, void *arg) { - struct updwalk_context *ctx = arg; - struct update_subgroup *subgrp; - struct vty *vty; - - vty = ctx->vty; - UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) - { - if (ctx->subgrp_id && (ctx->subgrp_id != subgrp->id)) - continue; - vty_out (vty, "update group %" PRIu64 ", subgroup %" PRIu64 "\n", updgrp->id, - subgrp->id); - subgrp_show_adjq_vty (subgrp, vty, ctx->flags); - } - return UPDWALK_CONTINUE; + struct updwalk_context *ctx = arg; + struct update_subgroup *subgrp; + struct vty *vty; + + vty = ctx->vty; + UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) + { + if (ctx->subgrp_id && (ctx->subgrp_id != subgrp->id)) + continue; + vty_out(vty, "update group %" PRIu64 ", subgroup %" PRIu64 "\n", + updgrp->id, subgrp->id); + subgrp_show_adjq_vty(subgrp, vty, ctx->flags); + } + return UPDWALK_CONTINUE; } -static void -updgrp_show_adj (struct bgp *bgp, afi_t afi, safi_t safi, - struct vty *vty, uint64_t id, u_int8_t flags) +static void updgrp_show_adj(struct bgp *bgp, afi_t afi, safi_t safi, + struct vty *vty, uint64_t id, u_int8_t flags) { - struct updwalk_context ctx; - memset (&ctx, 0, sizeof (ctx)); - ctx.vty = vty; - ctx.subgrp_id = id; - ctx.flags = flags; + struct updwalk_context ctx; + memset(&ctx, 0, sizeof(ctx)); + ctx.vty = vty; + ctx.subgrp_id = id; + ctx.flags = flags; - update_group_af_walk (bgp, afi, safi, updgrp_show_adj_walkcb, &ctx); + update_group_af_walk(bgp, afi, safi, updgrp_show_adj_walkcb, &ctx); } -static int -subgroup_coalesce_timer (struct thread *thread) +static int subgroup_coalesce_timer(struct thread *thread) { - struct update_subgroup *subgrp; - - subgrp = THREAD_ARG (thread); - if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0)) - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " announcing routes upon coalesce timer expiry", - (SUBGRP_UPDGRP (subgrp))->id, subgrp->id); - subgrp->t_coalesce = NULL; - subgrp->v_coalesce = 0; - subgroup_announce_route (subgrp); - - - /* While the announce_route() may kick off the route advertisement timer for - * the members of the subgroup, we'd like to send the initial updates much - * faster (i.e., without enforcing MRAI). Also, if there were no routes to - * announce, this is the method currently employed to trigger the EOR. - */ - if (!bgp_update_delay_active(SUBGRP_INST(subgrp))) - { - struct peer_af *paf; - struct peer *peer; - - SUBGRP_FOREACH_PEER (subgrp, paf) - { - peer = PAF_PEER(paf); - BGP_TIMER_OFF(peer->t_routeadv); - BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 0); - } - } - - return 0; + struct update_subgroup *subgrp; + + subgrp = THREAD_ARG(thread); + if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0)) + zlog_debug("u%" PRIu64 ":s%" PRIu64 + " announcing routes upon coalesce timer expiry", + (SUBGRP_UPDGRP(subgrp))->id, subgrp->id); + subgrp->t_coalesce = NULL; + subgrp->v_coalesce = 0; + subgroup_announce_route(subgrp); + + + /* While the announce_route() may kick off the route advertisement timer + * for + * the members of the subgroup, we'd like to send the initial updates + * much + * faster (i.e., without enforcing MRAI). Also, if there were no routes + * to + * announce, this is the method currently employed to trigger the EOR. + */ + if (!bgp_update_delay_active(SUBGRP_INST(subgrp))) { + struct peer_af *paf; + struct peer *peer; + + SUBGRP_FOREACH_PEER(subgrp, paf) + { + peer = PAF_PEER(paf); + BGP_TIMER_OFF(peer->t_routeadv); + BGP_TIMER_ON(peer->t_routeadv, bgp_routeadv_timer, 0); + } + } + + return 0; } -static int -update_group_announce_walkcb (struct update_group *updgrp, void *arg) +static int update_group_announce_walkcb(struct update_group *updgrp, void *arg) { - struct update_subgroup *subgrp; + struct update_subgroup *subgrp; - UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) - { - subgroup_announce_all (subgrp); - } + UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) + { + subgroup_announce_all(subgrp); + } - return UPDWALK_CONTINUE; + return UPDWALK_CONTINUE; } -static int -update_group_announce_rrc_walkcb (struct update_group *updgrp, void *arg) +static int update_group_announce_rrc_walkcb(struct update_group *updgrp, + void *arg) { - struct update_subgroup *subgrp; - afi_t afi; - safi_t safi; - struct peer *peer; - - afi = UPDGRP_AFI (updgrp); - safi = UPDGRP_SAFI (updgrp); - peer = UPDGRP_PEER (updgrp); - - /* Only announce if this is a group of route-reflector-clients */ - if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) - { - UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) - { - subgroup_announce_all (subgrp); - } - } - - return UPDWALK_CONTINUE; + struct update_subgroup *subgrp; + afi_t afi; + safi_t safi; + struct peer *peer; + + afi = UPDGRP_AFI(updgrp); + safi = UPDGRP_SAFI(updgrp); + peer = UPDGRP_PEER(updgrp); + + /* Only announce if this is a group of route-reflector-clients */ + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) { + UPDGRP_FOREACH_SUBGRP(updgrp, subgrp) + { + subgroup_announce_all(subgrp); + } + } + + return UPDWALK_CONTINUE; } /******************** @@ -365,275 +365,265 @@ update_group_announce_rrc_walkcb (struct update_group *updgrp, void *arg) * Allocate an adj-out object. Do proper initialization of its fields, * primarily its association with the subgroup and the prefix. */ -struct bgp_adj_out * -bgp_adj_out_alloc (struct update_subgroup *subgrp, struct bgp_node *rn, - u_int32_t addpath_tx_id) +struct bgp_adj_out *bgp_adj_out_alloc(struct update_subgroup *subgrp, + struct bgp_node *rn, + u_int32_t addpath_tx_id) { - struct bgp_adj_out *adj; - - adj = XCALLOC (MTYPE_BGP_ADJ_OUT, sizeof (struct bgp_adj_out)); - adj->subgroup = subgrp; - if (rn) - { - BGP_ADJ_OUT_ADD (rn, adj); - bgp_lock_node (rn); - adj->rn = rn; - } - - adj->addpath_tx_id = addpath_tx_id; - TAILQ_INSERT_TAIL (&(subgrp->adjq), adj, subgrp_adj_train); - SUBGRP_INCR_STAT (subgrp, adj_count); - return adj; + struct bgp_adj_out *adj; + + adj = XCALLOC(MTYPE_BGP_ADJ_OUT, sizeof(struct bgp_adj_out)); + adj->subgroup = subgrp; + if (rn) { + BGP_ADJ_OUT_ADD(rn, adj); + bgp_lock_node(rn); + adj->rn = rn; + } + + adj->addpath_tx_id = addpath_tx_id; + TAILQ_INSERT_TAIL(&(subgrp->adjq), adj, subgrp_adj_train); + SUBGRP_INCR_STAT(subgrp, adj_count); + return adj; } struct bgp_advertise * -bgp_advertise_clean_subgroup (struct update_subgroup *subgrp, - struct bgp_adj_out *adj) +bgp_advertise_clean_subgroup(struct update_subgroup *subgrp, + struct bgp_adj_out *adj) { - struct bgp_advertise *adv; - struct bgp_advertise_attr *baa; - struct bgp_advertise *next; - struct bgp_advertise_fifo *fhead; + struct bgp_advertise *adv; + struct bgp_advertise_attr *baa; + struct bgp_advertise *next; + struct bgp_advertise_fifo *fhead; - adv = adj->adv; - baa = adv->baa; - next = NULL; + adv = adj->adv; + baa = adv->baa; + next = NULL; - if (baa) - { - fhead = &subgrp->sync->update; + if (baa) { + fhead = &subgrp->sync->update; - /* Unlink myself from advertise attribute FIFO. */ - bgp_advertise_delete (baa, adv); + /* Unlink myself from advertise attribute FIFO. */ + bgp_advertise_delete(baa, adv); - /* Fetch next advertise candidate. */ - next = baa->adv; + /* Fetch next advertise candidate. */ + next = baa->adv; - /* Unintern BGP advertise attribute. */ - bgp_advertise_unintern (subgrp->hash, baa); - } - else - fhead = &subgrp->sync->withdraw; + /* Unintern BGP advertise attribute. */ + bgp_advertise_unintern(subgrp->hash, baa); + } else + fhead = &subgrp->sync->withdraw; - /* Unlink myself from advertisement FIFO. */ - BGP_ADV_FIFO_DEL (fhead, adv); + /* Unlink myself from advertisement FIFO. */ + BGP_ADV_FIFO_DEL(fhead, adv); - /* Free memory. */ - bgp_advertise_free (adj->adv); - adj->adv = NULL; + /* Free memory. */ + bgp_advertise_free(adj->adv); + adj->adv = NULL; - return next; + return next; } -void -bgp_adj_out_set_subgroup (struct bgp_node *rn, - struct update_subgroup *subgrp, - struct attr *attr, struct bgp_info *binfo) +void bgp_adj_out_set_subgroup(struct bgp_node *rn, + struct update_subgroup *subgrp, struct attr *attr, + struct bgp_info *binfo) { - struct bgp_adj_out *adj = NULL; - struct bgp_advertise *adv; - - if (DISABLE_BGP_ANNOUNCE) - return; - - /* Look for adjacency information. */ - adj = adj_lookup (rn, subgrp, binfo->addpath_tx_id); - - if (!adj) - { - adj = bgp_adj_out_alloc (subgrp, rn, binfo->addpath_tx_id); - if (!adj) - return; - } - - if (adj->adv) - bgp_advertise_clean_subgroup (subgrp, adj); - adj->adv = bgp_advertise_new (); - - adv = adj->adv; - adv->rn = rn; - assert (adv->binfo == NULL); - adv->binfo = bgp_info_lock (binfo); /* bgp_info adj_out reference */ - - if (attr) - adv->baa = bgp_advertise_intern (subgrp->hash, attr); - else - adv->baa = baa_new (); - adv->adj = adj; - - /* Add new advertisement to advertisement attribute list. */ - bgp_advertise_add (adv->baa, adv); - - /* - * If the update adv list is empty, trigger the member peers' - * mrai timers so the socket writes can happen. - */ - if (BGP_ADV_FIFO_EMPTY (&subgrp->sync->update)) - { - struct peer_af *paf; - - SUBGRP_FOREACH_PEER (subgrp, paf) - { - bgp_adjust_routeadv (PAF_PEER (paf)); + struct bgp_adj_out *adj = NULL; + struct bgp_advertise *adv; + + if (DISABLE_BGP_ANNOUNCE) + return; + + /* Look for adjacency information. */ + adj = adj_lookup(rn, subgrp, binfo->addpath_tx_id); + + if (!adj) { + adj = bgp_adj_out_alloc(subgrp, rn, binfo->addpath_tx_id); + if (!adj) + return; + } + + if (adj->adv) + bgp_advertise_clean_subgroup(subgrp, adj); + adj->adv = bgp_advertise_new(); + + adv = adj->adv; + adv->rn = rn; + assert(adv->binfo == NULL); + adv->binfo = bgp_info_lock(binfo); /* bgp_info adj_out reference */ + + if (attr) + adv->baa = bgp_advertise_intern(subgrp->hash, attr); + else + adv->baa = baa_new(); + adv->adj = adj; + + /* Add new advertisement to advertisement attribute list. */ + bgp_advertise_add(adv->baa, adv); + + /* + * If the update adv list is empty, trigger the member peers' + * mrai timers so the socket writes can happen. + */ + if (BGP_ADV_FIFO_EMPTY(&subgrp->sync->update)) { + struct peer_af *paf; + + SUBGRP_FOREACH_PEER(subgrp, paf) + { + bgp_adjust_routeadv(PAF_PEER(paf)); + } } - } - BGP_ADV_FIFO_ADD (&subgrp->sync->update, &adv->fifo); + BGP_ADV_FIFO_ADD(&subgrp->sync->update, &adv->fifo); - subgrp->version = max (subgrp->version, rn->version); + subgrp->version = max(subgrp->version, rn->version); } /* The only time 'withdraw' will be false is if we are sending * the "neighbor x.x.x.x default-originate" default and need to clear * bgp_adj_out for the 0.0.0.0/0 route in the BGP table. */ -void -bgp_adj_out_unset_subgroup (struct bgp_node *rn, - struct update_subgroup *subgrp, - char withdraw, - u_int32_t addpath_tx_id) +void bgp_adj_out_unset_subgroup(struct bgp_node *rn, + struct update_subgroup *subgrp, char withdraw, + u_int32_t addpath_tx_id) { - struct bgp_adj_out *adj; - struct bgp_advertise *adv; - char trigger_write; - - if (DISABLE_BGP_ANNOUNCE) - return; - - /* Lookup existing adjacency */ - if ((adj = adj_lookup (rn, subgrp, addpath_tx_id)) != NULL) - { - /* Clean up previous advertisement. */ - if (adj->adv) - bgp_advertise_clean_subgroup (subgrp, adj); - - if (adj->attr && withdraw) - { - /* We need advertisement structure. */ - adj->adv = bgp_advertise_new (); - adv = adj->adv; - adv->rn = rn; - adv->adj = adj; - - /* Note if we need to trigger a packet write */ - if (BGP_ADV_FIFO_EMPTY (&subgrp->sync->withdraw)) - trigger_write = 1; - else - trigger_write = 0; - - /* Add to synchronization entry for withdraw announcement. */ - BGP_ADV_FIFO_ADD (&subgrp->sync->withdraw, &adv->fifo); - - /* Schedule packet write, if FIFO is getting its first entry. */ - if (trigger_write) - subgroup_trigger_write(subgrp); - } - else - { - /* Remove myself from adjacency. */ - BGP_ADJ_OUT_DEL (rn, adj); - - /* Free allocated information. */ - adj_free (adj); - - bgp_unlock_node (rn); - } - } - - subgrp->version = max (subgrp->version, rn->version); + struct bgp_adj_out *adj; + struct bgp_advertise *adv; + char trigger_write; + + if (DISABLE_BGP_ANNOUNCE) + return; + + /* Lookup existing adjacency */ + if ((adj = adj_lookup(rn, subgrp, addpath_tx_id)) != NULL) { + /* Clean up previous advertisement. */ + if (adj->adv) + bgp_advertise_clean_subgroup(subgrp, adj); + + if (adj->attr && withdraw) { + /* We need advertisement structure. */ + adj->adv = bgp_advertise_new(); + adv = adj->adv; + adv->rn = rn; + adv->adj = adj; + + /* Note if we need to trigger a packet write */ + if (BGP_ADV_FIFO_EMPTY(&subgrp->sync->withdraw)) + trigger_write = 1; + else + trigger_write = 0; + + /* Add to synchronization entry for withdraw + * announcement. */ + BGP_ADV_FIFO_ADD(&subgrp->sync->withdraw, &adv->fifo); + + /* Schedule packet write, if FIFO is getting its first + * entry. */ + if (trigger_write) + subgroup_trigger_write(subgrp); + } else { + /* Remove myself from adjacency. */ + BGP_ADJ_OUT_DEL(rn, adj); + + /* Free allocated information. */ + adj_free(adj); + + bgp_unlock_node(rn); + } + } + + subgrp->version = max(subgrp->version, rn->version); } -void -bgp_adj_out_remove_subgroup (struct bgp_node *rn, struct bgp_adj_out *adj, - struct update_subgroup *subgrp) +void bgp_adj_out_remove_subgroup(struct bgp_node *rn, struct bgp_adj_out *adj, + struct update_subgroup *subgrp) { - if (adj->attr) - bgp_attr_unintern (&adj->attr); + if (adj->attr) + bgp_attr_unintern(&adj->attr); - if (adj->adv) - bgp_advertise_clean_subgroup (subgrp, adj); + if (adj->adv) + bgp_advertise_clean_subgroup(subgrp, adj); - BGP_ADJ_OUT_DEL (rn, adj); - adj_free (adj); + BGP_ADJ_OUT_DEL(rn, adj); + adj_free(adj); } /* * Go through all the routes and clean up the adj/adv structures corresponding * to the subgroup. */ -void -subgroup_clear_table (struct update_subgroup *subgrp) +void subgroup_clear_table(struct update_subgroup *subgrp) { - struct bgp_adj_out *aout, *taout; - - SUBGRP_FOREACH_ADJ_SAFE (subgrp, aout, taout) - { - struct bgp_node *rn = aout->rn; - bgp_adj_out_remove_subgroup (rn, aout, subgrp); - bgp_unlock_node (rn); - } + struct bgp_adj_out *aout, *taout; + + SUBGRP_FOREACH_ADJ_SAFE(subgrp, aout, taout) + { + struct bgp_node *rn = aout->rn; + bgp_adj_out_remove_subgroup(rn, aout, subgrp); + bgp_unlock_node(rn); + } } /* * subgroup_announce_table */ -void -subgroup_announce_table (struct update_subgroup *subgrp, - struct bgp_table *table) +void subgroup_announce_table(struct update_subgroup *subgrp, + struct bgp_table *table) { - struct bgp_node *rn; - struct bgp_info *ri; - struct attr attr; - struct peer *peer; - afi_t afi; - safi_t safi; - int addpath_capable; - - peer = SUBGRP_PEER (subgrp); - afi = SUBGRP_AFI (subgrp); - safi = SUBGRP_SAFI (subgrp); - addpath_capable = bgp_addpath_encode_tx (peer, afi, safi); - - if (safi == SAFI_LABELED_UNICAST) - safi = SAFI_UNICAST; - - if (!table) - table = peer->bgp->rib[afi][safi]; - - if (safi != SAFI_MPLS_VPN - && safi != SAFI_ENCAP - && safi != SAFI_EVPN - && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)) - subgroup_default_originate (subgrp, 0); - - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - for (ri = rn->info; ri; ri = ri->next) - - if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) || - (addpath_capable && bgp_addpath_tx_path(peer, afi, safi, ri))) - { - if (subgroup_announce_check (rn, ri, subgrp, &rn->p, &attr)) - bgp_adj_out_set_subgroup (rn, subgrp, &attr, ri); - else - bgp_adj_out_unset_subgroup (rn, subgrp, 1, ri->addpath_tx_id); - } - - /* - * We walked through the whole table -- make sure our version number - * is consistent with the one on the table. This should allow - * subgroups to merge sooner if a peer comes up when the route node - * with the largest version is no longer in the table. This also - * covers the pathological case where all routes in the table have - * now been deleted. - */ - subgrp->version = max (subgrp->version, table->version); - - /* - * Start a task to merge the subgroup if necessary. - */ - update_subgroup_trigger_merge_check (subgrp, 0); + struct bgp_node *rn; + struct bgp_info *ri; + struct attr attr; + struct peer *peer; + afi_t afi; + safi_t safi; + int addpath_capable; + + peer = SUBGRP_PEER(subgrp); + afi = SUBGRP_AFI(subgrp); + safi = SUBGRP_SAFI(subgrp); + addpath_capable = bgp_addpath_encode_tx(peer, afi, safi); + + if (safi == SAFI_LABELED_UNICAST) + safi = SAFI_UNICAST; + + if (!table) + table = peer->bgp->rib[afi][safi]; + + if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN + && CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_DEFAULT_ORIGINATE)) + subgroup_default_originate(subgrp, 0); + + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) + for (ri = rn->info; ri; ri = ri->next) + + if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED) + || (addpath_capable + && bgp_addpath_tx_path(peer, afi, safi, ri))) { + if (subgroup_announce_check(rn, ri, subgrp, + &rn->p, &attr)) + bgp_adj_out_set_subgroup(rn, subgrp, + &attr, ri); + else + bgp_adj_out_unset_subgroup( + rn, subgrp, 1, + ri->addpath_tx_id); + } + + /* + * We walked through the whole table -- make sure our version number + * is consistent with the one on the table. This should allow + * subgroups to merge sooner if a peer comes up when the route node + * with the largest version is no longer in the table. This also + * covers the pathological case where all routes in the table have + * now been deleted. + */ + subgrp->version = max(subgrp->version, table->version); + + /* + * Start a task to merge the subgroup if necessary. + */ + update_subgroup_trigger_merge_check(subgrp, 0); } /* @@ -641,151 +631,149 @@ subgroup_announce_table (struct update_subgroup *subgrp, * * Refresh all routes out to a subgroup. */ -void -subgroup_announce_route (struct update_subgroup *subgrp) +void subgroup_announce_route(struct update_subgroup *subgrp) { - struct bgp_node *rn; - struct bgp_table *table; - struct peer *onlypeer; - - if (update_subgroup_needs_refresh (subgrp)) - { - update_subgroup_set_needs_refresh (subgrp, 0); - } - - /* - * First update is deferred until ORF or ROUTE-REFRESH is received - */ - onlypeer = ((SUBGRP_PCOUNT (subgrp) == 1) ? - (SUBGRP_PFIRST (subgrp))->peer : NULL); - if (onlypeer && - CHECK_FLAG (onlypeer-> - af_sflags[SUBGRP_AFI (subgrp)][SUBGRP_SAFI (subgrp)], - PEER_STATUS_ORF_WAIT_REFRESH)) - return; - - if (SUBGRP_SAFI (subgrp) != SAFI_MPLS_VPN && - SUBGRP_SAFI (subgrp) != SAFI_ENCAP && - SUBGRP_SAFI (subgrp) != SAFI_EVPN) - subgroup_announce_table (subgrp, NULL); - else - for (rn = bgp_table_top (update_subgroup_rib (subgrp)); rn; - rn = bgp_route_next (rn)) - if ((table = (rn->info)) != NULL) - subgroup_announce_table (subgrp, table); + struct bgp_node *rn; + struct bgp_table *table; + struct peer *onlypeer; + + if (update_subgroup_needs_refresh(subgrp)) { + update_subgroup_set_needs_refresh(subgrp, 0); + } + + /* + * First update is deferred until ORF or ROUTE-REFRESH is received + */ + onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer + : NULL); + if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[SUBGRP_AFI(subgrp)] + [SUBGRP_SAFI(subgrp)], + PEER_STATUS_ORF_WAIT_REFRESH)) + return; + + if (SUBGRP_SAFI(subgrp) != SAFI_MPLS_VPN + && SUBGRP_SAFI(subgrp) != SAFI_ENCAP + && SUBGRP_SAFI(subgrp) != SAFI_EVPN) + subgroup_announce_table(subgrp, NULL); + else + for (rn = bgp_table_top(update_subgroup_rib(subgrp)); rn; + rn = bgp_route_next(rn)) + if ((table = (rn->info)) != NULL) + subgroup_announce_table(subgrp, table); } -void -subgroup_default_originate (struct update_subgroup *subgrp, int withdraw) +void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) { - struct bgp *bgp; - struct attr attr; - struct aspath *aspath; - struct prefix p; - struct peer *from; - struct bgp_node *rn; - struct bgp_info *ri; - struct peer *peer; - int ret = RMAP_DENYMATCH; - afi_t afi; - safi_t safi; - - if (!subgrp) - return; - - peer = SUBGRP_PEER (subgrp); - afi = SUBGRP_AFI (subgrp); - safi = SUBGRP_SAFI (subgrp); - - if (!(afi == AFI_IP || afi == AFI_IP6)) - return; - - bgp = peer->bgp; - from = bgp->peer_self; - - bgp_attr_default_set (&attr, BGP_ORIGIN_IGP); - aspath = attr.aspath; - attr.local_pref = bgp->default_local_pref; - - if (afi == AFI_IP) - str2prefix ("0.0.0.0/0", &p); - else if (afi == AFI_IP6) - { - str2prefix ("::/0", &p); - - /* IPv6 global nexthop must be included. */ - attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; - - /* If the peer is on shared nextwork and we have link-local - nexthop set it. */ - if (peer->shared_network - && !IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_local)) - attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; - } - - if (peer->default_rmap[afi][safi].name) - { - SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_DEFAULT); - for (rn = bgp_table_top (bgp->rib[afi][safi]); rn; - rn = bgp_route_next (rn)) - { - for (ri = rn->info; ri; ri = ri->next) - { - struct attr dummy_attr; - struct bgp_info info; - - /* Provide dummy so the route-map can't modify the attributes */ - bgp_attr_dup (&dummy_attr, ri->attr); - info.peer = ri->peer; - info.attr = &dummy_attr; - - ret = - route_map_apply (peer->default_rmap[afi][safi].map, &rn->p, - RMAP_BGP, &info); - - /* The route map might have set attributes. If we don't flush them - * here, they will be leaked. */ - bgp_attr_flush (&dummy_attr); - if (ret != RMAP_DENYMATCH) - break; - } - if (ret != RMAP_DENYMATCH) - break; + struct bgp *bgp; + struct attr attr; + struct aspath *aspath; + struct prefix p; + struct peer *from; + struct bgp_node *rn; + struct bgp_info *ri; + struct peer *peer; + int ret = RMAP_DENYMATCH; + afi_t afi; + safi_t safi; + + if (!subgrp) + return; + + peer = SUBGRP_PEER(subgrp); + afi = SUBGRP_AFI(subgrp); + safi = SUBGRP_SAFI(subgrp); + + if (!(afi == AFI_IP || afi == AFI_IP6)) + return; + + bgp = peer->bgp; + from = bgp->peer_self; + + bgp_attr_default_set(&attr, BGP_ORIGIN_IGP); + aspath = attr.aspath; + attr.local_pref = bgp->default_local_pref; + + if (afi == AFI_IP) + str2prefix("0.0.0.0/0", &p); + else if (afi == AFI_IP6) { + str2prefix("::/0", &p); + + /* IPv6 global nexthop must be included. */ + attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; + + /* If the peer is on shared nextwork and we have link-local + nexthop set it. */ + if (peer->shared_network + && !IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_local)) + attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; } - bgp->peer_self->rmap_type = 0; - - if (ret == RMAP_DENYMATCH) - withdraw = 1; - } - - if (withdraw) - { - if (CHECK_FLAG (subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) - subgroup_default_withdraw_packet (subgrp); - UNSET_FLAG (subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE); - } - else - { - if (!CHECK_FLAG (subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) - { - SET_FLAG (subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE); - subgroup_default_update_packet (subgrp, &attr, from); - - /* The 'neighbor x.x.x.x default-originate' default will act as an - * implicit withdraw for any previous UPDATEs sent for 0.0.0.0/0 so - * clear adj_out for the 0.0.0.0/0 prefix in the BGP table. - */ - if (afi == AFI_IP) - str2prefix ("0.0.0.0/0", &p); - else - str2prefix ("::/0", &p); - - rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, &p, NULL); - bgp_adj_out_unset_subgroup (rn, subgrp, 0, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); + + if (peer->default_rmap[afi][safi].name) { + SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_DEFAULT); + for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; + rn = bgp_route_next(rn)) { + for (ri = rn->info; ri; ri = ri->next) { + struct attr dummy_attr; + struct bgp_info info; + + /* Provide dummy so the route-map can't modify + * the attributes */ + bgp_attr_dup(&dummy_attr, ri->attr); + info.peer = ri->peer; + info.attr = &dummy_attr; + + ret = route_map_apply( + peer->default_rmap[afi][safi].map, + &rn->p, RMAP_BGP, &info); + + /* The route map might have set attributes. If + * we don't flush them + * here, they will be leaked. */ + bgp_attr_flush(&dummy_attr); + if (ret != RMAP_DENYMATCH) + break; + } + if (ret != RMAP_DENYMATCH) + break; + } + bgp->peer_self->rmap_type = 0; + + if (ret == RMAP_DENYMATCH) + withdraw = 1; } - } - aspath_unintern (&aspath); + if (withdraw) { + if (CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) + subgroup_default_withdraw_packet(subgrp); + UNSET_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE); + } else { + if (!CHECK_FLAG(subgrp->sflags, + SUBGRP_STATUS_DEFAULT_ORIGINATE)) { + SET_FLAG(subgrp->sflags, + SUBGRP_STATUS_DEFAULT_ORIGINATE); + subgroup_default_update_packet(subgrp, &attr, from); + + /* The 'neighbor x.x.x.x default-originate' default will + * act as an + * implicit withdraw for any previous UPDATEs sent for + * 0.0.0.0/0 so + * clear adj_out for the 0.0.0.0/0 prefix in the BGP + * table. + */ + if (afi == AFI_IP) + str2prefix("0.0.0.0/0", &p); + else + str2prefix("::/0", &p); + + rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, + &p, NULL); + bgp_adj_out_unset_subgroup( + rn, subgrp, 0, + BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); + } + } + + aspath_unintern(&aspath); } /* @@ -796,70 +784,64 @@ subgroup_default_originate (struct update_subgroup *subgrp, int withdraw) * subgrp->v_coalesce will be set to zero and the normal logic * prevails. */ -void -subgroup_announce_all (struct update_subgroup *subgrp) +void subgroup_announce_all(struct update_subgroup *subgrp) { - if (!subgrp) - return; - - /* - * If coalesce timer value is not set, announce routes immediately. - */ - if (!subgrp->v_coalesce) - { - if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0)) - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " announcing all routes", - subgrp->update_group->id, subgrp->id); - subgroup_announce_route (subgrp); - return; - } - - /* - * We should wait for the coalesce timer. Arm the timer if not done. - */ - if (!subgrp->t_coalesce) - { - thread_add_timer_msec(bm->master, subgroup_coalesce_timer, subgrp, - subgrp->v_coalesce, &subgrp->t_coalesce); - } + if (!subgrp) + return; + + /* + * If coalesce timer value is not set, announce routes immediately. + */ + if (!subgrp->v_coalesce) { + if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0)) + zlog_debug("u%" PRIu64 ":s%" PRIu64 + " announcing all routes", + subgrp->update_group->id, subgrp->id); + subgroup_announce_route(subgrp); + return; + } + + /* + * We should wait for the coalesce timer. Arm the timer if not done. + */ + if (!subgrp->t_coalesce) { + thread_add_timer_msec(bm->master, subgroup_coalesce_timer, + subgrp, subgrp->v_coalesce, + &subgrp->t_coalesce); + } } /* * Go through all update subgroups and set up the adv queue for the * input route. */ -void -group_announce_route (struct bgp *bgp, afi_t afi, safi_t safi, - struct bgp_node *rn, struct bgp_info *ri) +void group_announce_route(struct bgp *bgp, afi_t afi, safi_t safi, + struct bgp_node *rn, struct bgp_info *ri) { - struct updwalk_context ctx; - ctx.ri = ri; - ctx.rn = rn; - update_group_af_walk (bgp, afi, safi, group_announce_route_walkcb, &ctx); + struct updwalk_context ctx; + ctx.ri = ri; + ctx.rn = rn; + update_group_af_walk(bgp, afi, safi, group_announce_route_walkcb, &ctx); } -void -update_group_show_adj_queue (struct bgp *bgp, afi_t afi, safi_t safi, - struct vty *vty, uint64_t id) +void update_group_show_adj_queue(struct bgp *bgp, afi_t afi, safi_t safi, + struct vty *vty, uint64_t id) { - updgrp_show_adj (bgp, afi, safi, vty, id, UPDWALK_FLAGS_ADVQUEUE); + updgrp_show_adj(bgp, afi, safi, vty, id, UPDWALK_FLAGS_ADVQUEUE); } -void -update_group_show_advertised (struct bgp *bgp, afi_t afi, safi_t safi, - struct vty *vty, uint64_t id) +void update_group_show_advertised(struct bgp *bgp, afi_t afi, safi_t safi, + struct vty *vty, uint64_t id) { - updgrp_show_adj (bgp, afi, safi, vty, id, UPDWALK_FLAGS_ADVERTISED); + updgrp_show_adj(bgp, afi, safi, vty, id, UPDWALK_FLAGS_ADVERTISED); } -void -update_group_announce (struct bgp *bgp) +void update_group_announce(struct bgp *bgp) { - update_group_walk (bgp, update_group_announce_walkcb, NULL); + update_group_walk(bgp, update_group_announce_walkcb, NULL); } -void -update_group_announce_rrclients (struct bgp *bgp) +void update_group_announce_rrclients(struct bgp *bgp) { - update_group_walk (bgp, update_group_announce_rrc_walkcb, NULL); + update_group_walk(bgp, update_group_announce_rrc_walkcb, NULL); } diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c index 0ef4d4c0c..d7a4a3698 100644 --- a/bgpd/bgp_updgrp_packet.c +++ b/bgpd/bgp_updgrp_packet.c @@ -63,37 +63,34 @@ /******************** * PUBLIC FUNCTIONS ********************/ -struct bpacket * -bpacket_alloc () +struct bpacket *bpacket_alloc() { - struct bpacket *pkt; + struct bpacket *pkt; - pkt = - (struct bpacket *) XCALLOC (MTYPE_BGP_PACKET, sizeof (struct bpacket)); + pkt = (struct bpacket *)XCALLOC(MTYPE_BGP_PACKET, + sizeof(struct bpacket)); - return pkt; + return pkt; } -void -bpacket_free (struct bpacket *pkt) +void bpacket_free(struct bpacket *pkt) { - if (pkt->buffer) - stream_free (pkt->buffer); - pkt->buffer = NULL; - XFREE (MTYPE_BGP_PACKET, pkt); + if (pkt->buffer) + stream_free(pkt->buffer); + pkt->buffer = NULL; + XFREE(MTYPE_BGP_PACKET, pkt); } -void -bpacket_queue_init (struct bpacket_queue *q) +void bpacket_queue_init(struct bpacket_queue *q) { - TAILQ_INIT (&(q->pkts)); + TAILQ_INIT(&(q->pkts)); } /* * bpacket_queue_sanity_check */ -void -bpacket_queue_sanity_check (struct bpacket_queue __attribute__ ((__unused__)) *q) +void bpacket_queue_sanity_check(struct bpacket_queue __attribute__((__unused__)) + * q) { #if 0 struct bpacket *pkt; @@ -130,21 +127,20 @@ bpacket_queue_sanity_check (struct bpacket_queue __attribute__ ((__unused__)) *q * * Users of bpacket_queue should use bpacket_queue_add instead. */ -static void -bpacket_queue_add_packet (struct bpacket_queue *q, struct bpacket *pkt) +static void bpacket_queue_add_packet(struct bpacket_queue *q, + struct bpacket *pkt) { - struct bpacket *last_pkt; + struct bpacket *last_pkt; - if (TAILQ_EMPTY (&(q->pkts))) - TAILQ_INSERT_TAIL (&(q->pkts), pkt, pkt_train); - else - { - last_pkt = bpacket_queue_last (q); - TAILQ_INSERT_AFTER (&(q->pkts), last_pkt, pkt, pkt_train); - } - q->curr_count++; - if (q->hwm_count < q->curr_count) - q->hwm_count = q->curr_count; + if (TAILQ_EMPTY(&(q->pkts))) + TAILQ_INSERT_TAIL(&(q->pkts), pkt, pkt_train); + else { + last_pkt = bpacket_queue_last(q); + TAILQ_INSERT_AFTER(&(q->pkts), last_pkt, pkt, pkt_train); + } + q->curr_count++; + if (q->hwm_count < q->curr_count) + q->hwm_count = q->curr_count; } /* @@ -154,117 +150,107 @@ bpacket_queue_add_packet (struct bpacket_queue *q, struct bpacket *pkt) * not free or use the stream after * invoking this function. */ -struct bpacket * -bpacket_queue_add (struct bpacket_queue *q, struct stream *s, - struct bpacket_attr_vec_arr *vecarrp) +struct bpacket *bpacket_queue_add(struct bpacket_queue *q, struct stream *s, + struct bpacket_attr_vec_arr *vecarrp) { - struct bpacket *pkt; - struct bpacket *last_pkt; - - - pkt = bpacket_alloc (); - if (TAILQ_EMPTY (&(q->pkts))) - { - pkt->ver = 1; - pkt->buffer = s; - if (vecarrp) - memcpy (&pkt->arr, vecarrp, sizeof (struct bpacket_attr_vec_arr)); - else - bpacket_attr_vec_arr_reset (&pkt->arr); - bpacket_queue_add_packet (q, pkt); - bpacket_queue_sanity_check (q); - return pkt; - } + struct bpacket *pkt; + struct bpacket *last_pkt; + + + pkt = bpacket_alloc(); + if (TAILQ_EMPTY(&(q->pkts))) { + pkt->ver = 1; + pkt->buffer = s; + if (vecarrp) + memcpy(&pkt->arr, vecarrp, + sizeof(struct bpacket_attr_vec_arr)); + else + bpacket_attr_vec_arr_reset(&pkt->arr); + bpacket_queue_add_packet(q, pkt); + bpacket_queue_sanity_check(q); + return pkt; + } - /* - * Fill in the new information into the current sentinel and create a - * new sentinel. - */ - bpacket_queue_sanity_check (q); - last_pkt = bpacket_queue_last (q); - assert (last_pkt->buffer == NULL); - last_pkt->buffer = s; - if (vecarrp) - memcpy (&last_pkt->arr, vecarrp, sizeof (struct bpacket_attr_vec_arr)); - else - bpacket_attr_vec_arr_reset (&last_pkt->arr); - - pkt->ver = last_pkt->ver; - pkt->ver++; - bpacket_queue_add_packet (q, pkt); - - bpacket_queue_sanity_check (q); - return last_pkt; + /* + * Fill in the new information into the current sentinel and create a + * new sentinel. + */ + bpacket_queue_sanity_check(q); + last_pkt = bpacket_queue_last(q); + assert(last_pkt->buffer == NULL); + last_pkt->buffer = s; + if (vecarrp) + memcpy(&last_pkt->arr, vecarrp, + sizeof(struct bpacket_attr_vec_arr)); + else + bpacket_attr_vec_arr_reset(&last_pkt->arr); + + pkt->ver = last_pkt->ver; + pkt->ver++; + bpacket_queue_add_packet(q, pkt); + + bpacket_queue_sanity_check(q); + return last_pkt; } -struct bpacket * -bpacket_queue_first (struct bpacket_queue *q) +struct bpacket *bpacket_queue_first(struct bpacket_queue *q) { - return (TAILQ_FIRST (&(q->pkts))); + return (TAILQ_FIRST(&(q->pkts))); } -struct bpacket * -bpacket_queue_last (struct bpacket_queue *q) +struct bpacket *bpacket_queue_last(struct bpacket_queue *q) { - return TAILQ_LAST (&(q->pkts), pkt_queue); + return TAILQ_LAST(&(q->pkts), pkt_queue); } -struct bpacket * -bpacket_queue_remove (struct bpacket_queue *q) +struct bpacket *bpacket_queue_remove(struct bpacket_queue *q) { - struct bpacket *first; + struct bpacket *first; - first = bpacket_queue_first (q); - if (first) - { - TAILQ_REMOVE (&(q->pkts), first, pkt_train); - q->curr_count--; - } - return first; + first = bpacket_queue_first(q); + if (first) { + TAILQ_REMOVE(&(q->pkts), first, pkt_train); + q->curr_count--; + } + return first; } -unsigned int -bpacket_queue_length (struct bpacket_queue *q) +unsigned int bpacket_queue_length(struct bpacket_queue *q) { - return q->curr_count - 1; + return q->curr_count - 1; } -unsigned int -bpacket_queue_hwm_length (struct bpacket_queue *q) +unsigned int bpacket_queue_hwm_length(struct bpacket_queue *q) { - return q->hwm_count - 1; + return q->hwm_count - 1; } -int -bpacket_queue_is_full (struct bgp *bgp, struct bpacket_queue *q) +int bpacket_queue_is_full(struct bgp *bgp, struct bpacket_queue *q) { - if (q->curr_count >= bgp->default_subgroup_pkt_queue_max) - return 1; - return 0; + if (q->curr_count >= bgp->default_subgroup_pkt_queue_max) + return 1; + return 0; } -void -bpacket_add_peer (struct bpacket *pkt, struct peer_af *paf) +void bpacket_add_peer(struct bpacket *pkt, struct peer_af *paf) { - if (!pkt || !paf) - return; + if (!pkt || !paf) + return; - LIST_INSERT_HEAD (&(pkt->peers), paf, pkt_train); - paf->next_pkt_to_send = pkt; + LIST_INSERT_HEAD(&(pkt->peers), paf, pkt_train); + paf->next_pkt_to_send = pkt; } /* * bpacket_queue_cleanup */ -void -bpacket_queue_cleanup (struct bpacket_queue *q) +void bpacket_queue_cleanup(struct bpacket_queue *q) { - struct bpacket *pkt; + struct bpacket *pkt; - while ((pkt = bpacket_queue_remove (q))) - { - bpacket_free (pkt); - } + while ((pkt = bpacket_queue_remove(q))) { + bpacket_free(pkt); + } } /* @@ -275,63 +261,60 @@ bpacket_queue_cleanup (struct bpacket_queue *q) * * @return the number of packets deleted. */ -static int -bpacket_queue_compact (struct bpacket_queue *q) +static int bpacket_queue_compact(struct bpacket_queue *q) { - int num_deleted; - struct bpacket *pkt, *removed_pkt; + int num_deleted; + struct bpacket *pkt, *removed_pkt; - num_deleted = 0; + num_deleted = 0; - while (1) - { - pkt = bpacket_queue_first (q); - if (!pkt) - break; + while (1) { + pkt = bpacket_queue_first(q); + if (!pkt) + break; - /* - * Don't delete the sentinel. - */ - if (!pkt->buffer) - break; + /* + * Don't delete the sentinel. + */ + if (!pkt->buffer) + break; - if (!LIST_EMPTY (&(pkt->peers))) - break; + if (!LIST_EMPTY(&(pkt->peers))) + break; - removed_pkt = bpacket_queue_remove (q); - assert (pkt == removed_pkt); - bpacket_free (removed_pkt); + removed_pkt = bpacket_queue_remove(q); + assert(pkt == removed_pkt); + bpacket_free(removed_pkt); - num_deleted++; - } + num_deleted++; + } - bpacket_queue_sanity_check (q); - return num_deleted; + bpacket_queue_sanity_check(q); + return num_deleted; } -void -bpacket_queue_advance_peer (struct peer_af *paf) +void bpacket_queue_advance_peer(struct peer_af *paf) { - struct bpacket *pkt; - struct bpacket *old_pkt; - - old_pkt = paf->next_pkt_to_send; - if (old_pkt->buffer == NULL) - /* Already at end of list */ - return; - - LIST_REMOVE (paf, pkt_train); - pkt = TAILQ_NEXT (old_pkt, pkt_train); - bpacket_add_peer (pkt, paf); - - if (!bpacket_queue_compact (PAF_PKTQ (paf))) - return; - - /* - * Deleted one or more packets. Check if we can now merge this - * peer's subgroup into another subgroup. - */ - update_subgroup_check_merge (paf->subgroup, "advanced peer in queue"); + struct bpacket *pkt; + struct bpacket *old_pkt; + + old_pkt = paf->next_pkt_to_send; + if (old_pkt->buffer == NULL) + /* Already at end of list */ + return; + + LIST_REMOVE(paf, pkt_train); + pkt = TAILQ_NEXT(old_pkt, pkt_train); + bpacket_add_peer(pkt, paf); + + if (!bpacket_queue_compact(PAF_PKTQ(paf))) + return; + + /* + * Deleted one or more packets. Check if we can now merge this + * peer's subgroup into another subgroup. + */ + update_subgroup_check_merge(paf->subgroup, "advanced peer in queue"); } /* @@ -340,561 +323,587 @@ bpacket_queue_advance_peer (struct peer_af *paf) * Remove the peer from the packet queue of the subgroup it belongs * to. */ -void -bpacket_queue_remove_peer (struct peer_af *paf) +void bpacket_queue_remove_peer(struct peer_af *paf) { - struct bpacket_queue *q; + struct bpacket_queue *q; - q = PAF_PKTQ (paf); - assert (q); - if (!q) - return; + q = PAF_PKTQ(paf); + assert(q); + if (!q) + return; - LIST_REMOVE (paf, pkt_train); - paf->next_pkt_to_send = NULL; + LIST_REMOVE(paf, pkt_train); + paf->next_pkt_to_send = NULL; - bpacket_queue_compact (q); + bpacket_queue_compact(q); } -unsigned int -bpacket_queue_virtual_length (struct peer_af *paf) +unsigned int bpacket_queue_virtual_length(struct peer_af *paf) { - struct bpacket *pkt; - struct bpacket *last; - struct bpacket_queue *q; + struct bpacket *pkt; + struct bpacket *last; + struct bpacket_queue *q; - pkt = paf->next_pkt_to_send; - if (!pkt || (pkt->buffer == NULL)) - /* Already at end of list */ - return 0; + pkt = paf->next_pkt_to_send; + if (!pkt || (pkt->buffer == NULL)) + /* Already at end of list */ + return 0; - q = PAF_PKTQ (paf); - if (TAILQ_EMPTY (&(q->pkts))) - return 0; + q = PAF_PKTQ(paf); + if (TAILQ_EMPTY(&(q->pkts))) + return 0; - last = TAILQ_LAST (&(q->pkts), pkt_queue); - if (last->ver >= pkt->ver) - return last->ver - pkt->ver; + last = TAILQ_LAST(&(q->pkts), pkt_queue); + if (last->ver >= pkt->ver) + return last->ver - pkt->ver; - /* sequence # rolled over */ - return (UINT_MAX - pkt->ver + 1) + last->ver; + /* sequence # rolled over */ + return (UINT_MAX - pkt->ver + 1) + last->ver; } /* * Dump the bpacket queue */ -void -bpacket_queue_show_vty (struct bpacket_queue *q, struct vty *vty) +void bpacket_queue_show_vty(struct bpacket_queue *q, struct vty *vty) { - struct bpacket *pkt; - struct peer_af *paf; - - pkt = bpacket_queue_first (q); - while (pkt) - { - vty_out (vty, " Packet %p ver %u buffer %p\n", pkt, pkt->ver, - pkt->buffer); - - LIST_FOREACH (paf, &(pkt->peers), pkt_train) - { - vty_out (vty, " - %s\n", paf->peer->host); - } - pkt = bpacket_next (pkt); - } - return; + struct bpacket *pkt; + struct peer_af *paf; + + pkt = bpacket_queue_first(q); + while (pkt) { + vty_out(vty, " Packet %p ver %u buffer %p\n", pkt, pkt->ver, + pkt->buffer); + + LIST_FOREACH(paf, &(pkt->peers), pkt_train) + { + vty_out(vty, " - %s\n", paf->peer->host); + } + pkt = bpacket_next(pkt); + } + return; } -struct stream * -bpacket_reformat_for_peer (struct bpacket *pkt, struct peer_af *paf) +struct stream *bpacket_reformat_for_peer(struct bpacket *pkt, + struct peer_af *paf) { - struct stream *s = NULL; - bpacket_attr_vec *vec; - struct peer *peer; - char buf[BUFSIZ]; - char buf2[BUFSIZ]; - - s = stream_dup (pkt->buffer); - peer = PAF_PEER(paf); - - vec = &pkt->arr.entries[BGP_ATTR_VEC_NH]; - if (CHECK_FLAG (vec->flags, BPKT_ATTRVEC_FLAGS_UPDATED)) - { - u_int8_t nhlen; - afi_t nhafi = AFI_MAX; /* NH AFI is based on nhlen! */ - int route_map_sets_nh; - nhlen = stream_getc_from (s, vec->offset); - if (peer_cap_enhe(peer, paf->afi, paf->safi)) - nhafi = AFI_IP6; - else - nhafi = BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen); - - if (nhafi == AFI_IP) - { - struct in_addr v4nh, *mod_v4nh; - int nh_modified = 0; - size_t offset_nh = vec->offset + 1; - - route_map_sets_nh = - (CHECK_FLAG (vec->flags, BPKT_ATTRVEC_FLAGS_RMAP_IPV4_NH_CHANGED) || - CHECK_FLAG (vec->flags, BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS)); - - switch (nhlen) - { - case BGP_ATTR_NHLEN_IPV4: - break; - case BGP_ATTR_NHLEN_VPNV4: - offset_nh += 8; - break; - default: - /* TODO: handle IPv6 nexthops */ - zlog_warn ("%s: %s: invalid MP nexthop length (AFI IP): %u", - __func__, peer->host, nhlen); - stream_free (s); - return NULL; - } - - stream_get_from (&v4nh, s, offset_nh, IPV4_MAX_BYTELEN); - mod_v4nh = &v4nh; - - /* - * If route-map has set the nexthop, that is always used; if it is - * specified as peer-address, the peering address is picked up. - * Otherwise, if NH is unavailable from attribute, the peering addr - * is picked up; the "NH unavailable" case also covers next-hop-self - * and some other scenarios -- see subgroup_announce_check(). In - * all other cases, use the nexthop carried in the attribute unless - * it is EBGP non-multiaccess and there is no next-hop-unchanged setting. - * Note: It is assumed route-map cannot set the nexthop to an - * invalid value. - */ - if (route_map_sets_nh) - { - if (CHECK_FLAG(vec->flags, - BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS)) - { - mod_v4nh = &peer->nexthop.v4; - nh_modified = 1; - } - } - else if (!v4nh.s_addr) - { - mod_v4nh = &peer->nexthop.v4; - nh_modified = 1; - } - else if (peer->sort == BGP_PEER_EBGP && - paf->safi != SAFI_EVPN && - (bgp_multiaccess_check_v4 (v4nh, peer) == 0) && - !CHECK_FLAG(vec->flags, - BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED) && - !peer_af_flag_check (peer, nhafi, paf->safi, - PEER_FLAG_NEXTHOP_UNCHANGED)) - { - /* NOTE: not handling case where NH has new AFI */ - mod_v4nh = &peer->nexthop.v4; - nh_modified = 1; - } - - if (nh_modified) /* allow for VPN RD */ - stream_put_in_addr_at (s, offset_nh, mod_v4nh); - - if (bgp_debug_update(peer, NULL, NULL, 0)) - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " %s send UPDATE w/ nexthop %s%s", - PAF_SUBGRP(paf)->update_group->id, PAF_SUBGRP(paf)->id, - peer->host, inet_ntoa (*mod_v4nh), - (nhlen == 12 ? " and RD" : "")); + struct stream *s = NULL; + bpacket_attr_vec *vec; + struct peer *peer; + char buf[BUFSIZ]; + char buf2[BUFSIZ]; + + s = stream_dup(pkt->buffer); + peer = PAF_PEER(paf); + + vec = &pkt->arr.entries[BGP_ATTR_VEC_NH]; + if (CHECK_FLAG(vec->flags, BPKT_ATTRVEC_FLAGS_UPDATED)) { + u_int8_t nhlen; + afi_t nhafi = AFI_MAX; /* NH AFI is based on nhlen! */ + int route_map_sets_nh; + nhlen = stream_getc_from(s, vec->offset); + if (peer_cap_enhe(peer, paf->afi, paf->safi)) + nhafi = AFI_IP6; + else + nhafi = BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen); + + if (nhafi == AFI_IP) { + struct in_addr v4nh, *mod_v4nh; + int nh_modified = 0; + size_t offset_nh = vec->offset + 1; + + route_map_sets_nh = + (CHECK_FLAG( + vec->flags, + BPKT_ATTRVEC_FLAGS_RMAP_IPV4_NH_CHANGED) + || CHECK_FLAG( + vec->flags, + BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS)); + + switch (nhlen) { + case BGP_ATTR_NHLEN_IPV4: + break; + case BGP_ATTR_NHLEN_VPNV4: + offset_nh += 8; + break; + default: + /* TODO: handle IPv6 nexthops */ + zlog_warn( + "%s: %s: invalid MP nexthop length (AFI IP): %u", + __func__, peer->host, nhlen); + stream_free(s); + return NULL; + } + + stream_get_from(&v4nh, s, offset_nh, IPV4_MAX_BYTELEN); + mod_v4nh = &v4nh; + + /* + * If route-map has set the nexthop, that is always + * used; if it is + * specified as peer-address, the peering address is + * picked up. + * Otherwise, if NH is unavailable from attribute, the + * peering addr + * is picked up; the "NH unavailable" case also covers + * next-hop-self + * and some other scenarios -- see + * subgroup_announce_check(). In + * all other cases, use the nexthop carried in the + * attribute unless + * it is EBGP non-multiaccess and there is no + * next-hop-unchanged setting. + * Note: It is assumed route-map cannot set the nexthop + * to an + * invalid value. + */ + if (route_map_sets_nh) { + if (CHECK_FLAG( + vec->flags, + BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS)) { + mod_v4nh = &peer->nexthop.v4; + nh_modified = 1; + } + } else if (!v4nh.s_addr) { + mod_v4nh = &peer->nexthop.v4; + nh_modified = 1; + } else if ( + peer->sort == BGP_PEER_EBGP + && paf->safi != SAFI_EVPN + && (bgp_multiaccess_check_v4(v4nh, peer) == 0) + && !CHECK_FLAG( + vec->flags, + BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED) + && !peer_af_flag_check( + peer, nhafi, paf->safi, + PEER_FLAG_NEXTHOP_UNCHANGED)) { + /* NOTE: not handling case where NH has new AFI + */ + mod_v4nh = &peer->nexthop.v4; + nh_modified = 1; + } + + if (nh_modified) /* allow for VPN RD */ + stream_put_in_addr_at(s, offset_nh, mod_v4nh); + + if (bgp_debug_update(peer, NULL, NULL, 0)) + zlog_debug("u%" PRIu64 ":s%" PRIu64 + " %s send UPDATE w/ nexthop %s%s", + PAF_SUBGRP(paf)->update_group->id, + PAF_SUBGRP(paf)->id, peer->host, + inet_ntoa(*mod_v4nh), + (nhlen == 12 ? " and RD" : "")); + } else if (nhafi == AFI_IP6) { + struct in6_addr v6nhglobal, *mod_v6nhg; + struct in6_addr v6nhlocal, *mod_v6nhl; + int gnh_modified, lnh_modified; + size_t offset_nhglobal = vec->offset + 1; + size_t offset_nhlocal = vec->offset + 1; + + gnh_modified = lnh_modified = 0; + mod_v6nhg = &v6nhglobal; + mod_v6nhl = &v6nhlocal; + + route_map_sets_nh = + (CHECK_FLAG( + vec->flags, + BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED) + || CHECK_FLAG( + vec->flags, + BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS)); + + /* + * The logic here is rather similar to that for IPv4, + * the + * additional work being to handle 1 or 2 nexthops. + * Also, 3rd + * party nexthop is not propagated for EBGP right now. + */ + switch (nhlen) { + case BGP_ATTR_NHLEN_IPV6_GLOBAL: + break; + case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL: + offset_nhlocal += IPV6_MAX_BYTELEN; + break; + case BGP_ATTR_NHLEN_VPNV6_GLOBAL: + offset_nhglobal += 8; + break; + case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL: + offset_nhglobal += 8; + offset_nhlocal += 8 * 2 + IPV6_MAX_BYTELEN; + break; + default: + /* TODO: handle IPv4 nexthops */ + zlog_warn( + "%s: %s: invalid MP nexthop length (AFI IP6): %u", + __func__, peer->host, nhlen); + stream_free(s); + return NULL; + } + + stream_get_from(&v6nhglobal, s, offset_nhglobal, + IPV6_MAX_BYTELEN); + if (route_map_sets_nh) { + if (CHECK_FLAG( + vec->flags, + BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS)) { + mod_v6nhg = &peer->nexthop.v6_global; + gnh_modified = 1; + } + } else if (IN6_IS_ADDR_UNSPECIFIED(&v6nhglobal)) { + mod_v6nhg = &peer->nexthop.v6_global; + gnh_modified = 1; + } else if ( + peer->sort == BGP_PEER_EBGP + && !CHECK_FLAG( + vec->flags, + BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED) + && !peer_af_flag_check( + peer, nhafi, paf->safi, + PEER_FLAG_NEXTHOP_UNCHANGED)) { + /* NOTE: not handling case where NH has new AFI + */ + mod_v6nhg = &peer->nexthop.v6_global; + gnh_modified = 1; + } + + + if (nhlen == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL + || nhlen == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) { + stream_get_from(&v6nhlocal, s, offset_nhlocal, + IPV6_MAX_BYTELEN); + if (IN6_IS_ADDR_UNSPECIFIED(&v6nhlocal)) { + mod_v6nhl = &peer->nexthop.v6_local; + lnh_modified = 1; + } + } + + if (gnh_modified) + stream_put_in6_addr_at(s, offset_nhglobal, + mod_v6nhg); + if (lnh_modified) + stream_put_in6_addr_at(s, offset_nhlocal, + mod_v6nhl); + + if (bgp_debug_update(peer, NULL, NULL, 0)) { + if (nhlen == 32 || nhlen == 48) + zlog_debug( + "u%" PRIu64 ":s%" PRIu64 + " %s send UPDATE w/ mp_nexthops %s, %s%s", + PAF_SUBGRP(paf) + ->update_group->id, + PAF_SUBGRP(paf)->id, peer->host, + inet_ntop(AF_INET6, mod_v6nhg, + buf, BUFSIZ), + inet_ntop(AF_INET6, mod_v6nhl, + buf2, BUFSIZ), + (nhlen == 48 ? " and RD" : "")); + else + zlog_debug( + "u%" PRIu64 ":s%" PRIu64 + " %s send UPDATE w/ mp_nexthop %s%s", + PAF_SUBGRP(paf) + ->update_group->id, + PAF_SUBGRP(paf)->id, peer->host, + inet_ntop(AF_INET6, mod_v6nhg, + buf, BUFSIZ), + (nhlen == 24 ? " and RD" : "")); + } + } else if (paf->afi == AFI_L2VPN) { + struct in_addr v4nh, *mod_v4nh; + int nh_modified = 0; + + stream_get_from(&v4nh, s, vec->offset + 1, 4); + mod_v4nh = &v4nh; + + /* No route-map changes allowed for EVPN nexthops. */ + if (!v4nh.s_addr) { + mod_v4nh = &peer->nexthop.v4; + nh_modified = 1; + } + + if (nh_modified) + stream_put_in_addr_at(s, vec->offset + 1, + mod_v4nh); + + if (bgp_debug_update(peer, NULL, NULL, 0)) + zlog_debug("u%" PRIu64 ":s%" PRIu64 + " %s send UPDATE w/ nexthop %s", + PAF_SUBGRP(paf)->update_group->id, + PAF_SUBGRP(paf)->id, peer->host, + inet_ntoa(*mod_v4nh)); + } } - else if (nhafi == AFI_IP6) - { - struct in6_addr v6nhglobal, *mod_v6nhg; - struct in6_addr v6nhlocal, *mod_v6nhl; - int gnh_modified, lnh_modified; - size_t offset_nhglobal = vec->offset + 1; - size_t offset_nhlocal = vec->offset + 1; - - gnh_modified = lnh_modified = 0; - mod_v6nhg = &v6nhglobal; - mod_v6nhl = &v6nhlocal; - - route_map_sets_nh = - (CHECK_FLAG (vec->flags, BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED) || - CHECK_FLAG (vec->flags, BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS)); - - /* - * The logic here is rather similar to that for IPv4, the - * additional work being to handle 1 or 2 nexthops. Also, 3rd - * party nexthop is not propagated for EBGP right now. - */ - switch (nhlen) - { - case BGP_ATTR_NHLEN_IPV6_GLOBAL: - break; - case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL: - offset_nhlocal += IPV6_MAX_BYTELEN; - break; - case BGP_ATTR_NHLEN_VPNV6_GLOBAL: - offset_nhglobal += 8; - break; - case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL: - offset_nhglobal += 8; - offset_nhlocal += 8 * 2 + IPV6_MAX_BYTELEN; - break; - default: - /* TODO: handle IPv4 nexthops */ - zlog_warn ("%s: %s: invalid MP nexthop length (AFI IP6): %u", - __func__, peer->host, nhlen); - stream_free (s); - return NULL; - } - - stream_get_from (&v6nhglobal, s, offset_nhglobal, IPV6_MAX_BYTELEN); - if (route_map_sets_nh) - { - if (CHECK_FLAG(vec->flags, - BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS)) - { - mod_v6nhg = &peer->nexthop.v6_global; - gnh_modified = 1; - } - } - else if (IN6_IS_ADDR_UNSPECIFIED (&v6nhglobal)) - { - mod_v6nhg = &peer->nexthop.v6_global; - gnh_modified = 1; - } - else if (peer->sort == BGP_PEER_EBGP && - !CHECK_FLAG(vec->flags, - BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED) && - !peer_af_flag_check (peer, nhafi, paf->safi, - PEER_FLAG_NEXTHOP_UNCHANGED)) - { - /* NOTE: not handling case where NH has new AFI */ - mod_v6nhg = &peer->nexthop.v6_global; - gnh_modified = 1; - } - - - if (nhlen == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL || - nhlen == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) - { - stream_get_from (&v6nhlocal, s, offset_nhlocal, IPV6_MAX_BYTELEN); - if (IN6_IS_ADDR_UNSPECIFIED (&v6nhlocal)) - { - mod_v6nhl = &peer->nexthop.v6_local; - lnh_modified = 1; - } - } - - if (gnh_modified) - stream_put_in6_addr_at (s, offset_nhglobal, mod_v6nhg); - if (lnh_modified) - stream_put_in6_addr_at (s, offset_nhlocal, mod_v6nhl); - - if (bgp_debug_update(peer, NULL, NULL, 0)) - { - if (nhlen == 32 || nhlen == 48) - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " %s send UPDATE w/ mp_nexthops %s, %s%s", - PAF_SUBGRP(paf)->update_group->id, - PAF_SUBGRP(paf)->id, - peer->host, - inet_ntop (AF_INET6, mod_v6nhg, buf, BUFSIZ), - inet_ntop (AF_INET6, mod_v6nhl, buf2, BUFSIZ), - (nhlen == 48 ? " and RD" : "")); - else - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " %s send UPDATE w/ mp_nexthop %s%s", - PAF_SUBGRP(paf)->update_group->id, - PAF_SUBGRP(paf)->id, - peer->host, - inet_ntop (AF_INET6, mod_v6nhg, buf, BUFSIZ), - (nhlen == 24 ? " and RD" : "")); - } - } - else if (paf->afi == AFI_L2VPN) - { - struct in_addr v4nh, *mod_v4nh; - int nh_modified = 0; - - stream_get_from (&v4nh, s, vec->offset + 1, 4); - mod_v4nh = &v4nh; - - /* No route-map changes allowed for EVPN nexthops. */ - if (!v4nh.s_addr) - { - mod_v4nh = &peer->nexthop.v4; - nh_modified = 1; - } - - if (nh_modified) - stream_put_in_addr_at (s, vec->offset + 1, mod_v4nh); - - if (bgp_debug_update(peer, NULL, NULL, 0)) - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " %s send UPDATE w/ nexthop %s", - PAF_SUBGRP(paf)->update_group->id, PAF_SUBGRP(paf)->id, - peer->host, inet_ntoa (*mod_v4nh)); - - } - } - bgp_packet_add (peer, s); - return s; + bgp_packet_add(peer, s); + return s; } /* * Update the vecarr offsets to go beyond 'pos' bytes, i.e. add 'pos' * to each offset. */ -static void -bpacket_attr_vec_arr_update (struct bpacket_attr_vec_arr *vecarr, size_t pos) +static void bpacket_attr_vec_arr_update(struct bpacket_attr_vec_arr *vecarr, + size_t pos) { - int i; + int i; - if (!vecarr) - return; + if (!vecarr) + return; - for (i = 0; i < BGP_ATTR_VEC_MAX; i++) - vecarr->entries[i].offset += pos; + for (i = 0; i < BGP_ATTR_VEC_MAX; i++) + vecarr->entries[i].offset += pos; } /* * Return if there are packets to build for this subgroup. */ -int -subgroup_packets_to_build (struct update_subgroup *subgrp) +int subgroup_packets_to_build(struct update_subgroup *subgrp) { - struct bgp_advertise *adv; + struct bgp_advertise *adv; - if (!subgrp) - return 0; + if (!subgrp) + return 0; - adv = BGP_ADV_FIFO_HEAD (&subgrp->sync->withdraw); - if (adv) - return 1; + adv = BGP_ADV_FIFO_HEAD(&subgrp->sync->withdraw); + if (adv) + return 1; - adv = BGP_ADV_FIFO_HEAD (&subgrp->sync->update); - if (adv) - return 1; + adv = BGP_ADV_FIFO_HEAD(&subgrp->sync->update); + if (adv) + return 1; - return 0; + return 0; } /* Make BGP update packet. */ -struct bpacket * -subgroup_update_packet (struct update_subgroup *subgrp) +struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp) { - struct bpacket_attr_vec_arr vecarr; - struct bpacket *pkt; - struct peer *peer; - struct stream *s; - struct stream *snlri; - struct stream *packet; - struct bgp_adj_out *adj; - struct bgp_advertise *adv; - struct bgp_node *rn = NULL; - struct bgp_info *binfo = NULL; - bgp_size_t total_attr_len = 0; - unsigned long attrlen_pos = 0; - size_t mpattrlen_pos = 0; - size_t mpattr_pos = 0; - afi_t afi; - safi_t safi; - int space_remaining = 0; - int space_needed = 0; - char send_attr_str[BUFSIZ]; - int send_attr_printed = 0; - int num_pfx = 0; - int addpath_encode = 0; - u_int32_t addpath_tx_id = 0; - struct prefix_rd *prd = NULL; - mpls_label_t label = MPLS_INVALID_LABEL; - - if (!subgrp) - return NULL; - - if (bpacket_queue_is_full (SUBGRP_INST (subgrp), SUBGRP_PKTQ (subgrp))) - return NULL; - - peer = SUBGRP_PEER (subgrp); - afi = SUBGRP_AFI (subgrp); - safi = SUBGRP_SAFI (subgrp); - s = subgrp->work; - stream_reset (s); - snlri = subgrp->scratch; - stream_reset (snlri); - - bpacket_attr_vec_arr_reset (&vecarr); - - addpath_encode = bgp_addpath_encode_tx (peer, afi, safi); - - adv = BGP_ADV_FIFO_HEAD (&subgrp->sync->update); - while (adv) - { - assert (adv->rn); - rn = adv->rn; - adj = adv->adj; - addpath_tx_id = adj->addpath_tx_id; - binfo = adv->binfo; - - space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) - - BGP_MAX_PACKET_SIZE_OVERFLOW; - space_needed = BGP_NLRI_LENGTH + - bgp_packet_mpattr_prefix_size (afi, safi, &rn->p); - - /* When remaining space can't include NLRI and it's length. */ - if (space_remaining < space_needed) - break; - - /* If packet is empty, set attribute. */ - if (stream_empty (s)) - { - struct peer *from = NULL; - - if (binfo) - from = binfo->peer; - - /* 1: Write the BGP message header - 16 bytes marker, 2 bytes length, - * one byte message type. - */ - bgp_packet_set_marker (s, BGP_MSG_UPDATE); - - /* 2: withdrawn routes length */ - stream_putw (s, 0); - - /* 3: total attributes length - attrlen_pos stores the position */ - attrlen_pos = stream_get_endp (s); - stream_putw (s, 0); - - /* 4: if there is MP_REACH_NLRI attribute, that should be the first - * attribute, according to draft-ietf-idr-error-handling. Save the - * position. - */ - mpattr_pos = stream_get_endp (s); - - /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */ - total_attr_len = bgp_packet_attribute (NULL, peer, s, - adv->baa->attr, &vecarr, - NULL, afi, safi, - from, NULL, NULL, 0, 0); - - space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) - - BGP_MAX_PACKET_SIZE_OVERFLOW; - space_needed = BGP_NLRI_LENGTH + - bgp_packet_mpattr_prefix_size (afi, safi, &rn->p); - - /* If the attributes alone do not leave any room for NLRI then - * return */ - if (space_remaining < space_needed) - { - zlog_err ("u%" PRIu64 ":s%" PRIu64 " attributes too long, cannot send UPDATE", - subgrp->update_group->id, subgrp->id); - - /* Flush the FIFO update queue */ - while (adv) - adv = bgp_advertise_clean_subgroup (subgrp, adj); - return NULL; - } - - if (BGP_DEBUG (update, UPDATE_OUT) || - BGP_DEBUG (update, UPDATE_PREFIX)) - { - memset (send_attr_str, 0, BUFSIZ); - send_attr_printed = 0; - bgp_dump_attr (adv->baa->attr, send_attr_str, BUFSIZ); - } - } - - if ((afi == AFI_IP && safi == SAFI_UNICAST) && - !peer_cap_enhe(peer, afi, safi)) - stream_put_prefix_addpath (s, &rn->p, addpath_encode, addpath_tx_id); - else - { - /* Encode the prefix in MP_REACH_NLRI attribute */ - if (rn->prn) - prd = (struct prefix_rd *) &rn->prn->p; - - if (safi == SAFI_LABELED_UNICAST) - label = bgp_adv_label(rn, binfo, peer, afi, safi); - else - if (binfo && binfo->extra) - label = binfo->extra->label; - - if (stream_empty (snlri)) - mpattrlen_pos = bgp_packet_mpattr_start (snlri, peer, afi, safi, - &vecarr, adv->baa->attr); - - bgp_packet_mpattr_prefix (snlri, afi, safi, &rn->p, prd, - &label, addpath_encode, addpath_tx_id, adv->baa->attr); - } - - num_pfx++; - - if (bgp_debug_update(NULL, &rn->p, subgrp->update_group, 0)) - { - char pfx_buf[BGP_PRD_PATH_STRLEN]; - - if (!send_attr_printed) - { - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE w/ attr: %s", - subgrp->update_group->id, subgrp->id, send_attr_str); - if (!stream_empty (snlri)) - { - iana_afi_t pkt_afi; - safi_t pkt_safi; - - pkt_afi = afi_int2iana (afi); - pkt_safi = safi_int2iana (safi); - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send MP_REACH for afi/safi %d/%d", - subgrp->update_group->id, subgrp->id, pkt_afi, pkt_safi); - } - - send_attr_printed = 1; - } - - bgp_debug_rdpfxpath2str (afi, safi, prd, &rn->p, &label, - addpath_encode, addpath_tx_id, - pfx_buf, sizeof (pfx_buf)); - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s", - subgrp->update_group->id, subgrp->id, pfx_buf); - } - - /* Synchnorize attribute. */ - if (adj->attr) - bgp_attr_unintern (&adj->attr); - else - subgrp->scount++; - - adj->attr = bgp_attr_intern (adv->baa->attr); + struct bpacket_attr_vec_arr vecarr; + struct bpacket *pkt; + struct peer *peer; + struct stream *s; + struct stream *snlri; + struct stream *packet; + struct bgp_adj_out *adj; + struct bgp_advertise *adv; + struct bgp_node *rn = NULL; + struct bgp_info *binfo = NULL; + bgp_size_t total_attr_len = 0; + unsigned long attrlen_pos = 0; + size_t mpattrlen_pos = 0; + size_t mpattr_pos = 0; + afi_t afi; + safi_t safi; + int space_remaining = 0; + int space_needed = 0; + char send_attr_str[BUFSIZ]; + int send_attr_printed = 0; + int num_pfx = 0; + int addpath_encode = 0; + u_int32_t addpath_tx_id = 0; + struct prefix_rd *prd = NULL; + mpls_label_t label = MPLS_INVALID_LABEL; + + if (!subgrp) + return NULL; - adv = bgp_advertise_clean_subgroup (subgrp, adj); - } + if (bpacket_queue_is_full(SUBGRP_INST(subgrp), SUBGRP_PKTQ(subgrp))) + return NULL; - if (!stream_empty (s)) - { - if (!stream_empty (snlri)) - { - bgp_packet_mpattr_end (snlri, mpattrlen_pos); - total_attr_len += stream_get_endp (snlri); + peer = SUBGRP_PEER(subgrp); + afi = SUBGRP_AFI(subgrp); + safi = SUBGRP_SAFI(subgrp); + s = subgrp->work; + stream_reset(s); + snlri = subgrp->scratch; + stream_reset(snlri); + + bpacket_attr_vec_arr_reset(&vecarr); + + addpath_encode = bgp_addpath_encode_tx(peer, afi, safi); + + adv = BGP_ADV_FIFO_HEAD(&subgrp->sync->update); + while (adv) { + assert(adv->rn); + rn = adv->rn; + adj = adv->adj; + addpath_tx_id = adj->addpath_tx_id; + binfo = adv->binfo; + + space_remaining = STREAM_CONCAT_REMAIN(s, snlri, STREAM_SIZE(s)) + - BGP_MAX_PACKET_SIZE_OVERFLOW; + space_needed = BGP_NLRI_LENGTH + bgp_packet_mpattr_prefix_size( + afi, safi, &rn->p); + + /* When remaining space can't include NLRI and it's length. */ + if (space_remaining < space_needed) + break; + + /* If packet is empty, set attribute. */ + if (stream_empty(s)) { + struct peer *from = NULL; + + if (binfo) + from = binfo->peer; + + /* 1: Write the BGP message header - 16 bytes marker, 2 + * bytes length, + * one byte message type. + */ + bgp_packet_set_marker(s, BGP_MSG_UPDATE); + + /* 2: withdrawn routes length */ + stream_putw(s, 0); + + /* 3: total attributes length - attrlen_pos stores the + * position */ + attrlen_pos = stream_get_endp(s); + stream_putw(s, 0); + + /* 4: if there is MP_REACH_NLRI attribute, that should + * be the first + * attribute, according to + * draft-ietf-idr-error-handling. Save the + * position. + */ + mpattr_pos = stream_get_endp(s); + + /* 5: Encode all the attributes, except MP_REACH_NLRI + * attr. */ + total_attr_len = bgp_packet_attribute( + NULL, peer, s, adv->baa->attr, &vecarr, NULL, + afi, safi, from, NULL, NULL, 0, 0); + + space_remaining = + STREAM_CONCAT_REMAIN(s, snlri, STREAM_SIZE(s)) + - BGP_MAX_PACKET_SIZE_OVERFLOW; + space_needed = + BGP_NLRI_LENGTH + bgp_packet_mpattr_prefix_size( + afi, safi, &rn->p); + + /* If the attributes alone do not leave any room for + * NLRI then + * return */ + if (space_remaining < space_needed) { + zlog_err( + "u%" PRIu64 ":s%" PRIu64 + " attributes too long, cannot send UPDATE", + subgrp->update_group->id, subgrp->id); + + /* Flush the FIFO update queue */ + while (adv) + adv = bgp_advertise_clean_subgroup( + subgrp, adj); + return NULL; + } + + if (BGP_DEBUG(update, UPDATE_OUT) + || BGP_DEBUG(update, UPDATE_PREFIX)) { + memset(send_attr_str, 0, BUFSIZ); + send_attr_printed = 0; + bgp_dump_attr(adv->baa->attr, send_attr_str, + BUFSIZ); + } + } + + if ((afi == AFI_IP && safi == SAFI_UNICAST) + && !peer_cap_enhe(peer, afi, safi)) + stream_put_prefix_addpath(s, &rn->p, addpath_encode, + addpath_tx_id); + else { + /* Encode the prefix in MP_REACH_NLRI attribute */ + if (rn->prn) + prd = (struct prefix_rd *)&rn->prn->p; + + if (safi == SAFI_LABELED_UNICAST) + label = bgp_adv_label(rn, binfo, peer, afi, + safi); + else if (binfo && binfo->extra) + label = binfo->extra->label; + + if (stream_empty(snlri)) + mpattrlen_pos = bgp_packet_mpattr_start( + snlri, peer, afi, safi, &vecarr, + adv->baa->attr); + + bgp_packet_mpattr_prefix(snlri, afi, safi, &rn->p, prd, + &label, addpath_encode, + addpath_tx_id, adv->baa->attr); + } + + num_pfx++; + + if (bgp_debug_update(NULL, &rn->p, subgrp->update_group, 0)) { + char pfx_buf[BGP_PRD_PATH_STRLEN]; + + if (!send_attr_printed) { + zlog_debug("u%" PRIu64 ":s%" PRIu64 + " send UPDATE w/ attr: %s", + subgrp->update_group->id, subgrp->id, + send_attr_str); + if (!stream_empty(snlri)) { + iana_afi_t pkt_afi; + safi_t pkt_safi; + + pkt_afi = afi_int2iana(afi); + pkt_safi = safi_int2iana(safi); + zlog_debug( + "u%" PRIu64 ":s%" PRIu64 + " send MP_REACH for afi/safi %d/%d", + subgrp->update_group->id, + subgrp->id, pkt_afi, pkt_safi); + } + + send_attr_printed = 1; + } + + bgp_debug_rdpfxpath2str(afi, safi, prd, &rn->p, &label, + addpath_encode, addpath_tx_id, + pfx_buf, sizeof(pfx_buf)); + zlog_debug("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s", + subgrp->update_group->id, subgrp->id, + pfx_buf); + } + + /* Synchnorize attribute. */ + if (adj->attr) + bgp_attr_unintern(&adj->attr); + else + subgrp->scount++; + + adj->attr = bgp_attr_intern(adv->baa->attr); + + adv = bgp_advertise_clean_subgroup(subgrp, adj); } - /* set the total attribute length correctly */ - stream_putw_at (s, attrlen_pos, total_attr_len); - - if (!stream_empty (snlri)) - { - packet = stream_dupcat (s, snlri, mpattr_pos); - bpacket_attr_vec_arr_update (&vecarr, mpattr_pos); + if (!stream_empty(s)) { + if (!stream_empty(snlri)) { + bgp_packet_mpattr_end(snlri, mpattrlen_pos); + total_attr_len += stream_get_endp(snlri); + } + + /* set the total attribute length correctly */ + stream_putw_at(s, attrlen_pos, total_attr_len); + + if (!stream_empty(snlri)) { + packet = stream_dupcat(s, snlri, mpattr_pos); + bpacket_attr_vec_arr_update(&vecarr, mpattr_pos); + } else + packet = stream_dup(s); + bgp_packet_set_size(packet); + if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0)) + zlog_debug("u%" PRIu64 ":s%" PRIu64 + " send UPDATE len %zd numpfx %d", + subgrp->update_group->id, subgrp->id, + (stream_get_endp(packet) + - stream_get_getp(packet)), + num_pfx); + pkt = bpacket_queue_add(SUBGRP_PKTQ(subgrp), packet, &vecarr); + stream_reset(s); + stream_reset(snlri); + return pkt; } - else - packet = stream_dup (s); - bgp_packet_set_size (packet); - if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0)) - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE len %zd numpfx %d", - subgrp->update_group->id, subgrp->id, - (stream_get_endp(packet) - stream_get_getp(packet)), num_pfx); - pkt = bpacket_queue_add (SUBGRP_PKTQ (subgrp), packet, &vecarr); - stream_reset (s); - stream_reset (snlri); - return pkt; - } - return NULL; + return NULL; } /* Make BGP withdraw packet. */ @@ -907,400 +916,396 @@ subgroup_update_packet (struct update_subgroup *subgrp) 2-octet withdrawn route length (=0) | 2-octet attrlen | mp_unreach attr type | attr len | afi | safi | withdrawn prefixes */ -struct bpacket * -subgroup_withdraw_packet (struct update_subgroup *subgrp) +struct bpacket *subgroup_withdraw_packet(struct update_subgroup *subgrp) { - struct bpacket *pkt; - struct stream *s; - struct bgp_adj_out *adj; - struct bgp_advertise *adv; - struct peer *peer; - struct bgp_node *rn; - bgp_size_t unfeasible_len; - bgp_size_t total_attr_len; - size_t mp_start = 0; - size_t attrlen_pos = 0; - size_t mplen_pos = 0; - u_char first_time = 1; - afi_t afi; - safi_t safi; - int space_remaining = 0; - int space_needed = 0; - int num_pfx = 0; - int addpath_encode = 0; - u_int32_t addpath_tx_id = 0; - struct prefix_rd *prd = NULL; - - - if (!subgrp) - return NULL; - - if (bpacket_queue_is_full (SUBGRP_INST (subgrp), SUBGRP_PKTQ (subgrp))) - return NULL; - - peer = SUBGRP_PEER (subgrp); - afi = SUBGRP_AFI (subgrp); - safi = SUBGRP_SAFI (subgrp); - s = subgrp->work; - stream_reset (s); - addpath_encode = bgp_addpath_encode_tx (peer, afi, safi); - - while ((adv = BGP_ADV_FIFO_HEAD (&subgrp->sync->withdraw)) != NULL) - { - assert (adv->rn); - adj = adv->adj; - rn = adv->rn; - addpath_tx_id = adj->addpath_tx_id; - - space_remaining = STREAM_REMAIN (s) - - BGP_MAX_PACKET_SIZE_OVERFLOW; - space_needed = BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN + - bgp_packet_mpattr_prefix_size (afi, safi, &rn->p); - - if (space_remaining < space_needed) - break; - - if (stream_empty (s)) - { - bgp_packet_set_marker (s, BGP_MSG_UPDATE); - stream_putw (s, 0); /* unfeasible routes length */ - } - else - first_time = 0; - - if (afi == AFI_IP && safi == SAFI_UNICAST && - !peer_cap_enhe(peer, afi, safi)) - stream_put_prefix_addpath (s, &rn->p, addpath_encode, addpath_tx_id); - else - { - if (rn->prn) - prd = (struct prefix_rd *) &rn->prn->p; - - /* If first time, format the MP_UNREACH header */ - if (first_time) - { - iana_afi_t pkt_afi; - safi_t pkt_safi; - - pkt_afi = afi_int2iana (afi); - pkt_safi = safi_int2iana (safi); - - attrlen_pos = stream_get_endp (s); - /* total attr length = 0 for now. reevaluate later */ - stream_putw (s, 0); - mp_start = stream_get_endp (s); - mplen_pos = bgp_packet_mpunreach_start (s, afi, safi); - if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0)) - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send MP_UNREACH for afi/safi %d/%d", - subgrp->update_group->id, subgrp->id, pkt_afi, pkt_safi); - } - - bgp_packet_mpunreach_prefix (s, &rn->p, afi, safi, prd, NULL, - addpath_encode, addpath_tx_id, NULL); - } - - num_pfx++; + struct bpacket *pkt; + struct stream *s; + struct bgp_adj_out *adj; + struct bgp_advertise *adv; + struct peer *peer; + struct bgp_node *rn; + bgp_size_t unfeasible_len; + bgp_size_t total_attr_len; + size_t mp_start = 0; + size_t attrlen_pos = 0; + size_t mplen_pos = 0; + u_char first_time = 1; + afi_t afi; + safi_t safi; + int space_remaining = 0; + int space_needed = 0; + int num_pfx = 0; + int addpath_encode = 0; + u_int32_t addpath_tx_id = 0; + struct prefix_rd *prd = NULL; + + + if (!subgrp) + return NULL; - if (bgp_debug_update(NULL, &rn->p, subgrp->update_group, 0)) - { - char pfx_buf[BGP_PRD_PATH_STRLEN]; + if (bpacket_queue_is_full(SUBGRP_INST(subgrp), SUBGRP_PKTQ(subgrp))) + return NULL; - bgp_debug_rdpfxpath2str (afi, safi, prd, &rn->p, NULL, - addpath_encode, addpath_tx_id, - pfx_buf, sizeof (pfx_buf)); - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s -- unreachable", - subgrp->update_group->id, subgrp->id, pfx_buf); + peer = SUBGRP_PEER(subgrp); + afi = SUBGRP_AFI(subgrp); + safi = SUBGRP_SAFI(subgrp); + s = subgrp->work; + stream_reset(s); + addpath_encode = bgp_addpath_encode_tx(peer, afi, safi); + + while ((adv = BGP_ADV_FIFO_HEAD(&subgrp->sync->withdraw)) != NULL) { + assert(adv->rn); + adj = adv->adj; + rn = adv->rn; + addpath_tx_id = adj->addpath_tx_id; + + space_remaining = + STREAM_REMAIN(s) - BGP_MAX_PACKET_SIZE_OVERFLOW; + space_needed = + BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN + + bgp_packet_mpattr_prefix_size(afi, safi, &rn->p); + + if (space_remaining < space_needed) + break; + + if (stream_empty(s)) { + bgp_packet_set_marker(s, BGP_MSG_UPDATE); + stream_putw(s, 0); /* unfeasible routes length */ + } else + first_time = 0; + + if (afi == AFI_IP && safi == SAFI_UNICAST + && !peer_cap_enhe(peer, afi, safi)) + stream_put_prefix_addpath(s, &rn->p, addpath_encode, + addpath_tx_id); + else { + if (rn->prn) + prd = (struct prefix_rd *)&rn->prn->p; + + /* If first time, format the MP_UNREACH header */ + if (first_time) { + iana_afi_t pkt_afi; + safi_t pkt_safi; + + pkt_afi = afi_int2iana(afi); + pkt_safi = safi_int2iana(safi); + + attrlen_pos = stream_get_endp(s); + /* total attr length = 0 for now. reevaluate + * later */ + stream_putw(s, 0); + mp_start = stream_get_endp(s); + mplen_pos = bgp_packet_mpunreach_start(s, afi, + safi); + if (bgp_debug_update(NULL, NULL, + subgrp->update_group, 0)) + zlog_debug( + "u%" PRIu64 ":s%" PRIu64 + " send MP_UNREACH for afi/safi %d/%d", + subgrp->update_group->id, + subgrp->id, pkt_afi, pkt_safi); + } + + bgp_packet_mpunreach_prefix(s, &rn->p, afi, safi, prd, + NULL, addpath_encode, + addpath_tx_id, NULL); + } + + num_pfx++; + + if (bgp_debug_update(NULL, &rn->p, subgrp->update_group, 0)) { + char pfx_buf[BGP_PRD_PATH_STRLEN]; + + bgp_debug_rdpfxpath2str(afi, safi, prd, &rn->p, NULL, + addpath_encode, addpath_tx_id, + pfx_buf, sizeof(pfx_buf)); + zlog_debug("u%" PRIu64 ":s%" PRIu64 + " send UPDATE %s -- unreachable", + subgrp->update_group->id, subgrp->id, + pfx_buf); + } + + subgrp->scount--; + + bgp_adj_out_remove_subgroup(rn, adj, subgrp); + bgp_unlock_node(rn); } - subgrp->scount--; - - bgp_adj_out_remove_subgroup (rn, adj, subgrp); - bgp_unlock_node (rn); - } - - if (!stream_empty (s)) - { - if (afi == AFI_IP && safi == SAFI_UNICAST && - !peer_cap_enhe(peer, afi, safi)) - { - unfeasible_len - = stream_get_endp (s) - BGP_HEADER_SIZE - BGP_UNFEASIBLE_LEN; - stream_putw_at (s, BGP_HEADER_SIZE, unfeasible_len); - stream_putw (s, 0); - } - else - { - /* Set the mp_unreach attr's length */ - bgp_packet_mpunreach_end (s, mplen_pos); - - /* Set total path attribute length. */ - total_attr_len = stream_get_endp (s) - mp_start; - stream_putw_at (s, attrlen_pos, total_attr_len); + if (!stream_empty(s)) { + if (afi == AFI_IP && safi == SAFI_UNICAST + && !peer_cap_enhe(peer, afi, safi)) { + unfeasible_len = stream_get_endp(s) - BGP_HEADER_SIZE + - BGP_UNFEASIBLE_LEN; + stream_putw_at(s, BGP_HEADER_SIZE, unfeasible_len); + stream_putw(s, 0); + } else { + /* Set the mp_unreach attr's length */ + bgp_packet_mpunreach_end(s, mplen_pos); + + /* Set total path attribute length. */ + total_attr_len = stream_get_endp(s) - mp_start; + stream_putw_at(s, attrlen_pos, total_attr_len); + } + bgp_packet_set_size(s); + if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0)) + zlog_debug("u%" PRIu64 ":s%" PRIu64 + " send UPDATE (withdraw) len %zd numpfx %d", + subgrp->update_group->id, subgrp->id, + (stream_get_endp(s) - stream_get_getp(s)), + num_pfx); + pkt = bpacket_queue_add(SUBGRP_PKTQ(subgrp), stream_dup(s), + NULL); + stream_reset(s); + return pkt; } - bgp_packet_set_size (s); - if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0)) - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE (withdraw) len %zd numpfx %d", - subgrp->update_group->id, subgrp->id, - (stream_get_endp(s) - stream_get_getp(s)), num_pfx); - pkt = bpacket_queue_add (SUBGRP_PKTQ (subgrp), stream_dup (s), NULL); - stream_reset (s); - return pkt; - } - return NULL; + return NULL; } -void -subgroup_default_update_packet (struct update_subgroup *subgrp, - struct attr *attr, struct peer *from) +void subgroup_default_update_packet(struct update_subgroup *subgrp, + struct attr *attr, struct peer *from) { - struct stream *s; - struct peer *peer; - struct prefix p; - unsigned long pos; - bgp_size_t total_attr_len; - afi_t afi; - safi_t safi; - struct bpacket_attr_vec_arr vecarr; - int addpath_encode = 0; - - if (DISABLE_BGP_ANNOUNCE) - return; - - if (!subgrp) - return; - - peer = SUBGRP_PEER (subgrp); - afi = SUBGRP_AFI (subgrp); - safi = SUBGRP_SAFI (subgrp); - bpacket_attr_vec_arr_reset (&vecarr); - addpath_encode = bgp_addpath_encode_tx (peer, afi, safi); - - if (afi == AFI_IP) - str2prefix ("0.0.0.0/0", &p); - else - str2prefix ("::/0", &p); - - /* Logging the attribute. */ - if (bgp_debug_update(NULL, &p, subgrp->update_group, 0)) - { - char attrstr[BUFSIZ]; - char buf[PREFIX_STRLEN]; - /* ' with addpath ID ' 17 - * max strlen of uint32 + 10 - * +/- (just in case) + 1 - * null terminator + 1 - * ============================ 29 */ - char tx_id_buf[30]; - - attrstr[0] = '\0'; - - bgp_dump_attr (attr, attrstr, BUFSIZ); - - if (addpath_encode) - snprintf(tx_id_buf, sizeof (tx_id_buf), " with addpath ID %u", - BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); - - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s%s %s", - (SUBGRP_UPDGRP (subgrp))->id, subgrp->id, - prefix2str (&p, buf, sizeof (buf)), - tx_id_buf, attrstr); - } + struct stream *s; + struct peer *peer; + struct prefix p; + unsigned long pos; + bgp_size_t total_attr_len; + afi_t afi; + safi_t safi; + struct bpacket_attr_vec_arr vecarr; + int addpath_encode = 0; + + if (DISABLE_BGP_ANNOUNCE) + return; + + if (!subgrp) + return; + + peer = SUBGRP_PEER(subgrp); + afi = SUBGRP_AFI(subgrp); + safi = SUBGRP_SAFI(subgrp); + bpacket_attr_vec_arr_reset(&vecarr); + addpath_encode = bgp_addpath_encode_tx(peer, afi, safi); + + if (afi == AFI_IP) + str2prefix("0.0.0.0/0", &p); + else + str2prefix("::/0", &p); + + /* Logging the attribute. */ + if (bgp_debug_update(NULL, &p, subgrp->update_group, 0)) { + char attrstr[BUFSIZ]; + char buf[PREFIX_STRLEN]; + /* ' with addpath ID ' 17 + * max strlen of uint32 + 10 + * +/- (just in case) + 1 + * null terminator + 1 + * ============================ 29 */ + char tx_id_buf[30]; + + attrstr[0] = '\0'; + + bgp_dump_attr(attr, attrstr, BUFSIZ); + + if (addpath_encode) + snprintf(tx_id_buf, sizeof(tx_id_buf), + " with addpath ID %u", + BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); + + zlog_debug("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s%s %s", + (SUBGRP_UPDGRP(subgrp))->id, subgrp->id, + prefix2str(&p, buf, sizeof(buf)), tx_id_buf, + attrstr); + } - s = stream_new (BGP_MAX_PACKET_SIZE); + s = stream_new(BGP_MAX_PACKET_SIZE); - /* Make BGP update packet. */ - bgp_packet_set_marker (s, BGP_MSG_UPDATE); + /* Make BGP update packet. */ + bgp_packet_set_marker(s, BGP_MSG_UPDATE); - /* Unfeasible Routes Length. */ - stream_putw (s, 0); + /* Unfeasible Routes Length. */ + stream_putw(s, 0); - /* Make place for total attribute length. */ - pos = stream_get_endp (s); - stream_putw (s, 0); - total_attr_len = bgp_packet_attribute (NULL, peer, s, attr, &vecarr, &p, - afi, safi, from, NULL, NULL, - addpath_encode, - BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); + /* Make place for total attribute length. */ + pos = stream_get_endp(s); + stream_putw(s, 0); + total_attr_len = bgp_packet_attribute( + NULL, peer, s, attr, &vecarr, &p, afi, safi, from, NULL, NULL, + addpath_encode, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); - /* Set Total Path Attribute Length. */ - stream_putw_at (s, pos, total_attr_len); + /* Set Total Path Attribute Length. */ + stream_putw_at(s, pos, total_attr_len); - /* NLRI set. */ - if (p.family == AF_INET && safi == SAFI_UNICAST && - !peer_cap_enhe(peer, afi, safi)) - stream_put_prefix_addpath (s, &p, addpath_encode, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); + /* NLRI set. */ + if (p.family == AF_INET && safi == SAFI_UNICAST + && !peer_cap_enhe(peer, afi, safi)) + stream_put_prefix_addpath( + s, &p, addpath_encode, + BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); - /* Set size. */ - bgp_packet_set_size (s); + /* Set size. */ + bgp_packet_set_size(s); - (void) bpacket_queue_add (SUBGRP_PKTQ (subgrp), s, &vecarr); - subgroup_trigger_write(subgrp); + (void)bpacket_queue_add(SUBGRP_PKTQ(subgrp), s, &vecarr); + subgroup_trigger_write(subgrp); } -void -subgroup_default_withdraw_packet (struct update_subgroup *subgrp) +void subgroup_default_withdraw_packet(struct update_subgroup *subgrp) { - struct peer *peer; - struct stream *s; - struct prefix p; - unsigned long attrlen_pos = 0; - unsigned long cp; - bgp_size_t unfeasible_len; - bgp_size_t total_attr_len = 0; - size_t mp_start = 0; - size_t mplen_pos = 0; - afi_t afi; - safi_t safi; - int addpath_encode = 0; - - if (DISABLE_BGP_ANNOUNCE) - return; - - peer = SUBGRP_PEER (subgrp); - afi = SUBGRP_AFI (subgrp); - safi = SUBGRP_SAFI (subgrp); - addpath_encode = bgp_addpath_encode_tx (peer, afi, safi); - - if (afi == AFI_IP) - str2prefix ("0.0.0.0/0", &p); - else - str2prefix ("::/0", &p); - - if (bgp_debug_update(NULL, &p, subgrp->update_group, 0)) - { - char buf[PREFIX_STRLEN]; - /* ' with addpath ID ' 17 - * max strlen of uint32 + 10 - * +/- (just in case) + 1 - * null terminator + 1 - * ============================ 29 */ - char tx_id_buf[30]; - - if (addpath_encode) - snprintf(tx_id_buf, sizeof (tx_id_buf), " with addpath ID %u", - BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); - - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s%s -- unreachable", - (SUBGRP_UPDGRP (subgrp))->id, subgrp->id, - prefix2str (&p, buf, sizeof (buf)), tx_id_buf); - } + struct peer *peer; + struct stream *s; + struct prefix p; + unsigned long attrlen_pos = 0; + unsigned long cp; + bgp_size_t unfeasible_len; + bgp_size_t total_attr_len = 0; + size_t mp_start = 0; + size_t mplen_pos = 0; + afi_t afi; + safi_t safi; + int addpath_encode = 0; + + if (DISABLE_BGP_ANNOUNCE) + return; + + peer = SUBGRP_PEER(subgrp); + afi = SUBGRP_AFI(subgrp); + safi = SUBGRP_SAFI(subgrp); + addpath_encode = bgp_addpath_encode_tx(peer, afi, safi); + + if (afi == AFI_IP) + str2prefix("0.0.0.0/0", &p); + else + str2prefix("::/0", &p); + + if (bgp_debug_update(NULL, &p, subgrp->update_group, 0)) { + char buf[PREFIX_STRLEN]; + /* ' with addpath ID ' 17 + * max strlen of uint32 + 10 + * +/- (just in case) + 1 + * null terminator + 1 + * ============================ 29 */ + char tx_id_buf[30]; + + if (addpath_encode) + snprintf(tx_id_buf, sizeof(tx_id_buf), + " with addpath ID %u", + BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); + + zlog_debug("u%" PRIu64 ":s%" PRIu64 + " send UPDATE %s%s -- unreachable", + (SUBGRP_UPDGRP(subgrp))->id, subgrp->id, + prefix2str(&p, buf, sizeof(buf)), tx_id_buf); + } - s = stream_new (BGP_MAX_PACKET_SIZE); + s = stream_new(BGP_MAX_PACKET_SIZE); - /* Make BGP update packet. */ - bgp_packet_set_marker (s, BGP_MSG_UPDATE); + /* Make BGP update packet. */ + bgp_packet_set_marker(s, BGP_MSG_UPDATE); - /* Unfeasible Routes Length. */ ; - cp = stream_get_endp (s); - stream_putw (s, 0); + /* Unfeasible Routes Length. */; + cp = stream_get_endp(s); + stream_putw(s, 0); - /* Withdrawn Routes. */ - if (p.family == AF_INET && safi == SAFI_UNICAST && - !peer_cap_enhe(peer, afi, safi)) - { - stream_put_prefix_addpath (s, &p, addpath_encode, - BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); + /* Withdrawn Routes. */ + if (p.family == AF_INET && safi == SAFI_UNICAST + && !peer_cap_enhe(peer, afi, safi)) { + stream_put_prefix_addpath( + s, &p, addpath_encode, + BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); - unfeasible_len = stream_get_endp (s) - cp - 2; + unfeasible_len = stream_get_endp(s) - cp - 2; - /* Set unfeasible len. */ - stream_putw_at (s, cp, unfeasible_len); + /* Set unfeasible len. */ + stream_putw_at(s, cp, unfeasible_len); - /* Set total path attribute length. */ - stream_putw (s, 0); - } - else - { - attrlen_pos = stream_get_endp (s); - stream_putw (s, 0); - mp_start = stream_get_endp (s); - mplen_pos = bgp_packet_mpunreach_start (s, afi, safi); - bgp_packet_mpunreach_prefix (s, &p, afi, safi, NULL, NULL, - addpath_encode, - BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE, NULL); - - /* Set the mp_unreach attr's length */ - bgp_packet_mpunreach_end (s, mplen_pos); - - /* Set total path attribute length. */ - total_attr_len = stream_get_endp (s) - mp_start; - stream_putw_at (s, attrlen_pos, total_attr_len); - } + /* Set total path attribute length. */ + stream_putw(s, 0); + } else { + attrlen_pos = stream_get_endp(s); + stream_putw(s, 0); + mp_start = stream_get_endp(s); + mplen_pos = bgp_packet_mpunreach_start(s, afi, safi); + bgp_packet_mpunreach_prefix( + s, &p, afi, safi, NULL, NULL, addpath_encode, + BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE, NULL); - bgp_packet_set_size (s); + /* Set the mp_unreach attr's length */ + bgp_packet_mpunreach_end(s, mplen_pos); - (void) bpacket_queue_add (SUBGRP_PKTQ (subgrp), s, NULL); - subgroup_trigger_write(subgrp); + /* Set total path attribute length. */ + total_attr_len = stream_get_endp(s) - mp_start; + stream_putw_at(s, attrlen_pos, total_attr_len); + } + + bgp_packet_set_size(s); + + (void)bpacket_queue_add(SUBGRP_PKTQ(subgrp), s, NULL); + subgroup_trigger_write(subgrp); } static void -bpacket_vec_arr_inherit_attr_flags (struct bpacket_attr_vec_arr *vecarr, - bpacket_attr_vec_type type, - struct attr *attr) +bpacket_vec_arr_inherit_attr_flags(struct bpacket_attr_vec_arr *vecarr, + bpacket_attr_vec_type type, + struct attr *attr) { - if (CHECK_FLAG (attr->rmap_change_flags, - BATTR_RMAP_NEXTHOP_PEER_ADDRESS)) - SET_FLAG (vecarr->entries[BGP_ATTR_VEC_NH].flags, - BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS); - - if (CHECK_FLAG (attr->rmap_change_flags, BATTR_REFLECTED)) - SET_FLAG (vecarr->entries[BGP_ATTR_VEC_NH].flags, - BPKT_ATTRVEC_FLAGS_REFLECTED); - - if (CHECK_FLAG (attr->rmap_change_flags, - BATTR_RMAP_NEXTHOP_UNCHANGED)) - SET_FLAG (vecarr->entries[BGP_ATTR_VEC_NH].flags, - BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED); - - if (CHECK_FLAG (attr->rmap_change_flags, - BATTR_RMAP_IPV4_NHOP_CHANGED)) - SET_FLAG (vecarr->entries[BGP_ATTR_VEC_NH].flags, - BPKT_ATTRVEC_FLAGS_RMAP_IPV4_NH_CHANGED); - - if (CHECK_FLAG (attr->rmap_change_flags, - BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED)) - SET_FLAG (vecarr->entries[BGP_ATTR_VEC_NH].flags, - BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED); - - if (CHECK_FLAG (attr->rmap_change_flags, - BATTR_RMAP_IPV6_LL_NHOP_CHANGED)) - SET_FLAG (vecarr->entries[BGP_ATTR_VEC_NH].flags, - BPKT_ATTRVEC_FLAGS_RMAP_IPV6_LNH_CHANGED); + if (CHECK_FLAG(attr->rmap_change_flags, + BATTR_RMAP_NEXTHOP_PEER_ADDRESS)) + SET_FLAG(vecarr->entries[BGP_ATTR_VEC_NH].flags, + BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS); + + if (CHECK_FLAG(attr->rmap_change_flags, BATTR_REFLECTED)) + SET_FLAG(vecarr->entries[BGP_ATTR_VEC_NH].flags, + BPKT_ATTRVEC_FLAGS_REFLECTED); + + if (CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_NEXTHOP_UNCHANGED)) + SET_FLAG(vecarr->entries[BGP_ATTR_VEC_NH].flags, + BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED); + + if (CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_IPV4_NHOP_CHANGED)) + SET_FLAG(vecarr->entries[BGP_ATTR_VEC_NH].flags, + BPKT_ATTRVEC_FLAGS_RMAP_IPV4_NH_CHANGED); + + if (CHECK_FLAG(attr->rmap_change_flags, + BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED)) + SET_FLAG(vecarr->entries[BGP_ATTR_VEC_NH].flags, + BPKT_ATTRVEC_FLAGS_RMAP_IPV6_GNH_CHANGED); + + if (CHECK_FLAG(attr->rmap_change_flags, + BATTR_RMAP_IPV6_LL_NHOP_CHANGED)) + SET_FLAG(vecarr->entries[BGP_ATTR_VEC_NH].flags, + BPKT_ATTRVEC_FLAGS_RMAP_IPV6_LNH_CHANGED); } /* Reset the Attributes vector array. The vector array is used to override * certain output parameters in the packet for a particular peer */ -void -bpacket_attr_vec_arr_reset (struct bpacket_attr_vec_arr *vecarr) +void bpacket_attr_vec_arr_reset(struct bpacket_attr_vec_arr *vecarr) { - int i; + int i; - if (!vecarr) - return; + if (!vecarr) + return; - i = 0; - while (i < BGP_ATTR_VEC_MAX) - { - vecarr->entries[i].flags = 0; - vecarr->entries[i].offset = 0; - i++; - } + i = 0; + while (i < BGP_ATTR_VEC_MAX) { + vecarr->entries[i].flags = 0; + vecarr->entries[i].offset = 0; + i++; + } } /* Setup a particular node entry in the vecarr */ -void -bpacket_attr_vec_arr_set_vec (struct bpacket_attr_vec_arr *vecarr, - bpacket_attr_vec_type type, struct stream *s, - struct attr *attr) +void bpacket_attr_vec_arr_set_vec(struct bpacket_attr_vec_arr *vecarr, + bpacket_attr_vec_type type, struct stream *s, + struct attr *attr) { - if (!vecarr) - return; - assert (type < BGP_ATTR_VEC_MAX); - - SET_FLAG (vecarr->entries[type].flags, BPKT_ATTRVEC_FLAGS_UPDATED); - vecarr->entries[type].offset = stream_get_endp (s); - if (attr) - bpacket_vec_arr_inherit_attr_flags(vecarr, type, attr); + if (!vecarr) + return; + assert(type < BGP_ATTR_VEC_MAX); + + SET_FLAG(vecarr->entries[type].flags, BPKT_ATTRVEC_FLAGS_UPDATED); + vecarr->entries[type].offset = stream_get_endp(s); + if (attr) + bpacket_vec_arr_inherit_attr_flags(vecarr, type, attr); } diff --git a/bgpd/bgp_vnc_types.h b/bgpd/bgp_vnc_types.h index e97a47e1a..70f5646e9 100644 --- a/bgpd/bgp_vnc_types.h +++ b/bgpd/bgp_vnc_types.h @@ -1,4 +1,4 @@ -/* +/* * Copyright 2015-2016, LabN Consulting, L.L.C. * * This program is free software; you can redistribute it and/or @@ -21,20 +21,20 @@ #if ENABLE_BGP_VNC typedef enum { - BGP_VNC_SUBTLV_TYPE_LIFETIME=1, - BGP_VNC_SUBTLV_TYPE_RFPOPTION=2, /* deprecated */ + BGP_VNC_SUBTLV_TYPE_LIFETIME = 1, + BGP_VNC_SUBTLV_TYPE_RFPOPTION = 2, /* deprecated */ } bgp_vnc_subtlv_types; /* * VNC Attribute subtlvs */ struct bgp_vnc_subtlv_lifetime { - uint32_t lifetime; + uint32_t lifetime; }; struct bgp_vnc_subtlv_unaddr { - struct prefix un_address; /* IPv4 or IPv6; pfx length ignored */ + struct prefix un_address; /* IPv4 or IPv6; pfx length ignored */ }; -#endif /* ENABLE_BGP_VNC */ +#endif /* ENABLE_BGP_VNC */ #endif /* _QUAGGA_BGP_VNC_TYPES_H */ diff --git a/bgpd/bgp_vpn.c b/bgpd/bgp_vpn.c index c7f8ae3c0..ca98ff066 100644 --- a/bgpd/bgp_vpn.c +++ b/bgpd/bgp_vpn.c @@ -30,170 +30,221 @@ #include "bgpd/bgp_mplsvpn.h" #include "bgpd/bgp_vpn.h" -int -show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd, - afi_t afi, safi_t safi, u_char use_json) +int show_adj_route_vpn(struct vty *vty, struct peer *peer, + struct prefix_rd *prd, afi_t afi, safi_t safi, + u_char use_json) { - struct bgp *bgp; - struct bgp_table *table; - struct bgp_node *rn; - struct bgp_node *rm; - struct attr *attr; - int rd_header; - int header = 1; - json_object *json = NULL; - json_object *json_scode = NULL; - json_object *json_ocode = NULL; - json_object *json_routes = NULL; - json_object *json_array = NULL; - - bgp = bgp_get_default (); - if (bgp == NULL) - { - if (!use_json) - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING; - } - - if (use_json) - { - json_scode = json_object_new_object(); - json_ocode = json_object_new_object(); - json_routes = json_object_new_object(); - json = json_object_new_object(); - - json_object_string_add(json_scode, "suppressed", "s"); - json_object_string_add(json_scode, "damped", "d"); - json_object_string_add(json_scode, "history", "h"); - json_object_string_add(json_scode, "valid", "*"); - json_object_string_add(json_scode, "best", ">"); - json_object_string_add(json_scode, "internal", "i"); - - json_object_string_add(json_ocode, "igp", "i"); - json_object_string_add(json_ocode, "egp", "e"); - json_object_string_add(json_ocode, "incomplete", "?"); - } - - for (rn = bgp_table_top (bgp->rib[afi][SAFI_MPLS_VPN]); rn; - rn = bgp_route_next (rn)) - { - if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0) - continue; - - if ((table = rn->info) != NULL) - { - if (use_json) - json_array = json_object_new_array(); - else - json_array = NULL; - - rd_header = 1; - - for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm)) - { - if ((attr = rm->info) != NULL) - { - if (header) - { - if (use_json) - { - json_object_int_add(json, "bgpTableVersion", 0); - json_object_string_add(json, "bgpLocalRouterId", inet_ntoa (bgp->router_id)); - json_object_object_add(json, "bgpStatusCodes", json_scode); - json_object_object_add(json, "bgpOriginCodes", json_ocode); - } - else - { - vty_out (vty, "BGP table version is 0, local router ID is %s\n", - inet_ntoa(bgp->router_id)); - vty_out (vty, - "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n"); - vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n"); - vty_out (vty, V4_HEADER); - } - header = 0; - } - - if (rd_header) - { - u_int16_t type; - struct rd_as rd_as; - struct rd_ip rd_ip = {0}; + struct bgp *bgp; + struct bgp_table *table; + struct bgp_node *rn; + struct bgp_node *rm; + struct attr *attr; + int rd_header; + int header = 1; + json_object *json = NULL; + json_object *json_scode = NULL; + json_object *json_ocode = NULL; + json_object *json_routes = NULL; + json_object *json_array = NULL; + + bgp = bgp_get_default(); + if (bgp == NULL) { + if (!use_json) + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING; + } + + if (use_json) { + json_scode = json_object_new_object(); + json_ocode = json_object_new_object(); + json_routes = json_object_new_object(); + json = json_object_new_object(); + + json_object_string_add(json_scode, "suppressed", "s"); + json_object_string_add(json_scode, "damped", "d"); + json_object_string_add(json_scode, "history", "h"); + json_object_string_add(json_scode, "valid", "*"); + json_object_string_add(json_scode, "best", ">"); + json_object_string_add(json_scode, "internal", "i"); + + json_object_string_add(json_ocode, "igp", "i"); + json_object_string_add(json_ocode, "egp", "e"); + json_object_string_add(json_ocode, "incomplete", "?"); + } + + for (rn = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); rn; + rn = bgp_route_next(rn)) { + if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0) + continue; + + if ((table = rn->info) != NULL) { + if (use_json) + json_array = json_object_new_array(); + else + json_array = NULL; + + rd_header = 1; + + for (rm = bgp_table_top(table); rm; + rm = bgp_route_next(rm)) { + if ((attr = rm->info) != NULL) { + if (header) { + if (use_json) { + json_object_int_add( + json, + "bgpTableVersion", + 0); + json_object_string_add( + json, + "bgpLocalRouterId", + inet_ntoa( + bgp->router_id)); + json_object_object_add( + json, + "bgpStatusCodes", + json_scode); + json_object_object_add( + json, + "bgpOriginCodes", + json_ocode); + } else { + vty_out(vty, + "BGP table version is 0, local router ID is %s\n", + inet_ntoa( + bgp->router_id)); + vty_out(vty, + "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n"); + vty_out(vty, + "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n"); + vty_out(vty, V4_HEADER); + } + header = 0; + } + + if (rd_header) { + u_int16_t type; + struct rd_as rd_as; + struct rd_ip rd_ip = {0}; #if ENABLE_BGP_VNC - struct rd_vnc_eth rd_vnc_eth = {0}; + struct rd_vnc_eth rd_vnc_eth = { + 0}; #endif - u_char *pnt; - - pnt = rn->p.u.val; - - /* Decode RD type. */ - type = decode_rd_type (pnt); - /* Decode RD value. */ - if (type == RD_TYPE_AS) - decode_rd_as (pnt + 2, &rd_as); - else if (type == RD_TYPE_AS4) - decode_rd_as4 (pnt + 2, &rd_as); - else if (type == RD_TYPE_IP) - decode_rd_ip (pnt + 2, &rd_ip); + u_char *pnt; + + pnt = rn->p.u.val; + + /* Decode RD type. */ + type = decode_rd_type(pnt); + /* Decode RD value. */ + if (type == RD_TYPE_AS) + decode_rd_as(pnt + 2, + &rd_as); + else if (type == RD_TYPE_AS4) + decode_rd_as4(pnt + 2, + &rd_as); + else if (type == RD_TYPE_IP) + decode_rd_ip(pnt + 2, + &rd_ip); #if ENABLE_BGP_VNC - else if (type == RD_TYPE_VNC_ETH) - decode_rd_vnc_eth (pnt, &rd_vnc_eth); + else if (type + == RD_TYPE_VNC_ETH) + decode_rd_vnc_eth( + pnt, + &rd_vnc_eth); #endif - if (use_json) - { - char buffer[BUFSIZ]; - if (type == RD_TYPE_AS || type == RD_TYPE_AS4) - sprintf (buffer, "%u:%d", rd_as.as, rd_as.val); - else if (type == RD_TYPE_IP) - sprintf (buffer, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val); - json_object_string_add(json_routes, "routeDistinguisher", buffer); - } - else - { - vty_out (vty, "Route Distinguisher: "); - - if (type == RD_TYPE_AS || type == RD_TYPE_AS4) - vty_out (vty, "%u:%d", rd_as.as, rd_as.val); - else if (type == RD_TYPE_IP) - vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val); + if (use_json) { + char buffer[BUFSIZ]; + if (type == RD_TYPE_AS + || type == RD_TYPE_AS4) + sprintf(buffer, + "%u:%d", + rd_as.as, + rd_as.val); + else if (type + == RD_TYPE_IP) + sprintf(buffer, + "%s:%d", + inet_ntoa( + rd_ip.ip), + rd_ip.val); + json_object_string_add( + json_routes, + "routeDistinguisher", + buffer); + } else { + vty_out(vty, + "Route Distinguisher: "); + + if (type == RD_TYPE_AS + || type == RD_TYPE_AS4) + vty_out(vty, + "%u:%d", + rd_as.as, + rd_as.val); + else if (type + == RD_TYPE_IP) + vty_out(vty, + "%s:%d", + inet_ntoa( + rd_ip.ip), + rd_ip.val); #if ENABLE_BGP_VNC - else if (type == RD_TYPE_VNC_ETH) - vty_out (vty, "%u:%02x:%02x:%02x:%02x:%02x:%02x", - rd_vnc_eth.local_nve_id, - rd_vnc_eth.macaddr.octet[0], - rd_vnc_eth.macaddr.octet[1], - rd_vnc_eth.macaddr.octet[2], - rd_vnc_eth.macaddr.octet[3], - rd_vnc_eth.macaddr.octet[4], - rd_vnc_eth.macaddr.octet[5]); + else if ( + type + == RD_TYPE_VNC_ETH) + vty_out(vty, + "%u:%02x:%02x:%02x:%02x:%02x:%02x", + rd_vnc_eth + .local_nve_id, + rd_vnc_eth + .macaddr + .octet[0], + rd_vnc_eth + .macaddr + .octet[1], + rd_vnc_eth + .macaddr + .octet[2], + rd_vnc_eth + .macaddr + .octet[3], + rd_vnc_eth + .macaddr + .octet[4], + rd_vnc_eth + .macaddr + .octet[5]); #endif - vty_out (vty, "\n"); - } - rd_header = 0; - } - route_vty_out_tmp (vty, &rm->p, attr, SAFI_MPLS_VPN, use_json, json_array); - } - } - if (use_json) - { - struct prefix *p; - char buf_a[BUFSIZ]; - char buf_b[BUFSIZ]; - p = &rm->p; - sprintf(buf_a, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf_b, BUFSIZ), p->prefixlen); - json_object_object_add(json_routes, buf_a, json_array); - } - } - } - if (use_json) - { - json_object_object_add(json, "routes", json_routes); - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - return CMD_SUCCESS; + vty_out(vty, "\n"); + } + rd_header = 0; + } + route_vty_out_tmp(vty, &rm->p, attr, + SAFI_MPLS_VPN, + use_json, json_array); + } + } + if (use_json) { + struct prefix *p; + char buf_a[BUFSIZ]; + char buf_b[BUFSIZ]; + p = &rm->p; + sprintf(buf_a, "%s/%d", + inet_ntop(p->family, &p->u.prefix, + buf_b, BUFSIZ), + p->prefixlen); + json_object_object_add(json_routes, buf_a, + json_array); + } + } + } + if (use_json) { + json_object_object_add(json, "routes", json_routes); + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } + return CMD_SUCCESS; } - diff --git a/bgpd/bgp_vpn.h b/bgpd/bgp_vpn.h index fcccd45c7..d2a2cb4a5 100644 --- a/bgpd/bgp_vpn.h +++ b/bgpd/bgp_vpn.h @@ -23,8 +23,8 @@ #include -extern int -show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd, - afi_t afi, safi_t safi, u_char use_json); +extern int show_adj_route_vpn(struct vty *vty, struct peer *peer, + struct prefix_rd *prd, afi_t afi, safi_t safi, + u_char use_json); #endif /* _QUAGGA_BGP_VPN_H */ diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 9d0f6b44d..8ae015173 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -58,112 +58,104 @@ #include "bgpd/bgp_updgrp.h" #include "bgpd/bgp_bfd.h" -static struct peer_group * -listen_range_exists (struct bgp *bgp, struct prefix *range, int exact); - -static enum node_type -bgp_node_type (afi_t afi, safi_t safi) -{ - switch (afi) - { - case AFI_IP: - switch (safi) - { - case SAFI_UNICAST: - return BGP_IPV4_NODE; - break; - case SAFI_MULTICAST: - return BGP_IPV4M_NODE; - break; - case SAFI_LABELED_UNICAST: - return BGP_IPV4L_NODE; - break; - case SAFI_MPLS_VPN: - return BGP_VPNV4_NODE; - break; - } - break; - case AFI_IP6: - switch (safi) - { - case SAFI_UNICAST: - return BGP_IPV6_NODE; - break; - case SAFI_MULTICAST: - return BGP_IPV6M_NODE; - break; - case SAFI_LABELED_UNICAST: - return BGP_IPV6L_NODE; - break; - case SAFI_MPLS_VPN: - return BGP_VPNV6_NODE; - break; - } - break; - case AFI_L2VPN: - return BGP_EVPN_NODE; - break; - case AFI_MAX: - // We should never be here but to clarify the switch statement.. - return BGP_IPV4_NODE; - break; - } - - // Impossible to happen - return BGP_IPV4_NODE; +static struct peer_group *listen_range_exists(struct bgp *bgp, + struct prefix *range, int exact); + +static enum node_type bgp_node_type(afi_t afi, safi_t safi) +{ + switch (afi) { + case AFI_IP: + switch (safi) { + case SAFI_UNICAST: + return BGP_IPV4_NODE; + break; + case SAFI_MULTICAST: + return BGP_IPV4M_NODE; + break; + case SAFI_LABELED_UNICAST: + return BGP_IPV4L_NODE; + break; + case SAFI_MPLS_VPN: + return BGP_VPNV4_NODE; + break; + } + break; + case AFI_IP6: + switch (safi) { + case SAFI_UNICAST: + return BGP_IPV6_NODE; + break; + case SAFI_MULTICAST: + return BGP_IPV6M_NODE; + break; + case SAFI_LABELED_UNICAST: + return BGP_IPV6L_NODE; + break; + case SAFI_MPLS_VPN: + return BGP_VPNV6_NODE; + break; + } + break; + case AFI_L2VPN: + return BGP_EVPN_NODE; + break; + case AFI_MAX: + // We should never be here but to clarify the switch statement.. + return BGP_IPV4_NODE; + break; + } + + // Impossible to happen + return BGP_IPV4_NODE; } /* Utility function to get address family from current node. */ -afi_t -bgp_node_afi (struct vty *vty) -{ - afi_t afi; - switch (vty->node) - { - case BGP_IPV6_NODE: - case BGP_IPV6M_NODE: - case BGP_IPV6L_NODE: - case BGP_VPNV6_NODE: - afi = AFI_IP6; - break; - case BGP_EVPN_NODE: - afi = AFI_L2VPN; - break; - default: - afi = AFI_IP; - break; - } - return afi; +afi_t bgp_node_afi(struct vty *vty) +{ + afi_t afi; + switch (vty->node) { + case BGP_IPV6_NODE: + case BGP_IPV6M_NODE: + case BGP_IPV6L_NODE: + case BGP_VPNV6_NODE: + afi = AFI_IP6; + break; + case BGP_EVPN_NODE: + afi = AFI_L2VPN; + break; + default: + afi = AFI_IP; + break; + } + return afi; } /* Utility function to get subsequent address family from current node. */ -safi_t -bgp_node_safi (struct vty *vty) -{ - safi_t safi; - switch (vty->node) - { - case BGP_VPNV4_NODE: - case BGP_VPNV6_NODE: - safi = SAFI_MPLS_VPN; - break; - case BGP_IPV4M_NODE: - case BGP_IPV6M_NODE: - safi = SAFI_MULTICAST; - break; - case BGP_EVPN_NODE: - safi = SAFI_EVPN; - break; - case BGP_IPV4L_NODE: - case BGP_IPV6L_NODE: - safi = SAFI_LABELED_UNICAST; - break; - default: - safi = SAFI_UNICAST; - break; - } - return safi; +safi_t bgp_node_safi(struct vty *vty) +{ + safi_t safi; + switch (vty->node) { + case BGP_VPNV4_NODE: + case BGP_VPNV6_NODE: + safi = SAFI_MPLS_VPN; + break; + case BGP_IPV4M_NODE: + case BGP_IPV6M_NODE: + safi = SAFI_MULTICAST; + break; + case BGP_EVPN_NODE: + safi = SAFI_EVPN; + break; + case BGP_IPV4L_NODE: + case BGP_IPV6L_NODE: + safi = SAFI_LABELED_UNICAST; + break; + default: + safi = SAFI_UNICAST; + break; + } + return safi; } /** @@ -174,81 +166,69 @@ bgp_node_safi (struct vty *vty) * - "ipv6" * @return the corresponding afi_t */ -afi_t -bgp_vty_afi_from_str(const char *afi_str) -{ - afi_t afi = AFI_MAX; /* unknown */ - if (strmatch(afi_str, "ipv4")) - afi = AFI_IP; - else if (strmatch(afi_str, "ipv6")) - afi = AFI_IP6; - return afi; -} - -int -argv_find_and_parse_afi(struct cmd_token **argv, int argc, int *index, afi_t *afi) -{ - int ret = 0; - if (argv_find (argv, argc, "ipv4", index)) - { - ret = 1; - if (afi) - *afi = AFI_IP; - } - else if (argv_find (argv, argc, "ipv6", index)) - { - ret = 1; - if (afi) - *afi = AFI_IP6; - } - return ret; +afi_t bgp_vty_afi_from_str(const char *afi_str) +{ + afi_t afi = AFI_MAX; /* unknown */ + if (strmatch(afi_str, "ipv4")) + afi = AFI_IP; + else if (strmatch(afi_str, "ipv6")) + afi = AFI_IP6; + return afi; +} + +int argv_find_and_parse_afi(struct cmd_token **argv, int argc, int *index, + afi_t *afi) +{ + int ret = 0; + if (argv_find(argv, argc, "ipv4", index)) { + ret = 1; + if (afi) + *afi = AFI_IP; + } else if (argv_find(argv, argc, "ipv6", index)) { + ret = 1; + if (afi) + *afi = AFI_IP6; + } + return ret; } /* supports */ -safi_t -bgp_vty_safi_from_str(const char *safi_str) -{ - safi_t safi = SAFI_MAX; /* unknown */ - if (strmatch (safi_str, "multicast")) - safi = SAFI_MULTICAST; - else if (strmatch (safi_str, "unicast")) - safi = SAFI_UNICAST; - else if (strmatch (safi_str, "vpn")) - safi = SAFI_MPLS_VPN; - else if (strmatch (safi_str, "labeled-unicast")) - safi = SAFI_LABELED_UNICAST; - return safi; -} - -int -argv_find_and_parse_safi (struct cmd_token **argv, int argc, int *index, safi_t *safi) -{ - int ret = 0; - if (argv_find (argv, argc, "unicast", index)) - { - ret = 1; - if (safi) - *safi = SAFI_UNICAST; - } - else if (argv_find (argv, argc, "multicast", index)) - { - ret = 1; - if (safi) - *safi = SAFI_MULTICAST; - } - else if (argv_find (argv, argc, "labeled-unicast", index)) - { - ret = 1; - if (safi) - *safi = SAFI_LABELED_UNICAST; - } - else if (argv_find (argv, argc, "vpn", index)) - { - ret = 1; - if (safi) - *safi = SAFI_MPLS_VPN; - } - return ret; +safi_t bgp_vty_safi_from_str(const char *safi_str) +{ + safi_t safi = SAFI_MAX; /* unknown */ + if (strmatch(safi_str, "multicast")) + safi = SAFI_MULTICAST; + else if (strmatch(safi_str, "unicast")) + safi = SAFI_UNICAST; + else if (strmatch(safi_str, "vpn")) + safi = SAFI_MPLS_VPN; + else if (strmatch(safi_str, "labeled-unicast")) + safi = SAFI_LABELED_UNICAST; + return safi; +} + +int argv_find_and_parse_safi(struct cmd_token **argv, int argc, int *index, + safi_t *safi) +{ + int ret = 0; + if (argv_find(argv, argc, "unicast", index)) { + ret = 1; + if (safi) + *safi = SAFI_UNICAST; + } else if (argv_find(argv, argc, "multicast", index)) { + ret = 1; + if (safi) + *safi = SAFI_MULTICAST; + } else if (argv_find(argv, argc, "labeled-unicast", index)) { + ret = 1; + if (safi) + *safi = SAFI_LABELED_UNICAST; + } else if (argv_find(argv, argc, "vpn", index)) { + ret = 1; + if (safi) + *safi = SAFI_MPLS_VPN; + } + return ret; } /* @@ -261,7 +241,8 @@ argv_find_and_parse_safi (struct cmd_token **argv, int argc, int *index, safi_t * that is being parsed. * * The show commands are generally of the form: - * "show [ip] bgp [ VIEWVRFNAME] [ []] ..." + * "show [ip] bgp [ VIEWVRFNAME] [ + * []] ..." * * Since we use argv_find if the show command in particular doesn't have: * [ip] @@ -273,7 +254,8 @@ argv_find_and_parse_safi (struct cmd_token **argv, int argc, int *index, safi_t * the event of a parse error in the vrf. * argv -> The command tokens * argc -> How many command tokens we have - * idx -> The current place in the command, generally should be 0 for this function + * idx -> The current place in the command, generally should be 0 for this + * function * afi -> The parsed afi if it was included in the show command, returned here * safi -> The parsed safi if it was included in the show command, returned here * bgp -> Pointer to the bgp data structure we need to fill in. @@ -284,480 +266,448 @@ argv_find_and_parse_safi (struct cmd_token **argv, int argc, int *index, safi_t * Returns 0 for failure to parse correctly, else the idx position of where * it found the last token. */ -int -bgp_vty_find_and_parse_afi_safi_bgp (struct vty *vty, struct cmd_token **argv, int argc, int *idx, - afi_t *afi, safi_t *safi, struct bgp **bgp) -{ - char *vrf_name = NULL; - - assert (afi); - assert (safi); - assert (bgp); - - if (argv_find (argv, argc, "ip", idx)) - *afi = AFI_IP; - - if (argv_find (argv, argc, "view", idx) || argv_find (argv, argc, "vrf", idx)) - { - vrf_name = argv[*idx + 1]->arg; - - if (strmatch (vrf_name, "all")) - *bgp = NULL; - else - { - *bgp = bgp_lookup_by_name (vrf_name); - if (!*bgp) - { - vty_out (vty, "View/Vrf specified is unknown: %s\n", vrf_name); - *idx = 0; - return 0; - } - } - } - else - { - *bgp = bgp_get_default (); - if (!*bgp) - { - vty_out (vty, "Unable to find default BGP instance\n"); - *idx = 0; - return 0; - } - } - - if (argv_find_and_parse_afi (argv, argc, idx, afi)) - argv_find_and_parse_safi (argv, argc, idx, safi); - - *idx += 1; - return *idx; -} - -static int -peer_address_self_check (struct bgp *bgp, union sockunion *su) -{ - struct interface *ifp = NULL; - - if (su->sa.sa_family == AF_INET) - ifp = if_lookup_by_ipv4_exact (&su->sin.sin_addr, bgp->vrf_id); - else if (su->sa.sa_family == AF_INET6) - ifp = if_lookup_by_ipv6_exact (&su->sin6.sin6_addr, - su->sin6.sin6_scope_id, bgp->vrf_id); - - if (ifp) - return 1; - - return 0; +int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty, + struct cmd_token **argv, int argc, + int *idx, afi_t *afi, safi_t *safi, + struct bgp **bgp) +{ + char *vrf_name = NULL; + + assert(afi); + assert(safi); + assert(bgp); + + if (argv_find(argv, argc, "ip", idx)) + *afi = AFI_IP; + + if (argv_find(argv, argc, "view", idx) + || argv_find(argv, argc, "vrf", idx)) { + vrf_name = argv[*idx + 1]->arg; + + if (strmatch(vrf_name, "all")) + *bgp = NULL; + else { + *bgp = bgp_lookup_by_name(vrf_name); + if (!*bgp) { + vty_out(vty, + "View/Vrf specified is unknown: %s\n", + vrf_name); + *idx = 0; + return 0; + } + } + } else { + *bgp = bgp_get_default(); + if (!*bgp) { + vty_out(vty, "Unable to find default BGP instance\n"); + *idx = 0; + return 0; + } + } + + if (argv_find_and_parse_afi(argv, argc, idx, afi)) + argv_find_and_parse_safi(argv, argc, idx, safi); + + *idx += 1; + return *idx; +} + +static int peer_address_self_check(struct bgp *bgp, union sockunion *su) +{ + struct interface *ifp = NULL; + + if (su->sa.sa_family == AF_INET) + ifp = if_lookup_by_ipv4_exact(&su->sin.sin_addr, bgp->vrf_id); + else if (su->sa.sa_family == AF_INET6) + ifp = if_lookup_by_ipv6_exact(&su->sin6.sin6_addr, + su->sin6.sin6_scope_id, + bgp->vrf_id); + + if (ifp) + return 1; + + return 0; } /* Utility function for looking up peer from VTY. */ /* This is used only for configuration, so disallow if attempted on * a dynamic neighbor. */ -static struct peer * -peer_lookup_vty (struct vty *vty, const char *ip_str) -{ - struct bgp *bgp = VTY_GET_CONTEXT(bgp); - int ret; - union sockunion su; - struct peer *peer; - - if (!bgp) { - return NULL; - } - - ret = str2sockunion (ip_str, &su); - if (ret < 0) - { - peer = peer_lookup_by_conf_if (bgp, ip_str); - if (!peer) - { - if ((peer = peer_lookup_by_hostname(bgp, ip_str)) == NULL) - { - vty_out (vty, "%% Malformed address or name: %s\n", ip_str); - return NULL; - } - } - } - else - { - peer = peer_lookup (bgp, &su); - if (! peer) - { - vty_out (vty, "%% Specify remote-as or peer-group commands first\n"); - return NULL; - } - if (peer_dynamic_neighbor (peer)) - { - vty_out (vty, "%% Operation not allowed on a dynamic neighbor\n"); - return NULL; - } - - } - return peer; +static struct peer *peer_lookup_vty(struct vty *vty, const char *ip_str) +{ + struct bgp *bgp = VTY_GET_CONTEXT(bgp); + int ret; + union sockunion su; + struct peer *peer; + + if (!bgp) { + return NULL; + } + + ret = str2sockunion(ip_str, &su); + if (ret < 0) { + peer = peer_lookup_by_conf_if(bgp, ip_str); + if (!peer) { + if ((peer = peer_lookup_by_hostname(bgp, ip_str)) + == NULL) { + vty_out(vty, + "%% Malformed address or name: %s\n", + ip_str); + return NULL; + } + } + } else { + peer = peer_lookup(bgp, &su); + if (!peer) { + vty_out(vty, + "%% Specify remote-as or peer-group commands first\n"); + return NULL; + } + if (peer_dynamic_neighbor(peer)) { + vty_out(vty, + "%% Operation not allowed on a dynamic neighbor\n"); + return NULL; + } + } + return peer; } /* Utility function for looking up peer or peer group. */ /* This is used only for configuration, so disallow if attempted on * a dynamic neighbor. */ -struct peer * -peer_and_group_lookup_vty (struct vty *vty, const char *peer_str) -{ - struct bgp *bgp = VTY_GET_CONTEXT(bgp); - int ret; - union sockunion su; - struct peer *peer = NULL; - struct peer_group *group = NULL; - - if (!bgp) { - return NULL; - } - - ret = str2sockunion (peer_str, &su); - if (ret == 0) - { - /* IP address, locate peer. */ - peer = peer_lookup (bgp, &su); - } - else - { - /* Not IP, could match either peer configured on interface or a group. */ - peer = peer_lookup_by_conf_if (bgp, peer_str); - if (!peer) - group = peer_group_lookup (bgp, peer_str); - } - - if (peer) - { - if (peer_dynamic_neighbor (peer)) - { - vty_out (vty, "%% Operation not allowed on a dynamic neighbor\n"); - return NULL; - } - - return peer; - } - - if (group) - return group->conf; - - vty_out (vty, "%% Specify remote-as or peer-group commands first\n"); - - return NULL; -} - -int -bgp_vty_return (struct vty *vty, int ret) -{ - const char *str = NULL; - - switch (ret) - { - case BGP_ERR_INVALID_VALUE: - str = "Invalid value"; - break; - case BGP_ERR_INVALID_FLAG: - str = "Invalid flag"; - break; - case BGP_ERR_PEER_GROUP_SHUTDOWN: - str = "Peer-group has been shutdown. Activate the peer-group first"; - break; - case BGP_ERR_PEER_FLAG_CONFLICT: - str = "Can't set override-capability and strict-capability-match at the same time"; - break; - case BGP_ERR_PEER_GROUP_NO_REMOTE_AS: - str = "Specify remote-as or peer-group remote AS first"; - break; - case BGP_ERR_PEER_GROUP_CANT_CHANGE: - str = "Cannot change the peer-group. Deconfigure first"; - break; - case BGP_ERR_PEER_GROUP_MISMATCH: - str = "Peer is not a member of this peer-group"; - break; - case BGP_ERR_PEER_FILTER_CONFLICT: - str = "Prefix/distribute list can not co-exist"; - break; - case BGP_ERR_NOT_INTERNAL_PEER: - str = "Invalid command. Not an internal neighbor"; - break; - case BGP_ERR_REMOVE_PRIVATE_AS: - str = "remove-private-AS cannot be configured for IBGP peers"; - break; - case BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP: - str = "Local-AS allowed only for EBGP peers"; - break; - case BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS: - str = "Cannot have local-as same as BGP AS number"; - break; - case BGP_ERR_TCPSIG_FAILED: - str = "Error while applying TCP-Sig to session(s)"; - break; - case BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK: - str = "ebgp-multihop and ttl-security cannot be configured together"; - break; - case BGP_ERR_NO_IBGP_WITH_TTLHACK: - str = "ttl-security only allowed for EBGP peers"; - break; - case BGP_ERR_AS_OVERRIDE: - str = "as-override cannot be configured for IBGP peers"; - break; - case BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT: - str = "Invalid limit for number of dynamic neighbors"; - break; - case BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS: - str = "Dynamic neighbor listen range already exists"; - break; - case BGP_ERR_INVALID_FOR_DYNAMIC_PEER: - str = "Operation not allowed on a dynamic neighbor"; - break; - case BGP_ERR_INVALID_FOR_DIRECT_PEER: - str = "Operation not allowed on a directly connected neighbor"; - break; - case BGP_ERR_PEER_SAFI_CONFLICT: - str = "Cannot activate peer for both 'ipv4 unicast' and 'ipv4 labeled-unicast'"; - break; - } - if (str) - { - vty_out (vty, "%% %s\n", str); - return CMD_WARNING_CONFIG_FAILED; - } - return CMD_SUCCESS; +struct peer *peer_and_group_lookup_vty(struct vty *vty, const char *peer_str) +{ + struct bgp *bgp = VTY_GET_CONTEXT(bgp); + int ret; + union sockunion su; + struct peer *peer = NULL; + struct peer_group *group = NULL; + + if (!bgp) { + return NULL; + } + + ret = str2sockunion(peer_str, &su); + if (ret == 0) { + /* IP address, locate peer. */ + peer = peer_lookup(bgp, &su); + } else { + /* Not IP, could match either peer configured on interface or a + * group. */ + peer = peer_lookup_by_conf_if(bgp, peer_str); + if (!peer) + group = peer_group_lookup(bgp, peer_str); + } + + if (peer) { + if (peer_dynamic_neighbor(peer)) { + vty_out(vty, + "%% Operation not allowed on a dynamic neighbor\n"); + return NULL; + } + + return peer; + } + + if (group) + return group->conf; + + vty_out(vty, "%% Specify remote-as or peer-group commands first\n"); + + return NULL; +} + +int bgp_vty_return(struct vty *vty, int ret) +{ + const char *str = NULL; + + switch (ret) { + case BGP_ERR_INVALID_VALUE: + str = "Invalid value"; + break; + case BGP_ERR_INVALID_FLAG: + str = "Invalid flag"; + break; + case BGP_ERR_PEER_GROUP_SHUTDOWN: + str = "Peer-group has been shutdown. Activate the peer-group first"; + break; + case BGP_ERR_PEER_FLAG_CONFLICT: + str = "Can't set override-capability and strict-capability-match at the same time"; + break; + case BGP_ERR_PEER_GROUP_NO_REMOTE_AS: + str = "Specify remote-as or peer-group remote AS first"; + break; + case BGP_ERR_PEER_GROUP_CANT_CHANGE: + str = "Cannot change the peer-group. Deconfigure first"; + break; + case BGP_ERR_PEER_GROUP_MISMATCH: + str = "Peer is not a member of this peer-group"; + break; + case BGP_ERR_PEER_FILTER_CONFLICT: + str = "Prefix/distribute list can not co-exist"; + break; + case BGP_ERR_NOT_INTERNAL_PEER: + str = "Invalid command. Not an internal neighbor"; + break; + case BGP_ERR_REMOVE_PRIVATE_AS: + str = "remove-private-AS cannot be configured for IBGP peers"; + break; + case BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP: + str = "Local-AS allowed only for EBGP peers"; + break; + case BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS: + str = "Cannot have local-as same as BGP AS number"; + break; + case BGP_ERR_TCPSIG_FAILED: + str = "Error while applying TCP-Sig to session(s)"; + break; + case BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK: + str = "ebgp-multihop and ttl-security cannot be configured together"; + break; + case BGP_ERR_NO_IBGP_WITH_TTLHACK: + str = "ttl-security only allowed for EBGP peers"; + break; + case BGP_ERR_AS_OVERRIDE: + str = "as-override cannot be configured for IBGP peers"; + break; + case BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT: + str = "Invalid limit for number of dynamic neighbors"; + break; + case BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS: + str = "Dynamic neighbor listen range already exists"; + break; + case BGP_ERR_INVALID_FOR_DYNAMIC_PEER: + str = "Operation not allowed on a dynamic neighbor"; + break; + case BGP_ERR_INVALID_FOR_DIRECT_PEER: + str = "Operation not allowed on a directly connected neighbor"; + break; + case BGP_ERR_PEER_SAFI_CONFLICT: + str = "Cannot activate peer for both 'ipv4 unicast' and 'ipv4 labeled-unicast'"; + break; + } + if (str) { + vty_out(vty, "%% %s\n", str); + return CMD_WARNING_CONFIG_FAILED; + } + return CMD_SUCCESS; } /* BGP clear sort. */ -enum clear_sort -{ - clear_all, - clear_peer, - clear_group, - clear_external, - clear_as +enum clear_sort { + clear_all, + clear_peer, + clear_group, + clear_external, + clear_as }; -static void -bgp_clear_vty_error (struct vty *vty, struct peer *peer, afi_t afi, - safi_t safi, int error) -{ - switch (error) - { - case BGP_ERR_AF_UNCONFIGURED: - vty_out (vty, - "%%BGP: Enable %s address family for the neighbor %s\n", - afi_safi_print(afi, safi), peer->host); - break; - case BGP_ERR_SOFT_RECONFIG_UNCONFIGURED: - vty_out (vty, "%%BGP: Inbound soft reconfig for %s not possible as it\n has neither refresh capability, nor inbound soft reconfig\n", peer->host); - break; - default: - break; - } +static void bgp_clear_vty_error(struct vty *vty, struct peer *peer, afi_t afi, + safi_t safi, int error) +{ + switch (error) { + case BGP_ERR_AF_UNCONFIGURED: + vty_out(vty, + "%%BGP: Enable %s address family for the neighbor %s\n", + afi_safi_print(afi, safi), peer->host); + break; + case BGP_ERR_SOFT_RECONFIG_UNCONFIGURED: + vty_out(vty, + "%%BGP: Inbound soft reconfig for %s not possible as it\n has neither refresh capability, nor inbound soft reconfig\n", + peer->host); + break; + default: + break; + } } /* `clear ip bgp' functions. */ -static int -bgp_clear (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, - enum clear_sort sort,enum bgp_clear_type stype, const char *arg) -{ - int ret; - struct peer *peer; - struct listnode *node, *nnode; - - /* Clear all neighbors. */ - /* - * Pass along pointer to next node to peer_clear() when walking all nodes - * on the BGP instance as that may get freed if it is a doppelganger - */ - if (sort == clear_all) - { - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (stype == BGP_CLEAR_SOFT_NONE) - ret = peer_clear (peer, &nnode); - else if (peer->afc[afi][safi]) - ret = peer_clear_soft (peer, afi, safi, stype); - else - ret = 0; - - if (ret < 0) - bgp_clear_vty_error (vty, peer, afi, safi, ret); - } - - /* This is to apply read-only mode on this clear. */ - if (stype == BGP_CLEAR_SOFT_NONE) - bgp->update_delay_over = 0; - - return CMD_SUCCESS; - } - - /* Clear specified neighbors. */ - if (sort == clear_peer) - { - union sockunion su; - int ret; - - /* Make sockunion for lookup. */ - ret = str2sockunion (arg, &su); - if (ret < 0) - { - peer = peer_lookup_by_conf_if (bgp, arg); - if (!peer) - { - peer = peer_lookup_by_hostname(bgp, arg); - if (!peer) - { - vty_out (vty, "Malformed address or name: %s\n", arg); - return CMD_WARNING; +static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, + enum clear_sort sort, enum bgp_clear_type stype, + const char *arg) +{ + int ret; + struct peer *peer; + struct listnode *node, *nnode; + + /* Clear all neighbors. */ + /* + * Pass along pointer to next node to peer_clear() when walking all + * nodes + * on the BGP instance as that may get freed if it is a doppelganger + */ + if (sort == clear_all) { + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (stype == BGP_CLEAR_SOFT_NONE) + ret = peer_clear(peer, &nnode); + else if (peer->afc[afi][safi]) + ret = peer_clear_soft(peer, afi, safi, stype); + else + ret = 0; + + if (ret < 0) + bgp_clear_vty_error(vty, peer, afi, safi, ret); } - } - } - else - { - peer = peer_lookup (bgp, &su); - if (! peer) - { - vty_out (vty, "%%BGP: Unknown neighbor - \"%s\"\n", arg); - return CMD_WARNING; - } - } - - if (stype == BGP_CLEAR_SOFT_NONE) - ret = peer_clear (peer, NULL); - else - ret = peer_clear_soft (peer, afi, safi, stype); - - if (ret < 0) - bgp_clear_vty_error (vty, peer, afi, safi, ret); - - return CMD_SUCCESS; - } - - /* Clear all peer-group members. */ - if (sort == clear_group) - { - struct peer_group *group; - - group = peer_group_lookup (bgp, arg); - if (! group) - { - vty_out (vty, "%%BGP: No such peer-group %s\n", arg); - return CMD_WARNING; + + /* This is to apply read-only mode on this clear. */ + if (stype == BGP_CLEAR_SOFT_NONE) + bgp->update_delay_over = 0; + + return CMD_SUCCESS; } - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (stype == BGP_CLEAR_SOFT_NONE) - { - peer_clear (peer, NULL); - continue; - } + /* Clear specified neighbors. */ + if (sort == clear_peer) { + union sockunion su; + int ret; + + /* Make sockunion for lookup. */ + ret = str2sockunion(arg, &su); + if (ret < 0) { + peer = peer_lookup_by_conf_if(bgp, arg); + if (!peer) { + peer = peer_lookup_by_hostname(bgp, arg); + if (!peer) { + vty_out(vty, + "Malformed address or name: %s\n", + arg); + return CMD_WARNING; + } + } + } else { + peer = peer_lookup(bgp, &su); + if (!peer) { + vty_out(vty, + "%%BGP: Unknown neighbor - \"%s\"\n", + arg); + return CMD_WARNING; + } + } - if (! peer->afc[afi][safi]) - continue; + if (stype == BGP_CLEAR_SOFT_NONE) + ret = peer_clear(peer, NULL); + else + ret = peer_clear_soft(peer, afi, safi, stype); - ret = peer_clear_soft (peer, afi, safi, stype); + if (ret < 0) + bgp_clear_vty_error(vty, peer, afi, safi, ret); - if (ret < 0) - bgp_clear_vty_error (vty, peer, afi, safi, ret); + return CMD_SUCCESS; } - return CMD_SUCCESS; - } - if (sort == clear_external) - { - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->sort == BGP_PEER_IBGP) - continue; + /* Clear all peer-group members. */ + if (sort == clear_group) { + struct peer_group *group; - if (stype == BGP_CLEAR_SOFT_NONE) - ret = peer_clear (peer, &nnode); - else - ret = peer_clear_soft (peer, afi, safi, stype); + group = peer_group_lookup(bgp, arg); + if (!group) { + vty_out(vty, "%%BGP: No such peer-group %s\n", arg); + return CMD_WARNING; + } + + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (stype == BGP_CLEAR_SOFT_NONE) { + peer_clear(peer, NULL); + continue; + } + + if (!peer->afc[afi][safi]) + continue; + + ret = peer_clear_soft(peer, afi, safi, stype); - if (ret < 0) - bgp_clear_vty_error (vty, peer, afi, safi, ret); + if (ret < 0) + bgp_clear_vty_error(vty, peer, afi, safi, ret); + } + return CMD_SUCCESS; } - return CMD_SUCCESS; - } - if (sort == clear_as) - { - as_t as; - int find = 0; + if (sort == clear_external) { + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (peer->sort == BGP_PEER_IBGP) + continue; - as = strtoul(arg, NULL, 10); + if (stype == BGP_CLEAR_SOFT_NONE) + ret = peer_clear(peer, &nnode); + else + ret = peer_clear_soft(peer, afi, safi, stype); - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->as != as) - continue; - - find = 1; - if (stype == BGP_CLEAR_SOFT_NONE) - ret = peer_clear (peer, &nnode); - else - ret = peer_clear_soft (peer, afi, safi, stype); - - if (ret < 0) - bgp_clear_vty_error (vty, peer, afi, safi, ret); - } - if (! find) - vty_out (vty, "%%BGP: No peer is configured with AS %s\n", arg); - return CMD_SUCCESS; - } - - return CMD_SUCCESS; -} - -static int -bgp_clear_vty (struct vty *vty, const char *name, afi_t afi, safi_t safi, - enum clear_sort sort, enum bgp_clear_type stype, - const char *arg) -{ - struct bgp *bgp; - - /* BGP structure lookup. */ - if (name) - { - bgp = bgp_lookup_by_name (name); - if (bgp == NULL) - { - vty_out (vty, "Can't find BGP instance %s\n", name); - return CMD_WARNING; - } - } - else - { - bgp = bgp_get_default (); - if (bgp == NULL) - { - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING; - } - } - - return bgp_clear (vty, bgp, afi, safi, sort, stype, arg); + if (ret < 0) + bgp_clear_vty_error(vty, peer, afi, safi, ret); + } + return CMD_SUCCESS; + } + + if (sort == clear_as) { + as_t as; + int find = 0; + + as = strtoul(arg, NULL, 10); + + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (peer->as != as) + continue; + + find = 1; + if (stype == BGP_CLEAR_SOFT_NONE) + ret = peer_clear(peer, &nnode); + else + ret = peer_clear_soft(peer, afi, safi, stype); + + if (ret < 0) + bgp_clear_vty_error(vty, peer, afi, safi, ret); + } + if (!find) + vty_out(vty, + "%%BGP: No peer is configured with AS %s\n", + arg); + return CMD_SUCCESS; + } + + return CMD_SUCCESS; +} + +static int bgp_clear_vty(struct vty *vty, const char *name, afi_t afi, + safi_t safi, enum clear_sort sort, + enum bgp_clear_type stype, const char *arg) +{ + struct bgp *bgp; + + /* BGP structure lookup. */ + if (name) { + bgp = bgp_lookup_by_name(name); + if (bgp == NULL) { + vty_out(vty, "Can't find BGP instance %s\n", name); + return CMD_WARNING; + } + } else { + bgp = bgp_get_default(); + if (bgp == NULL) { + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING; + } + } + + return bgp_clear(vty, bgp, afi, safi, sort, stype, arg); } /* clear soft inbound */ -static void -bgp_clear_star_soft_in (struct vty *vty, const char *name) +static void bgp_clear_star_soft_in(struct vty *vty, const char *name) { - bgp_clear_vty (vty, name, AFI_IP, SAFI_UNICAST, clear_all, - BGP_CLEAR_SOFT_IN, NULL); - bgp_clear_vty (vty, name, AFI_IP6, SAFI_UNICAST, clear_all, - BGP_CLEAR_SOFT_IN, NULL); + bgp_clear_vty(vty, name, AFI_IP, SAFI_UNICAST, clear_all, + BGP_CLEAR_SOFT_IN, NULL); + bgp_clear_vty(vty, name, AFI_IP6, SAFI_UNICAST, clear_all, + BGP_CLEAR_SOFT_IN, NULL); } /* clear soft outbound */ -static void -bgp_clear_star_soft_out (struct vty *vty, const char *name) +static void bgp_clear_star_soft_out(struct vty *vty, const char *name) { - bgp_clear_vty (vty, name, AFI_IP, SAFI_UNICAST, clear_all, - BGP_CLEAR_SOFT_OUT, NULL); - bgp_clear_vty (vty, name, AFI_IP6, SAFI_UNICAST, clear_all, - BGP_CLEAR_SOFT_OUT, NULL); + bgp_clear_vty(vty, name, AFI_IP, SAFI_UNICAST, clear_all, + BGP_CLEAR_SOFT_OUT, NULL); + bgp_clear_vty(vty, name, AFI_IP6, SAFI_UNICAST, clear_all, + BGP_CLEAR_SOFT_OUT, NULL); } @@ -773,8 +723,8 @@ DEFUN (bgp_multiple_instance_func, BGP_STR "Enable bgp multiple instance\n") { - bgp_option_set (BGP_OPT_MULTIPLE_INSTANCE); - return CMD_SUCCESS; + bgp_option_set(BGP_OPT_MULTIPLE_INSTANCE); + return CMD_SUCCESS; } DEFUN (no_bgp_multiple_instance, @@ -784,15 +734,14 @@ DEFUN (no_bgp_multiple_instance, BGP_STR "BGP multiple instance\n") { - int ret; + int ret; - ret = bgp_option_unset (BGP_OPT_MULTIPLE_INSTANCE); - if (ret < 0) - { - vty_out (vty, "%% There are more than two BGP instances\n"); - return CMD_WARNING_CONFIG_FAILED; - } - return CMD_SUCCESS; + ret = bgp_option_unset(BGP_OPT_MULTIPLE_INSTANCE); + if (ret < 0) { + vty_out(vty, "%% There are more than two BGP instances\n"); + return CMD_WARNING_CONFIG_FAILED; + } + return CMD_SUCCESS; } DEFUN (bgp_config_type, @@ -803,13 +752,13 @@ DEFUN (bgp_config_type, "cisco\n" "zebra\n") { - int idx = 0; - if (argv_find (argv, argc, "cisco", &idx)) - bgp_option_set (BGP_OPT_CONFIG_CISCO); - else - bgp_option_unset (BGP_OPT_CONFIG_CISCO); + int idx = 0; + if (argv_find(argv, argc, "cisco", &idx)) + bgp_option_set(BGP_OPT_CONFIG_CISCO); + else + bgp_option_unset(BGP_OPT_CONFIG_CISCO); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bgp_config_type, @@ -821,8 +770,8 @@ DEFUN (no_bgp_config_type, "cisco\n" "zebra\n") { - bgp_option_unset (BGP_OPT_CONFIG_CISCO); - return CMD_SUCCESS; + bgp_option_unset(BGP_OPT_CONFIG_CISCO); + return CMD_SUCCESS; } @@ -832,7 +781,7 @@ DEFUN (no_synchronization, NO_STR "Perform IGP synchronization\n") { - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_auto_summary, @@ -841,7 +790,7 @@ DEFUN (no_auto_summary, NO_STR "Enable automatic network number summarization\n") { - return CMD_SUCCESS; + return CMD_SUCCESS; } /* "router bgp" commands. */ @@ -853,72 +802,71 @@ DEFUN_NOSH (router_bgp, AS_STR BGP_INSTANCE_HELP_STR) { - int idx_asn = 2; - int idx_view_vrf = 3; - int idx_vrf = 4; - int ret; - as_t as; - struct bgp *bgp; - const char *name = NULL; - enum bgp_instance_type inst_type; - - // "router bgp" without an ASN - if (argc == 2) - { - //Pending: Make VRF option available for ASN less config - bgp = bgp_get_default(); - - if (bgp == NULL) - { - vty_out (vty, "%% No BGP process is configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (listcount(bm->bgp) > 1) - { - vty_out (vty, "%% Multiple BGP processes are configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - // "router bgp X" - else - { - as = strtoul (argv[idx_asn]->arg, NULL, 10); - - inst_type = BGP_INSTANCE_TYPE_DEFAULT; - if (argc > 3) - { - name = argv[idx_vrf]->arg; - - if (!strcmp(argv[idx_view_vrf]->text, "vrf")) - inst_type = BGP_INSTANCE_TYPE_VRF; - else if (!strcmp(argv[idx_view_vrf]->text, "view")) - inst_type = BGP_INSTANCE_TYPE_VIEW; - } - - ret = bgp_get (&bgp, &as, name, inst_type); - switch (ret) - { - case BGP_ERR_MULTIPLE_INSTANCE_NOT_SET: - vty_out (vty, "Please specify 'bgp multiple-instance' first\n"); - return CMD_WARNING_CONFIG_FAILED; - case BGP_ERR_AS_MISMATCH: - vty_out (vty, "BGP is already running; AS is %u\n", as); - return CMD_WARNING_CONFIG_FAILED; - case BGP_ERR_INSTANCE_MISMATCH: - vty_out (vty, "BGP instance name and AS number mismatch\n"); - vty_out (vty, "BGP instance is already running; AS is %u\n", - as); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Pending: handle when user tries to change a view to vrf n vv. */ - } - - VTY_PUSH_CONTEXT(BGP_NODE, bgp); - - return CMD_SUCCESS; + int idx_asn = 2; + int idx_view_vrf = 3; + int idx_vrf = 4; + int ret; + as_t as; + struct bgp *bgp; + const char *name = NULL; + enum bgp_instance_type inst_type; + + // "router bgp" without an ASN + if (argc == 2) { + // Pending: Make VRF option available for ASN less config + bgp = bgp_get_default(); + + if (bgp == NULL) { + vty_out(vty, "%% No BGP process is configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (listcount(bm->bgp) > 1) { + vty_out(vty, + "%% Multiple BGP processes are configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + // "router bgp X" + else { + as = strtoul(argv[idx_asn]->arg, NULL, 10); + + inst_type = BGP_INSTANCE_TYPE_DEFAULT; + if (argc > 3) { + name = argv[idx_vrf]->arg; + + if (!strcmp(argv[idx_view_vrf]->text, "vrf")) + inst_type = BGP_INSTANCE_TYPE_VRF; + else if (!strcmp(argv[idx_view_vrf]->text, "view")) + inst_type = BGP_INSTANCE_TYPE_VIEW; + } + + ret = bgp_get(&bgp, &as, name, inst_type); + switch (ret) { + case BGP_ERR_MULTIPLE_INSTANCE_NOT_SET: + vty_out(vty, + "Please specify 'bgp multiple-instance' first\n"); + return CMD_WARNING_CONFIG_FAILED; + case BGP_ERR_AS_MISMATCH: + vty_out(vty, "BGP is already running; AS is %u\n", as); + return CMD_WARNING_CONFIG_FAILED; + case BGP_ERR_INSTANCE_MISMATCH: + vty_out(vty, + "BGP instance name and AS number mismatch\n"); + vty_out(vty, + "BGP instance is already running; AS is %u\n", + as); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Pending: handle when user tries to change a view to vrf n vv. + */ + } + + VTY_PUSH_CONTEXT(BGP_NODE, bgp); + + return CMD_SUCCESS; } /* "no router bgp" commands. */ @@ -931,53 +879,47 @@ DEFUN (no_router_bgp, AS_STR BGP_INSTANCE_HELP_STR) { - int idx_asn = 3; - int idx_vrf = 5; - as_t as; - struct bgp *bgp; - const char *name = NULL; + int idx_asn = 3; + int idx_vrf = 5; + as_t as; + struct bgp *bgp; + const char *name = NULL; - // "no router bgp" without an ASN - if (argc == 3) - { - //Pending: Make VRF option available for ASN less config - bgp = bgp_get_default(); + // "no router bgp" without an ASN + if (argc == 3) { + // Pending: Make VRF option available for ASN less config + bgp = bgp_get_default(); - if (bgp == NULL) - { - vty_out (vty, "%% No BGP process is configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (bgp == NULL) { + vty_out(vty, "%% No BGP process is configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (listcount(bm->bgp) > 1) - { - vty_out (vty, "%% Multiple BGP processes are configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - else - { - as = strtoul(argv[idx_asn]->arg, NULL, 10); + if (listcount(bm->bgp) > 1) { + vty_out(vty, + "%% Multiple BGP processes are configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } else { + as = strtoul(argv[idx_asn]->arg, NULL, 10); - if (argc > 4) - name = argv[idx_vrf]->arg; + if (argc > 4) + name = argv[idx_vrf]->arg; - /* Lookup bgp structure. */ - bgp = bgp_lookup (as, name); - if (! bgp) - { - vty_out (vty, "%% Can't find BGP instance\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } + /* Lookup bgp structure. */ + bgp = bgp_lookup(as, name); + if (!bgp) { + vty_out(vty, "%% Can't find BGP instance\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } - bgp_delete (bgp); + bgp_delete(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } - /* BGP router-id. */ DEFPY (bgp_router_id, @@ -987,9 +929,9 @@ DEFPY (bgp_router_id, "Override configured router identifier\n" "Manually configured router identifier\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_router_id_static_set (bgp, router_id); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_router_id_static_set(bgp, router_id); + return CMD_SUCCESS; } DEFPY (no_bgp_router_id, @@ -1000,21 +942,19 @@ DEFPY (no_bgp_router_id, "Override configured router identifier\n" "Manually configured router identifier\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); - if (router_id_str) - { - if (! IPV4_ADDR_SAME (&bgp->router_id_static, &router_id)) - { - vty_out (vty, "%% BGP router-id doesn't match\n"); - return CMD_WARNING_CONFIG_FAILED; + if (router_id_str) { + if (!IPV4_ADDR_SAME(&bgp->router_id_static, &router_id)) { + vty_out(vty, "%% BGP router-id doesn't match\n"); + return CMD_WARNING_CONFIG_FAILED; + } } - } - router_id.s_addr = 0; - bgp_router_id_static_set (bgp, router_id); + router_id.s_addr = 0; + bgp_router_id_static_set(bgp, router_id); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1027,22 +967,21 @@ DEFUN (bgp_cluster_id, "Route-Reflector Cluster-id in IP address format\n" "Route-Reflector Cluster-id as 32 bit quantity\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_ipv4 = 2; - int ret; - struct in_addr cluster; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_ipv4 = 2; + int ret; + struct in_addr cluster; - ret = inet_aton (argv[idx_ipv4]->arg, &cluster); - if (! ret) - { - vty_out (vty, "%% Malformed bgp cluster identifier\n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = inet_aton(argv[idx_ipv4]->arg, &cluster); + if (!ret) { + vty_out(vty, "%% Malformed bgp cluster identifier\n"); + return CMD_WARNING_CONFIG_FAILED; + } - bgp_cluster_id_set (bgp, &cluster); - bgp_clear_star_soft_out (vty, bgp->name); + bgp_cluster_id_set(bgp, &cluster); + bgp_clear_star_soft_out(vty, bgp->name); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bgp_cluster_id, @@ -1054,11 +993,11 @@ DEFUN (no_bgp_cluster_id, "Route-Reflector Cluster-id in IP address format\n" "Route-Reflector Cluster-id as 32 bit quantity\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_cluster_id_unset (bgp); - bgp_clear_star_soft_out (vty, bgp->name); + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_cluster_id_unset(bgp); + bgp_clear_star_soft_out(vty, bgp->name); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (bgp_confederation_identifier, @@ -1069,15 +1008,15 @@ DEFUN (bgp_confederation_identifier, "AS number\n" "Set routing domain confederation AS\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_number = 3; - as_t as; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_number = 3; + as_t as; - as = strtoul(argv[idx_number]->arg, NULL, 10); + as = strtoul(argv[idx_number]->arg, NULL, 10); - bgp_confederation_id_set (bgp, as); + bgp_confederation_id_set(bgp, as); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bgp_confederation_identifier, @@ -1089,10 +1028,10 @@ DEFUN (no_bgp_confederation_identifier, "AS number\n" "Set routing domain confederation AS\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_confederation_id_unset (bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_confederation_id_unset(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (bgp_confederation_peers, @@ -1103,24 +1042,23 @@ DEFUN (bgp_confederation_peers, "Peer ASs in BGP confederation\n" AS_STR) { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_asn = 3; - as_t as; - int i; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_asn = 3; + as_t as; + int i; - for (i = idx_asn; i < argc; i++) - { - as = strtoul(argv[i]->arg, NULL, 10); + for (i = idx_asn; i < argc; i++) { + as = strtoul(argv[i]->arg, NULL, 10); - if (bgp->as == as) - { - vty_out (vty, "%% Local member-AS not allowed in confed peer list\n"); - continue; - } + if (bgp->as == as) { + vty_out(vty, + "%% Local member-AS not allowed in confed peer list\n"); + continue; + } - bgp_confederation_peers_add (bgp, as); - } - return CMD_SUCCESS; + bgp_confederation_peers_add(bgp, as); + } + return CMD_SUCCESS; } DEFUN (no_bgp_confederation_peers, @@ -1132,18 +1070,17 @@ DEFUN (no_bgp_confederation_peers, "Peer ASs in BGP confederation\n" AS_STR) { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_asn = 4; - as_t as; - int i; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_asn = 4; + as_t as; + int i; - for (i = idx_asn; i < argc; i++) - { - as = strtoul(argv[i]->arg, NULL, 10); + for (i = idx_asn; i < argc; i++) { + as = strtoul(argv[i]->arg, NULL, 10); - bgp_confederation_peers_remove (bgp, as); - } - return CMD_SUCCESS; + bgp_confederation_peers_remove(bgp, as); + } + return CMD_SUCCESS; } /** @@ -1151,47 +1088,44 @@ DEFUN (no_bgp_confederation_peers, * @peer_type: BGP_PEER_EBGP or BGP_PEER_IBGP * @set: 1 for setting values, 0 for removing the max-paths config. */ -static int -bgp_maxpaths_config_vty (struct vty *vty, int peer_type, const char *mpaths, - u_int16_t options, int set) -{ - VTY_DECLVAR_CONTEXT(bgp, bgp); - u_int16_t maxpaths = 0; - int ret; - afi_t afi; - safi_t safi; - - afi = bgp_node_afi (vty); - safi = bgp_node_safi (vty); - - if (set) - { - maxpaths = strtol(mpaths, NULL, 10); - if (maxpaths > multipath_num) - { - vty_out (vty, - "%% Maxpaths Specified: %d is > than multipath num specified on bgp command line %d", - maxpaths, multipath_num); - return CMD_WARNING_CONFIG_FAILED; - } - ret = bgp_maximum_paths_set (bgp, afi, safi, peer_type, maxpaths, options); - } - else - ret = bgp_maximum_paths_unset (bgp, afi, safi, peer_type); - - if (ret < 0) - { - vty_out (vty, - "%% Failed to %sset maximum-paths %s %u for afi %u, safi %u\n", - (set == 1) ? "" : "un", - (peer_type == BGP_PEER_EBGP) ? "ebgp" : "ibgp", - maxpaths, afi, safi); - return CMD_WARNING_CONFIG_FAILED; - } - - bgp_recalculate_all_bestpaths (bgp); - - return CMD_SUCCESS; +static int bgp_maxpaths_config_vty(struct vty *vty, int peer_type, + const char *mpaths, u_int16_t options, + int set) +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + u_int16_t maxpaths = 0; + int ret; + afi_t afi; + safi_t safi; + + afi = bgp_node_afi(vty); + safi = bgp_node_safi(vty); + + if (set) { + maxpaths = strtol(mpaths, NULL, 10); + if (maxpaths > multipath_num) { + vty_out(vty, + "%% Maxpaths Specified: %d is > than multipath num specified on bgp command line %d", + maxpaths, multipath_num); + return CMD_WARNING_CONFIG_FAILED; + } + ret = bgp_maximum_paths_set(bgp, afi, safi, peer_type, maxpaths, + options); + } else + ret = bgp_maximum_paths_unset(bgp, afi, safi, peer_type); + + if (ret < 0) { + vty_out(vty, + "%% Failed to %sset maximum-paths %s %u for afi %u, safi %u\n", + (set == 1) ? "" : "un", + (peer_type == BGP_PEER_EBGP) ? "ebgp" : "ibgp", + maxpaths, afi, safi); + return CMD_WARNING_CONFIG_FAILED; + } + + bgp_recalculate_all_bestpaths(bgp); + + return CMD_SUCCESS; } DEFUN (bgp_maxmed_admin, @@ -1201,14 +1135,14 @@ DEFUN (bgp_maxmed_admin, "Advertise routes with max-med\n" "Administratively applied, for an indefinite period\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp->v_maxmed_admin = 1; - bgp->maxmed_admin_value = BGP_MAXMED_VALUE_DEFAULT; + bgp->v_maxmed_admin = 1; + bgp->maxmed_admin_value = BGP_MAXMED_VALUE_DEFAULT; - bgp_maxmed_update(bgp); + bgp_maxmed_update(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (bgp_maxmed_admin_medv, @@ -1219,15 +1153,15 @@ DEFUN (bgp_maxmed_admin_medv, "Administratively applied, for an indefinite period\n" "Max MED value to be used\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_number = 3; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_number = 3; - bgp->v_maxmed_admin = 1; - bgp->maxmed_admin_value = strtoul (argv[idx_number]->arg, NULL, 10); + bgp->v_maxmed_admin = 1; + bgp->maxmed_admin_value = strtoul(argv[idx_number]->arg, NULL, 10); - bgp_maxmed_update(bgp); + bgp_maxmed_update(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bgp_maxmed_admin, @@ -1239,12 +1173,12 @@ DEFUN (no_bgp_maxmed_admin, "Administratively applied, for an indefinite period\n" "Max MED value to be used\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp->v_maxmed_admin = BGP_MAXMED_ADMIN_UNCONFIGURED; - bgp->maxmed_admin_value = BGP_MAXMED_VALUE_DEFAULT; - bgp_maxmed_update(bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp->v_maxmed_admin = BGP_MAXMED_ADMIN_UNCONFIGURED; + bgp->maxmed_admin_value = BGP_MAXMED_VALUE_DEFAULT; + bgp_maxmed_update(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (bgp_maxmed_onstartup, @@ -1256,19 +1190,19 @@ DEFUN (bgp_maxmed_onstartup, "Time (seconds) period for max-med\n" "Max MED value to be used\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx = 0; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx = 0; - argv_find (argv, argc, "(5-86400)", &idx); - bgp->v_maxmed_onstartup = strtoul (argv[idx]->arg, NULL, 10); - if (argv_find (argv, argc, "(0-4294967295)", &idx)) - bgp->maxmed_onstartup_value = strtoul (argv[idx]->arg, NULL, 10); - else - bgp->maxmed_onstartup_value = BGP_MAXMED_VALUE_DEFAULT; + argv_find(argv, argc, "(5-86400)", &idx); + bgp->v_maxmed_onstartup = strtoul(argv[idx]->arg, NULL, 10); + if (argv_find(argv, argc, "(0-4294967295)", &idx)) + bgp->maxmed_onstartup_value = strtoul(argv[idx]->arg, NULL, 10); + else + bgp->maxmed_onstartup_value = BGP_MAXMED_VALUE_DEFAULT; - bgp_maxmed_update(bgp); + bgp_maxmed_update(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bgp_maxmed_onstartup, @@ -1281,77 +1215,72 @@ DEFUN (no_bgp_maxmed_onstartup, "Time (seconds) period for max-med\n" "Max MED value to be used\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); - /* Cancel max-med onstartup if its on */ - if (bgp->t_maxmed_onstartup) - { - THREAD_TIMER_OFF (bgp->t_maxmed_onstartup); - bgp->maxmed_onstartup_over = 1; - } + /* Cancel max-med onstartup if its on */ + if (bgp->t_maxmed_onstartup) { + THREAD_TIMER_OFF(bgp->t_maxmed_onstartup); + bgp->maxmed_onstartup_over = 1; + } - bgp->v_maxmed_onstartup = BGP_MAXMED_ONSTARTUP_UNCONFIGURED; - bgp->maxmed_onstartup_value = BGP_MAXMED_VALUE_DEFAULT; + bgp->v_maxmed_onstartup = BGP_MAXMED_ONSTARTUP_UNCONFIGURED; + bgp->maxmed_onstartup_value = BGP_MAXMED_VALUE_DEFAULT; - bgp_maxmed_update(bgp); + bgp_maxmed_update(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -bgp_update_delay_config_vty (struct vty *vty, const char *delay, - const char *wait) +static int bgp_update_delay_config_vty(struct vty *vty, const char *delay, + const char *wait) { - VTY_DECLVAR_CONTEXT(bgp, bgp); - u_int16_t update_delay; - u_int16_t establish_wait; + VTY_DECLVAR_CONTEXT(bgp, bgp); + u_int16_t update_delay; + u_int16_t establish_wait; - update_delay = strtoul(delay, NULL, 10); + update_delay = strtoul(delay, NULL, 10); - if (!wait) /* update-delay */ - { - bgp->v_update_delay = update_delay; - bgp->v_establish_wait = bgp->v_update_delay; - return CMD_SUCCESS; - } + if (!wait) /* update-delay */ + { + bgp->v_update_delay = update_delay; + bgp->v_establish_wait = bgp->v_update_delay; + return CMD_SUCCESS; + } - /* update-delay */ - establish_wait = atoi (wait); - if (update_delay < establish_wait) - { - vty_out (vty, "%%Failed: update-delay less than the establish-wait!\n"); - return CMD_WARNING_CONFIG_FAILED; - } + /* update-delay */ + establish_wait = atoi(wait); + if (update_delay < establish_wait) { + vty_out(vty, + "%%Failed: update-delay less than the establish-wait!\n"); + return CMD_WARNING_CONFIG_FAILED; + } - bgp->v_update_delay = update_delay; - bgp->v_establish_wait = establish_wait; + bgp->v_update_delay = update_delay; + bgp->v_establish_wait = establish_wait; - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -bgp_update_delay_deconfig_vty (struct vty *vty) +static int bgp_update_delay_deconfig_vty(struct vty *vty) { - VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp->v_update_delay = BGP_UPDATE_DELAY_DEF; - bgp->v_establish_wait = bgp->v_update_delay; + bgp->v_update_delay = BGP_UPDATE_DELAY_DEF; + bgp->v_establish_wait = bgp->v_update_delay; - return CMD_SUCCESS; + return CMD_SUCCESS; } -int -bgp_config_write_update_delay (struct vty *vty, struct bgp *bgp) +int bgp_config_write_update_delay(struct vty *vty, struct bgp *bgp) { - if (bgp->v_update_delay != BGP_UPDATE_DELAY_DEF) - { - vty_out (vty, " update-delay %d", bgp->v_update_delay); - if (bgp->v_update_delay != bgp->v_establish_wait) - vty_out (vty, " %d", bgp->v_establish_wait); - vty_out (vty, "\n"); - } + if (bgp->v_update_delay != BGP_UPDATE_DELAY_DEF) { + vty_out(vty, " update-delay %d", bgp->v_update_delay); + if (bgp->v_update_delay != bgp->v_establish_wait) + vty_out(vty, " %d", bgp->v_establish_wait); + vty_out(vty, "\n"); + } - return 0; + return 0; } @@ -1362,8 +1291,8 @@ DEFUN (bgp_update_delay, "Force initial delay for best-path and updates\n" "Seconds\n") { - int idx_number = 1; - return bgp_update_delay_config_vty(vty, argv[idx_number]->arg, NULL); + int idx_number = 1; + return bgp_update_delay_config_vty(vty, argv[idx_number]->arg, NULL); } DEFUN (bgp_update_delay_establish_wait, @@ -1373,9 +1302,10 @@ DEFUN (bgp_update_delay_establish_wait, "Seconds\n" "Seconds\n") { - int idx_number = 1; - int idx_number_2 = 2; - return bgp_update_delay_config_vty(vty, argv[idx_number]->arg, argv[idx_number_2]->arg); + int idx_number = 1; + int idx_number_2 = 2; + return bgp_update_delay_config_vty(vty, argv[idx_number]->arg, + argv[idx_number_2]->arg); } /* Update-delay deconfiguration */ @@ -1387,31 +1317,29 @@ DEFUN (no_bgp_update_delay, "Seconds\n" "Seconds\n") { - return bgp_update_delay_deconfig_vty(vty); + return bgp_update_delay_deconfig_vty(vty); } -static int -bgp_wpkt_quanta_config_vty (struct vty *vty, const char *num, char set) +static int bgp_wpkt_quanta_config_vty(struct vty *vty, const char *num, + char set) { - VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); - if (set) - bgp->wpkt_quanta = strtoul(num, NULL, 10); - else - bgp->wpkt_quanta = BGP_WRITE_PACKET_MAX; + if (set) + bgp->wpkt_quanta = strtoul(num, NULL, 10); + else + bgp->wpkt_quanta = BGP_WRITE_PACKET_MAX; - return CMD_SUCCESS; + return CMD_SUCCESS; } -int -bgp_config_write_wpkt_quanta (struct vty *vty, struct bgp *bgp) +int bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp) { - if (bgp->wpkt_quanta != BGP_WRITE_PACKET_MAX) - vty_out (vty, " write-quanta %d\n", - bgp->wpkt_quanta); + if (bgp->wpkt_quanta != BGP_WRITE_PACKET_MAX) + vty_out(vty, " write-quanta %d\n", bgp->wpkt_quanta); - return 0; + return 0; } @@ -1422,8 +1350,8 @@ DEFUN (bgp_wpkt_quanta, "How many packets to write to peer socket per run\n" "Number of packets\n") { - int idx_number = 1; - return bgp_wpkt_quanta_config_vty(vty, argv[idx_number]->arg, 1); + int idx_number = 1; + return bgp_wpkt_quanta_config_vty(vty, argv[idx_number]->arg, 1); } /* Update-delay deconfiguration */ @@ -1434,18 +1362,16 @@ DEFUN (no_bgp_wpkt_quanta, "How many packets to write to peer socket per run\n" "Number of packets\n") { - int idx_number = 2; - return bgp_wpkt_quanta_config_vty(vty, argv[idx_number]->arg, 0); + int idx_number = 2; + return bgp_wpkt_quanta_config_vty(vty, argv[idx_number]->arg, 0); } -int -bgp_config_write_coalesce_time (struct vty *vty, struct bgp *bgp) +int bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp) { - if (bgp->coalesce_time != BGP_DEFAULT_SUBGROUP_COALESCE_TIME) - vty_out (vty, " coalesce-time %u\n", - bgp->coalesce_time); + if (bgp->coalesce_time != BGP_DEFAULT_SUBGROUP_COALESCE_TIME) + vty_out(vty, " coalesce-time %u\n", bgp->coalesce_time); - return 0; + return 0; } @@ -1455,12 +1381,12 @@ DEFUN (bgp_coalesce_time, "Subgroup coalesce timer\n" "Subgroup coalesce timer value (in ms)\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx = 0; - argv_find (argv, argc, "(0-4294967295)", &idx); - bgp->coalesce_time = strtoul (argv[idx]->arg, NULL, 10); - return CMD_SUCCESS; + int idx = 0; + argv_find(argv, argc, "(0-4294967295)", &idx); + bgp->coalesce_time = strtoul(argv[idx]->arg, NULL, 10); + return CMD_SUCCESS; } DEFUN (no_bgp_coalesce_time, @@ -1470,10 +1396,10 @@ DEFUN (no_bgp_coalesce_time, "Subgroup coalesce timer\n" "Subgroup coalesce timer value (in ms)\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME; - return CMD_SUCCESS; + bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME; + return CMD_SUCCESS; } /* Maximum-paths configuration */ @@ -1483,15 +1409,15 @@ DEFUN (bgp_maxpaths, "Forward packets over multiple paths\n" "Number of paths\n") { - int idx_number = 1; - return bgp_maxpaths_config_vty(vty, BGP_PEER_EBGP, argv[idx_number]->arg, 0, 1); + int idx_number = 1; + return bgp_maxpaths_config_vty(vty, BGP_PEER_EBGP, + argv[idx_number]->arg, 0, 1); } -ALIAS_HIDDEN (bgp_maxpaths, - bgp_maxpaths_hidden_cmd, - "maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM), - "Forward packets over multiple paths\n" - "Number of paths\n") +ALIAS_HIDDEN(bgp_maxpaths, bgp_maxpaths_hidden_cmd, + "maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM), + "Forward packets over multiple paths\n" + "Number of paths\n") DEFUN (bgp_maxpaths_ibgp, bgp_maxpaths_ibgp_cmd, @@ -1500,16 +1426,16 @@ DEFUN (bgp_maxpaths_ibgp, "iBGP-multipath\n" "Number of paths\n") { - int idx_number = 2; - return bgp_maxpaths_config_vty(vty, BGP_PEER_IBGP, argv[idx_number]->arg, 0, 1); + int idx_number = 2; + return bgp_maxpaths_config_vty(vty, BGP_PEER_IBGP, + argv[idx_number]->arg, 0, 1); } -ALIAS_HIDDEN (bgp_maxpaths_ibgp, - bgp_maxpaths_ibgp_hidden_cmd, - "maximum-paths ibgp " CMD_RANGE_STR(1, MULTIPATH_NUM), - "Forward packets over multiple paths\n" - "iBGP-multipath\n" - "Number of paths\n") +ALIAS_HIDDEN(bgp_maxpaths_ibgp, bgp_maxpaths_ibgp_hidden_cmd, + "maximum-paths ibgp " CMD_RANGE_STR(1, MULTIPATH_NUM), + "Forward packets over multiple paths\n" + "iBGP-multipath\n" + "Number of paths\n") DEFUN (bgp_maxpaths_ibgp_cluster, bgp_maxpaths_ibgp_cluster_cmd, @@ -1519,18 +1445,19 @@ DEFUN (bgp_maxpaths_ibgp_cluster, "Number of paths\n" "Match the cluster length\n") { - int idx_number = 2; - return bgp_maxpaths_config_vty(vty, BGP_PEER_IBGP, argv[idx_number]->arg, - BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN, 1); + int idx_number = 2; + return bgp_maxpaths_config_vty( + vty, BGP_PEER_IBGP, argv[idx_number]->arg, + BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN, 1); } -ALIAS_HIDDEN (bgp_maxpaths_ibgp_cluster, - bgp_maxpaths_ibgp_cluster_hidden_cmd, - "maximum-paths ibgp " CMD_RANGE_STR(1, MULTIPATH_NUM) " equal-cluster-length", - "Forward packets over multiple paths\n" - "iBGP-multipath\n" - "Number of paths\n" - "Match the cluster length\n") +ALIAS_HIDDEN(bgp_maxpaths_ibgp_cluster, bgp_maxpaths_ibgp_cluster_hidden_cmd, + "maximum-paths ibgp " CMD_RANGE_STR( + 1, MULTIPATH_NUM) " equal-cluster-length", + "Forward packets over multiple paths\n" + "iBGP-multipath\n" + "Number of paths\n" + "Match the cluster length\n") DEFUN (no_bgp_maxpaths, no_bgp_maxpaths_cmd, @@ -1539,15 +1466,13 @@ DEFUN (no_bgp_maxpaths, "Forward packets over multiple paths\n" "Number of paths\n") { - return bgp_maxpaths_config_vty(vty, BGP_PEER_EBGP, NULL, 0, 0); + return bgp_maxpaths_config_vty(vty, BGP_PEER_EBGP, NULL, 0, 0); } -ALIAS_HIDDEN (no_bgp_maxpaths, - no_bgp_maxpaths_hidden_cmd, - "no maximum-paths [" CMD_RANGE_STR(1, MULTIPATH_NUM) "]", - NO_STR - "Forward packets over multiple paths\n" - "Number of paths\n") +ALIAS_HIDDEN(no_bgp_maxpaths, no_bgp_maxpaths_hidden_cmd, + "no maximum-paths [" CMD_RANGE_STR(1, MULTIPATH_NUM) "]", NO_STR + "Forward packets over multiple paths\n" + "Number of paths\n") DEFUN (no_bgp_maxpaths_ibgp, no_bgp_maxpaths_ibgp_cmd, @@ -1558,41 +1483,38 @@ DEFUN (no_bgp_maxpaths_ibgp, "Number of paths\n" "Match the cluster length\n") { - return bgp_maxpaths_config_vty(vty, BGP_PEER_IBGP, NULL, 0, 0); + return bgp_maxpaths_config_vty(vty, BGP_PEER_IBGP, NULL, 0, 0); } -ALIAS_HIDDEN (no_bgp_maxpaths_ibgp, - no_bgp_maxpaths_ibgp_hidden_cmd, - "no maximum-paths ibgp [" CMD_RANGE_STR(1, MULTIPATH_NUM) " [equal-cluster-length]]", - NO_STR - "Forward packets over multiple paths\n" - "iBGP-multipath\n" - "Number of paths\n" - "Match the cluster length\n") +ALIAS_HIDDEN(no_bgp_maxpaths_ibgp, no_bgp_maxpaths_ibgp_hidden_cmd, + "no maximum-paths ibgp [" CMD_RANGE_STR( + 1, MULTIPATH_NUM) " [equal-cluster-length]]", + NO_STR + "Forward packets over multiple paths\n" + "iBGP-multipath\n" + "Number of paths\n" + "Match the cluster length\n") -int -bgp_config_write_maxpaths (struct vty *vty, struct bgp *bgp, afi_t afi, - safi_t safi, int *write) +int bgp_config_write_maxpaths(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi, int *write) { - if (bgp->maxpaths[afi][safi].maxpaths_ebgp != MULTIPATH_NUM) - { - bgp_config_write_family_header (vty, afi, safi, write); - vty_out (vty, " maximum-paths %d\n", - bgp->maxpaths[afi][safi].maxpaths_ebgp); - } + if (bgp->maxpaths[afi][safi].maxpaths_ebgp != MULTIPATH_NUM) { + bgp_config_write_family_header(vty, afi, safi, write); + vty_out(vty, " maximum-paths %d\n", + bgp->maxpaths[afi][safi].maxpaths_ebgp); + } - if (bgp->maxpaths[afi][safi].maxpaths_ibgp != MULTIPATH_NUM) - { - bgp_config_write_family_header (vty, afi, safi, write); - vty_out (vty, " maximum-paths ibgp %d", - bgp->maxpaths[afi][safi].maxpaths_ibgp); - if (CHECK_FLAG (bgp->maxpaths[afi][safi].ibgp_flags, - BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN)) - vty_out (vty, " equal-cluster-length"); - vty_out (vty, "\n"); - } + if (bgp->maxpaths[afi][safi].maxpaths_ibgp != MULTIPATH_NUM) { + bgp_config_write_family_header(vty, afi, safi, write); + vty_out(vty, " maximum-paths ibgp %d", + bgp->maxpaths[afi][safi].maxpaths_ibgp); + if (CHECK_FLAG(bgp->maxpaths[afi][safi].ibgp_flags, + BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN)) + vty_out(vty, " equal-cluster-length"); + vty_out(vty, "\n"); + } - return 0; + return 0; } /* BGP timers. */ @@ -1605,25 +1527,25 @@ DEFUN (bgp_timers, "Keepalive interval\n" "Holdtime\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_number = 2; - int idx_number_2 = 3; - unsigned long keepalive = 0; - unsigned long holdtime = 0; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_number = 2; + int idx_number_2 = 3; + unsigned long keepalive = 0; + unsigned long holdtime = 0; - keepalive = strtoul(argv[idx_number]->arg, NULL, 10); - holdtime = strtoul(argv[idx_number_2]->arg, NULL, 10); + keepalive = strtoul(argv[idx_number]->arg, NULL, 10); + holdtime = strtoul(argv[idx_number_2]->arg, NULL, 10); - /* Holdtime value check. */ - if (holdtime < 3 && holdtime != 0) - { - vty_out (vty, "%% hold time value must be either 0 or greater than 3\n"); - return CMD_WARNING_CONFIG_FAILED; - } + /* Holdtime value check. */ + if (holdtime < 3 && holdtime != 0) { + vty_out(vty, + "%% hold time value must be either 0 or greater than 3\n"); + return CMD_WARNING_CONFIG_FAILED; + } - bgp_timers_set (bgp, keepalive, holdtime); + bgp_timers_set(bgp, keepalive, holdtime); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bgp_timers, @@ -1635,10 +1557,10 @@ DEFUN (no_bgp_timers, "Keepalive interval\n" "Holdtime\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_timers_unset (bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_timers_unset(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1649,11 +1571,11 @@ DEFUN (bgp_client_to_client_reflection, "Configure client to client route reflection\n" "reflection of routes allowed\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_unset (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT); - bgp_clear_star_soft_out (vty, bgp->name); + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_unset(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT); + bgp_clear_star_soft_out(vty, bgp->name); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bgp_client_to_client_reflection, @@ -1664,11 +1586,11 @@ DEFUN (no_bgp_client_to_client_reflection, "Configure client to client route reflection\n" "reflection of routes allowed\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_set (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT); - bgp_clear_star_soft_out (vty, bgp->name); + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_set(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT); + bgp_clear_star_soft_out(vty, bgp->name); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* "bgp always-compare-med" configuration. */ @@ -1678,11 +1600,11 @@ DEFUN (bgp_always_compare_med, "BGP specific commands\n" "Allow comparing MED from different neighbors\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_set (bgp, BGP_FLAG_ALWAYS_COMPARE_MED); - bgp_recalculate_all_bestpaths (bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_set(bgp, BGP_FLAG_ALWAYS_COMPARE_MED); + bgp_recalculate_all_bestpaths(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bgp_always_compare_med, @@ -1692,11 +1614,11 @@ DEFUN (no_bgp_always_compare_med, "BGP specific commands\n" "Allow comparing MED from different neighbors\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_unset (bgp, BGP_FLAG_ALWAYS_COMPARE_MED); - bgp_recalculate_all_bestpaths (bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_unset(bgp, BGP_FLAG_ALWAYS_COMPARE_MED); + bgp_recalculate_all_bestpaths(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* "bgp deterministic-med" configuration. */ @@ -1706,15 +1628,14 @@ DEFUN (bgp_deterministic_med, "BGP specific commands\n" "Pick the best-MED path among paths advertised from the neighboring AS\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); - if (!bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) - { - bgp_flag_set (bgp, BGP_FLAG_DETERMINISTIC_MED); - bgp_recalculate_all_bestpaths (bgp); - } + if (!bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) { + bgp_flag_set(bgp, BGP_FLAG_DETERMINISTIC_MED); + bgp_recalculate_all_bestpaths(bgp); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bgp_deterministic_med, @@ -1724,44 +1645,42 @@ DEFUN (no_bgp_deterministic_med, "BGP specific commands\n" "Pick the best-MED path among paths advertised from the neighboring AS\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int bestpath_per_as_used; - afi_t afi; - safi_t safi; - struct peer *peer; - struct listnode *node, *nnode; - - if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) - { - bestpath_per_as_used = 0; - - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) - { - bestpath_per_as_used = 1; - break; - } - - if (bestpath_per_as_used) - break; - } - - if (bestpath_per_as_used) - { - vty_out (vty, "bgp deterministic-med cannot be disabled while addpath-tx-bestpath-per-AS is in use\n"); - return CMD_WARNING_CONFIG_FAILED; - } - else - { - bgp_flag_unset (bgp, BGP_FLAG_DETERMINISTIC_MED); - bgp_recalculate_all_bestpaths (bgp); - } - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int bestpath_per_as_used; + afi_t afi; + safi_t safi; + struct peer *peer; + struct listnode *node, *nnode; + + if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) { + bestpath_per_as_used = 0; + + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; + safi++) + if (CHECK_FLAG( + peer->af_flags[afi][safi], + PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) { + bestpath_per_as_used = 1; + break; + } + + if (bestpath_per_as_used) + break; + } + + if (bestpath_per_as_used) { + vty_out(vty, + "bgp deterministic-med cannot be disabled while addpath-tx-bestpath-per-AS is in use\n"); + return CMD_WARNING_CONFIG_FAILED; + } else { + bgp_flag_unset(bgp, BGP_FLAG_DETERMINISTIC_MED); + bgp_recalculate_all_bestpaths(bgp); + } + } + + return CMD_SUCCESS; } /* "bgp graceful-restart" configuration. */ @@ -1771,9 +1690,9 @@ DEFUN (bgp_graceful_restart, "BGP specific commands\n" "Graceful restart capability parameters\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_set (bgp, BGP_FLAG_GRACEFUL_RESTART); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_set(bgp, BGP_FLAG_GRACEFUL_RESTART); + return CMD_SUCCESS; } DEFUN (no_bgp_graceful_restart, @@ -1783,9 +1702,9 @@ DEFUN (no_bgp_graceful_restart, "BGP specific commands\n" "Graceful restart capability parameters\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_unset (bgp, BGP_FLAG_GRACEFUL_RESTART); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_unset(bgp, BGP_FLAG_GRACEFUL_RESTART); + return CMD_SUCCESS; } DEFUN (bgp_graceful_restart_stalepath_time, @@ -1796,13 +1715,13 @@ DEFUN (bgp_graceful_restart_stalepath_time, "Set the max time to hold onto restarting peer's stale paths\n" "Delay value (seconds)\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_number = 3; - u_int32_t stalepath; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_number = 3; + u_int32_t stalepath; - stalepath = strtoul(argv[idx_number]->arg, NULL, 10); - bgp->stalepath_time = stalepath; - return CMD_SUCCESS; + stalepath = strtoul(argv[idx_number]->arg, NULL, 10); + bgp->stalepath_time = stalepath; + return CMD_SUCCESS; } DEFUN (bgp_graceful_restart_restart_time, @@ -1813,13 +1732,13 @@ DEFUN (bgp_graceful_restart_restart_time, "Set the time to wait to delete stale routes before a BGP open message is received\n" "Delay value (seconds)\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_number = 3; - u_int32_t restart; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_number = 3; + u_int32_t restart; - restart = strtoul(argv[idx_number]->arg, NULL, 10); - bgp->restart_time = restart; - return CMD_SUCCESS; + restart = strtoul(argv[idx_number]->arg, NULL, 10); + bgp->restart_time = restart; + return CMD_SUCCESS; } DEFUN (no_bgp_graceful_restart_stalepath_time, @@ -1831,10 +1750,10 @@ DEFUN (no_bgp_graceful_restart_stalepath_time, "Set the max time to hold onto restarting peer's stale paths\n" "Delay value (seconds)\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME; - return CMD_SUCCESS; + bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME; + return CMD_SUCCESS; } DEFUN (no_bgp_graceful_restart_restart_time, @@ -1846,10 +1765,10 @@ DEFUN (no_bgp_graceful_restart_restart_time, "Set the time to wait to delete stale routes before a BGP open message is received\n" "Delay value (seconds)\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp->restart_time = BGP_DEFAULT_RESTART_TIME; - return CMD_SUCCESS; + bgp->restart_time = BGP_DEFAULT_RESTART_TIME; + return CMD_SUCCESS; } DEFUN (bgp_graceful_restart_preserve_fw, @@ -1859,9 +1778,9 @@ DEFUN (bgp_graceful_restart_preserve_fw, "Graceful restart capability parameters\n" "Sets F-bit indication that fib is preserved while doing Graceful Restart\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_set(bgp, BGP_FLAG_GR_PRESERVE_FWD); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_set(bgp, BGP_FLAG_GR_PRESERVE_FWD); + return CMD_SUCCESS; } DEFUN (no_bgp_graceful_restart_preserve_fw, @@ -1872,9 +1791,9 @@ DEFUN (no_bgp_graceful_restart_preserve_fw, "Graceful restart capability parameters\n" "Unsets F-bit indication that fib is preserved while doing Graceful Restart\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_unset(bgp, BGP_FLAG_GR_PRESERVE_FWD); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_unset(bgp, BGP_FLAG_GR_PRESERVE_FWD); + return CMD_SUCCESS; } /* "bgp fast-external-failover" configuration. */ @@ -1884,9 +1803,9 @@ DEFUN (bgp_fast_external_failover, BGP_STR "Immediately reset session if a link to a directly connected external peer goes down\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_unset (bgp, BGP_FLAG_NO_FAST_EXT_FAILOVER); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_unset(bgp, BGP_FLAG_NO_FAST_EXT_FAILOVER); + return CMD_SUCCESS; } DEFUN (no_bgp_fast_external_failover, @@ -1896,9 +1815,9 @@ DEFUN (no_bgp_fast_external_failover, BGP_STR "Immediately reset session if a link to a directly connected external peer goes down\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_set (bgp, BGP_FLAG_NO_FAST_EXT_FAILOVER); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_set(bgp, BGP_FLAG_NO_FAST_EXT_FAILOVER); + return CMD_SUCCESS; } /* "bgp enforce-first-as" configuration. */ @@ -1908,11 +1827,11 @@ DEFUN (bgp_enforce_first_as, BGP_STR "Enforce the first AS for EBGP routes\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_set (bgp, BGP_FLAG_ENFORCE_FIRST_AS); - bgp_clear_star_soft_in (vty, bgp->name); + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_set(bgp, BGP_FLAG_ENFORCE_FIRST_AS); + bgp_clear_star_soft_in(vty, bgp->name); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bgp_enforce_first_as, @@ -1922,11 +1841,11 @@ DEFUN (no_bgp_enforce_first_as, BGP_STR "Enforce the first AS for EBGP routes\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_unset (bgp, BGP_FLAG_ENFORCE_FIRST_AS); - bgp_clear_star_soft_in (vty, bgp->name); + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_unset(bgp, BGP_FLAG_ENFORCE_FIRST_AS); + bgp_clear_star_soft_in(vty, bgp->name); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* "bgp bestpath compare-routerid" configuration. */ @@ -1937,11 +1856,11 @@ DEFUN (bgp_bestpath_compare_router_id, "Change the default bestpath selection\n" "Compare router-id for identical EBGP paths\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_set (bgp, BGP_FLAG_COMPARE_ROUTER_ID); - bgp_recalculate_all_bestpaths (bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_set(bgp, BGP_FLAG_COMPARE_ROUTER_ID); + bgp_recalculate_all_bestpaths(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bgp_bestpath_compare_router_id, @@ -1952,11 +1871,11 @@ DEFUN (no_bgp_bestpath_compare_router_id, "Change the default bestpath selection\n" "Compare router-id for identical EBGP paths\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_unset (bgp, BGP_FLAG_COMPARE_ROUTER_ID); - bgp_recalculate_all_bestpaths (bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_unset(bgp, BGP_FLAG_COMPARE_ROUTER_ID); + bgp_recalculate_all_bestpaths(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* "bgp bestpath as-path ignore" configuration. */ @@ -1968,11 +1887,11 @@ DEFUN (bgp_bestpath_aspath_ignore, "AS-path attribute\n" "Ignore as-path length in selecting a route\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_set (bgp, BGP_FLAG_ASPATH_IGNORE); - bgp_recalculate_all_bestpaths (bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_set(bgp, BGP_FLAG_ASPATH_IGNORE); + bgp_recalculate_all_bestpaths(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bgp_bestpath_aspath_ignore, @@ -1984,11 +1903,11 @@ DEFUN (no_bgp_bestpath_aspath_ignore, "AS-path attribute\n" "Ignore as-path length in selecting a route\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_unset (bgp, BGP_FLAG_ASPATH_IGNORE); - bgp_recalculate_all_bestpaths (bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_unset(bgp, BGP_FLAG_ASPATH_IGNORE); + bgp_recalculate_all_bestpaths(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* "bgp bestpath as-path confed" configuration. */ @@ -2000,11 +1919,11 @@ DEFUN (bgp_bestpath_aspath_confed, "AS-path attribute\n" "Compare path lengths including confederation sets & sequences in selecting a route\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_set (bgp, BGP_FLAG_ASPATH_CONFED); - bgp_recalculate_all_bestpaths (bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_set(bgp, BGP_FLAG_ASPATH_CONFED); + bgp_recalculate_all_bestpaths(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bgp_bestpath_aspath_confed, @@ -2016,11 +1935,11 @@ DEFUN (no_bgp_bestpath_aspath_confed, "AS-path attribute\n" "Compare path lengths including confederation sets & sequences in selecting a route\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_unset (bgp, BGP_FLAG_ASPATH_CONFED); - bgp_recalculate_all_bestpaths (bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_unset(bgp, BGP_FLAG_ASPATH_CONFED); + bgp_recalculate_all_bestpaths(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* "bgp bestpath as-path multipath-relax" configuration. */ @@ -2034,20 +1953,20 @@ DEFUN (bgp_bestpath_aspath_multipath_relax, "Generate an AS_SET\n" "Do not generate an AS_SET\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx = 0; - bgp_flag_set (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX); + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx = 0; + bgp_flag_set(bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX); - /* no-as-set is now the default behavior so we can silently - * ignore it */ - if (argv_find (argv, argc, "as-set", &idx)) - bgp_flag_set (bgp, BGP_FLAG_MULTIPATH_RELAX_AS_SET); - else - bgp_flag_unset (bgp, BGP_FLAG_MULTIPATH_RELAX_AS_SET) ; + /* no-as-set is now the default behavior so we can silently + * ignore it */ + if (argv_find(argv, argc, "as-set", &idx)) + bgp_flag_set(bgp, BGP_FLAG_MULTIPATH_RELAX_AS_SET); + else + bgp_flag_unset(bgp, BGP_FLAG_MULTIPATH_RELAX_AS_SET); - bgp_recalculate_all_bestpaths (bgp); + bgp_recalculate_all_bestpaths(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bgp_bestpath_aspath_multipath_relax, @@ -2061,12 +1980,12 @@ DEFUN (no_bgp_bestpath_aspath_multipath_relax, "Generate an AS_SET\n" "Do not generate an AS_SET\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_unset (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX); - bgp_flag_unset (bgp, BGP_FLAG_MULTIPATH_RELAX_AS_SET); - bgp_recalculate_all_bestpaths (bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_unset(bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX); + bgp_flag_unset(bgp, BGP_FLAG_MULTIPATH_RELAX_AS_SET); + bgp_recalculate_all_bestpaths(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* "bgp log-neighbor-changes" configuration. */ @@ -2076,9 +1995,9 @@ DEFUN (bgp_log_neighbor_changes, "BGP specific commands\n" "Log neighbor up/down and reset reason\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_set(bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES); + return CMD_SUCCESS; } DEFUN (no_bgp_log_neighbor_changes, @@ -2088,9 +2007,9 @@ DEFUN (no_bgp_log_neighbor_changes, "BGP specific commands\n" "Log neighbor up/down and reset reason\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_unset (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_unset(bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES); + return CMD_SUCCESS; } /* "bgp bestpath med" configuration. */ @@ -2105,18 +2024,18 @@ DEFUN (bgp_bestpath_med, "Treat missing MED as the least preferred one\n" "Compare MED among confederation paths\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx = 0; - if (argv_find (argv, argc, "confed", &idx)) - bgp_flag_set (bgp, BGP_FLAG_MED_CONFED); - idx = 0; - if (argv_find (argv, argc, "missing-as-worst", &idx)) - bgp_flag_set (bgp, BGP_FLAG_MED_MISSING_AS_WORST); + int idx = 0; + if (argv_find(argv, argc, "confed", &idx)) + bgp_flag_set(bgp, BGP_FLAG_MED_CONFED); + idx = 0; + if (argv_find(argv, argc, "missing-as-worst", &idx)) + bgp_flag_set(bgp, BGP_FLAG_MED_MISSING_AS_WORST); - bgp_recalculate_all_bestpaths (bgp); + bgp_recalculate_all_bestpaths(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bgp_bestpath_med, @@ -2131,18 +2050,18 @@ DEFUN (no_bgp_bestpath_med, "Treat missing MED as the least preferred one\n" "Compare MED among confederation paths\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx = 0; - if (argv_find (argv, argc, "confed", &idx)) - bgp_flag_unset (bgp, BGP_FLAG_MED_CONFED); - idx = 0; - if (argv_find (argv, argc, "missing-as-worst", &idx)) - bgp_flag_unset (bgp, BGP_FLAG_MED_MISSING_AS_WORST); + int idx = 0; + if (argv_find(argv, argc, "confed", &idx)) + bgp_flag_unset(bgp, BGP_FLAG_MED_CONFED); + idx = 0; + if (argv_find(argv, argc, "missing-as-worst", &idx)) + bgp_flag_unset(bgp, BGP_FLAG_MED_MISSING_AS_WORST); - bgp_recalculate_all_bestpaths (bgp); + bgp_recalculate_all_bestpaths(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* "no bgp default ipv4-unicast". */ @@ -2154,9 +2073,9 @@ DEFUN (no_bgp_default_ipv4_unicast, "Configure BGP defaults\n" "Activate ipv4-unicast for a peer by default\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_set (bgp, BGP_FLAG_NO_DEFAULT_IPV4); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_set(bgp, BGP_FLAG_NO_DEFAULT_IPV4); + return CMD_SUCCESS; } DEFUN (bgp_default_ipv4_unicast, @@ -2166,9 +2085,9 @@ DEFUN (bgp_default_ipv4_unicast, "Configure BGP defaults\n" "Activate ipv4-unicast for a peer by default\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_unset (bgp, BGP_FLAG_NO_DEFAULT_IPV4); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_unset(bgp, BGP_FLAG_NO_DEFAULT_IPV4); + return CMD_SUCCESS; } /* Display hostname in certain command outputs */ @@ -2179,9 +2098,9 @@ DEFUN (bgp_default_show_hostname, "Configure BGP defaults\n" "Show hostname in certain command ouputs\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_set (bgp, BGP_FLAG_SHOW_HOSTNAME); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_set(bgp, BGP_FLAG_SHOW_HOSTNAME); + return CMD_SUCCESS; } DEFUN (no_bgp_default_show_hostname, @@ -2192,9 +2111,9 @@ DEFUN (no_bgp_default_show_hostname, "Configure BGP defaults\n" "Show hostname in certain command ouputs\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_unset (bgp, BGP_FLAG_SHOW_HOSTNAME); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_unset(bgp, BGP_FLAG_SHOW_HOSTNAME); + return CMD_SUCCESS; } /* "bgp network import-check" configuration. */ @@ -2205,23 +2124,21 @@ DEFUN (bgp_network_import_check, "BGP network command\n" "Check BGP network route exists in IGP\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - if (!bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)) - { - bgp_flag_set (bgp, BGP_FLAG_IMPORT_CHECK); - bgp_static_redo_import_check(bgp); - } + VTY_DECLVAR_CONTEXT(bgp, bgp); + if (!bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)) { + bgp_flag_set(bgp, BGP_FLAG_IMPORT_CHECK); + bgp_static_redo_import_check(bgp); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } -ALIAS_HIDDEN (bgp_network_import_check, - bgp_network_import_check_exact_cmd, - "bgp network import-check exact", - "BGP specific commands\n" - "BGP network command\n" - "Check BGP network route exists in IGP\n" - "Match route precisely\n") +ALIAS_HIDDEN(bgp_network_import_check, bgp_network_import_check_exact_cmd, + "bgp network import-check exact", + "BGP specific commands\n" + "BGP network command\n" + "Check BGP network route exists in IGP\n" + "Match route precisely\n") DEFUN (no_bgp_network_import_check, no_bgp_network_import_check_cmd, @@ -2231,14 +2148,13 @@ DEFUN (no_bgp_network_import_check, "BGP network command\n" "Check BGP network route exists in IGP\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)) - { - bgp_flag_unset (bgp, BGP_FLAG_IMPORT_CHECK); - bgp_static_redo_import_check(bgp); - } + VTY_DECLVAR_CONTEXT(bgp, bgp); + if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)) { + bgp_flag_unset(bgp, BGP_FLAG_IMPORT_CHECK); + bgp_static_redo_import_check(bgp); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (bgp_default_local_preference, @@ -2249,16 +2165,16 @@ DEFUN (bgp_default_local_preference, "local preference (higher=more preferred)\n" "Configure default local preference value\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_number = 3; - u_int32_t local_pref; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_number = 3; + u_int32_t local_pref; - local_pref = strtoul(argv[idx_number]->arg, NULL, 10); + local_pref = strtoul(argv[idx_number]->arg, NULL, 10); - bgp_default_local_preference_set (bgp, local_pref); - bgp_clear_star_soft_in (vty, bgp->name); + bgp_default_local_preference_set(bgp, local_pref); + bgp_clear_star_soft_in(vty, bgp->name); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bgp_default_local_preference, @@ -2270,11 +2186,11 @@ DEFUN (no_bgp_default_local_preference, "local preference (higher=more preferred)\n" "Configure default local preference value\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_default_local_preference_unset (bgp); - bgp_clear_star_soft_in (vty, bgp->name); + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_default_local_preference_unset(bgp); + bgp_clear_star_soft_in(vty, bgp->name); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -2286,15 +2202,15 @@ DEFUN (bgp_default_subgroup_pkt_queue_max, "subgroup-pkt-queue-max\n" "Configure subgroup packet queue max\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_number = 3; - u_int32_t max_size; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_number = 3; + u_int32_t max_size; - max_size = strtoul(argv[idx_number]->arg, NULL, 10); + max_size = strtoul(argv[idx_number]->arg, NULL, 10); - bgp_default_subgroup_pkt_queue_max_set (bgp, max_size); + bgp_default_subgroup_pkt_queue_max_set(bgp, max_size); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bgp_default_subgroup_pkt_queue_max, @@ -2306,9 +2222,9 @@ DEFUN (no_bgp_default_subgroup_pkt_queue_max, "subgroup-pkt-queue-max\n" "Configure subgroup packet queue max\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_default_subgroup_pkt_queue_max_unset (bgp); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_default_subgroup_pkt_queue_max_unset(bgp); + return CMD_SUCCESS; } @@ -2319,16 +2235,15 @@ DEFUN (bgp_rr_allow_outbound_policy, "Allow modifications made by out route-map\n" "on ibgp neighbors\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); - if (!bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) - { - bgp_flag_set(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY); - update_group_announce_rrclients(bgp); - bgp_clear_star_soft_out (vty, bgp->name); - } + if (!bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) { + bgp_flag_set(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY); + update_group_announce_rrclients(bgp); + bgp_clear_star_soft_out(vty, bgp->name); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bgp_rr_allow_outbound_policy, @@ -2339,16 +2254,15 @@ DEFUN (no_bgp_rr_allow_outbound_policy, "Allow modifications made by out route-map\n" "on ibgp neighbors\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); - if (bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) - { - bgp_flag_unset(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY); - update_group_announce_rrclients(bgp); - bgp_clear_star_soft_out (vty, bgp->name); - } + if (bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) { + bgp_flag_unset(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY); + update_group_announce_rrclients(bgp); + bgp_clear_star_soft_out(vty, bgp->name); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (bgp_listen_limit, @@ -2359,15 +2273,15 @@ DEFUN (bgp_listen_limit, "maximum number of BGP Dynamic Neighbors that can be created\n" "Configure Dynamic Neighbors listen limit value\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_number = 3; - int listen_limit; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_number = 3; + int listen_limit; - listen_limit = strtoul(argv[idx_number]->arg, NULL, 10); + listen_limit = strtoul(argv[idx_number]->arg, NULL, 10); - bgp_listen_limit_set (bgp, listen_limit); + bgp_listen_limit_set(bgp, listen_limit); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bgp_listen_limit, @@ -2379,9 +2293,9 @@ DEFUN (no_bgp_listen_limit, "Configure Dynamic Neighbors listen limit value to default\n" "Configure Dynamic Neighbors listen limit value\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_listen_limit_unset (bgp); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_listen_limit_unset(bgp); + return CMD_SUCCESS; } @@ -2389,32 +2303,31 @@ DEFUN (no_bgp_listen_limit, * Check if this listen range is already configured. Check for exact * match or overlap based on input. */ -static struct peer_group * -listen_range_exists (struct bgp *bgp, struct prefix *range, int exact) -{ - struct listnode *node, *nnode; - struct listnode *node1, *nnode1; - struct peer_group *group; - struct prefix *lr; - afi_t afi; - int match; - - afi = family2afi(range->family); - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - { - for (ALL_LIST_ELEMENTS (group->listen_range[afi], node1, - nnode1, lr)) - { - if (exact) - match = prefix_same (range, lr); - else - match = (prefix_match (range, lr) || prefix_match (lr, range)); - if (match) - return group; - } - } - - return NULL; +static struct peer_group *listen_range_exists(struct bgp *bgp, + struct prefix *range, int exact) +{ + struct listnode *node, *nnode; + struct listnode *node1, *nnode1; + struct peer_group *group; + struct prefix *lr; + afi_t afi; + int match; + + afi = family2afi(range->family); + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) { + for (ALL_LIST_ELEMENTS(group->listen_range[afi], node1, nnode1, + lr)) { + if (exact) + match = prefix_same(range, lr); + else + match = (prefix_match(range, lr) + || prefix_match(lr, range)); + if (match) + return group; + } + } + + return NULL; } DEFUN (bgp_listen_range, @@ -2427,67 +2340,64 @@ DEFUN (bgp_listen_range, "Member of the peer-group\n" "Peer-group name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - struct prefix range; - struct peer_group *group, *existing_group; - afi_t afi; - int ret; - int idx = 0; - - argv_find (argv, argc, "A.B.C.D/M", &idx); - argv_find (argv, argc, "X:X::X:X/M", &idx); - char *prefix = argv[idx]->arg; - argv_find (argv, argc, "WORD", &idx); - char *peergroup = argv[idx]->arg; - - /* Convert IP prefix string to struct prefix. */ - ret = str2prefix (prefix, &range); - if (! ret) - { - vty_out (vty, "%% Malformed listen range\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - afi = family2afi(range.family); - - if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&range.u.prefix6)) - { - vty_out (vty, "%% Malformed listen range (link-local address)\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - apply_mask (&range); - - /* Check if same listen range is already configured. */ - existing_group = listen_range_exists (bgp, &range, 1); - if (existing_group) - { - if (strcmp (existing_group->name, peergroup) == 0) - return CMD_SUCCESS; - else - { - vty_out (vty, "%% Same listen range is attached to peer-group %s\n", - existing_group->name); - return CMD_WARNING_CONFIG_FAILED; - } - } - - /* Check if an overlapping listen range exists. */ - if (listen_range_exists (bgp, &range, 0)) - { - vty_out (vty, "%% Listen range overlaps with existing listen range\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - group = peer_group_lookup (bgp, peergroup); - if (! group) - { - vty_out (vty, "%% Configure the peer-group first\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ret = peer_group_listen_range_add(group, &range); - return bgp_vty_return (vty, ret); + VTY_DECLVAR_CONTEXT(bgp, bgp); + struct prefix range; + struct peer_group *group, *existing_group; + afi_t afi; + int ret; + int idx = 0; + + argv_find(argv, argc, "A.B.C.D/M", &idx); + argv_find(argv, argc, "X:X::X:X/M", &idx); + char *prefix = argv[idx]->arg; + argv_find(argv, argc, "WORD", &idx); + char *peergroup = argv[idx]->arg; + + /* Convert IP prefix string to struct prefix. */ + ret = str2prefix(prefix, &range); + if (!ret) { + vty_out(vty, "%% Malformed listen range\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + afi = family2afi(range.family); + + if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&range.u.prefix6)) { + vty_out(vty, + "%% Malformed listen range (link-local address)\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + apply_mask(&range); + + /* Check if same listen range is already configured. */ + existing_group = listen_range_exists(bgp, &range, 1); + if (existing_group) { + if (strcmp(existing_group->name, peergroup) == 0) + return CMD_SUCCESS; + else { + vty_out(vty, + "%% Same listen range is attached to peer-group %s\n", + existing_group->name); + return CMD_WARNING_CONFIG_FAILED; + } + } + + /* Check if an overlapping listen range exists. */ + if (listen_range_exists(bgp, &range, 0)) { + vty_out(vty, + "%% Listen range overlaps with existing listen range\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + group = peer_group_lookup(bgp, peergroup); + if (!group) { + vty_out(vty, "%% Configure the peer-group first\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = peer_group_listen_range_add(group, &range); + return bgp_vty_return(vty, ret); } DEFUN (no_bgp_listen_range, @@ -2501,75 +2411,71 @@ DEFUN (no_bgp_listen_range, "Member of the peer-group\n" "Peer-group name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - struct prefix range; - struct peer_group *group; - afi_t afi; - int ret; - int idx = 0; - - argv_find (argv, argc, "A.B.C.D/M", &idx); - argv_find (argv, argc, "X:X::X:X/M", &idx); - char *prefix = argv[idx]->arg; - argv_find (argv, argc, "WORD", &idx); - char *peergroup = argv[idx]->arg; - - /* Convert IP prefix string to struct prefix. */ - ret = str2prefix (prefix, &range); - if (! ret) - { - vty_out (vty, "%% Malformed listen range\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - afi = family2afi(range.family); - - if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&range.u.prefix6)) - { - vty_out (vty, "%% Malformed listen range (link-local address)\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - apply_mask (&range); - - group = peer_group_lookup (bgp, peergroup); - if (! group) - { - vty_out (vty, "%% Peer-group does not exist\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ret = peer_group_listen_range_del(group, &range); - return bgp_vty_return (vty, ret); -} - -int -bgp_config_write_listen (struct vty *vty, struct bgp *bgp) -{ - struct peer_group *group; - struct listnode *node, *nnode, *rnode, *nrnode; - struct prefix *range; - afi_t afi; - char buf[PREFIX2STR_BUFFER]; - - if (bgp->dynamic_neighbors_limit != BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT) - vty_out (vty, " bgp listen limit %d\n", - bgp->dynamic_neighbors_limit); - - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - for (ALL_LIST_ELEMENTS (group->listen_range[afi], rnode, nrnode, range)) - { - prefix2str(range, buf, sizeof(buf)); - vty_out(vty, " bgp listen range %s peer-group %s\n", - buf, group->name); - } - } - } - - return 0; + VTY_DECLVAR_CONTEXT(bgp, bgp); + struct prefix range; + struct peer_group *group; + afi_t afi; + int ret; + int idx = 0; + + argv_find(argv, argc, "A.B.C.D/M", &idx); + argv_find(argv, argc, "X:X::X:X/M", &idx); + char *prefix = argv[idx]->arg; + argv_find(argv, argc, "WORD", &idx); + char *peergroup = argv[idx]->arg; + + /* Convert IP prefix string to struct prefix. */ + ret = str2prefix(prefix, &range); + if (!ret) { + vty_out(vty, "%% Malformed listen range\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + afi = family2afi(range.family); + + if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&range.u.prefix6)) { + vty_out(vty, + "%% Malformed listen range (link-local address)\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + apply_mask(&range); + + group = peer_group_lookup(bgp, peergroup); + if (!group) { + vty_out(vty, "%% Peer-group does not exist\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = peer_group_listen_range_del(group, &range); + return bgp_vty_return(vty, ret); +} + +int bgp_config_write_listen(struct vty *vty, struct bgp *bgp) +{ + struct peer_group *group; + struct listnode *node, *nnode, *rnode, *nrnode; + struct prefix *range; + afi_t afi; + char buf[PREFIX2STR_BUFFER]; + + if (bgp->dynamic_neighbors_limit != BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT) + vty_out(vty, " bgp listen limit %d\n", + bgp->dynamic_neighbors_limit); + + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) { + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + for (ALL_LIST_ELEMENTS(group->listen_range[afi], rnode, + nrnode, range)) { + prefix2str(range, buf, sizeof(buf)); + vty_out(vty, + " bgp listen range %s peer-group %s\n", + buf, group->name); + } + } + } + + return 0; } @@ -2579,11 +2485,11 @@ DEFUN (bgp_disable_connected_route_check, "BGP specific commands\n" "Disable checking if nexthop is connected on ebgp sessions\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_set (bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK); - bgp_clear_star_soft_in (vty, bgp->name); + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_set(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK); + bgp_clear_star_soft_in(vty, bgp->name); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bgp_disable_connected_route_check, @@ -2593,78 +2499,72 @@ DEFUN (no_bgp_disable_connected_route_check, "BGP specific commands\n" "Disable checking if nexthop is connected on ebgp sessions\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_flag_unset (bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK); - bgp_clear_star_soft_in (vty, bgp->name); - - return CMD_SUCCESS; -} - - -static int -peer_remote_as_vty (struct vty *vty, const char *peer_str, - const char *as_str, afi_t afi, safi_t safi) -{ - VTY_DECLVAR_CONTEXT(bgp, bgp); - int ret; - as_t as; - int as_type = AS_SPECIFIED; - union sockunion su; - - if (as_str[0] == 'i') - { - as = 0; - as_type = AS_INTERNAL; - } - else if (as_str[0] == 'e') - { - as = 0; - as_type = AS_EXTERNAL; - } - else - { - /* Get AS number. */ - as = strtoul(as_str, NULL, 10); - } - - /* If peer is peer group, call proper function. */ - ret = str2sockunion (peer_str, &su); - if (ret < 0) - { - /* Check for peer by interface */ - ret = peer_remote_as (bgp, NULL, peer_str, &as, as_type, afi, safi); - if (ret < 0) - { - ret = peer_group_remote_as (bgp, peer_str, &as, as_type); - if (ret < 0) - { - vty_out (vty, "%% Create the peer-group or interface first\n"); - return CMD_WARNING_CONFIG_FAILED; - } - return CMD_SUCCESS; - } - } - else - { - if (peer_address_self_check (bgp, &su)) - { - vty_out (vty, "%% Can not configure the local system as neighbor\n"); - return CMD_WARNING_CONFIG_FAILED; - } - ret = peer_remote_as (bgp, &su, NULL, &as, as_type, afi, safi); - } - - /* This peer belongs to peer group. */ - switch (ret) - { - case BGP_ERR_PEER_GROUP_MEMBER: - vty_out (vty, "%% Peer-group AS %u. Cannot configure remote-as for member\n", as); - return CMD_WARNING_CONFIG_FAILED; - case BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT: - vty_out (vty, "%% The AS# can not be changed from %u to %s, peer-group members must be all internal or all external\n", as, as_str); - return CMD_WARNING_CONFIG_FAILED; - } - return bgp_vty_return (vty, ret); + VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp_flag_unset(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK); + bgp_clear_star_soft_in(vty, bgp->name); + + return CMD_SUCCESS; +} + + +static int peer_remote_as_vty(struct vty *vty, const char *peer_str, + const char *as_str, afi_t afi, safi_t safi) +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + int ret; + as_t as; + int as_type = AS_SPECIFIED; + union sockunion su; + + if (as_str[0] == 'i') { + as = 0; + as_type = AS_INTERNAL; + } else if (as_str[0] == 'e') { + as = 0; + as_type = AS_EXTERNAL; + } else { + /* Get AS number. */ + as = strtoul(as_str, NULL, 10); + } + + /* If peer is peer group, call proper function. */ + ret = str2sockunion(peer_str, &su); + if (ret < 0) { + /* Check for peer by interface */ + ret = peer_remote_as(bgp, NULL, peer_str, &as, as_type, afi, + safi); + if (ret < 0) { + ret = peer_group_remote_as(bgp, peer_str, &as, as_type); + if (ret < 0) { + vty_out(vty, + "%% Create the peer-group or interface first\n"); + return CMD_WARNING_CONFIG_FAILED; + } + return CMD_SUCCESS; + } + } else { + if (peer_address_self_check(bgp, &su)) { + vty_out(vty, + "%% Can not configure the local system as neighbor\n"); + return CMD_WARNING_CONFIG_FAILED; + } + ret = peer_remote_as(bgp, &su, NULL, &as, as_type, afi, safi); + } + + /* This peer belongs to peer group. */ + switch (ret) { + case BGP_ERR_PEER_GROUP_MEMBER: + vty_out(vty, + "%% Peer-group AS %u. Cannot configure remote-as for member\n", + as); + return CMD_WARNING_CONFIG_FAILED; + case BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT: + vty_out(vty, + "%% The AS# can not be changed from %u to %s, peer-group members must be all internal or all external\n", + as, as_str); + return CMD_WARNING_CONFIG_FAILED; + } + return bgp_vty_return(vty, ret); } DEFUN (neighbor_remote_as, @@ -2677,119 +2577,109 @@ DEFUN (neighbor_remote_as, "Internal BGP peer\n" "External BGP peer\n") { - int idx_peer = 1; - int idx_remote_as = 3; - return peer_remote_as_vty (vty, argv[idx_peer]->arg, argv[idx_remote_as]->arg, AFI_IP, SAFI_UNICAST); -} - -static int -peer_conf_interface_get (struct vty *vty, const char *conf_if, afi_t afi, - safi_t safi, int v6only, const char *peer_group_name, - const char *as_str) -{ - VTY_DECLVAR_CONTEXT(bgp, bgp); - as_t as = 0; - int as_type = AS_UNSPECIFIED; - struct peer *peer; - struct peer_group *group; - int ret = 0; - union sockunion su; - - group = peer_group_lookup (bgp, conf_if); - - if (group) - { - vty_out (vty, "%% Name conflict with peer-group \n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (as_str) - { - if (as_str[0] == 'i') - { - as_type = AS_INTERNAL; - } - else if (as_str[0] == 'e') - { - as_type = AS_EXTERNAL; - } - else - { - /* Get AS number. */ - as = strtoul(as_str, NULL, 10); - as_type = AS_SPECIFIED; - } - } - - peer = peer_lookup_by_conf_if (bgp, conf_if); - if (peer) - { - if (as_str) - ret = peer_remote_as (bgp, &su, conf_if, &as, as_type, afi, safi); - } - else - { - if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4) - && afi == AFI_IP && safi == SAFI_UNICAST) - peer = peer_create (NULL, conf_if, bgp, bgp->as, as, as_type, 0, 0, - NULL); - else - peer = peer_create (NULL, conf_if, bgp, bgp->as, as, as_type, afi, safi, - NULL); - - if (!peer) - { - vty_out (vty, "%% BGP failed to create peer\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (v6only) - SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); - - /* Request zebra to initiate IPv6 RAs on this interface. We do this - * any unnumbered peer in order to not worry about run-time transitions - * (e.g., peering is initially IPv4, but the IPv4 /30 or /31 address - * gets deleted later etc.) - */ - if (peer->ifp) - bgp_zebra_initiate_radv (bgp, peer); - } - - if ((v6only && !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) || - (!v6only && CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))) - { - if (v6only) - SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); - else - UNSET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); - - /* v6only flag changed. Reset bgp seesion */ - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_V6ONLY_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - } - - if (!CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE)) - peer_flag_set (peer, PEER_FLAG_CAPABILITY_ENHE); - - if (peer_group_name) - { - group = peer_group_lookup (bgp, peer_group_name); - if (! group) - { - vty_out (vty, "%% Configure the peer-group first\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ret = peer_group_bind (bgp, &su, peer, group, &as); - } - - return bgp_vty_return (vty, ret); + int idx_peer = 1; + int idx_remote_as = 3; + return peer_remote_as_vty(vty, argv[idx_peer]->arg, + argv[idx_remote_as]->arg, AFI_IP, + SAFI_UNICAST); +} + +static int peer_conf_interface_get(struct vty *vty, const char *conf_if, + afi_t afi, safi_t safi, int v6only, + const char *peer_group_name, + const char *as_str) +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + as_t as = 0; + int as_type = AS_UNSPECIFIED; + struct peer *peer; + struct peer_group *group; + int ret = 0; + union sockunion su; + + group = peer_group_lookup(bgp, conf_if); + + if (group) { + vty_out(vty, "%% Name conflict with peer-group \n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (as_str) { + if (as_str[0] == 'i') { + as_type = AS_INTERNAL; + } else if (as_str[0] == 'e') { + as_type = AS_EXTERNAL; + } else { + /* Get AS number. */ + as = strtoul(as_str, NULL, 10); + as_type = AS_SPECIFIED; + } + } + + peer = peer_lookup_by_conf_if(bgp, conf_if); + if (peer) { + if (as_str) + ret = peer_remote_as(bgp, &su, conf_if, &as, as_type, + afi, safi); + } else { + if (bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4) + && afi == AFI_IP && safi == SAFI_UNICAST) + peer = peer_create(NULL, conf_if, bgp, bgp->as, as, + as_type, 0, 0, NULL); + else + peer = peer_create(NULL, conf_if, bgp, bgp->as, as, + as_type, afi, safi, NULL); + + if (!peer) { + vty_out(vty, "%% BGP failed to create peer\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (v6only) + SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); + + /* Request zebra to initiate IPv6 RAs on this interface. We do + * this + * any unnumbered peer in order to not worry about run-time + * transitions + * (e.g., peering is initially IPv4, but the IPv4 /30 or /31 + * address + * gets deleted later etc.) + */ + if (peer->ifp) + bgp_zebra_initiate_radv(bgp, peer); + } + + if ((v6only && !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) + || (!v6only && CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))) { + if (v6only) + SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); + else + UNSET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); + + /* v6only flag changed. Reset bgp seesion */ + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_V6ONLY_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); + } + + if (!CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)) + peer_flag_set(peer, PEER_FLAG_CAPABILITY_ENHE); + + if (peer_group_name) { + group = peer_group_lookup(bgp, peer_group_name); + if (!group) { + vty_out(vty, "%% Configure the peer-group first\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = peer_group_bind(bgp, &su, peer, group, &as); + } + + return bgp_vty_return(vty, ret); } DEFUN (neighbor_interface_config, @@ -2801,15 +2691,16 @@ DEFUN (neighbor_interface_config, "Member of the peer-group\n" "Peer-group name\n") { - int idx_word = 1; - int idx_peer_group_word = 4; + int idx_word = 1; + int idx_peer_group_word = 4; - if (argc > idx_peer_group_word) - return peer_conf_interface_get (vty, argv[idx_word]->arg, AFI_IP, SAFI_UNICAST, 0, - argv[idx_peer_group_word]->arg, NULL); - else - return peer_conf_interface_get (vty, argv[idx_word]->arg, AFI_IP, SAFI_UNICAST, 0, - NULL, NULL); + if (argc > idx_peer_group_word) + return peer_conf_interface_get( + vty, argv[idx_word]->arg, AFI_IP, SAFI_UNICAST, 0, + argv[idx_peer_group_word]->arg, NULL); + else + return peer_conf_interface_get(vty, argv[idx_word]->arg, AFI_IP, + SAFI_UNICAST, 0, NULL, NULL); } DEFUN (neighbor_interface_config_v6only, @@ -2822,15 +2713,16 @@ DEFUN (neighbor_interface_config_v6only, "Member of the peer-group\n" "Peer-group name\n") { - int idx_word = 1; - int idx_peer_group_word = 5; + int idx_word = 1; + int idx_peer_group_word = 5; - if (argc > idx_peer_group_word) - return peer_conf_interface_get (vty, argv[idx_word]->arg, AFI_IP, SAFI_UNICAST, 1, - argv[idx_peer_group_word]->arg, NULL); + if (argc > idx_peer_group_word) + return peer_conf_interface_get( + vty, argv[idx_word]->arg, AFI_IP, SAFI_UNICAST, 1, + argv[idx_peer_group_word]->arg, NULL); - return peer_conf_interface_get (vty, argv[idx_word]->arg, AFI_IP, SAFI_UNICAST, 1, - NULL, NULL); + return peer_conf_interface_get(vty, argv[idx_word]->arg, AFI_IP, + SAFI_UNICAST, 1, NULL, NULL); } @@ -2845,10 +2737,11 @@ DEFUN (neighbor_interface_config_remote_as, "Internal BGP peer\n" "External BGP peer\n") { - int idx_word = 1; - int idx_remote_as = 4; - return peer_conf_interface_get (vty, argv[idx_word]->arg, AFI_IP, SAFI_UNICAST, 0, - NULL, argv[idx_remote_as]->arg); + int idx_word = 1; + int idx_remote_as = 4; + return peer_conf_interface_get(vty, argv[idx_word]->arg, AFI_IP, + SAFI_UNICAST, 0, NULL, + argv[idx_remote_as]->arg); } DEFUN (neighbor_interface_v6only_config_remote_as, @@ -2863,10 +2756,11 @@ DEFUN (neighbor_interface_v6only_config_remote_as, "Internal BGP peer\n" "External BGP peer\n") { - int idx_word = 1; - int idx_remote_as = 5; - return peer_conf_interface_get (vty, argv[idx_word]->arg, AFI_IP, SAFI_UNICAST, 1, - NULL, argv[idx_remote_as]->arg); + int idx_word = 1; + int idx_remote_as = 5; + return peer_conf_interface_get(vty, argv[idx_word]->arg, AFI_IP, + SAFI_UNICAST, 1, NULL, + argv[idx_remote_as]->arg); } DEFUN (neighbor_peer_group, @@ -2876,26 +2770,24 @@ DEFUN (neighbor_peer_group, "Interface name or neighbor tag\n" "Configure peer-group\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_word = 1; - struct peer *peer; - struct peer_group *group; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_word = 1; + struct peer *peer; + struct peer_group *group; - peer = peer_lookup_by_conf_if (bgp, argv[idx_word]->arg); - if (peer) - { - vty_out (vty, "%% Name conflict with interface: \n"); - return CMD_WARNING_CONFIG_FAILED; - } + peer = peer_lookup_by_conf_if(bgp, argv[idx_word]->arg); + if (peer) { + vty_out(vty, "%% Name conflict with interface: \n"); + return CMD_WARNING_CONFIG_FAILED; + } - group = peer_group_get (bgp, argv[idx_word]->arg); - if (! group) - { - vty_out (vty, "%% BGP failed to find or create peer-group\n"); - return CMD_WARNING_CONFIG_FAILED; - } + group = peer_group_get(bgp, argv[idx_word]->arg); + if (!group) { + vty_out(vty, "%% BGP failed to find or create peer-group\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_neighbor, @@ -2909,56 +2801,51 @@ DEFUN (no_neighbor, "Internal BGP peer\n" "External BGP peer\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_peer = 2; - int ret; - union sockunion su; - struct peer_group *group; - struct peer *peer; - struct peer *other; - - ret = str2sockunion (argv[idx_peer]->arg, &su); - if (ret < 0) - { - /* look up for neighbor by interface name config. */ - peer = peer_lookup_by_conf_if (bgp, argv[idx_peer]->arg); - if (peer) - { - /* Request zebra to terminate IPv6 RAs on this interface. */ - if (peer->ifp) - bgp_zebra_terminate_radv (peer->bgp, peer); - peer_delete (peer); - return CMD_SUCCESS; - } - - group = peer_group_lookup (bgp, argv[idx_peer]->arg); - if (group) - peer_group_delete (group); - else - { - vty_out (vty, "%% Create the peer-group first\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - else - { - peer = peer_lookup (bgp, &su); - if (peer) - { - if (peer_dynamic_neighbor (peer)) - { - vty_out (vty, "%% Operation not allowed on a dynamic neighbor\n"); - return CMD_WARNING_CONFIG_FAILED; - } + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_peer = 2; + int ret; + union sockunion su; + struct peer_group *group; + struct peer *peer; + struct peer *other; + + ret = str2sockunion(argv[idx_peer]->arg, &su); + if (ret < 0) { + /* look up for neighbor by interface name config. */ + peer = peer_lookup_by_conf_if(bgp, argv[idx_peer]->arg); + if (peer) { + /* Request zebra to terminate IPv6 RAs on this + * interface. */ + if (peer->ifp) + bgp_zebra_terminate_radv(peer->bgp, peer); + peer_delete(peer); + return CMD_SUCCESS; + } - other = peer->doppelganger; - peer_delete (peer); - if (other && other->status != Deleted) - peer_delete(other); + group = peer_group_lookup(bgp, argv[idx_peer]->arg); + if (group) + peer_group_delete(group); + else { + vty_out(vty, "%% Create the peer-group first\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } else { + peer = peer_lookup(bgp, &su); + if (peer) { + if (peer_dynamic_neighbor(peer)) { + vty_out(vty, + "%% Operation not allowed on a dynamic neighbor\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + other = peer->doppelganger; + peer_delete(peer); + if (other && other->status != Deleted) + peer_delete(other); + } } - } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_neighbor_interface_config, @@ -2976,25 +2863,22 @@ DEFUN (no_neighbor_interface_config, "Internal BGP peer\n" "External BGP peer\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_word = 2; - struct peer *peer; - - /* look up for neighbor by interface name config. */ - peer = peer_lookup_by_conf_if (bgp, argv[idx_word]->arg); - if (peer) - { - /* Request zebra to terminate IPv6 RAs on this interface. */ - if (peer->ifp) - bgp_zebra_terminate_radv (peer->bgp, peer); - peer_delete (peer); - } - else - { - vty_out (vty, "%% Create the bgp interface first\n"); - return CMD_WARNING_CONFIG_FAILED; - } - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_word = 2; + struct peer *peer; + + /* look up for neighbor by interface name config. */ + peer = peer_lookup_by_conf_if(bgp, argv[idx_word]->arg); + if (peer) { + /* Request zebra to terminate IPv6 RAs on this interface. */ + if (peer->ifp) + bgp_zebra_terminate_radv(peer->bgp, peer); + peer_delete(peer); + } else { + vty_out(vty, "%% Create the bgp interface first\n"); + return CMD_WARNING_CONFIG_FAILED; + } + return CMD_SUCCESS; } DEFUN (no_neighbor_peer_group, @@ -3005,19 +2889,18 @@ DEFUN (no_neighbor_peer_group, "Neighbor tag\n" "Configure peer-group\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_word = 2; - struct peer_group *group; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_word = 2; + struct peer_group *group; - group = peer_group_lookup (bgp, argv[idx_word]->arg); - if (group) - peer_group_delete (group); - else - { - vty_out (vty, "%% Create the peer-group first\n"); - return CMD_WARNING_CONFIG_FAILED; - } - return CMD_SUCCESS; + group = peer_group_lookup(bgp, argv[idx_word]->arg); + if (group) + peer_group_delete(group); + else { + vty_out(vty, "%% Create the peer-group first\n"); + return CMD_WARNING_CONFIG_FAILED; + } + return CMD_SUCCESS; } DEFUN (no_neighbor_interface_peer_group_remote_as, @@ -3031,28 +2914,26 @@ DEFUN (no_neighbor_interface_peer_group_remote_as, "Internal BGP peer\n" "External BGP peer\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_word = 2; - struct peer_group *group; - struct peer *peer; - - /* look up for neighbor by interface name config. */ - peer = peer_lookup_by_conf_if (bgp, argv[idx_word]->arg); - if (peer) - { - peer_as_change (peer, 0, AS_SPECIFIED); - return CMD_SUCCESS; - } - - group = peer_group_lookup (bgp, argv[idx_word]->arg); - if (group) - peer_group_remote_as_delete (group); - else - { - vty_out (vty, "%% Create the peer-group or interface first\n"); - return CMD_WARNING_CONFIG_FAILED; - } - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_word = 2; + struct peer_group *group; + struct peer *peer; + + /* look up for neighbor by interface name config. */ + peer = peer_lookup_by_conf_if(bgp, argv[idx_word]->arg); + if (peer) { + peer_as_change(peer, 0, AS_SPECIFIED); + return CMD_SUCCESS; + } + + group = peer_group_lookup(bgp, argv[idx_word]->arg); + if (group) + peer_group_remote_as_delete(group); + else { + vty_out(vty, "%% Create the peer-group or interface first\n"); + return CMD_WARNING_CONFIG_FAILED; + } + return CMD_SUCCESS; } DEFUN (neighbor_local_as, @@ -3063,19 +2944,19 @@ DEFUN (neighbor_local_as, "Specify a local-as number\n" "AS number used as local AS\n") { - int idx_peer = 1; - int idx_number = 3; - struct peer *peer; - int ret; - as_t as; + int idx_peer = 1; + int idx_number = 3; + struct peer *peer; + int ret; + as_t as; - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - as = strtoul(argv[idx_number]->arg, NULL, 10); - ret = peer_local_as_set (peer, as, 0, 0); - return bgp_vty_return (vty, ret); + as = strtoul(argv[idx_number]->arg, NULL, 10); + ret = peer_local_as_set(peer, as, 0, 0); + return bgp_vty_return(vty, ret); } DEFUN (neighbor_local_as_no_prepend, @@ -3087,19 +2968,19 @@ DEFUN (neighbor_local_as_no_prepend, "AS number used as local AS\n" "Do not prepend local-as to updates from ebgp peers\n") { - int idx_peer = 1; - int idx_number = 3; - struct peer *peer; - int ret; - as_t as; + int idx_peer = 1; + int idx_number = 3; + struct peer *peer; + int ret; + as_t as; - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - as = strtoul(argv[idx_number]->arg, NULL, 10); - ret = peer_local_as_set (peer, as, 1, 0); - return bgp_vty_return (vty, ret); + as = strtoul(argv[idx_number]->arg, NULL, 10); + ret = peer_local_as_set(peer, as, 1, 0); + return bgp_vty_return(vty, ret); } DEFUN (neighbor_local_as_no_prepend_replace_as, @@ -3112,19 +2993,19 @@ DEFUN (neighbor_local_as_no_prepend_replace_as, "Do not prepend local-as to updates from ebgp peers\n" "Do not prepend local-as to updates from ibgp peers\n") { - int idx_peer = 1; - int idx_number = 3; - struct peer *peer; - int ret; - as_t as; + int idx_peer = 1; + int idx_number = 3; + struct peer *peer; + int ret; + as_t as; - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - as = strtoul(argv[idx_number]->arg, NULL, 10); - ret = peer_local_as_set (peer, as, 1, 1); - return bgp_vty_return (vty, ret); + as = strtoul(argv[idx_number]->arg, NULL, 10); + ret = peer_local_as_set(peer, as, 1, 1); + return bgp_vty_return(vty, ret); } DEFUN (no_neighbor_local_as, @@ -3138,21 +3019,19 @@ DEFUN (no_neighbor_local_as, "Do not prepend local-as to updates from ebgp peers\n" "Do not prepend local-as to updates from ibgp peers\n") { - int idx_peer = 2; - struct peer *peer; - int ret; + int idx_peer = 2; + struct peer *peer; + int ret; - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - ret = peer_local_as_unset (peer); - return bgp_vty_return (vty, ret); + ret = peer_local_as_unset(peer); + return bgp_vty_return(vty, ret); } - - DEFUN (neighbor_solo, neighbor_solo_cmd, "neighbor solo", @@ -3160,16 +3039,16 @@ DEFUN (neighbor_solo, NEIGHBOR_ADDR_STR2 "Solo peer - part of its own update group\n") { - int idx_peer = 1; - struct peer *peer; - int ret; + int idx_peer = 1; + struct peer *peer; + int ret; - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - ret = update_group_adjust_soloness(peer, 1); - return bgp_vty_return (vty, ret); + ret = update_group_adjust_soloness(peer, 1); + return bgp_vty_return(vty, ret); } DEFUN (no_neighbor_solo, @@ -3180,16 +3059,16 @@ DEFUN (no_neighbor_solo, NEIGHBOR_ADDR_STR2 "Solo peer - part of its own update group\n") { - int idx_peer = 2; - struct peer *peer; - int ret; + int idx_peer = 2; + struct peer *peer; + int ret; - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - ret = update_group_adjust_soloness(peer, 0); - return bgp_vty_return (vty, ret); + ret = update_group_adjust_soloness(peer, 0); + return bgp_vty_return(vty, ret); } DEFUN (neighbor_password, @@ -3200,17 +3079,17 @@ DEFUN (neighbor_password, "Set a password\n" "The password\n") { - int idx_peer = 1; - int idx_line = 3; - struct peer *peer; - int ret; + int idx_peer = 1; + int idx_line = 3; + struct peer *peer; + int ret; - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - ret = peer_password_set (peer, argv[idx_line]->arg); - return bgp_vty_return (vty, ret); + ret = peer_password_set(peer, argv[idx_line]->arg); + return bgp_vty_return(vty, ret); } DEFUN (no_neighbor_password, @@ -3222,16 +3101,16 @@ DEFUN (no_neighbor_password, "Set a password\n" "The password\n") { - int idx_peer = 2; - struct peer *peer; - int ret; + int idx_peer = 2; + struct peer *peer; + int ret; - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - ret = peer_password_unset (peer); - return bgp_vty_return (vty, ret); + ret = peer_password_unset(peer); + return bgp_vty_return(vty, ret); } @@ -3242,24 +3121,22 @@ DEFUN (neighbor_activate, NEIGHBOR_ADDR_STR2 "Enable the Address Family for this Neighbor\n") { - int idx_peer = 1; - int ret; - struct peer *peer; + int idx_peer = 1; + int ret; + struct peer *peer; - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - ret = peer_activate (peer, bgp_node_afi (vty), bgp_node_safi (vty)); - return bgp_vty_return (vty, ret); + ret = peer_activate(peer, bgp_node_afi(vty), bgp_node_safi(vty)); + return bgp_vty_return(vty, ret); } -ALIAS_HIDDEN (neighbor_activate, - neighbor_activate_hidden_cmd, - "neighbor activate", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Enable the Address Family for this Neighbor\n") +ALIAS_HIDDEN(neighbor_activate, neighbor_activate_hidden_cmd, + "neighbor activate", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Enable the Address Family for this Neighbor\n") DEFUN (no_neighbor_activate, no_neighbor_activate_cmd, @@ -3269,26 +3146,23 @@ DEFUN (no_neighbor_activate, NEIGHBOR_ADDR_STR2 "Enable the Address Family for this Neighbor\n") { - int idx_peer = 2; - int ret; - struct peer *peer; + int idx_peer = 2; + int ret; + struct peer *peer; - /* Lookup peer. */ - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + /* Lookup peer. */ + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - ret = peer_deactivate (peer, bgp_node_afi (vty), bgp_node_safi (vty)); - return bgp_vty_return (vty, ret); + ret = peer_deactivate(peer, bgp_node_afi(vty), bgp_node_safi(vty)); + return bgp_vty_return(vty, ret); } -ALIAS_HIDDEN (no_neighbor_activate, - no_neighbor_activate_hidden_cmd, - "no neighbor activate", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Enable the Address Family for this Neighbor\n") +ALIAS_HIDDEN(no_neighbor_activate, no_neighbor_activate_hidden_cmd, + "no neighbor activate", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Enable the Address Family for this Neighbor\n") DEFUN (neighbor_set_peer_group, neighbor_set_peer_group_cmd, @@ -3298,69 +3172,64 @@ DEFUN (neighbor_set_peer_group, "Member of the peer-group\n" "Peer-group name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_peer = 1; - int idx_word = 3; - int ret; - as_t as; - union sockunion su; - struct peer *peer; - struct peer_group *group; - - peer = NULL; - - ret = str2sockunion (argv[idx_peer]->arg, &su); - if (ret < 0) - { - peer = peer_lookup_by_conf_if (bgp, argv[idx_peer]->arg); - if (!peer) - { - vty_out (vty, "%% Malformed address or name: %s\n", argv[idx_peer]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - } - else - { - if (peer_address_self_check (bgp, &su)) - { - vty_out (vty, "%% Can not configure the local system as neighbor\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Disallow for dynamic neighbor. */ - peer = peer_lookup (bgp, &su); - if (peer && peer_dynamic_neighbor (peer)) - { - vty_out (vty, "%% Operation not allowed on a dynamic neighbor\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - group = peer_group_lookup (bgp, argv[idx_word]->arg); - if (! group) - { - vty_out (vty, "%% Configure the peer-group first\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ret = peer_group_bind (bgp, &su, peer, group, &as); - - if (ret == BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT) - { - vty_out (vty, "%% Peer with AS %u cannot be in this peer-group, members must be all internal or all external\n", as); - return CMD_WARNING_CONFIG_FAILED; - } - - return bgp_vty_return (vty, ret); -} - -ALIAS_HIDDEN (neighbor_set_peer_group, - neighbor_set_peer_group_hidden_cmd, - "neighbor peer-group WORD", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Member of the peer-group\n" - "Peer-group name\n") + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_peer = 1; + int idx_word = 3; + int ret; + as_t as; + union sockunion su; + struct peer *peer; + struct peer_group *group; + + peer = NULL; + + ret = str2sockunion(argv[idx_peer]->arg, &su); + if (ret < 0) { + peer = peer_lookup_by_conf_if(bgp, argv[idx_peer]->arg); + if (!peer) { + vty_out(vty, "%% Malformed address or name: %s\n", + argv[idx_peer]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + } else { + if (peer_address_self_check(bgp, &su)) { + vty_out(vty, + "%% Can not configure the local system as neighbor\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Disallow for dynamic neighbor. */ + peer = peer_lookup(bgp, &su); + if (peer && peer_dynamic_neighbor(peer)) { + vty_out(vty, + "%% Operation not allowed on a dynamic neighbor\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + group = peer_group_lookup(bgp, argv[idx_word]->arg); + if (!group) { + vty_out(vty, "%% Configure the peer-group first\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = peer_group_bind(bgp, &su, peer, group, &as); + + if (ret == BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT) { + vty_out(vty, + "%% Peer with AS %u cannot be in this peer-group, members must be all internal or all external\n", + as); + return CMD_WARNING_CONFIG_FAILED; + } + + return bgp_vty_return(vty, ret); +} + +ALIAS_HIDDEN(neighbor_set_peer_group, neighbor_set_peer_group_hidden_cmd, + "neighbor peer-group WORD", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Member of the peer-group\n" + "Peer-group name\n") DEFUN (no_neighbor_set_peer_group, no_neighbor_set_peer_group_cmd, @@ -3371,80 +3240,77 @@ DEFUN (no_neighbor_set_peer_group, "Member of the peer-group\n" "Peer-group name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_peer = 2; - int idx_word = 4; - int ret; - struct peer *peer; - struct peer_group *group; - - peer = peer_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; - - group = peer_group_lookup (bgp, argv[idx_word]->arg); - if (! group) - { - vty_out (vty, "%% Configure the peer-group first\n"); - return CMD_WARNING_CONFIG_FAILED; - } + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_peer = 2; + int idx_word = 4; + int ret; + struct peer *peer; + struct peer_group *group; + + peer = peer_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; + + group = peer_group_lookup(bgp, argv[idx_word]->arg); + if (!group) { + vty_out(vty, "%% Configure the peer-group first\n"); + return CMD_WARNING_CONFIG_FAILED; + } - ret = peer_group_unbind (bgp, peer, group); + ret = peer_group_unbind(bgp, peer, group); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } -ALIAS_HIDDEN (no_neighbor_set_peer_group, - no_neighbor_set_peer_group_hidden_cmd, - "no neighbor peer-group WORD", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Member of the peer-group\n" - "Peer-group name\n") +ALIAS_HIDDEN(no_neighbor_set_peer_group, no_neighbor_set_peer_group_hidden_cmd, + "no neighbor peer-group WORD", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Member of the peer-group\n" + "Peer-group name\n") -static int -peer_flag_modify_vty (struct vty *vty, const char *ip_str, - u_int16_t flag, int set) +static int peer_flag_modify_vty(struct vty *vty, const char *ip_str, + u_int16_t flag, int set) { - int ret; - struct peer *peer; + int ret; + struct peer *peer; - peer = peer_and_group_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - /* - * If 'neighbor ', then this is for directly connected peers, - * we should not accept disable-connected-check. - */ - if (peer->conf_if && (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)) { - vty_out (vty, "%s is directly connected peer, cannot accept disable-" - "connected-check\n", ip_str); - return CMD_WARNING_CONFIG_FAILED; - } + /* + * If 'neighbor ', then this is for directly connected peers, + * we should not accept disable-connected-check. + */ + if (peer->conf_if && (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)) { + vty_out(vty, + "%s is directly connected peer, cannot accept disable-" + "connected-check\n", + ip_str); + return CMD_WARNING_CONFIG_FAILED; + } - if (!set && flag == PEER_FLAG_SHUTDOWN) - peer_tx_shutdown_message_unset (peer); + if (!set && flag == PEER_FLAG_SHUTDOWN) + peer_tx_shutdown_message_unset(peer); - if (set) - ret = peer_flag_set (peer, flag); - else - ret = peer_flag_unset (peer, flag); + if (set) + ret = peer_flag_set(peer, flag); + else + ret = peer_flag_unset(peer, flag); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } -static int -peer_flag_set_vty (struct vty *vty, const char *ip_str, u_int16_t flag) +static int peer_flag_set_vty(struct vty *vty, const char *ip_str, + u_int16_t flag) { - return peer_flag_modify_vty (vty, ip_str, flag, 1); + return peer_flag_modify_vty(vty, ip_str, flag, 1); } -static int -peer_flag_unset_vty (struct vty *vty, const char *ip_str, u_int16_t flag) +static int peer_flag_unset_vty(struct vty *vty, const char *ip_str, + u_int16_t flag) { - return peer_flag_modify_vty (vty, ip_str, flag, 0); + return peer_flag_modify_vty(vty, ip_str, flag, 0); } /* neighbor passive. */ @@ -3455,8 +3321,8 @@ DEFUN (neighbor_passive, NEIGHBOR_ADDR_STR2 "Don't send open messages to this neighbor\n") { - int idx_peer = 1; - return peer_flag_set_vty (vty, argv[idx_peer]->arg, PEER_FLAG_PASSIVE); + int idx_peer = 1; + return peer_flag_set_vty(vty, argv[idx_peer]->arg, PEER_FLAG_PASSIVE); } DEFUN (no_neighbor_passive, @@ -3467,8 +3333,8 @@ DEFUN (no_neighbor_passive, NEIGHBOR_ADDR_STR2 "Don't send open messages to this neighbor\n") { - int idx_peer = 2; - return peer_flag_unset_vty (vty, argv[idx_peer]->arg, PEER_FLAG_PASSIVE); + int idx_peer = 2; + return peer_flag_unset_vty(vty, argv[idx_peer]->arg, PEER_FLAG_PASSIVE); } /* neighbor shutdown. */ @@ -3481,29 +3347,27 @@ DEFUN (neighbor_shutdown_msg, "Add a shutdown message (draft-ietf-idr-shutdown-06)\n" "Shutdown message\n") { - int idx_peer = 1; + int idx_peer = 1; - if (argc >= 5) - { - struct peer *peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - char *message; + if (argc >= 5) { + struct peer *peer = + peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + char *message; - if (!peer) - return CMD_WARNING_CONFIG_FAILED; - message = argv_concat (argv, argc, 4); - peer_tx_shutdown_message_set (peer, message); - XFREE (MTYPE_TMP, message); - } + if (!peer) + return CMD_WARNING_CONFIG_FAILED; + message = argv_concat(argv, argc, 4); + peer_tx_shutdown_message_set(peer, message); + XFREE(MTYPE_TMP, message); + } - return peer_flag_set_vty (vty, argv[idx_peer]->arg, PEER_FLAG_SHUTDOWN); + return peer_flag_set_vty(vty, argv[idx_peer]->arg, PEER_FLAG_SHUTDOWN); } -ALIAS (neighbor_shutdown_msg, - neighbor_shutdown_cmd, - "neighbor shutdown", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Administratively shut down this neighbor\n") +ALIAS(neighbor_shutdown_msg, neighbor_shutdown_cmd, + "neighbor shutdown", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Administratively shut down this neighbor\n") DEFUN (no_neighbor_shutdown_msg, no_neighbor_shutdown_msg_cmd, @@ -3515,18 +3379,16 @@ DEFUN (no_neighbor_shutdown_msg, "Remove a shutdown message (draft-ietf-idr-shutdown-06)\n" "Shutdown message\n") { - int idx_peer = 2; + int idx_peer = 2; - return peer_flag_unset_vty (vty, argv[idx_peer]->arg, PEER_FLAG_SHUTDOWN); + return peer_flag_unset_vty(vty, argv[idx_peer]->arg, + PEER_FLAG_SHUTDOWN); } -ALIAS (no_neighbor_shutdown_msg, - no_neighbor_shutdown_cmd, - "no neighbor shutdown", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Administratively shut down this neighbor\n") +ALIAS(no_neighbor_shutdown_msg, no_neighbor_shutdown_cmd, + "no neighbor shutdown", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Administratively shut down this neighbor\n") /* neighbor capability dynamic. */ DEFUN (neighbor_capability_dynamic, @@ -3537,8 +3399,9 @@ DEFUN (neighbor_capability_dynamic, "Advertise capability to the peer\n" "Advertise dynamic capability to this neighbor\n") { - int idx_peer = 1; - return peer_flag_set_vty (vty, argv[idx_peer]->arg, PEER_FLAG_DYNAMIC_CAPABILITY); + int idx_peer = 1; + return peer_flag_set_vty(vty, argv[idx_peer]->arg, + PEER_FLAG_DYNAMIC_CAPABILITY); } DEFUN (no_neighbor_capability_dynamic, @@ -3550,8 +3413,9 @@ DEFUN (no_neighbor_capability_dynamic, "Advertise capability to the peer\n" "Advertise dynamic capability to this neighbor\n") { - int idx_peer = 2; - return peer_flag_unset_vty (vty, argv[idx_peer]->arg, PEER_FLAG_DYNAMIC_CAPABILITY); + int idx_peer = 2; + return peer_flag_unset_vty(vty, argv[idx_peer]->arg, + PEER_FLAG_DYNAMIC_CAPABILITY); } /* neighbor dont-capability-negotiate */ @@ -3562,8 +3426,9 @@ DEFUN (neighbor_dont_capability_negotiate, NEIGHBOR_ADDR_STR2 "Do not perform capability negotiation\n") { - int idx_peer = 1; - return peer_flag_set_vty (vty, argv[idx_peer]->arg, PEER_FLAG_DONT_CAPABILITY); + int idx_peer = 1; + return peer_flag_set_vty(vty, argv[idx_peer]->arg, + PEER_FLAG_DONT_CAPABILITY); } DEFUN (no_neighbor_dont_capability_negotiate, @@ -3574,8 +3439,9 @@ DEFUN (no_neighbor_dont_capability_negotiate, NEIGHBOR_ADDR_STR2 "Do not perform capability negotiation\n") { - int idx_peer = 2; - return peer_flag_unset_vty (vty, argv[idx_peer]->arg, PEER_FLAG_DONT_CAPABILITY); + int idx_peer = 2; + return peer_flag_unset_vty(vty, argv[idx_peer]->arg, + PEER_FLAG_DONT_CAPABILITY); } /* neighbor capability extended next hop encoding */ @@ -3587,8 +3453,9 @@ DEFUN (neighbor_capability_enhe, "Advertise capability to the peer\n" "Advertise extended next-hop capability to the peer\n") { - int idx_peer = 1; - return peer_flag_set_vty (vty, argv[idx_peer]->arg, PEER_FLAG_CAPABILITY_ENHE); + int idx_peer = 1; + return peer_flag_set_vty(vty, argv[idx_peer]->arg, + PEER_FLAG_CAPABILITY_ENHE); } DEFUN (no_neighbor_capability_enhe, @@ -3600,41 +3467,40 @@ DEFUN (no_neighbor_capability_enhe, "Advertise capability to the peer\n" "Advertise extended next-hop capability to the peer\n") { - int idx_peer = 2; - return peer_flag_unset_vty (vty, argv[idx_peer]->arg, PEER_FLAG_CAPABILITY_ENHE); + int idx_peer = 2; + return peer_flag_unset_vty(vty, argv[idx_peer]->arg, + PEER_FLAG_CAPABILITY_ENHE); } -static int -peer_af_flag_modify_vty (struct vty *vty, const char *peer_str, afi_t afi, - safi_t safi, u_int32_t flag, int set) +static int peer_af_flag_modify_vty(struct vty *vty, const char *peer_str, + afi_t afi, safi_t safi, u_int32_t flag, + int set) { - int ret; - struct peer *peer; + int ret; + struct peer *peer; - peer = peer_and_group_lookup_vty (vty, peer_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, peer_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - if (set) - ret = peer_af_flag_set (peer, afi, safi, flag); - else - ret = peer_af_flag_unset (peer, afi, safi, flag); + if (set) + ret = peer_af_flag_set(peer, afi, safi, flag); + else + ret = peer_af_flag_unset(peer, afi, safi, flag); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } -static int -peer_af_flag_set_vty (struct vty *vty, const char *peer_str, afi_t afi, - safi_t safi, u_int32_t flag) +static int peer_af_flag_set_vty(struct vty *vty, const char *peer_str, + afi_t afi, safi_t safi, u_int32_t flag) { - return peer_af_flag_modify_vty (vty, peer_str, afi, safi, flag, 1); + return peer_af_flag_modify_vty(vty, peer_str, afi, safi, flag, 1); } -static int -peer_af_flag_unset_vty (struct vty *vty, const char *peer_str, afi_t afi, - safi_t safi, u_int32_t flag) +static int peer_af_flag_unset_vty(struct vty *vty, const char *peer_str, + afi_t afi, safi_t safi, u_int32_t flag) { - return peer_af_flag_modify_vty (vty, peer_str, afi, safi, flag, 0); + return peer_af_flag_modify_vty(vty, peer_str, afi, safi, flag, 0); } /* neighbor capability orf prefix-list. */ @@ -3650,37 +3516,36 @@ DEFUN (neighbor_capability_orf_prefix, "Capability to RECEIVE the ORF from this neighbor\n" "Capability to SEND the ORF to this neighbor\n") { - int idx_peer = 1; - int idx_send_recv = 5; - u_int16_t flag = 0; - - if (strmatch (argv[idx_send_recv]->text, "send")) - flag = PEER_FLAG_ORF_PREFIX_SM; - else if (strmatch (argv[idx_send_recv]->text, "receive")) - flag = PEER_FLAG_ORF_PREFIX_RM; - else if (strmatch (argv[idx_send_recv]->text, "both")) - flag = PEER_FLAG_ORF_PREFIX_SM|PEER_FLAG_ORF_PREFIX_RM; - else - { - vty_out (vty, "%% BGP invalid orf prefix-list option\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return peer_af_flag_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), flag); -} - -ALIAS_HIDDEN (neighbor_capability_orf_prefix, - neighbor_capability_orf_prefix_hidden_cmd, - "neighbor capability orf prefix-list ", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Advertise capability to the peer\n" - "Advertise ORF capability to the peer\n" - "Advertise prefixlist ORF capability to this neighbor\n" - "Capability to SEND and RECEIVE the ORF to/from this neighbor\n" - "Capability to RECEIVE the ORF from this neighbor\n" - "Capability to SEND the ORF to this neighbor\n") + int idx_peer = 1; + int idx_send_recv = 5; + u_int16_t flag = 0; + + if (strmatch(argv[idx_send_recv]->text, "send")) + flag = PEER_FLAG_ORF_PREFIX_SM; + else if (strmatch(argv[idx_send_recv]->text, "receive")) + flag = PEER_FLAG_ORF_PREFIX_RM; + else if (strmatch(argv[idx_send_recv]->text, "both")) + flag = PEER_FLAG_ORF_PREFIX_SM | PEER_FLAG_ORF_PREFIX_RM; + else { + vty_out(vty, "%% BGP invalid orf prefix-list option\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), flag); +} + +ALIAS_HIDDEN( + neighbor_capability_orf_prefix, + neighbor_capability_orf_prefix_hidden_cmd, + "neighbor capability orf prefix-list ", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Advertise capability to the peer\n" + "Advertise ORF capability to the peer\n" + "Advertise prefixlist ORF capability to this neighbor\n" + "Capability to SEND and RECEIVE the ORF to/from this neighbor\n" + "Capability to RECEIVE the ORF from this neighbor\n" + "Capability to SEND the ORF to this neighbor\n") DEFUN (no_neighbor_capability_orf_prefix, no_neighbor_capability_orf_prefix_cmd, @@ -3695,38 +3560,37 @@ DEFUN (no_neighbor_capability_orf_prefix, "Capability to RECEIVE the ORF from this neighbor\n" "Capability to SEND the ORF to this neighbor\n") { - int idx_peer = 2; - int idx_send_recv = 6; - u_int16_t flag = 0; - - if (strmatch (argv[idx_send_recv]->text, "send")) - flag = PEER_FLAG_ORF_PREFIX_SM; - else if (strmatch (argv[idx_send_recv]->text, "receive")) - flag = PEER_FLAG_ORF_PREFIX_RM; - else if (strmatch (argv[idx_send_recv]->text, "both")) - flag = PEER_FLAG_ORF_PREFIX_SM|PEER_FLAG_ORF_PREFIX_RM; - else - { - vty_out (vty, "%% BGP invalid orf prefix-list option\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), flag); -} - -ALIAS_HIDDEN (no_neighbor_capability_orf_prefix, - no_neighbor_capability_orf_prefix_hidden_cmd, - "no neighbor capability orf prefix-list ", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Advertise capability to the peer\n" - "Advertise ORF capability to the peer\n" - "Advertise prefixlist ORF capability to this neighbor\n" - "Capability to SEND and RECEIVE the ORF to/from this neighbor\n" - "Capability to RECEIVE the ORF from this neighbor\n" - "Capability to SEND the ORF to this neighbor\n") + int idx_peer = 2; + int idx_send_recv = 6; + u_int16_t flag = 0; + + if (strmatch(argv[idx_send_recv]->text, "send")) + flag = PEER_FLAG_ORF_PREFIX_SM; + else if (strmatch(argv[idx_send_recv]->text, "receive")) + flag = PEER_FLAG_ORF_PREFIX_RM; + else if (strmatch(argv[idx_send_recv]->text, "both")) + flag = PEER_FLAG_ORF_PREFIX_SM | PEER_FLAG_ORF_PREFIX_RM; + else { + vty_out(vty, "%% BGP invalid orf prefix-list option\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), bgp_node_safi(vty), + flag); +} + +ALIAS_HIDDEN( + no_neighbor_capability_orf_prefix, + no_neighbor_capability_orf_prefix_hidden_cmd, + "no neighbor capability orf prefix-list ", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Advertise capability to the peer\n" + "Advertise ORF capability to the peer\n" + "Advertise prefixlist ORF capability to this neighbor\n" + "Capability to SEND and RECEIVE the ORF to/from this neighbor\n" + "Capability to RECEIVE the ORF from this neighbor\n" + "Capability to SEND the ORF to this neighbor\n") /* neighbor next-hop-self. */ DEFUN (neighbor_nexthop_self, @@ -3736,17 +3600,15 @@ DEFUN (neighbor_nexthop_self, NEIGHBOR_ADDR_STR2 "Disable the next hop calculation for this neighbor\n") { - int idx_peer = 1; - return peer_af_flag_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), PEER_FLAG_NEXTHOP_SELF); + int idx_peer = 1; + return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), PEER_FLAG_NEXTHOP_SELF); } -ALIAS_HIDDEN (neighbor_nexthop_self, - neighbor_nexthop_self_hidden_cmd, - "neighbor next-hop-self", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Disable the next hop calculation for this neighbor\n") +ALIAS_HIDDEN(neighbor_nexthop_self, neighbor_nexthop_self_hidden_cmd, + "neighbor next-hop-self", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Disable the next hop calculation for this neighbor\n") /* neighbor next-hop-self. */ DEFUN (neighbor_nexthop_self_force, @@ -3757,19 +3619,18 @@ DEFUN (neighbor_nexthop_self_force, "Disable the next hop calculation for this neighbor\n" "Set the next hop to self for reflected routes\n") { - int idx_peer = 1; - return peer_af_flag_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_FORCE_NEXTHOP_SELF); + int idx_peer = 1; + return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), + PEER_FLAG_FORCE_NEXTHOP_SELF); } -ALIAS_HIDDEN (neighbor_nexthop_self_force, - neighbor_nexthop_self_force_hidden_cmd, - "neighbor next-hop-self force", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Disable the next hop calculation for this neighbor\n" - "Set the next hop to self for reflected routes\n") +ALIAS_HIDDEN(neighbor_nexthop_self_force, + neighbor_nexthop_self_force_hidden_cmd, + "neighbor next-hop-self force", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Disable the next hop calculation for this neighbor\n" + "Set the next hop to self for reflected routes\n") DEFUN (no_neighbor_nexthop_self, no_neighbor_nexthop_self_cmd, @@ -3779,19 +3640,16 @@ DEFUN (no_neighbor_nexthop_self, NEIGHBOR_ADDR_STR2 "Disable the next hop calculation for this neighbor\n") { - int idx_peer = 2; - return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_NEXTHOP_SELF); + int idx_peer = 2; + return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), bgp_node_safi(vty), + PEER_FLAG_NEXTHOP_SELF); } -ALIAS_HIDDEN (no_neighbor_nexthop_self, - no_neighbor_nexthop_self_hidden_cmd, - "no neighbor next-hop-self", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Disable the next hop calculation for this neighbor\n") +ALIAS_HIDDEN(no_neighbor_nexthop_self, no_neighbor_nexthop_self_hidden_cmd, + "no neighbor next-hop-self", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Disable the next hop calculation for this neighbor\n") DEFUN (no_neighbor_nexthop_self_force, no_neighbor_nexthop_self_force_cmd, @@ -3802,20 +3660,18 @@ DEFUN (no_neighbor_nexthop_self_force, "Disable the next hop calculation for this neighbor\n" "Set the next hop to self for reflected routes\n") { - int idx_peer = 2; - return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_FORCE_NEXTHOP_SELF); + int idx_peer = 2; + return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), bgp_node_safi(vty), + PEER_FLAG_FORCE_NEXTHOP_SELF); } -ALIAS_HIDDEN (no_neighbor_nexthop_self_force, - no_neighbor_nexthop_self_force_hidden_cmd, - "no neighbor next-hop-self force", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Disable the next hop calculation for this neighbor\n" - "Set the next hop to self for reflected routes\n") +ALIAS_HIDDEN(no_neighbor_nexthop_self_force, + no_neighbor_nexthop_self_force_hidden_cmd, + "no neighbor next-hop-self force", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Disable the next hop calculation for this neighbor\n" + "Set the next hop to self for reflected routes\n") /* neighbor as-override */ DEFUN (neighbor_as_override, @@ -3825,18 +3681,15 @@ DEFUN (neighbor_as_override, NEIGHBOR_ADDR_STR2 "Override ASNs in outbound updates if aspath equals remote-as\n") { - int idx_peer = 1; - return peer_af_flag_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_AS_OVERRIDE); + int idx_peer = 1; + return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), PEER_FLAG_AS_OVERRIDE); } -ALIAS_HIDDEN (neighbor_as_override, - neighbor_as_override_hidden_cmd, - "neighbor as-override", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Override ASNs in outbound updates if aspath equals remote-as\n") +ALIAS_HIDDEN(neighbor_as_override, neighbor_as_override_hidden_cmd, + "neighbor as-override", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Override ASNs in outbound updates if aspath equals remote-as\n") DEFUN (no_neighbor_as_override, no_neighbor_as_override_cmd, @@ -3846,19 +3699,16 @@ DEFUN (no_neighbor_as_override, NEIGHBOR_ADDR_STR2 "Override ASNs in outbound updates if aspath equals remote-as\n") { - int idx_peer = 2; - return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_AS_OVERRIDE); + int idx_peer = 2; + return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), bgp_node_safi(vty), + PEER_FLAG_AS_OVERRIDE); } -ALIAS_HIDDEN (no_neighbor_as_override, - no_neighbor_as_override_hidden_cmd, - "no neighbor as-override", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Override ASNs in outbound updates if aspath equals remote-as\n") +ALIAS_HIDDEN(no_neighbor_as_override, no_neighbor_as_override_hidden_cmd, + "no neighbor as-override", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Override ASNs in outbound updates if aspath equals remote-as\n") /* neighbor remove-private-AS. */ DEFUN (neighbor_remove_private_as, @@ -3868,18 +3718,16 @@ DEFUN (neighbor_remove_private_as, NEIGHBOR_ADDR_STR2 "Remove private ASNs in outbound updates\n") { - int idx_peer = 1; - return peer_af_flag_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_REMOVE_PRIVATE_AS); + int idx_peer = 1; + return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), + PEER_FLAG_REMOVE_PRIVATE_AS); } -ALIAS_HIDDEN (neighbor_remove_private_as, - neighbor_remove_private_as_hidden_cmd, - "neighbor remove-private-AS", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Remove private ASNs in outbound updates\n") +ALIAS_HIDDEN(neighbor_remove_private_as, neighbor_remove_private_as_hidden_cmd, + "neighbor remove-private-AS", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Remove private ASNs in outbound updates\n") DEFUN (neighbor_remove_private_as_all, neighbor_remove_private_as_all_cmd, @@ -3889,19 +3737,18 @@ DEFUN (neighbor_remove_private_as_all, "Remove private ASNs in outbound updates\n" "Apply to all AS numbers") { - int idx_peer = 1; - return peer_af_flag_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_REMOVE_PRIVATE_AS_ALL); + int idx_peer = 1; + return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), + PEER_FLAG_REMOVE_PRIVATE_AS_ALL); } -ALIAS_HIDDEN (neighbor_remove_private_as_all, - neighbor_remove_private_as_all_hidden_cmd, - "neighbor remove-private-AS all", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Remove private ASNs in outbound updates\n" - "Apply to all AS numbers") +ALIAS_HIDDEN(neighbor_remove_private_as_all, + neighbor_remove_private_as_all_hidden_cmd, + "neighbor remove-private-AS all", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Remove private ASNs in outbound updates\n" + "Apply to all AS numbers") DEFUN (neighbor_remove_private_as_replace_as, neighbor_remove_private_as_replace_as_cmd, @@ -3911,19 +3758,18 @@ DEFUN (neighbor_remove_private_as_replace_as, "Remove private ASNs in outbound updates\n" "Replace private ASNs with our ASN in outbound updates\n") { - int idx_peer = 1; - return peer_af_flag_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE); + int idx_peer = 1; + return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), + PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE); } -ALIAS_HIDDEN (neighbor_remove_private_as_replace_as, - neighbor_remove_private_as_replace_as_hidden_cmd, - "neighbor remove-private-AS replace-AS", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Remove private ASNs in outbound updates\n" - "Replace private ASNs with our ASN in outbound updates\n") +ALIAS_HIDDEN(neighbor_remove_private_as_replace_as, + neighbor_remove_private_as_replace_as_hidden_cmd, + "neighbor remove-private-AS replace-AS", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Remove private ASNs in outbound updates\n" + "Replace private ASNs with our ASN in outbound updates\n") DEFUN (neighbor_remove_private_as_all_replace_as, neighbor_remove_private_as_all_replace_as_cmd, @@ -3934,20 +3780,20 @@ DEFUN (neighbor_remove_private_as_all_replace_as, "Apply to all AS numbers\n" "Replace private ASNs with our ASN in outbound updates\n") { - int idx_peer = 1; - return peer_af_flag_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE); + int idx_peer = 1; + return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), + PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE); } -ALIAS_HIDDEN (neighbor_remove_private_as_all_replace_as, - neighbor_remove_private_as_all_replace_as_hidden_cmd, - "neighbor remove-private-AS all replace-AS", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Remove private ASNs in outbound updates\n" - "Apply to all AS numbers\n" - "Replace private ASNs with our ASN in outbound updates\n") +ALIAS_HIDDEN( + neighbor_remove_private_as_all_replace_as, + neighbor_remove_private_as_all_replace_as_hidden_cmd, + "neighbor remove-private-AS all replace-AS", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Remove private ASNs in outbound updates\n" + "Apply to all AS numbers\n" + "Replace private ASNs with our ASN in outbound updates\n") DEFUN (no_neighbor_remove_private_as, no_neighbor_remove_private_as_cmd, @@ -3957,19 +3803,17 @@ DEFUN (no_neighbor_remove_private_as, NEIGHBOR_ADDR_STR2 "Remove private ASNs in outbound updates\n") { - int idx_peer = 2; - return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_REMOVE_PRIVATE_AS); + int idx_peer = 2; + return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), bgp_node_safi(vty), + PEER_FLAG_REMOVE_PRIVATE_AS); } -ALIAS_HIDDEN (no_neighbor_remove_private_as, - no_neighbor_remove_private_as_hidden_cmd, - "no neighbor remove-private-AS", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Remove private ASNs in outbound updates\n") +ALIAS_HIDDEN(no_neighbor_remove_private_as, + no_neighbor_remove_private_as_hidden_cmd, + "no neighbor remove-private-AS", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Remove private ASNs in outbound updates\n") DEFUN (no_neighbor_remove_private_as_all, no_neighbor_remove_private_as_all_cmd, @@ -3980,20 +3824,18 @@ DEFUN (no_neighbor_remove_private_as_all, "Remove private ASNs in outbound updates\n" "Apply to all AS numbers\n") { - int idx_peer = 2; - return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_REMOVE_PRIVATE_AS_ALL); + int idx_peer = 2; + return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), bgp_node_safi(vty), + PEER_FLAG_REMOVE_PRIVATE_AS_ALL); } -ALIAS_HIDDEN (no_neighbor_remove_private_as_all, - no_neighbor_remove_private_as_all_hidden_cmd, - "no neighbor remove-private-AS all", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Remove private ASNs in outbound updates\n" - "Apply to all AS numbers\n") +ALIAS_HIDDEN(no_neighbor_remove_private_as_all, + no_neighbor_remove_private_as_all_hidden_cmd, + "no neighbor remove-private-AS all", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Remove private ASNs in outbound updates\n" + "Apply to all AS numbers\n") DEFUN (no_neighbor_remove_private_as_replace_as, no_neighbor_remove_private_as_replace_as_cmd, @@ -4004,20 +3846,18 @@ DEFUN (no_neighbor_remove_private_as_replace_as, "Remove private ASNs in outbound updates\n" "Replace private ASNs with our ASN in outbound updates\n") { - int idx_peer = 2; - return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE); + int idx_peer = 2; + return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), bgp_node_safi(vty), + PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE); } -ALIAS_HIDDEN (no_neighbor_remove_private_as_replace_as, - no_neighbor_remove_private_as_replace_as_hidden_cmd, - "no neighbor remove-private-AS replace-AS", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Remove private ASNs in outbound updates\n" - "Replace private ASNs with our ASN in outbound updates\n") +ALIAS_HIDDEN(no_neighbor_remove_private_as_replace_as, + no_neighbor_remove_private_as_replace_as_hidden_cmd, + "no neighbor remove-private-AS replace-AS", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Remove private ASNs in outbound updates\n" + "Replace private ASNs with our ASN in outbound updates\n") DEFUN (no_neighbor_remove_private_as_all_replace_as, no_neighbor_remove_private_as_all_replace_as_cmd, @@ -4029,21 +3869,20 @@ DEFUN (no_neighbor_remove_private_as_all_replace_as, "Apply to all AS numbers\n" "Replace private ASNs with our ASN in outbound updates\n") { - int idx_peer = 2; - return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE); + int idx_peer = 2; + return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), bgp_node_safi(vty), + PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE); } -ALIAS_HIDDEN (no_neighbor_remove_private_as_all_replace_as, - no_neighbor_remove_private_as_all_replace_as_hidden_cmd, - "no neighbor remove-private-AS all replace-AS", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Remove private ASNs in outbound updates\n" - "Apply to all AS numbers\n" - "Replace private ASNs with our ASN in outbound updates\n") +ALIAS_HIDDEN( + no_neighbor_remove_private_as_all_replace_as, + no_neighbor_remove_private_as_all_replace_as_hidden_cmd, + "no neighbor remove-private-AS all replace-AS", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Remove private ASNs in outbound updates\n" + "Apply to all AS numbers\n" + "Replace private ASNs with our ASN in outbound updates\n") /* neighbor send-community. */ @@ -4054,18 +3893,16 @@ DEFUN (neighbor_send_community, NEIGHBOR_ADDR_STR2 "Send Community attribute to this neighbor\n") { - int idx_peer = 1; - return peer_af_flag_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_SEND_COMMUNITY); + int idx_peer = 1; + return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), + PEER_FLAG_SEND_COMMUNITY); } -ALIAS_HIDDEN (neighbor_send_community, - neighbor_send_community_hidden_cmd, - "neighbor send-community", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Send Community attribute to this neighbor\n") +ALIAS_HIDDEN(neighbor_send_community, neighbor_send_community_hidden_cmd, + "neighbor send-community", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Send Community attribute to this neighbor\n") DEFUN (no_neighbor_send_community, no_neighbor_send_community_cmd, @@ -4075,19 +3912,16 @@ DEFUN (no_neighbor_send_community, NEIGHBOR_ADDR_STR2 "Send Community attribute to this neighbor\n") { - int idx_peer = 2; - return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_SEND_COMMUNITY); + int idx_peer = 2; + return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), bgp_node_safi(vty), + PEER_FLAG_SEND_COMMUNITY); } -ALIAS_HIDDEN (no_neighbor_send_community, - no_neighbor_send_community_hidden_cmd, - "no neighbor send-community", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Send Community attribute to this neighbor\n") +ALIAS_HIDDEN(no_neighbor_send_community, no_neighbor_send_community_hidden_cmd, + "no neighbor send-community", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Send Community attribute to this neighbor\n") /* neighbor send-community extended. */ DEFUN (neighbor_send_community_type, @@ -4102,43 +3936,40 @@ DEFUN (neighbor_send_community_type, "Send Standard Community attributes\n" "Send Large Community attributes\n") { - int idx = 0; - u_int32_t flag = 0; - - char *peer = argv[1]->arg; - - if (argv_find (argv, argc, "standard", &idx)) - SET_FLAG (flag, PEER_FLAG_SEND_COMMUNITY); - else if (argv_find (argv, argc, "extended", &idx)) - SET_FLAG (flag, PEER_FLAG_SEND_EXT_COMMUNITY); - else if (argv_find (argv, argc, "large", &idx)) - SET_FLAG (flag, PEER_FLAG_SEND_LARGE_COMMUNITY); - else if (argv_find (argv, argc, "both", &idx)) - { - SET_FLAG (flag, PEER_FLAG_SEND_COMMUNITY); - SET_FLAG (flag, PEER_FLAG_SEND_EXT_COMMUNITY); - } - else - { - SET_FLAG (flag, PEER_FLAG_SEND_COMMUNITY); - SET_FLAG (flag, PEER_FLAG_SEND_EXT_COMMUNITY); - SET_FLAG (flag, PEER_FLAG_SEND_LARGE_COMMUNITY); - } - - return peer_af_flag_set_vty (vty, peer, bgp_node_afi (vty), bgp_node_safi (vty), flag); -} - -ALIAS_HIDDEN (neighbor_send_community_type, - neighbor_send_community_type_hidden_cmd, - "neighbor send-community ", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Send Community attribute to this neighbor\n" - "Send Standard and Extended Community attributes\n" - "Send Standard, Large and Extended Community attributes\n" - "Send Extended Community attributes\n" - "Send Standard Community attributes\n" - "Send Large Community attributes\n") + int idx = 0; + u_int32_t flag = 0; + + char *peer = argv[1]->arg; + + if (argv_find(argv, argc, "standard", &idx)) + SET_FLAG(flag, PEER_FLAG_SEND_COMMUNITY); + else if (argv_find(argv, argc, "extended", &idx)) + SET_FLAG(flag, PEER_FLAG_SEND_EXT_COMMUNITY); + else if (argv_find(argv, argc, "large", &idx)) + SET_FLAG(flag, PEER_FLAG_SEND_LARGE_COMMUNITY); + else if (argv_find(argv, argc, "both", &idx)) { + SET_FLAG(flag, PEER_FLAG_SEND_COMMUNITY); + SET_FLAG(flag, PEER_FLAG_SEND_EXT_COMMUNITY); + } else { + SET_FLAG(flag, PEER_FLAG_SEND_COMMUNITY); + SET_FLAG(flag, PEER_FLAG_SEND_EXT_COMMUNITY); + SET_FLAG(flag, PEER_FLAG_SEND_LARGE_COMMUNITY); + } + + return peer_af_flag_set_vty(vty, peer, bgp_node_afi(vty), + bgp_node_safi(vty), flag); +} + +ALIAS_HIDDEN( + neighbor_send_community_type, neighbor_send_community_type_hidden_cmd, + "neighbor send-community ", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Send Community attribute to this neighbor\n" + "Send Standard and Extended Community attributes\n" + "Send Standard, Large and Extended Community attributes\n" + "Send Extended Community attributes\n" + "Send Standard Community attributes\n" + "Send Large Community attributes\n") DEFUN (no_neighbor_send_community_type, no_neighbor_send_community_type_cmd, @@ -4153,48 +3984,47 @@ DEFUN (no_neighbor_send_community_type, "Send Standard Community attributes\n" "Send Large Community attributes\n") { - int idx_peer = 2; - - const char *type = argv[argc - 1]->text; - - if (strmatch (type, "standard")) - return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_SEND_COMMUNITY); - if (strmatch (type, "extended")) - return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_SEND_EXT_COMMUNITY); - if (strmatch (type, "large")) - return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_SEND_LARGE_COMMUNITY); - if (strmatch (type, "both")) - return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_SEND_COMMUNITY | - PEER_FLAG_SEND_EXT_COMMUNITY); - - /* if (strmatch (type, "all")) */ - return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - (PEER_FLAG_SEND_COMMUNITY | - PEER_FLAG_SEND_EXT_COMMUNITY| - PEER_FLAG_SEND_LARGE_COMMUNITY)); -} - -ALIAS_HIDDEN (no_neighbor_send_community_type, - no_neighbor_send_community_type_hidden_cmd, - "no neighbor send-community ", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Send Community attribute to this neighbor\n" - "Send Standard and Extended Community attributes\n" - "Send Standard, Large and Extended Community attributes\n" - "Send Extended Community attributes\n" - "Send Standard Community attributes\n" - "Send Large Community attributes\n") + int idx_peer = 2; + + const char *type = argv[argc - 1]->text; + + if (strmatch(type, "standard")) + return peer_af_flag_unset_vty( + vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), PEER_FLAG_SEND_COMMUNITY); + if (strmatch(type, "extended")) + return peer_af_flag_unset_vty( + vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), PEER_FLAG_SEND_EXT_COMMUNITY); + if (strmatch(type, "large")) + return peer_af_flag_unset_vty( + vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), PEER_FLAG_SEND_LARGE_COMMUNITY); + if (strmatch(type, "both")) + return peer_af_flag_unset_vty( + vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), + PEER_FLAG_SEND_COMMUNITY + | PEER_FLAG_SEND_EXT_COMMUNITY); + + /* if (strmatch (type, "all")) */ + return peer_af_flag_unset_vty( + vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty), + (PEER_FLAG_SEND_COMMUNITY | PEER_FLAG_SEND_EXT_COMMUNITY + | PEER_FLAG_SEND_LARGE_COMMUNITY)); +} + +ALIAS_HIDDEN( + no_neighbor_send_community_type, + no_neighbor_send_community_type_hidden_cmd, + "no neighbor send-community ", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Send Community attribute to this neighbor\n" + "Send Standard and Extended Community attributes\n" + "Send Standard, Large and Extended Community attributes\n" + "Send Extended Community attributes\n" + "Send Standard Community attributes\n" + "Send Large Community attributes\n") /* neighbor soft-reconfig. */ DEFUN (neighbor_soft_reconfiguration, @@ -4205,19 +4035,18 @@ DEFUN (neighbor_soft_reconfiguration, "Per neighbor soft reconfiguration\n" "Allow inbound soft reconfiguration for this neighbor\n") { - int idx_peer = 1; - return peer_af_flag_set_vty (vty, argv[idx_peer]->arg, - bgp_node_afi (vty), bgp_node_safi (vty), - PEER_FLAG_SOFT_RECONFIG); + int idx_peer = 1; + return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), + PEER_FLAG_SOFT_RECONFIG); } -ALIAS_HIDDEN (neighbor_soft_reconfiguration, - neighbor_soft_reconfiguration_hidden_cmd, - "neighbor soft-reconfiguration inbound", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Per neighbor soft reconfiguration\n" - "Allow inbound soft reconfiguration for this neighbor\n") +ALIAS_HIDDEN(neighbor_soft_reconfiguration, + neighbor_soft_reconfiguration_hidden_cmd, + "neighbor soft-reconfiguration inbound", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Per neighbor soft reconfiguration\n" + "Allow inbound soft reconfiguration for this neighbor\n") DEFUN (no_neighbor_soft_reconfiguration, no_neighbor_soft_reconfiguration_cmd, @@ -4228,20 +4057,18 @@ DEFUN (no_neighbor_soft_reconfiguration, "Per neighbor soft reconfiguration\n" "Allow inbound soft reconfiguration for this neighbor\n") { - int idx_peer = 2; - return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, - bgp_node_afi (vty), bgp_node_safi (vty), - PEER_FLAG_SOFT_RECONFIG); + int idx_peer = 2; + return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), bgp_node_safi(vty), + PEER_FLAG_SOFT_RECONFIG); } -ALIAS_HIDDEN (no_neighbor_soft_reconfiguration, - no_neighbor_soft_reconfiguration_hidden_cmd, - "no neighbor soft-reconfiguration inbound", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Per neighbor soft reconfiguration\n" - "Allow inbound soft reconfiguration for this neighbor\n") +ALIAS_HIDDEN(no_neighbor_soft_reconfiguration, + no_neighbor_soft_reconfiguration_hidden_cmd, + "no neighbor soft-reconfiguration inbound", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Per neighbor soft reconfiguration\n" + "Allow inbound soft reconfiguration for this neighbor\n") DEFUN (neighbor_route_reflector_client, neighbor_route_reflector_client_cmd, @@ -4250,25 +4077,24 @@ DEFUN (neighbor_route_reflector_client, NEIGHBOR_ADDR_STR2 "Configure a neighbor as Route Reflector client\n") { - int idx_peer = 1; - struct peer *peer; + int idx_peer = 1; + struct peer *peer; - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - return peer_af_flag_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_REFLECTOR_CLIENT); + return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), + PEER_FLAG_REFLECTOR_CLIENT); } -ALIAS_HIDDEN (neighbor_route_reflector_client, - neighbor_route_reflector_client_hidden_cmd, - "neighbor route-reflector-client", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Configure a neighbor as Route Reflector client\n") +ALIAS_HIDDEN(neighbor_route_reflector_client, + neighbor_route_reflector_client_hidden_cmd, + "neighbor route-reflector-client", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Configure a neighbor as Route Reflector client\n") DEFUN (no_neighbor_route_reflector_client, no_neighbor_route_reflector_client_cmd, @@ -4278,19 +4104,17 @@ DEFUN (no_neighbor_route_reflector_client, NEIGHBOR_ADDR_STR2 "Configure a neighbor as Route Reflector client\n") { - int idx_peer = 2; - return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_REFLECTOR_CLIENT); + int idx_peer = 2; + return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), bgp_node_safi(vty), + PEER_FLAG_REFLECTOR_CLIENT); } -ALIAS_HIDDEN (no_neighbor_route_reflector_client, - no_neighbor_route_reflector_client_hidden_cmd, - "no neighbor route-reflector-client", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Configure a neighbor as Route Reflector client\n") +ALIAS_HIDDEN(no_neighbor_route_reflector_client, + no_neighbor_route_reflector_client_hidden_cmd, + "no neighbor route-reflector-client", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Configure a neighbor as Route Reflector client\n") /* neighbor route-server-client. */ DEFUN (neighbor_route_server_client, @@ -4300,23 +4124,22 @@ DEFUN (neighbor_route_server_client, NEIGHBOR_ADDR_STR2 "Configure a neighbor as Route Server client\n") { - int idx_peer = 1; - struct peer *peer; + int idx_peer = 1; + struct peer *peer; - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; - return peer_af_flag_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_RSERVER_CLIENT); + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; + return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), + PEER_FLAG_RSERVER_CLIENT); } -ALIAS_HIDDEN (neighbor_route_server_client, - neighbor_route_server_client_hidden_cmd, - "neighbor route-server-client", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Configure a neighbor as Route Server client\n") +ALIAS_HIDDEN(neighbor_route_server_client, + neighbor_route_server_client_hidden_cmd, + "neighbor route-server-client", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Configure a neighbor as Route Server client\n") DEFUN (no_neighbor_route_server_client, no_neighbor_route_server_client_cmd, @@ -4326,19 +4149,17 @@ DEFUN (no_neighbor_route_server_client, NEIGHBOR_ADDR_STR2 "Configure a neighbor as Route Server client\n") { - int idx_peer = 2; - return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_RSERVER_CLIENT); + int idx_peer = 2; + return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), bgp_node_safi(vty), + PEER_FLAG_RSERVER_CLIENT); } -ALIAS_HIDDEN (no_neighbor_route_server_client, - no_neighbor_route_server_client_hidden_cmd, - "no neighbor route-server-client", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Configure a neighbor as Route Server client\n") +ALIAS_HIDDEN(no_neighbor_route_server_client, + no_neighbor_route_server_client_hidden_cmd, + "no neighbor route-server-client", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Configure a neighbor as Route Server client\n") DEFUN (neighbor_nexthop_local_unchanged, neighbor_nexthop_local_unchanged_cmd, @@ -4348,10 +4169,10 @@ DEFUN (neighbor_nexthop_local_unchanged, "Configure treatment of outgoing link-local nexthop attribute\n" "Leave link-local nexthop unchanged for this peer\n") { - int idx_peer = 1; - return peer_af_flag_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED ); + int idx_peer = 1; + return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), + PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED); } DEFUN (no_neighbor_nexthop_local_unchanged, @@ -4363,10 +4184,10 @@ DEFUN (no_neighbor_nexthop_local_unchanged, "Configure treatment of outgoing link-local-nexthop attribute\n" "Leave link-local nexthop unchanged for this peer\n") { - int idx_peer = 2; - return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED ); + int idx_peer = 2; + return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), bgp_node_safi(vty), + PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED); } DEFUN (neighbor_attr_unchanged, @@ -4379,38 +4200,38 @@ DEFUN (neighbor_attr_unchanged, "Nexthop attribute\n" "Med attribute\n") { - int idx = 0; - char *peer = argv[1]->arg; - u_int16_t flags = 0; - - if (argv_find (argv, argc, "as-path", &idx)) - SET_FLAG (flags, PEER_FLAG_AS_PATH_UNCHANGED); - idx = 0; - if (argv_find (argv, argc, "next-hop", &idx)) - SET_FLAG (flags, PEER_FLAG_NEXTHOP_UNCHANGED); - idx = 0; - if (argv_find (argv, argc, "med", &idx)) - SET_FLAG (flags, PEER_FLAG_MED_UNCHANGED); - - if (!flags) // no flags means all of them! - { - SET_FLAG (flags, PEER_FLAG_AS_PATH_UNCHANGED); - SET_FLAG (flags, PEER_FLAG_NEXTHOP_UNCHANGED); - SET_FLAG (flags, PEER_FLAG_MED_UNCHANGED); - } - - return peer_af_flag_set_vty (vty, peer, bgp_node_afi (vty), bgp_node_safi (vty), flags); -} - -ALIAS_HIDDEN (neighbor_attr_unchanged, - neighbor_attr_unchanged_hidden_cmd, - "neighbor attribute-unchanged [{as-path|next-hop|med}]", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "BGP attribute is propagated unchanged to this neighbor\n" - "As-path attribute\n" - "Nexthop attribute\n" - "Med attribute\n") + int idx = 0; + char *peer = argv[1]->arg; + u_int16_t flags = 0; + + if (argv_find(argv, argc, "as-path", &idx)) + SET_FLAG(flags, PEER_FLAG_AS_PATH_UNCHANGED); + idx = 0; + if (argv_find(argv, argc, "next-hop", &idx)) + SET_FLAG(flags, PEER_FLAG_NEXTHOP_UNCHANGED); + idx = 0; + if (argv_find(argv, argc, "med", &idx)) + SET_FLAG(flags, PEER_FLAG_MED_UNCHANGED); + + if (!flags) // no flags means all of them! + { + SET_FLAG(flags, PEER_FLAG_AS_PATH_UNCHANGED); + SET_FLAG(flags, PEER_FLAG_NEXTHOP_UNCHANGED); + SET_FLAG(flags, PEER_FLAG_MED_UNCHANGED); + } + + return peer_af_flag_set_vty(vty, peer, bgp_node_afi(vty), + bgp_node_safi(vty), flags); +} + +ALIAS_HIDDEN( + neighbor_attr_unchanged, neighbor_attr_unchanged_hidden_cmd, + "neighbor attribute-unchanged [{as-path|next-hop|med}]", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "BGP attribute is propagated unchanged to this neighbor\n" + "As-path attribute\n" + "Nexthop attribute\n" + "Med attribute\n") DEFUN (no_neighbor_attr_unchanged, no_neighbor_attr_unchanged_cmd, @@ -4423,73 +4244,70 @@ DEFUN (no_neighbor_attr_unchanged, "Nexthop attribute\n" "Med attribute\n") { - int idx = 0; - char *peer = argv[2]->arg; - u_int16_t flags = 0; - - if (argv_find (argv, argc, "as-path", &idx)) - SET_FLAG (flags, PEER_FLAG_AS_PATH_UNCHANGED); - idx = 0; - if (argv_find (argv, argc, "next-hop", &idx)) - SET_FLAG (flags, PEER_FLAG_NEXTHOP_UNCHANGED); - idx = 0; - if (argv_find (argv, argc, "med", &idx)) - SET_FLAG (flags, PEER_FLAG_MED_UNCHANGED); - - if (!flags) // no flags means all of them! - { - SET_FLAG (flags, PEER_FLAG_AS_PATH_UNCHANGED); - SET_FLAG (flags, PEER_FLAG_NEXTHOP_UNCHANGED); - SET_FLAG (flags, PEER_FLAG_MED_UNCHANGED); - } - - return peer_af_flag_unset_vty (vty, peer, bgp_node_afi (vty), bgp_node_safi (vty), flags); -} - -ALIAS_HIDDEN (no_neighbor_attr_unchanged, - no_neighbor_attr_unchanged_hidden_cmd, - "no neighbor attribute-unchanged [{as-path|next-hop|med}]", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "BGP attribute is propagated unchanged to this neighbor\n" - "As-path attribute\n" - "Nexthop attribute\n" - "Med attribute\n") + int idx = 0; + char *peer = argv[2]->arg; + u_int16_t flags = 0; + + if (argv_find(argv, argc, "as-path", &idx)) + SET_FLAG(flags, PEER_FLAG_AS_PATH_UNCHANGED); + idx = 0; + if (argv_find(argv, argc, "next-hop", &idx)) + SET_FLAG(flags, PEER_FLAG_NEXTHOP_UNCHANGED); + idx = 0; + if (argv_find(argv, argc, "med", &idx)) + SET_FLAG(flags, PEER_FLAG_MED_UNCHANGED); + + if (!flags) // no flags means all of them! + { + SET_FLAG(flags, PEER_FLAG_AS_PATH_UNCHANGED); + SET_FLAG(flags, PEER_FLAG_NEXTHOP_UNCHANGED); + SET_FLAG(flags, PEER_FLAG_MED_UNCHANGED); + } + + return peer_af_flag_unset_vty(vty, peer, bgp_node_afi(vty), + bgp_node_safi(vty), flags); +} + +ALIAS_HIDDEN( + no_neighbor_attr_unchanged, no_neighbor_attr_unchanged_hidden_cmd, + "no neighbor attribute-unchanged [{as-path|next-hop|med}]", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "BGP attribute is propagated unchanged to this neighbor\n" + "As-path attribute\n" + "Nexthop attribute\n" + "Med attribute\n") /* EBGP multihop configuration. */ -static int -peer_ebgp_multihop_set_vty (struct vty *vty, const char *ip_str, - const char *ttl_str) +static int peer_ebgp_multihop_set_vty(struct vty *vty, const char *ip_str, + const char *ttl_str) { - struct peer *peer; - unsigned int ttl; + struct peer *peer; + unsigned int ttl; - peer = peer_and_group_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - if (peer->conf_if) - return bgp_vty_return (vty, BGP_ERR_INVALID_FOR_DIRECT_PEER); + if (peer->conf_if) + return bgp_vty_return(vty, BGP_ERR_INVALID_FOR_DIRECT_PEER); - if (! ttl_str) - ttl = MAXTTL; - else - ttl = strtoul(ttl_str, NULL, 10); + if (!ttl_str) + ttl = MAXTTL; + else + ttl = strtoul(ttl_str, NULL, 10); - return bgp_vty_return (vty, peer_ebgp_multihop_set (peer, ttl)); + return bgp_vty_return(vty, peer_ebgp_multihop_set(peer, ttl)); } -static int -peer_ebgp_multihop_unset_vty (struct vty *vty, const char *ip_str) +static int peer_ebgp_multihop_unset_vty(struct vty *vty, const char *ip_str) { - struct peer *peer; + struct peer *peer; - peer = peer_and_group_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - return bgp_vty_return (vty, peer_ebgp_multihop_unset (peer)); + return bgp_vty_return(vty, peer_ebgp_multihop_unset(peer)); } /* neighbor ebgp-multihop. */ @@ -4500,8 +4318,8 @@ DEFUN (neighbor_ebgp_multihop, NEIGHBOR_ADDR_STR2 "Allow EBGP neighbors not on directly connected networks\n") { - int idx_peer = 1; - return peer_ebgp_multihop_set_vty (vty, argv[idx_peer]->arg, NULL); + int idx_peer = 1; + return peer_ebgp_multihop_set_vty(vty, argv[idx_peer]->arg, NULL); } DEFUN (neighbor_ebgp_multihop_ttl, @@ -4512,9 +4330,10 @@ DEFUN (neighbor_ebgp_multihop_ttl, "Allow EBGP neighbors not on directly connected networks\n" "maximum hop count\n") { - int idx_peer = 1; - int idx_number = 3; - return peer_ebgp_multihop_set_vty (vty, argv[idx_peer]->arg, argv[idx_number]->arg); + int idx_peer = 1; + int idx_number = 3; + return peer_ebgp_multihop_set_vty(vty, argv[idx_peer]->arg, + argv[idx_number]->arg); } DEFUN (no_neighbor_ebgp_multihop, @@ -4526,8 +4345,8 @@ DEFUN (no_neighbor_ebgp_multihop, "Allow EBGP neighbors not on directly connected networks\n" "maximum hop count\n") { - int idx_peer = 2; - return peer_ebgp_multihop_unset_vty (vty, argv[idx_peer]->arg); + int idx_peer = 2; + return peer_ebgp_multihop_unset_vty(vty, argv[idx_peer]->arg); } @@ -4540,8 +4359,9 @@ DEFUN (neighbor_disable_connected_check, "one-hop away EBGP peer using loopback address\n" "Enforce EBGP neighbors perform multihop\n") { - int idx_peer = 1; - return peer_flag_set_vty (vty, argv[idx_peer]->arg, PEER_FLAG_DISABLE_CONNECTED_CHECK); + int idx_peer = 1; + return peer_flag_set_vty(vty, argv[idx_peer]->arg, + PEER_FLAG_DISABLE_CONNECTED_CHECK); } DEFUN (no_neighbor_disable_connected_check, @@ -4553,8 +4373,9 @@ DEFUN (no_neighbor_disable_connected_check, "one-hop away EBGP peer using loopback address\n" "Enforce EBGP neighbors perform multihop\n") { - int idx_peer = 2; - return peer_flag_unset_vty (vty, argv[idx_peer]->arg, PEER_FLAG_DISABLE_CONNECTED_CHECK); + int idx_peer = 2; + return peer_flag_unset_vty(vty, argv[idx_peer]->arg, + PEER_FLAG_DISABLE_CONNECTED_CHECK); } DEFUN (neighbor_description, @@ -4565,22 +4386,22 @@ DEFUN (neighbor_description, "Neighbor specific description\n" "Up to 80 characters describing this neighbor\n") { - int idx_peer = 1; - int idx_line = 3; - struct peer *peer; - char *str; + int idx_peer = 1; + int idx_line = 3; + struct peer *peer; + char *str; - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - str = argv_concat(argv, argc, idx_line); + str = argv_concat(argv, argc, idx_line); - peer_description_set (peer, str); + peer_description_set(peer, str); - XFREE (MTYPE_TMP, str); + XFREE(MTYPE_TMP, str); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_neighbor_description, @@ -4592,62 +4413,57 @@ DEFUN (no_neighbor_description, "Neighbor specific description\n" "Up to 80 characters describing this neighbor\n") { - int idx_peer = 2; - struct peer *peer; + int idx_peer = 2; + struct peer *peer; - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - peer_description_unset (peer); + peer_description_unset(peer); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Neighbor update-source. */ -static int -peer_update_source_vty (struct vty *vty, const char *peer_str, - const char *source_str) -{ - struct peer *peer; - struct prefix p; - - peer = peer_and_group_lookup_vty (vty, peer_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; - - if (peer->conf_if) - return CMD_WARNING; - - if (source_str) - { - union sockunion su; - int ret = str2sockunion (source_str, &su); - - if (ret == 0) - peer_update_source_addr_set (peer, &su); - else - { - if (str2prefix (source_str, &p)) - { - vty_out (vty, "%% Invalid update-source, remove prefix length \n"); - return CMD_WARNING_CONFIG_FAILED; - } - else - peer_update_source_if_set (peer, source_str); - } - } - else - peer_update_source_unset (peer); - - return CMD_SUCCESS; -} - -#define BGP_UPDATE_SOURCE_HELP_STR \ - "IPv4 address\n" \ - "IPv6 address\n" \ - "Interface name (requires zebra to be running)\n" +static int peer_update_source_vty(struct vty *vty, const char *peer_str, + const char *source_str) +{ + struct peer *peer; + struct prefix p; + + peer = peer_and_group_lookup_vty(vty, peer_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; + + if (peer->conf_if) + return CMD_WARNING; + + if (source_str) { + union sockunion su; + int ret = str2sockunion(source_str, &su); + + if (ret == 0) + peer_update_source_addr_set(peer, &su); + else { + if (str2prefix(source_str, &p)) { + vty_out(vty, + "%% Invalid update-source, remove prefix length \n"); + return CMD_WARNING_CONFIG_FAILED; + } else + peer_update_source_if_set(peer, source_str); + } + } else + peer_update_source_unset(peer); + + return CMD_SUCCESS; +} + +#define BGP_UPDATE_SOURCE_HELP_STR \ + "IPv4 address\n" \ + "IPv6 address\n" \ + "Interface name (requires zebra to be running)\n" DEFUN (neighbor_update_source, neighbor_update_source_cmd, @@ -4657,9 +4473,10 @@ DEFUN (neighbor_update_source, "Source of routing updates\n" BGP_UPDATE_SOURCE_HELP_STR) { - int idx_peer = 1; - int idx_peer_2 = 3; - return peer_update_source_vty (vty, argv[idx_peer]->arg, argv[idx_peer_2]->arg); + int idx_peer = 1; + int idx_peer_2 = 3; + return peer_update_source_vty(vty, argv[idx_peer]->arg, + argv[idx_peer_2]->arg); } DEFUN (no_neighbor_update_source, @@ -4671,28 +4488,27 @@ DEFUN (no_neighbor_update_source, "Source of routing updates\n" BGP_UPDATE_SOURCE_HELP_STR) { - int idx_peer = 2; - return peer_update_source_vty (vty, argv[idx_peer]->arg, NULL); + int idx_peer = 2; + return peer_update_source_vty(vty, argv[idx_peer]->arg, NULL); } -static int -peer_default_originate_set_vty (struct vty *vty, const char *peer_str, - afi_t afi, safi_t safi, - const char *rmap, int set) +static int peer_default_originate_set_vty(struct vty *vty, const char *peer_str, + afi_t afi, safi_t safi, + const char *rmap, int set) { - int ret; - struct peer *peer; + int ret; + struct peer *peer; - peer = peer_and_group_lookup_vty (vty, peer_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, peer_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - if (set) - ret = peer_default_originate_set (peer, afi, safi, rmap); - else - ret = peer_default_originate_unset (peer, afi, safi); + if (set) + ret = peer_default_originate_set(peer, afi, safi, rmap); + else + ret = peer_default_originate_unset(peer, afi, safi); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } /* neighbor default-originate. */ @@ -4703,17 +4519,16 @@ DEFUN (neighbor_default_originate, NEIGHBOR_ADDR_STR2 "Originate default route to this neighbor\n") { - int idx_peer = 1; - return peer_default_originate_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), NULL, 1); + int idx_peer = 1; + return peer_default_originate_set_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), + bgp_node_safi(vty), NULL, 1); } -ALIAS_HIDDEN (neighbor_default_originate, - neighbor_default_originate_hidden_cmd, - "neighbor default-originate", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Originate default route to this neighbor\n") +ALIAS_HIDDEN(neighbor_default_originate, neighbor_default_originate_hidden_cmd, + "neighbor default-originate", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Originate default route to this neighbor\n") DEFUN (neighbor_default_originate_rmap, neighbor_default_originate_rmap_cmd, @@ -4724,20 +4539,21 @@ DEFUN (neighbor_default_originate_rmap, "Route-map to specify criteria to originate default\n" "route-map name\n") { - int idx_peer = 1; - int idx_word = 4; - return peer_default_originate_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), argv[idx_word]->arg, 1); + int idx_peer = 1; + int idx_word = 4; + return peer_default_originate_set_vty( + vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty), + argv[idx_word]->arg, 1); } -ALIAS_HIDDEN (neighbor_default_originate_rmap, - neighbor_default_originate_rmap_hidden_cmd, - "neighbor default-originate route-map WORD", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Originate default route to this neighbor\n" - "Route-map to specify criteria to originate default\n" - "route-map name\n") +ALIAS_HIDDEN( + neighbor_default_originate_rmap, + neighbor_default_originate_rmap_hidden_cmd, + "neighbor default-originate route-map WORD", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Originate default route to this neighbor\n" + "Route-map to specify criteria to originate default\n" + "route-map name\n") DEFUN (no_neighbor_default_originate, no_neighbor_default_originate_cmd, @@ -4749,48 +4565,43 @@ DEFUN (no_neighbor_default_originate, "Route-map to specify criteria to originate default\n" "route-map name\n") { - int idx_peer = 2; - return peer_default_originate_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), NULL, 0); + int idx_peer = 2; + return peer_default_originate_set_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), + bgp_node_safi(vty), NULL, 0); } -ALIAS_HIDDEN (no_neighbor_default_originate, - no_neighbor_default_originate_hidden_cmd, - "no neighbor default-originate [route-map WORD]", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Originate default route to this neighbor\n" - "Route-map to specify criteria to originate default\n" - "route-map name\n") +ALIAS_HIDDEN( + no_neighbor_default_originate, no_neighbor_default_originate_hidden_cmd, + "no neighbor default-originate [route-map WORD]", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Originate default route to this neighbor\n" + "Route-map to specify criteria to originate default\n" + "route-map name\n") /* Set neighbor's BGP port. */ -static int -peer_port_vty (struct vty *vty, const char *ip_str, int afi, - const char *port_str) -{ - struct peer *peer; - u_int16_t port; - struct servent *sp; - - peer = peer_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; - - if (! port_str) - { - sp = getservbyname ("bgp", "tcp"); - port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port); - } - else - { - port = strtoul(port_str, NULL, 10); - } +static int peer_port_vty(struct vty *vty, const char *ip_str, int afi, + const char *port_str) +{ + struct peer *peer; + u_int16_t port; + struct servent *sp; + + peer = peer_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; + + if (!port_str) { + sp = getservbyname("bgp", "tcp"); + port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs(sp->s_port); + } else { + port = strtoul(port_str, NULL, 10); + } - peer_port_set (peer, port); + peer_port_set(peer, port); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Set specified peer's BGP port. */ @@ -4802,9 +4613,10 @@ DEFUN (neighbor_port, "Neighbor's BGP port\n" "TCP port number\n") { - int idx_ip = 1; - int idx_number = 3; - return peer_port_vty (vty, argv[idx_ip]->arg, AFI_IP, argv[idx_number]->arg); + int idx_ip = 1; + int idx_number = 3; + return peer_port_vty(vty, argv[idx_ip]->arg, AFI_IP, + argv[idx_number]->arg); } DEFUN (no_neighbor_port, @@ -4816,44 +4628,41 @@ DEFUN (no_neighbor_port, "Neighbor's BGP port\n" "TCP port number\n") { - int idx_ip = 2; - return peer_port_vty (vty, argv[idx_ip]->arg, AFI_IP, NULL); + int idx_ip = 2; + return peer_port_vty(vty, argv[idx_ip]->arg, AFI_IP, NULL); } /* neighbor weight. */ -static int -peer_weight_set_vty (struct vty *vty, const char *ip_str, - afi_t afi, safi_t safi, - const char *weight_str) +static int peer_weight_set_vty(struct vty *vty, const char *ip_str, afi_t afi, + safi_t safi, const char *weight_str) { - int ret; - struct peer *peer; - unsigned long weight; + int ret; + struct peer *peer; + unsigned long weight; - peer = peer_and_group_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - weight = strtoul(weight_str, NULL, 10); + weight = strtoul(weight_str, NULL, 10); - ret = peer_weight_set (peer, afi, safi, weight); - return bgp_vty_return (vty, ret); + ret = peer_weight_set(peer, afi, safi, weight); + return bgp_vty_return(vty, ret); } -static int -peer_weight_unset_vty (struct vty *vty, const char *ip_str, - afi_t afi, safi_t safi) +static int peer_weight_unset_vty(struct vty *vty, const char *ip_str, afi_t afi, + safi_t safi) { - int ret; - struct peer *peer; + int ret; + struct peer *peer; - peer = peer_and_group_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - ret = peer_weight_unset (peer, afi, safi); - return bgp_vty_return (vty, ret); + ret = peer_weight_unset(peer, afi, safi); + return bgp_vty_return(vty, ret); } DEFUN (neighbor_weight, @@ -4864,22 +4673,17 @@ DEFUN (neighbor_weight, "Set default weight for routes from this neighbor\n" "default weight\n") { - int idx_peer = 1; - int idx_number = 3; - return peer_weight_set_vty (vty, - argv[idx_peer]->arg, - bgp_node_afi (vty), - bgp_node_safi (vty), - argv[idx_number]->arg); + int idx_peer = 1; + int idx_number = 3; + return peer_weight_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), argv[idx_number]->arg); } -ALIAS_HIDDEN (neighbor_weight, - neighbor_weight_hidden_cmd, - "neighbor weight (0-65535)", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Set default weight for routes from this neighbor\n" - "default weight\n") +ALIAS_HIDDEN(neighbor_weight, neighbor_weight_hidden_cmd, + "neighbor weight (0-65535)", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Set default weight for routes from this neighbor\n" + "default weight\n") DEFUN (no_neighbor_weight, no_neighbor_weight_cmd, @@ -4890,18 +4694,16 @@ DEFUN (no_neighbor_weight, "Set default weight for routes from this neighbor\n" "default weight\n") { - int idx_peer = 2; - return peer_weight_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), bgp_node_safi (vty)); + int idx_peer = 2; + return peer_weight_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), bgp_node_safi(vty)); } -ALIAS_HIDDEN (no_neighbor_weight, - no_neighbor_weight_hidden_cmd, - "no neighbor weight [(0-65535)]", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Set default weight for routes from this neighbor\n" - "default weight\n") +ALIAS_HIDDEN(no_neighbor_weight, no_neighbor_weight_hidden_cmd, + "no neighbor weight [(0-65535)]", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Set default weight for routes from this neighbor\n" + "default weight\n") /* Override capability negotiation. */ @@ -4912,8 +4714,9 @@ DEFUN (neighbor_override_capability, NEIGHBOR_ADDR_STR2 "Override capability negotiation result\n") { - int idx_peer = 1; - return peer_flag_set_vty (vty, argv[idx_peer]->arg, PEER_FLAG_OVERRIDE_CAPABILITY); + int idx_peer = 1; + return peer_flag_set_vty(vty, argv[idx_peer]->arg, + PEER_FLAG_OVERRIDE_CAPABILITY); } DEFUN (no_neighbor_override_capability, @@ -4924,8 +4727,9 @@ DEFUN (no_neighbor_override_capability, NEIGHBOR_ADDR_STR2 "Override capability negotiation result\n") { - int idx_peer = 2; - return peer_flag_unset_vty (vty, argv[idx_peer]->arg, PEER_FLAG_OVERRIDE_CAPABILITY); + int idx_peer = 2; + return peer_flag_unset_vty(vty, argv[idx_peer]->arg, + PEER_FLAG_OVERRIDE_CAPABILITY); } DEFUN (neighbor_strict_capability, @@ -4935,8 +4739,9 @@ DEFUN (neighbor_strict_capability, NEIGHBOR_ADDR_STR "Strict capability negotiation match\n") { - int idx_ip = 1; - return peer_flag_set_vty (vty, argv[idx_ip]->arg, PEER_FLAG_STRICT_CAP_MATCH); + int idx_ip = 1; + return peer_flag_set_vty(vty, argv[idx_ip]->arg, + PEER_FLAG_STRICT_CAP_MATCH); } DEFUN (no_neighbor_strict_capability, @@ -4947,44 +4752,43 @@ DEFUN (no_neighbor_strict_capability, NEIGHBOR_ADDR_STR "Strict capability negotiation match\n") { - int idx_ip = 2; - return peer_flag_unset_vty (vty, argv[idx_ip]->arg, PEER_FLAG_STRICT_CAP_MATCH); + int idx_ip = 2; + return peer_flag_unset_vty(vty, argv[idx_ip]->arg, + PEER_FLAG_STRICT_CAP_MATCH); } -static int -peer_timers_set_vty (struct vty *vty, const char *ip_str, - const char *keep_str, const char *hold_str) +static int peer_timers_set_vty(struct vty *vty, const char *ip_str, + const char *keep_str, const char *hold_str) { - int ret; - struct peer *peer; - u_int32_t keepalive; - u_int32_t holdtime; + int ret; + struct peer *peer; + u_int32_t keepalive; + u_int32_t holdtime; - peer = peer_and_group_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - keepalive = strtoul(keep_str, NULL, 10); - holdtime = strtoul(hold_str, NULL, 10); + keepalive = strtoul(keep_str, NULL, 10); + holdtime = strtoul(hold_str, NULL, 10); - ret = peer_timers_set (peer, keepalive, holdtime); + ret = peer_timers_set(peer, keepalive, holdtime); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } -static int -peer_timers_unset_vty (struct vty *vty, const char *ip_str) +static int peer_timers_unset_vty(struct vty *vty, const char *ip_str) { - int ret; - struct peer *peer; + int ret; + struct peer *peer; - peer = peer_and_group_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - ret = peer_timers_unset (peer); + ret = peer_timers_unset(peer); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } DEFUN (neighbor_timers, @@ -4996,10 +4800,12 @@ DEFUN (neighbor_timers, "Keepalive interval\n" "Holdtime\n") { - int idx_peer = 1; - int idx_number = 3; - int idx_number_2 = 4; - return peer_timers_set_vty (vty, argv[idx_peer]->arg, argv[idx_number]->arg, argv[idx_number_2]->arg); + int idx_peer = 1; + int idx_number = 3; + int idx_number_2 = 4; + return peer_timers_set_vty(vty, argv[idx_peer]->arg, + argv[idx_number]->arg, + argv[idx_number_2]->arg); } DEFUN (no_neighbor_timers, @@ -5012,43 +4818,41 @@ DEFUN (no_neighbor_timers, "Keepalive interval\n" "Holdtime\n") { - int idx_peer = 2; - return peer_timers_unset_vty (vty, argv[idx_peer]->arg); + int idx_peer = 2; + return peer_timers_unset_vty(vty, argv[idx_peer]->arg); } -static int -peer_timers_connect_set_vty (struct vty *vty, const char *ip_str, - const char *time_str) +static int peer_timers_connect_set_vty(struct vty *vty, const char *ip_str, + const char *time_str) { - int ret; - struct peer *peer; - u_int32_t connect; + int ret; + struct peer *peer; + u_int32_t connect; - peer = peer_and_group_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - connect = strtoul(time_str, NULL, 10); + connect = strtoul(time_str, NULL, 10); - ret = peer_timers_connect_set (peer, connect); + ret = peer_timers_connect_set(peer, connect); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } -static int -peer_timers_connect_unset_vty (struct vty *vty, const char *ip_str) +static int peer_timers_connect_unset_vty(struct vty *vty, const char *ip_str) { - int ret; - struct peer *peer; + int ret; + struct peer *peer; - peer = peer_and_group_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - ret = peer_timers_connect_unset (peer); + ret = peer_timers_connect_unset(peer); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } DEFUN (neighbor_timers_connect, @@ -5060,9 +4864,10 @@ DEFUN (neighbor_timers_connect, "BGP connect timer\n" "Connect timer\n") { - int idx_peer = 1; - int idx_number = 4; - return peer_timers_connect_set_vty (vty, argv[idx_peer]->arg, argv[idx_number]->arg); + int idx_peer = 1; + int idx_number = 4; + return peer_timers_connect_set_vty(vty, argv[idx_peer]->arg, + argv[idx_number]->arg); } DEFUN (no_neighbor_timers_connect, @@ -5075,32 +4880,31 @@ DEFUN (no_neighbor_timers_connect, "BGP connect timer\n" "Connect timer\n") { - int idx_peer = 2; - return peer_timers_connect_unset_vty (vty, argv[idx_peer]->arg); + int idx_peer = 2; + return peer_timers_connect_unset_vty(vty, argv[idx_peer]->arg); } -static int -peer_advertise_interval_vty (struct vty *vty, const char *ip_str, - const char *time_str, int set) +static int peer_advertise_interval_vty(struct vty *vty, const char *ip_str, + const char *time_str, int set) { - int ret; - struct peer *peer; - u_int32_t routeadv = 0; + int ret; + struct peer *peer; + u_int32_t routeadv = 0; - peer = peer_and_group_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - if (time_str) - routeadv = strtoul(time_str, NULL, 10); + if (time_str) + routeadv = strtoul(time_str, NULL, 10); - if (set) - ret = peer_advertise_interval_set (peer, routeadv); - else - ret = peer_advertise_interval_unset (peer); + if (set) + ret = peer_advertise_interval_set(peer, routeadv); + else + ret = peer_advertise_interval_unset(peer); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } DEFUN (neighbor_advertise_interval, @@ -5111,9 +4915,10 @@ DEFUN (neighbor_advertise_interval, "Minimum interval between sending BGP routing updates\n" "time in seconds\n") { - int idx_peer = 1; - int idx_number = 3; - return peer_advertise_interval_vty (vty, argv[idx_peer]->arg, argv[idx_number]->arg, 1); + int idx_peer = 1; + int idx_number = 3; + return peer_advertise_interval_vty(vty, argv[idx_peer]->arg, + argv[idx_number]->arg, 1); } DEFUN (no_neighbor_advertise_interval, @@ -5125,8 +4930,8 @@ DEFUN (no_neighbor_advertise_interval, "Minimum interval between sending BGP routing updates\n" "time in seconds\n") { - int idx_peer = 2; - return peer_advertise_interval_vty (vty, argv[idx_peer]->arg, NULL, 0); + int idx_peer = 2; + return peer_advertise_interval_vty(vty, argv[idx_peer]->arg, NULL, 0); } @@ -5139,29 +4944,28 @@ DEFUN (bgp_set_route_map_delay_timer, "Time in secs to wait before processing route-map changes\n" "0 disables the timer, no route updates happen when route-maps change\n") { - int idx_number = 3; - u_int32_t rmap_delay_timer; - - if (argv[idx_number]->arg) - { - rmap_delay_timer = strtoul(argv[idx_number]->arg, NULL, 10); - bm->rmap_update_timer = rmap_delay_timer; - - /* if the dynamic update handling is being disabled, and a timer is - * running, stop the timer and act as if the timer has already fired. - */ - if (!rmap_delay_timer && bm->t_rmap_update ) - { - BGP_TIMER_OFF(bm->t_rmap_update); - thread_execute (bm->master, bgp_route_map_update_timer, NULL, 0); + int idx_number = 3; + u_int32_t rmap_delay_timer; + + if (argv[idx_number]->arg) { + rmap_delay_timer = strtoul(argv[idx_number]->arg, NULL, 10); + bm->rmap_update_timer = rmap_delay_timer; + + /* if the dynamic update handling is being disabled, and a timer + * is + * running, stop the timer and act as if the timer has already + * fired. + */ + if (!rmap_delay_timer && bm->t_rmap_update) { + BGP_TIMER_OFF(bm->t_rmap_update); + thread_execute(bm->master, bgp_route_map_update_timer, + NULL, 0); + } + return CMD_SUCCESS; + } else { + vty_out(vty, "%% BGP invalid route-map delay-timer\n"); + return CMD_WARNING_CONFIG_FAILED; } - return CMD_SUCCESS; - } - else - { - vty_out (vty, "%% BGP invalid route-map delay-timer\n"); - return CMD_WARNING_CONFIG_FAILED; - } } DEFUN (no_bgp_set_route_map_delay_timer, @@ -5174,31 +4978,30 @@ DEFUN (no_bgp_set_route_map_delay_timer, "0 disables the timer, no route updates happen when route-maps change\n") { - bm->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER; + bm->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER; - return CMD_SUCCESS; + return CMD_SUCCESS; } /* neighbor interface */ -static int -peer_interface_vty (struct vty *vty, const char *ip_str, const char *str) +static int peer_interface_vty(struct vty *vty, const char *ip_str, + const char *str) { - struct peer *peer; + struct peer *peer; - peer = peer_lookup_vty (vty, ip_str); - if (! peer || peer->conf_if) - { - vty_out (vty, "%% BGP invalid peer %s\n", ip_str); - return CMD_WARNING_CONFIG_FAILED; - } + peer = peer_lookup_vty(vty, ip_str); + if (!peer || peer->conf_if) { + vty_out(vty, "%% BGP invalid peer %s\n", ip_str); + return CMD_WARNING_CONFIG_FAILED; + } - if (str) - peer_interface_set (peer, str); - else - peer_interface_unset (peer); + if (str) + peer_interface_set(peer, str); + else + peer_interface_unset(peer); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (neighbor_interface, @@ -5209,9 +5012,9 @@ DEFUN (neighbor_interface, "Interface\n" "Interface name\n") { - int idx_ip = 1; - int idx_word = 3; - return peer_interface_vty (vty, argv[idx_ip]->arg, argv[idx_word]->arg); + int idx_ip = 1; + int idx_word = 3; + return peer_interface_vty(vty, argv[idx_ip]->arg, argv[idx_word]->arg); } DEFUN (no_neighbor_interface, @@ -5223,8 +5026,8 @@ DEFUN (no_neighbor_interface, "Interface\n" "Interface name\n") { - int idx_peer = 2; - return peer_interface_vty (vty, argv[idx_peer]->arg, NULL); + int idx_peer = 2; + return peer_interface_vty(vty, argv[idx_peer]->arg, NULL); } DEFUN (neighbor_distribute_list, @@ -5239,37 +5042,37 @@ DEFUN (neighbor_distribute_list, "Filter incoming updates\n" "Filter outgoing updates\n") { - int idx_peer = 1; - int idx_acl = 3; - int direct, ret; - struct peer *peer; + int idx_peer = 1; + int idx_acl = 3; + int direct, ret; + struct peer *peer; - const char *pstr = argv[idx_peer]->arg; - const char *acl = argv[idx_acl]->arg; - const char *inout = argv[argc-1]->text; + const char *pstr = argv[idx_peer]->arg; + const char *acl = argv[idx_acl]->arg; + const char *inout = argv[argc - 1]->text; - peer = peer_and_group_lookup_vty (vty, pstr); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, pstr); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - /* Check filter direction. */ - direct = strmatch (inout, "in") ? FILTER_IN : FILTER_OUT; - ret = peer_distribute_set (peer, bgp_node_afi (vty), bgp_node_safi (vty), direct, acl); + /* Check filter direction. */ + direct = strmatch(inout, "in") ? FILTER_IN : FILTER_OUT; + ret = peer_distribute_set(peer, bgp_node_afi(vty), bgp_node_safi(vty), + direct, acl); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } -ALIAS_HIDDEN (neighbor_distribute_list, - neighbor_distribute_list_hidden_cmd, - "neighbor distribute-list <(1-199)|(1300-2699)|WORD> ", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Filter updates to/from this neighbor\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" - "IP Access-list name\n" - "Filter incoming updates\n" - "Filter outgoing updates\n") +ALIAS_HIDDEN( + neighbor_distribute_list, neighbor_distribute_list_hidden_cmd, + "neighbor distribute-list <(1-199)|(1300-2699)|WORD> ", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Filter updates to/from this neighbor\n" + "IP access-list number\n" + "IP access-list number (expanded range)\n" + "IP Access-list name\n" + "Filter incoming updates\n" + "Filter outgoing updates\n") DEFUN (no_neighbor_distribute_list, no_neighbor_distribute_list_cmd, @@ -5284,83 +5087,82 @@ DEFUN (no_neighbor_distribute_list, "Filter incoming updates\n" "Filter outgoing updates\n") { - int idx_peer = 2; - int direct, ret; - struct peer *peer; + int idx_peer = 2; + int direct, ret; + struct peer *peer; - const char *pstr = argv[idx_peer]->arg; - const char *inout = argv[argc-1]->text; + const char *pstr = argv[idx_peer]->arg; + const char *inout = argv[argc - 1]->text; - peer = peer_and_group_lookup_vty (vty, pstr); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, pstr); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - /* Check filter direction. */ - direct = strmatch (inout, "in") ? FILTER_IN : FILTER_OUT; - ret = peer_distribute_unset (peer, bgp_node_afi (vty), bgp_node_safi (vty), direct); + /* Check filter direction. */ + direct = strmatch(inout, "in") ? FILTER_IN : FILTER_OUT; + ret = peer_distribute_unset(peer, bgp_node_afi(vty), bgp_node_safi(vty), + direct); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } -ALIAS_HIDDEN (no_neighbor_distribute_list, - no_neighbor_distribute_list_hidden_cmd, - "no neighbor distribute-list <(1-199)|(1300-2699)|WORD> ", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Filter updates to/from this neighbor\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" - "IP Access-list name\n" - "Filter incoming updates\n" - "Filter outgoing updates\n") +ALIAS_HIDDEN( + no_neighbor_distribute_list, no_neighbor_distribute_list_hidden_cmd, + "no neighbor distribute-list <(1-199)|(1300-2699)|WORD> ", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Filter updates to/from this neighbor\n" + "IP access-list number\n" + "IP access-list number (expanded range)\n" + "IP Access-list name\n" + "Filter incoming updates\n" + "Filter outgoing updates\n") /* Set prefix list to the peer. */ -static int -peer_prefix_list_set_vty (struct vty *vty, const char *ip_str, afi_t afi, - safi_t safi, const char *name_str, - const char *direct_str) +static int peer_prefix_list_set_vty(struct vty *vty, const char *ip_str, + afi_t afi, safi_t safi, + const char *name_str, + const char *direct_str) { - int ret; - struct peer *peer; - int direct = FILTER_IN; + int ret; + struct peer *peer; + int direct = FILTER_IN; - peer = peer_and_group_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - /* Check filter direction. */ - if (strncmp (direct_str, "i", 1) == 0) - direct = FILTER_IN; - else if (strncmp (direct_str, "o", 1) == 0) - direct = FILTER_OUT; + /* Check filter direction. */ + if (strncmp(direct_str, "i", 1) == 0) + direct = FILTER_IN; + else if (strncmp(direct_str, "o", 1) == 0) + direct = FILTER_OUT; - ret = peer_prefix_list_set (peer, afi, safi, direct, name_str); + ret = peer_prefix_list_set(peer, afi, safi, direct, name_str); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } -static int -peer_prefix_list_unset_vty (struct vty *vty, const char *ip_str, afi_t afi, - safi_t safi, const char *direct_str) +static int peer_prefix_list_unset_vty(struct vty *vty, const char *ip_str, + afi_t afi, safi_t safi, + const char *direct_str) { - int ret; - struct peer *peer; - int direct = FILTER_IN; + int ret; + struct peer *peer; + int direct = FILTER_IN; - peer = peer_and_group_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - /* Check filter direction. */ - if (strncmp (direct_str, "i", 1) == 0) - direct = FILTER_IN; - else if (strncmp (direct_str, "o", 1) == 0) - direct = FILTER_OUT; + /* Check filter direction. */ + if (strncmp(direct_str, "i", 1) == 0) + direct = FILTER_IN; + else if (strncmp(direct_str, "o", 1) == 0) + direct = FILTER_OUT; - ret = peer_prefix_list_unset (peer, afi, safi, direct); + ret = peer_prefix_list_unset(peer, afi, safi, direct); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } DEFUN (neighbor_prefix_list, @@ -5373,22 +5175,21 @@ DEFUN (neighbor_prefix_list, "Filter incoming updates\n" "Filter outgoing updates\n") { - int idx_peer = 1; - int idx_word = 3; - int idx_in_out = 4; - return peer_prefix_list_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), argv[idx_word]->arg, argv[idx_in_out]->arg); + int idx_peer = 1; + int idx_word = 3; + int idx_in_out = 4; + return peer_prefix_list_set_vty( + vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty), + argv[idx_word]->arg, argv[idx_in_out]->arg); } -ALIAS_HIDDEN (neighbor_prefix_list, - neighbor_prefix_list_hidden_cmd, - "neighbor prefix-list WORD ", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Filter updates to/from this neighbor\n" - "Name of a prefix list\n" - "Filter incoming updates\n" - "Filter outgoing updates\n") +ALIAS_HIDDEN(neighbor_prefix_list, neighbor_prefix_list_hidden_cmd, + "neighbor prefix-list WORD ", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Filter updates to/from this neighbor\n" + "Name of a prefix list\n" + "Filter incoming updates\n" + "Filter outgoing updates\n") DEFUN (no_neighbor_prefix_list, no_neighbor_prefix_list_cmd, @@ -5401,69 +5202,64 @@ DEFUN (no_neighbor_prefix_list, "Filter incoming updates\n" "Filter outgoing updates\n") { - int idx_peer = 2; - int idx_in_out = 5; - return peer_prefix_list_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), argv[idx_in_out]->arg); + int idx_peer = 2; + int idx_in_out = 5; + return peer_prefix_list_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), bgp_node_safi(vty), + argv[idx_in_out]->arg); } -ALIAS_HIDDEN (no_neighbor_prefix_list, - no_neighbor_prefix_list_hidden_cmd, - "no neighbor prefix-list WORD ", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Filter updates to/from this neighbor\n" - "Name of a prefix list\n" - "Filter incoming updates\n" - "Filter outgoing updates\n") +ALIAS_HIDDEN(no_neighbor_prefix_list, no_neighbor_prefix_list_hidden_cmd, + "no neighbor prefix-list WORD ", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Filter updates to/from this neighbor\n" + "Name of a prefix list\n" + "Filter incoming updates\n" + "Filter outgoing updates\n") -static int -peer_aslist_set_vty (struct vty *vty, const char *ip_str, - afi_t afi, safi_t safi, - const char *name_str, const char *direct_str) +static int peer_aslist_set_vty(struct vty *vty, const char *ip_str, afi_t afi, + safi_t safi, const char *name_str, + const char *direct_str) { - int ret; - struct peer *peer; - int direct = FILTER_IN; + int ret; + struct peer *peer; + int direct = FILTER_IN; - peer = peer_and_group_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - /* Check filter direction. */ - if (strncmp (direct_str, "i", 1) == 0) - direct = FILTER_IN; - else if (strncmp (direct_str, "o", 1) == 0) - direct = FILTER_OUT; + /* Check filter direction. */ + if (strncmp(direct_str, "i", 1) == 0) + direct = FILTER_IN; + else if (strncmp(direct_str, "o", 1) == 0) + direct = FILTER_OUT; - ret = peer_aslist_set (peer, afi, safi, direct, name_str); + ret = peer_aslist_set(peer, afi, safi, direct, name_str); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } -static int -peer_aslist_unset_vty (struct vty *vty, const char *ip_str, - afi_t afi, safi_t safi, - const char *direct_str) +static int peer_aslist_unset_vty(struct vty *vty, const char *ip_str, afi_t afi, + safi_t safi, const char *direct_str) { - int ret; - struct peer *peer; - int direct = FILTER_IN; + int ret; + struct peer *peer; + int direct = FILTER_IN; - peer = peer_and_group_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - /* Check filter direction. */ - if (strncmp (direct_str, "i", 1) == 0) - direct = FILTER_IN; - else if (strncmp (direct_str, "o", 1) == 0) - direct = FILTER_OUT; + /* Check filter direction. */ + if (strncmp(direct_str, "i", 1) == 0) + direct = FILTER_IN; + else if (strncmp(direct_str, "o", 1) == 0) + direct = FILTER_OUT; - ret = peer_aslist_unset (peer, afi, safi, direct); + ret = peer_aslist_unset(peer, afi, safi, direct); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } DEFUN (neighbor_filter_list, @@ -5476,22 +5272,21 @@ DEFUN (neighbor_filter_list, "Filter incoming routes\n" "Filter outgoing routes\n") { - int idx_peer = 1; - int idx_word = 3; - int idx_in_out = 4; - return peer_aslist_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), argv[idx_word]->arg, argv[idx_in_out]->arg); + int idx_peer = 1; + int idx_word = 3; + int idx_in_out = 4; + return peer_aslist_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), argv[idx_word]->arg, + argv[idx_in_out]->arg); } -ALIAS_HIDDEN (neighbor_filter_list, - neighbor_filter_list_hidden_cmd, - "neighbor filter-list WORD ", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Establish BGP filters\n" - "AS path access-list name\n" - "Filter incoming routes\n" - "Filter outgoing routes\n") +ALIAS_HIDDEN(neighbor_filter_list, neighbor_filter_list_hidden_cmd, + "neighbor filter-list WORD ", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Establish BGP filters\n" + "AS path access-list name\n" + "Filter incoming routes\n" + "Filter outgoing routes\n") DEFUN (no_neighbor_filter_list, no_neighbor_filter_list_cmd, @@ -5504,69 +5299,66 @@ DEFUN (no_neighbor_filter_list, "Filter incoming routes\n" "Filter outgoing routes\n") { - int idx_peer = 2; - int idx_in_out = 5; - return peer_aslist_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), argv[idx_in_out]->arg); + int idx_peer = 2; + int idx_in_out = 5; + return peer_aslist_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), bgp_node_safi(vty), + argv[idx_in_out]->arg); } -ALIAS_HIDDEN (no_neighbor_filter_list, - no_neighbor_filter_list_hidden_cmd, - "no neighbor filter-list WORD ", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Establish BGP filters\n" - "AS path access-list name\n" - "Filter incoming routes\n" - "Filter outgoing routes\n") +ALIAS_HIDDEN(no_neighbor_filter_list, no_neighbor_filter_list_hidden_cmd, + "no neighbor filter-list WORD ", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Establish BGP filters\n" + "AS path access-list name\n" + "Filter incoming routes\n" + "Filter outgoing routes\n") /* Set route-map to the peer. */ -static int -peer_route_map_set_vty (struct vty *vty, const char *ip_str, - afi_t afi, safi_t safi, - const char *name_str, const char *direct_str) +static int peer_route_map_set_vty(struct vty *vty, const char *ip_str, + afi_t afi, safi_t safi, const char *name_str, + const char *direct_str) { - int ret; - struct peer *peer; - int direct = RMAP_IN; + int ret; + struct peer *peer; + int direct = RMAP_IN; - peer = peer_and_group_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - /* Check filter direction. */ - if (strncmp (direct_str, "in", 2) == 0) - direct = RMAP_IN; - else if (strncmp (direct_str, "o", 1) == 0) - direct = RMAP_OUT; + /* Check filter direction. */ + if (strncmp(direct_str, "in", 2) == 0) + direct = RMAP_IN; + else if (strncmp(direct_str, "o", 1) == 0) + direct = RMAP_OUT; - ret = peer_route_map_set (peer, afi, safi, direct, name_str); + ret = peer_route_map_set(peer, afi, safi, direct, name_str); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } -static int -peer_route_map_unset_vty (struct vty *vty, const char *ip_str, afi_t afi, - safi_t safi, const char *direct_str) +static int peer_route_map_unset_vty(struct vty *vty, const char *ip_str, + afi_t afi, safi_t safi, + const char *direct_str) { - int ret; - struct peer *peer; - int direct = RMAP_IN; + int ret; + struct peer *peer; + int direct = RMAP_IN; - peer = peer_and_group_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - /* Check filter direction. */ - if (strncmp (direct_str, "in", 2) == 0) - direct = RMAP_IN; - else if (strncmp (direct_str, "o", 1) == 0) - direct = RMAP_OUT; + /* Check filter direction. */ + if (strncmp(direct_str, "in", 2) == 0) + direct = RMAP_IN; + else if (strncmp(direct_str, "o", 1) == 0) + direct = RMAP_OUT; - ret = peer_route_map_unset (peer, afi, safi, direct); + ret = peer_route_map_unset(peer, afi, safi, direct); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } DEFUN (neighbor_route_map, @@ -5579,22 +5371,21 @@ DEFUN (neighbor_route_map, "Apply map to incoming routes\n" "Apply map to outbound routes\n") { - int idx_peer = 1; - int idx_word = 3; - int idx_in_out = 4; - return peer_route_map_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), argv[idx_word]->arg, argv[idx_in_out]->arg); + int idx_peer = 1; + int idx_word = 3; + int idx_in_out = 4; + return peer_route_map_set_vty( + vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty), + argv[idx_word]->arg, argv[idx_in_out]->arg); } -ALIAS_HIDDEN (neighbor_route_map, - neighbor_route_map_hidden_cmd, - "neighbor route-map WORD ", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Apply route map to neighbor\n" - "Name of route map\n" - "Apply map to incoming routes\n" - "Apply map to outbound routes\n") +ALIAS_HIDDEN(neighbor_route_map, neighbor_route_map_hidden_cmd, + "neighbor route-map WORD ", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Apply route map to neighbor\n" + "Name of route map\n" + "Apply map to incoming routes\n" + "Apply map to outbound routes\n") DEFUN (no_neighbor_route_map, no_neighbor_route_map_cmd, @@ -5607,55 +5398,52 @@ DEFUN (no_neighbor_route_map, "Apply map to incoming routes\n" "Apply map to outbound routes\n") { - int idx_peer = 2; - int idx_in_out = 5; - return peer_route_map_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), argv[idx_in_out]->arg); + int idx_peer = 2; + int idx_in_out = 5; + return peer_route_map_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), bgp_node_safi(vty), + argv[idx_in_out]->arg); } -ALIAS_HIDDEN (no_neighbor_route_map, - no_neighbor_route_map_hidden_cmd, - "no neighbor route-map WORD ", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Apply route map to neighbor\n" - "Name of route map\n" - "Apply map to incoming routes\n" - "Apply map to outbound routes\n") +ALIAS_HIDDEN(no_neighbor_route_map, no_neighbor_route_map_hidden_cmd, + "no neighbor route-map WORD ", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Apply route map to neighbor\n" + "Name of route map\n" + "Apply map to incoming routes\n" + "Apply map to outbound routes\n") /* Set unsuppress-map to the peer. */ -static int -peer_unsuppress_map_set_vty (struct vty *vty, const char *ip_str, afi_t afi, - safi_t safi, const char *name_str) +static int peer_unsuppress_map_set_vty(struct vty *vty, const char *ip_str, + afi_t afi, safi_t safi, + const char *name_str) { - int ret; - struct peer *peer; + int ret; + struct peer *peer; - peer = peer_and_group_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - ret = peer_unsuppress_map_set (peer, afi, safi, name_str); + ret = peer_unsuppress_map_set(peer, afi, safi, name_str); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } /* Unset route-map from the peer. */ -static int -peer_unsuppress_map_unset_vty (struct vty *vty, const char *ip_str, afi_t afi, - safi_t safi) +static int peer_unsuppress_map_unset_vty(struct vty *vty, const char *ip_str, + afi_t afi, safi_t safi) { - int ret; - struct peer *peer; + int ret; + struct peer *peer; - peer = peer_and_group_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - ret = peer_unsuppress_map_unset (peer, afi, safi); + ret = peer_unsuppress_map_unset(peer, afi, safi); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } DEFUN (neighbor_unsuppress_map, @@ -5666,19 +5454,18 @@ DEFUN (neighbor_unsuppress_map, "Route-map to selectively unsuppress suppressed routes\n" "Name of route map\n") { - int idx_peer = 1; - int idx_word = 3; - return peer_unsuppress_map_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), argv[idx_word]->arg); + int idx_peer = 1; + int idx_word = 3; + return peer_unsuppress_map_set_vty( + vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty), + argv[idx_word]->arg); } -ALIAS_HIDDEN (neighbor_unsuppress_map, - neighbor_unsuppress_map_hidden_cmd, - "neighbor unsuppress-map WORD", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Route-map to selectively unsuppress suppressed routes\n" - "Name of route map\n") +ALIAS_HIDDEN(neighbor_unsuppress_map, neighbor_unsuppress_map_hidden_cmd, + "neighbor unsuppress-map WORD", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Route-map to selectively unsuppress suppressed routes\n" + "Name of route map\n") DEFUN (no_neighbor_unsuppress_map, no_neighbor_unsuppress_map_cmd, @@ -5689,66 +5476,64 @@ DEFUN (no_neighbor_unsuppress_map, "Route-map to selectively unsuppress suppressed routes\n" "Name of route map\n") { - int idx_peer = 2; - return peer_unsuppress_map_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty)); + int idx_peer = 2; + return peer_unsuppress_map_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), + bgp_node_safi(vty)); } -ALIAS_HIDDEN (no_neighbor_unsuppress_map, - no_neighbor_unsuppress_map_hidden_cmd, - "no neighbor unsuppress-map WORD", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Route-map to selectively unsuppress suppressed routes\n" - "Name of route map\n") +ALIAS_HIDDEN(no_neighbor_unsuppress_map, no_neighbor_unsuppress_map_hidden_cmd, + "no neighbor unsuppress-map WORD", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Route-map to selectively unsuppress suppressed routes\n" + "Name of route map\n") -static int -peer_maximum_prefix_set_vty (struct vty *vty, const char *ip_str, afi_t afi, - safi_t safi, const char *num_str, - const char *threshold_str, int warning, - const char *restart_str) +static int peer_maximum_prefix_set_vty(struct vty *vty, const char *ip_str, + afi_t afi, safi_t safi, + const char *num_str, + const char *threshold_str, int warning, + const char *restart_str) { - int ret; - struct peer *peer; - u_int32_t max; - u_char threshold; - u_int16_t restart; + int ret; + struct peer *peer; + u_int32_t max; + u_char threshold; + u_int16_t restart; - peer = peer_and_group_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - max = strtoul(num_str, NULL, 10); - if (threshold_str) - threshold = atoi (threshold_str); - else - threshold = MAXIMUM_PREFIX_THRESHOLD_DEFAULT; + max = strtoul(num_str, NULL, 10); + if (threshold_str) + threshold = atoi(threshold_str); + else + threshold = MAXIMUM_PREFIX_THRESHOLD_DEFAULT; - if (restart_str) - restart = atoi (restart_str); - else - restart = 0; + if (restart_str) + restart = atoi(restart_str); + else + restart = 0; - ret = peer_maximum_prefix_set (peer, afi, safi, max, threshold, warning, restart); + ret = peer_maximum_prefix_set(peer, afi, safi, max, threshold, warning, + restart); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } -static int -peer_maximum_prefix_unset_vty (struct vty *vty, const char *ip_str, afi_t afi, - safi_t safi) +static int peer_maximum_prefix_unset_vty(struct vty *vty, const char *ip_str, + afi_t afi, safi_t safi) { - int ret; - struct peer *peer; + int ret; + struct peer *peer; - peer = peer_and_group_lookup_vty (vty, ip_str); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, ip_str); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - ret = peer_maximum_prefix_unset (peer, afi, safi); + ret = peer_maximum_prefix_unset(peer, afi, safi); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } /* Maximum number of prefix configuration. prefix count is different @@ -5762,20 +5547,18 @@ DEFUN (neighbor_maximum_prefix, "Maximum number of prefix accept from this peer\n" "maximum no. of prefix limit\n") { - int idx_peer = 1; - int idx_number = 3; - return peer_maximum_prefix_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), argv[idx_number]->arg, NULL, 0, - NULL); + int idx_peer = 1; + int idx_number = 3; + return peer_maximum_prefix_set_vty( + vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty), + argv[idx_number]->arg, NULL, 0, NULL); } -ALIAS_HIDDEN (neighbor_maximum_prefix, - neighbor_maximum_prefix_hidden_cmd, - "neighbor maximum-prefix (1-4294967295)", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Maximum number of prefix accept from this peer\n" - "maximum no. of prefix limit\n") +ALIAS_HIDDEN(neighbor_maximum_prefix, neighbor_maximum_prefix_hidden_cmd, + "neighbor maximum-prefix (1-4294967295)", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Maximum number of prefix accept from this peer\n" + "maximum no. of prefix limit\n") DEFUN (neighbor_maximum_prefix_threshold, neighbor_maximum_prefix_threshold_cmd, @@ -5786,22 +5569,22 @@ DEFUN (neighbor_maximum_prefix_threshold, "maximum no. of prefix limit\n" "Threshold value (%) at which to generate a warning msg\n") { - int idx_peer = 1; - int idx_number = 3; - int idx_number_2 = 4; - return peer_maximum_prefix_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), argv[idx_number]->arg, argv[idx_number_2]->arg, 0, - NULL); + int idx_peer = 1; + int idx_number = 3; + int idx_number_2 = 4; + return peer_maximum_prefix_set_vty( + vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty), + argv[idx_number]->arg, argv[idx_number_2]->arg, 0, NULL); } -ALIAS_HIDDEN (neighbor_maximum_prefix_threshold, - neighbor_maximum_prefix_threshold_hidden_cmd, - "neighbor maximum-prefix (1-4294967295) (1-100)", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Maximum number of prefix accept from this peer\n" - "maximum no. of prefix limit\n" - "Threshold value (%) at which to generate a warning msg\n") +ALIAS_HIDDEN( + neighbor_maximum_prefix_threshold, + neighbor_maximum_prefix_threshold_hidden_cmd, + "neighbor maximum-prefix (1-4294967295) (1-100)", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Maximum number of prefix accept from this peer\n" + "maximum no. of prefix limit\n" + "Threshold value (%) at which to generate a warning msg\n") DEFUN (neighbor_maximum_prefix_warning, neighbor_maximum_prefix_warning_cmd, @@ -5812,21 +5595,21 @@ DEFUN (neighbor_maximum_prefix_warning, "maximum no. of prefix limit\n" "Only give warning message when limit is exceeded\n") { - int idx_peer = 1; - int idx_number = 3; - return peer_maximum_prefix_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), argv[idx_number]->arg, NULL, 1, - NULL); + int idx_peer = 1; + int idx_number = 3; + return peer_maximum_prefix_set_vty( + vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty), + argv[idx_number]->arg, NULL, 1, NULL); } -ALIAS_HIDDEN (neighbor_maximum_prefix_warning, - neighbor_maximum_prefix_warning_hidden_cmd, - "neighbor maximum-prefix (1-4294967295) warning-only", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Maximum number of prefix accept from this peer\n" - "maximum no. of prefix limit\n" - "Only give warning message when limit is exceeded\n") +ALIAS_HIDDEN( + neighbor_maximum_prefix_warning, + neighbor_maximum_prefix_warning_hidden_cmd, + "neighbor maximum-prefix (1-4294967295) warning-only", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Maximum number of prefix accept from this peer\n" + "maximum no. of prefix limit\n" + "Only give warning message when limit is exceeded\n") DEFUN (neighbor_maximum_prefix_threshold_warning, neighbor_maximum_prefix_threshold_warning_cmd, @@ -5838,22 +5621,23 @@ DEFUN (neighbor_maximum_prefix_threshold_warning, "Threshold value (%) at which to generate a warning msg\n" "Only give warning message when limit is exceeded\n") { - int idx_peer = 1; - int idx_number = 3; - int idx_number_2 = 4; - return peer_maximum_prefix_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), argv[idx_number]->arg, argv[idx_number_2]->arg, 1, NULL); + int idx_peer = 1; + int idx_number = 3; + int idx_number_2 = 4; + return peer_maximum_prefix_set_vty( + vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty), + argv[idx_number]->arg, argv[idx_number_2]->arg, 1, NULL); } -ALIAS_HIDDEN (neighbor_maximum_prefix_threshold_warning, - neighbor_maximum_prefix_threshold_warning_hidden_cmd, - "neighbor maximum-prefix (1-4294967295) (1-100) warning-only", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Maximum number of prefix accept from this peer\n" - "maximum no. of prefix limit\n" - "Threshold value (%) at which to generate a warning msg\n" - "Only give warning message when limit is exceeded\n") +ALIAS_HIDDEN( + neighbor_maximum_prefix_threshold_warning, + neighbor_maximum_prefix_threshold_warning_hidden_cmd, + "neighbor maximum-prefix (1-4294967295) (1-100) warning-only", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Maximum number of prefix accept from this peer\n" + "maximum no. of prefix limit\n" + "Threshold value (%) at which to generate a warning msg\n" + "Only give warning message when limit is exceeded\n") DEFUN (neighbor_maximum_prefix_restart, neighbor_maximum_prefix_restart_cmd, @@ -5865,22 +5649,23 @@ DEFUN (neighbor_maximum_prefix_restart, "Restart bgp connection after limit is exceeded\n" "Restart interval in minutes") { - int idx_peer = 1; - int idx_number = 3; - int idx_number_2 = 5; - return peer_maximum_prefix_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), argv[idx_number]->arg, NULL, 0, argv[idx_number_2]->arg); + int idx_peer = 1; + int idx_number = 3; + int idx_number_2 = 5; + return peer_maximum_prefix_set_vty( + vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty), + argv[idx_number]->arg, NULL, 0, argv[idx_number_2]->arg); } -ALIAS_HIDDEN (neighbor_maximum_prefix_restart, - neighbor_maximum_prefix_restart_hidden_cmd, - "neighbor maximum-prefix (1-4294967295) restart (1-65535)", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Maximum number of prefix accept from this peer\n" - "maximum no. of prefix limit\n" - "Restart bgp connection after limit is exceeded\n" - "Restart interval in minutes") +ALIAS_HIDDEN( + neighbor_maximum_prefix_restart, + neighbor_maximum_prefix_restart_hidden_cmd, + "neighbor maximum-prefix (1-4294967295) restart (1-65535)", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Maximum number of prefix accept from this peer\n" + "maximum no. of prefix limit\n" + "Restart bgp connection after limit is exceeded\n" + "Restart interval in minutes") DEFUN (neighbor_maximum_prefix_threshold_restart, neighbor_maximum_prefix_threshold_restart_cmd, @@ -5893,24 +5678,26 @@ DEFUN (neighbor_maximum_prefix_threshold_restart, "Restart bgp connection after limit is exceeded\n" "Restart interval in minutes\n") { - int idx_peer = 1; - int idx_number = 3; - int idx_number_2 = 4; - int idx_number_3 = 6; - return peer_maximum_prefix_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), argv[idx_number]->arg, argv[idx_number_2]->arg, 0, argv[idx_number_3]->arg); -} - -ALIAS_HIDDEN (neighbor_maximum_prefix_threshold_restart, - neighbor_maximum_prefix_threshold_restart_hidden_cmd, - "neighbor maximum-prefix (1-4294967295) (1-100) restart (1-65535)", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Maximum number of prefixes to accept from this peer\n" - "maximum no. of prefix limit\n" - "Threshold value (%) at which to generate a warning msg\n" - "Restart bgp connection after limit is exceeded\n" - "Restart interval in minutes\n") + int idx_peer = 1; + int idx_number = 3; + int idx_number_2 = 4; + int idx_number_3 = 6; + return peer_maximum_prefix_set_vty( + vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty), + argv[idx_number]->arg, argv[idx_number_2]->arg, 0, + argv[idx_number_3]->arg); +} + +ALIAS_HIDDEN( + neighbor_maximum_prefix_threshold_restart, + neighbor_maximum_prefix_threshold_restart_hidden_cmd, + "neighbor maximum-prefix (1-4294967295) (1-100) restart (1-65535)", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Maximum number of prefixes to accept from this peer\n" + "maximum no. of prefix limit\n" + "Threshold value (%) at which to generate a warning msg\n" + "Restart bgp connection after limit is exceeded\n" + "Restart interval in minutes\n") DEFUN (no_neighbor_maximum_prefix, no_neighbor_maximum_prefix_cmd, @@ -5925,23 +5712,22 @@ DEFUN (no_neighbor_maximum_prefix, "Restart interval in minutes\n" "Only give warning message when limit is exceeded\n") { - int idx_peer = 2; - return peer_maximum_prefix_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty)); + int idx_peer = 2; + return peer_maximum_prefix_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), + bgp_node_safi(vty)); } -ALIAS_HIDDEN (no_neighbor_maximum_prefix, - no_neighbor_maximum_prefix_hidden_cmd, - "no neighbor maximum-prefix [(1-4294967295) [(1-100)] [restart (1-65535)] [warning-only]]", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Maximum number of prefixes to accept from this peer\n" - "maximum no. of prefix limit\n" - "Threshold value (%) at which to generate a warning msg\n" - "Restart bgp connection after limit is exceeded\n" - "Restart interval in minutes\n" - "Only give warning message when limit is exceeded\n") +ALIAS_HIDDEN( + no_neighbor_maximum_prefix, no_neighbor_maximum_prefix_hidden_cmd, + "no neighbor maximum-prefix [(1-4294967295) [(1-100)] [restart (1-65535)] [warning-only]]", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Maximum number of prefixes to accept from this peer\n" + "maximum no. of prefix limit\n" + "Threshold value (%) at which to generate a warning msg\n" + "Restart bgp connection after limit is exceeded\n" + "Restart interval in minutes\n" + "Only give warning message when limit is exceeded\n") /* "neighbor allowas-in" */ @@ -5954,41 +5740,39 @@ DEFUN (neighbor_allowas_in, "Number of occurances of AS number\n" "Only accept my AS in the as-path if the route was originated in my AS\n") { - int idx_peer = 1; - int idx_number_origin = 3; - int ret; - int origin = 0; - struct peer *peer; - int allow_num = 0; - - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; - - if (argc <= idx_number_origin) - allow_num = 3; - else - { - if (argv[idx_number_origin]->type == WORD_TKN) - origin = 1; - else - allow_num = atoi (argv[idx_number_origin]->arg); - } - - ret = peer_allowas_in_set (peer, bgp_node_afi (vty), bgp_node_safi (vty), - allow_num, origin); - - return bgp_vty_return (vty, ret); -} - -ALIAS_HIDDEN (neighbor_allowas_in, - neighbor_allowas_in_hidden_cmd, - "neighbor allowas-in [<(1-10)|origin>]", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Accept as-path with my AS present in it\n" - "Number of occurances of AS number\n" - "Only accept my AS in the as-path if the route was originated in my AS\n") + int idx_peer = 1; + int idx_number_origin = 3; + int ret; + int origin = 0; + struct peer *peer; + int allow_num = 0; + + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; + + if (argc <= idx_number_origin) + allow_num = 3; + else { + if (argv[idx_number_origin]->type == WORD_TKN) + origin = 1; + else + allow_num = atoi(argv[idx_number_origin]->arg); + } + + ret = peer_allowas_in_set(peer, bgp_node_afi(vty), bgp_node_safi(vty), + allow_num, origin); + + return bgp_vty_return(vty, ret); +} + +ALIAS_HIDDEN( + neighbor_allowas_in, neighbor_allowas_in_hidden_cmd, + "neighbor allowas-in [<(1-10)|origin>]", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Accept as-path with my AS present in it\n" + "Number of occurances of AS number\n" + "Only accept my AS in the as-path if the route was originated in my AS\n") DEFUN (no_neighbor_allowas_in, no_neighbor_allowas_in_cmd, @@ -6000,28 +5784,27 @@ DEFUN (no_neighbor_allowas_in, "Number of occurances of AS number\n" "Only accept my AS in the as-path if the route was originated in my AS\n") { - int idx_peer = 2; - int ret; - struct peer *peer; + int idx_peer = 2; + int ret; + struct peer *peer; - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - ret = peer_allowas_in_unset (peer, bgp_node_afi (vty), bgp_node_safi (vty)); + ret = peer_allowas_in_unset(peer, bgp_node_afi(vty), + bgp_node_safi(vty)); - return bgp_vty_return (vty, ret); + return bgp_vty_return(vty, ret); } -ALIAS_HIDDEN (no_neighbor_allowas_in, - no_neighbor_allowas_in_hidden_cmd, - "no neighbor allowas-in [<(1-10)|origin>]", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "allow local ASN appears in aspath attribute\n" - "Number of occurances of AS number\n" - "Only accept my AS in the as-path if the route was originated in my AS\n") +ALIAS_HIDDEN( + no_neighbor_allowas_in, no_neighbor_allowas_in_hidden_cmd, + "no neighbor allowas-in [<(1-10)|origin>]", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "allow local ASN appears in aspath attribute\n" + "Number of occurances of AS number\n" + "Only accept my AS in the as-path if the route was originated in my AS\n") DEFUN (neighbor_ttl_security, neighbor_ttl_security_cmd, @@ -6032,28 +5815,29 @@ DEFUN (neighbor_ttl_security, "Specify the maximum number of hops to the BGP peer\n" "Number of hops to BGP peer\n") { - int idx_peer = 1; - int idx_number = 4; - struct peer *peer; - int gtsm_hops; - - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; - - gtsm_hops = strtoul(argv[idx_number]->arg, NULL, 10); - - /* - * If 'neighbor swpX', then this is for directly connected peers, - * we should not accept a ttl-security hops value greater than 1. - */ - if (peer->conf_if && (gtsm_hops > 1)) { - vty_out (vty, "%s is directly connected peer, hops cannot exceed 1\n", - argv[idx_peer]->arg); - return CMD_WARNING_CONFIG_FAILED; - } + int idx_peer = 1; + int idx_number = 4; + struct peer *peer; + int gtsm_hops; + + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; + + gtsm_hops = strtoul(argv[idx_number]->arg, NULL, 10); + + /* + * If 'neighbor swpX', then this is for directly connected peers, + * we should not accept a ttl-security hops value greater than 1. + */ + if (peer->conf_if && (gtsm_hops > 1)) { + vty_out(vty, + "%s is directly connected peer, hops cannot exceed 1\n", + argv[idx_peer]->arg); + return CMD_WARNING_CONFIG_FAILED; + } - return bgp_vty_return (vty, peer_ttl_security_hops_set (peer, gtsm_hops)); + return bgp_vty_return(vty, peer_ttl_security_hops_set(peer, gtsm_hops)); } DEFUN (no_neighbor_ttl_security, @@ -6066,14 +5850,14 @@ DEFUN (no_neighbor_ttl_security, "Specify the maximum number of hops to the BGP peer\n" "Number of hops to BGP peer\n") { - int idx_peer = 2; - struct peer *peer; + int idx_peer = 2; + struct peer *peer; - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - return bgp_vty_return (vty, peer_ttl_security_hops_unset (peer)); + return bgp_vty_return(vty, peer_ttl_security_hops_unset(peer)); } DEFUN (neighbor_addpath_tx_all_paths, @@ -6083,24 +5867,23 @@ DEFUN (neighbor_addpath_tx_all_paths, NEIGHBOR_ADDR_STR2 "Use addpath to advertise all paths to a neighbor\n") { - int idx_peer = 1; - struct peer *peer; + int idx_peer = 1; + struct peer *peer; - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - return peer_af_flag_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_ADDPATH_TX_ALL_PATHS); + return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), + PEER_FLAG_ADDPATH_TX_ALL_PATHS); } -ALIAS_HIDDEN (neighbor_addpath_tx_all_paths, - neighbor_addpath_tx_all_paths_hidden_cmd, - "neighbor addpath-tx-all-paths", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Use addpath to advertise all paths to a neighbor\n") +ALIAS_HIDDEN(neighbor_addpath_tx_all_paths, + neighbor_addpath_tx_all_paths_hidden_cmd, + "neighbor addpath-tx-all-paths", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Use addpath to advertise all paths to a neighbor\n") DEFUN (no_neighbor_addpath_tx_all_paths, no_neighbor_addpath_tx_all_paths_cmd, @@ -6110,19 +5893,17 @@ DEFUN (no_neighbor_addpath_tx_all_paths, NEIGHBOR_ADDR_STR2 "Use addpath to advertise all paths to a neighbor\n") { - int idx_peer = 2; - return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_ADDPATH_TX_ALL_PATHS); + int idx_peer = 2; + return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), bgp_node_safi(vty), + PEER_FLAG_ADDPATH_TX_ALL_PATHS); } -ALIAS_HIDDEN (no_neighbor_addpath_tx_all_paths, - no_neighbor_addpath_tx_all_paths_hidden_cmd, - "no neighbor addpath-tx-all-paths", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Use addpath to advertise all paths to a neighbor\n") +ALIAS_HIDDEN(no_neighbor_addpath_tx_all_paths, + no_neighbor_addpath_tx_all_paths_hidden_cmd, + "no neighbor addpath-tx-all-paths", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Use addpath to advertise all paths to a neighbor\n") DEFUN (neighbor_addpath_tx_bestpath_per_as, neighbor_addpath_tx_bestpath_per_as_cmd, @@ -6131,24 +5912,23 @@ DEFUN (neighbor_addpath_tx_bestpath_per_as, NEIGHBOR_ADDR_STR2 "Use addpath to advertise the bestpath per each neighboring AS\n") { - int idx_peer = 1; - struct peer *peer; + int idx_peer = 1; + struct peer *peer; - peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); - if (! peer) - return CMD_WARNING_CONFIG_FAILED; + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - return peer_af_flag_set_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS); + return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty), + bgp_node_safi(vty), + PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS); } -ALIAS_HIDDEN (neighbor_addpath_tx_bestpath_per_as, - neighbor_addpath_tx_bestpath_per_as_hidden_cmd, - "neighbor addpath-tx-bestpath-per-AS", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Use addpath to advertise the bestpath per each neighboring AS\n") +ALIAS_HIDDEN(neighbor_addpath_tx_bestpath_per_as, + neighbor_addpath_tx_bestpath_per_as_hidden_cmd, + "neighbor addpath-tx-bestpath-per-AS", + NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Use addpath to advertise the bestpath per each neighboring AS\n") DEFUN (no_neighbor_addpath_tx_bestpath_per_as, no_neighbor_addpath_tx_bestpath_per_as_cmd, @@ -6158,19 +5938,17 @@ DEFUN (no_neighbor_addpath_tx_bestpath_per_as, NEIGHBOR_ADDR_STR2 "Use addpath to advertise the bestpath per each neighboring AS\n") { - int idx_peer = 2; - return peer_af_flag_unset_vty (vty, argv[idx_peer]->arg, bgp_node_afi (vty), - bgp_node_safi (vty), - PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS); + int idx_peer = 2; + return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg, + bgp_node_afi(vty), bgp_node_safi(vty), + PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS); } -ALIAS_HIDDEN (no_neighbor_addpath_tx_bestpath_per_as, - no_neighbor_addpath_tx_bestpath_per_as_hidden_cmd, - "no neighbor addpath-tx-bestpath-per-AS", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Use addpath to advertise the bestpath per each neighboring AS\n") +ALIAS_HIDDEN(no_neighbor_addpath_tx_bestpath_per_as, + no_neighbor_addpath_tx_bestpath_per_as_hidden_cmd, + "no neighbor addpath-tx-bestpath-per-AS", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Use addpath to advertise the bestpath per each neighboring AS\n") DEFUN_NOSH (address_family_ipv4_safi, address_family_ipv4_safi_cmd, @@ -6180,15 +5958,13 @@ DEFUN_NOSH (address_family_ipv4_safi, BGP_SAFI_WITH_LABEL_HELP_STR) { - if (argc == 3) - { - safi_t safi = bgp_vty_safi_from_str (argv[2]->text); - vty->node = bgp_node_type(AFI_IP, safi); - } - else - vty->node = BGP_IPV4_NODE; + if (argc == 3) { + safi_t safi = bgp_vty_safi_from_str(argv[2]->text); + vty->node = bgp_node_type(AFI_IP, safi); + } else + vty->node = BGP_IPV4_NODE; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_NOSH (address_family_ipv6_safi, @@ -6198,15 +5974,13 @@ DEFUN_NOSH (address_family_ipv6_safi, "Address Family\n" BGP_SAFI_WITH_LABEL_HELP_STR) { - if (argc == 3) - { - safi_t safi = bgp_vty_safi_from_str (argv[2]->text); - vty->node = bgp_node_type(AFI_IP6, safi); - } - else - vty->node = BGP_IPV6_NODE; + if (argc == 3) { + safi_t safi = bgp_vty_safi_from_str(argv[2]->text); + vty->node = bgp_node_type(AFI_IP6, safi); + } else + vty->node = BGP_IPV6_NODE; - return CMD_SUCCESS; + return CMD_SUCCESS; } #ifdef KEEP_OLD_VPN_COMMANDS @@ -6217,8 +5991,8 @@ DEFUN_NOSH (address_family_vpnv4, "Address Family\n" "Address Family modifier\n") { - vty->node = BGP_VPNV4_NODE; - return CMD_SUCCESS; + vty->node = BGP_VPNV4_NODE; + return CMD_SUCCESS; } DEFUN_NOSH (address_family_vpnv6, @@ -6228,8 +6002,8 @@ DEFUN_NOSH (address_family_vpnv6, "Address Family\n" "Address Family modifier\n") { - vty->node = BGP_VPNV6_NODE; - return CMD_SUCCESS; + vty->node = BGP_VPNV6_NODE; + return CMD_SUCCESS; } #endif @@ -6240,8 +6014,8 @@ DEFUN_NOSH (address_family_evpn, "Address Family\n" "Address Family modifier\n") { - vty->node = BGP_EVPN_NODE; - return CMD_SUCCESS; + vty->node = BGP_EVPN_NODE; + return CMD_SUCCESS; } DEFUN_NOSH (exit_address_family, @@ -6249,98 +6023,83 @@ DEFUN_NOSH (exit_address_family, "exit-address-family", "Exit from Address Family configuration mode\n") { - if (vty->node == BGP_IPV4_NODE - || vty->node == BGP_IPV4M_NODE - || vty->node == BGP_IPV4L_NODE - || vty->node == BGP_VPNV4_NODE - || vty->node == BGP_IPV6_NODE - || vty->node == BGP_IPV6M_NODE - || vty->node == BGP_IPV6L_NODE - || vty->node == BGP_VPNV6_NODE - || vty->node == BGP_EVPN_NODE) - vty->node = BGP_NODE; - return CMD_SUCCESS; + if (vty->node == BGP_IPV4_NODE || vty->node == BGP_IPV4M_NODE + || vty->node == BGP_IPV4L_NODE || vty->node == BGP_VPNV4_NODE + || vty->node == BGP_IPV6_NODE || vty->node == BGP_IPV6M_NODE + || vty->node == BGP_IPV6L_NODE || vty->node == BGP_VPNV6_NODE + || vty->node == BGP_EVPN_NODE) + vty->node = BGP_NODE; + return CMD_SUCCESS; } /* Recalculate bestpath and re-advertise a prefix */ -static int -bgp_clear_prefix (struct vty *vty, const char *view_name, const char *ip_str, - afi_t afi, safi_t safi, struct prefix_rd *prd) -{ - int ret; - struct prefix match; - struct bgp_node *rn; - struct bgp_node *rm; - struct bgp *bgp; - struct bgp_table *table; - struct bgp_table *rib; - - /* BGP structure lookup. */ - if (view_name) - { - bgp = bgp_lookup_by_name (view_name); - if (bgp == NULL) - { - vty_out (vty, "%% Can't find BGP instance %s\n", view_name); - return CMD_WARNING; - } - } - else - { - bgp = bgp_get_default (); - if (bgp == NULL) - { - vty_out (vty, "%% No BGP process is configured\n"); - return CMD_WARNING; - } - } - - /* Check IP address argument. */ - ret = str2prefix (ip_str, &match); - if (! ret) - { - vty_out (vty, "%% address is malformed\n"); - return CMD_WARNING; - } - - match.family = afi2family (afi); - rib = bgp->rib[afi][safi]; - - if (safi == SAFI_MPLS_VPN) - { - for (rn = bgp_table_top (rib); rn; rn = bgp_route_next (rn)) - { - if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0) - continue; - - if ((table = rn->info) != NULL) - { - if ((rm = bgp_node_match (table, &match)) != NULL) - { - if (rm->p.prefixlen == match.prefixlen) - { - SET_FLAG (rn->flags, BGP_NODE_USER_CLEAR); - bgp_process (bgp, rm, afi, safi); - } - bgp_unlock_node (rm); - } - } - } - } - else - { - if ((rn = bgp_node_match (rib, &match)) != NULL) - { - if (rn->p.prefixlen == match.prefixlen) - { - SET_FLAG (rn->flags, BGP_NODE_USER_CLEAR); - bgp_process (bgp, rn, afi, safi); - } - bgp_unlock_node (rn); - } - } - - return CMD_SUCCESS; +static int bgp_clear_prefix(struct vty *vty, const char *view_name, + const char *ip_str, afi_t afi, safi_t safi, + struct prefix_rd *prd) +{ + int ret; + struct prefix match; + struct bgp_node *rn; + struct bgp_node *rm; + struct bgp *bgp; + struct bgp_table *table; + struct bgp_table *rib; + + /* BGP structure lookup. */ + if (view_name) { + bgp = bgp_lookup_by_name(view_name); + if (bgp == NULL) { + vty_out(vty, "%% Can't find BGP instance %s\n", + view_name); + return CMD_WARNING; + } + } else { + bgp = bgp_get_default(); + if (bgp == NULL) { + vty_out(vty, "%% No BGP process is configured\n"); + return CMD_WARNING; + } + } + + /* Check IP address argument. */ + ret = str2prefix(ip_str, &match); + if (!ret) { + vty_out(vty, "%% address is malformed\n"); + return CMD_WARNING; + } + + match.family = afi2family(afi); + rib = bgp->rib[afi][safi]; + + if (safi == SAFI_MPLS_VPN) { + for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) { + if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0) + continue; + + if ((table = rn->info) != NULL) { + if ((rm = bgp_node_match(table, &match)) + != NULL) { + if (rm->p.prefixlen + == match.prefixlen) { + SET_FLAG(rn->flags, + BGP_NODE_USER_CLEAR); + bgp_process(bgp, rm, afi, safi); + } + bgp_unlock_node(rm); + } + } + } + } else { + if ((rn = bgp_node_match(rib, &match)) != NULL) { + if (rn->p.prefixlen == match.prefixlen) { + SET_FLAG(rn->flags, BGP_NODE_USER_CLEAR); + bgp_process(bgp, rn, afi, safi); + } + bgp_unlock_node(rn); + } + } + + return CMD_SUCCESS; } /* one clear bgp command to rule them all */ @@ -6368,87 +6127,73 @@ DEFUN (clear_ip_bgp_all, "Push out prefix-list ORF and do inbound soft reconfig\n" BGP_SOFT_OUT_STR) { - char *vrf = NULL; - - afi_t afi = AFI_IP6; - safi_t safi = SAFI_UNICAST; - enum clear_sort clr_sort = clear_peer; - enum bgp_clear_type clr_type; - char *clr_arg = NULL; - - int idx = 0; - - /* clear [ip] bgp */ - if (argv_find (argv, argc, "ip", &idx)) - afi = AFI_IP; - - /* [ VIEWVRFNAME] */ - if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx)) - { - vrf = argv[idx + 1]->arg; - idx += 2; - } - - /* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */ - if (argv_find_and_parse_afi (argv, argc, &idx, &afi)) - argv_find_and_parse_safi (argv, argc, &idx, &safi); - - /* <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external|peer-group WORD> */ - if (argv_find (argv, argc, "*", &idx)) - { - clr_sort = clear_all; - } - else if (argv_find (argv, argc, "A.B.C.D", &idx)) - { - clr_sort = clear_peer; - clr_arg = argv[idx]->arg; - } - else if (argv_find (argv, argc, "X:X::X:X", &idx)) - { - clr_sort = clear_peer; - clr_arg = argv[idx]->arg; - } - else if (argv_find (argv, argc, "peer-group", &idx)) - { - clr_sort = clear_group; - idx++; - clr_arg = argv[idx]->arg; - } - else if (argv_find (argv, argc, "WORD", &idx)) - { - clr_sort = clear_peer; - clr_arg = argv[idx]->arg; - } - else if (argv_find (argv, argc, "(1-4294967295)", &idx)) - { - clr_sort = clear_as; - clr_arg = argv[idx]->arg; - } - else if (argv_find (argv, argc, "external", &idx)) - { - clr_sort = clear_external; - } - - /* []|in [prefix-filter]|out>] */ - if (argv_find (argv, argc, "soft", &idx)) - { - if (argv_find (argv, argc, "in", &idx) || argv_find (argv, argc, "out", &idx)) - clr_type = strmatch (argv[idx]->text, "in") ? BGP_CLEAR_SOFT_IN : BGP_CLEAR_SOFT_OUT; - else - clr_type = BGP_CLEAR_SOFT_BOTH; - } - else if (argv_find (argv, argc, "in", &idx)) - { - clr_type = argv_find (argv, argc, "prefix-filter", &idx) ? BGP_CLEAR_SOFT_IN_ORF_PREFIX : BGP_CLEAR_SOFT_IN; - } - else if (argv_find (argv, argc, "out", &idx)) - { - clr_type = BGP_CLEAR_SOFT_OUT; - } - else - clr_type = BGP_CLEAR_SOFT_NONE; - - return bgp_clear_vty (vty, vrf, afi, safi, clr_sort, clr_type, clr_arg); + char *vrf = NULL; + + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; + enum clear_sort clr_sort = clear_peer; + enum bgp_clear_type clr_type; + char *clr_arg = NULL; + + int idx = 0; + + /* clear [ip] bgp */ + if (argv_find(argv, argc, "ip", &idx)) + afi = AFI_IP; + + /* [ VIEWVRFNAME] */ + if (argv_find(argv, argc, "view", &idx) + || argv_find(argv, argc, "vrf", &idx)) { + vrf = argv[idx + 1]->arg; + idx += 2; + } + + /* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */ + if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) + argv_find_and_parse_safi(argv, argc, &idx, &safi); + + /* <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external|peer-group WORD> */ + if (argv_find(argv, argc, "*", &idx)) { + clr_sort = clear_all; + } else if (argv_find(argv, argc, "A.B.C.D", &idx)) { + clr_sort = clear_peer; + clr_arg = argv[idx]->arg; + } else if (argv_find(argv, argc, "X:X::X:X", &idx)) { + clr_sort = clear_peer; + clr_arg = argv[idx]->arg; + } else if (argv_find(argv, argc, "peer-group", &idx)) { + clr_sort = clear_group; + idx++; + clr_arg = argv[idx]->arg; + } else if (argv_find(argv, argc, "WORD", &idx)) { + clr_sort = clear_peer; + clr_arg = argv[idx]->arg; + } else if (argv_find(argv, argc, "(1-4294967295)", &idx)) { + clr_sort = clear_as; + clr_arg = argv[idx]->arg; + } else if (argv_find(argv, argc, "external", &idx)) { + clr_sort = clear_external; + } + + /* []|in [prefix-filter]|out>] */ + if (argv_find(argv, argc, "soft", &idx)) { + if (argv_find(argv, argc, "in", &idx) + || argv_find(argv, argc, "out", &idx)) + clr_type = strmatch(argv[idx]->text, "in") + ? BGP_CLEAR_SOFT_IN + : BGP_CLEAR_SOFT_OUT; + else + clr_type = BGP_CLEAR_SOFT_BOTH; + } else if (argv_find(argv, argc, "in", &idx)) { + clr_type = argv_find(argv, argc, "prefix-filter", &idx) + ? BGP_CLEAR_SOFT_IN_ORF_PREFIX + : BGP_CLEAR_SOFT_IN; + } else if (argv_find(argv, argc, "out", &idx)) { + clr_type = BGP_CLEAR_SOFT_OUT; + } else + clr_type = BGP_CLEAR_SOFT_NONE; + + return bgp_clear_vty(vty, vrf, afi, safi, clr_sort, clr_type, clr_arg); } DEFUN (clear_ip_bgp_prefix, @@ -6461,18 +6206,18 @@ DEFUN (clear_ip_bgp_prefix, "Clear bestpath and re-advertise\n" "IPv4 prefix\n") { - char *vrf = NULL; - char *prefix = NULL; + char *vrf = NULL; + char *prefix = NULL; - int idx = 0; + int idx = 0; - /* [ VIEWVRFNAME] */ - if (argv_find (argv, argc, "WORD", &idx)) - vrf = argv[idx]->arg; + /* [ VIEWVRFNAME] */ + if (argv_find(argv, argc, "WORD", &idx)) + vrf = argv[idx]->arg; - prefix = argv[argc-1]->arg; + prefix = argv[argc - 1]->arg; - return bgp_clear_prefix (vty, vrf, prefix, AFI_IP, SAFI_UNICAST, NULL); + return bgp_clear_prefix(vty, vrf, prefix, AFI_IP, SAFI_UNICAST, NULL); } DEFUN (clear_bgp_ipv6_safi_prefix, @@ -6486,10 +6231,11 @@ DEFUN (clear_bgp_ipv6_safi_prefix, "Clear bestpath and re-advertise\n" "IPv6 prefix\n") { - int idx_safi = 3; - int idx_ipv6_prefixlen = 5; - return bgp_clear_prefix (vty, NULL, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, - bgp_vty_safi_from_str(argv[idx_safi]->text), NULL); + int idx_safi = 3; + int idx_ipv6_prefixlen = 5; + return bgp_clear_prefix( + vty, NULL, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, + bgp_vty_safi_from_str(argv[idx_safi]->text), NULL); } DEFUN (clear_bgp_instance_ipv6_safi_prefix, @@ -6504,11 +6250,12 @@ DEFUN (clear_bgp_instance_ipv6_safi_prefix, "Clear bestpath and re-advertise\n" "IPv6 prefix\n") { - int idx_word = 3; - int idx_safi = 5; - int idx_ipv6_prefixlen = 7; - return bgp_clear_prefix (vty, argv[idx_word]->arg, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, - bgp_vty_safi_from_str(argv[idx_safi]->text), NULL); + int idx_word = 3; + int idx_safi = 5; + int idx_ipv6_prefixlen = 7; + return bgp_clear_prefix( + vty, argv[idx_word]->arg, argv[idx_ipv6_prefixlen]->arg, + AFI_IP6, bgp_vty_safi_from_str(argv[idx_safi]->text), NULL); } DEFUN (show_bgp_views, @@ -6519,28 +6266,25 @@ DEFUN (show_bgp_views, BGP_STR "Show the defined BGP views\n") { - struct list *inst = bm->bgp; - struct listnode *node; - struct bgp *bgp; + struct list *inst = bm->bgp; + struct listnode *node; + struct bgp *bgp; - if (!bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE)) - { - vty_out (vty, "BGP Multiple Instance is not enabled\n"); - return CMD_WARNING; - } + if (!bgp_option_check(BGP_OPT_MULTIPLE_INSTANCE)) { + vty_out(vty, "BGP Multiple Instance is not enabled\n"); + return CMD_WARNING; + } - vty_out (vty, "Defined BGP views:\n"); - for (ALL_LIST_ELEMENTS_RO(inst, node, bgp)) - { - /* Skip VRFs. */ - if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) - continue; - vty_out (vty, "\t%s (AS%u)\n", - bgp->name ? bgp->name : "(null)", - bgp->as); - } + vty_out(vty, "Defined BGP views:\n"); + for (ALL_LIST_ELEMENTS_RO(inst, node, bgp)) { + /* Skip VRFs. */ + if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) + continue; + vty_out(vty, "\t%s (AS%u)\n", bgp->name ? bgp->name : "(null)", + bgp->as); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_bgp_vrfs, @@ -6552,102 +6296,97 @@ DEFUN (show_bgp_vrfs, "Show BGP VRFs\n" JSON_STR) { - struct list *inst = bm->bgp; - struct listnode *node; - struct bgp *bgp; - u_char uj = use_json(argc, argv); - json_object *json = NULL; - json_object *json_vrfs = NULL; - int count = 0; - static char header[] = "Type Id RouterId #PeersCfg #PeersEstb Name"; - - if (!bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE)) - { - vty_out (vty, "BGP Multiple Instance is not enabled\n"); - return CMD_WARNING; - } - - if (uj) - { - json = json_object_new_object(); - json_vrfs = json_object_new_object(); - } - - for (ALL_LIST_ELEMENTS_RO(inst, node, bgp)) - { - const char *name, *type; - struct peer *peer; - struct listnode *node, *nnode; - int peers_cfg, peers_estb; - json_object *json_vrf = NULL; - int vrf_id_ui; - - /* Skip Views. */ - if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) - continue; - - count++; - if (!uj && count == 1) - vty_out (vty, "%s\n", header); - - peers_cfg = peers_estb = 0; - if (uj) - json_vrf = json_object_new_object(); - - - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) - continue; - peers_cfg++; - if (peer->status == Established) - peers_estb++; - } - - if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - { - name = "Default"; - type = "DFLT"; - } - else - { - name = bgp->name; - type = "VRF"; - } - - vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN) ? -1 : bgp->vrf_id; - if (uj) - { - json_object_string_add(json_vrf, "type", type); - json_object_int_add(json_vrf, "vrfId", vrf_id_ui); - json_object_string_add(json_vrf, "routerId", inet_ntoa (bgp->router_id)); - json_object_int_add(json_vrf, "numConfiguredPeers", peers_cfg); - json_object_int_add(json_vrf, "numEstablishedPeers", peers_estb); - - json_object_object_add(json_vrfs, name, json_vrf); - } - else - vty_out (vty, "%4s %-5d %-16s %9u %10u %s\n", - type, vrf_id_ui, inet_ntoa (bgp->router_id), - peers_cfg, peers_estb, name); - } - - if (uj) - { - json_object_object_add(json, "vrfs", json_vrfs); - - json_object_int_add(json, "totalVrfs", count); - - vty_out (vty, "%s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - { - if (count) - vty_out (vty, "\nTotal number of VRFs (including default): %d\n", count); - } - - return CMD_SUCCESS; + struct list *inst = bm->bgp; + struct listnode *node; + struct bgp *bgp; + u_char uj = use_json(argc, argv); + json_object *json = NULL; + json_object *json_vrfs = NULL; + int count = 0; + static char header[] = + "Type Id RouterId #PeersCfg #PeersEstb Name"; + + if (!bgp_option_check(BGP_OPT_MULTIPLE_INSTANCE)) { + vty_out(vty, "BGP Multiple Instance is not enabled\n"); + return CMD_WARNING; + } + + if (uj) { + json = json_object_new_object(); + json_vrfs = json_object_new_object(); + } + + for (ALL_LIST_ELEMENTS_RO(inst, node, bgp)) { + const char *name, *type; + struct peer *peer; + struct listnode *node, *nnode; + int peers_cfg, peers_estb; + json_object *json_vrf = NULL; + int vrf_id_ui; + + /* Skip Views. */ + if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) + continue; + + count++; + if (!uj && count == 1) + vty_out(vty, "%s\n", header); + + peers_cfg = peers_estb = 0; + if (uj) + json_vrf = json_object_new_object(); + + + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) + continue; + peers_cfg++; + if (peer->status == Established) + peers_estb++; + } + + if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) { + name = "Default"; + type = "DFLT"; + } else { + name = bgp->name; + type = "VRF"; + } + + vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN) ? -1 : bgp->vrf_id; + if (uj) { + json_object_string_add(json_vrf, "type", type); + json_object_int_add(json_vrf, "vrfId", vrf_id_ui); + json_object_string_add(json_vrf, "routerId", + inet_ntoa(bgp->router_id)); + json_object_int_add(json_vrf, "numConfiguredPeers", + peers_cfg); + json_object_int_add(json_vrf, "numEstablishedPeers", + peers_estb); + + json_object_object_add(json_vrfs, name, json_vrf); + } else + vty_out(vty, "%4s %-5d %-16s %9u %10u %s\n", type, + vrf_id_ui, inet_ntoa(bgp->router_id), peers_cfg, + peers_estb, name); + } + + if (uj) { + json_object_object_add(json, "vrfs", json_vrfs); + + json_object_int_add(json, "totalVrfs", count); + + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else { + if (count) + vty_out(vty, + "\nTotal number of VRFs (including default): %d\n", + count); + } + + return CMD_SUCCESS; } DEFUN (show_bgp_memory, @@ -6658,642 +6397,753 @@ DEFUN (show_bgp_memory, BGP_STR "Global BGP memory statistics\n") { - char memstrbuf[MTYPE_MEMSTR_LEN]; - unsigned long count; - - /* RIB related usage stats */ - count = mtype_stats_alloc (MTYPE_BGP_NODE); - vty_out (vty, "%ld RIB nodes, using %s of memory\n", count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof (struct bgp_node))); - - count = mtype_stats_alloc (MTYPE_BGP_ROUTE); - vty_out (vty, "%ld BGP routes, using %s of memory\n", count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof (struct bgp_info))); - if ((count = mtype_stats_alloc (MTYPE_BGP_ROUTE_EXTRA))) - vty_out (vty, "%ld BGP route ancillaries, using %s of memory\n", count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof (struct bgp_info_extra))); - - if ((count = mtype_stats_alloc (MTYPE_BGP_STATIC))) - vty_out (vty, "%ld Static routes, using %s of memory\n", count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof (struct bgp_static))); - - if ((count = mtype_stats_alloc (MTYPE_BGP_PACKET))) - vty_out (vty, "%ld Packets, using %s of memory\n", count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof (struct bpacket))); - - /* Adj-In/Out */ - if ((count = mtype_stats_alloc (MTYPE_BGP_ADJ_IN))) - vty_out (vty, "%ld Adj-In entries, using %s of memory\n", count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof (struct bgp_adj_in))); - if ((count = mtype_stats_alloc (MTYPE_BGP_ADJ_OUT))) - vty_out (vty, "%ld Adj-Out entries, using %s of memory\n", count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof (struct bgp_adj_out))); - - if ((count = mtype_stats_alloc (MTYPE_BGP_NEXTHOP_CACHE))) - vty_out (vty, "%ld Nexthop cache entries, using %s of memory\n", count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof (struct bgp_nexthop_cache))); - - if ((count = mtype_stats_alloc (MTYPE_BGP_DAMP_INFO))) - vty_out (vty, "%ld Dampening entries, using %s of memory\n", count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof (struct bgp_damp_info))); - - /* Attributes */ - count = attr_count(); - vty_out (vty, "%ld BGP attributes, using %s of memory\n", count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof(struct attr))); - - if ((count = attr_unknown_count())) - vty_out (vty, "%ld unknown attributes\n", count); - - /* AS_PATH attributes */ - count = aspath_count (); - vty_out (vty, "%ld BGP AS-PATH entries, using %s of memory\n", count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof (struct aspath))); - - count = mtype_stats_alloc (MTYPE_AS_SEG); - vty_out (vty, "%ld BGP AS-PATH segments, using %s of memory\n", count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof (struct assegment))); - - /* Other attributes */ - if ((count = community_count ())) - vty_out (vty, "%ld BGP community entries, using %s of memory\n", count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof (struct community))); - if ((count = mtype_stats_alloc (MTYPE_ECOMMUNITY))) - vty_out (vty, "%ld BGP community entries, using %s of memory\n", count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof (struct ecommunity))); - if ((count = mtype_stats_alloc (MTYPE_LCOMMUNITY))) - vty_out (vty, "%ld BGP large-community entries, using %s of memory\n", - count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof (struct lcommunity))); - - if ((count = mtype_stats_alloc (MTYPE_CLUSTER))) - vty_out (vty, "%ld Cluster lists, using %s of memory\n", count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof (struct cluster_list))); - - /* Peer related usage */ - count = mtype_stats_alloc (MTYPE_BGP_PEER); - vty_out (vty, "%ld peers, using %s of memory\n", count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof (struct peer))); - - if ((count = mtype_stats_alloc (MTYPE_PEER_GROUP))) - vty_out (vty, "%ld peer groups, using %s of memory\n", count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof (struct peer_group))); - - /* Other */ - if ((count = mtype_stats_alloc (MTYPE_HASH))) - vty_out (vty, "%ld hash tables, using %s of memory\n", count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof (struct hash))); - if ((count = mtype_stats_alloc (MTYPE_HASH_BACKET))) - vty_out (vty, "%ld hash buckets, using %s of memory\n", count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof (struct hash_backet))); - if ((count = mtype_stats_alloc (MTYPE_BGP_REGEXP))) - vty_out (vty, "%ld compiled regexes, using %s of memory\n", count, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - count * sizeof (regex_t))); - return CMD_SUCCESS; + char memstrbuf[MTYPE_MEMSTR_LEN]; + unsigned long count; + + /* RIB related usage stats */ + count = mtype_stats_alloc(MTYPE_BGP_NODE); + vty_out(vty, "%ld RIB nodes, using %s of memory\n", count, + mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct bgp_node))); + + count = mtype_stats_alloc(MTYPE_BGP_ROUTE); + vty_out(vty, "%ld BGP routes, using %s of memory\n", count, + mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct bgp_info))); + if ((count = mtype_stats_alloc(MTYPE_BGP_ROUTE_EXTRA))) + vty_out(vty, "%ld BGP route ancillaries, using %s of memory\n", + count, + mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct bgp_info_extra))); + + if ((count = mtype_stats_alloc(MTYPE_BGP_STATIC))) + vty_out(vty, "%ld Static routes, using %s of memory\n", count, + mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct bgp_static))); + + if ((count = mtype_stats_alloc(MTYPE_BGP_PACKET))) + vty_out(vty, "%ld Packets, using %s of memory\n", count, + mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct bpacket))); + + /* Adj-In/Out */ + if ((count = mtype_stats_alloc(MTYPE_BGP_ADJ_IN))) + vty_out(vty, "%ld Adj-In entries, using %s of memory\n", count, + mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct bgp_adj_in))); + if ((count = mtype_stats_alloc(MTYPE_BGP_ADJ_OUT))) + vty_out(vty, "%ld Adj-Out entries, using %s of memory\n", count, + mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct bgp_adj_out))); + + if ((count = mtype_stats_alloc(MTYPE_BGP_NEXTHOP_CACHE))) + vty_out(vty, "%ld Nexthop cache entries, using %s of memory\n", + count, + mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct bgp_nexthop_cache))); + + if ((count = mtype_stats_alloc(MTYPE_BGP_DAMP_INFO))) + vty_out(vty, "%ld Dampening entries, using %s of memory\n", + count, + mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct bgp_damp_info))); + + /* Attributes */ + count = attr_count(); + vty_out(vty, "%ld BGP attributes, using %s of memory\n", count, + mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct attr))); + + if ((count = attr_unknown_count())) + vty_out(vty, "%ld unknown attributes\n", count); + + /* AS_PATH attributes */ + count = aspath_count(); + vty_out(vty, "%ld BGP AS-PATH entries, using %s of memory\n", count, + mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct aspath))); + + count = mtype_stats_alloc(MTYPE_AS_SEG); + vty_out(vty, "%ld BGP AS-PATH segments, using %s of memory\n", count, + mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct assegment))); + + /* Other attributes */ + if ((count = community_count())) + vty_out(vty, "%ld BGP community entries, using %s of memory\n", + count, mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct community))); + if ((count = mtype_stats_alloc(MTYPE_ECOMMUNITY))) + vty_out(vty, "%ld BGP community entries, using %s of memory\n", + count, mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct ecommunity))); + if ((count = mtype_stats_alloc(MTYPE_LCOMMUNITY))) + vty_out(vty, + "%ld BGP large-community entries, using %s of memory\n", + count, mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct lcommunity))); + + if ((count = mtype_stats_alloc(MTYPE_CLUSTER))) + vty_out(vty, "%ld Cluster lists, using %s of memory\n", count, + mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct cluster_list))); + + /* Peer related usage */ + count = mtype_stats_alloc(MTYPE_BGP_PEER); + vty_out(vty, "%ld peers, using %s of memory\n", count, + mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct peer))); + + if ((count = mtype_stats_alloc(MTYPE_PEER_GROUP))) + vty_out(vty, "%ld peer groups, using %s of memory\n", count, + mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct peer_group))); + + /* Other */ + if ((count = mtype_stats_alloc(MTYPE_HASH))) + vty_out(vty, "%ld hash tables, using %s of memory\n", count, + mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct hash))); + if ((count = mtype_stats_alloc(MTYPE_HASH_BACKET))) + vty_out(vty, "%ld hash buckets, using %s of memory\n", count, + mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct hash_backet))); + if ((count = mtype_stats_alloc(MTYPE_BGP_REGEXP))) + vty_out(vty, "%ld compiled regexes, using %s of memory\n", + count, mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(regex_t))); + return CMD_SUCCESS; } /* Show BGP peer's summary information. */ -static int -bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi, - u_char use_json, json_object *json) -{ - struct peer *peer; - struct listnode *node, *nnode; - unsigned int count = 0, dn_count = 0; - char timebuf[BGP_UPTIME_LEN], dn_flag[2]; - char neighbor_buf[VTY_BUFSIZ]; - int neighbor_col_default_width = 16; - int len; - int max_neighbor_width = 0; - int pfx_rcd_safi; - json_object *json_peer = NULL; - json_object *json_peers = NULL; - - /* labeled-unicast routes are installed in the unicast table so in order to - * display the correct PfxRcd value we must look at SAFI_UNICAST - */ - if (safi == SAFI_LABELED_UNICAST) - pfx_rcd_safi = SAFI_UNICAST; - else - pfx_rcd_safi = safi; - - if (use_json) - { - if (json == NULL) - json = json_object_new_object(); - - json_peers = json_object_new_object(); - } - else - { - /* Loop over all neighbors that will be displayed to determine how many - * characters are needed for the Neighbor column - */ - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) - continue; - - if (peer->afc[afi][safi]) - { - memset(dn_flag, '\0', sizeof(dn_flag)); - if (peer_dynamic_neighbor(peer)) - dn_flag[0] = '*'; - - if (peer->hostname && bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME)) - sprintf(neighbor_buf, "%s%s(%s) ", dn_flag, peer->hostname, peer->host); - else - sprintf(neighbor_buf, "%s%s ", dn_flag, peer->host); +static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, + u_char use_json, json_object *json) +{ + struct peer *peer; + struct listnode *node, *nnode; + unsigned int count = 0, dn_count = 0; + char timebuf[BGP_UPTIME_LEN], dn_flag[2]; + char neighbor_buf[VTY_BUFSIZ]; + int neighbor_col_default_width = 16; + int len; + int max_neighbor_width = 0; + int pfx_rcd_safi; + json_object *json_peer = NULL; + json_object *json_peers = NULL; + + /* labeled-unicast routes are installed in the unicast table so in order + * to + * display the correct PfxRcd value we must look at SAFI_UNICAST + */ + if (safi == SAFI_LABELED_UNICAST) + pfx_rcd_safi = SAFI_UNICAST; + else + pfx_rcd_safi = safi; + + if (use_json) { + if (json == NULL) + json = json_object_new_object(); + + json_peers = json_object_new_object(); + } else { + /* Loop over all neighbors that will be displayed to determine + * how many + * characters are needed for the Neighbor column + */ + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) + continue; + + if (peer->afc[afi][safi]) { + memset(dn_flag, '\0', sizeof(dn_flag)); + if (peer_dynamic_neighbor(peer)) + dn_flag[0] = '*'; + + if (peer->hostname + && bgp_flag_check(bgp, + BGP_FLAG_SHOW_HOSTNAME)) + sprintf(neighbor_buf, "%s%s(%s) ", + dn_flag, peer->hostname, + peer->host); + else + sprintf(neighbor_buf, "%s%s ", dn_flag, + peer->host); + + len = strlen(neighbor_buf); + + if (len > max_neighbor_width) + max_neighbor_width = len; + } + } - len = strlen(neighbor_buf); + /* Originally we displayed the Neighbor column as 16 + * characters wide so make that the default + */ + if (max_neighbor_width < neighbor_col_default_width) + max_neighbor_width = neighbor_col_default_width; + } - if (len > max_neighbor_width) - max_neighbor_width = len; - } - } + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) + continue; + + if (peer->afc[afi][safi]) { + if (!count) { + unsigned long ents; + char memstrbuf[MTYPE_MEMSTR_LEN]; + int vrf_id_ui; + + vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN) + ? -1 + : bgp->vrf_id; + + /* Usage summary and header */ + if (use_json) { + json_object_string_add( + json, "routerId", + inet_ntoa(bgp->router_id)); + json_object_int_add(json, "as", + bgp->as); + json_object_int_add(json, "vrfId", + vrf_id_ui); + json_object_string_add( + json, "vrfName", + (bgp->inst_type + == BGP_INSTANCE_TYPE_DEFAULT) + ? "Default" + : bgp->name); + } else { + vty_out(vty, + "BGP router identifier %s, local AS number %u vrf-id %d", + inet_ntoa(bgp->router_id), + bgp->as, vrf_id_ui); + vty_out(vty, "\n"); + } + + if (bgp_update_delay_configured(bgp)) { + if (use_json) { + json_object_int_add( + json, + "updateDelayLimit", + bgp->v_update_delay); + + if (bgp->v_update_delay + != bgp->v_establish_wait) + json_object_int_add( + json, + "updateDelayEstablishWait", + bgp->v_establish_wait); + + if (bgp_update_delay_active( + bgp)) { + json_object_string_add( + json, + "updateDelayFirstNeighbor", + bgp->update_delay_begin_time); + json_object_boolean_true_add( + json, + "updateDelayInProgress"); + } else { + if (bgp->update_delay_over) { + json_object_string_add( + json, + "updateDelayFirstNeighbor", + bgp->update_delay_begin_time); + json_object_string_add( + json, + "updateDelayBestpathResumed", + bgp->update_delay_end_time); + json_object_string_add( + json, + "updateDelayZebraUpdateResume", + bgp->update_delay_zebra_resume_time); + json_object_string_add( + json, + "updateDelayPeerUpdateResume", + bgp->update_delay_peers_resume_time); + } + } + } else { + vty_out(vty, + "Read-only mode update-delay limit: %d seconds\n", + bgp->v_update_delay); + if (bgp->v_update_delay + != bgp->v_establish_wait) + vty_out(vty, + " Establish wait: %d seconds\n", + bgp->v_establish_wait); + + if (bgp_update_delay_active( + bgp)) { + vty_out(vty, + " First neighbor established: %s\n", + bgp->update_delay_begin_time); + vty_out(vty, + " Delay in progress\n"); + } else { + if (bgp->update_delay_over) { + vty_out(vty, + " First neighbor established: %s\n", + bgp->update_delay_begin_time); + vty_out(vty, + " Best-paths resumed: %s\n", + bgp->update_delay_end_time); + vty_out(vty, + " zebra update resumed: %s\n", + bgp->update_delay_zebra_resume_time); + vty_out(vty, + " peers update resumed: %s\n", + bgp->update_delay_peers_resume_time); + } + } + } + } + + if (use_json) { + if (bgp_maxmed_onstartup_configured(bgp) + && bgp->maxmed_active) + json_object_boolean_true_add( + json, + "maxMedOnStartup"); + if (bgp->v_maxmed_admin) + json_object_boolean_true_add( + json, + "maxMedAdministrative"); + + json_object_int_add( + json, "tableVersion", + bgp_table_version( + bgp->rib[afi][safi])); + + ents = bgp_table_count( + bgp->rib[afi][safi]); + json_object_int_add(json, "ribCount", + ents); + json_object_int_add( + json, "ribMemory", + ents * sizeof(struct bgp_node)); + + ents = listcount(bgp->peer); + json_object_int_add(json, "peerCount", + ents); + json_object_int_add( + json, "peerMemory", + ents * sizeof(struct peer)); + + if ((ents = listcount(bgp->group))) { + json_object_int_add( + json, "peerGroupCount", + ents); + json_object_int_add( + json, "peerGroupMemory", + ents * sizeof(struct + peer_group)); + } + + if (CHECK_FLAG(bgp->af_flags[afi][safi], + BGP_CONFIG_DAMPENING)) + json_object_boolean_true_add( + json, + "dampeningEnabled"); + } else { + if (bgp_maxmed_onstartup_configured(bgp) + && bgp->maxmed_active) + vty_out(vty, + "Max-med on-startup active\n"); + if (bgp->v_maxmed_admin) + vty_out(vty, + "Max-med administrative active\n"); + + vty_out(vty, + "BGP table version %" PRIu64 + "\n", + bgp_table_version( + bgp->rib[afi][safi])); + + ents = bgp_table_count( + bgp->rib[afi][safi]); + vty_out(vty, + "RIB entries %ld, using %s of memory\n", + ents, + mtype_memstr( + memstrbuf, + sizeof(memstrbuf), + ents * sizeof(struct + bgp_node))); + + /* Peer related usage */ + ents = listcount(bgp->peer); + vty_out(vty, + "Peers %ld, using %s of memory\n", + ents, + mtype_memstr( + memstrbuf, + sizeof(memstrbuf), + ents * sizeof(struct + peer))); + + if ((ents = listcount(bgp->group))) + vty_out(vty, + "Peer groups %ld, using %s of memory\n", + ents, + mtype_memstr( + memstrbuf, + sizeof(memstrbuf), + ents * sizeof(struct + peer_group))); + + if (CHECK_FLAG(bgp->af_flags[afi][safi], + BGP_CONFIG_DAMPENING)) + vty_out(vty, + "Dampening enabled.\n"); + vty_out(vty, "\n"); + + /* Subtract 8 here because 'Neighbor' is + * 8 characters */ + vty_out(vty, "Neighbor"); + vty_out(vty, "%*s", + max_neighbor_width - 8, " "); + vty_out(vty, + "V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd\n"); + } + } + + count++; + + if (use_json) { + json_peer = json_object_new_object(); + + if (peer_dynamic_neighbor(peer)) + json_object_boolean_true_add( + json_peer, "dynamicPeer"); + + if (peer->hostname) + json_object_string_add(json_peer, + "hostname", + peer->hostname); + + if (peer->domainname) + json_object_string_add( + json_peer, "domainname", + peer->domainname); + + json_object_int_add(json_peer, "remoteAs", + peer->as); + json_object_int_add(json_peer, "version", 4); + json_object_int_add( + json_peer, "msgRcvd", + peer->open_in + peer->update_in + + peer->keepalive_in + + peer->notify_in + + peer->refresh_in + + peer->dynamic_cap_in); + json_object_int_add( + json_peer, "msgSent", + peer->open_out + peer->update_out + + peer->keepalive_out + + peer->notify_out + + peer->refresh_out + + peer->dynamic_cap_out); + + json_object_int_add(json_peer, "tableVersion", + peer->version[afi][safi]); + json_object_int_add(json_peer, "outq", + peer->obuf->count); + json_object_int_add(json_peer, "inq", 0); + peer_uptime(peer->uptime, timebuf, + BGP_UPTIME_LEN, use_json, + json_peer); + json_object_int_add( + json_peer, "prefixReceivedCount", + peer->pcount[afi][pfx_rcd_safi]); + + if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) + json_object_string_add(json_peer, + "state", + "Idle (Admin)"); + else if (CHECK_FLAG( + peer->sflags, + PEER_STATUS_PREFIX_OVERFLOW)) + json_object_string_add(json_peer, + "state", + "Idle (PfxCt)"); + else + json_object_string_add( + json_peer, "state", + lookup_msg(bgp_status_msg, + peer->status, NULL)); + + if (peer->conf_if) + json_object_string_add(json_peer, + "idType", + "interface"); + else if (peer->su.sa.sa_family == AF_INET) + json_object_string_add( + json_peer, "idType", "ipv4"); + else if (peer->su.sa.sa_family == AF_INET6) + json_object_string_add( + json_peer, "idType", "ipv6"); + + json_object_object_add(json_peers, peer->host, + json_peer); + } else { + memset(dn_flag, '\0', sizeof(dn_flag)); + if (peer_dynamic_neighbor(peer)) { + dn_count++; + dn_flag[0] = '*'; + } + + if (peer->hostname + && bgp_flag_check(bgp, + BGP_FLAG_SHOW_HOSTNAME)) + len = vty_out(vty, "%s%s(%s)", dn_flag, + peer->hostname, + peer->host); + else + len = vty_out(vty, "%s%s", dn_flag, + peer->host); + + /* pad the neighbor column with spaces */ + if (len < max_neighbor_width) + vty_out(vty, "%*s", + max_neighbor_width - len, " "); + + vty_out(vty, "4 %10u %7d %7d %8" PRIu64 + " %4d %4zd %8s", + peer->as, + peer->open_in + peer->update_in + + peer->keepalive_in + + peer->notify_in + + peer->refresh_in + + peer->dynamic_cap_in, + peer->open_out + peer->update_out + + peer->keepalive_out + + peer->notify_out + + peer->refresh_out + + peer->dynamic_cap_out, + peer->version[afi][safi], 0, + peer->obuf->count, + peer_uptime(peer->uptime, timebuf, + BGP_UPTIME_LEN, 0, NULL)); + + if (peer->status == Established) + vty_out(vty, " %12ld", + peer->pcount[afi] + [pfx_rcd_safi]); + else { + if (CHECK_FLAG(peer->flags, + PEER_FLAG_SHUTDOWN)) + vty_out(vty, " Idle (Admin)"); + else if ( + CHECK_FLAG( + peer->sflags, + PEER_STATUS_PREFIX_OVERFLOW)) + vty_out(vty, " Idle (PfxCt)"); + else + vty_out(vty, " %12s", + lookup_msg( + bgp_status_msg, + peer->status, + NULL)); + } + vty_out(vty, "\n"); + } + } + } - /* Originally we displayed the Neighbor column as 16 - * characters wide so make that the default - */ - if (max_neighbor_width < neighbor_col_default_width) - max_neighbor_width = neighbor_col_default_width; - } + if (use_json) { + json_object_object_add(json, "peers", json_peers); + + json_object_int_add(json, "totalPeers", count); + json_object_int_add(json, "dynamicPeers", dn_count); + + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else { + if (count) + vty_out(vty, "\nTotal number of neighbors %d\n", count); + else { + if (use_json) + vty_out(vty, + "{\"error\": {\"message\": \"No %s neighbor configured\"}}\n", + afi_safi_print(afi, safi)); + else + vty_out(vty, "No %s neighbor is configured\n", + afi_safi_print(afi, safi)); + } - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) - continue; + if (dn_count && !use_json) { + vty_out(vty, "* - dynamic neighbor\n"); + vty_out(vty, "%d dynamic neighbor(s), limit %d\n", + dn_count, bgp->dynamic_neighbors_limit); + } + } - if (peer->afc[afi][safi]) - { - if (!count) - { - unsigned long ents; - char memstrbuf[MTYPE_MEMSTR_LEN]; - int vrf_id_ui; - - vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN) ? -1 : bgp->vrf_id; - - /* Usage summary and header */ - if (use_json) - { - json_object_string_add(json, "routerId", inet_ntoa (bgp->router_id)); - json_object_int_add(json, "as", bgp->as); - json_object_int_add(json, "vrfId", vrf_id_ui); - json_object_string_add(json, "vrfName", - (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - ? "Default" : bgp->name); - } - else - { - vty_out (vty, - "BGP router identifier %s, local AS number %u vrf-id %d", - inet_ntoa (bgp->router_id), bgp->as, vrf_id_ui); - vty_out (vty, "\n"); - } - - if (bgp_update_delay_configured(bgp)) - { - if (use_json) - { - json_object_int_add(json, "updateDelayLimit", bgp->v_update_delay); - - if (bgp->v_update_delay != bgp->v_establish_wait) - json_object_int_add(json, "updateDelayEstablishWait", bgp->v_establish_wait); - - if (bgp_update_delay_active(bgp)) - { - json_object_string_add(json, "updateDelayFirstNeighbor", bgp->update_delay_begin_time); - json_object_boolean_true_add(json, "updateDelayInProgress"); - } - else - { - if (bgp->update_delay_over) - { - json_object_string_add(json, "updateDelayFirstNeighbor", - bgp->update_delay_begin_time); - json_object_string_add(json, "updateDelayBestpathResumed", - bgp->update_delay_end_time); - json_object_string_add(json, "updateDelayZebraUpdateResume", - bgp->update_delay_zebra_resume_time); - json_object_string_add(json, "updateDelayPeerUpdateResume", - bgp->update_delay_peers_resume_time); - } - } - } - else - { - vty_out (vty, "Read-only mode update-delay limit: %d seconds\n", - bgp->v_update_delay); - if (bgp->v_update_delay != bgp->v_establish_wait) - vty_out (vty, " Establish wait: %d seconds\n", - bgp->v_establish_wait); - - if (bgp_update_delay_active(bgp)) - { - vty_out (vty, " First neighbor established: %s\n", - bgp->update_delay_begin_time); - vty_out (vty, " Delay in progress\n"); - } - else - { - if (bgp->update_delay_over) - { - vty_out (vty, " First neighbor established: %s\n", - bgp->update_delay_begin_time); - vty_out (vty, " Best-paths resumed: %s\n", - bgp->update_delay_end_time); - vty_out (vty, " zebra update resumed: %s\n", - bgp->update_delay_zebra_resume_time); - vty_out (vty, " peers update resumed: %s\n", - bgp->update_delay_peers_resume_time); - } - } - } - } - - if (use_json) - { - if (bgp_maxmed_onstartup_configured(bgp) && bgp->maxmed_active) - json_object_boolean_true_add(json, "maxMedOnStartup"); - if (bgp->v_maxmed_admin) - json_object_boolean_true_add(json, "maxMedAdministrative"); - - json_object_int_add(json, "tableVersion", bgp_table_version(bgp->rib[afi][safi])); - - ents = bgp_table_count (bgp->rib[afi][safi]); - json_object_int_add(json, "ribCount", ents); - json_object_int_add(json, "ribMemory", ents * sizeof (struct bgp_node)); - - ents = listcount (bgp->peer); - json_object_int_add(json, "peerCount", ents); - json_object_int_add(json, "peerMemory", ents * sizeof (struct peer)); - - if ((ents = listcount (bgp->group))) - { - json_object_int_add(json, "peerGroupCount", ents); - json_object_int_add(json, "peerGroupMemory", ents * sizeof (struct peer_group)); - } - - if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) - json_object_boolean_true_add(json, "dampeningEnabled"); - } - else - { - if (bgp_maxmed_onstartup_configured(bgp) && bgp->maxmed_active) - vty_out (vty, "Max-med on-startup active\n"); - if (bgp->v_maxmed_admin) - vty_out (vty, "Max-med administrative active\n"); - - vty_out(vty, "BGP table version %" PRIu64 "\n", - bgp_table_version(bgp->rib[afi][safi])); - - ents = bgp_table_count (bgp->rib[afi][safi]); - vty_out (vty, "RIB entries %ld, using %s of memory\n", ents, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - ents * sizeof (struct bgp_node))); - - /* Peer related usage */ - ents = listcount (bgp->peer); - vty_out (vty, "Peers %ld, using %s of memory\n", - ents, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - ents * sizeof (struct peer))); - - if ((ents = listcount (bgp->group))) - vty_out (vty, "Peer groups %ld, using %s of memory\n", ents, - mtype_memstr (memstrbuf, sizeof (memstrbuf), - ents * sizeof (struct peer_group))); - - if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) - vty_out (vty, "Dampening enabled.\n"); - vty_out (vty, "\n"); - - /* Subtract 8 here because 'Neighbor' is 8 characters */ - vty_out (vty, "Neighbor"); - vty_out (vty, "%*s", max_neighbor_width - 8, " "); - vty_out (vty, "V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd\n"); - } - } - - count++; - - if (use_json) - { - json_peer = json_object_new_object(); - - if (peer_dynamic_neighbor(peer)) - json_object_boolean_true_add(json_peer, "dynamicPeer"); - - if (peer->hostname) - json_object_string_add(json_peer, "hostname", peer->hostname); - - if (peer->domainname) - json_object_string_add(json_peer, "domainname", peer->domainname); - - json_object_int_add(json_peer, "remoteAs", peer->as); - json_object_int_add(json_peer, "version", 4); - json_object_int_add(json_peer, "msgRcvd", - peer->open_in + peer->update_in + peer->keepalive_in - + peer->notify_in + peer->refresh_in - + peer->dynamic_cap_in); - json_object_int_add(json_peer, "msgSent", - peer->open_out + peer->update_out + peer->keepalive_out - + peer->notify_out + peer->refresh_out - + peer->dynamic_cap_out); - - json_object_int_add(json_peer, "tableVersion", peer->version[afi][safi]); - json_object_int_add(json_peer, "outq", peer->obuf->count); - json_object_int_add(json_peer, "inq", 0); - peer_uptime (peer->uptime, timebuf, BGP_UPTIME_LEN, use_json, json_peer); - json_object_int_add(json_peer, "prefixReceivedCount", peer->pcount[afi][pfx_rcd_safi]); - - if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN)) - json_object_string_add(json_peer, "state", "Idle (Admin)"); - else if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW)) - json_object_string_add(json_peer, "state", "Idle (PfxCt)"); - else - json_object_string_add(json_peer, "state", lookup_msg(bgp_status_msg, peer->status, NULL)); - - if (peer->conf_if) - json_object_string_add(json_peer, "idType", "interface"); - else if (peer->su.sa.sa_family == AF_INET) - json_object_string_add(json_peer, "idType", "ipv4"); - else if (peer->su.sa.sa_family == AF_INET6) - json_object_string_add(json_peer, "idType", "ipv6"); - - json_object_object_add(json_peers, peer->host, json_peer); - } - else - { - memset(dn_flag, '\0', sizeof(dn_flag)); - if (peer_dynamic_neighbor(peer)) - { - dn_count++; - dn_flag[0] = '*'; - } - - if (peer->hostname && bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME)) - len = vty_out (vty, "%s%s(%s)", dn_flag, peer->hostname, - peer->host); - else - len = vty_out (vty, "%s%s", dn_flag, peer->host); - - /* pad the neighbor column with spaces */ - if (len < max_neighbor_width) - vty_out (vty, "%*s", max_neighbor_width - len, " "); - - vty_out (vty, "4 %10u %7d %7d %8" PRIu64 " %4d %4zd %8s", - peer->as, - peer->open_in + peer->update_in + peer->keepalive_in - + peer->notify_in + peer->refresh_in - + peer->dynamic_cap_in, - peer->open_out + peer->update_out + peer->keepalive_out - + peer->notify_out + peer->refresh_out - + peer->dynamic_cap_out, - peer->version[afi][safi], - 0, - peer->obuf->count, - peer_uptime (peer->uptime, timebuf, BGP_UPTIME_LEN, 0, NULL)); - - if (peer->status == Established) - vty_out (vty, " %12ld", peer->pcount[afi][pfx_rcd_safi]); - else - { - if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN)) - vty_out (vty, " Idle (Admin)"); - else if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW)) - vty_out (vty, " Idle (PfxCt)"); - else - vty_out (vty, " %12s", lookup_msg(bgp_status_msg, peer->status, NULL)); - } - vty_out (vty, "\n"); - } - } - } - - if (use_json) - { - json_object_object_add(json, "peers", json_peers); - - json_object_int_add(json, "totalPeers", count); - json_object_int_add(json, "dynamicPeers", dn_count); - - vty_out (vty, "%s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - { - if (count) - vty_out (vty, "\nTotal number of neighbors %d\n", - count); - else - { - if (use_json) - vty_out(vty, "{\"error\": {\"message\": \"No %s neighbor configured\"}}\n", - afi_safi_print(afi, safi)); - else - vty_out (vty, "No %s neighbor is configured\n", - afi_safi_print(afi, safi)); - } - - if (dn_count && ! use_json) - { - vty_out(vty, "* - dynamic neighbor\n"); - vty_out(vty, - "%d dynamic neighbor(s), limit %d\n", - dn_count, bgp->dynamic_neighbors_limit); - } - } - - return CMD_SUCCESS; + return CMD_SUCCESS; } /* * Return if we have a peer configured to use this afi/safi */ -static int -bgp_show_summary_afi_safi_peer_exists (struct bgp *bgp, int afi, int safi) -{ - struct listnode *node; - struct peer *peer; - - for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer)) - { - if (!CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)) - continue; - - if (peer->afc[afi][safi]) - return 1; - } - - return 0; -} - -static void -bgp_show_summary_afi_safi (struct vty *vty, struct bgp *bgp, int afi, int safi, - u_char use_json, json_object *json) -{ - int is_first = 1; - int afi_wildcard = (afi == AFI_MAX); - int safi_wildcard = (safi == SAFI_MAX); - int is_wildcard = (afi_wildcard || safi_wildcard); - bool json_output = false; - - if (use_json && is_wildcard) - vty_out (vty, "{\n"); - if (afi_wildcard) - afi = 1; /* AFI_IP */ - while (afi < AFI_MAX) - { - if (safi_wildcard) - safi = 1; /* SAFI_UNICAST */ - while (safi < SAFI_MAX) - { - if (bgp_show_summary_afi_safi_peer_exists (bgp, afi, safi)) - { - json_output = true; - if (is_wildcard) - { - /* - * So limit output to those afi/safi pairs that - * actualy have something interesting in them - */ - if (use_json) - { - json = json_object_new_object(); - - if (! is_first) - vty_out (vty, ",\n"); - else - is_first = 0; - - vty_out(vty, "\"%s\":", afi_safi_json(afi, safi)); - } - else - { - vty_out (vty, "\n%s Summary:\n", afi_safi_print(afi, safi)); - } - } - bgp_show_summary (vty, bgp, afi, safi, use_json, json); - } - safi++; - if (safi == SAFI_RESERVED_4 || - safi == SAFI_RESERVED_5) /* handle special cases to match zebra.h */ - safi++; - if (! safi_wildcard) - safi = SAFI_MAX; - } - afi++; - if (! afi_wildcard || - afi == AFI_L2VPN) /* special case, not handled yet */ - afi = AFI_MAX; - } - - if (use_json && is_wildcard) - vty_out (vty, "}\n"); - else if (use_json && !json_output) - vty_out (vty, "{}\n"); -} - -static void -bgp_show_all_instances_summary_vty (struct vty *vty, afi_t afi, safi_t safi, - u_char use_json) -{ - struct listnode *node, *nnode; - struct bgp *bgp; - json_object *json = NULL; - int is_first = 1; - - if (use_json) - vty_out (vty, "{\n"); - - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - { - if (use_json) - { - json = json_object_new_object(); - - if (! is_first) - vty_out (vty, ",\n"); - else - is_first = 0; - - vty_out(vty, "\"%s\":", (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - ? "Default" : bgp->name); - } - else - { - vty_out (vty, "\nInstance %s:\n", - (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - ? "Default" : bgp->name); - } - bgp_show_summary_afi_safi (vty, bgp, afi, safi, use_json, json); - } - - if (use_json) - vty_out (vty, "}\n"); - -} - -int -bgp_show_summary_vty (struct vty *vty, const char *name, - afi_t afi, safi_t safi, u_char use_json) -{ - struct bgp *bgp; - - if (name) - { - if (strmatch(name, "all")) - { - bgp_show_all_instances_summary_vty (vty, afi, safi, use_json); - return CMD_SUCCESS; - } - else - { - bgp = bgp_lookup_by_name (name); - - if (! bgp) - { - if (use_json) - vty_out (vty, "{}\n"); - else - vty_out (vty, "%% No such BGP instance exist\n"); - return CMD_WARNING; - } - - bgp_show_summary_afi_safi (vty, bgp, afi, safi, use_json, NULL); - return CMD_SUCCESS; - } - } - - bgp = bgp_get_default (); - - if (bgp) - bgp_show_summary_afi_safi (vty, bgp, afi, safi, use_json, NULL); - - return CMD_SUCCESS; +static int bgp_show_summary_afi_safi_peer_exists(struct bgp *bgp, int afi, + int safi) +{ + struct listnode *node; + struct peer *peer; + + for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) { + if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) + continue; + + if (peer->afc[afi][safi]) + return 1; + } + + return 0; +} + +static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi, + int safi, u_char use_json, + json_object *json) +{ + int is_first = 1; + int afi_wildcard = (afi == AFI_MAX); + int safi_wildcard = (safi == SAFI_MAX); + int is_wildcard = (afi_wildcard || safi_wildcard); + bool json_output = false; + + if (use_json && is_wildcard) + vty_out(vty, "{\n"); + if (afi_wildcard) + afi = 1; /* AFI_IP */ + while (afi < AFI_MAX) { + if (safi_wildcard) + safi = 1; /* SAFI_UNICAST */ + while (safi < SAFI_MAX) { + if (bgp_show_summary_afi_safi_peer_exists(bgp, afi, + safi)) { + json_output = true; + if (is_wildcard) { + /* + * So limit output to those afi/safi + * pairs that + * actualy have something interesting in + * them + */ + if (use_json) { + json = json_object_new_object(); + + if (!is_first) + vty_out(vty, ",\n"); + else + is_first = 0; + + vty_out(vty, "\"%s\":", + afi_safi_json(afi, + safi)); + } else { + vty_out(vty, "\n%s Summary:\n", + afi_safi_print(afi, + safi)); + } + } + bgp_show_summary(vty, bgp, afi, safi, use_json, + json); + } + safi++; + if (safi == SAFI_RESERVED_4 + || safi + == SAFI_RESERVED_5) /* handle special + cases to match + zebra.h */ + safi++; + if (!safi_wildcard) + safi = SAFI_MAX; + } + afi++; + if (!afi_wildcard + || afi == AFI_L2VPN) /* special case, not handled yet */ + afi = AFI_MAX; + } + + if (use_json && is_wildcard) + vty_out(vty, "}\n"); + else if (use_json && !json_output) + vty_out(vty, "{}\n"); +} + +static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi, + safi_t safi, u_char use_json) +{ + struct listnode *node, *nnode; + struct bgp *bgp; + json_object *json = NULL; + int is_first = 1; + + if (use_json) + vty_out(vty, "{\n"); + + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) { + if (use_json) { + json = json_object_new_object(); + + if (!is_first) + vty_out(vty, ",\n"); + else + is_first = 0; + + vty_out(vty, "\"%s\":", + (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) + ? "Default" + : bgp->name); + } else { + vty_out(vty, "\nInstance %s:\n", + (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) + ? "Default" + : bgp->name); + } + bgp_show_summary_afi_safi(vty, bgp, afi, safi, use_json, json); + } + + if (use_json) + vty_out(vty, "}\n"); +} + +int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, + safi_t safi, u_char use_json) +{ + struct bgp *bgp; + + if (name) { + if (strmatch(name, "all")) { + bgp_show_all_instances_summary_vty(vty, afi, safi, + use_json); + return CMD_SUCCESS; + } else { + bgp = bgp_lookup_by_name(name); + + if (!bgp) { + if (use_json) + vty_out(vty, "{}\n"); + else + vty_out(vty, + "%% No such BGP instance exist\n"); + return CMD_WARNING; + } + + bgp_show_summary_afi_safi(vty, bgp, afi, safi, use_json, + NULL); + return CMD_SUCCESS; + } + } + + bgp = bgp_get_default(); + + if (bgp) + bgp_show_summary_afi_safi(vty, bgp, afi, safi, use_json, NULL); + + return CMD_SUCCESS; } /* `show [ip] bgp summary' commands. */ @@ -7309,56 +7159,55 @@ DEFUN (show_ip_bgp_summary, "Summary of BGP neighbor status\n" JSON_STR) { - char *vrf = NULL; - afi_t afi = AFI_MAX; - safi_t safi = SAFI_MAX; - - int idx = 0; - - /* show [ip] bgp */ - if (argv_find (argv, argc, "ip", &idx)) - afi = AFI_IP; - /* [ VIEWVRFNAME] */ - if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx)) - vrf = argv[++idx]->arg; - /* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */ - if (argv_find_and_parse_afi (argv, argc, &idx, &afi)) - { - argv_find_and_parse_safi (argv, argc, &idx, &safi); - } - - int uj = use_json (argc, argv); - - return bgp_show_summary_vty (vty, vrf, afi, safi, uj); -} - -const char * -afi_safi_print (afi_t afi, safi_t safi) -{ - if (afi == AFI_IP && safi == SAFI_UNICAST) - return "IPv4 Unicast"; - else if (afi == AFI_IP && safi == SAFI_MULTICAST) - return "IPv4 Multicast"; - else if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) - return "IPv4 Labeled Unicast"; - else if (afi == AFI_IP && safi == SAFI_MPLS_VPN) - return "IPv4 VPN"; - else if (afi == AFI_IP && safi == SAFI_ENCAP) - return "IPv4 Encap"; - else if (afi == AFI_IP6 && safi == SAFI_UNICAST) - return "IPv6 Unicast"; - else if (afi == AFI_IP6 && safi == SAFI_MULTICAST) - return "IPv6 Multicast"; - else if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) - return "IPv6 Labeled Unicast"; - else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN) - return "IPv6 VPN"; - else if (afi == AFI_IP6 && safi == SAFI_ENCAP) - return "IPv6 Encap"; - else if (afi == AFI_L2VPN && safi == SAFI_EVPN) - return "L2VPN EVPN"; - else - return "Unknown"; + char *vrf = NULL; + afi_t afi = AFI_MAX; + safi_t safi = SAFI_MAX; + + int idx = 0; + + /* show [ip] bgp */ + if (argv_find(argv, argc, "ip", &idx)) + afi = AFI_IP; + /* [ VIEWVRFNAME] */ + if (argv_find(argv, argc, "view", &idx) + || argv_find(argv, argc, "vrf", &idx)) + vrf = argv[++idx]->arg; + /* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */ + if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) { + argv_find_and_parse_safi(argv, argc, &idx, &safi); + } + + int uj = use_json(argc, argv); + + return bgp_show_summary_vty(vty, vrf, afi, safi, uj); +} + +const char *afi_safi_print(afi_t afi, safi_t safi) +{ + if (afi == AFI_IP && safi == SAFI_UNICAST) + return "IPv4 Unicast"; + else if (afi == AFI_IP && safi == SAFI_MULTICAST) + return "IPv4 Multicast"; + else if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) + return "IPv4 Labeled Unicast"; + else if (afi == AFI_IP && safi == SAFI_MPLS_VPN) + return "IPv4 VPN"; + else if (afi == AFI_IP && safi == SAFI_ENCAP) + return "IPv4 Encap"; + else if (afi == AFI_IP6 && safi == SAFI_UNICAST) + return "IPv6 Unicast"; + else if (afi == AFI_IP6 && safi == SAFI_MULTICAST) + return "IPv6 Multicast"; + else if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) + return "IPv6 Labeled Unicast"; + else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN) + return "IPv6 VPN"; + else if (afi == AFI_IP6 && safi == SAFI_ENCAP) + return "IPv6 Encap"; + else if (afi == AFI_L2VPN && safi == SAFI_EVPN) + return "L2VPN EVPN"; + else + return "Unknown"; } /* @@ -7367,1865 +7216,2531 @@ afi_safi_print (afi_t afi, safi_t safi) * to use this function, please ensure you * are doing this within json output */ -const char * -afi_safi_json (afi_t afi, safi_t safi) -{ - if (afi == AFI_IP && safi == SAFI_UNICAST) - return "ipv4Unicast"; - else if (afi == AFI_IP && safi == SAFI_MULTICAST) - return "ipv4Multicast"; - else if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) - return "ipv4LabeledUnicast"; - else if (afi == AFI_IP && safi == SAFI_MPLS_VPN) - return "ipv4Vpn"; - else if (afi == AFI_IP && safi == SAFI_ENCAP) - return "ipv4Encap"; - else if (afi == AFI_IP6 && safi == SAFI_UNICAST) - return "ipv6Unicast"; - else if (afi == AFI_IP6 && safi == SAFI_MULTICAST) - return "ipv6Multicast"; - else if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) - return "ipv6LabeledUnicast"; - else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN) - return "ipv6Vpn"; - else if (afi == AFI_IP6 && safi == SAFI_ENCAP) - return "ipv6Encap"; - else if (afi == AFI_L2VPN && safi == SAFI_EVPN) - return "l2VpnEvpn"; - else - return "Unknown"; +const char *afi_safi_json(afi_t afi, safi_t safi) +{ + if (afi == AFI_IP && safi == SAFI_UNICAST) + return "ipv4Unicast"; + else if (afi == AFI_IP && safi == SAFI_MULTICAST) + return "ipv4Multicast"; + else if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) + return "ipv4LabeledUnicast"; + else if (afi == AFI_IP && safi == SAFI_MPLS_VPN) + return "ipv4Vpn"; + else if (afi == AFI_IP && safi == SAFI_ENCAP) + return "ipv4Encap"; + else if (afi == AFI_IP6 && safi == SAFI_UNICAST) + return "ipv6Unicast"; + else if (afi == AFI_IP6 && safi == SAFI_MULTICAST) + return "ipv6Multicast"; + else if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) + return "ipv6LabeledUnicast"; + else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN) + return "ipv6Vpn"; + else if (afi == AFI_IP6 && safi == SAFI_ENCAP) + return "ipv6Encap"; + else if (afi == AFI_L2VPN && safi == SAFI_EVPN) + return "l2VpnEvpn"; + else + return "Unknown"; } /* Show BGP peer's information. */ -enum show_type +enum show_type { show_all, show_peer }; + +static void bgp_show_peer_afi_orf_cap(struct vty *vty, struct peer *p, + afi_t afi, safi_t safi, + u_int16_t adv_smcap, u_int16_t adv_rmcap, + u_int16_t rcv_smcap, u_int16_t rcv_rmcap, + u_char use_json, json_object *json_pref) +{ + /* Send-Mode */ + if (CHECK_FLAG(p->af_cap[afi][safi], adv_smcap) + || CHECK_FLAG(p->af_cap[afi][safi], rcv_smcap)) { + if (use_json) { + if (CHECK_FLAG(p->af_cap[afi][safi], adv_smcap) + && CHECK_FLAG(p->af_cap[afi][safi], rcv_smcap)) + json_object_string_add(json_pref, "sendMode", + "advertisedAndReceived"); + else if (CHECK_FLAG(p->af_cap[afi][safi], adv_smcap)) + json_object_string_add(json_pref, "sendMode", + "advertised"); + else if (CHECK_FLAG(p->af_cap[afi][safi], rcv_smcap)) + json_object_string_add(json_pref, "sendMode", + "received"); + } else { + vty_out(vty, " Send-mode: "); + if (CHECK_FLAG(p->af_cap[afi][safi], adv_smcap)) + vty_out(vty, "advertised"); + if (CHECK_FLAG(p->af_cap[afi][safi], rcv_smcap)) + vty_out(vty, "%sreceived", + CHECK_FLAG(p->af_cap[afi][safi], + adv_smcap) + ? ", " + : ""); + vty_out(vty, "\n"); + } + } + + /* Receive-Mode */ + if (CHECK_FLAG(p->af_cap[afi][safi], adv_rmcap) + || CHECK_FLAG(p->af_cap[afi][safi], rcv_rmcap)) { + if (use_json) { + if (CHECK_FLAG(p->af_cap[afi][safi], adv_rmcap) + && CHECK_FLAG(p->af_cap[afi][safi], rcv_rmcap)) + json_object_string_add(json_pref, "recvMode", + "advertisedAndReceived"); + else if (CHECK_FLAG(p->af_cap[afi][safi], adv_rmcap)) + json_object_string_add(json_pref, "recvMode", + "advertised"); + else if (CHECK_FLAG(p->af_cap[afi][safi], rcv_rmcap)) + json_object_string_add(json_pref, "recvMode", + "received"); + } else { + vty_out(vty, " Receive-mode: "); + if (CHECK_FLAG(p->af_cap[afi][safi], adv_rmcap)) + vty_out(vty, "advertised"); + if (CHECK_FLAG(p->af_cap[afi][safi], rcv_rmcap)) + vty_out(vty, "%sreceived", + CHECK_FLAG(p->af_cap[afi][safi], + adv_rmcap) + ? ", " + : ""); + vty_out(vty, "\n"); + } + } +} + +static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi, + safi_t safi, u_char use_json, + json_object *json_neigh) +{ + struct bgp_filter *filter; + struct peer_af *paf; + char orf_pfx_name[BUFSIZ]; + int orf_pfx_count; + json_object *json_af = NULL; + json_object *json_prefA = NULL; + json_object *json_prefB = NULL; + json_object *json_addr = NULL; + + if (use_json) { + json_addr = json_object_new_object(); + json_af = json_object_new_object(); + filter = &p->filter[afi][safi]; + + if (peer_group_active(p)) + json_object_string_add(json_addr, "peerGroupMember", + p->group->name); + + paf = peer_af_find(p, afi, safi); + if (paf && PAF_SUBGRP(paf)) { + json_object_int_add(json_addr, "updateGroupId", + PAF_UPDGRP(paf)->id); + json_object_int_add(json_addr, "subGroupId", + PAF_SUBGRP(paf)->id); + json_object_int_add(json_addr, "packetQueueLength", + bpacket_queue_virtual_length(paf)); + } + + if (CHECK_FLAG(p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_SM_RCV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_ADV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_RCV)) { + json_object_int_add(json_af, "orfType", + ORF_TYPE_PREFIX); + json_prefA = json_object_new_object(); + bgp_show_peer_afi_orf_cap(vty, p, afi, safi, + PEER_CAP_ORF_PREFIX_SM_ADV, + PEER_CAP_ORF_PREFIX_RM_ADV, + PEER_CAP_ORF_PREFIX_SM_RCV, + PEER_CAP_ORF_PREFIX_RM_RCV, + use_json, json_prefA); + json_object_object_add(json_af, "orfPrefixList", + json_prefA); + } + + if (CHECK_FLAG(p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_SM_OLD_RCV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_ADV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_OLD_RCV)) { + json_object_int_add(json_af, "orfOldType", + ORF_TYPE_PREFIX_OLD); + json_prefB = json_object_new_object(); + bgp_show_peer_afi_orf_cap( + vty, p, afi, safi, PEER_CAP_ORF_PREFIX_SM_ADV, + PEER_CAP_ORF_PREFIX_RM_ADV, + PEER_CAP_ORF_PREFIX_SM_OLD_RCV, + PEER_CAP_ORF_PREFIX_RM_OLD_RCV, use_json, + json_prefB); + json_object_object_add(json_af, "orfOldPrefixList", + json_prefB); + } + + if (CHECK_FLAG(p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_SM_RCV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_SM_OLD_RCV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_ADV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_RCV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_OLD_RCV)) + json_object_object_add(json_addr, "afDependentCap", + json_af); + else + json_object_free(json_af); + + sprintf(orf_pfx_name, "%s.%d.%d", p->host, afi, safi); + orf_pfx_count = prefix_bgp_show_prefix_list( + NULL, afi, orf_pfx_name, use_json); + + if (CHECK_FLAG(p->af_sflags[afi][safi], + PEER_STATUS_ORF_PREFIX_SEND) + || orf_pfx_count) { + if (CHECK_FLAG(p->af_sflags[afi][safi], + PEER_STATUS_ORF_PREFIX_SEND)) + json_object_boolean_true_add(json_neigh, + "orfSent"); + if (orf_pfx_count) + json_object_int_add(json_addr, "orfRecvCounter", + orf_pfx_count); + } + if (CHECK_FLAG(p->af_sflags[afi][safi], + PEER_STATUS_ORF_WAIT_REFRESH)) + json_object_string_add( + json_addr, "orfFirstUpdate", + "deferredUntilORFOrRouteRefreshRecvd"); + + if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_REFLECTOR_CLIENT)) + json_object_boolean_true_add(json_addr, + "routeReflectorClient"); + if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_RSERVER_CLIENT)) + json_object_boolean_true_add(json_addr, + "routeServerClient"); + if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)) + json_object_boolean_true_add(json_addr, + "inboundSoftConfigPermit"); + + if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) + json_object_boolean_true_add( + json_addr, + "privateAsNumsAllReplacedInUpdatesToNbr"); + else if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) + json_object_boolean_true_add( + json_addr, + "privateAsNumsReplacedInUpdatesToNbr"); + else if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) + json_object_boolean_true_add( + json_addr, + "privateAsNumsAllRemovedInUpdatesToNbr"); + else if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_REMOVE_PRIVATE_AS)) + json_object_boolean_true_add( + json_addr, + "privateAsNumsRemovedInUpdatesToNbr"); + + if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_ADDPATH_TX_ALL_PATHS)) + json_object_boolean_true_add(json_addr, + "addpathTxAllPaths"); + + if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) + json_object_boolean_true_add(json_addr, + "addpathTxBestpathPerAS"); + + if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_AS_OVERRIDE)) + json_object_string_add(json_addr, + "overrideASNsInOutboundUpdates", + "ifAspathEqualRemoteAs"); + + if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF) + || CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_FORCE_NEXTHOP_SELF)) + json_object_boolean_true_add(json_addr, + "routerAlwaysNextHop"); + if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_AS_PATH_UNCHANGED)) + json_object_boolean_true_add( + json_addr, "unchangedAsPathPropogatedToNbr"); + if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_NEXTHOP_UNCHANGED)) + json_object_boolean_true_add( + json_addr, "unchangedNextHopPropogatedToNbr"); + if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) + json_object_boolean_true_add( + json_addr, "unchangedMedPropogatedToNbr"); + if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY) + || CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_SEND_EXT_COMMUNITY)) { + if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_SEND_COMMUNITY) + && CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_SEND_EXT_COMMUNITY)) + json_object_string_add(json_addr, + "commAttriSentToNbr", + "extendedAndStandard"); + else if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_SEND_EXT_COMMUNITY)) + json_object_string_add(json_addr, + "commAttriSentToNbr", + "extended"); + else + json_object_string_add(json_addr, + "commAttriSentToNbr", + "standard"); + } + if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_DEFAULT_ORIGINATE)) { + if (p->default_rmap[afi][safi].name) + json_object_string_add( + json_addr, "defaultRouteMap", + p->default_rmap[afi][safi].name); + + if (paf && PAF_SUBGRP(paf) + && CHECK_FLAG(PAF_SUBGRP(paf)->sflags, + SUBGRP_STATUS_DEFAULT_ORIGINATE)) + json_object_boolean_true_add(json_addr, + "defaultSent"); + else + json_object_boolean_true_add(json_addr, + "defaultNotSent"); + } + + if (filter->plist[FILTER_IN].name + || filter->dlist[FILTER_IN].name + || filter->aslist[FILTER_IN].name + || filter->map[RMAP_IN].name) + json_object_boolean_true_add(json_addr, + "inboundPathPolicyConfig"); + if (filter->plist[FILTER_OUT].name + || filter->dlist[FILTER_OUT].name + || filter->aslist[FILTER_OUT].name + || filter->map[RMAP_OUT].name || filter->usmap.name) + json_object_boolean_true_add( + json_addr, "outboundPathPolicyConfig"); + + /* prefix-list */ + if (filter->plist[FILTER_IN].name) + json_object_string_add(json_addr, + "incomingUpdatePrefixFilterList", + filter->plist[FILTER_IN].name); + if (filter->plist[FILTER_OUT].name) + json_object_string_add(json_addr, + "outgoingUpdatePrefixFilterList", + filter->plist[FILTER_OUT].name); + + /* distribute-list */ + if (filter->dlist[FILTER_IN].name) + json_object_string_add( + json_addr, "incomingUpdateNetworkFilterList", + filter->dlist[FILTER_IN].name); + if (filter->dlist[FILTER_OUT].name) + json_object_string_add( + json_addr, "outgoingUpdateNetworkFilterList", + filter->dlist[FILTER_OUT].name); + + /* filter-list. */ + if (filter->aslist[FILTER_IN].name) + json_object_string_add(json_addr, + "incomingUpdateAsPathFilterList", + filter->aslist[FILTER_IN].name); + if (filter->aslist[FILTER_OUT].name) + json_object_string_add(json_addr, + "outgoingUpdateAsPathFilterList", + filter->aslist[FILTER_OUT].name); + + /* route-map. */ + if (filter->map[RMAP_IN].name) + json_object_string_add( + json_addr, "routeMapForIncomingAdvertisements", + filter->map[RMAP_IN].name); + if (filter->map[RMAP_OUT].name) + json_object_string_add( + json_addr, "routeMapForOutgoingAdvertisements", + filter->map[RMAP_OUT].name); + + /* unsuppress-map */ + if (filter->usmap.name) + json_object_string_add(json_addr, + "selectiveUnsuppressRouteMap", + filter->usmap.name); + + /* Receive prefix count */ + json_object_int_add(json_addr, "acceptedPrefixCounter", + p->pcount[afi][safi]); + + /* Maximum prefix */ + if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) { + json_object_int_add(json_addr, "prefixAllowedMax", + p->pmax[afi][safi]); + if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING)) + json_object_boolean_true_add( + json_addr, "prefixAllowedMaxWarning"); + json_object_int_add(json_addr, + "prefixAllowedWarningThresh", + p->pmax_threshold[afi][safi]); + if (p->pmax_restart[afi][safi]) + json_object_int_add( + json_addr, + "prefixAllowedRestartIntervalMsecs", + p->pmax_restart[afi][safi] * 60000); + } + json_object_object_add(json_neigh, afi_safi_print(afi, safi), + json_addr); + + } else { + filter = &p->filter[afi][safi]; + + vty_out(vty, " For address family: %s\n", + afi_safi_print(afi, safi)); + + if (peer_group_active(p)) + vty_out(vty, " %s peer-group member\n", + p->group->name); + + paf = peer_af_find(p, afi, safi); + if (paf && PAF_SUBGRP(paf)) { + vty_out(vty, " Update group %" PRIu64 + ", subgroup %" PRIu64 "\n", + PAF_UPDGRP(paf)->id, PAF_SUBGRP(paf)->id); + vty_out(vty, " Packet Queue length %d\n", + bpacket_queue_virtual_length(paf)); + } else { + vty_out(vty, " Not part of any update group\n"); + } + if (CHECK_FLAG(p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_SM_RCV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_SM_OLD_RCV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_ADV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_RCV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_OLD_RCV)) + vty_out(vty, " AF-dependant capabilities:\n"); + + if (CHECK_FLAG(p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_SM_RCV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_ADV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_RCV)) { + vty_out(vty, + " Outbound Route Filter (ORF) type (%d) Prefix-list:\n", + ORF_TYPE_PREFIX); + bgp_show_peer_afi_orf_cap( + vty, p, afi, safi, PEER_CAP_ORF_PREFIX_SM_ADV, + PEER_CAP_ORF_PREFIX_RM_ADV, + PEER_CAP_ORF_PREFIX_SM_RCV, + PEER_CAP_ORF_PREFIX_RM_RCV, use_json, NULL); + } + if (CHECK_FLAG(p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_SM_OLD_RCV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_ADV) + || CHECK_FLAG(p->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_OLD_RCV)) { + vty_out(vty, + " Outbound Route Filter (ORF) type (%d) Prefix-list:\n", + ORF_TYPE_PREFIX_OLD); + bgp_show_peer_afi_orf_cap( + vty, p, afi, safi, PEER_CAP_ORF_PREFIX_SM_ADV, + PEER_CAP_ORF_PREFIX_RM_ADV, + PEER_CAP_ORF_PREFIX_SM_OLD_RCV, + PEER_CAP_ORF_PREFIX_RM_OLD_RCV, use_json, NULL); + } + + sprintf(orf_pfx_name, "%s.%d.%d", p->host, afi, safi); + orf_pfx_count = prefix_bgp_show_prefix_list( + NULL, afi, orf_pfx_name, use_json); + + if (CHECK_FLAG(p->af_sflags[afi][safi], + PEER_STATUS_ORF_PREFIX_SEND) + || orf_pfx_count) { + vty_out(vty, " Outbound Route Filter (ORF):"); + if (CHECK_FLAG(p->af_sflags[afi][safi], + PEER_STATUS_ORF_PREFIX_SEND)) + vty_out(vty, " sent;"); + if (orf_pfx_count) + vty_out(vty, " received (%d entries)", + orf_pfx_count); + vty_out(vty, "\n"); + } + if (CHECK_FLAG(p->af_sflags[afi][safi], + PEER_STATUS_ORF_WAIT_REFRESH)) + vty_out(vty, + " First update is deferred until ORF or ROUTE-REFRESH is received\n"); + + if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_REFLECTOR_CLIENT)) + vty_out(vty, " Route-Reflector Client\n"); + if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_RSERVER_CLIENT)) + vty_out(vty, " Route-Server Client\n"); + if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)) + vty_out(vty, + " Inbound soft reconfiguration allowed\n"); + + if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) + vty_out(vty, + " Private AS numbers (all) replaced in updates to this neighbor\n"); + else if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) + vty_out(vty, + " Private AS numbers replaced in updates to this neighbor\n"); + else if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) + vty_out(vty, + " Private AS numbers (all) removed in updates to this neighbor\n"); + else if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_REMOVE_PRIVATE_AS)) + vty_out(vty, + " Private AS numbers removed in updates to this neighbor\n"); + + if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_ADDPATH_TX_ALL_PATHS)) + vty_out(vty, " Advertise all paths via addpath\n"); + + if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) + vty_out(vty, + " Advertise bestpath per AS via addpath\n"); + + if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_AS_OVERRIDE)) + vty_out(vty, + " Override ASNs in outbound updates if aspath equals remote-as\n"); + + if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF) + || CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_FORCE_NEXTHOP_SELF)) + vty_out(vty, " NEXT_HOP is always this router\n"); + if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_AS_PATH_UNCHANGED)) + vty_out(vty, + " AS_PATH is propagated unchanged to this neighbor\n"); + if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_NEXTHOP_UNCHANGED)) + vty_out(vty, + " NEXT_HOP is propagated unchanged to this neighbor\n"); + if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) + vty_out(vty, + " MED is propagated unchanged to this neighbor\n"); + if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY) + || CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_SEND_EXT_COMMUNITY) + || CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_SEND_LARGE_COMMUNITY)) { + vty_out(vty, + " Community attribute sent to this neighbor"); + if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_SEND_COMMUNITY) + && CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_SEND_EXT_COMMUNITY) + && CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_SEND_LARGE_COMMUNITY)) + vty_out(vty, "(all)\n"); + else if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_SEND_LARGE_COMMUNITY)) + vty_out(vty, "(large)\n"); + else if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_SEND_EXT_COMMUNITY)) + vty_out(vty, "(extended)\n"); + else + vty_out(vty, "(standard)\n"); + } + if (CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_DEFAULT_ORIGINATE)) { + vty_out(vty, " Default information originate,"); + + if (p->default_rmap[afi][safi].name) + vty_out(vty, " default route-map %s%s,", + p->default_rmap[afi][safi].map ? "*" + : "", + p->default_rmap[afi][safi].name); + if (paf && PAF_SUBGRP(paf) + && CHECK_FLAG(PAF_SUBGRP(paf)->sflags, + SUBGRP_STATUS_DEFAULT_ORIGINATE)) + vty_out(vty, " default sent\n"); + else + vty_out(vty, " default not sent\n"); + } + + if (filter->plist[FILTER_IN].name + || filter->dlist[FILTER_IN].name + || filter->aslist[FILTER_IN].name + || filter->map[RMAP_IN].name) + vty_out(vty, " Inbound path policy configured\n"); + if (filter->plist[FILTER_OUT].name + || filter->dlist[FILTER_OUT].name + || filter->aslist[FILTER_OUT].name + || filter->map[RMAP_OUT].name || filter->usmap.name) + vty_out(vty, " Outbound path policy configured\n"); + + /* prefix-list */ + if (filter->plist[FILTER_IN].name) + vty_out(vty, + " Incoming update prefix filter list is %s%s\n", + filter->plist[FILTER_IN].plist ? "*" : "", + filter->plist[FILTER_IN].name); + if (filter->plist[FILTER_OUT].name) + vty_out(vty, + " Outgoing update prefix filter list is %s%s\n", + filter->plist[FILTER_OUT].plist ? "*" : "", + filter->plist[FILTER_OUT].name); + + /* distribute-list */ + if (filter->dlist[FILTER_IN].name) + vty_out(vty, + " Incoming update network filter list is %s%s\n", + filter->dlist[FILTER_IN].alist ? "*" : "", + filter->dlist[FILTER_IN].name); + if (filter->dlist[FILTER_OUT].name) + vty_out(vty, + " Outgoing update network filter list is %s%s\n", + filter->dlist[FILTER_OUT].alist ? "*" : "", + filter->dlist[FILTER_OUT].name); + + /* filter-list. */ + if (filter->aslist[FILTER_IN].name) + vty_out(vty, + " Incoming update AS path filter list is %s%s\n", + filter->aslist[FILTER_IN].aslist ? "*" : "", + filter->aslist[FILTER_IN].name); + if (filter->aslist[FILTER_OUT].name) + vty_out(vty, + " Outgoing update AS path filter list is %s%s\n", + filter->aslist[FILTER_OUT].aslist ? "*" : "", + filter->aslist[FILTER_OUT].name); + + /* route-map. */ + if (filter->map[RMAP_IN].name) + vty_out(vty, + " Route map for incoming advertisements is %s%s\n", + filter->map[RMAP_IN].map ? "*" : "", + filter->map[RMAP_IN].name); + if (filter->map[RMAP_OUT].name) + vty_out(vty, + " Route map for outgoing advertisements is %s%s\n", + filter->map[RMAP_OUT].map ? "*" : "", + filter->map[RMAP_OUT].name); + + /* unsuppress-map */ + if (filter->usmap.name) + vty_out(vty, + " Route map for selective unsuppress is %s%s\n", + filter->usmap.map ? "*" : "", + filter->usmap.name); + + /* Receive prefix count */ + vty_out(vty, " %ld accepted prefixes\n", p->pcount[afi][safi]); + + /* Maximum prefix */ + if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) { + vty_out(vty, " Maximum prefixes allowed %ld%s\n", + p->pmax[afi][safi], + CHECK_FLAG(p->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING) + ? " (warning-only)" + : ""); + vty_out(vty, " Threshold for warning message %d%%", + p->pmax_threshold[afi][safi]); + if (p->pmax_restart[afi][safi]) + vty_out(vty, ", restart interval %d min", + p->pmax_restart[afi][safi]); + vty_out(vty, "\n"); + } + + vty_out(vty, "\n"); + } +} + +static void bgp_show_peer(struct vty *vty, struct peer *p, u_char use_json, + json_object *json) { - show_all, - show_peer -}; + struct bgp *bgp; + char buf1[PREFIX2STR_BUFFER], buf[SU_ADDRSTRLEN]; + char timebuf[BGP_UPTIME_LEN]; + char dn_flag[2]; + const char *subcode_str; + const char *code_str; + afi_t afi; + safi_t safi; + u_int16_t i; + u_char *msg; + json_object *json_neigh = NULL; + time_t epoch_tbuf; -static void -bgp_show_peer_afi_orf_cap (struct vty *vty, struct peer *p, afi_t afi, safi_t safi, - u_int16_t adv_smcap, u_int16_t adv_rmcap, u_int16_t rcv_smcap, - u_int16_t rcv_rmcap, u_char use_json, json_object *json_pref) -{ - /* Send-Mode */ - if (CHECK_FLAG (p->af_cap[afi][safi], adv_smcap) - || CHECK_FLAG (p->af_cap[afi][safi], rcv_smcap)) - { - if (use_json) - { - if (CHECK_FLAG (p->af_cap[afi][safi], adv_smcap) && CHECK_FLAG (p->af_cap[afi][safi], rcv_smcap)) - json_object_string_add(json_pref, "sendMode", "advertisedAndReceived"); - else if (CHECK_FLAG (p->af_cap[afi][safi], adv_smcap)) - json_object_string_add(json_pref, "sendMode", "advertised"); - else if (CHECK_FLAG (p->af_cap[afi][safi], rcv_smcap)) - json_object_string_add(json_pref, "sendMode", "received"); - } - else - { - vty_out (vty, " Send-mode: "); - if (CHECK_FLAG (p->af_cap[afi][safi], adv_smcap)) - vty_out (vty, "advertised"); - if (CHECK_FLAG (p->af_cap[afi][safi], rcv_smcap)) - vty_out (vty, "%sreceived", - CHECK_FLAG (p->af_cap[afi][safi], adv_smcap) ? - ", " : ""); - vty_out (vty, "\n"); - } - } - - /* Receive-Mode */ - if (CHECK_FLAG (p->af_cap[afi][safi], adv_rmcap) - || CHECK_FLAG (p->af_cap[afi][safi], rcv_rmcap)) - { - if (use_json) - { - if (CHECK_FLAG (p->af_cap[afi][safi], adv_rmcap) && CHECK_FLAG (p->af_cap[afi][safi], rcv_rmcap)) - json_object_string_add(json_pref, "recvMode", "advertisedAndReceived"); - else if (CHECK_FLAG (p->af_cap[afi][safi], adv_rmcap)) - json_object_string_add(json_pref, "recvMode", "advertised"); - else if (CHECK_FLAG (p->af_cap[afi][safi], rcv_rmcap)) - json_object_string_add(json_pref, "recvMode", "received"); - } - else - { - vty_out (vty, " Receive-mode: "); - if (CHECK_FLAG (p->af_cap[afi][safi], adv_rmcap)) - vty_out (vty, "advertised"); - if (CHECK_FLAG (p->af_cap[afi][safi], rcv_rmcap)) - vty_out (vty, "%sreceived", - CHECK_FLAG (p->af_cap[afi][safi], adv_rmcap) ? - ", " : ""); - vty_out (vty, "\n"); - } - } -} - -static void -bgp_show_peer_afi (struct vty *vty, struct peer *p, afi_t afi, safi_t safi, - u_char use_json, json_object *json_neigh) -{ - struct bgp_filter *filter; - struct peer_af *paf; - char orf_pfx_name[BUFSIZ]; - int orf_pfx_count; - json_object *json_af = NULL; - json_object *json_prefA = NULL; - json_object *json_prefB = NULL; - json_object *json_addr = NULL; - - if (use_json) - { - json_addr = json_object_new_object(); - json_af = json_object_new_object(); - filter = &p->filter[afi][safi]; - - if (peer_group_active(p)) - json_object_string_add(json_addr, "peerGroupMember", p->group->name); - - paf = peer_af_find(p, afi, safi); - if (paf && PAF_SUBGRP(paf)) - { - json_object_int_add(json_addr, "updateGroupId", PAF_UPDGRP(paf)->id); - json_object_int_add(json_addr, "subGroupId", PAF_SUBGRP(paf)->id); - json_object_int_add(json_addr, "packetQueueLength", bpacket_queue_virtual_length(paf)); - } - - if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)) - { - json_object_int_add(json_af, "orfType", ORF_TYPE_PREFIX); - json_prefA = json_object_new_object(); - bgp_show_peer_afi_orf_cap (vty, p, afi, safi, - PEER_CAP_ORF_PREFIX_SM_ADV, - PEER_CAP_ORF_PREFIX_RM_ADV, - PEER_CAP_ORF_PREFIX_SM_RCV, - PEER_CAP_ORF_PREFIX_RM_RCV, use_json, json_prefA); - json_object_object_add(json_af, "orfPrefixList", json_prefA); - } - - if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)) - { - json_object_int_add(json_af, "orfOldType", ORF_TYPE_PREFIX_OLD); - json_prefB = json_object_new_object(); - bgp_show_peer_afi_orf_cap (vty, p, afi, safi, - PEER_CAP_ORF_PREFIX_SM_ADV, - PEER_CAP_ORF_PREFIX_RM_ADV, - PEER_CAP_ORF_PREFIX_SM_OLD_RCV, - PEER_CAP_ORF_PREFIX_RM_OLD_RCV, use_json, json_prefB); - json_object_object_add(json_af, "orfOldPrefixList", json_prefB); - } - - if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)) - json_object_object_add(json_addr, "afDependentCap", json_af); - else - json_object_free(json_af); - - sprintf (orf_pfx_name, "%s.%d.%d", p->host, afi, safi); - orf_pfx_count = prefix_bgp_show_prefix_list (NULL, afi, orf_pfx_name, use_json); - - if (CHECK_FLAG (p->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND) - || orf_pfx_count) - { - if (CHECK_FLAG (p->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND)) - json_object_boolean_true_add(json_neigh, "orfSent"); - if (orf_pfx_count) - json_object_int_add(json_addr, "orfRecvCounter", orf_pfx_count); - } - if (CHECK_FLAG (p->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH)) - json_object_string_add(json_addr, "orfFirstUpdate", "deferredUntilORFOrRouteRefreshRecvd"); - - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) - json_object_boolean_true_add(json_addr, "routeReflectorClient"); - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)) - json_object_boolean_true_add(json_addr, "routeServerClient"); - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)) - json_object_boolean_true_add(json_addr, "inboundSoftConfigPermit"); - - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) - json_object_boolean_true_add(json_addr, "privateAsNumsAllReplacedInUpdatesToNbr"); - else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) - json_object_boolean_true_add(json_addr, "privateAsNumsReplacedInUpdatesToNbr"); - else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) - json_object_boolean_true_add(json_addr, "privateAsNumsAllRemovedInUpdatesToNbr"); - else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS)) - json_object_boolean_true_add(json_addr, "privateAsNumsRemovedInUpdatesToNbr"); - - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS)) - json_object_boolean_true_add(json_addr, "addpathTxAllPaths"); - - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) - json_object_boolean_true_add(json_addr, "addpathTxBestpathPerAS"); - - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_AS_OVERRIDE)) - json_object_string_add(json_addr, "overrideASNsInOutboundUpdates", "ifAspathEqualRemoteAs"); - - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF) || - CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_FORCE_NEXTHOP_SELF)) - json_object_boolean_true_add(json_addr, "routerAlwaysNextHop"); - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) - json_object_boolean_true_add(json_addr, "unchangedAsPathPropogatedToNbr"); - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) - json_object_boolean_true_add(json_addr, "unchangedNextHopPropogatedToNbr"); - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) - json_object_boolean_true_add(json_addr, "unchangedMedPropogatedToNbr"); - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY) - || CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)) - { - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY) - && CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)) - json_object_string_add(json_addr, "commAttriSentToNbr", "extendedAndStandard"); - else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)) - json_object_string_add(json_addr, "commAttriSentToNbr", "extended"); - else - json_object_string_add(json_addr, "commAttriSentToNbr", "standard"); - } - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)) - { - if (p->default_rmap[afi][safi].name) - json_object_string_add(json_addr, "defaultRouteMap", p->default_rmap[afi][safi].name); - - if (paf && PAF_SUBGRP(paf) && CHECK_FLAG(PAF_SUBGRP(paf)->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) - json_object_boolean_true_add(json_addr, "defaultSent"); - else - json_object_boolean_true_add(json_addr, "defaultNotSent"); - } - - if (filter->plist[FILTER_IN].name - || filter->dlist[FILTER_IN].name - || filter->aslist[FILTER_IN].name - || filter->map[RMAP_IN].name) - json_object_boolean_true_add(json_addr, "inboundPathPolicyConfig"); - if (filter->plist[FILTER_OUT].name - || filter->dlist[FILTER_OUT].name - || filter->aslist[FILTER_OUT].name - || filter->map[RMAP_OUT].name - || filter->usmap.name) - json_object_boolean_true_add(json_addr, "outboundPathPolicyConfig"); - - /* prefix-list */ - if (filter->plist[FILTER_IN].name) - json_object_string_add(json_addr, "incomingUpdatePrefixFilterList", filter->plist[FILTER_IN].name); - if (filter->plist[FILTER_OUT].name) - json_object_string_add(json_addr, "outgoingUpdatePrefixFilterList", filter->plist[FILTER_OUT].name); - - /* distribute-list */ - if (filter->dlist[FILTER_IN].name) - json_object_string_add(json_addr, "incomingUpdateNetworkFilterList", filter->dlist[FILTER_IN].name); - if (filter->dlist[FILTER_OUT].name) - json_object_string_add(json_addr, "outgoingUpdateNetworkFilterList", filter->dlist[FILTER_OUT].name); - - /* filter-list. */ - if (filter->aslist[FILTER_IN].name) - json_object_string_add(json_addr, "incomingUpdateAsPathFilterList", filter->aslist[FILTER_IN].name); - if (filter->aslist[FILTER_OUT].name) - json_object_string_add(json_addr, "outgoingUpdateAsPathFilterList", filter->aslist[FILTER_OUT].name); - - /* route-map. */ - if (filter->map[RMAP_IN].name) - json_object_string_add(json_addr, "routeMapForIncomingAdvertisements", filter->map[RMAP_IN].name); - if (filter->map[RMAP_OUT].name) - json_object_string_add(json_addr, "routeMapForOutgoingAdvertisements", filter->map[RMAP_OUT].name); - - /* unsuppress-map */ - if (filter->usmap.name) - json_object_string_add(json_addr, "selectiveUnsuppressRouteMap", filter->usmap.name); - - /* Receive prefix count */ - json_object_int_add(json_addr, "acceptedPrefixCounter", p->pcount[afi][safi]); - - /* Maximum prefix */ - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) - { - json_object_int_add(json_addr, "prefixAllowedMax", p->pmax[afi][safi]); - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)) - json_object_boolean_true_add(json_addr, "prefixAllowedMaxWarning"); - json_object_int_add(json_addr, "prefixAllowedWarningThresh", p->pmax_threshold[afi][safi]); - if (p->pmax_restart[afi][safi]) - json_object_int_add(json_addr, "prefixAllowedRestartIntervalMsecs", p->pmax_restart[afi][safi] * 60000); - } - json_object_object_add(json_neigh, afi_safi_print (afi, safi), json_addr); - - } - else - { - filter = &p->filter[afi][safi]; - - vty_out (vty, " For address family: %s\n", afi_safi_print (afi, safi)); - - if (peer_group_active(p)) - vty_out (vty, " %s peer-group member\n", p->group->name); - - paf = peer_af_find(p, afi, safi); - if (paf && PAF_SUBGRP(paf)) - { - vty_out (vty, " Update group %" PRIu64 ", subgroup %" PRIu64 "\n", - PAF_UPDGRP(paf)->id, PAF_SUBGRP(paf)->id); - vty_out (vty, " Packet Queue length %d\n", - bpacket_queue_virtual_length(paf)); - } - else - { - vty_out(vty, " Not part of any update group\n"); - } - if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)) - vty_out (vty, " AF-dependant capabilities:\n"); - - if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)) - { - vty_out (vty, " Outbound Route Filter (ORF) type (%d) Prefix-list:\n", - ORF_TYPE_PREFIX); - bgp_show_peer_afi_orf_cap (vty, p, afi, safi, - PEER_CAP_ORF_PREFIX_SM_ADV, - PEER_CAP_ORF_PREFIX_RM_ADV, - PEER_CAP_ORF_PREFIX_SM_RCV, - PEER_CAP_ORF_PREFIX_RM_RCV, use_json, NULL); - } - if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV) - || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)) - { - vty_out (vty, " Outbound Route Filter (ORF) type (%d) Prefix-list:\n", - ORF_TYPE_PREFIX_OLD); - bgp_show_peer_afi_orf_cap (vty, p, afi, safi, - PEER_CAP_ORF_PREFIX_SM_ADV, - PEER_CAP_ORF_PREFIX_RM_ADV, - PEER_CAP_ORF_PREFIX_SM_OLD_RCV, - PEER_CAP_ORF_PREFIX_RM_OLD_RCV, use_json, NULL); - } - - sprintf (orf_pfx_name, "%s.%d.%d", p->host, afi, safi); - orf_pfx_count = prefix_bgp_show_prefix_list (NULL, afi, orf_pfx_name, use_json); - - if (CHECK_FLAG (p->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND) - || orf_pfx_count) - { - vty_out (vty, " Outbound Route Filter (ORF):"); - if (CHECK_FLAG (p->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND)) - vty_out (vty, " sent;"); - if (orf_pfx_count) - vty_out (vty, " received (%d entries)", orf_pfx_count); - vty_out (vty, "\n"); - } - if (CHECK_FLAG (p->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH)) - vty_out (vty, " First update is deferred until ORF or ROUTE-REFRESH is received\n"); - - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) - vty_out (vty, " Route-Reflector Client\n"); - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)) - vty_out (vty, " Route-Server Client\n"); - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)) - vty_out (vty, " Inbound soft reconfiguration allowed\n"); - - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) - vty_out (vty, " Private AS numbers (all) replaced in updates to this neighbor\n"); - else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) - vty_out (vty, " Private AS numbers replaced in updates to this neighbor\n"); - else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) - vty_out (vty, " Private AS numbers (all) removed in updates to this neighbor\n"); - else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS)) - vty_out (vty, " Private AS numbers removed in updates to this neighbor\n"); - - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS)) - vty_out (vty, " Advertise all paths via addpath\n"); - - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) - vty_out (vty, " Advertise bestpath per AS via addpath\n"); - - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_AS_OVERRIDE)) - vty_out (vty, " Override ASNs in outbound updates if aspath equals remote-as\n"); - - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF) || - CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_FORCE_NEXTHOP_SELF)) - vty_out (vty, " NEXT_HOP is always this router\n"); - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) - vty_out (vty, " AS_PATH is propagated unchanged to this neighbor\n"); - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) - vty_out (vty, " NEXT_HOP is propagated unchanged to this neighbor\n"); - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) - vty_out (vty, " MED is propagated unchanged to this neighbor\n"); - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY) - || CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY) - || CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY)) - { - vty_out (vty, " Community attribute sent to this neighbor"); - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY) - && CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY) - && CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY)) - vty_out (vty, "(all)\n"); - else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY)) - vty_out (vty, "(large)\n"); - else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)) - vty_out (vty, "(extended)\n"); - else - vty_out (vty, "(standard)\n"); - } - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)) - { - vty_out (vty, " Default information originate,"); - - if (p->default_rmap[afi][safi].name) - vty_out (vty, " default route-map %s%s,", - p->default_rmap[afi][safi].map ? "*" : "", - p->default_rmap[afi][safi].name); - if (paf && PAF_SUBGRP(paf) && CHECK_FLAG(PAF_SUBGRP(paf)->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) - vty_out (vty, " default sent\n"); - else - vty_out (vty, " default not sent\n"); - } - - if (filter->plist[FILTER_IN].name - || filter->dlist[FILTER_IN].name - || filter->aslist[FILTER_IN].name - || filter->map[RMAP_IN].name) - vty_out (vty, " Inbound path policy configured\n"); - if (filter->plist[FILTER_OUT].name - || filter->dlist[FILTER_OUT].name - || filter->aslist[FILTER_OUT].name - || filter->map[RMAP_OUT].name - || filter->usmap.name) - vty_out (vty, " Outbound path policy configured\n"); - - /* prefix-list */ - if (filter->plist[FILTER_IN].name) - vty_out (vty, " Incoming update prefix filter list is %s%s\n", - filter->plist[FILTER_IN].plist ? "*" : "", - filter->plist[FILTER_IN].name); - if (filter->plist[FILTER_OUT].name) - vty_out (vty, " Outgoing update prefix filter list is %s%s\n", - filter->plist[FILTER_OUT].plist ? "*" : "", - filter->plist[FILTER_OUT].name); - - /* distribute-list */ - if (filter->dlist[FILTER_IN].name) - vty_out (vty, " Incoming update network filter list is %s%s\n", - filter->dlist[FILTER_IN].alist ? "*" : "", - filter->dlist[FILTER_IN].name); - if (filter->dlist[FILTER_OUT].name) - vty_out (vty, " Outgoing update network filter list is %s%s\n", - filter->dlist[FILTER_OUT].alist ? "*" : "", - filter->dlist[FILTER_OUT].name); - - /* filter-list. */ - if (filter->aslist[FILTER_IN].name) - vty_out (vty, " Incoming update AS path filter list is %s%s\n", - filter->aslist[FILTER_IN].aslist ? "*" : "", - filter->aslist[FILTER_IN].name); - if (filter->aslist[FILTER_OUT].name) - vty_out (vty, " Outgoing update AS path filter list is %s%s\n", - filter->aslist[FILTER_OUT].aslist ? "*" : "", - filter->aslist[FILTER_OUT].name); - - /* route-map. */ - if (filter->map[RMAP_IN].name) - vty_out (vty, " Route map for incoming advertisements is %s%s\n", - filter->map[RMAP_IN].map ? "*" : "", - filter->map[RMAP_IN].name); - if (filter->map[RMAP_OUT].name) - vty_out (vty, " Route map for outgoing advertisements is %s%s\n", - filter->map[RMAP_OUT].map ? "*" : "", - filter->map[RMAP_OUT].name); - - /* unsuppress-map */ - if (filter->usmap.name) - vty_out (vty, " Route map for selective unsuppress is %s%s\n", - filter->usmap.map ? "*" : "", - filter->usmap.name); - - /* Receive prefix count */ - vty_out (vty, " %ld accepted prefixes\n", p->pcount[afi][safi]); - - /* Maximum prefix */ - if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) - { - vty_out (vty, " Maximum prefixes allowed %ld%s\n", p->pmax[afi][safi], - CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING) - ? " (warning-only)" : ""); - vty_out (vty, " Threshold for warning message %d%%", - p->pmax_threshold[afi][safi]); - if (p->pmax_restart[afi][safi]) - vty_out (vty, ", restart interval %d min", p->pmax_restart[afi][safi]); - vty_out (vty, "\n"); - } - - vty_out (vty, "\n"); - } -} - -static void -bgp_show_peer (struct vty *vty, struct peer *p, u_char use_json, json_object *json) -{ - struct bgp *bgp; - char buf1[PREFIX2STR_BUFFER], buf[SU_ADDRSTRLEN]; - char timebuf[BGP_UPTIME_LEN]; - char dn_flag[2]; - const char *subcode_str; - const char *code_str; - afi_t afi; - safi_t safi; - u_int16_t i; - u_char *msg; - json_object *json_neigh = NULL; - time_t epoch_tbuf; - - bgp = p->bgp; - - if (use_json) - json_neigh = json_object_new_object(); - - memset (dn_flag, '\0', sizeof (dn_flag)); - if (!p->conf_if && peer_dynamic_neighbor (p)) - dn_flag[0] = '*'; - - if (!use_json) - { - if (p->conf_if) /* Configured interface name. */ - vty_out (vty, "BGP neighbor on %s: %s, ", p->conf_if, - BGP_PEER_SU_UNSPEC(p) ? "None" : - sockunion2str (&p->su, buf, SU_ADDRSTRLEN)); - else /* Configured IP address. */ - vty_out (vty, "BGP neighbor is %s%s, ", dn_flag, p->host); - } - - if (use_json) - { - if (p->conf_if && BGP_PEER_SU_UNSPEC(p)) - json_object_string_add(json_neigh, "bgpNeighborAddr", "none"); - else if (p->conf_if && !BGP_PEER_SU_UNSPEC(p)) - json_object_string_add(json_neigh, "bgpNeighborAddr", sockunion2str (&p->su, buf, SU_ADDRSTRLEN)); - - json_object_int_add(json_neigh, "remoteAs", p->as); - - if (p->change_local_as) - json_object_int_add(json_neigh, "localAs", p->change_local_as); - else - json_object_int_add(json_neigh, "localAs", p->local_as); - - if (CHECK_FLAG (p->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)) - json_object_boolean_true_add(json_neigh, "localAsNoPrepend"); - - if (CHECK_FLAG (p->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS)) - json_object_boolean_true_add(json_neigh, "localAsReplaceAs"); - } - else - { - if ((p->as_type == AS_SPECIFIED) || - (p->as_type == AS_EXTERNAL) || - (p->as_type == AS_INTERNAL)) - vty_out (vty, "remote AS %u, ", p->as); - else - vty_out (vty, "remote AS Unspecified, "); - vty_out (vty, "local AS %u%s%s, ", - p->change_local_as ? p->change_local_as : p->local_as, - CHECK_FLAG (p->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ? - " no-prepend" : "", - CHECK_FLAG (p->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ? - " replace-as" : ""); - } - /* peer type internal, external, confed-internal or confed-external */ - if (p->as == p->local_as) - { - if (use_json) - { - if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) - json_object_boolean_true_add(json_neigh, "nbrConfedInternalLink"); - else - json_object_boolean_true_add(json_neigh, "nbrInternalLink"); - } - else - { - if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) - vty_out (vty, "confed-internal link\n"); - else - vty_out (vty, "internal link\n"); - } - } - else - { - if (use_json) - { - if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) - json_object_boolean_true_add(json_neigh, "nbrConfedExternalLink"); - else - json_object_boolean_true_add(json_neigh, "nbrExternalLink"); - } - else - { - if (bgp_confederation_peers_check(bgp, p->as)) - vty_out (vty, "confed-external link\n"); - else - vty_out (vty, "external link\n"); - } - } - - /* Description. */ - if (p->desc) - { - if (use_json) - json_object_string_add(json_neigh, "nbrDesc", p->desc); - else - vty_out (vty, " Description: %s\n", p->desc); - } - - if (p->hostname) - { - if (use_json) - { - if (p->hostname) - json_object_string_add(json_neigh, "hostname", p->hostname); - - if (p->domainname) - json_object_string_add(json_neigh, "domainname", p->domainname); - } - else - { - if (p->domainname && (p->domainname[0] != '\0')) - vty_out(vty, "Hostname: %s.%s\n", p->hostname, p->domainname); - else - vty_out(vty, "Hostname: %s\n", p->hostname); - } - - } - - /* Peer-group */ - if (p->group) - { - if (use_json) - { - json_object_string_add(json_neigh, "peerGroup", p->group->name); - - if (dn_flag[0]) - { - struct prefix prefix, *range = NULL; - - sockunion2hostprefix(&(p->su), &prefix); - range = peer_group_lookup_dynamic_neighbor_range (p->group, &prefix); - - if (range) - { - prefix2str(range, buf1, sizeof(buf1)); - json_object_string_add(json_neigh, "peerSubnetRangeGroup", buf1); - } - } - } - else - { - vty_out (vty, " Member of peer-group %s for session parameters\n", - p->group->name); - - if (dn_flag[0]) - { - struct prefix prefix, *range = NULL; - - sockunion2hostprefix(&(p->su), &prefix); - range = peer_group_lookup_dynamic_neighbor_range (p->group, &prefix); - - if (range) - { - prefix2str(range, buf1, sizeof(buf1)); - vty_out (vty, " Belongs to the subnet range group: %s\n", buf1); - } - } - } - } - - if (use_json) - { - /* Administrative shutdown. */ - if (CHECK_FLAG (p->flags, PEER_FLAG_SHUTDOWN)) - json_object_boolean_true_add(json_neigh, "adminShutDown"); - - /* BGP Version. */ - json_object_int_add(json_neigh, "bgpVersion", 4); - json_object_string_add(json_neigh, "remoteRouterId", - inet_ntop (AF_INET, &p->remote_id, buf1, sizeof(buf1))); - - /* Confederation */ - if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION) && bgp_confederation_peers_check (bgp, p->as)) - json_object_boolean_true_add(json_neigh, "nbrCommonAdmin"); - - /* Status. */ - json_object_string_add(json_neigh, "bgpState", lookup_msg(bgp_status_msg, p->status, NULL)); - - if (p->status == Established) - { - time_t uptime; - struct tm *tm; - - uptime = bgp_clock(); - uptime -= p->uptime; - tm = gmtime(&uptime); - epoch_tbuf = time(NULL) - uptime; - - json_object_int_add(json_neigh, "bgpTimerUp", (tm->tm_sec * 1000) + (tm->tm_min * 60000) + (tm->tm_hour * 3600000)); - json_object_string_add(json_neigh, "bgpTimerUpString", peer_uptime (p->uptime, timebuf, BGP_UPTIME_LEN, 0, NULL)); - json_object_int_add(json_neigh, "bgpTimerUpEstablishedEpoch", epoch_tbuf); - } - - else if (p->status == Active) - { - if (CHECK_FLAG (p->flags, PEER_FLAG_PASSIVE)) - json_object_string_add(json_neigh, "bgpStateIs", "passive"); - else if (CHECK_FLAG (p->sflags, PEER_STATUS_NSF_WAIT)) - json_object_string_add(json_neigh, "bgpStateIs", "passiveNSF"); - } - - /* read timer */ - time_t uptime; - struct tm *tm; - - uptime = bgp_clock(); - uptime -= p->readtime; - tm = gmtime(&uptime); - json_object_int_add(json_neigh, "bgpTimerLastRead", (tm->tm_sec * 1000) + (tm->tm_min * 60000) + (tm->tm_hour * 3600000)); - - uptime = bgp_clock(); - uptime -= p->last_write; - tm = gmtime(&uptime); - json_object_int_add(json_neigh, "bgpTimerLastWrite", (tm->tm_sec * 1000) + (tm->tm_min * 60000) + (tm->tm_hour * 3600000)); - - uptime = bgp_clock(); - uptime -= p->update_time; - tm = gmtime(&uptime); - json_object_int_add(json_neigh, "bgpInUpdateElapsedTimeMsecs", - (tm->tm_sec * 1000) + (tm->tm_min * 60000) + (tm->tm_hour * 3600000)); - - /* Configured timer values. */ - json_object_int_add(json_neigh, "bgpTimerHoldTimeMsecs", p->v_holdtime * 1000); - json_object_int_add(json_neigh, "bgpTimerKeepAliveIntervalMsecs", p->v_keepalive * 1000); - - if (CHECK_FLAG (p->config, PEER_CONFIG_TIMER)) - { - json_object_int_add(json_neigh, "bgpTimerConfiguredHoldTimeMsecs", p->holdtime * 1000); - json_object_int_add(json_neigh, "bgpTimerConfiguredKeepAliveIntervalMsecs", p->keepalive * 1000); - } - } - else - { - /* Administrative shutdown. */ - if (CHECK_FLAG (p->flags, PEER_FLAG_SHUTDOWN)) - vty_out (vty, " Administratively shut down\n"); - - /* BGP Version. */ - vty_out (vty, " BGP version 4"); - vty_out (vty, ", remote router ID %s\n", - inet_ntop (AF_INET, &p->remote_id, buf1, sizeof(buf1))); - - /* Confederation */ - if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION) - && bgp_confederation_peers_check (bgp, p->as)) - vty_out (vty, " Neighbor under common administration\n"); - - /* Status. */ - vty_out (vty, " BGP state = %s", lookup_msg(bgp_status_msg, p->status, NULL)); - - if (p->status == Established) - vty_out (vty, ", up for %8s", peer_uptime (p->uptime, timebuf, BGP_UPTIME_LEN, 0, NULL)); - - else if (p->status == Active) - { - if (CHECK_FLAG (p->flags, PEER_FLAG_PASSIVE)) - vty_out (vty, " (passive)"); - else if (CHECK_FLAG (p->sflags, PEER_STATUS_NSF_WAIT)) - vty_out (vty, " (NSF passive)"); - } - vty_out (vty, "\n"); - - /* read timer */ - vty_out (vty, " Last read %s", peer_uptime (p->readtime, timebuf, BGP_UPTIME_LEN, 0, NULL)); - vty_out (vty, ", Last write %s\n", - peer_uptime (p->last_write, timebuf, BGP_UPTIME_LEN, 0, NULL)); - - /* Configured timer values. */ - vty_out (vty, " Hold time is %d, keepalive interval is %d seconds\n", - p->v_holdtime, p->v_keepalive); - if (CHECK_FLAG (p->config, PEER_CONFIG_TIMER)) - { - vty_out (vty, " Configured hold time is %d", p->holdtime); - vty_out (vty, ", keepalive interval is %d seconds\n", - p->keepalive); - } - } - /* Capability. */ - if (p->status == Established) - { - if (p->cap - || p->afc_adv[AFI_IP][SAFI_UNICAST] - || p->afc_recv[AFI_IP][SAFI_UNICAST] - || p->afc_adv[AFI_IP][SAFI_MULTICAST] - || p->afc_recv[AFI_IP][SAFI_MULTICAST] - || p->afc_adv[AFI_IP6][SAFI_UNICAST] - || p->afc_recv[AFI_IP6][SAFI_UNICAST] - || p->afc_adv[AFI_IP6][SAFI_MULTICAST] - || p->afc_recv[AFI_IP6][SAFI_MULTICAST] - || p->afc_adv[AFI_IP6][SAFI_MPLS_VPN] - || p->afc_recv[AFI_IP6][SAFI_MPLS_VPN] - || p->afc_adv[AFI_IP6][SAFI_ENCAP] - || p->afc_recv[AFI_IP6][SAFI_ENCAP] - || p->afc_adv[AFI_IP][SAFI_ENCAP] - || p->afc_recv[AFI_IP][SAFI_ENCAP] - || p->afc_adv[AFI_IP][SAFI_MPLS_VPN] - || p->afc_recv[AFI_IP][SAFI_MPLS_VPN]) - { - if (use_json) - { - json_object *json_cap = NULL; - - json_cap = json_object_new_object(); - - /* AS4 */ - if (CHECK_FLAG (p->cap, PEER_CAP_AS4_RCV) - || CHECK_FLAG (p->cap, PEER_CAP_AS4_ADV)) - { - if (CHECK_FLAG (p->cap, PEER_CAP_AS4_ADV) && CHECK_FLAG (p->cap, PEER_CAP_AS4_RCV)) - json_object_string_add(json_cap, "4byteAs", "advertisedAndReceived"); - else if (CHECK_FLAG (p->cap, PEER_CAP_AS4_ADV)) - json_object_string_add(json_cap, "4byteAs", "advertised"); - else if (CHECK_FLAG (p->cap, PEER_CAP_AS4_RCV)) - json_object_string_add(json_cap, "4byteAs", "received"); - } - - /* AddPath */ - if (CHECK_FLAG (p->cap, PEER_CAP_ADDPATH_RCV) - || CHECK_FLAG (p->cap, PEER_CAP_ADDPATH_ADV)) - { - json_object *json_add = NULL; - const char *print_store; - - json_add = json_object_new_object(); - - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - json_object *json_sub = NULL; - json_sub = json_object_new_object(); - print_store = afi_safi_print (afi, safi); - - if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_ADV) || - CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV)) - { - if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_ADV) && CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV)) - json_object_boolean_true_add(json_sub, "txAdvertisedAndReceived"); - else if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_ADV)) - json_object_boolean_true_add(json_sub, "txAdvertised"); - else if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV)) - json_object_boolean_true_add(json_sub, "txReceived"); - } - - if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) || - CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_RCV)) - { - if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) && CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_RCV)) - json_object_boolean_true_add(json_sub, "rxAdvertisedAndReceived"); - else if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)) - json_object_boolean_true_add(json_sub, "rxAdvertised"); - else if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_RCV)) - json_object_boolean_true_add(json_sub, "rxReceived"); - } - - if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_ADV) || - CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV) || - CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) || - CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_RCV)) - json_object_object_add(json_add, print_store, json_sub); - else - json_object_free(json_sub); - } - - json_object_object_add(json_cap, "addPath", json_add); - } - - /* Dynamic */ - if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_RCV) - || CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_ADV)) - { - if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_ADV) && CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_RCV)) - json_object_string_add(json_cap, "dynamic", "advertisedAndReceived"); - else if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_ADV)) - json_object_string_add(json_cap, "dynamic", "advertised"); - else if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_RCV)) - json_object_string_add(json_cap, "dynamic", "received"); - } - - /* Extended nexthop */ - if (CHECK_FLAG (p->cap, PEER_CAP_ENHE_RCV) - || CHECK_FLAG (p->cap, PEER_CAP_ENHE_ADV)) - { - json_object *json_nxt = NULL; - const char *print_store; - - - if (CHECK_FLAG (p->cap, PEER_CAP_ENHE_ADV) && CHECK_FLAG (p->cap, PEER_CAP_ENHE_RCV)) - json_object_string_add(json_cap, "extendedNexthop", "advertisedAndReceived"); - else if (CHECK_FLAG (p->cap, PEER_CAP_ENHE_ADV)) - json_object_string_add(json_cap, "extendedNexthop", "advertised"); - else if (CHECK_FLAG (p->cap, PEER_CAP_ENHE_RCV)) - json_object_string_add(json_cap, "extendedNexthop", "received"); - - if (CHECK_FLAG (p->cap, PEER_CAP_ENHE_RCV)) - { - json_nxt = json_object_new_object(); - - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - if (CHECK_FLAG (p->af_cap[AFI_IP][safi], PEER_CAP_ENHE_AF_RCV)) - { - print_store = afi_safi_print (AFI_IP, safi); - json_object_string_add(json_nxt, print_store, "recieved"); - } - } - json_object_object_add(json_cap, "extendedNexthopFamililesByPeer", json_nxt); - } - } - - /* Route Refresh */ - if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_ADV) - || CHECK_FLAG (p->cap, PEER_CAP_REFRESH_NEW_RCV) - || CHECK_FLAG (p->cap, PEER_CAP_REFRESH_OLD_RCV)) - { - if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_ADV) && (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_NEW_RCV) || CHECK_FLAG (p->cap, PEER_CAP_REFRESH_OLD_RCV))) - { - if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_OLD_RCV) && CHECK_FLAG (p->cap, PEER_CAP_REFRESH_NEW_RCV)) - json_object_string_add(json_cap, "routeRefresh", "advertisedAndReceivedOldNew"); - else - { - if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_OLD_RCV)) - json_object_string_add(json_cap, "routeRefresh", "advertisedAndReceivedOld"); - else - json_object_string_add(json_cap, "routeRefresh", "advertisedAndReceivedNew"); - } - } - else if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_ADV)) - json_object_string_add(json_cap, "routeRefresh", "advertised"); - else if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_NEW_RCV) || CHECK_FLAG (p->cap, PEER_CAP_REFRESH_OLD_RCV)) - json_object_string_add(json_cap, "routeRefresh", "received"); - } - - /* Multiprotocol Extensions */ - json_object *json_multi = NULL; - json_multi = json_object_new_object(); - - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - { - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - if (p->afc_adv[afi][safi] || p->afc_recv[afi][safi]) - { - json_object *json_exten = NULL; - json_exten = json_object_new_object(); - - if (p->afc_adv[afi][safi] && p->afc_recv[afi][safi]) - json_object_boolean_true_add(json_exten, "advertisedAndReceived"); - else if (p->afc_adv[afi][safi]) - json_object_boolean_true_add(json_exten, "advertised"); - else if (p->afc_recv[afi][safi]) - json_object_boolean_true_add(json_exten, "received"); - - json_object_object_add(json_multi, afi_safi_print (afi, safi), json_exten); - } - } - } - json_object_object_add(json_cap, "multiprotocolExtensions", json_multi); - - /* Gracefull Restart */ - if (CHECK_FLAG (p->cap, PEER_CAP_RESTART_RCV) - || CHECK_FLAG (p->cap, PEER_CAP_RESTART_ADV)) - { - if (CHECK_FLAG (p->cap, PEER_CAP_RESTART_ADV) && CHECK_FLAG (p->cap, PEER_CAP_RESTART_RCV)) - json_object_string_add(json_cap, "gracefulRestart", "advertisedAndReceived"); - else if (CHECK_FLAG (p->cap, PEER_CAP_RESTART_ADV)) - json_object_string_add(json_cap, "gracefulRestartCapability", "advertised"); - else if (CHECK_FLAG (p->cap, PEER_CAP_RESTART_RCV)) - json_object_string_add(json_cap, "gracefulRestartCapability", "received"); - - if (CHECK_FLAG (p->cap, PEER_CAP_RESTART_RCV)) - { - int restart_af_count = 0; - json_object *json_restart = NULL; - json_restart = json_object_new_object(); - - json_object_int_add(json_cap, "gracefulRestartRemoteTimerMsecs", p->v_gr_restart * 1000); - - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - { - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV)) - { - json_object *json_sub = NULL; - json_sub = json_object_new_object(); - - if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV)) - json_object_boolean_true_add(json_sub, "preserved"); - restart_af_count++; - json_object_object_add(json_restart, afi_safi_print (afi, safi), json_sub); - } - } - } - if (! restart_af_count) - { - json_object_string_add(json_cap, "addressFamiliesByPeer", "none"); - json_object_free(json_restart); - } - else - json_object_object_add(json_cap, "addressFamiliesByPeer", json_restart); - } - } - json_object_object_add(json_neigh, "neighborCapabilities", json_cap); - } - else - { - vty_out (vty, " Neighbor capabilities:\n"); - - /* AS4 */ - if (CHECK_FLAG (p->cap, PEER_CAP_AS4_RCV) - || CHECK_FLAG (p->cap, PEER_CAP_AS4_ADV)) - { - vty_out (vty, " 4 Byte AS:"); - if (CHECK_FLAG (p->cap, PEER_CAP_AS4_ADV)) - vty_out (vty, " advertised"); - if (CHECK_FLAG (p->cap, PEER_CAP_AS4_RCV)) - vty_out (vty, " %sreceived", - CHECK_FLAG (p->cap, PEER_CAP_AS4_ADV) ? "and " : ""); - vty_out (vty, "\n"); - } - - /* AddPath */ - if (CHECK_FLAG (p->cap, PEER_CAP_ADDPATH_RCV) - || CHECK_FLAG (p->cap, PEER_CAP_ADDPATH_ADV)) - { - vty_out (vty, " AddPath:\n"); - - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_ADV) || - CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV)) - { - vty_out (vty, " %s: TX ", afi_safi_print (afi, safi)); - - if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_ADV)) - vty_out (vty, "advertised %s", afi_safi_print (afi, safi)); - - if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV)) - vty_out (vty, "%sreceived", CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_ADV) ? " and " : "" ); - - vty_out (vty, "\n"); - } - - if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) || - CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_RCV)) - { - vty_out (vty, " %s: RX ", afi_safi_print (afi, safi)); - - if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)) - vty_out (vty, "advertised %s", afi_safi_print (afi, safi)); - - if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_RCV)) - vty_out (vty, "%sreceived", CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) ? " and " : "" ); - - vty_out (vty, "\n"); - } - } - } - - /* Dynamic */ - if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_RCV) - || CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_ADV)) - { - vty_out (vty, " Dynamic:"); - if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_ADV)) - vty_out (vty, " advertised"); - if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_RCV)) - vty_out (vty, " %sreceived", - CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_ADV) ? "and " : ""); - vty_out (vty, "\n"); - } - - /* Extended nexthop */ - if (CHECK_FLAG (p->cap, PEER_CAP_ENHE_RCV) - || CHECK_FLAG (p->cap, PEER_CAP_ENHE_ADV)) - { - vty_out (vty, " Extended nexthop:"); - if (CHECK_FLAG (p->cap, PEER_CAP_ENHE_ADV)) - vty_out (vty, " advertised"); - if (CHECK_FLAG (p->cap, PEER_CAP_ENHE_RCV)) - vty_out (vty, " %sreceived", - CHECK_FLAG (p->cap, PEER_CAP_ENHE_ADV) ? "and " : ""); - vty_out (vty, "\n"); - - if (CHECK_FLAG (p->cap, PEER_CAP_ENHE_RCV)) - { - vty_out (vty, " Address families by peer:\n "); - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - if (CHECK_FLAG (p->af_cap[AFI_IP][safi], PEER_CAP_ENHE_AF_RCV)) - vty_out (vty, " %s\n", - afi_safi_print (AFI_IP, safi)); - } - } - - /* Route Refresh */ - if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_ADV) - || CHECK_FLAG (p->cap, PEER_CAP_REFRESH_NEW_RCV) - || CHECK_FLAG (p->cap, PEER_CAP_REFRESH_OLD_RCV)) - { - vty_out (vty, " Route refresh:"); - if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_ADV)) - vty_out (vty, " advertised"); - if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_NEW_RCV) - || CHECK_FLAG (p->cap, PEER_CAP_REFRESH_OLD_RCV)) - vty_out (vty, " %sreceived(%s)", - CHECK_FLAG (p->cap, PEER_CAP_REFRESH_ADV) ? "and " : "", - (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_OLD_RCV) - && CHECK_FLAG (p->cap, PEER_CAP_REFRESH_NEW_RCV)) ? - "old & new" : CHECK_FLAG (p->cap, PEER_CAP_REFRESH_OLD_RCV) ? "old" : "new"); - - vty_out (vty, "\n"); - } - - /* Multiprotocol Extensions */ - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - if (p->afc_adv[afi][safi] || p->afc_recv[afi][safi]) - { - vty_out (vty, " Address Family %s:", afi_safi_print (afi, safi)); - if (p->afc_adv[afi][safi]) - vty_out (vty, " advertised"); - if (p->afc_recv[afi][safi]) - vty_out (vty, " %sreceived", p->afc_adv[afi][safi] ? "and " : ""); - vty_out (vty, "\n"); - } - - /* Hostname capability */ - if (CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_ADV) || - CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_RCV)) - { - vty_out (vty, " Hostname Capability:"); - if (CHECK_FLAG (p->cap, PEER_CAP_HOSTNAME_ADV)) - vty_out (vty, " advertised"); - if (CHECK_FLAG (p->cap, PEER_CAP_HOSTNAME_RCV)) - vty_out (vty, " %sreceived", - CHECK_FLAG (p->cap, PEER_CAP_HOSTNAME_ADV) ? "and " : ""); - vty_out (vty, "\n"); - } - - /* Gracefull Restart */ - if (CHECK_FLAG (p->cap, PEER_CAP_RESTART_RCV) - || CHECK_FLAG (p->cap, PEER_CAP_RESTART_ADV)) - { - vty_out (vty, " Graceful Restart Capabilty:"); - if (CHECK_FLAG (p->cap, PEER_CAP_RESTART_ADV)) - vty_out (vty, " advertised"); - if (CHECK_FLAG (p->cap, PEER_CAP_RESTART_RCV)) - vty_out (vty, " %sreceived", - CHECK_FLAG (p->cap, PEER_CAP_RESTART_ADV) ? "and " : ""); - vty_out (vty, "\n"); - - if (CHECK_FLAG (p->cap, PEER_CAP_RESTART_RCV)) - { - int restart_af_count = 0; - - vty_out (vty, " Remote Restart timer is %d seconds\n", - p->v_gr_restart); - vty_out (vty, " Address families by peer:\n "); - - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV)) - { - vty_out (vty, "%s%s(%s)", restart_af_count ? ", " : "", - afi_safi_print (afi, safi), - CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV) ? - "preserved" : "not preserved"); - restart_af_count++; - } - if (! restart_af_count) - vty_out (vty, "none"); - vty_out (vty, "\n"); - } - } - } - } - } - - /* graceful restart information */ - if (CHECK_FLAG (p->cap, PEER_CAP_RESTART_RCV) - || p->t_gr_restart - || p->t_gr_stale) - { - json_object *json_grace = NULL; - json_object *json_grace_send = NULL; - json_object *json_grace_recv = NULL; - int eor_send_af_count = 0; - int eor_receive_af_count = 0; - - if (use_json) - { - json_grace = json_object_new_object(); - json_grace_send = json_object_new_object(); - json_grace_recv = json_object_new_object(); - - if (p->status == Established) - { - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - { - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - if (CHECK_FLAG (p->af_sflags[afi][safi], PEER_STATUS_EOR_SEND)) - { - json_object_boolean_true_add(json_grace_send, afi_safi_print (afi, safi)); - eor_send_af_count++; - } - } - } - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - { - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - if (CHECK_FLAG (p->af_sflags[afi][safi], PEER_STATUS_EOR_RECEIVED)) - { - json_object_boolean_true_add(json_grace_recv, afi_safi_print (afi, safi)); - eor_receive_af_count++; - } - } - } - } - - json_object_object_add(json_grace, "endOfRibSend", json_grace_send); - json_object_object_add(json_grace, "endOfRibRecv", json_grace_recv); - - if (p->t_gr_restart) - json_object_int_add(json_grace, "gracefulRestartTimerMsecs", thread_timer_remain_second (p->t_gr_restart) * 1000); - - if (p->t_gr_stale) - json_object_int_add(json_grace, "gracefulStalepathTimerMsecs", thread_timer_remain_second (p->t_gr_stale) * 1000); - - json_object_object_add(json_neigh, "gracefulRestartInfo", json_grace); - } - else - { - vty_out (vty, " Graceful restart informations:\n"); - if (p->status == Established) - { - vty_out (vty, " End-of-RIB send: "); - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - { - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - if (CHECK_FLAG (p->af_sflags[afi][safi], PEER_STATUS_EOR_SEND)) - { - vty_out (vty, "%s%s", eor_send_af_count ? ", " : "", - afi_safi_print (afi, safi)); - eor_send_af_count++; - } - } - } - vty_out (vty, "\n"); - vty_out (vty, " End-of-RIB received: "); - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - { - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - if (CHECK_FLAG (p->af_sflags[afi][safi], PEER_STATUS_EOR_RECEIVED)) - { - vty_out (vty, "%s%s", eor_receive_af_count ? ", " : "", - afi_safi_print (afi, safi)); - eor_receive_af_count++; - } - } - } - vty_out (vty, "\n"); - } - - if (p->t_gr_restart) - vty_out (vty, " The remaining time of restart timer is %ld\n", - thread_timer_remain_second (p->t_gr_restart)); - - if (p->t_gr_stale) - vty_out (vty, " The remaining time of stalepath timer is %ld\n", - thread_timer_remain_second (p->t_gr_stale)); - } - } - if (use_json) - { - json_object *json_stat = NULL; - json_stat = json_object_new_object(); - /* Packet counts. */ - json_object_int_add(json_stat, "depthInq", 0); - json_object_int_add(json_stat, "depthOutq", (unsigned long) p->obuf->count); - json_object_int_add(json_stat, "opensSent", p->open_out); - json_object_int_add(json_stat, "opensRecv", p->open_in); - json_object_int_add(json_stat, "notificationsSent", p->notify_out); - json_object_int_add(json_stat, "notificationsRecv", p->notify_in); - json_object_int_add(json_stat, "updatesSent", p->update_out); - json_object_int_add(json_stat, "updatesRecv", p->update_in); - json_object_int_add(json_stat, "keepalivesSent", p->keepalive_out); - json_object_int_add(json_stat, "keepalivesRecv", p->keepalive_in); - json_object_int_add(json_stat, "routeRefreshSent", p->refresh_out); - json_object_int_add(json_stat, "routeRefreshRecv", p->refresh_in); - json_object_int_add(json_stat, "capabilitySent", p->dynamic_cap_out); - json_object_int_add(json_stat, "capabilityRecv", p->dynamic_cap_in); - json_object_int_add(json_stat, "totalSent", p->open_out + p->notify_out + p->update_out + p->keepalive_out + p->refresh_out + p->dynamic_cap_out); - json_object_int_add(json_stat, "totalRecv", p->open_in + p->notify_in + p->update_in + p->keepalive_in + p->refresh_in + p->dynamic_cap_in); - json_object_object_add(json_neigh, "messageStats", json_stat); - } - else - { - /* Packet counts. */ - vty_out (vty, " Message statistics:\n"); - vty_out (vty, " Inq depth is 0\n"); - vty_out (vty, " Outq depth is %lu\n", (unsigned long) p->obuf->count); - vty_out (vty, " Sent Rcvd\n"); - vty_out (vty, " Opens: %10d %10d\n", p->open_out, p->open_in); - vty_out (vty, " Notifications: %10d %10d\n", p->notify_out, p->notify_in); - vty_out (vty, " Updates: %10d %10d\n", p->update_out, p->update_in); - vty_out (vty, " Keepalives: %10d %10d\n", p->keepalive_out, p->keepalive_in); - vty_out (vty, " Route Refresh: %10d %10d\n", p->refresh_out, p->refresh_in); - vty_out (vty, " Capability: %10d %10d\n", p->dynamic_cap_out, p->dynamic_cap_in); - vty_out (vty, " Total: %10d %10d\n", p->open_out + p->notify_out + - p->update_out + p->keepalive_out + p->refresh_out + p->dynamic_cap_out, - p->open_in + p->notify_in + p->update_in + p->keepalive_in + p->refresh_in + - p->dynamic_cap_in); - } - - if (use_json) - { - /* advertisement-interval */ - json_object_int_add(json_neigh, "minBtwnAdvertisementRunsTimerMsecs", p->v_routeadv * 1000); - - /* Update-source. */ - if (p->update_if || p->update_source) - { - if (p->update_if) - json_object_string_add(json_neigh, "updateSource", p->update_if); - else if (p->update_source) - json_object_string_add(json_neigh, "updateSource", sockunion2str (p->update_source, buf1, SU_ADDRSTRLEN)); - } - } - else - { - /* advertisement-interval */ - vty_out (vty, " Minimum time between advertisement runs is %d seconds\n", - p->v_routeadv); - - /* Update-source. */ - if (p->update_if || p->update_source) - { - vty_out (vty, " Update source is "); - if (p->update_if) - vty_out (vty, "%s", p->update_if); - else if (p->update_source) - vty_out (vty, "%s", sockunion2str (p->update_source, buf1, SU_ADDRSTRLEN)); - vty_out (vty, "\n"); - } - - vty_out (vty, "\n"); - } - - /* Address Family Information */ - json_object *json_hold = NULL; - - if (use_json) - json_hold = json_object_new_object(); - - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - if (p->afc[afi][safi]) - bgp_show_peer_afi (vty, p, afi, safi, use_json, json_hold); - - if (use_json) - { - json_object_object_add(json_neigh, "addressFamilyInfo", json_hold); - json_object_int_add(json_neigh, "connectionsEstablished", p->established); - json_object_int_add(json_neigh, "connectionsDropped", p->dropped); - } - else - vty_out (vty, " Connections established %d; dropped %d\n", p->established, p->dropped); - - if (! p->last_reset) - { - if (use_json) - json_object_string_add(json_neigh, "lastReset", "never"); - else - vty_out (vty, " Last reset never\n"); - } - else - { - if (use_json) - { - time_t uptime; - struct tm *tm; - - uptime = bgp_clock(); - uptime -= p->resettime; - tm = gmtime(&uptime); - json_object_int_add(json_neigh, "lastResetTimerMsecs", (tm->tm_sec * 1000) + (tm->tm_min * 60000) + (tm->tm_hour * 3600000)); - json_object_string_add(json_neigh, "lastResetDueTo", peer_down_str[(int) p->last_reset]); - if (p->last_reset == PEER_DOWN_NOTIFY_SEND || - p->last_reset == PEER_DOWN_NOTIFY_RECEIVED) - { - char errorcodesubcode_hexstr[5]; - char errorcodesubcode_str[256]; - - code_str = bgp_notify_code_str(p->notify.code); - subcode_str = bgp_notify_subcode_str(p->notify.code, p->notify.subcode); - - sprintf(errorcodesubcode_hexstr, "%02X%02X", p->notify.code, p->notify.subcode); - json_object_string_add(json_neigh, "lastErrorCodeSubcode", errorcodesubcode_hexstr); - snprintf(errorcodesubcode_str, 255, "%s%s", code_str, subcode_str); - json_object_string_add(json_neigh, "lastNotificationReason", errorcodesubcode_str); - if (p->last_reset == PEER_DOWN_NOTIFY_RECEIVED - && p->notify.code == BGP_NOTIFY_CEASE - && (p->notify.subcode == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN - || p->notify.subcode == BGP_NOTIFY_CEASE_ADMIN_RESET) - && p->notify.length) - { - char msgbuf[1024]; - const char *msg_str; - - msg_str = bgp_notify_admin_message(msgbuf, sizeof(msgbuf), - (u_char*)p->notify.data, p->notify.length); - if (msg_str) - json_object_string_add(json_neigh, "lastShutdownDescription", msg_str); - } - } - } - else - { - vty_out (vty, " Last reset %s, ", - peer_uptime (p->resettime, timebuf, BGP_UPTIME_LEN, 0, NULL)); - - if (p->last_reset == PEER_DOWN_NOTIFY_SEND || - p->last_reset == PEER_DOWN_NOTIFY_RECEIVED) - { - code_str = bgp_notify_code_str(p->notify.code); - subcode_str = bgp_notify_subcode_str(p->notify.code, p->notify.subcode); - vty_out (vty, "due to NOTIFICATION %s (%s%s)\n", - p->last_reset == PEER_DOWN_NOTIFY_SEND ? "sent" : "received", - code_str, subcode_str); - if (p->last_reset == PEER_DOWN_NOTIFY_RECEIVED - && p->notify.code == BGP_NOTIFY_CEASE - && (p->notify.subcode == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN - || p->notify.subcode == BGP_NOTIFY_CEASE_ADMIN_RESET) - && p->notify.length) - { - char msgbuf[1024]; - const char *msg_str; - - msg_str = bgp_notify_admin_message(msgbuf, sizeof(msgbuf), - (u_char*)p->notify.data, p->notify.length); - if (msg_str) - vty_out (vty, " Message: \"%s\"\n", msg_str); - } - } - else - { - vty_out (vty, "due to %s\n", - peer_down_str[(int) p->last_reset]); - } - - if (p->last_reset_cause_size) - { - msg = p->last_reset_cause; - vty_out(vty, " Message received that caused BGP to send a NOTIFICATION:\n "); - for (i = 1; i <= p->last_reset_cause_size; i++) - { - vty_out(vty, "%02X", *msg++); - - if (i != p->last_reset_cause_size) - { - if (i % 16 == 0) - { - vty_out(vty, "\n "); - } - else if (i % 4 == 0) - { - vty_out(vty, " "); - } - } - } - vty_out(vty, "\n"); - } - } - } - - if (CHECK_FLAG (p->sflags, PEER_STATUS_PREFIX_OVERFLOW)) - { - if (use_json) - json_object_boolean_true_add(json_neigh, "prefixesConfigExceedMax"); - else - vty_out (vty, " Peer had exceeded the max. no. of prefixes configured.\n"); - - if (p->t_pmax_restart) - { - if (use_json) - { - json_object_boolean_true_add(json_neigh, "reducePrefixNumFrom"); - json_object_int_add(json_neigh, "restartInTimerMsec", thread_timer_remain_second (p->t_pmax_restart) * 1000); - } - else - vty_out (vty, " Reduce the no. of prefix from %s, will restart in %ld seconds\n", - p->host, thread_timer_remain_second (p->t_pmax_restart)); - } - else - { - if (use_json) - json_object_boolean_true_add(json_neigh, "reducePrefixNumAndClearIpBgp"); - else - vty_out (vty, " Reduce the no. of prefix and clear ip bgp %s to restore peering\n", - p->host); - } - } - - /* EBGP Multihop and GTSM */ - if (p->sort != BGP_PEER_IBGP) - { - if (use_json) - { - if (p->gtsm_hops > 0) - json_object_int_add(json_neigh, "externalBgpNbrMaxHopsAway", p->gtsm_hops); - else if (p->ttl > 1) - json_object_int_add(json_neigh, "externalBgpNbrMaxHopsAway", p->ttl); - } - else - { - if (p->gtsm_hops > 0) - vty_out (vty, " External BGP neighbor may be up to %d hops away.\n", - p->gtsm_hops); - else if (p->ttl > 1) - vty_out (vty, " External BGP neighbor may be up to %d hops away.\n", - p->ttl); - } - } - else - { - if (p->gtsm_hops > 0) - { - if (use_json) - json_object_int_add(json_neigh, "internalBgpNbrMaxHopsAway", p->gtsm_hops); - else - vty_out (vty, " Internal BGP neighbor may be up to %d hops away.\n", - p->gtsm_hops); - } - } - - /* Local address. */ - if (p->su_local) - { - if (use_json) - { - json_object_string_add(json_neigh, "hostLocal", sockunion2str (p->su_local, buf1, SU_ADDRSTRLEN)); - json_object_int_add(json_neigh, "portLocal", ntohs (p->su_local->sin.sin_port)); - } - else - vty_out (vty, "Local host: %s, Local port: %d\n", - sockunion2str (p->su_local, buf1, SU_ADDRSTRLEN), - ntohs (p->su_local->sin.sin_port)); - } - - /* Remote address. */ - if (p->su_remote) - { - if (use_json) - { - json_object_string_add(json_neigh, "hostForeign", sockunion2str (p->su_remote, buf1, SU_ADDRSTRLEN)); - json_object_int_add(json_neigh, "portForeign", ntohs (p->su_remote->sin.sin_port)); - } - else - vty_out (vty, "Foreign host: %s, Foreign port: %d\n", - sockunion2str (p->su_remote, buf1, SU_ADDRSTRLEN), - ntohs (p->su_remote->sin.sin_port)); - } - - /* Nexthop display. */ - if (p->su_local) - { - if (use_json) - { - json_object_string_add(json_neigh, "nexthop", - inet_ntop (AF_INET, &p->nexthop.v4, buf1, sizeof(buf1))); - json_object_string_add(json_neigh, "nexthopGlobal", - inet_ntop (AF_INET6, &p->nexthop.v6_global, buf1, sizeof(buf1))); - json_object_string_add(json_neigh, "nexthopLocal", - inet_ntop (AF_INET6, &p->nexthop.v6_local, buf1, sizeof(buf1))); - if (p->shared_network) - json_object_string_add(json_neigh, "bgpConnection", "sharedNetwork"); - else - json_object_string_add(json_neigh, "bgpConnection", "nonSharedNetwork"); - } - else - { - vty_out (vty, "Nexthop: %s\n", - inet_ntop (AF_INET, &p->nexthop.v4, buf1, sizeof(buf1))); - vty_out (vty, "Nexthop global: %s\n", - inet_ntop (AF_INET6, &p->nexthop.v6_global, buf1, sizeof(buf1))); - vty_out (vty, "Nexthop local: %s\n", - inet_ntop (AF_INET6, &p->nexthop.v6_local, buf1, sizeof(buf1))); - vty_out (vty, "BGP connection: %s\n", - p->shared_network ? "shared network" : "non shared network"); - } - } - - /* Timer information. */ - if (use_json) - { - json_object_int_add(json_neigh, "connectRetryTimer", p->v_connect); - if (p->status == Established && p->rtt) - json_object_int_add(json_neigh, "estimatedRttInMsecs", p->rtt); - if (p->t_start) - json_object_int_add(json_neigh, "nextStartTimerDueInMsecs", thread_timer_remain_second (p->t_start) * 1000); - if (p->t_connect) - json_object_int_add(json_neigh, "nextConnectTimerDueInMsecs", thread_timer_remain_second (p->t_connect) * 1000); - if (p->t_routeadv) - { - json_object_int_add(json_neigh, "mraiInterval", p->v_routeadv); - json_object_int_add(json_neigh, "mraiTimerExpireInMsecs", thread_timer_remain_second (p->t_routeadv) * 1000); - } - if (p->password) - json_object_int_add(json_neigh, "authenticationEnabled", 1); - - if (p->t_read) - json_object_string_add(json_neigh, "readThread", "on"); - else - json_object_string_add(json_neigh, "readThread", "off"); - if (p->t_write) - json_object_string_add(json_neigh, "writeThread", "on"); - else - json_object_string_add(json_neigh, "writeThread", "off"); - } - else - { - vty_out (vty, "BGP Connect Retry Timer in Seconds: %d\n", - p->v_connect); - if (p->status == Established && p->rtt) - vty_out (vty, "Estimated round trip time: %d ms\n", - p->rtt); - if (p->t_start) - vty_out (vty, "Next start timer due in %ld seconds\n", - thread_timer_remain_second (p->t_start)); - if (p->t_connect) - vty_out (vty, "Next connect timer due in %ld seconds\n", - thread_timer_remain_second (p->t_connect)); - if (p->t_routeadv) - vty_out (vty, "MRAI (interval %u) timer expires in %ld seconds\n", - p->v_routeadv, thread_timer_remain_second (p->t_routeadv)); - if (p->password) - vty_out (vty, "Peer Authentication Enabled\n"); - - vty_out (vty, "Read thread: %s Write thread: %s\n", - p->t_read ? "on" : "off", - p->t_write ? "on" : "off"); - } - - if (p->notify.code == BGP_NOTIFY_OPEN_ERR - && p->notify.subcode == BGP_NOTIFY_OPEN_UNSUP_CAPBL) - bgp_capability_vty_out (vty, p, use_json, json_neigh); - - if (!use_json) - vty_out (vty, "\n"); - - /* BFD information. */ - bgp_bfd_show_info(vty, p, use_json, json_neigh); - - if (use_json) - { - if (p->conf_if) /* Configured interface name. */ - json_object_object_add(json, p->conf_if, json_neigh); - else /* Configured IP address. */ - json_object_object_add(json, p->host, json_neigh); - } -} - -static int -bgp_show_neighbor (struct vty *vty, struct bgp *bgp, enum show_type type, - union sockunion *su, const char *conf_if, u_char use_json, json_object *json) -{ - struct listnode *node, *nnode; - struct peer *peer; - int find = 0; - - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) - continue; - - switch (type) - { - case show_all: - bgp_show_peer (vty, peer, use_json, json); - break; - case show_peer: - if (conf_if) - { - if ((peer->conf_if && !strcmp(peer->conf_if, conf_if)) || - (peer->hostname && !strcmp(peer->hostname, conf_if))) - { - find = 1; - bgp_show_peer (vty, peer, use_json, json); - } - } - else - { - if (sockunion_same (&peer->su, su)) - { - find = 1; - bgp_show_peer (vty, peer, use_json, json); - } - } - break; - } - } - - if (type == show_peer && ! find) - { - if (use_json) - json_object_boolean_true_add(json, "bgpNoSuchNeighbor"); - else - vty_out (vty, "%% No such neighbor\n"); - } - - if (use_json) - { - vty_out (vty, "%s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - { - vty_out (vty, "\n"); - } - - return CMD_SUCCESS; -} - -static void -bgp_show_all_instances_neighbors_vty (struct vty *vty, u_char use_json) -{ - struct listnode *node, *nnode; - struct bgp *bgp; - json_object *json = NULL; - int is_first = 1; - - if (use_json) - vty_out (vty, "{\n"); - - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - { - if (use_json) - { - if (!(json = json_object_new_object())) - { - zlog_err("Unable to allocate memory for JSON object"); - vty_out (vty, - "{\"error\": {\"message:\": \"Unable to allocate memory for JSON object\"}}}\n"); - return; - } - - json_object_int_add(json, "vrfId", - (bgp->vrf_id == VRF_UNKNOWN) - ? -1 : bgp->vrf_id); - json_object_string_add(json, "vrfName", - (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - ? "Default" : bgp->name); - - if (! is_first) - vty_out (vty, ",\n"); - else - is_first = 0; - - vty_out(vty, "\"%s\":", (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - ? "Default" : bgp->name); - } - else - { - vty_out (vty, "\nInstance %s:\n", - (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - ? "Default" : bgp->name); - } - bgp_show_neighbor (vty, bgp, show_all, NULL, NULL, use_json, json); - } - - if (use_json) - vty_out (vty, "}\n"); -} - -static int -bgp_show_neighbor_vty (struct vty *vty, const char *name, - enum show_type type, const char *ip_str, u_char use_json) -{ - int ret; - struct bgp *bgp; - union sockunion su; - json_object *json = NULL; - - if (name) - { - if (strmatch(name, "all")) - { - bgp_show_all_instances_neighbors_vty (vty, use_json); - return CMD_SUCCESS; - } - else - { - bgp = bgp_lookup_by_name (name); - if (! bgp) - { - if (use_json) - { - json = json_object_new_object(); - json_object_boolean_true_add(json, "bgpNoSuchInstance"); - vty_out (vty, "%s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - vty_out (vty, "%% No such BGP instance exist\n"); - - return CMD_WARNING; - } - } - } - else - { - bgp = bgp_get_default (); - } - - if (bgp) - { - json = json_object_new_object(); - if (ip_str) - { - ret = str2sockunion (ip_str, &su); - if (ret < 0) - bgp_show_neighbor (vty, bgp, type, NULL, ip_str, use_json, json); - else - bgp_show_neighbor (vty, bgp, type, &su, NULL, use_json, json); - } - else - { - bgp_show_neighbor (vty, bgp, type, NULL, NULL, use_json, json); - } - json_object_free (json); - } - - return CMD_SUCCESS; + bgp = p->bgp; + + if (use_json) + json_neigh = json_object_new_object(); + + memset(dn_flag, '\0', sizeof(dn_flag)); + if (!p->conf_if && peer_dynamic_neighbor(p)) + dn_flag[0] = '*'; + + if (!use_json) { + if (p->conf_if) /* Configured interface name. */ + vty_out(vty, "BGP neighbor on %s: %s, ", p->conf_if, + BGP_PEER_SU_UNSPEC(p) + ? "None" + : sockunion2str(&p->su, buf, + SU_ADDRSTRLEN)); + else /* Configured IP address. */ + vty_out(vty, "BGP neighbor is %s%s, ", dn_flag, + p->host); + } + + if (use_json) { + if (p->conf_if && BGP_PEER_SU_UNSPEC(p)) + json_object_string_add(json_neigh, "bgpNeighborAddr", + "none"); + else if (p->conf_if && !BGP_PEER_SU_UNSPEC(p)) + json_object_string_add( + json_neigh, "bgpNeighborAddr", + sockunion2str(&p->su, buf, SU_ADDRSTRLEN)); + + json_object_int_add(json_neigh, "remoteAs", p->as); + + if (p->change_local_as) + json_object_int_add(json_neigh, "localAs", + p->change_local_as); + else + json_object_int_add(json_neigh, "localAs", p->local_as); + + if (CHECK_FLAG(p->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)) + json_object_boolean_true_add(json_neigh, + "localAsNoPrepend"); + + if (CHECK_FLAG(p->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS)) + json_object_boolean_true_add(json_neigh, + "localAsReplaceAs"); + } else { + if ((p->as_type == AS_SPECIFIED) || (p->as_type == AS_EXTERNAL) + || (p->as_type == AS_INTERNAL)) + vty_out(vty, "remote AS %u, ", p->as); + else + vty_out(vty, "remote AS Unspecified, "); + vty_out(vty, "local AS %u%s%s, ", + p->change_local_as ? p->change_local_as : p->local_as, + CHECK_FLAG(p->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) + ? " no-prepend" + : "", + CHECK_FLAG(p->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) + ? " replace-as" + : ""); + } + /* peer type internal, external, confed-internal or confed-external */ + if (p->as == p->local_as) { + if (use_json) { + if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) + json_object_boolean_true_add( + json_neigh, "nbrConfedInternalLink"); + else + json_object_boolean_true_add(json_neigh, + "nbrInternalLink"); + } else { + if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) + vty_out(vty, "confed-internal link\n"); + else + vty_out(vty, "internal link\n"); + } + } else { + if (use_json) { + if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) + json_object_boolean_true_add( + json_neigh, "nbrConfedExternalLink"); + else + json_object_boolean_true_add(json_neigh, + "nbrExternalLink"); + } else { + if (bgp_confederation_peers_check(bgp, p->as)) + vty_out(vty, "confed-external link\n"); + else + vty_out(vty, "external link\n"); + } + } + + /* Description. */ + if (p->desc) { + if (use_json) + json_object_string_add(json_neigh, "nbrDesc", p->desc); + else + vty_out(vty, " Description: %s\n", p->desc); + } + + if (p->hostname) { + if (use_json) { + if (p->hostname) + json_object_string_add(json_neigh, "hostname", + p->hostname); + + if (p->domainname) + json_object_string_add(json_neigh, "domainname", + p->domainname); + } else { + if (p->domainname && (p->domainname[0] != '\0')) + vty_out(vty, "Hostname: %s.%s\n", p->hostname, + p->domainname); + else + vty_out(vty, "Hostname: %s\n", p->hostname); + } + } + + /* Peer-group */ + if (p->group) { + if (use_json) { + json_object_string_add(json_neigh, "peerGroup", + p->group->name); + + if (dn_flag[0]) { + struct prefix prefix, *range = NULL; + + sockunion2hostprefix(&(p->su), &prefix); + range = peer_group_lookup_dynamic_neighbor_range( + p->group, &prefix); + + if (range) { + prefix2str(range, buf1, sizeof(buf1)); + json_object_string_add( + json_neigh, + "peerSubnetRangeGroup", buf1); + } + } + } else { + vty_out(vty, + " Member of peer-group %s for session parameters\n", + p->group->name); + + if (dn_flag[0]) { + struct prefix prefix, *range = NULL; + + sockunion2hostprefix(&(p->su), &prefix); + range = peer_group_lookup_dynamic_neighbor_range( + p->group, &prefix); + + if (range) { + prefix2str(range, buf1, sizeof(buf1)); + vty_out(vty, + " Belongs to the subnet range group: %s\n", + buf1); + } + } + } + } + + if (use_json) { + /* Administrative shutdown. */ + if (CHECK_FLAG(p->flags, PEER_FLAG_SHUTDOWN)) + json_object_boolean_true_add(json_neigh, + "adminShutDown"); + + /* BGP Version. */ + json_object_int_add(json_neigh, "bgpVersion", 4); + json_object_string_add( + json_neigh, "remoteRouterId", + inet_ntop(AF_INET, &p->remote_id, buf1, sizeof(buf1))); + + /* Confederation */ + if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) + && bgp_confederation_peers_check(bgp, p->as)) + json_object_boolean_true_add(json_neigh, + "nbrCommonAdmin"); + + /* Status. */ + json_object_string_add( + json_neigh, "bgpState", + lookup_msg(bgp_status_msg, p->status, NULL)); + + if (p->status == Established) { + time_t uptime; + struct tm *tm; + + uptime = bgp_clock(); + uptime -= p->uptime; + tm = gmtime(&uptime); + epoch_tbuf = time(NULL) - uptime; + + json_object_int_add(json_neigh, "bgpTimerUp", + (tm->tm_sec * 1000) + + (tm->tm_min * 60000) + + (tm->tm_hour * 3600000)); + json_object_string_add(json_neigh, "bgpTimerUpString", + peer_uptime(p->uptime, timebuf, + BGP_UPTIME_LEN, 0, + NULL)); + json_object_int_add(json_neigh, + "bgpTimerUpEstablishedEpoch", + epoch_tbuf); + } + + else if (p->status == Active) { + if (CHECK_FLAG(p->flags, PEER_FLAG_PASSIVE)) + json_object_string_add(json_neigh, "bgpStateIs", + "passive"); + else if (CHECK_FLAG(p->sflags, PEER_STATUS_NSF_WAIT)) + json_object_string_add(json_neigh, "bgpStateIs", + "passiveNSF"); + } + + /* read timer */ + time_t uptime; + struct tm *tm; + + uptime = bgp_clock(); + uptime -= p->readtime; + tm = gmtime(&uptime); + json_object_int_add(json_neigh, "bgpTimerLastRead", + (tm->tm_sec * 1000) + (tm->tm_min * 60000) + + (tm->tm_hour * 3600000)); + + uptime = bgp_clock(); + uptime -= p->last_write; + tm = gmtime(&uptime); + json_object_int_add(json_neigh, "bgpTimerLastWrite", + (tm->tm_sec * 1000) + (tm->tm_min * 60000) + + (tm->tm_hour * 3600000)); + + uptime = bgp_clock(); + uptime -= p->update_time; + tm = gmtime(&uptime); + json_object_int_add(json_neigh, "bgpInUpdateElapsedTimeMsecs", + (tm->tm_sec * 1000) + (tm->tm_min * 60000) + + (tm->tm_hour * 3600000)); + + /* Configured timer values. */ + json_object_int_add(json_neigh, "bgpTimerHoldTimeMsecs", + p->v_holdtime * 1000); + json_object_int_add(json_neigh, + "bgpTimerKeepAliveIntervalMsecs", + p->v_keepalive * 1000); + + if (CHECK_FLAG(p->config, PEER_CONFIG_TIMER)) { + json_object_int_add(json_neigh, + "bgpTimerConfiguredHoldTimeMsecs", + p->holdtime * 1000); + json_object_int_add( + json_neigh, + "bgpTimerConfiguredKeepAliveIntervalMsecs", + p->keepalive * 1000); + } + } else { + /* Administrative shutdown. */ + if (CHECK_FLAG(p->flags, PEER_FLAG_SHUTDOWN)) + vty_out(vty, " Administratively shut down\n"); + + /* BGP Version. */ + vty_out(vty, " BGP version 4"); + vty_out(vty, ", remote router ID %s\n", + inet_ntop(AF_INET, &p->remote_id, buf1, sizeof(buf1))); + + /* Confederation */ + if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION) + && bgp_confederation_peers_check(bgp, p->as)) + vty_out(vty, + " Neighbor under common administration\n"); + + /* Status. */ + vty_out(vty, " BGP state = %s", + lookup_msg(bgp_status_msg, p->status, NULL)); + + if (p->status == Established) + vty_out(vty, ", up for %8s", + peer_uptime(p->uptime, timebuf, BGP_UPTIME_LEN, + 0, NULL)); + + else if (p->status == Active) { + if (CHECK_FLAG(p->flags, PEER_FLAG_PASSIVE)) + vty_out(vty, " (passive)"); + else if (CHECK_FLAG(p->sflags, PEER_STATUS_NSF_WAIT)) + vty_out(vty, " (NSF passive)"); + } + vty_out(vty, "\n"); + + /* read timer */ + vty_out(vty, " Last read %s", + peer_uptime(p->readtime, timebuf, BGP_UPTIME_LEN, 0, + NULL)); + vty_out(vty, ", Last write %s\n", + peer_uptime(p->last_write, timebuf, BGP_UPTIME_LEN, 0, + NULL)); + + /* Configured timer values. */ + vty_out(vty, + " Hold time is %d, keepalive interval is %d seconds\n", + p->v_holdtime, p->v_keepalive); + if (CHECK_FLAG(p->config, PEER_CONFIG_TIMER)) { + vty_out(vty, " Configured hold time is %d", + p->holdtime); + vty_out(vty, ", keepalive interval is %d seconds\n", + p->keepalive); + } + } + /* Capability. */ + if (p->status == Established) { + if (p->cap || p->afc_adv[AFI_IP][SAFI_UNICAST] + || p->afc_recv[AFI_IP][SAFI_UNICAST] + || p->afc_adv[AFI_IP][SAFI_MULTICAST] + || p->afc_recv[AFI_IP][SAFI_MULTICAST] + || p->afc_adv[AFI_IP6][SAFI_UNICAST] + || p->afc_recv[AFI_IP6][SAFI_UNICAST] + || p->afc_adv[AFI_IP6][SAFI_MULTICAST] + || p->afc_recv[AFI_IP6][SAFI_MULTICAST] + || p->afc_adv[AFI_IP6][SAFI_MPLS_VPN] + || p->afc_recv[AFI_IP6][SAFI_MPLS_VPN] + || p->afc_adv[AFI_IP6][SAFI_ENCAP] + || p->afc_recv[AFI_IP6][SAFI_ENCAP] + || p->afc_adv[AFI_IP][SAFI_ENCAP] + || p->afc_recv[AFI_IP][SAFI_ENCAP] + || p->afc_adv[AFI_IP][SAFI_MPLS_VPN] + || p->afc_recv[AFI_IP][SAFI_MPLS_VPN]) { + if (use_json) { + json_object *json_cap = NULL; + + json_cap = json_object_new_object(); + + /* AS4 */ + if (CHECK_FLAG(p->cap, PEER_CAP_AS4_RCV) + || CHECK_FLAG(p->cap, PEER_CAP_AS4_ADV)) { + if (CHECK_FLAG(p->cap, PEER_CAP_AS4_ADV) + && CHECK_FLAG(p->cap, + PEER_CAP_AS4_RCV)) + json_object_string_add( + json_cap, "4byteAs", + "advertisedAndReceived"); + else if (CHECK_FLAG(p->cap, + PEER_CAP_AS4_ADV)) + json_object_string_add( + json_cap, "4byteAs", + "advertised"); + else if (CHECK_FLAG(p->cap, + PEER_CAP_AS4_RCV)) + json_object_string_add( + json_cap, "4byteAs", + "received"); + } + + /* AddPath */ + if (CHECK_FLAG(p->cap, PEER_CAP_ADDPATH_RCV) + || CHECK_FLAG(p->cap, + PEER_CAP_ADDPATH_ADV)) { + json_object *json_add = NULL; + const char *print_store; + + json_add = json_object_new_object(); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; + safi < SAFI_MAX; safi++) { + json_object *json_sub = + NULL; + json_sub = + json_object_new_object(); + print_store = + afi_safi_print( + afi, + safi); + + if (CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_TX_ADV) + || CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_TX_RCV)) { + if (CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_TX_ADV) + && CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_TX_RCV)) + json_object_boolean_true_add( + json_sub, + "txAdvertisedAndReceived"); + else if ( + CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_TX_ADV)) + json_object_boolean_true_add( + json_sub, + "txAdvertised"); + else if ( + CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_TX_RCV)) + json_object_boolean_true_add( + json_sub, + "txReceived"); + } + + if (CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_RX_ADV) + || CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_RX_RCV)) { + if (CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_RX_ADV) + && CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_RX_RCV)) + json_object_boolean_true_add( + json_sub, + "rxAdvertisedAndReceived"); + else if ( + CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_RX_ADV)) + json_object_boolean_true_add( + json_sub, + "rxAdvertised"); + else if ( + CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_RX_RCV)) + json_object_boolean_true_add( + json_sub, + "rxReceived"); + } + + if (CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_TX_ADV) + || CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_TX_RCV) + || CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_RX_ADV) + || CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_RX_RCV)) + json_object_object_add( + json_add, + print_store, + json_sub); + else + json_object_free( + json_sub); + } + + json_object_object_add( + json_cap, "addPath", json_add); + } + + /* Dynamic */ + if (CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_RCV) + || CHECK_FLAG(p->cap, + PEER_CAP_DYNAMIC_ADV)) { + if (CHECK_FLAG(p->cap, + PEER_CAP_DYNAMIC_ADV) + && CHECK_FLAG(p->cap, + PEER_CAP_DYNAMIC_RCV)) + json_object_string_add( + json_cap, "dynamic", + "advertisedAndReceived"); + else if (CHECK_FLAG( + p->cap, + PEER_CAP_DYNAMIC_ADV)) + json_object_string_add( + json_cap, "dynamic", + "advertised"); + else if (CHECK_FLAG( + p->cap, + PEER_CAP_DYNAMIC_RCV)) + json_object_string_add( + json_cap, "dynamic", + "received"); + } + + /* Extended nexthop */ + if (CHECK_FLAG(p->cap, PEER_CAP_ENHE_RCV) + || CHECK_FLAG(p->cap, PEER_CAP_ENHE_ADV)) { + json_object *json_nxt = NULL; + const char *print_store; + + + if (CHECK_FLAG(p->cap, + PEER_CAP_ENHE_ADV) + && CHECK_FLAG(p->cap, + PEER_CAP_ENHE_RCV)) + json_object_string_add( + json_cap, + "extendedNexthop", + "advertisedAndReceived"); + else if (CHECK_FLAG(p->cap, + PEER_CAP_ENHE_ADV)) + json_object_string_add( + json_cap, + "extendedNexthop", + "advertised"); + else if (CHECK_FLAG(p->cap, + PEER_CAP_ENHE_RCV)) + json_object_string_add( + json_cap, + "extendedNexthop", + "received"); + + if (CHECK_FLAG(p->cap, + PEER_CAP_ENHE_RCV)) { + json_nxt = + json_object_new_object(); + + for (safi = SAFI_UNICAST; + safi < SAFI_MAX; safi++) { + if (CHECK_FLAG( + p->af_cap + [AFI_IP] + [safi], + PEER_CAP_ENHE_AF_RCV)) { + print_store = afi_safi_print( + AFI_IP, + safi); + json_object_string_add( + json_nxt, + print_store, + "recieved"); + } + } + json_object_object_add( + json_cap, + "extendedNexthopFamililesByPeer", + json_nxt); + } + } + + /* Route Refresh */ + if (CHECK_FLAG(p->cap, PEER_CAP_REFRESH_ADV) + || CHECK_FLAG(p->cap, + PEER_CAP_REFRESH_NEW_RCV) + || CHECK_FLAG(p->cap, + PEER_CAP_REFRESH_OLD_RCV)) { + if (CHECK_FLAG(p->cap, + PEER_CAP_REFRESH_ADV) + && (CHECK_FLAG( + p->cap, + PEER_CAP_REFRESH_NEW_RCV) + || CHECK_FLAG( + p->cap, + PEER_CAP_REFRESH_OLD_RCV))) { + if (CHECK_FLAG( + p->cap, + PEER_CAP_REFRESH_OLD_RCV) + && CHECK_FLAG( + p->cap, + PEER_CAP_REFRESH_NEW_RCV)) + json_object_string_add( + json_cap, + "routeRefresh", + "advertisedAndReceivedOldNew"); + else { + if (CHECK_FLAG( + p->cap, + PEER_CAP_REFRESH_OLD_RCV)) + json_object_string_add( + json_cap, + "routeRefresh", + "advertisedAndReceivedOld"); + else + json_object_string_add( + json_cap, + "routeRefresh", + "advertisedAndReceivedNew"); + } + } else if ( + CHECK_FLAG( + p->cap, + PEER_CAP_REFRESH_ADV)) + json_object_string_add( + json_cap, + "routeRefresh", + "advertised"); + else if ( + CHECK_FLAG( + p->cap, + PEER_CAP_REFRESH_NEW_RCV) + || CHECK_FLAG( + p->cap, + PEER_CAP_REFRESH_OLD_RCV)) + json_object_string_add( + json_cap, + "routeRefresh", + "received"); + } + + /* Multiprotocol Extensions */ + json_object *json_multi = NULL; + json_multi = json_object_new_object(); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + for (safi = SAFI_UNICAST; + safi < SAFI_MAX; safi++) { + if (p->afc_adv[afi][safi] + || p->afc_recv[afi][safi]) { + json_object + *json_exten = + NULL; + json_exten = + json_object_new_object(); + + if (p->afc_adv[afi] + [safi] + && p->afc_recv + [afi] + [safi]) + json_object_boolean_true_add( + json_exten, + "advertisedAndReceived"); + else if (p->afc_adv + [afi] + [safi]) + json_object_boolean_true_add( + json_exten, + "advertised"); + else if (p->afc_recv + [afi] + [safi]) + json_object_boolean_true_add( + json_exten, + "received"); + + json_object_object_add( + json_multi, + afi_safi_print( + afi, + safi), + json_exten); + } + } + } + json_object_object_add( + json_cap, "multiprotocolExtensions", + json_multi); + + /* Gracefull Restart */ + if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV) + || CHECK_FLAG(p->cap, + PEER_CAP_RESTART_ADV)) { + if (CHECK_FLAG(p->cap, + PEER_CAP_RESTART_ADV) + && CHECK_FLAG(p->cap, + PEER_CAP_RESTART_RCV)) + json_object_string_add( + json_cap, + "gracefulRestart", + "advertisedAndReceived"); + else if (CHECK_FLAG( + p->cap, + PEER_CAP_RESTART_ADV)) + json_object_string_add( + json_cap, + "gracefulRestartCapability", + "advertised"); + else if (CHECK_FLAG( + p->cap, + PEER_CAP_RESTART_RCV)) + json_object_string_add( + json_cap, + "gracefulRestartCapability", + "received"); + + if (CHECK_FLAG(p->cap, + PEER_CAP_RESTART_RCV)) { + int restart_af_count = 0; + json_object *json_restart = + NULL; + json_restart = + json_object_new_object(); + + json_object_int_add( + json_cap, + "gracefulRestartRemoteTimerMsecs", + p->v_gr_restart * 1000); + + for (afi = AFI_IP; + afi < AFI_MAX; afi++) { + for (safi = SAFI_UNICAST; + safi < SAFI_MAX; + safi++) { + if (CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_RESTART_AF_RCV)) { + json_object *json_sub = + NULL; + json_sub = + json_object_new_object(); + + if (CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_RESTART_AF_PRESERVE_RCV)) + json_object_boolean_true_add( + json_sub, + "preserved"); + restart_af_count++; + json_object_object_add( + json_restart, + afi_safi_print( + afi, + safi), + json_sub); + } + } + } + if (!restart_af_count) { + json_object_string_add( + json_cap, + "addressFamiliesByPeer", + "none"); + json_object_free( + json_restart); + } else + json_object_object_add( + json_cap, + "addressFamiliesByPeer", + json_restart); + } + } + json_object_object_add(json_neigh, + "neighborCapabilities", + json_cap); + } else { + vty_out(vty, " Neighbor capabilities:\n"); + + /* AS4 */ + if (CHECK_FLAG(p->cap, PEER_CAP_AS4_RCV) + || CHECK_FLAG(p->cap, PEER_CAP_AS4_ADV)) { + vty_out(vty, " 4 Byte AS:"); + if (CHECK_FLAG(p->cap, + PEER_CAP_AS4_ADV)) + vty_out(vty, " advertised"); + if (CHECK_FLAG(p->cap, + PEER_CAP_AS4_RCV)) + vty_out(vty, " %sreceived", + CHECK_FLAG( + p->cap, + PEER_CAP_AS4_ADV) + ? "and " + : ""); + vty_out(vty, "\n"); + } + + /* AddPath */ + if (CHECK_FLAG(p->cap, PEER_CAP_ADDPATH_RCV) + || CHECK_FLAG(p->cap, + PEER_CAP_ADDPATH_ADV)) { + vty_out(vty, " AddPath:\n"); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; + safi < SAFI_MAX; safi++) { + if (CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_TX_ADV) + || CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_TX_RCV)) { + vty_out(vty, + " %s: TX ", + afi_safi_print( + afi, + safi)); + + if (CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_TX_ADV)) + vty_out(vty, + "advertised %s", + afi_safi_print( + afi, + safi)); + + if (CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_TX_RCV)) + vty_out(vty, + "%sreceived", + CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_TX_ADV) + ? " and " + : ""); + + vty_out(vty, + "\n"); + } + + if (CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_RX_ADV) + || CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_RX_RCV)) { + vty_out(vty, + " %s: RX ", + afi_safi_print( + afi, + safi)); + + if (CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_RX_ADV)) + vty_out(vty, + "advertised %s", + afi_safi_print( + afi, + safi)); + + if (CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_RX_RCV)) + vty_out(vty, + "%sreceived", + CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_ADDPATH_AF_RX_ADV) + ? " and " + : ""); + + vty_out(vty, + "\n"); + } + } + } + + /* Dynamic */ + if (CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_RCV) + || CHECK_FLAG(p->cap, + PEER_CAP_DYNAMIC_ADV)) { + vty_out(vty, " Dynamic:"); + if (CHECK_FLAG(p->cap, + PEER_CAP_DYNAMIC_ADV)) + vty_out(vty, " advertised"); + if (CHECK_FLAG(p->cap, + PEER_CAP_DYNAMIC_RCV)) + vty_out(vty, " %sreceived", + CHECK_FLAG( + p->cap, + PEER_CAP_DYNAMIC_ADV) + ? "and " + : ""); + vty_out(vty, "\n"); + } + + /* Extended nexthop */ + if (CHECK_FLAG(p->cap, PEER_CAP_ENHE_RCV) + || CHECK_FLAG(p->cap, PEER_CAP_ENHE_ADV)) { + vty_out(vty, " Extended nexthop:"); + if (CHECK_FLAG(p->cap, + PEER_CAP_ENHE_ADV)) + vty_out(vty, " advertised"); + if (CHECK_FLAG(p->cap, + PEER_CAP_ENHE_RCV)) + vty_out(vty, " %sreceived", + CHECK_FLAG( + p->cap, + PEER_CAP_ENHE_ADV) + ? "and " + : ""); + vty_out(vty, "\n"); + + if (CHECK_FLAG(p->cap, + PEER_CAP_ENHE_RCV)) { + vty_out(vty, + " Address families by peer:\n "); + for (safi = SAFI_UNICAST; + safi < SAFI_MAX; safi++) + if (CHECK_FLAG( + p->af_cap + [AFI_IP] + [safi], + PEER_CAP_ENHE_AF_RCV)) + vty_out(vty, + " %s\n", + afi_safi_print( + AFI_IP, + safi)); + } + } + + /* Route Refresh */ + if (CHECK_FLAG(p->cap, PEER_CAP_REFRESH_ADV) + || CHECK_FLAG(p->cap, + PEER_CAP_REFRESH_NEW_RCV) + || CHECK_FLAG(p->cap, + PEER_CAP_REFRESH_OLD_RCV)) { + vty_out(vty, " Route refresh:"); + if (CHECK_FLAG(p->cap, + PEER_CAP_REFRESH_ADV)) + vty_out(vty, " advertised"); + if (CHECK_FLAG(p->cap, + PEER_CAP_REFRESH_NEW_RCV) + || CHECK_FLAG( + p->cap, + PEER_CAP_REFRESH_OLD_RCV)) + vty_out(vty, " %sreceived(%s)", + CHECK_FLAG( + p->cap, + PEER_CAP_REFRESH_ADV) + ? "and " + : "", + (CHECK_FLAG( + p->cap, + PEER_CAP_REFRESH_OLD_RCV) + && CHECK_FLAG( + p->cap, + PEER_CAP_REFRESH_NEW_RCV)) + ? "old & new" + : CHECK_FLAG( + p->cap, + PEER_CAP_REFRESH_OLD_RCV) + ? "old" + : "new"); + + vty_out(vty, "\n"); + } + + /* Multiprotocol Extensions */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; + safi < SAFI_MAX; safi++) + if (p->afc_adv[afi][safi] + || p->afc_recv[afi][safi]) { + vty_out(vty, + " Address Family %s:", + afi_safi_print( + afi, + safi)); + if (p->afc_adv[afi] + [safi]) + vty_out(vty, + " advertised"); + if (p->afc_recv[afi] + [safi]) + vty_out(vty, + " %sreceived", + p->afc_adv[afi] + [safi] + ? "and " + : ""); + vty_out(vty, "\n"); + } + + /* Hostname capability */ + if (CHECK_FLAG(p->cap, PEER_CAP_HOSTNAME_ADV) + || CHECK_FLAG(p->cap, + PEER_CAP_HOSTNAME_RCV)) { + vty_out(vty, + " Hostname Capability:"); + if (CHECK_FLAG(p->cap, + PEER_CAP_HOSTNAME_ADV)) + vty_out(vty, " advertised"); + if (CHECK_FLAG(p->cap, + PEER_CAP_HOSTNAME_RCV)) + vty_out(vty, " %sreceived", + CHECK_FLAG( + p->cap, + PEER_CAP_HOSTNAME_ADV) + ? "and " + : ""); + vty_out(vty, "\n"); + } + + /* Gracefull Restart */ + if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV) + || CHECK_FLAG(p->cap, + PEER_CAP_RESTART_ADV)) { + vty_out(vty, + " Graceful Restart Capabilty:"); + if (CHECK_FLAG(p->cap, + PEER_CAP_RESTART_ADV)) + vty_out(vty, " advertised"); + if (CHECK_FLAG(p->cap, + PEER_CAP_RESTART_RCV)) + vty_out(vty, " %sreceived", + CHECK_FLAG( + p->cap, + PEER_CAP_RESTART_ADV) + ? "and " + : ""); + vty_out(vty, "\n"); + + if (CHECK_FLAG(p->cap, + PEER_CAP_RESTART_RCV)) { + int restart_af_count = 0; + + vty_out(vty, + " Remote Restart timer is %d seconds\n", + p->v_gr_restart); + vty_out(vty, + " Address families by peer:\n "); + + for (afi = AFI_IP; + afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; + safi < SAFI_MAX; + safi++) + if (CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_RESTART_AF_RCV)) { + vty_out(vty, + "%s%s(%s)", + restart_af_count + ? ", " + : "", + afi_safi_print( + afi, + safi), + CHECK_FLAG( + p->af_cap + [afi] + [safi], + PEER_CAP_RESTART_AF_PRESERVE_RCV) + ? "preserved" + : "not preserved"); + restart_af_count++; + } + if (!restart_af_count) + vty_out(vty, "none"); + vty_out(vty, "\n"); + } + } + } + } + } + + /* graceful restart information */ + if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV) || p->t_gr_restart + || p->t_gr_stale) { + json_object *json_grace = NULL; + json_object *json_grace_send = NULL; + json_object *json_grace_recv = NULL; + int eor_send_af_count = 0; + int eor_receive_af_count = 0; + + if (use_json) { + json_grace = json_object_new_object(); + json_grace_send = json_object_new_object(); + json_grace_recv = json_object_new_object(); + + if (p->status == Established) { + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + for (safi = SAFI_UNICAST; + safi < SAFI_MAX; safi++) { + if (CHECK_FLAG( + p->af_sflags[afi] + [safi], + PEER_STATUS_EOR_SEND)) { + json_object_boolean_true_add( + json_grace_send, + afi_safi_print( + afi, + safi)); + eor_send_af_count++; + } + } + } + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + for (safi = SAFI_UNICAST; + safi < SAFI_MAX; safi++) { + if (CHECK_FLAG( + p->af_sflags[afi] + [safi], + PEER_STATUS_EOR_RECEIVED)) { + json_object_boolean_true_add( + json_grace_recv, + afi_safi_print( + afi, + safi)); + eor_receive_af_count++; + } + } + } + } + + json_object_object_add(json_grace, "endOfRibSend", + json_grace_send); + json_object_object_add(json_grace, "endOfRibRecv", + json_grace_recv); + + if (p->t_gr_restart) + json_object_int_add(json_grace, + "gracefulRestartTimerMsecs", + thread_timer_remain_second( + p->t_gr_restart) + * 1000); + + if (p->t_gr_stale) + json_object_int_add( + json_grace, + "gracefulStalepathTimerMsecs", + thread_timer_remain_second( + p->t_gr_stale) + * 1000); + + json_object_object_add( + json_neigh, "gracefulRestartInfo", json_grace); + } else { + vty_out(vty, " Graceful restart informations:\n"); + if (p->status == Established) { + vty_out(vty, " End-of-RIB send: "); + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + for (safi = SAFI_UNICAST; + safi < SAFI_MAX; safi++) { + if (CHECK_FLAG( + p->af_sflags[afi] + [safi], + PEER_STATUS_EOR_SEND)) { + vty_out(vty, "%s%s", + eor_send_af_count + ? ", " + : "", + afi_safi_print( + afi, + safi)); + eor_send_af_count++; + } + } + } + vty_out(vty, "\n"); + vty_out(vty, " End-of-RIB received: "); + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + for (safi = SAFI_UNICAST; + safi < SAFI_MAX; safi++) { + if (CHECK_FLAG( + p->af_sflags[afi] + [safi], + PEER_STATUS_EOR_RECEIVED)) { + vty_out(vty, "%s%s", + eor_receive_af_count + ? ", " + : "", + afi_safi_print( + afi, + safi)); + eor_receive_af_count++; + } + } + } + vty_out(vty, "\n"); + } + + if (p->t_gr_restart) + vty_out(vty, + " The remaining time of restart timer is %ld\n", + thread_timer_remain_second( + p->t_gr_restart)); + + if (p->t_gr_stale) + vty_out(vty, + " The remaining time of stalepath timer is %ld\n", + thread_timer_remain_second( + p->t_gr_stale)); + } + } + if (use_json) { + json_object *json_stat = NULL; + json_stat = json_object_new_object(); + /* Packet counts. */ + json_object_int_add(json_stat, "depthInq", 0); + json_object_int_add(json_stat, "depthOutq", + (unsigned long)p->obuf->count); + json_object_int_add(json_stat, "opensSent", p->open_out); + json_object_int_add(json_stat, "opensRecv", p->open_in); + json_object_int_add(json_stat, "notificationsSent", + p->notify_out); + json_object_int_add(json_stat, "notificationsRecv", + p->notify_in); + json_object_int_add(json_stat, "updatesSent", p->update_out); + json_object_int_add(json_stat, "updatesRecv", p->update_in); + json_object_int_add(json_stat, "keepalivesSent", + p->keepalive_out); + json_object_int_add(json_stat, "keepalivesRecv", + p->keepalive_in); + json_object_int_add(json_stat, "routeRefreshSent", + p->refresh_out); + json_object_int_add(json_stat, "routeRefreshRecv", + p->refresh_in); + json_object_int_add(json_stat, "capabilitySent", + p->dynamic_cap_out); + json_object_int_add(json_stat, "capabilityRecv", + p->dynamic_cap_in); + json_object_int_add(json_stat, "totalSent", + p->open_out + p->notify_out + p->update_out + + p->keepalive_out + p->refresh_out + + p->dynamic_cap_out); + json_object_int_add(json_stat, "totalRecv", + p->open_in + p->notify_in + p->update_in + + p->keepalive_in + p->refresh_in + + p->dynamic_cap_in); + json_object_object_add(json_neigh, "messageStats", json_stat); + } else { + /* Packet counts. */ + vty_out(vty, " Message statistics:\n"); + vty_out(vty, " Inq depth is 0\n"); + vty_out(vty, " Outq depth is %lu\n", + (unsigned long)p->obuf->count); + vty_out(vty, " Sent Rcvd\n"); + vty_out(vty, " Opens: %10d %10d\n", p->open_out, + p->open_in); + vty_out(vty, " Notifications: %10d %10d\n", p->notify_out, + p->notify_in); + vty_out(vty, " Updates: %10d %10d\n", p->update_out, + p->update_in); + vty_out(vty, " Keepalives: %10d %10d\n", p->keepalive_out, + p->keepalive_in); + vty_out(vty, " Route Refresh: %10d %10d\n", p->refresh_out, + p->refresh_in); + vty_out(vty, " Capability: %10d %10d\n", + p->dynamic_cap_out, p->dynamic_cap_in); + vty_out(vty, " Total: %10d %10d\n", + p->open_out + p->notify_out + p->update_out + + p->keepalive_out + p->refresh_out + + p->dynamic_cap_out, + p->open_in + p->notify_in + p->update_in + + p->keepalive_in + p->refresh_in + + p->dynamic_cap_in); + } + + if (use_json) { + /* advertisement-interval */ + json_object_int_add(json_neigh, + "minBtwnAdvertisementRunsTimerMsecs", + p->v_routeadv * 1000); + + /* Update-source. */ + if (p->update_if || p->update_source) { + if (p->update_if) + json_object_string_add(json_neigh, + "updateSource", + p->update_if); + else if (p->update_source) + json_object_string_add( + json_neigh, "updateSource", + sockunion2str(p->update_source, buf1, + SU_ADDRSTRLEN)); + } + } else { + /* advertisement-interval */ + vty_out(vty, + " Minimum time between advertisement runs is %d seconds\n", + p->v_routeadv); + + /* Update-source. */ + if (p->update_if || p->update_source) { + vty_out(vty, " Update source is "); + if (p->update_if) + vty_out(vty, "%s", p->update_if); + else if (p->update_source) + vty_out(vty, "%s", + sockunion2str(p->update_source, buf1, + SU_ADDRSTRLEN)); + vty_out(vty, "\n"); + } + + vty_out(vty, "\n"); + } + + /* Address Family Information */ + json_object *json_hold = NULL; + + if (use_json) + json_hold = json_object_new_object(); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + if (p->afc[afi][safi]) + bgp_show_peer_afi(vty, p, afi, safi, use_json, + json_hold); + + if (use_json) { + json_object_object_add(json_neigh, "addressFamilyInfo", + json_hold); + json_object_int_add(json_neigh, "connectionsEstablished", + p->established); + json_object_int_add(json_neigh, "connectionsDropped", + p->dropped); + } else + vty_out(vty, " Connections established %d; dropped %d\n", + p->established, p->dropped); + + if (!p->last_reset) { + if (use_json) + json_object_string_add(json_neigh, "lastReset", + "never"); + else + vty_out(vty, " Last reset never\n"); + } else { + if (use_json) { + time_t uptime; + struct tm *tm; + + uptime = bgp_clock(); + uptime -= p->resettime; + tm = gmtime(&uptime); + json_object_int_add(json_neigh, "lastResetTimerMsecs", + (tm->tm_sec * 1000) + + (tm->tm_min * 60000) + + (tm->tm_hour * 3600000)); + json_object_string_add( + json_neigh, "lastResetDueTo", + peer_down_str[(int)p->last_reset]); + if (p->last_reset == PEER_DOWN_NOTIFY_SEND + || p->last_reset == PEER_DOWN_NOTIFY_RECEIVED) { + char errorcodesubcode_hexstr[5]; + char errorcodesubcode_str[256]; + + code_str = bgp_notify_code_str(p->notify.code); + subcode_str = bgp_notify_subcode_str( + p->notify.code, p->notify.subcode); + + sprintf(errorcodesubcode_hexstr, "%02X%02X", + p->notify.code, p->notify.subcode); + json_object_string_add(json_neigh, + "lastErrorCodeSubcode", + errorcodesubcode_hexstr); + snprintf(errorcodesubcode_str, 255, "%s%s", + code_str, subcode_str); + json_object_string_add(json_neigh, + "lastNotificationReason", + errorcodesubcode_str); + if (p->last_reset == PEER_DOWN_NOTIFY_RECEIVED + && p->notify.code == BGP_NOTIFY_CEASE + && (p->notify.subcode + == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN + || p->notify.subcode + == BGP_NOTIFY_CEASE_ADMIN_RESET) + && p->notify.length) { + char msgbuf[1024]; + const char *msg_str; + + msg_str = bgp_notify_admin_message( + msgbuf, sizeof(msgbuf), + (u_char *)p->notify.data, + p->notify.length); + if (msg_str) + json_object_string_add( + json_neigh, + "lastShutdownDescription", + msg_str); + } + } + } else { + vty_out(vty, " Last reset %s, ", + peer_uptime(p->resettime, timebuf, + BGP_UPTIME_LEN, 0, NULL)); + + if (p->last_reset == PEER_DOWN_NOTIFY_SEND + || p->last_reset == PEER_DOWN_NOTIFY_RECEIVED) { + code_str = bgp_notify_code_str(p->notify.code); + subcode_str = bgp_notify_subcode_str( + p->notify.code, p->notify.subcode); + vty_out(vty, "due to NOTIFICATION %s (%s%s)\n", + p->last_reset == PEER_DOWN_NOTIFY_SEND + ? "sent" + : "received", + code_str, subcode_str); + if (p->last_reset == PEER_DOWN_NOTIFY_RECEIVED + && p->notify.code == BGP_NOTIFY_CEASE + && (p->notify.subcode + == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN + || p->notify.subcode + == BGP_NOTIFY_CEASE_ADMIN_RESET) + && p->notify.length) { + char msgbuf[1024]; + const char *msg_str; + + msg_str = bgp_notify_admin_message( + msgbuf, sizeof(msgbuf), + (u_char *)p->notify.data, + p->notify.length); + if (msg_str) + vty_out(vty, + " Message: \"%s\"\n", + msg_str); + } + } else { + vty_out(vty, "due to %s\n", + peer_down_str[(int)p->last_reset]); + } + + if (p->last_reset_cause_size) { + msg = p->last_reset_cause; + vty_out(vty, + " Message received that caused BGP to send a NOTIFICATION:\n "); + for (i = 1; i <= p->last_reset_cause_size; + i++) { + vty_out(vty, "%02X", *msg++); + + if (i != p->last_reset_cause_size) { + if (i % 16 == 0) { + vty_out(vty, "\n "); + } else if (i % 4 == 0) { + vty_out(vty, " "); + } + } + } + vty_out(vty, "\n"); + } + } + } + + if (CHECK_FLAG(p->sflags, PEER_STATUS_PREFIX_OVERFLOW)) { + if (use_json) + json_object_boolean_true_add(json_neigh, + "prefixesConfigExceedMax"); + else + vty_out(vty, + " Peer had exceeded the max. no. of prefixes configured.\n"); + + if (p->t_pmax_restart) { + if (use_json) { + json_object_boolean_true_add( + json_neigh, "reducePrefixNumFrom"); + json_object_int_add(json_neigh, + "restartInTimerMsec", + thread_timer_remain_second( + p->t_pmax_restart) + * 1000); + } else + vty_out(vty, + " Reduce the no. of prefix from %s, will restart in %ld seconds\n", + p->host, thread_timer_remain_second( + p->t_pmax_restart)); + } else { + if (use_json) + json_object_boolean_true_add( + json_neigh, + "reducePrefixNumAndClearIpBgp"); + else + vty_out(vty, + " Reduce the no. of prefix and clear ip bgp %s to restore peering\n", + p->host); + } + } + + /* EBGP Multihop and GTSM */ + if (p->sort != BGP_PEER_IBGP) { + if (use_json) { + if (p->gtsm_hops > 0) + json_object_int_add(json_neigh, + "externalBgpNbrMaxHopsAway", + p->gtsm_hops); + else if (p->ttl > 1) + json_object_int_add(json_neigh, + "externalBgpNbrMaxHopsAway", + p->ttl); + } else { + if (p->gtsm_hops > 0) + vty_out(vty, + " External BGP neighbor may be up to %d hops away.\n", + p->gtsm_hops); + else if (p->ttl > 1) + vty_out(vty, + " External BGP neighbor may be up to %d hops away.\n", + p->ttl); + } + } else { + if (p->gtsm_hops > 0) { + if (use_json) + json_object_int_add(json_neigh, + "internalBgpNbrMaxHopsAway", + p->gtsm_hops); + else + vty_out(vty, + " Internal BGP neighbor may be up to %d hops away.\n", + p->gtsm_hops); + } + } + + /* Local address. */ + if (p->su_local) { + if (use_json) { + json_object_string_add(json_neigh, "hostLocal", + sockunion2str(p->su_local, buf1, + SU_ADDRSTRLEN)); + json_object_int_add(json_neigh, "portLocal", + ntohs(p->su_local->sin.sin_port)); + } else + vty_out(vty, "Local host: %s, Local port: %d\n", + sockunion2str(p->su_local, buf1, SU_ADDRSTRLEN), + ntohs(p->su_local->sin.sin_port)); + } + + /* Remote address. */ + if (p->su_remote) { + if (use_json) { + json_object_string_add(json_neigh, "hostForeign", + sockunion2str(p->su_remote, buf1, + SU_ADDRSTRLEN)); + json_object_int_add(json_neigh, "portForeign", + ntohs(p->su_remote->sin.sin_port)); + } else + vty_out(vty, "Foreign host: %s, Foreign port: %d\n", + sockunion2str(p->su_remote, buf1, + SU_ADDRSTRLEN), + ntohs(p->su_remote->sin.sin_port)); + } + + /* Nexthop display. */ + if (p->su_local) { + if (use_json) { + json_object_string_add(json_neigh, "nexthop", + inet_ntop(AF_INET, + &p->nexthop.v4, buf1, + sizeof(buf1))); + json_object_string_add(json_neigh, "nexthopGlobal", + inet_ntop(AF_INET6, + &p->nexthop.v6_global, + buf1, sizeof(buf1))); + json_object_string_add(json_neigh, "nexthopLocal", + inet_ntop(AF_INET6, + &p->nexthop.v6_local, + buf1, sizeof(buf1))); + if (p->shared_network) + json_object_string_add(json_neigh, + "bgpConnection", + "sharedNetwork"); + else + json_object_string_add(json_neigh, + "bgpConnection", + "nonSharedNetwork"); + } else { + vty_out(vty, "Nexthop: %s\n", + inet_ntop(AF_INET, &p->nexthop.v4, buf1, + sizeof(buf1))); + vty_out(vty, "Nexthop global: %s\n", + inet_ntop(AF_INET6, &p->nexthop.v6_global, buf1, + sizeof(buf1))); + vty_out(vty, "Nexthop local: %s\n", + inet_ntop(AF_INET6, &p->nexthop.v6_local, buf1, + sizeof(buf1))); + vty_out(vty, "BGP connection: %s\n", + p->shared_network ? "shared network" + : "non shared network"); + } + } + + /* Timer information. */ + if (use_json) { + json_object_int_add(json_neigh, "connectRetryTimer", + p->v_connect); + if (p->status == Established && p->rtt) + json_object_int_add(json_neigh, "estimatedRttInMsecs", + p->rtt); + if (p->t_start) + json_object_int_add( + json_neigh, "nextStartTimerDueInMsecs", + thread_timer_remain_second(p->t_start) * 1000); + if (p->t_connect) + json_object_int_add( + json_neigh, "nextConnectTimerDueInMsecs", + thread_timer_remain_second(p->t_connect) + * 1000); + if (p->t_routeadv) { + json_object_int_add(json_neigh, "mraiInterval", + p->v_routeadv); + json_object_int_add( + json_neigh, "mraiTimerExpireInMsecs", + thread_timer_remain_second(p->t_routeadv) + * 1000); + } + if (p->password) + json_object_int_add(json_neigh, "authenticationEnabled", + 1); + + if (p->t_read) + json_object_string_add(json_neigh, "readThread", "on"); + else + json_object_string_add(json_neigh, "readThread", "off"); + if (p->t_write) + json_object_string_add(json_neigh, "writeThread", "on"); + else + json_object_string_add(json_neigh, "writeThread", + "off"); + } else { + vty_out(vty, "BGP Connect Retry Timer in Seconds: %d\n", + p->v_connect); + if (p->status == Established && p->rtt) + vty_out(vty, "Estimated round trip time: %d ms\n", + p->rtt); + if (p->t_start) + vty_out(vty, "Next start timer due in %ld seconds\n", + thread_timer_remain_second(p->t_start)); + if (p->t_connect) + vty_out(vty, "Next connect timer due in %ld seconds\n", + thread_timer_remain_second(p->t_connect)); + if (p->t_routeadv) + vty_out(vty, + "MRAI (interval %u) timer expires in %ld seconds\n", + p->v_routeadv, + thread_timer_remain_second(p->t_routeadv)); + if (p->password) + vty_out(vty, "Peer Authentication Enabled\n"); + + vty_out(vty, "Read thread: %s Write thread: %s\n", + p->t_read ? "on" : "off", p->t_write ? "on" : "off"); + } + + if (p->notify.code == BGP_NOTIFY_OPEN_ERR + && p->notify.subcode == BGP_NOTIFY_OPEN_UNSUP_CAPBL) + bgp_capability_vty_out(vty, p, use_json, json_neigh); + + if (!use_json) + vty_out(vty, "\n"); + + /* BFD information. */ + bgp_bfd_show_info(vty, p, use_json, json_neigh); + + if (use_json) { + if (p->conf_if) /* Configured interface name. */ + json_object_object_add(json, p->conf_if, json_neigh); + else /* Configured IP address. */ + json_object_object_add(json, p->host, json_neigh); + } +} + +static int bgp_show_neighbor(struct vty *vty, struct bgp *bgp, + enum show_type type, union sockunion *su, + const char *conf_if, u_char use_json, + json_object *json) +{ + struct listnode *node, *nnode; + struct peer *peer; + int find = 0; + + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) + continue; + + switch (type) { + case show_all: + bgp_show_peer(vty, peer, use_json, json); + break; + case show_peer: + if (conf_if) { + if ((peer->conf_if + && !strcmp(peer->conf_if, conf_if)) + || (peer->hostname + && !strcmp(peer->hostname, conf_if))) { + find = 1; + bgp_show_peer(vty, peer, use_json, + json); + } + } else { + if (sockunion_same(&peer->su, su)) { + find = 1; + bgp_show_peer(vty, peer, use_json, + json); + } + } + break; + } + } + + if (type == show_peer && !find) { + if (use_json) + json_object_boolean_true_add(json, "bgpNoSuchNeighbor"); + else + vty_out(vty, "%% No such neighbor\n"); + } + + if (use_json) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else { + vty_out(vty, "\n"); + } + + return CMD_SUCCESS; +} + +static void bgp_show_all_instances_neighbors_vty(struct vty *vty, + u_char use_json) +{ + struct listnode *node, *nnode; + struct bgp *bgp; + json_object *json = NULL; + int is_first = 1; + + if (use_json) + vty_out(vty, "{\n"); + + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) { + if (use_json) { + if (!(json = json_object_new_object())) { + zlog_err( + "Unable to allocate memory for JSON object"); + vty_out(vty, + "{\"error\": {\"message:\": \"Unable to allocate memory for JSON object\"}}}\n"); + return; + } + + json_object_int_add(json, "vrfId", + (bgp->vrf_id == VRF_UNKNOWN) + ? -1 + : bgp->vrf_id); + json_object_string_add( + json, "vrfName", + (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) + ? "Default" + : bgp->name); + + if (!is_first) + vty_out(vty, ",\n"); + else + is_first = 0; + + vty_out(vty, "\"%s\":", + (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) + ? "Default" + : bgp->name); + } else { + vty_out(vty, "\nInstance %s:\n", + (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) + ? "Default" + : bgp->name); + } + bgp_show_neighbor(vty, bgp, show_all, NULL, NULL, use_json, + json); + } + + if (use_json) + vty_out(vty, "}\n"); +} + +static int bgp_show_neighbor_vty(struct vty *vty, const char *name, + enum show_type type, const char *ip_str, + u_char use_json) +{ + int ret; + struct bgp *bgp; + union sockunion su; + json_object *json = NULL; + + if (name) { + if (strmatch(name, "all")) { + bgp_show_all_instances_neighbors_vty(vty, use_json); + return CMD_SUCCESS; + } else { + bgp = bgp_lookup_by_name(name); + if (!bgp) { + if (use_json) { + json = json_object_new_object(); + json_object_boolean_true_add( + json, "bgpNoSuchInstance"); + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, + JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else + vty_out(vty, + "%% No such BGP instance exist\n"); + + return CMD_WARNING; + } + } + } else { + bgp = bgp_get_default(); + } + + if (bgp) { + json = json_object_new_object(); + if (ip_str) { + ret = str2sockunion(ip_str, &su); + if (ret < 0) + bgp_show_neighbor(vty, bgp, type, NULL, ip_str, + use_json, json); + else + bgp_show_neighbor(vty, bgp, type, &su, NULL, + use_json, json); + } else { + bgp_show_neighbor(vty, bgp, type, NULL, NULL, use_json, + json); + } + json_object_free(json); + } + + return CMD_SUCCESS; } /* "show [ip] bgp neighbors" commands. */ @@ -9248,30 +9763,28 @@ DEFUN (show_ip_bgp_neighbors, "Neighbor on BGP configured interface\n" JSON_STR) { - char *vrf = NULL; - char *sh_arg = NULL; - enum show_type sh_type; + char *vrf = NULL; + char *sh_arg = NULL; + enum show_type sh_type; - u_char uj = use_json(argc, argv); + u_char uj = use_json(argc, argv); - int idx = 0; + int idx = 0; - if (argv_find (argv, argc, "view", &idx) || - argv_find (argv, argc, "vrf", &idx)) - vrf = argv[idx+1]->arg; + if (argv_find(argv, argc, "view", &idx) + || argv_find(argv, argc, "vrf", &idx)) + vrf = argv[idx + 1]->arg; - idx++; - if (argv_find (argv, argc, "A.B.C.D", &idx) || - argv_find (argv, argc, "X:X::X:X", &idx) || - argv_find (argv, argc, "WORD", &idx)) - { - sh_type = show_peer; - sh_arg = argv[idx]->arg; - } - else - sh_type = show_all; + idx++; + if (argv_find(argv, argc, "A.B.C.D", &idx) + || argv_find(argv, argc, "X:X::X:X", &idx) + || argv_find(argv, argc, "WORD", &idx)) { + sh_type = show_peer; + sh_arg = argv[idx]->arg; + } else + sh_type = show_all; - return bgp_show_neighbor_vty (vty, vrf, sh_type, sh_arg, uj); + return bgp_show_neighbor_vty(vty, vrf, sh_type, sh_arg, uj); } /* Show BGP's AS paths internal data. There are both `show [ip] bgp @@ -9286,21 +9799,21 @@ DEFUN (show_ip_bgp_paths, BGP_SAFI_HELP_STR "Path information\n") { - vty_out (vty, "Address Refcnt Path\n"); - aspath_print_all_vty (vty); - return CMD_SUCCESS; + vty_out(vty, "Address Refcnt Path\n"); + aspath_print_all_vty(vty); + return CMD_SUCCESS; } #include "hash.h" -static void -community_show_all_iterator (struct hash_backet *backet, struct vty *vty) +static void community_show_all_iterator(struct hash_backet *backet, + struct vty *vty) { - struct community *com; + struct community *com; - com = (struct community *) backet->data; - vty_out (vty, "[%p] (%ld) %s\n", (void *)backet, com->refcnt, - community_str (com)); + com = (struct community *)backet->data; + vty_out(vty, "[%p] (%ld) %s\n", (void *)backet, com->refcnt, + community_str(com)); } /* Show BGP's community internal data. */ @@ -9312,24 +9825,24 @@ DEFUN (show_ip_bgp_community_info, BGP_STR "List all bgp community information\n") { - vty_out (vty, "Address Refcnt Community\n"); + vty_out(vty, "Address Refcnt Community\n"); - hash_iterate (community_hash (), - (void (*) (struct hash_backet *, void *)) - community_show_all_iterator, - vty); + hash_iterate(community_hash(), + (void (*)(struct hash_backet *, + void *))community_show_all_iterator, + vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static void -lcommunity_show_all_iterator (struct hash_backet *backet, struct vty *vty) +static void lcommunity_show_all_iterator(struct hash_backet *backet, + struct vty *vty) { - struct lcommunity *lcom; + struct lcommunity *lcom; - lcom = (struct lcommunity *) backet->data; - vty_out (vty, "[%p] (%ld) %s\n", (void *)backet, lcom->refcnt, - lcommunity_str (lcom)); + lcom = (struct lcommunity *)backet->data; + vty_out(vty, "[%p] (%ld) %s\n", (void *)backet, lcom->refcnt, + lcommunity_str(lcom)); } /* Show BGP's community internal data. */ @@ -9341,14 +9854,14 @@ DEFUN (show_ip_bgp_lcommunity_info, BGP_STR "List all bgp large-community information\n") { - vty_out (vty, "Address Refcnt Large-community\n"); + vty_out(vty, "Address Refcnt Large-community\n"); - hash_iterate (lcommunity_hash (), - (void (*) (struct hash_backet *, void *)) - lcommunity_show_all_iterator, - vty); + hash_iterate(lcommunity_hash(), + (void (*)(struct hash_backet *, + void *))lcommunity_show_all_iterator, + vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -9360,51 +9873,44 @@ DEFUN (show_ip_bgp_attr_info, BGP_STR "List all bgp attribute information\n") { - attr_show_all (vty); - return CMD_SUCCESS; + attr_show_all(vty); + return CMD_SUCCESS; } -static void -bgp_show_all_instances_updgrps_vty (struct vty *vty, afi_t afi, safi_t safi) +static void bgp_show_all_instances_updgrps_vty(struct vty *vty, afi_t afi, + safi_t safi) { - struct listnode *node, *nnode; - struct bgp *bgp; + struct listnode *node, *nnode; + struct bgp *bgp; - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - { - vty_out (vty, "\nInstance %s:\n", - (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) ? "Default" : bgp->name); - update_group_show(bgp, afi, safi, vty, 0); - } + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) { + vty_out(vty, "\nInstance %s:\n", + (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) + ? "Default" + : bgp->name); + update_group_show(bgp, afi, safi, vty, 0); + } } -static int -bgp_show_update_groups(struct vty *vty, const char *name, - int afi, int safi, - uint64_t subgrp_id) +static int bgp_show_update_groups(struct vty *vty, const char *name, int afi, + int safi, uint64_t subgrp_id) { - struct bgp *bgp; + struct bgp *bgp; - if (name) - { - if (strmatch (name, "all")) - { - bgp_show_all_instances_updgrps_vty (vty, afi, safi); - return CMD_SUCCESS; - } - else - { - bgp = bgp_lookup_by_name (name); - } - } - else - { - bgp = bgp_get_default (); - } + if (name) { + if (strmatch(name, "all")) { + bgp_show_all_instances_updgrps_vty(vty, afi, safi); + return CMD_SUCCESS; + } else { + bgp = bgp_lookup_by_name(name); + } + } else { + bgp = bgp_get_default(); + } - if (bgp) - update_group_show(bgp, afi, safi, vty, subgrp_id); - return CMD_SUCCESS; + if (bgp) + update_group_show(bgp, afi, safi, vty, subgrp_id); + return CMD_SUCCESS; } DEFUN (show_ip_bgp_updgrps, @@ -9419,31 +9925,31 @@ DEFUN (show_ip_bgp_updgrps, "Detailed info about dynamic update groups\n" "Specific subgroup to display detailed info for\n") { - char *vrf = NULL; - afi_t afi = AFI_IP6; - safi_t safi = SAFI_UNICAST; - uint64_t subgrp_id = 0; - - int idx = 0; - - /* show [ip] bgp */ - if (argv_find (argv, argc, "ip", &idx)) - afi = AFI_IP; - /* [ VIEWVRFNAME] */ - if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx)) - vrf = argv[++idx]->arg; - /* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */ - if (argv_find_and_parse_afi (argv, argc, &idx, &afi)) - { - argv_find_and_parse_safi (argv, argc, &idx, &safi); - } + char *vrf = NULL; + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; + uint64_t subgrp_id = 0; + + int idx = 0; + + /* show [ip] bgp */ + if (argv_find(argv, argc, "ip", &idx)) + afi = AFI_IP; + /* [ VIEWVRFNAME] */ + if (argv_find(argv, argc, "view", &idx) + || argv_find(argv, argc, "vrf", &idx)) + vrf = argv[++idx]->arg; + /* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */ + if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) { + argv_find_and_parse_safi(argv, argc, &idx, &safi); + } - /* get subgroup id, if provided */ - idx = argc - 1; - if (argv[idx]->type == VARIABLE_TKN) - subgrp_id = strtoull(argv[idx]->arg, NULL, 10); + /* get subgroup id, if provided */ + idx = argc - 1; + if (argv[idx]->type == VARIABLE_TKN) + subgrp_id = strtoull(argv[idx]->arg, NULL, 10); - return (bgp_show_update_groups(vty, vrf, afi, safi, subgrp_id)); + return (bgp_show_update_groups(vty, vrf, afi, safi, subgrp_id)); } DEFUN (show_bgp_instance_all_ipv6_updgrps, @@ -9455,8 +9961,8 @@ DEFUN (show_bgp_instance_all_ipv6_updgrps, BGP_INSTANCE_ALL_HELP_STR "Detailed info about dynamic update groups\n") { - bgp_show_all_instances_updgrps_vty (vty, AFI_IP6, SAFI_UNICAST); - return CMD_SUCCESS; + bgp_show_all_instances_updgrps_vty(vty, AFI_IP6, SAFI_UNICAST); + return CMD_SUCCESS; } DEFUN (show_bgp_updgrps_stats, @@ -9468,13 +9974,13 @@ DEFUN (show_bgp_updgrps_stats, "Detailed info about dynamic update groups\n" "Statistics\n") { - struct bgp *bgp; + struct bgp *bgp; - bgp = bgp_get_default(); - if (bgp) - update_group_show_stats(bgp, vty); + bgp = bgp_get_default(); + if (bgp) + update_group_show_stats(bgp, vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_bgp_instance_updgrps_stats, @@ -9487,37 +9993,38 @@ DEFUN (show_bgp_instance_updgrps_stats, "Detailed info about dynamic update groups\n" "Statistics\n") { - int idx_word = 3; - struct bgp *bgp; + int idx_word = 3; + struct bgp *bgp; - bgp = bgp_lookup_by_name (argv[idx_word]->arg); - if (bgp) - update_group_show_stats(bgp, vty); + bgp = bgp_lookup_by_name(argv[idx_word]->arg); + if (bgp) + update_group_show_stats(bgp, vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static void -show_bgp_updgrps_adj_info_aux (struct vty *vty, const char *name, - afi_t afi, safi_t safi, - const char *what, uint64_t subgrp_id) +static void show_bgp_updgrps_adj_info_aux(struct vty *vty, const char *name, + afi_t afi, safi_t safi, + const char *what, uint64_t subgrp_id) { - struct bgp *bgp; + struct bgp *bgp; - if (name) - bgp = bgp_lookup_by_name (name); - else - bgp = bgp_get_default (); + if (name) + bgp = bgp_lookup_by_name(name); + else + bgp = bgp_get_default(); - if (bgp) - { - if (!strcmp(what, "advertise-queue")) - update_group_show_adj_queue(bgp, afi, safi, vty, subgrp_id); - else if (!strcmp(what, "advertised-routes")) - update_group_show_advertised(bgp, afi, safi, vty, subgrp_id); - else if (!strcmp(what, "packet-queue")) - update_group_show_packet_queue(bgp, afi, safi, vty, subgrp_id); - } + if (bgp) { + if (!strcmp(what, "advertise-queue")) + update_group_show_adj_queue(bgp, afi, safi, vty, + subgrp_id); + else if (!strcmp(what, "advertised-routes")) + update_group_show_advertised(bgp, afi, safi, vty, + subgrp_id); + else if (!strcmp(what, "packet-queue")) + update_group_show_packet_queue(bgp, afi, safi, vty, + subgrp_id); + } } DEFUN (show_ip_bgp_updgrps_adj, @@ -9530,11 +10037,11 @@ DEFUN (show_ip_bgp_updgrps_adj, "Advertisement queue\n" "Announced routes\n" "Packet queue\n") - { - int idx_type = 4; - show_bgp_updgrps_adj_info_aux(vty, NULL, AFI_IP, SAFI_UNICAST, argv[idx_type]->arg, 0); - return CMD_SUCCESS; + int idx_type = 4; + show_bgp_updgrps_adj_info_aux(vty, NULL, AFI_IP, SAFI_UNICAST, + argv[idx_type]->arg, 0); + return CMD_SUCCESS; } DEFUN (show_ip_bgp_instance_updgrps_adj, @@ -9548,12 +10055,12 @@ DEFUN (show_ip_bgp_instance_updgrps_adj, "Advertisement queue\n" "Announced routes\n" "Packet queue\n") - { - int idx_word = 4; - int idx_type = 6; - show_bgp_updgrps_adj_info_aux(vty, argv[idx_word]->arg, AFI_IP, SAFI_UNICAST, argv[idx_type]->arg, 0); - return CMD_SUCCESS; + int idx_word = 4; + int idx_type = 6; + show_bgp_updgrps_adj_info_aux(vty, argv[idx_word]->arg, AFI_IP, + SAFI_UNICAST, argv[idx_type]->arg, 0); + return CMD_SUCCESS; } DEFUN (show_bgp_updgrps_afi_adj, @@ -9568,14 +10075,14 @@ DEFUN (show_bgp_updgrps_afi_adj, "Announced routes\n" "Packet queue\n") { - int idx_afi = 2; - int idx_safi = 3; - int idx_type = 5; - show_bgp_updgrps_adj_info_aux(vty, NULL, - bgp_vty_afi_from_str(argv[idx_afi]->text), - bgp_vty_safi_from_str(argv[idx_safi]->text), - argv[idx_type]->arg, 0); - return CMD_SUCCESS; + int idx_afi = 2; + int idx_safi = 3; + int idx_type = 5; + show_bgp_updgrps_adj_info_aux( + vty, NULL, bgp_vty_afi_from_str(argv[idx_afi]->text), + bgp_vty_safi_from_str(argv[idx_safi]->text), + argv[idx_type]->arg, 0); + return CMD_SUCCESS; } DEFUN (show_bgp_updgrps_adj, @@ -9589,9 +10096,10 @@ DEFUN (show_bgp_updgrps_adj, "Announced routes\n" "Packet queue\n") { - int idx_type = 3; - show_bgp_updgrps_adj_info_aux(vty, NULL, AFI_IP6, SAFI_UNICAST, argv[idx_type]->arg, 0); - return CMD_SUCCESS; + int idx_type = 3; + show_bgp_updgrps_adj_info_aux(vty, NULL, AFI_IP6, SAFI_UNICAST, + argv[idx_type]->arg, 0); + return CMD_SUCCESS; } DEFUN (show_bgp_instance_updgrps_adj, @@ -9606,10 +10114,11 @@ DEFUN (show_bgp_instance_updgrps_adj, "Announced routes\n" "Packet queue\n") { - int idx_word = 3; - int idx_type = 5; - show_bgp_updgrps_adj_info_aux(vty, argv[idx_word]->arg, AFI_IP6, SAFI_UNICAST, argv[idx_type]->arg, 0); - return CMD_SUCCESS; + int idx_word = 3; + int idx_type = 5; + show_bgp_updgrps_adj_info_aux(vty, argv[idx_word]->arg, AFI_IP6, + SAFI_UNICAST, argv[idx_type]->arg, 0); + return CMD_SUCCESS; } DEFUN (show_ip_bgp_updgrps_adj_s, @@ -9623,16 +10132,16 @@ DEFUN (show_ip_bgp_updgrps_adj_s, "Advertisement queue\n" "Announced routes\n" "Packet queue\n") - { - int idx_subgroup_id = 4; - int idx_type = 5; - uint64_t subgrp_id; + int idx_subgroup_id = 4; + int idx_type = 5; + uint64_t subgrp_id; - subgrp_id = strtoull(argv[idx_subgroup_id]->arg, NULL, 10); + subgrp_id = strtoull(argv[idx_subgroup_id]->arg, NULL, 10); - show_bgp_updgrps_adj_info_aux(vty, NULL, AFI_IP, SAFI_UNICAST, argv[idx_type]->arg, subgrp_id); - return CMD_SUCCESS; + show_bgp_updgrps_adj_info_aux(vty, NULL, AFI_IP, SAFI_UNICAST, + argv[idx_type]->arg, subgrp_id); + return CMD_SUCCESS; } DEFUN (show_ip_bgp_instance_updgrps_adj_s, @@ -9647,17 +10156,18 @@ DEFUN (show_ip_bgp_instance_updgrps_adj_s, "Advertisement queue\n" "Announced routes\n" "Packet queue\n") - { - int idx_vrf = 4; - int idx_subgroup_id = 6; - int idx_type = 7; - uint64_t subgrp_id; + int idx_vrf = 4; + int idx_subgroup_id = 6; + int idx_type = 7; + uint64_t subgrp_id; - subgrp_id = strtoull(argv[idx_subgroup_id]->arg, NULL, 10); + subgrp_id = strtoull(argv[idx_subgroup_id]->arg, NULL, 10); - show_bgp_updgrps_adj_info_aux(vty, argv[idx_vrf]->arg, AFI_IP, SAFI_UNICAST, argv[idx_type]->arg, subgrp_id); - return CMD_SUCCESS; + show_bgp_updgrps_adj_info_aux(vty, argv[idx_vrf]->arg, AFI_IP, + SAFI_UNICAST, argv[idx_type]->arg, + subgrp_id); + return CMD_SUCCESS; } DEFUN (show_bgp_updgrps_afi_adj_s, @@ -9673,19 +10183,19 @@ DEFUN (show_bgp_updgrps_afi_adj_s, "Announced routes\n" "Packet queue\n") { - int idx_afi = 2; - int idx_safi = 3; - int idx_subgroup_id = 5; - int idx_type = 6; - uint64_t subgrp_id; + int idx_afi = 2; + int idx_safi = 3; + int idx_subgroup_id = 5; + int idx_type = 6; + uint64_t subgrp_id; - subgrp_id = strtoull(argv[idx_subgroup_id]->arg, NULL, 10); + subgrp_id = strtoull(argv[idx_subgroup_id]->arg, NULL, 10); - show_bgp_updgrps_adj_info_aux(vty, NULL, - bgp_vty_afi_from_str(argv[idx_afi]->text), - bgp_vty_safi_from_str(argv[idx_safi]->text), - argv[idx_type]->arg, subgrp_id); - return CMD_SUCCESS; + show_bgp_updgrps_adj_info_aux( + vty, NULL, bgp_vty_afi_from_str(argv[idx_afi]->text), + bgp_vty_safi_from_str(argv[idx_safi]->text), + argv[idx_type]->arg, subgrp_id); + return CMD_SUCCESS; } DEFUN (show_bgp_updgrps_adj_s, @@ -9700,14 +10210,15 @@ DEFUN (show_bgp_updgrps_adj_s, "Announced routes\n" "Packet queue\n") { - int idx_subgroup_id = 3; - int idx_type = 4; - uint64_t subgrp_id; + int idx_subgroup_id = 3; + int idx_type = 4; + uint64_t subgrp_id; - subgrp_id = strtoull(argv[idx_subgroup_id]->arg, NULL, 10); + subgrp_id = strtoull(argv[idx_subgroup_id]->arg, NULL, 10); - show_bgp_updgrps_adj_info_aux(vty, NULL, AFI_IP6, SAFI_UNICAST, argv[idx_type]->arg, subgrp_id); - return CMD_SUCCESS; + show_bgp_updgrps_adj_info_aux(vty, NULL, AFI_IP6, SAFI_UNICAST, + argv[idx_type]->arg, subgrp_id); + return CMD_SUCCESS; } DEFUN (show_bgp_instance_updgrps_adj_s, @@ -9723,175 +10234,162 @@ DEFUN (show_bgp_instance_updgrps_adj_s, "Announced routes\n" "Packet queue\n") { - int idx_vrf = 3; - int idx_subgroup_id = 5; - int idx_type = 6; - uint64_t subgrp_id; - - subgrp_id = strtoull(argv[idx_subgroup_id]->arg, NULL, 10); - - show_bgp_updgrps_adj_info_aux(vty, argv[idx_vrf]->arg, AFI_IP6, SAFI_UNICAST, argv[idx_type]->arg, subgrp_id); - return CMD_SUCCESS; -} - - - -static int -bgp_show_one_peer_group (struct vty *vty, struct peer_group *group) -{ - struct listnode *node, *nnode; - struct prefix *range; - struct peer *conf; - struct peer *peer; - char buf[PREFIX2STR_BUFFER]; - afi_t afi; - safi_t safi; - const char *peer_status; - const char *af_str; - int lr_count; - int dynamic; - int af_cfgd; - - conf = group->conf; - - if (conf->as_type == AS_SPECIFIED || - conf->as_type == AS_EXTERNAL) { - vty_out (vty, "\nBGP peer-group %s, remote AS %d\n", group->name, conf->as); - } else if (conf->as_type == AS_INTERNAL) { - vty_out (vty, "\nBGP peer-group %s, remote AS %d\n", group->name, group->bgp->as); - } else { - vty_out (vty, "\nBGP peer-group %s\n", group->name); - } - - if ((group->bgp->as == conf->as) || (conf->as_type == AS_INTERNAL)) - vty_out (vty, " Peer-group type is internal\n"); - else - vty_out (vty, " Peer-group type is external\n"); - - /* Display AFs configured. */ - vty_out (vty, " Configured address-families:"); - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - if (conf->afc[afi][safi]) - { - af_cfgd = 1; - vty_out (vty, " %s;", afi_safi_print(afi, safi)); - } - } - if (!af_cfgd) - vty_out (vty, " none\n"); - else - vty_out (vty, "\n"); - - /* Display listen ranges (for dynamic neighbors), if any */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - if (afi == AFI_IP) - af_str = "IPv4"; - else if (afi == AFI_IP6) - af_str = "IPv6"; - else - af_str = "???"; - lr_count = listcount(group->listen_range[afi]); - if (lr_count) - { - vty_out(vty, - " %d %s listen range(s)\n", - lr_count, af_str); - - - for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, - nnode, range)) - { - prefix2str(range, buf, sizeof(buf)); - vty_out(vty, " %s\n", buf); - } - } - } - - /* Display group members and their status */ - if (listcount(group->peer)) - { - vty_out (vty, " Peer-group members:\n"); - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN)) - peer_status = "Idle (Admin)"; - else if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW)) - peer_status = "Idle (PfxCt)"; - else - peer_status = lookup_msg(bgp_status_msg, peer->status, NULL); - - dynamic = peer_dynamic_neighbor(peer); - vty_out (vty, " %s %s %s \n", - peer->host, dynamic ? "(dynamic)" : "", - peer_status); - } - } - - return CMD_SUCCESS; -} + int idx_vrf = 3; + int idx_subgroup_id = 5; + int idx_type = 6; + uint64_t subgrp_id; + + subgrp_id = strtoull(argv[idx_subgroup_id]->arg, NULL, 10); + + show_bgp_updgrps_adj_info_aux(vty, argv[idx_vrf]->arg, AFI_IP6, + SAFI_UNICAST, argv[idx_type]->arg, + subgrp_id); + return CMD_SUCCESS; +} + + +static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group) +{ + struct listnode *node, *nnode; + struct prefix *range; + struct peer *conf; + struct peer *peer; + char buf[PREFIX2STR_BUFFER]; + afi_t afi; + safi_t safi; + const char *peer_status; + const char *af_str; + int lr_count; + int dynamic; + int af_cfgd; + + conf = group->conf; + + if (conf->as_type == AS_SPECIFIED || conf->as_type == AS_EXTERNAL) { + vty_out(vty, "\nBGP peer-group %s, remote AS %d\n", group->name, + conf->as); + } else if (conf->as_type == AS_INTERNAL) { + vty_out(vty, "\nBGP peer-group %s, remote AS %d\n", group->name, + group->bgp->as); + } else { + vty_out(vty, "\nBGP peer-group %s\n", group->name); + } -/* Show BGP peer group's information. */ -enum show_group_type -{ - show_all_groups, - show_peer_group -}; + if ((group->bgp->as == conf->as) || (conf->as_type == AS_INTERNAL)) + vty_out(vty, " Peer-group type is internal\n"); + else + vty_out(vty, " Peer-group type is external\n"); + + /* Display AFs configured. */ + vty_out(vty, " Configured address-families:"); + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + if (conf->afc[afi][safi]) { + af_cfgd = 1; + vty_out(vty, " %s;", afi_safi_print(afi, safi)); + } + } + if (!af_cfgd) + vty_out(vty, " none\n"); + else + vty_out(vty, "\n"); + + /* Display listen ranges (for dynamic neighbors), if any */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + if (afi == AFI_IP) + af_str = "IPv4"; + else if (afi == AFI_IP6) + af_str = "IPv6"; + else + af_str = "???"; + lr_count = listcount(group->listen_range[afi]); + if (lr_count) { + vty_out(vty, " %d %s listen range(s)\n", lr_count, + af_str); + + + for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, + nnode, range)) { + prefix2str(range, buf, sizeof(buf)); + vty_out(vty, " %s\n", buf); + } + } + } -static int -bgp_show_peer_group (struct vty *vty, struct bgp *bgp, - enum show_group_type type, const char *group_name) -{ - struct listnode *node, *nnode; - struct peer_group *group; - int find = 0; + /* Display group members and their status */ + if (listcount(group->peer)) { + vty_out(vty, " Peer-group members:\n"); + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) + peer_status = "Idle (Admin)"; + else if (CHECK_FLAG(peer->sflags, + PEER_STATUS_PREFIX_OVERFLOW)) + peer_status = "Idle (PfxCt)"; + else + peer_status = lookup_msg(bgp_status_msg, + peer->status, NULL); + + dynamic = peer_dynamic_neighbor(peer); + vty_out(vty, " %s %s %s \n", peer->host, + dynamic ? "(dynamic)" : "", peer_status); + } + } - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - { - switch (type) - { - case show_all_groups: - bgp_show_one_peer_group (vty, group); - break; - case show_peer_group: - if (group_name && (strcmp(group->name, group_name) == 0)) - { - find = 1; - bgp_show_one_peer_group (vty, group); - } - break; + return CMD_SUCCESS; +} + +/* Show BGP peer group's information. */ +enum show_group_type { show_all_groups, show_peer_group }; + +static int bgp_show_peer_group(struct vty *vty, struct bgp *bgp, + enum show_group_type type, + const char *group_name) +{ + struct listnode *node, *nnode; + struct peer_group *group; + int find = 0; + + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) { + switch (type) { + case show_all_groups: + bgp_show_one_peer_group(vty, group); + break; + case show_peer_group: + if (group_name + && (strcmp(group->name, group_name) == 0)) { + find = 1; + bgp_show_one_peer_group(vty, group); + } + break; + } } - } - if (type == show_peer_group && ! find) - vty_out (vty, "%% No such peer-group\n"); + if (type == show_peer_group && !find) + vty_out(vty, "%% No such peer-group\n"); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -bgp_show_peer_group_vty (struct vty *vty, const char *name, - enum show_group_type type, const char *group_name) +static int bgp_show_peer_group_vty(struct vty *vty, const char *name, + enum show_group_type type, + const char *group_name) { - struct bgp *bgp; - int ret = CMD_SUCCESS; + struct bgp *bgp; + int ret = CMD_SUCCESS; - if (name) - bgp = bgp_lookup_by_name (name); - else - bgp = bgp_get_default (); + if (name) + bgp = bgp_lookup_by_name(name); + else + bgp = bgp_get_default(); - if (! bgp) - { - vty_out (vty, "%% No such BGP instance exist\n"); - return CMD_WARNING; - } + if (!bgp) { + vty_out(vty, "%% No such BGP instance exist\n"); + return CMD_WARNING; + } - ret = bgp_show_peer_group (vty, bgp, type, group_name); + ret = bgp_show_peer_group(vty, bgp, type, group_name); - return ret; + return ret; } DEFUN (show_ip_bgp_peer_groups, @@ -9904,14 +10402,14 @@ DEFUN (show_ip_bgp_peer_groups, "Detailed information on BGP peer groups\n" "Peer group name\n") { - char *vrf, *pg; - vrf = pg = NULL; - int idx = 0; + char *vrf, *pg; + vrf = pg = NULL; + int idx = 0; - vrf = argv_find (argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL; - pg = argv_find (argv, argc, "PGNAME", &idx) ? argv[idx]->arg : NULL; + vrf = argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL; + pg = argv_find(argv, argc, "PGNAME", &idx) ? argv[idx]->arg : NULL; - return bgp_show_peer_group_vty (vty, vrf, show_all_groups, pg); + return bgp_show_peer_group_vty(vty, vrf, show_all_groups, pg); } @@ -9923,25 +10421,23 @@ DEFUN (bgp_redistribute_ipv4, "Redistribute information from another routing protocol\n" FRR_IP_REDIST_HELP_STR_BGPD) { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_protocol = 1; - int type; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_protocol = 1; + int type; - type = proto_redistnum (AFI_IP, argv[idx_protocol]->text); - if (type < 0) - { - vty_out (vty, "%% Invalid route type\n"); - return CMD_WARNING_CONFIG_FAILED; - } - bgp_redist_add(bgp, AFI_IP, type, 0); - return bgp_redistribute_set (bgp, AFI_IP, type, 0); + type = proto_redistnum(AFI_IP, argv[idx_protocol]->text); + if (type < 0) { + vty_out(vty, "%% Invalid route type\n"); + return CMD_WARNING_CONFIG_FAILED; + } + bgp_redist_add(bgp, AFI_IP, type, 0); + return bgp_redistribute_set(bgp, AFI_IP, type, 0); } -ALIAS_HIDDEN (bgp_redistribute_ipv4, - bgp_redistribute_ipv4_hidden_cmd, - "redistribute " FRR_IP_REDIST_STR_BGPD, - "Redistribute information from another routing protocol\n" - FRR_IP_REDIST_HELP_STR_BGPD) +ALIAS_HIDDEN( + bgp_redistribute_ipv4, bgp_redistribute_ipv4_hidden_cmd, + "redistribute " FRR_IP_REDIST_STR_BGPD, + "Redistribute information from another routing protocol\n" FRR_IP_REDIST_HELP_STR_BGPD) DEFUN (bgp_redistribute_ipv4_rmap, bgp_redistribute_ipv4_rmap_cmd, @@ -9951,31 +10447,29 @@ DEFUN (bgp_redistribute_ipv4_rmap, "Route map reference\n" "Pointer to route-map entries\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_protocol = 1; - int idx_word = 3; - int type; - struct bgp_redist *red; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_protocol = 1; + int idx_word = 3; + int type; + struct bgp_redist *red; - type = proto_redistnum (AFI_IP, argv[idx_protocol]->text); - if (type < 0) - { - vty_out (vty, "%% Invalid route type\n"); - return CMD_WARNING_CONFIG_FAILED; - } + type = proto_redistnum(AFI_IP, argv[idx_protocol]->text); + if (type < 0) { + vty_out(vty, "%% Invalid route type\n"); + return CMD_WARNING_CONFIG_FAILED; + } - red = bgp_redist_add(bgp, AFI_IP, type, 0); - bgp_redistribute_rmap_set (red, argv[idx_word]->arg); - return bgp_redistribute_set (bgp, AFI_IP, type, 0); + red = bgp_redist_add(bgp, AFI_IP, type, 0); + bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + return bgp_redistribute_set(bgp, AFI_IP, type, 0); } -ALIAS_HIDDEN (bgp_redistribute_ipv4_rmap, - bgp_redistribute_ipv4_rmap_hidden_cmd, - "redistribute " FRR_IP_REDIST_STR_BGPD " route-map WORD", - "Redistribute information from another routing protocol\n" - FRR_IP_REDIST_HELP_STR_BGPD - "Route map reference\n" - "Pointer to route-map entries\n") +ALIAS_HIDDEN( + bgp_redistribute_ipv4_rmap, bgp_redistribute_ipv4_rmap_hidden_cmd, + "redistribute " FRR_IP_REDIST_STR_BGPD " route-map WORD", + "Redistribute information from another routing protocol\n" FRR_IP_REDIST_HELP_STR_BGPD + "Route map reference\n" + "Pointer to route-map entries\n") DEFUN (bgp_redistribute_ipv4_metric, bgp_redistribute_ipv4_metric_cmd, @@ -9985,33 +10479,31 @@ DEFUN (bgp_redistribute_ipv4_metric, "Metric for redistributed routes\n" "Default metric\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_protocol = 1; - int idx_number = 3; - int type; - u_int32_t metric; - struct bgp_redist *red; - - type = proto_redistnum (AFI_IP, argv[idx_protocol]->text); - if (type < 0) - { - vty_out (vty, "%% Invalid route type\n"); - return CMD_WARNING_CONFIG_FAILED; - } - metric = strtoul(argv[idx_number]->arg, NULL, 10); - - red = bgp_redist_add(bgp, AFI_IP, type, 0); - bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric); - return bgp_redistribute_set (bgp, AFI_IP, type, 0); -} - -ALIAS_HIDDEN (bgp_redistribute_ipv4_metric, - bgp_redistribute_ipv4_metric_hidden_cmd, - "redistribute " FRR_IP_REDIST_STR_BGPD " metric (0-4294967295)", - "Redistribute information from another routing protocol\n" - FRR_IP_REDIST_HELP_STR_BGPD - "Metric for redistributed routes\n" - "Default metric\n") + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_protocol = 1; + int idx_number = 3; + int type; + u_int32_t metric; + struct bgp_redist *red; + + type = proto_redistnum(AFI_IP, argv[idx_protocol]->text); + if (type < 0) { + vty_out(vty, "%% Invalid route type\n"); + return CMD_WARNING_CONFIG_FAILED; + } + metric = strtoul(argv[idx_number]->arg, NULL, 10); + + red = bgp_redist_add(bgp, AFI_IP, type, 0); + bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric); + return bgp_redistribute_set(bgp, AFI_IP, type, 0); +} + +ALIAS_HIDDEN( + bgp_redistribute_ipv4_metric, bgp_redistribute_ipv4_metric_hidden_cmd, + "redistribute " FRR_IP_REDIST_STR_BGPD " metric (0-4294967295)", + "Redistribute information from another routing protocol\n" FRR_IP_REDIST_HELP_STR_BGPD + "Metric for redistributed routes\n" + "Default metric\n") DEFUN (bgp_redistribute_ipv4_rmap_metric, bgp_redistribute_ipv4_rmap_metric_cmd, @@ -10023,37 +10515,37 @@ DEFUN (bgp_redistribute_ipv4_rmap_metric, "Metric for redistributed routes\n" "Default metric\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_protocol = 1; - int idx_word = 3; - int idx_number = 5; - int type; - u_int32_t metric; - struct bgp_redist *red; - - type = proto_redistnum (AFI_IP, argv[idx_protocol]->text); - if (type < 0) - { - vty_out (vty, "%% Invalid route type\n"); - return CMD_WARNING_CONFIG_FAILED; - } - metric = strtoul(argv[idx_number]->arg, NULL, 10); - - red = bgp_redist_add(bgp, AFI_IP, type, 0); - bgp_redistribute_rmap_set (red, argv[idx_word]->arg); - bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric); - return bgp_redistribute_set (bgp, AFI_IP, type, 0); -} - -ALIAS_HIDDEN (bgp_redistribute_ipv4_rmap_metric, - bgp_redistribute_ipv4_rmap_metric_hidden_cmd, - "redistribute " FRR_IP_REDIST_STR_BGPD " route-map WORD metric (0-4294967295)", - "Redistribute information from another routing protocol\n" - FRR_IP_REDIST_HELP_STR_BGPD - "Route map reference\n" - "Pointer to route-map entries\n" - "Metric for redistributed routes\n" - "Default metric\n") + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_protocol = 1; + int idx_word = 3; + int idx_number = 5; + int type; + u_int32_t metric; + struct bgp_redist *red; + + type = proto_redistnum(AFI_IP, argv[idx_protocol]->text); + if (type < 0) { + vty_out(vty, "%% Invalid route type\n"); + return CMD_WARNING_CONFIG_FAILED; + } + metric = strtoul(argv[idx_number]->arg, NULL, 10); + + red = bgp_redist_add(bgp, AFI_IP, type, 0); + bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric); + return bgp_redistribute_set(bgp, AFI_IP, type, 0); +} + +ALIAS_HIDDEN( + bgp_redistribute_ipv4_rmap_metric, + bgp_redistribute_ipv4_rmap_metric_hidden_cmd, + "redistribute " FRR_IP_REDIST_STR_BGPD + " route-map WORD metric (0-4294967295)", + "Redistribute information from another routing protocol\n" FRR_IP_REDIST_HELP_STR_BGPD + "Route map reference\n" + "Pointer to route-map entries\n" + "Metric for redistributed routes\n" + "Default metric\n") DEFUN (bgp_redistribute_ipv4_metric_rmap, bgp_redistribute_ipv4_metric_rmap_cmd, @@ -10065,37 +10557,37 @@ DEFUN (bgp_redistribute_ipv4_metric_rmap, "Route map reference\n" "Pointer to route-map entries\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_protocol = 1; - int idx_number = 3; - int idx_word = 5; - int type; - u_int32_t metric; - struct bgp_redist *red; - - type = proto_redistnum (AFI_IP, argv[idx_protocol]->text); - if (type < 0) - { - vty_out (vty, "%% Invalid route type\n"); - return CMD_WARNING_CONFIG_FAILED; - } - metric = strtoul(argv[idx_number]->arg, NULL, 10); - - red = bgp_redist_add(bgp, AFI_IP, type, 0); - bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric); - bgp_redistribute_rmap_set (red, argv[idx_word]->arg); - return bgp_redistribute_set (bgp, AFI_IP, type, 0); -} - -ALIAS_HIDDEN (bgp_redistribute_ipv4_metric_rmap, - bgp_redistribute_ipv4_metric_rmap_hidden_cmd, - "redistribute " FRR_IP_REDIST_STR_BGPD " metric (0-4294967295) route-map WORD", - "Redistribute information from another routing protocol\n" - FRR_IP_REDIST_HELP_STR_BGPD - "Metric for redistributed routes\n" - "Default metric\n" - "Route map reference\n" - "Pointer to route-map entries\n") + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_protocol = 1; + int idx_number = 3; + int idx_word = 5; + int type; + u_int32_t metric; + struct bgp_redist *red; + + type = proto_redistnum(AFI_IP, argv[idx_protocol]->text); + if (type < 0) { + vty_out(vty, "%% Invalid route type\n"); + return CMD_WARNING_CONFIG_FAILED; + } + metric = strtoul(argv[idx_number]->arg, NULL, 10); + + red = bgp_redist_add(bgp, AFI_IP, type, 0); + bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric); + bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + return bgp_redistribute_set(bgp, AFI_IP, type, 0); +} + +ALIAS_HIDDEN( + bgp_redistribute_ipv4_metric_rmap, + bgp_redistribute_ipv4_metric_rmap_hidden_cmd, + "redistribute " FRR_IP_REDIST_STR_BGPD + " metric (0-4294967295) route-map WORD", + "Redistribute information from another routing protocol\n" FRR_IP_REDIST_HELP_STR_BGPD + "Metric for redistributed routes\n" + "Default metric\n" + "Route map reference\n" + "Pointer to route-map entries\n") DEFUN (bgp_redistribute_ipv4_ospf, bgp_redistribute_ipv4_ospf_cmd, @@ -10105,30 +10597,29 @@ DEFUN (bgp_redistribute_ipv4_ospf, "Non-main Kernel Routing Table\n" "Instance ID/Table ID\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_ospf_table = 1; - int idx_number = 2; - u_short instance; - u_short protocol; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_ospf_table = 1; + int idx_number = 2; + u_short instance; + u_short protocol; - instance = strtoul(argv[idx_number]->arg, NULL, 10); + instance = strtoul(argv[idx_number]->arg, NULL, 10); - if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) - protocol = ZEBRA_ROUTE_OSPF; - else - protocol = ZEBRA_ROUTE_TABLE; + if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) + protocol = ZEBRA_ROUTE_OSPF; + else + protocol = ZEBRA_ROUTE_TABLE; - bgp_redist_add(bgp, AFI_IP, protocol, instance); - return bgp_redistribute_set (bgp, AFI_IP, protocol, instance); + bgp_redist_add(bgp, AFI_IP, protocol, instance); + return bgp_redistribute_set(bgp, AFI_IP, protocol, instance); } -ALIAS_HIDDEN (bgp_redistribute_ipv4_ospf, - bgp_redistribute_ipv4_ospf_hidden_cmd, - "redistribute (1-65535)", - "Redistribute information from another routing protocol\n" - "Open Shortest Path First (OSPFv2)\n" - "Non-main Kernel Routing Table\n" - "Instance ID/Table ID\n") +ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf, bgp_redistribute_ipv4_ospf_hidden_cmd, + "redistribute (1-65535)", + "Redistribute information from another routing protocol\n" + "Open Shortest Path First (OSPFv2)\n" + "Non-main Kernel Routing Table\n" + "Instance ID/Table ID\n") DEFUN (bgp_redistribute_ipv4_ospf_rmap, bgp_redistribute_ipv4_ospf_rmap_cmd, @@ -10140,34 +10631,34 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap, "Route map reference\n" "Pointer to route-map entries\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_ospf_table = 1; - int idx_number = 2; - int idx_word = 4; - struct bgp_redist *red; - u_short instance; - int protocol; - - if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) - protocol = ZEBRA_ROUTE_OSPF; - else - protocol = ZEBRA_ROUTE_TABLE; - - instance = strtoul(argv[idx_number]->arg, NULL, 10); - red = bgp_redist_add(bgp, AFI_IP, protocol, instance); - bgp_redistribute_rmap_set (red, argv[idx_word]->arg); - return bgp_redistribute_set (bgp, AFI_IP, protocol, instance); -} - -ALIAS_HIDDEN (bgp_redistribute_ipv4_ospf_rmap, - bgp_redistribute_ipv4_ospf_rmap_hidden_cmd, - "redistribute (1-65535) route-map WORD", - "Redistribute information from another routing protocol\n" - "Open Shortest Path First (OSPFv2)\n" - "Non-main Kernel Routing Table\n" - "Instance ID/Table ID\n" - "Route map reference\n" - "Pointer to route-map entries\n") + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_ospf_table = 1; + int idx_number = 2; + int idx_word = 4; + struct bgp_redist *red; + u_short instance; + int protocol; + + if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) + protocol = ZEBRA_ROUTE_OSPF; + else + protocol = ZEBRA_ROUTE_TABLE; + + instance = strtoul(argv[idx_number]->arg, NULL, 10); + red = bgp_redist_add(bgp, AFI_IP, protocol, instance); + bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + return bgp_redistribute_set(bgp, AFI_IP, protocol, instance); +} + +ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf_rmap, + bgp_redistribute_ipv4_ospf_rmap_hidden_cmd, + "redistribute (1-65535) route-map WORD", + "Redistribute information from another routing protocol\n" + "Open Shortest Path First (OSPFv2)\n" + "Non-main Kernel Routing Table\n" + "Instance ID/Table ID\n" + "Route map reference\n" + "Pointer to route-map entries\n") DEFUN (bgp_redistribute_ipv4_ospf_metric, bgp_redistribute_ipv4_ospf_metric_cmd, @@ -10179,37 +10670,37 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric, "Metric for redistributed routes\n" "Default metric\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_ospf_table = 1; - int idx_number = 2; - int idx_number_2 = 4; - u_int32_t metric; - struct bgp_redist *red; - u_short instance; - int protocol; - - if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) - protocol = ZEBRA_ROUTE_OSPF; - else - protocol = ZEBRA_ROUTE_TABLE; - - instance = strtoul(argv[idx_number]->arg, NULL, 10); - metric = strtoul(argv[idx_number_2]->arg, NULL, 10); - - red = bgp_redist_add(bgp, AFI_IP, protocol, instance); - bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric); - return bgp_redistribute_set (bgp, AFI_IP, protocol, instance); -} - -ALIAS_HIDDEN (bgp_redistribute_ipv4_ospf_metric, - bgp_redistribute_ipv4_ospf_metric_hidden_cmd, - "redistribute (1-65535) metric (0-4294967295)", - "Redistribute information from another routing protocol\n" - "Open Shortest Path First (OSPFv2)\n" - "Non-main Kernel Routing Table\n" - "Instance ID/Table ID\n" - "Metric for redistributed routes\n" - "Default metric\n") + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_ospf_table = 1; + int idx_number = 2; + int idx_number_2 = 4; + u_int32_t metric; + struct bgp_redist *red; + u_short instance; + int protocol; + + if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) + protocol = ZEBRA_ROUTE_OSPF; + else + protocol = ZEBRA_ROUTE_TABLE; + + instance = strtoul(argv[idx_number]->arg, NULL, 10); + metric = strtoul(argv[idx_number_2]->arg, NULL, 10); + + red = bgp_redist_add(bgp, AFI_IP, protocol, instance); + bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric); + return bgp_redistribute_set(bgp, AFI_IP, protocol, instance); +} + +ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf_metric, + bgp_redistribute_ipv4_ospf_metric_hidden_cmd, + "redistribute (1-65535) metric (0-4294967295)", + "Redistribute information from another routing protocol\n" + "Open Shortest Path First (OSPFv2)\n" + "Non-main Kernel Routing Table\n" + "Instance ID/Table ID\n" + "Metric for redistributed routes\n" + "Default metric\n") DEFUN (bgp_redistribute_ipv4_ospf_rmap_metric, bgp_redistribute_ipv4_ospf_rmap_metric_cmd, @@ -10223,41 +10714,42 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap_metric, "Metric for redistributed routes\n" "Default metric\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_ospf_table = 1; - int idx_number = 2; - int idx_word = 4; - int idx_number_2 = 6; - u_int32_t metric; - struct bgp_redist *red; - u_short instance; - int protocol; - - if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) - protocol = ZEBRA_ROUTE_OSPF; - else - protocol = ZEBRA_ROUTE_TABLE; - - instance = strtoul(argv[idx_number]->arg, NULL, 10); - metric = strtoul(argv[idx_number_2]->arg, NULL, 10); - - red = bgp_redist_add(bgp, AFI_IP, protocol, instance); - bgp_redistribute_rmap_set (red, argv[idx_word]->arg); - bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric); - return bgp_redistribute_set (bgp, AFI_IP, protocol, instance); -} - -ALIAS_HIDDEN (bgp_redistribute_ipv4_ospf_rmap_metric, - bgp_redistribute_ipv4_ospf_rmap_metric_hidden_cmd, - "redistribute (1-65535) route-map WORD metric (0-4294967295)", - "Redistribute information from another routing protocol\n" - "Open Shortest Path First (OSPFv2)\n" - "Non-main Kernel Routing Table\n" - "Instance ID/Table ID\n" - "Route map reference\n" - "Pointer to route-map entries\n" - "Metric for redistributed routes\n" - "Default metric\n") + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_ospf_table = 1; + int idx_number = 2; + int idx_word = 4; + int idx_number_2 = 6; + u_int32_t metric; + struct bgp_redist *red; + u_short instance; + int protocol; + + if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) + protocol = ZEBRA_ROUTE_OSPF; + else + protocol = ZEBRA_ROUTE_TABLE; + + instance = strtoul(argv[idx_number]->arg, NULL, 10); + metric = strtoul(argv[idx_number_2]->arg, NULL, 10); + + red = bgp_redist_add(bgp, AFI_IP, protocol, instance); + bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric); + return bgp_redistribute_set(bgp, AFI_IP, protocol, instance); +} + +ALIAS_HIDDEN( + bgp_redistribute_ipv4_ospf_rmap_metric, + bgp_redistribute_ipv4_ospf_rmap_metric_hidden_cmd, + "redistribute (1-65535) route-map WORD metric (0-4294967295)", + "Redistribute information from another routing protocol\n" + "Open Shortest Path First (OSPFv2)\n" + "Non-main Kernel Routing Table\n" + "Instance ID/Table ID\n" + "Route map reference\n" + "Pointer to route-map entries\n" + "Metric for redistributed routes\n" + "Default metric\n") DEFUN (bgp_redistribute_ipv4_ospf_metric_rmap, bgp_redistribute_ipv4_ospf_metric_rmap_cmd, @@ -10271,41 +10763,42 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric_rmap, "Route map reference\n" "Pointer to route-map entries\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_ospf_table = 1; - int idx_number = 2; - int idx_number_2 = 4; - int idx_word = 6; - u_int32_t metric; - struct bgp_redist *red; - u_short instance; - int protocol; - - if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) - protocol = ZEBRA_ROUTE_OSPF; - else - protocol = ZEBRA_ROUTE_TABLE; - - instance = strtoul(argv[idx_number]->arg, NULL, 10); - metric = strtoul(argv[idx_number_2]->arg, NULL, 10); - - red = bgp_redist_add(bgp, AFI_IP, protocol, instance); - bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric); - bgp_redistribute_rmap_set (red, argv[idx_word]->arg); - return bgp_redistribute_set (bgp, AFI_IP, protocol, instance); -} - -ALIAS_HIDDEN (bgp_redistribute_ipv4_ospf_metric_rmap, - bgp_redistribute_ipv4_ospf_metric_rmap_hidden_cmd, - "redistribute (1-65535) metric (0-4294967295) route-map WORD", - "Redistribute information from another routing protocol\n" - "Open Shortest Path First (OSPFv2)\n" - "Non-main Kernel Routing Table\n" - "Instance ID/Table ID\n" - "Metric for redistributed routes\n" - "Default metric\n" - "Route map reference\n" - "Pointer to route-map entries\n") + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_ospf_table = 1; + int idx_number = 2; + int idx_number_2 = 4; + int idx_word = 6; + u_int32_t metric; + struct bgp_redist *red; + u_short instance; + int protocol; + + if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) + protocol = ZEBRA_ROUTE_OSPF; + else + protocol = ZEBRA_ROUTE_TABLE; + + instance = strtoul(argv[idx_number]->arg, NULL, 10); + metric = strtoul(argv[idx_number_2]->arg, NULL, 10); + + red = bgp_redist_add(bgp, AFI_IP, protocol, instance); + bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric); + bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + return bgp_redistribute_set(bgp, AFI_IP, protocol, instance); +} + +ALIAS_HIDDEN( + bgp_redistribute_ipv4_ospf_metric_rmap, + bgp_redistribute_ipv4_ospf_metric_rmap_hidden_cmd, + "redistribute (1-65535) metric (0-4294967295) route-map WORD", + "Redistribute information from another routing protocol\n" + "Open Shortest Path First (OSPFv2)\n" + "Non-main Kernel Routing Table\n" + "Instance ID/Table ID\n" + "Metric for redistributed routes\n" + "Default metric\n" + "Route map reference\n" + "Pointer to route-map entries\n") DEFUN (no_bgp_redistribute_ipv4_ospf, no_bgp_redistribute_ipv4_ospf_cmd, @@ -10320,33 +10813,33 @@ DEFUN (no_bgp_redistribute_ipv4_ospf, "Route map reference\n" "Pointer to route-map entries\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_ospf_table = 2; - int idx_number = 3; - u_short instance; - int protocol; - - if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) - protocol = ZEBRA_ROUTE_OSPF; - else - protocol = ZEBRA_ROUTE_TABLE; - - instance = strtoul(argv[idx_number]->arg, NULL, 10); - return bgp_redistribute_unset (bgp, AFI_IP, protocol, instance); -} - -ALIAS_HIDDEN (no_bgp_redistribute_ipv4_ospf, - no_bgp_redistribute_ipv4_ospf_hidden_cmd, - "no redistribute (1-65535) [metric (0-4294967295)] [route-map WORD]", - NO_STR - "Redistribute information from another routing protocol\n" - "Open Shortest Path First (OSPFv2)\n" - "Non-main Kernel Routing Table\n" - "Instance ID/Table ID\n" - "Metric for redistributed routes\n" - "Default metric\n" - "Route map reference\n" - "Pointer to route-map entries\n") + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_ospf_table = 2; + int idx_number = 3; + u_short instance; + int protocol; + + if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) + protocol = ZEBRA_ROUTE_OSPF; + else + protocol = ZEBRA_ROUTE_TABLE; + + instance = strtoul(argv[idx_number]->arg, NULL, 10); + return bgp_redistribute_unset(bgp, AFI_IP, protocol, instance); +} + +ALIAS_HIDDEN( + no_bgp_redistribute_ipv4_ospf, no_bgp_redistribute_ipv4_ospf_hidden_cmd, + "no redistribute (1-65535) [metric (0-4294967295)] [route-map WORD]", + NO_STR + "Redistribute information from another routing protocol\n" + "Open Shortest Path First (OSPFv2)\n" + "Non-main Kernel Routing Table\n" + "Instance ID/Table ID\n" + "Metric for redistributed routes\n" + "Default metric\n" + "Route map reference\n" + "Pointer to route-map entries\n") DEFUN (no_bgp_redistribute_ipv4, no_bgp_redistribute_ipv4_cmd, @@ -10359,29 +10852,28 @@ DEFUN (no_bgp_redistribute_ipv4, "Route map reference\n" "Pointer to route-map entries\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_protocol = 2; - int type; - - type = proto_redistnum (AFI_IP, argv[idx_protocol]->text); - if (type < 0) - { - vty_out (vty, "%% Invalid route type\n"); - return CMD_WARNING_CONFIG_FAILED; - } - return bgp_redistribute_unset (bgp, AFI_IP, type, 0); -} - -ALIAS_HIDDEN (no_bgp_redistribute_ipv4, - no_bgp_redistribute_ipv4_hidden_cmd, - "no redistribute " FRR_IP_REDIST_STR_BGPD " [metric (0-4294967295)] [route-map WORD]", - NO_STR - "Redistribute information from another routing protocol\n" - FRR_IP_REDIST_HELP_STR_BGPD - "Metric for redistributed routes\n" - "Default metric\n" - "Route map reference\n" - "Pointer to route-map entries\n") + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_protocol = 2; + int type; + + type = proto_redistnum(AFI_IP, argv[idx_protocol]->text); + if (type < 0) { + vty_out(vty, "%% Invalid route type\n"); + return CMD_WARNING_CONFIG_FAILED; + } + return bgp_redistribute_unset(bgp, AFI_IP, type, 0); +} + +ALIAS_HIDDEN( + no_bgp_redistribute_ipv4, no_bgp_redistribute_ipv4_hidden_cmd, + "no redistribute " FRR_IP_REDIST_STR_BGPD + " [metric (0-4294967295)] [route-map WORD]", + NO_STR + "Redistribute information from another routing protocol\n" FRR_IP_REDIST_HELP_STR_BGPD + "Metric for redistributed routes\n" + "Default metric\n" + "Route map reference\n" + "Pointer to route-map entries\n") DEFUN (bgp_redistribute_ipv6, bgp_redistribute_ipv6_cmd, @@ -10389,19 +10881,18 @@ DEFUN (bgp_redistribute_ipv6, "Redistribute information from another routing protocol\n" FRR_IP6_REDIST_HELP_STR_BGPD) { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_protocol = 1; - int type; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_protocol = 1; + int type; - type = proto_redistnum (AFI_IP6, argv[idx_protocol]->text); - if (type < 0) - { - vty_out (vty, "%% Invalid route type\n"); - return CMD_WARNING_CONFIG_FAILED; - } + type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text); + if (type < 0) { + vty_out(vty, "%% Invalid route type\n"); + return CMD_WARNING_CONFIG_FAILED; + } - bgp_redist_add(bgp, AFI_IP6, type, 0); - return bgp_redistribute_set (bgp, AFI_IP6, type, 0); + bgp_redist_add(bgp, AFI_IP6, type, 0); + return bgp_redistribute_set(bgp, AFI_IP6, type, 0); } DEFUN (bgp_redistribute_ipv6_rmap, @@ -10412,22 +10903,21 @@ DEFUN (bgp_redistribute_ipv6_rmap, "Route map reference\n" "Pointer to route-map entries\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_protocol = 1; - int idx_word = 3; - int type; - struct bgp_redist *red; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_protocol = 1; + int idx_word = 3; + int type; + struct bgp_redist *red; - type = proto_redistnum (AFI_IP6, argv[idx_protocol]->text); - if (type < 0) - { - vty_out (vty, "%% Invalid route type\n"); - return CMD_WARNING_CONFIG_FAILED; - } + type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text); + if (type < 0) { + vty_out(vty, "%% Invalid route type\n"); + return CMD_WARNING_CONFIG_FAILED; + } - red = bgp_redist_add(bgp, AFI_IP6, type, 0); - bgp_redistribute_rmap_set (red, argv[idx_word]->arg); - return bgp_redistribute_set (bgp, AFI_IP6, type, 0); + red = bgp_redist_add(bgp, AFI_IP6, type, 0); + bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + return bgp_redistribute_set(bgp, AFI_IP6, type, 0); } DEFUN (bgp_redistribute_ipv6_metric, @@ -10438,24 +10928,23 @@ DEFUN (bgp_redistribute_ipv6_metric, "Metric for redistributed routes\n" "Default metric\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_protocol = 1; - int idx_number = 3; - int type; - u_int32_t metric; - struct bgp_redist *red; - - type = proto_redistnum (AFI_IP6, argv[idx_protocol]->text); - if (type < 0) - { - vty_out (vty, "%% Invalid route type\n"); - return CMD_WARNING_CONFIG_FAILED; - } - metric = strtoul(argv[idx_number]->arg, NULL, 10); + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_protocol = 1; + int idx_number = 3; + int type; + u_int32_t metric; + struct bgp_redist *red; + + type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text); + if (type < 0) { + vty_out(vty, "%% Invalid route type\n"); + return CMD_WARNING_CONFIG_FAILED; + } + metric = strtoul(argv[idx_number]->arg, NULL, 10); - red = bgp_redist_add(bgp, AFI_IP6, type, 0); - bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric); - return bgp_redistribute_set (bgp, AFI_IP6, type, 0); + red = bgp_redist_add(bgp, AFI_IP6, type, 0); + bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric); + return bgp_redistribute_set(bgp, AFI_IP6, type, 0); } DEFUN (bgp_redistribute_ipv6_rmap_metric, @@ -10468,26 +10957,25 @@ DEFUN (bgp_redistribute_ipv6_rmap_metric, "Metric for redistributed routes\n" "Default metric\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_protocol = 1; - int idx_word = 3; - int idx_number = 5; - int type; - u_int32_t metric; - struct bgp_redist *red; - - type = proto_redistnum (AFI_IP6, argv[idx_protocol]->text); - if (type < 0) - { - vty_out (vty, "%% Invalid route type\n"); - return CMD_WARNING_CONFIG_FAILED; - } - metric = strtoul(argv[idx_number]->arg, NULL, 10); + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_protocol = 1; + int idx_word = 3; + int idx_number = 5; + int type; + u_int32_t metric; + struct bgp_redist *red; + + type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text); + if (type < 0) { + vty_out(vty, "%% Invalid route type\n"); + return CMD_WARNING_CONFIG_FAILED; + } + metric = strtoul(argv[idx_number]->arg, NULL, 10); - red = bgp_redist_add(bgp, AFI_IP6, type, 0); - bgp_redistribute_rmap_set (red, argv[idx_word]->arg); - bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric); - return bgp_redistribute_set (bgp, AFI_IP6, type, 0); + red = bgp_redist_add(bgp, AFI_IP6, type, 0); + bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric); + return bgp_redistribute_set(bgp, AFI_IP6, type, 0); } DEFUN (bgp_redistribute_ipv6_metric_rmap, @@ -10500,26 +10988,25 @@ DEFUN (bgp_redistribute_ipv6_metric_rmap, "Route map reference\n" "Pointer to route-map entries\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_protocol = 1; - int idx_number = 3; - int idx_word = 5; - int type; - u_int32_t metric; - struct bgp_redist *red; - - type = proto_redistnum (AFI_IP6, argv[idx_protocol]->text); - if (type < 0) - { - vty_out (vty, "%% Invalid route type\n"); - return CMD_WARNING_CONFIG_FAILED; - } - metric = strtoul(argv[idx_number]->arg, NULL, 10); + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_protocol = 1; + int idx_number = 3; + int idx_word = 5; + int type; + u_int32_t metric; + struct bgp_redist *red; + + type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text); + if (type < 0) { + vty_out(vty, "%% Invalid route type\n"); + return CMD_WARNING_CONFIG_FAILED; + } + metric = strtoul(argv[idx_number]->arg, NULL, 10); - red = bgp_redist_add(bgp, AFI_IP6, type, 0); - bgp_redistribute_metric_set(bgp, red, AFI_IP6, SAFI_UNICAST, metric); - bgp_redistribute_rmap_set (red, argv[idx_word]->arg); - return bgp_redistribute_set (bgp, AFI_IP6, type, 0); + red = bgp_redist_add(bgp, AFI_IP6, type, 0); + bgp_redistribute_metric_set(bgp, red, AFI_IP6, SAFI_UNICAST, metric); + bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + return bgp_redistribute_set(bgp, AFI_IP6, type, 0); } DEFUN (no_bgp_redistribute_ipv6, @@ -10533,1202 +11020,1248 @@ DEFUN (no_bgp_redistribute_ipv6, "Route map reference\n" "Pointer to route-map entries\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int idx_protocol = 2; - int type; - - type = proto_redistnum (AFI_IP6, argv[idx_protocol]->text); - if (type < 0) - { - vty_out (vty, "%% Invalid route type\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return bgp_redistribute_unset (bgp, AFI_IP6, type, 0); -} - -int -bgp_config_write_redistribute (struct vty *vty, struct bgp *bgp, afi_t afi, - safi_t safi, int *write) -{ - int i; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_protocol = 2; + int type; - /* Unicast redistribution only. */ - if (safi != SAFI_UNICAST) - return 0; + type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text); + if (type < 0) { + vty_out(vty, "%% Invalid route type\n"); + return CMD_WARNING_CONFIG_FAILED; + } - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - /* Redistribute BGP does not make sense. */ - if (i != ZEBRA_ROUTE_BGP) - { - struct list *red_list; - struct listnode *node; - struct bgp_redist *red; - - red_list = bgp->redist[afi][i]; - if (!red_list) - continue; - - for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) - { - /* Display "address-family" when it is not yet diplayed. */ - bgp_config_write_family_header (vty, afi, safi, write); - - /* "redistribute" configuration. */ - vty_out (vty, " redistribute %s", zebra_route_string(i)); - if (red->instance) - vty_out (vty, " %d", red->instance); - if (red->redist_metric_flag) - vty_out (vty, " metric %u", red->redist_metric); - if (red->rmap.name) - vty_out (vty, " route-map %s", red->rmap.name); - vty_out (vty, "\n"); - } - } - } - return *write; + return bgp_redistribute_unset(bgp, AFI_IP6, type, 0); +} + +int bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi, int *write) +{ + int i; + + /* Unicast redistribution only. */ + if (safi != SAFI_UNICAST) + return 0; + + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + /* Redistribute BGP does not make sense. */ + if (i != ZEBRA_ROUTE_BGP) { + struct list *red_list; + struct listnode *node; + struct bgp_redist *red; + + red_list = bgp->redist[afi][i]; + if (!red_list) + continue; + + for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { + /* Display "address-family" when it is not yet + * diplayed. */ + bgp_config_write_family_header(vty, afi, safi, + write); + + /* "redistribute" configuration. */ + vty_out(vty, " redistribute %s", + zebra_route_string(i)); + if (red->instance) + vty_out(vty, " %d", red->instance); + if (red->redist_metric_flag) + vty_out(vty, " metric %u", + red->redist_metric); + if (red->rmap.name) + vty_out(vty, " route-map %s", + red->rmap.name); + vty_out(vty, "\n"); + } + } + } + return *write; } /* BGP node structure. */ -static struct cmd_node bgp_node = -{ - BGP_NODE, - "%s(config-router)# ", - 1, +static struct cmd_node bgp_node = { + BGP_NODE, "%s(config-router)# ", 1, }; -static struct cmd_node bgp_ipv4_unicast_node = -{ - BGP_IPV4_NODE, - "%s(config-router-af)# ", - 1, +static struct cmd_node bgp_ipv4_unicast_node = { + BGP_IPV4_NODE, "%s(config-router-af)# ", 1, }; -static struct cmd_node bgp_ipv4_multicast_node = -{ - BGP_IPV4M_NODE, - "%s(config-router-af)# ", - 1, +static struct cmd_node bgp_ipv4_multicast_node = { + BGP_IPV4M_NODE, "%s(config-router-af)# ", 1, }; -static struct cmd_node bgp_ipv4_labeled_unicast_node = -{ - BGP_IPV4L_NODE, - "%s(config-router-af)# ", - 1, +static struct cmd_node bgp_ipv4_labeled_unicast_node = { + BGP_IPV4L_NODE, "%s(config-router-af)# ", 1, }; -static struct cmd_node bgp_ipv6_unicast_node = -{ - BGP_IPV6_NODE, - "%s(config-router-af)# ", - 1, +static struct cmd_node bgp_ipv6_unicast_node = { + BGP_IPV6_NODE, "%s(config-router-af)# ", 1, }; -static struct cmd_node bgp_ipv6_multicast_node = -{ - BGP_IPV6M_NODE, - "%s(config-router-af)# ", - 1, +static struct cmd_node bgp_ipv6_multicast_node = { + BGP_IPV6M_NODE, "%s(config-router-af)# ", 1, }; -static struct cmd_node bgp_ipv6_labeled_unicast_node = -{ - BGP_IPV6L_NODE, - "%s(config-router-af)# ", - 1, +static struct cmd_node bgp_ipv6_labeled_unicast_node = { + BGP_IPV6L_NODE, "%s(config-router-af)# ", 1, }; -static struct cmd_node bgp_vpnv4_node = -{ - BGP_VPNV4_NODE, - "%s(config-router-af)# ", - 1 -}; +static struct cmd_node bgp_vpnv4_node = {BGP_VPNV4_NODE, + "%s(config-router-af)# ", 1}; -static struct cmd_node bgp_vpnv6_node = -{ - BGP_VPNV6_NODE, - "%s(config-router-af-vpnv6)# ", - 1 -}; +static struct cmd_node bgp_vpnv6_node = {BGP_VPNV6_NODE, + "%s(config-router-af-vpnv6)# ", 1}; -static struct cmd_node bgp_evpn_node = -{ - BGP_EVPN_NODE, - "%s(config-router-evpn)# ", - 1 -}; +static struct cmd_node bgp_evpn_node = {BGP_EVPN_NODE, + "%s(config-router-evpn)# ", 1}; -static struct cmd_node bgp_evpn_vni_node = -{ - BGP_EVPN_VNI_NODE, - "%s(config-router-af-vni)# ", - 1 -}; +static struct cmd_node bgp_evpn_vni_node = {BGP_EVPN_VNI_NODE, + "%s(config-router-af-vni)# ", 1}; -static void community_list_vty (void); +static void community_list_vty(void); -static void -bgp_ac_neighbor (vector comps, struct cmd_token *token) +static void bgp_ac_neighbor(vector comps, struct cmd_token *token) { - struct bgp *bgp; - struct peer *peer; - struct peer_group *group; - struct listnode *lnbgp, *lnpeer; + struct bgp *bgp; + struct peer *peer; + struct peer_group *group; + struct listnode *lnbgp, *lnpeer; - for (ALL_LIST_ELEMENTS_RO (bm->bgp, lnbgp, bgp)) - { - for (ALL_LIST_ELEMENTS_RO (bgp->peer, lnpeer, peer)) - { - /* only provide suggestions on the appropriate input token type, - * they'll otherwise show up multiple times */ - enum cmd_token_type match_type; - char *name = peer->host; + for (ALL_LIST_ELEMENTS_RO(bm->bgp, lnbgp, bgp)) { + for (ALL_LIST_ELEMENTS_RO(bgp->peer, lnpeer, peer)) { + /* only provide suggestions on the appropriate input + * token type, + * they'll otherwise show up multiple times */ + enum cmd_token_type match_type; + char *name = peer->host; - if (peer->conf_if) - { - match_type = VARIABLE_TKN; - name = peer->conf_if; - } - else if (strchr(peer->host, ':')) - match_type = IPV6_TKN; - else - match_type = IPV4_TKN; + if (peer->conf_if) { + match_type = VARIABLE_TKN; + name = peer->conf_if; + } else if (strchr(peer->host, ':')) + match_type = IPV6_TKN; + else + match_type = IPV4_TKN; - if (token->type != match_type) - continue; + if (token->type != match_type) + continue; - vector_set(comps, XSTRDUP(MTYPE_COMPLETION, name)); - } + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, name)); + } - if (token->type == VARIABLE_TKN) - for (ALL_LIST_ELEMENTS_RO (bgp->group, lnpeer, group)) - vector_set(comps, XSTRDUP(MTYPE_COMPLETION, group->name)); - } + if (token->type == VARIABLE_TKN) + for (ALL_LIST_ELEMENTS_RO(bgp->group, lnpeer, group)) + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, + group->name)); + } } static const struct cmd_variable_handler bgp_var_neighbor[] = { - { - .varname = "neighbor", - .completions = bgp_ac_neighbor - }, { - .varname = "neighbors", - .completions = bgp_ac_neighbor - }, { - .completions = NULL - } -}; - -void -bgp_vty_init (void) -{ - cmd_variable_handler_register(bgp_var_neighbor); - - /* Install bgp top node. */ - install_node (&bgp_node, bgp_config_write); - install_node (&bgp_ipv4_unicast_node, NULL); - install_node (&bgp_ipv4_multicast_node, NULL); - install_node (&bgp_ipv4_labeled_unicast_node, NULL); - install_node (&bgp_ipv6_unicast_node, NULL); - install_node (&bgp_ipv6_multicast_node, NULL); - install_node (&bgp_ipv6_labeled_unicast_node, NULL); - install_node (&bgp_vpnv4_node, NULL); - install_node (&bgp_vpnv6_node, NULL); - install_node (&bgp_evpn_node, NULL); - install_node (&bgp_evpn_vni_node, NULL); - - /* Install default VTY commands to new nodes. */ - install_default (BGP_NODE); - install_default (BGP_IPV4_NODE); - install_default (BGP_IPV4M_NODE); - install_default (BGP_IPV4L_NODE); - install_default (BGP_IPV6_NODE); - install_default (BGP_IPV6M_NODE); - install_default (BGP_IPV6L_NODE); - install_default (BGP_VPNV4_NODE); - install_default (BGP_VPNV6_NODE); - install_default (BGP_EVPN_NODE); - install_default (BGP_EVPN_VNI_NODE); - - /* "bgp multiple-instance" commands. */ - install_element (CONFIG_NODE, &bgp_multiple_instance_cmd); - install_element (CONFIG_NODE, &no_bgp_multiple_instance_cmd); - - /* "bgp config-type" commands. */ - install_element (CONFIG_NODE, &bgp_config_type_cmd); - install_element (CONFIG_NODE, &no_bgp_config_type_cmd); - - /* bgp route-map delay-timer commands. */ - install_element (CONFIG_NODE, &bgp_set_route_map_delay_timer_cmd); - install_element (CONFIG_NODE, &no_bgp_set_route_map_delay_timer_cmd); - - /* Dummy commands (Currently not supported) */ - install_element (BGP_NODE, &no_synchronization_cmd); - install_element (BGP_NODE, &no_auto_summary_cmd); - - /* "router bgp" commands. */ - install_element (CONFIG_NODE, &router_bgp_cmd); - - /* "no router bgp" commands. */ - install_element (CONFIG_NODE, &no_router_bgp_cmd); - - /* "bgp router-id" commands. */ - install_element (BGP_NODE, &bgp_router_id_cmd); - install_element (BGP_NODE, &no_bgp_router_id_cmd); - - /* "bgp cluster-id" commands. */ - install_element (BGP_NODE, &bgp_cluster_id_cmd); - install_element (BGP_NODE, &no_bgp_cluster_id_cmd); - - /* "bgp confederation" commands. */ - install_element (BGP_NODE, &bgp_confederation_identifier_cmd); - install_element (BGP_NODE, &no_bgp_confederation_identifier_cmd); - - /* "bgp confederation peers" commands. */ - install_element (BGP_NODE, &bgp_confederation_peers_cmd); - install_element (BGP_NODE, &no_bgp_confederation_peers_cmd); - - /* bgp max-med command */ - install_element (BGP_NODE, &bgp_maxmed_admin_cmd); - install_element (BGP_NODE, &no_bgp_maxmed_admin_cmd); - install_element (BGP_NODE, &bgp_maxmed_admin_medv_cmd); - install_element (BGP_NODE, &bgp_maxmed_onstartup_cmd); - install_element (BGP_NODE, &no_bgp_maxmed_onstartup_cmd); - - /* bgp disable-ebgp-connected-nh-check */ - install_element (BGP_NODE, &bgp_disable_connected_route_check_cmd); - install_element (BGP_NODE, &no_bgp_disable_connected_route_check_cmd); - - /* bgp update-delay command */ - install_element (BGP_NODE, &bgp_update_delay_cmd); - install_element (BGP_NODE, &no_bgp_update_delay_cmd); - install_element (BGP_NODE, &bgp_update_delay_establish_wait_cmd); - - install_element (BGP_NODE, &bgp_wpkt_quanta_cmd); - install_element (BGP_NODE, &no_bgp_wpkt_quanta_cmd); - - install_element (BGP_NODE, &bgp_coalesce_time_cmd); - install_element (BGP_NODE, &no_bgp_coalesce_time_cmd); - - /* "maximum-paths" commands. */ - install_element (BGP_NODE, &bgp_maxpaths_hidden_cmd); - install_element (BGP_NODE, &no_bgp_maxpaths_hidden_cmd); - install_element (BGP_IPV4_NODE, &bgp_maxpaths_cmd); - install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_cmd); - install_element (BGP_IPV6_NODE, &bgp_maxpaths_cmd); - install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_cmd); - install_element (BGP_NODE, &bgp_maxpaths_ibgp_hidden_cmd); - install_element (BGP_NODE, &bgp_maxpaths_ibgp_cluster_hidden_cmd); - install_element (BGP_NODE, &no_bgp_maxpaths_ibgp_hidden_cmd); - install_element (BGP_IPV4_NODE, &bgp_maxpaths_ibgp_cmd); - install_element (BGP_IPV4_NODE, &bgp_maxpaths_ibgp_cluster_cmd); - install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_ibgp_cmd); - install_element (BGP_IPV6_NODE, &bgp_maxpaths_ibgp_cmd); - install_element (BGP_IPV6_NODE, &bgp_maxpaths_ibgp_cluster_cmd); - install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_ibgp_cmd); - - install_element (BGP_IPV6L_NODE, &bgp_maxpaths_cmd); - install_element (BGP_IPV6L_NODE, &no_bgp_maxpaths_cmd); - install_element (BGP_IPV6L_NODE, &bgp_maxpaths_ibgp_cmd); - install_element (BGP_IPV6L_NODE, &bgp_maxpaths_ibgp_cluster_cmd); - install_element (BGP_IPV6L_NODE, &no_bgp_maxpaths_ibgp_cmd); - - /* "timers bgp" commands. */ - install_element (BGP_NODE, &bgp_timers_cmd); - install_element (BGP_NODE, &no_bgp_timers_cmd); - - /* route-map delay-timer commands - per instance for backwards compat. */ - install_element (BGP_NODE, &bgp_set_route_map_delay_timer_cmd); - install_element (BGP_NODE, &no_bgp_set_route_map_delay_timer_cmd); - - /* "bgp client-to-client reflection" commands */ - install_element (BGP_NODE, &no_bgp_client_to_client_reflection_cmd); - install_element (BGP_NODE, &bgp_client_to_client_reflection_cmd); - - /* "bgp always-compare-med" commands */ - install_element (BGP_NODE, &bgp_always_compare_med_cmd); - install_element (BGP_NODE, &no_bgp_always_compare_med_cmd); - - /* "bgp deterministic-med" commands */ - install_element (BGP_NODE, &bgp_deterministic_med_cmd); - install_element (BGP_NODE, &no_bgp_deterministic_med_cmd); - - /* "bgp graceful-restart" commands */ - install_element (BGP_NODE, &bgp_graceful_restart_cmd); - install_element (BGP_NODE, &no_bgp_graceful_restart_cmd); - install_element (BGP_NODE, &bgp_graceful_restart_stalepath_time_cmd); - install_element (BGP_NODE, &no_bgp_graceful_restart_stalepath_time_cmd); - install_element (BGP_NODE, &bgp_graceful_restart_restart_time_cmd); - install_element (BGP_NODE, &no_bgp_graceful_restart_restart_time_cmd); - - install_element (BGP_NODE, &bgp_graceful_restart_preserve_fw_cmd); - install_element (BGP_NODE, &no_bgp_graceful_restart_preserve_fw_cmd); - - /* "bgp fast-external-failover" commands */ - install_element (BGP_NODE, &bgp_fast_external_failover_cmd); - install_element (BGP_NODE, &no_bgp_fast_external_failover_cmd); - - /* "bgp enforce-first-as" commands */ - install_element (BGP_NODE, &bgp_enforce_first_as_cmd); - install_element (BGP_NODE, &no_bgp_enforce_first_as_cmd); - - /* "bgp bestpath compare-routerid" commands */ - install_element (BGP_NODE, &bgp_bestpath_compare_router_id_cmd); - install_element (BGP_NODE, &no_bgp_bestpath_compare_router_id_cmd); - - /* "bgp bestpath as-path ignore" commands */ - install_element (BGP_NODE, &bgp_bestpath_aspath_ignore_cmd); - install_element (BGP_NODE, &no_bgp_bestpath_aspath_ignore_cmd); - - /* "bgp bestpath as-path confed" commands */ - install_element (BGP_NODE, &bgp_bestpath_aspath_confed_cmd); - install_element (BGP_NODE, &no_bgp_bestpath_aspath_confed_cmd); - - /* "bgp bestpath as-path multipath-relax" commands */ - install_element (BGP_NODE, &bgp_bestpath_aspath_multipath_relax_cmd); - install_element (BGP_NODE, &no_bgp_bestpath_aspath_multipath_relax_cmd); - - /* "bgp log-neighbor-changes" commands */ - install_element (BGP_NODE, &bgp_log_neighbor_changes_cmd); - install_element (BGP_NODE, &no_bgp_log_neighbor_changes_cmd); - - /* "bgp bestpath med" commands */ - install_element (BGP_NODE, &bgp_bestpath_med_cmd); - install_element (BGP_NODE, &no_bgp_bestpath_med_cmd); - - /* "no bgp default ipv4-unicast" commands. */ - install_element (BGP_NODE, &no_bgp_default_ipv4_unicast_cmd); - install_element (BGP_NODE, &bgp_default_ipv4_unicast_cmd); - - /* "bgp network import-check" commands. */ - install_element (BGP_NODE, &bgp_network_import_check_cmd); - install_element (BGP_NODE, &bgp_network_import_check_exact_cmd); - install_element (BGP_NODE, &no_bgp_network_import_check_cmd); - - /* "bgp default local-preference" commands. */ - install_element (BGP_NODE, &bgp_default_local_preference_cmd); - install_element (BGP_NODE, &no_bgp_default_local_preference_cmd); - - /* bgp default show-hostname */ - install_element (BGP_NODE, &bgp_default_show_hostname_cmd); - install_element (BGP_NODE, &no_bgp_default_show_hostname_cmd); - - /* "bgp default subgroup-pkt-queue-max" commands. */ - install_element (BGP_NODE, &bgp_default_subgroup_pkt_queue_max_cmd); - install_element (BGP_NODE, &no_bgp_default_subgroup_pkt_queue_max_cmd); - - /* bgp ibgp-allow-policy-mods command */ - install_element (BGP_NODE, &bgp_rr_allow_outbound_policy_cmd); - install_element (BGP_NODE, &no_bgp_rr_allow_outbound_policy_cmd); - - /* "bgp listen limit" commands. */ - install_element (BGP_NODE, &bgp_listen_limit_cmd); - install_element (BGP_NODE, &no_bgp_listen_limit_cmd); - - /* "bgp listen range" commands. */ - install_element (BGP_NODE, &bgp_listen_range_cmd); - install_element (BGP_NODE, &no_bgp_listen_range_cmd); - - /* "neighbor remote-as" commands. */ - install_element (BGP_NODE, &neighbor_remote_as_cmd); - install_element (BGP_NODE, &neighbor_interface_config_cmd); - install_element (BGP_NODE, &neighbor_interface_config_v6only_cmd); - install_element (BGP_NODE, &neighbor_interface_config_remote_as_cmd); - install_element (BGP_NODE, &neighbor_interface_v6only_config_remote_as_cmd); - install_element (BGP_NODE, &no_neighbor_cmd); - install_element (BGP_NODE, &no_neighbor_interface_config_cmd); - - /* "neighbor peer-group" commands. */ - install_element (BGP_NODE, &neighbor_peer_group_cmd); - install_element (BGP_NODE, &no_neighbor_peer_group_cmd); - install_element (BGP_NODE, &no_neighbor_interface_peer_group_remote_as_cmd); - - /* "neighbor local-as" commands. */ - install_element (BGP_NODE, &neighbor_local_as_cmd); - install_element (BGP_NODE, &neighbor_local_as_no_prepend_cmd); - install_element (BGP_NODE, &neighbor_local_as_no_prepend_replace_as_cmd); - install_element (BGP_NODE, &no_neighbor_local_as_cmd); - - /* "neighbor solo" commands. */ - install_element (BGP_NODE, &neighbor_solo_cmd); - install_element (BGP_NODE, &no_neighbor_solo_cmd); - - /* "neighbor password" commands. */ - install_element (BGP_NODE, &neighbor_password_cmd); - install_element (BGP_NODE, &no_neighbor_password_cmd); - - /* "neighbor activate" commands. */ - install_element (BGP_NODE, &neighbor_activate_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_activate_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_activate_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_activate_cmd); - install_element (BGP_IPV6_NODE, &neighbor_activate_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_activate_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_activate_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_activate_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_activate_cmd); - install_element (BGP_EVPN_NODE, &neighbor_activate_cmd); - - /* "no neighbor activate" commands. */ - install_element (BGP_NODE, &no_neighbor_activate_hidden_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_activate_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_activate_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_activate_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_activate_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_activate_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_activate_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_activate_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_activate_cmd); - install_element (BGP_EVPN_NODE, &no_neighbor_activate_cmd); - - /* "neighbor peer-group" set commands. */ - install_element (BGP_NODE, &neighbor_set_peer_group_cmd); - install_element (BGP_IPV4_NODE, &neighbor_set_peer_group_hidden_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_set_peer_group_hidden_cmd); - install_element (BGP_IPV6_NODE, &neighbor_set_peer_group_hidden_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_set_peer_group_hidden_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_set_peer_group_hidden_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_set_peer_group_hidden_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_set_peer_group_hidden_cmd); - - /* "no neighbor peer-group unset" commands. */ - install_element (BGP_NODE, &no_neighbor_set_peer_group_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_set_peer_group_hidden_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_set_peer_group_hidden_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_set_peer_group_hidden_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_set_peer_group_hidden_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_set_peer_group_hidden_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_set_peer_group_hidden_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_set_peer_group_hidden_cmd); - - /* "neighbor softreconfiguration inbound" commands.*/ - install_element (BGP_NODE, &neighbor_soft_reconfiguration_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_soft_reconfiguration_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_soft_reconfiguration_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_soft_reconfiguration_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_soft_reconfiguration_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_soft_reconfiguration_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_soft_reconfiguration_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_soft_reconfiguration_cmd); - install_element (BGP_IPV6_NODE, &neighbor_soft_reconfiguration_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_soft_reconfiguration_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_soft_reconfiguration_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_soft_reconfiguration_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_soft_reconfiguration_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_soft_reconfiguration_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_soft_reconfiguration_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_soft_reconfiguration_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_soft_reconfiguration_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_soft_reconfiguration_cmd); - - /* "neighbor attribute-unchanged" commands. */ - install_element (BGP_NODE, &neighbor_attr_unchanged_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_attr_unchanged_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_attr_unchanged_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_attr_unchanged_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_attr_unchanged_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_attr_unchanged_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_attr_unchanged_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_attr_unchanged_cmd); - install_element (BGP_IPV6_NODE, &neighbor_attr_unchanged_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_attr_unchanged_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_attr_unchanged_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_attr_unchanged_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_attr_unchanged_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_attr_unchanged_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_attr_unchanged_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_attr_unchanged_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_attr_unchanged_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_attr_unchanged_cmd); - - install_element (BGP_EVPN_NODE, &neighbor_attr_unchanged_cmd); - install_element (BGP_EVPN_NODE, &no_neighbor_attr_unchanged_cmd); - - /* "nexthop-local unchanged" commands */ - install_element (BGP_IPV6_NODE, &neighbor_nexthop_local_unchanged_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_nexthop_local_unchanged_cmd); - - /* "neighbor next-hop-self" commands. */ - install_element (BGP_NODE, &neighbor_nexthop_self_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_nexthop_self_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_nexthop_self_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_nexthop_self_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_nexthop_self_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_nexthop_self_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_nexthop_self_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_nexthop_self_cmd); - install_element (BGP_IPV6_NODE, &neighbor_nexthop_self_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_nexthop_self_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_nexthop_self_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_nexthop_self_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_nexthop_self_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_nexthop_self_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_nexthop_self_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_nexthop_self_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_nexthop_self_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_nexthop_self_cmd); - - /* "neighbor next-hop-self force" commands. */ - install_element (BGP_NODE, &neighbor_nexthop_self_force_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_nexthop_self_force_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_nexthop_self_force_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_nexthop_self_force_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_nexthop_self_force_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_nexthop_self_force_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_nexthop_self_force_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_nexthop_self_force_cmd); - install_element (BGP_IPV6_NODE, &neighbor_nexthop_self_force_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_nexthop_self_force_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_nexthop_self_force_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_nexthop_self_force_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_nexthop_self_force_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_nexthop_self_force_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_nexthop_self_force_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_nexthop_self_force_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_nexthop_self_force_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_nexthop_self_force_cmd); - - /* "neighbor as-override" commands. */ - install_element (BGP_NODE, &neighbor_as_override_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_as_override_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_as_override_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_as_override_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_as_override_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_as_override_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_as_override_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_as_override_cmd); - install_element (BGP_IPV6_NODE, &neighbor_as_override_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_as_override_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_as_override_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_as_override_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_as_override_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_as_override_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_as_override_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_as_override_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_as_override_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_as_override_cmd); - - /* "neighbor remove-private-AS" commands. */ - install_element (BGP_NODE, &neighbor_remove_private_as_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_remove_private_as_hidden_cmd); - install_element (BGP_NODE, &neighbor_remove_private_as_all_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_remove_private_as_all_hidden_cmd); - install_element (BGP_NODE, &neighbor_remove_private_as_replace_as_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_remove_private_as_replace_as_hidden_cmd); - install_element (BGP_NODE, &neighbor_remove_private_as_all_replace_as_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_remove_private_as_all_replace_as_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_remove_private_as_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_remove_private_as_cmd); - install_element (BGP_IPV4_NODE, &neighbor_remove_private_as_all_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_remove_private_as_all_cmd); - install_element (BGP_IPV4_NODE, &neighbor_remove_private_as_replace_as_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_remove_private_as_replace_as_cmd); - install_element (BGP_IPV4_NODE, &neighbor_remove_private_as_all_replace_as_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_remove_private_as_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_remove_private_as_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_remove_private_as_all_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_remove_private_as_all_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_remove_private_as_replace_as_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_remove_private_as_replace_as_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_remove_private_as_all_replace_as_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_remove_private_as_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_remove_private_as_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_remove_private_as_all_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_remove_private_as_all_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_remove_private_as_replace_as_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_remove_private_as_replace_as_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_remove_private_as_all_replace_as_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd); - install_element (BGP_IPV6_NODE, &neighbor_remove_private_as_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_remove_private_as_cmd); - install_element (BGP_IPV6_NODE, &neighbor_remove_private_as_all_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_remove_private_as_all_cmd); - install_element (BGP_IPV6_NODE, &neighbor_remove_private_as_replace_as_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_remove_private_as_replace_as_cmd); - install_element (BGP_IPV6_NODE, &neighbor_remove_private_as_all_replace_as_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_remove_private_as_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_remove_private_as_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_remove_private_as_all_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_remove_private_as_all_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_remove_private_as_replace_as_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_remove_private_as_replace_as_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_remove_private_as_all_replace_as_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_remove_private_as_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_remove_private_as_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_remove_private_as_all_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_remove_private_as_all_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_remove_private_as_replace_as_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_remove_private_as_replace_as_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_remove_private_as_all_replace_as_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_remove_private_as_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_remove_private_as_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_remove_private_as_all_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_remove_private_as_all_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_remove_private_as_replace_as_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_remove_private_as_replace_as_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_remove_private_as_all_replace_as_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_remove_private_as_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_remove_private_as_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_remove_private_as_all_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_remove_private_as_all_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_remove_private_as_replace_as_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_remove_private_as_replace_as_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_remove_private_as_all_replace_as_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd); - - /* "neighbor send-community" commands.*/ - install_element (BGP_NODE, &neighbor_send_community_hidden_cmd); - install_element (BGP_NODE, &neighbor_send_community_type_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_send_community_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_send_community_type_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_send_community_cmd); - install_element (BGP_IPV4_NODE, &neighbor_send_community_type_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_send_community_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_send_community_type_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_send_community_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_send_community_type_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_send_community_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_send_community_type_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_send_community_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_send_community_type_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_send_community_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_send_community_type_cmd); - install_element (BGP_IPV6_NODE, &neighbor_send_community_cmd); - install_element (BGP_IPV6_NODE, &neighbor_send_community_type_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_send_community_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_send_community_type_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_send_community_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_send_community_type_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_send_community_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_send_community_type_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_send_community_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_send_community_type_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_send_community_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_send_community_type_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_send_community_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_send_community_type_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_send_community_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_send_community_type_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_send_community_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_send_community_type_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_send_community_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_send_community_type_cmd); - - /* "neighbor route-reflector" commands.*/ - install_element (BGP_NODE, &neighbor_route_reflector_client_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_route_reflector_client_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_route_reflector_client_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_route_reflector_client_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_route_reflector_client_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_route_reflector_client_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_route_reflector_client_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_route_reflector_client_cmd); - install_element (BGP_IPV6_NODE, &neighbor_route_reflector_client_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_route_reflector_client_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_route_reflector_client_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_route_reflector_client_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_route_reflector_client_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_route_reflector_client_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_route_reflector_client_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_route_reflector_client_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_route_reflector_client_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_route_reflector_client_cmd); - install_element (BGP_EVPN_NODE, &neighbor_route_reflector_client_cmd); - install_element (BGP_EVPN_NODE, &no_neighbor_route_reflector_client_cmd); - - /* "neighbor route-server" commands.*/ - install_element (BGP_NODE, &neighbor_route_server_client_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_route_server_client_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_route_server_client_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_route_server_client_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_route_server_client_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_route_server_client_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_route_server_client_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_route_server_client_cmd); - install_element (BGP_IPV6_NODE, &neighbor_route_server_client_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_route_server_client_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_route_server_client_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_route_server_client_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_route_server_client_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_route_server_client_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_route_server_client_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_route_server_client_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_route_server_client_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_route_server_client_cmd); - - /* "neighbor addpath-tx-all-paths" commands.*/ - install_element (BGP_NODE, &neighbor_addpath_tx_all_paths_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_addpath_tx_all_paths_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_addpath_tx_all_paths_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_addpath_tx_all_paths_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_addpath_tx_all_paths_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_addpath_tx_all_paths_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_addpath_tx_all_paths_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_addpath_tx_all_paths_cmd); - install_element (BGP_IPV6_NODE, &neighbor_addpath_tx_all_paths_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_addpath_tx_all_paths_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_addpath_tx_all_paths_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_addpath_tx_all_paths_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_addpath_tx_all_paths_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_addpath_tx_all_paths_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_addpath_tx_all_paths_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_addpath_tx_all_paths_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_addpath_tx_all_paths_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_addpath_tx_all_paths_cmd); - - /* "neighbor addpath-tx-bestpath-per-AS" commands.*/ - install_element (BGP_NODE, &neighbor_addpath_tx_bestpath_per_as_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_addpath_tx_bestpath_per_as_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd); - install_element (BGP_IPV6_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd); - - /* "neighbor passive" commands. */ - install_element (BGP_NODE, &neighbor_passive_cmd); - install_element (BGP_NODE, &no_neighbor_passive_cmd); - - - /* "neighbor shutdown" commands. */ - install_element (BGP_NODE, &neighbor_shutdown_cmd); - install_element (BGP_NODE, &no_neighbor_shutdown_cmd); - install_element (BGP_NODE, &neighbor_shutdown_msg_cmd); - install_element (BGP_NODE, &no_neighbor_shutdown_msg_cmd); - - /* "neighbor capability extended-nexthop" commands.*/ - install_element (BGP_NODE, &neighbor_capability_enhe_cmd); - install_element (BGP_NODE, &no_neighbor_capability_enhe_cmd); - - /* "neighbor capability orf prefix-list" commands.*/ - install_element (BGP_NODE, &neighbor_capability_orf_prefix_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_capability_orf_prefix_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_capability_orf_prefix_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_capability_orf_prefix_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_capability_orf_prefix_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_capability_orf_prefix_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_capability_orf_prefix_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_capability_orf_prefix_cmd); - install_element (BGP_IPV6_NODE, &neighbor_capability_orf_prefix_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_capability_orf_prefix_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_capability_orf_prefix_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_capability_orf_prefix_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_capability_orf_prefix_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_capability_orf_prefix_cmd); - - /* "neighbor capability dynamic" commands.*/ - install_element (BGP_NODE, &neighbor_capability_dynamic_cmd); - install_element (BGP_NODE, &no_neighbor_capability_dynamic_cmd); - - /* "neighbor dont-capability-negotiate" commands. */ - install_element (BGP_NODE, &neighbor_dont_capability_negotiate_cmd); - install_element (BGP_NODE, &no_neighbor_dont_capability_negotiate_cmd); - - /* "neighbor ebgp-multihop" commands. */ - install_element (BGP_NODE, &neighbor_ebgp_multihop_cmd); - install_element (BGP_NODE, &neighbor_ebgp_multihop_ttl_cmd); - install_element (BGP_NODE, &no_neighbor_ebgp_multihop_cmd); - - /* "neighbor disable-connected-check" commands. */ - install_element (BGP_NODE, &neighbor_disable_connected_check_cmd); - install_element (BGP_NODE, &no_neighbor_disable_connected_check_cmd); - - /* "neighbor description" commands. */ - install_element (BGP_NODE, &neighbor_description_cmd); - install_element (BGP_NODE, &no_neighbor_description_cmd); - - /* "neighbor update-source" commands. "*/ - install_element (BGP_NODE, &neighbor_update_source_cmd); - install_element (BGP_NODE, &no_neighbor_update_source_cmd); - - /* "neighbor default-originate" commands. */ - install_element (BGP_NODE, &neighbor_default_originate_hidden_cmd); - install_element (BGP_NODE, &neighbor_default_originate_rmap_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_default_originate_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_default_originate_cmd); - install_element (BGP_IPV4_NODE, &neighbor_default_originate_rmap_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_default_originate_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_default_originate_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_default_originate_rmap_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_default_originate_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_default_originate_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_default_originate_rmap_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_default_originate_cmd); - install_element (BGP_IPV6_NODE, &neighbor_default_originate_cmd); - install_element (BGP_IPV6_NODE, &neighbor_default_originate_rmap_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_default_originate_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_default_originate_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_default_originate_rmap_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_default_originate_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_default_originate_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_default_originate_rmap_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_default_originate_cmd); - - /* "neighbor port" commands. */ - install_element (BGP_NODE, &neighbor_port_cmd); - install_element (BGP_NODE, &no_neighbor_port_cmd); - - /* "neighbor weight" commands. */ - install_element (BGP_NODE, &neighbor_weight_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_weight_hidden_cmd); - - install_element (BGP_IPV4_NODE, &neighbor_weight_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_weight_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_weight_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_weight_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_weight_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_weight_cmd); - install_element (BGP_IPV6_NODE, &neighbor_weight_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_weight_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_weight_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_weight_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_weight_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_weight_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_weight_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_weight_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_weight_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_weight_cmd); - - /* "neighbor override-capability" commands. */ - install_element (BGP_NODE, &neighbor_override_capability_cmd); - install_element (BGP_NODE, &no_neighbor_override_capability_cmd); - - /* "neighbor strict-capability-match" commands. */ - install_element (BGP_NODE, &neighbor_strict_capability_cmd); - install_element (BGP_NODE, &no_neighbor_strict_capability_cmd); - - /* "neighbor timers" commands. */ - install_element (BGP_NODE, &neighbor_timers_cmd); - install_element (BGP_NODE, &no_neighbor_timers_cmd); - - /* "neighbor timers connect" commands. */ - install_element (BGP_NODE, &neighbor_timers_connect_cmd); - install_element (BGP_NODE, &no_neighbor_timers_connect_cmd); - - /* "neighbor advertisement-interval" commands. */ - install_element (BGP_NODE, &neighbor_advertise_interval_cmd); - install_element (BGP_NODE, &no_neighbor_advertise_interval_cmd); - - /* "neighbor interface" commands. */ - install_element (BGP_NODE, &neighbor_interface_cmd); - install_element (BGP_NODE, &no_neighbor_interface_cmd); - - /* "neighbor distribute" commands. */ - install_element (BGP_NODE, &neighbor_distribute_list_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_distribute_list_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_distribute_list_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_distribute_list_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_distribute_list_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_distribute_list_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_distribute_list_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_distribute_list_cmd); - install_element (BGP_IPV6_NODE, &neighbor_distribute_list_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_distribute_list_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_distribute_list_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_distribute_list_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_distribute_list_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_distribute_list_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_distribute_list_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_distribute_list_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_distribute_list_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_distribute_list_cmd); - - /* "neighbor prefix-list" commands. */ - install_element (BGP_NODE, &neighbor_prefix_list_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_prefix_list_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_prefix_list_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_prefix_list_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_prefix_list_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_prefix_list_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_prefix_list_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_prefix_list_cmd); - install_element (BGP_IPV6_NODE, &neighbor_prefix_list_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_prefix_list_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_prefix_list_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_prefix_list_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_prefix_list_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_prefix_list_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_prefix_list_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_prefix_list_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_prefix_list_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_prefix_list_cmd); - - /* "neighbor filter-list" commands. */ - install_element (BGP_NODE, &neighbor_filter_list_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_filter_list_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_filter_list_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_filter_list_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_filter_list_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_filter_list_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_filter_list_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_filter_list_cmd); - install_element (BGP_IPV6_NODE, &neighbor_filter_list_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_filter_list_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_filter_list_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_filter_list_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_filter_list_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_filter_list_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_filter_list_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_filter_list_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_filter_list_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_filter_list_cmd); - - /* "neighbor route-map" commands. */ - install_element (BGP_NODE, &neighbor_route_map_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_route_map_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_route_map_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_route_map_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_route_map_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_route_map_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_route_map_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_route_map_cmd); - install_element (BGP_IPV6_NODE, &neighbor_route_map_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_route_map_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_route_map_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_route_map_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_route_map_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_route_map_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_route_map_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_route_map_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_route_map_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_route_map_cmd); - - /* "neighbor unsuppress-map" commands. */ - install_element (BGP_NODE, &neighbor_unsuppress_map_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_unsuppress_map_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_unsuppress_map_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_unsuppress_map_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_unsuppress_map_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_unsuppress_map_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_unsuppress_map_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_unsuppress_map_cmd); - install_element (BGP_IPV6_NODE, &neighbor_unsuppress_map_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_unsuppress_map_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_unsuppress_map_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_unsuppress_map_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_unsuppress_map_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_unsuppress_map_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_unsuppress_map_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_unsuppress_map_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_unsuppress_map_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_unsuppress_map_cmd); - - /* "neighbor maximum-prefix" commands. */ - install_element (BGP_NODE, &neighbor_maximum_prefix_hidden_cmd); - install_element (BGP_NODE, &neighbor_maximum_prefix_threshold_hidden_cmd); - install_element (BGP_NODE, &neighbor_maximum_prefix_warning_hidden_cmd); - install_element (BGP_NODE, &neighbor_maximum_prefix_threshold_warning_hidden_cmd); - install_element (BGP_NODE, &neighbor_maximum_prefix_restart_hidden_cmd); - install_element (BGP_NODE, &neighbor_maximum_prefix_threshold_restart_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_maximum_prefix_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_maximum_prefix_cmd); - install_element (BGP_IPV4_NODE, &neighbor_maximum_prefix_threshold_cmd); - install_element (BGP_IPV4_NODE, &neighbor_maximum_prefix_warning_cmd); - install_element (BGP_IPV4_NODE, &neighbor_maximum_prefix_threshold_warning_cmd); - install_element (BGP_IPV4_NODE, &neighbor_maximum_prefix_restart_cmd); - install_element (BGP_IPV4_NODE, &neighbor_maximum_prefix_threshold_restart_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_maximum_prefix_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_maximum_prefix_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_maximum_prefix_threshold_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_maximum_prefix_warning_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_maximum_prefix_threshold_warning_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_maximum_prefix_restart_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_maximum_prefix_threshold_restart_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_maximum_prefix_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_maximum_prefix_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_maximum_prefix_threshold_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_maximum_prefix_warning_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_maximum_prefix_threshold_warning_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_maximum_prefix_restart_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_maximum_prefix_threshold_restart_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_maximum_prefix_cmd); - install_element (BGP_IPV6_NODE, &neighbor_maximum_prefix_cmd); - install_element (BGP_IPV6_NODE, &neighbor_maximum_prefix_threshold_cmd); - install_element (BGP_IPV6_NODE, &neighbor_maximum_prefix_warning_cmd); - install_element (BGP_IPV6_NODE, &neighbor_maximum_prefix_threshold_warning_cmd); - install_element (BGP_IPV6_NODE, &neighbor_maximum_prefix_restart_cmd); - install_element (BGP_IPV6_NODE, &neighbor_maximum_prefix_threshold_restart_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_maximum_prefix_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_maximum_prefix_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_maximum_prefix_threshold_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_maximum_prefix_warning_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_maximum_prefix_threshold_warning_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_maximum_prefix_restart_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_maximum_prefix_threshold_restart_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_maximum_prefix_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_maximum_prefix_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_maximum_prefix_threshold_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_maximum_prefix_warning_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_maximum_prefix_threshold_warning_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_maximum_prefix_restart_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_maximum_prefix_threshold_restart_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_maximum_prefix_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_maximum_prefix_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_maximum_prefix_threshold_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_maximum_prefix_warning_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_maximum_prefix_threshold_warning_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_maximum_prefix_restart_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_maximum_prefix_threshold_restart_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_maximum_prefix_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_maximum_prefix_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_maximum_prefix_threshold_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_maximum_prefix_warning_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_maximum_prefix_threshold_warning_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_maximum_prefix_restart_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_maximum_prefix_threshold_restart_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_maximum_prefix_cmd); - - /* "neighbor allowas-in" */ - install_element (BGP_NODE, &neighbor_allowas_in_hidden_cmd); - install_element (BGP_NODE, &no_neighbor_allowas_in_hidden_cmd); - install_element (BGP_IPV4_NODE, &neighbor_allowas_in_cmd); - install_element (BGP_IPV4_NODE, &no_neighbor_allowas_in_cmd); - install_element (BGP_IPV4M_NODE, &neighbor_allowas_in_cmd); - install_element (BGP_IPV4M_NODE, &no_neighbor_allowas_in_cmd); - install_element (BGP_IPV4L_NODE, &neighbor_allowas_in_cmd); - install_element (BGP_IPV4L_NODE, &no_neighbor_allowas_in_cmd); - install_element (BGP_IPV6_NODE, &neighbor_allowas_in_cmd); - install_element (BGP_IPV6_NODE, &no_neighbor_allowas_in_cmd); - install_element (BGP_IPV6M_NODE, &neighbor_allowas_in_cmd); - install_element (BGP_IPV6M_NODE, &no_neighbor_allowas_in_cmd); - install_element (BGP_IPV6L_NODE, &neighbor_allowas_in_cmd); - install_element (BGP_IPV6L_NODE, &no_neighbor_allowas_in_cmd); - install_element (BGP_VPNV4_NODE, &neighbor_allowas_in_cmd); - install_element (BGP_VPNV4_NODE, &no_neighbor_allowas_in_cmd); - install_element (BGP_VPNV6_NODE, &neighbor_allowas_in_cmd); - install_element (BGP_VPNV6_NODE, &no_neighbor_allowas_in_cmd); - install_element (BGP_EVPN_NODE, &neighbor_allowas_in_cmd); - install_element (BGP_EVPN_NODE, &no_neighbor_allowas_in_cmd); - - /* address-family commands. */ - install_element (BGP_NODE, &address_family_ipv4_safi_cmd); - install_element (BGP_NODE, &address_family_ipv6_safi_cmd); + {.varname = "neighbor", .completions = bgp_ac_neighbor}, + {.varname = "neighbors", .completions = bgp_ac_neighbor}, + {.completions = NULL}}; + +void bgp_vty_init(void) +{ + cmd_variable_handler_register(bgp_var_neighbor); + + /* Install bgp top node. */ + install_node(&bgp_node, bgp_config_write); + install_node(&bgp_ipv4_unicast_node, NULL); + install_node(&bgp_ipv4_multicast_node, NULL); + install_node(&bgp_ipv4_labeled_unicast_node, NULL); + install_node(&bgp_ipv6_unicast_node, NULL); + install_node(&bgp_ipv6_multicast_node, NULL); + install_node(&bgp_ipv6_labeled_unicast_node, NULL); + install_node(&bgp_vpnv4_node, NULL); + install_node(&bgp_vpnv6_node, NULL); + install_node(&bgp_evpn_node, NULL); + install_node(&bgp_evpn_vni_node, NULL); + + /* Install default VTY commands to new nodes. */ + install_default(BGP_NODE); + install_default(BGP_IPV4_NODE); + install_default(BGP_IPV4M_NODE); + install_default(BGP_IPV4L_NODE); + install_default(BGP_IPV6_NODE); + install_default(BGP_IPV6M_NODE); + install_default(BGP_IPV6L_NODE); + install_default(BGP_VPNV4_NODE); + install_default(BGP_VPNV6_NODE); + install_default(BGP_EVPN_NODE); + install_default(BGP_EVPN_VNI_NODE); + + /* "bgp multiple-instance" commands. */ + install_element(CONFIG_NODE, &bgp_multiple_instance_cmd); + install_element(CONFIG_NODE, &no_bgp_multiple_instance_cmd); + + /* "bgp config-type" commands. */ + install_element(CONFIG_NODE, &bgp_config_type_cmd); + install_element(CONFIG_NODE, &no_bgp_config_type_cmd); + + /* bgp route-map delay-timer commands. */ + install_element(CONFIG_NODE, &bgp_set_route_map_delay_timer_cmd); + install_element(CONFIG_NODE, &no_bgp_set_route_map_delay_timer_cmd); + + /* Dummy commands (Currently not supported) */ + install_element(BGP_NODE, &no_synchronization_cmd); + install_element(BGP_NODE, &no_auto_summary_cmd); + + /* "router bgp" commands. */ + install_element(CONFIG_NODE, &router_bgp_cmd); + + /* "no router bgp" commands. */ + install_element(CONFIG_NODE, &no_router_bgp_cmd); + + /* "bgp router-id" commands. */ + install_element(BGP_NODE, &bgp_router_id_cmd); + install_element(BGP_NODE, &no_bgp_router_id_cmd); + + /* "bgp cluster-id" commands. */ + install_element(BGP_NODE, &bgp_cluster_id_cmd); + install_element(BGP_NODE, &no_bgp_cluster_id_cmd); + + /* "bgp confederation" commands. */ + install_element(BGP_NODE, &bgp_confederation_identifier_cmd); + install_element(BGP_NODE, &no_bgp_confederation_identifier_cmd); + + /* "bgp confederation peers" commands. */ + install_element(BGP_NODE, &bgp_confederation_peers_cmd); + install_element(BGP_NODE, &no_bgp_confederation_peers_cmd); + + /* bgp max-med command */ + install_element(BGP_NODE, &bgp_maxmed_admin_cmd); + install_element(BGP_NODE, &no_bgp_maxmed_admin_cmd); + install_element(BGP_NODE, &bgp_maxmed_admin_medv_cmd); + install_element(BGP_NODE, &bgp_maxmed_onstartup_cmd); + install_element(BGP_NODE, &no_bgp_maxmed_onstartup_cmd); + + /* bgp disable-ebgp-connected-nh-check */ + install_element(BGP_NODE, &bgp_disable_connected_route_check_cmd); + install_element(BGP_NODE, &no_bgp_disable_connected_route_check_cmd); + + /* bgp update-delay command */ + install_element(BGP_NODE, &bgp_update_delay_cmd); + install_element(BGP_NODE, &no_bgp_update_delay_cmd); + install_element(BGP_NODE, &bgp_update_delay_establish_wait_cmd); + + install_element(BGP_NODE, &bgp_wpkt_quanta_cmd); + install_element(BGP_NODE, &no_bgp_wpkt_quanta_cmd); + + install_element(BGP_NODE, &bgp_coalesce_time_cmd); + install_element(BGP_NODE, &no_bgp_coalesce_time_cmd); + + /* "maximum-paths" commands. */ + install_element(BGP_NODE, &bgp_maxpaths_hidden_cmd); + install_element(BGP_NODE, &no_bgp_maxpaths_hidden_cmd); + install_element(BGP_IPV4_NODE, &bgp_maxpaths_cmd); + install_element(BGP_IPV4_NODE, &no_bgp_maxpaths_cmd); + install_element(BGP_IPV6_NODE, &bgp_maxpaths_cmd); + install_element(BGP_IPV6_NODE, &no_bgp_maxpaths_cmd); + install_element(BGP_NODE, &bgp_maxpaths_ibgp_hidden_cmd); + install_element(BGP_NODE, &bgp_maxpaths_ibgp_cluster_hidden_cmd); + install_element(BGP_NODE, &no_bgp_maxpaths_ibgp_hidden_cmd); + install_element(BGP_IPV4_NODE, &bgp_maxpaths_ibgp_cmd); + install_element(BGP_IPV4_NODE, &bgp_maxpaths_ibgp_cluster_cmd); + install_element(BGP_IPV4_NODE, &no_bgp_maxpaths_ibgp_cmd); + install_element(BGP_IPV6_NODE, &bgp_maxpaths_ibgp_cmd); + install_element(BGP_IPV6_NODE, &bgp_maxpaths_ibgp_cluster_cmd); + install_element(BGP_IPV6_NODE, &no_bgp_maxpaths_ibgp_cmd); + + install_element(BGP_IPV6L_NODE, &bgp_maxpaths_cmd); + install_element(BGP_IPV6L_NODE, &no_bgp_maxpaths_cmd); + install_element(BGP_IPV6L_NODE, &bgp_maxpaths_ibgp_cmd); + install_element(BGP_IPV6L_NODE, &bgp_maxpaths_ibgp_cluster_cmd); + install_element(BGP_IPV6L_NODE, &no_bgp_maxpaths_ibgp_cmd); + + /* "timers bgp" commands. */ + install_element(BGP_NODE, &bgp_timers_cmd); + install_element(BGP_NODE, &no_bgp_timers_cmd); + + /* route-map delay-timer commands - per instance for backwards compat. + */ + install_element(BGP_NODE, &bgp_set_route_map_delay_timer_cmd); + install_element(BGP_NODE, &no_bgp_set_route_map_delay_timer_cmd); + + /* "bgp client-to-client reflection" commands */ + install_element(BGP_NODE, &no_bgp_client_to_client_reflection_cmd); + install_element(BGP_NODE, &bgp_client_to_client_reflection_cmd); + + /* "bgp always-compare-med" commands */ + install_element(BGP_NODE, &bgp_always_compare_med_cmd); + install_element(BGP_NODE, &no_bgp_always_compare_med_cmd); + + /* "bgp deterministic-med" commands */ + install_element(BGP_NODE, &bgp_deterministic_med_cmd); + install_element(BGP_NODE, &no_bgp_deterministic_med_cmd); + + /* "bgp graceful-restart" commands */ + install_element(BGP_NODE, &bgp_graceful_restart_cmd); + install_element(BGP_NODE, &no_bgp_graceful_restart_cmd); + install_element(BGP_NODE, &bgp_graceful_restart_stalepath_time_cmd); + install_element(BGP_NODE, &no_bgp_graceful_restart_stalepath_time_cmd); + install_element(BGP_NODE, &bgp_graceful_restart_restart_time_cmd); + install_element(BGP_NODE, &no_bgp_graceful_restart_restart_time_cmd); + + install_element(BGP_NODE, &bgp_graceful_restart_preserve_fw_cmd); + install_element(BGP_NODE, &no_bgp_graceful_restart_preserve_fw_cmd); + + /* "bgp fast-external-failover" commands */ + install_element(BGP_NODE, &bgp_fast_external_failover_cmd); + install_element(BGP_NODE, &no_bgp_fast_external_failover_cmd); + + /* "bgp enforce-first-as" commands */ + install_element(BGP_NODE, &bgp_enforce_first_as_cmd); + install_element(BGP_NODE, &no_bgp_enforce_first_as_cmd); + + /* "bgp bestpath compare-routerid" commands */ + install_element(BGP_NODE, &bgp_bestpath_compare_router_id_cmd); + install_element(BGP_NODE, &no_bgp_bestpath_compare_router_id_cmd); + + /* "bgp bestpath as-path ignore" commands */ + install_element(BGP_NODE, &bgp_bestpath_aspath_ignore_cmd); + install_element(BGP_NODE, &no_bgp_bestpath_aspath_ignore_cmd); + + /* "bgp bestpath as-path confed" commands */ + install_element(BGP_NODE, &bgp_bestpath_aspath_confed_cmd); + install_element(BGP_NODE, &no_bgp_bestpath_aspath_confed_cmd); + + /* "bgp bestpath as-path multipath-relax" commands */ + install_element(BGP_NODE, &bgp_bestpath_aspath_multipath_relax_cmd); + install_element(BGP_NODE, &no_bgp_bestpath_aspath_multipath_relax_cmd); + + /* "bgp log-neighbor-changes" commands */ + install_element(BGP_NODE, &bgp_log_neighbor_changes_cmd); + install_element(BGP_NODE, &no_bgp_log_neighbor_changes_cmd); + + /* "bgp bestpath med" commands */ + install_element(BGP_NODE, &bgp_bestpath_med_cmd); + install_element(BGP_NODE, &no_bgp_bestpath_med_cmd); + + /* "no bgp default ipv4-unicast" commands. */ + install_element(BGP_NODE, &no_bgp_default_ipv4_unicast_cmd); + install_element(BGP_NODE, &bgp_default_ipv4_unicast_cmd); + + /* "bgp network import-check" commands. */ + install_element(BGP_NODE, &bgp_network_import_check_cmd); + install_element(BGP_NODE, &bgp_network_import_check_exact_cmd); + install_element(BGP_NODE, &no_bgp_network_import_check_cmd); + + /* "bgp default local-preference" commands. */ + install_element(BGP_NODE, &bgp_default_local_preference_cmd); + install_element(BGP_NODE, &no_bgp_default_local_preference_cmd); + + /* bgp default show-hostname */ + install_element(BGP_NODE, &bgp_default_show_hostname_cmd); + install_element(BGP_NODE, &no_bgp_default_show_hostname_cmd); + + /* "bgp default subgroup-pkt-queue-max" commands. */ + install_element(BGP_NODE, &bgp_default_subgroup_pkt_queue_max_cmd); + install_element(BGP_NODE, &no_bgp_default_subgroup_pkt_queue_max_cmd); + + /* bgp ibgp-allow-policy-mods command */ + install_element(BGP_NODE, &bgp_rr_allow_outbound_policy_cmd); + install_element(BGP_NODE, &no_bgp_rr_allow_outbound_policy_cmd); + + /* "bgp listen limit" commands. */ + install_element(BGP_NODE, &bgp_listen_limit_cmd); + install_element(BGP_NODE, &no_bgp_listen_limit_cmd); + + /* "bgp listen range" commands. */ + install_element(BGP_NODE, &bgp_listen_range_cmd); + install_element(BGP_NODE, &no_bgp_listen_range_cmd); + + /* "neighbor remote-as" commands. */ + install_element(BGP_NODE, &neighbor_remote_as_cmd); + install_element(BGP_NODE, &neighbor_interface_config_cmd); + install_element(BGP_NODE, &neighbor_interface_config_v6only_cmd); + install_element(BGP_NODE, &neighbor_interface_config_remote_as_cmd); + install_element(BGP_NODE, + &neighbor_interface_v6only_config_remote_as_cmd); + install_element(BGP_NODE, &no_neighbor_cmd); + install_element(BGP_NODE, &no_neighbor_interface_config_cmd); + + /* "neighbor peer-group" commands. */ + install_element(BGP_NODE, &neighbor_peer_group_cmd); + install_element(BGP_NODE, &no_neighbor_peer_group_cmd); + install_element(BGP_NODE, + &no_neighbor_interface_peer_group_remote_as_cmd); + + /* "neighbor local-as" commands. */ + install_element(BGP_NODE, &neighbor_local_as_cmd); + install_element(BGP_NODE, &neighbor_local_as_no_prepend_cmd); + install_element(BGP_NODE, &neighbor_local_as_no_prepend_replace_as_cmd); + install_element(BGP_NODE, &no_neighbor_local_as_cmd); + + /* "neighbor solo" commands. */ + install_element(BGP_NODE, &neighbor_solo_cmd); + install_element(BGP_NODE, &no_neighbor_solo_cmd); + + /* "neighbor password" commands. */ + install_element(BGP_NODE, &neighbor_password_cmd); + install_element(BGP_NODE, &no_neighbor_password_cmd); + + /* "neighbor activate" commands. */ + install_element(BGP_NODE, &neighbor_activate_hidden_cmd); + install_element(BGP_IPV4_NODE, &neighbor_activate_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_activate_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_activate_cmd); + install_element(BGP_IPV6_NODE, &neighbor_activate_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_activate_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_activate_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_activate_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_activate_cmd); + install_element(BGP_EVPN_NODE, &neighbor_activate_cmd); + + /* "no neighbor activate" commands. */ + install_element(BGP_NODE, &no_neighbor_activate_hidden_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_activate_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_activate_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_activate_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_activate_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_activate_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_activate_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_activate_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_activate_cmd); + install_element(BGP_EVPN_NODE, &no_neighbor_activate_cmd); + + /* "neighbor peer-group" set commands. */ + install_element(BGP_NODE, &neighbor_set_peer_group_cmd); + install_element(BGP_IPV4_NODE, &neighbor_set_peer_group_hidden_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_set_peer_group_hidden_cmd); + install_element(BGP_IPV6_NODE, &neighbor_set_peer_group_hidden_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_set_peer_group_hidden_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_set_peer_group_hidden_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_set_peer_group_hidden_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_set_peer_group_hidden_cmd); + + /* "no neighbor peer-group unset" commands. */ + install_element(BGP_NODE, &no_neighbor_set_peer_group_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_set_peer_group_hidden_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_set_peer_group_hidden_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_set_peer_group_hidden_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_set_peer_group_hidden_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_set_peer_group_hidden_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_set_peer_group_hidden_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_set_peer_group_hidden_cmd); + + /* "neighbor softreconfiguration inbound" commands.*/ + install_element(BGP_NODE, &neighbor_soft_reconfiguration_hidden_cmd); + install_element(BGP_NODE, &no_neighbor_soft_reconfiguration_hidden_cmd); + install_element(BGP_IPV4_NODE, &neighbor_soft_reconfiguration_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_soft_reconfiguration_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_soft_reconfiguration_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_soft_reconfiguration_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_soft_reconfiguration_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_soft_reconfiguration_cmd); + install_element(BGP_IPV6_NODE, &neighbor_soft_reconfiguration_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_soft_reconfiguration_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_soft_reconfiguration_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_soft_reconfiguration_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_soft_reconfiguration_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_soft_reconfiguration_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_soft_reconfiguration_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_soft_reconfiguration_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_soft_reconfiguration_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_soft_reconfiguration_cmd); + + /* "neighbor attribute-unchanged" commands. */ + install_element(BGP_NODE, &neighbor_attr_unchanged_hidden_cmd); + install_element(BGP_NODE, &no_neighbor_attr_unchanged_hidden_cmd); + install_element(BGP_IPV4_NODE, &neighbor_attr_unchanged_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_attr_unchanged_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_attr_unchanged_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_attr_unchanged_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_attr_unchanged_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_attr_unchanged_cmd); + install_element(BGP_IPV6_NODE, &neighbor_attr_unchanged_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_attr_unchanged_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_attr_unchanged_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_attr_unchanged_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_attr_unchanged_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_attr_unchanged_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_attr_unchanged_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_attr_unchanged_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_attr_unchanged_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_attr_unchanged_cmd); + + install_element(BGP_EVPN_NODE, &neighbor_attr_unchanged_cmd); + install_element(BGP_EVPN_NODE, &no_neighbor_attr_unchanged_cmd); + + /* "nexthop-local unchanged" commands */ + install_element(BGP_IPV6_NODE, &neighbor_nexthop_local_unchanged_cmd); + install_element(BGP_IPV6_NODE, + &no_neighbor_nexthop_local_unchanged_cmd); + + /* "neighbor next-hop-self" commands. */ + install_element(BGP_NODE, &neighbor_nexthop_self_hidden_cmd); + install_element(BGP_NODE, &no_neighbor_nexthop_self_hidden_cmd); + install_element(BGP_IPV4_NODE, &neighbor_nexthop_self_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_nexthop_self_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_nexthop_self_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_nexthop_self_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_nexthop_self_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_nexthop_self_cmd); + install_element(BGP_IPV6_NODE, &neighbor_nexthop_self_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_nexthop_self_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_nexthop_self_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_nexthop_self_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_nexthop_self_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_nexthop_self_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_nexthop_self_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_nexthop_self_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_nexthop_self_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_nexthop_self_cmd); + + /* "neighbor next-hop-self force" commands. */ + install_element(BGP_NODE, &neighbor_nexthop_self_force_hidden_cmd); + install_element(BGP_NODE, &no_neighbor_nexthop_self_force_hidden_cmd); + install_element(BGP_IPV4_NODE, &neighbor_nexthop_self_force_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_nexthop_self_force_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_nexthop_self_force_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_nexthop_self_force_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_nexthop_self_force_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_nexthop_self_force_cmd); + install_element(BGP_IPV6_NODE, &neighbor_nexthop_self_force_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_nexthop_self_force_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_nexthop_self_force_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_nexthop_self_force_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_nexthop_self_force_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_nexthop_self_force_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_nexthop_self_force_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_nexthop_self_force_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_nexthop_self_force_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_nexthop_self_force_cmd); + + /* "neighbor as-override" commands. */ + install_element(BGP_NODE, &neighbor_as_override_hidden_cmd); + install_element(BGP_NODE, &no_neighbor_as_override_hidden_cmd); + install_element(BGP_IPV4_NODE, &neighbor_as_override_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_as_override_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_as_override_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_as_override_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_as_override_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_as_override_cmd); + install_element(BGP_IPV6_NODE, &neighbor_as_override_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_as_override_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_as_override_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_as_override_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_as_override_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_as_override_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_as_override_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_as_override_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_as_override_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_as_override_cmd); + + /* "neighbor remove-private-AS" commands. */ + install_element(BGP_NODE, &neighbor_remove_private_as_hidden_cmd); + install_element(BGP_NODE, &no_neighbor_remove_private_as_hidden_cmd); + install_element(BGP_NODE, &neighbor_remove_private_as_all_hidden_cmd); + install_element(BGP_NODE, + &no_neighbor_remove_private_as_all_hidden_cmd); + install_element(BGP_NODE, + &neighbor_remove_private_as_replace_as_hidden_cmd); + install_element(BGP_NODE, + &no_neighbor_remove_private_as_replace_as_hidden_cmd); + install_element(BGP_NODE, + &neighbor_remove_private_as_all_replace_as_hidden_cmd); + install_element( + BGP_NODE, + &no_neighbor_remove_private_as_all_replace_as_hidden_cmd); + install_element(BGP_IPV4_NODE, &neighbor_remove_private_as_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_remove_private_as_cmd); + install_element(BGP_IPV4_NODE, &neighbor_remove_private_as_all_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_remove_private_as_all_cmd); + install_element(BGP_IPV4_NODE, + &neighbor_remove_private_as_replace_as_cmd); + install_element(BGP_IPV4_NODE, + &no_neighbor_remove_private_as_replace_as_cmd); + install_element(BGP_IPV4_NODE, + &neighbor_remove_private_as_all_replace_as_cmd); + install_element(BGP_IPV4_NODE, + &no_neighbor_remove_private_as_all_replace_as_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_remove_private_as_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_remove_private_as_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_remove_private_as_all_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_remove_private_as_all_cmd); + install_element(BGP_IPV4M_NODE, + &neighbor_remove_private_as_replace_as_cmd); + install_element(BGP_IPV4M_NODE, + &no_neighbor_remove_private_as_replace_as_cmd); + install_element(BGP_IPV4M_NODE, + &neighbor_remove_private_as_all_replace_as_cmd); + install_element(BGP_IPV4M_NODE, + &no_neighbor_remove_private_as_all_replace_as_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_remove_private_as_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_remove_private_as_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_remove_private_as_all_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_remove_private_as_all_cmd); + install_element(BGP_IPV4L_NODE, + &neighbor_remove_private_as_replace_as_cmd); + install_element(BGP_IPV4L_NODE, + &no_neighbor_remove_private_as_replace_as_cmd); + install_element(BGP_IPV4L_NODE, + &neighbor_remove_private_as_all_replace_as_cmd); + install_element(BGP_IPV4L_NODE, + &no_neighbor_remove_private_as_all_replace_as_cmd); + install_element(BGP_IPV6_NODE, &neighbor_remove_private_as_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_remove_private_as_cmd); + install_element(BGP_IPV6_NODE, &neighbor_remove_private_as_all_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_remove_private_as_all_cmd); + install_element(BGP_IPV6_NODE, + &neighbor_remove_private_as_replace_as_cmd); + install_element(BGP_IPV6_NODE, + &no_neighbor_remove_private_as_replace_as_cmd); + install_element(BGP_IPV6_NODE, + &neighbor_remove_private_as_all_replace_as_cmd); + install_element(BGP_IPV6_NODE, + &no_neighbor_remove_private_as_all_replace_as_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_remove_private_as_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_remove_private_as_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_remove_private_as_all_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_remove_private_as_all_cmd); + install_element(BGP_IPV6M_NODE, + &neighbor_remove_private_as_replace_as_cmd); + install_element(BGP_IPV6M_NODE, + &no_neighbor_remove_private_as_replace_as_cmd); + install_element(BGP_IPV6M_NODE, + &neighbor_remove_private_as_all_replace_as_cmd); + install_element(BGP_IPV6M_NODE, + &no_neighbor_remove_private_as_all_replace_as_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_remove_private_as_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_remove_private_as_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_remove_private_as_all_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_remove_private_as_all_cmd); + install_element(BGP_IPV6L_NODE, + &neighbor_remove_private_as_replace_as_cmd); + install_element(BGP_IPV6L_NODE, + &no_neighbor_remove_private_as_replace_as_cmd); + install_element(BGP_IPV6L_NODE, + &neighbor_remove_private_as_all_replace_as_cmd); + install_element(BGP_IPV6L_NODE, + &no_neighbor_remove_private_as_all_replace_as_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_remove_private_as_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_remove_private_as_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_remove_private_as_all_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_remove_private_as_all_cmd); + install_element(BGP_VPNV4_NODE, + &neighbor_remove_private_as_replace_as_cmd); + install_element(BGP_VPNV4_NODE, + &no_neighbor_remove_private_as_replace_as_cmd); + install_element(BGP_VPNV4_NODE, + &neighbor_remove_private_as_all_replace_as_cmd); + install_element(BGP_VPNV4_NODE, + &no_neighbor_remove_private_as_all_replace_as_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_remove_private_as_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_remove_private_as_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_remove_private_as_all_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_remove_private_as_all_cmd); + install_element(BGP_VPNV6_NODE, + &neighbor_remove_private_as_replace_as_cmd); + install_element(BGP_VPNV6_NODE, + &no_neighbor_remove_private_as_replace_as_cmd); + install_element(BGP_VPNV6_NODE, + &neighbor_remove_private_as_all_replace_as_cmd); + install_element(BGP_VPNV6_NODE, + &no_neighbor_remove_private_as_all_replace_as_cmd); + + /* "neighbor send-community" commands.*/ + install_element(BGP_NODE, &neighbor_send_community_hidden_cmd); + install_element(BGP_NODE, &neighbor_send_community_type_hidden_cmd); + install_element(BGP_NODE, &no_neighbor_send_community_hidden_cmd); + install_element(BGP_NODE, &no_neighbor_send_community_type_hidden_cmd); + install_element(BGP_IPV4_NODE, &neighbor_send_community_cmd); + install_element(BGP_IPV4_NODE, &neighbor_send_community_type_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_send_community_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_send_community_type_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_send_community_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_send_community_type_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_send_community_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_send_community_type_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_send_community_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_send_community_type_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_send_community_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_send_community_type_cmd); + install_element(BGP_IPV6_NODE, &neighbor_send_community_cmd); + install_element(BGP_IPV6_NODE, &neighbor_send_community_type_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_send_community_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_send_community_type_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_send_community_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_send_community_type_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_send_community_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_send_community_type_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_send_community_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_send_community_type_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_send_community_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_send_community_type_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_send_community_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_send_community_type_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_send_community_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_send_community_type_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_send_community_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_send_community_type_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_send_community_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_send_community_type_cmd); + + /* "neighbor route-reflector" commands.*/ + install_element(BGP_NODE, &neighbor_route_reflector_client_hidden_cmd); + install_element(BGP_NODE, + &no_neighbor_route_reflector_client_hidden_cmd); + install_element(BGP_IPV4_NODE, &neighbor_route_reflector_client_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_route_reflector_client_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_route_reflector_client_cmd); + install_element(BGP_IPV4M_NODE, + &no_neighbor_route_reflector_client_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_route_reflector_client_cmd); + install_element(BGP_IPV4L_NODE, + &no_neighbor_route_reflector_client_cmd); + install_element(BGP_IPV6_NODE, &neighbor_route_reflector_client_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_route_reflector_client_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_route_reflector_client_cmd); + install_element(BGP_IPV6M_NODE, + &no_neighbor_route_reflector_client_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_route_reflector_client_cmd); + install_element(BGP_IPV6L_NODE, + &no_neighbor_route_reflector_client_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_route_reflector_client_cmd); + install_element(BGP_VPNV4_NODE, + &no_neighbor_route_reflector_client_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_route_reflector_client_cmd); + install_element(BGP_VPNV6_NODE, + &no_neighbor_route_reflector_client_cmd); + install_element(BGP_EVPN_NODE, &neighbor_route_reflector_client_cmd); + install_element(BGP_EVPN_NODE, &no_neighbor_route_reflector_client_cmd); + + /* "neighbor route-server" commands.*/ + install_element(BGP_NODE, &neighbor_route_server_client_hidden_cmd); + install_element(BGP_NODE, &no_neighbor_route_server_client_hidden_cmd); + install_element(BGP_IPV4_NODE, &neighbor_route_server_client_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_route_server_client_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_route_server_client_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_route_server_client_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_route_server_client_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_route_server_client_cmd); + install_element(BGP_IPV6_NODE, &neighbor_route_server_client_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_route_server_client_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_route_server_client_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_route_server_client_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_route_server_client_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_route_server_client_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_route_server_client_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_route_server_client_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_route_server_client_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_route_server_client_cmd); + + /* "neighbor addpath-tx-all-paths" commands.*/ + install_element(BGP_NODE, &neighbor_addpath_tx_all_paths_hidden_cmd); + install_element(BGP_NODE, &no_neighbor_addpath_tx_all_paths_hidden_cmd); + install_element(BGP_IPV4_NODE, &neighbor_addpath_tx_all_paths_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_addpath_tx_all_paths_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_addpath_tx_all_paths_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_addpath_tx_all_paths_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_addpath_tx_all_paths_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_addpath_tx_all_paths_cmd); + install_element(BGP_IPV6_NODE, &neighbor_addpath_tx_all_paths_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_addpath_tx_all_paths_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_addpath_tx_all_paths_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_addpath_tx_all_paths_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_addpath_tx_all_paths_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_addpath_tx_all_paths_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_addpath_tx_all_paths_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_addpath_tx_all_paths_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_addpath_tx_all_paths_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_addpath_tx_all_paths_cmd); + + /* "neighbor addpath-tx-bestpath-per-AS" commands.*/ + install_element(BGP_NODE, + &neighbor_addpath_tx_bestpath_per_as_hidden_cmd); + install_element(BGP_NODE, + &no_neighbor_addpath_tx_bestpath_per_as_hidden_cmd); + install_element(BGP_IPV4_NODE, + &neighbor_addpath_tx_bestpath_per_as_cmd); + install_element(BGP_IPV4_NODE, + &no_neighbor_addpath_tx_bestpath_per_as_cmd); + install_element(BGP_IPV4M_NODE, + &neighbor_addpath_tx_bestpath_per_as_cmd); + install_element(BGP_IPV4M_NODE, + &no_neighbor_addpath_tx_bestpath_per_as_cmd); + install_element(BGP_IPV4L_NODE, + &neighbor_addpath_tx_bestpath_per_as_cmd); + install_element(BGP_IPV4L_NODE, + &no_neighbor_addpath_tx_bestpath_per_as_cmd); + install_element(BGP_IPV6_NODE, + &neighbor_addpath_tx_bestpath_per_as_cmd); + install_element(BGP_IPV6_NODE, + &no_neighbor_addpath_tx_bestpath_per_as_cmd); + install_element(BGP_IPV6M_NODE, + &neighbor_addpath_tx_bestpath_per_as_cmd); + install_element(BGP_IPV6M_NODE, + &no_neighbor_addpath_tx_bestpath_per_as_cmd); + install_element(BGP_IPV6L_NODE, + &neighbor_addpath_tx_bestpath_per_as_cmd); + install_element(BGP_IPV6L_NODE, + &no_neighbor_addpath_tx_bestpath_per_as_cmd); + install_element(BGP_VPNV4_NODE, + &neighbor_addpath_tx_bestpath_per_as_cmd); + install_element(BGP_VPNV4_NODE, + &no_neighbor_addpath_tx_bestpath_per_as_cmd); + install_element(BGP_VPNV6_NODE, + &neighbor_addpath_tx_bestpath_per_as_cmd); + install_element(BGP_VPNV6_NODE, + &no_neighbor_addpath_tx_bestpath_per_as_cmd); + + /* "neighbor passive" commands. */ + install_element(BGP_NODE, &neighbor_passive_cmd); + install_element(BGP_NODE, &no_neighbor_passive_cmd); + + + /* "neighbor shutdown" commands. */ + install_element(BGP_NODE, &neighbor_shutdown_cmd); + install_element(BGP_NODE, &no_neighbor_shutdown_cmd); + install_element(BGP_NODE, &neighbor_shutdown_msg_cmd); + install_element(BGP_NODE, &no_neighbor_shutdown_msg_cmd); + + /* "neighbor capability extended-nexthop" commands.*/ + install_element(BGP_NODE, &neighbor_capability_enhe_cmd); + install_element(BGP_NODE, &no_neighbor_capability_enhe_cmd); + + /* "neighbor capability orf prefix-list" commands.*/ + install_element(BGP_NODE, &neighbor_capability_orf_prefix_hidden_cmd); + install_element(BGP_NODE, + &no_neighbor_capability_orf_prefix_hidden_cmd); + install_element(BGP_IPV4_NODE, &neighbor_capability_orf_prefix_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_capability_orf_prefix_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_capability_orf_prefix_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_capability_orf_prefix_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_capability_orf_prefix_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_capability_orf_prefix_cmd); + install_element(BGP_IPV6_NODE, &neighbor_capability_orf_prefix_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_capability_orf_prefix_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_capability_orf_prefix_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_capability_orf_prefix_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_capability_orf_prefix_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_capability_orf_prefix_cmd); + + /* "neighbor capability dynamic" commands.*/ + install_element(BGP_NODE, &neighbor_capability_dynamic_cmd); + install_element(BGP_NODE, &no_neighbor_capability_dynamic_cmd); + + /* "neighbor dont-capability-negotiate" commands. */ + install_element(BGP_NODE, &neighbor_dont_capability_negotiate_cmd); + install_element(BGP_NODE, &no_neighbor_dont_capability_negotiate_cmd); + + /* "neighbor ebgp-multihop" commands. */ + install_element(BGP_NODE, &neighbor_ebgp_multihop_cmd); + install_element(BGP_NODE, &neighbor_ebgp_multihop_ttl_cmd); + install_element(BGP_NODE, &no_neighbor_ebgp_multihop_cmd); + + /* "neighbor disable-connected-check" commands. */ + install_element(BGP_NODE, &neighbor_disable_connected_check_cmd); + install_element(BGP_NODE, &no_neighbor_disable_connected_check_cmd); + + /* "neighbor description" commands. */ + install_element(BGP_NODE, &neighbor_description_cmd); + install_element(BGP_NODE, &no_neighbor_description_cmd); + + /* "neighbor update-source" commands. "*/ + install_element(BGP_NODE, &neighbor_update_source_cmd); + install_element(BGP_NODE, &no_neighbor_update_source_cmd); + + /* "neighbor default-originate" commands. */ + install_element(BGP_NODE, &neighbor_default_originate_hidden_cmd); + install_element(BGP_NODE, &neighbor_default_originate_rmap_hidden_cmd); + install_element(BGP_NODE, &no_neighbor_default_originate_hidden_cmd); + install_element(BGP_IPV4_NODE, &neighbor_default_originate_cmd); + install_element(BGP_IPV4_NODE, &neighbor_default_originate_rmap_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_default_originate_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_default_originate_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_default_originate_rmap_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_default_originate_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_default_originate_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_default_originate_rmap_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_default_originate_cmd); + install_element(BGP_IPV6_NODE, &neighbor_default_originate_cmd); + install_element(BGP_IPV6_NODE, &neighbor_default_originate_rmap_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_default_originate_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_default_originate_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_default_originate_rmap_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_default_originate_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_default_originate_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_default_originate_rmap_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_default_originate_cmd); + + /* "neighbor port" commands. */ + install_element(BGP_NODE, &neighbor_port_cmd); + install_element(BGP_NODE, &no_neighbor_port_cmd); + + /* "neighbor weight" commands. */ + install_element(BGP_NODE, &neighbor_weight_hidden_cmd); + install_element(BGP_NODE, &no_neighbor_weight_hidden_cmd); + + install_element(BGP_IPV4_NODE, &neighbor_weight_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_weight_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_weight_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_weight_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_weight_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_weight_cmd); + install_element(BGP_IPV6_NODE, &neighbor_weight_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_weight_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_weight_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_weight_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_weight_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_weight_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_weight_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_weight_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_weight_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_weight_cmd); + + /* "neighbor override-capability" commands. */ + install_element(BGP_NODE, &neighbor_override_capability_cmd); + install_element(BGP_NODE, &no_neighbor_override_capability_cmd); + + /* "neighbor strict-capability-match" commands. */ + install_element(BGP_NODE, &neighbor_strict_capability_cmd); + install_element(BGP_NODE, &no_neighbor_strict_capability_cmd); + + /* "neighbor timers" commands. */ + install_element(BGP_NODE, &neighbor_timers_cmd); + install_element(BGP_NODE, &no_neighbor_timers_cmd); + + /* "neighbor timers connect" commands. */ + install_element(BGP_NODE, &neighbor_timers_connect_cmd); + install_element(BGP_NODE, &no_neighbor_timers_connect_cmd); + + /* "neighbor advertisement-interval" commands. */ + install_element(BGP_NODE, &neighbor_advertise_interval_cmd); + install_element(BGP_NODE, &no_neighbor_advertise_interval_cmd); + + /* "neighbor interface" commands. */ + install_element(BGP_NODE, &neighbor_interface_cmd); + install_element(BGP_NODE, &no_neighbor_interface_cmd); + + /* "neighbor distribute" commands. */ + install_element(BGP_NODE, &neighbor_distribute_list_hidden_cmd); + install_element(BGP_NODE, &no_neighbor_distribute_list_hidden_cmd); + install_element(BGP_IPV4_NODE, &neighbor_distribute_list_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_distribute_list_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_distribute_list_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_distribute_list_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_distribute_list_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_distribute_list_cmd); + install_element(BGP_IPV6_NODE, &neighbor_distribute_list_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_distribute_list_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_distribute_list_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_distribute_list_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_distribute_list_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_distribute_list_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_distribute_list_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_distribute_list_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_distribute_list_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_distribute_list_cmd); + + /* "neighbor prefix-list" commands. */ + install_element(BGP_NODE, &neighbor_prefix_list_hidden_cmd); + install_element(BGP_NODE, &no_neighbor_prefix_list_hidden_cmd); + install_element(BGP_IPV4_NODE, &neighbor_prefix_list_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_prefix_list_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_prefix_list_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_prefix_list_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_prefix_list_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_prefix_list_cmd); + install_element(BGP_IPV6_NODE, &neighbor_prefix_list_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_prefix_list_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_prefix_list_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_prefix_list_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_prefix_list_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_prefix_list_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_prefix_list_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_prefix_list_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_prefix_list_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_prefix_list_cmd); + + /* "neighbor filter-list" commands. */ + install_element(BGP_NODE, &neighbor_filter_list_hidden_cmd); + install_element(BGP_NODE, &no_neighbor_filter_list_hidden_cmd); + install_element(BGP_IPV4_NODE, &neighbor_filter_list_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_filter_list_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_filter_list_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_filter_list_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_filter_list_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_filter_list_cmd); + install_element(BGP_IPV6_NODE, &neighbor_filter_list_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_filter_list_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_filter_list_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_filter_list_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_filter_list_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_filter_list_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_filter_list_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_filter_list_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_filter_list_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_filter_list_cmd); + + /* "neighbor route-map" commands. */ + install_element(BGP_NODE, &neighbor_route_map_hidden_cmd); + install_element(BGP_NODE, &no_neighbor_route_map_hidden_cmd); + install_element(BGP_IPV4_NODE, &neighbor_route_map_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_route_map_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_route_map_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_route_map_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_route_map_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_route_map_cmd); + install_element(BGP_IPV6_NODE, &neighbor_route_map_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_route_map_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_route_map_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_route_map_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_route_map_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_route_map_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_route_map_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_route_map_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_route_map_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_route_map_cmd); + + /* "neighbor unsuppress-map" commands. */ + install_element(BGP_NODE, &neighbor_unsuppress_map_hidden_cmd); + install_element(BGP_NODE, &no_neighbor_unsuppress_map_hidden_cmd); + install_element(BGP_IPV4_NODE, &neighbor_unsuppress_map_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_unsuppress_map_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_unsuppress_map_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_unsuppress_map_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_unsuppress_map_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_unsuppress_map_cmd); + install_element(BGP_IPV6_NODE, &neighbor_unsuppress_map_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_unsuppress_map_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_unsuppress_map_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_unsuppress_map_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_unsuppress_map_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_unsuppress_map_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_unsuppress_map_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_unsuppress_map_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_unsuppress_map_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_unsuppress_map_cmd); + + /* "neighbor maximum-prefix" commands. */ + install_element(BGP_NODE, &neighbor_maximum_prefix_hidden_cmd); + install_element(BGP_NODE, + &neighbor_maximum_prefix_threshold_hidden_cmd); + install_element(BGP_NODE, &neighbor_maximum_prefix_warning_hidden_cmd); + install_element(BGP_NODE, + &neighbor_maximum_prefix_threshold_warning_hidden_cmd); + install_element(BGP_NODE, &neighbor_maximum_prefix_restart_hidden_cmd); + install_element(BGP_NODE, + &neighbor_maximum_prefix_threshold_restart_hidden_cmd); + install_element(BGP_NODE, &no_neighbor_maximum_prefix_hidden_cmd); + install_element(BGP_IPV4_NODE, &neighbor_maximum_prefix_cmd); + install_element(BGP_IPV4_NODE, &neighbor_maximum_prefix_threshold_cmd); + install_element(BGP_IPV4_NODE, &neighbor_maximum_prefix_warning_cmd); + install_element(BGP_IPV4_NODE, + &neighbor_maximum_prefix_threshold_warning_cmd); + install_element(BGP_IPV4_NODE, &neighbor_maximum_prefix_restart_cmd); + install_element(BGP_IPV4_NODE, + &neighbor_maximum_prefix_threshold_restart_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_maximum_prefix_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_maximum_prefix_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_maximum_prefix_threshold_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_maximum_prefix_warning_cmd); + install_element(BGP_IPV4M_NODE, + &neighbor_maximum_prefix_threshold_warning_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_maximum_prefix_restart_cmd); + install_element(BGP_IPV4M_NODE, + &neighbor_maximum_prefix_threshold_restart_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_maximum_prefix_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_maximum_prefix_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_maximum_prefix_threshold_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_maximum_prefix_warning_cmd); + install_element(BGP_IPV4L_NODE, + &neighbor_maximum_prefix_threshold_warning_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_maximum_prefix_restart_cmd); + install_element(BGP_IPV4L_NODE, + &neighbor_maximum_prefix_threshold_restart_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_maximum_prefix_cmd); + install_element(BGP_IPV6_NODE, &neighbor_maximum_prefix_cmd); + install_element(BGP_IPV6_NODE, &neighbor_maximum_prefix_threshold_cmd); + install_element(BGP_IPV6_NODE, &neighbor_maximum_prefix_warning_cmd); + install_element(BGP_IPV6_NODE, + &neighbor_maximum_prefix_threshold_warning_cmd); + install_element(BGP_IPV6_NODE, &neighbor_maximum_prefix_restart_cmd); + install_element(BGP_IPV6_NODE, + &neighbor_maximum_prefix_threshold_restart_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_maximum_prefix_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_maximum_prefix_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_maximum_prefix_threshold_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_maximum_prefix_warning_cmd); + install_element(BGP_IPV6M_NODE, + &neighbor_maximum_prefix_threshold_warning_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_maximum_prefix_restart_cmd); + install_element(BGP_IPV6M_NODE, + &neighbor_maximum_prefix_threshold_restart_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_maximum_prefix_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_maximum_prefix_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_maximum_prefix_threshold_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_maximum_prefix_warning_cmd); + install_element(BGP_IPV6L_NODE, + &neighbor_maximum_prefix_threshold_warning_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_maximum_prefix_restart_cmd); + install_element(BGP_IPV6L_NODE, + &neighbor_maximum_prefix_threshold_restart_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_maximum_prefix_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_maximum_prefix_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_maximum_prefix_threshold_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_maximum_prefix_warning_cmd); + install_element(BGP_VPNV4_NODE, + &neighbor_maximum_prefix_threshold_warning_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_maximum_prefix_restart_cmd); + install_element(BGP_VPNV4_NODE, + &neighbor_maximum_prefix_threshold_restart_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_maximum_prefix_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_maximum_prefix_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_maximum_prefix_threshold_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_maximum_prefix_warning_cmd); + install_element(BGP_VPNV6_NODE, + &neighbor_maximum_prefix_threshold_warning_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_maximum_prefix_restart_cmd); + install_element(BGP_VPNV6_NODE, + &neighbor_maximum_prefix_threshold_restart_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_maximum_prefix_cmd); + + /* "neighbor allowas-in" */ + install_element(BGP_NODE, &neighbor_allowas_in_hidden_cmd); + install_element(BGP_NODE, &no_neighbor_allowas_in_hidden_cmd); + install_element(BGP_IPV4_NODE, &neighbor_allowas_in_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_allowas_in_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_allowas_in_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_allowas_in_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_allowas_in_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_allowas_in_cmd); + install_element(BGP_IPV6_NODE, &neighbor_allowas_in_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_allowas_in_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_allowas_in_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_allowas_in_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_allowas_in_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_allowas_in_cmd); + install_element(BGP_VPNV4_NODE, &neighbor_allowas_in_cmd); + install_element(BGP_VPNV4_NODE, &no_neighbor_allowas_in_cmd); + install_element(BGP_VPNV6_NODE, &neighbor_allowas_in_cmd); + install_element(BGP_VPNV6_NODE, &no_neighbor_allowas_in_cmd); + install_element(BGP_EVPN_NODE, &neighbor_allowas_in_cmd); + install_element(BGP_EVPN_NODE, &no_neighbor_allowas_in_cmd); + + /* address-family commands. */ + install_element(BGP_NODE, &address_family_ipv4_safi_cmd); + install_element(BGP_NODE, &address_family_ipv6_safi_cmd); #ifdef KEEP_OLD_VPN_COMMANDS - install_element (BGP_NODE, &address_family_vpnv4_cmd); - install_element (BGP_NODE, &address_family_vpnv6_cmd); + install_element(BGP_NODE, &address_family_vpnv4_cmd); + install_element(BGP_NODE, &address_family_vpnv6_cmd); #endif /* KEEP_OLD_VPN_COMMANDS */ - install_element (BGP_NODE, &address_family_evpn_cmd); - - /* "exit-address-family" command. */ - install_element (BGP_IPV4_NODE, &exit_address_family_cmd); - install_element (BGP_IPV4M_NODE, &exit_address_family_cmd); - install_element (BGP_IPV4L_NODE, &exit_address_family_cmd); - install_element (BGP_IPV6_NODE, &exit_address_family_cmd); - install_element (BGP_IPV6M_NODE, &exit_address_family_cmd); - install_element (BGP_IPV6L_NODE, &exit_address_family_cmd); - install_element (BGP_VPNV4_NODE, &exit_address_family_cmd); - install_element (BGP_VPNV6_NODE, &exit_address_family_cmd); - install_element (BGP_EVPN_NODE, &exit_address_family_cmd); - - /* "clear ip bgp commands" */ - install_element (ENABLE_NODE, &clear_ip_bgp_all_cmd); - - /* clear ip bgp prefix */ - install_element (ENABLE_NODE, &clear_ip_bgp_prefix_cmd); - install_element (ENABLE_NODE, &clear_bgp_ipv6_safi_prefix_cmd); - install_element (ENABLE_NODE, &clear_bgp_instance_ipv6_safi_prefix_cmd); - - /* "show [ip] bgp summary" commands. */ - install_element (VIEW_NODE, &show_bgp_instance_all_ipv6_updgrps_cmd); - install_element (VIEW_NODE, &show_bgp_instance_updgrps_adj_cmd); - install_element (VIEW_NODE, &show_bgp_instance_updgrps_adj_s_cmd); - install_element (VIEW_NODE, &show_bgp_instance_updgrps_stats_cmd); - install_element (VIEW_NODE, &show_bgp_updgrps_adj_cmd); - install_element (VIEW_NODE, &show_bgp_updgrps_adj_s_cmd); - install_element (VIEW_NODE, &show_bgp_updgrps_afi_adj_cmd); - install_element (VIEW_NODE, &show_bgp_updgrps_afi_adj_s_cmd); - install_element (VIEW_NODE, &show_bgp_updgrps_stats_cmd); - install_element (VIEW_NODE, &show_ip_bgp_instance_updgrps_adj_cmd); - install_element (VIEW_NODE, &show_ip_bgp_instance_updgrps_adj_s_cmd); - install_element (VIEW_NODE, &show_ip_bgp_summary_cmd); - install_element (VIEW_NODE, &show_ip_bgp_updgrps_adj_cmd); - install_element (VIEW_NODE, &show_ip_bgp_updgrps_adj_s_cmd); - install_element (VIEW_NODE, &show_ip_bgp_updgrps_cmd); - - /* "show [ip] bgp neighbors" commands. */ - install_element (VIEW_NODE, &show_ip_bgp_neighbors_cmd); - - /* "show [ip] bgp peer-group" commands. */ - install_element (VIEW_NODE, &show_ip_bgp_peer_groups_cmd); - - /* "show [ip] bgp paths" commands. */ - install_element (VIEW_NODE, &show_ip_bgp_paths_cmd); - - /* "show [ip] bgp community" commands. */ - install_element (VIEW_NODE, &show_ip_bgp_community_info_cmd); - - /* "show ip bgp large-community" commands. */ - install_element (VIEW_NODE, &show_ip_bgp_lcommunity_info_cmd); - /* "show [ip] bgp attribute-info" commands. */ - install_element (VIEW_NODE, &show_ip_bgp_attr_info_cmd); - - /* "redistribute" commands. */ - install_element (BGP_NODE, &bgp_redistribute_ipv4_hidden_cmd); - install_element (BGP_NODE, &no_bgp_redistribute_ipv4_hidden_cmd); - install_element (BGP_NODE, &bgp_redistribute_ipv4_rmap_hidden_cmd); - install_element (BGP_NODE, &bgp_redistribute_ipv4_metric_hidden_cmd); - install_element (BGP_NODE, &bgp_redistribute_ipv4_rmap_metric_hidden_cmd); - install_element (BGP_NODE, &bgp_redistribute_ipv4_metric_rmap_hidden_cmd); - install_element (BGP_NODE, &bgp_redistribute_ipv4_ospf_hidden_cmd); - install_element (BGP_NODE, &no_bgp_redistribute_ipv4_ospf_hidden_cmd); - install_element (BGP_NODE, &bgp_redistribute_ipv4_ospf_rmap_hidden_cmd); - install_element (BGP_NODE, &bgp_redistribute_ipv4_ospf_metric_hidden_cmd); - install_element (BGP_NODE, &bgp_redistribute_ipv4_ospf_rmap_metric_hidden_cmd); - install_element (BGP_NODE, &bgp_redistribute_ipv4_ospf_metric_rmap_hidden_cmd); - install_element (BGP_IPV4_NODE, &bgp_redistribute_ipv4_cmd); - install_element (BGP_IPV4_NODE, &no_bgp_redistribute_ipv4_cmd); - install_element (BGP_IPV4_NODE, &bgp_redistribute_ipv4_rmap_cmd); - install_element (BGP_IPV4_NODE, &bgp_redistribute_ipv4_metric_cmd); - install_element (BGP_IPV4_NODE, &bgp_redistribute_ipv4_rmap_metric_cmd); - install_element (BGP_IPV4_NODE, &bgp_redistribute_ipv4_metric_rmap_cmd); - install_element (BGP_IPV4_NODE, &bgp_redistribute_ipv4_ospf_cmd); - install_element (BGP_IPV4_NODE, &no_bgp_redistribute_ipv4_ospf_cmd); - install_element (BGP_IPV4_NODE, &bgp_redistribute_ipv4_ospf_rmap_cmd); - install_element (BGP_IPV4_NODE, &bgp_redistribute_ipv4_ospf_metric_cmd); - install_element (BGP_IPV4_NODE, &bgp_redistribute_ipv4_ospf_rmap_metric_cmd); - install_element (BGP_IPV4_NODE, &bgp_redistribute_ipv4_ospf_metric_rmap_cmd); - install_element (BGP_IPV6_NODE, &bgp_redistribute_ipv6_cmd); - install_element (BGP_IPV6_NODE, &no_bgp_redistribute_ipv6_cmd); - install_element (BGP_IPV6_NODE, &bgp_redistribute_ipv6_rmap_cmd); - install_element (BGP_IPV6_NODE, &bgp_redistribute_ipv6_metric_cmd); - install_element (BGP_IPV6_NODE, &bgp_redistribute_ipv6_rmap_metric_cmd); - install_element (BGP_IPV6_NODE, &bgp_redistribute_ipv6_metric_rmap_cmd); - - /* ttl_security commands */ - install_element (BGP_NODE, &neighbor_ttl_security_cmd); - install_element (BGP_NODE, &no_neighbor_ttl_security_cmd); - - /* "show [ip] bgp memory" commands. */ - install_element (VIEW_NODE, &show_bgp_memory_cmd); - - /* "show [ip] bgp views" commands. */ - install_element (VIEW_NODE, &show_bgp_views_cmd); - - /* "show [ip] bgp vrfs" commands. */ - install_element (VIEW_NODE, &show_bgp_vrfs_cmd); - - /* Community-list. */ - community_list_vty (); + install_element(BGP_NODE, &address_family_evpn_cmd); + + /* "exit-address-family" command. */ + install_element(BGP_IPV4_NODE, &exit_address_family_cmd); + install_element(BGP_IPV4M_NODE, &exit_address_family_cmd); + install_element(BGP_IPV4L_NODE, &exit_address_family_cmd); + install_element(BGP_IPV6_NODE, &exit_address_family_cmd); + install_element(BGP_IPV6M_NODE, &exit_address_family_cmd); + install_element(BGP_IPV6L_NODE, &exit_address_family_cmd); + install_element(BGP_VPNV4_NODE, &exit_address_family_cmd); + install_element(BGP_VPNV6_NODE, &exit_address_family_cmd); + install_element(BGP_EVPN_NODE, &exit_address_family_cmd); + + /* "clear ip bgp commands" */ + install_element(ENABLE_NODE, &clear_ip_bgp_all_cmd); + + /* clear ip bgp prefix */ + install_element(ENABLE_NODE, &clear_ip_bgp_prefix_cmd); + install_element(ENABLE_NODE, &clear_bgp_ipv6_safi_prefix_cmd); + install_element(ENABLE_NODE, &clear_bgp_instance_ipv6_safi_prefix_cmd); + + /* "show [ip] bgp summary" commands. */ + install_element(VIEW_NODE, &show_bgp_instance_all_ipv6_updgrps_cmd); + install_element(VIEW_NODE, &show_bgp_instance_updgrps_adj_cmd); + install_element(VIEW_NODE, &show_bgp_instance_updgrps_adj_s_cmd); + install_element(VIEW_NODE, &show_bgp_instance_updgrps_stats_cmd); + install_element(VIEW_NODE, &show_bgp_updgrps_adj_cmd); + install_element(VIEW_NODE, &show_bgp_updgrps_adj_s_cmd); + install_element(VIEW_NODE, &show_bgp_updgrps_afi_adj_cmd); + install_element(VIEW_NODE, &show_bgp_updgrps_afi_adj_s_cmd); + install_element(VIEW_NODE, &show_bgp_updgrps_stats_cmd); + install_element(VIEW_NODE, &show_ip_bgp_instance_updgrps_adj_cmd); + install_element(VIEW_NODE, &show_ip_bgp_instance_updgrps_adj_s_cmd); + install_element(VIEW_NODE, &show_ip_bgp_summary_cmd); + install_element(VIEW_NODE, &show_ip_bgp_updgrps_adj_cmd); + install_element(VIEW_NODE, &show_ip_bgp_updgrps_adj_s_cmd); + install_element(VIEW_NODE, &show_ip_bgp_updgrps_cmd); + + /* "show [ip] bgp neighbors" commands. */ + install_element(VIEW_NODE, &show_ip_bgp_neighbors_cmd); + + /* "show [ip] bgp peer-group" commands. */ + install_element(VIEW_NODE, &show_ip_bgp_peer_groups_cmd); + + /* "show [ip] bgp paths" commands. */ + install_element(VIEW_NODE, &show_ip_bgp_paths_cmd); + + /* "show [ip] bgp community" commands. */ + install_element(VIEW_NODE, &show_ip_bgp_community_info_cmd); + + /* "show ip bgp large-community" commands. */ + install_element(VIEW_NODE, &show_ip_bgp_lcommunity_info_cmd); + /* "show [ip] bgp attribute-info" commands. */ + install_element(VIEW_NODE, &show_ip_bgp_attr_info_cmd); + + /* "redistribute" commands. */ + install_element(BGP_NODE, &bgp_redistribute_ipv4_hidden_cmd); + install_element(BGP_NODE, &no_bgp_redistribute_ipv4_hidden_cmd); + install_element(BGP_NODE, &bgp_redistribute_ipv4_rmap_hidden_cmd); + install_element(BGP_NODE, &bgp_redistribute_ipv4_metric_hidden_cmd); + install_element(BGP_NODE, + &bgp_redistribute_ipv4_rmap_metric_hidden_cmd); + install_element(BGP_NODE, + &bgp_redistribute_ipv4_metric_rmap_hidden_cmd); + install_element(BGP_NODE, &bgp_redistribute_ipv4_ospf_hidden_cmd); + install_element(BGP_NODE, &no_bgp_redistribute_ipv4_ospf_hidden_cmd); + install_element(BGP_NODE, &bgp_redistribute_ipv4_ospf_rmap_hidden_cmd); + install_element(BGP_NODE, + &bgp_redistribute_ipv4_ospf_metric_hidden_cmd); + install_element(BGP_NODE, + &bgp_redistribute_ipv4_ospf_rmap_metric_hidden_cmd); + install_element(BGP_NODE, + &bgp_redistribute_ipv4_ospf_metric_rmap_hidden_cmd); + install_element(BGP_IPV4_NODE, &bgp_redistribute_ipv4_cmd); + install_element(BGP_IPV4_NODE, &no_bgp_redistribute_ipv4_cmd); + install_element(BGP_IPV4_NODE, &bgp_redistribute_ipv4_rmap_cmd); + install_element(BGP_IPV4_NODE, &bgp_redistribute_ipv4_metric_cmd); + install_element(BGP_IPV4_NODE, &bgp_redistribute_ipv4_rmap_metric_cmd); + install_element(BGP_IPV4_NODE, &bgp_redistribute_ipv4_metric_rmap_cmd); + install_element(BGP_IPV4_NODE, &bgp_redistribute_ipv4_ospf_cmd); + install_element(BGP_IPV4_NODE, &no_bgp_redistribute_ipv4_ospf_cmd); + install_element(BGP_IPV4_NODE, &bgp_redistribute_ipv4_ospf_rmap_cmd); + install_element(BGP_IPV4_NODE, &bgp_redistribute_ipv4_ospf_metric_cmd); + install_element(BGP_IPV4_NODE, + &bgp_redistribute_ipv4_ospf_rmap_metric_cmd); + install_element(BGP_IPV4_NODE, + &bgp_redistribute_ipv4_ospf_metric_rmap_cmd); + install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_cmd); + install_element(BGP_IPV6_NODE, &no_bgp_redistribute_ipv6_cmd); + install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_rmap_cmd); + install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_metric_cmd); + install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_rmap_metric_cmd); + install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_metric_rmap_cmd); + + /* ttl_security commands */ + install_element(BGP_NODE, &neighbor_ttl_security_cmd); + install_element(BGP_NODE, &no_neighbor_ttl_security_cmd); + + /* "show [ip] bgp memory" commands. */ + install_element(VIEW_NODE, &show_bgp_memory_cmd); + + /* "show [ip] bgp views" commands. */ + install_element(VIEW_NODE, &show_bgp_views_cmd); + + /* "show [ip] bgp vrfs" commands. */ + install_element(VIEW_NODE, &show_bgp_vrfs_cmd); + + /* Community-list. */ + community_list_vty(); } #include "memory.h" @@ -11739,45 +12272,42 @@ bgp_vty_init (void) /* VTY functions. */ /* Direction value to string conversion. */ -static const char * -community_direct_str (int direct) -{ - switch (direct) - { - case COMMUNITY_DENY: - return "deny"; - case COMMUNITY_PERMIT: - return "permit"; - default: - return "unknown"; - } +static const char *community_direct_str(int direct) +{ + switch (direct) { + case COMMUNITY_DENY: + return "deny"; + case COMMUNITY_PERMIT: + return "permit"; + default: + return "unknown"; + } } /* Display error string. */ -static void -community_list_perror (struct vty *vty, int ret) -{ - switch (ret) - { - case COMMUNITY_LIST_ERR_CANT_FIND_LIST: - vty_out (vty, "%% Can't find community-list\n"); - break; - case COMMUNITY_LIST_ERR_MALFORMED_VAL: - vty_out (vty, "%% Malformed community-list value\n"); - break; - case COMMUNITY_LIST_ERR_STANDARD_CONFLICT: - vty_out (vty, "%% Community name conflict, previously defined as standard community\n"); - break; - case COMMUNITY_LIST_ERR_EXPANDED_CONFLICT: - vty_out (vty, "%% Community name conflict, previously defined as expanded community\n"); - break; - } +static void community_list_perror(struct vty *vty, int ret) +{ + switch (ret) { + case COMMUNITY_LIST_ERR_CANT_FIND_LIST: + vty_out(vty, "%% Can't find community-list\n"); + break; + case COMMUNITY_LIST_ERR_MALFORMED_VAL: + vty_out(vty, "%% Malformed community-list value\n"); + break; + case COMMUNITY_LIST_ERR_STANDARD_CONFLICT: + vty_out(vty, + "%% Community name conflict, previously defined as standard community\n"); + break; + case COMMUNITY_LIST_ERR_EXPANDED_CONFLICT: + vty_out(vty, + "%% Community name conflict, previously defined as expanded community\n"); + break; + } } /* "community-list" keyword help string. */ #define COMMUNITY_LIST_STR "Add a community list entry\n" - /* ip community-list standard */ DEFUN (ip_community_list_standard, ip_community_list_standard_cmd, @@ -11791,30 +12321,31 @@ DEFUN (ip_community_list_standard, "Specify community to accept\n" COMMUNITY_VAL_STR) { - char *cl_name_or_number = NULL; - int direct = 0; - int style = COMMUNITY_LIST_STANDARD; + char *cl_name_or_number = NULL; + int direct = 0; + int style = COMMUNITY_LIST_STANDARD; - int idx = 0; - argv_find (argv, argc, "(1-99)", &idx); - argv_find (argv, argc, "WORD", &idx); - cl_name_or_number = argv[idx]->arg; - direct = argv_find (argv, argc, "permit", &idx) ? COMMUNITY_PERMIT : COMMUNITY_DENY; - argv_find (argv, argc, "AA:NN", &idx); - char *str = argv_concat (argv, argc, idx); + int idx = 0; + argv_find(argv, argc, "(1-99)", &idx); + argv_find(argv, argc, "WORD", &idx); + cl_name_or_number = argv[idx]->arg; + direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT + : COMMUNITY_DENY; + argv_find(argv, argc, "AA:NN", &idx); + char *str = argv_concat(argv, argc, idx); - int ret = community_list_set (bgp_clist, cl_name_or_number, str, direct, style); + int ret = community_list_set(bgp_clist, cl_name_or_number, str, direct, + style); - XFREE (MTYPE_TMP, str); + XFREE(MTYPE_TMP, str); - if (ret < 0) - { - /* Display error string. */ - community_list_perror (vty, ret); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret < 0) { + /* Display error string. */ + community_list_perror(vty, ret); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_community_list_standard_all, @@ -11830,31 +12361,32 @@ DEFUN (no_ip_community_list_standard_all, "Specify community to accept\n" COMMUNITY_VAL_STR) { - int delete_all = 0; + int delete_all = 0; - char *cl_name_or_number = NULL; - int direct = 0; - int style = COMMUNITY_LIST_STANDARD; + char *cl_name_or_number = NULL; + int direct = 0; + int style = COMMUNITY_LIST_STANDARD; - int idx = 0; - argv_find (argv, argc, "(1-99)", &idx); - argv_find (argv, argc, "WORD", &idx); - cl_name_or_number = argv[idx]->arg; - direct = argv_find (argv, argc, "permit", &idx) ? COMMUNITY_PERMIT : COMMUNITY_DENY; - argv_find (argv, argc, "AA:NN", &idx); - char *str = argv_concat (argv, argc, idx); + int idx = 0; + argv_find(argv, argc, "(1-99)", &idx); + argv_find(argv, argc, "WORD", &idx); + cl_name_or_number = argv[idx]->arg; + direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT + : COMMUNITY_DENY; + argv_find(argv, argc, "AA:NN", &idx); + char *str = argv_concat(argv, argc, idx); - int ret = community_list_unset (bgp_clist, cl_name_or_number, str, direct, style, delete_all); + int ret = community_list_unset(bgp_clist, cl_name_or_number, str, + direct, style, delete_all); - XFREE (MTYPE_TMP, str); + XFREE(MTYPE_TMP, str); - if (ret < 0) - { - community_list_perror (vty, ret); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret < 0) { + community_list_perror(vty, ret); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* ip community-list expanded */ @@ -11870,30 +12402,31 @@ DEFUN (ip_community_list_expanded_all, "Specify community to accept\n" COMMUNITY_VAL_STR) { - char *cl_name_or_number = NULL; - int direct = 0; - int style = COMMUNITY_LIST_EXPANDED; + char *cl_name_or_number = NULL; + int direct = 0; + int style = COMMUNITY_LIST_EXPANDED; - int idx = 0; - argv_find (argv, argc, "(100-500)", &idx); - argv_find (argv, argc, "WORD", &idx); - cl_name_or_number = argv[idx]->arg; - direct = argv_find (argv, argc, "permit", &idx) ? COMMUNITY_PERMIT : COMMUNITY_DENY; - argv_find (argv, argc, "AA:NN", &idx); - char *str = argv_concat (argv, argc, idx); + int idx = 0; + argv_find(argv, argc, "(100-500)", &idx); + argv_find(argv, argc, "WORD", &idx); + cl_name_or_number = argv[idx]->arg; + direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT + : COMMUNITY_DENY; + argv_find(argv, argc, "AA:NN", &idx); + char *str = argv_concat(argv, argc, idx); - int ret = community_list_set (bgp_clist, cl_name_or_number, str, direct, style); + int ret = community_list_set(bgp_clist, cl_name_or_number, str, direct, + style); - XFREE (MTYPE_TMP, str); + XFREE(MTYPE_TMP, str); - if (ret < 0) - { - /* Display error string. */ - community_list_perror (vty, ret); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret < 0) { + /* Display error string. */ + community_list_perror(vty, ret); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_community_list_expanded_all, @@ -11909,62 +12442,63 @@ DEFUN (no_ip_community_list_expanded_all, "Specify community to accept\n" COMMUNITY_VAL_STR) { - int delete_all = 0; + int delete_all = 0; - char *cl_name_or_number = NULL; - int direct = 0; - int style = COMMUNITY_LIST_EXPANDED; + char *cl_name_or_number = NULL; + int direct = 0; + int style = COMMUNITY_LIST_EXPANDED; - int idx = 0; - argv_find (argv, argc, "(100-500)", &idx); - argv_find (argv, argc, "WORD", &idx); - cl_name_or_number = argv[idx]->arg; - direct = argv_find (argv, argc, "permit", &idx) ? COMMUNITY_PERMIT : COMMUNITY_DENY; - argv_find (argv, argc, "AA:NN", &idx); - char *str = argv_concat (argv, argc, idx); + int idx = 0; + argv_find(argv, argc, "(100-500)", &idx); + argv_find(argv, argc, "WORD", &idx); + cl_name_or_number = argv[idx]->arg; + direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT + : COMMUNITY_DENY; + argv_find(argv, argc, "AA:NN", &idx); + char *str = argv_concat(argv, argc, idx); - int ret = community_list_unset (bgp_clist, cl_name_or_number, str, direct, style, delete_all); + int ret = community_list_unset(bgp_clist, cl_name_or_number, str, + direct, style, delete_all); - XFREE (MTYPE_TMP, str); + XFREE(MTYPE_TMP, str); - if (ret < 0) - { - community_list_perror (vty, ret); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret < 0) { + community_list_perror(vty, ret); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } -static void -community_list_show (struct vty *vty, struct community_list *list) +static void community_list_show(struct vty *vty, struct community_list *list) { - struct community_entry *entry; + struct community_entry *entry; - for (entry = list->head; entry; entry = entry->next) - { - if (entry == list->head) - { - if (all_digit (list->name)) - vty_out (vty, "Community %s list %s\n", - entry->style == COMMUNITY_LIST_STANDARD ? - "standard" : "(expanded) access", - list->name); - else - vty_out (vty, "Named Community %s list %s\n", - entry->style == COMMUNITY_LIST_STANDARD ? - "standard" : "expanded", - list->name); - } - if (entry->any) - vty_out (vty, " %s\n", - community_direct_str (entry->direct)); - else - vty_out (vty, " %s %s\n", - community_direct_str (entry->direct), - entry->style == COMMUNITY_LIST_STANDARD - ? community_str (entry->u.com) : entry->config); - } + for (entry = list->head; entry; entry = entry->next) { + if (entry == list->head) { + if (all_digit(list->name)) + vty_out(vty, "Community %s list %s\n", + entry->style == COMMUNITY_LIST_STANDARD + ? "standard" + : "(expanded) access", + list->name); + else + vty_out(vty, "Named Community %s list %s\n", + entry->style == COMMUNITY_LIST_STANDARD + ? "standard" + : "expanded", + list->name); + } + if (entry->any) + vty_out(vty, " %s\n", + community_direct_str(entry->direct)); + else + vty_out(vty, " %s %s\n", + community_direct_str(entry->direct), + entry->style == COMMUNITY_LIST_STANDARD + ? community_str(entry->u.com) + : entry->config); + } } DEFUN (show_ip_community_list, @@ -11974,20 +12508,20 @@ DEFUN (show_ip_community_list, IP_STR "List community-list\n") { - struct community_list *list; - struct community_list_master *cm; + struct community_list *list; + struct community_list_master *cm; - cm = community_list_master_lookup (bgp_clist, COMMUNITY_LIST_MASTER); - if (! cm) - return CMD_SUCCESS; + cm = community_list_master_lookup(bgp_clist, COMMUNITY_LIST_MASTER); + if (!cm) + return CMD_SUCCESS; - for (list = cm->num.head; list; list = list->next) - community_list_show (vty, list); + for (list = cm->num.head; list; list = list->next) + community_list_show(vty, list); - for (list = cm->str.head; list; list = list->next) - community_list_show (vty, list); + for (list = cm->str.head; list; list = list->next) + community_list_show(vty, list); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_community_list_arg, @@ -11999,119 +12533,116 @@ DEFUN (show_ip_community_list_arg, "Community-list number\n" "Community-list name\n") { - int idx_comm_list = 3; - struct community_list *list; + int idx_comm_list = 3; + struct community_list *list; - list = community_list_lookup (bgp_clist, argv[idx_comm_list]->arg, COMMUNITY_LIST_MASTER); - if (! list) - { - vty_out (vty, "%% Can't find community-list\n"); - return CMD_WARNING; - } + list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg, + COMMUNITY_LIST_MASTER); + if (!list) { + vty_out(vty, "%% Can't find community-list\n"); + return CMD_WARNING; + } - community_list_show (vty, list); + community_list_show(vty, list); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* * Large Community code. */ -static int -lcommunity_list_set_vty (struct vty *vty, int argc, struct cmd_token **argv, - int style, int reject_all_digit_name) -{ - int ret; - int direct; - char *str; - int idx = 0; - char *cl_name; - - direct = argv_find (argv, argc, "permit", &idx) ? COMMUNITY_PERMIT : COMMUNITY_DENY; - - /* All digit name check. */ - idx = 0; - argv_find (argv, argc, "WORD", &idx); - argv_find (argv, argc, "(1-99)", &idx); - argv_find (argv, argc, "(100-500)", &idx); - cl_name = argv[idx]->arg; - if (reject_all_digit_name && all_digit (cl_name)) - { - vty_out (vty, "%% Community name cannot have all digits\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - idx = 0; - argv_find (argv, argc, "AA:BB:CC", &idx); - argv_find (argv, argc, "LINE", &idx); - /* Concat community string argument. */ - if (idx) - str = argv_concat (argv, argc, idx); - else - str = NULL; - - ret = lcommunity_list_set (bgp_clist, cl_name, str, direct, style); - - /* Free temporary community list string allocated by - argv_concat(). */ - if (str) - XFREE (MTYPE_TMP, str); - - if (ret < 0) - { - community_list_perror (vty, ret); - return CMD_WARNING_CONFIG_FAILED; - } - return CMD_SUCCESS; -} - -static int -lcommunity_list_unset_vty (struct vty *vty, int argc, struct cmd_token **argv, - int style) -{ - int ret; - int direct = 0; - char *str = NULL; - int idx = 0; - - argv_find (argv, argc, "permit", &idx); - argv_find (argv, argc, "deny", &idx); - - if (idx) - { - /* Check the list direct. */ - if (strncmp (argv[idx]->arg, "p", 1) == 0) - direct = COMMUNITY_PERMIT; - else - direct = COMMUNITY_DENY; - - idx = 0; - argv_find (argv, argc, "LINE", &idx); - argv_find (argv, argc, "AA:AA:NN", &idx); - /* Concat community string argument. */ - str = argv_concat (argv, argc, idx); - } - - idx = 0; - argv_find (argv, argc, "(1-99)", &idx); - argv_find (argv, argc, "(100-500)", &idx); - argv_find (argv, argc, "WORD", &idx); - - /* Unset community list. */ - ret = lcommunity_list_unset (bgp_clist, argv[idx]->arg, str, direct, style); - - /* Free temporary community list string allocated by - argv_concat(). */ - if (str) - XFREE (MTYPE_TMP, str); - - if (ret < 0) - { - community_list_perror (vty, ret); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; +static int lcommunity_list_set_vty(struct vty *vty, int argc, + struct cmd_token **argv, int style, + int reject_all_digit_name) +{ + int ret; + int direct; + char *str; + int idx = 0; + char *cl_name; + + direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT + : COMMUNITY_DENY; + + /* All digit name check. */ + idx = 0; + argv_find(argv, argc, "WORD", &idx); + argv_find(argv, argc, "(1-99)", &idx); + argv_find(argv, argc, "(100-500)", &idx); + cl_name = argv[idx]->arg; + if (reject_all_digit_name && all_digit(cl_name)) { + vty_out(vty, "%% Community name cannot have all digits\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + idx = 0; + argv_find(argv, argc, "AA:BB:CC", &idx); + argv_find(argv, argc, "LINE", &idx); + /* Concat community string argument. */ + if (idx) + str = argv_concat(argv, argc, idx); + else + str = NULL; + + ret = lcommunity_list_set(bgp_clist, cl_name, str, direct, style); + + /* Free temporary community list string allocated by + argv_concat(). */ + if (str) + XFREE(MTYPE_TMP, str); + + if (ret < 0) { + community_list_perror(vty, ret); + return CMD_WARNING_CONFIG_FAILED; + } + return CMD_SUCCESS; +} + +static int lcommunity_list_unset_vty(struct vty *vty, int argc, + struct cmd_token **argv, int style) +{ + int ret; + int direct = 0; + char *str = NULL; + int idx = 0; + + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + + if (idx) { + /* Check the list direct. */ + if (strncmp(argv[idx]->arg, "p", 1) == 0) + direct = COMMUNITY_PERMIT; + else + direct = COMMUNITY_DENY; + + idx = 0; + argv_find(argv, argc, "LINE", &idx); + argv_find(argv, argc, "AA:AA:NN", &idx); + /* Concat community string argument. */ + str = argv_concat(argv, argc, idx); + } + + idx = 0; + argv_find(argv, argc, "(1-99)", &idx); + argv_find(argv, argc, "(100-500)", &idx); + argv_find(argv, argc, "WORD", &idx); + + /* Unset community list. */ + ret = lcommunity_list_unset(bgp_clist, argv[idx]->arg, str, direct, + style); + + /* Free temporary community list string allocated by + argv_concat(). */ + if (str) + XFREE(MTYPE_TMP, str); + + if (ret < 0) { + community_list_perror(vty, ret); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } /* "large-community-list" keyword help string. */ @@ -12127,7 +12658,8 @@ DEFUN (ip_lcommunity_list_standard, "Specify large community to reject\n" "Specify large community to accept\n") { - return lcommunity_list_set_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_STANDARD, 0); + return lcommunity_list_set_vty(vty, argc, argv, + LARGE_COMMUNITY_LIST_STANDARD, 0); } DEFUN (ip_lcommunity_list_standard1, @@ -12140,7 +12672,8 @@ DEFUN (ip_lcommunity_list_standard1, "Specify large community to accept\n" LCOMMUNITY_VAL_STR) { - return lcommunity_list_set_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_STANDARD, 0); + return lcommunity_list_set_vty(vty, argc, argv, + LARGE_COMMUNITY_LIST_STANDARD, 0); } DEFUN (ip_lcommunity_list_expanded, @@ -12153,7 +12686,8 @@ DEFUN (ip_lcommunity_list_expanded, "Specify large community to accept\n" "An ordered list as a regular-expression\n") { - return lcommunity_list_set_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_EXPANDED, 0); + return lcommunity_list_set_vty(vty, argc, argv, + LARGE_COMMUNITY_LIST_EXPANDED, 0); } DEFUN (ip_lcommunity_list_name_standard, @@ -12166,7 +12700,8 @@ DEFUN (ip_lcommunity_list_name_standard, "Specify large community to reject\n" "Specify large community to accept\n") { - return lcommunity_list_set_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_STANDARD, 1); + return lcommunity_list_set_vty(vty, argc, argv, + LARGE_COMMUNITY_LIST_STANDARD, 1); } DEFUN (ip_lcommunity_list_name_standard1, @@ -12180,7 +12715,8 @@ DEFUN (ip_lcommunity_list_name_standard1, "Specify large community to accept\n" LCOMMUNITY_VAL_STR) { - return lcommunity_list_set_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_STANDARD, 1); + return lcommunity_list_set_vty(vty, argc, argv, + LARGE_COMMUNITY_LIST_STANDARD, 1); } DEFUN (ip_lcommunity_list_name_expanded, @@ -12194,7 +12730,8 @@ DEFUN (ip_lcommunity_list_name_expanded, "Specify large community to accept\n" "An ordered list as a regular-expression\n") { - return lcommunity_list_set_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_EXPANDED, 1); + return lcommunity_list_set_vty(vty, argc, argv, + LARGE_COMMUNITY_LIST_EXPANDED, 1); } DEFUN (no_ip_lcommunity_list_standard_all, @@ -12207,7 +12744,8 @@ DEFUN (no_ip_lcommunity_list_standard_all, "Large Community list number (expanded)\n" "Large Community list name\n") { - return lcommunity_list_unset_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_STANDARD); + return lcommunity_list_unset_vty(vty, argc, argv, + LARGE_COMMUNITY_LIST_STANDARD); } DEFUN (no_ip_lcommunity_list_name_expanded_all, @@ -12219,7 +12757,8 @@ DEFUN (no_ip_lcommunity_list_name_expanded_all, "Specify expanded large-community-list\n" "Large Community list name\n") { - return lcommunity_list_unset_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_EXPANDED); + return lcommunity_list_unset_vty(vty, argc, argv, + LARGE_COMMUNITY_LIST_EXPANDED); } DEFUN (no_ip_lcommunity_list_standard, @@ -12233,7 +12772,8 @@ DEFUN (no_ip_lcommunity_list_standard, "Specify large community to accept\n" LCOMMUNITY_VAL_STR) { - return lcommunity_list_unset_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_STANDARD); + return lcommunity_list_unset_vty(vty, argc, argv, + LARGE_COMMUNITY_LIST_STANDARD); } DEFUN (no_ip_lcommunity_list_expanded, @@ -12247,7 +12787,8 @@ DEFUN (no_ip_lcommunity_list_expanded, "Specify large community to accept\n" "An ordered list as a regular-expression\n") { - return lcommunity_list_unset_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_EXPANDED); + return lcommunity_list_unset_vty(vty, argc, argv, + LARGE_COMMUNITY_LIST_EXPANDED); } DEFUN (no_ip_lcommunity_list_name_standard, @@ -12262,7 +12803,8 @@ DEFUN (no_ip_lcommunity_list_name_standard, "Specify large community to accept\n" LCOMMUNITY_VAL_STR) { - return lcommunity_list_unset_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_STANDARD); + return lcommunity_list_unset_vty(vty, argc, argv, + LARGE_COMMUNITY_LIST_STANDARD); } DEFUN (no_ip_lcommunity_list_name_expanded, @@ -12277,38 +12819,40 @@ DEFUN (no_ip_lcommunity_list_name_expanded, "Specify large community to accept\n" "An ordered list as a regular-expression\n") { - return lcommunity_list_unset_vty (vty, argc, argv, LARGE_COMMUNITY_LIST_EXPANDED); -} - -static void -lcommunity_list_show (struct vty *vty, struct community_list *list) -{ - struct community_entry *entry; - - for (entry = list->head; entry; entry = entry->next) - { - if (entry == list->head) - { - if (all_digit (list->name)) - vty_out (vty, "Large community %s list %s\n", - entry->style == EXTCOMMUNITY_LIST_STANDARD ? - "standard" : "(expanded) access", - list->name); - else - vty_out (vty, "Named large community %s list %s\n", - entry->style == EXTCOMMUNITY_LIST_STANDARD ? - "standard" : "expanded", - list->name); - } - if (entry->any) - vty_out (vty, " %s\n", - community_direct_str (entry->direct)); - else - vty_out (vty, " %s %s\n", - community_direct_str (entry->direct), - entry->style == EXTCOMMUNITY_LIST_STANDARD ? - entry->u.ecom->str : entry->config); - } + return lcommunity_list_unset_vty(vty, argc, argv, + LARGE_COMMUNITY_LIST_EXPANDED); +} + +static void lcommunity_list_show(struct vty *vty, struct community_list *list) +{ + struct community_entry *entry; + + for (entry = list->head; entry; entry = entry->next) { + if (entry == list->head) { + if (all_digit(list->name)) + vty_out(vty, "Large community %s list %s\n", + entry->style == EXTCOMMUNITY_LIST_STANDARD + ? "standard" + : "(expanded) access", + list->name); + else + vty_out(vty, + "Named large community %s list %s\n", + entry->style == EXTCOMMUNITY_LIST_STANDARD + ? "standard" + : "expanded", + list->name); + } + if (entry->any) + vty_out(vty, " %s\n", + community_direct_str(entry->direct)); + else + vty_out(vty, " %s %s\n", + community_direct_str(entry->direct), + entry->style == EXTCOMMUNITY_LIST_STANDARD + ? entry->u.ecom->str + : entry->config); + } } DEFUN (show_ip_lcommunity_list, @@ -12318,20 +12862,21 @@ DEFUN (show_ip_lcommunity_list, IP_STR "List large-community list\n") { - struct community_list *list; - struct community_list_master *cm; + struct community_list *list; + struct community_list_master *cm; - cm = community_list_master_lookup (bgp_clist, LARGE_COMMUNITY_LIST_MASTER); - if (! cm) - return CMD_SUCCESS; + cm = community_list_master_lookup(bgp_clist, + LARGE_COMMUNITY_LIST_MASTER); + if (!cm) + return CMD_SUCCESS; - for (list = cm->num.head; list; list = list->next) - lcommunity_list_show (vty, list); + for (list = cm->num.head; list; list = list->next) + lcommunity_list_show(vty, list); - for (list = cm->str.head; list; list = list->next) - lcommunity_list_show (vty, list); + for (list = cm->str.head; list; list = list->next) + lcommunity_list_show(vty, list); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_lcommunity_list_arg, @@ -12343,18 +12888,18 @@ DEFUN (show_ip_lcommunity_list_arg, "large-community-list number\n" "large-community-list name\n") { - struct community_list *list; + struct community_list *list; - list = community_list_lookup (bgp_clist, argv[3]->arg, LARGE_COMMUNITY_LIST_MASTER); - if (! list) - { - vty_out (vty, "%% Can't find extcommunity-list\n"); - return CMD_WARNING; - } + list = community_list_lookup(bgp_clist, argv[3]->arg, + LARGE_COMMUNITY_LIST_MASTER); + if (!list) { + vty_out(vty, "%% Can't find extcommunity-list\n"); + return CMD_WARNING; + } - lcommunity_list_show (vty, list); + lcommunity_list_show(vty, list); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* "extcommunity-list" keyword help string. */ @@ -12373,29 +12918,30 @@ DEFUN (ip_extcommunity_list_standard, "Specify community to accept\n" EXTCOMMUNITY_VAL_STR) { - int style = EXTCOMMUNITY_LIST_STANDARD; - int direct = 0; - char *cl_number_or_name = NULL; + int style = EXTCOMMUNITY_LIST_STANDARD; + int direct = 0; + char *cl_number_or_name = NULL; - int idx = 0; - argv_find (argv, argc, "(1-99)", &idx); - argv_find (argv, argc, "WORD", &idx); - cl_number_or_name = argv[idx]->arg; - direct = argv_find (argv, argc, "permit", &idx) ? COMMUNITY_PERMIT : COMMUNITY_DENY; - argv_find (argv, argc, "AA:NN", &idx); - char *str = argv_concat (argv, argc, idx); + int idx = 0; + argv_find(argv, argc, "(1-99)", &idx); + argv_find(argv, argc, "WORD", &idx); + cl_number_or_name = argv[idx]->arg; + direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT + : COMMUNITY_DENY; + argv_find(argv, argc, "AA:NN", &idx); + char *str = argv_concat(argv, argc, idx); - int ret = extcommunity_list_set (bgp_clist, cl_number_or_name, str, direct, style); + int ret = extcommunity_list_set(bgp_clist, cl_number_or_name, str, + direct, style); - XFREE (MTYPE_TMP, str); + XFREE(MTYPE_TMP, str); - if (ret < 0) - { - community_list_perror (vty, ret); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret < 0) { + community_list_perror(vty, ret); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_extcommunity_list_name_expanded, @@ -12410,29 +12956,30 @@ DEFUN (ip_extcommunity_list_name_expanded, "Specify community to accept\n" "An ordered list as a regular-expression\n") { - int style = EXTCOMMUNITY_LIST_EXPANDED; - int direct = 0; - char *cl_number_or_name = NULL; + int style = EXTCOMMUNITY_LIST_EXPANDED; + int direct = 0; + char *cl_number_or_name = NULL; - int idx = 0; - argv_find (argv, argc, "(100-500)", &idx); - argv_find (argv, argc, "WORD", &idx); - cl_number_or_name = argv[idx]->arg; - direct = argv_find (argv, argc, "permit", &idx) ? COMMUNITY_PERMIT : COMMUNITY_DENY; - argv_find (argv, argc, "LINE", &idx); - char *str = argv_concat (argv, argc, idx); + int idx = 0; + argv_find(argv, argc, "(100-500)", &idx); + argv_find(argv, argc, "WORD", &idx); + cl_number_or_name = argv[idx]->arg; + direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT + : COMMUNITY_DENY; + argv_find(argv, argc, "LINE", &idx); + char *str = argv_concat(argv, argc, idx); - int ret = extcommunity_list_set (bgp_clist, cl_number_or_name, str, direct, style); + int ret = extcommunity_list_set(bgp_clist, cl_number_or_name, str, + direct, style); - XFREE (MTYPE_TMP, str); + XFREE(MTYPE_TMP, str); - if (ret < 0) - { - community_list_perror (vty, ret); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret < 0) { + community_list_perror(vty, ret); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_extcommunity_list_standard_all, @@ -12448,31 +12995,32 @@ DEFUN (no_ip_extcommunity_list_standard_all, "Specify community to accept\n" EXTCOMMUNITY_VAL_STR) { - int deleteall = 0; + int deleteall = 0; - int style = EXTCOMMUNITY_LIST_STANDARD; - int direct = 0; - char *cl_number_or_name = NULL; + int style = EXTCOMMUNITY_LIST_STANDARD; + int direct = 0; + char *cl_number_or_name = NULL; - int idx = 0; - argv_find (argv, argc, "(1-99)", &idx); - argv_find (argv, argc, "WORD", &idx); - cl_number_or_name = argv[idx]->arg; - direct = argv_find (argv, argc, "permit", &idx) ? COMMUNITY_PERMIT : COMMUNITY_DENY; - argv_find (argv, argc, "AA:NN", &idx); - char *str = argv_concat (argv, argc, idx); + int idx = 0; + argv_find(argv, argc, "(1-99)", &idx); + argv_find(argv, argc, "WORD", &idx); + cl_number_or_name = argv[idx]->arg; + direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT + : COMMUNITY_DENY; + argv_find(argv, argc, "AA:NN", &idx); + char *str = argv_concat(argv, argc, idx); - int ret = extcommunity_list_unset (bgp_clist, cl_number_or_name, str, direct, style, deleteall); + int ret = extcommunity_list_unset(bgp_clist, cl_number_or_name, str, + direct, style, deleteall); - XFREE (MTYPE_TMP, str); + XFREE(MTYPE_TMP, str); - if (ret < 0) - { - community_list_perror (vty, ret); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret < 0) { + community_list_perror(vty, ret); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_extcommunity_list_expanded_all, @@ -12488,62 +13036,64 @@ DEFUN (no_ip_extcommunity_list_expanded_all, "Specify community to accept\n" "An ordered list as a regular-expression\n") { - int deleteall = 0; + int deleteall = 0; - int style = EXTCOMMUNITY_LIST_EXPANDED; - int direct = 0; - char *cl_number_or_name = NULL; + int style = EXTCOMMUNITY_LIST_EXPANDED; + int direct = 0; + char *cl_number_or_name = NULL; - int idx = 0; - argv_find (argv, argc, "(100-500)", &idx); - argv_find (argv, argc, "WORD", &idx); - cl_number_or_name = argv[idx]->arg; - direct = argv_find (argv, argc, "permit", &idx) ? COMMUNITY_PERMIT : COMMUNITY_DENY; - argv_find (argv, argc, "LINE", &idx); - char *str = argv_concat (argv, argc, idx); + int idx = 0; + argv_find(argv, argc, "(100-500)", &idx); + argv_find(argv, argc, "WORD", &idx); + cl_number_or_name = argv[idx]->arg; + direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT + : COMMUNITY_DENY; + argv_find(argv, argc, "LINE", &idx); + char *str = argv_concat(argv, argc, idx); - int ret = extcommunity_list_unset (bgp_clist, cl_number_or_name, str, direct, style, deleteall); + int ret = extcommunity_list_unset(bgp_clist, cl_number_or_name, str, + direct, style, deleteall); - XFREE (MTYPE_TMP, str); + XFREE(MTYPE_TMP, str); - if (ret < 0) - { - community_list_perror (vty, ret); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret < 0) { + community_list_perror(vty, ret); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } -static void -extcommunity_list_show (struct vty *vty, struct community_list *list) +static void extcommunity_list_show(struct vty *vty, struct community_list *list) { - struct community_entry *entry; + struct community_entry *entry; - for (entry = list->head; entry; entry = entry->next) - { - if (entry == list->head) - { - if (all_digit (list->name)) - vty_out (vty, "Extended community %s list %s\n", - entry->style == EXTCOMMUNITY_LIST_STANDARD ? - "standard" : "(expanded) access", - list->name); - else - vty_out (vty, "Named extended community %s list %s\n", - entry->style == EXTCOMMUNITY_LIST_STANDARD ? - "standard" : "expanded", - list->name); - } - if (entry->any) - vty_out (vty, " %s\n", - community_direct_str (entry->direct)); - else - vty_out (vty, " %s %s\n", - community_direct_str (entry->direct), - entry->style == EXTCOMMUNITY_LIST_STANDARD ? - entry->u.ecom->str : entry->config); - } + for (entry = list->head; entry; entry = entry->next) { + if (entry == list->head) { + if (all_digit(list->name)) + vty_out(vty, "Extended community %s list %s\n", + entry->style == EXTCOMMUNITY_LIST_STANDARD + ? "standard" + : "(expanded) access", + list->name); + else + vty_out(vty, + "Named extended community %s list %s\n", + entry->style == EXTCOMMUNITY_LIST_STANDARD + ? "standard" + : "expanded", + list->name); + } + if (entry->any) + vty_out(vty, " %s\n", + community_direct_str(entry->direct)); + else + vty_out(vty, " %s %s\n", + community_direct_str(entry->direct), + entry->style == EXTCOMMUNITY_LIST_STANDARD + ? entry->u.ecom->str + : entry->config); + } } DEFUN (show_ip_extcommunity_list, @@ -12553,20 +13103,20 @@ DEFUN (show_ip_extcommunity_list, IP_STR "List extended-community list\n") { - struct community_list *list; - struct community_list_master *cm; + struct community_list *list; + struct community_list_master *cm; - cm = community_list_master_lookup (bgp_clist, EXTCOMMUNITY_LIST_MASTER); - if (! cm) - return CMD_SUCCESS; + cm = community_list_master_lookup(bgp_clist, EXTCOMMUNITY_LIST_MASTER); + if (!cm) + return CMD_SUCCESS; - for (list = cm->num.head; list; list = list->next) - extcommunity_list_show (vty, list); + for (list = cm->num.head; list; list = list->next) + extcommunity_list_show(vty, list); - for (list = cm->str.head; list; list = list->next) - extcommunity_list_show (vty, list); + for (list = cm->str.head; list; list = list->next) + extcommunity_list_show(vty, list); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_extcommunity_list_arg, @@ -12578,159 +13128,151 @@ DEFUN (show_ip_extcommunity_list_arg, "Extcommunity-list number\n" "Extcommunity-list name\n") { - int idx_comm_list = 3; - struct community_list *list; + int idx_comm_list = 3; + struct community_list *list; - list = community_list_lookup (bgp_clist, argv[idx_comm_list]->arg, EXTCOMMUNITY_LIST_MASTER); - if (! list) - { - vty_out (vty, "%% Can't find extcommunity-list\n"); - return CMD_WARNING; - } + list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg, + EXTCOMMUNITY_LIST_MASTER); + if (!list) { + vty_out(vty, "%% Can't find extcommunity-list\n"); + return CMD_WARNING; + } - extcommunity_list_show (vty, list); + extcommunity_list_show(vty, list); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Return configuration string of community-list entry. */ -static const char * -community_list_config_str (struct community_entry *entry) +static const char *community_list_config_str(struct community_entry *entry) { - const char *str; + const char *str; - if (entry->any) - str = ""; - else - { - if (entry->style == COMMUNITY_LIST_STANDARD) - str = community_str (entry->u.com); - else - str = entry->config; - } - return str; + if (entry->any) + str = ""; + else { + if (entry->style == COMMUNITY_LIST_STANDARD) + str = community_str(entry->u.com); + else + str = entry->config; + } + return str; } /* Display community-list and extcommunity-list configuration. */ -static int -community_list_config_write (struct vty *vty) -{ - struct community_list *list; - struct community_entry *entry; - struct community_list_master *cm; - int write = 0; - - /* Community-list. */ - cm = community_list_master_lookup (bgp_clist, COMMUNITY_LIST_MASTER); - - for (list = cm->num.head; list; list = list->next) - for (entry = list->head; entry; entry = entry->next) - { - vty_out (vty, "ip community-list %s %s %s\n", - list->name, community_direct_str (entry->direct), - community_list_config_str (entry)); - write++; - } - for (list = cm->str.head; list; list = list->next) - for (entry = list->head; entry; entry = entry->next) - { - vty_out (vty, "ip community-list %s %s %s %s\n", - entry->style == COMMUNITY_LIST_STANDARD - ? "standard" : "expanded", - list->name, community_direct_str (entry->direct), - community_list_config_str (entry)); - write++; - } - - /* Extcommunity-list. */ - cm = community_list_master_lookup (bgp_clist, EXTCOMMUNITY_LIST_MASTER); - - for (list = cm->num.head; list; list = list->next) - for (entry = list->head; entry; entry = entry->next) - { - vty_out (vty, "ip extcommunity-list %s %s %s\n", - list->name, community_direct_str (entry->direct), - community_list_config_str (entry)); - write++; - } - for (list = cm->str.head; list; list = list->next) - for (entry = list->head; entry; entry = entry->next) - { - vty_out (vty, "ip extcommunity-list %s %s %s %s\n", - entry->style == EXTCOMMUNITY_LIST_STANDARD - ? "standard" : "expanded", - list->name, community_direct_str (entry->direct), - community_list_config_str (entry)); - write++; - } - - - /* lcommunity-list. */ - cm = community_list_master_lookup (bgp_clist, LARGE_COMMUNITY_LIST_MASTER); - - for (list = cm->num.head; list; list = list->next) - for (entry = list->head; entry; entry = entry->next) - { - vty_out (vty, "ip large-community-list %s %s %s\n", - list->name, community_direct_str (entry->direct), - community_list_config_str (entry)); - write++; - } - for (list = cm->str.head; list; list = list->next) - for (entry = list->head; entry; entry = entry->next) - { - vty_out (vty, "ip large-community-list %s %s %s %s\n", - entry->style == LARGE_COMMUNITY_LIST_STANDARD - ? "standard" : "expanded", - list->name, community_direct_str (entry->direct), - community_list_config_str (entry)); - write++; - } - - return write; -} - -static struct cmd_node community_list_node = -{ - COMMUNITY_LIST_NODE, - "", - 1 /* Export to vtysh. */ +static int community_list_config_write(struct vty *vty) +{ + struct community_list *list; + struct community_entry *entry; + struct community_list_master *cm; + int write = 0; + + /* Community-list. */ + cm = community_list_master_lookup(bgp_clist, COMMUNITY_LIST_MASTER); + + for (list = cm->num.head; list; list = list->next) + for (entry = list->head; entry; entry = entry->next) { + vty_out(vty, "ip community-list %s %s %s\n", list->name, + community_direct_str(entry->direct), + community_list_config_str(entry)); + write++; + } + for (list = cm->str.head; list; list = list->next) + for (entry = list->head; entry; entry = entry->next) { + vty_out(vty, "ip community-list %s %s %s %s\n", + entry->style == COMMUNITY_LIST_STANDARD + ? "standard" + : "expanded", + list->name, community_direct_str(entry->direct), + community_list_config_str(entry)); + write++; + } + + /* Extcommunity-list. */ + cm = community_list_master_lookup(bgp_clist, EXTCOMMUNITY_LIST_MASTER); + + for (list = cm->num.head; list; list = list->next) + for (entry = list->head; entry; entry = entry->next) { + vty_out(vty, "ip extcommunity-list %s %s %s\n", + list->name, community_direct_str(entry->direct), + community_list_config_str(entry)); + write++; + } + for (list = cm->str.head; list; list = list->next) + for (entry = list->head; entry; entry = entry->next) { + vty_out(vty, "ip extcommunity-list %s %s %s %s\n", + entry->style == EXTCOMMUNITY_LIST_STANDARD + ? "standard" + : "expanded", + list->name, community_direct_str(entry->direct), + community_list_config_str(entry)); + write++; + } + + + /* lcommunity-list. */ + cm = community_list_master_lookup(bgp_clist, + LARGE_COMMUNITY_LIST_MASTER); + + for (list = cm->num.head; list; list = list->next) + for (entry = list->head; entry; entry = entry->next) { + vty_out(vty, "ip large-community-list %s %s %s\n", + list->name, community_direct_str(entry->direct), + community_list_config_str(entry)); + write++; + } + for (list = cm->str.head; list; list = list->next) + for (entry = list->head; entry; entry = entry->next) { + vty_out(vty, "ip large-community-list %s %s %s %s\n", + entry->style == LARGE_COMMUNITY_LIST_STANDARD + ? "standard" + : "expanded", + list->name, community_direct_str(entry->direct), + community_list_config_str(entry)); + write++; + } + + return write; +} + +static struct cmd_node community_list_node = { + COMMUNITY_LIST_NODE, "", 1 /* Export to vtysh. */ }; -static void -community_list_vty (void) -{ - install_node (&community_list_node, community_list_config_write); - - /* Community-list. */ - install_element (CONFIG_NODE, &ip_community_list_standard_cmd); - install_element (CONFIG_NODE, &ip_community_list_expanded_all_cmd); - install_element (CONFIG_NODE, &no_ip_community_list_standard_all_cmd); - install_element (CONFIG_NODE, &no_ip_community_list_expanded_all_cmd); - install_element (VIEW_NODE, &show_ip_community_list_cmd); - install_element (VIEW_NODE, &show_ip_community_list_arg_cmd); - - /* Extcommunity-list. */ - install_element (CONFIG_NODE, &ip_extcommunity_list_standard_cmd); - install_element (CONFIG_NODE, &ip_extcommunity_list_name_expanded_cmd); - install_element (CONFIG_NODE, &no_ip_extcommunity_list_standard_all_cmd); - install_element (CONFIG_NODE, &no_ip_extcommunity_list_expanded_all_cmd); - install_element (VIEW_NODE, &show_ip_extcommunity_list_cmd); - install_element (VIEW_NODE, &show_ip_extcommunity_list_arg_cmd); - - /* Large Community List */ - install_element (CONFIG_NODE, &ip_lcommunity_list_standard_cmd); - install_element (CONFIG_NODE, &ip_lcommunity_list_standard1_cmd); - install_element (CONFIG_NODE, &ip_lcommunity_list_expanded_cmd); - install_element (CONFIG_NODE, &ip_lcommunity_list_name_standard_cmd); - install_element (CONFIG_NODE, &ip_lcommunity_list_name_standard1_cmd); - install_element (CONFIG_NODE, &ip_lcommunity_list_name_expanded_cmd); - install_element (CONFIG_NODE, &no_ip_lcommunity_list_standard_all_cmd); - install_element (CONFIG_NODE, &no_ip_lcommunity_list_name_expanded_all_cmd); - install_element (CONFIG_NODE, &no_ip_lcommunity_list_standard_cmd); - install_element (CONFIG_NODE, &no_ip_lcommunity_list_expanded_cmd); - install_element (CONFIG_NODE, &no_ip_lcommunity_list_name_standard_cmd); - install_element (CONFIG_NODE, &no_ip_lcommunity_list_name_expanded_cmd); - install_element (VIEW_NODE, &show_ip_lcommunity_list_cmd); - install_element (VIEW_NODE, &show_ip_lcommunity_list_arg_cmd); +static void community_list_vty(void) +{ + install_node(&community_list_node, community_list_config_write); + + /* Community-list. */ + install_element(CONFIG_NODE, &ip_community_list_standard_cmd); + install_element(CONFIG_NODE, &ip_community_list_expanded_all_cmd); + install_element(CONFIG_NODE, &no_ip_community_list_standard_all_cmd); + install_element(CONFIG_NODE, &no_ip_community_list_expanded_all_cmd); + install_element(VIEW_NODE, &show_ip_community_list_cmd); + install_element(VIEW_NODE, &show_ip_community_list_arg_cmd); + + /* Extcommunity-list. */ + install_element(CONFIG_NODE, &ip_extcommunity_list_standard_cmd); + install_element(CONFIG_NODE, &ip_extcommunity_list_name_expanded_cmd); + install_element(CONFIG_NODE, &no_ip_extcommunity_list_standard_all_cmd); + install_element(CONFIG_NODE, &no_ip_extcommunity_list_expanded_all_cmd); + install_element(VIEW_NODE, &show_ip_extcommunity_list_cmd); + install_element(VIEW_NODE, &show_ip_extcommunity_list_arg_cmd); + + /* Large Community List */ + install_element(CONFIG_NODE, &ip_lcommunity_list_standard_cmd); + install_element(CONFIG_NODE, &ip_lcommunity_list_standard1_cmd); + install_element(CONFIG_NODE, &ip_lcommunity_list_expanded_cmd); + install_element(CONFIG_NODE, &ip_lcommunity_list_name_standard_cmd); + install_element(CONFIG_NODE, &ip_lcommunity_list_name_standard1_cmd); + install_element(CONFIG_NODE, &ip_lcommunity_list_name_expanded_cmd); + install_element(CONFIG_NODE, &no_ip_lcommunity_list_standard_all_cmd); + install_element(CONFIG_NODE, + &no_ip_lcommunity_list_name_expanded_all_cmd); + install_element(CONFIG_NODE, &no_ip_lcommunity_list_standard_cmd); + install_element(CONFIG_NODE, &no_ip_lcommunity_list_expanded_cmd); + install_element(CONFIG_NODE, &no_ip_lcommunity_list_name_standard_cmd); + install_element(CONFIG_NODE, &no_ip_lcommunity_list_name_expanded_cmd); + install_element(VIEW_NODE, &show_ip_lcommunity_list_cmd); + install_element(VIEW_NODE, &show_ip_lcommunity_list_arg_cmd); } diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h index 62228c64e..62bc27d50 100644 --- a/bgpd/bgp_vty.h +++ b/bgpd/bgp_vty.h @@ -29,47 +29,45 @@ struct bgp; #define BGP_AFI_CMD_STR "" #define BGP_AFI_HELP_STR "Address Family\nAddress Family\n" #define BGP_SAFI_CMD_STR "" -#define BGP_SAFI_HELP_STR \ - "Address Family modifier\n" \ - "Address Family modifier\n" \ - "Address Family modifier\n" +#define BGP_SAFI_HELP_STR \ + "Address Family modifier\n" \ + "Address Family modifier\n" \ + "Address Family modifier\n" #define BGP_AFI_SAFI_CMD_STR BGP_AFI_CMD_STR" "BGP_SAFI_CMD_STR #define BGP_AFI_SAFI_HELP_STR BGP_AFI_HELP_STR BGP_SAFI_HELP_STR #define BGP_SAFI_WITH_LABEL_CMD_STR "" -#define BGP_SAFI_WITH_LABEL_HELP_STR \ - "Address Family modifier\n" \ - "Address Family modifier\n" \ - "Address Family modifier\n" \ - "Address Family modifier\n" +#define BGP_SAFI_WITH_LABEL_HELP_STR \ + "Address Family modifier\n" \ + "Address Family modifier\n" \ + "Address Family modifier\n" \ + "Address Family modifier\n" -extern void bgp_vty_init (void); -extern const char *afi_safi_print (afi_t, safi_t); -extern const char *afi_safi_json (afi_t, safi_t); -extern int bgp_config_write_update_delay (struct vty *, struct bgp *); +extern void bgp_vty_init(void); +extern const char *afi_safi_print(afi_t, safi_t); +extern const char *afi_safi_json(afi_t, safi_t); +extern int bgp_config_write_update_delay(struct vty *, struct bgp *); extern int bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp); extern int bgp_config_write_listen(struct vty *vty, struct bgp *bgp); extern int bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp); -extern int bgp_vty_return (struct vty *vty, int ret); -extern struct peer * -peer_and_group_lookup_vty (struct vty *vty, const char *peer_str); +extern int bgp_vty_return(struct vty *vty, int ret); +extern struct peer *peer_and_group_lookup_vty(struct vty *vty, + const char *peer_str); -extern afi_t -bgp_vty_afi_from_str(const char *afi_str); +extern afi_t bgp_vty_afi_from_str(const char *afi_str); -extern safi_t -bgp_vty_safi_from_str(const char *safi_str); +extern safi_t bgp_vty_safi_from_str(const char *safi_str); -extern int -argv_find_and_parse_afi(struct cmd_token **argv, int argc, int *index, afi_t *afi); +extern int argv_find_and_parse_afi(struct cmd_token **argv, int argc, + int *index, afi_t *afi); -extern int -argv_find_and_parse_safi(struct cmd_token **argv, int argc, int *index, safi_t *safi); +extern int argv_find_and_parse_safi(struct cmd_token **argv, int argc, + int *index, safi_t *safi); -extern int -bgp_vty_find_and_parse_afi_safi_bgp (struct vty *vty, struct cmd_token **argv, int argc, int *idx, - afi_t *afi, safi_t *safi, struct bgp **bgp); -extern int -bgp_show_summary_vty (struct vty *vty, const char *name, - afi_t afi, safi_t safi, u_char use_json); +extern int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty, + struct cmd_token **argv, + int argc, int *idx, afi_t *afi, + safi_t *safi, struct bgp **bgp); +extern int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, + safi_t safi, u_char use_json); #endif /* _QUAGGA_BGP_VTY_H */ diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index f267e7a07..8bf5477a6 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -50,8 +50,8 @@ #include "bgpd/bgp_bfd.h" #include "bgpd/bgp_label.h" #if ENABLE_BGP_VNC -# include "bgpd/rfapi/rfapi_backend.h" -# include "bgpd/rfapi/vnc_export_bgp.h" +#include "bgpd/rfapi/rfapi_backend.h" +#include "bgpd/rfapi/vnc_export_bgp.h" #endif #include "bgpd/bgp_evpn.h" @@ -76,2195 +76,2143 @@ struct attr attr_cp[MULTIPATH_NUM]; unsigned int attr_index = 0; /* Once per address-family initialization of the attribute array */ -#define BGP_INFO_ATTR_BUF_INIT()\ -do {\ - memset(attr_cp, 0, MULTIPATH_NUM * sizeof(struct attr));\ - attr_index = 0;\ -} while (0) - -#define BGP_INFO_ATTR_BUF_COPY(info_src, info_dst)\ -do { \ - *info_dst = *info_src; \ - assert(attr_index != multipath_num);\ - bgp_attr_dup (&attr_cp[attr_index], info_src->attr); \ - bgp_attr_deep_dup (&attr_cp[attr_index], info_src->attr); \ - info_dst->attr = &attr_cp[attr_index]; \ - attr_index++;\ -} while (0) - -#define BGP_INFO_ATTR_BUF_FREE(info) \ -do { \ - bgp_attr_deep_free(info->attr); \ -} while (0) +#define BGP_INFO_ATTR_BUF_INIT() \ + do { \ + memset(attr_cp, 0, MULTIPATH_NUM * sizeof(struct attr)); \ + attr_index = 0; \ + } while (0) + +#define BGP_INFO_ATTR_BUF_COPY(info_src, info_dst) \ + do { \ + *info_dst = *info_src; \ + assert(attr_index != multipath_num); \ + bgp_attr_dup(&attr_cp[attr_index], info_src->attr); \ + bgp_attr_deep_dup(&attr_cp[attr_index], info_src->attr); \ + info_dst->attr = &attr_cp[attr_index]; \ + attr_index++; \ + } while (0) + +#define BGP_INFO_ATTR_BUF_FREE(info) \ + do { \ + bgp_attr_deep_free(info->attr); \ + } while (0) /* Can we install into zebra? */ -static inline int -bgp_install_info_to_zebra (struct bgp *bgp) +static inline int bgp_install_info_to_zebra(struct bgp *bgp) { - if (zclient->sock <= 0) - return 0; + if (zclient->sock <= 0) + return 0; - if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) - return 0; + if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + return 0; - return 1; + return 1; } int zclient_num_connects; /* Router-id update message from zebra. */ -static int -bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int bgp_router_id_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct prefix router_id; + struct prefix router_id; - zebra_router_id_update_read(zclient->ibuf,&router_id); + zebra_router_id_update_read(zclient->ibuf, &router_id); - if (BGP_DEBUG (zebra, ZEBRA)) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str(&router_id, buf, sizeof(buf)); - zlog_debug("Rx Router Id update VRF %u Id %s", vrf_id, buf); - } + if (BGP_DEBUG(zebra, ZEBRA)) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&router_id, buf, sizeof(buf)); + zlog_debug("Rx Router Id update VRF %u Id %s", vrf_id, buf); + } - bgp_router_id_zebra_bump (vrf_id, &router_id); - return 0; + bgp_router_id_zebra_bump(vrf_id, &router_id); + return 0; } /* Nexthop update message from zebra. */ -static int -bgp_read_nexthop_update (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int bgp_read_nexthop_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - bgp_parse_nexthop_update(command, vrf_id); - return 0; + bgp_parse_nexthop_update(command, vrf_id); + return 0; } -static int -bgp_read_import_check_update(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int bgp_read_import_check_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - bgp_parse_nexthop_update(command, vrf_id); - return 0; + bgp_parse_nexthop_update(command, vrf_id); + return 0; } /* Set or clear interface on which unnumbered neighbor is configured. This * would in turn cause BGP to initiate or turn off IPv6 RAs on this * interface. */ -static void -bgp_update_interface_nbrs (struct bgp *bgp, struct interface *ifp, - struct interface *upd_ifp) +static void bgp_update_interface_nbrs(struct bgp *bgp, struct interface *ifp, + struct interface *upd_ifp) { - struct listnode *node, *nnode; - struct peer *peer; - - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->conf_if && - (strcmp (peer->conf_if, ifp->name) == 0)) - { - if (upd_ifp) - { - peer->ifp = upd_ifp; - bgp_zebra_initiate_radv (bgp, peer); - } - else - { - bgp_zebra_terminate_radv (bgp, peer); - peer->ifp = upd_ifp; - } - } - } + struct listnode *node, *nnode; + struct peer *peer; + + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (peer->conf_if && (strcmp(peer->conf_if, ifp->name) == 0)) { + if (upd_ifp) { + peer->ifp = upd_ifp; + bgp_zebra_initiate_radv(bgp, peer); + } else { + bgp_zebra_terminate_radv(bgp, peer); + peer->ifp = upd_ifp; + } + } + } } -static int -bgp_read_fec_update (int command, struct zclient *zclient, - zebra_size_t length) +static int bgp_read_fec_update(int command, struct zclient *zclient, + zebra_size_t length) { - bgp_parse_fec_update(); - return 0; + bgp_parse_fec_update(); + return 0; } -static void -bgp_start_interface_nbrs (struct bgp *bgp, struct interface *ifp) +static void bgp_start_interface_nbrs(struct bgp *bgp, struct interface *ifp) { - struct listnode *node, *nnode; - struct peer *peer; - - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->conf_if && - (strcmp (peer->conf_if, ifp->name) == 0) && - peer->status != Established) - { - if (peer_active(peer)) - BGP_EVENT_ADD (peer, BGP_Stop); - BGP_EVENT_ADD (peer, BGP_Start); - } - } + struct listnode *node, *nnode; + struct peer *peer; + + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (peer->conf_if && (strcmp(peer->conf_if, ifp->name) == 0) + && peer->status != Established) { + if (peer_active(peer)) + BGP_EVENT_ADD(peer, BGP_Stop); + BGP_EVENT_ADD(peer, BGP_Start); + } + } } -static void -bgp_nbr_connected_add (struct bgp *bgp, struct nbr_connected *ifc) +static void bgp_nbr_connected_add(struct bgp *bgp, struct nbr_connected *ifc) { - struct listnode *node; - struct connected *connected; - struct interface *ifp; - struct prefix *p; - - /* Kick-off the FSM for any relevant peers only if there is a - * valid local address on the interface. - */ - ifp = ifc->ifp; - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) - { - p = connected->address; - if (p->family == AF_INET6 && - IN6_IS_ADDR_LINKLOCAL (&p->u.prefix6)) - break; - } - if (!connected) - return; - - bgp_start_interface_nbrs (bgp, ifp); + struct listnode *node; + struct connected *connected; + struct interface *ifp; + struct prefix *p; + + /* Kick-off the FSM for any relevant peers only if there is a + * valid local address on the interface. + */ + ifp = ifc->ifp; + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { + p = connected->address; + if (p->family == AF_INET6 + && IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6)) + break; + } + if (!connected) + return; + + bgp_start_interface_nbrs(bgp, ifp); } -static void -bgp_nbr_connected_delete (struct bgp *bgp, struct nbr_connected *ifc, int del) +static void bgp_nbr_connected_delete(struct bgp *bgp, struct nbr_connected *ifc, + int del) { - struct listnode *node, *nnode; - struct peer *peer; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0)) - { - peer->last_reset = PEER_DOWN_NBR_ADDR_DEL; - BGP_EVENT_ADD (peer, BGP_Stop); - } - } - /* Free neighbor also, if we're asked to. */ - if (del) - { - ifp = ifc->ifp; - listnode_delete (ifp->nbr_connected, ifc); - nbr_connected_free (ifc); - } + struct listnode *node, *nnode; + struct peer *peer; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (peer->conf_if + && (strcmp(peer->conf_if, ifc->ifp->name) == 0)) { + peer->last_reset = PEER_DOWN_NBR_ADDR_DEL; + BGP_EVENT_ADD(peer, BGP_Stop); + } + } + /* Free neighbor also, if we're asked to. */ + if (del) { + ifp = ifc->ifp; + listnode_delete(ifp->nbr_connected, ifc); + nbr_connected_free(ifc); + } } /* Inteface addition message from zebra. */ -static int -bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int bgp_interface_add(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - struct bgp *bgp; + struct interface *ifp; + struct bgp *bgp; - ifp = zebra_interface_add_read (zclient->ibuf, vrf_id); - if (!ifp) // unexpected - return 0; + ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); + if (!ifp) // unexpected + return 0; - if (BGP_DEBUG (zebra, ZEBRA) && ifp) - zlog_debug("Rx Intf add VRF %u IF %s", vrf_id, ifp->name); + if (BGP_DEBUG(zebra, ZEBRA) && ifp) + zlog_debug("Rx Intf add VRF %u IF %s", vrf_id, ifp->name); - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) + return 0; - bgp_update_interface_nbrs (bgp, ifp, ifp); - return 0; + bgp_update_interface_nbrs(bgp, ifp, ifp); + return 0; } -static int -bgp_interface_delete (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int bgp_interface_delete(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct interface *ifp; - struct bgp *bgp; + struct stream *s; + struct interface *ifp; + struct bgp *bgp; - s = zclient->ibuf; - ifp = zebra_interface_state_read (s, vrf_id); - if (!ifp) /* This may happen if we've just unregistered for a VRF. */ - return 0; + s = zclient->ibuf; + ifp = zebra_interface_state_read(s, vrf_id); + if (!ifp) /* This may happen if we've just unregistered for a VRF. */ + return 0; - ifp->ifindex = IFINDEX_DELETED; + ifp->ifindex = IFINDEX_DELETED; - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Rx Intf del VRF %u IF %s", vrf_id, ifp->name); + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Rx Intf del VRF %u IF %s", vrf_id, ifp->name); - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) + return 0; - bgp_update_interface_nbrs (bgp, ifp, NULL); - return 0; + bgp_update_interface_nbrs(bgp, ifp, NULL); + return 0; } -static int -bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int bgp_interface_up(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct interface *ifp; - struct connected *c; - struct nbr_connected *nc; - struct listnode *node, *nnode; - struct bgp *bgp; + struct stream *s; + struct interface *ifp; + struct connected *c; + struct nbr_connected *nc; + struct listnode *node, *nnode; + struct bgp *bgp; - s = zclient->ibuf; - ifp = zebra_interface_state_read (s, vrf_id); + s = zclient->ibuf; + ifp = zebra_interface_state_read(s, vrf_id); - if (! ifp) - return 0; + if (!ifp) + return 0; - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Rx Intf up VRF %u IF %s", vrf_id, ifp->name); + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Rx Intf up VRF %u IF %s", vrf_id, ifp->name); - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) + return 0; - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c)) - bgp_connected_add (bgp, c); + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, c)) + bgp_connected_add(bgp, c); - for (ALL_LIST_ELEMENTS (ifp->nbr_connected, node, nnode, nc)) - bgp_nbr_connected_add (bgp, nc); + for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, nc)) + bgp_nbr_connected_add(bgp, nc); - return 0; + return 0; } -static int -bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int bgp_interface_down(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct interface *ifp; - struct connected *c; - struct nbr_connected *nc; - struct listnode *node, *nnode; - struct bgp *bgp; + struct stream *s; + struct interface *ifp; + struct connected *c; + struct nbr_connected *nc; + struct listnode *node, *nnode; + struct bgp *bgp; - s = zclient->ibuf; - ifp = zebra_interface_state_read (s, vrf_id); - if (! ifp) - return 0; + s = zclient->ibuf; + ifp = zebra_interface_state_read(s, vrf_id); + if (!ifp) + return 0; - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Rx Intf down VRF %u IF %s", vrf_id, ifp->name); + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Rx Intf down VRF %u IF %s", vrf_id, ifp->name); - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) + return 0; - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c)) - bgp_connected_delete (bgp, c); + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, c)) + bgp_connected_delete(bgp, c); - for (ALL_LIST_ELEMENTS (ifp->nbr_connected, node, nnode, nc)) - bgp_nbr_connected_delete (bgp, nc, 1); + for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, nc)) + bgp_nbr_connected_delete(bgp, nc, 1); - /* Fast external-failover */ - { - struct peer *peer; + /* Fast external-failover */ + { + struct peer *peer; - if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER)) - return 0; + if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER)) + return 0; - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { #if defined(HAVE_CUMULUS) - /* Take down directly connected EBGP peers as well as 1-hop BFD - * tracked (directly connected) IBGP peers. - */ - if ((peer->ttl != 1) && (peer->gtsm_hops != 1) && - (!peer->bfd_info || bgp_bfd_is_peer_multihop(peer))) + /* Take down directly connected EBGP peers as well as + * 1-hop BFD + * tracked (directly connected) IBGP peers. + */ + if ((peer->ttl != 1) && (peer->gtsm_hops != 1) + && (!peer->bfd_info + || bgp_bfd_is_peer_multihop(peer))) #else - /* Take down directly connected EBGP peers */ - if ((peer->ttl != 1) && (peer->gtsm_hops != 1)) + /* Take down directly connected EBGP peers */ + if ((peer->ttl != 1) && (peer->gtsm_hops != 1)) #endif - continue; + continue; - if (ifp == peer->nexthop.ifp) - { - BGP_EVENT_ADD (peer, BGP_Stop); - peer->last_reset = PEER_DOWN_IF_DOWN; - } - } - } + if (ifp == peer->nexthop.ifp) { + BGP_EVENT_ADD(peer, BGP_Stop); + peer->last_reset = PEER_DOWN_IF_DOWN; + } + } + } - return 0; + return 0; } -static int -bgp_interface_address_add (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int bgp_interface_address_add(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct connected *ifc; - - ifc = zebra_interface_address_read (command, zclient->ibuf, vrf_id); - - if (ifc == NULL) - return 0; - - if (bgp_debug_zebra(ifc->address)) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str(ifc->address, buf, sizeof(buf)); - zlog_debug("Rx Intf address add VRF %u IF %s addr %s", - vrf_id, ifc->ifp->name, buf); - } - - if (if_is_operative (ifc->ifp)) - { - struct bgp *bgp; - - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; - - bgp_connected_add (bgp, ifc); - /* If we have learnt of any neighbors on this interface, - * check to kick off any BGP interface-based neighbors, - * but only if this is a link-local address. - */ - if (IN6_IS_ADDR_LINKLOCAL(&ifc->address->u.prefix6) && - !list_isempty(ifc->ifp->nbr_connected)) - bgp_start_interface_nbrs (bgp, ifc->ifp); - } - - return 0; + struct connected *ifc; + + ifc = zebra_interface_address_read(command, zclient->ibuf, vrf_id); + + if (ifc == NULL) + return 0; + + if (bgp_debug_zebra(ifc->address)) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(ifc->address, buf, sizeof(buf)); + zlog_debug("Rx Intf address add VRF %u IF %s addr %s", vrf_id, + ifc->ifp->name, buf); + } + + if (if_is_operative(ifc->ifp)) { + struct bgp *bgp; + + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) + return 0; + + bgp_connected_add(bgp, ifc); + /* If we have learnt of any neighbors on this interface, + * check to kick off any BGP interface-based neighbors, + * but only if this is a link-local address. + */ + if (IN6_IS_ADDR_LINKLOCAL(&ifc->address->u.prefix6) + && !list_isempty(ifc->ifp->nbr_connected)) + bgp_start_interface_nbrs(bgp, ifc->ifp); + } + + return 0; } -static int -bgp_interface_address_delete (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int bgp_interface_address_delete(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct connected *ifc; - struct bgp *bgp; + struct connected *ifc; + struct bgp *bgp; - ifc = zebra_interface_address_read (command, zclient->ibuf, vrf_id); + ifc = zebra_interface_address_read(command, zclient->ibuf, vrf_id); - if (ifc == NULL) - return 0; + if (ifc == NULL) + return 0; - if (bgp_debug_zebra(ifc->address)) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str(ifc->address, buf, sizeof(buf)); - zlog_debug("Rx Intf address del VRF %u IF %s addr %s", - vrf_id, ifc->ifp->name, buf); - } + if (bgp_debug_zebra(ifc->address)) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(ifc->address, buf, sizeof(buf)); + zlog_debug("Rx Intf address del VRF %u IF %s addr %s", vrf_id, + ifc->ifp->name, buf); + } - if (if_is_operative (ifc->ifp)) - { - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (bgp) - bgp_connected_delete (bgp, ifc); - } + if (if_is_operative(ifc->ifp)) { + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (bgp) + bgp_connected_delete(bgp, ifc); + } - connected_free (ifc); + connected_free(ifc); - return 0; + return 0; } -static int -bgp_interface_nbr_address_add (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int bgp_interface_nbr_address_add(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct nbr_connected *ifc = NULL; - struct bgp *bgp; - - ifc = zebra_interface_nbr_address_read (command, zclient->ibuf, vrf_id); - - if (ifc == NULL) - return 0; - - if (bgp_debug_zebra(ifc->address)) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str(ifc->address, buf, sizeof(buf)); - zlog_debug("Rx Intf neighbor add VRF %u IF %s addr %s", - vrf_id, ifc->ifp->name, buf); - } - - if (if_is_operative (ifc->ifp)) - { - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (bgp) - bgp_nbr_connected_add (bgp, ifc); - } - - return 0; + struct nbr_connected *ifc = NULL; + struct bgp *bgp; + + ifc = zebra_interface_nbr_address_read(command, zclient->ibuf, vrf_id); + + if (ifc == NULL) + return 0; + + if (bgp_debug_zebra(ifc->address)) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(ifc->address, buf, sizeof(buf)); + zlog_debug("Rx Intf neighbor add VRF %u IF %s addr %s", vrf_id, + ifc->ifp->name, buf); + } + + if (if_is_operative(ifc->ifp)) { + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (bgp) + bgp_nbr_connected_add(bgp, ifc); + } + + return 0; } -static int -bgp_interface_nbr_address_delete (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int bgp_interface_nbr_address_delete(int command, + struct zclient *zclient, + zebra_size_t length, + vrf_id_t vrf_id) { - struct nbr_connected *ifc = NULL; - struct bgp *bgp; + struct nbr_connected *ifc = NULL; + struct bgp *bgp; - ifc = zebra_interface_nbr_address_read (command, zclient->ibuf, vrf_id); + ifc = zebra_interface_nbr_address_read(command, zclient->ibuf, vrf_id); - if (ifc == NULL) - return 0; + if (ifc == NULL) + return 0; - if (bgp_debug_zebra(ifc->address)) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str(ifc->address, buf, sizeof(buf)); - zlog_debug("Rx Intf neighbor del VRF %u IF %s addr %s", - vrf_id, ifc->ifp->name, buf); - } + if (bgp_debug_zebra(ifc->address)) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(ifc->address, buf, sizeof(buf)); + zlog_debug("Rx Intf neighbor del VRF %u IF %s addr %s", vrf_id, + ifc->ifp->name, buf); + } - if (if_is_operative (ifc->ifp)) - { - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (bgp) - bgp_nbr_connected_delete (bgp, ifc, 0); - } + if (if_is_operative(ifc->ifp)) { + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (bgp) + bgp_nbr_connected_delete(bgp, ifc, 0); + } - nbr_connected_free (ifc); + nbr_connected_free(ifc); - return 0; + return 0; } /* VRF update for an interface. */ -static int -bgp_interface_vrf_update (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int bgp_interface_vrf_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - vrf_id_t new_vrf_id; - struct connected *c; - struct nbr_connected *nc; - struct listnode *node, *nnode; - struct bgp *bgp; + struct interface *ifp; + vrf_id_t new_vrf_id; + struct connected *c; + struct nbr_connected *nc; + struct listnode *node, *nnode; + struct bgp *bgp; - ifp = zebra_interface_vrf_update_read (zclient->ibuf, vrf_id, &new_vrf_id); - if (! ifp) - return 0; + ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id, + &new_vrf_id); + if (!ifp) + return 0; - if (BGP_DEBUG (zebra, ZEBRA) && ifp) - zlog_debug("Rx Intf VRF change VRF %u IF %s NewVRF %u", - vrf_id, ifp->name, new_vrf_id); + if (BGP_DEBUG(zebra, ZEBRA) && ifp) + zlog_debug("Rx Intf VRF change VRF %u IF %s NewVRF %u", vrf_id, + ifp->name, new_vrf_id); - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) + return 0; - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c)) - bgp_connected_delete (bgp, c); + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, c)) + bgp_connected_delete(bgp, c); - for (ALL_LIST_ELEMENTS (ifp->nbr_connected, node, nnode, nc)) - bgp_nbr_connected_delete (bgp, nc, 1); + for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, nc)) + bgp_nbr_connected_delete(bgp, nc, 1); - /* Fast external-failover */ - { - struct peer *peer; + /* Fast external-failover */ + { + struct peer *peer; - if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER)) - return 0; + if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER)) + return 0; - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if ((peer->ttl != 1) && (peer->gtsm_hops != 1)) - continue; + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if ((peer->ttl != 1) && (peer->gtsm_hops != 1)) + continue; - if (ifp == peer->nexthop.ifp) - BGP_EVENT_ADD (peer, BGP_Stop); - } - } + if (ifp == peer->nexthop.ifp) + BGP_EVENT_ADD(peer, BGP_Stop); + } + } - if_update_to_new_vrf (ifp, new_vrf_id); + if_update_to_new_vrf(ifp, new_vrf_id); - bgp = bgp_lookup_by_vrf_id (new_vrf_id); - if (!bgp) - return 0; + bgp = bgp_lookup_by_vrf_id(new_vrf_id); + if (!bgp) + return 0; - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c)) - bgp_connected_add (bgp, c); + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, c)) + bgp_connected_add(bgp, c); - for (ALL_LIST_ELEMENTS (ifp->nbr_connected, node, nnode, nc)) - bgp_nbr_connected_add (bgp, nc); - return 0; + for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, nc)) + bgp_nbr_connected_add(bgp, nc); + return 0; } /* Zebra route add and delete treatment. */ -static int -zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int zebra_read_ipv4(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv4 api; - struct in_addr nexthop; - struct prefix_ipv4 p; - unsigned int ifindex; - int i; - struct bgp *bgp; - - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; - - s = zclient->ibuf; - nexthop.s_addr = 0; - - /* Type, flags, message. */ - api.type = stream_getc (s); - api.instance = stream_getw (s); - api.flags = stream_getl (s); - api.message = stream_getc (s); - - /* IPv4 prefix. */ - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc (s)); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) - { - api.nexthop_num = stream_getc (s); - nexthop.s_addr = stream_get_ipv4 (s); - } - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) - { - api.ifindex_num = stream_getc (s); - ifindex = stream_getl (s); /* ifindex, unused */ - } - else - { - ifindex = 0; - } - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc (s); - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl (s); - else - api.metric = 0; - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl (s); - else - api.tag = 0; - - if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) - { - if (bgp_debug_zebra((struct prefix *)&p)) - { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Rx IPv4 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %"ROUTE_TAG_PRI, - vrf_id, - zebra_route_string(api.type), api.instance, - inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])), - p.prefixlen, - inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), - api.metric, - api.tag); + struct stream *s; + struct zapi_ipv4 api; + struct in_addr nexthop; + struct prefix_ipv4 p; + unsigned int ifindex; + int i; + struct bgp *bgp; + + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) + return 0; + + s = zclient->ibuf; + nexthop.s_addr = 0; + + /* Type, flags, message. */ + api.type = stream_getc(s); + api.instance = stream_getw(s); + api.flags = stream_getl(s); + api.message = stream_getc(s); + + /* IPv4 prefix. */ + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); + stream_get(&p.prefix, s, PSIZE(p.prefixlen)); + + /* Nexthop, ifindex, distance, metric. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { + api.nexthop_num = stream_getc(s); + nexthop.s_addr = stream_get_ipv4(s); } - /* - * The ADD message is actually an UPDATE and there is no explicit DEL - * for a prior redistributed route, if any. So, perform an implicit - * DEL processing for the same redistributed route from any other - * source type. - */ - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - if (i != api.type) - bgp_redistribute_delete(bgp, (struct prefix *)&p, i, api.instance); - } - - /* Now perform the add/update. */ - bgp_redistribute_add(bgp, (struct prefix *)&p, &nexthop, NULL, ifindex, - api.metric, api.type, api.instance, api.tag); - } - else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) - { - if (bgp_debug_zebra((struct prefix *)&p)) - { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Rx IPv4 route delete VRF %u %s[%d] %s/%d " - "nexthop %s metric %u tag %"ROUTE_TAG_PRI, - vrf_id, - zebra_route_string(api.type), api.instance, - inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])), - p.prefixlen, - inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), - api.metric, - api.tag); + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { + api.ifindex_num = stream_getc(s); + ifindex = stream_getl(s); /* ifindex, unused */ + } else { + ifindex = 0; + } + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) + api.distance = stream_getc(s); + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) + api.metric = stream_getl(s); + else + api.metric = 0; + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getl(s); + else + api.tag = 0; + + if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) { + if (bgp_debug_zebra((struct prefix *)&p)) { + char buf[2][INET_ADDRSTRLEN]; + zlog_debug( + "Rx IPv4 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %" ROUTE_TAG_PRI, + vrf_id, zebra_route_string(api.type), + api.instance, inet_ntop(AF_INET, &p.prefix, + buf[0], sizeof(buf[0])), + p.prefixlen, inet_ntop(AF_INET, &nexthop, + buf[1], sizeof(buf[1])), + api.metric, api.tag); + } + + /* + * The ADD message is actually an UPDATE and there is no + * explicit DEL + * for a prior redistributed route, if any. So, perform an + * implicit + * DEL processing for the same redistributed route from any + * other + * source type. + */ + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (i != api.type) + bgp_redistribute_delete(bgp, + (struct prefix *)&p, i, + api.instance); + } + + /* Now perform the add/update. */ + bgp_redistribute_add(bgp, (struct prefix *)&p, &nexthop, NULL, + ifindex, api.metric, api.type, + api.instance, api.tag); + } else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) { + if (bgp_debug_zebra((struct prefix *)&p)) { + char buf[2][INET_ADDRSTRLEN]; + zlog_debug( + "Rx IPv4 route delete VRF %u %s[%d] %s/%d " + "nexthop %s metric %u tag %" ROUTE_TAG_PRI, + vrf_id, zebra_route_string(api.type), + api.instance, inet_ntop(AF_INET, &p.prefix, + buf[0], sizeof(buf[0])), + p.prefixlen, inet_ntop(AF_INET, &nexthop, + buf[1], sizeof(buf[1])), + api.metric, api.tag); + } + bgp_redistribute_delete(bgp, (struct prefix *)&p, api.type, + api.instance); } - bgp_redistribute_delete(bgp, (struct prefix *)&p, api.type, api.instance); - } - return 0; + return 0; } /* Zebra route add and delete treatment. */ -static int -zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int zebra_read_ipv6(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv6 api; - struct in6_addr nexthop; - struct prefix_ipv6 p, src_p; - unsigned int ifindex; - int i; - struct bgp *bgp; - - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; - - s = zclient->ibuf; - memset (&nexthop, 0, sizeof (struct in6_addr)); - - /* Type, flags, message. */ - api.type = stream_getc (s); - api.instance = stream_getw (s); - api.flags = stream_getl (s); - api.message = stream_getc (s); - - /* IPv6 prefix. */ - memset (&p, 0, sizeof (struct prefix_ipv6)); - p.family = AF_INET6; - p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc (s)); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); - - memset (&src_p, 0, sizeof (struct prefix_ipv6)); - src_p.family = AF_INET6; - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_SRCPFX)) - { - src_p.prefixlen = stream_getc (s); - stream_get (&src_p.prefix, s, PSIZE (src_p.prefixlen)); - } - - if (src_p.prefixlen) - /* we completely ignore srcdest routes for now. */ - return 0; - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) - { - api.nexthop_num = stream_getc (s); - stream_get (&nexthop, s, 16); - } - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) - { - api.ifindex_num = stream_getc (s); - ifindex = stream_getl (s); /* ifindex, unused */ - } - else - { - ifindex = 0; - } - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc (s); - else - api.distance = 0; - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl (s); - else - api.metric = 0; - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl (s); - else - api.tag = 0; - - /* Simply ignore link-local address. */ - if (IN6_IS_ADDR_LINKLOCAL (&p.prefix)) - return 0; - - if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) - { - if (bgp_debug_zebra((struct prefix *)&p)) - { - char buf[2][INET6_ADDRSTRLEN]; - zlog_debug("Rx IPv6 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %"ROUTE_TAG_PRI, - vrf_id, - zebra_route_string(api.type), api.instance, - inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])), - p.prefixlen, - inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), - api.metric, - api.tag); + struct stream *s; + struct zapi_ipv6 api; + struct in6_addr nexthop; + struct prefix_ipv6 p, src_p; + unsigned int ifindex; + int i; + struct bgp *bgp; + + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) + return 0; + + s = zclient->ibuf; + memset(&nexthop, 0, sizeof(struct in6_addr)); + + /* Type, flags, message. */ + api.type = stream_getc(s); + api.instance = stream_getw(s); + api.flags = stream_getl(s); + api.message = stream_getc(s); + + /* IPv6 prefix. */ + memset(&p, 0, sizeof(struct prefix_ipv6)); + p.family = AF_INET6; + p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s)); + stream_get(&p.prefix, s, PSIZE(p.prefixlen)); + + memset(&src_p, 0, sizeof(struct prefix_ipv6)); + src_p.family = AF_INET6; + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { + src_p.prefixlen = stream_getc(s); + stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen)); } - /* - * The ADD message is actually an UPDATE and there is no explicit DEL - * for a prior redistributed route, if any. So, perform an implicit - * DEL processing for the same redistributed route from any other - * source type. - */ - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - if (i != api.type) - bgp_redistribute_delete(bgp, (struct prefix *)&p, i, api.instance); - } - - bgp_redistribute_add (bgp, (struct prefix *)&p, NULL, &nexthop, ifindex, - api.metric, api.type, api.instance, api.tag); - } - else if (command == ZEBRA_REDISTRIBUTE_IPV6_DEL) - { - if (bgp_debug_zebra((struct prefix *)&p)) - { - char buf[2][INET6_ADDRSTRLEN]; - zlog_debug("Rx IPv6 route delete VRF %u %s[%d] %s/%d " - "nexthop %s metric %u tag %"ROUTE_TAG_PRI, - vrf_id, - zebra_route_string(api.type), api.instance, - inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])), - p.prefixlen, - inet_ntop(AF_INET6, &nexthop, buf[1], sizeof(buf[1])), - api.metric, - api.tag); + if (src_p.prefixlen) + /* we completely ignore srcdest routes for now. */ + return 0; + + /* Nexthop, ifindex, distance, metric. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { + api.nexthop_num = stream_getc(s); + stream_get(&nexthop, s, 16); + } + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { + api.ifindex_num = stream_getc(s); + ifindex = stream_getl(s); /* ifindex, unused */ + } else { + ifindex = 0; } - bgp_redistribute_delete (bgp, (struct prefix *) &p, api.type, api.instance); - } - - return 0; + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) + api.distance = stream_getc(s); + else + api.distance = 0; + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) + api.metric = stream_getl(s); + else + api.metric = 0; + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getl(s); + else + api.tag = 0; + + /* Simply ignore link-local address. */ + if (IN6_IS_ADDR_LINKLOCAL(&p.prefix)) + return 0; + + if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) { + if (bgp_debug_zebra((struct prefix *)&p)) { + char buf[2][INET6_ADDRSTRLEN]; + zlog_debug( + "Rx IPv6 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %" ROUTE_TAG_PRI, + vrf_id, zebra_route_string(api.type), + api.instance, inet_ntop(AF_INET6, &p.prefix, + buf[0], sizeof(buf[0])), + p.prefixlen, inet_ntop(AF_INET, &nexthop, + buf[1], sizeof(buf[1])), + api.metric, api.tag); + } + + /* + * The ADD message is actually an UPDATE and there is no + * explicit DEL + * for a prior redistributed route, if any. So, perform an + * implicit + * DEL processing for the same redistributed route from any + * other + * source type. + */ + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (i != api.type) + bgp_redistribute_delete(bgp, + (struct prefix *)&p, i, + api.instance); + } + + bgp_redistribute_add(bgp, (struct prefix *)&p, NULL, &nexthop, + ifindex, api.metric, api.type, + api.instance, api.tag); + } else if (command == ZEBRA_REDISTRIBUTE_IPV6_DEL) { + if (bgp_debug_zebra((struct prefix *)&p)) { + char buf[2][INET6_ADDRSTRLEN]; + zlog_debug( + "Rx IPv6 route delete VRF %u %s[%d] %s/%d " + "nexthop %s metric %u tag %" ROUTE_TAG_PRI, + vrf_id, zebra_route_string(api.type), + api.instance, inet_ntop(AF_INET6, &p.prefix, + buf[0], sizeof(buf[0])), + p.prefixlen, inet_ntop(AF_INET6, &nexthop, + buf[1], sizeof(buf[1])), + api.metric, api.tag); + } + bgp_redistribute_delete(bgp, (struct prefix *)&p, api.type, + api.instance); + } + + return 0; } -struct interface * -if_lookup_by_ipv4 (struct in_addr *addr, vrf_id_t vrf_id) +struct interface *if_lookup_by_ipv4(struct in_addr *addr, vrf_id_t vrf_id) { - struct listnode *ifnode; - struct listnode *cnode; - struct interface *ifp; - struct connected *connected; - struct prefix_ipv4 p; - struct prefix *cp; - - p.family = AF_INET; - p.prefix = *addr; - p.prefixlen = IPV4_MAX_BITLEN; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist(vrf_id), ifnode, ifp)) - { - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected)) - { - cp = connected->address; - - if (cp->family == AF_INET) - if (prefix_match (cp, (struct prefix *)&p)) - return ifp; + struct listnode *ifnode; + struct listnode *cnode; + struct interface *ifp; + struct connected *connected; + struct prefix_ipv4 p; + struct prefix *cp; + + p.family = AF_INET; + p.prefix = *addr; + p.prefixlen = IPV4_MAX_BITLEN; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), ifnode, ifp)) { + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) { + cp = connected->address; + + if (cp->family == AF_INET) + if (prefix_match(cp, (struct prefix *)&p)) + return ifp; + } } - } - return NULL; + return NULL; } -struct interface * -if_lookup_by_ipv4_exact (struct in_addr *addr, vrf_id_t vrf_id) +struct interface *if_lookup_by_ipv4_exact(struct in_addr *addr, vrf_id_t vrf_id) { - struct listnode *ifnode; - struct listnode *cnode; - struct interface *ifp; - struct connected *connected; - struct prefix *cp; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist(vrf_id), ifnode, ifp)) - { - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected)) - { - cp = connected->address; - - if (cp->family == AF_INET) - if (IPV4_ADDR_SAME (&cp->u.prefix4, addr)) - return ifp; + struct listnode *ifnode; + struct listnode *cnode; + struct interface *ifp; + struct connected *connected; + struct prefix *cp; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), ifnode, ifp)) { + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) { + cp = connected->address; + + if (cp->family == AF_INET) + if (IPV4_ADDR_SAME(&cp->u.prefix4, addr)) + return ifp; + } } - } - return NULL; + return NULL; } -struct interface * -if_lookup_by_ipv6 (struct in6_addr *addr, ifindex_t ifindex, vrf_id_t vrf_id) +struct interface *if_lookup_by_ipv6(struct in6_addr *addr, ifindex_t ifindex, + vrf_id_t vrf_id) { - struct listnode *ifnode; - struct listnode *cnode; - struct interface *ifp; - struct connected *connected; - struct prefix_ipv6 p; - struct prefix *cp; - - p.family = AF_INET6; - p.prefix = *addr; - p.prefixlen = IPV6_MAX_BITLEN; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist(vrf_id), ifnode, ifp)) - { - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected)) - { - cp = connected->address; - - if (cp->family == AF_INET6) - if (prefix_match (cp, (struct prefix *)&p)) - { - if (IN6_IS_ADDR_LINKLOCAL(&cp->u.prefix6)) - { - if (ifindex == ifp->ifindex) - return ifp; - } - else - return ifp; - } + struct listnode *ifnode; + struct listnode *cnode; + struct interface *ifp; + struct connected *connected; + struct prefix_ipv6 p; + struct prefix *cp; + + p.family = AF_INET6; + p.prefix = *addr; + p.prefixlen = IPV6_MAX_BITLEN; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), ifnode, ifp)) { + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) { + cp = connected->address; + + if (cp->family == AF_INET6) + if (prefix_match(cp, (struct prefix *)&p)) { + if (IN6_IS_ADDR_LINKLOCAL( + &cp->u.prefix6)) { + if (ifindex == ifp->ifindex) + return ifp; + } else + return ifp; + } + } } - } - return NULL; + return NULL; } -struct interface * -if_lookup_by_ipv6_exact (struct in6_addr *addr, ifindex_t ifindex, vrf_id_t vrf_id) +struct interface *if_lookup_by_ipv6_exact(struct in6_addr *addr, + ifindex_t ifindex, vrf_id_t vrf_id) { - struct listnode *ifnode; - struct listnode *cnode; - struct interface *ifp; - struct connected *connected; - struct prefix *cp; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist(vrf_id), ifnode, ifp)) - { - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected)) - { - cp = connected->address; - - if (cp->family == AF_INET6) - if (IPV6_ADDR_SAME (&cp->u.prefix6, addr)) - { - if (IN6_IS_ADDR_LINKLOCAL(&cp->u.prefix6)) - { - if (ifindex == ifp->ifindex) - return ifp; - } - else - return ifp; - } + struct listnode *ifnode; + struct listnode *cnode; + struct interface *ifp; + struct connected *connected; + struct prefix *cp; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), ifnode, ifp)) { + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) { + cp = connected->address; + + if (cp->family == AF_INET6) + if (IPV6_ADDR_SAME(&cp->u.prefix6, addr)) { + if (IN6_IS_ADDR_LINKLOCAL( + &cp->u.prefix6)) { + if (ifindex == ifp->ifindex) + return ifp; + } else + return ifp; + } + } } - } - return NULL; + return NULL; } -static int -if_get_ipv6_global (struct interface *ifp, struct in6_addr *addr) +static int if_get_ipv6_global(struct interface *ifp, struct in6_addr *addr) { - struct listnode *cnode; - struct connected *connected; - struct prefix *cp; - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected)) - { - cp = connected->address; - - if (cp->family == AF_INET6) - if (! IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6)) - { - memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN); - return 1; - } - } - return 0; + struct listnode *cnode; + struct connected *connected; + struct prefix *cp; + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) { + cp = connected->address; + + if (cp->family == AF_INET6) + if (!IN6_IS_ADDR_LINKLOCAL(&cp->u.prefix6)) { + memcpy(addr, &cp->u.prefix6, IPV6_MAX_BYTELEN); + return 1; + } + } + return 0; } -static int -if_get_ipv6_local (struct interface *ifp, struct in6_addr *addr) +static int if_get_ipv6_local(struct interface *ifp, struct in6_addr *addr) { - struct listnode *cnode; - struct connected *connected; - struct prefix *cp; - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected)) - { - cp = connected->address; - - if (cp->family == AF_INET6) - if (IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6)) - { - memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN); - return 1; - } - } - return 0; + struct listnode *cnode; + struct connected *connected; + struct prefix *cp; + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) { + cp = connected->address; + + if (cp->family == AF_INET6) + if (IN6_IS_ADDR_LINKLOCAL(&cp->u.prefix6)) { + memcpy(addr, &cp->u.prefix6, IPV6_MAX_BYTELEN); + return 1; + } + } + return 0; } -static int -if_get_ipv4_address (struct interface *ifp, struct in_addr *addr) +static int if_get_ipv4_address(struct interface *ifp, struct in_addr *addr) { - struct listnode *cnode; - struct connected *connected; - struct prefix *cp; - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected)) - { - cp = connected->address; - if ((cp->family == AF_INET) && !ipv4_martian(&(cp->u.prefix4))) - { - *addr = cp->u.prefix4; - return 1; - } - } - return 0; + struct listnode *cnode; + struct connected *connected; + struct prefix *cp; + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) { + cp = connected->address; + if ((cp->family == AF_INET) + && !ipv4_martian(&(cp->u.prefix4))) { + *addr = cp->u.prefix4; + return 1; + } + } + return 0; } -int -bgp_nexthop_set (union sockunion *local, union sockunion *remote, - struct bgp_nexthop *nexthop, struct peer *peer) +int bgp_nexthop_set(union sockunion *local, union sockunion *remote, + struct bgp_nexthop *nexthop, struct peer *peer) { - int ret = 0; - struct interface *ifp = NULL; - - memset (nexthop, 0, sizeof (struct bgp_nexthop)); - - if (!local) - return -1; - if (!remote) - return -1; - - if (local->sa.sa_family == AF_INET) - { - nexthop->v4 = local->sin.sin_addr; - if (peer->update_if) - ifp = if_lookup_by_name (peer->update_if, peer->bgp->vrf_id); - else - ifp = if_lookup_by_ipv4_exact (&local->sin.sin_addr, peer->bgp->vrf_id); - } - if (local->sa.sa_family == AF_INET6) - { - if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr)) - { - if (peer->conf_if || peer->ifname) - ifp = if_lookup_by_name (peer->conf_if ? peer->conf_if : peer->ifname, peer->bgp->vrf_id); + int ret = 0; + struct interface *ifp = NULL; + + memset(nexthop, 0, sizeof(struct bgp_nexthop)); + + if (!local) + return -1; + if (!remote) + return -1; + + if (local->sa.sa_family == AF_INET) { + nexthop->v4 = local->sin.sin_addr; + if (peer->update_if) + ifp = if_lookup_by_name(peer->update_if, + peer->bgp->vrf_id); + else + ifp = if_lookup_by_ipv4_exact(&local->sin.sin_addr, + peer->bgp->vrf_id); } - else if (peer->update_if) - ifp = if_lookup_by_name (peer->update_if, peer->bgp->vrf_id); - else - ifp = if_lookup_by_ipv6_exact (&local->sin6.sin6_addr, - local->sin6.sin6_scope_id, - peer->bgp->vrf_id); - } - - if (!ifp) - return -1; - - nexthop->ifp = ifp; - - /* IPv4 connection, fetch and store IPv6 local address(es) if any. */ - if (local->sa.sa_family == AF_INET) - { - /* IPv6 nexthop*/ - ret = if_get_ipv6_global (ifp, &nexthop->v6_global); - - if (!ret) - { - /* There is no global nexthop. Use link-local address as both the - * global and link-local nexthop. In this scenario, the expectation - * for interop is that the network admin would use a route-map to - * specify the global IPv6 nexthop. - */ - if_get_ipv6_local (ifp, &nexthop->v6_global); - memcpy (&nexthop->v6_local, &nexthop->v6_global, - IPV6_MAX_BYTELEN); - } - else - if_get_ipv6_local (ifp, &nexthop->v6_local); - - if (if_lookup_by_ipv4 (&remote->sin.sin_addr, peer->bgp->vrf_id)) - peer->shared_network = 1; - else - peer->shared_network = 0; - } - - /* IPv6 connection, fetch and store IPv4 local address if any. */ - if (local->sa.sa_family == AF_INET6) - { - struct interface *direct = NULL; - - /* IPv4 nexthop. */ - ret = if_get_ipv4_address(ifp, &nexthop->v4); - if (!ret && peer->local_id.s_addr) - nexthop->v4 = peer->local_id; - - /* Global address*/ - if (! IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr)) - { - memcpy (&nexthop->v6_global, &local->sin6.sin6_addr, - IPV6_MAX_BYTELEN); - - /* If directory connected set link-local address. */ - direct = if_lookup_by_ipv6 (&remote->sin6.sin6_addr, - remote->sin6.sin6_scope_id, peer->bgp->vrf_id); - if (direct) - if_get_ipv6_local (ifp, &nexthop->v6_local); + if (local->sa.sa_family == AF_INET6) { + if (IN6_IS_ADDR_LINKLOCAL(&local->sin6.sin6_addr)) { + if (peer->conf_if || peer->ifname) + ifp = if_lookup_by_name(peer->conf_if + ? peer->conf_if + : peer->ifname, + peer->bgp->vrf_id); + } else if (peer->update_if) + ifp = if_lookup_by_name(peer->update_if, + peer->bgp->vrf_id); + else + ifp = if_lookup_by_ipv6_exact(&local->sin6.sin6_addr, + local->sin6.sin6_scope_id, + peer->bgp->vrf_id); } - else - /* Link-local address. */ - { - ret = if_get_ipv6_global (ifp, &nexthop->v6_global); - - /* If there is no global address. Set link-local address as - global. I know this break RFC specification... */ - /* In this scenario, the expectation for interop is that the - * network admin would use a route-map to specify the global - * IPv6 nexthop. - */ - if (!ret) - memcpy (&nexthop->v6_global, &local->sin6.sin6_addr, - IPV6_MAX_BYTELEN); - /* Always set the link-local address */ - memcpy (&nexthop->v6_local, &local->sin6.sin6_addr, - IPV6_MAX_BYTELEN); + + if (!ifp) + return -1; + + nexthop->ifp = ifp; + + /* IPv4 connection, fetch and store IPv6 local address(es) if any. */ + if (local->sa.sa_family == AF_INET) { + /* IPv6 nexthop*/ + ret = if_get_ipv6_global(ifp, &nexthop->v6_global); + + if (!ret) { + /* There is no global nexthop. Use link-local address as + * both the + * global and link-local nexthop. In this scenario, the + * expectation + * for interop is that the network admin would use a + * route-map to + * specify the global IPv6 nexthop. + */ + if_get_ipv6_local(ifp, &nexthop->v6_global); + memcpy(&nexthop->v6_local, &nexthop->v6_global, + IPV6_MAX_BYTELEN); + } else + if_get_ipv6_local(ifp, &nexthop->v6_local); + + if (if_lookup_by_ipv4(&remote->sin.sin_addr, peer->bgp->vrf_id)) + peer->shared_network = 1; + else + peer->shared_network = 0; } - if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr) || - if_lookup_by_ipv6 (&remote->sin6.sin6_addr, remote->sin6.sin6_scope_id, - peer->bgp->vrf_id)) - peer->shared_network = 1; - else - peer->shared_network = 0; - } + /* IPv6 connection, fetch and store IPv4 local address if any. */ + if (local->sa.sa_family == AF_INET6) { + struct interface *direct = NULL; + + /* IPv4 nexthop. */ + ret = if_get_ipv4_address(ifp, &nexthop->v4); + if (!ret && peer->local_id.s_addr) + nexthop->v4 = peer->local_id; + + /* Global address*/ + if (!IN6_IS_ADDR_LINKLOCAL(&local->sin6.sin6_addr)) { + memcpy(&nexthop->v6_global, &local->sin6.sin6_addr, + IPV6_MAX_BYTELEN); + + /* If directory connected set link-local address. */ + direct = if_lookup_by_ipv6(&remote->sin6.sin6_addr, + remote->sin6.sin6_scope_id, + peer->bgp->vrf_id); + if (direct) + if_get_ipv6_local(ifp, &nexthop->v6_local); + } else + /* Link-local address. */ + { + ret = if_get_ipv6_global(ifp, &nexthop->v6_global); + + /* If there is no global address. Set link-local + address as + global. I know this break RFC specification... */ + /* In this scenario, the expectation for interop is that + * the + * network admin would use a route-map to specify the + * global + * IPv6 nexthop. + */ + if (!ret) + memcpy(&nexthop->v6_global, + &local->sin6.sin6_addr, + IPV6_MAX_BYTELEN); + /* Always set the link-local address */ + memcpy(&nexthop->v6_local, &local->sin6.sin6_addr, + IPV6_MAX_BYTELEN); + } + + if (IN6_IS_ADDR_LINKLOCAL(&local->sin6.sin6_addr) + || if_lookup_by_ipv6(&remote->sin6.sin6_addr, + remote->sin6.sin6_scope_id, + peer->bgp->vrf_id)) + peer->shared_network = 1; + else + peer->shared_network = 0; + } - /* KAME stack specific treatment. */ +/* KAME stack specific treatment. */ #ifdef KAME - if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_global) - && IN6_LINKLOCAL_IFINDEX (nexthop->v6_global)) - { - SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_global, 0); - } - if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_local) - && IN6_LINKLOCAL_IFINDEX (nexthop->v6_local)) - { - SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_local, 0); - } + if (IN6_IS_ADDR_LINKLOCAL(&nexthop->v6_global) + && IN6_LINKLOCAL_IFINDEX(nexthop->v6_global)) { + SET_IN6_LINKLOCAL_IFINDEX(nexthop->v6_global, 0); + } + if (IN6_IS_ADDR_LINKLOCAL(&nexthop->v6_local) + && IN6_LINKLOCAL_IFINDEX(nexthop->v6_local)) { + SET_IN6_LINKLOCAL_IFINDEX(nexthop->v6_local, 0); + } #endif /* KAME */ - /* If we have identified the local interface, there is no error for now. */ - return 0; + /* If we have identified the local interface, there is no error for now. + */ + return 0; } -static struct in6_addr * -bgp_info_to_ipv6_nexthop (struct bgp_info *info) +static struct in6_addr *bgp_info_to_ipv6_nexthop(struct bgp_info *info) { - struct in6_addr *nexthop = NULL; - - /* Only global address nexthop exists. */ - if (info->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) - nexthop = &info->attr->mp_nexthop_global; - - /* If both global and link-local address present. */ - if (info->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) - { - /* Check if route-map is set to prefer global over link-local */ - if (info->attr->mp_nexthop_prefer_global) - nexthop = &info->attr->mp_nexthop_global; - else - { - /* Workaround for Cisco's nexthop bug. */ - if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->mp_nexthop_global) - && info->peer->su_remote->sa.sa_family == AF_INET6) - nexthop = &info->peer->su_remote->sin6.sin6_addr; - else - nexthop = &info->attr->mp_nexthop_local; - } - } - - return nexthop; + struct in6_addr *nexthop = NULL; + + /* Only global address nexthop exists. */ + if (info->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) + nexthop = &info->attr->mp_nexthop_global; + + /* If both global and link-local address present. */ + if (info->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) { + /* Check if route-map is set to prefer global over link-local */ + if (info->attr->mp_nexthop_prefer_global) + nexthop = &info->attr->mp_nexthop_global; + else { + /* Workaround for Cisco's nexthop bug. */ + if (IN6_IS_ADDR_UNSPECIFIED( + &info->attr->mp_nexthop_global) + && info->peer->su_remote->sa.sa_family == AF_INET6) + nexthop = + &info->peer->su_remote->sin6.sin6_addr; + else + nexthop = &info->attr->mp_nexthop_local; + } + } + + return nexthop; } -static int -bgp_table_map_apply (struct route_map *map, struct prefix *p, - struct bgp_info *info) +static int bgp_table_map_apply(struct route_map *map, struct prefix *p, + struct bgp_info *info) { - if (route_map_apply(map, p, RMAP_BGP, info) != RMAP_DENYMATCH) - return 1; - - if (bgp_debug_zebra(p)) - { - if (p->family == AF_INET) - { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra rmap deny: IPv4 route %s/%d nexthop %s", - inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), - p->prefixlen, - inet_ntop(AF_INET, &info->attr->nexthop, buf[1], - sizeof(buf[1]))); - } - if (p->family == AF_INET6) - { - char buf[2][INET6_ADDRSTRLEN]; - zlog_debug("Zebra rmap deny: IPv6 route %s/%d nexthop %s", - inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), - p->prefixlen, - inet_ntop(AF_INET6, bgp_info_to_ipv6_nexthop(info), buf[1], - sizeof(buf[1]))); - } - } - return 0; + if (route_map_apply(map, p, RMAP_BGP, info) != RMAP_DENYMATCH) + return 1; + + if (bgp_debug_zebra(p)) { + if (p->family == AF_INET) { + char buf[2][INET_ADDRSTRLEN]; + zlog_debug( + "Zebra rmap deny: IPv4 route %s/%d nexthop %s", + inet_ntop(AF_INET, &p->u.prefix4, buf[0], + sizeof(buf[0])), + p->prefixlen, + inet_ntop(AF_INET, &info->attr->nexthop, buf[1], + sizeof(buf[1]))); + } + if (p->family == AF_INET6) { + char buf[2][INET6_ADDRSTRLEN]; + zlog_debug( + "Zebra rmap deny: IPv6 route %s/%d nexthop %s", + inet_ntop(AF_INET6, &p->u.prefix6, buf[0], + sizeof(buf[0])), + p->prefixlen, + inet_ntop(AF_INET6, + bgp_info_to_ipv6_nexthop(info), + buf[1], sizeof(buf[1]))); + } + } + return 0; } -void -bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info, - struct bgp *bgp, afi_t afi, safi_t safi) +void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, + struct bgp_info *info, struct bgp *bgp, afi_t afi, + safi_t safi) { - u_int32_t flags; - u_char distance; - struct peer *peer; - struct bgp_info *mpinfo; - u_int32_t metric; - struct bgp_info local_info; - struct bgp_info *info_cp = &local_info; - route_tag_t tag; - mpls_label_t label; - - /* Don't try to install if we're not connected to Zebra or Zebra doesn't - * know of this instance. - */ - if (!bgp_install_info_to_zebra (bgp)) - return; - - if ((p->family == AF_INET && - !vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_BGP], bgp->vrf_id)) - || (p->family == AF_INET6 && - !vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_BGP], bgp->vrf_id))) - return; - - if (bgp->main_zebra_update_hold) - return; - - flags = 0; - peer = info->peer; - - tag = info->attr->tag; - - /* When we create an aggregate route we must also install a Null0 route in - * the RIB */ - if (info->sub_type == BGP_ROUTE_AGGREGATE) - SET_FLAG (flags, ZEBRA_FLAG_BLACKHOLE); - - if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED || - info->sub_type == BGP_ROUTE_AGGREGATE) - { - SET_FLAG (flags, ZEBRA_FLAG_IBGP); - SET_FLAG (flags, ZEBRA_FLAG_INTERNAL); - } - - if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1) - || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) - || bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) - - SET_FLAG (flags, ZEBRA_FLAG_INTERNAL); - - if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(info->attr)) - { - struct zapi_ipv4 api; - struct in_addr *nexthop; - char buf[2][INET_ADDRSTRLEN]; - int valid_nh_count = 0; - int has_valid_label = 0; - - /* resize nexthop buffer size if necessary */ - stream_reset (bgp_nexthop_buf); - nexthop = NULL; - - stream_reset (bgp_label_buf); - - if (bgp->table_map[afi][safi].name) - BGP_INFO_ATTR_BUF_INIT(); - - /* Metric is currently based on the best-path only */ - metric = info->attr->med; - for (mpinfo = info ; mpinfo; mpinfo = bgp_info_mpath_next (mpinfo)) - { - nexthop = NULL; - - if (bgp->table_map[afi][safi].name) - { - /* Copy info and attributes, so the route-map apply doesn't modify the - BGP route info. */ - BGP_INFO_ATTR_BUF_COPY(mpinfo, info_cp); - if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp)) - { - if (mpinfo == info) - { - /* Metric is currently based on the best-path only */ - metric = info_cp->attr->med; - tag = info_cp->attr->tag; - } - nexthop = &info_cp->attr->nexthop; - } - BGP_INFO_ATTR_BUF_FREE(info_cp); - } - else - nexthop = &mpinfo->attr->nexthop; - - if (nexthop == NULL) - continue; - - stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *)); - if (mpinfo->extra && bgp_is_valid_label(&mpinfo->extra->label)) - { - has_valid_label = 1; - label = label_pton(&mpinfo->extra->label); - stream_put (bgp_label_buf, &label, sizeof (mpls_label_t)); - } - valid_nh_count++; - } - - api.vrf_id = bgp->vrf_id; - api.flags = flags; - api.type = ZEBRA_ROUTE_BGP; - api.instance = 0; - api.message = 0; - api.safi = safi; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - - if (has_valid_label) - SET_FLAG (api.message, ZAPI_MESSAGE_LABEL); - - /* Note that this currently only applies to Null0 routes for aggregates. - * ZEBRA_FLAG_BLACKHOLE signals zapi_ipv4_route to encode a special - * BLACKHOLE nexthop. We want to set api.nexthop_num to zero since we - * do not want to also encode the 0.0.0.0 nexthop for the aggregate route. - */ - if (CHECK_FLAG(flags, ZEBRA_FLAG_BLACKHOLE)) - api.nexthop_num = 0; - else - api.nexthop_num = valid_nh_count; - - api.nexthop = (struct in_addr **)STREAM_DATA (bgp_nexthop_buf); - if (has_valid_label) - { - api.label_num = valid_nh_count; - api.label = (unsigned int *)STREAM_DATA (bgp_label_buf); - } - else - { - api.label_num = 0; - api.label = NULL; - } - api.ifindex_num = 0; - SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); - api.metric = metric; - api.tag = 0; - - if (tag) - { - SET_FLAG (api.message, ZAPI_MESSAGE_TAG); - api.tag = tag; - } - - distance = bgp_distance_apply (p, info, afi, safi, bgp); - if (distance) - { - SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = distance; + u_int32_t flags; + u_char distance; + struct peer *peer; + struct bgp_info *mpinfo; + u_int32_t metric; + struct bgp_info local_info; + struct bgp_info *info_cp = &local_info; + route_tag_t tag; + mpls_label_t label; + + /* Don't try to install if we're not connected to Zebra or Zebra doesn't + * know of this instance. + */ + if (!bgp_install_info_to_zebra(bgp)) + return; + + if ((p->family == AF_INET + && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_BGP], + bgp->vrf_id)) + || (p->family == AF_INET6 + && !vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_BGP], + bgp->vrf_id))) + return; + + if (bgp->main_zebra_update_hold) + return; + + flags = 0; + peer = info->peer; + + tag = info->attr->tag; + + /* When we create an aggregate route we must also install a Null0 route + * in + * the RIB */ + if (info->sub_type == BGP_ROUTE_AGGREGATE) + SET_FLAG(flags, ZEBRA_FLAG_BLACKHOLE); + + if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED + || info->sub_type == BGP_ROUTE_AGGREGATE) { + SET_FLAG(flags, ZEBRA_FLAG_IBGP); + SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); } - if (bgp_debug_zebra(p)) - { - int i; - char label_buf[20]; - zlog_debug("Tx IPv4 route %s VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI - " count %d", (valid_nh_count ? "add":"delete"), - bgp->vrf_id, - inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), - p->prefixlen, api.metric, api.tag, api.nexthop_num); - for (i = 0; i < api.nexthop_num; i++) - { - label_buf[0] = '\0'; - if (has_valid_label) - sprintf(label_buf, "label %u", api.label[i]); - zlog_debug(" nhop [%d]: %s %s", - i+1, - inet_ntop(AF_INET, api.nexthop[i], buf[1], sizeof(buf[1])), - label_buf); - } - } - - zapi_ipv4_route (valid_nh_count ? ZEBRA_IPV4_ROUTE_ADD: ZEBRA_IPV4_ROUTE_DELETE, - zclient, (struct prefix_ipv4 *) p, &api); - } - - /* We have to think about a IPv6 link-local address curse. */ - if (p->family == AF_INET6 || - (p->family == AF_INET && BGP_ATTR_NEXTHOP_AFI_IP6(info->attr))) - { - ifindex_t ifindex; - struct in6_addr *nexthop; - struct zapi_ipv6 api; - int valid_nh_count = 0; - char buf[2][INET6_ADDRSTRLEN]; - int has_valid_label = 0; - - stream_reset (bgp_nexthop_buf); - stream_reset (bgp_ifindices_buf); - stream_reset (bgp_label_buf); - - ifindex = 0; - nexthop = NULL; - - if (bgp->table_map[afi][safi].name) - BGP_INFO_ATTR_BUF_INIT(); - - metric = info->attr->med; - for (mpinfo = info ; mpinfo; mpinfo = bgp_info_mpath_next (mpinfo)) - { - ifindex = 0; - nexthop = NULL; - - if (bgp->table_map[afi][safi].name) - { - /* Copy info and attributes, so the route-map apply doesn't modify the - BGP route info. */ - BGP_INFO_ATTR_BUF_COPY(mpinfo, info_cp); - if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp)) - { - if (mpinfo == info) - { - metric = info_cp->attr->med; - tag = info_cp->attr->tag; - } - nexthop = bgp_info_to_ipv6_nexthop(info_cp); - } - BGP_INFO_ATTR_BUF_FREE(info_cp); - } - else - nexthop = bgp_info_to_ipv6_nexthop(mpinfo); - - if (nexthop == NULL) - continue; - - if ((mpinfo == info) && - mpinfo->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) - if (mpinfo->peer->nexthop.ifp) - ifindex = mpinfo->peer->nexthop.ifp->ifindex; - - if (!ifindex) - { - if (mpinfo->peer->conf_if || mpinfo->peer->ifname) - ifindex = ifname2ifindex (mpinfo->peer->conf_if ? mpinfo->peer->conf_if : mpinfo->peer->ifname, bgp->vrf_id); - else if (mpinfo->peer->nexthop.ifp) - ifindex = mpinfo->peer->nexthop.ifp->ifindex; - } - if (ifindex == 0) - continue; - - stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *)); - stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int)); - - if (mpinfo->extra && bgp_is_valid_label(&mpinfo->extra->label)) - { - has_valid_label = 1; - label = label_pton(&mpinfo->extra->label); - stream_put (bgp_label_buf, &label, sizeof (mpls_label_t)); - } - valid_nh_count++; - } - - /* Make Zebra API structure. */ - api.vrf_id = bgp->vrf_id; - api.flags = flags; - api.type = ZEBRA_ROUTE_BGP; - api.instance = 0; - api.message = 0; - api.safi = safi; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - - if (has_valid_label) - SET_FLAG (api.message, ZAPI_MESSAGE_LABEL); - - /* Note that this currently only applies to Null0 routes for aggregates. - * ZEBRA_FLAG_BLACKHOLE signals zapi_ipv6_route to encode a special - * BLACKHOLE nexthop. We want to set api.nexthop_num to zero since we - * do not want to also encode the :: nexthop for the aggregate route. - */ - if (CHECK_FLAG(flags, ZEBRA_FLAG_BLACKHOLE)) - api.nexthop_num = 0; - else - api.nexthop_num = valid_nh_count; - - api.nexthop = (struct in6_addr **)STREAM_DATA (bgp_nexthop_buf); - SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); - api.ifindex_num = valid_nh_count; - api.ifindex = (ifindex_t *)STREAM_DATA (bgp_ifindices_buf); - if (has_valid_label) - { - api.label_num = valid_nh_count; - api.label = (unsigned int *)STREAM_DATA (bgp_label_buf); - } - else - { - api.label_num = 0; - api.label = NULL; - } - SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); - api.metric = metric; - api.tag = 0; - - if (tag) - { - SET_FLAG (api.message, ZAPI_MESSAGE_TAG); - api.tag = tag; - } - - distance = bgp_distance_apply (p, info, afi, safi, bgp); - if (distance) - { - SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = distance; - } - - if (p->family == AF_INET) - { - if (bgp_debug_zebra(p)) - { - int i; - char label_buf[20]; - zlog_debug("Tx IPv4 route %s VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI, - valid_nh_count ? "add" : "delete", bgp->vrf_id, - inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), - p->prefixlen, api.metric, api.tag); - for (i = 0; i < api.nexthop_num; i++) - { - label_buf[0] = '\0'; - if (has_valid_label) - sprintf(label_buf, "label %u", api.label[i]); - zlog_debug(" nhop [%d]: %s if %s %s", - i+1, - inet_ntop(AF_INET6, api.nexthop[i], buf[1], sizeof(buf[1])), - ifindex2ifname (api.ifindex[i], bgp->vrf_id), - label_buf); - } - } - - if (valid_nh_count) - zapi_ipv4_route_ipv6_nexthop (ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD, - zclient, (struct prefix_ipv4 *) p, - (struct zapi_ipv6 *)&api); - else - zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, - zclient, (struct prefix_ipv4 *) p, (struct zapi_ipv4 *)&api); - } - else - { - if (bgp_debug_zebra(p)) - { - int i; - char label_buf[20]; - zlog_debug("Tx IPv6 route %s VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI, - valid_nh_count ? "add" : "delete", bgp->vrf_id, - inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), - p->prefixlen, api.metric, api.tag); - for (i = 0; i < api.nexthop_num; i++) - { - label_buf[0] = '\0'; - if (has_valid_label) - sprintf(label_buf, "label %u", api.label[i]); - zlog_debug(" nhop [%d]: %s if %s %s", - i+1, - inet_ntop(AF_INET6, api.nexthop[i], buf[1], sizeof(buf[1])), - ifindex2ifname (api.ifindex[i], bgp->vrf_id), - label_buf); - } - } - - zapi_ipv6_route (valid_nh_count ? - ZEBRA_IPV6_ROUTE_ADD : ZEBRA_IPV6_ROUTE_DELETE, - zclient, (struct prefix_ipv6 *) p, NULL, &api); - } - } + if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1) + || CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) + || bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) + + SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); + + if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(info->attr)) { + struct zapi_ipv4 api; + struct in_addr *nexthop; + char buf[2][INET_ADDRSTRLEN]; + int valid_nh_count = 0; + int has_valid_label = 0; + + /* resize nexthop buffer size if necessary */ + stream_reset(bgp_nexthop_buf); + nexthop = NULL; + + stream_reset(bgp_label_buf); + + if (bgp->table_map[afi][safi].name) + BGP_INFO_ATTR_BUF_INIT(); + + /* Metric is currently based on the best-path only */ + metric = info->attr->med; + for (mpinfo = info; mpinfo; + mpinfo = bgp_info_mpath_next(mpinfo)) { + nexthop = NULL; + + if (bgp->table_map[afi][safi].name) { + /* Copy info and attributes, so the route-map + apply doesn't modify the + BGP route info. */ + BGP_INFO_ATTR_BUF_COPY(mpinfo, info_cp); + if (bgp_table_map_apply( + bgp->table_map[afi][safi].map, p, + info_cp)) { + if (mpinfo == info) { + /* Metric is currently based on + * the best-path only */ + metric = info_cp->attr->med; + tag = info_cp->attr->tag; + } + nexthop = &info_cp->attr->nexthop; + } + BGP_INFO_ATTR_BUF_FREE(info_cp); + } else + nexthop = &mpinfo->attr->nexthop; + + if (nexthop == NULL) + continue; + + stream_put(bgp_nexthop_buf, &nexthop, + sizeof(struct in_addr *)); + if (mpinfo->extra + && bgp_is_valid_label(&mpinfo->extra->label)) { + has_valid_label = 1; + label = label_pton(&mpinfo->extra->label); + stream_put(bgp_label_buf, &label, + sizeof(mpls_label_t)); + } + valid_nh_count++; + } + + api.vrf_id = bgp->vrf_id; + api.flags = flags; + api.type = ZEBRA_ROUTE_BGP; + api.instance = 0; + api.message = 0; + api.safi = safi; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + + if (has_valid_label) + SET_FLAG(api.message, ZAPI_MESSAGE_LABEL); + + /* Note that this currently only applies to Null0 routes for + * aggregates. + * ZEBRA_FLAG_BLACKHOLE signals zapi_ipv4_route to encode a + * special + * BLACKHOLE nexthop. We want to set api.nexthop_num to zero + * since we + * do not want to also encode the 0.0.0.0 nexthop for the + * aggregate route. + */ + if (CHECK_FLAG(flags, ZEBRA_FLAG_BLACKHOLE)) + api.nexthop_num = 0; + else + api.nexthop_num = valid_nh_count; + + api.nexthop = (struct in_addr **)STREAM_DATA(bgp_nexthop_buf); + if (has_valid_label) { + api.label_num = valid_nh_count; + api.label = (unsigned int *)STREAM_DATA(bgp_label_buf); + } else { + api.label_num = 0; + api.label = NULL; + } + api.ifindex_num = 0; + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = metric; + api.tag = 0; + + if (tag) { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = tag; + } + + distance = bgp_distance_apply(p, info, afi, safi, bgp); + if (distance) { + SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = distance; + } + + if (bgp_debug_zebra(p)) { + int i; + char label_buf[20]; + zlog_debug( + "Tx IPv4 route %s VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI + " count %d", + (valid_nh_count ? "add" : "delete"), + bgp->vrf_id, inet_ntop(AF_INET, &p->u.prefix4, + buf[0], sizeof(buf[0])), + p->prefixlen, api.metric, api.tag, + api.nexthop_num); + for (i = 0; i < api.nexthop_num; i++) { + label_buf[0] = '\0'; + if (has_valid_label) + sprintf(label_buf, "label %u", + api.label[i]); + zlog_debug(" nhop [%d]: %s %s", i + 1, + inet_ntop(AF_INET, api.nexthop[i], + buf[1], sizeof(buf[1])), + label_buf); + } + } + + zapi_ipv4_route(valid_nh_count ? ZEBRA_IPV4_ROUTE_ADD + : ZEBRA_IPV4_ROUTE_DELETE, + zclient, (struct prefix_ipv4 *)p, &api); + } + + /* We have to think about a IPv6 link-local address curse. */ + if (p->family == AF_INET6 + || (p->family == AF_INET && BGP_ATTR_NEXTHOP_AFI_IP6(info->attr))) { + ifindex_t ifindex; + struct in6_addr *nexthop; + struct zapi_ipv6 api; + int valid_nh_count = 0; + char buf[2][INET6_ADDRSTRLEN]; + int has_valid_label = 0; + + stream_reset(bgp_nexthop_buf); + stream_reset(bgp_ifindices_buf); + stream_reset(bgp_label_buf); + + ifindex = 0; + nexthop = NULL; + + if (bgp->table_map[afi][safi].name) + BGP_INFO_ATTR_BUF_INIT(); + + metric = info->attr->med; + for (mpinfo = info; mpinfo; + mpinfo = bgp_info_mpath_next(mpinfo)) { + ifindex = 0; + nexthop = NULL; + + if (bgp->table_map[afi][safi].name) { + /* Copy info and attributes, so the route-map + apply doesn't modify the + BGP route info. */ + BGP_INFO_ATTR_BUF_COPY(mpinfo, info_cp); + if (bgp_table_map_apply( + bgp->table_map[afi][safi].map, p, + info_cp)) { + if (mpinfo == info) { + metric = info_cp->attr->med; + tag = info_cp->attr->tag; + } + nexthop = bgp_info_to_ipv6_nexthop( + info_cp); + } + BGP_INFO_ATTR_BUF_FREE(info_cp); + } else + nexthop = bgp_info_to_ipv6_nexthop(mpinfo); + + if (nexthop == NULL) + continue; + + if ((mpinfo == info) + && mpinfo->attr->mp_nexthop_len + == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) + if (mpinfo->peer->nexthop.ifp) + ifindex = mpinfo->peer->nexthop.ifp + ->ifindex; + + if (!ifindex) { + if (mpinfo->peer->conf_if + || mpinfo->peer->ifname) + ifindex = ifname2ifindex( + mpinfo->peer->conf_if + ? mpinfo->peer->conf_if + : mpinfo->peer->ifname, + bgp->vrf_id); + else if (mpinfo->peer->nexthop.ifp) + ifindex = mpinfo->peer->nexthop.ifp + ->ifindex; + } + if (ifindex == 0) + continue; + + stream_put(bgp_nexthop_buf, &nexthop, + sizeof(struct in6_addr *)); + stream_put(bgp_ifindices_buf, &ifindex, + sizeof(unsigned int)); + + if (mpinfo->extra + && bgp_is_valid_label(&mpinfo->extra->label)) { + has_valid_label = 1; + label = label_pton(&mpinfo->extra->label); + stream_put(bgp_label_buf, &label, + sizeof(mpls_label_t)); + } + valid_nh_count++; + } + + /* Make Zebra API structure. */ + api.vrf_id = bgp->vrf_id; + api.flags = flags; + api.type = ZEBRA_ROUTE_BGP; + api.instance = 0; + api.message = 0; + api.safi = safi; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + + if (has_valid_label) + SET_FLAG(api.message, ZAPI_MESSAGE_LABEL); + + /* Note that this currently only applies to Null0 routes for + * aggregates. + * ZEBRA_FLAG_BLACKHOLE signals zapi_ipv6_route to encode a + * special + * BLACKHOLE nexthop. We want to set api.nexthop_num to zero + * since we + * do not want to also encode the :: nexthop for the aggregate + * route. + */ + if (CHECK_FLAG(flags, ZEBRA_FLAG_BLACKHOLE)) + api.nexthop_num = 0; + else + api.nexthop_num = valid_nh_count; + + api.nexthop = (struct in6_addr **)STREAM_DATA(bgp_nexthop_buf); + SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); + api.ifindex_num = valid_nh_count; + api.ifindex = (ifindex_t *)STREAM_DATA(bgp_ifindices_buf); + if (has_valid_label) { + api.label_num = valid_nh_count; + api.label = (unsigned int *)STREAM_DATA(bgp_label_buf); + } else { + api.label_num = 0; + api.label = NULL; + } + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = metric; + api.tag = 0; + + if (tag) { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = tag; + } + + distance = bgp_distance_apply(p, info, afi, safi, bgp); + if (distance) { + SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = distance; + } + + if (p->family == AF_INET) { + if (bgp_debug_zebra(p)) { + int i; + char label_buf[20]; + zlog_debug( + "Tx IPv4 route %s VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI, + valid_nh_count ? "add" : "delete", + bgp->vrf_id, + inet_ntop(AF_INET, &p->u.prefix4, + buf[0], sizeof(buf[0])), + p->prefixlen, api.metric, api.tag); + for (i = 0; i < api.nexthop_num; i++) { + label_buf[0] = '\0'; + if (has_valid_label) + sprintf(label_buf, "label %u", + api.label[i]); + zlog_debug( + " nhop [%d]: %s if %s %s", + i + 1, + inet_ntop(AF_INET6, + api.nexthop[i], + buf[1], + sizeof(buf[1])), + ifindex2ifname(api.ifindex[i], + bgp->vrf_id), + label_buf); + } + } + + if (valid_nh_count) + zapi_ipv4_route_ipv6_nexthop( + ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD, + zclient, (struct prefix_ipv4 *)p, + (struct zapi_ipv6 *)&api); + else + zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, + zclient, + (struct prefix_ipv4 *)p, + (struct zapi_ipv4 *)&api); + } else { + if (bgp_debug_zebra(p)) { + int i; + char label_buf[20]; + zlog_debug( + "Tx IPv6 route %s VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI, + valid_nh_count ? "add" : "delete", + bgp->vrf_id, + inet_ntop(AF_INET6, &p->u.prefix6, + buf[0], sizeof(buf[0])), + p->prefixlen, api.metric, api.tag); + for (i = 0; i < api.nexthop_num; i++) { + label_buf[0] = '\0'; + if (has_valid_label) + sprintf(label_buf, "label %u", + api.label[i]); + zlog_debug( + " nhop [%d]: %s if %s %s", + i + 1, + inet_ntop(AF_INET6, + api.nexthop[i], + buf[1], + sizeof(buf[1])), + ifindex2ifname(api.ifindex[i], + bgp->vrf_id), + label_buf); + } + } + + zapi_ipv6_route( + valid_nh_count ? ZEBRA_IPV6_ROUTE_ADD + : ZEBRA_IPV6_ROUTE_DELETE, + zclient, (struct prefix_ipv6 *)p, NULL, &api); + } + } } /* Announce all routes of a table to zebra */ -void -bgp_zebra_announce_table (struct bgp *bgp, afi_t afi, safi_t safi) +void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi) { - struct bgp_node *rn; - struct bgp_table *table; - struct bgp_info *ri; - - /* Don't try to install if we're not connected to Zebra or Zebra doesn't - * know of this instance. - */ - if (!bgp_install_info_to_zebra (bgp)) - return; - - table = bgp->rib[afi][safi]; - if (!table) return; - - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - for (ri = rn->info; ri; ri = ri->next) - if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) - && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_NORMAL) - bgp_zebra_announce (rn, &rn->p, ri, bgp, afi, safi); + struct bgp_node *rn; + struct bgp_table *table; + struct bgp_info *ri; + + /* Don't try to install if we're not connected to Zebra or Zebra doesn't + * know of this instance. + */ + if (!bgp_install_info_to_zebra(bgp)) + return; + + table = bgp->rib[afi][safi]; + if (!table) + return; + + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) + for (ri = rn->info; ri; ri = ri->next) + if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED) + && ri->type == ZEBRA_ROUTE_BGP + && ri->sub_type == BGP_ROUTE_NORMAL) + bgp_zebra_announce(rn, &rn->p, ri, bgp, afi, + safi); } -void -bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi) +void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi) { - u_int32_t flags; - struct peer *peer; - - peer = info->peer; - assert(peer); - - /* Don't try to install if we're not connected to Zebra or Zebra doesn't - * know of this instance. - */ - if (!bgp_install_info_to_zebra (peer->bgp)) - return; - - if ((p->family == AF_INET && - !vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_BGP], peer->bgp->vrf_id)) - || (p->family == AF_INET6 && - !vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_BGP], peer->bgp->vrf_id))) - return; - - flags = 0; - - if (peer->sort == BGP_PEER_IBGP) - { - SET_FLAG (flags, ZEBRA_FLAG_INTERNAL); - SET_FLAG (flags, ZEBRA_FLAG_IBGP); - } - - if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1) - || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) - || bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) - SET_FLAG (flags, ZEBRA_FLAG_INTERNAL); - - if (p->family == AF_INET) - { - struct zapi_ipv4 api; - - api.vrf_id = peer->bgp->vrf_id; - api.flags = flags; - - api.type = ZEBRA_ROUTE_BGP; - api.instance = 0; - api.message = 0; - api.safi = safi; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.nexthop = NULL; - api.label_num = 0; - api.label = NULL; - api.ifindex_num = 0; - SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); - api.metric = info->attr->med; - api.tag = 0; - - if (info->attr->tag != 0) - { - SET_FLAG(api.message, ZAPI_MESSAGE_TAG); - api.tag = info->attr->tag; - } - - if (bgp_debug_zebra(p)) - { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Tx IPv4 route delete VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI, - peer->bgp->vrf_id, - inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), - p->prefixlen, api.metric, api.tag); + u_int32_t flags; + struct peer *peer; + + peer = info->peer; + assert(peer); + + /* Don't try to install if we're not connected to Zebra or Zebra doesn't + * know of this instance. + */ + if (!bgp_install_info_to_zebra(peer->bgp)) + return; + + if ((p->family == AF_INET + && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_BGP], + peer->bgp->vrf_id)) + || (p->family == AF_INET6 + && !vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_BGP], + peer->bgp->vrf_id))) + return; + + flags = 0; + + if (peer->sort == BGP_PEER_IBGP) { + SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); + SET_FLAG(flags, ZEBRA_FLAG_IBGP); } - zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, - (struct prefix_ipv4 *) p, &api); - } - /* We have to think about a IPv6 link-local address curse. */ - if (p->family == AF_INET6) - { - struct zapi_ipv6 api; - - api.vrf_id = peer->bgp->vrf_id; - api.flags = flags; - api.type = ZEBRA_ROUTE_BGP; - api.instance = 0; - api.message = 0; - api.safi = safi; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.nexthop = NULL; - api.ifindex_num = 0; - api.label_num = 0; - SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); - api.metric = info->attr->med; - api.tag = 0; - - if (info->attr->tag != 0) - { - SET_FLAG(api.message, ZAPI_MESSAGE_TAG); - api.tag = info->attr->tag; - } - - if (bgp_debug_zebra(p)) - { - char buf[2][INET6_ADDRSTRLEN]; - zlog_debug("Tx IPv6 route delete VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI, - peer->bgp->vrf_id, - inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), - p->prefixlen, api.metric, api.tag); + if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1) + || CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) + || bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) + SET_FLAG(flags, ZEBRA_FLAG_INTERNAL); + + if (p->family == AF_INET) { + struct zapi_ipv4 api; + + api.vrf_id = peer->bgp->vrf_id; + api.flags = flags; + + api.type = ZEBRA_ROUTE_BGP; + api.instance = 0; + api.message = 0; + api.safi = safi; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = 0; + api.nexthop = NULL; + api.label_num = 0; + api.label = NULL; + api.ifindex_num = 0; + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = info->attr->med; + api.tag = 0; + + if (info->attr->tag != 0) { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = info->attr->tag; + } + + if (bgp_debug_zebra(p)) { + char buf[2][INET_ADDRSTRLEN]; + zlog_debug( + "Tx IPv4 route delete VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI, + peer->bgp->vrf_id, + inet_ntop(AF_INET, &p->u.prefix4, buf[0], + sizeof(buf[0])), + p->prefixlen, api.metric, api.tag); + } + + zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, + (struct prefix_ipv4 *)p, &api); + } + /* We have to think about a IPv6 link-local address curse. */ + if (p->family == AF_INET6) { + struct zapi_ipv6 api; + + api.vrf_id = peer->bgp->vrf_id; + api.flags = flags; + api.type = ZEBRA_ROUTE_BGP; + api.instance = 0; + api.message = 0; + api.safi = safi; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = 0; + api.nexthop = NULL; + api.ifindex_num = 0; + api.label_num = 0; + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = info->attr->med; + api.tag = 0; + + if (info->attr->tag != 0) { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = info->attr->tag; + } + + if (bgp_debug_zebra(p)) { + char buf[2][INET6_ADDRSTRLEN]; + zlog_debug( + "Tx IPv6 route delete VRF %u %s/%d metric %u tag %" ROUTE_TAG_PRI, + peer->bgp->vrf_id, + inet_ntop(AF_INET6, &p->u.prefix6, buf[0], + sizeof(buf[0])), + p->prefixlen, api.metric, api.tag); + } + + zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, + (struct prefix_ipv6 *)p, NULL, &api); } - - zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, - (struct prefix_ipv6 *) p, NULL, &api); - } } -struct bgp_redist * -bgp_redist_lookup (struct bgp *bgp, afi_t afi, u_char type, u_short instance) +struct bgp_redist *bgp_redist_lookup(struct bgp *bgp, afi_t afi, u_char type, + u_short instance) { - struct list *red_list; - struct listnode *node; - struct bgp_redist *red; + struct list *red_list; + struct listnode *node; + struct bgp_redist *red; - red_list = bgp->redist[afi][type]; - if (!red_list) - return(NULL); + red_list = bgp->redist[afi][type]; + if (!red_list) + return (NULL); - for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) - if (red->instance == instance) - return red; + for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) + if (red->instance == instance) + return red; - return NULL; + return NULL; } -struct bgp_redist * -bgp_redist_add (struct bgp *bgp, afi_t afi, u_char type, u_short instance) +struct bgp_redist *bgp_redist_add(struct bgp *bgp, afi_t afi, u_char type, + u_short instance) { - struct list *red_list; - struct bgp_redist *red; + struct list *red_list; + struct bgp_redist *red; - red = bgp_redist_lookup(bgp, afi, type, instance); - if (red) - return red; + red = bgp_redist_lookup(bgp, afi, type, instance); + if (red) + return red; - if (!bgp->redist[afi][type]) - bgp->redist[afi][type] = list_new(); + if (!bgp->redist[afi][type]) + bgp->redist[afi][type] = list_new(); - red_list = bgp->redist[afi][type]; - red = (struct bgp_redist *)XCALLOC(MTYPE_BGP_REDIST, sizeof(struct bgp_redist)); - red->instance = instance; + red_list = bgp->redist[afi][type]; + red = (struct bgp_redist *)XCALLOC(MTYPE_BGP_REDIST, + sizeof(struct bgp_redist)); + red->instance = instance; - listnode_add(red_list, red); + listnode_add(red_list, red); - return red; + return red; } -static void -bgp_redist_del (struct bgp *bgp, afi_t afi, u_char type, u_short instance) +static void bgp_redist_del(struct bgp *bgp, afi_t afi, u_char type, + u_short instance) { - struct bgp_redist *red; - - red = bgp_redist_lookup(bgp, afi, type, instance); - - if (red) - { - listnode_delete(bgp->redist[afi][type], red); - XFREE (MTYPE_BGP_REDIST, red); - if (!bgp->redist[afi][type]->count) - { - list_free(bgp->redist[afi][type]); - bgp->redist[afi][type] = NULL; - } - } + struct bgp_redist *red; + + red = bgp_redist_lookup(bgp, afi, type, instance); + + if (red) { + listnode_delete(bgp->redist[afi][type], red); + XFREE(MTYPE_BGP_REDIST, red); + if (!bgp->redist[afi][type]->count) { + list_free(bgp->redist[afi][type]); + bgp->redist[afi][type] = NULL; + } + } } /* Other routes redistribution into BGP. */ -int -bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type, u_short instance) +int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type, u_short instance) { - /* Return if already redistribute flag is set. */ - if (instance) - { - if (redist_check_instance(&zclient->mi_redist[afi][type], instance)) - return CMD_WARNING; + /* Return if already redistribute flag is set. */ + if (instance) { + if (redist_check_instance(&zclient->mi_redist[afi][type], + instance)) + return CMD_WARNING; - redist_add_instance(&zclient->mi_redist[afi][type], instance); - } - else - { - if (vrf_bitmap_check (zclient->redist[afi][type], bgp->vrf_id)) - return CMD_WARNING; + redist_add_instance(&zclient->mi_redist[afi][type], instance); + } else { + if (vrf_bitmap_check(zclient->redist[afi][type], bgp->vrf_id)) + return CMD_WARNING; #if ENABLE_BGP_VNC - if (bgp->vrf_id == VRF_DEFAULT && - type == ZEBRA_ROUTE_VNC_DIRECT) { - vnc_export_bgp_enable(bgp, afi); /* only enables if mode bits cfg'd */ - } + if (bgp->vrf_id == VRF_DEFAULT + && type == ZEBRA_ROUTE_VNC_DIRECT) { + vnc_export_bgp_enable( + bgp, afi); /* only enables if mode bits cfg'd */ + } #endif - vrf_bitmap_set (zclient->redist[afi][type], bgp->vrf_id); - } + vrf_bitmap_set(zclient->redist[afi][type], bgp->vrf_id); + } - /* Don't try to register if we're not connected to Zebra or Zebra doesn't - * know of this instance. - */ - if (!bgp_install_info_to_zebra (bgp)) - return CMD_WARNING_CONFIG_FAILED; + /* Don't try to register if we're not connected to Zebra or Zebra + * doesn't + * know of this instance. + */ + if (!bgp_install_info_to_zebra(bgp)) + return CMD_WARNING_CONFIG_FAILED; - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Tx redistribute add VRF %u afi %d %s %d", - bgp->vrf_id, afi, - zebra_route_string(type), instance); + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Tx redistribute add VRF %u afi %d %s %d", + bgp->vrf_id, afi, zebra_route_string(type), + instance); - /* Send distribute add message to zebra. */ - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type, - instance, bgp->vrf_id); + /* Send distribute add message to zebra. */ + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type, + instance, bgp->vrf_id); - return CMD_SUCCESS; + return CMD_SUCCESS; } -int -bgp_redistribute_resend (struct bgp *bgp, afi_t afi, int type, u_short instance) +int bgp_redistribute_resend(struct bgp *bgp, afi_t afi, int type, + u_short instance) { - /* Don't try to send if we're not connected to Zebra or Zebra doesn't - * know of this instance. - */ - if (!bgp_install_info_to_zebra (bgp)) - return -1; - - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Tx redistribute del/add VRF %u afi %d %s %d", - bgp->vrf_id, afi, - zebra_route_string(type), instance); - - /* Send distribute add message to zebra. */ - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, type, - instance, bgp->vrf_id); - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type, - instance, bgp->vrf_id); - - return 0; + /* Don't try to send if we're not connected to Zebra or Zebra doesn't + * know of this instance. + */ + if (!bgp_install_info_to_zebra(bgp)) + return -1; + + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Tx redistribute del/add VRF %u afi %d %s %d", + bgp->vrf_id, afi, zebra_route_string(type), + instance); + + /* Send distribute add message to zebra. */ + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, type, + instance, bgp->vrf_id); + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type, + instance, bgp->vrf_id); + + return 0; } /* Redistribute with route-map specification. */ -int -bgp_redistribute_rmap_set (struct bgp_redist *red, const char *name) +int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name) { - if (red->rmap.name - && (strcmp (red->rmap.name, name) == 0)) - return 0; + if (red->rmap.name && (strcmp(red->rmap.name, name) == 0)) + return 0; - if (red->rmap.name) - XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name); - red->rmap.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name); - red->rmap.map = route_map_lookup_by_name (name); + if (red->rmap.name) + XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name); + red->rmap.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name); + red->rmap.map = route_map_lookup_by_name(name); - return 1; + return 1; } /* Redistribute with metric specification. */ -int -bgp_redistribute_metric_set (struct bgp *bgp, struct bgp_redist *red, afi_t afi, - int type, u_int32_t metric) +int bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red, + afi_t afi, int type, u_int32_t metric) { - struct bgp_node *rn; - struct bgp_info *ri; - - if (red->redist_metric_flag - && red->redist_metric == metric) - return 0; - - red->redist_metric_flag = 1; - red->redist_metric = metric; - - for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn; rn = bgp_route_next(rn)) - { - for (ri = rn->info; ri; ri = ri->next) - { - if (ri->sub_type == BGP_ROUTE_REDISTRIBUTE && - ri->type == type && - ri->instance == red->instance) - { - struct attr *old_attr; - struct attr new_attr; - - bgp_attr_dup (&new_attr, ri->attr); - new_attr.med = red->redist_metric; - old_attr = ri->attr; - ri->attr = bgp_attr_intern (&new_attr); - bgp_attr_unintern (&old_attr); - - bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED); - bgp_process(bgp, rn, afi, SAFI_UNICAST); - } - } - } - - return 1; + struct bgp_node *rn; + struct bgp_info *ri; + + if (red->redist_metric_flag && red->redist_metric == metric) + return 0; + + red->redist_metric_flag = 1; + red->redist_metric = metric; + + for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn; + rn = bgp_route_next(rn)) { + for (ri = rn->info; ri; ri = ri->next) { + if (ri->sub_type == BGP_ROUTE_REDISTRIBUTE + && ri->type == type + && ri->instance == red->instance) { + struct attr *old_attr; + struct attr new_attr; + + bgp_attr_dup(&new_attr, ri->attr); + new_attr.med = red->redist_metric; + old_attr = ri->attr; + ri->attr = bgp_attr_intern(&new_attr); + bgp_attr_unintern(&old_attr); + + bgp_info_set_flag(rn, ri, + BGP_INFO_ATTR_CHANGED); + bgp_process(bgp, rn, afi, SAFI_UNICAST); + } + } + } + + return 1; } /* Unset redistribution. */ -int -bgp_redistribute_unreg (struct bgp *bgp, afi_t afi, int type, u_short instance) +int bgp_redistribute_unreg(struct bgp *bgp, afi_t afi, int type, + u_short instance) { - struct bgp_redist *red; - - red = bgp_redist_lookup(bgp, afi, type, instance); - if (!red) - return CMD_SUCCESS; - - /* Return if zebra connection is disabled. */ - if (instance) - { - if (!redist_check_instance(&zclient->mi_redist[afi][type], instance)) - return CMD_WARNING; - redist_del_instance(&zclient->mi_redist[afi][type], instance); - } - else - { - if (! vrf_bitmap_check (zclient->redist[afi][type], bgp->vrf_id)) - return CMD_WARNING; - vrf_bitmap_unset (zclient->redist[afi][type], bgp->vrf_id); - } + struct bgp_redist *red; + + red = bgp_redist_lookup(bgp, afi, type, instance); + if (!red) + return CMD_SUCCESS; + + /* Return if zebra connection is disabled. */ + if (instance) { + if (!redist_check_instance(&zclient->mi_redist[afi][type], + instance)) + return CMD_WARNING; + redist_del_instance(&zclient->mi_redist[afi][type], instance); + } else { + if (!vrf_bitmap_check(zclient->redist[afi][type], bgp->vrf_id)) + return CMD_WARNING; + vrf_bitmap_unset(zclient->redist[afi][type], bgp->vrf_id); + } #if ENABLE_BGP_VNC - if (bgp->vrf_id == VRF_DEFAULT && - type == ZEBRA_ROUTE_VNC_DIRECT) { - vnc_export_bgp_disable(bgp, afi); - } + if (bgp->vrf_id == VRF_DEFAULT && type == ZEBRA_ROUTE_VNC_DIRECT) { + vnc_export_bgp_disable(bgp, afi); + } #endif - if (bgp_install_info_to_zebra (bgp)) - { - /* Send distribute delete message to zebra. */ - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Tx redistribute del VRF %u afi %d %s %d", - bgp->vrf_id, afi, zebra_route_string(type), instance); - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, type, instance, - bgp->vrf_id); - } - - /* Withdraw redistributed routes from current BGP's routing table. */ - bgp_redistribute_withdraw (bgp, afi, type, instance); - - return CMD_SUCCESS; + if (bgp_install_info_to_zebra(bgp)) { + /* Send distribute delete message to zebra. */ + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Tx redistribute del VRF %u afi %d %s %d", + bgp->vrf_id, afi, zebra_route_string(type), + instance); + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, + type, instance, bgp->vrf_id); + } + + /* Withdraw redistributed routes from current BGP's routing table. */ + bgp_redistribute_withdraw(bgp, afi, type, instance); + + return CMD_SUCCESS; } /* Unset redistribution. */ -int -bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type, u_short instance) +int bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type, + u_short instance) { - struct bgp_redist *red; + struct bgp_redist *red; - red = bgp_redist_lookup(bgp, afi, type, instance); - if (!red) - return CMD_SUCCESS; + red = bgp_redist_lookup(bgp, afi, type, instance); + if (!red) + return CMD_SUCCESS; - bgp_redistribute_unreg(bgp, afi, type, instance); + bgp_redistribute_unreg(bgp, afi, type, instance); - /* Unset route-map. */ - if (red->rmap.name) - XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name); - red->rmap.name = NULL; - red->rmap.map = NULL; + /* Unset route-map. */ + if (red->rmap.name) + XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name); + red->rmap.name = NULL; + red->rmap.map = NULL; - /* Unset metric. */ - red->redist_metric_flag = 0; - red->redist_metric = 0; + /* Unset metric. */ + red->redist_metric_flag = 0; + red->redist_metric = 0; - bgp_redist_del(bgp, afi, type, instance); + bgp_redist_del(bgp, afi, type, instance); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Update redistribute vrf bitmap during triggers like restart networking or delete/add VRFs */ -void -bgp_update_redist_vrf_bitmaps (struct bgp *bgp, vrf_id_t old_vrf_id) +void bgp_update_redist_vrf_bitmaps(struct bgp *bgp, vrf_id_t old_vrf_id) { - int i; - afi_t afi; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (vrf_bitmap_check (zclient->redist[afi][i], old_vrf_id)) - { - vrf_bitmap_unset (zclient->redist[afi][i], old_vrf_id); - vrf_bitmap_set (zclient->redist[afi][i], bgp->vrf_id); - } - return; + int i; + afi_t afi; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (vrf_bitmap_check(zclient->redist[afi][i], + old_vrf_id)) { + vrf_bitmap_unset(zclient->redist[afi][i], + old_vrf_id); + vrf_bitmap_set(zclient->redist[afi][i], + bgp->vrf_id); + } + return; } -void -bgp_zclient_reset (void) +void bgp_zclient_reset(void) { - zclient_reset (zclient); + zclient_reset(zclient); } /* Register this instance with Zebra. Invoked upon connect (for * default instance) and when other VRFs are learnt (or created and * already learnt). */ -void -bgp_zebra_instance_register (struct bgp *bgp) +void bgp_zebra_instance_register(struct bgp *bgp) { - /* Don't try to register if we're not connected to Zebra */ - if (!zclient || zclient->sock < 0) - return; + /* Don't try to register if we're not connected to Zebra */ + if (!zclient || zclient->sock < 0) + return; - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Registering VRF %u", bgp->vrf_id); + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Registering VRF %u", bgp->vrf_id); - /* Register for router-id, interfaces, redistributed routes. */ - zclient_send_reg_requests (zclient, bgp->vrf_id); + /* Register for router-id, interfaces, redistributed routes. */ + zclient_send_reg_requests(zclient, bgp->vrf_id); - /* For default instance, register to learn about VNIs, if appropriate. */ - if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT - && bgp->advertise_all_vni) - bgp_zebra_advertise_all_vni (bgp, 1); + /* For default instance, register to learn about VNIs, if appropriate. + */ + if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT + && bgp->advertise_all_vni) + bgp_zebra_advertise_all_vni(bgp, 1); } /* Deregister this instance with Zebra. Invoked upon the instance * being deleted (default or VRF) and it is already registered. */ -void -bgp_zebra_instance_deregister (struct bgp *bgp) +void bgp_zebra_instance_deregister(struct bgp *bgp) { - /* Don't try to deregister if we're not connected to Zebra */ - if (zclient->sock < 0) - return; + /* Don't try to deregister if we're not connected to Zebra */ + if (zclient->sock < 0) + return; - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Deregistering VRF %u", bgp->vrf_id); + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Deregistering VRF %u", bgp->vrf_id); - /* For default instance, unregister learning about VNIs, if appropriate. */ - if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT - && bgp->advertise_all_vni) - bgp_zebra_advertise_all_vni (bgp, 0); + /* For default instance, unregister learning about VNIs, if appropriate. + */ + if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT + && bgp->advertise_all_vni) + bgp_zebra_advertise_all_vni(bgp, 0); - /* Deregister for router-id, interfaces, redistributed routes. */ - zclient_send_dereg_requests (zclient, bgp->vrf_id); + /* Deregister for router-id, interfaces, redistributed routes. */ + zclient_send_dereg_requests(zclient, bgp->vrf_id); } -void -bgp_zebra_initiate_radv (struct bgp *bgp, struct peer *peer) +void bgp_zebra_initiate_radv(struct bgp *bgp, struct peer *peer) { - int ra_interval = BGP_UNNUM_DEFAULT_RA_INTERVAL; + int ra_interval = BGP_UNNUM_DEFAULT_RA_INTERVAL; - /* Don't try to initiate if we're not connected to Zebra */ - if (zclient->sock < 0) - return; + /* Don't try to initiate if we're not connected to Zebra */ + if (zclient->sock < 0) + return; - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("%u: Initiating RA for peer %s", bgp->vrf_id, peer->host); + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("%u: Initiating RA for peer %s", bgp->vrf_id, + peer->host); - zclient_send_interface_radv_req (zclient, bgp->vrf_id, peer->ifp, 1, ra_interval); + zclient_send_interface_radv_req(zclient, bgp->vrf_id, peer->ifp, 1, + ra_interval); } -void -bgp_zebra_terminate_radv (struct bgp *bgp, struct peer *peer) +void bgp_zebra_terminate_radv(struct bgp *bgp, struct peer *peer) { - /* Don't try to terminate if we're not connected to Zebra */ - if (zclient->sock < 0) - return; + /* Don't try to terminate if we're not connected to Zebra */ + if (zclient->sock < 0) + return; - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("%u: Terminating RA for peer %s", bgp->vrf_id, peer->host); + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("%u: Terminating RA for peer %s", bgp->vrf_id, + peer->host); - zclient_send_interface_radv_req (zclient, bgp->vrf_id, peer->ifp, 0, 0); + zclient_send_interface_radv_req(zclient, bgp->vrf_id, peer->ifp, 0, 0); } -int -bgp_zebra_advertise_all_vni (struct bgp *bgp, int advertise) +int bgp_zebra_advertise_all_vni(struct bgp *bgp, int advertise) { - struct stream *s; + struct stream *s; - /* Check socket. */ - if (!zclient || zclient->sock < 0) - return 0; + /* Check socket. */ + if (!zclient || zclient->sock < 0) + return 0; - /* Don't try to register if Zebra doesn't know of this instance. */ - if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) - return 0; + /* Don't try to register if Zebra doesn't know of this instance. */ + if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + return 0; - s = zclient->obuf; - stream_reset (s); + s = zclient->obuf; + stream_reset(s); - zclient_create_header (s, ZEBRA_ADVERTISE_ALL_VNI, bgp->vrf_id); - stream_putc(s, advertise); - stream_putw_at (s, 0, stream_get_endp (s)); + zclient_create_header(s, ZEBRA_ADVERTISE_ALL_VNI, bgp->vrf_id); + stream_putc(s, advertise); + stream_putw_at(s, 0, stream_get_endp(s)); - return zclient_send_message(zclient); + return zclient_send_message(zclient); } /* BGP has established connection with Zebra. */ -static void -bgp_zebra_connected (struct zclient *zclient) +static void bgp_zebra_connected(struct zclient *zclient) { - struct bgp *bgp; + struct bgp *bgp; - zclient_num_connects++; /* increment even if not responding */ + zclient_num_connects++; /* increment even if not responding */ - /* At this point, we may or may not have BGP instances configured, but - * we're only interested in the default VRF (others wouldn't have learnt - * the VRF from Zebra yet.) - */ - bgp = bgp_get_default(); - if (!bgp) - return; + /* At this point, we may or may not have BGP instances configured, but + * we're only interested in the default VRF (others wouldn't have learnt + * the VRF from Zebra yet.) + */ + bgp = bgp_get_default(); + if (!bgp) + return; - bgp_zebra_instance_register (bgp); + bgp_zebra_instance_register(bgp); - /* Send the client registration */ - bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); + /* Send the client registration */ + bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); - /* TODO - What if we have peers and networks configured, do we have to - * kick-start them? - */ + /* TODO - What if we have peers and networks configured, do we have to + * kick-start them? + */ } -static int -bgp_zebra_process_local_vni (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int bgp_zebra_process_local_vni(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - vni_t vni; - struct bgp *bgp; - struct in_addr vtep_ip; - - s = zclient->ibuf; - vni = stream_getl (s); - if (command == ZEBRA_VNI_ADD) - vtep_ip.s_addr = stream_get_ipv4 (s); - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; - - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug("Rx VNI %s VRF %u VNI %u", - (command == ZEBRA_VNI_ADD) ? "add" : "del", vrf_id, vni); - - if (command == ZEBRA_VNI_ADD) - return bgp_evpn_local_vni_add (bgp, vni, vtep_ip.s_addr? vtep_ip : bgp->router_id); - else - return bgp_evpn_local_vni_del (bgp, vni); + struct stream *s; + vni_t vni; + struct bgp *bgp; + struct in_addr vtep_ip; + + s = zclient->ibuf; + vni = stream_getl(s); + if (command == ZEBRA_VNI_ADD) + vtep_ip.s_addr = stream_get_ipv4(s); + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) + return 0; + + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Rx VNI %s VRF %u VNI %u", + (command == ZEBRA_VNI_ADD) ? "add" : "del", vrf_id, + vni); + + if (command == ZEBRA_VNI_ADD) + return bgp_evpn_local_vni_add( + bgp, vni, vtep_ip.s_addr ? vtep_ip : bgp->router_id); + else + return bgp_evpn_local_vni_del(bgp, vni); } -static int -bgp_zebra_process_local_macip (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int bgp_zebra_process_local_macip(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - vni_t vni; - struct bgp *bgp; - struct ethaddr mac; - struct ipaddr ip; - int ipa_len; - char buf[ETHER_ADDR_STRLEN]; - char buf1[INET6_ADDRSTRLEN]; - u_char sticky; - - memset (&ip, 0, sizeof (ip)); - s = zclient->ibuf; - vni = stream_getl (s); - stream_get (&mac.octet, s, ETHER_ADDR_LEN); - ipa_len = stream_getl (s); - if (ipa_len != 0 && - ipa_len != IPV4_MAX_BYTELEN && - ipa_len != IPV6_MAX_BYTELEN) - { - zlog_err ("%u:Recv MACIP %s with invalid IP addr length %d", - vrf_id, (command == ZEBRA_MACIP_ADD) ? "Add" : "Del", - ipa_len); - return -1; - } - - if (ipa_len) - { - ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4: IPADDR_V6; - stream_get (&ip.ip.addr, s, ipa_len); - } - sticky = stream_getc (s); - - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (!bgp) - return 0; - - if (BGP_DEBUG (zebra, ZEBRA)) - zlog_debug ("%u:Recv MACIP %s %sMAC %s IP %s VNI %u", - vrf_id, (command == ZEBRA_MACIP_ADD) ? "Add" : "Del", - sticky ? "sticky " : "", - prefix_mac2str (&mac, buf, sizeof (buf)), - ipaddr2str (&ip, buf1, sizeof(buf1)), vni); - - if (command == ZEBRA_MACIP_ADD) - return bgp_evpn_local_macip_add (bgp, vni, &mac, &ip, sticky); - else - return bgp_evpn_local_macip_del (bgp, vni, &mac, &ip); + struct stream *s; + vni_t vni; + struct bgp *bgp; + struct ethaddr mac; + struct ipaddr ip; + int ipa_len; + char buf[ETHER_ADDR_STRLEN]; + char buf1[INET6_ADDRSTRLEN]; + u_char sticky; + + memset(&ip, 0, sizeof(ip)); + s = zclient->ibuf; + vni = stream_getl(s); + stream_get(&mac.octet, s, ETHER_ADDR_LEN); + ipa_len = stream_getl(s); + if (ipa_len != 0 && ipa_len != IPV4_MAX_BYTELEN + && ipa_len != IPV6_MAX_BYTELEN) { + zlog_err("%u:Recv MACIP %s with invalid IP addr length %d", + vrf_id, (command == ZEBRA_MACIP_ADD) ? "Add" : "Del", + ipa_len); + return -1; + } + + if (ipa_len) { + ip.ipa_type = + (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4 : IPADDR_V6; + stream_get(&ip.ip.addr, s, ipa_len); + } + sticky = stream_getc(s); + + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) + return 0; + + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("%u:Recv MACIP %s %sMAC %s IP %s VNI %u", vrf_id, + (command == ZEBRA_MACIP_ADD) ? "Add" : "Del", + sticky ? "sticky " : "", + prefix_mac2str(&mac, buf, sizeof(buf)), + ipaddr2str(&ip, buf1, sizeof(buf1)), vni); + + if (command == ZEBRA_MACIP_ADD) + return bgp_evpn_local_macip_add(bgp, vni, &mac, &ip, sticky); + else + return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip); } -void -bgp_zebra_init (struct thread_master *master) +void bgp_zebra_init(struct thread_master *master) { - zclient_num_connects = 0; - - /* Set default values. */ - zclient = zclient_new (master); - zclient_init (zclient, ZEBRA_ROUTE_BGP, 0); - zclient->zebra_connected = bgp_zebra_connected; - zclient->router_id_update = bgp_router_id_update; - zclient->interface_add = bgp_interface_add; - zclient->interface_delete = bgp_interface_delete; - zclient->interface_address_add = bgp_interface_address_add; - zclient->interface_address_delete = bgp_interface_address_delete; - zclient->interface_nbr_address_add = bgp_interface_nbr_address_add; - zclient->interface_nbr_address_delete = bgp_interface_nbr_address_delete; - zclient->interface_vrf_update = bgp_interface_vrf_update; - zclient->redistribute_route_ipv4_add = zebra_read_ipv4; - zclient->redistribute_route_ipv4_del = zebra_read_ipv4; - zclient->interface_up = bgp_interface_up; - zclient->interface_down = bgp_interface_down; - zclient->redistribute_route_ipv6_add = zebra_read_ipv6; - zclient->redistribute_route_ipv6_del = zebra_read_ipv6; - zclient->nexthop_update = bgp_read_nexthop_update; - zclient->import_check_update = bgp_read_import_check_update; - zclient->fec_update = bgp_read_fec_update; - zclient->local_vni_add = bgp_zebra_process_local_vni; - zclient->local_vni_del = bgp_zebra_process_local_vni; - zclient->local_macip_add = bgp_zebra_process_local_macip; - zclient->local_macip_del = bgp_zebra_process_local_macip; - - bgp_nexthop_buf = stream_new(multipath_num * sizeof (struct in6_addr)); - bgp_ifindices_buf = stream_new(multipath_num * sizeof (unsigned int)); - bgp_label_buf = stream_new(multipath_num * sizeof (unsigned int)); + zclient_num_connects = 0; + + /* Set default values. */ + zclient = zclient_new(master); + zclient_init(zclient, ZEBRA_ROUTE_BGP, 0); + zclient->zebra_connected = bgp_zebra_connected; + zclient->router_id_update = bgp_router_id_update; + zclient->interface_add = bgp_interface_add; + zclient->interface_delete = bgp_interface_delete; + zclient->interface_address_add = bgp_interface_address_add; + zclient->interface_address_delete = bgp_interface_address_delete; + zclient->interface_nbr_address_add = bgp_interface_nbr_address_add; + zclient->interface_nbr_address_delete = + bgp_interface_nbr_address_delete; + zclient->interface_vrf_update = bgp_interface_vrf_update; + zclient->redistribute_route_ipv4_add = zebra_read_ipv4; + zclient->redistribute_route_ipv4_del = zebra_read_ipv4; + zclient->interface_up = bgp_interface_up; + zclient->interface_down = bgp_interface_down; + zclient->redistribute_route_ipv6_add = zebra_read_ipv6; + zclient->redistribute_route_ipv6_del = zebra_read_ipv6; + zclient->nexthop_update = bgp_read_nexthop_update; + zclient->import_check_update = bgp_read_import_check_update; + zclient->fec_update = bgp_read_fec_update; + zclient->local_vni_add = bgp_zebra_process_local_vni; + zclient->local_vni_del = bgp_zebra_process_local_vni; + zclient->local_macip_add = bgp_zebra_process_local_macip; + zclient->local_macip_del = bgp_zebra_process_local_macip; + + bgp_nexthop_buf = stream_new(multipath_num * sizeof(struct in6_addr)); + bgp_ifindices_buf = stream_new(multipath_num * sizeof(unsigned int)); + bgp_label_buf = stream_new(multipath_num * sizeof(unsigned int)); } -void -bgp_zebra_destroy(void) +void bgp_zebra_destroy(void) { - if (bgp_nexthop_buf) - stream_free (bgp_nexthop_buf); - if (bgp_ifindices_buf) - stream_free (bgp_ifindices_buf); - if (bgp_label_buf) - stream_free (bgp_label_buf); - - if (zclient == NULL) - return; - zclient_stop(zclient); - zclient_free(zclient); - zclient = NULL; + if (bgp_nexthop_buf) + stream_free(bgp_nexthop_buf); + if (bgp_ifindices_buf) + stream_free(bgp_ifindices_buf); + if (bgp_label_buf) + stream_free(bgp_label_buf); + + if (zclient == NULL) + return; + zclient_stop(zclient); + zclient_free(zclient); + zclient = NULL; } -int -bgp_zebra_num_connects(void) +int bgp_zebra_num_connects(void) { - return zclient_num_connects; + return zclient_num_connects; } diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index 7ad1f706d..8e55eb6d8 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -21,40 +21,43 @@ #ifndef _QUAGGA_BGP_ZEBRA_H #define _QUAGGA_BGP_ZEBRA_H -extern void bgp_zebra_init (struct thread_master *master); -extern void bgp_zebra_destroy (void); -extern int bgp_if_update_all (void); -extern int bgp_config_write_maxpaths (struct vty *, struct bgp *, afi_t, - safi_t, int *); -extern int bgp_config_write_redistribute (struct vty *, struct bgp *, afi_t, safi_t, - int *); -extern void bgp_zebra_announce (struct bgp_node *, struct prefix *, - struct bgp_info *, struct bgp *, afi_t, safi_t); -extern void bgp_zebra_announce_table (struct bgp *, afi_t, safi_t); -extern void bgp_zebra_withdraw (struct prefix *, struct bgp_info *, safi_t); - -extern void bgp_zebra_initiate_radv (struct bgp *bgp, struct peer *peer); -extern void bgp_zebra_terminate_radv (struct bgp *bgp, struct peer *peer); - -extern void bgp_zebra_instance_register (struct bgp *); -extern void bgp_zebra_instance_deregister (struct bgp *); - -extern struct bgp_redist *bgp_redist_lookup (struct bgp *, afi_t, u_char, u_short); -extern struct bgp_redist *bgp_redist_add (struct bgp *, afi_t, u_char, u_short); -extern int bgp_redistribute_set (struct bgp *, afi_t, int, u_short); -extern int bgp_redistribute_resend (struct bgp *, afi_t, int, u_short); -extern int bgp_redistribute_rmap_set (struct bgp_redist *, const char *); -extern int bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *, - afi_t, int, u_int32_t); -extern int bgp_redistribute_unset (struct bgp *, afi_t, int, u_short); -extern int bgp_redistribute_unreg (struct bgp *, afi_t, int, u_short); - -extern struct interface *if_lookup_by_ipv4 (struct in_addr *, vrf_id_t); -extern struct interface *if_lookup_by_ipv4_exact (struct in_addr *, vrf_id_t); -extern struct interface *if_lookup_by_ipv6 (struct in6_addr *, ifindex_t, vrf_id_t); -extern struct interface *if_lookup_by_ipv6_exact (struct in6_addr *, ifindex_t, vrf_id_t); - -extern int bgp_zebra_advertise_all_vni (struct bgp *, int); +extern void bgp_zebra_init(struct thread_master *master); +extern void bgp_zebra_destroy(void); +extern int bgp_if_update_all(void); +extern int bgp_config_write_maxpaths(struct vty *, struct bgp *, afi_t, safi_t, + int *); +extern int bgp_config_write_redistribute(struct vty *, struct bgp *, afi_t, + safi_t, int *); +extern void bgp_zebra_announce(struct bgp_node *, struct prefix *, + struct bgp_info *, struct bgp *, afi_t, safi_t); +extern void bgp_zebra_announce_table(struct bgp *, afi_t, safi_t); +extern void bgp_zebra_withdraw(struct prefix *, struct bgp_info *, safi_t); + +extern void bgp_zebra_initiate_radv(struct bgp *bgp, struct peer *peer); +extern void bgp_zebra_terminate_radv(struct bgp *bgp, struct peer *peer); + +extern void bgp_zebra_instance_register(struct bgp *); +extern void bgp_zebra_instance_deregister(struct bgp *); + +extern struct bgp_redist *bgp_redist_lookup(struct bgp *, afi_t, u_char, + u_short); +extern struct bgp_redist *bgp_redist_add(struct bgp *, afi_t, u_char, u_short); +extern int bgp_redistribute_set(struct bgp *, afi_t, int, u_short); +extern int bgp_redistribute_resend(struct bgp *, afi_t, int, u_short); +extern int bgp_redistribute_rmap_set(struct bgp_redist *, const char *); +extern int bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *, afi_t, + int, u_int32_t); +extern int bgp_redistribute_unset(struct bgp *, afi_t, int, u_short); +extern int bgp_redistribute_unreg(struct bgp *, afi_t, int, u_short); + +extern struct interface *if_lookup_by_ipv4(struct in_addr *, vrf_id_t); +extern struct interface *if_lookup_by_ipv4_exact(struct in_addr *, vrf_id_t); +extern struct interface *if_lookup_by_ipv6(struct in6_addr *, ifindex_t, + vrf_id_t); +extern struct interface *if_lookup_by_ipv6_exact(struct in6_addr *, ifindex_t, + vrf_id_t); + +extern int bgp_zebra_advertise_all_vni(struct bgp *, int); extern int bgp_zebra_num_connects(void); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 1b0d78ff9..3453da665 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -93,18 +93,17 @@ struct community_list_handler *bgp_clist; unsigned int multipath_num = MULTIPATH_NUM; -static void bgp_if_finish (struct bgp *bgp); +static void bgp_if_finish(struct bgp *bgp); extern struct zclient *zclient; -void -bgp_session_reset(struct peer *peer) +void bgp_session_reset(struct peer *peer) { - if (peer->doppelganger && (peer->doppelganger->status != Deleted) - && !(CHECK_FLAG(peer->doppelganger->flags, PEER_FLAG_CONFIG_NODE))) - peer_delete(peer->doppelganger); + if (peer->doppelganger && (peer->doppelganger->status != Deleted) + && !(CHECK_FLAG(peer->doppelganger->flags, PEER_FLAG_CONFIG_NODE))) + peer_delete(peer->doppelganger); - BGP_EVENT_ADD (peer, BGP_Stop); + BGP_EVENT_ADD(peer, BGP_Stop); } /* @@ -113,1145 +112,1061 @@ bgp_session_reset(struct peer *peer) * during walk of peer list, we would end up accessing the freed next * node. This function moves the next node along. */ -static void -bgp_session_reset_safe(struct peer *peer, struct listnode **nnode) +static void bgp_session_reset_safe(struct peer *peer, struct listnode **nnode) { - struct listnode *n; - struct peer *npeer; + struct listnode *n; + struct peer *npeer; - n = (nnode) ? *nnode : NULL; - npeer = (n) ? listgetdata(n) : NULL; + n = (nnode) ? *nnode : NULL; + npeer = (n) ? listgetdata(n) : NULL; - if (peer->doppelganger && (peer->doppelganger->status != Deleted) - && !(CHECK_FLAG(peer->doppelganger->flags, PEER_FLAG_CONFIG_NODE))) - { - if (peer->doppelganger == npeer) - /* nnode and *nnode are confirmed to be non-NULL here */ - *nnode = (*nnode)->next; - peer_delete(peer->doppelganger); - } + if (peer->doppelganger && (peer->doppelganger->status != Deleted) + && !(CHECK_FLAG(peer->doppelganger->flags, + PEER_FLAG_CONFIG_NODE))) { + if (peer->doppelganger == npeer) + /* nnode and *nnode are confirmed to be non-NULL here */ + *nnode = (*nnode)->next; + peer_delete(peer->doppelganger); + } - BGP_EVENT_ADD (peer, BGP_Stop); + BGP_EVENT_ADD(peer, BGP_Stop); } /* BGP global flag manipulation. */ -int -bgp_option_set (int flag) -{ - switch (flag) - { - case BGP_OPT_NO_FIB: - case BGP_OPT_MULTIPLE_INSTANCE: - case BGP_OPT_CONFIG_CISCO: - case BGP_OPT_NO_LISTEN: - SET_FLAG (bm->options, flag); - break; - default: - return BGP_ERR_INVALID_FLAG; - } - return 0; -} - -int -bgp_option_unset (int flag) -{ - switch (flag) - { - case BGP_OPT_MULTIPLE_INSTANCE: - if (listcount (bm->bgp) > 1) - return BGP_ERR_MULTIPLE_INSTANCE_USED; - /* Fall through. */ - case BGP_OPT_NO_FIB: - case BGP_OPT_CONFIG_CISCO: - UNSET_FLAG (bm->options, flag); - break; - default: - return BGP_ERR_INVALID_FLAG; - } - return 0; -} - -int -bgp_option_check (int flag) -{ - return CHECK_FLAG (bm->options, flag); +int bgp_option_set(int flag) +{ + switch (flag) { + case BGP_OPT_NO_FIB: + case BGP_OPT_MULTIPLE_INSTANCE: + case BGP_OPT_CONFIG_CISCO: + case BGP_OPT_NO_LISTEN: + SET_FLAG(bm->options, flag); + break; + default: + return BGP_ERR_INVALID_FLAG; + } + return 0; +} + +int bgp_option_unset(int flag) +{ + switch (flag) { + case BGP_OPT_MULTIPLE_INSTANCE: + if (listcount(bm->bgp) > 1) + return BGP_ERR_MULTIPLE_INSTANCE_USED; + /* Fall through. */ + case BGP_OPT_NO_FIB: + case BGP_OPT_CONFIG_CISCO: + UNSET_FLAG(bm->options, flag); + break; + default: + return BGP_ERR_INVALID_FLAG; + } + return 0; +} + +int bgp_option_check(int flag) +{ + return CHECK_FLAG(bm->options, flag); } /* BGP flag manipulation. */ -int -bgp_flag_set (struct bgp *bgp, int flag) +int bgp_flag_set(struct bgp *bgp, int flag) { - SET_FLAG (bgp->flags, flag); - return 0; + SET_FLAG(bgp->flags, flag); + return 0; } -int -bgp_flag_unset (struct bgp *bgp, int flag) +int bgp_flag_unset(struct bgp *bgp, int flag) { - UNSET_FLAG (bgp->flags, flag); - return 0; + UNSET_FLAG(bgp->flags, flag); + return 0; } -int -bgp_flag_check (struct bgp *bgp, int flag) +int bgp_flag_check(struct bgp *bgp, int flag) { - return CHECK_FLAG (bgp->flags, flag); + return CHECK_FLAG(bgp->flags, flag); } /* Internal function to set BGP structure configureation flag. */ -static void -bgp_config_set (struct bgp *bgp, int config) +static void bgp_config_set(struct bgp *bgp, int config) { - SET_FLAG (bgp->config, config); + SET_FLAG(bgp->config, config); } -static void -bgp_config_unset (struct bgp *bgp, int config) +static void bgp_config_unset(struct bgp *bgp, int config) { - UNSET_FLAG (bgp->config, config); + UNSET_FLAG(bgp->config, config); } -static int -bgp_config_check (struct bgp *bgp, int config) +static int bgp_config_check(struct bgp *bgp, int config) { - return CHECK_FLAG (bgp->config, config); + return CHECK_FLAG(bgp->config, config); } /* Set BGP router identifier. */ -static int -bgp_router_id_set (struct bgp *bgp, const struct in_addr *id) +static int bgp_router_id_set(struct bgp *bgp, const struct in_addr *id) { - struct peer *peer; - struct listnode *node, *nnode; + struct peer *peer; + struct listnode *node, *nnode; - if (IPV4_ADDR_SAME (&bgp->router_id, id)) - return 0; + if (IPV4_ADDR_SAME(&bgp->router_id, id)) + return 0; - /* EVPN uses router id in RD, withdraw them */ - if (bgp->advertise_all_vni) - bgp_evpn_handle_router_id_update (bgp, TRUE); + /* EVPN uses router id in RD, withdraw them */ + if (bgp->advertise_all_vni) + bgp_evpn_handle_router_id_update(bgp, TRUE); - IPV4_ADDR_COPY (&bgp->router_id, id); + IPV4_ADDR_COPY(&bgp->router_id, id); - /* Set all peer's local identifier with this value. */ - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - IPV4_ADDR_COPY (&peer->local_id, id); + /* Set all peer's local identifier with this value. */ + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + IPV4_ADDR_COPY(&peer->local_id, id); - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_RID_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - } + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_RID_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } + } - /* EVPN uses router id in RD, update them */ - if (bgp->advertise_all_vni) - bgp_evpn_handle_router_id_update (bgp, FALSE); + /* EVPN uses router id in RD, update them */ + if (bgp->advertise_all_vni) + bgp_evpn_handle_router_id_update(bgp, FALSE); - return 0; + return 0; } -void -bgp_router_id_zebra_bump (vrf_id_t vrf_id, const struct prefix *router_id) +void bgp_router_id_zebra_bump(vrf_id_t vrf_id, const struct prefix *router_id) { - struct listnode *node, *nnode; - struct bgp *bgp; + struct listnode *node, *nnode; + struct bgp *bgp; - if (vrf_id == VRF_DEFAULT) - { - /* Router-id change for default VRF has to also update all views. */ - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - { - if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) - continue; + if (vrf_id == VRF_DEFAULT) { + /* Router-id change for default VRF has to also update all + * views. */ + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) { + if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) + continue; - bgp->router_id_zebra = router_id->u.prefix4; - if (!bgp->router_id_static.s_addr) - bgp_router_id_set (bgp, &router_id->u.prefix4); - } - } - else - { - bgp = bgp_lookup_by_vrf_id (vrf_id); - if (bgp) - { - bgp->router_id_zebra = router_id->u.prefix4; + bgp->router_id_zebra = router_id->u.prefix4; + if (!bgp->router_id_static.s_addr) + bgp_router_id_set(bgp, &router_id->u.prefix4); + } + } else { + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (bgp) { + bgp->router_id_zebra = router_id->u.prefix4; - if (!bgp->router_id_static.s_addr) - bgp_router_id_set (bgp, &router_id->u.prefix4); - } - } + if (!bgp->router_id_static.s_addr) + bgp_router_id_set(bgp, &router_id->u.prefix4); + } + } } -int -bgp_router_id_static_set (struct bgp *bgp, struct in_addr id) +int bgp_router_id_static_set(struct bgp *bgp, struct in_addr id) { - bgp->router_id_static = id; - bgp_router_id_set (bgp, id.s_addr ? &id : &bgp->router_id_zebra); - return 0; + bgp->router_id_static = id; + bgp_router_id_set(bgp, id.s_addr ? &id : &bgp->router_id_zebra); + return 0; } /* BGP's cluster-id control. */ -int -bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id) +int bgp_cluster_id_set(struct bgp *bgp, struct in_addr *cluster_id) { - struct peer *peer; - struct listnode *node, *nnode; + struct peer *peer; + struct listnode *node, *nnode; - if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID) - && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id)) - return 0; + if (bgp_config_check(bgp, BGP_CONFIG_CLUSTER_ID) + && IPV4_ADDR_SAME(&bgp->cluster_id, cluster_id)) + return 0; - IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id); - bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID); + IPV4_ADDR_COPY(&bgp->cluster_id, cluster_id); + bgp_config_set(bgp, BGP_CONFIG_CLUSTER_ID); - /* Clear all IBGP peer. */ - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->sort != BGP_PEER_IBGP) - continue; + /* Clear all IBGP peer. */ + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (peer->sort != BGP_PEER_IBGP) + continue; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_CLID_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - } - return 0; + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_CLID_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } + } + return 0; } -int -bgp_cluster_id_unset (struct bgp *bgp) +int bgp_cluster_id_unset(struct bgp *bgp) { - struct peer *peer; - struct listnode *node, *nnode; + struct peer *peer; + struct listnode *node, *nnode; - if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)) - return 0; + if (!bgp_config_check(bgp, BGP_CONFIG_CLUSTER_ID)) + return 0; - bgp->cluster_id.s_addr = 0; - bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID); + bgp->cluster_id.s_addr = 0; + bgp_config_unset(bgp, BGP_CONFIG_CLUSTER_ID); - /* Clear all IBGP peer. */ - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->sort != BGP_PEER_IBGP) - continue; + /* Clear all IBGP peer. */ + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (peer->sort != BGP_PEER_IBGP) + continue; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_CLID_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - } - return 0; + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_CLID_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } + } + return 0; } /* time_t value that is monotonicly increasing * and uneffected by adjustments to system clock */ -time_t bgp_clock (void) +time_t bgp_clock(void) { - struct timeval tv; + struct timeval tv; - monotime(&tv); - return tv.tv_sec; + monotime(&tv); + return tv.tv_sec; } /* BGP timer configuration. */ -int -bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime) +int bgp_timers_set(struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime) { - bgp->default_keepalive = (keepalive < holdtime / 3 - ? keepalive : holdtime / 3); - bgp->default_holdtime = holdtime; + bgp->default_keepalive = + (keepalive < holdtime / 3 ? keepalive : holdtime / 3); + bgp->default_holdtime = holdtime; - return 0; + return 0; } -int -bgp_timers_unset (struct bgp *bgp) +int bgp_timers_unset(struct bgp *bgp) { - bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE; - bgp->default_holdtime = BGP_DEFAULT_HOLDTIME; + bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE; + bgp->default_holdtime = BGP_DEFAULT_HOLDTIME; - return 0; + return 0; } /* BGP confederation configuration. */ -int -bgp_confederation_id_set (struct bgp *bgp, as_t as) -{ - struct peer *peer; - struct listnode *node, *nnode; - int already_confed; - - if (as == 0) - return BGP_ERR_INVALID_AS; - - /* Remember - were we doing confederation before? */ - already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION); - bgp->confed_id = as; - bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION); - - /* If we were doing confederation already, this is just an external - AS change. Just Reset EBGP sessions, not CONFED sessions. If we - were not doing confederation before, reset all EBGP sessions. */ - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - /* We're looking for peers who's AS is not local or part of our - confederation. */ - if (already_confed) - { - if (peer_sort (peer) == BGP_PEER_EBGP) - { - peer->local_as = as; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset_safe(peer, &nnode); - } - } - else - { - /* Not doign confederation before, so reset every non-local - session */ - if (peer_sort (peer) != BGP_PEER_IBGP) - { - /* Reset the local_as to be our EBGP one */ - if (peer_sort (peer) == BGP_PEER_EBGP) - peer->local_as = as; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset_safe(peer, &nnode); - } - } - } - return 0; -} - -int -bgp_confederation_id_unset (struct bgp *bgp) -{ - struct peer *peer; - struct listnode *node, *nnode; - - bgp->confed_id = 0; - bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION); - - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - /* We're looking for peers who's AS is not local */ - if (peer_sort (peer) != BGP_PEER_IBGP) - { - peer->local_as = bgp->as; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - - else - bgp_session_reset_safe(peer, &nnode); +int bgp_confederation_id_set(struct bgp *bgp, as_t as) +{ + struct peer *peer; + struct listnode *node, *nnode; + int already_confed; + + if (as == 0) + return BGP_ERR_INVALID_AS; + + /* Remember - were we doing confederation before? */ + already_confed = bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION); + bgp->confed_id = as; + bgp_config_set(bgp, BGP_CONFIG_CONFEDERATION); + + /* If we were doing confederation already, this is just an external + AS change. Just Reset EBGP sessions, not CONFED sessions. If we + were not doing confederation before, reset all EBGP sessions. */ + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + /* We're looking for peers who's AS is not local or part of our + confederation. */ + if (already_confed) { + if (peer_sort(peer) == BGP_PEER_EBGP) { + peer->local_as = as; + if (BGP_IS_VALID_STATE_FOR_NOTIF( + peer->status)) { + peer->last_reset = + PEER_DOWN_CONFED_ID_CHANGE; + bgp_notify_send( + peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset_safe(peer, &nnode); + } + } else { + /* Not doign confederation before, so reset every + non-local + session */ + if (peer_sort(peer) != BGP_PEER_IBGP) { + /* Reset the local_as to be our EBGP one */ + if (peer_sort(peer) == BGP_PEER_EBGP) + peer->local_as = as; + if (BGP_IS_VALID_STATE_FOR_NOTIF( + peer->status)) { + peer->last_reset = + PEER_DOWN_CONFED_ID_CHANGE; + bgp_notify_send( + peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset_safe(peer, &nnode); + } + } } - } - return 0; + return 0; } -/* Is an AS part of the confed or not? */ -int -bgp_confederation_peers_check (struct bgp *bgp, as_t as) +int bgp_confederation_id_unset(struct bgp *bgp) { - int i; + struct peer *peer; + struct listnode *node, *nnode; + + bgp->confed_id = 0; + bgp_config_unset(bgp, BGP_CONFIG_CONFEDERATION); - if (! bgp) - return 0; + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + /* We're looking for peers who's AS is not local */ + if (peer_sort(peer) != BGP_PEER_IBGP) { + peer->local_as = bgp->as; + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } - for (i = 0; i < bgp->confed_peers_cnt; i++) - if (bgp->confed_peers[i] == as) - return 1; - - return 0; + else + bgp_session_reset_safe(peer, &nnode); + } + } + return 0; } -/* Add an AS to the confederation set. */ -int -bgp_confederation_peers_add (struct bgp *bgp, as_t as) +/* Is an AS part of the confed or not? */ +int bgp_confederation_peers_check(struct bgp *bgp, as_t as) { - struct peer *peer; - struct listnode *node, *nnode; - - if (! bgp) - return BGP_ERR_INVALID_BGP; + int i; - if (bgp->as == as) - return BGP_ERR_INVALID_AS; + if (!bgp) + return 0; - if (bgp_confederation_peers_check (bgp, as)) - return -1; + for (i = 0; i < bgp->confed_peers_cnt; i++) + if (bgp->confed_peers[i] == as) + return 1; - if (bgp->confed_peers) - bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST, - bgp->confed_peers, - (bgp->confed_peers_cnt + 1) * sizeof (as_t)); - else - bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST, - (bgp->confed_peers_cnt + 1) * sizeof (as_t)); - - bgp->confed_peers[bgp->confed_peers_cnt] = as; - bgp->confed_peers_cnt++; + return 0; +} - if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)) - { - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->as == as) - { - peer->local_as = bgp->as; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset_safe(peer, &nnode); - } - } - } - return 0; +/* Add an AS to the confederation set. */ +int bgp_confederation_peers_add(struct bgp *bgp, as_t as) +{ + struct peer *peer; + struct listnode *node, *nnode; + + if (!bgp) + return BGP_ERR_INVALID_BGP; + + if (bgp->as == as) + return BGP_ERR_INVALID_AS; + + if (bgp_confederation_peers_check(bgp, as)) + return -1; + + if (bgp->confed_peers) + bgp->confed_peers = + XREALLOC(MTYPE_BGP_CONFED_LIST, bgp->confed_peers, + (bgp->confed_peers_cnt + 1) * sizeof(as_t)); + else + bgp->confed_peers = + XMALLOC(MTYPE_BGP_CONFED_LIST, + (bgp->confed_peers_cnt + 1) * sizeof(as_t)); + + bgp->confed_peers[bgp->confed_peers_cnt] = as; + bgp->confed_peers_cnt++; + + if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) { + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (peer->as == as) { + peer->local_as = bgp->as; + if (BGP_IS_VALID_STATE_FOR_NOTIF( + peer->status)) { + peer->last_reset = + PEER_DOWN_CONFED_PEER_CHANGE; + bgp_notify_send( + peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset_safe(peer, &nnode); + } + } + } + return 0; } /* Delete an AS from the confederation set. */ -int -bgp_confederation_peers_remove (struct bgp *bgp, as_t as) -{ - int i; - int j; - struct peer *peer; - struct listnode *node, *nnode; - - if (! bgp) - return -1; - - if (! bgp_confederation_peers_check (bgp, as)) - return -1; - - for (i = 0; i < bgp->confed_peers_cnt; i++) - if (bgp->confed_peers[i] == as) - for(j = i + 1; j < bgp->confed_peers_cnt; j++) - bgp->confed_peers[j - 1] = bgp->confed_peers[j]; - - bgp->confed_peers_cnt--; - - if (bgp->confed_peers_cnt == 0) - { - if (bgp->confed_peers) - XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers); - bgp->confed_peers = NULL; - } - else - bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST, - bgp->confed_peers, - bgp->confed_peers_cnt * sizeof (as_t)); - - /* Now reset any peer who's remote AS has just been removed from the - CONFED */ - if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)) - { - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->as == as) - { - peer->local_as = bgp->confed_id; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset_safe(peer, &nnode); - } +int bgp_confederation_peers_remove(struct bgp *bgp, as_t as) +{ + int i; + int j; + struct peer *peer; + struct listnode *node, *nnode; + + if (!bgp) + return -1; + + if (!bgp_confederation_peers_check(bgp, as)) + return -1; + + for (i = 0; i < bgp->confed_peers_cnt; i++) + if (bgp->confed_peers[i] == as) + for (j = i + 1; j < bgp->confed_peers_cnt; j++) + bgp->confed_peers[j - 1] = bgp->confed_peers[j]; + + bgp->confed_peers_cnt--; + + if (bgp->confed_peers_cnt == 0) { + if (bgp->confed_peers) + XFREE(MTYPE_BGP_CONFED_LIST, bgp->confed_peers); + bgp->confed_peers = NULL; + } else + bgp->confed_peers = + XREALLOC(MTYPE_BGP_CONFED_LIST, bgp->confed_peers, + bgp->confed_peers_cnt * sizeof(as_t)); + + /* Now reset any peer who's remote AS has just been removed from the + CONFED */ + if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) { + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (peer->as == as) { + peer->local_as = bgp->confed_id; + if (BGP_IS_VALID_STATE_FOR_NOTIF( + peer->status)) { + peer->last_reset = + PEER_DOWN_CONFED_PEER_CHANGE; + bgp_notify_send( + peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset_safe(peer, &nnode); + } + } } - } - return 0; + return 0; } /* Local preference configuration. */ -int -bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref) +int bgp_default_local_preference_set(struct bgp *bgp, u_int32_t local_pref) { - if (! bgp) - return -1; + if (!bgp) + return -1; - bgp->default_local_pref = local_pref; + bgp->default_local_pref = local_pref; - return 0; + return 0; } -int -bgp_default_local_preference_unset (struct bgp *bgp) +int bgp_default_local_preference_unset(struct bgp *bgp) { - if (! bgp) - return -1; + if (!bgp) + return -1; - bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF; + bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF; - return 0; + return 0; } /* Local preference configuration. */ -int -bgp_default_subgroup_pkt_queue_max_set (struct bgp *bgp, u_int32_t queue_size) +int bgp_default_subgroup_pkt_queue_max_set(struct bgp *bgp, + u_int32_t queue_size) { - if (! bgp) - return -1; + if (!bgp) + return -1; - bgp->default_subgroup_pkt_queue_max = queue_size; + bgp->default_subgroup_pkt_queue_max = queue_size; - return 0; + return 0; } -int -bgp_default_subgroup_pkt_queue_max_unset (struct bgp *bgp) +int bgp_default_subgroup_pkt_queue_max_unset(struct bgp *bgp) { - if (! bgp) - return -1; - bgp->default_subgroup_pkt_queue_max = BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX; + if (!bgp) + return -1; + bgp->default_subgroup_pkt_queue_max = + BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX; - return 0; + return 0; } /* Listen limit configuration. */ -int -bgp_listen_limit_set (struct bgp *bgp, int listen_limit) +int bgp_listen_limit_set(struct bgp *bgp, int listen_limit) { - if (! bgp) - return -1; + if (!bgp) + return -1; - bgp->dynamic_neighbors_limit = listen_limit; + bgp->dynamic_neighbors_limit = listen_limit; - return 0; + return 0; } -int -bgp_listen_limit_unset (struct bgp *bgp) +int bgp_listen_limit_unset(struct bgp *bgp) { - if (! bgp) - return -1; + if (!bgp) + return -1; - bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT; + bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT; - return 0; + return 0; } -int -bgp_map_afi_safi_iana2int (iana_afi_t pkt_afi, safi_t pkt_safi, - afi_t *afi, safi_t *safi) +int bgp_map_afi_safi_iana2int(iana_afi_t pkt_afi, safi_t pkt_safi, afi_t *afi, + safi_t *safi) { - /* Map from IANA values to internal values, return error if - * values are unrecognized. - */ - *afi = afi_iana2int (pkt_afi); - *safi = safi_iana2int (pkt_safi); - if (*afi == AFI_MAX || *safi == SAFI_MAX) - return -1; + /* Map from IANA values to internal values, return error if + * values are unrecognized. + */ + *afi = afi_iana2int(pkt_afi); + *safi = safi_iana2int(pkt_safi); + if (*afi == AFI_MAX || *safi == SAFI_MAX) + return -1; - return 0; + return 0; } -int -bgp_map_afi_safi_int2iana (afi_t afi, safi_t safi, - iana_afi_t *pkt_afi, safi_t *pkt_safi) +int bgp_map_afi_safi_int2iana(afi_t afi, safi_t safi, iana_afi_t *pkt_afi, + safi_t *pkt_safi) { - /* Map from internal values to IANA values, return error if - * internal values are bad (unexpected). - */ - if (afi == AFI_MAX || safi == SAFI_MAX) - return -1; - *pkt_afi = afi_int2iana (afi); - *pkt_safi = safi_int2iana (safi); - return 0; + /* Map from internal values to IANA values, return error if + * internal values are bad (unexpected). + */ + if (afi == AFI_MAX || safi == SAFI_MAX) + return -1; + *pkt_afi = afi_int2iana(afi); + *pkt_safi = safi_int2iana(safi); + return 0; } -struct peer_af * -peer_af_create (struct peer *peer, afi_t afi, safi_t safi) +struct peer_af *peer_af_create(struct peer *peer, afi_t afi, safi_t safi) { - struct peer_af *af; - int afid; + struct peer_af *af; + int afid; - if (!peer) - return NULL; + if (!peer) + return NULL; - afid = afindex(afi, safi); - if (afid >= BGP_AF_MAX) - return NULL; + afid = afindex(afi, safi); + if (afid >= BGP_AF_MAX) + return NULL; - assert(peer->peer_af_array[afid] == NULL); + assert(peer->peer_af_array[afid] == NULL); - /* Allocate new peer af */ - af = XCALLOC (MTYPE_BGP_PEER_AF, sizeof (struct peer_af)); + /* Allocate new peer af */ + af = XCALLOC(MTYPE_BGP_PEER_AF, sizeof(struct peer_af)); - if (af == NULL) - { - zlog_err("Could not create af structure for peer %s", peer->host); - return NULL; - } + if (af == NULL) { + zlog_err("Could not create af structure for peer %s", + peer->host); + return NULL; + } - peer->peer_af_array[afid] = af; - af->afi = afi; - af->safi = safi; - af->afid = afid; - af->peer = peer; + peer->peer_af_array[afid] = af; + af->afi = afi; + af->safi = safi; + af->afid = afid; + af->peer = peer; - return af; + return af; } -struct peer_af * -peer_af_find (struct peer *peer, afi_t afi, safi_t safi) +struct peer_af *peer_af_find(struct peer *peer, afi_t afi, safi_t safi) { - int afid; + int afid; - if (!peer) - return NULL; + if (!peer) + return NULL; - afid = afindex(afi, safi); - if (afid >= BGP_AF_MAX) - return NULL; + afid = afindex(afi, safi); + if (afid >= BGP_AF_MAX) + return NULL; - return peer->peer_af_array[afid]; + return peer->peer_af_array[afid]; } -int -peer_af_delete (struct peer *peer, afi_t afi, safi_t safi) +int peer_af_delete(struct peer *peer, afi_t afi, safi_t safi) { - struct peer_af *af; - int afid; + struct peer_af *af; + int afid; - if (!peer) - return -1; + if (!peer) + return -1; - afid = afindex(afi, safi); - if (afid >= BGP_AF_MAX) - return -1; + afid = afindex(afi, safi); + if (afid >= BGP_AF_MAX) + return -1; - af = peer->peer_af_array[afid]; - if (!af) - return -1; + af = peer->peer_af_array[afid]; + if (!af) + return -1; - bgp_stop_announce_route_timer (af); + bgp_stop_announce_route_timer(af); - if (PAF_SUBGRP(af)) - { - if (BGP_DEBUG (update_groups, UPDATE_GROUPS)) - zlog_debug ("u%" PRIu64 ":s%" PRIu64 " remove peer %s", - af->subgroup->update_group->id, af->subgroup->id, peer->host); - } + if (PAF_SUBGRP(af)) { + if (BGP_DEBUG(update_groups, UPDATE_GROUPS)) + zlog_debug("u%" PRIu64 ":s%" PRIu64 " remove peer %s", + af->subgroup->update_group->id, + af->subgroup->id, peer->host); + } - update_subgroup_remove_peer (af->subgroup, af); + update_subgroup_remove_peer(af->subgroup, af); - peer->peer_af_array[afid] = NULL; - XFREE(MTYPE_BGP_PEER_AF, af); - return 0; + peer->peer_af_array[afid] = NULL; + XFREE(MTYPE_BGP_PEER_AF, af); + return 0; } /* Peer comparison function for sorting. */ -int -peer_cmp (struct peer *p1, struct peer *p2) +int peer_cmp(struct peer *p1, struct peer *p2) { - if (p1->group && !p2->group) - return -1; + if (p1->group && !p2->group) + return -1; - if (!p1->group && p2->group) - return 1; + if (!p1->group && p2->group) + return 1; - if (p1->group == p2->group) - { - if (p1->conf_if && !p2->conf_if) - return -1; + if (p1->group == p2->group) { + if (p1->conf_if && !p2->conf_if) + return -1; - if (!p1->conf_if && p2->conf_if) - return 1; + if (!p1->conf_if && p2->conf_if) + return 1; - if (p1->conf_if && p2->conf_if) - return if_cmp_name_func (p1->conf_if, p2->conf_if); - } - else - return strcmp (p1->group->name, p2->group->name); + if (p1->conf_if && p2->conf_if) + return if_cmp_name_func(p1->conf_if, p2->conf_if); + } else + return strcmp(p1->group->name, p2->group->name); - return sockunion_cmp (&p1->su, &p2->su); + return sockunion_cmp(&p1->su, &p2->su); } -static unsigned int -peer_hash_key_make(void *p) +static unsigned int peer_hash_key_make(void *p) { - struct peer *peer = p; - return sockunion_hash(&peer->su); + struct peer *peer = p; + return sockunion_hash(&peer->su); } -static int -peer_hash_cmp (const void *p1, const void *p2) +static int peer_hash_cmp(const void *p1, const void *p2) { - const struct peer *peer1 = p1; - const struct peer *peer2 = p2; - return (sockunion_same (&peer1->su, &peer2->su) && - CHECK_FLAG (peer1->flags, PEER_FLAG_CONFIG_NODE) == CHECK_FLAG (peer2->flags, PEER_FLAG_CONFIG_NODE)); + const struct peer *peer1 = p1; + const struct peer *peer2 = p2; + return (sockunion_same(&peer1->su, &peer2->su) + && CHECK_FLAG(peer1->flags, PEER_FLAG_CONFIG_NODE) + == CHECK_FLAG(peer2->flags, PEER_FLAG_CONFIG_NODE)); } -int -peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag) +int peer_af_flag_check(struct peer *peer, afi_t afi, safi_t safi, + u_int32_t flag) { - return CHECK_FLAG (peer->af_flags[afi][safi], flag); + return CHECK_FLAG(peer->af_flags[afi][safi], flag); } /* Return true if flag is set for the peer but not the peer-group */ -static int -peergroup_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag) +static int peergroup_af_flag_check(struct peer *peer, afi_t afi, safi_t safi, + u_int32_t flag) { - struct peer *g_peer = NULL; + struct peer *g_peer = NULL; - if (peer_af_flag_check (peer, afi, safi, flag)) - { - if (peer_group_active (peer)) - { - g_peer = peer->group->conf; + if (peer_af_flag_check(peer, afi, safi, flag)) { + if (peer_group_active(peer)) { + g_peer = peer->group->conf; - /* If this flag is not set for the peer's peer-group then return true */ - if (!peer_af_flag_check (g_peer, afi, safi, flag)) - { - return 1; - } - } + /* If this flag is not set for the peer's peer-group + * then return true */ + if (!peer_af_flag_check(g_peer, afi, safi, flag)) { + return 1; + } + } - /* peer is not in a peer-group but the flag is set to return true */ - else - { - return 1; - } - } + /* peer is not in a peer-group but the flag is set to return + true */ + else { + return 1; + } + } - return 0; + return 0; } /* Reset all address family specific configuration. */ -static void -peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi) +static void peer_af_flag_reset(struct peer *peer, afi_t afi, safi_t safi) { - int i; - struct bgp_filter *filter; - char orf_name[BUFSIZ]; + int i; + struct bgp_filter *filter; + char orf_name[BUFSIZ]; - filter = &peer->filter[afi][safi]; + filter = &peer->filter[afi][safi]; - /* Clear neighbor filter and route-map */ - for (i = FILTER_IN; i < FILTER_MAX; i++) - { - if (filter->dlist[i].name) - { - XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[i].name); - filter->dlist[i].name = NULL; - } - if (filter->plist[i].name) - { - XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[i].name); - filter->plist[i].name = NULL; - } - if (filter->aslist[i].name) - { - XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[i].name); - filter->aslist[i].name = NULL; + /* Clear neighbor filter and route-map */ + for (i = FILTER_IN; i < FILTER_MAX; i++) { + if (filter->dlist[i].name) { + XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[i].name); + filter->dlist[i].name = NULL; + } + if (filter->plist[i].name) { + XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[i].name); + filter->plist[i].name = NULL; + } + if (filter->aslist[i].name) { + XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[i].name); + filter->aslist[i].name = NULL; + } } - } - for (i = RMAP_IN; i < RMAP_MAX; i++) - { - if (filter->map[i].name) - { - XFREE(MTYPE_BGP_FILTER_NAME, filter->map[i].name); - filter->map[i].name = NULL; + for (i = RMAP_IN; i < RMAP_MAX; i++) { + if (filter->map[i].name) { + XFREE(MTYPE_BGP_FILTER_NAME, filter->map[i].name); + filter->map[i].name = NULL; + } } - } - - /* Clear unsuppress map. */ - if (filter->usmap.name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); - filter->usmap.name = NULL; - filter->usmap.map = NULL; - /* Clear neighbor's all address family flags. */ - peer->af_flags[afi][safi] = 0; + /* Clear unsuppress map. */ + if (filter->usmap.name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); + filter->usmap.name = NULL; + filter->usmap.map = NULL; - /* Clear neighbor's all address family sflags. */ - peer->af_sflags[afi][safi] = 0; + /* Clear neighbor's all address family flags. */ + peer->af_flags[afi][safi] = 0; - /* Clear neighbor's all address family capabilities. */ - peer->af_cap[afi][safi] = 0; + /* Clear neighbor's all address family sflags. */ + peer->af_sflags[afi][safi] = 0; - /* Clear ORF info */ - peer->orf_plist[afi][safi] = NULL; - sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi); - prefix_bgp_orf_remove_all (afi, orf_name); + /* Clear neighbor's all address family capabilities. */ + peer->af_cap[afi][safi] = 0; - /* Set default neighbor send-community. */ - if (! bgp_option_check (BGP_OPT_CONFIG_CISCO)) - { - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY); - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY); - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY); - } + /* Clear ORF info */ + peer->orf_plist[afi][safi] = NULL; + sprintf(orf_name, "%s.%d.%d", peer->host, afi, safi); + prefix_bgp_orf_remove_all(afi, orf_name); + + /* Set default neighbor send-community. */ + if (!bgp_option_check(BGP_OPT_CONFIG_CISCO)) { + SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY); + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_SEND_EXT_COMMUNITY); + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_SEND_LARGE_COMMUNITY); + } - /* Clear neighbor default_originate_rmap */ - if (peer->default_rmap[afi][safi].name) - XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name); - peer->default_rmap[afi][safi].name = NULL; - peer->default_rmap[afi][safi].map = NULL; + /* Clear neighbor default_originate_rmap */ + if (peer->default_rmap[afi][safi].name) + XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name); + peer->default_rmap[afi][safi].name = NULL; + peer->default_rmap[afi][safi].map = NULL; - /* Clear neighbor maximum-prefix */ - peer->pmax[afi][safi] = 0; - peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT; + /* Clear neighbor maximum-prefix */ + peer->pmax[afi][safi] = 0; + peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT; } /* peer global config reset */ -static void -peer_global_config_reset (struct peer *peer) +static void peer_global_config_reset(struct peer *peer) { - int v6only; + int v6only; - peer->change_local_as = 0; - peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? MAXTTL : 1); - if (peer->update_source) - { - sockunion_free (peer->update_source); - peer->update_source = NULL; - } - if (peer->update_if) - { - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - peer->update_if = NULL; - } + peer->change_local_as = 0; + peer->ttl = (peer_sort(peer) == BGP_PEER_IBGP ? MAXTTL : 1); + if (peer->update_source) { + sockunion_free(peer->update_source); + peer->update_source = NULL; + } + if (peer->update_if) { + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); + peer->update_if = NULL; + } - if (peer_sort (peer) == BGP_PEER_IBGP) - peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; - else - peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; + if (peer_sort(peer) == BGP_PEER_IBGP) + peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; + else + peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; - /* This is a per-peer specific flag and so we must preserve it */ - v6only = CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); + /* This is a per-peer specific flag and so we must preserve it */ + v6only = CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); - peer->flags = 0; + peer->flags = 0; - if (v6only) - SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); + if (v6only) + SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); - peer->config = 0; - peer->holdtime = 0; - peer->keepalive = 0; - peer->connect = 0; - peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; + peer->config = 0; + peer->holdtime = 0; + peer->keepalive = 0; + peer->connect = 0; + peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; - /* Reset some other configs back to defaults. */ - peer->v_start = BGP_INIT_START_TIMER; - peer->password = NULL; - peer->local_id = peer->bgp->router_id; - peer->v_holdtime = peer->bgp->default_holdtime; - peer->v_keepalive = peer->bgp->default_keepalive; + /* Reset some other configs back to defaults. */ + peer->v_start = BGP_INIT_START_TIMER; + peer->password = NULL; + peer->local_id = peer->bgp->router_id; + peer->v_holdtime = peer->bgp->default_holdtime; + peer->v_keepalive = peer->bgp->default_keepalive; - bfd_info_free(&(peer->bfd_info)); + bfd_info_free(&(peer->bfd_info)); - /* Set back the CONFIG_NODE flag. */ - SET_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE); + /* Set back the CONFIG_NODE flag. */ + SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); } /* Check peer's AS number and determines if this peer is IBGP or EBGP */ -static bgp_peer_sort_t -peer_calc_sort (struct peer *peer) +static bgp_peer_sort_t peer_calc_sort(struct peer *peer) { - struct bgp *bgp; + struct bgp *bgp; - bgp = peer->bgp; + bgp = peer->bgp; - /* Peer-group */ - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (peer->as_type == AS_INTERNAL) - return BGP_PEER_IBGP; + /* Peer-group */ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (peer->as_type == AS_INTERNAL) + return BGP_PEER_IBGP; - else if (peer->as_type == AS_EXTERNAL) - return BGP_PEER_EBGP; + else if (peer->as_type == AS_EXTERNAL) + return BGP_PEER_EBGP; - else if (peer->as_type == AS_SPECIFIED && peer->as) - return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP); + else if (peer->as_type == AS_SPECIFIED && peer->as) + return (bgp->as == peer->as ? BGP_PEER_IBGP + : BGP_PEER_EBGP); - else - { - struct peer *peer1; - peer1 = listnode_head (peer->group->peer); - - if (peer1) - return peer1->sort; - } - return BGP_PEER_INTERNAL; - } - - /* Normal peer */ - if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION)) - { - if (peer->local_as == 0) - return BGP_PEER_INTERNAL; - - if (peer->local_as == peer->as) - { - if (bgp->as == bgp->confed_id) - { - if (peer->local_as == bgp->as) - return BGP_PEER_IBGP; - else - return BGP_PEER_EBGP; - } - else - { - if (peer->local_as == bgp->confed_id) - return BGP_PEER_EBGP; - else - return BGP_PEER_IBGP; - } - } - - if (bgp_confederation_peers_check (bgp, peer->as)) - return BGP_PEER_CONFED; - - return BGP_PEER_EBGP; - } - else - { - if (peer->as_type != AS_SPECIFIED) - return (peer->as_type == AS_INTERNAL ? BGP_PEER_IBGP : BGP_PEER_EBGP); - - return (peer->local_as == 0 - ? BGP_PEER_INTERNAL : peer->local_as == peer->as - ? BGP_PEER_IBGP : BGP_PEER_EBGP); - } + else { + struct peer *peer1; + peer1 = listnode_head(peer->group->peer); + + if (peer1) + return peer1->sort; + } + return BGP_PEER_INTERNAL; + } + + /* Normal peer */ + if (bgp && CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) { + if (peer->local_as == 0) + return BGP_PEER_INTERNAL; + + if (peer->local_as == peer->as) { + if (bgp->as == bgp->confed_id) { + if (peer->local_as == bgp->as) + return BGP_PEER_IBGP; + else + return BGP_PEER_EBGP; + } else { + if (peer->local_as == bgp->confed_id) + return BGP_PEER_EBGP; + else + return BGP_PEER_IBGP; + } + } + + if (bgp_confederation_peers_check(bgp, peer->as)) + return BGP_PEER_CONFED; + + return BGP_PEER_EBGP; + } else { + if (peer->as_type != AS_SPECIFIED) + return (peer->as_type == AS_INTERNAL ? BGP_PEER_IBGP + : BGP_PEER_EBGP); + + return (peer->local_as == 0 + ? BGP_PEER_INTERNAL + : peer->local_as == peer->as ? BGP_PEER_IBGP + : BGP_PEER_EBGP); + } } /* Calculate and cache the peer "sort" */ -bgp_peer_sort_t -peer_sort (struct peer *peer) -{ - peer->sort = peer_calc_sort (peer); - return peer->sort; -} - -static void -peer_free (struct peer *peer) -{ - assert (peer->status == Deleted); - - QOBJ_UNREG (peer); - - /* this /ought/ to have been done already through bgp_stop earlier, - * but just to be sure.. - */ - bgp_timer_set (peer); - BGP_READ_OFF (peer->t_read); - BGP_WRITE_OFF (peer->t_write); - BGP_EVENT_FLUSH (peer); - - /* Free connected nexthop, if present */ - if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE) && - !peer_dynamic_neighbor (peer)) - bgp_delete_connected_nexthop (family2afi(peer->su.sa.sa_family), peer); - - XFREE (MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message); - - if (peer->desc) - { - XFREE (MTYPE_PEER_DESC, peer->desc); - peer->desc = NULL; - } - - /* Free allocated host character. */ - if (peer->host) - { - XFREE (MTYPE_BGP_PEER_HOST, peer->host); - peer->host = NULL; - } - - if (peer->domainname) - { - XFREE (MTYPE_BGP_PEER_HOST, peer->domainname); - peer->domainname = NULL; - } - - if (peer->ifname) - { - XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname); - peer->ifname = NULL; - } - - /* Update source configuration. */ - if (peer->update_source) - { - sockunion_free (peer->update_source); - peer->update_source = NULL; - } - - if (peer->update_if) - { - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - peer->update_if = NULL; - } - - if (peer->notify.data) - XFREE(MTYPE_TMP, peer->notify.data); - memset (&peer->notify, 0, sizeof (struct bgp_notify)); - - if (peer->clear_node_queue) - { - work_queue_free(peer->clear_node_queue); - peer->clear_node_queue = NULL; - } - - bgp_sync_delete (peer); - - if (peer->conf_if) - { - XFREE (MTYPE_PEER_CONF_IF, peer->conf_if); - peer->conf_if = NULL; - } - - bfd_info_free(&(peer->bfd_info)); - - bgp_unlock(peer->bgp); - - memset (peer, 0, sizeof (struct peer)); - - XFREE (MTYPE_BGP_PEER, peer); -} - +bgp_peer_sort_t peer_sort(struct peer *peer) +{ + peer->sort = peer_calc_sort(peer); + return peer->sort; +} + +static void peer_free(struct peer *peer) +{ + assert(peer->status == Deleted); + + QOBJ_UNREG(peer); + + /* this /ought/ to have been done already through bgp_stop earlier, + * but just to be sure.. + */ + bgp_timer_set(peer); + BGP_READ_OFF(peer->t_read); + BGP_WRITE_OFF(peer->t_write); + BGP_EVENT_FLUSH(peer); + + /* Free connected nexthop, if present */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE) + && !peer_dynamic_neighbor(peer)) + bgp_delete_connected_nexthop(family2afi(peer->su.sa.sa_family), + peer); + + XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message); + + if (peer->desc) { + XFREE(MTYPE_PEER_DESC, peer->desc); + peer->desc = NULL; + } + + /* Free allocated host character. */ + if (peer->host) { + XFREE(MTYPE_BGP_PEER_HOST, peer->host); + peer->host = NULL; + } + + if (peer->domainname) { + XFREE(MTYPE_BGP_PEER_HOST, peer->domainname); + peer->domainname = NULL; + } + + if (peer->ifname) { + XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname); + peer->ifname = NULL; + } + + /* Update source configuration. */ + if (peer->update_source) { + sockunion_free(peer->update_source); + peer->update_source = NULL; + } + + if (peer->update_if) { + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); + peer->update_if = NULL; + } + + if (peer->notify.data) + XFREE(MTYPE_TMP, peer->notify.data); + memset(&peer->notify, 0, sizeof(struct bgp_notify)); + + if (peer->clear_node_queue) { + work_queue_free(peer->clear_node_queue); + peer->clear_node_queue = NULL; + } + + bgp_sync_delete(peer); + + if (peer->conf_if) { + XFREE(MTYPE_PEER_CONF_IF, peer->conf_if); + peer->conf_if = NULL; + } + + bfd_info_free(&(peer->bfd_info)); + + bgp_unlock(peer->bgp); + + memset(peer, 0, sizeof(struct peer)); + + XFREE(MTYPE_BGP_PEER, peer); +} + /* increase reference count on a struct peer */ -struct peer * -peer_lock_with_caller (const char *name, struct peer *peer) +struct peer *peer_lock_with_caller(const char *name, struct peer *peer) { - assert (peer && (peer->lock >= 0)); + assert(peer && (peer->lock >= 0)); #if 0 zlog_debug("%s peer_lock %p %d", name, peer, peer->lock); #endif - - peer->lock++; - - return peer; + + peer->lock++; + + return peer; } /* decrease reference count on a struct peer * struct peer is freed and NULL returned if last reference */ -struct peer * -peer_unlock_with_caller (const char *name, struct peer *peer) +struct peer *peer_unlock_with_caller(const char *name, struct peer *peer) { - assert (peer && (peer->lock > 0)); + assert(peer && (peer->lock > 0)); #if 0 zlog_debug("%s peer_unlock %p %d", name, peer, peer->lock); #endif - - peer->lock--; - - if (peer->lock == 0) - { - peer_free (peer); - return NULL; - } - return peer; + peer->lock--; + + if (peer->lock == 0) { + peer_free(peer); + return NULL; + } + + return peer; } /* Allocate new peer object, implicitely locked. */ -struct peer * -peer_new (struct bgp *bgp) -{ - afi_t afi; - safi_t safi; - struct peer *peer; - struct servent *sp; - - /* bgp argument is absolutely required */ - assert (bgp); - if (!bgp) - return NULL; - - /* Allocate new peer. */ - peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer)); - - /* Set default value. */ - peer->fd = -1; - peer->v_start = BGP_INIT_START_TIMER; - peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; - peer->status = Idle; - peer->ostatus = Idle; - peer->cur_event = peer->last_event = peer->last_major_event = 0; - peer->bgp = bgp; - peer = peer_lock (peer); /* initial reference */ - bgp_lock (bgp); - peer->password = NULL; - - /* Set default flags. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - if (! bgp_option_check (BGP_OPT_CONFIG_CISCO)) - { - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY); - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY); - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY); - } - peer->orf_plist[afi][safi] = NULL; - } - SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN); +struct peer *peer_new(struct bgp *bgp) +{ + afi_t afi; + safi_t safi; + struct peer *peer; + struct servent *sp; + + /* bgp argument is absolutely required */ + assert(bgp); + if (!bgp) + return NULL; + + /* Allocate new peer. */ + peer = XCALLOC(MTYPE_BGP_PEER, sizeof(struct peer)); + + /* Set default value. */ + peer->fd = -1; + peer->v_start = BGP_INIT_START_TIMER; + peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; + peer->status = Idle; + peer->ostatus = Idle; + peer->cur_event = peer->last_event = peer->last_major_event = 0; + peer->bgp = bgp; + peer = peer_lock(peer); /* initial reference */ + bgp_lock(bgp); + peer->password = NULL; + + /* Set default flags. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + if (!bgp_option_check(BGP_OPT_CONFIG_CISCO)) { + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_SEND_COMMUNITY); + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_SEND_EXT_COMMUNITY); + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_SEND_LARGE_COMMUNITY); + } + peer->orf_plist[afi][safi] = NULL; + } + SET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN); - /* Create buffers. */ - peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE); - peer->obuf = stream_fifo_new (); + /* Create buffers. */ + peer->ibuf = stream_new(BGP_MAX_PACKET_SIZE); + peer->obuf = stream_fifo_new(); - /* We use a larger buffer for peer->work in the event that: - * - We RX a BGP_UPDATE where the attributes alone are just - * under BGP_MAX_PACKET_SIZE - * - The user configures an outbound route-map that does many as-path - * prepends or adds many communities. At most they can have CMD_ARGC_MAX - * args in a route-map so there is a finite limit on how large they can - * make the attributes. - * - * Having a buffer with BGP_MAX_PACKET_SIZE_OVERFLOW allows us to avoid bounds - * checking for every single attribute as we construct an UPDATE. - */ - peer->work = stream_new (BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW); - peer->scratch = stream_new (BGP_MAX_PACKET_SIZE); + /* We use a larger buffer for peer->work in the event that: + * - We RX a BGP_UPDATE where the attributes alone are just + * under BGP_MAX_PACKET_SIZE + * - The user configures an outbound route-map that does many as-path + * prepends or adds many communities. At most they can have + * CMD_ARGC_MAX + * args in a route-map so there is a finite limit on how large they + * can + * make the attributes. + * + * Having a buffer with BGP_MAX_PACKET_SIZE_OVERFLOW allows us to avoid + * bounds + * checking for every single attribute as we construct an UPDATE. + */ + peer->work = + stream_new(BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW); + peer->scratch = stream_new(BGP_MAX_PACKET_SIZE); - bgp_sync_init (peer); + bgp_sync_init(peer); - /* Get service port number. */ - sp = getservbyname ("bgp", "tcp"); - peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port); + /* Get service port number. */ + sp = getservbyname("bgp", "tcp"); + peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs(sp->s_port); - QOBJ_REG (peer, peer); - return peer; + QOBJ_REG(peer, peer); + return peer; } /* @@ -1259,168 +1174,165 @@ peer_new (struct bgp *bgp) * a neighbor is being deleted. If this about-to-be-deleted structure is * the one with all the config, then we have to copy over the info. */ -void -peer_xfer_config (struct peer *peer_dst, struct peer *peer_src) -{ - struct peer_af *paf; - afi_t afi; - safi_t safi; - int afidx; - - assert(peer_src); - assert(peer_dst); - - /* The following function is used by both peer group config copy to - * individual peer and when we transfer config - */ - if (peer_src->change_local_as) - peer_dst->change_local_as = peer_src->change_local_as; - - /* peer flags apply */ - peer_dst->flags = peer_src->flags; - peer_dst->cap = peer_src->cap; - peer_dst->config = peer_src->config; - - peer_dst->local_as = peer_src->local_as; - peer_dst->ifindex = peer_src->ifindex; - peer_dst->port = peer_src->port; - peer_sort(peer_dst); - peer_dst->rmap_type = peer_src->rmap_type; - - /* Timers */ - peer_dst->holdtime = peer_src->holdtime; - peer_dst->keepalive = peer_src->keepalive; - peer_dst->connect = peer_src->connect; - peer_dst->v_holdtime = peer_src->v_holdtime; - peer_dst->v_keepalive = peer_src->v_keepalive; - peer_dst->routeadv = peer_src->routeadv; - peer_dst->v_routeadv = peer_src->v_routeadv; - - /* password apply */ - if (peer_src->password && !peer_dst->password) - peer_dst->password = XSTRDUP (MTYPE_PEER_PASSWORD, peer_src->password); - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - peer_dst->afc[afi][safi] = peer_src->afc[afi][safi]; - peer_dst->af_flags[afi][safi] = peer_src->af_flags[afi][safi]; - peer_dst->allowas_in[afi][safi] = peer_src->allowas_in[afi][safi]; - peer_dst->weight[afi][safi] = peer_src->weight[afi][safi]; - } - - for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) - { - paf = peer_src->peer_af_array[afidx]; - if (paf != NULL) - peer_af_create(peer_dst, paf->afi, paf->safi); - } - - /* update-source apply */ - if (peer_src->update_source) - { - if (peer_dst->update_source) - sockunion_free (peer_dst->update_source); - if (peer_dst->update_if) - { - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if); - peer_dst->update_if = NULL; - } - peer_dst->update_source = sockunion_dup (peer_src->update_source); - } - else if (peer_src->update_if) - { - if (peer_dst->update_if) - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if); - if (peer_dst->update_source) - { - sockunion_free (peer_dst->update_source); - peer_dst->update_source = NULL; - } - peer_dst->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, peer_src->update_if); - } - - if (peer_src->ifname) - { - if (peer_dst->ifname) - XFREE(MTYPE_BGP_PEER_IFNAME, peer_dst->ifname); - - peer_dst->ifname = XSTRDUP(MTYPE_BGP_PEER_IFNAME, peer_src->ifname); - } -} - -static int -bgp_peer_conf_if_to_su_update_v4 (struct peer *peer, struct interface *ifp) -{ - struct connected *ifc; - struct prefix p; - u_int32_t addr; - struct listnode *node; - - /* If our IPv4 address on the interface is /30 or /31, we can derive the - * IPv4 address of the other end. - */ - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) - { - if (ifc->address && (ifc->address->family == AF_INET)) - { - PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); - if (p.prefixlen == 30) - { - peer->su.sa.sa_family = AF_INET; - addr = ntohl(p.u.prefix4.s_addr); - if (addr % 4 == 1) - peer->su.sin.sin_addr.s_addr = htonl(addr+1); - else if (addr % 4 == 2) - peer->su.sin.sin_addr.s_addr = htonl(addr-1); +void peer_xfer_config(struct peer *peer_dst, struct peer *peer_src) +{ + struct peer_af *paf; + afi_t afi; + safi_t safi; + int afidx; + + assert(peer_src); + assert(peer_dst); + + /* The following function is used by both peer group config copy to + * individual peer and when we transfer config + */ + if (peer_src->change_local_as) + peer_dst->change_local_as = peer_src->change_local_as; + + /* peer flags apply */ + peer_dst->flags = peer_src->flags; + peer_dst->cap = peer_src->cap; + peer_dst->config = peer_src->config; + + peer_dst->local_as = peer_src->local_as; + peer_dst->ifindex = peer_src->ifindex; + peer_dst->port = peer_src->port; + peer_sort(peer_dst); + peer_dst->rmap_type = peer_src->rmap_type; + + /* Timers */ + peer_dst->holdtime = peer_src->holdtime; + peer_dst->keepalive = peer_src->keepalive; + peer_dst->connect = peer_src->connect; + peer_dst->v_holdtime = peer_src->v_holdtime; + peer_dst->v_keepalive = peer_src->v_keepalive; + peer_dst->routeadv = peer_src->routeadv; + peer_dst->v_routeadv = peer_src->v_routeadv; + + /* password apply */ + if (peer_src->password && !peer_dst->password) + peer_dst->password = + XSTRDUP(MTYPE_PEER_PASSWORD, peer_src->password); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + peer_dst->afc[afi][safi] = peer_src->afc[afi][safi]; + peer_dst->af_flags[afi][safi] = + peer_src->af_flags[afi][safi]; + peer_dst->allowas_in[afi][safi] = + peer_src->allowas_in[afi][safi]; + peer_dst->weight[afi][safi] = + peer_src->weight[afi][safi]; + } + + for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) { + paf = peer_src->peer_af_array[afidx]; + if (paf != NULL) + peer_af_create(peer_dst, paf->afi, paf->safi); + } + + /* update-source apply */ + if (peer_src->update_source) { + if (peer_dst->update_source) + sockunion_free(peer_dst->update_source); + if (peer_dst->update_if) { + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if); + peer_dst->update_if = NULL; + } + peer_dst->update_source = + sockunion_dup(peer_src->update_source); + } else if (peer_src->update_if) { + if (peer_dst->update_if) + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if); + if (peer_dst->update_source) { + sockunion_free(peer_dst->update_source); + peer_dst->update_source = NULL; + } + peer_dst->update_if = + XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, peer_src->update_if); + } + + if (peer_src->ifname) { + if (peer_dst->ifname) + XFREE(MTYPE_BGP_PEER_IFNAME, peer_dst->ifname); + + peer_dst->ifname = + XSTRDUP(MTYPE_BGP_PEER_IFNAME, peer_src->ifname); + } +} + +static int bgp_peer_conf_if_to_su_update_v4(struct peer *peer, + struct interface *ifp) +{ + struct connected *ifc; + struct prefix p; + u_int32_t addr; + struct listnode *node; + + /* If our IPv4 address on the interface is /30 or /31, we can derive the + * IPv4 address of the other end. + */ + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { + if (ifc->address && (ifc->address->family == AF_INET)) { + PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); + if (p.prefixlen == 30) { + peer->su.sa.sa_family = AF_INET; + addr = ntohl(p.u.prefix4.s_addr); + if (addr % 4 == 1) + peer->su.sin.sin_addr.s_addr = + htonl(addr + 1); + else if (addr % 4 == 2) + peer->su.sin.sin_addr.s_addr = + htonl(addr - 1); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - peer->su.sin.sin_len = sizeof(struct sockaddr_in); + peer->su.sin.sin_len = + sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - return 1; - } - else if (p.prefixlen == 31) - { - peer->su.sa.sa_family = AF_INET; - addr = ntohl(p.u.prefix4.s_addr); - if (addr % 2 == 0) - peer->su.sin.sin_addr.s_addr = htonl(addr+1); - else - peer->su.sin.sin_addr.s_addr = htonl(addr-1); + return 1; + } else if (p.prefixlen == 31) { + peer->su.sa.sa_family = AF_INET; + addr = ntohl(p.u.prefix4.s_addr); + if (addr % 2 == 0) + peer->su.sin.sin_addr.s_addr = + htonl(addr + 1); + else + peer->su.sin.sin_addr.s_addr = + htonl(addr - 1); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - peer->su.sin.sin_len = sizeof(struct sockaddr_in); + peer->su.sin.sin_len = + sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - return 1; - } - else - if (bgp_debug_neighbor_events(peer)) - zlog_debug("%s: IPv4 interface address is not /30 or /31, v4 session not started", - peer->conf_if); - } - } - - return 0; -} - -static int -bgp_peer_conf_if_to_su_update_v6 (struct peer *peer, struct interface *ifp) -{ - struct nbr_connected *ifc_nbr; - - /* Have we learnt the peer's IPv6 link-local address? */ - if (ifp->nbr_connected && - (ifc_nbr = listnode_head(ifp->nbr_connected))) - { - peer->su.sa.sa_family = AF_INET6; - memcpy(&peer->su.sin6.sin6_addr, &ifc_nbr->address->u.prefix, - sizeof (struct in6_addr)); + return 1; + } else if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s: IPv4 interface address is not /30 or /31, v4 session not started", + peer->conf_if); + } + } + + return 0; +} + +static int bgp_peer_conf_if_to_su_update_v6(struct peer *peer, + struct interface *ifp) +{ + struct nbr_connected *ifc_nbr; + + /* Have we learnt the peer's IPv6 link-local address? */ + if (ifp->nbr_connected + && (ifc_nbr = listnode_head(ifp->nbr_connected))) { + peer->su.sa.sa_family = AF_INET6; + memcpy(&peer->su.sin6.sin6_addr, &ifc_nbr->address->u.prefix, + sizeof(struct in6_addr)); #ifdef SIN6_LEN - peer->su.sin6.sin6_len = sizeof (struct sockaddr_in6); + peer->su.sin6.sin6_len = sizeof(struct sockaddr_in6); #endif - peer->su.sin6.sin6_scope_id = ifp->ifindex; - return 1; - } + peer->su.sin6.sin6_scope_id = ifp->ifindex; + return 1; + } - return 0; + return 0; } /* @@ -1428,6414 +1340,6167 @@ bgp_peer_conf_if_to_su_update_v6 (struct peer *peer, struct interface *ifp) * learnt/derived peer address. If the address has changed, update the * password on the listen socket, if needed. */ -void -bgp_peer_conf_if_to_su_update (struct peer *peer) -{ - struct interface *ifp; - int prev_family; - int peer_addr_updated = 0; - - if (!peer->conf_if) - return; - - prev_family = peer->su.sa.sa_family; - if ((ifp = if_lookup_by_name (peer->conf_if, peer->bgp->vrf_id))) - { - peer->ifp = ifp; - /* If BGP unnumbered is not "v6only", we first see if we can derive the - * peer's IPv4 address. - */ - if (!CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) - peer_addr_updated = bgp_peer_conf_if_to_su_update_v4 (peer, ifp); - - /* If "v6only" or we can't derive peer's IPv4 address, see if we've - * learnt the peer's IPv6 link-local address. This is from the source - * IPv6 address in router advertisement. - */ - if (!peer_addr_updated) - peer_addr_updated = bgp_peer_conf_if_to_su_update_v6 (peer, ifp); - } - /* If we could derive the peer address, we may need to install the password - * configured for the peer, if any, on the listen socket. Otherwise, mark - * that peer's address is not available and uninstall the password, if - * needed. - */ - if (peer_addr_updated) - { - if (peer->password && prev_family == AF_UNSPEC) - bgp_md5_set (peer); - } - else - { - if (peer->password && prev_family != AF_UNSPEC) - bgp_md5_unset (peer); - peer->su.sa.sa_family = AF_UNSPEC; - memset(&peer->su.sin6.sin6_addr, 0, sizeof (struct in6_addr)); - } - - /* Since our su changed we need to del/add peer to the peerhash */ - hash_release(peer->bgp->peerhash, peer); - hash_get(peer->bgp->peerhash, peer, hash_alloc_intern); +void bgp_peer_conf_if_to_su_update(struct peer *peer) +{ + struct interface *ifp; + int prev_family; + int peer_addr_updated = 0; + + if (!peer->conf_if) + return; + + prev_family = peer->su.sa.sa_family; + if ((ifp = if_lookup_by_name(peer->conf_if, peer->bgp->vrf_id))) { + peer->ifp = ifp; + /* If BGP unnumbered is not "v6only", we first see if we can + * derive the + * peer's IPv4 address. + */ + if (!CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) + peer_addr_updated = + bgp_peer_conf_if_to_su_update_v4(peer, ifp); + + /* If "v6only" or we can't derive peer's IPv4 address, see if + * we've + * learnt the peer's IPv6 link-local address. This is from the + * source + * IPv6 address in router advertisement. + */ + if (!peer_addr_updated) + peer_addr_updated = + bgp_peer_conf_if_to_su_update_v6(peer, ifp); + } + /* If we could derive the peer address, we may need to install the + * password + * configured for the peer, if any, on the listen socket. Otherwise, + * mark + * that peer's address is not available and uninstall the password, if + * needed. + */ + if (peer_addr_updated) { + if (peer->password && prev_family == AF_UNSPEC) + bgp_md5_set(peer); + } else { + if (peer->password && prev_family != AF_UNSPEC) + bgp_md5_unset(peer); + peer->su.sa.sa_family = AF_UNSPEC; + memset(&peer->su.sin6.sin6_addr, 0, sizeof(struct in6_addr)); + } + + /* Since our su changed we need to del/add peer to the peerhash */ + hash_release(peer->bgp->peerhash, peer); + hash_get(peer->bgp->peerhash, peer, hash_alloc_intern); } /* Force a bestpath recalculation for all prefixes. This is used * when 'bgp bestpath' commands are entered. */ -void -bgp_recalculate_all_bestpaths (struct bgp *bgp) -{ - afi_t afi; - safi_t safi; - struct bgp_node *rn, *nrn; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - for (rn = bgp_table_top (bgp->rib[afi][safi]); rn; - rn = bgp_route_next (rn)) - { - if (rn->info != NULL) - { - /* Special handling for 2-level routing tables. */ - if (safi == SAFI_MPLS_VPN || - safi == SAFI_ENCAP || - safi == SAFI_EVPN) - { - for (nrn = bgp_table_top((struct bgp_table *)(rn->info)); - nrn; nrn = bgp_route_next (nrn)) - bgp_process (bgp, nrn, afi, safi); - } - else - bgp_process (bgp, rn, afi, safi); - } - } - } - } +void bgp_recalculate_all_bestpaths(struct bgp *bgp) +{ + afi_t afi; + safi_t safi; + struct bgp_node *rn, *nrn; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; + rn = bgp_route_next(rn)) { + if (rn->info != NULL) { + /* Special handling for 2-level routing + * tables. */ + if (safi == SAFI_MPLS_VPN + || safi == SAFI_ENCAP + || safi == SAFI_EVPN) { + for (nrn = bgp_table_top(( + struct bgp_table + *)(rn->info)); + nrn; + nrn = bgp_route_next(nrn)) + bgp_process(bgp, nrn, + afi, safi); + } else + bgp_process(bgp, rn, afi, safi); + } + } + } + } } /* Create new BGP peer. */ -struct peer * -peer_create (union sockunion *su, const char *conf_if, struct bgp *bgp, - as_t local_as, as_t remote_as, int as_type, afi_t afi, safi_t safi, struct peer_group *group) -{ - int active; - struct peer *peer; - char buf[SU_ADDRSTRLEN]; - - peer = peer_new (bgp); - if (conf_if) - { - peer->conf_if = XSTRDUP (MTYPE_PEER_CONF_IF, conf_if); - bgp_peer_conf_if_to_su_update(peer); - if (peer->host) - XFREE(MTYPE_BGP_PEER_HOST, peer->host); - peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, conf_if); - } - else if (su) - { - peer->su = *su; - sockunion2str (su, buf, SU_ADDRSTRLEN); - if (peer->host) - XFREE(MTYPE_BGP_PEER_HOST, peer->host); - peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf); - } - peer->local_as = local_as; - peer->as = remote_as; - peer->as_type = as_type; - peer->local_id = bgp->router_id; - peer->v_holdtime = bgp->default_holdtime; - peer->v_keepalive = bgp->default_keepalive; - if (peer_sort (peer) == BGP_PEER_IBGP) - peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; - else - peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; - - peer = peer_lock (peer); /* bgp peer list reference */ - peer->group = group; - listnode_add_sort (bgp->peer, peer); - hash_get(bgp->peerhash, peer, hash_alloc_intern); - - active = peer_active (peer); - - /* Last read and reset time set */ - peer->readtime = peer->resettime = bgp_clock (); - - /* Default TTL set. */ - peer->ttl = (peer->sort == BGP_PEER_IBGP) ? MAXTTL : 1; - - SET_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE); - - if (afi && safi) - { - peer->afc[afi][safi] = 1; - peer_af_create(peer, afi, safi); - } - - /* Set up peer's events and timers. */ - if (! active && peer_active (peer)) - bgp_timer_set (peer); - - return peer; +struct peer *peer_create(union sockunion *su, const char *conf_if, + struct bgp *bgp, as_t local_as, as_t remote_as, + int as_type, afi_t afi, safi_t safi, + struct peer_group *group) +{ + int active; + struct peer *peer; + char buf[SU_ADDRSTRLEN]; + + peer = peer_new(bgp); + if (conf_if) { + peer->conf_if = XSTRDUP(MTYPE_PEER_CONF_IF, conf_if); + bgp_peer_conf_if_to_su_update(peer); + if (peer->host) + XFREE(MTYPE_BGP_PEER_HOST, peer->host); + peer->host = XSTRDUP(MTYPE_BGP_PEER_HOST, conf_if); + } else if (su) { + peer->su = *su; + sockunion2str(su, buf, SU_ADDRSTRLEN); + if (peer->host) + XFREE(MTYPE_BGP_PEER_HOST, peer->host); + peer->host = XSTRDUP(MTYPE_BGP_PEER_HOST, buf); + } + peer->local_as = local_as; + peer->as = remote_as; + peer->as_type = as_type; + peer->local_id = bgp->router_id; + peer->v_holdtime = bgp->default_holdtime; + peer->v_keepalive = bgp->default_keepalive; + if (peer_sort(peer) == BGP_PEER_IBGP) + peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; + else + peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; + + peer = peer_lock(peer); /* bgp peer list reference */ + peer->group = group; + listnode_add_sort(bgp->peer, peer); + hash_get(bgp->peerhash, peer, hash_alloc_intern); + + active = peer_active(peer); + + /* Last read and reset time set */ + peer->readtime = peer->resettime = bgp_clock(); + + /* Default TTL set. */ + peer->ttl = (peer->sort == BGP_PEER_IBGP) ? MAXTTL : 1; + + SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); + + if (afi && safi) { + peer->afc[afi][safi] = 1; + peer_af_create(peer, afi, safi); + } + + /* Set up peer's events and timers. */ + if (!active && peer_active(peer)) + bgp_timer_set(peer); + + return peer; } /* Make accept BGP peer. This function is only called from the test code */ -struct peer * -peer_create_accept (struct bgp *bgp) +struct peer *peer_create_accept(struct bgp *bgp) { - struct peer *peer; + struct peer *peer; - peer = peer_new (bgp); + peer = peer_new(bgp); - peer = peer_lock (peer); /* bgp peer list reference */ - listnode_add_sort (bgp->peer, peer); + peer = peer_lock(peer); /* bgp peer list reference */ + listnode_add_sort(bgp->peer, peer); - return peer; + return peer; } /* Change peer's AS number. */ -void -peer_as_change (struct peer *peer, as_t as, int as_specified) -{ - bgp_peer_sort_t type; - struct peer *conf; - - /* Stop peer. */ - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - } - type = peer_sort (peer); - peer->as = as; - peer->as_type = as_specified; - - if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION) - && ! bgp_confederation_peers_check (peer->bgp, as) - && peer->bgp->as != as) - peer->local_as = peer->bgp->confed_id; - else - peer->local_as = peer->bgp->as; - - /* Advertisement-interval reset */ - conf = NULL; - if (peer->group) - conf = peer->group->conf; - - if (conf && CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV)) - { - peer->v_routeadv = conf->routeadv; - } - /* Only go back to the default advertisement-interval if the user had not - * already configured it */ - else if (!CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV)) - { - if (peer_sort (peer) == BGP_PEER_IBGP) - peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; - else - peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; - } - /* TTL reset */ - if (peer_sort (peer) == BGP_PEER_IBGP) - peer->ttl = MAXTTL; - else if (type == BGP_PEER_IBGP) - peer->ttl = 1; - - /* reflector-client reset */ - if (peer_sort (peer) != BGP_PEER_IBGP) - { - UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST], - PEER_FLAG_REFLECTOR_CLIENT); - UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST], - PEER_FLAG_REFLECTOR_CLIENT); - UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_LABELED_UNICAST], - PEER_FLAG_REFLECTOR_CLIENT); - UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN], - PEER_FLAG_REFLECTOR_CLIENT); - UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_ENCAP], - PEER_FLAG_REFLECTOR_CLIENT); - UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST], - PEER_FLAG_REFLECTOR_CLIENT); - UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST], - PEER_FLAG_REFLECTOR_CLIENT); - UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_LABELED_UNICAST], - PEER_FLAG_REFLECTOR_CLIENT); - UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MPLS_VPN], - PEER_FLAG_REFLECTOR_CLIENT); - UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_ENCAP], - PEER_FLAG_REFLECTOR_CLIENT); - UNSET_FLAG (peer->af_flags[AFI_L2VPN][SAFI_EVPN], - PEER_FLAG_REFLECTOR_CLIENT); - } - - /* local-as reset */ - if (peer_sort (peer) != BGP_PEER_EBGP) - { - peer->change_local_as = 0; - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); - } +void peer_as_change(struct peer *peer, as_t as, int as_specified) +{ + bgp_peer_sort_t type; + struct peer *conf; + + /* Stop peer. */ + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); + } + type = peer_sort(peer); + peer->as = as; + peer->as_type = as_specified; + + if (bgp_config_check(peer->bgp, BGP_CONFIG_CONFEDERATION) + && !bgp_confederation_peers_check(peer->bgp, as) + && peer->bgp->as != as) + peer->local_as = peer->bgp->confed_id; + else + peer->local_as = peer->bgp->as; + + /* Advertisement-interval reset */ + conf = NULL; + if (peer->group) + conf = peer->group->conf; + + if (conf && CHECK_FLAG(conf->config, PEER_CONFIG_ROUTEADV)) { + peer->v_routeadv = conf->routeadv; + } + /* Only go back to the default advertisement-interval if the user had + * not + * already configured it */ + else if (!CHECK_FLAG(peer->config, PEER_CONFIG_ROUTEADV)) { + if (peer_sort(peer) == BGP_PEER_IBGP) + peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; + else + peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; + } + /* TTL reset */ + if (peer_sort(peer) == BGP_PEER_IBGP) + peer->ttl = MAXTTL; + else if (type == BGP_PEER_IBGP) + peer->ttl = 1; + + /* reflector-client reset */ + if (peer_sort(peer) != BGP_PEER_IBGP) { + UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_UNICAST], + PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_MULTICAST], + PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_LABELED_UNICAST], + PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_MPLS_VPN], + PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_ENCAP], + PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_UNICAST], + PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_MULTICAST], + PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_LABELED_UNICAST], + PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_MPLS_VPN], + PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_ENCAP], + PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_L2VPN][SAFI_EVPN], + PEER_FLAG_REFLECTOR_CLIENT); + } + + /* local-as reset */ + if (peer_sort(peer) != BGP_PEER_EBGP) { + peer->change_local_as = 0; + UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); + UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); + } } /* If peer does not exist, create new one. If peer already exists, set AS number to the peer. */ -int -peer_remote_as (struct bgp *bgp, union sockunion *su, const char *conf_if, - as_t *as, int as_type, afi_t afi, safi_t safi) -{ - struct peer *peer; - as_t local_as; - - if (conf_if) - peer = peer_lookup_by_conf_if (bgp, conf_if); - else - peer = peer_lookup (bgp, su); - - if (peer) - { - /* Not allowed for a dynamic peer. */ - if (peer_dynamic_neighbor (peer)) - { - *as = peer->as; - return BGP_ERR_INVALID_FOR_DYNAMIC_PEER; - } - - /* When this peer is a member of peer-group. */ - if (peer->group) - { - if (peer->group->conf->as) - { - /* Return peer group's AS number. */ - *as = peer->group->conf->as; - return BGP_ERR_PEER_GROUP_MEMBER; - } - if (peer_sort (peer->group->conf) == BGP_PEER_IBGP) - { - if ((as_type != AS_INTERNAL) && (bgp->as != *as)) - { - *as = peer->as; - return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT; - } - } - else - { - if ((as_type != AS_EXTERNAL) && (bgp->as == *as)) - { - *as = peer->as; - return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT; - } - } - } - - /* Existing peer's AS number change. */ - if (((peer->as_type == AS_SPECIFIED) && peer->as != *as) || - (peer->as_type != as_type)) - peer_as_change (peer, *as, as_type); - } - else - { - if (conf_if) - return BGP_ERR_NO_INTERFACE_CONFIG; - - /* If the peer is not part of our confederation, and its not an - iBGP peer then spoof the source AS */ - if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION) - && ! bgp_confederation_peers_check (bgp, *as) - && bgp->as != *as) - local_as = bgp->confed_id; - else - local_as = bgp->as; - - /* If this is IPv4 unicast configuration and "no bgp default - ipv4-unicast" is specified. */ - - if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4) - && afi == AFI_IP && safi == SAFI_UNICAST) - peer_create (su, conf_if, bgp, local_as, *as, as_type, 0, 0, NULL); - else - peer_create (su, conf_if, bgp, local_as, *as, as_type, afi, safi, NULL); - } - - return 0; -} - -static int -non_peergroup_activate_af (struct peer *peer, afi_t afi, safi_t safi) -{ - int active; - - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - zlog_err("%s was called for peer-group %s", __func__, peer->host); - return 1; - } - - /* Do not activate a peer for both SAFI_UNICAST and SAFI_LABELED_UNICAST */ - if ((safi == SAFI_UNICAST && peer->afc[afi][SAFI_LABELED_UNICAST]) || - (safi == SAFI_LABELED_UNICAST && peer->afc[afi][SAFI_UNICAST])) - return BGP_ERR_PEER_SAFI_CONFLICT; - - /* Nothing to do if we've already activated this peer */ - if (peer->afc[afi][safi]) - return 0; - - if (peer_af_create(peer, afi, safi) == NULL) - return 1; - - active = peer_active (peer); - peer->afc[afi][safi] = 1; - - if (!active && peer_active (peer)) - { - bgp_timer_set (peer); - } - else - { - if (peer->status == Established) - { - if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV)) - { - peer->afc_adv[afi][safi] = 1; - bgp_capability_send (peer, afi, safi, - CAPABILITY_CODE_MP, - CAPABILITY_ACTION_SET); - if (peer->afc_recv[afi][safi]) - { - peer->afc_nego[afi][safi] = 1; - bgp_announce_route (peer, afi, safi); - } - } - else - { - peer->last_reset = PEER_DOWN_AF_ACTIVATE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - } - } - - return 0; -} +int peer_remote_as(struct bgp *bgp, union sockunion *su, const char *conf_if, + as_t *as, int as_type, afi_t afi, safi_t safi) +{ + struct peer *peer; + as_t local_as; + + if (conf_if) + peer = peer_lookup_by_conf_if(bgp, conf_if); + else + peer = peer_lookup(bgp, su); + + if (peer) { + /* Not allowed for a dynamic peer. */ + if (peer_dynamic_neighbor(peer)) { + *as = peer->as; + return BGP_ERR_INVALID_FOR_DYNAMIC_PEER; + } -/* Activate the peer or peer group for specified AFI and SAFI. */ -int -peer_activate (struct peer *peer, afi_t afi, safi_t safi) -{ - int ret = 0; - struct peer_group *group; - struct listnode *node, *nnode; - struct peer *tmp_peer; - - /* Nothing to do if we've already activated this peer */ - if (peer->afc[afi][safi]) - return ret; - - /* This is a peer-group so activate all of the members of the - * peer-group as well */ - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - - /* Do not activate a peer for both SAFI_UNICAST and SAFI_LABELED_UNICAST */ - if ((safi == SAFI_UNICAST && peer->afc[afi][SAFI_LABELED_UNICAST]) || - (safi == SAFI_LABELED_UNICAST && peer->afc[afi][SAFI_UNICAST])) - return BGP_ERR_PEER_SAFI_CONFLICT; - - peer->afc[afi][safi] = 1; - group = peer->group; - - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer)) - { - ret |= non_peergroup_activate_af (tmp_peer, afi, safi); - } - } - else - { - ret |= non_peergroup_activate_af (peer, afi, safi); - } - - return ret; -} - -static int -non_peergroup_deactivate_af (struct peer *peer, afi_t afi, safi_t safi) -{ - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - zlog_err("%s was called for peer-group %s", __func__, peer->host); - return 1; - } - - /* Nothing to do if we've already deactivated this peer */ - if (! peer->afc[afi][safi]) - return 0; - - /* De-activate the address family configuration. */ - peer->afc[afi][safi] = 0; - - if (peer_af_delete(peer, afi, safi) != 0) - { - zlog_err("couldn't delete af structure for peer %s", peer->host); - return 1; - } - - if (peer->status == Established) - { - if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV)) - { - peer->afc_adv[afi][safi] = 0; - peer->afc_nego[afi][safi] = 0; - - if (peer_active_nego (peer)) - { - bgp_capability_send (peer, afi, safi, - CAPABILITY_CODE_MP, - CAPABILITY_ACTION_UNSET); - bgp_clear_route (peer, afi, safi); - peer->pcount[afi][safi] = 0; - } - else - { - peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - } - else - { - peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - } - - return 0; -} - -int -peer_deactivate (struct peer *peer, afi_t afi, safi_t safi) -{ - int ret = 0; - struct peer_group *group; - struct peer *tmp_peer; - struct listnode *node, *nnode; - - /* Nothing to do if we've already de-activated this peer */ - if (! peer->afc[afi][safi]) - return ret; - - /* This is a peer-group so de-activate all of the members of the - * peer-group as well */ - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer->afc[afi][safi] = 0; - group = peer->group; - - if (peer_af_delete(peer, afi, safi) != 0) - { - zlog_err("couldn't delete af structure for peer %s", peer->host); - } - - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer)) - { - ret |= non_peergroup_deactivate_af (tmp_peer, afi, safi); - } - } - else - { - ret |= non_peergroup_deactivate_af (peer, afi, safi); - } - - return ret; -} - -int -peer_afc_set (struct peer *peer, afi_t afi, safi_t safi, int enable) -{ - if (enable) - return peer_activate (peer, afi, safi); - else - return peer_deactivate (peer, afi, safi); -} - -static void -peer_nsf_stop (struct peer *peer) -{ - afi_t afi; - safi_t safi; - - UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT); - UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE); - - for (afi = AFI_IP ; afi < AFI_MAX ; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_4 ; safi++) - peer->nsf[afi][safi] = 0; - - if (peer->t_gr_restart) - { - BGP_TIMER_OFF (peer->t_gr_restart); - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s graceful restart timer stopped", peer->host); - } - if (peer->t_gr_stale) - { - BGP_TIMER_OFF (peer->t_gr_stale); - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s graceful restart stalepath timer stopped", peer->host); - } - bgp_clear_route_all (peer); -} + /* When this peer is a member of peer-group. */ + if (peer->group) { + if (peer->group->conf->as) { + /* Return peer group's AS number. */ + *as = peer->group->conf->as; + return BGP_ERR_PEER_GROUP_MEMBER; + } + if (peer_sort(peer->group->conf) == BGP_PEER_IBGP) { + if ((as_type != AS_INTERNAL) + && (bgp->as != *as)) { + *as = peer->as; + return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT; + } + } else { + if ((as_type != AS_EXTERNAL) + && (bgp->as == *as)) { + *as = peer->as; + return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT; + } + } + } -/* Delete peer from confguration. - * - * The peer is moved to a dead-end "Deleted" neighbour-state, to allow - * it to "cool off" and refcounts to hit 0, at which state it is freed. - * - * This function /should/ take care to be idempotent, to guard against - * it being called multiple times through stray events that come in - * that happen to result in this function being called again. That - * said, getting here for a "Deleted" peer is a bug in the neighbour - * FSM. - */ -int -peer_delete (struct peer *peer) -{ - int i; - afi_t afi; - safi_t safi; - struct bgp *bgp; - struct bgp_filter *filter; - struct listnode *pn; - int accept_peer; - - assert (peer->status != Deleted); - - bgp = peer->bgp; - accept_peer = CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER); - - if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT)) - peer_nsf_stop (peer); - - SET_FLAG(peer->flags, PEER_FLAG_DELETE); - - /* If this peer belongs to peer group, clear up the - relationship. */ - if (peer->group) - { - if (peer_dynamic_neighbor(peer)) - peer_drop_dynamic_neighbor(peer); - - if ((pn = listnode_lookup (peer->group->peer, peer))) - { - peer = peer_unlock (peer); /* group->peer list reference */ - list_delete_node (peer->group->peer, pn); - } - peer->group = NULL; - } - - /* Withdraw all information from routing table. We can not use - * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is - * executed after peer structure is deleted. - */ - peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE; - bgp_stop (peer); - UNSET_FLAG(peer->flags, PEER_FLAG_DELETE); - - if (peer->doppelganger) - { - peer->doppelganger->doppelganger = NULL; - peer->doppelganger = NULL; - } - - UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER); - bgp_fsm_change_status (peer, Deleted); - - /* Remove from NHT */ - if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) - bgp_unlink_nexthop_by_peer (peer); - - /* Password configuration */ - if (peer->password) - { - XFREE (MTYPE_PEER_PASSWORD, peer->password); - peer->password = NULL; - - if (!accept_peer && - ! BGP_PEER_SU_UNSPEC(peer) && - ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - bgp_md5_unset (peer); - } - - bgp_timer_set (peer); /* stops all timers for Deleted */ - - /* Delete from all peer list. */ - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP) - && (pn = listnode_lookup (bgp->peer, peer))) - { - peer_unlock (peer); /* bgp peer list reference */ - list_delete_node (bgp->peer, pn); - hash_release(bgp->peerhash, peer); - } - - /* Buffers. */ - if (peer->ibuf) - { - stream_free (peer->ibuf); - peer->ibuf = NULL; - } - - if (peer->obuf) - { - stream_fifo_free (peer->obuf); - peer->obuf = NULL; - } - - if (peer->work) - { - stream_free (peer->work); - peer->work = NULL; - } - - if (peer->scratch) - { - stream_free(peer->scratch); - peer->scratch = NULL; - } - - /* Local and remote addresses. */ - if (peer->su_local) - { - sockunion_free (peer->su_local); - peer->su_local = NULL; - } - - if (peer->su_remote) - { - sockunion_free (peer->su_remote); - peer->su_remote = NULL; - } - - /* Free filter related memory. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - filter = &peer->filter[afi][safi]; + /* Existing peer's AS number change. */ + if (((peer->as_type == AS_SPECIFIED) && peer->as != *as) + || (peer->as_type != as_type)) + peer_as_change(peer, *as, as_type); + } else { + if (conf_if) + return BGP_ERR_NO_INTERFACE_CONFIG; + + /* If the peer is not part of our confederation, and its not an + iBGP peer then spoof the source AS */ + if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION) + && !bgp_confederation_peers_check(bgp, *as) + && bgp->as != *as) + local_as = bgp->confed_id; + else + local_as = bgp->as; + + /* If this is IPv4 unicast configuration and "no bgp default + ipv4-unicast" is specified. */ + + if (bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4) + && afi == AFI_IP && safi == SAFI_UNICAST) + peer_create(su, conf_if, bgp, local_as, *as, as_type, 0, + 0, NULL); + else + peer_create(su, conf_if, bgp, local_as, *as, as_type, + afi, safi, NULL); + } - for (i = FILTER_IN; i < FILTER_MAX; i++) - { - if (filter->dlist[i].name) - { - XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[i].name); - filter->dlist[i].name = NULL; - } - - if (filter->plist[i].name) - { - XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[i].name); - filter->plist[i].name = NULL; - } - - if (filter->aslist[i].name) - { - XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[i].name); - filter->aslist[i].name = NULL; - } - } - - for (i = RMAP_IN; i < RMAP_MAX; i++) - { - if (filter->map[i].name) - { - XFREE(MTYPE_BGP_FILTER_NAME, filter->map[i].name); - filter->map[i].name = NULL; - } - } + return 0; +} - if (filter->usmap.name) - { - XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); - filter->usmap.name = NULL; - } +static int non_peergroup_activate_af(struct peer *peer, afi_t afi, safi_t safi) +{ + int active; - if (peer->default_rmap[afi][safi].name) - { - XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name); - peer->default_rmap[afi][safi].name = NULL; - } - } + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + zlog_err("%s was called for peer-group %s", __func__, + peer->host); + return 1; + } - FOREACH_AFI_SAFI (afi, safi) - peer_af_delete (peer, afi, safi); + /* Do not activate a peer for both SAFI_UNICAST and SAFI_LABELED_UNICAST + */ + if ((safi == SAFI_UNICAST && peer->afc[afi][SAFI_LABELED_UNICAST]) + || (safi == SAFI_LABELED_UNICAST && peer->afc[afi][SAFI_UNICAST])) + return BGP_ERR_PEER_SAFI_CONFLICT; + + /* Nothing to do if we've already activated this peer */ + if (peer->afc[afi][safi]) + return 0; + + if (peer_af_create(peer, afi, safi) == NULL) + return 1; + + active = peer_active(peer); + peer->afc[afi][safi] = 1; + + if (!active && peer_active(peer)) { + bgp_timer_set(peer); + } else { + if (peer->status == Established) { + if (CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV)) { + peer->afc_adv[afi][safi] = 1; + bgp_capability_send(peer, afi, safi, + CAPABILITY_CODE_MP, + CAPABILITY_ACTION_SET); + if (peer->afc_recv[afi][safi]) { + peer->afc_nego[afi][safi] = 1; + bgp_announce_route(peer, afi, safi); + } + } else { + peer->last_reset = PEER_DOWN_AF_ACTIVATE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } + } + } - if (peer->hostname) - { - XFREE(MTYPE_BGP_PEER_HOST, peer->hostname); - peer->hostname = NULL; - } + return 0; +} - if (peer->domainname) - { - XFREE(MTYPE_BGP_PEER_HOST, peer->domainname); - peer->domainname = NULL; - } - - peer_unlock (peer); /* initial reference */ +/* Activate the peer or peer group for specified AFI and SAFI. */ +int peer_activate(struct peer *peer, afi_t afi, safi_t safi) +{ + int ret = 0; + struct peer_group *group; + struct listnode *node, *nnode; + struct peer *tmp_peer; + + /* Nothing to do if we've already activated this peer */ + if (peer->afc[afi][safi]) + return ret; + + /* This is a peer-group so activate all of the members of the + * peer-group as well */ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + + /* Do not activate a peer for both SAFI_UNICAST and + * SAFI_LABELED_UNICAST */ + if ((safi == SAFI_UNICAST + && peer->afc[afi][SAFI_LABELED_UNICAST]) + || (safi == SAFI_LABELED_UNICAST + && peer->afc[afi][SAFI_UNICAST])) + return BGP_ERR_PEER_SAFI_CONFLICT; + + peer->afc[afi][safi] = 1; + group = peer->group; + + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) { + ret |= non_peergroup_activate_af(tmp_peer, afi, safi); + } + } else { + ret |= non_peergroup_activate_af(peer, afi, safi); + } - return 0; + return ret; } -static int -peer_group_cmp (struct peer_group *g1, struct peer_group *g2) +static int non_peergroup_deactivate_af(struct peer *peer, afi_t afi, + safi_t safi) { - return strcmp (g1->name, g2->name); -} + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + zlog_err("%s was called for peer-group %s", __func__, + peer->host); + return 1; + } -/* Peer group cofiguration. */ -static struct peer_group * -peer_group_new (void) -{ - return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP, - sizeof (struct peer_group)); -} + /* Nothing to do if we've already deactivated this peer */ + if (!peer->afc[afi][safi]) + return 0; -static void -peer_group_free (struct peer_group *group) -{ - XFREE (MTYPE_PEER_GROUP, group); -} + /* De-activate the address family configuration. */ + peer->afc[afi][safi] = 0; -struct peer_group * -peer_group_lookup (struct bgp *bgp, const char *name) -{ - struct peer_group *group; - struct listnode *node, *nnode; + if (peer_af_delete(peer, afi, safi) != 0) { + zlog_err("couldn't delete af structure for peer %s", + peer->host); + return 1; + } - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - { - if (strcmp (group->name, name) == 0) - return group; - } - return NULL; -} + if (peer->status == Established) { + if (CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV)) { + peer->afc_adv[afi][safi] = 0; + peer->afc_nego[afi][safi] = 0; + + if (peer_active_nego(peer)) { + bgp_capability_send(peer, afi, safi, + CAPABILITY_CODE_MP, + CAPABILITY_ACTION_UNSET); + bgp_clear_route(peer, afi, safi); + peer->pcount[afi][safi] = 0; + } else { + peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } + } else { + peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } + } -struct peer_group * -peer_group_get (struct bgp *bgp, const char *name) -{ - struct peer_group *group; - afi_t afi; - - group = peer_group_lookup (bgp, name); - if (group) - return group; - - group = peer_group_new (); - group->bgp = bgp; - if (group->name) - XFREE(MTYPE_PEER_GROUP_HOST, group->name); - group->name = XSTRDUP(MTYPE_PEER_GROUP_HOST, name); - group->peer = list_new (); - for (afi = AFI_IP; afi < AFI_MAX; afi++) - group->listen_range[afi] = list_new (); - group->conf = peer_new (bgp); - if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)) - group->conf->afc[AFI_IP][SAFI_UNICAST] = 1; - if (group->conf->host) - XFREE(MTYPE_BGP_PEER_HOST, group->conf->host); - group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name); - group->conf->group = group; - group->conf->as = 0; - group->conf->ttl = 1; - group->conf->gtsm_hops = 0; - group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; - UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER); - UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT); - group->conf->keepalive = 0; - group->conf->holdtime = 0; - group->conf->connect = 0; - SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP); - listnode_add_sort (bgp->group, group); - - return group; -} - -static void -peer_group2peer_config_copy (struct peer_group *group, struct peer *peer) -{ - struct peer *conf; - int v6only; - - conf = group->conf; - - /* remote-as */ - if (conf->as) - peer->as = conf->as; - - /* remote-as */ - if (conf->change_local_as) - peer->change_local_as = conf->change_local_as; - - /* TTL */ - peer->ttl = conf->ttl; - - /* GTSM hops */ - peer->gtsm_hops = conf->gtsm_hops; - - /* this flag is per-neighbor and so has to be preserved */ - v6only = CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); - - /* peer flags apply */ - peer->flags = conf->flags; - - if (v6only) - SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); - - /* peer config apply */ - peer->config = conf->config; - - /* peer timers apply */ - peer->holdtime = conf->holdtime; - peer->keepalive = conf->keepalive; - peer->connect = conf->connect; - if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT)) - peer->v_connect = conf->connect; - else - peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; - - /* advertisement-interval reset */ - if (CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV)) - peer->v_routeadv = conf->routeadv; - else - if (peer_sort (peer) == BGP_PEER_IBGP) - peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; - else - peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; - - /* password apply */ - if (conf->password && !peer->password) - peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password); - - if (! BGP_PEER_SU_UNSPEC(peer)) - bgp_md5_set (peer); - - /* update-source apply */ - if (conf->update_source) - { - if (peer->update_source) - sockunion_free (peer->update_source); - if (peer->update_if) - { - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - peer->update_if = NULL; - } - peer->update_source = sockunion_dup (conf->update_source); - } - else if (conf->update_if) - { - if (peer->update_if) - XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - if (peer->update_source) - { - sockunion_free (peer->update_source); - peer->update_source = NULL; - } - peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if); - } - - bgp_bfd_peer_group2peer_copy(conf, peer); -} - -static void -peer_group2peer_config_copy_af (struct peer_group *group, struct peer *peer, - afi_t afi, safi_t safi) -{ - int in = FILTER_IN; - int out = FILTER_OUT; - struct peer *conf; - struct bgp_filter *pfilter; - struct bgp_filter *gfilter; - - conf = group->conf; - pfilter = &peer->filter[afi][safi]; - gfilter = &conf->filter[afi][safi]; - - /* peer af_flags apply */ - peer->af_flags[afi][safi] = conf->af_flags[afi][safi]; - - /* maximum-prefix */ - peer->pmax[afi][safi] = conf->pmax[afi][safi]; - peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi]; - peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi]; - - /* allowas-in */ - peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi]; - - /* weight */ - peer->weight[afi][safi] = conf->weight[afi][safi]; - - /* default-originate route-map */ - if (conf->default_rmap[afi][safi].name) - { - if (peer->default_rmap[afi][safi].name) - XFREE(MTYPE_BGP_FILTER_NAME, peer->default_rmap[afi][safi].name); - peer->default_rmap[afi][safi].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, conf->default_rmap[afi][safi].name); - peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map; - } - - /* inbound filter apply */ - if (gfilter->dlist[in].name && ! pfilter->dlist[in].name) - { - if (pfilter->dlist[in].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[in].name); - pfilter->dlist[in].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->dlist[in].name); - pfilter->dlist[in].alist = gfilter->dlist[in].alist; - } - - if (gfilter->plist[in].name && ! pfilter->plist[in].name) - { - if (pfilter->plist[in].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[in].name); - pfilter->plist[in].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->plist[in].name); - pfilter->plist[in].plist = gfilter->plist[in].plist; - } - - if (gfilter->aslist[in].name && ! pfilter->aslist[in].name) - { - if (pfilter->aslist[in].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[in].name); - pfilter->aslist[in].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->aslist[in].name); - pfilter->aslist[in].aslist = gfilter->aslist[in].aslist; - } - - if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name) - { - if (pfilter->map[RMAP_IN].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->map[RMAP_IN].name); - pfilter->map[RMAP_IN].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->map[RMAP_IN].name); - pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map; - } - - /* outbound filter apply */ - if (gfilter->dlist[out].name) - { - if (pfilter->dlist[out].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[out].name); - pfilter->dlist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->dlist[out].name); - pfilter->dlist[out].alist = gfilter->dlist[out].alist; - } - else - { - if (pfilter->dlist[out].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[out].name); - pfilter->dlist[out].name = NULL; - pfilter->dlist[out].alist = NULL; - } - - if (gfilter->plist[out].name) - { - if (pfilter->plist[out].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[out].name); - pfilter->plist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->plist[out].name); - pfilter->plist[out].plist = gfilter->plist[out].plist; - } - else - { - if (pfilter->plist[out].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[out].name); - pfilter->plist[out].name = NULL; - pfilter->plist[out].plist = NULL; - } - - if (gfilter->aslist[out].name) - { - if (pfilter->aslist[out].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[out].name); - pfilter->aslist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->aslist[out].name); - pfilter->aslist[out].aslist = gfilter->aslist[out].aslist; - } - else - { - if (pfilter->aslist[out].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[out].name); - pfilter->aslist[out].name = NULL; - pfilter->aslist[out].aslist = NULL; - } - - if (gfilter->map[RMAP_OUT].name) - { - if (pfilter->map[RMAP_OUT].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->map[RMAP_OUT].name); - pfilter->map[RMAP_OUT].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->map[RMAP_OUT].name); - pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map; - } - else - { - if (pfilter->map[RMAP_OUT].name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->map[RMAP_OUT].name); - pfilter->map[RMAP_OUT].name = NULL; - pfilter->map[RMAP_OUT].map = NULL; - } - - if (gfilter->usmap.name) - { - if (pfilter->usmap.name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->usmap.name); - pfilter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->usmap.name); - pfilter->usmap.map = gfilter->usmap.map; - } - else - { - if (pfilter->usmap.name) - XFREE(MTYPE_BGP_FILTER_NAME, pfilter->usmap.name); - pfilter->usmap.name = NULL; - pfilter->usmap.map = NULL; - } -} + return 0; +} -/* Peer group's remote AS configuration. */ -int -peer_group_remote_as (struct bgp *bgp, const char *group_name, - as_t *as, int as_type) +int peer_deactivate(struct peer *peer, afi_t afi, safi_t safi) { - struct peer_group *group; - struct peer *peer; - struct listnode *node, *nnode; + int ret = 0; + struct peer_group *group; + struct peer *tmp_peer; + struct listnode *node, *nnode; - group = peer_group_lookup (bgp, group_name); - if (! group) - return -1; + /* Nothing to do if we've already de-activated this peer */ + if (!peer->afc[afi][safi]) + return ret; - if ((as_type == group->conf->as_type) && (group->conf->as == *as)) - return 0; + /* This is a peer-group so de-activate all of the members of the + * peer-group as well */ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer->afc[afi][safi] = 0; + group = peer->group; + if (peer_af_delete(peer, afi, safi) != 0) { + zlog_err("couldn't delete af structure for peer %s", + peer->host); + } - /* When we setup peer-group AS number all peer group member's AS - number must be updated to same number. */ - peer_as_change (group->conf, *as, as_type); + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) { + ret |= non_peergroup_deactivate_af(tmp_peer, afi, safi); + } + } else { + ret |= non_peergroup_deactivate_af(peer, afi, safi); + } - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (((peer->as_type == AS_SPECIFIED) && peer->as != *as) || - (peer->as_type != as_type)) - peer_as_change (peer, *as, as_type); - } + return ret; +} - return 0; +int peer_afc_set(struct peer *peer, afi_t afi, safi_t safi, int enable) +{ + if (enable) + return peer_activate(peer, afi, safi); + else + return peer_deactivate(peer, afi, safi); } -int -peer_group_delete (struct peer_group *group) +static void peer_nsf_stop(struct peer *peer) { - struct bgp *bgp; - struct peer *peer; - struct prefix *prefix; - struct peer *other; - struct listnode *node, *nnode; - afi_t afi; + afi_t afi; + safi_t safi; - bgp = group->bgp; + UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT); + UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE); - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - other = peer->doppelganger; - peer_delete (peer); - if (other && other->status != Deleted) - { - other->group = NULL; - peer_delete(other); + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_RESERVED_4; safi++) + peer->nsf[afi][safi] = 0; + + if (peer->t_gr_restart) { + BGP_TIMER_OFF(peer->t_gr_restart); + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s graceful restart timer stopped", + peer->host); } - } - list_delete (group->peer); + if (peer->t_gr_stale) { + BGP_TIMER_OFF(peer->t_gr_stale); + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s graceful restart stalepath timer stopped", + peer->host); + } + bgp_clear_route_all(peer); +} - for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, prefix)) - { - prefix_free(prefix); - } - list_delete (group->listen_range[afi]); - } +/* Delete peer from confguration. + * + * The peer is moved to a dead-end "Deleted" neighbour-state, to allow + * it to "cool off" and refcounts to hit 0, at which state it is freed. + * + * This function /should/ take care to be idempotent, to guard against + * it being called multiple times through stray events that come in + * that happen to result in this function being called again. That + * said, getting here for a "Deleted" peer is a bug in the neighbour + * FSM. + */ +int peer_delete(struct peer *peer) +{ + int i; + afi_t afi; + safi_t safi; + struct bgp *bgp; + struct bgp_filter *filter; + struct listnode *pn; + int accept_peer; - XFREE(MTYPE_PEER_GROUP_HOST, group->name); - group->name = NULL; + assert(peer->status != Deleted); - bfd_info_free(&(group->conf->bfd_info)); + bgp = peer->bgp; + accept_peer = CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER); - group->conf->group = NULL; - peer_delete (group->conf); + if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) + peer_nsf_stop(peer); - /* Delete from all peer_group list. */ - listnode_delete (bgp->group, group); + SET_FLAG(peer->flags, PEER_FLAG_DELETE); - peer_group_free (group); + /* If this peer belongs to peer group, clear up the + relationship. */ + if (peer->group) { + if (peer_dynamic_neighbor(peer)) + peer_drop_dynamic_neighbor(peer); - return 0; -} + if ((pn = listnode_lookup(peer->group->peer, peer))) { + peer = peer_unlock( + peer); /* group->peer list reference */ + list_delete_node(peer->group->peer, pn); + } + peer->group = NULL; + } -int -peer_group_remote_as_delete (struct peer_group *group) -{ - struct peer *peer, *other; - struct listnode *node, *nnode; + /* Withdraw all information from routing table. We can not use + * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is + * executed after peer structure is deleted. + */ + peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE; + bgp_stop(peer); + UNSET_FLAG(peer->flags, PEER_FLAG_DELETE); + + if (peer->doppelganger) { + peer->doppelganger->doppelganger = NULL; + peer->doppelganger = NULL; + } - if ((group->conf->as_type == AS_UNSPECIFIED) || - ((! group->conf->as) && (group->conf->as_type == AS_SPECIFIED))) - return 0; + UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER); + bgp_fsm_change_status(peer, Deleted); - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - other = peer->doppelganger; + /* Remove from NHT */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) + bgp_unlink_nexthop_by_peer(peer); - peer_delete (peer); + /* Password configuration */ + if (peer->password) { + XFREE(MTYPE_PEER_PASSWORD, peer->password); + peer->password = NULL; - if (other && other->status != Deleted) - { - other->group = NULL; - peer_delete(other); + if (!accept_peer && !BGP_PEER_SU_UNSPEC(peer) + && !CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + bgp_md5_unset(peer); } - } - list_delete_all_node (group->peer); - group->conf->as = 0; - group->conf->as_type = AS_UNSPECIFIED; + bgp_timer_set(peer); /* stops all timers for Deleted */ - return 0; -} + /* Delete from all peer list. */ + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) + && (pn = listnode_lookup(bgp->peer, peer))) { + peer_unlock(peer); /* bgp peer list reference */ + list_delete_node(bgp->peer, pn); + hash_release(bgp->peerhash, peer); + } -int -peer_group_listen_range_add (struct peer_group *group, struct prefix *range) -{ - struct prefix *prefix; - struct listnode *node, *nnode; - afi_t afi; - - afi = family2afi(range->family); - - /* Group needs remote AS configured. */ - if (group->conf->as_type == AS_UNSPECIFIED) - return BGP_ERR_PEER_GROUP_NO_REMOTE_AS; - - /* Ensure no duplicates. Currently we don't care about overlaps. */ - for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, prefix)) - { - if (prefix_same(range, prefix)) - return 0; - } + /* Buffers. */ + if (peer->ibuf) { + stream_free(peer->ibuf); + peer->ibuf = NULL; + } - prefix = prefix_new(); - prefix_copy(prefix, range); - listnode_add(group->listen_range[afi], prefix); - return 0; -} + if (peer->obuf) { + stream_fifo_free(peer->obuf); + peer->obuf = NULL; + } -int -peer_group_listen_range_del (struct peer_group *group, struct prefix *range) -{ - struct prefix *prefix, prefix2; - struct listnode *node, *nnode; - struct peer *peer; - afi_t afi; - char buf[PREFIX2STR_BUFFER]; + if (peer->work) { + stream_free(peer->work); + peer->work = NULL; + } - afi = family2afi(range->family); + if (peer->scratch) { + stream_free(peer->scratch); + peer->scratch = NULL; + } - /* Identify the listen range. */ - for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, prefix)) - { - if (prefix_same(range, prefix)) - break; - } + /* Local and remote addresses. */ + if (peer->su_local) { + sockunion_free(peer->su_local); + peer->su_local = NULL; + } - if (!prefix) - return BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND; + if (peer->su_remote) { + sockunion_free(peer->su_remote); + peer->su_remote = NULL; + } - prefix2str(prefix, buf, sizeof(buf)); + /* Free filter related memory. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + filter = &peer->filter[afi][safi]; + + for (i = FILTER_IN; i < FILTER_MAX; i++) { + if (filter->dlist[i].name) { + XFREE(MTYPE_BGP_FILTER_NAME, + filter->dlist[i].name); + filter->dlist[i].name = NULL; + } + + if (filter->plist[i].name) { + XFREE(MTYPE_BGP_FILTER_NAME, + filter->plist[i].name); + filter->plist[i].name = NULL; + } + + if (filter->aslist[i].name) { + XFREE(MTYPE_BGP_FILTER_NAME, + filter->aslist[i].name); + filter->aslist[i].name = NULL; + } + } + + for (i = RMAP_IN; i < RMAP_MAX; i++) { + if (filter->map[i].name) { + XFREE(MTYPE_BGP_FILTER_NAME, + filter->map[i].name); + filter->map[i].name = NULL; + } + } + + if (filter->usmap.name) { + XFREE(MTYPE_BGP_FILTER_NAME, + filter->usmap.name); + filter->usmap.name = NULL; + } + + if (peer->default_rmap[afi][safi].name) { + XFREE(MTYPE_ROUTE_MAP_NAME, + peer->default_rmap[afi][safi].name); + peer->default_rmap[afi][safi].name = NULL; + } + } - /* Dispose off any dynamic neighbors that exist due to this listen range */ - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (!peer_dynamic_neighbor (peer)) - continue; + FOREACH_AFI_SAFI(afi, safi) + peer_af_delete(peer, afi, safi); - sockunion2hostprefix(&peer->su, &prefix2); - if (prefix_match(prefix, &prefix2)) - { - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("Deleting dynamic neighbor %s group %s upon " - "delete of listen range %s", - peer->host, group->name, buf); - peer_delete (peer); - } - } + if (peer->hostname) { + XFREE(MTYPE_BGP_PEER_HOST, peer->hostname); + peer->hostname = NULL; + } - /* Get rid of the listen range */ - listnode_delete(group->listen_range[afi], prefix); + if (peer->domainname) { + XFREE(MTYPE_BGP_PEER_HOST, peer->domainname); + peer->domainname = NULL; + } - return 0; -} + peer_unlock(peer); /* initial reference */ -/* Bind specified peer to peer group. */ -int -peer_group_bind (struct bgp *bgp, union sockunion *su, struct peer *peer, - struct peer_group *group, as_t *as) -{ - int first_member = 0; - afi_t afi; - safi_t safi; - int cap_enhe_preset = 0; - - /* Lookup the peer. */ - if (!peer) - peer = peer_lookup (bgp, su); - - /* The peer exist, bind it to the peer-group */ - if (peer) - { - /* When the peer already belongs to peer group, check the consistency. */ - if (peer_group_active (peer) && strcmp (peer->group->name, group->name) != 0) - return BGP_ERR_PEER_GROUP_CANT_CHANGE; - - /* The peer has not specified a remote-as, inherit it from the - * peer-group */ - if (peer->as_type == AS_UNSPECIFIED) - { - peer->as_type = group->conf->as_type; - peer->as = group->conf->as; - } - - if (! group->conf->as) - { - if (peer_sort (group->conf) != BGP_PEER_INTERNAL - && peer_sort (group->conf) != peer_sort (peer)) - { - if (as) - *as = peer->as; - return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT; - } - - if (peer_sort (group->conf) == BGP_PEER_INTERNAL) - first_member = 1; - } - - if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE)) - cap_enhe_preset = 1; - - peer_group2peer_config_copy(group, peer); - - /* - * Capability extended-nexthop is enabled for an interface neighbor by - * default. So, fix that up here. - */ - if (peer->conf_if && cap_enhe_preset) - peer_flag_set (peer, PEER_FLAG_CAPABILITY_ENHE); - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - if (group->conf->afc[afi][safi]) - { - peer->afc[afi][safi] = 1; - - if (peer_af_find(peer, afi, safi) || peer_af_create(peer, afi, safi)) - { - peer_group2peer_config_copy_af (group, peer, afi, safi); - } - } - else if (peer->afc[afi][safi]) - peer_deactivate (peer, afi, safi); - } - - if (peer->group) - { - assert (group && peer->group == group); - } - else - { - struct listnode *pn; - pn = listnode_lookup (bgp->peer, peer); - list_delete_node (bgp->peer, pn); - peer->group = group; - listnode_add_sort (bgp->peer, peer); - - peer = peer_lock (peer); /* group->peer list reference */ - listnode_add (group->peer, peer); - } - - if (first_member) - { - /* Advertisement-interval reset */ - if (! CHECK_FLAG (group->conf->config, PEER_CONFIG_ROUTEADV)) - { - if (peer_sort (group->conf) == BGP_PEER_IBGP) - group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; - else - group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; - } - - /* ebgp-multihop reset */ - if (peer_sort (group->conf) == BGP_PEER_IBGP) - group->conf->ttl = MAXTTL; - - /* local-as reset */ - if (peer_sort (group->conf) != BGP_PEER_EBGP) - { - group->conf->change_local_as = 0; - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); - } - } - - SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); - - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_RMAP_BIND; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - { - bgp_session_reset(peer); - } - } - - /* Create a new peer. */ - else - { - if ((group->conf->as_type == AS_SPECIFIED) && (! group->conf->as)) - { - return BGP_ERR_PEER_GROUP_NO_REMOTE_AS; - } - - peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, group->conf->as_type, 0, 0, group); - - peer = peer_lock (peer); /* group->peer list reference */ - listnode_add (group->peer, peer); - - peer_group2peer_config_copy(group, peer); - - /* If the peer-group is active for this afi/safi then activate for this peer */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - if (group->conf->afc[afi][safi]) - { - peer->afc[afi][safi] = 1; - peer_af_create(peer, afi, safi); - peer_group2peer_config_copy_af (group, peer, afi, safi); - } - else if (peer->afc[afi][safi]) - peer_deactivate (peer, afi, safi); - - SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); - - /* Set up peer's events and timers. */ - if (peer_active (peer)) - bgp_timer_set (peer); - } - - return 0; -} - -int -peer_group_unbind (struct bgp *bgp, struct peer *peer, - struct peer_group *group) -{ - struct peer *other; - afi_t afi; - safi_t safi; - - if (group != peer->group) - return BGP_ERR_PEER_GROUP_MISMATCH; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - if (peer->afc[afi][safi]) - { - peer->afc[afi][safi] = 0; - peer_af_flag_reset (peer, afi, safi); - - if (peer_af_delete(peer, afi, safi) != 0) - { - zlog_err("couldn't delete af structure for peer %s", peer->host); - } - } - } - - assert (listnode_lookup (group->peer, peer)); - peer_unlock (peer); /* peer group list reference */ - listnode_delete (group->peer, peer); - peer->group = NULL; - other = peer->doppelganger; - - if (group->conf->as) - { - peer_delete (peer); - if (other && other->status != Deleted) - { - if (other->group) - { - peer_unlock(other); - listnode_delete(group->peer, other); - } - other->group = NULL; - peer_delete(other); - } - return 0; - } - - bgp_bfd_deregister_peer(peer); - peer_global_config_reset (peer); - - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_RMAP_UNBIND; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - - return 0; -} - -static int -bgp_startup_timer_expire (struct thread *thread) -{ - struct bgp *bgp; - - bgp = THREAD_ARG (thread); - bgp->t_startup = NULL; - - return 0; + return 0; } -/* BGP instance creation by `router bgp' commands. */ -static struct bgp * -bgp_create (as_t *as, const char *name, enum bgp_instance_type inst_type) -{ - struct bgp *bgp; - afi_t afi; - safi_t safi; - - if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL) - return NULL; - - if (BGP_DEBUG (zebra, ZEBRA)) - { - if (inst_type == BGP_INSTANCE_TYPE_DEFAULT) - zlog_debug("Creating Default VRF, AS %u", *as); - else - zlog_debug("Creating %s %s, AS %u", - (inst_type == BGP_INSTANCE_TYPE_VRF) ? "VRF" : "VIEW", - name, *as); - } - - bgp_lock (bgp); - bgp->inst_type = inst_type; - bgp->vrf_id = (inst_type == BGP_INSTANCE_TYPE_DEFAULT) ? - VRF_DEFAULT : VRF_UNKNOWN; - bgp->peer_self = peer_new (bgp); - if (bgp->peer_self->host) - XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->host); - bgp->peer_self->host = XSTRDUP(MTYPE_BGP_PEER_HOST, "Static announcement"); - bgp->peer = list_new (); - bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp; - bgp->peerhash = hash_create (peer_hash_key_make, peer_hash_cmp, NULL); - - bgp->group = list_new (); - bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - bgp->route[afi][safi] = bgp_table_init (afi, safi); - bgp->aggregate[afi][safi] = bgp_table_init (afi, safi); - bgp->rib[afi][safi] = bgp_table_init (afi, safi); - - /* Enable maximum-paths */ - bgp_maximum_paths_set (bgp, afi, safi, BGP_PEER_EBGP, multipath_num, 0); - bgp_maximum_paths_set (bgp, afi, safi, BGP_PEER_IBGP, multipath_num, 0); - } - - bgp->v_update_delay = BGP_UPDATE_DELAY_DEF; - bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF; - bgp->default_subgroup_pkt_queue_max = BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX; - bgp->default_holdtime = BGP_DEFAULT_HOLDTIME; - bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE; - bgp->restart_time = BGP_DEFAULT_RESTART_TIME; - bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME; - bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT; - bgp->dynamic_neighbors_count = 0; -#if DFLT_BGP_IMPORT_CHECK - bgp_flag_set (bgp, BGP_FLAG_IMPORT_CHECK); -#endif -#if DFLT_BGP_SHOW_HOSTNAME - bgp_flag_set (bgp, BGP_FLAG_SHOW_HOSTNAME); -#endif -#if DFLT_BGP_LOG_NEIGHBOR_CHANGES - bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES); -#endif -#if DFLT_BGP_DETERMINISTIC_MED - bgp_flag_set (bgp, BGP_FLAG_DETERMINISTIC_MED); -#endif - bgp->addpath_tx_id = BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE; - - bgp->as = *as; - -#if ENABLE_BGP_VNC - if (inst_type != BGP_INSTANCE_TYPE_VRF) - { - bgp->rfapi = bgp_rfapi_new(bgp); - assert(bgp->rfapi); - assert(bgp->rfapi_cfg); - } -#endif /* ENABLE_BGP_VNC */ - - if (name) - { - bgp->name = XSTRDUP(MTYPE_BGP, name); - } - else - { - /* TODO - The startup timer needs to be run for the whole of BGP */ - thread_add_timer(bm->master, bgp_startup_timer_expire, bgp, - bgp->restart_time, &bgp->t_startup); - } - - bgp->wpkt_quanta = BGP_WRITE_PACKET_MAX; - bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME; - - QOBJ_REG (bgp, bgp); - - update_bgp_group_init(bgp); - bgp_evpn_init(bgp); - return bgp; +static int peer_group_cmp(struct peer_group *g1, struct peer_group *g2) +{ + return strcmp(g1->name, g2->name); } -/* Return the "default VRF" instance of BGP. */ -struct bgp * -bgp_get_default (void) +/* Peer group cofiguration. */ +static struct peer_group *peer_group_new(void) { - struct bgp *bgp; - struct listnode *node, *nnode; - - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - return bgp; - return NULL; + return (struct peer_group *)XCALLOC(MTYPE_PEER_GROUP, + sizeof(struct peer_group)); } -/* Lookup BGP entry. */ -struct bgp * -bgp_lookup (as_t as, const char *name) +static void peer_group_free(struct peer_group *group) { - struct bgp *bgp; - struct listnode *node, *nnode; - - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - if (bgp->as == as - && ((bgp->name == NULL && name == NULL) - || (bgp->name && name && strcmp (bgp->name, name) == 0))) - return bgp; - return NULL; + XFREE(MTYPE_PEER_GROUP, group); } -/* Lookup BGP structure by view name. */ -struct bgp * -bgp_lookup_by_name (const char *name) +struct peer_group *peer_group_lookup(struct bgp *bgp, const char *name) { - struct bgp *bgp; - struct listnode *node, *nnode; + struct peer_group *group; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) { + if (strcmp(group->name, name) == 0) + return group; + } + return NULL; +} + +struct peer_group *peer_group_get(struct bgp *bgp, const char *name) +{ + struct peer_group *group; + afi_t afi; + + group = peer_group_lookup(bgp, name); + if (group) + return group; + + group = peer_group_new(); + group->bgp = bgp; + if (group->name) + XFREE(MTYPE_PEER_GROUP_HOST, group->name); + group->name = XSTRDUP(MTYPE_PEER_GROUP_HOST, name); + group->peer = list_new(); + for (afi = AFI_IP; afi < AFI_MAX; afi++) + group->listen_range[afi] = list_new(); + group->conf = peer_new(bgp); + if (!bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4)) + group->conf->afc[AFI_IP][SAFI_UNICAST] = 1; + if (group->conf->host) + XFREE(MTYPE_BGP_PEER_HOST, group->conf->host); + group->conf->host = XSTRDUP(MTYPE_BGP_PEER_HOST, name); + group->conf->group = group; + group->conf->as = 0; + group->conf->ttl = 1; + group->conf->gtsm_hops = 0; + group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; + UNSET_FLAG(group->conf->config, PEER_CONFIG_TIMER); + UNSET_FLAG(group->conf->config, PEER_CONFIG_CONNECT); + group->conf->keepalive = 0; + group->conf->holdtime = 0; + group->conf->connect = 0; + SET_FLAG(group->conf->sflags, PEER_STATUS_GROUP); + listnode_add_sort(bgp->group, group); - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - if ((bgp->name == NULL && name == NULL) - || (bgp->name && name && strcmp (bgp->name, name) == 0)) - return bgp; - return NULL; + return group; } -/* Lookup BGP instance based on VRF id. */ -/* Note: Only to be used for incoming messages from Zebra. */ -struct bgp * -bgp_lookup_by_vrf_id (vrf_id_t vrf_id) +static void peer_group2peer_config_copy(struct peer_group *group, + struct peer *peer) { - struct vrf *vrf; + struct peer *conf; + int v6only; - /* Lookup VRF (in tree) and follow link. */ - vrf = vrf_lookup_by_id (vrf_id); - if (!vrf) - return NULL; - return (vrf->info) ? (struct bgp *)vrf->info : NULL; -} + conf = group->conf; -/* Called from VTY commands. */ -int -bgp_get (struct bgp **bgp_val, as_t *as, const char *name, - enum bgp_instance_type inst_type) -{ - struct bgp *bgp; - - /* Multiple instance check. */ - if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE)) - { - if (name) - bgp = bgp_lookup_by_name (name); - else - bgp = bgp_get_default (); - - /* Already exists. */ - if (bgp) - { - if (bgp->as != *as) - { - *as = bgp->as; - return BGP_ERR_INSTANCE_MISMATCH; - } - if (bgp->inst_type != inst_type) - return BGP_ERR_INSTANCE_MISMATCH; - *bgp_val = bgp; - return 0; - } - } - else - { - /* BGP instance name can not be specified for single instance. */ - if (name) - return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET; - - /* Get default BGP structure if exists. */ - bgp = bgp_get_default (); - - if (bgp) - { - if (bgp->as != *as) - { - *as = bgp->as; - return BGP_ERR_AS_MISMATCH; - } - *bgp_val = bgp; - return 0; - } - } + /* remote-as */ + if (conf->as) + peer->as = conf->as; - bgp = bgp_create (as, name, inst_type); - bgp_router_id_set(bgp, &bgp->router_id_zebra); - bgp_address_init (bgp); - bgp_scan_init (bgp); - *bgp_val = bgp; + /* remote-as */ + if (conf->change_local_as) + peer->change_local_as = conf->change_local_as; - bgp->t_rmap_def_originate_eval = NULL; + /* TTL */ + peer->ttl = conf->ttl; - /* Create BGP server socket, if first instance. */ - if (list_isempty(bm->bgp) - && !bgp_option_check (BGP_OPT_NO_LISTEN)) - { - if (bgp_socket (bm->port, bm->address) < 0) - return BGP_ERR_INVALID_VALUE; - } + /* GTSM hops */ + peer->gtsm_hops = conf->gtsm_hops; - listnode_add (bm->bgp, bgp); + /* this flag is per-neighbor and so has to be preserved */ + v6only = CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); - /* If Default instance or VRF, link to the VRF structure, if present. */ - if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT || - bgp->inst_type == BGP_INSTANCE_TYPE_VRF) - { - struct vrf *vrf; + /* peer flags apply */ + peer->flags = conf->flags; - vrf = bgp_vrf_lookup_by_instance_type (bgp); - if (vrf) - bgp_vrf_link (bgp, vrf); - } + if (v6only) + SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); - /* Register with Zebra, if needed */ - if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) - bgp_zebra_instance_register (bgp); + /* peer config apply */ + peer->config = conf->config; + /* peer timers apply */ + peer->holdtime = conf->holdtime; + peer->keepalive = conf->keepalive; + peer->connect = conf->connect; + if (CHECK_FLAG(conf->config, PEER_CONFIG_CONNECT)) + peer->v_connect = conf->connect; + else + peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; - return 0; -} + /* advertisement-interval reset */ + if (CHECK_FLAG(conf->config, PEER_CONFIG_ROUTEADV)) + peer->v_routeadv = conf->routeadv; + else if (peer_sort(peer) == BGP_PEER_IBGP) + peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; + else + peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; -/* - * Make BGP instance "up". Applies only to VRFs (non-default) and - * implies the VRF has been learnt from Zebra. - */ -void -bgp_instance_up (struct bgp *bgp) -{ - struct peer *peer; - struct listnode *node, *next; + /* password apply */ + if (conf->password && !peer->password) + peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, conf->password); - /* Register with zebra. */ - bgp_zebra_instance_register (bgp); + if (!BGP_PEER_SU_UNSPEC(peer)) + bgp_md5_set(peer); - /* Kick off any peers that may have been configured. */ - for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer)) - { - if (!BGP_PEER_START_SUPPRESSED (peer)) - BGP_EVENT_ADD (peer, BGP_Start); - } + /* update-source apply */ + if (conf->update_source) { + if (peer->update_source) + sockunion_free(peer->update_source); + if (peer->update_if) { + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); + peer->update_if = NULL; + } + peer->update_source = sockunion_dup(conf->update_source); + } else if (conf->update_if) { + if (peer->update_if) + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); + if (peer->update_source) { + sockunion_free(peer->update_source); + peer->update_source = NULL; + } + peer->update_if = + XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, conf->update_if); + } - /* Process any networks that have been configured. */ - bgp_static_add (bgp); + bgp_bfd_peer_group2peer_copy(conf, peer); } -/* - * Make BGP instance "down". Applies only to VRFs (non-default) and - * implies the VRF has been deleted by Zebra. - */ -void -bgp_instance_down (struct bgp *bgp) +static void peer_group2peer_config_copy_af(struct peer_group *group, + struct peer *peer, afi_t afi, + safi_t safi) { - struct peer *peer; - struct listnode *node; - struct listnode *next; + int in = FILTER_IN; + int out = FILTER_OUT; + struct peer *conf; + struct bgp_filter *pfilter; + struct bgp_filter *gfilter; - /* Stop timers. */ - if (bgp->t_rmap_def_originate_eval) - { - BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval); - bgp_unlock(bgp); /* TODO - This timer is started with a lock - why? */ - } + conf = group->conf; + pfilter = &peer->filter[afi][safi]; + gfilter = &conf->filter[afi][safi]; - /* Bring down peers, so corresponding routes are purged. */ - for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); - else - bgp_session_reset(peer); - } + /* peer af_flags apply */ + peer->af_flags[afi][safi] = conf->af_flags[afi][safi]; - /* Purge network and redistributed routes. */ - bgp_purge_static_redist_routes (bgp); -} + /* maximum-prefix */ + peer->pmax[afi][safi] = conf->pmax[afi][safi]; + peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi]; + peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi]; -/* Delete BGP instance. */ -int -bgp_delete (struct bgp *bgp) -{ - struct peer *peer; - struct peer_group *group; - struct listnode *node, *next; - struct vrf *vrf; - afi_t afi; - int i; - - THREAD_OFF (bgp->t_startup); - - if (BGP_DEBUG (zebra, ZEBRA)) - { - if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - zlog_debug("Deleting Default VRF"); - else - zlog_debug("Deleting %s %s", - (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) ? "VRF" : "VIEW", - bgp->name); - } - - /* Stop timers. */ - if (bgp->t_rmap_def_originate_eval) - { - BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval); - bgp_unlock(bgp); /* TODO - This timer is started with a lock - why? */ - } - - /* Inform peers we're going down. */ - for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); - } - - /* Delete static routes (networks). */ - bgp_static_delete (bgp); - - /* Unset redistribution. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (i != ZEBRA_ROUTE_BGP) - bgp_redistribute_unset (bgp, afi, i, 0); - - /* Free peers and peer-groups. */ - for (ALL_LIST_ELEMENTS (bgp->group, node, next, group)) - peer_group_delete (group); - - for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer)) - peer_delete (peer); - - if (bgp->peer_self) { - peer_delete(bgp->peer_self); - bgp->peer_self = NULL; - } - - update_bgp_group_free (bgp); - - /* TODO - Other memory may need to be freed - e.g., NHT */ + /* allowas-in */ + peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi]; -#if ENABLE_BGP_VNC - rfapi_delete(bgp); -#endif - bgp_cleanup_routes(bgp); + /* weight */ + peer->weight[afi][safi] = conf->weight[afi][safi]; - /* Remove visibility via the master list - there may however still be - * routes to be processed still referencing the struct bgp. - */ - listnode_delete (bm->bgp, bgp); + /* default-originate route-map */ + if (conf->default_rmap[afi][safi].name) { + if (peer->default_rmap[afi][safi].name) + XFREE(MTYPE_BGP_FILTER_NAME, + peer->default_rmap[afi][safi].name); + peer->default_rmap[afi][safi].name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, + conf->default_rmap[afi][safi].name); + peer->default_rmap[afi][safi].map = + conf->default_rmap[afi][safi].map; + } - /* Deregister from Zebra, if needed */ - if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) - bgp_zebra_instance_deregister (bgp); + /* inbound filter apply */ + if (gfilter->dlist[in].name && !pfilter->dlist[in].name) { + if (pfilter->dlist[in].name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[in].name); + pfilter->dlist[in].name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->dlist[in].name); + pfilter->dlist[in].alist = gfilter->dlist[in].alist; + } - /* Free interfaces in this instance. */ - bgp_if_finish (bgp); + if (gfilter->plist[in].name && !pfilter->plist[in].name) { + if (pfilter->plist[in].name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[in].name); + pfilter->plist[in].name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->plist[in].name); + pfilter->plist[in].plist = gfilter->plist[in].plist; + } - vrf = bgp_vrf_lookup_by_instance_type (bgp); - if (vrf) - bgp_vrf_unlink (bgp, vrf); + if (gfilter->aslist[in].name && !pfilter->aslist[in].name) { + if (pfilter->aslist[in].name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[in].name); + pfilter->aslist[in].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, + gfilter->aslist[in].name); + pfilter->aslist[in].aslist = gfilter->aslist[in].aslist; + } - thread_master_free_unused(bm->master); - bgp_unlock(bgp); /* initial reference */ + if (gfilter->map[RMAP_IN].name && !pfilter->map[RMAP_IN].name) { + if (pfilter->map[RMAP_IN].name) + XFREE(MTYPE_BGP_FILTER_NAME, + pfilter->map[RMAP_IN].name); + pfilter->map[RMAP_IN].name = XSTRDUP( + MTYPE_BGP_FILTER_NAME, gfilter->map[RMAP_IN].name); + pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map; + } - return 0; -} + /* outbound filter apply */ + if (gfilter->dlist[out].name) { + if (pfilter->dlist[out].name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[out].name); + pfilter->dlist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, + gfilter->dlist[out].name); + pfilter->dlist[out].alist = gfilter->dlist[out].alist; + } else { + if (pfilter->dlist[out].name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[out].name); + pfilter->dlist[out].name = NULL; + pfilter->dlist[out].alist = NULL; + } -static void bgp_free (struct bgp *); + if (gfilter->plist[out].name) { + if (pfilter->plist[out].name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[out].name); + pfilter->plist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, + gfilter->plist[out].name); + pfilter->plist[out].plist = gfilter->plist[out].plist; + } else { + if (pfilter->plist[out].name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[out].name); + pfilter->plist[out].name = NULL; + pfilter->plist[out].plist = NULL; + } -void -bgp_lock (struct bgp *bgp) -{ - ++bgp->lock; -} + if (gfilter->aslist[out].name) { + if (pfilter->aslist[out].name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[out].name); + pfilter->aslist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, + gfilter->aslist[out].name); + pfilter->aslist[out].aslist = gfilter->aslist[out].aslist; + } else { + if (pfilter->aslist[out].name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[out].name); + pfilter->aslist[out].name = NULL; + pfilter->aslist[out].aslist = NULL; + } -void -bgp_unlock(struct bgp *bgp) -{ - assert(bgp->lock > 0); - if (--bgp->lock == 0) - bgp_free (bgp); -} - -static void -bgp_free (struct bgp *bgp) -{ - afi_t afi; - safi_t safi; - struct bgp_table *table; - struct bgp_node *rn; - - QOBJ_UNREG (bgp); - - list_delete (bgp->group); - list_delete (bgp->peer); - - if (bgp->peerhash) - { - hash_free(bgp->peerhash); - bgp->peerhash = NULL; - } + if (gfilter->map[RMAP_OUT].name) { + if (pfilter->map[RMAP_OUT].name) + XFREE(MTYPE_BGP_FILTER_NAME, + pfilter->map[RMAP_OUT].name); + pfilter->map[RMAP_OUT].name = XSTRDUP( + MTYPE_BGP_FILTER_NAME, gfilter->map[RMAP_OUT].name); + pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map; + } else { + if (pfilter->map[RMAP_OUT].name) + XFREE(MTYPE_BGP_FILTER_NAME, + pfilter->map[RMAP_OUT].name); + pfilter->map[RMAP_OUT].name = NULL; + pfilter->map[RMAP_OUT].map = NULL; + } - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - /* Special handling for 2-level routing tables. */ - if (safi == SAFI_MPLS_VPN || - safi == SAFI_ENCAP || - safi == SAFI_EVPN) - { - for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; - rn = bgp_route_next (rn)) - { - table = (struct bgp_table *) rn->info; - bgp_table_finish(&table); - } - } - if (bgp->route[afi][safi]) - bgp_table_finish (&bgp->route[afi][safi]); - if (bgp->aggregate[afi][safi]) - bgp_table_finish (&bgp->aggregate[afi][safi]) ; - if (bgp->rib[afi][safi]) - bgp_table_finish (&bgp->rib[afi][safi]); - } - - bgp_scan_finish (bgp); - bgp_address_destroy (bgp); - - bgp_evpn_cleanup (bgp); - - if (bgp->name) - XFREE(MTYPE_BGP, bgp->name); - - XFREE (MTYPE_BGP, bgp); -} - -struct peer * -peer_lookup_by_conf_if (struct bgp *bgp, const char *conf_if) -{ - struct peer *peer; - struct listnode *node, *nnode; - - if (!conf_if) - return NULL; - - if (bgp != NULL) - { - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - if (peer->conf_if && !strcmp(peer->conf_if, conf_if) - && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) - return peer; - } - else if (bm->bgp != NULL) - { - struct listnode *bgpnode, *nbgpnode; - - for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp)) - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - if (peer->conf_if && !strcmp(peer->conf_if, conf_if) - && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) - return peer; - } - return NULL; -} - -struct peer * -peer_lookup_by_hostname (struct bgp *bgp, const char *hostname) -{ - struct peer *peer; - struct listnode *node, *nnode; - - if (!hostname) - return NULL; - - if (bgp != NULL) - { - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - if (peer->hostname && !strcmp(peer->hostname, hostname) - && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) - return peer; - } - else if (bm->bgp != NULL) - { - struct listnode *bgpnode, *nbgpnode; - - for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp)) - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - if (peer->hostname && !strcmp(peer->hostname, hostname) - && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER)) - return peer; - } - return NULL; -} - -struct peer * -peer_lookup (struct bgp *bgp, union sockunion *su) -{ - struct peer *peer = NULL; - struct peer tmp_peer; - - memset(&tmp_peer, 0, sizeof(struct peer)); - - /* - * We do not want to find the doppelganger peer so search for the peer in - * the hash that has PEER_FLAG_CONFIG_NODE - */ - SET_FLAG (tmp_peer.flags, PEER_FLAG_CONFIG_NODE); - - tmp_peer.su = *su; - - if (bgp != NULL) - { - peer = hash_lookup(bgp->peerhash, &tmp_peer); - } - else if (bm->bgp != NULL) - { - struct listnode *bgpnode, *nbgpnode; - - for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp)) - { - /* Skip VRFs, this function will not be invoked without an instance - * when examining VRFs. - */ - if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) - continue; - - peer = hash_lookup(bgp->peerhash, &tmp_peer); - - if (peer) - break; - } - } - - return peer; -} - -struct peer * -peer_create_bind_dynamic_neighbor (struct bgp *bgp, union sockunion *su, - struct peer_group *group) -{ - struct peer *peer; - afi_t afi; - safi_t safi; - - /* Create peer first; we've already checked group config is valid. */ - peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, group->conf->as_type, 0, 0, group); - if (!peer) - return NULL; - - /* Link to group */ - peer = peer_lock (peer); - listnode_add (group->peer, peer); - - peer_group2peer_config_copy(group, peer); - - /* - * Bind peer for all AFs configured for the group. We don't call - * peer_group_bind as that is sub-optimal and does some stuff we don't want. - */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - if (!group->conf->afc[afi][safi]) - continue; - peer->afc[afi][safi] = 1; - - if (!peer_af_find(peer, afi, safi)) - peer_af_create(peer, afi, safi); - - peer_group2peer_config_copy_af (group, peer, afi, safi); - } - - /* Mark as dynamic, but also as a "config node" for other things to work. */ - SET_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR); - SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); - - return peer; + if (gfilter->usmap.name) { + if (pfilter->usmap.name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->usmap.name); + pfilter->usmap.name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->usmap.name); + pfilter->usmap.map = gfilter->usmap.map; + } else { + if (pfilter->usmap.name) + XFREE(MTYPE_BGP_FILTER_NAME, pfilter->usmap.name); + pfilter->usmap.name = NULL; + pfilter->usmap.map = NULL; + } } -struct prefix * -peer_group_lookup_dynamic_neighbor_range (struct peer_group * group, - struct prefix * prefix) +/* Peer group's remote AS configuration. */ +int peer_group_remote_as(struct bgp *bgp, const char *group_name, as_t *as, + int as_type) { - struct listnode *node, *nnode; - struct prefix *range; - afi_t afi; + struct peer_group *group; + struct peer *peer; + struct listnode *node, *nnode; - afi = family2afi(prefix->family); + group = peer_group_lookup(bgp, group_name); + if (!group) + return -1; - if (group->listen_range[afi]) - for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, range)) - if (prefix_match(range, prefix)) - return range; + if ((as_type == group->conf->as_type) && (group->conf->as == *as)) + return 0; - return NULL; -} -struct peer_group * -peer_group_lookup_dynamic_neighbor (struct bgp *bgp, struct prefix *prefix, - struct prefix **listen_range) -{ - struct prefix *range = NULL; - struct peer_group *group = NULL; - struct listnode *node, *nnode; + /* When we setup peer-group AS number all peer group member's AS + number must be updated to same number. */ + peer_as_change(group->conf, *as, as_type); - *listen_range = NULL; - if (bgp != NULL) - { - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - if ((range = peer_group_lookup_dynamic_neighbor_range(group, prefix))) - break; - } - else if (bm->bgp != NULL) - { - struct listnode *bgpnode, *nbgpnode; - - for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp)) - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - if ((range = peer_group_lookup_dynamic_neighbor_range(group, prefix))) - goto found_range; - } + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (((peer->as_type == AS_SPECIFIED) && peer->as != *as) + || (peer->as_type != as_type)) + peer_as_change(peer, *as, as_type); + } - found_range: - *listen_range = range; - return (group && range) ? group : NULL; + return 0; } -struct peer * -peer_lookup_dynamic_neighbor (struct bgp *bgp, union sockunion *su) +int peer_group_delete(struct peer_group *group) { - struct peer_group *group; - struct bgp *gbgp; - struct peer *peer; - struct prefix prefix; - struct prefix *listen_range; - int dncount; - char buf[PREFIX2STR_BUFFER]; - char buf1[PREFIX2STR_BUFFER]; + struct bgp *bgp; + struct peer *peer; + struct prefix *prefix; + struct peer *other; + struct listnode *node, *nnode; + afi_t afi; - sockunion2hostprefix(su, &prefix); + bgp = group->bgp; - /* See if incoming connection matches a configured listen range. */ - group = peer_group_lookup_dynamic_neighbor (bgp, &prefix, &listen_range); + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + other = peer->doppelganger; + peer_delete(peer); + if (other && other->status != Deleted) { + other->group = NULL; + peer_delete(other); + } + } + list_delete(group->peer); - if (! group) - return NULL; + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode, + prefix)) { + prefix_free(prefix); + } + list_delete(group->listen_range[afi]); + } + XFREE(MTYPE_PEER_GROUP_HOST, group->name); + group->name = NULL; - gbgp = group->bgp; + bfd_info_free(&(group->conf->bfd_info)); - if (! gbgp) - return NULL; + group->conf->group = NULL; + peer_delete(group->conf); - prefix2str(&prefix, buf, sizeof(buf)); - prefix2str(listen_range, buf1, sizeof(buf1)); + /* Delete from all peer_group list. */ + listnode_delete(bgp->group, group); - if (bgp_debug_neighbor_events(NULL)) - zlog_debug ("Dynamic Neighbor %s matches group %s listen range %s", - buf, group->name, buf1); + peer_group_free(group); - /* Are we within the listen limit? */ - dncount = gbgp->dynamic_neighbors_count; + return 0; +} - if (dncount >= gbgp->dynamic_neighbors_limit) - { - if (bgp_debug_neighbor_events(NULL)) - zlog_debug ("Dynamic Neighbor %s rejected - at limit %d", - inet_sutop (su, buf), gbgp->dynamic_neighbors_limit); - return NULL; - } +int peer_group_remote_as_delete(struct peer_group *group) +{ + struct peer *peer, *other; + struct listnode *node, *nnode; - /* Ensure group is not disabled. */ - if (CHECK_FLAG (group->conf->flags, PEER_FLAG_SHUTDOWN)) - { - if (bgp_debug_neighbor_events(NULL)) - zlog_debug ("Dynamic Neighbor %s rejected - group %s disabled", - buf, group->name); - return NULL; - } + if ((group->conf->as_type == AS_UNSPECIFIED) + || ((!group->conf->as) && (group->conf->as_type == AS_SPECIFIED))) + return 0; - /* Check that at least one AF is activated for the group. */ - if (!peer_group_af_configured (group)) - { - if (bgp_debug_neighbor_events(NULL)) - zlog_debug ("Dynamic Neighbor %s rejected - no AF activated for group %s", - buf, group->name); - return NULL; - } + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + other = peer->doppelganger; - /* Create dynamic peer and bind to associated group. */ - peer = peer_create_bind_dynamic_neighbor (gbgp, su, group); - assert (peer); + peer_delete(peer); - gbgp->dynamic_neighbors_count = ++dncount; + if (other && other->status != Deleted) { + other->group = NULL; + peer_delete(other); + } + } + list_delete_all_node(group->peer); - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Dynamic Neighbor added, group %s count %d", - peer->host, group->name, dncount); + group->conf->as = 0; + group->conf->as_type = AS_UNSPECIFIED; - return peer; + return 0; } - -void peer_drop_dynamic_neighbor (struct peer *peer) + +int peer_group_listen_range_add(struct peer_group *group, struct prefix *range) { - int dncount = -1; - if (peer->group && peer->group->bgp) - { - dncount = peer->group->bgp->dynamic_neighbors_count; - if (dncount) - peer->group->bgp->dynamic_neighbors_count = --dncount; - } - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s dropped from group %s, count %d", - peer->host, peer->group->name, dncount); -} + struct prefix *prefix; + struct listnode *node, *nnode; + afi_t afi; + afi = family2afi(range->family); -/* If peer is configured at least one address family return 1. */ -int -peer_active (struct peer *peer) -{ - if (BGP_PEER_SU_UNSPEC(peer)) - return 0; - if (peer->afc[AFI_IP][SAFI_UNICAST] - || peer->afc[AFI_IP][SAFI_MULTICAST] - || peer->afc[AFI_IP][SAFI_LABELED_UNICAST] - || peer->afc[AFI_IP][SAFI_MPLS_VPN] - || peer->afc[AFI_IP][SAFI_ENCAP] - || peer->afc[AFI_IP6][SAFI_UNICAST] - || peer->afc[AFI_IP6][SAFI_MULTICAST] - || peer->afc[AFI_IP6][SAFI_LABELED_UNICAST] - || peer->afc[AFI_IP6][SAFI_MPLS_VPN] - || peer->afc[AFI_IP6][SAFI_ENCAP] - || peer->afc[AFI_L2VPN][SAFI_EVPN]) - return 1; - return 0; -} + /* Group needs remote AS configured. */ + if (group->conf->as_type == AS_UNSPECIFIED) + return BGP_ERR_PEER_GROUP_NO_REMOTE_AS; -/* If peer is negotiated at least one address family return 1. */ -int -peer_active_nego (struct peer *peer) -{ - if (peer->afc_nego[AFI_IP][SAFI_UNICAST] - || peer->afc_nego[AFI_IP][SAFI_MULTICAST] - || peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST] - || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] - || peer->afc_nego[AFI_IP][SAFI_ENCAP] - || peer->afc_nego[AFI_IP6][SAFI_UNICAST] - || peer->afc_nego[AFI_IP6][SAFI_MULTICAST] - || peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST] - || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN] - || peer->afc_nego[AFI_IP6][SAFI_ENCAP] - || peer->afc_nego[AFI_L2VPN][SAFI_EVPN]) - return 1; - return 0; + /* Ensure no duplicates. Currently we don't care about overlaps. */ + for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode, prefix)) { + if (prefix_same(range, prefix)) + return 0; + } + + prefix = prefix_new(); + prefix_copy(prefix, range); + listnode_add(group->listen_range[afi], prefix); + return 0; } -/* peer_flag_change_type. */ -enum peer_change_type +int peer_group_listen_range_del(struct peer_group *group, struct prefix *range) { - peer_change_none, - peer_change_reset, - peer_change_reset_in, - peer_change_reset_out, -}; + struct prefix *prefix, prefix2; + struct listnode *node, *nnode; + struct peer *peer; + afi_t afi; + char buf[PREFIX2STR_BUFFER]; -static void -peer_change_action (struct peer *peer, afi_t afi, safi_t safi, - enum peer_change_type type) -{ - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return; - - if (peer->status != Established) - return; - - if (type == peer_change_reset) - { - /* If we're resetting session, we've to delete both peer struct */ - if ((peer->doppelganger) && (peer->doppelganger->status != Deleted) - && (!CHECK_FLAG(peer->doppelganger->flags, - PEER_FLAG_CONFIG_NODE))) - peer_delete(peer->doppelganger); - - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else if (type == peer_change_reset_in) - { - if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV) - || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV)) - bgp_route_refresh_send (peer, afi, safi, 0, 0, 0); - else - { - if ((peer->doppelganger) && (peer->doppelganger->status != Deleted) - && (!CHECK_FLAG(peer->doppelganger->flags, - PEER_FLAG_CONFIG_NODE))) - peer_delete(peer->doppelganger); + afi = family2afi(range->family); - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); + /* Identify the listen range. */ + for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode, prefix)) { + if (prefix_same(range, prefix)) + break; } - } - else if (type == peer_change_reset_out) - { - update_group_adjust_peer(peer_af_find(peer, afi, safi)); - bgp_announce_route (peer, afi, safi); - } -} -struct peer_flag_action -{ - /* Peer's flag. */ - u_int32_t flag; + if (!prefix) + return BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND; + + prefix2str(prefix, buf, sizeof(buf)); + + /* Dispose off any dynamic neighbors that exist due to this listen range + */ + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (!peer_dynamic_neighbor(peer)) + continue; + + sockunion2hostprefix(&peer->su, &prefix2); + if (prefix_match(prefix, &prefix2)) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "Deleting dynamic neighbor %s group %s upon " + "delete of listen range %s", + peer->host, group->name, buf); + peer_delete(peer); + } + } - /* This flag can be set for peer-group member. */ - u_char not_for_member; + /* Get rid of the listen range */ + listnode_delete(group->listen_range[afi], prefix); - /* Action when the flag is changed. */ - enum peer_change_type type; + return 0; +} - /* Peer down cause */ - u_char peer_down; -}; +/* Bind specified peer to peer group. */ +int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer, + struct peer_group *group, as_t *as) +{ + int first_member = 0; + afi_t afi; + safi_t safi; + int cap_enhe_preset = 0; + + /* Lookup the peer. */ + if (!peer) + peer = peer_lookup(bgp, su); + + /* The peer exist, bind it to the peer-group */ + if (peer) { + /* When the peer already belongs to peer group, check the + * consistency. */ + if (peer_group_active(peer) + && strcmp(peer->group->name, group->name) != 0) + return BGP_ERR_PEER_GROUP_CANT_CHANGE; + + /* The peer has not specified a remote-as, inherit it from the + * peer-group */ + if (peer->as_type == AS_UNSPECIFIED) { + peer->as_type = group->conf->as_type; + peer->as = group->conf->as; + } -static const struct peer_flag_action peer_flag_action_list[] = - { - { PEER_FLAG_PASSIVE, 0, peer_change_reset }, - { PEER_FLAG_SHUTDOWN, 0, peer_change_reset }, - { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none }, - { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none }, - { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none }, - { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset }, - { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset }, - { PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset }, - { 0, 0, 0 } - }; - -static const struct peer_flag_action peer_af_flag_action_list[] = - { - { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out }, - { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out }, - { PEER_FLAG_SEND_LARGE_COMMUNITY, 1, peer_change_reset_out }, - { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out }, - { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset }, - { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset }, - { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in }, - { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out }, - { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out }, - { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out }, - // PEER_FLAG_DEFAULT_ORIGINATE - { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out }, - { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in }, - { PEER_FLAG_ALLOWAS_IN_ORIGIN, 0, peer_change_reset_in }, - { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset }, - { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset }, - // PEER_FLAG_MAX_PREFIX - // PEER_FLAG_MAX_PREFIX_WARNING - { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out }, - { PEER_FLAG_FORCE_NEXTHOP_SELF, 1, peer_change_reset_out }, - { PEER_FLAG_REMOVE_PRIVATE_AS_ALL, 1, peer_change_reset_out }, - { PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE,1, peer_change_reset_out }, - { PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out }, - { PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE,1, peer_change_reset_out }, - { PEER_FLAG_ADDPATH_TX_ALL_PATHS, 1, peer_change_reset }, - { PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS, 1, peer_change_reset }, - { PEER_FLAG_WEIGHT, 0, peer_change_reset_in }, - { 0, 0, 0 } - }; + if (!group->conf->as) { + if (peer_sort(group->conf) != BGP_PEER_INTERNAL + && peer_sort(group->conf) != peer_sort(peer)) { + if (as) + *as = peer->as; + return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT; + } -/* Proper action set. */ -static int -peer_flag_action_set (const struct peer_flag_action *action_list, int size, - struct peer_flag_action *action, u_int32_t flag) -{ - int i; - int found = 0; - int reset_in = 0; - int reset_out = 0; - const struct peer_flag_action *match = NULL; + if (peer_sort(group->conf) == BGP_PEER_INTERNAL) + first_member = 1; + } - /* Check peer's frag action. */ - for (i = 0; i < size; i++) - { - match = &action_list[i]; + if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)) + cap_enhe_preset = 1; + + peer_group2peer_config_copy(group, peer); + + /* + * Capability extended-nexthop is enabled for an interface + * neighbor by + * default. So, fix that up here. + */ + if (peer->conf_if && cap_enhe_preset) + peer_flag_set(peer, PEER_FLAG_CAPABILITY_ENHE); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + if (group->conf->afc[afi][safi]) { + peer->afc[afi][safi] = 1; + + if (peer_af_find(peer, afi, safi) + || peer_af_create(peer, afi, + safi)) { + peer_group2peer_config_copy_af( + group, peer, afi, safi); + } + } else if (peer->afc[afi][safi]) + peer_deactivate(peer, afi, safi); + } + + if (peer->group) { + assert(group && peer->group == group); + } else { + struct listnode *pn; + pn = listnode_lookup(bgp->peer, peer); + list_delete_node(bgp->peer, pn); + peer->group = group; + listnode_add_sort(bgp->peer, peer); + + peer = peer_lock(peer); /* group->peer list reference */ + listnode_add(group->peer, peer); + } - if (match->flag == 0) - break; + if (first_member) { + /* Advertisement-interval reset */ + if (!CHECK_FLAG(group->conf->config, + PEER_CONFIG_ROUTEADV)) { + if (peer_sort(group->conf) == BGP_PEER_IBGP) + group->conf->v_routeadv = + BGP_DEFAULT_IBGP_ROUTEADV; + else + group->conf->v_routeadv = + BGP_DEFAULT_EBGP_ROUTEADV; + } + + /* ebgp-multihop reset */ + if (peer_sort(group->conf) == BGP_PEER_IBGP) + group->conf->ttl = MAXTTL; + + /* local-as reset */ + if (peer_sort(group->conf) != BGP_PEER_EBGP) { + group->conf->change_local_as = 0; + UNSET_FLAG(peer->flags, + PEER_FLAG_LOCAL_AS_NO_PREPEND); + UNSET_FLAG(peer->flags, + PEER_FLAG_LOCAL_AS_REPLACE_AS); + } + } - if (match->flag & flag) - { - found = 1; - - if (match->type == peer_change_reset_in) - reset_in = 1; - if (match->type == peer_change_reset_out) - reset_out = 1; - if (match->type == peer_change_reset) - { - reset_in = 1; - reset_out = 1; - } - if (match->not_for_member) - action->not_for_member = 1; - } - } - - /* Set peer clear type. */ - if (reset_in && reset_out) - action->type = peer_change_reset; - else if (reset_in) - action->type = peer_change_reset_in; - else if (reset_out) - action->type = peer_change_reset_out; - else - action->type = peer_change_none; - - return found; -} - -static void -peer_flag_modify_action (struct peer *peer, u_int32_t flag) -{ - if (flag == PEER_FLAG_SHUTDOWN) - { - if (CHECK_FLAG (peer->flags, flag)) - { - if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT)) - peer_nsf_stop (peer); - - UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW); - if (peer->t_pmax_restart) - { - BGP_TIMER_OFF (peer->t_pmax_restart); - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Maximum-prefix restart timer canceled", - peer->host); - } - - if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT)) - peer_nsf_stop (peer); - - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - char *msg = peer->tx_shutdown_message; - size_t msglen; - - if (!msg && peer_group_active (peer)) - msg = peer->group->conf->tx_shutdown_message; - msglen = msg ? strlen(msg) : 0; - if (msglen > 128) - msglen = 128; - - if (msglen) - { - u_char msgbuf[129]; - - msgbuf[0] = msglen; - memcpy(msgbuf + 1, msg, msglen); - - bgp_notify_send_with_data (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN, - msgbuf, msglen + 1); - } - else - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); - } - else - bgp_session_reset(peer); - } - else - { - peer->v_start = BGP_INIT_START_TIMER; - BGP_EVENT_ADD (peer, BGP_Stop); - } - } - else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - if (flag == PEER_FLAG_DYNAMIC_CAPABILITY) - peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE; - else if (flag == PEER_FLAG_PASSIVE) - peer->last_reset = PEER_DOWN_PASSIVE_CHANGE; - else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK) - peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE; - - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); -} + SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); -/* Change specified peer flag. */ -static int -peer_flag_modify (struct peer *peer, u_int32_t flag, int set) -{ - int found; - int size; - struct peer_group *group; - struct peer *tmp_peer; - struct listnode *node, *nnode; - struct peer_flag_action action; - - memset (&action, 0, sizeof (struct peer_flag_action)); - size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action); - - found = peer_flag_action_set (peer_flag_action_list, size, &action, flag); - - /* No flag action is found. */ - if (! found) - return BGP_ERR_INVALID_FLAG; - - /* When unset the peer-group member's flag we have to check - peer-group configuration. */ - if (! set && peer_group_active (peer)) - if (CHECK_FLAG (peer->group->conf->flags, flag)) - { - if (flag == PEER_FLAG_SHUTDOWN) - return BGP_ERR_PEER_GROUP_SHUTDOWN; - } - - /* Flag conflict check. */ - if (set - && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH) - && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY)) - return BGP_ERR_PEER_FLAG_CONFLICT; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (set && CHECK_FLAG (peer->flags, flag) == flag) - return 0; - if (! set && ! CHECK_FLAG (peer->flags, flag)) - return 0; - } + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_RMAP_BIND; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else { + bgp_session_reset(peer); + } + } - if (set) - SET_FLAG (peer->flags, flag); - else - UNSET_FLAG (peer->flags, flag); - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (action.type == peer_change_reset) - peer_flag_modify_action (peer, flag); + /* Create a new peer. */ + else { + if ((group->conf->as_type == AS_SPECIFIED) + && (!group->conf->as)) { + return BGP_ERR_PEER_GROUP_NO_REMOTE_AS; + } - return 0; - } + peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as, + group->conf->as_type, 0, 0, group); - /* peer-group member updates. */ - group = peer->group; + peer = peer_lock(peer); /* group->peer list reference */ + listnode_add(group->peer, peer); - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer)) - { + peer_group2peer_config_copy(group, peer); - if (set && CHECK_FLAG (tmp_peer->flags, flag) == flag) - continue; + /* If the peer-group is active for this afi/safi then activate + * for this peer */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + if (group->conf->afc[afi][safi]) { + peer->afc[afi][safi] = 1; + peer_af_create(peer, afi, safi); + peer_group2peer_config_copy_af( + group, peer, afi, safi); + } else if (peer->afc[afi][safi]) + peer_deactivate(peer, afi, safi); - if (! set && ! CHECK_FLAG (tmp_peer->flags, flag)) - continue; + SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); - if (set) - SET_FLAG (tmp_peer->flags, flag); - else - UNSET_FLAG (tmp_peer->flags, flag); + /* Set up peer's events and timers. */ + if (peer_active(peer)) + bgp_timer_set(peer); + } - if (action.type == peer_change_reset) - peer_flag_modify_action (tmp_peer, flag); - } - return 0; + return 0; } -int -peer_flag_set (struct peer *peer, u_int32_t flag) +int peer_group_unbind(struct bgp *bgp, struct peer *peer, + struct peer_group *group) { - return peer_flag_modify (peer, flag, 1); -} + struct peer *other; + afi_t afi; + safi_t safi; -int -peer_flag_unset (struct peer *peer, u_int32_t flag) -{ - return peer_flag_modify (peer, flag, 0); -} + if (group != peer->group) + return BGP_ERR_PEER_GROUP_MISMATCH; -static int -peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag, - int set) -{ - int found; - int size; - struct listnode *node, *nnode; - struct peer_group *group; - struct peer_flag_action action; - struct peer *tmp_peer; - struct bgp *bgp; - int addpath_tx_used; + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + if (peer->afc[afi][safi]) { + peer->afc[afi][safi] = 0; + peer_af_flag_reset(peer, afi, safi); - memset (&action, 0, sizeof (struct peer_flag_action)); - size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action); - - found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag); - - /* No flag action is found. */ - if (! found) - return BGP_ERR_INVALID_FLAG; + if (peer_af_delete(peer, afi, safi) != 0) { + zlog_err( + "couldn't delete af structure for peer %s", + peer->host); + } + } + } - /* Special check for reflector client. */ - if (flag & PEER_FLAG_REFLECTOR_CLIENT - && peer_sort (peer) != BGP_PEER_IBGP) - return BGP_ERR_NOT_INTERNAL_PEER; + assert(listnode_lookup(group->peer, peer)); + peer_unlock(peer); /* peer group list reference */ + listnode_delete(group->peer, peer); + peer->group = NULL; + other = peer->doppelganger; + + if (group->conf->as) { + peer_delete(peer); + if (other && other->status != Deleted) { + if (other->group) { + peer_unlock(other); + listnode_delete(group->peer, other); + } + other->group = NULL; + peer_delete(other); + } + return 0; + } - /* Special check for remove-private-AS. */ - if (flag & PEER_FLAG_REMOVE_PRIVATE_AS - && peer_sort (peer) == BGP_PEER_IBGP) - return BGP_ERR_REMOVE_PRIVATE_AS; + bgp_bfd_deregister_peer(peer); + peer_global_config_reset(peer); - /* as-override is not allowed for IBGP peers */ - if (flag & PEER_FLAG_AS_OVERRIDE - && peer_sort (peer) == BGP_PEER_IBGP) - return BGP_ERR_AS_OVERRIDE; + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_RMAP_UNBIND; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); - /* When current flag configuration is same as requested one. */ - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag) return 0; - if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag)) - return 0; - } - - if (set) - SET_FLAG (peer->af_flags[afi][safi], flag); - else - UNSET_FLAG (peer->af_flags[afi][safi], flag); - - /* Execute action when peer is established. */ - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP) - && peer->status == Established) - { - if (! set && flag == PEER_FLAG_SOFT_RECONFIG) - bgp_clear_adj_in (peer, afi, safi); - else - { - if (flag == PEER_FLAG_REFLECTOR_CLIENT) - peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE; - else if (flag == PEER_FLAG_RSERVER_CLIENT) - peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE; - else if (flag == PEER_FLAG_ORF_PREFIX_SM) - peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE; - else if (flag == PEER_FLAG_ORF_PREFIX_RM) - peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE; - - peer_change_action (peer, afi, safi, action.type); - } - - } - - /* Peer group member updates. */ - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - group = peer->group; - - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer)) - { - if (set && CHECK_FLAG (tmp_peer->af_flags[afi][safi], flag) == flag) - continue; +} - if (! set && ! CHECK_FLAG (tmp_peer->af_flags[afi][safi], flag)) - continue; +static int bgp_startup_timer_expire(struct thread *thread) +{ + struct bgp *bgp; - if (set) - SET_FLAG (tmp_peer->af_flags[afi][safi], flag); - else - UNSET_FLAG (tmp_peer->af_flags[afi][safi], flag); + bgp = THREAD_ARG(thread); + bgp->t_startup = NULL; - if (tmp_peer->status == Established) - { - if (! set && flag == PEER_FLAG_SOFT_RECONFIG) - bgp_clear_adj_in (tmp_peer, afi, safi); - else - { - if (flag == PEER_FLAG_REFLECTOR_CLIENT) - tmp_peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE; - else if (flag == PEER_FLAG_RSERVER_CLIENT) - tmp_peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE; - else if (flag == PEER_FLAG_ORF_PREFIX_SM) - tmp_peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE; - else if (flag == PEER_FLAG_ORF_PREFIX_RM) - tmp_peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE; + return 0; +} - peer_change_action (tmp_peer, afi, safi, action.type); - } - } +/* BGP instance creation by `router bgp' commands. */ +static struct bgp *bgp_create(as_t *as, const char *name, + enum bgp_instance_type inst_type) +{ + struct bgp *bgp; + afi_t afi; + safi_t safi; + + if ((bgp = XCALLOC(MTYPE_BGP, sizeof(struct bgp))) == NULL) + return NULL; + + if (BGP_DEBUG(zebra, ZEBRA)) { + if (inst_type == BGP_INSTANCE_TYPE_DEFAULT) + zlog_debug("Creating Default VRF, AS %u", *as); + else + zlog_debug("Creating %s %s, AS %u", + (inst_type == BGP_INSTANCE_TYPE_VRF) + ? "VRF" + : "VIEW", + name, *as); } - } - /* Track if addpath TX is in use */ - if (flag & (PEER_FLAG_ADDPATH_TX_ALL_PATHS|PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) - { - bgp = peer->bgp; - addpath_tx_used = 0; + bgp_lock(bgp); + bgp->inst_type = inst_type; + bgp->vrf_id = (inst_type == BGP_INSTANCE_TYPE_DEFAULT) ? VRF_DEFAULT + : VRF_UNKNOWN; + bgp->peer_self = peer_new(bgp); + if (bgp->peer_self->host) + XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->host); + bgp->peer_self->host = + XSTRDUP(MTYPE_BGP_PEER_HOST, "Static announcement"); + bgp->peer = list_new(); + bgp->peer->cmp = (int (*)(void *, void *))peer_cmp; + bgp->peerhash = hash_create(peer_hash_key_make, peer_hash_cmp, NULL); + + bgp->group = list_new(); + bgp->group->cmp = (int (*)(void *, void *))peer_group_cmp; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + bgp->route[afi][safi] = bgp_table_init(afi, safi); + bgp->aggregate[afi][safi] = bgp_table_init(afi, safi); + bgp->rib[afi][safi] = bgp_table_init(afi, safi); + + /* Enable maximum-paths */ + bgp_maximum_paths_set(bgp, afi, safi, BGP_PEER_EBGP, + multipath_num, 0); + bgp_maximum_paths_set(bgp, afi, safi, BGP_PEER_IBGP, + multipath_num, 0); + } + + bgp->v_update_delay = BGP_UPDATE_DELAY_DEF; + bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF; + bgp->default_subgroup_pkt_queue_max = + BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX; + bgp->default_holdtime = BGP_DEFAULT_HOLDTIME; + bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE; + bgp->restart_time = BGP_DEFAULT_RESTART_TIME; + bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME; + bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT; + bgp->dynamic_neighbors_count = 0; +#if DFLT_BGP_IMPORT_CHECK + bgp_flag_set(bgp, BGP_FLAG_IMPORT_CHECK); +#endif +#if DFLT_BGP_SHOW_HOSTNAME + bgp_flag_set(bgp, BGP_FLAG_SHOW_HOSTNAME); +#endif +#if DFLT_BGP_LOG_NEIGHBOR_CHANGES + bgp_flag_set(bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES); +#endif +#if DFLT_BGP_DETERMINISTIC_MED + bgp_flag_set(bgp, BGP_FLAG_DETERMINISTIC_MED); +#endif + bgp->addpath_tx_id = BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE; + + bgp->as = *as; + +#if ENABLE_BGP_VNC + if (inst_type != BGP_INSTANCE_TYPE_VRF) { + bgp->rfapi = bgp_rfapi_new(bgp); + assert(bgp->rfapi); + assert(bgp->rfapi_cfg); + } +#endif /* ENABLE_BGP_VNC */ - if (set) - { - addpath_tx_used = 1; + if (name) { + bgp->name = XSTRDUP(MTYPE_BGP, name); + } else { + /* TODO - The startup timer needs to be run for the whole of BGP + */ + thread_add_timer(bm->master, bgp_startup_timer_expire, bgp, + bgp->restart_time, &bgp->t_startup); + } - if (flag & PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS) - { - if (!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)) - { - zlog_warn("%s: enabling bgp deterministic-med, this is required"\ - " for addpath-tx-bestpath-per-AS", - peer->host); - bgp_flag_set (bgp, BGP_FLAG_DETERMINISTIC_MED); - bgp_recalculate_all_bestpaths (bgp); - } - } - } - else - { - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, tmp_peer)) - { - if (CHECK_FLAG (tmp_peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS) || - CHECK_FLAG (tmp_peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) - { - addpath_tx_used = 1; - break; - } - } - } + bgp->wpkt_quanta = BGP_WRITE_PACKET_MAX; + bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME; - bgp->addpath_tx_used[afi][safi] = addpath_tx_used; - } + QOBJ_REG(bgp, bgp); - return 0; + update_bgp_group_init(bgp); + bgp_evpn_init(bgp); + return bgp; } -int -peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag) +/* Return the "default VRF" instance of BGP. */ +struct bgp *bgp_get_default(void) { - return peer_af_flag_modify (peer, afi, safi, flag, 1); + struct bgp *bgp; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) + if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) + return bgp; + return NULL; } -int -peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag) +/* Lookup BGP entry. */ +struct bgp *bgp_lookup(as_t as, const char *name) { - return peer_af_flag_modify (peer, afi, safi, flag, 0); -} + struct bgp *bgp; + struct listnode *node, *nnode; + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) + if (bgp->as == as + && ((bgp->name == NULL && name == NULL) + || (bgp->name && name && strcmp(bgp->name, name) == 0))) + return bgp; + return NULL; +} -int peer_tx_shutdown_message_set (struct peer *peer, const char *msg) +/* Lookup BGP structure by view name. */ +struct bgp *bgp_lookup_by_name(const char *name) { - XFREE (MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message); - peer->tx_shutdown_message = msg ? XSTRDUP (MTYPE_PEER_TX_SHUTDOWN_MSG, msg) : NULL; - return 0; + struct bgp *bgp; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) + if ((bgp->name == NULL && name == NULL) + || (bgp->name && name && strcmp(bgp->name, name) == 0)) + return bgp; + return NULL; } -int peer_tx_shutdown_message_unset (struct peer *peer) +/* Lookup BGP instance based on VRF id. */ +/* Note: Only to be used for incoming messages from Zebra. */ +struct bgp *bgp_lookup_by_vrf_id(vrf_id_t vrf_id) { - XFREE (MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message); - return 0; + struct vrf *vrf; + + /* Lookup VRF (in tree) and follow link. */ + vrf = vrf_lookup_by_id(vrf_id); + if (!vrf) + return NULL; + return (vrf->info) ? (struct bgp *)vrf->info : NULL; } +/* Called from VTY commands. */ +int bgp_get(struct bgp **bgp_val, as_t *as, const char *name, + enum bgp_instance_type inst_type) +{ + struct bgp *bgp; + + /* Multiple instance check. */ + if (bgp_option_check(BGP_OPT_MULTIPLE_INSTANCE)) { + if (name) + bgp = bgp_lookup_by_name(name); + else + bgp = bgp_get_default(); + + /* Already exists. */ + if (bgp) { + if (bgp->as != *as) { + *as = bgp->as; + return BGP_ERR_INSTANCE_MISMATCH; + } + if (bgp->inst_type != inst_type) + return BGP_ERR_INSTANCE_MISMATCH; + *bgp_val = bgp; + return 0; + } + } else { + /* BGP instance name can not be specified for single instance. + */ + if (name) + return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET; + + /* Get default BGP structure if exists. */ + bgp = bgp_get_default(); + + if (bgp) { + if (bgp->as != *as) { + *as = bgp->as; + return BGP_ERR_AS_MISMATCH; + } + *bgp_val = bgp; + return 0; + } + } -/* EBGP multihop configuration. */ -int -peer_ebgp_multihop_set (struct peer *peer, int ttl) -{ - struct peer_group *group; - struct listnode *node, *nnode; - struct peer *peer1; - - if (peer->sort == BGP_PEER_IBGP || peer->conf_if) - return 0; - - /* see comment in peer_ttl_security_hops_set() */ - if (ttl != MAXTTL) - { - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - group = peer->group; - if (group->conf->gtsm_hops != 0) - return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK; - - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1)) - { - if (peer1->sort == BGP_PEER_IBGP) - continue; - - if (peer1->gtsm_hops != 0) - return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK; - } - } - else - { - if (peer->gtsm_hops != 0) - return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK; - } - } - - peer->ttl = ttl; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else - bgp_session_reset(peer); - } - } - else - { - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (peer->sort == BGP_PEER_IBGP) - continue; - - peer->ttl = group->conf->ttl; - - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else - bgp_session_reset(peer); - } - } - return 0; -} - -int -peer_ebgp_multihop_unset (struct peer *peer) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - if (peer->sort == BGP_PEER_IBGP) - return 0; - - if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL) - return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK; - - if (peer_group_active (peer)) - peer->ttl = peer->group->conf->ttl; - else - peer->ttl = 1; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else - bgp_session_reset(peer); - } - else - { - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (peer->sort == BGP_PEER_IBGP) - continue; + bgp = bgp_create(as, name, inst_type); + bgp_router_id_set(bgp, &bgp->router_id_zebra); + bgp_address_init(bgp); + bgp_scan_init(bgp); + *bgp_val = bgp; - peer->ttl = 1; + bgp->t_rmap_def_originate_eval = NULL; - if (peer->fd >= 0) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else - bgp_session_reset(peer); - } + /* Create BGP server socket, if first instance. */ + if (list_isempty(bm->bgp) && !bgp_option_check(BGP_OPT_NO_LISTEN)) { + if (bgp_socket(bm->port, bm->address) < 0) + return BGP_ERR_INVALID_VALUE; } - } - return 0; -} -/* Neighbor description. */ -int -peer_description_set (struct peer *peer, const char *desc) -{ - if (peer->desc) - XFREE (MTYPE_PEER_DESC, peer->desc); + listnode_add(bm->bgp, bgp); - peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc); + /* If Default instance or VRF, link to the VRF structure, if present. */ + if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT + || bgp->inst_type == BGP_INSTANCE_TYPE_VRF) { + struct vrf *vrf; - return 0; -} + vrf = bgp_vrf_lookup_by_instance_type(bgp); + if (vrf) + bgp_vrf_link(bgp, vrf); + } -int -peer_description_unset (struct peer *peer) -{ - if (peer->desc) - XFREE (MTYPE_PEER_DESC, peer->desc); + /* Register with Zebra, if needed */ + if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + bgp_zebra_instance_register(bgp); - peer->desc = NULL; - return 0; + return 0; } -/* Neighbor update-source. */ -int -peer_update_source_if_set (struct peer *peer, const char *ifname) +/* + * Make BGP instance "up". Applies only to VRFs (non-default) and + * implies the VRF has been learnt from Zebra. + */ +void bgp_instance_up(struct bgp *bgp) { - struct peer_group *group; - struct listnode *node, *nnode; + struct peer *peer; + struct listnode *node, *next; - if (peer->update_if) - { - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP) - && strcmp (peer->update_if, ifname) == 0) - return 0; - - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - peer->update_if = NULL; - } - - if (peer->update_source) - { - sockunion_free (peer->update_source); - peer->update_source = NULL; - } - - peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname); - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - return 0; - } - - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (peer->update_if) - { - if (strcmp (peer->update_if, ifname) == 0) - continue; + /* Register with zebra. */ + bgp_zebra_instance_register(bgp); - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - peer->update_if = NULL; + /* Kick off any peers that may have been configured. */ + for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) { + if (!BGP_PEER_START_SUPPRESSED(peer)) + BGP_EVENT_ADD(peer, BGP_Start); } - if (peer->update_source) - { - sockunion_free (peer->update_source); - peer->update_source = NULL; + /* Process any networks that have been configured. */ + bgp_static_add(bgp); +} + +/* + * Make BGP instance "down". Applies only to VRFs (non-default) and + * implies the VRF has been deleted by Zebra. + */ +void bgp_instance_down(struct bgp *bgp) +{ + struct peer *peer; + struct listnode *node; + struct listnode *next; + + /* Stop timers. */ + if (bgp->t_rmap_def_originate_eval) { + BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval); + bgp_unlock(bgp); /* TODO - This timer is started with a lock - + why? */ } - peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname); + /* Bring down peers, so corresponding routes are purged. */ + for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); + else + bgp_session_reset(peer); + } - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - } - return 0; + /* Purge network and redistributed routes. */ + bgp_purge_static_redist_routes(bgp); } -int -peer_update_source_addr_set (struct peer *peer, const union sockunion *su) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - if (peer->update_source) - { - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP) - && sockunion_cmp (peer->update_source, su) == 0) - return 0; - sockunion_free (peer->update_source); - peer->update_source = NULL; - } - - if (peer->update_if) - { - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - peer->update_if = NULL; - - } - - peer->update_source = sockunion_dup (su); - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - return 0; - } - - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (peer->update_source) - { - if (sockunion_cmp (peer->update_source, su) == 0) - continue; - sockunion_free (peer->update_source); - peer->update_source = NULL; +/* Delete BGP instance. */ +int bgp_delete(struct bgp *bgp) +{ + struct peer *peer; + struct peer_group *group; + struct listnode *node, *next; + struct vrf *vrf; + afi_t afi; + int i; + + THREAD_OFF(bgp->t_startup); + + if (BGP_DEBUG(zebra, ZEBRA)) { + if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) + zlog_debug("Deleting Default VRF"); + else + zlog_debug("Deleting %s %s", + (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) + ? "VRF" + : "VIEW", + bgp->name); } - if (peer->update_if) - { - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - peer->update_if = NULL; - } - - peer->update_source = sockunion_dup (su); - - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - } - return 0; -} - -int -peer_update_source_unset (struct peer *peer) -{ - union sockunion *su; - struct peer_group *group; - struct listnode *node, *nnode; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP) - && ! peer->update_source - && ! peer->update_if) - return 0; - - if (peer->update_source) - { - sockunion_free (peer->update_source); - peer->update_source = NULL; - } - if (peer->update_if) - { - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - peer->update_if = NULL; - } - - if (peer_group_active (peer)) - { - group = peer->group; - - if (group->conf->update_source) - { - su = sockunion_dup (group->conf->update_source); - peer->update_source = su; - } - else if (group->conf->update_if) - peer->update_if = - XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if); - } - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - return 0; - } - - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (! peer->update_source && ! peer->update_if) - continue; - - if (peer->update_source) - { - sockunion_free (peer->update_source); - peer->update_source = NULL; + /* Stop timers. */ + if (bgp->t_rmap_def_originate_eval) { + BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval); + bgp_unlock(bgp); /* TODO - This timer is started with a lock - + why? */ } - if (peer->update_if) - { - XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - peer->update_if = NULL; + /* Inform peers we're going down. */ + for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); } - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - } - return 0; -} + /* Delete static routes (networks). */ + bgp_static_delete(bgp); -int -peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi, - const char *rmap) -{ - struct peer_group *group; - struct listnode *node, *nnode; + /* Unset redistribution. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (i != ZEBRA_ROUTE_BGP) + bgp_redistribute_unset(bgp, afi, i, 0); - if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE) - || (rmap && ! peer->default_rmap[afi][safi].name) - || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0)) - { - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE); + /* Free peers and peer-groups. */ + for (ALL_LIST_ELEMENTS(bgp->group, node, next, group)) + peer_group_delete(group); - if (rmap) - { - if (peer->default_rmap[afi][safi].name) - XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name); - peer->default_rmap[afi][safi].name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); - peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap); - } - } - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (peer->status == Established && peer->afc_nego[afi][safi]) { - update_group_adjust_peer(peer_af_find(peer, afi, safi)); - bgp_default_originate (peer, afi, safi, 0); - bgp_announce_route (peer, afi, safi); - } - return 0; - } - - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE); - - if (rmap) - { - if (peer->default_rmap[afi][safi].name) - XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name); - peer->default_rmap[afi][safi].name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); - peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap); + for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) + peer_delete(peer); + + if (bgp->peer_self) { + peer_delete(bgp->peer_self); + bgp->peer_self = NULL; } - if (peer->status == Established && peer->afc_nego[afi][safi]) { - update_group_adjust_peer(peer_af_find(peer, afi, safi)); - bgp_default_originate (peer, afi, safi, 0); - bgp_announce_route (peer, afi, safi); - } - } - return 0; -} + update_bgp_group_free(bgp); -int -peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi) -{ - struct peer_group *group; - struct listnode *node, *nnode; +/* TODO - Other memory may need to be freed - e.g., NHT */ + +#if ENABLE_BGP_VNC + rfapi_delete(bgp); +#endif + bgp_cleanup_routes(bgp); - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)) - { - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE); + /* Remove visibility via the master list - there may however still be + * routes to be processed still referencing the struct bgp. + */ + listnode_delete(bm->bgp, bgp); - if (peer->default_rmap[afi][safi].name) - XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name); - peer->default_rmap[afi][safi].name = NULL; - peer->default_rmap[afi][safi].map = NULL; - } + /* Deregister from Zebra, if needed */ + if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + bgp_zebra_instance_deregister(bgp); - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (peer->status == Established && peer->afc_nego[afi][safi]) { - update_group_adjust_peer(peer_af_find(peer, afi, safi)); - bgp_default_originate (peer, afi, safi, 1); - bgp_announce_route (peer, afi, safi); - } - return 0; - } + /* Free interfaces in this instance. */ + bgp_if_finish(bgp); - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE); + vrf = bgp_vrf_lookup_by_instance_type(bgp); + if (vrf) + bgp_vrf_unlink(bgp, vrf); - if (peer->default_rmap[afi][safi].name) - XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name); - peer->default_rmap[afi][safi].name = NULL; - peer->default_rmap[afi][safi].map = NULL; + thread_master_free_unused(bm->master); + bgp_unlock(bgp); /* initial reference */ - if (peer->status == Established && peer->afc_nego[afi][safi]) { - update_group_adjust_peer(peer_af_find(peer, afi, safi)); - bgp_default_originate (peer, afi, safi, 1); - bgp_announce_route (peer, afi, safi); - } - } - return 0; + return 0; } -int -peer_port_set (struct peer *peer, u_int16_t port) +static void bgp_free(struct bgp *); + +void bgp_lock(struct bgp *bgp) { - peer->port = port; - return 0; + ++bgp->lock; } -int -peer_port_unset (struct peer *peer) +void bgp_unlock(struct bgp *bgp) { - peer->port = BGP_PORT_DEFAULT; - return 0; + assert(bgp->lock > 0); + if (--bgp->lock == 0) + bgp_free(bgp); } -/* - * Helper function that is called after the name of the policy - * being used by a peer has changed (AF specific). Automatically - * initiates inbound or outbound processing as needed. - */ -static void -peer_on_policy_change (struct peer *peer, afi_t afi, safi_t safi, int outbound) +static void bgp_free(struct bgp *bgp) { - if (outbound) - { - update_group_adjust_peer (peer_af_find (peer, afi, safi)); - if (peer->status == Established) - bgp_announce_route(peer, afi, safi); - } - else - { - if (peer->status != Established) - return; - - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)) - bgp_soft_reconfig_in (peer, afi, safi); - else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV) - || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV)) - bgp_route_refresh_send (peer, afi, safi, 0, 0, 0); - } -} + afi_t afi; + safi_t safi; + struct bgp_table *table; + struct bgp_node *rn; + QOBJ_UNREG(bgp); -/* neighbor weight. */ -int -peer_weight_set (struct peer *peer, afi_t afi, safi_t safi, u_int16_t weight) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - if (peer->weight[afi][safi] != weight) - { - peer->weight[afi][safi] = weight; - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT); - peer_on_policy_change (peer, afi, safi, 0); - } - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (peer->weight[afi][safi] != weight) - { - peer->weight[afi][safi] = weight; - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT); - peer_on_policy_change (peer, afi, safi, 0); - } - } - return 0; -} - -int -peer_weight_unset (struct peer *peer, afi_t afi, safi_t safi) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - /* not the peer-group itself but a peer in a peer-group */ - if (peer_group_active (peer)) - { - group = peer->group; - - /* inherit weight from the peer-group */ - if (CHECK_FLAG (group->conf->af_flags[afi][safi], PEER_FLAG_WEIGHT)) - { - peer->weight[afi][safi] = group->conf->weight[afi][safi]; - peer_af_flag_set (peer, afi, safi, PEER_FLAG_WEIGHT); - peer_on_policy_change (peer, afi, safi, 0); - } - else - { - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT)) - { - peer->weight[afi][safi] = 0; - peer_af_flag_unset (peer, afi, safi, PEER_FLAG_WEIGHT); - peer_on_policy_change (peer, afi, safi, 0); - } - } - } - - else - { - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT)) - { - peer->weight[afi][safi] = 0; - peer_af_flag_unset (peer, afi, safi, PEER_FLAG_WEIGHT); - peer_on_policy_change (peer, afi, safi, 0); - } - - /* peer-group member updates. */ - group = peer->group; - - if (group) - { - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT)) - { - peer->weight[afi][safi] = 0; - peer_af_flag_unset (peer, afi, safi, PEER_FLAG_WEIGHT); - peer_on_policy_change (peer, afi, safi, 0); - } - } - } - } - return 0; -} - -int -peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - /* keepalive value check. */ - if (keepalive > 65535) - return BGP_ERR_INVALID_VALUE; - - /* Holdtime value check. */ - if (holdtime > 65535) - return BGP_ERR_INVALID_VALUE; - - /* Holdtime value must be either 0 or greater than 3. */ - if (holdtime < 3 && holdtime != 0) - return BGP_ERR_INVALID_VALUE; - - /* Set value to the configuration. */ - SET_FLAG (peer->config, PEER_CONFIG_TIMER); - peer->holdtime = holdtime; - peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3); - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - SET_FLAG (peer->config, PEER_CONFIG_TIMER); - peer->holdtime = group->conf->holdtime; - peer->keepalive = group->conf->keepalive; - } - return 0; -} - -int -peer_timers_unset (struct peer *peer) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - /* Clear configuration. */ - UNSET_FLAG (peer->config, PEER_CONFIG_TIMER); - peer->keepalive = 0; - peer->holdtime = 0; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - UNSET_FLAG (peer->config, PEER_CONFIG_TIMER); - peer->holdtime = 0; - peer->keepalive = 0; - } - - return 0; -} - -int -peer_timers_connect_set (struct peer *peer, u_int32_t connect) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - if (connect > 65535) - return BGP_ERR_INVALID_VALUE; - - /* Set value to the configuration. */ - SET_FLAG (peer->config, PEER_CONFIG_CONNECT); - peer->connect = connect; - - /* Set value to timer setting. */ - peer->v_connect = connect; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - SET_FLAG (peer->config, PEER_CONFIG_CONNECT); - peer->connect = connect; - peer->v_connect = connect; - } - return 0; -} - -int -peer_timers_connect_unset (struct peer *peer) -{ - struct peer_group *group; - struct listnode *node, *nnode; + list_delete(bgp->group); + list_delete(bgp->peer); - /* Clear configuration. */ - UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT); - peer->connect = 0; + if (bgp->peerhash) { + hash_free(bgp->peerhash); + bgp->peerhash = NULL; + } - /* Set timer setting to default value. */ - peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + /* Special handling for 2-level routing tables. */ + if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP + || safi == SAFI_EVPN) { + for (rn = bgp_table_top(bgp->rib[afi][safi]); + rn; rn = bgp_route_next(rn)) { + table = (struct bgp_table *)rn->info; + bgp_table_finish(&table); + } + } + if (bgp->route[afi][safi]) + bgp_table_finish(&bgp->route[afi][safi]); + if (bgp->aggregate[afi][safi]) + bgp_table_finish(&bgp->aggregate[afi][safi]); + if (bgp->rib[afi][safi]) + bgp_table_finish(&bgp->rib[afi][safi]); + } - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT); - peer->connect = 0; - peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; - } - return 0; -} - -int -peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv) -{ - struct peer_group *group; - struct listnode *node, *nnode; + bgp_scan_finish(bgp); + bgp_address_destroy(bgp); - if (routeadv > 600) - return BGP_ERR_INVALID_VALUE; - - SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV); - peer->routeadv = routeadv; - peer->v_routeadv = routeadv; + bgp_evpn_cleanup(bgp); - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) { - update_group_adjust_peer_afs (peer); - if (peer->status == Established) - bgp_announce_route_all (peer); - return 0; - } + if (bgp->name) + XFREE(MTYPE_BGP, bgp->name); - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV); - peer->routeadv = routeadv; - peer->v_routeadv = routeadv; - update_group_adjust_peer_afs (peer); - if (peer->status == Established) - bgp_announce_route_all (peer); - } - - return 0; + XFREE(MTYPE_BGP, bgp); } -int -peer_advertise_interval_unset (struct peer *peer) +struct peer *peer_lookup_by_conf_if(struct bgp *bgp, const char *conf_if) { - struct peer_group *group; - struct listnode *node, *nnode; + struct peer *peer; + struct listnode *node, *nnode; - UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV); - peer->routeadv = 0; - - if (peer->sort == BGP_PEER_IBGP) - peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; - else - peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) { - update_group_adjust_peer_afs (peer); - if (peer->status == Established) - bgp_announce_route_all (peer); - return 0; - } - - /* peer-group member updates. */ - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV); - peer->routeadv = 0; - - if (peer->sort == BGP_PEER_IBGP) - peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; - else - peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; - - update_group_adjust_peer_afs (peer); - if (peer->status == Established) - bgp_announce_route_all (peer); - } - - return 0; -} + if (!conf_if) + return NULL; -/* neighbor interface */ -void -peer_interface_set (struct peer *peer, const char *str) -{ - if (peer->ifname) - XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname); - peer->ifname = XSTRDUP(MTYPE_BGP_PEER_IFNAME, str); + if (bgp != NULL) { + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) + if (peer->conf_if && !strcmp(peer->conf_if, conf_if) + && !CHECK_FLAG(peer->sflags, + PEER_STATUS_ACCEPT_PEER)) + return peer; + } else if (bm->bgp != NULL) { + struct listnode *bgpnode, *nbgpnode; + + for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp)) + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) + if (peer->conf_if + && !strcmp(peer->conf_if, conf_if) + && !CHECK_FLAG(peer->sflags, + PEER_STATUS_ACCEPT_PEER)) + return peer; + } + return NULL; } -void -peer_interface_unset (struct peer *peer) +struct peer *peer_lookup_by_hostname(struct bgp *bgp, const char *hostname) { - if (peer->ifname) - XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname); - peer->ifname = NULL; -} + struct peer *peer; + struct listnode *node, *nnode; -/* Allow-as in. */ -int -peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num, - int origin) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - if (origin) - { - if (peer->allowas_in[afi][safi] || - CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN) || - !CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) - { - peer->allowas_in[afi][safi] = 0; - peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN); - peer_af_flag_set (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN); - peer_on_policy_change (peer, afi, safi, 0); - } - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (peer->allowas_in[afi][safi] || - CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN) || - !CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) - { - peer->allowas_in[afi][safi] = 0; - peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN); - peer_af_flag_set (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN); - peer_on_policy_change (peer, afi, safi, 0); - } - } - } - else - { - if (allow_num < 1 || allow_num > 10) - return BGP_ERR_INVALID_VALUE; - - if (peer->allowas_in[afi][safi] != allow_num || - CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) - { - peer->allowas_in[afi][safi] = allow_num; - peer_af_flag_set (peer, afi, safi, PEER_FLAG_ALLOWAS_IN); - peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN); - peer_on_policy_change (peer, afi, safi, 0); - } - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - if (peer->allowas_in[afi][safi] != allow_num || - CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) - { - peer->allowas_in[afi][safi] = allow_num; - peer_af_flag_set (peer, afi, safi, PEER_FLAG_ALLOWAS_IN); - peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN); - peer_on_policy_change (peer, afi, safi, 0); - } - } - } - - return 0; -} - -int -peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi) -{ - struct peer_group *group; - struct peer *tmp_peer; - struct listnode *node, *nnode; - - /* If this is a peer-group we must first clear the flags for all of the - * peer-group members - */ - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer)) - { - if (CHECK_FLAG (tmp_peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN) || - CHECK_FLAG (tmp_peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) - { - tmp_peer->allowas_in[afi][safi] = 0; - peer_af_flag_unset (tmp_peer, afi, safi, PEER_FLAG_ALLOWAS_IN); - peer_af_flag_unset (tmp_peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN); - peer_on_policy_change (tmp_peer, afi, safi, 0); - } - } - } - - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN) || - CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN)) - { - peer->allowas_in[afi][safi] = 0; - peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN); - peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN); - peer_on_policy_change (peer, afi, safi, 0); - } - - return 0; -} - -int -peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as) -{ - struct bgp *bgp = peer->bgp; - struct peer_group *group; - struct listnode *node, *nnode; - - if (peer_sort (peer) != BGP_PEER_EBGP - && peer_sort (peer) != BGP_PEER_INTERNAL) - return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP; - - if (bgp->as == as) - return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS; - - if (peer->as == as) - return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS; - - if (peer->change_local_as == as && - ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend) - || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) && - ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as) - || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as))) - return 0; - - peer->change_local_as = as; - if (no_prepend) - SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); - else - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); - - if (replace_as) - SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); - else - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - return 0; - } - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - peer->change_local_as = as; - if (no_prepend) - SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); - else - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); - - if (replace_as) - SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); - else - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); - - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - BGP_EVENT_ADD (peer, BGP_Stop); - } - - return 0; -} - -int -peer_local_as_unset (struct peer *peer) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - if (! peer->change_local_as) - return 0; - - peer->change_local_as = 0; - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - BGP_EVENT_ADD (peer, BGP_Stop); - - return 0; - } - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - peer->change_local_as = 0; - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); - UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); - - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - { - peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } - else - bgp_session_reset(peer); - } - return 0; -} + if (!hostname) + return NULL; -/* Set password for authenticating with the peer. */ -int -peer_password_set (struct peer *peer, const char *password) -{ - struct listnode *nn, *nnode; - int len = password ? strlen(password) : 0; - int ret = BGP_SUCCESS; - - if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN)) - return BGP_ERR_INVALID_VALUE; - - if (peer->password && strcmp (peer->password, password) == 0 - && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - if (peer->password) - XFREE (MTYPE_PEER_PASSWORD, peer->password); - - peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password); - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else - bgp_session_reset(peer); - - if (BGP_PEER_SU_UNSPEC(peer)) - return BGP_SUCCESS; - - return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED; - } - - for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer)) - { - if (peer->password && strcmp (peer->password, password) == 0) - continue; - - if (peer->password) - XFREE (MTYPE_PEER_PASSWORD, peer->password); - - peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password); - - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else - bgp_session_reset(peer); - - if (! BGP_PEER_SU_UNSPEC(peer)) - { - if (bgp_md5_set (peer) < 0) - ret = BGP_ERR_TCPSIG_FAILED; - } - } - - return ret; -} - -int -peer_password_unset (struct peer *peer) -{ - struct listnode *nn, *nnode; - - if (!peer->password - && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else - bgp_session_reset(peer); - - if (peer->password) - XFREE (MTYPE_PEER_PASSWORD, peer->password); - - peer->password = NULL; - - if (! BGP_PEER_SU_UNSPEC(peer)) - bgp_md5_unset (peer); - - return 0; - } - - XFREE (MTYPE_PEER_PASSWORD, peer->password); - peer->password = NULL; - - for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer)) - { - if (!peer->password) - continue; - - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); - else - bgp_session_reset(peer); - - XFREE (MTYPE_PEER_PASSWORD, peer->password); - peer->password = NULL; - - if (! BGP_PEER_SU_UNSPEC(peer)) - bgp_md5_unset (peer); - } - - return 0; -} + if (bgp != NULL) { + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) + if (peer->hostname && !strcmp(peer->hostname, hostname) + && !CHECK_FLAG(peer->sflags, + PEER_STATUS_ACCEPT_PEER)) + return peer; + } else if (bm->bgp != NULL) { + struct listnode *bgpnode, *nbgpnode; + + for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp)) + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) + if (peer->hostname + && !strcmp(peer->hostname, hostname) + && !CHECK_FLAG(peer->sflags, + PEER_STATUS_ACCEPT_PEER)) + return peer; + } + return NULL; +} + +struct peer *peer_lookup(struct bgp *bgp, union sockunion *su) +{ + struct peer *peer = NULL; + struct peer tmp_peer; + + memset(&tmp_peer, 0, sizeof(struct peer)); + + /* + * We do not want to find the doppelganger peer so search for the peer + * in + * the hash that has PEER_FLAG_CONFIG_NODE + */ + SET_FLAG(tmp_peer.flags, PEER_FLAG_CONFIG_NODE); + + tmp_peer.su = *su; + + if (bgp != NULL) { + peer = hash_lookup(bgp->peerhash, &tmp_peer); + } else if (bm->bgp != NULL) { + struct listnode *bgpnode, *nbgpnode; + + for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp)) { + /* Skip VRFs, this function will not be invoked without + * an instance + * when examining VRFs. + */ + if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) + continue; + + peer = hash_lookup(bgp->peerhash, &tmp_peer); + + if (peer) + break; + } + } + + return peer; +} + +struct peer *peer_create_bind_dynamic_neighbor(struct bgp *bgp, + union sockunion *su, + struct peer_group *group) +{ + struct peer *peer; + afi_t afi; + safi_t safi; + + /* Create peer first; we've already checked group config is valid. */ + peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as, + group->conf->as_type, 0, 0, group); + if (!peer) + return NULL; + + /* Link to group */ + peer = peer_lock(peer); + listnode_add(group->peer, peer); + + peer_group2peer_config_copy(group, peer); + + /* + * Bind peer for all AFs configured for the group. We don't call + * peer_group_bind as that is sub-optimal and does some stuff we don't + * want. + */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + if (!group->conf->afc[afi][safi]) + continue; + peer->afc[afi][safi] = 1; + + if (!peer_af_find(peer, afi, safi)) + peer_af_create(peer, afi, safi); + + peer_group2peer_config_copy_af(group, peer, afi, safi); + } + + /* Mark as dynamic, but also as a "config node" for other things to + * work. */ + SET_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR); + SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); + + return peer; +} + +struct prefix * +peer_group_lookup_dynamic_neighbor_range(struct peer_group *group, + struct prefix *prefix) +{ + struct listnode *node, *nnode; + struct prefix *range; + afi_t afi; + + afi = family2afi(prefix->family); + + if (group->listen_range[afi]) + for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode, + range)) + if (prefix_match(range, prefix)) + return range; + + return NULL; +} + +struct peer_group * +peer_group_lookup_dynamic_neighbor(struct bgp *bgp, struct prefix *prefix, + struct prefix **listen_range) +{ + struct prefix *range = NULL; + struct peer_group *group = NULL; + struct listnode *node, *nnode; + + *listen_range = NULL; + if (bgp != NULL) { + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) + if ((range = peer_group_lookup_dynamic_neighbor_range( + group, prefix))) + break; + } else if (bm->bgp != NULL) { + struct listnode *bgpnode, *nbgpnode; + + for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp)) + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) + if ((range = peer_group_lookup_dynamic_neighbor_range( + group, prefix))) + goto found_range; + } + +found_range: + *listen_range = range; + return (group && range) ? group : NULL; +} + +struct peer *peer_lookup_dynamic_neighbor(struct bgp *bgp, union sockunion *su) +{ + struct peer_group *group; + struct bgp *gbgp; + struct peer *peer; + struct prefix prefix; + struct prefix *listen_range; + int dncount; + char buf[PREFIX2STR_BUFFER]; + char buf1[PREFIX2STR_BUFFER]; + + sockunion2hostprefix(su, &prefix); + + /* See if incoming connection matches a configured listen range. */ + group = peer_group_lookup_dynamic_neighbor(bgp, &prefix, &listen_range); + + if (!group) + return NULL; + + + gbgp = group->bgp; + + if (!gbgp) + return NULL; + + prefix2str(&prefix, buf, sizeof(buf)); + prefix2str(listen_range, buf1, sizeof(buf1)); + + if (bgp_debug_neighbor_events(NULL)) + zlog_debug( + "Dynamic Neighbor %s matches group %s listen range %s", + buf, group->name, buf1); + + /* Are we within the listen limit? */ + dncount = gbgp->dynamic_neighbors_count; + + if (dncount >= gbgp->dynamic_neighbors_limit) { + if (bgp_debug_neighbor_events(NULL)) + zlog_debug("Dynamic Neighbor %s rejected - at limit %d", + inet_sutop(su, buf), + gbgp->dynamic_neighbors_limit); + return NULL; + } + + /* Ensure group is not disabled. */ + if (CHECK_FLAG(group->conf->flags, PEER_FLAG_SHUTDOWN)) { + if (bgp_debug_neighbor_events(NULL)) + zlog_debug( + "Dynamic Neighbor %s rejected - group %s disabled", + buf, group->name); + return NULL; + } + + /* Check that at least one AF is activated for the group. */ + if (!peer_group_af_configured(group)) { + if (bgp_debug_neighbor_events(NULL)) + zlog_debug( + "Dynamic Neighbor %s rejected - no AF activated for group %s", + buf, group->name); + return NULL; + } + + /* Create dynamic peer and bind to associated group. */ + peer = peer_create_bind_dynamic_neighbor(gbgp, su, group); + assert(peer); + + gbgp->dynamic_neighbors_count = ++dncount; + + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s Dynamic Neighbor added, group %s count %d", + peer->host, group->name, dncount); + + return peer; +} + +void peer_drop_dynamic_neighbor(struct peer *peer) +{ + int dncount = -1; + if (peer->group && peer->group->bgp) { + dncount = peer->group->bgp->dynamic_neighbors_count; + if (dncount) + peer->group->bgp->dynamic_neighbors_count = --dncount; + } + if (bgp_debug_neighbor_events(peer)) + zlog_debug("%s dropped from group %s, count %d", peer->host, + peer->group->name, dncount); +} + + +/* If peer is configured at least one address family return 1. */ +int peer_active(struct peer *peer) +{ + if (BGP_PEER_SU_UNSPEC(peer)) + return 0; + if (peer->afc[AFI_IP][SAFI_UNICAST] || peer->afc[AFI_IP][SAFI_MULTICAST] + || peer->afc[AFI_IP][SAFI_LABELED_UNICAST] + || peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP][SAFI_ENCAP] + || peer->afc[AFI_IP6][SAFI_UNICAST] + || peer->afc[AFI_IP6][SAFI_MULTICAST] + || peer->afc[AFI_IP6][SAFI_LABELED_UNICAST] + || peer->afc[AFI_IP6][SAFI_MPLS_VPN] + || peer->afc[AFI_IP6][SAFI_ENCAP] + || peer->afc[AFI_L2VPN][SAFI_EVPN]) + return 1; + return 0; +} + +/* If peer is negotiated at least one address family return 1. */ +int peer_active_nego(struct peer *peer) +{ + if (peer->afc_nego[AFI_IP][SAFI_UNICAST] + || peer->afc_nego[AFI_IP][SAFI_MULTICAST] + || peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST] + || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] + || peer->afc_nego[AFI_IP][SAFI_ENCAP] + || peer->afc_nego[AFI_IP6][SAFI_UNICAST] + || peer->afc_nego[AFI_IP6][SAFI_MULTICAST] + || peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST] + || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN] + || peer->afc_nego[AFI_IP6][SAFI_ENCAP] + || peer->afc_nego[AFI_L2VPN][SAFI_EVPN]) + return 1; + return 0; +} + +/* peer_flag_change_type. */ +enum peer_change_type { + peer_change_none, + peer_change_reset, + peer_change_reset_in, + peer_change_reset_out, +}; + +static void peer_change_action(struct peer *peer, afi_t afi, safi_t safi, + enum peer_change_type type) +{ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return; + + if (peer->status != Established) + return; + + if (type == peer_change_reset) { + /* If we're resetting session, we've to delete both peer struct + */ + if ((peer->doppelganger) + && (peer->doppelganger->status != Deleted) + && (!CHECK_FLAG(peer->doppelganger->flags, + PEER_FLAG_CONFIG_NODE))) + peer_delete(peer->doppelganger); + + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else if (type == peer_change_reset_in) { + if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV) + || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV)) + bgp_route_refresh_send(peer, afi, safi, 0, 0, 0); + else { + if ((peer->doppelganger) + && (peer->doppelganger->status != Deleted) + && (!CHECK_FLAG(peer->doppelganger->flags, + PEER_FLAG_CONFIG_NODE))) + peer_delete(peer->doppelganger); + + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } + } else if (type == peer_change_reset_out) { + update_group_adjust_peer(peer_af_find(peer, afi, safi)); + bgp_announce_route(peer, afi, safi); + } +} + +struct peer_flag_action { + /* Peer's flag. */ + u_int32_t flag; + + /* This flag can be set for peer-group member. */ + u_char not_for_member; + + /* Action when the flag is changed. */ + enum peer_change_type type; + + /* Peer down cause */ + u_char peer_down; +}; + +static const struct peer_flag_action peer_flag_action_list[] = { + {PEER_FLAG_PASSIVE, 0, peer_change_reset}, + {PEER_FLAG_SHUTDOWN, 0, peer_change_reset}, + {PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none}, + {PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none}, + {PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none}, + {PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset}, + {PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset}, + {PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset}, + {0, 0, 0}}; + +static const struct peer_flag_action peer_af_flag_action_list[] = { + {PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out}, + {PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out}, + {PEER_FLAG_SEND_LARGE_COMMUNITY, 1, peer_change_reset_out}, + {PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out}, + {PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset}, + {PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset}, + {PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in}, + {PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out}, + {PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out}, + {PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out}, + // PEER_FLAG_DEFAULT_ORIGINATE + {PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out}, + {PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in}, + {PEER_FLAG_ALLOWAS_IN_ORIGIN, 0, peer_change_reset_in}, + {PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset}, + {PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset}, + // PEER_FLAG_MAX_PREFIX + // PEER_FLAG_MAX_PREFIX_WARNING + {PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out}, + {PEER_FLAG_FORCE_NEXTHOP_SELF, 1, peer_change_reset_out}, + {PEER_FLAG_REMOVE_PRIVATE_AS_ALL, 1, peer_change_reset_out}, + {PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE, 1, peer_change_reset_out}, + {PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out}, + {PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE, 1, peer_change_reset_out}, + {PEER_FLAG_ADDPATH_TX_ALL_PATHS, 1, peer_change_reset}, + {PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS, 1, peer_change_reset}, + {PEER_FLAG_WEIGHT, 0, peer_change_reset_in}, + {0, 0, 0}}; + +/* Proper action set. */ +static int peer_flag_action_set(const struct peer_flag_action *action_list, + int size, struct peer_flag_action *action, + u_int32_t flag) +{ + int i; + int found = 0; + int reset_in = 0; + int reset_out = 0; + const struct peer_flag_action *match = NULL; + + /* Check peer's frag action. */ + for (i = 0; i < size; i++) { + match = &action_list[i]; + + if (match->flag == 0) + break; + + if (match->flag & flag) { + found = 1; + + if (match->type == peer_change_reset_in) + reset_in = 1; + if (match->type == peer_change_reset_out) + reset_out = 1; + if (match->type == peer_change_reset) { + reset_in = 1; + reset_out = 1; + } + if (match->not_for_member) + action->not_for_member = 1; + } + } + + /* Set peer clear type. */ + if (reset_in && reset_out) + action->type = peer_change_reset; + else if (reset_in) + action->type = peer_change_reset_in; + else if (reset_out) + action->type = peer_change_reset_out; + else + action->type = peer_change_none; + + return found; +} + +static void peer_flag_modify_action(struct peer *peer, u_int32_t flag) +{ + if (flag == PEER_FLAG_SHUTDOWN) { + if (CHECK_FLAG(peer->flags, flag)) { + if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) + peer_nsf_stop(peer); + + UNSET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW); + if (peer->t_pmax_restart) { + BGP_TIMER_OFF(peer->t_pmax_restart); + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Maximum-prefix restart timer canceled", + peer->host); + } + + if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)) + peer_nsf_stop(peer); + + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + char *msg = peer->tx_shutdown_message; + size_t msglen; + + if (!msg && peer_group_active(peer)) + msg = peer->group->conf + ->tx_shutdown_message; + msglen = msg ? strlen(msg) : 0; + if (msglen > 128) + msglen = 128; + + if (msglen) { + u_char msgbuf[129]; + + msgbuf[0] = msglen; + memcpy(msgbuf + 1, msg, msglen); + + bgp_notify_send_with_data( + peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN, + msgbuf, msglen + 1); + } else + bgp_notify_send( + peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); + } else + bgp_session_reset(peer); + } else { + peer->v_start = BGP_INIT_START_TIMER; + BGP_EVENT_ADD(peer, BGP_Stop); + } + } else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + if (flag == PEER_FLAG_DYNAMIC_CAPABILITY) + peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE; + else if (flag == PEER_FLAG_PASSIVE) + peer->last_reset = PEER_DOWN_PASSIVE_CHANGE; + else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK) + peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE; + + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); +} + +/* Change specified peer flag. */ +static int peer_flag_modify(struct peer *peer, u_int32_t flag, int set) +{ + int found; + int size; + struct peer_group *group; + struct peer *tmp_peer; + struct listnode *node, *nnode; + struct peer_flag_action action; + + memset(&action, 0, sizeof(struct peer_flag_action)); + size = sizeof peer_flag_action_list / sizeof(struct peer_flag_action); + + found = peer_flag_action_set(peer_flag_action_list, size, &action, + flag); + + /* No flag action is found. */ + if (!found) + return BGP_ERR_INVALID_FLAG; + + /* When unset the peer-group member's flag we have to check + peer-group configuration. */ + if (!set && peer_group_active(peer)) + if (CHECK_FLAG(peer->group->conf->flags, flag)) { + if (flag == PEER_FLAG_SHUTDOWN) + return BGP_ERR_PEER_GROUP_SHUTDOWN; + } + + /* Flag conflict check. */ + if (set && CHECK_FLAG(peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH) + && CHECK_FLAG(peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY)) + return BGP_ERR_PEER_FLAG_CONFLICT; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (set && CHECK_FLAG(peer->flags, flag) == flag) + return 0; + if (!set && !CHECK_FLAG(peer->flags, flag)) + return 0; + } + + if (set) + SET_FLAG(peer->flags, flag); + else + UNSET_FLAG(peer->flags, flag); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (action.type == peer_change_reset) + peer_flag_modify_action(peer, flag); + + return 0; + } + + /* peer-group member updates. */ + group = peer->group; + + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) { + + if (set && CHECK_FLAG(tmp_peer->flags, flag) == flag) + continue; + + if (!set && !CHECK_FLAG(tmp_peer->flags, flag)) + continue; + + if (set) + SET_FLAG(tmp_peer->flags, flag); + else + UNSET_FLAG(tmp_peer->flags, flag); + + if (action.type == peer_change_reset) + peer_flag_modify_action(tmp_peer, flag); + } + return 0; +} + +int peer_flag_set(struct peer *peer, u_int32_t flag) +{ + return peer_flag_modify(peer, flag, 1); +} + +int peer_flag_unset(struct peer *peer, u_int32_t flag) +{ + return peer_flag_modify(peer, flag, 0); +} + +static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi, + u_int32_t flag, int set) +{ + int found; + int size; + struct listnode *node, *nnode; + struct peer_group *group; + struct peer_flag_action action; + struct peer *tmp_peer; + struct bgp *bgp; + int addpath_tx_used; + + memset(&action, 0, sizeof(struct peer_flag_action)); + size = sizeof peer_af_flag_action_list + / sizeof(struct peer_flag_action); + + found = peer_flag_action_set(peer_af_flag_action_list, size, &action, + flag); + + /* No flag action is found. */ + if (!found) + return BGP_ERR_INVALID_FLAG; + + /* Special check for reflector client. */ + if (flag & PEER_FLAG_REFLECTOR_CLIENT + && peer_sort(peer) != BGP_PEER_IBGP) + return BGP_ERR_NOT_INTERNAL_PEER; + + /* Special check for remove-private-AS. */ + if (flag & PEER_FLAG_REMOVE_PRIVATE_AS + && peer_sort(peer) == BGP_PEER_IBGP) + return BGP_ERR_REMOVE_PRIVATE_AS; + + /* as-override is not allowed for IBGP peers */ + if (flag & PEER_FLAG_AS_OVERRIDE && peer_sort(peer) == BGP_PEER_IBGP) + return BGP_ERR_AS_OVERRIDE; + + /* When current flag configuration is same as requested one. */ + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (set && CHECK_FLAG(peer->af_flags[afi][safi], flag) == flag) + return 0; + if (!set && !CHECK_FLAG(peer->af_flags[afi][safi], flag)) + return 0; + } + + if (set) + SET_FLAG(peer->af_flags[afi][safi], flag); + else + UNSET_FLAG(peer->af_flags[afi][safi], flag); + + /* Execute action when peer is established. */ + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) + && peer->status == Established) { + if (!set && flag == PEER_FLAG_SOFT_RECONFIG) + bgp_clear_adj_in(peer, afi, safi); + else { + if (flag == PEER_FLAG_REFLECTOR_CLIENT) + peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE; + else if (flag == PEER_FLAG_RSERVER_CLIENT) + peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE; + else if (flag == PEER_FLAG_ORF_PREFIX_SM) + peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE; + else if (flag == PEER_FLAG_ORF_PREFIX_RM) + peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE; + + peer_change_action(peer, afi, safi, action.type); + } + } + + /* Peer group member updates. */ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + group = peer->group; + + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) { + if (set + && CHECK_FLAG(tmp_peer->af_flags[afi][safi], flag) + == flag) + continue; + + if (!set + && !CHECK_FLAG(tmp_peer->af_flags[afi][safi], flag)) + continue; + + if (set) + SET_FLAG(tmp_peer->af_flags[afi][safi], flag); + else + UNSET_FLAG(tmp_peer->af_flags[afi][safi], flag); + + if (tmp_peer->status == Established) { + if (!set && flag == PEER_FLAG_SOFT_RECONFIG) + bgp_clear_adj_in(tmp_peer, afi, safi); + else { + if (flag == PEER_FLAG_REFLECTOR_CLIENT) + tmp_peer->last_reset = + PEER_DOWN_RR_CLIENT_CHANGE; + else if (flag + == PEER_FLAG_RSERVER_CLIENT) + tmp_peer->last_reset = + PEER_DOWN_RS_CLIENT_CHANGE; + else if (flag + == PEER_FLAG_ORF_PREFIX_SM) + tmp_peer->last_reset = + PEER_DOWN_CAPABILITY_CHANGE; + else if (flag + == PEER_FLAG_ORF_PREFIX_RM) + tmp_peer->last_reset = + PEER_DOWN_CAPABILITY_CHANGE; + + peer_change_action(tmp_peer, afi, safi, + action.type); + } + } + } + } + + /* Track if addpath TX is in use */ + if (flag & (PEER_FLAG_ADDPATH_TX_ALL_PATHS + | PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) { + bgp = peer->bgp; + addpath_tx_used = 0; + + if (set) { + addpath_tx_used = 1; + + if (flag & PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS) { + if (!bgp_flag_check( + bgp, BGP_FLAG_DETERMINISTIC_MED)) { + zlog_warn( + "%s: enabling bgp deterministic-med, this is required" + " for addpath-tx-bestpath-per-AS", + peer->host); + bgp_flag_set( + bgp, + BGP_FLAG_DETERMINISTIC_MED); + bgp_recalculate_all_bestpaths(bgp); + } + } + } else { + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, + tmp_peer)) { + if (CHECK_FLAG(tmp_peer->af_flags[afi][safi], + PEER_FLAG_ADDPATH_TX_ALL_PATHS) + || CHECK_FLAG( + tmp_peer->af_flags[afi][safi], + PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) { + addpath_tx_used = 1; + break; + } + } + } + + bgp->addpath_tx_used[afi][safi] = addpath_tx_used; + } + + return 0; +} + +int peer_af_flag_set(struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag) +{ + return peer_af_flag_modify(peer, afi, safi, flag, 1); +} + +int peer_af_flag_unset(struct peer *peer, afi_t afi, safi_t safi, + u_int32_t flag) +{ + return peer_af_flag_modify(peer, afi, safi, flag, 0); +} + + +int peer_tx_shutdown_message_set(struct peer *peer, const char *msg) +{ + XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message); + peer->tx_shutdown_message = + msg ? XSTRDUP(MTYPE_PEER_TX_SHUTDOWN_MSG, msg) : NULL; + return 0; +} + +int peer_tx_shutdown_message_unset(struct peer *peer) +{ + XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message); + return 0; +} + + +/* EBGP multihop configuration. */ +int peer_ebgp_multihop_set(struct peer *peer, int ttl) +{ + struct peer_group *group; + struct listnode *node, *nnode; + struct peer *peer1; + + if (peer->sort == BGP_PEER_IBGP || peer->conf_if) + return 0; + + /* see comment in peer_ttl_security_hops_set() */ + if (ttl != MAXTTL) { + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + group = peer->group; + if (group->conf->gtsm_hops != 0) + return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK; + + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, + peer1)) { + if (peer1->sort == BGP_PEER_IBGP) + continue; + + if (peer1->gtsm_hops != 0) + return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK; + } + } else { + if (peer->gtsm_hops != 0) + return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK; + } + } + + peer->ttl = ttl; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + bgp_session_reset(peer); + } + } else { + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (peer->sort == BGP_PEER_IBGP) + continue; + + peer->ttl = group->conf->ttl; + + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + bgp_session_reset(peer); + } + } + return 0; +} + +int peer_ebgp_multihop_unset(struct peer *peer) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + if (peer->sort == BGP_PEER_IBGP) + return 0; + + if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL) + return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK; + + if (peer_group_active(peer)) + peer->ttl = peer->group->conf->ttl; + else + peer->ttl = 1; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + bgp_session_reset(peer); + } else { + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (peer->sort == BGP_PEER_IBGP) + continue; + + peer->ttl = 1; + + if (peer->fd >= 0) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send( + peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + bgp_session_reset(peer); + } + } + } + return 0; +} + +/* Neighbor description. */ +int peer_description_set(struct peer *peer, const char *desc) +{ + if (peer->desc) + XFREE(MTYPE_PEER_DESC, peer->desc); + + peer->desc = XSTRDUP(MTYPE_PEER_DESC, desc); + + return 0; +} + +int peer_description_unset(struct peer *peer) +{ + if (peer->desc) + XFREE(MTYPE_PEER_DESC, peer->desc); + + peer->desc = NULL; + + return 0; +} + +/* Neighbor update-source. */ +int peer_update_source_if_set(struct peer *peer, const char *ifname) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + if (peer->update_if) { + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) + && strcmp(peer->update_if, ifname) == 0) + return 0; + + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); + peer->update_if = NULL; + } + + if (peer->update_source) { + sockunion_free(peer->update_source); + peer->update_source = NULL; + } + + peer->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, ifname); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); + return 0; + } + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (peer->update_if) { + if (strcmp(peer->update_if, ifname) == 0) + continue; + + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); + peer->update_if = NULL; + } + + if (peer->update_source) { + sockunion_free(peer->update_source); + peer->update_source = NULL; + } + + peer->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, ifname); + + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); + } + return 0; +} + +int peer_update_source_addr_set(struct peer *peer, const union sockunion *su) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + if (peer->update_source) { + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) + && sockunion_cmp(peer->update_source, su) == 0) + return 0; + sockunion_free(peer->update_source); + peer->update_source = NULL; + } + + if (peer->update_if) { + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); + peer->update_if = NULL; + } + + peer->update_source = sockunion_dup(su); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); + return 0; + } + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (peer->update_source) { + if (sockunion_cmp(peer->update_source, su) == 0) + continue; + sockunion_free(peer->update_source); + peer->update_source = NULL; + } + + if (peer->update_if) { + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); + peer->update_if = NULL; + } + + peer->update_source = sockunion_dup(su); + + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); + } + return 0; +} + +int peer_update_source_unset(struct peer *peer) +{ + union sockunion *su; + struct peer_group *group; + struct listnode *node, *nnode; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) && !peer->update_source + && !peer->update_if) + return 0; + + if (peer->update_source) { + sockunion_free(peer->update_source); + peer->update_source = NULL; + } + if (peer->update_if) { + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); + peer->update_if = NULL; + } + + if (peer_group_active(peer)) { + group = peer->group; + + if (group->conf->update_source) { + su = sockunion_dup(group->conf->update_source); + peer->update_source = su; + } else if (group->conf->update_if) + peer->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, + group->conf->update_if); + } + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); + return 0; + } + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (!peer->update_source && !peer->update_if) + continue; + + if (peer->update_source) { + sockunion_free(peer->update_source); + peer->update_source = NULL; + } + + if (peer->update_if) { + XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); + peer->update_if = NULL; + } + + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); + } + return 0; +} + +int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi, + const char *rmap) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE) + || (rmap && !peer->default_rmap[afi][safi].name) + || (rmap + && strcmp(rmap, peer->default_rmap[afi][safi].name) != 0)) { + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_DEFAULT_ORIGINATE); + + if (rmap) { + if (peer->default_rmap[afi][safi].name) + XFREE(MTYPE_ROUTE_MAP_NAME, + peer->default_rmap[afi][safi].name); + peer->default_rmap[afi][safi].name = + XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); + peer->default_rmap[afi][safi].map = + route_map_lookup_by_name(rmap); + } + } + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (peer->status == Established && peer->afc_nego[afi][safi]) { + update_group_adjust_peer(peer_af_find(peer, afi, safi)); + bgp_default_originate(peer, afi, safi, 0); + bgp_announce_route(peer, afi, safi); + } + return 0; + } + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_DEFAULT_ORIGINATE); + + if (rmap) { + if (peer->default_rmap[afi][safi].name) + XFREE(MTYPE_ROUTE_MAP_NAME, + peer->default_rmap[afi][safi].name); + peer->default_rmap[afi][safi].name = + XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); + peer->default_rmap[afi][safi].map = + route_map_lookup_by_name(rmap); + } + + if (peer->status == Established && peer->afc_nego[afi][safi]) { + update_group_adjust_peer(peer_af_find(peer, afi, safi)); + bgp_default_originate(peer, afi, safi, 0); + bgp_announce_route(peer, afi, safi); + } + } + return 0; +} + +int peer_default_originate_unset(struct peer *peer, afi_t afi, safi_t safi) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_DEFAULT_ORIGINATE)) { + UNSET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_DEFAULT_ORIGINATE); + + if (peer->default_rmap[afi][safi].name) + XFREE(MTYPE_ROUTE_MAP_NAME, + peer->default_rmap[afi][safi].name); + peer->default_rmap[afi][safi].name = NULL; + peer->default_rmap[afi][safi].map = NULL; + } + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (peer->status == Established && peer->afc_nego[afi][safi]) { + update_group_adjust_peer(peer_af_find(peer, afi, safi)); + bgp_default_originate(peer, afi, safi, 1); + bgp_announce_route(peer, afi, safi); + } + return 0; + } + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + UNSET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_DEFAULT_ORIGINATE); + + if (peer->default_rmap[afi][safi].name) + XFREE(MTYPE_ROUTE_MAP_NAME, + peer->default_rmap[afi][safi].name); + peer->default_rmap[afi][safi].name = NULL; + peer->default_rmap[afi][safi].map = NULL; + + if (peer->status == Established && peer->afc_nego[afi][safi]) { + update_group_adjust_peer(peer_af_find(peer, afi, safi)); + bgp_default_originate(peer, afi, safi, 1); + bgp_announce_route(peer, afi, safi); + } + } + return 0; +} + +int peer_port_set(struct peer *peer, u_int16_t port) +{ + peer->port = port; + return 0; +} + +int peer_port_unset(struct peer *peer) +{ + peer->port = BGP_PORT_DEFAULT; + return 0; +} + +/* + * Helper function that is called after the name of the policy + * being used by a peer has changed (AF specific). Automatically + * initiates inbound or outbound processing as needed. + */ +static void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi, + int outbound) +{ + if (outbound) { + update_group_adjust_peer(peer_af_find(peer, afi, safi)); + if (peer->status == Established) + bgp_announce_route(peer, afi, safi); + } else { + if (peer->status != Established) + return; + + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_SOFT_RECONFIG)) + bgp_soft_reconfig_in(peer, afi, safi); + else if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV) + || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV)) + bgp_route_refresh_send(peer, afi, safi, 0, 0, 0); + } +} + + +/* neighbor weight. */ +int peer_weight_set(struct peer *peer, afi_t afi, safi_t safi, u_int16_t weight) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + if (peer->weight[afi][safi] != weight) { + peer->weight[afi][safi] = weight; + SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_WEIGHT); + peer_on_policy_change(peer, afi, safi, 0); + } + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return 0; + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (peer->weight[afi][safi] != weight) { + peer->weight[afi][safi] = weight; + SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_WEIGHT); + peer_on_policy_change(peer, afi, safi, 0); + } + } + return 0; +} + +int peer_weight_unset(struct peer *peer, afi_t afi, safi_t safi) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + /* not the peer-group itself but a peer in a peer-group */ + if (peer_group_active(peer)) { + group = peer->group; + + /* inherit weight from the peer-group */ + if (CHECK_FLAG(group->conf->af_flags[afi][safi], + PEER_FLAG_WEIGHT)) { + peer->weight[afi][safi] = + group->conf->weight[afi][safi]; + peer_af_flag_set(peer, afi, safi, PEER_FLAG_WEIGHT); + peer_on_policy_change(peer, afi, safi, 0); + } else { + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_WEIGHT)) { + peer->weight[afi][safi] = 0; + peer_af_flag_unset(peer, afi, safi, + PEER_FLAG_WEIGHT); + peer_on_policy_change(peer, afi, safi, 0); + } + } + } + + else { + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_WEIGHT)) { + peer->weight[afi][safi] = 0; + peer_af_flag_unset(peer, afi, safi, PEER_FLAG_WEIGHT); + peer_on_policy_change(peer, afi, safi, 0); + } + + /* peer-group member updates. */ + group = peer->group; + + if (group) { + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, + peer)) { + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_WEIGHT)) { + peer->weight[afi][safi] = 0; + peer_af_flag_unset(peer, afi, safi, + PEER_FLAG_WEIGHT); + peer_on_policy_change(peer, afi, safi, + 0); + } + } + } + } + return 0; +} + +int peer_timers_set(struct peer *peer, u_int32_t keepalive, u_int32_t holdtime) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + /* keepalive value check. */ + if (keepalive > 65535) + return BGP_ERR_INVALID_VALUE; + + /* Holdtime value check. */ + if (holdtime > 65535) + return BGP_ERR_INVALID_VALUE; + + /* Holdtime value must be either 0 or greater than 3. */ + if (holdtime < 3 && holdtime != 0) + return BGP_ERR_INVALID_VALUE; + + /* Set value to the configuration. */ + SET_FLAG(peer->config, PEER_CONFIG_TIMER); + peer->holdtime = holdtime; + peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return 0; + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + SET_FLAG(peer->config, PEER_CONFIG_TIMER); + peer->holdtime = group->conf->holdtime; + peer->keepalive = group->conf->keepalive; + } + return 0; +} + +int peer_timers_unset(struct peer *peer) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + /* Clear configuration. */ + UNSET_FLAG(peer->config, PEER_CONFIG_TIMER); + peer->keepalive = 0; + peer->holdtime = 0; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return 0; + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + UNSET_FLAG(peer->config, PEER_CONFIG_TIMER); + peer->holdtime = 0; + peer->keepalive = 0; + } + + return 0; +} + +int peer_timers_connect_set(struct peer *peer, u_int32_t connect) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + if (connect > 65535) + return BGP_ERR_INVALID_VALUE; + + /* Set value to the configuration. */ + SET_FLAG(peer->config, PEER_CONFIG_CONNECT); + peer->connect = connect; + + /* Set value to timer setting. */ + peer->v_connect = connect; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return 0; + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + SET_FLAG(peer->config, PEER_CONFIG_CONNECT); + peer->connect = connect; + peer->v_connect = connect; + } + return 0; +} + +int peer_timers_connect_unset(struct peer *peer) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + /* Clear configuration. */ + UNSET_FLAG(peer->config, PEER_CONFIG_CONNECT); + peer->connect = 0; + + /* Set timer setting to default value. */ + peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return 0; + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + UNSET_FLAG(peer->config, PEER_CONFIG_CONNECT); + peer->connect = 0; + peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; + } + return 0; +} + +int peer_advertise_interval_set(struct peer *peer, u_int32_t routeadv) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + if (routeadv > 600) + return BGP_ERR_INVALID_VALUE; + + SET_FLAG(peer->config, PEER_CONFIG_ROUTEADV); + peer->routeadv = routeadv; + peer->v_routeadv = routeadv; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + update_group_adjust_peer_afs(peer); + if (peer->status == Established) + bgp_announce_route_all(peer); + return 0; + } + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + SET_FLAG(peer->config, PEER_CONFIG_ROUTEADV); + peer->routeadv = routeadv; + peer->v_routeadv = routeadv; + update_group_adjust_peer_afs(peer); + if (peer->status == Established) + bgp_announce_route_all(peer); + } + + return 0; +} + +int peer_advertise_interval_unset(struct peer *peer) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + UNSET_FLAG(peer->config, PEER_CONFIG_ROUTEADV); + peer->routeadv = 0; + + if (peer->sort == BGP_PEER_IBGP) + peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; + else + peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + update_group_adjust_peer_afs(peer); + if (peer->status == Established) + bgp_announce_route_all(peer); + return 0; + } + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + UNSET_FLAG(peer->config, PEER_CONFIG_ROUTEADV); + peer->routeadv = 0; + + if (peer->sort == BGP_PEER_IBGP) + peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; + else + peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; + + update_group_adjust_peer_afs(peer); + if (peer->status == Established) + bgp_announce_route_all(peer); + } + + return 0; +} + +/* neighbor interface */ +void peer_interface_set(struct peer *peer, const char *str) +{ + if (peer->ifname) + XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname); + peer->ifname = XSTRDUP(MTYPE_BGP_PEER_IFNAME, str); +} + +void peer_interface_unset(struct peer *peer) +{ + if (peer->ifname) + XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname); + peer->ifname = NULL; +} + +/* Allow-as in. */ +int peer_allowas_in_set(struct peer *peer, afi_t afi, safi_t safi, + int allow_num, int origin) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + if (origin) { + if (peer->allowas_in[afi][safi] + || CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ALLOWAS_IN) + || !CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ALLOWAS_IN_ORIGIN)) { + peer->allowas_in[afi][safi] = 0; + peer_af_flag_unset(peer, afi, safi, + PEER_FLAG_ALLOWAS_IN); + peer_af_flag_set(peer, afi, safi, + PEER_FLAG_ALLOWAS_IN_ORIGIN); + peer_on_policy_change(peer, afi, safi, 0); + } + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return 0; + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (peer->allowas_in[afi][safi] + || CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ALLOWAS_IN) + || !CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ALLOWAS_IN_ORIGIN)) { + peer->allowas_in[afi][safi] = 0; + peer_af_flag_unset(peer, afi, safi, + PEER_FLAG_ALLOWAS_IN); + peer_af_flag_set(peer, afi, safi, + PEER_FLAG_ALLOWAS_IN_ORIGIN); + peer_on_policy_change(peer, afi, safi, 0); + } + } + } else { + if (allow_num < 1 || allow_num > 10) + return BGP_ERR_INVALID_VALUE; + + if (peer->allowas_in[afi][safi] != allow_num + || CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ALLOWAS_IN_ORIGIN)) { + peer->allowas_in[afi][safi] = allow_num; + peer_af_flag_set(peer, afi, safi, PEER_FLAG_ALLOWAS_IN); + peer_af_flag_unset(peer, afi, safi, + PEER_FLAG_ALLOWAS_IN_ORIGIN); + peer_on_policy_change(peer, afi, safi, 0); + } + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return 0; + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + if (peer->allowas_in[afi][safi] != allow_num + || CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ALLOWAS_IN_ORIGIN)) { + peer->allowas_in[afi][safi] = allow_num; + peer_af_flag_set(peer, afi, safi, + PEER_FLAG_ALLOWAS_IN); + peer_af_flag_unset(peer, afi, safi, + PEER_FLAG_ALLOWAS_IN_ORIGIN); + peer_on_policy_change(peer, afi, safi, 0); + } + } + } + + return 0; +} + +int peer_allowas_in_unset(struct peer *peer, afi_t afi, safi_t safi) +{ + struct peer_group *group; + struct peer *tmp_peer; + struct listnode *node, *nnode; + + /* If this is a peer-group we must first clear the flags for all of the + * peer-group members + */ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) { + if (CHECK_FLAG(tmp_peer->af_flags[afi][safi], + PEER_FLAG_ALLOWAS_IN) + || CHECK_FLAG(tmp_peer->af_flags[afi][safi], + PEER_FLAG_ALLOWAS_IN_ORIGIN)) { + tmp_peer->allowas_in[afi][safi] = 0; + peer_af_flag_unset(tmp_peer, afi, safi, + PEER_FLAG_ALLOWAS_IN); + peer_af_flag_unset(tmp_peer, afi, safi, + PEER_FLAG_ALLOWAS_IN_ORIGIN); + peer_on_policy_change(tmp_peer, afi, safi, 0); + } + } + } + + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN) + || CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_ALLOWAS_IN_ORIGIN)) { + peer->allowas_in[afi][safi] = 0; + peer_af_flag_unset(peer, afi, safi, PEER_FLAG_ALLOWAS_IN); + peer_af_flag_unset(peer, afi, safi, + PEER_FLAG_ALLOWAS_IN_ORIGIN); + peer_on_policy_change(peer, afi, safi, 0); + } + + return 0; +} + +int peer_local_as_set(struct peer *peer, as_t as, int no_prepend, + int replace_as) +{ + struct bgp *bgp = peer->bgp; + struct peer_group *group; + struct listnode *node, *nnode; + + if (peer_sort(peer) != BGP_PEER_EBGP + && peer_sort(peer) != BGP_PEER_INTERNAL) + return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP; + + if (bgp->as == as) + return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS; + + if (peer->as == as) + return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS; + + if (peer->change_local_as == as + && ((CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) + && no_prepend) + || (!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) + && !no_prepend)) + && ((CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) + && replace_as) + || (!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) + && !replace_as))) + return 0; + + peer->change_local_as = as; + if (no_prepend) + SET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); + else + UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); + + if (replace_as) + SET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); + else + UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); + return 0; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + peer->change_local_as = as; + if (no_prepend) + SET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); + else + UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); + + if (replace_as) + SET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); + else + UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); + + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + BGP_EVENT_ADD(peer, BGP_Stop); + } + + return 0; +} + +int peer_local_as_unset(struct peer *peer) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + if (!peer->change_local_as) + return 0; + + peer->change_local_as = 0; + UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); + UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + BGP_EVENT_ADD(peer, BGP_Stop); + + return 0; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + peer->change_local_as = 0; + UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND); + UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS); + + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE; + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + } else + bgp_session_reset(peer); + } + return 0; +} + +/* Set password for authenticating with the peer. */ +int peer_password_set(struct peer *peer, const char *password) +{ + struct listnode *nn, *nnode; + int len = password ? strlen(password) : 0; + int ret = BGP_SUCCESS; + + if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN)) + return BGP_ERR_INVALID_VALUE; + + if (peer->password && strcmp(peer->password, password) == 0 + && !CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return 0; + + if (peer->password) + XFREE(MTYPE_PEER_PASSWORD, peer->password); + + peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + bgp_session_reset(peer); + + if (BGP_PEER_SU_UNSPEC(peer)) + return BGP_SUCCESS; + + return (bgp_md5_set(peer) >= 0) ? BGP_SUCCESS + : BGP_ERR_TCPSIG_FAILED; + } + + for (ALL_LIST_ELEMENTS(peer->group->peer, nn, nnode, peer)) { + if (peer->password && strcmp(peer->password, password) == 0) + continue; + + if (peer->password) + XFREE(MTYPE_PEER_PASSWORD, peer->password); + + peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password); + + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + bgp_session_reset(peer); + + if (!BGP_PEER_SU_UNSPEC(peer)) { + if (bgp_md5_set(peer) < 0) + ret = BGP_ERR_TCPSIG_FAILED; + } + } + + return ret; +} + +int peer_password_unset(struct peer *peer) +{ + struct listnode *nn, *nnode; + + if (!peer->password && !CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return 0; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + bgp_session_reset(peer); + + if (peer->password) + XFREE(MTYPE_PEER_PASSWORD, peer->password); + + peer->password = NULL; + + if (!BGP_PEER_SU_UNSPEC(peer)) + bgp_md5_unset(peer); + + return 0; + } + + XFREE(MTYPE_PEER_PASSWORD, peer->password); + peer->password = NULL; + + for (ALL_LIST_ELEMENTS(peer->group->peer, nn, nnode, peer)) { + if (!peer->password) + continue; + + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + bgp_session_reset(peer); + + XFREE(MTYPE_PEER_PASSWORD, peer->password); + peer->password = NULL; + + if (!BGP_PEER_SU_UNSPEC(peer)) + bgp_md5_unset(peer); + } + + return 0; +} /* Set distribute list to the peer. */ -int -peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct, - const char *name) +int peer_distribute_set(struct peer *peer, afi_t afi, safi_t safi, int direct, + const char *name) +{ + struct bgp_filter *filter; + struct peer_group *group; + struct listnode *node, *nnode; + + if (direct != FILTER_IN && direct != FILTER_OUT) + return BGP_ERR_INVALID_VALUE; + + filter = &peer->filter[afi][safi]; + + if (filter->plist[direct].name) + return BGP_ERR_PEER_FILTER_CONFLICT; + + if (filter->dlist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name); + filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); + filter->dlist[direct].alist = access_list_lookup(afi, name); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + return 0; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + filter = &peer->filter[afi][safi]; + + if (filter->dlist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, + filter->dlist[direct].name); + filter->dlist[direct].name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, name); + filter->dlist[direct].alist = access_list_lookup(afi, name); + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + } + + return 0; +} + +int peer_distribute_unset(struct peer *peer, afi_t afi, safi_t safi, int direct) +{ + struct bgp_filter *filter; + struct bgp_filter *gfilter; + struct peer_group *group; + struct listnode *node, *nnode; + + if (direct != FILTER_IN && direct != FILTER_OUT) + return BGP_ERR_INVALID_VALUE; + + filter = &peer->filter[afi][safi]; + + /* apply peer-group filter */ + if (peer_group_active(peer)) { + gfilter = &peer->group->conf->filter[afi][safi]; + + if (gfilter->dlist[direct].name) { + if (filter->dlist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, + filter->dlist[direct].name); + filter->dlist[direct].name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, + gfilter->dlist[direct].name); + filter->dlist[direct].alist = + gfilter->dlist[direct].alist; + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + return 0; + } + } + + if (filter->dlist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name); + filter->dlist[direct].name = NULL; + filter->dlist[direct].alist = NULL; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + return 0; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + filter = &peer->filter[afi][safi]; + + if (filter->dlist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, + filter->dlist[direct].name); + filter->dlist[direct].name = NULL; + filter->dlist[direct].alist = NULL; + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + } + + return 0; +} + +/* Update distribute list. */ +static void peer_distribute_update(struct access_list *access) +{ + afi_t afi; + safi_t safi; + int direct; + struct listnode *mnode, *mnnode; + struct listnode *node, *nnode; + struct bgp *bgp; + struct peer *peer; + struct peer_group *group; + struct bgp_filter *filter; + + for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) { + if (access->name) + update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST, + access->name, 0, 0); + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; + safi++) { + filter = &peer->filter[afi][safi]; + + for (direct = FILTER_IN; + direct < FILTER_MAX; direct++) { + if (filter->dlist[direct].name) + filter->dlist[direct] + .alist = access_list_lookup( + afi, + filter->dlist[direct] + .name); + else + filter->dlist[direct] + .alist = NULL; + } + } + } + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) { + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; + safi++) { + filter = + &group->conf->filter[afi][safi]; + + for (direct = FILTER_IN; + direct < FILTER_MAX; direct++) { + if (filter->dlist[direct].name) + filter->dlist[direct] + .alist = access_list_lookup( + afi, + filter->dlist[direct] + .name); + else + filter->dlist[direct] + .alist = NULL; + } + } + } +#if ENABLE_BGP_VNC + vnc_prefix_list_update(bgp); +#endif + } +} + +/* Set prefix list to the peer. */ +int peer_prefix_list_set(struct peer *peer, afi_t afi, safi_t safi, int direct, + const char *name) +{ + struct bgp_filter *filter; + struct peer_group *group; + struct listnode *node, *nnode; + + if (direct != FILTER_IN && direct != FILTER_OUT) + return BGP_ERR_INVALID_VALUE; + + filter = &peer->filter[afi][safi]; + + if (filter->dlist[direct].name) + return BGP_ERR_PEER_FILTER_CONFLICT; + + if (filter->plist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name); + filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); + filter->plist[direct].plist = prefix_list_lookup(afi, name); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + return 0; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + filter = &peer->filter[afi][safi]; + + if (filter->plist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, + filter->plist[direct].name); + filter->plist[direct].name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, name); + filter->plist[direct].plist = prefix_list_lookup(afi, name); + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + } + return 0; +} + +int peer_prefix_list_unset(struct peer *peer, afi_t afi, safi_t safi, + int direct) +{ + struct bgp_filter *filter; + struct bgp_filter *gfilter; + struct peer_group *group; + struct listnode *node, *nnode; + + if (direct != FILTER_IN && direct != FILTER_OUT) + return BGP_ERR_INVALID_VALUE; + + filter = &peer->filter[afi][safi]; + + /* apply peer-group filter */ + if (peer_group_active(peer)) { + gfilter = &peer->group->conf->filter[afi][safi]; + + if (gfilter->plist[direct].name) { + if (filter->plist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, + filter->plist[direct].name); + filter->plist[direct].name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, + gfilter->plist[direct].name); + filter->plist[direct].plist = + gfilter->plist[direct].plist; + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + return 0; + } + } + + if (filter->plist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name); + filter->plist[direct].name = NULL; + filter->plist[direct].plist = NULL; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + return 0; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + filter = &peer->filter[afi][safi]; + + if (filter->plist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, + filter->plist[direct].name); + filter->plist[direct].name = NULL; + filter->plist[direct].plist = NULL; + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + } + + return 0; +} + +/* Update prefix-list list. */ +static void peer_prefix_list_update(struct prefix_list *plist) +{ + struct listnode *mnode, *mnnode; + struct listnode *node, *nnode; + struct bgp *bgp; + struct peer *peer; + struct peer_group *group; + struct bgp_filter *filter; + afi_t afi; + safi_t safi; + int direct; + + for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) { + + /* + * Update the prefix-list on update groups. + */ + update_group_policy_update( + bgp, BGP_POLICY_PREFIX_LIST, + plist ? prefix_list_name(plist) : NULL, 0, 0); + + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; + safi++) { + filter = &peer->filter[afi][safi]; + + for (direct = FILTER_IN; + direct < FILTER_MAX; direct++) { + if (filter->plist[direct].name) + filter->plist[direct] + .plist = prefix_list_lookup( + afi, + filter->plist[direct] + .name); + else + filter->plist[direct] + .plist = NULL; + } + } + } + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) { + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; + safi++) { + filter = + &group->conf->filter[afi][safi]; + + for (direct = FILTER_IN; + direct < FILTER_MAX; direct++) { + if (filter->plist[direct].name) + filter->plist[direct] + .plist = prefix_list_lookup( + afi, + filter->plist[direct] + .name); + else + filter->plist[direct] + .plist = NULL; + } + } + } + } +} + +int peer_aslist_set(struct peer *peer, afi_t afi, safi_t safi, int direct, + const char *name) +{ + struct bgp_filter *filter; + struct peer_group *group; + struct listnode *node, *nnode; + + if (direct != FILTER_IN && direct != FILTER_OUT) + return BGP_ERR_INVALID_VALUE; + + filter = &peer->filter[afi][safi]; + + if (filter->aslist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name); + filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); + filter->aslist[direct].aslist = as_list_lookup(name); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + return 0; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + filter = &peer->filter[afi][safi]; + + if (filter->aslist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, + filter->aslist[direct].name); + filter->aslist[direct].name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, name); + filter->aslist[direct].aslist = as_list_lookup(name); + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + } + return 0; +} + +int peer_aslist_unset(struct peer *peer, afi_t afi, safi_t safi, int direct) +{ + struct bgp_filter *filter; + struct bgp_filter *gfilter; + struct peer_group *group; + struct listnode *node, *nnode; + + if (direct != FILTER_IN && direct != FILTER_OUT) + return BGP_ERR_INVALID_VALUE; + + filter = &peer->filter[afi][safi]; + + /* apply peer-group filter */ + if (peer_group_active(peer)) { + gfilter = &peer->group->conf->filter[afi][safi]; + + if (gfilter->aslist[direct].name) { + if (filter->aslist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, + filter->aslist[direct].name); + filter->aslist[direct].name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, + gfilter->aslist[direct].name); + filter->aslist[direct].aslist = + gfilter->aslist[direct].aslist; + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + return 0; + } + } + + if (filter->aslist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name); + filter->aslist[direct].name = NULL; + filter->aslist[direct].aslist = NULL; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + return 0; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + filter = &peer->filter[afi][safi]; + + if (filter->aslist[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, + filter->aslist[direct].name); + filter->aslist[direct].name = NULL; + filter->aslist[direct].aslist = NULL; + peer_on_policy_change(peer, afi, safi, + (direct == FILTER_OUT) ? 1 : 0); + } + + return 0; +} + +static void peer_aslist_update(const char *aslist_name) +{ + afi_t afi; + safi_t safi; + int direct; + struct listnode *mnode, *mnnode; + struct listnode *node, *nnode; + struct bgp *bgp; + struct peer *peer; + struct peer_group *group; + struct bgp_filter *filter; + + for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) { + update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST, + aslist_name, 0, 0); + + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; + safi++) { + filter = &peer->filter[afi][safi]; + + for (direct = FILTER_IN; + direct < FILTER_MAX; direct++) { + if (filter->aslist[direct].name) + filter->aslist[direct] + .aslist = as_list_lookup( + filter->aslist[direct] + .name); + else + filter->aslist[direct] + .aslist = NULL; + } + } + } + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) { + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; + safi++) { + filter = + &group->conf->filter[afi][safi]; + + for (direct = FILTER_IN; + direct < FILTER_MAX; direct++) { + if (filter->aslist[direct].name) + filter->aslist[direct] + .aslist = as_list_lookup( + filter->aslist[direct] + .name); + else + filter->aslist[direct] + .aslist = NULL; + } + } + } + } +} + +static void peer_aslist_add(char *aslist_name) +{ + peer_aslist_update(aslist_name); + route_map_notify_dependencies((char *)aslist_name, + RMAP_EVENT_ASLIST_ADDED); +} + +static void peer_aslist_del(const char *aslist_name) +{ + peer_aslist_update(aslist_name); + route_map_notify_dependencies(aslist_name, RMAP_EVENT_ASLIST_DELETED); +} + + +int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int direct, + const char *name) +{ + struct bgp_filter *filter; + struct peer_group *group; + struct listnode *node, *nnode; + + if (direct != RMAP_IN && direct != RMAP_OUT) + return BGP_ERR_INVALID_VALUE; + + filter = &peer->filter[afi][safi]; + + if (filter->map[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name); + + filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); + filter->map[direct].map = route_map_lookup_by_name(name); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_on_policy_change(peer, afi, safi, + (direct == RMAP_OUT) ? 1 : 0); + return 0; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + filter = &peer->filter[afi][safi]; + + if (filter->map[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name); + filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); + filter->map[direct].map = route_map_lookup_by_name(name); + peer_on_policy_change(peer, afi, safi, + (direct == RMAP_OUT) ? 1 : 0); + } + return 0; +} + +/* Unset route-map from the peer. */ +int peer_route_map_unset(struct peer *peer, afi_t afi, safi_t safi, int direct) +{ + struct bgp_filter *filter; + struct bgp_filter *gfilter; + struct peer_group *group; + struct listnode *node, *nnode; + + if (direct != RMAP_IN && direct != RMAP_OUT) + return BGP_ERR_INVALID_VALUE; + + filter = &peer->filter[afi][safi]; + + /* apply peer-group filter */ + if (peer_group_active(peer)) { + gfilter = &peer->group->conf->filter[afi][safi]; + + if (gfilter->map[direct].name) { + if (filter->map[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, + filter->map[direct].name); + filter->map[direct].name = + XSTRDUP(MTYPE_BGP_FILTER_NAME, + gfilter->map[direct].name); + filter->map[direct].map = gfilter->map[direct].map; + peer_on_policy_change(peer, afi, safi, + (direct == RMAP_OUT) ? 1 : 0); + return 0; + } + } + + if (filter->map[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name); + filter->map[direct].name = NULL; + filter->map[direct].map = NULL; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_on_policy_change(peer, afi, safi, + (direct == RMAP_OUT) ? 1 : 0); + return 0; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + filter = &peer->filter[afi][safi]; + + if (filter->map[direct].name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name); + filter->map[direct].name = NULL; + filter->map[direct].map = NULL; + peer_on_policy_change(peer, afi, safi, + (direct == RMAP_OUT) ? 1 : 0); + } + return 0; +} + +/* Set unsuppress-map to the peer. */ +int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi, + const char *name) +{ + struct bgp_filter *filter; + struct peer_group *group; + struct listnode *node, *nnode; + + filter = &peer->filter[afi][safi]; + + if (filter->usmap.name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); + + filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); + filter->usmap.map = route_map_lookup_by_name(name); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_on_policy_change(peer, afi, safi, 1); + return 0; + } + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + filter = &peer->filter[afi][safi]; + + if (filter->usmap.name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); + filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); + filter->usmap.map = route_map_lookup_by_name(name); + peer_on_policy_change(peer, afi, safi, 1); + } + return 0; +} + +/* Unset route-map from the peer. */ +int peer_unsuppress_map_unset(struct peer *peer, afi_t afi, safi_t safi) { - struct bgp_filter *filter; - struct peer_group *group; - struct listnode *node, *nnode; + struct bgp_filter *filter; + struct peer_group *group; + struct listnode *node, *nnode; + + filter = &peer->filter[afi][safi]; - if (direct != FILTER_IN && direct != FILTER_OUT) - return BGP_ERR_INVALID_VALUE; + if (filter->usmap.name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); + filter->usmap.name = NULL; + filter->usmap.map = NULL; - filter = &peer->filter[afi][safi]; + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer_on_policy_change(peer, afi, safi, 1); + return 0; + } - if (filter->plist[direct].name) - return BGP_ERR_PEER_FILTER_CONFLICT; + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + filter = &peer->filter[afi][safi]; - if (filter->dlist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name); - filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->dlist[direct].alist = access_list_lookup (afi, name); + if (filter->usmap.name) + XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); + filter->usmap.name = NULL; + filter->usmap.map = NULL; + peer_on_policy_change(peer, afi, safi, 1); + } + return 0; +} - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - return 0; - } +int peer_maximum_prefix_set(struct peer *peer, afi_t afi, safi_t safi, + u_int32_t max, u_char threshold, int warning, + u_int16_t restart) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); + peer->pmax[afi][safi] = max; + peer->pmax_threshold[afi][safi] = threshold; + peer->pmax_restart[afi][safi] = restart; + if (warning) + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING); + else + UNSET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING); + + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX); + peer->pmax[afi][safi] = max; + peer->pmax_threshold[afi][safi] = threshold; + peer->pmax_restart[afi][safi] = restart; + if (warning) + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING); + else + UNSET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING); + + if ((peer->status == Established) + && (peer->afc[afi][safi])) + bgp_maximum_prefix_overflow(peer, afi, safi, 1); + } + } else { + if ((peer->status == Established) && (peer->afc[afi][safi])) + bgp_maximum_prefix_overflow(peer, afi, safi, 1); + } - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - filter = &peer->filter[afi][safi]; + return 0; +} - if (filter->dlist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name); - filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->dlist[direct].alist = access_list_lookup (afi, name); - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - } +int peer_maximum_prefix_unset(struct peer *peer, afi_t afi, safi_t safi) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + /* apply peer-group config */ + if (peer_group_active(peer)) { + if (CHECK_FLAG(peer->group->conf->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX)) + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX); + else + UNSET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX); + + if (CHECK_FLAG(peer->group->conf->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING)) + SET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING); + else + UNSET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING); + + peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi]; + peer->pmax_threshold[afi][safi] = + peer->group->conf->pmax_threshold[afi][safi]; + peer->pmax_restart[afi][safi] = + peer->group->conf->pmax_restart[afi][safi]; + return 0; + } - return 0; + UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); + UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); + peer->pmax[afi][safi] = 0; + peer->pmax_threshold[afi][safi] = 0; + peer->pmax_restart[afi][safi] = 0; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) + return 0; + + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); + UNSET_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING); + peer->pmax[afi][safi] = 0; + peer->pmax_threshold[afi][safi] = 0; + peer->pmax_restart[afi][safi] = 0; + } + return 0; } -int -peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct) +int is_ebgp_multihop_configured(struct peer *peer) { - struct bgp_filter *filter; - struct bgp_filter *gfilter; - struct peer_group *group; - struct listnode *node, *nnode; + struct peer_group *group; + struct listnode *node, *nnode; + struct peer *peer1; - if (direct != FILTER_IN && direct != FILTER_OUT) - return BGP_ERR_INVALID_VALUE; + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + group = peer->group; + if ((peer_sort(peer) != BGP_PEER_IBGP) + && (group->conf->ttl != 1)) + return 1; - filter = &peer->filter[afi][safi]; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer1)) { + if ((peer_sort(peer1) != BGP_PEER_IBGP) + && (peer1->ttl != 1)) + return 1; + } + } else { + if ((peer_sort(peer) != BGP_PEER_IBGP) && (peer->ttl != 1)) + return 1; + } + return 0; +} - /* apply peer-group filter */ - if (peer_group_active(peer)) - { - gfilter = &peer->group->conf->filter[afi][safi]; +/* Set # of hops between us and BGP peer. */ +int peer_ttl_security_hops_set(struct peer *peer, int gtsm_hops) +{ + struct peer_group *group; + struct listnode *node, *nnode; + int ret; + + zlog_debug("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", + gtsm_hops, peer->host); + + /* We cannot configure ttl-security hops when ebgp-multihop is already + set. For non peer-groups, the check is simple. For peer-groups, + it's + slightly messy, because we need to check both the peer-group + structure + and all peer-group members for any trace of ebgp-multihop + configuration + before actually applying the ttl-security rules. Cisco really made a + mess of this configuration parameter, and OpenBGPD got it right. + */ + + if ((peer->gtsm_hops == 0) && (peer->sort != BGP_PEER_IBGP)) { + if (is_ebgp_multihop_configured(peer)) + return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer->gtsm_hops = gtsm_hops; + + /* Calling ebgp multihop also resets the session. + * On restart, NHT will get setup correctly as will the + * min & max ttls on the socket. The return value is + * irrelevant. + */ + ret = peer_ebgp_multihop_set(peer, MAXTTL); + + if (ret != 0) + return ret; + } else { + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, + peer)) { + peer->gtsm_hops = group->conf->gtsm_hops; + + /* Calling ebgp multihop also resets the + * session. + * On restart, NHT will get setup correctly as + * will the + * min & max ttls on the socket. The return + * value is + * irrelevant. + */ + peer_ebgp_multihop_set(peer, MAXTTL); + } + } + } else { + /* Post the first gtsm setup or if its ibgp, maxttl setting + * isn't + * necessary, just set the minttl. + */ + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + peer->gtsm_hops = gtsm_hops; + + if (peer->fd >= 0) + sockopt_minttl(peer->su.sa.sa_family, peer->fd, + MAXTTL + 1 - gtsm_hops); + if ((peer->status < Established) && peer->doppelganger + && (peer->doppelganger->fd >= 0)) + sockopt_minttl(peer->su.sa.sa_family, + peer->doppelganger->fd, + MAXTTL + 1 - gtsm_hops); + } else { + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, + peer)) { + peer->gtsm_hops = group->conf->gtsm_hops; + + /* Change setting of existing peer + * established then change value (may break + * connectivity) + * not established yet (teardown session and + * restart) + * no session then do nothing (will get + * handled by next connection) + */ + if (peer->fd >= 0 && peer->gtsm_hops != 0) + sockopt_minttl( + peer->su.sa.sa_family, peer->fd, + MAXTTL + 1 - peer->gtsm_hops); + if ((peer->status < Established) + && peer->doppelganger + && (peer->doppelganger->fd >= 0)) + sockopt_minttl(peer->su.sa.sa_family, + peer->doppelganger->fd, + MAXTTL + 1 - gtsm_hops); + } + } + } - if (gfilter->dlist[direct].name) - { - if (filter->dlist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name); - filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->dlist[direct].name); - filter->dlist[direct].alist = gfilter->dlist[direct].alist; - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - return 0; - } - } - - if (filter->dlist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name); - filter->dlist[direct].name = NULL; - filter->dlist[direct].alist = NULL; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - return 0; - } - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - filter = &peer->filter[afi][safi]; - - if (filter->dlist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name); - filter->dlist[direct].name = NULL; - filter->dlist[direct].alist = NULL; - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - } - - return 0; + return 0; } -/* Update distribute list. */ -static void -peer_distribute_update (struct access_list *access) -{ - afi_t afi; - safi_t safi; - int direct; - struct listnode *mnode, *mnnode; - struct listnode *node, *nnode; - struct bgp *bgp; - struct peer *peer; - struct peer_group *group; - struct bgp_filter *filter; - - for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) - { - if (access->name) - update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST, access->name, - 0, 0); - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - filter = &peer->filter[afi][safi]; +int peer_ttl_security_hops_unset(struct peer *peer) +{ + struct peer_group *group; + struct listnode *node, *nnode; + int ret = 0; + + zlog_debug("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", + peer->host); + + /* if a peer-group member, then reset to peer-group default rather than + * 0 */ + if (peer_group_active(peer)) + peer->gtsm_hops = peer->group->conf->gtsm_hops; + else + peer->gtsm_hops = 0; + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + /* Invoking ebgp_multihop_set will set the TTL back to the + * original + * value as well as restting the NHT and such. The session is + * reset. + */ + if (peer->sort == BGP_PEER_EBGP) + ret = peer_ebgp_multihop_unset(peer); + else { + if (peer->fd >= 0) + sockopt_minttl(peer->su.sa.sa_family, peer->fd, + 0); + + if ((peer->status < Established) && peer->doppelganger + && (peer->doppelganger->fd >= 0)) + sockopt_minttl(peer->su.sa.sa_family, + peer->doppelganger->fd, 0); + } + } else { + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { + peer->gtsm_hops = 0; + if (peer->sort == BGP_PEER_EBGP) + ret = peer_ebgp_multihop_unset(peer); + else { + if (peer->fd >= 0) + sockopt_minttl(peer->su.sa.sa_family, + peer->fd, 0); + + if ((peer->status < Established) + && peer->doppelganger + && (peer->doppelganger->fd >= 0)) + sockopt_minttl(peer->su.sa.sa_family, + peer->doppelganger->fd, + 0); + } + } + } - for (direct = FILTER_IN; direct < FILTER_MAX; direct++) - { - if (filter->dlist[direct].name) - filter->dlist[direct].alist = - access_list_lookup (afi, filter->dlist[direct].name); - else - filter->dlist[direct].alist = NULL; - } - } - } - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - filter = &group->conf->filter[afi][safi]; - - for (direct = FILTER_IN; direct < FILTER_MAX; direct++) - { - if (filter->dlist[direct].name) - filter->dlist[direct].alist = - access_list_lookup (afi, filter->dlist[direct].name); - else - filter->dlist[direct].alist = NULL; - } - } + return ret; +} + +/* + * If peer clear is invoked in a loop for all peers on the BGP instance, + * it may end up freeing the doppelganger, and if this was the next node + * to the current node, we would end up accessing the freed next node. + * Pass along additional parameter which can be updated if next node + * is freed; only required when walking the peer list on BGP instance. + */ +int peer_clear(struct peer *peer, struct listnode **nnode) +{ + if (!CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) { + if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW)) { + UNSET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW); + if (peer->t_pmax_restart) { + BGP_TIMER_OFF(peer->t_pmax_restart); + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + "%s Maximum-prefix restart timer canceled", + peer->host); + } + BGP_EVENT_ADD(peer, BGP_Start); + return 0; + } + + peer->v_start = BGP_INIT_START_TIMER; + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_ADMIN_RESET); + else + bgp_session_reset_safe(peer, nnode); } -#if ENABLE_BGP_VNC - vnc_prefix_list_update(bgp); -#endif - } + return 0; } -/* Set prefix list to the peer. */ -int -peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct, - const char *name) +int peer_clear_soft(struct peer *peer, afi_t afi, safi_t safi, + enum bgp_clear_type stype) { - struct bgp_filter *filter; - struct peer_group *group; - struct listnode *node, *nnode; + struct peer_af *paf; - if (direct != FILTER_IN && direct != FILTER_OUT) - return BGP_ERR_INVALID_VALUE; + if (peer->status != Established) + return 0; - filter = &peer->filter[afi][safi]; + if (!peer->afc[afi][safi]) + return BGP_ERR_AF_UNCONFIGURED; - if (filter->dlist[direct].name) - return BGP_ERR_PEER_FILTER_CONFLICT; + peer->rtt = sockopt_tcp_rtt(peer->fd); - if (filter->plist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name); - filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->plist[direct].plist = prefix_list_lookup (afi, name); + if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH) { + /* Clear the "neighbor x.x.x.x default-originate" flag */ + paf = peer_af_find(peer, afi, safi); + if (paf && paf->subgroup + && CHECK_FLAG(paf->subgroup->sflags, + SUBGRP_STATUS_DEFAULT_ORIGINATE)) + UNSET_FLAG(paf->subgroup->sflags, + SUBGRP_STATUS_DEFAULT_ORIGINATE); - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - return 0; - } + bgp_announce_route(peer, afi, safi); + } - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - filter = &peer->filter[afi][safi]; + if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) { + if (CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_SM_ADV) + && (CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_RCV) + || CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_OLD_RCV))) { + struct bgp_filter *filter = &peer->filter[afi][safi]; + u_char prefix_type; + + if (CHECK_FLAG(peer->af_cap[afi][safi], + PEER_CAP_ORF_PREFIX_RM_RCV)) + prefix_type = ORF_TYPE_PREFIX; + else + prefix_type = ORF_TYPE_PREFIX_OLD; + + if (filter->plist[FILTER_IN].plist) { + if (CHECK_FLAG(peer->af_sflags[afi][safi], + PEER_STATUS_ORF_PREFIX_SEND)) + bgp_route_refresh_send( + peer, afi, safi, prefix_type, + REFRESH_DEFER, 1); + bgp_route_refresh_send(peer, afi, safi, + prefix_type, + REFRESH_IMMEDIATE, 0); + } else { + if (CHECK_FLAG(peer->af_sflags[afi][safi], + PEER_STATUS_ORF_PREFIX_SEND)) + bgp_route_refresh_send( + peer, afi, safi, prefix_type, + REFRESH_IMMEDIATE, 1); + else + bgp_route_refresh_send(peer, afi, safi, + 0, 0, 0); + } + return 0; + } + } - if (filter->plist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name); - filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->plist[direct].plist = prefix_list_lookup (afi, name); - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - } - return 0; + if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH + || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) { + /* If neighbor has soft reconfiguration inbound flag. + Use Adj-RIB-In database. */ + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_SOFT_RECONFIG)) + bgp_soft_reconfig_in(peer, afi, safi); + else { + /* If neighbor has route refresh capability, send route + refresh + message to the peer. */ + if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV) + || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV)) + bgp_route_refresh_send(peer, afi, safi, 0, 0, + 0); + else + return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED; + } + } + return 0; } -int -peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct) -{ - struct bgp_filter *filter; - struct bgp_filter *gfilter; - struct peer_group *group; - struct listnode *node, *nnode; +/* Display peer uptime.*/ +char *peer_uptime(time_t uptime2, char *buf, size_t len, u_char use_json, + json_object *json) +{ + time_t uptime1, epoch_tbuf; + struct tm *tm; + + /* Check buffer length. */ + if (len < BGP_UPTIME_LEN) { + if (!use_json) { + zlog_warn("peer_uptime (): buffer shortage %lu", + (u_long)len); + /* XXX: should return status instead of buf... */ + snprintf(buf, len, " "); + } + return buf; + } + + /* If there is no connection has been done before print `never'. */ + if (uptime2 == 0) { + if (use_json) { + json_object_string_add(json, "peerUptime", "never"); + json_object_int_add(json, "peerUptimeMsec", 0); + } else + snprintf(buf, len, "never"); + return buf; + } - if (direct != FILTER_IN && direct != FILTER_OUT) - return BGP_ERR_INVALID_VALUE; + /* Get current time. */ + uptime1 = bgp_clock(); + uptime1 -= uptime2; + tm = gmtime(&uptime1); - filter = &peer->filter[afi][safi]; +/* Making formatted timer strings. */ +#define ONE_DAY_SECOND 60*60*24 +#define ONE_WEEK_SECOND ONE_DAY_SECOND*7 +#define ONE_YEAR_SECOND ONE_DAY_SECOND*365 - /* apply peer-group filter */ - if (peer_group_active(peer)) - { - gfilter = &peer->group->conf->filter[afi][safi]; + if (uptime1 < ONE_DAY_SECOND) + snprintf(buf, len, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, + tm->tm_sec); + else if (uptime1 < ONE_WEEK_SECOND) + snprintf(buf, len, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour, + tm->tm_min); + else if (uptime1 < ONE_YEAR_SECOND) + snprintf(buf, len, "%02dw%dd%02dh", tm->tm_yday / 7, + tm->tm_yday - ((tm->tm_yday / 7) * 7), tm->tm_hour); + else + snprintf(buf, len, "%02dy%02dw%dd", tm->tm_year - 70, + tm->tm_yday / 7, + tm->tm_yday - ((tm->tm_yday / 7) * 7)); + + if (use_json) { + epoch_tbuf = time(NULL) - uptime1; + json_object_string_add(json, "peerUptime", buf); + json_object_int_add(json, "peerUptimeMsec", uptime1 * 1000); + json_object_int_add(json, "peerUptimeEstablishedEpoch", + epoch_tbuf); + } - if (gfilter->plist[direct].name) - { - if (filter->plist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name); - filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->plist[direct].name); - filter->plist[direct].plist = gfilter->plist[direct].plist; - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - return 0; - } - } - - if (filter->plist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name); - filter->plist[direct].name = NULL; - filter->plist[direct].plist = NULL; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - return 0; - } - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - filter = &peer->filter[afi][safi]; - - if (filter->plist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name); - filter->plist[direct].name = NULL; - filter->plist[direct].plist = NULL; - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - } - - return 0; + return buf; } -/* Update prefix-list list. */ -static void -peer_prefix_list_update (struct prefix_list *plist) -{ - struct listnode *mnode, *mnnode; - struct listnode *node, *nnode; - struct bgp *bgp; - struct peer *peer; - struct peer_group *group; - struct bgp_filter *filter; - afi_t afi; - safi_t safi; - int direct; - - for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) - { - - /* - * Update the prefix-list on update groups. - */ - update_group_policy_update(bgp, BGP_POLICY_PREFIX_LIST, - plist ? prefix_list_name(plist) : NULL, 0, 0); - - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - filter = &peer->filter[afi][safi]; +static void afi_header_vty_out(struct vty *vty, afi_t afi, safi_t safi, + int *write, const char *format, ...) +{ + va_list args; + int len = 0; + char buf[1024]; - for (direct = FILTER_IN; direct < FILTER_MAX; direct++) - { - if (filter->plist[direct].name) - filter->plist[direct].plist = - prefix_list_lookup (afi, filter->plist[direct].name); - else - filter->plist[direct].plist = NULL; - } - } - } - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - filter = &group->conf->filter[afi][safi]; - - for (direct = FILTER_IN; direct < FILTER_MAX; direct++) - { - if (filter->plist[direct].name) - filter->plist[direct].plist = - prefix_list_lookup (afi, filter->plist[direct].name); - else - filter->plist[direct].plist = NULL; - } - } - } - } -} - -int -peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct, - const char *name) -{ - struct bgp_filter *filter; - struct peer_group *group; - struct listnode *node, *nnode; - - if (direct != FILTER_IN && direct != FILTER_OUT) - return BGP_ERR_INVALID_VALUE; - - filter = &peer->filter[afi][safi]; - - if (filter->aslist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name); - filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->aslist[direct].aslist = as_list_lookup (name); - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - return 0; - } - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - filter = &peer->filter[afi][safi]; - - if (filter->aslist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name); - filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->aslist[direct].aslist = as_list_lookup (name); - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - } - return 0; -} - -int -peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct) -{ - struct bgp_filter *filter; - struct bgp_filter *gfilter; - struct peer_group *group; - struct listnode *node, *nnode; - - if (direct != FILTER_IN && direct != FILTER_OUT) - return BGP_ERR_INVALID_VALUE; - - filter = &peer->filter[afi][safi]; - - /* apply peer-group filter */ - if (peer_group_active(peer)) - { - gfilter = &peer->group->conf->filter[afi][safi]; - - if (gfilter->aslist[direct].name) - { - if (filter->aslist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name); - filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->aslist[direct].name); - filter->aslist[direct].aslist = gfilter->aslist[direct].aslist; - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - return 0; - } - } - - if (filter->aslist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name); - filter->aslist[direct].name = NULL; - filter->aslist[direct].aslist = NULL; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - return 0; - } - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - filter = &peer->filter[afi][safi]; - - if (filter->aslist[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name); - filter->aslist[direct].name = NULL; - filter->aslist[direct].aslist = NULL; - peer_on_policy_change(peer, afi, safi, - (direct == FILTER_OUT) ? 1 : 0); - } - - return 0; -} - -static void -peer_aslist_update (const char *aslist_name) -{ - afi_t afi; - safi_t safi; - int direct; - struct listnode *mnode, *mnnode; - struct listnode *node, *nnode; - struct bgp *bgp; - struct peer *peer; - struct peer_group *group; - struct bgp_filter *filter; - - for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) - { - update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST, aslist_name, - 0, 0); - - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - filter = &peer->filter[afi][safi]; + bgp_config_write_family_header(vty, afi, safi, write); - for (direct = FILTER_IN; direct < FILTER_MAX; direct++) - { - if (filter->aslist[direct].name) - filter->aslist[direct].aslist = - as_list_lookup (filter->aslist[direct].name); - else - filter->aslist[direct].aslist = NULL; - } - } - } - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - { - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - filter = &group->conf->filter[afi][safi]; + if (vty_shell(vty)) { + va_start(args, format); + vprintf(format, args); + va_end(args); + } else { + va_start(args, format); + len = vsnprintf(buf, sizeof(buf), format, args); + va_end(args); - for (direct = FILTER_IN; direct < FILTER_MAX; direct++) - { - if (filter->aslist[direct].name) - filter->aslist[direct].aslist = - as_list_lookup (filter->aslist[direct].name); - else - filter->aslist[direct].aslist = NULL; - } - } + buffer_put(vty->obuf, (u_char *)buf, len); } - } } -static void -peer_aslist_add (char *aslist_name) +static void bgp_config_write_filter(struct vty *vty, struct peer *peer, + afi_t afi, safi_t safi, int *write) { - peer_aslist_update (aslist_name); - route_map_notify_dependencies((char *)aslist_name, RMAP_EVENT_ASLIST_ADDED); -} + struct bgp_filter *filter; + struct bgp_filter *gfilter = NULL; + char *addr; + int in = FILTER_IN; + int out = FILTER_OUT; -static void -peer_aslist_del (const char *aslist_name) -{ - peer_aslist_update (aslist_name); - route_map_notify_dependencies(aslist_name, RMAP_EVENT_ASLIST_DELETED); -} + addr = peer->host; + filter = &peer->filter[afi][safi]; + if (peer_group_active(peer)) + gfilter = &peer->group->conf->filter[afi][safi]; + + /* distribute-list. */ + if (filter->dlist[in].name) + if (!gfilter || !gfilter->dlist[in].name + || strcmp(filter->dlist[in].name, gfilter->dlist[in].name) + != 0) { + afi_header_vty_out( + vty, afi, safi, write, + " neighbor %s distribute-list %s in\n", addr, + filter->dlist[in].name); + } -int -peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct, - const char *name) -{ - struct bgp_filter *filter; - struct peer_group *group; - struct listnode *node, *nnode; + if (filter->dlist[out].name && !gfilter) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s distribute-list %s out\n", + addr, filter->dlist[out].name); + } - if (direct != RMAP_IN && direct != RMAP_OUT) - return BGP_ERR_INVALID_VALUE; + /* prefix-list. */ + if (filter->plist[in].name) + if (!gfilter || !gfilter->plist[in].name + || strcmp(filter->plist[in].name, gfilter->plist[in].name) + != 0) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s prefix-list %s in\n", + addr, filter->plist[in].name); + } - filter = &peer->filter[afi][safi]; + if (filter->plist[out].name && !gfilter) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s prefix-list %s out\n", addr, + filter->plist[out].name); + } - if (filter->map[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name); + /* route-map. */ + if (filter->map[RMAP_IN].name) + if (!gfilter || !gfilter->map[RMAP_IN].name + || strcmp(filter->map[RMAP_IN].name, + gfilter->map[RMAP_IN].name) + != 0) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s route-map %s in\n", + addr, filter->map[RMAP_IN].name); + } - filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->map[direct].map = route_map_lookup_by_name (name); + if (filter->map[RMAP_OUT].name) + if (!gfilter || !gfilter->map[RMAP_OUT].name + || strcmp(filter->map[RMAP_OUT].name, + gfilter->map[RMAP_OUT].name) + != 0) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s route-map %s out\n", + addr, filter->map[RMAP_OUT].name); + } - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_on_policy_change(peer, afi, safi, - (direct == RMAP_OUT) ? 1 : 0); - return 0; - } + /* unsuppress-map */ + if (filter->usmap.name && !gfilter) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s unsuppress-map %s\n", addr, + filter->usmap.name); + } - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - filter = &peer->filter[afi][safi]; + /* filter-list. */ + if (filter->aslist[in].name) + if (!gfilter || !gfilter->aslist[in].name + || strcmp(filter->aslist[in].name, gfilter->aslist[in].name) + != 0) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s filter-list %s in\n", + addr, filter->aslist[in].name); + } - if (filter->map[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name); - filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->map[direct].map = route_map_lookup_by_name (name); - peer_on_policy_change(peer, afi, safi, - (direct == RMAP_OUT) ? 1 : 0); - } - return 0; + if (filter->aslist[out].name && !gfilter) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s filter-list %s out\n", addr, + filter->aslist[out].name); + } } -/* Unset route-map from the peer. */ -int -peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct) -{ - struct bgp_filter *filter; - struct bgp_filter *gfilter; - struct peer_group *group; - struct listnode *node, *nnode; +/* BGP peer configuration display function. */ +static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp, + struct peer *peer) +{ + struct peer *g_peer = NULL; + char buf[SU_ADDRSTRLEN]; + char *addr; + int if_pg_printed = FALSE; + int if_ras_printed = FALSE; + + /* Skip dynamic neighbors. */ + if (peer_dynamic_neighbor(peer)) + return; + + if (peer->conf_if) + addr = peer->conf_if; + else + addr = peer->host; + + /************************************ + ****** Global to the neighbor ****** + ************************************/ + if (peer->conf_if) { + if (CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) + vty_out(vty, " neighbor %s interface v6only", addr); + else + vty_out(vty, " neighbor %s interface", addr); + + if (peer_group_active(peer)) { + vty_out(vty, " peer-group %s", peer->group->name); + if_pg_printed = TRUE; + } else if (peer->as_type == AS_SPECIFIED) { + vty_out(vty, " remote-as %u", peer->as); + if_ras_printed = TRUE; + } else if (peer->as_type == AS_INTERNAL) { + vty_out(vty, " remote-as internal"); + if_ras_printed = TRUE; + } else if (peer->as_type == AS_EXTERNAL) { + vty_out(vty, " remote-as external"); + if_ras_printed = TRUE; + } - if (direct != RMAP_IN && direct != RMAP_OUT) - return BGP_ERR_INVALID_VALUE; + vty_out(vty, "\n"); + } - filter = &peer->filter[afi][safi]; + /* remote-as and peer-group */ + /* peer is a member of a peer-group */ + if (peer_group_active(peer)) { + g_peer = peer->group->conf; + + if (g_peer->as_type == AS_UNSPECIFIED && !if_ras_printed) { + if (peer->as_type == AS_SPECIFIED) { + vty_out(vty, " neighbor %s remote-as %u\n", + addr, peer->as); + } else if (peer->as_type == AS_INTERNAL) { + vty_out(vty, + " neighbor %s remote-as internal\n", + addr); + } else if (peer->as_type == AS_EXTERNAL) { + vty_out(vty, + " neighbor %s remote-as external\n", + addr); + } + } - /* apply peer-group filter */ - if (peer_group_active(peer)) - { - gfilter = &peer->group->conf->filter[afi][safi]; + /* For swpX peers we displayed the peer-group + * via 'neighbor swpX interface peer-group WORD' */ + if (!if_pg_printed) + vty_out(vty, " neighbor %s peer-group %s\n", addr, + peer->group->name); + } - if (gfilter->map[direct].name) - { - if (filter->map[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name); - filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->map[direct].name); - filter->map[direct].map = gfilter->map[direct].map; - peer_on_policy_change(peer, afi, safi, - (direct == RMAP_OUT) ? 1 : 0); - return 0; - } - } - - if (filter->map[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name); - filter->map[direct].name = NULL; - filter->map[direct].map = NULL; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_on_policy_change(peer, afi, safi, - (direct == RMAP_OUT) ? 1 : 0); - return 0; - } - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - filter = &peer->filter[afi][safi]; - - if (filter->map[direct].name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name); - filter->map[direct].name = NULL; - filter->map[direct].map = NULL; - peer_on_policy_change(peer, afi, safi, - (direct == RMAP_OUT) ? 1 : 0); - } - return 0; -} + /* peer is NOT a member of a peer-group */ + else { + /* peer is a peer-group, declare the peer-group */ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + vty_out(vty, " neighbor %s peer-group\n", addr); + } -/* Set unsuppress-map to the peer. */ -int -peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi, - const char *name) -{ - struct bgp_filter *filter; - struct peer_group *group; - struct listnode *node, *nnode; - - filter = &peer->filter[afi][safi]; - - if (filter->usmap.name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); - - filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->usmap.map = route_map_lookup_by_name (name); - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_on_policy_change(peer, afi, safi, 1); - return 0; - } - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - filter = &peer->filter[afi][safi]; - - if (filter->usmap.name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); - filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->usmap.map = route_map_lookup_by_name (name); - peer_on_policy_change(peer, afi, safi, 1); - } - return 0; -} + if (!if_ras_printed) { + if (peer->as_type == AS_SPECIFIED) { + vty_out(vty, " neighbor %s remote-as %u\n", + addr, peer->as); + } else if (peer->as_type == AS_INTERNAL) { + vty_out(vty, + " neighbor %s remote-as internal\n", + addr); + } else if (peer->as_type == AS_EXTERNAL) { + vty_out(vty, + " neighbor %s remote-as external\n", + addr); + } + } + } -/* Unset route-map from the peer. */ -int -peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi) -{ - struct bgp_filter *filter; - struct peer_group *group; - struct listnode *node, *nnode; - - filter = &peer->filter[afi][safi]; - - if (filter->usmap.name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); - filter->usmap.name = NULL; - filter->usmap.map = NULL; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer_on_policy_change(peer, afi, safi, 1); - return 0; - } - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - filter = &peer->filter[afi][safi]; - - if (filter->usmap.name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); - filter->usmap.name = NULL; - filter->usmap.map = NULL; - peer_on_policy_change(peer, afi, safi, 1); - } - return 0; -} - -int -peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi, - u_int32_t max, u_char threshold, - int warning, u_int16_t restart) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); - peer->pmax[afi][safi] = max; - peer->pmax_threshold[afi][safi] = threshold; - peer->pmax_restart[afi][safi] = restart; - if (warning) - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); - else - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); - - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); - peer->pmax[afi][safi] = max; - peer->pmax_threshold[afi][safi] = threshold; - peer->pmax_restart[afi][safi] = restart; - if (warning) - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); - else - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); - - if ((peer->status == Established) && (peer->afc[afi][safi])) - bgp_maximum_prefix_overflow (peer, afi, safi, 1); - } - } - else - { - if ((peer->status == Established) && (peer->afc[afi][safi])) - bgp_maximum_prefix_overflow (peer, afi, safi, 1); - } - - return 0; -} - -int -peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi) -{ - struct peer_group *group; - struct listnode *node, *nnode; - - /* apply peer-group config */ - if (peer_group_active(peer)) - { - if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], - PEER_FLAG_MAX_PREFIX)) - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); - else - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); - - if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], - PEER_FLAG_MAX_PREFIX_WARNING)) - SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); - else - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); - - peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi]; - peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi]; - peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi]; - return 0; - } - - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); - peer->pmax[afi][safi] = 0; - peer->pmax_threshold[afi][safi] = 0; - peer->pmax_restart[afi][safi] = 0; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - return 0; - - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); - UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING); - peer->pmax[afi][safi] = 0; - peer->pmax_threshold[afi][safi] = 0; - peer->pmax_restart[afi][safi] = 0; - } - return 0; -} - -int is_ebgp_multihop_configured (struct peer *peer) -{ - struct peer_group *group; - struct listnode *node, *nnode; - struct peer *peer1; - - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - group = peer->group; - if ((peer_sort(peer) != BGP_PEER_IBGP) && - (group->conf->ttl != 1)) - return 1; - - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1)) - { - if ((peer_sort (peer1) != BGP_PEER_IBGP) && - (peer1->ttl != 1)) - return 1; + /* local-as */ + if (peer->change_local_as) { + if (!peer_group_active(peer) + || peer->change_local_as != g_peer->change_local_as + || (CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) + != CHECK_FLAG(g_peer->flags, + PEER_FLAG_LOCAL_AS_NO_PREPEND)) + || (CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) + != CHECK_FLAG(g_peer->flags, + PEER_FLAG_LOCAL_AS_REPLACE_AS))) { + vty_out(vty, " neighbor %s local-as %u%s%s\n", addr, + peer->change_local_as, + CHECK_FLAG(peer->flags, + PEER_FLAG_LOCAL_AS_NO_PREPEND) + ? " no-prepend" + : "", + CHECK_FLAG(peer->flags, + PEER_FLAG_LOCAL_AS_REPLACE_AS) + ? " replace-as" + : ""); + } } - } - else - { - if ((peer_sort(peer) != BGP_PEER_IBGP) && - (peer->ttl != 1)) - return 1; - } - return 0; -} -/* Set # of hops between us and BGP peer. */ -int -peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops) -{ - struct peer_group *group; - struct listnode *node, *nnode; - int ret; + /* description */ + if (peer->desc) { + vty_out(vty, " neighbor %s description %s\n", addr, peer->desc); + } - zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host); + /* shutdown */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) { + if (!peer_group_active(peer) + || !CHECK_FLAG(g_peer->flags, PEER_FLAG_SHUTDOWN) + || peer->tx_shutdown_message) { + if (peer->tx_shutdown_message) + vty_out(vty, + " neighbor %s shutdown message %s\n", + addr, peer->tx_shutdown_message); + else + vty_out(vty, " neighbor %s shutdown\n", addr); + } + } - /* We cannot configure ttl-security hops when ebgp-multihop is already - set. For non peer-groups, the check is simple. For peer-groups, it's - slightly messy, because we need to check both the peer-group structure - and all peer-group members for any trace of ebgp-multihop configuration - before actually applying the ttl-security rules. Cisco really made a - mess of this configuration parameter, and OpenBGPD got it right. - */ + /* bfd */ + if (peer->bfd_info) { + if (!peer_group_active(peer) || !g_peer->bfd_info) { + bgp_bfd_peer_config_write(vty, peer, addr); + } + } - if ((peer->gtsm_hops == 0) && (peer->sort != BGP_PEER_IBGP)) - { - if (is_ebgp_multihop_configured (peer)) - return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK; + /* password */ + if (peer->password) { + if (!peer_group_active(peer) || !g_peer->password + || strcmp(peer->password, g_peer->password) != 0) { + vty_out(vty, " neighbor %s password %s\n", addr, + peer->password); + } + } - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer->gtsm_hops = gtsm_hops; + /* neighbor solo */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL)) { + if (!peer_group_active(peer)) { + vty_out(vty, " neighbor %s solo\n", addr); + } + } - /* Calling ebgp multihop also resets the session. - * On restart, NHT will get setup correctly as will the - * min & max ttls on the socket. The return value is - * irrelevant. - */ - ret = peer_ebgp_multihop_set (peer, MAXTTL); + /* BGP port */ + if (peer->port != BGP_PORT_DEFAULT) { + vty_out(vty, " neighbor %s port %d\n", addr, peer->port); + } - if (ret != 0) - return ret; + /* Local interface name */ + if (peer->ifname) { + vty_out(vty, " neighbor %s interface %s\n", addr, peer->ifname); } - else - { - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - peer->gtsm_hops = group->conf->gtsm_hops; - - /* Calling ebgp multihop also resets the session. - * On restart, NHT will get setup correctly as will the - * min & max ttls on the socket. The return value is - * irrelevant. - */ - peer_ebgp_multihop_set (peer, MAXTTL); - } - } - } - else - { - /* Post the first gtsm setup or if its ibgp, maxttl setting isn't - * necessary, just set the minttl. - */ - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - peer->gtsm_hops = gtsm_hops; - if (peer->fd >= 0) - sockopt_minttl (peer->su.sa.sa_family, peer->fd, - MAXTTL + 1 - gtsm_hops); - if ((peer->status < Established) && peer->doppelganger && - (peer->doppelganger->fd >= 0)) - sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd, - MAXTTL + 1 - gtsm_hops); + /* passive */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSIVE)) { + if (!peer_group_active(peer) + || !CHECK_FLAG(g_peer->flags, PEER_FLAG_PASSIVE)) { + vty_out(vty, " neighbor %s passive\n", addr); + } } - else - { - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - peer->gtsm_hops = group->conf->gtsm_hops; - - /* Change setting of existing peer - * established then change value (may break connectivity) - * not established yet (teardown session and restart) - * no session then do nothing (will get handled by next connection) - */ - if (peer->fd >= 0 && peer->gtsm_hops != 0) - sockopt_minttl (peer->su.sa.sa_family, peer->fd, - MAXTTL + 1 - peer->gtsm_hops); - if ((peer->status < Established) && peer->doppelganger && - (peer->doppelganger->fd >= 0)) - sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd, - MAXTTL + 1 - gtsm_hops); - - } - } - } - - return 0; -} - -int -peer_ttl_security_hops_unset (struct peer *peer) -{ - struct peer_group *group; - struct listnode *node, *nnode; - int ret = 0; - - zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host); - - /* if a peer-group member, then reset to peer-group default rather than 0 */ - if (peer_group_active (peer)) - peer->gtsm_hops = peer->group->conf->gtsm_hops; - else - peer->gtsm_hops = 0; - - if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - /* Invoking ebgp_multihop_set will set the TTL back to the original - * value as well as restting the NHT and such. The session is reset. - */ - if (peer->sort == BGP_PEER_EBGP) - ret = peer_ebgp_multihop_unset (peer); - else - { - if (peer->fd >= 0) - sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0); - - if ((peer->status < Established) && peer->doppelganger && - (peer->doppelganger->fd >= 0)) - sockopt_minttl (peer->su.sa.sa_family, - peer->doppelganger->fd, 0); - } - } - else - { - group = peer->group; - for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) - { - peer->gtsm_hops = 0; - if (peer->sort == BGP_PEER_EBGP) - ret = peer_ebgp_multihop_unset (peer); - else - { - if (peer->fd >= 0) - sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0); - if ((peer->status < Established) && peer->doppelganger && - (peer->doppelganger->fd >= 0)) - sockopt_minttl (peer->su.sa.sa_family, - peer->doppelganger->fd, 0); - } + /* ebgp-multihop */ + if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 + && !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL)) { + if (!peer_group_active(peer) || g_peer->ttl != peer->ttl) { + vty_out(vty, " neighbor %s ebgp-multihop %d\n", addr, + peer->ttl); + } } - } - return ret; -} + /* ttl-security hops */ + if (peer->gtsm_hops != 0) { + if (!peer_group_active(peer) + || g_peer->gtsm_hops != peer->gtsm_hops) { + vty_out(vty, " neighbor %s ttl-security hops %d\n", + addr, peer->gtsm_hops); + } + } + + /* disable-connected-check */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)) { + if (!peer_group_active(peer) + || !CHECK_FLAG(g_peer->flags, + PEER_FLAG_DISABLE_CONNECTED_CHECK)) { + vty_out(vty, " neighbor %s disable-connected-check\n", + addr); + } + } + + /* update-source */ + if (peer->update_if) { + if (!peer_group_active(peer) || !g_peer->update_if + || strcmp(g_peer->update_if, peer->update_if) != 0) { + vty_out(vty, " neighbor %s update-source %s\n", addr, + peer->update_if); + } + } + if (peer->update_source) { + if (!peer_group_active(peer) || !g_peer->update_source + || sockunion_cmp(g_peer->update_source, peer->update_source) + != 0) { + vty_out(vty, " neighbor %s update-source %s\n", addr, + sockunion2str(peer->update_source, buf, + SU_ADDRSTRLEN)); + } + } + + /* advertisement-interval */ + if (CHECK_FLAG(peer->config, PEER_CONFIG_ROUTEADV) + && ((!peer_group_active(peer) + && peer->v_routeadv != BGP_DEFAULT_EBGP_ROUTEADV) + || (peer_group_active(peer) + && peer->v_routeadv != g_peer->v_routeadv))) { + vty_out(vty, " neighbor %s advertisement-interval %u\n", addr, + peer->v_routeadv); + } + + /* timers */ + if (CHECK_FLAG(peer->config, PEER_CONFIG_TIMER) + && ((!peer_group_active(peer) + && (peer->keepalive != BGP_DEFAULT_KEEPALIVE + || peer->holdtime != BGP_DEFAULT_HOLDTIME)) + || (peer_group_active(peer) + && (peer->keepalive != g_peer->keepalive + || peer->holdtime != g_peer->holdtime)))) { + vty_out(vty, " neighbor %s timers %u %u\n", addr, + peer->keepalive, peer->holdtime); + } + + if (CHECK_FLAG(peer->config, PEER_CONFIG_CONNECT) + && ((!peer_group_active(peer) + && peer->connect != BGP_DEFAULT_CONNECT_RETRY) + || (peer_group_active(peer) + && peer->connect != g_peer->connect))) -/* - * If peer clear is invoked in a loop for all peers on the BGP instance, - * it may end up freeing the doppelganger, and if this was the next node - * to the current node, we would end up accessing the freed next node. - * Pass along additional parameter which can be updated if next node - * is freed; only required when walking the peer list on BGP instance. - */ -int -peer_clear (struct peer *peer, struct listnode **nnode) -{ - if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN)) - { - if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW)) - { - UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW); - if (peer->t_pmax_restart) - { - BGP_TIMER_OFF (peer->t_pmax_restart); - if (bgp_debug_neighbor_events(peer)) - zlog_debug ("%s Maximum-prefix restart timer canceled", - peer->host); - } - BGP_EVENT_ADD (peer, BGP_Start); - return 0; - } - - peer->v_start = BGP_INIT_START_TIMER; - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_ADMIN_RESET); - else - bgp_session_reset_safe(peer, nnode); - } - return 0; -} - -int -peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi, - enum bgp_clear_type stype) -{ - struct peer_af *paf; - - if (peer->status != Established) - return 0; - - if (! peer->afc[afi][safi]) - return BGP_ERR_AF_UNCONFIGURED; - - peer->rtt = sockopt_tcp_rtt (peer->fd); - - if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH) - { - /* Clear the "neighbor x.x.x.x default-originate" flag */ - paf = peer_af_find (peer, afi, safi); - if (paf && paf->subgroup && - CHECK_FLAG (paf->subgroup->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) - UNSET_FLAG (paf->subgroup->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE); - - bgp_announce_route (peer, afi, safi); - } - - if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) - { - if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV) - && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV) - || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV))) - { - struct bgp_filter *filter = &peer->filter[afi][safi]; - u_char prefix_type; - - if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)) - prefix_type = ORF_TYPE_PREFIX; - else - prefix_type = ORF_TYPE_PREFIX_OLD; - - if (filter->plist[FILTER_IN].plist) - { - if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND)) - bgp_route_refresh_send (peer, afi, safi, - prefix_type, REFRESH_DEFER, 1); - bgp_route_refresh_send (peer, afi, safi, prefix_type, - REFRESH_IMMEDIATE, 0); - } - else - { - if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND)) - bgp_route_refresh_send (peer, afi, safi, - prefix_type, REFRESH_IMMEDIATE, 1); - else - bgp_route_refresh_send (peer, afi, safi, 0, 0, 0); - } - return 0; - } - } - - if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH - || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) - { - /* If neighbor has soft reconfiguration inbound flag. - Use Adj-RIB-In database. */ - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)) - bgp_soft_reconfig_in (peer, afi, safi); - else { - /* If neighbor has route refresh capability, send route refresh - message to the peer. */ - if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV) - || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV)) - bgp_route_refresh_send (peer, afi, safi, 0, 0, 0); - else - return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED; + vty_out(vty, " neighbor %s timers connect %u\n", addr, + peer->connect); } - } - return 0; -} -/* Display peer uptime.*/ -char * -peer_uptime (time_t uptime2, char *buf, size_t len, u_char use_json, json_object *json) -{ - time_t uptime1, epoch_tbuf; - struct tm *tm; - - /* Check buffer length. */ - if (len < BGP_UPTIME_LEN) - { - if (!use_json) - { - zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len); - /* XXX: should return status instead of buf... */ - snprintf (buf, len, " "); - } - return buf; - } - - /* If there is no connection has been done before print `never'. */ - if (uptime2 == 0) - { - if (use_json) - { - json_object_string_add(json, "peerUptime", "never"); - json_object_int_add(json, "peerUptimeMsec", 0); - } - else - snprintf (buf, len, "never"); - return buf; - } - - /* Get current time. */ - uptime1 = bgp_clock (); - uptime1 -= uptime2; - tm = gmtime (&uptime1); - - /* Making formatted timer strings. */ -#define ONE_DAY_SECOND 60*60*24 -#define ONE_WEEK_SECOND ONE_DAY_SECOND*7 -#define ONE_YEAR_SECOND ONE_DAY_SECOND*365 + /* capability dynamic */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) { + if (!peer_group_active(peer) + || !CHECK_FLAG(g_peer->flags, + PEER_FLAG_DYNAMIC_CAPABILITY)) { + vty_out(vty, " neighbor %s capability dynamic\n", addr); + } + } - if (uptime1 < ONE_DAY_SECOND) - snprintf (buf, len, "%02d:%02d:%02d", - tm->tm_hour, tm->tm_min, tm->tm_sec); - else if (uptime1 < ONE_WEEK_SECOND) - snprintf (buf, len, "%dd%02dh%02dm", - tm->tm_yday, tm->tm_hour, tm->tm_min); - else if (uptime1 < ONE_YEAR_SECOND) - snprintf (buf, len, "%02dw%dd%02dh", - tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); - else - snprintf (buf, len, "%02dy%02dw%dd", - tm->tm_year - 70, tm->tm_yday/7, - tm->tm_yday - ((tm->tm_yday/7) * 7)); - - if (use_json) - { - epoch_tbuf = time(NULL) - uptime1; - json_object_string_add(json, "peerUptime", buf); - json_object_int_add(json, "peerUptimeMsec", uptime1 * 1000); - json_object_int_add(json, "peerUptimeEstablishedEpoch", epoch_tbuf); - } - - return buf; -} - -static void -afi_header_vty_out (struct vty *vty, afi_t afi, safi_t safi, - int *write, const char *format, ...) -{ - va_list args; - int len = 0; - char buf[1024]; - - bgp_config_write_family_header (vty, afi, safi, write); - - if (vty_shell (vty)) - { - va_start (args, format); - vprintf (format, args); - va_end (args); - } - else - { - va_start (args, format); - len = vsnprintf (buf, sizeof(buf), format, args); - va_end (args); - - buffer_put (vty->obuf, (u_char *) buf, len); - } -} - -static void -bgp_config_write_filter (struct vty *vty, struct peer *peer, - afi_t afi, safi_t safi, int *write) -{ - struct bgp_filter *filter; - struct bgp_filter *gfilter = NULL; - char *addr; - int in = FILTER_IN; - int out = FILTER_OUT; - - addr = peer->host; - filter = &peer->filter[afi][safi]; - - if (peer_group_active(peer)) - gfilter = &peer->group->conf->filter[afi][safi]; - - /* distribute-list. */ - if (filter->dlist[in].name) - if (! gfilter || ! gfilter->dlist[in].name - || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s distribute-list %s in\n", - addr, filter->dlist[in].name); - } - - if (filter->dlist[out].name && ! gfilter) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s distribute-list %s out\n", - addr, filter->dlist[out].name); - } - - /* prefix-list. */ - if (filter->plist[in].name) - if (! gfilter || ! gfilter->plist[in].name - || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s prefix-list %s in\n", - addr, filter->plist[in].name); - } - - if (filter->plist[out].name && ! gfilter) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s prefix-list %s out\n", - addr, filter->plist[out].name); - } - - /* route-map. */ - if (filter->map[RMAP_IN].name) - if (! gfilter || ! gfilter->map[RMAP_IN].name - || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s route-map %s in\n", - addr, filter->map[RMAP_IN].name); - } - - if (filter->map[RMAP_OUT].name) - if (! gfilter || ! gfilter->map[RMAP_OUT].name - || strcmp (filter->map[RMAP_OUT].name, gfilter->map[RMAP_OUT].name) != 0) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s route-map %s out\n", - addr, filter->map[RMAP_OUT].name); - } - - /* unsuppress-map */ - if (filter->usmap.name && ! gfilter) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s unsuppress-map %s\n", - addr, filter->usmap.name); - } - - /* filter-list. */ - if (filter->aslist[in].name) - if (! gfilter || ! gfilter->aslist[in].name - || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s filter-list %s in\n", - addr, filter->aslist[in].name); - } - - if (filter->aslist[out].name && ! gfilter) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s filter-list %s out\n", - addr, filter->aslist[out].name); - } -} + /* capability extended-nexthop */ + if (peer->ifp && !CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)) { + if (!peer_group_active(peer) + || !CHECK_FLAG(g_peer->flags, PEER_FLAG_CAPABILITY_ENHE)) { + vty_out(vty, + " no neighbor %s capability extended-nexthop\n", + addr); + } + } -/* BGP peer configuration display function. */ -static void -bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp, - struct peer *peer) -{ - struct peer *g_peer = NULL; - char buf[SU_ADDRSTRLEN]; - char *addr; - int if_pg_printed = FALSE; - int if_ras_printed = FALSE; - - /* Skip dynamic neighbors. */ - if (peer_dynamic_neighbor (peer)) - return; - - if (peer->conf_if) - addr = peer->conf_if; - else - addr = peer->host; - - /************************************ - ****** Global to the neighbor ****** - ************************************/ - if (peer->conf_if) - { - if (CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) - vty_out (vty, " neighbor %s interface v6only", addr); - else - vty_out (vty, " neighbor %s interface", addr); - - if (peer_group_active (peer)) - { - vty_out (vty, " peer-group %s", peer->group->name); - if_pg_printed = TRUE; - } - else if (peer->as_type == AS_SPECIFIED) - { - vty_out (vty, " remote-as %u", peer->as); - if_ras_printed = TRUE; - } - else if (peer->as_type == AS_INTERNAL) - { - vty_out (vty, " remote-as internal"); - if_ras_printed = TRUE; - } - else if (peer->as_type == AS_EXTERNAL) - { - vty_out (vty, " remote-as external"); - if_ras_printed = TRUE; - } - - vty_out (vty, "\n"); - } - - /* remote-as and peer-group */ - /* peer is a member of a peer-group */ - if (peer_group_active (peer)) - { - g_peer = peer->group->conf; - - if (g_peer->as_type == AS_UNSPECIFIED && !if_ras_printed) - { - if (peer->as_type == AS_SPECIFIED) - { - vty_out (vty, " neighbor %s remote-as %u\n", addr,peer->as); - } - else if (peer->as_type == AS_INTERNAL) - { - vty_out (vty, " neighbor %s remote-as internal\n", addr); - } - else if (peer->as_type == AS_EXTERNAL) - { - vty_out (vty, " neighbor %s remote-as external\n", addr); - } - } - - /* For swpX peers we displayed the peer-group - * via 'neighbor swpX interface peer-group WORD' */ - if (!if_pg_printed) - vty_out (vty, " neighbor %s peer-group %s\n", addr, - peer->group->name); - } - - /* peer is NOT a member of a peer-group */ - else - { - /* peer is a peer-group, declare the peer-group */ - if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) - { - vty_out (vty, " neighbor %s peer-group\n",addr); - } - - if (!if_ras_printed) - { - if (peer->as_type == AS_SPECIFIED) - { - vty_out (vty, " neighbor %s remote-as %u\n", addr,peer->as); - } - else if (peer->as_type == AS_INTERNAL) - { - vty_out (vty, " neighbor %s remote-as internal\n", addr); - } - else if (peer->as_type == AS_EXTERNAL) - { - vty_out (vty, " neighbor %s remote-as external\n", addr); - } - } - } - - /* local-as */ - if (peer->change_local_as) - { - if (! peer_group_active (peer) - || peer->change_local_as != g_peer->change_local_as - || (CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) != - CHECK_FLAG (g_peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)) - || (CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) != - CHECK_FLAG (g_peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS))) - { - vty_out (vty, " neighbor %s local-as %u%s%s\n", addr, - peer->change_local_as, - CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ? - " no-prepend" : "", - CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ? " replace-as" : ""); - } - } - - /* description */ - if (peer->desc) - { - vty_out (vty, " neighbor %s description %s\n", addr,peer->desc); - } - - /* shutdown */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN)) - { - if (! peer_group_active (peer) || - ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN) || - peer->tx_shutdown_message) - { - if (peer->tx_shutdown_message) - vty_out (vty, " neighbor %s shutdown message %s\n", addr, - peer->tx_shutdown_message); - else - vty_out (vty, " neighbor %s shutdown\n", addr); - } - } - - /* bfd */ - if (peer->bfd_info) - { - if (! peer_group_active (peer) || ! g_peer->bfd_info) - { - bgp_bfd_peer_config_write(vty, peer, addr); - } - } - - /* password */ - if (peer->password) - { - if (!peer_group_active (peer) - || ! g_peer->password - || strcmp (peer->password, g_peer->password) != 0) - { - vty_out (vty, " neighbor %s password %s\n", addr,peer->password); - } - } - - /* neighbor solo */ - if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL)) - { - if (!peer_group_active (peer)) - { - vty_out (vty, " neighbor %s solo\n", addr); - } - } - - /* BGP port */ - if (peer->port != BGP_PORT_DEFAULT) - { - vty_out (vty, " neighbor %s port %d\n", addr,peer->port); - } - - /* Local interface name */ - if (peer->ifname) - { - vty_out (vty, " neighbor %s interface %s\n", addr,peer->ifname); - } - - /* passive */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE)) - { - if (! peer_group_active (peer) || - ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE)) - { - vty_out (vty, " neighbor %s passive\n", addr); - } - } - - /* ebgp-multihop */ - if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 && - !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL)) - { - if (! peer_group_active (peer) || g_peer->ttl != peer->ttl) - { - vty_out (vty, " neighbor %s ebgp-multihop %d\n", addr,peer->ttl); - } - } - - /* ttl-security hops */ - if (peer->gtsm_hops != 0) - { - if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops) - { - vty_out (vty, " neighbor %s ttl-security hops %d\n", addr, - peer->gtsm_hops); - } - } - - /* disable-connected-check */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)) - { - if (! peer_group_active (peer) || - ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)) - { - vty_out (vty, " neighbor %s disable-connected-check\n", addr); - } - } - - /* update-source */ - if (peer->update_if) - { - if (! peer_group_active (peer) || ! g_peer->update_if - || strcmp (g_peer->update_if, peer->update_if) != 0) - { - vty_out (vty, " neighbor %s update-source %s\n", addr, - peer->update_if); - } - } - if (peer->update_source) - { - if (! peer_group_active (peer) || ! g_peer->update_source - || sockunion_cmp (g_peer->update_source, - peer->update_source) != 0) - { - vty_out (vty, " neighbor %s update-source %s\n", addr, - sockunion2str(peer->update_source, buf, SU_ADDRSTRLEN)); - } - } - - /* advertisement-interval */ - if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV) && - ((! peer_group_active (peer) && peer->v_routeadv != BGP_DEFAULT_EBGP_ROUTEADV) || - (peer_group_active (peer) && peer->v_routeadv != g_peer->v_routeadv))) - { - vty_out (vty, " neighbor %s advertisement-interval %u\n", - addr, peer->v_routeadv); - } - - /* timers */ - if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER) && - ((! peer_group_active (peer) && (peer->keepalive != BGP_DEFAULT_KEEPALIVE || peer->holdtime != BGP_DEFAULT_HOLDTIME)) || - (peer_group_active (peer) && (peer->keepalive != g_peer->keepalive || peer->holdtime != g_peer->holdtime)))) - { - vty_out (vty, " neighbor %s timers %u %u\n", addr, - peer->keepalive, peer->holdtime); - } - - if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) && - ((! peer_group_active (peer) && peer->connect != BGP_DEFAULT_CONNECT_RETRY) || - (peer_group_active (peer) && peer->connect != g_peer->connect))) - - { - vty_out (vty, " neighbor %s timers connect %u\n", addr, - peer->connect); - } - - /* capability dynamic */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) - { - if (! peer_group_active (peer) || - ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) - { - vty_out (vty, " neighbor %s capability dynamic\n",addr); - } - } - - /* capability extended-nexthop */ - if (peer->ifp && !CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE)) - { - if (! peer_group_active (peer) || - ! CHECK_FLAG (g_peer->flags, PEER_FLAG_CAPABILITY_ENHE)) - { - vty_out (vty, " no neighbor %s capability extended-nexthop\n", - addr); - } - } - - if (!peer->ifp && CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE)) - { - if (! peer_group_active (peer) || - ! CHECK_FLAG (g_peer->flags, PEER_FLAG_CAPABILITY_ENHE)) - { - vty_out (vty, " neighbor %s capability extended-nexthop\n",addr); - } - } - - /* dont-capability-negotiation */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY)) - { - if (! peer_group_active (peer) || - ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY)) - { - vty_out (vty, " neighbor %s dont-capability-negotiate\n",addr); - } - } - - /* override-capability */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) - { - if (! peer_group_active (peer) || - ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) - { - vty_out (vty, " neighbor %s override-capability\n",addr); - } - } - - /* strict-capability-match */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) - { - if (! peer_group_active (peer) || - ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) - { - vty_out (vty, " neighbor %s strict-capability-match\n",addr); - } - } + if (!peer->ifp && CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)) { + if (!peer_group_active(peer) + || !CHECK_FLAG(g_peer->flags, PEER_FLAG_CAPABILITY_ENHE)) { + vty_out(vty, + " neighbor %s capability extended-nexthop\n", + addr); + } + } + + /* dont-capability-negotiation */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_DONT_CAPABILITY)) { + if (!peer_group_active(peer) + || !CHECK_FLAG(g_peer->flags, PEER_FLAG_DONT_CAPABILITY)) { + vty_out(vty, " neighbor %s dont-capability-negotiate\n", + addr); + } + } + + /* override-capability */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) { + if (!peer_group_active(peer) + || !CHECK_FLAG(g_peer->flags, + PEER_FLAG_OVERRIDE_CAPABILITY)) { + vty_out(vty, " neighbor %s override-capability\n", + addr); + } + } + + /* strict-capability-match */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) { + if (!peer_group_active(peer) + || !CHECK_FLAG(g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) { + vty_out(vty, " neighbor %s strict-capability-match\n", + addr); + } + } } /* BGP peer configuration display function. */ -static void -bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, - struct peer *peer, afi_t afi, safi_t safi, - int *write) -{ - struct peer *g_peer = NULL; - char *addr; - - /* Skip dynamic neighbors. */ - if (peer_dynamic_neighbor (peer)) - return; - - if (peer->conf_if) - addr = peer->conf_if; - else - addr = peer->host; - - /************************************ - ****** Per AF to the neighbor ****** - ************************************/ - if (peer_group_active (peer)) - { - g_peer = peer->group->conf; - - /* If the peer-group is active but peer is not, print a 'no activate' */ - if (g_peer->afc[afi][safi] && !peer->afc[afi][safi]) - { - afi_header_vty_out (vty, afi, safi, write, - " no neighbor %s activate\n", - addr); - } - - /* If the peer-group is not active but peer is, print an 'activate' */ - else if (!g_peer->afc[afi][safi] && peer->afc[afi][safi]) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s activate\n", - addr); - } - } - else - { - if (peer->afc[afi][safi]) - { - if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) - { - if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)) - { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s activate\n", - addr); - } - } - else - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s activate\n", - addr); - } - else - { - if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) - { - if (!bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)) - { - afi_header_vty_out (vty, afi, safi, write, - " no neighbor %s activate\n", - addr); - } - } - } - } - - /* addpath TX knobs */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ADDPATH_TX_ALL_PATHS)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s addpath-tx-all-paths\n", - addr); - } - - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s addpath-tx-bestpath-per-AS\n", - addr); - } - - /* ORF capability. */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) || - peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_RM)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s capability orf prefix-list", - addr); - - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) && - peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_RM)) - vty_out (vty, " both"); - else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM)) - vty_out (vty, " send"); - else - vty_out (vty, " receive"); - vty_out (vty, "\n"); - } - - /* Route reflector client. */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s route-reflector-client\n", - addr); - } - - /* next-hop-self force */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_FORCE_NEXTHOP_SELF)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s next-hop-self force\n", - addr); - } - - /* next-hop-self */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s next-hop-self\n", - addr); - } - - /* remove-private-AS */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s remove-private-AS all replace-AS\n", - addr); - } - - else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s remove-private-AS replace-AS\n", - addr); - } - - else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s remove-private-AS all\n", - addr); - } - - else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s remove-private-AS\n", - addr); - } - - /* as-override */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s as-override\n", - addr); - } - - /* send-community print. */ - if (bgp_option_check (BGP_OPT_CONFIG_CISCO)) - { - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) - && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY) - && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s send-community all\n", - addr); - } - else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s send-community large\n", - addr); - } - else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s send-community extended\n", - addr); - } - else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s send-community\n", - addr); - } - } - else - { - if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) && - (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)) && - !peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY) && - (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) && - !peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY) && - (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY))) - { - afi_header_vty_out (vty, afi, safi, write, - " no neighbor %s send-community all\n", - addr); - } - else - { - if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY) && - (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY))) - { - afi_header_vty_out (vty, afi, safi, write, - " no neighbor %s send-community large\n", - addr); - } - - if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY) && - (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))) - { - afi_header_vty_out (vty, afi, safi, write, - " no neighbor %s send-community extended\n", - addr); - } - - if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) && - (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))) - { - afi_header_vty_out (vty, afi, safi, write, - " no neighbor %s send-community\n", - addr); - } - } - } - - /* Default information */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE) || - (g_peer && - ((peer->default_rmap[afi][safi].name && !g_peer->default_rmap[afi][safi].name) || - (!peer->default_rmap[afi][safi].name && g_peer->default_rmap[afi][safi].name) || - (peer->default_rmap[afi][safi].name && - strcmp(peer->default_rmap[afi][safi].name, g_peer->default_rmap[afi][safi].name))))) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s default-originate", addr); - if (peer->default_rmap[afi][safi].name) - vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name); - vty_out (vty, "\n"); - } - - /* Soft reconfiguration inbound. */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SOFT_RECONFIG)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s soft-reconfiguration inbound\n", - addr); - } - - /* maximum-prefix. */ - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) - if (! peer_group_active(peer) - || g_peer->pmax[afi][safi] != peer->pmax[afi][safi] - || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi] - || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING) - != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s maximum-prefix %lu", - addr, peer->pmax[afi][safi]); - if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT) - vty_out (vty, " %u", peer->pmax_threshold[afi][safi]); - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)) - vty_out (vty, " warning-only"); - if (peer->pmax_restart[afi][safi]) - vty_out (vty, " restart %u", peer->pmax_restart[afi][safi]); - vty_out (vty, "\n"); - } - - /* Route server client. */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_RSERVER_CLIENT)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s route-server-client\n", - addr); - } - - /* Nexthop-local unchanged. */ - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s nexthop-local unchanged\n", - addr); - } - - /* allowas-in <1-10> */ - if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN)) - { - if (! peer_group_active (peer) - || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN) - || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi]) - { - if (peer->allowas_in[afi][safi] == 3) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s allowas-in\n", - addr); - } - else - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s allowas-in %d\n", - addr, peer->allowas_in[afi][safi]); - } - } - } - - /* allowas-in origin */ - else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN)) - { - if (! peer_group_active (peer) - || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s allowas-in origin\n", - addr); - } - } - - /* weight */ - if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_WEIGHT)) - if (! peer_group_active (peer) - || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_WEIGHT) - || peer->weight[afi][safi] != g_peer->weight[afi][safi]) - { - if (peer->weight[afi][safi]) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s weight %lu\n", - addr, peer->weight[afi][safi]); - } - } - - /* Filter. */ - bgp_config_write_filter (vty, peer, afi, safi, write); - - /* atribute-unchanged. */ - if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED) - || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED) - || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) - { - if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) - && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED) - && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_MED_UNCHANGED)) - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s attribute-unchanged\n", - addr); - } - else - { - afi_header_vty_out (vty, afi, safi, write, - " neighbor %s attribute-unchanged%s%s%s\n", addr, - peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) ? - " as-path" : "", - peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED) ? - " next-hop" : "", - peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_MED_UNCHANGED) ? - " med" : ""); - } - } +static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, + struct peer *peer, afi_t afi, safi_t safi, + int *write) +{ + struct peer *g_peer = NULL; + char *addr; + + /* Skip dynamic neighbors. */ + if (peer_dynamic_neighbor(peer)) + return; + + if (peer->conf_if) + addr = peer->conf_if; + else + addr = peer->host; + + /************************************ + ****** Per AF to the neighbor ****** + ************************************/ + if (peer_group_active(peer)) { + g_peer = peer->group->conf; + + /* If the peer-group is active but peer is not, print a 'no + * activate' */ + if (g_peer->afc[afi][safi] && !peer->afc[afi][safi]) { + afi_header_vty_out(vty, afi, safi, write, + " no neighbor %s activate\n", addr); + } + + /* If the peer-group is not active but peer is, print an + 'activate' */ + else if (!g_peer->afc[afi][safi] && peer->afc[afi][safi]) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s activate\n", addr); + } + } else { + if (peer->afc[afi][safi]) { + if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) { + if (bgp_flag_check(bgp, + BGP_FLAG_NO_DEFAULT_IPV4)) { + afi_header_vty_out( + vty, afi, safi, write, + " neighbor %s activate\n", + addr); + } + } else + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s activate\n", + addr); + } else { + if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) { + if (!bgp_flag_check(bgp, + BGP_FLAG_NO_DEFAULT_IPV4)) { + afi_header_vty_out( + vty, afi, safi, write, + " no neighbor %s activate\n", + addr); + } + } + } + } + + /* addpath TX knobs */ + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_ADDPATH_TX_ALL_PATHS)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s addpath-tx-all-paths\n", + addr); + } + + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s addpath-tx-bestpath-per-AS\n", + addr); + } + + /* ORF capability. */ + if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) + || peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_ORF_PREFIX_RM)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s capability orf prefix-list", + addr); + + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_ORF_PREFIX_SM) + && peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_ORF_PREFIX_RM)) + vty_out(vty, " both"); + else if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_ORF_PREFIX_SM)) + vty_out(vty, " send"); + else + vty_out(vty, " receive"); + vty_out(vty, "\n"); + } + + /* Route reflector client. */ + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_REFLECTOR_CLIENT)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s route-reflector-client\n", + addr); + } + + /* next-hop-self force */ + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_FORCE_NEXTHOP_SELF)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s next-hop-self force\n", addr); + } + + /* next-hop-self */ + if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s next-hop-self\n", addr); + } + + /* remove-private-AS */ + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) { + afi_header_vty_out( + vty, afi, safi, write, + " neighbor %s remove-private-AS all replace-AS\n", + addr); + } + + else if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) { + afi_header_vty_out( + vty, afi, safi, write, + " neighbor %s remove-private-AS replace-AS\n", addr); + } + + else if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s remove-private-AS all\n", + addr); + } + + else if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_REMOVE_PRIVATE_AS)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s remove-private-AS\n", addr); + } + + /* as-override */ + if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s as-override\n", addr); + } + + /* send-community print. */ + if (bgp_option_check(BGP_OPT_CONFIG_CISCO)) { + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_SEND_COMMUNITY) + && peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_SEND_EXT_COMMUNITY) + && peergroup_af_flag_check( + peer, afi, safi, + PEER_FLAG_SEND_LARGE_COMMUNITY)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s send-community all\n", + addr); + } else if (peergroup_af_flag_check( + peer, afi, safi, + PEER_FLAG_SEND_LARGE_COMMUNITY)) { + afi_header_vty_out( + vty, afi, safi, write, + " neighbor %s send-community large\n", addr); + } else if (peergroup_af_flag_check( + peer, afi, safi, + PEER_FLAG_SEND_EXT_COMMUNITY)) { + afi_header_vty_out( + vty, afi, safi, write, + " neighbor %s send-community extended\n", + addr); + } else if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_SEND_COMMUNITY)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s send-community\n", + addr); + } + } else { + if (!peer_af_flag_check(peer, afi, safi, + PEER_FLAG_SEND_COMMUNITY) + && (!g_peer || peer_af_flag_check(g_peer, afi, safi, + PEER_FLAG_SEND_COMMUNITY)) + && !peer_af_flag_check(peer, afi, safi, + PEER_FLAG_SEND_EXT_COMMUNITY) + && (!g_peer + || peer_af_flag_check(g_peer, afi, safi, + PEER_FLAG_SEND_EXT_COMMUNITY)) + && !peer_af_flag_check(peer, afi, safi, + PEER_FLAG_SEND_LARGE_COMMUNITY) + && (!g_peer || peer_af_flag_check( + g_peer, afi, safi, + PEER_FLAG_SEND_LARGE_COMMUNITY))) { + afi_header_vty_out( + vty, afi, safi, write, + " no neighbor %s send-community all\n", addr); + } else { + if (!peer_af_flag_check(peer, afi, safi, + PEER_FLAG_SEND_LARGE_COMMUNITY) + && (!g_peer + || peer_af_flag_check( + g_peer, afi, safi, + PEER_FLAG_SEND_LARGE_COMMUNITY))) { + afi_header_vty_out( + vty, afi, safi, write, + " no neighbor %s send-community large\n", + addr); + } + + if (!peer_af_flag_check(peer, afi, safi, + PEER_FLAG_SEND_EXT_COMMUNITY) + && (!g_peer + || peer_af_flag_check( + g_peer, afi, safi, + PEER_FLAG_SEND_EXT_COMMUNITY))) { + afi_header_vty_out( + vty, afi, safi, write, + " no neighbor %s send-community extended\n", + addr); + } + + if (!peer_af_flag_check(peer, afi, safi, + PEER_FLAG_SEND_COMMUNITY) + && (!g_peer || peer_af_flag_check( + g_peer, afi, safi, + PEER_FLAG_SEND_COMMUNITY))) { + afi_header_vty_out( + vty, afi, safi, write, + " no neighbor %s send-community\n", + addr); + } + } + } + + /* Default information */ + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_DEFAULT_ORIGINATE) + || (g_peer + && ((peer->default_rmap[afi][safi].name + && !g_peer->default_rmap[afi][safi].name) + || (!peer->default_rmap[afi][safi].name + && g_peer->default_rmap[afi][safi].name) + || (peer->default_rmap[afi][safi].name + && strcmp(peer->default_rmap[afi][safi].name, + g_peer->default_rmap[afi][safi].name))))) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s default-originate", addr); + if (peer->default_rmap[afi][safi].name) + vty_out(vty, " route-map %s", + peer->default_rmap[afi][safi].name); + vty_out(vty, "\n"); + } + + /* Soft reconfiguration inbound. */ + if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_SOFT_RECONFIG)) { + afi_header_vty_out( + vty, afi, safi, write, + " neighbor %s soft-reconfiguration inbound\n", addr); + } + + /* maximum-prefix. */ + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) + if (!peer_group_active(peer) + || g_peer->pmax[afi][safi] != peer->pmax[afi][safi] + || g_peer->pmax_threshold[afi][safi] + != peer->pmax_threshold[afi][safi] + || CHECK_FLAG(g_peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING) + != CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s maximum-prefix %lu", + addr, peer->pmax[afi][safi]); + if (peer->pmax_threshold[afi][safi] + != MAXIMUM_PREFIX_THRESHOLD_DEFAULT) + vty_out(vty, " %u", + peer->pmax_threshold[afi][safi]); + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING)) + vty_out(vty, " warning-only"); + if (peer->pmax_restart[afi][safi]) + vty_out(vty, " restart %u", + peer->pmax_restart[afi][safi]); + vty_out(vty, "\n"); + } + + /* Route server client. */ + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_RSERVER_CLIENT)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s route-server-client\n", addr); + } + + /* Nexthop-local unchanged. */ + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s nexthop-local unchanged\n", + addr); + } + + /* allowas-in <1-10> */ + if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_ALLOWAS_IN)) { + if (!peer_group_active(peer) + || !peer_af_flag_check(g_peer, afi, safi, + PEER_FLAG_ALLOWAS_IN) + || peer->allowas_in[afi][safi] + != g_peer->allowas_in[afi][safi]) { + if (peer->allowas_in[afi][safi] == 3) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s allowas-in\n", + addr); + } else { + afi_header_vty_out( + vty, afi, safi, write, + " neighbor %s allowas-in %d\n", addr, + peer->allowas_in[afi][safi]); + } + } + } + + /* allowas-in origin */ + else if (peer_af_flag_check(peer, afi, safi, + PEER_FLAG_ALLOWAS_IN_ORIGIN)) { + if (!peer_group_active(peer) + || !peer_af_flag_check(g_peer, afi, safi, + PEER_FLAG_ALLOWAS_IN_ORIGIN)) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s allowas-in origin\n", + addr); + } + } + + /* weight */ + if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_WEIGHT)) + if (!peer_group_active(peer) + || !peer_af_flag_check(g_peer, afi, safi, PEER_FLAG_WEIGHT) + || peer->weight[afi][safi] != g_peer->weight[afi][safi]) { + if (peer->weight[afi][safi]) { + afi_header_vty_out(vty, afi, safi, write, + " neighbor %s weight %lu\n", + addr, + peer->weight[afi][safi]); + } + } + + /* Filter. */ + bgp_config_write_filter(vty, peer, afi, safi, write); + + /* atribute-unchanged. */ + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED) + || CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_NEXTHOP_UNCHANGED) + || CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) { + if (peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_AS_PATH_UNCHANGED) + && peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_NEXTHOP_UNCHANGED) + && peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_MED_UNCHANGED)) { + afi_header_vty_out( + vty, afi, safi, write, + " neighbor %s attribute-unchanged\n", addr); + } else { + afi_header_vty_out( + vty, afi, safi, write, + " neighbor %s attribute-unchanged%s%s%s\n", + addr, + peergroup_af_flag_check( + peer, afi, safi, + PEER_FLAG_AS_PATH_UNCHANGED) + ? " as-path" + : "", + peergroup_af_flag_check( + peer, afi, safi, + PEER_FLAG_NEXTHOP_UNCHANGED) + ? " next-hop" + : "", + peergroup_af_flag_check(peer, afi, safi, + PEER_FLAG_MED_UNCHANGED) + ? " med" + : ""); + } + } } /* Display "address-family" configuration header. */ -void -bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi, - int *write) -{ - if (*write) - return; - - vty_out (vty, " !\n address-family "); - - if (afi == AFI_IP) - { - if (safi == SAFI_UNICAST) - vty_out (vty, "ipv4 unicast"); - else if (safi == SAFI_LABELED_UNICAST) - vty_out (vty, "ipv4 labeled-unicast"); - else if (safi == SAFI_MULTICAST) - vty_out (vty, "ipv4 multicast"); - else if (safi == SAFI_MPLS_VPN) - vty_out (vty, "ipv4 vpn"); - else if (safi == SAFI_ENCAP) - vty_out (vty, "ipv4 encap"); - } - else if (afi == AFI_IP6) - { - if (safi == SAFI_UNICAST) - vty_out (vty, "ipv6 unicast"); - else if (safi == SAFI_LABELED_UNICAST) - vty_out (vty, "ipv6 labeled-unicast"); - else if (safi == SAFI_MULTICAST) - vty_out (vty, "ipv6 multicast"); - else if (safi == SAFI_MPLS_VPN) - vty_out (vty, "ipv6 vpn"); - else if (safi == SAFI_ENCAP) - vty_out (vty, "ipv6 encap"); - } - else if (afi == AFI_L2VPN) - { - if (safi == SAFI_EVPN) - vty_out (vty, "l2vpn evpn"); - } - vty_out (vty, "\n"); - - *write = 1; +void bgp_config_write_family_header(struct vty *vty, afi_t afi, safi_t safi, + int *write) +{ + if (*write) + return; + + vty_out(vty, " !\n address-family "); + + if (afi == AFI_IP) { + if (safi == SAFI_UNICAST) + vty_out(vty, "ipv4 unicast"); + else if (safi == SAFI_LABELED_UNICAST) + vty_out(vty, "ipv4 labeled-unicast"); + else if (safi == SAFI_MULTICAST) + vty_out(vty, "ipv4 multicast"); + else if (safi == SAFI_MPLS_VPN) + vty_out(vty, "ipv4 vpn"); + else if (safi == SAFI_ENCAP) + vty_out(vty, "ipv4 encap"); + } else if (afi == AFI_IP6) { + if (safi == SAFI_UNICAST) + vty_out(vty, "ipv6 unicast"); + else if (safi == SAFI_LABELED_UNICAST) + vty_out(vty, "ipv6 labeled-unicast"); + else if (safi == SAFI_MULTICAST) + vty_out(vty, "ipv6 multicast"); + else if (safi == SAFI_MPLS_VPN) + vty_out(vty, "ipv6 vpn"); + else if (safi == SAFI_ENCAP) + vty_out(vty, "ipv6 encap"); + } else if (afi == AFI_L2VPN) { + if (safi == SAFI_EVPN) + vty_out(vty, "l2vpn evpn"); + } + vty_out(vty, "\n"); + + *write = 1; } /* Address family based peer configuration display. */ -static int -bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi, - safi_t safi) +static int bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi) { - int write = 0; - struct peer *peer; - struct peer_group *group; - struct listnode *node, *nnode; + int write = 0; + struct peer *peer; + struct peer_group *group; + struct listnode *node, *nnode; - bgp_config_write_distance (vty, bgp, afi, safi, &write); + bgp_config_write_distance(vty, bgp, afi, safi, &write); - bgp_config_write_network (vty, bgp, afi, safi, &write); + bgp_config_write_network(vty, bgp, afi, safi, &write); - bgp_config_write_redistribute (vty, bgp, afi, safi, &write); + bgp_config_write_redistribute(vty, bgp, afi, safi, &write); - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - bgp_config_write_peer_af (vty, bgp, group->conf, afi, safi, &write); + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) + bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi, + &write); - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - /* Skip dynamic neighbors. */ - if (peer_dynamic_neighbor (peer)) - continue; + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + /* Skip dynamic neighbors. */ + if (peer_dynamic_neighbor(peer)) + continue; - /* Do not display doppelganger peers */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)) - bgp_config_write_peer_af (vty, bgp, peer, afi, safi, &write); - } + /* Do not display doppelganger peers */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) + bgp_config_write_peer_af(vty, bgp, peer, afi, safi, + &write); + } - bgp_config_write_maxpaths (vty, bgp, afi, safi, &write); - bgp_config_write_table_map (vty, bgp, afi, safi, &write); + bgp_config_write_maxpaths(vty, bgp, afi, safi, &write); + bgp_config_write_table_map(vty, bgp, afi, safi, &write); - if (safi == SAFI_EVPN) - bgp_config_write_evpn_info (vty, bgp, afi, safi, &write); + if (safi == SAFI_EVPN) + bgp_config_write_evpn_info(vty, bgp, afi, safi, &write); - if (write) - vty_out (vty, " exit-address-family\n"); + if (write) + vty_out(vty, " exit-address-family\n"); - return write; + return write; } -int -bgp_config_write (struct vty *vty) +int bgp_config_write(struct vty *vty) { - int write = 0; - struct bgp *bgp; - struct peer_group *group; - struct peer *peer; - struct listnode *node, *nnode; - struct listnode *mnode, *mnnode; + int write = 0; + struct bgp *bgp; + struct peer_group *group; + struct peer *peer; + struct listnode *node, *nnode; + struct listnode *mnode, *mnnode; - /* BGP Multiple instance. */ - if (!bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE)) - { - vty_out (vty, "no bgp multiple-instance\n"); - write++; - } + /* BGP Multiple instance. */ + if (!bgp_option_check(BGP_OPT_MULTIPLE_INSTANCE)) { + vty_out(vty, "no bgp multiple-instance\n"); + write++; + } - /* BGP Config type. */ - if (bgp_option_check (BGP_OPT_CONFIG_CISCO)) - { - vty_out (vty, "bgp config-type cisco\n"); - write++; - } + /* BGP Config type. */ + if (bgp_option_check(BGP_OPT_CONFIG_CISCO)) { + vty_out(vty, "bgp config-type cisco\n"); + write++; + } - if (bm->rmap_update_timer != RMAP_DEFAULT_UPDATE_TIMER) - vty_out (vty, "bgp route-map delay-timer %u\n",bm->rmap_update_timer); + if (bm->rmap_update_timer != RMAP_DEFAULT_UPDATE_TIMER) + vty_out(vty, "bgp route-map delay-timer %u\n", + bm->rmap_update_timer); + + /* BGP configuration. */ + for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) { + if (write) + vty_out(vty, "!\n"); + + /* Router bgp ASN */ + vty_out(vty, "router bgp %u", bgp->as); + + if (bgp_option_check(BGP_OPT_MULTIPLE_INSTANCE)) { + if (bgp->name) + vty_out(vty, " %s %s", + (bgp->inst_type + == BGP_INSTANCE_TYPE_VIEW) + ? "view" + : "vrf", + bgp->name); + } + vty_out(vty, "\n"); + + /* No Synchronization */ + if (bgp_option_check(BGP_OPT_CONFIG_CISCO)) + vty_out(vty, " no synchronization\n"); + + /* BGP fast-external-failover. */ + if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER)) + vty_out(vty, " no bgp fast-external-failover\n"); + + /* BGP router ID. */ + if (bgp->router_id_static.s_addr != 0) + vty_out(vty, " bgp router-id %s\n", + inet_ntoa(bgp->router_id_static)); + + /* BGP log-neighbor-changes. */ + if (!!bgp_flag_check(bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES) + != DFLT_BGP_LOG_NEIGHBOR_CHANGES) + vty_out(vty, " %sbgp log-neighbor-changes\n", + bgp_flag_check(bgp, + BGP_FLAG_LOG_NEIGHBOR_CHANGES) + ? "" + : "no "); + + /* BGP configuration. */ + if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED)) + vty_out(vty, " bgp always-compare-med\n"); + + /* BGP default ipv4-unicast. */ + if (bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4)) + vty_out(vty, " no bgp default ipv4-unicast\n"); + + /* BGP default local-preference. */ + if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF) + vty_out(vty, " bgp default local-preference %u\n", + bgp->default_local_pref); + + /* BGP default show-hostname */ + if (!!bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME) + != DFLT_BGP_SHOW_HOSTNAME) + vty_out(vty, " %sbgp default show-hostname\n", + bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME) + ? "" + : "no "); + + /* BGP default subgroup-pkt-queue-max. */ + if (bgp->default_subgroup_pkt_queue_max + != BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX) + vty_out(vty, " bgp default subgroup-pkt-queue-max %u\n", + bgp->default_subgroup_pkt_queue_max); + + /* BGP client-to-client reflection. */ + if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT)) + vty_out(vty, " no bgp client-to-client reflection\n"); + + /* BGP cluster ID. */ + if (CHECK_FLAG(bgp->config, BGP_CONFIG_CLUSTER_ID)) + vty_out(vty, " bgp cluster-id %s\n", + inet_ntoa(bgp->cluster_id)); + + /* Disable ebgp connected nexthop check */ + if (bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) + vty_out(vty, + " bgp disable-ebgp-connected-route-check\n"); + + /* Confederation identifier*/ + if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) + vty_out(vty, " bgp confederation identifier %i\n", + bgp->confed_id); + + /* Confederation peer */ + if (bgp->confed_peers_cnt > 0) { + int i; + + vty_out(vty, " bgp confederation peers"); + + for (i = 0; i < bgp->confed_peers_cnt; i++) + vty_out(vty, " %u", bgp->confed_peers[i]); + + vty_out(vty, "\n"); + } - /* BGP configuration. */ - for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) - { - if (write) - vty_out (vty, "!\n"); + /* BGP enforce-first-as. */ + if (bgp_flag_check(bgp, BGP_FLAG_ENFORCE_FIRST_AS)) + vty_out(vty, " bgp enforce-first-as\n"); + + /* BGP deterministic-med. */ + if (!!bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED) + != DFLT_BGP_DETERMINISTIC_MED) + vty_out(vty, " %sbgp deterministic-med\n", + bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED) + ? "" + : "no "); + + /* BGP update-delay. */ + bgp_config_write_update_delay(vty, bgp); + + if (bgp->v_maxmed_onstartup + != BGP_MAXMED_ONSTARTUP_UNCONFIGURED) { + vty_out(vty, " bgp max-med on-startup %u", + bgp->v_maxmed_onstartup); + if (bgp->maxmed_onstartup_value + != BGP_MAXMED_VALUE_DEFAULT) + vty_out(vty, " %u", + bgp->maxmed_onstartup_value); + vty_out(vty, "\n"); + } + if (bgp->v_maxmed_admin != BGP_MAXMED_ADMIN_UNCONFIGURED) { + vty_out(vty, " bgp max-med administrative"); + if (bgp->maxmed_admin_value != BGP_MAXMED_VALUE_DEFAULT) + vty_out(vty, " %u", bgp->maxmed_admin_value); + vty_out(vty, "\n"); + } - /* Router bgp ASN */ - vty_out (vty, "router bgp %u", bgp->as); + /* write quanta */ + bgp_config_write_wpkt_quanta(vty, bgp); + + /* coalesce time */ + bgp_config_write_coalesce_time(vty, bgp); + + /* BGP graceful-restart. */ + if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME) + vty_out(vty, + " bgp graceful-restart stalepath-time %u\n", + bgp->stalepath_time); + if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME) + vty_out(vty, " bgp graceful-restart restart-time %u\n", + bgp->restart_time); + if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_RESTART)) + vty_out(vty, " bgp graceful-restart\n"); + + /* BGP graceful-restart Preserve State F bit. */ + if (bgp_flag_check(bgp, BGP_FLAG_GR_PRESERVE_FWD)) + vty_out(vty, + " bgp graceful-restart preserve-fw-state\n"); + + /* BGP bestpath method. */ + if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE)) + vty_out(vty, " bgp bestpath as-path ignore\n"); + if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED)) + vty_out(vty, " bgp bestpath as-path confed\n"); + + if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) { + if (bgp_flag_check(bgp, + BGP_FLAG_MULTIPATH_RELAX_AS_SET)) { + vty_out(vty, + " bgp bestpath as-path multipath-relax as-set\n"); + } else { + vty_out(vty, + " bgp bestpath as-path multipath-relax\n"); + } + } - if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE)) - { - if (bgp->name) - vty_out (vty, " %s %s", - (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) ? - "view" : "vrf", bgp->name); - } - vty_out (vty, "\n"); - - /* No Synchronization */ - if (bgp_option_check (BGP_OPT_CONFIG_CISCO)) - vty_out (vty, " no synchronization\n"); - - /* BGP fast-external-failover. */ - if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER)) - vty_out (vty, " no bgp fast-external-failover\n"); - - /* BGP router ID. */ - if (bgp->router_id_static.s_addr != 0) - vty_out (vty, " bgp router-id %s\n", - inet_ntoa(bgp->router_id_static)); - - /* BGP log-neighbor-changes. */ - if (!!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES) - != DFLT_BGP_LOG_NEIGHBOR_CHANGES) - vty_out (vty, " %sbgp log-neighbor-changes\n", - bgp_flag_check(bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES) ? "" : "no "); - - /* BGP configuration. */ - if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED)) - vty_out (vty, " bgp always-compare-med\n"); - - /* BGP default ipv4-unicast. */ - if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)) - vty_out (vty, " no bgp default ipv4-unicast\n"); - - /* BGP default local-preference. */ - if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF) - vty_out (vty, " bgp default local-preference %u\n", - bgp->default_local_pref); - - /* BGP default show-hostname */ - if (!!bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME) - != DFLT_BGP_SHOW_HOSTNAME) - vty_out (vty, " %sbgp default show-hostname\n", - bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME) ? "" : "no "); - - /* BGP default subgroup-pkt-queue-max. */ - if (bgp->default_subgroup_pkt_queue_max != BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX) - vty_out (vty, " bgp default subgroup-pkt-queue-max %u\n", - bgp->default_subgroup_pkt_queue_max); - - /* BGP client-to-client reflection. */ - if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT)) - vty_out (vty, " no bgp client-to-client reflection\n"); - - /* BGP cluster ID. */ - if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID)) - vty_out (vty, " bgp cluster-id %s\n",inet_ntoa(bgp->cluster_id)); - - /* Disable ebgp connected nexthop check */ - if (bgp_flag_check (bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) - vty_out (vty, " bgp disable-ebgp-connected-route-check\n"); - - /* Confederation identifier*/ - if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION)) - vty_out (vty, " bgp confederation identifier %i\n",bgp->confed_id); - - /* Confederation peer */ - if (bgp->confed_peers_cnt > 0) - { - int i; - - vty_out (vty, " bgp confederation peers"); - - for (i = 0; i < bgp->confed_peers_cnt; i++) - vty_out(vty, " %u", bgp->confed_peers[i]); - - vty_out (vty, "\n"); - } - - /* BGP enforce-first-as. */ - if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS)) - vty_out (vty, " bgp enforce-first-as\n"); - - /* BGP deterministic-med. */ - if (!!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED) - != DFLT_BGP_DETERMINISTIC_MED) - vty_out (vty, " %sbgp deterministic-med\n", - bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED) ? "" : "no "); - - /* BGP update-delay. */ - bgp_config_write_update_delay (vty, bgp); - - if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED) - { - vty_out (vty, " bgp max-med on-startup %u", bgp->v_maxmed_onstartup); - if (bgp->maxmed_onstartup_value != BGP_MAXMED_VALUE_DEFAULT) - vty_out (vty, " %u", bgp->maxmed_onstartup_value); - vty_out (vty, "\n"); - } - if (bgp->v_maxmed_admin != BGP_MAXMED_ADMIN_UNCONFIGURED) - { - vty_out (vty, " bgp max-med administrative"); - if (bgp->maxmed_admin_value != BGP_MAXMED_VALUE_DEFAULT) - vty_out (vty, " %u", bgp->maxmed_admin_value); - vty_out (vty, "\n"); - } - - /* write quanta */ - bgp_config_write_wpkt_quanta (vty, bgp); - - /* coalesce time */ - bgp_config_write_coalesce_time(vty, bgp); - - /* BGP graceful-restart. */ - if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME) - vty_out (vty, " bgp graceful-restart stalepath-time %u\n", - bgp->stalepath_time); - if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME) - vty_out (vty, " bgp graceful-restart restart-time %u\n", - bgp->restart_time); - if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART)) - vty_out (vty, " bgp graceful-restart\n"); - - /* BGP graceful-restart Preserve State F bit. */ - if (bgp_flag_check (bgp, BGP_FLAG_GR_PRESERVE_FWD)) - vty_out (vty, " bgp graceful-restart preserve-fw-state\n"); - - /* BGP bestpath method. */ - if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE)) - vty_out (vty, " bgp bestpath as-path ignore\n"); - if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED)) - vty_out (vty, " bgp bestpath as-path confed\n"); - - if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) - { - if (bgp_flag_check (bgp, BGP_FLAG_MULTIPATH_RELAX_AS_SET)) - { - vty_out (vty, - " bgp bestpath as-path multipath-relax as-set\n"); - } - else - { - vty_out (vty, " bgp bestpath as-path multipath-relax\n"); - } - } - - if (bgp_flag_check (bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) { - vty_out (vty," bgp route-reflector allow-outbound-policy\n"); - } - if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID)) - vty_out (vty, " bgp bestpath compare-routerid\n"); - if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED) - || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST)) - { - vty_out (vty, " bgp bestpath med"); - if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)) - vty_out (vty, " confed"); - if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST)) - vty_out (vty, " missing-as-worst"); - vty_out (vty, "\n"); - } - - /* BGP network import check. */ - if (!!bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK) - != DFLT_BGP_IMPORT_CHECK) - vty_out (vty, " %sbgp network import-check\n", - bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK) ? "" : "no "); - - /* BGP flag dampening. */ - if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST], - BGP_CONFIG_DAMPENING)) - bgp_config_write_damp (vty); - - /* BGP timers configuration. */ - if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE - && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME) - vty_out (vty, " timers bgp %u %u\n", bgp->default_keepalive, - bgp->default_holdtime); - - /* peer-group */ - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - { - bgp_config_write_peer_global (vty, bgp, group->conf); - } + if (bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) { + vty_out(vty, + " bgp route-reflector allow-outbound-policy\n"); + } + if (bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID)) + vty_out(vty, " bgp bestpath compare-routerid\n"); + if (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED) + || bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST)) { + vty_out(vty, " bgp bestpath med"); + if (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED)) + vty_out(vty, " confed"); + if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST)) + vty_out(vty, " missing-as-worst"); + vty_out(vty, "\n"); + } - /* Normal neighbor configuration. */ - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)) - bgp_config_write_peer_global (vty, bgp, peer); - } + /* BGP network import check. */ + if (!!bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK) + != DFLT_BGP_IMPORT_CHECK) + vty_out(vty, " %sbgp network import-check\n", + bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK) + ? "" + : "no "); + + /* BGP flag dampening. */ + if (CHECK_FLAG(bgp->af_flags[AFI_IP][SAFI_UNICAST], + BGP_CONFIG_DAMPENING)) + bgp_config_write_damp(vty); + + /* BGP timers configuration. */ + if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE + && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME) + vty_out(vty, " timers bgp %u %u\n", + bgp->default_keepalive, bgp->default_holdtime); + + /* peer-group */ + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) { + bgp_config_write_peer_global(vty, bgp, group->conf); + } + + /* Normal neighbor configuration. */ + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) + bgp_config_write_peer_global(vty, bgp, peer); + } - /* listen range and limit for dynamic BGP neighbors */ - bgp_config_write_listen (vty, bgp); + /* listen range and limit for dynamic BGP neighbors */ + bgp_config_write_listen(vty, bgp); - /* No auto-summary */ - if (bgp_option_check (BGP_OPT_CONFIG_CISCO)) - vty_out (vty, " no auto-summary\n"); + /* No auto-summary */ + if (bgp_option_check(BGP_OPT_CONFIG_CISCO)) + vty_out(vty, " no auto-summary\n"); - /* IPv4 unicast configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_UNICAST); + /* IPv4 unicast configuration. */ + write += + bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST); - /* IPv4 multicast configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST); + /* IPv4 multicast configuration. */ + write += bgp_config_write_family(vty, bgp, AFI_IP, + SAFI_MULTICAST); - /* IPv4 labeled-unicast configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_LABELED_UNICAST); + /* IPv4 labeled-unicast configuration. */ + write += bgp_config_write_family(vty, bgp, AFI_IP, + SAFI_LABELED_UNICAST); - /* IPv4 VPN configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN); + /* IPv4 VPN configuration. */ + write += bgp_config_write_family(vty, bgp, AFI_IP, + SAFI_MPLS_VPN); - /* ENCAPv4 configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_ENCAP); + /* ENCAPv4 configuration. */ + write += bgp_config_write_family(vty, bgp, AFI_IP, SAFI_ENCAP); - /* IPv6 unicast configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST); + /* IPv6 unicast configuration. */ + write += bgp_config_write_family(vty, bgp, AFI_IP6, + SAFI_UNICAST); - /* IPv6 multicast configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST); + /* IPv6 multicast configuration. */ + write += bgp_config_write_family(vty, bgp, AFI_IP6, + SAFI_MULTICAST); - /* IPv6 labeled-unicast configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_LABELED_UNICAST); + /* IPv6 labeled-unicast configuration. */ + write += bgp_config_write_family(vty, bgp, AFI_IP6, + SAFI_LABELED_UNICAST); - /* IPv6 VPN configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MPLS_VPN); + /* IPv6 VPN configuration. */ + write += bgp_config_write_family(vty, bgp, AFI_IP6, + SAFI_MPLS_VPN); - /* ENCAPv6 configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_ENCAP); + /* ENCAPv6 configuration. */ + write += bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_ENCAP); - /* EVPN configuration. */ - write += bgp_config_write_family (vty, bgp, AFI_L2VPN, SAFI_EVPN); + /* EVPN configuration. */ + write += + bgp_config_write_family(vty, bgp, AFI_L2VPN, SAFI_EVPN); #if ENABLE_BGP_VNC - write += bgp_rfapi_cfg_write(vty, bgp); + write += bgp_rfapi_cfg_write(vty, bgp); #endif - write++; - } - return write; + write++; + } + return write; } -void -bgp_master_init (struct thread_master *master) +void bgp_master_init(struct thread_master *master) { - qobj_init (); + qobj_init(); - memset (&bgp_master, 0, sizeof (struct bgp_master)); + memset(&bgp_master, 0, sizeof(struct bgp_master)); - bm = &bgp_master; - bm->bgp = list_new (); - bm->listen_sockets = list_new (); - bm->port = BGP_PORT_DEFAULT; - bm->master = master; - bm->start_time = bgp_clock (); - bm->t_rmap_update = NULL; - bm->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER; + bm = &bgp_master; + bm->bgp = list_new(); + bm->listen_sockets = list_new(); + bm->port = BGP_PORT_DEFAULT; + bm->master = master; + bm->start_time = bgp_clock(); + bm->t_rmap_update = NULL; + bm->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER; - bgp_process_queue_init(); + bgp_process_queue_init(); - /* Enable multiple instances by default. */ - bgp_option_set (BGP_OPT_MULTIPLE_INSTANCE); + /* Enable multiple instances by default. */ + bgp_option_set(BGP_OPT_MULTIPLE_INSTANCE); - QOBJ_REG (bm, bgp_master); + QOBJ_REG(bm, bgp_master); } /* * Free up connected routes and interfaces for a BGP instance. Invoked upon * instance delete (non-default only) or BGP exit. */ -static void -bgp_if_finish (struct bgp *bgp) +static void bgp_if_finish(struct bgp *bgp) { - struct listnode *ifnode, *ifnnode; - struct interface *ifp; - - if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) - return; + struct listnode *ifnode, *ifnnode; + struct interface *ifp; + + if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) + return; - for (ALL_LIST_ELEMENTS (vrf_iflist(bgp->vrf_id), ifnode, ifnnode, ifp)) - { - struct listnode *c_node, *c_nnode; - struct connected *c; + for (ALL_LIST_ELEMENTS(vrf_iflist(bgp->vrf_id), ifnode, ifnnode, ifp)) { + struct listnode *c_node, *c_nnode; + struct connected *c; - for (ALL_LIST_ELEMENTS (ifp->connected, c_node, c_nnode, c)) - bgp_connected_delete (bgp, c); - } + for (ALL_LIST_ELEMENTS(ifp->connected, c_node, c_nnode, c)) + bgp_connected_delete(bgp, c); + } } -extern void bgp_snmp_init (void); +extern void bgp_snmp_init(void); -static void -bgp_viewvrf_autocomplete (vector comps, struct cmd_token *token) +static void bgp_viewvrf_autocomplete(vector comps, struct cmd_token *token) { - struct vrf *vrf = NULL; - struct listnode *next; - struct bgp *bgp; + struct vrf *vrf = NULL; + struct listnode *next; + struct bgp *bgp; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if (vrf->vrf_id != VRF_DEFAULT) - vector_set (comps, XSTRDUP (MTYPE_COMPLETION, vrf->name)); - } + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if (vrf->vrf_id != VRF_DEFAULT) + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name)); + } - for (ALL_LIST_ELEMENTS_RO (bm->bgp, next, bgp)) - { - if (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW) - continue; + for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) { + if (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW) + continue; - vector_set (comps, XSTRDUP (MTYPE_COMPLETION, bgp->name)); - } + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, bgp->name)); + } } static const struct cmd_variable_handler bgp_viewvrf_var_handlers[] = { - { - .tokenname = "VIEWVRFNAME", - .completions = bgp_viewvrf_autocomplete - }, - { - .completions = NULL - }, + {.tokenname = "VIEWVRFNAME", .completions = bgp_viewvrf_autocomplete}, + {.completions = NULL}, }; -void -bgp_init (void) +void bgp_init(void) { - /* allocates some vital data structures used by peer commands in vty_init */ + /* allocates some vital data structures used by peer commands in + * vty_init */ - /* Init zebra. */ - bgp_zebra_init(bm->master); + /* Init zebra. */ + bgp_zebra_init(bm->master); #if ENABLE_BGP_VNC - vnc_zebra_init (bm->master); + vnc_zebra_init(bm->master); #endif - /* BGP VTY commands installation. */ - bgp_vty_init (); - - /* BGP inits. */ - bgp_attr_init (); - bgp_debug_init (); - bgp_dump_init (); - bgp_route_init (); - bgp_route_map_init (); - bgp_scan_vty_init(); - bgp_mplsvpn_init (); + /* BGP VTY commands installation. */ + bgp_vty_init(); + + /* BGP inits. */ + bgp_attr_init(); + bgp_debug_init(); + bgp_dump_init(); + bgp_route_init(); + bgp_route_map_init(); + bgp_scan_vty_init(); + bgp_mplsvpn_init(); #if ENABLE_BGP_VNC - rfapi_init (); + rfapi_init(); #endif - bgp_ethernetvpn_init (); - - /* Access list initialize. */ - access_list_init (); - access_list_add_hook (peer_distribute_update); - access_list_delete_hook (peer_distribute_update); - - /* Filter list initialize. */ - bgp_filter_init (); - as_list_add_hook (peer_aslist_add); - as_list_delete_hook (peer_aslist_del); - - /* Prefix list initialize.*/ - prefix_list_init (); - prefix_list_add_hook (peer_prefix_list_update); - prefix_list_delete_hook (peer_prefix_list_update); - - /* Community list initialize. */ - bgp_clist = community_list_init (); - - /* BFD init */ - bgp_bfd_init(); - - cmd_variable_handler_register (bgp_viewvrf_var_handlers); -} - -void -bgp_terminate (void) -{ - struct bgp *bgp; - struct peer *peer; - struct listnode *node, *nnode; - struct listnode *mnode, *mnnode; - - QOBJ_UNREG (bm); - - /* Close the listener sockets first as this prevents peers from attempting - * to reconnect on receiving the peer unconfig message. In the presence - * of a large number of peers this will ensure that no peer is left with - * a dangling connection - */ - /* reverse bgp_master_init */ - bgp_close(); - if (bm->listen_sockets) - list_free(bm->listen_sockets); - bm->listen_sockets = NULL; - - for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - if (peer->status == Established || - peer->status == OpenSent || - peer->status == OpenConfirm) - bgp_notify_send (peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_PEER_UNCONFIG); - - if (bm->process_main_queue) - { - work_queue_free (bm->process_main_queue); - bm->process_main_queue = NULL; - } - - if (bm->t_rmap_update) - BGP_TIMER_OFF(bm->t_rmap_update); + bgp_ethernetvpn_init(); + + /* Access list initialize. */ + access_list_init(); + access_list_add_hook(peer_distribute_update); + access_list_delete_hook(peer_distribute_update); + + /* Filter list initialize. */ + bgp_filter_init(); + as_list_add_hook(peer_aslist_add); + as_list_delete_hook(peer_aslist_del); + + /* Prefix list initialize.*/ + prefix_list_init(); + prefix_list_add_hook(peer_prefix_list_update); + prefix_list_delete_hook(peer_prefix_list_update); + + /* Community list initialize. */ + bgp_clist = community_list_init(); + + /* BFD init */ + bgp_bfd_init(); + + cmd_variable_handler_register(bgp_viewvrf_var_handlers); +} + +void bgp_terminate(void) +{ + struct bgp *bgp; + struct peer *peer; + struct listnode *node, *nnode; + struct listnode *mnode, *mnnode; + + QOBJ_UNREG(bm); + + /* Close the listener sockets first as this prevents peers from + * attempting + * to reconnect on receiving the peer unconfig message. In the presence + * of a large number of peers this will ensure that no peer is left with + * a dangling connection + */ + /* reverse bgp_master_init */ + bgp_close(); + if (bm->listen_sockets) + list_free(bm->listen_sockets); + bm->listen_sockets = NULL; + + for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) + if (peer->status == Established + || peer->status == OpenSent + || peer->status == OpenConfirm) + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_PEER_UNCONFIG); + + if (bm->process_main_queue) { + work_queue_free(bm->process_main_queue); + bm->process_main_queue = NULL; + } + + if (bm->t_rmap_update) + BGP_TIMER_OFF(bm->t_rmap_update); } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 31aa6163b..67b8289c7 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -45,14 +45,14 @@ struct bpacket; /* * Allow the neighbor XXXX remote-as to take internal or external - * AS_SPECIFIED is zero to auto-inherit original non-feature/enhancement behavior + * AS_SPECIFIED is zero to auto-inherit original non-feature/enhancement + * behavior * in the system. */ -enum { - AS_UNSPECIFIED = 0, - AS_SPECIFIED, - AS_INTERNAL, - AS_EXTERNAL, +enum { AS_UNSPECIFIED = 0, + AS_SPECIFIED, + AS_INTERNAL, + AS_EXTERNAL, }; /* Typedef BGP specific types. */ @@ -60,95 +60,94 @@ typedef u_int32_t as_t; typedef u_int16_t as16_t; /* we may still encounter 16 Bit asnums */ typedef u_int16_t bgp_size_t; -#define max(a,b) \ - ({ __typeof__ (a) _a = (a); \ - __typeof__ (b) _b = (b); \ - _a > _b ? _a : _b; }) - -enum bgp_af_index -{ - BGP_AF_START, - BGP_AF_IPV4_UNICAST = BGP_AF_START, - BGP_AF_IPV4_MULTICAST, - BGP_AF_IPV4_VPN, - BGP_AF_IPV6_UNICAST, - BGP_AF_IPV6_MULTICAST, - BGP_AF_IPV6_VPN, - BGP_AF_IPV4_ENCAP, - BGP_AF_IPV6_ENCAP, - BGP_AF_L2VPN_EVPN, - BGP_AF_IPV4_LBL_UNICAST, - BGP_AF_IPV6_LBL_UNICAST, - BGP_AF_MAX +#define max(a, b) \ + ({ \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a > _b ? _a : _b; \ + }) + +enum bgp_af_index { + BGP_AF_START, + BGP_AF_IPV4_UNICAST = BGP_AF_START, + BGP_AF_IPV4_MULTICAST, + BGP_AF_IPV4_VPN, + BGP_AF_IPV6_UNICAST, + BGP_AF_IPV6_MULTICAST, + BGP_AF_IPV6_VPN, + BGP_AF_IPV4_ENCAP, + BGP_AF_IPV6_ENCAP, + BGP_AF_L2VPN_EVPN, + BGP_AF_IPV4_LBL_UNICAST, + BGP_AF_IPV6_LBL_UNICAST, + BGP_AF_MAX }; -#define AF_FOREACH(af) \ - for ((af) = BGP_AF_START; (af) < BGP_AF_MAX; (af)++) +#define AF_FOREACH(af) for ((af) = BGP_AF_START; (af) < BGP_AF_MAX; (af)++) -#define FOREACH_AFI_SAFI(afi, safi) \ - for (afi = AFI_IP; afi < AFI_MAX; afi++) \ - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) +#define FOREACH_AFI_SAFI(afi, safi) \ + for (afi = AFI_IP; afi < AFI_MAX; afi++) \ + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) /* BGP master for system wide configurations and variables. */ -struct bgp_master -{ - /* BGP instance list. */ - struct list *bgp; +struct bgp_master { + /* BGP instance list. */ + struct list *bgp; + + /* BGP thread master. */ + struct thread_master *master; - /* BGP thread master. */ - struct thread_master *master; + /* work queues */ + struct work_queue *process_main_queue; - /* work queues */ - struct work_queue *process_main_queue; - - /* Listening sockets */ - struct list *listen_sockets; - - /* BGP port number. */ - u_int16_t port; + /* Listening sockets */ + struct list *listen_sockets; - /* Listener address */ - char *address; + /* BGP port number. */ + u_int16_t port; - /* BGP start time. */ - time_t start_time; + /* Listener address */ + char *address; - /* Various BGP global configuration. */ - u_char options; + /* BGP start time. */ + time_t start_time; + + /* Various BGP global configuration. */ + u_char options; #define BGP_OPT_NO_FIB (1 << 0) #define BGP_OPT_MULTIPLE_INSTANCE (1 << 1) #define BGP_OPT_CONFIG_CISCO (1 << 2) #define BGP_OPT_NO_LISTEN (1 << 3) - uint64_t updgrp_idspace; - uint64_t subgrp_idspace; + uint64_t updgrp_idspace; + uint64_t subgrp_idspace; - /* timer to dampen route map changes */ - struct thread *t_rmap_update; /* Handle route map updates */ - u_int32_t rmap_update_timer; /* Route map update timer */ + /* timer to dampen route map changes */ + struct thread *t_rmap_update; /* Handle route map updates */ + u_int32_t rmap_update_timer; /* Route map update timer */ + /* $FRR indent$ */ + /* clang-format off */ #define RMAP_DEFAULT_UPDATE_TIMER 5 /* disabled by default */ - QOBJ_FIELDS + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(bgp_master) /* BGP route-map structure. */ -struct bgp_rmap -{ - char *name; - struct route_map *map; +struct bgp_rmap { + char *name; + struct route_map *map; }; -struct bgp_redist -{ - u_short instance; +struct bgp_redist { + u_short instance; - /* BGP redistribute metric configuration. */ - u_char redist_metric_flag; - u_int32_t redist_metric; + /* BGP redistribute metric configuration. */ + u_char redist_metric_flag; + u_int32_t redist_metric; - /* BGP redistribute route-map. */ - struct bgp_rmap rmap; + /* BGP redistribute route-map. */ + struct bgp_rmap rmap; }; /* @@ -159,122 +158,129 @@ struct bgp_redist * The "default" instance is treated separately to simplify the code. Note * that if deployed in a Multi-VRF environment, it may not exist. */ -enum bgp_instance_type -{ - BGP_INSTANCE_TYPE_DEFAULT, - BGP_INSTANCE_TYPE_VRF, - BGP_INSTANCE_TYPE_VIEW +enum bgp_instance_type { + BGP_INSTANCE_TYPE_DEFAULT, + BGP_INSTANCE_TYPE_VRF, + BGP_INSTANCE_TYPE_VIEW }; /* BGP instance structure. */ -struct bgp -{ - /* AS number of this BGP instance. */ - as_t as; - - /* Name of this BGP instance. */ - char *name; - - /* Type of instance and VRF id. */ - enum bgp_instance_type inst_type; - vrf_id_t vrf_id; - - /* Reference count to allow peer_delete to finish after bgp_delete */ - int lock; - - /* Self peer. */ - struct peer *peer_self; - - /* BGP peer. */ - struct list *peer; - struct hash *peerhash; - - /* BGP peer group. */ - struct list *group; - - /* The maximum number of BGP dynamic neighbors that can be created */ - int dynamic_neighbors_limit; - - /* The current number of BGP dynamic neighbors */ - int dynamic_neighbors_count; - - struct hash *update_groups[BGP_AF_MAX]; - - /* - * Global statistics for update groups. - */ - struct { - u_int32_t join_events; - u_int32_t prune_events; - u_int32_t merge_events; - u_int32_t split_events; - u_int32_t updgrp_switch_events; - u_int32_t peer_refreshes_combined; - u_int32_t adj_count; - u_int32_t merge_checks_triggered; - - u_int32_t updgrps_created; - u_int32_t updgrps_deleted; - u_int32_t subgrps_created; - u_int32_t subgrps_deleted; - } update_group_stats; - - /* BGP configuration. */ - u_int16_t config; +struct bgp { + /* AS number of this BGP instance. */ + as_t as; + + /* Name of this BGP instance. */ + char *name; + + /* Type of instance and VRF id. */ + enum bgp_instance_type inst_type; + vrf_id_t vrf_id; + + /* Reference count to allow peer_delete to finish after bgp_delete */ + int lock; + + /* Self peer. */ + struct peer *peer_self; + + /* BGP peer. */ + struct list *peer; + struct hash *peerhash; + + /* BGP peer group. */ + struct list *group; + + /* The maximum number of BGP dynamic neighbors that can be created */ + int dynamic_neighbors_limit; + + /* The current number of BGP dynamic neighbors */ + int dynamic_neighbors_count; + + struct hash *update_groups[BGP_AF_MAX]; + + /* + * Global statistics for update groups. + */ + struct { + u_int32_t join_events; + u_int32_t prune_events; + u_int32_t merge_events; + u_int32_t split_events; + u_int32_t updgrp_switch_events; + u_int32_t peer_refreshes_combined; + u_int32_t adj_count; + u_int32_t merge_checks_triggered; + + u_int32_t updgrps_created; + u_int32_t updgrps_deleted; + u_int32_t subgrps_created; + u_int32_t subgrps_deleted; + } update_group_stats; + + /* BGP configuration. */ + u_int16_t config; #define BGP_CONFIG_CLUSTER_ID (1 << 0) #define BGP_CONFIG_CONFEDERATION (1 << 1) - /* BGP router identifier. */ - struct in_addr router_id; - struct in_addr router_id_static; - struct in_addr router_id_zebra; + /* BGP router identifier. */ + struct in_addr router_id; + struct in_addr router_id_static; + struct in_addr router_id_zebra; - /* BGP route reflector cluster ID. */ - struct in_addr cluster_id; + /* BGP route reflector cluster ID. */ + struct in_addr cluster_id; - /* BGP confederation information. */ - as_t confed_id; - as_t *confed_peers; - int confed_peers_cnt; + /* BGP confederation information. */ + as_t confed_id; + as_t *confed_peers; + int confed_peers_cnt; - struct thread *t_startup; /* start-up timer on only once at the beginning */ + struct thread + *t_startup; /* start-up timer on only once at the beginning */ - u_int32_t v_maxmed_onstartup; /* Duration of max-med on start-up */ + u_int32_t v_maxmed_onstartup; /* Duration of max-med on start-up */ + /* $FRR indent$ */ + /* clang-format off */ #define BGP_MAXMED_ONSTARTUP_UNCONFIGURED 0 /* 0 means off, its the default */ - u_int32_t maxmed_onstartup_value; /* Max-med value when active on start-up */ - struct thread *t_maxmed_onstartup; /* non-null when max-med onstartup is on */ - u_char maxmed_onstartup_over; /* Flag to make it effective only once */ - - u_char v_maxmed_admin; /* 1/0 if max-med administrative is on/off */ + u_int32_t maxmed_onstartup_value; /* Max-med value when active on + start-up */ + struct thread + *t_maxmed_onstartup; /* non-null when max-med onstartup is on */ + u_char maxmed_onstartup_over; /* Flag to make it effective only once */ + + u_char v_maxmed_admin; /* 1/0 if max-med administrative is on/off */ + /* $FRR indent$ */ + /* clang-format off */ #define BGP_MAXMED_ADMIN_UNCONFIGURED 0 /* Off by default */ - u_int32_t maxmed_admin_value; /* Max-med value when administrative in on */ + u_int32_t + maxmed_admin_value; /* Max-med value when administrative in on + */ #define BGP_MAXMED_VALUE_DEFAULT 4294967294 /* Maximum by default */ - u_char maxmed_active; /* 1/0 if max-med is active or not */ - u_int32_t maxmed_value; /* Max-med value when its active */ - - /* BGP update delay on startup */ - struct thread *t_update_delay; - struct thread *t_establish_wait; - u_char update_delay_over; - u_char main_zebra_update_hold; - u_char main_peers_update_hold; - u_int16_t v_update_delay; - u_int16_t v_establish_wait; - char update_delay_begin_time[64]; - char update_delay_end_time[64]; - char update_delay_zebra_resume_time[64]; - char update_delay_peers_resume_time[64]; - u_int32_t established; - u_int32_t restarted_peers; - u_int32_t implicit_eors; - u_int32_t explicit_eors; + u_char maxmed_active; /* 1/0 if max-med is active or not */ + u_int32_t maxmed_value; /* Max-med value when its active */ + + /* BGP update delay on startup */ + struct thread *t_update_delay; + struct thread *t_establish_wait; + u_char update_delay_over; + u_char main_zebra_update_hold; + u_char main_peers_update_hold; + u_int16_t v_update_delay; + u_int16_t v_establish_wait; + char update_delay_begin_time[64]; + char update_delay_end_time[64]; + char update_delay_zebra_resume_time[64]; + char update_delay_peers_resume_time[64]; + u_int32_t established; + u_int32_t restarted_peers; + u_int32_t implicit_eors; + u_int32_t explicit_eors; #define BGP_UPDATE_DELAY_DEF 0 #define BGP_UPDATE_DELAY_MIN 0 #define BGP_UPDATE_DELAY_MAX 3600 - /* BGP flags. */ - u_int32_t flags; + /* BGP flags. */ + u_int32_t flags; #define BGP_FLAG_ALWAYS_COMPARE_MED (1 << 0) #define BGP_FLAG_DETERMINISTIC_MED (1 << 1) #define BGP_FLAG_MED_MISSING_AS_WORST (1 << 2) @@ -297,137 +303,135 @@ struct bgp #define BGP_FLAG_SHOW_HOSTNAME (1 << 19) #define BGP_FLAG_GR_PRESERVE_FWD (1 << 20) - /* BGP Per AF flags */ - u_int16_t af_flags[AFI_MAX][SAFI_MAX]; + /* BGP Per AF flags */ + u_int16_t af_flags[AFI_MAX][SAFI_MAX]; #define BGP_CONFIG_DAMPENING (1 << 0) - /* Route table for next-hop lookup cache. */ - struct bgp_table *nexthop_cache_table[AFI_MAX]; + /* Route table for next-hop lookup cache. */ + struct bgp_table *nexthop_cache_table[AFI_MAX]; - /* Route table for import-check */ - struct bgp_table *import_check_table[AFI_MAX]; + /* Route table for import-check */ + struct bgp_table *import_check_table[AFI_MAX]; - struct bgp_table *connected_table[AFI_MAX]; + struct bgp_table *connected_table[AFI_MAX]; - struct hash *address_hash; + struct hash *address_hash; - /* Static route configuration. */ - struct bgp_table *route[AFI_MAX][SAFI_MAX]; + /* Static route configuration. */ + struct bgp_table *route[AFI_MAX][SAFI_MAX]; - /* Aggregate address configuration. */ - struct bgp_table *aggregate[AFI_MAX][SAFI_MAX]; + /* Aggregate address configuration. */ + struct bgp_table *aggregate[AFI_MAX][SAFI_MAX]; - /* BGP routing information base. */ - struct bgp_table *rib[AFI_MAX][SAFI_MAX]; + /* BGP routing information base. */ + struct bgp_table *rib[AFI_MAX][SAFI_MAX]; - /* BGP table route-map. */ - struct bgp_rmap table_map[AFI_MAX][SAFI_MAX]; + /* BGP table route-map. */ + struct bgp_rmap table_map[AFI_MAX][SAFI_MAX]; - /* BGP redistribute configuration. */ - struct list *redist[AFI_MAX][ZEBRA_ROUTE_MAX]; + /* BGP redistribute configuration. */ + struct list *redist[AFI_MAX][ZEBRA_ROUTE_MAX]; - /* timer to re-evaluate neighbor default-originate route-maps */ - struct thread *t_rmap_def_originate_eval; + /* timer to re-evaluate neighbor default-originate route-maps */ + struct thread *t_rmap_def_originate_eval; #define RMAP_DEFAULT_ORIGINATE_EVAL_TIMER 5 - /* BGP distance configuration. */ - u_char distance_ebgp[AFI_MAX][SAFI_MAX]; - u_char distance_ibgp[AFI_MAX][SAFI_MAX]; - u_char distance_local[AFI_MAX][SAFI_MAX]; - - /* BGP default local-preference. */ - u_int32_t default_local_pref; - - /* BGP default subgroup pkt queue max */ - u_int32_t default_subgroup_pkt_queue_max; - - /* BGP default timer. */ - u_int32_t default_holdtime; - u_int32_t default_keepalive; - - /* BGP graceful restart */ - u_int32_t restart_time; - u_int32_t stalepath_time; - - /* Maximum-paths configuration */ - struct bgp_maxpaths_cfg { - u_int16_t maxpaths_ebgp; - u_int16_t maxpaths_ibgp; - u_int16_t ibgp_flags; + /* BGP distance configuration. */ + u_char distance_ebgp[AFI_MAX][SAFI_MAX]; + u_char distance_ibgp[AFI_MAX][SAFI_MAX]; + u_char distance_local[AFI_MAX][SAFI_MAX]; + + /* BGP default local-preference. */ + u_int32_t default_local_pref; + + /* BGP default subgroup pkt queue max */ + u_int32_t default_subgroup_pkt_queue_max; + + /* BGP default timer. */ + u_int32_t default_holdtime; + u_int32_t default_keepalive; + + /* BGP graceful restart */ + u_int32_t restart_time; + u_int32_t stalepath_time; + + /* Maximum-paths configuration */ + struct bgp_maxpaths_cfg { + u_int16_t maxpaths_ebgp; + u_int16_t maxpaths_ibgp; + u_int16_t ibgp_flags; #define BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN (1 << 0) - } maxpaths[AFI_MAX][SAFI_MAX]; + } maxpaths[AFI_MAX][SAFI_MAX]; - u_int32_t wpkt_quanta; /* per peer packet quanta to write */ - u_int32_t coalesce_time; + u_int32_t wpkt_quanta; /* per peer packet quanta to write */ + u_int32_t coalesce_time; - u_int32_t addpath_tx_id; - int addpath_tx_used[AFI_MAX][SAFI_MAX]; + u_int32_t addpath_tx_id; + int addpath_tx_used[AFI_MAX][SAFI_MAX]; #if ENABLE_BGP_VNC - struct rfapi_cfg *rfapi_cfg; - struct rfapi *rfapi; + struct rfapi_cfg *rfapi_cfg; + struct rfapi *rfapi; #endif - /* EVPN related information */ + /* EVPN related information */ - /* EVI hash table */ - struct hash *vnihash; + /* EVI hash table */ + struct hash *vnihash; - /* EVPN enable - advertise local VNIs and their MACs etc. */ - int advertise_all_vni; + /* EVPN enable - advertise local VNIs and their MACs etc. */ + int advertise_all_vni; - /* Hash table of Import RTs to EVIs */ - struct hash *import_rt_hash; + /* Hash table of Import RTs to EVIs */ + struct hash *import_rt_hash; - /* Id space for automatic RD derivation for an EVI */ - bitfield_t rd_idspace; + /* Id space for automatic RD derivation for an EVI */ + bitfield_t rd_idspace; - QOBJ_FIELDS + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(bgp) #define BGP_ROUTE_ADV_HOLD(bgp) (bgp->main_peers_update_hold) -#define IS_BGP_INST_KNOWN_TO_ZEBRA(bgp) \ - (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT || \ - (bgp->inst_type == BGP_INSTANCE_TYPE_VRF && bgp->vrf_id != VRF_UNKNOWN)) +#define IS_BGP_INST_KNOWN_TO_ZEBRA(bgp) \ + (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT \ + || (bgp->inst_type == BGP_INSTANCE_TYPE_VRF \ + && bgp->vrf_id != VRF_UNKNOWN)) /* BGP peer-group support. */ -struct peer_group -{ - /* Name of the peer-group. */ - char *name; +struct peer_group { + /* Name of the peer-group. */ + char *name; - /* Pointer to BGP. */ - struct bgp *bgp; - - /* Peer-group client list. */ - struct list *peer; + /* Pointer to BGP. */ + struct bgp *bgp; - /** Dynamic neighbor listening ranges */ - struct list *listen_range[AFI_MAX]; + /* Peer-group client list. */ + struct list *peer; - /* Peer-group config */ - struct peer *conf; + /** Dynamic neighbor listening ranges */ + struct list *listen_range[AFI_MAX]; + + /* Peer-group config */ + struct peer *conf; }; /* BGP Notify message format. */ -struct bgp_notify -{ - u_char code; - u_char subcode; - char *data; - bgp_size_t length; - u_char *raw_data; +struct bgp_notify { + u_char code; + u_char subcode; + char *data; + bgp_size_t length; + u_char *raw_data; }; /* Next hop self address. */ -struct bgp_nexthop -{ - struct interface *ifp; - struct in_addr v4; - struct in6_addr v6_global; - struct in6_addr v6_local; +struct bgp_nexthop { + struct interface *ifp; + struct in_addr v4; + struct in6_addr v6_global; + struct in6_addr v6_local; }; /* BGP addpath values */ @@ -440,9 +444,8 @@ struct bgp_nexthop /* BGP router distinguisher value. */ #define BGP_RD_SIZE 8 -struct bgp_rd -{ - u_char val[BGP_RD_SIZE]; +struct bgp_rd { + u_char val[BGP_RD_SIZE]; }; #define RMAP_IN 0 @@ -452,52 +455,45 @@ struct bgp_rd #include "filter.h" /* BGP filter structure. */ -struct bgp_filter -{ - /* Distribute-list. */ - struct - { - char *name; - struct access_list *alist; - } dlist[FILTER_MAX]; - - /* Prefix-list. */ - struct - { - char *name; - struct prefix_list *plist; - } plist[FILTER_MAX]; - - /* Filter-list. */ - struct - { - char *name; - struct as_list *aslist; - } aslist[FILTER_MAX]; - - /* Route-map. */ - struct - { - char *name; - struct route_map *map; - } map[RMAP_MAX]; - - /* Unsuppress-map. */ - struct - { - char *name; - struct route_map *map; - } usmap; +struct bgp_filter { + /* Distribute-list. */ + struct { + char *name; + struct access_list *alist; + } dlist[FILTER_MAX]; + + /* Prefix-list. */ + struct { + char *name; + struct prefix_list *plist; + } plist[FILTER_MAX]; + + /* Filter-list. */ + struct { + char *name; + struct as_list *aslist; + } aslist[FILTER_MAX]; + + /* Route-map. */ + struct { + char *name; + struct route_map *map; + } map[RMAP_MAX]; + + /* Unsuppress-map. */ + struct { + char *name; + struct route_map *map; + } usmap; }; /* IBGP/EBGP identifier. We also have a CONFED peer, which is to say, a peer who's AS is part of our Confederation. */ -typedef enum -{ - BGP_PEER_IBGP = 1, - BGP_PEER_EBGP, - BGP_PEER_INTERNAL, - BGP_PEER_CONFED, +typedef enum { + BGP_PEER_IBGP = 1, + BGP_PEER_EBGP, + BGP_PEER_INTERNAL, + BGP_PEER_CONFED, } bgp_peer_sort_t; /* BGP message header and packet size. */ @@ -512,132 +508,132 @@ typedef enum #define BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS 100 #define BGP_ANNOUNCE_ROUTE_DELAY_MS 500 -struct peer_af -{ - /* back pointer to the peer */ - struct peer *peer; +struct peer_af { + /* back pointer to the peer */ + struct peer *peer; - /* which subgroup the peer_af belongs to */ - struct update_subgroup *subgroup; + /* which subgroup the peer_af belongs to */ + struct update_subgroup *subgroup; - /* for being part of an update subgroup's peer list */ - LIST_ENTRY(peer_af) subgrp_train; + /* for being part of an update subgroup's peer list */ + LIST_ENTRY(peer_af) subgrp_train; - /* for being part of a packet's peer list */ - LIST_ENTRY(peer_af) pkt_train; + /* for being part of a packet's peer list */ + LIST_ENTRY(peer_af) pkt_train; - struct bpacket *next_pkt_to_send; + struct bpacket *next_pkt_to_send; - /* - * Trigger timer for bgp_announce_route(). - */ - struct thread *t_announce_route; + /* + * Trigger timer for bgp_announce_route(). + */ + struct thread *t_announce_route; - afi_t afi; - safi_t safi; - int afid; + afi_t afi; + safi_t safi; + int afid; }; /* BGP neighbor structure. */ -struct peer -{ - /* BGP structure. */ - struct bgp *bgp; - - /* reference count, primarily to allow bgp_process'ing of route_node's - * to be done after a struct peer is deleted. - * - * named 'lock' for hysterical reasons within Quagga. - */ - int lock; - - /* BGP peer group. */ - struct peer_group *group; - uint64_t version[AFI_MAX][SAFI_MAX]; - - /* BGP peer_af structures, per configured AF on this peer */ - struct peer_af *peer_af_array[BGP_AF_MAX]; - - /* Peer's remote AS number. */ - int as_type; - as_t as; - - /* Peer's local AS number. */ - as_t local_as; - - bgp_peer_sort_t sort; - - /* Peer's Change local AS number. */ - as_t change_local_as; - - /* Remote router ID. */ - struct in_addr remote_id; - - /* Local router ID. */ - struct in_addr local_id; - - /* Packet receive and send buffer. */ - struct stream *ibuf; - struct stream_fifo *obuf; - struct stream *work; - - /* We use a separate stream to encode MP_REACH_NLRI for efficient - * NLRI packing. peer->work stores all the other attributes. The - * actual packet is then constructed by concatenating the two. - */ - struct stream *scratch; - - /* the doppelganger peer structure, due to dual TCP conn setup */ - struct peer *doppelganger; - - /* Status of the peer. */ - int status; - int ostatus; - - /* FSM events, stored for debug purposes. - * Note: uchar used for reduced memory usage. - */ - unsigned char cur_event; - unsigned char last_event; - unsigned char last_major_event; - - /* Peer index, used for dumping TABLE_DUMP_V2 format */ - uint16_t table_dump_index; - - /* Peer information */ - int fd; /* File descriptor */ - int ttl; /* TTL of TCP connection to the peer. */ - int rtt; /* Estimated round-trip-time from TCP_INFO */ - int gtsm_hops; /* minimum hopcount to peer */ - char *desc; /* Description of the peer. */ - unsigned short port; /* Destination port for peer */ - char *host; /* Printable address of the peer. */ - union sockunion su; /* Sockunion address of the peer. */ +struct peer { + /* BGP structure. */ + struct bgp *bgp; + + /* reference count, primarily to allow bgp_process'ing of route_node's + * to be done after a struct peer is deleted. + * + * named 'lock' for hysterical reasons within Quagga. + */ + int lock; + + /* BGP peer group. */ + struct peer_group *group; + uint64_t version[AFI_MAX][SAFI_MAX]; + + /* BGP peer_af structures, per configured AF on this peer */ + struct peer_af *peer_af_array[BGP_AF_MAX]; + + /* Peer's remote AS number. */ + int as_type; + as_t as; + + /* Peer's local AS number. */ + as_t local_as; + + bgp_peer_sort_t sort; + + /* Peer's Change local AS number. */ + as_t change_local_as; + + /* Remote router ID. */ + struct in_addr remote_id; + + /* Local router ID. */ + struct in_addr local_id; + + /* Packet receive and send buffer. */ + struct stream *ibuf; + struct stream_fifo *obuf; + struct stream *work; + + /* We use a separate stream to encode MP_REACH_NLRI for efficient + * NLRI packing. peer->work stores all the other attributes. The + * actual packet is then constructed by concatenating the two. + */ + struct stream *scratch; + + /* the doppelganger peer structure, due to dual TCP conn setup */ + struct peer *doppelganger; + + /* Status of the peer. */ + int status; + int ostatus; + + /* FSM events, stored for debug purposes. + * Note: uchar used for reduced memory usage. + */ + unsigned char cur_event; + unsigned char last_event; + unsigned char last_major_event; + + /* Peer index, used for dumping TABLE_DUMP_V2 format */ + uint16_t table_dump_index; + + /* Peer information */ + int fd; /* File descriptor */ + int ttl; /* TTL of TCP connection to the peer. */ + int rtt; /* Estimated round-trip-time from TCP_INFO */ + int gtsm_hops; /* minimum hopcount to peer */ + char *desc; /* Description of the peer. */ + unsigned short port; /* Destination port for peer */ + char *host; /* Printable address of the peer. */ + union sockunion su; /* Sockunion address of the peer. */ + /* $FRR indent$ */ + /* clang-format off */ #define BGP_PEER_SU_UNSPEC(peer) (peer->su.sa.sa_family == AF_UNSPEC) - time_t uptime; /* Last Up/Down time */ - time_t readtime; /* Last read time */ - time_t resettime; /* Last reset time */ - - ifindex_t ifindex; /* ifindex of the BGP connection. */ - char *conf_if; /* neighbor interface config name. */ - struct interface *ifp; /* corresponding interface */ - char *ifname; /* bind interface name. */ - char *update_if; - union sockunion *update_source; - - union sockunion *su_local; /* Sockunion of local address. */ - union sockunion *su_remote; /* Sockunion of remote address. */ - int shared_network; /* Is this peer shared same network. */ - struct bgp_nexthop nexthop; /* Nexthop */ - - /* Peer address family configuration. */ - u_char afc[AFI_MAX][SAFI_MAX]; - u_char afc_nego[AFI_MAX][SAFI_MAX]; - u_char afc_adv[AFI_MAX][SAFI_MAX]; - u_char afc_recv[AFI_MAX][SAFI_MAX]; - - /* Capability flags (reset in bgp_stop) */ - u_int32_t cap; + time_t uptime; /* Last Up/Down time */ + time_t readtime; /* Last read time */ + time_t resettime; /* Last reset time */ + + ifindex_t ifindex; /* ifindex of the BGP connection. */ + char *conf_if; /* neighbor interface config name. */ + struct interface *ifp; /* corresponding interface */ + char *ifname; /* bind interface name. */ + char *update_if; + union sockunion *update_source; + + union sockunion *su_local; /* Sockunion of local address. */ + union sockunion *su_remote; /* Sockunion of remote address. */ + int shared_network; /* Is this peer shared same network. */ + struct bgp_nexthop nexthop; /* Nexthop */ + + /* Peer address family configuration. */ + u_char afc[AFI_MAX][SAFI_MAX]; + u_char afc_nego[AFI_MAX][SAFI_MAX]; + u_char afc_adv[AFI_MAX][SAFI_MAX]; + u_char afc_recv[AFI_MAX][SAFI_MAX]; + + /* Capability flags (reset in bgp_stop) */ + u_int32_t cap; #define PEER_CAP_REFRESH_ADV (1 << 0) /* refresh advertised */ #define PEER_CAP_REFRESH_OLD_RCV (1 << 1) /* refresh old received */ #define PEER_CAP_REFRESH_NEW_RCV (1 << 2) /* refresh rfc received */ @@ -656,8 +652,8 @@ struct peer #define PEER_CAP_HOSTNAME_ADV (1 << 15) /* hostname advertised */ #define PEER_CAP_HOSTNAME_RCV (1 << 16) /* hostname received */ - /* Capability flags (reset in bgp_stop) */ - u_int32_t af_cap[AFI_MAX][SAFI_MAX]; + /* Capability flags (reset in bgp_stop) */ + u_int32_t af_cap[AFI_MAX][SAFI_MAX]; #define PEER_CAP_ORF_PREFIX_SM_ADV (1 << 0) /* send-mode advertised */ #define PEER_CAP_ORF_PREFIX_RM_ADV (1 << 1) /* receive-mode advertised */ #define PEER_CAP_ORF_PREFIX_SM_RCV (1 << 2) /* send-mode received */ @@ -674,8 +670,8 @@ struct peer #define PEER_CAP_ENHE_AF_RCV (1 << 13) /* Extended nexthop afi/safi received */ #define PEER_CAP_ENHE_AF_NEGO (1 << 14) /* Extended nexthop afi/safi negotiated */ - /* Global configuration flags. */ - u_int32_t flags; + /* Global configuration flags. */ + u_int32_t flags; #define PEER_FLAG_PASSIVE (1 << 0) /* passive mode */ #define PEER_FLAG_SHUTDOWN (1 << 1) /* shutdown */ #define PEER_FLAG_DONT_CAPABILITY (1 << 2) /* dont-capability */ @@ -694,14 +690,14 @@ struct peer #if ENABLE_BGP_VNC #define PEER_FLAG_IS_RFAPI_HD (1 << 15) /* attached to rfapi HD */ #endif - /* outgoing message sent in CEASE_ADMIN_SHUTDOWN notify */ - char *tx_shutdown_message; + /* outgoing message sent in CEASE_ADMIN_SHUTDOWN notify */ + char *tx_shutdown_message; - /* NSF mode (graceful restart) */ - u_char nsf[AFI_MAX][SAFI_MAX]; + /* NSF mode (graceful restart) */ + u_char nsf[AFI_MAX][SAFI_MAX]; - /* Per AF configuration flags. */ - u_int32_t af_flags[AFI_MAX][SAFI_MAX]; + /* Per AF configuration flags. */ + u_int32_t af_flags[AFI_MAX][SAFI_MAX]; #define PEER_FLAG_SEND_COMMUNITY (1 << 0) /* send-community */ #define PEER_FLAG_SEND_EXT_COMMUNITY (1 << 1) /* send-community ext. */ #define PEER_FLAG_NEXTHOP_SELF (1 << 2) /* next-hop-self */ @@ -730,18 +726,17 @@ struct peer #define PEER_FLAG_ALLOWAS_IN_ORIGIN (1 << 25) /* allowas-in origin */ #define PEER_FLAG_SEND_LARGE_COMMUNITY (1 << 26) /* Send large Communities */ - /* MD5 password */ - char *password; + /* MD5 password */ + char *password; - /* default-originate route-map. */ - struct - { - char *name; - struct route_map *map; - } default_rmap[AFI_MAX][SAFI_MAX]; + /* default-originate route-map. */ + struct { + char *name; + struct route_map *map; + } default_rmap[AFI_MAX][SAFI_MAX]; - /* Peer status flags. */ - u_int16_t sflags; + /* Peer status flags. */ + u_int16_t sflags; #define PEER_STATUS_ACCEPT_PEER (1 << 0) /* accept peer */ #define PEER_STATUS_PREFIX_OVERFLOW (1 << 1) /* prefix-overflow */ #define PEER_STATUS_CAPABILITY_OPEN (1 << 2) /* capability open send */ @@ -750,8 +745,8 @@ struct peer #define PEER_STATUS_NSF_MODE (1 << 5) /* NSF aware peer */ #define PEER_STATUS_NSF_WAIT (1 << 6) /* wait comeback peer */ - /* Peer status af flags (reset in bgp_stop) */ - u_int16_t af_sflags[AFI_MAX][SAFI_MAX]; + /* Peer status af flags (reset in bgp_stop) */ + u_int16_t af_sflags[AFI_MAX][SAFI_MAX]; #define PEER_STATUS_ORF_PREFIX_SEND (1 << 0) /* prefix-list send peer */ #define PEER_STATUS_ORF_WAIT_REFRESH (1 << 1) /* wait refresh received peer */ #define PEER_STATUS_PREFIX_THRESHOLD (1 << 2) /* exceed prefix-threshold */ @@ -759,110 +754,111 @@ struct peer #define PEER_STATUS_EOR_SEND (1 << 4) /* end-of-rib send to peer */ #define PEER_STATUS_EOR_RECEIVED (1 << 5) /* end-of-rib received from peer */ - /* Default attribute value for the peer. */ - u_int32_t config; + /* Default attribute value for the peer. */ + u_int32_t config; #define PEER_CONFIG_TIMER (1 << 0) /* keepalive & holdtime */ #define PEER_CONFIG_CONNECT (1 << 1) /* connect */ #define PEER_CONFIG_ROUTEADV (1 << 2) /* route advertise */ - u_int32_t holdtime; - u_int32_t keepalive; - u_int32_t connect; - u_int32_t routeadv; - - /* Timer values. */ - u_int32_t v_start; - u_int32_t v_connect; - u_int32_t v_holdtime; - u_int32_t v_keepalive; - u_int32_t v_routeadv; - u_int32_t v_pmax_restart; - u_int32_t v_gr_restart; - - /* Threads. */ - struct thread *t_read; - struct thread *t_write; - struct thread *t_start; - struct thread *t_connect; - struct thread *t_holdtime; - struct thread *t_keepalive; - struct thread *t_routeadv; - struct thread *t_pmax_restart; - struct thread *t_gr_restart; - struct thread *t_gr_stale; - - /* workqueues */ - struct work_queue *clear_node_queue; - - /* Statistics field */ - u_int32_t open_in; /* Open message input count */ - u_int32_t open_out; /* Open message output count */ - u_int32_t update_in; /* Update message input count */ - u_int32_t update_out; /* Update message ouput count */ - time_t update_time; /* Update message received time. */ - u_int32_t keepalive_in; /* Keepalive input count */ - u_int32_t keepalive_out; /* Keepalive output count */ - u_int32_t notify_in; /* Notify input count */ - u_int32_t notify_out; /* Notify output count */ - u_int32_t refresh_in; /* Route Refresh input count */ - u_int32_t refresh_out; /* Route Refresh output count */ - u_int32_t dynamic_cap_in; /* Dynamic Capability input count. */ - u_int32_t dynamic_cap_out; /* Dynamic Capability output count. */ - - /* BGP state count */ - u_int32_t established; /* Established */ - u_int32_t dropped; /* Dropped */ - - /* Update delay related fields */ - u_char update_delay_over; /* When this is set, BGP is no more waiting for EOR */ - - /* Syncronization list and time. */ - struct bgp_synchronize *sync[AFI_MAX][SAFI_MAX]; - time_t synctime; - time_t last_write; /* timestamp when the last msg was written */ - time_t last_update; /* timestamp when the last UPDATE msg was written */ - - /* Send prefix count. */ - unsigned long scount[AFI_MAX][SAFI_MAX]; - - /* Announcement attribute hash. */ - struct hash *hash[AFI_MAX][SAFI_MAX]; - - /* Notify data. */ - struct bgp_notify notify; - - /* Whole packet size to be read. */ - unsigned long packet_size; - - /* Filter structure. */ - struct bgp_filter filter[AFI_MAX][SAFI_MAX]; - - /* ORF Prefix-list */ - struct prefix_list *orf_plist[AFI_MAX][SAFI_MAX]; - - /* Text description of last attribute rcvd */ - char rcvd_attr_str[BUFSIZ]; - - /* Track if we printed the attribute in debugs */ - int rcvd_attr_printed; - - /* Prefix count. */ - unsigned long pcount[AFI_MAX][SAFI_MAX]; - - /* Max prefix count. */ - unsigned long pmax[AFI_MAX][SAFI_MAX]; - u_char pmax_threshold[AFI_MAX][SAFI_MAX]; - u_int16_t pmax_restart[AFI_MAX][SAFI_MAX]; + u_int32_t holdtime; + u_int32_t keepalive; + u_int32_t connect; + u_int32_t routeadv; + + /* Timer values. */ + u_int32_t v_start; + u_int32_t v_connect; + u_int32_t v_holdtime; + u_int32_t v_keepalive; + u_int32_t v_routeadv; + u_int32_t v_pmax_restart; + u_int32_t v_gr_restart; + + /* Threads. */ + struct thread *t_read; + struct thread *t_write; + struct thread *t_start; + struct thread *t_connect; + struct thread *t_holdtime; + struct thread *t_keepalive; + struct thread *t_routeadv; + struct thread *t_pmax_restart; + struct thread *t_gr_restart; + struct thread *t_gr_stale; + + /* workqueues */ + struct work_queue *clear_node_queue; + + /* Statistics field */ + u_int32_t open_in; /* Open message input count */ + u_int32_t open_out; /* Open message output count */ + u_int32_t update_in; /* Update message input count */ + u_int32_t update_out; /* Update message ouput count */ + time_t update_time; /* Update message received time. */ + u_int32_t keepalive_in; /* Keepalive input count */ + u_int32_t keepalive_out; /* Keepalive output count */ + u_int32_t notify_in; /* Notify input count */ + u_int32_t notify_out; /* Notify output count */ + u_int32_t refresh_in; /* Route Refresh input count */ + u_int32_t refresh_out; /* Route Refresh output count */ + u_int32_t dynamic_cap_in; /* Dynamic Capability input count. */ + u_int32_t dynamic_cap_out; /* Dynamic Capability output count. */ + + /* BGP state count */ + u_int32_t established; /* Established */ + u_int32_t dropped; /* Dropped */ + + /* Update delay related fields */ + u_char update_delay_over; /* When this is set, BGP is no more waiting + for EOR */ + + /* Syncronization list and time. */ + struct bgp_synchronize *sync[AFI_MAX][SAFI_MAX]; + time_t synctime; + time_t last_write; /* timestamp when the last msg was written */ + time_t last_update; /* timestamp when the last UPDATE msg was written */ + + /* Send prefix count. */ + unsigned long scount[AFI_MAX][SAFI_MAX]; + + /* Announcement attribute hash. */ + struct hash *hash[AFI_MAX][SAFI_MAX]; + + /* Notify data. */ + struct bgp_notify notify; + + /* Whole packet size to be read. */ + unsigned long packet_size; + + /* Filter structure. */ + struct bgp_filter filter[AFI_MAX][SAFI_MAX]; + + /* ORF Prefix-list */ + struct prefix_list *orf_plist[AFI_MAX][SAFI_MAX]; + + /* Text description of last attribute rcvd */ + char rcvd_attr_str[BUFSIZ]; + + /* Track if we printed the attribute in debugs */ + int rcvd_attr_printed; + + /* Prefix count. */ + unsigned long pcount[AFI_MAX][SAFI_MAX]; + + /* Max prefix count. */ + unsigned long pmax[AFI_MAX][SAFI_MAX]; + u_char pmax_threshold[AFI_MAX][SAFI_MAX]; + u_int16_t pmax_restart[AFI_MAX][SAFI_MAX]; #define MAXIMUM_PREFIX_THRESHOLD_DEFAULT 75 - /* allowas-in. */ - char allowas_in[AFI_MAX][SAFI_MAX]; + /* allowas-in. */ + char allowas_in[AFI_MAX][SAFI_MAX]; - /* weight */ - unsigned long weight[AFI_MAX][SAFI_MAX]; + /* weight */ + unsigned long weight[AFI_MAX][SAFI_MAX]; - /* peer reset cause */ - char last_reset; + /* peer reset cause */ + char last_reset; #define PEER_DOWN_RID_CHANGE 1 /* bgp router-id command */ #define PEER_DOWN_REMOTE_AS_CHANGE 2 /* neighbor remote-as command */ #define PEER_DOWN_LOCAL_AS_CHANGE 3 /* neighbor local-as command */ @@ -889,11 +885,11 @@ struct peer #define PEER_DOWN_BFD_DOWN 24 /* BFD down */ #define PEER_DOWN_IF_DOWN 25 /* Interface down */ #define PEER_DOWN_NBR_ADDR_DEL 26 /* Peer address lost */ -unsigned long last_reset_cause_size; -u_char last_reset_cause[BGP_MAX_PACKET_SIZE]; + unsigned long last_reset_cause_size; + u_char last_reset_cause[BGP_MAX_PACKET_SIZE]; - /* The kind of route-map Flags.*/ - u_char rmap_type; + /* The kind of route-map Flags.*/ + u_char rmap_type; #define PEER_RMAP_TYPE_IN (1 << 0) /* neighbor route-map in */ #define PEER_RMAP_TYPE_OUT (1 << 1) /* neighbor route-map out */ #define PEER_RMAP_TYPE_NETWORK (1 << 2) /* network route-map */ @@ -903,40 +899,39 @@ u_char last_reset_cause[BGP_MAX_PACKET_SIZE]; #define PEER_RMAP_TYPE_IMPORT (1 << 6) /* neighbor route-map import */ #define PEER_RMAP_TYPE_EXPORT (1 << 7) /* neighbor route-map export */ - /* peer specific BFD information */ - struct bfd_info *bfd_info; + /* peer specific BFD information */ + struct bfd_info *bfd_info; - /* hostname and domainname advertised by host */ - char *hostname; - char *domainname; + /* hostname and domainname advertised by host */ + char *hostname; + char *domainname; - QOBJ_FIELDS + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(peer) /* Check if suppress start/restart of sessions to peer. */ -#define BGP_PEER_START_SUPPRESSED(P) \ - (CHECK_FLAG ((P)->flags, PEER_FLAG_SHUTDOWN) \ - || CHECK_FLAG ((P)->sflags, PEER_STATUS_PREFIX_OVERFLOW)) +#define BGP_PEER_START_SUPPRESSED(P) \ + (CHECK_FLAG((P)->flags, PEER_FLAG_SHUTDOWN) \ + || CHECK_FLAG((P)->sflags, PEER_STATUS_PREFIX_OVERFLOW)) #define PEER_PASSWORD_MINLEN (1) #define PEER_PASSWORD_MAXLEN (80) /* This structure's member directly points incoming packet data stream. */ -struct bgp_nlri -{ - /* AFI. */ - afi_t afi; +struct bgp_nlri { + /* AFI. */ + afi_t afi; - /* SAFI. */ - safi_t safi; + /* SAFI. */ + safi_t safi; - /* Pointer to NLRI byte stream. */ - u_char *nlri; + /* Pointer to NLRI byte stream. */ + u_char *nlri; - /* Length of whole NLRI. */ - bgp_size_t length; + /* Length of whole NLRI. */ + bgp_size_t length; }; /* BGP versions. */ @@ -1115,20 +1110,19 @@ struct bgp_nlri #define BGP_DYNAMIC_NEIGHBORS_LIMIT_MAX 5000 /* Flag for peer_clear_soft(). */ -enum bgp_clear_type -{ - BGP_CLEAR_SOFT_NONE, - BGP_CLEAR_SOFT_OUT, - BGP_CLEAR_SOFT_IN, - BGP_CLEAR_SOFT_BOTH, - BGP_CLEAR_SOFT_IN_ORF_PREFIX +enum bgp_clear_type { + BGP_CLEAR_SOFT_NONE, + BGP_CLEAR_SOFT_OUT, + BGP_CLEAR_SOFT_IN, + BGP_CLEAR_SOFT_BOTH, + BGP_CLEAR_SOFT_IN_ORF_PREFIX }; /* Macros. */ #define BGP_INPUT(P) ((P)->ibuf) #define BGP_INPUT_PNT(P) (STREAM_PNT(BGP_INPUT(P))) -#define BGP_IS_VALID_STATE_FOR_NOTIF(S)\ - (((S) == OpenSent) || ((S) == OpenConfirm) || ((S) == Established)) +#define BGP_IS_VALID_STATE_FOR_NOTIF(S) \ + (((S) == OpenSent) || ((S) == OpenConfirm) || ((S) == Established)) /* BGP error codes. */ #define BGP_SUCCESS 0 @@ -1171,44 +1165,45 @@ enum bgp_clear_type /* * Enumeration of different policy kinds a peer can be configured with. */ -typedef enum -{ - BGP_POLICY_ROUTE_MAP, - BGP_POLICY_FILTER_LIST, - BGP_POLICY_PREFIX_LIST, - BGP_POLICY_DISTRIBUTE_LIST, +typedef enum { + BGP_POLICY_ROUTE_MAP, + BGP_POLICY_FILTER_LIST, + BGP_POLICY_PREFIX_LIST, + BGP_POLICY_DISTRIBUTE_LIST, } bgp_policy_type_e; extern struct bgp_master *bm; extern unsigned int multipath_num; /* Prototypes. */ -extern void bgp_terminate (void); -extern void bgp_reset (void); -extern time_t bgp_clock (void); -extern void bgp_zclient_reset (void); -extern int bgp_nexthop_set (union sockunion *, union sockunion *, - struct bgp_nexthop *, struct peer *); -extern struct bgp *bgp_get_default (void); -extern struct bgp *bgp_lookup (as_t, const char *); -extern struct bgp *bgp_lookup_by_name (const char *); -extern struct bgp *bgp_lookup_by_vrf_id (vrf_id_t); -extern struct peer *peer_lookup (struct bgp *, union sockunion *); -extern struct peer *peer_lookup_by_conf_if (struct bgp *, const char *); +extern void bgp_terminate(void); +extern void bgp_reset(void); +extern time_t bgp_clock(void); +extern void bgp_zclient_reset(void); +extern int bgp_nexthop_set(union sockunion *, union sockunion *, + struct bgp_nexthop *, struct peer *); +extern struct bgp *bgp_get_default(void); +extern struct bgp *bgp_lookup(as_t, const char *); +extern struct bgp *bgp_lookup_by_name(const char *); +extern struct bgp *bgp_lookup_by_vrf_id(vrf_id_t); +extern struct peer *peer_lookup(struct bgp *, union sockunion *); +extern struct peer *peer_lookup_by_conf_if(struct bgp *, const char *); extern struct peer *peer_lookup_by_hostname(struct bgp *, const char *); -extern void bgp_peer_conf_if_to_su_update (struct peer *); +extern void bgp_peer_conf_if_to_su_update(struct peer *); extern int peer_group_listen_range_del(struct peer_group *, struct prefix *); -extern struct peer_group *peer_group_lookup (struct bgp *, const char *); -extern struct peer_group *peer_group_get (struct bgp *, const char *); -extern struct peer *peer_create_bind_dynamic_neighbor (struct bgp *, - union sockunion *, struct peer_group *); -extern struct prefix *peer_group_lookup_dynamic_neighbor_range ( - struct peer_group *, struct prefix *); -extern struct peer_group *peer_group_lookup_dynamic_neighbor (struct bgp *, - struct prefix *, struct prefix **); -extern struct peer *peer_lookup_dynamic_neighbor (struct bgp *, - union sockunion *); -extern void peer_drop_dynamic_neighbor (struct peer *); +extern struct peer_group *peer_group_lookup(struct bgp *, const char *); +extern struct peer_group *peer_group_get(struct bgp *, const char *); +extern struct peer *peer_create_bind_dynamic_neighbor(struct bgp *, + union sockunion *, + struct peer_group *); +extern struct prefix * +peer_group_lookup_dynamic_neighbor_range(struct peer_group *, struct prefix *); +extern struct peer_group *peer_group_lookup_dynamic_neighbor(struct bgp *, + struct prefix *, + struct prefix **); +extern struct peer *peer_lookup_dynamic_neighbor(struct bgp *, + union sockunion *); +extern void peer_drop_dynamic_neighbor(struct peer *); /* * Peers are incredibly easy to memory leak @@ -1220,361 +1215,345 @@ extern struct peer *peer_unlock_with_caller(const char *, struct peer *); #define peer_unlock(A) peer_unlock_with_caller(__FUNCTION__, (A)) #define peer_lock(B) peer_lock_with_caller(__FUNCTION__, (B)) -extern bgp_peer_sort_t peer_sort (struct peer *peer); -extern int peer_active (struct peer *); -extern int peer_active_nego (struct peer *); -extern void bgp_recalculate_all_bestpaths (struct bgp *bgp); +extern bgp_peer_sort_t peer_sort(struct peer *peer); +extern int peer_active(struct peer *); +extern int peer_active_nego(struct peer *); +extern void bgp_recalculate_all_bestpaths(struct bgp *bgp); extern struct peer *peer_create(union sockunion *, const char *, struct bgp *, - as_t, as_t, int, afi_t, safi_t, struct peer_group *); -extern struct peer *peer_create_accept (struct bgp *); -extern void peer_xfer_config (struct peer *dst, struct peer *src); -extern char *peer_uptime (time_t, char *, size_t, u_char, json_object *); + as_t, as_t, int, afi_t, safi_t, + struct peer_group *); +extern struct peer *peer_create_accept(struct bgp *); +extern void peer_xfer_config(struct peer *dst, struct peer *src); +extern char *peer_uptime(time_t, char *, size_t, u_char, json_object *); -extern int bgp_config_write (struct vty *); -extern void bgp_config_write_family_header (struct vty *, afi_t, safi_t, int *); +extern int bgp_config_write(struct vty *); +extern void bgp_config_write_family_header(struct vty *, afi_t, safi_t, int *); -extern void bgp_master_init (struct thread_master *master); +extern void bgp_master_init(struct thread_master *master); -extern void bgp_init (void); -extern void bgp_route_map_init (void); -extern void bgp_session_reset (struct peer *); +extern void bgp_init(void); +extern void bgp_route_map_init(void); +extern void bgp_session_reset(struct peer *); -extern int bgp_option_set (int); -extern int bgp_option_unset (int); -extern int bgp_option_check (int); +extern int bgp_option_set(int); +extern int bgp_option_unset(int); +extern int bgp_option_check(int); -extern int bgp_get (struct bgp **, as_t *, const char *, enum bgp_instance_type); -extern void bgp_instance_up (struct bgp *); -extern void bgp_instance_down (struct bgp *); -extern int bgp_delete (struct bgp *); +extern int bgp_get(struct bgp **, as_t *, const char *, enum bgp_instance_type); +extern void bgp_instance_up(struct bgp *); +extern void bgp_instance_down(struct bgp *); +extern int bgp_delete(struct bgp *); -extern int bgp_flag_set (struct bgp *, int); -extern int bgp_flag_unset (struct bgp *, int); -extern int bgp_flag_check (struct bgp *, int); +extern int bgp_flag_set(struct bgp *, int); +extern int bgp_flag_unset(struct bgp *, int); +extern int bgp_flag_check(struct bgp *, int); -extern void bgp_lock (struct bgp *); -extern void bgp_unlock (struct bgp *); +extern void bgp_lock(struct bgp *); +extern void bgp_unlock(struct bgp *); -extern void bgp_router_id_zebra_bump (vrf_id_t, const struct prefix*); -extern int bgp_router_id_static_set (struct bgp *, struct in_addr); +extern void bgp_router_id_zebra_bump(vrf_id_t, const struct prefix *); +extern int bgp_router_id_static_set(struct bgp *, struct in_addr); -extern int bgp_cluster_id_set (struct bgp *, struct in_addr *); -extern int bgp_cluster_id_unset (struct bgp *); +extern int bgp_cluster_id_set(struct bgp *, struct in_addr *); +extern int bgp_cluster_id_unset(struct bgp *); -extern int bgp_confederation_id_set (struct bgp *, as_t); -extern int bgp_confederation_id_unset (struct bgp *); -extern int bgp_confederation_peers_check (struct bgp *, as_t); +extern int bgp_confederation_id_set(struct bgp *, as_t); +extern int bgp_confederation_id_unset(struct bgp *); +extern int bgp_confederation_peers_check(struct bgp *, as_t); -extern int bgp_confederation_peers_add (struct bgp *, as_t); -extern int bgp_confederation_peers_remove (struct bgp *, as_t); +extern int bgp_confederation_peers_add(struct bgp *, as_t); +extern int bgp_confederation_peers_remove(struct bgp *, as_t); -extern int bgp_timers_set (struct bgp *, u_int32_t keepalive, u_int32_t holdtime); -extern int bgp_timers_unset (struct bgp *); +extern int bgp_timers_set(struct bgp *, u_int32_t keepalive, + u_int32_t holdtime); +extern int bgp_timers_unset(struct bgp *); -extern int bgp_default_local_preference_set (struct bgp *, u_int32_t); -extern int bgp_default_local_preference_unset (struct bgp *); +extern int bgp_default_local_preference_set(struct bgp *, u_int32_t); +extern int bgp_default_local_preference_unset(struct bgp *); -extern int bgp_default_subgroup_pkt_queue_max_set (struct bgp *bgp, u_int32_t); -extern int bgp_default_subgroup_pkt_queue_max_unset (struct bgp *bgp); +extern int bgp_default_subgroup_pkt_queue_max_set(struct bgp *bgp, u_int32_t); +extern int bgp_default_subgroup_pkt_queue_max_unset(struct bgp *bgp); -extern int bgp_listen_limit_set (struct bgp *, int); -extern int bgp_listen_limit_unset (struct bgp *); +extern int bgp_listen_limit_set(struct bgp *, int); +extern int bgp_listen_limit_unset(struct bgp *); -extern int bgp_update_delay_active (struct bgp *); -extern int bgp_update_delay_configured (struct bgp *); -extern void peer_as_change (struct peer *, as_t, int); -extern int peer_remote_as (struct bgp *, union sockunion *,const char *, as_t *, - int, afi_t, safi_t); -extern int peer_group_remote_as (struct bgp *, const char *, as_t *, int); -extern int peer_delete (struct peer *peer); -extern int peer_group_delete (struct peer_group *); -extern int peer_group_remote_as_delete (struct peer_group *); +extern int bgp_update_delay_active(struct bgp *); +extern int bgp_update_delay_configured(struct bgp *); +extern void peer_as_change(struct peer *, as_t, int); +extern int peer_remote_as(struct bgp *, union sockunion *, const char *, as_t *, + int, afi_t, safi_t); +extern int peer_group_remote_as(struct bgp *, const char *, as_t *, int); +extern int peer_delete(struct peer *peer); +extern int peer_group_delete(struct peer_group *); +extern int peer_group_remote_as_delete(struct peer_group *); extern int peer_group_listen_range_add(struct peer_group *, struct prefix *); -extern int peer_activate (struct peer *, afi_t, safi_t); -extern int peer_deactivate (struct peer *, afi_t, safi_t); -extern int peer_afc_set (struct peer *, afi_t, safi_t, int); +extern int peer_activate(struct peer *, afi_t, safi_t); +extern int peer_deactivate(struct peer *, afi_t, safi_t); +extern int peer_afc_set(struct peer *, afi_t, safi_t, int); -extern int peer_group_bind (struct bgp *, union sockunion *, struct peer *, - struct peer_group *, as_t *); -extern int peer_group_unbind (struct bgp *, struct peer *, struct peer_group *); +extern int peer_group_bind(struct bgp *, union sockunion *, struct peer *, + struct peer_group *, as_t *); +extern int peer_group_unbind(struct bgp *, struct peer *, struct peer_group *); -extern int peer_flag_set (struct peer *, u_int32_t); -extern int peer_flag_unset (struct peer *, u_int32_t); +extern int peer_flag_set(struct peer *, u_int32_t); +extern int peer_flag_unset(struct peer *, u_int32_t); -extern int peer_af_flag_set (struct peer *, afi_t, safi_t, u_int32_t); -extern int peer_af_flag_unset (struct peer *, afi_t, safi_t, u_int32_t); -extern int peer_af_flag_check (struct peer *, afi_t, safi_t, u_int32_t); +extern int peer_af_flag_set(struct peer *, afi_t, safi_t, u_int32_t); +extern int peer_af_flag_unset(struct peer *, afi_t, safi_t, u_int32_t); +extern int peer_af_flag_check(struct peer *, afi_t, safi_t, u_int32_t); -extern int peer_ebgp_multihop_set (struct peer *, int); -extern int peer_ebgp_multihop_unset (struct peer *); -extern int is_ebgp_multihop_configured (struct peer *peer); +extern int peer_ebgp_multihop_set(struct peer *, int); +extern int peer_ebgp_multihop_unset(struct peer *); +extern int is_ebgp_multihop_configured(struct peer *peer); -extern int peer_description_set (struct peer *, const char *); -extern int peer_description_unset (struct peer *); +extern int peer_description_set(struct peer *, const char *); +extern int peer_description_unset(struct peer *); -extern int peer_update_source_if_set (struct peer *, const char *); -extern int peer_update_source_addr_set (struct peer *, const union sockunion *); -extern int peer_update_source_unset (struct peer *); +extern int peer_update_source_if_set(struct peer *, const char *); +extern int peer_update_source_addr_set(struct peer *, const union sockunion *); +extern int peer_update_source_unset(struct peer *); -extern int peer_default_originate_set (struct peer *, afi_t, safi_t, const char *); -extern int peer_default_originate_unset (struct peer *, afi_t, safi_t); +extern int peer_default_originate_set(struct peer *, afi_t, safi_t, + const char *); +extern int peer_default_originate_unset(struct peer *, afi_t, safi_t); -extern int peer_port_set (struct peer *, u_int16_t); -extern int peer_port_unset (struct peer *); +extern int peer_port_set(struct peer *, u_int16_t); +extern int peer_port_unset(struct peer *); -extern int peer_weight_set (struct peer *, afi_t, safi_t, u_int16_t); -extern int peer_weight_unset (struct peer *, afi_t, safi_t); +extern int peer_weight_set(struct peer *, afi_t, safi_t, u_int16_t); +extern int peer_weight_unset(struct peer *, afi_t, safi_t); -extern int peer_timers_set (struct peer *, u_int32_t keepalive, u_int32_t holdtime); -extern int peer_timers_unset (struct peer *); +extern int peer_timers_set(struct peer *, u_int32_t keepalive, + u_int32_t holdtime); +extern int peer_timers_unset(struct peer *); -extern int peer_timers_connect_set (struct peer *, u_int32_t); -extern int peer_timers_connect_unset (struct peer *); +extern int peer_timers_connect_set(struct peer *, u_int32_t); +extern int peer_timers_connect_unset(struct peer *); -extern int peer_advertise_interval_set (struct peer *, u_int32_t); -extern int peer_advertise_interval_unset (struct peer *); +extern int peer_advertise_interval_set(struct peer *, u_int32_t); +extern int peer_advertise_interval_unset(struct peer *); -extern void peer_interface_set (struct peer *, const char *); -extern void peer_interface_unset (struct peer *); +extern void peer_interface_set(struct peer *, const char *); +extern void peer_interface_unset(struct peer *); -extern int peer_distribute_set (struct peer *, afi_t, safi_t, int, const char *); -extern int peer_distribute_unset (struct peer *, afi_t, safi_t, int); +extern int peer_distribute_set(struct peer *, afi_t, safi_t, int, const char *); +extern int peer_distribute_unset(struct peer *, afi_t, safi_t, int); -extern int peer_allowas_in_set (struct peer *, afi_t, safi_t, int, int); -extern int peer_allowas_in_unset (struct peer *, afi_t, safi_t); +extern int peer_allowas_in_set(struct peer *, afi_t, safi_t, int, int); +extern int peer_allowas_in_unset(struct peer *, afi_t, safi_t); -extern int peer_local_as_set (struct peer *, as_t, int, int); -extern int peer_local_as_unset (struct peer *); +extern int peer_local_as_set(struct peer *, as_t, int, int); +extern int peer_local_as_unset(struct peer *); -extern int peer_prefix_list_set (struct peer *, afi_t, safi_t, int, const char *); -extern int peer_prefix_list_unset (struct peer *, afi_t, safi_t, int); +extern int peer_prefix_list_set(struct peer *, afi_t, safi_t, int, + const char *); +extern int peer_prefix_list_unset(struct peer *, afi_t, safi_t, int); -extern int peer_aslist_set (struct peer *, afi_t, safi_t, int, const char *); -extern int peer_aslist_unset (struct peer *,afi_t, safi_t, int); +extern int peer_aslist_set(struct peer *, afi_t, safi_t, int, const char *); +extern int peer_aslist_unset(struct peer *, afi_t, safi_t, int); -extern int peer_route_map_set (struct peer *, afi_t, safi_t, int, const char *); -extern int peer_route_map_unset (struct peer *, afi_t, safi_t, int); +extern int peer_route_map_set(struct peer *, afi_t, safi_t, int, const char *); +extern int peer_route_map_unset(struct peer *, afi_t, safi_t, int); -extern int peer_unsuppress_map_set (struct peer *, afi_t, safi_t, const char *); +extern int peer_unsuppress_map_set(struct peer *, afi_t, safi_t, const char *); -extern int peer_password_set (struct peer *, const char *); -extern int peer_password_unset (struct peer *); +extern int peer_password_set(struct peer *, const char *); +extern int peer_password_unset(struct peer *); -extern int peer_unsuppress_map_unset (struct peer *, afi_t, safi_t); +extern int peer_unsuppress_map_unset(struct peer *, afi_t, safi_t); -extern int peer_maximum_prefix_set (struct peer *, afi_t, safi_t, u_int32_t, u_char, int, u_int16_t); -extern int peer_maximum_prefix_unset (struct peer *, afi_t, safi_t); +extern int peer_maximum_prefix_set(struct peer *, afi_t, safi_t, u_int32_t, + u_char, int, u_int16_t); +extern int peer_maximum_prefix_unset(struct peer *, afi_t, safi_t); -extern int peer_clear (struct peer *, struct listnode **); -extern int peer_clear_soft (struct peer *, afi_t, safi_t, enum bgp_clear_type); +extern int peer_clear(struct peer *, struct listnode **); +extern int peer_clear_soft(struct peer *, afi_t, safi_t, enum bgp_clear_type); -extern int peer_ttl_security_hops_set (struct peer *, int); -extern int peer_ttl_security_hops_unset (struct peer *); +extern int peer_ttl_security_hops_set(struct peer *, int); +extern int peer_ttl_security_hops_unset(struct peer *); -extern int peer_tx_shutdown_message_set (struct peer *, const char *msg); -extern int peer_tx_shutdown_message_unset (struct peer *); +extern int peer_tx_shutdown_message_set(struct peer *, const char *msg); +extern int peer_tx_shutdown_message_unset(struct peer *); -extern int bgp_route_map_update_timer (struct thread *thread); +extern int bgp_route_map_update_timer(struct thread *thread); extern void bgp_route_map_terminate(void); -extern int peer_cmp (struct peer *p1, struct peer *p2); +extern int peer_cmp(struct peer *p1, struct peer *p2); -extern int -bgp_map_afi_safi_iana2int (iana_afi_t pkt_afi, safi_t pkt_safi, - afi_t *afi, safi_t *safi); -extern int -bgp_map_afi_safi_int2iana (afi_t afi, safi_t safi, - iana_afi_t *pkt_afi, safi_t *pkt_safi); +extern int bgp_map_afi_safi_iana2int(iana_afi_t pkt_afi, safi_t pkt_safi, + afi_t *afi, safi_t *safi); +extern int bgp_map_afi_safi_int2iana(afi_t afi, safi_t safi, + iana_afi_t *pkt_afi, safi_t *pkt_safi); -extern struct peer_af * peer_af_create (struct peer *, afi_t, safi_t); -extern struct peer_af * peer_af_find (struct peer *, afi_t, safi_t); -extern int peer_af_delete (struct peer *, afi_t, safi_t); +extern struct peer_af *peer_af_create(struct peer *, afi_t, safi_t); +extern struct peer_af *peer_af_find(struct peer *, afi_t, safi_t); +extern int peer_af_delete(struct peer *, afi_t, safi_t); extern void bgp_close(void); -static inline int -afindex (afi_t afi, safi_t safi) +static inline int afindex(afi_t afi, safi_t safi) { - switch (afi) - { - case AFI_IP: - switch (safi) - { - case SAFI_UNICAST: - return BGP_AF_IPV4_UNICAST; - break; - case SAFI_MULTICAST: - return BGP_AF_IPV4_MULTICAST; - break; - case SAFI_LABELED_UNICAST: - return BGP_AF_IPV4_LBL_UNICAST; - break; - case SAFI_MPLS_VPN: - return BGP_AF_IPV4_VPN; - break; - case SAFI_ENCAP: - return BGP_AF_IPV4_ENCAP; - break; + switch (afi) { + case AFI_IP: + switch (safi) { + case SAFI_UNICAST: + return BGP_AF_IPV4_UNICAST; + break; + case SAFI_MULTICAST: + return BGP_AF_IPV4_MULTICAST; + break; + case SAFI_LABELED_UNICAST: + return BGP_AF_IPV4_LBL_UNICAST; + break; + case SAFI_MPLS_VPN: + return BGP_AF_IPV4_VPN; + break; + case SAFI_ENCAP: + return BGP_AF_IPV4_ENCAP; + break; + default: + return BGP_AF_MAX; + break; + } + break; + case AFI_IP6: + switch (safi) { + case SAFI_UNICAST: + return BGP_AF_IPV6_UNICAST; + break; + case SAFI_MULTICAST: + return BGP_AF_IPV6_MULTICAST; + break; + case SAFI_LABELED_UNICAST: + return BGP_AF_IPV6_LBL_UNICAST; + break; + case SAFI_MPLS_VPN: + return BGP_AF_IPV6_VPN; + break; + case SAFI_ENCAP: + return BGP_AF_IPV6_ENCAP; + break; + default: + return BGP_AF_MAX; + break; + } + break; + case AFI_L2VPN: + switch (safi) { + case SAFI_EVPN: + return BGP_AF_L2VPN_EVPN; + break; + default: + return BGP_AF_MAX; + break; + } default: - return BGP_AF_MAX; - break; + return BGP_AF_MAX; + break; } - break; - case AFI_IP6: - switch (safi) - { - case SAFI_UNICAST: - return BGP_AF_IPV6_UNICAST; - break; - case SAFI_MULTICAST: - return BGP_AF_IPV6_MULTICAST; - break; - case SAFI_LABELED_UNICAST: - return BGP_AF_IPV6_LBL_UNICAST; - break; - case SAFI_MPLS_VPN: - return BGP_AF_IPV6_VPN; - break; - case SAFI_ENCAP: - return BGP_AF_IPV6_ENCAP; - break; - default: - return BGP_AF_MAX; - break; - } - break; - case AFI_L2VPN: - switch (safi) - { - case SAFI_EVPN: - return BGP_AF_L2VPN_EVPN; - break; - default: - return BGP_AF_MAX; - break; - } - default: - return BGP_AF_MAX; - break; - } } /* If the peer is not a peer-group but is bound to a peer-group return 1 */ -static inline int -peer_group_active (struct peer *peer) +static inline int peer_group_active(struct peer *peer) { - if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP) && peer->group) - return 1; - return 0; + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) && peer->group) + return 1; + return 0; } /* If peer is negotiated at least one address family return 1. */ -static inline int -peer_afi_active_nego (const struct peer *peer, afi_t afi) +static inline int peer_afi_active_nego(const struct peer *peer, afi_t afi) { - if (peer->afc_nego[afi][SAFI_UNICAST] - || peer->afc_nego[afi][SAFI_MULTICAST] - || peer->afc_nego[afi][SAFI_LABELED_UNICAST] - || peer->afc_nego[afi][SAFI_MPLS_VPN] - || peer->afc_nego[afi][SAFI_ENCAP] - || peer->afc_nego[afi][SAFI_EVPN]) - return 1; - return 0; + if (peer->afc_nego[afi][SAFI_UNICAST] + || peer->afc_nego[afi][SAFI_MULTICAST] + || peer->afc_nego[afi][SAFI_LABELED_UNICAST] + || peer->afc_nego[afi][SAFI_MPLS_VPN] + || peer->afc_nego[afi][SAFI_ENCAP] + || peer->afc_nego[afi][SAFI_EVPN]) + return 1; + return 0; } /* If at least one address family activated for group, return 1. */ -static inline int -peer_group_af_configured (struct peer_group *group) +static inline int peer_group_af_configured(struct peer_group *group) { - struct peer *peer = group->conf; - - if (peer->afc[AFI_IP][SAFI_UNICAST] - || peer->afc[AFI_IP][SAFI_MULTICAST] - || peer->afc[AFI_IP][SAFI_LABELED_UNICAST] - || peer->afc[AFI_IP][SAFI_MPLS_VPN] - || peer->afc[AFI_IP][SAFI_ENCAP] - || peer->afc[AFI_IP6][SAFI_UNICAST] - || peer->afc[AFI_IP6][SAFI_MULTICAST] - || peer->afc[AFI_IP6][SAFI_LABELED_UNICAST] - || peer->afc[AFI_IP6][SAFI_MPLS_VPN] - || peer->afc[AFI_IP6][SAFI_ENCAP] - || peer->afc[AFI_IP6][SAFI_EVPN]) - return 1; - return 0; + struct peer *peer = group->conf; + + if (peer->afc[AFI_IP][SAFI_UNICAST] || peer->afc[AFI_IP][SAFI_MULTICAST] + || peer->afc[AFI_IP][SAFI_LABELED_UNICAST] + || peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP][SAFI_ENCAP] + || peer->afc[AFI_IP6][SAFI_UNICAST] + || peer->afc[AFI_IP6][SAFI_MULTICAST] + || peer->afc[AFI_IP6][SAFI_LABELED_UNICAST] + || peer->afc[AFI_IP6][SAFI_MPLS_VPN] + || peer->afc[AFI_IP6][SAFI_ENCAP] || peer->afc[AFI_IP6][SAFI_EVPN]) + return 1; + return 0; } -static inline char * -timestamp_string (time_t ts) +static inline char *timestamp_string(time_t ts) { - time_t tbuf; - tbuf = time(NULL) - (bgp_clock() - ts); - return ctime(&tbuf); + time_t tbuf; + tbuf = time(NULL) - (bgp_clock() - ts); + return ctime(&tbuf); } -static inline int -peer_established (struct peer *peer) +static inline int peer_established(struct peer *peer) { - if (peer->status == Established) - return 1; - return 0; + if (peer->status == Established) + return 1; + return 0; } -static inline int -peer_dynamic_neighbor (struct peer *peer) +static inline int peer_dynamic_neighbor(struct peer *peer) { - return (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR)) ? 1 : 0; + return (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR)) ? 1 : 0; } -static inline int -peer_cap_enhe (struct peer *peer, afi_t afi, safi_t safi) +static inline int peer_cap_enhe(struct peer *peer, afi_t afi, safi_t safi) { - return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_NEGO)); + return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_NEGO)); } /* Lookup VRF for BGP instance based on its type. */ -static inline struct vrf * -bgp_vrf_lookup_by_instance_type (struct bgp *bgp) +static inline struct vrf *bgp_vrf_lookup_by_instance_type(struct bgp *bgp) { - struct vrf *vrf; + struct vrf *vrf; - if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - vrf = vrf_lookup_by_id (VRF_DEFAULT); - else if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) - vrf = vrf_lookup_by_name (bgp->name); - else - vrf = NULL; + if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) + vrf = vrf_lookup_by_id(VRF_DEFAULT); + else if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) + vrf = vrf_lookup_by_name(bgp->name); + else + vrf = NULL; - return vrf; + return vrf; } /* Link BGP instance to VRF. */ -static inline void -bgp_vrf_link (struct bgp *bgp, struct vrf *vrf) +static inline void bgp_vrf_link(struct bgp *bgp, struct vrf *vrf) { - bgp->vrf_id = vrf->vrf_id; - if (vrf->info != (void *)bgp) - { - bgp_lock (bgp); - vrf->info = (void *)bgp; - } + bgp->vrf_id = vrf->vrf_id; + if (vrf->info != (void *)bgp) { + bgp_lock(bgp); + vrf->info = (void *)bgp; + } } /* Unlink BGP instance from VRF. */ -static inline void -bgp_vrf_unlink (struct bgp *bgp, struct vrf *vrf) +static inline void bgp_vrf_unlink(struct bgp *bgp, struct vrf *vrf) { - if (vrf->info == (void *)bgp) - { - vrf->info = NULL; - bgp_unlock (bgp); - } - bgp->vrf_id = VRF_UNKNOWN; + if (vrf->info == (void *)bgp) { + vrf->info = NULL; + bgp_unlock(bgp); + } + bgp->vrf_id = VRF_UNKNOWN; } -extern void bgp_update_redist_vrf_bitmaps (struct bgp*, vrf_id_t); +extern void bgp_update_redist_vrf_bitmaps(struct bgp *, vrf_id_t); /* For benefit of rfapi */ -extern struct peer * peer_new (struct bgp *bgp); +extern struct peer *peer_new(struct bgp *bgp); #endif /* _QUAGGA_BGPD_H */ diff --git a/bgpd/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c index d04b186df..8a93d3984 100644 --- a/bgpd/rfapi/bgp_rfapi_cfg.c +++ b/bgpd/rfapi/bgp_rfapi_cfg.c @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -52,32 +52,32 @@ DEFINE_MGROUP(RFAPI, "rfapi") -DEFINE_MTYPE(RFAPI, RFAPI_CFG, "NVE Configuration") -DEFINE_MTYPE(RFAPI, RFAPI_GROUP_CFG, "NVE Group Configuration") -DEFINE_MTYPE(RFAPI, RFAPI_L2_CFG, "RFAPI L2 Group Configuration") -DEFINE_MTYPE(RFAPI, RFAPI_RFP_GROUP_CFG, "RFAPI RFP Group Configuration") -DEFINE_MTYPE(RFAPI, RFAPI, "RFAPI Generic") -DEFINE_MTYPE(RFAPI, RFAPI_DESC, "RFAPI Descriptor") -DEFINE_MTYPE(RFAPI, RFAPI_IMPORTTABLE, "RFAPI Import Table") -DEFINE_MTYPE(RFAPI, RFAPI_MONITOR, "RFAPI Monitor VPN") -DEFINE_MTYPE(RFAPI, RFAPI_MONITOR_ENCAP, "RFAPI Monitor Encap") -DEFINE_MTYPE(RFAPI, RFAPI_NEXTHOP, "RFAPI Next Hop") -DEFINE_MTYPE(RFAPI, RFAPI_VN_OPTION, "RFAPI VN Option") -DEFINE_MTYPE(RFAPI, RFAPI_UN_OPTION, "RFAPI UN Option") -DEFINE_MTYPE(RFAPI, RFAPI_WITHDRAW, "RFAPI Withdraw") -DEFINE_MTYPE(RFAPI, RFAPI_RFG_NAME, "RFAPI RFGName") -DEFINE_MTYPE(RFAPI, RFAPI_ADB, "RFAPI Advertisement Data") -DEFINE_MTYPE(RFAPI, RFAPI_ETI, "RFAPI Export Table Info") -DEFINE_MTYPE(RFAPI, RFAPI_NVE_ADDR, "RFAPI NVE Address") -DEFINE_MTYPE(RFAPI, RFAPI_PREFIX_BAG, "RFAPI Prefix Bag") -DEFINE_MTYPE(RFAPI, RFAPI_IT_EXTRA, "RFAPI IT Extra") -DEFINE_MTYPE(RFAPI, RFAPI_INFO, "RFAPI Info") -DEFINE_MTYPE(RFAPI, RFAPI_ADDR, "RFAPI Addr") +DEFINE_MTYPE(RFAPI, RFAPI_CFG, "NVE Configuration") +DEFINE_MTYPE(RFAPI, RFAPI_GROUP_CFG, "NVE Group Configuration") +DEFINE_MTYPE(RFAPI, RFAPI_L2_CFG, "RFAPI L2 Group Configuration") +DEFINE_MTYPE(RFAPI, RFAPI_RFP_GROUP_CFG, "RFAPI RFP Group Configuration") +DEFINE_MTYPE(RFAPI, RFAPI, "RFAPI Generic") +DEFINE_MTYPE(RFAPI, RFAPI_DESC, "RFAPI Descriptor") +DEFINE_MTYPE(RFAPI, RFAPI_IMPORTTABLE, "RFAPI Import Table") +DEFINE_MTYPE(RFAPI, RFAPI_MONITOR, "RFAPI Monitor VPN") +DEFINE_MTYPE(RFAPI, RFAPI_MONITOR_ENCAP, "RFAPI Monitor Encap") +DEFINE_MTYPE(RFAPI, RFAPI_NEXTHOP, "RFAPI Next Hop") +DEFINE_MTYPE(RFAPI, RFAPI_VN_OPTION, "RFAPI VN Option") +DEFINE_MTYPE(RFAPI, RFAPI_UN_OPTION, "RFAPI UN Option") +DEFINE_MTYPE(RFAPI, RFAPI_WITHDRAW, "RFAPI Withdraw") +DEFINE_MTYPE(RFAPI, RFAPI_RFG_NAME, "RFAPI RFGName") +DEFINE_MTYPE(RFAPI, RFAPI_ADB, "RFAPI Advertisement Data") +DEFINE_MTYPE(RFAPI, RFAPI_ETI, "RFAPI Export Table Info") +DEFINE_MTYPE(RFAPI, RFAPI_NVE_ADDR, "RFAPI NVE Address") +DEFINE_MTYPE(RFAPI, RFAPI_PREFIX_BAG, "RFAPI Prefix Bag") +DEFINE_MTYPE(RFAPI, RFAPI_IT_EXTRA, "RFAPI IT Extra") +DEFINE_MTYPE(RFAPI, RFAPI_INFO, "RFAPI Info") +DEFINE_MTYPE(RFAPI, RFAPI_ADDR, "RFAPI Addr") DEFINE_MTYPE(RFAPI, RFAPI_UPDATED_RESPONSE_QUEUE, "RFAPI Updated Rsp Queue") -DEFINE_MTYPE(RFAPI, RFAPI_RECENT_DELETE, "RFAPI Recently Deleted Route") -DEFINE_MTYPE(RFAPI, RFAPI_L2ADDR_OPT, "RFAPI L2 Address Option") -DEFINE_MTYPE(RFAPI, RFAPI_AP, "RFAPI Advertised Prefix") -DEFINE_MTYPE(RFAPI, RFAPI_MONITOR_ETH, "RFAPI Monitor Ethernet") +DEFINE_MTYPE(RFAPI, RFAPI_RECENT_DELETE, "RFAPI Recently Deleted Route") +DEFINE_MTYPE(RFAPI, RFAPI_L2ADDR_OPT, "RFAPI L2 Address Option") +DEFINE_MTYPE(RFAPI, RFAPI_AP, "RFAPI Advertised Prefix") +DEFINE_MTYPE(RFAPI, RFAPI_MONITOR_ETH, "RFAPI Monitor Ethernet") DEFINE_QOBJ_TYPE(rfapi_nve_group_cfg) DEFINE_QOBJ_TYPE(rfapi_l2_group_cfg) @@ -86,139 +86,127 @@ DEFINE_QOBJ_TYPE(rfapi_l2_group_cfg) ***********************************************************************/ -/* +/* * compaitibility to old quagga_time call - * time_t value in terms of stabilised absolute time. + * time_t value in terms of stabilised absolute time. * replacement for POSIX time() */ -time_t -rfapi_time (time_t *t) +time_t rfapi_time(time_t *t) { - time_t clock = bgp_clock(); - if (t) - *t = clock; - return clock; + time_t clock = bgp_clock(); + if (t) + *t = clock; + return clock; } -void -nve_group_to_nve_list ( - struct rfapi_nve_group_cfg *rfg, - struct list **nves, - uint8_t family) /* AF_INET, AF_INET6 */ +void nve_group_to_nve_list(struct rfapi_nve_group_cfg *rfg, struct list **nves, + uint8_t family) /* AF_INET, AF_INET6 */ { - struct listnode *hln; - struct rfapi_descriptor *rfd; - - /* - * loop over nves in this grp, add to list - */ - for (ALL_LIST_ELEMENTS_RO (rfg->nves, hln, rfd)) - { - if (rfd->vn_addr.addr_family == family) - { - if (!*nves) - *nves = list_new (); - listnode_add (*nves, rfd); - } - } + struct listnode *hln; + struct rfapi_descriptor *rfd; + + /* + * loop over nves in this grp, add to list + */ + for (ALL_LIST_ELEMENTS_RO(rfg->nves, hln, rfd)) { + if (rfd->vn_addr.addr_family == family) { + if (!*nves) + *nves = list_new(); + listnode_add(*nves, rfd); + } + } } -struct rfapi_nve_group_cfg * -bgp_rfapi_cfg_match_group ( - struct rfapi_cfg *hc, - struct prefix *vn, - struct prefix *un) +struct rfapi_nve_group_cfg *bgp_rfapi_cfg_match_group(struct rfapi_cfg *hc, + struct prefix *vn, + struct prefix *un) { - struct rfapi_nve_group_cfg *rfg_vn = NULL; - struct rfapi_nve_group_cfg *rfg_un = NULL; - - struct route_table *rt_vn; - struct route_table *rt_un; - struct route_node *rn_vn; - struct route_node *rn_un; - - struct rfapi_nve_group_cfg *rfg; - struct listnode *node, *nnode; - - switch (vn->family) - { - case AF_INET: - rt_vn = &(hc->nve_groups_vn[AFI_IP]); - break; - case AF_INET6: - rt_vn = &(hc->nve_groups_vn[AFI_IP6]); - break; - default: - return NULL; - } - - switch (un->family) - { - case AF_INET: - rt_un = &(hc->nve_groups_un[AFI_IP]); - break; - case AF_INET6: - rt_un = &(hc->nve_groups_un[AFI_IP6]); - break; - default: - return NULL; - } - - rn_vn = route_node_match (rt_vn, vn); /* NB locks node */ - if (rn_vn) - { - rfg_vn = rn_vn->info; - route_unlock_node (rn_vn); - } - - rn_un = route_node_match (rt_un, un); /* NB locks node */ - if (rn_un) - { - rfg_un = rn_un->info; - route_unlock_node (rn_un); - } + struct rfapi_nve_group_cfg *rfg_vn = NULL; + struct rfapi_nve_group_cfg *rfg_un = NULL; + + struct route_table *rt_vn; + struct route_table *rt_un; + struct route_node *rn_vn; + struct route_node *rn_un; + + struct rfapi_nve_group_cfg *rfg; + struct listnode *node, *nnode; + + switch (vn->family) { + case AF_INET: + rt_vn = &(hc->nve_groups_vn[AFI_IP]); + break; + case AF_INET6: + rt_vn = &(hc->nve_groups_vn[AFI_IP6]); + break; + default: + return NULL; + } + + switch (un->family) { + case AF_INET: + rt_un = &(hc->nve_groups_un[AFI_IP]); + break; + case AF_INET6: + rt_un = &(hc->nve_groups_un[AFI_IP6]); + break; + default: + return NULL; + } + + rn_vn = route_node_match(rt_vn, vn); /* NB locks node */ + if (rn_vn) { + rfg_vn = rn_vn->info; + route_unlock_node(rn_vn); + } + + rn_un = route_node_match(rt_un, un); /* NB locks node */ + if (rn_un) { + rfg_un = rn_un->info; + route_unlock_node(rn_un); + } #if BGP_VNC_DEBUG_MATCH_GROUP - { - char buf[BUFSIZ]; + { + char buf[BUFSIZ]; - prefix2str (vn, buf, BUFSIZ); - vnc_zlog_debug_verbose ("%s: vn prefix: %s", __func__, buf); + prefix2str(vn, buf, BUFSIZ); + vnc_zlog_debug_verbose("%s: vn prefix: %s", __func__, buf); - prefix2str (un, buf, BUFSIZ); - vnc_zlog_debug_verbose ("%s: un prefix: %s", __func__, buf); + prefix2str(un, buf, BUFSIZ); + vnc_zlog_debug_verbose("%s: un prefix: %s", __func__, buf); - vnc_zlog_debug_verbose ("%s: rn_vn=%p, rn_un=%p, rfg_vn=%p, rfg_un=%p", - __func__, rn_vn, rn_un, rfg_vn, rfg_un); - } + vnc_zlog_debug_verbose( + "%s: rn_vn=%p, rn_un=%p, rfg_vn=%p, rfg_un=%p", + __func__, rn_vn, rn_un, rfg_vn, rfg_un); + } #endif - if (rfg_un == rfg_vn) /* same group */ - return rfg_un; - if (!rfg_un) /* un doesn't match, return vn-matched grp */ - return rfg_vn; - if (!rfg_vn) /* vn doesn't match, return un-matched grp */ - return rfg_un; - - /* - * Two different nve groups match: the group configured earlier wins. - * For now, just walk the sequential list and pick the first one. - * If this approach is too slow, then store serial numbers in the - * nve group structures as they are defined and just compare - * serial numbers. - */ - for (ALL_LIST_ELEMENTS (hc->nve_groups_sequential, node, nnode, rfg)) - { - if ((rfg == rfg_un) || (rfg == rfg_vn)) - { - return rfg; - } - } - vnc_zlog_debug_verbose ("%s: shouldn't happen, returning NULL when un and vn match", - __func__); - return NULL; /* shouldn't happen */ + if (rfg_un == rfg_vn) /* same group */ + return rfg_un; + if (!rfg_un) /* un doesn't match, return vn-matched grp */ + return rfg_vn; + if (!rfg_vn) /* vn doesn't match, return un-matched grp */ + return rfg_un; + + /* + * Two different nve groups match: the group configured earlier wins. + * For now, just walk the sequential list and pick the first one. + * If this approach is too slow, then store serial numbers in the + * nve group structures as they are defined and just compare + * serial numbers. + */ + for (ALL_LIST_ELEMENTS(hc->nve_groups_sequential, node, nnode, rfg)) { + if ((rfg == rfg_un) || (rfg == rfg_vn)) { + return rfg; + } + } + vnc_zlog_debug_verbose( + "%s: shouldn't happen, returning NULL when un and vn match", + __func__); + return NULL; /* shouldn't happen */ } /*------------------------------------------ @@ -230,15 +218,14 @@ bgp_rfapi_cfg_match_group ( * void * bgp structure * * returns: - * void * + * void * *------------------------------------------*/ -void * -rfapi_get_rfp_start_val (void *bgpv) +void *rfapi_get_rfp_start_val(void *bgpv) { - struct bgp *bgp = bgpv; - if (bgp == NULL || bgp->rfapi == NULL) - return NULL; - return bgp->rfapi->rfp; + struct bgp *bgp = bgpv; + if (bgp == NULL || bgp->rfapi == NULL) + return NULL; + return bgp->rfapi->rfp; } /*------------------------------------------ @@ -246,7 +233,7 @@ rfapi_get_rfp_start_val (void *bgpv) * * Returns if VNC (BGP VPN messaging /VPN & encap SAFIs) are configured * - * input: + * input: * bgp NULL (=use default instance) * * output: @@ -255,32 +242,28 @@ rfapi_get_rfp_start_val (void *bgpv) * 0 Success * ENXIO VNC not configured --------------------------------------------*/ -int -bgp_rfapi_is_vnc_configured (struct bgp *bgp) +int bgp_rfapi_is_vnc_configured(struct bgp *bgp) { - if (bgp == NULL) - bgp = bgp_get_default (); - - if (bgp && bgp->rfapi_cfg) - { - struct peer *peer; - struct peer_group *group; - struct listnode *node, *nnode; - /* if have configured VPN neighbors, assume running VNC */ - for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group)) - { - if (group->conf->afc[AFI_IP][SAFI_MPLS_VPN] || - group->conf->afc[AFI_IP6][SAFI_MPLS_VPN]) - return 0; - } - for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) - { - if (peer->afc[AFI_IP][SAFI_MPLS_VPN] || - peer->afc[AFI_IP6][SAFI_MPLS_VPN]) - return 0; - } - } - return ENXIO; + if (bgp == NULL) + bgp = bgp_get_default(); + + if (bgp && bgp->rfapi_cfg) { + struct peer *peer; + struct peer_group *group; + struct listnode *node, *nnode; + /* if have configured VPN neighbors, assume running VNC */ + for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) { + if (group->conf->afc[AFI_IP][SAFI_MPLS_VPN] + || group->conf->afc[AFI_IP6][SAFI_MPLS_VPN]) + return 0; + } + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + if (peer->afc[AFI_IP][SAFI_MPLS_VPN] + || peer->afc[AFI_IP6][SAFI_MPLS_VPN]) + return 0; + } + } + return ENXIO; } /*********************************************************************** @@ -295,25 +278,21 @@ DEFUN (vnc_advertise_un_method, "Method of advertising UN addresses\n" "Via Tunnel Encap attribute (in VPN SAFI)\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); - if (!bgp->rfapi_cfg) - { - vty_out (vty, "VNC not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!bgp->rfapi_cfg) { + vty_out(vty, "VNC not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (!strncmp (argv[2]->arg, "encap-safi", 7)) - { - bgp->rfapi_cfg->flags |= BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP; - } - else - { - bgp->rfapi_cfg->flags &= ~BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP; - } + if (!strncmp(argv[2]->arg, "encap-safi", 7)) { + bgp->rfapi_cfg->flags |= BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP; + } else { + bgp->rfapi_cfg->flags &= ~BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /*------------------------------------------------------------------------- @@ -325,50 +304,41 @@ DEFUN_NOSH (vnc_defaults, vnc_defaults_cmd, "vnc defaults", VNC_CONFIG_STR "Configure default NVE group\n") { - vty->node = BGP_VNC_DEFAULTS_NODE; - return CMD_SUCCESS; + vty->node = BGP_VNC_DEFAULTS_NODE; + return CMD_SUCCESS; } -static int -set_ecom_list ( - struct vty *vty, - int argc, - struct cmd_token **argv, - struct ecommunity **list) +static int set_ecom_list(struct vty *vty, int argc, struct cmd_token **argv, + struct ecommunity **list) { - struct ecommunity *ecom = NULL; - struct ecommunity *ecomadd; - - for (; argc; --argc, ++argv) - { - - ecomadd = ecommunity_str2com (argv[0]->arg, ECOMMUNITY_ROUTE_TARGET, 0); - if (!ecomadd) - { - vty_out (vty, "Malformed community-list value\n"); - if (ecom) - ecommunity_free (&ecom); - return CMD_WARNING_CONFIG_FAILED; - } - - if (ecom) - { - ecommunity_merge (ecom, ecomadd); - ecommunity_free (&ecomadd); - } - else - { - ecom = ecomadd; - } - } - - if (*list) - { - ecommunity_free (&*list); - } - *list = ecom; - - return CMD_SUCCESS; + struct ecommunity *ecom = NULL; + struct ecommunity *ecomadd; + + for (; argc; --argc, ++argv) { + + ecomadd = ecommunity_str2com(argv[0]->arg, + ECOMMUNITY_ROUTE_TARGET, 0); + if (!ecomadd) { + vty_out(vty, "Malformed community-list value\n"); + if (ecom) + ecommunity_free(&ecom); + return CMD_WARNING_CONFIG_FAILED; + } + + if (ecom) { + ecommunity_merge(ecom, ecomadd); + ecommunity_free(&ecomadd); + } else { + ecom = ecomadd; + } + } + + if (*list) { + ecommunity_free(&*list); + } + *list = ecom; + + return CMD_SUCCESS; } DEFUN (vnc_defaults_rt_import, @@ -378,9 +348,9 @@ DEFUN (vnc_defaults_rt_import, "Import filter\n" "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - return set_ecom_list (vty, argc - 2, argv + 2, - &bgp->rfapi_cfg->default_rt_import_list); + VTY_DECLVAR_CONTEXT(bgp, bgp); + return set_ecom_list(vty, argc - 2, argv + 2, + &bgp->rfapi_cfg->default_rt_import_list); } DEFUN (vnc_defaults_rt_export, @@ -390,9 +360,9 @@ DEFUN (vnc_defaults_rt_export, "Export filter\n" "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - return set_ecom_list (vty, argc - 2, argv + 2, - &bgp->rfapi_cfg->default_rt_export_list); + VTY_DECLVAR_CONTEXT(bgp, bgp); + return set_ecom_list(vty, argc - 2, argv + 2, + &bgp->rfapi_cfg->default_rt_export_list); } DEFUN (vnc_defaults_rt_both, @@ -402,15 +372,15 @@ DEFUN (vnc_defaults_rt_both, "Export+import filters\n" "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int rc; - - rc = set_ecom_list (vty, argc - 2, argv + 2, - &bgp->rfapi_cfg->default_rt_import_list); - if (rc != CMD_SUCCESS) - return rc; - return set_ecom_list (vty, argc - 2, argv + 2, - &bgp->rfapi_cfg->default_rt_export_list); + VTY_DECLVAR_CONTEXT(bgp, bgp); + int rc; + + rc = set_ecom_list(vty, argc - 2, argv + 2, + &bgp->rfapi_cfg->default_rt_import_list); + if (rc != CMD_SUCCESS) + return rc; + return set_ecom_list(vty, argc - 2, argv + 2, + &bgp->rfapi_cfg->default_rt_export_list); } DEFUN (vnc_defaults_rd, @@ -419,54 +389,48 @@ DEFUN (vnc_defaults_rd, "Specify default route distinguisher\n" "Route Distinguisher (: | : | auto:vn: )\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int ret; - struct prefix_rd prd; - - if (!strncmp (argv[1]->arg, "auto:vn:", 8)) - { - /* - * use AF_UNIX to designate automatically-assigned RD - * auto:vn:nn where nn is a 2-octet quantity - */ - char *end = NULL; - uint32_t value32 = strtoul (argv[1]->arg + 8, &end, 10); - uint16_t value = value32 & 0xffff; - - if (!argv[1]->arg[8] || *end) - { - vty_out (vty, "%% Malformed rd\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (value32 > 0xffff) - { - vty_out (vty, "%% Malformed rd (must be less than %u\n", - 0x0ffff); - return CMD_WARNING_CONFIG_FAILED; - } - - memset (&prd, 0, sizeof (prd)); - prd.family = AF_UNIX; - prd.prefixlen = 64; - prd.val[0] = (RD_TYPE_IP >> 8) & 0x0ff; - prd.val[1] = RD_TYPE_IP & 0x0ff; - prd.val[6] = (value >> 8) & 0x0ff; - prd.val[7] = value & 0x0ff; - - } - else - { - - ret = str2prefix_rd (argv[1]->arg, &prd); - if (!ret) - { - vty_out (vty, "%% Malformed rd\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - bgp->rfapi_cfg->default_rd = prd; - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int ret; + struct prefix_rd prd; + + if (!strncmp(argv[1]->arg, "auto:vn:", 8)) { + /* + * use AF_UNIX to designate automatically-assigned RD + * auto:vn:nn where nn is a 2-octet quantity + */ + char *end = NULL; + uint32_t value32 = strtoul(argv[1]->arg + 8, &end, 10); + uint16_t value = value32 & 0xffff; + + if (!argv[1]->arg[8] || *end) { + vty_out(vty, "%% Malformed rd\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (value32 > 0xffff) { + vty_out(vty, "%% Malformed rd (must be less than %u\n", + 0x0ffff); + return CMD_WARNING_CONFIG_FAILED; + } + + memset(&prd, 0, sizeof(prd)); + prd.family = AF_UNIX; + prd.prefixlen = 64; + prd.val[0] = (RD_TYPE_IP >> 8) & 0x0ff; + prd.val[1] = RD_TYPE_IP & 0x0ff; + prd.val[6] = (value >> 8) & 0x0ff; + prd.val[7] = value & 0x0ff; + + } else { + + ret = str2prefix_rd(argv[1]->arg, &prd); + if (!ret) { + vty_out(vty, "%% Malformed rd\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + bgp->rfapi_cfg->default_rd = prd; + return CMD_SUCCESS; } DEFUN (vnc_defaults_l2rd, @@ -476,36 +440,32 @@ DEFUN (vnc_defaults_l2rd, "Fixed value 1-255\n" "use the low-order octet of the NVE's VN address\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - uint8_t value = 0; - - if (strmatch(argv[1]->text, "auto-vn")) - { - value = 0; - } - else - { - char *end = NULL; - unsigned long value_l = strtoul (argv[1]->arg, &end, 10); - - value = value_l & 0xff; - if (!argv[1]->arg[0] || *end) - { - vty_out (vty, "%% Malformed l2 nve ID \"%s\"\n",argv[1]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - if ((value_l < 1) || (value_l > 0xff)) - { - vty_out (vty, - "%% Malformed l2 nve id (must be greater than 0 and less than %u\n", - 0x100); - return CMD_WARNING_CONFIG_FAILED; - } - } - bgp->rfapi_cfg->flags |= BGP_VNC_CONFIG_L2RD; - bgp->rfapi_cfg->default_l2rd = value; - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + uint8_t value = 0; + + if (strmatch(argv[1]->text, "auto-vn")) { + value = 0; + } else { + char *end = NULL; + unsigned long value_l = strtoul(argv[1]->arg, &end, 10); + + value = value_l & 0xff; + if (!argv[1]->arg[0] || *end) { + vty_out(vty, "%% Malformed l2 nve ID \"%s\"\n", + argv[1]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + if ((value_l < 1) || (value_l > 0xff)) { + vty_out(vty, + "%% Malformed l2 nve id (must be greater than 0 and less than %u\n", + 0x100); + return CMD_WARNING_CONFIG_FAILED; + } + } + bgp->rfapi_cfg->flags |= BGP_VNC_CONFIG_L2RD; + bgp->rfapi_cfg->default_l2rd = value; + + return CMD_SUCCESS; } DEFUN (vnc_defaults_no_l2rd, @@ -514,12 +474,12 @@ DEFUN (vnc_defaults_no_l2rd, NO_STR "Specify default Local Nve ID value to use in RD for L2 routes\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp->rfapi_cfg->default_l2rd = 0; - bgp->rfapi_cfg->flags &= ~BGP_VNC_CONFIG_L2RD; + bgp->rfapi_cfg->default_l2rd = 0; + bgp->rfapi_cfg->flags &= ~BGP_VNC_CONFIG_L2RD; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (vnc_defaults_responselifetime, @@ -528,262 +488,240 @@ DEFUN (vnc_defaults_responselifetime, "Specify default response lifetime\n" "Response lifetime in seconds\n" "Infinite response lifetime\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - uint32_t rspint; - struct rfapi *h = NULL; - struct listnode *hdnode; - struct rfapi_descriptor *rfd; - - h = bgp->rfapi; - if (!h) - return CMD_WARNING_CONFIG_FAILED; - - if (strmatch(argv[1]->text, "infinite")) - { - rspint = RFAPI_INFINITE_LIFETIME; - } - else - { - rspint = strtoul(argv[1]->arg, NULL, 10); - if (rspint > INT32_MAX) - rspint = INT32_MAX; /* is really an int, not an unsigned int */ - } - - bgp->rfapi_cfg->default_response_lifetime = rspint; - - for (ALL_LIST_ELEMENTS_RO (&h->descriptors, hdnode, rfd)) - if (rfd->rfg && !(rfd->rfg->flags & RFAPI_RFG_RESPONSE_LIFETIME)) - rfd->response_lifetime = rfd->rfg->response_lifetime = rspint; - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + uint32_t rspint; + struct rfapi *h = NULL; + struct listnode *hdnode; + struct rfapi_descriptor *rfd; + + h = bgp->rfapi; + if (!h) + return CMD_WARNING_CONFIG_FAILED; + + if (strmatch(argv[1]->text, "infinite")) { + rspint = RFAPI_INFINITE_LIFETIME; + } else { + rspint = strtoul(argv[1]->arg, NULL, 10); + if (rspint > INT32_MAX) + rspint = + INT32_MAX; /* is really an int, not an unsigned + int */ + } + + bgp->rfapi_cfg->default_response_lifetime = rspint; + + for (ALL_LIST_ELEMENTS_RO(&h->descriptors, hdnode, rfd)) + if (rfd->rfg + && !(rfd->rfg->flags & RFAPI_RFG_RESPONSE_LIFETIME)) + rfd->response_lifetime = rfd->rfg->response_lifetime = + rspint; + + return CMD_SUCCESS; } struct rfapi_nve_group_cfg * -bgp_rfapi_cfg_match_byname (struct bgp *bgp, const char *name, - rfapi_group_cfg_type_t type) /* _MAX = any */ +bgp_rfapi_cfg_match_byname(struct bgp *bgp, const char *name, + rfapi_group_cfg_type_t type) /* _MAX = any */ { - struct rfapi_nve_group_cfg *rfg; - struct listnode *node, *nnode; - - for (ALL_LIST_ELEMENTS - (bgp->rfapi_cfg->nve_groups_sequential, node, nnode, rfg)) - { - if ((type == RFAPI_GROUP_CFG_MAX || type == rfg->type) && - !strcmp (rfg->name, name)) - return rfg; - } - return NULL; + struct rfapi_nve_group_cfg *rfg; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->nve_groups_sequential, node, + nnode, rfg)) { + if ((type == RFAPI_GROUP_CFG_MAX || type == rfg->type) + && !strcmp(rfg->name, name)) + return rfg; + } + return NULL; } static struct rfapi_nve_group_cfg * -rfapi_group_new (struct bgp *bgp, - rfapi_group_cfg_type_t type, - const char *name) +rfapi_group_new(struct bgp *bgp, rfapi_group_cfg_type_t type, const char *name) { - struct rfapi_nve_group_cfg *rfg; - - rfg = XCALLOC (MTYPE_RFAPI_GROUP_CFG, sizeof (struct rfapi_nve_group_cfg)); - if (rfg) - { - rfg->type = type; - rfg->name = strdup (name); - /* add to tail of list */ - listnode_add (bgp->rfapi_cfg->nve_groups_sequential, rfg); - } - rfg->label = MPLS_LABEL_ILLEGAL; - QOBJ_REG (rfg, rfapi_nve_group_cfg); - - return rfg; + struct rfapi_nve_group_cfg *rfg; + + rfg = XCALLOC(MTYPE_RFAPI_GROUP_CFG, + sizeof(struct rfapi_nve_group_cfg)); + if (rfg) { + rfg->type = type; + rfg->name = strdup(name); + /* add to tail of list */ + listnode_add(bgp->rfapi_cfg->nve_groups_sequential, rfg); + } + rfg->label = MPLS_LABEL_ILLEGAL; + QOBJ_REG(rfg, rfapi_nve_group_cfg); + + return rfg; } -static struct rfapi_l2_group_cfg * -rfapi_l2_group_lookup_byname (struct bgp *bgp, const char *name) +static struct rfapi_l2_group_cfg *rfapi_l2_group_lookup_byname(struct bgp *bgp, + const char *name) { - struct rfapi_l2_group_cfg *rfg; - struct listnode *node, *nnode; - - if (bgp->rfapi_cfg->l2_groups == NULL) /* not the best place for this */ - bgp->rfapi_cfg->l2_groups = list_new (); - - for (ALL_LIST_ELEMENTS (bgp->rfapi_cfg->l2_groups, node, nnode, rfg)) - { - if (!strcmp (rfg->name, name)) - return rfg; - } - return NULL; + struct rfapi_l2_group_cfg *rfg; + struct listnode *node, *nnode; + + if (bgp->rfapi_cfg->l2_groups == NULL) /* not the best place for this */ + bgp->rfapi_cfg->l2_groups = list_new(); + + for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->l2_groups, node, nnode, rfg)) { + if (!strcmp(rfg->name, name)) + return rfg; + } + return NULL; } -static struct rfapi_l2_group_cfg * -rfapi_l2_group_new () +static struct rfapi_l2_group_cfg *rfapi_l2_group_new() { - struct rfapi_l2_group_cfg *rfg; + struct rfapi_l2_group_cfg *rfg; - rfg = XCALLOC (MTYPE_RFAPI_L2_CFG, sizeof (struct rfapi_l2_group_cfg)); - QOBJ_REG (rfg, rfapi_l2_group_cfg); + rfg = XCALLOC(MTYPE_RFAPI_L2_CFG, sizeof(struct rfapi_l2_group_cfg)); + QOBJ_REG(rfg, rfapi_l2_group_cfg); - return rfg; + return rfg; } -static void -rfapi_l2_group_del (struct rfapi_l2_group_cfg *rfg) +static void rfapi_l2_group_del(struct rfapi_l2_group_cfg *rfg) { - QOBJ_UNREG (rfg); - XFREE (MTYPE_RFAPI_L2_CFG, rfg); + QOBJ_UNREG(rfg); + XFREE(MTYPE_RFAPI_L2_CFG, rfg); } -static int -rfapi_str2route_type ( - const char *l3str, - const char *pstr, - afi_t *afi, - int *type) +static int rfapi_str2route_type(const char *l3str, const char *pstr, afi_t *afi, + int *type) { - if (!l3str || !pstr) - return EINVAL; - - if (!strcmp (l3str, "ipv4")) - { - *afi = AFI_IP; - } - else - { - if (!strcmp (l3str, "ipv6")) - *afi = AFI_IP6; - else - return ENOENT; - } - - if (!strcmp (pstr, "connected")) - *type = ZEBRA_ROUTE_CONNECT; - if (!strcmp (pstr, "kernel")) - *type = ZEBRA_ROUTE_KERNEL; - if (!strcmp (pstr, "static")) - *type = ZEBRA_ROUTE_STATIC; - if (!strcmp (pstr, "bgp")) - *type = ZEBRA_ROUTE_BGP; - if (!strcmp (pstr, "bgp-direct")) - *type = ZEBRA_ROUTE_BGP_DIRECT; - if (!strcmp (pstr, "bgp-direct-to-nve-groups")) - *type = ZEBRA_ROUTE_BGP_DIRECT_EXT; - - if (!strcmp (pstr, "rip")) - { - if (*afi == AFI_IP) - *type = ZEBRA_ROUTE_RIP; - else - *type = ZEBRA_ROUTE_RIPNG; - } - - if (!strcmp (pstr, "ripng")) - { - if (*afi == AFI_IP) - return EAFNOSUPPORT; - *type = ZEBRA_ROUTE_RIPNG; - } - - if (!strcmp (pstr, "ospf")) - { - if (*afi == AFI_IP) - *type = ZEBRA_ROUTE_OSPF; - else - *type = ZEBRA_ROUTE_OSPF6; - } - - if (!strcmp (pstr, "ospf6")) - { - if (*afi == AFI_IP) - return EAFNOSUPPORT; - *type = ZEBRA_ROUTE_OSPF6; - } - - return 0; + if (!l3str || !pstr) + return EINVAL; + + if (!strcmp(l3str, "ipv4")) { + *afi = AFI_IP; + } else { + if (!strcmp(l3str, "ipv6")) + *afi = AFI_IP6; + else + return ENOENT; + } + + if (!strcmp(pstr, "connected")) + *type = ZEBRA_ROUTE_CONNECT; + if (!strcmp(pstr, "kernel")) + *type = ZEBRA_ROUTE_KERNEL; + if (!strcmp(pstr, "static")) + *type = ZEBRA_ROUTE_STATIC; + if (!strcmp(pstr, "bgp")) + *type = ZEBRA_ROUTE_BGP; + if (!strcmp(pstr, "bgp-direct")) + *type = ZEBRA_ROUTE_BGP_DIRECT; + if (!strcmp(pstr, "bgp-direct-to-nve-groups")) + *type = ZEBRA_ROUTE_BGP_DIRECT_EXT; + + if (!strcmp(pstr, "rip")) { + if (*afi == AFI_IP) + *type = ZEBRA_ROUTE_RIP; + else + *type = ZEBRA_ROUTE_RIPNG; + } + + if (!strcmp(pstr, "ripng")) { + if (*afi == AFI_IP) + return EAFNOSUPPORT; + *type = ZEBRA_ROUTE_RIPNG; + } + + if (!strcmp(pstr, "ospf")) { + if (*afi == AFI_IP) + *type = ZEBRA_ROUTE_OSPF; + else + *type = ZEBRA_ROUTE_OSPF6; + } + + if (!strcmp(pstr, "ospf6")) { + if (*afi == AFI_IP) + return EAFNOSUPPORT; + *type = ZEBRA_ROUTE_OSPF6; + } + + return 0; } /*------------------------------------------------------------------------- * redistribute *-----------------------------------------------------------------------*/ -#define VNC_REDIST_ENABLE(bgp, afi, type) do { \ - switch (type) { \ - case ZEBRA_ROUTE_BGP_DIRECT: \ - vnc_import_bgp_redist_enable((bgp), (afi)); \ - break; \ - case ZEBRA_ROUTE_BGP_DIRECT_EXT: \ - vnc_import_bgp_exterior_redist_enable((bgp), (afi));\ - break; \ - default: \ - vnc_redistribute_set((bgp), (afi), (type)); \ - break; \ - } \ -} while (0) - -#define VNC_REDIST_DISABLE(bgp, afi, type) do { \ - switch (type) { \ - case ZEBRA_ROUTE_BGP_DIRECT: \ - vnc_import_bgp_redist_disable((bgp), (afi)); \ - break; \ - case ZEBRA_ROUTE_BGP_DIRECT_EXT: \ - vnc_import_bgp_exterior_redist_disable((bgp), (afi));\ - break; \ - default: \ - vnc_redistribute_unset((bgp), (afi), (type)); \ - break; \ - } \ -} while (0) +#define VNC_REDIST_ENABLE(bgp, afi, type) \ + do { \ + switch (type) { \ + case ZEBRA_ROUTE_BGP_DIRECT: \ + vnc_import_bgp_redist_enable((bgp), (afi)); \ + break; \ + case ZEBRA_ROUTE_BGP_DIRECT_EXT: \ + vnc_import_bgp_exterior_redist_enable((bgp), (afi)); \ + break; \ + default: \ + vnc_redistribute_set((bgp), (afi), (type)); \ + break; \ + } \ + } while (0) + +#define VNC_REDIST_DISABLE(bgp, afi, type) \ + do { \ + switch (type) { \ + case ZEBRA_ROUTE_BGP_DIRECT: \ + vnc_import_bgp_redist_disable((bgp), (afi)); \ + break; \ + case ZEBRA_ROUTE_BGP_DIRECT_EXT: \ + vnc_import_bgp_exterior_redist_disable((bgp), (afi)); \ + break; \ + default: \ + vnc_redistribute_unset((bgp), (afi), (type)); \ + break; \ + } \ + } while (0) static uint8_t redist_was_enabled[AFI_MAX][ZEBRA_ROUTE_MAX]; -static void -vnc_redistribute_prechange (struct bgp *bgp) +static void vnc_redistribute_prechange(struct bgp *bgp) { - afi_t afi; - int type; - - vnc_zlog_debug_verbose ("%s: entry", __func__); - memset (redist_was_enabled, 0, sizeof (redist_was_enabled)); - - /* - * Look to see if we have any redistribution enabled. If so, flush - * the corresponding routes and turn off redistribution temporarily. - * We need to do it because the RD's used for the redistributed - * routes depend on the nve group. - */ - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - for (type = 0; type < ZEBRA_ROUTE_MAX; ++type) - { - if (bgp->rfapi_cfg->redist[afi][type]) - { - redist_was_enabled[afi][type] = 1; - VNC_REDIST_DISABLE (bgp, afi, type); - } - } - } - vnc_zlog_debug_verbose ("%s: return", __func__); + afi_t afi; + int type; + + vnc_zlog_debug_verbose("%s: entry", __func__); + memset(redist_was_enabled, 0, sizeof(redist_was_enabled)); + + /* + * Look to see if we have any redistribution enabled. If so, flush + * the corresponding routes and turn off redistribution temporarily. + * We need to do it because the RD's used for the redistributed + * routes depend on the nve group. + */ + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + for (type = 0; type < ZEBRA_ROUTE_MAX; ++type) { + if (bgp->rfapi_cfg->redist[afi][type]) { + redist_was_enabled[afi][type] = 1; + VNC_REDIST_DISABLE(bgp, afi, type); + } + } + } + vnc_zlog_debug_verbose("%s: return", __func__); } -static void -vnc_redistribute_postchange (struct bgp *bgp) +static void vnc_redistribute_postchange(struct bgp *bgp) { - afi_t afi; - int type; - - vnc_zlog_debug_verbose ("%s: entry", __func__); - /* - * If we turned off redistribution above, turn it back on. Doing so - * will tell zebra to resend the routes to us - */ - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - for (type = 0; type < ZEBRA_ROUTE_MAX; ++type) - { - if (redist_was_enabled[afi][type]) - { - VNC_REDIST_ENABLE (bgp, afi, type); - } - } - } - vnc_zlog_debug_verbose ("%s: return", __func__); + afi_t afi; + int type; + + vnc_zlog_debug_verbose("%s: entry", __func__); + /* + * If we turned off redistribution above, turn it back on. Doing so + * will tell zebra to resend the routes to us + */ + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + for (type = 0; type < ZEBRA_ROUTE_MAX; ++type) { + if (redist_was_enabled[afi][type]) { + VNC_REDIST_ENABLE(bgp, afi, type); + } + } + } + vnc_zlog_debug_verbose("%s: return", __func__); } DEFUN (vnc_redistribute_rh_roo_localadmin, @@ -794,51 +732,46 @@ DEFUN (vnc_redistribute_rh_roo_localadmin, "Resolve-NVE mode\n" "Route Origin Extended Community Local Admin Field\n" "Field value\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - uint32_t localadmin; - char *endptr; - - if (!bgp->rfapi_cfg) - { - vty_out (vty, "RFAPI not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - localadmin = strtoul (argv[4]->arg, &endptr, 0); - if (!argv[4]->arg[0] || *endptr) - { - vty_out (vty, "%% Malformed value\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (localadmin > 0xffff) - { - vty_out (vty, "%% Value out of range (0-%d)\n", 0xffff); - return CMD_WARNING_CONFIG_FAILED; - } - - if (bgp->rfapi_cfg->resolve_nve_roo_local_admin == localadmin) - return CMD_SUCCESS; - - if ((bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) == - BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE) - { - - vnc_export_bgp_prechange (bgp); - } - vnc_redistribute_prechange (bgp); - - bgp->rfapi_cfg->resolve_nve_roo_local_admin = localadmin; - - if ((bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) == - BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE) - { - - vnc_export_bgp_postchange (bgp); - } - vnc_redistribute_postchange (bgp); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + uint32_t localadmin; + char *endptr; + + if (!bgp->rfapi_cfg) { + vty_out(vty, "RFAPI not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + localadmin = strtoul(argv[4]->arg, &endptr, 0); + if (!argv[4]->arg[0] || *endptr) { + vty_out(vty, "%% Malformed value\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (localadmin > 0xffff) { + vty_out(vty, "%% Value out of range (0-%d)\n", 0xffff); + return CMD_WARNING_CONFIG_FAILED; + } + + if (bgp->rfapi_cfg->resolve_nve_roo_local_admin == localadmin) + return CMD_SUCCESS; + + if ((bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) + == BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE) { + + vnc_export_bgp_prechange(bgp); + } + vnc_redistribute_prechange(bgp); + + bgp->rfapi_cfg->resolve_nve_roo_local_admin = localadmin; + + if ((bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) + == BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE) { + + vnc_export_bgp_postchange(bgp); + } + vnc_redistribute_postchange(bgp); + + return CMD_SUCCESS; } @@ -851,43 +784,40 @@ DEFUN (vnc_redistribute_mode, "Based on redistribute nve-group\n" "Unmodified\n" "Resolve each nexthop to connected NVEs\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - vnc_redist_mode_t newmode; - - if (!bgp->rfapi_cfg) - { - vty_out (vty, "RFAPI not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - - switch (argv[3]->arg[0]) - { - case 'n': - newmode = VNC_REDIST_MODE_RFG; - break; - - case 'p': - newmode = VNC_REDIST_MODE_PLAIN; - break; - - case 'r': - newmode = VNC_REDIST_MODE_RESOLVE_NVE; - break; - - default: - vty_out (vty, "unknown redistribute mode\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (newmode != bgp->rfapi_cfg->redist_mode) - { - vnc_redistribute_prechange (bgp); - bgp->rfapi_cfg->redist_mode = newmode; - vnc_redistribute_postchange (bgp); - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + vnc_redist_mode_t newmode; + + if (!bgp->rfapi_cfg) { + vty_out(vty, "RFAPI not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + + switch (argv[3]->arg[0]) { + case 'n': + newmode = VNC_REDIST_MODE_RFG; + break; + + case 'p': + newmode = VNC_REDIST_MODE_PLAIN; + break; + + case 'r': + newmode = VNC_REDIST_MODE_RESOLVE_NVE; + break; + + default: + vty_out(vty, "unknown redistribute mode\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (newmode != bgp->rfapi_cfg->redist_mode) { + vnc_redistribute_prechange(bgp); + bgp->rfapi_cfg->redist_mode = newmode; + vnc_redistribute_postchange(bgp); + } + + return CMD_SUCCESS; } DEFUN (vnc_redistribute_protocol, @@ -905,36 +835,33 @@ DEFUN (vnc_redistribute_protocol, "From Open Shortest Path First (OSPF)\n" "From Routing Information Protocol (RIP)\n" "From Static routes\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int type = ZEBRA_ROUTE_MAX; /* init to bogus value */ - afi_t afi; - - if (!bgp->rfapi_cfg) - { - vty_out (vty, "RFAPI not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (rfapi_str2route_type (argv[2]->arg, argv[3]->arg, &afi, &type)) - { - vty_out (vty, "%% Invalid route type\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (type == ZEBRA_ROUTE_BGP_DIRECT_EXT) - { - if (bgp->rfapi_cfg->redist_bgp_exterior_view_name) - { - VNC_REDIST_DISABLE (bgp, afi, type); /* disabled view implicitly */ - free (bgp->rfapi_cfg->redist_bgp_exterior_view_name); - bgp->rfapi_cfg->redist_bgp_exterior_view_name = NULL; - } - bgp->rfapi_cfg->redist_bgp_exterior_view = bgp; - } - - VNC_REDIST_ENABLE (bgp, afi, type); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int type = ZEBRA_ROUTE_MAX; /* init to bogus value */ + afi_t afi; + + if (!bgp->rfapi_cfg) { + vty_out(vty, "RFAPI not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (rfapi_str2route_type(argv[2]->arg, argv[3]->arg, &afi, &type)) { + vty_out(vty, "%% Invalid route type\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (type == ZEBRA_ROUTE_BGP_DIRECT_EXT) { + if (bgp->rfapi_cfg->redist_bgp_exterior_view_name) { + VNC_REDIST_DISABLE(bgp, afi, + type); /* disabled view implicitly */ + free(bgp->rfapi_cfg->redist_bgp_exterior_view_name); + bgp->rfapi_cfg->redist_bgp_exterior_view_name = NULL; + } + bgp->rfapi_cfg->redist_bgp_exterior_view = bgp; + } + + VNC_REDIST_ENABLE(bgp, afi, type); + + return CMD_SUCCESS; } DEFUN (vnc_no_redistribute_protocol, @@ -953,35 +880,31 @@ DEFUN (vnc_no_redistribute_protocol, "From Open Shortest Path First (OSPF)\n" "From Routing Information Protocol (RIP)\n" "From Static routes\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int type; - afi_t afi; - - if (!bgp->rfapi_cfg) - { - vty_out (vty, "RFAPI not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (rfapi_str2route_type (argv[3]->arg, argv[4]->arg, &afi, &type)) - { - vty_out (vty, "%% Invalid route type\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - VNC_REDIST_DISABLE (bgp, afi, type); - - if (type == ZEBRA_ROUTE_BGP_DIRECT_EXT) - { - if (bgp->rfapi_cfg->redist_bgp_exterior_view_name) - { - free (bgp->rfapi_cfg->redist_bgp_exterior_view_name); - bgp->rfapi_cfg->redist_bgp_exterior_view_name = NULL; - } - bgp->rfapi_cfg->redist_bgp_exterior_view = NULL; - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int type; + afi_t afi; + + if (!bgp->rfapi_cfg) { + vty_out(vty, "RFAPI not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (rfapi_str2route_type(argv[3]->arg, argv[4]->arg, &afi, &type)) { + vty_out(vty, "%% Invalid route type\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + VNC_REDIST_DISABLE(bgp, afi, type); + + if (type == ZEBRA_ROUTE_BGP_DIRECT_EXT) { + if (bgp->rfapi_cfg->redist_bgp_exterior_view_name) { + free(bgp->rfapi_cfg->redist_bgp_exterior_view_name); + bgp->rfapi_cfg->redist_bgp_exterior_view_name = NULL; + } + bgp->rfapi_cfg->redist_bgp_exterior_view = NULL; + } + + return CMD_SUCCESS; } DEFUN (vnc_redistribute_bgp_exterior, @@ -994,31 +917,31 @@ DEFUN (vnc_redistribute_bgp_exterior, "From BGP without Zebra, only to configured NVE groups\n" "From BGP view\n" "BGP view name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int type; - afi_t afi; - - if (!bgp->rfapi_cfg) - { - vty_out (vty, "RFAPI not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (rfapi_str2route_type (argv[2]->arg, "bgp-direct-to-nve-groups", &afi, &type)) - { - vty_out (vty, "%% Invalid route type\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (bgp->rfapi_cfg->redist_bgp_exterior_view_name) - free (bgp->rfapi_cfg->redist_bgp_exterior_view_name); - bgp->rfapi_cfg->redist_bgp_exterior_view_name = strdup (argv[5]->arg); - /* could be NULL if name is not defined yet */ - bgp->rfapi_cfg->redist_bgp_exterior_view = bgp_lookup_by_name (argv[5]->arg); - - VNC_REDIST_ENABLE (bgp, afi, type); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int type; + afi_t afi; + + if (!bgp->rfapi_cfg) { + vty_out(vty, "RFAPI not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (rfapi_str2route_type(argv[2]->arg, "bgp-direct-to-nve-groups", &afi, + &type)) { + vty_out(vty, "%% Invalid route type\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (bgp->rfapi_cfg->redist_bgp_exterior_view_name) + free(bgp->rfapi_cfg->redist_bgp_exterior_view_name); + bgp->rfapi_cfg->redist_bgp_exterior_view_name = strdup(argv[5]->arg); + /* could be NULL if name is not defined yet */ + bgp->rfapi_cfg->redist_bgp_exterior_view = + bgp_lookup_by_name(argv[5]->arg); + + VNC_REDIST_ENABLE(bgp, afi, type); + + return CMD_SUCCESS; } DEFUN (vnc_redistribute_nvegroup, @@ -1028,29 +951,28 @@ DEFUN (vnc_redistribute_nvegroup, "Assign a NVE group to routes redistributed from another routing protocol\n" "NVE group\n" "Group name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); - if (!bgp->rfapi_cfg) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!bgp->rfapi_cfg) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } - vnc_redistribute_prechange (bgp); + vnc_redistribute_prechange(bgp); - /* - * OK if nve group doesn't exist yet; we'll set the pointer - * when the group is defined later - */ - bgp->rfapi_cfg->rfg_redist = bgp_rfapi_cfg_match_byname (bgp, argv[3]->arg, - RFAPI_GROUP_CFG_NVE); - if (bgp->rfapi_cfg->rfg_redist_name) - free (bgp->rfapi_cfg->rfg_redist_name); - bgp->rfapi_cfg->rfg_redist_name = strdup (argv[3]->arg); + /* + * OK if nve group doesn't exist yet; we'll set the pointer + * when the group is defined later + */ + bgp->rfapi_cfg->rfg_redist = bgp_rfapi_cfg_match_byname( + bgp, argv[3]->arg, RFAPI_GROUP_CFG_NVE); + if (bgp->rfapi_cfg->rfg_redist_name) + free(bgp->rfapi_cfg->rfg_redist_name); + bgp->rfapi_cfg->rfg_redist_name = strdup(argv[3]->arg); - vnc_redistribute_postchange (bgp); + vnc_redistribute_postchange(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (vnc_redistribute_no_nvegroup, @@ -1061,24 +983,23 @@ DEFUN (vnc_redistribute_no_nvegroup, "Redistribute from other protocol\n" "Assign a NVE group to routes redistributed from another routing protocol\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); - if (!bgp->rfapi_cfg) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!bgp->rfapi_cfg) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } - vnc_redistribute_prechange (bgp); + vnc_redistribute_prechange(bgp); - bgp->rfapi_cfg->rfg_redist = NULL; - if (bgp->rfapi_cfg->rfg_redist_name) - free (bgp->rfapi_cfg->rfg_redist_name); - bgp->rfapi_cfg->rfg_redist_name = NULL; + bgp->rfapi_cfg->rfg_redist = NULL; + if (bgp->rfapi_cfg->rfg_redist_name) + free(bgp->rfapi_cfg->rfg_redist_name); + bgp->rfapi_cfg->rfg_redist_name = NULL; - vnc_redistribute_postchange (bgp); + vnc_redistribute_postchange(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1091,28 +1012,25 @@ DEFUN (vnc_redistribute_lifetime, "lifetime value (32 bit)\n" "Allow lifetime to never expire\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); - if (!bgp->rfapi_cfg) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!bgp->rfapi_cfg) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } - vnc_redistribute_prechange (bgp); + vnc_redistribute_prechange(bgp); - if (strmatch(argv[3]->text, "infinite")) - { - bgp->rfapi_cfg->redist_lifetime = RFAPI_INFINITE_LIFETIME; - } - else - { - bgp->rfapi_cfg->redist_lifetime = strtoul(argv[3]->arg, NULL, 10); - } + if (strmatch(argv[3]->text, "infinite")) { + bgp->rfapi_cfg->redist_lifetime = RFAPI_INFINITE_LIFETIME; + } else { + bgp->rfapi_cfg->redist_lifetime = + strtoul(argv[3]->arg, NULL, 10); + } - vnc_redistribute_postchange (bgp); + vnc_redistribute_postchange(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } /*-- redist policy, non-nvegroup start --*/ @@ -1128,45 +1046,38 @@ DEFUN (vnc_redist_bgpdirect_no_prefixlist, "IPv4 routes\n" "IPv6 routes\n" "Prefix-list for filtering redistributed routes\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - afi_t afi; - struct rfapi_cfg *hc; - uint8_t route_type = 0; - - if (!(hc = bgp->rfapi_cfg)) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (strmatch(argv[3]->text, "bgp-direct")) - { - route_type = ZEBRA_ROUTE_BGP_DIRECT; - } - else - { - route_type = ZEBRA_ROUTE_BGP_DIRECT_EXT; - } - - if (strmatch(argv[4]->text, "ipv4")) - { - afi = AFI_IP; - } - else - { - afi = AFI_IP6; - } - - vnc_redistribute_prechange (bgp); - - if (hc->plist_redist_name[route_type][afi]) - free (hc->plist_redist_name[route_type][afi]); - hc->plist_redist_name[route_type][afi] = NULL; - hc->plist_redist[route_type][afi] = NULL; - - vnc_redistribute_postchange (bgp); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + afi_t afi; + struct rfapi_cfg *hc; + uint8_t route_type = 0; + + if (!(hc = bgp->rfapi_cfg)) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (strmatch(argv[3]->text, "bgp-direct")) { + route_type = ZEBRA_ROUTE_BGP_DIRECT; + } else { + route_type = ZEBRA_ROUTE_BGP_DIRECT_EXT; + } + + if (strmatch(argv[4]->text, "ipv4")) { + afi = AFI_IP; + } else { + afi = AFI_IP6; + } + + vnc_redistribute_prechange(bgp); + + if (hc->plist_redist_name[route_type][afi]) + free(hc->plist_redist_name[route_type][afi]); + hc->plist_redist_name[route_type][afi] = NULL; + hc->plist_redist[route_type][afi] = NULL; + + vnc_redistribute_postchange(bgp); + + return CMD_SUCCESS; } DEFUN (vnc_redist_bgpdirect_prefixlist, @@ -1181,45 +1092,39 @@ DEFUN (vnc_redist_bgpdirect_prefixlist, "Prefix-list for filtering redistributed routes\n" "prefix list name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - struct rfapi_cfg *hc; - afi_t afi; - uint8_t route_type = 0; - - if (!(hc = bgp->rfapi_cfg)) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (strmatch(argv[2]->text, "bgp-direct")) - { - route_type = ZEBRA_ROUTE_BGP_DIRECT; - } - else - { - route_type = ZEBRA_ROUTE_BGP_DIRECT_EXT; - } - - if (strmatch(argv[3]->text, "ipv4")) - { - afi = AFI_IP; - } - else - { - afi = AFI_IP6; - } - - vnc_redistribute_prechange (bgp); - - if (hc->plist_redist_name[route_type][afi]) - free (hc->plist_redist_name[route_type][afi]); - hc->plist_redist_name[route_type][afi] = strdup (argv[5]->arg); - hc->plist_redist[route_type][afi] = prefix_list_lookup (afi, argv[5]->arg); - - vnc_redistribute_postchange (bgp); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + struct rfapi_cfg *hc; + afi_t afi; + uint8_t route_type = 0; + + if (!(hc = bgp->rfapi_cfg)) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (strmatch(argv[2]->text, "bgp-direct")) { + route_type = ZEBRA_ROUTE_BGP_DIRECT; + } else { + route_type = ZEBRA_ROUTE_BGP_DIRECT_EXT; + } + + if (strmatch(argv[3]->text, "ipv4")) { + afi = AFI_IP; + } else { + afi = AFI_IP6; + } + + vnc_redistribute_prechange(bgp); + + if (hc->plist_redist_name[route_type][afi]) + free(hc->plist_redist_name[route_type][afi]); + hc->plist_redist_name[route_type][afi] = strdup(argv[5]->arg); + hc->plist_redist[route_type][afi] = + prefix_list_lookup(afi, argv[5]->arg); + + vnc_redistribute_postchange(bgp); + + return CMD_SUCCESS; } DEFUN (vnc_redist_bgpdirect_no_routemap, @@ -1232,35 +1137,31 @@ DEFUN (vnc_redist_bgpdirect_no_routemap, "Redistribute from BGP without Zebra, only to configured NVE groups\n" "Route-map for filtering redistributed routes\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - struct rfapi_cfg *hc; - uint8_t route_type = 0; - - if (!(hc = bgp->rfapi_cfg)) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (strmatch(argv[3]->text, "bgp-direct")) - { - route_type = ZEBRA_ROUTE_BGP_DIRECT; - } - else - { - route_type = ZEBRA_ROUTE_BGP_DIRECT_EXT; - } - - vnc_redistribute_prechange (bgp); - - if (hc->routemap_redist_name[route_type]) - free (hc->routemap_redist_name[route_type]); - hc->routemap_redist_name[route_type] = NULL; - hc->routemap_redist[route_type] = NULL; - - vnc_redistribute_postchange (bgp); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + struct rfapi_cfg *hc; + uint8_t route_type = 0; + + if (!(hc = bgp->rfapi_cfg)) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (strmatch(argv[3]->text, "bgp-direct")) { + route_type = ZEBRA_ROUTE_BGP_DIRECT; + } else { + route_type = ZEBRA_ROUTE_BGP_DIRECT_EXT; + } + + vnc_redistribute_prechange(bgp); + + if (hc->routemap_redist_name[route_type]) + free(hc->routemap_redist_name[route_type]); + hc->routemap_redist_name[route_type] = NULL; + hc->routemap_redist[route_type] = NULL; + + vnc_redistribute_postchange(bgp); + + return CMD_SUCCESS; } DEFUN (vnc_redist_bgpdirect_routemap, @@ -1272,35 +1173,32 @@ DEFUN (vnc_redist_bgpdirect_routemap, "Redistribute from BGP without Zebra, only to configured NVE groups\n" "Route-map for filtering exported routes\n" "route map name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - struct rfapi_cfg *hc; - uint8_t route_type = 0; - - if (!(hc = bgp->rfapi_cfg)) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (strmatch(argv[2]->text, "bgp-direct")) - { - route_type = ZEBRA_ROUTE_BGP_DIRECT; - } - else - { - route_type = ZEBRA_ROUTE_BGP_DIRECT_EXT; - } - - vnc_redistribute_prechange (bgp); - - if (hc->routemap_redist_name[route_type]) - free (hc->routemap_redist_name[route_type]); - hc->routemap_redist_name[route_type] = strdup (argv[4]->arg); - hc->routemap_redist[route_type] = route_map_lookup_by_name (argv[4]->arg); - - vnc_redistribute_postchange (bgp); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + struct rfapi_cfg *hc; + uint8_t route_type = 0; + + if (!(hc = bgp->rfapi_cfg)) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (strmatch(argv[2]->text, "bgp-direct")) { + route_type = ZEBRA_ROUTE_BGP_DIRECT; + } else { + route_type = ZEBRA_ROUTE_BGP_DIRECT_EXT; + } + + vnc_redistribute_prechange(bgp); + + if (hc->routemap_redist_name[route_type]) + free(hc->routemap_redist_name[route_type]); + hc->routemap_redist_name[route_type] = strdup(argv[4]->arg); + hc->routemap_redist[route_type] = + route_map_lookup_by_name(argv[4]->arg); + + vnc_redistribute_postchange(bgp); + + return CMD_SUCCESS; } /*-- redist policy, non-nvegroup end --*/ @@ -1317,43 +1215,38 @@ DEFUN (vnc_nve_group_redist_bgpdirect_no_prefixlist, "IPv6 routes\n" "Prefix-list for filtering redistributed routes\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg) - afi_t afi; - - if (!bgp->rfapi_cfg) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (strmatch(argv[3]->text, "ipv4")) - { - afi = AFI_IP; - } - else - { - afi = AFI_IP6; - } - - vnc_redistribute_prechange (bgp); - - if (rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]) - free (rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]); - rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi] = NULL; - rfg->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi] = NULL; - - vnc_redistribute_postchange (bgp); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg) + afi_t afi; + + if (!bgp->rfapi_cfg) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (strmatch(argv[3]->text, "ipv4")) { + afi = AFI_IP; + } else { + afi = AFI_IP6; + } + + vnc_redistribute_prechange(bgp); + + if (rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]) + free(rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]); + rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi] = NULL; + rfg->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi] = NULL; + + vnc_redistribute_postchange(bgp); + + return CMD_SUCCESS; } DEFUN (vnc_nve_group_redist_bgpdirect_prefixlist, @@ -1366,44 +1259,40 @@ DEFUN (vnc_nve_group_redist_bgpdirect_prefixlist, "Prefix-list for filtering redistributed routes\n" "prefix list name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - afi_t afi; - - if (!bgp->rfapi_cfg) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (strmatch(argv[2]->text, "ipv4")) - { - afi = AFI_IP; - } - else - { - afi = AFI_IP6; - } - - vnc_redistribute_prechange (bgp); - - if (rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]) - free (rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]); - rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi] = strdup (argv[4]->arg); - rfg->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi] = - prefix_list_lookup (afi, argv[4]->arg); - - vnc_redistribute_postchange (bgp); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + afi_t afi; + + if (!bgp->rfapi_cfg) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (strmatch(argv[2]->text, "ipv4")) { + afi = AFI_IP; + } else { + afi = AFI_IP6; + } + + vnc_redistribute_prechange(bgp); + + if (rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]) + free(rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]); + rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi] = + strdup(argv[4]->arg); + rfg->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi] = + prefix_list_lookup(afi, argv[4]->arg); + + vnc_redistribute_postchange(bgp); + + return CMD_SUCCESS; } DEFUN (vnc_nve_group_redist_bgpdirect_no_routemap, @@ -1414,33 +1303,31 @@ DEFUN (vnc_nve_group_redist_bgpdirect_no_routemap, "Redistribute from BGP directly\n" "Route-map for filtering redistributed routes\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - if (!bgp->rfapi_cfg) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!bgp->rfapi_cfg) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } - vnc_redistribute_prechange (bgp); + vnc_redistribute_prechange(bgp); - if (rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]) - free (rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]); - rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT] = NULL; - rfg->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT] = NULL; + if (rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]) + free(rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]); + rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT] = NULL; + rfg->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT] = NULL; - vnc_redistribute_postchange (bgp); + vnc_redistribute_postchange(bgp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (vnc_nve_group_redist_bgpdirect_routemap, @@ -1450,34 +1337,33 @@ DEFUN (vnc_nve_group_redist_bgpdirect_routemap, "Redistribute from BGP directly\n" "Route-map for filtering exported routes\n" "route map name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - - if (!bgp->rfapi_cfg) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - vnc_redistribute_prechange (bgp); - - if (rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]) - free (rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]); - rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT] = strdup (argv[3]->arg); - rfg->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT] = - route_map_lookup_by_name (argv[3]->arg); - - vnc_redistribute_postchange (bgp); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + + if (!bgp->rfapi_cfg) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + vnc_redistribute_prechange(bgp); + + if (rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]) + free(rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]); + rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT] = + strdup(argv[3]->arg); + rfg->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT] = + route_map_lookup_by_name(argv[3]->arg); + + vnc_redistribute_postchange(bgp); + + return CMD_SUCCESS; } /*-- redist policy, nvegroup end --*/ @@ -1498,116 +1384,106 @@ DEFUN (vnc_export_mode, "Export routes with NVE connected router next-hops\n" "Disable export\n" "Export routes with registering NVE as next-hop\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - uint32_t oldmode = 0; - uint32_t newmode = 0; - - if (!bgp->rfapi_cfg) - { - vty_out (vty, "VNC not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (argv[2]->arg[0] == 'b') - { - oldmode = bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS; - switch (argv[4]->arg[0]) - { - case 'g': - newmode = BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP; - break; - case 'c': - newmode = BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE; - break; - case 'n': - newmode = 0; - break; - case 'r': - newmode = BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH; - break; - default: - vty_out (vty, "Invalid mode specified\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (newmode == oldmode) - { - vty_out (vty, "Mode unchanged\n"); - return CMD_SUCCESS; - } - - vnc_export_bgp_prechange (bgp); - - bgp->rfapi_cfg->flags &= ~BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS; - bgp->rfapi_cfg->flags |= newmode; - - vnc_export_bgp_postchange (bgp); - - - } - else - { - /* - * export to zebra with RH mode is not yet implemented - */ - vty_out (vty,"Changing modes for zebra export not implemented yet\n"); - return CMD_WARNING_CONFIG_FAILED; - - oldmode = bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS; - bgp->rfapi_cfg->flags &= ~BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS; - switch (argv[4]->arg[0]) - { - case 'g': - if (oldmode == BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_RH) - { - /* TBD */ - } - bgp->rfapi_cfg->flags |= BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP; - if (oldmode != BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP) - { - /* TBD */ - } - break; - case 'n': - if (oldmode == BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_RH) - { - /* TBD */ - } - if (oldmode == BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP) - { - /* TBD */ - } - break; - case 'r': - if (oldmode == BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP) - { - /* TBD */ - } - bgp->rfapi_cfg->flags |= BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_RH; - if (oldmode != BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_RH) - { - /* TBD */ - } - break; - default: - vty_out (vty, "Invalid mode\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + uint32_t oldmode = 0; + uint32_t newmode = 0; + + if (!bgp->rfapi_cfg) { + vty_out(vty, "VNC not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (argv[2]->arg[0] == 'b') { + oldmode = bgp->rfapi_cfg->flags + & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS; + switch (argv[4]->arg[0]) { + case 'g': + newmode = BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP; + break; + case 'c': + newmode = BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE; + break; + case 'n': + newmode = 0; + break; + case 'r': + newmode = BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH; + break; + default: + vty_out(vty, "Invalid mode specified\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (newmode == oldmode) { + vty_out(vty, "Mode unchanged\n"); + return CMD_SUCCESS; + } + + vnc_export_bgp_prechange(bgp); + + bgp->rfapi_cfg->flags &= ~BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS; + bgp->rfapi_cfg->flags |= newmode; + + vnc_export_bgp_postchange(bgp); + + + } else { + /* + * export to zebra with RH mode is not yet implemented + */ + vty_out(vty, + "Changing modes for zebra export not implemented yet\n"); + return CMD_WARNING_CONFIG_FAILED; + + oldmode = bgp->rfapi_cfg->flags + & BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS; + bgp->rfapi_cfg->flags &= ~BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS; + switch (argv[4]->arg[0]) { + case 'g': + if (oldmode == BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_RH) { + /* TBD */ + } + bgp->rfapi_cfg->flags |= + BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP; + if (oldmode != BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP) { + /* TBD */ + } + break; + case 'n': + if (oldmode == BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_RH) { + /* TBD */ + } + if (oldmode == BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP) { + /* TBD */ + } + break; + case 'r': + if (oldmode == BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP) { + /* TBD */ + } + bgp->rfapi_cfg->flags |= + BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_RH; + if (oldmode != BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_RH) { + /* TBD */ + } + break; + default: + vty_out(vty, "Invalid mode\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + return CMD_SUCCESS; } -static struct rfapi_rfg_name * -rfgn_new () +static struct rfapi_rfg_name *rfgn_new() { - return XCALLOC (MTYPE_RFAPI_RFG_NAME, sizeof (struct rfapi_rfg_name)); + return XCALLOC(MTYPE_RFAPI_RFG_NAME, sizeof(struct rfapi_rfg_name)); } -static void -rfgn_free (struct rfapi_rfg_name *rfgn) +static void rfgn_free(struct rfapi_rfg_name *rfgn) { - XFREE (MTYPE_RFAPI_RFG_NAME, rfgn); + XFREE(MTYPE_RFAPI_RFG_NAME, rfgn); } DEFUN (vnc_export_nvegroup, @@ -1620,91 +1496,86 @@ DEFUN (vnc_export_nvegroup, "NVE group, used in 'group-nve' export mode\n" "NVE group\n" "Group name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - struct rfapi_nve_group_cfg *rfg_new; - - if (!bgp->rfapi_cfg) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - rfg_new = bgp_rfapi_cfg_match_byname (bgp, argv[5]->arg, RFAPI_GROUP_CFG_NVE); - - if (argv[2]->arg[0] == 'b') - { - - struct listnode *node; - struct rfapi_rfg_name *rfgn; - - /* - * Set group for export to BGP Direct - */ - - /* see if group is already included in export list */ - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_direct_bgp_l, - node, rfgn)) - { - - if (!strcmp (rfgn->name, argv[5]->arg)) - { - /* already in the list: we're done */ - return CMD_SUCCESS; - } - } - - rfgn = rfgn_new (); - rfgn->name = strdup (argv[5]->arg); - rfgn->rfg = rfg_new; /* OK if not set yet */ - - listnode_add (bgp->rfapi_cfg->rfg_export_direct_bgp_l, rfgn); - - vnc_zlog_debug_verbose ("%s: testing rfg_new", __func__); - if (rfg_new) - { - vnc_zlog_debug_verbose ("%s: testing bgp grp mode enabled", __func__); - if (VNC_EXPORT_BGP_GRP_ENABLED (bgp->rfapi_cfg)) - vnc_zlog_debug_verbose ("%s: calling vnc_direct_bgp_add_group", __func__); - vnc_direct_bgp_add_group (bgp, rfg_new); - } - - } - else - { - - struct listnode *node; - struct rfapi_rfg_name *rfgn; - - /* - * Set group for export to Zebra - */ - - /* see if group is already included in export list */ - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_zebra_l, - node, rfgn)) - { - - if (!strcmp (rfgn->name, argv[5]->arg)) - { - /* already in the list: we're done */ - return CMD_SUCCESS; - } - } - - rfgn = rfgn_new (); - rfgn->name = strdup (argv[5]->arg); - rfgn->rfg = rfg_new; /* OK if not set yet */ - - listnode_add (bgp->rfapi_cfg->rfg_export_zebra_l, rfgn); - - if (rfg_new) - { - if (VNC_EXPORT_ZEBRA_GRP_ENABLED (bgp->rfapi_cfg)) - vnc_zebra_add_group (bgp, rfg_new); - } - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + struct rfapi_nve_group_cfg *rfg_new; + + if (!bgp->rfapi_cfg) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + rfg_new = bgp_rfapi_cfg_match_byname(bgp, argv[5]->arg, + RFAPI_GROUP_CFG_NVE); + + if (argv[2]->arg[0] == 'b') { + + struct listnode *node; + struct rfapi_rfg_name *rfgn; + + /* + * Set group for export to BGP Direct + */ + + /* see if group is already included in export list */ + for (ALL_LIST_ELEMENTS_RO( + bgp->rfapi_cfg->rfg_export_direct_bgp_l, node, + rfgn)) { + + if (!strcmp(rfgn->name, argv[5]->arg)) { + /* already in the list: we're done */ + return CMD_SUCCESS; + } + } + + rfgn = rfgn_new(); + rfgn->name = strdup(argv[5]->arg); + rfgn->rfg = rfg_new; /* OK if not set yet */ + + listnode_add(bgp->rfapi_cfg->rfg_export_direct_bgp_l, rfgn); + + vnc_zlog_debug_verbose("%s: testing rfg_new", __func__); + if (rfg_new) { + vnc_zlog_debug_verbose( + "%s: testing bgp grp mode enabled", __func__); + if (VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) + vnc_zlog_debug_verbose( + "%s: calling vnc_direct_bgp_add_group", + __func__); + vnc_direct_bgp_add_group(bgp, rfg_new); + } + + } else { + + struct listnode *node; + struct rfapi_rfg_name *rfgn; + + /* + * Set group for export to Zebra + */ + + /* see if group is already included in export list */ + for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_zebra_l, + node, rfgn)) { + + if (!strcmp(rfgn->name, argv[5]->arg)) { + /* already in the list: we're done */ + return CMD_SUCCESS; + } + } + + rfgn = rfgn_new(); + rfgn->name = strdup(argv[5]->arg); + rfgn->rfg = rfg_new; /* OK if not set yet */ + + listnode_add(bgp->rfapi_cfg->rfg_export_zebra_l, rfgn); + + if (rfg_new) { + if (VNC_EXPORT_ZEBRA_GRP_ENABLED(bgp->rfapi_cfg)) + vnc_zebra_add_group(bgp, rfg_new); + } + } + + return CMD_SUCCESS; } /* @@ -1721,54 +1592,52 @@ DEFUN (vnc_no_export_nvegroup, "NVE group, used in 'group-nve' export mode\n" "Disable export of VNC routes\n" "NVE group\n" "Group name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - struct listnode *node, *nnode; - struct rfapi_rfg_name *rfgn; - - if (!bgp->rfapi_cfg) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (argv[2]->arg[0] == 'b') - { - for (ALL_LIST_ELEMENTS (bgp->rfapi_cfg->rfg_export_direct_bgp_l, - node, nnode, rfgn)) - { - - if (rfgn->name && !strcmp (rfgn->name, argv[6]->arg)) - { - vnc_zlog_debug_verbose ("%s: matched \"%s\"", __func__, rfgn->name); - if (rfgn->rfg) - vnc_direct_bgp_del_group (bgp, rfgn->rfg); - free (rfgn->name); - list_delete_node (bgp->rfapi_cfg->rfg_export_direct_bgp_l, - node); - rfgn_free (rfgn); - break; - } - } - } - else - { - for (ALL_LIST_ELEMENTS (bgp->rfapi_cfg->rfg_export_zebra_l, - node, nnode, rfgn)) - { - - vnc_zlog_debug_verbose ("does rfg \"%s\" match?", rfgn->name); - if (rfgn->name && !strcmp (rfgn->name, argv[6]->arg)) - { - if (rfgn->rfg) - vnc_zebra_del_group (bgp, rfgn->rfg); - free (rfgn->name); - list_delete_node (bgp->rfapi_cfg->rfg_export_zebra_l, node); - rfgn_free (rfgn); - break; - } - } - } - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + struct listnode *node, *nnode; + struct rfapi_rfg_name *rfgn; + + if (!bgp->rfapi_cfg) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (argv[2]->arg[0] == 'b') { + for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_direct_bgp_l, + node, nnode, rfgn)) { + + if (rfgn->name && !strcmp(rfgn->name, argv[6]->arg)) { + vnc_zlog_debug_verbose("%s: matched \"%s\"", + __func__, rfgn->name); + if (rfgn->rfg) + vnc_direct_bgp_del_group(bgp, + rfgn->rfg); + free(rfgn->name); + list_delete_node( + bgp->rfapi_cfg->rfg_export_direct_bgp_l, + node); + rfgn_free(rfgn); + break; + } + } + } else { + for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_zebra_l, node, + nnode, rfgn)) { + + vnc_zlog_debug_verbose("does rfg \"%s\" match?", + rfgn->name); + if (rfgn->name && !strcmp(rfgn->name, argv[6]->arg)) { + if (rfgn->rfg) + vnc_zebra_del_group(bgp, rfgn->rfg); + free(rfgn->name); + list_delete_node( + bgp->rfapi_cfg->rfg_export_zebra_l, + node); + rfgn_free(rfgn); + break; + } + } + } + return CMD_SUCCESS; } DEFUN (vnc_nve_group_export_no_prefixlist, @@ -1782,63 +1651,53 @@ DEFUN (vnc_nve_group_export_no_prefixlist, "IPv6 routes\n" "Prefix-list for filtering exported routes\n" "prefix list name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - afi_t afi; - - if (!bgp->rfapi_cfg) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (strmatch(argv[3]->text, "ipv4")) - { - afi = AFI_IP; - } - else - { - afi = AFI_IP6; - } - - if (argv[2]->arg[0] == 'b') - { - if (((argc > 5) - && strmatch(argv[5]->text, rfg->plist_export_bgp_name[afi])) - || (argc <= 5)) - { - - if (rfg->plist_export_bgp_name[afi]) - free (rfg->plist_export_bgp_name[afi]); - rfg->plist_export_bgp_name[afi] = NULL; - rfg->plist_export_bgp[afi] = NULL; - - vnc_direct_bgp_reexport_group_afi (bgp, rfg, afi); - } - } - else - { - if (((argc > 5) - && strmatch(argv[5]->text, rfg->plist_export_zebra_name[afi])) - || (argc <= 5)) - { - if (rfg->plist_export_zebra_name[afi]) - free (rfg->plist_export_zebra_name[afi]); - rfg->plist_export_zebra_name[afi] = NULL; - rfg->plist_export_zebra[afi] = NULL; - - vnc_zebra_reexport_group_afi (bgp, rfg, afi); - } - } - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + afi_t afi; + + if (!bgp->rfapi_cfg) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (strmatch(argv[3]->text, "ipv4")) { + afi = AFI_IP; + } else { + afi = AFI_IP6; + } + + if (argv[2]->arg[0] == 'b') { + if (((argc > 5) && strmatch(argv[5]->text, + rfg->plist_export_bgp_name[afi])) + || (argc <= 5)) { + + if (rfg->plist_export_bgp_name[afi]) + free(rfg->plist_export_bgp_name[afi]); + rfg->plist_export_bgp_name[afi] = NULL; + rfg->plist_export_bgp[afi] = NULL; + + vnc_direct_bgp_reexport_group_afi(bgp, rfg, afi); + } + } else { + if (((argc > 5) && strmatch(argv[5]->text, + rfg->plist_export_zebra_name[afi])) + || (argc <= 5)) { + if (rfg->plist_export_zebra_name[afi]) + free(rfg->plist_export_zebra_name[afi]); + rfg->plist_export_zebra_name[afi] = NULL; + rfg->plist_export_zebra[afi] = NULL; + + vnc_zebra_reexport_group_afi(bgp, rfg, afi); + } + } + return CMD_SUCCESS; } DEFUN (vnc_nve_group_export_prefixlist, @@ -1851,53 +1710,47 @@ DEFUN (vnc_nve_group_export_prefixlist, "IPv6 routes\n" "Prefix-list for filtering exported routes\n" "prefix list name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - afi_t afi; - - if (!bgp->rfapi_cfg) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (strmatch(argv[2]->text, "ipv4")) - { - afi = AFI_IP; - } - else - { - afi = AFI_IP6; - } - - if (argv[1]->arg[0] == 'b') - { - if (rfg->plist_export_bgp_name[afi]) - free (rfg->plist_export_bgp_name[afi]); - rfg->plist_export_bgp_name[afi] = strdup (argv[4]->arg); - rfg->plist_export_bgp[afi] = prefix_list_lookup (afi, argv[4]->arg); - - vnc_direct_bgp_reexport_group_afi (bgp, rfg, afi); - - } - else - { - if (rfg->plist_export_zebra_name[afi]) - free (rfg->plist_export_zebra_name[afi]); - rfg->plist_export_zebra_name[afi] = strdup (argv[4]->arg); - rfg->plist_export_zebra[afi] = prefix_list_lookup (afi, argv[4]->arg); - - vnc_zebra_reexport_group_afi (bgp, rfg, afi); - } - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + afi_t afi; + + if (!bgp->rfapi_cfg) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (strmatch(argv[2]->text, "ipv4")) { + afi = AFI_IP; + } else { + afi = AFI_IP6; + } + + if (argv[1]->arg[0] == 'b') { + if (rfg->plist_export_bgp_name[afi]) + free(rfg->plist_export_bgp_name[afi]); + rfg->plist_export_bgp_name[afi] = strdup(argv[4]->arg); + rfg->plist_export_bgp[afi] = + prefix_list_lookup(afi, argv[4]->arg); + + vnc_direct_bgp_reexport_group_afi(bgp, rfg, afi); + + } else { + if (rfg->plist_export_zebra_name[afi]) + free(rfg->plist_export_zebra_name[afi]); + rfg->plist_export_zebra_name[afi] = strdup(argv[4]->arg); + rfg->plist_export_zebra[afi] = + prefix_list_lookup(afi, argv[4]->arg); + + vnc_zebra_reexport_group_afi(bgp, rfg, afi); + } + return CMD_SUCCESS; } DEFUN (vnc_nve_group_export_no_routemap, @@ -1909,55 +1762,48 @@ DEFUN (vnc_nve_group_export_no_routemap, "Export to Zebra (experimental)\n" "Route-map for filtering exported routes\n" "route map name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - - if (!bgp->rfapi_cfg) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (argv[2]->arg[0] == 'b') - { - if (((argc > 4) - && strmatch(argv[4]->text, rfg->routemap_export_bgp_name)) - || (argc <= 4)) - { - - if (rfg->routemap_export_bgp_name) - free (rfg->routemap_export_bgp_name); - rfg->routemap_export_bgp_name = NULL; - rfg->routemap_export_bgp = NULL; - - vnc_direct_bgp_reexport_group_afi (bgp, rfg, AFI_IP); - vnc_direct_bgp_reexport_group_afi (bgp, rfg, AFI_IP6); - } - } - else - { - if (((argc > 4) - && strmatch(argv[4]->text, rfg->routemap_export_zebra_name)) - || (argc <= 4)) - { - if (rfg->routemap_export_zebra_name) - free (rfg->routemap_export_zebra_name); - rfg->routemap_export_zebra_name = NULL; - rfg->routemap_export_zebra = NULL; - - vnc_zebra_reexport_group_afi (bgp, rfg, AFI_IP); - vnc_zebra_reexport_group_afi (bgp, rfg, AFI_IP6); - } - } - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + + if (!bgp->rfapi_cfg) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (argv[2]->arg[0] == 'b') { + if (((argc > 4) + && strmatch(argv[4]->text, rfg->routemap_export_bgp_name)) + || (argc <= 4)) { + + if (rfg->routemap_export_bgp_name) + free(rfg->routemap_export_bgp_name); + rfg->routemap_export_bgp_name = NULL; + rfg->routemap_export_bgp = NULL; + + vnc_direct_bgp_reexport_group_afi(bgp, rfg, AFI_IP); + vnc_direct_bgp_reexport_group_afi(bgp, rfg, AFI_IP6); + } + } else { + if (((argc > 4) && strmatch(argv[4]->text, + rfg->routemap_export_zebra_name)) + || (argc <= 4)) { + if (rfg->routemap_export_zebra_name) + free(rfg->routemap_export_zebra_name); + rfg->routemap_export_zebra_name = NULL; + rfg->routemap_export_zebra = NULL; + + vnc_zebra_reexport_group_afi(bgp, rfg, AFI_IP); + vnc_zebra_reexport_group_afi(bgp, rfg, AFI_IP6); + } + } + return CMD_SUCCESS; } DEFUN (vnc_nve_group_export_routemap, @@ -1968,42 +1814,39 @@ DEFUN (vnc_nve_group_export_routemap, "Export to Zebra (experimental)\n" "Route-map for filtering exported routes\n" "route map name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - - if (!bgp->rfapi_cfg) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (argv[1]->arg[0] == 'b') - { - if (rfg->routemap_export_bgp_name) - free (rfg->routemap_export_bgp_name); - rfg->routemap_export_bgp_name = strdup (argv[3]->arg); - rfg->routemap_export_bgp = route_map_lookup_by_name (argv[3]->arg); - vnc_direct_bgp_reexport_group_afi (bgp, rfg, AFI_IP); - vnc_direct_bgp_reexport_group_afi (bgp, rfg, AFI_IP6); - } - else - { - if (rfg->routemap_export_zebra_name) - free (rfg->routemap_export_zebra_name); - rfg->routemap_export_zebra_name = strdup (argv[3]->arg); - rfg->routemap_export_zebra = route_map_lookup_by_name (argv[3]->arg); - vnc_zebra_reexport_group_afi (bgp, rfg, AFI_IP); - vnc_zebra_reexport_group_afi (bgp, rfg, AFI_IP6); - } - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + + if (!bgp->rfapi_cfg) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (argv[1]->arg[0] == 'b') { + if (rfg->routemap_export_bgp_name) + free(rfg->routemap_export_bgp_name); + rfg->routemap_export_bgp_name = strdup(argv[3]->arg); + rfg->routemap_export_bgp = + route_map_lookup_by_name(argv[3]->arg); + vnc_direct_bgp_reexport_group_afi(bgp, rfg, AFI_IP); + vnc_direct_bgp_reexport_group_afi(bgp, rfg, AFI_IP6); + } else { + if (rfg->routemap_export_zebra_name) + free(rfg->routemap_export_zebra_name); + rfg->routemap_export_zebra_name = strdup(argv[3]->arg); + rfg->routemap_export_zebra = + route_map_lookup_by_name(argv[3]->arg); + vnc_zebra_reexport_group_afi(bgp, rfg, AFI_IP); + vnc_zebra_reexport_group_afi(bgp, rfg, AFI_IP6); + } + return CMD_SUCCESS; } DEFUN (vnc_nve_export_no_prefixlist, @@ -2018,54 +1861,44 @@ DEFUN (vnc_nve_export_no_prefixlist, "IPv6 prefixes\n" "Prefix-list for filtering exported routes\n" "Prefix list name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - struct rfapi_cfg *hc; - afi_t afi; - - if (!(hc = bgp->rfapi_cfg)) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (strmatch(argv[4]->text, "ipv4")) - { - afi = AFI_IP; - } - else - { - afi = AFI_IP6; - } - - if (argv[3]->arg[0] == 'b') - { - if (((argc > 6) - && hc->plist_export_bgp_name[afi] - && strmatch(argv[6]->text, hc->plist_export_bgp_name[afi])) - || (argc <= 6)) - { - - free (hc->plist_export_bgp_name[afi]); - hc->plist_export_bgp_name[afi] = NULL; - hc->plist_export_bgp[afi] = NULL; - vnc_direct_bgp_reexport (bgp, afi); - } - } - else - { - if (((argc > 6) - && hc->plist_export_zebra_name[afi] - && strmatch(argv[6]->text, hc->plist_export_zebra_name[afi])) - || (argc <= 6)) - { - - free (hc->plist_export_zebra_name[afi]); - hc->plist_export_zebra_name[afi] = NULL; - hc->plist_export_zebra[afi] = NULL; - /* TBD vnc_zebra_rh_reexport(bgp, afi); */ - } - } - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + struct rfapi_cfg *hc; + afi_t afi; + + if (!(hc = bgp->rfapi_cfg)) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (strmatch(argv[4]->text, "ipv4")) { + afi = AFI_IP; + } else { + afi = AFI_IP6; + } + + if (argv[3]->arg[0] == 'b') { + if (((argc > 6) && hc->plist_export_bgp_name[afi] + && strmatch(argv[6]->text, hc->plist_export_bgp_name[afi])) + || (argc <= 6)) { + + free(hc->plist_export_bgp_name[afi]); + hc->plist_export_bgp_name[afi] = NULL; + hc->plist_export_bgp[afi] = NULL; + vnc_direct_bgp_reexport(bgp, afi); + } + } else { + if (((argc > 6) && hc->plist_export_zebra_name[afi] + && strmatch(argv[6]->text, + hc->plist_export_zebra_name[afi])) + || (argc <= 6)) { + + free(hc->plist_export_zebra_name[afi]); + hc->plist_export_zebra_name[afi] = NULL; + hc->plist_export_zebra[afi] = NULL; + /* TBD vnc_zebra_rh_reexport(bgp, afi); */ + } + } + return CMD_SUCCESS; } DEFUN (vnc_nve_export_prefixlist, @@ -2079,42 +1912,37 @@ DEFUN (vnc_nve_export_prefixlist, "IPv6 prefixes\n" "Prefix-list for filtering exported routes\n" "Prefix list name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - struct rfapi_cfg *hc; - afi_t afi; - - if (!(hc = bgp->rfapi_cfg)) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (strmatch(argv[3]->text, "ipv4")) - { - afi = AFI_IP; - } - else - { - afi = AFI_IP6; - } - - if (argv[2]->arg[0] == 'b') - { - if (hc->plist_export_bgp_name[afi]) - free (hc->plist_export_bgp_name[afi]); - hc->plist_export_bgp_name[afi] = strdup (argv[5]->arg); - hc->plist_export_bgp[afi] = prefix_list_lookup (afi, argv[5]->arg); - vnc_direct_bgp_reexport (bgp, afi); - } - else - { - if (hc->plist_export_zebra_name[afi]) - free (hc->plist_export_zebra_name[afi]); - hc->plist_export_zebra_name[afi] = strdup (argv[5]->arg); - hc->plist_export_zebra[afi] = prefix_list_lookup (afi, argv[5]->arg); - /* TBD vnc_zebra_rh_reexport(bgp, afi); */ - } - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + struct rfapi_cfg *hc; + afi_t afi; + + if (!(hc = bgp->rfapi_cfg)) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (strmatch(argv[3]->text, "ipv4")) { + afi = AFI_IP; + } else { + afi = AFI_IP6; + } + + if (argv[2]->arg[0] == 'b') { + if (hc->plist_export_bgp_name[afi]) + free(hc->plist_export_bgp_name[afi]); + hc->plist_export_bgp_name[afi] = strdup(argv[5]->arg); + hc->plist_export_bgp[afi] = + prefix_list_lookup(afi, argv[5]->arg); + vnc_direct_bgp_reexport(bgp, afi); + } else { + if (hc->plist_export_zebra_name[afi]) + free(hc->plist_export_zebra_name[afi]); + hc->plist_export_zebra_name[afi] = strdup(argv[5]->arg); + hc->plist_export_zebra[afi] = + prefix_list_lookup(afi, argv[5]->arg); + /* TBD vnc_zebra_rh_reexport(bgp, afi); */ + } + return CMD_SUCCESS; } DEFUN (vnc_nve_export_no_routemap, @@ -2127,46 +1955,38 @@ DEFUN (vnc_nve_export_no_routemap, "Export to Zebra (experimental)\n" "Route-map for filtering exported routes\n" "Route map name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - struct rfapi_cfg *hc; - - if (!(hc = bgp->rfapi_cfg)) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (argv[3]->arg[0] == 'b') - { - if (((argc > 5) - && hc->routemap_export_bgp_name - && strmatch(argv[5]->text, hc->routemap_export_bgp_name)) - || (argc <= 5)) - { - - free (hc->routemap_export_bgp_name); - hc->routemap_export_bgp_name = NULL; - hc->routemap_export_bgp = NULL; - vnc_direct_bgp_reexport (bgp, AFI_IP); - vnc_direct_bgp_reexport (bgp, AFI_IP6); - } - } - else - { - if (((argc > 5) - && hc->routemap_export_zebra_name - && strmatch(argv[5]->text, hc->routemap_export_zebra_name)) - || (argc <= 5)) - { - - free (hc->routemap_export_zebra_name); - hc->routemap_export_zebra_name = NULL; - hc->routemap_export_zebra = NULL; - /* TBD vnc_zebra_rh_reexport(bgp, AFI_IP); */ - /* TBD vnc_zebra_rh_reexport(bgp, AFI_IP6); */ - } - } - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + struct rfapi_cfg *hc; + + if (!(hc = bgp->rfapi_cfg)) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (argv[3]->arg[0] == 'b') { + if (((argc > 5) && hc->routemap_export_bgp_name + && strmatch(argv[5]->text, hc->routemap_export_bgp_name)) + || (argc <= 5)) { + + free(hc->routemap_export_bgp_name); + hc->routemap_export_bgp_name = NULL; + hc->routemap_export_bgp = NULL; + vnc_direct_bgp_reexport(bgp, AFI_IP); + vnc_direct_bgp_reexport(bgp, AFI_IP6); + } + } else { + if (((argc > 5) && hc->routemap_export_zebra_name + && strmatch(argv[5]->text, hc->routemap_export_zebra_name)) + || (argc <= 5)) { + + free(hc->routemap_export_zebra_name); + hc->routemap_export_zebra_name = NULL; + hc->routemap_export_zebra = NULL; + /* TBD vnc_zebra_rh_reexport(bgp, AFI_IP); */ + /* TBD vnc_zebra_rh_reexport(bgp, AFI_IP6); */ + } + } + return CMD_SUCCESS; } DEFUN (vnc_nve_export_routemap, @@ -2178,232 +1998,210 @@ DEFUN (vnc_nve_export_routemap, "Export to Zebra (experimental)\n" "Route-map for filtering exported routes\n" "Route map name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - struct rfapi_cfg *hc; - - if (!(hc = bgp->rfapi_cfg)) - { - vty_out (vty, "rfapi not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (argv[2]->arg[0] == 'b') - { - if (hc->routemap_export_bgp_name) - free (hc->routemap_export_bgp_name); - hc->routemap_export_bgp_name = strdup (argv[4]->arg); - hc->routemap_export_bgp = route_map_lookup_by_name (argv[4]->arg); - vnc_direct_bgp_reexport (bgp, AFI_IP); - vnc_direct_bgp_reexport (bgp, AFI_IP6); - } - else - { - if (hc->routemap_export_zebra_name) - free (hc->routemap_export_zebra_name); - hc->routemap_export_zebra_name = strdup (argv[4]->arg); - hc->routemap_export_zebra = route_map_lookup_by_name (argv[4]->arg); - /* TBD vnc_zebra_rh_reexport(bgp, AFI_IP); */ - /* TBD vnc_zebra_rh_reexport(bgp, AFI_IP6); */ - } - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + struct rfapi_cfg *hc; + + if (!(hc = bgp->rfapi_cfg)) { + vty_out(vty, "rfapi not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (argv[2]->arg[0] == 'b') { + if (hc->routemap_export_bgp_name) + free(hc->routemap_export_bgp_name); + hc->routemap_export_bgp_name = strdup(argv[4]->arg); + hc->routemap_export_bgp = + route_map_lookup_by_name(argv[4]->arg); + vnc_direct_bgp_reexport(bgp, AFI_IP); + vnc_direct_bgp_reexport(bgp, AFI_IP6); + } else { + if (hc->routemap_export_zebra_name) + free(hc->routemap_export_zebra_name); + hc->routemap_export_zebra_name = strdup(argv[4]->arg); + hc->routemap_export_zebra = + route_map_lookup_by_name(argv[4]->arg); + /* TBD vnc_zebra_rh_reexport(bgp, AFI_IP); */ + /* TBD vnc_zebra_rh_reexport(bgp, AFI_IP6); */ + } + return CMD_SUCCESS; } /* * respond to changes in the global prefix list configuration */ -void -vnc_prefix_list_update (struct bgp *bgp) +void vnc_prefix_list_update(struct bgp *bgp) { - afi_t afi; - struct listnode *n; - struct rfapi_nve_group_cfg *rfg; - struct rfapi_cfg *hc; - int i; - - if (!bgp) - { - vnc_zlog_debug_verbose ("%s: No BGP process is configured", __func__); - return; - } - - if (!(hc = bgp->rfapi_cfg)) - { - vnc_zlog_debug_verbose ("%s: rfapi not configured", __func__); - return; - } - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - /* - * Loop over nve groups - */ - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->nve_groups_sequential, - n, rfg)) - { - - if (rfg->plist_export_bgp_name[afi]) - { - rfg->plist_export_bgp[afi] = - prefix_list_lookup (afi, rfg->plist_export_bgp_name[afi]); - } - if (rfg->plist_export_zebra_name[afi]) - { - rfg->plist_export_zebra[afi] = - prefix_list_lookup (afi, rfg->plist_export_zebra_name[afi]); - } - for (i = 0; i < ZEBRA_ROUTE_MAX; ++i) - { - if (rfg->plist_redist_name[i][afi]) - { - rfg->plist_redist[i][afi] = - prefix_list_lookup (afi, rfg->plist_redist_name[i][afi]); - } - } - - vnc_direct_bgp_reexport_group_afi (bgp, rfg, afi); - /* TBD vnc_zebra_reexport_group_afi(bgp, rfg, afi); */ - } - - /* - * RH config, too - */ - if (hc->plist_export_bgp_name[afi]) - { - hc->plist_export_bgp[afi] = - prefix_list_lookup (afi, hc->plist_export_bgp_name[afi]); - } - if (hc->plist_export_zebra_name[afi]) - { - hc->plist_export_zebra[afi] = - prefix_list_lookup (afi, hc->plist_export_zebra_name[afi]); - } - - for (i = 0; i < ZEBRA_ROUTE_MAX; ++i) - { - if (hc->plist_redist_name[i][afi]) - { - hc->plist_redist[i][afi] = - prefix_list_lookup (afi, hc->plist_redist_name[i][afi]); - } - } - - } - - vnc_direct_bgp_reexport (bgp, AFI_IP); - vnc_direct_bgp_reexport (bgp, AFI_IP6); - - /* TBD vnc_zebra_rh_reexport(bgp, AFI_IP); */ - /* TBD vnc_zebra_rh_reexport(bgp, AFI_IP6); */ - - vnc_redistribute_prechange (bgp); - vnc_redistribute_postchange (bgp); + afi_t afi; + struct listnode *n; + struct rfapi_nve_group_cfg *rfg; + struct rfapi_cfg *hc; + int i; + + if (!bgp) { + vnc_zlog_debug_verbose("%s: No BGP process is configured", + __func__); + return; + } + + if (!(hc = bgp->rfapi_cfg)) { + vnc_zlog_debug_verbose("%s: rfapi not configured", __func__); + return; + } + + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + /* + * Loop over nve groups + */ + for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->nve_groups_sequential, + n, rfg)) { + + if (rfg->plist_export_bgp_name[afi]) { + rfg->plist_export_bgp[afi] = prefix_list_lookup( + afi, rfg->plist_export_bgp_name[afi]); + } + if (rfg->plist_export_zebra_name[afi]) { + rfg->plist_export_zebra + [afi] = prefix_list_lookup( + afi, rfg->plist_export_zebra_name[afi]); + } + for (i = 0; i < ZEBRA_ROUTE_MAX; ++i) { + if (rfg->plist_redist_name[i][afi]) { + rfg->plist_redist + [i][afi] = prefix_list_lookup( + afi, + rfg->plist_redist_name[i][afi]); + } + } + + vnc_direct_bgp_reexport_group_afi(bgp, rfg, afi); + /* TBD vnc_zebra_reexport_group_afi(bgp, rfg, afi); */ + } + + /* + * RH config, too + */ + if (hc->plist_export_bgp_name[afi]) { + hc->plist_export_bgp[afi] = prefix_list_lookup( + afi, hc->plist_export_bgp_name[afi]); + } + if (hc->plist_export_zebra_name[afi]) { + hc->plist_export_zebra[afi] = prefix_list_lookup( + afi, hc->plist_export_zebra_name[afi]); + } + + for (i = 0; i < ZEBRA_ROUTE_MAX; ++i) { + if (hc->plist_redist_name[i][afi]) { + hc->plist_redist[i][afi] = prefix_list_lookup( + afi, hc->plist_redist_name[i][afi]); + } + } + } + + vnc_direct_bgp_reexport(bgp, AFI_IP); + vnc_direct_bgp_reexport(bgp, AFI_IP6); + + /* TBD vnc_zebra_rh_reexport(bgp, AFI_IP); */ + /* TBD vnc_zebra_rh_reexport(bgp, AFI_IP6); */ + + vnc_redistribute_prechange(bgp); + vnc_redistribute_postchange(bgp); } /* * respond to changes in the global route map configuration */ -void -vnc_routemap_update (struct bgp *bgp, const char *unused) +void vnc_routemap_update(struct bgp *bgp, const char *unused) { - struct listnode *n; - struct rfapi_nve_group_cfg *rfg; - struct rfapi_cfg *hc; - int i; - - vnc_zlog_debug_verbose ("%s(arg=%s)", __func__, unused); - - if (!bgp) - { - vnc_zlog_debug_verbose ("%s: No BGP process is configured", __func__); - return; - } - - if (!(hc = bgp->rfapi_cfg)) - { - vnc_zlog_debug_verbose ("%s: rfapi not configured", __func__); - return; - } - - /* - * Loop over nve groups - */ - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->nve_groups_sequential, n, rfg)) - { - - if (rfg->routemap_export_bgp_name) - { - rfg->routemap_export_bgp = - route_map_lookup_by_name (rfg->routemap_export_bgp_name); - } - if (rfg->routemap_export_zebra_name) - { - rfg->routemap_export_bgp = - route_map_lookup_by_name (rfg->routemap_export_zebra_name); - } - for (i = 0; i < ZEBRA_ROUTE_MAX; ++i) - { - if (rfg->routemap_redist_name[i]) - { - rfg->routemap_redist[i] = - route_map_lookup_by_name (rfg->routemap_redist_name[i]); - } - } - - vnc_direct_bgp_reexport_group_afi (bgp, rfg, AFI_IP); - vnc_direct_bgp_reexport_group_afi (bgp, rfg, AFI_IP6); - /* TBD vnc_zebra_reexport_group_afi(bgp, rfg, afi); */ - } - - /* - * RH config, too - */ - if (hc->routemap_export_bgp_name) - { - hc->routemap_export_bgp = - route_map_lookup_by_name (hc->routemap_export_bgp_name); - } - if (hc->routemap_export_zebra_name) - { - hc->routemap_export_bgp = - route_map_lookup_by_name (hc->routemap_export_zebra_name); - } - for (i = 0; i < ZEBRA_ROUTE_MAX; ++i) - { - if (hc->routemap_redist_name[i]) - { - hc->routemap_redist[i] = - route_map_lookup_by_name (hc->routemap_redist_name[i]); - } - } - - vnc_direct_bgp_reexport (bgp, AFI_IP); - vnc_direct_bgp_reexport (bgp, AFI_IP6); - - /* TBD vnc_zebra_rh_reexport(bgp, AFI_IP); */ - /* TBD vnc_zebra_rh_reexport(bgp, AFI_IP6); */ - - vnc_redistribute_prechange (bgp); - vnc_redistribute_postchange (bgp); - - vnc_zlog_debug_verbose ("%s done", __func__); + struct listnode *n; + struct rfapi_nve_group_cfg *rfg; + struct rfapi_cfg *hc; + int i; + + vnc_zlog_debug_verbose("%s(arg=%s)", __func__, unused); + + if (!bgp) { + vnc_zlog_debug_verbose("%s: No BGP process is configured", + __func__); + return; + } + + if (!(hc = bgp->rfapi_cfg)) { + vnc_zlog_debug_verbose("%s: rfapi not configured", __func__); + return; + } + + /* + * Loop over nve groups + */ + for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->nve_groups_sequential, n, + rfg)) { + + if (rfg->routemap_export_bgp_name) { + rfg->routemap_export_bgp = route_map_lookup_by_name( + rfg->routemap_export_bgp_name); + } + if (rfg->routemap_export_zebra_name) { + rfg->routemap_export_bgp = route_map_lookup_by_name( + rfg->routemap_export_zebra_name); + } + for (i = 0; i < ZEBRA_ROUTE_MAX; ++i) { + if (rfg->routemap_redist_name[i]) { + rfg->routemap_redist[i] = + route_map_lookup_by_name( + rfg->routemap_redist_name[i]); + } + } + + vnc_direct_bgp_reexport_group_afi(bgp, rfg, AFI_IP); + vnc_direct_bgp_reexport_group_afi(bgp, rfg, AFI_IP6); + /* TBD vnc_zebra_reexport_group_afi(bgp, rfg, afi); */ + } + + /* + * RH config, too + */ + if (hc->routemap_export_bgp_name) { + hc->routemap_export_bgp = + route_map_lookup_by_name(hc->routemap_export_bgp_name); + } + if (hc->routemap_export_zebra_name) { + hc->routemap_export_bgp = route_map_lookup_by_name( + hc->routemap_export_zebra_name); + } + for (i = 0; i < ZEBRA_ROUTE_MAX; ++i) { + if (hc->routemap_redist_name[i]) { + hc->routemap_redist[i] = route_map_lookup_by_name( + hc->routemap_redist_name[i]); + } + } + + vnc_direct_bgp_reexport(bgp, AFI_IP); + vnc_direct_bgp_reexport(bgp, AFI_IP6); + + /* TBD vnc_zebra_rh_reexport(bgp, AFI_IP); */ + /* TBD vnc_zebra_rh_reexport(bgp, AFI_IP6); */ + + vnc_redistribute_prechange(bgp); + vnc_redistribute_postchange(bgp); + + vnc_zlog_debug_verbose("%s done", __func__); } -static void -vnc_routemap_event (route_map_event_t type, /* ignored */ - const char *rmap_name) /* ignored */ +static void vnc_routemap_event(route_map_event_t type, /* ignored */ + const char *rmap_name) /* ignored */ { - struct listnode *mnode, *mnnode; - struct bgp *bgp; + struct listnode *mnode, *mnnode; + struct bgp *bgp; - vnc_zlog_debug_verbose ("%s(event type=%d)", __func__, type); - if (bm->bgp == NULL) /* may be called during cleanup */ - return; + vnc_zlog_debug_verbose("%s(event type=%d)", __func__, type); + if (bm->bgp == NULL) /* may be called during cleanup */ + return; - for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp)) - vnc_routemap_update (bgp, rmap_name); + for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) + vnc_routemap_update(bgp, rmap_name); - vnc_zlog_debug_verbose ("%s: done", __func__); + vnc_zlog_debug_verbose("%s: done", __func__); } /*------------------------------------------------------------------------- @@ -2416,288 +2214,267 @@ DEFUN_NOSH (vnc_nve_group, "vnc nve-group NAME", VNC_CONFIG_STR "Configure a NVE group\n" "Group name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - struct rfapi_nve_group_cfg *rfg; - struct listnode *node, *nnode; - struct rfapi_rfg_name *rfgn; - - /* Search for name */ - rfg = bgp_rfapi_cfg_match_byname (bgp, argv[2]->arg, RFAPI_GROUP_CFG_NVE); - - if (!rfg) - { - rfg = rfapi_group_new (bgp, RFAPI_GROUP_CFG_NVE, argv[2]->arg); - if (!rfg) - { - /* Error out of memory */ - vty_out (vty, "Can't allocate memory for NVE group\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Copy defaults from struct rfapi_cfg */ - rfg->rd = bgp->rfapi_cfg->default_rd; - if (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_L2RD) - { - rfg->l2rd = bgp->rfapi_cfg->default_l2rd; - rfg->flags |= RFAPI_RFG_L2RD; - } - rfg->rd = bgp->rfapi_cfg->default_rd; - rfg->response_lifetime = bgp->rfapi_cfg->default_response_lifetime; - - if (bgp->rfapi_cfg->default_rt_export_list) - { - rfg->rt_export_list = - ecommunity_dup (bgp->rfapi_cfg->default_rt_export_list); - } - - if (bgp->rfapi_cfg->default_rt_import_list) - { - rfg->rt_import_list = - ecommunity_dup (bgp->rfapi_cfg->default_rt_import_list); - rfg->rfapi_import_table = - rfapiImportTableRefAdd (bgp, rfg->rt_import_list, rfg); - } - - /* - * If a redist nve group was named but the group was not defined, - * make the linkage now - */ - if (!bgp->rfapi_cfg->rfg_redist) - { - if (bgp->rfapi_cfg->rfg_redist_name && - !strcmp (bgp->rfapi_cfg->rfg_redist_name, rfg->name)) - { - - vnc_redistribute_prechange (bgp); - bgp->rfapi_cfg->rfg_redist = rfg; - vnc_redistribute_postchange (bgp); - - } - } - - /* - * Same treatment for bgp-direct export group - */ - for (ALL_LIST_ELEMENTS (bgp->rfapi_cfg->rfg_export_direct_bgp_l, - node, nnode, rfgn)) - { - - if (!strcmp (rfgn->name, rfg->name)) - { - rfgn->rfg = rfg; - vnc_direct_bgp_add_group (bgp, rfg); - break; - } - } - - /* - * Same treatment for zebra export group - */ - for (ALL_LIST_ELEMENTS (bgp->rfapi_cfg->rfg_export_zebra_l, - node, nnode, rfgn)) - { - - vnc_zlog_debug_verbose ("%s: ezport zebra: checking if \"%s\" == \"%s\"", - __func__, rfgn->name, rfg->name); - if (!strcmp (rfgn->name, rfg->name)) - { - rfgn->rfg = rfg; - vnc_zebra_add_group (bgp, rfg); - break; - } - } - } - - /* - * XXX subsequent calls will need to make sure this item is still - * in the linked list and has the same name - */ - VTY_PUSH_CONTEXT_SUB (BGP_VNC_NVE_GROUP_NODE, rfg); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + struct rfapi_nve_group_cfg *rfg; + struct listnode *node, *nnode; + struct rfapi_rfg_name *rfgn; + + /* Search for name */ + rfg = bgp_rfapi_cfg_match_byname(bgp, argv[2]->arg, + RFAPI_GROUP_CFG_NVE); + + if (!rfg) { + rfg = rfapi_group_new(bgp, RFAPI_GROUP_CFG_NVE, argv[2]->arg); + if (!rfg) { + /* Error out of memory */ + vty_out(vty, "Can't allocate memory for NVE group\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Copy defaults from struct rfapi_cfg */ + rfg->rd = bgp->rfapi_cfg->default_rd; + if (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_L2RD) { + rfg->l2rd = bgp->rfapi_cfg->default_l2rd; + rfg->flags |= RFAPI_RFG_L2RD; + } + rfg->rd = bgp->rfapi_cfg->default_rd; + rfg->response_lifetime = + bgp->rfapi_cfg->default_response_lifetime; + + if (bgp->rfapi_cfg->default_rt_export_list) { + rfg->rt_export_list = ecommunity_dup( + bgp->rfapi_cfg->default_rt_export_list); + } + + if (bgp->rfapi_cfg->default_rt_import_list) { + rfg->rt_import_list = ecommunity_dup( + bgp->rfapi_cfg->default_rt_import_list); + rfg->rfapi_import_table = rfapiImportTableRefAdd( + bgp, rfg->rt_import_list, rfg); + } + + /* + * If a redist nve group was named but the group was not + * defined, + * make the linkage now + */ + if (!bgp->rfapi_cfg->rfg_redist) { + if (bgp->rfapi_cfg->rfg_redist_name + && !strcmp(bgp->rfapi_cfg->rfg_redist_name, + rfg->name)) { + + vnc_redistribute_prechange(bgp); + bgp->rfapi_cfg->rfg_redist = rfg; + vnc_redistribute_postchange(bgp); + } + } + + /* + * Same treatment for bgp-direct export group + */ + for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_direct_bgp_l, + node, nnode, rfgn)) { + + if (!strcmp(rfgn->name, rfg->name)) { + rfgn->rfg = rfg; + vnc_direct_bgp_add_group(bgp, rfg); + break; + } + } + + /* + * Same treatment for zebra export group + */ + for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_zebra_l, node, + nnode, rfgn)) { + + vnc_zlog_debug_verbose( + "%s: ezport zebra: checking if \"%s\" == \"%s\"", + __func__, rfgn->name, rfg->name); + if (!strcmp(rfgn->name, rfg->name)) { + rfgn->rfg = rfg; + vnc_zebra_add_group(bgp, rfg); + break; + } + } + } + + /* + * XXX subsequent calls will need to make sure this item is still + * in the linked list and has the same name + */ + VTY_PUSH_CONTEXT_SUB(BGP_VNC_NVE_GROUP_NODE, rfg); + + return CMD_SUCCESS; } -static void -bgp_rfapi_delete_nve_group ( - struct vty *vty, /* NULL = no output */ - struct bgp *bgp, - struct rfapi_nve_group_cfg *rfg) +static void bgp_rfapi_delete_nve_group(struct vty *vty, /* NULL = no output */ + struct bgp *bgp, + struct rfapi_nve_group_cfg *rfg) { - struct list *orphaned_nves = NULL; - struct listnode *node, *nnode; - - /* - * If there are currently-open NVEs that belong to this group, - * zero out their references to this group structure. - */ - if (rfg->nves) - { - struct rfapi_descriptor *rfd; - orphaned_nves = list_new (); - while ((rfd = listnode_head (rfg->nves))) - { - rfd->rfg = NULL; - listnode_delete (rfg->nves, rfd); - listnode_add (orphaned_nves, rfd); - } - list_delete (rfg->nves); - rfg->nves = NULL; - } - - /* delete it */ - free (rfg->name); - if (rfg->rfapi_import_table) - rfapiImportTableRefDelByIt (bgp, rfg->rfapi_import_table); - if (rfg->rt_import_list) - ecommunity_free (&rfg->rt_import_list); - if (rfg->rt_export_list) - ecommunity_free (&rfg->rt_export_list); - - if (rfg->vn_node) - { - rfg->vn_node->info = NULL; - route_unlock_node (rfg->vn_node); /* frees */ - } - if (rfg->un_node) - { - rfg->un_node->info = NULL; - route_unlock_node (rfg->un_node); /* frees */ - } - if (rfg->rfp_cfg) - XFREE (MTYPE_RFAPI_RFP_GROUP_CFG, rfg->rfp_cfg); - listnode_delete (bgp->rfapi_cfg->nve_groups_sequential, rfg); - - QOBJ_UNREG (rfg); - XFREE (MTYPE_RFAPI_GROUP_CFG, rfg); - - /* - * Attempt to reassign the orphaned nves to a new group. If - * a NVE can not be reassigned, its rfd->rfg will remain NULL - * and it will become a zombie until released by rfapi_close(). - */ - if (orphaned_nves) - { - struct rfapi_descriptor *rfd; - - for (ALL_LIST_ELEMENTS (orphaned_nves, node, nnode, rfd)) - { - /* - * 1. rfapi_close() equivalent except: - * a. don't free original descriptor - * b. remember query list - * c. remember advertised route list - * 2. rfapi_open() equivalent except: - * a. reuse original descriptor - * 3. rfapi_register() on remembered advertised route list - * 4. rfapi_query on rememebred query list - */ - - int rc; - - rc = rfapi_reopen (rfd, bgp); - - if (!rc) - { - list_delete_node (orphaned_nves, node); - if (vty) - vty_out (vty, "WARNING: reassigned NVE vn="); - rfapiPrintRfapiIpAddr (vty, &rfd->vn_addr); - if (vty) - vty_out (vty, " un="); - rfapiPrintRfapiIpAddr (vty, &rfd->un_addr); - if (vty) - vty_out (vty, " to new group \"%s\"\n",rfd->rfg->name); - - } - } - - for (ALL_LIST_ELEMENTS_RO (orphaned_nves, node, rfd)) - { - if (vty) - vty_out (vty, "WARNING: orphaned NVE vn="); - rfapiPrintRfapiIpAddr (vty, &rfd->vn_addr); - if (vty) - vty_out (vty, " un="); - rfapiPrintRfapiIpAddr (vty, &rfd->un_addr); - if (vty) - vty_out (vty, "\n"); - } - list_delete (orphaned_nves); - } + struct list *orphaned_nves = NULL; + struct listnode *node, *nnode; + + /* + * If there are currently-open NVEs that belong to this group, + * zero out their references to this group structure. + */ + if (rfg->nves) { + struct rfapi_descriptor *rfd; + orphaned_nves = list_new(); + while ((rfd = listnode_head(rfg->nves))) { + rfd->rfg = NULL; + listnode_delete(rfg->nves, rfd); + listnode_add(orphaned_nves, rfd); + } + list_delete(rfg->nves); + rfg->nves = NULL; + } + + /* delete it */ + free(rfg->name); + if (rfg->rfapi_import_table) + rfapiImportTableRefDelByIt(bgp, rfg->rfapi_import_table); + if (rfg->rt_import_list) + ecommunity_free(&rfg->rt_import_list); + if (rfg->rt_export_list) + ecommunity_free(&rfg->rt_export_list); + + if (rfg->vn_node) { + rfg->vn_node->info = NULL; + route_unlock_node(rfg->vn_node); /* frees */ + } + if (rfg->un_node) { + rfg->un_node->info = NULL; + route_unlock_node(rfg->un_node); /* frees */ + } + if (rfg->rfp_cfg) + XFREE(MTYPE_RFAPI_RFP_GROUP_CFG, rfg->rfp_cfg); + listnode_delete(bgp->rfapi_cfg->nve_groups_sequential, rfg); + + QOBJ_UNREG(rfg); + XFREE(MTYPE_RFAPI_GROUP_CFG, rfg); + + /* + * Attempt to reassign the orphaned nves to a new group. If + * a NVE can not be reassigned, its rfd->rfg will remain NULL + * and it will become a zombie until released by rfapi_close(). + */ + if (orphaned_nves) { + struct rfapi_descriptor *rfd; + + for (ALL_LIST_ELEMENTS(orphaned_nves, node, nnode, rfd)) { + /* + * 1. rfapi_close() equivalent except: + * a. don't free original descriptor + * b. remember query list + * c. remember advertised route list + * 2. rfapi_open() equivalent except: + * a. reuse original descriptor + * 3. rfapi_register() on remembered advertised route + * list + * 4. rfapi_query on rememebred query list + */ + + int rc; + + rc = rfapi_reopen(rfd, bgp); + + if (!rc) { + list_delete_node(orphaned_nves, node); + if (vty) + vty_out(vty, + "WARNING: reassigned NVE vn="); + rfapiPrintRfapiIpAddr(vty, &rfd->vn_addr); + if (vty) + vty_out(vty, " un="); + rfapiPrintRfapiIpAddr(vty, &rfd->un_addr); + if (vty) + vty_out(vty, " to new group \"%s\"\n", + rfd->rfg->name); + } + } + + for (ALL_LIST_ELEMENTS_RO(orphaned_nves, node, rfd)) { + if (vty) + vty_out(vty, "WARNING: orphaned NVE vn="); + rfapiPrintRfapiIpAddr(vty, &rfd->vn_addr); + if (vty) + vty_out(vty, " un="); + rfapiPrintRfapiIpAddr(vty, &rfd->un_addr); + if (vty) + vty_out(vty, "\n"); + } + list_delete(orphaned_nves); + } } static int -bgp_rfapi_delete_named_nve_group ( - struct vty *vty, /* NULL = no output */ - struct bgp *bgp, - const char *rfg_name, /* NULL = any */ - rfapi_group_cfg_type_t type) /* _MAX = any */ +bgp_rfapi_delete_named_nve_group(struct vty *vty, /* NULL = no output */ + struct bgp *bgp, + const char *rfg_name, /* NULL = any */ + rfapi_group_cfg_type_t type) /* _MAX = any */ { - struct rfapi_nve_group_cfg *rfg = NULL; - struct listnode *node, *nnode; - struct rfapi_rfg_name *rfgn; - - /* Search for name */ - if (rfg_name) - { - rfg = bgp_rfapi_cfg_match_byname (bgp, rfg_name, type); - if (!rfg) - { - if (vty) - vty_out (vty, "No NVE group named \"%s\"\n",rfg_name); - return CMD_WARNING_CONFIG_FAILED; - } - } - - /* - * If this group is the redist nve group, unlink it - */ - if (rfg_name == NULL || bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_prechange (bgp); - bgp->rfapi_cfg->rfg_redist = NULL; - vnc_redistribute_postchange (bgp); - } - - - /* - * remove reference from bgp direct export list - */ - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_direct_bgp_l, - node, rfgn)) - { - if (rfg_name == NULL || - (type == RFAPI_GROUP_CFG_NVE && !strcmp (rfgn->name, rfg_name))) - { - rfgn->rfg = NULL; - /* remove exported routes from this group */ - vnc_direct_bgp_del_group (bgp, rfg); - break; - } - } - - /* - * remove reference from zebra export list - */ - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_zebra_l, node, rfgn)) - { - - if (rfg_name == NULL || - (type == RFAPI_GROUP_CFG_NVE && !strcmp (rfgn->name, rfg_name))) - { - rfgn->rfg = NULL; - /* remove exported routes from this group */ - vnc_zebra_del_group (bgp, rfg); - break; - } - } - if (rfg) - bgp_rfapi_delete_nve_group (vty, bgp, rfg); - else /* must be delete all */ - for (ALL_LIST_ELEMENTS - (bgp->rfapi_cfg->nve_groups_sequential, node, nnode, rfg)) - bgp_rfapi_delete_nve_group (vty, bgp, rfg); - return CMD_SUCCESS; + struct rfapi_nve_group_cfg *rfg = NULL; + struct listnode *node, *nnode; + struct rfapi_rfg_name *rfgn; + + /* Search for name */ + if (rfg_name) { + rfg = bgp_rfapi_cfg_match_byname(bgp, rfg_name, type); + if (!rfg) { + if (vty) + vty_out(vty, "No NVE group named \"%s\"\n", + rfg_name); + return CMD_WARNING_CONFIG_FAILED; + } + } + + /* + * If this group is the redist nve group, unlink it + */ + if (rfg_name == NULL || bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_prechange(bgp); + bgp->rfapi_cfg->rfg_redist = NULL; + vnc_redistribute_postchange(bgp); + } + + + /* + * remove reference from bgp direct export list + */ + for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node, + rfgn)) { + if (rfg_name == NULL || (type == RFAPI_GROUP_CFG_NVE + && !strcmp(rfgn->name, rfg_name))) { + rfgn->rfg = NULL; + /* remove exported routes from this group */ + vnc_direct_bgp_del_group(bgp, rfg); + break; + } + } + + /* + * remove reference from zebra export list + */ + for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_zebra_l, node, + rfgn)) { + + if (rfg_name == NULL || (type == RFAPI_GROUP_CFG_NVE + && !strcmp(rfgn->name, rfg_name))) { + rfgn->rfg = NULL; + /* remove exported routes from this group */ + vnc_zebra_del_group(bgp, rfg); + break; + } + } + if (rfg) + bgp_rfapi_delete_nve_group(vty, bgp, rfg); + else /* must be delete all */ + for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->nve_groups_sequential, + node, nnode, rfg)) + bgp_rfapi_delete_nve_group(vty, bgp, rfg); + return CMD_SUCCESS; } DEFUN (vnc_no_nve_group, @@ -2708,9 +2485,10 @@ DEFUN (vnc_no_nve_group, "Configure a NVE group\n" "Group name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT(bgp, bgp); - return bgp_rfapi_delete_named_nve_group (vty, bgp, argv[3]->arg, RFAPI_GROUP_CFG_NVE); + return bgp_rfapi_delete_named_nve_group(vty, bgp, argv[3]->arg, + RFAPI_GROUP_CFG_NVE); } DEFUN (vnc_nve_group_prefix, @@ -2722,116 +2500,101 @@ DEFUN (vnc_nve_group_prefix, "IPv4 prefix\n" "IPv6 prefix\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - struct prefix p; - int afi; - struct route_table *rt; - struct route_node *rn; - int is_un_prefix = 0; - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (!str2prefix (argv[2]->arg, &p)) - { - vty_out (vty, "Malformed prefix \"%s\"\n", argv[2]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - - afi = family2afi (p.family); - if (!afi) - { - vty_out (vty, "Unsupported address family\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (argv[1]->arg[0] == 'u') - { - rt = &(bgp->rfapi_cfg->nve_groups_un[afi]); - is_un_prefix = 1; - } - else - { - rt = &(bgp->rfapi_cfg->nve_groups_vn[afi]); - } - - rn = route_node_get (rt, &p); /* NB locks node */ - if (rn->info) - { - /* - * There is already a group with this prefix - */ - route_unlock_node (rn); - if (rn->info != rfg) - { - /* - * different group name: fail - */ - vty_out (vty, "nve group \"%s\" already has \"%s\" prefix %s\n", - ((struct rfapi_nve_group_cfg *) (rn->info))->name, - argv[1]->arg, argv[2]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - else - { - /* - * same group name: it's already in the correct place - * in the table, so we're done. - * - * Implies rfg->(vn|un)_prefix is already correct. - */ - return CMD_SUCCESS; - } - } - - if (bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_prechange (bgp); - } - - /* New prefix, new node */ - - if (is_un_prefix) - { - - /* detach rfg from previous route table location */ - if (rfg->un_node) - { - rfg->un_node->info = NULL; - route_unlock_node (rfg->un_node); /* frees */ - } - rfg->un_node = rn; /* back ref */ - rfg->un_prefix = p; - - } - else - { - - /* detach rfg from previous route table location */ - if (rfg->vn_node) - { - rfg->vn_node->info = NULL; - route_unlock_node (rfg->vn_node); /* frees */ - } - rfg->vn_node = rn; /* back ref */ - rfg->vn_prefix = p; - } - - /* attach */ - rn->info = rfg; - - if (bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_postchange (bgp); - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + struct prefix p; + int afi; + struct route_table *rt; + struct route_node *rn; + int is_un_prefix = 0; + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (!str2prefix(argv[2]->arg, &p)) { + vty_out(vty, "Malformed prefix \"%s\"\n", argv[2]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + + afi = family2afi(p.family); + if (!afi) { + vty_out(vty, "Unsupported address family\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (argv[1]->arg[0] == 'u') { + rt = &(bgp->rfapi_cfg->nve_groups_un[afi]); + is_un_prefix = 1; + } else { + rt = &(bgp->rfapi_cfg->nve_groups_vn[afi]); + } + + rn = route_node_get(rt, &p); /* NB locks node */ + if (rn->info) { + /* + * There is already a group with this prefix + */ + route_unlock_node(rn); + if (rn->info != rfg) { + /* + * different group name: fail + */ + vty_out(vty, + "nve group \"%s\" already has \"%s\" prefix %s\n", + ((struct rfapi_nve_group_cfg *)(rn->info)) + ->name, + argv[1]->arg, argv[2]->arg); + return CMD_WARNING_CONFIG_FAILED; + } else { + /* + * same group name: it's already in the correct place + * in the table, so we're done. + * + * Implies rfg->(vn|un)_prefix is already correct. + */ + return CMD_SUCCESS; + } + } + + if (bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_prechange(bgp); + } + + /* New prefix, new node */ + + if (is_un_prefix) { + + /* detach rfg from previous route table location */ + if (rfg->un_node) { + rfg->un_node->info = NULL; + route_unlock_node(rfg->un_node); /* frees */ + } + rfg->un_node = rn; /* back ref */ + rfg->un_prefix = p; + + } else { + + /* detach rfg from previous route table location */ + if (rfg->vn_node) { + rfg->vn_node->info = NULL; + route_unlock_node(rfg->vn_node); /* frees */ + } + rfg->vn_node = rn; /* back ref */ + rfg->vn_prefix = p; + } + + /* attach */ + rn->info = rfg; + + if (bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_postchange(bgp); + } + + return CMD_SUCCESS; } DEFUN (vnc_nve_group_rt_import, @@ -2841,67 +2604,64 @@ DEFUN (vnc_nve_group_rt_import, "Import filter\n" "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - int rc; - struct listnode *node; - struct rfapi_rfg_name *rfgn; - int is_export_bgp = 0; - int is_export_zebra = 0; - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - rc = set_ecom_list (vty, argc - 2, argv + 2, &rfg->rt_import_list); - if (rc != CMD_SUCCESS) - return rc; - - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_direct_bgp_l, - node, rfgn)) - { - - if (rfgn->rfg == rfg) - { - is_export_bgp = 1; - break; - } - } - - if (is_export_bgp) - vnc_direct_bgp_del_group (bgp, rfg); - - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_zebra_l, node, rfgn)) - { - - if (rfgn->rfg == rfg) - { - is_export_zebra = 1; - break; - } - } - - if (is_export_zebra) - vnc_zebra_del_group (bgp, rfg); - - /* - * stop referencing old import table, now reference new one - */ - if (rfg->rfapi_import_table) - rfapiImportTableRefDelByIt (bgp, rfg->rfapi_import_table); - rfg->rfapi_import_table = rfapiImportTableRefAdd (bgp, rfg->rt_import_list, rfg); - - if (is_export_bgp) - vnc_direct_bgp_add_group (bgp, rfg); - - if (is_export_zebra) - vnc_zebra_add_group (bgp, rfg); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + int rc; + struct listnode *node; + struct rfapi_rfg_name *rfgn; + int is_export_bgp = 0; + int is_export_zebra = 0; + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + rc = set_ecom_list(vty, argc - 2, argv + 2, &rfg->rt_import_list); + if (rc != CMD_SUCCESS) + return rc; + + for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node, + rfgn)) { + + if (rfgn->rfg == rfg) { + is_export_bgp = 1; + break; + } + } + + if (is_export_bgp) + vnc_direct_bgp_del_group(bgp, rfg); + + for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_zebra_l, node, + rfgn)) { + + if (rfgn->rfg == rfg) { + is_export_zebra = 1; + break; + } + } + + if (is_export_zebra) + vnc_zebra_del_group(bgp, rfg); + + /* + * stop referencing old import table, now reference new one + */ + if (rfg->rfapi_import_table) + rfapiImportTableRefDelByIt(bgp, rfg->rfapi_import_table); + rfg->rfapi_import_table = + rfapiImportTableRefAdd(bgp, rfg->rt_import_list, rfg); + + if (is_export_bgp) + vnc_direct_bgp_add_group(bgp, rfg); + + if (is_export_zebra) + vnc_zebra_add_group(bgp, rfg); + + return CMD_SUCCESS; } DEFUN (vnc_nve_group_rt_export, @@ -2911,31 +2671,28 @@ DEFUN (vnc_nve_group_rt_export, "Export filter\n" "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - int rc; - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_prechange (bgp); - } - - rc = set_ecom_list (vty, argc - 2, argv + 2, &rfg->rt_export_list); - - if (bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_postchange (bgp); - } - - return rc; + VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + int rc; + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_prechange(bgp); + } + + rc = set_ecom_list(vty, argc - 2, argv + 2, &rfg->rt_export_list); + + if (bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_postchange(bgp); + } + + return rc; } DEFUN (vnc_nve_group_rt_both, @@ -2945,83 +2702,76 @@ DEFUN (vnc_nve_group_rt_both, "Export+import filters\n" "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - int rc; - int is_export_bgp = 0; - int is_export_zebra = 0; - struct listnode *node; - struct rfapi_rfg_name *rfgn; - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - rc = set_ecom_list (vty, argc - 2, argv + 2, &rfg->rt_import_list); - if (rc != CMD_SUCCESS) - return rc; - - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_direct_bgp_l, - node, rfgn)) - { - - if (rfgn->rfg == rfg) - { - is_export_bgp = 1; - break; - } - } - - if (is_export_bgp) - vnc_direct_bgp_del_group (bgp, rfg); - - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_zebra_l, node, rfgn)) - { - - if (rfgn->rfg == rfg) - { - is_export_zebra = 1; - break; - } - } - - if (is_export_zebra) - { - vnc_zlog_debug_verbose ("%s: is_export_zebra", __func__); - vnc_zebra_del_group (bgp, rfg); - } - - /* - * stop referencing old import table, now reference new one - */ - if (rfg->rfapi_import_table) - rfapiImportTableRefDelByIt (bgp, rfg->rfapi_import_table); - rfg->rfapi_import_table = rfapiImportTableRefAdd (bgp, rfg->rt_import_list, rfg); - - if (is_export_bgp) - vnc_direct_bgp_add_group (bgp, rfg); - - if (is_export_zebra) - vnc_zebra_add_group (bgp, rfg); - - if (bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_prechange (bgp); - } - - rc = set_ecom_list (vty, argc - 2, argv + 2, &rfg->rt_export_list); - - if (bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_postchange (bgp); - } - - return rc; - + VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + int rc; + int is_export_bgp = 0; + int is_export_zebra = 0; + struct listnode *node; + struct rfapi_rfg_name *rfgn; + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + rc = set_ecom_list(vty, argc - 2, argv + 2, &rfg->rt_import_list); + if (rc != CMD_SUCCESS) + return rc; + + for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node, + rfgn)) { + + if (rfgn->rfg == rfg) { + is_export_bgp = 1; + break; + } + } + + if (is_export_bgp) + vnc_direct_bgp_del_group(bgp, rfg); + + for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_zebra_l, node, + rfgn)) { + + if (rfgn->rfg == rfg) { + is_export_zebra = 1; + break; + } + } + + if (is_export_zebra) { + vnc_zlog_debug_verbose("%s: is_export_zebra", __func__); + vnc_zebra_del_group(bgp, rfg); + } + + /* + * stop referencing old import table, now reference new one + */ + if (rfg->rfapi_import_table) + rfapiImportTableRefDelByIt(bgp, rfg->rfapi_import_table); + rfg->rfapi_import_table = + rfapiImportTableRefAdd(bgp, rfg->rt_import_list, rfg); + + if (is_export_bgp) + vnc_direct_bgp_add_group(bgp, rfg); + + if (is_export_zebra) + vnc_zebra_add_group(bgp, rfg); + + if (bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_prechange(bgp); + } + + rc = set_ecom_list(vty, argc - 2, argv + 2, &rfg->rt_export_list); + + if (bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_postchange(bgp); + } + + return rc; } DEFUN (vnc_nve_group_l2rd, @@ -3031,45 +2781,40 @@ DEFUN (vnc_nve_group_l2rd, "Fixed value 1-255\n" "use the low-order octet of the NVE's VN address\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (strmatch(argv[1]->text, "auto:vn")) - { - rfg->l2rd = 0; - } - else - { - char *end = NULL; - unsigned long value_l = strtoul (argv[1]->arg, &end, 10); - uint8_t value = value_l & 0xff; - - if (!argv[1]->arg[0] || *end) - { - vty_out (vty, "%% Malformed l2 nve ID \"%s\"\n",argv[1]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - if ((value_l < 1) || (value_l > 0xff)) - { - vty_out (vty, - "%% Malformed l2 nve id (must be greater than 0 and less than %u\n", - 0x100); - return CMD_WARNING_CONFIG_FAILED; - } - - rfg->l2rd = value; - } - rfg->flags |= RFAPI_RFG_L2RD; - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (strmatch(argv[1]->text, "auto:vn")) { + rfg->l2rd = 0; + } else { + char *end = NULL; + unsigned long value_l = strtoul(argv[1]->arg, &end, 10); + uint8_t value = value_l & 0xff; + + if (!argv[1]->arg[0] || *end) { + vty_out(vty, "%% Malformed l2 nve ID \"%s\"\n", + argv[1]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + if ((value_l < 1) || (value_l > 0xff)) { + vty_out(vty, + "%% Malformed l2 nve id (must be greater than 0 and less than %u\n", + 0x100); + return CMD_WARNING_CONFIG_FAILED; + } + + rfg->l2rd = value; + } + rfg->flags |= RFAPI_RFG_L2RD; + + return CMD_SUCCESS; } DEFUN (vnc_nve_group_no_l2rd, @@ -3078,21 +2823,20 @@ DEFUN (vnc_nve_group_no_l2rd, NO_STR "Specify default Local Nve ID value to use in RD for L2 routes\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } - rfg->l2rd = 0; - rfg->flags &= ~RFAPI_RFG_L2RD; + rfg->l2rd = 0; + rfg->flags &= ~RFAPI_RFG_L2RD; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (vnc_nve_group_rd, @@ -3101,73 +2845,64 @@ DEFUN (vnc_nve_group_rd, "Specify route distinguisher\n" "Route Distinguisher (: | : | auto:vn: )\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - int ret; - struct prefix_rd prd; - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (!strncmp (argv[1]->arg, "auto:vn:", 8)) - { - /* - * use AF_UNIX to designate automatically-assigned RD - * auto:vn:nn where nn is a 2-octet quantity - */ - char *end = NULL; - uint32_t value32 = strtoul (argv[1]->arg + 8, &end, 10); - uint16_t value = value32 & 0xffff; - - if (!argv[1]->arg[8] || *end) - { - vty_out (vty, "%% Malformed rd\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (value32 > 0xffff) - { - vty_out (vty, "%% Malformed rd (must be less than %u\n", - 0x0ffff); - return CMD_WARNING_CONFIG_FAILED; - } - - memset (&prd, 0, sizeof (prd)); - prd.family = AF_UNIX; - prd.prefixlen = 64; - prd.val[0] = (RD_TYPE_IP >> 8) & 0x0ff; - prd.val[1] = RD_TYPE_IP & 0x0ff; - prd.val[6] = (value >> 8) & 0x0ff; - prd.val[7] = value & 0x0ff; - - } - else - { - - ret = str2prefix_rd (argv[1]->arg, &prd); - if (!ret) - { - vty_out (vty, "%% Malformed rd\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - if (bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_prechange (bgp); - } - - rfg->rd = prd; - - if (bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_postchange (bgp); - } - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + int ret; + struct prefix_rd prd; + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (!strncmp(argv[1]->arg, "auto:vn:", 8)) { + /* + * use AF_UNIX to designate automatically-assigned RD + * auto:vn:nn where nn is a 2-octet quantity + */ + char *end = NULL; + uint32_t value32 = strtoul(argv[1]->arg + 8, &end, 10); + uint16_t value = value32 & 0xffff; + + if (!argv[1]->arg[8] || *end) { + vty_out(vty, "%% Malformed rd\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (value32 > 0xffff) { + vty_out(vty, "%% Malformed rd (must be less than %u\n", + 0x0ffff); + return CMD_WARNING_CONFIG_FAILED; + } + + memset(&prd, 0, sizeof(prd)); + prd.family = AF_UNIX; + prd.prefixlen = 64; + prd.val[0] = (RD_TYPE_IP >> 8) & 0x0ff; + prd.val[1] = RD_TYPE_IP & 0x0ff; + prd.val[6] = (value >> 8) & 0x0ff; + prd.val[7] = value & 0x0ff; + + } else { + + ret = str2prefix_rd(argv[1]->arg, &prd); + if (!ret) { + vty_out(vty, "%% Malformed rd\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + if (bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_prechange(bgp); + } + + rfg->rd = prd; + + if (bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_postchange(bgp); + } + return CMD_SUCCESS; } DEFUN (vnc_nve_group_responselifetime, @@ -3176,40 +2911,36 @@ DEFUN (vnc_nve_group_responselifetime, "Specify response lifetime\n" "Response lifetime in seconds\n" "Infinite response lifetime\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - unsigned int rspint; - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - struct rfapi_descriptor *rfd; - struct listnode *hdnode; - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (strmatch(argv[1]->text, "infinite")) - { - rspint = RFAPI_INFINITE_LIFETIME; - } - else - { - rspint = strtoul(argv[1]->arg, NULL, 10); - } - - rfg->response_lifetime = rspint; - rfg->flags |= RFAPI_RFG_RESPONSE_LIFETIME; - if (rfg->nves) - for (ALL_LIST_ELEMENTS_RO (rfg->nves, hdnode, rfd)) - rfd->response_lifetime = rspint; - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(bgp, bgp); + unsigned int rspint; + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + struct rfapi_descriptor *rfd; + struct listnode *hdnode; + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (strmatch(argv[1]->text, "infinite")) { + rspint = RFAPI_INFINITE_LIFETIME; + } else { + rspint = strtoul(argv[1]->arg, NULL, 10); + } + + rfg->response_lifetime = rspint; + rfg->flags |= RFAPI_RFG_RESPONSE_LIFETIME; + if (rfg->nves) + for (ALL_LIST_ELEMENTS_RO(rfg->nves, hdnode, rfd)) + rfd->response_lifetime = rspint; + return CMD_SUCCESS; } /* * Sigh. This command, like exit-address-family, is a hack to deal - * with the lack of rigorous level control in the command handler. + * with the lack of rigorous level control in the command handler. * TBD fix command handler. */ DEFUN_NOSH (exit_vnc, @@ -3217,27 +2948,20 @@ DEFUN_NOSH (exit_vnc, "exit-vnc", "Exit VNC configuration mode\n") { - if (vty->node == BGP_VNC_DEFAULTS_NODE || - vty->node == BGP_VNC_NVE_GROUP_NODE || - vty->node == BGP_VNC_L2_GROUP_NODE) - { - - vty->node = BGP_NODE; - } - return CMD_SUCCESS; + if (vty->node == BGP_VNC_DEFAULTS_NODE + || vty->node == BGP_VNC_NVE_GROUP_NODE + || vty->node == BGP_VNC_L2_GROUP_NODE) { + + vty->node = BGP_NODE; + } + return CMD_SUCCESS; } static struct cmd_node bgp_vnc_defaults_node = { - BGP_VNC_DEFAULTS_NODE, - "%s(config-router-vnc-defaults)# ", - 1 -}; + BGP_VNC_DEFAULTS_NODE, "%s(config-router-vnc-defaults)# ", 1}; static struct cmd_node bgp_vnc_nve_group_node = { - BGP_VNC_NVE_GROUP_NODE, - "%s(config-router-vnc-nve-group)# ", - 1 -}; + BGP_VNC_NVE_GROUP_NODE, "%s(config-router-vnc-nve-group)# ", 1}; /*------------------------------------------------------------------------- * VNC nve-group @@ -3250,35 +2974,33 @@ DEFUN_NOSH (vnc_vrf_policy, "Configure a VRF policy group\n" "VRF name\n") { - struct rfapi_nve_group_cfg *rfg; - VTY_DECLVAR_CONTEXT(bgp, bgp); - - if (!bgp) - { - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Search for name */ - rfg = bgp_rfapi_cfg_match_byname (bgp, argv[1]->arg, RFAPI_GROUP_CFG_VRF); - - if (!rfg) - { - rfg = rfapi_group_new (bgp, RFAPI_GROUP_CFG_VRF, argv[1]->arg); - if (!rfg) - { - /* Error out of memory */ - vty_out (vty, "Can't allocate memory for NVE group\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - /* - * XXX subsequent calls will need to make sure this item is still - * in the linked list and has the same name - */ - VTY_PUSH_CONTEXT_SUB (BGP_VRF_POLICY_NODE, rfg); - - return CMD_SUCCESS; + struct rfapi_nve_group_cfg *rfg; + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (!bgp) { + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Search for name */ + rfg = bgp_rfapi_cfg_match_byname(bgp, argv[1]->arg, + RFAPI_GROUP_CFG_VRF); + + if (!rfg) { + rfg = rfapi_group_new(bgp, RFAPI_GROUP_CFG_VRF, argv[1]->arg); + if (!rfg) { + /* Error out of memory */ + vty_out(vty, "Can't allocate memory for NVE group\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + /* + * XXX subsequent calls will need to make sure this item is still + * in the linked list and has the same name + */ + VTY_PUSH_CONTEXT_SUB(BGP_VRF_POLICY_NODE, rfg); + + return CMD_SUCCESS; } DEFUN (vnc_no_vrf_policy, @@ -3288,14 +3010,14 @@ DEFUN (vnc_no_vrf_policy, "Remove a VRF policy group\n" "VRF name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - - if (!bgp) - { - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - return bgp_rfapi_delete_named_nve_group (vty, bgp, argv[2]->arg, RFAPI_GROUP_CFG_VRF); + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (!bgp) { + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + return bgp_rfapi_delete_named_nve_group(vty, bgp, argv[2]->arg, + RFAPI_GROUP_CFG_VRF); } DEFUN (vnc_vrf_policy_label, @@ -3304,39 +3026,35 @@ DEFUN (vnc_vrf_policy_label, "Default label value for VRF\n" "Label Value <0-1048575>\n") { - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - - uint32_t label; - VTY_DECLVAR_CONTEXT(bgp, bgp); - - if (!bgp) - { - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - label = strtoul(argv[1]->arg, NULL, 10); - - if (bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_prechange (bgp); - } - - rfg->label = label; - - if (bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_postchange (bgp); - } - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + + uint32_t label; + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (!bgp) { + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + label = strtoul(argv[1]->arg, NULL, 10); + + if (bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_prechange(bgp); + } + + rfg->label = label; + + if (bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_postchange(bgp); + } + return CMD_SUCCESS; } DEFUN (vnc_vrf_policy_no_label, @@ -3345,29 +3063,26 @@ DEFUN (vnc_vrf_policy_no_label, NO_STR "Remove VRF default label\n") { - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - VTY_DECLVAR_CONTEXT(bgp, bgp); - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current VRF group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_prechange (bgp); - } - - rfg->label = MPLS_LABEL_ILLEGAL; - - if (bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_postchange (bgp); - } - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current VRF group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_prechange(bgp); + } + + rfg->label = MPLS_LABEL_ILLEGAL; + + if (bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_postchange(bgp); + } + return CMD_SUCCESS; } DEFUN (vnc_vrf_policy_nexthop, @@ -3378,45 +3093,40 @@ DEFUN (vnc_vrf_policy_nexthop, "IPv6 prefix\n" "Use configured router-id (default)\n") { - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - struct prefix p; - - VTY_DECLVAR_CONTEXT(bgp, bgp); - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current VRF no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_prechange (bgp); - } - - if (!str2prefix (argv[1]->arg, &p) && p.family) - { - //vty_out (vty, "Nexthop set to self\n"); - SET_FLAG (rfg->flags, RFAPI_RFG_VPN_NH_SELF); - memset(&rfg->vn_prefix, 0, sizeof(struct prefix)); - } - else - { - UNSET_FLAG (rfg->flags, RFAPI_RFG_VPN_NH_SELF); - rfg->vn_prefix = p; - rfg->un_prefix = p; - } - - /* TBD handle router-id/ nexthop changes when have advertised prefixes */ - - if (bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_postchange (bgp); - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + struct prefix p; + + VTY_DECLVAR_CONTEXT(bgp, bgp); + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current VRF no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_prechange(bgp); + } + + if (!str2prefix(argv[1]->arg, &p) && p.family) { + // vty_out (vty, "Nexthop set to self\n"); + SET_FLAG(rfg->flags, RFAPI_RFG_VPN_NH_SELF); + memset(&rfg->vn_prefix, 0, sizeof(struct prefix)); + } else { + UNSET_FLAG(rfg->flags, RFAPI_RFG_VPN_NH_SELF); + rfg->vn_prefix = p; + rfg->un_prefix = p; + } + + /* TBD handle router-id/ nexthop changes when have advertised prefixes + */ + + if (bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_postchange(bgp); + } + + return CMD_SUCCESS; } /* The RT code should be refactored/simplified with above... */ @@ -3427,73 +3137,69 @@ DEFUN (vnc_vrf_policy_rt_import, "Import filter\n" "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n") { - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - VTY_DECLVAR_CONTEXT(bgp, bgp); - int rc; - struct listnode *node; - struct rfapi_rfg_name *rfgn; - int is_export_bgp = 0; - int is_export_zebra = 0; - - if (!bgp) - { - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - rc = set_ecom_list (vty, argc-2, argv+2, &rfg->rt_import_list); - if (rc != CMD_SUCCESS) - return rc; - - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_direct_bgp_l, - node, rfgn)) - { - - if (rfgn->rfg == rfg) - { - is_export_bgp = 1; - break; - } - } - - if (is_export_bgp) - vnc_direct_bgp_del_group (bgp, rfg); - - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_zebra_l, node, rfgn)) - { - - if (rfgn->rfg == rfg) - { - is_export_zebra = 1; - break; - } - } - - if (is_export_zebra) - vnc_zebra_del_group (bgp, rfg); - - /* - * stop referencing old import table, now reference new one - */ - if (rfg->rfapi_import_table) - rfapiImportTableRefDelByIt (bgp, rfg->rfapi_import_table); - rfg->rfapi_import_table = rfapiImportTableRefAdd (bgp, rfg->rt_import_list, rfg); - - if (is_export_bgp) - vnc_direct_bgp_add_group (bgp, rfg); - - if (is_export_zebra) - vnc_zebra_add_group (bgp, rfg); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + int rc; + struct listnode *node; + struct rfapi_rfg_name *rfgn; + int is_export_bgp = 0; + int is_export_zebra = 0; + + if (!bgp) { + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + rc = set_ecom_list(vty, argc - 2, argv + 2, &rfg->rt_import_list); + if (rc != CMD_SUCCESS) + return rc; + + for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node, + rfgn)) { + + if (rfgn->rfg == rfg) { + is_export_bgp = 1; + break; + } + } + + if (is_export_bgp) + vnc_direct_bgp_del_group(bgp, rfg); + + for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_zebra_l, node, + rfgn)) { + + if (rfgn->rfg == rfg) { + is_export_zebra = 1; + break; + } + } + + if (is_export_zebra) + vnc_zebra_del_group(bgp, rfg); + + /* + * stop referencing old import table, now reference new one + */ + if (rfg->rfapi_import_table) + rfapiImportTableRefDelByIt(bgp, rfg->rfapi_import_table); + rfg->rfapi_import_table = + rfapiImportTableRefAdd(bgp, rfg->rt_import_list, rfg); + + if (is_export_bgp) + vnc_direct_bgp_add_group(bgp, rfg); + + if (is_export_zebra) + vnc_zebra_add_group(bgp, rfg); + + return CMD_SUCCESS; } DEFUN (vnc_vrf_policy_rt_export, @@ -3503,37 +3209,33 @@ DEFUN (vnc_vrf_policy_rt_export, "Export filter\n" "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n") { - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - VTY_DECLVAR_CONTEXT(bgp, bgp); - int rc; - - if (!bgp) - { - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_prechange (bgp); - } - - rc = set_ecom_list (vty, argc-2, argv+2, &rfg->rt_export_list); - - if (bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_postchange (bgp); - } - - return rc; + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + int rc; + + if (!bgp) { + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_prechange(bgp); + } + + rc = set_ecom_list(vty, argc - 2, argv + 2, &rfg->rt_export_list); + + if (bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_postchange(bgp); + } + + return rc; } DEFUN (vnc_vrf_policy_rt_both, @@ -3543,89 +3245,81 @@ DEFUN (vnc_vrf_policy_rt_both, "Export+import filters\n" "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n") { - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - VTY_DECLVAR_CONTEXT(bgp, bgp); - int rc; - int is_export_bgp = 0; - int is_export_zebra = 0; - struct listnode *node; - struct rfapi_rfg_name *rfgn; - - if (!bgp) - { - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - rc = set_ecom_list (vty, argc-2, argv+2, &rfg->rt_import_list); - if (rc != CMD_SUCCESS) - return rc; - - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_direct_bgp_l, - node, rfgn)) - { - - if (rfgn->rfg == rfg) - { - is_export_bgp = 1; - break; - } - } - - if (is_export_bgp) - vnc_direct_bgp_del_group (bgp, rfg); - - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_zebra_l, node, rfgn)) - { - - if (rfgn->rfg == rfg) - { - is_export_zebra = 1; - break; - } - } - - if (is_export_zebra) - { - vnc_zlog_debug_verbose ("%s: is_export_zebra", __func__); - vnc_zebra_del_group (bgp, rfg); - } - - /* - * stop referencing old import table, now reference new one - */ - if (rfg->rfapi_import_table) - rfapiImportTableRefDelByIt (bgp, rfg->rfapi_import_table); - rfg->rfapi_import_table = rfapiImportTableRefAdd (bgp, rfg->rt_import_list, rfg); - - if (is_export_bgp) - vnc_direct_bgp_add_group (bgp, rfg); - - if (is_export_zebra) - vnc_zebra_add_group (bgp, rfg); - - if (bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_prechange (bgp); - } - - rc = set_ecom_list (vty, argc-2, argv+2, &rfg->rt_export_list); - - if (bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_postchange (bgp); - } - - return rc; - + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + int rc; + int is_export_bgp = 0; + int is_export_zebra = 0; + struct listnode *node; + struct rfapi_rfg_name *rfgn; + + if (!bgp) { + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + rc = set_ecom_list(vty, argc - 2, argv + 2, &rfg->rt_import_list); + if (rc != CMD_SUCCESS) + return rc; + + for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node, + rfgn)) { + + if (rfgn->rfg == rfg) { + is_export_bgp = 1; + break; + } + } + + if (is_export_bgp) + vnc_direct_bgp_del_group(bgp, rfg); + + for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_zebra_l, node, + rfgn)) { + + if (rfgn->rfg == rfg) { + is_export_zebra = 1; + break; + } + } + + if (is_export_zebra) { + vnc_zlog_debug_verbose("%s: is_export_zebra", __func__); + vnc_zebra_del_group(bgp, rfg); + } + + /* + * stop referencing old import table, now reference new one + */ + if (rfg->rfapi_import_table) + rfapiImportTableRefDelByIt(bgp, rfg->rfapi_import_table); + rfg->rfapi_import_table = + rfapiImportTableRefAdd(bgp, rfg->rt_import_list, rfg); + + if (is_export_bgp) + vnc_direct_bgp_add_group(bgp, rfg); + + if (is_export_zebra) + vnc_zebra_add_group(bgp, rfg); + + if (bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_prechange(bgp); + } + + rc = set_ecom_list(vty, argc - 2, argv + 2, &rfg->rt_export_list); + + if (bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_postchange(bgp); + } + + return rc; } DEFUN (vnc_vrf_policy_rd, @@ -3634,79 +3328,69 @@ DEFUN (vnc_vrf_policy_rd, "Specify default VRF route distinguisher\n" "Route Distinguisher (: | : | auto:nh: )\n") { - int ret; - struct prefix_rd prd; - VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); - VTY_DECLVAR_CONTEXT(bgp, bgp); - - if (!bgp) - { - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (!strncmp (argv[1]->arg, "auto:nh:", 8)) - { - /* - * use AF_UNIX to designate automatically-assigned RD - * auto:vn:nn where nn is a 2-octet quantity - */ - char *end = NULL; - uint32_t value32 = strtoul (argv[1]->arg + 8, &end, 10); - uint16_t value = value32 & 0xffff; - - if (!*(argv[1]->arg + 5) || *end) - { - vty_out (vty, "%% Malformed rd\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (value32 > 0xffff) - { - vty_out (vty, "%% Malformed rd (must be less than %u\n", - 0x0ffff); - return CMD_WARNING_CONFIG_FAILED; - } - - memset (&prd, 0, sizeof (prd)); - prd.family = AF_UNIX; - prd.prefixlen = 64; - prd.val[0] = (RD_TYPE_IP >> 8) & 0x0ff; - prd.val[1] = RD_TYPE_IP & 0x0ff; - prd.val[6] = (value >> 8) & 0x0ff; - prd.val[7] = value & 0x0ff; - - } - else - { - - ret = str2prefix_rd (argv[1]->arg, &prd); - if (!ret) - { - vty_out (vty, "%% Malformed rd\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - if (bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_prechange (bgp); - } - - rfg->rd = prd; - - if (bgp->rfapi_cfg->rfg_redist == rfg) - { - vnc_redistribute_postchange (bgp); - } - return CMD_SUCCESS; + int ret; + struct prefix_rd prd; + VTY_DECLVAR_CONTEXT_SUB(rfapi_nve_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (!bgp) { + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (!strncmp(argv[1]->arg, "auto:nh:", 8)) { + /* + * use AF_UNIX to designate automatically-assigned RD + * auto:vn:nn where nn is a 2-octet quantity + */ + char *end = NULL; + uint32_t value32 = strtoul(argv[1]->arg + 8, &end, 10); + uint16_t value = value32 & 0xffff; + + if (!*(argv[1]->arg + 5) || *end) { + vty_out(vty, "%% Malformed rd\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (value32 > 0xffff) { + vty_out(vty, "%% Malformed rd (must be less than %u\n", + 0x0ffff); + return CMD_WARNING_CONFIG_FAILED; + } + + memset(&prd, 0, sizeof(prd)); + prd.family = AF_UNIX; + prd.prefixlen = 64; + prd.val[0] = (RD_TYPE_IP >> 8) & 0x0ff; + prd.val[1] = RD_TYPE_IP & 0x0ff; + prd.val[6] = (value >> 8) & 0x0ff; + prd.val[7] = value & 0x0ff; + + } else { + + ret = str2prefix_rd(argv[1]->arg, &prd); + if (!ret) { + vty_out(vty, "%% Malformed rd\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + if (bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_prechange(bgp); + } + + rfg->rd = prd; + + if (bgp->rfapi_cfg->rfg_redist == rfg) { + vnc_redistribute_postchange(bgp); + } + return CMD_SUCCESS; } DEFUN_NOSH (exit_vrf_policy, @@ -3714,18 +3398,14 @@ DEFUN_NOSH (exit_vrf_policy, "exit-vrf-policy", "Exit VRF policy configuration mode\n") { - if (vty->node == BGP_VRF_POLICY_NODE) - { - vty->node = BGP_NODE; - } - return CMD_SUCCESS; + if (vty->node == BGP_VRF_POLICY_NODE) { + vty->node = BGP_NODE; + } + return CMD_SUCCESS; } static struct cmd_node bgp_vrf_policy_node = { - BGP_VRF_POLICY_NODE, - "%s(config-router-vrf-policy)# ", - 1 -}; + BGP_VRF_POLICY_NODE, "%s(config-router-vrf-policy)# ", 1}; /*------------------------------------------------------------------------- * vnc-l2-group @@ -3737,88 +3417,82 @@ DEFUN_NOSH (vnc_l2_group, "vnc l2-group NAME", VNC_CONFIG_STR "Configure a L2 group\n" "Group name\n") { - struct rfapi_l2_group_cfg *rfg; - VTY_DECLVAR_CONTEXT(bgp, bgp); - - if (!bgp) - { - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Search for name */ - rfg = rfapi_l2_group_lookup_byname (bgp, argv[1]->arg); - - if (!rfg) - { - rfg = rfapi_l2_group_new (); - if (!rfg) - { - /* Error out of memory */ - vty_out (vty, "Can't allocate memory for L2 group\n"); - return CMD_WARNING_CONFIG_FAILED; - } - rfg->name = strdup (argv[1]->arg); - /* add to tail of list */ - listnode_add (bgp->rfapi_cfg->l2_groups, rfg); - } - - /* - * XXX subsequent calls will need to make sure this item is still - * in the linked list and has the same name - */ - VTY_PUSH_CONTEXT_SUB (BGP_VNC_L2_GROUP_NODE, rfg); - return CMD_SUCCESS; + struct rfapi_l2_group_cfg *rfg; + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (!bgp) { + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Search for name */ + rfg = rfapi_l2_group_lookup_byname(bgp, argv[1]->arg); + + if (!rfg) { + rfg = rfapi_l2_group_new(); + if (!rfg) { + /* Error out of memory */ + vty_out(vty, "Can't allocate memory for L2 group\n"); + return CMD_WARNING_CONFIG_FAILED; + } + rfg->name = strdup(argv[1]->arg); + /* add to tail of list */ + listnode_add(bgp->rfapi_cfg->l2_groups, rfg); + } + + /* + * XXX subsequent calls will need to make sure this item is still + * in the linked list and has the same name + */ + VTY_PUSH_CONTEXT_SUB(BGP_VNC_L2_GROUP_NODE, rfg); + return CMD_SUCCESS; } -static void -bgp_rfapi_delete_l2_group ( - struct vty *vty, /* NULL = no output */ - struct bgp *bgp, - struct rfapi_l2_group_cfg *rfg) +static void bgp_rfapi_delete_l2_group(struct vty *vty, /* NULL = no output */ + struct bgp *bgp, + struct rfapi_l2_group_cfg *rfg) { - /* delete it */ - free (rfg->name); - if (rfg->rt_import_list) - ecommunity_free (&rfg->rt_import_list); - if (rfg->rt_export_list) - ecommunity_free (&rfg->rt_export_list); - if (rfg->labels) - list_delete (rfg->labels); - if (rfg->rfp_cfg) - XFREE (MTYPE_RFAPI_RFP_GROUP_CFG, rfg->rfp_cfg); - listnode_delete (bgp->rfapi_cfg->l2_groups, rfg); - - rfapi_l2_group_del (rfg); + /* delete it */ + free(rfg->name); + if (rfg->rt_import_list) + ecommunity_free(&rfg->rt_import_list); + if (rfg->rt_export_list) + ecommunity_free(&rfg->rt_export_list); + if (rfg->labels) + list_delete(rfg->labels); + if (rfg->rfp_cfg) + XFREE(MTYPE_RFAPI_RFP_GROUP_CFG, rfg->rfp_cfg); + listnode_delete(bgp->rfapi_cfg->l2_groups, rfg); + + rfapi_l2_group_del(rfg); } static int -bgp_rfapi_delete_named_l2_group ( - struct vty *vty, /* NULL = no output */ - struct bgp *bgp, - const char *rfg_name) /* NULL = any */ +bgp_rfapi_delete_named_l2_group(struct vty *vty, /* NULL = no output */ + struct bgp *bgp, + const char *rfg_name) /* NULL = any */ { - struct rfapi_l2_group_cfg *rfg = NULL; - struct listnode *node, *nnode; - - /* Search for name */ - if (rfg_name) - { - rfg = rfapi_l2_group_lookup_byname (bgp, rfg_name); - if (!rfg) - { - if (vty) - vty_out (vty, "No L2 group named \"%s\"\n",rfg_name); - return CMD_WARNING_CONFIG_FAILED; - } - } - - if (rfg) - bgp_rfapi_delete_l2_group (vty, bgp, rfg); - else /* must be delete all */ - for (ALL_LIST_ELEMENTS (bgp->rfapi_cfg->l2_groups, node, nnode, rfg)) - bgp_rfapi_delete_l2_group (vty, bgp, rfg); - return CMD_SUCCESS; + struct rfapi_l2_group_cfg *rfg = NULL; + struct listnode *node, *nnode; + + /* Search for name */ + if (rfg_name) { + rfg = rfapi_l2_group_lookup_byname(bgp, rfg_name); + if (!rfg) { + if (vty) + vty_out(vty, "No L2 group named \"%s\"\n", + rfg_name); + return CMD_WARNING_CONFIG_FAILED; + } + } + + if (rfg) + bgp_rfapi_delete_l2_group(vty, bgp, rfg); + else /* must be delete all */ + for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->l2_groups, node, nnode, + rfg)) + bgp_rfapi_delete_l2_group(vty, bgp, rfg); + return CMD_SUCCESS; } DEFUN (vnc_no_l2_group, @@ -3829,14 +3503,13 @@ DEFUN (vnc_no_l2_group, "Configure a L2 group\n" "Group name\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - - if (!bgp) - { - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - return bgp_rfapi_delete_named_l2_group (vty, bgp, argv[3]->arg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (!bgp) { + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + return bgp_rfapi_delete_named_l2_group(vty, bgp, argv[3]->arg); } @@ -3846,26 +3519,24 @@ DEFUN (vnc_l2_group_lni, "Specify Logical Network ID associated with group\n" "value\n") { - VTY_DECLVAR_CONTEXT_SUB(rfapi_l2_group_cfg, rfg); - VTY_DECLVAR_CONTEXT(bgp, bgp); - - if (!bgp) - { - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->l2_groups, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current L2 group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - rfg->logical_net_id = strtoul(argv[1]->arg, NULL, 10); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT_SUB(rfapi_l2_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + + if (!bgp) { + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->l2_groups, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current L2 group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + rfg->logical_net_id = strtoul(argv[1]->arg, NULL, 10); + + return CMD_SUCCESS; } DEFUN (vnc_l2_group_labels, @@ -3874,41 +3545,37 @@ DEFUN (vnc_l2_group_labels, "Specify label values associated with group\n" "Space separated list of label values <0-1048575>\n") { - VTY_DECLVAR_CONTEXT_SUB(rfapi_l2_group_cfg, rfg); - VTY_DECLVAR_CONTEXT(bgp, bgp); - struct list *ll; - - if (!bgp) - { - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->l2_groups, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current L2 group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ll = rfg->labels; - if (ll == NULL) - { - ll = list_new (); - rfg->labels = ll; - } - argc--; - argv++; - for (; argc; --argc, ++argv) - { - uint32_t label; - label = strtoul(argv[0]->arg, NULL, 10); - if (!listnode_lookup (ll, (void *) (uintptr_t) label)) - listnode_add (ll, (void *) (uintptr_t) label); - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT_SUB(rfapi_l2_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + struct list *ll; + + if (!bgp) { + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->l2_groups, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current L2 group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ll = rfg->labels; + if (ll == NULL) { + ll = list_new(); + rfg->labels = ll; + } + argc--; + argv++; + for (; argc; --argc, ++argv) { + uint32_t label; + label = strtoul(argv[0]->arg, NULL, 10); + if (!listnode_lookup(ll, (void *)(uintptr_t)label)) + listnode_add(ll, (void *)(uintptr_t)label); + } + + return CMD_SUCCESS; } DEFUN (vnc_l2_group_no_labels, @@ -3918,41 +3585,37 @@ DEFUN (vnc_l2_group_no_labels, "Specify label values associated with L2 group\n" "Space separated list of label values <0-1048575>\n") { - VTY_DECLVAR_CONTEXT_SUB(rfapi_l2_group_cfg, rfg); - VTY_DECLVAR_CONTEXT(bgp, bgp); - struct list *ll; - - if (!bgp) - { - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->l2_groups, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current L2 group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ll = rfg->labels; - if (ll == NULL) - { - vty_out (vty, "Label no longer associated with group\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - argc-=2; - argv+=2; - for (; argc; --argc, ++argv) - { - uint32_t label; - label = strtoul(argv[0]->arg, NULL, 10); - listnode_delete (ll, (void *) (uintptr_t) label); - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT_SUB(rfapi_l2_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + struct list *ll; + + if (!bgp) { + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->l2_groups, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current L2 group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ll = rfg->labels; + if (ll == NULL) { + vty_out(vty, "Label no longer associated with group\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + argc -= 2; + argv += 2; + for (; argc; --argc, ++argv) { + uint32_t label; + label = strtoul(argv[0]->arg, NULL, 10); + listnode_delete(ll, (void *)(uintptr_t)label); + } + + return CMD_SUCCESS; } DEFUN (vnc_l2_group_rt, @@ -3964,1086 +3627,1075 @@ DEFUN (vnc_l2_group_rt, "Import filters\n" "A route target\n") { - VTY_DECLVAR_CONTEXT_SUB(rfapi_l2_group_cfg, rfg); - VTY_DECLVAR_CONTEXT(bgp, bgp); - int rc = CMD_SUCCESS; - int do_import = 0; - int do_export = 0; - - switch (argv[1]->arg[0]) - { - case 'b': - do_export = 1; /* fall through */ - case 'i': - do_import = 1; - break; - case 'e': - do_export = 1; - break; - default: - vty_out (vty, "Unknown option, %s\n", argv[1]->arg); - return CMD_ERR_NO_MATCH; - - } - if (!bgp) - { - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* make sure it's still in list */ - if (!listnode_lookup (bgp->rfapi_cfg->l2_groups, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current L2 group no longer exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (do_import) - rc = set_ecom_list (vty, argc-2, argv+2, &rfg->rt_import_list); - if (rc == CMD_SUCCESS && do_export) - rc = set_ecom_list (vty, argc-2, argv+2, &rfg->rt_export_list); - return rc; + VTY_DECLVAR_CONTEXT_SUB(rfapi_l2_group_cfg, rfg); + VTY_DECLVAR_CONTEXT(bgp, bgp); + int rc = CMD_SUCCESS; + int do_import = 0; + int do_export = 0; + + switch (argv[1]->arg[0]) { + case 'b': + do_export = 1; /* fall through */ + case 'i': + do_import = 1; + break; + case 'e': + do_export = 1; + break; + default: + vty_out(vty, "Unknown option, %s\n", argv[1]->arg); + return CMD_ERR_NO_MATCH; + } + if (!bgp) { + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* make sure it's still in list */ + if (!listnode_lookup(bgp->rfapi_cfg->l2_groups, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current L2 group no longer exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (do_import) + rc = set_ecom_list(vty, argc - 2, argv + 2, + &rfg->rt_import_list); + if (rc == CMD_SUCCESS && do_export) + rc = set_ecom_list(vty, argc - 2, argv + 2, + &rfg->rt_export_list); + return rc; } static struct cmd_node bgp_vnc_l2_group_node = { - BGP_VNC_L2_GROUP_NODE, - "%s(config-router-vnc-l2-group)# ", - 1 -}; + BGP_VNC_L2_GROUP_NODE, "%s(config-router-vnc-l2-group)# ", 1}; struct rfapi_l2_group_cfg * -bgp_rfapi_get_group_by_lni_label ( - struct bgp *bgp, - uint32_t logical_net_id, - uint32_t label) +bgp_rfapi_get_group_by_lni_label(struct bgp *bgp, uint32_t logical_net_id, + uint32_t label) { - struct rfapi_l2_group_cfg *rfg; - struct listnode *node; - - if (bgp->rfapi_cfg->l2_groups == NULL) /* not the best place for this */ - return NULL; - - label = label & 0xfffff; /* label is 20 bits! */ - - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->l2_groups, node, rfg)) - { - if (rfg->logical_net_id == logical_net_id) - { - struct listnode *lnode; - void *data; - for (ALL_LIST_ELEMENTS_RO (rfg->labels, lnode, data)) - if (((uint32_t) ((uintptr_t) data)) == label) - { /* match! */ - return rfg; - } - } - } - return NULL; + struct rfapi_l2_group_cfg *rfg; + struct listnode *node; + + if (bgp->rfapi_cfg->l2_groups == NULL) /* not the best place for this */ + return NULL; + + label = label & 0xfffff; /* label is 20 bits! */ + + for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->l2_groups, node, rfg)) { + if (rfg->logical_net_id == logical_net_id) { + struct listnode *lnode; + void *data; + for (ALL_LIST_ELEMENTS_RO(rfg->labels, lnode, data)) + if (((uint32_t)((uintptr_t)data)) + == label) { /* match! */ + return rfg; + } + } + } + return NULL; } -struct list * -bgp_rfapi_get_labellist_by_lni_label ( - struct bgp *bgp, - uint32_t logical_net_id, - uint32_t label) +struct list *bgp_rfapi_get_labellist_by_lni_label(struct bgp *bgp, + uint32_t logical_net_id, + uint32_t label) { - struct rfapi_l2_group_cfg *rfg; - rfg = bgp_rfapi_get_group_by_lni_label (bgp, logical_net_id, label); - if (rfg) - { - return rfg->labels; - } - return NULL; + struct rfapi_l2_group_cfg *rfg; + rfg = bgp_rfapi_get_group_by_lni_label(bgp, logical_net_id, label); + if (rfg) { + return rfg->labels; + } + return NULL; } struct ecommunity * -bgp_rfapi_get_ecommunity_by_lni_label ( - struct bgp *bgp, - uint32_t is_import, - uint32_t logical_net_id, - uint32_t label) +bgp_rfapi_get_ecommunity_by_lni_label(struct bgp *bgp, uint32_t is_import, + uint32_t logical_net_id, uint32_t label) { - struct rfapi_l2_group_cfg *rfg; - rfg = bgp_rfapi_get_group_by_lni_label (bgp, logical_net_id, label); - if (rfg) - { - if (is_import) - return rfg->rt_import_list; - else - return rfg->rt_export_list; - } - return NULL; + struct rfapi_l2_group_cfg *rfg; + rfg = bgp_rfapi_get_group_by_lni_label(bgp, logical_net_id, label); + if (rfg) { + if (is_import) + return rfg->rt_import_list; + else + return rfg->rt_export_list; + } + return NULL; } -void -bgp_rfapi_cfg_init (void) +void bgp_rfapi_cfg_init(void) { - /* main bgpd code does not use this hook, but vnc does */ - route_map_event_hook (vnc_routemap_event); - - install_node (&bgp_vnc_defaults_node, NULL); - install_node (&bgp_vnc_nve_group_node, NULL); - install_node (&bgp_vrf_policy_node, NULL); - install_node (&bgp_vnc_l2_group_node, NULL); - install_default (BGP_VRF_POLICY_NODE); - install_default (BGP_VNC_DEFAULTS_NODE); - install_default (BGP_VNC_NVE_GROUP_NODE); - install_default (BGP_VNC_L2_GROUP_NODE); - - /* - * Add commands - */ - install_element (BGP_NODE, &vnc_defaults_cmd); - install_element (BGP_NODE, &vnc_nve_group_cmd); - install_element (BGP_NODE, &vnc_no_nve_group_cmd); - install_element (BGP_NODE, &vnc_vrf_policy_cmd); - install_element (BGP_NODE, &vnc_no_vrf_policy_cmd); - install_element (BGP_NODE, &vnc_l2_group_cmd); - install_element (BGP_NODE, &vnc_no_l2_group_cmd); - install_element (BGP_NODE, &vnc_advertise_un_method_cmd); - install_element (BGP_NODE, &vnc_export_mode_cmd); - - install_element (BGP_VNC_DEFAULTS_NODE, &vnc_defaults_rt_import_cmd); - install_element (BGP_VNC_DEFAULTS_NODE, &vnc_defaults_rt_export_cmd); - install_element (BGP_VNC_DEFAULTS_NODE, &vnc_defaults_rt_both_cmd); - install_element (BGP_VNC_DEFAULTS_NODE, &vnc_defaults_rd_cmd); - install_element (BGP_VNC_DEFAULTS_NODE, &vnc_defaults_l2rd_cmd); - install_element (BGP_VNC_DEFAULTS_NODE, &vnc_defaults_no_l2rd_cmd); - install_element (BGP_VNC_DEFAULTS_NODE, &vnc_defaults_responselifetime_cmd); - install_element (BGP_VNC_DEFAULTS_NODE, &exit_vnc_cmd); - - install_element (BGP_NODE, &vnc_redistribute_protocol_cmd); - install_element (BGP_NODE, &vnc_no_redistribute_protocol_cmd); - install_element (BGP_NODE, &vnc_redistribute_nvegroup_cmd); - install_element (BGP_NODE, &vnc_redistribute_no_nvegroup_cmd); - install_element (BGP_NODE, &vnc_redistribute_lifetime_cmd); - install_element (BGP_NODE, &vnc_redistribute_rh_roo_localadmin_cmd); - install_element (BGP_NODE, &vnc_redistribute_mode_cmd); - install_element (BGP_NODE, &vnc_redistribute_bgp_exterior_cmd); - - install_element (BGP_NODE, &vnc_redist_bgpdirect_no_prefixlist_cmd); - install_element (BGP_NODE, &vnc_redist_bgpdirect_prefixlist_cmd); - install_element (BGP_NODE, &vnc_redist_bgpdirect_no_routemap_cmd); - install_element (BGP_NODE, &vnc_redist_bgpdirect_routemap_cmd); - - install_element (BGP_VNC_NVE_GROUP_NODE, - &vnc_nve_group_redist_bgpdirect_no_prefixlist_cmd); - install_element (BGP_VNC_NVE_GROUP_NODE, - &vnc_nve_group_redist_bgpdirect_prefixlist_cmd); - install_element (BGP_VNC_NVE_GROUP_NODE, - &vnc_nve_group_redist_bgpdirect_no_routemap_cmd); - install_element (BGP_VNC_NVE_GROUP_NODE, - &vnc_nve_group_redist_bgpdirect_routemap_cmd); - - install_element (BGP_NODE, &vnc_export_nvegroup_cmd); - install_element (BGP_NODE, &vnc_no_export_nvegroup_cmd); - install_element (BGP_NODE, &vnc_nve_export_prefixlist_cmd); - install_element (BGP_NODE, &vnc_nve_export_routemap_cmd); - install_element (BGP_NODE, &vnc_nve_export_no_prefixlist_cmd); - install_element (BGP_NODE, &vnc_nve_export_no_routemap_cmd); - - install_element (BGP_VNC_NVE_GROUP_NODE, &vnc_nve_group_l2rd_cmd); - install_element (BGP_VNC_NVE_GROUP_NODE, &vnc_nve_group_no_l2rd_cmd); - install_element (BGP_VNC_NVE_GROUP_NODE, &vnc_nve_group_prefix_cmd); - install_element (BGP_VNC_NVE_GROUP_NODE, &vnc_nve_group_rt_import_cmd); - install_element (BGP_VNC_NVE_GROUP_NODE, &vnc_nve_group_rt_export_cmd); - install_element (BGP_VNC_NVE_GROUP_NODE, &vnc_nve_group_rt_both_cmd); - install_element (BGP_VNC_NVE_GROUP_NODE, &vnc_nve_group_rd_cmd); - install_element (BGP_VNC_NVE_GROUP_NODE, - &vnc_nve_group_responselifetime_cmd); - install_element (BGP_VNC_NVE_GROUP_NODE, - &vnc_nve_group_export_prefixlist_cmd); - install_element (BGP_VNC_NVE_GROUP_NODE, - &vnc_nve_group_export_routemap_cmd); - install_element (BGP_VNC_NVE_GROUP_NODE, - &vnc_nve_group_export_no_prefixlist_cmd); - install_element (BGP_VNC_NVE_GROUP_NODE, - &vnc_nve_group_export_no_routemap_cmd); - install_element (BGP_VNC_NVE_GROUP_NODE, &exit_vnc_cmd); - - install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_label_cmd); - install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_no_label_cmd); - //Reenable to support VRF controller use case and testing - install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_nexthop_cmd); - install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_rt_import_cmd); - install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_rt_export_cmd); - install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_rt_both_cmd); - install_element (BGP_VRF_POLICY_NODE, &vnc_vrf_policy_rd_cmd); - install_element (BGP_VRF_POLICY_NODE, &exit_vrf_policy_cmd); - - install_element (BGP_VNC_L2_GROUP_NODE, &vnc_l2_group_lni_cmd); - install_element (BGP_VNC_L2_GROUP_NODE, &vnc_l2_group_labels_cmd); - install_element (BGP_VNC_L2_GROUP_NODE, &vnc_l2_group_no_labels_cmd); - install_element (BGP_VNC_L2_GROUP_NODE, &vnc_l2_group_rt_cmd); - install_element (BGP_VNC_L2_GROUP_NODE, &exit_vnc_cmd); + /* main bgpd code does not use this hook, but vnc does */ + route_map_event_hook(vnc_routemap_event); + + install_node(&bgp_vnc_defaults_node, NULL); + install_node(&bgp_vnc_nve_group_node, NULL); + install_node(&bgp_vrf_policy_node, NULL); + install_node(&bgp_vnc_l2_group_node, NULL); + install_default(BGP_VRF_POLICY_NODE); + install_default(BGP_VNC_DEFAULTS_NODE); + install_default(BGP_VNC_NVE_GROUP_NODE); + install_default(BGP_VNC_L2_GROUP_NODE); + + /* + * Add commands + */ + install_element(BGP_NODE, &vnc_defaults_cmd); + install_element(BGP_NODE, &vnc_nve_group_cmd); + install_element(BGP_NODE, &vnc_no_nve_group_cmd); + install_element(BGP_NODE, &vnc_vrf_policy_cmd); + install_element(BGP_NODE, &vnc_no_vrf_policy_cmd); + install_element(BGP_NODE, &vnc_l2_group_cmd); + install_element(BGP_NODE, &vnc_no_l2_group_cmd); + install_element(BGP_NODE, &vnc_advertise_un_method_cmd); + install_element(BGP_NODE, &vnc_export_mode_cmd); + + install_element(BGP_VNC_DEFAULTS_NODE, &vnc_defaults_rt_import_cmd); + install_element(BGP_VNC_DEFAULTS_NODE, &vnc_defaults_rt_export_cmd); + install_element(BGP_VNC_DEFAULTS_NODE, &vnc_defaults_rt_both_cmd); + install_element(BGP_VNC_DEFAULTS_NODE, &vnc_defaults_rd_cmd); + install_element(BGP_VNC_DEFAULTS_NODE, &vnc_defaults_l2rd_cmd); + install_element(BGP_VNC_DEFAULTS_NODE, &vnc_defaults_no_l2rd_cmd); + install_element(BGP_VNC_DEFAULTS_NODE, + &vnc_defaults_responselifetime_cmd); + install_element(BGP_VNC_DEFAULTS_NODE, &exit_vnc_cmd); + + install_element(BGP_NODE, &vnc_redistribute_protocol_cmd); + install_element(BGP_NODE, &vnc_no_redistribute_protocol_cmd); + install_element(BGP_NODE, &vnc_redistribute_nvegroup_cmd); + install_element(BGP_NODE, &vnc_redistribute_no_nvegroup_cmd); + install_element(BGP_NODE, &vnc_redistribute_lifetime_cmd); + install_element(BGP_NODE, &vnc_redistribute_rh_roo_localadmin_cmd); + install_element(BGP_NODE, &vnc_redistribute_mode_cmd); + install_element(BGP_NODE, &vnc_redistribute_bgp_exterior_cmd); + + install_element(BGP_NODE, &vnc_redist_bgpdirect_no_prefixlist_cmd); + install_element(BGP_NODE, &vnc_redist_bgpdirect_prefixlist_cmd); + install_element(BGP_NODE, &vnc_redist_bgpdirect_no_routemap_cmd); + install_element(BGP_NODE, &vnc_redist_bgpdirect_routemap_cmd); + + install_element(BGP_VNC_NVE_GROUP_NODE, + &vnc_nve_group_redist_bgpdirect_no_prefixlist_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, + &vnc_nve_group_redist_bgpdirect_prefixlist_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, + &vnc_nve_group_redist_bgpdirect_no_routemap_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, + &vnc_nve_group_redist_bgpdirect_routemap_cmd); + + install_element(BGP_NODE, &vnc_export_nvegroup_cmd); + install_element(BGP_NODE, &vnc_no_export_nvegroup_cmd); + install_element(BGP_NODE, &vnc_nve_export_prefixlist_cmd); + install_element(BGP_NODE, &vnc_nve_export_routemap_cmd); + install_element(BGP_NODE, &vnc_nve_export_no_prefixlist_cmd); + install_element(BGP_NODE, &vnc_nve_export_no_routemap_cmd); + + install_element(BGP_VNC_NVE_GROUP_NODE, &vnc_nve_group_l2rd_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, &vnc_nve_group_no_l2rd_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, &vnc_nve_group_prefix_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, &vnc_nve_group_rt_import_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, &vnc_nve_group_rt_export_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, &vnc_nve_group_rt_both_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, &vnc_nve_group_rd_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, + &vnc_nve_group_responselifetime_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, + &vnc_nve_group_export_prefixlist_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, + &vnc_nve_group_export_routemap_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, + &vnc_nve_group_export_no_prefixlist_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, + &vnc_nve_group_export_no_routemap_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, &exit_vnc_cmd); + + install_element(BGP_VRF_POLICY_NODE, &vnc_vrf_policy_label_cmd); + install_element(BGP_VRF_POLICY_NODE, &vnc_vrf_policy_no_label_cmd); + // Reenable to support VRF controller use case and testing + install_element(BGP_VRF_POLICY_NODE, &vnc_vrf_policy_nexthop_cmd); + install_element(BGP_VRF_POLICY_NODE, &vnc_vrf_policy_rt_import_cmd); + install_element(BGP_VRF_POLICY_NODE, &vnc_vrf_policy_rt_export_cmd); + install_element(BGP_VRF_POLICY_NODE, &vnc_vrf_policy_rt_both_cmd); + install_element(BGP_VRF_POLICY_NODE, &vnc_vrf_policy_rd_cmd); + install_element(BGP_VRF_POLICY_NODE, &exit_vrf_policy_cmd); + + install_element(BGP_VNC_L2_GROUP_NODE, &vnc_l2_group_lni_cmd); + install_element(BGP_VNC_L2_GROUP_NODE, &vnc_l2_group_labels_cmd); + install_element(BGP_VNC_L2_GROUP_NODE, &vnc_l2_group_no_labels_cmd); + install_element(BGP_VNC_L2_GROUP_NODE, &vnc_l2_group_rt_cmd); + install_element(BGP_VNC_L2_GROUP_NODE, &exit_vnc_cmd); } -struct rfapi_cfg * -bgp_rfapi_cfg_new (struct rfapi_rfp_cfg *cfg) +struct rfapi_cfg *bgp_rfapi_cfg_new(struct rfapi_rfp_cfg *cfg) { - struct rfapi_cfg *h; - int afi; - - h = - (struct rfapi_cfg *) XCALLOC (MTYPE_RFAPI_CFG, sizeof (struct rfapi_cfg)); - assert (h); - - h->nve_groups_sequential = list_new (); - assert (h->nve_groups_sequential); - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - /* ugly, to deal with addition of delegates, part of 0.99.24.1 merge */ - h->nve_groups_vn[afi].delegate = route_table_get_default_delegate (); - h->nve_groups_un[afi].delegate = route_table_get_default_delegate (); - } - h->default_response_lifetime = BGP_VNC_DEFAULT_RESPONSE_LIFETIME_DEFAULT; - h->rfg_export_direct_bgp_l = list_new (); - h->rfg_export_zebra_l = list_new (); - h->resolve_nve_roo_local_admin = - BGP_VNC_CONFIG_RESOLVE_NVE_ROO_LOCAL_ADMIN_DEFAULT; - - SET_FLAG (h->flags, BGP_VNC_CONFIG_FLAGS_DEFAULT); - - if (cfg == NULL) - { - h->rfp_cfg.download_type = RFAPI_RFP_DOWNLOAD_PARTIAL; - h->rfp_cfg.ftd_advertisement_interval = - RFAPI_RFP_CFG_DEFAULT_FTD_ADVERTISEMENT_INTERVAL; - h->rfp_cfg.holddown_factor = RFAPI_RFP_CFG_DEFAULT_HOLDDOWN_FACTOR; - h->rfp_cfg.use_updated_response = 0; - h->rfp_cfg.use_removes = 0; - } - else - { - h->rfp_cfg.download_type = cfg->download_type; - h->rfp_cfg.ftd_advertisement_interval = cfg->ftd_advertisement_interval; - h->rfp_cfg.holddown_factor = cfg->holddown_factor; - h->rfp_cfg.use_updated_response = cfg->use_updated_response; - h->rfp_cfg.use_removes = cfg->use_removes; - if (cfg->use_updated_response) - h->flags &= ~BGP_VNC_CONFIG_CALLBACK_DISABLE; - else - h->flags |= BGP_VNC_CONFIG_CALLBACK_DISABLE; - if (cfg->use_removes) - h->flags &= ~BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE; - else - h->flags |= BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE; - } - return h; + struct rfapi_cfg *h; + int afi; + + h = (struct rfapi_cfg *)XCALLOC(MTYPE_RFAPI_CFG, + sizeof(struct rfapi_cfg)); + assert(h); + + h->nve_groups_sequential = list_new(); + assert(h->nve_groups_sequential); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + /* ugly, to deal with addition of delegates, part of 0.99.24.1 + * merge */ + h->nve_groups_vn[afi].delegate = + route_table_get_default_delegate(); + h->nve_groups_un[afi].delegate = + route_table_get_default_delegate(); + } + h->default_response_lifetime = + BGP_VNC_DEFAULT_RESPONSE_LIFETIME_DEFAULT; + h->rfg_export_direct_bgp_l = list_new(); + h->rfg_export_zebra_l = list_new(); + h->resolve_nve_roo_local_admin = + BGP_VNC_CONFIG_RESOLVE_NVE_ROO_LOCAL_ADMIN_DEFAULT; + + SET_FLAG(h->flags, BGP_VNC_CONFIG_FLAGS_DEFAULT); + + if (cfg == NULL) { + h->rfp_cfg.download_type = RFAPI_RFP_DOWNLOAD_PARTIAL; + h->rfp_cfg.ftd_advertisement_interval = + RFAPI_RFP_CFG_DEFAULT_FTD_ADVERTISEMENT_INTERVAL; + h->rfp_cfg.holddown_factor = + RFAPI_RFP_CFG_DEFAULT_HOLDDOWN_FACTOR; + h->rfp_cfg.use_updated_response = 0; + h->rfp_cfg.use_removes = 0; + } else { + h->rfp_cfg.download_type = cfg->download_type; + h->rfp_cfg.ftd_advertisement_interval = + cfg->ftd_advertisement_interval; + h->rfp_cfg.holddown_factor = cfg->holddown_factor; + h->rfp_cfg.use_updated_response = cfg->use_updated_response; + h->rfp_cfg.use_removes = cfg->use_removes; + if (cfg->use_updated_response) + h->flags &= ~BGP_VNC_CONFIG_CALLBACK_DISABLE; + else + h->flags |= BGP_VNC_CONFIG_CALLBACK_DISABLE; + if (cfg->use_removes) + h->flags &= ~BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE; + else + h->flags |= BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE; + } + return h; } -void -bgp_rfapi_cfg_destroy (struct bgp *bgp, struct rfapi_cfg *h) +void bgp_rfapi_cfg_destroy(struct bgp *bgp, struct rfapi_cfg *h) { - if (h == NULL) - return; - - bgp_rfapi_delete_named_nve_group (NULL, bgp, NULL, RFAPI_GROUP_CFG_MAX); - bgp_rfapi_delete_named_l2_group (NULL, bgp, NULL); - if (h->l2_groups != NULL) - list_delete (h->l2_groups); - list_delete (h->nve_groups_sequential); - list_delete (h->rfg_export_direct_bgp_l); - list_delete (h->rfg_export_zebra_l); - if (h->default_rt_export_list) - ecommunity_free (&h->default_rt_export_list); - if (h->default_rt_import_list) - ecommunity_free (&h->default_rt_import_list); - if (h->default_rfp_cfg) - XFREE (MTYPE_RFAPI_RFP_GROUP_CFG, h->default_rfp_cfg); - XFREE (MTYPE_RFAPI_CFG, h); - + if (h == NULL) + return; + + bgp_rfapi_delete_named_nve_group(NULL, bgp, NULL, RFAPI_GROUP_CFG_MAX); + bgp_rfapi_delete_named_l2_group(NULL, bgp, NULL); + if (h->l2_groups != NULL) + list_delete(h->l2_groups); + list_delete(h->nve_groups_sequential); + list_delete(h->rfg_export_direct_bgp_l); + list_delete(h->rfg_export_zebra_l); + if (h->default_rt_export_list) + ecommunity_free(&h->default_rt_export_list); + if (h->default_rt_import_list) + ecommunity_free(&h->default_rt_import_list); + if (h->default_rfp_cfg) + XFREE(MTYPE_RFAPI_RFP_GROUP_CFG, h->default_rfp_cfg); + XFREE(MTYPE_RFAPI_CFG, h); } -int -bgp_rfapi_cfg_write (struct vty *vty, struct bgp *bgp) +int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp) { - struct listnode *node, *nnode; - struct rfapi_nve_group_cfg *rfg; - struct rfapi_cfg *hc = bgp->rfapi_cfg; - struct rfapi_rfg_name *rfgn; - int write = 0; - afi_t afi; - int type; - if (bgp->rfapi == NULL || hc == NULL) - return write; - - vty_out (vty, "!\n"); - for (ALL_LIST_ELEMENTS (hc->nve_groups_sequential, node, nnode, rfg)) - if (rfg->type == RFAPI_GROUP_CFG_VRF) - { - ++write; - vty_out (vty, " vrf-policy %s\n", rfg->name); - if (rfg->label <= MPLS_LABEL_MAX) - { - vty_out (vty, " label %u\n", rfg->label); - - } - if (CHECK_FLAG (rfg->flags, RFAPI_RFG_VPN_NH_SELF)) - { - vty_out (vty, " nexthop self\n"); - - } - else - { - if (rfg->vn_prefix.family) - { - char buf[BUFSIZ]; - buf[0] = buf[BUFSIZ - 1] = 0; - inet_ntop(rfg->vn_prefix.family, &rfg->vn_prefix.u.prefix, buf, sizeof(buf)); - if (!buf[0] || buf[BUFSIZ - 1]) - { - //vty_out (vty, "nexthop self\n"); - } - else - { - vty_out (vty, " nexthop %s\n", buf); - } - } - } - - if (rfg->rd.prefixlen) - { - char buf[BUFSIZ]; - buf[0] = buf[BUFSIZ - 1] = 0; - - if (AF_UNIX == rfg->rd.family) - { - - uint16_t value = 0; - - value = ((rfg->rd.val[6] << 8) & 0x0ff00) | - (rfg->rd.val[7] & 0x0ff); - - vty_out (vty, " rd auto:nh:%d\n", value); - - } - else - { - - if (!prefix_rd2str (&rfg->rd, buf, BUFSIZ) || - !buf[0] || buf[BUFSIZ - 1]) - { - - vty_out (vty, "!Error: Can't convert rd\n"); - } - else - { - vty_out (vty, " rd %s\n", buf); - } - } - } - - if (rfg->rt_import_list && rfg->rt_export_list && - ecommunity_cmp (rfg->rt_import_list, rfg->rt_export_list)) - { - char *b = ecommunity_ecom2str (rfg->rt_import_list, - ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET); - vty_out (vty, " rt both %s\n", b); - XFREE (MTYPE_ECOMMUNITY_STR, b); - } - else - { - if (rfg->rt_import_list) - { - char *b = ecommunity_ecom2str (rfg->rt_import_list, - ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET); - vty_out (vty, " rt import %s\n", b); - XFREE (MTYPE_ECOMMUNITY_STR, b); - } - if (rfg->rt_export_list) - { - char *b = ecommunity_ecom2str (rfg->rt_export_list, - ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET); - vty_out (vty, " rt export %s\n", b); - XFREE (MTYPE_ECOMMUNITY_STR, b); - } - } - - /* - * route filtering: prefix-lists and route-maps - */ - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - - const char *afistr = (afi == AFI_IP) ? "ipv4" : "ipv6"; - - if (rfg->plist_export_bgp_name[afi]) - { - vty_out (vty, " export bgp %s prefix-list %s\n", - afistr,rfg->plist_export_bgp_name[afi]); - } - if (rfg->plist_export_zebra_name[afi]) - { - vty_out (vty, " export zebra %s prefix-list %s\n", - afistr,rfg->plist_export_zebra_name[afi]); - } - /* - * currently we only support redist plists for bgp-direct. - * If we later add plist support for redistributing other - * protocols, we'll need to loop over protocols here - */ - if (rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]) - { - vty_out (vty, " redistribute bgp-direct %s prefix-list %s\n", - afistr, - rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]); - } - if (rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT_EXT][afi]) - { - vty_out (vty, - " redistribute bgp-direct-to-nve-groups %s prefix-list %s\n", - afistr, - rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT_EXT][afi]); - } - } - - if (rfg->routemap_export_bgp_name) - { - vty_out (vty, " export bgp route-map %s\n", - rfg->routemap_export_bgp_name); - } - if (rfg->routemap_export_zebra_name) - { - vty_out (vty, " export zebra route-map %s\n", - rfg->routemap_export_zebra_name); - } - if (rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]) - { - vty_out (vty, " redistribute bgp-direct route-map %s\n", - rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]); - } - if (rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT_EXT]) - { - vty_out (vty, - " redistribute bgp-direct-to-nve-groups route-map %s\n", - rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT_EXT]); - } - vty_out (vty, " exit-vrf-policy\n"); - vty_out (vty, "!\n"); - } - if (hc->flags & BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP) - { - vty_out (vty, " vnc advertise-un-method encap-safi\n"); - write++; - } - - { /* was based on listen ports */ - /* for now allow both old and new */ - if (bgp->rfapi->rfp_methods.cfg_cb) - write += (bgp->rfapi->rfp_methods.cfg_cb) (vty, bgp->rfapi->rfp); - - if (write) - vty_out (vty, "!\n"); - - if (hc->l2_groups) - { - struct rfapi_l2_group_cfg *rfg = NULL; - struct listnode *gnode; - for (ALL_LIST_ELEMENTS_RO (hc->l2_groups, gnode, rfg)) - { - struct listnode *lnode; - void *data; - ++write; - vty_out (vty, " vnc l2-group %s\n", rfg->name); - if (rfg->logical_net_id != 0) - vty_out (vty, " logical-network-id %u\n", - rfg->logical_net_id); - if (rfg->labels != NULL && listhead (rfg->labels) != NULL) - { - vty_out (vty, " labels "); - for (ALL_LIST_ELEMENTS_RO (rfg->labels, lnode, data)) - { - vty_out (vty, "%hu ", (uint16_t) ((uintptr_t) data)); - } - vty_out (vty, "\n"); - } - - if (rfg->rt_import_list && rfg->rt_export_list && - ecommunity_cmp (rfg->rt_import_list, rfg->rt_export_list)) - { - char *b = ecommunity_ecom2str (rfg->rt_import_list, - ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET); - vty_out (vty, " rt both %s\n", b); - XFREE (MTYPE_ECOMMUNITY_STR, b); - } - else - { - if (rfg->rt_import_list) - { - char *b = ecommunity_ecom2str (rfg->rt_import_list, - ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET); - vty_out (vty, " rt import %s\n", b); - XFREE (MTYPE_ECOMMUNITY_STR, b); - } - if (rfg->rt_export_list) - { - char *b = ecommunity_ecom2str (rfg->rt_export_list, - ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET); - vty_out (vty, " rt export %s\n", b); - XFREE (MTYPE_ECOMMUNITY_STR, b); - } - } - if (bgp->rfapi->rfp_methods.cfg_group_cb) - write += - (bgp->rfapi->rfp_methods.cfg_group_cb) (vty, - bgp->rfapi->rfp, - RFAPI_RFP_CFG_GROUP_L2, - rfg->name, - rfg->rfp_cfg); - vty_out (vty, " exit-vnc\n"); - vty_out (vty, "!\n"); - } - } - - if (hc->default_rd.family || - hc->default_response_lifetime || - hc->default_rt_import_list || - hc->default_rt_export_list || hc->nve_groups_sequential->count) - { - - - ++write; - vty_out (vty, " vnc defaults\n"); - - if (hc->default_rd.prefixlen) - { - char buf[BUFSIZ]; - buf[0] = buf[BUFSIZ - 1] = 0; - - if (AF_UNIX == hc->default_rd.family) - { - uint16_t value = 0; - - value = ((hc->default_rd.val[6] << 8) & 0x0ff00) | - (hc->default_rd.val[7] & 0x0ff); - - vty_out (vty, " rd auto:vn:%d\n", value); - - } - else - { - - if (!prefix_rd2str (&hc->default_rd, buf, BUFSIZ) || - !buf[0] || buf[BUFSIZ - 1]) - { - - vty_out (vty, "!Error: Can't convert rd\n"); - } - else - { - vty_out (vty, " rd %s\n", buf); - } - } - } - if (hc->default_response_lifetime) - { - vty_out (vty, " response-lifetime "); - if (hc->default_response_lifetime != UINT32_MAX) - vty_out (vty, "%d", hc->default_response_lifetime); - else - vty_out (vty, "infinite"); - vty_out (vty, "\n"); - } - if (hc->default_rt_import_list && hc->default_rt_export_list && - ecommunity_cmp (hc->default_rt_import_list, - hc->default_rt_export_list)) - { - char *b = ecommunity_ecom2str (hc->default_rt_import_list, - ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET); - vty_out (vty, " rt both %s\n", b); - XFREE (MTYPE_ECOMMUNITY_STR, b); - } - else - { - if (hc->default_rt_import_list) - { - char *b = ecommunity_ecom2str (hc->default_rt_import_list, - ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET); - vty_out (vty, " rt import %s\n", b); - XFREE (MTYPE_ECOMMUNITY_STR, b); - } - if (hc->default_rt_export_list) - { - char *b = ecommunity_ecom2str (hc->default_rt_export_list, - ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET); - vty_out (vty, " rt export %s\n", b); - XFREE (MTYPE_ECOMMUNITY_STR, b); - } - } - if (bgp->rfapi->rfp_methods.cfg_group_cb) - write += - (bgp->rfapi->rfp_methods.cfg_group_cb) (vty, - bgp->rfapi->rfp, - RFAPI_RFP_CFG_GROUP_DEFAULT, - NULL, - bgp->rfapi_cfg->default_rfp_cfg); - vty_out (vty, " exit-vnc\n"); - vty_out (vty, "!\n"); - } - - for (ALL_LIST_ELEMENTS (hc->nve_groups_sequential, node, nnode, rfg)) - if (rfg->type == RFAPI_GROUP_CFG_NVE) - { - ++write; - vty_out (vty, " vnc nve-group %s\n", rfg->name); - - if (rfg->vn_prefix.family && rfg->vn_node) - { - char buf[BUFSIZ]; - buf[0] = buf[BUFSIZ - 1] = 0; - - prefix2str (&rfg->vn_prefix, buf, BUFSIZ); - if (!buf[0] || buf[BUFSIZ - 1]) - { - vty_out (vty, "!Error: Can't convert prefix\n"); - } - else - { - vty_out (vty, " prefix %s %s\n", "vn", buf); - } - } - - if (rfg->un_prefix.family && rfg->un_node) - { - char buf[BUFSIZ]; - buf[0] = buf[BUFSIZ - 1] = 0; - prefix2str (&rfg->un_prefix, buf, BUFSIZ); - if (!buf[0] || buf[BUFSIZ - 1]) - { - vty_out (vty, "!Error: Can't convert prefix\n"); - } - else - { - vty_out (vty, " prefix %s %s\n", "un", buf); - } - } - - - if (rfg->rd.prefixlen) - { - char buf[BUFSIZ]; - buf[0] = buf[BUFSIZ - 1] = 0; - - if (AF_UNIX == rfg->rd.family) - { - - uint16_t value = 0; - - value = ((rfg->rd.val[6] << 8) & 0x0ff00) | - (rfg->rd.val[7] & 0x0ff); - - vty_out (vty, " rd auto:vn:%d\n", value); - - } - else - { - - if (!prefix_rd2str (&rfg->rd, buf, BUFSIZ) || - !buf[0] || buf[BUFSIZ - 1]) - { - - vty_out (vty, "!Error: Can't convert rd\n"); - } - else - { - vty_out (vty, " rd %s\n", buf); - } - } - } - if (rfg->flags & RFAPI_RFG_RESPONSE_LIFETIME) - { - vty_out (vty, " response-lifetime "); - if (rfg->response_lifetime != UINT32_MAX) - vty_out (vty, "%d", rfg->response_lifetime); - else - vty_out (vty, "infinite"); - vty_out (vty, "\n"); - } - - if (rfg->rt_import_list && rfg->rt_export_list && - ecommunity_cmp (rfg->rt_import_list, rfg->rt_export_list)) - { - char *b = ecommunity_ecom2str (rfg->rt_import_list, - ECOMMUNITY_FORMAT_ROUTE_MAP, - ECOMMUNITY_ROUTE_TARGET); - vty_out (vty, " rt both %s\n", b); - XFREE (MTYPE_ECOMMUNITY_STR, b); - } - else - { - if (rfg->rt_import_list) - { - char *b = ecommunity_ecom2str (rfg->rt_import_list, - ECOMMUNITY_FORMAT_ROUTE_MAP, - ECOMMUNITY_ROUTE_TARGET); - vty_out (vty, " rt import %s\n", b); - XFREE (MTYPE_ECOMMUNITY_STR, b); - } - if (rfg->rt_export_list) - { - char *b = ecommunity_ecom2str (rfg->rt_export_list, - ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET); - vty_out (vty, " rt export %s\n", b); - XFREE (MTYPE_ECOMMUNITY_STR, b); - } - } - - /* - * route filtering: prefix-lists and route-maps - */ - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - - const char *afistr = (afi == AFI_IP) ? "ipv4" : "ipv6"; - - if (rfg->plist_export_bgp_name[afi]) - { - vty_out (vty, " export bgp %s prefix-list %s\n", - afistr,rfg->plist_export_bgp_name[afi]); - } - if (rfg->plist_export_zebra_name[afi]) - { - vty_out (vty, " export zebra %s prefix-list %s\n", - afistr,rfg->plist_export_zebra_name[afi]); - } - /* - * currently we only support redist plists for bgp-direct. - * If we later add plist support for redistributing other - * protocols, we'll need to loop over protocols here - */ - if (rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]) - { - vty_out (vty, " redistribute bgp-direct %s prefix-list %s\n", - afistr, - rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]); - } - if (rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT_EXT][afi]) - { - vty_out (vty, - " redistribute bgp-direct-to-nve-groups %s prefix-list %s\n", - afistr, - rfg->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT_EXT][afi]); - } - } - - if (rfg->routemap_export_bgp_name) - { - vty_out (vty, " export bgp route-map %s\n", - rfg->routemap_export_bgp_name); - } - if (rfg->routemap_export_zebra_name) - { - vty_out (vty, " export zebra route-map %s\n", - rfg->routemap_export_zebra_name); - } - if (rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]) - { - vty_out (vty, " redistribute bgp-direct route-map %s\n", - rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]); - } - if (rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT_EXT]) - { - vty_out (vty, - " redistribute bgp-direct-to-nve-groups route-map %s\n", - rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT_EXT]); - } - if (bgp->rfapi->rfp_methods.cfg_group_cb) - write += - (bgp->rfapi->rfp_methods.cfg_group_cb) (vty, - bgp->rfapi->rfp, - RFAPI_RFP_CFG_GROUP_NVE, - rfg->name, rfg->rfp_cfg); - vty_out (vty, " exit-vnc\n"); - vty_out (vty, "!\n"); - } - } /* have listen ports */ - - /* - * route export to other protocols - */ - if (VNC_EXPORT_BGP_GRP_ENABLED (hc)) - { - vty_out (vty, " vnc export bgp mode group-nve\n"); - } - else if (VNC_EXPORT_BGP_RH_ENABLED (hc)) - { - vty_out (vty, " vnc export bgp mode registering-nve\n"); - } - else if (VNC_EXPORT_BGP_CE_ENABLED (hc)) - { - vty_out (vty, " vnc export bgp mode ce\n"); - } - - if (VNC_EXPORT_ZEBRA_GRP_ENABLED (hc)) - { - vty_out (vty, " vnc export zebra mode group-nve\n"); - } - else if (VNC_EXPORT_ZEBRA_RH_ENABLED (hc)) - { - vty_out (vty, " vnc export zebra mode registering-nve\n"); - } - - if (hc->rfg_export_direct_bgp_l) - { - for (ALL_LIST_ELEMENTS (hc->rfg_export_direct_bgp_l, node, nnode, rfgn)) - { - - vty_out (vty, " vnc export bgp group-nve group %s\n", - rfgn->name); - } - } - - if (hc->rfg_export_zebra_l) - { - for (ALL_LIST_ELEMENTS (hc->rfg_export_zebra_l, node, nnode, rfgn)) - { - - vty_out (vty, " vnc export zebra group-nve group %s\n", - rfgn->name); - } - } - - - if (hc->rfg_redist_name) - { - vty_out (vty, " vnc redistribute nve-group %s\n", - hc->rfg_redist_name); - } - if (hc->redist_lifetime) - { - vty_out (vty, " vnc redistribute lifetime %d\n", - hc->redist_lifetime); - } - if (hc->resolve_nve_roo_local_admin != - BGP_VNC_CONFIG_RESOLVE_NVE_ROO_LOCAL_ADMIN_DEFAULT) - { - - vty_out (vty, " vnc redistribute resolve-nve roo-ec-local-admin %d\n", - hc->resolve_nve_roo_local_admin); - } - - if (hc->redist_mode) /* ! default */ - { - const char *s = ""; - - switch (hc->redist_mode) - { - case VNC_REDIST_MODE_PLAIN: - s = "plain"; - break; - case VNC_REDIST_MODE_RFG: - s = "nve-group"; - break; - case VNC_REDIST_MODE_RESOLVE_NVE: - s = "resolve-nve"; - break; - } - if (s) - { - vty_out (vty, " vnc redistribute mode %s\n", s); - } - } - - /* - * route filtering: prefix-lists and route-maps - */ - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - - const char *afistr = (afi == AFI_IP) ? "ipv4" : "ipv6"; - - if (hc->plist_export_bgp_name[afi]) - { - vty_out (vty, " vnc export bgp %s prefix-list %s\n", - afistr, hc->plist_export_bgp_name[afi]); - } - if (hc->plist_export_zebra_name[afi]) - { - vty_out (vty, " vnc export zebra %s prefix-list %s\n", - afistr, hc->plist_export_zebra_name[afi]); - } - if (hc->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]) - { - vty_out (vty, " vnc redistribute bgp-direct %s prefix-list %s\n", - afistr,hc->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]); - } - } - - if (hc->routemap_export_bgp_name) - { - vty_out (vty, " vnc export bgp route-map %s\n", - hc->routemap_export_bgp_name); - } - if (hc->routemap_export_zebra_name) - { - vty_out (vty, " vnc export zebra route-map %s\n", - hc->routemap_export_zebra_name); - } - if (hc->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]) - { - vty_out (vty, " vnc redistribute bgp-direct route-map %s\n", - hc->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]); - } - - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - for (type = 0; type < ZEBRA_ROUTE_MAX; ++type) - { - if (hc->redist[afi][type]) - { - if (type == ZEBRA_ROUTE_BGP_DIRECT_EXT && - hc->redist_bgp_exterior_view_name) - { - vty_out (vty, " vnc redistribute %s %s view %s\n", - ((afi == AFI_IP) ? "ipv4" : "ipv6"), - zebra_route_string (type), - hc->redist_bgp_exterior_view_name); - } - else - { - vty_out (vty, " vnc redistribute %s %s\n", - ((afi == AFI_IP) ? "ipv4" : "ipv6"), - zebra_route_string(type)); - } - } - } - } - return write; + struct listnode *node, *nnode; + struct rfapi_nve_group_cfg *rfg; + struct rfapi_cfg *hc = bgp->rfapi_cfg; + struct rfapi_rfg_name *rfgn; + int write = 0; + afi_t afi; + int type; + if (bgp->rfapi == NULL || hc == NULL) + return write; + + vty_out(vty, "!\n"); + for (ALL_LIST_ELEMENTS(hc->nve_groups_sequential, node, nnode, rfg)) + if (rfg->type == RFAPI_GROUP_CFG_VRF) { + ++write; + vty_out(vty, " vrf-policy %s\n", rfg->name); + if (rfg->label <= MPLS_LABEL_MAX) { + vty_out(vty, " label %u\n", rfg->label); + } + if (CHECK_FLAG(rfg->flags, RFAPI_RFG_VPN_NH_SELF)) { + vty_out(vty, " nexthop self\n"); + + } else { + if (rfg->vn_prefix.family) { + char buf[BUFSIZ]; + buf[0] = buf[BUFSIZ - 1] = 0; + inet_ntop(rfg->vn_prefix.family, + &rfg->vn_prefix.u.prefix, buf, + sizeof(buf)); + if (!buf[0] || buf[BUFSIZ - 1]) { + // vty_out (vty, "nexthop + // self\n"); + } else { + vty_out(vty, " nexthop %s\n", + buf); + } + } + } + + if (rfg->rd.prefixlen) { + char buf[BUFSIZ]; + buf[0] = buf[BUFSIZ - 1] = 0; + + if (AF_UNIX == rfg->rd.family) { + + uint16_t value = 0; + + value = ((rfg->rd.val[6] << 8) + & 0x0ff00) + | (rfg->rd.val[7] & 0x0ff); + + vty_out(vty, " rd auto:nh:%d\n", + value); + + } else { + + if (!prefix_rd2str(&rfg->rd, buf, + BUFSIZ) + || !buf[0] || buf[BUFSIZ - 1]) { + + vty_out(vty, + "!Error: Can't convert rd\n"); + } else { + vty_out(vty, " rd %s\n", buf); + } + } + } + + if (rfg->rt_import_list && rfg->rt_export_list + && ecommunity_cmp(rfg->rt_import_list, + rfg->rt_export_list)) { + char *b = ecommunity_ecom2str( + rfg->rt_import_list, + ECOMMUNITY_FORMAT_ROUTE_MAP, + ECOMMUNITY_ROUTE_TARGET); + vty_out(vty, " rt both %s\n", b); + XFREE(MTYPE_ECOMMUNITY_STR, b); + } else { + if (rfg->rt_import_list) { + char *b = ecommunity_ecom2str( + rfg->rt_import_list, + ECOMMUNITY_FORMAT_ROUTE_MAP, + ECOMMUNITY_ROUTE_TARGET); + vty_out(vty, " rt import %s\n", b); + XFREE(MTYPE_ECOMMUNITY_STR, b); + } + if (rfg->rt_export_list) { + char *b = ecommunity_ecom2str( + rfg->rt_export_list, + ECOMMUNITY_FORMAT_ROUTE_MAP, + ECOMMUNITY_ROUTE_TARGET); + vty_out(vty, " rt export %s\n", b); + XFREE(MTYPE_ECOMMUNITY_STR, b); + } + } + + /* + * route filtering: prefix-lists and route-maps + */ + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + + const char *afistr = + (afi == AFI_IP) ? "ipv4" : "ipv6"; + + if (rfg->plist_export_bgp_name[afi]) { + vty_out(vty, + " export bgp %s prefix-list %s\n", + afistr, + rfg->plist_export_bgp_name + [afi]); + } + if (rfg->plist_export_zebra_name[afi]) { + vty_out(vty, + " export zebra %s prefix-list %s\n", + afistr, + rfg->plist_export_zebra_name + [afi]); + } + /* + * currently we only support redist plists for + * bgp-direct. + * If we later add plist support for + * redistributing other + * protocols, we'll need to loop over protocols + * here + */ + if (rfg->plist_redist_name + [ZEBRA_ROUTE_BGP_DIRECT][afi]) { + vty_out(vty, + " redistribute bgp-direct %s prefix-list %s\n", + afistr, + rfg->plist_redist_name + [ZEBRA_ROUTE_BGP_DIRECT] + [afi]); + } + if (rfg->plist_redist_name + [ZEBRA_ROUTE_BGP_DIRECT_EXT][afi]) { + vty_out(vty, + " redistribute bgp-direct-to-nve-groups %s prefix-list %s\n", + afistr, + rfg->plist_redist_name + [ZEBRA_ROUTE_BGP_DIRECT_EXT] + [afi]); + } + } + + if (rfg->routemap_export_bgp_name) { + vty_out(vty, " export bgp route-map %s\n", + rfg->routemap_export_bgp_name); + } + if (rfg->routemap_export_zebra_name) { + vty_out(vty, " export zebra route-map %s\n", + rfg->routemap_export_zebra_name); + } + if (rfg->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]) { + vty_out(vty, + " redistribute bgp-direct route-map %s\n", + rfg->routemap_redist_name + [ZEBRA_ROUTE_BGP_DIRECT]); + } + if (rfg->routemap_redist_name + [ZEBRA_ROUTE_BGP_DIRECT_EXT]) { + vty_out(vty, + " redistribute bgp-direct-to-nve-groups route-map %s\n", + rfg->routemap_redist_name + [ZEBRA_ROUTE_BGP_DIRECT_EXT]); + } + vty_out(vty, " exit-vrf-policy\n"); + vty_out(vty, "!\n"); + } + if (hc->flags & BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP) { + vty_out(vty, " vnc advertise-un-method encap-safi\n"); + write++; + } + + { /* was based on listen ports */ + /* for now allow both old and new */ + if (bgp->rfapi->rfp_methods.cfg_cb) + write += (bgp->rfapi->rfp_methods.cfg_cb)( + vty, bgp->rfapi->rfp); + + if (write) + vty_out(vty, "!\n"); + + if (hc->l2_groups) { + struct rfapi_l2_group_cfg *rfg = NULL; + struct listnode *gnode; + for (ALL_LIST_ELEMENTS_RO(hc->l2_groups, gnode, rfg)) { + struct listnode *lnode; + void *data; + ++write; + vty_out(vty, " vnc l2-group %s\n", rfg->name); + if (rfg->logical_net_id != 0) + vty_out(vty, + " logical-network-id %u\n", + rfg->logical_net_id); + if (rfg->labels != NULL + && listhead(rfg->labels) != NULL) { + vty_out(vty, " labels "); + for (ALL_LIST_ELEMENTS_RO(rfg->labels, + lnode, + data)) { + vty_out(vty, "%hu ", + (uint16_t)( + (uintptr_t) + data)); + } + vty_out(vty, "\n"); + } + + if (rfg->rt_import_list && rfg->rt_export_list + && ecommunity_cmp(rfg->rt_import_list, + rfg->rt_export_list)) { + char *b = ecommunity_ecom2str( + rfg->rt_import_list, + ECOMMUNITY_FORMAT_ROUTE_MAP, + ECOMMUNITY_ROUTE_TARGET); + vty_out(vty, " rt both %s\n", b); + XFREE(MTYPE_ECOMMUNITY_STR, b); + } else { + if (rfg->rt_import_list) { + char *b = ecommunity_ecom2str( + rfg->rt_import_list, + ECOMMUNITY_FORMAT_ROUTE_MAP, + ECOMMUNITY_ROUTE_TARGET); + vty_out(vty, " rt import %s\n", + b); + XFREE(MTYPE_ECOMMUNITY_STR, b); + } + if (rfg->rt_export_list) { + char *b = ecommunity_ecom2str( + rfg->rt_export_list, + ECOMMUNITY_FORMAT_ROUTE_MAP, + ECOMMUNITY_ROUTE_TARGET); + vty_out(vty, " rt export %s\n", + b); + XFREE(MTYPE_ECOMMUNITY_STR, b); + } + } + if (bgp->rfapi->rfp_methods.cfg_group_cb) + write += (bgp->rfapi->rfp_methods + .cfg_group_cb)( + vty, bgp->rfapi->rfp, + RFAPI_RFP_CFG_GROUP_L2, + rfg->name, rfg->rfp_cfg); + vty_out(vty, " exit-vnc\n"); + vty_out(vty, "!\n"); + } + } + + if (hc->default_rd.family || hc->default_response_lifetime + || hc->default_rt_import_list || hc->default_rt_export_list + || hc->nve_groups_sequential->count) { + + + ++write; + vty_out(vty, " vnc defaults\n"); + + if (hc->default_rd.prefixlen) { + char buf[BUFSIZ]; + buf[0] = buf[BUFSIZ - 1] = 0; + + if (AF_UNIX == hc->default_rd.family) { + uint16_t value = 0; + + value = ((hc->default_rd.val[6] << 8) + & 0x0ff00) + | (hc->default_rd.val[7] + & 0x0ff); + + vty_out(vty, " rd auto:vn:%d\n", + value); + + } else { + + if (!prefix_rd2str(&hc->default_rd, buf, + BUFSIZ) + || !buf[0] || buf[BUFSIZ - 1]) { + + vty_out(vty, + "!Error: Can't convert rd\n"); + } else { + vty_out(vty, " rd %s\n", buf); + } + } + } + if (hc->default_response_lifetime) { + vty_out(vty, " response-lifetime "); + if (hc->default_response_lifetime != UINT32_MAX) + vty_out(vty, "%d", + hc->default_response_lifetime); + else + vty_out(vty, "infinite"); + vty_out(vty, "\n"); + } + if (hc->default_rt_import_list + && hc->default_rt_export_list + && ecommunity_cmp(hc->default_rt_import_list, + hc->default_rt_export_list)) { + char *b = ecommunity_ecom2str( + hc->default_rt_import_list, + ECOMMUNITY_FORMAT_ROUTE_MAP, + ECOMMUNITY_ROUTE_TARGET); + vty_out(vty, " rt both %s\n", b); + XFREE(MTYPE_ECOMMUNITY_STR, b); + } else { + if (hc->default_rt_import_list) { + char *b = ecommunity_ecom2str( + hc->default_rt_import_list, + ECOMMUNITY_FORMAT_ROUTE_MAP, + ECOMMUNITY_ROUTE_TARGET); + vty_out(vty, " rt import %s\n", b); + XFREE(MTYPE_ECOMMUNITY_STR, b); + } + if (hc->default_rt_export_list) { + char *b = ecommunity_ecom2str( + hc->default_rt_export_list, + ECOMMUNITY_FORMAT_ROUTE_MAP, + ECOMMUNITY_ROUTE_TARGET); + vty_out(vty, " rt export %s\n", b); + XFREE(MTYPE_ECOMMUNITY_STR, b); + } + } + if (bgp->rfapi->rfp_methods.cfg_group_cb) + write += (bgp->rfapi->rfp_methods.cfg_group_cb)( + vty, bgp->rfapi->rfp, + RFAPI_RFP_CFG_GROUP_DEFAULT, NULL, + bgp->rfapi_cfg->default_rfp_cfg); + vty_out(vty, " exit-vnc\n"); + vty_out(vty, "!\n"); + } + + for (ALL_LIST_ELEMENTS(hc->nve_groups_sequential, node, nnode, + rfg)) + if (rfg->type == RFAPI_GROUP_CFG_NVE) { + ++write; + vty_out(vty, " vnc nve-group %s\n", rfg->name); + + if (rfg->vn_prefix.family && rfg->vn_node) { + char buf[BUFSIZ]; + buf[0] = buf[BUFSIZ - 1] = 0; + + prefix2str(&rfg->vn_prefix, buf, + BUFSIZ); + if (!buf[0] || buf[BUFSIZ - 1]) { + vty_out(vty, + "!Error: Can't convert prefix\n"); + } else { + vty_out(vty, " prefix %s %s\n", + "vn", buf); + } + } + + if (rfg->un_prefix.family && rfg->un_node) { + char buf[BUFSIZ]; + buf[0] = buf[BUFSIZ - 1] = 0; + prefix2str(&rfg->un_prefix, buf, + BUFSIZ); + if (!buf[0] || buf[BUFSIZ - 1]) { + vty_out(vty, + "!Error: Can't convert prefix\n"); + } else { + vty_out(vty, " prefix %s %s\n", + "un", buf); + } + } + + + if (rfg->rd.prefixlen) { + char buf[BUFSIZ]; + buf[0] = buf[BUFSIZ - 1] = 0; + + if (AF_UNIX == rfg->rd.family) { + + uint16_t value = 0; + + value = ((rfg->rd.val[6] << 8) + & 0x0ff00) + | (rfg->rd.val[7] + & 0x0ff); + + vty_out(vty, + " rd auto:vn:%d\n", + value); + + } else { + + if (!prefix_rd2str(&rfg->rd, + buf, BUFSIZ) + || !buf[0] + || buf[BUFSIZ - 1]) { + + vty_out(vty, + "!Error: Can't convert rd\n"); + } else { + vty_out(vty, + " rd %s\n", + buf); + } + } + } + if (rfg->flags & RFAPI_RFG_RESPONSE_LIFETIME) { + vty_out(vty, " response-lifetime "); + if (rfg->response_lifetime + != UINT32_MAX) + vty_out(vty, "%d", + rfg->response_lifetime); + else + vty_out(vty, "infinite"); + vty_out(vty, "\n"); + } + + if (rfg->rt_import_list && rfg->rt_export_list + && ecommunity_cmp(rfg->rt_import_list, + rfg->rt_export_list)) { + char *b = ecommunity_ecom2str( + rfg->rt_import_list, + ECOMMUNITY_FORMAT_ROUTE_MAP, + ECOMMUNITY_ROUTE_TARGET); + vty_out(vty, " rt both %s\n", b); + XFREE(MTYPE_ECOMMUNITY_STR, b); + } else { + if (rfg->rt_import_list) { + char *b = ecommunity_ecom2str( + rfg->rt_import_list, + ECOMMUNITY_FORMAT_ROUTE_MAP, + ECOMMUNITY_ROUTE_TARGET); + vty_out(vty, " rt import %s\n", + b); + XFREE(MTYPE_ECOMMUNITY_STR, b); + } + if (rfg->rt_export_list) { + char *b = ecommunity_ecom2str( + rfg->rt_export_list, + ECOMMUNITY_FORMAT_ROUTE_MAP, + ECOMMUNITY_ROUTE_TARGET); + vty_out(vty, " rt export %s\n", + b); + XFREE(MTYPE_ECOMMUNITY_STR, b); + } + } + + /* + * route filtering: prefix-lists and route-maps + */ + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + + const char *afistr = (afi == AFI_IP) + ? "ipv4" + : "ipv6"; + + if (rfg->plist_export_bgp_name[afi]) { + vty_out(vty, + " export bgp %s prefix-list %s\n", + afistr, + rfg->plist_export_bgp_name + [afi]); + } + if (rfg->plist_export_zebra_name[afi]) { + vty_out(vty, + " export zebra %s prefix-list %s\n", + afistr, + rfg->plist_export_zebra_name + [afi]); + } + /* + * currently we only support redist + * plists for bgp-direct. + * If we later add plist support for + * redistributing other + * protocols, we'll need to loop over + * protocols here + */ + if (rfg->plist_redist_name + [ZEBRA_ROUTE_BGP_DIRECT] + [afi]) { + vty_out(vty, + " redistribute bgp-direct %s prefix-list %s\n", + afistr, + rfg->plist_redist_name + [ZEBRA_ROUTE_BGP_DIRECT] + [afi]); + } + if (rfg->plist_redist_name + [ZEBRA_ROUTE_BGP_DIRECT_EXT] + [afi]) { + vty_out(vty, + " redistribute bgp-direct-to-nve-groups %s prefix-list %s\n", + afistr, + rfg->plist_redist_name + [ZEBRA_ROUTE_BGP_DIRECT_EXT] + [afi]); + } + } + + if (rfg->routemap_export_bgp_name) { + vty_out(vty, + " export bgp route-map %s\n", + rfg->routemap_export_bgp_name); + } + if (rfg->routemap_export_zebra_name) { + vty_out(vty, + " export zebra route-map %s\n", + rfg->routemap_export_zebra_name); + } + if (rfg->routemap_redist_name + [ZEBRA_ROUTE_BGP_DIRECT]) { + vty_out(vty, + " redistribute bgp-direct route-map %s\n", + rfg->routemap_redist_name + [ZEBRA_ROUTE_BGP_DIRECT]); + } + if (rfg->routemap_redist_name + [ZEBRA_ROUTE_BGP_DIRECT_EXT]) { + vty_out(vty, + " redistribute bgp-direct-to-nve-groups route-map %s\n", + rfg->routemap_redist_name + [ZEBRA_ROUTE_BGP_DIRECT_EXT]); + } + if (bgp->rfapi->rfp_methods.cfg_group_cb) + write += (bgp->rfapi->rfp_methods + .cfg_group_cb)( + vty, bgp->rfapi->rfp, + RFAPI_RFP_CFG_GROUP_NVE, + rfg->name, rfg->rfp_cfg); + vty_out(vty, " exit-vnc\n"); + vty_out(vty, "!\n"); + } + } /* have listen ports */ + + /* + * route export to other protocols + */ + if (VNC_EXPORT_BGP_GRP_ENABLED(hc)) { + vty_out(vty, " vnc export bgp mode group-nve\n"); + } else if (VNC_EXPORT_BGP_RH_ENABLED(hc)) { + vty_out(vty, " vnc export bgp mode registering-nve\n"); + } else if (VNC_EXPORT_BGP_CE_ENABLED(hc)) { + vty_out(vty, " vnc export bgp mode ce\n"); + } + + if (VNC_EXPORT_ZEBRA_GRP_ENABLED(hc)) { + vty_out(vty, " vnc export zebra mode group-nve\n"); + } else if (VNC_EXPORT_ZEBRA_RH_ENABLED(hc)) { + vty_out(vty, " vnc export zebra mode registering-nve\n"); + } + + if (hc->rfg_export_direct_bgp_l) { + for (ALL_LIST_ELEMENTS(hc->rfg_export_direct_bgp_l, node, nnode, + rfgn)) { + + vty_out(vty, " vnc export bgp group-nve group %s\n", + rfgn->name); + } + } + + if (hc->rfg_export_zebra_l) { + for (ALL_LIST_ELEMENTS(hc->rfg_export_zebra_l, node, nnode, + rfgn)) { + + vty_out(vty, " vnc export zebra group-nve group %s\n", + rfgn->name); + } + } + + + if (hc->rfg_redist_name) { + vty_out(vty, " vnc redistribute nve-group %s\n", + hc->rfg_redist_name); + } + if (hc->redist_lifetime) { + vty_out(vty, " vnc redistribute lifetime %d\n", + hc->redist_lifetime); + } + if (hc->resolve_nve_roo_local_admin + != BGP_VNC_CONFIG_RESOLVE_NVE_ROO_LOCAL_ADMIN_DEFAULT) { + + vty_out(vty, + " vnc redistribute resolve-nve roo-ec-local-admin %d\n", + hc->resolve_nve_roo_local_admin); + } + + if (hc->redist_mode) /* ! default */ + { + const char *s = ""; + + switch (hc->redist_mode) { + case VNC_REDIST_MODE_PLAIN: + s = "plain"; + break; + case VNC_REDIST_MODE_RFG: + s = "nve-group"; + break; + case VNC_REDIST_MODE_RESOLVE_NVE: + s = "resolve-nve"; + break; + } + if (s) { + vty_out(vty, " vnc redistribute mode %s\n", s); + } + } + + /* + * route filtering: prefix-lists and route-maps + */ + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + + const char *afistr = (afi == AFI_IP) ? "ipv4" : "ipv6"; + + if (hc->plist_export_bgp_name[afi]) { + vty_out(vty, " vnc export bgp %s prefix-list %s\n", + afistr, hc->plist_export_bgp_name[afi]); + } + if (hc->plist_export_zebra_name[afi]) { + vty_out(vty, " vnc export zebra %s prefix-list %s\n", + afistr, hc->plist_export_zebra_name[afi]); + } + if (hc->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT][afi]) { + vty_out(vty, + " vnc redistribute bgp-direct %s prefix-list %s\n", + afistr, + hc->plist_redist_name[ZEBRA_ROUTE_BGP_DIRECT] + [afi]); + } + } + + if (hc->routemap_export_bgp_name) { + vty_out(vty, " vnc export bgp route-map %s\n", + hc->routemap_export_bgp_name); + } + if (hc->routemap_export_zebra_name) { + vty_out(vty, " vnc export zebra route-map %s\n", + hc->routemap_export_zebra_name); + } + if (hc->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]) { + vty_out(vty, " vnc redistribute bgp-direct route-map %s\n", + hc->routemap_redist_name[ZEBRA_ROUTE_BGP_DIRECT]); + } + + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + for (type = 0; type < ZEBRA_ROUTE_MAX; ++type) { + if (hc->redist[afi][type]) { + if (type == ZEBRA_ROUTE_BGP_DIRECT_EXT + && hc->redist_bgp_exterior_view_name) { + vty_out(vty, + " vnc redistribute %s %s view %s\n", + ((afi == AFI_IP) ? "ipv4" + : "ipv6"), + zebra_route_string(type), + hc->redist_bgp_exterior_view_name); + } else { + vty_out(vty, + " vnc redistribute %s %s\n", + ((afi == AFI_IP) ? "ipv4" + : "ipv6"), + zebra_route_string(type)); + } + } + } + } + return write; } -void -bgp_rfapi_show_summary (struct bgp *bgp, struct vty *vty) +void bgp_rfapi_show_summary(struct bgp *bgp, struct vty *vty) { - struct rfapi_cfg *hc = bgp->rfapi_cfg; - int afi, type, redist = 0; - char tmp[40]; - if (hc == NULL) - return; - - vty_out (vty, "%-39s %-19s %s\n", "VNC Advertise method:", - (hc->flags & BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP - ? "Encapsulation SAFI" : "Tunnel Encap attribute"), - ((hc->flags & BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP) == (BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP & BGP_VNC_CONFIG_FLAGS_DEFAULT) ? "(default)" : "")); - /* export */ - vty_out (vty, "%-39s ", "Export from VNC:"); - /* - * route export to other protocols - */ - if (VNC_EXPORT_BGP_GRP_ENABLED (hc)) - { - redist++; - vty_out (vty, "ToBGP Groups={"); - if (hc->rfg_export_direct_bgp_l) - { - int cnt = 0; - struct listnode *node, *nnode; - struct rfapi_rfg_name *rfgn; - for (ALL_LIST_ELEMENTS (hc->rfg_export_direct_bgp_l, - node, nnode, rfgn)) - { - if (cnt++ != 0) - vty_out (vty, ","); - - vty_out (vty, "%s", rfgn->name); - } - } - vty_out (vty, "}"); - } - else if (VNC_EXPORT_BGP_RH_ENABLED (hc)) - { - redist++; - vty_out (vty, "ToBGP {Registering NVE}"); - /* note filters, route-maps not shown */ - } - else if (VNC_EXPORT_BGP_CE_ENABLED (hc)) - { - redist++; - vty_out (vty, "ToBGP {NVE connected router:%d}", - hc->resolve_nve_roo_local_admin); - /* note filters, route-maps not shown */ - } - - if (VNC_EXPORT_ZEBRA_GRP_ENABLED (hc)) - { - redist++; - vty_out (vty, "%sToZebra Groups={", (redist == 1 ? "" : " ")); - if (hc->rfg_export_direct_bgp_l) - { - int cnt = 0; - struct listnode *node, *nnode; - struct rfapi_rfg_name *rfgn; - for (ALL_LIST_ELEMENTS (hc->rfg_export_zebra_l, node, nnode, rfgn)) - { - if (cnt++ != 0) - vty_out (vty, ","); - vty_out (vty, "%s", rfgn->name); - } - } - vty_out (vty, "}"); - } - else if (VNC_EXPORT_ZEBRA_RH_ENABLED (hc)) - { - redist++; - vty_out (vty, "%sToZebra {Registering NVE}", (redist == 1 ? "" : " ")); - /* note filters, route-maps not shown */ - } - vty_out (vty, "%-19s %s\n", (redist ? "" : "Off"), - (redist ? "" : "(default)")); - - /* Redistribution */ - redist = 0; - vty_out (vty, "%-39s ", "Redistribution into VNC:"); - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - for (type = 0; type < ZEBRA_ROUTE_MAX; ++type) - { - if (hc->redist[afi][type]) - { - vty_out (vty, "{%s,%s} ", - ((afi == AFI_IP) ? "ipv4" : "ipv6"), - zebra_route_string (type)); - redist++; - } - } - } - vty_out (vty, "%-19s %s\n", (redist ? "" : "Off"), - (redist ? "" : "(default)")); - - vty_out (vty, "%-39s %3u%-16s %s\n", "RFP Registration Hold-Down Factor:", - hc->rfp_cfg.holddown_factor, "%", - (hc->rfp_cfg.holddown_factor == RFAPI_RFP_CFG_DEFAULT_HOLDDOWN_FACTOR ? "(default)" : "")); - vty_out (vty, "%-39s %-19s %s\n", "RFP Updated responses:", - (hc->rfp_cfg.use_updated_response == 0 ? "Off" : "On"), - (hc->rfp_cfg.use_updated_response == 0 ? "(default)" : "")); - vty_out (vty, "%-39s %-19s %s\n", "RFP Removal responses:", - (hc->rfp_cfg.use_removes == 0 ? "Off" : "On"), - (hc->rfp_cfg.use_removes == 0 ? "(default)" : "")); - vty_out (vty, "%-39s %-19s %s\n", "RFP Full table download:", - (hc->rfp_cfg.download_type == - RFAPI_RFP_DOWNLOAD_FULL ? "On" : "Off"), - (hc->rfp_cfg.download_type == RFAPI_RFP_DOWNLOAD_PARTIAL ? "(default)" : "")); - sprintf (tmp, "%u seconds", hc->rfp_cfg.ftd_advertisement_interval); - vty_out (vty, "%-39s %-19s %s\n", " Advertisement Interval:", tmp, - (hc->rfp_cfg.ftd_advertisement_interval == RFAPI_RFP_CFG_DEFAULT_FTD_ADVERTISEMENT_INTERVAL ? "(default)" : "")); - vty_out (vty, "%-39s %d seconds\n", "Default RFP response lifetime:", - hc->default_response_lifetime); - vty_out (vty, "\n"); - return; + struct rfapi_cfg *hc = bgp->rfapi_cfg; + int afi, type, redist = 0; + char tmp[40]; + if (hc == NULL) + return; + + vty_out(vty, "%-39s %-19s %s\n", "VNC Advertise method:", + (hc->flags & BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP + ? "Encapsulation SAFI" + : "Tunnel Encap attribute"), + ((hc->flags & BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP) + == (BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP + & BGP_VNC_CONFIG_FLAGS_DEFAULT) + ? "(default)" + : "")); + /* export */ + vty_out(vty, "%-39s ", "Export from VNC:"); + /* + * route export to other protocols + */ + if (VNC_EXPORT_BGP_GRP_ENABLED(hc)) { + redist++; + vty_out(vty, "ToBGP Groups={"); + if (hc->rfg_export_direct_bgp_l) { + int cnt = 0; + struct listnode *node, *nnode; + struct rfapi_rfg_name *rfgn; + for (ALL_LIST_ELEMENTS(hc->rfg_export_direct_bgp_l, + node, nnode, rfgn)) { + if (cnt++ != 0) + vty_out(vty, ","); + + vty_out(vty, "%s", rfgn->name); + } + } + vty_out(vty, "}"); + } else if (VNC_EXPORT_BGP_RH_ENABLED(hc)) { + redist++; + vty_out(vty, "ToBGP {Registering NVE}"); + /* note filters, route-maps not shown */ + } else if (VNC_EXPORT_BGP_CE_ENABLED(hc)) { + redist++; + vty_out(vty, "ToBGP {NVE connected router:%d}", + hc->resolve_nve_roo_local_admin); + /* note filters, route-maps not shown */ + } + + if (VNC_EXPORT_ZEBRA_GRP_ENABLED(hc)) { + redist++; + vty_out(vty, "%sToZebra Groups={", (redist == 1 ? "" : " ")); + if (hc->rfg_export_direct_bgp_l) { + int cnt = 0; + struct listnode *node, *nnode; + struct rfapi_rfg_name *rfgn; + for (ALL_LIST_ELEMENTS(hc->rfg_export_zebra_l, node, + nnode, rfgn)) { + if (cnt++ != 0) + vty_out(vty, ","); + vty_out(vty, "%s", rfgn->name); + } + } + vty_out(vty, "}"); + } else if (VNC_EXPORT_ZEBRA_RH_ENABLED(hc)) { + redist++; + vty_out(vty, "%sToZebra {Registering NVE}", + (redist == 1 ? "" : " ")); + /* note filters, route-maps not shown */ + } + vty_out(vty, "%-19s %s\n", (redist ? "" : "Off"), + (redist ? "" : "(default)")); + + /* Redistribution */ + redist = 0; + vty_out(vty, "%-39s ", "Redistribution into VNC:"); + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + for (type = 0; type < ZEBRA_ROUTE_MAX; ++type) { + if (hc->redist[afi][type]) { + vty_out(vty, "{%s,%s} ", + ((afi == AFI_IP) ? "ipv4" : "ipv6"), + zebra_route_string(type)); + redist++; + } + } + } + vty_out(vty, "%-19s %s\n", (redist ? "" : "Off"), + (redist ? "" : "(default)")); + + vty_out(vty, "%-39s %3u%-16s %s\n", + "RFP Registration Hold-Down Factor:", + hc->rfp_cfg.holddown_factor, "%", + (hc->rfp_cfg.holddown_factor + == RFAPI_RFP_CFG_DEFAULT_HOLDDOWN_FACTOR + ? "(default)" + : "")); + vty_out(vty, "%-39s %-19s %s\n", "RFP Updated responses:", + (hc->rfp_cfg.use_updated_response == 0 ? "Off" : "On"), + (hc->rfp_cfg.use_updated_response == 0 ? "(default)" : "")); + vty_out(vty, "%-39s %-19s %s\n", "RFP Removal responses:", + (hc->rfp_cfg.use_removes == 0 ? "Off" : "On"), + (hc->rfp_cfg.use_removes == 0 ? "(default)" : "")); + vty_out(vty, "%-39s %-19s %s\n", "RFP Full table download:", + (hc->rfp_cfg.download_type == RFAPI_RFP_DOWNLOAD_FULL ? "On" + : "Off"), + (hc->rfp_cfg.download_type == RFAPI_RFP_DOWNLOAD_PARTIAL + ? "(default)" + : "")); + sprintf(tmp, "%u seconds", hc->rfp_cfg.ftd_advertisement_interval); + vty_out(vty, "%-39s %-19s %s\n", " Advertisement Interval:", tmp, + (hc->rfp_cfg.ftd_advertisement_interval + == RFAPI_RFP_CFG_DEFAULT_FTD_ADVERTISEMENT_INTERVAL + ? "(default)" + : "")); + vty_out(vty, "%-39s %d seconds\n", "Default RFP response lifetime:", + hc->default_response_lifetime); + vty_out(vty, "\n"); + return; } -struct rfapi_cfg * -bgp_rfapi_get_config (struct bgp *bgp) +struct rfapi_cfg *bgp_rfapi_get_config(struct bgp *bgp) { - struct rfapi_cfg *hc = NULL; - if (bgp == NULL) - bgp = bgp_get_default (); - if (bgp != NULL) - hc = bgp->rfapi_cfg; - return hc; + struct rfapi_cfg *hc = NULL; + if (bgp == NULL) + bgp = bgp_get_default(); + if (bgp != NULL) + hc = bgp->rfapi_cfg; + return hc; } #endif /* ENABLE_BGP_VNC */ diff --git a/bgpd/rfapi/bgp_rfapi_cfg.h b/bgpd/rfapi/bgp_rfapi_cfg.h index 44abbe222..d99aefa60 100644 --- a/bgpd/rfapi/bgp_rfapi_cfg.h +++ b/bgpd/rfapi/bgp_rfapi_cfg.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -27,200 +27,195 @@ #if ENABLE_BGP_VNC #include "rfapi.h" -struct rfapi_l2_group_cfg -{ - char *name; - uint32_t logical_net_id; - struct list *labels; /* list of uint32_t */ - struct ecommunity *rt_import_list; - struct ecommunity *rt_export_list; - void *rfp_cfg; /* rfp owned group config */ +struct rfapi_l2_group_cfg { + char *name; + uint32_t logical_net_id; + struct list *labels; /* list of uint32_t */ + struct ecommunity *rt_import_list; + struct ecommunity *rt_export_list; + void *rfp_cfg; /* rfp owned group config */ - QOBJ_FIELDS + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(rfapi_l2_group_cfg) -typedef enum -{ - RFAPI_GROUP_CFG_NVE = 1, - RFAPI_GROUP_CFG_VRF, - RFAPI_GROUP_CFG_L2, - RFAPI_GROUP_CFG_MAX +typedef enum { + RFAPI_GROUP_CFG_NVE = 1, + RFAPI_GROUP_CFG_VRF, + RFAPI_GROUP_CFG_L2, + RFAPI_GROUP_CFG_MAX } rfapi_group_cfg_type_t; -struct rfapi_nve_group_cfg -{ - struct route_node *vn_node; /* backref */ - struct route_node *un_node; /* backref */ +struct rfapi_nve_group_cfg { + struct route_node *vn_node; /* backref */ + struct route_node *un_node; /* backref */ - rfapi_group_cfg_type_t type; /* NVE|VPN */ - char *name; /* unique by type! */ - struct prefix vn_prefix; - struct prefix un_prefix; + rfapi_group_cfg_type_t type; /* NVE|VPN */ + char *name; /* unique by type! */ + struct prefix vn_prefix; + struct prefix un_prefix; - struct prefix_rd rd; - uint8_t l2rd; /* 0 = VN addr LSB */ - uint32_t response_lifetime; - uint32_t flags; + struct prefix_rd rd; + uint8_t l2rd; /* 0 = VN addr LSB */ + uint32_t response_lifetime; + uint32_t flags; #define RFAPI_RFG_RESPONSE_LIFETIME 0x01 /* bits */ #define RFAPI_RFG_L2RD 0x02 #define RFAPI_RFG_VPN_NH_SELF 0x04 - struct ecommunity *rt_import_list; - struct ecommunity *rt_export_list; - struct rfapi_import_table *rfapi_import_table; - - void *rfp_cfg; /* rfp owned group config */ - /* - * List of NVE descriptors that are assigned to this NVE group - * - * Currently (Mar 2010) this list is used only by the route - * export code to generate per-NVE nexthops for each route. - * - * The nve descriptors listed here have pointers back to - * this nve group config structure to enable them to delete - * their own list entries when they are closed. Consequently, - * if an instance of this nve group config structure is deleted, - * we must first set the nve descriptor references to it to NULL. - */ - struct list *nves; - - /* - * Route filtering - * - * Prefix lists are segregated by afi (part of the base plist code) - * Route-maps are not segregated - */ - char *plist_export_bgp_name[AFI_MAX]; - struct prefix_list *plist_export_bgp[AFI_MAX]; - - char *plist_export_zebra_name[AFI_MAX]; - struct prefix_list *plist_export_zebra[AFI_MAX]; - - char *plist_redist_name[ZEBRA_ROUTE_MAX][AFI_MAX]; - struct prefix_list *plist_redist[ZEBRA_ROUTE_MAX][AFI_MAX]; - - char *routemap_export_bgp_name; - struct route_map *routemap_export_bgp; - - char *routemap_export_zebra_name; - struct route_map *routemap_export_zebra; - - char *routemap_redist_name[ZEBRA_ROUTE_MAX]; - struct route_map *routemap_redist[ZEBRA_ROUTE_MAX]; - - /* for VRF type groups */ - uint32_t label; - struct rfapi_descriptor *rfd; - QOBJ_FIELDS + struct ecommunity *rt_import_list; + struct ecommunity *rt_export_list; + struct rfapi_import_table *rfapi_import_table; + + void *rfp_cfg; /* rfp owned group config */ + /* + * List of NVE descriptors that are assigned to this NVE group + * + * Currently (Mar 2010) this list is used only by the route + * export code to generate per-NVE nexthops for each route. + * + * The nve descriptors listed here have pointers back to + * this nve group config structure to enable them to delete + * their own list entries when they are closed. Consequently, + * if an instance of this nve group config structure is deleted, + * we must first set the nve descriptor references to it to NULL. + */ + struct list *nves; + + /* + * Route filtering + * + * Prefix lists are segregated by afi (part of the base plist code) + * Route-maps are not segregated + */ + char *plist_export_bgp_name[AFI_MAX]; + struct prefix_list *plist_export_bgp[AFI_MAX]; + + char *plist_export_zebra_name[AFI_MAX]; + struct prefix_list *plist_export_zebra[AFI_MAX]; + + char *plist_redist_name[ZEBRA_ROUTE_MAX][AFI_MAX]; + struct prefix_list *plist_redist[ZEBRA_ROUTE_MAX][AFI_MAX]; + + char *routemap_export_bgp_name; + struct route_map *routemap_export_bgp; + + char *routemap_export_zebra_name; + struct route_map *routemap_export_zebra; + + char *routemap_redist_name[ZEBRA_ROUTE_MAX]; + struct route_map *routemap_redist[ZEBRA_ROUTE_MAX]; + + /* for VRF type groups */ + uint32_t label; + struct rfapi_descriptor *rfd; + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(rfapi_nve_group_cfg) -struct rfapi_rfg_name -{ - struct rfapi_nve_group_cfg *rfg; - char *name; +struct rfapi_rfg_name { + struct rfapi_nve_group_cfg *rfg; + char *name; }; -typedef enum -{ - VNC_REDIST_MODE_PLAIN = 0, /* 0 = default */ - VNC_REDIST_MODE_RFG, - VNC_REDIST_MODE_RESOLVE_NVE +typedef enum { + VNC_REDIST_MODE_PLAIN = 0, /* 0 = default */ + VNC_REDIST_MODE_RFG, + VNC_REDIST_MODE_RESOLVE_NVE } vnc_redist_mode_t; -struct rfapi_cfg -{ - struct prefix_rd default_rd; - uint8_t default_l2rd; - struct ecommunity *default_rt_import_list; - struct ecommunity *default_rt_export_list; - uint32_t default_response_lifetime; +struct rfapi_cfg { + struct prefix_rd default_rd; + uint8_t default_l2rd; + struct ecommunity *default_rt_import_list; + struct ecommunity *default_rt_export_list; + uint32_t default_response_lifetime; #define BGP_VNC_DEFAULT_RESPONSE_LIFETIME_DEFAULT 3600 - void *default_rfp_cfg; /* rfp owned group config */ - - struct list *l2_groups; /* rfapi_l2_group_cfg list */ - /* three views into the same collection of rfapi_nve_group_cfg */ - struct list *nve_groups_sequential; - struct route_table nve_groups_vn[AFI_MAX]; - struct route_table nve_groups_un[AFI_MAX]; - - /* - * For Single VRF export to ordinary routing protocols. This is - * the nve-group that the ordinary protocols belong to. We use it - * to set the RD when sending unicast Zebra routes to VNC - */ - uint8_t redist[AFI_MAX][ZEBRA_ROUTE_MAX]; - uint32_t redist_lifetime; - vnc_redist_mode_t redist_mode; - - /* - * view name of BGP unicast instance that holds - * exterior routes - */ - char *redist_bgp_exterior_view_name; - struct bgp *redist_bgp_exterior_view; - - /* - * nve group for redistribution of routes from zebra to VNC - * (which is probably not useful for production networks) - */ - char *rfg_redist_name; - struct rfapi_nve_group_cfg *rfg_redist; - - /* - * List of NVE groups on whose behalf we will export VNC - * routes to zebra. ((NB: it's actually a list of ) - * This list is used when BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS is - * BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP - */ - struct list *rfg_export_zebra_l; - - /* - * List of NVE groups on whose behalf we will export VNC - * routes directly to the bgp unicast RIB. (NB: it's actually - * a list of ) - * This list is used when BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS is - * BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP - */ - struct list *rfg_export_direct_bgp_l; - - /* - * Exported Route filtering - * - * Prefix lists are segregated by afi (part of the base plist code) - * Route-maps are not segregated - */ - char *plist_export_bgp_name[AFI_MAX]; - struct prefix_list *plist_export_bgp[AFI_MAX]; - - char *plist_export_zebra_name[AFI_MAX]; - struct prefix_list *plist_export_zebra[AFI_MAX]; - - char *routemap_export_bgp_name; - struct route_map *routemap_export_bgp; - - char *routemap_export_zebra_name; - struct route_map *routemap_export_zebra; - - /* - * Redistributed route filtering (routes from other - * protocols into VNC) - */ - char *plist_redist_name[ZEBRA_ROUTE_MAX][AFI_MAX]; - struct prefix_list *plist_redist[ZEBRA_ROUTE_MAX][AFI_MAX]; - - char *routemap_redist_name[ZEBRA_ROUTE_MAX]; - struct route_map *routemap_redist[ZEBRA_ROUTE_MAX]; - - /* - * For importing bgp unicast routes to VNC, we encode the CE - * (route nexthop) in a Route Origin extended community. The - * local part (16-bit) is user-configurable. - */ - uint16_t resolve_nve_roo_local_admin; + void *default_rfp_cfg; /* rfp owned group config */ + + struct list *l2_groups; /* rfapi_l2_group_cfg list */ + /* three views into the same collection of rfapi_nve_group_cfg */ + struct list *nve_groups_sequential; + struct route_table nve_groups_vn[AFI_MAX]; + struct route_table nve_groups_un[AFI_MAX]; + + /* + * For Single VRF export to ordinary routing protocols. This is + * the nve-group that the ordinary protocols belong to. We use it + * to set the RD when sending unicast Zebra routes to VNC + */ + uint8_t redist[AFI_MAX][ZEBRA_ROUTE_MAX]; + uint32_t redist_lifetime; + vnc_redist_mode_t redist_mode; + + /* + * view name of BGP unicast instance that holds + * exterior routes + */ + char *redist_bgp_exterior_view_name; + struct bgp *redist_bgp_exterior_view; + + /* + * nve group for redistribution of routes from zebra to VNC + * (which is probably not useful for production networks) + */ + char *rfg_redist_name; + struct rfapi_nve_group_cfg *rfg_redist; + + /* + * List of NVE groups on whose behalf we will export VNC + * routes to zebra. ((NB: it's actually a list of ) + * This list is used when BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS is + * BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP + */ + struct list *rfg_export_zebra_l; + + /* + * List of NVE groups on whose behalf we will export VNC + * routes directly to the bgp unicast RIB. (NB: it's actually + * a list of ) + * This list is used when BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS is + * BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP + */ + struct list *rfg_export_direct_bgp_l; + + /* + * Exported Route filtering + * + * Prefix lists are segregated by afi (part of the base plist code) + * Route-maps are not segregated + */ + char *plist_export_bgp_name[AFI_MAX]; + struct prefix_list *plist_export_bgp[AFI_MAX]; + + char *plist_export_zebra_name[AFI_MAX]; + struct prefix_list *plist_export_zebra[AFI_MAX]; + + char *routemap_export_bgp_name; + struct route_map *routemap_export_bgp; + + char *routemap_export_zebra_name; + struct route_map *routemap_export_zebra; + + /* + * Redistributed route filtering (routes from other + * protocols into VNC) + */ + char *plist_redist_name[ZEBRA_ROUTE_MAX][AFI_MAX]; + struct prefix_list *plist_redist[ZEBRA_ROUTE_MAX][AFI_MAX]; + + char *routemap_redist_name[ZEBRA_ROUTE_MAX]; + struct route_map *routemap_redist[ZEBRA_ROUTE_MAX]; + + /* + * For importing bgp unicast routes to VNC, we encode the CE + * (route nexthop) in a Route Origin extended community. The + * local part (16-bit) is user-configurable. + */ + uint16_t resolve_nve_roo_local_admin; #define BGP_VNC_CONFIG_RESOLVE_NVE_ROO_LOCAL_ADMIN_DEFAULT 5226 - uint32_t flags; + uint32_t flags; #define BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP 0x00000001 #define BGP_VNC_CONFIG_CALLBACK_DISABLE 0x00000002 #define BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE 0x00000004 @@ -244,98 +239,76 @@ struct rfapi_cfg /* Filter querying NVE's registrations from responses */ /* Default to updated-responses off */ /* Default to removal-responses off */ -#define BGP_VNC_CONFIG_FLAGS_DEFAULT \ - (BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP |\ - BGP_VNC_CONFIG_CALLBACK_DISABLE |\ - BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE) +#define BGP_VNC_CONFIG_FLAGS_DEFAULT \ + (BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP | BGP_VNC_CONFIG_CALLBACK_DISABLE \ + | BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE) - struct rfapi_rfp_cfg rfp_cfg; /* rfp related configuration */ + struct rfapi_rfp_cfg rfp_cfg; /* rfp related configuration */ }; -#define VNC_EXPORT_ZEBRA_GRP_ENABLED(hc) \ - (((hc)->flags & BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS) == \ - BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP) +#define VNC_EXPORT_ZEBRA_GRP_ENABLED(hc) \ + (((hc)->flags & BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS) \ + == BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_GRP) -#define VNC_EXPORT_ZEBRA_RH_ENABLED(hc) \ - (((hc)->flags & BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS) == \ - BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_RH) +#define VNC_EXPORT_ZEBRA_RH_ENABLED(hc) \ + (((hc)->flags & BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_BITS) \ + == BGP_VNC_CONFIG_EXPORT_ZEBRA_MODE_RH) -#define VNC_EXPORT_BGP_GRP_ENABLED(hc) \ - (((hc)->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) == \ - BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP) +#define VNC_EXPORT_BGP_GRP_ENABLED(hc) \ + (((hc)->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) \ + == BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP) -#define VNC_EXPORT_BGP_RH_ENABLED(hc) \ - (((hc)->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) == \ - BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH) +#define VNC_EXPORT_BGP_RH_ENABLED(hc) \ + (((hc)->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) \ + == BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH) -#define VNC_EXPORT_BGP_CE_ENABLED(hc) \ - (((hc)->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) == \ - BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE) +#define VNC_EXPORT_BGP_CE_ENABLED(hc) \ + (((hc)->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) \ + == BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE) -void -bgp_rfapi_cfg_init (void); +void bgp_rfapi_cfg_init(void); -struct rfapi_cfg * -bgp_rfapi_cfg_new (struct rfapi_rfp_cfg *cfg); +struct rfapi_cfg *bgp_rfapi_cfg_new(struct rfapi_rfp_cfg *cfg); -void -bgp_rfapi_cfg_destroy (struct bgp *bgp, struct rfapi_cfg *h); +void bgp_rfapi_cfg_destroy(struct bgp *bgp, struct rfapi_cfg *h); -int -bgp_rfapi_cfg_write (struct vty *vty, struct bgp *bgp); +int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp); -extern int -bgp_rfapi_is_vnc_configured (struct bgp *bgp); +extern int bgp_rfapi_is_vnc_configured(struct bgp *bgp); -extern void -nve_group_to_nve_list ( - struct rfapi_nve_group_cfg *rfg, - struct list **nves, - uint8_t family); /* AF_INET, AF_INET6 */ +extern void nve_group_to_nve_list(struct rfapi_nve_group_cfg *rfg, + struct list **nves, + uint8_t family); /* AF_INET, AF_INET6 */ -struct rfapi_nve_group_cfg * -bgp_rfapi_cfg_match_group ( - struct rfapi_cfg *hc, - struct prefix *vn, - struct prefix *un); +struct rfapi_nve_group_cfg *bgp_rfapi_cfg_match_group(struct rfapi_cfg *hc, + struct prefix *vn, + struct prefix *un); struct rfapi_nve_group_cfg * -bgp_rfapi_cfg_match_byname ( - struct bgp *bgp, - const char *name, - rfapi_group_cfg_type_t type); /* _MAX = any */ +bgp_rfapi_cfg_match_byname(struct bgp *bgp, const char *name, + rfapi_group_cfg_type_t type); /* _MAX = any */ -extern void -vnc_prefix_list_update (struct bgp *bgp); +extern void vnc_prefix_list_update(struct bgp *bgp); -extern void -vnc_routemap_update (struct bgp *bgp, const char *unused); +extern void vnc_routemap_update(struct bgp *bgp, const char *unused); -extern void -bgp_rfapi_show_summary (struct bgp *bgp, struct vty *vty); +extern void bgp_rfapi_show_summary(struct bgp *bgp, struct vty *vty); -extern struct rfapi_cfg * -bgp_rfapi_get_config (struct bgp *bgp); +extern struct rfapi_cfg *bgp_rfapi_get_config(struct bgp *bgp); extern struct rfapi_l2_group_cfg * -bgp_rfapi_get_group_by_lni_label ( - struct bgp *bgp, - uint32_t logical_net_id, - uint32_t label); +bgp_rfapi_get_group_by_lni_label(struct bgp *bgp, uint32_t logical_net_id, + uint32_t label); extern struct ecommunity * -bgp_rfapi_get_ecommunity_by_lni_label ( - struct bgp *bgp, - uint32_t is_import, - uint32_t logical_net_id, - uint32_t label); /* note, 20bit label! */ +bgp_rfapi_get_ecommunity_by_lni_label(struct bgp *bgp, uint32_t is_import, + uint32_t logical_net_id, + uint32_t label); /* note, 20bit label! */ extern struct list * -bgp_rfapi_get_labellist_by_lni_label ( - struct bgp *bgp, - uint32_t logical_net_id, - uint32_t label); /* note, 20bit label! */ +bgp_rfapi_get_labellist_by_lni_label(struct bgp *bgp, uint32_t logical_net_id, + uint32_t label); /* note, 20bit label! */ #endif /* ENABLE_BGP_VNC */ diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c index a959b9827..3a2a608a7 100644 --- a/bgpd/rfapi/rfapi.c +++ b/bgpd/rfapi/rfapi.c @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -65,38 +65,36 @@ #include #endif /* HAVE_GLIBC_BACKTRACE */ -struct ethaddr rfapi_ethaddr0 = { {0} }; +struct ethaddr rfapi_ethaddr0 = {{0}}; #define DEBUG_RFAPI_STR "RF API debugging/testing command\n" -const char * -rfapi_error_str (int code) +const char *rfapi_error_str(int code) { - switch (code) - { - case 0: - return "Success"; - case ENXIO: - return "BGP or VNC not configured"; - case ENOENT: - return "No match"; - case EEXIST: - return "Handle already open"; - case ENOMSG: - return "Incomplete configuration"; - case EAFNOSUPPORT: - return "Invalid address family"; - case EDEADLK: - return "Called from within a callback procedure"; - case EBADF: - return "Invalid handle"; - case EINVAL: - return "Invalid argument"; - case ESTALE: - return "Stale descriptor"; - default: - return "Unknown error"; - } + switch (code) { + case 0: + return "Success"; + case ENXIO: + return "BGP or VNC not configured"; + case ENOENT: + return "No match"; + case EEXIST: + return "Handle already open"; + case ENOMSG: + return "Incomplete configuration"; + case EAFNOSUPPORT: + return "Invalid address family"; + case EDEADLK: + return "Called from within a callback procedure"; + case EBADF: + return "Invalid handle"; + case EINVAL: + return "Invalid argument"; + case ESTALE: + return "Stale descriptor"; + default: + return "Unknown error"; + } } /*------------------------------------------ @@ -106,20 +104,19 @@ rfapi_error_str (int code) * rfp_start_val value returned by rfp_start or * NULL (=use default instance) * - * input: + * input: * None * * output: * * return value: The bgp instance default lifetime for a response. --------------------------------------------*/ -int -rfapi_get_response_lifetime_default (void *rfp_start_val) +int rfapi_get_response_lifetime_default(void *rfp_start_val) { - struct bgp *bgp = rfapi_bgp_lookup_by_rfp (rfp_start_val); - if (bgp) - return bgp->rfapi_cfg->default_response_lifetime; - return BGP_VNC_DEFAULT_RESPONSE_LIFETIME_DEFAULT; + struct bgp *bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val); + if (bgp) + return bgp->rfapi_cfg->default_response_lifetime; + return BGP_VNC_DEFAULT_RESPONSE_LIFETIME_DEFAULT; } /*------------------------------------------ @@ -127,7 +124,7 @@ rfapi_get_response_lifetime_default (void *rfp_start_val) * * Returns if VNC (BGP VPN messaging /VPN & encap SAFIs) are configured * - * input: + * input: * rfp_start_val value returned by rfp_start or * NULL (=use default instance) * @@ -137,11 +134,10 @@ rfapi_get_response_lifetime_default (void *rfp_start_val) * 0 Success * ENXIO VNC not configured --------------------------------------------*/ -int -rfapi_is_vnc_configured (void *rfp_start_val) +int rfapi_is_vnc_configured(void *rfp_start_val) { - struct bgp *bgp = rfapi_bgp_lookup_by_rfp (rfp_start_val); - return bgp_rfapi_is_vnc_configured (bgp); + struct bgp *bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val); + return bgp_rfapi_is_vnc_configured(bgp); } @@ -150,19 +146,18 @@ rfapi_is_vnc_configured (void *rfp_start_val) * * Get the virtual network address used by an NVE based on it's RFD * - * input: + * input: * rfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic * * output: * - * return value: + * return value: * vn NVE virtual network address *------------------------------------------*/ -struct rfapi_ip_addr * -rfapi_get_vn_addr (void *rfd) +struct rfapi_ip_addr *rfapi_get_vn_addr(void *rfd) { - struct rfapi_descriptor *rrfd = (struct rfapi_descriptor *) rfd; - return &rrfd->vn_addr; + struct rfapi_descriptor *rrfd = (struct rfapi_descriptor *)rfd; + return &rrfd->vn_addr; } /*------------------------------------------ @@ -170,505 +165,459 @@ rfapi_get_vn_addr (void *rfd) * * Get the underlay network address used by an NVE based on it's RFD * - * input: + * input: * rfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic * * output: * - * return value: + * return value: * un NVE underlay network address *------------------------------------------*/ -struct rfapi_ip_addr * -rfapi_get_un_addr (void *rfd) +struct rfapi_ip_addr *rfapi_get_un_addr(void *rfd) { - struct rfapi_descriptor *rrfd = (struct rfapi_descriptor *) rfd; - return &rrfd->un_addr; + struct rfapi_descriptor *rrfd = (struct rfapi_descriptor *)rfd; + return &rrfd->un_addr; } -int -rfapi_ip_addr_cmp (struct rfapi_ip_addr *a1, struct rfapi_ip_addr *a2) +int rfapi_ip_addr_cmp(struct rfapi_ip_addr *a1, struct rfapi_ip_addr *a2) { - if (a1->addr_family != a2->addr_family) - return a1->addr_family - a2->addr_family; + if (a1->addr_family != a2->addr_family) + return a1->addr_family - a2->addr_family; - if (a1->addr_family == AF_INET) - { - return IPV4_ADDR_CMP (&a1->addr.v4, &a2->addr.v4); - } + if (a1->addr_family == AF_INET) { + return IPV4_ADDR_CMP(&a1->addr.v4, &a2->addr.v4); + } - if (a1->addr_family == AF_INET6) - { - return IPV6_ADDR_CMP (&a1->addr.v6, &a2->addr.v6); - } + if (a1->addr_family == AF_INET6) { + return IPV6_ADDR_CMP(&a1->addr.v6, &a2->addr.v6); + } - assert (1); - /* NOTREACHED */ - return 1; + assert(1); + /* NOTREACHED */ + return 1; } -static int -rfapi_find_node ( - struct bgp *bgp, - struct rfapi_ip_addr *vn_addr, - struct rfapi_ip_addr *un_addr, - struct route_node **node) +static int rfapi_find_node(struct bgp *bgp, struct rfapi_ip_addr *vn_addr, + struct rfapi_ip_addr *un_addr, + struct route_node **node) { - struct rfapi *h; - struct prefix p; - struct route_node *rn; - int rc; - int afi; + struct rfapi *h; + struct prefix p; + struct route_node *rn; + int rc; + int afi; - if (!bgp) - { - return ENXIO; - } + if (!bgp) { + return ENXIO; + } - h = bgp->rfapi; - if (!h) - { - return ENXIO; - } + h = bgp->rfapi; + if (!h) { + return ENXIO; + } - afi = family2afi (un_addr->addr_family); - if (!afi) - { - return EAFNOSUPPORT; - } + afi = family2afi(un_addr->addr_family); + if (!afi) { + return EAFNOSUPPORT; + } - if ((rc = rfapiRaddr2Qprefix (un_addr, &p))) - return rc; + if ((rc = rfapiRaddr2Qprefix(un_addr, &p))) + return rc; - rn = route_node_lookup (&h->un[afi], &p); + rn = route_node_lookup(&h->un[afi], &p); - if (!rn) - return ENOENT; + if (!rn) + return ENOENT; - route_unlock_node (rn); + route_unlock_node(rn); - *node = rn; + *node = rn; - return 0; + return 0; } -int -rfapi_find_rfd ( - struct bgp *bgp, - struct rfapi_ip_addr *vn_addr, - struct rfapi_ip_addr *un_addr, - struct rfapi_descriptor **rfd) +int rfapi_find_rfd(struct bgp *bgp, struct rfapi_ip_addr *vn_addr, + struct rfapi_ip_addr *un_addr, struct rfapi_descriptor **rfd) { - struct route_node *rn; - int rc; + struct route_node *rn; + int rc; - rc = rfapi_find_node (bgp, vn_addr, un_addr, &rn); + rc = rfapi_find_node(bgp, vn_addr, un_addr, &rn); - if (rc) - return rc; + if (rc) + return rc; - for (*rfd = (struct rfapi_descriptor *) (rn->info); *rfd; - *rfd = (*rfd)->next) - { - if (!rfapi_ip_addr_cmp (&(*rfd)->vn_addr, vn_addr)) - break; - } + for (*rfd = (struct rfapi_descriptor *)(rn->info); *rfd; + *rfd = (*rfd)->next) { + if (!rfapi_ip_addr_cmp(&(*rfd)->vn_addr, vn_addr)) + break; + } - if (!*rfd) - return ENOENT; + if (!*rfd) + return ENOENT; - return 0; + return 0; } /*------------------------------------------ * rfapi_find_handle * - * input: + * input: * un underlay network address * vn virtual network address * * output: * pHandle pointer to location to store handle * - * return value: + * return value: * 0 Success * ENOENT no matching handle * ENXIO BGP or VNC not configured *------------------------------------------*/ -static int -rfapi_find_handle ( - struct bgp *bgp, - struct rfapi_ip_addr *vn_addr, - struct rfapi_ip_addr *un_addr, - rfapi_handle *handle) +static int rfapi_find_handle(struct bgp *bgp, struct rfapi_ip_addr *vn_addr, + struct rfapi_ip_addr *un_addr, + rfapi_handle *handle) { - struct rfapi_descriptor **rfd; + struct rfapi_descriptor **rfd; - rfd = (struct rfapi_descriptor **) handle; + rfd = (struct rfapi_descriptor **)handle; - return rfapi_find_rfd (bgp, vn_addr, un_addr, rfd); + return rfapi_find_rfd(bgp, vn_addr, un_addr, rfd); } -static int -rfapi_find_handle_vty ( - struct vty *vty, - struct rfapi_ip_addr *vn_addr, - struct rfapi_ip_addr *un_addr, - rfapi_handle *handle) +static int rfapi_find_handle_vty(struct vty *vty, struct rfapi_ip_addr *vn_addr, + struct rfapi_ip_addr *un_addr, + rfapi_handle *handle) { - struct bgp *bgp; - struct rfapi_descriptor **rfd; + struct bgp *bgp; + struct rfapi_descriptor **rfd; - bgp = bgp_get_default (); /* assume 1 instance for now */ + bgp = bgp_get_default(); /* assume 1 instance for now */ - rfd = (struct rfapi_descriptor **) handle; + rfd = (struct rfapi_descriptor **)handle; - return rfapi_find_rfd (bgp, vn_addr, un_addr, rfd); + return rfapi_find_rfd(bgp, vn_addr, un_addr, rfd); } -static int -is_valid_rfd (struct rfapi_descriptor *rfd) +static int is_valid_rfd(struct rfapi_descriptor *rfd) { - rfapi_handle hh; + rfapi_handle hh; - if (!rfd || rfd->bgp == NULL) - return 0; + if (!rfd || rfd->bgp == NULL) + return 0; - if (CHECK_FLAG(rfd->flags, RFAPI_HD_FLAG_IS_VRF)) /* assume VRF/internal are valid */ - return 1; + if (CHECK_FLAG( + rfd->flags, + RFAPI_HD_FLAG_IS_VRF)) /* assume VRF/internal are valid */ + return 1; - if (rfapi_find_handle (rfd->bgp, &rfd->vn_addr, &rfd->un_addr, &hh)) - return 0; + if (rfapi_find_handle(rfd->bgp, &rfd->vn_addr, &rfd->un_addr, &hh)) + return 0; - if (rfd != hh) - return 0; + if (rfd != hh) + return 0; - return 1; + return 1; } /* * check status of descriptor */ -int -rfapi_check (void *handle) +int rfapi_check(void *handle) { - struct rfapi_descriptor *rfd = (struct rfapi_descriptor *) handle; - rfapi_handle hh; - int rc; + struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle; + rfapi_handle hh; + int rc; - if (!rfd || rfd->bgp == NULL) - return EINVAL; + if (!rfd || rfd->bgp == NULL) + return EINVAL; - if (CHECK_FLAG(rfd->flags, RFAPI_HD_FLAG_IS_VRF)) /* assume VRF/internal are valid */ - return 0; + if (CHECK_FLAG( + rfd->flags, + RFAPI_HD_FLAG_IS_VRF)) /* assume VRF/internal are valid */ + return 0; - if ((rc = rfapi_find_handle (rfd->bgp, &rfd->vn_addr, &rfd->un_addr, &hh))) - return rc; + if ((rc = rfapi_find_handle(rfd->bgp, &rfd->vn_addr, &rfd->un_addr, + &hh))) + return rc; - if (rfd != hh) - return ENOENT; + if (rfd != hh) + return ENOENT; - if (!rfd->rfg) - return ESTALE; + if (!rfd->rfg) + return ESTALE; - return 0; + return 0; } - -void -del_vnc_route ( - struct rfapi_descriptor *rfd, - struct peer *peer, /* rfd->peer for RFP regs */ - struct bgp *bgp, - safi_t safi, - struct prefix *p, - struct prefix_rd *prd, - uint8_t type, - uint8_t sub_type, - struct rfapi_nexthop *lnh, - int kill) +void del_vnc_route(struct rfapi_descriptor *rfd, + struct peer *peer, /* rfd->peer for RFP regs */ + struct bgp *bgp, safi_t safi, struct prefix *p, + struct prefix_rd *prd, uint8_t type, uint8_t sub_type, + struct rfapi_nexthop *lnh, int kill) { - afi_t afi; /* of the VN address */ - struct bgp_node *bn; - struct bgp_info *bi; - char buf[BUFSIZ]; - char buf2[BUFSIZ]; - struct prefix_rd prd0; - - prefix2str (p, buf, BUFSIZ); - buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */ - - prefix_rd2str (prd, buf2, BUFSIZ); - buf2[BUFSIZ - 1] = 0; - - afi = family2afi (p->family); - assert (afi == AFI_IP || afi == AFI_IP6); - - if (safi == SAFI_ENCAP) - { - memset (&prd0, 0, sizeof (prd0)); - prd0.family = AF_UNSPEC; - prd0.prefixlen = 64; - prd = &prd0; - } - bn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd); - - vnc_zlog_debug_verbose - ("%s: peer=%p, prefix=%s, prd=%s afi=%d, safi=%d bn=%p, bn->info=%p", - __func__, peer, buf, buf2, afi, safi, bn, (bn ? bn->info : NULL)); - - for (bi = (bn ? bn->info : NULL); bi; bi = bi->next) - { - - vnc_zlog_debug_verbose - ("%s: trying bi=%p, bi->peer=%p, bi->type=%d, bi->sub_type=%d, bi->extra->vnc.export.rfapi_handle=%p, local_pref=%u", - __func__, bi, bi->peer, bi->type, bi->sub_type, - (bi->extra ? bi->extra->vnc.export.rfapi_handle : NULL), - ((bi->attr && CHECK_FLAG(bi->attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))? bi->attr->local_pref: 0)); - - if (bi->peer == peer && - bi->type == type && - bi->sub_type == sub_type && - bi->extra && bi->extra->vnc.export.rfapi_handle == (void *) rfd) - { - - vnc_zlog_debug_verbose ("%s: matched it", __func__); - - break; - } - } - - if (lnh) - { - /* - * lnh set means to JUST delete the local nexthop from this - * route. Leave the route itself in place. - * TBD add return code reporting of success/failure - */ - if (!bi || !bi->extra || !bi->extra->vnc.export.local_nexthops) - { - /* - * no local nexthops - */ - vnc_zlog_debug_verbose ("%s: lnh list already empty at prefix %s", - __func__, buf); - goto done; - } - - /* - * look for it - */ - struct listnode *node; - struct rfapi_nexthop *pLnh = NULL; - - for (ALL_LIST_ELEMENTS_RO (bi->extra->vnc.export.local_nexthops, - node, pLnh)) - { - - if (prefix_same (&pLnh->addr, &lnh->addr)) - { - break; - } - } - - if (pLnh) - { - listnode_delete (bi->extra->vnc.export.local_nexthops, pLnh); - - /* silly rabbit, listnode_delete doesn't invoke list->del on data */ - rfapi_nexthop_free (pLnh); - } - else - { - vnc_zlog_debug_verbose ("%s: desired lnh not found %s", __func__, buf); - } - goto done; - } - - /* - * loop back to import tables - * Do this before removing from BGP RIB because rfapiProcessWithdraw - * might refer to it - */ - rfapiProcessWithdraw (peer, rfd, p, prd, NULL, afi, safi, type, kill); - - if (bi) - { - char buf[BUFSIZ]; - - prefix2str (p, buf, BUFSIZ); - buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */ - - vnc_zlog_debug_verbose ("%s: Found route (safi=%d) to delete at prefix %s", - __func__, safi, buf); - - if (safi == SAFI_MPLS_VPN) - { - struct bgp_node *prn = NULL; - struct bgp_table *table = NULL; - - prn = bgp_node_get (bgp->rib[afi][safi], (struct prefix *) prd); - if (prn->info) - { - table = (struct bgp_table *) (prn->info); - - vnc_import_bgp_del_vnc_host_route_mode_resolve_nve (bgp, - prd, - table, - p, bi); - } - bgp_unlock_node (prn); - } - - /* - * Delete local_nexthops list - */ - if (bi->extra && bi->extra->vnc.export.local_nexthops) - { - list_delete (bi->extra->vnc.export.local_nexthops); - } - - bgp_aggregate_decrement (bgp, p, bi, afi, safi); - bgp_info_delete (bn, bi); - bgp_process (bgp, bn, afi, safi); - } - else - { - vnc_zlog_debug_verbose ("%s: Couldn't find route (safi=%d) at prefix %s", - __func__, safi, buf); - } + afi_t afi; /* of the VN address */ + struct bgp_node *bn; + struct bgp_info *bi; + char buf[BUFSIZ]; + char buf2[BUFSIZ]; + struct prefix_rd prd0; + + prefix2str(p, buf, BUFSIZ); + buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */ + + prefix_rd2str(prd, buf2, BUFSIZ); + buf2[BUFSIZ - 1] = 0; + + afi = family2afi(p->family); + assert(afi == AFI_IP || afi == AFI_IP6); + + if (safi == SAFI_ENCAP) { + memset(&prd0, 0, sizeof(prd0)); + prd0.family = AF_UNSPEC; + prd0.prefixlen = 64; + prd = &prd0; + } + bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd); + + vnc_zlog_debug_verbose( + "%s: peer=%p, prefix=%s, prd=%s afi=%d, safi=%d bn=%p, bn->info=%p", + __func__, peer, buf, buf2, afi, safi, bn, + (bn ? bn->info : NULL)); + + for (bi = (bn ? bn->info : NULL); bi; bi = bi->next) { + + vnc_zlog_debug_verbose( + "%s: trying bi=%p, bi->peer=%p, bi->type=%d, bi->sub_type=%d, bi->extra->vnc.export.rfapi_handle=%p, local_pref=%u", + __func__, bi, bi->peer, bi->type, bi->sub_type, + (bi->extra ? bi->extra->vnc.export.rfapi_handle : NULL), + ((bi->attr + && CHECK_FLAG(bi->attr->flag, + ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) + ? bi->attr->local_pref + : 0)); + + if (bi->peer == peer && bi->type == type + && bi->sub_type == sub_type && bi->extra + && bi->extra->vnc.export.rfapi_handle == (void *)rfd) { + + vnc_zlog_debug_verbose("%s: matched it", __func__); + + break; + } + } + + if (lnh) { + /* + * lnh set means to JUST delete the local nexthop from this + * route. Leave the route itself in place. + * TBD add return code reporting of success/failure + */ + if (!bi || !bi->extra + || !bi->extra->vnc.export.local_nexthops) { + /* + * no local nexthops + */ + vnc_zlog_debug_verbose( + "%s: lnh list already empty at prefix %s", + __func__, buf); + goto done; + } + + /* + * look for it + */ + struct listnode *node; + struct rfapi_nexthop *pLnh = NULL; + + for (ALL_LIST_ELEMENTS_RO(bi->extra->vnc.export.local_nexthops, + node, pLnh)) { + + if (prefix_same(&pLnh->addr, &lnh->addr)) { + break; + } + } + + if (pLnh) { + listnode_delete(bi->extra->vnc.export.local_nexthops, + pLnh); + + /* silly rabbit, listnode_delete doesn't invoke + * list->del on data */ + rfapi_nexthop_free(pLnh); + } else { + vnc_zlog_debug_verbose("%s: desired lnh not found %s", + __func__, buf); + } + goto done; + } + + /* + * loop back to import tables + * Do this before removing from BGP RIB because rfapiProcessWithdraw + * might refer to it + */ + rfapiProcessWithdraw(peer, rfd, p, prd, NULL, afi, safi, type, kill); + + if (bi) { + char buf[BUFSIZ]; + + prefix2str(p, buf, BUFSIZ); + buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */ + + vnc_zlog_debug_verbose( + "%s: Found route (safi=%d) to delete at prefix %s", + __func__, safi, buf); + + if (safi == SAFI_MPLS_VPN) { + struct bgp_node *prn = NULL; + struct bgp_table *table = NULL; + + prn = bgp_node_get(bgp->rib[afi][safi], + (struct prefix *)prd); + if (prn->info) { + table = (struct bgp_table *)(prn->info); + + vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( + bgp, prd, table, p, bi); + } + bgp_unlock_node(prn); + } + + /* + * Delete local_nexthops list + */ + if (bi->extra && bi->extra->vnc.export.local_nexthops) { + list_delete(bi->extra->vnc.export.local_nexthops); + } + + bgp_aggregate_decrement(bgp, p, bi, afi, safi); + bgp_info_delete(bn, bi); + bgp_process(bgp, bn, afi, safi); + } else { + vnc_zlog_debug_verbose( + "%s: Couldn't find route (safi=%d) at prefix %s", + __func__, safi, buf); + } done: - bgp_unlock_node (bn); + bgp_unlock_node(bn); } -struct rfapi_nexthop * -rfapi_nexthop_new (struct rfapi_nexthop *copyme) +struct rfapi_nexthop *rfapi_nexthop_new(struct rfapi_nexthop *copyme) { - struct rfapi_nexthop *new = - XCALLOC (MTYPE_RFAPI_NEXTHOP, sizeof (struct rfapi_nexthop)); - if (copyme) - *new = *copyme; - return new; + struct rfapi_nexthop *new = + XCALLOC(MTYPE_RFAPI_NEXTHOP, sizeof(struct rfapi_nexthop)); + if (copyme) + *new = *copyme; + return new; } -void -rfapi_nexthop_free (void *p) +void rfapi_nexthop_free(void *p) { - struct rfapi_nexthop *goner = p; - XFREE (MTYPE_RFAPI_NEXTHOP, goner); + struct rfapi_nexthop *goner = p; + XFREE(MTYPE_RFAPI_NEXTHOP, goner); } -struct rfapi_vn_option * -rfapi_vn_options_dup (struct rfapi_vn_option *existing) +struct rfapi_vn_option *rfapi_vn_options_dup(struct rfapi_vn_option *existing) { - struct rfapi_vn_option *p; - struct rfapi_vn_option *head = NULL; - struct rfapi_vn_option *tail = NULL; - - for (p = existing; p; p = p->next) - { - struct rfapi_vn_option *new; - - new = XCALLOC (MTYPE_RFAPI_VN_OPTION, sizeof (struct rfapi_vn_option)); - *new = *p; - new->next = NULL; - if (tail) - (tail)->next = new; - tail = new; - if (!head) - { - head = new; - } - } - return head; + struct rfapi_vn_option *p; + struct rfapi_vn_option *head = NULL; + struct rfapi_vn_option *tail = NULL; + + for (p = existing; p; p = p->next) { + struct rfapi_vn_option *new; + + new = XCALLOC(MTYPE_RFAPI_VN_OPTION, + sizeof(struct rfapi_vn_option)); + *new = *p; + new->next = NULL; + if (tail) + (tail)->next = new; + tail = new; + if (!head) { + head = new; + } + } + return head; } -void -rfapi_un_options_free (struct rfapi_un_option *p) +void rfapi_un_options_free(struct rfapi_un_option *p) { - struct rfapi_un_option *next; + struct rfapi_un_option *next; - while (p) - { - next = p->next; - XFREE (MTYPE_RFAPI_UN_OPTION, p); - p = next; - } + while (p) { + next = p->next; + XFREE(MTYPE_RFAPI_UN_OPTION, p); + p = next; + } } -void -rfapi_vn_options_free (struct rfapi_vn_option *p) +void rfapi_vn_options_free(struct rfapi_vn_option *p) { - struct rfapi_vn_option *next; + struct rfapi_vn_option *next; - while (p) - { - next = p->next; - XFREE (MTYPE_RFAPI_VN_OPTION, p); - p = next; - } + while (p) { + next = p->next; + XFREE(MTYPE_RFAPI_VN_OPTION, p); + p = next; + } } /* Based on bgp_redistribute_add() */ -void -add_vnc_route ( - struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ - struct bgp *bgp, - int safi, - struct prefix *p, - struct prefix_rd *prd, - struct rfapi_ip_addr *nexthop, - uint32_t *local_pref, - uint32_t *lifetime, /* NULL => dont send lifetime */ - struct bgp_tea_options *rfp_options, - struct rfapi_un_option *options_un, - struct rfapi_vn_option *options_vn, - struct ecommunity *rt_export_list,/* Copied, not consumed */ - uint32_t *med, /* NULL => don't set med */ - uint32_t *label, /* low order 3 bytes */ - uint8_t type, - uint8_t sub_type, /* RFP, NORMAL or REDIST */ - int flags) +void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ + struct bgp *bgp, int safi, struct prefix *p, + struct prefix_rd *prd, struct rfapi_ip_addr *nexthop, + uint32_t *local_pref, + uint32_t *lifetime, /* NULL => dont send lifetime */ + struct bgp_tea_options *rfp_options, + struct rfapi_un_option *options_un, + struct rfapi_vn_option *options_vn, + struct ecommunity *rt_export_list, /* Copied, not consumed */ + uint32_t *med, /* NULL => don't set med */ + uint32_t *label, /* low order 3 bytes */ + uint8_t type, uint8_t sub_type, /* RFP, NORMAL or REDIST */ + int flags) { - afi_t afi; /* of the VN address */ - struct bgp_info *new; - struct bgp_info *bi; - struct bgp_node *bn; - - struct attr attr = { 0 }; - struct attr *new_attr; - uint32_t label_val; - - struct bgp_attr_encap_subtlv *encaptlv; - char buf[BUFSIZ]; - char buf2[BUFSIZ]; -#if 0 /* unused? */ + afi_t afi; /* of the VN address */ + struct bgp_info *new; + struct bgp_info *bi; + struct bgp_node *bn; + + struct attr attr = {0}; + struct attr *new_attr; + uint32_t label_val; + + struct bgp_attr_encap_subtlv *encaptlv; + char buf[BUFSIZ]; + char buf2[BUFSIZ]; +#if 0 /* unused? */ struct prefix pfx_buf; #endif - struct rfapi_nexthop *lnh = NULL; /* local nexthop */ - struct rfapi_vn_option *vo; - struct rfapi_l2address_option *l2o = NULL; - struct rfapi_ip_addr *un_addr = &rfd->un_addr; + struct rfapi_nexthop *lnh = NULL; /* local nexthop */ + struct rfapi_vn_option *vo; + struct rfapi_l2address_option *l2o = NULL; + struct rfapi_ip_addr *un_addr = &rfd->un_addr; - bgp_encap_types TunnelType = BGP_ENCAP_TYPE_RESERVED; - struct bgp_redist *red; + bgp_encap_types TunnelType = BGP_ENCAP_TYPE_RESERVED; + struct bgp_redist *red; - if (safi == SAFI_ENCAP && - !(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP)) - { + if (safi == SAFI_ENCAP + && !(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP)) { - /* - * Encap mode not enabled. UN addresses will be communicated - * via VNC Tunnel subtlv instead. - */ - vnc_zlog_debug_verbose ("%s: encap mode not enabled, not adding SAFI_ENCAP route", - __func__); - return; - } + /* + * Encap mode not enabled. UN addresses will be communicated + * via VNC Tunnel subtlv instead. + */ + vnc_zlog_debug_verbose( + "%s: encap mode not enabled, not adding SAFI_ENCAP route", + __func__); + return; + } -#if 0 /* unused? */ +#if 0 /* unused? */ if ((safi == SAFI_MPLS_VPN) && (flags & RFAPI_AHR_SET_PFX_TO_NEXTHOP)) { @@ -682,579 +631,542 @@ add_vnc_route ( p = &pfx_buf; } #endif - for (vo = options_vn; vo; vo = vo->next) - { - if (RFAPI_VN_OPTION_TYPE_L2ADDR == vo->type) - { - l2o = &vo->v.l2addr; - if (RFAPI_0_ETHERADDR (&l2o->macaddr)) - l2o = NULL; /* not MAC resolution */ - } - if (RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP == vo->type) - { - lnh = &vo->v.local_nexthop; - } - } - - if (label) - label_val = *label; - else - label_val = MPLS_LABEL_IMPLICIT_NULL; - - prefix_rd2str (prd, buf2, BUFSIZ); - buf2[BUFSIZ - 1] = 0; - - - afi = family2afi (p->family); - assert (afi == AFI_IP || afi == AFI_IP6); - - vnc_zlog_debug_verbose ("%s: afi=%s, safi=%s", __func__, afi2str (afi), - safi2str (safi)); - - /* Make default attribute. Produces already-interned attr.aspath */ - /* Cripes, the memory management of attributes is byzantine */ - - bgp_attr_default_set (&attr, BGP_ORIGIN_INCOMPLETE); - - /* - * At this point: - * attr: static - * extra: dynamically allocated, owned by attr - * aspath: points to interned hash from aspath hash table - */ - - - /* - * Route-specific un_options get added to the VPN SAFI - * advertisement tunnel encap attribute. (the per-NVE - * "default" un_options are put into the 1-per-NVE ENCAP - * SAFI advertisement). The VPN SAFI also gets the - * default un_options if there are no route-specific options. - */ - if (options_un) - { - struct rfapi_un_option *uo; - - for (uo = options_un; uo; uo = uo->next) - { - if (RFAPI_UN_OPTION_TYPE_TUNNELTYPE == uo->type) - { - TunnelType = rfapi_tunneltype_option_to_tlv ( - bgp, un_addr, &uo->v.tunnel, &attr, l2o != NULL); - } - } - } - else - { - /* - * Add encap attr - * These are the NVE-specific "default" un_options which are - * put into the 1-per-NVE ENCAP advertisement. - */ - if (rfd->default_tunneltype_option.type) - { - TunnelType = rfapi_tunneltype_option_to_tlv ( - bgp, un_addr, &rfd->default_tunneltype_option, &attr, - l2o != NULL); - } - else /* create default for local addse */ - if (type == ZEBRA_ROUTE_BGP && sub_type == BGP_ROUTE_RFP) - TunnelType = - rfapi_tunneltype_option_to_tlv (bgp, un_addr, NULL, - &attr, l2o != NULL); - } - - if (TunnelType == BGP_ENCAP_TYPE_MPLS) - { - if (safi == SAFI_ENCAP) - { - /* Encap SAFI not used with MPLS */ - vnc_zlog_debug_verbose ("%s: mpls tunnel type, encap safi omitted", __func__); - aspath_unintern (&attr.aspath); /* Unintern original. */ - return; - } - } - - if (local_pref) - { - attr.local_pref = *local_pref; - attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF); - } - - if (med) - { - attr.med = *med; - attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); - } - - /* override default weight assigned by bgp_attr_default_set() */ - attr.weight = rfd->peer ? rfd->peer->weight[afi][safi] : 0; - - /* - * NB: ticket 81: do not reset attr.aspath here because it would - * cause iBGP peers to drop route - */ - - /* - * Set originator ID for routes imported from BGP directly. - * These routes could be synthetic, and therefore could - * reuse the peer pointers of the routes they are derived - * from. Setting the originator ID to "us" prevents the - * wrong originator ID from being sent when this route is - * sent from a route reflector. - */ - if (type == ZEBRA_ROUTE_BGP_DIRECT || type == ZEBRA_ROUTE_BGP_DIRECT_EXT) - { - attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID); - attr.originator_id = bgp->router_id; - } - - - /* Set up vnc attribute (sub-tlv for Prefix Lifetime) */ - if (lifetime && *lifetime != RFAPI_INFINITE_LIFETIME) - { - uint32_t lt; - - encaptlv = - XCALLOC (MTYPE_ENCAP_TLV, - sizeof (struct bgp_attr_encap_subtlv) - 1 + 4); - assert (encaptlv); - encaptlv->type = BGP_VNC_SUBTLV_TYPE_LIFETIME; /* prefix lifetime */ - encaptlv->length = 4; - lt = htonl (*lifetime); - memcpy (encaptlv->value, <, 4); - attr.vnc_subtlvs = encaptlv; - vnc_zlog_debug_verbose ("%s: set Encap Attr Prefix Lifetime to %d", - __func__, *lifetime); - } - - /* add rfp options to vnc attr */ - if (rfp_options) - { - - if (flags & RFAPI_AHR_RFPOPT_IS_VNCTLV) - { - - /* - * this flag means we're passing a pointer to an - * existing encap tlv chain which we should copy. - * It's a hack to avoid adding yet another argument - * to add_vnc_route() - */ - encaptlv = - encap_tlv_dup ((struct bgp_attr_encap_subtlv *) rfp_options); - if (attr.vnc_subtlvs) - { - attr.vnc_subtlvs->next = encaptlv; - } - else - { - attr.vnc_subtlvs = encaptlv; - } - - } - else - { - struct bgp_tea_options *hop; - /* XXX max of one tlv present so far from above code */ - struct bgp_attr_encap_subtlv *tail = attr.vnc_subtlvs; - - for (hop = rfp_options; hop; hop = hop->next) - { - - /* - * Construct subtlv - */ - encaptlv = XCALLOC (MTYPE_ENCAP_TLV, - sizeof (struct bgp_attr_encap_subtlv) - 1 + - 2 + hop->length); - assert (encaptlv); - encaptlv->type = BGP_VNC_SUBTLV_TYPE_RFPOPTION; /* RFP option */ - encaptlv->length = 2 + hop->length; - *((uint8_t *) (encaptlv->value) + 0) = hop->type; - *((uint8_t *) (encaptlv->value) + 1) = hop->length; - memcpy (((uint8_t *) encaptlv->value) + 2, hop->value, - hop->length); - - /* - * add to end of subtlv chain - */ - if (tail) - { - tail->next = encaptlv; - } - else - { - attr.vnc_subtlvs = encaptlv; - } - tail = encaptlv; - } - } - } - - /* - * At this point: - * attr: static - * extra: dynamically allocated, owned by attr - * vnc_subtlvs: dynamic chain, length 1 - * aspath: points to interned hash from aspath hash table - */ - - - attr.ecommunity = ecommunity_new (); - assert (attr.ecommunity); - - if (TunnelType != BGP_ENCAP_TYPE_MPLS && - TunnelType != BGP_ENCAP_TYPE_RESERVED) - { - /* - * Add BGP Encapsulation Extended Community. Format described in - * section 4.5 of RFC 5512. - * Always include when not MPLS type, to disambiguate this case. - */ - struct ecommunity_val beec; - - memset (&beec, 0, sizeof (beec)); - beec.val[0] = ECOMMUNITY_ENCODE_OPAQUE; - beec.val[1] = ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP; - beec.val[6] = ((TunnelType) >> 8) & 0xff; - beec.val[7] = (TunnelType) & 0xff; - ecommunity_add_val (attr.ecommunity, &beec); - } - - /* - * Add extended community attributes to match rt export list - */ - if (rt_export_list) - { - attr.ecommunity = - ecommunity_merge (attr.ecommunity, rt_export_list); - } - - if (attr.ecommunity->size) - { - attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES); - } - else - { - ecommunity_free (&attr.ecommunity); - attr.ecommunity = NULL; - } - vnc_zlog_debug_verbose ("%s: attr.ecommunity=%p", __func__, - attr.ecommunity); - - - /* - * At this point: - * attr: static - * extra: dynamically allocated, owned by attr - * vnc_subtlvs: dynamic chain, length 1 - * ecommunity: dynamic 2-part - * aspath: points to interned hash from aspath hash table - */ - - /* stuff nexthop in attr_extra; which field depends on IPv4 or IPv6 */ - switch (nexthop->addr_family) - { - case AF_INET: - /* - * set this field to prevent bgp_route.c code from setting - * mp_nexthop_global_in to self - */ - attr.nexthop.s_addr = nexthop->addr.v4.s_addr; - - attr.mp_nexthop_global_in = nexthop->addr.v4; - attr.mp_nexthop_len = 4; - break; - - case AF_INET6: - attr.mp_nexthop_global = nexthop->addr.v6; - attr.mp_nexthop_len = 16; - break; - - default: - assert (0); - } - - - prefix2str (p, buf, BUFSIZ); - buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */ - - /* - * At this point: - * - * attr: static - * extra: dynamically allocated, owned by attr - * vnc_subtlvs: dynamic chain, length 1 - * ecommunity: dynamic 2-part - * aspath: points to interned hash from aspath hash table - */ - - red = bgp_redist_lookup(bgp, afi, type, VRF_DEFAULT); - - if (red && red->redist_metric_flag) - { - attr.med = red->redist_metric; - attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); - } - - bn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd); - - /* - * bgp_attr_intern creates a new reference to a cached - * attribute, but leaves the following bits of trash: - * - old attr - * - old attr->extra (free via bgp_attr_extra_free(attr)) - * - * Note that it frees the original attr->extra->ecommunity - * but leaves the new attribute pointing to the ORIGINAL - * vnc options (which therefore we needn't free from the - * static attr) - */ - new_attr = bgp_attr_intern (&attr); - - aspath_unintern (&attr.aspath); /* Unintern original. */ - - /* - * At this point: - * - * attr: static - * extra: dynamically allocated, owned by attr - * vnc_subtlvs: dynamic chain, length 1 - * ecommunity: POINTS TO INTERNED ecom, THIS REF NOT COUNTED - * - * new_attr: an attr that is part of the hash table, distinct - * from attr which is static. - * extra: dynamically allocated, owned by new_attr (in hash table) - * vnc_subtlvs: POINTS TO SAME dynamic chain AS attr - * ecommunity: POINTS TO interned/refcounted dynamic 2-part AS attr - * aspath: POINTS TO interned/refcounted hashed block - */ - for (bi = bn->info; bi; bi = bi->next) - { - /* probably only need to check bi->extra->vnc.export.rfapi_handle */ - if (bi->peer == rfd->peer && - bi->type == type && - bi->sub_type == sub_type && - bi->extra && bi->extra->vnc.export.rfapi_handle == (void *) rfd) - { - - break; - } - } - - if (bi) - { - - /* - * Adding new local_nexthop, which does not by itself change - * what is advertised via BGP - */ - if (lnh) - { - if (!bi->extra->vnc.export.local_nexthops) - { - /* TBD make arrangements to free when needed */ - bi->extra->vnc.export.local_nexthops = list_new (); - bi->extra->vnc.export.local_nexthops->del = rfapi_nexthop_free; - } - - /* - * already present? - */ - struct listnode *node; - struct rfapi_nexthop *pLnh = NULL; - - for (ALL_LIST_ELEMENTS_RO (bi->extra->vnc.export.local_nexthops, - node, pLnh)) - { - - if (prefix_same (&pLnh->addr, &lnh->addr)) - { - break; - } - } - - /* - * Not present, add new one - */ - if (!pLnh) - { - pLnh = rfapi_nexthop_new (lnh); - listnode_add (bi->extra->vnc.export.local_nexthops, pLnh); - } - } - - if (attrhash_cmp (bi->attr, new_attr) && - !CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)) - { - bgp_attr_unintern (&new_attr); - bgp_unlock_node (bn); - - vnc_zlog_debug_any ("%s: Found route (safi=%d) at prefix %s, no change", - __func__, safi, buf); - - goto done; - } - else - { - /* The attribute is changed. */ - bgp_info_set_flag (bn, bi, BGP_INFO_ATTR_CHANGED); - - if (safi == SAFI_MPLS_VPN) - { - struct bgp_node *prn = NULL; - struct bgp_table *table = NULL; - - prn = bgp_node_get (bgp->rib[afi][safi], (struct prefix *) prd); - if (prn->info) - { - table = (struct bgp_table *) (prn->info); - - vnc_import_bgp_del_vnc_host_route_mode_resolve_nve ( - bgp, prd, table, p, bi); - } - bgp_unlock_node (prn); - } - - /* Rewrite BGP route information. */ - if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)) - bgp_info_restore (bn, bi); - else - bgp_aggregate_decrement (bgp, p, bi, afi, safi); - bgp_attr_unintern (&bi->attr); - bi->attr = new_attr; - bi->uptime = bgp_clock (); - - - if (safi == SAFI_MPLS_VPN) - { - struct bgp_node *prn = NULL; - struct bgp_table *table = NULL; - - prn = bgp_node_get (bgp->rib[afi][safi], (struct prefix *) prd); - if (prn->info) - { - table = (struct bgp_table *) (prn->info); - - vnc_import_bgp_add_vnc_host_route_mode_resolve_nve ( - bgp, prd, table, p, bi); - } - bgp_unlock_node (prn); - } - - /* Process change. */ - bgp_aggregate_increment (bgp, p, bi, afi, safi); - bgp_process (bgp, bn, afi, safi); - bgp_unlock_node (bn); - - vnc_zlog_debug_any ("%s: Found route (safi=%d) at prefix %s, changed attr", - __func__, safi, buf); - - goto done; - } - } - - - new = bgp_info_new (); - new->type = type; - new->sub_type = sub_type; - new->peer = rfd->peer; - SET_FLAG (new->flags, BGP_INFO_VALID); - new->attr = new_attr; - new->uptime = bgp_clock (); - - /* save backref to rfapi handle */ - assert (bgp_info_extra_get (new)); - new->extra->vnc.export.rfapi_handle = (void *) rfd; - encode_label (label_val, &new->extra->label); - - /* debug */ - - if (VNC_DEBUG(VERBOSE)) - { - vnc_zlog_debug_verbose ("%s: printing BI", __func__); - rfapiPrintBi (NULL, new); - } - - bgp_aggregate_increment (bgp, p, new, afi, safi); - bgp_info_add (bn, new); - - if (safi == SAFI_MPLS_VPN) - { - struct bgp_node *prn = NULL; - struct bgp_table *table = NULL; - - prn = bgp_node_get (bgp->rib[afi][safi], (struct prefix *) prd); - if (prn->info) - { - table = (struct bgp_table *) (prn->info); - - vnc_import_bgp_add_vnc_host_route_mode_resolve_nve ( - bgp, prd, table, p, new); - } - bgp_unlock_node (prn); - encode_label (label_val, &bn->local_label); - } - - bgp_unlock_node (bn); - bgp_process (bgp, bn, afi, safi); - - vnc_zlog_debug_any ("%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%s)", - __func__, safi2str (safi), buf, bn, buf2); + for (vo = options_vn; vo; vo = vo->next) { + if (RFAPI_VN_OPTION_TYPE_L2ADDR == vo->type) { + l2o = &vo->v.l2addr; + if (RFAPI_0_ETHERADDR(&l2o->macaddr)) + l2o = NULL; /* not MAC resolution */ + } + if (RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP == vo->type) { + lnh = &vo->v.local_nexthop; + } + } + + if (label) + label_val = *label; + else + label_val = MPLS_LABEL_IMPLICIT_NULL; + + prefix_rd2str(prd, buf2, BUFSIZ); + buf2[BUFSIZ - 1] = 0; + + + afi = family2afi(p->family); + assert(afi == AFI_IP || afi == AFI_IP6); + + vnc_zlog_debug_verbose("%s: afi=%s, safi=%s", __func__, afi2str(afi), + safi2str(safi)); + + /* Make default attribute. Produces already-interned attr.aspath */ + /* Cripes, the memory management of attributes is byzantine */ + + bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE); + + /* + * At this point: + * attr: static + * extra: dynamically allocated, owned by attr + * aspath: points to interned hash from aspath hash table + */ + + + /* + * Route-specific un_options get added to the VPN SAFI + * advertisement tunnel encap attribute. (the per-NVE + * "default" un_options are put into the 1-per-NVE ENCAP + * SAFI advertisement). The VPN SAFI also gets the + * default un_options if there are no route-specific options. + */ + if (options_un) { + struct rfapi_un_option *uo; + + for (uo = options_un; uo; uo = uo->next) { + if (RFAPI_UN_OPTION_TYPE_TUNNELTYPE == uo->type) { + TunnelType = rfapi_tunneltype_option_to_tlv( + bgp, un_addr, &uo->v.tunnel, &attr, + l2o != NULL); + } + } + } else { + /* + * Add encap attr + * These are the NVE-specific "default" un_options which are + * put into the 1-per-NVE ENCAP advertisement. + */ + if (rfd->default_tunneltype_option.type) { + TunnelType = rfapi_tunneltype_option_to_tlv( + bgp, un_addr, &rfd->default_tunneltype_option, + &attr, l2o != NULL); + } else /* create default for local addse */ + if (type == ZEBRA_ROUTE_BGP + && sub_type == BGP_ROUTE_RFP) + TunnelType = rfapi_tunneltype_option_to_tlv( + bgp, un_addr, NULL, &attr, l2o != NULL); + } + + if (TunnelType == BGP_ENCAP_TYPE_MPLS) { + if (safi == SAFI_ENCAP) { + /* Encap SAFI not used with MPLS */ + vnc_zlog_debug_verbose( + "%s: mpls tunnel type, encap safi omitted", + __func__); + aspath_unintern(&attr.aspath); /* Unintern original. */ + return; + } + } + + if (local_pref) { + attr.local_pref = *local_pref; + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF); + } + + if (med) { + attr.med = *med; + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); + } + + /* override default weight assigned by bgp_attr_default_set() */ + attr.weight = rfd->peer ? rfd->peer->weight[afi][safi] : 0; + + /* + * NB: ticket 81: do not reset attr.aspath here because it would + * cause iBGP peers to drop route + */ + + /* + * Set originator ID for routes imported from BGP directly. + * These routes could be synthetic, and therefore could + * reuse the peer pointers of the routes they are derived + * from. Setting the originator ID to "us" prevents the + * wrong originator ID from being sent when this route is + * sent from a route reflector. + */ + if (type == ZEBRA_ROUTE_BGP_DIRECT + || type == ZEBRA_ROUTE_BGP_DIRECT_EXT) { + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID); + attr.originator_id = bgp->router_id; + } + + + /* Set up vnc attribute (sub-tlv for Prefix Lifetime) */ + if (lifetime && *lifetime != RFAPI_INFINITE_LIFETIME) { + uint32_t lt; + + encaptlv = + XCALLOC(MTYPE_ENCAP_TLV, + sizeof(struct bgp_attr_encap_subtlv) - 1 + 4); + assert(encaptlv); + encaptlv->type = + BGP_VNC_SUBTLV_TYPE_LIFETIME; /* prefix lifetime */ + encaptlv->length = 4; + lt = htonl(*lifetime); + memcpy(encaptlv->value, <, 4); + attr.vnc_subtlvs = encaptlv; + vnc_zlog_debug_verbose( + "%s: set Encap Attr Prefix Lifetime to %d", __func__, + *lifetime); + } + + /* add rfp options to vnc attr */ + if (rfp_options) { + + if (flags & RFAPI_AHR_RFPOPT_IS_VNCTLV) { + + /* + * this flag means we're passing a pointer to an + * existing encap tlv chain which we should copy. + * It's a hack to avoid adding yet another argument + * to add_vnc_route() + */ + encaptlv = encap_tlv_dup( + (struct bgp_attr_encap_subtlv *)rfp_options); + if (attr.vnc_subtlvs) { + attr.vnc_subtlvs->next = encaptlv; + } else { + attr.vnc_subtlvs = encaptlv; + } + + } else { + struct bgp_tea_options *hop; + /* XXX max of one tlv present so far from above code */ + struct bgp_attr_encap_subtlv *tail = attr.vnc_subtlvs; + + for (hop = rfp_options; hop; hop = hop->next) { + + /* + * Construct subtlv + */ + encaptlv = XCALLOC( + MTYPE_ENCAP_TLV, + sizeof(struct bgp_attr_encap_subtlv) - 1 + + 2 + hop->length); + assert(encaptlv); + encaptlv->type = + BGP_VNC_SUBTLV_TYPE_RFPOPTION; /* RFP + option + */ + encaptlv->length = 2 + hop->length; + *((uint8_t *)(encaptlv->value) + 0) = hop->type; + *((uint8_t *)(encaptlv->value) + 1) = + hop->length; + memcpy(((uint8_t *)encaptlv->value) + 2, + hop->value, hop->length); + + /* + * add to end of subtlv chain + */ + if (tail) { + tail->next = encaptlv; + } else { + attr.vnc_subtlvs = encaptlv; + } + tail = encaptlv; + } + } + } + + /* + * At this point: + * attr: static + * extra: dynamically allocated, owned by attr + * vnc_subtlvs: dynamic chain, length 1 + * aspath: points to interned hash from aspath hash table + */ + + + attr.ecommunity = ecommunity_new(); + assert(attr.ecommunity); + + if (TunnelType != BGP_ENCAP_TYPE_MPLS + && TunnelType != BGP_ENCAP_TYPE_RESERVED) { + /* + * Add BGP Encapsulation Extended Community. Format described in + * section 4.5 of RFC 5512. + * Always include when not MPLS type, to disambiguate this case. + */ + struct ecommunity_val beec; + + memset(&beec, 0, sizeof(beec)); + beec.val[0] = ECOMMUNITY_ENCODE_OPAQUE; + beec.val[1] = ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP; + beec.val[6] = ((TunnelType) >> 8) & 0xff; + beec.val[7] = (TunnelType)&0xff; + ecommunity_add_val(attr.ecommunity, &beec); + } + + /* + * Add extended community attributes to match rt export list + */ + if (rt_export_list) { + attr.ecommunity = + ecommunity_merge(attr.ecommunity, rt_export_list); + } + + if (attr.ecommunity->size) { + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES); + } else { + ecommunity_free(&attr.ecommunity); + attr.ecommunity = NULL; + } + vnc_zlog_debug_verbose("%s: attr.ecommunity=%p", __func__, + attr.ecommunity); + + + /* + * At this point: + * attr: static + * extra: dynamically allocated, owned by attr + * vnc_subtlvs: dynamic chain, length 1 + * ecommunity: dynamic 2-part + * aspath: points to interned hash from aspath hash table + */ + + /* stuff nexthop in attr_extra; which field depends on IPv4 or IPv6 */ + switch (nexthop->addr_family) { + case AF_INET: + /* + * set this field to prevent bgp_route.c code from setting + * mp_nexthop_global_in to self + */ + attr.nexthop.s_addr = nexthop->addr.v4.s_addr; + + attr.mp_nexthop_global_in = nexthop->addr.v4; + attr.mp_nexthop_len = 4; + break; + + case AF_INET6: + attr.mp_nexthop_global = nexthop->addr.v6; + attr.mp_nexthop_len = 16; + break; + + default: + assert(0); + } + + + prefix2str(p, buf, BUFSIZ); + buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */ + + /* + * At this point: + * + * attr: static + * extra: dynamically allocated, owned by attr + * vnc_subtlvs: dynamic chain, length 1 + * ecommunity: dynamic 2-part + * aspath: points to interned hash from aspath hash table + */ + + red = bgp_redist_lookup(bgp, afi, type, VRF_DEFAULT); + + if (red && red->redist_metric_flag) { + attr.med = red->redist_metric; + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); + } + + bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd); + + /* + * bgp_attr_intern creates a new reference to a cached + * attribute, but leaves the following bits of trash: + * - old attr + * - old attr->extra (free via bgp_attr_extra_free(attr)) + * + * Note that it frees the original attr->extra->ecommunity + * but leaves the new attribute pointing to the ORIGINAL + * vnc options (which therefore we needn't free from the + * static attr) + */ + new_attr = bgp_attr_intern(&attr); + + aspath_unintern(&attr.aspath); /* Unintern original. */ + + /* + * At this point: + * + * attr: static + * extra: dynamically allocated, owned by attr + * vnc_subtlvs: dynamic chain, length 1 + * ecommunity: POINTS TO INTERNED ecom, THIS REF NOT COUNTED + * + * new_attr: an attr that is part of the hash table, distinct + * from attr which is static. + * extra: dynamically allocated, owned by new_attr (in hash table) + * vnc_subtlvs: POINTS TO SAME dynamic chain AS attr + * ecommunity: POINTS TO interned/refcounted dynamic 2-part AS attr + * aspath: POINTS TO interned/refcounted hashed block + */ + for (bi = bn->info; bi; bi = bi->next) { + /* probably only need to check + * bi->extra->vnc.export.rfapi_handle */ + if (bi->peer == rfd->peer && bi->type == type + && bi->sub_type == sub_type && bi->extra + && bi->extra->vnc.export.rfapi_handle == (void *)rfd) { + + break; + } + } + + if (bi) { + + /* + * Adding new local_nexthop, which does not by itself change + * what is advertised via BGP + */ + if (lnh) { + if (!bi->extra->vnc.export.local_nexthops) { + /* TBD make arrangements to free when needed */ + bi->extra->vnc.export.local_nexthops = + list_new(); + bi->extra->vnc.export.local_nexthops->del = + rfapi_nexthop_free; + } + + /* + * already present? + */ + struct listnode *node; + struct rfapi_nexthop *pLnh = NULL; + + for (ALL_LIST_ELEMENTS_RO( + bi->extra->vnc.export.local_nexthops, node, + pLnh)) { + + if (prefix_same(&pLnh->addr, &lnh->addr)) { + break; + } + } + + /* + * Not present, add new one + */ + if (!pLnh) { + pLnh = rfapi_nexthop_new(lnh); + listnode_add( + bi->extra->vnc.export.local_nexthops, + pLnh); + } + } + + if (attrhash_cmp(bi->attr, new_attr) + && !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) { + bgp_attr_unintern(&new_attr); + bgp_unlock_node(bn); + + vnc_zlog_debug_any( + "%s: Found route (safi=%d) at prefix %s, no change", + __func__, safi, buf); + + goto done; + } else { + /* The attribute is changed. */ + bgp_info_set_flag(bn, bi, BGP_INFO_ATTR_CHANGED); + + if (safi == SAFI_MPLS_VPN) { + struct bgp_node *prn = NULL; + struct bgp_table *table = NULL; + + prn = bgp_node_get(bgp->rib[afi][safi], + (struct prefix *)prd); + if (prn->info) { + table = (struct bgp_table *)(prn->info); + + vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( + bgp, prd, table, p, bi); + } + bgp_unlock_node(prn); + } + + /* Rewrite BGP route information. */ + if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + bgp_info_restore(bn, bi); + else + bgp_aggregate_decrement(bgp, p, bi, afi, safi); + bgp_attr_unintern(&bi->attr); + bi->attr = new_attr; + bi->uptime = bgp_clock(); + + + if (safi == SAFI_MPLS_VPN) { + struct bgp_node *prn = NULL; + struct bgp_table *table = NULL; + + prn = bgp_node_get(bgp->rib[afi][safi], + (struct prefix *)prd); + if (prn->info) { + table = (struct bgp_table *)(prn->info); + + vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( + bgp, prd, table, p, bi); + } + bgp_unlock_node(prn); + } + + /* Process change. */ + bgp_aggregate_increment(bgp, p, bi, afi, safi); + bgp_process(bgp, bn, afi, safi); + bgp_unlock_node(bn); + + vnc_zlog_debug_any( + "%s: Found route (safi=%d) at prefix %s, changed attr", + __func__, safi, buf); + + goto done; + } + } + + + new = bgp_info_new(); + new->type = type; + new->sub_type = sub_type; + new->peer = rfd->peer; + SET_FLAG(new->flags, BGP_INFO_VALID); + new->attr = new_attr; + new->uptime = bgp_clock(); + + /* save backref to rfapi handle */ + assert(bgp_info_extra_get(new)); + new->extra->vnc.export.rfapi_handle = (void *)rfd; + encode_label(label_val, &new->extra->label); + + /* debug */ + + if (VNC_DEBUG(VERBOSE)) { + vnc_zlog_debug_verbose("%s: printing BI", __func__); + rfapiPrintBi(NULL, new); + } + + bgp_aggregate_increment(bgp, p, new, afi, safi); + bgp_info_add(bn, new); + + if (safi == SAFI_MPLS_VPN) { + struct bgp_node *prn = NULL; + struct bgp_table *table = NULL; + + prn = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd); + if (prn->info) { + table = (struct bgp_table *)(prn->info); + + vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( + bgp, prd, table, p, new); + } + bgp_unlock_node(prn); + encode_label(label_val, &bn->local_label); + } + + bgp_unlock_node(bn); + bgp_process(bgp, bn, afi, safi); + + vnc_zlog_debug_any( + "%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%s)", + __func__, safi2str(safi), buf, bn, buf2); done: - /* Loop back to import tables */ - rfapiProcessUpdate (rfd->peer, - rfd, - p, prd, new_attr, afi, safi, type, sub_type, &label_val); - vnc_zlog_debug_verbose ("%s: looped back import route (safi=%d)", __func__, safi); + /* Loop back to import tables */ + rfapiProcessUpdate(rfd->peer, rfd, p, prd, new_attr, afi, safi, type, + sub_type, &label_val); + vnc_zlog_debug_verbose("%s: looped back import route (safi=%d)", + __func__, safi); } -uint32_t -rfp_cost_to_localpref (uint8_t cost) +uint32_t rfp_cost_to_localpref(uint8_t cost) { - return 255 - cost; + return 255 - cost; } -static void -rfapiTunnelRouteAnnounce ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - uint32_t *pLifetime) +static void rfapiTunnelRouteAnnounce(struct bgp *bgp, + struct rfapi_descriptor *rfd, + uint32_t *pLifetime) { - struct prefix_rd prd; - struct prefix pfx_vn; - int rc; - uint32_t local_pref = rfp_cost_to_localpref (0); - - rc = rfapiRaddr2Qprefix (&(rfd->vn_addr), &pfx_vn); - assert (!rc); - - /* - * Construct route distinguisher = 0 - */ - memset (&prd, 0, sizeof (prd)); - prd.family = AF_UNSPEC; - prd.prefixlen = 64; - - add_vnc_route (rfd, /* rfapi descr, for export list & backref */ - bgp, /* which bgp instance */ - SAFI_ENCAP, /* which SAFI */ - &pfx_vn, /* prefix to advertise */ - &prd, /* route distinguisher to use */ - &rfd->un_addr, /* nexthop */ - &local_pref, - pLifetime, /* max lifetime of child VPN routes */ - NULL, /* no rfp options for ENCAP safi */ - NULL, /* rfp un options */ - NULL, /* rfp vn options */ - rfd->rt_export_list, - NULL, /* med */ - NULL, /* label: default */ - ZEBRA_ROUTE_BGP, - BGP_ROUTE_RFP, - 0); + struct prefix_rd prd; + struct prefix pfx_vn; + int rc; + uint32_t local_pref = rfp_cost_to_localpref(0); + + rc = rfapiRaddr2Qprefix(&(rfd->vn_addr), &pfx_vn); + assert(!rc); + + /* + * Construct route distinguisher = 0 + */ + memset(&prd, 0, sizeof(prd)); + prd.family = AF_UNSPEC; + prd.prefixlen = 64; + + add_vnc_route(rfd, /* rfapi descr, for export list & backref */ + bgp, /* which bgp instance */ + SAFI_ENCAP, /* which SAFI */ + &pfx_vn, /* prefix to advertise */ + &prd, /* route distinguisher to use */ + &rfd->un_addr, /* nexthop */ + &local_pref, + pLifetime, /* max lifetime of child VPN routes */ + NULL, /* no rfp options for ENCAP safi */ + NULL, /* rfp un options */ + NULL, /* rfp vn options */ + rfd->rt_export_list, NULL, /* med */ + NULL, /* label: default */ + ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, 0); } @@ -1265,88 +1177,84 @@ rfapiTunnelRouteAnnounce ( /*------------------------------------------ * rfapi_rfp_set_configuration * - * This is used to change rfapi's processing behavior based on - * RFP requirements. + * This is used to change rfapi's processing behavior based on + * RFP requirements. * - * input: + * input: * rfp_start_val value returned by rfp_start * rfapi_rfp_cfg Pointer to configuration structure * * output: * none * - * return value: + * return value: * 0 Success * ENXIO Unabled to locate configured BGP/VNC --------------------------------------------*/ -int -rfapi_rfp_set_configuration (void *rfp_start_val, struct rfapi_rfp_cfg *new) +int rfapi_rfp_set_configuration(void *rfp_start_val, struct rfapi_rfp_cfg *new) { - struct rfapi_rfp_cfg *rcfg; - struct bgp *bgp; - - bgp = rfapi_bgp_lookup_by_rfp (rfp_start_val); - - if (!new || !bgp || !bgp->rfapi_cfg) - return ENXIO; - - rcfg = &bgp->rfapi_cfg->rfp_cfg; - rcfg->download_type = new->download_type; - rcfg->ftd_advertisement_interval = new->ftd_advertisement_interval; - rcfg->holddown_factor = new->holddown_factor; - - if (rcfg->use_updated_response != new->use_updated_response) - { - rcfg->use_updated_response = new->use_updated_response; - if (rcfg->use_updated_response) - rfapiMonitorCallbacksOn (bgp); - else - rfapiMonitorCallbacksOff (bgp); - } - if (rcfg->use_removes != new->use_removes) - { - rcfg->use_removes = new->use_removes; - if (rcfg->use_removes) - rfapiMonitorResponseRemovalOn (bgp); - else - rfapiMonitorResponseRemovalOff (bgp); - } - return 0; + struct rfapi_rfp_cfg *rcfg; + struct bgp *bgp; + + bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val); + + if (!new || !bgp || !bgp->rfapi_cfg) + return ENXIO; + + rcfg = &bgp->rfapi_cfg->rfp_cfg; + rcfg->download_type = new->download_type; + rcfg->ftd_advertisement_interval = new->ftd_advertisement_interval; + rcfg->holddown_factor = new->holddown_factor; + + if (rcfg->use_updated_response != new->use_updated_response) { + rcfg->use_updated_response = new->use_updated_response; + if (rcfg->use_updated_response) + rfapiMonitorCallbacksOn(bgp); + else + rfapiMonitorCallbacksOff(bgp); + } + if (rcfg->use_removes != new->use_removes) { + rcfg->use_removes = new->use_removes; + if (rcfg->use_removes) + rfapiMonitorResponseRemovalOn(bgp); + else + rfapiMonitorResponseRemovalOff(bgp); + } + return 0; } /*------------------------------------------ * rfapi_rfp_set_cb_methods * - * Change registered callback functions for asynchronous notifications + * Change registered callback functions for asynchronous notifications * from RFAPI to the RFP client. * - * input: + * input: * rfp_start_val value returned by rfp_start * methods Pointer to struct rfapi_rfp_cb_methods containing * pointers to callback methods as described above * - * return value: + * return value: * 0 Success * ENXIO BGP or VNC not configured *------------------------------------------*/ -int -rfapi_rfp_set_cb_methods (void *rfp_start_val, - struct rfapi_rfp_cb_methods *methods) +int rfapi_rfp_set_cb_methods(void *rfp_start_val, + struct rfapi_rfp_cb_methods *methods) { - struct rfapi *h; - struct bgp *bgp; + struct rfapi *h; + struct bgp *bgp; - bgp = rfapi_bgp_lookup_by_rfp (rfp_start_val); - if (!bgp) - return ENXIO; + bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val); + if (!bgp) + return ENXIO; - h = bgp->rfapi; - if (!h) - return ENXIO; + h = bgp->rfapi; + if (!h) + return ENXIO; - h->rfp_methods = *methods; + h->rfp_methods = *methods; - return 0; + return 0; } /*********************************************************************** @@ -1358,570 +1266,520 @@ rfapi_rfp_set_cb_methods (void *rfp_start_val, * The advertised_prefixes[] array elements should be NULL to * have this function set them to newly-allocated radix trees. */ -static int -rfapi_open_inner ( - struct rfapi_descriptor *rfd, - struct bgp *bgp, - struct rfapi *h, - struct rfapi_nve_group_cfg *rfg) +static int rfapi_open_inner(struct rfapi_descriptor *rfd, struct bgp *bgp, + struct rfapi *h, struct rfapi_nve_group_cfg *rfg) { - int ret; + int ret; + + if (h->flags & RFAPI_INCALLBACK) + return EDEADLK; + + /* + * Fill in configured fields + */ + + /* + * If group's RD is specified as "auto", then fill in based + * on NVE's VN address + */ + rfd->rd = rfg->rd; + + if (rfd->rd.family == AF_UNIX) { + ret = rfapi_set_autord_from_vn(&rfd->rd, &rfd->vn_addr); + if (ret != 0) + return ret; + } + rfd->rt_export_list = (rfg->rt_export_list) + ? ecommunity_dup(rfg->rt_export_list) + : NULL; + rfd->response_lifetime = rfg->response_lifetime; + rfd->rfg = rfg; + + /* + * Fill in BGP peer structure + */ + rfd->peer = peer_new(bgp); + rfd->peer->status = Established; /* keep bgp core happy */ + bgp_sync_delete(rfd->peer); /* don't need these */ + if (rfd->peer->ibuf) { + stream_free(rfd->peer->ibuf); /* don't need it */ + rfd->peer->ibuf = NULL; + } + if (rfd->peer->obuf) { + stream_fifo_free(rfd->peer->obuf); /* don't need it */ + rfd->peer->obuf = NULL; + } + if (rfd->peer->work) { + stream_free(rfd->peer->work); /* don't need it */ + rfd->peer->work = NULL; + } + { /* base code assumes have valid host pointer */ + char buf[BUFSIZ]; + buf[0] = 0; + + if (rfd->vn_addr.addr_family == AF_INET) { + inet_ntop(AF_INET, &rfd->vn_addr.addr.v4, buf, BUFSIZ); + } else if (rfd->vn_addr.addr_family == AF_INET6) { + inet_ntop(AF_INET6, &rfd->vn_addr.addr.v6, buf, BUFSIZ); + } + rfd->peer->host = XSTRDUP(MTYPE_BGP_PEER_HOST, buf); + } + /* Mark peer as belonging to HD */ + SET_FLAG(rfd->peer->flags, PEER_FLAG_IS_RFAPI_HD); + + /* + * Set min prefix lifetime to max value so it will get set + * upon first rfapi_register() + */ + rfd->min_prefix_lifetime = UINT32_MAX; - if (h->flags & RFAPI_INCALLBACK) - return EDEADLK; +/* + * Allocate response tables if needed + */ +#define RFD_RTINIT_AFI(rh, ary, afi) \ + do { \ + if (!ary[afi]) { \ + ary[afi] = route_table_init(); \ + ary[afi]->info = rh; \ + } \ + } while (0) + +#define RFD_RTINIT(rh, ary) \ + do { \ + RFD_RTINIT_AFI(rh, ary, AFI_IP); \ + RFD_RTINIT_AFI(rh, ary, AFI_IP6); \ + RFD_RTINIT_AFI(rh, ary, AFI_L2VPN); \ + } while (0) + + RFD_RTINIT(rfd, rfd->rib); + RFD_RTINIT(rfd, rfd->rib_pending); + RFD_RTINIT(rfd, rfd->rsp_times); + + /* + * Link to Import Table + */ + rfd->import_table = rfg->rfapi_import_table; + rfd->import_table->refcount += 1; + + rfapiApInit(&rfd->advertised); + + /* + * add this NVE descriptor to the list of NVEs in the NVE group + */ + if (!rfg->nves) { + rfg->nves = list_new(); + } + listnode_add(rfg->nves, rfd); + + vnc_direct_bgp_add_nve(bgp, rfd); + vnc_zebra_add_nve(bgp, rfd); + + return 0; +} - /* - * Fill in configured fields - */ +/* moved from rfapi_register */ +int rfapi_init_and_open(struct bgp *bgp, struct rfapi_descriptor *rfd, + struct rfapi_nve_group_cfg *rfg) +{ + struct rfapi *h = bgp->rfapi; + char buf_vn[BUFSIZ]; + char buf_un[BUFSIZ]; + afi_t afi_vn, afi_un; + struct prefix pfx_un; + struct route_node *rn; + + + rfapi_time(&rfd->open_time); + + if (rfg->type == RFAPI_GROUP_CFG_VRF) + SET_FLAG(rfd->flags, RFAPI_HD_FLAG_IS_VRF); + + rfapiRfapiIpAddr2Str(&rfd->vn_addr, buf_vn, BUFSIZ); + rfapiRfapiIpAddr2Str(&rfd->un_addr, buf_un, BUFSIZ); + + vnc_zlog_debug_verbose("%s: new RFD with VN=%s UN=%s cookie=%p", + __func__, buf_vn, buf_un, rfd->cookie); + + if (rfg->type != RFAPI_GROUP_CFG_VRF) /* unclear if needed for VRF */ + { + listnode_add(&h->descriptors, rfd); + if (h->descriptors.count > h->stat.max_descriptors) { + h->stat.max_descriptors = h->descriptors.count; + } + + /* + * attach to UN radix tree + */ + afi_vn = family2afi(rfd->vn_addr.addr_family); + afi_un = family2afi(rfd->un_addr.addr_family); + assert(afi_vn && afi_un); + assert(!rfapiRaddr2Qprefix(&rfd->un_addr, &pfx_un)); + + rn = route_node_get(&(h->un[afi_un]), &pfx_un); + assert(rn); + rfd->next = rn->info; + rn->info = rfd; + rfd->un_node = rn; + } + return rfapi_open_inner(rfd, bgp, h, rfg); +} - /* - * If group's RD is specified as "auto", then fill in based - * on NVE's VN address - */ - rfd->rd = rfg->rd; +struct rfapi_vn_option *rfapiVnOptionsDup(struct rfapi_vn_option *orig) +{ + struct rfapi_vn_option *head = NULL; + struct rfapi_vn_option *tail = NULL; + struct rfapi_vn_option *vo = NULL; + + for (vo = orig; vo; vo = vo->next) { + struct rfapi_vn_option *new; + + new = XCALLOC(MTYPE_RFAPI_VN_OPTION, + sizeof(struct rfapi_vn_option)); + memcpy(new, vo, sizeof(struct rfapi_vn_option)); + new->next = NULL; + + if (tail) { + tail->next = new; + } else { + head = tail = new; + } + } + return head; +} - if (rfd->rd.family == AF_UNIX) - { - ret = rfapi_set_autord_from_vn (&rfd->rd, &rfd->vn_addr); - if (ret != 0) - return ret; - } - rfd->rt_export_list = (rfg->rt_export_list) ? - ecommunity_dup (rfg->rt_export_list) : NULL; - rfd->response_lifetime = rfg->response_lifetime; - rfd->rfg = rfg; +struct rfapi_un_option *rfapiUnOptionsDup(struct rfapi_un_option *orig) +{ + struct rfapi_un_option *head = NULL; + struct rfapi_un_option *tail = NULL; + struct rfapi_un_option *uo = NULL; + + for (uo = orig; uo; uo = uo->next) { + struct rfapi_un_option *new; + + new = XCALLOC(MTYPE_RFAPI_UN_OPTION, + sizeof(struct rfapi_un_option)); + memcpy(new, uo, sizeof(struct rfapi_un_option)); + new->next = NULL; + + if (tail) { + tail->next = new; + } else { + head = tail = new; + } + } + return head; +} - /* - * Fill in BGP peer structure - */ - rfd->peer = peer_new (bgp); - rfd->peer->status = Established; /* keep bgp core happy */ - bgp_sync_delete (rfd->peer); /* don't need these */ - if (rfd->peer->ibuf) - { - stream_free (rfd->peer->ibuf); /* don't need it */ - rfd->peer->ibuf = NULL; - } - if (rfd->peer->obuf) - { - stream_fifo_free (rfd->peer->obuf); /* don't need it */ - rfd->peer->obuf = NULL; - } - if (rfd->peer->work) - { - stream_free (rfd->peer->work); /* don't need it */ - rfd->peer->work = NULL; - } - { /* base code assumes have valid host pointer */ - char buf[BUFSIZ]; - buf[0] = 0; - - if (rfd->vn_addr.addr_family == AF_INET) - { - inet_ntop (AF_INET, &rfd->vn_addr.addr.v4, buf, BUFSIZ); - } - else if (rfd->vn_addr.addr_family == AF_INET6) - { - inet_ntop (AF_INET6, &rfd->vn_addr.addr.v6, buf, BUFSIZ); - } - rfd->peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf); - } - /* Mark peer as belonging to HD */ - SET_FLAG (rfd->peer->flags, PEER_FLAG_IS_RFAPI_HD); - - /* - * Set min prefix lifetime to max value so it will get set - * upon first rfapi_register() - */ - rfd->min_prefix_lifetime = UINT32_MAX; - - /* - * Allocate response tables if needed - */ -#define RFD_RTINIT_AFI(rh, ary, afi) do {\ - if (!ary[afi]) { \ - ary[afi] = route_table_init ();\ - ary[afi]->info = rh;\ - }\ -} while (0) - -#define RFD_RTINIT(rh, ary) do {\ - RFD_RTINIT_AFI(rh, ary, AFI_IP);\ - RFD_RTINIT_AFI(rh, ary, AFI_IP6);\ - RFD_RTINIT_AFI(rh, ary, AFI_L2VPN);\ -} while(0) - - RFD_RTINIT(rfd, rfd->rib); - RFD_RTINIT(rfd, rfd->rib_pending); - RFD_RTINIT(rfd, rfd->rsp_times); - - /* - * Link to Import Table - */ - rfd->import_table = rfg->rfapi_import_table; - rfd->import_table->refcount += 1; - - rfapiApInit (&rfd->advertised); - - /* - * add this NVE descriptor to the list of NVEs in the NVE group - */ - if (!rfg->nves) - { - rfg->nves = list_new (); - } - listnode_add (rfg->nves, rfd); - - vnc_direct_bgp_add_nve (bgp, rfd); - vnc_zebra_add_nve (bgp, rfd); - - return 0; -} - -/* moved from rfapi_register */ -int -rfapi_init_and_open( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct rfapi_nve_group_cfg *rfg) +struct bgp_tea_options *rfapiOptionsDup(struct bgp_tea_options *orig) { - struct rfapi *h = bgp->rfapi; - char buf_vn[BUFSIZ]; - char buf_un[BUFSIZ]; - afi_t afi_vn, afi_un; - struct prefix pfx_un; - struct route_node *rn; - - - rfapi_time (&rfd->open_time); - - if (rfg->type == RFAPI_GROUP_CFG_VRF) - SET_FLAG(rfd->flags, RFAPI_HD_FLAG_IS_VRF); - - rfapiRfapiIpAddr2Str (&rfd->vn_addr, buf_vn, BUFSIZ); - rfapiRfapiIpAddr2Str (&rfd->un_addr, buf_un, BUFSIZ); - - vnc_zlog_debug_verbose ("%s: new RFD with VN=%s UN=%s cookie=%p", - __func__, buf_vn, buf_un, rfd->cookie); - - if (rfg->type != RFAPI_GROUP_CFG_VRF) /* unclear if needed for VRF */ - { - listnode_add (&h->descriptors, rfd); - if (h->descriptors.count > h->stat.max_descriptors) - { - h->stat.max_descriptors = h->descriptors.count; - } - - /* - * attach to UN radix tree - */ - afi_vn = family2afi (rfd->vn_addr.addr_family); - afi_un = family2afi (rfd->un_addr.addr_family); - assert (afi_vn && afi_un); - assert (!rfapiRaddr2Qprefix (&rfd->un_addr, &pfx_un)); - - rn = route_node_get (&(h->un[afi_un]), &pfx_un); - assert (rn); - rfd->next = rn->info; - rn->info = rfd; - rfd->un_node = rn; - } - return rfapi_open_inner (rfd, bgp, h, rfg); + struct bgp_tea_options *head = NULL; + struct bgp_tea_options *tail = NULL; + struct bgp_tea_options *hop = NULL; + + for (hop = orig; hop; hop = hop->next) { + struct bgp_tea_options *new; + + new = XCALLOC(MTYPE_BGP_TEA_OPTIONS, + sizeof(struct bgp_tea_options)); + memcpy(new, hop, sizeof(struct bgp_tea_options)); + new->next = NULL; + if (hop->value) { + new->value = XCALLOC(MTYPE_BGP_TEA_OPTIONS_VALUE, + hop->length); + memcpy(new->value, hop->value, hop->length); + } + if (tail) { + tail->next = new; + } else { + head = tail = new; + } + } + return head; } -struct rfapi_vn_option * -rfapiVnOptionsDup (struct rfapi_vn_option *orig) +void rfapiFreeBgpTeaOptionChain(struct bgp_tea_options *p) { - struct rfapi_vn_option *head = NULL; - struct rfapi_vn_option *tail = NULL; - struct rfapi_vn_option *vo = NULL; + struct bgp_tea_options *next; - for (vo = orig; vo; vo = vo->next) - { - struct rfapi_vn_option *new; + while (p) { + next = p->next; - new = XCALLOC (MTYPE_RFAPI_VN_OPTION, sizeof (struct rfapi_vn_option)); - memcpy (new, vo, sizeof (struct rfapi_vn_option)); - new->next = NULL; + if (p->value) { + XFREE(MTYPE_BGP_TEA_OPTIONS_VALUE, p->value); + p->value = NULL; + } + XFREE(MTYPE_BGP_TEA_OPTIONS, p); - if (tail) - { - tail->next = new; - } - else - { - head = tail = new; - } - } - return head; -} - -struct rfapi_un_option * -rfapiUnOptionsDup (struct rfapi_un_option *orig) -{ - struct rfapi_un_option *head = NULL; - struct rfapi_un_option *tail = NULL; - struct rfapi_un_option *uo = NULL; - - for (uo = orig; uo; uo = uo->next) - { - struct rfapi_un_option *new; - - new = XCALLOC (MTYPE_RFAPI_UN_OPTION, sizeof (struct rfapi_un_option)); - memcpy (new, uo, sizeof (struct rfapi_un_option)); - new->next = NULL; - - if (tail) - { - tail->next = new; - } - else - { - head = tail = new; - } - } - return head; -} - -struct bgp_tea_options * -rfapiOptionsDup (struct bgp_tea_options *orig) -{ - struct bgp_tea_options *head = NULL; - struct bgp_tea_options *tail = NULL; - struct bgp_tea_options *hop = NULL; - - for (hop = orig; hop; hop = hop->next) - { - struct bgp_tea_options *new; - - new = XCALLOC (MTYPE_BGP_TEA_OPTIONS, sizeof (struct bgp_tea_options)); - memcpy (new, hop, sizeof (struct bgp_tea_options)); - new->next = NULL; - if (hop->value) - { - new->value = XCALLOC (MTYPE_BGP_TEA_OPTIONS_VALUE, hop->length); - memcpy (new->value, hop->value, hop->length); - } - if (tail) - { - tail->next = new; - } - else - { - head = tail = new; - } - } - return head; -} - -void -rfapiFreeBgpTeaOptionChain (struct bgp_tea_options *p) -{ - struct bgp_tea_options *next; - - while (p) - { - next = p->next; - - if (p->value) - { - XFREE (MTYPE_BGP_TEA_OPTIONS_VALUE, p->value); - p->value = NULL; - } - XFREE (MTYPE_BGP_TEA_OPTIONS, p); - - p = next; - } + p = next; + } } -void -rfapiAdbFree (struct rfapi_adb *adb) +void rfapiAdbFree(struct rfapi_adb *adb) { - XFREE (MTYPE_RFAPI_ADB, adb); + XFREE(MTYPE_RFAPI_ADB, adb); } static int -rfapi_query_inner ( - void *handle, - struct rfapi_ip_addr *target, - struct rfapi_l2address_option *l2o, /* may be NULL */ - struct rfapi_next_hop_entry **ppNextHopEntry) +rfapi_query_inner(void *handle, struct rfapi_ip_addr *target, + struct rfapi_l2address_option *l2o, /* may be NULL */ + struct rfapi_next_hop_entry **ppNextHopEntry) { - afi_t afi; - struct prefix p; - struct prefix p_original; - struct route_node *rn; - struct rfapi_descriptor *rfd = (struct rfapi_descriptor *) handle; - struct bgp *bgp = rfd->bgp; - struct rfapi_next_hop_entry *pNHE = NULL; - struct rfapi_ip_addr *self_vn_addr = NULL; - int eth_is_0 = 0; - int use_eth_resolution = 0; - struct rfapi_next_hop_entry *i_nhe; - - /* preemptive */ - if (!bgp) - { - vnc_zlog_debug_verbose ("%s: No BGP instance, returning ENXIO", __func__); - return ENXIO; - } - if (!bgp->rfapi) - { - vnc_zlog_debug_verbose ("%s: No RFAPI instance, returning ENXIO", __func__); - return ENXIO; - } - if (bgp->rfapi->flags & RFAPI_INCALLBACK) - { - vnc_zlog_debug_verbose ("%s: Called during calback, returning EDEADLK", __func__); - return EDEADLK; - } - - if (!is_valid_rfd (rfd)) - { - vnc_zlog_debug_verbose ("%s: invalid handle, returning EBADF", __func__); - return EBADF; - } - - rfd->rsp_counter++; /* dedup: identify this generation */ - rfd->rsp_time = rfapi_time (NULL); /* response content dedup */ - rfd->ftd_last_allowed_time = - bgp_clock() - bgp->rfapi_cfg->rfp_cfg.ftd_advertisement_interval; - - if (l2o) - { - if (!memcmp (l2o->macaddr.octet, rfapi_ethaddr0.octet, ETHER_ADDR_LEN)) - { - eth_is_0 = 1; - } - /* per t/c Paul/Lou 151022 */ - if (!eth_is_0 || l2o->logical_net_id) - { - use_eth_resolution = 1; - } - } - - if (ppNextHopEntry) - *ppNextHopEntry = NULL; - - /* - * Save original target in prefix form. In case of L2-based queries, - * p_original will be modified to reflect the L2 target - */ - assert(!rfapiRaddr2Qprefix (target, &p_original)); - - if (bgp->rfapi_cfg->rfp_cfg.download_type == RFAPI_RFP_DOWNLOAD_FULL) - { - /* convert query to 0/0 when full-table download is enabled */ - memset ((char *) &p, 0, sizeof (p)); - p.family = target->addr_family; - } - else - { - p = p_original; - } - - { - char buf[BUFSIZ]; - char *s; - - prefix2str (&p, buf, BUFSIZ); - buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */ - vnc_zlog_debug_verbose ("%s(rfd=%p, target=%s, ppNextHop=%p)", - __func__, rfd, buf, ppNextHopEntry); - - s = ecommunity_ecom2str(rfd->import_table->rt_import_list, - ECOMMUNITY_FORMAT_ROUTE_MAP, 0); - vnc_zlog_debug_verbose("%s rfd->import_table=%p, rfd->import_table->rt_import_list: %s", - __func__, rfd->import_table, s); XFREE (MTYPE_ECOMMUNITY_STR, s); - } - - afi = family2afi (p.family); - assert (afi); - - if (CHECK_FLAG (bgp->rfapi_cfg->flags, BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP)) - { - self_vn_addr = &rfd->vn_addr; - } - - if (use_eth_resolution) - { - uint32_t logical_net_id = l2o->logical_net_id; - struct ecommunity *l2com; - - /* - * fix up p_original to contain L2 address - */ - rfapiL2o2Qprefix (l2o, &p_original); - - l2com = - bgp_rfapi_get_ecommunity_by_lni_label (bgp, 1, logical_net_id, - l2o->label); - if (l2com) - { - uint8_t *v = l2com->val; - logical_net_id = (v[5] << 16) + (v[6] << 8) + (v[7]); - } - /* - * Ethernet/L2-based lookup - * - * Always returns IT node corresponding to route - */ - - if (RFAPI_RFP_DOWNLOAD_FULL == bgp->rfapi_cfg->rfp_cfg.download_type) - { - eth_is_0 = 1; - } - - rn = rfapiMonitorEthAdd (bgp, - rfd, - (eth_is_0 ? &rfapi_ethaddr0 : &l2o->macaddr), - logical_net_id); - - if (eth_is_0) - { - struct rfapi_ip_prefix rprefix; - - memset (&rprefix, 0, sizeof (rprefix)); - rprefix.prefix.addr_family = target->addr_family; - if (target->addr_family == AF_INET) - { - rprefix.length = 32; - } - else - { - rprefix.length = 128; - } - - pNHE = rfapiEthRouteTable2NextHopList (logical_net_id, &rprefix, - rfd->response_lifetime, self_vn_addr, rfd->rib[afi], &p_original); - goto done; - } - - } - else - { - - /* - * IP-based lookup - */ - - rn = rfapiMonitorAdd (bgp, rfd, &p); - - /* - * If target address is 0, this request is special: means to - * return ALL routes in the table - * - * Monitors for All-Routes queries get put on a special list, - * not in the VPN tree - */ - if (RFAPI_0_PREFIX (&p)) - { - - vnc_zlog_debug_verbose ("%s: 0-prefix", __func__); - - /* - * Generate nexthop list for caller - */ - pNHE = rfapiRouteTable2NextHopList ( - rfd->import_table->imported_vpn[afi], rfd->response_lifetime, - self_vn_addr, rfd->rib[afi], &p_original); - goto done; - } - - if (rn) - { - route_lock_node (rn); /* so we can unlock below */ - } - else - { - /* - * returns locked node. Don't unlock yet because the unlock - * might free it before we're done with it. This situation - * could occur when rfapiMonitorGetAttachNode() returns a - * newly-created default node. - */ - rn = rfapiMonitorGetAttachNode (rfd, &p); - } - } - - assert (rn); - if (!rn->info) - { - route_unlock_node (rn); - vnc_zlog_debug_verbose ("%s: VPN route not found, returning ENOENT", __func__); - return ENOENT; - } - - if (VNC_DEBUG(RFAPI_QUERY)) - { - rfapiShowImportTable (NULL, "query", rfd->import_table->imported_vpn[afi], - 1); - } - - if (use_eth_resolution) - { - - struct rfapi_ip_prefix rprefix; - - memset (&rprefix, 0, sizeof (rprefix)); - rprefix.prefix.addr_family = target->addr_family; - if (target->addr_family == AF_INET) - { - rprefix.length = 32; - } - else - { - rprefix.length = 128; - } - - pNHE = rfapiEthRouteNode2NextHopList (rn, &rprefix, - rfd->response_lifetime, self_vn_addr, rfd->rib[afi], &p_original); - - - } - else - { - /* - * Generate answer to query - */ - pNHE = rfapiRouteNode2NextHopList(rn, rfd->response_lifetime, - self_vn_addr, rfd->rib[afi], &p_original); - } - - route_unlock_node (rn); + afi_t afi; + struct prefix p; + struct prefix p_original; + struct route_node *rn; + struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle; + struct bgp *bgp = rfd->bgp; + struct rfapi_next_hop_entry *pNHE = NULL; + struct rfapi_ip_addr *self_vn_addr = NULL; + int eth_is_0 = 0; + int use_eth_resolution = 0; + struct rfapi_next_hop_entry *i_nhe; + + /* preemptive */ + if (!bgp) { + vnc_zlog_debug_verbose("%s: No BGP instance, returning ENXIO", + __func__); + return ENXIO; + } + if (!bgp->rfapi) { + vnc_zlog_debug_verbose("%s: No RFAPI instance, returning ENXIO", + __func__); + return ENXIO; + } + if (bgp->rfapi->flags & RFAPI_INCALLBACK) { + vnc_zlog_debug_verbose( + "%s: Called during calback, returning EDEADLK", + __func__); + return EDEADLK; + } + + if (!is_valid_rfd(rfd)) { + vnc_zlog_debug_verbose("%s: invalid handle, returning EBADF", + __func__); + return EBADF; + } + + rfd->rsp_counter++; /* dedup: identify this generation */ + rfd->rsp_time = rfapi_time(NULL); /* response content dedup */ + rfd->ftd_last_allowed_time = + bgp_clock() + - bgp->rfapi_cfg->rfp_cfg.ftd_advertisement_interval; + + if (l2o) { + if (!memcmp(l2o->macaddr.octet, rfapi_ethaddr0.octet, + ETHER_ADDR_LEN)) { + eth_is_0 = 1; + } + /* per t/c Paul/Lou 151022 */ + if (!eth_is_0 || l2o->logical_net_id) { + use_eth_resolution = 1; + } + } + + if (ppNextHopEntry) + *ppNextHopEntry = NULL; + + /* + * Save original target in prefix form. In case of L2-based queries, + * p_original will be modified to reflect the L2 target + */ + assert(!rfapiRaddr2Qprefix(target, &p_original)); + + if (bgp->rfapi_cfg->rfp_cfg.download_type == RFAPI_RFP_DOWNLOAD_FULL) { + /* convert query to 0/0 when full-table download is enabled */ + memset((char *)&p, 0, sizeof(p)); + p.family = target->addr_family; + } else { + p = p_original; + } + + { + char buf[BUFSIZ]; + char *s; + + prefix2str(&p, buf, BUFSIZ); + buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */ + vnc_zlog_debug_verbose("%s(rfd=%p, target=%s, ppNextHop=%p)", + __func__, rfd, buf, ppNextHopEntry); + + s = ecommunity_ecom2str(rfd->import_table->rt_import_list, + ECOMMUNITY_FORMAT_ROUTE_MAP, 0); + vnc_zlog_debug_verbose( + "%s rfd->import_table=%p, rfd->import_table->rt_import_list: %s", + __func__, rfd->import_table, s); + XFREE(MTYPE_ECOMMUNITY_STR, s); + } + + afi = family2afi(p.family); + assert(afi); + + if (CHECK_FLAG(bgp->rfapi_cfg->flags, + BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP)) { + self_vn_addr = &rfd->vn_addr; + } + + if (use_eth_resolution) { + uint32_t logical_net_id = l2o->logical_net_id; + struct ecommunity *l2com; + + /* + * fix up p_original to contain L2 address + */ + rfapiL2o2Qprefix(l2o, &p_original); + + l2com = bgp_rfapi_get_ecommunity_by_lni_label( + bgp, 1, logical_net_id, l2o->label); + if (l2com) { + uint8_t *v = l2com->val; + logical_net_id = (v[5] << 16) + (v[6] << 8) + (v[7]); + } + /* + * Ethernet/L2-based lookup + * + * Always returns IT node corresponding to route + */ + + if (RFAPI_RFP_DOWNLOAD_FULL + == bgp->rfapi_cfg->rfp_cfg.download_type) { + eth_is_0 = 1; + } + + rn = rfapiMonitorEthAdd( + bgp, rfd, (eth_is_0 ? &rfapi_ethaddr0 : &l2o->macaddr), + logical_net_id); + + if (eth_is_0) { + struct rfapi_ip_prefix rprefix; + + memset(&rprefix, 0, sizeof(rprefix)); + rprefix.prefix.addr_family = target->addr_family; + if (target->addr_family == AF_INET) { + rprefix.length = 32; + } else { + rprefix.length = 128; + } + + pNHE = rfapiEthRouteTable2NextHopList( + logical_net_id, &rprefix, + rfd->response_lifetime, self_vn_addr, + rfd->rib[afi], &p_original); + goto done; + } + + } else { + + /* + * IP-based lookup + */ + + rn = rfapiMonitorAdd(bgp, rfd, &p); + + /* + * If target address is 0, this request is special: means to + * return ALL routes in the table + * + * Monitors for All-Routes queries get put on a special list, + * not in the VPN tree + */ + if (RFAPI_0_PREFIX(&p)) { + + vnc_zlog_debug_verbose("%s: 0-prefix", __func__); + + /* + * Generate nexthop list for caller + */ + pNHE = rfapiRouteTable2NextHopList( + rfd->import_table->imported_vpn[afi], + rfd->response_lifetime, self_vn_addr, + rfd->rib[afi], &p_original); + goto done; + } + + if (rn) { + route_lock_node(rn); /* so we can unlock below */ + } else { + /* + * returns locked node. Don't unlock yet because the + * unlock + * might free it before we're done with it. This + * situation + * could occur when rfapiMonitorGetAttachNode() returns + * a + * newly-created default node. + */ + rn = rfapiMonitorGetAttachNode(rfd, &p); + } + } + + assert(rn); + if (!rn->info) { + route_unlock_node(rn); + vnc_zlog_debug_verbose( + "%s: VPN route not found, returning ENOENT", __func__); + return ENOENT; + } + + if (VNC_DEBUG(RFAPI_QUERY)) { + rfapiShowImportTable(NULL, "query", + rfd->import_table->imported_vpn[afi], 1); + } + + if (use_eth_resolution) { + + struct rfapi_ip_prefix rprefix; + + memset(&rprefix, 0, sizeof(rprefix)); + rprefix.prefix.addr_family = target->addr_family; + if (target->addr_family == AF_INET) { + rprefix.length = 32; + } else { + rprefix.length = 128; + } + + pNHE = rfapiEthRouteNode2NextHopList( + rn, &rprefix, rfd->response_lifetime, self_vn_addr, + rfd->rib[afi], &p_original); + + + } else { + /* + * Generate answer to query + */ + pNHE = rfapiRouteNode2NextHopList(rn, rfd->response_lifetime, + self_vn_addr, rfd->rib[afi], + &p_original); + } + + route_unlock_node(rn); done: - if (ppNextHopEntry) - { - /* only count if caller gets it */ - ++bgp->rfapi->response_immediate_count; - } - - if (!pNHE) - { - vnc_zlog_debug_verbose ("%s: NO NHEs, returning ENOENT", __func__); - return ENOENT; - } - - /* - * count nexthops for statistics - */ - for (i_nhe = pNHE; i_nhe; i_nhe = i_nhe->next) - { - ++rfd->stat_count_nh_reachable; - } - - if (ppNextHopEntry) - { - *ppNextHopEntry = pNHE; - } - else - { - rfapi_free_next_hop_list (pNHE); - } - - vnc_zlog_debug_verbose ("%s: success", __func__); - return 0; + if (ppNextHopEntry) { + /* only count if caller gets it */ + ++bgp->rfapi->response_immediate_count; + } + + if (!pNHE) { + vnc_zlog_debug_verbose("%s: NO NHEs, returning ENOENT", + __func__); + return ENOENT; + } + + /* + * count nexthops for statistics + */ + for (i_nhe = pNHE; i_nhe; i_nhe = i_nhe->next) { + ++rfd->stat_count_nh_reachable; + } + + if (ppNextHopEntry) { + *ppNextHopEntry = pNHE; + } else { + rfapi_free_next_hop_list(pNHE); + } + + vnc_zlog_debug_verbose("%s: success", __func__); + return 0; } /* @@ -1929,68 +1787,63 @@ done: * nve-group in the event that its original nve-group is * administratively deleted. */ -static int -rfapi_open_rfd (struct rfapi_descriptor *rfd, struct bgp *bgp) +static int rfapi_open_rfd(struct rfapi_descriptor *rfd, struct bgp *bgp) { - struct prefix pfx_vn; - struct prefix pfx_un; - struct rfapi_nve_group_cfg *rfg; - struct rfapi *h; - struct rfapi_cfg *hc; - int rc; - - h = bgp->rfapi; - if (!h) - return ENXIO; - - hc = bgp->rfapi_cfg; - if (!hc) - return ENXIO; - - rc = rfapiRaddr2Qprefix (&rfd->vn_addr, &pfx_vn); - assert (!rc); - - rc = rfapiRaddr2Qprefix (&rfd->un_addr, &pfx_un); - assert (!rc); - - /* - * Find the matching nve group config block - */ - rfg = bgp_rfapi_cfg_match_group (hc, &pfx_vn, &pfx_un); - if (!rfg) - { - return ENOENT; - } - - /* - * check nve group config block for required values - */ - if (!rfg->rt_export_list || !rfg->rfapi_import_table) - { - - return ENOMSG; - } - - rc = rfapi_open_inner (rfd, bgp, h, rfg); - if (rc) - { - return rc; - } - - /* - * re-advertise registered routes, this time as part of new NVE-group - */ - rfapiApReadvertiseAll (bgp, rfd); - - /* - * re-attach callbacks to import table - */ - if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)) - { - rfapiMonitorAttachImportHd (rfd); - } - - return 0; + struct prefix pfx_vn; + struct prefix pfx_un; + struct rfapi_nve_group_cfg *rfg; + struct rfapi *h; + struct rfapi_cfg *hc; + int rc; + + h = bgp->rfapi; + if (!h) + return ENXIO; + + hc = bgp->rfapi_cfg; + if (!hc) + return ENXIO; + + rc = rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx_vn); + assert(!rc); + + rc = rfapiRaddr2Qprefix(&rfd->un_addr, &pfx_un); + assert(!rc); + + /* + * Find the matching nve group config block + */ + rfg = bgp_rfapi_cfg_match_group(hc, &pfx_vn, &pfx_un); + if (!rfg) { + return ENOENT; + } + + /* + * check nve group config block for required values + */ + if (!rfg->rt_export_list || !rfg->rfapi_import_table) { + + return ENOMSG; + } + + rc = rfapi_open_inner(rfd, bgp, h, rfg); + if (rc) { + return rc; + } + + /* + * re-advertise registered routes, this time as part of new NVE-group + */ + rfapiApReadvertiseAll(bgp, rfd); + + /* + * re-attach callbacks to import table + */ + if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)) { + rfapiMonitorAttachImportHd(rfd); + } + + return 0; } /*------------------------------------------ @@ -1999,7 +1852,7 @@ rfapi_open_rfd (struct rfapi_descriptor *rfd, struct bgp *bgp) * This function initializes a NVE record and associates it with * the specified VN and underlay network addresses * - * input: + * input: * rfp_start_val value returned by rfp_start * vn NVE virtual network address * @@ -2017,13 +1870,13 @@ rfapi_open_rfd (struct rfapi_descriptor *rfd, struct bgp *bgp) * * output: * response_lifetime The length of time that responses sent to this - * NVE are valid. + * NVE are valid. * * pHandle pointer to location to store rfapi handle. The * handle must be passed on subsequent rfapi_ calls. * * - * return value: + * return value: * 0 Success * EEXIST NVE with this {vn,un} already open * ENOENT No matching nve group config @@ -2033,443 +1886,419 @@ rfapi_open_rfd (struct rfapi_descriptor *rfd, struct bgp *bgp) * but underlay network address is not IPv4 * EDEADLK Called from within a callback procedure *------------------------------------------*/ -int -rfapi_open ( - void *rfp_start_val, - struct rfapi_ip_addr *vn, - struct rfapi_ip_addr *un, - struct rfapi_un_option *default_options, - uint32_t *response_lifetime, - void *userdata, /* callback cookie */ - rfapi_handle *pHandle) +int rfapi_open(void *rfp_start_val, struct rfapi_ip_addr *vn, + struct rfapi_ip_addr *un, + struct rfapi_un_option *default_options, + uint32_t *response_lifetime, + void *userdata, /* callback cookie */ + rfapi_handle *pHandle) { - struct bgp *bgp; - struct rfapi *h; - struct rfapi_descriptor *rfd; - struct rfapi_cfg *hc; - struct rfapi_nve_group_cfg *rfg; - - struct prefix pfx_vn; - struct prefix pfx_un; - - int rc; - rfapi_handle hh = NULL; - int reusing_provisional = 0; - - { - char buf[2][INET_ADDRSTRLEN]; - vnc_zlog_debug_verbose ("%s: VN=%s UN=%s", __func__, - rfapiRfapiIpAddr2Str (vn, buf[0], INET_ADDRSTRLEN), - rfapiRfapiIpAddr2Str (un, buf[1], INET_ADDRSTRLEN)); - } - - assert (pHandle); - *pHandle = NULL; - - bgp = rfapi_bgp_lookup_by_rfp (rfp_start_val); - if (!bgp) - return ENXIO; - - h = bgp->rfapi; - if (!h) - return ENXIO; - - hc = bgp->rfapi_cfg; - if (!hc) - return ENXIO; - - if (h->flags & RFAPI_INCALLBACK) - return EDEADLK; - - rc = rfapiRaddr2Qprefix (vn, &pfx_vn); - assert (!rc); - - rc = rfapiRaddr2Qprefix (un, &pfx_un); - assert (!rc); - - /* - * already have a descriptor with VN and UN? - */ - if (!rfapi_find_handle (bgp, vn, un, &hh)) - { - /* - * we might have set up a handle for static routes before - * this NVE was opened. In that case, reuse the handle - */ - rfd = hh; - if (!CHECK_FLAG (rfd->flags, RFAPI_HD_FLAG_PROVISIONAL)) - { - return EEXIST; - } - - /* - * reuse provisional descriptor - * hh is not NULL - */ - reusing_provisional = 1; - } - - /* - * Find the matching nve group config block - */ - rfg = bgp_rfapi_cfg_match_group (hc, &pfx_vn, &pfx_un); - if (!rfg) - { - ++h->stat.count_unknown_nves; - { - char buf[2][INET_ADDRSTRLEN]; - zlog_notice ("%s: no matching group VN=%s UN=%s", __func__, - rfapiRfapiIpAddr2Str (vn, buf[0], INET_ADDRSTRLEN), - rfapiRfapiIpAddr2Str (un, buf[1], INET_ADDRSTRLEN)); - } - return ENOENT; - } - - /* - * check nve group config block for required values - */ - if (!rfg->rt_export_list || !rfg->rfapi_import_table) - { - - ++h->stat.count_unknown_nves; - return ENOMSG; - } - - /* - * If group config specifies auto-rd assignment, check that - * VN address is IPv4|v6 so we don't fail in rfapi_open_inner(). - * Check here so we don't need to unwind memory allocations, &c. - */ - if ((rfg->rd.family == AF_UNIX) && (vn->addr_family != AF_INET) - && (vn->addr_family != AF_INET6)) - { - return EAFNOSUPPORT; - } - - if (hh) - { - /* - * reusing provisional rfd - */ - rfd = hh; - } - else - { - rfd = XCALLOC (MTYPE_RFAPI_DESC, sizeof (struct rfapi_descriptor)); - } - assert (rfd); - - rfd->bgp = bgp; - if (default_options) - { - struct rfapi_un_option *p; - - for (p = default_options; p; p = p->next) - { - if ((RFAPI_UN_OPTION_TYPE_PROVISIONAL == p->type)) - { - rfd->flags |= RFAPI_HD_FLAG_PROVISIONAL; - } - if ((RFAPI_UN_OPTION_TYPE_TUNNELTYPE == p->type)) - { - rfd->default_tunneltype_option = p->v.tunnel; - } - } - } - - /* - * Fill in caller fields - */ - rfd->vn_addr = *vn; - rfd->un_addr = *un; - rfd->cookie = userdata; - - if (!reusing_provisional) - { - rc = rfapi_init_and_open(bgp, rfd, rfg); - /* - * This can fail only if the VN address is IPv6 and the group - * specified auto-assignment of RDs, which only works for v4, - * and the check above should catch it. - * - * Another failure possibility is that we were called - * during an rfapi callback. Also checked above. - */ - assert (!rc); - } - - if (response_lifetime) - *response_lifetime = rfd->response_lifetime; - *pHandle = rfd; - return 0; + struct bgp *bgp; + struct rfapi *h; + struct rfapi_descriptor *rfd; + struct rfapi_cfg *hc; + struct rfapi_nve_group_cfg *rfg; + + struct prefix pfx_vn; + struct prefix pfx_un; + + int rc; + rfapi_handle hh = NULL; + int reusing_provisional = 0; + + { + char buf[2][INET_ADDRSTRLEN]; + vnc_zlog_debug_verbose( + "%s: VN=%s UN=%s", __func__, + rfapiRfapiIpAddr2Str(vn, buf[0], INET_ADDRSTRLEN), + rfapiRfapiIpAddr2Str(un, buf[1], INET_ADDRSTRLEN)); + } + + assert(pHandle); + *pHandle = NULL; + + bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val); + if (!bgp) + return ENXIO; + + h = bgp->rfapi; + if (!h) + return ENXIO; + + hc = bgp->rfapi_cfg; + if (!hc) + return ENXIO; + + if (h->flags & RFAPI_INCALLBACK) + return EDEADLK; + + rc = rfapiRaddr2Qprefix(vn, &pfx_vn); + assert(!rc); + + rc = rfapiRaddr2Qprefix(un, &pfx_un); + assert(!rc); + + /* + * already have a descriptor with VN and UN? + */ + if (!rfapi_find_handle(bgp, vn, un, &hh)) { + /* + * we might have set up a handle for static routes before + * this NVE was opened. In that case, reuse the handle + */ + rfd = hh; + if (!CHECK_FLAG(rfd->flags, RFAPI_HD_FLAG_PROVISIONAL)) { + return EEXIST; + } + + /* + * reuse provisional descriptor + * hh is not NULL + */ + reusing_provisional = 1; + } + + /* + * Find the matching nve group config block + */ + rfg = bgp_rfapi_cfg_match_group(hc, &pfx_vn, &pfx_un); + if (!rfg) { + ++h->stat.count_unknown_nves; + { + char buf[2][INET_ADDRSTRLEN]; + zlog_notice("%s: no matching group VN=%s UN=%s", + __func__, + rfapiRfapiIpAddr2Str(vn, buf[0], + INET_ADDRSTRLEN), + rfapiRfapiIpAddr2Str(un, buf[1], + INET_ADDRSTRLEN)); + } + return ENOENT; + } + + /* + * check nve group config block for required values + */ + if (!rfg->rt_export_list || !rfg->rfapi_import_table) { + + ++h->stat.count_unknown_nves; + return ENOMSG; + } + + /* + * If group config specifies auto-rd assignment, check that + * VN address is IPv4|v6 so we don't fail in rfapi_open_inner(). + * Check here so we don't need to unwind memory allocations, &c. + */ + if ((rfg->rd.family == AF_UNIX) && (vn->addr_family != AF_INET) + && (vn->addr_family != AF_INET6)) { + return EAFNOSUPPORT; + } + + if (hh) { + /* + * reusing provisional rfd + */ + rfd = hh; + } else { + rfd = XCALLOC(MTYPE_RFAPI_DESC, + sizeof(struct rfapi_descriptor)); + } + assert(rfd); + + rfd->bgp = bgp; + if (default_options) { + struct rfapi_un_option *p; + + for (p = default_options; p; p = p->next) { + if ((RFAPI_UN_OPTION_TYPE_PROVISIONAL == p->type)) { + rfd->flags |= RFAPI_HD_FLAG_PROVISIONAL; + } + if ((RFAPI_UN_OPTION_TYPE_TUNNELTYPE == p->type)) { + rfd->default_tunneltype_option = p->v.tunnel; + } + } + } + + /* + * Fill in caller fields + */ + rfd->vn_addr = *vn; + rfd->un_addr = *un; + rfd->cookie = userdata; + + if (!reusing_provisional) { + rc = rfapi_init_and_open(bgp, rfd, rfg); + /* + * This can fail only if the VN address is IPv6 and the group + * specified auto-assignment of RDs, which only works for v4, + * and the check above should catch it. + * + * Another failure possibility is that we were called + * during an rfapi callback. Also checked above. + */ + assert(!rc); + } + + if (response_lifetime) + *response_lifetime = rfd->response_lifetime; + *pHandle = rfd; + return 0; } /* * For use with debug functions */ -static int -rfapi_set_response_cb (struct rfapi_descriptor *rfd, - rfapi_response_cb_t * response_cb) +static int rfapi_set_response_cb(struct rfapi_descriptor *rfd, + rfapi_response_cb_t *response_cb) { - if (!is_valid_rfd (rfd)) - return EBADF; - rfd->response_cb = response_cb; - return 0; + if (!is_valid_rfd(rfd)) + return EBADF; + rfd->response_cb = response_cb; + return 0; } /* - * rfapi_close_inner - * - * Does almost all the work of rfapi_close, except: - * 1. preserves the descriptor (doesn't free it) - * 2. preserves the prefix query list (i.e., rfd->mon list) - * 3. preserves the advertised prefix list (rfd->advertised) - * 4. preserves the rib and rib_pending tables - * - * The purpose of organizing it this way is to support on-the-fly - * reassignment of an already-open nve to a new nve-group in the - * event that its original nve-group is administratively deleted. - */ -static int -rfapi_close_inner (struct rfapi_descriptor *rfd, struct bgp *bgp) -{ - int rc; - struct prefix pfx_vn; - struct prefix_rd prd; /* currently always 0 for VN->UN */ - - if (!is_valid_rfd (rfd)) - return EBADF; - - rc = rfapiRaddr2Qprefix (&rfd->vn_addr, &pfx_vn); - assert (!rc); /* should never have bad AF in stored vn address */ - - /* - * update exported routes to reflect disappearance of this NVE as nexthop - */ - vnc_direct_bgp_del_nve (bgp, rfd); - vnc_zebra_del_nve (bgp, rfd); - - /* - * unlink this HD's monitors from import table - */ - rfapiMonitorDetachImportHd (rfd); - - /* - * Unlink from Import Table - * NB rfd->import_table will be NULL if we are closing a stale descriptor - */ - if (rfd->import_table) - rfapiImportTableRefDelByIt (bgp, rfd->import_table); - rfd->import_table = NULL; - - /* - * Construct route distinguisher - */ - memset (&prd, 0, sizeof (prd)); - prd = rfd->rd; - prd.family = AF_UNSPEC; - prd.prefixlen = 64; - - /* - * withdraw tunnel - */ - del_vnc_route ( - rfd, - rfd->peer, - bgp, - SAFI_ENCAP, - &pfx_vn, /* prefix being advertised */ - &prd, /* route distinguisher to use (0 for ENCAP) */ - ZEBRA_ROUTE_BGP, - BGP_ROUTE_RFP, - NULL, - 0); /* no kill */ - - /* - * Construct route distinguisher for VPN routes - */ - prd = rfd->rd; - prd.family = AF_UNSPEC; - prd.prefixlen = 64; - - /* - * find all VPN routes associated with this rfd and delete them, too - */ - rfapiApWithdrawAll (bgp, rfd); - - /* - * remove this nve descriptor from the list of nves - * associated with the nve group - */ - if (rfd->rfg) - { - listnode_delete (rfd->rfg->nves, rfd); - rfd->rfg = NULL; /* XXX mark as orphaned/stale */ - } - - if (rfd->rt_export_list) - ecommunity_free (&rfd->rt_export_list); - rfd->rt_export_list = NULL; - - /* - * free peer structure (possibly delayed until its - * refcount reaches zero) - */ - if (rfd->peer) - { - vnc_zlog_debug_verbose ("%s: calling peer_delete(%p), #%d", - __func__, rfd->peer, rfd->peer->lock); - peer_delete (rfd->peer); - } - rfd->peer = NULL; - - return 0; + * rfapi_close_inner + * + * Does almost all the work of rfapi_close, except: + * 1. preserves the descriptor (doesn't free it) + * 2. preserves the prefix query list (i.e., rfd->mon list) + * 3. preserves the advertised prefix list (rfd->advertised) + * 4. preserves the rib and rib_pending tables + * + * The purpose of organizing it this way is to support on-the-fly + * reassignment of an already-open nve to a new nve-group in the + * event that its original nve-group is administratively deleted. + */ +static int rfapi_close_inner(struct rfapi_descriptor *rfd, struct bgp *bgp) +{ + int rc; + struct prefix pfx_vn; + struct prefix_rd prd; /* currently always 0 for VN->UN */ + + if (!is_valid_rfd(rfd)) + return EBADF; + + rc = rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx_vn); + assert(!rc); /* should never have bad AF in stored vn address */ + + /* + * update exported routes to reflect disappearance of this NVE as + * nexthop + */ + vnc_direct_bgp_del_nve(bgp, rfd); + vnc_zebra_del_nve(bgp, rfd); + + /* + * unlink this HD's monitors from import table + */ + rfapiMonitorDetachImportHd(rfd); + + /* + * Unlink from Import Table + * NB rfd->import_table will be NULL if we are closing a stale + * descriptor + */ + if (rfd->import_table) + rfapiImportTableRefDelByIt(bgp, rfd->import_table); + rfd->import_table = NULL; + + /* + * Construct route distinguisher + */ + memset(&prd, 0, sizeof(prd)); + prd = rfd->rd; + prd.family = AF_UNSPEC; + prd.prefixlen = 64; + + /* + * withdraw tunnel + */ + del_vnc_route(rfd, rfd->peer, bgp, SAFI_ENCAP, + &pfx_vn, /* prefix being advertised */ + &prd, /* route distinguisher to use (0 for ENCAP) */ + ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, NULL, 0); /* no kill */ + + /* + * Construct route distinguisher for VPN routes + */ + prd = rfd->rd; + prd.family = AF_UNSPEC; + prd.prefixlen = 64; + + /* + * find all VPN routes associated with this rfd and delete them, too + */ + rfapiApWithdrawAll(bgp, rfd); + + /* + * remove this nve descriptor from the list of nves + * associated with the nve group + */ + if (rfd->rfg) { + listnode_delete(rfd->rfg->nves, rfd); + rfd->rfg = NULL; /* XXX mark as orphaned/stale */ + } + + if (rfd->rt_export_list) + ecommunity_free(&rfd->rt_export_list); + rfd->rt_export_list = NULL; + + /* + * free peer structure (possibly delayed until its + * refcount reaches zero) + */ + if (rfd->peer) { + vnc_zlog_debug_verbose("%s: calling peer_delete(%p), #%d", + __func__, rfd->peer, rfd->peer->lock); + peer_delete(rfd->peer); + } + rfd->peer = NULL; + + return 0; } -int -rfapi_close (void *handle) +int rfapi_close(void *handle) { - struct rfapi_descriptor *rfd = (struct rfapi_descriptor *) handle; - int rc; - struct route_node *node; - struct bgp *bgp; - struct rfapi *h; + struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle; + int rc; + struct route_node *node; + struct bgp *bgp; + struct rfapi *h; - vnc_zlog_debug_verbose ("%s: rfd=%p", __func__, rfd); + vnc_zlog_debug_verbose("%s: rfd=%p", __func__, rfd); #if RFAPI_WHO_IS_CALLING_ME #ifdef HAVE_GLIBC_BACKTRACE #define RFAPI_DEBUG_BACKTRACE_NENTRIES 5 - { - void *buf[RFAPI_DEBUG_BACKTRACE_NENTRIES]; - char **syms; - int i; - size_t size; - - size = backtrace (buf, RFAPI_DEBUG_BACKTRACE_NENTRIES); - syms = backtrace_symbols (buf, size); - for (i = 0; i < size && i < RFAPI_DEBUG_BACKTRACE_NENTRIES; ++i) - { - vnc_zlog_debug_verbose ("backtrace[%2d]: %s", i, syms[i]); - } - free (syms); - } + { + void *buf[RFAPI_DEBUG_BACKTRACE_NENTRIES]; + char **syms; + int i; + size_t size; + + size = backtrace(buf, RFAPI_DEBUG_BACKTRACE_NENTRIES); + syms = backtrace_symbols(buf, size); + for (i = 0; i < size && i < RFAPI_DEBUG_BACKTRACE_NENTRIES; + ++i) { + vnc_zlog_debug_verbose("backtrace[%2d]: %s", i, + syms[i]); + } + free(syms); + } #endif #endif - bgp = rfd->bgp; - if (!bgp) - return ENXIO; - - h = bgp->rfapi; - if (!h) - return ENXIO; - - if (!is_valid_rfd (rfd)) - return EBADF; - - if (h->flags & RFAPI_INCALLBACK) - { - /* - * Queue these close requests for processing after callback - * is finished - */ - if (!CHECK_FLAG (rfd->flags, RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY)) - { - work_queue_add (h->deferred_close_q, handle); - vnc_zlog_debug_verbose ("%s: added handle %p to deferred close queue", - __func__, handle); - } - return 0; - } - - if (CHECK_FLAG (rfd->flags, RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY)) - { - - vnc_zlog_debug_verbose ("%s administrative close rfd=%p", __func__, rfd); - - if (h && h->rfp_methods.close_cb) - { - vnc_zlog_debug_verbose ("%s calling close callback rfd=%p", __func__, rfd); - - /* - * call the callback fairly early so that it can still lookup un/vn - * from handle, etc. - * - * NB RFAPI_INCALLBACK is tested above, so if we reach this point - * we are not already in the context of a callback. - */ - h->flags |= RFAPI_INCALLBACK; - (*h->rfp_methods.close_cb) (handle, EIDRM); - h->flags &= ~RFAPI_INCALLBACK; - } - } - - if (rfd->rfg) - { - /* - * Orphaned descriptors have already done this part, so do - * only for non-orphaned descriptors. - */ - if ((rc = rfapi_close_inner (rfd, bgp))) - return rc; - } - - /* - * Remove descriptor from UN index - * (remove from chain at node) - */ - rc = rfapi_find_node (bgp, &rfd->vn_addr, &rfd->un_addr, &node); - if (!rc) - { - struct rfapi_descriptor *hh; - - if (node->info == rfd) - { - node->info = rfd->next; - } - else - { - - for (hh = node->info; hh; hh = hh->next) - { - if (hh->next == rfd) - { - hh->next = rfd->next; - break; - } - } - } - route_unlock_node (node); - } - - /* - * remove from descriptor list - */ - listnode_delete (&h->descriptors, rfd); - - /* - * Delete monitor list items and free monitor structures - */ - (void) rfapiMonitorDelHd (rfd); - - /* - * release advertised prefix data - */ - rfapiApRelease (&rfd->advertised); - - /* - * Release RFP callback RIB - */ - rfapiRibFree (rfd); - - /* - * free descriptor - */ - memset (rfd, 0, sizeof (struct rfapi_descriptor)); - XFREE (MTYPE_RFAPI_DESC, rfd); - - return 0; + bgp = rfd->bgp; + if (!bgp) + return ENXIO; + + h = bgp->rfapi; + if (!h) + return ENXIO; + + if (!is_valid_rfd(rfd)) + return EBADF; + + if (h->flags & RFAPI_INCALLBACK) { + /* + * Queue these close requests for processing after callback + * is finished + */ + if (!CHECK_FLAG(rfd->flags, + RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY)) { + work_queue_add(h->deferred_close_q, handle); + vnc_zlog_debug_verbose( + "%s: added handle %p to deferred close queue", + __func__, handle); + } + return 0; + } + + if (CHECK_FLAG(rfd->flags, RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY)) { + + vnc_zlog_debug_verbose("%s administrative close rfd=%p", + __func__, rfd); + + if (h && h->rfp_methods.close_cb) { + vnc_zlog_debug_verbose( + "%s calling close callback rfd=%p", __func__, + rfd); + + /* + * call the callback fairly early so that it can still + * lookup un/vn + * from handle, etc. + * + * NB RFAPI_INCALLBACK is tested above, so if we reach + * this point + * we are not already in the context of a callback. + */ + h->flags |= RFAPI_INCALLBACK; + (*h->rfp_methods.close_cb)(handle, EIDRM); + h->flags &= ~RFAPI_INCALLBACK; + } + } + + if (rfd->rfg) { + /* + * Orphaned descriptors have already done this part, so do + * only for non-orphaned descriptors. + */ + if ((rc = rfapi_close_inner(rfd, bgp))) + return rc; + } + + /* + * Remove descriptor from UN index + * (remove from chain at node) + */ + rc = rfapi_find_node(bgp, &rfd->vn_addr, &rfd->un_addr, &node); + if (!rc) { + struct rfapi_descriptor *hh; + + if (node->info == rfd) { + node->info = rfd->next; + } else { + + for (hh = node->info; hh; hh = hh->next) { + if (hh->next == rfd) { + hh->next = rfd->next; + break; + } + } + } + route_unlock_node(node); + } + + /* + * remove from descriptor list + */ + listnode_delete(&h->descriptors, rfd); + + /* + * Delete monitor list items and free monitor structures + */ + (void)rfapiMonitorDelHd(rfd); + + /* + * release advertised prefix data + */ + rfapiApRelease(&rfd->advertised); + + /* + * Release RFP callback RIB + */ + rfapiRibFree(rfd); + + /* + * free descriptor + */ + memset(rfd, 0, sizeof(struct rfapi_descriptor)); + XFREE(MTYPE_RFAPI_DESC, rfd); + + return 0; } /* @@ -2489,580 +2318,535 @@ rfapi_close (void *handle) * caused by deleting and then adding the NVE: advertised prefixes * and nexthop lists for exported routes can turn over. */ -int -rfapi_reopen (struct rfapi_descriptor *rfd, struct bgp *bgp) +int rfapi_reopen(struct rfapi_descriptor *rfd, struct bgp *bgp) { - struct rfapi *h; - int rc; - - if ((rc = rfapi_close_inner (rfd, bgp))) - { - return rc; - } - if ((rc = rfapi_open_rfd (rfd, bgp))) - { - - h = bgp->rfapi; - - assert (!CHECK_FLAG (h->flags, RFAPI_INCALLBACK)); - - if (CHECK_FLAG (rfd->flags, RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY) && - h && h->rfp_methods.close_cb) - { - - /* - * NB RFAPI_INCALLBACK is tested above, so if we reach this point - * we are not already in the context of a callback. - */ - h->flags |= RFAPI_INCALLBACK; - (*h->rfp_methods.close_cb) ((rfapi_handle) rfd, ESTALE); - h->flags &= ~RFAPI_INCALLBACK; - } - return rc; - } - return 0; + struct rfapi *h; + int rc; + + if ((rc = rfapi_close_inner(rfd, bgp))) { + return rc; + } + if ((rc = rfapi_open_rfd(rfd, bgp))) { + + h = bgp->rfapi; + + assert(!CHECK_FLAG(h->flags, RFAPI_INCALLBACK)); + + if (CHECK_FLAG(rfd->flags, + RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY) + && h && h->rfp_methods.close_cb) { + + /* + * NB RFAPI_INCALLBACK is tested above, so if we reach + * this point + * we are not already in the context of a callback. + */ + h->flags |= RFAPI_INCALLBACK; + (*h->rfp_methods.close_cb)((rfapi_handle)rfd, ESTALE); + h->flags &= ~RFAPI_INCALLBACK; + } + return rc; + } + return 0; } /*********************************************************************** * NVE Routes ***********************************************************************/ -/* +/* * Announce reachability to this prefix via the NVE */ -int -rfapi_register ( - void *handle, - struct rfapi_ip_prefix *prefix, - uint32_t lifetime, /* host byte order */ - struct rfapi_un_option *options_un, - struct rfapi_vn_option *options_vn, - rfapi_register_action action) +int rfapi_register(void *handle, struct rfapi_ip_prefix *prefix, + uint32_t lifetime, /* host byte order */ + struct rfapi_un_option *options_un, + struct rfapi_vn_option *options_vn, + rfapi_register_action action) { - struct rfapi_descriptor *rfd = (struct rfapi_descriptor *) handle; - struct bgp *bgp; - struct prefix p; - struct prefix *pfx_ip = NULL; - struct prefix_rd prd; - int afi; - struct prefix pfx_mac_buf; - struct prefix *pfx_mac = NULL; - struct prefix pfx_vn_buf; - const char *action_str = NULL; - uint32_t *label = NULL; - struct rfapi_vn_option *vo; - struct rfapi_l2address_option *l2o = NULL; - struct prefix_rd *prd_override = NULL; - - switch (action) - { - case RFAPI_REGISTER_ADD: - action_str = "add"; - break; - case RFAPI_REGISTER_WITHDRAW: - action_str = "withdraw"; - break; - case RFAPI_REGISTER_KILL: - action_str = "kill"; - break; - default: - assert (0); - break; - } - - /* - * Inspect VN options - */ - for (vo = options_vn; vo; vo = vo->next) - { - if (RFAPI_VN_OPTION_TYPE_L2ADDR == vo->type) - { - l2o = &vo->v.l2addr; - } - if (RFAPI_VN_OPTION_TYPE_INTERNAL_RD == vo->type) - { - prd_override = &vo->v.internal_rd; - } - } - - /********************************************************************* - * advertise prefix - *********************************************************************/ - - /* - * set

based on - */ - assert (!rfapiRprefix2Qprefix (prefix, &p)); - - afi = family2afi (prefix->prefix.addr_family); - assert (afi); - - - { - char buf[BUFSIZ]; - - prefix2str (&p, buf, BUFSIZ); - buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */ - vnc_zlog_debug_verbose - ("%s(rfd=%p, pfx=%s, lifetime=%d, opts_un=%p, opts_vn=%p, action=%s)", - __func__, rfd, buf, lifetime, options_un, options_vn, action_str); - } - - /* - * These tests come after the prefix conversion so that we can - * print the prefix in a debug message before failing - */ - - bgp = rfd->bgp; - if (!bgp) - { - vnc_zlog_debug_verbose ("%s: no BGP instance: returning ENXIO", __func__); - return ENXIO; - } - if (!bgp->rfapi) - { - vnc_zlog_debug_verbose ("%s: no RFAPI instance: returning ENXIO", __func__); - return ENXIO; - } - if (!rfd->rfg) - { - if (RFAPI_REGISTER_ADD == action) - { - ++bgp->rfapi->stat.count_registrations_failed; - } - vnc_zlog_debug_verbose ("%s: rfd=%p, no RF GRP instance: returning ESTALE", - __func__, rfd); - return ESTALE; - } - - if (bgp->rfapi->flags & RFAPI_INCALLBACK) - { - if (RFAPI_REGISTER_ADD == action) - { - ++bgp->rfapi->stat.count_registrations_failed; - } - vnc_zlog_debug_verbose ("%s: in callback: returning EDEADLK", __func__); - return EDEADLK; - } - - if (!is_valid_rfd (rfd)) - { - if (RFAPI_REGISTER_ADD == action) - { - ++bgp->rfapi->stat.count_registrations_failed; - } - vnc_zlog_debug_verbose ("%s: invalid handle: returning EBADF", __func__); - return EBADF; - } - - /* - * Is there a MAC address in this registration? - */ - if (l2o && !RFAPI_0_ETHERADDR (&l2o->macaddr)) - { - rfapiL2o2Qprefix (l2o, &pfx_mac_buf); - pfx_mac = &pfx_mac_buf; - } - - /* - * Is there an IP prefix in this registration? - */ - if (!(RFAPI_0_PREFIX (&p) && RFAPI_HOST_PREFIX (&p))) - { - pfx_ip = &p; - } - else - { - if (!pfx_mac) - { - vnc_zlog_debug_verbose ("%s: missing mac addr that is required for host 0 pfx", - __func__); - if (RFAPI_REGISTER_ADD == action) - { - ++bgp->rfapi->stat.count_registrations_failed; - } - return EINVAL; - } - if (rfapiRaddr2Qprefix (&rfd->vn_addr, &pfx_vn_buf)) - { - vnc_zlog_debug_verbose ("%s: handle has bad vn_addr: returning EBADF", - __func__); - if (RFAPI_REGISTER_ADD == action) - { - ++bgp->rfapi->stat.count_registrations_failed; - } - return EBADF; - } - } - - if (RFAPI_REGISTER_ADD == action) - { - ++bgp->rfapi->stat.count_registrations; - } - - /* - * Figure out if this registration is missing an IP address - * - * MAC-addr based: - * - * In RFAPI, we use prefixes in family AF_LINK to store - * the MAC addresses. These prefixes are used for the - * list of advertised prefixes and in the RFAPI import - * tables. - * - * In BGP proper, we use the prefix matching the NVE's - * VN address with a host prefix-length (i.e., 32 or 128). - * - */ - if (l2o && l2o->logical_net_id && RFAPI_0_PREFIX (&p) && - RFAPI_HOST_PREFIX (&p)) - { - - rfapiL2o2Qprefix (l2o, &pfx_mac_buf); - pfx_mac = &pfx_mac_buf; - } - - /* - * Construct route distinguisher - */ - if (prd_override) - { - prd = *prd_override; - } - else - { - memset (&prd, 0, sizeof (prd)); - if (pfx_mac) - { - prd.family = AF_UNSPEC; - prd.prefixlen = 64; - encode_rd_type(RD_TYPE_VNC_ETH, prd.val); - if (l2o->local_nve_id || !(rfd->rfg->flags & RFAPI_RFG_L2RD)) - { - /* - * If Local NVE ID is specified in message, use it. - * (if no local default configured, also use it even if 0) - */ - prd.val[1] = l2o->local_nve_id; - } - else - { - if (rfd->rfg->l2rd) - { - /* - * locally-configured literal value - */ - prd.val[1] = rfd->rfg->l2rd; - } - else - { - /* - * 0 means auto:vn, which means use LSB of VN addr - */ - if (rfd->vn_addr.addr_family == AF_INET) - { - prd.val[1] = - *(((char *) &rfd->vn_addr.addr.v4.s_addr) + 3); - } - else - { - prd.val[1] = - *(((char *) &rfd->vn_addr.addr.v6.s6_addr) + 15); - } - } - } - memcpy (prd.val + 2, pfx_mac->u.prefix_eth.octet, 6); - } - else - { - prd = rfd->rd; - prd.family = AF_UNSPEC; - prd.prefixlen = 64; - } - } - - - if (action == RFAPI_REGISTER_WITHDRAW || action == RFAPI_REGISTER_KILL) - { - - int adv_tunnel = 0; - - /* - * withdraw previous advertisement - */ - del_vnc_route ( - rfd, - rfd->peer, - bgp, - SAFI_MPLS_VPN, - pfx_ip ? pfx_ip : &pfx_vn_buf, /* prefix being advertised */ - &prd, /* route distinguisher (0 for ENCAP) */ - ZEBRA_ROUTE_BGP, - BGP_ROUTE_RFP, - NULL, - action == RFAPI_REGISTER_KILL); - - if (0 == rfapiApDelete (bgp, rfd, &p, pfx_mac, &prd, &adv_tunnel)) - { - if (adv_tunnel) - rfapiTunnelRouteAnnounce (bgp, rfd, &rfd->max_prefix_lifetime); - } - - } - else - { - - int adv_tunnel = 0; - uint32_t local_pref; - struct ecommunity *rtlist = NULL; - struct ecommunity_val ecom_value; - - if (!rfapiApCount (rfd)) - { - /* - * make sure we advertise tunnel route upon adding the - * first VPN route - */ - adv_tunnel = 1; - } - - if (rfapiApAdd (bgp, rfd, &p, pfx_mac, &prd, lifetime, prefix->cost, - l2o)) - { - adv_tunnel = 1; - } - - vnc_zlog_debug_verbose ("%s: adv_tunnel = %d", __func__, adv_tunnel); - if (adv_tunnel) - { - vnc_zlog_debug_verbose ("%s: announcing tunnel route", __func__); - rfapiTunnelRouteAnnounce (bgp, rfd, &rfd->max_prefix_lifetime); - } - - vnc_zlog_debug_verbose ("%s: calling add_vnc_route", __func__); - - local_pref = rfp_cost_to_localpref (prefix->cost); - - if (l2o && l2o->label) - label = &l2o->label; - - if (pfx_mac) - { - struct ecommunity *l2com = NULL; - - if (label) - { - l2com = bgp_rfapi_get_ecommunity_by_lni_label (bgp, 1, - l2o->logical_net_id, - *label); - } - if (l2com) - { - rtlist = ecommunity_dup (l2com); - } - else - { - /* - * If mac address is set, add an RT based on the registered LNI - */ - memset ((char *) &ecom_value, 0, sizeof (ecom_value)); - ecom_value.val[1] = ECOMMUNITY_ROUTE_TARGET; - ecom_value.val[5] = (l2o->logical_net_id >> 16) & 0xff; - ecom_value.val[6] = (l2o->logical_net_id >> 8) & 0xff; - ecom_value.val[7] = (l2o->logical_net_id >> 0) & 0xff; - rtlist = ecommunity_new(); - ecommunity_add_val (rtlist, &ecom_value); - } - if (l2o->tag_id) - { - as_t as = bgp->as; - uint16_t val = l2o->tag_id; - memset ((char *) &ecom_value, 0, sizeof (ecom_value)); - ecom_value.val[1] = ECOMMUNITY_ROUTE_TARGET; - if (as > BGP_AS_MAX) - { - ecom_value.val[0] = ECOMMUNITY_ENCODE_AS4; - ecom_value.val[2] = (as >>24) & 0xff; - ecom_value.val[3] = (as >>16) & 0xff; - ecom_value.val[4] = (as >>8) & 0xff; - ecom_value.val[5] = as & 0xff; - } - else - { - ecom_value.val[0] = ECOMMUNITY_ENCODE_AS; - ecom_value.val[2] = (as >>8) & 0xff; - ecom_value.val[3] = as & 0xff; - } - ecom_value.val[6] = (val >> 8) & 0xff; - ecom_value.val[7] = val & 0xff; - if (rtlist == NULL) - rtlist = ecommunity_new(); - ecommunity_add_val (rtlist, &ecom_value); - } - } - - /* - * advertise prefix via tunnel endpoint - */ - add_vnc_route ( - rfd, /* rfapi descr, for export list & backref */ - bgp, /* which bgp instance */ - SAFI_MPLS_VPN, /* which SAFI */ - (pfx_ip ? pfx_ip : &pfx_vn_buf), /* prefix being advertised */ - &prd, /* route distinguisher to use (0 for ENCAP) */ - &rfd->vn_addr, /* nexthop */ - &local_pref, - &lifetime, /* prefix lifetime -> Tunnel Encap attr */ - NULL, - options_un, /* rfapi un options */ - options_vn, /* rfapi vn options */ - (rtlist ? rtlist : rfd->rt_export_list), - NULL, /* med */ - label, /* label: default */ - ZEBRA_ROUTE_BGP, - BGP_ROUTE_RFP, - 0); - - if (rtlist) - ecommunity_free (&rtlist); /* sets rtlist = NULL */ - } - - vnc_zlog_debug_verbose ("%s: success", __func__); - return 0; + struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle; + struct bgp *bgp; + struct prefix p; + struct prefix *pfx_ip = NULL; + struct prefix_rd prd; + int afi; + struct prefix pfx_mac_buf; + struct prefix *pfx_mac = NULL; + struct prefix pfx_vn_buf; + const char *action_str = NULL; + uint32_t *label = NULL; + struct rfapi_vn_option *vo; + struct rfapi_l2address_option *l2o = NULL; + struct prefix_rd *prd_override = NULL; + + switch (action) { + case RFAPI_REGISTER_ADD: + action_str = "add"; + break; + case RFAPI_REGISTER_WITHDRAW: + action_str = "withdraw"; + break; + case RFAPI_REGISTER_KILL: + action_str = "kill"; + break; + default: + assert(0); + break; + } + + /* + * Inspect VN options + */ + for (vo = options_vn; vo; vo = vo->next) { + if (RFAPI_VN_OPTION_TYPE_L2ADDR == vo->type) { + l2o = &vo->v.l2addr; + } + if (RFAPI_VN_OPTION_TYPE_INTERNAL_RD == vo->type) { + prd_override = &vo->v.internal_rd; + } + } + + /********************************************************************* + * advertise prefix + *********************************************************************/ + + /* + * set

based on + */ + assert(!rfapiRprefix2Qprefix(prefix, &p)); + + afi = family2afi(prefix->prefix.addr_family); + assert(afi); + + + { + char buf[BUFSIZ]; + + prefix2str(&p, buf, BUFSIZ); + buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */ + vnc_zlog_debug_verbose( + "%s(rfd=%p, pfx=%s, lifetime=%d, opts_un=%p, opts_vn=%p, action=%s)", + __func__, rfd, buf, lifetime, options_un, options_vn, + action_str); + } + + /* + * These tests come after the prefix conversion so that we can + * print the prefix in a debug message before failing + */ + + bgp = rfd->bgp; + if (!bgp) { + vnc_zlog_debug_verbose("%s: no BGP instance: returning ENXIO", + __func__); + return ENXIO; + } + if (!bgp->rfapi) { + vnc_zlog_debug_verbose("%s: no RFAPI instance: returning ENXIO", + __func__); + return ENXIO; + } + if (!rfd->rfg) { + if (RFAPI_REGISTER_ADD == action) { + ++bgp->rfapi->stat.count_registrations_failed; + } + vnc_zlog_debug_verbose( + "%s: rfd=%p, no RF GRP instance: returning ESTALE", + __func__, rfd); + return ESTALE; + } + + if (bgp->rfapi->flags & RFAPI_INCALLBACK) { + if (RFAPI_REGISTER_ADD == action) { + ++bgp->rfapi->stat.count_registrations_failed; + } + vnc_zlog_debug_verbose("%s: in callback: returning EDEADLK", + __func__); + return EDEADLK; + } + + if (!is_valid_rfd(rfd)) { + if (RFAPI_REGISTER_ADD == action) { + ++bgp->rfapi->stat.count_registrations_failed; + } + vnc_zlog_debug_verbose("%s: invalid handle: returning EBADF", + __func__); + return EBADF; + } + + /* + * Is there a MAC address in this registration? + */ + if (l2o && !RFAPI_0_ETHERADDR(&l2o->macaddr)) { + rfapiL2o2Qprefix(l2o, &pfx_mac_buf); + pfx_mac = &pfx_mac_buf; + } + + /* + * Is there an IP prefix in this registration? + */ + if (!(RFAPI_0_PREFIX(&p) && RFAPI_HOST_PREFIX(&p))) { + pfx_ip = &p; + } else { + if (!pfx_mac) { + vnc_zlog_debug_verbose( + "%s: missing mac addr that is required for host 0 pfx", + __func__); + if (RFAPI_REGISTER_ADD == action) { + ++bgp->rfapi->stat.count_registrations_failed; + } + return EINVAL; + } + if (rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx_vn_buf)) { + vnc_zlog_debug_verbose( + "%s: handle has bad vn_addr: returning EBADF", + __func__); + if (RFAPI_REGISTER_ADD == action) { + ++bgp->rfapi->stat.count_registrations_failed; + } + return EBADF; + } + } + + if (RFAPI_REGISTER_ADD == action) { + ++bgp->rfapi->stat.count_registrations; + } + + /* + * Figure out if this registration is missing an IP address + * + * MAC-addr based: + * + * In RFAPI, we use prefixes in family AF_LINK to store + * the MAC addresses. These prefixes are used for the + * list of advertised prefixes and in the RFAPI import + * tables. + * + * In BGP proper, we use the prefix matching the NVE's + * VN address with a host prefix-length (i.e., 32 or 128). + * + */ + if (l2o && l2o->logical_net_id && RFAPI_0_PREFIX(&p) + && RFAPI_HOST_PREFIX(&p)) { + + rfapiL2o2Qprefix(l2o, &pfx_mac_buf); + pfx_mac = &pfx_mac_buf; + } + + /* + * Construct route distinguisher + */ + if (prd_override) { + prd = *prd_override; + } else { + memset(&prd, 0, sizeof(prd)); + if (pfx_mac) { + prd.family = AF_UNSPEC; + prd.prefixlen = 64; + encode_rd_type(RD_TYPE_VNC_ETH, prd.val); + if (l2o->local_nve_id + || !(rfd->rfg->flags & RFAPI_RFG_L2RD)) { + /* + * If Local NVE ID is specified in message, use + * it. + * (if no local default configured, also use it + * even if 0) + */ + prd.val[1] = l2o->local_nve_id; + } else { + if (rfd->rfg->l2rd) { + /* + * locally-configured literal value + */ + prd.val[1] = rfd->rfg->l2rd; + } else { + /* + * 0 means auto:vn, which means use LSB + * of VN addr + */ + if (rfd->vn_addr.addr_family + == AF_INET) { + prd.val[1] = + *(((char *)&rfd->vn_addr + .addr.v4 + .s_addr) + + 3); + } else { + prd.val[1] = + *(((char *)&rfd->vn_addr + .addr.v6 + .s6_addr) + + 15); + } + } + } + memcpy(prd.val + 2, pfx_mac->u.prefix_eth.octet, 6); + } else { + prd = rfd->rd; + prd.family = AF_UNSPEC; + prd.prefixlen = 64; + } + } + + + if (action == RFAPI_REGISTER_WITHDRAW + || action == RFAPI_REGISTER_KILL) { + + int adv_tunnel = 0; + + /* + * withdraw previous advertisement + */ + del_vnc_route( + rfd, rfd->peer, bgp, SAFI_MPLS_VPN, + pfx_ip ? pfx_ip + : &pfx_vn_buf, /* prefix being advertised */ + &prd, /* route distinguisher (0 for ENCAP) */ + ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, NULL, + action == RFAPI_REGISTER_KILL); + + if (0 == rfapiApDelete(bgp, rfd, &p, pfx_mac, &prd, + &adv_tunnel)) { + if (adv_tunnel) + rfapiTunnelRouteAnnounce( + bgp, rfd, &rfd->max_prefix_lifetime); + } + + } else { + + int adv_tunnel = 0; + uint32_t local_pref; + struct ecommunity *rtlist = NULL; + struct ecommunity_val ecom_value; + + if (!rfapiApCount(rfd)) { + /* + * make sure we advertise tunnel route upon adding the + * first VPN route + */ + adv_tunnel = 1; + } + + if (rfapiApAdd(bgp, rfd, &p, pfx_mac, &prd, lifetime, + prefix->cost, l2o)) { + adv_tunnel = 1; + } + + vnc_zlog_debug_verbose("%s: adv_tunnel = %d", __func__, + adv_tunnel); + if (adv_tunnel) { + vnc_zlog_debug_verbose("%s: announcing tunnel route", + __func__); + rfapiTunnelRouteAnnounce(bgp, rfd, + &rfd->max_prefix_lifetime); + } + + vnc_zlog_debug_verbose("%s: calling add_vnc_route", __func__); + + local_pref = rfp_cost_to_localpref(prefix->cost); + + if (l2o && l2o->label) + label = &l2o->label; + + if (pfx_mac) { + struct ecommunity *l2com = NULL; + + if (label) { + l2com = bgp_rfapi_get_ecommunity_by_lni_label( + bgp, 1, l2o->logical_net_id, *label); + } + if (l2com) { + rtlist = ecommunity_dup(l2com); + } else { + /* + * If mac address is set, add an RT based on the + * registered LNI + */ + memset((char *)&ecom_value, 0, + sizeof(ecom_value)); + ecom_value.val[1] = ECOMMUNITY_ROUTE_TARGET; + ecom_value.val[5] = + (l2o->logical_net_id >> 16) & 0xff; + ecom_value.val[6] = + (l2o->logical_net_id >> 8) & 0xff; + ecom_value.val[7] = + (l2o->logical_net_id >> 0) & 0xff; + rtlist = ecommunity_new(); + ecommunity_add_val(rtlist, &ecom_value); + } + if (l2o->tag_id) { + as_t as = bgp->as; + uint16_t val = l2o->tag_id; + memset((char *)&ecom_value, 0, + sizeof(ecom_value)); + ecom_value.val[1] = ECOMMUNITY_ROUTE_TARGET; + if (as > BGP_AS_MAX) { + ecom_value.val[0] = + ECOMMUNITY_ENCODE_AS4; + ecom_value.val[2] = (as >> 24) & 0xff; + ecom_value.val[3] = (as >> 16) & 0xff; + ecom_value.val[4] = (as >> 8) & 0xff; + ecom_value.val[5] = as & 0xff; + } else { + ecom_value.val[0] = + ECOMMUNITY_ENCODE_AS; + ecom_value.val[2] = (as >> 8) & 0xff; + ecom_value.val[3] = as & 0xff; + } + ecom_value.val[6] = (val >> 8) & 0xff; + ecom_value.val[7] = val & 0xff; + if (rtlist == NULL) + rtlist = ecommunity_new(); + ecommunity_add_val(rtlist, &ecom_value); + } + } + + /* + * advertise prefix via tunnel endpoint + */ + add_vnc_route( + rfd, /* rfapi descr, for export list & backref */ + bgp, /* which bgp instance */ + SAFI_MPLS_VPN, /* which SAFI */ + (pfx_ip ? pfx_ip + : &pfx_vn_buf), /* prefix being advertised */ + &prd, /* route distinguisher to use (0 for ENCAP) */ + &rfd->vn_addr, /* nexthop */ + &local_pref, + &lifetime, /* prefix lifetime -> Tunnel Encap attr */ + NULL, options_un, /* rfapi un options */ + options_vn, /* rfapi vn options */ + (rtlist ? rtlist : rfd->rt_export_list), NULL, /* med */ + label, /* label: default */ + ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, 0); + + if (rtlist) + ecommunity_free(&rtlist); /* sets rtlist = NULL */ + } + + vnc_zlog_debug_verbose("%s: success", __func__); + return 0; } -int -rfapi_query ( - void *handle, - struct rfapi_ip_addr *target, - struct rfapi_l2address_option *l2o, /* may be NULL */ - struct rfapi_next_hop_entry **ppNextHopEntry) +int rfapi_query(void *handle, struct rfapi_ip_addr *target, + struct rfapi_l2address_option *l2o, /* may be NULL */ + struct rfapi_next_hop_entry **ppNextHopEntry) { - struct rfapi_descriptor *rfd = (struct rfapi_descriptor *) handle; - struct bgp *bgp = rfd->bgp; - int rc; - - assert (ppNextHopEntry); - *ppNextHopEntry = NULL; - - if (bgp && bgp->rfapi) - { - bgp->rfapi->stat.count_queries++; - } - - if (!rfd->rfg) - { - if (bgp && bgp->rfapi) - ++bgp->rfapi->stat.count_queries_failed; - return ESTALE; - } - - if ((rc = rfapi_query_inner (handle, target, l2o, ppNextHopEntry))) - { - if (bgp && bgp->rfapi) - ++bgp->rfapi->stat.count_queries_failed; - } - return rc; + struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle; + struct bgp *bgp = rfd->bgp; + int rc; + + assert(ppNextHopEntry); + *ppNextHopEntry = NULL; + + if (bgp && bgp->rfapi) { + bgp->rfapi->stat.count_queries++; + } + + if (!rfd->rfg) { + if (bgp && bgp->rfapi) + ++bgp->rfapi->stat.count_queries_failed; + return ESTALE; + } + + if ((rc = rfapi_query_inner(handle, target, l2o, ppNextHopEntry))) { + if (bgp && bgp->rfapi) + ++bgp->rfapi->stat.count_queries_failed; + } + return rc; } -int -rfapi_query_done (rfapi_handle handle, struct rfapi_ip_addr *target) +int rfapi_query_done(rfapi_handle handle, struct rfapi_ip_addr *target) { - struct prefix p; - int rc; - struct rfapi_descriptor *rfd = (struct rfapi_descriptor *) handle; - struct bgp *bgp = rfd->bgp; + struct prefix p; + int rc; + struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle; + struct bgp *bgp = rfd->bgp; - if (!rfd->rfg) - return ESTALE; + if (!rfd->rfg) + return ESTALE; - assert (target); - rc = rfapiRaddr2Qprefix (target, &p); - assert (!rc); + assert(target); + rc = rfapiRaddr2Qprefix(target, &p); + assert(!rc); - if (!is_valid_rfd (rfd)) - return EBADF; + if (!is_valid_rfd(rfd)) + return EBADF; - /* preemptive */ - if (!bgp || !bgp->rfapi) - return ENXIO; + /* preemptive */ + if (!bgp || !bgp->rfapi) + return ENXIO; - if (bgp->rfapi->flags & RFAPI_INCALLBACK) - return EDEADLK; + if (bgp->rfapi->flags & RFAPI_INCALLBACK) + return EDEADLK; - rfapiMonitorDel (bgp, rfd, &p); + rfapiMonitorDel(bgp, rfd, &p); - return 0; + return 0; } -int -rfapi_query_done_all (rfapi_handle handle, int *count) +int rfapi_query_done_all(rfapi_handle handle, int *count) { - struct rfapi_descriptor *rfd = (struct rfapi_descriptor *) handle; - struct bgp *bgp = rfd->bgp;; - int num; + struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle; + struct bgp *bgp = rfd->bgp; + ; + int num; - if (!rfd->rfg) - return ESTALE; + if (!rfd->rfg) + return ESTALE; - if (!is_valid_rfd (rfd)) - return EBADF; + if (!is_valid_rfd(rfd)) + return EBADF; - /* preemptive */ - if (!bgp || !bgp->rfapi) - return ENXIO; + /* preemptive */ + if (!bgp || !bgp->rfapi) + return ENXIO; - if (bgp->rfapi->flags & RFAPI_INCALLBACK) - return EDEADLK; + if (bgp->rfapi->flags & RFAPI_INCALLBACK) + return EDEADLK; - num = rfapiMonitorDelHd (rfd); + num = rfapiMonitorDelHd(rfd); - if (count) - *count = num; + if (count) + *count = num; - return 0; + return 0; } -void -rfapi_free_next_hop_list (struct rfapi_next_hop_entry *list) +void rfapi_free_next_hop_list(struct rfapi_next_hop_entry *list) { - struct rfapi_next_hop_entry *nh; - struct rfapi_next_hop_entry *next; - - for (nh = list; nh; nh = next) - { - next = nh->next; - rfapi_un_options_free (nh->un_options); - nh->un_options = NULL; - rfapi_vn_options_free (nh->vn_options); - nh->vn_options = NULL; - XFREE (MTYPE_RFAPI_NEXTHOP, nh); - } + struct rfapi_next_hop_entry *nh; + struct rfapi_next_hop_entry *next; + + for (nh = list; nh; nh = next) { + next = nh->next; + rfapi_un_options_free(nh->un_options); + nh->un_options = NULL; + rfapi_vn_options_free(nh->vn_options); + nh->vn_options = NULL; + XFREE(MTYPE_RFAPI_NEXTHOP, nh); + } } /* * NULL handle => return total count across all nves */ -uint32_t -rfapi_monitor_count (void *handle) +uint32_t rfapi_monitor_count(void *handle) { - struct bgp *bgp = bgp_get_default (); - uint32_t count; + struct bgp *bgp = bgp_get_default(); + uint32_t count; - if (handle) - { - struct rfapi_descriptor *rfd = (struct rfapi_descriptor *) handle; - count = rfd->monitor_count; - } - else - { + if (handle) { + struct rfapi_descriptor *rfd = + (struct rfapi_descriptor *)handle; + count = rfd->monitor_count; + } else { - if (!bgp || !bgp->rfapi) - return 0; + if (!bgp || !bgp->rfapi) + return 0; - count = bgp->rfapi->monitor_count; - } + count = bgp->rfapi->monitor_count; + } - return count; + return count; } /*********************************************************************** @@ -3077,8 +2861,8 @@ DEFUN (debug_rfapi_show_nves, SHOW_STR "NVE Information\n") { - rfapiPrintMatchingDescriptors (vty, NULL, NULL); - return CMD_SUCCESS; + rfapiPrintMatchingDescriptors(vty, NULL, NULL); + return CMD_SUCCESS; } DEFUN ( @@ -3094,28 +2878,23 @@ DEFUN ( "IPv4 address\n" "IPv6 address\n") { - struct prefix pfx; - - if (!str2prefix (argv[5]->arg, &pfx)) - { - vty_out (vty, "Malformed address \"%s\"\n", argv[5]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - if (pfx.family != AF_INET && pfx.family != AF_INET6) - { - vty_out (vty, "Invalid address \"%s\"\n", argv[5]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - - if (argv[4]->arg[0] == 'u') - { - rfapiPrintMatchingDescriptors (vty, NULL, &pfx); - } - else - { - rfapiPrintMatchingDescriptors (vty, &pfx, NULL); - } - return CMD_SUCCESS; + struct prefix pfx; + + if (!str2prefix(argv[5]->arg, &pfx)) { + vty_out(vty, "Malformed address \"%s\"\n", argv[5]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + if (pfx.family != AF_INET && pfx.family != AF_INET6) { + vty_out(vty, "Invalid address \"%s\"\n", argv[5]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + + if (argv[4]->arg[0] == 'u') { + rfapiPrintMatchingDescriptors(vty, NULL, &pfx); + } else { + rfapiPrintMatchingDescriptors(vty, &pfx, NULL); + } + return CMD_SUCCESS; } /* @@ -3123,29 +2902,27 @@ DEFUN ( * with a stream pointing to a vty, the user will have to type something * before the callback output shows up */ -static void -test_nexthops_callback ( -// struct rfapi_ip_addr *target, - struct rfapi_next_hop_entry *next_hops, - void *userdata) +static void test_nexthops_callback( + // struct rfapi_ip_addr *target, + struct rfapi_next_hop_entry *next_hops, void *userdata) { - void *stream = userdata; + void *stream = userdata; - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; - fp (out, "Nexthops Callback, Target=("); - //rfapiPrintRfapiIpAddr(stream, target); - fp (out, ")\n"); + fp(out, "Nexthops Callback, Target=("); + // rfapiPrintRfapiIpAddr(stream, target); + fp(out, ")\n"); - rfapiPrintNhl (stream, next_hops); + rfapiPrintNhl(stream, next_hops); - rfapi_free_next_hop_list (next_hops); + rfapi_free_next_hop_list(next_hops); } DEFUN (debug_rfapi_open, @@ -3161,35 +2938,35 @@ DEFUN (debug_rfapi_open, "underlay network interface IPv4 address\n" "underlay network interface IPv6 address\n") { - struct rfapi_ip_addr vn; - struct rfapi_ip_addr un; - uint32_t lifetime; - int rc; - rfapi_handle handle; + struct rfapi_ip_addr vn; + struct rfapi_ip_addr un; + uint32_t lifetime; + int rc; + rfapi_handle handle; - /* - * Get VN addr - */ - if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[4]->arg, &vn))) - return rc; + /* + * Get VN addr + */ + if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn))) + return rc; - /* - * Get UN addr - */ - if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[6]->arg, &un))) - return rc; + /* + * Get UN addr + */ + if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un))) + return rc; - rc = rfapi_open (rfapi_get_rfp_start_val_by_bgp (bgp_get_default ()), - &vn, &un, /*&uo */ NULL, &lifetime, NULL, &handle); + rc = rfapi_open(rfapi_get_rfp_start_val_by_bgp(bgp_get_default()), &vn, + &un, /*&uo */ NULL, &lifetime, NULL, &handle); - vty_out (vty, "rfapi_open: status %d, handle %p, lifetime %d\n", - rc, handle, lifetime); + vty_out(vty, "rfapi_open: status %d, handle %p, lifetime %d\n", rc, + handle, lifetime); - rc = rfapi_set_response_cb (handle, test_nexthops_callback); + rc = rfapi_set_response_cb(handle, test_nexthops_callback); - vty_out (vty, "rfapi_set_response_cb: status %d\n", rc); + vty_out(vty, "rfapi_set_response_cb: status %d\n", rc); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -3206,37 +2983,36 @@ DEFUN (debug_rfapi_close_vn_un, "underlay network interface IPv4 address\n" "underlay network interface IPv6 address\n") { - struct rfapi_ip_addr vn; - struct rfapi_ip_addr un; - rfapi_handle handle; - int rc; + struct rfapi_ip_addr vn; + struct rfapi_ip_addr un; + rfapi_handle handle; + int rc; - /* - * Get VN addr - */ - if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[4]->arg, &vn))) - return rc; + /* + * Get VN addr + */ + if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn))) + return rc; - /* - * Get UN addr - */ - if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[6]->arg, &un))) - return rc; + /* + * Get UN addr + */ + if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un))) + return rc; - if (rfapi_find_handle_vty (vty, &vn, &un, &handle)) - { - vty_out (vty, "can't locate handle matching vn=%s, un=%s\n", - argv[4]->arg, argv[6]->arg); - return CMD_WARNING_CONFIG_FAILED; - } + if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) { + vty_out(vty, "can't locate handle matching vn=%s, un=%s\n", + argv[4]->arg, argv[6]->arg); + return CMD_WARNING_CONFIG_FAILED; + } - rc = rfapi_close (handle); + rc = rfapi_close(handle); - vty_out (vty, "rfapi_close(handle=%p): status %d\n", handle,rc); + vty_out(vty, "rfapi_close(handle=%p): status %d\n", handle, rc); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_rfapi_close_rfd, @@ -3247,23 +3023,22 @@ DEFUN (debug_rfapi_close_rfd, "rfapi_close\n" "indicate handle follows\n" "rfapi handle in hexadecimal\n") { - rfapi_handle handle; - int rc; - char *endptr = NULL; + rfapi_handle handle; + int rc; + char *endptr = NULL; - handle = (rfapi_handle) (uintptr_t) (strtoull (argv[4]->arg, &endptr, 16)); + handle = (rfapi_handle)(uintptr_t)(strtoull(argv[4]->arg, &endptr, 16)); - if (*endptr != '\0' || (uintptr_t) handle == UINTPTR_MAX) - { - vty_out (vty, "Invalid value: %s\n", argv[4]->arg); - return CMD_WARNING_CONFIG_FAILED; - } + if (*endptr != '\0' || (uintptr_t)handle == UINTPTR_MAX) { + vty_out(vty, "Invalid value: %s\n", argv[4]->arg); + return CMD_WARNING_CONFIG_FAILED; + } - rc = rfapi_close (handle); + rc = rfapi_close(handle); - vty_out (vty, "rfapi_close(handle=%p): status %d\n", handle,rc); + vty_out(vty, "rfapi_close(handle=%p): status %d\n", handle, rc); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_rfapi_register_vn_un, @@ -3275,77 +3050,70 @@ DEFUN (debug_rfapi_register_vn_un, "indicate vn addr follows\n" "virtual network IPv4 interface address\n" "virtual network IPv6 interface address\n" - "indicate un addr follows\n" - "underlay network IPv4 interface address\n" - "underlay network IPv6 interface address\n" - "indicate prefix follows\n" - "IPv4 prefix\n" - "IPv6 prefix\n" - "indicate lifetime follows\n" - "lifetime\n") -{ - struct rfapi_ip_addr vn; - struct rfapi_ip_addr un; - rfapi_handle handle; - struct prefix pfx; - uint32_t lifetime; - struct rfapi_ip_prefix hpfx; - int rc; - - /* - * Get VN addr - */ - if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[4]->arg, &vn))) - return rc; - - - /* - * Get UN addr - */ - if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[6]->arg, &un))) - return rc; - - - if (rfapi_find_handle_vty (vty, &vn, &un, &handle)) - { - vty_out (vty, "can't locate handle matching vn=%s, un=%s\n", - argv[4]->arg, argv[6]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - - /* - * Get prefix to advertise - */ - if (!str2prefix (argv[8]->arg, &pfx)) - { - vty_out (vty, "Malformed prefix \"%s\"\n", argv[8]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - if (pfx.family != AF_INET && pfx.family != AF_INET6) - { - vty_out (vty, "Bad family for prefix \"%s\"\n", argv[8]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - rfapiQprefix2Rprefix (&pfx, &hpfx); - - if (strmatch(argv[10]->text, "infinite")) - { - lifetime = RFAPI_INFINITE_LIFETIME; - } - else - { - lifetime = strtoul(argv[10]->arg, NULL, 10); - } - - - rc = rfapi_register (handle, &hpfx, lifetime, NULL, NULL, 0); - if (rc) - { - vty_out (vty, "rfapi_register failed with rc=%d (%s)\n", rc, - strerror(rc)); - } - - return CMD_SUCCESS; + "indicate un addr follows\n" + "underlay network IPv4 interface address\n" + "underlay network IPv6 interface address\n" + "indicate prefix follows\n" + "IPv4 prefix\n" + "IPv6 prefix\n" + "indicate lifetime follows\n" + "lifetime\n") +{ + struct rfapi_ip_addr vn; + struct rfapi_ip_addr un; + rfapi_handle handle; + struct prefix pfx; + uint32_t lifetime; + struct rfapi_ip_prefix hpfx; + int rc; + + /* + * Get VN addr + */ + if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn))) + return rc; + + + /* + * Get UN addr + */ + if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un))) + return rc; + + + if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) { + vty_out(vty, "can't locate handle matching vn=%s, un=%s\n", + argv[4]->arg, argv[6]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + + /* + * Get prefix to advertise + */ + if (!str2prefix(argv[8]->arg, &pfx)) { + vty_out(vty, "Malformed prefix \"%s\"\n", argv[8]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + if (pfx.family != AF_INET && pfx.family != AF_INET6) { + vty_out(vty, "Bad family for prefix \"%s\"\n", argv[8]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + rfapiQprefix2Rprefix(&pfx, &hpfx); + + if (strmatch(argv[10]->text, "infinite")) { + lifetime = RFAPI_INFINITE_LIFETIME; + } else { + lifetime = strtoul(argv[10]->arg, NULL, 10); + } + + + rc = rfapi_register(handle, &hpfx, lifetime, NULL, NULL, 0); + if (rc) { + vty_out(vty, "rfapi_register failed with rc=%d (%s)\n", rc, + strerror(rc)); + } + + return CMD_SUCCESS; } DEFUN (debug_rfapi_register_vn_un_l2o, @@ -3370,91 +3138,82 @@ DEFUN (debug_rfapi_register_vn_un_l2o, "indicate lni follows\n" "lni value range\n") { - struct rfapi_ip_addr vn; - struct rfapi_ip_addr un; - rfapi_handle handle; - struct prefix pfx; - uint32_t lifetime; - struct rfapi_ip_prefix hpfx; - int rc; - struct rfapi_vn_option optary[10]; /* XXX must be big enough */ - struct rfapi_vn_option *opt = NULL; - int opt_next = 0; - - /* - * Get VN addr - */ - if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[4]->arg, &vn))) - return rc; - - - /* - * Get UN addr - */ - if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[6]->arg, &un))) - return rc; - - - if (rfapi_find_handle_vty (vty, &vn, &un, &handle)) - { - vty_out (vty, "can't locate handle matching vn=%s, un=%s\n", - argv[4]->arg, argv[6]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - - /* - * Get prefix to advertise - */ - if (!str2prefix (argv[8]->arg, &pfx)) - { - vty_out (vty, "Malformed prefix \"%s\"\n", argv[8]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - if (pfx.family != AF_INET && pfx.family != AF_INET6) - { - vty_out (vty, "Bad family for prefix \"%s\"\n", argv[8]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - rfapiQprefix2Rprefix (&pfx, &hpfx); - - if (strmatch(argv[10]->text, "infinite")) - { - lifetime = RFAPI_INFINITE_LIFETIME; - } - else - { - lifetime = strtoul(argv[10]->arg, NULL, 10); - } - - /* L2 option parsing START */ - memset (optary, 0, sizeof (optary)); - optary[opt_next].v.l2addr.logical_net_id = strtoul(argv[14]->arg, NULL, 10); - if ((rc = rfapiStr2EthAddr (argv[12]->arg, &optary[opt_next].v.l2addr.macaddr))) - { - vty_out (vty, "Bad mac address \"%s\"\n", argv[12]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - optary[opt_next].type = RFAPI_VN_OPTION_TYPE_L2ADDR; - if (opt_next) - { - optary[opt_next - 1].next = optary + opt_next; - } - else - { - opt = optary; - } - ++opt_next; - /* L2 option parsing END */ - - /* TBD fixme */ - rc = rfapi_register (handle, &hpfx, lifetime, NULL /* &uo */ , opt, 0); - if (rc) - { - vty_out (vty, "rfapi_register failed with rc=%d (%s)\n", rc, - strerror(rc)); - } - - return CMD_SUCCESS; + struct rfapi_ip_addr vn; + struct rfapi_ip_addr un; + rfapi_handle handle; + struct prefix pfx; + uint32_t lifetime; + struct rfapi_ip_prefix hpfx; + int rc; + struct rfapi_vn_option optary[10]; /* XXX must be big enough */ + struct rfapi_vn_option *opt = NULL; + int opt_next = 0; + + /* + * Get VN addr + */ + if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn))) + return rc; + + + /* + * Get UN addr + */ + if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un))) + return rc; + + + if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) { + vty_out(vty, "can't locate handle matching vn=%s, un=%s\n", + argv[4]->arg, argv[6]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + + /* + * Get prefix to advertise + */ + if (!str2prefix(argv[8]->arg, &pfx)) { + vty_out(vty, "Malformed prefix \"%s\"\n", argv[8]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + if (pfx.family != AF_INET && pfx.family != AF_INET6) { + vty_out(vty, "Bad family for prefix \"%s\"\n", argv[8]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + rfapiQprefix2Rprefix(&pfx, &hpfx); + + if (strmatch(argv[10]->text, "infinite")) { + lifetime = RFAPI_INFINITE_LIFETIME; + } else { + lifetime = strtoul(argv[10]->arg, NULL, 10); + } + + /* L2 option parsing START */ + memset(optary, 0, sizeof(optary)); + optary[opt_next].v.l2addr.logical_net_id = + strtoul(argv[14]->arg, NULL, 10); + if ((rc = rfapiStr2EthAddr(argv[12]->arg, + &optary[opt_next].v.l2addr.macaddr))) { + vty_out(vty, "Bad mac address \"%s\"\n", argv[12]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + optary[opt_next].type = RFAPI_VN_OPTION_TYPE_L2ADDR; + if (opt_next) { + optary[opt_next - 1].next = optary + opt_next; + } else { + opt = optary; + } + ++opt_next; + /* L2 option parsing END */ + + /* TBD fixme */ + rc = rfapi_register(handle, &hpfx, lifetime, NULL /* &uo */, opt, 0); + if (rc) { + vty_out(vty, "rfapi_register failed with rc=%d (%s)\n", rc, + strerror(rc)); + } + + return CMD_SUCCESS; } @@ -3470,52 +3229,49 @@ DEFUN (debug_rfapi_unregister_vn_un, "underlay network interface address\n" "indicate prefix follows\n" "prefix") { - struct rfapi_ip_addr vn; - struct rfapi_ip_addr un; - rfapi_handle handle; - struct prefix pfx; - struct rfapi_ip_prefix hpfx; - int rc; - - /* - * Get VN addr - */ - if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[4]->arg, &vn))) - return rc; - - - /* - * Get UN addr - */ - if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[6]->arg, &un))) - return rc; - - - if (rfapi_find_handle_vty (vty, &vn, &un, &handle)) - { - vty_out (vty, "can't locate handle matching vn=%s, un=%s\n", - argv[4]->arg, argv[6]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - - /* - * Get prefix to advertise - */ - if (!str2prefix (argv[8]->arg, &pfx)) - { - vty_out (vty, "Malformed prefix \"%s\"\n", argv[8]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - if (pfx.family != AF_INET && pfx.family != AF_INET6) - { - vty_out (vty, "Bad family for prefix \"%s\"\n", argv[8]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - rfapiQprefix2Rprefix (&pfx, &hpfx); - - rfapi_register (handle, &hpfx, 0, NULL, NULL, 1); - - return CMD_SUCCESS; + struct rfapi_ip_addr vn; + struct rfapi_ip_addr un; + rfapi_handle handle; + struct prefix pfx; + struct rfapi_ip_prefix hpfx; + int rc; + + /* + * Get VN addr + */ + if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn))) + return rc; + + + /* + * Get UN addr + */ + if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un))) + return rc; + + + if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) { + vty_out(vty, "can't locate handle matching vn=%s, un=%s\n", + argv[4]->arg, argv[6]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + + /* + * Get prefix to advertise + */ + if (!str2prefix(argv[8]->arg, &pfx)) { + vty_out(vty, "Malformed prefix \"%s\"\n", argv[8]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + if (pfx.family != AF_INET && pfx.family != AF_INET6) { + vty_out(vty, "Bad family for prefix \"%s\"\n", argv[8]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + rfapiQprefix2Rprefix(&pfx, &hpfx); + + rfapi_register(handle, &hpfx, 0, NULL, NULL, 1); + + return CMD_SUCCESS; } DEFUN (debug_rfapi_query_vn_un, @@ -3534,60 +3290,57 @@ DEFUN (debug_rfapi_query_vn_un, "target IPv4 address\n" "target IPv6 address\n") { - struct rfapi_ip_addr vn; - struct rfapi_ip_addr un; - struct rfapi_ip_addr target; - rfapi_handle handle; - int rc; - struct rfapi_next_hop_entry *pNextHopEntry; - - /* - * Get VN addr - */ - if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[4]->arg, &vn))) - return rc; - - - /* - * Get UN addr - */ - if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[6]->arg, &un))) - return rc; - - - /* - * Get target addr - */ - if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[8]->arg, &target))) - return rc; - - - if (rfapi_find_handle_vty (vty, &vn, &un, &handle)) - { - vty_out (vty, "can't locate handle matching vn=%s, un=%s\n", - argv[4]->arg, argv[6]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - - /* - * options parameter not used? Set to NULL for now - */ - rc = rfapi_query (handle, &target, NULL, &pNextHopEntry); - - if (rc) - { - vty_out (vty, "rfapi_query failed with rc=%d (%s)\n", rc, - strerror(rc)); - } - else - { - /* - * print nexthop list - */ - test_nexthops_callback ( /*&target, */ pNextHopEntry, vty); /* frees nh list! */ - } - - return CMD_SUCCESS; + struct rfapi_ip_addr vn; + struct rfapi_ip_addr un; + struct rfapi_ip_addr target; + rfapi_handle handle; + int rc; + struct rfapi_next_hop_entry *pNextHopEntry; + + /* + * Get VN addr + */ + if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn))) + return rc; + + + /* + * Get UN addr + */ + if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un))) + return rc; + + + /* + * Get target addr + */ + if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[8]->arg, &target))) + return rc; + + + if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) { + vty_out(vty, "can't locate handle matching vn=%s, un=%s\n", + argv[4]->arg, argv[6]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + + /* + * options parameter not used? Set to NULL for now + */ + rc = rfapi_query(handle, &target, NULL, &pNextHopEntry); + + if (rc) { + vty_out(vty, "rfapi_query failed with rc=%d (%s)\n", rc, + strerror(rc)); + } else { + /* + * print nexthop list + */ + test_nexthops_callback(/*&target, */ pNextHopEntry, + vty); /* frees nh list! */ + } + + return CMD_SUCCESS; } @@ -3608,28 +3361,28 @@ DEFUN (debug_rfapi_query_vn_un_l2o, "indicate target MAC addr follows\n" "target MAC addr\n") { - struct rfapi_ip_addr vn; - struct rfapi_ip_addr un; - struct rfapi_ip_addr target; - rfapi_handle handle; - int rc; - struct rfapi_next_hop_entry *pNextHopEntry; - struct rfapi_l2address_option l2o_buf; - struct bgp_tea_options hopt; - uint8_t valbuf[14]; - - /* - * Get VN addr - */ - if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[4]->arg, &vn))) - return rc; - - - /* - * Get UN addr - */ - if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[6]->arg, &un))) - return rc; + struct rfapi_ip_addr vn; + struct rfapi_ip_addr un; + struct rfapi_ip_addr target; + rfapi_handle handle; + int rc; + struct rfapi_next_hop_entry *pNextHopEntry; + struct rfapi_l2address_option l2o_buf; + struct bgp_tea_options hopt; + uint8_t valbuf[14]; + + /* + * Get VN addr + */ + if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn))) + return rc; + + + /* + * Get UN addr + */ + if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un))) + return rc; #if 0 /* there is no IP target arg here ?????? */ @@ -3639,65 +3392,61 @@ DEFUN (debug_rfapi_query_vn_un_l2o, if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[2], &target))) return rc; #else - vty_out (vty, "%% This command is broken.\n"); - return CMD_WARNING_CONFIG_FAILED; + vty_out(vty, "%% This command is broken.\n"); + return CMD_WARNING_CONFIG_FAILED; #endif - if (rfapi_find_handle_vty (vty, &vn, &un, &handle)) - { - vty_out (vty, "can't locate handle matching vn=%s, un=%s\n", - argv[4]->arg, argv[6]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - - /* - * Set up L2 parameters - */ - memset (&l2o_buf, 0, sizeof (l2o_buf)); - if (rfapiStr2EthAddr (argv[10]->arg, &l2o_buf.macaddr)) - { - vty_out (vty, "Bad mac address \"%s\"\n", argv[10]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - - l2o_buf.logical_net_id = strtoul(argv[8]->arg, NULL, 10); - - /* construct option chain */ - - memset (valbuf, 0, sizeof (valbuf)); - memcpy (valbuf, &l2o_buf.macaddr.octet, ETHER_ADDR_LEN); - valbuf[11] = (l2o_buf.logical_net_id >> 16) & 0xff; - valbuf[12] = (l2o_buf.logical_net_id >> 8) & 0xff; - valbuf[13] = l2o_buf.logical_net_id & 0xff; - - memset (&hopt, 0, sizeof (hopt)); - hopt.options_count = 1; - hopt.options_length = sizeof (valbuf); /* is this right? */ - hopt.type = RFAPI_VN_OPTION_TYPE_L2ADDR; - hopt.length = sizeof (valbuf); - hopt.value = valbuf; - - - /* - * options parameter not used? Set to NULL for now - */ - rc = rfapi_query (handle, &target, &l2o_buf, &pNextHopEntry); - - if (rc) - { - vty_out (vty, "rfapi_query failed with rc=%d (%s)\n", rc, - strerror(rc)); - } - else - { - /* - * print nexthop list - */ - /* TBD enhance to print L2 information */ - test_nexthops_callback ( /*&target, */ pNextHopEntry, vty); /* frees nh list! */ - } - - return CMD_SUCCESS; + if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) { + vty_out(vty, "can't locate handle matching vn=%s, un=%s\n", + argv[4]->arg, argv[6]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + + /* + * Set up L2 parameters + */ + memset(&l2o_buf, 0, sizeof(l2o_buf)); + if (rfapiStr2EthAddr(argv[10]->arg, &l2o_buf.macaddr)) { + vty_out(vty, "Bad mac address \"%s\"\n", argv[10]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + + l2o_buf.logical_net_id = strtoul(argv[8]->arg, NULL, 10); + + /* construct option chain */ + + memset(valbuf, 0, sizeof(valbuf)); + memcpy(valbuf, &l2o_buf.macaddr.octet, ETHER_ADDR_LEN); + valbuf[11] = (l2o_buf.logical_net_id >> 16) & 0xff; + valbuf[12] = (l2o_buf.logical_net_id >> 8) & 0xff; + valbuf[13] = l2o_buf.logical_net_id & 0xff; + + memset(&hopt, 0, sizeof(hopt)); + hopt.options_count = 1; + hopt.options_length = sizeof(valbuf); /* is this right? */ + hopt.type = RFAPI_VN_OPTION_TYPE_L2ADDR; + hopt.length = sizeof(valbuf); + hopt.value = valbuf; + + + /* + * options parameter not used? Set to NULL for now + */ + rc = rfapi_query(handle, &target, &l2o_buf, &pNextHopEntry); + + if (rc) { + vty_out(vty, "rfapi_query failed with rc=%d (%s)\n", rc, + strerror(rc)); + } else { + /* + * print nexthop list + */ + /* TBD enhance to print L2 information */ + test_nexthops_callback(/*&target, */ pNextHopEntry, + vty); /* frees nh list! */ + } + + return CMD_SUCCESS; } @@ -3718,48 +3467,47 @@ DEFUN (debug_rfapi_query_done_vn_un, "Target IPv4 address\n" "Target IPv6 address\n") { - struct rfapi_ip_addr vn; - struct rfapi_ip_addr un; - struct rfapi_ip_addr target; - rfapi_handle handle; - int rc; + struct rfapi_ip_addr vn; + struct rfapi_ip_addr un; + struct rfapi_ip_addr target; + rfapi_handle handle; + int rc; - /* - * Get VN addr - */ - if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[5]->arg, &vn))) - return rc; + /* + * Get VN addr + */ + if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[5]->arg, &vn))) + return rc; - /* - * Get UN addr - */ - if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[7]->arg, &un))) - return rc; + /* + * Get UN addr + */ + if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[7]->arg, &un))) + return rc; - /* - * Get target addr - */ - if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[9]->arg, &target))) - return rc; + /* + * Get target addr + */ + if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[9]->arg, &target))) + return rc; - if (rfapi_find_handle_vty (vty, &vn, &un, &handle)) - { - vty_out (vty, "can't locate handle matching vn=%s, un=%s\n", - argv[5]->arg, argv[7]->arg); - return CMD_WARNING_CONFIG_FAILED; - } + if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) { + vty_out(vty, "can't locate handle matching vn=%s, un=%s\n", + argv[5]->arg, argv[7]->arg); + return CMD_WARNING_CONFIG_FAILED; + } - /* - * options parameter not used? Set to NULL for now - */ - rc = rfapi_query_done (handle, &target); + /* + * options parameter not used? Set to NULL for now + */ + rc = rfapi_query_done(handle, &target); - vty_out (vty, "rfapi_query_done returned %d\n", rc); + vty_out(vty, "rfapi_query_done returned %d\n", rc); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_rfapi_show_import, @@ -3770,83 +3518,82 @@ DEFUN (debug_rfapi_show_import, SHOW_STR "import\n") { - struct bgp *bgp; - struct rfapi *h; - struct rfapi_import_table *it; - char *s; - int first_l2 = 1; - - /* - * Show all import tables - */ - - bgp = bgp_get_default (); /* assume 1 instance for now */ - if (!bgp) - { - vty_out (vty, "No BGP instance\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - h = bgp->rfapi; - if (!h) - { - vty_out (vty, "No RFAPI instance\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* - * Iterate over all import tables; do a filtered import - * for the afi/safi combination - */ - - - for (it = h->imports; it; it = it->next) - { - s = ecommunity_ecom2str (it->rt_import_list, - ECOMMUNITY_FORMAT_ROUTE_MAP, 0); - vty_out (vty, "Import Table %p, RTs: %s\n", it, s); - XFREE (MTYPE_ECOMMUNITY_STR, s); - - rfapiShowImportTable (vty, "IP VPN", it->imported_vpn[AFI_IP], 1); - rfapiShowImportTable (vty, "IP ENCAP", it->imported_encap[AFI_IP], 0); - rfapiShowImportTable (vty, "IP6 VPN", it->imported_vpn[AFI_IP6], 1); - rfapiShowImportTable (vty, "IP6 ENCAP", it->imported_encap[AFI_IP6], 0); - } - - if (h->import_mac) - { - void *cursor = NULL; - uint32_t lni; - uintptr_t lni_as_ptr; - int rc; - char buf[BUFSIZ]; - - for (rc = - skiplist_next (h->import_mac, (void **) &lni_as_ptr, (void **) &it, - &cursor); !rc; - rc = - skiplist_next (h->import_mac, (void **) &lni_as_ptr, (void **) &it, - &cursor)) - { - - if (it->imported_vpn[AFI_L2VPN]) - { - lni = lni_as_ptr; - if (first_l2) - { - vty_out (vty, "\nLNI-based Ethernet Tables:\n"); - first_l2 = 0; - } - snprintf (buf, BUFSIZ, "L2VPN LNI=%u", lni); - rfapiShowImportTable (vty, buf, it->imported_vpn[AFI_L2VPN], 1); - } - } - } - - rfapiShowImportTable (vty, "CE IT - IP VPN", - h->it_ce->imported_vpn[AFI_IP], 1); - - return CMD_SUCCESS; + struct bgp *bgp; + struct rfapi *h; + struct rfapi_import_table *it; + char *s; + int first_l2 = 1; + + /* + * Show all import tables + */ + + bgp = bgp_get_default(); /* assume 1 instance for now */ + if (!bgp) { + vty_out(vty, "No BGP instance\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + h = bgp->rfapi; + if (!h) { + vty_out(vty, "No RFAPI instance\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* + * Iterate over all import tables; do a filtered import + * for the afi/safi combination + */ + + + for (it = h->imports; it; it = it->next) { + s = ecommunity_ecom2str(it->rt_import_list, + ECOMMUNITY_FORMAT_ROUTE_MAP, 0); + vty_out(vty, "Import Table %p, RTs: %s\n", it, s); + XFREE(MTYPE_ECOMMUNITY_STR, s); + + rfapiShowImportTable(vty, "IP VPN", it->imported_vpn[AFI_IP], + 1); + rfapiShowImportTable(vty, "IP ENCAP", + it->imported_encap[AFI_IP], 0); + rfapiShowImportTable(vty, "IP6 VPN", it->imported_vpn[AFI_IP6], + 1); + rfapiShowImportTable(vty, "IP6 ENCAP", + it->imported_encap[AFI_IP6], 0); + } + + if (h->import_mac) { + void *cursor = NULL; + uint32_t lni; + uintptr_t lni_as_ptr; + int rc; + char buf[BUFSIZ]; + + for (rc = skiplist_next(h->import_mac, (void **)&lni_as_ptr, + (void **)&it, &cursor); + !rc; + rc = skiplist_next(h->import_mac, (void **)&lni_as_ptr, + (void **)&it, &cursor)) { + + if (it->imported_vpn[AFI_L2VPN]) { + lni = lni_as_ptr; + if (first_l2) { + vty_out(vty, + "\nLNI-based Ethernet Tables:\n"); + first_l2 = 0; + } + snprintf(buf, BUFSIZ, "L2VPN LNI=%u", lni); + rfapiShowImportTable( + vty, buf, it->imported_vpn[AFI_L2VPN], + 1); + } + } + } + + rfapiShowImportTable(vty, "CE IT - IP VPN", + h->it_ce->imported_vpn[AFI_IP], 1); + + return CMD_SUCCESS; } DEFUN (debug_rfapi_show_import_vn_un, @@ -3863,45 +3610,44 @@ DEFUN (debug_rfapi_show_import_vn_un, "underlay network interface IPv4 address\n" "underlay network interface IPv6 address\n") { - struct rfapi_ip_addr vn; - struct rfapi_ip_addr un; - rfapi_handle handle; - int rc; - struct rfapi_descriptor *rfd; - - /* - * Get VN addr - */ - if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[5]->arg, &vn))) - return rc; - - - /* - * Get UN addr - */ - if ((rc = rfapiCliGetRfapiIpAddr (vty, argv[7]->arg, &un))) - return rc; - - - if (rfapi_find_handle_vty (vty, &vn, &un, &handle)) - { - vty_out (vty, "can't locate handle matching vn=%s, un=%s\n", - argv[5]->arg, argv[7]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - - rfd = (struct rfapi_descriptor *) handle; - - rfapiShowImportTable (vty, "IP VPN", - rfd->import_table->imported_vpn[AFI_IP], 1); - rfapiShowImportTable (vty, "IP ENCAP", - rfd->import_table->imported_encap[AFI_IP], 0); - rfapiShowImportTable (vty, "IP6 VPN", - rfd->import_table->imported_vpn[AFI_IP6], 1); - rfapiShowImportTable (vty, "IP6 ENCAP", - rfd->import_table->imported_encap[AFI_IP6], 0); - - return CMD_SUCCESS; + struct rfapi_ip_addr vn; + struct rfapi_ip_addr un; + rfapi_handle handle; + int rc; + struct rfapi_descriptor *rfd; + + /* + * Get VN addr + */ + if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[5]->arg, &vn))) + return rc; + + + /* + * Get UN addr + */ + if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[7]->arg, &un))) + return rc; + + + if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) { + vty_out(vty, "can't locate handle matching vn=%s, un=%s\n", + argv[5]->arg, argv[7]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + + rfd = (struct rfapi_descriptor *)handle; + + rfapiShowImportTable(vty, "IP VPN", + rfd->import_table->imported_vpn[AFI_IP], 1); + rfapiShowImportTable(vty, "IP ENCAP", + rfd->import_table->imported_encap[AFI_IP], 0); + rfapiShowImportTable(vty, "IP6 VPN", + rfd->import_table->imported_vpn[AFI_IP6], 1); + rfapiShowImportTable(vty, "IP6 ENCAP", + rfd->import_table->imported_encap[AFI_IP6], 0); + + return CMD_SUCCESS; } DEFUN (debug_rfapi_response_omit_self, @@ -3912,25 +3658,25 @@ DEFUN (debug_rfapi_response_omit_self, "Omit self in RFP responses\n" "filter out self from responses\n" "leave self in responses\n") { - struct bgp *bgp = bgp_get_default (); - - if (!bgp) - { - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (!bgp->rfapi_cfg) - { - vty_out (vty, "VNC not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (strmatch(argv[3]->text, "on")) - SET_FLAG (bgp->rfapi_cfg->flags, BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP); - else - UNSET_FLAG (bgp->rfapi_cfg->flags, BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP); - - return CMD_SUCCESS; + struct bgp *bgp = bgp_get_default(); + + if (!bgp) { + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (!bgp->rfapi_cfg) { + vty_out(vty, "VNC not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (strmatch(argv[3]->text, "on")) + SET_FLAG(bgp->rfapi_cfg->flags, + BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP); + else + UNSET_FLAG(bgp->rfapi_cfg->flags, + BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP); + + return CMD_SUCCESS; } @@ -3943,9 +3689,9 @@ DEFUN (skiplist_test_cli, "skiplist command\n" "test\n") { - skiplist_test (vty); + skiplist_test(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (skiplist_debug_cli, @@ -3954,151 +3700,139 @@ DEFUN (skiplist_debug_cli, "skiplist command\n" "debug\n") { - skiplist_debug (vty, NULL); - return CMD_SUCCESS; + skiplist_debug(vty, NULL); + return CMD_SUCCESS; } #endif /* RFAPI_DEBUG_SKIPLIST_CLI */ -void -rfapi_init (void) +void rfapi_init(void) { - bgp_rfapi_cfg_init (); - vnc_debug_init(); + bgp_rfapi_cfg_init(); + vnc_debug_init(); - install_element (ENABLE_NODE, &debug_rfapi_show_import_cmd); - install_element (ENABLE_NODE, &debug_rfapi_show_import_vn_un_cmd); + install_element(ENABLE_NODE, &debug_rfapi_show_import_cmd); + install_element(ENABLE_NODE, &debug_rfapi_show_import_vn_un_cmd); - install_element (ENABLE_NODE, &debug_rfapi_open_cmd); - install_element (ENABLE_NODE, &debug_rfapi_close_vn_un_cmd); - install_element (ENABLE_NODE, &debug_rfapi_close_rfd_cmd); - install_element (ENABLE_NODE, &debug_rfapi_register_vn_un_cmd); - install_element (ENABLE_NODE, &debug_rfapi_unregister_vn_un_cmd); - install_element (ENABLE_NODE, &debug_rfapi_query_vn_un_cmd); - install_element (ENABLE_NODE, &debug_rfapi_query_vn_un_done_cmd); - install_element (ENABLE_NODE, &debug_rfapi_query_vn_un_l2o_cmd); + install_element(ENABLE_NODE, &debug_rfapi_open_cmd); + install_element(ENABLE_NODE, &debug_rfapi_close_vn_un_cmd); + install_element(ENABLE_NODE, &debug_rfapi_close_rfd_cmd); + install_element(ENABLE_NODE, &debug_rfapi_register_vn_un_cmd); + install_element(ENABLE_NODE, &debug_rfapi_unregister_vn_un_cmd); + install_element(ENABLE_NODE, &debug_rfapi_query_vn_un_cmd); + install_element(ENABLE_NODE, &debug_rfapi_query_vn_un_done_cmd); + install_element(ENABLE_NODE, &debug_rfapi_query_vn_un_l2o_cmd); - install_element (ENABLE_NODE, &debug_rfapi_response_omit_self_cmd); + install_element(ENABLE_NODE, &debug_rfapi_response_omit_self_cmd); - /* Need the following show commands for gpz test scripts */ - install_element (ENABLE_NODE, &debug_rfapi_show_nves_cmd); - install_element (ENABLE_NODE, &debug_rfapi_show_nves_vn_un_cmd); - install_element (ENABLE_NODE, &debug_rfapi_register_vn_un_l2o_cmd); + /* Need the following show commands for gpz test scripts */ + install_element(ENABLE_NODE, &debug_rfapi_show_nves_cmd); + install_element(ENABLE_NODE, &debug_rfapi_show_nves_vn_un_cmd); + install_element(ENABLE_NODE, &debug_rfapi_register_vn_un_l2o_cmd); #ifdef RFAPI_DEBUG_SKIPLIST_CLI - install_element (ENABLE_NODE, &skiplist_test_cli_cmd); - install_element (ENABLE_NODE, &skiplist_debug_cli_cmd); + install_element(ENABLE_NODE, &skiplist_test_cli_cmd); + install_element(ENABLE_NODE, &skiplist_debug_cli_cmd); #endif - rfapi_vty_init (); + rfapi_vty_init(); } #ifdef DEBUG_RFAPI -static void -rfapi_print_exported (struct bgp *bgp) +static void rfapi_print_exported(struct bgp *bgp) { - struct bgp_node *rdn; - struct bgp_node *rn; - struct bgp_info *bi; - - if (!bgp) - return; - - for (rdn = bgp_table_top (bgp->rib[AFI_IP][SAFI_MPLS_VPN]); rdn; - rdn = bgp_route_next (rdn)) - { - if (!rdn->info) - continue; - fprintf (stderr, "%s: vpn rdn=%p\n", __func__, rdn); - for (rn = bgp_table_top (rdn->info); rn; rn = bgp_route_next (rn)) - { - if (!rn->info) - continue; - fprintf (stderr, "%s: rn=%p\n", __func__, rn); - for (bi = rn->info; bi; bi = bi->next) - { - rfapiPrintBi ((void *) 2, bi); /* 2 => stderr */ - } - } - } - for (rdn = bgp_table_top (bgp->rib[AFI_IP][SAFI_ENCAP]); rdn; - rdn = bgp_route_next (rdn)) - { - if (!rdn->info) - continue; - fprintf (stderr, "%s: encap rdn=%p\n", __func__, rdn); - for (rn = bgp_table_top (rdn->info); rn; rn = bgp_route_next (rn)) - { - if (!rn->info) - continue; - fprintf (stderr, "%s: rn=%p\n", __func__, rn); - for (bi = rn->info; bi; bi = bi->next) - { - rfapiPrintBi ((void *) 2, bi); /* 2 => stderr */ - } - } - } - + struct bgp_node *rdn; + struct bgp_node *rn; + struct bgp_info *bi; + + if (!bgp) + return; + + for (rdn = bgp_table_top(bgp->rib[AFI_IP][SAFI_MPLS_VPN]); rdn; + rdn = bgp_route_next(rdn)) { + if (!rdn->info) + continue; + fprintf(stderr, "%s: vpn rdn=%p\n", __func__, rdn); + for (rn = bgp_table_top(rdn->info); rn; + rn = bgp_route_next(rn)) { + if (!rn->info) + continue; + fprintf(stderr, "%s: rn=%p\n", __func__, rn); + for (bi = rn->info; bi; bi = bi->next) { + rfapiPrintBi((void *)2, bi); /* 2 => stderr */ + } + } + } + for (rdn = bgp_table_top(bgp->rib[AFI_IP][SAFI_ENCAP]); rdn; + rdn = bgp_route_next(rdn)) { + if (!rdn->info) + continue; + fprintf(stderr, "%s: encap rdn=%p\n", __func__, rdn); + for (rn = bgp_table_top(rdn->info); rn; + rn = bgp_route_next(rn)) { + if (!rn->info) + continue; + fprintf(stderr, "%s: rn=%p\n", __func__, rn); + for (bi = rn->info; bi; bi = bi->next) { + rfapiPrintBi((void *)2, bi); /* 2 => stderr */ + } + } + } } #endif /* defined(DEBUG_RFAPI) */ /* * Free all memory to prepare for clean exit as seen by valgrind memcheck */ -void -rfapi_delete (struct bgp *bgp) +void rfapi_delete(struct bgp *bgp) { - extern void rfp_clear_vnc_nve_all (void); /* can't fix correctly yet */ - - /* - * This clears queries and registered routes, and closes nves - */ - if (bgp->rfapi) - rfp_clear_vnc_nve_all (); - bgp_rfapi_cfg_destroy (bgp, bgp->rfapi_cfg); - bgp->rfapi_cfg = NULL; - bgp_rfapi_destroy (bgp, bgp->rfapi); - bgp->rfapi = NULL; + extern void rfp_clear_vnc_nve_all(void); /* can't fix correctly yet */ + + /* + * This clears queries and registered routes, and closes nves + */ + if (bgp->rfapi) + rfp_clear_vnc_nve_all(); + bgp_rfapi_cfg_destroy(bgp, bgp->rfapi_cfg); + bgp->rfapi_cfg = NULL; + bgp_rfapi_destroy(bgp, bgp->rfapi); + bgp->rfapi = NULL; #ifdef DEBUG_RFAPI - /* - * show what's left in the BGP MPLSVPN RIB - */ - rfapi_print_exported (bgp); + /* + * show what's left in the BGP MPLSVPN RIB + */ + rfapi_print_exported(bgp); #endif - } -int -rfapi_set_autord_from_vn (struct prefix_rd *rd, struct rfapi_ip_addr *vn) +int rfapi_set_autord_from_vn(struct prefix_rd *rd, struct rfapi_ip_addr *vn) { - vnc_zlog_debug_verbose ("%s: auto-assigning RD", __func__); - if (vn->addr_family != AF_INET - && vn->addr_family != AF_INET6) - { - vnc_zlog_debug_verbose ("%s: can't auto-assign RD, VN addr family is not IPv4" - "|v6" - , __func__); - return EAFNOSUPPORT; - } - rd->family = AF_UNSPEC; - rd->prefixlen = 64; - rd->val[1] = RD_TYPE_IP; - if (vn->addr_family == AF_INET) - { - memcpy (rd->val + 2, &vn->addr.v4.s_addr, 4); - } - else - { /* is v6 */ - memcpy (rd->val + 2, &vn->addr.v6.s6_addr32[3], 4);/* low order 4 bytes */ - } - { - char buf[BUFSIZ]; - buf[0] = 0; - prefix_rd2str (rd, buf, BUFSIZ); - buf[BUFSIZ - 1] = 0; - vnc_zlog_debug_verbose ("%s: auto-RD is set to %s", __func__, buf); - } - return 0; + vnc_zlog_debug_verbose("%s: auto-assigning RD", __func__); + if (vn->addr_family != AF_INET && vn->addr_family != AF_INET6) { + vnc_zlog_debug_verbose( + "%s: can't auto-assign RD, VN addr family is not IPv4" + "|v6", + __func__); + return EAFNOSUPPORT; + } + rd->family = AF_UNSPEC; + rd->prefixlen = 64; + rd->val[1] = RD_TYPE_IP; + if (vn->addr_family == AF_INET) { + memcpy(rd->val + 2, &vn->addr.v4.s_addr, 4); + } else { /* is v6 */ + memcpy(rd->val + 2, &vn->addr.v6.s6_addr32[3], + 4); /* low order 4 bytes */ + } + { + char buf[BUFSIZ]; + buf[0] = 0; + prefix_rd2str(rd, buf, BUFSIZ); + buf[BUFSIZ - 1] = 0; + vnc_zlog_debug_verbose("%s: auto-RD is set to %s", __func__, + buf); + } + return 0; } /*------------------------------------------ @@ -4106,7 +3840,7 @@ rfapi_set_autord_from_vn (struct prefix_rd *rd, struct rfapi_ip_addr *vn) * * Find bgp instance pointer based on value returned by rfp_start * - * input: + * input: * rfp_start_val value returned by rfp_startor * NULL (=get default instance) * @@ -4118,19 +3852,19 @@ rfapi_set_autord_from_vn (struct prefix_rd *rd, struct rfapi_ip_addr *vn) * NULL = not found * --------------------------------------------*/ -struct bgp * -rfapi_bgp_lookup_by_rfp (void *rfp_start_val) +struct bgp *rfapi_bgp_lookup_by_rfp(void *rfp_start_val) { - struct bgp *bgp = NULL; - struct listnode *node, *nnode; - - if (rfp_start_val == NULL) - bgp = bgp_get_default (); - else - for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) - if (bgp->rfapi != NULL && bgp->rfapi->rfp == rfp_start_val) - return bgp; - return bgp; + struct bgp *bgp = NULL; + struct listnode *node, *nnode; + + if (rfp_start_val == NULL) + bgp = bgp_get_default(); + else + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) + if (bgp->rfapi != NULL + && bgp->rfapi->rfp == rfp_start_val) + return bgp; + return bgp; } /*------------------------------------------ @@ -4138,7 +3872,7 @@ rfapi_bgp_lookup_by_rfp (void *rfp_start_val) * * Find bgp instance pointer based on value returned by rfp_start * - * input: + * input: * bgp bgp instance pointer * * output: @@ -4149,91 +3883,81 @@ rfapi_bgp_lookup_by_rfp (void *rfp_start_val) * NULL = not found * --------------------------------------------*/ -void * -rfapi_get_rfp_start_val_by_bgp (struct bgp *bgp) +void *rfapi_get_rfp_start_val_by_bgp(struct bgp *bgp) { - if (!bgp || !bgp->rfapi) - return NULL; - return bgp->rfapi->rfp; + if (!bgp || !bgp->rfapi) + return NULL; + return bgp->rfapi->rfp; } /*********************************************************************** * RFP group specific configuration ***********************************************************************/ -static void * -rfapi_rfp_get_or_init_group_config_default ( - struct rfapi_cfg *rfc, - struct vty *vty, - uint32_t size) +static void *rfapi_rfp_get_or_init_group_config_default(struct rfapi_cfg *rfc, + struct vty *vty, + uint32_t size) { - if (rfc->default_rfp_cfg == NULL && size > 0) - { - rfc->default_rfp_cfg = XCALLOC (MTYPE_RFAPI_RFP_GROUP_CFG, size); - vnc_zlog_debug_verbose ("%s: allocated, size=%d", __func__, size); - - } - return rfc->default_rfp_cfg; + if (rfc->default_rfp_cfg == NULL && size > 0) { + rfc->default_rfp_cfg = XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG, size); + vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__, + size); + } + return rfc->default_rfp_cfg; } -static void * -rfapi_rfp_get_or_init_group_config_nve ( - struct rfapi_cfg *rfc, - struct vty *vty, - uint32_t size) +static void *rfapi_rfp_get_or_init_group_config_nve(struct rfapi_cfg *rfc, + struct vty *vty, + uint32_t size) { - struct rfapi_nve_group_cfg *rfg = VTY_GET_CONTEXT_SUB(rfapi_nve_group_cfg); - - /* make sure group is still in list */ - if (!rfg || !listnode_lookup (rfc->nve_groups_sequential, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current NVE group no longer exists\n"); - return NULL; - } - - if (rfg->rfp_cfg == NULL && size > 0) - { - rfg->rfp_cfg = XCALLOC (MTYPE_RFAPI_RFP_GROUP_CFG, size); - vnc_zlog_debug_verbose ("%s: allocated, size=%d", __func__, size); - - } - return rfg->rfp_cfg; + struct rfapi_nve_group_cfg *rfg = + VTY_GET_CONTEXT_SUB(rfapi_nve_group_cfg); + + /* make sure group is still in list */ + if (!rfg || !listnode_lookup(rfc->nve_groups_sequential, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current NVE group no longer exists\n"); + return NULL; + } + + if (rfg->rfp_cfg == NULL && size > 0) { + rfg->rfp_cfg = XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG, size); + vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__, + size); + } + return rfg->rfp_cfg; } -static void * -rfapi_rfp_get_or_init_group_config_l2 ( - struct rfapi_cfg *rfc, - struct vty *vty, - uint32_t size) +static void *rfapi_rfp_get_or_init_group_config_l2(struct rfapi_cfg *rfc, + struct vty *vty, + uint32_t size) { - struct rfapi_l2_group_cfg *rfg = VTY_GET_CONTEXT_SUB(rfapi_l2_group_cfg); - - /* make sure group is still in list */ - if (!rfg || !listnode_lookup (rfc->l2_groups, rfg)) - { - /* Not in list anymore */ - vty_out (vty, "Current L2 group no longer exists\n"); - return NULL; - } - if (rfg->rfp_cfg == NULL && size > 0) - { - rfg->rfp_cfg = XCALLOC (MTYPE_RFAPI_RFP_GROUP_CFG, size); - vnc_zlog_debug_verbose ("%s: allocated, size=%d", __func__, size); - - } - return rfg->rfp_cfg; + struct rfapi_l2_group_cfg *rfg = + VTY_GET_CONTEXT_SUB(rfapi_l2_group_cfg); + + /* make sure group is still in list */ + if (!rfg || !listnode_lookup(rfc->l2_groups, rfg)) { + /* Not in list anymore */ + vty_out(vty, "Current L2 group no longer exists\n"); + return NULL; + } + if (rfg->rfp_cfg == NULL && size > 0) { + rfg->rfp_cfg = XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG, size); + vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__, + size); + } + return rfg->rfp_cfg; } /*------------------------------------------ * rfapi_rfp_init_group_config_ptr_vty * * This is used to init or return a previously init'ed group specific - * configuration pointer. Group is identified by vty context. + * configuration pointer. Group is identified by vty context. * NOTE: size is ignored when a previously init'ed value is returned. * RFAPI frees rfp_cfg_group when group is deleted during reconfig, * bgp restart or shutdown. * - * input: + * input: * rfp_start_val value returned by rfp_start * type group type * vty quagga vty context @@ -4242,46 +3966,43 @@ rfapi_rfp_get_or_init_group_config_l2 ( * output: * none * - * return value: + * return value: * rfp_cfg_group NULL or Pointer to configuration structure --------------------------------------------*/ -void * -rfapi_rfp_init_group_config_ptr_vty ( - void *rfp_start_val, - rfapi_rfp_cfg_group_type type, - struct vty *vty, - uint32_t size) +void *rfapi_rfp_init_group_config_ptr_vty(void *rfp_start_val, + rfapi_rfp_cfg_group_type type, + struct vty *vty, uint32_t size) { - struct bgp *bgp; - void *ret = NULL; - - if (rfp_start_val == NULL || vty == NULL) - return NULL; - - bgp = rfapi_bgp_lookup_by_rfp (rfp_start_val); - if (!bgp || !bgp->rfapi_cfg) - return NULL; - - switch (type) - { - case RFAPI_RFP_CFG_GROUP_DEFAULT: - ret = rfapi_rfp_get_or_init_group_config_default (bgp->rfapi_cfg, - vty, size); - break; - case RFAPI_RFP_CFG_GROUP_NVE: - ret = rfapi_rfp_get_or_init_group_config_nve (bgp->rfapi_cfg, - vty, size); - break; - case RFAPI_RFP_CFG_GROUP_L2: - ret = rfapi_rfp_get_or_init_group_config_l2 (bgp->rfapi_cfg, vty, size); - break; - default: - zlog_err ("%s: Unknown group type=%d", __func__, type); - /* should never happen */ - assert ("Unknown type" == NULL); - break; - } - return ret; + struct bgp *bgp; + void *ret = NULL; + + if (rfp_start_val == NULL || vty == NULL) + return NULL; + + bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val); + if (!bgp || !bgp->rfapi_cfg) + return NULL; + + switch (type) { + case RFAPI_RFP_CFG_GROUP_DEFAULT: + ret = rfapi_rfp_get_or_init_group_config_default(bgp->rfapi_cfg, + vty, size); + break; + case RFAPI_RFP_CFG_GROUP_NVE: + ret = rfapi_rfp_get_or_init_group_config_nve(bgp->rfapi_cfg, + vty, size); + break; + case RFAPI_RFP_CFG_GROUP_L2: + ret = rfapi_rfp_get_or_init_group_config_l2(bgp->rfapi_cfg, vty, + size); + break; + default: + zlog_err("%s: Unknown group type=%d", __func__, type); + /* should never happen */ + assert("Unknown type" == NULL); + break; + } + return ret; } /*------------------------------------------ @@ -4290,9 +4011,9 @@ rfapi_rfp_init_group_config_ptr_vty ( * This is used to get group specific configuration pointer. * Group is identified by type and vty context. * RFAPI frees rfp_cfg_group when group is deleted during reconfig, - * bgp restart or shutdown. + * bgp restart or shutdown. * - * input: + * input: * rfp_start_val value returned by rfp_start * type group type * vty quagga vty context @@ -4301,64 +4022,56 @@ rfapi_rfp_init_group_config_ptr_vty ( * none * * return value: - * rfp_cfg_group Pointer to configuration structure + * rfp_cfg_group Pointer to configuration structure --------------------------------------------*/ -void * -rfapi_rfp_get_group_config_ptr_vty ( - void *rfp_start_val, - rfapi_rfp_cfg_group_type type, - struct vty *vty) +void *rfapi_rfp_get_group_config_ptr_vty(void *rfp_start_val, + rfapi_rfp_cfg_group_type type, + struct vty *vty) { - return rfapi_rfp_init_group_config_ptr_vty (rfp_start_val, type, vty, 0); + return rfapi_rfp_init_group_config_ptr_vty(rfp_start_val, type, vty, 0); } static void * -rfapi_rfp_get_group_config_name_nve ( - struct rfapi_cfg *rfc, - const char *name, - void *criteria, - rfp_group_config_search_cb_t *search_cb) +rfapi_rfp_get_group_config_name_nve(struct rfapi_cfg *rfc, const char *name, + void *criteria, + rfp_group_config_search_cb_t *search_cb) { - struct rfapi_nve_group_cfg *rfg; - struct listnode *node; - - for (ALL_LIST_ELEMENTS_RO (rfc->nve_groups_sequential, node, rfg)) - { - if (!strcmp (rfg->name, name) && /* name match */ - (search_cb == NULL || !search_cb (criteria, rfg->rfp_cfg))) - return rfg->rfp_cfg; - } - return NULL; + struct rfapi_nve_group_cfg *rfg; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO(rfc->nve_groups_sequential, node, rfg)) { + if (!strcmp(rfg->name, name) && /* name match */ + (search_cb == NULL || !search_cb(criteria, rfg->rfp_cfg))) + return rfg->rfp_cfg; + } + return NULL; } static void * -rfapi_rfp_get_group_config_name_l2 ( - struct rfapi_cfg *rfc, - const char *name, - void *criteria, - rfp_group_config_search_cb_t *search_cb) +rfapi_rfp_get_group_config_name_l2(struct rfapi_cfg *rfc, const char *name, + void *criteria, + rfp_group_config_search_cb_t *search_cb) { - struct rfapi_l2_group_cfg *rfg; - struct listnode *node; - - for (ALL_LIST_ELEMENTS_RO (rfc->l2_groups, node, rfg)) - { - if (!strcmp (rfg->name, name) && /* name match */ - (search_cb == NULL || !search_cb (criteria, rfg->rfp_cfg))) - return rfg->rfp_cfg; - } - return NULL; + struct rfapi_l2_group_cfg *rfg; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO(rfc->l2_groups, node, rfg)) { + if (!strcmp(rfg->name, name) && /* name match */ + (search_cb == NULL || !search_cb(criteria, rfg->rfp_cfg))) + return rfg->rfp_cfg; + } + return NULL; } /*------------------------------------------ * rfapi_rfp_get_group_config_ptr_name * * This is used to get group specific configuration pointer. - * Group is identified by type and name context. + * Group is identified by type and name context. * RFAPI frees rfp_cfg_group when group is deleted during reconfig, * bgp restart or shutdown. * - * input: + * input: * rfp_start_val value returned by rfp_start * type group type * name group name @@ -4369,46 +4082,41 @@ rfapi_rfp_get_group_config_name_l2 ( * none * * return value: - * rfp_cfg_group Pointer to configuration structure + * rfp_cfg_group Pointer to configuration structure --------------------------------------------*/ -void * -rfapi_rfp_get_group_config_ptr_name ( - void *rfp_start_val, - rfapi_rfp_cfg_group_type type, - const char *name, - void *criteria, - rfp_group_config_search_cb_t *search_cb) +void *rfapi_rfp_get_group_config_ptr_name( + void *rfp_start_val, rfapi_rfp_cfg_group_type type, const char *name, + void *criteria, rfp_group_config_search_cb_t *search_cb) { - struct bgp *bgp; - void *ret = NULL; - - if (rfp_start_val == NULL || name == NULL) - return NULL; - - bgp = rfapi_bgp_lookup_by_rfp (rfp_start_val); - if (!bgp || !bgp->rfapi_cfg) - return NULL; - - switch (type) - { - case RFAPI_RFP_CFG_GROUP_DEFAULT: - ret = bgp->rfapi_cfg->default_rfp_cfg; - break; - case RFAPI_RFP_CFG_GROUP_NVE: - ret = rfapi_rfp_get_group_config_name_nve (bgp->rfapi_cfg, - name, criteria, search_cb); - break; - case RFAPI_RFP_CFG_GROUP_L2: - ret = rfapi_rfp_get_group_config_name_l2 (bgp->rfapi_cfg, - name, criteria, search_cb); - break; - default: - zlog_err ("%s: Unknown group type=%d", __func__, type); - /* should never happen */ - assert ("Unknown type" == NULL); - break; - } - return ret; + struct bgp *bgp; + void *ret = NULL; + + if (rfp_start_val == NULL || name == NULL) + return NULL; + + bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val); + if (!bgp || !bgp->rfapi_cfg) + return NULL; + + switch (type) { + case RFAPI_RFP_CFG_GROUP_DEFAULT: + ret = bgp->rfapi_cfg->default_rfp_cfg; + break; + case RFAPI_RFP_CFG_GROUP_NVE: + ret = rfapi_rfp_get_group_config_name_nve(bgp->rfapi_cfg, name, + criteria, search_cb); + break; + case RFAPI_RFP_CFG_GROUP_L2: + ret = rfapi_rfp_get_group_config_name_l2(bgp->rfapi_cfg, name, + criteria, search_cb); + break; + default: + zlog_err("%s: Unknown group type=%d", __func__, type); + /* should never happen */ + assert("Unknown type" == NULL); + break; + } + return ret; } /*------------------------------------------ @@ -4419,7 +4127,7 @@ rfapi_rfp_get_group_config_ptr_name ( * RFAPI frees rfp_cfg_group when group is deleted during reconfig, * bgp restart or shutdown. * - * input: + * input: * rfp_start_val value returned by rfp_start * type group type * logical_net_id group logical network identifier @@ -4430,35 +4138,34 @@ rfapi_rfp_get_group_config_ptr_name ( * none * * return value: - * rfp_cfg_group Pointer to configuration structure + * rfp_cfg_group Pointer to configuration structure --------------------------------------------*/ void * -rfapi_rfp_get_l2_group_config_ptr_lni ( - void *rfp_start_val, - uint32_t logical_net_id, - void *criteria, - rfp_group_config_search_cb_t *search_cb) +rfapi_rfp_get_l2_group_config_ptr_lni(void *rfp_start_val, + uint32_t logical_net_id, void *criteria, + rfp_group_config_search_cb_t *search_cb) { - struct bgp *bgp; - struct rfapi_l2_group_cfg *rfg; - struct listnode *node; - - if (rfp_start_val == NULL) - return NULL; - - bgp = rfapi_bgp_lookup_by_rfp (rfp_start_val); - if (!bgp || !bgp->rfapi_cfg) - return NULL; - - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->l2_groups, node, rfg)) - { - if (rfg->logical_net_id == logical_net_id && - (search_cb == NULL || !search_cb (criteria, rfg->rfp_cfg))) - { - if (rfg->rfp_cfg == NULL) - vnc_zlog_debug_verbose ("%s: returning rfp group config for lni=0", __func__); - return rfg->rfp_cfg; - } - } - return NULL; + struct bgp *bgp; + struct rfapi_l2_group_cfg *rfg; + struct listnode *node; + + if (rfp_start_val == NULL) + return NULL; + + bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val); + if (!bgp || !bgp->rfapi_cfg) + return NULL; + + for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->l2_groups, node, rfg)) { + if (rfg->logical_net_id == logical_net_id + && (search_cb == NULL + || !search_cb(criteria, rfg->rfp_cfg))) { + if (rfg->rfp_cfg == NULL) + vnc_zlog_debug_verbose( + "%s: returning rfp group config for lni=0", + __func__); + return rfg->rfp_cfg; + } + } + return NULL; } diff --git a/bgpd/rfapi/rfapi.h b/bgpd/rfapi/rfapi.h index 11d41c9d1..8eb0d717d 100644 --- a/bgpd/rfapi/rfapi.h +++ b/bgpd/rfapi/rfapi.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -32,138 +32,127 @@ #include "bgpd/bgp_encap_types.h" /* probably ought to have a field-specific define in config.h */ -# ifndef s6_addr32 /* for solaris/bsd */ -# ifdef SOLARIS_IPV6 +#ifndef s6_addr32 /* for solaris/bsd */ +#ifdef SOLARIS_IPV6 # define s6_addr32 _S6_un._S6_u32 -# else +#else # define s6_addr32 __u6_addr.__u6_addr32 -# endif -# endif +#endif +#endif #define RFAPI_V4_ADDR 0x04 #define RFAPI_V6_ADDR 0x06 #define RFAPI_SHOW_STR "VNC information\n" -struct rfapi_ip_addr -{ - uint8_t addr_family; /* AF_INET | AF_INET6 */ - union - { - struct in_addr v4; /* in network order */ - struct in6_addr v6; /* in network order */ - } addr; +struct rfapi_ip_addr { + uint8_t addr_family; /* AF_INET | AF_INET6 */ + union { + struct in_addr v4; /* in network order */ + struct in6_addr v6; /* in network order */ + } addr; }; -struct rfapi_ip_prefix -{ - uint8_t length; - uint8_t cost; /* bgp local pref = 255 - cost */ - struct rfapi_ip_addr prefix; +struct rfapi_ip_prefix { + uint8_t length; + uint8_t cost; /* bgp local pref = 255 - cost */ + struct rfapi_ip_addr prefix; }; -struct rfapi_nexthop -{ - struct prefix addr; - uint8_t cost; +struct rfapi_nexthop { + struct prefix addr; + uint8_t cost; }; -struct rfapi_next_hop_entry -{ - struct rfapi_next_hop_entry *next; - struct rfapi_ip_prefix prefix; - uint32_t lifetime; - struct rfapi_ip_addr un_address; - struct rfapi_ip_addr vn_address; - struct rfapi_vn_option *vn_options; - struct rfapi_un_option *un_options; +struct rfapi_next_hop_entry { + struct rfapi_next_hop_entry *next; + struct rfapi_ip_prefix prefix; + uint32_t lifetime; + struct rfapi_ip_addr un_address; + struct rfapi_ip_addr vn_address; + struct rfapi_vn_option *vn_options; + struct rfapi_un_option *un_options; }; #define RFAPI_REMOVE_RESPONSE_LIFETIME 0 #define RFAPI_INFINITE_LIFETIME 0xFFFFFFFF -struct rfapi_l2address_option -{ - struct ethaddr macaddr; /* use 0 to assign label to IP prefix */ - uint32_t label; /* 20bit label in low bits, no TC, S, or TTL */ - uint32_t logical_net_id; /* ~= EVPN Ethernet Segment Id, - must not be zero for mac regis. */ - uint8_t local_nve_id; - uint16_t tag_id; /* EVPN Ethernet Tag ID, 0 = none */ +struct rfapi_l2address_option { + struct ethaddr macaddr; /* use 0 to assign label to IP prefix */ + uint32_t label; /* 20bit label in low bits, no TC, S, or TTL */ + uint32_t logical_net_id; /* ~= EVPN Ethernet Segment Id, + must not be zero for mac regis. */ + uint8_t local_nve_id; + uint16_t tag_id; /* EVPN Ethernet Tag ID, 0 = none */ }; -typedef enum -{ - RFAPI_UN_OPTION_TYPE_PROVISIONAL, /* internal use only */ - RFAPI_UN_OPTION_TYPE_TUNNELTYPE, +typedef enum { + RFAPI_UN_OPTION_TYPE_PROVISIONAL, /* internal use only */ + RFAPI_UN_OPTION_TYPE_TUNNELTYPE, } rfapi_un_option_type; -struct rfapi_tunneltype_option -{ - bgp_encap_types type; - union - { - struct bgp_encap_type_reserved reserved; - struct bgp_encap_type_l2tpv3_over_ip l2tpv3_ip; - struct bgp_encap_type_gre gre; - struct bgp_encap_type_transmit_tunnel_endpoint transmit_tunnel_endpoint; - struct bgp_encap_type_ipsec_in_tunnel_mode ipsec_tunnel; - struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode ip_ipsec; - struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode mpls_ipsec; - struct bgp_encap_type_ip_in_ip ip_ip; - struct bgp_encap_type_vxlan vxlan; - struct bgp_encap_type_nvgre nvgre; - struct bgp_encap_type_mpls mpls; - struct bgp_encap_type_mpls_in_gre mpls_gre; - struct bgp_encap_type_vxlan_gpe vxlan_gpe; - struct bgp_encap_type_mpls_in_udp mpls_udp; - struct bgp_encap_type_pbb pbb; - } bgpinfo; +struct rfapi_tunneltype_option { + bgp_encap_types type; + union { + struct bgp_encap_type_reserved reserved; + struct bgp_encap_type_l2tpv3_over_ip l2tpv3_ip; + struct bgp_encap_type_gre gre; + struct bgp_encap_type_transmit_tunnel_endpoint + transmit_tunnel_endpoint; + struct bgp_encap_type_ipsec_in_tunnel_mode ipsec_tunnel; + struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode + ip_ipsec; + struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode + mpls_ipsec; + struct bgp_encap_type_ip_in_ip ip_ip; + struct bgp_encap_type_vxlan vxlan; + struct bgp_encap_type_nvgre nvgre; + struct bgp_encap_type_mpls mpls; + struct bgp_encap_type_mpls_in_gre mpls_gre; + struct bgp_encap_type_vxlan_gpe vxlan_gpe; + struct bgp_encap_type_mpls_in_udp mpls_udp; + struct bgp_encap_type_pbb pbb; + } bgpinfo; }; -struct rfapi_un_option -{ - struct rfapi_un_option *next; - rfapi_un_option_type type; - union - { - struct rfapi_tunneltype_option tunnel; - } v; +struct rfapi_un_option { + struct rfapi_un_option *next; + rfapi_un_option_type type; + union { + struct rfapi_tunneltype_option tunnel; + } v; }; -typedef enum -{ - RFAPI_VN_OPTION_TYPE_L2ADDR = 3, /* Layer 2 address, 3 for legacy compatibility */ - RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP, /* for static routes */ - RFAPI_VN_OPTION_TYPE_INTERNAL_RD, /* internal use only */ +typedef enum { + RFAPI_VN_OPTION_TYPE_L2ADDR = + 3, /* Layer 2 address, 3 for legacy compatibility */ + RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP, /* for static routes */ + RFAPI_VN_OPTION_TYPE_INTERNAL_RD, /* internal use only */ } rfapi_vn_option_type; -struct rfapi_vn_option -{ - struct rfapi_vn_option *next; +struct rfapi_vn_option { + struct rfapi_vn_option *next; - rfapi_vn_option_type type; + rfapi_vn_option_type type; - union - { - struct rfapi_l2address_option l2addr; + union { + struct rfapi_l2address_option l2addr; - /* - * If this option is present, the next hop is local to the - * client NVE (i.e., not via a tunnel). - */ - struct rfapi_nexthop local_nexthop; + /* + * If this option is present, the next hop is local to the + * client NVE (i.e., not via a tunnel). + */ + struct rfapi_nexthop local_nexthop; - /* - * For rfapi internal use only - */ - struct prefix_rd internal_rd; - } v; + /* + * For rfapi internal use only + */ + struct prefix_rd internal_rd; + } v; }; -struct rfapi_l2address_option_match -{ - struct rfapi_l2address_option o; - uint32_t flags; +struct rfapi_l2address_option_match { + struct rfapi_l2address_option o; + uint32_t flags; #define RFAPI_L2O_MACADDR 0x00000001 #define RFAPI_L2O_LABEL 0x00000002 @@ -181,7 +170,7 @@ typedef void *rfapi_handle; /*------------------------------------------ * rfapi_response_cb_t (callback typedef) * - * Callbacks of this type are used to provide asynchronous + * Callbacks of this type are used to provide asynchronous * route updates from RFAPI to the RFP client. * * response_cb @@ -200,7 +189,7 @@ typedef void *rfapi_handle; * has been added or deleted. Deleted routes are indicated * with lifetime==RFAPI_REMOVE_RESPONSE_LIFETIME. * - * input: + * input: * next_hops a list of possible next hops. * This is a linked list allocated within the * rfapi. The response_cb callback function is responsible @@ -211,16 +200,16 @@ typedef void *rfapi_handle; * rfapi_open() * *------------------------------------------*/ -typedef void (rfapi_response_cb_t) (struct rfapi_next_hop_entry * next_hops, - void *userdata); +typedef void(rfapi_response_cb_t)(struct rfapi_next_hop_entry *next_hops, + void *userdata); /*------------------------------------------ * rfapi_nve_close_cb_t (callback typedef) * - * Callbacks of this type are used to provide asynchronous + * Callbacks of this type are used to provide asynchronous * notification that an rfapi_handle was invalidated * - * input: + * input: * pHandle Firmerly valid rfapi_handle returned to * client via rfapi_open(). * @@ -228,72 +217,67 @@ typedef void (rfapi_response_cb_t) (struct rfapi_next_hop_entry * next_hops, * ESTALE handle invalidated by configuration change * *------------------------------------------*/ -typedef void (rfapi_nve_close_cb_t) (rfapi_handle pHandle, int reason); +typedef void(rfapi_nve_close_cb_t)(rfapi_handle pHandle, int reason); /*------------------------------------------ * rfp_cfg_write_cb_t (callback typedef) * * This callback is used to generate output for any config parameters - * that may supported by RFP via RFP defined vty commands at the bgp + * that may supported by RFP via RFP defined vty commands at the bgp * level. See loglevel as an example. * - * input: + * input: * vty -- quagga vty context * rfp_start_val -- value returned by rfp_start * * output: * to vty, rfp related configuration * - * return value: + * return value: * lines written --------------------------------------------*/ -typedef int (rfp_cfg_write_cb_t) (struct vty * vty, void *rfp_start_val); +typedef int(rfp_cfg_write_cb_t)(struct vty *vty, void *rfp_start_val); /*------------------------------------------ * rfp_cfg_group_write_cb_t (callback typedef) * * This callback is used to generate output for any config parameters - * that may supported by RFP via RFP defined vty commands at the + * that may supported by RFP via RFP defined vty commands at the * L2 or NVE level. See loglevel as an example. * - * input: + * input: * vty quagga vty context * rfp_start_val value returned by rfp_start * type group type * name group name - * rfp_cfg_group Pointer to configuration structure + * rfp_cfg_group Pointer to configuration structure * * output: * to vty, rfp related configuration * - * return value: + * return value: * lines written --------------------------------------------*/ -typedef enum -{ - RFAPI_RFP_CFG_GROUP_DEFAULT, - RFAPI_RFP_CFG_GROUP_NVE, - RFAPI_RFP_CFG_GROUP_L2 +typedef enum { + RFAPI_RFP_CFG_GROUP_DEFAULT, + RFAPI_RFP_CFG_GROUP_NVE, + RFAPI_RFP_CFG_GROUP_L2 } rfapi_rfp_cfg_group_type; -typedef int (rfp_cfg_group_write_cb_t) (struct vty * vty, - void *rfp_start_val, - rfapi_rfp_cfg_group_type type, - const char *name, - void *rfp_cfg_group); +typedef int(rfp_cfg_group_write_cb_t)(struct vty *vty, void *rfp_start_val, + rfapi_rfp_cfg_group_type type, + const char *name, void *rfp_cfg_group); /*********************************************************************** * Configuration related defines and structures ***********************************************************************/ -struct rfapi_rfp_cb_methods -{ - rfp_cfg_write_cb_t *cfg_cb; /* show top level config */ - rfp_cfg_group_write_cb_t *cfg_group_cb; /* show group level config */ - rfapi_response_cb_t *response_cb; /* unsolicited responses */ - rfapi_response_cb_t *local_cb; /* local route add/delete */ - rfapi_nve_close_cb_t *close_cb; /* handle closed */ - +struct rfapi_rfp_cb_methods { + rfp_cfg_write_cb_t *cfg_cb; /* show top level config */ + rfp_cfg_group_write_cb_t *cfg_group_cb; /* show group level config */ + rfapi_response_cb_t *response_cb; /* unsolicited responses */ + rfapi_response_cb_t *local_cb; /* local route add/delete */ + rfapi_nve_close_cb_t *close_cb; /* handle closed */ }; /* @@ -303,7 +287,7 @@ struct rfapi_rfp_cb_methods */ #define RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY (60*120) -/* +/* * the factor that should be applied to a prefix's value * before using it to expire a withdrawn prefix, expressed as a percent. * Thus, a value of 100 means to use the exact value of , @@ -312,46 +296,44 @@ struct rfapi_rfp_cb_methods #define RFAPI_RFP_CFG_DEFAULT_HOLDDOWN_FACTOR 150 /* - * This is used by rfapi to determine if RFP is using/supports + * This is used by rfapi to determine if RFP is using/supports * a partial (i.e., cache) or full table download approach for * mapping information. When full table download approach is * used all information is passed to RFP after an initial - * rfapi_query. When partial table download is used, only - * information matching a query is passed. + * rfapi_query. When partial table download is used, only + * information matching a query is passed. */ -typedef enum -{ - RFAPI_RFP_DOWNLOAD_PARTIAL = 0, - RFAPI_RFP_DOWNLOAD_FULL +typedef enum { + RFAPI_RFP_DOWNLOAD_PARTIAL = 0, + RFAPI_RFP_DOWNLOAD_FULL } rfapi_rfp_download_type; #define RFAPI_RFP_CFG_DEFAULT_FTD_ADVERTISEMENT_INTERVAL 1 -struct rfapi_rfp_cfg -{ - /* partial or full table download */ - rfapi_rfp_download_type download_type; /* default=partial */ - /* - * When full-table-download is enabled, this is the minimum - * number of seconds between times a non-queried prefix will - * be updated to a particular NVE. - * default: RFAPI_RFP_CFG_DEFAULT_FTD_ADVERTISEMENT_INTERVAL - */ - uint32_t ftd_advertisement_interval; - /* - * percentage of registration lifetime to continue to use information - * post soft-state refresh timeout - default: RFAPI_RFP_CFG_DEFAULT_HOLDDOWN_FACTOR - */ - uint32_t holddown_factor; - /* Control generation of updated RFP responses */ - uint8_t use_updated_response; /* default=0/no */ - /* when use_updated_response, also generate remove responses */ - uint8_t use_removes; /* default=0/no */ +struct rfapi_rfp_cfg { + /* partial or full table download */ + rfapi_rfp_download_type download_type; /* default=partial */ + /* + * When full-table-download is enabled, this is the minimum + * number of seconds between times a non-queried prefix will + * be updated to a particular NVE. + * default: RFAPI_RFP_CFG_DEFAULT_FTD_ADVERTISEMENT_INTERVAL + */ + uint32_t ftd_advertisement_interval; + /* + * percentage of registration lifetime to continue to use information + * post soft-state refresh timeout + default: RFAPI_RFP_CFG_DEFAULT_HOLDDOWN_FACTOR + */ + uint32_t holddown_factor; + /* Control generation of updated RFP responses */ + uint8_t use_updated_response; /* default=0/no */ + /* when use_updated_response, also generate remove responses */ + uint8_t use_removes; /* default=0/no */ }; /*********************************************************************** - * Process related functions -- MUST be provided by the RFAPI user <<=== + * Process related functions -- MUST be provided by the RFAPI user <<=== ***********************************************************************/ /*------------------------------------------ @@ -359,38 +341,35 @@ struct rfapi_rfp_cfg * * This function will start the RFP code * - * input: + * input: * master quagga thread_master to tie into bgpd threads - * + * * output: - * cfgp Pointer to rfapi_rfp_cfg (null = use defaults), + * cfgp Pointer to rfapi_rfp_cfg (null = use defaults), * copied by caller, updated via rfp_set_configuration * cbmp Pointer to rfapi_rfp_cb_methods, may be null * copied by caller, updated via rfapi_rfp_set_cb_methods - * return value: + * return value: * rfp_start_val rfp returned value passed on rfp_stop and other rfapi calls --------------------------------------------*/ -extern void * -rfp_start ( - struct thread_master *master, - struct rfapi_rfp_cfg **cfgp, - struct rfapi_rfp_cb_methods **cbmp); +extern void *rfp_start(struct thread_master *master, + struct rfapi_rfp_cfg **cfgp, + struct rfapi_rfp_cb_methods **cbmp); /*------------------------------------------ * rfp_stop * * This function is called on shutdown to trigger RFP cleanup * - * input: + * input: * rfp_start_val * * output: * none * - * return value: + * return value: --------------------------------------------*/ -extern void -rfp_stop (void *rfp_start_val); +extern void rfp_stop(void *rfp_start_val); /*********************************************************************** * RFP processing behavior configuration @@ -399,44 +378,40 @@ rfp_stop (void *rfp_start_val); /*------------------------------------------ * rfapi_rfp_set_configuration * - * This is used to change rfapi's processing behavior based on - * RFP requirements. + * This is used to change rfapi's processing behavior based on + * RFP requirements. * - * input: + * input: * rfp_start_val value returned by rfp_start * rfapi_rfp_cfg Pointer to configuration structure * * output: * none * - * return value: + * return value: * 0 Success * ENXIO Unabled to locate configured BGP/VNC --------------------------------------------*/ -extern int -rfapi_rfp_set_configuration ( - void *rfp_start_val, - struct rfapi_rfp_cfg *rfp_cfg); +extern int rfapi_rfp_set_configuration(void *rfp_start_val, + struct rfapi_rfp_cfg *rfp_cfg); /*------------------------------------------ * rfapi_rfp_set_cb_methods * - * Change registered callback functions for asynchronous notifications + * Change registered callback functions for asynchronous notifications * from RFAPI to the RFP client. * - * input: + * input: * rfp_start_val value by rfp_start * methods Pointer to struct rfapi_rfp_cb_methods containing * pointers to callback methods as described above * - * return value: + * return value: * 0 Success * ENXIO BGP or VNC not configured *------------------------------------------*/ -extern int -rfapi_rfp_set_cb_methods ( - void *rfp_start_val, - struct rfapi_rfp_cb_methods *methods); +extern int rfapi_rfp_set_cb_methods(void *rfp_start_val, + struct rfapi_rfp_cb_methods *methods); /*********************************************************************** * RFP group specific configuration @@ -446,12 +421,12 @@ rfapi_rfp_set_cb_methods ( * rfapi_rfp_init_group_config_ptr_vty * * This is used to init or return a previously init'ed group specific - * configuration pointer. Group is identified by vty context. + * configuration pointer. Group is identified by vty context. * NOTE: size is ignored when a previously init'ed value is returned. * RFAPI frees rfp_cfg_group when group is deleted during reconfig, * bgp restart or shutdown. * - * input: + * input: * rfp_start_val value returned by rfp_start * type group type * vty quagga vty context @@ -460,25 +435,23 @@ rfapi_rfp_set_cb_methods ( * output: * none * - * return value: + * return value: * rfp_cfg_group NULL or Pointer to configuration structure --------------------------------------------*/ -extern void * -rfapi_rfp_init_group_config_ptr_vty ( - void *rfp_start_val, - rfapi_rfp_cfg_group_type type, - struct vty *vty, - uint32_t size); +extern void *rfapi_rfp_init_group_config_ptr_vty(void *rfp_start_val, + rfapi_rfp_cfg_group_type type, + struct vty *vty, + uint32_t size); /*------------------------------------------ * rfapi_rfp_get_group_config_ptr_vty * * This is used to get group specific configuration pointer. - * Group is identified by type and vty context. + * Group is identified by type and vty context. * RFAPI frees rfp_cfg_group when group is deleted during reconfig, * bgp restart or shutdown. * - * input: + * input: * rfp_start_val value returned by rfp_start * type group type * vty quagga vty context @@ -487,43 +460,40 @@ rfapi_rfp_init_group_config_ptr_vty ( * none * * return value: - * rfp_cfg_group Pointer to configuration structure + * rfp_cfg_group Pointer to configuration structure --------------------------------------------*/ -extern void * -rfapi_rfp_get_group_config_ptr_vty ( - void *rfp_start_val, - rfapi_rfp_cfg_group_type type, - struct vty *vty); +extern void *rfapi_rfp_get_group_config_ptr_vty(void *rfp_start_val, + rfapi_rfp_cfg_group_type type, + struct vty *vty); /*------------------------------------------ * rfp_group_config_search_cb_t (callback typedef) * - * This callback is used to called from within a + * This callback is used to called from within a * rfapi_rfp_get_group_config_ptr to check if the rfp_cfg_group * matches the search criteria * - * input: + * input: * criteria RFAPI caller provided serach criteria * rfp_cfg_group Pointer to configuration structure | NULL * * output: * - * return value: + * return value: * 0 Match/Success * ENOENT No matching --------------------------------------------*/ -typedef int (rfp_group_config_search_cb_t) (void *criteria, - void *rfp_cfg_group); +typedef int(rfp_group_config_search_cb_t)(void *criteria, void *rfp_cfg_group); /*------------------------------------------ * rfapi_rfp_get_group_config_ptr_name * * This is used to get group specific configuration pointer. - * Group is identified by type and name context. + * Group is identified by type and name context. * RFAPI frees rfp_cfg_group when group is deleted during reconfig, * bgp restart or shutdown. * - * input: + * input: * rfp_start_val value returned by rfp_start * type group type * name group name @@ -534,15 +504,11 @@ typedef int (rfp_group_config_search_cb_t) (void *criteria, * none * * return value: - * rfp_cfg_group Pointer to configuration structure + * rfp_cfg_group Pointer to configuration structure --------------------------------------------*/ -extern void * -rfapi_rfp_get_group_config_ptr_name ( - void *rfp_start_val, - rfapi_rfp_cfg_group_type type, - const char *name, - void *criteria, - rfp_group_config_search_cb_t *search_cb); +extern void *rfapi_rfp_get_group_config_ptr_name( + void *rfp_start_val, rfapi_rfp_cfg_group_type type, const char *name, + void *criteria, rfp_group_config_search_cb_t *search_cb); /*------------------------------------------ * rfapi_rfp_get_l2_group_config_ptr_lni @@ -550,9 +516,9 @@ rfapi_rfp_get_group_config_ptr_name ( * This is used to get group specific configuration pointer. * Group is identified by type and logical network identifier. * RFAPI frees rfp_cfg_group when group is deleted during reconfig, - * bgp restart or shutdown. + * bgp restart or shutdown. * - * input: + * input: * rfp_start_val value returned by rfp_start * logical_net_id group logical network identifier * criteria RFAPI caller provided serach criteria @@ -562,14 +528,12 @@ rfapi_rfp_get_group_config_ptr_name ( * none * * return value: - * rfp_cfg_group Pointer to configuration structure + * rfp_cfg_group Pointer to configuration structure --------------------------------------------*/ extern void * -rfapi_rfp_get_l2_group_config_ptr_lni ( - void *rfp_start_val, - uint32_t logical_net_id, - void *criteria, - rfp_group_config_search_cb_t *search_cb); +rfapi_rfp_get_l2_group_config_ptr_lni(void *rfp_start_val, + uint32_t logical_net_id, void *criteria, + rfp_group_config_search_cb_t *search_cb); /*********************************************************************** * NVE Sessions @@ -581,7 +545,7 @@ rfapi_rfp_get_l2_group_config_ptr_lni ( * This function initializes a NVE record and associates it with * the specified VN and underlay network addresses * - * input: + * input: * rfp_start_val value returned by rfp_start * vn NVE virtual network address * @@ -599,13 +563,13 @@ rfapi_rfp_get_l2_group_config_ptr_lni ( * * output: * response_lifetime The length of time that responses sent to this - * NVE are valid. + * NVE are valid. * * pHandle pointer to location to store rfapi handle. The * handle must be passed on subsequent rfapi_ calls. * * - * return value: + * return value: * 0 Success * EEXIST NVE with this {vn,un} already open * ENOENT No matching nve group config @@ -615,15 +579,11 @@ rfapi_rfp_get_l2_group_config_ptr_lni ( * but underlay network address is not IPv4 * EDEADLK Called from within a callback procedure *------------------------------------------*/ -extern int -rfapi_open ( - void *rfp_start_val, - struct rfapi_ip_addr *vn, - struct rfapi_ip_addr *un, - struct rfapi_un_option *default_options, - uint32_t *response_lifetime, - void *userdata, - rfapi_handle *pHandle); +extern int rfapi_open(void *rfp_start_val, struct rfapi_ip_addr *vn, + struct rfapi_ip_addr *un, + struct rfapi_un_option *default_options, + uint32_t *response_lifetime, void *userdata, + rfapi_handle *pHandle); /*------------------------------------------ @@ -633,7 +593,7 @@ rfapi_open ( * from within a rfapi callback procedure is permitted (the close * will be completed asynchronously after the callback finishes). * - * input: + * input: * rfd: rfapi descriptor returned by rfapi_open * * output: @@ -643,15 +603,14 @@ rfapi_open ( * EBADF invalid handle * ENXIO BGP or VNC not configured *------------------------------------------*/ -extern int -rfapi_close (rfapi_handle rfd); +extern int rfapi_close(rfapi_handle rfd); /*------------------------------------------ * rfapi_check * * Test rfapi descriptor * - * input: + * input: * rfd: rfapi descriptor returned by rfapi_open * * output: @@ -664,8 +623,7 @@ rfapi_close (rfapi_handle rfd); * ENXIO BGP or VNC not configured * EAFNOSUPPORT Internal addressing error *------------------------------------------*/ -extern int -rfapi_check (rfapi_handle rfd); +extern int rfapi_check(rfapi_handle rfd); /*********************************************************************** * NVE Routes @@ -674,14 +632,14 @@ rfapi_check (rfapi_handle rfd); /*------------------------------------------ * rfapi_query * - * This function queries the RIB for a - * particular route. Note that this call may result in subsequent + * This function queries the RIB for a + * particular route. Note that this call may result in subsequent * callbacks to response_cb. Response callbacks can be cancelled * by calling rfapi_query_done. A duplicate query using the same target * will result in only one callback per change in next_hops. (i.e., * cancel/replace the prior query results.) * - * input: + * input: * rfd: rfapi descriptor returned by rfapi_open * target: the destination address * l2o ptr to L2 Options struct, NULL if not present in query @@ -701,20 +659,17 @@ rfapi_check (rfapi_handle rfd); * ESTALE descriptor is no longer usable; should be closed * EDEADLK Called from within a callback procedure --------------------------------------------*/ -extern int -rfapi_query ( - rfapi_handle rfd, - struct rfapi_ip_addr *target, - struct rfapi_l2address_option *l2o, - struct rfapi_next_hop_entry **ppNextHopEntry); +extern int rfapi_query(rfapi_handle rfd, struct rfapi_ip_addr *target, + struct rfapi_l2address_option *l2o, + struct rfapi_next_hop_entry **ppNextHopEntry); /*------------------------------------------ * rfapi_query_done * - * Notifies the rfapi that the user is no longer interested - * in the specified target. + * Notifies the rfapi that the user is no longer interested + * in the specified target. * - * input: + * input: * rfd: rfapi descriptor returned by rfapi_open * target: the destination address * @@ -728,16 +683,15 @@ rfapi_query ( * ESTALE descriptor is no longer usable; should be closed * EDEADLK Called from within a callback procedure --------------------------------------------*/ -extern int -rfapi_query_done (rfapi_handle rfd, struct rfapi_ip_addr *target); +extern int rfapi_query_done(rfapi_handle rfd, struct rfapi_ip_addr *target); /*------------------------------------------ * rfapi_query_done_all * - * Notifies the rfapi that the user is no longer interested - * in any target. + * Notifies the rfapi that the user is no longer interested + * in any target. * - * input: + * input: * rfd: rfapi descriptor returned by rfapi_open * * output: @@ -750,8 +704,7 @@ rfapi_query_done (rfapi_handle rfd, struct rfapi_ip_addr *target); * ESTALE descriptor is no longer usable; should be closed * EDEADLK Called from within a callback procedure --------------------------------------------*/ -extern int -rfapi_query_done_all (rfapi_handle rfd, int *count); +extern int rfapi_query_done_all(rfapi_handle rfd, int *count); /*------------------------------------------ * rfapi_register @@ -759,11 +712,11 @@ rfapi_query_done_all (rfapi_handle rfd, int *count); * Requests that reachability to the indicated prefix via this NVE * be advertised by BGP. If is non-zero, then the previously- * advertised prefix should be withdrawn. - * - * (This function should NOT be called if the rfapi_open() function + * + * (This function should NOT be called if the rfapi_open() function * returns NULL) * - * input: + * input: * rfd: rfapi descriptor returned by rfapi_open * prefix: A prefix to be registered or deregistered * lifetime Prefix lifetime in seconds, host byte order @@ -785,21 +738,16 @@ rfapi_query_done_all (rfapi_handle rfd, int *count); * EDEADLK Called from within a callback procedure --------------------------------------------*/ -typedef enum -{ - RFAPI_REGISTER_ADD, - RFAPI_REGISTER_WITHDRAW, - RFAPI_REGISTER_KILL +typedef enum { + RFAPI_REGISTER_ADD, + RFAPI_REGISTER_WITHDRAW, + RFAPI_REGISTER_KILL } rfapi_register_action; -extern int -rfapi_register ( - rfapi_handle rfd, - struct rfapi_ip_prefix *prefix, - uint32_t lifetime, - struct rfapi_un_option *options_un, - struct rfapi_vn_option *options_vn, - rfapi_register_action action); +extern int rfapi_register(rfapi_handle rfd, struct rfapi_ip_prefix *prefix, + uint32_t lifetime, struct rfapi_un_option *options_un, + struct rfapi_vn_option *options_vn, + rfapi_register_action action); /*********************************************************************** * Helper / Utility functions @@ -810,32 +758,30 @@ rfapi_register ( * * Get the virtual network address used by an NVE based on it's RFD * - * input: + * input: * rfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic * * output: * - * return value: + * return value: * vn NVE virtual network address *------------------------------------------*/ -extern struct rfapi_ip_addr * -rfapi_get_vn_addr (void *); +extern struct rfapi_ip_addr *rfapi_get_vn_addr(void *); /*------------------------------------------ * rfapi_get_un_addr * * Get the underlay network address used by an NVE based on it's RFD * - * input: + * input: * rfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic * * output: * - * return value: + * return value: * un NVE underlay network address *------------------------------------------*/ -extern struct rfapi_ip_addr * -rfapi_get_un_addr (void *); +extern struct rfapi_ip_addr *rfapi_get_un_addr(void *); /*------------------------------------------ * rfapi_error_str @@ -850,8 +796,7 @@ rfapi_get_un_addr (void *); * * const char * String *------------------------------------------*/ -extern const char * -rfapi_error_str (int code); +extern const char *rfapi_error_str(int code); /*------------------------------------------ * rfapi_get_rfp_start_val @@ -862,17 +807,16 @@ rfapi_error_str (int code); * void * bgp structure * * returns: - * void * + * void * *------------------------------------------*/ -extern void * -rfapi_get_rfp_start_val (void *bgpv); +extern void *rfapi_get_rfp_start_val(void *bgpv); /*------------------------------------------ * rfapi_compare_rfds * * Compare two generic rfapi descriptors. * - * input: + * input: * rfd1: rfapi descriptor returned by rfapi_open or rfapi_create_generic * rfd2: rfapi descriptor returned by rfapi_open or rfapi_create_generic * @@ -882,24 +826,22 @@ rfapi_get_rfp_start_val (void *bgpv); * 0 Mismatch * 1 Match *------------------------------------------*/ -extern int -rfapi_compare_rfds (void *rfd1, void *rfd2); +extern int rfapi_compare_rfds(void *rfd1, void *rfd2); /*------------------------------------------ * rfapi_free_next_hop_list * * Frees a next_hop_list returned by a rfapi_query invocation * - * input: - * list: a pointer to a response list (as a + * input: + * list: a pointer to a response list (as a * struct rfapi_next_hop_entry) to free. * * output: * * return value: None --------------------------------------------*/ -extern void -rfapi_free_next_hop_list (struct rfapi_next_hop_entry *list); +extern void rfapi_free_next_hop_list(struct rfapi_next_hop_entry *list); /*------------------------------------------ * rfapi_get_response_lifetime_default @@ -908,22 +850,21 @@ rfapi_free_next_hop_list (struct rfapi_next_hop_entry *list); * rfp_start_val value returned by rfp_start or * NULL (=use default instance) * - * input: + * input: * None * * output: * * return value: The bgp instance default lifetime for a response. --------------------------------------------*/ -extern int -rfapi_get_response_lifetime_default (void *rfp_start_val); +extern int rfapi_get_response_lifetime_default(void *rfp_start_val); /*------------------------------------------ * rfapi_is_vnc_configured * * Returns if VNC (BGP VPN messaging /VPN & encap SAFIs) are configured * - * input: + * input: * rfp_start_val value returned by rfp_start or * NULL (=use default instance) * @@ -933,15 +874,14 @@ rfapi_get_response_lifetime_default (void *rfp_start_val); * 0 Success * ENXIO VNC not configured --------------------------------------------*/ -extern int -rfapi_is_vnc_configured (void *rfp_start_val); +extern int rfapi_is_vnc_configured(void *rfp_start_val); /*------------------------------------------ * rfapi_bgp_lookup_by_rfp * * Find bgp instance pointer based on value returned by rfp_start * - * input: + * input: * rfp_start_val value returned by rfp_startor * NULL (=get default instance) * @@ -953,15 +893,14 @@ rfapi_is_vnc_configured (void *rfp_start_val); * NULL = not found * --------------------------------------------*/ -extern struct bgp * -rfapi_bgp_lookup_by_rfp (void *rfp_start_val); +extern struct bgp *rfapi_bgp_lookup_by_rfp(void *rfp_start_val); /*------------------------------------------ * rfapi_get_rfp_start_val_by_bgp * * Find bgp instance pointer based on value returned by rfp_start * - * input: + * input: * bgp bgp instance pointer * * output: @@ -972,8 +911,7 @@ rfapi_bgp_lookup_by_rfp (void *rfp_start_val); * NULL = not found * --------------------------------------------*/ -extern void * -rfapi_get_rfp_start_val_by_bgp (struct bgp *bgp); +extern void *rfapi_get_rfp_start_val_by_bgp(struct bgp *bgp); #endif /* ENABLE_BGP_VNC */ diff --git a/bgpd/rfapi/rfapi_ap.c b/bgpd/rfapi/rfapi_ap.c index fac28cd74..3112505d4 100644 --- a/bgpd/rfapi/rfapi_ap.c +++ b/bgpd/rfapi/rfapi_ap.c @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -83,541 +83,476 @@ * is used to spread out the sort for adbs with the same lifetime * and thereby make the skip list operations more efficient. */ -static int -sl_adb_lifetime_cmp (void *adb1, void *adb2) +static int sl_adb_lifetime_cmp(void *adb1, void *adb2) { - struct rfapi_adb *a1 = adb1; - struct rfapi_adb *a2 = adb2; + struct rfapi_adb *a1 = adb1; + struct rfapi_adb *a2 = adb2; - if (a1->lifetime < a2->lifetime) - return -1; - if (a1->lifetime > a2->lifetime) - return 1; + if (a1->lifetime < a2->lifetime) + return -1; + if (a1->lifetime > a2->lifetime) + return 1; - if (a1 < a2) - return -1; - if (a1 > a2) - return 1; + if (a1 < a2) + return -1; + if (a1 > a2) + return 1; - return 0; + return 0; } -void -rfapiApInit (struct rfapi_advertised_prefixes *ap) +void rfapiApInit(struct rfapi_advertised_prefixes *ap) { - ap->ipN_by_prefix = skiplist_new (0, rfapi_rib_key_cmp, NULL); - ap->ip0_by_ether = skiplist_new (0, rfapi_rib_key_cmp, NULL); - ap->by_lifetime = skiplist_new (0, sl_adb_lifetime_cmp, NULL); + ap->ipN_by_prefix = skiplist_new(0, rfapi_rib_key_cmp, NULL); + ap->ip0_by_ether = skiplist_new(0, rfapi_rib_key_cmp, NULL); + ap->by_lifetime = skiplist_new(0, sl_adb_lifetime_cmp, NULL); } -void -rfapiApRelease (struct rfapi_advertised_prefixes *ap) +void rfapiApRelease(struct rfapi_advertised_prefixes *ap) { - struct rfapi_adb *adb; - - /* Free ADBs and lifetime items */ - while (0 == skiplist_first (ap->by_lifetime, NULL, (void **) &adb)) - { - rfapiAdbFree (adb); - skiplist_delete_first (ap->by_lifetime); - } - - while (0 == skiplist_delete_first (ap->ipN_by_prefix)); - while (0 == skiplist_delete_first (ap->ip0_by_ether)); - - /* Free lists */ - skiplist_free (ap->ipN_by_prefix); - skiplist_free (ap->ip0_by_ether); - skiplist_free (ap->by_lifetime); - - ap->ipN_by_prefix = NULL; - ap->ip0_by_ether = NULL; - ap->by_lifetime = NULL; + struct rfapi_adb *adb; + + /* Free ADBs and lifetime items */ + while (0 == skiplist_first(ap->by_lifetime, NULL, (void **)&adb)) { + rfapiAdbFree(adb); + skiplist_delete_first(ap->by_lifetime); + } + + while (0 == skiplist_delete_first(ap->ipN_by_prefix)) + ; + while (0 == skiplist_delete_first(ap->ip0_by_ether)) + ; + + /* Free lists */ + skiplist_free(ap->ipN_by_prefix); + skiplist_free(ap->ip0_by_ether); + skiplist_free(ap->by_lifetime); + + ap->ipN_by_prefix = NULL; + ap->ip0_by_ether = NULL; + ap->by_lifetime = NULL; } -int -rfapiApCount (struct rfapi_descriptor *rfd) +int rfapiApCount(struct rfapi_descriptor *rfd) { - if (!rfd->advertised.by_lifetime) - return 0; + if (!rfd->advertised.by_lifetime) + return 0; - return skiplist_count (rfd->advertised.by_lifetime); + return skiplist_count(rfd->advertised.by_lifetime); } -int -rfapiApCountAll (struct bgp *bgp) +int rfapiApCountAll(struct bgp *bgp) { - struct rfapi *h; - struct listnode *node; - struct rfapi_descriptor *rfd; - int total = 0; - - h = bgp->rfapi; - if (h) - { - for (ALL_LIST_ELEMENTS_RO (&h->descriptors, node, rfd)) - { - total += rfapiApCount (rfd); - } - } - return total; + struct rfapi *h; + struct listnode *node; + struct rfapi_descriptor *rfd; + int total = 0; + + h = bgp->rfapi; + if (h) { + for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) { + total += rfapiApCount(rfd); + } + } + return total; } -void -rfapiApReadvertiseAll (struct bgp *bgp, struct rfapi_descriptor *rfd) +void rfapiApReadvertiseAll(struct bgp *bgp, struct rfapi_descriptor *rfd) { - struct rfapi_adb *adb; - void *cursor = NULL; - int rc; - - for (rc = - skiplist_next (rfd->advertised.by_lifetime, NULL, (void **) &adb, - &cursor); rc == 0; - rc = - skiplist_next (rfd->advertised.by_lifetime, NULL, (void **) &adb, - &cursor)) - { - - struct prefix_rd prd; - uint32_t local_pref = rfp_cost_to_localpref (adb->cost); - - prd = rfd->rd; - prd.family = AF_UNSPEC; - prd.prefixlen = 64; - - /* - * TBD this is not quite right. When pfx_ip is 0/32 or 0/128, - * we need to substitute the VN address as the prefix - */ - add_vnc_route (rfd, bgp, SAFI_MPLS_VPN, &adb->u.s.prefix_ip, &prd, /* RD to use (0 for ENCAP) */ - &rfd->vn_addr, /* nexthop */ - &local_pref, &adb->lifetime, NULL, NULL, /* struct rfapi_un_option */ - NULL, /* struct rfapi_vn_option */ - rfd->rt_export_list, NULL, /* med */ - NULL, ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, 0); - } + struct rfapi_adb *adb; + void *cursor = NULL; + int rc; + + for (rc = skiplist_next(rfd->advertised.by_lifetime, NULL, + (void **)&adb, &cursor); + rc == 0; rc = skiplist_next(rfd->advertised.by_lifetime, NULL, + (void **)&adb, &cursor)) { + + struct prefix_rd prd; + uint32_t local_pref = rfp_cost_to_localpref(adb->cost); + + prd = rfd->rd; + prd.family = AF_UNSPEC; + prd.prefixlen = 64; + + /* + * TBD this is not quite right. When pfx_ip is 0/32 or 0/128, + * we need to substitute the VN address as the prefix + */ + add_vnc_route(rfd, bgp, SAFI_MPLS_VPN, &adb->u.s.prefix_ip, + &prd, /* RD to use (0 for ENCAP) */ + &rfd->vn_addr, /* nexthop */ + &local_pref, &adb->lifetime, NULL, + NULL, /* struct rfapi_un_option */ + NULL, /* struct rfapi_vn_option */ + rfd->rt_export_list, NULL, /* med */ + NULL, ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, 0); + } } -void -rfapiApWithdrawAll (struct bgp *bgp, struct rfapi_descriptor *rfd) +void rfapiApWithdrawAll(struct bgp *bgp, struct rfapi_descriptor *rfd) { - struct rfapi_adb *adb; - void *cursor; - int rc; - - - cursor = NULL; - for (rc = - skiplist_next (rfd->advertised.by_lifetime, NULL, (void **) &adb, - &cursor); rc == 0; - rc = - skiplist_next (rfd->advertised.by_lifetime, NULL, (void **) &adb, - &cursor)) - { - - struct prefix pfx_vn_buf; - struct prefix *pfx_ip; - - if (!(RFAPI_0_PREFIX (&adb->u.s.prefix_ip) && - RFAPI_HOST_PREFIX (&adb->u.s.prefix_ip))) - { - - pfx_ip = &adb->u.s.prefix_ip; - - } - else - { - - pfx_ip = NULL; - - /* - * 0/32 or 0/128 => mac advertisement - */ - if (rfapiRaddr2Qprefix (&rfd->vn_addr, &pfx_vn_buf)) - { - /* - * Bad: it means we can't delete the route - */ - vnc_zlog_debug_verbose ("%s: BAD: handle has bad vn_addr: skipping", - __func__); - continue; - } - } - - del_vnc_route (rfd, rfd->peer, bgp, SAFI_MPLS_VPN, pfx_ip ? pfx_ip : &pfx_vn_buf, &adb->u.s.prd, /* RD to use (0 for ENCAP) */ - ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, NULL, 0); - } + struct rfapi_adb *adb; + void *cursor; + int rc; + + + cursor = NULL; + for (rc = skiplist_next(rfd->advertised.by_lifetime, NULL, + (void **)&adb, &cursor); + rc == 0; rc = skiplist_next(rfd->advertised.by_lifetime, NULL, + (void **)&adb, &cursor)) { + + struct prefix pfx_vn_buf; + struct prefix *pfx_ip; + + if (!(RFAPI_0_PREFIX(&adb->u.s.prefix_ip) + && RFAPI_HOST_PREFIX(&adb->u.s.prefix_ip))) { + + pfx_ip = &adb->u.s.prefix_ip; + + } else { + + pfx_ip = NULL; + + /* + * 0/32 or 0/128 => mac advertisement + */ + if (rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx_vn_buf)) { + /* + * Bad: it means we can't delete the route + */ + vnc_zlog_debug_verbose( + "%s: BAD: handle has bad vn_addr: skipping", + __func__); + continue; + } + } + + del_vnc_route(rfd, rfd->peer, bgp, SAFI_MPLS_VPN, + pfx_ip ? pfx_ip : &pfx_vn_buf, + &adb->u.s.prd, /* RD to use (0 for ENCAP) */ + ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, NULL, 0); + } } /* * returns nonzero if tunnel readvertisement is needed, 0 otherwise */ -static int -rfapiApAdjustLifetimeStats ( - struct rfapi_descriptor *rfd, - uint32_t *old_lifetime, /* set if removing/replacing */ - uint32_t *new_lifetime) /* set if replacing/adding */ +static int rfapiApAdjustLifetimeStats( + struct rfapi_descriptor *rfd, + uint32_t *old_lifetime, /* set if removing/replacing */ + uint32_t *new_lifetime) /* set if replacing/adding */ { - int advertise = 0; - int find_max = 0; - int find_min = 0; - - vnc_zlog_debug_verbose ("%s: rfd=%p, pOldLife=%p, pNewLife=%p", - __func__, rfd, old_lifetime, new_lifetime); - if (old_lifetime) - vnc_zlog_debug_verbose ("%s: OldLife=%d", __func__, *old_lifetime); - if (new_lifetime) - vnc_zlog_debug_verbose ("%s: NewLife=%d", __func__, *new_lifetime); - - if (new_lifetime) - { - /* - * Adding new lifetime - */ - if (old_lifetime) - { - /* - * replacing existing lifetime - */ - - - /* old and new are same */ - if (*old_lifetime == *new_lifetime) - return 0; - - if (*old_lifetime == rfd->min_prefix_lifetime) - { - find_min = 1; - } - if (*old_lifetime == rfd->max_prefix_lifetime) - { - find_max = 1; - } - - /* no need to search if new value is at or equals min|max */ - if (*new_lifetime <= rfd->min_prefix_lifetime) - { - rfd->min_prefix_lifetime = *new_lifetime; - find_min = 0; - } - if (*new_lifetime >= rfd->max_prefix_lifetime) - { - rfd->max_prefix_lifetime = *new_lifetime; - advertise = 1; - find_max = 0; - } - - } - else - { - /* - * Just adding new lifetime - */ - if (*new_lifetime < rfd->min_prefix_lifetime) - { - rfd->min_prefix_lifetime = *new_lifetime; - } - if (*new_lifetime > rfd->max_prefix_lifetime) - { - advertise = 1; - rfd->max_prefix_lifetime = *new_lifetime; - } - - } - } - else - { - /* - * Deleting - */ - - /* - * See if the max prefix lifetime for this NVE has decreased. - * The easy optimization: track min & max; walk the table only - * if they are different. - * The general optimization: index the advertised_prefixes - * table by lifetime. - * - * Note: for a given nve_descriptor, only one of the - * advertised_prefixes[] tables will be used: viz., the - * address family that matches the VN address. - * - */ - if (rfd->max_prefix_lifetime == rfd->min_prefix_lifetime) - { - - /* - * Common case: all lifetimes are the same. Only - * thing we need to do here is check if there are - * no exported routes left. In that case, reinitialize - * the max and min values. - */ - if (!rfapiApCount (rfd)) - { - rfd->max_prefix_lifetime = 0; - rfd->min_prefix_lifetime = UINT32_MAX; - } - - - } - else - { - if (old_lifetime) - { - if (*old_lifetime == rfd->min_prefix_lifetime) - { - find_min = 1; - } - if (*old_lifetime == rfd->max_prefix_lifetime) - { - find_max = 1; - } - } - } - } - - if (find_min || find_max) - { - uint32_t min = UINT32_MAX; - uint32_t max = 0; - - struct rfapi_adb *adb_min; - struct rfapi_adb *adb_max; - - if (!skiplist_first - (rfd->advertised.by_lifetime, (void **) &adb_min, NULL) - && !skiplist_last (rfd->advertised.by_lifetime, (void **) &adb_max, - NULL)) - { - - /* - * This should always work - */ - min = adb_min->lifetime; - max = adb_max->lifetime; - - } - else - { - - void *cursor; - struct rfapi_rib_key rk; - struct rfapi_adb *adb; - int rc; - - vnc_zlog_debug_verbose ("%s: walking to find new min/max", __func__); - - cursor = NULL; - for (rc = skiplist_next (rfd->advertised.ipN_by_prefix, - (void **) &rk, (void **) &adb, - &cursor); !rc; - rc = - skiplist_next (rfd->advertised.ipN_by_prefix, - (void **) &rk, (void **) &adb, &cursor)) - { - - uint32_t lt = adb->lifetime; - - if (lt > max) - max = lt; - if (lt < min) - min = lt; - } - cursor = NULL; - for (rc = skiplist_next (rfd->advertised.ip0_by_ether, - (void **) &rk, (void **) &adb, - &cursor); !rc; - rc = - skiplist_next (rfd->advertised.ip0_by_ether, (void **) &rk, - (void **) &adb, &cursor)) - { - - uint32_t lt = adb->lifetime; - - if (lt > max) - max = lt; - if (lt < min) - min = lt; - } - } - - /* - * trigger tunnel route update - * but only if we found a VPN route and it had - * a lifetime greater than 0 - */ - if (max && rfd->max_prefix_lifetime != max) - advertise = 1; - rfd->max_prefix_lifetime = max; - rfd->min_prefix_lifetime = min; - } - - vnc_zlog_debug_verbose ("%s: returning advertise=%d, min=%d, max=%d", - __func__, advertise, rfd->min_prefix_lifetime, - rfd->max_prefix_lifetime); - - return (advertise != 0); + int advertise = 0; + int find_max = 0; + int find_min = 0; + + vnc_zlog_debug_verbose("%s: rfd=%p, pOldLife=%p, pNewLife=%p", __func__, + rfd, old_lifetime, new_lifetime); + if (old_lifetime) + vnc_zlog_debug_verbose("%s: OldLife=%d", __func__, + *old_lifetime); + if (new_lifetime) + vnc_zlog_debug_verbose("%s: NewLife=%d", __func__, + *new_lifetime); + + if (new_lifetime) { + /* + * Adding new lifetime + */ + if (old_lifetime) { + /* + * replacing existing lifetime + */ + + + /* old and new are same */ + if (*old_lifetime == *new_lifetime) + return 0; + + if (*old_lifetime == rfd->min_prefix_lifetime) { + find_min = 1; + } + if (*old_lifetime == rfd->max_prefix_lifetime) { + find_max = 1; + } + + /* no need to search if new value is at or equals + * min|max */ + if (*new_lifetime <= rfd->min_prefix_lifetime) { + rfd->min_prefix_lifetime = *new_lifetime; + find_min = 0; + } + if (*new_lifetime >= rfd->max_prefix_lifetime) { + rfd->max_prefix_lifetime = *new_lifetime; + advertise = 1; + find_max = 0; + } + + } else { + /* + * Just adding new lifetime + */ + if (*new_lifetime < rfd->min_prefix_lifetime) { + rfd->min_prefix_lifetime = *new_lifetime; + } + if (*new_lifetime > rfd->max_prefix_lifetime) { + advertise = 1; + rfd->max_prefix_lifetime = *new_lifetime; + } + } + } else { + /* + * Deleting + */ + + /* + * See if the max prefix lifetime for this NVE has decreased. + * The easy optimization: track min & max; walk the table only + * if they are different. + * The general optimization: index the advertised_prefixes + * table by lifetime. + * + * Note: for a given nve_descriptor, only one of the + * advertised_prefixes[] tables will be used: viz., the + * address family that matches the VN address. + * + */ + if (rfd->max_prefix_lifetime == rfd->min_prefix_lifetime) { + + /* + * Common case: all lifetimes are the same. Only + * thing we need to do here is check if there are + * no exported routes left. In that case, reinitialize + * the max and min values. + */ + if (!rfapiApCount(rfd)) { + rfd->max_prefix_lifetime = 0; + rfd->min_prefix_lifetime = UINT32_MAX; + } + + + } else { + if (old_lifetime) { + if (*old_lifetime == rfd->min_prefix_lifetime) { + find_min = 1; + } + if (*old_lifetime == rfd->max_prefix_lifetime) { + find_max = 1; + } + } + } + } + + if (find_min || find_max) { + uint32_t min = UINT32_MAX; + uint32_t max = 0; + + struct rfapi_adb *adb_min; + struct rfapi_adb *adb_max; + + if (!skiplist_first(rfd->advertised.by_lifetime, + (void **)&adb_min, NULL) + && !skiplist_last(rfd->advertised.by_lifetime, + (void **)&adb_max, NULL)) { + + /* + * This should always work + */ + min = adb_min->lifetime; + max = adb_max->lifetime; + + } else { + + void *cursor; + struct rfapi_rib_key rk; + struct rfapi_adb *adb; + int rc; + + vnc_zlog_debug_verbose( + "%s: walking to find new min/max", __func__); + + cursor = NULL; + for (rc = skiplist_next(rfd->advertised.ipN_by_prefix, + (void **)&rk, (void **)&adb, + &cursor); + !rc; + rc = skiplist_next(rfd->advertised.ipN_by_prefix, + (void **)&rk, (void **)&adb, + &cursor)) { + + uint32_t lt = adb->lifetime; + + if (lt > max) + max = lt; + if (lt < min) + min = lt; + } + cursor = NULL; + for (rc = skiplist_next(rfd->advertised.ip0_by_ether, + (void **)&rk, (void **)&adb, + &cursor); + !rc; + rc = skiplist_next(rfd->advertised.ip0_by_ether, + (void **)&rk, (void **)&adb, + &cursor)) { + + uint32_t lt = adb->lifetime; + + if (lt > max) + max = lt; + if (lt < min) + min = lt; + } + } + + /* + * trigger tunnel route update + * but only if we found a VPN route and it had + * a lifetime greater than 0 + */ + if (max && rfd->max_prefix_lifetime != max) + advertise = 1; + rfd->max_prefix_lifetime = max; + rfd->min_prefix_lifetime = min; + } + + vnc_zlog_debug_verbose("%s: returning advertise=%d, min=%d, max=%d", + __func__, advertise, rfd->min_prefix_lifetime, + rfd->max_prefix_lifetime); + + return (advertise != 0); } -/* +/* * Return Value * * 0 No need to advertise tunnel route * non-0 advertise tunnel route */ -int -rfapiApAdd ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct prefix *pfx_ip, - struct prefix *pfx_eth, - struct prefix_rd *prd, - uint32_t lifetime, - uint8_t cost, - struct rfapi_l2address_option *l2o) /* other options TBD */ +int rfapiApAdd(struct bgp *bgp, struct rfapi_descriptor *rfd, + struct prefix *pfx_ip, struct prefix *pfx_eth, + struct prefix_rd *prd, uint32_t lifetime, uint8_t cost, + struct rfapi_l2address_option *l2o) /* other options TBD */ { - int rc; - struct rfapi_adb *adb; - uint32_t old_lifetime = 0; - int use_ip0 = 0; - struct rfapi_rib_key rk; - - rfapi_rib_key_init(pfx_ip, prd, pfx_eth, &rk); - if (RFAPI_0_PREFIX (pfx_ip) && RFAPI_HOST_PREFIX (pfx_ip)) - { - use_ip0 = 1; - assert (pfx_eth); - rc = - skiplist_search (rfd->advertised.ip0_by_ether, &rk, - (void **) &adb); - - } - else - { - - /* find prefix in advertised prefixes list */ - rc = - skiplist_search (rfd->advertised.ipN_by_prefix, &rk, - (void **) &adb); - } - - - if (rc) - { - /* Not found */ - adb = XCALLOC (MTYPE_RFAPI_ADB, sizeof (struct rfapi_adb)); - assert (adb); - adb->lifetime = lifetime; - adb->u.key = rk; - - if (use_ip0) - { - assert (pfx_eth); - skiplist_insert (rfd->advertised.ip0_by_ether, &adb->u.key, - adb); - } - else - { - skiplist_insert (rfd->advertised.ipN_by_prefix, &adb->u.key, - adb); - } - - skiplist_insert (rfd->advertised.by_lifetime, adb, adb); - } - else - { - old_lifetime = adb->lifetime; - if (old_lifetime != lifetime) - { - assert (!skiplist_delete (rfd->advertised.by_lifetime, adb, NULL)); - adb->lifetime = lifetime; - assert (!skiplist_insert (rfd->advertised.by_lifetime, adb, adb)); - } - } - adb->cost = cost; - if (l2o) - adb->l2o = *l2o; - else - memset (&adb->l2o, 0, sizeof (struct rfapi_l2address_option)); - - if (rfapiApAdjustLifetimeStats - (rfd, (rc ? NULL : &old_lifetime), &lifetime)) - return 1; - - return 0; + int rc; + struct rfapi_adb *adb; + uint32_t old_lifetime = 0; + int use_ip0 = 0; + struct rfapi_rib_key rk; + + rfapi_rib_key_init(pfx_ip, prd, pfx_eth, &rk); + if (RFAPI_0_PREFIX(pfx_ip) && RFAPI_HOST_PREFIX(pfx_ip)) { + use_ip0 = 1; + assert(pfx_eth); + rc = skiplist_search(rfd->advertised.ip0_by_ether, &rk, + (void **)&adb); + + } else { + + /* find prefix in advertised prefixes list */ + rc = skiplist_search(rfd->advertised.ipN_by_prefix, &rk, + (void **)&adb); + } + + + if (rc) { + /* Not found */ + adb = XCALLOC(MTYPE_RFAPI_ADB, sizeof(struct rfapi_adb)); + assert(adb); + adb->lifetime = lifetime; + adb->u.key = rk; + + if (use_ip0) { + assert(pfx_eth); + skiplist_insert(rfd->advertised.ip0_by_ether, + &adb->u.key, adb); + } else { + skiplist_insert(rfd->advertised.ipN_by_prefix, + &adb->u.key, adb); + } + + skiplist_insert(rfd->advertised.by_lifetime, adb, adb); + } else { + old_lifetime = adb->lifetime; + if (old_lifetime != lifetime) { + assert(!skiplist_delete(rfd->advertised.by_lifetime, + adb, NULL)); + adb->lifetime = lifetime; + assert(!skiplist_insert(rfd->advertised.by_lifetime, + adb, adb)); + } + } + adb->cost = cost; + if (l2o) + adb->l2o = *l2o; + else + memset(&adb->l2o, 0, sizeof(struct rfapi_l2address_option)); + + if (rfapiApAdjustLifetimeStats(rfd, (rc ? NULL : &old_lifetime), + &lifetime)) + return 1; + + return 0; } /* * After this function returns successfully, caller should call * rfapiAdjustLifetimeStats() and possibly rfapiTunnelRouteAnnounce() */ -int -rfapiApDelete ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct prefix *pfx_ip, - struct prefix *pfx_eth, - struct prefix_rd *prd, - int *advertise_tunnel) /* out */ +int rfapiApDelete(struct bgp *bgp, struct rfapi_descriptor *rfd, + struct prefix *pfx_ip, struct prefix *pfx_eth, + struct prefix_rd *prd, int *advertise_tunnel) /* out */ { - int rc; - struct rfapi_adb *adb; - uint32_t old_lifetime; - int use_ip0 = 0; - struct rfapi_rib_key rk; - - if (advertise_tunnel) - *advertise_tunnel = 0; - - rfapi_rib_key_init(pfx_ip, prd, pfx_eth, &rk); - /* find prefix in advertised prefixes list */ - if (RFAPI_0_PREFIX (pfx_ip) && RFAPI_HOST_PREFIX (pfx_ip)) - { - use_ip0 = 1; - assert (pfx_eth); - - rc = - skiplist_search (rfd->advertised.ip0_by_ether, &rk, - (void **) &adb); - - } - else - { - - /* find prefix in advertised prefixes list */ - rc = - skiplist_search (rfd->advertised.ipN_by_prefix, &rk, - (void **) &adb); - } - - if (rc) - { - return ENOENT; - } - - old_lifetime = adb->lifetime; - - if (use_ip0) - { - rc = skiplist_delete (rfd->advertised.ip0_by_ether, &rk, NULL); - } - else - { - rc = skiplist_delete (rfd->advertised.ipN_by_prefix, &rk, NULL); - } - assert (!rc); - - rc = skiplist_delete (rfd->advertised.by_lifetime, adb, NULL); - assert (!rc); - - rfapiAdbFree (adb); - - if (rfapiApAdjustLifetimeStats (rfd, &old_lifetime, NULL)) - { - if (advertise_tunnel) - *advertise_tunnel = 1; - } - - return 0; + int rc; + struct rfapi_adb *adb; + uint32_t old_lifetime; + int use_ip0 = 0; + struct rfapi_rib_key rk; + + if (advertise_tunnel) + *advertise_tunnel = 0; + + rfapi_rib_key_init(pfx_ip, prd, pfx_eth, &rk); + /* find prefix in advertised prefixes list */ + if (RFAPI_0_PREFIX(pfx_ip) && RFAPI_HOST_PREFIX(pfx_ip)) { + use_ip0 = 1; + assert(pfx_eth); + + rc = skiplist_search(rfd->advertised.ip0_by_ether, &rk, + (void **)&adb); + + } else { + + /* find prefix in advertised prefixes list */ + rc = skiplist_search(rfd->advertised.ipN_by_prefix, &rk, + (void **)&adb); + } + + if (rc) { + return ENOENT; + } + + old_lifetime = adb->lifetime; + + if (use_ip0) { + rc = skiplist_delete(rfd->advertised.ip0_by_ether, &rk, NULL); + } else { + rc = skiplist_delete(rfd->advertised.ipN_by_prefix, &rk, NULL); + } + assert(!rc); + + rc = skiplist_delete(rfd->advertised.by_lifetime, adb, NULL); + assert(!rc); + + rfapiAdbFree(adb); + + if (rfapiApAdjustLifetimeStats(rfd, &old_lifetime, NULL)) { + if (advertise_tunnel) + *advertise_tunnel = 1; + } + + return 0; } diff --git a/bgpd/rfapi/rfapi_ap.h b/bgpd/rfapi/rfapi_ap.h index c875a52e5..56977bd24 100644 --- a/bgpd/rfapi/rfapi_ap.h +++ b/bgpd/rfapi/rfapi_ap.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -56,44 +56,30 @@ #include "rfapi_rib.h" -extern void -rfapiApInit (struct rfapi_advertised_prefixes *ap); +extern void rfapiApInit(struct rfapi_advertised_prefixes *ap); -extern void -rfapiApRelease (struct rfapi_advertised_prefixes *ap); - -extern int -rfapiApCount (struct rfapi_descriptor *rfd); +extern void rfapiApRelease(struct rfapi_advertised_prefixes *ap); +extern int rfapiApCount(struct rfapi_descriptor *rfd); -extern int -rfapiApCountAll (struct bgp *bgp); -extern void -rfapiApReadvertiseAll (struct bgp *bgp, struct rfapi_descriptor *rfd); +extern int rfapiApCountAll(struct bgp *bgp); -extern void -rfapiApWithdrawAll (struct bgp *bgp, struct rfapi_descriptor *rfd); +extern void rfapiApReadvertiseAll(struct bgp *bgp, + struct rfapi_descriptor *rfd); -extern int -rfapiApAdd ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct prefix *pfx_ip, - struct prefix *pfx_eth, - struct prefix_rd *prd, - uint32_t lifetime, - uint8_t cost, - struct rfapi_l2address_option *l2o); /* other options TBD */ +extern void rfapiApWithdrawAll(struct bgp *bgp, struct rfapi_descriptor *rfd); extern int -rfapiApDelete ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct prefix *pfx_ip, - struct prefix *pfx_eth, - struct prefix_rd *prd, - int *advertise_tunnel); /* out */ +rfapiApAdd(struct bgp *bgp, struct rfapi_descriptor *rfd, struct prefix *pfx_ip, + struct prefix *pfx_eth, struct prefix_rd *prd, uint32_t lifetime, + uint8_t cost, + struct rfapi_l2address_option *l2o); /* other options TBD */ + +extern int rfapiApDelete(struct bgp *bgp, struct rfapi_descriptor *rfd, + struct prefix *pfx_ip, struct prefix *pfx_eth, + struct prefix_rd *prd, + int *advertise_tunnel); /* out */ #endif /* _QUAGGA_BGP_RFAPI_AP_H */ diff --git a/bgpd/rfapi/rfapi_backend.h b/bgpd/rfapi/rfapi_backend.h index a2537bd91..4455d66a2 100644 --- a/bgpd/rfapi/rfapi_backend.h +++ b/bgpd/rfapi/rfapi_backend.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -26,56 +26,44 @@ #include "bgpd/bgp_route.h" #include "bgpd/bgp_nexthop.h" -extern void rfapi_init (void); -extern void vnc_zebra_init (struct thread_master *master); -extern void vnc_zebra_destroy (void); +extern void rfapi_init(void); +extern void vnc_zebra_init(struct thread_master *master); +extern void vnc_zebra_destroy(void); -extern void rfapi_delete (struct bgp *); +extern void rfapi_delete(struct bgp *); -struct rfapi *bgp_rfapi_new (struct bgp *bgp); -void bgp_rfapi_destroy (struct bgp *bgp, struct rfapi *h); +struct rfapi *bgp_rfapi_new(struct bgp *bgp); +void bgp_rfapi_destroy(struct bgp *bgp, struct rfapi *h); -extern void -rfapiProcessUpdate (struct peer *peer, - void *rfd, - struct prefix *p, - struct prefix_rd *prd, - struct attr *attr, - afi_t afi, - safi_t safi, - u_char type, u_char sub_type, uint32_t * label); +extern void rfapiProcessUpdate(struct peer *peer, void *rfd, struct prefix *p, + struct prefix_rd *prd, struct attr *attr, + afi_t afi, safi_t safi, u_char type, + u_char sub_type, uint32_t *label); -extern void -rfapiProcessWithdraw (struct peer *peer, - void *rfd, - struct prefix *p, - struct prefix_rd *prd, - struct attr *attr, - afi_t afi, safi_t safi, u_char type, int kill); +extern void rfapiProcessWithdraw(struct peer *peer, void *rfd, struct prefix *p, + struct prefix_rd *prd, struct attr *attr, + afi_t afi, safi_t safi, u_char type, int kill); -extern void rfapiProcessPeerDown (struct peer *peer); +extern void rfapiProcessPeerDown(struct peer *peer); -extern void -vnc_zebra_announce (struct prefix *p, - struct bgp_info *new_select, struct bgp *bgp); +extern void vnc_zebra_announce(struct prefix *p, struct bgp_info *new_select, + struct bgp *bgp); -extern void -vnc_zebra_withdraw (struct prefix *p, struct bgp_info *old_select); +extern void vnc_zebra_withdraw(struct prefix *p, struct bgp_info *old_select); -extern void -rfapi_vty_out_vncinfo (struct vty *vty, - struct prefix *p, struct bgp_info *bi, safi_t safi); +extern void rfapi_vty_out_vncinfo(struct vty *vty, struct prefix *p, + struct bgp_info *bi, safi_t safi); -extern void vnc_direct_bgp_vpn_enable (struct bgp *bgp, afi_t afi); +extern void vnc_direct_bgp_vpn_enable(struct bgp *bgp, afi_t afi); -extern void vnc_direct_bgp_vpn_disable (struct bgp *bgp, afi_t afi); +extern void vnc_direct_bgp_vpn_disable(struct bgp *bgp, afi_t afi); -extern void vnc_direct_bgp_rh_vpn_enable (struct bgp *bgp, afi_t afi); +extern void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi); -extern void vnc_direct_bgp_rh_vpn_disable (struct bgp *bgp, afi_t afi); +extern void vnc_direct_bgp_rh_vpn_disable(struct bgp *bgp, afi_t afi); #endif /* ENABLE_BGP_VNC */ diff --git a/bgpd/rfapi/rfapi_descriptor_rfp_utils.c b/bgpd/rfapi/rfapi_descriptor_rfp_utils.c index d05b27128..3217d34e7 100644 --- a/bgpd/rfapi/rfapi_descriptor_rfp_utils.c +++ b/bgpd/rfapi/rfapi_descriptor_rfp_utils.c @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -36,15 +36,14 @@ #include "bgpd/rfapi/vnc_debug.h" -void * -rfapi_create_generic (struct rfapi_ip_addr *vn, struct rfapi_ip_addr *un) +void *rfapi_create_generic(struct rfapi_ip_addr *vn, struct rfapi_ip_addr *un) { - struct rfapi_descriptor *rfd; - rfd = XCALLOC (MTYPE_RFAPI_DESC, sizeof (struct rfapi_descriptor)); - vnc_zlog_debug_verbose ("%s: rfd=%p", __func__, rfd); - rfd->vn_addr = *vn; - rfd->un_addr = *un; - return (void *) rfd; + struct rfapi_descriptor *rfd; + rfd = XCALLOC(MTYPE_RFAPI_DESC, sizeof(struct rfapi_descriptor)); + vnc_zlog_debug_verbose("%s: rfd=%p", __func__, rfd); + rfd->vn_addr = *vn; + rfd->un_addr = *un; + return (void *)rfd; } /*------------------------------------------ @@ -52,20 +51,19 @@ rfapi_create_generic (struct rfapi_ip_addr *vn, struct rfapi_ip_addr *un) * * Compare two generic rfapi descriptors. * - * input: + * input: * grfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic * * output: * - * return value: + * return value: * *------------------------------------------*/ -void -rfapi_free_generic (void *grfd) +void rfapi_free_generic(void *grfd) { - struct rfapi_descriptor *rfd; - rfd = (struct rfapi_descriptor *) grfd; - XFREE (MTYPE_RFAPI_DESC, rfd); + struct rfapi_descriptor *rfd; + rfd = (struct rfapi_descriptor *)grfd; + XFREE(MTYPE_RFAPI_DESC, rfd); } @@ -74,7 +72,7 @@ rfapi_free_generic (void *grfd) * * Compare two generic rfapi descriptors. * - * input: + * input: * rfd1: rfapi descriptor returned by rfapi_open or rfapi_create_generic * rfd2: rfapi descriptor returned by rfapi_open or rfapi_create_generic * @@ -84,48 +82,45 @@ rfapi_free_generic (void *grfd) * 0 Mismatch * 1 Match *------------------------------------------*/ -int -rfapi_compare_rfds (void *rfd1, void *rfd2) +int rfapi_compare_rfds(void *rfd1, void *rfd2) { - struct rfapi_descriptor *rrfd1, *rrfd2; - int match = 0; + struct rfapi_descriptor *rrfd1, *rrfd2; + int match = 0; - rrfd1 = (struct rfapi_descriptor *) rfd1; - rrfd2 = (struct rfapi_descriptor *) rfd2; + rrfd1 = (struct rfapi_descriptor *)rfd1; + rrfd2 = (struct rfapi_descriptor *)rfd2; - if (rrfd1->vn_addr.addr_family == rrfd2->vn_addr.addr_family) - { - if (rrfd1->vn_addr.addr_family == AF_INET) - match = IPV4_ADDR_SAME (&(rrfd1->vn_addr.addr.v4), - &(rrfd2->vn_addr.addr.v4)); - else - match = IPV6_ADDR_SAME (&(rrfd1->vn_addr.addr.v6), - &(rrfd2->vn_addr.addr.v6)); - } + if (rrfd1->vn_addr.addr_family == rrfd2->vn_addr.addr_family) { + if (rrfd1->vn_addr.addr_family == AF_INET) + match = IPV4_ADDR_SAME(&(rrfd1->vn_addr.addr.v4), + &(rrfd2->vn_addr.addr.v4)); + else + match = IPV6_ADDR_SAME(&(rrfd1->vn_addr.addr.v6), + &(rrfd2->vn_addr.addr.v6)); + } - /* - * If the VN addresses don't match in all forms, - * give up. - */ - if (!match) - return 0; + /* + * If the VN addresses don't match in all forms, + * give up. + */ + if (!match) + return 0; - /* - * do the process again for the UN addresses. - */ - match = 0; - if (rrfd1->un_addr.addr_family == rrfd2->un_addr.addr_family) - { - /* VN addresses match - * UN address families match - * now check the actual UN addresses - */ - if (rrfd1->un_addr.addr_family == AF_INET) - match = IPV4_ADDR_SAME (&(rrfd1->un_addr.addr.v4), - &(rrfd2->un_addr.addr.v4)); - else - match = IPV6_ADDR_SAME (&(rrfd1->un_addr.addr.v6), - &(rrfd2->un_addr.addr.v6)); - } - return match; + /* + * do the process again for the UN addresses. + */ + match = 0; + if (rrfd1->un_addr.addr_family == rrfd2->un_addr.addr_family) { + /* VN addresses match + * UN address families match + * now check the actual UN addresses + */ + if (rrfd1->un_addr.addr_family == AF_INET) + match = IPV4_ADDR_SAME(&(rrfd1->un_addr.addr.v4), + &(rrfd2->un_addr.addr.v4)); + else + match = IPV6_ADDR_SAME(&(rrfd1->un_addr.addr.v6), + &(rrfd2->un_addr.addr.v6)); + } + return match; } diff --git a/bgpd/rfapi/rfapi_descriptor_rfp_utils.h b/bgpd/rfapi/rfapi_descriptor_rfp_utils.h index 04fbfbcec..dcc197961 100644 --- a/bgpd/rfapi/rfapi_descriptor_rfp_utils.h +++ b/bgpd/rfapi/rfapi_descriptor_rfp_utils.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -19,20 +19,20 @@ */ -extern void *rfapi_create_generic (struct rfapi_ip_addr *vn, - struct rfapi_ip_addr *un); +extern void *rfapi_create_generic(struct rfapi_ip_addr *vn, + struct rfapi_ip_addr *un); /*------------------------------------------ * rfapi_free_generic * * Compare two generic rfapi descriptors. * - * input: + * input: * grfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic * * output: * - * return value: + * return value: * *------------------------------------------*/ -extern void rfapi_free_generic (void *grfd); +extern void rfapi_free_generic(void *grfd); diff --git a/bgpd/rfapi/rfapi_encap_tlv.c b/bgpd/rfapi/rfapi_encap_tlv.c index 24bfb41bf..f31342e19 100644 --- a/bgpd/rfapi/rfapi_encap_tlv.c +++ b/bgpd/rfapi/rfapi_encap_tlv.c @@ -1,4 +1,4 @@ -/* +/* * Copyright 2015-2016, LabN Consulting, L.L.C. * * This program is free software; you can redistribute it and/or @@ -37,374 +37,350 @@ #include "bgpd/rfapi/bgp_rfapi_cfg.h" #include "bgpd/rfapi/vnc_debug.h" -static void -rfapi_add_endpoint_address_to_subtlv ( - struct bgp *bgp, - struct rfapi_ip_addr *ea, - struct bgp_tea_subtlv_remote_endpoint *subtlv) +static void rfapi_add_endpoint_address_to_subtlv( + struct bgp *bgp, struct rfapi_ip_addr *ea, + struct bgp_tea_subtlv_remote_endpoint *subtlv) { - subtlv->family = ea->addr_family; - if (subtlv->family == AF_INET) - subtlv->ip_address.v4 = ea->addr.v4; - else - subtlv->ip_address.v6 = ea->addr.v6; - subtlv->as4 = htonl (bgp->as); + subtlv->family = ea->addr_family; + if (subtlv->family == AF_INET) + subtlv->ip_address.v4 = ea->addr.v4; + else + subtlv->ip_address.v6 = ea->addr.v6; + subtlv->as4 = htonl(bgp->as); } bgp_encap_types -rfapi_tunneltype_option_to_tlv ( - struct bgp *bgp, - struct rfapi_ip_addr *ea, - struct rfapi_tunneltype_option *tto, - struct attr *attr, - int always_add) +rfapi_tunneltype_option_to_tlv(struct bgp *bgp, struct rfapi_ip_addr *ea, + struct rfapi_tunneltype_option *tto, + struct attr *attr, int always_add) { -#define _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(ttype) \ - if ((always_add || (bgp->rfapi_cfg && \ - !CHECK_FLAG(bgp->rfapi_cfg->flags, \ - BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP))) && \ - ea && !CHECK_SUBTLV_FLAG(&tto->bgpinfo.ttype, \ - BGP_TEA_SUBTLV_REMOTE_ENDPOINT)) { \ - rfapi_add_endpoint_address_to_subtlv(bgp, ea, \ - &tto->bgpinfo.ttype.st_endpoint); \ - SET_SUBTLV_FLAG(&tto->bgpinfo.ttype, BGP_TEA_SUBTLV_REMOTE_ENDPOINT); \ - } - - struct rfapi_tunneltype_option dto; - if (tto == NULL) - { /* create default type */ - tto = &dto; - memset (tto, 0, sizeof (dto)); - tto->type = RFAPI_BGP_ENCAP_TYPE_DEFAULT; - } - switch (tto->type) - { - case BGP_ENCAP_TYPE_L2TPV3_OVER_IP: - _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (l2tpv3_ip); - bgp_encap_type_l2tpv3overip_to_tlv (&tto->bgpinfo.l2tpv3_ip, attr); - break; - - case BGP_ENCAP_TYPE_GRE: - _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (gre); - bgp_encap_type_gre_to_tlv (&tto->bgpinfo.gre, attr); - break; - - case BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT: - _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (transmit_tunnel_endpoint); - bgp_encap_type_transmit_tunnel_endpoint (&tto->bgpinfo.transmit_tunnel_endpoint, - attr); - break; - - case BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE: - _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (ipsec_tunnel); - bgp_encap_type_ipsec_in_tunnel_mode_to_tlv (&tto->bgpinfo.ipsec_tunnel, - attr); - break; - - case BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE: - _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (ip_ipsec); - bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode_to_tlv - (&tto->bgpinfo.ip_ipsec, attr); - break; - - case BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE: - _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (mpls_ipsec); - bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode_to_tlv - (&tto->bgpinfo.mpls_ipsec, attr); - break; - - case BGP_ENCAP_TYPE_IP_IN_IP: - _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (ip_ip); - bgp_encap_type_ip_in_ip_to_tlv (&tto->bgpinfo.ip_ip, attr); - break; - - case BGP_ENCAP_TYPE_VXLAN: - _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (vxlan); - bgp_encap_type_vxlan_to_tlv (&tto->bgpinfo.vxlan, attr); - break; - - case BGP_ENCAP_TYPE_NVGRE: - _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (nvgre); - bgp_encap_type_nvgre_to_tlv (&tto->bgpinfo.nvgre, attr); - break; - - case BGP_ENCAP_TYPE_MPLS: - /* nothing to do for MPLS */ - break; - - case BGP_ENCAP_TYPE_MPLS_IN_GRE: - _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (mpls_gre); - bgp_encap_type_mpls_in_gre_to_tlv (&tto->bgpinfo.mpls_gre, attr); - break; - - case BGP_ENCAP_TYPE_VXLAN_GPE: - _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (vxlan_gpe); - bgp_encap_type_vxlan_gpe_to_tlv (&tto->bgpinfo.vxlan_gpe, attr); - break; - - case BGP_ENCAP_TYPE_MPLS_IN_UDP: - _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (mpls_udp); - bgp_encap_type_mpls_in_udp_to_tlv (&tto->bgpinfo.mpls_udp, attr); - break; - - case BGP_ENCAP_TYPE_PBB: - _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS (pbb); - bgp_encap_type_pbb_to_tlv (&tto->bgpinfo.pbb, attr); - break; - - default: - assert (0); - } - return tto->type; +#define _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(ttype) \ + if ((always_add \ + || (bgp->rfapi_cfg \ + && !CHECK_FLAG(bgp->rfapi_cfg->flags, \ + BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP))) \ + && ea \ + && !CHECK_SUBTLV_FLAG(&tto->bgpinfo.ttype, \ + BGP_TEA_SUBTLV_REMOTE_ENDPOINT)) { \ + rfapi_add_endpoint_address_to_subtlv( \ + bgp, ea, &tto->bgpinfo.ttype.st_endpoint); \ + SET_SUBTLV_FLAG(&tto->bgpinfo.ttype, \ + BGP_TEA_SUBTLV_REMOTE_ENDPOINT); \ + } + + struct rfapi_tunneltype_option dto; + if (tto == NULL) { /* create default type */ + tto = &dto; + memset(tto, 0, sizeof(dto)); + tto->type = RFAPI_BGP_ENCAP_TYPE_DEFAULT; + } + switch (tto->type) { + case BGP_ENCAP_TYPE_L2TPV3_OVER_IP: + _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(l2tpv3_ip); + bgp_encap_type_l2tpv3overip_to_tlv(&tto->bgpinfo.l2tpv3_ip, + attr); + break; + + case BGP_ENCAP_TYPE_GRE: + _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(gre); + bgp_encap_type_gre_to_tlv(&tto->bgpinfo.gre, attr); + break; + + case BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT: + _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(transmit_tunnel_endpoint); + bgp_encap_type_transmit_tunnel_endpoint( + &tto->bgpinfo.transmit_tunnel_endpoint, attr); + break; + + case BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE: + _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(ipsec_tunnel); + bgp_encap_type_ipsec_in_tunnel_mode_to_tlv( + &tto->bgpinfo.ipsec_tunnel, attr); + break; + + case BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE: + _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(ip_ipsec); + bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode_to_tlv( + &tto->bgpinfo.ip_ipsec, attr); + break; + + case BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE: + _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(mpls_ipsec); + bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode_to_tlv( + &tto->bgpinfo.mpls_ipsec, attr); + break; + + case BGP_ENCAP_TYPE_IP_IN_IP: + _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(ip_ip); + bgp_encap_type_ip_in_ip_to_tlv(&tto->bgpinfo.ip_ip, attr); + break; + + case BGP_ENCAP_TYPE_VXLAN: + _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(vxlan); + bgp_encap_type_vxlan_to_tlv(&tto->bgpinfo.vxlan, attr); + break; + + case BGP_ENCAP_TYPE_NVGRE: + _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(nvgre); + bgp_encap_type_nvgre_to_tlv(&tto->bgpinfo.nvgre, attr); + break; + + case BGP_ENCAP_TYPE_MPLS: + /* nothing to do for MPLS */ + break; + + case BGP_ENCAP_TYPE_MPLS_IN_GRE: + _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(mpls_gre); + bgp_encap_type_mpls_in_gre_to_tlv(&tto->bgpinfo.mpls_gre, attr); + break; + + case BGP_ENCAP_TYPE_VXLAN_GPE: + _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(vxlan_gpe); + bgp_encap_type_vxlan_gpe_to_tlv(&tto->bgpinfo.vxlan_gpe, attr); + break; + + case BGP_ENCAP_TYPE_MPLS_IN_UDP: + _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(mpls_udp); + bgp_encap_type_mpls_in_udp_to_tlv(&tto->bgpinfo.mpls_udp, attr); + break; + + case BGP_ENCAP_TYPE_PBB: + _RTTO_MAYBE_ADD_ENDPOINT_ADDRESS(pbb); + bgp_encap_type_pbb_to_tlv(&tto->bgpinfo.pbb, attr); + break; + + default: + assert(0); + } + return tto->type; } -struct rfapi_un_option * -rfapi_encap_tlv_to_un_option (struct attr *attr) +struct rfapi_un_option *rfapi_encap_tlv_to_un_option(struct attr *attr) { - struct rfapi_un_option *uo = NULL; - struct rfapi_tunneltype_option *tto; - int rc; - struct bgp_attr_encap_subtlv *stlv; - - /* no tunnel encap attr stored */ - if (!attr->encap_tunneltype) - return NULL; - - stlv = attr->encap_subtlvs; - - uo = XCALLOC (MTYPE_RFAPI_UN_OPTION, sizeof (struct rfapi_un_option)); - assert (uo); - uo->type = RFAPI_UN_OPTION_TYPE_TUNNELTYPE; - uo->v.tunnel.type = attr->encap_tunneltype; - tto = &uo->v.tunnel; - - switch (attr->encap_tunneltype) - { - case BGP_ENCAP_TYPE_L2TPV3_OVER_IP: - rc = tlv_to_bgp_encap_type_l2tpv3overip (stlv, &tto->bgpinfo.l2tpv3_ip); - break; - - case BGP_ENCAP_TYPE_GRE: - rc = tlv_to_bgp_encap_type_gre (stlv, &tto->bgpinfo.gre); - break; - - case BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT: - rc = tlv_to_bgp_encap_type_transmit_tunnel_endpoint (stlv, - &tto->bgpinfo.transmit_tunnel_endpoint); - break; - - case BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE: - rc = tlv_to_bgp_encap_type_ipsec_in_tunnel_mode (stlv, - &tto->bgpinfo.ipsec_tunnel); - break; - - case BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE: - rc = - tlv_to_bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode (stlv, - &tto->bgpinfo.ip_ipsec); - break; - - case BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE: - rc = - tlv_to_bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode - (stlv, &tto->bgpinfo.mpls_ipsec); - break; - - case BGP_ENCAP_TYPE_IP_IN_IP: - rc = tlv_to_bgp_encap_type_ip_in_ip (stlv, &tto->bgpinfo.ip_ip); - break; - - case BGP_ENCAP_TYPE_VXLAN: - rc = tlv_to_bgp_encap_type_vxlan (stlv, &tto->bgpinfo.vxlan); - break; - - case BGP_ENCAP_TYPE_NVGRE: - rc = tlv_to_bgp_encap_type_nvgre (stlv, &tto->bgpinfo.nvgre); - break; - - case BGP_ENCAP_TYPE_MPLS: - rc = tlv_to_bgp_encap_type_mpls (stlv, &tto->bgpinfo.mpls); - break; - - case BGP_ENCAP_TYPE_MPLS_IN_GRE: - rc = tlv_to_bgp_encap_type_mpls_in_gre (stlv, &tto->bgpinfo.mpls_gre); - break; - - case BGP_ENCAP_TYPE_VXLAN_GPE: - rc = tlv_to_bgp_encap_type_vxlan_gpe (stlv, &tto->bgpinfo.vxlan_gpe); - break; - - case BGP_ENCAP_TYPE_MPLS_IN_UDP: - rc = tlv_to_bgp_encap_type_mpls_in_udp (stlv, &tto->bgpinfo.mpls_udp); - break; - - case BGP_ENCAP_TYPE_PBB: - rc = tlv_to_bgp_encap_type_pbb (stlv, &tto->bgpinfo.pbb); - break; - - default: - vnc_zlog_debug_verbose ("%s: unknown tunnel type %d", - __func__, attr->encap_tunneltype); - rc = -1; - break; - } - if (rc) - { - XFREE (MTYPE_RFAPI_UN_OPTION, uo); - uo = NULL; - } - return uo; + struct rfapi_un_option *uo = NULL; + struct rfapi_tunneltype_option *tto; + int rc; + struct bgp_attr_encap_subtlv *stlv; + + /* no tunnel encap attr stored */ + if (!attr->encap_tunneltype) + return NULL; + + stlv = attr->encap_subtlvs; + + uo = XCALLOC(MTYPE_RFAPI_UN_OPTION, sizeof(struct rfapi_un_option)); + assert(uo); + uo->type = RFAPI_UN_OPTION_TYPE_TUNNELTYPE; + uo->v.tunnel.type = attr->encap_tunneltype; + tto = &uo->v.tunnel; + + switch (attr->encap_tunneltype) { + case BGP_ENCAP_TYPE_L2TPV3_OVER_IP: + rc = tlv_to_bgp_encap_type_l2tpv3overip( + stlv, &tto->bgpinfo.l2tpv3_ip); + break; + + case BGP_ENCAP_TYPE_GRE: + rc = tlv_to_bgp_encap_type_gre(stlv, &tto->bgpinfo.gre); + break; + + case BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT: + rc = tlv_to_bgp_encap_type_transmit_tunnel_endpoint( + stlv, &tto->bgpinfo.transmit_tunnel_endpoint); + break; + + case BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE: + rc = tlv_to_bgp_encap_type_ipsec_in_tunnel_mode( + stlv, &tto->bgpinfo.ipsec_tunnel); + break; + + case BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE: + rc = tlv_to_bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode( + stlv, &tto->bgpinfo.ip_ipsec); + break; + + case BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE: + rc = tlv_to_bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode( + stlv, &tto->bgpinfo.mpls_ipsec); + break; + + case BGP_ENCAP_TYPE_IP_IN_IP: + rc = tlv_to_bgp_encap_type_ip_in_ip(stlv, &tto->bgpinfo.ip_ip); + break; + + case BGP_ENCAP_TYPE_VXLAN: + rc = tlv_to_bgp_encap_type_vxlan(stlv, &tto->bgpinfo.vxlan); + break; + + case BGP_ENCAP_TYPE_NVGRE: + rc = tlv_to_bgp_encap_type_nvgre(stlv, &tto->bgpinfo.nvgre); + break; + + case BGP_ENCAP_TYPE_MPLS: + rc = tlv_to_bgp_encap_type_mpls(stlv, &tto->bgpinfo.mpls); + break; + + case BGP_ENCAP_TYPE_MPLS_IN_GRE: + rc = tlv_to_bgp_encap_type_mpls_in_gre(stlv, + &tto->bgpinfo.mpls_gre); + break; + + case BGP_ENCAP_TYPE_VXLAN_GPE: + rc = tlv_to_bgp_encap_type_vxlan_gpe(stlv, + &tto->bgpinfo.vxlan_gpe); + break; + + case BGP_ENCAP_TYPE_MPLS_IN_UDP: + rc = tlv_to_bgp_encap_type_mpls_in_udp(stlv, + &tto->bgpinfo.mpls_udp); + break; + + case BGP_ENCAP_TYPE_PBB: + rc = tlv_to_bgp_encap_type_pbb(stlv, &tto->bgpinfo.pbb); + break; + + default: + vnc_zlog_debug_verbose("%s: unknown tunnel type %d", __func__, + attr->encap_tunneltype); + rc = -1; + break; + } + if (rc) { + XFREE(MTYPE_RFAPI_UN_OPTION, uo); + uo = NULL; + } + return uo; } /*********************************************************************** * SUBTLV PRINT ***********************************************************************/ -static void -subtlv_print_encap_l2tpv3_over_ip ( - void *stream, - int column_offset, - struct bgp_tea_subtlv_encap_l2tpv3_over_ip *st) +static void subtlv_print_encap_l2tpv3_over_ip( + void *stream, int column_offset, + struct bgp_tea_subtlv_encap_l2tpv3_over_ip *st) { - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; - - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - if (!st) - return; - - fp (out, "%*s%s%s", column_offset, "", "SubTLV: Encap(L2TPv3 over IP)", - vty_newline); - fp (out, "%*s SessionID: %d%s", column_offset, "", st->sessionid, - vty_newline); - fp (out, "%*s Cookie: (length %d)%s", column_offset, "", st->cookie_length, - vty_newline); + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; + + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + if (!st) + return; + + fp(out, "%*s%s%s", column_offset, "", "SubTLV: Encap(L2TPv3 over IP)", + vty_newline); + fp(out, "%*s SessionID: %d%s", column_offset, "", st->sessionid, + vty_newline); + fp(out, "%*s Cookie: (length %d)%s", column_offset, "", + st->cookie_length, vty_newline); } -static void -subtlv_print_encap_gre ( - void *stream, - int column_offset, - struct bgp_tea_subtlv_encap_gre_key *st) +static void subtlv_print_encap_gre(void *stream, int column_offset, + struct bgp_tea_subtlv_encap_gre_key *st) { - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; - - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - if (!st) - return; - - fp (out, "%*s%s%s", column_offset, "", "SubTLV: Encap(GRE)", vty_newline); - fp (out, "%*s GRE key: %d (0x%x)%s", column_offset, "", st->gre_key, - st->gre_key, vty_newline); + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; + + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + if (!st) + return; + + fp(out, "%*s%s%s", column_offset, "", "SubTLV: Encap(GRE)", + vty_newline); + fp(out, "%*s GRE key: %d (0x%x)%s", column_offset, "", st->gre_key, + st->gre_key, vty_newline); } -static void -subtlv_print_encap_pbb ( - void *stream, - int column_offset, - struct bgp_tea_subtlv_encap_pbb *st) +static void subtlv_print_encap_pbb(void *stream, int column_offset, + struct bgp_tea_subtlv_encap_pbb *st) { - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; - - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - if (!st) - return; - - fp (out, "%*s%s%s", column_offset, "", "SubTLV: Encap(PBB)", vty_newline); - if (st->flag_isid) - { - fp (out, "%*s ISID: %d (0x%x)%s", column_offset, "", st->isid, - st->isid, vty_newline); - } - if (st->flag_vid) - { - fp (out, "%*s VID: %d (0x%x)%s", column_offset, "", st->vid, st->vid, - vty_newline); - } - fp (out, "%*s MACADDR %02x:%02x:%02x:%02x:%02x:%02x%s", - column_offset, "", - st->macaddr[0], - st->macaddr[1], - st->macaddr[2], - st->macaddr[3], st->macaddr[4], st->macaddr[5], vty_newline); + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; + + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + if (!st) + return; + + fp(out, "%*s%s%s", column_offset, "", "SubTLV: Encap(PBB)", + vty_newline); + if (st->flag_isid) { + fp(out, "%*s ISID: %d (0x%x)%s", column_offset, "", st->isid, + st->isid, vty_newline); + } + if (st->flag_vid) { + fp(out, "%*s VID: %d (0x%x)%s", column_offset, "", st->vid, + st->vid, vty_newline); + } + fp(out, "%*s MACADDR %02x:%02x:%02x:%02x:%02x:%02x%s", column_offset, + "", st->macaddr[0], st->macaddr[1], st->macaddr[2], st->macaddr[3], + st->macaddr[4], st->macaddr[5], vty_newline); } -static void -subtlv_print_proto_type ( - void *stream, - int column_offset, - struct bgp_tea_subtlv_proto_type *st) +static void subtlv_print_proto_type(void *stream, int column_offset, + struct bgp_tea_subtlv_proto_type *st) { - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; - - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - if (!st) - return; - - fp (out, "%*s%s%s", column_offset, "", "SubTLV: Encap(Proto Type)", - vty_newline); - fp (out, "%*s Proto %d (0x%x)%s", column_offset, "", st->proto, st->proto, - vty_newline); + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; + + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + if (!st) + return; + + fp(out, "%*s%s%s", column_offset, "", "SubTLV: Encap(Proto Type)", + vty_newline); + fp(out, "%*s Proto %d (0x%x)%s", column_offset, "", st->proto, + st->proto, vty_newline); } -static void -subtlv_print_color ( - void *stream, - int column_offset, - struct bgp_tea_subtlv_color *st) +static void subtlv_print_color(void *stream, int column_offset, + struct bgp_tea_subtlv_color *st) { - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; - - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - if (!st) - return; - - fp (out, "%*s%s%s", column_offset, "", "SubTLV: Color", vty_newline); - fp (out, "%*s Color: %d (0x%x)", column_offset, "", st->color, st->color, - vty_newline); + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; + + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + if (!st) + return; + + fp(out, "%*s%s%s", column_offset, "", "SubTLV: Color", vty_newline); + fp(out, "%*s Color: %d (0x%x)", column_offset, "", st->color, + st->color, vty_newline); } -static void -subtlv_print_ipsec_ta ( - void *stream, - int column_offset, - struct bgp_tea_subtlv_ipsec_ta *st) +static void subtlv_print_ipsec_ta(void *stream, int column_offset, + struct bgp_tea_subtlv_ipsec_ta *st) { - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; - - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - if (!st) - return; - - fp (out, "%*s%s%s", column_offset, "", "SubTLV: IPSEC TA", vty_newline); - fp (out, "%*s Authenticator Type: %d (0x%x)", column_offset, "", - st->authenticator_type, st->authenticator_type, vty_newline); - fp (out, "%*s Authenticator: (length %d)", column_offset, "", - st->authenticator_length, vty_newline); + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; + + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + if (!st) + return; + + fp(out, "%*s%s%s", column_offset, "", "SubTLV: IPSEC TA", vty_newline); + fp(out, "%*s Authenticator Type: %d (0x%x)", column_offset, "", + st->authenticator_type, st->authenticator_type, vty_newline); + fp(out, "%*s Authenticator: (length %d)", column_offset, "", + st->authenticator_length, vty_newline); } /*********************************************************************** @@ -412,396 +388,358 @@ subtlv_print_ipsec_ta ( ***********************************************************************/ static void -print_encap_type_l2tpv3overip ( - void *stream, - int column_offset, - struct bgp_encap_type_l2tpv3_over_ip *bet) +print_encap_type_l2tpv3overip(void *stream, int column_offset, + struct bgp_encap_type_l2tpv3_over_ip *bet) { - const char *type = "L2TPv3 over IP"; - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; - - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - if (!bet) - return; - - fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); - - subtlv_print_encap_l2tpv3_over_ip (stream, column_offset + 2, - &bet->st_encap); - subtlv_print_proto_type (stream, column_offset + 2, &bet->st_proto); - subtlv_print_color (stream, column_offset + 2, &bet->st_color); + const char *type = "L2TPv3 over IP"; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; + + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + if (!bet) + return; + + fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); + + subtlv_print_encap_l2tpv3_over_ip(stream, column_offset + 2, + &bet->st_encap); + subtlv_print_proto_type(stream, column_offset + 2, &bet->st_proto); + subtlv_print_color(stream, column_offset + 2, &bet->st_color); } -static void -print_encap_type_gre ( - void *stream, - int column_offset, - struct bgp_encap_type_gre *bet) +static void print_encap_type_gre(void *stream, int column_offset, + struct bgp_encap_type_gre *bet) { - const char *type = "GRE"; - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; - - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - if (!bet) - return; - - fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); - - subtlv_print_encap_gre (stream, column_offset + 2, &bet->st_encap); - subtlv_print_proto_type (stream, column_offset + 2, &bet->st_proto); - subtlv_print_color (stream, column_offset + 2, &bet->st_color); + const char *type = "GRE"; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; + + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + if (!bet) + return; + + fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); + + subtlv_print_encap_gre(stream, column_offset + 2, &bet->st_encap); + subtlv_print_proto_type(stream, column_offset + 2, &bet->st_proto); + subtlv_print_color(stream, column_offset + 2, &bet->st_color); } -static void -print_encap_type_ip_in_ip ( - void *stream, - int column_offset, - struct bgp_encap_type_ip_in_ip *bet) +static void print_encap_type_ip_in_ip(void *stream, int column_offset, + struct bgp_encap_type_ip_in_ip *bet) { - const char *type = "IP in IP"; - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; + const char *type = "IP in IP"; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - if (!bet) - return; + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + if (!bet) + return; - fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); + fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); - subtlv_print_proto_type (stream, column_offset + 2, &bet->st_proto); - subtlv_print_color (stream, column_offset + 2, &bet->st_color); + subtlv_print_proto_type(stream, column_offset + 2, &bet->st_proto); + subtlv_print_color(stream, column_offset + 2, &bet->st_color); } -static void -print_encap_type_transmit_tunnel_endpoint ( - void *stream, - int column_offset, - struct bgp_encap_type_transmit_tunnel_endpoint *bet) +static void print_encap_type_transmit_tunnel_endpoint( + void *stream, int column_offset, + struct bgp_encap_type_transmit_tunnel_endpoint *bet) { - const char *type = "Transmit Tunnel Endpoint"; - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; + const char *type = "Transmit Tunnel Endpoint"; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - if (!bet) - return; + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + if (!bet) + return; - fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); + fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); - /* no subtlvs for this type */ + /* no subtlvs for this type */ } -static void -print_encap_type_ipsec_in_tunnel_mode ( - void *stream, - int column_offset, - struct bgp_encap_type_ipsec_in_tunnel_mode *bet) +static void print_encap_type_ipsec_in_tunnel_mode( + void *stream, int column_offset, + struct bgp_encap_type_ipsec_in_tunnel_mode *bet) { - const char *type = "IPSEC in Tunnel mode"; - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; - - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - if (!bet) - return; - - fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); - subtlv_print_ipsec_ta (stream, column_offset + 2, &bet->st_ipsec_ta); + const char *type = "IPSEC in Tunnel mode"; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; + + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + if (!bet) + return; + + fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); + subtlv_print_ipsec_ta(stream, column_offset + 2, &bet->st_ipsec_ta); } -static void -print_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode ( - void *stream, - int column_offset, - struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet) +static void print_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode( + void *stream, int column_offset, + struct bgp_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode *bet) { - const char *type = "IP in IP Tunnel with IPSEC transport mode"; - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; + const char *type = "IP in IP Tunnel with IPSEC transport mode"; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - if (!bet) - return; + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + if (!bet) + return; - fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); + fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); - subtlv_print_ipsec_ta (stream, column_offset + 2, &bet->st_ipsec_ta); + subtlv_print_ipsec_ta(stream, column_offset + 2, &bet->st_ipsec_ta); } -static void -print_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode ( - void *stream, - int column_offset, - struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet) +static void print_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode( + void *stream, int column_offset, + struct bgp_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode *bet) { - const char *type = "MPLS in IP Tunnel with IPSEC transport mode"; - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; + const char *type = "MPLS in IP Tunnel with IPSEC transport mode"; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - if (!bet) - return; + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + if (!bet) + return; - fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); + fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); - subtlv_print_ipsec_ta (stream, column_offset + 2, &bet->st_ipsec_ta); + subtlv_print_ipsec_ta(stream, column_offset + 2, &bet->st_ipsec_ta); } -static void -print_encap_type_pbb ( - void *stream, - int column_offset, - struct bgp_encap_type_pbb *bet) +static void print_encap_type_pbb(void *stream, int column_offset, + struct bgp_encap_type_pbb *bet) { - const char *type = "PBB"; - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; + const char *type = "PBB"; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - if (!bet) - return; + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + if (!bet) + return; - fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); + fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); - subtlv_print_encap_pbb (stream, column_offset + 2, &bet->st_encap); + subtlv_print_encap_pbb(stream, column_offset + 2, &bet->st_encap); } -static void -print_encap_type_vxlan ( - void *stream, - int column_offset, - struct bgp_encap_type_vxlan *bet) +static void print_encap_type_vxlan(void *stream, int column_offset, + struct bgp_encap_type_vxlan *bet) { - const char *type = "VXLAN"; - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; + const char *type = "VXLAN"; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - if (!bet) - return; + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + if (!bet) + return; - fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); + fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); - /* no subtlvs for this type */ + /* no subtlvs for this type */ } -static void -print_encap_type_nvgre ( - void *stream, - int column_offset, - struct bgp_encap_type_nvgre *bet) +static void print_encap_type_nvgre(void *stream, int column_offset, + struct bgp_encap_type_nvgre *bet) { - const char *type = "NVGRE"; - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; + const char *type = "NVGRE"; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - if (!bet) - return; + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + if (!bet) + return; - fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); + fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); - /* no subtlvs for this type */ + /* no subtlvs for this type */ } -static void -print_encap_type_mpls ( - void *stream, - int column_offset, - struct bgp_encap_type_mpls *bet) +static void print_encap_type_mpls(void *stream, int column_offset, + struct bgp_encap_type_mpls *bet) { - const char *type = "MPLS"; - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; + const char *type = "MPLS"; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - if (!bet) - return; + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + if (!bet) + return; - fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); + fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); - /* no subtlvs for this type */ + /* no subtlvs for this type */ } -static void -print_encap_type_mpls_in_gre ( - void *stream, - int column_offset, - struct bgp_encap_type_mpls_in_gre *bet) +static void print_encap_type_mpls_in_gre(void *stream, int column_offset, + struct bgp_encap_type_mpls_in_gre *bet) { - const char *type = "MPLS in GRE"; - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; + const char *type = "MPLS in GRE"; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - if (!bet) - return; + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + if (!bet) + return; - fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); + fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); - /* no subtlvs for this type */ + /* no subtlvs for this type */ } -static void -print_encap_type_vxlan_gpe ( - void *stream, - int column_offset, - struct bgp_encap_type_vxlan_gpe *bet) +static void print_encap_type_vxlan_gpe(void *stream, int column_offset, + struct bgp_encap_type_vxlan_gpe *bet) { - const char *type = "VXLAN GPE"; - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; + const char *type = "VXLAN GPE"; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - if (!bet) - return; + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + if (!bet) + return; - fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); + fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); - /* no subtlvs for this type */ + /* no subtlvs for this type */ } -static void -print_encap_type_mpls_in_udp ( - void *stream, - int column_offset, - struct bgp_encap_type_mpls_in_udp *bet) +static void print_encap_type_mpls_in_udp(void *stream, int column_offset, + struct bgp_encap_type_mpls_in_udp *bet) { - const char *type = "MPLS in UDP"; - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; + const char *type = "MPLS in UDP"; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - if (!bet) - return; + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + if (!bet) + return; - fp (out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); + fp(out, "%*sTEA type %s%s", column_offset, "", type, vty_newline); - /* no subtlvs for this type */ + /* no subtlvs for this type */ } -void -rfapi_print_tunneltype_option ( - void *stream, - int column_offset, - struct rfapi_tunneltype_option *tto) +void rfapi_print_tunneltype_option(void *stream, int column_offset, + struct rfapi_tunneltype_option *tto) { - switch (tto->type) - { - case BGP_ENCAP_TYPE_L2TPV3_OVER_IP: - print_encap_type_l2tpv3overip (stream, column_offset, - &tto->bgpinfo.l2tpv3_ip); - break; - - case BGP_ENCAP_TYPE_GRE: - print_encap_type_gre (stream, column_offset, &tto->bgpinfo.gre); - break; - - case BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT: - print_encap_type_transmit_tunnel_endpoint (stream, column_offset, - &tto->bgpinfo.transmit_tunnel_endpoint); - break; - - case BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE: - print_encap_type_ipsec_in_tunnel_mode (stream, column_offset, - &tto->bgpinfo.ipsec_tunnel); - break; - - case BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE: - print_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode (stream, - column_offset, - &tto->bgpinfo.ip_ipsec); - break; - - case BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE: - print_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode (stream, - column_offset, - &tto->bgpinfo.mpls_ipsec); - break; - - case BGP_ENCAP_TYPE_IP_IN_IP: - print_encap_type_ip_in_ip (stream, column_offset, &tto->bgpinfo.ip_ip); - break; - - case BGP_ENCAP_TYPE_VXLAN: - print_encap_type_vxlan (stream, column_offset, &tto->bgpinfo.vxlan); - break; - - case BGP_ENCAP_TYPE_NVGRE: - print_encap_type_nvgre (stream, column_offset, &tto->bgpinfo.nvgre); - break; - - case BGP_ENCAP_TYPE_MPLS: - print_encap_type_mpls (stream, column_offset, &tto->bgpinfo.mpls); - break; - - case BGP_ENCAP_TYPE_MPLS_IN_GRE: - print_encap_type_mpls_in_gre (stream, column_offset, - &tto->bgpinfo.mpls_gre); - break; - - case BGP_ENCAP_TYPE_VXLAN_GPE: - print_encap_type_vxlan_gpe (stream, column_offset, - &tto->bgpinfo.vxlan_gpe); - break; - - case BGP_ENCAP_TYPE_MPLS_IN_UDP: - print_encap_type_mpls_in_udp (stream, column_offset, - &tto->bgpinfo.mpls_udp); - break; - - case BGP_ENCAP_TYPE_PBB: - print_encap_type_pbb (stream, column_offset, &tto->bgpinfo.pbb); - break; - - default: - assert (0); - } + switch (tto->type) { + case BGP_ENCAP_TYPE_L2TPV3_OVER_IP: + print_encap_type_l2tpv3overip(stream, column_offset, + &tto->bgpinfo.l2tpv3_ip); + break; + + case BGP_ENCAP_TYPE_GRE: + print_encap_type_gre(stream, column_offset, &tto->bgpinfo.gre); + break; + + case BGP_ENCAP_TYPE_TRANSMIT_TUNNEL_ENDPOINT: + print_encap_type_transmit_tunnel_endpoint( + stream, column_offset, + &tto->bgpinfo.transmit_tunnel_endpoint); + break; + + case BGP_ENCAP_TYPE_IPSEC_IN_TUNNEL_MODE: + print_encap_type_ipsec_in_tunnel_mode( + stream, column_offset, &tto->bgpinfo.ipsec_tunnel); + break; + + case BGP_ENCAP_TYPE_IP_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE: + print_encap_type_ip_in_ip_tunnel_with_ipsec_transport_mode( + stream, column_offset, &tto->bgpinfo.ip_ipsec); + break; + + case BGP_ENCAP_TYPE_MPLS_IN_IP_TUNNEL_WITH_IPSEC_TRANSPORT_MODE: + print_encap_type_mpls_in_ip_tunnel_with_ipsec_transport_mode( + stream, column_offset, &tto->bgpinfo.mpls_ipsec); + break; + + case BGP_ENCAP_TYPE_IP_IN_IP: + print_encap_type_ip_in_ip(stream, column_offset, + &tto->bgpinfo.ip_ip); + break; + + case BGP_ENCAP_TYPE_VXLAN: + print_encap_type_vxlan(stream, column_offset, + &tto->bgpinfo.vxlan); + break; + + case BGP_ENCAP_TYPE_NVGRE: + print_encap_type_nvgre(stream, column_offset, + &tto->bgpinfo.nvgre); + break; + + case BGP_ENCAP_TYPE_MPLS: + print_encap_type_mpls(stream, column_offset, + &tto->bgpinfo.mpls); + break; + + case BGP_ENCAP_TYPE_MPLS_IN_GRE: + print_encap_type_mpls_in_gre(stream, column_offset, + &tto->bgpinfo.mpls_gre); + break; + + case BGP_ENCAP_TYPE_VXLAN_GPE: + print_encap_type_vxlan_gpe(stream, column_offset, + &tto->bgpinfo.vxlan_gpe); + break; + + case BGP_ENCAP_TYPE_MPLS_IN_UDP: + print_encap_type_mpls_in_udp(stream, column_offset, + &tto->bgpinfo.mpls_udp); + break; + + case BGP_ENCAP_TYPE_PBB: + print_encap_type_pbb(stream, column_offset, &tto->bgpinfo.pbb); + break; + + default: + assert(0); + } } diff --git a/bgpd/rfapi/rfapi_encap_tlv.h b/bgpd/rfapi/rfapi_encap_tlv.h index 19e16a41a..57e1b5ef0 100644 --- a/bgpd/rfapi/rfapi_encap_tlv.h +++ b/bgpd/rfapi/rfapi_encap_tlv.h @@ -1,4 +1,4 @@ -/* +/* * Copyright 2015-2016, LabN Consulting, L.L.C. * * This program is free software; you can redistribute it and/or @@ -22,21 +22,14 @@ #define RFAPI_BGP_ENCAP_TYPE_DEFAULT BGP_ENCAP_TYPE_IP_IN_IP extern bgp_encap_types -rfapi_tunneltype_option_to_tlv ( - struct bgp *bgp, - struct rfapi_ip_addr *ea, - struct rfapi_tunneltype_option *tto, - struct attr *attr, - int always_add); +rfapi_tunneltype_option_to_tlv(struct bgp *bgp, struct rfapi_ip_addr *ea, + struct rfapi_tunneltype_option *tto, + struct attr *attr, int always_add); -extern struct rfapi_un_option * -rfapi_encap_tlv_to_un_option (struct attr *attr); +extern struct rfapi_un_option *rfapi_encap_tlv_to_un_option(struct attr *attr); -extern void -rfapi_print_tunneltype_option ( - void *stream, - int column_offset, - struct rfapi_tunneltype_option *tto); +extern void rfapi_print_tunneltype_option(void *stream, int column_offset, + struct rfapi_tunneltype_option *tto); #endif /* _QUAGGA_BGP_RFAPI_ENCAP_TLV_H */ diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c index dc8dc1ed2..d0379e1ef 100644 --- a/bgpd/rfapi/rfapi_import.c +++ b/bgpd/rfapi/rfapi_import.c @@ -1,22 +1,22 @@ - /* - * - * Copyright 2009-2016, LabN Consulting, L.L.C. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; see the file COPYING; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ +/* +* +* Copyright 2009-2016, LabN Consulting, L.L.C. +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; see the file COPYING; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* * File: rfapi_import.c @@ -38,7 +38,7 @@ #include "bgpd/bgp_ecommunity.h" #include "bgpd/bgp_attr.h" #include "bgpd/bgp_route.h" -#include "bgpd/bgp_mplsvpn.h" /* prefix_rd2str() */ +#include "bgpd/bgp_mplsvpn.h" /* prefix_rd2str() */ #include "bgpd/bgp_vnc_types.h" #include "bgpd/rfapi/rfapi.h" @@ -75,47 +75,44 @@ * Allocated for each withdraw timer instance; freed when the timer * expires or is canceled */ -struct rfapi_withdraw -{ - struct rfapi_import_table *import_table; - struct route_node *node; - struct bgp_info *info; - safi_t safi; /* used only for bulk operations */ - /* - * For import table node reference count checking (i.e., debugging). - * Normally when a timer expires, lockoffset should be 0. However, if - * the timer expiration function is called directly (e.g., - * rfapiExpireVpnNow), the node could be locked by a preceding - * route_top() or route_next() in a loop, so we need to pass this - * value in. - */ - int lockoffset; +struct rfapi_withdraw { + struct rfapi_import_table *import_table; + struct route_node *node; + struct bgp_info *info; + safi_t safi; /* used only for bulk operations */ + /* + * For import table node reference count checking (i.e., debugging). + * Normally when a timer expires, lockoffset should be 0. However, if + * the timer expiration function is called directly (e.g., + * rfapiExpireVpnNow), the node could be locked by a preceding + * route_top() or route_next() in a loop, so we need to pass this + * value in. + */ + int lockoffset; }; -/* +/* * DEBUG FUNCTION * It's evil and fiendish. It's compiler-dependent. * ? Might need LDFLAGS -rdynamic to produce all function names */ -void -rfapiDebugBacktrace (void) +void rfapiDebugBacktrace(void) { #ifdef HAVE_GLIBC_BACKTRACE #define RFAPI_DEBUG_BACKTRACE_NENTRIES 200 - void *buf[RFAPI_DEBUG_BACKTRACE_NENTRIES]; - char **syms; - size_t i; - size_t size; + void *buf[RFAPI_DEBUG_BACKTRACE_NENTRIES]; + char **syms; + size_t i; + size_t size; - size = backtrace (buf, RFAPI_DEBUG_BACKTRACE_NENTRIES); - syms = backtrace_symbols (buf, size); + size = backtrace(buf, RFAPI_DEBUG_BACKTRACE_NENTRIES); + syms = backtrace_symbols(buf, size); - for (i = 0; i < size && i < RFAPI_DEBUG_BACKTRACE_NENTRIES; ++i) - { - vnc_zlog_debug_verbose ("backtrace[%2zu]: %s", i, syms[i]); - } + for (i = 0; i < size && i < RFAPI_DEBUG_BACKTRACE_NENTRIES; ++i) { + vnc_zlog_debug_verbose("backtrace[%2zu]: %s", i, syms[i]); + } - free (syms); + free(syms); #else #endif } @@ -125,89 +122,80 @@ rfapiDebugBacktrace (void) * Count remote routes and compare with actively-maintained values. * Abort if they disagree. */ -void -rfapiCheckRouteCount () +void rfapiCheckRouteCount() { - struct bgp *bgp = bgp_get_default (); - struct rfapi *h; - struct rfapi_import_table *it; - afi_t afi; - - assert (bgp); - - h = bgp->rfapi; - assert (h); - - for (it = h->imports; it; it = it->next) - { - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - - struct route_table *rt; - struct route_node *rn; - - int holddown_count = 0; - int local_count = 0; - int imported_count = 0; - int remote_count = 0; - - rt = it->imported_vpn[afi]; - - for (rn = route_top (rt); rn; rn = route_next (rn)) - { - struct bgp_info *bi; - struct bgp_info *next; - - for (bi = rn->info; bi; bi = next) - { - next = bi->next; - - if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)) - { - ++holddown_count; - - } - else - { - if (RFAPI_LOCAL_BI (bi)) - { - ++local_count; - } - else - { - if (RFAPI_DIRECT_IMPORT_BI (bi)) - { - ++imported_count; - } - else - { - ++remote_count; - } - } - } - } - } - - if (it->holddown_count[afi] != holddown_count) - { - vnc_zlog_debug_verbose ("%s: it->holddown_count %d != holddown_count %d", - __func__, it->holddown_count[afi], holddown_count); - assert (0); - } - if (it->remote_count[afi] != remote_count) - { - vnc_zlog_debug_verbose ("%s: it->remote_count %d != remote_count %d", - __func__, it->remote_count[afi], remote_count); - assert (0); - } - if (it->imported_count[afi] != imported_count) - { - vnc_zlog_debug_verbose ("%s: it->imported_count %d != imported_count %d", - __func__, it->imported_count[afi], imported_count); - assert (0); - } - } - } + struct bgp *bgp = bgp_get_default(); + struct rfapi *h; + struct rfapi_import_table *it; + afi_t afi; + + assert(bgp); + + h = bgp->rfapi; + assert(h); + + for (it = h->imports; it; it = it->next) { + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + + struct route_table *rt; + struct route_node *rn; + + int holddown_count = 0; + int local_count = 0; + int imported_count = 0; + int remote_count = 0; + + rt = it->imported_vpn[afi]; + + for (rn = route_top(rt); rn; rn = route_next(rn)) { + struct bgp_info *bi; + struct bgp_info *next; + + for (bi = rn->info; bi; bi = next) { + next = bi->next; + + if (CHECK_FLAG(bi->flags, + BGP_INFO_REMOVED)) { + ++holddown_count; + + } else { + if (RFAPI_LOCAL_BI(bi)) { + ++local_count; + } else { + if (RFAPI_DIRECT_IMPORT_BI( + bi)) { + ++imported_count; + } else { + ++remote_count; + } + } + } + } + } + + if (it->holddown_count[afi] != holddown_count) { + vnc_zlog_debug_verbose( + "%s: it->holddown_count %d != holddown_count %d", + __func__, it->holddown_count[afi], + holddown_count); + assert(0); + } + if (it->remote_count[afi] != remote_count) { + vnc_zlog_debug_verbose( + "%s: it->remote_count %d != remote_count %d", + __func__, it->remote_count[afi], + remote_count); + assert(0); + } + if (it->imported_count[afi] != imported_count) { + vnc_zlog_debug_verbose( + "%s: it->imported_count %d != imported_count %d", + __func__, it->imported_count[afi], + imported_count); + assert(0); + } + } + } } #if DEBUG_ROUTE_COUNTERS @@ -224,825 +212,777 @@ rfapiCheckRouteCount () * node->lock == 1, and we have to validate the refcount before * the node is deleted. In this case, we specify lockoffset 1. */ -void -rfapiCheckRefcount (struct route_node *rn, safi_t safi, int lockoffset) +void rfapiCheckRefcount(struct route_node *rn, safi_t safi, int lockoffset) { - unsigned int count_bi = 0; - unsigned int count_monitor = 0; - struct bgp_info *bi; - struct rfapi_monitor_encap *hme; - struct rfapi_monitor_vpn *hmv; - - for (bi = rn->info; bi; bi = bi->next) - ++count_bi; - - - if (rn->aggregate) - { - ++count_monitor; /* rfapi_it_extra */ - - switch (safi) - { - void *cursor; - int rc; - - case SAFI_ENCAP: - for (hme = RFAPI_MONITOR_ENCAP (rn); hme; hme = hme->next) - ++count_monitor; - break; - - case SAFI_MPLS_VPN: - - for (hmv = RFAPI_MONITOR_VPN (rn); hmv; hmv = hmv->next) - ++count_monitor; - - if (RFAPI_MONITOR_EXTERIOR (rn)->source) - { - ++count_monitor; /* sl */ - cursor = NULL; - for (rc = skiplist_next (RFAPI_MONITOR_EXTERIOR (rn)->source, - NULL, NULL, &cursor); - !rc; - rc = skiplist_next (RFAPI_MONITOR_EXTERIOR (rn)->source, - NULL, NULL, &cursor)) - { - - ++count_monitor; /* sl entry */ - } - } - break; - - default: - assert (0); - } - } - - if (count_bi + count_monitor + lockoffset != rn->lock) - { - vnc_zlog_debug_verbose - ("%s: count_bi=%d, count_monitor=%d, lockoffset=%d, rn->lock=%d", - __func__, count_bi, count_monitor, lockoffset, rn->lock); - assert (0); - } + unsigned int count_bi = 0; + unsigned int count_monitor = 0; + struct bgp_info *bi; + struct rfapi_monitor_encap *hme; + struct rfapi_monitor_vpn *hmv; + + for (bi = rn->info; bi; bi = bi->next) + ++count_bi; + + + if (rn->aggregate) { + ++count_monitor; /* rfapi_it_extra */ + + switch (safi) { + void *cursor; + int rc; + + case SAFI_ENCAP: + for (hme = RFAPI_MONITOR_ENCAP(rn); hme; + hme = hme->next) + ++count_monitor; + break; + + case SAFI_MPLS_VPN: + + for (hmv = RFAPI_MONITOR_VPN(rn); hmv; hmv = hmv->next) + ++count_monitor; + + if (RFAPI_MONITOR_EXTERIOR(rn)->source) { + ++count_monitor; /* sl */ + cursor = NULL; + for (rc = skiplist_next( + RFAPI_MONITOR_EXTERIOR(rn)->source, + NULL, NULL, &cursor); + !rc; + rc = skiplist_next( + RFAPI_MONITOR_EXTERIOR(rn)->source, + NULL, NULL, &cursor)) { + + ++count_monitor; /* sl entry */ + } + } + break; + + default: + assert(0); + } + } + + if (count_bi + count_monitor + lockoffset != rn->lock) { + vnc_zlog_debug_verbose( + "%s: count_bi=%d, count_monitor=%d, lockoffset=%d, rn->lock=%d", + __func__, count_bi, count_monitor, lockoffset, + rn->lock); + assert(0); + } } /* * Perform deferred rfapi_close operations that were queued * during callbacks. */ -static wq_item_status -rfapi_deferred_close_workfunc (struct work_queue *q, void *data) +static wq_item_status rfapi_deferred_close_workfunc(struct work_queue *q, + void *data) { - struct rfapi_descriptor *rfd = data; - struct rfapi *h = q->spec.data; - - assert (!(h->flags & RFAPI_INCALLBACK)); - rfapi_close (rfd); - vnc_zlog_debug_verbose ("%s: completed deferred close on handle %p", __func__, rfd); - return WQ_SUCCESS; + struct rfapi_descriptor *rfd = data; + struct rfapi *h = q->spec.data; + + assert(!(h->flags & RFAPI_INCALLBACK)); + rfapi_close(rfd); + vnc_zlog_debug_verbose("%s: completed deferred close on handle %p", + __func__, rfd); + return WQ_SUCCESS; } /* * Extract layer 2 option from Encap TLVS in BGP attrs */ -int -rfapiGetL2o (struct attr *attr, struct rfapi_l2address_option *l2o) +int rfapiGetL2o(struct attr *attr, struct rfapi_l2address_option *l2o) { - if (attr) - { - - struct bgp_attr_encap_subtlv *pEncap; - - for (pEncap = attr->vnc_subtlvs; pEncap; pEncap = pEncap->next) - { - - if (pEncap->type == BGP_VNC_SUBTLV_TYPE_RFPOPTION) - { - if (pEncap->value[0] == RFAPI_VN_OPTION_TYPE_L2ADDR) - { - - if (pEncap->value[1] == 14) - { - memcpy (l2o->macaddr.octet, pEncap->value + 2, - ETHER_ADDR_LEN); - l2o->label = - ((pEncap->value[10] >> 4) & 0x0f) + - ((pEncap->value[9] << 4) & 0xff0) + - ((pEncap->value[8] << 12) & 0xff000); - - l2o->local_nve_id = pEncap->value[12]; - - l2o->logical_net_id = - (pEncap->value[15] & 0xff) + - ((pEncap->value[14] << 8) & 0xff00) + - ((pEncap->value[13] << 16) & 0xff0000); - } - - return 0; - } - } - } - } - - return ENOENT; + if (attr) { + + struct bgp_attr_encap_subtlv *pEncap; + + for (pEncap = attr->vnc_subtlvs; pEncap; + pEncap = pEncap->next) { + + if (pEncap->type == BGP_VNC_SUBTLV_TYPE_RFPOPTION) { + if (pEncap->value[0] + == RFAPI_VN_OPTION_TYPE_L2ADDR) { + + if (pEncap->value[1] == 14) { + memcpy(l2o->macaddr.octet, + pEncap->value + 2, + ETHER_ADDR_LEN); + l2o->label = + ((pEncap->value[10] + >> 4) + & 0x0f) + + ((pEncap->value[9] + << 4) + & 0xff0) + + ((pEncap->value[8] + << 12) + & 0xff000); + + l2o->local_nve_id = + pEncap->value[12]; + + l2o->logical_net_id = + (pEncap->value[15] + & 0xff) + + ((pEncap->value[14] + << 8) + & 0xff00) + + ((pEncap->value[13] + << 16) + & 0xff0000); + } + + return 0; + } + } + } + } + + return ENOENT; } /* * Extract the lifetime from the Tunnel Encap attribute of a route in * an import table */ -int -rfapiGetVncLifetime (struct attr *attr, uint32_t * lifetime) +int rfapiGetVncLifetime(struct attr *attr, uint32_t *lifetime) { - struct bgp_attr_encap_subtlv *pEncap; + struct bgp_attr_encap_subtlv *pEncap; - *lifetime = RFAPI_INFINITE_LIFETIME; /* default to infinite */ + *lifetime = RFAPI_INFINITE_LIFETIME; /* default to infinite */ - if (attr) - { + if (attr) { - for (pEncap = attr->vnc_subtlvs; pEncap; pEncap = pEncap->next) - { + for (pEncap = attr->vnc_subtlvs; pEncap; + pEncap = pEncap->next) { - if (pEncap->type == BGP_VNC_SUBTLV_TYPE_LIFETIME) - { /* lifetime */ - if (pEncap->length == 4) - { - memcpy (lifetime, pEncap->value, 4); - *lifetime = ntohl (*lifetime); - return 0; - } - } - } - } + if (pEncap->type + == BGP_VNC_SUBTLV_TYPE_LIFETIME) { /* lifetime */ + if (pEncap->length == 4) { + memcpy(lifetime, pEncap->value, 4); + *lifetime = ntohl(*lifetime); + return 0; + } + } + } + } - return ENOENT; + return ENOENT; } /* * Extract the tunnel type from the extended community */ -int -rfapiGetTunnelType (struct attr *attr, - bgp_encap_types *type) +int rfapiGetTunnelType(struct attr *attr, bgp_encap_types *type) { - *type = BGP_ENCAP_TYPE_MPLS; /* default to MPLS */ - if (attr && attr->ecommunity) - { - struct ecommunity *ecom = attr->ecommunity; - int i; - - for (i = 0; i < (ecom->size * ECOMMUNITY_SIZE); i += ECOMMUNITY_SIZE) - { - uint8_t *ep; - - ep = ecom->val + i; - if (ep[0] == ECOMMUNITY_ENCODE_OPAQUE && - ep[1] == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP) - { - *type = (ep[6]<<8) + ep[7]; - return 0; - } - } - } - - return ENOENT; + *type = BGP_ENCAP_TYPE_MPLS; /* default to MPLS */ + if (attr && attr->ecommunity) { + struct ecommunity *ecom = attr->ecommunity; + int i; + + for (i = 0; i < (ecom->size * ECOMMUNITY_SIZE); + i += ECOMMUNITY_SIZE) { + uint8_t *ep; + + ep = ecom->val + i; + if (ep[0] == ECOMMUNITY_ENCODE_OPAQUE + && ep[1] == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP) { + *type = (ep[6] << 8) + ep[7]; + return 0; + } + } + } + + return ENOENT; } /* * Look for UN address in Encap attribute */ -int -rfapiGetVncTunnelUnAddr (struct attr *attr, struct prefix *p) +int rfapiGetVncTunnelUnAddr(struct attr *attr, struct prefix *p) { - struct bgp_attr_encap_subtlv *pEncap; - bgp_encap_types tun_type; - - rfapiGetTunnelType (attr, &tun_type); - if (tun_type == BGP_ENCAP_TYPE_MPLS) - { - if (!p) - return 0; - /* MPLS carries UN address in next hop */ - rfapiNexthop2Prefix (attr, p); - if (p->family != 0) - return 0; - - return ENOENT; - } - if (attr) - { - for (pEncap = attr->encap_subtlvs; pEncap; pEncap = pEncap->next) - { - - if (pEncap->type == BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT) - { /* un addr */ - switch (pEncap->length) - { - case 8: - if (p) - { - p->family = AF_INET; - p->prefixlen = 32; - memcpy (p->u.val, pEncap->value, 4); - } - return 0; - - case 20: - if (p) - { - p->family = AF_INET6; - p->prefixlen = 128; - memcpy (p->u.val, pEncap->value, 16); - } - return 0; - } - } - } - } - - return ENOENT; + struct bgp_attr_encap_subtlv *pEncap; + bgp_encap_types tun_type; + + rfapiGetTunnelType(attr, &tun_type); + if (tun_type == BGP_ENCAP_TYPE_MPLS) { + if (!p) + return 0; + /* MPLS carries UN address in next hop */ + rfapiNexthop2Prefix(attr, p); + if (p->family != 0) + return 0; + + return ENOENT; + } + if (attr) { + for (pEncap = attr->encap_subtlvs; pEncap; + pEncap = pEncap->next) { + + if (pEncap->type + == BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT) { /* un + addr + */ + switch (pEncap->length) { + case 8: + if (p) { + p->family = AF_INET; + p->prefixlen = 32; + memcpy(p->u.val, pEncap->value, + 4); + } + return 0; + + case 20: + if (p) { + p->family = AF_INET6; + p->prefixlen = 128; + memcpy(p->u.val, pEncap->value, + 16); + } + return 0; + } + } + } + } + + return ENOENT; } /* * Get UN address wherever it might be */ -int -rfapiGetUnAddrOfVpnBi (struct bgp_info *bi, struct prefix *p) +int rfapiGetUnAddrOfVpnBi(struct bgp_info *bi, struct prefix *p) { - /* If it's in this route's VNC attribute, we're done */ - if (!rfapiGetVncTunnelUnAddr (bi->attr, p)) - return 0; - /* - * Otherwise, see if it's cached from a corresponding ENCAP SAFI - * advertisement - */ - if (bi->extra) - { - switch (bi->extra->vnc.import.un_family) - { - case AF_INET: - if (p) - { - p->family = bi->extra->vnc.import.un_family; - p->u.prefix4 = bi->extra->vnc.import.un.addr4; - p->prefixlen = 32; - } - return 0; - case AF_INET6: - if (p) - { - p->family = bi->extra->vnc.import.un_family; - p->u.prefix6 = bi->extra->vnc.import.un.addr6; - p->prefixlen = 128; - } - return 0; - default: - if (p) - p->family = 0; + /* If it's in this route's VNC attribute, we're done */ + if (!rfapiGetVncTunnelUnAddr(bi->attr, p)) + return 0; + /* + * Otherwise, see if it's cached from a corresponding ENCAP SAFI + * advertisement + */ + if (bi->extra) { + switch (bi->extra->vnc.import.un_family) { + case AF_INET: + if (p) { + p->family = bi->extra->vnc.import.un_family; + p->u.prefix4 = bi->extra->vnc.import.un.addr4; + p->prefixlen = 32; + } + return 0; + case AF_INET6: + if (p) { + p->family = bi->extra->vnc.import.un_family; + p->u.prefix6 = bi->extra->vnc.import.un.addr6; + p->prefixlen = 128; + } + return 0; + default: + if (p) + p->family = 0; #if DEBUG_ENCAP_MONITOR - vnc_zlog_debug_verbose ("%s: bi->extra->vnc.import.un_family is 0, no UN addr", - __func__); + vnc_zlog_debug_verbose( + "%s: bi->extra->vnc.import.un_family is 0, no UN addr", + __func__); #endif - break; - } - } + break; + } + } - return ENOENT; + return ENOENT; } /* * Make a new bgp_info from gathered parameters */ -static struct bgp_info * -rfapiBgpInfoCreate ( - struct attr *attr, - struct peer *peer, - void *rfd, - struct prefix_rd *prd, - u_char type, - u_char sub_type, - uint32_t *label) +static struct bgp_info *rfapiBgpInfoCreate(struct attr *attr, struct peer *peer, + void *rfd, struct prefix_rd *prd, + u_char type, u_char sub_type, + uint32_t *label) { - struct bgp_info *new; - - new = bgp_info_new (); - assert (new); - - if (attr) - { - if (!new->attr) - new->attr = bgp_attr_intern (attr); - } - bgp_info_extra_get (new); - if (prd) - { - new->extra->vnc.import.rd = *prd; - rfapi_time (&new->extra->vnc.import.create_time); - } - if (label) - encode_label (*label, &new->extra->label); - new->type = type; - new->sub_type = sub_type; - new->peer = peer; - peer_lock (peer); - - return new; + struct bgp_info *new; + + new = bgp_info_new(); + assert(new); + + if (attr) { + if (!new->attr) + new->attr = bgp_attr_intern(attr); + } + bgp_info_extra_get(new); + if (prd) { + new->extra->vnc.import.rd = *prd; + rfapi_time(&new->extra->vnc.import.create_time); + } + if (label) + encode_label(*label, &new->extra->label); + new->type = type; + new->sub_type = sub_type; + new->peer = peer; + peer_lock(peer); + + return new; } /* * Frees bgp_info as used in import tables (parts are not * allocated exactly the way they are in the main RIBs) */ -static void -rfapiBgpInfoFree (struct bgp_info *goner) +static void rfapiBgpInfoFree(struct bgp_info *goner) { - if (!goner) - return; - - if (goner->peer) - { - vnc_zlog_debug_verbose ("%s: calling peer_unlock(%p), #%d", - __func__, goner->peer, goner->peer->lock); - peer_unlock (goner->peer); - } - - if (goner->attr) - { - bgp_attr_unintern (&goner->attr); - } - if (goner->extra) - { - assert (!goner->extra->damp_info); /* Not used in import tbls */ - XFREE (MTYPE_BGP_ROUTE_EXTRA, goner->extra); - goner->extra = NULL; - } - XFREE (MTYPE_BGP_ROUTE, goner); + if (!goner) + return; + + if (goner->peer) { + vnc_zlog_debug_verbose("%s: calling peer_unlock(%p), #%d", + __func__, goner->peer, + goner->peer->lock); + peer_unlock(goner->peer); + } + + if (goner->attr) { + bgp_attr_unintern(&goner->attr); + } + if (goner->extra) { + assert(!goner->extra->damp_info); /* Not used in import tbls */ + XFREE(MTYPE_BGP_ROUTE_EXTRA, goner->extra); + goner->extra = NULL; + } + XFREE(MTYPE_BGP_ROUTE, goner); } -struct rfapi_import_table * -rfapiMacImportTableGetNoAlloc (struct bgp *bgp, uint32_t lni) +struct rfapi_import_table *rfapiMacImportTableGetNoAlloc(struct bgp *bgp, + uint32_t lni) { - struct rfapi *h; - struct rfapi_import_table *it = NULL; - uintptr_t lni_as_ptr = lni; + struct rfapi *h; + struct rfapi_import_table *it = NULL; + uintptr_t lni_as_ptr = lni; - h = bgp->rfapi; - if (!h) - return NULL; + h = bgp->rfapi; + if (!h) + return NULL; - if (!h->import_mac) - return NULL; + if (!h->import_mac) + return NULL; - if (skiplist_search (h->import_mac, (void *) lni_as_ptr, (void **) &it)) - return NULL; + if (skiplist_search(h->import_mac, (void *)lni_as_ptr, (void **)&it)) + return NULL; - return it; + return it; } -struct rfapi_import_table * -rfapiMacImportTableGet (struct bgp *bgp, uint32_t lni) +struct rfapi_import_table *rfapiMacImportTableGet(struct bgp *bgp, uint32_t lni) { - struct rfapi *h; - struct rfapi_import_table *it = NULL; - uintptr_t lni_as_ptr = lni; - - h = bgp->rfapi; - assert (h); - - if (!h->import_mac) - { - /* default cmp is good enough for LNI */ - h->import_mac = skiplist_new (0, NULL, NULL); - } - - if (skiplist_search (h->import_mac, (void *) lni_as_ptr, (void **) &it)) - { - - struct ecommunity *enew; - struct ecommunity_val eval; - afi_t afi; - - it = - XCALLOC (MTYPE_RFAPI_IMPORTTABLE, sizeof (struct rfapi_import_table)); - /* set RT list of new import table based on LNI */ - memset ((char *) &eval, 0, sizeof (eval)); - eval.val[0] = 0; /* VNC L2VPN */ - eval.val[1] = 2; /* VNC L2VPN */ - eval.val[5] = (lni >> 16) & 0xff; - eval.val[6] = (lni >> 8) & 0xff; - eval.val[7] = (lni >> 0) & 0xff; - - enew = ecommunity_new (); - ecommunity_add_val (enew, &eval); - it->rt_import_list = enew; - - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - it->imported_vpn[afi] = route_table_init (); - it->imported_encap[afi] = route_table_init (); - } - - it->l2_logical_net_id = lni; - - skiplist_insert (h->import_mac, (void *) lni_as_ptr, it); - } - - assert (it); - return it; + struct rfapi *h; + struct rfapi_import_table *it = NULL; + uintptr_t lni_as_ptr = lni; + + h = bgp->rfapi; + assert(h); + + if (!h->import_mac) { + /* default cmp is good enough for LNI */ + h->import_mac = skiplist_new(0, NULL, NULL); + } + + if (skiplist_search(h->import_mac, (void *)lni_as_ptr, (void **)&it)) { + + struct ecommunity *enew; + struct ecommunity_val eval; + afi_t afi; + + it = XCALLOC(MTYPE_RFAPI_IMPORTTABLE, + sizeof(struct rfapi_import_table)); + /* set RT list of new import table based on LNI */ + memset((char *)&eval, 0, sizeof(eval)); + eval.val[0] = 0; /* VNC L2VPN */ + eval.val[1] = 2; /* VNC L2VPN */ + eval.val[5] = (lni >> 16) & 0xff; + eval.val[6] = (lni >> 8) & 0xff; + eval.val[7] = (lni >> 0) & 0xff; + + enew = ecommunity_new(); + ecommunity_add_val(enew, &eval); + it->rt_import_list = enew; + + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + it->imported_vpn[afi] = route_table_init(); + it->imported_encap[afi] = route_table_init(); + } + + it->l2_logical_net_id = lni; + + skiplist_insert(h->import_mac, (void *)lni_as_ptr, it); + } + + assert(it); + return it; } /* * Implement MONITOR_MOVE_SHORTER(original_node) from * RFAPI-Import-Event-Handling.txt - * + * * Returns pointer to the list of moved monitors */ static struct rfapi_monitor_vpn * -rfapiMonitorMoveShorter (struct route_node *original_vpn_node, int lockoffset) +rfapiMonitorMoveShorter(struct route_node *original_vpn_node, int lockoffset) { - struct bgp_info *bi; - struct route_node *par; - struct rfapi_monitor_vpn *m; - struct rfapi_monitor_vpn *mlast; - struct rfapi_monitor_vpn *moved; - int movecount = 0; - int parent_already_refcounted = 0; + struct bgp_info *bi; + struct route_node *par; + struct rfapi_monitor_vpn *m; + struct rfapi_monitor_vpn *mlast; + struct rfapi_monitor_vpn *moved; + int movecount = 0; + int parent_already_refcounted = 0; - RFAPI_CHECK_REFCOUNT (original_vpn_node, SAFI_MPLS_VPN, lockoffset); + RFAPI_CHECK_REFCOUNT(original_vpn_node, SAFI_MPLS_VPN, lockoffset); #if DEBUG_MONITOR_MOVE_SHORTER - { - char buf[BUFSIZ]; + { + char buf[BUFSIZ]; - prefix2str (&original_vpn_node->p, buf, BUFSIZ); - buf[BUFSIZ - 1] = 0; - vnc_zlog_debug_verbose ("%s: called with node pfx=%s", __func__, buf); - } + prefix2str(&original_vpn_node->p, buf, BUFSIZ); + buf[BUFSIZ - 1] = 0; + vnc_zlog_debug_verbose("%s: called with node pfx=%s", __func__, + buf); + } #endif - /* - * 1. If there is at least one bi (either regular route or - * route marked as withdrawn, with a pending timer) at - * original_node with a valid UN address, we're done. Return. - */ - for (bi = original_vpn_node->info; bi; bi = bi->next) - { - struct prefix pfx; - - if (!rfapiGetUnAddrOfVpnBi (bi, &pfx)) - { + /* + * 1. If there is at least one bi (either regular route or + * route marked as withdrawn, with a pending timer) at + * original_node with a valid UN address, we're done. Return. + */ + for (bi = original_vpn_node->info; bi; bi = bi->next) { + struct prefix pfx; + + if (!rfapiGetUnAddrOfVpnBi(bi, &pfx)) { #if DEBUG_MONITOR_MOVE_SHORTER - vnc_zlog_debug_verbose ("%s: have valid UN at original node, no change", - __func__); + vnc_zlog_debug_verbose( + "%s: have valid UN at original node, no change", + __func__); #endif - return NULL; - } - } - - /* - * 2. Travel up the tree (toward less-specific prefixes) from - * original_node to find the first node that has at least - * one route (even if it is only a withdrawn route) with a - * valid UN address. Call this node "Node P." - */ - for (par = original_vpn_node->parent; par; par = par->parent) - { - for (bi = par->info; bi; bi = bi->next) - { - struct prefix pfx; - if (!rfapiGetUnAddrOfVpnBi (bi, &pfx)) - { - break; - } - } - if (bi) - break; - } - - if (par) - { - RFAPI_CHECK_REFCOUNT (par, SAFI_MPLS_VPN, 0); - } - - /* - * If no less-specific routes, try to use the 0/0 node - */ - if (!par) - { - /* this isn't necessarily 0/0 */ - par = route_top (original_vpn_node->table); - - /* - * If we got the top node but it wasn't 0/0, - * ignore it - */ - if (par && par->p.prefixlen) - { - route_unlock_node (par); /* maybe free */ - par = NULL; - } - - if (par) - { - ++parent_already_refcounted; - } - } - - /* - * Create 0/0 node if it isn't there - */ - if (!par) - { - struct prefix pfx_default; - - memset (&pfx_default, 0, sizeof (pfx_default)); - pfx_default.family = original_vpn_node->p.family; - - /* creates default node if none exists */ - par = route_node_get (original_vpn_node->table, &pfx_default); - ++parent_already_refcounted; - } - - /* - * 3. Move each of the monitors found at original_node to Node P. - * These are "Moved Monitors." - * - */ - - /* - * Attach at end so that the list pointer we return points - * only to the moved routes - */ - for (m = RFAPI_MONITOR_VPN (par), mlast = NULL; m; mlast = m, m = m->next); - - if (mlast) - { - moved = mlast->next = RFAPI_MONITOR_VPN (original_vpn_node); - } - else - { - moved = RFAPI_MONITOR_VPN_W_ALLOC (par) = - RFAPI_MONITOR_VPN (original_vpn_node); - } - if (RFAPI_MONITOR_VPN (original_vpn_node)) /* check agg, so not allocated */ - RFAPI_MONITOR_VPN_W_ALLOC (original_vpn_node) = NULL; - - /* - * update the node pointers on the monitors - */ - for (m = moved; m; m = m->next) - { - ++movecount; - m->node = par; - } - - RFAPI_CHECK_REFCOUNT (par, SAFI_MPLS_VPN, - parent_already_refcounted - movecount); - while (movecount > parent_already_refcounted) - { - route_lock_node (par); - ++parent_already_refcounted; - } - while (movecount < parent_already_refcounted) - { - /* unlikely, but code defensively */ - route_unlock_node (par); - --parent_already_refcounted; - } - RFAPI_CHECK_REFCOUNT (original_vpn_node, SAFI_MPLS_VPN, - movecount + lockoffset); - while (movecount--) - { - route_unlock_node (original_vpn_node); - } + return NULL; + } + } + + /* + * 2. Travel up the tree (toward less-specific prefixes) from + * original_node to find the first node that has at least + * one route (even if it is only a withdrawn route) with a + * valid UN address. Call this node "Node P." + */ + for (par = original_vpn_node->parent; par; par = par->parent) { + for (bi = par->info; bi; bi = bi->next) { + struct prefix pfx; + if (!rfapiGetUnAddrOfVpnBi(bi, &pfx)) { + break; + } + } + if (bi) + break; + } + + if (par) { + RFAPI_CHECK_REFCOUNT(par, SAFI_MPLS_VPN, 0); + } + + /* + * If no less-specific routes, try to use the 0/0 node + */ + if (!par) { + /* this isn't necessarily 0/0 */ + par = route_top(original_vpn_node->table); + + /* + * If we got the top node but it wasn't 0/0, + * ignore it + */ + if (par && par->p.prefixlen) { + route_unlock_node(par); /* maybe free */ + par = NULL; + } + + if (par) { + ++parent_already_refcounted; + } + } + + /* + * Create 0/0 node if it isn't there + */ + if (!par) { + struct prefix pfx_default; + + memset(&pfx_default, 0, sizeof(pfx_default)); + pfx_default.family = original_vpn_node->p.family; + + /* creates default node if none exists */ + par = route_node_get(original_vpn_node->table, &pfx_default); + ++parent_already_refcounted; + } + + /* + * 3. Move each of the monitors found at original_node to Node P. + * These are "Moved Monitors." + * + */ + + /* + * Attach at end so that the list pointer we return points + * only to the moved routes + */ + for (m = RFAPI_MONITOR_VPN(par), mlast = NULL; m; + mlast = m, m = m->next) + ; + + if (mlast) { + moved = mlast->next = RFAPI_MONITOR_VPN(original_vpn_node); + } else { + moved = RFAPI_MONITOR_VPN_W_ALLOC(par) = + RFAPI_MONITOR_VPN(original_vpn_node); + } + if (RFAPI_MONITOR_VPN( + original_vpn_node)) /* check agg, so not allocated */ + RFAPI_MONITOR_VPN_W_ALLOC(original_vpn_node) = NULL; + + /* + * update the node pointers on the monitors + */ + for (m = moved; m; m = m->next) { + ++movecount; + m->node = par; + } + + RFAPI_CHECK_REFCOUNT(par, SAFI_MPLS_VPN, + parent_already_refcounted - movecount); + while (movecount > parent_already_refcounted) { + route_lock_node(par); + ++parent_already_refcounted; + } + while (movecount < parent_already_refcounted) { + /* unlikely, but code defensively */ + route_unlock_node(par); + --parent_already_refcounted; + } + RFAPI_CHECK_REFCOUNT(original_vpn_node, SAFI_MPLS_VPN, + movecount + lockoffset); + while (movecount--) { + route_unlock_node(original_vpn_node); + } #if DEBUG_MONITOR_MOVE_SHORTER - { - char buf[BUFSIZ]; + { + char buf[BUFSIZ]; - prefix2str (&par->p, buf, BUFSIZ); - buf[BUFSIZ - 1] = 0; - vnc_zlog_debug_verbose ("%s: moved to node pfx=%s", __func__, buf); - } + prefix2str(&par->p, buf, BUFSIZ); + buf[BUFSIZ - 1] = 0; + vnc_zlog_debug_verbose("%s: moved to node pfx=%s", __func__, + buf); + } #endif - return moved; + return moved; } /* * Implement MONITOR_MOVE_LONGER(new_node) from * RFAPI-Import-Event-Handling.txt */ -static void -rfapiMonitorMoveLonger (struct route_node *new_vpn_node) +static void rfapiMonitorMoveLonger(struct route_node *new_vpn_node) { - struct rfapi_monitor_vpn *monitor; - struct rfapi_monitor_vpn *mlast; - struct bgp_info *bi; - struct route_node *par; - - RFAPI_CHECK_REFCOUNT (new_vpn_node, SAFI_MPLS_VPN, 0); - - /* - * Make sure we have at least one valid route at the new node - */ - for (bi = new_vpn_node->info; bi; bi = bi->next) - { - struct prefix pfx; - if (!rfapiGetUnAddrOfVpnBi (bi, &pfx)) - break; - } - - if (!bi) - { - vnc_zlog_debug_verbose ("%s: no valid routes at node %p, so not attempting moves", - __func__, new_vpn_node); - return; - } - - /* - * Find first parent node that has monitors - */ - for (par = new_vpn_node->parent; par; par = par->parent) - { - if (RFAPI_MONITOR_VPN (par)) - break; - } - - if (!par) - { - vnc_zlog_debug_verbose ("%s: no parent nodes with monitors, done", __func__); - return; - } - - /* - * Check each of these monitors to see of their longest-match - * is now the updated node. Move any such monitors to the more- - * specific updated node - */ - for (mlast = NULL, monitor = RFAPI_MONITOR_VPN (par); monitor;) - { - - /* - * If new longest match for monitor prefix is the new - * route's prefix, move monitor to new route's prefix - */ - if (prefix_match (&new_vpn_node->p, &monitor->p)) - { - /* detach */ - if (mlast) - { - mlast->next = monitor->next; - } - else - { - RFAPI_MONITOR_VPN_W_ALLOC (par) = monitor->next; - } - - - /* attach */ - monitor->next = RFAPI_MONITOR_VPN (new_vpn_node); - RFAPI_MONITOR_VPN_W_ALLOC (new_vpn_node) = monitor; - monitor->node = new_vpn_node; - - route_lock_node (new_vpn_node); /* incr refcount */ - - monitor = mlast ? mlast->next : RFAPI_MONITOR_VPN (par); - - RFAPI_CHECK_REFCOUNT (par, SAFI_MPLS_VPN, 1); - /* decr refcount after we're done with par as this might free it */ - route_unlock_node (par); - - continue; - } - mlast = monitor; - monitor = monitor->next; - } - - RFAPI_CHECK_REFCOUNT (new_vpn_node, SAFI_MPLS_VPN, 0); + struct rfapi_monitor_vpn *monitor; + struct rfapi_monitor_vpn *mlast; + struct bgp_info *bi; + struct route_node *par; + + RFAPI_CHECK_REFCOUNT(new_vpn_node, SAFI_MPLS_VPN, 0); + + /* + * Make sure we have at least one valid route at the new node + */ + for (bi = new_vpn_node->info; bi; bi = bi->next) { + struct prefix pfx; + if (!rfapiGetUnAddrOfVpnBi(bi, &pfx)) + break; + } + + if (!bi) { + vnc_zlog_debug_verbose( + "%s: no valid routes at node %p, so not attempting moves", + __func__, new_vpn_node); + return; + } + + /* + * Find first parent node that has monitors + */ + for (par = new_vpn_node->parent; par; par = par->parent) { + if (RFAPI_MONITOR_VPN(par)) + break; + } + + if (!par) { + vnc_zlog_debug_verbose( + "%s: no parent nodes with monitors, done", __func__); + return; + } + + /* + * Check each of these monitors to see of their longest-match + * is now the updated node. Move any such monitors to the more- + * specific updated node + */ + for (mlast = NULL, monitor = RFAPI_MONITOR_VPN(par); monitor;) { + + /* + * If new longest match for monitor prefix is the new + * route's prefix, move monitor to new route's prefix + */ + if (prefix_match(&new_vpn_node->p, &monitor->p)) { + /* detach */ + if (mlast) { + mlast->next = monitor->next; + } else { + RFAPI_MONITOR_VPN_W_ALLOC(par) = monitor->next; + } + + + /* attach */ + monitor->next = RFAPI_MONITOR_VPN(new_vpn_node); + RFAPI_MONITOR_VPN_W_ALLOC(new_vpn_node) = monitor; + monitor->node = new_vpn_node; + + route_lock_node(new_vpn_node); /* incr refcount */ + + monitor = mlast ? mlast->next : RFAPI_MONITOR_VPN(par); + + RFAPI_CHECK_REFCOUNT(par, SAFI_MPLS_VPN, 1); + /* decr refcount after we're done with par as this might + * free it */ + route_unlock_node(par); + + continue; + } + mlast = monitor; + monitor = monitor->next; + } + + RFAPI_CHECK_REFCOUNT(new_vpn_node, SAFI_MPLS_VPN, 0); } -static void -rfapiBgpInfoChainFree (struct bgp_info *bi) +static void rfapiBgpInfoChainFree(struct bgp_info *bi) { - struct bgp_info *next; - - while (bi) - { - - /* - * If there is a timer waiting to delete this bi, cancel - * the timer and delete immediately - */ - if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED) && - bi->extra->vnc.import.timer) - { - - struct thread *t = (struct thread *) bi->extra->vnc.import.timer; - struct rfapi_withdraw *wcb = t->arg; - - XFREE (MTYPE_RFAPI_WITHDRAW, wcb); - thread_cancel (t); - } - - next = bi->next; - bi->next = NULL; - rfapiBgpInfoFree (bi); - bi = next; - } + struct bgp_info *next; + + while (bi) { + + /* + * If there is a timer waiting to delete this bi, cancel + * the timer and delete immediately + */ + if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED) + && bi->extra->vnc.import.timer) { + + struct thread *t = + (struct thread *)bi->extra->vnc.import.timer; + struct rfapi_withdraw *wcb = t->arg; + + XFREE(MTYPE_RFAPI_WITHDRAW, wcb); + thread_cancel(t); + } + + next = bi->next; + bi->next = NULL; + rfapiBgpInfoFree(bi); + bi = next; + } } -static void -rfapiImportTableFlush (struct rfapi_import_table *it) +static void rfapiImportTableFlush(struct rfapi_import_table *it) { - afi_t afi; - - /* - * Free ecommunity - */ - ecommunity_free (&it->rt_import_list); - it->rt_import_list = NULL; - - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - - struct route_node *rn; - - for (rn = route_top (it->imported_vpn[afi]); rn; rn = route_next (rn)) - { - /* - * Each route_node has: - * aggregate: points to rfapi_it_extra with monitor chain(s) - * info: points to chain of bgp_info - */ - /* free bgp_info and its children */ - rfapiBgpInfoChainFree (rn->info); - rn->info = NULL; - - rfapiMonitorExtraFlush (SAFI_MPLS_VPN, rn); - } - - for (rn = route_top (it->imported_encap[afi]); rn; rn = route_next (rn)) - { - /* free bgp_info and its children */ - rfapiBgpInfoChainFree (rn->info); - rn->info = NULL; - - rfapiMonitorExtraFlush (SAFI_ENCAP, rn); - } - - route_table_finish (it->imported_vpn[afi]); - route_table_finish (it->imported_encap[afi]); - } - if (it->monitor_exterior_orphans) - { - skiplist_free (it->monitor_exterior_orphans); - } + afi_t afi; + + /* + * Free ecommunity + */ + ecommunity_free(&it->rt_import_list); + it->rt_import_list = NULL; + + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + + struct route_node *rn; + + for (rn = route_top(it->imported_vpn[afi]); rn; + rn = route_next(rn)) { + /* + * Each route_node has: + * aggregate: points to rfapi_it_extra with monitor + * chain(s) + * info: points to chain of bgp_info + */ + /* free bgp_info and its children */ + rfapiBgpInfoChainFree(rn->info); + rn->info = NULL; + + rfapiMonitorExtraFlush(SAFI_MPLS_VPN, rn); + } + + for (rn = route_top(it->imported_encap[afi]); rn; + rn = route_next(rn)) { + /* free bgp_info and its children */ + rfapiBgpInfoChainFree(rn->info); + rn->info = NULL; + + rfapiMonitorExtraFlush(SAFI_ENCAP, rn); + } + + route_table_finish(it->imported_vpn[afi]); + route_table_finish(it->imported_encap[afi]); + } + if (it->monitor_exterior_orphans) { + skiplist_free(it->monitor_exterior_orphans); + } } -void -rfapiImportTableRefDelByIt ( - struct bgp *bgp, - struct rfapi_import_table *it_target) +void rfapiImportTableRefDelByIt(struct bgp *bgp, + struct rfapi_import_table *it_target) { - struct rfapi *h; - struct rfapi_import_table *it; - struct rfapi_import_table *prev = NULL; - - assert (it_target); - - h = bgp->rfapi; - assert (h); - - for (it = h->imports; it; prev = it, it = it->next) - { - if (it == it_target) - break; - } - - assert (it); - assert (it->refcount); - - it->refcount -= 1; - - if (!it->refcount) - { - if (prev) - { - prev->next = it->next; - } - else - { - h->imports = it->next; - } - rfapiImportTableFlush (it); - XFREE (MTYPE_RFAPI_IMPORTTABLE, it); - } + struct rfapi *h; + struct rfapi_import_table *it; + struct rfapi_import_table *prev = NULL; + + assert(it_target); + + h = bgp->rfapi; + assert(h); + + for (it = h->imports; it; prev = it, it = it->next) { + if (it == it_target) + break; + } + + assert(it); + assert(it->refcount); + + it->refcount -= 1; + + if (!it->refcount) { + if (prev) { + prev->next = it->next; + } else { + h->imports = it->next; + } + rfapiImportTableFlush(it); + XFREE(MTYPE_RFAPI_IMPORTTABLE, it); + } } #if RFAPI_REQUIRE_ENCAP_BEEC @@ -1050,298 +990,272 @@ rfapiImportTableRefDelByIt ( * Look for magic BGP Encapsulation Extended Community value * Format in RFC 5512 Sect. 4.5 */ -static int -rfapiEcommunitiesMatchBeec (struct ecommunity *ecom, - bgp_encap_types type) +static int rfapiEcommunitiesMatchBeec(struct ecommunity *ecom, + bgp_encap_types type) { - int i; - - if (!ecom) - return 0; + int i; - for (i = 0; i < (ecom->size * ECOMMUNITY_SIZE); i += ECOMMUNITY_SIZE) - { + if (!ecom) + return 0; - uint8_t *ep; + for (i = 0; i < (ecom->size * ECOMMUNITY_SIZE); i += ECOMMUNITY_SIZE) { - ep = ecom->val + i; + uint8_t *ep; - if (ep[0] == ECOMMUNITY_ENCODE_OPAQUE && - ep[1] == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP && - ep[6] == ((type && 0xff00)>>8) && - ep[7] == (type&0xff)) - { + ep = ecom->val + i; - return 1; - } - } - return 0; + if (ep[0] == ECOMMUNITY_ENCODE_OPAQUE + && ep[1] == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP + && ep[6] == ((type && 0xff00) >> 8) + && ep[7] == (type & 0xff)) { + return 1; + } + } + return 0; } #endif -int -rfapiEcommunitiesIntersect (struct ecommunity *e1, struct ecommunity *e2) +int rfapiEcommunitiesIntersect(struct ecommunity *e1, struct ecommunity *e2) { - int i, j; - - if (!e1 || !e2) - return 0; - - { - char *s1, *s2; - s1 = ecommunity_ecom2str (e1, ECOMMUNITY_FORMAT_DISPLAY, 0); - s2 = ecommunity_ecom2str (e2, ECOMMUNITY_FORMAT_DISPLAY, 0); - vnc_zlog_debug_verbose ("%s: e1[%s], e2[%s]", __func__, s1, s2); - XFREE (MTYPE_ECOMMUNITY_STR, s1); - XFREE (MTYPE_ECOMMUNITY_STR, s2); - } - - for (i = 0; i < e1->size; ++i) - { - for (j = 0; j < e2->size; ++j) - { - if (!memcmp (e1->val + (i * ECOMMUNITY_SIZE), - e2->val + (j * ECOMMUNITY_SIZE), ECOMMUNITY_SIZE)) - { - - return 1; - } - } - } - return 0; + int i, j; + + if (!e1 || !e2) + return 0; + + { + char *s1, *s2; + s1 = ecommunity_ecom2str(e1, ECOMMUNITY_FORMAT_DISPLAY, 0); + s2 = ecommunity_ecom2str(e2, ECOMMUNITY_FORMAT_DISPLAY, 0); + vnc_zlog_debug_verbose("%s: e1[%s], e2[%s]", __func__, s1, s2); + XFREE(MTYPE_ECOMMUNITY_STR, s1); + XFREE(MTYPE_ECOMMUNITY_STR, s2); + } + + for (i = 0; i < e1->size; ++i) { + for (j = 0; j < e2->size; ++j) { + if (!memcmp(e1->val + (i * ECOMMUNITY_SIZE), + e2->val + (j * ECOMMUNITY_SIZE), + ECOMMUNITY_SIZE)) { + + return 1; + } + } + } + return 0; } -int -rfapiEcommunityGetLNI (struct ecommunity *ecom, uint32_t * lni) +int rfapiEcommunityGetLNI(struct ecommunity *ecom, uint32_t *lni) { - if (ecom) - { - int i; - for (i = 0; i < ecom->size; ++i) - { - uint8_t *p = ecom->val + (i * ECOMMUNITY_SIZE); - - if ((*(p + 0) == 0x00) && (*(p + 1) == 0x02)) - { - - *lni = (*(p + 5) << 16) | (*(p + 6) << 8) | (*(p + 7)); - return 0; - } - } - } - return ENOENT; + if (ecom) { + int i; + for (i = 0; i < ecom->size; ++i) { + uint8_t *p = ecom->val + (i * ECOMMUNITY_SIZE); + + if ((*(p + 0) == 0x00) && (*(p + 1) == 0x02)) { + + *lni = (*(p + 5) << 16) | (*(p + 6) << 8) + | (*(p + 7)); + return 0; + } + } + } + return ENOENT; } -int -rfapiEcommunityGetEthernetTag (struct ecommunity *ecom, uint16_t * tag_id) +int rfapiEcommunityGetEthernetTag(struct ecommunity *ecom, uint16_t *tag_id) { - struct bgp *bgp = bgp_get_default (); - *tag_id = 0; /* default to untagged */ - if (ecom) - { - int i; - for (i = 0; i < ecom->size; ++i) - { - as_t as = 0; - int encode = 0; - uint8_t *p = ecom->val + (i * ECOMMUNITY_SIZE); - - /* High-order octet of type. */ - encode = *p++; - - if (*p++ == ECOMMUNITY_ROUTE_TARGET) { - if (encode == ECOMMUNITY_ENCODE_AS4) - { - as = (*p++ << 24); - as |= (*p++ << 16); - as |= (*p++ << 8); - as |= (*p++); - } - else if (encode == ECOMMUNITY_ENCODE_AS) - { - as = (*p++ << 8); - as |= (*p++); - p += 2; /* skip next two, tag/vid always in lowest bytes */ - } - if (as == bgp->as) - { - *tag_id = *p++ << 8; - *tag_id |= (*p++); - return 0; - } - } - } - } - return ENOENT; + struct bgp *bgp = bgp_get_default(); + *tag_id = 0; /* default to untagged */ + if (ecom) { + int i; + for (i = 0; i < ecom->size; ++i) { + as_t as = 0; + int encode = 0; + uint8_t *p = ecom->val + (i * ECOMMUNITY_SIZE); + + /* High-order octet of type. */ + encode = *p++; + + if (*p++ == ECOMMUNITY_ROUTE_TARGET) { + if (encode == ECOMMUNITY_ENCODE_AS4) { + as = (*p++ << 24); + as |= (*p++ << 16); + as |= (*p++ << 8); + as |= (*p++); + } else if (encode == ECOMMUNITY_ENCODE_AS) { + as = (*p++ << 8); + as |= (*p++); + p += + 2; /* skip next two, tag/vid + always in lowest bytes */ + } + if (as == bgp->as) { + *tag_id = *p++ << 8; + *tag_id |= (*p++); + return 0; + } + } + } + } + return ENOENT; } -static int -rfapiVpnBiNhEqualsPt (struct bgp_info *bi, struct rfapi_ip_addr *hpt) +static int rfapiVpnBiNhEqualsPt(struct bgp_info *bi, struct rfapi_ip_addr *hpt) { - uint8_t family; + uint8_t family; - if (!hpt || !bi) - return 0; + if (!hpt || !bi) + return 0; - family = BGP_MP_NEXTHOP_FAMILY (bi->attr->mp_nexthop_len); + family = BGP_MP_NEXTHOP_FAMILY(bi->attr->mp_nexthop_len); - if (hpt->addr_family != family) - return 0; + if (hpt->addr_family != family) + return 0; - switch (family) - { - case AF_INET: - if (bi->attr->mp_nexthop_global_in.s_addr != hpt->addr.v4.s_addr) - return 0; - break; + switch (family) { + case AF_INET: + if (bi->attr->mp_nexthop_global_in.s_addr + != hpt->addr.v4.s_addr) + return 0; + break; - case AF_INET6: - if (IPV6_ADDR_CMP (&bi->attr->mp_nexthop_global, &hpt->addr.v6)) - return 0; - break; + case AF_INET6: + if (IPV6_ADDR_CMP(&bi->attr->mp_nexthop_global, &hpt->addr.v6)) + return 0; + break; - default: - return 0; - break; - } + default: + return 0; + break; + } - return 1; + return 1; } /* * Compare 2 VPN BIs. Return true if they have the same VN and UN addresses */ -static int -rfapiVpnBiSamePtUn (struct bgp_info *bi1, struct bgp_info *bi2) +static int rfapiVpnBiSamePtUn(struct bgp_info *bi1, struct bgp_info *bi2) { - struct prefix pfx_un1; - struct prefix pfx_un2; - - if (!bi1 || !bi2) - return 0; - - if (!bi1->attr || !bi2->attr) - return 0; - - /* - * VN address comparisons - */ - - if (BGP_MP_NEXTHOP_FAMILY (bi1->attr->mp_nexthop_len) != - BGP_MP_NEXTHOP_FAMILY (bi2->attr->mp_nexthop_len)) - { - return 0; - } - - switch (BGP_MP_NEXTHOP_FAMILY (bi1->attr->mp_nexthop_len)) - { - case AF_INET: - if (bi1->attr->mp_nexthop_global_in.s_addr != - bi2->attr->mp_nexthop_global_in.s_addr) - return 0; - break; - - case AF_INET6: - if (IPV6_ADDR_CMP (&bi1->attr->mp_nexthop_global, - &bi2->attr->mp_nexthop_global)) - return 0; - break; - - default: - return 0; - break; - } - - /* - * UN address comparisons - */ - if (rfapiGetVncTunnelUnAddr (bi1->attr, &pfx_un1)) - { - if (bi1->extra) - { - pfx_un1.family = bi1->extra->vnc.import.un_family; - switch (bi1->extra->vnc.import.un_family) - { - case AF_INET: - pfx_un1.u.prefix4 = bi1->extra->vnc.import.un.addr4; - break; - case AF_INET6: - pfx_un1.u.prefix6 = bi1->extra->vnc.import.un.addr6; - break; - default: - pfx_un1.family = 0; - break; - } - } - } - - if (rfapiGetVncTunnelUnAddr (bi2->attr, &pfx_un2)) - { - if (bi2->extra) - { - pfx_un2.family = bi2->extra->vnc.import.un_family; - switch (bi2->extra->vnc.import.un_family) - { - case AF_INET: - pfx_un2.u.prefix4 = bi2->extra->vnc.import.un.addr4; - break; - case AF_INET6: - pfx_un2.u.prefix6 = bi2->extra->vnc.import.un.addr6; - break; - default: - pfx_un2.family = 0; - break; - } - } - } - - if (!pfx_un1.family || !pfx_un2.family) - return 0; - - if (pfx_un1.family != pfx_un2.family) - return 0; - - switch (pfx_un1.family) - { - case AF_INET: - if (!IPV4_ADDR_SAME - (&pfx_un1.u.prefix4.s_addr, &pfx_un2.u.prefix4.s_addr)) - return 0; - break; - case AF_INET6: - if (!IPV6_ADDR_SAME (&pfx_un1.u.prefix6, &pfx_un2.u.prefix6)) - return 0; - break; - } - - - - return 1; + struct prefix pfx_un1; + struct prefix pfx_un2; + + if (!bi1 || !bi2) + return 0; + + if (!bi1->attr || !bi2->attr) + return 0; + + /* + * VN address comparisons + */ + + if (BGP_MP_NEXTHOP_FAMILY(bi1->attr->mp_nexthop_len) + != BGP_MP_NEXTHOP_FAMILY(bi2->attr->mp_nexthop_len)) { + return 0; + } + + switch (BGP_MP_NEXTHOP_FAMILY(bi1->attr->mp_nexthop_len)) { + case AF_INET: + if (bi1->attr->mp_nexthop_global_in.s_addr + != bi2->attr->mp_nexthop_global_in.s_addr) + return 0; + break; + + case AF_INET6: + if (IPV6_ADDR_CMP(&bi1->attr->mp_nexthop_global, + &bi2->attr->mp_nexthop_global)) + return 0; + break; + + default: + return 0; + break; + } + + /* + * UN address comparisons + */ + if (rfapiGetVncTunnelUnAddr(bi1->attr, &pfx_un1)) { + if (bi1->extra) { + pfx_un1.family = bi1->extra->vnc.import.un_family; + switch (bi1->extra->vnc.import.un_family) { + case AF_INET: + pfx_un1.u.prefix4 = + bi1->extra->vnc.import.un.addr4; + break; + case AF_INET6: + pfx_un1.u.prefix6 = + bi1->extra->vnc.import.un.addr6; + break; + default: + pfx_un1.family = 0; + break; + } + } + } + + if (rfapiGetVncTunnelUnAddr(bi2->attr, &pfx_un2)) { + if (bi2->extra) { + pfx_un2.family = bi2->extra->vnc.import.un_family; + switch (bi2->extra->vnc.import.un_family) { + case AF_INET: + pfx_un2.u.prefix4 = + bi2->extra->vnc.import.un.addr4; + break; + case AF_INET6: + pfx_un2.u.prefix6 = + bi2->extra->vnc.import.un.addr6; + break; + default: + pfx_un2.family = 0; + break; + } + } + } + + if (!pfx_un1.family || !pfx_un2.family) + return 0; + + if (pfx_un1.family != pfx_un2.family) + return 0; + + switch (pfx_un1.family) { + case AF_INET: + if (!IPV4_ADDR_SAME(&pfx_un1.u.prefix4.s_addr, + &pfx_un2.u.prefix4.s_addr)) + return 0; + break; + case AF_INET6: + if (!IPV6_ADDR_SAME(&pfx_un1.u.prefix6, &pfx_un2.u.prefix6)) + return 0; + break; + } + + + return 1; } -uint8_t -rfapiRfpCost (struct attr * attr) +uint8_t rfapiRfpCost(struct attr *attr) { - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) - { - if (attr->local_pref > 255) - { - return 0; - } - return 255 - attr->local_pref; - } - - return 255; + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) { + if (attr->local_pref > 255) { + return 0; + } + return 255 - attr->local_pref; + } + + return 255; } /*------------------------------------------ * rfapi_extract_l2o * - * Find Layer 2 options in an option chain + * Find Layer 2 options in an option chain * - * input: + * input: * pHop option chain * * output: @@ -1352,404 +1266,384 @@ rfapiRfpCost (struct attr * attr) * 1 no options found * --------------------------------------------*/ -int -rfapi_extract_l2o (struct bgp_tea_options *pHop, /* chain of options */ - struct rfapi_l2address_option *l2o) /* return extracted value */ +int rfapi_extract_l2o( + struct bgp_tea_options *pHop, /* chain of options */ + struct rfapi_l2address_option *l2o) /* return extracted value */ { - struct bgp_tea_options *p; + struct bgp_tea_options *p; - for (p = pHop; p; p = p->next) - { - if ((p->type == RFAPI_VN_OPTION_TYPE_L2ADDR) && (p->length >= 8)) - { + for (p = pHop; p; p = p->next) { + if ((p->type == RFAPI_VN_OPTION_TYPE_L2ADDR) + && (p->length >= 8)) { - char *v = p->value; + char *v = p->value; - memcpy (&l2o->macaddr, v, 6); + memcpy(&l2o->macaddr, v, 6); - l2o->label = - ((v[6] << 12) & 0xff000) + - ((v[7] << 4) & 0xff0) + ((v[8] >> 4) & 0xf); + l2o->label = ((v[6] << 12) & 0xff000) + + ((v[7] << 4) & 0xff0) + + ((v[8] >> 4) & 0xf); - l2o->local_nve_id = (uint8_t) v[10]; + l2o->local_nve_id = (uint8_t)v[10]; - l2o->logical_net_id = (v[11] << 16) + (v[12] << 8) + (v[13] << 0); + l2o->logical_net_id = + (v[11] << 16) + (v[12] << 8) + (v[13] << 0); - return 0; - } - } - return 1; + return 0; + } + } + return 1; } static struct rfapi_next_hop_entry * -rfapiRouteInfo2NextHopEntry ( - struct rfapi_ip_prefix *rprefix, - struct bgp_info *bi, /* route to encode */ - uint32_t lifetime, /* use this in nhe */ - struct route_node *rn) /* req for L2 eth addr */ +rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix, + struct bgp_info *bi, /* route to encode */ + uint32_t lifetime, /* use this in nhe */ + struct route_node *rn) /* req for L2 eth addr */ { - struct rfapi_next_hop_entry *new; - int have_vnc_tunnel_un = 0; + struct rfapi_next_hop_entry *new; + int have_vnc_tunnel_un = 0; #if DEBUG_ENCAP_MONITOR - vnc_zlog_debug_verbose ("%s: entry, bi %p, rn %p", __func__, bi, rn); + vnc_zlog_debug_verbose("%s: entry, bi %p, rn %p", __func__, bi, rn); #endif - new = XCALLOC (MTYPE_RFAPI_NEXTHOP, sizeof (struct rfapi_next_hop_entry)); - assert (new); - - new->prefix = *rprefix; - - if (bi->extra && - decode_rd_type(bi->extra->vnc.import.rd.val) == RD_TYPE_VNC_ETH) - { - /* ethernet */ - - struct rfapi_vn_option *vo; - - vo = XCALLOC (MTYPE_RFAPI_VN_OPTION, sizeof (struct rfapi_vn_option)); - assert (vo); - - vo->type = RFAPI_VN_OPTION_TYPE_L2ADDR; - - memcpy (&vo->v.l2addr.macaddr, &rn->p.u.prefix_eth.octet, - ETHER_ADDR_LEN); - /* only low 3 bytes of this are significant */ - if (bi->attr) - { - (void) rfapiEcommunityGetLNI (bi->attr->ecommunity, - &vo->v.l2addr.logical_net_id); - (void) rfapiEcommunityGetEthernetTag (bi->attr->ecommunity, - &vo->v.l2addr.tag_id); - } - - /* local_nve_id comes from lower byte of RD type */ - vo->v.l2addr.local_nve_id = bi->extra->vnc.import.rd.val[1]; - - /* label comes from MP_REACH_NLRI label */ - vo->v.l2addr.label = decode_label (&bi->extra->label); - - new->vn_options = vo; - - /* - * If there is an auxiliary prefix (i.e., host IP address), - * use it as the nexthop prefix instead of the query prefix - */ - if (bi->extra->vnc.import.aux_prefix.family) - { - rfapiQprefix2Rprefix (&bi->extra->vnc.import.aux_prefix, - &new->prefix); - } - } - - if (bi->attr) - { - bgp_encap_types tun_type; - new->prefix.cost = rfapiRfpCost (bi->attr); - - struct bgp_attr_encap_subtlv *pEncap; - - switch (BGP_MP_NEXTHOP_FAMILY (bi->attr->mp_nexthop_len)) - { - case AF_INET: - new->vn_address.addr_family = AF_INET; - new->vn_address.addr.v4 = bi->attr->mp_nexthop_global_in; - break; - - case AF_INET6: - new->vn_address.addr_family = AF_INET6; - new->vn_address.addr.v6 = bi->attr->mp_nexthop_global; - break; - - default: - zlog_warn ("%s: invalid vpn nexthop length: %d", - __func__, bi->attr->mp_nexthop_len); - rfapi_free_next_hop_list (new); - return NULL; - } - - for (pEncap = bi->attr->vnc_subtlvs; pEncap; - pEncap = pEncap->next) - { - switch (pEncap->type) - { - case BGP_VNC_SUBTLV_TYPE_LIFETIME: - /* use configured lifetime, not attr lifetime */ - break; - - default: - zlog_warn ("%s: unknown VNC option type %d", - __func__, pEncap->type); - - - break; - } - } - - rfapiGetTunnelType (bi->attr, &tun_type); - if (tun_type == BGP_ENCAP_TYPE_MPLS) - { - struct prefix p; - /* MPLS carries UN address in next hop */ - rfapiNexthop2Prefix (bi->attr, &p); - if (p.family != 0) - { - rfapiQprefix2Raddr(&p, &new->un_address); - have_vnc_tunnel_un = 1; - } - } - - for (pEncap = bi->attr->encap_subtlvs; pEncap; - pEncap = pEncap->next) - { - switch (pEncap->type) - { - case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: - /* - * Overrides ENCAP UN address, if any - */ - switch (pEncap->length) - { - - case 8: - new->un_address.addr_family = AF_INET; - memcpy (&new->un_address.addr.v4, pEncap->value, 4); - have_vnc_tunnel_un = 1; - break; - - case 20: - new->un_address.addr_family = AF_INET6; - memcpy (&new->un_address.addr.v6, pEncap->value, 16); - have_vnc_tunnel_un = 1; - break; - - default: - zlog_warn - ("%s: invalid tunnel subtlv UN addr length (%d) for bi %p", - __func__, pEncap->length, bi); - } - break; - - default: - zlog_warn ("%s: unknown Encap Attribute option type %d", - __func__, pEncap->type); - - - break; - } - } - - new->un_options = rfapi_encap_tlv_to_un_option (bi->attr); + new = XCALLOC(MTYPE_RFAPI_NEXTHOP, sizeof(struct rfapi_next_hop_entry)); + assert(new); + + new->prefix = *rprefix; + + if (bi->extra + && decode_rd_type(bi->extra->vnc.import.rd.val) + == RD_TYPE_VNC_ETH) { + /* ethernet */ + + struct rfapi_vn_option *vo; + + vo = XCALLOC(MTYPE_RFAPI_VN_OPTION, + sizeof(struct rfapi_vn_option)); + assert(vo); + + vo->type = RFAPI_VN_OPTION_TYPE_L2ADDR; + + memcpy(&vo->v.l2addr.macaddr, &rn->p.u.prefix_eth.octet, + ETHER_ADDR_LEN); + /* only low 3 bytes of this are significant */ + if (bi->attr) { + (void)rfapiEcommunityGetLNI( + bi->attr->ecommunity, + &vo->v.l2addr.logical_net_id); + (void)rfapiEcommunityGetEthernetTag( + bi->attr->ecommunity, &vo->v.l2addr.tag_id); + } + + /* local_nve_id comes from lower byte of RD type */ + vo->v.l2addr.local_nve_id = bi->extra->vnc.import.rd.val[1]; + + /* label comes from MP_REACH_NLRI label */ + vo->v.l2addr.label = decode_label(&bi->extra->label); + + new->vn_options = vo; + + /* + * If there is an auxiliary prefix (i.e., host IP address), + * use it as the nexthop prefix instead of the query prefix + */ + if (bi->extra->vnc.import.aux_prefix.family) { + rfapiQprefix2Rprefix(&bi->extra->vnc.import.aux_prefix, + &new->prefix); + } + } + + if (bi->attr) { + bgp_encap_types tun_type; + new->prefix.cost = rfapiRfpCost(bi->attr); + + struct bgp_attr_encap_subtlv *pEncap; + + switch (BGP_MP_NEXTHOP_FAMILY(bi->attr->mp_nexthop_len)) { + case AF_INET: + new->vn_address.addr_family = AF_INET; + new->vn_address.addr.v4 = + bi->attr->mp_nexthop_global_in; + break; + + case AF_INET6: + new->vn_address.addr_family = AF_INET6; + new->vn_address.addr.v6 = bi->attr->mp_nexthop_global; + break; + + default: + zlog_warn("%s: invalid vpn nexthop length: %d", + __func__, bi->attr->mp_nexthop_len); + rfapi_free_next_hop_list(new); + return NULL; + } + + for (pEncap = bi->attr->vnc_subtlvs; pEncap; + pEncap = pEncap->next) { + switch (pEncap->type) { + case BGP_VNC_SUBTLV_TYPE_LIFETIME: + /* use configured lifetime, not attr lifetime */ + break; + + default: + zlog_warn("%s: unknown VNC option type %d", + __func__, pEncap->type); + + + break; + } + } + + rfapiGetTunnelType(bi->attr, &tun_type); + if (tun_type == BGP_ENCAP_TYPE_MPLS) { + struct prefix p; + /* MPLS carries UN address in next hop */ + rfapiNexthop2Prefix(bi->attr, &p); + if (p.family != 0) { + rfapiQprefix2Raddr(&p, &new->un_address); + have_vnc_tunnel_un = 1; + } + } + + for (pEncap = bi->attr->encap_subtlvs; pEncap; + pEncap = pEncap->next) { + switch (pEncap->type) { + case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: + /* + * Overrides ENCAP UN address, if any + */ + switch (pEncap->length) { + + case 8: + new->un_address.addr_family = AF_INET; + memcpy(&new->un_address.addr.v4, + pEncap->value, 4); + have_vnc_tunnel_un = 1; + break; + + case 20: + new->un_address.addr_family = AF_INET6; + memcpy(&new->un_address.addr.v6, + pEncap->value, 16); + have_vnc_tunnel_un = 1; + break; + + default: + zlog_warn( + "%s: invalid tunnel subtlv UN addr length (%d) for bi %p", + __func__, pEncap->length, bi); + } + break; + + default: + zlog_warn( + "%s: unknown Encap Attribute option type %d", + __func__, pEncap->type); + + + break; + } + } + + new->un_options = rfapi_encap_tlv_to_un_option(bi->attr); #if DEBUG_ENCAP_MONITOR - vnc_zlog_debug_verbose ("%s: line %d: have_vnc_tunnel_un=%d", - __func__, __LINE__, have_vnc_tunnel_un); + vnc_zlog_debug_verbose("%s: line %d: have_vnc_tunnel_un=%d", + __func__, __LINE__, have_vnc_tunnel_un); #endif - if (!have_vnc_tunnel_un && bi && bi->extra) - { - /* - * use cached UN address from ENCAP route - */ - new->un_address.addr_family = bi->extra->vnc.import.un_family; - switch (new->un_address.addr_family) - { - case AF_INET: - new->un_address.addr.v4 = bi->extra->vnc.import.un.addr4; - break; - case AF_INET6: - new->un_address.addr.v6 = bi->extra->vnc.import.un.addr6; - break; - default: - zlog_warn ("%s: invalid UN addr family (%d) for bi %p", - __func__, new->un_address.addr_family, bi); - rfapi_free_next_hop_list (new); - return NULL; - break; - } - } - } - - new->lifetime = lifetime; - return new; + if (!have_vnc_tunnel_un && bi && bi->extra) { + /* + * use cached UN address from ENCAP route + */ + new->un_address.addr_family = + bi->extra->vnc.import.un_family; + switch (new->un_address.addr_family) { + case AF_INET: + new->un_address.addr.v4 = + bi->extra->vnc.import.un.addr4; + break; + case AF_INET6: + new->un_address.addr.v6 = + bi->extra->vnc.import.un.addr6; + break; + default: + zlog_warn( + "%s: invalid UN addr family (%d) for bi %p", + __func__, new->un_address.addr_family, + bi); + rfapi_free_next_hop_list(new); + return NULL; + break; + } + } + } + + new->lifetime = lifetime; + return new; } -int -rfapiHasNonRemovedRoutes (struct route_node *rn) +int rfapiHasNonRemovedRoutes(struct route_node *rn) { - struct bgp_info *bi; + struct bgp_info *bi; - for (bi = rn->info; bi; bi = bi->next) - { - struct prefix pfx; + for (bi = rn->info; bi; bi = bi->next) { + struct prefix pfx; - if (!CHECK_FLAG (bi->flags, BGP_INFO_REMOVED) && - (bi->extra && !rfapiGetUnAddrOfVpnBi (bi, &pfx))) - { + if (!CHECK_FLAG(bi->flags, BGP_INFO_REMOVED) + && (bi->extra && !rfapiGetUnAddrOfVpnBi(bi, &pfx))) { - return 1; - } - } - return 0; + return 1; + } + } + return 0; } #if DEBUG_IT_NODES -/* +/* * DEBUG FUNCTION */ -void -rfapiDumpNode (struct route_node *rn) +void rfapiDumpNode(struct route_node *rn) { - struct bgp_info *bi; - - vnc_zlog_debug_verbose ("%s: rn=%p", __func__, rn); - for (bi = rn->info; bi; bi = bi->next) - { - struct prefix pfx; - int ctrc = rfapiGetUnAddrOfVpnBi (bi, &pfx); - int nr; - - if (!CHECK_FLAG (bi->flags, BGP_INFO_REMOVED) && (bi->extra && !ctrc)) - { - - nr = 1; - } - else - { - nr = 0; - } - - vnc_zlog_debug_verbose (" bi=%p, nr=%d, flags=0x%x, extra=%p, ctrc=%d", - bi, nr, bi->flags, bi->extra, ctrc); - } + struct bgp_info *bi; + + vnc_zlog_debug_verbose("%s: rn=%p", __func__, rn); + for (bi = rn->info; bi; bi = bi->next) { + struct prefix pfx; + int ctrc = rfapiGetUnAddrOfVpnBi(bi, &pfx); + int nr; + + if (!CHECK_FLAG(bi->flags, BGP_INFO_REMOVED) + && (bi->extra && !ctrc)) { + + nr = 1; + } else { + nr = 0; + } + + vnc_zlog_debug_verbose( + " bi=%p, nr=%d, flags=0x%x, extra=%p, ctrc=%d", bi, nr, + bi->flags, bi->extra, ctrc); + } } #endif -static int -rfapiNhlAddNodeRoutes ( - struct route_node *rn, /* in */ - struct rfapi_ip_prefix *rprefix, /* in */ - uint32_t lifetime, /* in */ - int removed, /* in */ - struct rfapi_next_hop_entry **head, /* in/out */ - struct rfapi_next_hop_entry **tail, /* in/out */ - struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ - struct route_node *rfd_rib_node,/* preload this NVE rib node */ - struct prefix *pfx_target_original) /* query target */ +static int rfapiNhlAddNodeRoutes( + struct route_node *rn, /* in */ + struct rfapi_ip_prefix *rprefix, /* in */ + uint32_t lifetime, /* in */ + int removed, /* in */ + struct rfapi_next_hop_entry **head, /* in/out */ + struct rfapi_next_hop_entry **tail, /* in/out */ + struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ + struct route_node *rfd_rib_node, /* preload this NVE rib node */ + struct prefix *pfx_target_original) /* query target */ { - struct bgp_info *bi; - struct rfapi_next_hop_entry *new; - struct prefix pfx_un; - struct skiplist *seen_nexthops; - int count = 0; - int is_l2 = (rn->p.family == AF_ETHERNET); - - if (rfapiRibFTDFilterRecentPrefix( - (struct rfapi_descriptor *)(rfd_rib_node->table->info), rn, - pfx_target_original)) - { - return 0; - } - - seen_nexthops = - skiplist_new (0, vnc_prefix_cmp, (void (*)(void *)) prefix_free); - - for (bi = rn->info; bi; bi = bi->next) - { - - struct prefix pfx_vn; - struct prefix *newpfx; - - if (removed && !CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)) - { + struct bgp_info *bi; + struct rfapi_next_hop_entry *new; + struct prefix pfx_un; + struct skiplist *seen_nexthops; + int count = 0; + int is_l2 = (rn->p.family == AF_ETHERNET); + + if (rfapiRibFTDFilterRecentPrefix( + (struct rfapi_descriptor *)(rfd_rib_node->table->info), rn, + pfx_target_original)) { + return 0; + } + + seen_nexthops = + skiplist_new(0, vnc_prefix_cmp, (void (*)(void *))prefix_free); + + for (bi = rn->info; bi; bi = bi->next) { + + struct prefix pfx_vn; + struct prefix *newpfx; + + if (removed && !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) { #if DEBUG_RETURNED_NHL - vnc_zlog_debug_verbose ("%s: want holddown, this route not holddown, skip", - __func__); + vnc_zlog_debug_verbose( + "%s: want holddown, this route not holddown, skip", + __func__); #endif - continue; - } - if (!removed && CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)) - { - continue; - } - - if (!bi->extra) - { - continue; - } - - /* - * Check for excluded VN address - */ - if (rfapiVpnBiNhEqualsPt (bi, exclude_vnaddr)) - continue; - - /* - * Check for VN address (nexthop) copied already - */ - if (is_l2) - { - /* L2 routes: semantic nexthop in aux_prefix; VN addr ain't it */ - pfx_vn = bi->extra->vnc.import.aux_prefix; - } - else - { - rfapiNexthop2Prefix (bi->attr, &pfx_vn); - } - if (!skiplist_search (seen_nexthops, &pfx_vn, NULL)) - { + continue; + } + if (!removed && CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) { + continue; + } + + if (!bi->extra) { + continue; + } + + /* + * Check for excluded VN address + */ + if (rfapiVpnBiNhEqualsPt(bi, exclude_vnaddr)) + continue; + + /* + * Check for VN address (nexthop) copied already + */ + if (is_l2) { + /* L2 routes: semantic nexthop in aux_prefix; VN addr + * ain't it */ + pfx_vn = bi->extra->vnc.import.aux_prefix; + } else { + rfapiNexthop2Prefix(bi->attr, &pfx_vn); + } + if (!skiplist_search(seen_nexthops, &pfx_vn, NULL)) { #if DEBUG_RETURNED_NHL - char buf[BUFSIZ]; + char buf[BUFSIZ]; - prefix2str (&pfx_vn, buf, BUFSIZ); - buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */ - vnc_zlog_debug_verbose ("%s: already put VN/nexthop %s, skip", __func__, buf); + prefix2str(&pfx_vn, buf, BUFSIZ); + buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */ + vnc_zlog_debug_verbose( + "%s: already put VN/nexthop %s, skip", __func__, + buf); #endif - continue; - } + continue; + } - if (rfapiGetUnAddrOfVpnBi (bi, &pfx_un)) - { + if (rfapiGetUnAddrOfVpnBi(bi, &pfx_un)) { #if DEBUG_ENCAP_MONITOR - vnc_zlog_debug_verbose ("%s: failed to get UN address of this VPN bi", - __func__); + vnc_zlog_debug_verbose( + "%s: failed to get UN address of this VPN bi", + __func__); #endif - continue; - } - - newpfx = prefix_new (); - *newpfx = pfx_vn; - skiplist_insert (seen_nexthops, newpfx, newpfx); - - new = rfapiRouteInfo2NextHopEntry(rprefix, bi, lifetime, rn); - if (new) - { - if (rfapiRibPreloadBi(rfd_rib_node, &pfx_vn, &pfx_un, lifetime, bi)) - { - /* duplicate filtered by RIB */ - rfapi_free_next_hop_list (new); - new = NULL; - } - } - - if (new) - { - if (*tail) - { - (*tail)->next = new; - } - else - { - *head = new; - } - *tail = new; - ++count; - } - } - - skiplist_free (seen_nexthops); - - return count; + continue; + } + + newpfx = prefix_new(); + *newpfx = pfx_vn; + skiplist_insert(seen_nexthops, newpfx, newpfx); + + new = rfapiRouteInfo2NextHopEntry(rprefix, bi, lifetime, rn); + if (new) { + if (rfapiRibPreloadBi(rfd_rib_node, &pfx_vn, &pfx_un, + lifetime, bi)) { + /* duplicate filtered by RIB */ + rfapi_free_next_hop_list(new); + new = NULL; + } + } + + if (new) { + if (*tail) { + (*tail)->next = new; + } else { + *head = new; + } + *tail = new; + ++count; + } + } + + skiplist_free(seen_nexthops); + + return count; } @@ -1762,85 +1656,84 @@ rfapiNhlAddNodeRoutes ( * its routes in the list, so we skip it if the right or left node * matches (of course, we still travel down its child subtrees). */ -static int -rfapiNhlAddSubtree ( - struct route_node *rn, /* in */ - uint32_t lifetime, /* in */ - struct rfapi_next_hop_entry **head, /* in/out */ - struct rfapi_next_hop_entry **tail, /* in/out */ - struct route_node *omit_node, /* in */ - struct rfapi_ip_addr *exclude_vnaddr,/* omit routes to same NVE */ - struct route_table *rfd_rib_table,/* preload here */ - struct prefix *pfx_target_original) /* query target */ +static int rfapiNhlAddSubtree( + struct route_node *rn, /* in */ + uint32_t lifetime, /* in */ + struct rfapi_next_hop_entry **head, /* in/out */ + struct rfapi_next_hop_entry **tail, /* in/out */ + struct route_node *omit_node, /* in */ + struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ + struct route_table *rfd_rib_table, /* preload here */ + struct prefix *pfx_target_original) /* query target */ { - struct rfapi_ip_prefix rprefix; - int rcount = 0; - - /* FIXME: need to find a better way here to work without sticking our - * hands in node->link */ - if (rn->l_left && rn->l_left != omit_node) - { - if (rn->l_left->info) - { - int count = 0; - struct route_node *rib_rn = NULL; - - rfapiQprefix2Rprefix (&rn->l_left->p, &rprefix); - if (rfd_rib_table) - { - rib_rn = route_node_get(rfd_rib_table, &rn->l_left->p); - } - - count = rfapiNhlAddNodeRoutes (rn->l_left, &rprefix, lifetime, 0, - head, tail, exclude_vnaddr, rib_rn, pfx_target_original); - if (!count) - { - count = rfapiNhlAddNodeRoutes (rn->l_left, &rprefix, lifetime, 1, - head, tail, exclude_vnaddr, rib_rn, pfx_target_original); - } - rcount += count; - if (rib_rn) - route_unlock_node(rib_rn); - } - } - - if (rn->l_right && rn->l_right != omit_node) - { - if (rn->l_right->info) - { - int count = 0; - struct route_node *rib_rn = NULL; - - rfapiQprefix2Rprefix (&rn->l_right->p, &rprefix); - if (rfd_rib_table) - { - rib_rn = route_node_get(rfd_rib_table, &rn->l_right->p); - } - count = rfapiNhlAddNodeRoutes (rn->l_right, &rprefix, lifetime, 0, - head, tail, exclude_vnaddr, rib_rn, pfx_target_original); - if (!count) - { - count = rfapiNhlAddNodeRoutes (rn->l_right, &rprefix, lifetime, 1, - head, tail, exclude_vnaddr, rib_rn, pfx_target_original); - } - rcount += count; - if (rib_rn) - route_unlock_node(rib_rn); - } - } - - if (rn->l_left) - { - rcount += rfapiNhlAddSubtree (rn->l_left, lifetime, head, tail, omit_node, - exclude_vnaddr, rfd_rib_table, pfx_target_original); - } - if (rn->l_right) - { - rcount += rfapiNhlAddSubtree (rn->l_right, lifetime, head, tail, - omit_node, exclude_vnaddr, rfd_rib_table, pfx_target_original); - } - - return rcount; + struct rfapi_ip_prefix rprefix; + int rcount = 0; + + /* FIXME: need to find a better way here to work without sticking our + * hands in node->link */ + if (rn->l_left && rn->l_left != omit_node) { + if (rn->l_left->info) { + int count = 0; + struct route_node *rib_rn = NULL; + + rfapiQprefix2Rprefix(&rn->l_left->p, &rprefix); + if (rfd_rib_table) { + rib_rn = route_node_get(rfd_rib_table, + &rn->l_left->p); + } + + count = rfapiNhlAddNodeRoutes( + rn->l_left, &rprefix, lifetime, 0, head, tail, + exclude_vnaddr, rib_rn, pfx_target_original); + if (!count) { + count = rfapiNhlAddNodeRoutes( + rn->l_left, &rprefix, lifetime, 1, head, + tail, exclude_vnaddr, rib_rn, + pfx_target_original); + } + rcount += count; + if (rib_rn) + route_unlock_node(rib_rn); + } + } + + if (rn->l_right && rn->l_right != omit_node) { + if (rn->l_right->info) { + int count = 0; + struct route_node *rib_rn = NULL; + + rfapiQprefix2Rprefix(&rn->l_right->p, &rprefix); + if (rfd_rib_table) { + rib_rn = route_node_get(rfd_rib_table, + &rn->l_right->p); + } + count = rfapiNhlAddNodeRoutes( + rn->l_right, &rprefix, lifetime, 0, head, tail, + exclude_vnaddr, rib_rn, pfx_target_original); + if (!count) { + count = rfapiNhlAddNodeRoutes( + rn->l_right, &rprefix, lifetime, 1, + head, tail, exclude_vnaddr, rib_rn, + pfx_target_original); + } + rcount += count; + if (rib_rn) + route_unlock_node(rib_rn); + } + } + + if (rn->l_left) { + rcount += rfapiNhlAddSubtree( + rn->l_left, lifetime, head, tail, omit_node, + exclude_vnaddr, rfd_rib_table, pfx_target_original); + } + if (rn->l_right) { + rcount += rfapiNhlAddSubtree( + rn->l_right, lifetime, head, tail, omit_node, + exclude_vnaddr, rfd_rib_table, pfx_target_original); + } + + return rcount; } /* @@ -1854,343 +1747,326 @@ rfapiNhlAddSubtree ( * then return those, and also include all the non-removed routes from the * next less-specific node (i.e., this node's parent) at the end. */ -struct rfapi_next_hop_entry * -rfapiRouteNode2NextHopList ( - struct route_node *rn, - uint32_t lifetime, /* put into nexthop entries */ - struct rfapi_ip_addr *exclude_vnaddr,/* omit routes to same NVE */ - struct route_table *rfd_rib_table,/* preload here */ - struct prefix *pfx_target_original) /* query target */ +struct rfapi_next_hop_entry *rfapiRouteNode2NextHopList( + struct route_node *rn, uint32_t lifetime, /* put into nexthop entries */ + struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ + struct route_table *rfd_rib_table, /* preload here */ + struct prefix *pfx_target_original) /* query target */ { - struct rfapi_ip_prefix rprefix; - struct rfapi_next_hop_entry *answer = NULL; - struct rfapi_next_hop_entry *last = NULL; - struct route_node *parent; - int count = 0; - struct route_node *rib_rn; + struct rfapi_ip_prefix rprefix; + struct rfapi_next_hop_entry *answer = NULL; + struct rfapi_next_hop_entry *last = NULL; + struct route_node *parent; + int count = 0; + struct route_node *rib_rn; #if DEBUG_RETURNED_NHL - { - char buf[BUFSIZ]; - - prefix2str (&rn->p, buf, BUFSIZ); - buf[BUFSIZ - 1] = 0; - vnc_zlog_debug_verbose ("%s: called with node pfx=%s", __func__, buf); - } - rfapiDebugBacktrace (); + { + char buf[BUFSIZ]; + + prefix2str(&rn->p, buf, BUFSIZ); + buf[BUFSIZ - 1] = 0; + vnc_zlog_debug_verbose("%s: called with node pfx=%s", __func__, + buf); + } + rfapiDebugBacktrace(); #endif - rfapiQprefix2Rprefix (&rn->p, &rprefix); - - rib_rn = rfd_rib_table? route_node_get(rfd_rib_table, &rn->p): NULL; - - /* - * Add non-withdrawn routes at this node - */ - count = rfapiNhlAddNodeRoutes (rn, &rprefix, lifetime, 0, &answer, &last, - exclude_vnaddr, rib_rn, pfx_target_original); - - /* - * If the list has at least one entry, it's finished - */ - if (count) - { - count += rfapiNhlAddSubtree (rn, lifetime, &answer, &last, NULL, - exclude_vnaddr, rfd_rib_table, pfx_target_original); - vnc_zlog_debug_verbose ("%s: %d nexthops, answer=%p", __func__, count, answer); + rfapiQprefix2Rprefix(&rn->p, &rprefix); + + rib_rn = rfd_rib_table ? route_node_get(rfd_rib_table, &rn->p) : NULL; + + /* + * Add non-withdrawn routes at this node + */ + count = rfapiNhlAddNodeRoutes(rn, &rprefix, lifetime, 0, &answer, &last, + exclude_vnaddr, rib_rn, + pfx_target_original); + + /* + * If the list has at least one entry, it's finished + */ + if (count) { + count += rfapiNhlAddSubtree(rn, lifetime, &answer, &last, NULL, + exclude_vnaddr, rfd_rib_table, + pfx_target_original); + vnc_zlog_debug_verbose("%s: %d nexthops, answer=%p", __func__, + count, answer); #if DEBUG_RETURNED_NHL - rfapiPrintNhl (NULL, answer); + rfapiPrintNhl(NULL, answer); #endif - if (rib_rn) - route_unlock_node(rib_rn); - return answer; - } - - /* - * Add withdrawn routes at this node - */ - count = rfapiNhlAddNodeRoutes (rn, &rprefix, lifetime, 1, &answer, &last, - exclude_vnaddr, rib_rn, pfx_target_original); - if (rib_rn) - route_unlock_node(rib_rn); - - // rfapiPrintNhl(NULL, answer); - - /* - * walk up the tree until we find a node with non-deleted - * routes, then add them - */ - for (parent = rn->parent; parent; parent = parent->parent) - { - if (rfapiHasNonRemovedRoutes (parent)) - { - break; - } - } - - /* - * Add non-withdrawn routes from less-specific prefix - */ - if (parent) - { - rib_rn = rfd_rib_table? route_node_get(rfd_rib_table, &parent->p): NULL; - rfapiQprefix2Rprefix (&parent->p, &rprefix); - count += rfapiNhlAddNodeRoutes (parent, &rprefix, lifetime, 0, - &answer, &last, exclude_vnaddr, rib_rn, pfx_target_original); - count += rfapiNhlAddSubtree (parent, lifetime, &answer, &last, rn, - exclude_vnaddr, rfd_rib_table, pfx_target_original); - if (rib_rn) - route_unlock_node(rib_rn); - } - else - { - /* - * There is no parent with non-removed routes. Still need to - * add subtree of original node if it contributed routes to the - * answer. - */ - if (count) - count += rfapiNhlAddSubtree (rn, lifetime, &answer, &last, rn, - exclude_vnaddr, rfd_rib_table, pfx_target_original); - } - - vnc_zlog_debug_verbose ("%s: %d nexthops, answer=%p", __func__, count, answer); + if (rib_rn) + route_unlock_node(rib_rn); + return answer; + } + + /* + * Add withdrawn routes at this node + */ + count = rfapiNhlAddNodeRoutes(rn, &rprefix, lifetime, 1, &answer, &last, + exclude_vnaddr, rib_rn, + pfx_target_original); + if (rib_rn) + route_unlock_node(rib_rn); + + // rfapiPrintNhl(NULL, answer); + + /* + * walk up the tree until we find a node with non-deleted + * routes, then add them + */ + for (parent = rn->parent; parent; parent = parent->parent) { + if (rfapiHasNonRemovedRoutes(parent)) { + break; + } + } + + /* + * Add non-withdrawn routes from less-specific prefix + */ + if (parent) { + rib_rn = rfd_rib_table + ? route_node_get(rfd_rib_table, &parent->p) + : NULL; + rfapiQprefix2Rprefix(&parent->p, &rprefix); + count += rfapiNhlAddNodeRoutes(parent, &rprefix, lifetime, 0, + &answer, &last, exclude_vnaddr, + rib_rn, pfx_target_original); + count += rfapiNhlAddSubtree(parent, lifetime, &answer, &last, + rn, exclude_vnaddr, rfd_rib_table, + pfx_target_original); + if (rib_rn) + route_unlock_node(rib_rn); + } else { + /* + * There is no parent with non-removed routes. Still need to + * add subtree of original node if it contributed routes to the + * answer. + */ + if (count) + count += rfapiNhlAddSubtree(rn, lifetime, &answer, + &last, rn, exclude_vnaddr, + rfd_rib_table, + pfx_target_original); + } + + vnc_zlog_debug_verbose("%s: %d nexthops, answer=%p", __func__, count, + answer); #if DEBUG_RETURNED_NHL - rfapiPrintNhl (NULL, answer); + rfapiPrintNhl(NULL, answer); #endif - return answer; + return answer; } /* * Construct nexthop list of all routes in table */ -struct rfapi_next_hop_entry * -rfapiRouteTable2NextHopList ( - struct route_table *rt, - uint32_t lifetime, /* put into nexthop entries */ - struct rfapi_ip_addr *exclude_vnaddr,/* omit routes to same NVE */ - struct route_table *rfd_rib_table, /* preload this NVE rib table */ - struct prefix *pfx_target_original) /* query target */ +struct rfapi_next_hop_entry *rfapiRouteTable2NextHopList( + struct route_table *rt, + uint32_t lifetime, /* put into nexthop entries */ + struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ + struct route_table *rfd_rib_table, /* preload this NVE rib table */ + struct prefix *pfx_target_original) /* query target */ { - struct route_node *rn; - struct rfapi_next_hop_entry *biglist = NULL; - struct rfapi_next_hop_entry *nhl; - struct rfapi_next_hop_entry *tail = NULL; - int count = 0; - - for (rn = route_top (rt); rn; rn = route_next (rn)) - { - - nhl = rfapiRouteNode2NextHopList (rn, lifetime, exclude_vnaddr, - rfd_rib_table, pfx_target_original); - if (!tail) - { - tail = biglist = nhl; - if (tail) - count = 1; - } - else - { - tail->next = nhl; - } - if (tail) - { - while (tail->next) - { - ++count; - tail = tail->next; - } - } - } - - vnc_zlog_debug_verbose ("%s: returning %d routes", __func__, count); - return biglist; + struct route_node *rn; + struct rfapi_next_hop_entry *biglist = NULL; + struct rfapi_next_hop_entry *nhl; + struct rfapi_next_hop_entry *tail = NULL; + int count = 0; + + for (rn = route_top(rt); rn; rn = route_next(rn)) { + + nhl = rfapiRouteNode2NextHopList(rn, lifetime, exclude_vnaddr, + rfd_rib_table, + pfx_target_original); + if (!tail) { + tail = biglist = nhl; + if (tail) + count = 1; + } else { + tail->next = nhl; + } + if (tail) { + while (tail->next) { + ++count; + tail = tail->next; + } + } + } + + vnc_zlog_debug_verbose("%s: returning %d routes", __func__, count); + return biglist; } -struct rfapi_next_hop_entry * -rfapiEthRouteNode2NextHopList ( - struct route_node *rn, - struct rfapi_ip_prefix *rprefix, - uint32_t lifetime, /* put into nexthop entries */ - struct rfapi_ip_addr *exclude_vnaddr,/* omit routes to same NVE */ - struct route_table *rfd_rib_table,/* preload NVE rib table */ - struct prefix *pfx_target_original) /* query target */ +struct rfapi_next_hop_entry *rfapiEthRouteNode2NextHopList( + struct route_node *rn, struct rfapi_ip_prefix *rprefix, + uint32_t lifetime, /* put into nexthop entries */ + struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ + struct route_table *rfd_rib_table, /* preload NVE rib table */ + struct prefix *pfx_target_original) /* query target */ { - int count = 0; - struct rfapi_next_hop_entry *answer = NULL; - struct rfapi_next_hop_entry *last = NULL; - struct route_node *rib_rn; + int count = 0; + struct rfapi_next_hop_entry *answer = NULL; + struct rfapi_next_hop_entry *last = NULL; + struct route_node *rib_rn; - rib_rn = rfd_rib_table? route_node_get(rfd_rib_table, &rn->p): NULL; + rib_rn = rfd_rib_table ? route_node_get(rfd_rib_table, &rn->p) : NULL; - count = rfapiNhlAddNodeRoutes (rn, rprefix, lifetime, 0, &answer, &last, - NULL, rib_rn, pfx_target_original); + count = rfapiNhlAddNodeRoutes(rn, rprefix, lifetime, 0, &answer, &last, + NULL, rib_rn, pfx_target_original); #if DEBUG_ENCAP_MONITOR - vnc_zlog_debug_verbose ("%s: node %p: %d non-holddown routes", __func__, rn, count); + vnc_zlog_debug_verbose("%s: node %p: %d non-holddown routes", __func__, + rn, count); #endif - if (!count) - { - count = rfapiNhlAddNodeRoutes (rn, rprefix, lifetime, 1, &answer, &last, - exclude_vnaddr, rib_rn, pfx_target_original); - vnc_zlog_debug_verbose ("%s: node %p: %d holddown routes", __func__, rn, count); - } + if (!count) { + count = rfapiNhlAddNodeRoutes(rn, rprefix, lifetime, 1, &answer, + &last, exclude_vnaddr, rib_rn, + pfx_target_original); + vnc_zlog_debug_verbose("%s: node %p: %d holddown routes", + __func__, rn, count); + } - if (rib_rn) - route_unlock_node(rib_rn); + if (rib_rn) + route_unlock_node(rib_rn); #if DEBUG_RETURNED_NHL - rfapiPrintNhl (NULL, answer); + rfapiPrintNhl(NULL, answer); #endif - return answer; + return answer; } /* * Construct nexthop list of all routes in table */ -struct rfapi_next_hop_entry * -rfapiEthRouteTable2NextHopList ( - uint32_t logical_net_id, - struct rfapi_ip_prefix *rprefix, - uint32_t lifetime, /* put into nexthop entries */ - struct rfapi_ip_addr *exclude_vnaddr,/* omit routes to same NVE */ - struct route_table *rfd_rib_table, /* preload NVE rib node */ - struct prefix *pfx_target_original) /* query target */ +struct rfapi_next_hop_entry *rfapiEthRouteTable2NextHopList( + uint32_t logical_net_id, struct rfapi_ip_prefix *rprefix, + uint32_t lifetime, /* put into nexthop entries */ + struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ + struct route_table *rfd_rib_table, /* preload NVE rib node */ + struct prefix *pfx_target_original) /* query target */ { - struct rfapi_import_table *it; - struct bgp *bgp = bgp_get_default (); - struct route_table *rt; - struct route_node *rn; - struct rfapi_next_hop_entry *biglist = NULL; - struct rfapi_next_hop_entry *nhl; - struct rfapi_next_hop_entry *tail = NULL; - int count = 0; - - - it = rfapiMacImportTableGet (bgp, logical_net_id); - rt = it->imported_vpn[AFI_L2VPN]; - - for (rn = route_top (rt); rn; rn = route_next (rn)) - { - - nhl = rfapiEthRouteNode2NextHopList(rn, rprefix, lifetime, - exclude_vnaddr, rfd_rib_table, pfx_target_original); - if (!tail) - { - tail = biglist = nhl; - if (tail) - count = 1; - } - else - { - tail->next = nhl; - } - if (tail) - { - while (tail->next) - { - ++count; - tail = tail->next; - } - } - } - - vnc_zlog_debug_verbose ("%s: returning %d routes", __func__, count); - return biglist; + struct rfapi_import_table *it; + struct bgp *bgp = bgp_get_default(); + struct route_table *rt; + struct route_node *rn; + struct rfapi_next_hop_entry *biglist = NULL; + struct rfapi_next_hop_entry *nhl; + struct rfapi_next_hop_entry *tail = NULL; + int count = 0; + + + it = rfapiMacImportTableGet(bgp, logical_net_id); + rt = it->imported_vpn[AFI_L2VPN]; + + for (rn = route_top(rt); rn; rn = route_next(rn)) { + + nhl = rfapiEthRouteNode2NextHopList( + rn, rprefix, lifetime, exclude_vnaddr, rfd_rib_table, + pfx_target_original); + if (!tail) { + tail = biglist = nhl; + if (tail) + count = 1; + } else { + tail->next = nhl; + } + if (tail) { + while (tail->next) { + ++count; + tail = tail->next; + } + } + } + + vnc_zlog_debug_verbose("%s: returning %d routes", __func__, count); + return biglist; } /* * Insert a new bi to the imported route table node, * keeping the list of BIs sorted best route first */ -static void -rfapiBgpInfoAttachSorted ( - struct route_node *rn, - struct bgp_info *info_new, - afi_t afi, - safi_t safi) +static void rfapiBgpInfoAttachSorted(struct route_node *rn, + struct bgp_info *info_new, afi_t afi, + safi_t safi) { - struct bgp *bgp; - struct bgp_info *prev; - struct bgp_info *next; - char pfx_buf[PREFIX2STR_BUFFER]; - - - bgp = bgp_get_default (); /* assume 1 instance for now */ - - if (VNC_DEBUG(IMPORT_BI_ATTACH)) - { - vnc_zlog_debug_verbose ("%s: info_new->peer=%p", __func__, info_new->peer); - vnc_zlog_debug_verbose ("%s: info_new->peer->su_remote=%p", __func__, - info_new->peer->su_remote); - } - - for (prev = NULL, next = rn->info; next; prev = next, next = next->next) - { - if (!bgp || - (!CHECK_FLAG (info_new->flags, BGP_INFO_REMOVED) && - CHECK_FLAG (next->flags, BGP_INFO_REMOVED)) || - bgp_info_cmp_compatible (bgp, info_new, next, pfx_buf, afi, safi) == -1) - { /* -1 if 1st is better */ - break; - } - } - vnc_zlog_debug_verbose ("%s: prev=%p, next=%p", __func__, prev, next); - if (prev) - { - prev->next = info_new; - } - else - { - rn->info = info_new; - } - info_new->prev = prev; - info_new->next = next; - if (next) - next->prev = info_new; - bgp_attr_intern (info_new->attr); + struct bgp *bgp; + struct bgp_info *prev; + struct bgp_info *next; + char pfx_buf[PREFIX2STR_BUFFER]; + + + bgp = bgp_get_default(); /* assume 1 instance for now */ + + if (VNC_DEBUG(IMPORT_BI_ATTACH)) { + vnc_zlog_debug_verbose("%s: info_new->peer=%p", __func__, + info_new->peer); + vnc_zlog_debug_verbose("%s: info_new->peer->su_remote=%p", + __func__, info_new->peer->su_remote); + } + + for (prev = NULL, next = rn->info; next; + prev = next, next = next->next) { + if (!bgp || (!CHECK_FLAG(info_new->flags, BGP_INFO_REMOVED) + && CHECK_FLAG(next->flags, BGP_INFO_REMOVED)) + || bgp_info_cmp_compatible(bgp, info_new, next, pfx_buf, + afi, safi) + == -1) { /* -1 if 1st is better */ + break; + } + } + vnc_zlog_debug_verbose("%s: prev=%p, next=%p", __func__, prev, next); + if (prev) { + prev->next = info_new; + } else { + rn->info = info_new; + } + info_new->prev = prev; + info_new->next = next; + if (next) + next->prev = info_new; + bgp_attr_intern(info_new->attr); } -static void -rfapiBgpInfoDetach (struct route_node *rn, struct bgp_info *bi) +static void rfapiBgpInfoDetach(struct route_node *rn, struct bgp_info *bi) { - /* - * Remove the route (doubly-linked) - */ - // bgp_attr_unintern (&bi->attr); - if (bi->next) - bi->next->prev = bi->prev; - if (bi->prev) - bi->prev->next = bi->next; - else - rn->info = bi->next; + /* + * Remove the route (doubly-linked) + */ + // bgp_attr_unintern (&bi->attr); + if (bi->next) + bi->next->prev = bi->prev; + if (bi->prev) + bi->prev->next = bi->next; + else + rn->info = bi->next; } /* * For L3-indexed import tables */ -static int -rfapi_bi_peer_rd_cmp (void *b1, void *b2) +static int rfapi_bi_peer_rd_cmp(void *b1, void *b2) { - struct bgp_info *bi1 = b1; - struct bgp_info *bi2 = b2; - - /* - * Compare peers - */ - if (bi1->peer < bi2->peer) - return -1; - if (bi1->peer > bi2->peer) - return 1; - - /* - * compare RDs - */ - return vnc_prefix_cmp ((struct prefix *) &bi1->extra->vnc.import.rd, - (struct prefix *) &bi2->extra->vnc.import.rd); + struct bgp_info *bi1 = b1; + struct bgp_info *bi2 = b2; + + /* + * Compare peers + */ + if (bi1->peer < bi2->peer) + return -1; + if (bi1->peer > bi2->peer) + return 1; + + /* + * compare RDs + */ + return vnc_prefix_cmp((struct prefix *)&bi1->extra->vnc.import.rd, + (struct prefix *)&bi2->extra->vnc.import.rd); } /* @@ -2198,765 +2074,717 @@ rfapi_bi_peer_rd_cmp (void *b1, void *b2) * The BIs in these tables should ALWAYS have an aux_prefix set because * they arrive via IPv4 or IPv6 advertisements. */ -static int -rfapi_bi_peer_rd_aux_cmp (void *b1, void *b2) +static int rfapi_bi_peer_rd_aux_cmp(void *b1, void *b2) { - struct bgp_info *bi1 = b1; - struct bgp_info *bi2 = b2; - int rc; - - /* - * Compare peers - */ - if (bi1->peer < bi2->peer) - return -1; - if (bi1->peer > bi2->peer) - return 1; - - /* - * compare RDs - */ - rc = vnc_prefix_cmp ((struct prefix *) &bi1->extra->vnc.import.rd, - (struct prefix *) &bi2->extra->vnc.import.rd); - if (rc) - { - return rc; - } - - /* - * L2 import tables can have multiple entries with the - * same MAC address, same RD, but different L3 addresses. - * - * Use presence of aux_prefix with AF=ethernet and prefixlen=1 - * as magic value to signify explicit wildcarding of the aux_prefix. - * This magic value will not appear in bona fide bi entries in - * the import table, but is allowed in the "fake" bi used to - * probe the table when searching. (We have to test both b1 and b2 - * because there is no guarantee of the order the test key and - * the real key will be passed) - */ - if ((bi1->extra->vnc.import.aux_prefix.family == AF_ETHERNET && - (bi1->extra->vnc.import.aux_prefix.prefixlen == 1)) || - (bi2->extra->vnc.import.aux_prefix.family == AF_ETHERNET && - (bi2->extra->vnc.import.aux_prefix.prefixlen == 1))) - { - - /* - * wildcard aux address specified - */ - return 0; - } - - return vnc_prefix_cmp (&bi1->extra->vnc.import.aux_prefix, - &bi2->extra->vnc.import.aux_prefix); + struct bgp_info *bi1 = b1; + struct bgp_info *bi2 = b2; + int rc; + + /* + * Compare peers + */ + if (bi1->peer < bi2->peer) + return -1; + if (bi1->peer > bi2->peer) + return 1; + + /* + * compare RDs + */ + rc = vnc_prefix_cmp((struct prefix *)&bi1->extra->vnc.import.rd, + (struct prefix *)&bi2->extra->vnc.import.rd); + if (rc) { + return rc; + } + + /* + * L2 import tables can have multiple entries with the + * same MAC address, same RD, but different L3 addresses. + * + * Use presence of aux_prefix with AF=ethernet and prefixlen=1 + * as magic value to signify explicit wildcarding of the aux_prefix. + * This magic value will not appear in bona fide bi entries in + * the import table, but is allowed in the "fake" bi used to + * probe the table when searching. (We have to test both b1 and b2 + * because there is no guarantee of the order the test key and + * the real key will be passed) + */ + if ((bi1->extra->vnc.import.aux_prefix.family == AF_ETHERNET + && (bi1->extra->vnc.import.aux_prefix.prefixlen == 1)) + || (bi2->extra->vnc.import.aux_prefix.family == AF_ETHERNET + && (bi2->extra->vnc.import.aux_prefix.prefixlen == 1))) { + + /* + * wildcard aux address specified + */ + return 0; + } + + return vnc_prefix_cmp(&bi1->extra->vnc.import.aux_prefix, + &bi2->extra->vnc.import.aux_prefix); } /* * Index on RD and Peer */ -static void -rfapiItBiIndexAdd ( - struct route_node *rn, /* Import table VPN node */ - struct bgp_info *bi) /* new BI */ +static void rfapiItBiIndexAdd(struct route_node *rn, /* Import table VPN node */ + struct bgp_info *bi) /* new BI */ { - struct skiplist *sl; - - assert (rn); - assert (bi); - assert (bi->extra); - - { - char buf[BUFSIZ]; - prefix_rd2str (&bi->extra->vnc.import.rd, buf, BUFSIZ); - vnc_zlog_debug_verbose ("%s: bi %p, peer %p, rd %s", __func__, bi, bi->peer, buf); - } - - sl = RFAPI_RDINDEX_W_ALLOC (rn); - if (!sl) - { - if (AF_ETHERNET == rn->p.family) - { - sl = skiplist_new (0, rfapi_bi_peer_rd_aux_cmp, NULL); - } - else - { - sl = skiplist_new (0, rfapi_bi_peer_rd_cmp, NULL); - } - RFAPI_IT_EXTRA_GET (rn)->u.vpn.idx_rd = sl; - route_lock_node (rn); /* for skiplist */ - } - assert (!skiplist_insert (sl, (void *) bi, (void *) bi)); - route_lock_node (rn); /* for skiplist entry */ - - /* NB: BIs in import tables are not refcounted */ + struct skiplist *sl; + + assert(rn); + assert(bi); + assert(bi->extra); + + { + char buf[BUFSIZ]; + prefix_rd2str(&bi->extra->vnc.import.rd, buf, BUFSIZ); + vnc_zlog_debug_verbose("%s: bi %p, peer %p, rd %s", __func__, + bi, bi->peer, buf); + } + + sl = RFAPI_RDINDEX_W_ALLOC(rn); + if (!sl) { + if (AF_ETHERNET == rn->p.family) { + sl = skiplist_new(0, rfapi_bi_peer_rd_aux_cmp, NULL); + } else { + sl = skiplist_new(0, rfapi_bi_peer_rd_cmp, NULL); + } + RFAPI_IT_EXTRA_GET(rn)->u.vpn.idx_rd = sl; + route_lock_node(rn); /* for skiplist */ + } + assert(!skiplist_insert(sl, (void *)bi, (void *)bi)); + route_lock_node(rn); /* for skiplist entry */ + + /* NB: BIs in import tables are not refcounted */ } -static void -rfapiItBiIndexDump (struct route_node *rn) +static void rfapiItBiIndexDump(struct route_node *rn) { - struct skiplist *sl; - void *cursor = NULL; - struct bgp_info *k; - struct bgp_info *v; - int rc; - - sl = RFAPI_RDINDEX (rn); - if (!sl) - return; - - for (rc = skiplist_next (sl, (void **) &k, (void **) &v, &cursor); - !rc; rc = skiplist_next (sl, (void **) &k, (void **) &v, &cursor)) - { - - char buf[BUFSIZ]; - char buf_aux_pfx[BUFSIZ]; - - prefix_rd2str (&k->extra->vnc.import.rd, buf, BUFSIZ); - buf_aux_pfx[0] = 0; - if (k->extra->vnc.import.aux_prefix.family) - { - prefix2str (&k->extra->vnc.import.aux_prefix, buf_aux_pfx, BUFSIZ); - } - else - { - strncpy (buf_aux_pfx, "(none)", BUFSIZ); - buf_aux_pfx[BUFSIZ - 1] = 0; - } - - vnc_zlog_debug_verbose ("bi %p, peer %p, rd %s, aux_prefix %s", k, k->peer, buf, - buf_aux_pfx); - } + struct skiplist *sl; + void *cursor = NULL; + struct bgp_info *k; + struct bgp_info *v; + int rc; + + sl = RFAPI_RDINDEX(rn); + if (!sl) + return; + + for (rc = skiplist_next(sl, (void **)&k, (void **)&v, &cursor); !rc; + rc = skiplist_next(sl, (void **)&k, (void **)&v, &cursor)) { + + char buf[BUFSIZ]; + char buf_aux_pfx[BUFSIZ]; + + prefix_rd2str(&k->extra->vnc.import.rd, buf, BUFSIZ); + buf_aux_pfx[0] = 0; + if (k->extra->vnc.import.aux_prefix.family) { + prefix2str(&k->extra->vnc.import.aux_prefix, + buf_aux_pfx, BUFSIZ); + } else { + strncpy(buf_aux_pfx, "(none)", BUFSIZ); + buf_aux_pfx[BUFSIZ - 1] = 0; + } + + vnc_zlog_debug_verbose("bi %p, peer %p, rd %s, aux_prefix %s", + k, k->peer, buf, buf_aux_pfx); + } } -static struct bgp_info * -rfapiItBiIndexSearch ( - struct route_node *rn, /* Import table VPN node */ - struct prefix_rd *prd, - struct peer *peer, - struct prefix *aux_prefix) /* optional L3 addr for L2 ITs */ +static struct bgp_info *rfapiItBiIndexSearch( + struct route_node *rn, /* Import table VPN node */ + struct prefix_rd *prd, struct peer *peer, + struct prefix *aux_prefix) /* optional L3 addr for L2 ITs */ { - struct skiplist *sl; - int rc; - struct bgp_info bi_fake; - struct bgp_info_extra bi_extra; - struct bgp_info *bi_result; + struct skiplist *sl; + int rc; + struct bgp_info bi_fake; + struct bgp_info_extra bi_extra; + struct bgp_info *bi_result; - sl = RFAPI_RDINDEX (rn); - if (!sl) - return NULL; + sl = RFAPI_RDINDEX(rn); + if (!sl) + return NULL; #if DEBUG_BI_SEARCH - { - char buf[BUFSIZ]; - char buf_aux_pfx[BUFSIZ]; - - prefix_rd2str (prd, buf, BUFSIZ); - if (aux_prefix) - { - prefix2str (aux_prefix, buf_aux_pfx, BUFSIZ); - } - else - { - strncpy (buf_aux_pfx, "(nil)", BUFSIZ - 1); - buf_aux_pfx[BUFSIZ - 1] = 0; - } - - vnc_zlog_debug_verbose ("%s want prd=%s, peer=%p, aux_prefix=%s", - __func__, buf, peer, buf_aux_pfx); - rfapiItBiIndexDump (rn); - } + { + char buf[BUFSIZ]; + char buf_aux_pfx[BUFSIZ]; + + prefix_rd2str(prd, buf, BUFSIZ); + if (aux_prefix) { + prefix2str(aux_prefix, buf_aux_pfx, BUFSIZ); + } else { + strncpy(buf_aux_pfx, "(nil)", BUFSIZ - 1); + buf_aux_pfx[BUFSIZ - 1] = 0; + } + + vnc_zlog_debug_verbose("%s want prd=%s, peer=%p, aux_prefix=%s", + __func__, buf, peer, buf_aux_pfx); + rfapiItBiIndexDump(rn); + } #endif - /* threshold is a WAG */ - if (sl->count < 3) - { + /* threshold is a WAG */ + if (sl->count < 3) { #if DEBUG_BI_SEARCH - vnc_zlog_debug_verbose ("%s: short list algorithm", __func__); + vnc_zlog_debug_verbose("%s: short list algorithm", __func__); #endif - /* if short list, linear search might be faster */ - for (bi_result = rn->info; bi_result; bi_result = bi_result->next) - { + /* if short list, linear search might be faster */ + for (bi_result = rn->info; bi_result; + bi_result = bi_result->next) { #if DEBUG_BI_SEARCH - { - char buf[BUFSIZ]; - prefix_rd2str (&bi_result->extra->vnc.import.rd, buf, BUFSIZ); - vnc_zlog_debug_verbose ("%s: bi has prd=%s, peer=%p", __func__, - buf, bi_result->peer); - } + { + char buf[BUFSIZ]; + prefix_rd2str(&bi_result->extra->vnc.import.rd, + buf, BUFSIZ); + vnc_zlog_debug_verbose( + "%s: bi has prd=%s, peer=%p", __func__, + buf, bi_result->peer); + } #endif - if (peer == bi_result->peer && - !prefix_cmp ((struct prefix *) &bi_result->extra->vnc.import.rd, - (struct prefix *) prd)) - { + if (peer == bi_result->peer + && !prefix_cmp((struct prefix *)&bi_result->extra + ->vnc.import.rd, + (struct prefix *)prd)) { #if DEBUG_BI_SEARCH - vnc_zlog_debug_verbose ("%s: peer and RD same, doing aux_prefix check", - __func__); + vnc_zlog_debug_verbose( + "%s: peer and RD same, doing aux_prefix check", + __func__); #endif - if (!aux_prefix || - !prefix_cmp (aux_prefix, - &bi_result->extra->vnc.import.aux_prefix)) - { + if (!aux_prefix + || !prefix_cmp(aux_prefix, + &bi_result->extra->vnc.import + .aux_prefix)) { #if DEBUG_BI_SEARCH - vnc_zlog_debug_verbose ("%s: match", __func__); + vnc_zlog_debug_verbose("%s: match", + __func__); #endif - break; - } - - } - } - return bi_result; - } - - bi_fake.peer = peer; - bi_fake.extra = &bi_extra; - bi_fake.extra->vnc.import.rd = *(struct prefix_rd *) prd; - if (aux_prefix) - { - bi_fake.extra->vnc.import.aux_prefix = *aux_prefix; - } - else - { - /* wildcard */ - bi_fake.extra->vnc.import.aux_prefix.family = AF_ETHERNET; - bi_fake.extra->vnc.import.aux_prefix.prefixlen = 1; - } - - rc = skiplist_search (sl, (void *) &bi_fake, (void *) &bi_result); - - if (rc) - { + break; + } + } + } + return bi_result; + } + + bi_fake.peer = peer; + bi_fake.extra = &bi_extra; + bi_fake.extra->vnc.import.rd = *(struct prefix_rd *)prd; + if (aux_prefix) { + bi_fake.extra->vnc.import.aux_prefix = *aux_prefix; + } else { + /* wildcard */ + bi_fake.extra->vnc.import.aux_prefix.family = AF_ETHERNET; + bi_fake.extra->vnc.import.aux_prefix.prefixlen = 1; + } + + rc = skiplist_search(sl, (void *)&bi_fake, (void *)&bi_result); + + if (rc) { #if DEBUG_BI_SEARCH - vnc_zlog_debug_verbose ("%s: no match", __func__); + vnc_zlog_debug_verbose("%s: no match", __func__); #endif - return NULL; - } + return NULL; + } #if DEBUG_BI_SEARCH - vnc_zlog_debug_verbose ("%s: matched bi=%p", __func__, bi_result); + vnc_zlog_debug_verbose("%s: matched bi=%p", __func__, bi_result); #endif - return bi_result; + return bi_result; } -static void -rfapiItBiIndexDel ( - struct route_node *rn, /* Import table VPN node */ - struct bgp_info *bi) /* old BI */ +static void rfapiItBiIndexDel(struct route_node *rn, /* Import table VPN node */ + struct bgp_info *bi) /* old BI */ { - struct skiplist *sl; - int rc; + struct skiplist *sl; + int rc; - { - char buf[BUFSIZ]; - prefix_rd2str (&bi->extra->vnc.import.rd, buf, BUFSIZ); - vnc_zlog_debug_verbose ("%s: bi %p, peer %p, rd %s", __func__, bi, bi->peer, buf); - } + { + char buf[BUFSIZ]; + prefix_rd2str(&bi->extra->vnc.import.rd, buf, BUFSIZ); + vnc_zlog_debug_verbose("%s: bi %p, peer %p, rd %s", __func__, + bi, bi->peer, buf); + } - sl = RFAPI_RDINDEX (rn); - assert (sl); + sl = RFAPI_RDINDEX(rn); + assert(sl); - rc = skiplist_delete (sl, (void *) (bi), (void *) bi); - if (rc) - { - rfapiItBiIndexDump (rn); - } - assert (!rc); + rc = skiplist_delete(sl, (void *)(bi), (void *)bi); + if (rc) { + rfapiItBiIndexDump(rn); + } + assert(!rc); - route_unlock_node (rn); /* for skiplist entry */ + route_unlock_node(rn); /* for skiplist entry */ - /* NB: BIs in import tables are not refcounted */ + /* NB: BIs in import tables are not refcounted */ } /* * Add a backreference at the ENCAP node to the VPN route that * refers to it */ -static void -rfapiMonitorEncapAdd ( - struct rfapi_import_table *import_table, - struct prefix *p, /* VN address */ - struct route_node *vpn_rn, /* VPN node */ - struct bgp_info *vpn_bi) /* VPN bi/route */ +static void rfapiMonitorEncapAdd(struct rfapi_import_table *import_table, + struct prefix *p, /* VN address */ + struct route_node *vpn_rn, /* VPN node */ + struct bgp_info *vpn_bi) /* VPN bi/route */ { - afi_t afi = family2afi (p->family); - struct route_node *rn; - struct rfapi_monitor_encap *m; - - assert (afi); - rn = route_node_get (import_table->imported_encap[afi], p); /* locks rn */ - assert (rn); - - m = - XCALLOC (MTYPE_RFAPI_MONITOR_ENCAP, sizeof (struct rfapi_monitor_encap)); - assert (m); - - m->node = vpn_rn; - m->bi = vpn_bi; - m->rn = rn; - - /* insert to encap node's list */ - m->next = RFAPI_MONITOR_ENCAP (rn); - if (m->next) - m->next->prev = m; - RFAPI_MONITOR_ENCAP_W_ALLOC (rn) = m; - - /* for easy lookup when deleting vpn route */ - vpn_bi->extra->vnc.import.hme = m; - - vnc_zlog_debug_verbose - ("%s: it=%p, vpn_bi=%p, afi=%d, encap rn=%p, setting vpn_bi->extra->vnc.import.hme=%p", - __func__, import_table, vpn_bi, afi, rn, m); - - RFAPI_CHECK_REFCOUNT (rn, SAFI_ENCAP, 0); - bgp_attr_intern (vpn_bi->attr); + afi_t afi = family2afi(p->family); + struct route_node *rn; + struct rfapi_monitor_encap *m; + + assert(afi); + rn = route_node_get(import_table->imported_encap[afi], + p); /* locks rn */ + assert(rn); + + m = XCALLOC(MTYPE_RFAPI_MONITOR_ENCAP, + sizeof(struct rfapi_monitor_encap)); + assert(m); + + m->node = vpn_rn; + m->bi = vpn_bi; + m->rn = rn; + + /* insert to encap node's list */ + m->next = RFAPI_MONITOR_ENCAP(rn); + if (m->next) + m->next->prev = m; + RFAPI_MONITOR_ENCAP_W_ALLOC(rn) = m; + + /* for easy lookup when deleting vpn route */ + vpn_bi->extra->vnc.import.hme = m; + + vnc_zlog_debug_verbose( + "%s: it=%p, vpn_bi=%p, afi=%d, encap rn=%p, setting vpn_bi->extra->vnc.import.hme=%p", + __func__, import_table, vpn_bi, afi, rn, m); + + RFAPI_CHECK_REFCOUNT(rn, SAFI_ENCAP, 0); + bgp_attr_intern(vpn_bi->attr); } -static void -rfapiMonitorEncapDelete (struct bgp_info *vpn_bi) +static void rfapiMonitorEncapDelete(struct bgp_info *vpn_bi) { - /* - * Remove encap monitor - */ - vnc_zlog_debug_verbose ("%s: vpn_bi=%p", __func__, vpn_bi); - if (vpn_bi->extra) - { - struct rfapi_monitor_encap *hme = vpn_bi->extra->vnc.import.hme; - - if (hme) - { - - vnc_zlog_debug_verbose ("%s: hme=%p", __func__, hme); - - /* Refcount checking takes too long here */ - //RFAPI_CHECK_REFCOUNT(hme->rn, SAFI_ENCAP, 0); - if (hme->next) - hme->next->prev = hme->prev; - if (hme->prev) - hme->prev->next = hme->next; - else - RFAPI_MONITOR_ENCAP_W_ALLOC (hme->rn) = hme->next; - /* Refcount checking takes too long here */ - //RFAPI_CHECK_REFCOUNT(hme->rn, SAFI_ENCAP, 1); - - /* see if the struct rfapi_it_extra is empty and can be freed */ - rfapiMonitorExtraPrune (SAFI_ENCAP, hme->rn); - - route_unlock_node (hme->rn); /* decr ref count */ - XFREE (MTYPE_RFAPI_MONITOR_ENCAP, hme); - vpn_bi->extra->vnc.import.hme = NULL; - } - } + /* + * Remove encap monitor + */ + vnc_zlog_debug_verbose("%s: vpn_bi=%p", __func__, vpn_bi); + if (vpn_bi->extra) { + struct rfapi_monitor_encap *hme = vpn_bi->extra->vnc.import.hme; + + if (hme) { + + vnc_zlog_debug_verbose("%s: hme=%p", __func__, hme); + + /* Refcount checking takes too long here */ + // RFAPI_CHECK_REFCOUNT(hme->rn, SAFI_ENCAP, 0); + if (hme->next) + hme->next->prev = hme->prev; + if (hme->prev) + hme->prev->next = hme->next; + else + RFAPI_MONITOR_ENCAP_W_ALLOC(hme->rn) = + hme->next; + /* Refcount checking takes too long here */ + // RFAPI_CHECK_REFCOUNT(hme->rn, SAFI_ENCAP, 1); + + /* see if the struct rfapi_it_extra is empty and can be + * freed */ + rfapiMonitorExtraPrune(SAFI_ENCAP, hme->rn); + + route_unlock_node(hme->rn); /* decr ref count */ + XFREE(MTYPE_RFAPI_MONITOR_ENCAP, hme); + vpn_bi->extra->vnc.import.hme = NULL; + } + } } /* * quagga lib/thread.h says this must return int even though * it doesn't do anything with the return value */ -static int -rfapiWithdrawTimerVPN (struct thread *t) +static int rfapiWithdrawTimerVPN(struct thread *t) { - struct rfapi_withdraw *wcb = t->arg; - struct bgp_info *bi = wcb->info; - struct bgp *bgp = bgp_get_default (); - - struct rfapi_monitor_vpn *moved; - afi_t afi; - - assert (wcb->node); - assert (bi); - assert (wcb->import_table); - assert (bi->extra); - - RFAPI_CHECK_REFCOUNT (wcb->node, SAFI_MPLS_VPN, wcb->lockoffset); - - { - char buf[BUFSIZ]; - - vnc_zlog_debug_verbose ("%s: removing bi %p at prefix %s/%d", - __func__, - bi, - rfapi_ntop (wcb->node->p.family, &wcb->node->p.u.prefix, buf, - BUFSIZ), wcb->node->p.prefixlen); - } - - /* - * Remove the route (doubly-linked) - */ - if (CHECK_FLAG (bi->flags, BGP_INFO_VALID) - && VALID_INTERIOR_TYPE (bi->type)) - RFAPI_MONITOR_EXTERIOR (wcb->node)->valid_interior_count--; - - afi = family2afi (wcb->node->p.family); - wcb->import_table->holddown_count[afi] -= 1; /* keep count consistent */ - rfapiItBiIndexDel (wcb->node, bi); - rfapiBgpInfoDetach (wcb->node, bi); /* with removed bi */ - - vnc_import_bgp_exterior_del_route_interior (bgp, wcb->import_table, - wcb->node, bi); - - - /* - * If VNC is configured to send response remove messages, AND - * if the removed route had a UN address, do response removal - * processing. - */ - if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE)) - { - - int has_valid_duplicate = 0; - struct bgp_info *bii; - - /* - * First check if there are any OTHER routes at this node - * that have the same nexthop and a valid UN address. If - * there are (e.g., from other peers), then the route isn't - * really gone, so skip sending a response removal message. - */ - for (bii = wcb->node->info; bii; bii = bii->next) - { - if (rfapiVpnBiSamePtUn (bi, bii)) - { - has_valid_duplicate = 1; - break; - } - } - - vnc_zlog_debug_verbose ("%s: has_valid_duplicate=%d", __func__, - has_valid_duplicate); - - if (!has_valid_duplicate) - { - rfapiRibPendingDeleteRoute (bgp, wcb->import_table, afi, wcb->node); - } - } - - rfapiMonitorEncapDelete (bi); - - /* - * If there are no VPN monitors at this VPN Node A, - * we are done - */ - if (!RFAPI_MONITOR_VPN (wcb->node)) - { - vnc_zlog_debug_verbose ("%s: no VPN monitors at this node", __func__); - goto done; - } - - /* - * rfapiMonitorMoveShorter only moves monitors if there are - * no remaining valid routes at the current node - */ - moved = rfapiMonitorMoveShorter (wcb->node, 1); - - if (moved) - { - rfapiMonitorMovedUp (wcb->import_table, wcb->node, moved->node, moved); - } + struct rfapi_withdraw *wcb = t->arg; + struct bgp_info *bi = wcb->info; + struct bgp *bgp = bgp_get_default(); + + struct rfapi_monitor_vpn *moved; + afi_t afi; + + assert(wcb->node); + assert(bi); + assert(wcb->import_table); + assert(bi->extra); + + RFAPI_CHECK_REFCOUNT(wcb->node, SAFI_MPLS_VPN, wcb->lockoffset); + + { + char buf[BUFSIZ]; + + vnc_zlog_debug_verbose( + "%s: removing bi %p at prefix %s/%d", __func__, bi, + rfapi_ntop(wcb->node->p.family, &wcb->node->p.u.prefix, + buf, BUFSIZ), + wcb->node->p.prefixlen); + } + + /* + * Remove the route (doubly-linked) + */ + if (CHECK_FLAG(bi->flags, BGP_INFO_VALID) + && VALID_INTERIOR_TYPE(bi->type)) + RFAPI_MONITOR_EXTERIOR(wcb->node)->valid_interior_count--; + + afi = family2afi(wcb->node->p.family); + wcb->import_table->holddown_count[afi] -= 1; /* keep count consistent */ + rfapiItBiIndexDel(wcb->node, bi); + rfapiBgpInfoDetach(wcb->node, bi); /* with removed bi */ + + vnc_import_bgp_exterior_del_route_interior(bgp, wcb->import_table, + wcb->node, bi); + + + /* + * If VNC is configured to send response remove messages, AND + * if the removed route had a UN address, do response removal + * processing. + */ + if (!(bgp->rfapi_cfg->flags + & BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE)) { + + int has_valid_duplicate = 0; + struct bgp_info *bii; + + /* + * First check if there are any OTHER routes at this node + * that have the same nexthop and a valid UN address. If + * there are (e.g., from other peers), then the route isn't + * really gone, so skip sending a response removal message. + */ + for (bii = wcb->node->info; bii; bii = bii->next) { + if (rfapiVpnBiSamePtUn(bi, bii)) { + has_valid_duplicate = 1; + break; + } + } + + vnc_zlog_debug_verbose("%s: has_valid_duplicate=%d", __func__, + has_valid_duplicate); + + if (!has_valid_duplicate) { + rfapiRibPendingDeleteRoute(bgp, wcb->import_table, afi, + wcb->node); + } + } + + rfapiMonitorEncapDelete(bi); + + /* + * If there are no VPN monitors at this VPN Node A, + * we are done + */ + if (!RFAPI_MONITOR_VPN(wcb->node)) { + vnc_zlog_debug_verbose("%s: no VPN monitors at this node", + __func__); + goto done; + } + + /* + * rfapiMonitorMoveShorter only moves monitors if there are + * no remaining valid routes at the current node + */ + moved = rfapiMonitorMoveShorter(wcb->node, 1); + + if (moved) { + rfapiMonitorMovedUp(wcb->import_table, wcb->node, moved->node, + moved); + } done: - /* - * Free VPN bi - */ - rfapiBgpInfoFree (bi); - wcb->info = NULL; - - /* - * If route count at this node has gone to 0, withdraw exported prefix - */ - if (!wcb->node->info) - { - /* see if the struct rfapi_it_extra is empty and can be freed */ - rfapiMonitorExtraPrune (SAFI_MPLS_VPN, wcb->node); - vnc_direct_bgp_del_prefix (bgp, wcb->import_table, wcb->node); - vnc_zebra_del_prefix (bgp, wcb->import_table, wcb->node); - } - else - { - /* - * nexthop change event - * vnc_direct_bgp_add_prefix() will recompute the VN addr ecommunity - */ - vnc_direct_bgp_add_prefix (bgp, wcb->import_table, wcb->node); - } - - RFAPI_CHECK_REFCOUNT (wcb->node, SAFI_MPLS_VPN, 1 + wcb->lockoffset); - route_unlock_node (wcb->node); /* decr ref count */ - XFREE (MTYPE_RFAPI_WITHDRAW, wcb); - return 0; + /* + * Free VPN bi + */ + rfapiBgpInfoFree(bi); + wcb->info = NULL; + + /* + * If route count at this node has gone to 0, withdraw exported prefix + */ + if (!wcb->node->info) { + /* see if the struct rfapi_it_extra is empty and can be freed */ + rfapiMonitorExtraPrune(SAFI_MPLS_VPN, wcb->node); + vnc_direct_bgp_del_prefix(bgp, wcb->import_table, wcb->node); + vnc_zebra_del_prefix(bgp, wcb->import_table, wcb->node); + } else { + /* + * nexthop change event + * vnc_direct_bgp_add_prefix() will recompute the VN addr + * ecommunity + */ + vnc_direct_bgp_add_prefix(bgp, wcb->import_table, wcb->node); + } + + RFAPI_CHECK_REFCOUNT(wcb->node, SAFI_MPLS_VPN, 1 + wcb->lockoffset); + route_unlock_node(wcb->node); /* decr ref count */ + XFREE(MTYPE_RFAPI_WITHDRAW, wcb); + return 0; } /* * This works for multiprotocol extension, but not for plain ol' * unicast IPv4 because that nexthop is stored in attr->nexthop */ -void -rfapiNexthop2Prefix (struct attr *attr, struct prefix *p) +void rfapiNexthop2Prefix(struct attr *attr, struct prefix *p) { - assert (p); - assert (attr); - - memset (p, 0, sizeof (struct prefix)); - - switch (p->family = BGP_MP_NEXTHOP_FAMILY (attr->mp_nexthop_len)) - { - case AF_INET: - p->u.prefix4 = attr->mp_nexthop_global_in; - p->prefixlen = 32; - break; - - case AF_INET6: - p->u.prefix6 = attr->mp_nexthop_global; - p->prefixlen = 128; - break; - - default: - vnc_zlog_debug_verbose ("%s: Family is unknown = %d", - __func__, p->family); - } + assert(p); + assert(attr); + + memset(p, 0, sizeof(struct prefix)); + + switch (p->family = BGP_MP_NEXTHOP_FAMILY(attr->mp_nexthop_len)) { + case AF_INET: + p->u.prefix4 = attr->mp_nexthop_global_in; + p->prefixlen = 32; + break; + + case AF_INET6: + p->u.prefix6 = attr->mp_nexthop_global; + p->prefixlen = 128; + break; + + default: + vnc_zlog_debug_verbose("%s: Family is unknown = %d", __func__, + p->family); + } } -void -rfapiUnicastNexthop2Prefix (afi_t afi, struct attr *attr, struct prefix *p) +void rfapiUnicastNexthop2Prefix(afi_t afi, struct attr *attr, struct prefix *p) { - if (afi == AFI_IP) - { - p->family = AF_INET; - p->prefixlen = 32; - p->u.prefix4 = attr->nexthop; - } - else - { - rfapiNexthop2Prefix (attr, p); - } + if (afi == AFI_IP) { + p->family = AF_INET; + p->prefixlen = 32; + p->u.prefix4 = attr->nexthop; + } else { + rfapiNexthop2Prefix(attr, p); + } } -static int -rfapiAttrNexthopAddrDifferent (struct prefix *p1, struct prefix *p2) +static int rfapiAttrNexthopAddrDifferent(struct prefix *p1, struct prefix *p2) { - if (!p1 || !p2) - { - vnc_zlog_debug_verbose ("%s: p1 or p2 is NULL", __func__); - return 1; - } - - /* - * Are address families the same? - */ - if (p1->family != p2->family) - { - return 1; - } - - switch (p1->family) - { - case AF_INET: - if (IPV4_ADDR_SAME (&p1->u.prefix4, &p2->u.prefix4)) - return 0; - break; - - case AF_INET6: - if (IPV6_ADDR_SAME (&p1->u.prefix6, &p2->u.prefix6)) - return 0; - break; - - default: - assert (1); - - } - - return 1; + if (!p1 || !p2) { + vnc_zlog_debug_verbose("%s: p1 or p2 is NULL", __func__); + return 1; + } + + /* + * Are address families the same? + */ + if (p1->family != p2->family) { + return 1; + } + + switch (p1->family) { + case AF_INET: + if (IPV4_ADDR_SAME(&p1->u.prefix4, &p2->u.prefix4)) + return 0; + break; + + case AF_INET6: + if (IPV6_ADDR_SAME(&p1->u.prefix6, &p2->u.prefix6)) + return 0; + break; + + default: + assert(1); + } + + return 1; } -static void -rfapiCopyUnEncap2VPN (struct bgp_info *encap_bi, struct bgp_info *vpn_bi) +static void rfapiCopyUnEncap2VPN(struct bgp_info *encap_bi, + struct bgp_info *vpn_bi) { - if (!encap_bi->attr) - { - zlog_warn ("%s: no encap bi attr/extra, can't copy UN address", - __func__); - return; - } - - if (!vpn_bi || !vpn_bi->extra) - { - zlog_warn ("%s: no vpn bi attr/extra, can't copy UN address", - __func__); - return; - } - - switch (BGP_MP_NEXTHOP_FAMILY (encap_bi->attr->mp_nexthop_len)) - { - case AF_INET: - - /* - * instrumentation to debug segfault of 091127 - */ - vnc_zlog_debug_verbose ("%s: vpn_bi=%p", __func__, vpn_bi); - if (vpn_bi) - { - vnc_zlog_debug_verbose ("%s: vpn_bi->extra=%p", __func__, vpn_bi->extra); - } - - vpn_bi->extra->vnc.import.un_family = AF_INET; - vpn_bi->extra->vnc.import.un.addr4 = encap_bi->attr->mp_nexthop_global_in; - break; - - case AF_INET6: - vpn_bi->extra->vnc.import.un_family = AF_INET6; - vpn_bi->extra->vnc.import.un.addr6 = encap_bi->attr->mp_nexthop_global; - break; - - default: - zlog_warn ("%s: invalid encap nexthop length: %d", - __func__, encap_bi->attr->mp_nexthop_len); - vpn_bi->extra->vnc.import.un_family = 0; - break; - } + if (!encap_bi->attr) { + zlog_warn("%s: no encap bi attr/extra, can't copy UN address", + __func__); + return; + } + + if (!vpn_bi || !vpn_bi->extra) { + zlog_warn("%s: no vpn bi attr/extra, can't copy UN address", + __func__); + return; + } + + switch (BGP_MP_NEXTHOP_FAMILY(encap_bi->attr->mp_nexthop_len)) { + case AF_INET: + + /* + * instrumentation to debug segfault of 091127 + */ + vnc_zlog_debug_verbose("%s: vpn_bi=%p", __func__, vpn_bi); + if (vpn_bi) { + vnc_zlog_debug_verbose("%s: vpn_bi->extra=%p", __func__, + vpn_bi->extra); + } + + vpn_bi->extra->vnc.import.un_family = AF_INET; + vpn_bi->extra->vnc.import.un.addr4 = + encap_bi->attr->mp_nexthop_global_in; + break; + + case AF_INET6: + vpn_bi->extra->vnc.import.un_family = AF_INET6; + vpn_bi->extra->vnc.import.un.addr6 = + encap_bi->attr->mp_nexthop_global; + break; + + default: + zlog_warn("%s: invalid encap nexthop length: %d", __func__, + encap_bi->attr->mp_nexthop_len); + vpn_bi->extra->vnc.import.un_family = 0; + break; + } } /* * returns 0 on success, nonzero on error */ -static int -rfapiWithdrawEncapUpdateCachedUn ( - struct rfapi_import_table *import_table, - struct bgp_info *encap_bi, - struct route_node *vpn_rn, - struct bgp_info *vpn_bi) +static int rfapiWithdrawEncapUpdateCachedUn( + struct rfapi_import_table *import_table, struct bgp_info *encap_bi, + struct route_node *vpn_rn, struct bgp_info *vpn_bi) { - if (!encap_bi) - { - - /* - * clear cached UN address - */ - if (!vpn_bi || !vpn_bi->extra) - { - zlog_warn ("%s: missing VPN bi/extra, can't clear UN addr", - __func__); - return 1; - } - vpn_bi->extra->vnc.import.un_family = 0; - memset (&vpn_bi->extra->vnc.import.un, 0, - sizeof (vpn_bi->extra->vnc.import.un)); - if (CHECK_FLAG (vpn_bi->flags, BGP_INFO_VALID)) - { - if (rfapiGetVncTunnelUnAddr (vpn_bi->attr, NULL)) - { - UNSET_FLAG (vpn_bi->flags, BGP_INFO_VALID); - if (VALID_INTERIOR_TYPE (vpn_bi->type)) - RFAPI_MONITOR_EXTERIOR (vpn_rn)->valid_interior_count--; - /* signal interior route withdrawal to import-exterior */ - vnc_import_bgp_exterior_del_route_interior (bgp_get_default (), - import_table, - vpn_rn, vpn_bi); - } - } - - } - else - { - if (!vpn_bi) - { - zlog_warn ("%s: missing VPN bi, can't clear UN addr", __func__); - return 1; - } - rfapiCopyUnEncap2VPN (encap_bi, vpn_bi); - if (!CHECK_FLAG (vpn_bi->flags, BGP_INFO_VALID)) - { - SET_FLAG (vpn_bi->flags, BGP_INFO_VALID); - if (VALID_INTERIOR_TYPE (vpn_bi->type)) - RFAPI_MONITOR_EXTERIOR (vpn_rn)->valid_interior_count++; - /* signal interior route withdrawal to import-exterior */ - vnc_import_bgp_exterior_add_route_interior (bgp_get_default (), - import_table, - vpn_rn, vpn_bi); - } - } - return 0; + if (!encap_bi) { + + /* + * clear cached UN address + */ + if (!vpn_bi || !vpn_bi->extra) { + zlog_warn( + "%s: missing VPN bi/extra, can't clear UN addr", + __func__); + return 1; + } + vpn_bi->extra->vnc.import.un_family = 0; + memset(&vpn_bi->extra->vnc.import.un, 0, + sizeof(vpn_bi->extra->vnc.import.un)); + if (CHECK_FLAG(vpn_bi->flags, BGP_INFO_VALID)) { + if (rfapiGetVncTunnelUnAddr(vpn_bi->attr, NULL)) { + UNSET_FLAG(vpn_bi->flags, BGP_INFO_VALID); + if (VALID_INTERIOR_TYPE(vpn_bi->type)) + RFAPI_MONITOR_EXTERIOR(vpn_rn) + ->valid_interior_count--; + /* signal interior route withdrawal to + * import-exterior */ + vnc_import_bgp_exterior_del_route_interior( + bgp_get_default(), import_table, vpn_rn, + vpn_bi); + } + } + + } else { + if (!vpn_bi) { + zlog_warn("%s: missing VPN bi, can't clear UN addr", + __func__); + return 1; + } + rfapiCopyUnEncap2VPN(encap_bi, vpn_bi); + if (!CHECK_FLAG(vpn_bi->flags, BGP_INFO_VALID)) { + SET_FLAG(vpn_bi->flags, BGP_INFO_VALID); + if (VALID_INTERIOR_TYPE(vpn_bi->type)) + RFAPI_MONITOR_EXTERIOR(vpn_rn) + ->valid_interior_count++; + /* signal interior route withdrawal to import-exterior + */ + vnc_import_bgp_exterior_add_route_interior( + bgp_get_default(), import_table, vpn_rn, + vpn_bi); + } + } + return 0; } -static int -rfapiWithdrawTimerEncap (struct thread *t) +static int rfapiWithdrawTimerEncap(struct thread *t) { - struct rfapi_withdraw *wcb = t->arg; - struct bgp_info *bi = wcb->info; - int was_first_route = 0; - struct rfapi_monitor_encap *em; - struct skiplist *vpn_node_sl = skiplist_new (0, NULL, NULL); - - assert (wcb->node); - assert (bi); - assert (wcb->import_table); - - RFAPI_CHECK_REFCOUNT (wcb->node, SAFI_ENCAP, 0); - - if (wcb->node->info == bi) - was_first_route = 1; - - /* - * Remove the route/bi and free it - */ - rfapiBgpInfoDetach (wcb->node, bi); - rfapiBgpInfoFree (bi); - - if (!was_first_route) - goto done; - - for (em = RFAPI_MONITOR_ENCAP (wcb->node); em; em = em->next) - { - - /* - * Update monitoring VPN BIs with new encap info at the - * head of the encap bi chain (which could be NULL after - * removing the expiring bi above) - */ - if (rfapiWithdrawEncapUpdateCachedUn - (wcb->import_table, wcb->node->info, em->node, em->bi)) - continue; - - /* - * Build a list of unique VPN nodes referenced by these monitors. - * Use a skiplist for speed. - */ - skiplist_insert (vpn_node_sl, em->node, em->node); - } - - - /* - * for each VPN node referenced in the ENCAP monitors: - */ - struct route_node *rn; - while (!skiplist_first (vpn_node_sl, (void **) &rn, NULL)) - { - if (!wcb->node->info) - { - struct rfapi_monitor_vpn *moved; - - moved = rfapiMonitorMoveShorter (rn, 0); - if (moved) - { - //rfapiDoRouteCallback(wcb->import_table, moved->node, moved); - rfapiMonitorMovedUp (wcb->import_table, rn, moved->node, moved); - } - } - else - { - //rfapiDoRouteCallback(wcb->import_table, rn, NULL); - rfapiMonitorItNodeChanged (wcb->import_table, rn, NULL); - } - skiplist_delete_first (vpn_node_sl); - } + struct rfapi_withdraw *wcb = t->arg; + struct bgp_info *bi = wcb->info; + int was_first_route = 0; + struct rfapi_monitor_encap *em; + struct skiplist *vpn_node_sl = skiplist_new(0, NULL, NULL); + + assert(wcb->node); + assert(bi); + assert(wcb->import_table); + + RFAPI_CHECK_REFCOUNT(wcb->node, SAFI_ENCAP, 0); + + if (wcb->node->info == bi) + was_first_route = 1; + + /* + * Remove the route/bi and free it + */ + rfapiBgpInfoDetach(wcb->node, bi); + rfapiBgpInfoFree(bi); + + if (!was_first_route) + goto done; + + for (em = RFAPI_MONITOR_ENCAP(wcb->node); em; em = em->next) { + + /* + * Update monitoring VPN BIs with new encap info at the + * head of the encap bi chain (which could be NULL after + * removing the expiring bi above) + */ + if (rfapiWithdrawEncapUpdateCachedUn(wcb->import_table, + wcb->node->info, em->node, + em->bi)) + continue; + + /* + * Build a list of unique VPN nodes referenced by these + * monitors. + * Use a skiplist for speed. + */ + skiplist_insert(vpn_node_sl, em->node, em->node); + } + + + /* + * for each VPN node referenced in the ENCAP monitors: + */ + struct route_node *rn; + while (!skiplist_first(vpn_node_sl, (void **)&rn, NULL)) { + if (!wcb->node->info) { + struct rfapi_monitor_vpn *moved; + + moved = rfapiMonitorMoveShorter(rn, 0); + if (moved) { + // rfapiDoRouteCallback(wcb->import_table, + // moved->node, moved); + rfapiMonitorMovedUp(wcb->import_table, rn, + moved->node, moved); + } + } else { + // rfapiDoRouteCallback(wcb->import_table, rn, NULL); + rfapiMonitorItNodeChanged(wcb->import_table, rn, NULL); + } + skiplist_delete_first(vpn_node_sl); + } done: - RFAPI_CHECK_REFCOUNT (wcb->node, SAFI_ENCAP, 1); - route_unlock_node (wcb->node); /* decr ref count */ - XFREE (MTYPE_RFAPI_WITHDRAW, wcb); - skiplist_free (vpn_node_sl); - return 0; + RFAPI_CHECK_REFCOUNT(wcb->node, SAFI_ENCAP, 1); + route_unlock_node(wcb->node); /* decr ref count */ + XFREE(MTYPE_RFAPI_WITHDRAW, wcb); + skiplist_free(vpn_node_sl); + return 0; } @@ -2965,1391 +2793,1272 @@ done: * in each case */ static void -rfapiBiStartWithdrawTimer ( - struct rfapi_import_table *import_table, - struct route_node *rn, - struct bgp_info *bi, - afi_t afi, - safi_t safi, - int (*timer_service_func) (struct thread *)) +rfapiBiStartWithdrawTimer(struct rfapi_import_table *import_table, + struct route_node *rn, struct bgp_info *bi, afi_t afi, + safi_t safi, + int (*timer_service_func)(struct thread *)) { - uint32_t lifetime; - struct rfapi_withdraw *wcb; - - if CHECK_FLAG - (bi->flags, BGP_INFO_REMOVED) - { - /* - * Already on the path to being withdrawn, - * should already have a timer set up to - * delete it. - */ - vnc_zlog_debug_verbose ("%s: already being withdrawn, do nothing", __func__); - return; - } - - rfapiGetVncLifetime (bi->attr, &lifetime); - vnc_zlog_debug_verbose ("%s: VNC lifetime is %u", __func__, lifetime); - - /* - * withdrawn routes get to hang around for a while - */ - SET_FLAG (bi->flags, BGP_INFO_REMOVED); - - /* set timer to remove the route later */ - lifetime = rfapiGetHolddownFromLifetime (lifetime); - vnc_zlog_debug_verbose ("%s: using timeout %u", __func__, lifetime); - - /* - * Stash import_table, node, and info for use by timer - * service routine, which is supposed to free the wcb. - */ - wcb = XCALLOC (MTYPE_RFAPI_WITHDRAW, sizeof (struct rfapi_withdraw)); - assert (wcb); - wcb->node = rn; - wcb->info = bi; - wcb->import_table = import_table; - bgp_attr_intern (bi->attr); - - if (VNC_DEBUG(VERBOSE)) - { - vnc_zlog_debug_verbose - ("%s: wcb values: node=%p, info=%p, import_table=%p (bi follows)", - __func__, wcb->node, wcb->info, wcb->import_table); - rfapiPrintBi (NULL, bi); - } - - - assert (bi->extra); - if (lifetime > UINT32_MAX / 1001) - { - /* sub-optimal case, but will probably never happen */ - bi->extra->vnc.import.timer = NULL; - thread_add_timer(bm->master, timer_service_func, wcb, lifetime, - &bi->extra->vnc.import.timer); - } - else - { - static uint32_t jitter; - uint32_t lifetime_msec; - - /* - * the goal here is to spread out the timers so they are - * sortable in the skip list - */ - if (++jitter >= 1000) - jitter = 0; - - lifetime_msec = (lifetime * 1000) + jitter; - - bi->extra->vnc.import.timer = NULL; - thread_add_timer_msec(bm->master, timer_service_func, wcb, lifetime_msec, - &bi->extra->vnc.import.timer); - } - - /* re-sort route list (BGP_INFO_REMOVED routes are last) */ - if (((struct bgp_info *) rn->info)->next) - { - rfapiBgpInfoDetach (rn, bi); - rfapiBgpInfoAttachSorted (rn, bi, afi, safi); - } + uint32_t lifetime; + struct rfapi_withdraw *wcb; + + if + CHECK_FLAG(bi->flags, BGP_INFO_REMOVED) + { + /* + * Already on the path to being withdrawn, + * should already have a timer set up to + * delete it. + */ + vnc_zlog_debug_verbose( + "%s: already being withdrawn, do nothing", + __func__); + return; + } + + rfapiGetVncLifetime(bi->attr, &lifetime); + vnc_zlog_debug_verbose("%s: VNC lifetime is %u", __func__, lifetime); + + /* + * withdrawn routes get to hang around for a while + */ + SET_FLAG(bi->flags, BGP_INFO_REMOVED); + + /* set timer to remove the route later */ + lifetime = rfapiGetHolddownFromLifetime(lifetime); + vnc_zlog_debug_verbose("%s: using timeout %u", __func__, lifetime); + + /* + * Stash import_table, node, and info for use by timer + * service routine, which is supposed to free the wcb. + */ + wcb = XCALLOC(MTYPE_RFAPI_WITHDRAW, sizeof(struct rfapi_withdraw)); + assert(wcb); + wcb->node = rn; + wcb->info = bi; + wcb->import_table = import_table; + bgp_attr_intern(bi->attr); + + if (VNC_DEBUG(VERBOSE)) { + vnc_zlog_debug_verbose( + "%s: wcb values: node=%p, info=%p, import_table=%p (bi follows)", + __func__, wcb->node, wcb->info, wcb->import_table); + rfapiPrintBi(NULL, bi); + } + + + assert(bi->extra); + if (lifetime > UINT32_MAX / 1001) { + /* sub-optimal case, but will probably never happen */ + bi->extra->vnc.import.timer = NULL; + thread_add_timer(bm->master, timer_service_func, wcb, lifetime, + &bi->extra->vnc.import.timer); + } else { + static uint32_t jitter; + uint32_t lifetime_msec; + + /* + * the goal here is to spread out the timers so they are + * sortable in the skip list + */ + if (++jitter >= 1000) + jitter = 0; + + lifetime_msec = (lifetime * 1000) + jitter; + + bi->extra->vnc.import.timer = NULL; + thread_add_timer_msec(bm->master, timer_service_func, wcb, + lifetime_msec, + &bi->extra->vnc.import.timer); + } + + /* re-sort route list (BGP_INFO_REMOVED routes are last) */ + if (((struct bgp_info *)rn->info)->next) { + rfapiBgpInfoDetach(rn, bi); + rfapiBgpInfoAttachSorted(rn, bi, afi, safi); + } } -typedef void (rfapi_bi_filtered_import_f) (struct rfapi_import_table *, - int, - struct peer *, - void *, - struct prefix *, - struct prefix *, - afi_t, - struct prefix_rd *, - struct attr *, - u_char, u_char, uint32_t *); +typedef void(rfapi_bi_filtered_import_f)(struct rfapi_import_table *, int, + struct peer *, void *, struct prefix *, + struct prefix *, afi_t, + struct prefix_rd *, struct attr *, + u_char, u_char, uint32_t *); -static void -rfapiExpireEncapNow ( - struct rfapi_import_table *it, - struct route_node *rn, - struct bgp_info *bi) +static void rfapiExpireEncapNow(struct rfapi_import_table *it, + struct route_node *rn, struct bgp_info *bi) { - struct rfapi_withdraw *wcb; - struct thread t; - - /* - * pretend we're an expiring timer - */ - wcb = XCALLOC (MTYPE_RFAPI_WITHDRAW, sizeof (struct rfapi_withdraw)); - wcb->info = bi; - wcb->node = rn; - wcb->import_table = it; - memset (&t, 0, sizeof (t)); - t.arg = wcb; - rfapiWithdrawTimerEncap (&t); /* frees wcb */ + struct rfapi_withdraw *wcb; + struct thread t; + + /* + * pretend we're an expiring timer + */ + wcb = XCALLOC(MTYPE_RFAPI_WITHDRAW, sizeof(struct rfapi_withdraw)); + wcb->info = bi; + wcb->node = rn; + wcb->import_table = it; + memset(&t, 0, sizeof(t)); + t.arg = wcb; + rfapiWithdrawTimerEncap(&t); /* frees wcb */ } -static int -rfapiGetNexthop (struct attr *attr, struct prefix *prefix) +static int rfapiGetNexthop(struct attr *attr, struct prefix *prefix) { - switch (BGP_MP_NEXTHOP_FAMILY (attr->mp_nexthop_len)) - { - case AF_INET: - prefix->family = AF_INET; - prefix->prefixlen = 32; - prefix->u.prefix4 = attr->mp_nexthop_global_in; - break; - case AF_INET6: - prefix->family = AF_INET6; - prefix->prefixlen = 128; - prefix->u.prefix6 = attr->mp_nexthop_global; - break; - default: - vnc_zlog_debug_verbose ("%s: unknown attr->mp_nexthop_len %d", __func__, - attr->mp_nexthop_len); - return EINVAL; - } - return 0; + switch (BGP_MP_NEXTHOP_FAMILY(attr->mp_nexthop_len)) { + case AF_INET: + prefix->family = AF_INET; + prefix->prefixlen = 32; + prefix->u.prefix4 = attr->mp_nexthop_global_in; + break; + case AF_INET6: + prefix->family = AF_INET6; + prefix->prefixlen = 128; + prefix->u.prefix6 = attr->mp_nexthop_global; + break; + default: + vnc_zlog_debug_verbose("%s: unknown attr->mp_nexthop_len %d", + __func__, attr->mp_nexthop_len); + return EINVAL; + } + return 0; } -/* +/* * import a bgp_info if its route target list intersects with the * import table's route target list */ -static void -rfapiBgpInfoFilteredImportEncap ( - struct rfapi_import_table *import_table, - int action, - struct peer *peer, - void *rfd, /* set for looped back routes */ - struct prefix *p, - struct prefix *aux_prefix, /* Unused for encap routes */ - afi_t afi, - struct prefix_rd *prd, - struct attr *attr, /* part of bgp_info */ - u_char type, /* part of bgp_info */ - u_char sub_type, /* part of bgp_info */ - uint32_t *label) /* part of bgp_info */ +static void rfapiBgpInfoFilteredImportEncap( + struct rfapi_import_table *import_table, int action, struct peer *peer, + void *rfd, /* set for looped back routes */ + struct prefix *p, + struct prefix *aux_prefix, /* Unused for encap routes */ + afi_t afi, struct prefix_rd *prd, + struct attr *attr, /* part of bgp_info */ + u_char type, /* part of bgp_info */ + u_char sub_type, /* part of bgp_info */ + uint32_t *label) /* part of bgp_info */ { - struct route_table *rt = NULL; - struct route_node *rn; - struct bgp_info *info_new; - struct bgp_info *bi; - struct bgp_info *next; - char buf[BUFSIZ]; - - struct prefix p_firstbi_old; - struct prefix p_firstbi_new; - int replacing = 0; - const char *action_str = NULL; - struct prefix un_prefix; - - struct bgp *bgp; - bgp = bgp_get_default (); /* assume 1 instance for now */ - - switch (action) - { - case FIF_ACTION_UPDATE: - action_str = "update"; - break; - case FIF_ACTION_WITHDRAW: - action_str = "withdraw"; - break; - case FIF_ACTION_KILL: - action_str = "kill"; - break; - default: - assert (0); - break; - } - - vnc_zlog_debug_verbose ("%s: entry: %s: prefix %s/%d", __func__, - action_str, - inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen); - - memset (&p_firstbi_old, 0, sizeof (p_firstbi_old)); - memset (&p_firstbi_new, 0, sizeof (p_firstbi_new)); - - if (action == FIF_ACTION_UPDATE) - { - /* - * Compare rt lists. If no intersection, don't import this route - * On a withdraw, peer and RD are sufficient to determine if - * we should act. - */ - if (!attr || !attr->ecommunity) - { - - vnc_zlog_debug_verbose ("%s: attr, extra, or ecommunity missing, not importing", - __func__); - return; - } + struct route_table *rt = NULL; + struct route_node *rn; + struct bgp_info *info_new; + struct bgp_info *bi; + struct bgp_info *next; + char buf[BUFSIZ]; + + struct prefix p_firstbi_old; + struct prefix p_firstbi_new; + int replacing = 0; + const char *action_str = NULL; + struct prefix un_prefix; + + struct bgp *bgp; + bgp = bgp_get_default(); /* assume 1 instance for now */ + + switch (action) { + case FIF_ACTION_UPDATE: + action_str = "update"; + break; + case FIF_ACTION_WITHDRAW: + action_str = "withdraw"; + break; + case FIF_ACTION_KILL: + action_str = "kill"; + break; + default: + assert(0); + break; + } + + vnc_zlog_debug_verbose( + "%s: entry: %s: prefix %s/%d", __func__, action_str, + inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen); + + memset(&p_firstbi_old, 0, sizeof(p_firstbi_old)); + memset(&p_firstbi_new, 0, sizeof(p_firstbi_new)); + + if (action == FIF_ACTION_UPDATE) { + /* + * Compare rt lists. If no intersection, don't import this route + * On a withdraw, peer and RD are sufficient to determine if + * we should act. + */ + if (!attr || !attr->ecommunity) { + + vnc_zlog_debug_verbose( + "%s: attr, extra, or ecommunity missing, not importing", + __func__); + return; + } #if RFAPI_REQUIRE_ENCAP_BEEC - if (!rfapiEcommunitiesMatchBeec (attr->ecommunity)) - { - vnc_zlog_debug_verbose ("%s: it=%p: no match for BGP Encapsulation ecommunity", - __func__, import_table); - return; - } + if (!rfapiEcommunitiesMatchBeec(attr->ecommunity)) { + vnc_zlog_debug_verbose( + "%s: it=%p: no match for BGP Encapsulation ecommunity", + __func__, import_table); + return; + } #endif - if (!rfapiEcommunitiesIntersect (import_table->rt_import_list, - attr->ecommunity)) - { - - vnc_zlog_debug_verbose ("%s: it=%p: no ecommunity intersection", - __func__, import_table); - return; - } - - /* - * Updates must also have a nexthop address - */ - memset (&un_prefix, 0, sizeof (un_prefix)); /* keep valgrind happy */ - if (rfapiGetNexthop (attr, &un_prefix)) - { - vnc_zlog_debug_verbose ("%s: missing nexthop address", __func__); - return; - } - } - - /* - * Figure out which radix tree the route would go into - */ - switch (afi) - { - case AFI_IP: - case AFI_IP6: - rt = import_table->imported_encap[afi]; - break; - - default: - zlog_err ("%s: bad afi %d", __func__, afi); - return; - } - - /* - * route_node_lookup returns a node only if there is at least - * one route attached. - */ - rn = route_node_lookup (rt, p); + if (!rfapiEcommunitiesIntersect(import_table->rt_import_list, + attr->ecommunity)) { + + vnc_zlog_debug_verbose( + "%s: it=%p: no ecommunity intersection", + __func__, import_table); + return; + } + + /* + * Updates must also have a nexthop address + */ + memset(&un_prefix, 0, + sizeof(un_prefix)); /* keep valgrind happy */ + if (rfapiGetNexthop(attr, &un_prefix)) { + vnc_zlog_debug_verbose("%s: missing nexthop address", + __func__); + return; + } + } + + /* + * Figure out which radix tree the route would go into + */ + switch (afi) { + case AFI_IP: + case AFI_IP6: + rt = import_table->imported_encap[afi]; + break; + + default: + zlog_err("%s: bad afi %d", __func__, afi); + return; + } + + /* + * route_node_lookup returns a node only if there is at least + * one route attached. + */ + rn = route_node_lookup(rt, p); #if DEBUG_ENCAP_MONITOR - vnc_zlog_debug_verbose ("%s: initial encap lookup(it=%p) rn=%p", - __func__, import_table, rn); + vnc_zlog_debug_verbose("%s: initial encap lookup(it=%p) rn=%p", + __func__, import_table, rn); #endif - if (rn) - { - - RFAPI_CHECK_REFCOUNT (rn, SAFI_ENCAP, 1); - route_unlock_node (rn); /* undo lock in route_node_lookup */ - - - /* - * capture nexthop of first bi - */ - if (rn->info) - { - rfapiNexthop2Prefix (((struct bgp_info *) (rn->info))->attr, - &p_firstbi_old); - } - - for (bi = rn->info; bi; bi = bi->next) - { - - /* - * Does this bgp_info refer to the same route - * as we are trying to add? - */ - vnc_zlog_debug_verbose ("%s: comparing BI %p", __func__, bi); - - - /* - * Compare RDs - * - * RD of import table bi is in bi->extra->vnc.import.rd - * RD of info_orig is in prd - */ - if (!bi->extra) - { - vnc_zlog_debug_verbose ("%s: no bi->extra", __func__); - continue; - } - if (prefix_cmp ((struct prefix *) &bi->extra->vnc.import.rd, - (struct prefix *) prd)) - { - - vnc_zlog_debug_verbose ("%s: prd does not match", __func__); - continue; - } - - /* - * Compare peers - */ - if (bi->peer != peer) - { - vnc_zlog_debug_verbose ("%s: peer does not match", __func__); - continue; - } - - vnc_zlog_debug_verbose ("%s: found matching bi", __func__); - - /* Same route. Delete this bi, replace with new one */ - - if (action == FIF_ACTION_WITHDRAW) - { - - vnc_zlog_debug_verbose ("%s: withdrawing at prefix %s/%d", - __func__, - inet_ntop (rn->p.family, &rn->p.u.prefix, buf, - BUFSIZ), rn->p.prefixlen); - - rfapiBiStartWithdrawTimer (import_table, rn, bi, - afi, SAFI_ENCAP, - rfapiWithdrawTimerEncap); - - } - else - { - vnc_zlog_debug_verbose ("%s: %s at prefix %s/%d", - __func__, - ((action == - FIF_ACTION_KILL) ? "killing" : "replacing"), - inet_ntop (rn->p.family, &rn->p.u.prefix, buf, - BUFSIZ), rn->p.prefixlen); - - /* - * If this route is waiting to be deleted because of - * a previous withdraw, we must cancel its timer. - */ - if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED) - && bi->extra->vnc.import.timer) - { - - struct thread *t = - (struct thread *) bi->extra->vnc.import.timer; - struct rfapi_withdraw *wcb = t->arg; - - XFREE (MTYPE_RFAPI_WITHDRAW, wcb); - thread_cancel (t); - } - - if (action == FIF_ACTION_UPDATE) - { - rfapiBgpInfoDetach (rn, bi); - rfapiBgpInfoFree (bi); - replacing = 1; - } - else - { - /* - * Kill: do export stuff when removing bi - */ - struct rfapi_withdraw *wcb; - struct thread t; - - /* - * pretend we're an expiring timer - */ - wcb = - XCALLOC (MTYPE_RFAPI_WITHDRAW, - sizeof (struct rfapi_withdraw)); - wcb->info = bi; - wcb->node = rn; - wcb->import_table = import_table; - memset (&t, 0, sizeof (t)); - t.arg = wcb; - rfapiWithdrawTimerEncap (&t); /* frees wcb */ - } - } - - break; - } - } - - if (rn) - RFAPI_CHECK_REFCOUNT (rn, SAFI_ENCAP, replacing ? 1 : 0); - - if (action == FIF_ACTION_WITHDRAW || action == FIF_ACTION_KILL) - return; - - info_new = rfapiBgpInfoCreate (attr, peer, rfd, prd, type, sub_type, NULL); - - if (rn) - { - if (!replacing) - route_lock_node (rn); /* incr ref count for new BI */ - } - else - { - rn = route_node_get (rt, p); - } - - vnc_zlog_debug_verbose ("%s: (afi=%d, rn=%p) inserting at prefix %s/%d", - __func__, - afi, - rn, - inet_ntop (rn->p.family, &rn->p.u.prefix, buf, BUFSIZ), - rn->p.prefixlen); - - rfapiBgpInfoAttachSorted (rn, info_new, afi, SAFI_ENCAP); - - /* - * Delete holddown routes from same NVE. See details in - * rfapiBgpInfoFilteredImportVPN() - */ - for (bi = info_new->next; bi; bi = next) - { - - struct prefix pfx_un; - int un_match = 0; - - next = bi->next; - if (!CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)) - continue; - - /* - * We already match the VN address (it is the prefix - * of the route node) - */ - - if (!rfapiGetNexthop (bi->attr, &pfx_un) && - prefix_same (&pfx_un, &un_prefix)) - { - - un_match = 1; - } - - if (!un_match) - continue; - - vnc_zlog_debug_verbose ("%s: removing holddown bi matching NVE of new route", - __func__); - if (bi->extra->vnc.import.timer) - { - struct thread *t = (struct thread *) bi->extra->vnc.import.timer; - struct rfapi_withdraw *wcb = t->arg; - - XFREE (MTYPE_RFAPI_WITHDRAW, wcb); - thread_cancel (t); - } - rfapiExpireEncapNow (import_table, rn, bi); - } - - rfapiNexthop2Prefix (((struct bgp_info *) (rn->info))->attr, - &p_firstbi_new); - - /* - * If the nexthop address of the selected Encap route (i.e., - * the UN address) has changed, then we must update the VPN - * routes that refer to this Encap route and possibly force - * rfapi callbacks. - */ - if (rfapiAttrNexthopAddrDifferent (&p_firstbi_old, &p_firstbi_new)) - { - - struct rfapi_monitor_encap *m; - struct rfapi_monitor_encap *mnext; - - struct route_node *referenced_vpn_prefix; - - /* - * Optimized approach: build radix tree on the fly to - * hold list of VPN nodes referenced by the ENCAP monitors - * - * The nodes in this table correspond to prefixes of VPN routes. - * The "info" pointer of the node points to a chain of - * struct rfapi_monitor_encap, each of which refers to a - * specific VPN node. - */ - struct route_table *referenced_vpn_table; - - referenced_vpn_table = route_table_init (); - assert (referenced_vpn_table); - - /* - * iterate over the set of monitors at this ENCAP node. - */ + if (rn) { + + RFAPI_CHECK_REFCOUNT(rn, SAFI_ENCAP, 1); + route_unlock_node(rn); /* undo lock in route_node_lookup */ + + + /* + * capture nexthop of first bi + */ + if (rn->info) { + rfapiNexthop2Prefix( + ((struct bgp_info *)(rn->info))->attr, + &p_firstbi_old); + } + + for (bi = rn->info; bi; bi = bi->next) { + + /* + * Does this bgp_info refer to the same route + * as we are trying to add? + */ + vnc_zlog_debug_verbose("%s: comparing BI %p", __func__, + bi); + + + /* + * Compare RDs + * + * RD of import table bi is in bi->extra->vnc.import.rd + * RD of info_orig is in prd + */ + if (!bi->extra) { + vnc_zlog_debug_verbose("%s: no bi->extra", + __func__); + continue; + } + if (prefix_cmp( + (struct prefix *)&bi->extra->vnc.import.rd, + (struct prefix *)prd)) { + + vnc_zlog_debug_verbose("%s: prd does not match", + __func__); + continue; + } + + /* + * Compare peers + */ + if (bi->peer != peer) { + vnc_zlog_debug_verbose( + "%s: peer does not match", __func__); + continue; + } + + vnc_zlog_debug_verbose("%s: found matching bi", + __func__); + + /* Same route. Delete this bi, replace with new one */ + + if (action == FIF_ACTION_WITHDRAW) { + + vnc_zlog_debug_verbose( + "%s: withdrawing at prefix %s/%d", + __func__, + inet_ntop(rn->p.family, &rn->p.u.prefix, + buf, BUFSIZ), + rn->p.prefixlen); + + rfapiBiStartWithdrawTimer( + import_table, rn, bi, afi, SAFI_ENCAP, + rfapiWithdrawTimerEncap); + + } else { + vnc_zlog_debug_verbose( + "%s: %s at prefix %s/%d", __func__, + ((action == FIF_ACTION_KILL) + ? "killing" + : "replacing"), + inet_ntop(rn->p.family, &rn->p.u.prefix, + buf, BUFSIZ), + rn->p.prefixlen); + + /* + * If this route is waiting to be deleted + * because of + * a previous withdraw, we must cancel its + * timer. + */ + if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED) + && bi->extra->vnc.import.timer) { + + struct thread *t = + (struct thread *)bi->extra->vnc + .import.timer; + struct rfapi_withdraw *wcb = t->arg; + + XFREE(MTYPE_RFAPI_WITHDRAW, wcb); + thread_cancel(t); + } + + if (action == FIF_ACTION_UPDATE) { + rfapiBgpInfoDetach(rn, bi); + rfapiBgpInfoFree(bi); + replacing = 1; + } else { + /* + * Kill: do export stuff when removing + * bi + */ + struct rfapi_withdraw *wcb; + struct thread t; + + /* + * pretend we're an expiring timer + */ + wcb = XCALLOC( + MTYPE_RFAPI_WITHDRAW, + sizeof(struct rfapi_withdraw)); + wcb->info = bi; + wcb->node = rn; + wcb->import_table = import_table; + memset(&t, 0, sizeof(t)); + t.arg = wcb; + rfapiWithdrawTimerEncap( + &t); /* frees wcb */ + } + } + + break; + } + } + + if (rn) + RFAPI_CHECK_REFCOUNT(rn, SAFI_ENCAP, replacing ? 1 : 0); + + if (action == FIF_ACTION_WITHDRAW || action == FIF_ACTION_KILL) + return; + + info_new = + rfapiBgpInfoCreate(attr, peer, rfd, prd, type, sub_type, NULL); + + if (rn) { + if (!replacing) + route_lock_node(rn); /* incr ref count for new BI */ + } else { + rn = route_node_get(rt, p); + } + + vnc_zlog_debug_verbose( + "%s: (afi=%d, rn=%p) inserting at prefix %s/%d", __func__, afi, + rn, inet_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ), + rn->p.prefixlen); + + rfapiBgpInfoAttachSorted(rn, info_new, afi, SAFI_ENCAP); + + /* + * Delete holddown routes from same NVE. See details in + * rfapiBgpInfoFilteredImportVPN() + */ + for (bi = info_new->next; bi; bi = next) { + + struct prefix pfx_un; + int un_match = 0; + + next = bi->next; + if (!CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + continue; + + /* + * We already match the VN address (it is the prefix + * of the route node) + */ + + if (!rfapiGetNexthop(bi->attr, &pfx_un) + && prefix_same(&pfx_un, &un_prefix)) { + + un_match = 1; + } + + if (!un_match) + continue; + + vnc_zlog_debug_verbose( + "%s: removing holddown bi matching NVE of new route", + __func__); + if (bi->extra->vnc.import.timer) { + struct thread *t = + (struct thread *)bi->extra->vnc.import.timer; + struct rfapi_withdraw *wcb = t->arg; + + XFREE(MTYPE_RFAPI_WITHDRAW, wcb); + thread_cancel(t); + } + rfapiExpireEncapNow(import_table, rn, bi); + } + + rfapiNexthop2Prefix(((struct bgp_info *)(rn->info))->attr, + &p_firstbi_new); + + /* + * If the nexthop address of the selected Encap route (i.e., + * the UN address) has changed, then we must update the VPN + * routes that refer to this Encap route and possibly force + * rfapi callbacks. + */ + if (rfapiAttrNexthopAddrDifferent(&p_firstbi_old, &p_firstbi_new)) { + + struct rfapi_monitor_encap *m; + struct rfapi_monitor_encap *mnext; + + struct route_node *referenced_vpn_prefix; + + /* + * Optimized approach: build radix tree on the fly to + * hold list of VPN nodes referenced by the ENCAP monitors + * + * The nodes in this table correspond to prefixes of VPN routes. + * The "info" pointer of the node points to a chain of + * struct rfapi_monitor_encap, each of which refers to a + * specific VPN node. + */ + struct route_table *referenced_vpn_table; + + referenced_vpn_table = route_table_init(); + assert(referenced_vpn_table); + +/* + * iterate over the set of monitors at this ENCAP node. + */ #if DEBUG_ENCAP_MONITOR - vnc_zlog_debug_verbose ("%s: examining monitors at rn=%p", __func__, rn); + vnc_zlog_debug_verbose("%s: examining monitors at rn=%p", + __func__, rn); #endif - for (m = RFAPI_MONITOR_ENCAP (rn); m; m = m->next) - { - - /* - * For each referenced bi/route, copy the ENCAP route's - * nexthop to the VPN route's cached UN address field and set - * the address family of the cached UN address field. - */ - rfapiCopyUnEncap2VPN (info_new, m->bi); - if (!CHECK_FLAG (m->bi->flags, BGP_INFO_VALID)) - { - SET_FLAG (m->bi->flags, BGP_INFO_VALID); - if (VALID_INTERIOR_TYPE (m->bi->type)) - RFAPI_MONITOR_EXTERIOR (m->node)->valid_interior_count++; - vnc_import_bgp_exterior_add_route_interior (bgp, - import_table, - m->node, m->bi); - } - - /* - * Build a list of unique VPN nodes referenced by these monitors - * - * There could be more than one VPN node here with a given - * prefix. Those are currently in an unsorted linear list - * per prefix. - */ - - referenced_vpn_prefix = - route_node_get (referenced_vpn_table, &m->node->p); - assert (referenced_vpn_prefix); - for (mnext = referenced_vpn_prefix->info; mnext; - mnext = mnext->next) - { - - if (mnext->node == m->node) - break; - } - - if (mnext) - { - /* - * already have an entry for this VPN node - */ - route_unlock_node (referenced_vpn_prefix); - } - else - { - mnext = XCALLOC (MTYPE_RFAPI_MONITOR_ENCAP, - sizeof (struct rfapi_monitor_encap)); - assert (mnext); - mnext->node = m->node; - mnext->next = referenced_vpn_prefix->info; - referenced_vpn_prefix->info = mnext; - } - - } - - /* - * for each VPN node referenced in the ENCAP monitors: - */ - for (referenced_vpn_prefix = route_top (referenced_vpn_table); - referenced_vpn_prefix; - referenced_vpn_prefix = route_next (referenced_vpn_prefix)) - { - - while ((m = referenced_vpn_prefix->info)) - { - - struct route_node *n; - - rfapiMonitorMoveLonger (m->node); - for (n = m->node; n; n = n->parent) - { - //rfapiDoRouteCallback(import_table, n, NULL); - } - rfapiMonitorItNodeChanged (import_table, m->node, NULL); - - referenced_vpn_prefix->info = m->next; - route_unlock_node (referenced_vpn_prefix); - XFREE (MTYPE_RFAPI_MONITOR_ENCAP, m); - } - - } - route_table_finish (referenced_vpn_table); - } - - RFAPI_CHECK_REFCOUNT (rn, SAFI_ENCAP, 0); + for (m = RFAPI_MONITOR_ENCAP(rn); m; m = m->next) { + + /* + * For each referenced bi/route, copy the ENCAP route's + * nexthop to the VPN route's cached UN address field + * and set + * the address family of the cached UN address field. + */ + rfapiCopyUnEncap2VPN(info_new, m->bi); + if (!CHECK_FLAG(m->bi->flags, BGP_INFO_VALID)) { + SET_FLAG(m->bi->flags, BGP_INFO_VALID); + if (VALID_INTERIOR_TYPE(m->bi->type)) + RFAPI_MONITOR_EXTERIOR(m->node) + ->valid_interior_count++; + vnc_import_bgp_exterior_add_route_interior( + bgp, import_table, m->node, m->bi); + } + + /* + * Build a list of unique VPN nodes referenced by these + * monitors + * + * There could be more than one VPN node here with a + * given + * prefix. Those are currently in an unsorted linear + * list + * per prefix. + */ + + referenced_vpn_prefix = route_node_get( + referenced_vpn_table, &m->node->p); + assert(referenced_vpn_prefix); + for (mnext = referenced_vpn_prefix->info; mnext; + mnext = mnext->next) { + + if (mnext->node == m->node) + break; + } + + if (mnext) { + /* + * already have an entry for this VPN node + */ + route_unlock_node(referenced_vpn_prefix); + } else { + mnext = XCALLOC( + MTYPE_RFAPI_MONITOR_ENCAP, + sizeof(struct rfapi_monitor_encap)); + assert(mnext); + mnext->node = m->node; + mnext->next = referenced_vpn_prefix->info; + referenced_vpn_prefix->info = mnext; + } + } + + /* + * for each VPN node referenced in the ENCAP monitors: + */ + for (referenced_vpn_prefix = route_top(referenced_vpn_table); + referenced_vpn_prefix; referenced_vpn_prefix = route_next( + referenced_vpn_prefix)) { + + while ((m = referenced_vpn_prefix->info)) { + + struct route_node *n; + + rfapiMonitorMoveLonger(m->node); + for (n = m->node; n; n = n->parent) { + // rfapiDoRouteCallback(import_table, n, + // NULL); + } + rfapiMonitorItNodeChanged(import_table, m->node, + NULL); + + referenced_vpn_prefix->info = m->next; + route_unlock_node(referenced_vpn_prefix); + XFREE(MTYPE_RFAPI_MONITOR_ENCAP, m); + } + } + route_table_finish(referenced_vpn_table); + } + + RFAPI_CHECK_REFCOUNT(rn, SAFI_ENCAP, 0); } -static void -rfapiExpireVpnNow ( - struct rfapi_import_table *it, - struct route_node *rn, - struct bgp_info *bi, - int lockoffset) +static void rfapiExpireVpnNow(struct rfapi_import_table *it, + struct route_node *rn, struct bgp_info *bi, + int lockoffset) { - struct rfapi_withdraw *wcb; - struct thread t; - - /* - * pretend we're an expiring timer - */ - wcb = XCALLOC (MTYPE_RFAPI_WITHDRAW, sizeof (struct rfapi_withdraw)); - wcb->info = bi; - wcb->node = rn; - wcb->import_table = it; - wcb->lockoffset = lockoffset; - memset (&t, 0, sizeof (t)); - t.arg = wcb; - rfapiWithdrawTimerVPN (&t); /* frees wcb */ + struct rfapi_withdraw *wcb; + struct thread t; + + /* + * pretend we're an expiring timer + */ + wcb = XCALLOC(MTYPE_RFAPI_WITHDRAW, sizeof(struct rfapi_withdraw)); + wcb->info = bi; + wcb->node = rn; + wcb->import_table = it; + wcb->lockoffset = lockoffset; + memset(&t, 0, sizeof(t)); + t.arg = wcb; + rfapiWithdrawTimerVPN(&t); /* frees wcb */ } -/* +/* * import a bgp_info if its route target list intersects with the * import table's route target list */ -void -rfapiBgpInfoFilteredImportVPN ( - struct rfapi_import_table *import_table, - int action, - struct peer *peer, - void *rfd, /* set for looped back routes */ - struct prefix *p, - struct prefix *aux_prefix, /* AFI_L2VPN: optional IP */ - afi_t afi, - struct prefix_rd *prd, - struct attr *attr, /* part of bgp_info */ - u_char type, /* part of bgp_info */ - u_char sub_type, /* part of bgp_info */ - uint32_t *label) /* part of bgp_info */ +void rfapiBgpInfoFilteredImportVPN( + struct rfapi_import_table *import_table, int action, struct peer *peer, + void *rfd, /* set for looped back routes */ + struct prefix *p, + struct prefix *aux_prefix, /* AFI_L2VPN: optional IP */ + afi_t afi, struct prefix_rd *prd, + struct attr *attr, /* part of bgp_info */ + u_char type, /* part of bgp_info */ + u_char sub_type, /* part of bgp_info */ + uint32_t *label) /* part of bgp_info */ { - struct route_table *rt = NULL; - struct route_node *rn; - struct route_node *n; - struct bgp_info *info_new; - struct bgp_info *bi; - struct bgp_info *next; - char buf[BUFSIZ]; - struct prefix vn_prefix; - struct prefix un_prefix; - int un_prefix_valid = 0; - struct route_node *ern; - int replacing = 0; - int original_had_routes = 0; - struct prefix original_nexthop; - const char *action_str = NULL; - int is_it_ce = 0; - - struct bgp *bgp; - bgp = bgp_get_default (); /* assume 1 instance for now */ - - switch (action) - { - case FIF_ACTION_UPDATE: - action_str = "update"; - break; - case FIF_ACTION_WITHDRAW: - action_str = "withdraw"; - break; - case FIF_ACTION_KILL: - action_str = "kill"; - break; - default: - assert (0); - break; - } - - if (import_table == bgp->rfapi->it_ce) - is_it_ce = 1; - - vnc_zlog_debug_verbose ("%s: entry: %s%s: prefix %s/%d: it %p, afi %s", __func__, - (is_it_ce ? "CE-IT " : ""), - action_str, - rfapi_ntop (p->family, &p->u.prefix, buf, BUFSIZ), - p->prefixlen, import_table, afi2str (afi)); - - VNC_ITRCCK; - - /* - * Compare rt lists. If no intersection, don't import this route - * On a withdraw, peer and RD are sufficient to determine if - * we should act. - */ - if (action == FIF_ACTION_UPDATE) - { - if (!attr || !attr->ecommunity) - { - - vnc_zlog_debug_verbose ("%s: attr, extra, or ecommunity missing, not importing", - __func__); - return; - } - if ((import_table != bgp->rfapi->it_ce) && - !rfapiEcommunitiesIntersect (import_table->rt_import_list, - attr->ecommunity)) - { - - vnc_zlog_debug_verbose ("%s: it=%p: no ecommunity intersection", - __func__, import_table); - return; - } - - memset (&vn_prefix, 0, sizeof (vn_prefix)); /* keep valgrind happy */ - if (rfapiGetNexthop (attr, &vn_prefix)) - { - /* missing nexthop address would be a bad, bad thing */ - vnc_zlog_debug_verbose ("%s: missing nexthop", __func__); - return; - } - } - - /* - * Figure out which radix tree the route would go into - */ - switch (afi) - { - case AFI_IP: - case AFI_IP6: - case AFI_L2VPN: - rt = import_table->imported_vpn[afi]; - break; - - default: - zlog_err ("%s: bad afi %d", __func__, afi); - return; - } - - /* clear it */ - memset (&original_nexthop, 0, sizeof (original_nexthop)); - - /* - * route_node_lookup returns a node only if there is at least - * one route attached. - */ - rn = route_node_lookup (rt, p); - - vnc_zlog_debug_verbose ("%s: rn=%p", __func__, rn); - - if (rn) - { - - RFAPI_CHECK_REFCOUNT (rn, SAFI_MPLS_VPN, 1); - route_unlock_node (rn); /* undo lock in route_node_lookup */ - - if (rn->info) - original_had_routes = 1; - - if (VNC_DEBUG(VERBOSE)) - { - vnc_zlog_debug_verbose ("%s: showing IT node on entry", __func__); - rfapiShowItNode (NULL, rn); /* debug */ - } - - /* - * Look for same route (will have same RD and peer) - */ - bi = rfapiItBiIndexSearch (rn, prd, peer, aux_prefix); - - if (bi) - { - - /* - * This was an old test when we iterated over the - * BIs linearly. Since we're now looking up with - * RD and peer, comparing types should not be - * needed. Changed to assertion. - * - * Compare types. Doing so prevents a RFP-originated - * route from matching an imported route, for example. - */ - assert (bi->type == type); - - vnc_zlog_debug_verbose ("%s: found matching bi", __func__); - - /* - * In the special CE table, withdrawals occur without holddown - */ - if (import_table == bgp->rfapi->it_ce) - { - vnc_direct_bgp_del_route_ce (bgp, rn, bi); - if (action == FIF_ACTION_WITHDRAW) - action = FIF_ACTION_KILL; - } - - if (action == FIF_ACTION_WITHDRAW) - { - - int washolddown = CHECK_FLAG (bi->flags, BGP_INFO_REMOVED); - - vnc_zlog_debug_verbose ("%s: withdrawing at prefix %s/%d%s", - __func__, - rfapi_ntop (rn->p.family, &rn->p.u.prefix, buf, - BUFSIZ), rn->p.prefixlen, - (washolddown ? " (already being withdrawn)" : "")); - - VNC_ITRCCK; - if (!washolddown) - { - rfapiBiStartWithdrawTimer (import_table, rn, bi, - afi, SAFI_MPLS_VPN, - rfapiWithdrawTimerVPN); - - RFAPI_UPDATE_ITABLE_COUNT (bi, import_table, afi, -1); - import_table->holddown_count[afi] += 1; - } - VNC_ITRCCK; - } - else - { - vnc_zlog_debug_verbose ("%s: %s at prefix %s/%d", - __func__, - ((action == - FIF_ACTION_KILL) ? "killing" : "replacing"), - rfapi_ntop (rn->p.family, &rn->p.u.prefix, buf, - BUFSIZ), rn->p.prefixlen); - - /* - * If this route is waiting to be deleted because of - * a previous withdraw, we must cancel its timer. - */ - if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED) && - bi->extra->vnc.import.timer) - { - - struct thread *t = - (struct thread *) bi->extra->vnc.import.timer; - struct rfapi_withdraw *wcb = t->arg; - - XFREE (MTYPE_RFAPI_WITHDRAW, wcb); - thread_cancel (t); - - import_table->holddown_count[afi] -= 1; - RFAPI_UPDATE_ITABLE_COUNT (bi, import_table, afi, 1); - } - /* - * decrement remote count (if route is remote) because - * we are going to remove it below - */ - RFAPI_UPDATE_ITABLE_COUNT (bi, import_table, afi, -1); - if (action == FIF_ACTION_UPDATE) - { - replacing = 1; - - /* - * make copy of original nexthop so we can see if it changed - */ - rfapiGetNexthop (bi->attr, &original_nexthop); - - /* - * remove bi without doing any export processing - */ - if (CHECK_FLAG (bi->flags, BGP_INFO_VALID) - && VALID_INTERIOR_TYPE (bi->type)) - RFAPI_MONITOR_EXTERIOR (rn)->valid_interior_count--; - rfapiItBiIndexDel (rn, bi); - rfapiBgpInfoDetach (rn, bi); - rfapiMonitorEncapDelete (bi); - vnc_import_bgp_exterior_del_route_interior (bgp, - import_table, - rn, bi); - rfapiBgpInfoFree (bi); - } - else - { - /* Kill */ - /* - * remove bi and do export processing - */ - import_table->holddown_count[afi] += 1; - rfapiExpireVpnNow (import_table, rn, bi, 0); - } - - } - } - - } - - if (rn) - RFAPI_CHECK_REFCOUNT (rn, SAFI_MPLS_VPN, replacing ? 1 : 0); - - if (action == FIF_ACTION_WITHDRAW || action == FIF_ACTION_KILL) - { - VNC_ITRCCK; - return; - } - - info_new = rfapiBgpInfoCreate (attr, peer, rfd, prd, type, sub_type, label); - - /* - * lookup un address in encap table - */ - ern = route_node_match (import_table->imported_encap[afi], &vn_prefix); - if (ern) - { - rfapiCopyUnEncap2VPN (ern->info, info_new); - route_unlock_node (ern); /* undo lock in route_note_match */ - } - else - { - char buf[BUFSIZ]; - prefix2str (&vn_prefix, buf, sizeof (buf)); - buf[BUFSIZ - 1] = 0; - /* Not a big deal, just means VPN route got here first */ - vnc_zlog_debug_verbose ("%s: no encap route for vn addr %s", __func__, buf); - info_new->extra->vnc.import.un_family = 0; - } - - if (rn) - { - if (!replacing) - route_lock_node (rn); - } - else - { - /* - * No need to increment reference count, so only "get" - * if the node is not there already - */ - rn = route_node_get (rt, p); - } - - /* - * For ethernet routes, if there is an accompanying IP address, - * save it in the bi - */ - if ((AFI_L2VPN == afi) && aux_prefix) - { - - vnc_zlog_debug_verbose ("%s: setting BI's aux_prefix", __func__); - info_new->extra->vnc.import.aux_prefix = *aux_prefix; - } - - vnc_zlog_debug_verbose ("%s: inserting bi %p at prefix %s/%d #%d", - __func__, - info_new, - rfapi_ntop (rn->p.family, &rn->p.u.prefix, buf, BUFSIZ), - rn->p.prefixlen, rn->lock); - - rfapiBgpInfoAttachSorted (rn, info_new, afi, SAFI_MPLS_VPN); - rfapiItBiIndexAdd (rn, info_new); - if (!rfapiGetUnAddrOfVpnBi (info_new, NULL)) - { - if (VALID_INTERIOR_TYPE (info_new->type)) - RFAPI_MONITOR_EXTERIOR (rn)->valid_interior_count++; - SET_FLAG (info_new->flags, BGP_INFO_VALID); - } - RFAPI_UPDATE_ITABLE_COUNT (info_new, import_table, afi, 1); - vnc_import_bgp_exterior_add_route_interior (bgp, import_table, rn, - info_new); - - if (import_table == bgp->rfapi->it_ce) - vnc_direct_bgp_add_route_ce (bgp, rn, info_new); - - if (VNC_DEBUG(VERBOSE)) - { - vnc_zlog_debug_verbose ("%s: showing IT node", __func__); - rfapiShowItNode (NULL, rn); /* debug */ - } - - rfapiMonitorEncapAdd (import_table, &vn_prefix, rn, info_new); - - if (!rfapiGetUnAddrOfVpnBi (info_new, &un_prefix)) - { - - /* - * if we have a valid UN address (either via Encap route - * or via tunnel attribute), then we should attempt - * to move any monitors at less-specific nodes to this node - */ - rfapiMonitorMoveLonger (rn); - - un_prefix_valid = 1; - - } - - /* - * 101129 Enhancement: if we add a route (implication: it is not - * in holddown), delete all other routes from this nve at this - * node that are in holddown, regardless of peer. - * - * Reasons it's OK to do that: - * - * - if the holddown route being deleted originally came from BGP VPN, - * it is already gone from BGP (implication of holddown), so there - * won't be any added inconsistency with the BGP RIB. - * - * - once a fresh route is added at a prefix, any routes in holddown - * at that prefix will not show up in RFP responses, so deleting - * the holddown routes won't affect the contents of responses. - * - * - lifetimes are supposed to be consistent, so there should not - * be a case where the fresh route has a shorter lifetime than - * the holddown route, so we don't expect the fresh route to - * disappear and complete its holddown time before the existing - * holddown routes time out. Therefore, we won't have a situation - * where we expect the existing holddown routes to be hidden and - * then to reappear sometime later (as holddown routes) in a - * RFP response. - * - * Among other things, this would enable us to skirt the problem - * of local holddown routes that refer to NVE descriptors that - * have already been closed (if the same NVE triggers a subsequent - * rfapi_open(), the new peer is different and doesn't match the - * peer of the holddown route, so the stale holddown route still - * hangs around until it times out instead of just being replaced - * by the fresh route). - */ - /* - * We know that the new bi will have been inserted before any routes - * in holddown, so we can skip any that came before it - */ - for (bi = info_new->next; bi; bi = next) - { - - struct prefix pfx_vn; - struct prefix pfx_un; - int un_match = 0; - int remote_peer_match = 0; - - next = bi->next; - - /* - * Must be holddown - */ - if (!CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)) - continue; - - /* - * Must match VN address (nexthop of VPN route) - */ - if (rfapiGetNexthop (bi->attr, &pfx_vn)) - continue; - if (!prefix_same (&pfx_vn, &vn_prefix)) - continue; - - if (un_prefix_valid && /* new route UN addr */ - !rfapiGetUnAddrOfVpnBi (bi, &pfx_un) && /* old route UN addr */ - prefix_same (&pfx_un, &un_prefix)) - { /* compare */ - un_match = 1; - } - if (!RFAPI_LOCAL_BI (bi) && !RFAPI_LOCAL_BI (info_new) && - sockunion_same (&bi->peer->su, &info_new->peer->su)) - { - /* old & new are both remote, same peer */ - remote_peer_match = 1; - } - - if (!un_match & !remote_peer_match) - continue; - - vnc_zlog_debug_verbose ("%s: removing holddown bi matching NVE of new route", - __func__); - if (bi->extra->vnc.import.timer) - { - struct thread *t = (struct thread *) bi->extra->vnc.import.timer; - struct rfapi_withdraw *wcb = t->arg; - - XFREE (MTYPE_RFAPI_WITHDRAW, wcb); - thread_cancel (t); - } - rfapiExpireVpnNow (import_table, rn, bi, 0); - } - - if (!original_had_routes) - { - /* - * We went from 0 usable routes to 1 usable route. Perform the - * "Adding a Route" export process. - */ - vnc_direct_bgp_add_prefix (bgp, import_table, rn); - vnc_zebra_add_prefix (bgp, import_table, rn); - } - else - { - /* - * Check for nexthop change event - * Note: the prefix_same() test below detects two situations: - * 1. route is replaced, new route has different nexthop - * 2. new route is added (original_nexthop is 0) - */ - struct prefix new_nexthop; - - rfapiGetNexthop (attr, &new_nexthop); - if (!prefix_same (&original_nexthop, &new_nexthop)) - { - /* - * nexthop change event - * vnc_direct_bgp_add_prefix() will recompute VN addr ecommunity - */ - vnc_direct_bgp_add_prefix (bgp, import_table, rn); - } - } - - if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)) - { - for (n = rn; n; n = n->parent) - { - //rfapiDoRouteCallback(import_table, n, NULL); - } - rfapiMonitorItNodeChanged (import_table, rn, NULL); - } - RFAPI_CHECK_REFCOUNT (rn, SAFI_MPLS_VPN, 0); - VNC_ITRCCK; + struct route_table *rt = NULL; + struct route_node *rn; + struct route_node *n; + struct bgp_info *info_new; + struct bgp_info *bi; + struct bgp_info *next; + char buf[BUFSIZ]; + struct prefix vn_prefix; + struct prefix un_prefix; + int un_prefix_valid = 0; + struct route_node *ern; + int replacing = 0; + int original_had_routes = 0; + struct prefix original_nexthop; + const char *action_str = NULL; + int is_it_ce = 0; + + struct bgp *bgp; + bgp = bgp_get_default(); /* assume 1 instance for now */ + + switch (action) { + case FIF_ACTION_UPDATE: + action_str = "update"; + break; + case FIF_ACTION_WITHDRAW: + action_str = "withdraw"; + break; + case FIF_ACTION_KILL: + action_str = "kill"; + break; + default: + assert(0); + break; + } + + if (import_table == bgp->rfapi->it_ce) + is_it_ce = 1; + + vnc_zlog_debug_verbose("%s: entry: %s%s: prefix %s/%d: it %p, afi %s", + __func__, (is_it_ce ? "CE-IT " : ""), action_str, + rfapi_ntop(p->family, &p->u.prefix, buf, BUFSIZ), + p->prefixlen, import_table, afi2str(afi)); + + VNC_ITRCCK; + + /* + * Compare rt lists. If no intersection, don't import this route + * On a withdraw, peer and RD are sufficient to determine if + * we should act. + */ + if (action == FIF_ACTION_UPDATE) { + if (!attr || !attr->ecommunity) { + + vnc_zlog_debug_verbose( + "%s: attr, extra, or ecommunity missing, not importing", + __func__); + return; + } + if ((import_table != bgp->rfapi->it_ce) + && !rfapiEcommunitiesIntersect(import_table->rt_import_list, + attr->ecommunity)) { + + vnc_zlog_debug_verbose( + "%s: it=%p: no ecommunity intersection", + __func__, import_table); + return; + } + + memset(&vn_prefix, 0, + sizeof(vn_prefix)); /* keep valgrind happy */ + if (rfapiGetNexthop(attr, &vn_prefix)) { + /* missing nexthop address would be a bad, bad thing */ + vnc_zlog_debug_verbose("%s: missing nexthop", __func__); + return; + } + } + + /* + * Figure out which radix tree the route would go into + */ + switch (afi) { + case AFI_IP: + case AFI_IP6: + case AFI_L2VPN: + rt = import_table->imported_vpn[afi]; + break; + + default: + zlog_err("%s: bad afi %d", __func__, afi); + return; + } + + /* clear it */ + memset(&original_nexthop, 0, sizeof(original_nexthop)); + + /* + * route_node_lookup returns a node only if there is at least + * one route attached. + */ + rn = route_node_lookup(rt, p); + + vnc_zlog_debug_verbose("%s: rn=%p", __func__, rn); + + if (rn) { + + RFAPI_CHECK_REFCOUNT(rn, SAFI_MPLS_VPN, 1); + route_unlock_node(rn); /* undo lock in route_node_lookup */ + + if (rn->info) + original_had_routes = 1; + + if (VNC_DEBUG(VERBOSE)) { + vnc_zlog_debug_verbose("%s: showing IT node on entry", + __func__); + rfapiShowItNode(NULL, rn); /* debug */ + } + + /* + * Look for same route (will have same RD and peer) + */ + bi = rfapiItBiIndexSearch(rn, prd, peer, aux_prefix); + + if (bi) { + + /* + * This was an old test when we iterated over the + * BIs linearly. Since we're now looking up with + * RD and peer, comparing types should not be + * needed. Changed to assertion. + * + * Compare types. Doing so prevents a RFP-originated + * route from matching an imported route, for example. + */ + assert(bi->type == type); + + vnc_zlog_debug_verbose("%s: found matching bi", + __func__); + + /* + * In the special CE table, withdrawals occur without + * holddown + */ + if (import_table == bgp->rfapi->it_ce) { + vnc_direct_bgp_del_route_ce(bgp, rn, bi); + if (action == FIF_ACTION_WITHDRAW) + action = FIF_ACTION_KILL; + } + + if (action == FIF_ACTION_WITHDRAW) { + + int washolddown = + CHECK_FLAG(bi->flags, BGP_INFO_REMOVED); + + vnc_zlog_debug_verbose( + "%s: withdrawing at prefix %s/%d%s", + __func__, rfapi_ntop(rn->p.family, + &rn->p.u.prefix, + buf, BUFSIZ), + rn->p.prefixlen, + (washolddown + ? " (already being withdrawn)" + : "")); + + VNC_ITRCCK; + if (!washolddown) { + rfapiBiStartWithdrawTimer( + import_table, rn, bi, afi, + SAFI_MPLS_VPN, + rfapiWithdrawTimerVPN); + + RFAPI_UPDATE_ITABLE_COUNT( + bi, import_table, afi, -1); + import_table->holddown_count[afi] += 1; + } + VNC_ITRCCK; + } else { + vnc_zlog_debug_verbose( + "%s: %s at prefix %s/%d", __func__, + ((action == FIF_ACTION_KILL) + ? "killing" + : "replacing"), + rfapi_ntop(rn->p.family, + &rn->p.u.prefix, buf, + BUFSIZ), + rn->p.prefixlen); + + /* + * If this route is waiting to be deleted + * because of + * a previous withdraw, we must cancel its + * timer. + */ + if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED) + && bi->extra->vnc.import.timer) { + + struct thread *t = + (struct thread *)bi->extra->vnc + .import.timer; + struct rfapi_withdraw *wcb = t->arg; + + XFREE(MTYPE_RFAPI_WITHDRAW, wcb); + thread_cancel(t); + + import_table->holddown_count[afi] -= 1; + RFAPI_UPDATE_ITABLE_COUNT( + bi, import_table, afi, 1); + } + /* + * decrement remote count (if route is remote) + * because + * we are going to remove it below + */ + RFAPI_UPDATE_ITABLE_COUNT(bi, import_table, afi, + -1); + if (action == FIF_ACTION_UPDATE) { + replacing = 1; + + /* + * make copy of original nexthop so we + * can see if it changed + */ + rfapiGetNexthop(bi->attr, + &original_nexthop); + + /* + * remove bi without doing any export + * processing + */ + if (CHECK_FLAG(bi->flags, + BGP_INFO_VALID) + && VALID_INTERIOR_TYPE(bi->type)) + RFAPI_MONITOR_EXTERIOR(rn) + ->valid_interior_count--; + rfapiItBiIndexDel(rn, bi); + rfapiBgpInfoDetach(rn, bi); + rfapiMonitorEncapDelete(bi); + vnc_import_bgp_exterior_del_route_interior( + bgp, import_table, rn, bi); + rfapiBgpInfoFree(bi); + } else { + /* Kill */ + /* + * remove bi and do export processing + */ + import_table->holddown_count[afi] += 1; + rfapiExpireVpnNow(import_table, rn, bi, + 0); + } + } + } + } + + if (rn) + RFAPI_CHECK_REFCOUNT(rn, SAFI_MPLS_VPN, replacing ? 1 : 0); + + if (action == FIF_ACTION_WITHDRAW || action == FIF_ACTION_KILL) { + VNC_ITRCCK; + return; + } + + info_new = + rfapiBgpInfoCreate(attr, peer, rfd, prd, type, sub_type, label); + + /* + * lookup un address in encap table + */ + ern = route_node_match(import_table->imported_encap[afi], &vn_prefix); + if (ern) { + rfapiCopyUnEncap2VPN(ern->info, info_new); + route_unlock_node(ern); /* undo lock in route_note_match */ + } else { + char buf[BUFSIZ]; + prefix2str(&vn_prefix, buf, sizeof(buf)); + buf[BUFSIZ - 1] = 0; + /* Not a big deal, just means VPN route got here first */ + vnc_zlog_debug_verbose("%s: no encap route for vn addr %s", + __func__, buf); + info_new->extra->vnc.import.un_family = 0; + } + + if (rn) { + if (!replacing) + route_lock_node(rn); + } else { + /* + * No need to increment reference count, so only "get" + * if the node is not there already + */ + rn = route_node_get(rt, p); + } + + /* + * For ethernet routes, if there is an accompanying IP address, + * save it in the bi + */ + if ((AFI_L2VPN == afi) && aux_prefix) { + + vnc_zlog_debug_verbose("%s: setting BI's aux_prefix", __func__); + info_new->extra->vnc.import.aux_prefix = *aux_prefix; + } + + vnc_zlog_debug_verbose( + "%s: inserting bi %p at prefix %s/%d #%d", __func__, info_new, + rfapi_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ), + rn->p.prefixlen, rn->lock); + + rfapiBgpInfoAttachSorted(rn, info_new, afi, SAFI_MPLS_VPN); + rfapiItBiIndexAdd(rn, info_new); + if (!rfapiGetUnAddrOfVpnBi(info_new, NULL)) { + if (VALID_INTERIOR_TYPE(info_new->type)) + RFAPI_MONITOR_EXTERIOR(rn)->valid_interior_count++; + SET_FLAG(info_new->flags, BGP_INFO_VALID); + } + RFAPI_UPDATE_ITABLE_COUNT(info_new, import_table, afi, 1); + vnc_import_bgp_exterior_add_route_interior(bgp, import_table, rn, + info_new); + + if (import_table == bgp->rfapi->it_ce) + vnc_direct_bgp_add_route_ce(bgp, rn, info_new); + + if (VNC_DEBUG(VERBOSE)) { + vnc_zlog_debug_verbose("%s: showing IT node", __func__); + rfapiShowItNode(NULL, rn); /* debug */ + } + + rfapiMonitorEncapAdd(import_table, &vn_prefix, rn, info_new); + + if (!rfapiGetUnAddrOfVpnBi(info_new, &un_prefix)) { + + /* + * if we have a valid UN address (either via Encap route + * or via tunnel attribute), then we should attempt + * to move any monitors at less-specific nodes to this node + */ + rfapiMonitorMoveLonger(rn); + + un_prefix_valid = 1; + } + + /* + * 101129 Enhancement: if we add a route (implication: it is not + * in holddown), delete all other routes from this nve at this + * node that are in holddown, regardless of peer. + * + * Reasons it's OK to do that: + * + * - if the holddown route being deleted originally came from BGP VPN, + * it is already gone from BGP (implication of holddown), so there + * won't be any added inconsistency with the BGP RIB. + * + * - once a fresh route is added at a prefix, any routes in holddown + * at that prefix will not show up in RFP responses, so deleting + * the holddown routes won't affect the contents of responses. + * + * - lifetimes are supposed to be consistent, so there should not + * be a case where the fresh route has a shorter lifetime than + * the holddown route, so we don't expect the fresh route to + * disappear and complete its holddown time before the existing + * holddown routes time out. Therefore, we won't have a situation + * where we expect the existing holddown routes to be hidden and + * then to reappear sometime later (as holddown routes) in a + * RFP response. + * + * Among other things, this would enable us to skirt the problem + * of local holddown routes that refer to NVE descriptors that + * have already been closed (if the same NVE triggers a subsequent + * rfapi_open(), the new peer is different and doesn't match the + * peer of the holddown route, so the stale holddown route still + * hangs around until it times out instead of just being replaced + * by the fresh route). + */ + /* + * We know that the new bi will have been inserted before any routes + * in holddown, so we can skip any that came before it + */ + for (bi = info_new->next; bi; bi = next) { + + struct prefix pfx_vn; + struct prefix pfx_un; + int un_match = 0; + int remote_peer_match = 0; + + next = bi->next; + + /* + * Must be holddown + */ + if (!CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + continue; + + /* + * Must match VN address (nexthop of VPN route) + */ + if (rfapiGetNexthop(bi->attr, &pfx_vn)) + continue; + if (!prefix_same(&pfx_vn, &vn_prefix)) + continue; + + if (un_prefix_valid && /* new route UN addr */ + !rfapiGetUnAddrOfVpnBi(bi, &pfx_un) + && /* old route UN addr */ + prefix_same(&pfx_un, &un_prefix)) { /* compare */ + un_match = 1; + } + if (!RFAPI_LOCAL_BI(bi) && !RFAPI_LOCAL_BI(info_new) + && sockunion_same(&bi->peer->su, &info_new->peer->su)) { + /* old & new are both remote, same peer */ + remote_peer_match = 1; + } + + if (!un_match & !remote_peer_match) + continue; + + vnc_zlog_debug_verbose( + "%s: removing holddown bi matching NVE of new route", + __func__); + if (bi->extra->vnc.import.timer) { + struct thread *t = + (struct thread *)bi->extra->vnc.import.timer; + struct rfapi_withdraw *wcb = t->arg; + + XFREE(MTYPE_RFAPI_WITHDRAW, wcb); + thread_cancel(t); + } + rfapiExpireVpnNow(import_table, rn, bi, 0); + } + + if (!original_had_routes) { + /* + * We went from 0 usable routes to 1 usable route. Perform the + * "Adding a Route" export process. + */ + vnc_direct_bgp_add_prefix(bgp, import_table, rn); + vnc_zebra_add_prefix(bgp, import_table, rn); + } else { + /* + * Check for nexthop change event + * Note: the prefix_same() test below detects two situations: + * 1. route is replaced, new route has different nexthop + * 2. new route is added (original_nexthop is 0) + */ + struct prefix new_nexthop; + + rfapiGetNexthop(attr, &new_nexthop); + if (!prefix_same(&original_nexthop, &new_nexthop)) { + /* + * nexthop change event + * vnc_direct_bgp_add_prefix() will recompute VN addr + * ecommunity + */ + vnc_direct_bgp_add_prefix(bgp, import_table, rn); + } + } + + if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)) { + for (n = rn; n; n = n->parent) { + // rfapiDoRouteCallback(import_table, n, NULL); + } + rfapiMonitorItNodeChanged(import_table, rn, NULL); + } + RFAPI_CHECK_REFCOUNT(rn, SAFI_MPLS_VPN, 0); + VNC_ITRCCK; } static rfapi_bi_filtered_import_f * -rfapiBgpInfoFilteredImportFunction (safi_t safi) +rfapiBgpInfoFilteredImportFunction(safi_t safi) { - switch (safi) - { - case SAFI_MPLS_VPN: - return rfapiBgpInfoFilteredImportVPN; - - case SAFI_ENCAP: - return rfapiBgpInfoFilteredImportEncap; - } - zlog_err ("%s: bad safi %d", __func__, safi); - return NULL; + switch (safi) { + case SAFI_MPLS_VPN: + return rfapiBgpInfoFilteredImportVPN; + + case SAFI_ENCAP: + return rfapiBgpInfoFilteredImportEncap; + } + zlog_err("%s: bad safi %d", __func__, safi); + return NULL; } -void -rfapiProcessUpdate ( - struct peer *peer, - void *rfd, /* set when looped from RFP/RFAPI */ - struct prefix *p, - struct prefix_rd *prd, - struct attr *attr, - afi_t afi, - safi_t safi, - u_char type, - u_char sub_type, - uint32_t *label) +void rfapiProcessUpdate(struct peer *peer, + void *rfd, /* set when looped from RFP/RFAPI */ + struct prefix *p, struct prefix_rd *prd, + struct attr *attr, afi_t afi, safi_t safi, u_char type, + u_char sub_type, uint32_t *label) { - struct bgp *bgp; - struct rfapi *h; - struct rfapi_import_table *it; - int has_ip_route = 1; - uint32_t lni = 0; - - bgp = bgp_get_default (); /* assume 1 instance for now */ - assert (bgp); - - h = bgp->rfapi; - assert (h); - - /* - * look at high-order byte of RD. FF means MAC - * address is present (VNC L2VPN) - */ - if ((safi == SAFI_MPLS_VPN) && - (decode_rd_type(prd->val) == RD_TYPE_VNC_ETH)) - { - struct prefix pfx_mac_buf; - struct prefix pfx_nexthop_buf; - int rc; - - /* - * Set flag if prefix and nexthop are the same - don't - * add the route to normal IP-based import tables - */ - if (!rfapiGetNexthop (attr, &pfx_nexthop_buf)) - { - if (!prefix_cmp (&pfx_nexthop_buf, p)) - { - has_ip_route = 0; - } - } - - memset (&pfx_mac_buf, 0, sizeof (pfx_mac_buf)); - pfx_mac_buf.family = AF_ETHERNET; - pfx_mac_buf.prefixlen = 48; - memcpy (&pfx_mac_buf.u.prefix_eth.octet, prd->val + 2, 6); - - /* - * Find rt containing LNI (Logical Network ID), which - * _should_ always be present when mac address is present - */ - rc = rfapiEcommunityGetLNI (attr->ecommunity, &lni); - - vnc_zlog_debug_verbose - ("%s: rfapiEcommunityGetLNI returned %d, lni=%d, attr=%p", - __func__, rc, lni, attr); - if (attr && !rc) - { - it = rfapiMacImportTableGet (bgp, lni); - - rfapiBgpInfoFilteredImportVPN ( - it, - FIF_ACTION_UPDATE, - peer, - rfd, - &pfx_mac_buf, /* prefix */ - p, /* aux prefix: IP addr */ - AFI_L2VPN, - prd, - attr, - type, - sub_type, - label); - } - - } - - if (!has_ip_route) - return; - - /* - * Iterate over all import tables; do a filtered import - * for the afi/safi combination - */ - for (it = h->imports; it; it = it->next) - { - (*rfapiBgpInfoFilteredImportFunction (safi)) ( - it, - FIF_ACTION_UPDATE, - peer, - rfd, - p, /* prefix */ - NULL, - afi, - prd, - attr, - type, - sub_type, - label); - } - - if (safi == SAFI_MPLS_VPN) - { - vnc_direct_bgp_rh_add_route (bgp, afi, p, peer, attr); - } - - if (safi == SAFI_MPLS_VPN) - { - rfapiBgpInfoFilteredImportVPN ( - bgp->rfapi->it_ce, - FIF_ACTION_UPDATE, - peer, - rfd, - p, /* prefix */ - NULL, - afi, - prd, - attr, - type, - sub_type, - label); - } + struct bgp *bgp; + struct rfapi *h; + struct rfapi_import_table *it; + int has_ip_route = 1; + uint32_t lni = 0; + + bgp = bgp_get_default(); /* assume 1 instance for now */ + assert(bgp); + + h = bgp->rfapi; + assert(h); + + /* + * look at high-order byte of RD. FF means MAC + * address is present (VNC L2VPN) + */ + if ((safi == SAFI_MPLS_VPN) + && (decode_rd_type(prd->val) == RD_TYPE_VNC_ETH)) { + struct prefix pfx_mac_buf; + struct prefix pfx_nexthop_buf; + int rc; + + /* + * Set flag if prefix and nexthop are the same - don't + * add the route to normal IP-based import tables + */ + if (!rfapiGetNexthop(attr, &pfx_nexthop_buf)) { + if (!prefix_cmp(&pfx_nexthop_buf, p)) { + has_ip_route = 0; + } + } + + memset(&pfx_mac_buf, 0, sizeof(pfx_mac_buf)); + pfx_mac_buf.family = AF_ETHERNET; + pfx_mac_buf.prefixlen = 48; + memcpy(&pfx_mac_buf.u.prefix_eth.octet, prd->val + 2, 6); + + /* + * Find rt containing LNI (Logical Network ID), which + * _should_ always be present when mac address is present + */ + rc = rfapiEcommunityGetLNI(attr->ecommunity, &lni); + + vnc_zlog_debug_verbose( + "%s: rfapiEcommunityGetLNI returned %d, lni=%d, attr=%p", + __func__, rc, lni, attr); + if (attr && !rc) { + it = rfapiMacImportTableGet(bgp, lni); + + rfapiBgpInfoFilteredImportVPN( + it, FIF_ACTION_UPDATE, peer, rfd, + &pfx_mac_buf, /* prefix */ + p, /* aux prefix: IP addr */ + AFI_L2VPN, prd, attr, type, sub_type, label); + } + } + + if (!has_ip_route) + return; + + /* + * Iterate over all import tables; do a filtered import + * for the afi/safi combination + */ + for (it = h->imports; it; it = it->next) { + (*rfapiBgpInfoFilteredImportFunction(safi))( + it, FIF_ACTION_UPDATE, peer, rfd, p, /* prefix */ + NULL, afi, prd, attr, type, sub_type, label); + } + + if (safi == SAFI_MPLS_VPN) { + vnc_direct_bgp_rh_add_route(bgp, afi, p, peer, attr); + } + + if (safi == SAFI_MPLS_VPN) { + rfapiBgpInfoFilteredImportVPN( + bgp->rfapi->it_ce, FIF_ACTION_UPDATE, peer, rfd, + p, /* prefix */ + NULL, afi, prd, attr, type, sub_type, label); + } } -void -rfapiProcessWithdraw ( - struct peer *peer, - void *rfd, - struct prefix *p, - struct prefix_rd *prd, - struct attr *attr, - afi_t afi, - safi_t safi, - u_char type, - int kill) +void rfapiProcessWithdraw(struct peer *peer, void *rfd, struct prefix *p, + struct prefix_rd *prd, struct attr *attr, afi_t afi, + safi_t safi, u_char type, int kill) { - struct bgp *bgp; - struct rfapi *h; - struct rfapi_import_table *it; - - bgp = bgp_get_default (); /* assume 1 instance for now */ - assert (bgp); - - h = bgp->rfapi; - assert (h); - - /* - * look at high-order byte of RD. FF means MAC - * address is present (VNC L2VPN) - */ - if (h->import_mac != NULL && safi == SAFI_MPLS_VPN && - decode_rd_type(prd->val) == RD_TYPE_VNC_ETH) - { - struct prefix pfx_mac_buf; - void *cursor = NULL; - int rc; - - memset (&pfx_mac_buf, 0, sizeof (pfx_mac_buf)); - pfx_mac_buf.family = AF_ETHERNET; - pfx_mac_buf.prefixlen = 48; - memcpy (&pfx_mac_buf.u.prefix_eth, prd->val + 2, 6); - - /* - * withdraw does not contain attrs, so we don't have - * access to the route's LNI, which would ordinarily - * select the specific mac-based import table. Instead, - * we must iterate over all mac-based tables and rely - * on the RD to match. - * - * If this approach is too slow, add an index where - * key is {RD, peer} and value is the import table - */ - for (rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor); - rc == 0; - rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor)) - { + struct bgp *bgp; + struct rfapi *h; + struct rfapi_import_table *it; + + bgp = bgp_get_default(); /* assume 1 instance for now */ + assert(bgp); + + h = bgp->rfapi; + assert(h); + + /* + * look at high-order byte of RD. FF means MAC + * address is present (VNC L2VPN) + */ + if (h->import_mac != NULL && safi == SAFI_MPLS_VPN + && decode_rd_type(prd->val) == RD_TYPE_VNC_ETH) { + struct prefix pfx_mac_buf; + void *cursor = NULL; + int rc; + + memset(&pfx_mac_buf, 0, sizeof(pfx_mac_buf)); + pfx_mac_buf.family = AF_ETHERNET; + pfx_mac_buf.prefixlen = 48; + memcpy(&pfx_mac_buf.u.prefix_eth, prd->val + 2, 6); + + /* + * withdraw does not contain attrs, so we don't have + * access to the route's LNI, which would ordinarily + * select the specific mac-based import table. Instead, + * we must iterate over all mac-based tables and rely + * on the RD to match. + * + * If this approach is too slow, add an index where + * key is {RD, peer} and value is the import table + */ + for (rc = skiplist_next(h->import_mac, NULL, (void **)&it, + &cursor); + rc == 0; rc = skiplist_next(h->import_mac, NULL, + (void **)&it, &cursor)) { #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose - ("%s: calling rfapiBgpInfoFilteredImportVPN(it=%p, afi=AFI_L2VPN)", - __func__, it); + vnc_zlog_debug_verbose( + "%s: calling rfapiBgpInfoFilteredImportVPN(it=%p, afi=AFI_L2VPN)", + __func__, it); #endif - rfapiBgpInfoFilteredImportVPN ( - it, - (kill ? FIF_ACTION_KILL : FIF_ACTION_WITHDRAW), - peer, - rfd, - &pfx_mac_buf, /* prefix */ - p, /* aux_prefix: IP */ - AFI_L2VPN, - prd, - attr, - type, - 0, - NULL); /* sub_type & label unused for withdraw */ - } - } - - /* - * XXX For the case where the withdraw involves an L2 - * route with no IP information, we rely on the lack - * of RT-list intersection to filter out the withdraw - * from the IP-based import tables below - */ - - /* - * Iterate over all import tables; do a filtered import - * for the afi/safi combination - */ - - for (it = h->imports; it; it = it->next) - { - (*rfapiBgpInfoFilteredImportFunction (safi)) ( - it, - (kill ? FIF_ACTION_KILL : FIF_ACTION_WITHDRAW), - peer, - rfd, - p, /* prefix */ - NULL, - afi, - prd, - attr, - type, - 0, - NULL); /* sub_type & label unused for withdraw */ - } - - /* TBD the deletion should happen after the lifetime expires */ - if (safi == SAFI_MPLS_VPN) - vnc_direct_bgp_rh_del_route (bgp, afi, p, peer); - - if (safi == SAFI_MPLS_VPN) - { - rfapiBgpInfoFilteredImportVPN ( - bgp->rfapi->it_ce, - (kill ? FIF_ACTION_KILL : FIF_ACTION_WITHDRAW), - peer, - rfd, - p, /* prefix */ - NULL, - afi, - prd, - attr, - type, - 0, - NULL); /* sub_type & label unused for withdraw */ - } + rfapiBgpInfoFilteredImportVPN( + it, + (kill ? FIF_ACTION_KILL : FIF_ACTION_WITHDRAW), + peer, rfd, &pfx_mac_buf, /* prefix */ + p, /* aux_prefix: IP */ + AFI_L2VPN, prd, attr, type, 0, + NULL); /* sub_type & label unused for withdraw + */ + } + } + + /* + * XXX For the case where the withdraw involves an L2 + * route with no IP information, we rely on the lack + * of RT-list intersection to filter out the withdraw + * from the IP-based import tables below + */ + + /* + * Iterate over all import tables; do a filtered import + * for the afi/safi combination + */ + + for (it = h->imports; it; it = it->next) { + (*rfapiBgpInfoFilteredImportFunction(safi))( + it, (kill ? FIF_ACTION_KILL : FIF_ACTION_WITHDRAW), + peer, rfd, p, /* prefix */ + NULL, afi, prd, attr, type, 0, + NULL); /* sub_type & label unused for withdraw */ + } + + /* TBD the deletion should happen after the lifetime expires */ + if (safi == SAFI_MPLS_VPN) + vnc_direct_bgp_rh_del_route(bgp, afi, p, peer); + + if (safi == SAFI_MPLS_VPN) { + rfapiBgpInfoFilteredImportVPN( + bgp->rfapi->it_ce, + (kill ? FIF_ACTION_KILL : FIF_ACTION_WITHDRAW), peer, + rfd, p, /* prefix */ + NULL, afi, prd, attr, type, 0, + NULL); /* sub_type & label unused for withdraw */ + } } /* @@ -4378,65 +4087,57 @@ rfapiProcessWithdraw ( /* surprise, this gets called from peer_delete(), from rfapi_close() */ -static void -rfapiProcessPeerDownRt ( - struct peer *peer, - struct rfapi_import_table *import_table, - afi_t afi, - safi_t safi) +static void rfapiProcessPeerDownRt(struct peer *peer, + struct rfapi_import_table *import_table, + afi_t afi, safi_t safi) { - struct route_node *rn; - struct bgp_info *bi; - struct route_table *rt; - int (*timer_service_func) (struct thread *); - - assert (afi == AFI_IP || afi == AFI_IP6); - - VNC_ITRCCK; - - switch (safi) - { - case SAFI_MPLS_VPN: - rt = import_table->imported_vpn[afi]; - timer_service_func = rfapiWithdrawTimerVPN; - break; - case SAFI_ENCAP: - rt = import_table->imported_encap[afi]; - timer_service_func = rfapiWithdrawTimerEncap; - break; - default: - assert (0); - } - - - for (rn = route_top (rt); rn; rn = route_next (rn)) - { - for (bi = rn->info; bi; bi = bi->next) - { - if (bi->peer == peer) - { - - if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)) - { - /* already in holddown, skip */ - continue; - } - - if (safi == SAFI_MPLS_VPN) - { - RFAPI_UPDATE_ITABLE_COUNT (bi, import_table, afi, -1); - import_table->holddown_count[afi] += 1; - } - rfapiBiStartWithdrawTimer (import_table, rn, bi, - afi, safi, - timer_service_func); - } - } - } - VNC_ITRCCK; + struct route_node *rn; + struct bgp_info *bi; + struct route_table *rt; + int (*timer_service_func)(struct thread *); + + assert(afi == AFI_IP || afi == AFI_IP6); + + VNC_ITRCCK; + + switch (safi) { + case SAFI_MPLS_VPN: + rt = import_table->imported_vpn[afi]; + timer_service_func = rfapiWithdrawTimerVPN; + break; + case SAFI_ENCAP: + rt = import_table->imported_encap[afi]; + timer_service_func = rfapiWithdrawTimerEncap; + break; + default: + assert(0); + } + + + for (rn = route_top(rt); rn; rn = route_next(rn)) { + for (bi = rn->info; bi; bi = bi->next) { + if (bi->peer == peer) { + + if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) { + /* already in holddown, skip */ + continue; + } + + if (safi == SAFI_MPLS_VPN) { + RFAPI_UPDATE_ITABLE_COUNT( + bi, import_table, afi, -1); + import_table->holddown_count[afi] += 1; + } + rfapiBiStartWithdrawTimer(import_table, rn, bi, + afi, safi, + timer_service_func); + } + } + } + VNC_ITRCCK; } -/* +/* * This gets called when a peer connection drops. We have to remove * all the routes from this peer. * @@ -4444,49 +4145,46 @@ rfapiProcessPeerDownRt ( * grouping withdrawn routes so we can generate callbacks more * efficiently. */ -void -rfapiProcessPeerDown (struct peer *peer) +void rfapiProcessPeerDown(struct peer *peer) { - struct bgp *bgp; - struct rfapi *h; - struct rfapi_import_table *it; - - /* - * If this peer is a "dummy" peer structure atached to a RFAPI - * nve_descriptor, we don't need to walk the import tables - * because the routes are already withdrawn by rfapi_close() - */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_IS_RFAPI_HD)) - return; - - /* - * 1. Visit all BIs in all ENCAP import tables. - * Start withdraw timer on the BIs that match peer. - * - * 2. Visit All BIs in all VPN import tables. - * Start withdraw timer on the BIs that match peer. - */ - - bgp = bgp_get_default (); /* assume 1 instance for now */ - if (!bgp) - return; - - h = bgp->rfapi; - assert (h); - - for (it = h->imports; it; it = it->next) - { - rfapiProcessPeerDownRt (peer, it, AFI_IP, SAFI_ENCAP); - rfapiProcessPeerDownRt (peer, it, AFI_IP6, SAFI_ENCAP); - rfapiProcessPeerDownRt (peer, it, AFI_IP, SAFI_MPLS_VPN); - rfapiProcessPeerDownRt (peer, it, AFI_IP6, SAFI_MPLS_VPN); - } - - if (h->it_ce) - { - rfapiProcessPeerDownRt (peer, h->it_ce, AFI_IP, SAFI_MPLS_VPN); - rfapiProcessPeerDownRt (peer, h->it_ce, AFI_IP6, SAFI_MPLS_VPN); - } + struct bgp *bgp; + struct rfapi *h; + struct rfapi_import_table *it; + + /* + * If this peer is a "dummy" peer structure atached to a RFAPI + * nve_descriptor, we don't need to walk the import tables + * because the routes are already withdrawn by rfapi_close() + */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)) + return; + + /* + * 1. Visit all BIs in all ENCAP import tables. + * Start withdraw timer on the BIs that match peer. + * + * 2. Visit All BIs in all VPN import tables. + * Start withdraw timer on the BIs that match peer. + */ + + bgp = bgp_get_default(); /* assume 1 instance for now */ + if (!bgp) + return; + + h = bgp->rfapi; + assert(h); + + for (it = h->imports; it; it = it->next) { + rfapiProcessPeerDownRt(peer, it, AFI_IP, SAFI_ENCAP); + rfapiProcessPeerDownRt(peer, it, AFI_IP6, SAFI_ENCAP); + rfapiProcessPeerDownRt(peer, it, AFI_IP, SAFI_MPLS_VPN); + rfapiProcessPeerDownRt(peer, it, AFI_IP6, SAFI_MPLS_VPN); + } + + if (h->it_ce) { + rfapiProcessPeerDownRt(peer, h->it_ce, AFI_IP, SAFI_MPLS_VPN); + rfapiProcessPeerDownRt(peer, h->it_ce, AFI_IP6, SAFI_MPLS_VPN); + } } /* @@ -4494,445 +4192,431 @@ rfapiProcessPeerDown (struct peer *peer) * filtered according to the import table's RT list * * TBD: does this function need additions to match rfapiProcessUpdate() - * for, e.g., L2 handling? + * for, e.g., L2 handling? */ -static void -rfapiBgpTableFilteredImport ( - struct bgp *bgp, - struct rfapi_import_table *it, - afi_t afi, - safi_t safi) +static void rfapiBgpTableFilteredImport(struct bgp *bgp, + struct rfapi_import_table *it, + afi_t afi, safi_t safi) { - struct bgp_node *rn1; - struct bgp_node *rn2; - - /* Only these SAFIs have 2-level RIBS */ - assert (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP); - - /* - * Now visit all the rd nodes and the nodes of all the - * route tables attached to them, and import the routes - * if they have matching route targets - */ - for (rn1 = bgp_table_top (bgp->rib[afi][safi]); - rn1; rn1 = bgp_route_next (rn1)) - { - - if (rn1->info) - { - for (rn2 = bgp_table_top (rn1->info); - rn2; rn2 = bgp_route_next (rn2)) - { - - struct bgp_info *bi; - - for (bi = rn2->info; bi; bi = bi->next) - { - u_int32_t label = 0; - - if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)) - continue; - - if (bi->extra) - label = decode_label (&bi->extra->label); - (*rfapiBgpInfoFilteredImportFunction (safi)) ( - it, /* which import table */ - FIF_ACTION_UPDATE, - bi->peer, - NULL, - &rn2->p, /* prefix */ - NULL, - afi, - (struct prefix_rd *) &rn1->p, - bi->attr, - bi->type, - bi->sub_type, - &label); - } - } - } - } + struct bgp_node *rn1; + struct bgp_node *rn2; + + /* Only these SAFIs have 2-level RIBS */ + assert(safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP); + + /* + * Now visit all the rd nodes and the nodes of all the + * route tables attached to them, and import the routes + * if they have matching route targets + */ + for (rn1 = bgp_table_top(bgp->rib[afi][safi]); rn1; + rn1 = bgp_route_next(rn1)) { + + if (rn1->info) { + for (rn2 = bgp_table_top(rn1->info); rn2; + rn2 = bgp_route_next(rn2)) { + + struct bgp_info *bi; + + for (bi = rn2->info; bi; bi = bi->next) { + u_int32_t label = 0; + + if (CHECK_FLAG(bi->flags, + BGP_INFO_REMOVED)) + continue; + + if (bi->extra) + label = decode_label( + &bi->extra->label); + (*rfapiBgpInfoFilteredImportFunction( + safi))( + it, /* which import table */ + FIF_ACTION_UPDATE, bi->peer, + NULL, &rn2->p, /* prefix */ + NULL, afi, + (struct prefix_rd *)&rn1->p, + bi->attr, bi->type, + bi->sub_type, &label); + } + } + } + } } /* per-bgp-instance rfapi data */ -struct rfapi * -bgp_rfapi_new (struct bgp *bgp) +struct rfapi *bgp_rfapi_new(struct bgp *bgp) { - struct rfapi *h; - int afi; - struct rfapi_rfp_cfg *cfg = NULL; - struct rfapi_rfp_cb_methods *cbm = NULL; - - assert (bgp->rfapi_cfg == NULL); - - h = (struct rfapi *) XCALLOC (MTYPE_RFAPI, sizeof (struct rfapi)); - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - /* ugly, to deal with addition of delegates, part of 0.99.24.1 merge */ - h->un[afi].delegate = route_table_get_default_delegate (); - } - - /* - * initialize the ce import table - */ - h->it_ce = - XCALLOC (MTYPE_RFAPI_IMPORTTABLE, sizeof (struct rfapi_import_table)); - h->it_ce->imported_vpn[AFI_IP] = route_table_init (); - h->it_ce->imported_vpn[AFI_IP6] = route_table_init (); - h->it_ce->imported_encap[AFI_IP] = route_table_init (); - h->it_ce->imported_encap[AFI_IP6] = route_table_init (); - rfapiBgpTableFilteredImport (bgp, h->it_ce, AFI_IP, SAFI_MPLS_VPN); - rfapiBgpTableFilteredImport (bgp, h->it_ce, AFI_IP6, SAFI_MPLS_VPN); - - /* - * Set up work queue for deferred rfapi_close operations - */ - h->deferred_close_q = work_queue_new (bm->master, "rfapi deferred close"); - h->deferred_close_q->spec.workfunc = rfapi_deferred_close_workfunc; - h->deferred_close_q->spec.data = h; - - h->rfp = rfp_start (bm->master, &cfg, &cbm); - bgp->rfapi_cfg = bgp_rfapi_cfg_new (cfg); - if (cbm != NULL) - { - h->rfp_methods = *cbm; - } - return h; + struct rfapi *h; + int afi; + struct rfapi_rfp_cfg *cfg = NULL; + struct rfapi_rfp_cb_methods *cbm = NULL; + + assert(bgp->rfapi_cfg == NULL); + + h = (struct rfapi *)XCALLOC(MTYPE_RFAPI, sizeof(struct rfapi)); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + /* ugly, to deal with addition of delegates, part of 0.99.24.1 + * merge */ + h->un[afi].delegate = route_table_get_default_delegate(); + } + + /* + * initialize the ce import table + */ + h->it_ce = XCALLOC(MTYPE_RFAPI_IMPORTTABLE, + sizeof(struct rfapi_import_table)); + h->it_ce->imported_vpn[AFI_IP] = route_table_init(); + h->it_ce->imported_vpn[AFI_IP6] = route_table_init(); + h->it_ce->imported_encap[AFI_IP] = route_table_init(); + h->it_ce->imported_encap[AFI_IP6] = route_table_init(); + rfapiBgpTableFilteredImport(bgp, h->it_ce, AFI_IP, SAFI_MPLS_VPN); + rfapiBgpTableFilteredImport(bgp, h->it_ce, AFI_IP6, SAFI_MPLS_VPN); + + /* + * Set up work queue for deferred rfapi_close operations + */ + h->deferred_close_q = + work_queue_new(bm->master, "rfapi deferred close"); + h->deferred_close_q->spec.workfunc = rfapi_deferred_close_workfunc; + h->deferred_close_q->spec.data = h; + + h->rfp = rfp_start(bm->master, &cfg, &cbm); + bgp->rfapi_cfg = bgp_rfapi_cfg_new(cfg); + if (cbm != NULL) { + h->rfp_methods = *cbm; + } + return h; } -void -bgp_rfapi_destroy (struct bgp *bgp, struct rfapi *h) +void bgp_rfapi_destroy(struct bgp *bgp, struct rfapi *h) { - if (bgp == NULL || h == NULL) - return; - - if (h->resolve_nve_nexthop) - { - skiplist_free (h->resolve_nve_nexthop); - h->resolve_nve_nexthop = NULL; - } - - route_table_finish (h->it_ce->imported_vpn[AFI_IP]); - route_table_finish (h->it_ce->imported_vpn[AFI_IP6]); - route_table_finish (h->it_ce->imported_encap[AFI_IP]); - route_table_finish (h->it_ce->imported_encap[AFI_IP6]); - - if (h->import_mac) - { - struct rfapi_import_table *it; - void *cursor; - int rc; - - for (cursor = NULL, - rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor); - !rc; - rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor)) - { - - rfapiImportTableFlush (it); - XFREE (MTYPE_RFAPI_IMPORTTABLE, it); - } - skiplist_free (h->import_mac); - h->import_mac = NULL; - } - - work_queue_free (h->deferred_close_q); - - if (h->rfp != NULL) - rfp_stop (h->rfp); - XFREE (MTYPE_RFAPI_IMPORTTABLE, h->it_ce); - XFREE (MTYPE_RFAPI, h); + if (bgp == NULL || h == NULL) + return; + + if (h->resolve_nve_nexthop) { + skiplist_free(h->resolve_nve_nexthop); + h->resolve_nve_nexthop = NULL; + } + + route_table_finish(h->it_ce->imported_vpn[AFI_IP]); + route_table_finish(h->it_ce->imported_vpn[AFI_IP6]); + route_table_finish(h->it_ce->imported_encap[AFI_IP]); + route_table_finish(h->it_ce->imported_encap[AFI_IP6]); + + if (h->import_mac) { + struct rfapi_import_table *it; + void *cursor; + int rc; + + for (cursor = NULL, + rc = skiplist_next(h->import_mac, NULL, (void **)&it, + &cursor); + !rc; rc = skiplist_next(h->import_mac, NULL, (void **)&it, + &cursor)) { + + rfapiImportTableFlush(it); + XFREE(MTYPE_RFAPI_IMPORTTABLE, it); + } + skiplist_free(h->import_mac); + h->import_mac = NULL; + } + + work_queue_free(h->deferred_close_q); + + if (h->rfp != NULL) + rfp_stop(h->rfp); + XFREE(MTYPE_RFAPI_IMPORTTABLE, h->it_ce); + XFREE(MTYPE_RFAPI, h); } struct rfapi_import_table * -rfapiImportTableRefAdd (struct bgp *bgp, struct ecommunity *rt_import_list, - struct rfapi_nve_group_cfg *rfg) +rfapiImportTableRefAdd(struct bgp *bgp, struct ecommunity *rt_import_list, + struct rfapi_nve_group_cfg *rfg) { - struct rfapi *h; - struct rfapi_import_table *it; - afi_t afi; - - h = bgp->rfapi; - assert (h); - - for (it = h->imports; it; it = it->next) - { - if (ecommunity_cmp (it->rt_import_list, rt_import_list)) - break; - } - - vnc_zlog_debug_verbose ("%s: matched it=%p", __func__, it); - - if (!it) - { - it = - XCALLOC (MTYPE_RFAPI_IMPORTTABLE, sizeof (struct rfapi_import_table)); - assert (it); - it->next = h->imports; - h->imports = it; - - it->rt_import_list = ecommunity_dup (rt_import_list); - it->rfg = rfg; - it->monitor_exterior_orphans = - skiplist_new (0, NULL, (void (*)(void *)) prefix_free); - - /* - * fill import route tables from RIBs - * - * Potential area for optimization. If this occurs when - * tables are large (e.g., the operator adds a nve group - * with a new RT list to a running system), it could take - * a while. - * - */ - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - - it->imported_vpn[afi] = route_table_init (); - it->imported_encap[afi] = route_table_init (); - - rfapiBgpTableFilteredImport (bgp, it, afi, SAFI_MPLS_VPN); - rfapiBgpTableFilteredImport (bgp, it, afi, SAFI_ENCAP); - - vnc_import_bgp_exterior_redist_enable_it (bgp, afi, it); - } - } - - it->refcount += 1; - - return it; + struct rfapi *h; + struct rfapi_import_table *it; + afi_t afi; + + h = bgp->rfapi; + assert(h); + + for (it = h->imports; it; it = it->next) { + if (ecommunity_cmp(it->rt_import_list, rt_import_list)) + break; + } + + vnc_zlog_debug_verbose("%s: matched it=%p", __func__, it); + + if (!it) { + it = XCALLOC(MTYPE_RFAPI_IMPORTTABLE, + sizeof(struct rfapi_import_table)); + assert(it); + it->next = h->imports; + h->imports = it; + + it->rt_import_list = ecommunity_dup(rt_import_list); + it->rfg = rfg; + it->monitor_exterior_orphans = + skiplist_new(0, NULL, (void (*)(void *))prefix_free); + + /* + * fill import route tables from RIBs + * + * Potential area for optimization. If this occurs when + * tables are large (e.g., the operator adds a nve group + * with a new RT list to a running system), it could take + * a while. + * + */ + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + + it->imported_vpn[afi] = route_table_init(); + it->imported_encap[afi] = route_table_init(); + + rfapiBgpTableFilteredImport(bgp, it, afi, + SAFI_MPLS_VPN); + rfapiBgpTableFilteredImport(bgp, it, afi, SAFI_ENCAP); + + vnc_import_bgp_exterior_redist_enable_it(bgp, afi, it); + } + } + + it->refcount += 1; + + return it; } /* * skiplist element free function */ -static void -delete_rem_pfx_na_free (void *na) +static void delete_rem_pfx_na_free(void *na) { - uint32_t *pCounter = ((struct rfapi_nve_addr *) na)->info; + uint32_t *pCounter = ((struct rfapi_nve_addr *)na)->info; - *pCounter += 1; - XFREE (MTYPE_RFAPI_NVE_ADDR, na); + *pCounter += 1; + XFREE(MTYPE_RFAPI_NVE_ADDR, na); } /* * Common deleter for IP and MAC import tables */ -static void -rfapiDeleteRemotePrefixesIt ( - struct bgp *bgp, - struct rfapi_import_table *it, - struct prefix *un, - struct prefix *vn, - struct prefix *p, - int delete_active, - int delete_holddown, - uint32_t *pARcount, - uint32_t *pAHcount, - uint32_t *pHRcount, - uint32_t *pHHcount, - struct skiplist *uniq_active_nves, - struct skiplist *uniq_holddown_nves) +static void rfapiDeleteRemotePrefixesIt( + struct bgp *bgp, struct rfapi_import_table *it, struct prefix *un, + struct prefix *vn, struct prefix *p, int delete_active, + int delete_holddown, uint32_t *pARcount, uint32_t *pAHcount, + uint32_t *pHRcount, uint32_t *pHHcount, + struct skiplist *uniq_active_nves, struct skiplist *uniq_holddown_nves) { - afi_t afi; + afi_t afi; #if DEBUG_L2_EXTRA - { - char buf_pfx[BUFSIZ]; - - if (p) - { - prefix2str (p, buf_pfx, BUFSIZ); - } - else - { - buf_pfx[0] = '*'; - buf_pfx[1] = 0; - } - - vnc_zlog_debug_verbose ("%s: entry, p=%s, delete_active=%d, delete_holddown=%d", - __func__, buf_pfx, delete_active, delete_holddown); - } + { + char buf_pfx[BUFSIZ]; + + if (p) { + prefix2str(p, buf_pfx, BUFSIZ); + } else { + buf_pfx[0] = '*'; + buf_pfx[1] = 0; + } + + vnc_zlog_debug_verbose( + "%s: entry, p=%s, delete_active=%d, delete_holddown=%d", + __func__, buf_pfx, delete_active, delete_holddown); + } #endif - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - - struct route_table *rt; - struct route_node *rn; - - if (p && (family2afi (p->family) != afi)) - { - continue; - } - - rt = it->imported_vpn[afi]; - if (!rt) - continue; - - vnc_zlog_debug_verbose ("%s: scanning rt for afi=%d", __func__, afi); - - for (rn = route_top (rt); rn; rn = route_next (rn)) - { - struct bgp_info *bi; - struct bgp_info *next; - - if (VNC_DEBUG(IMPORT_DEL_REMOTE)) - { - char p1line[BUFSIZ]; - char p2line[BUFSIZ]; - - prefix2str (p, p1line, BUFSIZ); - prefix2str (&rn->p, p2line, BUFSIZ); - vnc_zlog_debug_any ("%s: want %s, have %s", __func__, p1line, p2line); - } - - if (p && prefix_cmp (p, &rn->p)) - continue; - - { - char buf_pfx[BUFSIZ]; - prefix2str (&rn->p, buf_pfx, BUFSIZ); - vnc_zlog_debug_verbose ("%s: rn pfx=%s", __func__, buf_pfx); - } - - /* TBD is this valid for afi == AFI_L2VPN? */ - RFAPI_CHECK_REFCOUNT (rn, SAFI_MPLS_VPN, 1); - - for (bi = rn->info; bi; bi = next) - { - next = bi->next; - - struct prefix qpt; - struct prefix qct; - int qpt_valid = 0; - int qct_valid = 0; - int is_active = 0; - - vnc_zlog_debug_verbose ("%s: examining bi %p", __func__, bi); - - if (bi->attr) - { - if (!rfapiGetNexthop (bi->attr, &qpt)) - qpt_valid = 1; - } - if (vn) - { - if (!qpt_valid || !prefix_match (vn, &qpt)) - { + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + + struct route_table *rt; + struct route_node *rn; + + if (p && (family2afi(p->family) != afi)) { + continue; + } + + rt = it->imported_vpn[afi]; + if (!rt) + continue; + + vnc_zlog_debug_verbose("%s: scanning rt for afi=%d", __func__, + afi); + + for (rn = route_top(rt); rn; rn = route_next(rn)) { + struct bgp_info *bi; + struct bgp_info *next; + + if (VNC_DEBUG(IMPORT_DEL_REMOTE)) { + char p1line[BUFSIZ]; + char p2line[BUFSIZ]; + + prefix2str(p, p1line, BUFSIZ); + prefix2str(&rn->p, p2line, BUFSIZ); + vnc_zlog_debug_any("%s: want %s, have %s", + __func__, p1line, p2line); + } + + if (p && prefix_cmp(p, &rn->p)) + continue; + + { + char buf_pfx[BUFSIZ]; + prefix2str(&rn->p, buf_pfx, BUFSIZ); + vnc_zlog_debug_verbose("%s: rn pfx=%s", + __func__, buf_pfx); + } + + /* TBD is this valid for afi == AFI_L2VPN? */ + RFAPI_CHECK_REFCOUNT(rn, SAFI_MPLS_VPN, 1); + + for (bi = rn->info; bi; bi = next) { + next = bi->next; + + struct prefix qpt; + struct prefix qct; + int qpt_valid = 0; + int qct_valid = 0; + int is_active = 0; + + vnc_zlog_debug_verbose("%s: examining bi %p", + __func__, bi); + + if (bi->attr) { + if (!rfapiGetNexthop(bi->attr, &qpt)) + qpt_valid = 1; + } + if (vn) { + if (!qpt_valid + || !prefix_match(vn, &qpt)) { #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose - ("%s: continue at vn && !qpt_valid || !prefix_match(vn, &qpt)", - __func__); + vnc_zlog_debug_verbose( + "%s: continue at vn && !qpt_valid || !prefix_match(vn, &qpt)", + __func__); #endif - continue; - } - } + continue; + } + } - if (!rfapiGetUnAddrOfVpnBi (bi, &qct)) - qct_valid = 1; + if (!rfapiGetUnAddrOfVpnBi(bi, &qct)) + qct_valid = 1; - if (un) - { - if (!qct_valid || !prefix_match (un, &qct)) - { + if (un) { + if (!qct_valid + || !prefix_match(un, &qct)) { #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose - ("%s: continue at un && !qct_valid || !prefix_match(un, &qct)", - __func__); + vnc_zlog_debug_verbose( + "%s: continue at un && !qct_valid || !prefix_match(un, &qct)", + __func__); #endif - continue; - } - } - - - /* - * Blow bi away - */ - /* - * If this route is waiting to be deleted because of - * a previous withdraw, we must cancel its timer. - */ - if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)) - { - if (!delete_holddown) - continue; - if (bi->extra->vnc.import.timer) - { - - struct thread *t = - (struct thread *) bi->extra->vnc.import.timer; - struct rfapi_withdraw *wcb = t->arg; - - wcb->import_table->holddown_count[afi] -= 1; - RFAPI_UPDATE_ITABLE_COUNT (bi, wcb->import_table, afi, - 1); - XFREE (MTYPE_RFAPI_WITHDRAW, wcb); - thread_cancel (t); - } - } - else - { - if (!delete_active) - continue; - is_active = 1; - } - - vnc_zlog_debug_verbose - ("%s: deleting bi %p (qct_valid=%d, qpt_valid=%d, delete_holddown=%d, delete_active=%d)", - __func__, bi, qct_valid, qpt_valid, delete_holddown, - delete_active); - - - /* - * add nve to list - */ - if (qct_valid && qpt_valid) - { - - struct rfapi_nve_addr na; - struct rfapi_nve_addr *nap; - - memset (&na, 0, sizeof (na)); - assert (!rfapiQprefix2Raddr (&qct, &na.un)); - assert (!rfapiQprefix2Raddr (&qpt, &na.vn)); - - if (skiplist_search ((is_active ? uniq_active_nves : - uniq_holddown_nves), &na, - (void **) &nap)) - { - char line[BUFSIZ]; - - nap = XCALLOC (MTYPE_RFAPI_NVE_ADDR, - sizeof (struct rfapi_nve_addr)); - assert (nap); - *nap = na; - nap->info = is_active ? pAHcount : pHHcount; - skiplist_insert ((is_active ? uniq_active_nves : - uniq_holddown_nves), nap, nap); - - rfapiNveAddr2Str (nap, line, BUFSIZ); - } - } - - vnc_direct_bgp_rh_del_route (bgp, afi, &rn->p, bi->peer); - - RFAPI_UPDATE_ITABLE_COUNT (bi, it, afi, -1); - it->holddown_count[afi] += 1; - rfapiExpireVpnNow (it, rn, bi, 1); - - vnc_zlog_debug_verbose ("%s: incrementing count (is_active=%d)", - __func__, is_active); - - if (is_active) - ++ * pARcount; - else - ++ * pHRcount; - } - } - } + continue; + } + } + + + /* + * Blow bi away + */ + /* + * If this route is waiting to be deleted + * because of + * a previous withdraw, we must cancel its + * timer. + */ + if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) { + if (!delete_holddown) + continue; + if (bi->extra->vnc.import.timer) { + + struct thread *t = + (struct thread *)bi + ->extra->vnc + .import.timer; + struct rfapi_withdraw *wcb = + t->arg; + + wcb->import_table + ->holddown_count[afi] -= + 1; + RFAPI_UPDATE_ITABLE_COUNT( + bi, wcb->import_table, + afi, 1); + XFREE(MTYPE_RFAPI_WITHDRAW, + wcb); + thread_cancel(t); + } + } else { + if (!delete_active) + continue; + is_active = 1; + } + + vnc_zlog_debug_verbose( + "%s: deleting bi %p (qct_valid=%d, qpt_valid=%d, delete_holddown=%d, delete_active=%d)", + __func__, bi, qct_valid, qpt_valid, + delete_holddown, delete_active); + + + /* + * add nve to list + */ + if (qct_valid && qpt_valid) { + + struct rfapi_nve_addr na; + struct rfapi_nve_addr *nap; + + memset(&na, 0, sizeof(na)); + assert(!rfapiQprefix2Raddr(&qct, + &na.un)); + assert(!rfapiQprefix2Raddr(&qpt, + &na.vn)); + + if (skiplist_search( + (is_active + ? uniq_active_nves + : uniq_holddown_nves), + &na, (void **)&nap)) { + char line[BUFSIZ]; + + nap = XCALLOC( + MTYPE_RFAPI_NVE_ADDR, + sizeof(struct + rfapi_nve_addr)); + assert(nap); + *nap = na; + nap->info = is_active + ? pAHcount + : pHHcount; + skiplist_insert( + (is_active + ? uniq_active_nves + : uniq_holddown_nves), + nap, nap); + + rfapiNveAddr2Str(nap, line, + BUFSIZ); + } + } + + vnc_direct_bgp_rh_del_route(bgp, afi, &rn->p, + bi->peer); + + RFAPI_UPDATE_ITABLE_COUNT(bi, it, afi, -1); + it->holddown_count[afi] += 1; + rfapiExpireVpnNow(it, rn, bi, 1); + + vnc_zlog_debug_verbose( + "%s: incrementing count (is_active=%d)", + __func__, is_active); + + if (is_active) + ++*pARcount; + else + ++*pHRcount; + } + } + } } @@ -4944,7 +4628,7 @@ rfapiDeleteRemotePrefixesIt ( * * UI helper: For use by the "clear vnc prefixes" command * - * input: + * input: * un if set, tunnel must match this prefix * vn if set, nexthop prefix must match this prefix * p if set, prefix must match this prefix @@ -4959,133 +4643,110 @@ rfapiDeleteRemotePrefixesIt ( * return value: * void --------------------------------------------*/ -void -rfapiDeleteRemotePrefixes ( - struct prefix *un, - struct prefix *vn, - struct prefix *p, - struct rfapi_import_table *arg_it, - int delete_active, - int delete_holddown, - uint32_t *pARcount, - uint32_t *pAHcount, - uint32_t *pHRcount, - uint32_t *pHHcount) +void rfapiDeleteRemotePrefixes(struct prefix *un, struct prefix *vn, + struct prefix *p, + struct rfapi_import_table *arg_it, + int delete_active, int delete_holddown, + uint32_t *pARcount, uint32_t *pAHcount, + uint32_t *pHRcount, uint32_t *pHHcount) { - struct bgp *bgp; - struct rfapi *h; - struct rfapi_import_table *it; - uint32_t deleted_holddown_route_count = 0; - uint32_t deleted_active_route_count = 0; - uint32_t deleted_holddown_nve_count = 0; - uint32_t deleted_active_nve_count = 0; - struct skiplist *uniq_holddown_nves; - struct skiplist *uniq_active_nves; - - VNC_ITRCCK; - - bgp = bgp_get_default (); /* assume 1 instance for now */ - /* If no bgp instantiated yet, no vnc prefixes exist */ - if (!bgp) - return; - - h = bgp->rfapi; - assert (h); - - uniq_holddown_nves = - skiplist_new (0, rfapi_nve_addr_cmp, delete_rem_pfx_na_free); - uniq_active_nves = - skiplist_new (0, rfapi_nve_addr_cmp, delete_rem_pfx_na_free); - - /* - * Iterate over all import tables; do a filtered import - * for the afi/safi combination - */ - - if (arg_it) - it = arg_it; - else - it = h->imports; - for (; it; ) - { - - vnc_zlog_debug_verbose - ("%s: calling rfapiDeleteRemotePrefixesIt() on (IP) import %p", - __func__, it); - - rfapiDeleteRemotePrefixesIt ( - bgp, - it, - un, - vn, - p, - delete_active, - delete_holddown, - &deleted_active_route_count, - &deleted_active_nve_count, - &deleted_holddown_route_count, - &deleted_holddown_nve_count, - uniq_active_nves, - uniq_holddown_nves); - - if (arg_it) - it = NULL; - else - it = it->next; - } - - /* - * Now iterate over L2 import tables - */ - if (h->import_mac && !(p && (p->family != AF_ETHERNET))) - { - - void *cursor = NULL; - int rc; - - for (cursor = NULL, - rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor); - !rc; - rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor)) - { - - vnc_zlog_debug_verbose - ("%s: calling rfapiDeleteRemotePrefixesIt() on import_mac %p", - __func__, it); - - rfapiDeleteRemotePrefixesIt ( - bgp, - it, - un, - vn, - p, - delete_active, - delete_holddown, - &deleted_active_route_count, - &deleted_active_nve_count, - &deleted_holddown_route_count, - &deleted_holddown_nve_count, - uniq_active_nves, - uniq_holddown_nves); - } - } - - /* - * our custom element freeing function above counts as it deletes - */ - skiplist_free (uniq_holddown_nves); - skiplist_free (uniq_active_nves); - - if (pARcount) - *pARcount = deleted_active_route_count; - if (pAHcount) - *pAHcount = deleted_active_nve_count; - if (pHRcount) - *pHRcount = deleted_holddown_route_count; - if (pHHcount) - *pHHcount = deleted_holddown_nve_count; - - VNC_ITRCCK; + struct bgp *bgp; + struct rfapi *h; + struct rfapi_import_table *it; + uint32_t deleted_holddown_route_count = 0; + uint32_t deleted_active_route_count = 0; + uint32_t deleted_holddown_nve_count = 0; + uint32_t deleted_active_nve_count = 0; + struct skiplist *uniq_holddown_nves; + struct skiplist *uniq_active_nves; + + VNC_ITRCCK; + + bgp = bgp_get_default(); /* assume 1 instance for now */ + /* If no bgp instantiated yet, no vnc prefixes exist */ + if (!bgp) + return; + + h = bgp->rfapi; + assert(h); + + uniq_holddown_nves = + skiplist_new(0, rfapi_nve_addr_cmp, delete_rem_pfx_na_free); + uniq_active_nves = + skiplist_new(0, rfapi_nve_addr_cmp, delete_rem_pfx_na_free); + + /* + * Iterate over all import tables; do a filtered import + * for the afi/safi combination + */ + + if (arg_it) + it = arg_it; + else + it = h->imports; + for (; it;) { + + vnc_zlog_debug_verbose( + "%s: calling rfapiDeleteRemotePrefixesIt() on (IP) import %p", + __func__, it); + + rfapiDeleteRemotePrefixesIt( + bgp, it, un, vn, p, delete_active, delete_holddown, + &deleted_active_route_count, &deleted_active_nve_count, + &deleted_holddown_route_count, + &deleted_holddown_nve_count, uniq_active_nves, + uniq_holddown_nves); + + if (arg_it) + it = NULL; + else + it = it->next; + } + + /* + * Now iterate over L2 import tables + */ + if (h->import_mac && !(p && (p->family != AF_ETHERNET))) { + + void *cursor = NULL; + int rc; + + for (cursor = NULL, + rc = skiplist_next(h->import_mac, NULL, (void **)&it, + &cursor); + !rc; rc = skiplist_next(h->import_mac, NULL, (void **)&it, + &cursor)) { + + vnc_zlog_debug_verbose( + "%s: calling rfapiDeleteRemotePrefixesIt() on import_mac %p", + __func__, it); + + rfapiDeleteRemotePrefixesIt( + bgp, it, un, vn, p, delete_active, + delete_holddown, &deleted_active_route_count, + &deleted_active_nve_count, + &deleted_holddown_route_count, + &deleted_holddown_nve_count, uniq_active_nves, + uniq_holddown_nves); + } + } + + /* + * our custom element freeing function above counts as it deletes + */ + skiplist_free(uniq_holddown_nves); + skiplist_free(uniq_active_nves); + + if (pARcount) + *pARcount = deleted_active_route_count; + if (pAHcount) + *pAHcount = deleted_active_nve_count; + if (pHRcount) + *pHRcount = deleted_holddown_route_count; + if (pHHcount) + *pHHcount = deleted_holddown_nve_count; + + VNC_ITRCCK; } /*------------------------------------------ @@ -5093,7 +4754,7 @@ rfapiDeleteRemotePrefixes ( * * UI helper: count VRF routes from BGP side * - * input: + * input: * * output * pALRcount count of active local routes @@ -5104,83 +4765,73 @@ rfapiDeleteRemotePrefixes ( * return value: * void --------------------------------------------*/ -void -rfapiCountAllItRoutes (int *pALRcount, /* active local routes */ - int *pARRcount, /* active remote routes */ - int *pHRcount, /* holddown routes */ - int *pIRcount) /* imported routes */ +void rfapiCountAllItRoutes(int *pALRcount, /* active local routes */ + int *pARRcount, /* active remote routes */ + int *pHRcount, /* holddown routes */ + int *pIRcount) /* imported routes */ { - struct bgp *bgp; - struct rfapi *h; - struct rfapi_import_table *it; - afi_t afi; - - int total_active_local = 0; - int total_active_remote = 0; - int total_holddown = 0; - int total_imported = 0; - - bgp = bgp_get_default (); /* assume 1 instance for now */ - assert (bgp); - - h = bgp->rfapi; - assert (h); - - /* - * Iterate over all import tables; do a filtered import - * for the afi/safi combination - */ - - for (it = h->imports; it; it = it->next) - { - - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - - total_active_local += it->local_count[afi]; - total_active_remote += it->remote_count[afi]; - total_holddown += it->holddown_count[afi]; - total_imported += it->imported_count[afi]; - - } - } - - void *cursor; - int rc; - - if (h->import_mac) - { - for (cursor = NULL, - rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor); - !rc; - rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor)) - { - - total_active_local += it->local_count[AFI_L2VPN]; - total_active_remote += it->remote_count[AFI_L2VPN]; - total_holddown += it->holddown_count[AFI_L2VPN]; - total_imported += it->imported_count[AFI_L2VPN]; - - } - } - - - if (pALRcount) - { - *pALRcount = total_active_local; - } - if (pARRcount) - { - *pARRcount = total_active_remote; - } - if (pHRcount) - { - *pHRcount = total_holddown; - } - if (pIRcount) - { - *pIRcount = total_imported; - } + struct bgp *bgp; + struct rfapi *h; + struct rfapi_import_table *it; + afi_t afi; + + int total_active_local = 0; + int total_active_remote = 0; + int total_holddown = 0; + int total_imported = 0; + + bgp = bgp_get_default(); /* assume 1 instance for now */ + assert(bgp); + + h = bgp->rfapi; + assert(h); + + /* + * Iterate over all import tables; do a filtered import + * for the afi/safi combination + */ + + for (it = h->imports; it; it = it->next) { + + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + + total_active_local += it->local_count[afi]; + total_active_remote += it->remote_count[afi]; + total_holddown += it->holddown_count[afi]; + total_imported += it->imported_count[afi]; + } + } + + void *cursor; + int rc; + + if (h->import_mac) { + for (cursor = NULL, + rc = skiplist_next(h->import_mac, NULL, (void **)&it, + &cursor); + !rc; rc = skiplist_next(h->import_mac, NULL, (void **)&it, + &cursor)) { + + total_active_local += it->local_count[AFI_L2VPN]; + total_active_remote += it->remote_count[AFI_L2VPN]; + total_holddown += it->holddown_count[AFI_L2VPN]; + total_imported += it->imported_count[AFI_L2VPN]; + } + } + + + if (pALRcount) { + *pALRcount = total_active_local; + } + if (pARRcount) { + *pARRcount = total_active_remote; + } + if (pHRcount) { + *pHRcount = total_holddown; + } + if (pIRcount) { + *pIRcount = total_imported; + } } /*------------------------------------------ @@ -5188,7 +4839,7 @@ rfapiCountAllItRoutes (int *pALRcount, /* active local routes */ * * calculate holddown value based on lifetime * - * input: + * input: * lifetime lifetime * * return value: @@ -5197,22 +4848,21 @@ rfapiCountAllItRoutes (int *pALRcount, /* active local routes */ * --------------------------------------------*/ /* hold down time maxes out at RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY */ -uint32_t -rfapiGetHolddownFromLifetime (uint32_t lifetime) +uint32_t rfapiGetHolddownFromLifetime(uint32_t lifetime) { - uint32_t factor; - struct bgp *bgp; - - bgp = bgp_get_default (); - if (bgp && bgp->rfapi_cfg) - factor = bgp->rfapi_cfg->rfp_cfg.holddown_factor; - else - factor = RFAPI_RFP_CFG_DEFAULT_HOLDDOWN_FACTOR; - - if (factor < 100 || lifetime < RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY) - lifetime = lifetime * factor / 100; - if (lifetime < RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY) - return lifetime; - else - return RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY; + uint32_t factor; + struct bgp *bgp; + + bgp = bgp_get_default(); + if (bgp && bgp->rfapi_cfg) + factor = bgp->rfapi_cfg->rfp_cfg.holddown_factor; + else + factor = RFAPI_RFP_CFG_DEFAULT_HOLDDOWN_FACTOR; + + if (factor < 100 || lifetime < RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY) + lifetime = lifetime * factor / 100; + if (lifetime < RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY) + return lifetime; + else + return RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY; } diff --git a/bgpd/rfapi/rfapi_import.h b/bgpd/rfapi/rfapi_import.h index 1888d5f25..fc5bb01ce 100644 --- a/bgpd/rfapi/rfapi_import.h +++ b/bgpd/rfapi/rfapi_import.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -34,72 +34,60 @@ * routes are not segregated by RD - the RD is stored in bgp_info_extra * and is needed to determine if two prefixes are the same. */ -struct rfapi_import_table -{ - struct rfapi_import_table *next; - struct rfapi_nve_group_cfg *rfg; - struct ecommunity *rt_import_list; /* copied from nve grp */ - int refcount; /* nve grps and nves */ - uint32_t l2_logical_net_id; /* L2 only: EVPN Eth Seg Id */ - struct route_table *imported_vpn[AFI_MAX]; - struct rfapi_monitor_vpn *vpn0_queries[AFI_MAX]; - struct rfapi_monitor_eth *eth0_queries; - struct route_table *imported_encap[AFI_MAX]; - struct skiplist *monitor_exterior_orphans; - int local_count[AFI_MAX]; - int remote_count[AFI_MAX]; - int holddown_count[AFI_MAX]; - int imported_count[AFI_MAX]; +struct rfapi_import_table { + struct rfapi_import_table *next; + struct rfapi_nve_group_cfg *rfg; + struct ecommunity *rt_import_list; /* copied from nve grp */ + int refcount; /* nve grps and nves */ + uint32_t l2_logical_net_id; /* L2 only: EVPN Eth Seg Id */ + struct route_table *imported_vpn[AFI_MAX]; + struct rfapi_monitor_vpn *vpn0_queries[AFI_MAX]; + struct rfapi_monitor_eth *eth0_queries; + struct route_table *imported_encap[AFI_MAX]; + struct skiplist *monitor_exterior_orphans; + int local_count[AFI_MAX]; + int remote_count[AFI_MAX]; + int holddown_count[AFI_MAX]; + int imported_count[AFI_MAX]; }; -#define RFAPI_LOCAL_BI(bi) \ - (((bi)->type == ZEBRA_ROUTE_BGP) && ((bi)->sub_type == BGP_ROUTE_RFP)) +#define RFAPI_LOCAL_BI(bi) \ + (((bi)->type == ZEBRA_ROUTE_BGP) && ((bi)->sub_type == BGP_ROUTE_RFP)) -#define RFAPI_DIRECT_IMPORT_BI(bi) \ - (((bi)->type == ZEBRA_ROUTE_BGP_DIRECT) || ((bi)->type == ZEBRA_ROUTE_BGP_DIRECT_EXT)) +#define RFAPI_DIRECT_IMPORT_BI(bi) \ + (((bi)->type == ZEBRA_ROUTE_BGP_DIRECT) \ + || ((bi)->type == ZEBRA_ROUTE_BGP_DIRECT_EXT)) -#define RFAPI_UPDATE_ITABLE_COUNT(bi, itable, afi, cnt) \ - if (RFAPI_LOCAL_BI(bi)) { \ - (itable)->local_count[(afi)] += (cnt); \ - } else { \ - if (RFAPI_DIRECT_IMPORT_BI(bi)) \ - (itable)->imported_count[(afi)] += (cnt); \ - else \ - (itable)->remote_count[(afi)] += (cnt); \ - } +#define RFAPI_UPDATE_ITABLE_COUNT(bi, itable, afi, cnt) \ + if (RFAPI_LOCAL_BI(bi)) { \ + (itable)->local_count[(afi)] += (cnt); \ + } else { \ + if (RFAPI_DIRECT_IMPORT_BI(bi)) \ + (itable)->imported_count[(afi)] += (cnt); \ + else \ + (itable)->remote_count[(afi)] += (cnt); \ + } -extern uint8_t -rfapiRfpCost (struct attr *attr); +extern uint8_t rfapiRfpCost(struct attr *attr); -extern void -rfapiDebugBacktrace (void); +extern void rfapiDebugBacktrace(void); -extern void -rfapiCheckRouteCount (void); +extern void rfapiCheckRouteCount(void); /* * Print BI in an Import Table */ -extern void -rfapiPrintBi (void *stream, struct bgp_info *bi); +extern void rfapiPrintBi(void *stream, struct bgp_info *bi); -extern void -rfapiShowImportTable ( - void *stream, - const char *label, - struct route_table *rt, - int isvpn); +extern void rfapiShowImportTable(void *stream, const char *label, + struct route_table *rt, int isvpn); extern struct rfapi_import_table * -rfapiImportTableRefAdd ( - struct bgp *bgp, - struct ecommunity *rt_import_list, - struct rfapi_nve_group_cfg *rfg); +rfapiImportTableRefAdd(struct bgp *bgp, struct ecommunity *rt_import_list, + struct rfapi_nve_group_cfg *rfg); -extern void -rfapiImportTableRefDelByIt ( - struct bgp *bgp, - struct rfapi_import_table *it_target); +extern void rfapiImportTableRefDelByIt(struct bgp *bgp, + struct rfapi_import_table *it_target); /* @@ -111,106 +99,78 @@ rfapiImportTableRefDelByIt ( * then return those, and also include all the non-removed routes from the * next less-specific node (i.e., this node's parent) at the end. */ -extern struct rfapi_next_hop_entry * -rfapiRouteNode2NextHopList ( - struct route_node *rn, - uint32_t lifetime, /* put into nexthop entries */ - struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ - struct route_table *rfd_rib_table, /* preload this NVE rib table */ - struct prefix *pfx_target_original); /* query target */ - -extern struct rfapi_next_hop_entry * -rfapiRouteTable2NextHopList ( - struct route_table *rt, - uint32_t lifetime, /* put into nexthop entries */ - struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ - struct route_table *rfd_rib_table, /* preload this NVE rib table */ - struct prefix *pfx_target_original); /* query target */ - -extern struct rfapi_next_hop_entry * -rfapiEthRouteTable2NextHopList ( - uint32_t logical_net_id, - struct rfapi_ip_prefix *rprefix, - uint32_t lifetime, /* put into nexthop entries */ - struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ - struct route_table *rib_route_table,/* preload NVE rib node */ - struct prefix *pfx_target_original); /* query target */ - -extern int -rfapiEcommunitiesIntersect (struct ecommunity *e1, struct ecommunity *e2); - -extern void -rfapiCheckRefcount (struct route_node *rn, safi_t safi, int lockoffset); - -extern int -rfapiHasNonRemovedRoutes (struct route_node *rn); - -extern int -rfapiProcessDeferredClose (struct thread *t); - -extern int -rfapiGetUnAddrOfVpnBi (struct bgp_info *bi, struct prefix *p); - -extern void -rfapiNexthop2Prefix (struct attr *attr, struct prefix *p); - -extern void -rfapiUnicastNexthop2Prefix ( - afi_t afi, - struct attr *attr, - struct prefix *p); +extern struct rfapi_next_hop_entry *rfapiRouteNode2NextHopList( + struct route_node *rn, uint32_t lifetime, /* put into nexthop entries */ + struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ + struct route_table *rfd_rib_table, /* preload this NVE rib table */ + struct prefix *pfx_target_original); /* query target */ + +extern struct rfapi_next_hop_entry *rfapiRouteTable2NextHopList( + struct route_table *rt, + uint32_t lifetime, /* put into nexthop entries */ + struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ + struct route_table *rfd_rib_table, /* preload this NVE rib table */ + struct prefix *pfx_target_original); /* query target */ + +extern struct rfapi_next_hop_entry *rfapiEthRouteTable2NextHopList( + uint32_t logical_net_id, struct rfapi_ip_prefix *rprefix, + uint32_t lifetime, /* put into nexthop entries */ + struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ + struct route_table *rib_route_table, /* preload NVE rib node */ + struct prefix *pfx_target_original); /* query target */ + +extern int rfapiEcommunitiesIntersect(struct ecommunity *e1, + struct ecommunity *e2); + +extern void rfapiCheckRefcount(struct route_node *rn, safi_t safi, + int lockoffset); + +extern int rfapiHasNonRemovedRoutes(struct route_node *rn); + +extern int rfapiProcessDeferredClose(struct thread *t); + +extern int rfapiGetUnAddrOfVpnBi(struct bgp_info *bi, struct prefix *p); + +extern void rfapiNexthop2Prefix(struct attr *attr, struct prefix *p); + +extern void rfapiUnicastNexthop2Prefix(afi_t afi, struct attr *attr, + struct prefix *p); /* Filtered Import Function actions */ #define FIF_ACTION_UPDATE 0 #define FIF_ACTION_WITHDRAW 1 #define FIF_ACTION_KILL 2 -extern void -rfapiBgpInfoFilteredImportVPN ( - struct rfapi_import_table *import_table, - int action, - struct peer *peer, - void *rfd, /* set for looped back routes */ - struct prefix *p, - struct prefix *aux_prefix, /* AFI_ETHER: optional IP */ - afi_t afi, - struct prefix_rd *prd, - struct attr *attr, /* part of bgp_info */ - u_char type, /* part of bgp_info */ - u_char sub_type, /* part of bgp_info */ - uint32_t *label); /* part of bgp_info */ - -extern struct rfapi_next_hop_entry * -rfapiEthRouteNode2NextHopList ( - struct route_node *rn, - struct rfapi_ip_prefix *rprefix, - uint32_t lifetime, /* put into nexthop entries */ - struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ - struct route_table *rib_route_table,/* preload NVE rib table */ - struct prefix *pfx_target_original); /* query target */ +extern void rfapiBgpInfoFilteredImportVPN( + struct rfapi_import_table *import_table, int action, struct peer *peer, + void *rfd, /* set for looped back routes */ + struct prefix *p, + struct prefix *aux_prefix, /* AFI_ETHER: optional IP */ + afi_t afi, struct prefix_rd *prd, + struct attr *attr, /* part of bgp_info */ + u_char type, /* part of bgp_info */ + u_char sub_type, /* part of bgp_info */ + uint32_t *label); /* part of bgp_info */ -extern struct rfapi_import_table * -rfapiMacImportTableGetNoAlloc ( - struct bgp *bgp, - uint32_t lni); +extern struct rfapi_next_hop_entry *rfapiEthRouteNode2NextHopList( + struct route_node *rn, struct rfapi_ip_prefix *rprefix, + uint32_t lifetime, /* put into nexthop entries */ + struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */ + struct route_table *rib_route_table, /* preload NVE rib table */ + struct prefix *pfx_target_original); /* query target */ -extern struct rfapi_import_table * -rfapiMacImportTableGet ( - struct bgp *bgp, - uint32_t lni); +extern struct rfapi_import_table *rfapiMacImportTableGetNoAlloc(struct bgp *bgp, + uint32_t lni); + +extern struct rfapi_import_table *rfapiMacImportTableGet(struct bgp *bgp, + uint32_t lni); -extern int -rfapiGetL2o ( - struct attr *attr, - struct rfapi_l2address_option *l2o); +extern int rfapiGetL2o(struct attr *attr, struct rfapi_l2address_option *l2o); -extern int rfapiEcommunityGetLNI ( - struct ecommunity *ecom, - uint32_t *lni); +extern int rfapiEcommunityGetLNI(struct ecommunity *ecom, uint32_t *lni); -extern int rfapiEcommunityGetEthernetTag ( - struct ecommunity *ecom, - uint16_t * tag_id); +extern int rfapiEcommunityGetEthernetTag(struct ecommunity *ecom, + uint16_t *tag_id); /* enable for debugging; disable for performance */ #if 0 @@ -224,7 +184,7 @@ extern int rfapiEcommunityGetEthernetTag ( * * UI helper: For use by the "clear vnc prefixes" command * - * input: + * input: * un if set, tunnel must match this prefix * vn if set, nexthop prefix must match this prefix * p if set, prefix must match this prefix @@ -239,25 +199,21 @@ extern int rfapiEcommunityGetEthernetTag ( * return value: * void --------------------------------------------*/ -extern void -rfapiDeleteRemotePrefixes ( - struct prefix *un, - struct prefix *vn, - struct prefix *p, - struct rfapi_import_table *it, - int delete_active, - int delete_holddown, - uint32_t *pARcount, /* active routes */ - uint32_t *pAHcount, /* active nves */ - uint32_t *pHRcount, /* holddown routes */ - uint32_t *pHHcount); /* holddown nves */ +extern void rfapiDeleteRemotePrefixes(struct prefix *un, struct prefix *vn, + struct prefix *p, + struct rfapi_import_table *it, + int delete_active, int delete_holddown, + uint32_t *pARcount, /* active routes */ + uint32_t *pAHcount, /* active nves */ + uint32_t *pHRcount, /* holddown routes */ + uint32_t *pHHcount); /* holddown nves */ /*------------------------------------------ * rfapiCountAllItRoutes * * UI helper: count VRF routes from BGP side * - * input: + * input: * * output * pARcount count of active routes @@ -267,19 +223,17 @@ rfapiDeleteRemotePrefixes ( * return value: * void --------------------------------------------*/ -extern void -rfapiCountAllItRoutes ( - int *pALRcount, /* active local routes */ - int *pARRcount, /* active remote routes */ - int *pHRcount, /* holddown routes */ - int *pIRcount); /* direct imported routes */ +extern void rfapiCountAllItRoutes(int *pALRcount, /* active local routes */ + int *pARRcount, /* active remote routes */ + int *pHRcount, /* holddown routes */ + int *pIRcount); /* direct imported routes */ /*------------------------------------------ * rfapiGetHolddownFromLifetime * * calculate holddown value based on lifetime * - * input: + * input: * lifetime lifetime * * return value: @@ -287,7 +241,6 @@ rfapiCountAllItRoutes ( * and RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY * --------------------------------------------*/ -extern uint32_t -rfapiGetHolddownFromLifetime (uint32_t lifetime); +extern uint32_t rfapiGetHolddownFromLifetime(uint32_t lifetime); #endif /* QUAGGA_HGP_RFAPI_IMPORT_H */ diff --git a/bgpd/rfapi/rfapi_monitor.c b/bgpd/rfapi/rfapi_monitor.c index 275e44896..9c0d9da6f 100644 --- a/bgpd/rfapi/rfapi_monitor.c +++ b/bgpd/rfapi/rfapi_monitor.c @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -54,49 +54,44 @@ #define DEBUG_DUP_CHECK 0 #define DEBUG_ETH_SL 0 -static void -rfapiMonitorTimerRestart (struct rfapi_monitor_vpn *m); +static void rfapiMonitorTimerRestart(struct rfapi_monitor_vpn *m); -static void -rfapiMonitorEthTimerRestart (struct rfapi_monitor_eth *m); +static void rfapiMonitorEthTimerRestart(struct rfapi_monitor_eth *m); /* * Forward declarations */ -static void -rfapiMonitorEthDetachImport (struct bgp *bgp, struct rfapi_monitor_eth *mon); +static void rfapiMonitorEthDetachImport(struct bgp *bgp, + struct rfapi_monitor_eth *mon); #if DEBUG_ETH_SL /* * Debug function, special case */ -void -rfapiMonitorEthSlCheck( - struct route_node *rn, - const char *tag1, - const char *tag2) +void rfapiMonitorEthSlCheck(struct route_node *rn, const char *tag1, + const char *tag2) { - struct route_node *rn_saved = NULL; - static struct skiplist *sl_saved = NULL; - struct skiplist *sl; - - if (!rn) - return; - - if (rn_saved && (rn != rn_saved)) - return; - - if (!rn_saved) - rn_saved = rn; - - sl = RFAPI_MONITOR_ETH(rn); - if (sl || sl_saved) - { - vnc_zlog_debug_verbose("%s[%s%s]: rn=%p, rn->lock=%d, old sl=%p, new sl=%p", - __func__, (tag1? tag1: ""), (tag2? tag2: ""), rn, rn->lock, - sl_saved, sl); - sl_saved = sl; - } + struct route_node *rn_saved = NULL; + static struct skiplist *sl_saved = NULL; + struct skiplist *sl; + + if (!rn) + return; + + if (rn_saved && (rn != rn_saved)) + return; + + if (!rn_saved) + rn_saved = rn; + + sl = RFAPI_MONITOR_ETH(rn); + if (sl || sl_saved) { + vnc_zlog_debug_verbose( + "%s[%s%s]: rn=%p, rn->lock=%d, old sl=%p, new sl=%p", + __func__, (tag1 ? tag1 : ""), (tag2 ? tag2 : ""), rn, + rn->lock, sl_saved, sl); + sl_saved = sl; + } } #endif @@ -104,13 +99,12 @@ rfapiMonitorEthSlCheck( * Debugging function that aborts when it finds monitors whose * "next" pointer * references themselves */ -void -rfapiMonitorLoopCheck (struct rfapi_monitor_vpn *mchain) +void rfapiMonitorLoopCheck(struct rfapi_monitor_vpn *mchain) { - struct rfapi_monitor_vpn *m; + struct rfapi_monitor_vpn *m; - for (m = mchain; m; m = m->next) - assert (m != m->next); + for (m = mchain; m; m = m->next) + assert(m != m->next); } #if DEBUG_DUP_CHECK @@ -118,381 +112,349 @@ rfapiMonitorLoopCheck (struct rfapi_monitor_vpn *mchain) * Debugging code: see if a monitor is mentioned more than once * in a HD's monitor list */ -void -rfapiMonitorDupCheck (struct bgp *bgp) +void rfapiMonitorDupCheck(struct bgp *bgp) { - struct listnode *hnode; - struct rfapi_descriptor *rfd; - - for (ALL_LIST_ELEMENTS_RO (&bgp->rfapi->descriptors, hnode, rfd)) - { - struct route_node *mrn; - - if (!rfd->mon) - continue; - - for (mrn = route_top (rfd->mon); mrn; mrn = route_next (mrn)) - { - struct rfapi_monitor_vpn *m; - for (m = (struct rfapi_monitor_vpn *) (mrn->info); m; m = m->next) - m->dcount = 0; - } - } - - for (ALL_LIST_ELEMENTS_RO (&bgp->rfapi->descriptors, hnode, rfd)) - { - struct route_node *mrn; - - if (!rfd->mon) - continue; - - for (mrn = route_top (rfd->mon); mrn; mrn = route_next (mrn)) - { - struct rfapi_monitor_vpn *m; - - for (m = (struct rfapi_monitor_vpn *) (mrn->info); m; m = m->next) - assert (++m->dcount == 1); - } - } + struct listnode *hnode; + struct rfapi_descriptor *rfd; + + for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, hnode, rfd)) { + struct route_node *mrn; + + if (!rfd->mon) + continue; + + for (mrn = route_top(rfd->mon); mrn; mrn = route_next(mrn)) { + struct rfapi_monitor_vpn *m; + for (m = (struct rfapi_monitor_vpn *)(mrn->info); m; + m = m->next) + m->dcount = 0; + } + } + + for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, hnode, rfd)) { + struct route_node *mrn; + + if (!rfd->mon) + continue; + + for (mrn = route_top(rfd->mon); mrn; mrn = route_next(mrn)) { + struct rfapi_monitor_vpn *m; + + for (m = (struct rfapi_monitor_vpn *)(mrn->info); m; + m = m->next) + assert(++m->dcount == 1); + } + } } #endif /* debug */ -void -rfapiMonitorCleanCheck (struct bgp *bgp) +void rfapiMonitorCleanCheck(struct bgp *bgp) { - struct listnode *hnode; - struct rfapi_descriptor *rfd; + struct listnode *hnode; + struct rfapi_descriptor *rfd; - for (ALL_LIST_ELEMENTS_RO (&bgp->rfapi->descriptors, hnode, rfd)) - { - assert (!rfd->import_table->vpn0_queries[AFI_IP]); - assert (!rfd->import_table->vpn0_queries[AFI_IP6]); + for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, hnode, rfd)) { + assert(!rfd->import_table->vpn0_queries[AFI_IP]); + assert(!rfd->import_table->vpn0_queries[AFI_IP6]); - struct route_node *rn; + struct route_node *rn; - for (rn = route_top (rfd->import_table->imported_vpn[AFI_IP]); rn; - rn = route_next (rn)) - { + for (rn = route_top(rfd->import_table->imported_vpn[AFI_IP]); + rn; rn = route_next(rn)) { - assert (!RFAPI_MONITOR_VPN (rn)); - } - for (rn = route_top (rfd->import_table->imported_vpn[AFI_IP6]); rn; - rn = route_next (rn)) - { + assert(!RFAPI_MONITOR_VPN(rn)); + } + for (rn = route_top(rfd->import_table->imported_vpn[AFI_IP6]); + rn; rn = route_next(rn)) { - assert (!RFAPI_MONITOR_VPN (rn)); - } - } + assert(!RFAPI_MONITOR_VPN(rn)); + } + } } /* debug */ -void -rfapiMonitorCheckAttachAllowed (void) +void rfapiMonitorCheckAttachAllowed(void) { - struct bgp *bgp = bgp_get_default (); - assert (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)); + struct bgp *bgp = bgp_get_default(); + assert(!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)); } -void -rfapiMonitorExtraFlush (safi_t safi, struct route_node *rn) +void rfapiMonitorExtraFlush(safi_t safi, struct route_node *rn) { - struct rfapi_it_extra *hie; - struct rfapi_monitor_vpn *v; - struct rfapi_monitor_vpn *v_next; - struct rfapi_monitor_encap *e = NULL; - struct rfapi_monitor_encap *e_next = NULL; - - if (!rn) - return; - - if (!rn->aggregate) - return; - - hie = (struct rfapi_it_extra *) (rn->aggregate); - - switch (safi) - { - case SAFI_ENCAP: - for (e = hie->u.encap.e; e; e = e_next) - { - e_next = e->next; - e->next = NULL; - XFREE (MTYPE_RFAPI_MONITOR_ENCAP, e); - route_unlock_node (rn); - } - hie->u.encap.e = NULL; - break; - - case SAFI_MPLS_VPN: - for (v = hie->u.vpn.v; v; v = v_next) - { - v_next = v->next; - v->next = NULL; - XFREE (MTYPE_RFAPI_MONITOR, e); - route_unlock_node (rn); - } - hie->u.vpn.v = NULL; - if (hie->u.vpn.e.source) - { - while (!skiplist_delete_first (hie->u.vpn.e.source)) - { - route_unlock_node (rn); - } - skiplist_free (hie->u.vpn.e.source); - hie->u.vpn.e.source = NULL; - route_unlock_node (rn); - } - if (hie->u.vpn.idx_rd) - { - /* looping through bi->extra->vnc.import.rd is tbd */ - while (!skiplist_delete_first (hie->u.vpn.idx_rd)) - { - route_unlock_node (rn); - } - skiplist_free (hie->u.vpn.idx_rd); - hie->u.vpn.idx_rd = NULL; - route_unlock_node (rn); - } - if (hie->u.vpn.mon_eth) - { - while (!skiplist_delete_first (hie->u.vpn.mon_eth)) - { - route_unlock_node (rn); - } - skiplist_free (hie->u.vpn.mon_eth); - hie->u.vpn.mon_eth = NULL; - route_unlock_node (rn); - } - break; - - default: - assert (0); - } - XFREE (MTYPE_RFAPI_IT_EXTRA, hie); - rn->aggregate = NULL; - route_unlock_node (rn); + struct rfapi_it_extra *hie; + struct rfapi_monitor_vpn *v; + struct rfapi_monitor_vpn *v_next; + struct rfapi_monitor_encap *e = NULL; + struct rfapi_monitor_encap *e_next = NULL; + + if (!rn) + return; + + if (!rn->aggregate) + return; + + hie = (struct rfapi_it_extra *)(rn->aggregate); + + switch (safi) { + case SAFI_ENCAP: + for (e = hie->u.encap.e; e; e = e_next) { + e_next = e->next; + e->next = NULL; + XFREE(MTYPE_RFAPI_MONITOR_ENCAP, e); + route_unlock_node(rn); + } + hie->u.encap.e = NULL; + break; + + case SAFI_MPLS_VPN: + for (v = hie->u.vpn.v; v; v = v_next) { + v_next = v->next; + v->next = NULL; + XFREE(MTYPE_RFAPI_MONITOR, e); + route_unlock_node(rn); + } + hie->u.vpn.v = NULL; + if (hie->u.vpn.e.source) { + while (!skiplist_delete_first(hie->u.vpn.e.source)) { + route_unlock_node(rn); + } + skiplist_free(hie->u.vpn.e.source); + hie->u.vpn.e.source = NULL; + route_unlock_node(rn); + } + if (hie->u.vpn.idx_rd) { + /* looping through bi->extra->vnc.import.rd is tbd */ + while (!skiplist_delete_first(hie->u.vpn.idx_rd)) { + route_unlock_node(rn); + } + skiplist_free(hie->u.vpn.idx_rd); + hie->u.vpn.idx_rd = NULL; + route_unlock_node(rn); + } + if (hie->u.vpn.mon_eth) { + while (!skiplist_delete_first(hie->u.vpn.mon_eth)) { + route_unlock_node(rn); + } + skiplist_free(hie->u.vpn.mon_eth); + hie->u.vpn.mon_eth = NULL; + route_unlock_node(rn); + } + break; + + default: + assert(0); + } + XFREE(MTYPE_RFAPI_IT_EXTRA, hie); + rn->aggregate = NULL; + route_unlock_node(rn); } /* * If the child lists are empty, release the rfapi_it_extra struct */ -void -rfapiMonitorExtraPrune (safi_t safi, struct route_node *rn) +void rfapiMonitorExtraPrune(safi_t safi, struct route_node *rn) { - struct rfapi_it_extra *hie; - - if (!rn) - return; - - if (!rn->aggregate) - return; - - hie = (struct rfapi_it_extra *) (rn->aggregate); - - switch (safi) - { - case SAFI_ENCAP: - if (hie->u.encap.e) - return; - break; - - case SAFI_MPLS_VPN: - if (hie->u.vpn.v) - return; - if (hie->u.vpn.mon_eth) - { - if (skiplist_count (hie->u.vpn.mon_eth)) - return; - skiplist_free (hie->u.vpn.mon_eth); - hie->u.vpn.mon_eth = NULL; - route_unlock_node (rn); /* uncount skiplist */ - } - if (hie->u.vpn.e.source) - { - if (skiplist_count (hie->u.vpn.e.source)) - return; - skiplist_free (hie->u.vpn.e.source); - hie->u.vpn.e.source = NULL; - route_unlock_node (rn); - } - if (hie->u.vpn.idx_rd) - { - if (skiplist_count (hie->u.vpn.idx_rd)) - return; - skiplist_free (hie->u.vpn.idx_rd); - hie->u.vpn.idx_rd = NULL; - route_unlock_node (rn); - } - if (hie->u.vpn.mon_eth) - { - if (skiplist_count (hie->u.vpn.mon_eth)) - return; - skiplist_free (hie->u.vpn.mon_eth); - hie->u.vpn.mon_eth = NULL; - route_unlock_node (rn); - } - break; - - default: - assert (0); - } - XFREE (MTYPE_RFAPI_IT_EXTRA, hie); - rn->aggregate = NULL; - route_unlock_node (rn); + struct rfapi_it_extra *hie; + + if (!rn) + return; + + if (!rn->aggregate) + return; + + hie = (struct rfapi_it_extra *)(rn->aggregate); + + switch (safi) { + case SAFI_ENCAP: + if (hie->u.encap.e) + return; + break; + + case SAFI_MPLS_VPN: + if (hie->u.vpn.v) + return; + if (hie->u.vpn.mon_eth) { + if (skiplist_count(hie->u.vpn.mon_eth)) + return; + skiplist_free(hie->u.vpn.mon_eth); + hie->u.vpn.mon_eth = NULL; + route_unlock_node(rn); /* uncount skiplist */ + } + if (hie->u.vpn.e.source) { + if (skiplist_count(hie->u.vpn.e.source)) + return; + skiplist_free(hie->u.vpn.e.source); + hie->u.vpn.e.source = NULL; + route_unlock_node(rn); + } + if (hie->u.vpn.idx_rd) { + if (skiplist_count(hie->u.vpn.idx_rd)) + return; + skiplist_free(hie->u.vpn.idx_rd); + hie->u.vpn.idx_rd = NULL; + route_unlock_node(rn); + } + if (hie->u.vpn.mon_eth) { + if (skiplist_count(hie->u.vpn.mon_eth)) + return; + skiplist_free(hie->u.vpn.mon_eth); + hie->u.vpn.mon_eth = NULL; + route_unlock_node(rn); + } + break; + + default: + assert(0); + } + XFREE(MTYPE_RFAPI_IT_EXTRA, hie); + rn->aggregate = NULL; + route_unlock_node(rn); } /* * returns locked node */ -struct route_node * -rfapiMonitorGetAttachNode (struct rfapi_descriptor *rfd, struct prefix *p) +struct route_node *rfapiMonitorGetAttachNode(struct rfapi_descriptor *rfd, + struct prefix *p) { - afi_t afi; - struct route_node *rn; - - if (RFAPI_0_PREFIX (p)) - { - assert (1); - } - - afi = family2afi (p->family); - assert (afi); - - /* - * It's possible that even though there is a route at this node, - * there are no routes with valid UN addresses (i.e,. with no - * valid tunnel routes). Check for that and walk back up the - * tree if necessary. - * - * When the outer loop completes, the matched node, if any, is - * locked (i.e., its reference count has been incremented) to - * account for the VPN monitor we are about to attach. - * - * if a monitor is moved to another node, there must be - * corresponding unlock/locks - */ - for (rn = route_node_match (rfd->import_table->imported_vpn[afi], p); rn;) - { - - struct bgp_info *bi; - struct prefix pfx_dummy; - - /* TBD update this code to use new valid_interior_count */ - for (bi = rn->info; bi; bi = bi->next) - { - /* - * If there is a cached ENCAP UN address, it's a usable - * VPN route - */ - if (bi->extra && bi->extra->vnc.import.un_family) - { - break; - } - - /* - * Or if there is a valid Encap Attribute tunnel subtlv address, - * it's a usable VPN route. - */ - if (!rfapiGetVncTunnelUnAddr (bi->attr, &pfx_dummy)) - { - break; - } - } - if (bi) - break; - - route_unlock_node (rn); - if ((rn = rn->parent)) - { - route_lock_node (rn); - } - } - - if (!rn) - { - struct prefix pfx_default; - - memset (&pfx_default, 0, sizeof (pfx_default)); - pfx_default.family = p->family; - - /* creates default node if none exists, and increments ref count */ - rn = - route_node_get (rfd->import_table->imported_vpn[afi], &pfx_default); - } - - return rn; + afi_t afi; + struct route_node *rn; + + if (RFAPI_0_PREFIX(p)) { + assert(1); + } + + afi = family2afi(p->family); + assert(afi); + + /* + * It's possible that even though there is a route at this node, + * there are no routes with valid UN addresses (i.e,. with no + * valid tunnel routes). Check for that and walk back up the + * tree if necessary. + * + * When the outer loop completes, the matched node, if any, is + * locked (i.e., its reference count has been incremented) to + * account for the VPN monitor we are about to attach. + * + * if a monitor is moved to another node, there must be + * corresponding unlock/locks + */ + for (rn = route_node_match(rfd->import_table->imported_vpn[afi], p); + rn;) { + + struct bgp_info *bi; + struct prefix pfx_dummy; + + /* TBD update this code to use new valid_interior_count */ + for (bi = rn->info; bi; bi = bi->next) { + /* + * If there is a cached ENCAP UN address, it's a usable + * VPN route + */ + if (bi->extra && bi->extra->vnc.import.un_family) { + break; + } + + /* + * Or if there is a valid Encap Attribute tunnel subtlv + * address, + * it's a usable VPN route. + */ + if (!rfapiGetVncTunnelUnAddr(bi->attr, &pfx_dummy)) { + break; + } + } + if (bi) + break; + + route_unlock_node(rn); + if ((rn = rn->parent)) { + route_lock_node(rn); + } + } + + if (!rn) { + struct prefix pfx_default; + + memset(&pfx_default, 0, sizeof(pfx_default)); + pfx_default.family = p->family; + + /* creates default node if none exists, and increments ref count + */ + rn = route_node_get(rfd->import_table->imported_vpn[afi], + &pfx_default); + } + + return rn; } -/* +/* * If this function happens to attach the monitor to a radix tree * node (as opposed to the 0-prefix list), the node pointer is * returned (for the benefit of caller which might like to use it * to generate an immediate query response). */ -static struct route_node * -rfapiMonitorAttachImport (struct rfapi_descriptor *rfd, - struct rfapi_monitor_vpn *m) +static struct route_node *rfapiMonitorAttachImport(struct rfapi_descriptor *rfd, + struct rfapi_monitor_vpn *m) { - struct route_node *rn; - - rfapiMonitorCheckAttachAllowed (); - - if (RFAPI_0_PREFIX (&m->p)) - { - /* - * Add new monitor entry to vpn0 list - */ - afi_t afi; - - afi = family2afi (m->p.family); - assert (afi); - - m->next = rfd->import_table->vpn0_queries[afi]; - rfd->import_table->vpn0_queries[afi] = m; - vnc_zlog_debug_verbose ("%s: attached monitor %p to vpn0 list", __func__, m); - return NULL; - } - - /* - * Attach new monitor entry to import table node - */ - rn = rfapiMonitorGetAttachNode (rfd, &m->p); /* returns locked rn */ - m->node = rn; - m->next = RFAPI_MONITOR_VPN (rn); - RFAPI_MONITOR_VPN_W_ALLOC (rn) = m; - RFAPI_CHECK_REFCOUNT (rn, SAFI_MPLS_VPN, 0); - vnc_zlog_debug_verbose ("%s: attached monitor %p to rn %p", __func__, m, rn); - return rn; + struct route_node *rn; + + rfapiMonitorCheckAttachAllowed(); + + if (RFAPI_0_PREFIX(&m->p)) { + /* + * Add new monitor entry to vpn0 list + */ + afi_t afi; + + afi = family2afi(m->p.family); + assert(afi); + + m->next = rfd->import_table->vpn0_queries[afi]; + rfd->import_table->vpn0_queries[afi] = m; + vnc_zlog_debug_verbose("%s: attached monitor %p to vpn0 list", + __func__, m); + return NULL; + } + + /* + * Attach new monitor entry to import table node + */ + rn = rfapiMonitorGetAttachNode(rfd, &m->p); /* returns locked rn */ + m->node = rn; + m->next = RFAPI_MONITOR_VPN(rn); + RFAPI_MONITOR_VPN_W_ALLOC(rn) = m; + RFAPI_CHECK_REFCOUNT(rn, SAFI_MPLS_VPN, 0); + vnc_zlog_debug_verbose("%s: attached monitor %p to rn %p", __func__, m, + rn); + return rn; } /* * reattach monitors for this HD to import table */ -void -rfapiMonitorAttachImportHd (struct rfapi_descriptor *rfd) +void rfapiMonitorAttachImportHd(struct rfapi_descriptor *rfd) { - struct route_node *mrn; - - if (!rfd->mon) - { - /* - * No monitors for this HD - */ - return; - } - - for (mrn = route_top (rfd->mon); mrn; mrn = route_next (mrn)) - { - - if (!mrn->info) - continue; - - (void) rfapiMonitorAttachImport (rfd, - (struct rfapi_monitor_vpn - *) (mrn->info)); - } + struct route_node *mrn; + + if (!rfd->mon) { + /* + * No monitors for this HD + */ + return; + } + + for (mrn = route_top(rfd->mon); mrn; mrn = route_next(mrn)) { + + if (!mrn->info) + continue; + + (void)rfapiMonitorAttachImport( + rfd, (struct rfapi_monitor_vpn *)(mrn->info)); + } } /* @@ -506,1198 +468,1123 @@ rfapiMonitorAttachImportHd (struct rfapi_descriptor *rfd) * caller will have to do its own lookup. */ struct route_node * -rfapiMonitorAdd ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct prefix *p) +rfapiMonitorAdd(struct bgp *bgp, struct rfapi_descriptor *rfd, struct prefix *p) { - struct rfapi_monitor_vpn *m; - struct route_node *rn; - - /* - * Initialize nve's monitor list if needed - * NB use the same radix tree for IPv4 and IPv6 targets. - * The prefix will always have full-length mask (/32, /128) - * or be 0/0 so they won't get mixed up. - */ - if (!rfd->mon) - { - rfd->mon = route_table_init (); - } - rn = route_node_get (rfd->mon, p); - if (rn->info) - { - /* - * received this query before, no further action needed - */ - rfapiMonitorTimerRestart ((struct rfapi_monitor_vpn *) rn->info); - route_unlock_node (rn); - return NULL; - } - - /* - * New query for this nve, record it in the HD - */ - rn->info = XCALLOC (MTYPE_RFAPI_MONITOR, sizeof (struct rfapi_monitor_vpn)); - m = (struct rfapi_monitor_vpn *) (rn->info); - m->rfd = rfd; - prefix_copy (&m->p, p); - - ++rfd->monitor_count; - ++bgp->rfapi->monitor_count; - - rfapiMonitorTimerRestart (m); - - if (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE) - { - /* - * callbacks turned off, so don't attach monitor to import table - */ - return NULL; - } - - - /* - * attach to import table - */ - return rfapiMonitorAttachImport (rfd, m); + struct rfapi_monitor_vpn *m; + struct route_node *rn; + + /* + * Initialize nve's monitor list if needed + * NB use the same radix tree for IPv4 and IPv6 targets. + * The prefix will always have full-length mask (/32, /128) + * or be 0/0 so they won't get mixed up. + */ + if (!rfd->mon) { + rfd->mon = route_table_init(); + } + rn = route_node_get(rfd->mon, p); + if (rn->info) { + /* + * received this query before, no further action needed + */ + rfapiMonitorTimerRestart((struct rfapi_monitor_vpn *)rn->info); + route_unlock_node(rn); + return NULL; + } + + /* + * New query for this nve, record it in the HD + */ + rn->info = + XCALLOC(MTYPE_RFAPI_MONITOR, sizeof(struct rfapi_monitor_vpn)); + m = (struct rfapi_monitor_vpn *)(rn->info); + m->rfd = rfd; + prefix_copy(&m->p, p); + + ++rfd->monitor_count; + ++bgp->rfapi->monitor_count; + + rfapiMonitorTimerRestart(m); + + if (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE) { + /* + * callbacks turned off, so don't attach monitor to import table + */ + return NULL; + } + + + /* + * attach to import table + */ + return rfapiMonitorAttachImport(rfd, m); } /* * returns monitor pointer if found, NULL if not */ static struct rfapi_monitor_vpn * -rfapiMonitorDetachImport (struct rfapi_monitor_vpn *m) +rfapiMonitorDetachImport(struct rfapi_monitor_vpn *m) { - struct rfapi_monitor_vpn *prev; - struct rfapi_monitor_vpn *this = NULL; - - if (RFAPI_0_PREFIX (&m->p)) - { - afi_t afi; - - /* - * 0-prefix monitors are stored in a special list and not - * in the import VPN tree - */ - - afi = family2afi (m->p.family); - assert (afi); - - if (m->rfd->import_table) - { - for (prev = NULL, this = m->rfd->import_table->vpn0_queries[afi]; - this; prev = this, this = this->next) - { - - if (this == m) - break; - } - if (this) - { - if (!prev) - { - m->rfd->import_table->vpn0_queries[afi] = this->next; - } - else - { - prev->next = this->next; - } - } - } - } - else - { - - if (m->node) - { - for (prev = NULL, - this = RFAPI_MONITOR_VPN (m->node); - this; prev = this, this = this->next) - { - - if (this == m) - break; - } - if (this) - { - if (prev) - { - prev->next = this->next; - } - else - { - RFAPI_MONITOR_VPN_W_ALLOC (m->node) = this->next; - } - RFAPI_CHECK_REFCOUNT (m->node, SAFI_MPLS_VPN, 1); - route_unlock_node (m->node); - } - m->node = NULL; - } - } - return this; + struct rfapi_monitor_vpn *prev; + struct rfapi_monitor_vpn *this = NULL; + + if (RFAPI_0_PREFIX(&m->p)) { + afi_t afi; + + /* + * 0-prefix monitors are stored in a special list and not + * in the import VPN tree + */ + + afi = family2afi(m->p.family); + assert(afi); + + if (m->rfd->import_table) { + for (prev = NULL, + this = m->rfd->import_table->vpn0_queries[afi]; + this; prev = this, this = this->next) { + + if (this == m) + break; + } + if (this) { + if (!prev) { + m->rfd->import_table + ->vpn0_queries[afi] = + this->next; + } else { + prev->next = this->next; + } + } + } + } else { + + if (m->node) { + for (prev = NULL, this = RFAPI_MONITOR_VPN(m->node); + this; prev = this, this = this->next) { + + if (this == m) + break; + } + if (this) { + if (prev) { + prev->next = this->next; + } else { + RFAPI_MONITOR_VPN_W_ALLOC(m->node) = + this->next; + } + RFAPI_CHECK_REFCOUNT(m->node, SAFI_MPLS_VPN, 1); + route_unlock_node(m->node); + } + m->node = NULL; + } + } + return this; } -void -rfapiMonitorDetachImportHd (struct rfapi_descriptor *rfd) +void rfapiMonitorDetachImportHd(struct rfapi_descriptor *rfd) { - struct route_node *rn; - - if (!rfd->mon) - return; - - for (rn = route_top (rfd->mon); rn; rn = route_next (rn)) - { - if (rn->info) - { - rfapiMonitorDetachImport ((struct rfapi_monitor_vpn *) (rn->info)); - } - } + struct route_node *rn; + + if (!rfd->mon) + return; + + for (rn = route_top(rfd->mon); rn; rn = route_next(rn)) { + if (rn->info) { + rfapiMonitorDetachImport( + (struct rfapi_monitor_vpn *)(rn->info)); + } + } } -void -rfapiMonitorDel ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct prefix *p) +void rfapiMonitorDel(struct bgp *bgp, struct rfapi_descriptor *rfd, + struct prefix *p) { - struct route_node *rn; - struct rfapi_monitor_vpn *m; - - assert (rfd->mon); - rn = route_node_get (rfd->mon, p); /* locks node */ - m = rn->info; - - assert (m); - - /* - * remove from import table - */ - if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)) - { - rfapiMonitorDetachImport (m); - } - - if (m->timer) - { - thread_cancel (m->timer); - m->timer = NULL; - } - - /* - * remove from rfd list - */ - XFREE (MTYPE_RFAPI_MONITOR, m); - rn->info = NULL; - route_unlock_node (rn); /* undo original lock when created */ - route_unlock_node (rn); /* undo lock in route_node_get */ - - --rfd->monitor_count; - --bgp->rfapi->monitor_count; + struct route_node *rn; + struct rfapi_monitor_vpn *m; + + assert(rfd->mon); + rn = route_node_get(rfd->mon, p); /* locks node */ + m = rn->info; + + assert(m); + + /* + * remove from import table + */ + if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)) { + rfapiMonitorDetachImport(m); + } + + if (m->timer) { + thread_cancel(m->timer); + m->timer = NULL; + } + + /* + * remove from rfd list + */ + XFREE(MTYPE_RFAPI_MONITOR, m); + rn->info = NULL; + route_unlock_node(rn); /* undo original lock when created */ + route_unlock_node(rn); /* undo lock in route_node_get */ + + --rfd->monitor_count; + --bgp->rfapi->monitor_count; } /* * returns count of monitors deleted */ -int -rfapiMonitorDelHd (struct rfapi_descriptor *rfd) +int rfapiMonitorDelHd(struct rfapi_descriptor *rfd) { - struct route_node *rn; - struct bgp *bgp; - int count = 0; - - vnc_zlog_debug_verbose ("%s: entry rfd=%p", __func__, rfd); - - bgp = bgp_get_default (); - - if (rfd->mon) - { - for (rn = route_top (rfd->mon); rn; rn = route_next (rn)) - { - struct rfapi_monitor_vpn *m; - if ((m = rn->info)) - { - if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)) - { - rfapiMonitorDetachImport (m); - } - - if (m->timer) - { - thread_cancel (m->timer); - m->timer = NULL; - } - - XFREE (MTYPE_RFAPI_MONITOR, m); - rn->info = NULL; - route_unlock_node (rn); /* undo original lock when created */ - ++count; - --rfd->monitor_count; - --bgp->rfapi->monitor_count; - } - } - route_table_finish (rfd->mon); - rfd->mon = NULL; - } - - if (rfd->mon_eth) - { - - struct rfapi_monitor_eth *mon_eth; - - while (!skiplist_first (rfd->mon_eth, NULL, (void **) &mon_eth)) - { - - int rc; - - if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)) - { - rfapiMonitorEthDetachImport (bgp, mon_eth); - } - else - { + struct route_node *rn; + struct bgp *bgp; + int count = 0; + + vnc_zlog_debug_verbose("%s: entry rfd=%p", __func__, rfd); + + bgp = bgp_get_default(); + + if (rfd->mon) { + for (rn = route_top(rfd->mon); rn; rn = route_next(rn)) { + struct rfapi_monitor_vpn *m; + if ((m = rn->info)) { + if (!(bgp->rfapi_cfg->flags + & BGP_VNC_CONFIG_CALLBACK_DISABLE)) { + rfapiMonitorDetachImport(m); + } + + if (m->timer) { + thread_cancel(m->timer); + m->timer = NULL; + } + + XFREE(MTYPE_RFAPI_MONITOR, m); + rn->info = NULL; + route_unlock_node(rn); /* undo original lock + when created */ + ++count; + --rfd->monitor_count; + --bgp->rfapi->monitor_count; + } + } + route_table_finish(rfd->mon); + rfd->mon = NULL; + } + + if (rfd->mon_eth) { + + struct rfapi_monitor_eth *mon_eth; + + while (!skiplist_first(rfd->mon_eth, NULL, (void **)&mon_eth)) { + + int rc; + + if (!(bgp->rfapi_cfg->flags + & BGP_VNC_CONFIG_CALLBACK_DISABLE)) { + rfapiMonitorEthDetachImport(bgp, mon_eth); + } else { #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose - ("%s: callbacks disabled, not attempting to detach mon_eth %p", - __func__, mon_eth); + vnc_zlog_debug_verbose( + "%s: callbacks disabled, not attempting to detach mon_eth %p", + __func__, mon_eth); #endif - } - - if (mon_eth->timer) - { - thread_cancel (mon_eth->timer); - mon_eth->timer = NULL; - } - - /* - * remove from rfd list - */ - rc = skiplist_delete (rfd->mon_eth, mon_eth, mon_eth); - assert (!rc); - - vnc_zlog_debug_verbose ("%s: freeing mon_eth %p", __func__, mon_eth); - XFREE (MTYPE_RFAPI_MONITOR_ETH, mon_eth); - - ++count; - --rfd->monitor_count; - --bgp->rfapi->monitor_count; - } - skiplist_free (rfd->mon_eth); - rfd->mon_eth = NULL; - - } - - return count; + } + + if (mon_eth->timer) { + thread_cancel(mon_eth->timer); + mon_eth->timer = NULL; + } + + /* + * remove from rfd list + */ + rc = skiplist_delete(rfd->mon_eth, mon_eth, mon_eth); + assert(!rc); + + vnc_zlog_debug_verbose("%s: freeing mon_eth %p", + __func__, mon_eth); + XFREE(MTYPE_RFAPI_MONITOR_ETH, mon_eth); + + ++count; + --rfd->monitor_count; + --bgp->rfapi->monitor_count; + } + skiplist_free(rfd->mon_eth); + rfd->mon_eth = NULL; + } + + return count; } -void -rfapiMonitorResponseRemovalOff (struct bgp *bgp) +void rfapiMonitorResponseRemovalOff(struct bgp *bgp) { - if (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE) - { - return; - } - bgp->rfapi_cfg->flags |= BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE; + if (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE) { + return; + } + bgp->rfapi_cfg->flags |= BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE; } -void -rfapiMonitorResponseRemovalOn (struct bgp *bgp) +void rfapiMonitorResponseRemovalOn(struct bgp *bgp) { - if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE)) - { - return; - } - bgp->rfapi_cfg->flags &= ~BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE; + if (!(bgp->rfapi_cfg->flags + & BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE)) { + return; + } + bgp->rfapi_cfg->flags &= ~BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE; } -static int -rfapiMonitorTimerExpire (struct thread *t) +static int rfapiMonitorTimerExpire(struct thread *t) { - struct rfapi_monitor_vpn *m = t->arg; + struct rfapi_monitor_vpn *m = t->arg; - /* forget reference to thread, it's gone */ - m->timer = NULL; + /* forget reference to thread, it's gone */ + m->timer = NULL; - /* delete the monitor */ - rfapiMonitorDel (bgp_get_default (), m->rfd, &m->p); + /* delete the monitor */ + rfapiMonitorDel(bgp_get_default(), m->rfd, &m->p); - return 0; + return 0; } -static void -rfapiMonitorTimerRestart (struct rfapi_monitor_vpn *m) +static void rfapiMonitorTimerRestart(struct rfapi_monitor_vpn *m) { - if (m->timer) - { - unsigned long remain = thread_timer_remain_second (m->timer); - - /* unexpected case, but avoid wraparound problems below */ - if (remain > m->rfd->response_lifetime) - return; - - /* don't restart if we just restarted recently */ - if (m->rfd->response_lifetime - remain < 2) - return; - - thread_cancel (m->timer); - m->timer = NULL; - } - - { - char buf[BUFSIZ]; - - vnc_zlog_debug_verbose ("%s: target %s life %u", __func__, - rfapi_ntop (m->p.family, m->p.u.val, buf, BUFSIZ), - m->rfd->response_lifetime); - } - m->timer = NULL; - thread_add_timer(bm->master, rfapiMonitorTimerExpire, m, m->rfd->response_lifetime, - &m->timer); + if (m->timer) { + unsigned long remain = thread_timer_remain_second(m->timer); + + /* unexpected case, but avoid wraparound problems below */ + if (remain > m->rfd->response_lifetime) + return; + + /* don't restart if we just restarted recently */ + if (m->rfd->response_lifetime - remain < 2) + return; + + thread_cancel(m->timer); + m->timer = NULL; + } + + { + char buf[BUFSIZ]; + + vnc_zlog_debug_verbose( + "%s: target %s life %u", __func__, + rfapi_ntop(m->p.family, m->p.u.val, buf, BUFSIZ), + m->rfd->response_lifetime); + } + m->timer = NULL; + thread_add_timer(bm->master, rfapiMonitorTimerExpire, m, + m->rfd->response_lifetime, &m->timer); } -/* +/* * called when an updated response is sent to the NVE. Per * ticket 255, restart timers for any monitors that could have * been responsible for the response, i.e., any monitors for * the exact prefix or a parent of it. */ -void -rfapiMonitorTimersRestart (struct rfapi_descriptor *rfd, struct prefix *p) +void rfapiMonitorTimersRestart(struct rfapi_descriptor *rfd, struct prefix *p) { - struct route_node *rn; - - if (AF_ETHERNET == p->family) - { - struct rfapi_monitor_eth *mon_eth; - int rc; - void *cursor; - - /* - * XXX match any LNI - */ - for (cursor = NULL, - rc = - skiplist_next (rfd->mon_eth, NULL, (void **) &mon_eth, &cursor); - rc == 0; - rc = - skiplist_next (rfd->mon_eth, NULL, (void **) &mon_eth, &cursor)) - { - - if (!memcmp (mon_eth->macaddr.octet, p->u.prefix_eth.octet, - ETHER_ADDR_LEN)) - { - - rfapiMonitorEthTimerRestart (mon_eth); - - } - } - - } - else - { - for (rn = route_top (rfd->mon); rn; rn = route_next (rn)) - { - struct rfapi_monitor_vpn *m; - - if (!((m = rn->info))) - continue; - - /* NB order of test is significant ! */ - if (!m->node || prefix_match (&m->node->p, p)) - { - rfapiMonitorTimerRestart (m); - } - } - } + struct route_node *rn; + + if (AF_ETHERNET == p->family) { + struct rfapi_monitor_eth *mon_eth; + int rc; + void *cursor; + + /* + * XXX match any LNI + */ + for (cursor = NULL, + rc = skiplist_next(rfd->mon_eth, NULL, (void **)&mon_eth, + &cursor); + rc == 0; rc = skiplist_next(rfd->mon_eth, NULL, + (void **)&mon_eth, &cursor)) { + + if (!memcmp(mon_eth->macaddr.octet, + p->u.prefix_eth.octet, ETHER_ADDR_LEN)) { + + rfapiMonitorEthTimerRestart(mon_eth); + } + } + + } else { + for (rn = route_top(rfd->mon); rn; rn = route_next(rn)) { + struct rfapi_monitor_vpn *m; + + if (!((m = rn->info))) + continue; + + /* NB order of test is significant ! */ + if (!m->node || prefix_match(&m->node->p, p)) { + rfapiMonitorTimerRestart(m); + } + } + } } /* * Find monitors at this node and all its parents. Call * rfapiRibUpdatePendingNode with this node and all corresponding NVEs. */ -void -rfapiMonitorItNodeChanged ( - struct rfapi_import_table *import_table, - struct route_node *it_node, - struct rfapi_monitor_vpn *monitor_list) /* for base it node, NULL=all */ +void rfapiMonitorItNodeChanged( + struct rfapi_import_table *import_table, struct route_node *it_node, + struct rfapi_monitor_vpn *monitor_list) /* for base it node, NULL=all */ { - struct skiplist *nves_seen; - struct route_node *rn = it_node; - struct bgp *bgp = bgp_get_default (); - afi_t afi = family2afi (rn->p.family); + struct skiplist *nves_seen; + struct route_node *rn = it_node; + struct bgp *bgp = bgp_get_default(); + afi_t afi = family2afi(rn->p.family); #if DEBUG_L2_EXTRA - char buf_prefix[BUFSIZ]; + char buf_prefix[BUFSIZ]; #endif - assert (bgp); - assert (import_table); + assert(bgp); + assert(import_table); - nves_seen = skiplist_new (0, NULL, NULL); + nves_seen = skiplist_new(0, NULL, NULL); #if DEBUG_L2_EXTRA - prefix2str (&it_node->p, buf_prefix, BUFSIZ); - vnc_zlog_debug_verbose ("%s: it=%p, it_node=%p, it_node->prefix=%s", - __func__, import_table, it_node, buf_prefix); + prefix2str(&it_node->p, buf_prefix, BUFSIZ); + vnc_zlog_debug_verbose("%s: it=%p, it_node=%p, it_node->prefix=%s", + __func__, import_table, it_node, buf_prefix); #endif - if (AFI_L2VPN == afi) - { - struct rfapi_monitor_eth *m; - struct skiplist *sl; - void *cursor; - int rc; - - if ((sl = RFAPI_MONITOR_ETH (rn))) - { - - for (cursor = NULL, - rc = skiplist_next (sl, NULL, (void **) &m, (void **) &cursor); - !rc; - rc = skiplist_next (sl, NULL, (void **) &m, (void **) &cursor)) - { - - if (skiplist_search (nves_seen, m->rfd, NULL)) - { - /* - * Haven't done this NVE yet. Add to "seen" list. - */ - assert (!skiplist_insert (nves_seen, m->rfd, NULL)); - - /* - * update its RIB - */ - rfapiRibUpdatePendingNode(bgp, m->rfd, import_table, - it_node, m->rfd->response_lifetime); - } - } - } - - } - else - { - - struct rfapi_monitor_vpn *m; - - if (monitor_list) - { - m = monitor_list; - } - else - { - m = RFAPI_MONITOR_VPN (rn); - } - - do - { - /* - * If we have reached the root node (parent==NULL) and there - * are no routes here (info==NULL), and the IT node that - * changed was not the root node (it_node->parent != NULL), - * then any monitors at this node are here because they had - * no match at all. Therefore, do not send route updates to them - * because we haven't sent them an initial route. - */ - if (!rn->parent && !rn->info && it_node->parent) - break; - - for (; m; m = m->next) - { - - if (RFAPI_0_PREFIX (&m->p)) - { - /* shouldn't happen, but be safe */ - continue; - } - if (skiplist_search (nves_seen, m->rfd, NULL)) - { - /* - * Haven't done this NVE yet. Add to "seen" list. - */ - assert (!skiplist_insert (nves_seen, m->rfd, NULL)); - - { - char buf_attach_pfx[BUFSIZ]; - char buf_target_pfx[BUFSIZ]; - - prefix2str (&m->node->p, buf_attach_pfx, BUFSIZ); - prefix2str (&m->p, buf_target_pfx, BUFSIZ); - vnc_zlog_debug_verbose - ("%s: update rfd %p attached to pfx %s (targ=%s)", - __func__, m->rfd, buf_attach_pfx, buf_target_pfx); - } - - /* - * update its RIB - */ - rfapiRibUpdatePendingNode(bgp, m->rfd, import_table, - it_node, m->rfd->response_lifetime); - } - } - rn = rn->parent; - if (rn) - m = RFAPI_MONITOR_VPN (rn); - } - while (rn); - } - - /* - * All-routes L2 monitors - */ - if (AFI_L2VPN == afi) - { - struct rfapi_monitor_eth *e; + if (AFI_L2VPN == afi) { + struct rfapi_monitor_eth *m; + struct skiplist *sl; + void *cursor; + int rc; + + if ((sl = RFAPI_MONITOR_ETH(rn))) { + + for (cursor = NULL, + rc = skiplist_next(sl, NULL, (void **)&m, + (void **)&cursor); + !rc; rc = skiplist_next(sl, NULL, (void **)&m, + (void **)&cursor)) { + + if (skiplist_search(nves_seen, m->rfd, NULL)) { + /* + * Haven't done this NVE yet. Add to + * "seen" list. + */ + assert(!skiplist_insert(nves_seen, + m->rfd, NULL)); + + /* + * update its RIB + */ + rfapiRibUpdatePendingNode( + bgp, m->rfd, import_table, + it_node, + m->rfd->response_lifetime); + } + } + } + + } else { + + struct rfapi_monitor_vpn *m; + + if (monitor_list) { + m = monitor_list; + } else { + m = RFAPI_MONITOR_VPN(rn); + } + + do { + /* + * If we have reached the root node (parent==NULL) and + * there + * are no routes here (info==NULL), and the IT node that + * changed was not the root node (it_node->parent != + * NULL), + * then any monitors at this node are here because they + * had + * no match at all. Therefore, do not send route updates + * to them + * because we haven't sent them an initial route. + */ + if (!rn->parent && !rn->info && it_node->parent) + break; + + for (; m; m = m->next) { + + if (RFAPI_0_PREFIX(&m->p)) { + /* shouldn't happen, but be safe */ + continue; + } + if (skiplist_search(nves_seen, m->rfd, NULL)) { + /* + * Haven't done this NVE yet. Add to + * "seen" list. + */ + assert(!skiplist_insert(nves_seen, + m->rfd, NULL)); + + { + char buf_attach_pfx[BUFSIZ]; + char buf_target_pfx[BUFSIZ]; + + prefix2str(&m->node->p, + buf_attach_pfx, + BUFSIZ); + prefix2str(&m->p, + buf_target_pfx, + BUFSIZ); + vnc_zlog_debug_verbose( + "%s: update rfd %p attached to pfx %s (targ=%s)", + __func__, m->rfd, + buf_attach_pfx, + buf_target_pfx); + } + + /* + * update its RIB + */ + rfapiRibUpdatePendingNode( + bgp, m->rfd, import_table, + it_node, + m->rfd->response_lifetime); + } + } + rn = rn->parent; + if (rn) + m = RFAPI_MONITOR_VPN(rn); + } while (rn); + } + + /* + * All-routes L2 monitors + */ + if (AFI_L2VPN == afi) { + struct rfapi_monitor_eth *e; #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: checking L2 all-routes monitors", __func__); + vnc_zlog_debug_verbose("%s: checking L2 all-routes monitors", + __func__); #endif - for (e = import_table->eth0_queries; e; e = e->next) - { + for (e = import_table->eth0_queries; e; e = e->next) { #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: checking eth0 mon=%p", __func__, e); + vnc_zlog_debug_verbose("%s: checking eth0 mon=%p", + __func__, e); #endif - if (skiplist_search (nves_seen, e->rfd, NULL)) - { - /* - * Haven't done this NVE yet. Add to "seen" list. - */ - assert (!skiplist_insert (nves_seen, e->rfd, NULL)); - - /* - * update its RIB - */ + if (skiplist_search(nves_seen, e->rfd, NULL)) { + /* + * Haven't done this NVE yet. Add to "seen" + * list. + */ + assert(!skiplist_insert(nves_seen, e->rfd, + NULL)); + +/* + * update its RIB + */ #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: found L2 all-routes monitor %p", __func__, e); + vnc_zlog_debug_verbose( + "%s: found L2 all-routes monitor %p", + __func__, e); #endif - rfapiRibUpdatePendingNode (bgp, e->rfd, import_table, it_node, - e->rfd->response_lifetime); - } - } - } - else - { - struct rfapi_monitor_vpn *m; - - /* - * All-routes IPv4. IPv6 monitors - */ - for (m = import_table->vpn0_queries[afi]; m; m = m->next) - { - if (skiplist_search (nves_seen, m->rfd, NULL)) - { - /* - * Haven't done this NVE yet. Add to "seen" list. - */ - assert (!skiplist_insert (nves_seen, m->rfd, NULL)); - - /* - * update its RIB - */ - rfapiRibUpdatePendingNode (bgp, m->rfd, import_table, it_node, - m->rfd->response_lifetime); - } - } - } - - skiplist_free (nves_seen); + rfapiRibUpdatePendingNode( + bgp, e->rfd, import_table, it_node, + e->rfd->response_lifetime); + } + } + } else { + struct rfapi_monitor_vpn *m; + + /* + * All-routes IPv4. IPv6 monitors + */ + for (m = import_table->vpn0_queries[afi]; m; m = m->next) { + if (skiplist_search(nves_seen, m->rfd, NULL)) { + /* + * Haven't done this NVE yet. Add to "seen" + * list. + */ + assert(!skiplist_insert(nves_seen, m->rfd, + NULL)); + + /* + * update its RIB + */ + rfapiRibUpdatePendingNode( + bgp, m->rfd, import_table, it_node, + m->rfd->response_lifetime); + } + } + } + + skiplist_free(nves_seen); } /* * For the listed monitors, update new node and its subtree, but * omit old node and its subtree */ -void -rfapiMonitorMovedUp ( - struct rfapi_import_table *import_table, - struct route_node *old_node, - struct route_node *new_node, - struct rfapi_monitor_vpn *monitor_list) +void rfapiMonitorMovedUp(struct rfapi_import_table *import_table, + struct route_node *old_node, + struct route_node *new_node, + struct rfapi_monitor_vpn *monitor_list) { - struct bgp *bgp = bgp_get_default (); - struct rfapi_monitor_vpn *m; - - assert (new_node); - assert (old_node); - assert (new_node != old_node); - - /* - * If new node is 0/0 and there is no route there, don't - * generate an update because it will not contain any - * routes including the target. - */ - if (!new_node->parent && !new_node->info) - { - vnc_zlog_debug_verbose ("%s: new monitor at 0/0 and no routes, no updates", - __func__); - return; - } - - for (m = monitor_list; m; m = m->next) - { - rfapiRibUpdatePendingNode (bgp, m->rfd, import_table, new_node, - m->rfd->response_lifetime); - rfapiRibUpdatePendingNodeSubtree (bgp, m->rfd, import_table, new_node, - old_node, m->rfd->response_lifetime); - } + struct bgp *bgp = bgp_get_default(); + struct rfapi_monitor_vpn *m; + + assert(new_node); + assert(old_node); + assert(new_node != old_node); + + /* + * If new node is 0/0 and there is no route there, don't + * generate an update because it will not contain any + * routes including the target. + */ + if (!new_node->parent && !new_node->info) { + vnc_zlog_debug_verbose( + "%s: new monitor at 0/0 and no routes, no updates", + __func__); + return; + } + + for (m = monitor_list; m; m = m->next) { + rfapiRibUpdatePendingNode(bgp, m->rfd, import_table, new_node, + m->rfd->response_lifetime); + rfapiRibUpdatePendingNodeSubtree(bgp, m->rfd, import_table, + new_node, old_node, + m->rfd->response_lifetime); + } } -static int -rfapiMonitorEthTimerExpire (struct thread *t) +static int rfapiMonitorEthTimerExpire(struct thread *t) { - struct rfapi_monitor_eth *m = t->arg; + struct rfapi_monitor_eth *m = t->arg; - /* forget reference to thread, it's gone */ - m->timer = NULL; + /* forget reference to thread, it's gone */ + m->timer = NULL; - /* delete the monitor */ - rfapiMonitorEthDel (bgp_get_default (), m->rfd, &m->macaddr, - m->logical_net_id); + /* delete the monitor */ + rfapiMonitorEthDel(bgp_get_default(), m->rfd, &m->macaddr, + m->logical_net_id); - return 0; + return 0; } -static void -rfapiMonitorEthTimerRestart (struct rfapi_monitor_eth *m) +static void rfapiMonitorEthTimerRestart(struct rfapi_monitor_eth *m) { - if (m->timer) - { - unsigned long remain = thread_timer_remain_second (m->timer); - - /* unexpected case, but avoid wraparound problems below */ - if (remain > m->rfd->response_lifetime) - return; - - /* don't restart if we just restarted recently */ - if (m->rfd->response_lifetime - remain < 2) - return; - - thread_cancel (m->timer); - m->timer = NULL; - } - - { - char buf[BUFSIZ]; - - vnc_zlog_debug_verbose ("%s: target %s life %u", __func__, - rfapiEthAddr2Str (&m->macaddr, buf, BUFSIZ), - m->rfd->response_lifetime); - } - m->timer = NULL; - thread_add_timer(bm->master, rfapiMonitorEthTimerExpire, m, m->rfd->response_lifetime, - &m->timer); + if (m->timer) { + unsigned long remain = thread_timer_remain_second(m->timer); + + /* unexpected case, but avoid wraparound problems below */ + if (remain > m->rfd->response_lifetime) + return; + + /* don't restart if we just restarted recently */ + if (m->rfd->response_lifetime - remain < 2) + return; + + thread_cancel(m->timer); + m->timer = NULL; + } + + { + char buf[BUFSIZ]; + + vnc_zlog_debug_verbose( + "%s: target %s life %u", __func__, + rfapiEthAddr2Str(&m->macaddr, buf, BUFSIZ), + m->rfd->response_lifetime); + } + m->timer = NULL; + thread_add_timer(bm->master, rfapiMonitorEthTimerExpire, m, + m->rfd->response_lifetime, &m->timer); } -static int -mon_eth_cmp (void *a, void *b) +static int mon_eth_cmp(void *a, void *b) { - struct rfapi_monitor_eth *m1; - struct rfapi_monitor_eth *m2; - - int i; - - m1 = (struct rfapi_monitor_eth *) a; - m2 = (struct rfapi_monitor_eth *) b; - - /* - * compare ethernet addresses - */ - for (i = 0; i < ETHER_ADDR_LEN; ++i) - { - if (m1->macaddr.octet[i] != m2->macaddr.octet[i]) - return (m1->macaddr.octet[i] - m2->macaddr.octet[i]); - } - - /* - * compare LNIs - */ - return (m1->logical_net_id - m2->logical_net_id); + struct rfapi_monitor_eth *m1; + struct rfapi_monitor_eth *m2; + + int i; + + m1 = (struct rfapi_monitor_eth *)a; + m2 = (struct rfapi_monitor_eth *)b; + + /* + * compare ethernet addresses + */ + for (i = 0; i < ETHER_ADDR_LEN; ++i) { + if (m1->macaddr.octet[i] != m2->macaddr.octet[i]) + return (m1->macaddr.octet[i] - m2->macaddr.octet[i]); + } + + /* + * compare LNIs + */ + return (m1->logical_net_id - m2->logical_net_id); } -static void -rfapiMonitorEthAttachImport ( - struct rfapi_import_table *it, - struct route_node *rn, /* it node attach point if non-0 */ - struct rfapi_monitor_eth *mon) /* monitor struct to attach */ +static void rfapiMonitorEthAttachImport( + struct rfapi_import_table *it, + struct route_node *rn, /* it node attach point if non-0 */ + struct rfapi_monitor_eth *mon) /* monitor struct to attach */ { - struct skiplist *sl; - int rc; + struct skiplist *sl; + int rc; - vnc_zlog_debug_verbose ("%s: it=%p", __func__, it); + vnc_zlog_debug_verbose("%s: it=%p", __func__, it); - rfapiMonitorCheckAttachAllowed (); + rfapiMonitorCheckAttachAllowed(); - if (RFAPI_0_ETHERADDR (&mon->macaddr)) - { - /* - * These go on a different list - */ - mon->next = it->eth0_queries; - it->eth0_queries = mon; + if (RFAPI_0_ETHERADDR(&mon->macaddr)) { + /* + * These go on a different list + */ + mon->next = it->eth0_queries; + it->eth0_queries = mon; #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: attached monitor %p to eth0 list", __func__, mon); + vnc_zlog_debug_verbose("%s: attached monitor %p to eth0 list", + __func__, mon); #endif - return; - } + return; + } - if (rn == NULL) - { + if (rn == NULL) { #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: rn is null!", __func__); + vnc_zlog_debug_verbose("%s: rn is null!", __func__); #endif - return; - } - - /* - * Get sl to attach to - */ - sl = RFAPI_MONITOR_ETH_W_ALLOC (rn); - if (!sl) - { - sl = RFAPI_MONITOR_ETH_W_ALLOC (rn) = skiplist_new (0, NULL, NULL); - route_lock_node(rn); /* count skiplist mon_eth */ - } + return; + } + + /* + * Get sl to attach to + */ + sl = RFAPI_MONITOR_ETH_W_ALLOC(rn); + if (!sl) { + sl = RFAPI_MONITOR_ETH_W_ALLOC(rn) = + skiplist_new(0, NULL, NULL); + route_lock_node(rn); /* count skiplist mon_eth */ + } #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: rn=%p, rn->lock=%d, sl=%p, attaching eth mon %p", - __func__, rn, rn->lock, sl, mon); + vnc_zlog_debug_verbose( + "%s: rn=%p, rn->lock=%d, sl=%p, attaching eth mon %p", __func__, + rn, rn->lock, sl, mon); #endif - rc = skiplist_insert (sl, (void *) mon, (void *) mon); - assert (!rc); + rc = skiplist_insert(sl, (void *)mon, (void *)mon); + assert(!rc); - /* count eth monitor */ - route_lock_node(rn); + /* count eth monitor */ + route_lock_node(rn); } /* * reattach monitors for this HD to import table */ -static void -rfapiMonitorEthAttachImportHd (struct bgp *bgp, struct rfapi_descriptor *rfd) +static void rfapiMonitorEthAttachImportHd(struct bgp *bgp, + struct rfapi_descriptor *rfd) { - void *cursor; - struct rfapi_monitor_eth *mon; - int rc; - - if (!rfd->mon_eth) - { - /* - * No monitors for this HD - */ - return; - } - - for (cursor = NULL, - rc = skiplist_next (rfd->mon_eth, NULL, (void **) &mon, &cursor); - rc == 0; - rc = skiplist_next (rfd->mon_eth, NULL, (void **) &mon, &cursor)) - { - - struct rfapi_import_table *it; - struct prefix pfx_mac_buf; - struct route_node *rn; - - it = rfapiMacImportTableGet (bgp, mon->logical_net_id); - assert (it); - - memset ((void *) &pfx_mac_buf, 0, sizeof (struct prefix)); - pfx_mac_buf.family = AF_ETHERNET; - pfx_mac_buf.prefixlen = 48; - pfx_mac_buf.u.prefix_eth = mon->macaddr; - - rn = route_node_get (it->imported_vpn[AFI_L2VPN], &pfx_mac_buf); - assert (rn); - - (void) rfapiMonitorEthAttachImport (it, rn, mon); - } + void *cursor; + struct rfapi_monitor_eth *mon; + int rc; + + if (!rfd->mon_eth) { + /* + * No monitors for this HD + */ + return; + } + + for (cursor = NULL, + rc = skiplist_next(rfd->mon_eth, NULL, (void **)&mon, &cursor); + rc == 0; + rc = skiplist_next(rfd->mon_eth, NULL, (void **)&mon, &cursor)) { + + struct rfapi_import_table *it; + struct prefix pfx_mac_buf; + struct route_node *rn; + + it = rfapiMacImportTableGet(bgp, mon->logical_net_id); + assert(it); + + memset((void *)&pfx_mac_buf, 0, sizeof(struct prefix)); + pfx_mac_buf.family = AF_ETHERNET; + pfx_mac_buf.prefixlen = 48; + pfx_mac_buf.u.prefix_eth = mon->macaddr; + + rn = route_node_get(it->imported_vpn[AFI_L2VPN], &pfx_mac_buf); + assert(rn); + + (void)rfapiMonitorEthAttachImport(it, rn, mon); + } } -static void -rfapiMonitorEthDetachImport ( - struct bgp *bgp, - struct rfapi_monitor_eth *mon) /* monitor struct to detach */ +static void rfapiMonitorEthDetachImport( + struct bgp *bgp, + struct rfapi_monitor_eth *mon) /* monitor struct to detach */ { - struct rfapi_import_table *it; - struct prefix pfx_mac_buf; - struct skiplist *sl; - struct route_node *rn; - int rc; - - it = rfapiMacImportTableGet (bgp, mon->logical_net_id); - assert (it); - - if (RFAPI_0_ETHERADDR (&mon->macaddr)) - { - struct rfapi_monitor_eth *prev; - struct rfapi_monitor_eth *this = NULL; - - for (prev = NULL, - this = it->eth0_queries; this; prev = this, this = this->next) - { - - if (this == mon) - break; - } - if (this) - { - if (!prev) - { - it->eth0_queries = this->next; - } - else - { - prev->next = this->next; - } - } + struct rfapi_import_table *it; + struct prefix pfx_mac_buf; + struct skiplist *sl; + struct route_node *rn; + int rc; + + it = rfapiMacImportTableGet(bgp, mon->logical_net_id); + assert(it); + + if (RFAPI_0_ETHERADDR(&mon->macaddr)) { + struct rfapi_monitor_eth *prev; + struct rfapi_monitor_eth *this = NULL; + + for (prev = NULL, this = it->eth0_queries; this; + prev = this, this = this->next) { + + if (this == mon) + break; + } + if (this) { + if (!prev) { + it->eth0_queries = this->next; + } else { + prev->next = this->next; + } + } #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: it=%p, LNI=%d, detached eth0 mon %p", - __func__, it, mon->logical_net_id, mon); + vnc_zlog_debug_verbose( + "%s: it=%p, LNI=%d, detached eth0 mon %p", __func__, it, + mon->logical_net_id, mon); #endif - return; - } + return; + } - memset ((void *) &pfx_mac_buf, 0, sizeof (struct prefix)); - pfx_mac_buf.family = AF_ETHERNET; - pfx_mac_buf.prefixlen = 48; - pfx_mac_buf.u.prefix_eth = mon->macaddr; + memset((void *)&pfx_mac_buf, 0, sizeof(struct prefix)); + pfx_mac_buf.family = AF_ETHERNET; + pfx_mac_buf.prefixlen = 48; + pfx_mac_buf.u.prefix_eth = mon->macaddr; - rn = route_node_get (it->imported_vpn[AFI_L2VPN], &pfx_mac_buf); - assert (rn); + rn = route_node_get(it->imported_vpn[AFI_L2VPN], &pfx_mac_buf); + assert(rn); #if DEBUG_L2_EXTRA - char buf_prefix[BUFSIZ]; - prefix2str (&rn->p, buf_prefix, BUFSIZ); + char buf_prefix[BUFSIZ]; + prefix2str(&rn->p, buf_prefix, BUFSIZ); #endif - /* - * Get sl to detach from - */ - sl = RFAPI_MONITOR_ETH (rn); + /* + * Get sl to detach from + */ + sl = RFAPI_MONITOR_ETH(rn); #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: it=%p, rn=%p, rn->lock=%d, sl=%p, pfx=%s, LNI=%d, detaching eth mon %p", - __func__, it, rn, rn->lock, sl, buf_prefix, mon->logical_net_id, mon); + vnc_zlog_debug_verbose( + "%s: it=%p, rn=%p, rn->lock=%d, sl=%p, pfx=%s, LNI=%d, detaching eth mon %p", + __func__, it, rn, rn->lock, sl, buf_prefix, mon->logical_net_id, + mon); #endif - assert (sl); + assert(sl); - rc = skiplist_delete (sl, (void *) mon, (void *) mon); - assert (!rc); + rc = skiplist_delete(sl, (void *)mon, (void *)mon); + assert(!rc); - /* uncount eth monitor */ - route_unlock_node(rn); + /* uncount eth monitor */ + route_unlock_node(rn); } -struct route_node * -rfapiMonitorEthAdd ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct ethaddr *macaddr, - uint32_t logical_net_id) +struct route_node *rfapiMonitorEthAdd(struct bgp *bgp, + struct rfapi_descriptor *rfd, + struct ethaddr *macaddr, + uint32_t logical_net_id) { - int rc; - struct rfapi_monitor_eth mon_buf; - struct rfapi_monitor_eth *val; - struct rfapi_import_table *it; - struct route_node *rn = NULL; - struct prefix pfx_mac_buf; - - if (!rfd->mon_eth) - { - rfd->mon_eth = skiplist_new (0, mon_eth_cmp, NULL); - } - - it = rfapiMacImportTableGet (bgp, logical_net_id); - assert (it); - - /* - * Get route node in import table. Here is where we attach the - * monitor. - * - * Look it up now because we return it to caller regardless of - * whether we create a new monitor or not. - */ - memset ((void *) &pfx_mac_buf, 0, sizeof (struct prefix)); - pfx_mac_buf.family = AF_ETHERNET; - pfx_mac_buf.prefixlen = 48; - pfx_mac_buf.u.prefix_eth = *macaddr; - - if (!RFAPI_0_ETHERADDR (macaddr)) - { - rn = route_node_get (it->imported_vpn[AFI_L2VPN], &pfx_mac_buf); - assert (rn); - } - - memset ((void *) &mon_buf, 0, sizeof (mon_buf)); - mon_buf.rfd = rfd; - mon_buf.macaddr = *macaddr; - mon_buf.logical_net_id = logical_net_id; - - { - char buf[BUFSIZ]; - - vnc_zlog_debug_verbose ("%s: LNI=%d: rfd=%p, pfx=%s", - __func__, logical_net_id, rfd, - rfapi_ntop (pfx_mac_buf.family, pfx_mac_buf.u.val, buf, - BUFSIZ)); - } - - - /* - * look up query - */ - rc = skiplist_search (rfd->mon_eth, (void *) &mon_buf, (void **) &val); - if (!rc) - { - /* - * Found monitor - we have seen this query before - * restart timer - */ - vnc_zlog_debug_verbose ("%s: already present in rfd->mon_eth, not adding", - __func__); - rfapiMonitorEthTimerRestart (val); - return rn; - } - - /* - * New query - */ - val = XCALLOC (MTYPE_RFAPI_MONITOR_ETH, sizeof (struct rfapi_monitor_eth)); - assert (val); - *val = mon_buf; - - ++rfd->monitor_count; - ++bgp->rfapi->monitor_count; - - rc = skiplist_insert (rfd->mon_eth, val, val); + int rc; + struct rfapi_monitor_eth mon_buf; + struct rfapi_monitor_eth *val; + struct rfapi_import_table *it; + struct route_node *rn = NULL; + struct prefix pfx_mac_buf; + + if (!rfd->mon_eth) { + rfd->mon_eth = skiplist_new(0, mon_eth_cmp, NULL); + } + + it = rfapiMacImportTableGet(bgp, logical_net_id); + assert(it); + + /* + * Get route node in import table. Here is where we attach the + * monitor. + * + * Look it up now because we return it to caller regardless of + * whether we create a new monitor or not. + */ + memset((void *)&pfx_mac_buf, 0, sizeof(struct prefix)); + pfx_mac_buf.family = AF_ETHERNET; + pfx_mac_buf.prefixlen = 48; + pfx_mac_buf.u.prefix_eth = *macaddr; + + if (!RFAPI_0_ETHERADDR(macaddr)) { + rn = route_node_get(it->imported_vpn[AFI_L2VPN], &pfx_mac_buf); + assert(rn); + } + + memset((void *)&mon_buf, 0, sizeof(mon_buf)); + mon_buf.rfd = rfd; + mon_buf.macaddr = *macaddr; + mon_buf.logical_net_id = logical_net_id; + + { + char buf[BUFSIZ]; + + vnc_zlog_debug_verbose( + "%s: LNI=%d: rfd=%p, pfx=%s", __func__, logical_net_id, + rfd, rfapi_ntop(pfx_mac_buf.family, pfx_mac_buf.u.val, + buf, BUFSIZ)); + } + + + /* + * look up query + */ + rc = skiplist_search(rfd->mon_eth, (void *)&mon_buf, (void **)&val); + if (!rc) { + /* + * Found monitor - we have seen this query before + * restart timer + */ + vnc_zlog_debug_verbose( + "%s: already present in rfd->mon_eth, not adding", + __func__); + rfapiMonitorEthTimerRestart(val); + return rn; + } + + /* + * New query + */ + val = XCALLOC(MTYPE_RFAPI_MONITOR_ETH, + sizeof(struct rfapi_monitor_eth)); + assert(val); + *val = mon_buf; + + ++rfd->monitor_count; + ++bgp->rfapi->monitor_count; + + rc = skiplist_insert(rfd->mon_eth, val, val); #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: inserted rfd=%p mon_eth=%p, rc=%d", __func__, rfd, val, - rc); + vnc_zlog_debug_verbose("%s: inserted rfd=%p mon_eth=%p, rc=%d", + __func__, rfd, val, rc); #endif - /* - * start timer - */ - rfapiMonitorEthTimerRestart (val); + /* + * start timer + */ + rfapiMonitorEthTimerRestart(val); - if (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE) - { - /* - * callbacks turned off, so don't attach monitor to import table - */ + if (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE) { +/* + * callbacks turned off, so don't attach monitor to import table + */ #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose - ("%s: callbacks turned off, not attaching mon_eth %p to import table", - __func__, val); + vnc_zlog_debug_verbose( + "%s: callbacks turned off, not attaching mon_eth %p to import table", + __func__, val); #endif - return rn; - } + return rn; + } - /* - * attach to import table - */ - rfapiMonitorEthAttachImport (it, rn, val); + /* + * attach to import table + */ + rfapiMonitorEthAttachImport(it, rn, val); - return rn; + return rn; } -void -rfapiMonitorEthDel ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct ethaddr *macaddr, - uint32_t logical_net_id) +void rfapiMonitorEthDel(struct bgp *bgp, struct rfapi_descriptor *rfd, + struct ethaddr *macaddr, uint32_t logical_net_id) { - struct rfapi_monitor_eth *val; - struct rfapi_monitor_eth mon_buf; - int rc; + struct rfapi_monitor_eth *val; + struct rfapi_monitor_eth mon_buf; + int rc; - vnc_zlog_debug_verbose ("%s: entry rfd=%p", __func__, rfd); + vnc_zlog_debug_verbose("%s: entry rfd=%p", __func__, rfd); - assert (rfd->mon_eth); + assert(rfd->mon_eth); - memset ((void *) &mon_buf, 0, sizeof (mon_buf)); - mon_buf.macaddr = *macaddr; - mon_buf.logical_net_id = logical_net_id; + memset((void *)&mon_buf, 0, sizeof(mon_buf)); + mon_buf.macaddr = *macaddr; + mon_buf.logical_net_id = logical_net_id; - rc = skiplist_search (rfd->mon_eth, (void *) &mon_buf, (void **) &val); - assert (!rc); + rc = skiplist_search(rfd->mon_eth, (void *)&mon_buf, (void **)&val); + assert(!rc); - /* - * remove from import table - */ - if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)) - { - rfapiMonitorEthDetachImport (bgp, val); - } + /* + * remove from import table + */ + if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)) { + rfapiMonitorEthDetachImport(bgp, val); + } - if (val->timer) - { - thread_cancel (val->timer); - val->timer = NULL; - } + if (val->timer) { + thread_cancel(val->timer); + val->timer = NULL; + } - /* - * remove from rfd list - */ - rc = skiplist_delete (rfd->mon_eth, val, val); - assert (!rc); + /* + * remove from rfd list + */ + rc = skiplist_delete(rfd->mon_eth, val, val); + assert(!rc); #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: freeing mon_eth %p", __func__, val); + vnc_zlog_debug_verbose("%s: freeing mon_eth %p", __func__, val); #endif - XFREE (MTYPE_RFAPI_MONITOR_ETH, val); + XFREE(MTYPE_RFAPI_MONITOR_ETH, val); - --rfd->monitor_count; - --bgp->rfapi->monitor_count; + --rfd->monitor_count; + --bgp->rfapi->monitor_count; } -void -rfapiMonitorCallbacksOff (struct bgp *bgp) +void rfapiMonitorCallbacksOff(struct bgp *bgp) { - struct rfapi_import_table *it; - afi_t afi; - struct route_table *rt; - struct route_node *rn; - void *cursor; - int rc; - struct rfapi *h = bgp->rfapi; - - if (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE) - { - /* - * Already off. - */ - return; - } - bgp->rfapi_cfg->flags |= BGP_VNC_CONFIG_CALLBACK_DISABLE; + struct rfapi_import_table *it; + afi_t afi; + struct route_table *rt; + struct route_node *rn; + void *cursor; + int rc; + struct rfapi *h = bgp->rfapi; + + if (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE) { + /* + * Already off. + */ + return; + } + bgp->rfapi_cfg->flags |= BGP_VNC_CONFIG_CALLBACK_DISABLE; #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: turned off callbacks", __func__); + vnc_zlog_debug_verbose("%s: turned off callbacks", __func__); #endif - if (h == NULL) - return; - /* - * detach monitors from import VPN tables. The monitors - * will still be linked in per-nve monitor lists. - */ - for (it = h->imports; it; it = it->next) - { - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - - struct rfapi_monitor_vpn *m; - struct rfapi_monitor_vpn *next; - - rt = it->imported_vpn[afi]; - - for (rn = route_top (rt); rn; rn = route_next (rn)) - { - m = RFAPI_MONITOR_VPN (rn); - if (RFAPI_MONITOR_VPN (rn)) - RFAPI_MONITOR_VPN_W_ALLOC (rn) = NULL; - for (; m; m = next) - { - next = m->next; - m->next = NULL; /* gratuitous safeness */ - m->node = NULL; - route_unlock_node (rn); /* uncount */ - } - } - - for (m = it->vpn0_queries[afi]; m; m = next) - { - next = m->next; - m->next = NULL; /* gratuitous safeness */ - m->node = NULL; - } - it->vpn0_queries[afi] = NULL; /* detach first monitor */ - } - } - - /* - * detach monitors from import Eth tables. The monitors - * will still be linked in per-nve monitor lists. - */ - - /* - * Loop over ethernet import tables - */ - for (cursor = NULL, - rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor); - !rc; rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor)) - { - struct rfapi_monitor_eth *e; - struct rfapi_monitor_eth *enext; - - /* - * The actual route table - */ - rt = it->imported_vpn[AFI_L2VPN]; - - /* - * Find non-0 monitors (i.e., actual addresses, not FTD monitors) - */ - for (rn = route_top (rt); rn; rn = route_next (rn)) - { - struct skiplist *sl; - - sl = RFAPI_MONITOR_ETH (rn); - while (!skiplist_delete_first(sl)) - { - route_unlock_node (rn); /* uncount monitor */ - } - } - - /* - * Find 0-monitors (FTD queries) - */ - for (e = it->eth0_queries; e; e = enext) - { + if (h == NULL) + return; + /* + * detach monitors from import VPN tables. The monitors + * will still be linked in per-nve monitor lists. + */ + for (it = h->imports; it; it = it->next) { + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + + struct rfapi_monitor_vpn *m; + struct rfapi_monitor_vpn *next; + + rt = it->imported_vpn[afi]; + + for (rn = route_top(rt); rn; rn = route_next(rn)) { + m = RFAPI_MONITOR_VPN(rn); + if (RFAPI_MONITOR_VPN(rn)) + RFAPI_MONITOR_VPN_W_ALLOC(rn) = NULL; + for (; m; m = next) { + next = m->next; + m->next = + NULL; /* gratuitous safeness */ + m->node = NULL; + route_unlock_node(rn); /* uncount */ + } + } + + for (m = it->vpn0_queries[afi]; m; m = next) { + next = m->next; + m->next = NULL; /* gratuitous safeness */ + m->node = NULL; + } + it->vpn0_queries[afi] = NULL; /* detach first monitor */ + } + } + + /* + * detach monitors from import Eth tables. The monitors + * will still be linked in per-nve monitor lists. + */ + + /* + * Loop over ethernet import tables + */ + for (cursor = NULL, + rc = skiplist_next(h->import_mac, NULL, (void **)&it, &cursor); + !rc; + rc = skiplist_next(h->import_mac, NULL, (void **)&it, &cursor)) { + struct rfapi_monitor_eth *e; + struct rfapi_monitor_eth *enext; + + /* + * The actual route table + */ + rt = it->imported_vpn[AFI_L2VPN]; + + /* + * Find non-0 monitors (i.e., actual addresses, not FTD + * monitors) + */ + for (rn = route_top(rt); rn; rn = route_next(rn)) { + struct skiplist *sl; + + sl = RFAPI_MONITOR_ETH(rn); + while (!skiplist_delete_first(sl)) { + route_unlock_node(rn); /* uncount monitor */ + } + } + + /* + * Find 0-monitors (FTD queries) + */ + for (e = it->eth0_queries; e; e = enext) { #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: detaching eth0 mon %p", __func__, e); + vnc_zlog_debug_verbose("%s: detaching eth0 mon %p", + __func__, e); #endif - enext = e->next; - e->next = NULL; /* gratuitous safeness */ - } - it->eth0_queries = NULL; /* detach first monitor */ - } + enext = e->next; + e->next = NULL; /* gratuitous safeness */ + } + it->eth0_queries = NULL; /* detach first monitor */ + } } -void -rfapiMonitorCallbacksOn (struct bgp *bgp) +void rfapiMonitorCallbacksOn(struct bgp *bgp) { - struct listnode *hnode; - struct rfapi_descriptor *rfd; - - if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)) - { - /* - * Already on. It's important that we don't try to reattach - * monitors that are already attached because, in the interest - * of performance, there is no checking at the lower level - * whether a monitor is already attached. It leads to - * corrupted chains (e.g., looped pointers) - */ - return; - } - bgp->rfapi_cfg->flags &= ~BGP_VNC_CONFIG_CALLBACK_DISABLE; + struct listnode *hnode; + struct rfapi_descriptor *rfd; + + if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)) { + /* + * Already on. It's important that we don't try to reattach + * monitors that are already attached because, in the interest + * of performance, there is no checking at the lower level + * whether a monitor is already attached. It leads to + * corrupted chains (e.g., looped pointers) + */ + return; + } + bgp->rfapi_cfg->flags &= ~BGP_VNC_CONFIG_CALLBACK_DISABLE; #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: turned on callbacks", __func__); + vnc_zlog_debug_verbose("%s: turned on callbacks", __func__); #endif - if (bgp->rfapi == NULL) - return; - - /* - * reattach monitors - */ - for (ALL_LIST_ELEMENTS_RO (&bgp->rfapi->descriptors, hnode, rfd)) - { - - rfapiMonitorAttachImportHd (rfd); - rfapiMonitorEthAttachImportHd (bgp, rfd); - } + if (bgp->rfapi == NULL) + return; + + /* + * reattach monitors + */ + for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, hnode, rfd)) { + + rfapiMonitorAttachImportHd(rfd); + rfapiMonitorEthAttachImportHd(bgp, rfd); + } } diff --git a/bgpd/rfapi/rfapi_monitor.h b/bgpd/rfapi/rfapi_monitor.h index 667d61ec1..edc9744cd 100644 --- a/bgpd/rfapi/rfapi_monitor.h +++ b/bgpd/rfapi/rfapi_monitor.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -29,35 +29,32 @@ * These get attached to the nodes in an import table (using "aggregate" ptr) * to indicate which nves are interested in a prefix/target */ -struct rfapi_monitor_vpn -{ - struct rfapi_monitor_vpn *next; /* chain from struct route_node */ - struct rfapi_descriptor *rfd; /* which NVE requested the route */ - struct prefix p; /* constant: pfx in original request */ - struct route_node *node; /* node we're currently attached to */ - uint32_t flags; +struct rfapi_monitor_vpn { + struct rfapi_monitor_vpn *next; /* chain from struct route_node */ + struct rfapi_descriptor *rfd; /* which NVE requested the route */ + struct prefix p; /* constant: pfx in original request */ + struct route_node *node; /* node we're currently attached to */ + uint32_t flags; #define RFAPI_MON_FLAG_NEEDCALLBACK 0x00000001 /* deferred callback */ - //int dcount; /* debugging counter */ - struct thread *timer; + // int dcount; /* debugging counter */ + struct thread *timer; }; -struct rfapi_monitor_encap -{ - struct rfapi_monitor_encap *next; - struct rfapi_monitor_encap *prev; - struct route_node *node; /* VPN node */ - struct bgp_info *bi; /* VPN bi */ - struct route_node *rn; /* parent node */ +struct rfapi_monitor_encap { + struct rfapi_monitor_encap *next; + struct rfapi_monitor_encap *prev; + struct route_node *node; /* VPN node */ + struct bgp_info *bi; /* VPN bi */ + struct route_node *rn; /* parent node */ }; -struct rfapi_monitor_eth -{ - struct rfapi_monitor_eth *next; /* for use in vpn0_queries list */ - struct rfapi_descriptor *rfd; /* which NVE requested the route */ - struct ethaddr macaddr; - uint32_t logical_net_id; - struct thread *timer; +struct rfapi_monitor_eth { + struct rfapi_monitor_eth *next; /* for use in vpn0_queries list */ + struct rfapi_descriptor *rfd; /* which NVE requested the route */ + struct ethaddr macaddr; + uint32_t logical_net_id; + struct thread *timer; }; /* @@ -75,142 +72,119 @@ struct rfapi_monitor_eth * - one lock per chained struct rfapi_monitor_encap * */ -struct rfapi_it_extra -{ - union - { - struct - { - struct rfapi_monitor_vpn *v; - struct skiplist *idx_rd; /* RD index */ - struct skiplist *mon_eth; /* ether queries */ - struct - { - /* routes with UN addrs, either cached encap or Encap TLV */ - int valid_interior_count; - - /* unicast exterior routes, key=bi, val=allocated prefix */ - struct skiplist *source; - } e; - } vpn; - struct - { - struct rfapi_monitor_encap *e; - } encap; - } u; +struct rfapi_it_extra { + union { + struct { + struct rfapi_monitor_vpn *v; + struct skiplist *idx_rd; /* RD index */ + struct skiplist *mon_eth; /* ether queries */ + struct { + /* routes with UN addrs, either cached encap or + * Encap TLV */ + int valid_interior_count; + + /* unicast exterior routes, key=bi, + * val=allocated prefix */ + struct skiplist *source; + } e; + } vpn; + struct { + struct rfapi_monitor_encap *e; + } encap; + } u; }; -#define RFAPI_IT_EXTRA_GET(rn) ((struct rfapi_it_extra *)( \ - (rn)->aggregate? (rn)->aggregate: \ - (route_lock_node(rn), (rn)->aggregate = \ - XCALLOC(MTYPE_RFAPI_IT_EXTRA,sizeof(struct rfapi_it_extra))))) +#define RFAPI_IT_EXTRA_GET(rn) \ + ((struct rfapi_it_extra \ + *)((rn)->aggregate \ + ? (rn)->aggregate \ + : (route_lock_node(rn), \ + (rn)->aggregate = XCALLOC( \ + MTYPE_RFAPI_IT_EXTRA, \ + sizeof(struct rfapi_it_extra))))) -#define RFAPI_RDINDEX(rn) \ - ((rn)->aggregate ? RFAPI_IT_EXTRA_GET(rn)->u.vpn.idx_rd : NULL) +#define RFAPI_RDINDEX(rn) \ + ((rn)->aggregate ? RFAPI_IT_EXTRA_GET(rn)->u.vpn.idx_rd : NULL) #define RFAPI_RDINDEX_W_ALLOC(rn) (RFAPI_IT_EXTRA_GET(rn)->u.vpn.idx_rd) -#define RFAPI_MONITOR_ETH(rn) \ - ((rn)->aggregate ? RFAPI_IT_EXTRA_GET(rn)->u.vpn.mon_eth : NULL) +#define RFAPI_MONITOR_ETH(rn) \ + ((rn)->aggregate ? RFAPI_IT_EXTRA_GET(rn)->u.vpn.mon_eth : NULL) #define RFAPI_MONITOR_ETH_W_ALLOC(rn) (RFAPI_IT_EXTRA_GET(rn)->u.vpn.mon_eth) -#define RFAPI_MONITOR_VPN(rn) \ - ((rn)->aggregate ? RFAPI_IT_EXTRA_GET(rn)->u.vpn.v : NULL) +#define RFAPI_MONITOR_VPN(rn) \ + ((rn)->aggregate ? RFAPI_IT_EXTRA_GET(rn)->u.vpn.v : NULL) #define RFAPI_MONITOR_VPN_W_ALLOC(rn) (RFAPI_IT_EXTRA_GET(rn)->u.vpn.v) -#define RFAPI_MONITOR_ENCAP(rn) \ - ((rn)->aggregate ? RFAPI_IT_EXTRA_GET(rn)->u.encap.e : NULL) +#define RFAPI_MONITOR_ENCAP(rn) \ + ((rn)->aggregate ? RFAPI_IT_EXTRA_GET(rn)->u.encap.e : NULL) #define RFAPI_MONITOR_ENCAP_W_ALLOC(rn) (RFAPI_IT_EXTRA_GET(rn)->u.encap.e) #define RFAPI_MONITOR_EXTERIOR(rn) (&(RFAPI_IT_EXTRA_GET(rn)->u.vpn.e)) -#define RFAPI_HAS_MONITOR_EXTERIOR(rn) (rn && rn->aggregate && \ - ((struct rfapi_it_extra *)(rn->aggregate))->u.vpn.e.source && \ - !skiplist_first(((struct rfapi_it_extra *)(rn->aggregate))-> \ - u.vpn.e.source, NULL, NULL)) +#define RFAPI_HAS_MONITOR_EXTERIOR(rn) \ + (rn && rn->aggregate \ + && ((struct rfapi_it_extra *)(rn->aggregate))->u.vpn.e.source \ + && !skiplist_first(((struct rfapi_it_extra *)(rn->aggregate)) \ + ->u.vpn.e.source, \ + NULL, NULL)) -extern void -rfapiMonitorLoopCheck (struct rfapi_monitor_vpn *mchain); +extern void rfapiMonitorLoopCheck(struct rfapi_monitor_vpn *mchain); -extern void -rfapiMonitorCleanCheck (struct bgp *bgp); +extern void rfapiMonitorCleanCheck(struct bgp *bgp); -extern void -rfapiMonitorCheckAttachAllowed (void); +extern void rfapiMonitorCheckAttachAllowed(void); -extern void -rfapiMonitorExtraFlush (safi_t safi, struct route_node *rn); +extern void rfapiMonitorExtraFlush(safi_t safi, struct route_node *rn); extern struct route_node * -rfapiMonitorGetAttachNode (struct rfapi_descriptor *rfd, struct prefix *p); +rfapiMonitorGetAttachNode(struct rfapi_descriptor *rfd, struct prefix *p); -extern void -rfapiMonitorAttachImportHd (struct rfapi_descriptor *rfd); +extern void rfapiMonitorAttachImportHd(struct rfapi_descriptor *rfd); -extern struct route_node * -rfapiMonitorAdd ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct prefix *p); +extern struct route_node *rfapiMonitorAdd(struct bgp *bgp, + struct rfapi_descriptor *rfd, + struct prefix *p); -extern void -rfapiMonitorDetachImportHd (struct rfapi_descriptor *rfd); +extern void rfapiMonitorDetachImportHd(struct rfapi_descriptor *rfd); -extern void -rfapiMonitorDel ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct prefix *p); +extern void rfapiMonitorDel(struct bgp *bgp, struct rfapi_descriptor *rfd, + struct prefix *p); -extern int -rfapiMonitorDelHd (struct rfapi_descriptor *rfd); +extern int rfapiMonitorDelHd(struct rfapi_descriptor *rfd); -extern void -rfapiMonitorCallbacksOff (struct bgp *bgp); +extern void rfapiMonitorCallbacksOff(struct bgp *bgp); -extern void -rfapiMonitorCallbacksOn (struct bgp *bgp); +extern void rfapiMonitorCallbacksOn(struct bgp *bgp); -extern void -rfapiMonitorResponseRemovalOff (struct bgp *bgp); +extern void rfapiMonitorResponseRemovalOff(struct bgp *bgp); -extern void -rfapiMonitorResponseRemovalOn (struct bgp *bgp); +extern void rfapiMonitorResponseRemovalOn(struct bgp *bgp); -extern void -rfapiMonitorExtraPrune (safi_t safi, struct route_node *rn); +extern void rfapiMonitorExtraPrune(safi_t safi, struct route_node *rn); -extern void -rfapiMonitorTimersRestart (struct rfapi_descriptor *rfd, struct prefix *p); +extern void rfapiMonitorTimersRestart(struct rfapi_descriptor *rfd, + struct prefix *p); -extern void -rfapiMonitorItNodeChanged ( - struct rfapi_import_table *import_table, - struct route_node *it_node, - struct rfapi_monitor_vpn *monitor_list); +extern void rfapiMonitorItNodeChanged(struct rfapi_import_table *import_table, + struct route_node *it_node, + struct rfapi_monitor_vpn *monitor_list); -extern void -rfapiMonitorMovedUp ( - struct rfapi_import_table *import_table, - struct route_node *old_node, - struct route_node *new_node, - struct rfapi_monitor_vpn *monitor_list); +extern void rfapiMonitorMovedUp(struct rfapi_import_table *import_table, + struct route_node *old_node, + struct route_node *new_node, + struct rfapi_monitor_vpn *monitor_list); -extern struct route_node * -rfapiMonitorEthAdd ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct ethaddr *macaddr, - uint32_t logical_net_id); - -extern void -rfapiMonitorEthDel ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct ethaddr *macaddr, - uint32_t logical_net_id); +extern struct route_node *rfapiMonitorEthAdd(struct bgp *bgp, + struct rfapi_descriptor *rfd, + struct ethaddr *macaddr, + uint32_t logical_net_id); + +extern void rfapiMonitorEthDel(struct bgp *bgp, struct rfapi_descriptor *rfd, + struct ethaddr *macaddr, + uint32_t logical_net_id); #endif /* QUAGGA_HGP_RFAPI_MONITOR_H */ diff --git a/bgpd/rfapi/rfapi_nve_addr.c b/bgpd/rfapi/rfapi_nve_addr.c index f80455bbe..0fb887912 100644 --- a/bgpd/rfapi/rfapi_nve_addr.c +++ b/bgpd/rfapi/rfapi_nve_addr.c @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -41,135 +41,118 @@ #define DEBUG_NVE_ADDR 0 -void rfapiNveAddr2Str (struct rfapi_nve_addr *, char *, int); +void rfapiNveAddr2Str(struct rfapi_nve_addr *, char *, int); #if DEBUG_NVE_ADDR -static void -logdifferent (const char *tag, - struct rfapi_nve_addr *a, struct rfapi_nve_addr *b) +static void logdifferent(const char *tag, struct rfapi_nve_addr *a, + struct rfapi_nve_addr *b) { - char a_str[BUFSIZ]; - char b_str[BUFSIZ]; + char a_str[BUFSIZ]; + char b_str[BUFSIZ]; - rfapiNveAddr2Str (a, a_str, BUFSIZ); - rfapiNveAddr2Str (b, b_str, BUFSIZ); - vnc_zlog_debug_verbose ("%s: [%s] [%s]", tag, a_str, b_str); + rfapiNveAddr2Str(a, a_str, BUFSIZ); + rfapiNveAddr2Str(b, b_str, BUFSIZ); + vnc_zlog_debug_verbose("%s: [%s] [%s]", tag, a_str, b_str); } #endif -int -rfapi_nve_addr_cmp (void *k1, void *k2) +int rfapi_nve_addr_cmp(void *k1, void *k2) { - struct rfapi_nve_addr *a = (struct rfapi_nve_addr *) k1; - struct rfapi_nve_addr *b = (struct rfapi_nve_addr *) k2; - int ret = 0; + struct rfapi_nve_addr *a = (struct rfapi_nve_addr *)k1; + struct rfapi_nve_addr *b = (struct rfapi_nve_addr *)k2; + int ret = 0; - if (!a || !b) - { + if (!a || !b) { #if DEBUG_NVE_ADDR - vnc_zlog_debug_verbose ("%s: missing address a=%p b=%p", __func__, a, b); + vnc_zlog_debug_verbose("%s: missing address a=%p b=%p", + __func__, a, b); #endif - return (a - b); - } - if (a->un.addr_family != b->un.addr_family) - { + return (a - b); + } + if (a->un.addr_family != b->un.addr_family) { #if DEBUG_NVE_ADDR - vnc_zlog_debug_verbose ("diff: UN addr fam a->un.af=%d, b->un.af=%d", - a->un.addr_family, b->un.addr_family); + vnc_zlog_debug_verbose( + "diff: UN addr fam a->un.af=%d, b->un.af=%d", + a->un.addr_family, b->un.addr_family); #endif - return (a->un.addr_family - b->un.addr_family); - } - if (a->un.addr_family == AF_INET) - { - ret = IPV4_ADDR_CMP (&a->un.addr.v4, &b->un.addr.v4); - if (ret != 0) - { + return (a->un.addr_family - b->un.addr_family); + } + if (a->un.addr_family == AF_INET) { + ret = IPV4_ADDR_CMP(&a->un.addr.v4, &b->un.addr.v4); + if (ret != 0) { #if DEBUG_NVE_ADDR - logdifferent ("diff: UN addr", a, b); + logdifferent("diff: UN addr", a, b); #endif - return ret; - } - } - else if (a->un.addr_family == AF_INET6) - { - ret = IPV6_ADDR_CMP (&a->un.addr.v6, &b->un.addr.v6); - if (ret == 0) - { + return ret; + } + } else if (a->un.addr_family == AF_INET6) { + ret = IPV6_ADDR_CMP(&a->un.addr.v6, &b->un.addr.v6); + if (ret == 0) { #if DEBUG_NVE_ADDR - logdifferent ("diff: UN addr", a, b); + logdifferent("diff: UN addr", a, b); #endif - return ret; - } - } - else - { - assert (0); - } - if (a->vn.addr_family != b->vn.addr_family) - { + return ret; + } + } else { + assert(0); + } + if (a->vn.addr_family != b->vn.addr_family) { #if DEBUG_NVE_ADDR - vnc_zlog_debug_verbose ("diff: pT addr fam a->vn.af=%d, b->vn.af=%d", - a->vn.addr_family, b->vn.addr_family); + vnc_zlog_debug_verbose( + "diff: pT addr fam a->vn.af=%d, b->vn.af=%d", + a->vn.addr_family, b->vn.addr_family); #endif - return (a->vn.addr_family - b->vn.addr_family); - } - if (a->vn.addr_family == AF_INET) - { - ret = IPV4_ADDR_CMP (&a->vn.addr.v4, &b->vn.addr.v4); - if (ret != 0) - { + return (a->vn.addr_family - b->vn.addr_family); + } + if (a->vn.addr_family == AF_INET) { + ret = IPV4_ADDR_CMP(&a->vn.addr.v4, &b->vn.addr.v4); + if (ret != 0) { #if DEBUG_NVE_ADDR - logdifferent ("diff: VN addr", a, b); + logdifferent("diff: VN addr", a, b); #endif - return ret; - } - } - else if (a->vn.addr_family == AF_INET6) - { - ret = IPV6_ADDR_CMP (&a->vn.addr.v6, &b->vn.addr.v6); - if (ret == 0) - { + return ret; + } + } else if (a->vn.addr_family == AF_INET6) { + ret = IPV6_ADDR_CMP(&a->vn.addr.v6, &b->vn.addr.v6); + if (ret == 0) { #if DEBUG_NVE_ADDR - logdifferent ("diff: VN addr", a, b); + logdifferent("diff: VN addr", a, b); #endif - return ret; - } - } - else - { - assert (0); - } - return 0; + return ret; + } + } else { + assert(0); + } + return 0; } -void -rfapiNveAddr2Str (struct rfapi_nve_addr *na, char *buf, int bufsize) +void rfapiNveAddr2Str(struct rfapi_nve_addr *na, char *buf, int bufsize) { - char *p = buf; - int r; + char *p = buf; + int r; #define REMAIN (bufsize - (p-buf)) #define INCP {p += (r > REMAIN)? REMAIN: r;} - if (bufsize < 1) - return; + if (bufsize < 1) + return; - r = snprintf (p, REMAIN, "VN="); - INCP; + r = snprintf(p, REMAIN, "VN="); + INCP; - if (!rfapiRfapiIpAddr2Str (&na->vn, p, REMAIN)) - goto done; + if (!rfapiRfapiIpAddr2Str(&na->vn, p, REMAIN)) + goto done; - buf[bufsize - 1] = 0; - p = buf + strlen (buf); + buf[bufsize - 1] = 0; + p = buf + strlen(buf); - r = snprintf (p, REMAIN, ", UN="); - INCP; + r = snprintf(p, REMAIN, ", UN="); + INCP; - rfapiRfapiIpAddr2Str (&na->un, p, REMAIN); + rfapiRfapiIpAddr2Str(&na->un, p, REMAIN); done: - buf[bufsize - 1] = 0; + buf[bufsize - 1] = 0; } diff --git a/bgpd/rfapi/rfapi_nve_addr.h b/bgpd/rfapi/rfapi_nve_addr.h index f2159d106..2d54d4a3c 100644 --- a/bgpd/rfapi/rfapi_nve_addr.h +++ b/bgpd/rfapi/rfapi_nve_addr.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -23,20 +23,16 @@ #include "rfapi.h" -struct rfapi_nve_addr -{ - struct rfapi_ip_addr vn; - struct rfapi_ip_addr un; - void *info; +struct rfapi_nve_addr { + struct rfapi_ip_addr vn; + struct rfapi_ip_addr un; + void *info; }; -extern int -rfapi_nve_addr_cmp (void *k1, void *k2); - -extern void -rfapiNveAddr2Str (struct rfapi_nve_addr *na, char *buf, int bufsize); +extern int rfapi_nve_addr_cmp(void *k1, void *k2); +extern void rfapiNveAddr2Str(struct rfapi_nve_addr *na, char *buf, int bufsize); #endif /* _QUAGGA_BGP_RFAPI_NVE_ADDR_H */ diff --git a/bgpd/rfapi/rfapi_private.h b/bgpd/rfapi/rfapi_private.h index 5a6936fcc..e7a3e5aae 100644 --- a/bgpd/rfapi/rfapi_private.h +++ b/bgpd/rfapi/rfapi_private.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -/* +/* * Internal definitions for RFAPI. Not for use by other code */ @@ -40,96 +40,94 @@ * 1. each is referenced in by_lifetime * 2. each is referenced by exactly one of: ipN_by_prefix, ip0_by_ether */ -struct rfapi_advertised_prefixes -{ - struct skiplist *ipN_by_prefix; /* all except 0/32, 0/128 */ - struct skiplist *ip0_by_ether; /* ip prefix 0/32, 0/128 */ - struct skiplist *by_lifetime; /* all */ +struct rfapi_advertised_prefixes { + struct skiplist *ipN_by_prefix; /* all except 0/32, 0/128 */ + struct skiplist *ip0_by_ether; /* ip prefix 0/32, 0/128 */ + struct skiplist *by_lifetime; /* all */ }; -struct rfapi_descriptor -{ - struct route_node *un_node; /* backref to un table */ - - struct rfapi_descriptor *next; /* next vn_addr */ - - /* supplied by client */ - struct bgp *bgp; /* from rfp_start_val */ - struct rfapi_ip_addr vn_addr; - struct rfapi_ip_addr un_addr; - rfapi_response_cb_t *response_cb; /* override per-bgp response_cb */ - void *cookie; /* for callbacks */ - struct rfapi_tunneltype_option default_tunneltype_option; - - /* supplied by matched configuration */ - struct prefix_rd rd; - struct ecommunity *rt_export_list; - uint32_t response_lifetime; - - /* list of prefixes currently being advertised by this nve */ - struct rfapi_advertised_prefixes advertised; - - time_t open_time; - - uint32_t max_prefix_lifetime; - uint32_t min_prefix_lifetime; - - /* reference to this nve's import table */ - struct rfapi_import_table *import_table; - - uint32_t monitor_count; - struct route_table *mon; /* rfapi_monitors */ - struct skiplist *mon_eth; /* ethernet monitors */ - - /* - * rib RIB as seen by NVE - * rib_pending RIB containing nodes with updated info chains - * rsp_times last time we sent response containing pfx - */ - uint32_t rib_prefix_count; /* pfxes with routes */ - struct route_table *rib[AFI_MAX]; - struct route_table *rib_pending[AFI_MAX]; - struct work_queue *updated_responses_queue; - struct route_table *rsp_times[AFI_MAX]; - - uint32_t rsp_counter; /* dedup initial rsp */ - time_t rsp_time; /* dedup initial rsp */ - time_t ftd_last_allowed_time; /* FTD filter */ - - unsigned int stat_count_nh_reachable; - unsigned int stat_count_nh_removal; - - /* - * points to the original nve group structure that matched - * when this nve_descriptor was created. We use this pointer - * in rfapi_close() to find the nve group structure and - * delete its reference back to us. - * - * If the nve group structure is deleted (via configuration - * change) while this nve_descriptor exists, this rfg pointer - * will be set to NULL. - */ - struct rfapi_nve_group_cfg *rfg; - - /* - * This ~7kB structure is here to permit multiple routes for - * a prefix to be injected to BGP. There are at least two - * situations where such conditions obtain: - * - * When an VNC route is exported to BGP on behalf of the set of - * NVEs that belong to the export NVE group, it is replicated - * so that there is one route per NVE (and the route's nexthop - * is the NVE's VN address). - * - * Each of these routes being injected to BGP must have a distinct - * peer pointer (otherwise, if they have the same peer pointer, each - * route will be considered an implicit waithdraw of the previous - * route injected from that peer, and the new route will replace - * rather than augment the old one(s)). - */ - struct peer *peer; - - uint32_t flags; +struct rfapi_descriptor { + struct route_node *un_node; /* backref to un table */ + + struct rfapi_descriptor *next; /* next vn_addr */ + + /* supplied by client */ + struct bgp *bgp; /* from rfp_start_val */ + struct rfapi_ip_addr vn_addr; + struct rfapi_ip_addr un_addr; + rfapi_response_cb_t *response_cb; /* override per-bgp response_cb */ + void *cookie; /* for callbacks */ + struct rfapi_tunneltype_option default_tunneltype_option; + + /* supplied by matched configuration */ + struct prefix_rd rd; + struct ecommunity *rt_export_list; + uint32_t response_lifetime; + + /* list of prefixes currently being advertised by this nve */ + struct rfapi_advertised_prefixes advertised; + + time_t open_time; + + uint32_t max_prefix_lifetime; + uint32_t min_prefix_lifetime; + + /* reference to this nve's import table */ + struct rfapi_import_table *import_table; + + uint32_t monitor_count; + struct route_table *mon; /* rfapi_monitors */ + struct skiplist *mon_eth; /* ethernet monitors */ + + /* + * rib RIB as seen by NVE + * rib_pending RIB containing nodes with updated info chains + * rsp_times last time we sent response containing pfx + */ + uint32_t rib_prefix_count; /* pfxes with routes */ + struct route_table *rib[AFI_MAX]; + struct route_table *rib_pending[AFI_MAX]; + struct work_queue *updated_responses_queue; + struct route_table *rsp_times[AFI_MAX]; + + uint32_t rsp_counter; /* dedup initial rsp */ + time_t rsp_time; /* dedup initial rsp */ + time_t ftd_last_allowed_time; /* FTD filter */ + + unsigned int stat_count_nh_reachable; + unsigned int stat_count_nh_removal; + + /* + * points to the original nve group structure that matched + * when this nve_descriptor was created. We use this pointer + * in rfapi_close() to find the nve group structure and + * delete its reference back to us. + * + * If the nve group structure is deleted (via configuration + * change) while this nve_descriptor exists, this rfg pointer + * will be set to NULL. + */ + struct rfapi_nve_group_cfg *rfg; + + /* + * This ~7kB structure is here to permit multiple routes for + * a prefix to be injected to BGP. There are at least two + * situations where such conditions obtain: + * + * When an VNC route is exported to BGP on behalf of the set of + * NVEs that belong to the export NVE group, it is replicated + * so that there is one route per NVE (and the route's nexthop + * is the NVE's VN address). + * + * Each of these routes being injected to BGP must have a distinct + * peer pointer (otherwise, if they have the same peer pointer, each + * route will be considered an implicit waithdraw of the previous + * route injected from that peer, and the new route will replace + * rather than augment the old one(s)). + */ + struct peer *peer; + + uint32_t flags; #define RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_IP 0x00000001 #define RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_IP6 0x00000002 #define RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_L2VPN 0x00000004 @@ -138,30 +136,32 @@ struct rfapi_descriptor #define RFAPI_HD_FLAG_IS_VRF 0x00000012 }; -#define RFAPI_QUEUED_FLAG(afi) ( \ - ((afi) == AFI_IP)? RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_IP: \ - (((afi) == AFI_IP6)? RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_IP6: \ - (((afi) == AFI_L2VPN)? RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_L2VPN: \ - (assert(0), 0) ))) +#define RFAPI_QUEUED_FLAG(afi) \ + (((afi) == AFI_IP) \ + ? RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_IP \ + : (((afi) == AFI_IP6) \ + ? RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_IP6 \ + : (((afi) == AFI_L2VPN) \ + ? RFAPI_HD_FLAG_CALLBACK_SCHEDULED_AFI_L2VPN \ + : (assert(0), 0)))) -struct rfapi_global_stats -{ - time_t last_reset; - unsigned int max_descriptors; +struct rfapi_global_stats { + time_t last_reset; + unsigned int max_descriptors; - unsigned int count_unknown_nves; + unsigned int count_unknown_nves; - unsigned int count_queries; - unsigned int count_queries_failed; + unsigned int count_queries; + unsigned int count_queries_failed; - unsigned int max_responses; /* semantics? */ + unsigned int max_responses; /* semantics? */ - unsigned int count_registrations; - unsigned int count_registrations_failed; + unsigned int count_registrations; + unsigned int count_registrations_failed; - unsigned int count_updated_response_updates; - unsigned int count_updated_response_deletes; + unsigned int count_updated_response_updates; + unsigned int count_updated_response_deletes; }; /* @@ -170,220 +170,187 @@ struct rfapi_global_stats * Radix tree is indexed by un address; follow chain and * check vn address to get exact match. */ -struct rfapi -{ - struct route_table un[AFI_MAX]; - struct rfapi_import_table *imports; /* IPv4, IPv6 */ - struct list descriptors;/* debug & resolve-nve imports */ - - struct rfapi_global_stats stat; - - /* - * callbacks into RFP, set at startup time (bgp_rfapi_new() gets - * values from rfp_start()) or via rfapi_rfp_set_cb_methods() - * (otherwise NULL). Note that the response_cb method can also - * be overridden per-rfd (currently used only for debug/test scenarios) - */ - struct rfapi_rfp_cb_methods rfp_methods; - - /* - * Import tables for Ethernet over IPSEC - * - * The skiplist keys are LNIs. Values are pointers - * to struct rfapi_import_table. - */ - struct skiplist *import_mac; /* L2 */ - - /* - * when exporting plain routes ("registered-nve" mode) to - * bgp unicast or zebra, we need to keep track of information - * related to expiring the routes according to the VNC lifetime - */ - struct route_table *rt_export_bgp[AFI_MAX]; - struct route_table *rt_export_zebra[AFI_MAX]; - - /* - * For VNC->BGP unicast exports in CE mode, we need a - * routing table that collects all of the VPN routes - * in a single tree. The VPN rib is split up according - * to RD first, so we can't use that. This is an import - * table that matches all RTs. - */ - struct rfapi_import_table *it_ce; - - /* - * when importing bgp-direct routes in resolve-nve mode, - * this list maps unicast route nexthops to their bgp_infos - * in the unicast table - */ - struct skiplist *resolve_nve_nexthop; - - /* - * Descriptors for which rfapi_close() was called during a callback. - * They will be closed after the callback finishes. - */ - struct work_queue *deferred_close_q; - - /* - * For "show vnc responses" - */ - uint32_t response_immediate_count; - uint32_t response_updated_count; - uint32_t monitor_count; - - uint32_t rib_prefix_count_total; - uint32_t rib_prefix_count_total_max; - - uint32_t flags; +struct rfapi { + struct route_table un[AFI_MAX]; + struct rfapi_import_table *imports; /* IPv4, IPv6 */ + struct list descriptors; /* debug & resolve-nve imports */ + + struct rfapi_global_stats stat; + + /* + * callbacks into RFP, set at startup time (bgp_rfapi_new() gets + * values from rfp_start()) or via rfapi_rfp_set_cb_methods() + * (otherwise NULL). Note that the response_cb method can also + * be overridden per-rfd (currently used only for debug/test scenarios) + */ + struct rfapi_rfp_cb_methods rfp_methods; + + /* + * Import tables for Ethernet over IPSEC + * + * The skiplist keys are LNIs. Values are pointers + * to struct rfapi_import_table. + */ + struct skiplist *import_mac; /* L2 */ + + /* + * when exporting plain routes ("registered-nve" mode) to + * bgp unicast or zebra, we need to keep track of information + * related to expiring the routes according to the VNC lifetime + */ + struct route_table *rt_export_bgp[AFI_MAX]; + struct route_table *rt_export_zebra[AFI_MAX]; + + /* + * For VNC->BGP unicast exports in CE mode, we need a + * routing table that collects all of the VPN routes + * in a single tree. The VPN rib is split up according + * to RD first, so we can't use that. This is an import + * table that matches all RTs. + */ + struct rfapi_import_table *it_ce; + + /* + * when importing bgp-direct routes in resolve-nve mode, + * this list maps unicast route nexthops to their bgp_infos + * in the unicast table + */ + struct skiplist *resolve_nve_nexthop; + + /* + * Descriptors for which rfapi_close() was called during a callback. + * They will be closed after the callback finishes. + */ + struct work_queue *deferred_close_q; + + /* + * For "show vnc responses" + */ + uint32_t response_immediate_count; + uint32_t response_updated_count; + uint32_t monitor_count; + + uint32_t rib_prefix_count_total; + uint32_t rib_prefix_count_total_max; + + uint32_t flags; #define RFAPI_INCALLBACK 0x00000001 - void *rfp; /* from rfp_start */ + void *rfp; /* from rfp_start */ }; -#define RFAPI_RIB_PREFIX_COUNT_INCR(rfd, rfapi) do { \ - ++(rfd)->rib_prefix_count; \ - ++(rfapi)->rib_prefix_count_total; \ - if ((rfapi)->rib_prefix_count_total > (rfapi)->rib_prefix_count_total_max) \ - ++(rfapi)->rib_prefix_count_total_max; \ - } while (0) - -#define RFAPI_RIB_PREFIX_COUNT_DECR(rfd, rfapi) do { \ - --(rfd)->rib_prefix_count; \ - --(rfapi)->rib_prefix_count_total; \ - } while (0) - -#define RFAPI_0_PREFIX(prefix) ( \ - (((prefix)->family == AF_INET)? (prefix)->u.prefix4.s_addr == 0: \ - (((prefix)->family == AF_INET6)? \ - (IN6_IS_ADDR_UNSPECIFIED(&(prefix)->u.prefix6)) : 0)) \ -) - -#define RFAPI_0_ETHERADDR(ea) ( \ - ((ea)->octet[0] | (ea)->octet[1] | (ea)->octet[2] | \ - (ea)->octet[3] | (ea)->octet[4] | (ea)->octet[5]) == 0) - -#define RFAPI_HOST_PREFIX(prefix) ( \ - ((prefix)->family == AF_INET)? ((prefix)->prefixlen == 32): \ - (((prefix)->family == AF_INET6)? ((prefix)->prefixlen == 128): 0) ) - -extern void -rfapiQprefix2Rprefix ( - struct prefix *qprefix, - struct rfapi_ip_prefix *rprefix); - -extern int -rfapi_find_rfd ( - struct bgp *bgp, - struct rfapi_ip_addr *vn_addr, - struct rfapi_ip_addr *un_addr, - struct rfapi_descriptor **rfd); +#define RFAPI_RIB_PREFIX_COUNT_INCR(rfd, rfapi) \ + do { \ + ++(rfd)->rib_prefix_count; \ + ++(rfapi)->rib_prefix_count_total; \ + if ((rfapi)->rib_prefix_count_total \ + > (rfapi)->rib_prefix_count_total_max) \ + ++(rfapi)->rib_prefix_count_total_max; \ + } while (0) + +#define RFAPI_RIB_PREFIX_COUNT_DECR(rfd, rfapi) \ + do { \ + --(rfd)->rib_prefix_count; \ + --(rfapi)->rib_prefix_count_total; \ + } while (0) + +#define RFAPI_0_PREFIX(prefix) \ + ((((prefix)->family == AF_INET) \ + ? (prefix)->u.prefix4.s_addr == 0 \ + : (((prefix)->family == AF_INET6) \ + ? (IN6_IS_ADDR_UNSPECIFIED(&(prefix)->u.prefix6)) \ + : 0))) + +#define RFAPI_0_ETHERADDR(ea) \ + (((ea)->octet[0] | (ea)->octet[1] | (ea)->octet[2] | (ea)->octet[3] \ + | (ea)->octet[4] | (ea)->octet[5]) \ + == 0) + +#define RFAPI_HOST_PREFIX(prefix) \ + (((prefix)->family == AF_INET) \ + ? ((prefix)->prefixlen == 32) \ + : (((prefix)->family == AF_INET6) \ + ? ((prefix)->prefixlen == 128) \ + : 0)) + +extern void rfapiQprefix2Rprefix(struct prefix *qprefix, + struct rfapi_ip_prefix *rprefix); + +extern int rfapi_find_rfd(struct bgp *bgp, struct rfapi_ip_addr *vn_addr, + struct rfapi_ip_addr *un_addr, + struct rfapi_descriptor **rfd); extern void -add_vnc_route ( - struct rfapi_descriptor *rfd, /* cookie + UN addr for VPN */ - struct bgp *bgp, - int safi, - struct prefix *p, - struct prefix_rd *prd, - struct rfapi_ip_addr *nexthop, - uint32_t *local_pref, /* host byte order */ - uint32_t *lifetime, /* host byte order */ - struct bgp_tea_options *rfp_options, - struct rfapi_un_option *options_un, - struct rfapi_vn_option *options_vn, - struct ecommunity *rt_export_list, - uint32_t *med, - uint32_t *label, - uint8_t type, - uint8_t sub_type, - int flags); +add_vnc_route(struct rfapi_descriptor *rfd, /* cookie + UN addr for VPN */ + struct bgp *bgp, int safi, struct prefix *p, + struct prefix_rd *prd, struct rfapi_ip_addr *nexthop, + uint32_t *local_pref, /* host byte order */ + uint32_t *lifetime, /* host byte order */ + struct bgp_tea_options *rfp_options, + struct rfapi_un_option *options_un, + struct rfapi_vn_option *options_vn, + struct ecommunity *rt_export_list, uint32_t *med, uint32_t *label, + uint8_t type, uint8_t sub_type, int flags); #define RFAPI_AHR_NO_TUNNEL_SUBTLV 0x00000001 #define RFAPI_AHR_RFPOPT_IS_VNCTLV 0x00000002 /* hack! */ -#if 0 /* unused? */ +#if 0 /* unused? */ # define RFAPI_AHR_SET_PFX_TO_NEXTHOP 0x00000004 #endif -extern void -del_vnc_route ( - struct rfapi_descriptor *rfd, - struct peer *peer, - struct bgp *bgp, - safi_t safi, - struct prefix *p, - struct prefix_rd *prd, - uint8_t type, - uint8_t sub_type, - struct rfapi_nexthop *lnh, - int kill); +extern void del_vnc_route(struct rfapi_descriptor *rfd, struct peer *peer, + struct bgp *bgp, safi_t safi, struct prefix *p, + struct prefix_rd *prd, uint8_t type, uint8_t sub_type, + struct rfapi_nexthop *lnh, int kill); -extern int -rfapiCliGetPrefixAddr (struct vty *vty, const char *str, struct prefix *p); +extern int rfapiCliGetPrefixAddr(struct vty *vty, const char *str, + struct prefix *p); -extern int -rfapiGetVncLifetime (struct attr *attr, uint32_t * lifetime); +extern int rfapiGetVncLifetime(struct attr *attr, uint32_t *lifetime); -extern int -rfapiGetTunnelType (struct attr *attr, bgp_encap_types *type); +extern int rfapiGetTunnelType(struct attr *attr, bgp_encap_types *type); -extern int -rfapiGetVncTunnelUnAddr (struct attr *attr, struct prefix *p); +extern int rfapiGetVncTunnelUnAddr(struct attr *attr, struct prefix *p); -extern int -rfapi_reopen (struct rfapi_descriptor *rfd, struct bgp *bgp); +extern int rfapi_reopen(struct rfapi_descriptor *rfd, struct bgp *bgp); -extern void -vnc_import_bgp_add_rfp_host_route_mode_resolve_nve ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct prefix *prefix); +extern void vnc_import_bgp_add_rfp_host_route_mode_resolve_nve( + struct bgp *bgp, struct rfapi_descriptor *rfd, struct prefix *prefix); -extern void -vnc_import_bgp_del_rfp_host_route_mode_resolve_nve ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct prefix *prefix); +extern void vnc_import_bgp_del_rfp_host_route_mode_resolve_nve( + struct bgp *bgp, struct rfapi_descriptor *rfd, struct prefix *prefix); -extern void -rfapiFreeBgpTeaOptionChain (struct bgp_tea_options *p); +extern void rfapiFreeBgpTeaOptionChain(struct bgp_tea_options *p); -extern struct rfapi_vn_option * -rfapiVnOptionsDup (struct rfapi_vn_option *orig); +extern struct rfapi_vn_option *rfapiVnOptionsDup(struct rfapi_vn_option *orig); -extern struct rfapi_un_option * -rfapiUnOptionsDup (struct rfapi_un_option *orig); +extern struct rfapi_un_option *rfapiUnOptionsDup(struct rfapi_un_option *orig); -extern struct bgp_tea_options * -rfapiOptionsDup (struct bgp_tea_options *orig); +extern struct bgp_tea_options *rfapiOptionsDup(struct bgp_tea_options *orig); -extern int -rfapi_ip_addr_cmp (struct rfapi_ip_addr *a1, struct rfapi_ip_addr *a2); +extern int rfapi_ip_addr_cmp(struct rfapi_ip_addr *a1, + struct rfapi_ip_addr *a2); -extern uint32_t -rfp_cost_to_localpref (uint8_t cost); +extern uint32_t rfp_cost_to_localpref(uint8_t cost); -extern int -rfapi_set_autord_from_vn (struct prefix_rd *rd, struct rfapi_ip_addr *vn); +extern int rfapi_set_autord_from_vn(struct prefix_rd *rd, + struct rfapi_ip_addr *vn); -extern struct rfapi_nexthop * -rfapi_nexthop_new (struct rfapi_nexthop *copyme); +extern struct rfapi_nexthop *rfapi_nexthop_new(struct rfapi_nexthop *copyme); -extern void -rfapi_nexthop_free (void *goner); +extern void rfapi_nexthop_free(void *goner); extern struct rfapi_vn_option * -rfapi_vn_options_dup (struct rfapi_vn_option *existing); +rfapi_vn_options_dup(struct rfapi_vn_option *existing); -extern void -rfapi_un_options_free (struct rfapi_un_option *goner); +extern void rfapi_un_options_free(struct rfapi_un_option *goner); -extern void -rfapi_vn_options_free (struct rfapi_vn_option *goner); +extern void rfapi_vn_options_free(struct rfapi_vn_option *goner); /*------------------------------------------ * rfapi_extract_l2o * - * Find Layer 2 options in an option chain + * Find Layer 2 options in an option chain * - * input: + * input: * pHop option chain * * output: @@ -394,17 +361,16 @@ rfapi_vn_options_free (struct rfapi_vn_option *goner); * 1 no options found * --------------------------------------------*/ -extern int -rfapi_extract_l2o ( - struct bgp_tea_options *pHop, /* chain of options */ - struct rfapi_l2address_option *l2o); /* return extracted value */ +extern int rfapi_extract_l2o( + struct bgp_tea_options *pHop, /* chain of options */ + struct rfapi_l2address_option *l2o); /* return extracted value */ -/* +/* * compaitibility to old quagga_time call - * time_t value in terms of stabilised absolute time. + * time_t value in terms of stabilised absolute time. * replacement for POSIX time() */ -extern time_t rfapi_time (time_t *t); +extern time_t rfapi_time(time_t *t); DECLARE_MGROUP(RFAPI) DECLARE_MTYPE(RFAPI_CFG) @@ -441,10 +407,7 @@ DECLARE_MTYPE(RFAPI_MONITOR_ETH) * The advertised_prefixes[] array elements should be NULL to * have this function set them to newly-allocated radix trees. */ -extern int -rfapi_init_and_open( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct rfapi_nve_group_cfg *rfg); +extern int rfapi_init_and_open(struct bgp *bgp, struct rfapi_descriptor *rfd, + struct rfapi_nve_group_cfg *rfg); #endif /* _QUAGGA_BGP_RFAPI_PRIVATE_H */ diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c index 902e70207..a414df1ab 100644 --- a/bgpd/rfapi/rfapi_rib.c +++ b/bgpd/rfapi/rfapi_rib.c @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -58,8 +58,8 @@ /* forward decl */ #if DEBUG_NHL -static void -rfapiRibShowRibSl (void *stream, struct prefix *pfx, struct skiplist *sl); +static void rfapiRibShowRibSl(void *stream, struct prefix *pfx, + struct skiplist *sl); #endif /* @@ -121,330 +121,295 @@ rfapiRibShowRibSl (void *stream, struct prefix *pfx, struct skiplist *sl); /* * iterate over RIB to count responses, compare with running counters */ -void -rfapiRibCheckCounts ( - int checkstats, /* validate rfd & global counts */ - unsigned int offset) /* number of ri's held separately */ +void rfapiRibCheckCounts( + int checkstats, /* validate rfd & global counts */ + unsigned int offset) /* number of ri's held separately */ { - struct rfapi_descriptor *rfd; - struct listnode *node; - - struct bgp *bgp = bgp_get_default (); - - uint32_t t_pfx_active = 0; - uint32_t t_pfx_deleted = 0; - - uint32_t t_ri_active = 0; - uint32_t t_ri_deleted = 0; - uint32_t t_ri_pend = 0; - - unsigned int alloc_count; - - /* - * loop over NVEs - */ - for (ALL_LIST_ELEMENTS_RO (&bgp->rfapi->descriptors, node, rfd)) - { - - afi_t afi; - uint32_t pfx_active = 0; - uint32_t pfx_deleted = 0; - - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - - struct route_node *rn; - - for (rn = route_top (rfd->rib[afi]); rn; rn = route_next (rn)) - { - - struct skiplist *sl = rn->info; - struct skiplist *dsl = rn->aggregate; - uint32_t ri_active = 0; - uint32_t ri_deleted = 0; - - if (sl) - { - ri_active = skiplist_count (sl); - assert (ri_active); - t_ri_active += ri_active; - ++pfx_active; - ++t_pfx_active; - } - - if (dsl) - { - ri_deleted = skiplist_count (dsl); - t_ri_deleted += ri_deleted; - ++pfx_deleted; - ++t_pfx_deleted; - } - } - for (rn = route_top (rfd->rib_pending[afi]); rn; - rn = route_next (rn)) - { - - struct list *l = rn->info; /* sorted by cost */ - struct skiplist *sl = rn->aggregate; - uint32_t ri_pend_cost = 0; - uint32_t ri_pend_uniq = 0; - - if (sl) - { - ri_pend_uniq = skiplist_count (sl); - } - - if (l && (l != (void *) 1)) - { - ri_pend_cost = l->count; - t_ri_pend += l->count; - } - - assert (ri_pend_uniq == ri_pend_cost); - } - } - - if (checkstats) - { - if (pfx_active != rfd->rib_prefix_count) - { - vnc_zlog_debug_verbose ("%s: rfd %p actual pfx count %u != running %u", - __func__, rfd, pfx_active, rfd->rib_prefix_count); - assert (0); - } - } - } - - if (checkstats && bgp && bgp->rfapi) - { - if (t_pfx_active != bgp->rfapi->rib_prefix_count_total) - { - vnc_zlog_debug_verbose ("%s: actual total pfx count %u != running %u", - __func__, t_pfx_active, - bgp->rfapi->rib_prefix_count_total); - assert (0); - } - } - - /* - * Check against memory allocation count - */ - alloc_count = mtype_stats_alloc (MTYPE_RFAPI_INFO); - assert (t_ri_active + t_ri_deleted + t_ri_pend + offset == alloc_count); + struct rfapi_descriptor *rfd; + struct listnode *node; + + struct bgp *bgp = bgp_get_default(); + + uint32_t t_pfx_active = 0; + uint32_t t_pfx_deleted = 0; + + uint32_t t_ri_active = 0; + uint32_t t_ri_deleted = 0; + uint32_t t_ri_pend = 0; + + unsigned int alloc_count; + + /* + * loop over NVEs + */ + for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, node, rfd)) { + + afi_t afi; + uint32_t pfx_active = 0; + uint32_t pfx_deleted = 0; + + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + + struct route_node *rn; + + for (rn = route_top(rfd->rib[afi]); rn; + rn = route_next(rn)) { + + struct skiplist *sl = rn->info; + struct skiplist *dsl = rn->aggregate; + uint32_t ri_active = 0; + uint32_t ri_deleted = 0; + + if (sl) { + ri_active = skiplist_count(sl); + assert(ri_active); + t_ri_active += ri_active; + ++pfx_active; + ++t_pfx_active; + } + + if (dsl) { + ri_deleted = skiplist_count(dsl); + t_ri_deleted += ri_deleted; + ++pfx_deleted; + ++t_pfx_deleted; + } + } + for (rn = route_top(rfd->rib_pending[afi]); rn; + rn = route_next(rn)) { + + struct list *l = rn->info; /* sorted by cost */ + struct skiplist *sl = rn->aggregate; + uint32_t ri_pend_cost = 0; + uint32_t ri_pend_uniq = 0; + + if (sl) { + ri_pend_uniq = skiplist_count(sl); + } + + if (l && (l != (void *)1)) { + ri_pend_cost = l->count; + t_ri_pend += l->count; + } + + assert(ri_pend_uniq == ri_pend_cost); + } + } + + if (checkstats) { + if (pfx_active != rfd->rib_prefix_count) { + vnc_zlog_debug_verbose( + "%s: rfd %p actual pfx count %u != running %u", + __func__, rfd, pfx_active, + rfd->rib_prefix_count); + assert(0); + } + } + } + + if (checkstats && bgp && bgp->rfapi) { + if (t_pfx_active != bgp->rfapi->rib_prefix_count_total) { + vnc_zlog_debug_verbose( + "%s: actual total pfx count %u != running %u", + __func__, t_pfx_active, + bgp->rfapi->rib_prefix_count_total); + assert(0); + } + } + + /* + * Check against memory allocation count + */ + alloc_count = mtype_stats_alloc(MTYPE_RFAPI_INFO); + assert(t_ri_active + t_ri_deleted + t_ri_pend + offset == alloc_count); } -static struct rfapi_info * -rfapi_info_new () +static struct rfapi_info *rfapi_info_new() { - return XCALLOC (MTYPE_RFAPI_INFO, sizeof (struct rfapi_info)); + return XCALLOC(MTYPE_RFAPI_INFO, sizeof(struct rfapi_info)); } -void -rfapiFreeRfapiUnOptionChain (struct rfapi_un_option *p) +void rfapiFreeRfapiUnOptionChain(struct rfapi_un_option *p) { - while (p) - { - struct rfapi_un_option *next; - - next = p->next; - XFREE (MTYPE_RFAPI_UN_OPTION, p); - p = next; - } + while (p) { + struct rfapi_un_option *next; + + next = p->next; + XFREE(MTYPE_RFAPI_UN_OPTION, p); + p = next; + } } -void -rfapiFreeRfapiVnOptionChain (struct rfapi_vn_option *p) +void rfapiFreeRfapiVnOptionChain(struct rfapi_vn_option *p) { - while (p) - { - struct rfapi_vn_option *next; - - next = p->next; - XFREE (MTYPE_RFAPI_VN_OPTION, p); - p = next; - } + while (p) { + struct rfapi_vn_option *next; + + next = p->next; + XFREE(MTYPE_RFAPI_VN_OPTION, p); + p = next; + } } -static void -rfapi_info_free (struct rfapi_info *goner) +static void rfapi_info_free(struct rfapi_info *goner) { - if (goner) - { - if (goner->tea_options) - { - rfapiFreeBgpTeaOptionChain (goner->tea_options); - goner->tea_options = NULL; - } - if (goner->un_options) - { - rfapiFreeRfapiUnOptionChain (goner->un_options); - goner->un_options = NULL; - } - if (goner->vn_options) - { - rfapiFreeRfapiVnOptionChain (goner->vn_options); - goner->vn_options = NULL; - } - if (goner->timer) - { - struct rfapi_rib_tcb *tcb; - - tcb = ((struct thread *) goner->timer)->arg; - thread_cancel ((struct thread *) goner->timer); - XFREE (MTYPE_RFAPI_RECENT_DELETE, tcb); - goner->timer = NULL; - } - XFREE (MTYPE_RFAPI_INFO, goner); - } + if (goner) { + if (goner->tea_options) { + rfapiFreeBgpTeaOptionChain(goner->tea_options); + goner->tea_options = NULL; + } + if (goner->un_options) { + rfapiFreeRfapiUnOptionChain(goner->un_options); + goner->un_options = NULL; + } + if (goner->vn_options) { + rfapiFreeRfapiVnOptionChain(goner->vn_options); + goner->vn_options = NULL; + } + if (goner->timer) { + struct rfapi_rib_tcb *tcb; + + tcb = ((struct thread *)goner->timer)->arg; + thread_cancel((struct thread *)goner->timer); + XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb); + goner->timer = NULL; + } + XFREE(MTYPE_RFAPI_INFO, goner); + } } /* * Timer control block for recently-deleted and expired routes */ -struct rfapi_rib_tcb -{ - struct rfapi_descriptor *rfd; - struct skiplist *sl; - struct rfapi_info *ri; - struct route_node *rn; - int flags; +struct rfapi_rib_tcb { + struct rfapi_descriptor *rfd; + struct skiplist *sl; + struct rfapi_info *ri; + struct route_node *rn; + int flags; #define RFAPI_RIB_TCB_FLAG_DELETED 0x00000001 }; /* * remove route from rib */ -static int -rfapiRibExpireTimer (struct thread *t) +static int rfapiRibExpireTimer(struct thread *t) { - struct rfapi_rib_tcb *tcb = t->arg; - - RFAPI_RIB_CHECK_COUNTS (1, 0); - - /* - * Forget reference to thread. Otherwise rfapi_info_free() will - * attempt to free thread pointer as an option chain - */ - tcb->ri->timer = NULL; - - /* "deleted" skiplist frees ri, "active" doesn't */ - assert (!skiplist_delete (tcb->sl, &tcb->ri->rk, NULL)); - if (!tcb->sl->del) - { - /* - * XXX in this case, skiplist has no delete function: we must - * therefore delete rfapi_info explicitly. - */ - rfapi_info_free (tcb->ri); - } - - if (skiplist_empty (tcb->sl)) - { - if (CHECK_FLAG (tcb->flags, RFAPI_RIB_TCB_FLAG_DELETED)) - tcb->rn->aggregate = NULL; - else - { - struct bgp *bgp = bgp_get_default (); - tcb->rn->info = NULL; - RFAPI_RIB_PREFIX_COUNT_DECR (tcb->rfd, bgp->rfapi); - } - skiplist_free (tcb->sl); - route_unlock_node (tcb->rn); - } - - XFREE (MTYPE_RFAPI_RECENT_DELETE, tcb); - - RFAPI_RIB_CHECK_COUNTS (1, 0); - - return 0; + struct rfapi_rib_tcb *tcb = t->arg; + + RFAPI_RIB_CHECK_COUNTS(1, 0); + + /* + * Forget reference to thread. Otherwise rfapi_info_free() will + * attempt to free thread pointer as an option chain + */ + tcb->ri->timer = NULL; + + /* "deleted" skiplist frees ri, "active" doesn't */ + assert(!skiplist_delete(tcb->sl, &tcb->ri->rk, NULL)); + if (!tcb->sl->del) { + /* + * XXX in this case, skiplist has no delete function: we must + * therefore delete rfapi_info explicitly. + */ + rfapi_info_free(tcb->ri); + } + + if (skiplist_empty(tcb->sl)) { + if (CHECK_FLAG(tcb->flags, RFAPI_RIB_TCB_FLAG_DELETED)) + tcb->rn->aggregate = NULL; + else { + struct bgp *bgp = bgp_get_default(); + tcb->rn->info = NULL; + RFAPI_RIB_PREFIX_COUNT_DECR(tcb->rfd, bgp->rfapi); + } + skiplist_free(tcb->sl); + route_unlock_node(tcb->rn); + } + + XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb); + + RFAPI_RIB_CHECK_COUNTS(1, 0); + + return 0; } static void -rfapiRibStartTimer ( - struct rfapi_descriptor *rfd, - struct rfapi_info *ri, - struct route_node *rn, /* route node attached to */ - int deleted) +rfapiRibStartTimer(struct rfapi_descriptor *rfd, struct rfapi_info *ri, + struct route_node *rn, /* route node attached to */ + int deleted) { - struct thread *t = ri->timer; - struct rfapi_rib_tcb *tcb = NULL; - char buf_prefix[BUFSIZ]; - - if (t) - { - tcb = t->arg; - thread_cancel (t); - ri->timer = NULL; - } - else - { - tcb = - XCALLOC (MTYPE_RFAPI_RECENT_DELETE, sizeof (struct rfapi_rib_tcb)); - } - tcb->rfd = rfd; - tcb->ri = ri; - tcb->rn = rn; - if (deleted) - { - tcb->sl = (struct skiplist *) rn->aggregate; - SET_FLAG (tcb->flags, RFAPI_RIB_TCB_FLAG_DELETED); - } - else - { - tcb->sl = (struct skiplist *) rn->info; - UNSET_FLAG (tcb->flags, RFAPI_RIB_TCB_FLAG_DELETED); - } - - prefix2str (&rn->p, buf_prefix, BUFSIZ); - vnc_zlog_debug_verbose ("%s: rfd %p pfx %s life %u", __func__, rfd, buf_prefix, - ri->lifetime); - ri->timer = NULL; - thread_add_timer(bm->master, rfapiRibExpireTimer, tcb, ri->lifetime, - &ri->timer); - assert (ri->timer); + struct thread *t = ri->timer; + struct rfapi_rib_tcb *tcb = NULL; + char buf_prefix[BUFSIZ]; + + if (t) { + tcb = t->arg; + thread_cancel(t); + ri->timer = NULL; + } else { + tcb = XCALLOC(MTYPE_RFAPI_RECENT_DELETE, + sizeof(struct rfapi_rib_tcb)); + } + tcb->rfd = rfd; + tcb->ri = ri; + tcb->rn = rn; + if (deleted) { + tcb->sl = (struct skiplist *)rn->aggregate; + SET_FLAG(tcb->flags, RFAPI_RIB_TCB_FLAG_DELETED); + } else { + tcb->sl = (struct skiplist *)rn->info; + UNSET_FLAG(tcb->flags, RFAPI_RIB_TCB_FLAG_DELETED); + } + + prefix2str(&rn->p, buf_prefix, BUFSIZ); + vnc_zlog_debug_verbose("%s: rfd %p pfx %s life %u", __func__, rfd, + buf_prefix, ri->lifetime); + ri->timer = NULL; + thread_add_timer(bm->master, rfapiRibExpireTimer, tcb, ri->lifetime, + &ri->timer); + assert(ri->timer); } -extern void -rfapi_rib_key_init (struct prefix *prefix, /* may be NULL */ - struct prefix_rd *rd, /* may be NULL */ - struct prefix *aux, /* may be NULL */ - struct rfapi_rib_key *rk) - +extern void rfapi_rib_key_init(struct prefix *prefix, /* may be NULL */ + struct prefix_rd *rd, /* may be NULL */ + struct prefix *aux, /* may be NULL */ + struct rfapi_rib_key *rk) + { - memset((void *)rk, 0, sizeof(struct rfapi_rib_key)); - if (prefix) - rk->vn = *prefix; - if (rd) - rk->rd = *rd; - if (aux) - rk->aux_prefix = *aux; + memset((void *)rk, 0, sizeof(struct rfapi_rib_key)); + if (prefix) + rk->vn = *prefix; + if (rd) + rk->rd = *rd; + if (aux) + rk->aux_prefix = *aux; } /* * Compares two s */ -int -rfapi_rib_key_cmp (void *k1, void *k2) +int rfapi_rib_key_cmp(void *k1, void *k2) { - struct rfapi_rib_key *a = (struct rfapi_rib_key *) k1; - struct rfapi_rib_key *b = (struct rfapi_rib_key *) k2; - int ret; + struct rfapi_rib_key *a = (struct rfapi_rib_key *)k1; + struct rfapi_rib_key *b = (struct rfapi_rib_key *)k2; + int ret; - if (!a || !b) - return (a - b); + if (!a || !b) + return (a - b); - ret = vnc_prefix_cmp (&a->vn, &b->vn); - if (ret) - return ret; + ret = vnc_prefix_cmp(&a->vn, &b->vn); + if (ret) + return ret; - ret = vnc_prefix_cmp(&a->rd, &b->rd); - if (ret) - return ret; + ret = vnc_prefix_cmp(&a->rd, &b->rd); + if (ret) + return ret; - ret = vnc_prefix_cmp (&a->aux_prefix, &b->aux_prefix); + ret = vnc_prefix_cmp(&a->aux_prefix, &b->aux_prefix); - return ret; + return ret; } @@ -459,295 +424,296 @@ rfapi_rib_key_cmp (void *k1, void *k2) * thoroughly, but it's not clear that the extra compuation would * be worth it. */ -static int -bgp_tea_options_cmp (struct bgp_tea_options *a, struct bgp_tea_options *b) +static int bgp_tea_options_cmp(struct bgp_tea_options *a, + struct bgp_tea_options *b) { - int rc; - - if (!a || !b) - { - return (a - b); - } - - if (a->type != b->type) - return (a->type - b->type); - if (a->length != b->length) - return (a->length = b->length); - if ((rc = memcmp (a->value, b->value, a->length))) - return rc; - if (!a->next != !b->next) - { /* logical xor */ - return (a->next - b->next); - } - if (a->next) - return bgp_tea_options_cmp (a->next, b->next); - return 0; + int rc; + + if (!a || !b) { + return (a - b); + } + if (a->type != b->type) + return (a->type - b->type); + if (a->length != b->length) + return (a->length = b->length); + if ((rc = memcmp(a->value, b->value, a->length))) + return rc; + if (!a->next != !b->next) { /* logical xor */ + return (a->next - b->next); + } + if (a->next) + return bgp_tea_options_cmp(a->next, b->next); + return 0; } -static int -rfapi_info_cmp (struct rfapi_info *a, struct rfapi_info *b) +static int rfapi_info_cmp(struct rfapi_info *a, struct rfapi_info *b) { - int rc; + int rc; - if (!a || !b) - return (a - b); + if (!a || !b) + return (a - b); - if ((rc = rfapi_rib_key_cmp (&a->rk, &b->rk))) - return rc; + if ((rc = rfapi_rib_key_cmp(&a->rk, &b->rk))) + return rc; - if ((rc = vnc_prefix_cmp (&a->un, &b->un))) - return rc; + if ((rc = vnc_prefix_cmp(&a->un, &b->un))) + return rc; - if (a->cost != b->cost) - return (a->cost - b->cost); + if (a->cost != b->cost) + return (a->cost - b->cost); - if (a->lifetime != b->lifetime) - return (a->lifetime - b->lifetime); + if (a->lifetime != b->lifetime) + return (a->lifetime - b->lifetime); - if ((rc = bgp_tea_options_cmp (a->tea_options, b->tea_options))) - return rc; + if ((rc = bgp_tea_options_cmp(a->tea_options, b->tea_options))) + return rc; - return 0; + return 0; } -void -rfapiRibClear (struct rfapi_descriptor *rfd) +void rfapiRibClear(struct rfapi_descriptor *rfd) { - struct bgp *bgp; - afi_t afi; + struct bgp *bgp; + afi_t afi; - if (rfd->bgp) - bgp = rfd->bgp; - else - bgp = bgp_get_default (); + if (rfd->bgp) + bgp = rfd->bgp; + else + bgp = bgp_get_default(); #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: rfd=%p", __func__, rfd); + vnc_zlog_debug_verbose("%s: rfd=%p", __func__, rfd); #endif - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - struct route_node *pn; - struct route_node *rn; - - if (rfd->rib_pending[afi]) - { - for (pn = route_top (rfd->rib_pending[afi]); pn; - pn = route_next (pn)) - { - if (pn->aggregate) - { - /* - * free references into the rfapi_info structures before - * freeing the structures themselves - */ - skiplist_free ((struct skiplist *) (pn->aggregate)); - pn->aggregate = NULL; - route_unlock_node (pn); /* skiplist deleted */ - } - /* - * free the rfapi_info structures - */ - if (pn->info) - { - if (pn->info != (void *) 1) - { - list_delete ((struct list *) (pn->info)); - } - pn->info = NULL; - route_unlock_node (pn); /* linklist or 1 deleted */ - } - } - } - if (rfd->rib[afi]) - { - for (rn = route_top (rfd->rib[afi]); rn; rn = route_next (rn)) - { - if (rn->info) - { - - struct rfapi_info *ri; - - while (0 == - skiplist_first ((struct skiplist *) rn->info, NULL, - (void **) &ri)) - { - - rfapi_info_free (ri); - skiplist_delete_first ((struct skiplist *) rn->info); - } - skiplist_free ((struct skiplist *) rn->info); - rn->info = NULL; - route_unlock_node (rn); - RFAPI_RIB_PREFIX_COUNT_DECR (rfd, bgp->rfapi); - } - if (rn->aggregate) - { - - struct rfapi_info *ri_del; - - /* delete skiplist & contents */ - while (!skiplist_first ((struct skiplist *) (rn->aggregate), - NULL, (void **) &ri_del)) - { - - /* sl->del takes care of ri_del */ - skiplist_delete_first ( - (struct skiplist *) (rn->aggregate)); - } - skiplist_free ((struct skiplist *) (rn->aggregate)); - - rn->aggregate = NULL; - route_unlock_node (rn); - } - } - } - } - if (rfd->updated_responses_queue) - { - work_queue_free (rfd->updated_responses_queue); - rfd->updated_responses_queue = NULL; - } + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + struct route_node *pn; + struct route_node *rn; + + if (rfd->rib_pending[afi]) { + for (pn = route_top(rfd->rib_pending[afi]); pn; + pn = route_next(pn)) { + if (pn->aggregate) { + /* + * free references into the rfapi_info + * structures before + * freeing the structures themselves + */ + skiplist_free( + (struct skiplist + *)(pn->aggregate)); + pn->aggregate = NULL; + route_unlock_node( + pn); /* skiplist deleted */ + } + /* + * free the rfapi_info structures + */ + if (pn->info) { + if (pn->info != (void *)1) { + list_delete( + (struct list + *)(pn->info)); + } + pn->info = NULL; + route_unlock_node( + pn); /* linklist or 1 deleted */ + } + } + } + if (rfd->rib[afi]) { + for (rn = route_top(rfd->rib[afi]); rn; + rn = route_next(rn)) { + if (rn->info) { + + struct rfapi_info *ri; + + while (0 == skiplist_first( + (struct skiplist *) + rn->info, + NULL, + (void **)&ri)) { + + rfapi_info_free(ri); + skiplist_delete_first( + (struct skiplist *) + rn->info); + } + skiplist_free( + (struct skiplist *)rn->info); + rn->info = NULL; + route_unlock_node(rn); + RFAPI_RIB_PREFIX_COUNT_DECR(rfd, + bgp->rfapi); + } + if (rn->aggregate) { + + struct rfapi_info *ri_del; + + /* delete skiplist & contents */ + while (!skiplist_first( + (struct skiplist + *)(rn->aggregate), + NULL, (void **)&ri_del)) { + + /* sl->del takes care of ri_del + */ + skiplist_delete_first(( + struct skiplist + *)(rn->aggregate)); + } + skiplist_free( + (struct skiplist + *)(rn->aggregate)); + + rn->aggregate = NULL; + route_unlock_node(rn); + } + } + } + } + if (rfd->updated_responses_queue) { + work_queue_free(rfd->updated_responses_queue); + rfd->updated_responses_queue = NULL; + } } /* * Release all dynamically-allocated memory that is part of an HD's RIB */ -void -rfapiRibFree (struct rfapi_descriptor *rfd) +void rfapiRibFree(struct rfapi_descriptor *rfd) { - afi_t afi; + afi_t afi; - /* - * NB rfd is typically detached from master list, so is not included - * in the count performed by RFAPI_RIB_CHECK_COUNTS - */ + /* + * NB rfd is typically detached from master list, so is not included + * in the count performed by RFAPI_RIB_CHECK_COUNTS + */ - /* - * Free routes attached to radix trees - */ - rfapiRibClear (rfd); + /* + * Free routes attached to radix trees + */ + rfapiRibClear(rfd); - /* Now the uncounted rfapi_info's are freed, so the check should succeed */ - RFAPI_RIB_CHECK_COUNTS (1, 0); + /* Now the uncounted rfapi_info's are freed, so the check should succeed + */ + RFAPI_RIB_CHECK_COUNTS(1, 0); - /* - * Free radix trees - */ - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - route_table_finish (rfd->rib_pending[afi]); - rfd->rib_pending[afi] = NULL; + /* + * Free radix trees + */ + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + route_table_finish(rfd->rib_pending[afi]); + rfd->rib_pending[afi] = NULL; - route_table_finish (rfd->rib[afi]); - rfd->rib[afi] = NULL; + route_table_finish(rfd->rib[afi]); + rfd->rib[afi] = NULL; - /* NB route_table_finish frees only prefix nodes, not chained info */ - route_table_finish (rfd->rsp_times[afi]); - rfd->rib[afi] = NULL; - } + /* NB route_table_finish frees only prefix nodes, not chained + * info */ + route_table_finish(rfd->rsp_times[afi]); + rfd->rib[afi] = NULL; + } } /* * Copies struct bgp_info to struct rfapi_info, except for rk fields and un */ -static void -rfapiRibBi2Ri( - struct bgp_info *bi, - struct rfapi_info *ri, - uint32_t lifetime) +static void rfapiRibBi2Ri(struct bgp_info *bi, struct rfapi_info *ri, + uint32_t lifetime) { - struct bgp_attr_encap_subtlv *pEncap; - - ri->cost = rfapiRfpCost (bi->attr); - ri->lifetime = lifetime; - - /* This loop based on rfapiRouteInfo2NextHopEntry() */ - for (pEncap = bi->attr->vnc_subtlvs; pEncap; pEncap = pEncap->next) - { - struct bgp_tea_options *hop; - - switch (pEncap->type) - { - case BGP_VNC_SUBTLV_TYPE_LIFETIME: - /* use configured lifetime, not attr lifetime */ - break; - - case BGP_VNC_SUBTLV_TYPE_RFPOPTION: - hop = XCALLOC (MTYPE_BGP_TEA_OPTIONS, - sizeof (struct bgp_tea_options)); - assert (hop); - hop->type = pEncap->value[0]; - hop->length = pEncap->value[1]; - hop->value = XCALLOC (MTYPE_BGP_TEA_OPTIONS_VALUE, - pEncap->length - 2); - assert (hop->value); - memcpy (hop->value, pEncap->value + 2, pEncap->length - 2); - if (hop->length > pEncap->length - 2) - { - zlog_warn ("%s: VNC subtlv length mismatch: " - "RFP option says %d, attr says %d " - "(shrinking)", - __func__, hop->length, pEncap->length - 2); - hop->length = pEncap->length - 2; - } - hop->next = ri->tea_options; - ri->tea_options = hop; - break; - - default: - break; - } - } - - rfapi_un_options_free (ri->un_options); /* maybe free old version */ - ri->un_options = rfapi_encap_tlv_to_un_option (bi->attr); - - /* - * VN options - */ - if (bi->extra && - decode_rd_type(bi->extra->vnc.import.rd.val) == RD_TYPE_VNC_ETH) - { - /* ethernet route */ - - struct rfapi_vn_option *vo; - - vo = XCALLOC (MTYPE_RFAPI_VN_OPTION, sizeof (struct rfapi_vn_option)); - assert (vo); - - vo->type = RFAPI_VN_OPTION_TYPE_L2ADDR; - - /* copy from RD already stored in bi, so we don't need it_node */ - memcpy (&vo->v.l2addr.macaddr, bi->extra->vnc.import.rd.val+2, - ETHER_ADDR_LEN); - - if (bi->attr) - { - (void) rfapiEcommunityGetLNI (bi->attr->ecommunity, - &vo->v.l2addr.logical_net_id); - (void) rfapiEcommunityGetEthernetTag (bi->attr->ecommunity, - &vo->v.l2addr.tag_id); - } - - /* local_nve_id comes from RD */ - vo->v.l2addr.local_nve_id = bi->extra->vnc.import.rd.val[1]; - - /* label comes from MP_REACH_NLRI label */ - vo->v.l2addr.label = decode_label (&bi->extra->label); - - rfapi_vn_options_free (ri->vn_options); /* maybe free old version */ - ri->vn_options = vo; - } - - /* - * If there is an auxiliary IP address (L2 can have it), copy it - */ - if (bi && bi->extra && bi->extra->vnc.import.aux_prefix.family) - { - ri->rk.aux_prefix = bi->extra->vnc.import.aux_prefix; - } + struct bgp_attr_encap_subtlv *pEncap; + + ri->cost = rfapiRfpCost(bi->attr); + ri->lifetime = lifetime; + + /* This loop based on rfapiRouteInfo2NextHopEntry() */ + for (pEncap = bi->attr->vnc_subtlvs; pEncap; pEncap = pEncap->next) { + struct bgp_tea_options *hop; + + switch (pEncap->type) { + case BGP_VNC_SUBTLV_TYPE_LIFETIME: + /* use configured lifetime, not attr lifetime */ + break; + + case BGP_VNC_SUBTLV_TYPE_RFPOPTION: + hop = XCALLOC(MTYPE_BGP_TEA_OPTIONS, + sizeof(struct bgp_tea_options)); + assert(hop); + hop->type = pEncap->value[0]; + hop->length = pEncap->value[1]; + hop->value = XCALLOC(MTYPE_BGP_TEA_OPTIONS_VALUE, + pEncap->length - 2); + assert(hop->value); + memcpy(hop->value, pEncap->value + 2, + pEncap->length - 2); + if (hop->length > pEncap->length - 2) { + zlog_warn( + "%s: VNC subtlv length mismatch: " + "RFP option says %d, attr says %d " + "(shrinking)", + __func__, hop->length, + pEncap->length - 2); + hop->length = pEncap->length - 2; + } + hop->next = ri->tea_options; + ri->tea_options = hop; + break; + + default: + break; + } + } + + rfapi_un_options_free(ri->un_options); /* maybe free old version */ + ri->un_options = rfapi_encap_tlv_to_un_option(bi->attr); + + /* + * VN options + */ + if (bi->extra + && decode_rd_type(bi->extra->vnc.import.rd.val) + == RD_TYPE_VNC_ETH) { + /* ethernet route */ + + struct rfapi_vn_option *vo; + + vo = XCALLOC(MTYPE_RFAPI_VN_OPTION, + sizeof(struct rfapi_vn_option)); + assert(vo); + + vo->type = RFAPI_VN_OPTION_TYPE_L2ADDR; + + /* copy from RD already stored in bi, so we don't need it_node + */ + memcpy(&vo->v.l2addr.macaddr, bi->extra->vnc.import.rd.val + 2, + ETHER_ADDR_LEN); + + if (bi->attr) { + (void)rfapiEcommunityGetLNI( + bi->attr->ecommunity, + &vo->v.l2addr.logical_net_id); + (void)rfapiEcommunityGetEthernetTag( + bi->attr->ecommunity, &vo->v.l2addr.tag_id); + } + + /* local_nve_id comes from RD */ + vo->v.l2addr.local_nve_id = bi->extra->vnc.import.rd.val[1]; + + /* label comes from MP_REACH_NLRI label */ + vo->v.l2addr.label = decode_label(&bi->extra->label); + + rfapi_vn_options_free( + ri->vn_options); /* maybe free old version */ + ri->vn_options = vo; + } + + /* + * If there is an auxiliary IP address (L2 can have it), copy it + */ + if (bi && bi->extra && bi->extra->vnc.import.aux_prefix.family) { + ri->rk.aux_prefix = bi->extra->vnc.import.aux_prefix; + } } /* @@ -768,94 +734,86 @@ rfapiRibBi2Ri( * 0 OK to include route in response * !0 do not include route in response */ -int -rfapiRibPreloadBi( - struct route_node *rfd_rib_node, /* NULL = don't preload or filter */ - struct prefix *pfx_vn, - struct prefix *pfx_un, - uint32_t lifetime, - struct bgp_info *bi) +int rfapiRibPreloadBi( + struct route_node *rfd_rib_node, /* NULL = don't preload or filter */ + struct prefix *pfx_vn, struct prefix *pfx_un, uint32_t lifetime, + struct bgp_info *bi) { - struct rfapi_descriptor *rfd; - struct skiplist *slRibPt = NULL; - struct rfapi_info *ori = NULL; - struct rfapi_rib_key rk; - struct route_node *trn; - afi_t afi; - - if (!rfd_rib_node) - return 0; - - afi = family2afi(rfd_rib_node->p.family); - - rfd = (struct rfapi_descriptor *)(rfd_rib_node->table->info); - - memset((void *)&rk, 0, sizeof(rk)); - rk.vn = *pfx_vn; - rk.rd = bi->extra->vnc.import.rd; - - /* - * If there is an auxiliary IP address (L2 can have it), copy it - */ - if (bi->extra->vnc.import.aux_prefix.family) - { - rk.aux_prefix = bi->extra->vnc.import.aux_prefix; - } - - /* - * is this route already in NVE's RIB? - */ - slRibPt = (struct skiplist *) rfd_rib_node->info; - - if (slRibPt && !skiplist_search (slRibPt, &rk, (void **) &ori)) - { - - if ((ori->rsp_counter == rfd->rsp_counter) && - (ori->last_sent_time == rfd->rsp_time)) - { - return -1; /* duplicate in this response */ + struct rfapi_descriptor *rfd; + struct skiplist *slRibPt = NULL; + struct rfapi_info *ori = NULL; + struct rfapi_rib_key rk; + struct route_node *trn; + afi_t afi; + + if (!rfd_rib_node) + return 0; + + afi = family2afi(rfd_rib_node->p.family); + + rfd = (struct rfapi_descriptor *)(rfd_rib_node->table->info); + + memset((void *)&rk, 0, sizeof(rk)); + rk.vn = *pfx_vn; + rk.rd = bi->extra->vnc.import.rd; + + /* + * If there is an auxiliary IP address (L2 can have it), copy it + */ + if (bi->extra->vnc.import.aux_prefix.family) { + rk.aux_prefix = bi->extra->vnc.import.aux_prefix; + } + + /* + * is this route already in NVE's RIB? + */ + slRibPt = (struct skiplist *)rfd_rib_node->info; + + if (slRibPt && !skiplist_search(slRibPt, &rk, (void **)&ori)) { + + if ((ori->rsp_counter == rfd->rsp_counter) + && (ori->last_sent_time == rfd->rsp_time)) { + return -1; /* duplicate in this response */ + } + + /* found: update contents of existing route in RIB */ + ori->un = *pfx_un; + rfapiRibBi2Ri(bi, ori, lifetime); + } else { + /* not found: add new route to RIB */ + ori = rfapi_info_new(); + ori->rk = rk; + ori->un = *pfx_un; + rfapiRibBi2Ri(bi, ori, lifetime); + + if (!slRibPt) { + slRibPt = skiplist_new(0, rfapi_rib_key_cmp, NULL); + rfd_rib_node->info = slRibPt; + route_lock_node(rfd_rib_node); + RFAPI_RIB_PREFIX_COUNT_INCR(rfd, rfd->bgp->rfapi); + } + skiplist_insert(slRibPt, &ori->rk, ori); } - /* found: update contents of existing route in RIB */ - ori->un = *pfx_un; - rfapiRibBi2Ri(bi, ori, lifetime); - } - else - { - /* not found: add new route to RIB */ - ori = rfapi_info_new (); - ori->rk = rk; - ori->un = *pfx_un; - rfapiRibBi2Ri(bi, ori, lifetime); - - if (!slRibPt) - { - slRibPt = skiplist_new (0, rfapi_rib_key_cmp, NULL); - rfd_rib_node->info = slRibPt; - route_lock_node (rfd_rib_node); - RFAPI_RIB_PREFIX_COUNT_INCR (rfd, rfd->bgp->rfapi); - } - skiplist_insert (slRibPt, &ori->rk, ori); - } - - ori->last_sent_time = rfapi_time (NULL); - - /* - * poke timer - */ - RFAPI_RIB_CHECK_COUNTS (0, 0); - rfapiRibStartTimer (rfd, ori, rfd_rib_node, 0); - RFAPI_RIB_CHECK_COUNTS (0, 0); - - /* - * Update last sent time for prefix - */ - trn = route_node_get (rfd->rsp_times[afi], &rfd_rib_node->p); /* locks trn */ - trn->info = (void *) (uintptr_t) bgp_clock (); - if (trn->lock > 1) - route_unlock_node (trn); - - return 0; + ori->last_sent_time = rfapi_time(NULL); + + /* + * poke timer + */ + RFAPI_RIB_CHECK_COUNTS(0, 0); + rfapiRibStartTimer(rfd, ori, rfd_rib_node, 0); + RFAPI_RIB_CHECK_COUNTS(0, 0); + + /* + * Update last sent time for prefix + */ + trn = route_node_get(rfd->rsp_times[afi], + &rfd_rib_node->p); /* locks trn */ + trn->info = (void *)(uintptr_t)bgp_clock(); + if (trn->lock > 1) + route_unlock_node(trn); + + return 0; } /* @@ -882,617 +840,638 @@ rfapiRibPreloadBi( * * Clear pending node */ -static void -process_pending_node ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - afi_t afi, - struct route_node *pn, /* pending node */ - struct rfapi_next_hop_entry **head, - struct rfapi_next_hop_entry **tail) +static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd, + afi_t afi, + struct route_node *pn, /* pending node */ + struct rfapi_next_hop_entry **head, + struct rfapi_next_hop_entry **tail) { - struct listnode *node = NULL; - struct listnode *nnode = NULL; - struct rfapi_info *ri = NULL; /* happy valgrind */ - struct rfapi_ip_prefix hp = { 0 }; /* pfx to put in NHE */ - struct route_node *rn = NULL; - struct skiplist *slRibPt = NULL; /* rib list */ - struct skiplist *slPendPt = NULL; - struct list *lPendCost = NULL; - struct list *delete_list = NULL; - int printedprefix = 0; - char buf_prefix[BUFSIZ]; - int rib_node_started_nonempty = 0; - int sendingsomeroutes = 0; + struct listnode *node = NULL; + struct listnode *nnode = NULL; + struct rfapi_info *ri = NULL; /* happy valgrind */ + struct rfapi_ip_prefix hp = {0}; /* pfx to put in NHE */ + struct route_node *rn = NULL; + struct skiplist *slRibPt = NULL; /* rib list */ + struct skiplist *slPendPt = NULL; + struct list *lPendCost = NULL; + struct list *delete_list = NULL; + int printedprefix = 0; + char buf_prefix[BUFSIZ]; + int rib_node_started_nonempty = 0; + int sendingsomeroutes = 0; #if DEBUG_PROCESS_PENDING_NODE - unsigned int count_rib_initial = 0; - unsigned int count_pend_vn_initial = 0; - unsigned int count_pend_cost_initial = 0; + unsigned int count_rib_initial = 0; + unsigned int count_pend_vn_initial = 0; + unsigned int count_pend_cost_initial = 0; #endif - assert (pn); - prefix2str (&pn->p, buf_prefix, BUFSIZ); - vnc_zlog_debug_verbose ("%s: afi=%d, %s pn->info=%p", - __func__, afi, buf_prefix, pn->info); + assert(pn); + prefix2str(&pn->p, buf_prefix, BUFSIZ); + vnc_zlog_debug_verbose("%s: afi=%d, %s pn->info=%p", __func__, afi, + buf_prefix, pn->info); - if (AFI_L2VPN != afi) - { - rfapiQprefix2Rprefix (&pn->p, &hp); - } + if (AFI_L2VPN != afi) { + rfapiQprefix2Rprefix(&pn->p, &hp); + } - RFAPI_RIB_CHECK_COUNTS (1, 0); + RFAPI_RIB_CHECK_COUNTS(1, 0); - /* - * Find corresponding RIB node - */ - rn = route_node_get (rfd->rib[afi], &pn->p); /* locks rn */ + /* + * Find corresponding RIB node + */ + rn = route_node_get(rfd->rib[afi], &pn->p); /* locks rn */ - /* - * RIB skiplist has key=rfapi_addr={vn,un}, val = rfapi_info, - * skiplist.del = NULL - */ - slRibPt = (struct skiplist *) rn->info; - if (slRibPt) - rib_node_started_nonempty = 1; + /* + * RIB skiplist has key=rfapi_addr={vn,un}, val = rfapi_info, + * skiplist.del = NULL + */ + slRibPt = (struct skiplist *)rn->info; + if (slRibPt) + rib_node_started_nonempty = 1; - slPendPt = (struct skiplist *) (pn->aggregate); - lPendCost = (struct list *) (pn->info); + slPendPt = (struct skiplist *)(pn->aggregate); + lPendCost = (struct list *)(pn->info); #if DEBUG_PROCESS_PENDING_NODE - /* debugging */ - if (slRibPt) - count_rib_initial = skiplist_count (slRibPt); + /* debugging */ + if (slRibPt) + count_rib_initial = skiplist_count(slRibPt); - if (slPendPt) - count_pend_vn_initial = skiplist_count (slPendPt); + if (slPendPt) + count_pend_vn_initial = skiplist_count(slPendPt); - if (lPendCost && lPendCost != (struct list *) 1) - count_pend_cost_initial = lPendCost->count; + if (lPendCost && lPendCost != (struct list *)1) + count_pend_cost_initial = lPendCost->count; #endif - /* - * Handle special case: delete all routes at prefix - */ - if (lPendCost == (struct list *) 1) - { - vnc_zlog_debug_verbose ("%s: lPendCost=1 => delete all", __func__); - if (slRibPt && !skiplist_empty (slRibPt)) - { - delete_list = list_new (); - while (0 == skiplist_first (slRibPt, NULL, (void **) &ri)) - { - - char buf[BUFSIZ]; - char buf2[BUFSIZ]; - - listnode_add (delete_list, ri); - vnc_zlog_debug_verbose ("%s: after listnode_add, delete_list->count=%d", - __func__, delete_list->count); - rfapiFreeBgpTeaOptionChain (ri->tea_options); - ri->tea_options = NULL; - - if (ri->timer) - { - struct rfapi_rib_tcb *tcb; - - tcb = ((struct thread *) ri->timer)->arg; - thread_cancel (ri->timer); - XFREE (MTYPE_RFAPI_RECENT_DELETE, tcb); - ri->timer = NULL; - } - - prefix2str (&ri->rk.vn, buf, BUFSIZ); - prefix2str (&ri->un, buf2, BUFSIZ); - vnc_zlog_debug_verbose - ("%s: put dl pfx=%s vn=%s un=%s cost=%d life=%d vn_options=%p", - __func__, buf_prefix, buf, buf2, ri->cost, ri->lifetime, - ri->vn_options); - - skiplist_delete_first (slRibPt); - } - - assert (skiplist_empty (slRibPt)); - - skiplist_free (slRibPt); - rn->info = slRibPt = NULL; - route_unlock_node (rn); - - lPendCost = pn->info = NULL; - route_unlock_node (pn); - - goto callback; - } - if (slRibPt) - { - skiplist_free (slRibPt); - rn->info = NULL; - route_unlock_node (rn); - } - - assert (!slPendPt); - if (slPendPt) - { /* TBD I think we can toss this block */ - skiplist_free (slPendPt); - pn->aggregate = NULL; - route_unlock_node (pn); - } - - pn->info = NULL; - route_unlock_node (pn); - - route_unlock_node (rn); /* route_node_get() */ - - if (rib_node_started_nonempty) - { - RFAPI_RIB_PREFIX_COUNT_DECR (rfd, bgp->rfapi); - } - - RFAPI_RIB_CHECK_COUNTS (1, 0); - - return; - } - - vnc_zlog_debug_verbose ("%s: lPendCost->count=%d, slRibPt->count=%d", - __func__, - (lPendCost ? (int) lPendCost->count : -1), - (slRibPt ? (int) slRibPt->count : -1)); - - /* - * Iterate over routes at RIB Node. - * If not found at Pending Node, delete from RIB Node and add to deletelist - * If found at Pending Node - * If identical rfapi_info, delete from Pending Node - */ - if (slRibPt) - { - void *cursor = NULL; - struct rfapi_info *ori; - - /* - * Iterate over RIB List - * - */ - while (!skiplist_next (slRibPt, NULL, (void **) &ori, &cursor)) - { - - if (skiplist_search (slPendPt, &ori->rk, (void **) &ri)) - { - /* - * Not in Pending list, so it should be deleted - */ - if (!delete_list) - delete_list = list_new (); - listnode_add (delete_list, ori); - rfapiFreeBgpTeaOptionChain (ori->tea_options); - ori->tea_options = NULL; - if (ori->timer) - { - struct rfapi_rib_tcb *tcb; - - tcb = ((struct thread *) ori->timer)->arg; - thread_cancel (ori->timer); - XFREE (MTYPE_RFAPI_RECENT_DELETE, tcb); - ori->timer = NULL; - } + /* + * Handle special case: delete all routes at prefix + */ + if (lPendCost == (struct list *)1) { + vnc_zlog_debug_verbose("%s: lPendCost=1 => delete all", + __func__); + if (slRibPt && !skiplist_empty(slRibPt)) { + delete_list = list_new(); + while (0 + == skiplist_first(slRibPt, NULL, (void **)&ri)) { + + char buf[BUFSIZ]; + char buf2[BUFSIZ]; + + listnode_add(delete_list, ri); + vnc_zlog_debug_verbose( + "%s: after listnode_add, delete_list->count=%d", + __func__, delete_list->count); + rfapiFreeBgpTeaOptionChain(ri->tea_options); + ri->tea_options = NULL; + + if (ri->timer) { + struct rfapi_rib_tcb *tcb; + + tcb = ((struct thread *)ri->timer)->arg; + thread_cancel(ri->timer); + XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb); + ri->timer = NULL; + } + + prefix2str(&ri->rk.vn, buf, BUFSIZ); + prefix2str(&ri->un, buf2, BUFSIZ); + vnc_zlog_debug_verbose( + "%s: put dl pfx=%s vn=%s un=%s cost=%d life=%d vn_options=%p", + __func__, buf_prefix, buf, buf2, + ri->cost, ri->lifetime, ri->vn_options); + + skiplist_delete_first(slRibPt); + } + + assert(skiplist_empty(slRibPt)); + + skiplist_free(slRibPt); + rn->info = slRibPt = NULL; + route_unlock_node(rn); + + lPendCost = pn->info = NULL; + route_unlock_node(pn); + + goto callback; + } + if (slRibPt) { + skiplist_free(slRibPt); + rn->info = NULL; + route_unlock_node(rn); + } + + assert(!slPendPt); + if (slPendPt) { /* TBD I think we can toss this block */ + skiplist_free(slPendPt); + pn->aggregate = NULL; + route_unlock_node(pn); + } + + pn->info = NULL; + route_unlock_node(pn); + + route_unlock_node(rn); /* route_node_get() */ + + if (rib_node_started_nonempty) { + RFAPI_RIB_PREFIX_COUNT_DECR(rfd, bgp->rfapi); + } + + RFAPI_RIB_CHECK_COUNTS(1, 0); + + return; + } + + vnc_zlog_debug_verbose("%s: lPendCost->count=%d, slRibPt->count=%d", + __func__, + (lPendCost ? (int)lPendCost->count : -1), + (slRibPt ? (int)slRibPt->count : -1)); + + /* + * Iterate over routes at RIB Node. + * If not found at Pending Node, delete from RIB Node and add to + * deletelist + * If found at Pending Node + * If identical rfapi_info, delete from Pending Node + */ + if (slRibPt) { + void *cursor = NULL; + struct rfapi_info *ori; + + /* + * Iterate over RIB List + * + */ + while (!skiplist_next(slRibPt, NULL, (void **)&ori, &cursor)) { + + if (skiplist_search(slPendPt, &ori->rk, (void **)&ri)) { + /* + * Not in Pending list, so it should be deleted + */ + if (!delete_list) + delete_list = list_new(); + listnode_add(delete_list, ori); + rfapiFreeBgpTeaOptionChain(ori->tea_options); + ori->tea_options = NULL; + if (ori->timer) { + struct rfapi_rib_tcb *tcb; + + tcb = ((struct thread *)ori->timer) + ->arg; + thread_cancel(ori->timer); + XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb); + ori->timer = NULL; + } #if DEBUG_PROCESS_PENDING_NODE - /* deleted from slRibPt below, after we're done iterating */ - vnc_zlog_debug_verbose - ("%s: slRibPt ri %p not matched in pending list, delete", - __func__, ori); + /* deleted from slRibPt below, after we're done + * iterating */ + vnc_zlog_debug_verbose( + "%s: slRibPt ri %p not matched in pending list, delete", + __func__, ori); #endif - } - else - { - /* - * Found in pending list. If same lifetime, cost, options, - * then remove from pending list because the route - * hasn't changed. - */ - if (!rfapi_info_cmp (ori, ri)) - { - skiplist_delete (slPendPt, &ri->rk, NULL); - assert (lPendCost); - if (lPendCost) - { - /* linear walk: might need optimization */ - listnode_delete (lPendCost, ri); /* XXX doesn't free data! bug? */ - rfapi_info_free (ri); /* grr... */ - } - } + } else { + /* + * Found in pending list. If same lifetime, + * cost, options, + * then remove from pending list because the + * route + * hasn't changed. + */ + if (!rfapi_info_cmp(ori, ri)) { + skiplist_delete(slPendPt, &ri->rk, + NULL); + assert(lPendCost); + if (lPendCost) { + /* linear walk: might need + * optimization */ + listnode_delete(lPendCost, + ri); /* XXX + doesn't + free + data! + bug? */ + rfapi_info_free( + ri); /* grr... */ + } + } #if DEBUG_PROCESS_PENDING_NODE - vnc_zlog_debug_verbose ("%s: slRibPt ri %p matched in pending list, %s", - __func__, ori, - (same ? "same info" : "different info")); + vnc_zlog_debug_verbose( + "%s: slRibPt ri %p matched in pending list, %s", + __func__, ori, + (same ? "same info" + : "different info")); #endif - } - } - /* - * Go back and delete items from RIB - */ - if (delete_list) - { - for (ALL_LIST_ELEMENTS_RO (delete_list, node, ri)) - { - vnc_zlog_debug_verbose ("%s: deleting ri %p from slRibPt", __func__, ri); - assert (!skiplist_delete (slRibPt, &ri->rk, NULL)); - } - if (skiplist_empty (slRibPt)) - { - skiplist_free (slRibPt); - slRibPt = rn->info = NULL; - route_unlock_node (rn); - } - } - } - - RFAPI_RIB_CHECK_COUNTS (0, (delete_list ? delete_list->count : 0)); - - /* - * Iterate over routes at Pending Node - * - * If {vn} found at RIB Node, update RIB Node route contents to match PN - * If {vn} NOT found at RIB Node, add copy to RIB Node - */ - if (lPendCost) - { - for (ALL_LIST_ELEMENTS_RO (lPendCost, node, ri)) - { - - struct rfapi_info *ori; - - if (slRibPt && !skiplist_search (slRibPt, &ri->rk, (void **) &ori)) - { - - /* found: update contents of existing route in RIB */ - ori->un = ri->un; - ori->cost = ri->cost; - ori->lifetime = ri->lifetime; - rfapiFreeBgpTeaOptionChain (ori->tea_options); - ori->tea_options = rfapiOptionsDup (ri->tea_options); - ori->last_sent_time = rfapi_time (NULL); - - rfapiFreeRfapiVnOptionChain (ori->vn_options); - ori->vn_options = rfapiVnOptionsDup (ri->vn_options); - - rfapiFreeRfapiUnOptionChain (ori->un_options); - ori->un_options = rfapiUnOptionsDup (ri->un_options); - - vnc_zlog_debug_verbose - ("%s: matched lPendCost item %p in slRibPt, rewrote", - __func__, ri); - - } - else - { - - char buf_rd[BUFSIZ]; - - /* not found: add new route to RIB */ - ori = rfapi_info_new (); - ori->rk = ri->rk; - ori->un = ri->un; - ori->cost = ri->cost; - ori->lifetime = ri->lifetime; - ori->tea_options = rfapiOptionsDup (ri->tea_options); - ori->last_sent_time = rfapi_time (NULL); - ori->vn_options = rfapiVnOptionsDup (ri->vn_options); - ori->un_options = rfapiUnOptionsDup (ri->un_options); - - if (!slRibPt) - { - slRibPt = skiplist_new (0, rfapi_rib_key_cmp, NULL); - rn->info = slRibPt; - route_lock_node (rn); - } - skiplist_insert (slRibPt, &ori->rk, ori); + } + } + /* + * Go back and delete items from RIB + */ + if (delete_list) { + for (ALL_LIST_ELEMENTS_RO(delete_list, node, ri)) { + vnc_zlog_debug_verbose( + "%s: deleting ri %p from slRibPt", + __func__, ri); + assert(!skiplist_delete(slRibPt, &ri->rk, + NULL)); + } + if (skiplist_empty(slRibPt)) { + skiplist_free(slRibPt); + slRibPt = rn->info = NULL; + route_unlock_node(rn); + } + } + } + + RFAPI_RIB_CHECK_COUNTS(0, (delete_list ? delete_list->count : 0)); + + /* + * Iterate over routes at Pending Node + * + * If {vn} found at RIB Node, update RIB Node route contents to match PN + * If {vn} NOT found at RIB Node, add copy to RIB Node + */ + if (lPendCost) { + for (ALL_LIST_ELEMENTS_RO(lPendCost, node, ri)) { + + struct rfapi_info *ori; + + if (slRibPt + && !skiplist_search(slRibPt, &ri->rk, + (void **)&ori)) { + + /* found: update contents of existing route in + * RIB */ + ori->un = ri->un; + ori->cost = ri->cost; + ori->lifetime = ri->lifetime; + rfapiFreeBgpTeaOptionChain(ori->tea_options); + ori->tea_options = + rfapiOptionsDup(ri->tea_options); + ori->last_sent_time = rfapi_time(NULL); + + rfapiFreeRfapiVnOptionChain(ori->vn_options); + ori->vn_options = + rfapiVnOptionsDup(ri->vn_options); + + rfapiFreeRfapiUnOptionChain(ori->un_options); + ori->un_options = + rfapiUnOptionsDup(ri->un_options); + + vnc_zlog_debug_verbose( + "%s: matched lPendCost item %p in slRibPt, rewrote", + __func__, ri); + + } else { + + char buf_rd[BUFSIZ]; + + /* not found: add new route to RIB */ + ori = rfapi_info_new(); + ori->rk = ri->rk; + ori->un = ri->un; + ori->cost = ri->cost; + ori->lifetime = ri->lifetime; + ori->tea_options = + rfapiOptionsDup(ri->tea_options); + ori->last_sent_time = rfapi_time(NULL); + ori->vn_options = + rfapiVnOptionsDup(ri->vn_options); + ori->un_options = + rfapiUnOptionsDup(ri->un_options); + + if (!slRibPt) { + slRibPt = skiplist_new( + 0, rfapi_rib_key_cmp, NULL); + rn->info = slRibPt; + route_lock_node(rn); + } + skiplist_insert(slRibPt, &ori->rk, ori); #if DEBUG_RIB_SL_RD - prefix_rd2str(&ori->rk.rd, buf_rd, sizeof(buf_rd)); + prefix_rd2str(&ori->rk.rd, buf_rd, + sizeof(buf_rd)); #else - buf_rd[0] = 0; + buf_rd[0] = 0; #endif - vnc_zlog_debug_verbose ("%s: nomatch lPendCost item %p in slRibPt, added (rd=%s)", - __func__, ri, buf_rd); - } - - /* - * poke timer - */ - RFAPI_RIB_CHECK_COUNTS (0, (delete_list ? delete_list->count : 0)); - rfapiRibStartTimer (rfd, ori, rn, 0); - RFAPI_RIB_CHECK_COUNTS (0, (delete_list ? delete_list->count : 0)); - } - } + vnc_zlog_debug_verbose( + "%s: nomatch lPendCost item %p in slRibPt, added (rd=%s)", + __func__, ri, buf_rd); + } + + /* + * poke timer + */ + RFAPI_RIB_CHECK_COUNTS( + 0, (delete_list ? delete_list->count : 0)); + rfapiRibStartTimer(rfd, ori, rn, 0); + RFAPI_RIB_CHECK_COUNTS( + 0, (delete_list ? delete_list->count : 0)); + } + } callback: - /* - * Construct NHL as concatenation of pending list + delete list - */ - - - RFAPI_RIB_CHECK_COUNTS (0, (delete_list ? delete_list->count : 0)); - - if (lPendCost) - { - - char buf[BUFSIZ]; - char buf2[BUFSIZ]; - - vnc_zlog_debug_verbose ("%s: lPendCost->count now %d", __func__, lPendCost->count); - vnc_zlog_debug_verbose ("%s: For prefix %s (a)", __func__, buf_prefix); - printedprefix = 1; - - for (ALL_LIST_ELEMENTS (lPendCost, node, nnode, ri)) - { - - struct rfapi_next_hop_entry *new; - struct route_node *trn; - - new = - XCALLOC (MTYPE_RFAPI_NEXTHOP, - sizeof (struct rfapi_next_hop_entry)); - assert (new); - - if (ri->rk.aux_prefix.family) - { - rfapiQprefix2Rprefix (&ri->rk.aux_prefix, &new->prefix); - } - else - { - new->prefix = hp; - if (AFI_L2VPN == afi) - { - /* hp is 0; need to set length to match AF of vn */ - new->prefix.length = - (ri->rk.vn.family == AF_INET) ? 32 : 128; - } - } - new->prefix.cost = ri->cost; - new->lifetime = ri->lifetime; - rfapiQprefix2Raddr (&ri->rk.vn, &new->vn_address); - rfapiQprefix2Raddr (&ri->un, &new->un_address); - /* free option chain from ri */ - rfapiFreeBgpTeaOptionChain (ri->tea_options); - - ri->tea_options = NULL; /* option chain was transferred to NHL */ - - new->vn_options = ri->vn_options; - ri->vn_options = NULL; /* option chain was transferred to NHL */ - - new->un_options = ri->un_options; - ri->un_options = NULL; /* option chain was transferred to NHL */ - - if (*tail) - (*tail)->next = new; - *tail = new; - if (!*head) - { - *head = new; - } - sendingsomeroutes = 1; - - ++rfd->stat_count_nh_reachable; - ++bgp->rfapi->stat.count_updated_response_updates; - - /* - * update this NVE's timestamp for this prefix - */ - trn = route_node_get (rfd->rsp_times[afi], &pn->p); /* locks trn */ - trn->info = (void *) (uintptr_t) bgp_clock (); - if (trn->lock > 1) - route_unlock_node (trn); - - rfapiRfapiIpAddr2Str (&new->vn_address, buf, BUFSIZ); - rfapiRfapiIpAddr2Str (&new->un_address, buf2, BUFSIZ); - vnc_zlog_debug_verbose ("%s: add vn=%s un=%s cost=%d life=%d", __func__, - buf, buf2, new->prefix.cost, new->lifetime); - } - } - - RFAPI_RIB_CHECK_COUNTS (0, (delete_list ? delete_list->count : 0)); - - if (delete_list) - { - - char buf[BUFSIZ]; - char buf2[BUFSIZ]; - - if (!printedprefix) - { - vnc_zlog_debug_verbose ("%s: For prefix %s (d)", __func__, buf_prefix); - } - vnc_zlog_debug_verbose ("%s: delete_list has %d elements", - __func__, delete_list->count); - - RFAPI_RIB_CHECK_COUNTS (0, delete_list->count); - if (!CHECK_FLAG (bgp->rfapi_cfg->flags, - BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE)) - { - - for (ALL_LIST_ELEMENTS (delete_list, node, nnode, ri)) - { - - struct rfapi_next_hop_entry *new; - struct rfapi_info *ri_del; - - RFAPI_RIB_CHECK_COUNTS (0, delete_list->count); - new = XCALLOC (MTYPE_RFAPI_NEXTHOP, - sizeof (struct rfapi_next_hop_entry)); - assert (new); - - if (ri->rk.aux_prefix.family) - { - rfapiQprefix2Rprefix (&ri->rk.aux_prefix, &new->prefix); - } - else - { - new->prefix = hp; - if (AFI_L2VPN == afi) - { - /* hp is 0; need to set length to match AF of vn */ - new->prefix.length = - (ri->rk.vn.family == AF_INET) ? 32 : 128; - } - } - - new->prefix.cost = ri->cost; - new->lifetime = RFAPI_REMOVE_RESPONSE_LIFETIME; - rfapiQprefix2Raddr (&ri->rk.vn, &new->vn_address); - rfapiQprefix2Raddr (&ri->un, &new->un_address); - - new->vn_options = ri->vn_options; - ri->vn_options = NULL; /* option chain was transferred to NHL */ - - new->un_options = ri->un_options; - ri->un_options = NULL; /* option chain was transferred to NHL */ - - if (*tail) - (*tail)->next = new; - *tail = new; - if (!*head) - { - *head = new; - } - ++rfd->stat_count_nh_removal; - ++bgp->rfapi->stat.count_updated_response_deletes; - - rfapiRfapiIpAddr2Str (&new->vn_address, buf, BUFSIZ); - rfapiRfapiIpAddr2Str (&new->un_address, buf2, BUFSIZ); - vnc_zlog_debug_verbose ("%s: DEL vn=%s un=%s cost=%d life=%d", __func__, - buf, buf2, new->prefix.cost, new->lifetime); - - RFAPI_RIB_CHECK_COUNTS (0, delete_list->count); - /* - * Update/add to list of recent deletions at this prefix - */ - if (!rn->aggregate) - { - rn->aggregate = skiplist_new (0, rfapi_rib_key_cmp, - (void (*)(void *)) - rfapi_info_free); - route_lock_node (rn); - } - RFAPI_RIB_CHECK_COUNTS (0, delete_list->count); - - /* sanity check lifetime */ - if (ri->lifetime > RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY) - ri->lifetime = RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY; - - RFAPI_RIB_CHECK_COUNTS (0, delete_list->count); - /* cancel normal expire timer */ - if (ri->timer) - { - struct rfapi_rib_tcb *tcb; - - tcb = ((struct thread *) ri->timer)->arg; - thread_cancel ((struct thread *) ri->timer); - XFREE (MTYPE_RFAPI_RECENT_DELETE, tcb); - ri->timer = NULL; - } - RFAPI_RIB_CHECK_COUNTS (0, delete_list->count); - - /* - * Look in "recently-deleted" list - */ - if (skiplist_search ((struct skiplist *) (rn->aggregate), - &ri->rk, (void **) &ri_del)) - { - - int rc; - - RFAPI_RIB_CHECK_COUNTS (0, delete_list->count); - /* - * NOT in "recently-deleted" list - */ - list_delete_node (delete_list, node); /* does not free ri */ - rc = skiplist_insert ((struct skiplist *) (rn->aggregate), - &ri->rk, ri); - assert (!rc); - - RFAPI_RIB_CHECK_COUNTS (0, delete_list->count); - rfapiRibStartTimer (rfd, ri, rn, 1); - RFAPI_RIB_CHECK_COUNTS (0, delete_list->count); - ri->last_sent_time = rfapi_time (NULL); + /* + * Construct NHL as concatenation of pending list + delete list + */ + + + RFAPI_RIB_CHECK_COUNTS(0, (delete_list ? delete_list->count : 0)); + + if (lPendCost) { + + char buf[BUFSIZ]; + char buf2[BUFSIZ]; + + vnc_zlog_debug_verbose("%s: lPendCost->count now %d", __func__, + lPendCost->count); + vnc_zlog_debug_verbose("%s: For prefix %s (a)", __func__, + buf_prefix); + printedprefix = 1; + + for (ALL_LIST_ELEMENTS(lPendCost, node, nnode, ri)) { + + struct rfapi_next_hop_entry *new; + struct route_node *trn; + + new = XCALLOC(MTYPE_RFAPI_NEXTHOP, + sizeof(struct rfapi_next_hop_entry)); + assert(new); + + if (ri->rk.aux_prefix.family) { + rfapiQprefix2Rprefix(&ri->rk.aux_prefix, + &new->prefix); + } else { + new->prefix = hp; + if (AFI_L2VPN == afi) { + /* hp is 0; need to set length to match + * AF of vn */ + new->prefix.length = + (ri->rk.vn.family == AF_INET) + ? 32 + : 128; + } + } + new->prefix.cost = ri->cost; + new->lifetime = ri->lifetime; + rfapiQprefix2Raddr(&ri->rk.vn, &new->vn_address); + rfapiQprefix2Raddr(&ri->un, &new->un_address); + /* free option chain from ri */ + rfapiFreeBgpTeaOptionChain(ri->tea_options); + + ri->tea_options = + NULL; /* option chain was transferred to NHL */ + + new->vn_options = ri->vn_options; + ri->vn_options = + NULL; /* option chain was transferred to NHL */ + + new->un_options = ri->un_options; + ri->un_options = + NULL; /* option chain was transferred to NHL */ + + if (*tail) + (*tail)->next = new; + *tail = new; + if (!*head) { + *head = new; + } + sendingsomeroutes = 1; + + ++rfd->stat_count_nh_reachable; + ++bgp->rfapi->stat.count_updated_response_updates; + + /* + * update this NVE's timestamp for this prefix + */ + trn = route_node_get(rfd->rsp_times[afi], + &pn->p); /* locks trn */ + trn->info = (void *)(uintptr_t)bgp_clock(); + if (trn->lock > 1) + route_unlock_node(trn); + + rfapiRfapiIpAddr2Str(&new->vn_address, buf, BUFSIZ); + rfapiRfapiIpAddr2Str(&new->un_address, buf2, BUFSIZ); + vnc_zlog_debug_verbose( + "%s: add vn=%s un=%s cost=%d life=%d", + __func__, buf, buf2, new->prefix.cost, + new->lifetime); + } + } + + RFAPI_RIB_CHECK_COUNTS(0, (delete_list ? delete_list->count : 0)); + + if (delete_list) { + + char buf[BUFSIZ]; + char buf2[BUFSIZ]; + + if (!printedprefix) { + vnc_zlog_debug_verbose("%s: For prefix %s (d)", + __func__, buf_prefix); + } + vnc_zlog_debug_verbose("%s: delete_list has %d elements", + __func__, delete_list->count); + + RFAPI_RIB_CHECK_COUNTS(0, delete_list->count); + if (!CHECK_FLAG(bgp->rfapi_cfg->flags, + BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE)) { + + for (ALL_LIST_ELEMENTS(delete_list, node, nnode, ri)) { + + struct rfapi_next_hop_entry *new; + struct rfapi_info *ri_del; + + RFAPI_RIB_CHECK_COUNTS(0, delete_list->count); + new = XCALLOC( + MTYPE_RFAPI_NEXTHOP, + sizeof(struct rfapi_next_hop_entry)); + assert(new); + + if (ri->rk.aux_prefix.family) { + rfapiQprefix2Rprefix(&ri->rk.aux_prefix, + &new->prefix); + } else { + new->prefix = hp; + if (AFI_L2VPN == afi) { + /* hp is 0; need to set length + * to match AF of vn */ + new->prefix.length = + (ri->rk.vn.family + == AF_INET) + ? 32 + : 128; + } + } + + new->prefix.cost = ri->cost; + new->lifetime = RFAPI_REMOVE_RESPONSE_LIFETIME; + rfapiQprefix2Raddr(&ri->rk.vn, + &new->vn_address); + rfapiQprefix2Raddr(&ri->un, &new->un_address); + + new->vn_options = ri->vn_options; + ri->vn_options = NULL; /* option chain was + transferred to NHL */ + + new->un_options = ri->un_options; + ri->un_options = NULL; /* option chain was + transferred to NHL */ + + if (*tail) + (*tail)->next = new; + *tail = new; + if (!*head) { + *head = new; + } + ++rfd->stat_count_nh_removal; + ++bgp->rfapi->stat + .count_updated_response_deletes; + + rfapiRfapiIpAddr2Str(&new->vn_address, buf, + BUFSIZ); + rfapiRfapiIpAddr2Str(&new->un_address, buf2, + BUFSIZ); + vnc_zlog_debug_verbose( + "%s: DEL vn=%s un=%s cost=%d life=%d", + __func__, buf, buf2, new->prefix.cost, + new->lifetime); + + RFAPI_RIB_CHECK_COUNTS(0, delete_list->count); + /* + * Update/add to list of recent deletions at + * this prefix + */ + if (!rn->aggregate) { + rn->aggregate = skiplist_new( + 0, rfapi_rib_key_cmp, + (void (*)(void *)) + rfapi_info_free); + route_lock_node(rn); + } + RFAPI_RIB_CHECK_COUNTS(0, delete_list->count); + + /* sanity check lifetime */ + if (ri->lifetime + > RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY) + ri->lifetime = + RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY; + + RFAPI_RIB_CHECK_COUNTS(0, delete_list->count); + /* cancel normal expire timer */ + if (ri->timer) { + struct rfapi_rib_tcb *tcb; + + tcb = ((struct thread *)ri->timer)->arg; + thread_cancel( + (struct thread *)ri->timer); + XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb); + ri->timer = NULL; + } + RFAPI_RIB_CHECK_COUNTS(0, delete_list->count); + + /* + * Look in "recently-deleted" list + */ + if (skiplist_search( + (struct skiplist *)(rn->aggregate), + &ri->rk, (void **)&ri_del)) { + + int rc; + + RFAPI_RIB_CHECK_COUNTS( + 0, delete_list->count); + /* + * NOT in "recently-deleted" list + */ + list_delete_node( + delete_list, + node); /* does not free ri */ + rc = skiplist_insert( + (struct skiplist + *)(rn->aggregate), + &ri->rk, ri); + assert(!rc); + + RFAPI_RIB_CHECK_COUNTS( + 0, delete_list->count); + rfapiRibStartTimer(rfd, ri, rn, 1); + RFAPI_RIB_CHECK_COUNTS( + 0, delete_list->count); + ri->last_sent_time = rfapi_time(NULL); #if DEBUG_RIB_SL_RD - { - char buf_rd[BUFSIZ]; - prefix_rd2str(&ri->rk.rd, buf_rd, sizeof(buf_rd)); - vnc_zlog_debug_verbose("%s: move route to recently deleted list, rd=%s", - __func__, buf_rd); - } + { + char buf_rd[BUFSIZ]; + prefix_rd2str(&ri->rk.rd, + buf_rd, + sizeof(buf_rd)); + vnc_zlog_debug_verbose( + "%s: move route to recently deleted list, rd=%s", + __func__, buf_rd); + } #endif - } - else - { - /* - * IN "recently-deleted" list - */ - RFAPI_RIB_CHECK_COUNTS (0, delete_list->count); - rfapiRibStartTimer (rfd, ri_del, rn, 1); - RFAPI_RIB_CHECK_COUNTS (0, delete_list->count); - ri->last_sent_time = rfapi_time (NULL); - - } - } - } - else - { - vnc_zlog_debug_verbose ("%s: response removal disabled, omitting removals", - __func__); - } - - delete_list->del = (void (*)(void *)) rfapi_info_free; - list_delete (delete_list); - } - - RFAPI_RIB_CHECK_COUNTS (0, 0); - - /* - * Reset pending lists. The final route_unlock_node() will probably - * cause the pending node to be released. - */ - if (slPendPt) - { - skiplist_free (slPendPt); - pn->aggregate = NULL; - route_unlock_node (pn); - } - if (lPendCost) - { - list_delete (lPendCost); - pn->info = NULL; - route_unlock_node (pn); - } - RFAPI_RIB_CHECK_COUNTS (0, 0); - - if (rib_node_started_nonempty) - { - if (!rn->info) - { - RFAPI_RIB_PREFIX_COUNT_DECR (rfd, bgp->rfapi); - } - } - else - { - if (rn->info) - { - RFAPI_RIB_PREFIX_COUNT_INCR (rfd, bgp->rfapi); - } - } - - if (sendingsomeroutes) - rfapiMonitorTimersRestart (rfd, &pn->p); - - route_unlock_node (rn); /* route_node_get() */ - - RFAPI_RIB_CHECK_COUNTS (1, 0); + } else { + /* + * IN "recently-deleted" list + */ + RFAPI_RIB_CHECK_COUNTS( + 0, delete_list->count); + rfapiRibStartTimer(rfd, ri_del, rn, 1); + RFAPI_RIB_CHECK_COUNTS( + 0, delete_list->count); + ri->last_sent_time = rfapi_time(NULL); + } + } + } else { + vnc_zlog_debug_verbose( + "%s: response removal disabled, omitting removals", + __func__); + } + + delete_list->del = (void (*)(void *))rfapi_info_free; + list_delete(delete_list); + } + + RFAPI_RIB_CHECK_COUNTS(0, 0); + + /* + * Reset pending lists. The final route_unlock_node() will probably + * cause the pending node to be released. + */ + if (slPendPt) { + skiplist_free(slPendPt); + pn->aggregate = NULL; + route_unlock_node(pn); + } + if (lPendCost) { + list_delete(lPendCost); + pn->info = NULL; + route_unlock_node(pn); + } + RFAPI_RIB_CHECK_COUNTS(0, 0); + + if (rib_node_started_nonempty) { + if (!rn->info) { + RFAPI_RIB_PREFIX_COUNT_DECR(rfd, bgp->rfapi); + } + } else { + if (rn->info) { + RFAPI_RIB_PREFIX_COUNT_INCR(rfd, bgp->rfapi); + } + } + + if (sendingsomeroutes) + rfapiMonitorTimersRestart(rfd, &pn->p); + + route_unlock_node(rn); /* route_node_get() */ + + RFAPI_RIB_CHECK_COUNTS(1, 0); } /* @@ -1503,97 +1482,95 @@ callback: * Do callback * */ -static void -rib_do_callback_onepass (struct rfapi_descriptor *rfd, afi_t afi) +static void rib_do_callback_onepass(struct rfapi_descriptor *rfd, afi_t afi) { - struct bgp *bgp = bgp_get_default (); - struct rfapi_next_hop_entry *head = NULL; - struct rfapi_next_hop_entry *tail = NULL; - struct route_node *rn; + struct bgp *bgp = bgp_get_default(); + struct rfapi_next_hop_entry *head = NULL; + struct rfapi_next_hop_entry *tail = NULL; + struct route_node *rn; #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: rfd=%p, afi=%d", __func__, rfd, afi); + vnc_zlog_debug_verbose("%s: rfd=%p, afi=%d", __func__, rfd, afi); #endif - if (!rfd->rib_pending[afi]) - return; + if (!rfd->rib_pending[afi]) + return; - assert (bgp->rfapi); + assert(bgp->rfapi); - for (rn = route_top (rfd->rib_pending[afi]); rn; rn = route_next (rn)) - { - process_pending_node (bgp, rfd, afi, rn, &head, &tail); - } + for (rn = route_top(rfd->rib_pending[afi]); rn; rn = route_next(rn)) { + process_pending_node(bgp, rfd, afi, rn, &head, &tail); + } - if (head) - { - rfapi_response_cb_t *f; + if (head) { + rfapi_response_cb_t *f; #if DEBUG_NHL - vnc_zlog_debug_verbose ("%s: response callback NHL follows:", __func__); - rfapiPrintNhl (NULL, head); + vnc_zlog_debug_verbose("%s: response callback NHL follows:", + __func__); + rfapiPrintNhl(NULL, head); #endif - if (rfd->response_cb) - f = rfd->response_cb; - else - f = bgp->rfapi->rfp_methods.response_cb; - - bgp->rfapi->flags |= RFAPI_INCALLBACK; - vnc_zlog_debug_verbose ("%s: invoking updated response callback", __func__); - (*f) (head, rfd->cookie); - bgp->rfapi->flags &= ~RFAPI_INCALLBACK; - ++bgp->rfapi->response_updated_count; - } + if (rfd->response_cb) + f = rfd->response_cb; + else + f = bgp->rfapi->rfp_methods.response_cb; + + bgp->rfapi->flags |= RFAPI_INCALLBACK; + vnc_zlog_debug_verbose("%s: invoking updated response callback", + __func__); + (*f)(head, rfd->cookie); + bgp->rfapi->flags &= ~RFAPI_INCALLBACK; + ++bgp->rfapi->response_updated_count; + } } -static wq_item_status -rfapiRibDoQueuedCallback (struct work_queue *wq, void *data) +static wq_item_status rfapiRibDoQueuedCallback(struct work_queue *wq, + void *data) { - struct rfapi_descriptor *rfd; - afi_t afi; - uint32_t queued_flag; + struct rfapi_descriptor *rfd; + afi_t afi; + uint32_t queued_flag; - RFAPI_RIB_CHECK_COUNTS (1, 0); + RFAPI_RIB_CHECK_COUNTS(1, 0); - rfd = ((struct rfapi_updated_responses_queue *) data)->rfd; - afi = ((struct rfapi_updated_responses_queue *) data)->afi; + rfd = ((struct rfapi_updated_responses_queue *)data)->rfd; + afi = ((struct rfapi_updated_responses_queue *)data)->afi; - /* Make sure the HD wasn't closed after the work item was scheduled */ - if (rfapi_check (rfd)) - return WQ_SUCCESS; + /* Make sure the HD wasn't closed after the work item was scheduled */ + if (rfapi_check(rfd)) + return WQ_SUCCESS; - rib_do_callback_onepass (rfd, afi); + rib_do_callback_onepass(rfd, afi); - queued_flag = RFAPI_QUEUED_FLAG (afi); + queued_flag = RFAPI_QUEUED_FLAG(afi); - UNSET_FLAG (rfd->flags, queued_flag); + UNSET_FLAG(rfd->flags, queued_flag); - RFAPI_RIB_CHECK_COUNTS (1, 0); + RFAPI_RIB_CHECK_COUNTS(1, 0); - return WQ_SUCCESS; + return WQ_SUCCESS; } -static void -rfapiRibQueueItemDelete (struct work_queue *wq, void *data) +static void rfapiRibQueueItemDelete(struct work_queue *wq, void *data) { - XFREE (MTYPE_RFAPI_UPDATED_RESPONSE_QUEUE, data); + XFREE(MTYPE_RFAPI_UPDATED_RESPONSE_QUEUE, data); } -static void -updated_responses_queue_init (struct rfapi_descriptor *rfd) +static void updated_responses_queue_init(struct rfapi_descriptor *rfd) { - if (rfd->updated_responses_queue) - return; - - rfd->updated_responses_queue = work_queue_new (bm->master, - "rfapi updated responses"); - assert (rfd->updated_responses_queue); - - rfd->updated_responses_queue->spec.workfunc = rfapiRibDoQueuedCallback; - rfd->updated_responses_queue->spec.del_item_data = rfapiRibQueueItemDelete; - rfd->updated_responses_queue->spec.max_retries = 0; - rfd->updated_responses_queue->spec.hold = 1; + if (rfd->updated_responses_queue) + return; + + rfd->updated_responses_queue = + work_queue_new(bm->master, "rfapi updated responses"); + assert(rfd->updated_responses_queue); + + rfd->updated_responses_queue->spec.workfunc = rfapiRibDoQueuedCallback; + rfd->updated_responses_queue->spec.del_item_data = + rfapiRibQueueItemDelete; + rfd->updated_responses_queue->spec.max_retries = 0; + rfd->updated_responses_queue->spec.hold = 1; } /* @@ -1608,219 +1585,202 @@ updated_responses_queue_init (struct rfapi_descriptor *rfd) * * Based on rfapiNhlAddNodeRoutes() */ -void -rfapiRibUpdatePendingNode ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct rfapi_import_table *it, /* needed for L2 */ - struct route_node *it_node, - uint32_t lifetime) +void rfapiRibUpdatePendingNode( + struct bgp *bgp, struct rfapi_descriptor *rfd, + struct rfapi_import_table *it, /* needed for L2 */ + struct route_node *it_node, uint32_t lifetime) { - struct prefix *prefix; - struct bgp_info *bi; - struct route_node *pn; - afi_t afi; - uint32_t queued_flag; - int count = 0; - char buf[BUFSIZ]; - - vnc_zlog_debug_verbose ("%s: entry", __func__); - - if (CHECK_FLAG (bgp->rfapi_cfg->flags, BGP_VNC_CONFIG_CALLBACK_DISABLE)) - return; - - vnc_zlog_debug_verbose ("%s: callbacks are not disabled", __func__); - - RFAPI_RIB_CHECK_COUNTS (1, 0); - - prefix = &it_node->p; - afi = family2afi (prefix->family); - prefix2str (prefix, buf, BUFSIZ); - vnc_zlog_debug_verbose ("%s: prefix=%s", __func__, buf); - - pn = route_node_get (rfd->rib_pending[afi], prefix); - assert (pn); - - vnc_zlog_debug_verbose ("%s: pn->info=%p, pn->aggregate=%p", __func__, pn->info, - pn->aggregate); - - if (pn->aggregate) - { - /* - * free references into the rfapi_info structures before - * freeing the structures themselves - */ - skiplist_free ((struct skiplist *) (pn->aggregate)); - pn->aggregate = NULL; - route_unlock_node (pn); /* skiplist deleted */ - } - - - /* - * free the rfapi_info structures - */ - if (pn->info) - { - if (pn->info != (void *) 1) - { - list_delete ((struct list *) (pn->info)); - } - pn->info = NULL; - route_unlock_node (pn); /* linklist or 1 deleted */ - } - - /* - * The BIs in the import table are already sorted by cost - */ - for (bi = it_node->info; bi; bi = bi->next) - { - - struct rfapi_info *ri; - struct prefix pfx_nh; - - if (!bi->attr) - { - /* shouldn't happen */ - /* TBD increment error stats counter */ - continue; - } - if (!bi->extra) - { - /* shouldn't happen */ - /* TBD increment error stats counter */ - continue; - } - - rfapiNexthop2Prefix (bi->attr, &pfx_nh); - - /* - * Omit route if nexthop is self - */ - if (CHECK_FLAG - (bgp->rfapi_cfg->flags, BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP)) - { - - struct prefix pfx_vn; - - rfapiRaddr2Qprefix (&rfd->vn_addr, &pfx_vn); - if (prefix_same (&pfx_vn, &pfx_nh)) - continue; - } - - ri = rfapi_info_new (); - ri->rk.vn = pfx_nh; - ri->rk.rd = bi->extra->vnc.import.rd; - /* - * If there is an auxiliary IP address (L2 can have it), copy it - */ - if (bi->extra->vnc.import.aux_prefix.family) - { - ri->rk.aux_prefix = bi->extra->vnc.import.aux_prefix; - } - - if (rfapiGetUnAddrOfVpnBi (bi, &ri->un)) - { - rfapi_info_free (ri); - continue; - } - - if (!pn->aggregate) - { - pn->aggregate = skiplist_new (0, rfapi_rib_key_cmp, NULL); - route_lock_node (pn); - } - - /* - * If we have already added this nexthop, the insert will fail. - * Note that the skiplist key is a pointer INTO the rfapi_info - * structure which will be added to the "info" list. - * The skiplist entry VALUE is not used for anything but - * might be useful during debugging. - */ - if (skiplist_insert ((struct skiplist *) pn->aggregate, &ri->rk, ri)) - { - - /* - * duplicate - */ - rfapi_info_free (ri); - continue; - } - - rfapiRibBi2Ri(bi, ri, lifetime); - - if (!pn->info) - { - pn->info = list_new (); - ((struct list *)(pn->info))->del = (void (*)(void *))rfapi_info_free; - route_lock_node (pn); - } - - listnode_add ((struct list *) (pn->info), ri); - } - - if (pn->info) - { - count = ((struct list *) (pn->info))->count; - } - - if (!count) - { - assert (!pn->info); - assert (!pn->aggregate); - pn->info = (void *) 1; /* magic value means this node has no routes */ - route_lock_node (pn); - } - - route_unlock_node (pn); /* route_node_get */ - - queued_flag = RFAPI_QUEUED_FLAG (afi); - - if (!CHECK_FLAG (rfd->flags, queued_flag)) - { - - struct rfapi_updated_responses_queue *urq; - - urq = XCALLOC (MTYPE_RFAPI_UPDATED_RESPONSE_QUEUE, - sizeof (struct rfapi_updated_responses_queue)); - assert (urq); - if (!rfd->updated_responses_queue) - updated_responses_queue_init (rfd); - - SET_FLAG (rfd->flags, queued_flag); - urq->rfd = rfd; - urq->afi = afi; - work_queue_add (rfd->updated_responses_queue, urq); - } - RFAPI_RIB_CHECK_COUNTS (1, 0); + struct prefix *prefix; + struct bgp_info *bi; + struct route_node *pn; + afi_t afi; + uint32_t queued_flag; + int count = 0; + char buf[BUFSIZ]; + + vnc_zlog_debug_verbose("%s: entry", __func__); + + if (CHECK_FLAG(bgp->rfapi_cfg->flags, BGP_VNC_CONFIG_CALLBACK_DISABLE)) + return; + + vnc_zlog_debug_verbose("%s: callbacks are not disabled", __func__); + + RFAPI_RIB_CHECK_COUNTS(1, 0); + + prefix = &it_node->p; + afi = family2afi(prefix->family); + prefix2str(prefix, buf, BUFSIZ); + vnc_zlog_debug_verbose("%s: prefix=%s", __func__, buf); + + pn = route_node_get(rfd->rib_pending[afi], prefix); + assert(pn); + + vnc_zlog_debug_verbose("%s: pn->info=%p, pn->aggregate=%p", __func__, + pn->info, pn->aggregate); + + if (pn->aggregate) { + /* + * free references into the rfapi_info structures before + * freeing the structures themselves + */ + skiplist_free((struct skiplist *)(pn->aggregate)); + pn->aggregate = NULL; + route_unlock_node(pn); /* skiplist deleted */ + } + + + /* + * free the rfapi_info structures + */ + if (pn->info) { + if (pn->info != (void *)1) { + list_delete((struct list *)(pn->info)); + } + pn->info = NULL; + route_unlock_node(pn); /* linklist or 1 deleted */ + } + + /* + * The BIs in the import table are already sorted by cost + */ + for (bi = it_node->info; bi; bi = bi->next) { + + struct rfapi_info *ri; + struct prefix pfx_nh; + + if (!bi->attr) { + /* shouldn't happen */ + /* TBD increment error stats counter */ + continue; + } + if (!bi->extra) { + /* shouldn't happen */ + /* TBD increment error stats counter */ + continue; + } + + rfapiNexthop2Prefix(bi->attr, &pfx_nh); + + /* + * Omit route if nexthop is self + */ + if (CHECK_FLAG(bgp->rfapi_cfg->flags, + BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP)) { + + struct prefix pfx_vn; + + rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx_vn); + if (prefix_same(&pfx_vn, &pfx_nh)) + continue; + } + + ri = rfapi_info_new(); + ri->rk.vn = pfx_nh; + ri->rk.rd = bi->extra->vnc.import.rd; + /* + * If there is an auxiliary IP address (L2 can have it), copy it + */ + if (bi->extra->vnc.import.aux_prefix.family) { + ri->rk.aux_prefix = bi->extra->vnc.import.aux_prefix; + } + + if (rfapiGetUnAddrOfVpnBi(bi, &ri->un)) { + rfapi_info_free(ri); + continue; + } + + if (!pn->aggregate) { + pn->aggregate = + skiplist_new(0, rfapi_rib_key_cmp, NULL); + route_lock_node(pn); + } + + /* + * If we have already added this nexthop, the insert will fail. + * Note that the skiplist key is a pointer INTO the rfapi_info + * structure which will be added to the "info" list. + * The skiplist entry VALUE is not used for anything but + * might be useful during debugging. + */ + if (skiplist_insert((struct skiplist *)pn->aggregate, &ri->rk, + ri)) { + + /* + * duplicate + */ + rfapi_info_free(ri); + continue; + } + + rfapiRibBi2Ri(bi, ri, lifetime); + + if (!pn->info) { + pn->info = list_new(); + ((struct list *)(pn->info))->del = + (void (*)(void *))rfapi_info_free; + route_lock_node(pn); + } + + listnode_add((struct list *)(pn->info), ri); + } + + if (pn->info) { + count = ((struct list *)(pn->info))->count; + } + + if (!count) { + assert(!pn->info); + assert(!pn->aggregate); + pn->info = (void *)1; /* magic value means this node has no + routes */ + route_lock_node(pn); + } + + route_unlock_node(pn); /* route_node_get */ + + queued_flag = RFAPI_QUEUED_FLAG(afi); + + if (!CHECK_FLAG(rfd->flags, queued_flag)) { + + struct rfapi_updated_responses_queue *urq; + + urq = XCALLOC(MTYPE_RFAPI_UPDATED_RESPONSE_QUEUE, + sizeof(struct rfapi_updated_responses_queue)); + assert(urq); + if (!rfd->updated_responses_queue) + updated_responses_queue_init(rfd); + + SET_FLAG(rfd->flags, queued_flag); + urq->rfd = rfd; + urq->afi = afi; + work_queue_add(rfd->updated_responses_queue, urq); + } + RFAPI_RIB_CHECK_COUNTS(1, 0); } -void -rfapiRibUpdatePendingNodeSubtree ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct rfapi_import_table *it, - struct route_node *it_node, - struct route_node *omit_subtree, /* may be NULL */ - uint32_t lifetime) +void rfapiRibUpdatePendingNodeSubtree( + struct bgp *bgp, struct rfapi_descriptor *rfd, + struct rfapi_import_table *it, struct route_node *it_node, + struct route_node *omit_subtree, /* may be NULL */ + uint32_t lifetime) { - /* FIXME: need to find a better way here to work without sticking our - * hands in node->link */ - if (it_node->l_left && (it_node->l_left != omit_subtree)) - { - if (it_node->l_left->info) - rfapiRibUpdatePendingNode (bgp, rfd, it, it_node->l_left, lifetime); - rfapiRibUpdatePendingNodeSubtree (bgp, rfd, it, it_node->l_left, - omit_subtree, lifetime); - } - - if (it_node->l_right && (it_node->l_right != omit_subtree)) - { - if (it_node->l_right->info) - rfapiRibUpdatePendingNode (bgp, rfd, it, it_node->l_right, lifetime); - rfapiRibUpdatePendingNodeSubtree (bgp, rfd, it, it_node->l_right, - omit_subtree, lifetime); - } + /* FIXME: need to find a better way here to work without sticking our + * hands in node->link */ + if (it_node->l_left && (it_node->l_left != omit_subtree)) { + if (it_node->l_left->info) + rfapiRibUpdatePendingNode(bgp, rfd, it, it_node->l_left, + lifetime); + rfapiRibUpdatePendingNodeSubtree(bgp, rfd, it, it_node->l_left, + omit_subtree, lifetime); + } + + if (it_node->l_right && (it_node->l_right != omit_subtree)) { + if (it_node->l_right->info) + rfapiRibUpdatePendingNode(bgp, rfd, it, + it_node->l_right, lifetime); + rfapiRibUpdatePendingNodeSubtree(bgp, rfd, it, it_node->l_right, + omit_subtree, lifetime); + } } /* @@ -1829,72 +1789,72 @@ rfapiRibUpdatePendingNodeSubtree ( * 0 allow prefix to be included in response * !0 don't allow prefix to be included in response */ -int -rfapiRibFTDFilterRecentPrefix( - struct rfapi_descriptor *rfd, - struct route_node *it_rn, /* import table node */ - struct prefix *pfx_target_original) /* query target */ +int rfapiRibFTDFilterRecentPrefix( + struct rfapi_descriptor *rfd, + struct route_node *it_rn, /* import table node */ + struct prefix *pfx_target_original) /* query target */ { - struct bgp *bgp = rfd->bgp; - afi_t afi = family2afi(it_rn->p.family); - time_t prefix_time; - struct route_node *trn; - - /* - * Not in FTD mode, so allow prefix - */ - if (bgp->rfapi_cfg->rfp_cfg.download_type != RFAPI_RFP_DOWNLOAD_FULL) - return 0; - - /* - * TBD - * This matches behavior of now-obsolete rfapiRibFTDFilterRecent(), - * but we need to decide if that is correct. - */ - if (it_rn->p.family == AF_ETHERNET) - return 0; + struct bgp *bgp = rfd->bgp; + afi_t afi = family2afi(it_rn->p.family); + time_t prefix_time; + struct route_node *trn; + + /* + * Not in FTD mode, so allow prefix + */ + if (bgp->rfapi_cfg->rfp_cfg.download_type != RFAPI_RFP_DOWNLOAD_FULL) + return 0; + + /* + * TBD + * This matches behavior of now-obsolete rfapiRibFTDFilterRecent(), + * but we need to decide if that is correct. + */ + if (it_rn->p.family == AF_ETHERNET) + return 0; #if DEBUG_FTD_FILTER_RECENT - { - char buf_pfx[BUFSIZ]; + { + char buf_pfx[BUFSIZ]; - prefix2str(&it_rn->p, buf_pfx, BUFSIZ); - vnc_zlog_debug_verbose("%s: prefix %s", __func__, buf_pfx); - } + prefix2str(&it_rn->p, buf_pfx, BUFSIZ); + vnc_zlog_debug_verbose("%s: prefix %s", __func__, buf_pfx); + } #endif - /* - * prefix covers target address, so allow prefix - */ - if (prefix_match (&it_rn->p, pfx_target_original)) - { + /* + * prefix covers target address, so allow prefix + */ + if (prefix_match(&it_rn->p, pfx_target_original)) { #if DEBUG_FTD_FILTER_RECENT - vnc_zlog_debug_verbose("%s: prefix covers target, allowed", __func__); + vnc_zlog_debug_verbose("%s: prefix covers target, allowed", + __func__); #endif - return 0; - } + return 0; + } - /* - * check this NVE's timestamp for this prefix - */ - trn = route_node_get (rfd->rsp_times[afi], &it_rn->p); /* locks trn */ - prefix_time = (time_t) trn->info; - if (trn->lock > 1) - route_unlock_node (trn); + /* + * check this NVE's timestamp for this prefix + */ + trn = route_node_get(rfd->rsp_times[afi], &it_rn->p); /* locks trn */ + prefix_time = (time_t)trn->info; + if (trn->lock > 1) + route_unlock_node(trn); #if DEBUG_FTD_FILTER_RECENT - vnc_zlog_debug_verbose("%s: last sent time %lu, last allowed time %lu", - __func__, prefix_time, rfd->ftd_last_allowed_time); + vnc_zlog_debug_verbose("%s: last sent time %lu, last allowed time %lu", + __func__, prefix_time, + rfd->ftd_last_allowed_time); #endif - /* - * haven't sent this prefix, which doesn't cover target address, - * to NVE since ftd_advertisement_interval, so OK to send now. - */ - if (prefix_time <= rfd->ftd_last_allowed_time) - return 0; + /* + * haven't sent this prefix, which doesn't cover target address, + * to NVE since ftd_advertisement_interval, so OK to send now. + */ + if (prefix_time <= rfd->ftd_last_allowed_time) + return 0; - return 1; + return 1; } /* @@ -1905,648 +1865,626 @@ rfapiRibFTDFilterRecentPrefix( * value of nexthop chain. */ struct rfapi_next_hop_entry * -rfapiRibPreload ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct rfapi_next_hop_entry *response, - int use_eth_resolution) +rfapiRibPreload(struct bgp *bgp, struct rfapi_descriptor *rfd, + struct rfapi_next_hop_entry *response, int use_eth_resolution) { - struct rfapi_next_hop_entry *nhp; - struct rfapi_next_hop_entry *nhp_next; - struct rfapi_next_hop_entry *head = NULL; - struct rfapi_next_hop_entry *tail = NULL; - time_t new_last_sent_time; - - vnc_zlog_debug_verbose ("%s: loading response=%p, use_eth_resolution=%d", - __func__, response, use_eth_resolution); - - new_last_sent_time = rfapi_time (NULL); - - for (nhp = response; nhp; nhp = nhp_next) - { - - struct prefix pfx; - struct rfapi_rib_key rk; - afi_t afi; - struct rfapi_info *ri; - int need_insert; - struct route_node *rn; - int rib_node_started_nonempty = 0; - struct route_node *trn; - int allowed = 0; - - /* save in case we delete nhp */ - nhp_next = nhp->next; - - if (nhp->lifetime == RFAPI_REMOVE_RESPONSE_LIFETIME) - { - /* - * weird, shouldn't happen - */ - vnc_zlog_debug_verbose - ("%s: got nhp->lifetime == RFAPI_REMOVE_RESPONSE_LIFETIME", - __func__); - continue; - } - - - if (use_eth_resolution) - { - /* get the prefix of the ethernet address in the L2 option */ - struct rfapi_l2address_option *pL2o; - struct rfapi_vn_option *vo; - - /* - * Look for VN option of type RFAPI_VN_OPTION_TYPE_L2ADDR - */ - for (pL2o = NULL, vo = nhp->vn_options; vo; vo = vo->next) - { - if (RFAPI_VN_OPTION_TYPE_L2ADDR == vo->type) - { - pL2o = &vo->v.l2addr; - break; - } - } - - if (!pL2o) - { - /* - * not supposed to happen - */ - vnc_zlog_debug_verbose ("%s: missing L2 info", __func__); - continue; - } - - afi = AFI_L2VPN; - rfapiL2o2Qprefix (pL2o, &pfx); - } - else - { - rfapiRprefix2Qprefix (&nhp->prefix, &pfx); - afi = family2afi (pfx.family); - } - - /* - * TBD for ethernet, rib must know the right way to distinguish - * duplicate routes - * - * Current approach: prefix is key to radix tree; then - * each prefix has a set of routes with unique VN addrs - */ - - /* - * Look up prefix in RIB - */ - rn = route_node_get (rfd->rib[afi], &pfx); /* locks rn */ - - if (rn->info) - { - rib_node_started_nonempty = 1; - } - else - { - rn->info = skiplist_new (0, rfapi_rib_key_cmp, NULL); - route_lock_node (rn); - } - - /* - * Look up route at prefix - */ - need_insert = 0; - memset ((void *) &rk, 0, sizeof (rk)); - assert (!rfapiRaddr2Qprefix (&nhp->vn_address, &rk.vn)); - - if (use_eth_resolution) - { - /* copy what came from aux_prefix to rk.aux_prefix */ - rfapiRprefix2Qprefix (&nhp->prefix, &rk.aux_prefix); - if (RFAPI_0_PREFIX (&rk.aux_prefix) - && RFAPI_HOST_PREFIX (&rk.aux_prefix)) - { - /* mark as "none" if nhp->prefix is 0/32 or 0/128 */ - rk.aux_prefix.family = 0; - } - } + struct rfapi_next_hop_entry *nhp; + struct rfapi_next_hop_entry *nhp_next; + struct rfapi_next_hop_entry *head = NULL; + struct rfapi_next_hop_entry *tail = NULL; + time_t new_last_sent_time; + + vnc_zlog_debug_verbose("%s: loading response=%p, use_eth_resolution=%d", + __func__, response, use_eth_resolution); + + new_last_sent_time = rfapi_time(NULL); + + for (nhp = response; nhp; nhp = nhp_next) { + + struct prefix pfx; + struct rfapi_rib_key rk; + afi_t afi; + struct rfapi_info *ri; + int need_insert; + struct route_node *rn; + int rib_node_started_nonempty = 0; + struct route_node *trn; + int allowed = 0; + + /* save in case we delete nhp */ + nhp_next = nhp->next; + + if (nhp->lifetime == RFAPI_REMOVE_RESPONSE_LIFETIME) { + /* + * weird, shouldn't happen + */ + vnc_zlog_debug_verbose( + "%s: got nhp->lifetime == RFAPI_REMOVE_RESPONSE_LIFETIME", + __func__); + continue; + } + + + if (use_eth_resolution) { + /* get the prefix of the ethernet address in the L2 + * option */ + struct rfapi_l2address_option *pL2o; + struct rfapi_vn_option *vo; + + /* + * Look for VN option of type + * RFAPI_VN_OPTION_TYPE_L2ADDR + */ + for (pL2o = NULL, vo = nhp->vn_options; vo; + vo = vo->next) { + if (RFAPI_VN_OPTION_TYPE_L2ADDR == vo->type) { + pL2o = &vo->v.l2addr; + break; + } + } + + if (!pL2o) { + /* + * not supposed to happen + */ + vnc_zlog_debug_verbose("%s: missing L2 info", + __func__); + continue; + } + + afi = AFI_L2VPN; + rfapiL2o2Qprefix(pL2o, &pfx); + } else { + rfapiRprefix2Qprefix(&nhp->prefix, &pfx); + afi = family2afi(pfx.family); + } + + /* + * TBD for ethernet, rib must know the right way to distinguish + * duplicate routes + * + * Current approach: prefix is key to radix tree; then + * each prefix has a set of routes with unique VN addrs + */ + + /* + * Look up prefix in RIB + */ + rn = route_node_get(rfd->rib[afi], &pfx); /* locks rn */ + + if (rn->info) { + rib_node_started_nonempty = 1; + } else { + rn->info = skiplist_new(0, rfapi_rib_key_cmp, NULL); + route_lock_node(rn); + } + + /* + * Look up route at prefix + */ + need_insert = 0; + memset((void *)&rk, 0, sizeof(rk)); + assert(!rfapiRaddr2Qprefix(&nhp->vn_address, &rk.vn)); + + if (use_eth_resolution) { + /* copy what came from aux_prefix to rk.aux_prefix */ + rfapiRprefix2Qprefix(&nhp->prefix, &rk.aux_prefix); + if (RFAPI_0_PREFIX(&rk.aux_prefix) + && RFAPI_HOST_PREFIX(&rk.aux_prefix)) { + /* mark as "none" if nhp->prefix is 0/32 or + * 0/128 */ + rk.aux_prefix.family = 0; + } + } #if DEBUG_NHL - { - char str_vn[BUFSIZ]; - char str_aux_prefix[BUFSIZ]; - - str_vn[0] = 0; - str_aux_prefix[0] = 0; - - prefix2str (&rk.vn, str_vn, BUFSIZ); - prefix2str (&rk.aux_prefix, str_aux_prefix, BUFSIZ); - - if (!rk.aux_prefix.family) - { - - } - vnc_zlog_debug_verbose ("%s: rk.vn=%s rk.aux_prefix=%s", - __func__, str_vn, - (rk.aux_prefix.family ? str_aux_prefix : "-")); - } - vnc_zlog_debug_verbose ("%s: RIB skiplist for this prefix follows", __func__); - rfapiRibShowRibSl (NULL, &rn->p, (struct skiplist *) rn->info); + { + char str_vn[BUFSIZ]; + char str_aux_prefix[BUFSIZ]; + + str_vn[0] = 0; + str_aux_prefix[0] = 0; + + prefix2str(&rk.vn, str_vn, BUFSIZ); + prefix2str(&rk.aux_prefix, str_aux_prefix, BUFSIZ); + + if (!rk.aux_prefix.family) { + } + vnc_zlog_debug_verbose( + "%s: rk.vn=%s rk.aux_prefix=%s", __func__, + str_vn, + (rk.aux_prefix.family ? str_aux_prefix : "-")); + } + vnc_zlog_debug_verbose( + "%s: RIB skiplist for this prefix follows", __func__); + rfapiRibShowRibSl(NULL, &rn->p, (struct skiplist *)rn->info); #endif - if (!skiplist_search ((struct skiplist *) rn->info, &rk, (void **) &ri)) - { - /* - * Already have this route; make values match - */ - rfapiFreeRfapiUnOptionChain (ri->un_options); - ri->un_options = NULL; - rfapiFreeRfapiVnOptionChain (ri->vn_options); - ri->vn_options = NULL; + if (!skiplist_search((struct skiplist *)rn->info, &rk, + (void **)&ri)) { + /* + * Already have this route; make values match + */ + rfapiFreeRfapiUnOptionChain(ri->un_options); + ri->un_options = NULL; + rfapiFreeRfapiVnOptionChain(ri->vn_options); + ri->vn_options = NULL; #if DEBUG_NHL - vnc_zlog_debug_verbose ("%s: found in RIB", __func__); + vnc_zlog_debug_verbose("%s: found in RIB", __func__); #endif - /* - * Filter duplicate routes from initial response. - * Check timestamps to avoid wraparound problems - */ - if ((ri->rsp_counter != rfd->rsp_counter) || - (ri->last_sent_time != new_last_sent_time)) - { + /* + * Filter duplicate routes from initial response. + * Check timestamps to avoid wraparound problems + */ + if ((ri->rsp_counter != rfd->rsp_counter) + || (ri->last_sent_time != new_last_sent_time)) { #if DEBUG_NHL - vnc_zlog_debug_verbose ("%s: allowed due to counter/timestamp diff", - __func__); + vnc_zlog_debug_verbose( + "%s: allowed due to counter/timestamp diff", + __func__); #endif - allowed = 1; - } + allowed = 1; + } - } - else - { + } else { #if DEBUG_NHL - vnc_zlog_debug_verbose ("%s: allowed due to not yet in RIB", __func__); + vnc_zlog_debug_verbose( + "%s: allowed due to not yet in RIB", __func__); #endif - /* not found: add new route to RIB */ - ri = rfapi_info_new (); - need_insert = 1; - allowed = 1; - } - - ri->rk = rk; - assert (!rfapiRaddr2Qprefix (&nhp->un_address, &ri->un)); - ri->cost = nhp->prefix.cost; - ri->lifetime = nhp->lifetime; - ri->vn_options = rfapiVnOptionsDup (nhp->vn_options); - ri->rsp_counter = rfd->rsp_counter; - ri->last_sent_time = rfapi_time (NULL); - - if (need_insert) - { - int rc; - rc = skiplist_insert ((struct skiplist *) rn->info, &ri->rk, ri); - assert (!rc); - } - - if (!rib_node_started_nonempty) - { - RFAPI_RIB_PREFIX_COUNT_INCR (rfd, bgp->rfapi); - } - - RFAPI_RIB_CHECK_COUNTS (0, 0); - rfapiRibStartTimer (rfd, ri, rn, 0); - RFAPI_RIB_CHECK_COUNTS (0, 0); - - route_unlock_node (rn); - - /* - * update this NVE's timestamp for this prefix - */ - trn = route_node_get (rfd->rsp_times[afi], &pfx); /* locks trn */ - trn->info = (void *) (uintptr_t) bgp_clock (); - if (trn->lock > 1) - route_unlock_node (trn); - - { - char str_pfx[BUFSIZ]; - char str_pfx_vn[BUFSIZ]; - - prefix2str (&pfx, str_pfx, BUFSIZ); - prefix2str (&rk.vn, str_pfx_vn, BUFSIZ); - vnc_zlog_debug_verbose - ("%s: added pfx=%s nh[vn]=%s, cost=%u, lifetime=%u, allowed=%d", - __func__, str_pfx, str_pfx_vn, nhp->prefix.cost, nhp->lifetime, - allowed); - } - - if (allowed) - { - if (tail) - (tail)->next = nhp; - tail = nhp; - if (!head) - { - head = nhp; - } - } - else - { - rfapi_un_options_free (nhp->un_options); - nhp->un_options = NULL; - rfapi_vn_options_free (nhp->vn_options); - nhp->vn_options = NULL; - - XFREE (MTYPE_RFAPI_NEXTHOP, nhp); - nhp = NULL; - } - } - - if (tail) - tail->next = NULL; - return head; + /* not found: add new route to RIB */ + ri = rfapi_info_new(); + need_insert = 1; + allowed = 1; + } + + ri->rk = rk; + assert(!rfapiRaddr2Qprefix(&nhp->un_address, &ri->un)); + ri->cost = nhp->prefix.cost; + ri->lifetime = nhp->lifetime; + ri->vn_options = rfapiVnOptionsDup(nhp->vn_options); + ri->rsp_counter = rfd->rsp_counter; + ri->last_sent_time = rfapi_time(NULL); + + if (need_insert) { + int rc; + rc = skiplist_insert((struct skiplist *)rn->info, + &ri->rk, ri); + assert(!rc); + } + + if (!rib_node_started_nonempty) { + RFAPI_RIB_PREFIX_COUNT_INCR(rfd, bgp->rfapi); + } + + RFAPI_RIB_CHECK_COUNTS(0, 0); + rfapiRibStartTimer(rfd, ri, rn, 0); + RFAPI_RIB_CHECK_COUNTS(0, 0); + + route_unlock_node(rn); + + /* + * update this NVE's timestamp for this prefix + */ + trn = route_node_get(rfd->rsp_times[afi], &pfx); /* locks trn */ + trn->info = (void *)(uintptr_t)bgp_clock(); + if (trn->lock > 1) + route_unlock_node(trn); + + { + char str_pfx[BUFSIZ]; + char str_pfx_vn[BUFSIZ]; + + prefix2str(&pfx, str_pfx, BUFSIZ); + prefix2str(&rk.vn, str_pfx_vn, BUFSIZ); + vnc_zlog_debug_verbose( + "%s: added pfx=%s nh[vn]=%s, cost=%u, lifetime=%u, allowed=%d", + __func__, str_pfx, str_pfx_vn, nhp->prefix.cost, + nhp->lifetime, allowed); + } + + if (allowed) { + if (tail) + (tail)->next = nhp; + tail = nhp; + if (!head) { + head = nhp; + } + } else { + rfapi_un_options_free(nhp->un_options); + nhp->un_options = NULL; + rfapi_vn_options_free(nhp->vn_options); + nhp->vn_options = NULL; + + XFREE(MTYPE_RFAPI_NEXTHOP, nhp); + nhp = NULL; + } + } + + if (tail) + tail->next = NULL; + return head; } -void -rfapiRibPendingDeleteRoute ( - struct bgp *bgp, - struct rfapi_import_table *it, - afi_t afi, - struct route_node *it_node) +void rfapiRibPendingDeleteRoute(struct bgp *bgp, struct rfapi_import_table *it, + afi_t afi, struct route_node *it_node) { - struct rfapi_descriptor *rfd; - struct listnode *node; - char buf[BUFSIZ]; - - prefix2str (&it_node->p, buf, BUFSIZ); - vnc_zlog_debug_verbose ("%s: entry, it=%p, afi=%d, it_node=%p, pfx=%s", - __func__, it, afi, it_node, buf); - - if (AFI_L2VPN == afi) - { - /* - * ethernet import tables are per-LNI and each ethernet monitor - * identifies the rfd that owns it. - */ - struct rfapi_monitor_eth *m; - struct route_node *rn; - struct skiplist *sl; - void *cursor; - int rc; - - /* - * route-specific monitors - */ - if ((sl = RFAPI_MONITOR_ETH (it_node))) - { - - vnc_zlog_debug_verbose ("%s: route-specific skiplist: %p", __func__, sl); - - for (cursor = NULL, rc = - skiplist_next (sl, NULL, (void **) &m, (void **) &cursor); !rc; - rc = skiplist_next (sl, NULL, (void **) &m, (void **) &cursor)) - { + struct rfapi_descriptor *rfd; + struct listnode *node; + char buf[BUFSIZ]; + + prefix2str(&it_node->p, buf, BUFSIZ); + vnc_zlog_debug_verbose("%s: entry, it=%p, afi=%d, it_node=%p, pfx=%s", + __func__, it, afi, it_node, buf); + + if (AFI_L2VPN == afi) { + /* + * ethernet import tables are per-LNI and each ethernet monitor + * identifies the rfd that owns it. + */ + struct rfapi_monitor_eth *m; + struct route_node *rn; + struct skiplist *sl; + void *cursor; + int rc; + + /* + * route-specific monitors + */ + if ((sl = RFAPI_MONITOR_ETH(it_node))) { + + vnc_zlog_debug_verbose( + "%s: route-specific skiplist: %p", __func__, + sl); + + for (cursor = NULL, + rc = skiplist_next(sl, NULL, (void **)&m, + (void **)&cursor); + !rc; rc = skiplist_next(sl, NULL, (void **)&m, + (void **)&cursor)) { #if DEBUG_PENDING_DELETE_ROUTE - vnc_zlog_debug_verbose ("%s: eth monitor rfd=%p", __func__, m->rfd); + vnc_zlog_debug_verbose("%s: eth monitor rfd=%p", + __func__, m->rfd); #endif - /* - * If we have already sent a route with this prefix to this - * NVE, it's OK to send an update with the delete - */ - if ((rn = route_node_lookup (m->rfd->rib[afi], &it_node->p))) - { - rfapiRibUpdatePendingNode (bgp, m->rfd, it, it_node, - m->rfd->response_lifetime); - route_unlock_node (rn); - } - } - } - - /* - * all-routes/FTD monitors - */ - for (m = it->eth0_queries; m; m = m->next) - { + /* + * If we have already sent a route with this + * prefix to this + * NVE, it's OK to send an update with the + * delete + */ + if ((rn = route_node_lookup(m->rfd->rib[afi], + &it_node->p))) { + rfapiRibUpdatePendingNode( + bgp, m->rfd, it, it_node, + m->rfd->response_lifetime); + route_unlock_node(rn); + } + } + } + + /* + * all-routes/FTD monitors + */ + for (m = it->eth0_queries; m; m = m->next) { #if DEBUG_PENDING_DELETE_ROUTE - vnc_zlog_debug_verbose ("%s: eth0 monitor rfd=%p", __func__, m->rfd); + vnc_zlog_debug_verbose("%s: eth0 monitor rfd=%p", + __func__, m->rfd); #endif - /* - * If we have already sent a route with this prefix to this - * NVE, it's OK to send an update with the delete - */ - if ((rn = route_node_lookup (m->rfd->rib[afi], &it_node->p))) - { - rfapiRibUpdatePendingNode (bgp, m->rfd, it, it_node, - m->rfd->response_lifetime); - } - } - - } - else - { - /* - * Find RFDs that reference this import table - */ - for (ALL_LIST_ELEMENTS_RO (&bgp->rfapi->descriptors, node, rfd)) - { - - struct route_node *rn; - - vnc_zlog_debug_verbose ("%s: comparing rfd(%p)->import_table=%p to it=%p", - __func__, rfd, rfd->import_table, it); - - if (rfd->import_table != it) - continue; - - vnc_zlog_debug_verbose ("%s: matched rfd %p", __func__, rfd); - - /* - * If we have sent a response to this NVE with this prefix - * previously, we should send an updated response. - */ - if ((rn = route_node_lookup (rfd->rib[afi], &it_node->p))) - { - rfapiRibUpdatePendingNode (bgp, rfd, it, it_node, - rfd->response_lifetime); - route_unlock_node (rn); - } - } - } + /* + * If we have already sent a route with this prefix to + * this + * NVE, it's OK to send an update with the delete + */ + if ((rn = route_node_lookup(m->rfd->rib[afi], + &it_node->p))) { + rfapiRibUpdatePendingNode( + bgp, m->rfd, it, it_node, + m->rfd->response_lifetime); + } + } + + } else { + /* + * Find RFDs that reference this import table + */ + for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, node, + rfd)) { + + struct route_node *rn; + + vnc_zlog_debug_verbose( + "%s: comparing rfd(%p)->import_table=%p to it=%p", + __func__, rfd, rfd->import_table, it); + + if (rfd->import_table != it) + continue; + + vnc_zlog_debug_verbose("%s: matched rfd %p", __func__, + rfd); + + /* + * If we have sent a response to this NVE with this + * prefix + * previously, we should send an updated response. + */ + if ((rn = route_node_lookup(rfd->rib[afi], + &it_node->p))) { + rfapiRibUpdatePendingNode( + bgp, rfd, it, it_node, + rfd->response_lifetime); + route_unlock_node(rn); + } + } + } } -void -rfapiRibShowResponsesSummary (void *stream) +void rfapiRibShowResponsesSummary(void *stream) { - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; - struct bgp *bgp = bgp_get_default (); - - int nves = 0; - int nves_with_nonempty_ribs = 0; - struct rfapi_descriptor *rfd; - struct listnode *node; - - - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - - fp (out, "%-24s ", "Responses: (Prefixes)"); - fp (out, "%-8s %-8u ", "Active:", bgp->rfapi->rib_prefix_count_total); - fp (out, "%-8s %-8u", "Maximum:", bgp->rfapi->rib_prefix_count_total_max); - fp (out, "\n"); - - fp (out, "%-24s ", " (Updated)"); - fp (out, "%-8s %-8u ", "Update:", - bgp->rfapi->stat.count_updated_response_updates); - fp (out, "%-8s %-8u", "Remove:", - bgp->rfapi->stat.count_updated_response_deletes); - fp (out, "%-8s %-8u", "Total:", - bgp->rfapi->stat.count_updated_response_updates + - bgp->rfapi->stat.count_updated_response_deletes); - fp (out, "\n"); - - fp (out, "%-24s ", " (NVEs)"); - for (ALL_LIST_ELEMENTS_RO (&bgp->rfapi->descriptors, node, rfd)) - { - ++nves; - if (rfd->rib_prefix_count) - ++nves_with_nonempty_ribs; - } - fp (out, "%-8s %-8u ", "Active:", nves_with_nonempty_ribs); - fp (out, "%-8s %-8u", "Total:", nves); - fp (out, "\n"); - + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; + struct bgp *bgp = bgp_get_default(); + + int nves = 0; + int nves_with_nonempty_ribs = 0; + struct rfapi_descriptor *rfd; + struct listnode *node; + + + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + + fp(out, "%-24s ", "Responses: (Prefixes)"); + fp(out, "%-8s %-8u ", "Active:", bgp->rfapi->rib_prefix_count_total); + fp(out, "%-8s %-8u", + "Maximum:", bgp->rfapi->rib_prefix_count_total_max); + fp(out, "\n"); + + fp(out, "%-24s ", " (Updated)"); + fp(out, "%-8s %-8u ", + "Update:", bgp->rfapi->stat.count_updated_response_updates); + fp(out, "%-8s %-8u", + "Remove:", bgp->rfapi->stat.count_updated_response_deletes); + fp(out, "%-8s %-8u", "Total:", + bgp->rfapi->stat.count_updated_response_updates + + bgp->rfapi->stat.count_updated_response_deletes); + fp(out, "\n"); + + fp(out, "%-24s ", " (NVEs)"); + for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, node, rfd)) { + ++nves; + if (rfd->rib_prefix_count) + ++nves_with_nonempty_ribs; + } + fp(out, "%-8s %-8u ", "Active:", nves_with_nonempty_ribs); + fp(out, "%-8s %-8u", "Total:", nves); + fp(out, "\n"); } -void -rfapiRibShowResponsesSummaryClear (void) +void rfapiRibShowResponsesSummaryClear(void) { - struct bgp *bgp = bgp_get_default (); + struct bgp *bgp = bgp_get_default(); - bgp->rfapi->rib_prefix_count_total_max = bgp->rfapi->rib_prefix_count_total; + bgp->rfapi->rib_prefix_count_total_max = + bgp->rfapi->rib_prefix_count_total; } -static int -print_rib_sl ( - int (*fp) (void *, const char *, ...), - struct vty *vty, - void *out, - struct skiplist *sl, - int deleted, - char *str_pfx, - int *printedprefix) +static int print_rib_sl(int (*fp)(void *, const char *, ...), struct vty *vty, + void *out, struct skiplist *sl, int deleted, + char *str_pfx, int *printedprefix) { - struct rfapi_info *ri; - int rc; - void *cursor; - int routes_displayed = 0; - - cursor = NULL; - for (rc = skiplist_next (sl, NULL, (void **) &ri, &cursor); - !rc; rc = skiplist_next (sl, NULL, (void **) &ri, &cursor)) - { - - char str_vn[BUFSIZ]; - char str_un[BUFSIZ]; - char str_lifetime[BUFSIZ]; - char str_age[BUFSIZ]; - char *p; - char str_rd[BUFSIZ]; - - ++routes_displayed; - - prefix2str (&ri->rk.vn, str_vn, BUFSIZ); - p = index (str_vn, '/'); - if (p) - *p = 0; - - prefix2str (&ri->un, str_un, BUFSIZ); - p = index (str_un, '/'); - if (p) - *p = 0; - - rfapiFormatSeconds (ri->lifetime, str_lifetime, BUFSIZ); + struct rfapi_info *ri; + int rc; + void *cursor; + int routes_displayed = 0; + + cursor = NULL; + for (rc = skiplist_next(sl, NULL, (void **)&ri, &cursor); !rc; + rc = skiplist_next(sl, NULL, (void **)&ri, &cursor)) { + + char str_vn[BUFSIZ]; + char str_un[BUFSIZ]; + char str_lifetime[BUFSIZ]; + char str_age[BUFSIZ]; + char *p; + char str_rd[BUFSIZ]; + + ++routes_displayed; + + prefix2str(&ri->rk.vn, str_vn, BUFSIZ); + p = index(str_vn, '/'); + if (p) + *p = 0; + + prefix2str(&ri->un, str_un, BUFSIZ); + p = index(str_un, '/'); + if (p) + *p = 0; + + rfapiFormatSeconds(ri->lifetime, str_lifetime, BUFSIZ); #if RFAPI_REGISTRATIONS_REPORT_AGE - rfapiFormatAge (ri->last_sent_time, str_age, BUFSIZ); + rfapiFormatAge(ri->last_sent_time, str_age, BUFSIZ); #else - { - time_t now = rfapi_time (NULL); - time_t expire = ri->last_sent_time + (time_t) ri->lifetime; - /* allow for delayed/async removal */ - rfapiFormatSeconds ((expire > now ? expire - now : 1), - str_age, BUFSIZ); - } + { + time_t now = rfapi_time(NULL); + time_t expire = + ri->last_sent_time + (time_t)ri->lifetime; + /* allow for delayed/async removal */ + rfapiFormatSeconds((expire > now ? expire - now : 1), + str_age, BUFSIZ); + } #endif - str_rd[0] = 0; /* start empty */ + str_rd[0] = 0; /* start empty */ #if DEBUG_RIB_SL_RD - str_rd[0] = ' '; - prefix_rd2str(&ri->rk.rd, str_rd+1, BUFSIZ-1); + str_rd[0] = ' '; + prefix_rd2str(&ri->rk.rd, str_rd + 1, BUFSIZ - 1); #endif - fp (out, " %c %-20s %-15s %-15s %-4u %-8s %-8s%s\n", - deleted ? 'r' : ' ', - *printedprefix ? "" : str_pfx, - str_vn, str_un, ri->cost, str_lifetime, str_age, str_rd); + fp(out, " %c %-20s %-15s %-15s %-4u %-8s %-8s%s\n", + deleted ? 'r' : ' ', *printedprefix ? "" : str_pfx, str_vn, + str_un, ri->cost, str_lifetime, str_age, str_rd); - if (!*printedprefix) - *printedprefix = 1; - } - return routes_displayed; + if (!*printedprefix) + *printedprefix = 1; + } + return routes_displayed; } #if DEBUG_NHL /* * This one is for debugging (set stream to NULL to send output to log) */ -static void -rfapiRibShowRibSl (void *stream, struct prefix *pfx, struct skiplist *sl) +static void rfapiRibShowRibSl(void *stream, struct prefix *pfx, + struct skiplist *sl) { - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; - int nhs_displayed = 0; - char str_pfx[BUFSIZ]; - int printedprefix = 0; + int nhs_displayed = 0; + char str_pfx[BUFSIZ]; + int printedprefix = 0; - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; - prefix2str (pfx, str_pfx, BUFSIZ); + prefix2str(pfx, str_pfx, BUFSIZ); - nhs_displayed += print_rib_sl (fp, vty, out, sl, - 0, str_pfx, &printedprefix); + nhs_displayed += + print_rib_sl(fp, vty, out, sl, 0, str_pfx, &printedprefix); } #endif -void -rfapiRibShowResponses ( - void *stream, - struct prefix *pfx_match, - int show_removed) +void rfapiRibShowResponses(void *stream, struct prefix *pfx_match, + int show_removed) { - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; - - struct rfapi_descriptor *rfd; - struct listnode *node; - - struct bgp *bgp = bgp_get_default (); - int printedheader = 0; - int routes_total = 0; - int nhs_total = 0; - int prefixes_total = 0; - int prefixes_displayed = 0; - int nves_total = 0; - int nves_with_routes = 0; - int nves_displayed = 0; - int routes_displayed = 0; - int nhs_displayed = 0; - - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - /* - * loop over NVEs - */ - for (ALL_LIST_ELEMENTS_RO (&bgp->rfapi->descriptors, node, rfd)) - { - - int printednve = 0; - afi_t afi; - - ++nves_total; - if (rfd->rib_prefix_count) - ++nves_with_routes; - - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - - struct route_node *rn; - - if (!rfd->rib[afi]) - continue; - - for (rn = route_top (rfd->rib[afi]); rn; rn = route_next (rn)) - { - - struct skiplist *sl; - char str_pfx[BUFSIZ]; - int printedprefix = 0; - - if (!show_removed) - sl = rn->info; - else - sl = rn->aggregate; - - if (!sl) - continue; - - routes_total++; - nhs_total += skiplist_count (sl); - ++prefixes_total; - - if (pfx_match && !prefix_match (pfx_match, &rn->p) && - !prefix_match (&rn->p, pfx_match)) - continue; - - ++prefixes_displayed; - - if (!printedheader) - { - ++printedheader; - - fp (out, "\n[%s]\n", - show_removed ? "Removed" : "Active"); - fp (out, "%-15s %-15s\n", "Querying VN", "Querying UN"); - fp (out, " %-20s %-15s %-15s %4s %-8s %-8s\n", - "Prefix", "Registered VN", "Registered UN", "Cost", - "Lifetime", + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; + + struct rfapi_descriptor *rfd; + struct listnode *node; + + struct bgp *bgp = bgp_get_default(); + int printedheader = 0; + int routes_total = 0; + int nhs_total = 0; + int prefixes_total = 0; + int prefixes_displayed = 0; + int nves_total = 0; + int nves_with_routes = 0; + int nves_displayed = 0; + int routes_displayed = 0; + int nhs_displayed = 0; + + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + /* + * loop over NVEs + */ + for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, node, rfd)) { + + int printednve = 0; + afi_t afi; + + ++nves_total; + if (rfd->rib_prefix_count) + ++nves_with_routes; + + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + + struct route_node *rn; + + if (!rfd->rib[afi]) + continue; + + for (rn = route_top(rfd->rib[afi]); rn; + rn = route_next(rn)) { + + struct skiplist *sl; + char str_pfx[BUFSIZ]; + int printedprefix = 0; + + if (!show_removed) + sl = rn->info; + else + sl = rn->aggregate; + + if (!sl) + continue; + + routes_total++; + nhs_total += skiplist_count(sl); + ++prefixes_total; + + if (pfx_match + && !prefix_match(pfx_match, &rn->p) + && !prefix_match(&rn->p, pfx_match)) + continue; + + ++prefixes_displayed; + + if (!printedheader) { + ++printedheader; + + fp(out, "\n[%s]\n", + show_removed ? "Removed" : "Active"); + fp(out, "%-15s %-15s\n", "Querying VN", + "Querying UN"); + fp(out, + " %-20s %-15s %-15s %4s %-8s %-8s\n", + "Prefix", "Registered VN", + "Registered UN", "Cost", "Lifetime", #if RFAPI_REGISTRATIONS_REPORT_AGE - "Age" + "Age" #else - "Remaining" + "Remaining" #endif - ); - } - if (!printednve) - { - char str_vn[BUFSIZ]; - char str_un[BUFSIZ]; - - ++printednve; - ++nves_displayed; - - fp (out, "%-15s %-15s\n", - rfapiRfapiIpAddr2Str (&rfd->vn_addr, str_vn, BUFSIZ), - rfapiRfapiIpAddr2Str (&rfd->un_addr, str_un, BUFSIZ)); - - } - prefix2str (&rn->p, str_pfx, BUFSIZ); - //fp(out, " %s\n", buf); /* prefix */ - - routes_displayed++; - nhs_displayed += print_rib_sl (fp, vty, out, sl, - show_removed, str_pfx, - &printedprefix); - } - } - } - - if (routes_total) - { - fp (out, "\n"); - fp (out, "Displayed %u NVEs, and %u out of %u %s prefixes", - nves_displayed, routes_displayed, - routes_total, show_removed ? "removed" : "active"); - if (nhs_displayed != routes_displayed || nhs_total != routes_total) - fp (out, " with %u out of %u next hops", nhs_displayed, nhs_total); - fp (out, "\n"); - } + ); + } + if (!printednve) { + char str_vn[BUFSIZ]; + char str_un[BUFSIZ]; + + ++printednve; + ++nves_displayed; + + fp(out, "%-15s %-15s\n", + rfapiRfapiIpAddr2Str(&rfd->vn_addr, + str_vn, BUFSIZ), + rfapiRfapiIpAddr2Str(&rfd->un_addr, + str_un, + BUFSIZ)); + } + prefix2str(&rn->p, str_pfx, BUFSIZ); + // fp(out, " %s\n", buf); /* prefix */ + + routes_displayed++; + nhs_displayed += print_rib_sl( + fp, vty, out, sl, show_removed, str_pfx, + &printedprefix); + } + } + } + + if (routes_total) { + fp(out, "\n"); + fp(out, "Displayed %u NVEs, and %u out of %u %s prefixes", + nves_displayed, routes_displayed, routes_total, + show_removed ? "removed" : "active"); + if (nhs_displayed != routes_displayed + || nhs_total != routes_total) + fp(out, " with %u out of %u next hops", nhs_displayed, + nhs_total); + fp(out, "\n"); + } } diff --git a/bgpd/rfapi/rfapi_rib.h b/bgpd/rfapi/rfapi_rib.h index 40e4c0c2f..0542727c2 100644 --- a/bgpd/rfapi/rfapi_rib.h +++ b/bgpd/rfapi/rfapi_rib.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -33,16 +33,15 @@ * For L2 RIBs, it is possible to have multiple routes to a given L2 * prefix via a given VN address, but each route having a unique aux_prefix. */ -struct rfapi_rib_key -{ - struct prefix vn; - struct prefix_rd rd; - - /* - * for L2 routes: optional IP addr - * .family == 0 means "none" - */ - struct prefix aux_prefix; +struct rfapi_rib_key { + struct prefix vn; + struct prefix_rd rd; + + /* + * for L2 routes: optional IP addr + * .family == 0 means "none" + */ + struct prefix aux_prefix; }; #include "rfapi.h" @@ -51,118 +50,90 @@ struct rfapi_rib_key * * Holds NVE prefix advertisement information */ -struct rfapi_adb -{ - union { - struct { - struct prefix prefix_ip; - struct prefix_rd prd; - struct prefix prefix_eth; - } s; /* mainly for legacy use */ - struct rfapi_rib_key key; - } u; - uint32_t lifetime; - uint8_t cost; - struct rfapi_l2address_option l2o; +struct rfapi_adb { + union { + struct { + struct prefix prefix_ip; + struct prefix_rd prd; + struct prefix prefix_eth; + } s; /* mainly for legacy use */ + struct rfapi_rib_key key; + } u; + uint32_t lifetime; + uint8_t cost; + struct rfapi_l2address_option l2o; }; -struct rfapi_info -{ - struct rfapi_rib_key rk; /* NVE VN addr + aux addr */ - struct prefix un; - uint8_t cost; - uint32_t lifetime; - time_t last_sent_time; - uint32_t rsp_counter; /* dedup initial responses */ - struct bgp_tea_options *tea_options; - struct rfapi_un_option *un_options; - struct rfapi_vn_option *vn_options; - struct thread *timer; +struct rfapi_info { + struct rfapi_rib_key rk; /* NVE VN addr + aux addr */ + struct prefix un; + uint8_t cost; + uint32_t lifetime; + time_t last_sent_time; + uint32_t rsp_counter; /* dedup initial responses */ + struct bgp_tea_options *tea_options; + struct rfapi_un_option *un_options; + struct rfapi_vn_option *vn_options; + struct thread *timer; }; /* * Work item for updated responses queue */ -struct rfapi_updated_responses_queue -{ - struct rfapi_descriptor *rfd; - afi_t afi; +struct rfapi_updated_responses_queue { + struct rfapi_descriptor *rfd; + afi_t afi; }; -extern void -rfapiRibClear (struct rfapi_descriptor *rfd); +extern void rfapiRibClear(struct rfapi_descriptor *rfd); -extern void -rfapiRibFree (struct rfapi_descriptor *rfd); +extern void rfapiRibFree(struct rfapi_descriptor *rfd); -extern void -rfapiRibUpdatePendingNode ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct rfapi_import_table *it, - struct route_node *it_node, - uint32_t lifetime); +extern void rfapiRibUpdatePendingNode(struct bgp *bgp, + struct rfapi_descriptor *rfd, + struct rfapi_import_table *it, + struct route_node *it_node, + uint32_t lifetime); -extern void -rfapiRibUpdatePendingNodeSubtree ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct rfapi_import_table *it, - struct route_node *it_node, - struct route_node *omit_subtree, - uint32_t lifetime); - -extern int -rfapiRibPreloadBi( - struct route_node *rfd_rib_node, - struct prefix *pfx_vn, - struct prefix *pfx_un, - uint32_t lifetime, - struct bgp_info *bi); +extern void rfapiRibUpdatePendingNodeSubtree(struct bgp *bgp, + struct rfapi_descriptor *rfd, + struct rfapi_import_table *it, + struct route_node *it_node, + struct route_node *omit_subtree, + uint32_t lifetime); + +extern int rfapiRibPreloadBi(struct route_node *rfd_rib_node, + struct prefix *pfx_vn, struct prefix *pfx_un, + uint32_t lifetime, struct bgp_info *bi); extern struct rfapi_next_hop_entry * -rfapiRibPreload ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - struct rfapi_next_hop_entry *response, - int use_eth_resolution); +rfapiRibPreload(struct bgp *bgp, struct rfapi_descriptor *rfd, + struct rfapi_next_hop_entry *response, int use_eth_resolution); -extern void -rfapiRibPendingDeleteRoute ( - struct bgp *bgp, - struct rfapi_import_table *it, - afi_t afi, - struct route_node *it_node); +extern void rfapiRibPendingDeleteRoute(struct bgp *bgp, + struct rfapi_import_table *it, afi_t afi, + struct route_node *it_node); -extern void -rfapiRibShowResponsesSummary (void *stream); +extern void rfapiRibShowResponsesSummary(void *stream); -extern void -rfapiRibShowResponsesSummaryClear (void); +extern void rfapiRibShowResponsesSummaryClear(void); -extern void -rfapiRibShowResponses ( - void *stream, - struct prefix *pfx_match, - int show_removed); +extern void rfapiRibShowResponses(void *stream, struct prefix *pfx_match, + int show_removed); -extern int -rfapiRibFTDFilterRecentPrefix( - struct rfapi_descriptor *rfd, - struct route_node *it_rn, /* import table node */ - struct prefix *pfx_target_original); /* query target */ +extern int rfapiRibFTDFilterRecentPrefix( + struct rfapi_descriptor *rfd, + struct route_node *it_rn, /* import table node */ + struct prefix *pfx_target_original); /* query target */ -extern void -rfapiFreeRfapiUnOptionChain (struct rfapi_un_option *p); +extern void rfapiFreeRfapiUnOptionChain(struct rfapi_un_option *p); -extern void -rfapiFreeRfapiVnOptionChain (struct rfapi_vn_option *p); +extern void rfapiFreeRfapiVnOptionChain(struct rfapi_vn_option *p); extern void -rfapiRibCheckCounts ( - int checkstats, /* validate rfd & global counts */ - unsigned int offset); /* number of ri's held separately */ +rfapiRibCheckCounts(int checkstats, /* validate rfd & global counts */ + unsigned int offset); /* number of ri's held separately */ /* enable for debugging; disable for performance */ #if 0 @@ -171,16 +142,13 @@ rfapiRibCheckCounts ( #define RFAPI_RIB_CHECK_COUNTS(checkstats, offset) #endif -extern void -rfapi_rib_key_init (struct prefix *prefix, /* may be NULL */ - struct prefix_rd *rd, /* may be NULL */ - struct prefix *aux, /* may be NULL */ - struct rfapi_rib_key *rk); +extern void rfapi_rib_key_init(struct prefix *prefix, /* may be NULL */ + struct prefix_rd *rd, /* may be NULL */ + struct prefix *aux, /* may be NULL */ + struct rfapi_rib_key *rk); -extern int -rfapi_rib_key_cmp (void *k1, void *k2); +extern int rfapi_rib_key_cmp(void *k1, void *k2); -extern void -rfapiAdbFree (struct rfapi_adb *adb); +extern void rfapiAdbFree(struct rfapi_adb *adb); #endif /* QUAGGA_HGP_RFAPI_RIB_H */ diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c index 103f87ed0..98c3decbd 100644 --- a/bgpd/rfapi/rfapi_vty.c +++ b/bgpd/rfapi/rfapi_vty.c @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -69,68 +69,53 @@ #define FMT_DAY (24 * FMT_HOUR) #define FMT_YEAR (365 * FMT_DAY) -char * -rfapiFormatSeconds (uint32_t seconds, char *buf, size_t len) +char *rfapiFormatSeconds(uint32_t seconds, char *buf, size_t len) { - int year, day, hour, min; - - if (seconds >= FMT_YEAR) - { - year = seconds / FMT_YEAR; - seconds -= year * FMT_YEAR; - } - else - year = 0; - - if (seconds >= FMT_DAY) - { - day = seconds / FMT_DAY; - seconds -= day * FMT_DAY; - } - else - day = 0; - - if (seconds >= FMT_HOUR) - { - hour = seconds / FMT_HOUR; - seconds -= hour * FMT_HOUR; - } - else - hour = 0; - - if (seconds >= FMT_MIN) - { - min = seconds / FMT_MIN; - seconds -= min * FMT_MIN; - } - else - min = 0; - - if (year > 0) - { - snprintf (buf, len, "%dy%dd%dh", year, day, hour); - } - else if (day > 0) - { - snprintf (buf, len, "%dd%dh%dm", day, hour, min); - } - else - { - snprintf (buf, len, "%02d:%02d:%02d", hour, min, seconds); - } - - return buf; + int year, day, hour, min; + + if (seconds >= FMT_YEAR) { + year = seconds / FMT_YEAR; + seconds -= year * FMT_YEAR; + } else + year = 0; + + if (seconds >= FMT_DAY) { + day = seconds / FMT_DAY; + seconds -= day * FMT_DAY; + } else + day = 0; + + if (seconds >= FMT_HOUR) { + hour = seconds / FMT_HOUR; + seconds -= hour * FMT_HOUR; + } else + hour = 0; + + if (seconds >= FMT_MIN) { + min = seconds / FMT_MIN; + seconds -= min * FMT_MIN; + } else + min = 0; + + if (year > 0) { + snprintf(buf, len, "%dy%dd%dh", year, day, hour); + } else if (day > 0) { + snprintf(buf, len, "%dd%dh%dm", day, hour, min); + } else { + snprintf(buf, len, "%02d:%02d:%02d", hour, min, seconds); + } + + return buf; } -char * -rfapiFormatAge (time_t age, char *buf, size_t len) +char *rfapiFormatAge(time_t age, char *buf, size_t len) { - time_t now, age_adjusted; + time_t now, age_adjusted; - now = rfapi_time (NULL); - age_adjusted = now - age; + now = rfapi_time(NULL); + age_adjusted = now - age; - return rfapiFormatSeconds (age_adjusted, buf, len); + return rfapiFormatSeconds(age_adjusted, buf, len); } @@ -138,47 +123,43 @@ rfapiFormatAge (time_t age, char *buf, size_t len) * Reimplementation of quagga/lib/prefix.c function, but * for RFAPI-style prefixes */ -void -rfapiRprefixApplyMask (struct rfapi_ip_prefix *rprefix) +void rfapiRprefixApplyMask(struct rfapi_ip_prefix *rprefix) { - uint8_t *pnt; - int index; - int offset; - - static uint8_t maskbit[] = - { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; - - switch (rprefix->prefix.addr_family) - { - case AF_INET: - index = rprefix->length / 8; - if (index < 4) - { - pnt = (uint8_t *) & rprefix->prefix.addr.v4; - offset = rprefix->length % 8; - pnt[index] &= maskbit[offset]; - index++; - while (index < 4) - pnt[index++] = 0; - } - break; - - case AF_INET6: - index = rprefix->length / 8; - if (index < 16) - { - pnt = (uint8_t *) & rprefix->prefix.addr.v6; - offset = rprefix->length % 8; - pnt[index] &= maskbit[offset]; - index++; - while (index < 16) - pnt[index++] = 0; - } - break; - - default: - assert (0); - } + uint8_t *pnt; + int index; + int offset; + + static uint8_t maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, + 0xf8, 0xfc, 0xfe, 0xff}; + + switch (rprefix->prefix.addr_family) { + case AF_INET: + index = rprefix->length / 8; + if (index < 4) { + pnt = (uint8_t *)&rprefix->prefix.addr.v4; + offset = rprefix->length % 8; + pnt[index] &= maskbit[offset]; + index++; + while (index < 4) + pnt[index++] = 0; + } + break; + + case AF_INET6: + index = rprefix->length / 8; + if (index < 16) { + pnt = (uint8_t *)&rprefix->prefix.addr.v6; + offset = rprefix->length % 8; + pnt[index] &= maskbit[offset]; + index++; + while (index < 16) + pnt[index++] = 0; + } + break; + + default: + assert(0); + } } /* @@ -190,71 +171,67 @@ rfapiRprefixApplyMask (struct rfapi_ip_prefix *rprefix) * 0 Success * <0 Error */ -int -rfapiQprefix2Raddr (struct prefix *qprefix, struct rfapi_ip_addr *raddr) +int rfapiQprefix2Raddr(struct prefix *qprefix, struct rfapi_ip_addr *raddr) { - memset (raddr, 0, sizeof (struct rfapi_ip_addr)); - raddr->addr_family = qprefix->family; - switch (qprefix->family) - { - case AF_INET: - if (qprefix->prefixlen != 32) - return -1; - raddr->addr.v4 = qprefix->u.prefix4; - break; - case AF_INET6: - if (qprefix->prefixlen != 128) - return -1; - raddr->addr.v6 = qprefix->u.prefix6; - break; - default: - return -1; - } - return 0; + memset(raddr, 0, sizeof(struct rfapi_ip_addr)); + raddr->addr_family = qprefix->family; + switch (qprefix->family) { + case AF_INET: + if (qprefix->prefixlen != 32) + return -1; + raddr->addr.v4 = qprefix->u.prefix4; + break; + case AF_INET6: + if (qprefix->prefixlen != 128) + return -1; + raddr->addr.v6 = qprefix->u.prefix6; + break; + default: + return -1; + } + return 0; } -/* +/* * Translate Quagga prefix to RFAPI prefix */ /* rprefix->cost set to 0 */ -void -rfapiQprefix2Rprefix (struct prefix *qprefix, struct rfapi_ip_prefix *rprefix) +void rfapiQprefix2Rprefix(struct prefix *qprefix, + struct rfapi_ip_prefix *rprefix) { - memset (rprefix, 0, sizeof (struct rfapi_ip_prefix)); - rprefix->length = qprefix->prefixlen; - rprefix->prefix.addr_family = qprefix->family; - switch (qprefix->family) - { - case AF_INET: - rprefix->prefix.addr.v4 = qprefix->u.prefix4; - break; - case AF_INET6: - rprefix->prefix.addr.v6 = qprefix->u.prefix6; - break; - default: - assert (0); - } + memset(rprefix, 0, sizeof(struct rfapi_ip_prefix)); + rprefix->length = qprefix->prefixlen; + rprefix->prefix.addr_family = qprefix->family; + switch (qprefix->family) { + case AF_INET: + rprefix->prefix.addr.v4 = qprefix->u.prefix4; + break; + case AF_INET6: + rprefix->prefix.addr.v6 = qprefix->u.prefix6; + break; + default: + assert(0); + } } -int -rfapiRprefix2Qprefix (struct rfapi_ip_prefix *rprefix, struct prefix *qprefix) +int rfapiRprefix2Qprefix(struct rfapi_ip_prefix *rprefix, + struct prefix *qprefix) { - memset (qprefix, 0, sizeof (struct prefix)); - qprefix->prefixlen = rprefix->length; - qprefix->family = rprefix->prefix.addr_family; - - switch (rprefix->prefix.addr_family) - { - case AF_INET: - qprefix->u.prefix4 = rprefix->prefix.addr.v4; - break; - case AF_INET6: - qprefix->u.prefix6 = rprefix->prefix.addr.v6; - break; - default: - return EAFNOSUPPORT; - } - return 0; + memset(qprefix, 0, sizeof(struct prefix)); + qprefix->prefixlen = rprefix->length; + qprefix->family = rprefix->prefix.addr_family; + + switch (rprefix->prefix.addr_family) { + case AF_INET: + qprefix->u.prefix4 = rprefix->prefix.addr.v4; + break; + case AF_INET6: + qprefix->u.prefix6 = rprefix->prefix.addr.v6; + break; + default: + return EAFNOSUPPORT; + } + return 0; } /* @@ -264,122 +241,111 @@ rfapiRprefix2Qprefix (struct rfapi_ip_prefix *rprefix, struct prefix *qprefix) * For paralellism with quagga/lib/prefix.c. if we need a comparison * where host bits are ignored, call that function rfapiRprefixCmp. */ -int -rfapiRprefixSame (struct rfapi_ip_prefix *hp1, struct rfapi_ip_prefix *hp2) +int rfapiRprefixSame(struct rfapi_ip_prefix *hp1, struct rfapi_ip_prefix *hp2) { - if (hp1->prefix.addr_family != hp2->prefix.addr_family) - return 0; - if (hp1->length != hp2->length) - return 0; - if (hp1->prefix.addr_family == AF_INET) - if (IPV4_ADDR_SAME (&hp1->prefix.addr.v4, &hp2->prefix.addr.v4)) - return 1; - if (hp1->prefix.addr_family == AF_INET6) - if (IPV6_ADDR_SAME (&hp1->prefix.addr.v6, &hp2->prefix.addr.v6)) - return 1; - return 0; + if (hp1->prefix.addr_family != hp2->prefix.addr_family) + return 0; + if (hp1->length != hp2->length) + return 0; + if (hp1->prefix.addr_family == AF_INET) + if (IPV4_ADDR_SAME(&hp1->prefix.addr.v4, &hp2->prefix.addr.v4)) + return 1; + if (hp1->prefix.addr_family == AF_INET6) + if (IPV6_ADDR_SAME(&hp1->prefix.addr.v6, &hp2->prefix.addr.v6)) + return 1; + return 0; } -int -rfapiRaddr2Qprefix (struct rfapi_ip_addr *hia, struct prefix *pfx) +int rfapiRaddr2Qprefix(struct rfapi_ip_addr *hia, struct prefix *pfx) { - memset (pfx, 0, sizeof (struct prefix)); - pfx->family = hia->addr_family; - - switch (hia->addr_family) - { - case AF_INET: - pfx->prefixlen = 32; - pfx->u.prefix4 = hia->addr.v4; - break; - case AF_INET6: - pfx->prefixlen = 128; - pfx->u.prefix6 = hia->addr.v6; - break; - default: - return EAFNOSUPPORT; - } - return 0; + memset(pfx, 0, sizeof(struct prefix)); + pfx->family = hia->addr_family; + + switch (hia->addr_family) { + case AF_INET: + pfx->prefixlen = 32; + pfx->u.prefix4 = hia->addr.v4; + break; + case AF_INET6: + pfx->prefixlen = 128; + pfx->u.prefix6 = hia->addr.v6; + break; + default: + return EAFNOSUPPORT; + } + return 0; } -void -rfapiL2o2Qprefix (struct rfapi_l2address_option *l2o, struct prefix *pfx) +void rfapiL2o2Qprefix(struct rfapi_l2address_option *l2o, struct prefix *pfx) { - memset (pfx, 0, sizeof (struct prefix)); - pfx->family = AF_ETHERNET; - pfx->prefixlen = 48; - pfx->u.prefix_eth = l2o->macaddr; + memset(pfx, 0, sizeof(struct prefix)); + pfx->family = AF_ETHERNET; + pfx->prefixlen = 48; + pfx->u.prefix_eth = l2o->macaddr; } -char * -rfapiEthAddr2Str (const struct ethaddr *ea, char *buf, int bufsize) +char *rfapiEthAddr2Str(const struct ethaddr *ea, char *buf, int bufsize) { - return prefix_mac2str (ea, buf, bufsize); + return prefix_mac2str(ea, buf, bufsize); } -int -rfapiStr2EthAddr (const char *str, struct ethaddr *ea) +int rfapiStr2EthAddr(const char *str, struct ethaddr *ea) { - unsigned int a[6]; - int i; + unsigned int a[6]; + int i; - if (sscanf (str, "%2x:%2x:%2x:%2x:%2x:%2x", - a + 0, a + 1, a + 2, a + 3, a + 4, a + 5) != 6) - { + if (sscanf(str, "%2x:%2x:%2x:%2x:%2x:%2x", a + 0, a + 1, a + 2, a + 3, + a + 4, a + 5) + != 6) { - return EINVAL; - } + return EINVAL; + } - for (i = 0; i < 6; ++i) - ea->octet[i] = a[i] & 0xff; + for (i = 0; i < 6; ++i) + ea->octet[i] = a[i] & 0xff; - return 0; + return 0; } -const char * -rfapi_ntop (int af, const void *src, char *buf, socklen_t size) +const char *rfapi_ntop(int af, const void *src, char *buf, socklen_t size) { - if (af == AF_ETHERNET) - { - return rfapiEthAddr2Str ((const struct ethaddr *) src, buf, size); - } + if (af == AF_ETHERNET) { + return rfapiEthAddr2Str((const struct ethaddr *)src, buf, size); + } - return inet_ntop (af, src, buf, size); + return inet_ntop(af, src, buf, size); } -int -rfapiDebugPrintf (void *dummy, const char *format, ...) +int rfapiDebugPrintf(void *dummy, const char *format, ...) { - va_list args; - va_start (args, format); - vzlog (LOG_DEBUG, format, args); - va_end (args); - return 0; + va_list args; + va_start(args, format); + vzlog(LOG_DEBUG, format, args); + va_end(args); + return 0; } -static int -rfapiStdioPrintf (void *stream, const char *format, ...) +static int rfapiStdioPrintf(void *stream, const char *format, ...) { - FILE *file = NULL; - - va_list args; - va_start (args, format); - - switch ((uintptr_t) stream) - { - case 1: - file = stdout; - break; - case 2: - file = stderr; - break; - default: - assert (0); - } - - vfprintf (file, format, args); - va_end (args); - return 0; + FILE *file = NULL; + + va_list args; + va_start(args, format); + + switch ((uintptr_t)stream) { + case 1: + file = stdout; + break; + case 2: + file = stderr; + break; + default: + assert(0); + } + + vfprintf(file, format, args); + va_end(args); + return 0; } /* Fake out for debug logging */ @@ -387,1133 +353,1016 @@ static struct vty vty_dummy_zlog; static struct vty vty_dummy_stdio; #define HVTYNL ((vty == &vty_dummy_zlog)? "": "\n") -static const char * -str_vty_newline (struct vty *vty) +static const char *str_vty_newline(struct vty *vty) { - if (vty == &vty_dummy_zlog) - return ""; - return "\n"; + if (vty == &vty_dummy_zlog) + return ""; + return "\n"; } -int -rfapiStream2Vty ( - void *stream, /* input */ - int (**fp) (void *, const char *, ...), /* output */ - struct vty **vty, /* output */ - void **outstream, /* output */ - const char **vty_newline) /* output */ +int rfapiStream2Vty(void *stream, /* input */ + int (**fp)(void *, const char *, ...), /* output */ + struct vty **vty, /* output */ + void **outstream, /* output */ + const char **vty_newline) /* output */ { - if (!stream) - { - vty_dummy_zlog.type = VTY_SHELL; /* for VTYNL */ - *vty = &vty_dummy_zlog; - *fp = (int (*)(void *, const char *,...)) rfapiDebugPrintf; - *outstream = NULL; - *vty_newline = str_vty_newline (*vty); - return (vzlog_test (LOG_DEBUG)); - } - - if (((uintptr_t) stream == (uintptr_t) 1) || - ((uintptr_t) stream == (uintptr_t) 2)) - { - - vty_dummy_stdio.type = VTY_SHELL; /* for VTYNL */ - *vty = &vty_dummy_stdio; - *fp = (int (*)(void *, const char *,...)) rfapiStdioPrintf; - *outstream = stream; - *vty_newline = str_vty_newline (*vty); - return 1; - } - - if (stream) - { - *vty = stream; /* VTYNL requires vty to be legit */ - *fp = (int (*)(void *, const char *,...)) vty_out; - *outstream = stream; - *vty_newline = str_vty_newline (*vty); - return 1; - } - - return 0; + if (!stream) { + vty_dummy_zlog.type = VTY_SHELL; /* for VTYNL */ + *vty = &vty_dummy_zlog; + *fp = (int (*)(void *, const char *, ...))rfapiDebugPrintf; + *outstream = NULL; + *vty_newline = str_vty_newline(*vty); + return (vzlog_test(LOG_DEBUG)); + } + + if (((uintptr_t)stream == (uintptr_t)1) + || ((uintptr_t)stream == (uintptr_t)2)) { + + vty_dummy_stdio.type = VTY_SHELL; /* for VTYNL */ + *vty = &vty_dummy_stdio; + *fp = (int (*)(void *, const char *, ...))rfapiStdioPrintf; + *outstream = stream; + *vty_newline = str_vty_newline(*vty); + return 1; + } + + if (stream) { + *vty = stream; /* VTYNL requires vty to be legit */ + *fp = (int (*)(void *, const char *, ...))vty_out; + *outstream = stream; + *vty_newline = str_vty_newline(*vty); + return 1; + } + + return 0; } /* called from bgpd/bgp_vty.c'route_vty_out() */ -void -rfapi_vty_out_vncinfo ( - struct vty *vty, - struct prefix *p, - struct bgp_info *bi, - safi_t safi) +void rfapi_vty_out_vncinfo(struct vty *vty, struct prefix *p, + struct bgp_info *bi, safi_t safi) { - char *s; - uint32_t lifetime; - - /* - * Print, on an indented line: - * UN address [if VPN route and VNC UN addr subtlv] - * EC list - * VNC lifetime - */ - vty_out (vty, " "); - - if (safi == SAFI_MPLS_VPN) - { - struct prefix pfx_un; - - if (!rfapiGetVncTunnelUnAddr (bi->attr, &pfx_un)) - { - char buf[BUFSIZ]; - vty_out (vty, "UN=%s", inet_ntop (pfx_un.family, - pfx_un.u.val, buf, BUFSIZ)); - } - } - - if (bi->attr && bi->attr->ecommunity) - { - s = ecommunity_ecom2str (bi->attr->ecommunity, - ECOMMUNITY_FORMAT_ROUTE_MAP, 0); - vty_out (vty, " EC{%s}", s); - XFREE (MTYPE_ECOMMUNITY_STR, s); - } - - if (bi->extra != NULL) - vty_out (vty, " label=%u", decode_label (&bi->extra->label)); - - if (!rfapiGetVncLifetime (bi->attr, &lifetime)) - { - vty_out (vty, " life=%d", lifetime); - } - - vty_out (vty, " type=%s, subtype=%d", - zebra_route_string (bi->type), bi->sub_type); - - vty_out (vty, "%s", HVTYNL); + char *s; + uint32_t lifetime; + + /* + * Print, on an indented line: + * UN address [if VPN route and VNC UN addr subtlv] + * EC list + * VNC lifetime + */ + vty_out(vty, " "); + + if (safi == SAFI_MPLS_VPN) { + struct prefix pfx_un; + + if (!rfapiGetVncTunnelUnAddr(bi->attr, &pfx_un)) { + char buf[BUFSIZ]; + vty_out(vty, "UN=%s", + inet_ntop(pfx_un.family, pfx_un.u.val, buf, + BUFSIZ)); + } + } + + if (bi->attr && bi->attr->ecommunity) { + s = ecommunity_ecom2str(bi->attr->ecommunity, + ECOMMUNITY_FORMAT_ROUTE_MAP, 0); + vty_out(vty, " EC{%s}", s); + XFREE(MTYPE_ECOMMUNITY_STR, s); + } + + if (bi->extra != NULL) + vty_out(vty, " label=%u", decode_label(&bi->extra->label)); + + if (!rfapiGetVncLifetime(bi->attr, &lifetime)) { + vty_out(vty, " life=%d", lifetime); + } + + vty_out(vty, " type=%s, subtype=%d", zebra_route_string(bi->type), + bi->sub_type); + + vty_out(vty, "%s", HVTYNL); } -void -rfapiPrintAttrPtrs (void *stream, struct attr *attr) +void rfapiPrintAttrPtrs(void *stream, struct attr *attr) { - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; - - char buf[BUFSIZ]; - - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - - fp (out, "Attr[%p]:%s", attr, HVTYNL); - if (!attr) - return; - - /* IPv4 Nexthop */ - inet_ntop (AF_INET, &attr->nexthop, buf, BUFSIZ); - fp (out, " nexthop=%s%s", buf, HVTYNL); - - fp (out, " aspath=%p, refcnt=%d%s", attr->aspath, - (attr->aspath ? attr->aspath->refcnt : 0), HVTYNL); - fp (out, " community=%p, refcnt=%d%s", attr->community, - (attr->community ? attr->community->refcnt : 0), HVTYNL); - - fp (out, " ecommunity=%p, refcnt=%d%s", attr->ecommunity, - (attr->ecommunity ? attr->ecommunity->refcnt : 0), HVTYNL); - fp (out, " cluster=%p, refcnt=%d%s", attr->cluster, - (attr->cluster ? attr->cluster->refcnt : 0), HVTYNL); - fp (out, " transit=%p, refcnt=%d%s", attr->transit, - (attr->transit ? attr->transit->refcnt : 0), HVTYNL); + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; + + char buf[BUFSIZ]; + + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + + fp(out, "Attr[%p]:%s", attr, HVTYNL); + if (!attr) + return; + + /* IPv4 Nexthop */ + inet_ntop(AF_INET, &attr->nexthop, buf, BUFSIZ); + fp(out, " nexthop=%s%s", buf, HVTYNL); + + fp(out, " aspath=%p, refcnt=%d%s", attr->aspath, + (attr->aspath ? attr->aspath->refcnt : 0), HVTYNL); + fp(out, " community=%p, refcnt=%d%s", attr->community, + (attr->community ? attr->community->refcnt : 0), HVTYNL); + + fp(out, " ecommunity=%p, refcnt=%d%s", attr->ecommunity, + (attr->ecommunity ? attr->ecommunity->refcnt : 0), HVTYNL); + fp(out, " cluster=%p, refcnt=%d%s", attr->cluster, + (attr->cluster ? attr->cluster->refcnt : 0), HVTYNL); + fp(out, " transit=%p, refcnt=%d%s", attr->transit, + (attr->transit ? attr->transit->refcnt : 0), HVTYNL); } /* * Print BI in an Import Table */ -void -rfapiPrintBi (void *stream, struct bgp_info *bi) +void rfapiPrintBi(void *stream, struct bgp_info *bi) { - char buf[BUFSIZ]; - char *s; - - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; - - char line[BUFSIZ]; - char *p = line; - int r; - int has_macaddr = 0; - struct ethaddr macaddr; - struct rfapi_l2address_option l2o_buf; - uint8_t l2hid=0; /* valid if has_macaddr */ + char buf[BUFSIZ]; + char *s; + + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; + + char line[BUFSIZ]; + char *p = line; + int r; + int has_macaddr = 0; + struct ethaddr macaddr; + struct rfapi_l2address_option l2o_buf; + uint8_t l2hid = 0; /* valid if has_macaddr */ #define REMAIN (BUFSIZ - (p-line)) #define INCP {p += (r > REMAIN)? REMAIN: r;} - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - - if (!bi) - return; - - if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED) && bi->extra - && bi->extra->vnc.import.timer) - { - struct thread *t = (struct thread *) bi->extra->vnc.import.timer; - r = snprintf (p, REMAIN, " [%4lu] ", thread_timer_remain_second (t)); - INCP; - - } - else - { - r = snprintf (p, REMAIN, " "); - INCP; - } - - if (bi->extra) - { - /* TBD This valid only for SAFI_MPLS_VPN, but not for encap */ - if (decode_rd_type(bi->extra->vnc.import.rd.val) == RD_TYPE_VNC_ETH) - { - has_macaddr = 1; - memcpy (macaddr.octet, bi->extra->vnc.import.rd.val + 2, 6); - l2hid = bi->extra->vnc.import.rd.val[1]; - } - } - - /* - * Print these items: - * type/subtype - * nexthop address - * lifetime - * RFP option sizes (they are opaque values) - * extended communities (RTs) - */ - if (bi->attr) - { - uint32_t lifetime; - int printed_1st_gol = 0; - struct bgp_attr_encap_subtlv *pEncap; - struct prefix pfx_un; - int af = BGP_MP_NEXTHOP_FAMILY (bi->attr->mp_nexthop_len); - - /* Nexthop */ - if (af == AF_INET) - { - r = snprintf (p, REMAIN, "%s", inet_ntop (AF_INET, - &bi->attr->mp_nexthop_global_in, - buf, BUFSIZ)); - INCP; - } - else if (af == AF_INET6) - { - r = snprintf (p, REMAIN, "%s", inet_ntop (AF_INET6, - &bi->attr->mp_nexthop_global, - buf, BUFSIZ)); - INCP; - } - else - { - r = snprintf (p, REMAIN, "?"); - INCP; - } - - /* - * VNC tunnel subtlv, if present, contains UN address - */ - if (!rfapiGetVncTunnelUnAddr (bi->attr, &pfx_un)) - { - r = snprintf (p, REMAIN, " un=%s", inet_ntop (pfx_un.family, - pfx_un.u.val, buf, - BUFSIZ)); - INCP; - - } - - /* Lifetime */ - if (rfapiGetVncLifetime (bi->attr, &lifetime)) - { - r = snprintf (p, REMAIN, " nolife"); - INCP; - } - else - { - if (lifetime == 0xffffffff) - r = snprintf (p, REMAIN, " %6s", "infini"); - else - r = snprintf (p, REMAIN, " %6u", lifetime); - INCP; - } - - /* RFP option lengths */ - for (pEncap = bi->attr->vnc_subtlvs; pEncap; - pEncap = pEncap->next) - { - - if (pEncap->type == BGP_VNC_SUBTLV_TYPE_RFPOPTION) - { - if (printed_1st_gol) - { - r = snprintf (p, REMAIN, ","); - INCP; - } - else - { - r = snprintf (p, REMAIN, " "); /* leading space */ - INCP; - } - r = snprintf (p, REMAIN, "%d", pEncap->length); - INCP; - printed_1st_gol = 1; - } - } - - /* RT list */ - if (bi->attr->ecommunity) - { - s = ecommunity_ecom2str (bi->attr->ecommunity, - ECOMMUNITY_FORMAT_ROUTE_MAP, 0); - r = snprintf (p, REMAIN, " %s", s); - INCP; - XFREE (MTYPE_ECOMMUNITY_STR, s); - } - - } - - r = snprintf (p, REMAIN, " bi@%p", bi); - INCP; - - r = snprintf (p, REMAIN, " p@%p", bi->peer); - INCP; - - if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)) - { - r = snprintf (p, REMAIN, " HD=yes"); - INCP; - } - else - { - r = snprintf (p, REMAIN, " HD=no"); - INCP; - } - - if (bi->attr) - { - - if (bi->attr->weight) - { - r = snprintf (p, REMAIN, " W=%d", bi->attr->weight); - INCP; - } - - if (bi->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) - { - r = snprintf (p, REMAIN, " LP=%d", bi->attr->local_pref); - INCP; - } - else - { - r = snprintf (p, REMAIN, " LP=unset"); - INCP; - } - } - - r = - snprintf (p, REMAIN, " %c:%u", zebra_route_char (bi->type), bi->sub_type); - INCP; - - fp (out, "%s%s", line, HVTYNL); - - if (has_macaddr) - { - fp (out, " RD HID=%d ETH=%02x:%02x:%02x:%02x:%02x:%02x%s", - l2hid, - macaddr.octet[0], - macaddr.octet[1], - macaddr.octet[2], - macaddr.octet[3], macaddr.octet[4], macaddr.octet[5], HVTYNL); - } - - if (!rfapiGetL2o (bi->attr, &l2o_buf)) - { - fp (out, - " L2O ETH=%02x:%02x:%02x:%02x:%02x:%02x LBL=%d LNI=%d LHI=%hhu%s", - l2o_buf.macaddr.octet[0], l2o_buf.macaddr.octet[1], - l2o_buf.macaddr.octet[2], l2o_buf.macaddr.octet[3], - l2o_buf.macaddr.octet[4], l2o_buf.macaddr.octet[5], l2o_buf.label, - l2o_buf.logical_net_id, l2o_buf.local_nve_id, HVTYNL); - } - if (bi->extra && bi->extra->vnc.import.aux_prefix.family) - { - char buf[BUFSIZ]; - const char *sp; - - sp = rfapi_ntop (bi->extra->vnc.import.aux_prefix.family, - &bi->extra->vnc.import.aux_prefix.u.prefix, - buf, BUFSIZ); - buf[BUFSIZ - 1] = 0; - if (sp) - { - fp (out, " IP: %s%s", sp, HVTYNL); - } - } - { - struct rfapi_un_option *uo = rfapi_encap_tlv_to_un_option (bi->attr); - if (uo) - { - rfapi_print_tunneltype_option (stream, 8, &uo->v.tunnel); - rfapi_un_options_free (uo); - } - } + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + + if (!bi) + return; + + if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED) && bi->extra + && bi->extra->vnc.import.timer) { + struct thread *t = (struct thread *)bi->extra->vnc.import.timer; + r = snprintf(p, REMAIN, " [%4lu] ", + thread_timer_remain_second(t)); + INCP; + + } else { + r = snprintf(p, REMAIN, " "); + INCP; + } + + if (bi->extra) { + /* TBD This valid only for SAFI_MPLS_VPN, but not for encap */ + if (decode_rd_type(bi->extra->vnc.import.rd.val) + == RD_TYPE_VNC_ETH) { + has_macaddr = 1; + memcpy(macaddr.octet, bi->extra->vnc.import.rd.val + 2, + 6); + l2hid = bi->extra->vnc.import.rd.val[1]; + } + } + + /* + * Print these items: + * type/subtype + * nexthop address + * lifetime + * RFP option sizes (they are opaque values) + * extended communities (RTs) + */ + if (bi->attr) { + uint32_t lifetime; + int printed_1st_gol = 0; + struct bgp_attr_encap_subtlv *pEncap; + struct prefix pfx_un; + int af = BGP_MP_NEXTHOP_FAMILY(bi->attr->mp_nexthop_len); + + /* Nexthop */ + if (af == AF_INET) { + r = snprintf(p, REMAIN, "%s", + inet_ntop(AF_INET, + &bi->attr->mp_nexthop_global_in, + buf, BUFSIZ)); + INCP; + } else if (af == AF_INET6) { + r = snprintf(p, REMAIN, "%s", + inet_ntop(AF_INET6, + &bi->attr->mp_nexthop_global, + buf, BUFSIZ)); + INCP; + } else { + r = snprintf(p, REMAIN, "?"); + INCP; + } + + /* + * VNC tunnel subtlv, if present, contains UN address + */ + if (!rfapiGetVncTunnelUnAddr(bi->attr, &pfx_un)) { + r = snprintf(p, REMAIN, " un=%s", + inet_ntop(pfx_un.family, pfx_un.u.val, buf, + BUFSIZ)); + INCP; + } + + /* Lifetime */ + if (rfapiGetVncLifetime(bi->attr, &lifetime)) { + r = snprintf(p, REMAIN, " nolife"); + INCP; + } else { + if (lifetime == 0xffffffff) + r = snprintf(p, REMAIN, " %6s", "infini"); + else + r = snprintf(p, REMAIN, " %6u", lifetime); + INCP; + } + + /* RFP option lengths */ + for (pEncap = bi->attr->vnc_subtlvs; pEncap; + pEncap = pEncap->next) { + + if (pEncap->type == BGP_VNC_SUBTLV_TYPE_RFPOPTION) { + if (printed_1st_gol) { + r = snprintf(p, REMAIN, ","); + INCP; + } else { + r = snprintf(p, REMAIN, + " "); /* leading space */ + INCP; + } + r = snprintf(p, REMAIN, "%d", pEncap->length); + INCP; + printed_1st_gol = 1; + } + } + + /* RT list */ + if (bi->attr->ecommunity) { + s = ecommunity_ecom2str(bi->attr->ecommunity, + ECOMMUNITY_FORMAT_ROUTE_MAP, 0); + r = snprintf(p, REMAIN, " %s", s); + INCP; + XFREE(MTYPE_ECOMMUNITY_STR, s); + } + } + + r = snprintf(p, REMAIN, " bi@%p", bi); + INCP; + + r = snprintf(p, REMAIN, " p@%p", bi->peer); + INCP; + + if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) { + r = snprintf(p, REMAIN, " HD=yes"); + INCP; + } else { + r = snprintf(p, REMAIN, " HD=no"); + INCP; + } + + if (bi->attr) { + + if (bi->attr->weight) { + r = snprintf(p, REMAIN, " W=%d", bi->attr->weight); + INCP; + } + + if (bi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) { + r = snprintf(p, REMAIN, " LP=%d", bi->attr->local_pref); + INCP; + } else { + r = snprintf(p, REMAIN, " LP=unset"); + INCP; + } + } + + r = snprintf(p, REMAIN, " %c:%u", zebra_route_char(bi->type), + bi->sub_type); + INCP; + + fp(out, "%s%s", line, HVTYNL); + + if (has_macaddr) { + fp(out, " RD HID=%d ETH=%02x:%02x:%02x:%02x:%02x:%02x%s", + l2hid, macaddr.octet[0], macaddr.octet[1], macaddr.octet[2], + macaddr.octet[3], macaddr.octet[4], macaddr.octet[5], + HVTYNL); + } + + if (!rfapiGetL2o(bi->attr, &l2o_buf)) { + fp(out, + " L2O ETH=%02x:%02x:%02x:%02x:%02x:%02x LBL=%d LNI=%d LHI=%hhu%s", + l2o_buf.macaddr.octet[0], l2o_buf.macaddr.octet[1], + l2o_buf.macaddr.octet[2], l2o_buf.macaddr.octet[3], + l2o_buf.macaddr.octet[4], l2o_buf.macaddr.octet[5], + l2o_buf.label, l2o_buf.logical_net_id, l2o_buf.local_nve_id, + HVTYNL); + } + if (bi->extra && bi->extra->vnc.import.aux_prefix.family) { + char buf[BUFSIZ]; + const char *sp; + + sp = rfapi_ntop(bi->extra->vnc.import.aux_prefix.family, + &bi->extra->vnc.import.aux_prefix.u.prefix, buf, + BUFSIZ); + buf[BUFSIZ - 1] = 0; + if (sp) { + fp(out, " IP: %s%s", sp, HVTYNL); + } + } + { + struct rfapi_un_option *uo = + rfapi_encap_tlv_to_un_option(bi->attr); + if (uo) { + rfapi_print_tunneltype_option(stream, 8, &uo->v.tunnel); + rfapi_un_options_free(uo); + } + } } -char * -rfapiMonitorVpn2Str (struct rfapi_monitor_vpn *m, char *buf, int size) +char *rfapiMonitorVpn2Str(struct rfapi_monitor_vpn *m, char *buf, int size) { - char buf_pfx[BUFSIZ]; - char buf_vn[BUFSIZ]; - char buf_un[BUFSIZ]; - int rc; - - rfapiRfapiIpAddr2Str (&m->rfd->un_addr, buf_vn, BUFSIZ); - rfapiRfapiIpAddr2Str (&m->rfd->vn_addr, buf_un, BUFSIZ); - - rc = snprintf (buf, size, - "m=%p, next=%p, rfd=%p(vn=%s un=%s), p=%s/%d, node=%p", - m, m->next, m->rfd, buf_vn, buf_un, - inet_ntop (m->p.family, &m->p.u.prefix, buf_pfx, BUFSIZ), - m->p.prefixlen, m->node); - buf[size - 1] = 0; - if (rc >= size) - return NULL; - return buf; + char buf_pfx[BUFSIZ]; + char buf_vn[BUFSIZ]; + char buf_un[BUFSIZ]; + int rc; + + rfapiRfapiIpAddr2Str(&m->rfd->un_addr, buf_vn, BUFSIZ); + rfapiRfapiIpAddr2Str(&m->rfd->vn_addr, buf_un, BUFSIZ); + + rc = snprintf(buf, size, + "m=%p, next=%p, rfd=%p(vn=%s un=%s), p=%s/%d, node=%p", m, + m->next, m->rfd, buf_vn, buf_un, + inet_ntop(m->p.family, &m->p.u.prefix, buf_pfx, BUFSIZ), + m->p.prefixlen, m->node); + buf[size - 1] = 0; + if (rc >= size) + return NULL; + return buf; } -static void -rfapiDebugPrintMonitorVpn (void *stream, struct rfapi_monitor_vpn *m) +static void rfapiDebugPrintMonitorVpn(void *stream, struct rfapi_monitor_vpn *m) { - char buf[BUFSIZ]; + char buf[BUFSIZ]; - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; - rfapiMonitorVpn2Str (m, buf, BUFSIZ); - fp (out, " Mon %s%s", buf, HVTYNL); + rfapiMonitorVpn2Str(m, buf, BUFSIZ); + fp(out, " Mon %s%s", buf, HVTYNL); } -static void -rfapiDebugPrintMonitorEncap (void *stream, struct rfapi_monitor_encap *m) +static void rfapiDebugPrintMonitorEncap(void *stream, + struct rfapi_monitor_encap *m) { - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out = NULL; - const char *vty_newline; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out = NULL; + const char *vty_newline; - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; - fp (out, " Mon m=%p, next=%p, node=%p, bi=%p%s", - m, m->next, m->node, m->bi, HVTYNL); + fp(out, " Mon m=%p, next=%p, node=%p, bi=%p%s", m, m->next, m->node, + m->bi, HVTYNL); } -void -rfapiShowItNode (void *stream, struct route_node *rn) +void rfapiShowItNode(void *stream, struct route_node *rn) { - struct bgp_info *bi; - char buf[BUFSIZ]; + struct bgp_info *bi; + char buf[BUFSIZ]; - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; - fp (out, "%s/%d @%p #%d%s", - rfapi_ntop (rn->p.family, &rn->p.u.prefix, buf, BUFSIZ), - rn->p.prefixlen, rn, rn->lock, HVTYNL); + fp(out, "%s/%d @%p #%d%s", + rfapi_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ), + rn->p.prefixlen, rn, rn->lock, HVTYNL); - for (bi = rn->info; bi; bi = bi->next) - { - rfapiPrintBi (stream, bi); - } + for (bi = rn->info; bi; bi = bi->next) { + rfapiPrintBi(stream, bi); + } - /* doesn't show montors */ + /* doesn't show montors */ } -void -rfapiShowImportTable ( - void *stream, - const char *label, - struct route_table *rt, - int isvpn) +void rfapiShowImportTable(void *stream, const char *label, + struct route_table *rt, int isvpn) { - struct route_node *rn; - char buf[BUFSIZ]; - - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; - - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - - fp (out, "Import Table [%s]%s", label, HVTYNL); - - for (rn = route_top (rt); rn; rn = route_next (rn)) - { - struct bgp_info *bi; - - if (rn->p.family == AF_ETHERNET) - { - rfapiEthAddr2Str (&rn->p.u.prefix_eth, buf, BUFSIZ); - } - else - { - inet_ntop (rn->p.family, &rn->p.u.prefix, buf, BUFSIZ); - } - - fp (out, "%s/%d @%p #%d%s", buf, rn->p.prefixlen, rn, rn->lock - 1, /* account for loop iterator locking */ - HVTYNL); - - for (bi = rn->info; bi; bi = bi->next) - { - rfapiPrintBi (stream, bi); - } - - if (isvpn) - { - struct rfapi_monitor_vpn *m; - for (m = RFAPI_MONITOR_VPN (rn); m; m = m->next) - { - rfapiDebugPrintMonitorVpn (stream, m); - } - } - else - { - struct rfapi_monitor_encap *m; - for (m = RFAPI_MONITOR_ENCAP (rn); m; m = m->next) - { - rfapiDebugPrintMonitorEncap (stream, m); - } - } - } + struct route_node *rn; + char buf[BUFSIZ]; + + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; + + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + + fp(out, "Import Table [%s]%s", label, HVTYNL); + + for (rn = route_top(rt); rn; rn = route_next(rn)) { + struct bgp_info *bi; + + if (rn->p.family == AF_ETHERNET) { + rfapiEthAddr2Str(&rn->p.u.prefix_eth, buf, BUFSIZ); + } else { + inet_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ); + } + + fp(out, "%s/%d @%p #%d%s", buf, rn->p.prefixlen, rn, + rn->lock - 1, /* account for loop iterator locking */ + HVTYNL); + + for (bi = rn->info; bi; bi = bi->next) { + rfapiPrintBi(stream, bi); + } + + if (isvpn) { + struct rfapi_monitor_vpn *m; + for (m = RFAPI_MONITOR_VPN(rn); m; m = m->next) { + rfapiDebugPrintMonitorVpn(stream, m); + } + } else { + struct rfapi_monitor_encap *m; + for (m = RFAPI_MONITOR_ENCAP(rn); m; m = m->next) { + rfapiDebugPrintMonitorEncap(stream, m); + } + } + } } -int -rfapiShowVncQueries (void *stream, struct prefix *pfx_match) +int rfapiShowVncQueries(void *stream, struct prefix *pfx_match) { - struct bgp *bgp; - struct rfapi *h; - struct listnode *node; - struct rfapi_descriptor *rfd; - - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; - - int printedheader = 0; - - int nves_total = 0; - int nves_with_queries = 0; - int nves_displayed = 0; - - int queries_total = 0; - int queries_displayed = 0; - - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return CMD_WARNING; - - bgp = bgp_get_default (); /* assume 1 instance for now */ - if (!bgp) - { - vty_out (vty, "No BGP instance\n"); - return CMD_WARNING; - } - - h = bgp->rfapi; - if (!h) - { - vty_out (vty, "No RFAPI instance\n"); - return CMD_WARNING; - } - - for (ALL_LIST_ELEMENTS_RO (&h->descriptors, node, rfd)) - { - - struct route_node *rn; - int printedquerier = 0; - - - ++nves_total; - - if (rfd->mon || (rfd->mon_eth && skiplist_count (rfd->mon_eth))) - { - ++nves_with_queries; - } - else - { - continue; - } - - /* - * IP Queries - */ - if (rfd->mon) - { - for (rn = route_top (rfd->mon); rn; rn = route_next (rn)) - { - struct rfapi_monitor_vpn *m; - char buf_remain[BUFSIZ]; - char buf_pfx[BUFSIZ]; - - if (!rn->info) - continue; - - m = rn->info; - - ++queries_total; - - if (pfx_match && !prefix_match (pfx_match, &rn->p) && - !prefix_match (&rn->p, pfx_match)) - continue; - - ++queries_displayed; - - if (!printedheader) - { - ++printedheader; - fp (out, "\n"); - fp (out, "%-15s %-15s %-15s %-10s\n", - "VN Address", "UN Address", - "Target", "Remaining"); - } - - if (!printedquerier) - { - char buf_vn[BUFSIZ]; - char buf_un[BUFSIZ]; - - rfapiRfapiIpAddr2Str (&rfd->un_addr, buf_un, BUFSIZ); - rfapiRfapiIpAddr2Str (&rfd->vn_addr, buf_vn, BUFSIZ); - - fp (out, "%-15s %-15s", buf_vn, buf_un); - printedquerier = 1; - - ++nves_displayed; - } - else - fp (out, "%-15s %-15s", "", ""); - buf_remain[0] = 0; - if (m->timer) - { - rfapiFormatSeconds (thread_timer_remain_second (m->timer), - buf_remain, BUFSIZ); - } - fp (out, " %-15s %-10s\n", - inet_ntop (m->p.family, &m->p.u.prefix, buf_pfx, BUFSIZ), - buf_remain); - } - } - - /* - * Ethernet Queries - */ - if (rfd->mon_eth && skiplist_count (rfd->mon_eth)) - { - - int rc; - void *cursor; - struct rfapi_monitor_eth *mon_eth; - - for (cursor = NULL, - rc = - skiplist_next (rfd->mon_eth, NULL, (void **) &mon_eth, - &cursor); rc == 0; - rc = - skiplist_next (rfd->mon_eth, NULL, (void **) &mon_eth, - &cursor)) - { - - char buf_remain[BUFSIZ]; - char buf_pfx[BUFSIZ]; - struct prefix pfx_mac; - - ++queries_total; - - vnc_zlog_debug_verbose ("%s: checking rfd=%p mon_eth=%p", __func__, rfd, - mon_eth); - - memset ((void *) &pfx_mac, 0, sizeof (struct prefix)); - pfx_mac.family = AF_ETHERNET; - pfx_mac.prefixlen = 48; - pfx_mac.u.prefix_eth = mon_eth->macaddr; - - if (pfx_match && !prefix_match (pfx_match, &pfx_mac) && - !prefix_match (&pfx_mac, pfx_match)) - continue; - - ++queries_displayed; - - if (!printedheader) - { - ++printedheader; - fp (out, "\n"); - fp (out, "%-15s %-15s %-17s %10s %-10s\n", - "VN Address", "UN Address", - "Target", "LNI", "Remaining"); - } - - if (!printedquerier) - { - char buf_vn[BUFSIZ]; - char buf_un[BUFSIZ]; - - rfapiRfapiIpAddr2Str (&rfd->un_addr, buf_un, BUFSIZ); - rfapiRfapiIpAddr2Str (&rfd->vn_addr, buf_vn, BUFSIZ); - - fp (out, "%-15s %-15s", buf_vn, buf_un); - printedquerier = 1; - - ++nves_displayed; - } - else - fp (out, "%-15s %-15s", "", ""); - buf_remain[0] = 0; - if (mon_eth->timer) - { - rfapiFormatSeconds (thread_timer_remain_second - (mon_eth->timer), buf_remain, BUFSIZ); - } - fp (out, " %-17s %10d %-10s\n", - rfapi_ntop (pfx_mac.family, &pfx_mac.u.prefix, buf_pfx, - BUFSIZ), mon_eth->logical_net_id, buf_remain); - } - } - } - - if (queries_total) - { - fp (out, "\n"); - fp (out, "Displayed %d out of %d total queries\n", - queries_displayed, queries_total); - } - return CMD_SUCCESS; + struct bgp *bgp; + struct rfapi *h; + struct listnode *node; + struct rfapi_descriptor *rfd; + + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; + + int printedheader = 0; + + int nves_total = 0; + int nves_with_queries = 0; + int nves_displayed = 0; + + int queries_total = 0; + int queries_displayed = 0; + + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return CMD_WARNING; + + bgp = bgp_get_default(); /* assume 1 instance for now */ + if (!bgp) { + vty_out(vty, "No BGP instance\n"); + return CMD_WARNING; + } + + h = bgp->rfapi; + if (!h) { + vty_out(vty, "No RFAPI instance\n"); + return CMD_WARNING; + } + + for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) { + + struct route_node *rn; + int printedquerier = 0; + + + ++nves_total; + + if (rfd->mon + || (rfd->mon_eth && skiplist_count(rfd->mon_eth))) { + ++nves_with_queries; + } else { + continue; + } + + /* + * IP Queries + */ + if (rfd->mon) { + for (rn = route_top(rfd->mon); rn; + rn = route_next(rn)) { + struct rfapi_monitor_vpn *m; + char buf_remain[BUFSIZ]; + char buf_pfx[BUFSIZ]; + + if (!rn->info) + continue; + + m = rn->info; + + ++queries_total; + + if (pfx_match + && !prefix_match(pfx_match, &rn->p) + && !prefix_match(&rn->p, pfx_match)) + continue; + + ++queries_displayed; + + if (!printedheader) { + ++printedheader; + fp(out, "\n"); + fp(out, "%-15s %-15s %-15s %-10s\n", + "VN Address", "UN Address", "Target", + "Remaining"); + } + + if (!printedquerier) { + char buf_vn[BUFSIZ]; + char buf_un[BUFSIZ]; + + rfapiRfapiIpAddr2Str(&rfd->un_addr, + buf_un, BUFSIZ); + rfapiRfapiIpAddr2Str(&rfd->vn_addr, + buf_vn, BUFSIZ); + + fp(out, "%-15s %-15s", buf_vn, buf_un); + printedquerier = 1; + + ++nves_displayed; + } else + fp(out, "%-15s %-15s", "", ""); + buf_remain[0] = 0; + if (m->timer) { + rfapiFormatSeconds( + thread_timer_remain_second( + m->timer), + buf_remain, BUFSIZ); + } + fp(out, " %-15s %-10s\n", + inet_ntop(m->p.family, &m->p.u.prefix, + buf_pfx, BUFSIZ), + buf_remain); + } + } + + /* + * Ethernet Queries + */ + if (rfd->mon_eth && skiplist_count(rfd->mon_eth)) { + + int rc; + void *cursor; + struct rfapi_monitor_eth *mon_eth; + + for (cursor = NULL, + rc = skiplist_next(rfd->mon_eth, NULL, + (void **)&mon_eth, &cursor); + rc == 0; + rc = skiplist_next(rfd->mon_eth, NULL, + (void **)&mon_eth, &cursor)) { + + char buf_remain[BUFSIZ]; + char buf_pfx[BUFSIZ]; + struct prefix pfx_mac; + + ++queries_total; + + vnc_zlog_debug_verbose( + "%s: checking rfd=%p mon_eth=%p", + __func__, rfd, mon_eth); + + memset((void *)&pfx_mac, 0, + sizeof(struct prefix)); + pfx_mac.family = AF_ETHERNET; + pfx_mac.prefixlen = 48; + pfx_mac.u.prefix_eth = mon_eth->macaddr; + + if (pfx_match + && !prefix_match(pfx_match, &pfx_mac) + && !prefix_match(&pfx_mac, pfx_match)) + continue; + + ++queries_displayed; + + if (!printedheader) { + ++printedheader; + fp(out, "\n"); + fp(out, + "%-15s %-15s %-17s %10s %-10s\n", + "VN Address", "UN Address", "Target", + "LNI", "Remaining"); + } + + if (!printedquerier) { + char buf_vn[BUFSIZ]; + char buf_un[BUFSIZ]; + + rfapiRfapiIpAddr2Str(&rfd->un_addr, + buf_un, BUFSIZ); + rfapiRfapiIpAddr2Str(&rfd->vn_addr, + buf_vn, BUFSIZ); + + fp(out, "%-15s %-15s", buf_vn, buf_un); + printedquerier = 1; + + ++nves_displayed; + } else + fp(out, "%-15s %-15s", "", ""); + buf_remain[0] = 0; + if (mon_eth->timer) { + rfapiFormatSeconds( + thread_timer_remain_second( + mon_eth->timer), + buf_remain, BUFSIZ); + } + fp(out, " %-17s %10d %-10s\n", + rfapi_ntop(pfx_mac.family, &pfx_mac.u.prefix, + buf_pfx, BUFSIZ), + mon_eth->logical_net_id, buf_remain); + } + } + } + + if (queries_total) { + fp(out, "\n"); + fp(out, "Displayed %d out of %d total queries\n", + queries_displayed, queries_total); + } + return CMD_SUCCESS; } -static int -rfapiPrintRemoteRegBi ( - struct bgp *bgp, - void *stream, - struct route_node *rn, - struct bgp_info *bi) +static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream, + struct route_node *rn, struct bgp_info *bi) { - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; - struct prefix pfx_un; - struct prefix pfx_vn; - uint8_t cost; - uint32_t lifetime; - bgp_encap_types tun_type; - - char buf_pfx[BUFSIZ]; - char buf_ntop[BUFSIZ]; - char buf_un[BUFSIZ]; - char buf_vn[BUFSIZ]; - char buf_lifetime[BUFSIZ]; - int nlines = 0; - - if (!stream) - return 0; /* for debug log, print into buf & call output once */ - - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return 0; - - /* - * Prefix - */ - buf_pfx[0] = 0; - snprintf (buf_pfx, BUFSIZ, "%s/%d", - rfapi_ntop (rn->p.family, &rn->p.u.prefix, buf_ntop, BUFSIZ), - rn->p.prefixlen); - buf_pfx[BUFSIZ - 1] = 0; - nlines++; - - /* - * UN addr - */ - buf_un[0] = 0; - if (!rfapiGetUnAddrOfVpnBi (bi, &pfx_un)) - { - snprintf (buf_un, BUFSIZ, "%s", - inet_ntop (pfx_un.family, &pfx_un.u.prefix, buf_ntop, - BUFSIZ)); - } - - rfapiGetTunnelType(bi->attr,&tun_type); - /* - * VN addr - */ - buf_vn[0] = 0; - rfapiNexthop2Prefix (bi->attr, &pfx_vn); - if (tun_type == BGP_ENCAP_TYPE_MPLS) - { - /* MPLS carries un in nrli next hop (same as vn for IP tunnels) */ - snprintf (buf_un, BUFSIZ, "%s", - inet_ntop (pfx_vn.family, &pfx_vn.u.prefix, buf_ntop, BUFSIZ)); - if (bi->extra) - { - u_int32_t l = decode_label (&bi->extra->label); - snprintf (buf_vn, BUFSIZ, "Label: %d", l); - } - else /* should never happen */ - { - snprintf (buf_vn, BUFSIZ, "Label: N/A"); - } - } - else - { - snprintf (buf_vn, BUFSIZ, "%s", - inet_ntop (pfx_vn.family, &pfx_vn.u.prefix, buf_ntop, BUFSIZ)); - } - buf_vn[BUFSIZ - 1] = 0; - buf_un[BUFSIZ - 1] = 0; - - /* - * Cost is encoded in local_pref as (255-cost) - * See rfapi_import.c'rfapiRouteInfo2NextHopEntry() for conversion - * back to cost. - */ - if (bi->attr) - { - uint32_t local_pref; - if (bi->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) - local_pref = bi->attr->local_pref; - else - local_pref = 0; - cost = (local_pref > 255) ? 0 : 255 - local_pref; - } - else - { - cost = 0; - } - - fp (out, "%-20s ", buf_pfx); - fp (out, "%-15s ", buf_vn); - fp (out, "%-15s ", buf_un); - fp (out, "%-4d ", cost); - - /* Lifetime */ - /* NB rfapiGetVncLifetime sets infinite value when returning !0 */ - if (rfapiGetVncLifetime (bi->attr, &lifetime) || - (lifetime == RFAPI_INFINITE_LIFETIME)) - { - - fp (out, "%-10s ", "infinite"); - } - else - { - time_t t_lifetime = lifetime; - rfapiFormatSeconds (t_lifetime, buf_lifetime, BUFSIZ); - fp (out, "%-10s ", buf_lifetime); - } - - if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED) && - bi->extra && bi->extra->vnc.import.timer) - { - - uint32_t remaining; - time_t age; - char buf_age[BUFSIZ]; - - struct thread *t = (struct thread *) bi->extra->vnc.import.timer; - remaining = thread_timer_remain_second (t); + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; + struct prefix pfx_un; + struct prefix pfx_vn; + uint8_t cost; + uint32_t lifetime; + bgp_encap_types tun_type; + + char buf_pfx[BUFSIZ]; + char buf_ntop[BUFSIZ]; + char buf_un[BUFSIZ]; + char buf_vn[BUFSIZ]; + char buf_lifetime[BUFSIZ]; + int nlines = 0; + + if (!stream) + return 0; /* for debug log, print into buf & call output once */ + + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return 0; + + /* + * Prefix + */ + buf_pfx[0] = 0; + snprintf(buf_pfx, BUFSIZ, "%s/%d", + rfapi_ntop(rn->p.family, &rn->p.u.prefix, buf_ntop, BUFSIZ), + rn->p.prefixlen); + buf_pfx[BUFSIZ - 1] = 0; + nlines++; + + /* + * UN addr + */ + buf_un[0] = 0; + if (!rfapiGetUnAddrOfVpnBi(bi, &pfx_un)) { + snprintf(buf_un, BUFSIZ, "%s", + inet_ntop(pfx_un.family, &pfx_un.u.prefix, buf_ntop, + BUFSIZ)); + } + + rfapiGetTunnelType(bi->attr, &tun_type); + /* + * VN addr + */ + buf_vn[0] = 0; + rfapiNexthop2Prefix(bi->attr, &pfx_vn); + if (tun_type == BGP_ENCAP_TYPE_MPLS) { + /* MPLS carries un in nrli next hop (same as vn for IP tunnels) + */ + snprintf(buf_un, BUFSIZ, "%s", + inet_ntop(pfx_vn.family, &pfx_vn.u.prefix, buf_ntop, + BUFSIZ)); + if (bi->extra) { + u_int32_t l = decode_label(&bi->extra->label); + snprintf(buf_vn, BUFSIZ, "Label: %d", l); + } else /* should never happen */ + { + snprintf(buf_vn, BUFSIZ, "Label: N/A"); + } + } else { + snprintf(buf_vn, BUFSIZ, "%s", + inet_ntop(pfx_vn.family, &pfx_vn.u.prefix, buf_ntop, + BUFSIZ)); + } + buf_vn[BUFSIZ - 1] = 0; + buf_un[BUFSIZ - 1] = 0; + + /* + * Cost is encoded in local_pref as (255-cost) + * See rfapi_import.c'rfapiRouteInfo2NextHopEntry() for conversion + * back to cost. + */ + if (bi->attr) { + uint32_t local_pref; + if (bi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) + local_pref = bi->attr->local_pref; + else + local_pref = 0; + cost = (local_pref > 255) ? 0 : 255 - local_pref; + } else { + cost = 0; + } + + fp(out, "%-20s ", buf_pfx); + fp(out, "%-15s ", buf_vn); + fp(out, "%-15s ", buf_un); + fp(out, "%-4d ", cost); + + /* Lifetime */ + /* NB rfapiGetVncLifetime sets infinite value when returning !0 */ + if (rfapiGetVncLifetime(bi->attr, &lifetime) + || (lifetime == RFAPI_INFINITE_LIFETIME)) { + + fp(out, "%-10s ", "infinite"); + } else { + time_t t_lifetime = lifetime; + rfapiFormatSeconds(t_lifetime, buf_lifetime, BUFSIZ); + fp(out, "%-10s ", buf_lifetime); + } + + if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED) && bi->extra + && bi->extra->vnc.import.timer) { + + uint32_t remaining; + time_t age; + char buf_age[BUFSIZ]; + + struct thread *t = (struct thread *)bi->extra->vnc.import.timer; + remaining = thread_timer_remain_second(t); #if RFAPI_REGISTRATIONS_REPORT_AGE - /* - * Calculate when the timer started. Doing so here saves - * us a timestamp field in "struct bgp_info". - * - * See rfapi_import.c'rfapiBiStartWithdrawTimer() for the - * original calculation. - */ - age = rfapiGetHolddownFromLifetime (lifetime, factor) - remaining; + /* + * Calculate when the timer started. Doing so here saves + * us a timestamp field in "struct bgp_info". + * + * See rfapi_import.c'rfapiBiStartWithdrawTimer() for the + * original calculation. + */ + age = rfapiGetHolddownFromLifetime(lifetime, factor) + - remaining; #else /* report remaining time */ - age = remaining; + age = remaining; #endif - rfapiFormatSeconds (age, buf_age, BUFSIZ); - - fp (out, "%-10s ", buf_age); - - } - else if (RFAPI_LOCAL_BI (bi)) - { - - char buf_age[BUFSIZ]; - - if (bi && bi->extra && bi->extra->vnc.import.create_time) - { - rfapiFormatAge (bi->extra->vnc.import.create_time, buf_age, BUFSIZ); - } - else - { - buf_age[0] = '?'; - buf_age[1] = 0; - } - fp (out, "%-10s ", buf_age); - } - fp (out, "%s", HVTYNL); - - if (rn->p.family == AF_ETHERNET) - { - /* - * If there is a corresponding IP address && != VN address, - * print that on the next line - */ - - if (bi && bi->extra && bi->extra->vnc.import.aux_prefix.family) - { - const char *sp; - - sp = rfapi_ntop (bi->extra->vnc.import.aux_prefix.family, - &bi->extra->vnc.import.aux_prefix.u.prefix, - buf_ntop, BUFSIZ); - buf_ntop[BUFSIZ - 1] = 0; - - if (sp && strcmp (buf_vn, sp) != 0) - { - fp (out, " IP: %s", sp); - if (nlines == 1) - nlines++; - } - } - } - if (tun_type != BGP_ENCAP_TYPE_MPLS && bi->extra) - { - u_int32_t l = decode_label (&bi->extra->label); - if (!MPLS_LABEL_IS_NULL (l)) - { - fp (out, " Label: %d", l); - if (nlines == 1) - nlines++; - } - } - if (nlines > 1) - fp (out, "%s", HVTYNL); - - return 1; + rfapiFormatSeconds(age, buf_age, BUFSIZ); + + fp(out, "%-10s ", buf_age); + + } else if (RFAPI_LOCAL_BI(bi)) { + + char buf_age[BUFSIZ]; + + if (bi && bi->extra && bi->extra->vnc.import.create_time) { + rfapiFormatAge(bi->extra->vnc.import.create_time, + buf_age, BUFSIZ); + } else { + buf_age[0] = '?'; + buf_age[1] = 0; + } + fp(out, "%-10s ", buf_age); + } + fp(out, "%s", HVTYNL); + + if (rn->p.family == AF_ETHERNET) { + /* + * If there is a corresponding IP address && != VN address, + * print that on the next line + */ + + if (bi && bi->extra + && bi->extra->vnc.import.aux_prefix.family) { + const char *sp; + + sp = rfapi_ntop( + bi->extra->vnc.import.aux_prefix.family, + &bi->extra->vnc.import.aux_prefix.u.prefix, + buf_ntop, BUFSIZ); + buf_ntop[BUFSIZ - 1] = 0; + + if (sp && strcmp(buf_vn, sp) != 0) { + fp(out, " IP: %s", sp); + if (nlines == 1) + nlines++; + } + } + } + if (tun_type != BGP_ENCAP_TYPE_MPLS && bi->extra) { + u_int32_t l = decode_label(&bi->extra->label); + if (!MPLS_LABEL_IS_NULL(l)) { + fp(out, " Label: %d", l); + if (nlines == 1) + nlines++; + } + } + if (nlines > 1) + fp(out, "%s", HVTYNL); + + return 1; } -static int -rfapiShowRemoteRegistrationsIt ( - struct bgp *bgp, - void *stream, - struct rfapi_import_table *it, - struct prefix *prefix_only, - int show_expiring, /* either/or */ - int show_local, - int show_remote, - int show_imported, /* either/or */ - uint32_t *pLni) /* AFI_L2VPN only */ +static int rfapiShowRemoteRegistrationsIt(struct bgp *bgp, void *stream, + struct rfapi_import_table *it, + struct prefix *prefix_only, + int show_expiring, /* either/or */ + int show_local, int show_remote, + int show_imported, /* either/or */ + uint32_t *pLni) /* AFI_L2VPN only */ { - afi_t afi; - int printed_rtlist_hdr = 0; - - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; - int total = 0; - int printed = 0; - - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return printed; - - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - - struct route_node *rn; - - if (!it->imported_vpn[afi]) - continue; - - for (rn = route_top (it->imported_vpn[afi]); rn; rn = route_next (rn)) - { - - struct bgp_info *bi; - int count_only; - - /* allow for wider or more narrow mask from user */ - if (prefix_only && - !prefix_match (prefix_only, &rn->p) && - !prefix_match (&rn->p, prefix_only)) - count_only = 1; - else - count_only = 0; - - for (bi = rn->info; bi; bi = bi->next) - { - - if (!show_local && RFAPI_LOCAL_BI (bi)) - { - - /* local route from RFP */ - continue; - } - - if (!show_remote && !RFAPI_LOCAL_BI (bi)) - { - - /* remote route */ - continue; - } - - if (show_expiring && !CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)) - continue; - - if (!show_expiring && CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)) - continue; - - if (bi->type == ZEBRA_ROUTE_BGP_DIRECT || - bi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT) - { - if (!show_imported) - continue; - } - else - { - if (show_imported) - continue; - } - - total++; - if (count_only == 1) - continue; - if (!printed_rtlist_hdr) - { - const char *agetype = ""; - char *s; - const char *type = ""; - if (show_imported) - { - type = "Imported"; - } - else - { - if (show_expiring) - { - type = "Holddown"; - } - else - { - if (RFAPI_LOCAL_BI (bi)) - { - type = "Local"; - } - else - { - type = "Remote"; - } - } - } - - s = ecommunity_ecom2str (it->rt_import_list, - ECOMMUNITY_FORMAT_ROUTE_MAP, 0); - - if (pLni) - { - fp (out, "%s[%s] L2VPN Network 0x%x (%u) RT={%s}", - HVTYNL, type, *pLni, (*pLni & 0xfff), s); - } - else - { - fp (out, "%s[%s] Prefix RT={%s}", - HVTYNL, type, s); - } - XFREE (MTYPE_ECOMMUNITY_STR, s); - - if (it->rfg && it->rfg->name) - { - fp (out, " %s \"%s\"", - (it->rfg->type == RFAPI_GROUP_CFG_VRF ? - "VRF" : "NVE group"), - it->rfg->name); - } - fp (out, "%s", HVTYNL); - if (show_expiring) - { + afi_t afi; + int printed_rtlist_hdr = 0; + + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; + int total = 0; + int printed = 0; + + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return printed; + + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + + struct route_node *rn; + + if (!it->imported_vpn[afi]) + continue; + + for (rn = route_top(it->imported_vpn[afi]); rn; + rn = route_next(rn)) { + + struct bgp_info *bi; + int count_only; + + /* allow for wider or more narrow mask from user */ + if (prefix_only && !prefix_match(prefix_only, &rn->p) + && !prefix_match(&rn->p, prefix_only)) + count_only = 1; + else + count_only = 0; + + for (bi = rn->info; bi; bi = bi->next) { + + if (!show_local && RFAPI_LOCAL_BI(bi)) { + + /* local route from RFP */ + continue; + } + + if (!show_remote && !RFAPI_LOCAL_BI(bi)) { + + /* remote route */ + continue; + } + + if (show_expiring + && !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + continue; + + if (!show_expiring + && CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + continue; + + if (bi->type == ZEBRA_ROUTE_BGP_DIRECT + || bi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT) { + if (!show_imported) + continue; + } else { + if (show_imported) + continue; + } + + total++; + if (count_only == 1) + continue; + if (!printed_rtlist_hdr) { + const char *agetype = ""; + char *s; + const char *type = ""; + if (show_imported) { + type = "Imported"; + } else { + if (show_expiring) { + type = "Holddown"; + } else { + if (RFAPI_LOCAL_BI( + bi)) { + type = "Local"; + } else { + type = "Remote"; + } + } + } + + s = ecommunity_ecom2str( + it->rt_import_list, + ECOMMUNITY_FORMAT_ROUTE_MAP, 0); + + if (pLni) { + fp(out, + "%s[%s] L2VPN Network 0x%x (%u) RT={%s}", + HVTYNL, type, *pLni, + (*pLni & 0xfff), s); + } else { + fp(out, "%s[%s] Prefix RT={%s}", + HVTYNL, type, s); + } + XFREE(MTYPE_ECOMMUNITY_STR, s); + + if (it->rfg && it->rfg->name) { + fp(out, " %s \"%s\"", + (it->rfg->type == RFAPI_GROUP_CFG_VRF + ? "VRF" + : "NVE group"), + it->rfg->name); + } + fp(out, "%s", HVTYNL); + if (show_expiring) { #if RFAPI_REGISTRATIONS_REPORT_AGE - agetype = "Age"; + agetype = "Age"; #else - agetype = "Remaining"; + agetype = "Remaining"; #endif - } - else if (show_local) - { - agetype = "Age"; - } - - printed_rtlist_hdr = 1; - - fp (out, "%-20s %-15s %-15s %4s %-10s %-10s%s", - (pLni ? "L2 Address/IP" : "Prefix"), - "VN Address", "UN Address", "Cost", - "Lifetime", agetype, HVTYNL); - } - printed += rfapiPrintRemoteRegBi (bgp, stream, rn, bi); - } - } - } - - if (printed > 0) - { - - const char *type = "prefixes"; - - if (show_imported) - { - type = "imported prefixes"; - } - else - { - if (show_expiring) - { - type = "prefixes in holddown"; - } - else - { - if (show_local && !show_remote) - { - type = "locally registered prefixes"; - } - else if (!show_local && show_remote) - { - type = "remotely registered prefixes"; - } - } - } - - fp (out, "Displayed %d out of %d %s%s", - printed, total, type, HVTYNL); + } else if (show_local) { + agetype = "Age"; + } + + printed_rtlist_hdr = 1; + + fp(out, + "%-20s %-15s %-15s %4s %-10s %-10s%s", + (pLni ? "L2 Address/IP" : "Prefix"), + "VN Address", "UN Address", "Cost", + "Lifetime", agetype, HVTYNL); + } + printed += rfapiPrintRemoteRegBi(bgp, stream, + rn, bi); + } + } + } + + if (printed > 0) { + + const char *type = "prefixes"; + + if (show_imported) { + type = "imported prefixes"; + } else { + if (show_expiring) { + type = "prefixes in holddown"; + } else { + if (show_local && !show_remote) { + type = "locally registered prefixes"; + } else if (!show_local && show_remote) { + type = "remotely registered prefixes"; + } + } + } + + fp(out, "Displayed %d out of %d %s%s", printed, total, type, + HVTYNL); #if DEBUG_SHOW_EXTRA - fp(out, "IT table above: it=%p%s", it, HVTYNL); + fp(out, "IT table above: it=%p%s", it, HVTYNL); #endif - } - return printed; + } + return printed; } - /* * rfapiShowRemoteRegistrations * @@ -1521,70 +1370,56 @@ rfapiShowRemoteRegistrationsIt ( * is mean to produce the "remote" portion of the output * of "show vnc registrations". */ -int -rfapiShowRemoteRegistrations ( - void *stream, - struct prefix *prefix_only, - int show_expiring, - int show_local, - int show_remote, - int show_imported) +int rfapiShowRemoteRegistrations(void *stream, struct prefix *prefix_only, + int show_expiring, int show_local, + int show_remote, int show_imported) { - struct bgp *bgp; - struct rfapi *h; - struct rfapi_import_table *it; - int printed = 0; - - bgp = bgp_get_default (); - if (!bgp) - { - return printed; - } - - h = bgp->rfapi; - if (!h) - { - return printed; - } - - for (it = h->imports; it; it = it->next) - { - printed += - rfapiShowRemoteRegistrationsIt (bgp, stream, it, prefix_only, - show_expiring, show_local, - show_remote, show_imported, NULL); - } - - if (h->import_mac) - { - void *cursor = NULL; - int rc; - uintptr_t lni_as_ptr; - uint32_t lni; - uint32_t *pLni; - - for (rc = - skiplist_next (h->import_mac, (void **) &lni_as_ptr, (void **) &it, - &cursor); !rc; - rc = - skiplist_next (h->import_mac, (void **) &lni_as_ptr, (void **) &it, - &cursor)) - { - pLni = NULL; - if ((lni_as_ptr & 0xffffffff) == lni_as_ptr) - { - lni = (uint32_t) (lni_as_ptr & 0xffffffff); - pLni = &lni; - } - - printed += - rfapiShowRemoteRegistrationsIt (bgp, stream, it, prefix_only, - show_expiring, show_local, - show_remote, show_imported, pLni); - } - } - - return printed; + struct bgp *bgp; + struct rfapi *h; + struct rfapi_import_table *it; + int printed = 0; + + bgp = bgp_get_default(); + if (!bgp) { + return printed; + } + + h = bgp->rfapi; + if (!h) { + return printed; + } + + for (it = h->imports; it; it = it->next) { + printed += rfapiShowRemoteRegistrationsIt( + bgp, stream, it, prefix_only, show_expiring, show_local, + show_remote, show_imported, NULL); + } + + if (h->import_mac) { + void *cursor = NULL; + int rc; + uintptr_t lni_as_ptr; + uint32_t lni; + uint32_t *pLni; + + for (rc = skiplist_next(h->import_mac, (void **)&lni_as_ptr, + (void **)&it, &cursor); + !rc; + rc = skiplist_next(h->import_mac, (void **)&lni_as_ptr, + (void **)&it, &cursor)) { + pLni = NULL; + if ((lni_as_ptr & 0xffffffff) == lni_as_ptr) { + lni = (uint32_t)(lni_as_ptr & 0xffffffff); + pLni = &lni; + } + + printed += rfapiShowRemoteRegistrationsIt( + bgp, stream, it, prefix_only, show_expiring, + show_local, show_remote, show_imported, pLni); + } + } + + return printed; } /*------------------------------------------ @@ -1592,7 +1427,7 @@ rfapiShowRemoteRegistrations ( * * UI helper: generate string from rfapi_ip_addr * - * input: + * input: * a IP v4/v6 address * * output @@ -1603,385 +1438,342 @@ rfapiShowRemoteRegistrations ( * NULL conversion failed * non-NULL pointer to buf --------------------------------------------*/ -const char * -rfapiRfapiIpAddr2Str (struct rfapi_ip_addr *a, char *buf, int bufsize) +const char *rfapiRfapiIpAddr2Str(struct rfapi_ip_addr *a, char *buf, + int bufsize) { - const char *rc = NULL; - - switch (a->addr_family) - { - case AF_INET: - rc = inet_ntop (a->addr_family, &a->addr.v4, buf, bufsize); - break; - case AF_INET6: - rc = inet_ntop (a->addr_family, &a->addr.v6, buf, bufsize); - break; - } - return rc; + const char *rc = NULL; + + switch (a->addr_family) { + case AF_INET: + rc = inet_ntop(a->addr_family, &a->addr.v4, buf, bufsize); + break; + case AF_INET6: + rc = inet_ntop(a->addr_family, &a->addr.v6, buf, bufsize); + break; + } + return rc; } -void -rfapiPrintRfapiIpAddr (void *stream, struct rfapi_ip_addr *a) +void rfapiPrintRfapiIpAddr(void *stream, struct rfapi_ip_addr *a) { - char buf[BUFSIZ]; - const char *rc = NULL; + char buf[BUFSIZ]; + const char *rc = NULL; - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out = NULL; - const char *vty_newline; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out = NULL; + const char *vty_newline; - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; - rc = rfapiRfapiIpAddr2Str (a, buf, BUFSIZ); + rc = rfapiRfapiIpAddr2Str(a, buf, BUFSIZ); - if (rc) - fp (out, "%s", buf); + if (rc) + fp(out, "%s", buf); } -const char * -rfapiRfapiIpPrefix2Str (struct rfapi_ip_prefix *p, char *buf, int bufsize) +const char *rfapiRfapiIpPrefix2Str(struct rfapi_ip_prefix *p, char *buf, + int bufsize) { - struct rfapi_ip_addr *a = &p->prefix; - const char *rc = NULL; - - switch (a->addr_family) - { - case AF_INET: - rc = inet_ntop (a->addr_family, &a->addr.v4, buf, bufsize); - break; - case AF_INET6: - rc = inet_ntop (a->addr_family, &a->addr.v6, buf, bufsize); - break; - } - - if (rc) - { - int alen = strlen (buf); - int remaining = bufsize - alen - 1; - int slen; - - if (remaining > 0) - { - slen = snprintf (buf + alen, remaining, "/%u", p->length); - if (slen < remaining) /* see man page for snprintf(3) */ - return rc; - } - } - - return NULL; + struct rfapi_ip_addr *a = &p->prefix; + const char *rc = NULL; + + switch (a->addr_family) { + case AF_INET: + rc = inet_ntop(a->addr_family, &a->addr.v4, buf, bufsize); + break; + case AF_INET6: + rc = inet_ntop(a->addr_family, &a->addr.v6, buf, bufsize); + break; + } + + if (rc) { + int alen = strlen(buf); + int remaining = bufsize - alen - 1; + int slen; + + if (remaining > 0) { + slen = snprintf(buf + alen, remaining, "/%u", + p->length); + if (slen < remaining) /* see man page for snprintf(3) */ + return rc; + } + } + + return NULL; } -void -rfapiPrintRfapiIpPrefix (void *stream, struct rfapi_ip_prefix *p) +void rfapiPrintRfapiIpPrefix(void *stream, struct rfapi_ip_prefix *p) { - char buf[BUFSIZ]; - const char *rc; + char buf[BUFSIZ]; + const char *rc; - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out = NULL; - const char *vty_newline; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out = NULL; + const char *vty_newline; - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; - rc = rfapiRfapiIpPrefix2Str (p, buf, BUFSIZ); + rc = rfapiRfapiIpPrefix2Str(p, buf, BUFSIZ); - if (rc) - fp (out, "%s:%u", buf, p->cost); - else - fp (out, "?/?:?"); + if (rc) + fp(out, "%s:%u", buf, p->cost); + else + fp(out, "?/?:?"); } -void -rfapiPrintRd (struct vty *vty, struct prefix_rd *prd) +void rfapiPrintRd(struct vty *vty, struct prefix_rd *prd) { - char buf[BUFSIZ]; + char buf[BUFSIZ]; - buf[0] = 0; - prefix_rd2str (prd, buf, BUFSIZ); - buf[BUFSIZ - 1] = 0; - vty_out (vty, "%s", buf); + buf[0] = 0; + prefix_rd2str(prd, buf, BUFSIZ); + buf[BUFSIZ - 1] = 0; + vty_out(vty, "%s", buf); } -void -rfapiPrintAdvertisedInfo ( - struct vty *vty, - struct rfapi_descriptor *rfd, - safi_t safi, - struct prefix *p) +void rfapiPrintAdvertisedInfo(struct vty *vty, struct rfapi_descriptor *rfd, + safi_t safi, struct prefix *p) { - afi_t afi; /* of the VN address */ - struct bgp_node *bn; - struct bgp_info *bi; - uint8_t type = ZEBRA_ROUTE_BGP; - struct bgp *bgp; - int printed = 0; - struct prefix_rd prd0; - struct prefix_rd *prd; - - /* - * Find the bgp_info in the RIB corresponding to this - * prefix and rfd - */ - - afi = family2afi (p->family); - assert (afi == AFI_IP || afi == AFI_IP6); - - bgp = bgp_get_default (); /* assume 1 instance for now */ - assert (bgp); - - if (safi == SAFI_ENCAP) - { - memset (&prd0, 0, sizeof (prd0)); - prd0.family = AF_UNSPEC; - prd0.prefixlen = 64; - prd = &prd0; - } - else - { - prd = &rfd->rd; - } - bn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd); - - vty_out (vty, " bn=%p%s", bn, HVTYNL); - - for (bi = bn->info; bi; bi = bi->next) - { - if (bi->peer == rfd->peer && - bi->type == type && - bi->sub_type == BGP_ROUTE_RFP && - bi->extra && bi->extra->vnc.export.rfapi_handle == (void *) rfd) - { - - rfapiPrintBi (vty, bi); - printed = 1; - } - } - - if (!printed) - { - vty_out (vty, " --?--%s", HVTYNL); - return; - } - + afi_t afi; /* of the VN address */ + struct bgp_node *bn; + struct bgp_info *bi; + uint8_t type = ZEBRA_ROUTE_BGP; + struct bgp *bgp; + int printed = 0; + struct prefix_rd prd0; + struct prefix_rd *prd; + + /* + * Find the bgp_info in the RIB corresponding to this + * prefix and rfd + */ + + afi = family2afi(p->family); + assert(afi == AFI_IP || afi == AFI_IP6); + + bgp = bgp_get_default(); /* assume 1 instance for now */ + assert(bgp); + + if (safi == SAFI_ENCAP) { + memset(&prd0, 0, sizeof(prd0)); + prd0.family = AF_UNSPEC; + prd0.prefixlen = 64; + prd = &prd0; + } else { + prd = &rfd->rd; + } + bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd); + + vty_out(vty, " bn=%p%s", bn, HVTYNL); + + for (bi = bn->info; bi; bi = bi->next) { + if (bi->peer == rfd->peer && bi->type == type + && bi->sub_type == BGP_ROUTE_RFP && bi->extra + && bi->extra->vnc.export.rfapi_handle == (void *)rfd) { + + rfapiPrintBi(vty, bi); + printed = 1; + } + } + + if (!printed) { + vty_out(vty, " --?--%s", HVTYNL); + return; + } } -void -rfapiPrintDescriptor (struct vty *vty, struct rfapi_descriptor *rfd) +void rfapiPrintDescriptor(struct vty *vty, struct rfapi_descriptor *rfd) { - /* pHD un-addr vn-addr pCB cookie rd lifetime */ - /* RT export list */ - /* RT import list */ - /* list of advertised prefixes */ - /* dump import table */ - - char *s; - void *cursor; - int rc; - afi_t afi; - struct rfapi_adb *adb; - char buf[BUFSIZ]; - - vty_out (vty, "%-10p ", rfd); - rfapiPrintRfapiIpAddr (vty, &rfd->un_addr); - vty_out (vty, " "); - rfapiPrintRfapiIpAddr (vty, &rfd->vn_addr); - vty_out (vty, " %p %p ", rfd->response_cb, rfd->cookie); - rfapiPrintRd (vty, &rfd->rd); - vty_out (vty, " %d", rfd->response_lifetime); - vty_out (vty, " %s", (rfd->rfg ? rfd->rfg->name : "")); - vty_out (vty, "%s", HVTYNL); - - vty_out (vty, " Peer %p #%d%s", rfd->peer, rfd->peer->lock, HVTYNL); - - /* export RT list */ - if (rfd->rt_export_list) - { - s = - ecommunity_ecom2str (rfd->rt_export_list, - ECOMMUNITY_FORMAT_ROUTE_MAP, 0); - vty_out (vty, " Export %s%s", s, HVTYNL); - XFREE (MTYPE_ECOMMUNITY_STR, s); - } - else - { - vty_out (vty, " Export (nil)%s", HVTYNL); - } - - /* import RT list */ - if (rfd->import_table) - { - s = ecommunity_ecom2str (rfd->import_table->rt_import_list, - ECOMMUNITY_FORMAT_ROUTE_MAP, 0); - vty_out (vty, " Import %s%s", s, HVTYNL); - XFREE (MTYPE_ECOMMUNITY_STR, s); - } - else - { - vty_out (vty, " Import (nil)%s", HVTYNL); - } - - for (afi = AFI_IP; afi < AFI_MAX; ++afi) - { - u_char family; - - family = afi2family (afi); - if (!family) - continue; - - cursor = NULL; - for (rc = - skiplist_next (rfd->advertised.ipN_by_prefix, NULL, (void **) &adb, - &cursor); rc == 0; - rc = - skiplist_next (rfd->advertised.ipN_by_prefix, NULL, (void **) &adb, - &cursor)) - { - - /* group like family prefixes together in output */ - if (family != adb->u.s.prefix_ip.family) - continue; - - prefix2str (&adb->u.s.prefix_ip, buf, BUFSIZ); - buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */ - - vty_out (vty, " Adv Pfx: %s%s", buf, HVTYNL); - rfapiPrintAdvertisedInfo (vty, rfd, SAFI_MPLS_VPN, &adb->u.s.prefix_ip); - } - } - for (rc = - skiplist_next (rfd->advertised.ip0_by_ether, NULL, (void **) &adb, - &cursor); rc == 0; - rc = - skiplist_next (rfd->advertised.ip0_by_ether, NULL, (void **) &adb, - &cursor)) - { - - prefix2str (&adb->u.s.prefix_eth, buf, BUFSIZ); - buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */ - - vty_out (vty, " Adv Pfx: %s%s", buf, HVTYNL); - - /* TBD update the following function to print ethernet info */ - /* Also need to pass/use rd */ - rfapiPrintAdvertisedInfo (vty, rfd, SAFI_MPLS_VPN, &adb->u.s.prefix_ip); - } - vty_out (vty, "%s", HVTYNL); + /* pHD un-addr vn-addr pCB cookie rd lifetime */ + /* RT export list */ + /* RT import list */ + /* list of advertised prefixes */ + /* dump import table */ + + char *s; + void *cursor; + int rc; + afi_t afi; + struct rfapi_adb *adb; + char buf[BUFSIZ]; + + vty_out(vty, "%-10p ", rfd); + rfapiPrintRfapiIpAddr(vty, &rfd->un_addr); + vty_out(vty, " "); + rfapiPrintRfapiIpAddr(vty, &rfd->vn_addr); + vty_out(vty, " %p %p ", rfd->response_cb, rfd->cookie); + rfapiPrintRd(vty, &rfd->rd); + vty_out(vty, " %d", rfd->response_lifetime); + vty_out(vty, " %s", (rfd->rfg ? rfd->rfg->name : "")); + vty_out(vty, "%s", HVTYNL); + + vty_out(vty, " Peer %p #%d%s", rfd->peer, rfd->peer->lock, HVTYNL); + + /* export RT list */ + if (rfd->rt_export_list) { + s = ecommunity_ecom2str(rfd->rt_export_list, + ECOMMUNITY_FORMAT_ROUTE_MAP, 0); + vty_out(vty, " Export %s%s", s, HVTYNL); + XFREE(MTYPE_ECOMMUNITY_STR, s); + } else { + vty_out(vty, " Export (nil)%s", HVTYNL); + } + + /* import RT list */ + if (rfd->import_table) { + s = ecommunity_ecom2str(rfd->import_table->rt_import_list, + ECOMMUNITY_FORMAT_ROUTE_MAP, 0); + vty_out(vty, " Import %s%s", s, HVTYNL); + XFREE(MTYPE_ECOMMUNITY_STR, s); + } else { + vty_out(vty, " Import (nil)%s", HVTYNL); + } + + for (afi = AFI_IP; afi < AFI_MAX; ++afi) { + u_char family; + + family = afi2family(afi); + if (!family) + continue; + + cursor = NULL; + for (rc = skiplist_next(rfd->advertised.ipN_by_prefix, NULL, + (void **)&adb, &cursor); + rc == 0; + rc = skiplist_next(rfd->advertised.ipN_by_prefix, NULL, + (void **)&adb, &cursor)) { + + /* group like family prefixes together in output */ + if (family != adb->u.s.prefix_ip.family) + continue; + + prefix2str(&adb->u.s.prefix_ip, buf, BUFSIZ); + buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */ + + vty_out(vty, " Adv Pfx: %s%s", buf, HVTYNL); + rfapiPrintAdvertisedInfo(vty, rfd, SAFI_MPLS_VPN, + &adb->u.s.prefix_ip); + } + } + for (rc = skiplist_next(rfd->advertised.ip0_by_ether, NULL, + (void **)&adb, &cursor); + rc == 0; rc = skiplist_next(rfd->advertised.ip0_by_ether, NULL, + (void **)&adb, &cursor)) { + + prefix2str(&adb->u.s.prefix_eth, buf, BUFSIZ); + buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */ + + vty_out(vty, " Adv Pfx: %s%s", buf, HVTYNL); + + /* TBD update the following function to print ethernet info */ + /* Also need to pass/use rd */ + rfapiPrintAdvertisedInfo(vty, rfd, SAFI_MPLS_VPN, + &adb->u.s.prefix_ip); + } + vty_out(vty, "%s", HVTYNL); } /* * test scripts rely on first line for each nve starting in 1st column, * leading whitespace for additional detail of that nve */ -void -rfapiPrintMatchingDescriptors (struct vty *vty, - struct prefix *vn_prefix, - struct prefix *un_prefix) +void rfapiPrintMatchingDescriptors(struct vty *vty, struct prefix *vn_prefix, + struct prefix *un_prefix) { - struct bgp *bgp; - struct rfapi *h; - struct listnode *ln; - struct rfapi_descriptor *rfd; - int printed = 0; - - bgp = bgp_get_default (); /* assume 1 instance for now */ - if (!bgp) - return; - - h = bgp->rfapi; - assert (h); - - for (ln = listhead (&h->descriptors); ln; ln = listnextnode (ln)) - { - rfd = listgetdata (ln); - - struct prefix pfx; - - if (vn_prefix) - { - assert (!rfapiRaddr2Qprefix (&rfd->vn_addr, &pfx)); - if (!prefix_match (vn_prefix, &pfx)) - continue; - } - - if (un_prefix) - { - assert (!rfapiRaddr2Qprefix (&rfd->un_addr, &pfx)); - if (!prefix_match (un_prefix, &pfx)) - continue; - } - - if (!printed) - { - /* print column header */ - vty_out (vty, - "%s %s %s %s %s %s %s %s%s", - "descriptor", "un-addr", "vn-addr", "callback", "cookie", - "RD", "lifetime", "group", HVTYNL); - } - rfapiPrintDescriptor (vty, rfd); - printed = 1; - } + struct bgp *bgp; + struct rfapi *h; + struct listnode *ln; + struct rfapi_descriptor *rfd; + int printed = 0; + + bgp = bgp_get_default(); /* assume 1 instance for now */ + if (!bgp) + return; + + h = bgp->rfapi; + assert(h); + + for (ln = listhead(&h->descriptors); ln; ln = listnextnode(ln)) { + rfd = listgetdata(ln); + + struct prefix pfx; + + if (vn_prefix) { + assert(!rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx)); + if (!prefix_match(vn_prefix, &pfx)) + continue; + } + + if (un_prefix) { + assert(!rfapiRaddr2Qprefix(&rfd->un_addr, &pfx)); + if (!prefix_match(un_prefix, &pfx)) + continue; + } + + if (!printed) { + /* print column header */ + vty_out(vty, "%s %s %s %s %s %s %s %s%s", "descriptor", + "un-addr", "vn-addr", "callback", "cookie", + "RD", "lifetime", "group", HVTYNL); + } + rfapiPrintDescriptor(vty, rfd); + printed = 1; + } } /* * Parse an address and put into a struct prefix */ -int -rfapiCliGetPrefixAddr (struct vty *vty, const char *str, struct prefix *p) +int rfapiCliGetPrefixAddr(struct vty *vty, const char *str, struct prefix *p) { - if (!str2prefix (str, p)) - { - vty_out (vty, "Malformed address \"%s\"%s", str, HVTYNL); - return CMD_WARNING; - } - switch (p->family) - { - case AF_INET: - if (p->prefixlen != 32) - { - vty_out (vty, "Not a host address: \"%s\"%s", str, HVTYNL); - return CMD_WARNING; - } - break; - case AF_INET6: - if (p->prefixlen != 128) - { - vty_out (vty, "Not a host address: \"%s\"%s", str, HVTYNL); - return CMD_WARNING; - } - break; - default: - vty_out (vty, "Invalid address \"%s\"%s", str, HVTYNL); - return CMD_WARNING; - } - return 0; + if (!str2prefix(str, p)) { + vty_out(vty, "Malformed address \"%s\"%s", str, HVTYNL); + return CMD_WARNING; + } + switch (p->family) { + case AF_INET: + if (p->prefixlen != 32) { + vty_out(vty, "Not a host address: \"%s\"%s", str, + HVTYNL); + return CMD_WARNING; + } + break; + case AF_INET6: + if (p->prefixlen != 128) { + vty_out(vty, "Not a host address: \"%s\"%s", str, + HVTYNL); + return CMD_WARNING; + } + break; + default: + vty_out(vty, "Invalid address \"%s\"%s", str, HVTYNL); + return CMD_WARNING; + } + return 0; } -int -rfapiCliGetRfapiIpAddr ( - struct vty *vty, - const char *str, - struct rfapi_ip_addr *hai) +int rfapiCliGetRfapiIpAddr(struct vty *vty, const char *str, + struct rfapi_ip_addr *hai) { - struct prefix pfx; - int rc; + struct prefix pfx; + int rc; - rc = rfapiCliGetPrefixAddr (vty, str, &pfx); - if (rc) - return rc; + rc = rfapiCliGetPrefixAddr(vty, str, &pfx); + if (rc) + return rc; - hai->addr_family = pfx.family; - if (pfx.family == AF_INET) - hai->addr.v4 = pfx.u.prefix4; - else - hai->addr.v6 = pfx.u.prefix6; + hai->addr_family = pfx.family; + if (pfx.family == AF_INET) + hai->addr.v4 = pfx.u.prefix4; + else + hai->addr.v6 = pfx.u.prefix6; - return 0; + return 0; } /* @@ -1989,137 +1781,125 @@ rfapiCliGetRfapiIpAddr ( * with a stream pointing to a vty, the user will have to type something * before the callback output shows up */ -void -rfapiPrintNhl (void *stream, struct rfapi_next_hop_entry *next_hops) +void rfapiPrintNhl(void *stream, struct rfapi_next_hop_entry *next_hops) { - struct rfapi_next_hop_entry *nh; - int count; + struct rfapi_next_hop_entry *nh; + int count; - int (*fp) (void *, const char *, ...); - struct vty *vty; - void *out; - const char *vty_newline; + int (*fp)(void *, const char *, ...); + struct vty *vty; + void *out; + const char *vty_newline; #define REMAIN (BUFSIZ - (p-line)) #define INCP {p += (r > REMAIN)? REMAIN: r;} - - if (rfapiStream2Vty (stream, &fp, &vty, &out, &vty_newline) == 0) - return; - - for (nh = next_hops, count = 1; nh; nh = nh->next, ++count) - { - - char line[BUFSIZ]; - char *p = line; - int r; - - r = snprintf (p, REMAIN, "%3d pfx=", count); - INCP; - - if (rfapiRfapiIpPrefix2Str (&nh->prefix, p, REMAIN)) - { - /* it fit, so count length */ - r = strlen (p); - } - else - { - /* didn't fit */ - goto truncate; - } - INCP; - - r = snprintf (p, REMAIN, ", un="); - INCP; - - if (rfapiRfapiIpAddr2Str (&nh->un_address, p, REMAIN)) - { - /* it fit, so count length */ - r = strlen (p); - } - else - { - /* didn't fit */ - goto truncate; - } - INCP; - - r = snprintf (p, REMAIN, ", vn="); - INCP; - - if (rfapiRfapiIpAddr2Str (&nh->vn_address, p, REMAIN)) - { - /* it fit, so count length */ - r = strlen (p); - } - else - { - /* didn't fit */ - goto truncate; - } - INCP; - - truncate: - line[BUFSIZ - 1] = 0; - fp (out, "%s%s", line, HVTYNL); - - /* - * options - */ - if (nh->vn_options) - { - struct rfapi_vn_option *vo; - char offset[] = " "; - - for (vo = nh->vn_options; vo; vo = vo->next) - { - char pbuf[100]; - - switch (vo->type) - { - case RFAPI_VN_OPTION_TYPE_L2ADDR: - rfapiEthAddr2Str (&vo->v.l2addr.macaddr, pbuf, - sizeof (pbuf)); - fp (out, "%sL2 %s LBL=0x%06x NETID=0x%06x NVEID=%d%s", - offset, pbuf, (vo->v.l2addr.label & 0x00ffffff), - (vo->v.l2addr.logical_net_id & 0x00ffffff), - vo->v.l2addr.local_nve_id, HVTYNL); - break; - - case RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP: - prefix2str (&vo->v.local_nexthop.addr, pbuf, sizeof (pbuf)); - fp (out, "%sLNH %s cost=%d%s", - offset, pbuf, vo->v.local_nexthop.cost, HVTYNL); - break; - - default: - fp (out, "%svn option type %d (unknown)%s", - offset, vo->type, HVTYNL); - break; - } - } - } - if (nh->un_options) - { - struct rfapi_un_option *uo; - char offset[] = " "; - - for (uo = nh->un_options; uo; uo = uo->next) - { - switch (uo->type) - { - case RFAPI_UN_OPTION_TYPE_TUNNELTYPE: - rfapi_print_tunneltype_option (stream, 8, &uo->v.tunnel); - break; - default: - fp (out, "%sUN Option type %d%s", - offset, uo->type, vty_newline); - break; - } - - } - } - } + if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) + return; + + for (nh = next_hops, count = 1; nh; nh = nh->next, ++count) { + + char line[BUFSIZ]; + char *p = line; + int r; + + r = snprintf(p, REMAIN, "%3d pfx=", count); + INCP; + + if (rfapiRfapiIpPrefix2Str(&nh->prefix, p, REMAIN)) { + /* it fit, so count length */ + r = strlen(p); + } else { + /* didn't fit */ + goto truncate; + } + INCP; + + r = snprintf(p, REMAIN, ", un="); + INCP; + + if (rfapiRfapiIpAddr2Str(&nh->un_address, p, REMAIN)) { + /* it fit, so count length */ + r = strlen(p); + } else { + /* didn't fit */ + goto truncate; + } + INCP; + + r = snprintf(p, REMAIN, ", vn="); + INCP; + + if (rfapiRfapiIpAddr2Str(&nh->vn_address, p, REMAIN)) { + /* it fit, so count length */ + r = strlen(p); + } else { + /* didn't fit */ + goto truncate; + } + INCP; + + truncate: + line[BUFSIZ - 1] = 0; + fp(out, "%s%s", line, HVTYNL); + + /* + * options + */ + if (nh->vn_options) { + struct rfapi_vn_option *vo; + char offset[] = " "; + + for (vo = nh->vn_options; vo; vo = vo->next) { + char pbuf[100]; + + switch (vo->type) { + case RFAPI_VN_OPTION_TYPE_L2ADDR: + rfapiEthAddr2Str(&vo->v.l2addr.macaddr, + pbuf, sizeof(pbuf)); + fp(out, + "%sL2 %s LBL=0x%06x NETID=0x%06x NVEID=%d%s", + offset, pbuf, + (vo->v.l2addr.label & 0x00ffffff), + (vo->v.l2addr.logical_net_id + & 0x00ffffff), + vo->v.l2addr.local_nve_id, HVTYNL); + break; + + case RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP: + prefix2str(&vo->v.local_nexthop.addr, + pbuf, sizeof(pbuf)); + fp(out, "%sLNH %s cost=%d%s", offset, + pbuf, vo->v.local_nexthop.cost, + HVTYNL); + break; + + default: + fp(out, + "%svn option type %d (unknown)%s", + offset, vo->type, HVTYNL); + break; + } + } + } + if (nh->un_options) { + struct rfapi_un_option *uo; + char offset[] = " "; + + for (uo = nh->un_options; uo; uo = uo->next) { + switch (uo->type) { + case RFAPI_UN_OPTION_TYPE_TUNNELTYPE: + rfapi_print_tunneltype_option( + stream, 8, &uo->v.tunnel); + break; + default: + fp(out, "%sUN Option type %d%s", offset, + uo->type, vty_newline); + break; + } + } + } + } } /*********************************************************************** @@ -2129,397 +1909,350 @@ rfapiPrintNhl (void *stream, struct rfapi_next_hop_entry *next_hops) /* * Add another nexthop to the NHL */ -static void -rfapiAddDeleteLocalRfpPrefix ( - struct rfapi_ip_addr *un_addr, - struct rfapi_ip_addr *vn_addr, - struct rfapi_ip_prefix *rprefix, - int is_add, - uint32_t lifetime, /* add only */ - struct rfapi_vn_option *vn_options, - struct rfapi_next_hop_entry **head, - struct rfapi_next_hop_entry **tail) +static void rfapiAddDeleteLocalRfpPrefix(struct rfapi_ip_addr *un_addr, + struct rfapi_ip_addr *vn_addr, + struct rfapi_ip_prefix *rprefix, + int is_add, + uint32_t lifetime, /* add only */ + struct rfapi_vn_option *vn_options, + struct rfapi_next_hop_entry **head, + struct rfapi_next_hop_entry **tail) { - struct rfapi_next_hop_entry *new; - - /* - * construct NHL - */ - - new = XCALLOC (MTYPE_RFAPI_NEXTHOP, sizeof (struct rfapi_next_hop_entry)); - new->prefix = *rprefix; - new->un_address = *un_addr; - new->vn_address = *vn_addr; - - new->vn_options = vn_options; - if (is_add) - { - new->lifetime = lifetime; - } - else - { - new->lifetime = RFAPI_REMOVE_RESPONSE_LIFETIME; - } - - if (*tail) - (*tail)->next = new; - *tail = new; - if (!*head) - { - *head = new; - } + struct rfapi_next_hop_entry *new; + + /* + * construct NHL + */ + + new = XCALLOC(MTYPE_RFAPI_NEXTHOP, sizeof(struct rfapi_next_hop_entry)); + new->prefix = *rprefix; + new->un_address = *un_addr; + new->vn_address = *vn_addr; + + new->vn_options = vn_options; + if (is_add) { + new->lifetime = lifetime; + } else { + new->lifetime = RFAPI_REMOVE_RESPONSE_LIFETIME; + } + + if (*tail) + (*tail)->next = new; + *tail = new; + if (!*head) { + *head = new; + } } static int -register_add ( - struct vty *vty, - struct cmd_token *carg_prefix, - struct cmd_token *carg_vn, - struct cmd_token *carg_un, - struct cmd_token *carg_cost, /* optional */ - struct cmd_token *carg_lifetime, /* optional */ - struct cmd_token *carg_macaddr, /* optional */ - struct cmd_token *carg_vni, /* mac present=>mandatory Virtual Network ID */ - int argc, - struct cmd_token **argv) +register_add(struct vty *vty, struct cmd_token *carg_prefix, + struct cmd_token *carg_vn, struct cmd_token *carg_un, + struct cmd_token *carg_cost, /* optional */ + struct cmd_token *carg_lifetime, /* optional */ + struct cmd_token *carg_macaddr, /* optional */ + struct cmd_token + *carg_vni, /* mac present=>mandatory Virtual Network ID */ + int argc, struct cmd_token **argv) { - const char *arg_prefix = carg_prefix ? carg_prefix->arg : NULL; - const char *arg_vn = carg_vn ? carg_vn->arg : NULL; - const char *arg_un = carg_un ? carg_un->arg : NULL; - const char *arg_cost = carg_cost ? carg_cost->arg : NULL; - const char *arg_lifetime = carg_lifetime ? carg_lifetime->arg : NULL; - const char *arg_macaddr = carg_macaddr ? carg_macaddr->arg : NULL; - const char *arg_vni = carg_vni ? carg_vni->arg : NULL; - struct rfapi_ip_addr vn_address; - struct rfapi_ip_addr un_address; - struct prefix pfx; - struct rfapi_ip_prefix rpfx; - uint32_t cost; - uint32_t lnh_cost; - uint32_t lifetime; - rfapi_handle rfd; - struct rfapi_vn_option optary[10]; /* XXX must be big enough */ - struct rfapi_vn_option *opt = NULL; - int opt_next = 0; - - int rc = CMD_WARNING_CONFIG_FAILED; - char *endptr; - struct bgp *bgp; - struct rfapi *h; - struct rfapi_cfg *rfapi_cfg; - - const char *arg_lnh = NULL; - const char *arg_lnh_cost = NULL; - - bgp = bgp_get_default (); /* assume 1 instance for now */ - if (!bgp) - { - if (vty) - vty_out (vty, "BGP not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - h = bgp->rfapi; - rfapi_cfg = bgp->rfapi_cfg; - if (!h || !rfapi_cfg) - { - if (vty) - vty_out (vty, "RFAPI not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - for (; argc; --argc, ++argv) - { - if (strmatch(argv[0]->text, "local-next-hop")) - { - if (arg_lnh) - { - vty_out (vty,"local-next-hop specified more than once\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (argc <= 1) - { - vty_out (vty,"Missing parameter for local-next-hop\n"); - return CMD_WARNING_CONFIG_FAILED; - } - ++argv, --argc; - arg_lnh = argv[0]->arg; - } - if (strmatch(argv[0]->text, "local-cost")) - { - if (arg_lnh_cost) - { - vty_out (vty,"local-cost specified more than once\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (argc <= 1) - { - vty_out (vty,"Missing parameter for local-cost\n"); - return CMD_WARNING_CONFIG_FAILED; - } - ++argv, --argc; - arg_lnh_cost = argv[0]->arg; - } - } - - if ((rc = rfapiCliGetRfapiIpAddr (vty, arg_vn, &vn_address))) - goto fail; - if ((rc = rfapiCliGetRfapiIpAddr (vty, arg_un, &un_address))) - goto fail; - - /* arg_prefix is optional if mac address is given */ - if (arg_macaddr && !arg_prefix) - { - /* - * fake up a 0/32 or 0/128 prefix - */ - switch (vn_address.addr_family) - { - case AF_INET: - arg_prefix = "0.0.0.0/32"; - break; - case AF_INET6: - arg_prefix = "0::0/128"; - break; - default: - vty_out (vty,"Internal error, unknown VN address family\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - } - - if (!str2prefix (arg_prefix, &pfx)) - { - vty_out (vty, "Malformed prefix \"%s\"\n",arg_prefix); - goto fail; - } - if (pfx.family != AF_INET - && pfx.family != AF_INET6) - { - vty_out (vty, "prefix \"%s\" has invalid address family\n", - arg_prefix); - goto fail; - } - - - memset (optary, 0, sizeof (optary)); - - if (arg_cost) - { - endptr = NULL; - cost = strtoul (arg_cost, &endptr, 10); - if (*endptr != '\0' || cost > 255) - { - vty_out (vty, "%% Invalid %s value\n", "cost"); - goto fail; - } - } - else - { - cost = 255; - } - - if (arg_lifetime) - { - if (!strcmp (arg_lifetime, "infinite")) - { - lifetime = RFAPI_INFINITE_LIFETIME; - } - else - { - endptr = NULL; - lifetime = strtoul (arg_lifetime, &endptr, 10); - if (*endptr != '\0') - { - vty_out (vty, "%% Invalid %s value\n","lifetime"); - goto fail; - } - } - } - else - { - lifetime = RFAPI_INFINITE_LIFETIME; /* default infinite */ - } - - if (arg_lnh_cost) - { - if (!arg_lnh) - { - vty_out (vty, - "%% %s may only be specified with local-next-hop\n", - "local-cost"); - goto fail; - } - endptr = NULL; - lnh_cost = strtoul (arg_lnh_cost, &endptr, 10); - if (*endptr != '\0' || lnh_cost > 255) - { - vty_out (vty, "%% Invalid %s value\n","local-cost"); - goto fail; - } - } - else - { - lnh_cost = 255; - } - - if (arg_lnh) - { - if (!arg_prefix) - { - vty_out (vty, "%% %s may only be specified with prefix\n", - "local-next-hop"); - goto fail; - } - if ((rc = rfapiCliGetPrefixAddr (vty, arg_lnh, - &optary[opt_next].v. - local_nexthop.addr))) - { - - goto fail; - } - - optary[opt_next].v.local_nexthop.cost = lnh_cost; - optary[opt_next].type = RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP; - - if (opt_next) - { - optary[opt_next - 1].next = optary + opt_next; - } - else - { - opt = optary; - } - ++opt_next; - } - - if (arg_vni && !arg_macaddr) - { - vty_out (vty, "%% %s may only be specified with mac address\n", - "virtual-network-identifier"); - goto fail; - } - - if (arg_macaddr) - { - if (!arg_vni) - { - vty_out (vty, - "Missing \"vni\" parameter (mandatory with mac)\n"); - return CMD_WARNING_CONFIG_FAILED; - } - optary[opt_next].v.l2addr.logical_net_id = strtoul(arg_vni, NULL, - 10); - - if ((rc = rfapiStr2EthAddr (arg_macaddr, - &optary[opt_next].v.l2addr.macaddr))) - { - vty_out (vty, "Invalid %s value\n","mac address"); - goto fail; - } - /* TBD label, NVE ID */ - - optary[opt_next].type = RFAPI_VN_OPTION_TYPE_L2ADDR; - - if (opt_next) - { - optary[opt_next - 1].next = optary + opt_next; - } - else - { - opt = optary; - } - ++opt_next; - } - - vnc_zlog_debug_verbose - ("%s: vn=%s, un=%s, prefix=%s, cost=%s, lifetime=%s, lnh=%s", - __func__, arg_vn, arg_un, arg_prefix, - (arg_cost ? arg_cost : "NULL"), - (arg_lifetime ? arg_lifetime : "NULL"), - (arg_lnh ? arg_lnh : "NULL")); - - rfapiQprefix2Rprefix (&pfx, &rpfx); - - rpfx.cost = cost & 255; - - /* look up rf descriptor, call open if it doesn't exist */ - rc = - rfapi_find_rfd (bgp, &vn_address, &un_address, - (struct rfapi_descriptor **) &rfd); - if (rc) - { - if (ENOENT == rc) - { - struct rfapi_un_option uo; - - /* - * flag descriptor as provisionally opened for static route - * registration so that we can fix up the other parameters - * when the real open comes along - */ - memset (&uo, 0, sizeof (uo)); - uo.type = RFAPI_UN_OPTION_TYPE_PROVISIONAL; - - rc = rfapi_open (rfapi_get_rfp_start_val_by_bgp (bgp), &vn_address, &un_address, &uo, /* flags */ - NULL, NULL, /* no userdata */ - &rfd); - if (rc) - { - vty_out (vty, "Can't open session for this NVE: %s\n", - rfapi_error_str(rc)); - rc = CMD_WARNING_CONFIG_FAILED; - goto fail; - } - } - else - { - vty_out (vty, "Can't find session for this NVE: %s\n", - rfapi_error_str(rc)); - goto fail; - } - } - - rc = - rfapi_register (rfd, &rpfx, lifetime, NULL, opt, RFAPI_REGISTER_ADD); - if (!rc) - { - struct rfapi_next_hop_entry *head = NULL; - struct rfapi_next_hop_entry *tail = NULL; - struct rfapi_vn_option *vn_opt_new; - - vnc_zlog_debug_verbose ("%s: rfapi_register succeeded, returning 0", __func__); - - if (h->rfp_methods.local_cb) - { - struct rfapi_descriptor *r = (struct rfapi_descriptor *) rfd; - vn_opt_new = rfapi_vn_options_dup (opt); - - rfapiAddDeleteLocalRfpPrefix (&r->un_addr, &r->vn_addr, &rpfx, - 1, lifetime, vn_opt_new, &head, - &tail); - if (head) - { - h->flags |= RFAPI_INCALLBACK; - (*h->rfp_methods.local_cb) (head, r->cookie); - h->flags &= ~RFAPI_INCALLBACK; - } - head = tail = NULL; - } - return 0; - } - - vnc_zlog_debug_verbose ("%s: rfapi_register failed", __func__); - vty_out (vty, "\n"); - vty_out (vty, "Registration failed.\n"); - vty_out (vty, - "Confirm that either the VN or UN address matches a configured NVE group.\n"); - return CMD_WARNING_CONFIG_FAILED; - - fail: - vnc_zlog_debug_verbose ("%s: fail, rc=%d", __func__, rc); - return rc; + const char *arg_prefix = carg_prefix ? carg_prefix->arg : NULL; + const char *arg_vn = carg_vn ? carg_vn->arg : NULL; + const char *arg_un = carg_un ? carg_un->arg : NULL; + const char *arg_cost = carg_cost ? carg_cost->arg : NULL; + const char *arg_lifetime = carg_lifetime ? carg_lifetime->arg : NULL; + const char *arg_macaddr = carg_macaddr ? carg_macaddr->arg : NULL; + const char *arg_vni = carg_vni ? carg_vni->arg : NULL; + struct rfapi_ip_addr vn_address; + struct rfapi_ip_addr un_address; + struct prefix pfx; + struct rfapi_ip_prefix rpfx; + uint32_t cost; + uint32_t lnh_cost; + uint32_t lifetime; + rfapi_handle rfd; + struct rfapi_vn_option optary[10]; /* XXX must be big enough */ + struct rfapi_vn_option *opt = NULL; + int opt_next = 0; + + int rc = CMD_WARNING_CONFIG_FAILED; + char *endptr; + struct bgp *bgp; + struct rfapi *h; + struct rfapi_cfg *rfapi_cfg; + + const char *arg_lnh = NULL; + const char *arg_lnh_cost = NULL; + + bgp = bgp_get_default(); /* assume 1 instance for now */ + if (!bgp) { + if (vty) + vty_out(vty, "BGP not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + h = bgp->rfapi; + rfapi_cfg = bgp->rfapi_cfg; + if (!h || !rfapi_cfg) { + if (vty) + vty_out(vty, "RFAPI not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + for (; argc; --argc, ++argv) { + if (strmatch(argv[0]->text, "local-next-hop")) { + if (arg_lnh) { + vty_out(vty, + "local-next-hop specified more than once\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (argc <= 1) { + vty_out(vty, + "Missing parameter for local-next-hop\n"); + return CMD_WARNING_CONFIG_FAILED; + } + ++argv, --argc; + arg_lnh = argv[0]->arg; + } + if (strmatch(argv[0]->text, "local-cost")) { + if (arg_lnh_cost) { + vty_out(vty, + "local-cost specified more than once\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (argc <= 1) { + vty_out(vty, + "Missing parameter for local-cost\n"); + return CMD_WARNING_CONFIG_FAILED; + } + ++argv, --argc; + arg_lnh_cost = argv[0]->arg; + } + } + + if ((rc = rfapiCliGetRfapiIpAddr(vty, arg_vn, &vn_address))) + goto fail; + if ((rc = rfapiCliGetRfapiIpAddr(vty, arg_un, &un_address))) + goto fail; + + /* arg_prefix is optional if mac address is given */ + if (arg_macaddr && !arg_prefix) { + /* + * fake up a 0/32 or 0/128 prefix + */ + switch (vn_address.addr_family) { + case AF_INET: + arg_prefix = "0.0.0.0/32"; + break; + case AF_INET6: + arg_prefix = "0::0/128"; + break; + default: + vty_out(vty, + "Internal error, unknown VN address family\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + if (!str2prefix(arg_prefix, &pfx)) { + vty_out(vty, "Malformed prefix \"%s\"\n", arg_prefix); + goto fail; + } + if (pfx.family != AF_INET && pfx.family != AF_INET6) { + vty_out(vty, "prefix \"%s\" has invalid address family\n", + arg_prefix); + goto fail; + } + + + memset(optary, 0, sizeof(optary)); + + if (arg_cost) { + endptr = NULL; + cost = strtoul(arg_cost, &endptr, 10); + if (*endptr != '\0' || cost > 255) { + vty_out(vty, "%% Invalid %s value\n", "cost"); + goto fail; + } + } else { + cost = 255; + } + + if (arg_lifetime) { + if (!strcmp(arg_lifetime, "infinite")) { + lifetime = RFAPI_INFINITE_LIFETIME; + } else { + endptr = NULL; + lifetime = strtoul(arg_lifetime, &endptr, 10); + if (*endptr != '\0') { + vty_out(vty, "%% Invalid %s value\n", + "lifetime"); + goto fail; + } + } + } else { + lifetime = RFAPI_INFINITE_LIFETIME; /* default infinite */ + } + + if (arg_lnh_cost) { + if (!arg_lnh) { + vty_out(vty, + "%% %s may only be specified with local-next-hop\n", + "local-cost"); + goto fail; + } + endptr = NULL; + lnh_cost = strtoul(arg_lnh_cost, &endptr, 10); + if (*endptr != '\0' || lnh_cost > 255) { + vty_out(vty, "%% Invalid %s value\n", "local-cost"); + goto fail; + } + } else { + lnh_cost = 255; + } + + if (arg_lnh) { + if (!arg_prefix) { + vty_out(vty, + "%% %s may only be specified with prefix\n", + "local-next-hop"); + goto fail; + } + if ((rc = rfapiCliGetPrefixAddr( + vty, arg_lnh, + &optary[opt_next].v.local_nexthop.addr))) { + + goto fail; + } + + optary[opt_next].v.local_nexthop.cost = lnh_cost; + optary[opt_next].type = RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP; + + if (opt_next) { + optary[opt_next - 1].next = optary + opt_next; + } else { + opt = optary; + } + ++opt_next; + } + + if (arg_vni && !arg_macaddr) { + vty_out(vty, "%% %s may only be specified with mac address\n", + "virtual-network-identifier"); + goto fail; + } + + if (arg_macaddr) { + if (!arg_vni) { + vty_out(vty, + "Missing \"vni\" parameter (mandatory with mac)\n"); + return CMD_WARNING_CONFIG_FAILED; + } + optary[opt_next].v.l2addr.logical_net_id = + strtoul(arg_vni, NULL, 10); + + if ((rc = rfapiStr2EthAddr( + arg_macaddr, + &optary[opt_next].v.l2addr.macaddr))) { + vty_out(vty, "Invalid %s value\n", "mac address"); + goto fail; + } + /* TBD label, NVE ID */ + + optary[opt_next].type = RFAPI_VN_OPTION_TYPE_L2ADDR; + + if (opt_next) { + optary[opt_next - 1].next = optary + opt_next; + } else { + opt = optary; + } + ++opt_next; + } + + vnc_zlog_debug_verbose( + "%s: vn=%s, un=%s, prefix=%s, cost=%s, lifetime=%s, lnh=%s", + __func__, arg_vn, arg_un, arg_prefix, + (arg_cost ? arg_cost : "NULL"), + (arg_lifetime ? arg_lifetime : "NULL"), + (arg_lnh ? arg_lnh : "NULL")); + + rfapiQprefix2Rprefix(&pfx, &rpfx); + + rpfx.cost = cost & 255; + + /* look up rf descriptor, call open if it doesn't exist */ + rc = rfapi_find_rfd(bgp, &vn_address, &un_address, + (struct rfapi_descriptor **)&rfd); + if (rc) { + if (ENOENT == rc) { + struct rfapi_un_option uo; + + /* + * flag descriptor as provisionally opened for static + * route + * registration so that we can fix up the other + * parameters + * when the real open comes along + */ + memset(&uo, 0, sizeof(uo)); + uo.type = RFAPI_UN_OPTION_TYPE_PROVISIONAL; + + rc = rfapi_open(rfapi_get_rfp_start_val_by_bgp(bgp), + &vn_address, &un_address, + &uo, /* flags */ + NULL, NULL, /* no userdata */ + &rfd); + if (rc) { + vty_out(vty, + "Can't open session for this NVE: %s\n", + rfapi_error_str(rc)); + rc = CMD_WARNING_CONFIG_FAILED; + goto fail; + } + } else { + vty_out(vty, "Can't find session for this NVE: %s\n", + rfapi_error_str(rc)); + goto fail; + } + } + + rc = rfapi_register(rfd, &rpfx, lifetime, NULL, opt, + RFAPI_REGISTER_ADD); + if (!rc) { + struct rfapi_next_hop_entry *head = NULL; + struct rfapi_next_hop_entry *tail = NULL; + struct rfapi_vn_option *vn_opt_new; + + vnc_zlog_debug_verbose( + "%s: rfapi_register succeeded, returning 0", __func__); + + if (h->rfp_methods.local_cb) { + struct rfapi_descriptor *r = + (struct rfapi_descriptor *)rfd; + vn_opt_new = rfapi_vn_options_dup(opt); + + rfapiAddDeleteLocalRfpPrefix(&r->un_addr, &r->vn_addr, + &rpfx, 1, lifetime, + vn_opt_new, &head, &tail); + if (head) { + h->flags |= RFAPI_INCALLBACK; + (*h->rfp_methods.local_cb)(head, r->cookie); + h->flags &= ~RFAPI_INCALLBACK; + } + head = tail = NULL; + } + return 0; + } + + vnc_zlog_debug_verbose("%s: rfapi_register failed", __func__); + vty_out(vty, "\n"); + vty_out(vty, "Registration failed.\n"); + vty_out(vty, + "Confirm that either the VN or UN address matches a configured NVE group.\n"); + return CMD_WARNING_CONFIG_FAILED; + +fail: + vnc_zlog_debug_verbose("%s: fail, rc=%d", __func__, rc); + return rc; } /************************************************************************ @@ -2545,10 +2278,10 @@ DEFUN (add_vnc_prefix_cost_life_lnh, "Lifetime value in seconds\n" "[local-next-hop (A.B.C.D|X:X::X:X)] [local-cost <0-255>]\n") { - /* pfx vn un cost life */ - return register_add (vty, argv[3], argv[5], argv[7], argv[9], argv[11], - /* mac vni */ - NULL, NULL, argc - 12, argv + 12); + /* pfx vn un cost life */ + return register_add(vty, argv[3], argv[5], argv[7], argv[9], argv[11], + /* mac vni */ + NULL, NULL, argc - 12, argv + 12); } DEFUN (add_vnc_prefix_life_cost_lnh, @@ -2571,10 +2304,10 @@ DEFUN (add_vnc_prefix_life_cost_lnh, "Administrative cost\n" "[local-next-hop (A.B.C.D|X:X::X:X)] [local-cost <0-255>]\n") { - /* pfx vn un cost life */ - return register_add (vty, argv[3], argv[5], argv[7], argv[11], argv[9], - /* mac vni */ - NULL, NULL, argc - 12, argv + 12); + /* pfx vn un cost life */ + return register_add(vty, argv[3], argv[5], argv[7], argv[11], argv[9], + /* mac vni */ + NULL, NULL, argc - 12, argv + 12); } DEFUN (add_vnc_prefix_cost_lnh, @@ -2595,10 +2328,10 @@ DEFUN (add_vnc_prefix_cost_lnh, "Administrative cost\n" "[local-next-hop (A.B.C.D|X:X::X:X)] [local-cost <0-255>]\n") { - /* pfx vn un cost life */ - return register_add (vty, argv[3], argv[5], argv[7], argv[9], NULL, - /* mac vni */ - NULL, NULL, argc - 10, argv + 10); + /* pfx vn un cost life */ + return register_add(vty, argv[3], argv[5], argv[7], argv[9], NULL, + /* mac vni */ + NULL, NULL, argc - 10, argv + 10); } DEFUN (add_vnc_prefix_life_lnh, @@ -2619,10 +2352,10 @@ DEFUN (add_vnc_prefix_life_lnh, "Lifetime value in seconds\n" "[local-next-hop (A.B.C.D|X:X::X:X)] [local-cost <0-255>]\n") { - /* pfx vn un cost life */ - return register_add (vty, argv[3], argv[5], argv[7], NULL, argv[9], - /* mac vni */ - NULL, NULL, argc - 10, argv + 10); + /* pfx vn un cost life */ + return register_add(vty, argv[3], argv[5], argv[7], NULL, argv[9], + /* mac vni */ + NULL, NULL, argc - 10, argv + 10); } DEFUN (add_vnc_prefix_lnh, @@ -2641,10 +2374,10 @@ DEFUN (add_vnc_prefix_lnh, "UN IPv6 interface address\n" "[local-next-hop (A.B.C.D|X:X::X:X)] [local-cost <0-255>]\n") { - /* pfx vn un cost life */ - return register_add (vty, argv[3], argv[5], argv[7], NULL, NULL, - /* mac vni */ - NULL, NULL, argc - 8, argv + 8); + /* pfx vn un cost life */ + return register_add(vty, argv[3], argv[5], argv[7], NULL, NULL, + /* mac vni */ + NULL, NULL, argc - 8, argv + 8); } /************************************************************************ @@ -2669,10 +2402,10 @@ DEFUN (add_vnc_prefix_cost_life, "Registration lifetime [default: infinite]\n" "Lifetime value in seconds\n") { - /* pfx vn un cost life */ - return register_add (vty, argv[3], argv[5], argv[7], argv[9], argv[11], - /* mac vni */ - NULL, NULL, 0, NULL); + /* pfx vn un cost life */ + return register_add(vty, argv[3], argv[5], argv[7], argv[9], argv[11], + /* mac vni */ + NULL, NULL, 0, NULL); } DEFUN (add_vnc_prefix_life_cost, @@ -2694,10 +2427,10 @@ DEFUN (add_vnc_prefix_life_cost, "Administrative cost [default: 255]\n" "Administrative cost\n") { - /* pfx vn un cost life */ - return register_add (vty, argv[3], argv[5], argv[7], argv[11], argv[9], - /* mac vni */ - NULL, NULL, 0, NULL); + /* pfx vn un cost life */ + return register_add(vty, argv[3], argv[5], argv[7], argv[11], argv[9], + /* mac vni */ + NULL, NULL, 0, NULL); } DEFUN (add_vnc_prefix_cost, @@ -2717,10 +2450,10 @@ DEFUN (add_vnc_prefix_cost, "Administrative cost [default: 255]\n" "Administrative cost\n") { - /* pfx vn un cost life */ - return register_add (vty, argv[3], argv[5], argv[7], argv[9], NULL, - /* mac vni */ - NULL, NULL, 0, NULL); + /* pfx vn un cost life */ + return register_add(vty, argv[3], argv[5], argv[7], argv[9], NULL, + /* mac vni */ + NULL, NULL, 0, NULL); } DEFUN (add_vnc_prefix_life, @@ -2740,10 +2473,10 @@ DEFUN (add_vnc_prefix_life, "Registration lifetime [default: infinite]\n" "Lifetime value in seconds\n") { - /* pfx vn un cost life */ - return register_add (vty, argv[3], argv[5], argv[7], NULL, argv[9], - /* mac vni */ - NULL, NULL, 0, NULL); + /* pfx vn un cost life */ + return register_add(vty, argv[3], argv[5], argv[7], NULL, argv[9], + /* mac vni */ + NULL, NULL, 0, NULL); } DEFUN (add_vnc_prefix, @@ -2761,10 +2494,10 @@ DEFUN (add_vnc_prefix, "UN IPv4 interface address\n" "UN IPv6 interface address\n") { - /* pfx vn un cost life */ - return register_add (vty, argv[3], argv[5], argv[7], NULL, NULL, - /* mac vni */ - NULL, NULL, 0, NULL); + /* pfx vn un cost life */ + return register_add(vty, argv[3], argv[5], argv[7], NULL, NULL, + /* mac vni */ + NULL, NULL, 0, NULL); } /************************************************************************ @@ -2793,10 +2526,10 @@ DEFUN (add_vnc_mac_vni_prefix_cost_life, "Registration lifetime [default: infinite]\n" "Lifetime value in seconds\n") { - /* pfx vn un cost life */ - return register_add (vty, argv[11], argv[7], argv[9], argv[13], argv[15], - /* mac vni */ - argv[3], argv[5], 0, NULL); + /* pfx vn un cost life */ + return register_add(vty, argv[11], argv[7], argv[9], argv[13], argv[15], + /* mac vni */ + argv[3], argv[5], 0, NULL); } @@ -2821,10 +2554,10 @@ DEFUN (add_vnc_mac_vni_prefix_life, "Registration lifetime [default: infinite]\n" "Lifetime value in seconds\n") { - /* pfx vn un cost life */ - return register_add (vty, argv[11], argv[7], argv[9], NULL, argv[13], - /* mac vni */ - argv[3], argv[5], 0, NULL); + /* pfx vn un cost life */ + return register_add(vty, argv[11], argv[7], argv[9], NULL, argv[13], + /* mac vni */ + argv[3], argv[5], 0, NULL); } DEFUN (add_vnc_mac_vni_prefix_cost, @@ -2847,10 +2580,10 @@ DEFUN (add_vnc_mac_vni_prefix_cost, "IPv6 prefix\n" "Administrative cost [default: 255]\n" "Administrative cost\n") { - /* pfx vn un cost life */ - return register_add (vty, argv[11], argv[7], argv[9], argv[13], NULL, - /* mac vni */ - argv[3], argv[5], 0, NULL); + /* pfx vn un cost life */ + return register_add(vty, argv[11], argv[7], argv[9], argv[13], NULL, + /* mac vni */ + argv[3], argv[5], 0, NULL); } DEFUN (add_vnc_mac_vni_prefix, @@ -2871,10 +2604,10 @@ DEFUN (add_vnc_mac_vni_prefix, "Add/modify prefix related information\n" "IPv4 prefix\n" "IPv6 prefix\n") { - /* pfx vn un cost life */ - return register_add (vty, argv[11], argv[7], argv[9], NULL, NULL, - /* mac vni */ - argv[3], argv[5], 0, NULL); + /* pfx vn un cost life */ + return register_add(vty, argv[11], argv[7], argv[9], NULL, NULL, + /* mac vni */ + argv[3], argv[5], 0, NULL); } DEFUN (add_vnc_mac_vni_cost_life, @@ -2897,10 +2630,10 @@ DEFUN (add_vnc_mac_vni_cost_life, "Registration lifetime [default: infinite]\n" "Lifetime value in seconds\n") { - /* pfx vn un cost life */ - return register_add (vty, NULL, argv[7], argv[9], argv[11], argv[13], - /* mac vni */ - argv[3], argv[5], 0, NULL); + /* pfx vn un cost life */ + return register_add(vty, NULL, argv[7], argv[9], argv[11], argv[13], + /* mac vni */ + argv[3], argv[5], 0, NULL); } @@ -2921,10 +2654,10 @@ DEFUN (add_vnc_mac_vni_cost, "UN IPv6 interface address\n" "Administrative cost [default: 255]\n" "Administrative cost\n") { - /* pfx vn un cost life */ - return register_add (vty, NULL, argv[7], argv[9], argv[11], NULL, - /* mac vni */ - argv[3], argv[5], 0, NULL); + /* pfx vn un cost life */ + return register_add(vty, NULL, argv[7], argv[9], argv[11], NULL, + /* mac vni */ + argv[3], argv[5], 0, NULL); } @@ -2946,10 +2679,10 @@ DEFUN (add_vnc_mac_vni_life, "Registration lifetime [default: infinite]\n" "Lifetime value in seconds\n") { - /* pfx vn un cost life */ - return register_add (vty, NULL, argv[7], argv[9], NULL, argv[11], - /* mac vni */ - argv[3], argv[5], 0, NULL); + /* pfx vn un cost life */ + return register_add(vty, NULL, argv[7], argv[9], NULL, argv[11], + /* mac vni */ + argv[3], argv[5], 0, NULL); } @@ -2968,674 +2701,643 @@ DEFUN (add_vnc_mac_vni, "UN address of NVE\n" "UN IPv4 interface address\n" "UN IPv6 interface address\n") { - /* pfx vn un cost life */ - return register_add (vty, NULL, argv[7], argv[9], NULL, NULL, - /* mac vni */ - argv[3], argv[5], 0, NULL); + /* pfx vn un cost life */ + return register_add(vty, NULL, argv[7], argv[9], NULL, NULL, + /* mac vni */ + argv[3], argv[5], 0, NULL); } /************************************************************************ * Delete prefix ************************************************************************/ -struct rfapi_local_reg_delete_arg -{ - /* - * match parameters - */ - struct bgp *bgp; - struct rfapi_ip_addr un_address; /* AF==0: wildcard */ - struct rfapi_ip_addr vn_address; /* AF==0: wildcard */ - struct prefix prefix; /* AF==0: wildcard */ - struct prefix_rd rd; /* plen!=64: wildcard */ - struct rfapi_nve_group_cfg *rfg; /* NULL: wildcard */ - - struct rfapi_l2address_option_match l2o; - - /* - * result parameters - */ - struct vty *vty; - uint32_t reg_count; - uint32_t pfx_count; - uint32_t query_count; - - uint32_t failed_pfx_count; - - uint32_t nve_count; - struct skiplist *nves; - - uint32_t remote_active_nve_count; - uint32_t remote_active_pfx_count; - uint32_t remote_holddown_nve_count; - uint32_t remote_holddown_pfx_count; +struct rfapi_local_reg_delete_arg { + /* + * match parameters + */ + struct bgp *bgp; + struct rfapi_ip_addr un_address; /* AF==0: wildcard */ + struct rfapi_ip_addr vn_address; /* AF==0: wildcard */ + struct prefix prefix; /* AF==0: wildcard */ + struct prefix_rd rd; /* plen!=64: wildcard */ + struct rfapi_nve_group_cfg *rfg; /* NULL: wildcard */ + + struct rfapi_l2address_option_match l2o; + + /* + * result parameters + */ + struct vty *vty; + uint32_t reg_count; + uint32_t pfx_count; + uint32_t query_count; + + uint32_t failed_pfx_count; + + uint32_t nve_count; + struct skiplist *nves; + + uint32_t remote_active_nve_count; + uint32_t remote_active_pfx_count; + uint32_t remote_holddown_nve_count; + uint32_t remote_holddown_pfx_count; }; -struct nve_addr -{ - struct rfapi_ip_addr vn; - struct rfapi_ip_addr un; - struct rfapi_descriptor *rfd; - struct rfapi_local_reg_delete_arg *cda; +struct nve_addr { + struct rfapi_ip_addr vn; + struct rfapi_ip_addr un; + struct rfapi_descriptor *rfd; + struct rfapi_local_reg_delete_arg *cda; }; -static void -nve_addr_free (void *hap) +static void nve_addr_free(void *hap) { - ((struct nve_addr *) hap)->cda->nve_count += 1; - XFREE (MTYPE_RFAPI_NVE_ADDR, hap); + ((struct nve_addr *)hap)->cda->nve_count += 1; + XFREE(MTYPE_RFAPI_NVE_ADDR, hap); } -static int -nve_addr_cmp (void *k1, void *k2) +static int nve_addr_cmp(void *k1, void *k2) { - struct nve_addr *a = (struct nve_addr *) k1; - struct nve_addr *b = (struct nve_addr *) k2; - int ret = 0; - - if (!a || !b) - { - return (a - b); - } - if (a->un.addr_family != b->un.addr_family) - { - return (a->un.addr_family - b->un.addr_family); - } - if (a->vn.addr_family != b->vn.addr_family) - { - return (a->vn.addr_family - b->vn.addr_family); - } - if (a->un.addr_family == AF_INET) - { - ret = IPV4_ADDR_CMP (&a->un.addr.v4, &b->un.addr.v4); - if (ret != 0) - { - return ret; - } - } - else if (a->un.addr_family == AF_INET6) - { - ret = IPV6_ADDR_CMP (&a->un.addr.v6, &b->un.addr.v6); - if (ret != 0) - { - return ret; - } - } - else - { - assert (0); - } - if (a->vn.addr_family == AF_INET) - { - ret = IPV4_ADDR_CMP (&a->vn.addr.v4, &b->vn.addr.v4); - if (ret != 0) - return ret; - } - else if (a->vn.addr_family == AF_INET6) - { - ret = IPV6_ADDR_CMP (&a->vn.addr.v6, &b->vn.addr.v6); - if (ret == 0) - { - return ret; - } - } - else - { - assert (0); - } - return 0; + struct nve_addr *a = (struct nve_addr *)k1; + struct nve_addr *b = (struct nve_addr *)k2; + int ret = 0; + + if (!a || !b) { + return (a - b); + } + if (a->un.addr_family != b->un.addr_family) { + return (a->un.addr_family - b->un.addr_family); + } + if (a->vn.addr_family != b->vn.addr_family) { + return (a->vn.addr_family - b->vn.addr_family); + } + if (a->un.addr_family == AF_INET) { + ret = IPV4_ADDR_CMP(&a->un.addr.v4, &b->un.addr.v4); + if (ret != 0) { + return ret; + } + } else if (a->un.addr_family == AF_INET6) { + ret = IPV6_ADDR_CMP(&a->un.addr.v6, &b->un.addr.v6); + if (ret != 0) { + return ret; + } + } else { + assert(0); + } + if (a->vn.addr_family == AF_INET) { + ret = IPV4_ADDR_CMP(&a->vn.addr.v4, &b->vn.addr.v4); + if (ret != 0) + return ret; + } else if (a->vn.addr_family == AF_INET6) { + ret = IPV6_ADDR_CMP(&a->vn.addr.v6, &b->vn.addr.v6); + if (ret == 0) { + return ret; + } + } else { + assert(0); + } + return 0; } -static int -parse_deleter_args ( - struct vty *vty, - struct bgp *bgp, - const char *arg_prefix, - const char *arg_vn, - const char *arg_un, - const char *arg_l2addr, - const char *arg_vni, - const char *arg_rd, - struct rfapi_nve_group_cfg *arg_rfg, - struct rfapi_local_reg_delete_arg *rcdarg) +static int parse_deleter_args(struct vty *vty, struct bgp *bgp, + const char *arg_prefix, const char *arg_vn, + const char *arg_un, const char *arg_l2addr, + const char *arg_vni, const char *arg_rd, + struct rfapi_nve_group_cfg *arg_rfg, + struct rfapi_local_reg_delete_arg *rcdarg) { - int rc = CMD_WARNING; - - memset (rcdarg, 0, sizeof (struct rfapi_local_reg_delete_arg)); - - rcdarg->vty = vty; - if (bgp == NULL) - bgp = bgp_get_default(); - rcdarg->bgp = bgp; - rcdarg->rfg = arg_rfg; /* may be NULL */ - - if (arg_vn && strcmp (arg_vn, "*")) - { - if ((rc = rfapiCliGetRfapiIpAddr (vty, arg_vn, &rcdarg->vn_address))) - return rc; - } - if (arg_un && strcmp (arg_un, "*")) - { - if ((rc = rfapiCliGetRfapiIpAddr (vty, arg_un, &rcdarg->un_address))) - return rc; - } - if (arg_prefix && strcmp (arg_prefix, "*")) - { - - if (!str2prefix (arg_prefix, &rcdarg->prefix)) - { - vty_out (vty, "Malformed prefix \"%s\"\n", arg_prefix); - return rc; - } - } - - if (arg_l2addr) - { - if (!arg_vni) - { - vty_out (vty, "Missing VNI\n"); - return rc; - } - if (strcmp (arg_l2addr, "*")) - { - if ((rc = rfapiStr2EthAddr (arg_l2addr, &rcdarg->l2o.o.macaddr))) - { - vty_out (vty, "Malformed L2 Address \"%s\"\n", - arg_l2addr); - return rc; - } - rcdarg->l2o.flags |= RFAPI_L2O_MACADDR; - } - if (strcmp (arg_vni, "*")) - { - rcdarg->l2o.o.logical_net_id = strtoul(arg_vni, NULL, 10); - rcdarg->l2o.flags |= RFAPI_L2O_LNI; - } - } - if (arg_rd) - { - if (!str2prefix_rd (arg_rd, &rcdarg->rd)) - { - vty_out (vty, "Malformed RD \"%s\"\n", - arg_rd); - return rc; - } - } - - return CMD_SUCCESS; + int rc = CMD_WARNING; + + memset(rcdarg, 0, sizeof(struct rfapi_local_reg_delete_arg)); + + rcdarg->vty = vty; + if (bgp == NULL) + bgp = bgp_get_default(); + rcdarg->bgp = bgp; + rcdarg->rfg = arg_rfg; /* may be NULL */ + + if (arg_vn && strcmp(arg_vn, "*")) { + if ((rc = rfapiCliGetRfapiIpAddr(vty, arg_vn, + &rcdarg->vn_address))) + return rc; + } + if (arg_un && strcmp(arg_un, "*")) { + if ((rc = rfapiCliGetRfapiIpAddr(vty, arg_un, + &rcdarg->un_address))) + return rc; + } + if (arg_prefix && strcmp(arg_prefix, "*")) { + + if (!str2prefix(arg_prefix, &rcdarg->prefix)) { + vty_out(vty, "Malformed prefix \"%s\"\n", arg_prefix); + return rc; + } + } + + if (arg_l2addr) { + if (!arg_vni) { + vty_out(vty, "Missing VNI\n"); + return rc; + } + if (strcmp(arg_l2addr, "*")) { + if ((rc = rfapiStr2EthAddr(arg_l2addr, + &rcdarg->l2o.o.macaddr))) { + vty_out(vty, "Malformed L2 Address \"%s\"\n", + arg_l2addr); + return rc; + } + rcdarg->l2o.flags |= RFAPI_L2O_MACADDR; + } + if (strcmp(arg_vni, "*")) { + rcdarg->l2o.o.logical_net_id = + strtoul(arg_vni, NULL, 10); + rcdarg->l2o.flags |= RFAPI_L2O_LNI; + } + } + if (arg_rd) { + if (!str2prefix_rd(arg_rd, &rcdarg->rd)) { + vty_out(vty, "Malformed RD \"%s\"\n", arg_rd); + return rc; + } + } + + return CMD_SUCCESS; } static int -parse_deleter_tokens ( - struct vty *vty, - struct bgp *bgp, - struct cmd_token *carg_prefix, - struct cmd_token *carg_vn, - struct cmd_token *carg_un, - struct cmd_token *carg_l2addr, - struct cmd_token *carg_vni, - struct cmd_token *carg_rd, - struct rfapi_nve_group_cfg *arg_rfg, - struct rfapi_local_reg_delete_arg *rcdarg) +parse_deleter_tokens(struct vty *vty, struct bgp *bgp, + struct cmd_token *carg_prefix, struct cmd_token *carg_vn, + struct cmd_token *carg_un, struct cmd_token *carg_l2addr, + struct cmd_token *carg_vni, struct cmd_token *carg_rd, + struct rfapi_nve_group_cfg *arg_rfg, + struct rfapi_local_reg_delete_arg *rcdarg) { - const char *arg_prefix = carg_prefix ? carg_prefix->arg : NULL; - const char *arg_vn = carg_vn ? carg_vn->arg : NULL; - const char *arg_un = carg_un ? carg_un->arg : NULL; - const char *arg_l2addr = carg_l2addr ? carg_l2addr->arg : NULL; - const char *arg_vni = carg_vni ? carg_vni->arg : NULL; - const char *arg_rd = carg_rd ? carg_rd->arg : NULL; - return parse_deleter_args (vty, bgp,arg_prefix, arg_vn, arg_un, - arg_l2addr, arg_vni, arg_rd, - arg_rfg, rcdarg); + const char *arg_prefix = carg_prefix ? carg_prefix->arg : NULL; + const char *arg_vn = carg_vn ? carg_vn->arg : NULL; + const char *arg_un = carg_un ? carg_un->arg : NULL; + const char *arg_l2addr = carg_l2addr ? carg_l2addr->arg : NULL; + const char *arg_vni = carg_vni ? carg_vni->arg : NULL; + const char *arg_rd = carg_rd ? carg_rd->arg : NULL; + return parse_deleter_args(vty, bgp, arg_prefix, arg_vn, arg_un, + arg_l2addr, arg_vni, arg_rd, arg_rfg, rcdarg); } -static void -record_nve_in_cda_list ( - struct rfapi_local_reg_delete_arg *cda, - struct rfapi_ip_addr *un_address, - struct rfapi_ip_addr *vn_address, - struct rfapi_descriptor *rfd) +static void record_nve_in_cda_list(struct rfapi_local_reg_delete_arg *cda, + struct rfapi_ip_addr *un_address, + struct rfapi_ip_addr *vn_address, + struct rfapi_descriptor *rfd) { - struct nve_addr ha; - struct nve_addr *hap; - - memset (&ha, 0, sizeof (ha)); - ha.un = *un_address; - ha.vn = *vn_address; - ha.rfd = rfd; - - if (!cda->nves) - cda->nves = skiplist_new (0, nve_addr_cmp, nve_addr_free); - - if (skiplist_search (cda->nves, &ha, (void *) &hap)) - { - hap = XCALLOC (MTYPE_RFAPI_NVE_ADDR, sizeof (struct nve_addr)); - assert (hap); - ha.cda = cda; - * hap = ha; - skiplist_insert (cda->nves, hap, hap); - } + struct nve_addr ha; + struct nve_addr *hap; + + memset(&ha, 0, sizeof(ha)); + ha.un = *un_address; + ha.vn = *vn_address; + ha.rfd = rfd; + + if (!cda->nves) + cda->nves = skiplist_new(0, nve_addr_cmp, nve_addr_free); + + if (skiplist_search(cda->nves, &ha, (void *)&hap)) { + hap = XCALLOC(MTYPE_RFAPI_NVE_ADDR, sizeof(struct nve_addr)); + assert(hap); + ha.cda = cda; + *hap = ha; + skiplist_insert(cda->nves, hap, hap); + } } -static void -clear_vnc_responses (struct rfapi_local_reg_delete_arg *cda) +static void clear_vnc_responses(struct rfapi_local_reg_delete_arg *cda) { - struct rfapi *h; - struct rfapi_descriptor *rfd; - int query_count = 0; - struct listnode *node; - struct bgp *bgp_default = bgp_get_default (); - - if (cda->vn_address.addr_family && cda->un_address.addr_family) - { - /* - * Single nve case - */ - if (rfapi_find_rfd - (bgp_default, &cda->vn_address, &cda->un_address, &rfd)) - return; - - rfapiRibClear (rfd); - rfapi_query_done_all (rfd, &query_count); - cda->query_count += query_count; - - /* - * Track unique nves seen - */ - record_nve_in_cda_list (cda, &rfd->un_addr, &rfd->vn_addr, rfd); - return; - } - - /* - * wildcard case - */ - - if (!bgp_default) - return; /* ENXIO */ - - h = bgp_default->rfapi; - - if (!h) - return; /* ENXIO */ - - for (ALL_LIST_ELEMENTS_RO (&h->descriptors, node, rfd)) - { - /* - * match un, vn addresses of NVEs - */ - if (cda->un_address.addr_family && - rfapi_ip_addr_cmp (&cda->un_address, &rfd->un_addr)) - { - continue; - } - if (cda->vn_address.addr_family && - rfapi_ip_addr_cmp (&cda->vn_address, &rfd->vn_addr)) - { - continue; - } - - rfapiRibClear (rfd); - - rfapi_query_done_all (rfd, &query_count); - cda->query_count += query_count; - - /* - * Track unique nves seen - */ - record_nve_in_cda_list (cda, &rfd->un_addr, &rfd->vn_addr, rfd); - } + struct rfapi *h; + struct rfapi_descriptor *rfd; + int query_count = 0; + struct listnode *node; + struct bgp *bgp_default = bgp_get_default(); + + if (cda->vn_address.addr_family && cda->un_address.addr_family) { + /* + * Single nve case + */ + if (rfapi_find_rfd(bgp_default, &cda->vn_address, + &cda->un_address, &rfd)) + return; + + rfapiRibClear(rfd); + rfapi_query_done_all(rfd, &query_count); + cda->query_count += query_count; + + /* + * Track unique nves seen + */ + record_nve_in_cda_list(cda, &rfd->un_addr, &rfd->vn_addr, rfd); + return; + } + + /* + * wildcard case + */ + + if (!bgp_default) + return; /* ENXIO */ + + h = bgp_default->rfapi; + + if (!h) + return; /* ENXIO */ + + for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) { + /* + * match un, vn addresses of NVEs + */ + if (cda->un_address.addr_family + && rfapi_ip_addr_cmp(&cda->un_address, &rfd->un_addr)) { + continue; + } + if (cda->vn_address.addr_family + && rfapi_ip_addr_cmp(&cda->vn_address, &rfd->vn_addr)) { + continue; + } + + rfapiRibClear(rfd); + + rfapi_query_done_all(rfd, &query_count); + cda->query_count += query_count; + + /* + * Track unique nves seen + */ + record_nve_in_cda_list(cda, &rfd->un_addr, &rfd->vn_addr, rfd); + } } /* * TBD need to count deleted prefixes and nves? * * ENXIO BGP or VNC not configured - */ -static int -rfapiDeleteLocalPrefixesByRFD (struct rfapi_local_reg_delete_arg *cda, - struct rfapi_descriptor *rfd) + */ +static int rfapiDeleteLocalPrefixesByRFD(struct rfapi_local_reg_delete_arg *cda, + struct rfapi_descriptor *rfd) { - struct rfapi_ip_addr *pUn; /* NULL = wildcard */ - struct rfapi_ip_addr *pVn; /* NULL = wildcard */ - struct prefix *pPrefix; /* NULL = wildcard */ - struct prefix_rd *pPrd; /* NULL = wildcard */ + struct rfapi_ip_addr *pUn; /* NULL = wildcard */ + struct rfapi_ip_addr *pVn; /* NULL = wildcard */ + struct prefix *pPrefix; /* NULL = wildcard */ + struct prefix_rd *pPrd; /* NULL = wildcard */ - struct rfapi_ip_prefix rprefix; - struct rfapi_next_hop_entry *head = NULL; - struct rfapi_next_hop_entry *tail = NULL; + struct rfapi_ip_prefix rprefix; + struct rfapi_next_hop_entry *head = NULL; + struct rfapi_next_hop_entry *tail = NULL; #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: entry", __func__); + vnc_zlog_debug_verbose("%s: entry", __func__); #endif - pUn = (cda->un_address.addr_family ? &cda->un_address : NULL); - pVn = (cda->vn_address.addr_family ? &cda->vn_address : NULL); - pPrefix = (cda->prefix.family ? &cda->prefix : NULL); - pPrd = (cda->rd.prefixlen == 64 ? &cda->rd : NULL); - - if (pPrefix) - { - rfapiQprefix2Rprefix (pPrefix, &rprefix); - } - - do /* to preserve old code structure */ - { - struct rfapi *h=cda->bgp->rfapi;; - struct rfapi_adb *adb; - int rc; - int deleted_from_this_nve; - struct nve_addr ha; - struct nve_addr *hap; + pUn = (cda->un_address.addr_family ? &cda->un_address : NULL); + pVn = (cda->vn_address.addr_family ? &cda->vn_address : NULL); + pPrefix = (cda->prefix.family ? &cda->prefix : NULL); + pPrd = (cda->rd.prefixlen == 64 ? &cda->rd : NULL); + + if (pPrefix) { + rfapiQprefix2Rprefix(pPrefix, &rprefix); + } + + do /* to preserve old code structure */ + { + struct rfapi *h = cda->bgp->rfapi; + ; + struct rfapi_adb *adb; + int rc; + int deleted_from_this_nve; + struct nve_addr ha; + struct nve_addr *hap; #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: rfd=%p", __func__, rfd); + vnc_zlog_debug_verbose("%s: rfd=%p", __func__, rfd); #endif - /* - * match un, vn addresses of NVEs - */ - if (pUn && (rfapi_ip_addr_cmp (pUn, &rfd->un_addr))) - continue; - if (pVn && (rfapi_ip_addr_cmp (pVn, &rfd->vn_addr))) - continue; + /* + * match un, vn addresses of NVEs + */ + if (pUn && (rfapi_ip_addr_cmp(pUn, &rfd->un_addr))) + continue; + if (pVn && (rfapi_ip_addr_cmp(pVn, &rfd->vn_addr))) + continue; #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: un, vn match", __func__); + vnc_zlog_debug_verbose("%s: un, vn match", __func__); #endif - /* - * match prefix - */ - - deleted_from_this_nve = 0; - - { - struct skiplist *sl; - struct rfapi_ip_prefix rp; - void *cursor; - struct list *adb_delete_list; - - /* - * The advertisements are stored in a skiplist. Withdrawing - * the registration deletes the advertisement from the - * skiplist, which we can't do while iterating over that - * same skiplist using the current skiplist API. - * - * Strategy: iterate over the skiplist and build another - * list containing only the matching ADBs. Then delete - * _everything_ in that second list (which can be done - * using either skiplists or quagga linklists). - */ - adb_delete_list = list_new (); - - /* - * Advertised IP prefixes (not 0/32 or 0/128) - */ - sl = rfd->advertised.ipN_by_prefix; - - for (cursor = NULL, - rc = skiplist_next (sl, NULL, (void **) &adb, &cursor); - !rc; rc = skiplist_next (sl, NULL, (void **) &adb, &cursor)) - { - - if (pPrefix) - { - if (!prefix_same (pPrefix, &adb->u.s.prefix_ip)) - { + /* + * match prefix + */ + + deleted_from_this_nve = 0; + + { + struct skiplist *sl; + struct rfapi_ip_prefix rp; + void *cursor; + struct list *adb_delete_list; + + /* + * The advertisements are stored in a skiplist. + * Withdrawing + * the registration deletes the advertisement from the + * skiplist, which we can't do while iterating over that + * same skiplist using the current skiplist API. + * + * Strategy: iterate over the skiplist and build another + * list containing only the matching ADBs. Then delete + * _everything_ in that second list (which can be done + * using either skiplists or quagga linklists). + */ + adb_delete_list = list_new(); + + /* + * Advertised IP prefixes (not 0/32 or 0/128) + */ + sl = rfd->advertised.ipN_by_prefix; + + for (cursor = NULL, + rc = skiplist_next(sl, NULL, (void **)&adb, + &cursor); + !rc; rc = skiplist_next(sl, NULL, (void **)&adb, + &cursor)) { + + if (pPrefix) { + if (!prefix_same(pPrefix, + &adb->u.s.prefix_ip)) { #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: adb=%p, prefix doesn't match, skipping", - __func__, adb); + vnc_zlog_debug_verbose( + "%s: adb=%p, prefix doesn't match, skipping", + __func__, adb); #endif - continue; - } - } - if (pPrd) - { - if (memcmp(pPrd->val, adb->u.s.prd.val, 8) != 0) - { + continue; + } + } + if (pPrd) { + if (memcmp(pPrd->val, adb->u.s.prd.val, + 8) + != 0) { #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: adb=%p, RD doesn't match, skipping", - __func__, adb); + vnc_zlog_debug_verbose( + "%s: adb=%p, RD doesn't match, skipping", + __func__, adb); #endif - continue; - } - } - if (CHECK_FLAG (cda->l2o.flags, RFAPI_L2O_MACADDR)) - { - if (memcmp - (cda->l2o.o.macaddr.octet, - adb->u.s.prefix_eth.u.prefix_eth.octet, ETHER_ADDR_LEN)) - { + continue; + } + } + if (CHECK_FLAG(cda->l2o.flags, + RFAPI_L2O_MACADDR)) { + if (memcmp(cda->l2o.o.macaddr.octet, + adb->u.s.prefix_eth.u + .prefix_eth.octet, + ETHER_ADDR_LEN)) { #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: adb=%p, macaddr doesn't match, skipping", - __func__, adb); + vnc_zlog_debug_verbose( + "%s: adb=%p, macaddr doesn't match, skipping", + __func__, adb); #endif - continue; - } - } - - if (CHECK_FLAG (cda->l2o.flags, RFAPI_L2O_LNI)) - { - if (cda->l2o.o.logical_net_id != adb->l2o.logical_net_id) - { + continue; + } + } + + if (CHECK_FLAG(cda->l2o.flags, RFAPI_L2O_LNI)) { + if (cda->l2o.o.logical_net_id + != adb->l2o.logical_net_id) { #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: adb=%p, LNI doesn't match, skipping", - __func__, adb); + vnc_zlog_debug_verbose( + "%s: adb=%p, LNI doesn't match, skipping", + __func__, adb); #endif - continue; - } - } + continue; + } + } #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: ipN adding adb %p to delete list", __func__, - adb); + vnc_zlog_debug_verbose( + "%s: ipN adding adb %p to delete list", + __func__, adb); #endif - listnode_add (adb_delete_list, adb); - } - - struct listnode *node; - - for (ALL_LIST_ELEMENTS_RO (adb_delete_list, node, adb)) - { - int this_advertisement_prefix_count; - struct rfapi_vn_option optary[3]; - struct rfapi_vn_option *opt = NULL; - int cur_opt = 0; - - this_advertisement_prefix_count = 1; - - rfapiQprefix2Rprefix (&adb->u.s.prefix_ip, &rp); - - memset (optary, 0, sizeof (optary)); - - /* if mac addr present in advert, make l2o vn option */ - if (adb->u.s.prefix_eth.family == AF_ETHERNET) - { - if (opt != NULL) - opt->next = &optary[cur_opt]; - opt = &optary[cur_opt++]; - opt->type = RFAPI_VN_OPTION_TYPE_L2ADDR; - opt->v.l2addr.macaddr = adb->u.s.prefix_eth.u.prefix_eth; - ++this_advertisement_prefix_count; - } - /* - * use saved RD value instead of trying to invert - * complex RD computation in rfapi_register() - */ - if (opt != NULL) - opt->next = &optary[cur_opt]; - opt = &optary[cur_opt++]; - opt->type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD; - opt->v.internal_rd = adb->u.s.prd; + listnode_add(adb_delete_list, adb); + } + + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO(adb_delete_list, node, adb)) { + int this_advertisement_prefix_count; + struct rfapi_vn_option optary[3]; + struct rfapi_vn_option *opt = NULL; + int cur_opt = 0; + + this_advertisement_prefix_count = 1; + + rfapiQprefix2Rprefix(&adb->u.s.prefix_ip, &rp); + + memset(optary, 0, sizeof(optary)); + + /* if mac addr present in advert, make l2o vn + * option */ + if (adb->u.s.prefix_eth.family == AF_ETHERNET) { + if (opt != NULL) + opt->next = &optary[cur_opt]; + opt = &optary[cur_opt++]; + opt->type = RFAPI_VN_OPTION_TYPE_L2ADDR; + opt->v.l2addr.macaddr = + adb->u.s.prefix_eth.u + .prefix_eth; + ++this_advertisement_prefix_count; + } + /* + * use saved RD value instead of trying to + * invert + * complex RD computation in rfapi_register() + */ + if (opt != NULL) + opt->next = &optary[cur_opt]; + opt = &optary[cur_opt++]; + opt->type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD; + opt->v.internal_rd = adb->u.s.prd; #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: ipN killing reg from adb %p ", __func__, adb); + vnc_zlog_debug_verbose( + "%s: ipN killing reg from adb %p ", + __func__, adb); #endif - rc = rfapi_register (rfd, &rp, 0, NULL, - (cur_opt ? optary : NULL), RFAPI_REGISTER_KILL); - if (!rc) - { - cda->pfx_count += this_advertisement_prefix_count; - cda->reg_count += 1; - deleted_from_this_nve = 1; - } - if (h->rfp_methods.local_cb) - { - rfapiAddDeleteLocalRfpPrefix (&rfd->un_addr, &rfd->vn_addr, - &rp, 0, 0, NULL, &head, &tail); - } - } - list_delete_all_node (adb_delete_list); - - if (!(pPrefix && !RFAPI_0_PREFIX (pPrefix))) - { - void *cursor; - - /* - * Caller didn't specify a prefix, or specified (0/32 or 0/128) - */ - - /* - * Advertised 0/32 and 0/128 (indexed by ethernet address) - */ - sl = rfd->advertised.ip0_by_ether; - - for (cursor = NULL, - rc = skiplist_next (sl, NULL, (void **) &adb, &cursor); - !rc; rc = skiplist_next (sl, NULL, (void **) &adb, &cursor)) - { - - if (CHECK_FLAG (cda->l2o.flags, RFAPI_L2O_MACADDR)) - { - if (memcmp (cda->l2o.o.macaddr.octet, - adb->u.s.prefix_eth.u.prefix_eth.octet, - ETHER_ADDR_LEN)) - { - - continue; - } - } - if (CHECK_FLAG (cda->l2o.flags, RFAPI_L2O_LNI)) - { - if (cda->l2o.o.logical_net_id != adb->l2o.logical_net_id) - { - continue; - } - } + rc = rfapi_register(rfd, &rp, 0, NULL, + (cur_opt ? optary : NULL), + RFAPI_REGISTER_KILL); + if (!rc) { + cda->pfx_count += + this_advertisement_prefix_count; + cda->reg_count += 1; + deleted_from_this_nve = 1; + } + if (h->rfp_methods.local_cb) { + rfapiAddDeleteLocalRfpPrefix( + &rfd->un_addr, &rfd->vn_addr, + &rp, 0, 0, NULL, &head, &tail); + } + } + list_delete_all_node(adb_delete_list); + + if (!(pPrefix && !RFAPI_0_PREFIX(pPrefix))) { + void *cursor; + + /* + * Caller didn't specify a prefix, or specified + * (0/32 or 0/128) + */ + + /* + * Advertised 0/32 and 0/128 (indexed by + * ethernet address) + */ + sl = rfd->advertised.ip0_by_ether; + + for (cursor = NULL, + rc = skiplist_next(sl, NULL, (void **)&adb, + &cursor); + !rc; + rc = skiplist_next(sl, NULL, (void **)&adb, + &cursor)) { + + if (CHECK_FLAG(cda->l2o.flags, + RFAPI_L2O_MACADDR)) { + if (memcmp(cda->l2o.o.macaddr + .octet, + adb->u.s.prefix_eth.u + .prefix_eth + .octet, + ETHER_ADDR_LEN)) { + + continue; + } + } + if (CHECK_FLAG(cda->l2o.flags, + RFAPI_L2O_LNI)) { + if (cda->l2o.o.logical_net_id + != adb->l2o.logical_net_id) { + continue; + } + } #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: ip0 adding adb %p to delete list", - __func__, adb); + vnc_zlog_debug_verbose( + "%s: ip0 adding adb %p to delete list", + __func__, adb); #endif - listnode_add (adb_delete_list, adb); - } + listnode_add(adb_delete_list, adb); + } - for (ALL_LIST_ELEMENTS_RO (adb_delete_list, node, adb)) - { + for (ALL_LIST_ELEMENTS_RO(adb_delete_list, node, + adb)) { - struct rfapi_vn_option vn; + struct rfapi_vn_option vn; - rfapiQprefix2Rprefix (&adb->u.s.prefix_ip, &rp); + rfapiQprefix2Rprefix( + &adb->u.s.prefix_ip, &rp); - memset (&vn, 0, sizeof (vn)); - vn.type = RFAPI_VN_OPTION_TYPE_L2ADDR; - vn.v.l2addr = adb->l2o; + memset(&vn, 0, sizeof(vn)); + vn.type = RFAPI_VN_OPTION_TYPE_L2ADDR; + vn.v.l2addr = adb->l2o; #if DEBUG_L2_EXTRA - vnc_zlog_debug_verbose ("%s: ip0 killing reg from adb %p ", - __func__, adb); + vnc_zlog_debug_verbose( + "%s: ip0 killing reg from adb %p ", + __func__, adb); #endif - rc = rfapi_register (rfd, &rp, 0, NULL, &vn, - RFAPI_REGISTER_KILL); - if (!rc) - { - cda->pfx_count += 1; - cda->reg_count += 1; - deleted_from_this_nve = 1; - } - if (h->rfp_methods.local_cb) - { - struct rfapi_vn_option *vn_opt_new; - - vn_opt_new = rfapi_vn_options_dup (&vn); - rfapiAddDeleteLocalRfpPrefix (&rfd->un_addr, - &rfd->vn_addr, &rp, 0, 0, - vn_opt_new, &head, &tail); - } - } - list_delete_all_node (adb_delete_list); - } - list_delete (adb_delete_list); - } - - - if (head) - { /* should not be set if (NULL == rfapi_cfg->local_cb) */ - h->flags |= RFAPI_INCALLBACK; - (*h->rfp_methods.local_cb) (head, rfd->cookie); - h->flags &= ~RFAPI_INCALLBACK; - head = tail = NULL; - } - - if (deleted_from_this_nve) - { - /* - * track unique NVEs seen - */ - memset (&ha, 0, sizeof (ha)); - ha.un = rfd->un_addr; - ha.vn = rfd->vn_addr; - - if (!cda->nves) - cda->nves = skiplist_new (0, nve_addr_cmp, nve_addr_free); - if (skiplist_search (cda->nves, &ha, (void **) &hap)) - { - hap = XCALLOC (MTYPE_RFAPI_NVE_ADDR, sizeof (struct nve_addr)); - assert (hap); - ha.cda = cda; - *hap = ha; - skiplist_insert (cda->nves, hap, hap); - } - } - } while (0); /* to preserve old code structure */ - - return 0; + rc = rfapi_register( + rfd, &rp, 0, NULL, &vn, + RFAPI_REGISTER_KILL); + if (!rc) { + cda->pfx_count += 1; + cda->reg_count += 1; + deleted_from_this_nve = 1; + } + if (h->rfp_methods.local_cb) { + struct rfapi_vn_option + *vn_opt_new; + + vn_opt_new = + rfapi_vn_options_dup( + &vn); + rfapiAddDeleteLocalRfpPrefix( + &rfd->un_addr, + &rfd->vn_addr, &rp, 0, + 0, vn_opt_new, &head, + &tail); + } + } + list_delete_all_node(adb_delete_list); + } + list_delete(adb_delete_list); + } + + + if (head) { /* should not be set if (NULL == + rfapi_cfg->local_cb) */ + h->flags |= RFAPI_INCALLBACK; + (*h->rfp_methods.local_cb)(head, rfd->cookie); + h->flags &= ~RFAPI_INCALLBACK; + head = tail = NULL; + } + + if (deleted_from_this_nve) { + /* + * track unique NVEs seen + */ + memset(&ha, 0, sizeof(ha)); + ha.un = rfd->un_addr; + ha.vn = rfd->vn_addr; + + if (!cda->nves) + cda->nves = skiplist_new(0, nve_addr_cmp, + nve_addr_free); + if (skiplist_search(cda->nves, &ha, (void **)&hap)) { + hap = XCALLOC(MTYPE_RFAPI_NVE_ADDR, + sizeof(struct nve_addr)); + assert(hap); + ha.cda = cda; + *hap = ha; + skiplist_insert(cda->nves, hap, hap); + } + } + } while (0); /* to preserve old code structure */ + + return 0; } -static int -rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda) +static int rfapiDeleteLocalPrefixes(struct rfapi_local_reg_delete_arg *cda) { - int rc = 0; - - if (cda->rfg) - { - if (cda->rfg->rfd) /* if not open, nothing to delete */ - rc = rfapiDeleteLocalPrefixesByRFD (cda, cda->rfg->rfd); - } - else - { - struct bgp *bgp = cda->bgp; - struct rfapi *h; - struct rfapi_cfg *rfapi_cfg; - - struct listnode *node; - struct rfapi_descriptor *rfd; - if (!bgp) - return ENXIO; - h = bgp->rfapi; - rfapi_cfg = bgp->rfapi_cfg; - if (!h || !rfapi_cfg) - return ENXIO; - vnc_zlog_debug_verbose ("%s: starting descriptor loop", __func__); - for (ALL_LIST_ELEMENTS_RO (&h->descriptors, node, rfd)) - { - rc = rfapiDeleteLocalPrefixesByRFD (cda, rfd); - } - } - return rc; + int rc = 0; + + if (cda->rfg) { + if (cda->rfg->rfd) /* if not open, nothing to delete */ + rc = rfapiDeleteLocalPrefixesByRFD(cda, cda->rfg->rfd); + } else { + struct bgp *bgp = cda->bgp; + struct rfapi *h; + struct rfapi_cfg *rfapi_cfg; + + struct listnode *node; + struct rfapi_descriptor *rfd; + if (!bgp) + return ENXIO; + h = bgp->rfapi; + rfapi_cfg = bgp->rfapi_cfg; + if (!h || !rfapi_cfg) + return ENXIO; + vnc_zlog_debug_verbose("%s: starting descriptor loop", + __func__); + for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) { + rc = rfapiDeleteLocalPrefixesByRFD(cda, rfd); + } + } + return rc; } /* @@ -3643,108 +3345,98 @@ rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda) * * Deletes local and remote prefixes that match */ -static void -clear_vnc_prefix (struct rfapi_local_reg_delete_arg *cda) +static void clear_vnc_prefix(struct rfapi_local_reg_delete_arg *cda) { - struct prefix pfx_un; - struct prefix pfx_vn; - - struct prefix *pUN = NULL; - struct prefix *pVN = NULL; - struct prefix *pPrefix = NULL; - - struct rfapi_import_table *it = NULL; - - /* - * Delete matching remote prefixes in holddown - */ - if (cda->vn_address.addr_family) - { - if (!rfapiRaddr2Qprefix (&cda->vn_address, &pfx_vn)) - pVN = &pfx_vn; - } - if (cda->un_address.addr_family) - { - if (!rfapiRaddr2Qprefix (&cda->un_address, &pfx_un)) - pUN = &pfx_un; - } - if (cda->prefix.family) - { - pPrefix = &cda->prefix; - } - if (cda->rfg) - { - it = cda->rfg->rfapi_import_table; - } - rfapiDeleteRemotePrefixes (pUN, pVN, pPrefix, it, - 0, 1, &cda->remote_active_pfx_count, - &cda->remote_active_nve_count, - &cda->remote_holddown_pfx_count, - &cda->remote_holddown_nve_count); - - /* - * Now do local prefixes - */ - rfapiDeleteLocalPrefixes (cda); + struct prefix pfx_un; + struct prefix pfx_vn; + + struct prefix *pUN = NULL; + struct prefix *pVN = NULL; + struct prefix *pPrefix = NULL; + + struct rfapi_import_table *it = NULL; + + /* + * Delete matching remote prefixes in holddown + */ + if (cda->vn_address.addr_family) { + if (!rfapiRaddr2Qprefix(&cda->vn_address, &pfx_vn)) + pVN = &pfx_vn; + } + if (cda->un_address.addr_family) { + if (!rfapiRaddr2Qprefix(&cda->un_address, &pfx_un)) + pUN = &pfx_un; + } + if (cda->prefix.family) { + pPrefix = &cda->prefix; + } + if (cda->rfg) { + it = cda->rfg->rfapi_import_table; + } + rfapiDeleteRemotePrefixes( + pUN, pVN, pPrefix, it, 0, 1, &cda->remote_active_pfx_count, + &cda->remote_active_nve_count, &cda->remote_holddown_pfx_count, + &cda->remote_holddown_nve_count); + + /* + * Now do local prefixes + */ + rfapiDeleteLocalPrefixes(cda); } -static void -print_cleared_stats (struct rfapi_local_reg_delete_arg *cda) +static void print_cleared_stats(struct rfapi_local_reg_delete_arg *cda) { - struct vty *vty = cda->vty; /* for benefit of VTYNL */ - - /* Our special element-deleting function counts nves */ - if (cda->nves) - { - skiplist_free (cda->nves); - cda->nves = NULL; - } - if (cda->failed_pfx_count) - vty_out (vty, "Failed to delete %d prefixes\n", - cda->failed_pfx_count); - - /* left as "prefixes" even in single case for ease of machine parsing */ - vty_out (vty, - "[Local] Cleared %u registrations, %u prefixes, %u responses from %d NVEs\n", - cda->reg_count, cda->pfx_count, cda->query_count,cda->nve_count); - -/* - * We don't currently allow deletion of active remote prefixes from - * the command line - */ - - vty_out (vty, "[Holddown] Cleared %u prefixes from %u NVEs\n", - cda->remote_holddown_pfx_count,cda->remote_holddown_nve_count); + struct vty *vty = cda->vty; /* for benefit of VTYNL */ + + /* Our special element-deleting function counts nves */ + if (cda->nves) { + skiplist_free(cda->nves); + cda->nves = NULL; + } + if (cda->failed_pfx_count) + vty_out(vty, "Failed to delete %d prefixes\n", + cda->failed_pfx_count); + + /* left as "prefixes" even in single case for ease of machine parsing */ + vty_out(vty, + "[Local] Cleared %u registrations, %u prefixes, %u responses from %d NVEs\n", + cda->reg_count, cda->pfx_count, cda->query_count, + cda->nve_count); + + /* + * We don't currently allow deletion of active remote prefixes from + * the command line + */ + + vty_out(vty, "[Holddown] Cleared %u prefixes from %u NVEs\n", + cda->remote_holddown_pfx_count, cda->remote_holddown_nve_count); } -/* +/* * Caller has already deleted registrations and queries for this/these * NVEs. Now we just have to close their descriptors. */ -static void -clear_vnc_nve_closer (struct rfapi_local_reg_delete_arg *cda) +static void clear_vnc_nve_closer(struct rfapi_local_reg_delete_arg *cda) { - struct skiplist *sl = cda->nves; /* contains affected NVEs */ - struct nve_addr *pKey; - struct nve_addr *pValue; - void *cursor = NULL; - int rc; - - if (!sl) - return; - - for (rc = skiplist_next (sl, (void **) &pKey, (void **) &pValue, &cursor); - !rc; - rc = skiplist_next (sl, (void **) &pKey, (void **) &pValue, &cursor)) - { - - if (pValue->rfd) - { - ((struct rfapi_descriptor *) pValue->rfd)->flags |= - RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY; - rfapi_close (pValue->rfd); - } - } + struct skiplist *sl = cda->nves; /* contains affected NVEs */ + struct nve_addr *pKey; + struct nve_addr *pValue; + void *cursor = NULL; + int rc; + + if (!sl) + return; + + for (rc = skiplist_next(sl, (void **)&pKey, (void **)&pValue, &cursor); + !rc; rc = skiplist_next(sl, (void **)&pKey, (void **)&pValue, + &cursor)) { + + if (pValue->rfd) { + ((struct rfapi_descriptor *)pValue->rfd)->flags |= + RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY; + rfapi_close(pValue->rfd); + } + } } DEFUN (clear_vnc_nve_all, @@ -3756,21 +3448,22 @@ DEFUN (clear_vnc_nve_all, "For all NVEs\n") { - struct rfapi_local_reg_delete_arg cda; - int rc; + struct rfapi_local_reg_delete_arg cda; + int rc; - if ((rc = parse_deleter_args (vty, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &cda))) - return rc; + if ((rc = parse_deleter_args(vty, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, &cda))) + return rc; - cda.vty = vty; + cda.vty = vty; - clear_vnc_responses (&cda); - clear_vnc_prefix (&cda); - clear_vnc_nve_closer (&cda); + clear_vnc_responses(&cda); + clear_vnc_prefix(&cda); + clear_vnc_nve_closer(&cda); - print_cleared_stats (&cda); + print_cleared_stats(&cda); - return 0; + return 0; } DEFUN (clear_vnc_nve_vn_un, @@ -3788,22 +3481,22 @@ DEFUN (clear_vnc_nve_vn_un, "UN IPv4 interface address\n" "UN IPv6 interface address\n") { - struct rfapi_local_reg_delete_arg cda; - int rc; + struct rfapi_local_reg_delete_arg cda; + int rc; - if ((rc = - parse_deleter_tokens (vty, NULL, NULL, argv[4], argv[6], NULL, NULL, NULL, NULL, &cda))) - return rc; + if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[4], argv[6], NULL, + NULL, NULL, NULL, &cda))) + return rc; - cda.vty = vty; + cda.vty = vty; - clear_vnc_responses (&cda); - clear_vnc_prefix (&cda); - clear_vnc_nve_closer (&cda); + clear_vnc_responses(&cda); + clear_vnc_prefix(&cda); + clear_vnc_nve_closer(&cda); - print_cleared_stats (&cda); + print_cleared_stats(&cda); - return 0; + return 0; } DEFUN (clear_vnc_nve_un_vn, @@ -3821,22 +3514,22 @@ DEFUN (clear_vnc_nve_un_vn, "VN IPv4 interface address\n" "VN IPv6 interface address\n") { - struct rfapi_local_reg_delete_arg cda; - int rc; + struct rfapi_local_reg_delete_arg cda; + int rc; - if ((rc = - parse_deleter_tokens (vty, NULL, NULL, argv[6], argv[4], NULL, NULL, NULL, NULL, &cda))) - return rc; + if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[6], argv[4], NULL, + NULL, NULL, NULL, &cda))) + return rc; - cda.vty = vty; + cda.vty = vty; - clear_vnc_responses (&cda); - clear_vnc_prefix (&cda); - clear_vnc_nve_closer (&cda); + clear_vnc_responses(&cda); + clear_vnc_prefix(&cda); + clear_vnc_nve_closer(&cda); - print_cleared_stats (&cda); + print_cleared_stats(&cda); - return 0; + return 0; } DEFUN (clear_vnc_nve_vn, @@ -3850,20 +3543,21 @@ DEFUN (clear_vnc_nve_vn, "VN IPv4 interface address\n" "VN IPv6 interface address\n") { - struct rfapi_local_reg_delete_arg cda; - int rc; + struct rfapi_local_reg_delete_arg cda; + int rc; - if ((rc = parse_deleter_tokens (vty, NULL, NULL, argv[4], NULL, NULL, NULL, NULL, NULL, &cda))) - return rc; + if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[4], NULL, NULL, + NULL, NULL, NULL, &cda))) + return rc; - cda.vty = vty; + cda.vty = vty; - clear_vnc_responses (&cda); - clear_vnc_prefix (&cda); - clear_vnc_nve_closer (&cda); + clear_vnc_responses(&cda); + clear_vnc_prefix(&cda); + clear_vnc_nve_closer(&cda); - print_cleared_stats (&cda); - return 0; + print_cleared_stats(&cda); + return 0; } DEFUN (clear_vnc_nve_un, @@ -3877,20 +3571,21 @@ DEFUN (clear_vnc_nve_un, "UN IPv4 interface address\n" "UN IPv6 interface address\n") { - struct rfapi_local_reg_delete_arg cda; - int rc; + struct rfapi_local_reg_delete_arg cda; + int rc; - if ((rc = parse_deleter_tokens (vty, NULL, NULL, NULL, argv[4], NULL, NULL, NULL, NULL, &cda))) - return rc; + if ((rc = parse_deleter_tokens(vty, NULL, NULL, NULL, argv[4], NULL, + NULL, NULL, NULL, &cda))) + return rc; - cda.vty = vty; + cda.vty = vty; - clear_vnc_responses (&cda); - clear_vnc_prefix (&cda); - clear_vnc_nve_closer (&cda); + clear_vnc_responses(&cda); + clear_vnc_prefix(&cda); + clear_vnc_nve_closer(&cda); - print_cleared_stats (&cda); - return 0; + print_cleared_stats(&cda); + return 0; } /*------------------------------------------------- @@ -3919,16 +3614,16 @@ DEFUN (clear_vnc_prefix_vn_un, "UN IPv4 interface address\n" "UN IPv6 interface address\n") { - struct rfapi_local_reg_delete_arg cda; - int rc; - - if ((rc = - parse_deleter_tokens (vty, NULL, argv[3], argv[5], argv[7], NULL, NULL, NULL, NULL, &cda))) - return rc; - cda.vty = vty; - clear_vnc_prefix (&cda); - print_cleared_stats (&cda); - return 0; + struct rfapi_local_reg_delete_arg cda; + int rc; + + if ((rc = parse_deleter_tokens(vty, NULL, argv[3], argv[5], argv[7], + NULL, NULL, NULL, NULL, &cda))) + return rc; + cda.vty = vty; + clear_vnc_prefix(&cda); + print_cleared_stats(&cda); + return 0; } DEFUN (clear_vnc_prefix_un_vn, @@ -3949,16 +3644,16 @@ DEFUN (clear_vnc_prefix_un_vn, "VN IPv4 interface address\n" "VN IPv6 interface address\n") { - struct rfapi_local_reg_delete_arg cda; - int rc; - - if ((rc = - parse_deleter_tokens (vty, NULL, argv[3], argv[7], argv[5], NULL, NULL, NULL, NULL, &cda))) - return rc; - cda.vty = vty; - clear_vnc_prefix (&cda); - print_cleared_stats (&cda); - return 0; + struct rfapi_local_reg_delete_arg cda; + int rc; + + if ((rc = parse_deleter_tokens(vty, NULL, argv[3], argv[7], argv[5], + NULL, NULL, NULL, NULL, &cda))) + return rc; + cda.vty = vty; + clear_vnc_prefix(&cda); + print_cleared_stats(&cda); + return 0; } DEFUN (clear_vnc_prefix_un, @@ -3975,16 +3670,16 @@ DEFUN (clear_vnc_prefix_un, "UN IPv4 interface address\n" "UN IPv6 interface address\n") { - struct rfapi_local_reg_delete_arg cda; - int rc; - - if ((rc = - parse_deleter_tokens (vty, NULL, argv[3], NULL, argv[5], NULL, NULL, NULL, NULL, &cda))) - return rc; - cda.vty = vty; - clear_vnc_prefix (&cda); - print_cleared_stats (&cda); - return 0; + struct rfapi_local_reg_delete_arg cda; + int rc; + + if ((rc = parse_deleter_tokens(vty, NULL, argv[3], NULL, argv[5], NULL, + NULL, NULL, NULL, &cda))) + return rc; + cda.vty = vty; + clear_vnc_prefix(&cda); + print_cleared_stats(&cda); + return 0; } DEFUN (clear_vnc_prefix_vn, @@ -4001,16 +3696,16 @@ DEFUN (clear_vnc_prefix_vn, "VN IPv4 interface address\n" "VN IPv6 interface address\n") { - struct rfapi_local_reg_delete_arg cda; - int rc; - - if ((rc = - parse_deleter_tokens (vty, NULL, argv[3], argv[5], NULL, NULL, NULL, NULL, NULL, &cda))) - return rc; - cda.vty = vty; - clear_vnc_prefix (&cda); - print_cleared_stats (&cda); - return 0; + struct rfapi_local_reg_delete_arg cda; + int rc; + + if ((rc = parse_deleter_tokens(vty, NULL, argv[3], argv[5], NULL, NULL, + NULL, NULL, NULL, &cda))) + return rc; + cda.vty = vty; + clear_vnc_prefix(&cda); + print_cleared_stats(&cda); + return 0; } DEFUN (clear_vnc_prefix_all, @@ -4024,15 +3719,16 @@ DEFUN (clear_vnc_prefix_all, "IPv6 prefix\n" "From any NVE\n") { - struct rfapi_local_reg_delete_arg cda; - int rc; - - if ((rc = parse_deleter_tokens (vty, NULL, argv[3], NULL, NULL, NULL, NULL, NULL, NULL, &cda))) - return rc; - cda.vty = vty; - clear_vnc_prefix (&cda); - print_cleared_stats (&cda); - return 0; + struct rfapi_local_reg_delete_arg cda; + int rc; + + if ((rc = parse_deleter_tokens(vty, NULL, argv[3], NULL, NULL, NULL, + NULL, NULL, NULL, &cda))) + return rc; + cda.vty = vty; + clear_vnc_prefix(&cda); + print_cleared_stats(&cda); + return 0; } /*------------------------------------------------- @@ -4063,18 +3759,17 @@ DEFUN (clear_vnc_mac_vn_un, "UN IPv4 interface address\n" "UN IPv6 interface address\n") { - struct rfapi_local_reg_delete_arg cda; - int rc; - - /* pfx vn un L2 VNI */ - if ((rc = - parse_deleter_tokens (vty, NULL, NULL, argv[7], argv[9], argv[3], argv[5], - NULL, NULL, &cda))) - return rc; - cda.vty = vty; - clear_vnc_prefix (&cda); - print_cleared_stats (&cda); - return 0; + struct rfapi_local_reg_delete_arg cda; + int rc; + + /* pfx vn un L2 VNI */ + if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[7], argv[9], + argv[3], argv[5], NULL, NULL, &cda))) + return rc; + cda.vty = vty; + clear_vnc_prefix(&cda); + print_cleared_stats(&cda); + return 0; } DEFUN (clear_vnc_mac_un_vn, @@ -4097,18 +3792,17 @@ DEFUN (clear_vnc_mac_un_vn, "VN IPv4 interface address\n" "VN IPv6 interface address\n") { - struct rfapi_local_reg_delete_arg cda; - int rc; - - /* pfx vn un L2 VNI */ - if ((rc = - parse_deleter_tokens (vty, NULL, NULL, argv[9], argv[7], argv[3], argv[5], - NULL, NULL, &cda))) - return rc; - cda.vty = vty; - clear_vnc_prefix (&cda); - print_cleared_stats (&cda); - return 0; + struct rfapi_local_reg_delete_arg cda; + int rc; + + /* pfx vn un L2 VNI */ + if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[9], argv[7], + argv[3], argv[5], NULL, NULL, &cda))) + return rc; + cda.vty = vty; + clear_vnc_prefix(&cda); + print_cleared_stats(&cda); + return 0; } DEFUN (clear_vnc_mac_un, @@ -4127,17 +3821,17 @@ DEFUN (clear_vnc_mac_un, "UN IPv4 interface address\n" "UN IPv6 interface address\n") { - struct rfapi_local_reg_delete_arg cda; - int rc; - - /* pfx vn un L2 VNI */ - if ((rc = - parse_deleter_tokens (vty, NULL, NULL, NULL, argv[7], argv[3], argv[5], NULL, NULL, &cda))) - return rc; - cda.vty = vty; - clear_vnc_prefix (&cda); - print_cleared_stats (&cda); - return 0; + struct rfapi_local_reg_delete_arg cda; + int rc; + + /* pfx vn un L2 VNI */ + if ((rc = parse_deleter_tokens(vty, NULL, NULL, NULL, argv[7], argv[3], + argv[5], NULL, NULL, &cda))) + return rc; + cda.vty = vty; + clear_vnc_prefix(&cda); + print_cleared_stats(&cda); + return 0; } DEFUN (clear_vnc_mac_vn, @@ -4156,17 +3850,17 @@ DEFUN (clear_vnc_mac_vn, "VN IPv4 interface address\n" "VN IPv6 interface address\n") { - struct rfapi_local_reg_delete_arg cda; - int rc; - - /* pfx vn un L2 VNI */ - if ((rc = - parse_deleter_tokens (vty, NULL, NULL, argv[7], NULL, argv[3], argv[5], NULL, NULL, &cda))) - return rc; - cda.vty = vty; - clear_vnc_prefix (&cda); - print_cleared_stats (&cda); - return 0; + struct rfapi_local_reg_delete_arg cda; + int rc; + + /* pfx vn un L2 VNI */ + if ((rc = parse_deleter_tokens(vty, NULL, NULL, argv[7], NULL, argv[3], + argv[5], NULL, NULL, &cda))) + return rc; + cda.vty = vty; + clear_vnc_prefix(&cda); + print_cleared_stats(&cda); + return 0; } DEFUN (clear_vnc_mac_all, @@ -4182,17 +3876,17 @@ DEFUN (clear_vnc_mac_all, "Virtual network identifier\n" "From any NVE\n") { - struct rfapi_local_reg_delete_arg cda; - int rc; - - /* pfx vn un L2 VNI */ - if ((rc = - parse_deleter_tokens (vty, NULL, NULL, NULL, NULL, argv[3], argv[5], NULL, NULL, &cda))) - return rc; - cda.vty = vty; - clear_vnc_prefix (&cda); - print_cleared_stats (&cda); - return 0; + struct rfapi_local_reg_delete_arg cda; + int rc; + + /* pfx vn un L2 VNI */ + if ((rc = parse_deleter_tokens(vty, NULL, NULL, NULL, NULL, argv[3], + argv[5], NULL, NULL, &cda))) + return rc; + cda.vty = vty; + clear_vnc_prefix(&cda); + print_cleared_stats(&cda); + return 0; } /*------------------------------------------------- @@ -4223,18 +3917,17 @@ DEFUN (clear_vnc_mac_vn_un_prefix, "IPv4 prefix\n" "IPv6 prefix\n") { - struct rfapi_local_reg_delete_arg cda; - int rc; - - /* pfx vn un L2 VNI */ - if ((rc = - parse_deleter_tokens (vty, NULL, argv[11], argv[7], argv[9], argv[3], argv[5], - NULL, NULL, &cda))) - return rc; - cda.vty = vty; - clear_vnc_prefix (&cda); - print_cleared_stats (&cda); - return 0; + struct rfapi_local_reg_delete_arg cda; + int rc; + + /* pfx vn un L2 VNI */ + if ((rc = parse_deleter_tokens(vty, NULL, argv[11], argv[7], argv[9], + argv[3], argv[5], NULL, NULL, &cda))) + return rc; + cda.vty = vty; + clear_vnc_prefix(&cda); + print_cleared_stats(&cda); + return 0; } DEFUN (clear_vnc_mac_un_vn_prefix, @@ -4265,18 +3958,17 @@ DEFUN (clear_vnc_mac_un_vn_prefix, "IPv4 prefix\n" "IPv6 prefix\n") { - struct rfapi_local_reg_delete_arg cda; - int rc; - - /* pfx vn un L2 VNI */ - if ((rc = - parse_deleter_tokens (vty, NULL, argv[11], argv[9], argv[7], argv[3], argv[5], - NULL, NULL, &cda))) - return rc; - cda.vty = vty; - clear_vnc_prefix (&cda); - print_cleared_stats (&cda); - return 0; + struct rfapi_local_reg_delete_arg cda; + int rc; + + /* pfx vn un L2 VNI */ + if ((rc = parse_deleter_tokens(vty, NULL, argv[11], argv[9], argv[7], + argv[3], argv[5], NULL, NULL, &cda))) + return rc; + cda.vty = vty; + clear_vnc_prefix(&cda); + print_cleared_stats(&cda); + return 0; } DEFUN (clear_vnc_mac_un_prefix, @@ -4299,18 +3991,17 @@ DEFUN (clear_vnc_mac_un_prefix, "IPv4 Prefix\n" "IPv6 Prefix\n") { - struct rfapi_local_reg_delete_arg cda; - int rc; - - /* pfx vn un L2 VNI */ - if ((rc = - parse_deleter_tokens (vty, NULL, argv[9], NULL, argv[7], argv[3], argv[5], - NULL, NULL, &cda))) - return rc; - cda.vty = vty; - clear_vnc_prefix (&cda); - print_cleared_stats (&cda); - return 0; + struct rfapi_local_reg_delete_arg cda; + int rc; + + /* pfx vn un L2 VNI */ + if ((rc = parse_deleter_tokens(vty, NULL, argv[9], NULL, argv[7], + argv[3], argv[5], NULL, NULL, &cda))) + return rc; + cda.vty = vty; + clear_vnc_prefix(&cda); + print_cleared_stats(&cda); + return 0; } DEFUN (clear_vnc_mac_vn_prefix, @@ -4333,18 +4024,17 @@ DEFUN (clear_vnc_mac_vn_prefix, "IPv4 Prefix\n" "IPv6 Prefix\n") { - struct rfapi_local_reg_delete_arg cda; - int rc; - - /* pfx vn un L2 VNI */ - if ((rc = - parse_deleter_tokens (vty, NULL, argv[9], argv[7], NULL, argv[3], argv[5], - NULL, NULL, &cda))) - return rc; - cda.vty = vty; - clear_vnc_prefix (&cda); - print_cleared_stats (&cda); - return 0; + struct rfapi_local_reg_delete_arg cda; + int rc; + + /* pfx vn un L2 VNI */ + if ((rc = parse_deleter_tokens(vty, NULL, argv[9], argv[7], NULL, + argv[3], argv[5], NULL, NULL, &cda))) + return rc; + cda.vty = vty; + clear_vnc_prefix(&cda); + print_cleared_stats(&cda); + return 0; } DEFUN (clear_vnc_mac_all_prefix, @@ -4363,17 +4053,17 @@ DEFUN (clear_vnc_mac_all_prefix, "VN IPv4 interface address\n" "VN IPv6 interface address\n") { - struct rfapi_local_reg_delete_arg cda; - int rc; - - /* pfx vn un L2 VNI */ - if ((rc = - parse_deleter_tokens (vty, NULL, argv[7], NULL, NULL, argv[3], argv[5], NULL, NULL, &cda))) - return rc; - cda.vty = vty; - clear_vnc_prefix (&cda); - print_cleared_stats (&cda); - return 0; + struct rfapi_local_reg_delete_arg cda; + int rc; + + /* pfx vn un L2 VNI */ + if ((rc = parse_deleter_tokens(vty, NULL, argv[7], NULL, NULL, argv[3], + argv[5], NULL, NULL, &cda))) + return rc; + cda.vty = vty; + clear_vnc_prefix(&cda); + print_cleared_stats(&cda); + return 0; } /************************************************************************ @@ -4382,222 +4072,216 @@ DEFUN (clear_vnc_mac_all_prefix, /* copied from rfp_vty.c */ -static int -check_and_display_is_vnc_running (struct vty *vty) +static int check_and_display_is_vnc_running(struct vty *vty) { - if (!bgp_rfapi_is_vnc_configured (NULL)) - return 1; /* is running */ - - if (vty) - { - vty_out (vty, - "VNC is not configured. (There are no configured BGP VPN SAFI peers.)\n"); - } - return 0; /* not running */ + if (!bgp_rfapi_is_vnc_configured(NULL)) + return 1; /* is running */ + + if (vty) { + vty_out(vty, + "VNC is not configured. (There are no configured BGP VPN SAFI peers.)\n"); + } + return 0; /* not running */ } -static int -rfapi_vty_show_nve_summary (struct vty *vty, show_nve_summary_t show_type) +static int rfapi_vty_show_nve_summary(struct vty *vty, + show_nve_summary_t show_type) { - struct bgp *bgp_default = bgp_get_default (); - struct rfapi *h; - int is_vnc_running = !bgp_rfapi_is_vnc_configured (bgp_default); - - int active_local_routes; - int active_remote_routes; - int holddown_remote_routes; - int imported_remote_routes; - - if (!bgp_default) - goto notcfg; - - h = bgp_default->rfapi; - - if (!h) - goto notcfg; - - /* don't show local info if not running RFP */ - if (is_vnc_running || show_type == SHOW_NVE_SUMMARY_REGISTERED) - { - - switch (show_type) - { - - case SHOW_NVE_SUMMARY_ACTIVE_NVES: - vty_out (vty, "%-24s ", "NVEs:"); - vty_out (vty, "%-8s %-8u ", "Active:", h->descriptors.count); - vty_out (vty, "%-8s %-8u ", "Maximum:", h->stat.max_descriptors); - vty_out (vty, "%-8s %-8u", "Unknown:", h->stat.count_unknown_nves); - break; - - case SHOW_NVE_SUMMARY_REGISTERED: - /* - * NB: With the introduction of L2 route support, we no - * longer have a one-to-one correspondence between - * locally-originated route advertisements and routes in - * the import tables that have local origin. This - * discrepancy arises because a single advertisement - * may contain both an IP prefix and a MAC address. - * Such an advertisement results in two import table - * entries: one indexed by IP prefix, the other indexed - * by MAC address. - * - * TBD: update computation and display of registration - * statistics to reflect the underlying semantics. - */ - if (is_vnc_running) - { - vty_out (vty, "%-24s ", "Registrations:"); - vty_out (vty, "%-8s %-8u ", "Active:", - rfapiApCountAll (bgp_default)); - vty_out (vty, "%-8s %-8u ", "Failed:", - h->stat.count_registrations_failed); - vty_out (vty, "%-8s %-8u", "Total:", - h->stat.count_registrations); - vty_out (vty, "\n"); - } - vty_out (vty, "%-24s ", "Prefixes registered:"); - vty_out (vty, "\n"); - - rfapiCountAllItRoutes (&active_local_routes, - &active_remote_routes, - &holddown_remote_routes, - &imported_remote_routes); - - /* local */ - if (is_vnc_running) - { - vty_out (vty, " %-20s ", "Locally:"); - vty_out (vty, "%-8s %-8u ", "Active:", active_local_routes); - vty_out (vty, "\n"); - } - - - vty_out (vty, " %-20s ", "Remotely:"); - vty_out (vty, "%-8s %-8u", "Active:", active_remote_routes); - vty_out (vty, "\n"); - vty_out (vty, " %-20s ", "In Holddown:"); - vty_out (vty, "%-8s %-8u", "Active:", holddown_remote_routes); - vty_out (vty, "\n"); - vty_out (vty, " %-20s ", "Imported:"); - vty_out (vty, "%-8s %-8u", "Active:", imported_remote_routes); - break; - - case SHOW_NVE_SUMMARY_QUERIES: - vty_out (vty, "%-24s ", "Queries:"); - vty_out (vty, "%-8s %-8u ", "Active:", rfapi_monitor_count (NULL)); - vty_out (vty, "%-8s %-8u ", "Failed:", - h->stat.count_queries_failed); - vty_out (vty, "%-8s %-8u", "Total:", h->stat.count_queries); - break; - - case SHOW_NVE_SUMMARY_RESPONSES: - rfapiRibShowResponsesSummary (vty); - - default: - break; - } - vty_out (vty, "\n"); - } - return 0; + struct bgp *bgp_default = bgp_get_default(); + struct rfapi *h; + int is_vnc_running = !bgp_rfapi_is_vnc_configured(bgp_default); + + int active_local_routes; + int active_remote_routes; + int holddown_remote_routes; + int imported_remote_routes; + + if (!bgp_default) + goto notcfg; + + h = bgp_default->rfapi; + + if (!h) + goto notcfg; + + /* don't show local info if not running RFP */ + if (is_vnc_running || show_type == SHOW_NVE_SUMMARY_REGISTERED) { + + switch (show_type) { + + case SHOW_NVE_SUMMARY_ACTIVE_NVES: + vty_out(vty, "%-24s ", "NVEs:"); + vty_out(vty, "%-8s %-8u ", + "Active:", h->descriptors.count); + vty_out(vty, "%-8s %-8u ", + "Maximum:", h->stat.max_descriptors); + vty_out(vty, "%-8s %-8u", + "Unknown:", h->stat.count_unknown_nves); + break; + + case SHOW_NVE_SUMMARY_REGISTERED: + /* + * NB: With the introduction of L2 route support, we no + * longer have a one-to-one correspondence between + * locally-originated route advertisements and routes in + * the import tables that have local origin. This + * discrepancy arises because a single advertisement + * may contain both an IP prefix and a MAC address. + * Such an advertisement results in two import table + * entries: one indexed by IP prefix, the other indexed + * by MAC address. + * + * TBD: update computation and display of registration + * statistics to reflect the underlying semantics. + */ + if (is_vnc_running) { + vty_out(vty, "%-24s ", "Registrations:"); + vty_out(vty, "%-8s %-8u ", "Active:", + rfapiApCountAll(bgp_default)); + vty_out(vty, "%-8s %-8u ", "Failed:", + h->stat.count_registrations_failed); + vty_out(vty, "%-8s %-8u", + "Total:", h->stat.count_registrations); + vty_out(vty, "\n"); + } + vty_out(vty, "%-24s ", "Prefixes registered:"); + vty_out(vty, "\n"); + + rfapiCountAllItRoutes(&active_local_routes, + &active_remote_routes, + &holddown_remote_routes, + &imported_remote_routes); + + /* local */ + if (is_vnc_running) { + vty_out(vty, " %-20s ", "Locally:"); + vty_out(vty, "%-8s %-8u ", + "Active:", active_local_routes); + vty_out(vty, "\n"); + } + + + vty_out(vty, " %-20s ", "Remotely:"); + vty_out(vty, "%-8s %-8u", + "Active:", active_remote_routes); + vty_out(vty, "\n"); + vty_out(vty, " %-20s ", "In Holddown:"); + vty_out(vty, "%-8s %-8u", + "Active:", holddown_remote_routes); + vty_out(vty, "\n"); + vty_out(vty, " %-20s ", "Imported:"); + vty_out(vty, "%-8s %-8u", + "Active:", imported_remote_routes); + break; + + case SHOW_NVE_SUMMARY_QUERIES: + vty_out(vty, "%-24s ", "Queries:"); + vty_out(vty, "%-8s %-8u ", + "Active:", rfapi_monitor_count(NULL)); + vty_out(vty, "%-8s %-8u ", + "Failed:", h->stat.count_queries_failed); + vty_out(vty, "%-8s %-8u", + "Total:", h->stat.count_queries); + break; + + case SHOW_NVE_SUMMARY_RESPONSES: + rfapiRibShowResponsesSummary(vty); + + default: + break; + } + vty_out(vty, "\n"); + } + return 0; notcfg: - vty_out (vty, "VNC is not configured.\n"); - return CMD_WARNING; + vty_out(vty, "VNC is not configured.\n"); + return CMD_WARNING; } -static int -rfapi_show_nves ( - struct vty *vty, - struct prefix *vn_prefix, - struct prefix *un_prefix) +static int rfapi_show_nves(struct vty *vty, struct prefix *vn_prefix, + struct prefix *un_prefix) { - //struct hash *rfds; - //struct rfp_rfapi_descriptor_param param; - - struct bgp *bgp_default = bgp_get_default (); - struct rfapi *h; - struct listnode *node; - struct rfapi_descriptor *rfd; - - int total = 0; - int printed = 0; - int rc; - - if (!bgp_default) - goto notcfg; - - h = bgp_default->rfapi; - - if (!h) - goto notcfg; - - rc = rfapi_vty_show_nve_summary (vty, SHOW_NVE_SUMMARY_ACTIVE_NVES); - if (rc) - return rc; - - for (ALL_LIST_ELEMENTS_RO (&h->descriptors, node, rfd)) - { - struct prefix pfx; - char vn_addr_buf[INET6_ADDRSTRLEN] = - { - 0,}; - char un_addr_buf[INET6_ADDRSTRLEN] = - { - 0,}; - char age[10]; - - ++total; - - if (vn_prefix) - { - assert (!rfapiRaddr2Qprefix (&rfd->vn_addr, &pfx)); - if (!prefix_match (vn_prefix, &pfx)) - continue; - } - - if (un_prefix) - { - assert (!rfapiRaddr2Qprefix (&rfd->un_addr, &pfx)); - if (!prefix_match (un_prefix, &pfx)) - continue; - } - - rfapiRfapiIpAddr2Str (&rfd->vn_addr, vn_addr_buf, INET6_ADDRSTRLEN); - rfapiRfapiIpAddr2Str (&rfd->un_addr, un_addr_buf, INET6_ADDRSTRLEN); - - if (!printed) - { - /* print out a header */ - vty_out (vty, - " Active Next Hops\n"); - vty_out (vty, "%-15s %-15s %-5s %-5s %-6s %-6s %s\n", - "VN Address", - "UN Address", - "Regis", "Resps", "Reach", "Remove", "Age"); - } - - ++printed; - - vty_out (vty, "%-15s %-15s %-5u %-5u %-6u %-6u %s\n", - vn_addr_buf, - un_addr_buf, - rfapiApCount (rfd), - rfapi_monitor_count (rfd), - rfd->stat_count_nh_reachable, - rfd->stat_count_nh_removal, - rfapiFormatAge(rfd->open_time, age, 10)); - } - - if (printed > 0 || vn_prefix || un_prefix) - vty_out (vty, "Displayed %d out of %d active NVEs\n", - printed, total); - - return 0; + // struct hash *rfds; + // struct rfp_rfapi_descriptor_param param; + + struct bgp *bgp_default = bgp_get_default(); + struct rfapi *h; + struct listnode *node; + struct rfapi_descriptor *rfd; + + int total = 0; + int printed = 0; + int rc; + + if (!bgp_default) + goto notcfg; + + h = bgp_default->rfapi; + + if (!h) + goto notcfg; + + rc = rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_ACTIVE_NVES); + if (rc) + return rc; + + for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) { + struct prefix pfx; + char vn_addr_buf[INET6_ADDRSTRLEN] = { + 0, + }; + char un_addr_buf[INET6_ADDRSTRLEN] = { + 0, + }; + char age[10]; + + ++total; + + if (vn_prefix) { + assert(!rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx)); + if (!prefix_match(vn_prefix, &pfx)) + continue; + } + + if (un_prefix) { + assert(!rfapiRaddr2Qprefix(&rfd->un_addr, &pfx)); + if (!prefix_match(un_prefix, &pfx)) + continue; + } + + rfapiRfapiIpAddr2Str(&rfd->vn_addr, vn_addr_buf, + INET6_ADDRSTRLEN); + rfapiRfapiIpAddr2Str(&rfd->un_addr, un_addr_buf, + INET6_ADDRSTRLEN); + + if (!printed) { + /* print out a header */ + vty_out(vty, + " Active Next Hops\n"); + vty_out(vty, "%-15s %-15s %-5s %-5s %-6s %-6s %s\n", + "VN Address", "UN Address", "Regis", "Resps", + "Reach", "Remove", "Age"); + } + + ++printed; + + vty_out(vty, "%-15s %-15s %-5u %-5u %-6u %-6u %s\n", + vn_addr_buf, un_addr_buf, rfapiApCount(rfd), + rfapi_monitor_count(rfd), rfd->stat_count_nh_reachable, + rfd->stat_count_nh_removal, + rfapiFormatAge(rfd->open_time, age, 10)); + } + + if (printed > 0 || vn_prefix || un_prefix) + vty_out(vty, "Displayed %d out of %d active NVEs\n", printed, + total); + + return 0; notcfg: - vty_out (vty, "VNC is not configured.\n"); - return CMD_WARNING; + vty_out(vty, "VNC is not configured.\n"); + return CMD_WARNING; } @@ -4608,15 +4292,15 @@ DEFUN (vnc_show_summary, VNC_SHOW_STR "Display VNC status summary\n") { - if (!check_and_display_is_vnc_running (vty)) - return CMD_SUCCESS; - bgp_rfapi_show_summary (bgp_get_default (), vty); - vty_out (vty, "\n"); - rfapi_vty_show_nve_summary (vty, SHOW_NVE_SUMMARY_ACTIVE_NVES); - rfapi_vty_show_nve_summary (vty, SHOW_NVE_SUMMARY_QUERIES); - rfapi_vty_show_nve_summary (vty, SHOW_NVE_SUMMARY_RESPONSES); - rfapi_vty_show_nve_summary (vty, SHOW_NVE_SUMMARY_REGISTERED); - return CMD_SUCCESS; + if (!check_and_display_is_vnc_running(vty)) + return CMD_SUCCESS; + bgp_rfapi_show_summary(bgp_get_default(), vty); + vty_out(vty, "\n"); + rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_ACTIVE_NVES); + rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_QUERIES); + rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_RESPONSES); + rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_REGISTERED); + return CMD_SUCCESS; } DEFUN (vnc_show_nves, @@ -4626,8 +4310,8 @@ DEFUN (vnc_show_nves, VNC_SHOW_STR "List known NVEs\n") { - rfapi_show_nves (vty, NULL, NULL); - return CMD_SUCCESS; + rfapi_show_nves(vty, NULL, NULL); + return CMD_SUCCESS; } DEFUN (vnc_show_nves_ptct, @@ -4641,75 +4325,65 @@ DEFUN (vnc_show_nves_ptct, "IPv4 interface address\n" "IPv6 interface address\n") { - struct prefix pfx; - - if (!check_and_display_is_vnc_running (vty)) - return CMD_SUCCESS; - - if (!str2prefix (argv[4]->arg, &pfx)) - { - vty_out (vty, "Malformed address \"%s\"\n", argv[4]->arg); - return CMD_WARNING; - } - if (pfx.family != AF_INET && pfx.family != AF_INET6) - { - vty_out (vty, "Invalid address \"%s\"\n", argv[4]->arg); - return CMD_WARNING; - } - - if (argv[3]->arg[0] == 'u') - { - rfapi_show_nves (vty, NULL, &pfx); - } - else - { - rfapi_show_nves (vty, &pfx, NULL); - } - - return CMD_SUCCESS; + struct prefix pfx; + + if (!check_and_display_is_vnc_running(vty)) + return CMD_SUCCESS; + + if (!str2prefix(argv[4]->arg, &pfx)) { + vty_out(vty, "Malformed address \"%s\"\n", argv[4]->arg); + return CMD_WARNING; + } + if (pfx.family != AF_INET && pfx.family != AF_INET6) { + vty_out(vty, "Invalid address \"%s\"\n", argv[4]->arg); + return CMD_WARNING; + } + + if (argv[3]->arg[0] == 'u') { + rfapi_show_nves(vty, NULL, &pfx); + } else { + rfapi_show_nves(vty, &pfx, NULL); + } + + return CMD_SUCCESS; } /* adapted from rfp_registration_cache_log() */ -static void -rfapi_show_registrations ( - struct vty *vty, - struct prefix *restrict_to, - int show_local, - int show_remote, - int show_holddown, - int show_imported) +static void rfapi_show_registrations(struct vty *vty, + struct prefix *restrict_to, int show_local, + int show_remote, int show_holddown, + int show_imported) { - int printed = 0; - - if (!vty) - return; - - rfapi_vty_show_nve_summary (vty, SHOW_NVE_SUMMARY_REGISTERED); - - if (show_local) - { - /* non-expiring, local */ - printed += rfapiShowRemoteRegistrations (vty, restrict_to, 0, 1, 0, 0); - } - if (show_remote) - { - /* non-expiring, non-local */ - printed += rfapiShowRemoteRegistrations (vty, restrict_to, 0, 0, 1, 0); - } - if (show_holddown) - { - /* expiring, including local */ - printed += rfapiShowRemoteRegistrations (vty, restrict_to, 1, 1, 1, 0); - } - if (show_imported) - { - /* non-expiring, non-local */ - printed += rfapiShowRemoteRegistrations (vty, restrict_to, 0, 0, 1, 1); - } - if (!printed) - { - vty_out (vty, "\n"); - } + int printed = 0; + + if (!vty) + return; + + rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_REGISTERED); + + if (show_local) { + /* non-expiring, local */ + printed += rfapiShowRemoteRegistrations(vty, restrict_to, 0, 1, + 0, 0); + } + if (show_remote) { + /* non-expiring, non-local */ + printed += rfapiShowRemoteRegistrations(vty, restrict_to, 0, 0, + 1, 0); + } + if (show_holddown) { + /* expiring, including local */ + printed += rfapiShowRemoteRegistrations(vty, restrict_to, 1, 1, + 1, 0); + } + if (show_imported) { + /* non-expiring, non-local */ + printed += rfapiShowRemoteRegistrations(vty, restrict_to, 0, 0, + 1, 1); + } + if (!printed) { + vty_out(vty, "\n"); + } } DEFUN (vnc_show_registrations_pfx, @@ -4722,24 +4396,20 @@ DEFUN (vnc_show_registrations_pfx, "Limit output to a particular IPv6 prefix\n" "Limit output to a particular IPv6 address\n") { - struct prefix p; - struct prefix *p_addr = NULL; - - if (argc > 3) - { - if (!str2prefix (argv[3]->arg, &p)) - { - vty_out (vty, "Invalid prefix: %s\n", argv[3]->arg); - return CMD_SUCCESS; - } - else - { - p_addr = &p; - } - } - - rfapi_show_registrations (vty, p_addr, 1, 1, 1, 1); - return CMD_SUCCESS; + struct prefix p; + struct prefix *p_addr = NULL; + + if (argc > 3) { + if (!str2prefix(argv[3]->arg, &p)) { + vty_out(vty, "Invalid prefix: %s\n", argv[3]->arg); + return CMD_SUCCESS; + } else { + p_addr = &p; + } + } + + rfapi_show_registrations(vty, p_addr, 1, 1, 1, 1); + return CMD_SUCCESS; } DEFUN (vnc_show_registrations_some_pfx, @@ -4757,56 +4427,50 @@ DEFUN (vnc_show_registrations_some_pfx, "Limit output to a particular prefix or address\n" "Limit output to a particular prefix or address\n") { - struct prefix p; - struct prefix *p_addr = NULL; - - int show_local = 0; - int show_remote = 0; - int show_holddown = 0; - int show_imported = 0; - - if (argc > 4) - { - if (!str2prefix (argv[4]->arg, &p)) - { - vty_out (vty, "Invalid prefix: %s\n", argv[4]->arg); - return CMD_SUCCESS; - } - else - { - p_addr = &p; - } - } - switch (argv[3]->arg[0]) - { - case 'a': - show_local = 1; - show_remote = 1; - show_holddown = 1; - show_imported = 1; - break; - - case 'h': - show_holddown = 1; - break; - - case 'i': - show_imported = 1; - break; - - case 'l': - show_local = 1; - break; - - case 'r': - show_remote = 1; - break; - } - - rfapi_show_registrations (vty, p_addr, - show_local, show_remote, show_holddown, - show_imported); - return CMD_SUCCESS; + struct prefix p; + struct prefix *p_addr = NULL; + + int show_local = 0; + int show_remote = 0; + int show_holddown = 0; + int show_imported = 0; + + if (argc > 4) { + if (!str2prefix(argv[4]->arg, &p)) { + vty_out(vty, "Invalid prefix: %s\n", argv[4]->arg); + return CMD_SUCCESS; + } else { + p_addr = &p; + } + } + switch (argv[3]->arg[0]) { + case 'a': + show_local = 1; + show_remote = 1; + show_holddown = 1; + show_imported = 1; + break; + + case 'h': + show_holddown = 1; + break; + + case 'i': + show_imported = 1; + break; + + case 'l': + show_local = 1; + break; + + case 'r': + show_remote = 1; + break; + } + + rfapi_show_registrations(vty, p_addr, show_local, show_remote, + show_holddown, show_imported); + return CMD_SUCCESS; } DEFUN (vnc_show_responses_pfx, @@ -4819,29 +4483,25 @@ DEFUN (vnc_show_responses_pfx, "Limit output to a particular IPv6 prefix\n" "Limit output to a particular IPv6 address\n" ) { - struct prefix p; - struct prefix *p_addr = NULL; - - if (argc > 3) - { - if (!str2prefix (argv[3]->arg, &p)) - { - vty_out (vty, "Invalid prefix: %s\n", argv[3]->arg); - return CMD_SUCCESS; - } - else - { - p_addr = &p; - } - } - rfapi_vty_show_nve_summary (vty, SHOW_NVE_SUMMARY_QUERIES); - - rfapiRibShowResponsesSummary (vty); - - rfapiRibShowResponses (vty, p_addr, 0); - rfapiRibShowResponses (vty, p_addr, 1); - - return CMD_SUCCESS; + struct prefix p; + struct prefix *p_addr = NULL; + + if (argc > 3) { + if (!str2prefix(argv[3]->arg, &p)) { + vty_out(vty, "Invalid prefix: %s\n", argv[3]->arg); + return CMD_SUCCESS; + } else { + p_addr = &p; + } + } + rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_QUERIES); + + rfapiRibShowResponsesSummary(vty); + + rfapiRibShowResponses(vty, p_addr, 0); + rfapiRibShowResponses(vty, p_addr, 1); + + return CMD_SUCCESS; } DEFUN (vnc_show_responses_some_pfx, @@ -4856,49 +4516,44 @@ DEFUN (vnc_show_responses_some_pfx, "Limit output to a particular IPv6 prefix\n" "Limit output to a particular IPV6 address\n") { - struct prefix p; - struct prefix *p_addr = NULL; - - int show_active = 0; - int show_removed = 0; - - if (!check_and_display_is_vnc_running (vty)) - return CMD_SUCCESS; - - if (argc > 4) - { - if (!str2prefix (argv[4]->arg, &p)) - { - vty_out (vty, "Invalid prefix: %s\n", argv[4]->arg); - return CMD_SUCCESS; - } - else - { - p_addr = &p; - } - } - - switch (argv[3]->arg[0]) - { - case 'a': - show_active = 1; - break; - - case 'r': - show_removed = 1; - break; - } - - rfapi_vty_show_nve_summary (vty, SHOW_NVE_SUMMARY_QUERIES); - - rfapiRibShowResponsesSummary (vty); - - if (show_active) - rfapiRibShowResponses (vty, p_addr, 0); - if (show_removed) - rfapiRibShowResponses (vty, p_addr, 1); - - return CMD_SUCCESS; + struct prefix p; + struct prefix *p_addr = NULL; + + int show_active = 0; + int show_removed = 0; + + if (!check_and_display_is_vnc_running(vty)) + return CMD_SUCCESS; + + if (argc > 4) { + if (!str2prefix(argv[4]->arg, &p)) { + vty_out(vty, "Invalid prefix: %s\n", argv[4]->arg); + return CMD_SUCCESS; + } else { + p_addr = &p; + } + } + + switch (argv[3]->arg[0]) { + case 'a': + show_active = 1; + break; + + case 'r': + show_removed = 1; + break; + } + + rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_QUERIES); + + rfapiRibShowResponsesSummary(vty); + + if (show_active) + rfapiRibShowResponses(vty, p_addr, 0); + if (show_removed) + rfapiRibShowResponses(vty, p_addr, 1); + + return CMD_SUCCESS; } DEFUN (show_vnc_queries_pfx, @@ -4911,22 +4566,20 @@ DEFUN (show_vnc_queries_pfx, "Limit output to a particular IPv6 prefix\n" "Limit output to a particualr IPV6 address\n") { - struct prefix pfx; - struct prefix *p = NULL; - - if (argc > 3) - { - if (!str2prefix (argv[3]->arg, &pfx)) - { - vty_out (vty, "Invalid prefix: %s\n", argv[3]->arg); - return CMD_WARNING; - } - p = &pfx; - } - - rfapi_vty_show_nve_summary (vty, SHOW_NVE_SUMMARY_QUERIES); - - return rfapiShowVncQueries (vty, p); + struct prefix pfx; + struct prefix *p = NULL; + + if (argc > 3) { + if (!str2prefix(argv[3]->arg, &pfx)) { + vty_out(vty, "Invalid prefix: %s\n", argv[3]->arg); + return CMD_WARNING; + } + p = &pfx; + } + + rfapi_vty_show_nve_summary(vty, SHOW_NVE_SUMMARY_QUERIES); + + return rfapiShowVncQueries(vty, p); } DEFUN (vnc_clear_counters, @@ -4936,43 +4589,42 @@ DEFUN (vnc_clear_counters, VNC_SHOW_STR "Reset VNC counters\n") { - struct bgp *bgp_default = bgp_get_default (); - struct rfapi *h; - struct listnode *node; - struct rfapi_descriptor *rfd; + struct bgp *bgp_default = bgp_get_default(); + struct rfapi *h; + struct listnode *node; + struct rfapi_descriptor *rfd; - if (!bgp_default) - goto notcfg; + if (!bgp_default) + goto notcfg; - h = bgp_default->rfapi; + h = bgp_default->rfapi; - if (!h) - goto notcfg; + if (!h) + goto notcfg; - /* per-rfd */ - for (ALL_LIST_ELEMENTS_RO (&h->descriptors, node, rfd)) - { - rfd->stat_count_nh_reachable = 0; - rfd->stat_count_nh_removal = 0; - } + /* per-rfd */ + for (ALL_LIST_ELEMENTS_RO(&h->descriptors, node, rfd)) { + rfd->stat_count_nh_reachable = 0; + rfd->stat_count_nh_removal = 0; + } - /* global */ - memset (&h->stat, 0, sizeof (h->stat)); + /* global */ + memset(&h->stat, 0, sizeof(h->stat)); - /* - * 151122 per bug 103, set count_registrations = number active. - * Do same for queries - */ - h->stat.count_registrations = rfapiApCountAll (bgp_default); - h->stat.count_queries = rfapi_monitor_count (NULL); + /* + * 151122 per bug 103, set count_registrations = number active. + * Do same for queries + */ + h->stat.count_registrations = rfapiApCountAll(bgp_default); + h->stat.count_queries = rfapi_monitor_count(NULL); - rfapiRibShowResponsesSummaryClear (); + rfapiRibShowResponsesSummaryClear(); - return CMD_SUCCESS; + return CMD_SUCCESS; notcfg: - vty_out (vty, "VNC is not configured.\n"); - return CMD_WARNING; + vty_out(vty, "VNC is not configured.\n"); + return CMD_WARNING; } /************************************************************************ @@ -4981,172 +4633,160 @@ notcfg: * add [vrf ] prefix * [rd ] [label ] [local-preference <0-4294967295>] ************************************************************************/ -static int -vnc_add_vrf_prefix (struct vty *vty, - const char *arg_vrf, - const char *arg_prefix, - const char *arg_rd, /* optional */ - const char *arg_label, /* optional */ - const char *arg_pref) /* optional */ +static int vnc_add_vrf_prefix(struct vty *vty, const char *arg_vrf, + const char *arg_prefix, + const char *arg_rd, /* optional */ + const char *arg_label, /* optional */ + const char *arg_pref) /* optional */ { - struct bgp *bgp; - struct rfapi_nve_group_cfg *rfg; - struct prefix pfx; - struct rfapi_ip_prefix rpfx; - uint32_t pref = 0; - struct rfapi_vn_option optary[3]; - struct rfapi_vn_option *opt = NULL; - int cur_opt = 0; - - bgp = bgp_get_default (); /* assume main instance for now */ - if (!bgp) - { - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (!bgp->rfapi || !bgp->rfapi_cfg) - { - vty_out (vty, "VRF support not configured\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - rfg = bgp_rfapi_cfg_match_byname (bgp, arg_vrf, RFAPI_GROUP_CFG_VRF); - /* arg checks */ - if (!rfg) - { - vty_out (vty, "VRF \"%s\" appears not to be configured.\n", - arg_vrf); - return CMD_WARNING_CONFIG_FAILED; - } - if (!rfg->rt_export_list || !rfg->rfapi_import_table) - { - vty_out (vty, "VRF \"%s\" is missing RT import/export RT configuration.\n", - arg_vrf); - return CMD_WARNING_CONFIG_FAILED; - } - if (!rfg->rd.family && !arg_rd) - { - vty_out (vty, "VRF \"%s\" isn't configured with an RD, so RD must be provided.\n", - arg_vrf); - return CMD_WARNING_CONFIG_FAILED; - } - if (rfg->label > MPLS_LABEL_MAX && !arg_label) - { - vty_out (vty, "VRF \"%s\" isn't configured with a default labels, so a label must be provided.\n", - arg_vrf); - return CMD_WARNING_CONFIG_FAILED; - } - if (!str2prefix (arg_prefix, &pfx)) - { - vty_out (vty, "Malformed prefix \"%s\"\n", - arg_prefix); - return CMD_WARNING_CONFIG_FAILED; - } - rfapiQprefix2Rprefix (&pfx, &rpfx); - memset (optary, 0, sizeof (optary)); - if (arg_rd) - { - if (opt != NULL) - opt->next = &optary[cur_opt]; - opt = &optary[cur_opt++]; - opt->type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD; - if (!str2prefix_rd (arg_rd, &opt->v.internal_rd)) - { - vty_out (vty, "Malformed RD \"%s\"\n", - arg_rd); - return CMD_WARNING_CONFIG_FAILED; - } - } - if (rfg->label <= MPLS_LABEL_MAX || arg_label) - { - struct rfapi_l2address_option *l2o; - if (opt != NULL) - opt->next = &optary[cur_opt]; - opt = &optary[cur_opt++]; - opt->type = RFAPI_VN_OPTION_TYPE_L2ADDR; - l2o = &opt->v.l2addr; - if (arg_label) - { - int32_t label; - label = strtoul(arg_label, NULL, 10); - l2o->label = label; - } - else - l2o->label = rfg->label; - } - if (arg_pref) - { - char *endptr = NULL; - pref = strtoul (arg_pref, &endptr, 10); - if (*endptr != '\0') - { - vty_out (vty, "%% Invalid local-preference value \"%s\"\n", - arg_pref); - return CMD_WARNING_CONFIG_FAILED; - } - } - rpfx.cost = 255 - (pref & 255) ; - if (rfg->rfd == NULL) /* need new rfapi_handle */ - { - /* based on rfapi_open */ - struct rfapi_descriptor *rfd; - rfd = XCALLOC (MTYPE_RFAPI_DESC, sizeof (struct rfapi_descriptor)); - rfd->bgp = bgp; - rfg->rfd = rfd; - /* leave most fields empty as will get from (dynamic) config when needed */ - rfd->default_tunneltype_option.type = BGP_ENCAP_TYPE_MPLS; - rfd->cookie = rfg; - if (rfg->vn_prefix.family && - !CHECK_FLAG(rfg->flags, RFAPI_RFG_VPN_NH_SELF)) - { - rfapiQprefix2Raddr(&rfg->vn_prefix, &rfd->vn_addr); - } - else - { - memset(&rfd->vn_addr, 0, sizeof(struct rfapi_ip_addr)); - rfd->vn_addr.addr_family = AF_INET; - rfd->vn_addr.addr.v4 = bgp->router_id; - } - rfd->un_addr = rfd->vn_addr; /* sigh, need something in UN for lookups */ - vnc_zlog_debug_verbose ("%s: Opening RFD for VRF %s", - __func__, rfg->name); - rfapi_init_and_open(bgp, rfd, rfg); - } - - if (!rfapi_register (rfg->rfd, &rpfx, RFAPI_INFINITE_LIFETIME, NULL, - (cur_opt ? optary : NULL), RFAPI_REGISTER_ADD)) - { - struct rfapi_next_hop_entry *head = NULL; - struct rfapi_next_hop_entry *tail = NULL; - struct rfapi_vn_option *vn_opt_new; - - vnc_zlog_debug_verbose ("%s: rfapi_register succeeded", __func__); - - if (bgp->rfapi->rfp_methods.local_cb) - { - struct rfapi_descriptor *r = (struct rfapi_descriptor *) rfg->rfd; - vn_opt_new = rfapi_vn_options_dup (opt); - - rfapiAddDeleteLocalRfpPrefix (&r->un_addr, &r->vn_addr, &rpfx, - 1, RFAPI_INFINITE_LIFETIME, - vn_opt_new, &head, &tail); - if (head) - { - bgp->rfapi->flags |= RFAPI_INCALLBACK; - (*bgp->rfapi->rfp_methods.local_cb) (head, r->cookie); - bgp->rfapi->flags &= ~RFAPI_INCALLBACK; - } - head = tail = NULL; - } - vnc_zlog_debug_verbose ("%s completed, count=%d/%d", __func__, - rfg->rfapi_import_table->local_count[AFI_IP], - rfg->rfapi_import_table->local_count[AFI_IP6]); - return CMD_SUCCESS; - } - - vnc_zlog_debug_verbose ("%s: rfapi_register failed", __func__); - vty_out (vty, "Add failed.\n"); - return CMD_WARNING_CONFIG_FAILED; + struct bgp *bgp; + struct rfapi_nve_group_cfg *rfg; + struct prefix pfx; + struct rfapi_ip_prefix rpfx; + uint32_t pref = 0; + struct rfapi_vn_option optary[3]; + struct rfapi_vn_option *opt = NULL; + int cur_opt = 0; + + bgp = bgp_get_default(); /* assume main instance for now */ + if (!bgp) { + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (!bgp->rfapi || !bgp->rfapi_cfg) { + vty_out(vty, "VRF support not configured\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + rfg = bgp_rfapi_cfg_match_byname(bgp, arg_vrf, RFAPI_GROUP_CFG_VRF); + /* arg checks */ + if (!rfg) { + vty_out(vty, "VRF \"%s\" appears not to be configured.\n", + arg_vrf); + return CMD_WARNING_CONFIG_FAILED; + } + if (!rfg->rt_export_list || !rfg->rfapi_import_table) { + vty_out(vty, + "VRF \"%s\" is missing RT import/export RT configuration.\n", + arg_vrf); + return CMD_WARNING_CONFIG_FAILED; + } + if (!rfg->rd.family && !arg_rd) { + vty_out(vty, + "VRF \"%s\" isn't configured with an RD, so RD must be provided.\n", + arg_vrf); + return CMD_WARNING_CONFIG_FAILED; + } + if (rfg->label > MPLS_LABEL_MAX && !arg_label) { + vty_out(vty, + "VRF \"%s\" isn't configured with a default labels, so a label must be provided.\n", + arg_vrf); + return CMD_WARNING_CONFIG_FAILED; + } + if (!str2prefix(arg_prefix, &pfx)) { + vty_out(vty, "Malformed prefix \"%s\"\n", arg_prefix); + return CMD_WARNING_CONFIG_FAILED; + } + rfapiQprefix2Rprefix(&pfx, &rpfx); + memset(optary, 0, sizeof(optary)); + if (arg_rd) { + if (opt != NULL) + opt->next = &optary[cur_opt]; + opt = &optary[cur_opt++]; + opt->type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD; + if (!str2prefix_rd(arg_rd, &opt->v.internal_rd)) { + vty_out(vty, "Malformed RD \"%s\"\n", arg_rd); + return CMD_WARNING_CONFIG_FAILED; + } + } + if (rfg->label <= MPLS_LABEL_MAX || arg_label) { + struct rfapi_l2address_option *l2o; + if (opt != NULL) + opt->next = &optary[cur_opt]; + opt = &optary[cur_opt++]; + opt->type = RFAPI_VN_OPTION_TYPE_L2ADDR; + l2o = &opt->v.l2addr; + if (arg_label) { + int32_t label; + label = strtoul(arg_label, NULL, 10); + l2o->label = label; + } else + l2o->label = rfg->label; + } + if (arg_pref) { + char *endptr = NULL; + pref = strtoul(arg_pref, &endptr, 10); + if (*endptr != '\0') { + vty_out(vty, + "%% Invalid local-preference value \"%s\"\n", + arg_pref); + return CMD_WARNING_CONFIG_FAILED; + } + } + rpfx.cost = 255 - (pref & 255); + if (rfg->rfd == NULL) /* need new rfapi_handle */ + { + /* based on rfapi_open */ + struct rfapi_descriptor *rfd; + rfd = XCALLOC(MTYPE_RFAPI_DESC, + sizeof(struct rfapi_descriptor)); + rfd->bgp = bgp; + rfg->rfd = rfd; + /* leave most fields empty as will get from (dynamic) config + * when needed */ + rfd->default_tunneltype_option.type = BGP_ENCAP_TYPE_MPLS; + rfd->cookie = rfg; + if (rfg->vn_prefix.family + && !CHECK_FLAG(rfg->flags, RFAPI_RFG_VPN_NH_SELF)) { + rfapiQprefix2Raddr(&rfg->vn_prefix, &rfd->vn_addr); + } else { + memset(&rfd->vn_addr, 0, sizeof(struct rfapi_ip_addr)); + rfd->vn_addr.addr_family = AF_INET; + rfd->vn_addr.addr.v4 = bgp->router_id; + } + rfd->un_addr = rfd->vn_addr; /* sigh, need something in UN for + lookups */ + vnc_zlog_debug_verbose("%s: Opening RFD for VRF %s", __func__, + rfg->name); + rfapi_init_and_open(bgp, rfd, rfg); + } + + if (!rfapi_register(rfg->rfd, &rpfx, RFAPI_INFINITE_LIFETIME, NULL, + (cur_opt ? optary : NULL), RFAPI_REGISTER_ADD)) { + struct rfapi_next_hop_entry *head = NULL; + struct rfapi_next_hop_entry *tail = NULL; + struct rfapi_vn_option *vn_opt_new; + + vnc_zlog_debug_verbose("%s: rfapi_register succeeded", + __func__); + + if (bgp->rfapi->rfp_methods.local_cb) { + struct rfapi_descriptor *r = + (struct rfapi_descriptor *)rfg->rfd; + vn_opt_new = rfapi_vn_options_dup(opt); + + rfapiAddDeleteLocalRfpPrefix(&r->un_addr, &r->vn_addr, + &rpfx, 1, + RFAPI_INFINITE_LIFETIME, + vn_opt_new, &head, &tail); + if (head) { + bgp->rfapi->flags |= RFAPI_INCALLBACK; + (*bgp->rfapi->rfp_methods.local_cb)(head, + r->cookie); + bgp->rfapi->flags &= ~RFAPI_INCALLBACK; + } + head = tail = NULL; + } + vnc_zlog_debug_verbose( + "%s completed, count=%d/%d", __func__, + rfg->rfapi_import_table->local_count[AFI_IP], + rfg->rfapi_import_table->local_count[AFI_IP6]); + return CMD_SUCCESS; + } + + vnc_zlog_debug_verbose("%s: rfapi_register failed", __func__); + vty_out(vty, "Add failed.\n"); + return CMD_WARNING_CONFIG_FAILED; } DEFUN (add_vrf_prefix_rd_label_pref, @@ -5165,33 +4805,32 @@ DEFUN (add_vrf_prefix_rd_label_pref, "Set advertised local preference\n" "local preference (higher=more preferred)\n") { - char *arg_vrf = argv[2]->arg; - char *arg_prefix = argv[4]->arg; - char *arg_rd = NULL; /* optional */ - char *arg_label = NULL; /* optional */ - char *arg_pref = NULL; /* optional */ - int pargc = 5; - argc--; /* don't parse argument */ - while (pargc < argc) - { - switch (argv[pargc++]->arg[0]) - { - case 'r': - arg_rd = argv[pargc]->arg; - break; - case 'l': - arg_label = argv[pargc]->arg; - break; - case 'p': - arg_pref = argv[pargc]->arg; - break; - default: - break; - } - pargc ++; - } - - return vnc_add_vrf_prefix (vty, arg_vrf, arg_prefix, arg_rd, arg_label, arg_pref); + char *arg_vrf = argv[2]->arg; + char *arg_prefix = argv[4]->arg; + char *arg_rd = NULL; /* optional */ + char *arg_label = NULL; /* optional */ + char *arg_pref = NULL; /* optional */ + int pargc = 5; + argc--; /* don't parse argument */ + while (pargc < argc) { + switch (argv[pargc++]->arg[0]) { + case 'r': + arg_rd = argv[pargc]->arg; + break; + case 'l': + arg_label = argv[pargc]->arg; + break; + case 'p': + arg_pref = argv[pargc]->arg; + break; + default: + break; + } + pargc++; + } + + return vnc_add_vrf_prefix(vty, arg_vrf, arg_prefix, arg_rd, arg_label, + arg_pref); } /************************************************************************ @@ -5199,89 +4838,78 @@ DEFUN (add_vrf_prefix_rd_label_pref, * * clear [vrf ] prefix [rd ] ************************************************************************/ -static int -rfapi_cfg_group_it_count(struct rfapi_nve_group_cfg *rfg) +static int rfapi_cfg_group_it_count(struct rfapi_nve_group_cfg *rfg) { - int count = 0; - afi_t afi = AFI_MAX; - while (afi-- > 0) - { - count += rfg->rfapi_import_table->local_count[afi]; - } - return count; + int count = 0; + afi_t afi = AFI_MAX; + while (afi-- > 0) { + count += rfg->rfapi_import_table->local_count[afi]; + } + return count; } -static void -clear_vnc_vrf_closer (struct rfapi_nve_group_cfg *rfg) +static void clear_vnc_vrf_closer(struct rfapi_nve_group_cfg *rfg) { - struct rfapi_descriptor *rfd = rfg->rfd; - afi_t afi; - - if (rfd == NULL) - return; - /* check if IT is empty */ - for (afi = 0; - afi < AFI_MAX && rfg->rfapi_import_table->local_count[afi] == 0; - afi++); - - if (afi == AFI_MAX) - { - vnc_zlog_debug_verbose ("%s: closing RFD for VRF %s", - __func__, rfg->name); - rfg->rfd = NULL; - rfapi_close(rfd); - } - else - { - vnc_zlog_debug_verbose ("%s: VRF %s afi=%d count=%d", - __func__, rfg->name, afi, - rfg->rfapi_import_table->local_count[afi]); - } + struct rfapi_descriptor *rfd = rfg->rfd; + afi_t afi; + + if (rfd == NULL) + return; + /* check if IT is empty */ + for (afi = 0; + afi < AFI_MAX && rfg->rfapi_import_table->local_count[afi] == 0; + afi++) + ; + + if (afi == AFI_MAX) { + vnc_zlog_debug_verbose("%s: closing RFD for VRF %s", __func__, + rfg->name); + rfg->rfd = NULL; + rfapi_close(rfd); + } else { + vnc_zlog_debug_verbose( + "%s: VRF %s afi=%d count=%d", __func__, rfg->name, afi, + rfg->rfapi_import_table->local_count[afi]); + } } -static int -vnc_clear_vrf (struct vty *vty, - struct bgp *bgp, - const char *arg_vrf, - const char *arg_prefix, /* NULL = all */ - const char *arg_rd) /* optional */ +static int vnc_clear_vrf(struct vty *vty, struct bgp *bgp, const char *arg_vrf, + const char *arg_prefix, /* NULL = all */ + const char *arg_rd) /* optional */ { - struct rfapi_nve_group_cfg *rfg; - struct rfapi_local_reg_delete_arg cda; - int rc; - int start_count; - - if (bgp == NULL) - bgp = bgp_get_default (); /* assume main instance for now */ - if (!bgp) - { - vty_out (vty, "No BGP process is configured\n"); - return CMD_WARNING; - } - if (!bgp->rfapi || !bgp->rfapi_cfg) - { - vty_out (vty, "VRF support not configured\n"); - return CMD_WARNING; - } - rfg = bgp_rfapi_cfg_match_byname (bgp, arg_vrf, RFAPI_GROUP_CFG_VRF); - /* arg checks */ - if (!rfg) - { - vty_out (vty, "VRF \"%s\" appears not to be configured.\n", - arg_vrf); - return CMD_WARNING; - } - rc = parse_deleter_args (vty, bgp, arg_prefix, NULL, NULL, NULL, NULL, - arg_rd, rfg, &cda); - if (rc != CMD_SUCCESS) /* parse error */ - return rc; - - start_count = rfapi_cfg_group_it_count(rfg); - clear_vnc_prefix (&cda); - clear_vnc_vrf_closer (rfg); - vty_out (vty, "Cleared %u out of %d prefixes.\n", - cda.pfx_count, start_count); - return CMD_SUCCESS; + struct rfapi_nve_group_cfg *rfg; + struct rfapi_local_reg_delete_arg cda; + int rc; + int start_count; + + if (bgp == NULL) + bgp = bgp_get_default(); /* assume main instance for now */ + if (!bgp) { + vty_out(vty, "No BGP process is configured\n"); + return CMD_WARNING; + } + if (!bgp->rfapi || !bgp->rfapi_cfg) { + vty_out(vty, "VRF support not configured\n"); + return CMD_WARNING; + } + rfg = bgp_rfapi_cfg_match_byname(bgp, arg_vrf, RFAPI_GROUP_CFG_VRF); + /* arg checks */ + if (!rfg) { + vty_out(vty, "VRF \"%s\" appears not to be configured.\n", + arg_vrf); + return CMD_WARNING; + } + rc = parse_deleter_args(vty, bgp, arg_prefix, NULL, NULL, NULL, NULL, + arg_rd, rfg, &cda); + if (rc != CMD_SUCCESS) /* parse error */ + return rc; + + start_count = rfapi_cfg_group_it_count(rfg); + clear_vnc_prefix(&cda); + clear_vnc_vrf_closer(rfg); + vty_out(vty, "Cleared %u out of %d prefixes.\n", cda.pfx_count, + start_count); + return CMD_SUCCESS; } DEFUN (clear_vrf_prefix_rd, @@ -5296,27 +4924,25 @@ DEFUN (clear_vrf_prefix_rd, "Specific VRF Route Distinguisher\n" ": or :\n") { - char *arg_vrf = argv[2]->arg; - char *arg_prefix = NULL; /* optional */ - char *arg_rd = NULL; /* optional */ - int pargc = 3; - argc--; /* don't check parameter */ - while (pargc < argc) - { - switch (argv[pargc++]->arg[0]) - { - case 'r': - arg_rd = argv[pargc]->arg; - break; - case 'p': - arg_prefix = argv[pargc]->arg; - break; - default: - break; - } - pargc ++; - } - return vnc_clear_vrf (vty, NULL, arg_vrf, arg_prefix, arg_rd); + char *arg_vrf = argv[2]->arg; + char *arg_prefix = NULL; /* optional */ + char *arg_rd = NULL; /* optional */ + int pargc = 3; + argc--; /* don't check parameter */ + while (pargc < argc) { + switch (argv[pargc++]->arg[0]) { + case 'r': + arg_rd = argv[pargc]->arg; + break; + case 'p': + arg_prefix = argv[pargc]->arg; + break; + default: + break; + } + pargc++; + } + return vnc_clear_vrf(vty, NULL, arg_vrf, arg_prefix, arg_rd); } DEFUN (clear_vrf_all, @@ -5327,71 +4953,71 @@ DEFUN (clear_vrf_all, "VRF name\n" "All prefixes\n") { - char *arg_vrf = argv[2]->arg; - return vnc_clear_vrf (vty, NULL, arg_vrf, NULL, NULL); + char *arg_vrf = argv[2]->arg; + return vnc_clear_vrf(vty, NULL, arg_vrf, NULL, NULL); } -void rfapi_vty_init () +void rfapi_vty_init() { - install_element (ENABLE_NODE, &add_vnc_prefix_cost_life_lnh_cmd); - install_element (ENABLE_NODE, &add_vnc_prefix_life_cost_lnh_cmd); - install_element (ENABLE_NODE, &add_vnc_prefix_cost_lnh_cmd); - install_element (ENABLE_NODE, &add_vnc_prefix_life_lnh_cmd); - install_element (ENABLE_NODE, &add_vnc_prefix_lnh_cmd); - - install_element (ENABLE_NODE, &add_vnc_prefix_cost_life_cmd); - install_element (ENABLE_NODE, &add_vnc_prefix_life_cost_cmd); - install_element (ENABLE_NODE, &add_vnc_prefix_cost_cmd); - install_element (ENABLE_NODE, &add_vnc_prefix_life_cmd); - install_element (ENABLE_NODE, &add_vnc_prefix_cmd); - - install_element (ENABLE_NODE, &add_vnc_mac_vni_prefix_cost_life_cmd); - install_element (ENABLE_NODE, &add_vnc_mac_vni_prefix_life_cmd); - install_element (ENABLE_NODE, &add_vnc_mac_vni_prefix_cost_cmd); - install_element (ENABLE_NODE, &add_vnc_mac_vni_prefix_cmd); - install_element (ENABLE_NODE, &add_vnc_mac_vni_cost_life_cmd); - install_element (ENABLE_NODE, &add_vnc_mac_vni_cost_cmd); - install_element (ENABLE_NODE, &add_vnc_mac_vni_life_cmd); - install_element (ENABLE_NODE, &add_vnc_mac_vni_cmd); - - install_element (ENABLE_NODE, &add_vrf_prefix_rd_label_pref_cmd); - - install_element (ENABLE_NODE, &clear_vnc_nve_all_cmd); - install_element (ENABLE_NODE, &clear_vnc_nve_vn_un_cmd); - install_element (ENABLE_NODE, &clear_vnc_nve_un_vn_cmd); - install_element (ENABLE_NODE, &clear_vnc_nve_vn_cmd); - install_element (ENABLE_NODE, &clear_vnc_nve_un_cmd); - - install_element (ENABLE_NODE, &clear_vnc_prefix_vn_un_cmd); - install_element (ENABLE_NODE, &clear_vnc_prefix_un_vn_cmd); - install_element (ENABLE_NODE, &clear_vnc_prefix_un_cmd); - install_element (ENABLE_NODE, &clear_vnc_prefix_vn_cmd); - install_element (ENABLE_NODE, &clear_vnc_prefix_all_cmd); - - install_element (ENABLE_NODE, &clear_vnc_mac_vn_un_cmd); - install_element (ENABLE_NODE, &clear_vnc_mac_un_vn_cmd); - install_element (ENABLE_NODE, &clear_vnc_mac_un_cmd); - install_element (ENABLE_NODE, &clear_vnc_mac_vn_cmd); - install_element (ENABLE_NODE, &clear_vnc_mac_all_cmd); - - install_element (ENABLE_NODE, &clear_vnc_mac_vn_un_prefix_cmd); - install_element (ENABLE_NODE, &clear_vnc_mac_un_vn_prefix_cmd); - install_element (ENABLE_NODE, &clear_vnc_mac_un_prefix_cmd); - install_element (ENABLE_NODE, &clear_vnc_mac_vn_prefix_cmd); - install_element (ENABLE_NODE, &clear_vnc_mac_all_prefix_cmd); - - install_element (ENABLE_NODE, &clear_vrf_prefix_rd_cmd); - install_element (ENABLE_NODE, &clear_vrf_all_cmd); - - install_element (ENABLE_NODE, &vnc_clear_counters_cmd); - - install_element (VIEW_NODE, &vnc_show_summary_cmd); - install_element (VIEW_NODE, &vnc_show_nves_cmd); - install_element (VIEW_NODE, &vnc_show_nves_ptct_cmd); - - install_element (VIEW_NODE, &vnc_show_registrations_pfx_cmd); - install_element (VIEW_NODE, &vnc_show_registrations_some_pfx_cmd); - install_element (VIEW_NODE, &vnc_show_responses_pfx_cmd); - install_element (VIEW_NODE, &vnc_show_responses_some_pfx_cmd); - install_element (VIEW_NODE, &show_vnc_queries_pfx_cmd); + install_element(ENABLE_NODE, &add_vnc_prefix_cost_life_lnh_cmd); + install_element(ENABLE_NODE, &add_vnc_prefix_life_cost_lnh_cmd); + install_element(ENABLE_NODE, &add_vnc_prefix_cost_lnh_cmd); + install_element(ENABLE_NODE, &add_vnc_prefix_life_lnh_cmd); + install_element(ENABLE_NODE, &add_vnc_prefix_lnh_cmd); + + install_element(ENABLE_NODE, &add_vnc_prefix_cost_life_cmd); + install_element(ENABLE_NODE, &add_vnc_prefix_life_cost_cmd); + install_element(ENABLE_NODE, &add_vnc_prefix_cost_cmd); + install_element(ENABLE_NODE, &add_vnc_prefix_life_cmd); + install_element(ENABLE_NODE, &add_vnc_prefix_cmd); + + install_element(ENABLE_NODE, &add_vnc_mac_vni_prefix_cost_life_cmd); + install_element(ENABLE_NODE, &add_vnc_mac_vni_prefix_life_cmd); + install_element(ENABLE_NODE, &add_vnc_mac_vni_prefix_cost_cmd); + install_element(ENABLE_NODE, &add_vnc_mac_vni_prefix_cmd); + install_element(ENABLE_NODE, &add_vnc_mac_vni_cost_life_cmd); + install_element(ENABLE_NODE, &add_vnc_mac_vni_cost_cmd); + install_element(ENABLE_NODE, &add_vnc_mac_vni_life_cmd); + install_element(ENABLE_NODE, &add_vnc_mac_vni_cmd); + + install_element(ENABLE_NODE, &add_vrf_prefix_rd_label_pref_cmd); + + install_element(ENABLE_NODE, &clear_vnc_nve_all_cmd); + install_element(ENABLE_NODE, &clear_vnc_nve_vn_un_cmd); + install_element(ENABLE_NODE, &clear_vnc_nve_un_vn_cmd); + install_element(ENABLE_NODE, &clear_vnc_nve_vn_cmd); + install_element(ENABLE_NODE, &clear_vnc_nve_un_cmd); + + install_element(ENABLE_NODE, &clear_vnc_prefix_vn_un_cmd); + install_element(ENABLE_NODE, &clear_vnc_prefix_un_vn_cmd); + install_element(ENABLE_NODE, &clear_vnc_prefix_un_cmd); + install_element(ENABLE_NODE, &clear_vnc_prefix_vn_cmd); + install_element(ENABLE_NODE, &clear_vnc_prefix_all_cmd); + + install_element(ENABLE_NODE, &clear_vnc_mac_vn_un_cmd); + install_element(ENABLE_NODE, &clear_vnc_mac_un_vn_cmd); + install_element(ENABLE_NODE, &clear_vnc_mac_un_cmd); + install_element(ENABLE_NODE, &clear_vnc_mac_vn_cmd); + install_element(ENABLE_NODE, &clear_vnc_mac_all_cmd); + + install_element(ENABLE_NODE, &clear_vnc_mac_vn_un_prefix_cmd); + install_element(ENABLE_NODE, &clear_vnc_mac_un_vn_prefix_cmd); + install_element(ENABLE_NODE, &clear_vnc_mac_un_prefix_cmd); + install_element(ENABLE_NODE, &clear_vnc_mac_vn_prefix_cmd); + install_element(ENABLE_NODE, &clear_vnc_mac_all_prefix_cmd); + + install_element(ENABLE_NODE, &clear_vrf_prefix_rd_cmd); + install_element(ENABLE_NODE, &clear_vrf_all_cmd); + + install_element(ENABLE_NODE, &vnc_clear_counters_cmd); + + install_element(VIEW_NODE, &vnc_show_summary_cmd); + install_element(VIEW_NODE, &vnc_show_nves_cmd); + install_element(VIEW_NODE, &vnc_show_nves_ptct_cmd); + + install_element(VIEW_NODE, &vnc_show_registrations_pfx_cmd); + install_element(VIEW_NODE, &vnc_show_registrations_some_pfx_cmd); + install_element(VIEW_NODE, &vnc_show_responses_pfx_cmd); + install_element(VIEW_NODE, &vnc_show_responses_some_pfx_cmd); + install_element(VIEW_NODE, &show_vnc_queries_pfx_cmd); } diff --git a/bgpd/rfapi/rfapi_vty.h b/bgpd/rfapi/rfapi_vty.h index 46b77b55e..a08183aa4 100644 --- a/bgpd/rfapi/rfapi_vty.h +++ b/bgpd/rfapi/rfapi_vty.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -23,74 +23,59 @@ #include "lib/vty.h" -typedef enum -{ - SHOW_NVE_SUMMARY_ACTIVE_NVES, - SHOW_NVE_SUMMARY_UNKNOWN_NVES, /* legacy */ - SHOW_NVE_SUMMARY_REGISTERED, - SHOW_NVE_SUMMARY_QUERIES, - SHOW_NVE_SUMMARY_RESPONSES, - SHOW_NVE_SUMMARY_MAX +typedef enum { + SHOW_NVE_SUMMARY_ACTIVE_NVES, + SHOW_NVE_SUMMARY_UNKNOWN_NVES, /* legacy */ + SHOW_NVE_SUMMARY_REGISTERED, + SHOW_NVE_SUMMARY_QUERIES, + SHOW_NVE_SUMMARY_RESPONSES, + SHOW_NVE_SUMMARY_MAX } show_nve_summary_t; #define VNC_SHOW_STR "VNC information\n" -extern char * -rfapiFormatSeconds (uint32_t seconds, char *buf, size_t len); +extern char *rfapiFormatSeconds(uint32_t seconds, char *buf, size_t len); -extern char * -rfapiFormatAge (time_t age, char *buf, size_t len); +extern char *rfapiFormatAge(time_t age, char *buf, size_t len); -extern void -rfapiRprefixApplyMask (struct rfapi_ip_prefix *rprefix); +extern void rfapiRprefixApplyMask(struct rfapi_ip_prefix *rprefix); -extern int -rfapiQprefix2Raddr (struct prefix *qprefix, struct rfapi_ip_addr *raddr); +extern int rfapiQprefix2Raddr(struct prefix *qprefix, + struct rfapi_ip_addr *raddr); -extern void -rfapiQprefix2Rprefix (struct prefix *qprefix, - struct rfapi_ip_prefix *rprefix); +extern void rfapiQprefix2Rprefix(struct prefix *qprefix, + struct rfapi_ip_prefix *rprefix); -extern int -rfapiRprefix2Qprefix (struct rfapi_ip_prefix *rprefix, - struct prefix *qprefix); +extern int rfapiRprefix2Qprefix(struct rfapi_ip_prefix *rprefix, + struct prefix *qprefix); -extern int -rfapiRaddr2Qprefix (struct rfapi_ip_addr *hia, struct prefix *pfx); +extern int rfapiRaddr2Qprefix(struct rfapi_ip_addr *hia, struct prefix *pfx); -extern int -rfapiRprefixSame (struct rfapi_ip_prefix *hp1, struct rfapi_ip_prefix *hp2); +extern int rfapiRprefixSame(struct rfapi_ip_prefix *hp1, + struct rfapi_ip_prefix *hp2); -extern void -rfapiL2o2Qprefix (struct rfapi_l2address_option *l2o, struct prefix *pfx); +extern void rfapiL2o2Qprefix(struct rfapi_l2address_option *l2o, + struct prefix *pfx); -extern int -rfapiStr2EthAddr (const char *str, struct ethaddr *ea); +extern int rfapiStr2EthAddr(const char *str, struct ethaddr *ea); -extern const char * -rfapi_ntop ( - int af, - const void *src, - char *buf, - socklen_t size); +extern const char *rfapi_ntop(int af, const void *src, char *buf, + socklen_t size); -extern int -rfapiDebugPrintf (void *dummy, const char *format, ...); +extern int rfapiDebugPrintf(void *dummy, const char *format, ...); -extern int -rfapiStream2Vty ( - void *stream, /* input */ - int (**fp) (void *, const char *, ...), /* output */ - struct vty **vty, /* output */ - void **outstream, /* output */ - const char **vty_newline); /* output */ +extern int rfapiStream2Vty(void *stream, /* input */ + int (**fp)(void *, const char *, ...), /* output */ + struct vty **vty, /* output */ + void **outstream, /* output */ + const char **vty_newline); /* output */ /*------------------------------------------ * rfapiRfapiIpAddr2Str * * UI helper: generate string from rfapi_ip_addr * - * input: + * input: * a IP v4/v6 address * * output @@ -101,75 +86,50 @@ rfapiStream2Vty ( * NULL conversion failed * non-NULL pointer to buf --------------------------------------------*/ -extern const char * -rfapiRfapiIpAddr2Str (struct rfapi_ip_addr *a, char *buf, int bufsize); +extern const char *rfapiRfapiIpAddr2Str(struct rfapi_ip_addr *a, char *buf, + int bufsize); -extern void -rfapiPrintRfapiIpAddr (void *stream, struct rfapi_ip_addr *a); +extern void rfapiPrintRfapiIpAddr(void *stream, struct rfapi_ip_addr *a); -extern void -rfapiPrintRfapiIpPrefix (void *stream, struct rfapi_ip_prefix *p); +extern void rfapiPrintRfapiIpPrefix(void *stream, struct rfapi_ip_prefix *p); -void -rfapiPrintRd (struct vty *vty, struct prefix_rd *prd); +void rfapiPrintRd(struct vty *vty, struct prefix_rd *prd); -extern void -rfapiPrintAdvertisedInfo ( - struct vty *vty, - struct rfapi_descriptor *rfd, - safi_t safi, - struct prefix *p); +extern void rfapiPrintAdvertisedInfo(struct vty *vty, + struct rfapi_descriptor *rfd, safi_t safi, + struct prefix *p); -extern void -rfapiPrintDescriptor (struct vty *vty, struct rfapi_descriptor *rfd); +extern void rfapiPrintDescriptor(struct vty *vty, struct rfapi_descriptor *rfd); -extern void -rfapiPrintMatchingDescriptors (struct vty *vty, - struct prefix *vn_prefix, - struct prefix *un_prefix); +extern void rfapiPrintMatchingDescriptors(struct vty *vty, + struct prefix *vn_prefix, + struct prefix *un_prefix); -extern void -rfapiPrintAttrPtrs (void *stream, struct attr *attr); +extern void rfapiPrintAttrPtrs(void *stream, struct attr *attr); /* * Parse an address and put into a struct prefix */ -extern int -rfapiCliGetPrefixAddr (struct vty *vty, const char *str, struct prefix *p); - -extern int -rfapiCliGetRfapiIpAddr ( - struct vty *vty, - const char *str, - struct rfapi_ip_addr *hai); - -extern void -rfapiPrintNhl (void *stream, struct rfapi_next_hop_entry *next_hops); - -extern char * -rfapiMonitorVpn2Str ( - struct rfapi_monitor_vpn *m, - char *buf, - int size); - -extern const char * -rfapiRfapiIpPrefix2Str ( - struct rfapi_ip_prefix *p, - char *buf, - int bufsize); - -extern void -rfapiShowItNode (void *stream, struct route_node *rn); - -extern char * -rfapiEthAddr2Str ( - const struct ethaddr *ea, - char *buf, - int bufsize); +extern int rfapiCliGetPrefixAddr(struct vty *vty, const char *str, + struct prefix *p); + +extern int rfapiCliGetRfapiIpAddr(struct vty *vty, const char *str, + struct rfapi_ip_addr *hai); + +extern void rfapiPrintNhl(void *stream, struct rfapi_next_hop_entry *next_hops); + +extern char *rfapiMonitorVpn2Str(struct rfapi_monitor_vpn *m, char *buf, + int size); + +extern const char *rfapiRfapiIpPrefix2Str(struct rfapi_ip_prefix *p, char *buf, + int bufsize); + +extern void rfapiShowItNode(void *stream, struct route_node *rn); + +extern char *rfapiEthAddr2Str(const struct ethaddr *ea, char *buf, int bufsize); /* install vty commands */ -extern void -rfapi_vty_init (void); +extern void rfapi_vty_init(void); /*------------------------------------------ * rfapiShowRemoteRegistrations @@ -177,7 +137,7 @@ rfapi_vty_init (void); * UI helper: produces the "remote" portion of the output * of "show vnc registrations". * - * input: + * input: * stream pointer to output stream * prefix_only pointer to prefix. If non-NULL, print only registrations * matching the specified prefix @@ -189,21 +149,17 @@ rfapi_vty_init (void); * 0 nothing printed * >0 something printed --------------------------------------------*/ -extern int -rfapiShowRemoteRegistrations ( - void *stream, - struct prefix *prefix_only, - int show_expiring, - int show_local, - int show_remote, - int show_imported); +extern int rfapiShowRemoteRegistrations(void *stream, + struct prefix *prefix_only, + int show_expiring, int show_local, + int show_remote, int show_imported); /*------------------------------------------ * rfapi_monitor_count * * UI helper: count number of active monitors * - * input: + * input: * handle rfapi handle (NULL to count across * all open handles) * @@ -212,11 +168,9 @@ rfapiShowRemoteRegistrations ( * return value: * count of monitors --------------------------------------------*/ -extern uint32_t -rfapi_monitor_count (rfapi_handle); +extern uint32_t rfapi_monitor_count(rfapi_handle); -extern int -rfapiShowVncQueries (void *stream, struct prefix *pfx_match); +extern int rfapiShowVncQueries(void *stream, struct prefix *pfx_match); #endif diff --git a/bgpd/rfapi/vnc_debug.c b/bgpd/rfapi/vnc_debug.c index 1f9e1b10f..d4ff9451c 100644 --- a/bgpd/rfapi/vnc_debug.c +++ b/bgpd/rfapi/vnc_debug.c @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2016, LabN Consulting, L.L.C. * @@ -34,19 +34,18 @@ unsigned long conf_vnc_debug; unsigned long term_vnc_debug; struct vnc_debug { - unsigned long bit; - const char *name; + unsigned long bit; + const char *name; }; -struct vnc_debug vncdebug[] = -{ - {VNC_DEBUG_RFAPI_QUERY, "rfapi-query"}, - {VNC_DEBUG_IMPORT_BI_ATTACH, "import-bi-attach"}, - {VNC_DEBUG_IMPORT_DEL_REMOTE, "import-del-remote"}, - {VNC_DEBUG_EXPORT_BGP_GETCE, "export-bgp-getce"}, - {VNC_DEBUG_EXPORT_BGP_DIRECT_ADD, "export-bgp-direct-add"}, - {VNC_DEBUG_IMPORT_BGP_ADD_ROUTE, "import-bgp-add-route"}, - {VNC_DEBUG_VERBOSE, "verbose"}, +struct vnc_debug vncdebug[] = { + {VNC_DEBUG_RFAPI_QUERY, "rfapi-query"}, + {VNC_DEBUG_IMPORT_BI_ATTACH, "import-bi-attach"}, + {VNC_DEBUG_IMPORT_DEL_REMOTE, "import-del-remote"}, + {VNC_DEBUG_EXPORT_BGP_GETCE, "export-bgp-getce"}, + {VNC_DEBUG_EXPORT_BGP_DIRECT_ADD, "export-bgp-direct-add"}, + {VNC_DEBUG_IMPORT_BGP_ADD_ROUTE, "import-bgp-add-route"}, + {VNC_DEBUG_VERBOSE, "verbose"}, }; #define VNC_STR "VNC information\n" @@ -65,28 +64,23 @@ DEFUN (debug_bgp_vnc, "import delete remote routes\n" "verbose logging\n") { - size_t i; - - for (i = 0; i < (sizeof(vncdebug) / sizeof(struct vnc_debug)); ++i) - { - if (strmatch(argv[3]->text, vncdebug[i].name)) - { - if (vty->node == CONFIG_NODE) - { - conf_vnc_debug |= vncdebug[i].bit; - term_vnc_debug |= vncdebug[i].bit; - } - else - { - term_vnc_debug |= vncdebug[i].bit; - vty_out (vty, "BGP vnc %s debugging is on\n", - vncdebug[i].name); - } - return CMD_SUCCESS; + size_t i; + + for (i = 0; i < (sizeof(vncdebug) / sizeof(struct vnc_debug)); ++i) { + if (strmatch(argv[3]->text, vncdebug[i].name)) { + if (vty->node == CONFIG_NODE) { + conf_vnc_debug |= vncdebug[i].bit; + term_vnc_debug |= vncdebug[i].bit; + } else { + term_vnc_debug |= vncdebug[i].bit; + vty_out(vty, "BGP vnc %s debugging is on\n", + vncdebug[i].name); + } + return CMD_SUCCESS; + } } - } - vty_out (vty, "Unknown debug flag: %s\n", argv[3]->arg); - return CMD_WARNING_CONFIG_FAILED; + vty_out(vty, "Unknown debug flag: %s\n", argv[3]->arg); + return CMD_WARNING_CONFIG_FAILED; } DEFUN (no_debug_bgp_vnc, @@ -102,30 +96,25 @@ DEFUN (no_debug_bgp_vnc, "import delete remote routes\n" "verbose logging\n") { - size_t i; - - if (strmatch(argv[0]->text, "no")) - argc--, argv++; - for (i = 0; i < (sizeof(vncdebug) / sizeof(struct vnc_debug)); ++i) - { - if (strmatch(argv[3]->text, vncdebug[i].name)) - { - if (vty->node == CONFIG_NODE) - { - conf_vnc_debug &= ~vncdebug[i].bit; - term_vnc_debug &= ~vncdebug[i].bit; - } - else - { - term_vnc_debug &= ~vncdebug[i].bit; - vty_out (vty, "BGP vnc %s debugging is off\n", - vncdebug[i].name); - } - return CMD_SUCCESS; + size_t i; + + if (strmatch(argv[0]->text, "no")) + argc--, argv++; + for (i = 0; i < (sizeof(vncdebug) / sizeof(struct vnc_debug)); ++i) { + if (strmatch(argv[3]->text, vncdebug[i].name)) { + if (vty->node == CONFIG_NODE) { + conf_vnc_debug &= ~vncdebug[i].bit; + term_vnc_debug &= ~vncdebug[i].bit; + } else { + term_vnc_debug &= ~vncdebug[i].bit; + vty_out(vty, "BGP vnc %s debugging is off\n", + vncdebug[i].name); + } + return CMD_SUCCESS; + } } - } - vty_out (vty, "Unknown debug flag: %s\n", argv[3]->arg); - return CMD_WARNING_CONFIG_FAILED; + vty_out(vty, "Unknown debug flag: %s\n", argv[3]->arg); + return CMD_WARNING_CONFIG_FAILED; } @@ -143,10 +132,10 @@ DEFUN (no_debug_bgp_vnc_all, BGP_STR VNC_STR) { - term_vnc_debug = 0; - vty_out (vty, "All possible VNC debugging has been turned off\n"); - - return CMD_SUCCESS; + term_vnc_debug = 0; + vty_out(vty, "All possible VNC debugging has been turned off\n"); + + return CMD_SUCCESS; } /*********************************************************************** @@ -161,55 +150,44 @@ DEFUN (show_debugging_bgp_vnc, BGP_STR VNC_STR) { - size_t i; + size_t i; - vty_out (vty, "BGP VNC debugging status:\n"); + vty_out(vty, "BGP VNC debugging status:\n"); - for (i = 0; i < (sizeof(vncdebug) / sizeof(struct vnc_debug)); ++i) - { - if (term_vnc_debug & vncdebug[i].bit) - { - vty_out (vty, " BGP VNC %s debugging is on\n", - vncdebug[i].name); + for (i = 0; i < (sizeof(vncdebug) / sizeof(struct vnc_debug)); ++i) { + if (term_vnc_debug & vncdebug[i].bit) { + vty_out(vty, " BGP VNC %s debugging is on\n", + vncdebug[i].name); + } } - } - vty_out (vty, "\n"); - return CMD_SUCCESS; + vty_out(vty, "\n"); + return CMD_SUCCESS; } -static int -bgp_vnc_config_write_debug (struct vty *vty) +static int bgp_vnc_config_write_debug(struct vty *vty) { - int write = 0; - size_t i; - - for (i = 0; i < (sizeof(vncdebug) / sizeof(struct vnc_debug)); ++i) - { - if (conf_vnc_debug & vncdebug[i].bit) - { - vty_out (vty, "debug bgp vnc %s\n", vncdebug[i].name); - write++; + int write = 0; + size_t i; + + for (i = 0; i < (sizeof(vncdebug) / sizeof(struct vnc_debug)); ++i) { + if (conf_vnc_debug & vncdebug[i].bit) { + vty_out(vty, "debug bgp vnc %s\n", vncdebug[i].name); + write++; + } } - } - return write; + return write; } -static struct cmd_node debug_node = -{ - DEBUG_VNC_NODE, - "", - 1 -}; +static struct cmd_node debug_node = {DEBUG_VNC_NODE, "", 1}; -void -vnc_debug_init (void) +void vnc_debug_init(void) { - install_node (&debug_node, bgp_vnc_config_write_debug); - install_element (ENABLE_NODE, &show_debugging_bgp_vnc_cmd); + install_node(&debug_node, bgp_vnc_config_write_debug); + install_element(ENABLE_NODE, &show_debugging_bgp_vnc_cmd); - install_element (ENABLE_NODE, &debug_bgp_vnc_cmd); - install_element (CONFIG_NODE, &debug_bgp_vnc_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_vnc_cmd); + install_element(ENABLE_NODE, &debug_bgp_vnc_cmd); + install_element(CONFIG_NODE, &debug_bgp_vnc_cmd); + install_element(ENABLE_NODE, &no_debug_bgp_vnc_cmd); - install_element (ENABLE_NODE, &no_debug_bgp_vnc_all_cmd); + install_element(ENABLE_NODE, &no_debug_bgp_vnc_all_cmd); } diff --git a/bgpd/rfapi/vnc_debug.h b/bgpd/rfapi/vnc_debug.h index c1d81f5c1..dd4938307 100644 --- a/bgpd/rfapi/vnc_debug.h +++ b/bgpd/rfapi/vnc_debug.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2016, LabN Consulting, L.L.C. * @@ -44,8 +44,7 @@ extern unsigned long term_vnc_debug; #define vnc_zlog_debug_verbose if (VNC_DEBUG(VERBOSE)) zlog_debug #define vnc_zlog_debug_any if (VNC_DEBUG(ANY)) zlog_debug -extern void -vnc_debug_init (void); +extern void vnc_debug_init(void); #endif /* ENABLE_BGP_VNC */ diff --git a/bgpd/rfapi/vnc_export_bgp.c b/bgpd/rfapi/vnc_export_bgp.c index 342dc6a19..b699cec9e 100644 --- a/bgpd/rfapi/vnc_export_bgp.c +++ b/bgpd/rfapi/vnc_export_bgp.c @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -63,472 +63,441 @@ * - strip Tunnel Encap attr * - copy all ECs */ -static void -encap_attr_export_ce ( - struct attr *new, - struct attr *orig, - struct prefix *use_nexthop) +static void encap_attr_export_ce(struct attr *new, struct attr *orig, + struct prefix *use_nexthop) { - /* - * Make "new" a ghost attr copy of "orig" - */ - memset (new, 0, sizeof (struct attr)); - bgp_attr_dup (new, orig); - - /* - * Set nexthop - */ - switch (use_nexthop->family) - { - case AF_INET: - new->nexthop = use_nexthop->u.prefix4; - new->mp_nexthop_len = 4; /* bytes */ - new->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP); - break; - - case AF_INET6: - new->mp_nexthop_global = use_nexthop->u.prefix6; - new->mp_nexthop_len = 16; /* bytes */ - break; - - default: - assert (0); - break; - } - - /* - * Set MED - * - * Note that it will be deleted when BGP sends to any eBGP - * peer unless PEER_FLAG_MED_UNCHANGED is set: - * - * neighbor NEIGHBOR attribute-unchanged med - */ - if (!CHECK_FLAG (new->flag, BGP_ATTR_MULTI_EXIT_DISC)) - { - if (CHECK_FLAG (new->flag, BGP_ATTR_LOCAL_PREF)) - { - if (new->local_pref > 255) - new->med = 0; - else - new->med = 255 - new->local_pref; - } - else - { - new->med = 255; /* shouldn't happen */ - } - new->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); - } - - /* - * "new" is now a ghost attr: - * - it owns an "extra" struct - * - it owns any non-interned parts - * - any references to interned parts are not counted - * - * Caller should, after using the attr, call: - * - bgp_attr_flush() to free non-interned parts - */ + /* + * Make "new" a ghost attr copy of "orig" + */ + memset(new, 0, sizeof(struct attr)); + bgp_attr_dup(new, orig); + + /* + * Set nexthop + */ + switch (use_nexthop->family) { + case AF_INET: + new->nexthop = use_nexthop->u.prefix4; + new->mp_nexthop_len = 4; /* bytes */ + new->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); + break; + + case AF_INET6: + new->mp_nexthop_global = use_nexthop->u.prefix6; + new->mp_nexthop_len = 16; /* bytes */ + break; + + default: + assert(0); + break; + } + + /* + * Set MED + * + * Note that it will be deleted when BGP sends to any eBGP + * peer unless PEER_FLAG_MED_UNCHANGED is set: + * + * neighbor NEIGHBOR attribute-unchanged med + */ + if (!CHECK_FLAG(new->flag, BGP_ATTR_MULTI_EXIT_DISC)) { + if (CHECK_FLAG(new->flag, BGP_ATTR_LOCAL_PREF)) { + if (new->local_pref > 255) + new->med = 0; + else + new->med = 255 - new->local_pref; + } else { + new->med = 255; /* shouldn't happen */ + } + new->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); + } + + /* + * "new" is now a ghost attr: + * - it owns an "extra" struct + * - it owns any non-interned parts + * - any references to interned parts are not counted + * + * Caller should, after using the attr, call: + * - bgp_attr_flush() to free non-interned parts + */ } -static int -getce (struct bgp *bgp, struct attr *attr, struct prefix *pfx_ce) +static int getce(struct bgp *bgp, struct attr *attr, struct prefix *pfx_ce) { - uint8_t *ecp; - int i; - uint16_t localadmin = bgp->rfapi_cfg->resolve_nve_roo_local_admin; - - for (ecp = attr->ecommunity->val, i = 0; - i < attr->ecommunity->size; ++i, ecp += ECOMMUNITY_SIZE) - { - - if (VNC_DEBUG(EXPORT_BGP_GETCE)) - { - vnc_zlog_debug_any ("%s: %02x %02x %02x %02x %02x %02x %02x %02x", - __func__, - ecp[0], ecp[1], ecp[2], ecp[3], ecp[4], ecp[5], ecp[6], - ecp[7]); - } - - /* - * is it ROO? - */ - if (ecp[0] != 1 || ecp[1] != 3) - { - continue; - } - - /* - * Match local admin value? - */ - if (ecp[6] != ((localadmin & 0xff00) >> 8) || - ecp[7] != (localadmin & 0xff)) - continue; - - memset ((uint8_t *) pfx_ce, 0, sizeof (*pfx_ce)); - memcpy (&pfx_ce->u.prefix4, ecp + 2, 4); - pfx_ce->family = AF_INET; - pfx_ce->prefixlen = 32; - - return 0; - } - return -1; + uint8_t *ecp; + int i; + uint16_t localadmin = bgp->rfapi_cfg->resolve_nve_roo_local_admin; + + for (ecp = attr->ecommunity->val, i = 0; i < attr->ecommunity->size; + ++i, ecp += ECOMMUNITY_SIZE) { + + if (VNC_DEBUG(EXPORT_BGP_GETCE)) { + vnc_zlog_debug_any( + "%s: %02x %02x %02x %02x %02x %02x %02x %02x", + __func__, ecp[0], ecp[1], ecp[2], ecp[3], + ecp[4], ecp[5], ecp[6], ecp[7]); + } + + /* + * is it ROO? + */ + if (ecp[0] != 1 || ecp[1] != 3) { + continue; + } + + /* + * Match local admin value? + */ + if (ecp[6] != ((localadmin & 0xff00) >> 8) + || ecp[7] != (localadmin & 0xff)) + continue; + + memset((uint8_t *)pfx_ce, 0, sizeof(*pfx_ce)); + memcpy(&pfx_ce->u.prefix4, ecp + 2, 4); + pfx_ce->family = AF_INET; + pfx_ce->prefixlen = 32; + + return 0; + } + return -1; } -void -vnc_direct_bgp_add_route_ce ( - struct bgp *bgp, - struct route_node *rn, - struct bgp_info *bi) +void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct route_node *rn, + struct bgp_info *bi) { - struct attr *attr = bi->attr; - struct peer *peer = bi->peer; - struct prefix *prefix = &rn->p; - afi_t afi = family2afi (prefix->family); - struct bgp_node *urn; - struct bgp_info *ubi; - struct attr hattr; - struct attr *iattr; - struct prefix ce_nexthop; - struct prefix post_routemap_nexthop; - - - if (!afi) - { - zlog_err ("%s: can't get afi of route node", __func__); - return; - } - - if ((bi->type != ZEBRA_ROUTE_BGP) || - (bi->sub_type != BGP_ROUTE_NORMAL && - bi->sub_type != BGP_ROUTE_RFP && bi->sub_type != BGP_ROUTE_STATIC)) - { - - vnc_zlog_debug_verbose ("%s: wrong route type/sub_type for export, skipping", - __func__); - return; - } - - /* check bgp redist flag for vnc direct ("vpn") routes */ - if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) - { - vnc_zlog_debug_verbose ("%s: bgp redistribution of VNC direct routes is off", - __func__); - return; - } - - if (!bgp->rfapi_cfg) - { - vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__); - return; - } - - if (!VNC_EXPORT_BGP_CE_ENABLED (bgp->rfapi_cfg)) - { - vnc_zlog_debug_verbose ("%s: export-to-bgp ce mode not enabled, skipping", - __func__); - return; - } - - /* - * prefix list check - */ - if (bgp->rfapi_cfg->plist_export_bgp[afi]) - { - if (prefix_list_apply (bgp->rfapi_cfg->plist_export_bgp[afi], prefix) == - PREFIX_DENY) - { - vnc_zlog_debug_verbose ("%s: prefix list denied, skipping", __func__); - return; - } - } - - - /* - * Extract CE - * This works only for IPv4 because IPv6 addresses are too big - * to fit in an extended community - */ - if (getce (bgp, attr, &ce_nexthop)) - { - vnc_zlog_debug_verbose ("%s: EC has no encoded CE, skipping", __func__); - return; - } - - /* - * Is this route already represented in the unicast RIB? - * (look up prefix; compare route type, sub_type, peer, nexthop) - */ - urn = - bgp_afi_node_get (bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST, prefix, - NULL); - for (ubi = urn->info; ubi; ubi = ubi->next) - { - struct prefix unicast_nexthop; - - if (CHECK_FLAG (ubi->flags, BGP_INFO_REMOVED)) - continue; - - rfapiUnicastNexthop2Prefix (afi, ubi->attr, &unicast_nexthop); - - if (ubi->type == ZEBRA_ROUTE_VNC_DIRECT && - ubi->sub_type == BGP_ROUTE_REDISTRIBUTE && - ubi->peer == peer && prefix_same (&unicast_nexthop, &ce_nexthop)) - { - - vnc_zlog_debug_verbose - ("%s: already have matching exported unicast route, skipping", - __func__); - return; - } - } - - /* - * Construct new attribute set with CE addr as - * nexthop and without Tunnel Encap attr - */ - encap_attr_export_ce (&hattr, attr, &ce_nexthop); - if (bgp->rfapi_cfg->routemap_export_bgp) - { - struct bgp_info info; - route_map_result_t ret; - - memset (&info, 0, sizeof (info)); - info.peer = peer; - info.attr = &hattr; - ret = - route_map_apply (bgp->rfapi_cfg->routemap_export_bgp, prefix, - RMAP_BGP, &info); - if (ret == RMAP_DENYMATCH) - { - bgp_attr_flush (&hattr); - return; - } - } - - iattr = bgp_attr_intern (&hattr); - bgp_attr_flush (&hattr); - - /* - * Rule: disallow route-map alteration of next-hop, because it - * would make it too difficult to keep track of the correspondence - * between VPN routes and unicast routes. - */ - rfapiUnicastNexthop2Prefix (afi, iattr, &post_routemap_nexthop); - - if (!prefix_same (&ce_nexthop, &post_routemap_nexthop)) - { - vnc_zlog_debug_verbose - ("%s: route-map modification of nexthop not allowed, skipping", - __func__); - bgp_attr_unintern (&iattr); - return; - } - - bgp_update (peer, prefix, - 0, /* addpath_id */ - iattr, /* bgp_update copies this attr */ - afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ - NULL, /* tag not used for unicast */ - 0, NULL); /* EVPN not used */ - bgp_attr_unintern (&iattr); + struct attr *attr = bi->attr; + struct peer *peer = bi->peer; + struct prefix *prefix = &rn->p; + afi_t afi = family2afi(prefix->family); + struct bgp_node *urn; + struct bgp_info *ubi; + struct attr hattr; + struct attr *iattr; + struct prefix ce_nexthop; + struct prefix post_routemap_nexthop; + + + if (!afi) { + zlog_err("%s: can't get afi of route node", __func__); + return; + } + + if ((bi->type != ZEBRA_ROUTE_BGP) + || (bi->sub_type != BGP_ROUTE_NORMAL + && bi->sub_type != BGP_ROUTE_RFP + && bi->sub_type != BGP_ROUTE_STATIC)) { + + vnc_zlog_debug_verbose( + "%s: wrong route type/sub_type for export, skipping", + __func__); + return; + } + + /* check bgp redist flag for vnc direct ("vpn") routes */ + if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) { + vnc_zlog_debug_verbose( + "%s: bgp redistribution of VNC direct routes is off", + __func__); + return; + } + + if (!bgp->rfapi_cfg) { + vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", + __func__); + return; + } + + if (!VNC_EXPORT_BGP_CE_ENABLED(bgp->rfapi_cfg)) { + vnc_zlog_debug_verbose( + "%s: export-to-bgp ce mode not enabled, skipping", + __func__); + return; + } + + /* + * prefix list check + */ + if (bgp->rfapi_cfg->plist_export_bgp[afi]) { + if (prefix_list_apply(bgp->rfapi_cfg->plist_export_bgp[afi], + prefix) + == PREFIX_DENY) { + vnc_zlog_debug_verbose( + "%s: prefix list denied, skipping", __func__); + return; + } + } + + + /* + * Extract CE + * This works only for IPv4 because IPv6 addresses are too big + * to fit in an extended community + */ + if (getce(bgp, attr, &ce_nexthop)) { + vnc_zlog_debug_verbose("%s: EC has no encoded CE, skipping", + __func__); + return; + } + + /* + * Is this route already represented in the unicast RIB? + * (look up prefix; compare route type, sub_type, peer, nexthop) + */ + urn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST, + prefix, NULL); + for (ubi = urn->info; ubi; ubi = ubi->next) { + struct prefix unicast_nexthop; + + if (CHECK_FLAG(ubi->flags, BGP_INFO_REMOVED)) + continue; + + rfapiUnicastNexthop2Prefix(afi, ubi->attr, &unicast_nexthop); + + if (ubi->type == ZEBRA_ROUTE_VNC_DIRECT + && ubi->sub_type == BGP_ROUTE_REDISTRIBUTE + && ubi->peer == peer + && prefix_same(&unicast_nexthop, &ce_nexthop)) { + + vnc_zlog_debug_verbose( + "%s: already have matching exported unicast route, skipping", + __func__); + return; + } + } + + /* + * Construct new attribute set with CE addr as + * nexthop and without Tunnel Encap attr + */ + encap_attr_export_ce(&hattr, attr, &ce_nexthop); + if (bgp->rfapi_cfg->routemap_export_bgp) { + struct bgp_info info; + route_map_result_t ret; + + memset(&info, 0, sizeof(info)); + info.peer = peer; + info.attr = &hattr; + ret = route_map_apply(bgp->rfapi_cfg->routemap_export_bgp, + prefix, RMAP_BGP, &info); + if (ret == RMAP_DENYMATCH) { + bgp_attr_flush(&hattr); + return; + } + } + + iattr = bgp_attr_intern(&hattr); + bgp_attr_flush(&hattr); + + /* + * Rule: disallow route-map alteration of next-hop, because it + * would make it too difficult to keep track of the correspondence + * between VPN routes and unicast routes. + */ + rfapiUnicastNexthop2Prefix(afi, iattr, &post_routemap_nexthop); + + if (!prefix_same(&ce_nexthop, &post_routemap_nexthop)) { + vnc_zlog_debug_verbose( + "%s: route-map modification of nexthop not allowed, skipping", + __func__); + bgp_attr_unintern(&iattr); + return; + } + + bgp_update(peer, prefix, 0, /* addpath_id */ + iattr, /* bgp_update copies this attr */ + afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, + BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ + NULL, /* tag not used for unicast */ + 0, NULL); /* EVPN not used */ + bgp_attr_unintern(&iattr); } /* * "Withdrawing a Route" export process */ -void -vnc_direct_bgp_del_route_ce ( - struct bgp *bgp, - struct route_node *rn, - struct bgp_info *bi) +void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct route_node *rn, + struct bgp_info *bi) { - afi_t afi = family2afi (rn->p.family); - struct bgp_info *vbi; - struct prefix ce_nexthop; - - if (!afi) - { - zlog_err ("%s: bad afi", __func__); - return; - } - - /* check bgp redist flag for vnc direct ("vpn") routes */ - if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) - { - vnc_zlog_debug_verbose ("%s: bgp redistribution of VNC direct routes is off", - __func__); - return; - } - - if (!bgp->rfapi_cfg) - { - vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__); - return; - } - if (!VNC_EXPORT_BGP_CE_ENABLED (bgp->rfapi_cfg)) - { - vnc_zlog_debug_verbose ("%s: export-to-bgp ce mode not enabled, skipping", - __func__); - return; - } - - /* - * Extract CE - * This works only for IPv4 because IPv6 addresses are too big - * to fit in an extended community - */ - if (getce (bgp, bi->attr, &ce_nexthop)) - { - vnc_zlog_debug_verbose ("%s: EC has no encoded CE, skipping", __func__); - return; - } - - /* - * Look for other VPN routes with same prefix, same 5226 CE, - * same peer. If at least one is present, don't remove the - * route from the unicast RIB - */ - - for (vbi = rn->info; vbi; vbi = vbi->next) - { - struct prefix ce; - if (bi == vbi) - continue; - if (bi->peer != vbi->peer) - continue; - if (getce (bgp, vbi->attr, &ce)) - continue; - if (prefix_same (&ce, &ce_nexthop)) - { - vnc_zlog_debug_verbose ("%s: still have a route via CE, not deleting unicast", - __func__); - return; - } - } - - /* - * withdraw the route - */ - bgp_withdraw (bi->peer, &rn->p, - 0, /* addpath_id */ - NULL, /* attr, ignored */ - afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ - NULL, NULL); /* tag not used for unicast */ + afi_t afi = family2afi(rn->p.family); + struct bgp_info *vbi; + struct prefix ce_nexthop; + + if (!afi) { + zlog_err("%s: bad afi", __func__); + return; + } + + /* check bgp redist flag for vnc direct ("vpn") routes */ + if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) { + vnc_zlog_debug_verbose( + "%s: bgp redistribution of VNC direct routes is off", + __func__); + return; + } + + if (!bgp->rfapi_cfg) { + vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", + __func__); + return; + } + if (!VNC_EXPORT_BGP_CE_ENABLED(bgp->rfapi_cfg)) { + vnc_zlog_debug_verbose( + "%s: export-to-bgp ce mode not enabled, skipping", + __func__); + return; + } + + /* + * Extract CE + * This works only for IPv4 because IPv6 addresses are too big + * to fit in an extended community + */ + if (getce(bgp, bi->attr, &ce_nexthop)) { + vnc_zlog_debug_verbose("%s: EC has no encoded CE, skipping", + __func__); + return; + } + + /* + * Look for other VPN routes with same prefix, same 5226 CE, + * same peer. If at least one is present, don't remove the + * route from the unicast RIB + */ + + for (vbi = rn->info; vbi; vbi = vbi->next) { + struct prefix ce; + if (bi == vbi) + continue; + if (bi->peer != vbi->peer) + continue; + if (getce(bgp, vbi->attr, &ce)) + continue; + if (prefix_same(&ce, &ce_nexthop)) { + vnc_zlog_debug_verbose( + "%s: still have a route via CE, not deleting unicast", + __func__); + return; + } + } + /* + * withdraw the route + */ + bgp_withdraw(bi->peer, &rn->p, 0, /* addpath_id */ + NULL, /* attr, ignored */ + afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, + BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ + NULL, NULL); /* tag not used for unicast */ } -static void -vnc_direct_bgp_vpn_enable_ce (struct bgp *bgp, afi_t afi) +static void vnc_direct_bgp_vpn_enable_ce(struct bgp *bgp, afi_t afi) { - struct rfapi_cfg *hc; - struct route_node *rn; - struct bgp_info *ri; + struct rfapi_cfg *hc; + struct route_node *rn; + struct bgp_info *ri; - vnc_zlog_debug_verbose ("%s: entry, afi=%d", __func__, afi); + vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi); - if (!bgp) - return; + if (!bgp) + return; - if (!(hc = bgp->rfapi_cfg)) - return; + if (!(hc = bgp->rfapi_cfg)) + return; - if (!VNC_EXPORT_BGP_CE_ENABLED (bgp->rfapi_cfg)) - { - vnc_zlog_debug_verbose ("%s: export of CE routes not enabled, skipping", __func__); - return; - } - - if (afi != AFI_IP - && afi != AFI_IP6) - { - vnc_zlog_debug_verbose ("%s: bad afi: %d", __func__, afi); - return; - } + if (!VNC_EXPORT_BGP_CE_ENABLED(bgp->rfapi_cfg)) { + vnc_zlog_debug_verbose( + "%s: export of CE routes not enabled, skipping", + __func__); + return; + } - /* - * Go through entire ce import table and export to BGP unicast. - */ - for (rn = route_top (bgp->rfapi->it_ce->imported_vpn[afi]); rn; - rn = route_next (rn)) - { + if (afi != AFI_IP && afi != AFI_IP6) { + vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi); + return; + } - if (!rn->info) - continue; + /* + * Go through entire ce import table and export to BGP unicast. + */ + for (rn = route_top(bgp->rfapi->it_ce->imported_vpn[afi]); rn; + rn = route_next(rn)) { - { - char prefixstr[BUFSIZ]; + if (!rn->info) + continue; - prefixstr[0] = 0; - inet_ntop (rn->p.family, &rn->p.u.prefix, prefixstr, BUFSIZ); - vnc_zlog_debug_verbose ("%s: checking prefix %s/%d", __func__, prefixstr, - rn->p.prefixlen); - } + { + char prefixstr[BUFSIZ]; - for (ri = rn->info; ri; ri = ri->next) - { + prefixstr[0] = 0; + inet_ntop(rn->p.family, &rn->p.u.prefix, prefixstr, + BUFSIZ); + vnc_zlog_debug_verbose("%s: checking prefix %s/%d", + __func__, prefixstr, + rn->p.prefixlen); + } - vnc_zlog_debug_verbose ("%s: ri->sub_type: %d", __func__, ri->sub_type); + for (ri = rn->info; ri; ri = ri->next) { - if (ri->sub_type == BGP_ROUTE_NORMAL || - ri->sub_type == BGP_ROUTE_RFP || - ri->sub_type == BGP_ROUTE_STATIC) - { + vnc_zlog_debug_verbose("%s: ri->sub_type: %d", __func__, + ri->sub_type); - vnc_direct_bgp_add_route_ce (bgp, rn, ri); - } + if (ri->sub_type == BGP_ROUTE_NORMAL + || ri->sub_type == BGP_ROUTE_RFP + || ri->sub_type == BGP_ROUTE_STATIC) { - } - } + vnc_direct_bgp_add_route_ce(bgp, rn, ri); + } + } + } } -static void -vnc_direct_bgp_vpn_disable_ce (struct bgp *bgp, afi_t afi) +static void vnc_direct_bgp_vpn_disable_ce(struct bgp *bgp, afi_t afi) { - struct bgp_node *rn; - - vnc_zlog_debug_verbose ("%s: entry, afi=%d", __func__, afi); - - if (!bgp) - return; - - if (afi != AFI_IP - && afi != AFI_IP6) - { - vnc_zlog_debug_verbose ("%s: bad afi: %d", __func__, afi); - return; - } - - /* - * Go through the entire BGP unicast table and remove routes that - * originated from us - */ - for (rn = bgp_table_top (bgp->rib[afi][SAFI_UNICAST]); rn; - rn = bgp_route_next (rn)) - { - - struct bgp_info *ri; - struct bgp_info *next; - - for (ri = rn->info, next = NULL; ri; ri = next) - { - - next = ri->next; - - if (ri->type == ZEBRA_ROUTE_VNC_DIRECT && - ri->sub_type == BGP_ROUTE_REDISTRIBUTE) - { - - bgp_withdraw (ri->peer, &rn->p, /* prefix */ - 0, /* addpath_id */ - NULL, /* ignored */ - AFI_IP, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ - NULL, NULL); /* tag not used for unicast */ - } - } - } + struct bgp_node *rn; + + vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi); + + if (!bgp) + return; + + if (afi != AFI_IP && afi != AFI_IP6) { + vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi); + return; + } + + /* + * Go through the entire BGP unicast table and remove routes that + * originated from us + */ + for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn; + rn = bgp_route_next(rn)) { + + struct bgp_info *ri; + struct bgp_info *next; + + for (ri = rn->info, next = NULL; ri; ri = next) { + + next = ri->next; + + if (ri->type == ZEBRA_ROUTE_VNC_DIRECT + && ri->sub_type == BGP_ROUTE_REDISTRIBUTE) { + + bgp_withdraw( + ri->peer, &rn->p, /* prefix */ + 0, /* addpath_id */ + NULL, /* ignored */ + AFI_IP, SAFI_UNICAST, + ZEBRA_ROUTE_VNC_DIRECT, + BGP_ROUTE_REDISTRIBUTE, + NULL, /* RD not used for unicast */ + NULL, + NULL); /* tag not used for unicast */ + } + } + } } /*********************************************************************** @@ -539,73 +508,68 @@ vnc_direct_bgp_vpn_disable_ce (struct bgp *bgp, afi_t afi) * Export methods that proxy nexthop BEGIN ***********************************************************************/ -static struct ecommunity * -vnc_route_origin_ecom (struct route_node *rn) +static struct ecommunity *vnc_route_origin_ecom(struct route_node *rn) { - struct ecommunity *new; - struct bgp_info *bi; - - if (!rn->info) - return NULL; - - new = ecommunity_new (); - - for (bi = rn->info; bi; bi = bi->next) - { - - struct ecommunity_val roec; - - switch (BGP_MP_NEXTHOP_FAMILY (bi->attr->mp_nexthop_len)) - { - case AF_INET: - memset (&roec, 0, sizeof (roec)); - roec.val[0] = 0x01; - roec.val[1] = 0x03; - memcpy (roec.val + 2, - &bi->attr->mp_nexthop_global_in.s_addr, 4); - roec.val[6] = 0; - roec.val[7] = 0; - ecommunity_add_val (new, &roec); - break; - case AF_INET6: - /* No support for IPv6 addresses in extended communities */ - break; - } - } - - if (!new->size) - { - ecommunity_free (&new); - new = NULL; - } - - return new; + struct ecommunity *new; + struct bgp_info *bi; + + if (!rn->info) + return NULL; + + new = ecommunity_new(); + + for (bi = rn->info; bi; bi = bi->next) { + + struct ecommunity_val roec; + + switch (BGP_MP_NEXTHOP_FAMILY(bi->attr->mp_nexthop_len)) { + case AF_INET: + memset(&roec, 0, sizeof(roec)); + roec.val[0] = 0x01; + roec.val[1] = 0x03; + memcpy(roec.val + 2, + &bi->attr->mp_nexthop_global_in.s_addr, 4); + roec.val[6] = 0; + roec.val[7] = 0; + ecommunity_add_val(new, &roec); + break; + case AF_INET6: + /* No support for IPv6 addresses in extended communities + */ + break; + } + } + + if (!new->size) { + ecommunity_free(&new); + new = NULL; + } + + return new; } -static struct ecommunity * -vnc_route_origin_ecom_single (struct in_addr *origin) +static struct ecommunity *vnc_route_origin_ecom_single(struct in_addr *origin) { - struct ecommunity *new; - struct ecommunity_val roec; - - memset (&roec, 0, sizeof (roec)); - roec.val[0] = 0x01; - roec.val[1] = 0x03; - memcpy (roec.val + 2, &origin->s_addr, 4); - roec.val[6] = 0; - roec.val[7] = 0; - - new = ecommunity_new (); - assert (new); - ecommunity_add_val (new, &roec); - - if (!new->size) - { - ecommunity_free (&new); - new = NULL; - } - - return new; + struct ecommunity *new; + struct ecommunity_val roec; + + memset(&roec, 0, sizeof(roec)); + roec.val[0] = 0x01; + roec.val[1] = 0x03; + memcpy(roec.val + 2, &origin->s_addr, 4); + roec.val[6] = 0; + roec.val[7] = 0; + + new = ecommunity_new(); + assert(new); + ecommunity_add_val(new, &roec); + + if (!new->size) { + ecommunity_free(&new); + new = NULL; + } + + return new; } @@ -615,750 +579,722 @@ vnc_route_origin_ecom_single (struct in_addr *origin) * memory is allocated by caller. */ static int -encap_attr_export ( - struct attr *new, - struct attr *orig, - struct prefix *new_nexthop, - struct route_node *rn) /* for VN addrs for ecom list */ - /* if rn is 0, use route's nexthop */ +encap_attr_export(struct attr *new, struct attr *orig, + struct prefix *new_nexthop, + struct route_node *rn) /* for VN addrs for ecom list */ + /* if rn is 0, use route's nexthop */ { - struct prefix orig_nexthop; - struct prefix *use_nexthop; - static struct ecommunity *ecom_ro; - - if (new_nexthop) - { - use_nexthop = new_nexthop; - } - else - { - use_nexthop = &orig_nexthop; - orig_nexthop.family = - BGP_MP_NEXTHOP_FAMILY (orig->mp_nexthop_len); - if (orig_nexthop.family == AF_INET) - { - orig_nexthop.prefixlen = 32; - orig_nexthop.u.prefix4 = orig->mp_nexthop_global_in; - } - else if (orig_nexthop.family == AF_INET6) - { - orig_nexthop.prefixlen = 128; - orig_nexthop.u.prefix6 = orig->mp_nexthop_global; - } - else - { - return -1; /* FAIL - can't compute nexthop */ - } - } - - - /* - * Make "new" a ghost attr copy of "orig" - */ - memset (new, 0, sizeof (struct attr)); - bgp_attr_dup (new, orig); - - /* - * Set nexthop - */ - switch (use_nexthop->family) - { - case AF_INET: - new->nexthop = use_nexthop->u.prefix4; - new->mp_nexthop_len = 4; /* bytes */ - new->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP); - break; - - case AF_INET6: - new->mp_nexthop_global = use_nexthop->u.prefix6; - new->mp_nexthop_len = 16; /* bytes */ - break; - - default: - assert (0); - break; - } - - if (rn) - { - ecom_ro = vnc_route_origin_ecom (rn); - } - else - { - /* TBD test/assert for IPv6 */ - ecom_ro = vnc_route_origin_ecom_single (&use_nexthop->u.prefix4); - } - if (new->ecommunity) - { - if (ecom_ro) - new->ecommunity = ecommunity_merge (ecom_ro, new->ecommunity); - } - else - { - new->ecommunity = ecom_ro; - } - if (ecom_ro) - { - new->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES); - } - - /* - * Set MED - * - * Note that it will be deleted when BGP sends to any eBGP - * peer unless PEER_FLAG_MED_UNCHANGED is set: - * - * neighbor NEIGHBOR attribute-unchanged med - */ - if (!CHECK_FLAG (new->flag, BGP_ATTR_MULTI_EXIT_DISC)) - { - if (CHECK_FLAG (new->flag, BGP_ATTR_LOCAL_PREF)) - { - if (new->local_pref > 255) - new->med = 0; - else - new->med = 255 - new->local_pref; - } - else - { - new->med = 255; /* shouldn't happen */ - } - new->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); - } - - /* - * "new" is now a ghost attr: - * - it owns an "extra" struct - * - it owns any non-interned parts - * - any references to interned parts are not counted - * - * Caller should, after using the attr, call: - * - bgp_attr_flush() to free non-interned parts - */ - - return 0; + struct prefix orig_nexthop; + struct prefix *use_nexthop; + static struct ecommunity *ecom_ro; + + if (new_nexthop) { + use_nexthop = new_nexthop; + } else { + use_nexthop = &orig_nexthop; + orig_nexthop.family = + BGP_MP_NEXTHOP_FAMILY(orig->mp_nexthop_len); + if (orig_nexthop.family == AF_INET) { + orig_nexthop.prefixlen = 32; + orig_nexthop.u.prefix4 = orig->mp_nexthop_global_in; + } else if (orig_nexthop.family == AF_INET6) { + orig_nexthop.prefixlen = 128; + orig_nexthop.u.prefix6 = orig->mp_nexthop_global; + } else { + return -1; /* FAIL - can't compute nexthop */ + } + } + + + /* + * Make "new" a ghost attr copy of "orig" + */ + memset(new, 0, sizeof(struct attr)); + bgp_attr_dup(new, orig); + + /* + * Set nexthop + */ + switch (use_nexthop->family) { + case AF_INET: + new->nexthop = use_nexthop->u.prefix4; + new->mp_nexthop_len = 4; /* bytes */ + new->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); + break; + + case AF_INET6: + new->mp_nexthop_global = use_nexthop->u.prefix6; + new->mp_nexthop_len = 16; /* bytes */ + break; + + default: + assert(0); + break; + } + + if (rn) { + ecom_ro = vnc_route_origin_ecom(rn); + } else { + /* TBD test/assert for IPv6 */ + ecom_ro = vnc_route_origin_ecom_single(&use_nexthop->u.prefix4); + } + if (new->ecommunity) { + if (ecom_ro) + new->ecommunity = + ecommunity_merge(ecom_ro, new->ecommunity); + } else { + new->ecommunity = ecom_ro; + } + if (ecom_ro) { + new->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES); + } + + /* + * Set MED + * + * Note that it will be deleted when BGP sends to any eBGP + * peer unless PEER_FLAG_MED_UNCHANGED is set: + * + * neighbor NEIGHBOR attribute-unchanged med + */ + if (!CHECK_FLAG(new->flag, BGP_ATTR_MULTI_EXIT_DISC)) { + if (CHECK_FLAG(new->flag, BGP_ATTR_LOCAL_PREF)) { + if (new->local_pref > 255) + new->med = 0; + else + new->med = 255 - new->local_pref; + } else { + new->med = 255; /* shouldn't happen */ + } + new->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); + } + + /* + * "new" is now a ghost attr: + * - it owns an "extra" struct + * - it owns any non-interned parts + * - any references to interned parts are not counted + * + * Caller should, after using the attr, call: + * - bgp_attr_flush() to free non-interned parts + */ + + return 0; } /* * "Adding a Route" export process */ -void -vnc_direct_bgp_add_prefix ( - struct bgp *bgp, - struct rfapi_import_table *import_table, - struct route_node *rn) +void vnc_direct_bgp_add_prefix(struct bgp *bgp, + struct rfapi_import_table *import_table, + struct route_node *rn) { - struct attr attr = { 0 }; - struct listnode *node, *nnode; - struct rfapi_rfg_name *rfgn; - afi_t afi = family2afi (rn->p.family); - - if (!afi) - { - zlog_err ("%s: can't get afi of route node", __func__); - return; - } - - /* check bgp redist flag for vnc direct ("vpn") routes */ - if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) - { - vnc_zlog_debug_verbose ("%s: bgp redistribution of VNC direct routes is off", - __func__); - return; - } - - if (!bgp->rfapi_cfg) - { - vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__); - return; - } - - if (!VNC_EXPORT_BGP_GRP_ENABLED (bgp->rfapi_cfg)) - { - vnc_zlog_debug_verbose ("%s: export-to-bgp group mode not enabled, skipping", - __func__); - return; - } - - if (!listcount (bgp->rfapi_cfg->rfg_export_direct_bgp_l)) - { - vnc_zlog_debug_verbose ("%s: no bgp-direct export nve group, skipping", __func__); - return; - } - - bgp_attr_default_set (&attr, BGP_ORIGIN_INCOMPLETE); - /* TBD set some configured med, see add_vnc_route() */ - - vnc_zlog_debug_verbose ("%s: looping over nve-groups in direct-bgp export list", - __func__); - - for (ALL_LIST_ELEMENTS (bgp->rfapi_cfg->rfg_export_direct_bgp_l, - node, nnode, rfgn)) - { - - struct listnode *ln; - - /* - * If nve group is not defined yet, skip it - */ - if (!rfgn->rfg) - continue; - - /* - * If the nve group uses a different import table, skip it - */ - if (import_table != rfgn->rfg->rfapi_import_table) - continue; - - /* - * if no NVEs currently associated with this group, skip it - */ - if (!rfgn->rfg->nves) - continue; - - /* - * per-nve-group prefix list check - */ - if (rfgn->rfg->plist_export_bgp[afi]) - { - if (prefix_list_apply (rfgn->rfg->plist_export_bgp[afi], &rn->p) == - PREFIX_DENY) - - continue; - } - - /* - * For each NVE that is assigned to the export nve group, generate - * a route with that NVE as its next hop - */ - for (ln = listhead (rfgn->rfg->nves); ln; ln = listnextnode (ln)) - { - - struct prefix nhp; - struct rfapi_descriptor *irfd; - struct bgp_info info; - struct attr hattr; - struct attr *iattr; - - irfd = listgetdata (ln); - - if (rfapiRaddr2Qprefix (&irfd->vn_addr, &nhp)) - continue; - - /* - * Construct new attribute set with NVE's VN addr as - * nexthop and without Tunnel Encap attr - */ - if (encap_attr_export (&hattr, &attr, &nhp, rn)) - continue; - - if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD)) - { - vnc_zlog_debug_any ("%s: attr follows", __func__); - rfapiPrintAttrPtrs (NULL, &attr); - vnc_zlog_debug_any ("%s: hattr follows", __func__); - rfapiPrintAttrPtrs (NULL, &hattr); - } - - if (rfgn->rfg->routemap_export_bgp) - { - route_map_result_t ret; - info.peer = irfd->peer; - info.attr = &hattr; - ret = route_map_apply (rfgn->rfg->routemap_export_bgp, &rn->p, - RMAP_BGP, &info); - if (ret == RMAP_DENYMATCH) - { - bgp_attr_flush (&hattr); - vnc_zlog_debug_verbose - ("%s: route map says DENY, so not calling bgp_update", - __func__); - continue; - } - } - - if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD)) - { - vnc_zlog_debug_any ("%s: hattr after route_map_apply:", __func__); - rfapiPrintAttrPtrs (NULL, &hattr); - } - - iattr = bgp_attr_intern (&hattr); - bgp_attr_flush (&hattr); - - bgp_update (irfd->peer, &rn->p, /* prefix */ - 0, /* addpath_id */ - iattr, /* bgp_update copies it */ - afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ - NULL, /* tag not used for unicast */ - 0, NULL); /* EVPN not used */ - - bgp_attr_unintern (&iattr); - } - } - - aspath_unintern (&attr.aspath); + struct attr attr = {0}; + struct listnode *node, *nnode; + struct rfapi_rfg_name *rfgn; + afi_t afi = family2afi(rn->p.family); + + if (!afi) { + zlog_err("%s: can't get afi of route node", __func__); + return; + } + + /* check bgp redist flag for vnc direct ("vpn") routes */ + if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) { + vnc_zlog_debug_verbose( + "%s: bgp redistribution of VNC direct routes is off", + __func__); + return; + } + + if (!bgp->rfapi_cfg) { + vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", + __func__); + return; + } + + if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) { + vnc_zlog_debug_verbose( + "%s: export-to-bgp group mode not enabled, skipping", + __func__); + return; + } + + if (!listcount(bgp->rfapi_cfg->rfg_export_direct_bgp_l)) { + vnc_zlog_debug_verbose( + "%s: no bgp-direct export nve group, skipping", + __func__); + return; + } + + bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE); + /* TBD set some configured med, see add_vnc_route() */ + + vnc_zlog_debug_verbose( + "%s: looping over nve-groups in direct-bgp export list", + __func__); + + for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node, + nnode, rfgn)) { + + struct listnode *ln; + + /* + * If nve group is not defined yet, skip it + */ + if (!rfgn->rfg) + continue; + + /* + * If the nve group uses a different import table, skip it + */ + if (import_table != rfgn->rfg->rfapi_import_table) + continue; + + /* + * if no NVEs currently associated with this group, skip it + */ + if (!rfgn->rfg->nves) + continue; + + /* + * per-nve-group prefix list check + */ + if (rfgn->rfg->plist_export_bgp[afi]) { + if (prefix_list_apply(rfgn->rfg->plist_export_bgp[afi], + &rn->p) + == PREFIX_DENY) + + continue; + } + + /* + * For each NVE that is assigned to the export nve group, + * generate + * a route with that NVE as its next hop + */ + for (ln = listhead(rfgn->rfg->nves); ln; + ln = listnextnode(ln)) { + + struct prefix nhp; + struct rfapi_descriptor *irfd; + struct bgp_info info; + struct attr hattr; + struct attr *iattr; + + irfd = listgetdata(ln); + + if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp)) + continue; + + /* + * Construct new attribute set with NVE's VN addr as + * nexthop and without Tunnel Encap attr + */ + if (encap_attr_export(&hattr, &attr, &nhp, rn)) + continue; + + if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD)) { + vnc_zlog_debug_any("%s: attr follows", + __func__); + rfapiPrintAttrPtrs(NULL, &attr); + vnc_zlog_debug_any("%s: hattr follows", + __func__); + rfapiPrintAttrPtrs(NULL, &hattr); + } + + if (rfgn->rfg->routemap_export_bgp) { + route_map_result_t ret; + info.peer = irfd->peer; + info.attr = &hattr; + ret = route_map_apply( + rfgn->rfg->routemap_export_bgp, &rn->p, + RMAP_BGP, &info); + if (ret == RMAP_DENYMATCH) { + bgp_attr_flush(&hattr); + vnc_zlog_debug_verbose( + "%s: route map says DENY, so not calling bgp_update", + __func__); + continue; + } + } + + if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD)) { + vnc_zlog_debug_any( + "%s: hattr after route_map_apply:", + __func__); + rfapiPrintAttrPtrs(NULL, &hattr); + } + + iattr = bgp_attr_intern(&hattr); + bgp_attr_flush(&hattr); + + bgp_update(irfd->peer, &rn->p, /* prefix */ + 0, /* addpath_id */ + iattr, /* bgp_update copies it */ + afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, + BGP_ROUTE_REDISTRIBUTE, + NULL, /* RD not used for unicast */ + NULL, /* tag not used for unicast */ + 0, NULL); /* EVPN not used */ + + bgp_attr_unintern(&iattr); + } + } + + aspath_unintern(&attr.aspath); } /* * "Withdrawing a Route" export process */ -void -vnc_direct_bgp_del_prefix ( - struct bgp *bgp, - struct rfapi_import_table *import_table, - struct route_node *rn) +void vnc_direct_bgp_del_prefix(struct bgp *bgp, + struct rfapi_import_table *import_table, + struct route_node *rn) { - struct listnode *node, *nnode; - struct rfapi_rfg_name *rfgn; - afi_t afi = family2afi (rn->p.family); - - if (!afi) - { - zlog_err ("%s: can't get afi route node", __func__); - return; - } - - /* check bgp redist flag for vnc direct ("vpn") routes */ - if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) - { - vnc_zlog_debug_verbose ("%s: bgp redistribution of VNC direct routes is off", - __func__); - return; - } - - if (!bgp->rfapi_cfg) - { - vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__); - return; - } - - if (!VNC_EXPORT_BGP_GRP_ENABLED (bgp->rfapi_cfg)) - { - vnc_zlog_debug_verbose ("%s: export-to-bgp group mode not enabled, skipping", - __func__); - return; - } - - if (!listcount (bgp->rfapi_cfg->rfg_export_direct_bgp_l)) - { - vnc_zlog_debug_verbose ("%s: no bgp-direct export nve group, skipping", __func__); - return; - } - - for (ALL_LIST_ELEMENTS (bgp->rfapi_cfg->rfg_export_direct_bgp_l, - node, nnode, rfgn)) - { - - struct listnode *ln; - - /* - * If nve group is not defined yet, skip it - */ - if (!rfgn->rfg) - continue; - - /* - * if no NVEs currently associated with this group, skip it - */ - if (!rfgn->rfg->nves) - continue; - - /* - * If the nve group uses a different import table, - * skip it - */ - if (import_table != rfgn->rfg->rfapi_import_table) - continue; - - /* - * For each NVE that is assigned to the export nve group, generate - * a route with that NVE as its next hop - */ - for (ln = listhead (rfgn->rfg->nves); ln; ln = listnextnode (ln)) - { - - struct prefix nhp; - struct rfapi_descriptor *irfd; - - irfd = listgetdata (ln); - - if (rfapiRaddr2Qprefix (&irfd->vn_addr, &nhp)) - continue; - - bgp_withdraw (irfd->peer, &rn->p, /* prefix */ - 0, /* addpath_id */ - NULL, /* attr, ignored */ - afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ - NULL, NULL); /* tag not used for unicast */ - } - } + struct listnode *node, *nnode; + struct rfapi_rfg_name *rfgn; + afi_t afi = family2afi(rn->p.family); + + if (!afi) { + zlog_err("%s: can't get afi route node", __func__); + return; + } + + /* check bgp redist flag for vnc direct ("vpn") routes */ + if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) { + vnc_zlog_debug_verbose( + "%s: bgp redistribution of VNC direct routes is off", + __func__); + return; + } + + if (!bgp->rfapi_cfg) { + vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", + __func__); + return; + } + + if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) { + vnc_zlog_debug_verbose( + "%s: export-to-bgp group mode not enabled, skipping", + __func__); + return; + } + + if (!listcount(bgp->rfapi_cfg->rfg_export_direct_bgp_l)) { + vnc_zlog_debug_verbose( + "%s: no bgp-direct export nve group, skipping", + __func__); + return; + } + + for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node, + nnode, rfgn)) { + + struct listnode *ln; + + /* + * If nve group is not defined yet, skip it + */ + if (!rfgn->rfg) + continue; + + /* + * if no NVEs currently associated with this group, skip it + */ + if (!rfgn->rfg->nves) + continue; + + /* + * If the nve group uses a different import table, + * skip it + */ + if (import_table != rfgn->rfg->rfapi_import_table) + continue; + + /* + * For each NVE that is assigned to the export nve group, + * generate + * a route with that NVE as its next hop + */ + for (ln = listhead(rfgn->rfg->nves); ln; + ln = listnextnode(ln)) { + + struct prefix nhp; + struct rfapi_descriptor *irfd; + + irfd = listgetdata(ln); + + if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp)) + continue; + + bgp_withdraw(irfd->peer, &rn->p, /* prefix */ + 0, /* addpath_id */ + NULL, /* attr, ignored */ + afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, + BGP_ROUTE_REDISTRIBUTE, + NULL, /* RD not used for unicast */ + NULL, NULL); /* tag not used for unicast */ + } + } } -void -vnc_direct_bgp_add_nve (struct bgp *bgp, struct rfapi_descriptor *rfd) +void vnc_direct_bgp_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd) { - struct listnode *node, *nnode; - struct rfapi_rfg_name *rfgn; - struct rfapi_nve_group_cfg *rfg = rfd->rfg; - afi_t afi = family2afi (rfd->vn_addr.addr_family); - - if (!afi) - { - zlog_err ("%s: can't get afi of nve vn addr", __func__); - return; - } - - if (!bgp) - return; - if (!bgp->rfapi_cfg) - { - vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__); - return; - } - if (!VNC_EXPORT_BGP_GRP_ENABLED (bgp->rfapi_cfg)) - { - vnc_zlog_debug_verbose ("%s: export-to-bgp group mode not enabled, skipping", - __func__); - return; - } - - if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) - { - vnc_zlog_debug_verbose ("%s: bgp redistribution of VNC direct routes is off", - __func__); - return; - } - - /* - * Loop over the list of NVE-Groups configured for - * exporting to direct-bgp and see if this new NVE's - * group is among them. - */ - for (ALL_LIST_ELEMENTS (bgp->rfapi_cfg->rfg_export_direct_bgp_l, - node, nnode, rfgn)) - { - - /* - * Yes, this NVE's group is configured for export to direct-bgp - */ - if (rfgn->rfg == rfg) - { - - struct route_table *rt = NULL; - struct route_node *rn; - struct attr attr = { 0 }; - struct rfapi_import_table *import_table; - - - import_table = rfg->rfapi_import_table; - - bgp_attr_default_set (&attr, BGP_ORIGIN_INCOMPLETE); - /* TBD set some configured med, see add_vnc_route() */ - - if (afi == AFI_IP - || afi == AFI_IP6) - { - rt = import_table->imported_vpn[afi]; - } - else - { - zlog_err ("%s: bad afi %d", __func__, afi); - return; - } - - /* - * Walk the NVE-Group's VNC Import table - */ - for (rn = route_top (rt); rn; rn = route_next (rn)) - { - - if (rn->info) - { - - struct prefix nhp; - struct rfapi_descriptor *irfd = rfd; - struct attr hattr; - struct attr *iattr; - struct bgp_info info; - - if (rfapiRaddr2Qprefix (&irfd->vn_addr, &nhp)) - continue; - - /* - * per-nve-group prefix list check - */ - if (rfgn->rfg->plist_export_bgp[afi]) - { - if (prefix_list_apply (rfgn->rfg->plist_export_bgp[afi], - &rn->p) == PREFIX_DENY) - - continue; - } - - - /* - * Construct new attribute set with NVE's VN addr as - * nexthop and without Tunnel Encap attr - */ - if (encap_attr_export (&hattr, &attr, &nhp, rn)) - continue; - - if (rfgn->rfg->routemap_export_bgp) - { - route_map_result_t ret; - info.peer = irfd->peer; - info.attr = &hattr; - ret = route_map_apply (rfgn->rfg->routemap_export_bgp, - &rn->p, RMAP_BGP, &info); - if (ret == RMAP_DENYMATCH) - { - bgp_attr_flush (&hattr); - continue; - } - - } - - iattr = bgp_attr_intern (&hattr); - bgp_attr_flush (&hattr); - - bgp_update (irfd->peer, &rn->p, /* prefix */ - 0, /* addpath_id */ - iattr, /* bgp_update copies it */ - afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ - NULL, /* tag not used for unicast */ - 0, NULL); /* EVPN not used */ - - bgp_attr_unintern (&iattr); - - } - } - - aspath_unintern (&attr.aspath); - } - } + struct listnode *node, *nnode; + struct rfapi_rfg_name *rfgn; + struct rfapi_nve_group_cfg *rfg = rfd->rfg; + afi_t afi = family2afi(rfd->vn_addr.addr_family); + + if (!afi) { + zlog_err("%s: can't get afi of nve vn addr", __func__); + return; + } + + if (!bgp) + return; + if (!bgp->rfapi_cfg) { + vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", + __func__); + return; + } + if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) { + vnc_zlog_debug_verbose( + "%s: export-to-bgp group mode not enabled, skipping", + __func__); + return; + } + + if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) { + vnc_zlog_debug_verbose( + "%s: bgp redistribution of VNC direct routes is off", + __func__); + return; + } + + /* + * Loop over the list of NVE-Groups configured for + * exporting to direct-bgp and see if this new NVE's + * group is among them. + */ + for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node, + nnode, rfgn)) { + + /* + * Yes, this NVE's group is configured for export to direct-bgp + */ + if (rfgn->rfg == rfg) { + + struct route_table *rt = NULL; + struct route_node *rn; + struct attr attr = {0}; + struct rfapi_import_table *import_table; + + + import_table = rfg->rfapi_import_table; + + bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE); + /* TBD set some configured med, see add_vnc_route() */ + + if (afi == AFI_IP || afi == AFI_IP6) { + rt = import_table->imported_vpn[afi]; + } else { + zlog_err("%s: bad afi %d", __func__, afi); + return; + } + + /* + * Walk the NVE-Group's VNC Import table + */ + for (rn = route_top(rt); rn; rn = route_next(rn)) { + + if (rn->info) { + + struct prefix nhp; + struct rfapi_descriptor *irfd = rfd; + struct attr hattr; + struct attr *iattr; + struct bgp_info info; + + if (rfapiRaddr2Qprefix(&irfd->vn_addr, + &nhp)) + continue; + + /* + * per-nve-group prefix list check + */ + if (rfgn->rfg->plist_export_bgp[afi]) { + if (prefix_list_apply( + rfgn->rfg->plist_export_bgp + [afi], + &rn->p) + == PREFIX_DENY) + + continue; + } + + + /* + * Construct new attribute set with + * NVE's VN addr as + * nexthop and without Tunnel Encap attr + */ + if (encap_attr_export(&hattr, &attr, + &nhp, rn)) + continue; + + if (rfgn->rfg->routemap_export_bgp) { + route_map_result_t ret; + info.peer = irfd->peer; + info.attr = &hattr; + ret = route_map_apply( + rfgn->rfg + ->routemap_export_bgp, + &rn->p, RMAP_BGP, + &info); + if (ret == RMAP_DENYMATCH) { + bgp_attr_flush(&hattr); + continue; + } + } + + iattr = bgp_attr_intern(&hattr); + bgp_attr_flush(&hattr); + + bgp_update(irfd->peer, + &rn->p, /* prefix */ + 0, /* addpath_id */ + iattr, /* bgp_update copies + it */ + afi, SAFI_UNICAST, + ZEBRA_ROUTE_VNC_DIRECT, + BGP_ROUTE_REDISTRIBUTE, + NULL, /* RD not used for + unicast */ + NULL, /* tag not used for + unicast */ + 0, NULL); /* EVPN not used */ + + bgp_attr_unintern(&iattr); + } + } + + aspath_unintern(&attr.aspath); + } + } } -void -vnc_direct_bgp_del_nve (struct bgp *bgp, struct rfapi_descriptor *rfd) +void vnc_direct_bgp_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd) { - struct listnode *node, *nnode; - struct rfapi_rfg_name *rfgn; - struct rfapi_nve_group_cfg *rfg = rfd->rfg; - afi_t afi = family2afi (rfd->vn_addr.addr_family); - - if (!afi) - { - zlog_err ("%s: can't get afi of nve vn addr", __func__); - return; - } - - if (!bgp) - return; - if (!bgp->rfapi_cfg) - { - vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__); - return; - } - if (!VNC_EXPORT_BGP_GRP_ENABLED (bgp->rfapi_cfg)) - { - vnc_zlog_debug_verbose ("%s: export-to-bgp group mode not enabled, skipping", - __func__); - return; - } - - if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) - { - vnc_zlog_debug_verbose ("%s: bgp redistribution of VNC direct routes is off", - __func__); - return; - } - - /* - * Loop over the list of NVE-Groups configured for - * exporting to direct-bgp and see if this new NVE's - * group is among them. - */ - for (ALL_LIST_ELEMENTS (bgp->rfapi_cfg->rfg_export_direct_bgp_l, - node, nnode, rfgn)) - { - - /* - * Yes, this NVE's group is configured for export to direct-bgp - */ - if (rfg && rfgn->rfg == rfg) - { - - struct route_table *rt = NULL; - struct route_node *rn; - struct rfapi_import_table *import_table; - - import_table = rfg->rfapi_import_table; - - if (afi == AFI_IP - || afi == AFI_IP6) - { - rt = import_table->imported_vpn[afi]; - } - else - { - zlog_err ("%s: bad afi %d", __func__, afi); - return; - } - - /* - * Walk the NVE-Group's VNC Import table - */ - for (rn = route_top (rt); rn; rn = route_next (rn)) - { - - if (rn->info) - { - - struct prefix nhp; - struct rfapi_descriptor *irfd = rfd; - - if (rfapiRaddr2Qprefix (&irfd->vn_addr, &nhp)) - continue; - - bgp_withdraw (irfd->peer, &rn->p, /* prefix */ - 0, /* addpath_id */ - NULL, /* attr, ignored */ - afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ - NULL, NULL); /* tag not used for unicast */ - - } - } - } - } -} + struct listnode *node, *nnode; + struct rfapi_rfg_name *rfgn; + struct rfapi_nve_group_cfg *rfg = rfd->rfg; + afi_t afi = family2afi(rfd->vn_addr.addr_family); + + if (!afi) { + zlog_err("%s: can't get afi of nve vn addr", __func__); + return; + } + + if (!bgp) + return; + if (!bgp->rfapi_cfg) { + vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", + __func__); + return; + } + if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) { + vnc_zlog_debug_verbose( + "%s: export-to-bgp group mode not enabled, skipping", + __func__); + return; + } + + if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) { + vnc_zlog_debug_verbose( + "%s: bgp redistribution of VNC direct routes is off", + __func__); + return; + } + /* + * Loop over the list of NVE-Groups configured for + * exporting to direct-bgp and see if this new NVE's + * group is among them. + */ + for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node, + nnode, rfgn)) { + + /* + * Yes, this NVE's group is configured for export to direct-bgp + */ + if (rfg && rfgn->rfg == rfg) { + + struct route_table *rt = NULL; + struct route_node *rn; + struct rfapi_import_table *import_table; + + import_table = rfg->rfapi_import_table; + + if (afi == AFI_IP || afi == AFI_IP6) { + rt = import_table->imported_vpn[afi]; + } else { + zlog_err("%s: bad afi %d", __func__, afi); + return; + } + + /* + * Walk the NVE-Group's VNC Import table + */ + for (rn = route_top(rt); rn; rn = route_next(rn)) { + + if (rn->info) { + + struct prefix nhp; + struct rfapi_descriptor *irfd = rfd; + + if (rfapiRaddr2Qprefix(&irfd->vn_addr, + &nhp)) + continue; + + bgp_withdraw(irfd->peer, + &rn->p, /* prefix */ + 0, /* addpath_id */ + NULL, /* attr, ignored */ + afi, SAFI_UNICAST, + ZEBRA_ROUTE_VNC_DIRECT, + BGP_ROUTE_REDISTRIBUTE, + NULL, /* RD not used for + unicast */ + NULL, NULL); /* tag not + used for + unicast */ + } + } + } + } +} /* * Caller is responsible for ensuring that the specified nve-group * is actually part of the list of exported nve groups. */ -static void -vnc_direct_bgp_add_group_afi ( - struct bgp *bgp, - struct rfapi_nve_group_cfg *rfg, - afi_t afi) +static void vnc_direct_bgp_add_group_afi(struct bgp *bgp, + struct rfapi_nve_group_cfg *rfg, + afi_t afi) { - struct route_table *rt = NULL; - struct route_node *rn; - struct attr attr = { 0 }; - struct rfapi_import_table *import_table; - - vnc_zlog_debug_verbose ("%s: entry", __func__); - - import_table = rfg->rfapi_import_table; - if (!import_table) - { - vnc_zlog_debug_verbose ("%s: import table not defined, returning", __func__); - return; - } - - if (afi == AFI_IP - || afi == AFI_IP6) - { - rt = import_table->imported_vpn[afi]; - } - else - { - zlog_err ("%s: bad afi %d", __func__, afi); - return; - } - - if (!rfg->nves) - { - /* avoid segfault below if list doesn't exist */ - vnc_zlog_debug_verbose ("%s: no NVEs in this group", __func__); - return; - } - - bgp_attr_default_set (&attr, BGP_ORIGIN_INCOMPLETE); - /* TBD set some configured med, see add_vnc_route() */ - - /* - * Walk the NVE-Group's VNC Import table - */ - for (rn = route_top (rt); rn; rn = route_next (rn)) - { - - if (rn->info) - { - - struct listnode *ln; - - /* - * per-nve-group prefix list check - */ - if (rfg->plist_export_bgp[afi]) - { - if (prefix_list_apply (rfg->plist_export_bgp[afi], &rn->p) == - PREFIX_DENY) - - continue; - } - - /* - * For each NVE that is assigned to the export nve group, generate - * a route with that NVE as its next hop - */ - for (ln = listhead (rfg->nves); ln; ln = listnextnode (ln)) - { - - struct prefix nhp; - struct rfapi_descriptor *irfd; - struct bgp_info info; - struct attr hattr; - struct attr *iattr; - - irfd = listgetdata (ln); - - if (rfapiRaddr2Qprefix (&irfd->vn_addr, &nhp)) - continue; - - /* - * Construct new attribute set with NVE's VN addr as - * nexthop and without Tunnel Encap attr - */ - if (encap_attr_export (&hattr, &attr, &nhp, rn)) - continue; - - if (rfg->routemap_export_bgp) - { - route_map_result_t ret; - info.peer = irfd->peer; - info.attr = &hattr; - ret = route_map_apply (rfg->routemap_export_bgp, - &rn->p, RMAP_BGP, &info); - if (ret == RMAP_DENYMATCH) - { - bgp_attr_flush (&hattr); - continue; - } - - } - - iattr = bgp_attr_intern (&hattr); - bgp_attr_flush (&hattr); - - bgp_update (irfd->peer, &rn->p, /* prefix */ - 0, /* addpath_id */ - iattr, /* bgp_update copies it */ - afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ - NULL, /* tag not used for unicast */ - 0, NULL); /* EVPN not used */ - - bgp_attr_unintern (&iattr); - } - } - } - - aspath_unintern (&attr.aspath); + struct route_table *rt = NULL; + struct route_node *rn; + struct attr attr = {0}; + struct rfapi_import_table *import_table; + + vnc_zlog_debug_verbose("%s: entry", __func__); + + import_table = rfg->rfapi_import_table; + if (!import_table) { + vnc_zlog_debug_verbose( + "%s: import table not defined, returning", __func__); + return; + } + + if (afi == AFI_IP || afi == AFI_IP6) { + rt = import_table->imported_vpn[afi]; + } else { + zlog_err("%s: bad afi %d", __func__, afi); + return; + } + + if (!rfg->nves) { + /* avoid segfault below if list doesn't exist */ + vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__); + return; + } + + bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE); + /* TBD set some configured med, see add_vnc_route() */ + + /* + * Walk the NVE-Group's VNC Import table + */ + for (rn = route_top(rt); rn; rn = route_next(rn)) { + + if (rn->info) { + + struct listnode *ln; + + /* + * per-nve-group prefix list check + */ + if (rfg->plist_export_bgp[afi]) { + if (prefix_list_apply( + rfg->plist_export_bgp[afi], &rn->p) + == PREFIX_DENY) + + continue; + } + + /* + * For each NVE that is assigned to the export nve + * group, generate + * a route with that NVE as its next hop + */ + for (ln = listhead(rfg->nves); ln; + ln = listnextnode(ln)) { + + struct prefix nhp; + struct rfapi_descriptor *irfd; + struct bgp_info info; + struct attr hattr; + struct attr *iattr; + + irfd = listgetdata(ln); + + if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp)) + continue; + + /* + * Construct new attribute set with NVE's VN + * addr as + * nexthop and without Tunnel Encap attr + */ + if (encap_attr_export(&hattr, &attr, &nhp, rn)) + continue; + + if (rfg->routemap_export_bgp) { + route_map_result_t ret; + info.peer = irfd->peer; + info.attr = &hattr; + ret = route_map_apply( + rfg->routemap_export_bgp, + &rn->p, RMAP_BGP, &info); + if (ret == RMAP_DENYMATCH) { + bgp_attr_flush(&hattr); + continue; + } + } + + iattr = bgp_attr_intern(&hattr); + bgp_attr_flush(&hattr); + + bgp_update(irfd->peer, &rn->p, /* prefix */ + 0, /* addpath_id */ + iattr, /* bgp_update copies it */ + afi, SAFI_UNICAST, + ZEBRA_ROUTE_VNC_DIRECT, + BGP_ROUTE_REDISTRIBUTE, + NULL, /* RD not used for unicast */ + NULL, /* tag not used for unicast */ + 0, NULL); /* EVPN not used */ + + bgp_attr_unintern(&iattr); + } + } + } + + aspath_unintern(&attr.aspath); } @@ -1366,80 +1302,77 @@ vnc_direct_bgp_add_group_afi ( * Caller is responsible for ensuring that the specified nve-group * is actually part of the list of exported nve groups. */ -void -vnc_direct_bgp_add_group (struct bgp *bgp, struct rfapi_nve_group_cfg *rfg) +void vnc_direct_bgp_add_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg) { - vnc_direct_bgp_add_group_afi (bgp, rfg, AFI_IP); - vnc_direct_bgp_add_group_afi (bgp, rfg, AFI_IP6); + vnc_direct_bgp_add_group_afi(bgp, rfg, AFI_IP); + vnc_direct_bgp_add_group_afi(bgp, rfg, AFI_IP6); } - /* * Caller is responsible for ensuring that the specified nve-group * was actually part of the list of exported nve groups. */ -static void -vnc_direct_bgp_del_group_afi ( - struct bgp *bgp, - struct rfapi_nve_group_cfg *rfg, - afi_t afi) +static void vnc_direct_bgp_del_group_afi(struct bgp *bgp, + struct rfapi_nve_group_cfg *rfg, + afi_t afi) { - struct route_table *rt = NULL; - struct route_node *rn; - struct rfapi_import_table *import_table; - - vnc_zlog_debug_verbose ("%s: entry", __func__); - - import_table = rfg->rfapi_import_table; - if (!import_table) - { - vnc_zlog_debug_verbose ("%s: import table not defined, returning", __func__); - return; - } - - assert (afi == AFI_IP - || afi == AFI_IP6); - rt = import_table->imported_vpn[afi]; - - if (!rfg->nves) - { - /* avoid segfault below if list does not exist */ - vnc_zlog_debug_verbose ("%s: no NVEs in this group", __func__); - return; - } - - /* - * Walk the NVE-Group's VNC Import table - */ - for (rn = route_top (rt); rn; rn = route_next (rn)) - { - - if (rn->info) - { - - struct listnode *ln; - - /* - * For each NVE that is assigned to the export nve group, generate - * a route with that NVE as its next hop - */ - for (ln = listhead (rfg->nves); ln; ln = listnextnode (ln)) - { - - struct rfapi_descriptor *irfd; - - irfd = listgetdata (ln); - - bgp_withdraw (irfd->peer, &rn->p, /* prefix */ - 0, /* addpath_id */ - NULL, /* attr, ignored */ - afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ - NULL, NULL); /* tag not used for unicast */ - - } - } - } + struct route_table *rt = NULL; + struct route_node *rn; + struct rfapi_import_table *import_table; + + vnc_zlog_debug_verbose("%s: entry", __func__); + + import_table = rfg->rfapi_import_table; + if (!import_table) { + vnc_zlog_debug_verbose( + "%s: import table not defined, returning", __func__); + return; + } + + assert(afi == AFI_IP || afi == AFI_IP6); + rt = import_table->imported_vpn[afi]; + + if (!rfg->nves) { + /* avoid segfault below if list does not exist */ + vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__); + return; + } + + /* + * Walk the NVE-Group's VNC Import table + */ + for (rn = route_top(rt); rn; rn = route_next(rn)) { + + if (rn->info) { + + struct listnode *ln; + + /* + * For each NVE that is assigned to the export nve + * group, generate + * a route with that NVE as its next hop + */ + for (ln = listhead(rfg->nves); ln; + ln = listnextnode(ln)) { + + struct rfapi_descriptor *irfd; + + irfd = listgetdata(ln); + + bgp_withdraw( + irfd->peer, &rn->p, /* prefix */ + 0, /* addpath_id */ + NULL, /* attr, ignored */ + afi, SAFI_UNICAST, + ZEBRA_ROUTE_VNC_DIRECT, + BGP_ROUTE_REDISTRIBUTE, + NULL, /* RD not used for unicast */ + NULL, + NULL); /* tag not used for unicast */ + } + } + } } @@ -1447,189 +1380,173 @@ vnc_direct_bgp_del_group_afi ( * Caller is responsible for ensuring that the specified nve-group * was actually part of the list of exported nve groups. */ -void -vnc_direct_bgp_del_group (struct bgp *bgp, struct rfapi_nve_group_cfg *rfg) +void vnc_direct_bgp_del_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg) { - vnc_direct_bgp_del_group_afi (bgp, rfg, AFI_IP); - vnc_direct_bgp_del_group_afi (bgp, rfg, AFI_IP6); + vnc_direct_bgp_del_group_afi(bgp, rfg, AFI_IP); + vnc_direct_bgp_del_group_afi(bgp, rfg, AFI_IP6); } -void -vnc_direct_bgp_reexport_group_afi ( - struct bgp *bgp, - struct rfapi_nve_group_cfg *rfg, - afi_t afi) +void vnc_direct_bgp_reexport_group_afi(struct bgp *bgp, + struct rfapi_nve_group_cfg *rfg, + afi_t afi) { - struct listnode *node; - struct rfapi_rfg_name *rfgn; - - if (VNC_EXPORT_BGP_GRP_ENABLED (bgp->rfapi_cfg)) - { - /* - * look in the list of currently-exported groups - */ - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_direct_bgp_l, - node, rfgn)) - { - - if (rfgn->rfg == rfg) - { - /* - * If it matches, reexport it - */ - vnc_direct_bgp_del_group_afi (bgp, rfg, afi); - vnc_direct_bgp_add_group_afi (bgp, rfg, afi); - break; - } - } - } + struct listnode *node; + struct rfapi_rfg_name *rfgn; + + if (VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) { + /* + * look in the list of currently-exported groups + */ + for (ALL_LIST_ELEMENTS_RO( + bgp->rfapi_cfg->rfg_export_direct_bgp_l, node, + rfgn)) { + + if (rfgn->rfg == rfg) { + /* + * If it matches, reexport it + */ + vnc_direct_bgp_del_group_afi(bgp, rfg, afi); + vnc_direct_bgp_add_group_afi(bgp, rfg, afi); + break; + } + } + } } -static void -vnc_direct_bgp_unexport_table ( - afi_t afi, - struct route_table *rt, - struct list *nve_list) +static void vnc_direct_bgp_unexport_table(afi_t afi, struct route_table *rt, + struct list *nve_list) { - if (nve_list) - { - - struct route_node *rn; - - for (rn = route_top (rt); rn; rn = route_next (rn)) - { - - if (rn->info) - { - - struct listnode *hln; - struct rfapi_descriptor *irfd; - - for (ALL_LIST_ELEMENTS_RO (nve_list, hln, irfd)) - { - - bgp_withdraw (irfd->peer, &rn->p, /* prefix */ - 0, /* addpath_id */ - NULL, /* attr, ignored */ - afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ - NULL, NULL); /* tag not used for unicast, EVPN neither */ - - } - } - } - } + if (nve_list) { + + struct route_node *rn; + + for (rn = route_top(rt); rn; rn = route_next(rn)) { + + if (rn->info) { + + struct listnode *hln; + struct rfapi_descriptor *irfd; + + for (ALL_LIST_ELEMENTS_RO(nve_list, hln, + irfd)) { + + bgp_withdraw(irfd->peer, + &rn->p, /* prefix */ + 0, /* addpath_id */ + NULL, /* attr, ignored */ + afi, SAFI_UNICAST, + ZEBRA_ROUTE_VNC_DIRECT, + BGP_ROUTE_REDISTRIBUTE, + NULL, /* RD not used for + unicast */ + NULL, NULL); /* tag not + used for + unicast, + EVPN + neither */ + } + } + } + } } -static void -import_table_to_nve_list_direct_bgp ( - struct bgp *bgp, - struct rfapi_import_table *it, - struct list **nves, - uint8_t family) +static void import_table_to_nve_list_direct_bgp(struct bgp *bgp, + struct rfapi_import_table *it, + struct list **nves, + uint8_t family) { - struct listnode *node; - struct rfapi_rfg_name *rfgn; - - /* - * Loop over the list of NVE-Groups configured for - * exporting to direct-bgp. - * - * Build a list of NVEs that use this import table - */ - *nves = NULL; - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_direct_bgp_l, - node, rfgn)) - { - - /* - * If this NVE-Group's import table matches the current one - */ - if (rfgn->rfg && rfgn->rfg->nves && rfgn->rfg->rfapi_import_table == it) - { - - nve_group_to_nve_list (rfgn->rfg, nves, family); - } - } + struct listnode *node; + struct rfapi_rfg_name *rfgn; + + /* + * Loop over the list of NVE-Groups configured for + * exporting to direct-bgp. + * + * Build a list of NVEs that use this import table + */ + *nves = NULL; + for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node, + rfgn)) { + + /* + * If this NVE-Group's import table matches the current one + */ + if (rfgn->rfg && rfgn->rfg->nves + && rfgn->rfg->rfapi_import_table == it) { + + nve_group_to_nve_list(rfgn->rfg, nves, family); + } + } } -void -vnc_direct_bgp_vpn_enable (struct bgp *bgp, afi_t afi) +void vnc_direct_bgp_vpn_enable(struct bgp *bgp, afi_t afi) { - struct listnode *rfgn; - struct rfapi_nve_group_cfg *rfg; - - if (!bgp) - return; - - if (!VNC_EXPORT_BGP_GRP_ENABLED (bgp->rfapi_cfg)) - { - vnc_zlog_debug_verbose ("%s: export-to-bgp group mode not enabled, skipping", - __func__); - return; - } - - if (afi != AFI_IP - && afi != AFI_IP6) - { - vnc_zlog_debug_verbose ("%s: bad afi: %d", __func__, afi); - return; - } - - /* - * Policy is applied per-nve-group, so we need to iterate - * over the groups to add everything. - */ - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->nve_groups_sequential, - rfgn, rfg)) - { - - /* - * contains policy management - */ - vnc_direct_bgp_add_group_afi (bgp, rfg, afi); - } + struct listnode *rfgn; + struct rfapi_nve_group_cfg *rfg; + + if (!bgp) + return; + + if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) { + vnc_zlog_debug_verbose( + "%s: export-to-bgp group mode not enabled, skipping", + __func__); + return; + } + + if (afi != AFI_IP && afi != AFI_IP6) { + vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi); + return; + } + + /* + * Policy is applied per-nve-group, so we need to iterate + * over the groups to add everything. + */ + for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->nve_groups_sequential, rfgn, + rfg)) { + + /* + * contains policy management + */ + vnc_direct_bgp_add_group_afi(bgp, rfg, afi); + } } -void -vnc_direct_bgp_vpn_disable (struct bgp *bgp, afi_t afi) +void vnc_direct_bgp_vpn_disable(struct bgp *bgp, afi_t afi) { - struct rfapi_import_table *it; - uint8_t family = afi2family (afi); + struct rfapi_import_table *it; + uint8_t family = afi2family(afi); - vnc_zlog_debug_verbose ("%s: entry, afi=%d", __func__, afi); + vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi); - if (!bgp) - return; + if (!bgp) + return; - if (!bgp->rfapi) - { - vnc_zlog_debug_verbose ("%s: rfapi not initialized", __func__); - return; - } + if (!bgp->rfapi) { + vnc_zlog_debug_verbose("%s: rfapi not initialized", __func__); + return; + } - if (!family || (afi != AFI_IP - && afi != AFI_IP6)) - { - vnc_zlog_debug_verbose ("%s: bad afi: %d", __func__, afi); - return; - } + if (!family || (afi != AFI_IP && afi != AFI_IP6)) { + vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi); + return; + } - for (it = bgp->rfapi->imports; it; it = it->next) - { + for (it = bgp->rfapi->imports; it; it = it->next) { - struct list *nve_list = NULL; + struct list *nve_list = NULL; - import_table_to_nve_list_direct_bgp (bgp, it, &nve_list, family); + import_table_to_nve_list_direct_bgp(bgp, it, &nve_list, family); - if (nve_list) - { - vnc_direct_bgp_unexport_table (afi, it->imported_vpn[afi], - nve_list); - list_free (nve_list); - } - } + if (nve_list) { + vnc_direct_bgp_unexport_table( + afi, it->imported_vpn[afi], nve_list); + list_free(nve_list); + } + } } @@ -1649,137 +1566,121 @@ vnc_direct_bgp_vpn_disable (struct bgp *bgp, afi_t afi) * TBD do we need to check bi->type and bi->sub_type here, or does * caller do it? */ -void -vnc_direct_bgp_rh_add_route ( - struct bgp *bgp, - afi_t afi, - struct prefix *prefix, - struct peer *peer, - struct attr *attr) +void vnc_direct_bgp_rh_add_route(struct bgp *bgp, afi_t afi, + struct prefix *prefix, struct peer *peer, + struct attr *attr) { - struct vnc_export_info *eti; - struct attr hattr; - struct rfapi_cfg *hc; - struct attr *iattr; - - if (!afi) - { - zlog_err ("%s: can't get afi of route node", __func__); - return; - } - - /* check bgp redist flag for vnc direct ("vpn") routes */ - if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) - { - vnc_zlog_debug_verbose ("%s: bgp redistribution of VNC direct routes is off", - __func__); - return; - } - - if (!(hc = bgp->rfapi_cfg)) - { - vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__); - return; - } - - if (!VNC_EXPORT_BGP_RH_ENABLED (bgp->rfapi_cfg)) - { - vnc_zlog_debug_verbose ("%s: export-to-bgp RH mode not enabled, skipping", - __func__); - return; - } - - /* - * prefix list check - */ - if (hc->plist_export_bgp[afi]) - { - if (prefix_list_apply (hc->plist_export_bgp[afi], prefix) == - PREFIX_DENY) - return; - } - - /* - * Construct new attribute set with NVE's VN addr as - * nexthop and without Tunnel Encap attr - */ - if (encap_attr_export (&hattr, attr, NULL, NULL)) - return; - if (hc->routemap_export_bgp) - { - struct bgp_info info; - route_map_result_t ret; - - memset (&info, 0, sizeof (info)); - info.peer = peer; - info.attr = &hattr; - ret = - route_map_apply (hc->routemap_export_bgp, prefix, RMAP_BGP, &info); - if (ret == RMAP_DENYMATCH) - { - bgp_attr_flush (&hattr); - return; - } - } - - iattr = bgp_attr_intern (&hattr); - bgp_attr_flush (&hattr); - - /* - * record route information that we will need to expire - * this route - */ - eti = vnc_eti_get (bgp, EXPORT_TYPE_BGP, prefix, peer, - ZEBRA_ROUTE_VNC_DIRECT_RH, BGP_ROUTE_REDISTRIBUTE); - rfapiGetVncLifetime (attr, &eti->lifetime); - eti->lifetime = rfapiGetHolddownFromLifetime (eti->lifetime); - - if (eti->timer) - { - /* - * export expiration timer is already running on - * this route: cancel it - */ - thread_cancel (eti->timer); - eti->timer = NULL; - } - - bgp_update (peer, prefix, /* prefix */ - 0, /* addpath_id */ - iattr, /* bgp_update copies this attr */ - afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT_RH, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ - NULL, /* tag not used for unicast, EVPN neither */ - 0, NULL); /* EVPN not used */ - bgp_attr_unintern (&iattr); + struct vnc_export_info *eti; + struct attr hattr; + struct rfapi_cfg *hc; + struct attr *iattr; + + if (!afi) { + zlog_err("%s: can't get afi of route node", __func__); + return; + } + + /* check bgp redist flag for vnc direct ("vpn") routes */ + if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) { + vnc_zlog_debug_verbose( + "%s: bgp redistribution of VNC direct routes is off", + __func__); + return; + } + + if (!(hc = bgp->rfapi_cfg)) { + vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", + __func__); + return; + } + + if (!VNC_EXPORT_BGP_RH_ENABLED(bgp->rfapi_cfg)) { + vnc_zlog_debug_verbose( + "%s: export-to-bgp RH mode not enabled, skipping", + __func__); + return; + } + + /* + * prefix list check + */ + if (hc->plist_export_bgp[afi]) { + if (prefix_list_apply(hc->plist_export_bgp[afi], prefix) + == PREFIX_DENY) + return; + } + + /* + * Construct new attribute set with NVE's VN addr as + * nexthop and without Tunnel Encap attr + */ + if (encap_attr_export(&hattr, attr, NULL, NULL)) + return; + if (hc->routemap_export_bgp) { + struct bgp_info info; + route_map_result_t ret; + + memset(&info, 0, sizeof(info)); + info.peer = peer; + info.attr = &hattr; + ret = route_map_apply(hc->routemap_export_bgp, prefix, RMAP_BGP, + &info); + if (ret == RMAP_DENYMATCH) { + bgp_attr_flush(&hattr); + return; + } + } + + iattr = bgp_attr_intern(&hattr); + bgp_attr_flush(&hattr); + + /* + * record route information that we will need to expire + * this route + */ + eti = vnc_eti_get(bgp, EXPORT_TYPE_BGP, prefix, peer, + ZEBRA_ROUTE_VNC_DIRECT_RH, BGP_ROUTE_REDISTRIBUTE); + rfapiGetVncLifetime(attr, &eti->lifetime); + eti->lifetime = rfapiGetHolddownFromLifetime(eti->lifetime); + + if (eti->timer) { + /* + * export expiration timer is already running on + * this route: cancel it + */ + thread_cancel(eti->timer); + eti->timer = NULL; + } + bgp_update(peer, prefix, /* prefix */ + 0, /* addpath_id */ + iattr, /* bgp_update copies this attr */ + afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT_RH, + BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ + NULL, /* tag not used for unicast, EVPN neither */ + 0, NULL); /* EVPN not used */ + bgp_attr_unintern(&iattr); } -static int -vncExportWithdrawTimer (struct thread *t) +static int vncExportWithdrawTimer(struct thread *t) { - struct vnc_export_info *eti = t->arg; - - /* - * withdraw the route - */ - bgp_withdraw ( - eti->peer, - &eti->node->p, - 0, /* addpath_id */ - NULL, /* attr, ignored */ - family2afi (eti->node->p.family), - SAFI_UNICAST, - eti->type, - eti->subtype, - NULL, /* RD not used for unicast */ - NULL, NULL); /* tag not used for unicast, EVPN neither */ - - /* - * Free the eti - */ - vnc_eti_delete (eti); - - return 0; + struct vnc_export_info *eti = t->arg; + + /* + * withdraw the route + */ + bgp_withdraw(eti->peer, &eti->node->p, 0, /* addpath_id */ + NULL, /* attr, ignored */ + family2afi(eti->node->p.family), SAFI_UNICAST, eti->type, + eti->subtype, NULL, /* RD not used for unicast */ + NULL, NULL); /* tag not used for unicast, EVPN neither */ + + /* + * Free the eti + */ + vnc_eti_delete(eti); + + return 0; } /* @@ -1787,287 +1688,295 @@ vncExportWithdrawTimer (struct thread *t) * TBD do we need to check bi->type and bi->sub_type here, or does * caller do it? */ -void -vnc_direct_bgp_rh_del_route ( - struct bgp *bgp, - afi_t afi, - struct prefix *prefix, - struct peer *peer) +void vnc_direct_bgp_rh_del_route(struct bgp *bgp, afi_t afi, + struct prefix *prefix, struct peer *peer) { - struct vnc_export_info *eti; - - if (!afi) - { - zlog_err ("%s: can't get afi route node", __func__); - return; - } - - /* check bgp redist flag for vnc direct ("vpn") routes */ - if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) - { - vnc_zlog_debug_verbose ("%s: bgp redistribution of VNC direct routes is off", - __func__); - return; - } - - if (!bgp->rfapi_cfg) - { - vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__); - return; - } - if (!VNC_EXPORT_BGP_RH_ENABLED (bgp->rfapi_cfg)) - { - vnc_zlog_debug_verbose ("%s: export-to-bgp group mode not enabled, skipping", - __func__); - return; - } - - eti = vnc_eti_get (bgp, EXPORT_TYPE_BGP, prefix, peer, - ZEBRA_ROUTE_VNC_DIRECT_RH, BGP_ROUTE_REDISTRIBUTE); - - if (!eti->timer && eti->lifetime <= INT32_MAX) - { - eti->timer = NULL; - thread_add_timer(bm->master, vncExportWithdrawTimer, eti, eti->lifetime, - &eti->timer); - vnc_zlog_debug_verbose ("%s: set expiration timer for %u seconds", - __func__, eti->lifetime); - } + struct vnc_export_info *eti; + + if (!afi) { + zlog_err("%s: can't get afi route node", __func__); + return; + } + + /* check bgp redist flag for vnc direct ("vpn") routes */ + if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) { + vnc_zlog_debug_verbose( + "%s: bgp redistribution of VNC direct routes is off", + __func__); + return; + } + + if (!bgp->rfapi_cfg) { + vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", + __func__); + return; + } + if (!VNC_EXPORT_BGP_RH_ENABLED(bgp->rfapi_cfg)) { + vnc_zlog_debug_verbose( + "%s: export-to-bgp group mode not enabled, skipping", + __func__); + return; + } + + eti = vnc_eti_get(bgp, EXPORT_TYPE_BGP, prefix, peer, + ZEBRA_ROUTE_VNC_DIRECT_RH, BGP_ROUTE_REDISTRIBUTE); + + if (!eti->timer && eti->lifetime <= INT32_MAX) { + eti->timer = NULL; + thread_add_timer(bm->master, vncExportWithdrawTimer, eti, + eti->lifetime, &eti->timer); + vnc_zlog_debug_verbose( + "%s: set expiration timer for %u seconds", __func__, + eti->lifetime); + } } -void -vnc_direct_bgp_rh_vpn_enable (struct bgp *bgp, afi_t afi) +void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi) { - struct prefix_rd prd; - struct bgp_node *prn; - struct rfapi_cfg *hc; - - vnc_zlog_debug_verbose ("%s: entry, afi=%d", __func__, afi); - - if (!bgp) - return; - - if (!(hc = bgp->rfapi_cfg)) - return; - - if (!VNC_EXPORT_BGP_RH_ENABLED (bgp->rfapi_cfg)) - { - vnc_zlog_debug_verbose ("%s: export of RH routes not enabled, skipping", __func__); - return; - } - - if (afi != AFI_IP - && afi != AFI_IP6) - { - vnc_zlog_debug_verbose ("%s: bad afi: %d", __func__, afi); - return; - } - - /* - * Go through the entire BGP VPN table and export to BGP unicast. - */ - - vnc_zlog_debug_verbose ("%s: starting RD loop", __func__); - - /* Loop over all the RDs */ - for (prn = bgp_table_top (bgp->rib[afi][SAFI_MPLS_VPN]); prn; - prn = bgp_route_next (prn)) - { - - struct bgp_table *table; - struct bgp_node *rn; - struct bgp_info *ri; - - memset (&prd, 0, sizeof (prd)); - prd.family = AF_UNSPEC; - prd.prefixlen = 64; - memcpy (prd.val, prn->p.u.val, 8); - - /* This is the per-RD table of prefixes */ - table = prn->info; - - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - { - - /* - * skip prefix list check if no routes here - */ - if (!rn->info) - continue; - - { - char prefixstr[BUFSIZ]; - - prefixstr[0] = 0; - inet_ntop (rn->p.family, &rn->p.u.prefix, prefixstr, BUFSIZ); - vnc_zlog_debug_verbose ("%s: checking prefix %s/%d", __func__, prefixstr, - rn->p.prefixlen); - } - - /* - * prefix list check - */ - if (hc->plist_export_bgp[afi]) - { - if (prefix_list_apply (hc->plist_export_bgp[afi], &rn->p) == - PREFIX_DENY) - { - - vnc_zlog_debug_verbose ("%s: prefix list says DENY", __func__); - continue; - } - } - - for (ri = rn->info; ri; ri = ri->next) - { - - vnc_zlog_debug_verbose ("%s: ri->sub_type: %d", __func__, ri->sub_type); - - if (ri->sub_type == BGP_ROUTE_NORMAL || - ri->sub_type == BGP_ROUTE_RFP) - { - - struct vnc_export_info *eti; - struct attr hattr; - struct attr *iattr; - - /* - * Construct new attribute set with NVE's VN addr as - * nexthop and without Tunnel Encap attr - */ - if (encap_attr_export (&hattr, ri->attr, NULL, NULL)) - { - vnc_zlog_debug_verbose ("%s: encap_attr_export failed", __func__); - continue; - } - - if (hc->routemap_export_bgp) - { - struct bgp_info info; - route_map_result_t ret; - - memset (&info, 0, sizeof (info)); - info.peer = ri->peer; - info.attr = &hattr; - ret = route_map_apply (hc->routemap_export_bgp, - &rn->p, RMAP_BGP, &info); - if (ret == RMAP_DENYMATCH) - { - bgp_attr_flush (&hattr); - vnc_zlog_debug_verbose ("%s: route map says DENY", __func__); - continue; - } - } - - iattr = bgp_attr_intern (&hattr); - bgp_attr_flush (&hattr); - - /* - * record route information that we will need to expire - * this route - */ - eti = vnc_eti_get (bgp, EXPORT_TYPE_BGP, &rn->p, ri->peer, - ZEBRA_ROUTE_VNC_DIRECT_RH, - BGP_ROUTE_REDISTRIBUTE); - rfapiGetVncLifetime (ri->attr, &eti->lifetime); - - if (eti->timer) - { - /* - * export expiration timer is already running on - * this route: cancel it - */ - thread_cancel (eti->timer); - eti->timer = NULL; - } - - vnc_zlog_debug_verbose ("%s: calling bgp_update", __func__); - - bgp_update (ri->peer, &rn->p, /* prefix */ - 0, /* addpath_id */ - iattr, /* bgp_update copies it */ - AFI_IP, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT_RH, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ - NULL, /* tag not used for unicast, EVPN neither */ - 0, NULL); /* EVPN not used */ - bgp_attr_unintern (&iattr); - } - } - } - } + struct prefix_rd prd; + struct bgp_node *prn; + struct rfapi_cfg *hc; + + vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi); + + if (!bgp) + return; + + if (!(hc = bgp->rfapi_cfg)) + return; + + if (!VNC_EXPORT_BGP_RH_ENABLED(bgp->rfapi_cfg)) { + vnc_zlog_debug_verbose( + "%s: export of RH routes not enabled, skipping", + __func__); + return; + } + + if (afi != AFI_IP && afi != AFI_IP6) { + vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi); + return; + } + + /* + * Go through the entire BGP VPN table and export to BGP unicast. + */ + + vnc_zlog_debug_verbose("%s: starting RD loop", __func__); + + /* Loop over all the RDs */ + for (prn = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); prn; + prn = bgp_route_next(prn)) { + + struct bgp_table *table; + struct bgp_node *rn; + struct bgp_info *ri; + + memset(&prd, 0, sizeof(prd)); + prd.family = AF_UNSPEC; + prd.prefixlen = 64; + memcpy(prd.val, prn->p.u.val, 8); + + /* This is the per-RD table of prefixes */ + table = prn->info; + + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { + + /* + * skip prefix list check if no routes here + */ + if (!rn->info) + continue; + + { + char prefixstr[BUFSIZ]; + + prefixstr[0] = 0; + inet_ntop(rn->p.family, &rn->p.u.prefix, + prefixstr, BUFSIZ); + vnc_zlog_debug_verbose( + "%s: checking prefix %s/%d", __func__, + prefixstr, rn->p.prefixlen); + } + + /* + * prefix list check + */ + if (hc->plist_export_bgp[afi]) { + if (prefix_list_apply(hc->plist_export_bgp[afi], + &rn->p) + == PREFIX_DENY) { + + vnc_zlog_debug_verbose( + "%s: prefix list says DENY", + __func__); + continue; + } + } + + for (ri = rn->info; ri; ri = ri->next) { + + vnc_zlog_debug_verbose("%s: ri->sub_type: %d", + __func__, ri->sub_type); + + if (ri->sub_type == BGP_ROUTE_NORMAL + || ri->sub_type == BGP_ROUTE_RFP) { + + struct vnc_export_info *eti; + struct attr hattr; + struct attr *iattr; + + /* + * Construct new attribute set with + * NVE's VN addr as + * nexthop and without Tunnel Encap attr + */ + if (encap_attr_export(&hattr, ri->attr, + NULL, NULL)) { + vnc_zlog_debug_verbose( + "%s: encap_attr_export failed", + __func__); + continue; + } + + if (hc->routemap_export_bgp) { + struct bgp_info info; + route_map_result_t ret; + + memset(&info, 0, sizeof(info)); + info.peer = ri->peer; + info.attr = &hattr; + ret = route_map_apply( + hc->routemap_export_bgp, + &rn->p, RMAP_BGP, + &info); + if (ret == RMAP_DENYMATCH) { + bgp_attr_flush(&hattr); + vnc_zlog_debug_verbose( + "%s: route map says DENY", + __func__); + continue; + } + } + + iattr = bgp_attr_intern(&hattr); + bgp_attr_flush(&hattr); + + /* + * record route information that we will + * need to expire + * this route + */ + eti = vnc_eti_get( + bgp, EXPORT_TYPE_BGP, &rn->p, + ri->peer, + ZEBRA_ROUTE_VNC_DIRECT_RH, + BGP_ROUTE_REDISTRIBUTE); + rfapiGetVncLifetime(ri->attr, + &eti->lifetime); + + if (eti->timer) { + /* + * export expiration timer is + * already running on + * this route: cancel it + */ + thread_cancel(eti->timer); + eti->timer = NULL; + } + + vnc_zlog_debug_verbose( + "%s: calling bgp_update", + __func__); + + bgp_update(ri->peer, + &rn->p, /* prefix */ + 0, /* addpath_id */ + iattr, /* bgp_update copies + it */ + AFI_IP, SAFI_UNICAST, + ZEBRA_ROUTE_VNC_DIRECT_RH, + BGP_ROUTE_REDISTRIBUTE, + NULL, /* RD not used for + unicast */ + NULL, /* tag not used for + unicast, EVPN + neither */ + 0, NULL); /* EVPN not used */ + bgp_attr_unintern(&iattr); + } + } + } + } } -void -vnc_direct_bgp_rh_vpn_disable (struct bgp *bgp, afi_t afi) +void vnc_direct_bgp_rh_vpn_disable(struct bgp *bgp, afi_t afi) { - struct bgp_node *rn; - - vnc_zlog_debug_verbose ("%s: entry, afi=%d", __func__, afi); - - if (!bgp) - return; - - if (afi != AFI_IP - && afi != AFI_IP6) - { - vnc_zlog_debug_verbose ("%s: bad afi: %d", __func__, afi); - return; - } - - /* - * Go through the entire BGP unicast table and remove routes that - * originated from us - */ - for (rn = bgp_table_top (bgp->rib[afi][SAFI_UNICAST]); rn; - rn = bgp_route_next (rn)) - { - - struct bgp_info *ri; - struct bgp_info *next; - - for (ri = rn->info, next = NULL; ri; ri = next) - { - - next = ri->next; - - if (ri->type == ZEBRA_ROUTE_VNC_DIRECT_RH && - ri->sub_type == BGP_ROUTE_REDISTRIBUTE) - { - - struct vnc_export_info *eti; - - /* - * Delete routes immediately (no timer) - */ - eti = - vnc_eti_checktimer (bgp, EXPORT_TYPE_BGP, &rn->p, ri->peer, - ZEBRA_ROUTE_VNC_DIRECT_RH, - BGP_ROUTE_REDISTRIBUTE); - if (eti) - { - if (eti->timer) - thread_cancel (eti->timer); - vnc_eti_delete (eti); - } - - bgp_withdraw (ri->peer, &rn->p, /* prefix */ - 0, /* addpath_id */ - NULL, /* ignored */ - AFI_IP, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT_RH, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ - NULL, NULL); /* tag not used for unicast, EVPN neither */ - } - } - } + struct bgp_node *rn; + + vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi); + + if (!bgp) + return; + + if (afi != AFI_IP && afi != AFI_IP6) { + vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi); + return; + } + + /* + * Go through the entire BGP unicast table and remove routes that + * originated from us + */ + for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn; + rn = bgp_route_next(rn)) { + + struct bgp_info *ri; + struct bgp_info *next; + + for (ri = rn->info, next = NULL; ri; ri = next) { + + next = ri->next; + + if (ri->type == ZEBRA_ROUTE_VNC_DIRECT_RH + && ri->sub_type == BGP_ROUTE_REDISTRIBUTE) { + + struct vnc_export_info *eti; + + /* + * Delete routes immediately (no timer) + */ + eti = vnc_eti_checktimer( + bgp, EXPORT_TYPE_BGP, &rn->p, ri->peer, + ZEBRA_ROUTE_VNC_DIRECT_RH, + BGP_ROUTE_REDISTRIBUTE); + if (eti) { + if (eti->timer) + thread_cancel(eti->timer); + vnc_eti_delete(eti); + } + + bgp_withdraw(ri->peer, &rn->p, /* prefix */ + 0, /* addpath_id */ + NULL, /* ignored */ + AFI_IP, SAFI_UNICAST, + ZEBRA_ROUTE_VNC_DIRECT_RH, + BGP_ROUTE_REDISTRIBUTE, + NULL, /* RD not used for unicast */ + NULL, NULL); /* tag not used for + unicast, EVPN + neither */ + } + } + } } -void -vnc_direct_bgp_rh_reexport (struct bgp *bgp, afi_t afi) +void vnc_direct_bgp_rh_reexport(struct bgp *bgp, afi_t afi) { - if (VNC_EXPORT_BGP_RH_ENABLED (bgp->rfapi_cfg)) - { - vnc_direct_bgp_rh_vpn_disable (bgp, afi); - vnc_direct_bgp_rh_vpn_enable (bgp, afi); - } + if (VNC_EXPORT_BGP_RH_ENABLED(bgp->rfapi_cfg)) { + vnc_direct_bgp_rh_vpn_disable(bgp, afi); + vnc_direct_bgp_rh_vpn_enable(bgp, afi); + } } /*********************************************************************** @@ -2079,67 +1988,60 @@ vnc_direct_bgp_rh_reexport (struct bgp *bgp, afi_t afi) * is OK to call this function from, e.g., bgp_redistribute_set() * without caring if export is enabled or not */ -void -vnc_export_bgp_enable (struct bgp *bgp, afi_t afi) +void vnc_export_bgp_enable(struct bgp *bgp, afi_t afi) { - switch (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) - { - case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE: - break; - - case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP: - vnc_direct_bgp_vpn_enable (bgp, afi); - break; - - case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH: - vnc_direct_bgp_rh_vpn_enable (bgp, afi); - break; - - case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE: - vnc_direct_bgp_vpn_enable_ce (bgp, afi); - break; - } + switch (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) { + case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE: + break; + + case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP: + vnc_direct_bgp_vpn_enable(bgp, afi); + break; + + case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH: + vnc_direct_bgp_rh_vpn_enable(bgp, afi); + break; + + case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE: + vnc_direct_bgp_vpn_enable_ce(bgp, afi); + break; + } } -void -vnc_export_bgp_disable (struct bgp *bgp, afi_t afi) +void vnc_export_bgp_disable(struct bgp *bgp, afi_t afi) { - switch (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) - { - case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE: - break; - - case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP: - vnc_direct_bgp_vpn_disable (bgp, afi); - break; - - case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH: - vnc_direct_bgp_rh_vpn_disable (bgp, afi); - break; - - case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE: - vnc_direct_bgp_vpn_disable_ce (bgp, afi); - break; - } + switch (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) { + case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE: + break; + + case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP: + vnc_direct_bgp_vpn_disable(bgp, afi); + break; + + case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH: + vnc_direct_bgp_rh_vpn_disable(bgp, afi); + break; + + case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE: + vnc_direct_bgp_vpn_disable_ce(bgp, afi); + break; + } } -void -vnc_export_bgp_prechange (struct bgp *bgp) +void vnc_export_bgp_prechange(struct bgp *bgp) { - vnc_export_bgp_disable (bgp, AFI_IP); - vnc_export_bgp_disable (bgp, AFI_IP6); + vnc_export_bgp_disable(bgp, AFI_IP); + vnc_export_bgp_disable(bgp, AFI_IP6); } -void -vnc_export_bgp_postchange (struct bgp *bgp) +void vnc_export_bgp_postchange(struct bgp *bgp) { - vnc_export_bgp_enable (bgp, AFI_IP); - vnc_export_bgp_enable (bgp, AFI_IP6); + vnc_export_bgp_enable(bgp, AFI_IP); + vnc_export_bgp_enable(bgp, AFI_IP6); } -void -vnc_direct_bgp_reexport (struct bgp *bgp, afi_t afi) +void vnc_direct_bgp_reexport(struct bgp *bgp, afi_t afi) { - vnc_export_bgp_disable (bgp, afi); - vnc_export_bgp_enable (bgp, afi); + vnc_export_bgp_disable(bgp, afi); + vnc_export_bgp_enable(bgp, afi); } diff --git a/bgpd/rfapi/vnc_export_bgp.h b/bgpd/rfapi/vnc_export_bgp.h index 7dbbb40e0..a6f8c82c0 100644 --- a/bgpd/rfapi/vnc_export_bgp.h +++ b/bgpd/rfapi/vnc_export_bgp.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -28,14 +28,14 @@ #include "bgpd/bgp_route.h" -extern void vnc_direct_bgp_rh_reexport (struct bgp *bgp, afi_t afi); +extern void vnc_direct_bgp_rh_reexport(struct bgp *bgp, afi_t afi); -extern void vnc_export_bgp_prechange (struct bgp *bgp); +extern void vnc_export_bgp_prechange(struct bgp *bgp); -extern void vnc_export_bgp_postchange (struct bgp *bgp); +extern void vnc_export_bgp_postchange(struct bgp *bgp); -extern void vnc_export_bgp_enable (struct bgp *bgp, afi_t afi); +extern void vnc_export_bgp_enable(struct bgp *bgp, afi_t afi); -extern void vnc_export_bgp_disable (struct bgp *bgp, afi_t afi); +extern void vnc_export_bgp_disable(struct bgp *bgp, afi_t afi); #endif /* _QUAGGA_RFAPI_VNC_EXPORT_BGP_H_ */ diff --git a/bgpd/rfapi/vnc_export_bgp_p.h b/bgpd/rfapi/vnc_export_bgp_p.h index 31830a3c1..c164a3543 100644 --- a/bgpd/rfapi/vnc_export_bgp_p.h +++ b/bgpd/rfapi/vnc_export_bgp_p.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -29,66 +29,46 @@ #include "rfapi_private.h" -extern void -vnc_direct_bgp_add_route_ce ( - struct bgp *bgp, - struct route_node *rn, - struct bgp_info *bi); - -extern void -vnc_direct_bgp_del_route_ce ( - struct bgp *bgp, - struct route_node *rn, - struct bgp_info *bi); - -extern void -vnc_direct_bgp_add_prefix ( - struct bgp *bgp, - struct rfapi_import_table *import_table, - struct route_node *rn); - -extern void -vnc_direct_bgp_del_prefix ( - struct bgp *bgp, - struct rfapi_import_table *import_table, - struct route_node *rn); - -extern void -vnc_direct_bgp_add_nve (struct bgp *bgp, struct rfapi_descriptor *rfd); - -extern void -vnc_direct_bgp_del_nve (struct bgp *bgp, struct rfapi_descriptor *rfd); - -extern void -vnc_direct_bgp_add_group (struct bgp *bgp, struct rfapi_nve_group_cfg *rfg); - -extern void -vnc_direct_bgp_del_group (struct bgp *bgp, struct rfapi_nve_group_cfg *rfg); - -extern void -vnc_direct_bgp_reexport_group_afi ( - struct bgp *bgp, - struct rfapi_nve_group_cfg *rfg, - afi_t afi); - - -extern void -vnc_direct_bgp_rh_add_route ( - struct bgp *bgp, - afi_t afi, - struct prefix *prefix, - struct peer *peer, - struct attr *attr); - - -extern void -vnc_direct_bgp_rh_del_route ( - struct bgp *bgp, - afi_t afi, - struct prefix *prefix, - struct peer *peer); - -extern void -vnc_direct_bgp_reexport (struct bgp *bgp, afi_t afi); +extern void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct route_node *rn, + struct bgp_info *bi); + +extern void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct route_node *rn, + struct bgp_info *bi); + +extern void vnc_direct_bgp_add_prefix(struct bgp *bgp, + struct rfapi_import_table *import_table, + struct route_node *rn); + +extern void vnc_direct_bgp_del_prefix(struct bgp *bgp, + struct rfapi_import_table *import_table, + struct route_node *rn); + +extern void vnc_direct_bgp_add_nve(struct bgp *bgp, + struct rfapi_descriptor *rfd); + +extern void vnc_direct_bgp_del_nve(struct bgp *bgp, + struct rfapi_descriptor *rfd); + +extern void vnc_direct_bgp_add_group(struct bgp *bgp, + struct rfapi_nve_group_cfg *rfg); + +extern void vnc_direct_bgp_del_group(struct bgp *bgp, + struct rfapi_nve_group_cfg *rfg); + +extern void vnc_direct_bgp_reexport_group_afi(struct bgp *bgp, + struct rfapi_nve_group_cfg *rfg, + afi_t afi); + + +extern void vnc_direct_bgp_rh_add_route(struct bgp *bgp, afi_t afi, + struct prefix *prefix, + struct peer *peer, struct attr *attr); + + +extern void vnc_direct_bgp_rh_del_route(struct bgp *bgp, afi_t afi, + struct prefix *prefix, + struct peer *peer); + +extern void vnc_direct_bgp_reexport(struct bgp *bgp, afi_t afi); #endif /* _QUAGGA_RFAPI_VNC_EXPORT_BGP_P_H_ */ diff --git a/bgpd/rfapi/vnc_export_table.c b/bgpd/rfapi/vnc_export_table.c index 5c7a64d3b..bbdb59c12 100644 --- a/bgpd/rfapi/vnc_export_table.c +++ b/bgpd/rfapi/vnc_export_table.c @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -33,182 +33,160 @@ #include "bgpd/rfapi/rfapi_import.h" #include "bgpd/rfapi/vnc_debug.h" -struct route_node * -vnc_etn_get (struct bgp *bgp, vnc_export_type_t type, struct prefix *p) +struct route_node *vnc_etn_get(struct bgp *bgp, vnc_export_type_t type, + struct prefix *p) { - struct route_table *t = NULL; - struct route_node *rn = NULL; - afi_t afi; - - if (!bgp || !bgp->rfapi) - return NULL; - - afi = family2afi (p->family); - assert (afi == AFI_IP || afi == AFI_IP6); - - switch (type) - { - case EXPORT_TYPE_BGP: - if (!bgp->rfapi->rt_export_bgp[afi]) - bgp->rfapi->rt_export_bgp[afi] = route_table_init (); - t = bgp->rfapi->rt_export_bgp[afi]; - break; - - case EXPORT_TYPE_ZEBRA: - if (!bgp->rfapi->rt_export_zebra[afi]) - bgp->rfapi->rt_export_zebra[afi] = route_table_init (); - t = bgp->rfapi->rt_export_zebra[afi]; - break; - } - - if (t) - rn = route_node_get (t, p); - return rn; + struct route_table *t = NULL; + struct route_node *rn = NULL; + afi_t afi; + + if (!bgp || !bgp->rfapi) + return NULL; + + afi = family2afi(p->family); + assert(afi == AFI_IP || afi == AFI_IP6); + + switch (type) { + case EXPORT_TYPE_BGP: + if (!bgp->rfapi->rt_export_bgp[afi]) + bgp->rfapi->rt_export_bgp[afi] = route_table_init(); + t = bgp->rfapi->rt_export_bgp[afi]; + break; + + case EXPORT_TYPE_ZEBRA: + if (!bgp->rfapi->rt_export_zebra[afi]) + bgp->rfapi->rt_export_zebra[afi] = route_table_init(); + t = bgp->rfapi->rt_export_zebra[afi]; + break; + } + + if (t) + rn = route_node_get(t, p); + return rn; } -struct route_node * -vnc_etn_lookup (struct bgp *bgp, vnc_export_type_t type, struct prefix *p) +struct route_node *vnc_etn_lookup(struct bgp *bgp, vnc_export_type_t type, + struct prefix *p) { - struct route_table *t = NULL; - struct route_node *rn = NULL; - afi_t afi; - - if (!bgp || !bgp->rfapi) - return NULL; - - afi = family2afi (p->family); - assert (afi == AFI_IP || afi == AFI_IP6); - - switch (type) - { - case EXPORT_TYPE_BGP: - if (!bgp->rfapi->rt_export_bgp[afi]) - bgp->rfapi->rt_export_bgp[afi] = route_table_init (); - t = bgp->rfapi->rt_export_bgp[afi]; - break; - - case EXPORT_TYPE_ZEBRA: - if (!bgp->rfapi->rt_export_zebra[afi]) - bgp->rfapi->rt_export_zebra[afi] = route_table_init (); - t = bgp->rfapi->rt_export_zebra[afi]; - break; - } - - if (t) - rn = route_node_lookup (t, p); - return rn; + struct route_table *t = NULL; + struct route_node *rn = NULL; + afi_t afi; + + if (!bgp || !bgp->rfapi) + return NULL; + + afi = family2afi(p->family); + assert(afi == AFI_IP || afi == AFI_IP6); + + switch (type) { + case EXPORT_TYPE_BGP: + if (!bgp->rfapi->rt_export_bgp[afi]) + bgp->rfapi->rt_export_bgp[afi] = route_table_init(); + t = bgp->rfapi->rt_export_bgp[afi]; + break; + + case EXPORT_TYPE_ZEBRA: + if (!bgp->rfapi->rt_export_zebra[afi]) + bgp->rfapi->rt_export_zebra[afi] = route_table_init(); + t = bgp->rfapi->rt_export_zebra[afi]; + break; + } + + if (t) + rn = route_node_lookup(t, p); + return rn; } -struct vnc_export_info * -vnc_eti_get ( - struct bgp *bgp, - vnc_export_type_t etype, - struct prefix *p, - struct peer *peer, - uint8_t type, - uint8_t subtype) +struct vnc_export_info *vnc_eti_get(struct bgp *bgp, vnc_export_type_t etype, + struct prefix *p, struct peer *peer, + uint8_t type, uint8_t subtype) { - struct route_node *etn; - struct vnc_export_info *eti; - - etn = vnc_etn_get (bgp, etype, p); - assert (etn); - - for (eti = etn->info; eti; eti = eti->next) - { - if (peer == eti->peer && type == eti->type && subtype == eti->subtype) - { - - break; - } - } - - if (eti) - { - route_unlock_node (etn); - } - else - { - eti = XCALLOC (MTYPE_RFAPI_ETI, sizeof (struct vnc_export_info)); - assert (eti); - eti->node = etn; - eti->peer = peer; - peer_lock (peer); - eti->type = type; - eti->subtype = subtype; - eti->next = etn->info; - etn->info = eti; - } - - return eti; + struct route_node *etn; + struct vnc_export_info *eti; + + etn = vnc_etn_get(bgp, etype, p); + assert(etn); + + for (eti = etn->info; eti; eti = eti->next) { + if (peer == eti->peer && type == eti->type + && subtype == eti->subtype) { + + break; + } + } + + if (eti) { + route_unlock_node(etn); + } else { + eti = XCALLOC(MTYPE_RFAPI_ETI, sizeof(struct vnc_export_info)); + assert(eti); + eti->node = etn; + eti->peer = peer; + peer_lock(peer); + eti->type = type; + eti->subtype = subtype; + eti->next = etn->info; + etn->info = eti; + } + + return eti; } -void -vnc_eti_delete (struct vnc_export_info *goner) +void vnc_eti_delete(struct vnc_export_info *goner) { - struct route_node *etn; - struct vnc_export_info *eti; - struct vnc_export_info *eti_prev = NULL; - - etn = goner->node; - - for (eti = etn->info; eti; eti_prev = eti, eti = eti->next) - { - if (eti == goner) - break; - } - - if (!eti) - { - vnc_zlog_debug_verbose ("%s: COULDN'T FIND ETI", __func__); - return; - } - - if (eti_prev) - { - eti_prev->next = goner->next; - } - else - { - etn->info = goner->next; - } - - peer_unlock (eti->peer); - goner->node = NULL; - XFREE (MTYPE_RFAPI_ETI, goner); - - route_unlock_node (etn); + struct route_node *etn; + struct vnc_export_info *eti; + struct vnc_export_info *eti_prev = NULL; + + etn = goner->node; + + for (eti = etn->info; eti; eti_prev = eti, eti = eti->next) { + if (eti == goner) + break; + } + + if (!eti) { + vnc_zlog_debug_verbose("%s: COULDN'T FIND ETI", __func__); + return; + } + + if (eti_prev) { + eti_prev->next = goner->next; + } else { + etn->info = goner->next; + } + + peer_unlock(eti->peer); + goner->node = NULL; + XFREE(MTYPE_RFAPI_ETI, goner); + + route_unlock_node(etn); } -struct vnc_export_info * -vnc_eti_checktimer ( - struct bgp *bgp, - vnc_export_type_t etype, - struct prefix *p, - struct peer *peer, - uint8_t type, - uint8_t subtype) +struct vnc_export_info *vnc_eti_checktimer(struct bgp *bgp, + vnc_export_type_t etype, + struct prefix *p, struct peer *peer, + uint8_t type, uint8_t subtype) { - struct route_node *etn; - struct vnc_export_info *eti; + struct route_node *etn; + struct vnc_export_info *eti; - etn = vnc_etn_lookup (bgp, etype, p); - if (!etn) - return NULL; + etn = vnc_etn_lookup(bgp, etype, p); + if (!etn) + return NULL; - for (eti = etn->info; eti; eti = eti->next) - { - if (peer == eti->peer && type == eti->type && subtype == eti->subtype) - { + for (eti = etn->info; eti; eti = eti->next) { + if (peer == eti->peer && type == eti->type + && subtype == eti->subtype) { - break; - } - } + break; + } + } - route_unlock_node (etn); + route_unlock_node(etn); - if (eti && eti->timer) - return eti; + if (eti && eti->timer) + return eti; - return NULL; + return NULL; } diff --git a/bgpd/rfapi/vnc_export_table.h b/bgpd/rfapi/vnc_export_table.h index 234520670..aa38233e8 100644 --- a/bgpd/rfapi/vnc_export_table.h +++ b/bgpd/rfapi/vnc_export_table.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -30,55 +30,37 @@ #define VNC_EXPORT_TYPE_BGP 1 #define VNC_EXPORT_TYPE_ZEBRA 2 -typedef enum vnc_export_type -{ - EXPORT_TYPE_BGP, - EXPORT_TYPE_ZEBRA +typedef enum vnc_export_type { + EXPORT_TYPE_BGP, + EXPORT_TYPE_ZEBRA } vnc_export_type_t; -struct vnc_export_info -{ - struct vnc_export_info *next; - struct route_node *node; - struct peer *peer; - u_char type; - u_char subtype; - uint32_t lifetime; - struct thread *timer; +struct vnc_export_info { + struct vnc_export_info *next; + struct route_node *node; + struct peer *peer; + u_char type; + u_char subtype; + uint32_t lifetime; + struct thread *timer; }; -extern struct route_node * -vnc_etn_get ( - struct bgp *bgp, - vnc_export_type_t type, - struct prefix *p); +extern struct route_node *vnc_etn_get(struct bgp *bgp, vnc_export_type_t type, + struct prefix *p); extern struct route_node * -vnc_etn_lookup ( - struct bgp *bgp, - vnc_export_type_t type, - struct prefix *p); +vnc_etn_lookup(struct bgp *bgp, vnc_export_type_t type, struct prefix *p); -extern struct vnc_export_info * -vnc_eti_get ( - struct bgp *bgp, - vnc_export_type_t etype, - struct prefix *p, - struct peer *peer, - uint8_t type, - uint8_t subtype); +extern struct vnc_export_info *vnc_eti_get(struct bgp *bgp, + vnc_export_type_t etype, + struct prefix *p, struct peer *peer, + uint8_t type, uint8_t subtype); -extern void -vnc_eti_delete (struct vnc_export_info *goner); +extern void vnc_eti_delete(struct vnc_export_info *goner); extern struct vnc_export_info * -vnc_eti_checktimer ( - struct bgp *bgp, - vnc_export_type_t etype, - struct prefix *p, - struct peer *peer, - uint8_t type, - uint8_t subtype); +vnc_eti_checktimer(struct bgp *bgp, vnc_export_type_t etype, struct prefix *p, + struct peer *peer, uint8_t type, uint8_t subtype); #endif /* _QUAGGA_VNC_VNC_EXPORT_TABLE_H_ */ diff --git a/bgpd/rfapi/vnc_import_bgp.c b/bgpd/rfapi/vnc_import_bgp.c index 1daf02a6b..117d4fbfd 100644 --- a/bgpd/rfapi/vnc_import_bgp.c +++ b/bgpd/rfapi/vnc_import_bgp.c @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -37,7 +37,7 @@ #include "bgpd/bgp_ecommunity.h" #include "bgpd/bgp_attr.h" #include "bgpd/bgp_route.h" -#include "bgpd/bgp_mplsvpn.h" /* for RD_TYPE_IP */ +#include "bgpd/bgp_mplsvpn.h" /* for RD_TYPE_IP */ #include "bgpd/rfapi/vnc_export_bgp.h" #include "bgpd/rfapi/bgp_rfapi_cfg.h" @@ -69,237 +69,212 @@ static struct rfapi_descriptor vncHDResolveNve; /* dummy nve descriptor */ * * LOCAL_PREF unchanged */ -uint32_t -calc_local_pref (struct attr *attr, struct peer *peer) +uint32_t calc_local_pref(struct attr *attr, struct peer *peer) { - uint32_t local_pref = 0; - - if (!attr) - { - if (peer) - { - return peer->bgp->default_local_pref; - } - return bgp_get_default ()->default_local_pref; - } - - if (peer && (peer->as != peer->bgp->as)) - { - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) - { - if (attr->med > 255) - { - local_pref = 0; - } - else - { - local_pref = 255 - attr->med; - } - } - else - { - local_pref = peer->bgp->default_local_pref; - } - } - else - { - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) - { - local_pref = attr->local_pref; - } - else - { - if (peer && peer->bgp) - { - local_pref = peer->bgp->default_local_pref; - } - } - } - - return local_pref; + uint32_t local_pref = 0; + + if (!attr) { + if (peer) { + return peer->bgp->default_local_pref; + } + return bgp_get_default()->default_local_pref; + } + + if (peer && (peer->as != peer->bgp->as)) { + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) { + if (attr->med > 255) { + local_pref = 0; + } else { + local_pref = 255 - attr->med; + } + } else { + local_pref = peer->bgp->default_local_pref; + } + } else { + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) { + local_pref = attr->local_pref; + } else { + if (peer && peer->bgp) { + local_pref = peer->bgp->default_local_pref; + } + } + } + + return local_pref; } -static int -is_host_prefix (struct prefix *p) +static int is_host_prefix(struct prefix *p) { - switch (p->family) - { - case AF_INET: - return (p->prefixlen == 32); - case AF_INET6: - return (p->prefixlen == 128); - } - return 0; + switch (p->family) { + case AF_INET: + return (p->prefixlen == 32); + case AF_INET6: + return (p->prefixlen == 128); + } + return 0; } /*********************************************************************** * RHN list ***********************************************************************/ -struct prefix_bag -{ - struct prefix hpfx; /* ce address = unicast nexthop */ - struct prefix upfx; /* unicast prefix */ - struct bgp_info *ubi; /* unicast route */ +struct prefix_bag { + struct prefix hpfx; /* ce address = unicast nexthop */ + struct prefix upfx; /* unicast prefix */ + struct bgp_info *ubi; /* unicast route */ }; -static const u_char maskbit[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, - 0xf8, 0xfc, 0xfe, 0xff -}; +static const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, + 0xf8, 0xfc, 0xfe, 0xff}; -int -vnc_prefix_cmp (void *pfx1, void *pfx2) +int vnc_prefix_cmp(void *pfx1, void *pfx2) { - int offset; - int shift; - u_char mask; - - struct prefix *p1 = pfx1; - struct prefix *p2 = pfx2; - - if (p1->family < p2->family) - return -1; - if (p1->family > p2->family) - return 1; - - if (p1->prefixlen < p2->prefixlen) - return -1; - if (p1->prefixlen > p2->prefixlen) - return 1; - - offset = p1->prefixlen / 8; - shift = p1->prefixlen % 8; - if (shift == 0 && offset) - { /* catch aligned case */ - offset--; - shift = 8; - } - - /* Set both prefix's head pointer. */ - const u_char *pp1 = (const u_char *) &p1->u.prefix; - const u_char *pp2 = (const u_char *) &p2->u.prefix; - - while (offset--) - { - if (*pp1 < *pp2) - return -1; - if (*pp1 > *pp2) - return 1; - ++pp1; - ++pp2; - } - - mask = maskbit[shift]; - if ((*pp1 & mask) < (*pp2 & mask)) - return -1; - if ((*pp1 & mask) > (*pp2 & mask)) - return 1; - - return 0; + int offset; + int shift; + u_char mask; + + struct prefix *p1 = pfx1; + struct prefix *p2 = pfx2; + + if (p1->family < p2->family) + return -1; + if (p1->family > p2->family) + return 1; + + if (p1->prefixlen < p2->prefixlen) + return -1; + if (p1->prefixlen > p2->prefixlen) + return 1; + + offset = p1->prefixlen / 8; + shift = p1->prefixlen % 8; + if (shift == 0 && offset) { /* catch aligned case */ + offset--; + shift = 8; + } + + /* Set both prefix's head pointer. */ + const u_char *pp1 = (const u_char *)&p1->u.prefix; + const u_char *pp2 = (const u_char *)&p2->u.prefix; + + while (offset--) { + if (*pp1 < *pp2) + return -1; + if (*pp1 > *pp2) + return 1; + ++pp1; + ++pp2; + } + + mask = maskbit[shift]; + if ((*pp1 & mask) < (*pp2 & mask)) + return -1; + if ((*pp1 & mask) > (*pp2 & mask)) + return 1; + + return 0; } -static void -prefix_bag_free (void *pb) +static void prefix_bag_free(void *pb) { - XFREE (MTYPE_RFAPI_PREFIX_BAG, pb); + XFREE(MTYPE_RFAPI_PREFIX_BAG, pb); } #if DEBUG_RHN_LIST -static void -print_rhn_list (const char *tag1, const char *tag2) +static void print_rhn_list(const char *tag1, const char *tag2) { - struct bgp *bgp; - struct skiplist *sl; - struct skiplistnode *p; - struct prefix_bag *pb; - int count = 0; - - bgp = bgp_get_default (); - if (!bgp) - return; - - sl = bgp->frapi->resolve_nve_nexthop; - if (!sl) - { - vnc_zlog_debug_verbose ("%s: %s: RHN List is empty", (tag1 ? tag1 : ""), - (tag2 ? tag2 : "")); - return; - } - - vnc_zlog_debug_verbose ("%s: %s: RHN list:", (tag1 ? tag1 : ""), (tag2 ? tag2 : "")); - - /* XXX uses secret knowledge of skiplist structure */ - for (p = sl->header->forward[0]; p; p = p->forward[0]) - { - char kbuf[BUFSIZ]; - char hbuf[BUFSIZ]; - char ubuf[BUFSIZ]; - - pb = p->value; - - prefix2str (p->key, kbuf, BUFSIZ); - prefix2str (&pb->hpfx, hbuf, BUFSIZ); - prefix2str (&pb->upfx, ubuf, BUFSIZ); - - vnc_zlog_debug_verbose ("RHN Entry %d (q=%p): kpfx=%s, upfx=%s, hpfx=%s, ubi=%p", - ++count, p, kbuf, ubuf, hbuf, pb->ubi); - } + struct bgp *bgp; + struct skiplist *sl; + struct skiplistnode *p; + struct prefix_bag *pb; + int count = 0; + + bgp = bgp_get_default(); + if (!bgp) + return; + + sl = bgp->frapi->resolve_nve_nexthop; + if (!sl) { + vnc_zlog_debug_verbose("%s: %s: RHN List is empty", + (tag1 ? tag1 : ""), (tag2 ? tag2 : "")); + return; + } + + vnc_zlog_debug_verbose("%s: %s: RHN list:", (tag1 ? tag1 : ""), + (tag2 ? tag2 : "")); + + /* XXX uses secret knowledge of skiplist structure */ + for (p = sl->header->forward[0]; p; p = p->forward[0]) { + char kbuf[BUFSIZ]; + char hbuf[BUFSIZ]; + char ubuf[BUFSIZ]; + + pb = p->value; + + prefix2str(p->key, kbuf, BUFSIZ); + prefix2str(&pb->hpfx, hbuf, BUFSIZ); + prefix2str(&pb->upfx, ubuf, BUFSIZ); + + vnc_zlog_debug_verbose( + "RHN Entry %d (q=%p): kpfx=%s, upfx=%s, hpfx=%s, ubi=%p", + ++count, p, kbuf, ubuf, hbuf, pb->ubi); + } } #endif #ifdef ENABLE_VNC_RHNCK -static void -vnc_rhnck (char *tag) +static void vnc_rhnck(char *tag) { - struct bgp *bgp; - struct skiplist *sl; - struct skiplistnode *p; - - bgp = bgp_get_default (); - if (!bgp) - return; - sl = bgp->rfapi->resolve_nve_nexthop; - - if (!sl) - return; - - /* XXX uses secret knowledge of skiplist structure */ - for (p = sl->header->forward[0]; p; p = p->forward[0]) - { - struct prefix_bag *pb; - struct prefix *pkey; - afi_t afi; - struct prefix pfx_orig_nexthop; - - memset (&pfx_orig_nexthop, 0, sizeof (struct prefix)); /* keep valgrind happy */ - - pkey = p->key; - pb = p->value; - - afi = family2afi (pb->upfx.family); - - rfapiUnicastNexthop2Prefix (afi, pb->ubi->attr, &pfx_orig_nexthop); - - /* pb->hpfx, pb->ubi nexthop, pkey should all reflect the same pfx */ - assert (!vnc_prefix_cmp (&pb->hpfx, pkey)); - if (vnc_prefix_cmp (&pb->hpfx, &pfx_orig_nexthop)) - { - char str_onh[BUFSIZ]; - char str_nve_pfx[BUFSIZ]; - - prefix2str (&pfx_orig_nexthop, str_onh, BUFSIZ); - str_onh[BUFSIZ - 1] = 0; - - prefix2str (&pb->hpfx, str_nve_pfx, BUFSIZ); - str_nve_pfx[BUFSIZ - 1] = 0; - - vnc_zlog_debug_verbose - ("%s: %s: FATAL: resolve_nve_nexthop list item bi nexthop %s != nve pfx %s", - __func__, tag, str_onh, str_nve_pfx); - assert (0); - } - } - vnc_zlog_debug_verbose ("%s: vnc_rhnck OK", tag); + struct bgp *bgp; + struct skiplist *sl; + struct skiplistnode *p; + + bgp = bgp_get_default(); + if (!bgp) + return; + sl = bgp->rfapi->resolve_nve_nexthop; + + if (!sl) + return; + + /* XXX uses secret knowledge of skiplist structure */ + for (p = sl->header->forward[0]; p; p = p->forward[0]) { + struct prefix_bag *pb; + struct prefix *pkey; + afi_t afi; + struct prefix pfx_orig_nexthop; + + memset(&pfx_orig_nexthop, 0, + sizeof(struct prefix)); /* keep valgrind happy */ + + pkey = p->key; + pb = p->value; + + afi = family2afi(pb->upfx.family); + + rfapiUnicastNexthop2Prefix(afi, pb->ubi->attr, + &pfx_orig_nexthop); + + /* pb->hpfx, pb->ubi nexthop, pkey should all reflect the same + * pfx */ + assert(!vnc_prefix_cmp(&pb->hpfx, pkey)); + if (vnc_prefix_cmp(&pb->hpfx, &pfx_orig_nexthop)) { + char str_onh[BUFSIZ]; + char str_nve_pfx[BUFSIZ]; + + prefix2str(&pfx_orig_nexthop, str_onh, BUFSIZ); + str_onh[BUFSIZ - 1] = 0; + + prefix2str(&pb->hpfx, str_nve_pfx, BUFSIZ); + str_nve_pfx[BUFSIZ - 1] = 0; + + vnc_zlog_debug_verbose( + "%s: %s: FATAL: resolve_nve_nexthop list item bi nexthop %s != nve pfx %s", + __func__, tag, str_onh, str_nve_pfx); + assert(0); + } + } + vnc_zlog_debug_verbose("%s: vnc_rhnck OK", tag); } #define VNC_RHNCK(n) do {char buf[BUFSIZ];sprintf(buf,"%s: %s", __func__, #n);vnc_rhnck(buf);} while (0) @@ -324,1181 +299,1106 @@ vnc_rhnck (char *tag) * * If return code is 0, caller MUST release ecom */ -static int -process_unicast_route ( - struct bgp *bgp, /* in */ - afi_t afi, /* in */ - struct prefix *prefix, /* in */ - struct bgp_info *info, /* in */ - struct ecommunity **ecom, /* OUT */ - struct prefix *unicast_nexthop) /* OUT */ +static int process_unicast_route(struct bgp *bgp, /* in */ + afi_t afi, /* in */ + struct prefix *prefix, /* in */ + struct bgp_info *info, /* in */ + struct ecommunity **ecom, /* OUT */ + struct prefix *unicast_nexthop) /* OUT */ { - struct rfapi_cfg *hc = bgp->rfapi_cfg; - struct peer *peer = info->peer; - struct attr *attr = info->attr; - struct attr hattr; - struct route_map *rmap = NULL; - struct prefix pfx_orig_nexthop; - - memset (&pfx_orig_nexthop, 0, sizeof (struct prefix)); /* keep valgrind happy */ - - /* - * prefix list check - */ - if (hc->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi]) - { - vnc_zlog_debug_verbose ("%s: HC prefix list is set, checking", __func__); - if (prefix_list_apply - (hc->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi], - prefix) == PREFIX_DENY) - { - vnc_zlog_debug_verbose ("%s: prefix list returns DENY, blocking route", - __func__); - return -1; - } - vnc_zlog_debug_verbose ("%s: prefix list returns PASS, allowing route", __func__); - } - - /* apply routemap, if any, later */ - rmap = hc->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT]; - - /* - * Extract original nexthop, which we expect to be a NVE connected router - * Note that this is the nexthop before any possible application of policy - */ - /* - * Incoming prefix is unicast. If v6, it is in multiprotocol area, - * but if v4 it is in attr->nexthop - */ - rfapiUnicastNexthop2Prefix (afi, attr, &pfx_orig_nexthop); - - /* - * route map handling - * This code is here because it allocates an interned attr which - * must be freed before we return. It's easier to put it after - * all of the possible returns above. - */ - memset (&hattr, 0, sizeof (struct attr)); - bgp_attr_dup (&hattr, attr); /* hattr becomes a ghost attr */ - - if (rmap) - { - struct bgp_info info; - route_map_result_t ret; - - memset (&info, 0, sizeof (info)); - info.peer = peer; - info.attr = &hattr; - ret = route_map_apply (rmap, prefix, RMAP_BGP, &info); - if (ret == RMAP_DENYMATCH) - { - bgp_attr_flush (&hattr); - vnc_zlog_debug_verbose ("%s: route map \"%s\" says DENY, returning", __func__, - rmap->name); - return -1; - } - } - - /* - * Get the (possibly altered by policy) unicast nexthop - * for later lookup in the Import Table by caller - */ - rfapiUnicastNexthop2Prefix (afi, &hattr, unicast_nexthop); - - if (hattr.ecommunity) - *ecom = ecommunity_dup (hattr.ecommunity); - else - *ecom = ecommunity_new (); - - /* - * Done with hattr, clean up - */ - bgp_attr_flush (&hattr); - - /* - * Add EC that carries original NH of iBGP route (2 bytes = magic - * value indicating it came from an VNC gateway; default 5226, but - * must be user configurable). Note that this is the nexthop before - * any application of policy. - */ - { - struct ecommunity_val vnc_gateway_magic; - uint16_t localadmin; - - /* Using route origin extended community type */ - memset (&vnc_gateway_magic, 0, sizeof (vnc_gateway_magic)); - vnc_gateway_magic.val[0] = 0x01; - vnc_gateway_magic.val[1] = 0x03; - - /* Only works for IPv4 nexthops */ - if (prefix->family == AF_INET) - { - memcpy (vnc_gateway_magic.val + 2, &unicast_nexthop->u.prefix4, 4); - } - localadmin = htons (hc->resolve_nve_roo_local_admin); - memcpy (vnc_gateway_magic.val + 6, (char *) &localadmin, 2); - - ecommunity_add_val (*ecom, &vnc_gateway_magic); - } - - return 0; + struct rfapi_cfg *hc = bgp->rfapi_cfg; + struct peer *peer = info->peer; + struct attr *attr = info->attr; + struct attr hattr; + struct route_map *rmap = NULL; + struct prefix pfx_orig_nexthop; + + memset(&pfx_orig_nexthop, 0, + sizeof(struct prefix)); /* keep valgrind happy */ + + /* + * prefix list check + */ + if (hc->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi]) { + vnc_zlog_debug_verbose("%s: HC prefix list is set, checking", + __func__); + if (prefix_list_apply( + hc->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi], + prefix) + == PREFIX_DENY) { + vnc_zlog_debug_verbose( + "%s: prefix list returns DENY, blocking route", + __func__); + return -1; + } + vnc_zlog_debug_verbose( + "%s: prefix list returns PASS, allowing route", + __func__); + } + + /* apply routemap, if any, later */ + rmap = hc->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT]; + + /* + * Extract original nexthop, which we expect to be a NVE connected + * router + * Note that this is the nexthop before any possible application of + * policy + */ + /* + * Incoming prefix is unicast. If v6, it is in multiprotocol area, + * but if v4 it is in attr->nexthop + */ + rfapiUnicastNexthop2Prefix(afi, attr, &pfx_orig_nexthop); + + /* + * route map handling + * This code is here because it allocates an interned attr which + * must be freed before we return. It's easier to put it after + * all of the possible returns above. + */ + memset(&hattr, 0, sizeof(struct attr)); + bgp_attr_dup(&hattr, attr); /* hattr becomes a ghost attr */ + + if (rmap) { + struct bgp_info info; + route_map_result_t ret; + + memset(&info, 0, sizeof(info)); + info.peer = peer; + info.attr = &hattr; + ret = route_map_apply(rmap, prefix, RMAP_BGP, &info); + if (ret == RMAP_DENYMATCH) { + bgp_attr_flush(&hattr); + vnc_zlog_debug_verbose( + "%s: route map \"%s\" says DENY, returning", + __func__, rmap->name); + return -1; + } + } + + /* + * Get the (possibly altered by policy) unicast nexthop + * for later lookup in the Import Table by caller + */ + rfapiUnicastNexthop2Prefix(afi, &hattr, unicast_nexthop); + + if (hattr.ecommunity) + *ecom = ecommunity_dup(hattr.ecommunity); + else + *ecom = ecommunity_new(); + + /* + * Done with hattr, clean up + */ + bgp_attr_flush(&hattr); + + /* + * Add EC that carries original NH of iBGP route (2 bytes = magic + * value indicating it came from an VNC gateway; default 5226, but + * must be user configurable). Note that this is the nexthop before + * any application of policy. + */ + { + struct ecommunity_val vnc_gateway_magic; + uint16_t localadmin; + + /* Using route origin extended community type */ + memset(&vnc_gateway_magic, 0, sizeof(vnc_gateway_magic)); + vnc_gateway_magic.val[0] = 0x01; + vnc_gateway_magic.val[1] = 0x03; + + /* Only works for IPv4 nexthops */ + if (prefix->family == AF_INET) { + memcpy(vnc_gateway_magic.val + 2, + &unicast_nexthop->u.prefix4, 4); + } + localadmin = htons(hc->resolve_nve_roo_local_admin); + memcpy(vnc_gateway_magic.val + 6, (char *)&localadmin, 2); + + ecommunity_add_val(*ecom, &vnc_gateway_magic); + } + + return 0; } -static void -vnc_import_bgp_add_route_mode_resolve_nve_one_bi ( - struct bgp *bgp, - afi_t afi, - struct bgp_info *bi, /* VPN bi */ - struct prefix_rd *prd, /* RD */ - struct prefix *prefix, /* unicast route prefix */ - uint32_t *local_pref,/* NULL = no local_pref */ - uint32_t *med, /* NULL = no med */ - struct ecommunity *ecom) /* generated ecoms */ +static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi( + struct bgp *bgp, afi_t afi, struct bgp_info *bi, /* VPN bi */ + struct prefix_rd *prd, /* RD */ + struct prefix *prefix, /* unicast route prefix */ + uint32_t *local_pref, /* NULL = no local_pref */ + uint32_t *med, /* NULL = no med */ + struct ecommunity *ecom) /* generated ecoms */ { - struct prefix un; - struct prefix nexthop; - struct rfapi_ip_addr nexthop_h; - uint32_t lifetime; - uint32_t *plifetime; - struct bgp_attr_encap_subtlv *encaptlvs; - uint32_t label = 0; - - struct rfapi_un_option optary[3]; - struct rfapi_un_option *opt = NULL; - int cur_opt = 0; - - vnc_zlog_debug_verbose ("%s: entry", __func__); - - if (bi->type != ZEBRA_ROUTE_BGP && bi->type != ZEBRA_ROUTE_BGP_DIRECT) - { - - return; - } - if (bi->sub_type != BGP_ROUTE_NORMAL && - bi->sub_type != BGP_ROUTE_STATIC && bi->sub_type != BGP_ROUTE_RFP) - { - - return; - } - if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)) - return; - - vncHDResolveNve.peer = bi->peer; - if (!rfapiGetVncTunnelUnAddr (bi->attr, &un)) - { - if (rfapiQprefix2Raddr (&un, &vncHDResolveNve.un_addr)) - return; - } - else - { - memset (&vncHDResolveNve.un_addr, 0, sizeof (vncHDResolveNve.un_addr)); - } - - /* Use nexthop of VPN route as nexthop of constructed route */ - rfapiNexthop2Prefix (bi->attr, &nexthop); - rfapiQprefix2Raddr (&nexthop, &nexthop_h); - - if (rfapiGetVncLifetime (bi->attr, &lifetime)) - { - plifetime = NULL; - } - else - { - plifetime = &lifetime; - } - - if (bi->attr) - { - encaptlvs = bi->attr->vnc_subtlvs; - if (bi->attr->encap_tunneltype != BGP_ENCAP_TYPE_RESERVED && - bi->attr->encap_tunneltype != BGP_ENCAP_TYPE_MPLS) - { - if (opt != NULL) - opt->next = &optary[cur_opt]; - opt = &optary[cur_opt++]; - memset (opt, 0, sizeof (struct rfapi_un_option)); - opt->type = RFAPI_UN_OPTION_TYPE_TUNNELTYPE; - opt->v.tunnel.type = bi->attr->encap_tunneltype; - /* TBD parse bi->attr->extra->encap_subtlvs */ - } - } - else - { - encaptlvs = NULL; - } - - struct ecommunity *new_ecom = ecommunity_dup (ecom); - - if (bi->attr && bi->attr->ecommunity) - ecommunity_merge (new_ecom, bi->attr->ecommunity); - - if (bi->extra) - label = decode_label (&bi->extra->label); - - add_vnc_route ( - &vncHDResolveNve, - bgp, - SAFI_MPLS_VPN, - prefix, /* unicast route prefix */ - prd, - &nexthop_h, /* new nexthop */ - local_pref, - plifetime, - (struct bgp_tea_options *) encaptlvs, /* RFP options */ - opt, - NULL, - new_ecom, - med, /* NULL => don't set med */ - (label?&label:NULL), /* NULL= default */ - ZEBRA_ROUTE_BGP_DIRECT, - BGP_ROUTE_REDISTRIBUTE, - RFAPI_AHR_RFPOPT_IS_VNCTLV); /* flags */ - - ecommunity_free (&new_ecom); + struct prefix un; + struct prefix nexthop; + struct rfapi_ip_addr nexthop_h; + uint32_t lifetime; + uint32_t *plifetime; + struct bgp_attr_encap_subtlv *encaptlvs; + uint32_t label = 0; + + struct rfapi_un_option optary[3]; + struct rfapi_un_option *opt = NULL; + int cur_opt = 0; + vnc_zlog_debug_verbose("%s: entry", __func__); + + if (bi->type != ZEBRA_ROUTE_BGP && bi->type != ZEBRA_ROUTE_BGP_DIRECT) { + + return; + } + if (bi->sub_type != BGP_ROUTE_NORMAL && bi->sub_type != BGP_ROUTE_STATIC + && bi->sub_type != BGP_ROUTE_RFP) { + + return; + } + if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + return; + + vncHDResolveNve.peer = bi->peer; + if (!rfapiGetVncTunnelUnAddr(bi->attr, &un)) { + if (rfapiQprefix2Raddr(&un, &vncHDResolveNve.un_addr)) + return; + } else { + memset(&vncHDResolveNve.un_addr, 0, + sizeof(vncHDResolveNve.un_addr)); + } + + /* Use nexthop of VPN route as nexthop of constructed route */ + rfapiNexthop2Prefix(bi->attr, &nexthop); + rfapiQprefix2Raddr(&nexthop, &nexthop_h); + + if (rfapiGetVncLifetime(bi->attr, &lifetime)) { + plifetime = NULL; + } else { + plifetime = &lifetime; + } + + if (bi->attr) { + encaptlvs = bi->attr->vnc_subtlvs; + if (bi->attr->encap_tunneltype != BGP_ENCAP_TYPE_RESERVED + && bi->attr->encap_tunneltype != BGP_ENCAP_TYPE_MPLS) { + if (opt != NULL) + opt->next = &optary[cur_opt]; + opt = &optary[cur_opt++]; + memset(opt, 0, sizeof(struct rfapi_un_option)); + opt->type = RFAPI_UN_OPTION_TYPE_TUNNELTYPE; + opt->v.tunnel.type = bi->attr->encap_tunneltype; + /* TBD parse bi->attr->extra->encap_subtlvs */ + } + } else { + encaptlvs = NULL; + } + + struct ecommunity *new_ecom = ecommunity_dup(ecom); + + if (bi->attr && bi->attr->ecommunity) + ecommunity_merge(new_ecom, bi->attr->ecommunity); + + if (bi->extra) + label = decode_label(&bi->extra->label); + + add_vnc_route(&vncHDResolveNve, bgp, SAFI_MPLS_VPN, + prefix, /* unicast route prefix */ + prd, &nexthop_h, /* new nexthop */ + local_pref, plifetime, + (struct bgp_tea_options *)encaptlvs, /* RFP options */ + opt, NULL, new_ecom, med, /* NULL => don't set med */ + (label ? &label : NULL), /* NULL= default */ + ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE, + RFAPI_AHR_RFPOPT_IS_VNCTLV); /* flags */ + + ecommunity_free(&new_ecom); } -static void -vnc_import_bgp_add_route_mode_resolve_nve_one_rd ( - struct prefix_rd *prd, /* RD */ - struct bgp_table *table_rd, /* per-rd VPN route table */ - afi_t afi, - struct bgp *bgp, - struct prefix *prefix, /* unicast prefix */ - struct ecommunity *ecom, /* generated ecoms */ - uint32_t *local_pref, /* NULL = no local_pref */ - uint32_t *med, /* NULL = no med */ - struct prefix *ubi_nexthop) /* unicast nexthop */ +static void vnc_import_bgp_add_route_mode_resolve_nve_one_rd( + struct prefix_rd *prd, /* RD */ + struct bgp_table *table_rd, /* per-rd VPN route table */ + afi_t afi, struct bgp *bgp, struct prefix *prefix, /* unicast prefix */ + struct ecommunity *ecom, /* generated ecoms */ + uint32_t *local_pref, /* NULL = no local_pref */ + uint32_t *med, /* NULL = no med */ + struct prefix *ubi_nexthop) /* unicast nexthop */ { - struct bgp_node *bn; - struct bgp_info *bi; + struct bgp_node *bn; + struct bgp_info *bi; - if (!table_rd) - return; + if (!table_rd) + return; - { - char str_nh[BUFSIZ]; + { + char str_nh[BUFSIZ]; - prefix2str (ubi_nexthop, str_nh, BUFSIZ); - str_nh[BUFSIZ - 1] = 0; + prefix2str(ubi_nexthop, str_nh, BUFSIZ); + str_nh[BUFSIZ - 1] = 0; - vnc_zlog_debug_verbose ("%s: ubi_nexthop=%s", __func__, str_nh); - } + vnc_zlog_debug_verbose("%s: ubi_nexthop=%s", __func__, str_nh); + } - /* exact match */ - bn = bgp_node_lookup (table_rd, ubi_nexthop); - if (!bn) - { - vnc_zlog_debug_verbose ("%s: no match in RD's table for ubi_nexthop", __func__); - return; - } + /* exact match */ + bn = bgp_node_lookup(table_rd, ubi_nexthop); + if (!bn) { + vnc_zlog_debug_verbose( + "%s: no match in RD's table for ubi_nexthop", __func__); + return; + } - /* Iterate over bgp_info items at this node */ - for (bi = bn->info; bi; bi = bi->next) - { + /* Iterate over bgp_info items at this node */ + for (bi = bn->info; bi; bi = bi->next) { - vnc_import_bgp_add_route_mode_resolve_nve_one_bi (bgp, afi, bi, /* VPN bi */ - prd, - prefix, - local_pref, - med, ecom); - } + vnc_import_bgp_add_route_mode_resolve_nve_one_bi( + bgp, afi, bi, /* VPN bi */ + prd, prefix, local_pref, med, ecom); + } - bgp_unlock_node (bn); + bgp_unlock_node(bn); } -static void -vnc_import_bgp_add_route_mode_resolve_nve ( - struct bgp *bgp, - struct prefix *prefix,/* unicast prefix */ - struct bgp_info *info) /* unicast info */ +static void vnc_import_bgp_add_route_mode_resolve_nve( + struct bgp *bgp, struct prefix *prefix, /* unicast prefix */ + struct bgp_info *info) /* unicast info */ { - afi_t afi = family2afi (prefix->family); - struct rfapi_cfg *hc = NULL; - - struct prefix pfx_unicast_nexthop = { 0 }; /* happy valgrind */ - - struct ecommunity *ecom = NULL; - uint32_t local_pref; - uint32_t *med = NULL; - - struct prefix_bag *pb; - struct bgp_node *bnp; /* prd table node */ - - /*debugging */ - { - char str_pfx[BUFSIZ]; - char str_nh[BUFSIZ]; - struct prefix nh; - - prefix2str (prefix, str_pfx, BUFSIZ); - str_pfx[BUFSIZ - 1] = 0; - - nh.prefixlen = 0; - rfapiUnicastNexthop2Prefix (afi, info->attr, &nh); - if (nh.prefixlen) - { - prefix2str (&nh, str_nh, BUFSIZ); - str_nh[BUFSIZ - 1] = 0; - } - else - { - str_nh[0] = '?'; - str_nh[1] = 0; - } - - vnc_zlog_debug_verbose ("%s(bgp=%p, unicast prefix=%s, unicast nh=%s)", - __func__, bgp, str_pfx, str_nh); - } - - if (info->type != ZEBRA_ROUTE_BGP) - { - vnc_zlog_debug_verbose ("%s: unicast type %d=\"%s\" is not %d=%s, skipping", - __func__, info->type, zebra_route_string (info->type), - ZEBRA_ROUTE_BGP, "ZEBRA_ROUTE_BGP"); - return; - } - - /* - * Preliminary checks - */ - - if (!afi) - { - zlog_err ("%s: can't get afi of prefix", __func__); - return; - } - - if (!(hc = bgp->rfapi_cfg)) - { - vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__); - return; - } - - /* check vnc redist flag for bgp direct routes */ - if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) - { - vnc_zlog_debug_verbose - ("%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping", - __func__, afi); - return; - } - - - if (process_unicast_route (bgp, afi, prefix, info, - &ecom, &pfx_unicast_nexthop)) - { - - vnc_zlog_debug_verbose ("%s: process_unicast_route error, skipping", __func__); - return; - } - - local_pref = calc_local_pref (info->attr, info->peer); - if (info->attr && - (info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))) - { - - med = &info->attr->med; - } - - - /* - * At this point, we have allocated: - * - * ecom ecommunity ptr, union of unicast and ROO parts (no NVE part) - * - * And we have set: - * - * pfx_unicast_nexthop nexthop of uncast route - */ - - if (!bgp->rfapi->resolve_nve_nexthop) - { - bgp->rfapi->resolve_nve_nexthop = - skiplist_new (SKIPLIST_FLAG_ALLOW_DUPLICATES, vnc_prefix_cmp, - prefix_bag_free); - } - - pb = XCALLOC (MTYPE_RFAPI_PREFIX_BAG, sizeof (struct prefix_bag)); - pb->hpfx = pfx_unicast_nexthop; - pb->ubi = info; - pb->upfx = *prefix; - - bgp_info_lock (info); /* skiplist refers to it */ - skiplist_insert (bgp->rfapi->resolve_nve_nexthop, &pb->hpfx, pb); - - /* - * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop - * (exact match, /32). If an exact match is found, call add_vnc_route. - */ - - for (bnp = bgp_table_top (bgp->rib[afi][SAFI_MPLS_VPN]); bnp; - bnp = bgp_route_next (bnp)) - { - - struct bgp_table *table; - - table = (struct bgp_table *) (bnp->info); - - if (!table) - continue; - - vnc_import_bgp_add_route_mode_resolve_nve_one_rd ((struct prefix_rd *) - &bnp->p, table, afi, - bgp, prefix, ecom, - &local_pref, med, - &pfx_unicast_nexthop); - - } - - - if (ecom) - ecommunity_free (&ecom); - - vnc_zlog_debug_verbose ("%s: done", __func__); + afi_t afi = family2afi(prefix->family); + struct rfapi_cfg *hc = NULL; + + struct prefix pfx_unicast_nexthop = {0}; /* happy valgrind */ + + struct ecommunity *ecom = NULL; + uint32_t local_pref; + uint32_t *med = NULL; + + struct prefix_bag *pb; + struct bgp_node *bnp; /* prd table node */ + + /*debugging */ + { + char str_pfx[BUFSIZ]; + char str_nh[BUFSIZ]; + struct prefix nh; + + prefix2str(prefix, str_pfx, BUFSIZ); + str_pfx[BUFSIZ - 1] = 0; + + nh.prefixlen = 0; + rfapiUnicastNexthop2Prefix(afi, info->attr, &nh); + if (nh.prefixlen) { + prefix2str(&nh, str_nh, BUFSIZ); + str_nh[BUFSIZ - 1] = 0; + } else { + str_nh[0] = '?'; + str_nh[1] = 0; + } + + vnc_zlog_debug_verbose( + "%s(bgp=%p, unicast prefix=%s, unicast nh=%s)", + __func__, bgp, str_pfx, str_nh); + } + + if (info->type != ZEBRA_ROUTE_BGP) { + vnc_zlog_debug_verbose( + "%s: unicast type %d=\"%s\" is not %d=%s, skipping", + __func__, info->type, zebra_route_string(info->type), + ZEBRA_ROUTE_BGP, "ZEBRA_ROUTE_BGP"); + return; + } + + /* + * Preliminary checks + */ + + if (!afi) { + zlog_err("%s: can't get afi of prefix", __func__); + return; + } + + if (!(hc = bgp->rfapi_cfg)) { + vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", + __func__); + return; + } + + /* check vnc redist flag for bgp direct routes */ + if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) { + vnc_zlog_debug_verbose( + "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping", + __func__, afi); + return; + } + + + if (process_unicast_route(bgp, afi, prefix, info, &ecom, + &pfx_unicast_nexthop)) { + + vnc_zlog_debug_verbose( + "%s: process_unicast_route error, skipping", __func__); + return; + } + + local_pref = calc_local_pref(info->attr, info->peer); + if (info->attr + && (info->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))) { + + med = &info->attr->med; + } + + + /* + * At this point, we have allocated: + * + * ecom ecommunity ptr, union of unicast and ROO parts (no NVE part) + * + * And we have set: + * + * pfx_unicast_nexthop nexthop of uncast route + */ + + if (!bgp->rfapi->resolve_nve_nexthop) { + bgp->rfapi->resolve_nve_nexthop = + skiplist_new(SKIPLIST_FLAG_ALLOW_DUPLICATES, + vnc_prefix_cmp, prefix_bag_free); + } + + pb = XCALLOC(MTYPE_RFAPI_PREFIX_BAG, sizeof(struct prefix_bag)); + pb->hpfx = pfx_unicast_nexthop; + pb->ubi = info; + pb->upfx = *prefix; + + bgp_info_lock(info); /* skiplist refers to it */ + skiplist_insert(bgp->rfapi->resolve_nve_nexthop, &pb->hpfx, pb); + + /* + * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop + * (exact match, /32). If an exact match is found, call add_vnc_route. + */ + + for (bnp = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); bnp; + bnp = bgp_route_next(bnp)) { + + struct bgp_table *table; + + table = (struct bgp_table *)(bnp->info); + + if (!table) + continue; + + vnc_import_bgp_add_route_mode_resolve_nve_one_rd( + (struct prefix_rd *)&bnp->p, table, afi, bgp, prefix, + ecom, &local_pref, med, &pfx_unicast_nexthop); + } + + + if (ecom) + ecommunity_free(&ecom); + + vnc_zlog_debug_verbose("%s: done", __func__); } -static void -vnc_import_bgp_add_route_mode_plain (struct bgp *bgp, - struct prefix *prefix, - struct bgp_info *info) +static void vnc_import_bgp_add_route_mode_plain(struct bgp *bgp, + struct prefix *prefix, + struct bgp_info *info) { - afi_t afi = family2afi (prefix->family); - struct peer *peer = info->peer; - struct attr *attr = info->attr; - struct attr hattr; - struct rfapi_cfg *hc = NULL; - struct attr *iattr = NULL; - - struct rfapi_ip_addr vnaddr; - struct prefix vn_pfx_space; - struct prefix *vn_pfx = NULL; - int ahr_flags = 0; - struct ecommunity *ecom = NULL; - struct prefix_rd prd; - struct route_map *rmap = NULL; - uint32_t local_pref; - uint32_t *med = NULL; - - { - char buf[BUFSIZ]; - - buf[0] = 0; - prefix2str (prefix, buf, BUFSIZ); - buf[BUFSIZ - 1] = 0; - vnc_zlog_debug_verbose ("%s(prefix=%s) entry", __func__, buf); - } - - if (!afi) - { - zlog_err ("%s: can't get afi of prefix", __func__); - return; - } - - if (!(hc = bgp->rfapi_cfg)) - { - vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__); - return; - } - - /* check vnc redist flag for bgp direct routes */ - if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) - { - vnc_zlog_debug_verbose - ("%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping", - __func__, afi); - return; - } - - /* - * mode "plain" specific code - */ - { - vnc_zlog_debug_verbose ("%s: NOT using redist RFG", __func__); - - /* - * prefix list check - */ - if (hc->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi]) - { - vnc_zlog_debug_verbose ("%s: HC prefix list is set, checking", __func__); - if (prefix_list_apply - (hc->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi], - prefix) == PREFIX_DENY) - { - vnc_zlog_debug_verbose ("%s: prefix list returns DENY, blocking route", - __func__); - return; - } - vnc_zlog_debug_verbose ("%s: prefix list returns PASS, allowing route", __func__); - } - - /* apply routemap, if any, later */ - rmap = hc->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT]; - - /* - * Incoming prefix is unicast. If v6, it is in multiprotocol area, - * but if v4 it is in attr->nexthop - */ - rfapiUnicastNexthop2Prefix (afi, attr, &vn_pfx_space); - vn_pfx = &vn_pfx_space; - - /* UN address */ - ahr_flags |= RFAPI_AHR_NO_TUNNEL_SUBTLV; - } - - if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE)) - { - char buf[BUFSIZ]; - - buf[0] = 0; - prefix2str (vn_pfx, buf, BUFSIZ); - buf[BUFSIZ - 1] = 0; - vnc_zlog_debug_any ("%s vn_pfx=%s", __func__, buf); - } - - /* - * Compute VN address - */ - if (rfapiQprefix2Raddr (vn_pfx, &vnaddr)) - { - vnc_zlog_debug_verbose ("%s: redist VN invalid, skipping", __func__); - return; - } - - /* - * route map handling - * This code is here because it allocates an interned attr which - * must be freed before we return. It's easier to put it after - * all of the possible returns above. - */ - memset (&hattr, 0, sizeof (struct attr)); - bgp_attr_dup (&hattr, attr); /* hattr becomes a ghost attr */ - - if (rmap) - { - struct bgp_info info; - route_map_result_t ret; - - memset (&info, 0, sizeof (info)); - info.peer = peer; - info.attr = &hattr; - ret = route_map_apply (rmap, prefix, RMAP_BGP, &info); - if (ret == RMAP_DENYMATCH) - { - bgp_attr_flush (&hattr); - vnc_zlog_debug_verbose ("%s: route map \"%s\" says DENY, returning", __func__, - rmap->name); - return; - } - } - - iattr = bgp_attr_intern (&hattr); - bgp_attr_flush (&hattr); - - /* Now iattr is an allocated interned attr */ - - /* - * Mode "plain" specific code - * - * Sets RD in dummy HD - * Allocates ecom - */ - { - if (vnaddr.addr_family != AF_INET) - { - vnc_zlog_debug_verbose - ("%s: can't auto-assign RD, VN AF (%d) is not IPv4, skipping", - __func__, vnaddr.addr_family); - if (iattr) - { - bgp_attr_unintern (&iattr); - } - return; - } - memset (&prd, 0, sizeof (prd)); - rfapi_set_autord_from_vn (&prd, &vnaddr); - - if (iattr && iattr->ecommunity) - ecom = ecommunity_dup (iattr->ecommunity); - - } - - local_pref = calc_local_pref (iattr, peer); - - if (iattr && (iattr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))) - { - med = &iattr->med; - } - - if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE)) - { - char buf[BUFSIZ]; - - buf[0] = 0; - rfapiRfapiIpAddr2Str (&vnaddr, buf, BUFSIZ); - buf[BUFSIZ - 1] = 0; - vnc_zlog_debug_any ("%s: setting vnaddr to %s", __func__, buf); - } - - vncHDBgpDirect.peer = peer; - add_vnc_route (&vncHDBgpDirect, bgp, SAFI_MPLS_VPN, prefix, &prd, &vnaddr, &local_pref, &(bgp->rfapi_cfg->redist_lifetime), NULL, /* RFP options */ - NULL, NULL, ecom, med, /* med */ - NULL, /* label: default */ - ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE, ahr_flags); - vncHDBgpDirect.peer = NULL; - - if (ecom) - ecommunity_free (&ecom); + afi_t afi = family2afi(prefix->family); + struct peer *peer = info->peer; + struct attr *attr = info->attr; + struct attr hattr; + struct rfapi_cfg *hc = NULL; + struct attr *iattr = NULL; + + struct rfapi_ip_addr vnaddr; + struct prefix vn_pfx_space; + struct prefix *vn_pfx = NULL; + int ahr_flags = 0; + struct ecommunity *ecom = NULL; + struct prefix_rd prd; + struct route_map *rmap = NULL; + uint32_t local_pref; + uint32_t *med = NULL; + + { + char buf[BUFSIZ]; + + buf[0] = 0; + prefix2str(prefix, buf, BUFSIZ); + buf[BUFSIZ - 1] = 0; + vnc_zlog_debug_verbose("%s(prefix=%s) entry", __func__, buf); + } + + if (!afi) { + zlog_err("%s: can't get afi of prefix", __func__); + return; + } + + if (!(hc = bgp->rfapi_cfg)) { + vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", + __func__); + return; + } + + /* check vnc redist flag for bgp direct routes */ + if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) { + vnc_zlog_debug_verbose( + "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping", + __func__, afi); + return; + } + + /* + * mode "plain" specific code + */ + { + vnc_zlog_debug_verbose("%s: NOT using redist RFG", __func__); + + /* + * prefix list check + */ + if (hc->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi]) { + vnc_zlog_debug_verbose( + "%s: HC prefix list is set, checking", + __func__); + if (prefix_list_apply( + hc->plist_redist[ZEBRA_ROUTE_BGP_DIRECT] + [afi], + prefix) + == PREFIX_DENY) { + vnc_zlog_debug_verbose( + "%s: prefix list returns DENY, blocking route", + __func__); + return; + } + vnc_zlog_debug_verbose( + "%s: prefix list returns PASS, allowing route", + __func__); + } + + /* apply routemap, if any, later */ + rmap = hc->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT]; + + /* + * Incoming prefix is unicast. If v6, it is in multiprotocol + * area, + * but if v4 it is in attr->nexthop + */ + rfapiUnicastNexthop2Prefix(afi, attr, &vn_pfx_space); + vn_pfx = &vn_pfx_space; + + /* UN address */ + ahr_flags |= RFAPI_AHR_NO_TUNNEL_SUBTLV; + } + + if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE)) { + char buf[BUFSIZ]; + + buf[0] = 0; + prefix2str(vn_pfx, buf, BUFSIZ); + buf[BUFSIZ - 1] = 0; + vnc_zlog_debug_any("%s vn_pfx=%s", __func__, buf); + } + + /* + * Compute VN address + */ + if (rfapiQprefix2Raddr(vn_pfx, &vnaddr)) { + vnc_zlog_debug_verbose("%s: redist VN invalid, skipping", + __func__); + return; + } + + /* + * route map handling + * This code is here because it allocates an interned attr which + * must be freed before we return. It's easier to put it after + * all of the possible returns above. + */ + memset(&hattr, 0, sizeof(struct attr)); + bgp_attr_dup(&hattr, attr); /* hattr becomes a ghost attr */ + + if (rmap) { + struct bgp_info info; + route_map_result_t ret; + + memset(&info, 0, sizeof(info)); + info.peer = peer; + info.attr = &hattr; + ret = route_map_apply(rmap, prefix, RMAP_BGP, &info); + if (ret == RMAP_DENYMATCH) { + bgp_attr_flush(&hattr); + vnc_zlog_debug_verbose( + "%s: route map \"%s\" says DENY, returning", + __func__, rmap->name); + return; + } + } + + iattr = bgp_attr_intern(&hattr); + bgp_attr_flush(&hattr); + + /* Now iattr is an allocated interned attr */ + + /* + * Mode "plain" specific code + * + * Sets RD in dummy HD + * Allocates ecom + */ + { + if (vnaddr.addr_family != AF_INET) { + vnc_zlog_debug_verbose( + "%s: can't auto-assign RD, VN AF (%d) is not IPv4, skipping", + __func__, vnaddr.addr_family); + if (iattr) { + bgp_attr_unintern(&iattr); + } + return; + } + memset(&prd, 0, sizeof(prd)); + rfapi_set_autord_from_vn(&prd, &vnaddr); + + if (iattr && iattr->ecommunity) + ecom = ecommunity_dup(iattr->ecommunity); + } + + local_pref = calc_local_pref(iattr, peer); + + if (iattr && (iattr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))) { + med = &iattr->med; + } + + if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE)) { + char buf[BUFSIZ]; + + buf[0] = 0; + rfapiRfapiIpAddr2Str(&vnaddr, buf, BUFSIZ); + buf[BUFSIZ - 1] = 0; + vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__, buf); + } + + vncHDBgpDirect.peer = peer; + add_vnc_route(&vncHDBgpDirect, bgp, SAFI_MPLS_VPN, prefix, &prd, + &vnaddr, &local_pref, &(bgp->rfapi_cfg->redist_lifetime), + NULL, /* RFP options */ + NULL, NULL, ecom, med, /* med */ + NULL, /* label: default */ + ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE, + ahr_flags); + vncHDBgpDirect.peer = NULL; + + if (ecom) + ecommunity_free(&ecom); } static void -vnc_import_bgp_add_route_mode_nvegroup (struct bgp *bgp, - struct prefix *prefix, - struct bgp_info *info, - struct rfapi_nve_group_cfg *rfg) +vnc_import_bgp_add_route_mode_nvegroup(struct bgp *bgp, struct prefix *prefix, + struct bgp_info *info, + struct rfapi_nve_group_cfg *rfg) { - afi_t afi = family2afi (prefix->family); - struct peer *peer = info->peer; - struct attr *attr = info->attr; - struct attr hattr; - struct rfapi_cfg *hc = NULL; - struct attr *iattr = NULL; - - struct rfapi_ip_addr vnaddr; - struct prefix *vn_pfx = NULL; - int ahr_flags = 0; - struct ecommunity *ecom = NULL; - struct prefix_rd prd; - struct route_map *rmap = NULL; - uint32_t local_pref; - - { - char buf[BUFSIZ]; - - buf[0] = 0; - prefix2str (prefix, buf, BUFSIZ); - buf[BUFSIZ - 1] = 0; - vnc_zlog_debug_verbose ("%s(prefix=%s) entry", __func__, buf); - } - - assert (rfg); - - if (!afi) - { - zlog_err ("%s: can't get afi of prefix", __func__); - return; - } - - if (!(hc = bgp->rfapi_cfg)) - { - vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__); - return; - } - - /* check vnc redist flag for bgp direct routes */ - if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) - { - vnc_zlog_debug_verbose - ("%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping", - __func__, afi); - return; - } - - - /* - * RFG-specific code - */ - { - - struct rfapi_ip_prefix pfx_un; - - vnc_zlog_debug_verbose ("%s: using redist RFG", __func__); - - /* - * RFG prefix list check - */ - if (rfg->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi]) - { - vnc_zlog_debug_verbose ("%s: RFG prefix list is set, checking", __func__); - if (prefix_list_apply - (rfg->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi], - prefix) == PREFIX_DENY) - { - vnc_zlog_debug_verbose ("%s: prefix list returns DENY, blocking route", - __func__); - return; - } - vnc_zlog_debug_verbose ("%s: prefix list returns PASS, allowing route", __func__); - } - - /* apply routemap, if any, later */ - rmap = rfg->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT]; - - /* - * export nve group's VN addr prefix must be a /32 which - * will yield the VN addr to use - */ - vn_pfx = &rfg->vn_prefix; - - /* - * UN Address - */ - if (!is_host_prefix (&rfg->un_prefix)) - { - /* NB prefixlen==0 means it has not been configured */ - vnc_zlog_debug_verbose ("%s: redist RFG UN pfx not host pfx (plen=%d), skipping", - __func__, rfg->un_prefix.prefixlen); - return; - } - - rfapiQprefix2Rprefix (&rfg->un_prefix, &pfx_un); - - vncHDBgpDirect.un_addr = pfx_un.prefix; - } - - if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE)) - { - char buf[BUFSIZ]; - - buf[0] = 0; - prefix2str (vn_pfx, buf, BUFSIZ); - buf[BUFSIZ - 1] = 0; - vnc_zlog_debug_any ("%s vn_pfx=%s", __func__, buf); - } - - /* - * Compute VN address - */ - if (rfapiQprefix2Raddr (vn_pfx, &vnaddr)) - { - vnc_zlog_debug_verbose ("%s: redist VN invalid, skipping", __func__); - return; - } - - /* - * route map handling - * This code is here because it allocates an interned attr which - * must be freed before we return. It's easier to put it after - * all of the possible returns above. - */ - memset (&hattr, 0, sizeof (struct attr)); - bgp_attr_dup (&hattr, attr); /* hattr becomes a ghost attr */ - - if (rmap) - { - struct bgp_info info; - route_map_result_t ret; - - memset (&info, 0, sizeof (info)); - info.peer = peer; - info.attr = &hattr; - ret = route_map_apply (rmap, prefix, RMAP_BGP, &info); - if (ret == RMAP_DENYMATCH) - { - bgp_attr_flush (&hattr); - vnc_zlog_debug_verbose ("%s: route map \"%s\" says DENY, returning", __func__, - rmap->name); - return; - } - } - - iattr = bgp_attr_intern (&hattr); - bgp_attr_flush (&hattr); - - /* Now iattr is an allocated interned attr */ - - /* - * RFG-specific code - * - * Sets RD in dummy HD - * Allocates ecom - */ - { - - memset (&prd, 0, sizeof (prd)); - prd = rfg->rd; - prd.family = AF_UNSPEC; - prd.prefixlen = 64; - - if (rfg->rd.family == AF_UNIX) - { - rfapi_set_autord_from_vn (&prd, &vnaddr); - } - - if (rfg->rt_export_list) - ecom = ecommunity_dup (bgp->rfapi_cfg->rfg_redist->rt_export_list); - else - ecom = ecommunity_new (); - - if (iattr && iattr->ecommunity) - ecom = ecommunity_merge (ecom, iattr->ecommunity); - } - - local_pref = calc_local_pref (iattr, peer); - - if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE)) - { - char buf[BUFSIZ]; - - buf[0] = 0; - rfapiRfapiIpAddr2Str (&vnaddr, buf, BUFSIZ); - buf[BUFSIZ - 1] = 0; - vnc_zlog_debug_any ("%s: setting vnaddr to %s", __func__, buf); - } - - vncHDBgpDirect.peer = peer; - add_vnc_route ( - &vncHDBgpDirect, - bgp, - SAFI_MPLS_VPN, - prefix, - &prd, - &vnaddr, - &local_pref, - &(bgp->rfapi_cfg->redist_lifetime), - NULL, /* RFP options */ - NULL, - NULL, - ecom, - NULL, /* med */ - NULL, /* label: default */ - ZEBRA_ROUTE_BGP_DIRECT, - BGP_ROUTE_REDISTRIBUTE, - ahr_flags); - vncHDBgpDirect.peer = NULL; - - if (ecom) - ecommunity_free (&ecom); + afi_t afi = family2afi(prefix->family); + struct peer *peer = info->peer; + struct attr *attr = info->attr; + struct attr hattr; + struct rfapi_cfg *hc = NULL; + struct attr *iattr = NULL; + + struct rfapi_ip_addr vnaddr; + struct prefix *vn_pfx = NULL; + int ahr_flags = 0; + struct ecommunity *ecom = NULL; + struct prefix_rd prd; + struct route_map *rmap = NULL; + uint32_t local_pref; + + { + char buf[BUFSIZ]; + + buf[0] = 0; + prefix2str(prefix, buf, BUFSIZ); + buf[BUFSIZ - 1] = 0; + vnc_zlog_debug_verbose("%s(prefix=%s) entry", __func__, buf); + } + + assert(rfg); + + if (!afi) { + zlog_err("%s: can't get afi of prefix", __func__); + return; + } + + if (!(hc = bgp->rfapi_cfg)) { + vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", + __func__); + return; + } + + /* check vnc redist flag for bgp direct routes */ + if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) { + vnc_zlog_debug_verbose( + "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping", + __func__, afi); + return; + } + + + /* + * RFG-specific code + */ + { + + struct rfapi_ip_prefix pfx_un; + + vnc_zlog_debug_verbose("%s: using redist RFG", __func__); + + /* + * RFG prefix list check + */ + if (rfg->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi]) { + vnc_zlog_debug_verbose( + "%s: RFG prefix list is set, checking", + __func__); + if (prefix_list_apply( + rfg->plist_redist[ZEBRA_ROUTE_BGP_DIRECT] + [afi], + prefix) + == PREFIX_DENY) { + vnc_zlog_debug_verbose( + "%s: prefix list returns DENY, blocking route", + __func__); + return; + } + vnc_zlog_debug_verbose( + "%s: prefix list returns PASS, allowing route", + __func__); + } + + /* apply routemap, if any, later */ + rmap = rfg->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT]; + + /* + * export nve group's VN addr prefix must be a /32 which + * will yield the VN addr to use + */ + vn_pfx = &rfg->vn_prefix; + + /* + * UN Address + */ + if (!is_host_prefix(&rfg->un_prefix)) { + /* NB prefixlen==0 means it has not been configured */ + vnc_zlog_debug_verbose( + "%s: redist RFG UN pfx not host pfx (plen=%d), skipping", + __func__, rfg->un_prefix.prefixlen); + return; + } + + rfapiQprefix2Rprefix(&rfg->un_prefix, &pfx_un); + + vncHDBgpDirect.un_addr = pfx_un.prefix; + } + + if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE)) { + char buf[BUFSIZ]; + + buf[0] = 0; + prefix2str(vn_pfx, buf, BUFSIZ); + buf[BUFSIZ - 1] = 0; + vnc_zlog_debug_any("%s vn_pfx=%s", __func__, buf); + } + + /* + * Compute VN address + */ + if (rfapiQprefix2Raddr(vn_pfx, &vnaddr)) { + vnc_zlog_debug_verbose("%s: redist VN invalid, skipping", + __func__); + return; + } + + /* + * route map handling + * This code is here because it allocates an interned attr which + * must be freed before we return. It's easier to put it after + * all of the possible returns above. + */ + memset(&hattr, 0, sizeof(struct attr)); + bgp_attr_dup(&hattr, attr); /* hattr becomes a ghost attr */ + + if (rmap) { + struct bgp_info info; + route_map_result_t ret; + + memset(&info, 0, sizeof(info)); + info.peer = peer; + info.attr = &hattr; + ret = route_map_apply(rmap, prefix, RMAP_BGP, &info); + if (ret == RMAP_DENYMATCH) { + bgp_attr_flush(&hattr); + vnc_zlog_debug_verbose( + "%s: route map \"%s\" says DENY, returning", + __func__, rmap->name); + return; + } + } + + iattr = bgp_attr_intern(&hattr); + bgp_attr_flush(&hattr); + + /* Now iattr is an allocated interned attr */ + + /* + * RFG-specific code + * + * Sets RD in dummy HD + * Allocates ecom + */ + { + + memset(&prd, 0, sizeof(prd)); + prd = rfg->rd; + prd.family = AF_UNSPEC; + prd.prefixlen = 64; + + if (rfg->rd.family == AF_UNIX) { + rfapi_set_autord_from_vn(&prd, &vnaddr); + } + + if (rfg->rt_export_list) + ecom = ecommunity_dup( + bgp->rfapi_cfg->rfg_redist->rt_export_list); + else + ecom = ecommunity_new(); + + if (iattr && iattr->ecommunity) + ecom = ecommunity_merge(ecom, iattr->ecommunity); + } + + local_pref = calc_local_pref(iattr, peer); + + if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE)) { + char buf[BUFSIZ]; + + buf[0] = 0; + rfapiRfapiIpAddr2Str(&vnaddr, buf, BUFSIZ); + buf[BUFSIZ - 1] = 0; + vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__, buf); + } + + vncHDBgpDirect.peer = peer; + add_vnc_route(&vncHDBgpDirect, bgp, SAFI_MPLS_VPN, prefix, &prd, + &vnaddr, &local_pref, &(bgp->rfapi_cfg->redist_lifetime), + NULL, /* RFP options */ + NULL, NULL, ecom, NULL, /* med */ + NULL, /* label: default */ + ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE, + ahr_flags); + vncHDBgpDirect.peer = NULL; + + if (ecom) + ecommunity_free(&ecom); } -static void -vnc_import_bgp_del_route_mode_plain (struct bgp *bgp, - struct prefix *prefix, - struct bgp_info *info) +static void vnc_import_bgp_del_route_mode_plain(struct bgp *bgp, + struct prefix *prefix, + struct bgp_info *info) { - struct prefix_rd prd; - afi_t afi = family2afi (prefix->family); - struct prefix *vn_pfx = NULL; - struct rfapi_ip_addr vnaddr; - struct prefix vn_pfx_space; - - - assert (afi); - - /* - * Compute VN address - */ - - if (info && info->attr) - { - rfapiUnicastNexthop2Prefix (afi, info->attr, &vn_pfx_space); - } - else - { - vnc_zlog_debug_verbose ("%s: no attr, can't delete route", __func__); - return; - } - vn_pfx = &vn_pfx_space; - - vnaddr.addr_family = vn_pfx->family; - switch (vn_pfx->family) - { - case AF_INET: - if (vn_pfx->prefixlen != 32) - { - vnc_zlog_debug_verbose ("%s: redist VN plen (%d) != 32, skipping", - __func__, vn_pfx->prefixlen); - return; - } - vnaddr.addr.v4 = vn_pfx->u.prefix4; - break; - - case AF_INET6: - if (vn_pfx->prefixlen != 128) - { - vnc_zlog_debug_verbose ("%s: redist VN plen (%d) != 128, skipping", - __func__, vn_pfx->prefixlen); - return; - } - vnaddr.addr.v6 = vn_pfx->u.prefix6; - break; - - default: - vnc_zlog_debug_verbose ("%s: no redist RFG VN host pfx configured, skipping", - __func__); - return; - } - - - memset (&prd, 0, sizeof (prd)); - if (rfapi_set_autord_from_vn (&prd, &vnaddr)) - { - vnc_zlog_debug_verbose ("%s: can't auto-assign RD, skipping", __func__); - return; - } - - vncHDBgpDirect.peer = info->peer; - vnc_zlog_debug_verbose ("%s: setting peer to %p", __func__, vncHDBgpDirect.peer); - del_vnc_route (&vncHDBgpDirect, - info->peer, - bgp, - SAFI_MPLS_VPN, - prefix, - &prd, - ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, 1); - - vncHDBgpDirect.peer = NULL; + struct prefix_rd prd; + afi_t afi = family2afi(prefix->family); + struct prefix *vn_pfx = NULL; + struct rfapi_ip_addr vnaddr; + struct prefix vn_pfx_space; + + + assert(afi); + + /* + * Compute VN address + */ + + if (info && info->attr) { + rfapiUnicastNexthop2Prefix(afi, info->attr, &vn_pfx_space); + } else { + vnc_zlog_debug_verbose("%s: no attr, can't delete route", + __func__); + return; + } + vn_pfx = &vn_pfx_space; + + vnaddr.addr_family = vn_pfx->family; + switch (vn_pfx->family) { + case AF_INET: + if (vn_pfx->prefixlen != 32) { + vnc_zlog_debug_verbose( + "%s: redist VN plen (%d) != 32, skipping", + __func__, vn_pfx->prefixlen); + return; + } + vnaddr.addr.v4 = vn_pfx->u.prefix4; + break; + + case AF_INET6: + if (vn_pfx->prefixlen != 128) { + vnc_zlog_debug_verbose( + "%s: redist VN plen (%d) != 128, skipping", + __func__, vn_pfx->prefixlen); + return; + } + vnaddr.addr.v6 = vn_pfx->u.prefix6; + break; + + default: + vnc_zlog_debug_verbose( + "%s: no redist RFG VN host pfx configured, skipping", + __func__); + return; + } + + + memset(&prd, 0, sizeof(prd)); + if (rfapi_set_autord_from_vn(&prd, &vnaddr)) { + vnc_zlog_debug_verbose("%s: can't auto-assign RD, skipping", + __func__); + return; + } + + vncHDBgpDirect.peer = info->peer; + vnc_zlog_debug_verbose("%s: setting peer to %p", __func__, + vncHDBgpDirect.peer); + del_vnc_route(&vncHDBgpDirect, info->peer, bgp, SAFI_MPLS_VPN, prefix, + &prd, ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE, + NULL, 1); + + vncHDBgpDirect.peer = NULL; } -static void -vnc_import_bgp_del_route_mode_nvegroup (struct bgp *bgp, - struct prefix *prefix, - struct bgp_info *info) +static void vnc_import_bgp_del_route_mode_nvegroup(struct bgp *bgp, + struct prefix *prefix, + struct bgp_info *info) { - struct prefix_rd prd; - afi_t afi = family2afi (prefix->family); - struct rfapi_nve_group_cfg *rfg = NULL; - struct prefix *vn_pfx = NULL; - struct rfapi_ip_addr vnaddr; - - - assert (afi); - - assert ((rfg = bgp->rfapi_cfg->rfg_redist)); - - /* - * Compute VN address - */ - - /* - * export nve group's VN addr prefix must be a /32 which - * will yield the VN addr to use - */ - vn_pfx = &rfg->vn_prefix; - - - vnaddr.addr_family = vn_pfx->family; - switch (vn_pfx->family) - { - case AF_INET: - if (vn_pfx->prefixlen != 32) - { - vnc_zlog_debug_verbose ("%s: redist VN plen (%d) != 32, skipping", - __func__, vn_pfx->prefixlen); - return; - } - vnaddr.addr.v4 = vn_pfx->u.prefix4; - break; - - case AF_INET6: - if (vn_pfx->prefixlen != 128) - { - vnc_zlog_debug_verbose ("%s: redist VN plen (%d) != 128, skipping", - __func__, vn_pfx->prefixlen); - return; - } - vnaddr.addr.v6 = vn_pfx->u.prefix6; - break; - - default: - vnc_zlog_debug_verbose ("%s: no redist RFG VN host pfx configured, skipping", - __func__); - return; - } - - memset (&prd, 0, sizeof (prd)); - prd = rfg->rd; - prd.family = AF_UNSPEC; - prd.prefixlen = 64; - - if (rfg->rd.family == AF_UNIX) - { - /* means "auto" with VN addr */ - if (rfapi_set_autord_from_vn (&prd, &vnaddr)) - { - vnc_zlog_debug_verbose ("%s: can't auto-assign RD, skipping", __func__); - return; - } - } - - - vncHDBgpDirect.peer = info->peer; - vnc_zlog_debug_verbose ("%s: setting peer to %p", __func__, vncHDBgpDirect.peer); - del_vnc_route (&vncHDBgpDirect, - info->peer, - bgp, - SAFI_MPLS_VPN, - prefix, - &prd, - ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, 1); - - vncHDBgpDirect.peer = NULL; + struct prefix_rd prd; + afi_t afi = family2afi(prefix->family); + struct rfapi_nve_group_cfg *rfg = NULL; + struct prefix *vn_pfx = NULL; + struct rfapi_ip_addr vnaddr; + + + assert(afi); + + assert((rfg = bgp->rfapi_cfg->rfg_redist)); + + /* + * Compute VN address + */ + + /* + * export nve group's VN addr prefix must be a /32 which + * will yield the VN addr to use + */ + vn_pfx = &rfg->vn_prefix; + + + vnaddr.addr_family = vn_pfx->family; + switch (vn_pfx->family) { + case AF_INET: + if (vn_pfx->prefixlen != 32) { + vnc_zlog_debug_verbose( + "%s: redist VN plen (%d) != 32, skipping", + __func__, vn_pfx->prefixlen); + return; + } + vnaddr.addr.v4 = vn_pfx->u.prefix4; + break; + + case AF_INET6: + if (vn_pfx->prefixlen != 128) { + vnc_zlog_debug_verbose( + "%s: redist VN plen (%d) != 128, skipping", + __func__, vn_pfx->prefixlen); + return; + } + vnaddr.addr.v6 = vn_pfx->u.prefix6; + break; + + default: + vnc_zlog_debug_verbose( + "%s: no redist RFG VN host pfx configured, skipping", + __func__); + return; + } + + memset(&prd, 0, sizeof(prd)); + prd = rfg->rd; + prd.family = AF_UNSPEC; + prd.prefixlen = 64; + + if (rfg->rd.family == AF_UNIX) { + /* means "auto" with VN addr */ + if (rfapi_set_autord_from_vn(&prd, &vnaddr)) { + vnc_zlog_debug_verbose( + "%s: can't auto-assign RD, skipping", __func__); + return; + } + } + + + vncHDBgpDirect.peer = info->peer; + vnc_zlog_debug_verbose("%s: setting peer to %p", __func__, + vncHDBgpDirect.peer); + del_vnc_route(&vncHDBgpDirect, info->peer, bgp, SAFI_MPLS_VPN, prefix, + &prd, ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE, + NULL, 1); + + vncHDBgpDirect.peer = NULL; } -static void -vnc_import_bgp_del_route_mode_resolve_nve_one_bi ( - struct bgp *bgp, - afi_t afi, - struct bgp_info *bi, /* VPN bi */ - struct prefix_rd *prd, /* RD */ - struct prefix *prefix)/* unicast route prefix */ +static void vnc_import_bgp_del_route_mode_resolve_nve_one_bi( + struct bgp *bgp, afi_t afi, struct bgp_info *bi, /* VPN bi */ + struct prefix_rd *prd, /* RD */ + struct prefix *prefix) /* unicast route prefix */ { - struct prefix un; - - if (bi->type != ZEBRA_ROUTE_BGP && bi->type != ZEBRA_ROUTE_BGP_DIRECT) - { - - return; - } - if (bi->sub_type != BGP_ROUTE_NORMAL && - bi->sub_type != BGP_ROUTE_STATIC && bi->sub_type != BGP_ROUTE_RFP) - { - - return; - } - if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)) - return; - - vncHDResolveNve.peer = bi->peer; - if (!rfapiGetVncTunnelUnAddr (bi->attr, &un)) - { - if (rfapiQprefix2Raddr (&un, &vncHDResolveNve.un_addr)) - return; - } - else - { - memset (&vncHDResolveNve.un_addr, 0, sizeof (vncHDResolveNve.un_addr)); - } - - del_vnc_route (&vncHDResolveNve, vncHDResolveNve.peer, bgp, SAFI_MPLS_VPN, prefix, /* unicast route prefix */ - prd, ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, 0); /* flags */ + struct prefix un; + + if (bi->type != ZEBRA_ROUTE_BGP && bi->type != ZEBRA_ROUTE_BGP_DIRECT) { + return; + } + if (bi->sub_type != BGP_ROUTE_NORMAL && bi->sub_type != BGP_ROUTE_STATIC + && bi->sub_type != BGP_ROUTE_RFP) { + + return; + } + if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + return; + + vncHDResolveNve.peer = bi->peer; + if (!rfapiGetVncTunnelUnAddr(bi->attr, &un)) { + if (rfapiQprefix2Raddr(&un, &vncHDResolveNve.un_addr)) + return; + } else { + memset(&vncHDResolveNve.un_addr, 0, + sizeof(vncHDResolveNve.un_addr)); + } + + del_vnc_route(&vncHDResolveNve, vncHDResolveNve.peer, bgp, + SAFI_MPLS_VPN, prefix, /* unicast route prefix */ + prd, ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, + 0); /* flags */ } -static void -vnc_import_bgp_del_route_mode_resolve_nve_one_rd ( - struct prefix_rd *prd, - struct bgp_table *table_rd, /* per-rd VPN route table */ - afi_t afi, - struct bgp *bgp, - struct prefix *prefix, /* unicast prefix */ - struct prefix *ubi_nexthop) /* unicast bi's nexthop */ +static void vnc_import_bgp_del_route_mode_resolve_nve_one_rd( + struct prefix_rd *prd, + struct bgp_table *table_rd, /* per-rd VPN route table */ + afi_t afi, struct bgp *bgp, struct prefix *prefix, /* unicast prefix */ + struct prefix *ubi_nexthop) /* unicast bi's nexthop */ { - struct bgp_node *bn; - struct bgp_info *bi; + struct bgp_node *bn; + struct bgp_info *bi; - if (!table_rd) - return; + if (!table_rd) + return; - { - char str_nh[BUFSIZ]; + { + char str_nh[BUFSIZ]; - prefix2str (ubi_nexthop, str_nh, BUFSIZ); - str_nh[BUFSIZ - 1] = 0; + prefix2str(ubi_nexthop, str_nh, BUFSIZ); + str_nh[BUFSIZ - 1] = 0; - vnc_zlog_debug_verbose ("%s: ubi_nexthop=%s", __func__, str_nh); - } + vnc_zlog_debug_verbose("%s: ubi_nexthop=%s", __func__, str_nh); + } - /* exact match */ - bn = bgp_node_lookup (table_rd, ubi_nexthop); - if (!bn) - { - vnc_zlog_debug_verbose ("%s: no match in RD's table for ubi_nexthop", __func__); - return; - } + /* exact match */ + bn = bgp_node_lookup(table_rd, ubi_nexthop); + if (!bn) { + vnc_zlog_debug_verbose( + "%s: no match in RD's table for ubi_nexthop", __func__); + return; + } - /* Iterate over bgp_info items at this node */ - for (bi = bn->info; bi; bi = bi->next) - { + /* Iterate over bgp_info items at this node */ + for (bi = bn->info; bi; bi = bi->next) { - vnc_import_bgp_del_route_mode_resolve_nve_one_bi (bgp, afi, bi, /* VPN bi */ - prd, /* VPN RD */ - prefix); /* unicast route prefix */ - } + vnc_import_bgp_del_route_mode_resolve_nve_one_bi( + bgp, afi, bi, /* VPN bi */ + prd, /* VPN RD */ + prefix); /* unicast route prefix */ + } - bgp_unlock_node (bn); + bgp_unlock_node(bn); } -static void -vnc_import_bgp_del_route_mode_resolve_nve (struct bgp *bgp, - afi_t afi, - struct prefix *prefix, - struct bgp_info *info) +static void vnc_import_bgp_del_route_mode_resolve_nve(struct bgp *bgp, + afi_t afi, + struct prefix *prefix, + struct bgp_info *info) { - struct ecommunity *ecom = NULL; - struct prefix pfx_unicast_nexthop = { 0 }; /* happy valgrind */ - - //struct listnode *hnode; - //struct rfapi_descriptor *rfd; - struct prefix_bag *pb; - void *cursor; - struct skiplist *sl = bgp->rfapi->resolve_nve_nexthop; - int rc; - struct bgp_node *bnp; /* prd table node */ - - if (!sl) - { - vnc_zlog_debug_verbose ("%s: no RHN entries, skipping", __func__); - return; - } - - if (info->type != ZEBRA_ROUTE_BGP) - { - vnc_zlog_debug_verbose ("%s: unicast type %d=\"%s\" is not %d=%s, skipping", - __func__, info->type, zebra_route_string (info->type), - ZEBRA_ROUTE_BGP, "ZEBRA_ROUTE_BGP"); - return; - } - - if (process_unicast_route (bgp, afi, prefix, info, - &ecom, &pfx_unicast_nexthop)) - { - - vnc_zlog_debug_verbose ("%s: process_unicast_route error, skipping", __func__); - return; - } - - rc = skiplist_first_value (sl, &pfx_unicast_nexthop, (void *) &pb, &cursor); - while (!rc) - { - if (pb->ubi == info) - { - skiplist_delete (sl, &pfx_unicast_nexthop, pb); - bgp_info_unlock (info); - break; - } - rc = - skiplist_next_value (sl, &pfx_unicast_nexthop, (void *) &pb, &cursor); - } - - /* - * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop - * (exact match, /32). If an exact match is found, call add_vnc_route. - */ - - for (bnp = bgp_table_top (bgp->rib[afi][SAFI_MPLS_VPN]); bnp; - bnp = bgp_route_next (bnp)) - { - - struct bgp_table *table; - - table = (struct bgp_table *) (bnp->info); - - if (!table) - continue; - - vnc_import_bgp_del_route_mode_resolve_nve_one_rd ((struct prefix_rd *) &bnp->p, table, afi, bgp, prefix, &pfx_unicast_nexthop); /* TBD how is this set? */ - } - - if (ecom) - ecommunity_free (&ecom); -} + struct ecommunity *ecom = NULL; + struct prefix pfx_unicast_nexthop = {0}; /* happy valgrind */ + + // struct listnode *hnode; + // struct rfapi_descriptor *rfd; + struct prefix_bag *pb; + void *cursor; + struct skiplist *sl = bgp->rfapi->resolve_nve_nexthop; + int rc; + struct bgp_node *bnp; /* prd table node */ + + if (!sl) { + vnc_zlog_debug_verbose("%s: no RHN entries, skipping", + __func__); + return; + } + if (info->type != ZEBRA_ROUTE_BGP) { + vnc_zlog_debug_verbose( + "%s: unicast type %d=\"%s\" is not %d=%s, skipping", + __func__, info->type, zebra_route_string(info->type), + ZEBRA_ROUTE_BGP, "ZEBRA_ROUTE_BGP"); + return; + } + if (process_unicast_route(bgp, afi, prefix, info, &ecom, + &pfx_unicast_nexthop)) { + + vnc_zlog_debug_verbose( + "%s: process_unicast_route error, skipping", __func__); + return; + } + + rc = skiplist_first_value(sl, &pfx_unicast_nexthop, (void *)&pb, + &cursor); + while (!rc) { + if (pb->ubi == info) { + skiplist_delete(sl, &pfx_unicast_nexthop, pb); + bgp_info_unlock(info); + break; + } + rc = skiplist_next_value(sl, &pfx_unicast_nexthop, (void *)&pb, + &cursor); + } + + /* + * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop + * (exact match, /32). If an exact match is found, call add_vnc_route. + */ + + for (bnp = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); bnp; + bnp = bgp_route_next(bnp)) { + + struct bgp_table *table; + + table = (struct bgp_table *)(bnp->info); + + if (!table) + continue; + + vnc_import_bgp_del_route_mode_resolve_nve_one_rd( + (struct prefix_rd *)&bnp->p, table, afi, bgp, prefix, + &pfx_unicast_nexthop); /* TBD how is this set? */ + } + + if (ecom) + ecommunity_free(&ecom); +} /*********************************************************************** @@ -1509,262 +1409,256 @@ vnc_import_bgp_del_route_mode_resolve_nve (struct bgp *bgp, * Should be called whan a bi is added to VPN RIB. This function * will check if it is a host route and return immediately if not. */ -void -vnc_import_bgp_add_vnc_host_route_mode_resolve_nve ( - struct bgp *bgp, - struct prefix_rd *prd, /* RD */ - struct bgp_table *table_rd, /* per-rd VPN route table */ - struct prefix *prefix, /* VPN prefix */ - struct bgp_info *bi) /* new VPN host route */ +void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( + struct bgp *bgp, struct prefix_rd *prd, /* RD */ + struct bgp_table *table_rd, /* per-rd VPN route table */ + struct prefix *prefix, /* VPN prefix */ + struct bgp_info *bi) /* new VPN host route */ { - afi_t afi = family2afi (prefix->family); - struct skiplist *sl = NULL; - int rc; - struct prefix_bag *pb; - void *cursor; - struct rfapi_cfg *hc = NULL; - - vnc_zlog_debug_verbose ("%s: entry", __func__); - - if (afi != AFI_IP && afi != AFI_IP6) - { - vnc_zlog_debug_verbose ("%s: bad afi %d, skipping", __func__, afi); - return; - } - - if (!(hc = bgp->rfapi_cfg)) - { - vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__); - return; - } - - /* check vnc redist flag for bgp direct routes */ - if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) - { - vnc_zlog_debug_verbose - ("%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping", - __func__, afi); - return; - } - - if (hc->redist_mode != VNC_REDIST_MODE_RESOLVE_NVE) - { - vnc_zlog_debug_verbose ("%s: not in resolve-nve mode, skipping", __func__); - return; - } - - if (bgp && bgp->rfapi) - sl = bgp->rfapi->resolve_nve_nexthop; - - if (!sl) - { - vnc_zlog_debug_verbose ("%s: no resolve_nve_nexthop skiplist, skipping", __func__); - return; - } - - if (!is_host_prefix (prefix)) - { - vnc_zlog_debug_verbose ("%s: not host prefix, skipping", __func__); - return; - } - - rc = skiplist_first_value (sl, prefix, (void *) &pb, &cursor); - while (!rc) - { - struct ecommunity *ecom; - struct prefix pfx_unicast_nexthop; - uint32_t *med = NULL; - uint32_t local_pref; - - memset (&pfx_unicast_nexthop, 0, sizeof (struct prefix)); /* keep valgrind happy */ - - if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE)) - { - char hbuf[BUFSIZ]; - char ubuf[BUFSIZ]; + afi_t afi = family2afi(prefix->family); + struct skiplist *sl = NULL; + int rc; + struct prefix_bag *pb; + void *cursor; + struct rfapi_cfg *hc = NULL; + + vnc_zlog_debug_verbose("%s: entry", __func__); + + if (afi != AFI_IP && afi != AFI_IP6) { + vnc_zlog_debug_verbose("%s: bad afi %d, skipping", __func__, + afi); + return; + } + + if (!(hc = bgp->rfapi_cfg)) { + vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", + __func__); + return; + } - prefix2str (&pb->hpfx, hbuf, BUFSIZ); - prefix2str (&pb->upfx, ubuf, BUFSIZ); + /* check vnc redist flag for bgp direct routes */ + if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) { + vnc_zlog_debug_verbose( + "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping", + __func__, afi); + return; + } - vnc_zlog_debug_any - ("%s: examining RHN Entry (q=%p): upfx=%s, hpfx=%s, ubi=%p", - __func__, cursor, ubuf, hbuf, pb->ubi); + if (hc->redist_mode != VNC_REDIST_MODE_RESOLVE_NVE) { + vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping", + __func__); + return; } - if (process_unicast_route (bgp, afi, &pb->upfx, pb->ubi, - &ecom, &pfx_unicast_nexthop)) - { + if (bgp && bgp->rfapi) + sl = bgp->rfapi->resolve_nve_nexthop; + + if (!sl) { + vnc_zlog_debug_verbose( + "%s: no resolve_nve_nexthop skiplist, skipping", + __func__); + return; + } + + if (!is_host_prefix(prefix)) { + vnc_zlog_debug_verbose("%s: not host prefix, skipping", + __func__); + return; + } + + rc = skiplist_first_value(sl, prefix, (void *)&pb, &cursor); + while (!rc) { + struct ecommunity *ecom; + struct prefix pfx_unicast_nexthop; + uint32_t *med = NULL; + uint32_t local_pref; + + memset(&pfx_unicast_nexthop, 0, + sizeof(struct prefix)); /* keep valgrind happy */ + + if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE)) { + char hbuf[BUFSIZ]; + char ubuf[BUFSIZ]; - vnc_zlog_debug_verbose ("%s: process_unicast_route error, skipping", __func__); - continue; - } - local_pref = calc_local_pref (pb->ubi->attr, pb->ubi->peer); + prefix2str(&pb->hpfx, hbuf, BUFSIZ); + prefix2str(&pb->upfx, ubuf, BUFSIZ); - if (pb->ubi->attr && - (pb->ubi->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))) - { + vnc_zlog_debug_any( + "%s: examining RHN Entry (q=%p): upfx=%s, hpfx=%s, ubi=%p", + __func__, cursor, ubuf, hbuf, pb->ubi); + } - med = &pb->ubi->attr->med; - } + if (process_unicast_route(bgp, afi, &pb->upfx, pb->ubi, &ecom, + &pfx_unicast_nexthop)) { - /* - * Sanity check - */ - if (vnc_prefix_cmp (&pfx_unicast_nexthop, prefix)) - { - char str_unh[BUFSIZ]; - char str_nve_pfx[BUFSIZ]; + vnc_zlog_debug_verbose( + "%s: process_unicast_route error, skipping", + __func__); + continue; + } + local_pref = calc_local_pref(pb->ubi->attr, pb->ubi->peer); - prefix2str (&pfx_unicast_nexthop, str_unh, BUFSIZ); - str_unh[BUFSIZ - 1] = 0; + if (pb->ubi->attr + && (pb->ubi->attr->flag + & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))) { - prefix2str (prefix, str_nve_pfx, BUFSIZ); - str_nve_pfx[BUFSIZ - 1] = 0; + med = &pb->ubi->attr->med; + } - vnc_zlog_debug_verbose - ("%s: FATAL: resolve_nve_nexthop list item bi nexthop %s != nve pfx %s", - __func__, str_unh, str_nve_pfx); - assert (0); - } + /* + * Sanity check + */ + if (vnc_prefix_cmp(&pfx_unicast_nexthop, prefix)) { + char str_unh[BUFSIZ]; + char str_nve_pfx[BUFSIZ]; - vnc_import_bgp_add_route_mode_resolve_nve_one_bi (bgp, afi, bi, /* VPN bi */ - prd, &pb->upfx, /* unicast prefix */ - &local_pref, - med, ecom); + prefix2str(&pfx_unicast_nexthop, str_unh, BUFSIZ); + str_unh[BUFSIZ - 1] = 0; - if (ecom) - ecommunity_free (&ecom); + prefix2str(prefix, str_nve_pfx, BUFSIZ); + str_nve_pfx[BUFSIZ - 1] = 0; + + vnc_zlog_debug_verbose( + "%s: FATAL: resolve_nve_nexthop list item bi nexthop %s != nve pfx %s", + __func__, str_unh, str_nve_pfx); + assert(0); + } + + vnc_import_bgp_add_route_mode_resolve_nve_one_bi( + bgp, afi, bi, /* VPN bi */ + prd, &pb->upfx, /* unicast prefix */ + &local_pref, med, ecom); + + if (ecom) + ecommunity_free(&ecom); #if DEBUG_RHN_LIST - /* debug */ - { - char pbuf[BUFSIZ]; + /* debug */ + { + char pbuf[BUFSIZ]; - prefix2str (prefix, pbuf, BUFSIZ); + prefix2str(prefix, pbuf, BUFSIZ); - vnc_zlog_debug_verbose ("%s: advancing past RHN Entry (q=%p): with prefix %s", - __func__, cursor, pbuf); - print_rhn_list (__func__, NULL); /* debug */ - } + vnc_zlog_debug_verbose( + "%s: advancing past RHN Entry (q=%p): with prefix %s", + __func__, cursor, pbuf); + print_rhn_list(__func__, NULL); /* debug */ + } #endif - rc = skiplist_next_value (sl, prefix, (void *) &pb, &cursor); - } - vnc_zlog_debug_verbose ("%s: done", __func__); + rc = skiplist_next_value(sl, prefix, (void *)&pb, &cursor); + } + vnc_zlog_debug_verbose("%s: done", __func__); } -void -vnc_import_bgp_del_vnc_host_route_mode_resolve_nve ( - struct bgp *bgp, - struct prefix_rd *prd, /* RD */ - struct bgp_table *table_rd, /* per-rd VPN route table */ - struct prefix *prefix, /* VPN prefix */ - struct bgp_info *bi) /* old VPN host route */ +void vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( + struct bgp *bgp, struct prefix_rd *prd, /* RD */ + struct bgp_table *table_rd, /* per-rd VPN route table */ + struct prefix *prefix, /* VPN prefix */ + struct bgp_info *bi) /* old VPN host route */ { - afi_t afi = family2afi (prefix->family); - struct skiplist *sl = NULL; - struct prefix_bag *pb; - void *cursor; - struct rfapi_cfg *hc = NULL; - int rc; - - { - char str_pfx[BUFSIZ]; - - prefix2str (prefix, str_pfx, BUFSIZ); - str_pfx[BUFSIZ - 1] = 0; - - vnc_zlog_debug_verbose ("%s(bgp=%p, nve prefix=%s)", __func__, bgp, str_pfx); - } - - if (afi != AFI_IP && afi != AFI_IP6) - return; - - if (!(hc = bgp->rfapi_cfg)) - { - vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__); - return; - } - - /* check vnc redist flag for bgp direct routes */ - if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) - { - vnc_zlog_debug_verbose - ("%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping", - __func__, afi); - return; - } - - if (hc->redist_mode != VNC_REDIST_MODE_RESOLVE_NVE) - { - vnc_zlog_debug_verbose ("%s: not in resolve-nve mode, skipping", __func__); - return; - } - - if (bgp && bgp->rfapi) - sl = bgp->rfapi->resolve_nve_nexthop; - - if (!sl) - { - vnc_zlog_debug_verbose ("%s: no RHN entries, skipping", __func__); - return; - } - - if (!is_host_prefix (prefix)) - { - vnc_zlog_debug_verbose ("%s: not host route, skip", __func__); - return; - } - - /* - * Find all entries with key == CE in the RHN list - */ - rc = skiplist_first_value (sl, prefix, (void *) &pb, &cursor); - while (!rc) - { - - struct ecommunity *ecom; - struct prefix pfx_unicast_nexthop; - - memset (&pfx_unicast_nexthop, 0, sizeof (struct prefix)); /* keep valgrind happy */ - - if (process_unicast_route (bgp, afi, &pb->upfx, pb->ubi, - &ecom, &pfx_unicast_nexthop)) - { - - vnc_zlog_debug_verbose ("%s: process_unicast_route error, skipping", __func__); - continue; - } - - /* - * Sanity check - */ - if (vnc_prefix_cmp (&pfx_unicast_nexthop, prefix)) - { - char str_unh[BUFSIZ]; - char str_nve_pfx[BUFSIZ]; - - prefix2str (&pfx_unicast_nexthop, str_unh, BUFSIZ); - str_unh[BUFSIZ - 1] = 0; - - prefix2str (prefix, str_nve_pfx, BUFSIZ); - str_nve_pfx[BUFSIZ - 1] = 0; - - vnc_zlog_debug_verbose - ("%s: FATAL: resolve_nve_nexthop list item bi nexthop %s != nve pfx %s", - __func__, str_unh, str_nve_pfx); - assert (0); - } - - vnc_import_bgp_del_route_mode_resolve_nve_one_bi (bgp, - afi, - bi, prd, &pb->upfx); - - if (ecom) - ecommunity_free (&ecom); - - rc = skiplist_next_value (sl, prefix, (void *) &pb, &cursor); - } + afi_t afi = family2afi(prefix->family); + struct skiplist *sl = NULL; + struct prefix_bag *pb; + void *cursor; + struct rfapi_cfg *hc = NULL; + int rc; + + { + char str_pfx[BUFSIZ]; + + prefix2str(prefix, str_pfx, BUFSIZ); + str_pfx[BUFSIZ - 1] = 0; + + vnc_zlog_debug_verbose("%s(bgp=%p, nve prefix=%s)", __func__, + bgp, str_pfx); + } + + if (afi != AFI_IP && afi != AFI_IP6) + return; + + if (!(hc = bgp->rfapi_cfg)) { + vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", + __func__); + return; + } + + /* check vnc redist flag for bgp direct routes */ + if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) { + vnc_zlog_debug_verbose( + "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping", + __func__, afi); + return; + } + + if (hc->redist_mode != VNC_REDIST_MODE_RESOLVE_NVE) { + vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping", + __func__); + return; + } + + if (bgp && bgp->rfapi) + sl = bgp->rfapi->resolve_nve_nexthop; + + if (!sl) { + vnc_zlog_debug_verbose("%s: no RHN entries, skipping", + __func__); + return; + } + + if (!is_host_prefix(prefix)) { + vnc_zlog_debug_verbose("%s: not host route, skip", __func__); + return; + } + + /* + * Find all entries with key == CE in the RHN list + */ + rc = skiplist_first_value(sl, prefix, (void *)&pb, &cursor); + while (!rc) { + + struct ecommunity *ecom; + struct prefix pfx_unicast_nexthop; + + memset(&pfx_unicast_nexthop, 0, + sizeof(struct prefix)); /* keep valgrind happy */ + + if (process_unicast_route(bgp, afi, &pb->upfx, pb->ubi, &ecom, + &pfx_unicast_nexthop)) { + + vnc_zlog_debug_verbose( + "%s: process_unicast_route error, skipping", + __func__); + continue; + } + + /* + * Sanity check + */ + if (vnc_prefix_cmp(&pfx_unicast_nexthop, prefix)) { + char str_unh[BUFSIZ]; + char str_nve_pfx[BUFSIZ]; + + prefix2str(&pfx_unicast_nexthop, str_unh, BUFSIZ); + str_unh[BUFSIZ - 1] = 0; + + prefix2str(prefix, str_nve_pfx, BUFSIZ); + str_nve_pfx[BUFSIZ - 1] = 0; + + vnc_zlog_debug_verbose( + "%s: FATAL: resolve_nve_nexthop list item bi nexthop %s != nve pfx %s", + __func__, str_unh, str_nve_pfx); + assert(0); + } + + vnc_import_bgp_del_route_mode_resolve_nve_one_bi( + bgp, afi, bi, prd, &pb->upfx); + + if (ecom) + ecommunity_free(&ecom); + + rc = skiplist_next_value(sl, prefix, (void *)&pb, &cursor); + } } @@ -1774,25 +1668,24 @@ vnc_import_bgp_del_vnc_host_route_mode_resolve_nve ( #define DEBUG_IS_USABLE_INTERIOR 1 -static int -is_usable_interior_route (struct bgp_info *bi_interior) +static int is_usable_interior_route(struct bgp_info *bi_interior) { - if (!VALID_INTERIOR_TYPE (bi_interior->type)) - { + if (!VALID_INTERIOR_TYPE(bi_interior->type)) { #if DEBUG_IS_USABLE_INTERIOR - vnc_zlog_debug_verbose ("%s: NO: type %d is not valid interior type", - __func__, bi_interior->type); + vnc_zlog_debug_verbose( + "%s: NO: type %d is not valid interior type", __func__, + bi_interior->type); #endif - return 0; - } - if (!CHECK_FLAG (bi_interior->flags, BGP_INFO_VALID)) - { + return 0; + } + if (!CHECK_FLAG(bi_interior->flags, BGP_INFO_VALID)) { #if DEBUG_IS_USABLE_INTERIOR - vnc_zlog_debug_verbose ("%s: NO: BGP_INFO_VALID not set", __func__); + vnc_zlog_debug_verbose("%s: NO: BGP_INFO_VALID not set", + __func__); #endif - return 0; - } - return 1; + return 0; + } + return 1; } /* @@ -1804,192 +1697,188 @@ is_usable_interior_route (struct bgp_info *bi_interior) * We filter here on the instance name to make sure we get only the * right routes. */ -static void -vnc_import_bgp_exterior_add_route_it ( - struct bgp *bgp, /* exterior instance, we hope */ - struct prefix *prefix,/* unicast prefix */ - struct bgp_info *info, /* unicast info */ - struct rfapi_import_table *it_only)/* NULL, or limit to this IT */ +static void vnc_import_bgp_exterior_add_route_it( + struct bgp *bgp, /* exterior instance, we hope */ + struct prefix *prefix, /* unicast prefix */ + struct bgp_info *info, /* unicast info */ + struct rfapi_import_table *it_only) /* NULL, or limit to this IT */ { - struct rfapi *h; - struct rfapi_cfg *hc; - struct prefix pfx_orig_nexthop; - struct rfapi_import_table *it; - struct bgp *bgp_default = bgp_get_default (); - afi_t afi = family2afi (prefix->family); - - if (!bgp_default) - return; - - h = bgp_default->rfapi; - hc = bgp_default->rfapi_cfg; - - vnc_zlog_debug_verbose ("%s: entry with it=%p", __func__, it_only); - - if (!h || !hc) - { - vnc_zlog_debug_verbose ("%s: rfapi or rfapi_cfg not instantiated, skipping", - __func__); - return; - } - if (!hc->redist_bgp_exterior_view) - { - vnc_zlog_debug_verbose ("%s: exterior view not set, skipping", __func__); - return; - } - if (bgp != hc->redist_bgp_exterior_view) - { - vnc_zlog_debug_verbose ("%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping", - __func__, bgp, hc->redist_bgp_exterior_view); - return; - } - - if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) - { - vnc_zlog_debug_verbose ("%s: redist of exterior routes not enabled, skipping", - __func__); - return; - } - - if (!info->attr) - { - vnc_zlog_debug_verbose ("%s: no info, skipping", __func__); - return; - } - - /* - * Extract nexthop from exterior route - * - * Incoming prefix is unicast. If v6, it is in multiprotocol area, - * but if v4 it is in attr->nexthop - */ - rfapiUnicastNexthop2Prefix (afi, info->attr, &pfx_orig_nexthop); - - for (it = h->imports; it; it = it->next) - { - struct route_table *table; - struct route_node *rn; - struct route_node *par; - struct bgp_info *bi_interior; - int have_usable_route; - - vnc_zlog_debug_verbose ("%s: doing it %p", __func__, it); - - if (it_only && (it_only != it)) - { - vnc_zlog_debug_verbose ("%s: doesn't match it_only %p", __func__, it_only); - continue; - } - - table = it->imported_vpn[afi]; - - for (rn = route_node_match (table, &pfx_orig_nexthop), - have_usable_route = 0; (!have_usable_route) && rn;) - { - - vnc_zlog_debug_verbose ("%s: it %p trying rn %p", __func__, it, rn); - - for (bi_interior = rn->info; bi_interior; - bi_interior = bi_interior->next) - { - struct prefix_rd *prd; - struct attr new_attr; - u_int32_t label = 0; - - if (!is_usable_interior_route (bi_interior)) - continue; - - vnc_zlog_debug_verbose ("%s: usable: bi_interior %p", __func__, - bi_interior); - - /* - * have a legitimate route to exterior's nexthop - * via NVE. - * - * Import unicast route to the import table - */ - have_usable_route = 1; - - if (bi_interior->extra) - { - prd = &bi_interior->extra->vnc.import.rd; - label = decode_label (&bi_interior->extra->label); - } - else - prd = NULL; - - /* use local_pref from unicast route */ - memset (&new_attr, 0, sizeof (struct attr)); - bgp_attr_dup (&new_attr, bi_interior->attr); - if (info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) - { - new_attr.local_pref = info->attr->local_pref; - new_attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF); - } - - rfapiBgpInfoFilteredImportVPN (it, FIF_ACTION_UPDATE, bi_interior->peer, NULL, /* rfd */ - prefix, - NULL, - afi, - prd, - &new_attr, - ZEBRA_ROUTE_BGP_DIRECT_EXT, - BGP_ROUTE_REDISTRIBUTE, &label); - - } - - if (have_usable_route) - { - /* - * Make monitor - * - * TBD factor this out into its own function - */ - struct prefix *pfx_mon = prefix_new (); - if (!RFAPI_MONITOR_EXTERIOR (rn)->source) - { - RFAPI_MONITOR_EXTERIOR (rn)->source = - skiplist_new (0, NULL, (void (*)(void *)) prefix_free); - route_lock_node (rn); /* for skiplist */ - } - route_lock_node (rn); /* for skiplist entry */ - prefix_copy (pfx_mon, prefix); - if (!skiplist_insert (RFAPI_MONITOR_EXTERIOR (rn)->source, - info, pfx_mon)) - { - - bgp_info_lock (info); - } - } - par = rn->parent; - if (par) - route_lock_node (par); - route_unlock_node (rn); - rn = par; - } - if (rn) - route_unlock_node (rn); - - if (!have_usable_route) - { - struct prefix *pfx_mon = prefix_new (); - prefix_copy (pfx_mon, prefix); - if (!skiplist_insert (it->monitor_exterior_orphans, info, pfx_mon)) - { - - bgp_info_lock (info); - } - } - } + struct rfapi *h; + struct rfapi_cfg *hc; + struct prefix pfx_orig_nexthop; + struct rfapi_import_table *it; + struct bgp *bgp_default = bgp_get_default(); + afi_t afi = family2afi(prefix->family); + + if (!bgp_default) + return; + + h = bgp_default->rfapi; + hc = bgp_default->rfapi_cfg; + + vnc_zlog_debug_verbose("%s: entry with it=%p", __func__, it_only); + + if (!h || !hc) { + vnc_zlog_debug_verbose( + "%s: rfapi or rfapi_cfg not instantiated, skipping", + __func__); + return; + } + if (!hc->redist_bgp_exterior_view) { + vnc_zlog_debug_verbose("%s: exterior view not set, skipping", + __func__); + return; + } + if (bgp != hc->redist_bgp_exterior_view) { + vnc_zlog_debug_verbose( + "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping", + __func__, bgp, hc->redist_bgp_exterior_view); + return; + } + + if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) { + vnc_zlog_debug_verbose( + "%s: redist of exterior routes not enabled, skipping", + __func__); + return; + } + + if (!info->attr) { + vnc_zlog_debug_verbose("%s: no info, skipping", __func__); + return; + } + + /* + * Extract nexthop from exterior route + * + * Incoming prefix is unicast. If v6, it is in multiprotocol area, + * but if v4 it is in attr->nexthop + */ + rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_orig_nexthop); + + for (it = h->imports; it; it = it->next) { + struct route_table *table; + struct route_node *rn; + struct route_node *par; + struct bgp_info *bi_interior; + int have_usable_route; + + vnc_zlog_debug_verbose("%s: doing it %p", __func__, it); + + if (it_only && (it_only != it)) { + vnc_zlog_debug_verbose("%s: doesn't match it_only %p", + __func__, it_only); + continue; + } + + table = it->imported_vpn[afi]; + + for (rn = route_node_match(table, &pfx_orig_nexthop), + have_usable_route = 0; + (!have_usable_route) && rn;) { + + vnc_zlog_debug_verbose("%s: it %p trying rn %p", + __func__, it, rn); + + for (bi_interior = rn->info; bi_interior; + bi_interior = bi_interior->next) { + struct prefix_rd *prd; + struct attr new_attr; + u_int32_t label = 0; + + if (!is_usable_interior_route(bi_interior)) + continue; + + vnc_zlog_debug_verbose( + "%s: usable: bi_interior %p", __func__, + bi_interior); + + /* + * have a legitimate route to exterior's nexthop + * via NVE. + * + * Import unicast route to the import table + */ + have_usable_route = 1; + + if (bi_interior->extra) { + prd = &bi_interior->extra->vnc.import + .rd; + label = decode_label( + &bi_interior->extra->label); + } else + prd = NULL; + + /* use local_pref from unicast route */ + memset(&new_attr, 0, sizeof(struct attr)); + bgp_attr_dup(&new_attr, bi_interior->attr); + if (info->attr->flag + & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) { + new_attr.local_pref = + info->attr->local_pref; + new_attr.flag |= ATTR_FLAG_BIT( + BGP_ATTR_LOCAL_PREF); + } + + rfapiBgpInfoFilteredImportVPN( + it, FIF_ACTION_UPDATE, + bi_interior->peer, NULL, /* rfd */ + prefix, NULL, afi, prd, &new_attr, + ZEBRA_ROUTE_BGP_DIRECT_EXT, + BGP_ROUTE_REDISTRIBUTE, &label); + } + + if (have_usable_route) { + /* + * Make monitor + * + * TBD factor this out into its own function + */ + struct prefix *pfx_mon = prefix_new(); + if (!RFAPI_MONITOR_EXTERIOR(rn)->source) { + RFAPI_MONITOR_EXTERIOR(rn)->source = + skiplist_new( + 0, NULL, + (void (*)(void *)) + prefix_free); + route_lock_node(rn); /* for skiplist */ + } + route_lock_node(rn); /* for skiplist entry */ + prefix_copy(pfx_mon, prefix); + if (!skiplist_insert( + RFAPI_MONITOR_EXTERIOR(rn)->source, + info, pfx_mon)) { + + bgp_info_lock(info); + } + } + par = rn->parent; + if (par) + route_lock_node(par); + route_unlock_node(rn); + rn = par; + } + if (rn) + route_unlock_node(rn); + + if (!have_usable_route) { + struct prefix *pfx_mon = prefix_new(); + prefix_copy(pfx_mon, prefix); + if (!skiplist_insert(it->monitor_exterior_orphans, info, + pfx_mon)) { + + bgp_info_lock(info); + } + } + } } -void -vnc_import_bgp_exterior_add_route ( - struct bgp *bgp, /* exterior instance, we hope */ - struct prefix *prefix,/* unicast prefix */ - struct bgp_info *info) /* unicast info */ +void vnc_import_bgp_exterior_add_route( + struct bgp *bgp, /* exterior instance, we hope */ + struct prefix *prefix, /* unicast prefix */ + struct bgp_info *info) /* unicast info */ { - vnc_import_bgp_exterior_add_route_it (bgp, prefix, info, NULL); + vnc_import_bgp_exterior_add_route_it(bgp, prefix, info, NULL); } /* @@ -2001,155 +1890,163 @@ vnc_import_bgp_exterior_add_route ( * We filter here on the instance name to make sure we get only the * right routes. */ -void -vnc_import_bgp_exterior_del_route ( - struct bgp *bgp, - struct prefix *prefix, /* unicast prefix */ - struct bgp_info *info) /* unicast info */ +void vnc_import_bgp_exterior_del_route( + struct bgp *bgp, struct prefix *prefix, /* unicast prefix */ + struct bgp_info *info) /* unicast info */ { - struct rfapi *h; - struct rfapi_cfg *hc; - struct rfapi_import_table *it; - struct prefix pfx_orig_nexthop; - afi_t afi = family2afi (prefix->family); - struct bgp *bgp_default = bgp_get_default (); - - if (!bgp_default) - return; - - memset (&pfx_orig_nexthop, 0, sizeof (struct prefix)); /* keep valgrind happy */ - - h = bgp_default->rfapi; - hc = bgp_default->rfapi_cfg; - - if (!h || !hc) - { - vnc_zlog_debug_verbose ("%s: rfapi or rfapi_cfg not instantiated, skipping", - __func__); - return; - } - if (!hc->redist_bgp_exterior_view) - { - vnc_zlog_debug_verbose ("%s: exterior view not set, skipping", __func__); - return; - } - if (bgp != hc->redist_bgp_exterior_view) - { - vnc_zlog_debug_verbose ("%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping", - __func__, bgp, hc->redist_bgp_exterior_view); - return; - } - if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) - { - vnc_zlog_debug_verbose ("%s: redist of exterior routes no enabled, skipping", - __func__); - return; - } - - if (!info->attr) - { - vnc_zlog_debug_verbose ("%s: no info, skipping", __func__); - return; - } - - /* - * Extract nexthop from exterior route - * - * Incoming prefix is unicast. If v6, it is in multiprotocol area, - * but if v4 it is in attr->nexthop - */ - rfapiUnicastNexthop2Prefix (afi, info->attr, &pfx_orig_nexthop); - - for (it = h->imports; it; it = it->next) - { - struct route_table *table; - struct route_node *rn; - struct route_node *par; - struct bgp_info *bi_interior; - int have_usable_route; - - table = it->imported_vpn[afi]; - - for (rn = route_node_match (table, &pfx_orig_nexthop), - have_usable_route = 0; (!have_usable_route) && rn;) - { - - for (bi_interior = rn->info; bi_interior; - bi_interior = bi_interior->next) - { - struct prefix_rd *prd; - u_int32_t label = 0; - - if (!is_usable_interior_route (bi_interior)) - continue; - - /* - * have a legitimate route to exterior's nexthop - * via NVE. - * - * Import unicast route to the import table - */ - have_usable_route = 1; - - if (bi_interior->extra) - { - prd = &bi_interior->extra->vnc.import.rd; - label = decode_label (&bi_interior->extra->label); - } - else - prd = NULL; - - rfapiBgpInfoFilteredImportVPN (it, FIF_ACTION_KILL, bi_interior->peer, NULL, /* rfd */ - prefix, - NULL, - afi, - prd, - bi_interior->attr, - ZEBRA_ROUTE_BGP_DIRECT_EXT, - BGP_ROUTE_REDISTRIBUTE, &label); - - /* - * Delete monitor - * - * TBD factor this out into its own function - */ - { - if (RFAPI_MONITOR_EXTERIOR (rn)->source) - { - if (!skiplist_delete (RFAPI_MONITOR_EXTERIOR (rn)->source, - info, NULL)) - { - - bgp_info_unlock (info); - route_unlock_node (rn); /* sl entry */ - } - if (skiplist_empty (RFAPI_MONITOR_EXTERIOR (rn)->source)) - { - skiplist_free (RFAPI_MONITOR_EXTERIOR (rn)->source); - RFAPI_MONITOR_EXTERIOR (rn)->source = NULL; - route_unlock_node (rn); /* skiplist itself */ - } - } - } - } - par = rn->parent; - if (par) - route_lock_node (par); - route_unlock_node (rn); - rn = par; - } - if (rn) - route_unlock_node (rn); - - if (!have_usable_route) - { - if (!skiplist_delete (it->monitor_exterior_orphans, info, NULL)) - { - - bgp_info_unlock (info); - } - } - } + struct rfapi *h; + struct rfapi_cfg *hc; + struct rfapi_import_table *it; + struct prefix pfx_orig_nexthop; + afi_t afi = family2afi(prefix->family); + struct bgp *bgp_default = bgp_get_default(); + + if (!bgp_default) + return; + + memset(&pfx_orig_nexthop, 0, + sizeof(struct prefix)); /* keep valgrind happy */ + + h = bgp_default->rfapi; + hc = bgp_default->rfapi_cfg; + + if (!h || !hc) { + vnc_zlog_debug_verbose( + "%s: rfapi or rfapi_cfg not instantiated, skipping", + __func__); + return; + } + if (!hc->redist_bgp_exterior_view) { + vnc_zlog_debug_verbose("%s: exterior view not set, skipping", + __func__); + return; + } + if (bgp != hc->redist_bgp_exterior_view) { + vnc_zlog_debug_verbose( + "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping", + __func__, bgp, hc->redist_bgp_exterior_view); + return; + } + if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) { + vnc_zlog_debug_verbose( + "%s: redist of exterior routes no enabled, skipping", + __func__); + return; + } + + if (!info->attr) { + vnc_zlog_debug_verbose("%s: no info, skipping", __func__); + return; + } + + /* + * Extract nexthop from exterior route + * + * Incoming prefix is unicast. If v6, it is in multiprotocol area, + * but if v4 it is in attr->nexthop + */ + rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_orig_nexthop); + + for (it = h->imports; it; it = it->next) { + struct route_table *table; + struct route_node *rn; + struct route_node *par; + struct bgp_info *bi_interior; + int have_usable_route; + + table = it->imported_vpn[afi]; + + for (rn = route_node_match(table, &pfx_orig_nexthop), + have_usable_route = 0; + (!have_usable_route) && rn;) { + + for (bi_interior = rn->info; bi_interior; + bi_interior = bi_interior->next) { + struct prefix_rd *prd; + u_int32_t label = 0; + + if (!is_usable_interior_route(bi_interior)) + continue; + + /* + * have a legitimate route to exterior's nexthop + * via NVE. + * + * Import unicast route to the import table + */ + have_usable_route = 1; + + if (bi_interior->extra) { + prd = &bi_interior->extra->vnc.import + .rd; + label = decode_label( + &bi_interior->extra->label); + } else + prd = NULL; + + rfapiBgpInfoFilteredImportVPN( + it, FIF_ACTION_KILL, bi_interior->peer, + NULL, /* rfd */ + prefix, NULL, afi, prd, + bi_interior->attr, + ZEBRA_ROUTE_BGP_DIRECT_EXT, + BGP_ROUTE_REDISTRIBUTE, &label); + + /* + * Delete monitor + * + * TBD factor this out into its own function + */ + { + if (RFAPI_MONITOR_EXTERIOR(rn) + ->source) { + if (!skiplist_delete( + RFAPI_MONITOR_EXTERIOR( + rn) + ->source, + info, NULL)) { + + bgp_info_unlock(info); + route_unlock_node( + rn); /* sl entry + */ + } + if (skiplist_empty( + RFAPI_MONITOR_EXTERIOR( + rn) + ->source)) { + skiplist_free( + RFAPI_MONITOR_EXTERIOR( + rn) + ->source); + RFAPI_MONITOR_EXTERIOR( + rn) + ->source = NULL; + route_unlock_node( + rn); /* skiplist + itself + */ + } + } + } + } + par = rn->parent; + if (par) + route_lock_node(par); + route_unlock_node(rn); + rn = par; + } + if (rn) + route_unlock_node(rn); + + if (!have_usable_route) { + if (!skiplist_delete(it->monitor_exterior_orphans, info, + NULL)) { + + bgp_info_unlock(info); + } + } + } } /* @@ -2159,387 +2056,378 @@ vnc_import_bgp_exterior_del_route ( * NB should also be called whenever an existing vpn interior route * becomes valid (e.g., valid_interior_count is inremented) */ -void -vnc_import_bgp_exterior_add_route_interior ( - struct bgp *bgp, - struct rfapi_import_table *it, - struct route_node *rn_interior, /* VPN IT node */ - struct bgp_info *bi_interior) /* VPN IT route */ +void vnc_import_bgp_exterior_add_route_interior( + struct bgp *bgp, struct rfapi_import_table *it, + struct route_node *rn_interior, /* VPN IT node */ + struct bgp_info *bi_interior) /* VPN IT route */ { - afi_t afi = family2afi (rn_interior->p.family); - struct route_node *par; - struct bgp_info *bi_exterior; - struct prefix *pfx_exterior; /* exterior pfx */ - void *cursor; - int rc; - struct list *list_adopted; - - vnc_zlog_debug_verbose ("%s: entry", __func__); - - if (!is_usable_interior_route (bi_interior)) - { - vnc_zlog_debug_verbose ("%s: not usable interior route, skipping", __func__); - return; - } - - if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) - { - vnc_zlog_debug_verbose ("%s: redist of exterior routes no enabled, skipping", - __func__); - return; - } - - if (it == bgp->rfapi->it_ce) - { - vnc_zlog_debug_verbose ("%s: import table is it_ce, skipping", __func__); - return; - } - - /*debugging */ - { - char str_pfx[BUFSIZ]; - - prefix2str (&rn_interior->p, str_pfx, BUFSIZ); - str_pfx[BUFSIZ - 1] = 0; - - vnc_zlog_debug_verbose ("%s: interior prefix=%s, bi type=%d", - __func__, str_pfx, bi_interior->type); - } - - if (RFAPI_HAS_MONITOR_EXTERIOR (rn_interior)) - { - - int count = 0; /* debugging */ - - vnc_zlog_debug_verbose ("%s: has exterior monitor; ext src: %p", __func__, - RFAPI_MONITOR_EXTERIOR (rn_interior)->source); - - /* - * There is a monitor here already. Therefore, we do not need - * to do any pulldown. Just construct exterior routes based - * on the new interior route. - */ - cursor = NULL; - for (rc = skiplist_next (RFAPI_MONITOR_EXTERIOR (rn_interior)->source, - (void **) &bi_exterior, - (void **) &pfx_exterior, &cursor); !rc; - rc = - skiplist_next (RFAPI_MONITOR_EXTERIOR (rn_interior)->source, - (void **) &bi_exterior, (void **) &pfx_exterior, - &cursor)) - { - - struct prefix_rd *prd; - struct attr new_attr; - u_int32_t label = 0; - - - ++count; /* debugging */ - - assert (bi_exterior); - assert (pfx_exterior); - - if (bi_interior->extra) - { - prd = &bi_interior->extra->vnc.import.rd; - label = decode_label (&bi_interior->extra->label); - } - else - prd = NULL; - - /* use local_pref from unicast route */ - memset (&new_attr, 0, sizeof (struct attr)); - bgp_attr_dup (&new_attr, bi_interior->attr); - if (bi_exterior && - (bi_exterior->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))) - { - new_attr.local_pref = bi_exterior->attr->local_pref; - new_attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF); - } - - rfapiBgpInfoFilteredImportVPN (it, FIF_ACTION_UPDATE, bi_interior->peer, NULL, /* rfd */ - pfx_exterior, - NULL, - afi, - prd, - &new_attr, - ZEBRA_ROUTE_BGP_DIRECT_EXT, - BGP_ROUTE_REDISTRIBUTE, &label); - - } - vnc_zlog_debug_verbose - ("%s: finished constructing exteriors based on existing monitors", - __func__); - return; - } - - vnc_zlog_debug_verbose ("%s: no exterior monitor", __func__); - - /* - * No monitor at this node. Is this the first valid interior - * route at this node? - */ - if (RFAPI_MONITOR_EXTERIOR (rn_interior)->valid_interior_count > 1) - { - vnc_zlog_debug_verbose - ("%s: new interior route not first valid one, skipping pulldown", - __func__); - return; - } - - /* - * Look up the tree for possible pulldown candidates. - * Find nearest parent with an exterior route monitor - */ - for (par = rn_interior->parent; par; par = par->parent) - { - if (RFAPI_HAS_MONITOR_EXTERIOR (par)) - break; - } - - if (par) - { - - vnc_zlog_debug_verbose ("%s: checking parent %p for possible pulldowns", - __func__, par); - - /* check monitors at par for possible pulldown */ - cursor = NULL; - for (rc = skiplist_next (RFAPI_MONITOR_EXTERIOR (par)->source, - (void **) &bi_exterior, - (void **) &pfx_exterior, &cursor); !rc; - rc = - skiplist_next (RFAPI_MONITOR_EXTERIOR (par)->source, - (void **) &bi_exterior, (void **) &pfx_exterior, - &cursor)) - { - - struct prefix pfx_nexthop; - - memset (&pfx_nexthop, 0, sizeof (struct prefix)); /* keep valgrind happy */ - - /* check original nexthop for prefix match */ - rfapiUnicastNexthop2Prefix (afi, bi_exterior->attr, &pfx_nexthop); - - if (prefix_match (&rn_interior->p, &pfx_nexthop)) - { - - struct bgp_info *bi; - struct prefix_rd *prd; - struct attr new_attr; - u_int32_t label = 0; - - /* do pull-down */ - - /* - * add monitor to longer prefix - */ - struct prefix *pfx_mon = prefix_new (); - prefix_copy (pfx_mon, pfx_exterior); - if (!RFAPI_MONITOR_EXTERIOR (rn_interior)->source) - { - RFAPI_MONITOR_EXTERIOR (rn_interior)->source = - skiplist_new (0, NULL, (void (*)(void *)) prefix_free); - route_lock_node (rn_interior); - } - skiplist_insert (RFAPI_MONITOR_EXTERIOR (rn_interior)->source, - bi_exterior, pfx_mon); - route_lock_node (rn_interior); - - /* - * Delete constructed exterior routes based on - * parent routes. - */ - for (bi = par->info; bi; bi = bi->next) - { - - if (bi->extra) - { - prd = &bi->extra->vnc.import.rd; - label = decode_label (&bi->extra->label); - } - else - prd = NULL; - - rfapiBgpInfoFilteredImportVPN (it, FIF_ACTION_KILL, bi->peer, NULL, /* rfd */ - pfx_exterior, - NULL, - afi, - prd, - bi->attr, - ZEBRA_ROUTE_BGP_DIRECT_EXT, - BGP_ROUTE_REDISTRIBUTE, - &label); - } - - - /* - * Add constructed exterior routes based on - * the new interior route at longer prefix. - */ - if (bi_interior->extra) - { - prd = &bi_interior->extra->vnc.import.rd; - label = decode_label (&bi_interior->extra->label); - } - else - prd = NULL; - - /* use local_pref from unicast route */ - memset (&new_attr, 0, sizeof (struct attr)); - bgp_attr_dup (&new_attr, bi_interior->attr); - if (bi_exterior && - (bi_exterior->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))) - { - new_attr.local_pref = bi_exterior->attr->local_pref; - new_attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF); - } - - rfapiBgpInfoFilteredImportVPN (it, FIF_ACTION_UPDATE, bi_interior->peer, NULL, /* rfd */ - pfx_exterior, - NULL, - afi, - prd, - &new_attr, - ZEBRA_ROUTE_BGP_DIRECT_EXT, - BGP_ROUTE_REDISTRIBUTE, &label); - - } - } - - /* - * The only monitors at rn_interior are the ones we added just - * above, so we can use the rn_interior list to identify which - * monitors to delete from the parent. - */ - cursor = NULL; - for (rc = skiplist_next (RFAPI_MONITOR_EXTERIOR (rn_interior)->source, - (void **) &bi_exterior, NULL, &cursor); - !rc; - rc = skiplist_next (RFAPI_MONITOR_EXTERIOR (rn_interior)->source, - (void **) &bi_exterior, NULL, &cursor)) - { - - - skiplist_delete (RFAPI_MONITOR_EXTERIOR (par)->source, - bi_exterior, NULL); - route_unlock_node (par); /* sl entry */ - } - if (skiplist_empty (RFAPI_MONITOR_EXTERIOR (par)->source)) - { - skiplist_free (RFAPI_MONITOR_EXTERIOR (par)->source); - RFAPI_MONITOR_EXTERIOR (par)->source = NULL; - route_unlock_node (par); /* sl itself */ - } - } - - vnc_zlog_debug_verbose ("%s: checking orphans", __func__); - - /* - * See if any orphans can be pulled down to the current node - */ - cursor = NULL; - list_adopted = NULL; - for (rc = skiplist_next (it->monitor_exterior_orphans, - (void **) &bi_exterior, (void **) &pfx_exterior, - &cursor); !rc; - rc = - skiplist_next (it->monitor_exterior_orphans, (void **) &bi_exterior, - (void **) &pfx_exterior, &cursor)) - { - - struct prefix pfx_nexthop; - char buf[BUFSIZ]; - afi_t afi_exterior = family2afi (pfx_exterior->family); - - prefix2str (pfx_exterior, buf, sizeof (buf)); - buf[sizeof (buf) - 1] = 0; - vnc_zlog_debug_verbose ("%s: checking exterior orphan at prefix %s", __func__, buf); - - if (afi_exterior != afi) - { - vnc_zlog_debug_verbose ("%s: exterior orphan afi %d != interior afi %d, skip", - __func__, afi_exterior, afi); - continue; - } - - /* check original nexthop for prefix match */ - rfapiUnicastNexthop2Prefix (afi, bi_exterior->attr, &pfx_nexthop); - - if (prefix_match (&rn_interior->p, &pfx_nexthop)) - { - - struct prefix_rd *prd; - struct attr new_attr; - u_int32_t label = 0; - - /* do pull-down */ - - /* - * add monitor to longer prefix - */ - - struct prefix *pfx_mon = prefix_new (); - prefix_copy (pfx_mon, pfx_exterior); - if (!RFAPI_MONITOR_EXTERIOR (rn_interior)->source) - { - RFAPI_MONITOR_EXTERIOR (rn_interior)->source = - skiplist_new (0, NULL, (void (*)(void *)) prefix_free); - route_lock_node (rn_interior); /* sl */ - } - skiplist_insert (RFAPI_MONITOR_EXTERIOR (rn_interior)->source, - bi_exterior, pfx_mon); - route_lock_node (rn_interior); /* sl entry */ - if (!list_adopted) - { - list_adopted = list_new (); - } - listnode_add (list_adopted, bi_exterior); - - /* - * Add constructed exterior routes based on the - * new interior route at the longer prefix. - */ - if (bi_interior->extra) - { - prd = &bi_interior->extra->vnc.import.rd; - label = decode_label (&bi_interior->extra->label); - } - else - prd = NULL; - - /* use local_pref from unicast route */ - memset (&new_attr, 0, sizeof (struct attr)); - bgp_attr_dup (&new_attr, bi_interior->attr); - if (bi_exterior && - (bi_exterior->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))) - { - new_attr.local_pref = bi_exterior->attr->local_pref; - new_attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF); - } - - rfapiBgpInfoFilteredImportVPN (it, FIF_ACTION_UPDATE, bi_interior->peer, NULL, /* rfd */ - pfx_exterior, - NULL, - afi, - prd, - &new_attr, - ZEBRA_ROUTE_BGP_DIRECT_EXT, - BGP_ROUTE_REDISTRIBUTE, &label); - - } - } - if (list_adopted) - { - struct listnode *node; - struct route_node *bi_exterior; - - for (ALL_LIST_ELEMENTS_RO (list_adopted, node, bi_exterior)) - { - skiplist_delete (it->monitor_exterior_orphans, bi_exterior, NULL); - } - list_delete (list_adopted); - } + afi_t afi = family2afi(rn_interior->p.family); + struct route_node *par; + struct bgp_info *bi_exterior; + struct prefix *pfx_exterior; /* exterior pfx */ + void *cursor; + int rc; + struct list *list_adopted; + + vnc_zlog_debug_verbose("%s: entry", __func__); + + if (!is_usable_interior_route(bi_interior)) { + vnc_zlog_debug_verbose( + "%s: not usable interior route, skipping", __func__); + return; + } + + if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) { + vnc_zlog_debug_verbose( + "%s: redist of exterior routes no enabled, skipping", + __func__); + return; + } + + if (it == bgp->rfapi->it_ce) { + vnc_zlog_debug_verbose("%s: import table is it_ce, skipping", + __func__); + return; + } + + /*debugging */ + { + char str_pfx[BUFSIZ]; + + prefix2str(&rn_interior->p, str_pfx, BUFSIZ); + str_pfx[BUFSIZ - 1] = 0; + + vnc_zlog_debug_verbose("%s: interior prefix=%s, bi type=%d", + __func__, str_pfx, bi_interior->type); + } + + if (RFAPI_HAS_MONITOR_EXTERIOR(rn_interior)) { + + int count = 0; /* debugging */ + + vnc_zlog_debug_verbose( + "%s: has exterior monitor; ext src: %p", __func__, + RFAPI_MONITOR_EXTERIOR(rn_interior)->source); + + /* + * There is a monitor here already. Therefore, we do not need + * to do any pulldown. Just construct exterior routes based + * on the new interior route. + */ + cursor = NULL; + for (rc = skiplist_next( + RFAPI_MONITOR_EXTERIOR(rn_interior)->source, + (void **)&bi_exterior, (void **)&pfx_exterior, + &cursor); + !rc; rc = skiplist_next( + RFAPI_MONITOR_EXTERIOR(rn_interior)->source, + (void **)&bi_exterior, (void **)&pfx_exterior, + &cursor)) { + + struct prefix_rd *prd; + struct attr new_attr; + u_int32_t label = 0; + + + ++count; /* debugging */ + + assert(bi_exterior); + assert(pfx_exterior); + + if (bi_interior->extra) { + prd = &bi_interior->extra->vnc.import.rd; + label = decode_label( + &bi_interior->extra->label); + } else + prd = NULL; + + /* use local_pref from unicast route */ + memset(&new_attr, 0, sizeof(struct attr)); + bgp_attr_dup(&new_attr, bi_interior->attr); + if (bi_exterior + && (bi_exterior->attr->flag + & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) { + new_attr.local_pref = + bi_exterior->attr->local_pref; + new_attr.flag |= + ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF); + } + + rfapiBgpInfoFilteredImportVPN( + it, FIF_ACTION_UPDATE, bi_interior->peer, + NULL, /* rfd */ + pfx_exterior, NULL, afi, prd, &new_attr, + ZEBRA_ROUTE_BGP_DIRECT_EXT, + BGP_ROUTE_REDISTRIBUTE, &label); + } + vnc_zlog_debug_verbose( + "%s: finished constructing exteriors based on existing monitors", + __func__); + return; + } + + vnc_zlog_debug_verbose("%s: no exterior monitor", __func__); + + /* + * No monitor at this node. Is this the first valid interior + * route at this node? + */ + if (RFAPI_MONITOR_EXTERIOR(rn_interior)->valid_interior_count > 1) { + vnc_zlog_debug_verbose( + "%s: new interior route not first valid one, skipping pulldown", + __func__); + return; + } + + /* + * Look up the tree for possible pulldown candidates. + * Find nearest parent with an exterior route monitor + */ + for (par = rn_interior->parent; par; par = par->parent) { + if (RFAPI_HAS_MONITOR_EXTERIOR(par)) + break; + } + + if (par) { + + vnc_zlog_debug_verbose( + "%s: checking parent %p for possible pulldowns", + __func__, par); + + /* check monitors at par for possible pulldown */ + cursor = NULL; + for (rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(par)->source, + (void **)&bi_exterior, + (void **)&pfx_exterior, &cursor); + !rc; + rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(par)->source, + (void **)&bi_exterior, + (void **)&pfx_exterior, &cursor)) { + + struct prefix pfx_nexthop; + + memset(&pfx_nexthop, 0, + sizeof(struct prefix)); /* keep valgrind happy */ + + /* check original nexthop for prefix match */ + rfapiUnicastNexthop2Prefix(afi, bi_exterior->attr, + &pfx_nexthop); + + if (prefix_match(&rn_interior->p, &pfx_nexthop)) { + + struct bgp_info *bi; + struct prefix_rd *prd; + struct attr new_attr; + u_int32_t label = 0; + + /* do pull-down */ + + /* + * add monitor to longer prefix + */ + struct prefix *pfx_mon = prefix_new(); + prefix_copy(pfx_mon, pfx_exterior); + if (!RFAPI_MONITOR_EXTERIOR(rn_interior) + ->source) { + RFAPI_MONITOR_EXTERIOR(rn_interior) + ->source = skiplist_new( + 0, NULL, + (void (*)(void *))prefix_free); + route_lock_node(rn_interior); + } + skiplist_insert( + RFAPI_MONITOR_EXTERIOR(rn_interior) + ->source, + bi_exterior, pfx_mon); + route_lock_node(rn_interior); + + /* + * Delete constructed exterior routes based on + * parent routes. + */ + for (bi = par->info; bi; bi = bi->next) { + + if (bi->extra) { + prd = &bi->extra->vnc.import.rd; + label = decode_label( + &bi->extra->label); + } else + prd = NULL; + + rfapiBgpInfoFilteredImportVPN( + it, FIF_ACTION_KILL, bi->peer, + NULL, /* rfd */ + pfx_exterior, NULL, afi, prd, + bi->attr, + ZEBRA_ROUTE_BGP_DIRECT_EXT, + BGP_ROUTE_REDISTRIBUTE, &label); + } + + + /* + * Add constructed exterior routes based on + * the new interior route at longer prefix. + */ + if (bi_interior->extra) { + prd = &bi_interior->extra->vnc.import + .rd; + label = decode_label( + &bi_interior->extra->label); + } else + prd = NULL; + + /* use local_pref from unicast route */ + memset(&new_attr, 0, sizeof(struct attr)); + bgp_attr_dup(&new_attr, bi_interior->attr); + if (bi_exterior + && (bi_exterior->attr->flag + & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) { + new_attr.local_pref = + bi_exterior->attr->local_pref; + new_attr.flag |= ATTR_FLAG_BIT( + BGP_ATTR_LOCAL_PREF); + } + + rfapiBgpInfoFilteredImportVPN( + it, FIF_ACTION_UPDATE, + bi_interior->peer, NULL, /* rfd */ + pfx_exterior, NULL, afi, prd, &new_attr, + ZEBRA_ROUTE_BGP_DIRECT_EXT, + BGP_ROUTE_REDISTRIBUTE, &label); + } + } + + /* + * The only monitors at rn_interior are the ones we added just + * above, so we can use the rn_interior list to identify which + * monitors to delete from the parent. + */ + cursor = NULL; + for (rc = skiplist_next( + RFAPI_MONITOR_EXTERIOR(rn_interior)->source, + (void **)&bi_exterior, NULL, &cursor); + !rc; rc = skiplist_next( + RFAPI_MONITOR_EXTERIOR(rn_interior)->source, + (void **)&bi_exterior, NULL, &cursor)) { + + + skiplist_delete(RFAPI_MONITOR_EXTERIOR(par)->source, + bi_exterior, NULL); + route_unlock_node(par); /* sl entry */ + } + if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(par)->source)) { + skiplist_free(RFAPI_MONITOR_EXTERIOR(par)->source); + RFAPI_MONITOR_EXTERIOR(par)->source = NULL; + route_unlock_node(par); /* sl itself */ + } + } + + vnc_zlog_debug_verbose("%s: checking orphans", __func__); + + /* + * See if any orphans can be pulled down to the current node + */ + cursor = NULL; + list_adopted = NULL; + for (rc = skiplist_next(it->monitor_exterior_orphans, + (void **)&bi_exterior, (void **)&pfx_exterior, + &cursor); + !rc; rc = skiplist_next(it->monitor_exterior_orphans, + (void **)&bi_exterior, + (void **)&pfx_exterior, &cursor)) { + + struct prefix pfx_nexthop; + char buf[BUFSIZ]; + afi_t afi_exterior = family2afi(pfx_exterior->family); + + prefix2str(pfx_exterior, buf, sizeof(buf)); + buf[sizeof(buf) - 1] = 0; + vnc_zlog_debug_verbose( + "%s: checking exterior orphan at prefix %s", __func__, + buf); + + if (afi_exterior != afi) { + vnc_zlog_debug_verbose( + "%s: exterior orphan afi %d != interior afi %d, skip", + __func__, afi_exterior, afi); + continue; + } + + /* check original nexthop for prefix match */ + rfapiUnicastNexthop2Prefix(afi, bi_exterior->attr, + &pfx_nexthop); + + if (prefix_match(&rn_interior->p, &pfx_nexthop)) { + + struct prefix_rd *prd; + struct attr new_attr; + u_int32_t label = 0; + + /* do pull-down */ + + /* + * add monitor to longer prefix + */ + + struct prefix *pfx_mon = prefix_new(); + prefix_copy(pfx_mon, pfx_exterior); + if (!RFAPI_MONITOR_EXTERIOR(rn_interior)->source) { + RFAPI_MONITOR_EXTERIOR(rn_interior)->source = + skiplist_new( + 0, NULL, + (void (*)(void *))prefix_free); + route_lock_node(rn_interior); /* sl */ + } + skiplist_insert( + RFAPI_MONITOR_EXTERIOR(rn_interior)->source, + bi_exterior, pfx_mon); + route_lock_node(rn_interior); /* sl entry */ + if (!list_adopted) { + list_adopted = list_new(); + } + listnode_add(list_adopted, bi_exterior); + + /* + * Add constructed exterior routes based on the + * new interior route at the longer prefix. + */ + if (bi_interior->extra) { + prd = &bi_interior->extra->vnc.import.rd; + label = decode_label( + &bi_interior->extra->label); + } else + prd = NULL; + + /* use local_pref from unicast route */ + memset(&new_attr, 0, sizeof(struct attr)); + bgp_attr_dup(&new_attr, bi_interior->attr); + if (bi_exterior + && (bi_exterior->attr->flag + & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) { + new_attr.local_pref = + bi_exterior->attr->local_pref; + new_attr.flag |= + ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF); + } + + rfapiBgpInfoFilteredImportVPN( + it, FIF_ACTION_UPDATE, bi_interior->peer, + NULL, /* rfd */ + pfx_exterior, NULL, afi, prd, &new_attr, + ZEBRA_ROUTE_BGP_DIRECT_EXT, + BGP_ROUTE_REDISTRIBUTE, &label); + } + } + if (list_adopted) { + struct listnode *node; + struct route_node *bi_exterior; + + for (ALL_LIST_ELEMENTS_RO(list_adopted, node, bi_exterior)) { + skiplist_delete(it->monitor_exterior_orphans, + bi_exterior, NULL); + } + list_delete(list_adopted); + } } /* @@ -2552,348 +2440,327 @@ vnc_import_bgp_exterior_add_route_interior ( * NB should also be called whenever an existing vpn interior route * becomes invalid (e.g., valid_interior_count is decremented) */ -void -vnc_import_bgp_exterior_del_route_interior ( - struct bgp *bgp, - struct rfapi_import_table *it, - struct route_node *rn_interior, /* VPN IT node */ - struct bgp_info *bi_interior) /* VPN IT route */ +void vnc_import_bgp_exterior_del_route_interior( + struct bgp *bgp, struct rfapi_import_table *it, + struct route_node *rn_interior, /* VPN IT node */ + struct bgp_info *bi_interior) /* VPN IT route */ { - afi_t afi = family2afi (rn_interior->p.family); - struct route_node *par; - struct bgp_info *bi_exterior; - struct prefix *pfx_exterior; /* exterior pfx */ - void *cursor; - int rc; - - if (!VALID_INTERIOR_TYPE (bi_interior->type)) - { - vnc_zlog_debug_verbose ("%s: type %d not valid interior type, skipping", - __func__, bi_interior->type); - return; - } - - if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) - { - vnc_zlog_debug_verbose ("%s: redist of exterior routes no enabled, skipping", - __func__); - return; - } - - if (it == bgp->rfapi->it_ce) - { - vnc_zlog_debug_verbose ("%s: it is it_ce, skipping", __func__); - return; - } - - /* If no exterior routes depend on this prefix, nothing to do */ - if (!RFAPI_HAS_MONITOR_EXTERIOR (rn_interior)) - { - vnc_zlog_debug_verbose ("%s: no exterior monitor, skipping", __func__); - return; - } - - /*debugging */ - { - char str_pfx[BUFSIZ]; - - prefix2str (&rn_interior->p, str_pfx, BUFSIZ); - str_pfx[BUFSIZ - 1] = 0; - - vnc_zlog_debug_verbose ("%s: interior prefix=%s, bi type=%d", - __func__, str_pfx, bi_interior->type); - } - - /* - * Remove constructed routes based on the deleted interior route - */ - cursor = NULL; - for (rc = skiplist_next (RFAPI_MONITOR_EXTERIOR (rn_interior)->source, - (void **) &bi_exterior, (void **) &pfx_exterior, - &cursor); !rc; - rc = - skiplist_next (RFAPI_MONITOR_EXTERIOR (rn_interior)->source, - (void **) &bi_exterior, (void **) &pfx_exterior, - &cursor)) - { - - struct prefix_rd *prd; - u_int32_t label = 0; - - if (bi_interior->extra) - { - prd = &bi_interior->extra->vnc.import.rd; - label = decode_label (&bi_interior->extra->label); - } - else - prd = NULL; - - rfapiBgpInfoFilteredImportVPN (it, FIF_ACTION_KILL, bi_interior->peer, NULL, /* rfd */ - pfx_exterior, - NULL, - afi, - prd, - bi_interior->attr, - ZEBRA_ROUTE_BGP_DIRECT_EXT, - BGP_ROUTE_REDISTRIBUTE, &label); - } - - /* - * If there are no remaining valid interior routes at this prefix, - * we need to look up the tree for a possible node to move monitors to - */ - if (RFAPI_MONITOR_EXTERIOR (rn_interior)->valid_interior_count) - { - vnc_zlog_debug_verbose ("%s: interior routes still present, skipping", __func__); - return; - } - - /* - * Find nearest parent with at least one valid interior route - * If none is found, par will end up NULL, and we will move - * the monitors to the orphan list for this import table - */ - for (par = rn_interior->parent; par; par = par->parent) - { - if (RFAPI_MONITOR_EXTERIOR (par)->valid_interior_count) - break; - } - - vnc_zlog_debug_verbose ("%s: par=%p, ext src: %p", __func__, - par, RFAPI_MONITOR_EXTERIOR (rn_interior)->source); - - /* move all monitors */ - /* - * We will use and delete every element of the source skiplist - */ - while (!skiplist_first (RFAPI_MONITOR_EXTERIOR (rn_interior)->source, - (void **) &bi_exterior, (void **) &pfx_exterior)) - { - - struct prefix *pfx_mon = prefix_new (); - - prefix_copy (pfx_mon, pfx_exterior); - - if (par) - { - - struct bgp_info *bi; - - /* - * Add monitor to parent node - */ - if (!RFAPI_MONITOR_EXTERIOR (par)->source) - { - RFAPI_MONITOR_EXTERIOR (par)->source = - skiplist_new (0, NULL, (void (*)(void *)) prefix_free); - route_lock_node (par); /* sl */ - } - skiplist_insert (RFAPI_MONITOR_EXTERIOR (par)->source, - bi_exterior, pfx_mon); - route_lock_node (par); /* sl entry */ - - /* Add constructed exterior routes based on parent */ - for (bi = par->info; bi; bi = bi->next) - { - - struct prefix_rd *prd; - struct attr new_attr; - u_int32_t label = 0; - - if (bi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT) - continue; - - if (bi->extra) - { - prd = &bi->extra->vnc.import.rd; - label = decode_label (&bi->extra->label); - } - else - prd = NULL; - - /* use local_pref from unicast route */ - memset (&new_attr, 0, sizeof (struct attr)); - bgp_attr_dup (&new_attr, bi->attr); - if (bi_exterior && - (bi_exterior->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))) - { - new_attr.local_pref = bi_exterior->attr->local_pref; - new_attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF); - } - - rfapiBgpInfoFilteredImportVPN (it, FIF_ACTION_UPDATE, bi->peer, NULL, /* rfd */ - pfx_exterior, - NULL, - afi, - prd, - &new_attr, - ZEBRA_ROUTE_BGP_DIRECT_EXT, - BGP_ROUTE_REDISTRIBUTE, &label); - - } - - } - else - { - - /* - * No interior route for exterior's nexthop. Save monitor - * in orphan list to await future route. - */ - skiplist_insert (it->monitor_exterior_orphans, - bi_exterior, pfx_mon); - } - - skiplist_delete_first (RFAPI_MONITOR_EXTERIOR (rn_interior)->source); - route_unlock_node (rn_interior); /* sl entry */ - } - if (skiplist_empty (RFAPI_MONITOR_EXTERIOR (rn_interior)->source)) - { - skiplist_free (RFAPI_MONITOR_EXTERIOR (rn_interior)->source); - RFAPI_MONITOR_EXTERIOR (rn_interior)->source = NULL; - route_unlock_node (rn_interior); /* sl itself */ - } + afi_t afi = family2afi(rn_interior->p.family); + struct route_node *par; + struct bgp_info *bi_exterior; + struct prefix *pfx_exterior; /* exterior pfx */ + void *cursor; + int rc; + + if (!VALID_INTERIOR_TYPE(bi_interior->type)) { + vnc_zlog_debug_verbose( + "%s: type %d not valid interior type, skipping", + __func__, bi_interior->type); + return; + } + + if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) { + vnc_zlog_debug_verbose( + "%s: redist of exterior routes no enabled, skipping", + __func__); + return; + } + + if (it == bgp->rfapi->it_ce) { + vnc_zlog_debug_verbose("%s: it is it_ce, skipping", __func__); + return; + } + + /* If no exterior routes depend on this prefix, nothing to do */ + if (!RFAPI_HAS_MONITOR_EXTERIOR(rn_interior)) { + vnc_zlog_debug_verbose("%s: no exterior monitor, skipping", + __func__); + return; + } + + /*debugging */ + { + char str_pfx[BUFSIZ]; + + prefix2str(&rn_interior->p, str_pfx, BUFSIZ); + str_pfx[BUFSIZ - 1] = 0; + + vnc_zlog_debug_verbose("%s: interior prefix=%s, bi type=%d", + __func__, str_pfx, bi_interior->type); + } + + /* + * Remove constructed routes based on the deleted interior route + */ + cursor = NULL; + for (rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior)->source, + (void **)&bi_exterior, (void **)&pfx_exterior, + &cursor); + !rc; + rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior)->source, + (void **)&bi_exterior, (void **)&pfx_exterior, + &cursor)) { + + struct prefix_rd *prd; + u_int32_t label = 0; + + if (bi_interior->extra) { + prd = &bi_interior->extra->vnc.import.rd; + label = decode_label(&bi_interior->extra->label); + } else + prd = NULL; + + rfapiBgpInfoFilteredImportVPN( + it, FIF_ACTION_KILL, bi_interior->peer, NULL, /* rfd */ + pfx_exterior, NULL, afi, prd, bi_interior->attr, + ZEBRA_ROUTE_BGP_DIRECT_EXT, BGP_ROUTE_REDISTRIBUTE, + &label); + } + + /* + * If there are no remaining valid interior routes at this prefix, + * we need to look up the tree for a possible node to move monitors to + */ + if (RFAPI_MONITOR_EXTERIOR(rn_interior)->valid_interior_count) { + vnc_zlog_debug_verbose( + "%s: interior routes still present, skipping", + __func__); + return; + } + /* + * Find nearest parent with at least one valid interior route + * If none is found, par will end up NULL, and we will move + * the monitors to the orphan list for this import table + */ + for (par = rn_interior->parent; par; par = par->parent) { + if (RFAPI_MONITOR_EXTERIOR(par)->valid_interior_count) + break; + } + + vnc_zlog_debug_verbose("%s: par=%p, ext src: %p", __func__, par, + RFAPI_MONITOR_EXTERIOR(rn_interior)->source); + + /* move all monitors */ + /* + * We will use and delete every element of the source skiplist + */ + while (!skiplist_first(RFAPI_MONITOR_EXTERIOR(rn_interior)->source, + (void **)&bi_exterior, (void **)&pfx_exterior)) { + + struct prefix *pfx_mon = prefix_new(); + + prefix_copy(pfx_mon, pfx_exterior); + + if (par) { + + struct bgp_info *bi; + + /* + * Add monitor to parent node + */ + if (!RFAPI_MONITOR_EXTERIOR(par)->source) { + RFAPI_MONITOR_EXTERIOR(par)->source = + skiplist_new( + 0, NULL, + (void (*)(void *))prefix_free); + route_lock_node(par); /* sl */ + } + skiplist_insert(RFAPI_MONITOR_EXTERIOR(par)->source, + bi_exterior, pfx_mon); + route_lock_node(par); /* sl entry */ + + /* Add constructed exterior routes based on parent */ + for (bi = par->info; bi; bi = bi->next) { + + struct prefix_rd *prd; + struct attr new_attr; + u_int32_t label = 0; + + if (bi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT) + continue; + + if (bi->extra) { + prd = &bi->extra->vnc.import.rd; + label = decode_label(&bi->extra->label); + } else + prd = NULL; + + /* use local_pref from unicast route */ + memset(&new_attr, 0, sizeof(struct attr)); + bgp_attr_dup(&new_attr, bi->attr); + if (bi_exterior + && (bi_exterior->attr->flag + & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) { + new_attr.local_pref = + bi_exterior->attr->local_pref; + new_attr.flag |= ATTR_FLAG_BIT( + BGP_ATTR_LOCAL_PREF); + } + + rfapiBgpInfoFilteredImportVPN( + it, FIF_ACTION_UPDATE, bi->peer, + NULL, /* rfd */ + pfx_exterior, NULL, afi, prd, &new_attr, + ZEBRA_ROUTE_BGP_DIRECT_EXT, + BGP_ROUTE_REDISTRIBUTE, &label); + } + + } else { + + /* + * No interior route for exterior's nexthop. Save + * monitor + * in orphan list to await future route. + */ + skiplist_insert(it->monitor_exterior_orphans, + bi_exterior, pfx_mon); + } + + skiplist_delete_first( + RFAPI_MONITOR_EXTERIOR(rn_interior)->source); + route_unlock_node(rn_interior); /* sl entry */ + } + if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(rn_interior)->source)) { + skiplist_free(RFAPI_MONITOR_EXTERIOR(rn_interior)->source); + RFAPI_MONITOR_EXTERIOR(rn_interior)->source = NULL; + route_unlock_node(rn_interior); /* sl itself */ + } } /*********************************************************************** * Generic add/delete unicast routes ***********************************************************************/ -void -vnc_import_bgp_add_route ( - struct bgp *bgp, - struct prefix *prefix, - struct bgp_info *info) +void vnc_import_bgp_add_route(struct bgp *bgp, struct prefix *prefix, + struct bgp_info *info) { - afi_t afi = family2afi (prefix->family); + afi_t afi = family2afi(prefix->family); - { - struct prefix pfx_nexthop; - char buf[BUFSIZ]; - char buf_nh[BUFSIZ]; + { + struct prefix pfx_nexthop; + char buf[BUFSIZ]; + char buf_nh[BUFSIZ]; - prefix2str (prefix, buf, BUFSIZ); - rfapiUnicastNexthop2Prefix (afi, info->attr, &pfx_nexthop); - prefix2str (&pfx_nexthop, buf_nh, BUFSIZ); + prefix2str(prefix, buf, BUFSIZ); + rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_nexthop); + prefix2str(&pfx_nexthop, buf_nh, BUFSIZ); - vnc_zlog_debug_verbose ("%s: pfx %s, nh %s", __func__, buf, buf_nh); - } + vnc_zlog_debug_verbose("%s: pfx %s, nh %s", __func__, buf, + buf_nh); + } #if DEBUG_RHN_LIST - print_rhn_list(__func__, "ENTER "); + print_rhn_list(__func__, "ENTER "); #endif - VNC_RHNCK (enter); - - if (!afi) - { - zlog_err ("%s: can't get afi of prefix", __func__); - return; - } - - if (!bgp->rfapi_cfg) - { - vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__); - return; - } - - /* check vnc redist flag for bgp direct routes */ - if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) - { - vnc_zlog_debug_verbose - ("%s: bgp->rfapi_cfg->redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping", - __func__, afi, ZEBRA_ROUTE_BGP_DIRECT); - return; - } - - switch (bgp->rfapi_cfg->redist_mode) - { - case VNC_REDIST_MODE_PLAIN: - vnc_import_bgp_add_route_mode_plain (bgp, prefix, info); - break; - - case VNC_REDIST_MODE_RFG: - if (bgp->rfapi_cfg->rfg_redist) - vnc_import_bgp_add_route_mode_nvegroup (bgp, prefix, info, - bgp->rfapi_cfg->rfg_redist); - else - vnc_zlog_debug_verbose ("%s: mode RFG but no redist RFG", __func__); - break; - - case VNC_REDIST_MODE_RESOLVE_NVE: - vnc_import_bgp_add_route_mode_resolve_nve (bgp, prefix, info); - break; - } + VNC_RHNCK(enter); + + if (!afi) { + zlog_err("%s: can't get afi of prefix", __func__); + return; + } + + if (!bgp->rfapi_cfg) { + vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", + __func__); + return; + } + + /* check vnc redist flag for bgp direct routes */ + if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) { + vnc_zlog_debug_verbose( + "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping", + __func__, afi, ZEBRA_ROUTE_BGP_DIRECT); + return; + } + + switch (bgp->rfapi_cfg->redist_mode) { + case VNC_REDIST_MODE_PLAIN: + vnc_import_bgp_add_route_mode_plain(bgp, prefix, info); + break; + + case VNC_REDIST_MODE_RFG: + if (bgp->rfapi_cfg->rfg_redist) + vnc_import_bgp_add_route_mode_nvegroup( + bgp, prefix, info, bgp->rfapi_cfg->rfg_redist); + else + vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG", + __func__); + break; + + case VNC_REDIST_MODE_RESOLVE_NVE: + vnc_import_bgp_add_route_mode_resolve_nve(bgp, prefix, info); + break; + } #if DEBUG_RHN_LIST - print_rhn_list(__func__, "LEAVE "); + print_rhn_list(__func__, "LEAVE "); #endif - VNC_RHNCK (leave); + VNC_RHNCK(leave); } /* * "Withdrawing a Route" import process */ -void -vnc_import_bgp_del_route ( - struct bgp *bgp, - struct prefix *prefix, - struct bgp_info *info) /* unicast info */ +void vnc_import_bgp_del_route(struct bgp *bgp, struct prefix *prefix, + struct bgp_info *info) /* unicast info */ { - afi_t afi = family2afi (prefix->family); + afi_t afi = family2afi(prefix->family); - assert (afi); + assert(afi); - { - struct prefix pfx_nexthop; - char buf[BUFSIZ]; - char buf_nh[BUFSIZ]; + { + struct prefix pfx_nexthop; + char buf[BUFSIZ]; + char buf_nh[BUFSIZ]; - prefix2str (prefix, buf, BUFSIZ); - rfapiUnicastNexthop2Prefix (afi, info->attr, &pfx_nexthop); - prefix2str (&pfx_nexthop, buf_nh, BUFSIZ); + prefix2str(prefix, buf, BUFSIZ); + rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_nexthop); + prefix2str(&pfx_nexthop, buf_nh, BUFSIZ); - vnc_zlog_debug_verbose ("%s: pfx %s, nh %s", __func__, buf, buf_nh); - } + vnc_zlog_debug_verbose("%s: pfx %s, nh %s", __func__, buf, + buf_nh); + } #if DEBUG_RHN_LIST - print_rhn_list(__func__, "ENTER "); + print_rhn_list(__func__, "ENTER "); #endif - VNC_RHNCK (enter); - - if (!bgp->rfapi_cfg) - { - vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__); - return; - } - - /* check bgp redist flag for vnc direct ("vpn") routes */ - if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) - { - vnc_zlog_debug_verbose ("%s: bgp redistribution of afi=%d VNC direct routes is off", - __func__, afi); - return; - } - - switch (bgp->rfapi_cfg->redist_mode) - { - case VNC_REDIST_MODE_PLAIN: - vnc_import_bgp_del_route_mode_plain (bgp, prefix, info); - break; - - case VNC_REDIST_MODE_RFG: - if (bgp->rfapi_cfg->rfg_redist) - vnc_import_bgp_del_route_mode_nvegroup (bgp, prefix, info); - else - vnc_zlog_debug_verbose ("%s: mode RFG but no redist RFG", __func__); - break; - - case VNC_REDIST_MODE_RESOLVE_NVE: - vnc_import_bgp_del_route_mode_resolve_nve (bgp, afi, prefix, info); - break; - - } + VNC_RHNCK(enter); + + if (!bgp->rfapi_cfg) { + vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", + __func__); + return; + } + + /* check bgp redist flag for vnc direct ("vpn") routes */ + if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) { + vnc_zlog_debug_verbose( + "%s: bgp redistribution of afi=%d VNC direct routes is off", + __func__, afi); + return; + } + + switch (bgp->rfapi_cfg->redist_mode) { + case VNC_REDIST_MODE_PLAIN: + vnc_import_bgp_del_route_mode_plain(bgp, prefix, info); + break; + + case VNC_REDIST_MODE_RFG: + if (bgp->rfapi_cfg->rfg_redist) + vnc_import_bgp_del_route_mode_nvegroup(bgp, prefix, + info); + else + vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG", + __func__); + break; + + case VNC_REDIST_MODE_RESOLVE_NVE: + vnc_import_bgp_del_route_mode_resolve_nve(bgp, afi, prefix, + info); + break; + } #if DEBUG_RHN_LIST - print_rhn_list(__func__, "LEAVE "); + print_rhn_list(__func__, "LEAVE "); #endif - VNC_RHNCK (leave); + VNC_RHNCK(leave); } @@ -2901,257 +2768,257 @@ vnc_import_bgp_del_route ( * Enable/Disable ***********************************************************************/ -void -vnc_import_bgp_redist_enable (struct bgp *bgp, afi_t afi) +void vnc_import_bgp_redist_enable(struct bgp *bgp, afi_t afi) { - /* iterate over bgp unicast v4 and v6 routes, call vnc_import_bgp_add_route */ + /* iterate over bgp unicast v4 and v6 routes, call + * vnc_import_bgp_add_route */ - struct bgp_node *rn; + struct bgp_node *rn; - vnc_zlog_debug_verbose ("%s: entry, afi=%d", __func__, afi); + vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi); - if (bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) - { - vnc_zlog_debug_verbose ("%s: already enabled for afi %d, skipping", __func__, afi); - return; - } - bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT] = 1; + if (bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) { + vnc_zlog_debug_verbose( + "%s: already enabled for afi %d, skipping", __func__, + afi); + return; + } + bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT] = 1; - for (rn = bgp_table_top (bgp->rib[afi][SAFI_UNICAST]); - rn; rn = bgp_route_next (rn)) - { + for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn; + rn = bgp_route_next(rn)) { - struct bgp_info *bi; + struct bgp_info *bi; - for (bi = rn->info; bi; bi = bi->next) - { + for (bi = rn->info; bi; bi = bi->next) { - if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)) - continue; + if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + continue; - vnc_import_bgp_add_route (bgp, &rn->p, bi); - } - } - vnc_zlog_debug_verbose ("%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return", - __func__, afi, ZEBRA_ROUTE_BGP_DIRECT); + vnc_import_bgp_add_route(bgp, &rn->p, bi); + } + } + vnc_zlog_debug_verbose( + "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return", + __func__, afi, ZEBRA_ROUTE_BGP_DIRECT); } -void -vnc_import_bgp_exterior_redist_enable (struct bgp *bgp, afi_t afi) +void vnc_import_bgp_exterior_redist_enable(struct bgp *bgp, afi_t afi) { - struct bgp *bgp_exterior; - struct bgp_node *rn; - - bgp_exterior = bgp->rfapi_cfg->redist_bgp_exterior_view; + struct bgp *bgp_exterior; + struct bgp_node *rn; - if (bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) - { - vnc_zlog_debug_verbose ("%s: already enabled for afi %d, skipping", __func__, afi); - return; - } - bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT] = 1; + bgp_exterior = bgp->rfapi_cfg->redist_bgp_exterior_view; - if (!bgp_exterior) - { - vnc_zlog_debug_verbose ("%s: no exterior view set yet, no routes to import yet", - __func__); - return; - } + if (bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) { + vnc_zlog_debug_verbose( + "%s: already enabled for afi %d, skipping", __func__, + afi); + return; + } + bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT] = 1; - for (rn = bgp_table_top (bgp_exterior->rib[afi][SAFI_UNICAST]); - rn; rn = bgp_route_next (rn)) - { + if (!bgp_exterior) { + vnc_zlog_debug_verbose( + "%s: no exterior view set yet, no routes to import yet", + __func__); + return; + } - struct bgp_info *bi; + for (rn = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]); rn; + rn = bgp_route_next(rn)) { - for (bi = rn->info; bi; bi = bi->next) - { + struct bgp_info *bi; - if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)) - continue; + for (bi = rn->info; bi; bi = bi->next) { - vnc_import_bgp_exterior_add_route (bgp_exterior, &rn->p, bi); - } - } - vnc_zlog_debug_verbose ("%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return", - __func__, afi, ZEBRA_ROUTE_BGP_DIRECT); + if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + continue; + vnc_import_bgp_exterior_add_route(bgp_exterior, &rn->p, + bi); + } + } + vnc_zlog_debug_verbose( + "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return", + __func__, afi, ZEBRA_ROUTE_BGP_DIRECT); } /* * This function is for populating a newly-created Import Table */ -void -vnc_import_bgp_exterior_redist_enable_it ( - struct bgp *bgp, - afi_t afi, - struct rfapi_import_table *it_only) +void vnc_import_bgp_exterior_redist_enable_it( + struct bgp *bgp, afi_t afi, struct rfapi_import_table *it_only) { - struct bgp *bgp_exterior; - struct bgp_node *rn; + struct bgp *bgp_exterior; + struct bgp_node *rn; - vnc_zlog_debug_verbose ("%s: entry", __func__); + vnc_zlog_debug_verbose("%s: entry", __func__); - bgp_exterior = bgp->rfapi_cfg->redist_bgp_exterior_view; + bgp_exterior = bgp->rfapi_cfg->redist_bgp_exterior_view; - if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) - { - vnc_zlog_debug_verbose ("%s: not enabled for afi %d, skipping", __func__, afi); - return; - } - - if (!bgp_exterior) - { - vnc_zlog_debug_verbose ("%s: no exterior view set yet, no routes to import yet", - __func__); - return; - } + if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) { + vnc_zlog_debug_verbose("%s: not enabled for afi %d, skipping", + __func__, afi); + return; + } - for (rn = bgp_table_top (bgp_exterior->rib[afi][SAFI_UNICAST]); - rn; rn = bgp_route_next (rn)) - { + if (!bgp_exterior) { + vnc_zlog_debug_verbose( + "%s: no exterior view set yet, no routes to import yet", + __func__); + return; + } - struct bgp_info *bi; + for (rn = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]); rn; + rn = bgp_route_next(rn)) { - for (bi = rn->info; bi; bi = bi->next) - { + struct bgp_info *bi; - if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)) - continue; + for (bi = rn->info; bi; bi = bi->next) { - vnc_import_bgp_exterior_add_route_it (bgp_exterior, &rn->p, bi, - it_only); - } - } + if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + continue; + vnc_import_bgp_exterior_add_route_it( + bgp_exterior, &rn->p, bi, it_only); + } + } } -void -vnc_import_bgp_redist_disable (struct bgp *bgp, afi_t afi) +void vnc_import_bgp_redist_disable(struct bgp *bgp, afi_t afi) { - /* - * iterate over vpn routes, find routes of type ZEBRA_ROUTE_BGP_DIRECT, - * delete (call timer expire immediately) - */ - struct bgp_node *rn1; - struct bgp_node *rn2; - - vnc_zlog_debug_verbose ("%s: entry", __func__); - - if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) - { - vnc_zlog_debug_verbose ("%s: already disabled for afi %d, skipping", __func__, afi); - return; - } - - /* - * Two-level table for SAFI_MPLS_VPN - * Be careful when changing the things we iterate over - */ - for (rn1 = bgp_table_top (bgp->rib[afi][SAFI_MPLS_VPN]); - rn1; rn1 = bgp_route_next (rn1)) - { - - if (rn1->info) - { - for (rn2 = bgp_table_top (rn1->info); - rn2; rn2 = bgp_route_next (rn2)) - { - - struct bgp_info *bi; - struct bgp_info *nextbi; - - for (bi = rn2->info; bi; bi = nextbi) - { - - nextbi = bi->next; - - if (bi->type == ZEBRA_ROUTE_BGP_DIRECT) - { - - struct rfapi_descriptor *rfd; - vncHDBgpDirect.peer = bi->peer; - - rfd = bi->extra->vnc.export.rfapi_handle; - - vnc_zlog_debug_verbose - ("%s: deleting bi=%p, bi->peer=%p, bi->type=%d, bi->sub_type=%d, bi->extra->vnc.export.rfapi_handle=%p [passing rfd=%p]", - __func__, bi, bi->peer, bi->type, bi->sub_type, - (bi->extra ? bi->extra->vnc. - export.rfapi_handle : NULL), rfd); - - - del_vnc_route (rfd, bi->peer, bgp, SAFI_MPLS_VPN, &rn2->p, (struct prefix_rd *) &rn1->p, bi->type, bi->sub_type, NULL, 1); /* kill */ - - vncHDBgpDirect.peer = NULL; - } - } - } - } - } - /* Clear RHN list */ - if (bgp->rfapi->resolve_nve_nexthop) - { - struct prefix_bag *pb; - struct bgp_info *info; - while (!skiplist_first - (bgp->rfapi->resolve_nve_nexthop, NULL, (void *) &pb)) - { - info = pb->ubi; - skiplist_delete_first (bgp->rfapi->resolve_nve_nexthop); - bgp_info_unlock (info); - } - } - - bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT] = 0; - vnc_zlog_debug_verbose ("%s: return", __func__); + /* + * iterate over vpn routes, find routes of type ZEBRA_ROUTE_BGP_DIRECT, + * delete (call timer expire immediately) + */ + struct bgp_node *rn1; + struct bgp_node *rn2; + + vnc_zlog_debug_verbose("%s: entry", __func__); + + if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) { + vnc_zlog_debug_verbose( + "%s: already disabled for afi %d, skipping", __func__, + afi); + return; + } + + /* + * Two-level table for SAFI_MPLS_VPN + * Be careful when changing the things we iterate over + */ + for (rn1 = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); rn1; + rn1 = bgp_route_next(rn1)) { + + if (rn1->info) { + for (rn2 = bgp_table_top(rn1->info); rn2; + rn2 = bgp_route_next(rn2)) { + + struct bgp_info *bi; + struct bgp_info *nextbi; + + for (bi = rn2->info; bi; bi = nextbi) { + + nextbi = bi->next; + + if (bi->type + == ZEBRA_ROUTE_BGP_DIRECT) { + + struct rfapi_descriptor *rfd; + vncHDBgpDirect.peer = bi->peer; + + rfd = bi->extra->vnc.export + .rfapi_handle; + + vnc_zlog_debug_verbose( + "%s: deleting bi=%p, bi->peer=%p, bi->type=%d, bi->sub_type=%d, bi->extra->vnc.export.rfapi_handle=%p [passing rfd=%p]", + __func__, bi, bi->peer, + bi->type, bi->sub_type, + (bi->extra + ? bi->extra + ->vnc + .export + .rfapi_handle + : NULL), + rfd); + + + del_vnc_route( + rfd, bi->peer, bgp, + SAFI_MPLS_VPN, &rn2->p, + (struct prefix_rd *)&rn1 + ->p, + bi->type, bi->sub_type, + NULL, 1); /* kill */ + + vncHDBgpDirect.peer = NULL; + } + } + } + } + } + /* Clear RHN list */ + if (bgp->rfapi->resolve_nve_nexthop) { + struct prefix_bag *pb; + struct bgp_info *info; + while (!skiplist_first(bgp->rfapi->resolve_nve_nexthop, NULL, + (void *)&pb)) { + info = pb->ubi; + skiplist_delete_first(bgp->rfapi->resolve_nve_nexthop); + bgp_info_unlock(info); + } + } + + bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT] = 0; + vnc_zlog_debug_verbose("%s: return", __func__); } -void -vnc_import_bgp_exterior_redist_disable (struct bgp *bgp, afi_t afi) +void vnc_import_bgp_exterior_redist_disable(struct bgp *bgp, afi_t afi) { - struct rfapi_cfg *hc = bgp->rfapi_cfg; - struct bgp *bgp_exterior = hc->redist_bgp_exterior_view; + struct rfapi_cfg *hc = bgp->rfapi_cfg; + struct bgp *bgp_exterior = hc->redist_bgp_exterior_view; - vnc_zlog_debug_verbose ("%s: entry", __func__); + vnc_zlog_debug_verbose("%s: entry", __func__); - if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) - { - vnc_zlog_debug_verbose ("%s: already disabled for afi %d, skipping", __func__, afi); - return; - } + if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) { + vnc_zlog_debug_verbose( + "%s: already disabled for afi %d, skipping", __func__, + afi); + return; + } - if (!bgp_exterior) - { - vnc_zlog_debug_verbose ("%s: bgp exterior view not defined, skipping", __func__); - return; - } + if (!bgp_exterior) { + vnc_zlog_debug_verbose( + "%s: bgp exterior view not defined, skipping", + __func__); + return; + } - { - struct bgp_node *rn; - for (rn = bgp_table_top (bgp_exterior->rib[afi][SAFI_UNICAST]); - rn; rn = bgp_route_next (rn)) - { + { + struct bgp_node *rn; + for (rn = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]); + rn; rn = bgp_route_next(rn)) { - struct bgp_info *bi; + struct bgp_info *bi; - for (bi = rn->info; bi; bi = bi->next) - { + for (bi = rn->info; bi; bi = bi->next) { - if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)) - continue; + if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + continue; - vnc_import_bgp_exterior_del_route (bgp_exterior, &rn->p, bi); - } - } + vnc_import_bgp_exterior_del_route(bgp_exterior, + &rn->p, bi); + } + } #if DEBUG_RHN_LIST - print_rhn_list (__func__, NULL); + print_rhn_list(__func__, NULL); #endif - } + } - bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT] = 0; - vnc_zlog_debug_verbose ("%s: return", __func__); + bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT] = 0; + vnc_zlog_debug_verbose("%s: return", __func__); } diff --git a/bgpd/rfapi/vnc_import_bgp.h b/bgpd/rfapi/vnc_import_bgp.h index 9a7261067..7c1593990 100644 --- a/bgpd/rfapi/vnc_import_bgp.h +++ b/bgpd/rfapi/vnc_import_bgp.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -27,66 +27,48 @@ #include "bgpd/bgpd.h" #include "bgpd/bgp_route.h" -#define VALID_INTERIOR_TYPE(type) \ - (((type) == ZEBRA_ROUTE_BGP) || ((type) == ZEBRA_ROUTE_BGP_DIRECT)) +#define VALID_INTERIOR_TYPE(type) \ + (((type) == ZEBRA_ROUTE_BGP) || ((type) == ZEBRA_ROUTE_BGP_DIRECT)) -extern uint32_t -calc_local_pref (struct attr *attr, struct peer *peer); +extern uint32_t calc_local_pref(struct attr *attr, struct peer *peer); -extern int -vnc_prefix_cmp (void *pfx1, void *pfx2); +extern int vnc_prefix_cmp(void *pfx1, void *pfx2); -extern void -vnc_import_bgp_add_route ( - struct bgp *bgp, - struct prefix *prefix, - struct bgp_info *info); +extern void vnc_import_bgp_add_route(struct bgp *bgp, struct prefix *prefix, + struct bgp_info *info); -extern void -vnc_import_bgp_del_route ( - struct bgp *bgp, - struct prefix *prefix, - struct bgp_info *info); +extern void vnc_import_bgp_del_route(struct bgp *bgp, struct prefix *prefix, + struct bgp_info *info); -extern void -vnc_import_bgp_redist_enable (struct bgp *bgp, afi_t afi); +extern void vnc_import_bgp_redist_enable(struct bgp *bgp, afi_t afi); -extern void -vnc_import_bgp_redist_disable (struct bgp *bgp, afi_t afi); +extern void vnc_import_bgp_redist_disable(struct bgp *bgp, afi_t afi); -extern void -vnc_import_bgp_exterior_redist_enable (struct bgp *bgp, afi_t afi); +extern void vnc_import_bgp_exterior_redist_enable(struct bgp *bgp, afi_t afi); -extern void -vnc_import_bgp_exterior_redist_disable (struct bgp *bgp, afi_t afi); +extern void vnc_import_bgp_exterior_redist_disable(struct bgp *bgp, afi_t afi); -extern void -vnc_import_bgp_exterior_add_route ( - struct bgp *bgp, /* exterior instance, we hope */ - struct prefix *prefix,/* unicast prefix */ - struct bgp_info *info); /* unicast info */ - -extern void -vnc_import_bgp_exterior_del_route ( - struct bgp *bgp, - struct prefix *prefix,/* unicast prefix */ - struct bgp_info *info); /* unicast info */ - -extern void -vnc_import_bgp_add_vnc_host_route_mode_resolve_nve ( - struct bgp *bgp, - struct prefix_rd *prd, /* RD */ - struct bgp_table *table_rd, /* per-rd VPN route table */ - struct prefix *prefix, /* VPN prefix */ - struct bgp_info *bi); /* new VPN host route */ +extern void vnc_import_bgp_exterior_add_route( + struct bgp *bgp, /* exterior instance, we hope */ + struct prefix *prefix, /* unicast prefix */ + struct bgp_info *info); /* unicast info */ extern void -vnc_import_bgp_del_vnc_host_route_mode_resolve_nve ( - struct bgp *bgp, - struct prefix_rd *prd, /* RD */ - struct bgp_table *table_rd, /* per-rd VPN route table */ - struct prefix *prefix, /* VPN prefix */ - struct bgp_info *bi); /* old VPN host route */ +vnc_import_bgp_exterior_del_route(struct bgp *bgp, + struct prefix *prefix, /* unicast prefix */ + struct bgp_info *info); /* unicast info */ + +extern void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( + struct bgp *bgp, struct prefix_rd *prd, /* RD */ + struct bgp_table *table_rd, /* per-rd VPN route table */ + struct prefix *prefix, /* VPN prefix */ + struct bgp_info *bi); /* new VPN host route */ + +extern void vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( + struct bgp *bgp, struct prefix_rd *prd, /* RD */ + struct bgp_table *table_rd, /* per-rd VPN route table */ + struct prefix *prefix, /* VPN prefix */ + struct bgp_info *bi); /* old VPN host route */ #endif /* _QUAGGA_RFAPI_VNC_IMPORT_BGP_H_ */ diff --git a/bgpd/rfapi/vnc_import_bgp_p.h b/bgpd/rfapi/vnc_import_bgp_p.h index 19bcd1925..b38fa2276 100644 --- a/bgpd/rfapi/vnc_import_bgp_p.h +++ b/bgpd/rfapi/vnc_import_bgp_p.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -27,24 +27,18 @@ #include "bgpd/bgpd.h" #include "bgpd/bgp_route.h" -extern void -vnc_import_bgp_exterior_add_route_interior ( - struct bgp *bgp, - struct rfapi_import_table *it, - struct route_node *rn_interior, /* VPN IT node */ - struct bgp_info *bi_interior); /* VPN IT route */ +extern void vnc_import_bgp_exterior_add_route_interior( + struct bgp *bgp, struct rfapi_import_table *it, + struct route_node *rn_interior, /* VPN IT node */ + struct bgp_info *bi_interior); /* VPN IT route */ -extern void -vnc_import_bgp_exterior_del_route_interior ( - struct bgp *bgp, - struct rfapi_import_table *it, - struct route_node *rn_interior, /* VPN IT node */ - struct bgp_info *bi_interior); /* VPN IT route */ +extern void vnc_import_bgp_exterior_del_route_interior( + struct bgp *bgp, struct rfapi_import_table *it, + struct route_node *rn_interior, /* VPN IT node */ + struct bgp_info *bi_interior); /* VPN IT route */ extern void -vnc_import_bgp_exterior_redist_enable_it ( - struct bgp *bgp, - afi_t afi, - struct rfapi_import_table *it_only); +vnc_import_bgp_exterior_redist_enable_it(struct bgp *bgp, afi_t afi, + struct rfapi_import_table *it_only); #endif /* _QUAGGA_RFAPI_VNC_IMPORT_BGP_P_H_ */ diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c index de1249ff2..3075d4109 100644 --- a/bgpd/rfapi/vnc_zebra.c +++ b/bgpd/rfapi/vnc_zebra.c @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -47,7 +47,7 @@ #include "bgpd/rfapi/rfapi_backend.h" #include "bgpd/rfapi/vnc_debug.h" -static struct rfapi_descriptor vncHD1VR; /* Single-VR export dummy nve descr */ +static struct rfapi_descriptor vncHD1VR; /* Single-VR export dummy nve descr */ static struct zclient *zclient_vnc = NULL; /*********************************************************************** @@ -57,281 +57,271 @@ static struct zclient *zclient_vnc = NULL; /* * Routes coming from zebra get added to VNC here */ -static void -vnc_redistribute_add ( - struct prefix *p, - struct in_addr *nexthop, - u_int32_t metric, - uint8_t type) +static void vnc_redistribute_add(struct prefix *p, struct in_addr *nexthop, + u_int32_t metric, uint8_t type) { - struct bgp *bgp = bgp_get_default (); - struct prefix_rd prd; - struct rfapi_ip_addr vnaddr; - afi_t afi; - uint32_t local_pref = rfp_cost_to_localpref (metric > 255 ? 255 : metric); - - if (!bgp) - return; - - if (!bgp->rfapi_cfg) - { - vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__); - return; - } - - afi = family2afi (p->family); - if (!afi) - { - vnc_zlog_debug_verbose ("%s: unknown prefix address family %d", __func__, - p->family); - return; - } - - if (!bgp->rfapi_cfg->redist[afi][type]) - { - vnc_zlog_debug_verbose - ("%s: bgp->rfapi_cfg->redist[afi=%d][type=%d] is 0, skipping", - __func__, afi, type); - return; - } - if (!bgp->rfapi_cfg->rfg_redist) - { - vnc_zlog_debug_verbose ("%s: no redist nve group, skipping", __func__); - return; - } - - /* - * Assume nve group's configured VN address prefix is a host - * route which also happens to give the NVE VN address to use - * for redistributing into VNC. - */ - vnaddr.addr_family = bgp->rfapi_cfg->rfg_redist->vn_prefix.family; - switch (bgp->rfapi_cfg->rfg_redist->vn_prefix.family) - { - case AF_INET: - if (bgp->rfapi_cfg->rfg_redist->vn_prefix.prefixlen != 32) - { - vnc_zlog_debug_verbose - ("%s: redist nve group VN prefix len (%d) != 32, skipping", - __func__, bgp->rfapi_cfg->rfg_redist->vn_prefix.prefixlen); - return; - } - vnaddr.addr.v4 = bgp->rfapi_cfg->rfg_redist->vn_prefix.u.prefix4; - break; - case AF_INET6: - if (bgp->rfapi_cfg->rfg_redist->vn_prefix.prefixlen != 128) - { - vnc_zlog_debug_verbose - ("%s: redist nve group VN prefix len (%d) != 128, skipping", - __func__, bgp->rfapi_cfg->rfg_redist->vn_prefix.prefixlen); - return; - } - vnaddr.addr.v6 = bgp->rfapi_cfg->rfg_redist->vn_prefix.u.prefix6; - break; - default: - vnc_zlog_debug_verbose - ("%s: no redist nve group VN host prefix configured, skipping", - __func__); - return; - } - - /* - * Assume nve group's configured UN address prefix is a host - * route which also happens to give the NVE UN address to use - * for redistributing into VNC. - */ - - /* - * Set UN address in dummy nve descriptor so add_vnc_route - * can use it in VNC tunnel SubTLV - */ - { - struct rfapi_ip_prefix pfx_un; - - rfapiQprefix2Rprefix (&bgp->rfapi_cfg->rfg_redist->un_prefix, &pfx_un); - - switch (pfx_un.prefix.addr_family) - { - case AF_INET: - if (pfx_un.length != 32) - { - vnc_zlog_debug_verbose - ("%s: redist nve group UN prefix len (%d) != 32, skipping", - __func__, pfx_un.length); - return; - } - break; - case AF_INET6: - if (pfx_un.length != 128) - { - vnc_zlog_debug_verbose - ("%s: redist nve group UN prefix len (%d) != 128, skipping", - __func__, pfx_un.length); - return; - } - break; - default: - vnc_zlog_debug_verbose - ("%s: no redist nve group UN host prefix configured, skipping", - __func__); - return; - } - - vncHD1VR.un_addr = pfx_un.prefix; - - if (!vncHD1VR.peer) - { - /* - * Same setup as in rfapi_open() - */ - vncHD1VR.peer = peer_new (bgp); - vncHD1VR.peer->status = Established; /* keep bgp core happy */ - bgp_sync_delete (vncHD1VR.peer); /* don't need these */ - if (vncHD1VR.peer->ibuf) - { - stream_free (vncHD1VR.peer->ibuf); /* don't need it */ - vncHD1VR.peer->ibuf = NULL; - } - if (vncHD1VR.peer->obuf) - { - stream_fifo_free (vncHD1VR.peer->obuf); /* don't need it */ - vncHD1VR.peer->obuf = NULL; - } - if (vncHD1VR.peer->work) - { - stream_free (vncHD1VR.peer->work); /* don't need it */ - vncHD1VR.peer->work = NULL; - } - /* base code assumes have valid host pointer */ - vncHD1VR.peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, ".zebra."); - - /* Mark peer as belonging to HD */ - SET_FLAG (vncHD1VR.peer->flags, PEER_FLAG_IS_RFAPI_HD); - } - } - - memset (&prd, 0, sizeof (prd)); - prd = bgp->rfapi_cfg->rfg_redist->rd; - prd.family = AF_UNSPEC; - prd.prefixlen = 64; - - add_vnc_route (&vncHD1VR, /* cookie + UN addr */ - bgp, SAFI_MPLS_VPN, p, &prd, &vnaddr, &local_pref, &(bgp->rfapi_cfg->redist_lifetime), NULL, /* RFP options */ - NULL, /* struct rfapi_un_option */ - NULL, /* struct rfapi_vn_option */ - bgp->rfapi_cfg->rfg_redist->rt_export_list, NULL, NULL, /* label: default */ - type, BGP_ROUTE_REDISTRIBUTE, 0); /* flags */ + struct bgp *bgp = bgp_get_default(); + struct prefix_rd prd; + struct rfapi_ip_addr vnaddr; + afi_t afi; + uint32_t local_pref = + rfp_cost_to_localpref(metric > 255 ? 255 : metric); + + if (!bgp) + return; + + if (!bgp->rfapi_cfg) { + vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", + __func__); + return; + } + + afi = family2afi(p->family); + if (!afi) { + vnc_zlog_debug_verbose("%s: unknown prefix address family %d", + __func__, p->family); + return; + } + + if (!bgp->rfapi_cfg->redist[afi][type]) { + vnc_zlog_debug_verbose( + "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d] is 0, skipping", + __func__, afi, type); + return; + } + if (!bgp->rfapi_cfg->rfg_redist) { + vnc_zlog_debug_verbose("%s: no redist nve group, skipping", + __func__); + return; + } + + /* + * Assume nve group's configured VN address prefix is a host + * route which also happens to give the NVE VN address to use + * for redistributing into VNC. + */ + vnaddr.addr_family = bgp->rfapi_cfg->rfg_redist->vn_prefix.family; + switch (bgp->rfapi_cfg->rfg_redist->vn_prefix.family) { + case AF_INET: + if (bgp->rfapi_cfg->rfg_redist->vn_prefix.prefixlen != 32) { + vnc_zlog_debug_verbose( + "%s: redist nve group VN prefix len (%d) != 32, skipping", + __func__, + bgp->rfapi_cfg->rfg_redist->vn_prefix + .prefixlen); + return; + } + vnaddr.addr.v4 = + bgp->rfapi_cfg->rfg_redist->vn_prefix.u.prefix4; + break; + case AF_INET6: + if (bgp->rfapi_cfg->rfg_redist->vn_prefix.prefixlen != 128) { + vnc_zlog_debug_verbose( + "%s: redist nve group VN prefix len (%d) != 128, skipping", + __func__, + bgp->rfapi_cfg->rfg_redist->vn_prefix + .prefixlen); + return; + } + vnaddr.addr.v6 = + bgp->rfapi_cfg->rfg_redist->vn_prefix.u.prefix6; + break; + default: + vnc_zlog_debug_verbose( + "%s: no redist nve group VN host prefix configured, skipping", + __func__); + return; + } + + /* + * Assume nve group's configured UN address prefix is a host + * route which also happens to give the NVE UN address to use + * for redistributing into VNC. + */ + + /* + * Set UN address in dummy nve descriptor so add_vnc_route + * can use it in VNC tunnel SubTLV + */ + { + struct rfapi_ip_prefix pfx_un; + + rfapiQprefix2Rprefix(&bgp->rfapi_cfg->rfg_redist->un_prefix, + &pfx_un); + + switch (pfx_un.prefix.addr_family) { + case AF_INET: + if (pfx_un.length != 32) { + vnc_zlog_debug_verbose( + "%s: redist nve group UN prefix len (%d) != 32, skipping", + __func__, pfx_un.length); + return; + } + break; + case AF_INET6: + if (pfx_un.length != 128) { + vnc_zlog_debug_verbose( + "%s: redist nve group UN prefix len (%d) != 128, skipping", + __func__, pfx_un.length); + return; + } + break; + default: + vnc_zlog_debug_verbose( + "%s: no redist nve group UN host prefix configured, skipping", + __func__); + return; + } + + vncHD1VR.un_addr = pfx_un.prefix; + + if (!vncHD1VR.peer) { + /* + * Same setup as in rfapi_open() + */ + vncHD1VR.peer = peer_new(bgp); + vncHD1VR.peer->status = + Established; /* keep bgp core happy */ + bgp_sync_delete(vncHD1VR.peer); /* don't need these */ + if (vncHD1VR.peer->ibuf) { + stream_free(vncHD1VR.peer + ->ibuf); /* don't need it */ + vncHD1VR.peer->ibuf = NULL; + } + if (vncHD1VR.peer->obuf) { + stream_fifo_free( + vncHD1VR.peer + ->obuf); /* don't need it */ + vncHD1VR.peer->obuf = NULL; + } + if (vncHD1VR.peer->work) { + stream_free(vncHD1VR.peer + ->work); /* don't need it */ + vncHD1VR.peer->work = NULL; + } + /* base code assumes have valid host pointer */ + vncHD1VR.peer->host = + XSTRDUP(MTYPE_BGP_PEER_HOST, ".zebra."); + + /* Mark peer as belonging to HD */ + SET_FLAG(vncHD1VR.peer->flags, PEER_FLAG_IS_RFAPI_HD); + } + } + + memset(&prd, 0, sizeof(prd)); + prd = bgp->rfapi_cfg->rfg_redist->rd; + prd.family = AF_UNSPEC; + prd.prefixlen = 64; + + add_vnc_route(&vncHD1VR, /* cookie + UN addr */ + bgp, SAFI_MPLS_VPN, p, &prd, &vnaddr, &local_pref, + &(bgp->rfapi_cfg->redist_lifetime), + NULL, /* RFP options */ + NULL, /* struct rfapi_un_option */ + NULL, /* struct rfapi_vn_option */ + bgp->rfapi_cfg->rfg_redist->rt_export_list, NULL, + NULL, /* label: default */ + type, BGP_ROUTE_REDISTRIBUTE, 0); /* flags */ } /* * Route deletions from zebra propagate to VNC here */ -static void -vnc_redistribute_delete (struct prefix *p, uint8_t type) +static void vnc_redistribute_delete(struct prefix *p, uint8_t type) { - struct bgp *bgp = bgp_get_default (); - struct prefix_rd prd; - afi_t afi; - - if (!bgp) - return; - - if (!bgp->rfapi_cfg) - { - vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__); - return; - } - afi = family2afi (p->family); - if (!afi) - { - vnc_zlog_debug_verbose ("%s: unknown prefix address family %d", __func__, - p->family); - return; - } - if (!bgp->rfapi_cfg->redist[afi][type]) - { - vnc_zlog_debug_verbose - ("%s: bgp->rfapi_cfg->redist[afi=%d][type=%d] is 0, skipping", - __func__, afi, type); - return; - } - if (!bgp->rfapi_cfg->rfg_redist) - { - vnc_zlog_debug_verbose ("%s: no redist nve group, skipping", __func__); - return; - } - - memset (&prd, 0, sizeof (prd)); - prd = bgp->rfapi_cfg->rfg_redist->rd; - prd.family = AF_UNSPEC; - prd.prefixlen = 64; - - del_vnc_route (&vncHD1VR, /* use dummy ptr as cookie */ - vncHD1VR.peer, - bgp, - SAFI_MPLS_VPN, - p, &prd, type, BGP_ROUTE_REDISTRIBUTE, NULL, 0); + struct bgp *bgp = bgp_get_default(); + struct prefix_rd prd; + afi_t afi; + + if (!bgp) + return; + + if (!bgp->rfapi_cfg) { + vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", + __func__); + return; + } + afi = family2afi(p->family); + if (!afi) { + vnc_zlog_debug_verbose("%s: unknown prefix address family %d", + __func__, p->family); + return; + } + if (!bgp->rfapi_cfg->redist[afi][type]) { + vnc_zlog_debug_verbose( + "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d] is 0, skipping", + __func__, afi, type); + return; + } + if (!bgp->rfapi_cfg->rfg_redist) { + vnc_zlog_debug_verbose("%s: no redist nve group, skipping", + __func__); + return; + } + + memset(&prd, 0, sizeof(prd)); + prd = bgp->rfapi_cfg->rfg_redist->rd; + prd.family = AF_UNSPEC; + prd.prefixlen = 64; + + del_vnc_route(&vncHD1VR, /* use dummy ptr as cookie */ + vncHD1VR.peer, bgp, SAFI_MPLS_VPN, p, &prd, type, + BGP_ROUTE_REDISTRIBUTE, NULL, 0); } /* * Flush all redistributed routes of type */ -static void -vnc_redistribute_withdraw (struct bgp *bgp, afi_t afi, uint8_t type) +static void vnc_redistribute_withdraw(struct bgp *bgp, afi_t afi, uint8_t type) { - struct prefix_rd prd; - struct bgp_table *table; - struct bgp_node *prn; - struct bgp_node *rn; - - vnc_zlog_debug_verbose ("%s: entry", __func__); - - if (!bgp) - return; - if (!bgp->rfapi_cfg) - { - vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__); - return; - } - - /* - * Loop over all the RDs - */ - for (prn = bgp_table_top (bgp->rib[afi][SAFI_MPLS_VPN]); prn; - prn = bgp_route_next (prn)) - { - memset (&prd, 0, sizeof (prd)); - prd.family = AF_UNSPEC; - prd.prefixlen = 64; - memcpy (prd.val, prn->p.u.val, 8); - - /* This is the per-RD table of prefixes */ - table = prn->info; - - for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) - { - - struct bgp_info *ri; - - for (ri = rn->info; ri; ri = ri->next) - { - if (ri->type == type) - { /* has matching redist type */ - break; - } - } - if (ri) - { - del_vnc_route (&vncHD1VR, /* use dummy ptr as cookie */ - vncHD1VR.peer, - bgp, - SAFI_MPLS_VPN, - &(rn->p), - &prd, type, BGP_ROUTE_REDISTRIBUTE, NULL, 0); - } - } - } - vnc_zlog_debug_verbose ("%s: return", __func__); + struct prefix_rd prd; + struct bgp_table *table; + struct bgp_node *prn; + struct bgp_node *rn; + + vnc_zlog_debug_verbose("%s: entry", __func__); + + if (!bgp) + return; + if (!bgp->rfapi_cfg) { + vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", + __func__); + return; + } + + /* + * Loop over all the RDs + */ + for (prn = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); prn; + prn = bgp_route_next(prn)) { + memset(&prd, 0, sizeof(prd)); + prd.family = AF_UNSPEC; + prd.prefixlen = 64; + memcpy(prd.val, prn->p.u.val, 8); + + /* This is the per-RD table of prefixes */ + table = prn->info; + + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { + + struct bgp_info *ri; + + for (ri = rn->info; ri; ri = ri->next) { + if (ri->type + == type) { /* has matching redist type */ + break; + } + } + if (ri) { + del_vnc_route( + &vncHD1VR, /* use dummy ptr as cookie */ + vncHD1VR.peer, bgp, SAFI_MPLS_VPN, + &(rn->p), &prd, type, + BGP_ROUTE_REDISTRIBUTE, NULL, 0); + } + } + } + vnc_zlog_debug_verbose("%s: return", __func__); } /* @@ -339,177 +329,159 @@ vnc_redistribute_withdraw (struct bgp *bgp, afi_t afi, uint8_t type) * * Assumes 1 nexthop */ -static int -vnc_zebra_read_ipv4 ( - int command, - struct zclient *zclient, - zebra_size_t length, - vrf_id_t vrf_id) +static int vnc_zebra_read_ipv4(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv4 api; - struct in_addr nexthop; - struct prefix_ipv4 p; - - s = zclient->ibuf; - nexthop.s_addr = 0; - - /* Type, flags, message. */ - api.type = stream_getc (s); - api.flags = stream_getc (s); - api.message = stream_getc (s); - - /* IPv4 prefix. */ - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = stream_getc (s); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) - { - api.nexthop_num = stream_getc (s); - nexthop.s_addr = stream_get_ipv4 (s); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) - { - api.ifindex_num = stream_getc (s); - stream_getl (s); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc (s); - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl (s); - else - api.metric = 0; - - if (command == ZEBRA_IPV4_ROUTE_ADD) - { - if (BGP_DEBUG (zebra, ZEBRA)) - { - char buf[2][INET_ADDRSTRLEN]; - vnc_zlog_debug_verbose - ("%s: Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u", - __func__, zebra_route_string (api.type), inet_ntop (AF_INET, - &p.prefix, - buf[0], - sizeof (buf - [0])), - p.prefixlen, inet_ntop (AF_INET, &nexthop, buf[1], - sizeof (buf[1])), api.metric); - } - vnc_redistribute_add ((struct prefix *) &p, &nexthop, api.metric, - api.type); - } - else - { - if (BGP_DEBUG (zebra, ZEBRA)) - { - char buf[2][INET_ADDRSTRLEN]; - vnc_zlog_debug_verbose ("%s: Zebra rcvd: IPv4 route delete %s %s/%d " - "nexthop %s metric %u", - __func__, - zebra_route_string (api.type), - inet_ntop (AF_INET, &p.prefix, buf[0], sizeof (buf[0])), - p.prefixlen, - inet_ntop (AF_INET, &nexthop, buf[1], sizeof (buf[1])), - api.metric); - } - vnc_redistribute_delete ((struct prefix *) &p, api.type); - } - - return 0; + struct stream *s; + struct zapi_ipv4 api; + struct in_addr nexthop; + struct prefix_ipv4 p; + + s = zclient->ibuf; + nexthop.s_addr = 0; + + /* Type, flags, message. */ + api.type = stream_getc(s); + api.flags = stream_getc(s); + api.message = stream_getc(s); + + /* IPv4 prefix. */ + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefixlen = stream_getc(s); + stream_get(&p.prefix, s, PSIZE(p.prefixlen)); + + /* Nexthop, ifindex, distance, metric. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { + api.nexthop_num = stream_getc(s); + nexthop.s_addr = stream_get_ipv4(s); + } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { + api.ifindex_num = stream_getc(s); + stream_getl(s); + } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) + api.distance = stream_getc(s); + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) + api.metric = stream_getl(s); + else + api.metric = 0; + + if (command == ZEBRA_IPV4_ROUTE_ADD) { + if (BGP_DEBUG(zebra, ZEBRA)) { + char buf[2][INET_ADDRSTRLEN]; + vnc_zlog_debug_verbose( + "%s: Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u", + __func__, zebra_route_string(api.type), + inet_ntop(AF_INET, &p.prefix, buf[0], + sizeof(buf[0])), + p.prefixlen, inet_ntop(AF_INET, &nexthop, + buf[1], sizeof(buf[1])), + api.metric); + } + vnc_redistribute_add((struct prefix *)&p, &nexthop, api.metric, + api.type); + } else { + if (BGP_DEBUG(zebra, ZEBRA)) { + char buf[2][INET_ADDRSTRLEN]; + vnc_zlog_debug_verbose( + "%s: Zebra rcvd: IPv4 route delete %s %s/%d " + "nexthop %s metric %u", + __func__, zebra_route_string(api.type), + inet_ntop(AF_INET, &p.prefix, buf[0], + sizeof(buf[0])), + p.prefixlen, inet_ntop(AF_INET, &nexthop, + buf[1], sizeof(buf[1])), + api.metric); + } + vnc_redistribute_delete((struct prefix *)&p, api.type); + } + + return 0; } /* Zebra route add and delete treatment. */ -static int -vnc_zebra_read_ipv6 ( - int command, - struct zclient *zclient, - zebra_size_t length, - vrf_id_t vrf_id) +static int vnc_zebra_read_ipv6(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv6 api; - struct in6_addr nexthop; - struct prefix_ipv6 p, src_p; - - s = zclient->ibuf; - memset (&nexthop, 0, sizeof (struct in6_addr)); - - /* Type, flags, message. */ - api.type = stream_getc (s); - api.flags = stream_getc (s); - api.message = stream_getc (s); - - /* IPv6 prefix. */ - memset (&p, 0, sizeof (struct prefix_ipv6)); - p.family = AF_INET6; - p.prefixlen = stream_getc (s); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); - - memset (&src_p, 0, sizeof (struct prefix_ipv6)); - src_p.family = AF_INET6; - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_SRCPFX)) - { - src_p.prefixlen = stream_getc (s); - stream_get (&src_p.prefix, s, PSIZE (src_p.prefixlen)); - } - - if (src_p.prefixlen) - /* we completely ignore srcdest routes for now. */ - return 0; - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) - { - api.nexthop_num = stream_getc (s); - stream_get (&nexthop, s, 16); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) - { - api.ifindex_num = stream_getc (s); - stream_getl (s); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc (s); - else - api.distance = 0; - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl (s); - else - api.metric = 0; - - /* Simply ignore link-local address. */ - if (IN6_IS_ADDR_LINKLOCAL (&p.prefix)) - return 0; - - if (command == ZEBRA_IPV6_ROUTE_ADD) - { - if (BGP_DEBUG (zebra, ZEBRA)) - { - char buf[INET6_ADDRSTRLEN]; - vnc_zlog_debug_verbose ("Zebra rcvd: IPv6 route add %s %s/%d metric %u", - zebra_route_string (api.type), - inet_ntop (AF_INET6, &p.prefix, buf, sizeof (buf)), - p.prefixlen, api.metric); - } - vnc_redistribute_add ((struct prefix *) &p, NULL, api.metric, api.type); - } - else - { - if (BGP_DEBUG (zebra, ZEBRA)) - { - char buf[INET6_ADDRSTRLEN]; - vnc_zlog_debug_verbose ("Zebra rcvd: IPv6 route delete %s %s/%d metric %u", - zebra_route_string (api.type), - inet_ntop (AF_INET6, &p.prefix, buf, sizeof (buf)), - p.prefixlen, api.metric); - } - vnc_redistribute_delete ((struct prefix *) &p, api.type); - } - - return 0; + struct stream *s; + struct zapi_ipv6 api; + struct in6_addr nexthop; + struct prefix_ipv6 p, src_p; + + s = zclient->ibuf; + memset(&nexthop, 0, sizeof(struct in6_addr)); + + /* Type, flags, message. */ + api.type = stream_getc(s); + api.flags = stream_getc(s); + api.message = stream_getc(s); + + /* IPv6 prefix. */ + memset(&p, 0, sizeof(struct prefix_ipv6)); + p.family = AF_INET6; + p.prefixlen = stream_getc(s); + stream_get(&p.prefix, s, PSIZE(p.prefixlen)); + + memset(&src_p, 0, sizeof(struct prefix_ipv6)); + src_p.family = AF_INET6; + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { + src_p.prefixlen = stream_getc(s); + stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen)); + } + + if (src_p.prefixlen) + /* we completely ignore srcdest routes for now. */ + return 0; + + /* Nexthop, ifindex, distance, metric. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { + api.nexthop_num = stream_getc(s); + stream_get(&nexthop, s, 16); + } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { + api.ifindex_num = stream_getc(s); + stream_getl(s); + } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) + api.distance = stream_getc(s); + else + api.distance = 0; + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) + api.metric = stream_getl(s); + else + api.metric = 0; + + /* Simply ignore link-local address. */ + if (IN6_IS_ADDR_LINKLOCAL(&p.prefix)) + return 0; + + if (command == ZEBRA_IPV6_ROUTE_ADD) { + if (BGP_DEBUG(zebra, ZEBRA)) { + char buf[INET6_ADDRSTRLEN]; + vnc_zlog_debug_verbose( + "Zebra rcvd: IPv6 route add %s %s/%d metric %u", + zebra_route_string(api.type), + inet_ntop(AF_INET6, &p.prefix, buf, + sizeof(buf)), + p.prefixlen, api.metric); + } + vnc_redistribute_add((struct prefix *)&p, NULL, api.metric, + api.type); + } else { + if (BGP_DEBUG(zebra, ZEBRA)) { + char buf[INET6_ADDRSTRLEN]; + vnc_zlog_debug_verbose( + "Zebra rcvd: IPv6 route delete %s %s/%d metric %u", + zebra_route_string(api.type), + inet_ntop(AF_INET6, &p.prefix, buf, + sizeof(buf)), + p.prefixlen, api.metric); + } + vnc_redistribute_delete((struct prefix *)&p, api.type); + } + + return 0; } /*********************************************************************** @@ -519,509 +491,465 @@ vnc_zebra_read_ipv6 ( /* * low-level message builder */ -static void -vnc_zebra_route_msg ( - struct prefix *p, - int nhp_count, - void *nhp_ary, - int add) /* 1 = add, 0 = del */ +static void vnc_zebra_route_msg(struct prefix *p, int nhp_count, void *nhp_ary, + int add) /* 1 = add, 0 = del */ { - if (!nhp_count) - { - vnc_zlog_debug_verbose ("%s: empty nexthop list, skipping", __func__); - return; - } - - if (p->family == AF_INET) - { - - struct zapi_ipv4 api; - - api.flags = 0; - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_VNC; - api.message = 0; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); /* TBD what's it mean? */ - api.nexthop_num = nhp_count; - api.nexthop = nhp_ary; - api.ifindex_num = 0; - api.instance = 0; - api.safi = SAFI_UNICAST; - - if (BGP_DEBUG (zebra, ZEBRA)) - { - - char buf[INET_ADDRSTRLEN]; - vnc_zlog_debug_verbose ("%s: Zebra send: IPv4 route %s %s/%d, nhp_count=%d", - __func__, - (add ? "add" : "del"), - inet_ntop (AF_INET, &p->u.prefix4, buf, sizeof (buf)), - p->prefixlen, nhp_count); - } - - zapi_ipv4_route ((add ? ZEBRA_IPV4_NEXTHOP_ADD : - ZEBRA_IPV4_NEXTHOP_DELETE), zclient_vnc, - (struct prefix_ipv4 *) p, &api); - - } - else if (p->family == AF_INET6) - { - - struct zapi_ipv6 api; - ifindex_t ifindex = 0; - - /* Make Zebra API structure. */ - api.flags = 0; - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_VNC; - api.message = 0; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); /* TBD means? */ - api.nexthop_num = nhp_count; - api.nexthop = nhp_ary; - SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); - api.ifindex_num = 1; - api.ifindex = &ifindex; - api.instance = 0; - api.safi = SAFI_UNICAST; - - if (BGP_DEBUG (zebra, ZEBRA)) - { - - char buf[INET6_ADDRSTRLEN]; - vnc_zlog_debug_verbose ("%s: Zebra send: IPv6 route %s %s/%d nhp_count=%d", - __func__, - (add ? "add" : "del"), - inet_ntop (AF_INET6, &p->u.prefix6, buf, sizeof (buf)), - p->prefixlen, nhp_count); - } - - zapi_ipv6_route ((add ? ZEBRA_IPV6_NEXTHOP_ADD : - ZEBRA_IPV6_NEXTHOP_DELETE), zclient_vnc, - (struct prefix_ipv6 *) p, NULL, &api); - } - else - { - vnc_zlog_debug_verbose ("%s: unknown prefix address family, skipping", __func__); - return; - } + if (!nhp_count) { + vnc_zlog_debug_verbose("%s: empty nexthop list, skipping", + __func__); + return; + } + + if (p->family == AF_INET) { + + struct zapi_ipv4 api; + + api.flags = 0; + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_VNC; + api.message = 0; + SET_FLAG(api.message, + ZAPI_MESSAGE_NEXTHOP); /* TBD what's it mean? */ + api.nexthop_num = nhp_count; + api.nexthop = nhp_ary; + api.ifindex_num = 0; + api.instance = 0; + api.safi = SAFI_UNICAST; + + if (BGP_DEBUG(zebra, ZEBRA)) { + + char buf[INET_ADDRSTRLEN]; + vnc_zlog_debug_verbose( + "%s: Zebra send: IPv4 route %s %s/%d, nhp_count=%d", + __func__, (add ? "add" : "del"), + inet_ntop(AF_INET, &p->u.prefix4, buf, + sizeof(buf)), + p->prefixlen, nhp_count); + } + + zapi_ipv4_route((add ? ZEBRA_IPV4_NEXTHOP_ADD + : ZEBRA_IPV4_NEXTHOP_DELETE), + zclient_vnc, (struct prefix_ipv4 *)p, &api); + + } else if (p->family == AF_INET6) { + + struct zapi_ipv6 api; + ifindex_t ifindex = 0; + + /* Make Zebra API structure. */ + api.flags = 0; + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_VNC; + api.message = 0; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); /* TBD means? */ + api.nexthop_num = nhp_count; + api.nexthop = nhp_ary; + SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); + api.ifindex_num = 1; + api.ifindex = &ifindex; + api.instance = 0; + api.safi = SAFI_UNICAST; + + if (BGP_DEBUG(zebra, ZEBRA)) { + + char buf[INET6_ADDRSTRLEN]; + vnc_zlog_debug_verbose( + "%s: Zebra send: IPv6 route %s %s/%d nhp_count=%d", + __func__, (add ? "add" : "del"), + inet_ntop(AF_INET6, &p->u.prefix6, buf, + sizeof(buf)), + p->prefixlen, nhp_count); + } + + zapi_ipv6_route((add ? ZEBRA_IPV6_NEXTHOP_ADD + : ZEBRA_IPV6_NEXTHOP_DELETE), + zclient_vnc, (struct prefix_ipv6 *)p, NULL, + &api); + } else { + vnc_zlog_debug_verbose( + "%s: unknown prefix address family, skipping", + __func__); + return; + } } static void -nve_list_to_nh_array ( - u_char family, - struct list *nve_list, - int *nh_count_ret, - void **nh_ary_ret, /* returned address array */ - void **nhp_ary_ret) /* returned pointer array */ +nve_list_to_nh_array(u_char family, struct list *nve_list, int *nh_count_ret, + void **nh_ary_ret, /* returned address array */ + void **nhp_ary_ret) /* returned pointer array */ { - int nve_count = listcount (nve_list); + int nve_count = listcount(nve_list); - *nh_count_ret = 0; - *nh_ary_ret = NULL; - *nhp_ary_ret = NULL; + *nh_count_ret = 0; + *nh_ary_ret = NULL; + *nhp_ary_ret = NULL; - if (!nve_count) - { - vnc_zlog_debug_verbose ("%s: empty nve_list, skipping", __func__); - return; - } + if (!nve_count) { + vnc_zlog_debug_verbose("%s: empty nve_list, skipping", + __func__); + return; + } - if (family == AF_INET) - { - struct listnode *ln; - struct in_addr *iap; - struct in_addr **v; + if (family == AF_INET) { + struct listnode *ln; + struct in_addr *iap; + struct in_addr **v; - /* - * Array of nexthop addresses - */ - *nh_ary_ret = XCALLOC (MTYPE_TMP, nve_count * sizeof (struct in_addr)); + /* + * Array of nexthop addresses + */ + *nh_ary_ret = + XCALLOC(MTYPE_TMP, nve_count * sizeof(struct in_addr)); - /* - * Array of pointers to nexthop addresses - */ - *nhp_ary_ret = - XCALLOC (MTYPE_TMP, nve_count * sizeof (struct in_addr *)); - iap = *nh_ary_ret; - v = *nhp_ary_ret; + /* + * Array of pointers to nexthop addresses + */ + *nhp_ary_ret = XCALLOC(MTYPE_TMP, + nve_count * sizeof(struct in_addr *)); + iap = *nh_ary_ret; + v = *nhp_ary_ret; - for (ln = listhead (nve_list); ln; ln = listnextnode (ln)) - { + for (ln = listhead(nve_list); ln; ln = listnextnode(ln)) { - struct rfapi_descriptor *irfd; - struct prefix nhp; + struct rfapi_descriptor *irfd; + struct prefix nhp; - irfd = listgetdata (ln); + irfd = listgetdata(ln); - if (rfapiRaddr2Qprefix (&irfd->vn_addr, &nhp)) - continue; + if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp)) + continue; - *iap = nhp.u.prefix4; - *v = iap; - vnc_zlog_debug_verbose ("%s: ipadr: (%p)<-0x%x, ptr: (%p)<-%p", - __func__, iap, nhp.u.prefix4.s_addr, v, iap); + *iap = nhp.u.prefix4; + *v = iap; + vnc_zlog_debug_verbose( + "%s: ipadr: (%p)<-0x%x, ptr: (%p)<-%p", + __func__, iap, nhp.u.prefix4.s_addr, v, iap); - ++iap; - ++v; - ++*nh_count_ret; - } + ++iap; + ++v; + ++*nh_count_ret; + } - } - else if (family == AF_INET6) - { + } else if (family == AF_INET6) { - struct listnode *ln; + struct listnode *ln; - *nh_ary_ret = XCALLOC (MTYPE_TMP, nve_count * sizeof (struct in6_addr)); + *nh_ary_ret = + XCALLOC(MTYPE_TMP, nve_count * sizeof(struct in6_addr)); - *nhp_ary_ret = XCALLOC (MTYPE_TMP, - nve_count * sizeof (struct in6_addr *)); + *nhp_ary_ret = XCALLOC(MTYPE_TMP, + nve_count * sizeof(struct in6_addr *)); - for (ln = listhead (nve_list); ln; ln = listnextnode (ln)) - { + for (ln = listhead(nve_list); ln; ln = listnextnode(ln)) { - struct rfapi_descriptor *irfd; - struct in6_addr *iap = *nh_ary_ret; - struct in6_addr **v = *nhp_ary_ret; - struct prefix nhp; + struct rfapi_descriptor *irfd; + struct in6_addr *iap = *nh_ary_ret; + struct in6_addr **v = *nhp_ary_ret; + struct prefix nhp; - irfd = listgetdata (ln); + irfd = listgetdata(ln); - if (rfapiRaddr2Qprefix (&irfd->vn_addr, &nhp)) - continue; + if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp)) + continue; - *iap = nhp.u.prefix6; - *v = iap; + *iap = nhp.u.prefix6; + *v = iap; - ++iap; - ++v; - ++*nh_count_ret; - } - } + ++iap; + ++v; + ++*nh_count_ret; + } + } } -static void -import_table_to_nve_list_zebra ( - struct bgp *bgp, - struct rfapi_import_table *it, - struct list **nves, - uint8_t family) +static void import_table_to_nve_list_zebra(struct bgp *bgp, + struct rfapi_import_table *it, + struct list **nves, uint8_t family) { - struct listnode *node; - struct rfapi_rfg_name *rfgn; - - /* - * Loop over the list of NVE-Groups configured for - * exporting to direct-bgp. - * - * Build a list of NVEs that use this import table - */ - *nves = NULL; - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_zebra_l, node, rfgn)) - { - - /* - * If this NVE-Group's import table matches the current one - */ - if (rfgn->rfg && rfgn->rfg->nves && rfgn->rfg->rfapi_import_table == it) - { - - nve_group_to_nve_list (rfgn->rfg, nves, family); - } - } + struct listnode *node; + struct rfapi_rfg_name *rfgn; + + /* + * Loop over the list of NVE-Groups configured for + * exporting to direct-bgp. + * + * Build a list of NVEs that use this import table + */ + *nves = NULL; + for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_zebra_l, node, + rfgn)) { + + /* + * If this NVE-Group's import table matches the current one + */ + if (rfgn->rfg && rfgn->rfg->nves + && rfgn->rfg->rfapi_import_table == it) { + + nve_group_to_nve_list(rfgn->rfg, nves, family); + } + } } -static void -vnc_zebra_add_del_prefix ( - struct bgp *bgp, - struct rfapi_import_table *import_table, - struct route_node *rn, - int add) /* !0 = add, 0 = del */ +static void vnc_zebra_add_del_prefix(struct bgp *bgp, + struct rfapi_import_table *import_table, + struct route_node *rn, + int add) /* !0 = add, 0 = del */ { - struct list *nves; - - int nexthop_count = 0; - void *nh_ary = NULL; - void *nhp_ary = NULL; - - vnc_zlog_debug_verbose ("%s: entry, add=%d", __func__, add); - - if (zclient_vnc->sock < 0) - return; - - if (rn->p.family != AF_INET - && rn->p.family != AF_INET6) - { - zlog_err ("%s: invalid route node addr family", __func__); - return; - } - - if (!zclient_vnc->redist[family2afi(rn->p.family)][ZEBRA_ROUTE_VNC]) - return; - - if (!bgp->rfapi_cfg) - { - vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__); - return; - } - if (!listcount (bgp->rfapi_cfg->rfg_export_zebra_l)) - { - vnc_zlog_debug_verbose ("%s: no zebra export nve group, skipping", __func__); - return; - } - - import_table_to_nve_list_zebra (bgp, import_table, &nves, rn->p.family); - - if (nves) - { - nve_list_to_nh_array (rn->p.family, - nves, &nexthop_count, &nh_ary, &nhp_ary); - - list_delete (nves); - - if (nexthop_count) - vnc_zebra_route_msg (&rn->p, nexthop_count, nhp_ary, add); - } - - if (nhp_ary) - XFREE (MTYPE_TMP, nhp_ary); - if (nh_ary) - XFREE (MTYPE_TMP, nh_ary); + struct list *nves; + + int nexthop_count = 0; + void *nh_ary = NULL; + void *nhp_ary = NULL; + + vnc_zlog_debug_verbose("%s: entry, add=%d", __func__, add); + + if (zclient_vnc->sock < 0) + return; + + if (rn->p.family != AF_INET && rn->p.family != AF_INET6) { + zlog_err("%s: invalid route node addr family", __func__); + return; + } + + if (!zclient_vnc->redist[family2afi(rn->p.family)][ZEBRA_ROUTE_VNC]) + return; + + if (!bgp->rfapi_cfg) { + vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", + __func__); + return; + } + if (!listcount(bgp->rfapi_cfg->rfg_export_zebra_l)) { + vnc_zlog_debug_verbose( + "%s: no zebra export nve group, skipping", __func__); + return; + } + + import_table_to_nve_list_zebra(bgp, import_table, &nves, rn->p.family); + + if (nves) { + nve_list_to_nh_array(rn->p.family, nves, &nexthop_count, + &nh_ary, &nhp_ary); + + list_delete(nves); + + if (nexthop_count) + vnc_zebra_route_msg(&rn->p, nexthop_count, nhp_ary, + add); + } + + if (nhp_ary) + XFREE(MTYPE_TMP, nhp_ary); + if (nh_ary) + XFREE(MTYPE_TMP, nh_ary); } -void -vnc_zebra_add_prefix ( - struct bgp *bgp, - struct rfapi_import_table *import_table, - struct route_node *rn) +void vnc_zebra_add_prefix(struct bgp *bgp, + struct rfapi_import_table *import_table, + struct route_node *rn) { - vnc_zebra_add_del_prefix (bgp, import_table, rn, 1); + vnc_zebra_add_del_prefix(bgp, import_table, rn, 1); } -void -vnc_zebra_del_prefix ( - struct bgp *bgp, - struct rfapi_import_table *import_table, - struct route_node *rn) +void vnc_zebra_del_prefix(struct bgp *bgp, + struct rfapi_import_table *import_table, + struct route_node *rn) { - vnc_zebra_add_del_prefix (bgp, import_table, rn, 0); + vnc_zebra_add_del_prefix(bgp, import_table, rn, 0); } - -static void -vnc_zebra_add_del_nve ( - struct bgp *bgp, - struct rfapi_descriptor *rfd, - int add) /* 0 = del, !0 = add */ +static void vnc_zebra_add_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd, + int add) /* 0 = del, !0 = add */ { - struct listnode *node; - struct rfapi_rfg_name *rfgn; - struct rfapi_nve_group_cfg *rfg = rfd->rfg; - afi_t afi = family2afi (rfd->vn_addr.addr_family); - struct prefix nhp; -// struct prefix *nhpp; - void *pAddr; - - vnc_zlog_debug_verbose ("%s: entry, add=%d", __func__, add); - - if (zclient_vnc->sock < 0) - return; - - if (!zclient_vnc->redist[afi][ZEBRA_ROUTE_VNC]) - return; - - if (afi != AFI_IP && afi != AFI_IP6) - { - zlog_err ("%s: invalid vn addr family", __func__); - return; - } - - if (!bgp) - return; - if (!bgp->rfapi_cfg) - { - vnc_zlog_debug_verbose ("%s: bgp->rfapi_cfg is NULL, skipping", __func__); - return; - } - - if (rfapiRaddr2Qprefix (&rfd->vn_addr, &nhp)) - { - vnc_zlog_debug_verbose ("%s: can't convert vn address, skipping", __func__); - return; - } - - pAddr = &nhp.u.prefix4; - - /* - * Loop over the list of NVE-Groups configured for - * exporting to zebra and see if this new NVE's - * group is among them. - */ - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_zebra_l, node, rfgn)) - { - - /* - * Yes, this NVE's group is configured for export to zebra - */ - if (rfgn->rfg == rfg) - { - - struct route_table *rt = NULL; - struct route_node *rn; - struct rfapi_import_table *import_table; - import_table = rfg->rfapi_import_table; - - vnc_zlog_debug_verbose ("%s: this nve's group is in zebra export list", - __func__); - - rt = import_table->imported_vpn[afi]; - - /* - * Walk the NVE-Group's VNC Import table - */ - for (rn = route_top (rt); rn; rn = route_next (rn)) - { - - if (rn->info) - { - - vnc_zlog_debug_verbose ("%s: sending %s", __func__, - (add ? "add" : "del")); - vnc_zebra_route_msg (&rn->p, 1, &pAddr, add); - } - } - } - } + struct listnode *node; + struct rfapi_rfg_name *rfgn; + struct rfapi_nve_group_cfg *rfg = rfd->rfg; + afi_t afi = family2afi(rfd->vn_addr.addr_family); + struct prefix nhp; + // struct prefix *nhpp; + void *pAddr; + + vnc_zlog_debug_verbose("%s: entry, add=%d", __func__, add); + + if (zclient_vnc->sock < 0) + return; + + if (!zclient_vnc->redist[afi][ZEBRA_ROUTE_VNC]) + return; + + if (afi != AFI_IP && afi != AFI_IP6) { + zlog_err("%s: invalid vn addr family", __func__); + return; + } + + if (!bgp) + return; + if (!bgp->rfapi_cfg) { + vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", + __func__); + return; + } + + if (rfapiRaddr2Qprefix(&rfd->vn_addr, &nhp)) { + vnc_zlog_debug_verbose("%s: can't convert vn address, skipping", + __func__); + return; + } + + pAddr = &nhp.u.prefix4; + + /* + * Loop over the list of NVE-Groups configured for + * exporting to zebra and see if this new NVE's + * group is among them. + */ + for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_zebra_l, node, + rfgn)) { + + /* + * Yes, this NVE's group is configured for export to zebra + */ + if (rfgn->rfg == rfg) { + + struct route_table *rt = NULL; + struct route_node *rn; + struct rfapi_import_table *import_table; + import_table = rfg->rfapi_import_table; + + vnc_zlog_debug_verbose( + "%s: this nve's group is in zebra export list", + __func__); + + rt = import_table->imported_vpn[afi]; + + /* + * Walk the NVE-Group's VNC Import table + */ + for (rn = route_top(rt); rn; rn = route_next(rn)) { + + if (rn->info) { + + vnc_zlog_debug_verbose( + "%s: sending %s", __func__, + (add ? "add" : "del")); + vnc_zebra_route_msg(&rn->p, 1, &pAddr, + add); + } + } + } + } } -void -vnc_zebra_add_nve (struct bgp *bgp, struct rfapi_descriptor *rfd) +void vnc_zebra_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd) { - vnc_zebra_add_del_nve (bgp, rfd, 1); + vnc_zebra_add_del_nve(bgp, rfd, 1); } -void -vnc_zebra_del_nve (struct bgp *bgp, struct rfapi_descriptor *rfd) +void vnc_zebra_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd) { - vnc_zebra_add_del_nve (bgp, rfd, 0); + vnc_zebra_add_del_nve(bgp, rfd, 0); } -static void -vnc_zebra_add_del_group_afi ( - struct bgp *bgp, - struct rfapi_nve_group_cfg *rfg, - afi_t afi, - int add) +static void vnc_zebra_add_del_group_afi(struct bgp *bgp, + struct rfapi_nve_group_cfg *rfg, + afi_t afi, int add) { - struct route_table *rt = NULL; - struct route_node *rn; - struct rfapi_import_table *import_table; - uint8_t family = afi2family (afi); - - struct list *nves = NULL; - int nexthop_count = 0; - void *nh_ary = NULL; - void *nhp_ary = NULL; - - vnc_zlog_debug_verbose ("%s: entry", __func__); - import_table = rfg->rfapi_import_table; - if (!import_table) - { - vnc_zlog_debug_verbose ("%s: import table not defined, returning", __func__); - return; - } - - if (afi == AFI_IP - || afi == AFI_IP6) - { - rt = import_table->imported_vpn[afi]; - } - else - { - zlog_err ("%s: bad afi %d", __func__, afi); - return; - } - - if (!family) - { - zlog_err ("%s: computed bad family: %d", __func__, family); - return; - } - - if (!rfg->nves) - { - /* avoid segfault below if list doesn't exist */ - vnc_zlog_debug_verbose ("%s: no NVEs in this group", __func__); - return; - } - - nve_group_to_nve_list (rfg, &nves, family); - if (nves) - { - vnc_zlog_debug_verbose ("%s: have nves", __func__); - nve_list_to_nh_array (family, nves, &nexthop_count, &nh_ary, &nhp_ary); - - vnc_zlog_debug_verbose ("%s: family: %d, nve count: %d", __func__, family, - nexthop_count); - - list_delete (nves); - - if (nexthop_count) - { - /* - * Walk the NVE-Group's VNC Import table - */ - for (rn = route_top (rt); rn; rn = route_next (rn)) - { - if (rn->info) - { - vnc_zebra_route_msg (&rn->p, nexthop_count, nhp_ary, add); - } - } - } - if (nhp_ary) - XFREE (MTYPE_TMP, nhp_ary); - if (nh_ary) - XFREE (MTYPE_TMP, nh_ary); - } + struct route_table *rt = NULL; + struct route_node *rn; + struct rfapi_import_table *import_table; + uint8_t family = afi2family(afi); + + struct list *nves = NULL; + int nexthop_count = 0; + void *nh_ary = NULL; + void *nhp_ary = NULL; + + vnc_zlog_debug_verbose("%s: entry", __func__); + import_table = rfg->rfapi_import_table; + if (!import_table) { + vnc_zlog_debug_verbose( + "%s: import table not defined, returning", __func__); + return; + } + + if (afi == AFI_IP || afi == AFI_IP6) { + rt = import_table->imported_vpn[afi]; + } else { + zlog_err("%s: bad afi %d", __func__, afi); + return; + } + + if (!family) { + zlog_err("%s: computed bad family: %d", __func__, family); + return; + } + + if (!rfg->nves) { + /* avoid segfault below if list doesn't exist */ + vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__); + return; + } + + nve_group_to_nve_list(rfg, &nves, family); + if (nves) { + vnc_zlog_debug_verbose("%s: have nves", __func__); + nve_list_to_nh_array(family, nves, &nexthop_count, &nh_ary, + &nhp_ary); + + vnc_zlog_debug_verbose("%s: family: %d, nve count: %d", + __func__, family, nexthop_count); + + list_delete(nves); + + if (nexthop_count) { + /* + * Walk the NVE-Group's VNC Import table + */ + for (rn = route_top(rt); rn; rn = route_next(rn)) { + if (rn->info) { + vnc_zebra_route_msg(&rn->p, + nexthop_count, + nhp_ary, add); + } + } + } + if (nhp_ary) + XFREE(MTYPE_TMP, nhp_ary); + if (nh_ary) + XFREE(MTYPE_TMP, nh_ary); + } } -void -vnc_zebra_add_group (struct bgp *bgp, struct rfapi_nve_group_cfg *rfg) +void vnc_zebra_add_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg) { - vnc_zebra_add_del_group_afi (bgp, rfg, AFI_IP, 1); - vnc_zebra_add_del_group_afi (bgp, rfg, AFI_IP6, 1); + vnc_zebra_add_del_group_afi(bgp, rfg, AFI_IP, 1); + vnc_zebra_add_del_group_afi(bgp, rfg, AFI_IP6, 1); } -void -vnc_zebra_del_group (struct bgp *bgp, struct rfapi_nve_group_cfg *rfg) +void vnc_zebra_del_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg) { - vnc_zlog_debug_verbose ("%s: entry", __func__); - vnc_zebra_add_del_group_afi (bgp, rfg, AFI_IP, 0); - vnc_zebra_add_del_group_afi (bgp, rfg, AFI_IP6, 0); + vnc_zlog_debug_verbose("%s: entry", __func__); + vnc_zebra_add_del_group_afi(bgp, rfg, AFI_IP, 0); + vnc_zebra_add_del_group_afi(bgp, rfg, AFI_IP6, 0); } -void -vnc_zebra_reexport_group_afi ( - struct bgp *bgp, - struct rfapi_nve_group_cfg *rfg, - afi_t afi) +void vnc_zebra_reexport_group_afi(struct bgp *bgp, + struct rfapi_nve_group_cfg *rfg, afi_t afi) { - struct listnode *node; - struct rfapi_rfg_name *rfgn; - - for (ALL_LIST_ELEMENTS_RO (bgp->rfapi_cfg->rfg_export_zebra_l, node, rfgn)) - { - - if (rfgn->rfg == rfg) - { - vnc_zebra_add_del_group_afi (bgp, rfg, afi, 0); - vnc_zebra_add_del_group_afi (bgp, rfg, afi, 1); - break; - } - } + struct listnode *node; + struct rfapi_rfg_name *rfgn; + + for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_zebra_l, node, + rfgn)) { + + if (rfgn->rfg == rfg) { + vnc_zebra_add_del_group_afi(bgp, rfg, afi, 0); + vnc_zebra_add_del_group_afi(bgp, rfg, afi, 1); + break; + } + } } @@ -1031,77 +959,76 @@ vnc_zebra_reexport_group_afi ( /* Other routes redistribution into BGP. */ -int -vnc_redistribute_set (struct bgp *bgp, afi_t afi, int type) +int vnc_redistribute_set(struct bgp *bgp, afi_t afi, int type) { - if (!bgp->rfapi_cfg) - { - return CMD_WARNING_CONFIG_FAILED; - } + if (!bgp->rfapi_cfg) { + return CMD_WARNING_CONFIG_FAILED; + } - /* Set flag to BGP instance. */ - bgp->rfapi_cfg->redist[afi][type] = 1; + /* Set flag to BGP instance. */ + bgp->rfapi_cfg->redist[afi][type] = 1; -// bgp->redist[afi][type] = 1; + // bgp->redist[afi][type] = 1; - /* Return if already redistribute flag is set. */ - if (zclient_vnc->redist[afi][type]) - return CMD_WARNING_CONFIG_FAILED; + /* Return if already redistribute flag is set. */ + if (zclient_vnc->redist[afi][type]) + return CMD_WARNING_CONFIG_FAILED; - vrf_bitmap_set (zclient_vnc->redist[afi][type], VRF_DEFAULT); + vrf_bitmap_set(zclient_vnc->redist[afi][type], VRF_DEFAULT); - //zclient_vnc->redist[afi][type] = 1; + // zclient_vnc->redist[afi][type] = 1; - /* Return if zebra connection is not established. */ - if (zclient_vnc->sock < 0) - return CMD_WARNING_CONFIG_FAILED; + /* Return if zebra connection is not established. */ + if (zclient_vnc->sock < 0) + return CMD_WARNING_CONFIG_FAILED; - if (BGP_DEBUG (zebra, ZEBRA)) - vnc_zlog_debug_verbose ("Zebra send: redistribute add %s", zebra_route_string (type)); + if (BGP_DEBUG(zebra, ZEBRA)) + vnc_zlog_debug_verbose("Zebra send: redistribute add %s", + zebra_route_string(type)); - /* Send distribute add message to zebra. */ - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient_vnc, afi, type, 0, VRF_DEFAULT); + /* Send distribute add message to zebra. */ + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient_vnc, afi, type, + 0, VRF_DEFAULT); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Unset redistribution. */ -int -vnc_redistribute_unset (struct bgp *bgp, afi_t afi, int type) +int vnc_redistribute_unset(struct bgp *bgp, afi_t afi, int type) { - vnc_zlog_debug_verbose ("%s: type=%d entry", __func__, type); - - if (!bgp->rfapi_cfg) - { - vnc_zlog_debug_verbose ("%s: return (no rfapi_cfg)", __func__); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Unset flag from BGP instance. */ - bgp->rfapi_cfg->redist[afi][type] = 0; - - /* Return if zebra connection is disabled. */ - if (!zclient_vnc->redist[afi][type]) - return CMD_WARNING_CONFIG_FAILED; - zclient_vnc->redist[afi][type] = 0; - - if (bgp->rfapi_cfg->redist[AFI_IP][type] == 0 - && bgp->rfapi_cfg->redist[AFI_IP6][type] == 0 && zclient_vnc->sock >= 0) - { - /* Send distribute delete message to zebra. */ - if (BGP_DEBUG (zebra, ZEBRA)) - vnc_zlog_debug_verbose ("Zebra send: redistribute delete %s", - zebra_route_string (type)); - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient_vnc, afi, type, - 0, VRF_DEFAULT); - } - - /* Withdraw redistributed routes from current BGP's routing table. */ - vnc_redistribute_withdraw (bgp, afi, type); - - vnc_zlog_debug_verbose ("%s: return", __func__); - - return CMD_SUCCESS; + vnc_zlog_debug_verbose("%s: type=%d entry", __func__, type); + + if (!bgp->rfapi_cfg) { + vnc_zlog_debug_verbose("%s: return (no rfapi_cfg)", __func__); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Unset flag from BGP instance. */ + bgp->rfapi_cfg->redist[afi][type] = 0; + + /* Return if zebra connection is disabled. */ + if (!zclient_vnc->redist[afi][type]) + return CMD_WARNING_CONFIG_FAILED; + zclient_vnc->redist[afi][type] = 0; + + if (bgp->rfapi_cfg->redist[AFI_IP][type] == 0 + && bgp->rfapi_cfg->redist[AFI_IP6][type] == 0 + && zclient_vnc->sock >= 0) { + /* Send distribute delete message to zebra. */ + if (BGP_DEBUG(zebra, ZEBRA)) + vnc_zlog_debug_verbose( + "Zebra send: redistribute delete %s", + zebra_route_string(type)); + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient_vnc, + afi, type, 0, VRF_DEFAULT); + } + + /* Withdraw redistributed routes from current BGP's routing table. */ + vnc_redistribute_withdraw(bgp, afi, type); + + vnc_zlog_debug_verbose("%s: return", __func__); + + return CMD_SUCCESS; } @@ -1109,25 +1036,23 @@ vnc_redistribute_unset (struct bgp *bgp, afi_t afi, int type) * Modeled after bgp_zebra.c'bgp_zebra_init() * Charriere asks, "Is it possible to carry two?" */ -void -vnc_zebra_init (struct thread_master *master) +void vnc_zebra_init(struct thread_master *master) { - /* Set default values. */ - zclient_vnc = zclient_new (master); - zclient_init (zclient_vnc, ZEBRA_ROUTE_VNC, 0); - - zclient_vnc->redistribute_route_ipv4_add = vnc_zebra_read_ipv4; - zclient_vnc->redistribute_route_ipv4_del = vnc_zebra_read_ipv4; - zclient_vnc->redistribute_route_ipv6_add = vnc_zebra_read_ipv6; - zclient_vnc->redistribute_route_ipv6_del = vnc_zebra_read_ipv6; + /* Set default values. */ + zclient_vnc = zclient_new(master); + zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0); + + zclient_vnc->redistribute_route_ipv4_add = vnc_zebra_read_ipv4; + zclient_vnc->redistribute_route_ipv4_del = vnc_zebra_read_ipv4; + zclient_vnc->redistribute_route_ipv6_add = vnc_zebra_read_ipv6; + zclient_vnc->redistribute_route_ipv6_del = vnc_zebra_read_ipv6; } -void -vnc_zebra_destroy (void) +void vnc_zebra_destroy(void) { - if (zclient_vnc == NULL) - return; - zclient_stop (zclient_vnc); - zclient_free (zclient_vnc); - zclient_vnc = NULL; + if (zclient_vnc == NULL) + return; + zclient_stop(zclient_vnc); + zclient_free(zclient_vnc); + zclient_vnc = NULL; } diff --git a/bgpd/rfapi/vnc_zebra.h b/bgpd/rfapi/vnc_zebra.h index 68e567ec3..708aaeef5 100644 --- a/bgpd/rfapi/vnc_zebra.h +++ b/bgpd/rfapi/vnc_zebra.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2009-2016, LabN Consulting, L.L.C. * @@ -27,40 +27,30 @@ #include "lib/zebra.h" -extern void -vnc_zebra_add_prefix ( - struct bgp *bgp, - struct rfapi_import_table *import_table, - struct route_node *rn); +extern void vnc_zebra_add_prefix(struct bgp *bgp, + struct rfapi_import_table *import_table, + struct route_node *rn); -extern void -vnc_zebra_del_prefix ( - struct bgp *bgp, - struct rfapi_import_table *import_table, - struct route_node *rn); +extern void vnc_zebra_del_prefix(struct bgp *bgp, + struct rfapi_import_table *import_table, + struct route_node *rn); -extern void -vnc_zebra_add_nve (struct bgp *bgp, struct rfapi_descriptor *rfd); +extern void vnc_zebra_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd); -extern void -vnc_zebra_del_nve (struct bgp *bgp, struct rfapi_descriptor *rfd); +extern void vnc_zebra_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd); -extern void -vnc_zebra_add_group (struct bgp *bgp, struct rfapi_nve_group_cfg *rfg); +extern void vnc_zebra_add_group(struct bgp *bgp, + struct rfapi_nve_group_cfg *rfg); -extern void -vnc_zebra_del_group (struct bgp *bgp, struct rfapi_nve_group_cfg *rfg); +extern void vnc_zebra_del_group(struct bgp *bgp, + struct rfapi_nve_group_cfg *rfg); -extern void -vnc_zebra_reexport_group_afi ( - struct bgp *bgp, - struct rfapi_nve_group_cfg *rfg, - afi_t afi); +extern void vnc_zebra_reexport_group_afi(struct bgp *bgp, + struct rfapi_nve_group_cfg *rfg, + afi_t afi); -extern int -vnc_redistribute_set (struct bgp *bgp, afi_t afi, int type); +extern int vnc_redistribute_set(struct bgp *bgp, afi_t afi, int type); -extern int -vnc_redistribute_unset (struct bgp *bgp, afi_t afi, int type); +extern int vnc_redistribute_unset(struct bgp *bgp, afi_t afi, int type); #endif /* _QUAGGA_BGP_VNC_ZEBRA_H */ diff --git a/bgpd/rfp-example/librfp/rfp.h b/bgpd/rfp-example/librfp/rfp.h index a8df87f82..ecb0c7990 100644 --- a/bgpd/rfp-example/librfp/rfp.h +++ b/bgpd/rfp-example/librfp/rfp.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2015-2016, LabN Consulting, L.L.C. * @@ -23,8 +23,8 @@ #define _RFP_H #include "bgpd/rfapi/rfapi.h" -extern int bgp_rfp_cfg_write (void *vty, void *bgp); +extern int bgp_rfp_cfg_write(void *vty, void *bgp); /* TO BE REMOVED */ -void rfp_clear_vnc_nve_all (void); +void rfp_clear_vnc_nve_all(void); #endif /* _RFP_H */ diff --git a/bgpd/rfp-example/librfp/rfp_example.c b/bgpd/rfp-example/librfp/rfp_example.c index 451be7770..fb112a886 100644 --- a/bgpd/rfp-example/librfp/rfp_example.c +++ b/bgpd/rfp-example/librfp/rfp_example.c @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2015-2016, LabN Consulting, L.L.C. * @@ -23,15 +23,15 @@ #include "bgpd/rfapi/rfapi.h" #include "lib/command.h" -struct rfp_instance_t -{ - struct rfapi_rfp_cfg rfapi_config; - struct rfapi_rfp_cb_methods rfapi_callbacks; - struct thread_master *master; - uint32_t config_var; +struct rfp_instance_t { + struct rfapi_rfp_cfg rfapi_config; + struct rfapi_rfp_cb_methods rfapi_callbacks; + struct thread_master *master; + uint32_t config_var; }; -struct rfp_instance_t global_rfi; /* dynamically allocate in full implementation */ +struct rfp_instance_t + global_rfi; /* dynamically allocate in full implementation */ /*********************************************************************** * Sample VTY / internal function @@ -44,26 +44,25 @@ DEFUN (rfp_example_config_value, "Example value to be configured\n" "Value to display") { - uint32_t value = 0; - struct rfp_instance_t *rfi = NULL; - rfi = rfapi_get_rfp_start_val (VTY_GET_CONTEXT (bgp)); /* BGP_NODE */ - assert (rfi != NULL); + uint32_t value = 0; + struct rfp_instance_t *rfi = NULL; + rfi = rfapi_get_rfp_start_val(VTY_GET_CONTEXT(bgp)); /* BGP_NODE */ + assert(rfi != NULL); - value = strtoul(argv[2]->arg, NULL, 10); - if (rfi) - rfi->config_var = value; - return CMD_SUCCESS; + value = strtoul(argv[2]->arg, NULL, 10); + if (rfi) + rfi->config_var = value; + return CMD_SUCCESS; } -static void -rfp_vty_install () +static void rfp_vty_install() { - static int installed = 0; - if (installed) /* do this only once */ - return; - installed = 1; - /* example of new cli command */ - install_element (BGP_NODE, &rfp_example_config_value_cmd); + static int installed = 0; + if (installed) /* do this only once */ + return; + installed = 1; + /* example of new cli command */ + install_element(BGP_NODE, &rfp_example_config_value_cmd); } /*********************************************************************** @@ -73,7 +72,7 @@ rfp_vty_install () /*------------------------------------------ * rfp_response_cb * - * Callbacks of this type are used to provide asynchronous + * Callbacks of this type are used to provide asynchronous * route updates from RFAPI to the RFP client. * * response_cb @@ -87,7 +86,7 @@ rfp_vty_install () * filtered out if the global BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP * flag is set. * - * input: + * input: * next_hops a list of possible next hops. * This is a linked list allocated within the * rfapi. The response_cb callback function is responsible @@ -98,25 +97,25 @@ rfp_vty_install () * rfapi_open() * *------------------------------------------*/ -static void -rfp_response_cb (struct rfapi_next_hop_entry *next_hops, void *userdata) +static void rfp_response_cb(struct rfapi_next_hop_entry *next_hops, + void *userdata) { - /* - * Identify NVE based on userdata, which is a value passed - * to RFAPI in the rfapi_open call - */ + /* + * Identify NVE based on userdata, which is a value passed + * to RFAPI in the rfapi_open call + */ - /* process list of next_hops */ + /* process list of next_hops */ - /* free next hops */ - rfapi_free_next_hop_list (next_hops); - return; + /* free next hops */ + rfapi_free_next_hop_list(next_hops); + return; } /*------------------------------------------ * rfp_local_cb * - * Callbacks of this type are used to provide asynchronous + * Callbacks of this type are used to provide asynchronous * route updates from RFAPI to the RFP client. * * local_cb @@ -124,7 +123,7 @@ rfp_response_cb (struct rfapi_next_hop_entry *next_hops, void *userdata) * has been added or deleted. Deleted routes are indicated * with lifetime==RFAPI_REMOVE_RESPONSE_LIFETIME. * - * input: + * input: * next_hops a list of possible next hops. * This is a linked list allocated within the * rfapi. The local_cb callback function is responsible @@ -135,28 +134,27 @@ rfp_response_cb (struct rfapi_next_hop_entry *next_hops, void *userdata) * rfapi_open() * *------------------------------------------*/ -static void -rfp_local_cb (struct rfapi_next_hop_entry *next_hops, void *userdata) +static void rfp_local_cb(struct rfapi_next_hop_entry *next_hops, void *userdata) { - /* - * Identify NVE based on userdata, which is a value passed - * to RFAPI in the rfapi_open call - */ + /* + * Identify NVE based on userdata, which is a value passed + * to RFAPI in the rfapi_open call + */ - /* process list of local next_hops */ + /* process list of local next_hops */ - /* free next hops */ - rfapi_free_next_hop_list (next_hops); - return; + /* free next hops */ + rfapi_free_next_hop_list(next_hops); + return; } /*------------------------------------------ - * rfp_close_cb + * rfp_close_cb * - * Callbacks used to provide asynchronous + * Callbacks used to provide asynchronous * notification that an rfapi_handle was invalidated * - * input: + * input: * pHandle Firmerly valid rfapi_handle returned to * client via rfapi_open(). * @@ -164,44 +162,42 @@ rfp_local_cb (struct rfapi_next_hop_entry *next_hops, void *userdata) * ESTALE handle invalidated by configuration change * *------------------------------------------*/ -static void -rfp_close_cb (rfapi_handle pHandle, int reason) +static void rfp_close_cb(rfapi_handle pHandle, int reason) { - /* close / invalidate NVE with the pHandle returned by the rfapi_open call */ - return; + /* close / invalidate NVE with the pHandle returned by the rfapi_open + * call */ + return; } /*------------------------------------------ * rfp_cfg_write_cb * * This callback is used to generate output for any config parameters - * that may supported by RFP via RFP defined vty commands at the bgp + * that may supported by RFP via RFP defined vty commands at the bgp * level. See loglevel as an example. * - * input: + * input: * vty -- quagga vty context * rfp_start_val -- value returned by rfp_start * * output: * to vty, rfp related configuration * - * return value: + * return value: * lines written --------------------------------------------*/ -static int -rfp_cfg_write_cb (struct vty *vty, void *rfp_start_val) +static int rfp_cfg_write_cb(struct vty *vty, void *rfp_start_val) { - struct rfp_instance_t *rfi = rfp_start_val; - int write = 0; - assert (rfp_start_val != NULL); - if (rfi->config_var != 0) - { - vty_out (vty, " rfp example-config-value %u", rfi->config_var); - vty_out (vty, "\n"); - write++; - } + struct rfp_instance_t *rfi = rfp_start_val; + int write = 0; + assert(rfp_start_val != NULL); + if (rfi->config_var != 0) { + vty_out(vty, " rfp example-config-value %u", rfi->config_var); + vty_out(vty, "\n"); + write++; + } - return write; + return write; } /*********************************************************************** @@ -213,50 +209,51 @@ rfp_cfg_write_cb (struct vty *vty, void *rfp_start_val) * * This function will start the RFP code * - * input: + * input: * master quagga thread_master to tie into bgpd threads - * + * * output: - * cfgp Pointer to rfapi_rfp_cfg (null = use defaults), + * cfgp Pointer to rfapi_rfp_cfg (null = use defaults), * copied by caller, updated via rfp_set_configuration * cbmp Pointer to rfapi_rfp_cb_methods, may be null * copied by caller, updated via rfapi_rfp_set_cb_methods * - * return value: + * return value: * rfp_start_val rfp returned value passed on rfp_stop and rfp_cfg_write - * + * --------------------------------------------*/ -void * -rfp_start (struct thread_master *master, - struct rfapi_rfp_cfg **cfgp, struct rfapi_rfp_cb_methods **cbmp) +void *rfp_start(struct thread_master *master, struct rfapi_rfp_cfg **cfgp, + struct rfapi_rfp_cb_methods **cbmp) { - memset (&global_rfi, 0, sizeof (struct rfp_instance_t)); - global_rfi.master = master; /* for BGPD threads */ + memset(&global_rfi, 0, sizeof(struct rfp_instance_t)); + global_rfi.master = master; /* for BGPD threads */ - /* initilize struct rfapi_rfp_cfg, see rfapi.h */ - global_rfi.rfapi_config.download_type = RFAPI_RFP_DOWNLOAD_FULL; /* default=partial */ - global_rfi.rfapi_config.ftd_advertisement_interval = - RFAPI_RFP_CFG_DEFAULT_FTD_ADVERTISEMENT_INTERVAL; - global_rfi.rfapi_config.holddown_factor = 0; /* default: RFAPI_RFP_CFG_DEFAULT_HOLDDOWN_FACTOR */ - global_rfi.rfapi_config.use_updated_response = 1; /* 0=no */ - global_rfi.rfapi_config.use_removes = 1; /* 0=no */ + /* initilize struct rfapi_rfp_cfg, see rfapi.h */ + global_rfi.rfapi_config.download_type = + RFAPI_RFP_DOWNLOAD_FULL; /* default=partial */ + global_rfi.rfapi_config.ftd_advertisement_interval = + RFAPI_RFP_CFG_DEFAULT_FTD_ADVERTISEMENT_INTERVAL; + global_rfi.rfapi_config.holddown_factor = + 0; /* default: RFAPI_RFP_CFG_DEFAULT_HOLDDOWN_FACTOR */ + global_rfi.rfapi_config.use_updated_response = 1; /* 0=no */ + global_rfi.rfapi_config.use_removes = 1; /* 0=no */ - /* initilize structrfapi_rfp_cb_methods , see rfapi.h */ - global_rfi.rfapi_callbacks.cfg_cb = rfp_cfg_write_cb; - /* no group config */ - global_rfi.rfapi_callbacks.response_cb = rfp_response_cb; - global_rfi.rfapi_callbacks.local_cb = rfp_local_cb; - global_rfi.rfapi_callbacks.close_cb = rfp_close_cb; + /* initilize structrfapi_rfp_cb_methods , see rfapi.h */ + global_rfi.rfapi_callbacks.cfg_cb = rfp_cfg_write_cb; + /* no group config */ + global_rfi.rfapi_callbacks.response_cb = rfp_response_cb; + global_rfi.rfapi_callbacks.local_cb = rfp_local_cb; + global_rfi.rfapi_callbacks.close_cb = rfp_close_cb; - if (cfgp != NULL) - *cfgp = &global_rfi.rfapi_config; - if (cbmp != NULL) - *cbmp = &global_rfi.rfapi_callbacks; + if (cfgp != NULL) + *cfgp = &global_rfi.rfapi_config; + if (cbmp != NULL) + *cbmp = &global_rfi.rfapi_callbacks; - rfp_vty_install (); + rfp_vty_install(); - return &global_rfi; + return &global_rfi; } /*------------------------------------------ @@ -264,24 +261,22 @@ rfp_start (struct thread_master *master, * * This function is called on shutdown to trigger RFP cleanup * - * input: + * input: * none * * output: * none * - * return value: + * return value: * rfp_start_val --------------------------------------------*/ -void -rfp_stop (void *rfp_start_val) +void rfp_stop(void *rfp_start_val) { - assert (rfp_start_val != NULL); + assert(rfp_start_val != NULL); } /* TO BE REMOVED */ -void -rfp_clear_vnc_nve_all (void) +void rfp_clear_vnc_nve_all(void) { - return; + return; } diff --git a/bgpd/rfp-example/librfp/rfp_internal.h b/bgpd/rfp-example/librfp/rfp_internal.h index b8cfeb049..f54f40dd1 100644 --- a/bgpd/rfp-example/librfp/rfp_internal.h +++ b/bgpd/rfp-example/librfp/rfp_internal.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2015-2016, LabN Consulting, L.L.C. * diff --git a/bgpd/rfp-example/rfptest/rfptest.c b/bgpd/rfp-example/rfptest/rfptest.c index 2141933d1..53e1c33cf 100644 --- a/bgpd/rfp-example/rfptest/rfptest.c +++ b/bgpd/rfp-example/rfptest/rfptest.c @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2015-2016, LabN Consulting, L.L.C. * @@ -23,9 +23,8 @@ #include #include #include "rfptest.h" -int -main () +int main() { - printf ("Your test code goes here.\n"); - exit (1); + printf("Your test code goes here.\n"); + exit(1); } diff --git a/bgpd/rfp-example/rfptest/rfptest.h b/bgpd/rfp-example/rfptest/rfptest.h index 2ebd7d12b..1f0ccb8c4 100644 --- a/bgpd/rfp-example/rfptest/rfptest.h +++ b/bgpd/rfp-example/rfptest/rfptest.h @@ -1,4 +1,4 @@ -/* +/* * * Copyright 2015-2016, LabN Consulting, L.L.C. * diff --git a/defaults.h b/defaults.h index d9fd44e14..fd38aaed7 100644 --- a/defaults.h +++ b/defaults.h @@ -36,7 +36,7 @@ #define DFLT_OSPF_LOG_ADJACENCY_CHANGES 1 #define DFLT_OSPF6_LOG_ADJACENCY_CHANGES 1 -#else /* !HAVE_DATACENTER */ +#else /* !HAVE_DATACENTER */ #define DFLT_BGP_IMPORT_CHECK 0 #define DFLT_BGP_TIMERS_CONNECT 120 diff --git a/eigrpd/eigrp_const.h b/eigrpd/eigrp_const.h index 813358757..a6282665e 100644 --- a/eigrpd/eigrp_const.h +++ b/eigrpd/eigrp_const.h @@ -48,7 +48,6 @@ #define EIGRP_VARIANCE_DEFAULT 1 #define EIGRP_MAX_PATHS_DEFAULT 4 - /* Return values of functions involved in packet verification */ #define MSG_OK 0 #define MSG_NG 1 @@ -63,12 +62,11 @@ #define EIGRP_AUTH_MD5_TLV_SIZE 40 #define EIGRP_AUTH_SHA256_TLV_SIZE 56 -/*Cisco routers use only first 44 bytes of basic hello for their MD5 calculations*/ +/*Cisco routers use only first 44 bytes of basic hello for their MD5 + * calculations*/ #define EIGRP_MD5_BASIC_COMPUTE 44 #define EIGRP_MD5_UPDATE_INIT_COMPUTE 40 - - #define EIGRP_AUTH_BASIC_HELLO_FLAG 0x01 #define EIGRP_AUTH_TID_HELLO_FLAG 0x02 #define EIGRP_AUTH_UPDATE_INIT_FLAG 0x04 @@ -109,14 +107,14 @@ #define EIGRP_HELLO_ADD_SEQUENCE 0x02 #define EIGRP_HELLO_GRACEFUL_SHUTDOWN_NBR 0x04 - /* EIGRP Network Type. */ - #define EIGRP_IFTYPE_NONE 0 - #define EIGRP_IFTYPE_POINTOPOINT 1 - #define EIGRP_IFTYPE_BROADCAST 2 - #define EIGRP_IFTYPE_NBMA 3 - #define EIGRP_IFTYPE_POINTOMULTIPOINT 4 - #define EIGRP_IFTYPE_LOOPBACK 5 - #define EIGRP_IFTYPE_MAX 6 +/* EIGRP Network Type. */ +#define EIGRP_IFTYPE_NONE 0 +#define EIGRP_IFTYPE_POINTOPOINT 1 +#define EIGRP_IFTYPE_BROADCAST 2 +#define EIGRP_IFTYPE_NBMA 3 +#define EIGRP_IFTYPE_POINTOMULTIPOINT 4 +#define EIGRP_IFTYPE_LOOPBACK 5 +#define EIGRP_IFTYPE_MAX 6 #define EIGRP_IF_ACTIVE 0 #define EIGRP_IF_PASSIVE 1 @@ -138,11 +136,11 @@ /*EEGRP FSM states*/ enum eigrp_fsm_states { - EIGRP_FSM_STATE_PASSIVE, - EIGRP_FSM_STATE_ACTIVE_0, - EIGRP_FSM_STATE_ACTIVE_1, - EIGRP_FSM_STATE_ACTIVE_2, - EIGRP_FSM_STATE_ACTIVE_3, + EIGRP_FSM_STATE_PASSIVE, + EIGRP_FSM_STATE_ACTIVE_0, + EIGRP_FSM_STATE_ACTIVE_1, + EIGRP_FSM_STATE_ACTIVE_2, + EIGRP_FSM_STATE_ACTIVE_3, }; /*EIGRP FSM events return values*/ @@ -175,7 +173,7 @@ enum eigrp_fsm_states { #define IDRP_PROTID 10 /*!< InterDomain Routing Protocol */ #define CONN_PROTID 11 /*!< Connected source */ -/* +/* * metric k-value defaults */ #define EIGRP_K1_DEFAULT 1 //!< unweighed inverse bandwidth @@ -185,14 +183,12 @@ enum eigrp_fsm_states { #define EIGRP_K5_DEFAULT 0 //!< no reliability term #define EIGRP_K6_DEFAULT 0 //!< do not add in extended metrics - /* * EIGRP Fixed header */ #define EIGRP_HEADER_LEN 20U #define EIGRP_PACKET_MAX_LEN 65535U /* includes IP Header size. */ - #define EIGRP_TLV_HDR_LENGTH 4 /** @@ -255,7 +251,8 @@ enum eigrp_fsm_states { #define EIGRP_TLV_PEER_TERMINATION_LEN (9U) #define EIGRP_TLV_PEER_TIDLIST (EIGRP_TLV_GENERAL | 0x0008) /*!< peer sub-topology list */ -/* Older cisco routers send TIDLIST value wrong, adding for backwards compatabily */ +/* Older cisco routers send TIDLIST value wrong, adding for backwards + * compatabily */ #define EIGRP_TLV_PEER_MTRLIST (EIGRP_TLV_GENERAL | 0x00f5) /** @@ -414,7 +411,6 @@ enum eigrp_fsm_states { #define EIGRP_EXTCOMM_RPM 0x8805 /* EIGRP Remote: Protocol + Metric */ #define EIGRP_EXTCOMM_VRR 0x8806 /* EIGRP Vecmet: Rsvd + (internal) Routerid */ - /* * EIGRP Filter constants */ diff --git a/eigrpd/eigrp_dump.c b/eigrpd/eigrp_dump.c index 9e18c0dca..ba24abe5b 100644 --- a/eigrpd/eigrp_dump.c +++ b/eigrpd/eigrp_dump.c @@ -63,282 +63,260 @@ unsigned long conf_debug_eigrp_zebra = 0; unsigned long conf_debug_eigrp_transmit = 0; -static int -config_write_debug (struct vty *vty) +static int config_write_debug(struct vty *vty) { - int write = 0; - int i; + int write = 0; + int i; - const char *type_str[] = {"update", "request", "query", "reply", - "hello", "", "probe", "ack", "", - "SIA query", "SIA reply", "stub", "all"}; - const char *detail_str[] = {"", " send", " recv", "", " detail", - " send detail", " recv detail", " detail"}; + const char *type_str[] = {"update", "request", "query", "reply", + "hello", "", "probe", "ack", + "", "SIA query", "SIA reply", "stub", + "all"}; + const char *detail_str[] = { + "", " send", " recv", "", + " detail", " send detail", " recv detail", " detail"}; - /* debug eigrp event. */ + /* debug eigrp event. */ - /* debug eigrp packet */ - for (i = 0; i < 10; i++) - { - if (conf_debug_eigrp_packet[i] == 0 && term_debug_eigrp_packet[i] == 0 ) - continue; + /* debug eigrp packet */ + for (i = 0; i < 10; i++) { + if (conf_debug_eigrp_packet[i] == 0 + && term_debug_eigrp_packet[i] == 0) + continue; - vty_out (vty, "debug eigrp packet %s%s\n", - type_str[i],detail_str[conf_debug_eigrp_packet[i]]); - write = 1; - } + vty_out(vty, "debug eigrp packet %s%s\n", type_str[i], + detail_str[conf_debug_eigrp_packet[i]]); + write = 1; + } - return write; + return write; } -static int -eigrp_neighbor_packet_queue_sum (struct eigrp_interface *ei) +static int eigrp_neighbor_packet_queue_sum(struct eigrp_interface *ei) { - struct eigrp_neighbor *nbr; - struct listnode *node, *nnode; - int sum; - sum = 0; + struct eigrp_neighbor *nbr; + struct listnode *node, *nnode; + int sum; + sum = 0; - for (ALL_LIST_ELEMENTS (ei->nbrs, node, nnode, nbr)) - { - sum += nbr->retrans_queue->count; - } + for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) { + sum += nbr->retrans_queue->count; + } - return sum; + return sum; } /* * Expects header to be in host order */ -void -eigrp_ip_header_dump (struct ip *iph) +void eigrp_ip_header_dump(struct ip *iph) { - /* IP Header dump. */ - zlog_debug ("ip_v %u", iph->ip_v); - zlog_debug ("ip_hl %u", iph->ip_hl); - zlog_debug ("ip_tos %u", iph->ip_tos); - zlog_debug ("ip_len %u", iph->ip_len); - zlog_debug ("ip_id %u", (u_int32_t) iph->ip_id); - zlog_debug ("ip_off %u", (u_int32_t) iph->ip_off); - zlog_debug ("ip_ttl %u", iph->ip_ttl); - zlog_debug ("ip_p %u", iph->ip_p); - zlog_debug ("ip_sum 0x%x", (u_int32_t) iph->ip_sum); - zlog_debug ("ip_src %s", inet_ntoa (iph->ip_src)); - zlog_debug ("ip_dst %s", inet_ntoa (iph->ip_dst)); + /* IP Header dump. */ + zlog_debug("ip_v %u", iph->ip_v); + zlog_debug("ip_hl %u", iph->ip_hl); + zlog_debug("ip_tos %u", iph->ip_tos); + zlog_debug("ip_len %u", iph->ip_len); + zlog_debug("ip_id %u", (u_int32_t)iph->ip_id); + zlog_debug("ip_off %u", (u_int32_t)iph->ip_off); + zlog_debug("ip_ttl %u", iph->ip_ttl); + zlog_debug("ip_p %u", iph->ip_p); + zlog_debug("ip_sum 0x%x", (u_int32_t)iph->ip_sum); + zlog_debug("ip_src %s", inet_ntoa(iph->ip_src)); + zlog_debug("ip_dst %s", inet_ntoa(iph->ip_dst)); } /* * Expects header to be in host order */ -void -eigrp_header_dump (struct eigrp_header *eigrph) +void eigrp_header_dump(struct eigrp_header *eigrph) { - /* EIGRP Header dump. */ - zlog_debug ("eigrp_version %u", eigrph->version); - zlog_debug ("eigrp_opcode %u", eigrph->opcode); - zlog_debug ("eigrp_checksum 0x%x", ntohs(eigrph->checksum)); - zlog_debug ("eigrp_flags 0x%x", ntohl(eigrph->flags)); - zlog_debug ("eigrp_sequence %u", ntohl(eigrph->sequence)); - zlog_debug ("eigrp_ack %u", ntohl(eigrph->ack)); - zlog_debug ("eigrp_vrid %u", ntohs(eigrph->vrid)); - zlog_debug ("eigrp_AS %u", ntohs(eigrph->ASNumber)); + /* EIGRP Header dump. */ + zlog_debug("eigrp_version %u", eigrph->version); + zlog_debug("eigrp_opcode %u", eigrph->opcode); + zlog_debug("eigrp_checksum 0x%x", ntohs(eigrph->checksum)); + zlog_debug("eigrp_flags 0x%x", ntohl(eigrph->flags)); + zlog_debug("eigrp_sequence %u", ntohl(eigrph->sequence)); + zlog_debug("eigrp_ack %u", ntohl(eigrph->ack)); + zlog_debug("eigrp_vrid %u", ntohs(eigrph->vrid)); + zlog_debug("eigrp_AS %u", ntohs(eigrph->ASNumber)); } -const char * -eigrp_if_name_string (struct eigrp_interface *ei) +const char *eigrp_if_name_string(struct eigrp_interface *ei) { - static char buf[EIGRP_IF_STRING_MAXLEN] = ""; + static char buf[EIGRP_IF_STRING_MAXLEN] = ""; - if (!ei) - return "inactive"; + if (!ei) + return "inactive"; - snprintf (buf, EIGRP_IF_STRING_MAXLEN, - "%s", ei->ifp->name); - return buf; + snprintf(buf, EIGRP_IF_STRING_MAXLEN, "%s", ei->ifp->name); + return buf; } -const char * -eigrp_topology_ip_string (struct eigrp_prefix_entry *tn) +const char *eigrp_topology_ip_string(struct eigrp_prefix_entry *tn) { - static char buf[EIGRP_IF_STRING_MAXLEN] = ""; - u_int32_t ifaddr; - - ifaddr = ntohl (tn->destination_ipv4->prefix.s_addr); - snprintf (buf, EIGRP_IF_STRING_MAXLEN, - "%u.%u.%u.%u", - (ifaddr >> 24) & 0xff, (ifaddr >> 16) & 0xff, - (ifaddr >> 8) & 0xff, ifaddr & 0xff); - return buf; + static char buf[EIGRP_IF_STRING_MAXLEN] = ""; + u_int32_t ifaddr; + + ifaddr = ntohl(tn->destination_ipv4->prefix.s_addr); + snprintf(buf, EIGRP_IF_STRING_MAXLEN, "%u.%u.%u.%u", + (ifaddr >> 24) & 0xff, (ifaddr >> 16) & 0xff, + (ifaddr >> 8) & 0xff, ifaddr & 0xff); + return buf; } -const char * -eigrp_if_ip_string (struct eigrp_interface *ei) +const char *eigrp_if_ip_string(struct eigrp_interface *ei) { - static char buf[EIGRP_IF_STRING_MAXLEN] = ""; - u_int32_t ifaddr; + static char buf[EIGRP_IF_STRING_MAXLEN] = ""; + u_int32_t ifaddr; - if (!ei) - return "inactive"; + if (!ei) + return "inactive"; - ifaddr = ntohl (ei->address->u.prefix4.s_addr); - snprintf (buf, EIGRP_IF_STRING_MAXLEN, - "%u.%u.%u.%u", - (ifaddr >> 24) & 0xff, (ifaddr >> 16) & 0xff, - (ifaddr >> 8) & 0xff, ifaddr & 0xff); + ifaddr = ntohl(ei->address->u.prefix4.s_addr); + snprintf(buf, EIGRP_IF_STRING_MAXLEN, "%u.%u.%u.%u", + (ifaddr >> 24) & 0xff, (ifaddr >> 16) & 0xff, + (ifaddr >> 8) & 0xff, ifaddr & 0xff); - return buf; + return buf; } -const char * -eigrp_neigh_ip_string (struct eigrp_neighbor *nbr) +const char *eigrp_neigh_ip_string(struct eigrp_neighbor *nbr) { - static char buf[EIGRP_IF_STRING_MAXLEN] = ""; - u_int32_t ifaddr; + static char buf[EIGRP_IF_STRING_MAXLEN] = ""; + u_int32_t ifaddr; - ifaddr = ntohl (nbr->src.s_addr); - snprintf (buf, EIGRP_IF_STRING_MAXLEN, - "%u.%u.%u.%u", - (ifaddr >> 24) & 0xff, (ifaddr >> 16) & 0xff, - (ifaddr >> 8) & 0xff, ifaddr & 0xff); + ifaddr = ntohl(nbr->src.s_addr); + snprintf(buf, EIGRP_IF_STRING_MAXLEN, "%u.%u.%u.%u", + (ifaddr >> 24) & 0xff, (ifaddr >> 16) & 0xff, + (ifaddr >> 8) & 0xff, ifaddr & 0xff); - return buf; + return buf; } -void -show_ip_eigrp_interface_header (struct vty *vty, struct eigrp *eigrp) +void show_ip_eigrp_interface_header(struct vty *vty, struct eigrp *eigrp) { - vty_out (vty, "\nEIGRP interfaces for AS(%d)\n\n %-10s %-10s %-10s %-6s %-12s %-7s %-14s %-12s %-8s %-8s %-8s\n %-39s %-12s %-7s %-14s %-12s %-8s\n", - eigrp->AS, - "Interface", "Bandwidth", "Delay", "Peers", "Xmit Queue", "Mean", - "Pacing Time", "Multicast", "Pending", "Hello", "Holdtime", - "","Un/Reliable","SRTT","Un/Reliable","Flow Timer", - "Routes"); + vty_out(vty, + "\nEIGRP interfaces for AS(%d)\n\n %-10s %-10s %-10s %-6s %-12s %-7s %-14s %-12s %-8s %-8s %-8s\n %-39s %-12s %-7s %-14s %-12s %-8s\n", + eigrp->AS, "Interface", "Bandwidth", "Delay", "Peers", + "Xmit Queue", "Mean", "Pacing Time", "Multicast", "Pending", + "Hello", "Holdtime", "", "Un/Reliable", "SRTT", "Un/Reliable", + "Flow Timer", "Routes"); } -void -show_ip_eigrp_interface_sub (struct vty *vty, struct eigrp *eigrp, - struct eigrp_interface *ei) +void show_ip_eigrp_interface_sub(struct vty *vty, struct eigrp *eigrp, + struct eigrp_interface *ei) { - vty_out (vty, "%-11s ", eigrp_if_name_string (ei)); - vty_out (vty, "%-11u", IF_DEF_PARAMS (ei->ifp)->bandwidth); - vty_out (vty, "%-11u", IF_DEF_PARAMS (ei->ifp)->delay); - vty_out (vty, "%-7u", ei->nbrs->count); - vty_out (vty, "%u %c %-10u",0,'/', eigrp_neighbor_packet_queue_sum (ei)); - vty_out (vty, "%-7u %-14u %-12u %-8u", 0, 0, 0, 0); - vty_out (vty, "%-8u %-8u \n", - IF_DEF_PARAMS (ei->ifp)->v_hello, - IF_DEF_PARAMS(ei->ifp)->v_wait); + vty_out(vty, "%-11s ", eigrp_if_name_string(ei)); + vty_out(vty, "%-11u", IF_DEF_PARAMS(ei->ifp)->bandwidth); + vty_out(vty, "%-11u", IF_DEF_PARAMS(ei->ifp)->delay); + vty_out(vty, "%-7u", ei->nbrs->count); + vty_out(vty, "%u %c %-10u", 0, '/', + eigrp_neighbor_packet_queue_sum(ei)); + vty_out(vty, "%-7u %-14u %-12u %-8u", 0, 0, 0, 0); + vty_out(vty, "%-8u %-8u \n", IF_DEF_PARAMS(ei->ifp)->v_hello, + IF_DEF_PARAMS(ei->ifp)->v_wait); } -void -show_ip_eigrp_interface_detail (struct vty *vty, struct eigrp *eigrp, - struct eigrp_interface *ei) +void show_ip_eigrp_interface_detail(struct vty *vty, struct eigrp *eigrp, + struct eigrp_interface *ei) { - vty_out (vty, "%-2s %s %d %-3s \n","","Hello interval is ", 0, " sec"); - vty_out (vty, "%-2s %s %s \n","", "Next xmit serial",""); - vty_out (vty, "%-2s %s %d %s %d %s %d %s %d \n", - "", "Un/reliable mcasts: ", 0, "/", 0, "Un/reliable ucasts: ", - 0, "/", 0); - vty_out (vty, "%-2s %s %d %s %d %s %d \n", - "", "Mcast exceptions: ", 0, " CR packets: ", - 0, " ACKs supressed: ", 0); - vty_out (vty, "%-2s %s %d %s %d \n", - "", "Retransmissions sent: ", 0, "Out-of-sequence rcvd: ", - 0); - vty_out (vty, "%-2s %s %s %s \n", - "", "Authentication mode is ", "not","set"); - vty_out (vty, "%-2s %s \n", "", "Use multicast"); + vty_out(vty, "%-2s %s %d %-3s \n", "", "Hello interval is ", 0, " sec"); + vty_out(vty, "%-2s %s %s \n", "", "Next xmit serial", ""); + vty_out(vty, "%-2s %s %d %s %d %s %d %s %d \n", "", + "Un/reliable mcasts: ", 0, "/", 0, "Un/reliable ucasts: ", 0, + "/", 0); + vty_out(vty, "%-2s %s %d %s %d %s %d \n", "", "Mcast exceptions: ", 0, + " CR packets: ", 0, " ACKs supressed: ", 0); + vty_out(vty, "%-2s %s %d %s %d \n", "", "Retransmissions sent: ", 0, + "Out-of-sequence rcvd: ", 0); + vty_out(vty, "%-2s %s %s %s \n", "", "Authentication mode is ", "not", + "set"); + vty_out(vty, "%-2s %s \n", "", "Use multicast"); } -void -show_ip_eigrp_neighbor_header (struct vty *vty, struct eigrp *eigrp) +void show_ip_eigrp_neighbor_header(struct vty *vty, struct eigrp *eigrp) { - vty_out (vty, "\nEIGRP neighbors for AS(%d)\n\n%-3s %-17s %-20s %-6s %-8s %-6s %-5s %-5s %-5s\n %-41s %-6s %-8s %-6s %-4s %-6s %-5s \n", - eigrp->AS, - "H", "Address", "Interface", "Hold", "Uptime", - "SRTT", "RTO", "Q", "Seq", - "","(sec)","","(ms)","","Cnt","Num"); + vty_out(vty, + "\nEIGRP neighbors for AS(%d)\n\n%-3s %-17s %-20s %-6s %-8s %-6s %-5s %-5s %-5s\n %-41s %-6s %-8s %-6s %-4s %-6s %-5s \n", + eigrp->AS, "H", "Address", "Interface", "Hold", "Uptime", + "SRTT", "RTO", "Q", "Seq", "", "(sec)", "", "(ms)", "", "Cnt", + "Num"); } -void -show_ip_eigrp_neighbor_sub (struct vty *vty, struct eigrp_neighbor *nbr, - int detail) +void show_ip_eigrp_neighbor_sub(struct vty *vty, struct eigrp_neighbor *nbr, + int detail) { - vty_out (vty, "%-3u %-17s %-21s", 0, - eigrp_neigh_ip_string (nbr), eigrp_if_name_string (nbr->ei)); - vty_out (vty,"%-7lu", thread_timer_remain_second (nbr->t_holddown)); - vty_out (vty,"%-8u %-6u %-5u", 0, 0, EIGRP_PACKET_RETRANS_TIME); - vty_out (vty,"%-7lu", nbr->retrans_queue->count); - vty_out (vty,"%u\n", nbr->recv_sequence_number); - - - if (detail) - { - vty_out(vty," Version %u.%u/%u.%u", - nbr->os_rel_major, nbr->os_rel_minor, - nbr->tlv_rel_major, nbr->tlv_rel_minor); - vty_out(vty,", Retrans: %lu, Retries: %lu", - nbr->retrans_queue->count, 0UL); - vty_out (vty,", %s\n", eigrp_nbr_state_str(nbr)); - } + vty_out(vty, "%-3u %-17s %-21s", 0, eigrp_neigh_ip_string(nbr), + eigrp_if_name_string(nbr->ei)); + vty_out(vty, "%-7lu", thread_timer_remain_second(nbr->t_holddown)); + vty_out(vty, "%-8u %-6u %-5u", 0, 0, EIGRP_PACKET_RETRANS_TIME); + vty_out(vty, "%-7lu", nbr->retrans_queue->count); + vty_out(vty, "%u\n", nbr->recv_sequence_number); + + + if (detail) { + vty_out(vty, " Version %u.%u/%u.%u", nbr->os_rel_major, + nbr->os_rel_minor, nbr->tlv_rel_major, + nbr->tlv_rel_minor); + vty_out(vty, ", Retrans: %lu, Retries: %lu", + nbr->retrans_queue->count, 0UL); + vty_out(vty, ", %s\n", eigrp_nbr_state_str(nbr)); + } } /* * Print standard header for show EIGRP topology output */ -void -show_ip_eigrp_topology_header (struct vty *vty, struct eigrp *eigrp) +void show_ip_eigrp_topology_header(struct vty *vty, struct eigrp *eigrp) { - struct in_addr router_id; - router_id.s_addr = eigrp->router_id; - - vty_out (vty, "\nEIGRP Topology Table for AS(%d)/ID(%s)\n\n", eigrp->AS, inet_ntoa(router_id)); - vty_out (vty, "Codes: P - Passive, A - Active, U - Update, Q - Query, " - "R - Reply\n r - reply Status, s - sia Status\n\n"); + struct in_addr router_id; + router_id.s_addr = eigrp->router_id; + + vty_out(vty, "\nEIGRP Topology Table for AS(%d)/ID(%s)\n\n", eigrp->AS, + inet_ntoa(router_id)); + vty_out(vty, + "Codes: P - Passive, A - Active, U - Update, Q - Query, " + "R - Reply\n r - reply Status, s - sia Status\n\n"); } -void -show_ip_eigrp_prefix_entry (struct vty *vty, struct eigrp_prefix_entry *tn) +void show_ip_eigrp_prefix_entry(struct vty *vty, struct eigrp_prefix_entry *tn) { - struct list *successors = eigrp_topology_get_successor(tn); + struct list *successors = eigrp_topology_get_successor(tn); - vty_out (vty, "%-3c",(tn->state > 0) ? 'A' : 'P'); + vty_out(vty, "%-3c", (tn->state > 0) ? 'A' : 'P'); - vty_out (vty, "%s/%u, ", - inet_ntoa (tn->destination_ipv4->prefix), tn->destination_ipv4->prefixlen); - vty_out (vty, "%u successors, ", successors->count); - vty_out (vty, "FD is %u, serno: %" PRIu64 " \n", tn->fdistance, tn->serno); + vty_out(vty, "%s/%u, ", inet_ntoa(tn->destination_ipv4->prefix), + tn->destination_ipv4->prefixlen); + vty_out(vty, "%u successors, ", successors->count); + vty_out(vty, "FD is %u, serno: %" PRIu64 " \n", tn->fdistance, + tn->serno); - list_delete(successors); + list_delete(successors); } -void -show_ip_eigrp_neighbor_entry (struct vty *vty, struct eigrp *eigrp, - struct eigrp_neighbor_entry *te, int *first) +void show_ip_eigrp_neighbor_entry(struct vty *vty, struct eigrp *eigrp, + struct eigrp_neighbor_entry *te, int *first) { - if (te->reported_distance == EIGRP_MAX_METRIC) - return; - - if (*first) - { - show_ip_eigrp_prefix_entry (vty, te->prefix); - *first = 0; - } - - if (te->adv_router == eigrp->neighbor_self) - vty_out (vty, "%-7s%s, %s\n", " ", "via Connected", - eigrp_if_name_string(te->ei)); - else - { - vty_out (vty, "%-7s%s%s (%u/%u), %s\n", - " ", "via ", inet_ntoa (te->adv_router->src), - te->distance, te->reported_distance, - eigrp_if_name_string(te->ei)); - } + if (te->reported_distance == EIGRP_MAX_METRIC) + return; + + if (*first) { + show_ip_eigrp_prefix_entry(vty, te->prefix); + *first = 0; + } + + if (te->adv_router == eigrp->neighbor_self) + vty_out(vty, "%-7s%s, %s\n", " ", "via Connected", + eigrp_if_name_string(te->ei)); + else { + vty_out(vty, "%-7s%s%s (%u/%u), %s\n", " ", "via ", + inet_ntoa(te->adv_router->src), te->distance, + te->reported_distance, eigrp_if_name_string(te->ei)); + } } @@ -349,40 +327,47 @@ DEFUN (show_debugging_eigrp, DEBUG_STR EIGRP_STR) { - int i; - - vty_out (vty, "EIGRP debugging status:\n"); - - /* Show debug status for events. */ - if (IS_DEBUG_EIGRP(event,EVENT)) - vty_out (vty, " EIGRP event debugging is on\n"); - - /* Show debug status for EIGRP Packets. */ - for (i = 0; i < 11 ; i++) - { - if (i == 8) - continue; - - if (IS_DEBUG_EIGRP_PACKET (i, SEND) && IS_DEBUG_EIGRP_PACKET (i, RECV)) - { - vty_out (vty, " EIGRP packet %s%s debugging is on\n", - lookup_msg(eigrp_packet_type_str, i + 1, NULL), - IS_DEBUG_EIGRP_PACKET (i, PACKET_DETAIL) ? " detail" : ""); - } - else - { - if (IS_DEBUG_EIGRP_PACKET (i, SEND)) - vty_out (vty, " EIGRP packet %s send%s debugging is on\n", - lookup_msg(eigrp_packet_type_str, i + 1, NULL), - IS_DEBUG_EIGRP_PACKET (i, PACKET_DETAIL) ? " detail" : ""); - if (IS_DEBUG_EIGRP_PACKET (i, RECV)) - vty_out (vty, " EIGRP packet %s receive%s debugging is on\n", - lookup_msg(eigrp_packet_type_str, i + 1, NULL), - IS_DEBUG_EIGRP_PACKET (i, PACKET_DETAIL) ? " detail" : ""); - } - } - - return CMD_SUCCESS; + int i; + + vty_out(vty, "EIGRP debugging status:\n"); + + /* Show debug status for events. */ + if (IS_DEBUG_EIGRP(event, EVENT)) + vty_out(vty, " EIGRP event debugging is on\n"); + + /* Show debug status for EIGRP Packets. */ + for (i = 0; i < 11; i++) { + if (i == 8) + continue; + + if (IS_DEBUG_EIGRP_PACKET(i, SEND) + && IS_DEBUG_EIGRP_PACKET(i, RECV)) { + vty_out(vty, " EIGRP packet %s%s debugging is on\n", + lookup_msg(eigrp_packet_type_str, i + 1, NULL), + IS_DEBUG_EIGRP_PACKET(i, PACKET_DETAIL) + ? " detail" + : ""); + } else { + if (IS_DEBUG_EIGRP_PACKET(i, SEND)) + vty_out(vty, + " EIGRP packet %s send%s debugging is on\n", + lookup_msg(eigrp_packet_type_str, i + 1, + NULL), + IS_DEBUG_EIGRP_PACKET(i, PACKET_DETAIL) + ? " detail" + : ""); + if (IS_DEBUG_EIGRP_PACKET(i, RECV)) + vty_out(vty, + " EIGRP packet %s receive%s debugging is on\n", + lookup_msg(eigrp_packet_type_str, i + 1, + NULL), + IS_DEBUG_EIGRP_PACKET(i, PACKET_DETAIL) + ? " detail" + : ""); + } + } + + return CMD_SUCCESS; } @@ -402,27 +387,27 @@ DEFUN (debug_eigrp_transmit, "all packets\n" "Detailed Information\n") { - int flag = 0; - int idx = 2; - - /* send or recv. */ - if (argv_find (argv, argc, "send", &idx)) - flag = EIGRP_DEBUG_SEND; - else if (argv_find (argv, argc, "recv", &idx)) - flag = EIGRP_DEBUG_RECV; - else if (argv_find (argv, argc, "all", &idx) == 0) - flag = EIGRP_DEBUG_SEND_RECV; - - /* detail option */ - if (argv_find (argv, argc, "detail", &idx) == 0) - flag = EIGRP_DEBUG_PACKET_DETAIL; - - if (vty->node == CONFIG_NODE) - DEBUG_TRANSMIT_ON (0, flag); - else - TERM_DEBUG_TRANSMIT_ON (0, flag); - - return CMD_SUCCESS; + int flag = 0; + int idx = 2; + + /* send or recv. */ + if (argv_find(argv, argc, "send", &idx)) + flag = EIGRP_DEBUG_SEND; + else if (argv_find(argv, argc, "recv", &idx)) + flag = EIGRP_DEBUG_RECV; + else if (argv_find(argv, argc, "all", &idx) == 0) + flag = EIGRP_DEBUG_SEND_RECV; + + /* detail option */ + if (argv_find(argv, argc, "detail", &idx) == 0) + flag = EIGRP_DEBUG_PACKET_DETAIL; + + if (vty->node == CONFIG_NODE) + DEBUG_TRANSMIT_ON(0, flag); + else + TERM_DEBUG_TRANSMIT_ON(0, flag); + + return CMD_SUCCESS; } DEFUN (no_debug_eigrp_transmit, @@ -437,27 +422,27 @@ DEFUN (no_debug_eigrp_transmit, "all packets\n" "Detailed Information\n") { - int flag = 0; - int idx = 3; - - /* send or recv. */ - if (argv_find (argv, argc, "send", &idx) == 0) - flag = EIGRP_DEBUG_SEND; - else if (argv_find (argv, argc, "recv", &idx) == 0) - flag = EIGRP_DEBUG_RECV; - else if (argv_find (argv, argc, "all", &idx) == 0) - flag = EIGRP_DEBUG_SEND_RECV; - - /* detail option */ - if (argv_find (argv, argc, "detail", &idx) == 0) - flag = EIGRP_DEBUG_PACKET_DETAIL; - - if (vty->node == CONFIG_NODE) - DEBUG_TRANSMIT_OFF (0, flag); - else - TERM_DEBUG_TRANSMIT_OFF (0, flag); - - return CMD_SUCCESS; + int flag = 0; + int idx = 3; + + /* send or recv. */ + if (argv_find(argv, argc, "send", &idx) == 0) + flag = EIGRP_DEBUG_SEND; + else if (argv_find(argv, argc, "recv", &idx) == 0) + flag = EIGRP_DEBUG_RECV; + else if (argv_find(argv, argc, "all", &idx) == 0) + flag = EIGRP_DEBUG_SEND_RECV; + + /* detail option */ + if (argv_find(argv, argc, "detail", &idx) == 0) + flag = EIGRP_DEBUG_PACKET_DETAIL; + + if (vty->node == CONFIG_NODE) + DEBUG_TRANSMIT_OFF(0, flag); + else + TERM_DEBUG_TRANSMIT_OFF(0, flag); + + return CMD_SUCCESS; } DEFUN (debug_eigrp_packets, @@ -483,59 +468,58 @@ DEFUN (debug_eigrp_packets, "Receive Packets\n" "Detail Information\n") { - int type = 0; - int flag = 0; - int i; - int idx = 0; - - /* Check packet type. */ - if (argv_find (argv, argc, "hello", &idx) == 0) - type = EIGRP_DEBUG_HELLO; - if (argv_find (argv, argc, "update", &idx) == 0) - type = EIGRP_DEBUG_UPDATE; - if (argv_find (argv, argc, "query", &idx) == 0) - type = EIGRP_DEBUG_QUERY; - if (argv_find (argv, argc, "ack", &idx) == 0) - type = EIGRP_DEBUG_ACK; - if (argv_find (argv, argc, "probe", &idx) == 0) - type = EIGRP_DEBUG_PROBE; - if (argv_find (argv, argc, "stub", &idx) == 0) - type = EIGRP_DEBUG_STUB; - if (argv_find (argv, argc, "reply", &idx) == 0) - type = EIGRP_DEBUG_REPLY; - if (argv_find (argv, argc, "request", &idx) == 0) - type = EIGRP_DEBUG_REQUEST; - if (argv_find (argv, argc, "siaquery", &idx) == 0) - type = EIGRP_DEBUG_SIAQUERY; - if (argv_find (argv, argc, "siareply", &idx) == 0) - type = EIGRP_DEBUG_SIAREPLY; - if (argv_find (argv, argc, "all", &idx) == 0) - type = EIGRP_DEBUG_PACKETS_ALL; - - - /* All packet types, both send and recv. */ - flag = EIGRP_DEBUG_SEND_RECV; - - /* send or recv. */ - if (argv_find (argv, argc, "s", &idx) == 0) - flag = EIGRP_DEBUG_SEND; - else if (argv_find (argv, argc, "r", &idx) == 0) - flag = EIGRP_DEBUG_RECV; - - /* detail. */ - if (argv_find (argv, argc, "detail", &idx) == 0) - flag |= EIGRP_DEBUG_PACKET_DETAIL; - - for (i = 0; i < 11; i++) - if (type & (0x01 << i)) - { - if (vty->node == CONFIG_NODE) - DEBUG_PACKET_ON (i, flag); - else - TERM_DEBUG_PACKET_ON (i, flag); - } - - return CMD_SUCCESS; + int type = 0; + int flag = 0; + int i; + int idx = 0; + + /* Check packet type. */ + if (argv_find(argv, argc, "hello", &idx) == 0) + type = EIGRP_DEBUG_HELLO; + if (argv_find(argv, argc, "update", &idx) == 0) + type = EIGRP_DEBUG_UPDATE; + if (argv_find(argv, argc, "query", &idx) == 0) + type = EIGRP_DEBUG_QUERY; + if (argv_find(argv, argc, "ack", &idx) == 0) + type = EIGRP_DEBUG_ACK; + if (argv_find(argv, argc, "probe", &idx) == 0) + type = EIGRP_DEBUG_PROBE; + if (argv_find(argv, argc, "stub", &idx) == 0) + type = EIGRP_DEBUG_STUB; + if (argv_find(argv, argc, "reply", &idx) == 0) + type = EIGRP_DEBUG_REPLY; + if (argv_find(argv, argc, "request", &idx) == 0) + type = EIGRP_DEBUG_REQUEST; + if (argv_find(argv, argc, "siaquery", &idx) == 0) + type = EIGRP_DEBUG_SIAQUERY; + if (argv_find(argv, argc, "siareply", &idx) == 0) + type = EIGRP_DEBUG_SIAREPLY; + if (argv_find(argv, argc, "all", &idx) == 0) + type = EIGRP_DEBUG_PACKETS_ALL; + + + /* All packet types, both send and recv. */ + flag = EIGRP_DEBUG_SEND_RECV; + + /* send or recv. */ + if (argv_find(argv, argc, "s", &idx) == 0) + flag = EIGRP_DEBUG_SEND; + else if (argv_find(argv, argc, "r", &idx) == 0) + flag = EIGRP_DEBUG_RECV; + + /* detail. */ + if (argv_find(argv, argc, "detail", &idx) == 0) + flag |= EIGRP_DEBUG_PACKET_DETAIL; + + for (i = 0; i < 11; i++) + if (type & (0x01 << i)) { + if (vty->node == CONFIG_NODE) + DEBUG_PACKET_ON(i, flag); + else + TERM_DEBUG_PACKET_ON(i, flag); + } + + return CMD_SUCCESS; } DEFUN (no_debug_eigrp_packets, @@ -562,82 +546,75 @@ DEFUN (no_debug_eigrp_packets, "Receive Packets\n" "Detailed Information\n") { - int type = 0; - int flag = 0; - int i; - int idx = 0; - - /* Check packet type. */ - if (argv_find (argv, argc, "hello", &idx) == 0) - type = EIGRP_DEBUG_HELLO; - if (argv_find (argv, argc, "update", &idx) == 0) - type = EIGRP_DEBUG_UPDATE; - if (argv_find (argv, argc, "query", &idx) == 0) - type = EIGRP_DEBUG_QUERY; - if (argv_find (argv, argc, "ack", &idx) == 0) - type = EIGRP_DEBUG_ACK; - if (argv_find (argv, argc, "probe", &idx) == 0) - type = EIGRP_DEBUG_PROBE; - if (argv_find (argv, argc, "stub", &idx) == 0) - type = EIGRP_DEBUG_STUB; - if (argv_find (argv, argc, "reply", &idx) == 0) - type = EIGRP_DEBUG_REPLY; - if (argv_find (argv, argc, "request", &idx) == 0) - type = EIGRP_DEBUG_REQUEST; - if (argv_find (argv, argc, "siaquery", &idx) == 0) - type = EIGRP_DEBUG_SIAQUERY; - if (argv_find (argv, argc, "siareply", &idx) == 0) - type = EIGRP_DEBUG_SIAREPLY; - - /* Default, both send and recv. */ - flag = EIGRP_DEBUG_SEND_RECV; - - /* send or recv. */ - if (argv_find (argv, argc, "send", &idx) == 0) - flag = EIGRP_DEBUG_SEND; - else if (argv_find (argv, argc, "reply", &idx) == 0) - flag = EIGRP_DEBUG_RECV; - - /* detail. */ - if (argv_find (argv, argc, "detail", &idx) == 0) - flag |= EIGRP_DEBUG_PACKET_DETAIL; - - for (i = 0; i < 11; i++) - if (type & (0x01 << i)) - { - if (vty->node == CONFIG_NODE) - DEBUG_PACKET_OFF (i, flag); - else - TERM_DEBUG_PACKET_OFF (i, flag); - } - - return CMD_SUCCESS; + int type = 0; + int flag = 0; + int i; + int idx = 0; + + /* Check packet type. */ + if (argv_find(argv, argc, "hello", &idx) == 0) + type = EIGRP_DEBUG_HELLO; + if (argv_find(argv, argc, "update", &idx) == 0) + type = EIGRP_DEBUG_UPDATE; + if (argv_find(argv, argc, "query", &idx) == 0) + type = EIGRP_DEBUG_QUERY; + if (argv_find(argv, argc, "ack", &idx) == 0) + type = EIGRP_DEBUG_ACK; + if (argv_find(argv, argc, "probe", &idx) == 0) + type = EIGRP_DEBUG_PROBE; + if (argv_find(argv, argc, "stub", &idx) == 0) + type = EIGRP_DEBUG_STUB; + if (argv_find(argv, argc, "reply", &idx) == 0) + type = EIGRP_DEBUG_REPLY; + if (argv_find(argv, argc, "request", &idx) == 0) + type = EIGRP_DEBUG_REQUEST; + if (argv_find(argv, argc, "siaquery", &idx) == 0) + type = EIGRP_DEBUG_SIAQUERY; + if (argv_find(argv, argc, "siareply", &idx) == 0) + type = EIGRP_DEBUG_SIAREPLY; + + /* Default, both send and recv. */ + flag = EIGRP_DEBUG_SEND_RECV; + + /* send or recv. */ + if (argv_find(argv, argc, "send", &idx) == 0) + flag = EIGRP_DEBUG_SEND; + else if (argv_find(argv, argc, "reply", &idx) == 0) + flag = EIGRP_DEBUG_RECV; + + /* detail. */ + if (argv_find(argv, argc, "detail", &idx) == 0) + flag |= EIGRP_DEBUG_PACKET_DETAIL; + + for (i = 0; i < 11; i++) + if (type & (0x01 << i)) { + if (vty->node == CONFIG_NODE) + DEBUG_PACKET_OFF(i, flag); + else + TERM_DEBUG_PACKET_OFF(i, flag); + } + + return CMD_SUCCESS; } /* Debug node. */ -static struct cmd_node eigrp_debug_node = -{ - DEBUG_NODE, - "", - 1 /* VTYSH */ +static struct cmd_node eigrp_debug_node = { + DEBUG_NODE, "", 1 /* VTYSH */ }; /* Initialize debug commands. */ -void -eigrp_debug_init () +void eigrp_debug_init() { - install_node (&eigrp_debug_node, config_write_debug); - - install_element (ENABLE_NODE, &show_debugging_eigrp_cmd); - install_element (ENABLE_NODE, &debug_eigrp_packets_all_cmd); - install_element (ENABLE_NODE, &no_debug_eigrp_packets_all_cmd); - install_element (ENABLE_NODE, &debug_eigrp_transmit_cmd); - install_element (ENABLE_NODE, &no_debug_eigrp_transmit_cmd); - - install_element (CONFIG_NODE, &show_debugging_eigrp_cmd); - install_element (CONFIG_NODE, &debug_eigrp_packets_all_cmd); - install_element (CONFIG_NODE, &no_debug_eigrp_packets_all_cmd); - install_element (CONFIG_NODE, &no_debug_eigrp_transmit_cmd); + install_node(&eigrp_debug_node, config_write_debug); + + install_element(ENABLE_NODE, &show_debugging_eigrp_cmd); + install_element(ENABLE_NODE, &debug_eigrp_packets_all_cmd); + install_element(ENABLE_NODE, &no_debug_eigrp_packets_all_cmd); + install_element(ENABLE_NODE, &debug_eigrp_transmit_cmd); + install_element(ENABLE_NODE, &no_debug_eigrp_transmit_cmd); + + install_element(CONFIG_NODE, &show_debugging_eigrp_cmd); + install_element(CONFIG_NODE, &debug_eigrp_packets_all_cmd); + install_element(CONFIG_NODE, &no_debug_eigrp_packets_all_cmd); + install_element(CONFIG_NODE, &no_debug_eigrp_transmit_cmd); } - - diff --git a/eigrpd/eigrp_dump.h b/eigrpd/eigrp_dump.h index e18efd453..7f9381595 100644 --- a/eigrpd/eigrp_dump.h +++ b/eigrpd/eigrp_dump.h @@ -71,94 +71,94 @@ extern unsigned long term_debug_eigrp_zebra; #define CONF_DEBUG_NEI_OFF(a, b) conf_debug_eigrp_nei[a] &= ~(b) #define TERM_DEBUG_NEI_ON(a, b) term_debug_eigrp_nei[a] |= (b) #define TERM_DEBUG_NEI_OFF(a, b) term_debug_eigrp_nei[a] &= ~(b) -#define DEBUG_NEI_ON(a, b) \ - do { \ - CONF_DEBUG_NEI_ON(a, b); \ - TERM_DEBUG_NEI_ON(a, b); \ - } while (0) -#define DEBUG_NEI_OFF(a, b) \ - do { \ - CONF_DEBUG_NEI_OFF(a, b); \ - TERM_DEBUG_NEI_OFF(a, b); \ - } while (0) +#define DEBUG_NEI_ON(a, b) \ + do { \ + CONF_DEBUG_NEI_ON(a, b); \ + TERM_DEBUG_NEI_ON(a, b); \ + } while (0) +#define DEBUG_NEI_OFF(a, b) \ + do { \ + CONF_DEBUG_NEI_OFF(a, b); \ + TERM_DEBUG_NEI_OFF(a, b); \ + } while (0) #define CONF_DEBUG_PACKET_ON(a, b) conf_debug_eigrp_packet[a] |= (b) #define CONF_DEBUG_PACKET_OFF(a, b) conf_debug_eigrp_packet[a] &= ~(b) #define TERM_DEBUG_PACKET_ON(a, b) term_debug_eigrp_packet[a] |= (b) #define TERM_DEBUG_PACKET_OFF(a, b) term_debug_eigrp_packet[a] &= ~(b) -#define DEBUG_PACKET_ON(a, b) \ - do { \ - CONF_DEBUG_PACKET_ON(a, b); \ - TERM_DEBUG_PACKET_ON(a, b); \ - } while (0) -#define DEBUG_PACKET_OFF(a, b) \ - do { \ - CONF_DEBUG_PACKET_OFF(a, b); \ - TERM_DEBUG_PACKET_OFF(a, b); \ - } while (0) +#define DEBUG_PACKET_ON(a, b) \ + do { \ + CONF_DEBUG_PACKET_ON(a, b); \ + TERM_DEBUG_PACKET_ON(a, b); \ + } while (0) +#define DEBUG_PACKET_OFF(a, b) \ + do { \ + CONF_DEBUG_PACKET_OFF(a, b); \ + TERM_DEBUG_PACKET_OFF(a, b); \ + } while (0) #define CONF_DEBUG_TRANSMIT_ON(a, b) conf_debug_eigrp_transmit |= (b) #define CONF_DEBUG_TRANSMIT_OFF(a, b) conf_debug_eigrp_transmit &= ~(b) #define TERM_DEBUG_TRANSMIT_ON(a, b) term_debug_eigrp_transmit |= (b) #define TERM_DEBUG_TRANSMIT_OFF(a, b) term_debug_eigrp_transmit &= ~(b) -#define DEBUG_TRANSMIT_ON(a, b) \ - do { \ - CONF_DEBUG_TRANSMIT_ON(a, b); \ - TERM_DEBUG_TRANSMIT_ON(a, b); \ - } while (0) -#define DEBUG_TRANSMIT_OFF(a, b) \ - do { \ - CONF_DEBUG_TRANSMIT_OFF(a, b); \ - TERM_DEBUG_TRANSMIT_OFF(a, b); \ - } while (0) +#define DEBUG_TRANSMIT_ON(a, b) \ + do { \ + CONF_DEBUG_TRANSMIT_ON(a, b); \ + TERM_DEBUG_TRANSMIT_ON(a, b); \ + } while (0) +#define DEBUG_TRANSMIT_OFF(a, b) \ + do { \ + CONF_DEBUG_TRANSMIT_OFF(a, b); \ + TERM_DEBUG_TRANSMIT_OFF(a, b); \ + } while (0) #define CONF_DEBUG_ON(a, b) conf_debug_eigrp_ ## a |= (EIGRP_DEBUG_ ## b) #define CONF_DEBUG_OFF(a, b) conf_debug_eigrp_ ## a &= ~(EIGRP_DEBUG_ ## b) #define TERM_DEBUG_ON(a, b) term_debug_eigrp_ ## a |= (EIGRP_DEBUG_ ## b) #define TERM_DEBUG_OFF(a, b) term_debug_eigrp_ ## a &= ~(EIGRP_DEBUG_ ## b) -#define DEBUG_ON(a, b) \ - do { \ - CONF_DEBUG_ON(a, b); \ - TERM_DEBUG_ON(a, b); \ - } while (0) -#define DEBUG_OFF(a, b) \ - do { \ - CONF_DEBUG_OFF(a, b); \ - TERM_DEBUG_OFF(a, b); \ - } while (0) +#define DEBUG_ON(a, b) \ + do { \ + CONF_DEBUG_ON(a, b); \ + TERM_DEBUG_ON(a, b); \ + } while (0) +#define DEBUG_OFF(a, b) \ + do { \ + CONF_DEBUG_OFF(a, b); \ + TERM_DEBUG_OFF(a, b); \ + } while (0) /* Macro for checking debug option. */ -#define IS_DEBUG_EIGRP_PACKET(a, b) \ - (term_debug_eigrp_packet[a] & EIGRP_DEBUG_ ## b) -#define IS_DEBUG_EIGRP_TRANSMIT(a, b) \ - (term_debug_eigrp_transmit & EIGRP_DEBUG_ ## b) -#define IS_DEBUG_EIGRP_NEI(a, b) \ - (term_debug_eigrp_nei & EIGRP_DEBUG_ ## b) -#define IS_DEBUG_EIGRP(a, b) \ - (term_debug_eigrp & EIGRP_DEBUG_ ## b) +#define IS_DEBUG_EIGRP_PACKET(a, b) \ + (term_debug_eigrp_packet[a] & EIGRP_DEBUG_##b) +#define IS_DEBUG_EIGRP_TRANSMIT(a, b) \ + (term_debug_eigrp_transmit & EIGRP_DEBUG_##b) +#define IS_DEBUG_EIGRP_NEI(a, b) (term_debug_eigrp_nei & EIGRP_DEBUG_##b) +#define IS_DEBUG_EIGRP(a, b) (term_debug_eigrp & EIGRP_DEBUG_##b) #define IS_DEBUG_EIGRP_EVENT IS_DEBUG_EIGRP(event, EVENT) - /* Prototypes. */ -extern const char *eigrp_if_name_string (struct eigrp_interface *); -extern const char *eigrp_if_ip_string (struct eigrp_interface *); -extern const char *eigrp_neigh_ip_string (struct eigrp_neighbor *); -extern const char *eigrp_topology_ip_string (struct eigrp_prefix_entry *); +extern const char *eigrp_if_name_string(struct eigrp_interface *); +extern const char *eigrp_if_ip_string(struct eigrp_interface *); +extern const char *eigrp_neigh_ip_string(struct eigrp_neighbor *); +extern const char *eigrp_topology_ip_string(struct eigrp_prefix_entry *); extern void eigrp_ip_header_dump(struct ip *); extern void eigrp_header_dump(struct eigrp_header *); -extern void show_ip_eigrp_interface_header (struct vty *, struct eigrp *); -extern void show_ip_eigrp_neighbor_header (struct vty *, struct eigrp *); -extern void show_ip_eigrp_topology_header (struct vty *, struct eigrp *); -extern void show_ip_eigrp_interface_detail (struct vty *, struct eigrp *, - struct eigrp_interface *); -extern void show_ip_eigrp_interface_sub (struct vty *, struct eigrp *, - struct eigrp_interface *); -extern void show_ip_eigrp_neighbor_sub (struct vty *, struct eigrp_neighbor *, int); -extern void show_ip_eigrp_prefix_entry (struct vty *, struct eigrp_prefix_entry *); -extern void show_ip_eigrp_neighbor_entry (struct vty *, struct eigrp *, struct eigrp_neighbor_entry *, int *); - -extern void eigrp_debug_init (void); +extern void show_ip_eigrp_interface_header(struct vty *, struct eigrp *); +extern void show_ip_eigrp_neighbor_header(struct vty *, struct eigrp *); +extern void show_ip_eigrp_topology_header(struct vty *, struct eigrp *); +extern void show_ip_eigrp_interface_detail(struct vty *, struct eigrp *, + struct eigrp_interface *); +extern void show_ip_eigrp_interface_sub(struct vty *, struct eigrp *, + struct eigrp_interface *); +extern void show_ip_eigrp_neighbor_sub(struct vty *, struct eigrp_neighbor *, + int); +extern void show_ip_eigrp_prefix_entry(struct vty *, + struct eigrp_prefix_entry *); +extern void show_ip_eigrp_neighbor_entry(struct vty *, struct eigrp *, + struct eigrp_neighbor_entry *, int *); + +extern void eigrp_debug_init(void); #endif /* _ZEBRA_EIGRPD_DUMP_H_ */ diff --git a/eigrpd/eigrp_filter.c b/eigrpd/eigrp_filter.c index df5933217..7b9e0de52 100644 --- a/eigrpd/eigrp_filter.c +++ b/eigrpd/eigrp_filter.c @@ -62,82 +62,72 @@ /* * Distribute-list update functions. */ -void -eigrp_distribute_update (struct distribute *dist) +void eigrp_distribute_update(struct distribute *dist) { - struct interface *ifp; - struct eigrp_interface *ei = NULL; - struct access_list *alist; - struct prefix_list *plist; - //struct route_map *routemap; - struct eigrp *e; - - /* if no interface address is present, set list to eigrp process struct */ - e = eigrp_lookup(); - - /* Check if distribute-list was set for process or interface */ - if (! dist->ifname) - { - /* access list IN for whole process */ - if (dist->list[DISTRIBUTE_V4_IN]) - { - alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_V4_IN]); - if (alist) - e->list[EIGRP_FILTER_IN] = alist; - else - e->list[EIGRP_FILTER_IN] = NULL; - } - else - { - e->list[EIGRP_FILTER_IN] = NULL; - } - - /* access list OUT for whole process */ - if (dist->list[DISTRIBUTE_V4_OUT]) - { - alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_V4_OUT]); - if (alist) - e->list[EIGRP_FILTER_OUT] = alist; - else - e->list[EIGRP_FILTER_OUT] = NULL; - } - else - { - e->list[EIGRP_FILTER_OUT] = NULL; - } - - /* PREFIX_LIST IN for process */ - if (dist->prefix[DISTRIBUTE_V4_IN]) - { - plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_V4_IN]); - if (plist) - { - e->prefix[EIGRP_FILTER_IN] = plist; - } - else - e->prefix[EIGRP_FILTER_IN] = NULL; - } else - e->prefix[EIGRP_FILTER_IN] = NULL; - - /* PREFIX_LIST OUT for process */ - if (dist->prefix[DISTRIBUTE_V4_OUT]) - { - plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_V4_OUT]); - if (plist) - { - e->prefix[EIGRP_FILTER_OUT] = plist; - - } - else - e->prefix[EIGRP_FILTER_OUT] = NULL; - } - else - e->prefix[EIGRP_FILTER_OUT] = NULL; - - //This is commented out, because the distribute.[ch] code - //changes looked poorly written from first glance - //commit was 133bdf2d - //TODO: DBS + struct interface *ifp; + struct eigrp_interface *ei = NULL; + struct access_list *alist; + struct prefix_list *plist; + // struct route_map *routemap; + struct eigrp *e; + + /* if no interface address is present, set list to eigrp process struct + */ + e = eigrp_lookup(); + + /* Check if distribute-list was set for process or interface */ + if (!dist->ifname) { + /* access list IN for whole process */ + if (dist->list[DISTRIBUTE_V4_IN]) { + alist = access_list_lookup( + AFI_IP, dist->list[DISTRIBUTE_V4_IN]); + if (alist) + e->list[EIGRP_FILTER_IN] = alist; + else + e->list[EIGRP_FILTER_IN] = NULL; + } else { + e->list[EIGRP_FILTER_IN] = NULL; + } + + /* access list OUT for whole process */ + if (dist->list[DISTRIBUTE_V4_OUT]) { + alist = access_list_lookup( + AFI_IP, dist->list[DISTRIBUTE_V4_OUT]); + if (alist) + e->list[EIGRP_FILTER_OUT] = alist; + else + e->list[EIGRP_FILTER_OUT] = NULL; + } else { + e->list[EIGRP_FILTER_OUT] = NULL; + } + + /* PREFIX_LIST IN for process */ + if (dist->prefix[DISTRIBUTE_V4_IN]) { + plist = prefix_list_lookup( + AFI_IP, dist->prefix[DISTRIBUTE_V4_IN]); + if (plist) { + e->prefix[EIGRP_FILTER_IN] = plist; + } else + e->prefix[EIGRP_FILTER_IN] = NULL; + } else + e->prefix[EIGRP_FILTER_IN] = NULL; + + /* PREFIX_LIST OUT for process */ + if (dist->prefix[DISTRIBUTE_V4_OUT]) { + plist = prefix_list_lookup( + AFI_IP, dist->prefix[DISTRIBUTE_V4_OUT]); + if (plist) { + e->prefix[EIGRP_FILTER_OUT] = plist; + + } else + e->prefix[EIGRP_FILTER_OUT] = NULL; + } else + e->prefix[EIGRP_FILTER_OUT] = NULL; + +// This is commented out, because the distribute.[ch] code +// changes looked poorly written from first glance +// commit was 133bdf2d +// TODO: DBS #if 0 /* route-map IN for whole process */ if (dist->route[DISTRIBUTE_V4_IN]) @@ -167,90 +157,82 @@ eigrp_distribute_update (struct distribute *dist) e->routemap[EIGRP_FILTER_OUT] = NULL; } #endif - //TODO: check Graceful restart after 10sec - - /* check if there is already GR scheduled */ - if(e->t_distribute != NULL) - { - /* if is, cancel schedule */ - thread_cancel(e->t_distribute); - } - /* schedule Graceful restart for whole process in 10sec */ - e->t_distribute = NULL; - thread_add_timer(master, eigrp_distribute_timer_process, e, (10), - &e->t_distribute); - - return; - } - - ifp = if_lookup_by_name (dist->ifname, VRF_DEFAULT); - if (ifp == NULL) - return; - - /*struct eigrp_if_info * info = ifp->info; - ei = info->eigrp_interface;*/ - struct listnode *node, *nnode; - struct eigrp_interface *ei2; - /* Find proper interface */ - for (ALL_LIST_ELEMENTS (e->eiflist, node, nnode, ei2)) - { - if(strcmp(ei2->ifp->name,ifp->name) == 0){ - ei = ei2; - break; - } - } - - /* Access-list for interface in */ - if (dist->list[DISTRIBUTE_V4_IN]) - { - alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_V4_IN]); - if (alist){ - ei->list[EIGRP_FILTER_IN] = alist; - } - else - ei->list[EIGRP_FILTER_IN] = NULL; - } - else - { - ei->list[EIGRP_FILTER_IN] = NULL; - } - - /* Access-list for interface in */ - if (dist->list[DISTRIBUTE_V4_OUT]) - { - alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_V4_OUT]); - if (alist) - ei->list[EIGRP_FILTER_OUT] = alist; - else - ei->list[EIGRP_FILTER_OUT] = NULL; - - } - else - ei->list[EIGRP_FILTER_OUT] = NULL; - - /* Prefix-list for interface in */ - if (dist->prefix[DISTRIBUTE_V4_IN]) - { - plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_V4_IN]); - if (plist) - ei->prefix[EIGRP_FILTER_IN] = plist; - else - ei->prefix[EIGRP_FILTER_IN] = NULL; - } - else - ei->prefix[EIGRP_FILTER_IN] = NULL; - - /* Prefix-list for interface out */ - if (dist->prefix[DISTRIBUTE_V4_OUT]) - { - plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_V4_OUT]); - if (plist) - ei->prefix[EIGRP_FILTER_OUT] = plist; - else - ei->prefix[EIGRP_FILTER_OUT] = NULL; - } - else - ei->prefix[EIGRP_FILTER_OUT] = NULL; + // TODO: check Graceful restart after 10sec + + /* check if there is already GR scheduled */ + if (e->t_distribute != NULL) { + /* if is, cancel schedule */ + thread_cancel(e->t_distribute); + } + /* schedule Graceful restart for whole process in 10sec */ + e->t_distribute = NULL; + thread_add_timer(master, eigrp_distribute_timer_process, e, + (10), &e->t_distribute); + + return; + } + + ifp = if_lookup_by_name(dist->ifname, VRF_DEFAULT); + if (ifp == NULL) + return; + + /*struct eigrp_if_info * info = ifp->info; + ei = info->eigrp_interface;*/ + struct listnode *node, *nnode; + struct eigrp_interface *ei2; + /* Find proper interface */ + for (ALL_LIST_ELEMENTS(e->eiflist, node, nnode, ei2)) { + if (strcmp(ei2->ifp->name, ifp->name) == 0) { + ei = ei2; + break; + } + } + + /* Access-list for interface in */ + if (dist->list[DISTRIBUTE_V4_IN]) { + alist = access_list_lookup(AFI_IP, + dist->list[DISTRIBUTE_V4_IN]); + if (alist) { + ei->list[EIGRP_FILTER_IN] = alist; + } else + ei->list[EIGRP_FILTER_IN] = NULL; + } else { + ei->list[EIGRP_FILTER_IN] = NULL; + } + + /* Access-list for interface in */ + if (dist->list[DISTRIBUTE_V4_OUT]) { + alist = access_list_lookup(AFI_IP, + dist->list[DISTRIBUTE_V4_OUT]); + if (alist) + ei->list[EIGRP_FILTER_OUT] = alist; + else + ei->list[EIGRP_FILTER_OUT] = NULL; + + } else + ei->list[EIGRP_FILTER_OUT] = NULL; + + /* Prefix-list for interface in */ + if (dist->prefix[DISTRIBUTE_V4_IN]) { + plist = prefix_list_lookup(AFI_IP, + dist->prefix[DISTRIBUTE_V4_IN]); + if (plist) + ei->prefix[EIGRP_FILTER_IN] = plist; + else + ei->prefix[EIGRP_FILTER_IN] = NULL; + } else + ei->prefix[EIGRP_FILTER_IN] = NULL; + + /* Prefix-list for interface out */ + if (dist->prefix[DISTRIBUTE_V4_OUT]) { + plist = prefix_list_lookup(AFI_IP, + dist->prefix[DISTRIBUTE_V4_OUT]); + if (plist) + ei->prefix[EIGRP_FILTER_OUT] = plist; + else + ei->prefix[EIGRP_FILTER_OUT] = NULL; + } else + ei->prefix[EIGRP_FILTER_OUT] = NULL; #if 0 /* route-map IN for whole process */ @@ -282,53 +264,49 @@ eigrp_distribute_update (struct distribute *dist) ei->routemap[EIGRP_FILTER_OUT] = NULL; } #endif - //TODO: check Graceful restart after 10sec - - /* check if there is already GR scheduled */ - if(ei->t_distribute != NULL) - { - /* if is, cancel schedule */ - thread_cancel(ei->t_distribute); - } - /* schedule Graceful restart for interface in 10sec */ - e->t_distribute = NULL; - thread_add_timer(master, eigrp_distribute_timer_interface, ei, 10, - &e->t_distribute); + // TODO: check Graceful restart after 10sec + + /* check if there is already GR scheduled */ + if (ei->t_distribute != NULL) { + /* if is, cancel schedule */ + thread_cancel(ei->t_distribute); + } + /* schedule Graceful restart for interface in 10sec */ + e->t_distribute = NULL; + thread_add_timer(master, eigrp_distribute_timer_interface, ei, 10, + &e->t_distribute); } /* * Function called by prefix-list and access-list update */ -void -eigrp_distribute_update_interface (struct interface *ifp) +void eigrp_distribute_update_interface(struct interface *ifp) { - struct distribute *dist; + struct distribute *dist; - dist = distribute_lookup (ifp->name); - if (dist) - eigrp_distribute_update (dist); + dist = distribute_lookup(ifp->name); + if (dist) + eigrp_distribute_update(dist); } /* Update all interface's distribute list. * Function used in hook for prefix-list */ -void -eigrp_distribute_update_all (struct prefix_list *notused) +void eigrp_distribute_update_all(struct prefix_list *notused) { - struct interface *ifp; - struct listnode *node, *nnode; + struct interface *ifp; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (vrf_iflist(VRF_DEFAULT), node, nnode, ifp)) - eigrp_distribute_update_interface (ifp); + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), node, nnode, ifp)) + eigrp_distribute_update_interface(ifp); } /* * Function used in hook for acces-list */ -void -eigrp_distribute_update_all_wrapper(struct access_list *notused) +void eigrp_distribute_update_all_wrapper(struct access_list *notused) { - eigrp_distribute_update_all(NULL); + eigrp_distribute_update_all(NULL); } /* @@ -342,18 +320,17 @@ eigrp_distribute_update_all_wrapper(struct access_list *notused) * Called when 10sec waiting time expire and * executes Graceful restart for whole process */ -int -eigrp_distribute_timer_process (struct thread *thread) +int eigrp_distribute_timer_process(struct thread *thread) { - struct eigrp *eigrp; + struct eigrp *eigrp; - eigrp = THREAD_ARG(thread); - eigrp->t_distribute = NULL; + eigrp = THREAD_ARG(thread); + eigrp->t_distribute = NULL; - /* execute GR for whole process */ - eigrp_update_send_process_GR(eigrp, EIGRP_GR_FILTER, NULL); + /* execute GR for whole process */ + eigrp_update_send_process_GR(eigrp, EIGRP_GR_FILTER, NULL); - return 0; + return 0; } /* @@ -367,16 +344,15 @@ eigrp_distribute_timer_process (struct thread *thread) * Called when 10sec waiting time expire and * executes Graceful restart for interface */ -int -eigrp_distribute_timer_interface (struct thread *thread) +int eigrp_distribute_timer_interface(struct thread *thread) { - struct eigrp_interface *ei; + struct eigrp_interface *ei; - ei = THREAD_ARG(thread); - ei->t_distribute = NULL; + ei = THREAD_ARG(thread); + ei->t_distribute = NULL; - /* execute GR for interface */ - eigrp_update_send_interface_GR(ei, EIGRP_GR_FILTER, NULL); + /* execute GR for interface */ + eigrp_update_send_interface_GR(ei, EIGRP_GR_FILTER, NULL); - return 0; + return 0; } diff --git a/eigrpd/eigrp_filter.h b/eigrpd/eigrp_filter.h index 117cf3c49..caec19b0f 100644 --- a/eigrpd/eigrp_filter.h +++ b/eigrpd/eigrp_filter.h @@ -33,11 +33,11 @@ #ifndef EIGRPD_EIGRP_FILTER_H_ #define EIGRPD_EIGRP_FILTER_H_ -extern void eigrp_distribute_update (struct distribute *); -extern void eigrp_distribute_update_interface (struct interface *); -extern void eigrp_distribute_update_all (struct prefix_list *); +extern void eigrp_distribute_update(struct distribute *); +extern void eigrp_distribute_update_interface(struct interface *); +extern void eigrp_distribute_update_all(struct prefix_list *); extern void eigrp_distribute_update_all_wrapper(struct access_list *); -extern int eigrp_distribute_timer_process (struct thread *); -extern int eigrp_distribute_timer_interface (struct thread *); +extern int eigrp_distribute_timer_process(struct thread *); +extern int eigrp_distribute_timer_interface(struct thread *); #endif /* EIGRPD_EIGRP_FILTER_H_ */ diff --git a/eigrpd/eigrp_fsm.c b/eigrpd/eigrp_fsm.c index 44a474758..852362e19 100644 --- a/eigrpd/eigrp_fsm.c +++ b/eigrpd/eigrp_fsm.c @@ -44,12 +44,14 @@ * / / / +----+ \ \ * | | | | | | * | v | | | v - * +===========+ (6) +===========+ +===========+ (6) +===========+ - * | |------->| | (5) | |-------->| | - * | | (4) | |------>| | (4) | | - * | ACTIVE 0 |<-------| ACTIVE 1 | | ACTIVE 2 |<--------| ACTIVE 3 | - * +--| | +--| | +--| | +--| | - * | +===========+ | +===========+ | +===========+ | +===========+ + * +===========+ (6) +===========+ +===========+ (6) +===========+ + * | |------->| | (5) | |-------->| | + * | | (4) | |------>| | (4) | | + * | ACTIVE 0 |<-------| ACTIVE 1 | | ACTIVE 2 |<--------| ACTIVE 3 + * | + * +--| | +--| | +--| | +--| | + * | +===========+ | +===========+ | +===========+ | + * +===========+ * | ^ |(5) | ^ | ^ ^ | ^ * | | +---------|------|------------|----+ | | | * +-------+ +------+ +---------+ +---------+ @@ -109,59 +111,64 @@ int eigrp_fsm_event_qact(struct eigrp_fsm_action_message *); * Functions are should be executed within separate thread. */ struct { - int - (*func)(struct eigrp_fsm_action_message *); -} NSM[EIGRP_FSM_STATE_MAX][EIGRP_FSM_EVENT_MAX] = { { - //PASSIVE STATE - { eigrp_fsm_event_nq_fcn }, /* Event 0 */ - { eigrp_fsm_event_keep_state }, /* Event 1 */ - { eigrp_fsm_event_q_fcn }, /* Event 2 */ - { eigrp_fsm_event_keep_state }, /* Event 3 */ - { eigrp_fsm_event_keep_state }, /* Event 4 */ - { eigrp_fsm_event_keep_state }, /* Event 5 */ - { eigrp_fsm_event_keep_state }, /* Event 6 */ - { eigrp_fsm_event_keep_state }, /* Event 7 */ - }, { - //Active 0 state - { eigrp_fsm_event_keep_state }, /* Event 0 */ - { eigrp_fsm_event_keep_state }, /* Event 1 */ - { eigrp_fsm_event_keep_state }, /* Event 2 */ - { eigrp_fsm_event_lr_fcs }, /* Event 3 */ - { eigrp_fsm_event_keep_state }, /* Event 4 */ - { eigrp_fsm_event_qact }, /* Event 5 */ - { eigrp_fsm_event_lr_fcn }, /* Event 6 */ - { eigrp_fsm_event_keep_state }, /* Event 7 */ - }, { - //Active 1 state - { eigrp_fsm_event_keep_state }, /* Event 0 */ - { eigrp_fsm_event_lr }, /* Event 1 */ - { eigrp_fsm_event_keep_state }, /* Event 2 */ - { eigrp_fsm_event_keep_state }, /* Event 3 */ - { eigrp_fsm_event_dinc }, /* Event 4 */ - { eigrp_fsm_event_qact }, /* Event 5 */ - { eigrp_fsm_event_keep_state }, /* Event 6 */ - { eigrp_fsm_event_keep_state }, /* Event 7 */ - }, { - //Active 2 state - { eigrp_fsm_event_keep_state }, /* Event 0 */ - { eigrp_fsm_event_keep_state }, /* Event 1 */ - { eigrp_fsm_event_keep_state }, /* Event 2 */ - { eigrp_fsm_event_lr_fcs }, /* Event 3 */ - { eigrp_fsm_event_keep_state }, /* Event 4 */ - { eigrp_fsm_event_keep_state }, /* Event 5 */ - { eigrp_fsm_event_lr_fcn }, /* Event 6 */ - { eigrp_fsm_event_keep_state }, /* Event 7 */ - }, { - //Active 3 state - { eigrp_fsm_event_keep_state }, /* Event 0 */ - { eigrp_fsm_event_lr }, /* Event 1 */ - { eigrp_fsm_event_keep_state }, /* Event 2 */ - { eigrp_fsm_event_keep_state }, /* Event 3 */ - { eigrp_fsm_event_dinc }, /* Event 4 */ - { eigrp_fsm_event_keep_state }, /* Event 5 */ - { eigrp_fsm_event_keep_state }, /* Event 6 */ - { eigrp_fsm_event_keep_state }, /* Event 7 */ -}, }; + int (*func)(struct eigrp_fsm_action_message *); +} NSM[EIGRP_FSM_STATE_MAX][EIGRP_FSM_EVENT_MAX] = { + { + // PASSIVE STATE + {eigrp_fsm_event_nq_fcn}, /* Event 0 */ + {eigrp_fsm_event_keep_state}, /* Event 1 */ + {eigrp_fsm_event_q_fcn}, /* Event 2 */ + {eigrp_fsm_event_keep_state}, /* Event 3 */ + {eigrp_fsm_event_keep_state}, /* Event 4 */ + {eigrp_fsm_event_keep_state}, /* Event 5 */ + {eigrp_fsm_event_keep_state}, /* Event 6 */ + {eigrp_fsm_event_keep_state}, /* Event 7 */ + }, + { + // Active 0 state + {eigrp_fsm_event_keep_state}, /* Event 0 */ + {eigrp_fsm_event_keep_state}, /* Event 1 */ + {eigrp_fsm_event_keep_state}, /* Event 2 */ + {eigrp_fsm_event_lr_fcs}, /* Event 3 */ + {eigrp_fsm_event_keep_state}, /* Event 4 */ + {eigrp_fsm_event_qact}, /* Event 5 */ + {eigrp_fsm_event_lr_fcn}, /* Event 6 */ + {eigrp_fsm_event_keep_state}, /* Event 7 */ + }, + { + // Active 1 state + {eigrp_fsm_event_keep_state}, /* Event 0 */ + {eigrp_fsm_event_lr}, /* Event 1 */ + {eigrp_fsm_event_keep_state}, /* Event 2 */ + {eigrp_fsm_event_keep_state}, /* Event 3 */ + {eigrp_fsm_event_dinc}, /* Event 4 */ + {eigrp_fsm_event_qact}, /* Event 5 */ + {eigrp_fsm_event_keep_state}, /* Event 6 */ + {eigrp_fsm_event_keep_state}, /* Event 7 */ + }, + { + // Active 2 state + {eigrp_fsm_event_keep_state}, /* Event 0 */ + {eigrp_fsm_event_keep_state}, /* Event 1 */ + {eigrp_fsm_event_keep_state}, /* Event 2 */ + {eigrp_fsm_event_lr_fcs}, /* Event 3 */ + {eigrp_fsm_event_keep_state}, /* Event 4 */ + {eigrp_fsm_event_keep_state}, /* Event 5 */ + {eigrp_fsm_event_lr_fcn}, /* Event 6 */ + {eigrp_fsm_event_keep_state}, /* Event 7 */ + }, + { + // Active 3 state + {eigrp_fsm_event_keep_state}, /* Event 0 */ + {eigrp_fsm_event_lr}, /* Event 1 */ + {eigrp_fsm_event_keep_state}, /* Event 2 */ + {eigrp_fsm_event_keep_state}, /* Event 3 */ + {eigrp_fsm_event_dinc}, /* Event 4 */ + {eigrp_fsm_event_keep_state}, /* Event 5 */ + {eigrp_fsm_event_keep_state}, /* Event 6 */ + {eigrp_fsm_event_keep_state}, /* Event 7 */ + }, +}; /* * Main function in which are make decisions which event occurred. @@ -173,185 +180,158 @@ struct { */ int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) { - // Loading base information from message - //struct eigrp *eigrp = msg->eigrp; - struct eigrp_prefix_entry *prefix = msg->prefix; - struct eigrp_neighbor_entry *entry = msg->entry; - u_char actual_state = prefix->state; - - if (entry == NULL) - { - entry = eigrp_neighbor_entry_new(); - entry->adv_router = msg->adv_router; - entry->ei = msg->adv_router->ei; - entry->prefix = prefix; - msg->entry = entry; - } - - // Dividing by actual state of prefix's FSM - switch (actual_state) - { - case EIGRP_FSM_STATE_PASSIVE: - { - //Calculate resultant metrics and insert to correct position in entries list - eigrp_topology_update_distance(msg); - - struct eigrp_neighbor_entry * head = - (struct eigrp_neighbor_entry *) entry->prefix->entries->head->data; - //zlog_info ("flag: %d rdist: %u dist: %u pfdist: %u pdist: %u", head->flags, head->reported_distance, head->distance, prefix->fdistance, prefix->distance); - if (head->reported_distance < prefix->fdistance) - { - return EIGRP_FSM_KEEP_STATE; - } - /* - * if best entry doesn't satisfy feasibility condition it means move to active state - * dependently if it was query from successor - */ - else - { - if (msg->packet_type == EIGRP_OPC_QUERY) - { - return EIGRP_FSM_EVENT_Q_FCN; - } - else - { - return EIGRP_FSM_EVENT_NQ_FCN; - } - } - - break; - } - case EIGRP_FSM_STATE_ACTIVE_0: - { - eigrp_topology_update_distance(msg); - - if (msg->packet_type == EIGRP_OPC_REPLY) { - listnode_delete(prefix->rij, entry->adv_router); - if (prefix->rij->count) - { - return EIGRP_FSM_KEEP_STATE; - } - else - { - zlog_info("All reply received\n"); - if (((struct eigrp_neighbor_entry *) prefix->entries->head->data)->reported_distance - < prefix->fdistance) - { - return EIGRP_FSM_EVENT_LR_FCS; - } - - return EIGRP_FSM_EVENT_LR_FCN; - } - } - else if (msg->packet_type == EIGRP_OPC_QUERY - && (entry->flags & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)) - { - return EIGRP_FSM_EVENT_QACT; - } - - return EIGRP_FSM_KEEP_STATE; - - break; - } - case EIGRP_FSM_STATE_ACTIVE_1: - { - int change = eigrp_topology_update_distance(msg); - - if (msg->packet_type == EIGRP_OPC_QUERY - && (entry->flags & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)) - { - return EIGRP_FSM_EVENT_QACT; - } - else if (msg->packet_type == EIGRP_OPC_REPLY) - { - listnode_delete(prefix->rij, entry->adv_router); - - if (change == 1 - && (entry->flags & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)) - { - return EIGRP_FSM_EVENT_DINC; - } - else if (prefix->rij->count) - { - return EIGRP_FSM_KEEP_STATE; - } - else - { - zlog_info("All reply received\n"); - return EIGRP_FSM_EVENT_LR; - } - } - else if (msg->packet_type == EIGRP_OPC_UPDATE && change == 1 - && (entry->flags & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)) - { - return EIGRP_FSM_EVENT_DINC; - } - return EIGRP_FSM_KEEP_STATE; - - break; - } - case EIGRP_FSM_STATE_ACTIVE_2: - { - eigrp_topology_update_distance(msg); - - if (msg->packet_type == EIGRP_OPC_REPLY) - { - listnode_delete(prefix->rij, entry->adv_router); - if (prefix->rij->count) - { - return EIGRP_FSM_KEEP_STATE; - } - else - { - zlog_info("All reply received\n"); - if (((struct eigrp_neighbor_entry *) prefix->entries->head->data)->reported_distance - < prefix->fdistance) - { - return EIGRP_FSM_EVENT_LR_FCS; - } - - return EIGRP_FSM_EVENT_LR_FCN; - } - } - return EIGRP_FSM_KEEP_STATE; - - break; - } - case EIGRP_FSM_STATE_ACTIVE_3: - { - int change = eigrp_topology_update_distance(msg); - - if (msg->packet_type == EIGRP_OPC_REPLY) - { - listnode_delete(prefix->rij, entry->adv_router); - - if (change == 1 - && (entry->flags & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)) - { - return EIGRP_FSM_EVENT_DINC; - } - else if (prefix->rij->count) - { - return EIGRP_FSM_KEEP_STATE; - } - else - { - zlog_info("All reply received\n"); - return EIGRP_FSM_EVENT_LR; - } - } - else if (msg->packet_type == EIGRP_OPC_UPDATE && change == 1 - && (entry->flags & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)) - { - return EIGRP_FSM_EVENT_DINC; - } - return EIGRP_FSM_KEEP_STATE; - - break; - } - } - - return EIGRP_FSM_KEEP_STATE; + // Loading base information from message + // struct eigrp *eigrp = msg->eigrp; + struct eigrp_prefix_entry *prefix = msg->prefix; + struct eigrp_neighbor_entry *entry = msg->entry; + u_char actual_state = prefix->state; + + if (entry == NULL) { + entry = eigrp_neighbor_entry_new(); + entry->adv_router = msg->adv_router; + entry->ei = msg->adv_router->ei; + entry->prefix = prefix; + msg->entry = entry; + } + + // Dividing by actual state of prefix's FSM + switch (actual_state) { + case EIGRP_FSM_STATE_PASSIVE: { + // Calculate resultant metrics and insert to correct position in + // entries list + eigrp_topology_update_distance(msg); + + struct eigrp_neighbor_entry *head = + (struct eigrp_neighbor_entry *) + entry->prefix->entries->head->data; + // zlog_info ("flag: %d rdist: %u dist: %u pfdist: %u pdist: + // %u", head->flags, head->reported_distance, head->distance, + // prefix->fdistance, prefix->distance); + if (head->reported_distance < prefix->fdistance) { + return EIGRP_FSM_KEEP_STATE; + } + /* + * if best entry doesn't satisfy feasibility condition it means + * move to active state + * dependently if it was query from successor + */ + else { + if (msg->packet_type == EIGRP_OPC_QUERY) { + return EIGRP_FSM_EVENT_Q_FCN; + } else { + return EIGRP_FSM_EVENT_NQ_FCN; + } + } + + break; + } + case EIGRP_FSM_STATE_ACTIVE_0: { + eigrp_topology_update_distance(msg); + + if (msg->packet_type == EIGRP_OPC_REPLY) { + listnode_delete(prefix->rij, entry->adv_router); + if (prefix->rij->count) { + return EIGRP_FSM_KEEP_STATE; + } else { + zlog_info("All reply received\n"); + if (((struct eigrp_neighbor_entry *) + prefix->entries->head->data) + ->reported_distance + < prefix->fdistance) { + return EIGRP_FSM_EVENT_LR_FCS; + } + + return EIGRP_FSM_EVENT_LR_FCN; + } + } else if (msg->packet_type == EIGRP_OPC_QUERY + && (entry->flags + & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)) { + return EIGRP_FSM_EVENT_QACT; + } + + return EIGRP_FSM_KEEP_STATE; + + break; + } + case EIGRP_FSM_STATE_ACTIVE_1: { + int change = eigrp_topology_update_distance(msg); + + if (msg->packet_type == EIGRP_OPC_QUERY + && (entry->flags & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)) { + return EIGRP_FSM_EVENT_QACT; + } else if (msg->packet_type == EIGRP_OPC_REPLY) { + listnode_delete(prefix->rij, entry->adv_router); + + if (change == 1 + && (entry->flags + & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)) { + return EIGRP_FSM_EVENT_DINC; + } else if (prefix->rij->count) { + return EIGRP_FSM_KEEP_STATE; + } else { + zlog_info("All reply received\n"); + return EIGRP_FSM_EVENT_LR; + } + } else if (msg->packet_type == EIGRP_OPC_UPDATE && change == 1 + && (entry->flags + & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)) { + return EIGRP_FSM_EVENT_DINC; + } + return EIGRP_FSM_KEEP_STATE; + + break; + } + case EIGRP_FSM_STATE_ACTIVE_2: { + eigrp_topology_update_distance(msg); + + if (msg->packet_type == EIGRP_OPC_REPLY) { + listnode_delete(prefix->rij, entry->adv_router); + if (prefix->rij->count) { + return EIGRP_FSM_KEEP_STATE; + } else { + zlog_info("All reply received\n"); + if (((struct eigrp_neighbor_entry *) + prefix->entries->head->data) + ->reported_distance + < prefix->fdistance) { + return EIGRP_FSM_EVENT_LR_FCS; + } + + return EIGRP_FSM_EVENT_LR_FCN; + } + } + return EIGRP_FSM_KEEP_STATE; + + break; + } + case EIGRP_FSM_STATE_ACTIVE_3: { + int change = eigrp_topology_update_distance(msg); + + if (msg->packet_type == EIGRP_OPC_REPLY) { + listnode_delete(prefix->rij, entry->adv_router); + + if (change == 1 + && (entry->flags + & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)) { + return EIGRP_FSM_EVENT_DINC; + } else if (prefix->rij->count) { + return EIGRP_FSM_KEEP_STATE; + } else { + zlog_info("All reply received\n"); + return EIGRP_FSM_EVENT_LR; + } + } else if (msg->packet_type == EIGRP_OPC_UPDATE && change == 1 + && (entry->flags + & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)) { + return EIGRP_FSM_EVENT_DINC; + } + return EIGRP_FSM_KEEP_STATE; + + break; + } + } + + return EIGRP_FSM_KEEP_STATE; } /* @@ -360,11 +340,12 @@ int eigrp_get_fsm_event(struct eigrp_fsm_action_message *msg) */ int eigrp_fsm_event(struct eigrp_fsm_action_message *msg, int event) { - zlog_info("EIGRP AS: %d State: %d Event: %d Network: %s\n", msg->eigrp->AS, - msg->prefix->state, event, eigrp_topology_ip_string(msg->prefix)); - (*(NSM[msg->prefix->state][event].func))(msg); + zlog_info("EIGRP AS: %d State: %d Event: %d Network: %s\n", + msg->eigrp->AS, msg->prefix->state, event, + eigrp_topology_ip_string(msg->prefix)); + (*(NSM[msg->prefix->state][event].func))(msg); - return 1; + return 1; } /* @@ -373,214 +354,226 @@ int eigrp_fsm_event(struct eigrp_fsm_action_message *msg, int event) */ int eigrp_fsm_event_nq_fcn(struct eigrp_fsm_action_message *msg) { - struct eigrp *eigrp = msg->eigrp; - struct eigrp_prefix_entry *prefix = msg->prefix; - struct list *successors = eigrp_topology_get_successor(prefix); - - assert(successors); // If this is NULL we have shit the bed, fun huh? - - prefix->state = EIGRP_FSM_STATE_ACTIVE_1; - prefix->rdistance = prefix->distance = prefix->fdistance = - ((struct eigrp_neighbor_entry *) successors->head->data)->distance; - prefix->reported_metric = - ((struct eigrp_neighbor_entry *) successors->head->data)->total_metric; - - if (eigrp_nbr_count_get()) - { - prefix->req_action |= EIGRP_FSM_NEED_QUERY; - listnode_add(eigrp->topology_changes_internalIPV4,prefix); - } - else - { - eigrp_fsm_event_lr(msg); //in the case that there are no more neighbors left - } - - list_delete(successors); - - return 1; + struct eigrp *eigrp = msg->eigrp; + struct eigrp_prefix_entry *prefix = msg->prefix; + struct list *successors = eigrp_topology_get_successor(prefix); + + assert(successors); // If this is NULL we have shit the bed, fun huh? + + prefix->state = EIGRP_FSM_STATE_ACTIVE_1; + prefix->rdistance = prefix->distance = prefix->fdistance = + ((struct eigrp_neighbor_entry *)successors->head->data) + ->distance; + prefix->reported_metric = + ((struct eigrp_neighbor_entry *)successors->head->data) + ->total_metric; + + if (eigrp_nbr_count_get()) { + prefix->req_action |= EIGRP_FSM_NEED_QUERY; + listnode_add(eigrp->topology_changes_internalIPV4, prefix); + } else { + eigrp_fsm_event_lr(msg); // in the case that there are no more + // neighbors left + } + + list_delete(successors); + + return 1; } int eigrp_fsm_event_q_fcn(struct eigrp_fsm_action_message *msg) { - struct eigrp *eigrp = msg->eigrp; - struct eigrp_prefix_entry *prefix = msg->prefix; - struct list *successors = eigrp_topology_get_successor(prefix); - - assert(successors); // If this is NULL somebody poked us in the eye. - - prefix->state = EIGRP_FSM_STATE_ACTIVE_3; - prefix->rdistance = prefix->distance = prefix->fdistance = - ((struct eigrp_neighbor_entry *) successors->head->data)->distance; - prefix->reported_metric = - ((struct eigrp_neighbor_entry *) successors->head->data)->total_metric; - if (eigrp_nbr_count_get()) - { - prefix->req_action |= EIGRP_FSM_NEED_QUERY; - listnode_add(eigrp->topology_changes_internalIPV4,prefix); - } - else - { - eigrp_fsm_event_lr(msg); //in the case that there are no more neighbors left - } - - list_delete(successors); - - return 1; + struct eigrp *eigrp = msg->eigrp; + struct eigrp_prefix_entry *prefix = msg->prefix; + struct list *successors = eigrp_topology_get_successor(prefix); + + assert(successors); // If this is NULL somebody poked us in the eye. + + prefix->state = EIGRP_FSM_STATE_ACTIVE_3; + prefix->rdistance = prefix->distance = prefix->fdistance = + ((struct eigrp_neighbor_entry *)successors->head->data) + ->distance; + prefix->reported_metric = + ((struct eigrp_neighbor_entry *)successors->head->data) + ->total_metric; + if (eigrp_nbr_count_get()) { + prefix->req_action |= EIGRP_FSM_NEED_QUERY; + listnode_add(eigrp->topology_changes_internalIPV4, prefix); + } else { + eigrp_fsm_event_lr(msg); // in the case that there are no more + // neighbors left + } + + list_delete(successors); + + return 1; } int eigrp_fsm_event_keep_state(struct eigrp_fsm_action_message *msg) { - struct eigrp_prefix_entry *prefix = msg->prefix; - - if (prefix->state == EIGRP_FSM_STATE_PASSIVE) - { - if (!eigrp_metrics_is_same(prefix->reported_metric, - ((struct eigrp_neighbor_entry *) prefix->entries->head->data)->total_metric)) - { - prefix->rdistance = - prefix->fdistance = - prefix->distance = - ((struct eigrp_neighbor_entry *) prefix->entries->head->data)->distance; - prefix->reported_metric = - ((struct eigrp_neighbor_entry *) prefix->entries->head->data)->total_metric; - if (msg->packet_type == EIGRP_OPC_QUERY) - eigrp_send_reply(msg->adv_router, prefix); - prefix->req_action |= EIGRP_FSM_NEED_UPDATE; - listnode_add((eigrp_lookup())->topology_changes_internalIPV4,prefix); - } - eigrp_topology_update_node_flags(prefix); - eigrp_update_routing_table(prefix); - } - - if (msg->packet_type == EIGRP_OPC_QUERY) - eigrp_send_reply(msg->adv_router, prefix); - - return 1; + struct eigrp_prefix_entry *prefix = msg->prefix; + + if (prefix->state == EIGRP_FSM_STATE_PASSIVE) { + if (!eigrp_metrics_is_same(prefix->reported_metric, + ((struct eigrp_neighbor_entry *) + prefix->entries->head->data) + ->total_metric)) { + prefix->rdistance = prefix->fdistance = + prefix->distance = + ((struct eigrp_neighbor_entry *) + prefix->entries->head->data) + ->distance; + prefix->reported_metric = + ((struct eigrp_neighbor_entry *) + prefix->entries->head->data) + ->total_metric; + if (msg->packet_type == EIGRP_OPC_QUERY) + eigrp_send_reply(msg->adv_router, prefix); + prefix->req_action |= EIGRP_FSM_NEED_UPDATE; + listnode_add( + (eigrp_lookup())->topology_changes_internalIPV4, + prefix); + } + eigrp_topology_update_node_flags(prefix); + eigrp_update_routing_table(prefix); + } + + if (msg->packet_type == EIGRP_OPC_QUERY) + eigrp_send_reply(msg->adv_router, prefix); + + return 1; } int eigrp_fsm_event_lr(struct eigrp_fsm_action_message *msg) { - struct eigrp *eigrp = msg->eigrp; - struct eigrp_prefix_entry *prefix = msg->prefix; - prefix->fdistance = - prefix->distance = - prefix->rdistance = - ((struct eigrp_neighbor_entry *) (prefix->entries->head->data))->distance; - prefix->reported_metric = - ((struct eigrp_neighbor_entry *) (prefix->entries->head->data))->total_metric; - - if (prefix->state == EIGRP_FSM_STATE_ACTIVE_3) - { - struct list *successors = eigrp_topology_get_successor(prefix); - - assert(successors); // It's like Napolean and Waterloo - - eigrp_send_reply(((struct eigrp_neighbor_entry *)successors->head->data)->adv_router, prefix); - list_delete(successors); - } - - prefix->state = EIGRP_FSM_STATE_PASSIVE; - prefix->req_action |= EIGRP_FSM_NEED_UPDATE; - listnode_add(eigrp->topology_changes_internalIPV4,prefix); - eigrp_topology_update_node_flags(prefix); - eigrp_update_routing_table(prefix); - eigrp_update_topology_table_prefix(eigrp->topology_table, prefix); - - return 1; + struct eigrp *eigrp = msg->eigrp; + struct eigrp_prefix_entry *prefix = msg->prefix; + prefix->fdistance = prefix->distance = prefix->rdistance = + ((struct eigrp_neighbor_entry *)(prefix->entries->head->data)) + ->distance; + prefix->reported_metric = + ((struct eigrp_neighbor_entry *)(prefix->entries->head->data)) + ->total_metric; + + if (prefix->state == EIGRP_FSM_STATE_ACTIVE_3) { + struct list *successors = eigrp_topology_get_successor(prefix); + + assert(successors); // It's like Napolean and Waterloo + + eigrp_send_reply( + ((struct eigrp_neighbor_entry *)successors->head->data) + ->adv_router, + prefix); + list_delete(successors); + } + + prefix->state = EIGRP_FSM_STATE_PASSIVE; + prefix->req_action |= EIGRP_FSM_NEED_UPDATE; + listnode_add(eigrp->topology_changes_internalIPV4, prefix); + eigrp_topology_update_node_flags(prefix); + eigrp_update_routing_table(prefix); + eigrp_update_topology_table_prefix(eigrp->topology_table, prefix); + + return 1; } int eigrp_fsm_event_dinc(struct eigrp_fsm_action_message *msg) { - struct list *successors = eigrp_topology_get_successor(msg->prefix); + struct list *successors = eigrp_topology_get_successor(msg->prefix); - assert(successors); // Trump and his big hands + assert(successors); // Trump and his big hands - msg->prefix->state = - msg->prefix->state == EIGRP_FSM_STATE_ACTIVE_1 ? - EIGRP_FSM_STATE_ACTIVE_0 : EIGRP_FSM_STATE_ACTIVE_2; - msg->prefix->distance = - ((struct eigrp_neighbor_entry *)successors->head->data)->distance; - if (!msg->prefix->rij->count) - (*(NSM[msg->prefix->state][eigrp_get_fsm_event(msg)].func))(msg); + msg->prefix->state = msg->prefix->state == EIGRP_FSM_STATE_ACTIVE_1 + ? EIGRP_FSM_STATE_ACTIVE_0 + : EIGRP_FSM_STATE_ACTIVE_2; + msg->prefix->distance = + ((struct eigrp_neighbor_entry *)successors->head->data) + ->distance; + if (!msg->prefix->rij->count) + (*(NSM[msg->prefix->state][eigrp_get_fsm_event(msg)].func))( + msg); - list_delete(successors); - return 1; + list_delete(successors); + return 1; } int eigrp_fsm_event_lr_fcs(struct eigrp_fsm_action_message *msg) { - struct eigrp *eigrp = msg->eigrp; - struct eigrp_prefix_entry *prefix = msg->prefix; - prefix->state = EIGRP_FSM_STATE_PASSIVE; - prefix->distance = - prefix->rdistance = - ((struct eigrp_neighbor_entry *) (prefix->entries->head->data))->distance; - prefix->reported_metric = - ((struct eigrp_neighbor_entry *) (prefix->entries->head->data))->total_metric; - prefix->fdistance = - prefix->fdistance > prefix->distance ? - prefix->distance : prefix->fdistance; - if (prefix->state == EIGRP_FSM_STATE_ACTIVE_2) - { - struct list *successors = eigrp_topology_get_successor(prefix); - - assert(successors); // Having a spoon and all you need is a knife - - eigrp_send_reply(((struct eigrp_neighbor_entry *)successors->head->data)->adv_router, prefix); - - list_delete(successors); - } - prefix->req_action |= EIGRP_FSM_NEED_UPDATE; - listnode_add(eigrp->topology_changes_internalIPV4,prefix); - eigrp_topology_update_node_flags(prefix); - eigrp_update_routing_table(prefix); - eigrp_update_topology_table_prefix(eigrp->topology_table, prefix); - - return 1; + struct eigrp *eigrp = msg->eigrp; + struct eigrp_prefix_entry *prefix = msg->prefix; + prefix->state = EIGRP_FSM_STATE_PASSIVE; + prefix->distance = prefix->rdistance = + ((struct eigrp_neighbor_entry *)(prefix->entries->head->data)) + ->distance; + prefix->reported_metric = + ((struct eigrp_neighbor_entry *)(prefix->entries->head->data)) + ->total_metric; + prefix->fdistance = prefix->fdistance > prefix->distance + ? prefix->distance + : prefix->fdistance; + if (prefix->state == EIGRP_FSM_STATE_ACTIVE_2) { + struct list *successors = eigrp_topology_get_successor(prefix); + + assert(successors); // Having a spoon and all you need is a + // knife + + eigrp_send_reply( + ((struct eigrp_neighbor_entry *)successors->head->data) + ->adv_router, + prefix); + + list_delete(successors); + } + prefix->req_action |= EIGRP_FSM_NEED_UPDATE; + listnode_add(eigrp->topology_changes_internalIPV4, prefix); + eigrp_topology_update_node_flags(prefix); + eigrp_update_routing_table(prefix); + eigrp_update_topology_table_prefix(eigrp->topology_table, prefix); + + return 1; } int eigrp_fsm_event_lr_fcn(struct eigrp_fsm_action_message *msg) { - struct eigrp *eigrp = msg->eigrp; - struct eigrp_prefix_entry *prefix = msg->prefix; - struct list *successors = eigrp_topology_get_successor(prefix); - - assert(successors); // Routing without a stack - - prefix->state = - prefix->state == EIGRP_FSM_STATE_ACTIVE_0 ? - EIGRP_FSM_STATE_ACTIVE_1 : EIGRP_FSM_STATE_ACTIVE_3; - struct eigrp_neighbor_entry *best_successor = - ((struct eigrp_neighbor_entry *) (successors->head->data)); - prefix->rdistance = prefix->distance = best_successor->distance; - prefix->reported_metric = best_successor->total_metric; - - if (eigrp_nbr_count_get()) - { - prefix->req_action |= EIGRP_FSM_NEED_QUERY; - listnode_add(eigrp->topology_changes_internalIPV4,prefix); - } - else - { - eigrp_fsm_event_lr(msg); //in the case that there are no more neighbors left - } - - list_delete(successors); - - return 1; + struct eigrp *eigrp = msg->eigrp; + struct eigrp_prefix_entry *prefix = msg->prefix; + struct list *successors = eigrp_topology_get_successor(prefix); + + assert(successors); // Routing without a stack + + prefix->state = prefix->state == EIGRP_FSM_STATE_ACTIVE_0 + ? EIGRP_FSM_STATE_ACTIVE_1 + : EIGRP_FSM_STATE_ACTIVE_3; + struct eigrp_neighbor_entry *best_successor = + ((struct eigrp_neighbor_entry *)(successors->head->data)); + prefix->rdistance = prefix->distance = best_successor->distance; + prefix->reported_metric = best_successor->total_metric; + + if (eigrp_nbr_count_get()) { + prefix->req_action |= EIGRP_FSM_NEED_QUERY; + listnode_add(eigrp->topology_changes_internalIPV4, prefix); + } else { + eigrp_fsm_event_lr(msg); // in the case that there are no more + // neighbors left + } + + list_delete(successors); + + return 1; } int eigrp_fsm_event_qact(struct eigrp_fsm_action_message *msg) { - struct list *successors = eigrp_topology_get_successor(msg->prefix); + struct list *successors = eigrp_topology_get_successor(msg->prefix); - assert(successors); // Cats and no Dogs + assert(successors); // Cats and no Dogs - msg->prefix->state = EIGRP_FSM_STATE_ACTIVE_2; - msg->prefix->distance = - ((struct eigrp_neighbor_entry *) (successors->head->data))->distance; + msg->prefix->state = EIGRP_FSM_STATE_ACTIVE_2; + msg->prefix->distance = + ((struct eigrp_neighbor_entry *)(successors->head->data)) + ->distance; - list_delete(successors); - return 1; + list_delete(successors); + return 1; } diff --git a/eigrpd/eigrp_fsm.h b/eigrpd/eigrp_fsm.h index 4ba0d8873..97a1f4928 100644 --- a/eigrpd/eigrp_fsm.h +++ b/eigrpd/eigrp_fsm.h @@ -28,9 +28,8 @@ #ifndef _ZEBRA_EIGRP_FSM_H #define _ZEBRA_EIGRP_FSM_H - -extern int eigrp_get_fsm_event (struct eigrp_fsm_action_message *); -extern int eigrp_fsm_event (struct eigrp_fsm_action_message *, int); +extern int eigrp_get_fsm_event(struct eigrp_fsm_action_message *); +extern int eigrp_fsm_event(struct eigrp_fsm_action_message *, int); #endif /* _ZEBRA_EIGRP_DUAL_H */ diff --git a/eigrpd/eigrp_hello.c b/eigrpd/eigrp_hello.c index 8750cf2dc..b7c2f7f18 100644 --- a/eigrpd/eigrp_hello.c +++ b/eigrpd/eigrp_hello.c @@ -56,25 +56,23 @@ #include "eigrpd/eigrp_macros.h" /* Packet Type String. */ -static const struct message eigrp_general_tlv_type_str[] = -{ - { EIGRP_TLV_PARAMETER, "PARAMETER" }, - { EIGRP_TLV_AUTH, "AUTH" }, - { EIGRP_TLV_SEQ, "SEQ" }, - { EIGRP_TLV_SW_VERSION, "SW_VERSION" }, - { EIGRP_TLV_NEXT_MCAST_SEQ, "NEXT_MCAST_SEQ" }, - { EIGRP_TLV_PEER_TERMINATION, "PEER_TERMINATION" }, - { EIGRP_TLV_PEER_MTRLIST, "PEER_MTRLIST" }, - { EIGRP_TLV_PEER_TIDLIST, "PEER_TIDLIST" }, - { 0 } -}; +static const struct message eigrp_general_tlv_type_str[] = { + {EIGRP_TLV_PARAMETER, "PARAMETER"}, + {EIGRP_TLV_AUTH, "AUTH"}, + {EIGRP_TLV_SEQ, "SEQ"}, + {EIGRP_TLV_SW_VERSION, "SW_VERSION"}, + {EIGRP_TLV_NEXT_MCAST_SEQ, "NEXT_MCAST_SEQ"}, + {EIGRP_TLV_PEER_TERMINATION, "PEER_TERMINATION"}, + {EIGRP_TLV_PEER_MTRLIST, "PEER_MTRLIST"}, + {EIGRP_TLV_PEER_TIDLIST, "PEER_TIDLIST"}, + {0}}; /* * @fn eigrp_hello_timer * * @param[in] thread current execution thread timer is associated with - * + * * @return int always returns 0 * * @par @@ -82,27 +80,26 @@ static const struct message eigrp_general_tlv_type_str[] = * Sends hello packet via multicast for all interfaces eigrp * is configured for */ -int -eigrp_hello_timer (struct thread *thread) +int eigrp_hello_timer(struct thread *thread) { - struct eigrp_interface *ei; + struct eigrp_interface *ei; - ei = THREAD_ARG(thread); - ei->t_hello = NULL; + ei = THREAD_ARG(thread); + ei->t_hello = NULL; - if (IS_DEBUG_EIGRP(0, TIMERS)) - zlog_debug ("Start Hello Timer (%s) Expire [%u]", - IF_NAME(ei), EIGRP_IF_PARAM(ei, v_hello)); + if (IS_DEBUG_EIGRP(0, TIMERS)) + zlog_debug("Start Hello Timer (%s) Expire [%u]", IF_NAME(ei), + EIGRP_IF_PARAM(ei, v_hello)); - /* Sending hello packet. */ - eigrp_hello_send(ei, EIGRP_HELLO_NORMAL, NULL); + /* Sending hello packet. */ + eigrp_hello_send(ei, EIGRP_HELLO_NORMAL, NULL); - /* Hello timer set. */ - ei->t_hello = NULL; - thread_add_timer(master, eigrp_hello_timer, ei, EIGRP_IF_PARAM(ei, v_hello), - &ei->t_hello); + /* Hello timer set. */ + ei->t_hello = NULL; + thread_add_timer(master, eigrp_hello_timer, ei, + EIGRP_IF_PARAM(ei, v_hello), &ei->t_hello); - return 0; + return 0; } /** @@ -121,84 +118,89 @@ eigrp_hello_timer (struct thread *thread) * older TLV packet formats. */ static struct eigrp_neighbor * -eigrp_hello_parameter_decode (struct eigrp_neighbor *nbr, - struct eigrp_tlv_hdr_type *tlv) +eigrp_hello_parameter_decode(struct eigrp_neighbor *nbr, + struct eigrp_tlv_hdr_type *tlv) { - struct eigrp *eigrp = nbr->ei->eigrp; - struct TLV_Parameter_Type *param = (struct TLV_Parameter_Type *)tlv; - - /* copy over the values passed in by the neighbor */ - nbr->K1 = param->K1; - nbr->K2 = param->K2; - nbr->K3 = param->K3; - nbr->K4 = param->K4; - nbr->K5 = param->K5; - nbr->K6 = param->K6; - nbr->v_holddown = ntohs(param->hold_time); - - /* - * Check K1-K5 have the correct values to be able to become neighbors - * K6 does not have to match - */ - if ((eigrp->k_values[0] == nbr->K1) && - (eigrp->k_values[1] == nbr->K2) && - (eigrp->k_values[2] == nbr->K3) && - (eigrp->k_values[3] == nbr->K4) && - (eigrp->k_values[4] == nbr->K5)) - { - - if (eigrp_nbr_state_get(nbr) == EIGRP_NEIGHBOR_DOWN) - { - zlog_info("Neighbor %s (%s) is pending: new adjacency", - inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); - - /* Expedited hello sent */ - eigrp_hello_send(nbr->ei, EIGRP_HELLO_NORMAL, NULL); - - // if(ntohl(nbr->ei->address->u.prefix4.s_addr) > ntohl(nbr->src.s_addr)) - eigrp_update_send_init(nbr); - - eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_PENDING); - } - } - else - { - if (eigrp_nbr_state_get(nbr) != EIGRP_NEIGHBOR_DOWN) - { - if ((param->K1 & param->K2 & param->K3 & param->K4 & param->K5) == 255) - { - zlog_info ("Neighbor %s (%s) is down: Interface PEER-TERMINATION received", - inet_ntoa (nbr->src),ifindex2ifname (nbr->ei->ifp->ifindex, VRF_DEFAULT)); - eigrp_nbr_delete (nbr); - return NULL; - } - else - { - zlog_info ("Neighbor %s (%s) going down: Kvalue mismatch", - inet_ntoa (nbr->src),ifindex2ifname (nbr->ei->ifp->ifindex, VRF_DEFAULT)); - eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN); - } - } - } - - return nbr; + struct eigrp *eigrp = nbr->ei->eigrp; + struct TLV_Parameter_Type *param = (struct TLV_Parameter_Type *)tlv; + + /* copy over the values passed in by the neighbor */ + nbr->K1 = param->K1; + nbr->K2 = param->K2; + nbr->K3 = param->K3; + nbr->K4 = param->K4; + nbr->K5 = param->K5; + nbr->K6 = param->K6; + nbr->v_holddown = ntohs(param->hold_time); + + /* + * Check K1-K5 have the correct values to be able to become neighbors + * K6 does not have to match + */ + if ((eigrp->k_values[0] == nbr->K1) && (eigrp->k_values[1] == nbr->K2) + && (eigrp->k_values[2] == nbr->K3) + && (eigrp->k_values[3] == nbr->K4) + && (eigrp->k_values[4] == nbr->K5)) { + + if (eigrp_nbr_state_get(nbr) == EIGRP_NEIGHBOR_DOWN) { + zlog_info("Neighbor %s (%s) is pending: new adjacency", + inet_ntoa(nbr->src), + ifindex2ifname(nbr->ei->ifp->ifindex, + VRF_DEFAULT)); + + /* Expedited hello sent */ + eigrp_hello_send(nbr->ei, EIGRP_HELLO_NORMAL, NULL); + + // if(ntohl(nbr->ei->address->u.prefix4.s_addr) > + // ntohl(nbr->src.s_addr)) + eigrp_update_send_init(nbr); + + eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_PENDING); + } + } else { + if (eigrp_nbr_state_get(nbr) != EIGRP_NEIGHBOR_DOWN) { + if ((param->K1 & param->K2 & param->K3 & param->K4 + & param->K5) + == 255) { + zlog_info( + "Neighbor %s (%s) is down: Interface PEER-TERMINATION received", + inet_ntoa(nbr->src), + ifindex2ifname(nbr->ei->ifp->ifindex, + VRF_DEFAULT)); + eigrp_nbr_delete(nbr); + return NULL; + } else { + zlog_info( + "Neighbor %s (%s) going down: Kvalue mismatch", + inet_ntoa(nbr->src), + ifindex2ifname(nbr->ei->ifp->ifindex, + VRF_DEFAULT)); + eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN); + } + } + } + + return nbr; } static u_char -eigrp_hello_authentication_decode(struct stream *s, struct eigrp_tlv_hdr_type *tlv_header, - struct eigrp_neighbor *nbr) +eigrp_hello_authentication_decode(struct stream *s, + struct eigrp_tlv_hdr_type *tlv_header, + struct eigrp_neighbor *nbr) { - struct TLV_MD5_Authentication_Type *md5; + struct TLV_MD5_Authentication_Type *md5; - md5 = (struct TLV_MD5_Authentication_Type *) tlv_header; + md5 = (struct TLV_MD5_Authentication_Type *)tlv_header; - if(md5->auth_type == EIGRP_AUTH_TYPE_MD5) - return eigrp_check_md5_digest(s, md5, nbr, EIGRP_AUTH_BASIC_HELLO_FLAG); - else if (md5->auth_type == EIGRP_AUTH_TYPE_SHA256) - return eigrp_check_sha256_digest(s, (struct TLV_SHA256_Authentication_Type *)tlv_header, - nbr, EIGRP_AUTH_BASIC_HELLO_FLAG); + if (md5->auth_type == EIGRP_AUTH_TYPE_MD5) + return eigrp_check_md5_digest(s, md5, nbr, + EIGRP_AUTH_BASIC_HELLO_FLAG); + else if (md5->auth_type == EIGRP_AUTH_TYPE_SHA256) + return eigrp_check_sha256_digest( + s, (struct TLV_SHA256_Authentication_Type *)tlv_header, + nbr, EIGRP_AUTH_BASIC_HELLO_FLAG); - return 0; + return 0; } /** @@ -214,17 +216,16 @@ eigrp_hello_authentication_decode(struct stream *s, struct eigrp_tlv_hdr_type *t * This consists of two bytes of OS version, and two bytes of EIGRP * revision number. */ -static void -eigrp_sw_version_decode (struct eigrp_neighbor *nbr, - struct eigrp_tlv_hdr_type *tlv) +static void eigrp_sw_version_decode(struct eigrp_neighbor *nbr, + struct eigrp_tlv_hdr_type *tlv) { - struct TLV_Software_Type *version = (struct TLV_Software_Type *)tlv; + struct TLV_Software_Type *version = (struct TLV_Software_Type *)tlv; - nbr->os_rel_major = version->vender_major; - nbr->os_rel_minor = version->vender_minor; - nbr->tlv_rel_major = version->eigrp_major; - nbr->tlv_rel_minor = version->eigrp_minor; - return; + nbr->os_rel_major = version->vender_major; + nbr->os_rel_minor = version->vender_minor; + nbr->tlv_rel_major = version->eigrp_major; + nbr->tlv_rel_minor = version->eigrp_minor; + return; } /** @@ -240,54 +241,54 @@ eigrp_sw_version_decode (struct eigrp_neighbor *nbr, * a match is found, move the sending neighbor to the down state. If * out address is not in the TLV, then ignore the peer termination */ -static void -eigrp_peer_termination_decode (struct eigrp_neighbor *nbr, - struct eigrp_tlv_hdr_type *tlv) +static void eigrp_peer_termination_decode(struct eigrp_neighbor *nbr, + struct eigrp_tlv_hdr_type *tlv) { - struct TLV_Peer_Termination_type *param = (struct TLV_Peer_Termination_type *)tlv; - - uint32_t my_ip = nbr->ei->address->u.prefix4.s_addr; - uint32_t received_ip = param->neighbor_ip; - - if(my_ip == received_ip) - { - zlog_info ("Neighbor %s (%s) is down: Peer Termination received", - inet_ntoa (nbr->src), - ifindex2ifname (nbr->ei->ifp->ifindex, VRF_DEFAULT)); - /* set neighbor to DOWN */ - nbr->state = EIGRP_NEIGHBOR_DOWN; - /* delete neighbor */ - eigrp_nbr_delete (nbr); - } + struct TLV_Peer_Termination_type *param = + (struct TLV_Peer_Termination_type *)tlv; + + uint32_t my_ip = nbr->ei->address->u.prefix4.s_addr; + uint32_t received_ip = param->neighbor_ip; + + if (my_ip == received_ip) { + zlog_info("Neighbor %s (%s) is down: Peer Termination received", + inet_ntoa(nbr->src), + ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); + /* set neighbor to DOWN */ + nbr->state = EIGRP_NEIGHBOR_DOWN; + /* delete neighbor */ + eigrp_nbr_delete(nbr); + } } /** * @fn eigrp_peer_termination_encode * * @param[in,out] s packet stream TLV is stored to - * @param[in] nbr_addr pointer to neighbor address for Peer Termination TLV + * @param[in] nbr_addr pointer to neighbor address for Peer + * Termination TLV * * @return u_int16_t number of bytes added to packet stream * * @par * Function used to encode Peer Termination TLV to Hello packet. */ -static u_int16_t -eigrp_peer_termination_encode (struct stream *s, struct in_addr *nbr_addr) +static u_int16_t eigrp_peer_termination_encode(struct stream *s, + struct in_addr *nbr_addr) { - u_int16_t length = EIGRP_TLV_PEER_TERMINATION_LEN; + u_int16_t length = EIGRP_TLV_PEER_TERMINATION_LEN; - /* fill in type and length */ - stream_putw(s, EIGRP_TLV_PEER_TERMINATION); - stream_putw(s, length); + /* fill in type and length */ + stream_putw(s, EIGRP_TLV_PEER_TERMINATION); + stream_putw(s, length); - /* fill in unknown field 0x04 */ - stream_putc(s, 0x04); + /* fill in unknown field 0x04 */ + stream_putc(s, 0x04); - /* finally neighbor IP address */ - stream_put_ipv4(s, nbr_addr->s_addr); + /* finally neighbor IP address */ + stream_put_ipv4(s, nbr_addr->s_addr); - return(length); + return (length); } /* @@ -307,98 +308,101 @@ eigrp_peer_termination_encode (struct stream *s, struct in_addr *nbr_addr) * will validate the peer associated with the src ip address of the ip * header, and then decode each of the general TLVs which the packet * may contain. - * + * * @usage * Not all TLVs are current decoder. This is a work in progress.. */ -void -eigrp_hello_receive (struct eigrp *eigrp, struct ip *iph, struct eigrp_header *eigrph, - struct stream *s, struct eigrp_interface *ei, int size) +void eigrp_hello_receive(struct eigrp *eigrp, struct ip *iph, + struct eigrp_header *eigrph, struct stream *s, + struct eigrp_interface *ei, int size) { - struct eigrp_tlv_hdr_type *tlv_header; - struct eigrp_neighbor *nbr; - uint16_t type; - uint16_t length; - - /* get neighbor struct */ - nbr = eigrp_nbr_get(ei, eigrph, iph); - - /* neighbor must be valid, eigrp_nbr_get creates if none existed */ - assert(nbr); - - if (IS_DEBUG_EIGRP_PACKET(eigrph->opcode - 1, RECV)) - zlog_debug("Processing Hello size[%u] int(%s) nbr(%s)", - size, ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT), - inet_ntoa(nbr->src)); - - size -= EIGRP_HEADER_LEN; - if (size < 0) - return; - - tlv_header = (struct eigrp_tlv_hdr_type *)eigrph->tlv; - - do { - type = ntohs(tlv_header->type); - length = ntohs(tlv_header->length); - - if ((length > 0) && (length <= size)) - { - if (IS_DEBUG_EIGRP_PACKET(0, RECV)) - zlog_debug(" General TLV(%s)", lookup_msg(eigrp_general_tlv_type_str, type, NULL)); - - // determine what General TLV is being processed - switch (type) - { - case EIGRP_TLV_PARAMETER: - nbr = eigrp_hello_parameter_decode(nbr, tlv_header); - if (!nbr) - return; - break; - case EIGRP_TLV_AUTH: - { - if(eigrp_hello_authentication_decode(s,tlv_header,nbr) == 0) - return; - else - break; - break; - } - case EIGRP_TLV_SEQ: - break; - case EIGRP_TLV_SW_VERSION: - eigrp_sw_version_decode(nbr, tlv_header); - break; - case EIGRP_TLV_NEXT_MCAST_SEQ: - break; - case EIGRP_TLV_PEER_TERMINATION: - eigrp_peer_termination_decode(nbr, tlv_header); - return; - break; - case EIGRP_TLV_PEER_MTRLIST: - case EIGRP_TLV_PEER_TIDLIST: - break; - default: - break; - } - } - - tlv_header = (struct eigrp_tlv_hdr_type *)(((char *)tlv_header) + length); - size -= length; - - } while (size > 0); - - - /*If received packet is hello with Parameter TLV*/ - if (ntohl(eigrph->ack) == 0) - { - /* increment statistics. */ - ei->hello_in++; - if (nbr) - eigrp_nbr_state_update(nbr); - - } - - if (IS_DEBUG_EIGRP_PACKET(0, RECV)) - zlog_debug("Hello Packet received from %s", inet_ntoa(nbr->src)); + struct eigrp_tlv_hdr_type *tlv_header; + struct eigrp_neighbor *nbr; + uint16_t type; + uint16_t length; + + /* get neighbor struct */ + nbr = eigrp_nbr_get(ei, eigrph, iph); + + /* neighbor must be valid, eigrp_nbr_get creates if none existed */ + assert(nbr); + + if (IS_DEBUG_EIGRP_PACKET(eigrph->opcode - 1, RECV)) + zlog_debug("Processing Hello size[%u] int(%s) nbr(%s)", size, + ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT), + inet_ntoa(nbr->src)); + + size -= EIGRP_HEADER_LEN; + if (size < 0) + return; + + tlv_header = (struct eigrp_tlv_hdr_type *)eigrph->tlv; + + do { + type = ntohs(tlv_header->type); + length = ntohs(tlv_header->length); + + if ((length > 0) && (length <= size)) { + if (IS_DEBUG_EIGRP_PACKET(0, RECV)) + zlog_debug( + " General TLV(%s)", + lookup_msg(eigrp_general_tlv_type_str, + type, NULL)); + + // determine what General TLV is being processed + switch (type) { + case EIGRP_TLV_PARAMETER: + nbr = eigrp_hello_parameter_decode(nbr, + tlv_header); + if (!nbr) + return; + break; + case EIGRP_TLV_AUTH: { + if (eigrp_hello_authentication_decode( + s, tlv_header, nbr) + == 0) + return; + else + break; + break; + } + case EIGRP_TLV_SEQ: + break; + case EIGRP_TLV_SW_VERSION: + eigrp_sw_version_decode(nbr, tlv_header); + break; + case EIGRP_TLV_NEXT_MCAST_SEQ: + break; + case EIGRP_TLV_PEER_TERMINATION: + eigrp_peer_termination_decode(nbr, tlv_header); + return; + break; + case EIGRP_TLV_PEER_MTRLIST: + case EIGRP_TLV_PEER_TIDLIST: + break; + default: + break; + } + } + + tlv_header = (struct eigrp_tlv_hdr_type *)(((char *)tlv_header) + + length); + size -= length; + + } while (size > 0); + + + /*If received packet is hello with Parameter TLV*/ + if (ntohl(eigrph->ack) == 0) { + /* increment statistics. */ + ei->hello_in++; + if (nbr) + eigrp_nbr_state_update(nbr); + } + + if (IS_DEBUG_EIGRP_PACKET(0, RECV)) + zlog_debug("Hello Packet received from %s", + inet_ntoa(nbr->src)); } /** @@ -413,25 +417,24 @@ eigrp_hello_receive (struct eigrp *eigrp, struct ip *iph, struct eigrp_header *e * This consists of two bytes of OS version, and two bytes of EIGRP * revision number. */ -static u_int16_t -eigrp_sw_version_encode (struct stream *s) +static u_int16_t eigrp_sw_version_encode(struct stream *s) { - u_int16_t length = EIGRP_TLV_SW_VERSION_LEN; + u_int16_t length = EIGRP_TLV_SW_VERSION_LEN; - // setup the tlv fields - stream_putw(s, EIGRP_TLV_SW_VERSION); - stream_putw(s, length); + // setup the tlv fields + stream_putw(s, EIGRP_TLV_SW_VERSION); + stream_putw(s, length); - // encode the version of quagga we're running - // DVS: need to figure out a cleaner way to do this - stream_putc(s, 0); //!< major os version - stream_putc(s, 99); //!< minor os version + // encode the version of quagga we're running + // DVS: need to figure out a cleaner way to do this + stream_putc(s, 0); //!< major os version + stream_putc(s, 99); //!< minor os version - /* and the core eigrp version */ - stream_putc(s, EIGRP_MAJOR_VERSION); - stream_putc(s, EIGRP_MINOR_VERSION); + /* and the core eigrp version */ + stream_putc(s, EIGRP_MAJOR_VERSION); + stream_putc(s, EIGRP_MINOR_VERSION); - return(length); + return (length); } /** @@ -445,11 +448,10 @@ eigrp_sw_version_encode (struct stream *s) * If doing mutli-topology, then store the supported TID list. * This is currently a place holder function */ -static u_int16_t -eigrp_tidlist_encode (struct stream *s) +static u_int16_t eigrp_tidlist_encode(struct stream *s) { - //u_int16_t length = EIGRP_TLV_SW_VERSION_LEN; - return 0; + // u_int16_t length = EIGRP_TLV_SW_VERSION_LEN; + return 0; } /** @@ -463,55 +465,50 @@ eigrp_tidlist_encode (struct stream *s) * Part of conditional receive process * */ -static u_int16_t -eigrp_sequence_encode (struct stream *s) +static u_int16_t eigrp_sequence_encode(struct stream *s) { - u_int16_t length = EIGRP_TLV_SEQ_BASE_LEN; - struct eigrp *eigrp; - struct eigrp_interface *ei; - struct listnode *node, *node2, *nnode2; - struct eigrp_neighbor *nbr; - size_t backup_end, size_end; - int found; - - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - return 0; - } - - // add in the parameters TLV - backup_end = stream_get_endp(s); - stream_putw(s, EIGRP_TLV_SEQ); - size_end = s->endp; - stream_putw(s, 0x0000); - stream_putc(s, IPV4_MAX_BYTELEN); - - found = 0; - for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei)) - { - for (ALL_LIST_ELEMENTS (ei->nbrs, node2, nnode2, nbr)) - { - if(nbr->multicast_queue->count > 0) - { - length += (u_int16_t) stream_put_ipv4(s,nbr->src.s_addr); - found = 1; - } - } - } - - if(found == 0) - { - stream_set_endp(s,backup_end); - return 0; - } - - backup_end = stream_get_endp (s); - stream_set_endp (s,size_end); - stream_putw (s, length); - stream_set_endp (s, backup_end); - - return length; + u_int16_t length = EIGRP_TLV_SEQ_BASE_LEN; + struct eigrp *eigrp; + struct eigrp_interface *ei; + struct listnode *node, *node2, *nnode2; + struct eigrp_neighbor *nbr; + size_t backup_end, size_end; + int found; + + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + return 0; + } + + // add in the parameters TLV + backup_end = stream_get_endp(s); + stream_putw(s, EIGRP_TLV_SEQ); + size_end = s->endp; + stream_putw(s, 0x0000); + stream_putc(s, IPV4_MAX_BYTELEN); + + found = 0; + for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) { + for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) { + if (nbr->multicast_queue->count > 0) { + length += (u_int16_t)stream_put_ipv4( + s, nbr->src.s_addr); + found = 1; + } + } + } + + if (found == 0) { + stream_set_endp(s, backup_end); + return 0; + } + + backup_end = stream_get_endp(s); + stream_set_endp(s, size_end); + stream_putw(s, length); + stream_set_endp(s, backup_end); + + return length; } /** @@ -525,24 +522,22 @@ eigrp_sequence_encode (struct stream *s) * Part of conditional receive process * */ -static u_int16_t -eigrp_next_sequence_encode (struct stream *s) +static u_int16_t eigrp_next_sequence_encode(struct stream *s) { - u_int16_t length = EIGRP_NEXT_SEQUENCE_TLV_SIZE; - struct eigrp *eigrp; + u_int16_t length = EIGRP_NEXT_SEQUENCE_TLV_SIZE; + struct eigrp *eigrp; - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - return 0; - } + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + return 0; + } - // add in the parameters TLV - stream_putw(s, EIGRP_TLV_NEXT_MCAST_SEQ); - stream_putw(s, EIGRP_NEXT_SEQUENCE_TLV_SIZE); - stream_putl(s,eigrp->sequence_number+1); + // add in the parameters TLV + stream_putw(s, EIGRP_TLV_NEXT_MCAST_SEQ); + stream_putw(s, EIGRP_NEXT_SEQUENCE_TLV_SIZE); + stream_putl(s, eigrp->sequence_number + 1); - return length; + return length; } /** @@ -560,39 +555,38 @@ eigrp_next_sequence_encode (struct stream *s) * Note the addition of K6 for the new extended metrics, and does not apply to * older TLV packet formats. */ -static u_int16_t -eigrp_hello_parameter_encode (struct eigrp_interface *ei, struct stream *s, u_char flags) +static u_int16_t eigrp_hello_parameter_encode(struct eigrp_interface *ei, + struct stream *s, u_char flags) { - u_int16_t length = EIGRP_TLV_PARAMETER_LEN; - - // add in the parameters TLV - stream_putw(s, EIGRP_TLV_PARAMETER); - stream_putw(s, EIGRP_TLV_PARAMETER_LEN); - - //if graceful shutdown is needed to be announced, send all 255 in K values - if(flags & EIGRP_HELLO_GRACEFUL_SHUTDOWN) - { - stream_putc(s, 0xff); /* K1 */ - stream_putc(s, 0xff); /* K2 */ - stream_putc(s, 0xff); /* K3 */ - stream_putc(s, 0xff); /* K4 */ - stream_putc(s, 0xff); /* K5 */ - stream_putc(s, 0xff); /* K6 */ - } - else // set k values - { - stream_putc(s, ei->eigrp->k_values[0]); /* K1 */ - stream_putc(s, ei->eigrp->k_values[1]); /* K2 */ - stream_putc(s, ei->eigrp->k_values[2]); /* K3 */ - stream_putc(s, ei->eigrp->k_values[3]); /* K4 */ - stream_putc(s, ei->eigrp->k_values[4]); /* K5 */ - stream_putc(s, ei->eigrp->k_values[5]); /* K6 */ - } - - // and set hold time value.. - stream_putw(s, IF_DEF_PARAMS(ei->ifp)->v_wait); - - return length; + u_int16_t length = EIGRP_TLV_PARAMETER_LEN; + + // add in the parameters TLV + stream_putw(s, EIGRP_TLV_PARAMETER); + stream_putw(s, EIGRP_TLV_PARAMETER_LEN); + + // if graceful shutdown is needed to be announced, send all 255 in K + // values + if (flags & EIGRP_HELLO_GRACEFUL_SHUTDOWN) { + stream_putc(s, 0xff); /* K1 */ + stream_putc(s, 0xff); /* K2 */ + stream_putc(s, 0xff); /* K3 */ + stream_putc(s, 0xff); /* K4 */ + stream_putc(s, 0xff); /* K5 */ + stream_putc(s, 0xff); /* K6 */ + } else // set k values + { + stream_putc(s, ei->eigrp->k_values[0]); /* K1 */ + stream_putc(s, ei->eigrp->k_values[1]); /* K2 */ + stream_putc(s, ei->eigrp->k_values[2]); /* K3 */ + stream_putc(s, ei->eigrp->k_values[3]); /* K4 */ + stream_putc(s, ei->eigrp->k_values[4]); /* K5 */ + stream_putc(s, ei->eigrp->k_values[5]); /* K6 */ + } + + // and set hold time value.. + stream_putw(s, IF_DEF_PARAMS(ei->ifp)->v_wait); + + return length; } /** @@ -602,7 +596,8 @@ eigrp_hello_parameter_encode (struct eigrp_interface *ei, struct stream *s, u_ch * @param[in] s packet stream TLV is stored to * @param[in] ack if non-zero, neigbors sequence packet to ack * @param[in] flags type of hello packet - * @param[in] nbr_addr pointer to neighbor address for Peer Termination TLV + * @param[in] nbr_addr pointer to neighbor address for Peer + * Termination TLV * * @return eigrp_packet pointer initialize hello packet * @@ -610,77 +605,77 @@ eigrp_hello_parameter_encode (struct eigrp_interface *ei, struct stream *s, u_ch * Allocate an EIGRP hello packet, and add in the the approperate TLVs * */ -static struct eigrp_packet * -eigrp_hello_encode (struct eigrp_interface *ei, in_addr_t addr, u_int32_t ack, - u_char flags, struct in_addr *nbr_addr) +static struct eigrp_packet *eigrp_hello_encode(struct eigrp_interface *ei, + in_addr_t addr, u_int32_t ack, + u_char flags, + struct in_addr *nbr_addr) { - struct eigrp_packet *ep; - u_int16_t length = EIGRP_HEADER_LEN; - - // allocate a new packet to be sent - ep = eigrp_packet_new(ei->ifp->mtu); - - if (ep) - { - // encode common header feilds - eigrp_packet_header_init(EIGRP_OPC_HELLO, ei, ep->s, 0, 0, ack); - - // encode Authentication TLV - if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && - (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL)) - { - length += eigrp_add_authTLV_MD5_to_stream(ep->s,ei); - } - else if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_SHA256) && - (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL)) - { - length += eigrp_add_authTLV_SHA256_to_stream(ep->s,ei); - } - - /* encode appropriate parameters to Hello packet */ - if(flags & EIGRP_HELLO_GRACEFUL_SHUTDOWN) - length += eigrp_hello_parameter_encode(ei, ep->s, EIGRP_HELLO_GRACEFUL_SHUTDOWN); - else - length += eigrp_hello_parameter_encode(ei, ep->s, EIGRP_HELLO_NORMAL); - - // figure out the version of code we're running - length += eigrp_sw_version_encode(ep->s); - - if(flags & EIGRP_HELLO_ADD_SEQUENCE) - { - length += eigrp_sequence_encode(ep->s); - length += eigrp_next_sequence_encode(ep->s); - } - - // add in the TID list if doing multi-topology - length += eigrp_tidlist_encode(ep->s); - - /* encode Peer Termination TLV if needed */ - if(flags & EIGRP_HELLO_GRACEFUL_SHUTDOWN_NBR) - length += eigrp_peer_termination_encode(ep->s, nbr_addr); - - // Set packet length - ep->length = length; - - // set soruce address for the hello packet - ep->dst.s_addr = addr; - - if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && - (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL)) - { - eigrp_make_md5_digest(ei,ep->s, EIGRP_AUTH_BASIC_HELLO_FLAG); - } - else if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_SHA256) && - (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL)) - { - eigrp_make_sha256_digest(ei,ep->s, EIGRP_AUTH_BASIC_HELLO_FLAG); - } - - // EIGRP Checksum - eigrp_packet_checksum(ei, ep->s, length); - } - - return(ep); + struct eigrp_packet *ep; + u_int16_t length = EIGRP_HEADER_LEN; + + // allocate a new packet to be sent + ep = eigrp_packet_new(ei->ifp->mtu); + + if (ep) { + // encode common header feilds + eigrp_packet_header_init(EIGRP_OPC_HELLO, ei, ep->s, 0, 0, ack); + + // encode Authentication TLV + if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) + && (IF_DEF_PARAMS(ei->ifp)->auth_keychain != NULL)) { + length += eigrp_add_authTLV_MD5_to_stream(ep->s, ei); + } else if ((IF_DEF_PARAMS(ei->ifp)->auth_type + == EIGRP_AUTH_TYPE_SHA256) + && (IF_DEF_PARAMS(ei->ifp)->auth_keychain != NULL)) { + length += eigrp_add_authTLV_SHA256_to_stream(ep->s, ei); + } + + /* encode appropriate parameters to Hello packet */ + if (flags & EIGRP_HELLO_GRACEFUL_SHUTDOWN) + length += eigrp_hello_parameter_encode( + ei, ep->s, EIGRP_HELLO_GRACEFUL_SHUTDOWN); + else + length += eigrp_hello_parameter_encode( + ei, ep->s, EIGRP_HELLO_NORMAL); + + // figure out the version of code we're running + length += eigrp_sw_version_encode(ep->s); + + if (flags & EIGRP_HELLO_ADD_SEQUENCE) { + length += eigrp_sequence_encode(ep->s); + length += eigrp_next_sequence_encode(ep->s); + } + + // add in the TID list if doing multi-topology + length += eigrp_tidlist_encode(ep->s); + + /* encode Peer Termination TLV if needed */ + if (flags & EIGRP_HELLO_GRACEFUL_SHUTDOWN_NBR) + length += + eigrp_peer_termination_encode(ep->s, nbr_addr); + + // Set packet length + ep->length = length; + + // set soruce address for the hello packet + ep->dst.s_addr = addr; + + if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) + && (IF_DEF_PARAMS(ei->ifp)->auth_keychain != NULL)) { + eigrp_make_md5_digest(ei, ep->s, + EIGRP_AUTH_BASIC_HELLO_FLAG); + } else if ((IF_DEF_PARAMS(ei->ifp)->auth_type + == EIGRP_AUTH_TYPE_SHA256) + && (IF_DEF_PARAMS(ei->ifp)->auth_keychain != NULL)) { + eigrp_make_sha256_digest(ei, ep->s, + EIGRP_AUTH_BASIC_HELLO_FLAG); + } + + // EIGRP Checksum + eigrp_packet_checksum(ei, ep->s, length); + } + + return (ep); } /** @@ -696,32 +691,32 @@ eigrp_hello_encode (struct eigrp_interface *ei, in_addr_t addr, u_int32_t ack, * updated to the neighbor's sequence number to acknolodge any * outstanding packets */ -void -eigrp_hello_send_ack (struct eigrp_neighbor *nbr) +void eigrp_hello_send_ack(struct eigrp_neighbor *nbr) { - struct eigrp_packet *ep; - - /* if packet succesfully created, add it to the interface queue */ - ep = eigrp_hello_encode(nbr->ei, nbr->src.s_addr, nbr->recv_sequence_number, EIGRP_HELLO_NORMAL, NULL); - - if (ep) - { - if (IS_DEBUG_EIGRP_PACKET(0, SEND)) - zlog_debug("Queueing [Hello] Ack Seq [%u] nbr [%s]", - nbr->recv_sequence_number, inet_ntoa(nbr->src)); - - /* Add packet to the top of the interface output queue*/ - eigrp_fifo_push_head(nbr->ei->obuf, ep); - - /* Hook thread to write packet. */ - if (nbr->ei->on_write_q == 0) - { - listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei); - nbr->ei->on_write_q = 1; - } - thread_add_write(master, eigrp_write, nbr->ei->eigrp, nbr->ei->eigrp->fd, - &nbr->ei->eigrp->t_write); - } + struct eigrp_packet *ep; + + /* if packet succesfully created, add it to the interface queue */ + ep = eigrp_hello_encode(nbr->ei, nbr->src.s_addr, + nbr->recv_sequence_number, EIGRP_HELLO_NORMAL, + NULL); + + if (ep) { + if (IS_DEBUG_EIGRP_PACKET(0, SEND)) + zlog_debug("Queueing [Hello] Ack Seq [%u] nbr [%s]", + nbr->recv_sequence_number, + inet_ntoa(nbr->src)); + + /* Add packet to the top of the interface output queue*/ + eigrp_fifo_push_head(nbr->ei->obuf, ep); + + /* Hook thread to write packet. */ + if (nbr->ei->on_write_q == 0) { + listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei); + nbr->ei->on_write_q = 1; + } + thread_add_write(master, eigrp_write, nbr->ei->eigrp, + nbr->ei->eigrp->fd, &nbr->ei->eigrp->t_write); + } } /** @@ -729,7 +724,8 @@ eigrp_hello_send_ack (struct eigrp_neighbor *nbr) * * @param[in] ei pointer to interface hello should be sent * @param[in] flags type of hello packet - * @param[in] nbr_addr pointer to neighbor address for Peer Termination TLV + * @param[in] nbr_addr pointer to neighbor address for Peer + * Termination TLV * * @return void * @@ -738,46 +734,44 @@ eigrp_hello_send_ack (struct eigrp_neighbor *nbr) * sending. If no packets are currently queues, the packet will be * sent immadiatly */ -void -eigrp_hello_send (struct eigrp_interface *ei, u_char flags, struct in_addr *nbr_addr) +void eigrp_hello_send(struct eigrp_interface *ei, u_char flags, + struct in_addr *nbr_addr) { - struct eigrp_packet *ep = NULL; - - /* If this is passive interface, do not send EIGRP Hello. - if ((EIGRP_IF_PASSIVE_STATUS (ei) == EIGRP_IF_PASSIVE) || - (ei->type != EIGRP_IFTYPE_NBMA)) - return; - */ - - if (IS_DEBUG_EIGRP_PACKET(0, SEND)) - zlog_debug("Queueing [Hello] Interface(%s)", IF_NAME(ei)); - - /* if packet was succesfully created, then add it to the interface queue */ - ep = eigrp_hello_encode(ei, htonl(EIGRP_MULTICAST_ADDRESS), 0, flags, nbr_addr); - - if (ep) - { - // Add packet to the top of the interface output queue - eigrp_fifo_push_head(ei->obuf, ep); - - /* Hook thread to write packet. */ - if (ei->on_write_q == 0) - { - listnode_add(ei->eigrp->oi_write_q, ei); - ei->on_write_q = 1; - } - - if (ei->eigrp->t_write == NULL) - { - if(flags & EIGRP_HELLO_GRACEFUL_SHUTDOWN) - { - thread_execute(master, eigrp_write, ei->eigrp, ei->eigrp->fd); - } - else - { - thread_add_write(master, eigrp_write, ei->eigrp, ei->eigrp->fd, - &ei->eigrp->t_write); - } - } - } + struct eigrp_packet *ep = NULL; + + /* If this is passive interface, do not send EIGRP Hello. + if ((EIGRP_IF_PASSIVE_STATUS (ei) == EIGRP_IF_PASSIVE) || + (ei->type != EIGRP_IFTYPE_NBMA)) + return; + */ + + if (IS_DEBUG_EIGRP_PACKET(0, SEND)) + zlog_debug("Queueing [Hello] Interface(%s)", IF_NAME(ei)); + + /* if packet was succesfully created, then add it to the interface queue + */ + ep = eigrp_hello_encode(ei, htonl(EIGRP_MULTICAST_ADDRESS), 0, flags, + nbr_addr); + + if (ep) { + // Add packet to the top of the interface output queue + eigrp_fifo_push_head(ei->obuf, ep); + + /* Hook thread to write packet. */ + if (ei->on_write_q == 0) { + listnode_add(ei->eigrp->oi_write_q, ei); + ei->on_write_q = 1; + } + + if (ei->eigrp->t_write == NULL) { + if (flags & EIGRP_HELLO_GRACEFUL_SHUTDOWN) { + thread_execute(master, eigrp_write, ei->eigrp, + ei->eigrp->fd); + } else { + thread_add_write(master, eigrp_write, ei->eigrp, + ei->eigrp->fd, + &ei->eigrp->t_write); + } + } + } } diff --git a/eigrpd/eigrp_interface.c b/eigrpd/eigrp_interface.c index a9deafe25..2312cc6ed 100644 --- a/eigrpd/eigrp_interface.c +++ b/eigrpd/eigrp_interface.c @@ -54,470 +54,448 @@ #include "eigrpd/eigrp_topology.h" #include "eigrpd/eigrp_memory.h" -static void -eigrp_delete_from_if (struct interface *, struct eigrp_interface *); +static void eigrp_delete_from_if(struct interface *, struct eigrp_interface *); -static void -eigrp_add_to_if (struct interface *ifp, struct eigrp_interface *ei) +static void eigrp_add_to_if(struct interface *ifp, struct eigrp_interface *ei) { - struct route_node *rn; - struct prefix p; - - p = *ei->address; - p.prefixlen = IPV4_MAX_PREFIXLEN; - - rn = route_node_get (IF_OIFS (ifp), &p); - /* rn->info should either be NULL or equal to this ei - * as route_node_get may return an existing node - */ - assert (!rn->info || rn->info == ei); - rn->info = ei; + struct route_node *rn; + struct prefix p; + + p = *ei->address; + p.prefixlen = IPV4_MAX_PREFIXLEN; + + rn = route_node_get(IF_OIFS(ifp), &p); + /* rn->info should either be NULL or equal to this ei + * as route_node_get may return an existing node + */ + assert(!rn->info || rn->info == ei); + rn->info = ei; } -struct eigrp_interface * -eigrp_if_new (struct eigrp *eigrp, struct interface *ifp, struct prefix *p) +struct eigrp_interface *eigrp_if_new(struct eigrp *eigrp, struct interface *ifp, + struct prefix *p) { - struct eigrp_interface *ei; - int i; + struct eigrp_interface *ei; + int i; - if ((ei = eigrp_if_table_lookup (ifp, p)) == NULL) - { - ei = XCALLOC (MTYPE_EIGRP_IF, sizeof (struct eigrp_interface)); - memset (ei, 0, sizeof (struct eigrp_interface)); - } - else - return ei; + if ((ei = eigrp_if_table_lookup(ifp, p)) == NULL) { + ei = XCALLOC(MTYPE_EIGRP_IF, sizeof(struct eigrp_interface)); + memset(ei, 0, sizeof(struct eigrp_interface)); + } else + return ei; - /* Set zebra interface pointer. */ - ei->ifp = ifp; - ei->address = p; + /* Set zebra interface pointer. */ + ei->ifp = ifp; + ei->address = p; - eigrp_add_to_if (ifp, ei); - listnode_add (eigrp->eiflist, ei); + eigrp_add_to_if(ifp, ei); + listnode_add(eigrp->eiflist, ei); - ei->type = EIGRP_IFTYPE_BROADCAST; + ei->type = EIGRP_IFTYPE_BROADCAST; - /* Initialize neighbor list. */ - ei->nbrs = list_new (); + /* Initialize neighbor list. */ + ei->nbrs = list_new(); - ei->crypt_seqnum = time (NULL); + ei->crypt_seqnum = time(NULL); - /* Initialize lists */ - for (i = 0; i < EIGRP_FILTER_MAX; i++) - { - ei->list[i] = NULL; - ei->prefix[i] = NULL; - ei->routemap[i] = NULL; - } + /* Initialize lists */ + for (i = 0; i < EIGRP_FILTER_MAX; i++) { + ei->list[i] = NULL; + ei->prefix[i] = NULL; + ei->routemap[i] = NULL; + } - return ei; + return ei; } /* lookup ei for specified prefix/ifp */ -struct eigrp_interface * -eigrp_if_table_lookup (struct interface *ifp, struct prefix *prefix) +struct eigrp_interface *eigrp_if_table_lookup(struct interface *ifp, + struct prefix *prefix) { - struct prefix p; - struct route_node *rn; - struct eigrp_interface *rninfo = NULL; + struct prefix p; + struct route_node *rn; + struct eigrp_interface *rninfo = NULL; - p = *prefix; - p.prefixlen = IPV4_MAX_PREFIXLEN; + p = *prefix; + p.prefixlen = IPV4_MAX_PREFIXLEN; - /* route_node_get implicitly locks */ - if ((rn = route_node_lookup (IF_OIFS (ifp), &p))) - { - rninfo = (struct eigrp_interface *) rn->info; - route_unlock_node (rn); - } + /* route_node_get implicitly locks */ + if ((rn = route_node_lookup(IF_OIFS(ifp), &p))) { + rninfo = (struct eigrp_interface *)rn->info; + route_unlock_node(rn); + } - return rninfo; + return rninfo; } -int -eigrp_if_delete_hook (struct interface *ifp) +int eigrp_if_delete_hook(struct interface *ifp) { - struct route_node *rn; + struct route_node *rn; - route_table_finish (IF_OIFS (ifp)); + route_table_finish(IF_OIFS(ifp)); - for (rn = route_top (IF_OIFS_PARAMS (ifp)); rn; rn = route_next (rn)) - if (rn->info) - eigrp_del_if_params (rn->info); - route_table_finish (IF_OIFS_PARAMS (ifp)); + for (rn = route_top(IF_OIFS_PARAMS(ifp)); rn; rn = route_next(rn)) + if (rn->info) + eigrp_del_if_params(rn->info); + route_table_finish(IF_OIFS_PARAMS(ifp)); - XFREE (MTYPE_EIGRP_IF_INFO, ifp->info); - ifp->info = NULL; + XFREE(MTYPE_EIGRP_IF_INFO, ifp->info); + ifp->info = NULL; - return 0; + return 0; } struct list *eigrp_iflist; -void -eigrp_if_init () +void eigrp_if_init() { - /* Initialize Zebra interface data structure. */ - if_add_hook (IF_NEW_HOOK, eigrp_if_new_hook); - if_add_hook (IF_DELETE_HOOK, eigrp_if_delete_hook); + /* Initialize Zebra interface data structure. */ + if_add_hook(IF_NEW_HOOK, eigrp_if_new_hook); + if_add_hook(IF_DELETE_HOOK, eigrp_if_delete_hook); } -int -eigrp_if_new_hook (struct interface *ifp) +int eigrp_if_new_hook(struct interface *ifp) { - int rc = 0; + int rc = 0; - ifp->info = XCALLOC (MTYPE_EIGRP_IF_INFO, sizeof (struct eigrp_if_info)); + ifp->info = XCALLOC(MTYPE_EIGRP_IF_INFO, sizeof(struct eigrp_if_info)); - IF_OIFS (ifp) = route_table_init (); - IF_OIFS_PARAMS (ifp) = route_table_init (); + IF_OIFS(ifp) = route_table_init(); + IF_OIFS_PARAMS(ifp) = route_table_init(); - IF_DEF_PARAMS (ifp) = eigrp_new_if_params (); + IF_DEF_PARAMS(ifp) = eigrp_new_if_params(); - SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_hello); - IF_DEF_PARAMS (ifp)->v_hello = (u_int32_t) EIGRP_HELLO_INTERVAL_DEFAULT; + SET_IF_PARAM(IF_DEF_PARAMS(ifp), v_hello); + IF_DEF_PARAMS(ifp)->v_hello = (u_int32_t)EIGRP_HELLO_INTERVAL_DEFAULT; - SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_wait); - IF_DEF_PARAMS (ifp)->v_wait = (u_int16_t) EIGRP_HOLD_INTERVAL_DEFAULT; + SET_IF_PARAM(IF_DEF_PARAMS(ifp), v_wait); + IF_DEF_PARAMS(ifp)->v_wait = (u_int16_t)EIGRP_HOLD_INTERVAL_DEFAULT; - SET_IF_PARAM (IF_DEF_PARAMS (ifp), bandwidth); - IF_DEF_PARAMS (ifp)->bandwidth = (u_int32_t) EIGRP_BANDWIDTH_DEFAULT; + SET_IF_PARAM(IF_DEF_PARAMS(ifp), bandwidth); + IF_DEF_PARAMS(ifp)->bandwidth = (u_int32_t)EIGRP_BANDWIDTH_DEFAULT; - SET_IF_PARAM (IF_DEF_PARAMS (ifp), delay); - IF_DEF_PARAMS (ifp)->delay = (u_int32_t) EIGRP_DELAY_DEFAULT; + SET_IF_PARAM(IF_DEF_PARAMS(ifp), delay); + IF_DEF_PARAMS(ifp)->delay = (u_int32_t)EIGRP_DELAY_DEFAULT; - SET_IF_PARAM (IF_DEF_PARAMS (ifp), reliability); - IF_DEF_PARAMS (ifp)->reliability = (u_char) EIGRP_RELIABILITY_DEFAULT; + SET_IF_PARAM(IF_DEF_PARAMS(ifp), reliability); + IF_DEF_PARAMS(ifp)->reliability = (u_char)EIGRP_RELIABILITY_DEFAULT; - SET_IF_PARAM (IF_DEF_PARAMS (ifp), load); - IF_DEF_PARAMS (ifp)->load = (u_char) EIGRP_LOAD_DEFAULT; + SET_IF_PARAM(IF_DEF_PARAMS(ifp), load); + IF_DEF_PARAMS(ifp)->load = (u_char)EIGRP_LOAD_DEFAULT; - SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_type); - IF_DEF_PARAMS (ifp)->auth_type = EIGRP_AUTH_TYPE_NONE; + SET_IF_PARAM(IF_DEF_PARAMS(ifp), auth_type); + IF_DEF_PARAMS(ifp)->auth_type = EIGRP_AUTH_TYPE_NONE; - SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_keychain); - IF_DEF_PARAMS (ifp)->auth_keychain= NULL; + SET_IF_PARAM(IF_DEF_PARAMS(ifp), auth_keychain); + IF_DEF_PARAMS(ifp)->auth_keychain = NULL; - return rc; + return rc; } -struct eigrp_if_params * -eigrp_new_if_params (void) +struct eigrp_if_params *eigrp_new_if_params(void) { - struct eigrp_if_params *eip; - - eip = XCALLOC (MTYPE_EIGRP_IF_PARAMS, sizeof (struct eigrp_if_params)); - if (!eip) - return NULL; - - UNSET_IF_PARAM (eip, passive_interface); - UNSET_IF_PARAM (eip, v_hello); - UNSET_IF_PARAM (eip, v_wait); - UNSET_IF_PARAM (eip, bandwidth); - UNSET_IF_PARAM (eip, delay); - UNSET_IF_PARAM (eip, reliability); - UNSET_IF_PARAM (eip, load); - UNSET_IF_PARAM (eip, auth_keychain); - UNSET_IF_PARAM (eip, auth_type); - - return eip; + struct eigrp_if_params *eip; + + eip = XCALLOC(MTYPE_EIGRP_IF_PARAMS, sizeof(struct eigrp_if_params)); + if (!eip) + return NULL; + + UNSET_IF_PARAM(eip, passive_interface); + UNSET_IF_PARAM(eip, v_hello); + UNSET_IF_PARAM(eip, v_wait); + UNSET_IF_PARAM(eip, bandwidth); + UNSET_IF_PARAM(eip, delay); + UNSET_IF_PARAM(eip, reliability); + UNSET_IF_PARAM(eip, load); + UNSET_IF_PARAM(eip, auth_keychain); + UNSET_IF_PARAM(eip, auth_type); + + return eip; } -void -eigrp_del_if_params (struct eigrp_if_params *eip) +void eigrp_del_if_params(struct eigrp_if_params *eip) { - if(eip->auth_keychain) - free(eip->auth_keychain); + if (eip->auth_keychain) + free(eip->auth_keychain); - XFREE (MTYPE_EIGRP_IF_PARAMS, eip); + XFREE(MTYPE_EIGRP_IF_PARAMS, eip); } -struct eigrp_if_params * -eigrp_lookup_if_params (struct interface *ifp, struct in_addr addr) +struct eigrp_if_params *eigrp_lookup_if_params(struct interface *ifp, + struct in_addr addr) { - struct prefix_ipv4 p; - struct route_node *rn; + struct prefix_ipv4 p; + struct route_node *rn; - p.family = AF_INET; - p.prefixlen = IPV4_MAX_PREFIXLEN; - p.prefix = addr; + p.family = AF_INET; + p.prefixlen = IPV4_MAX_PREFIXLEN; + p.prefix = addr; - rn = route_node_lookup (IF_OIFS_PARAMS (ifp), (struct prefix*) &p); + rn = route_node_lookup(IF_OIFS_PARAMS(ifp), (struct prefix *)&p); - if (rn) - { - route_unlock_node (rn); - return rn->info; - } + if (rn) { + route_unlock_node(rn); + return rn->info; + } - return NULL; + return NULL; } -int -eigrp_if_up (struct eigrp_interface *ei) +int eigrp_if_up(struct eigrp_interface *ei) { - struct eigrp_prefix_entry *pe; - struct eigrp_neighbor_entry *ne; - struct eigrp_metrics metric; - struct eigrp_interface *ei2; - struct listnode *node, *nnode; - struct eigrp *eigrp = eigrp_lookup (); - - if (ei == NULL) - return 0; - - if (eigrp != NULL) - eigrp_adjust_sndbuflen (eigrp, ei->ifp->mtu); - else - zlog_warn ("%s: eigrp_lookup () returned NULL", __func__); - eigrp_if_stream_set (ei); - - /* Set multicast memberships appropriately for new state. */ - eigrp_if_set_multicast (ei); - - thread_add_event(master, eigrp_hello_timer, ei, (1), NULL); - - /*Prepare metrics*/ - metric.bandwith = eigrp_bandwidth_to_scaled (EIGRP_IF_PARAM (ei,bandwidth)); - metric.delay = eigrp_delay_to_scaled (EIGRP_IF_PARAM (ei,delay)); - metric.load = EIGRP_IF_PARAM (ei,load); - metric.reliability = EIGRP_IF_PARAM (ei,reliability); - metric.mtu[0] = 0xDC; - metric.mtu[1] = 0x05; - metric.mtu[2] = 0x00; - metric.hop_count = 0; - metric.flags = 0; - metric.tag = 0; - - /*Add connected entry to topology table*/ - - struct prefix_ipv4 dest_addr; - - dest_addr.family = AF_INET; - dest_addr.prefix = ei->connected->address->u.prefix4; - dest_addr.prefixlen = ei->connected->address->prefixlen; - apply_mask_ipv4 (&dest_addr); - pe = eigrp_topology_table_lookup_ipv4 (eigrp->topology_table, &dest_addr); - - if (pe == NULL) - { - pe = eigrp_prefix_entry_new (); - pe->serno = eigrp->serno; - pe->destination_ipv4 = prefix_ipv4_new (); - prefix_copy ((struct prefix *)pe->destination_ipv4, - (struct prefix *)&dest_addr); - pe->af = AF_INET; - pe->nt = EIGRP_TOPOLOGY_TYPE_CONNECTED; - - pe->state = EIGRP_FSM_STATE_PASSIVE; - pe->fdistance = eigrp_calculate_metrics (eigrp, metric); - pe->req_action |= EIGRP_FSM_NEED_UPDATE; - eigrp_prefix_entry_add (eigrp->topology_table, pe); - listnode_add(eigrp->topology_changes_internalIPV4, pe); - } - ne = eigrp_neighbor_entry_new (); - ne->ei = ei; - ne->reported_metric = metric; - ne->total_metric = metric; - ne->distance = eigrp_calculate_metrics (eigrp, metric); - ne->reported_distance = 0; - ne->prefix = pe; - ne->adv_router = eigrp->neighbor_self; - ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG; - eigrp_neighbor_entry_add (pe, ne); - - for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei2)) - { - if (ei2->nbrs->count != 0) - { - eigrp_update_send (ei2); - } - } - - pe->req_action &= ~EIGRP_FSM_NEED_UPDATE; - listnode_delete(eigrp->topology_changes_internalIPV4, pe); - - return 1; + struct eigrp_prefix_entry *pe; + struct eigrp_neighbor_entry *ne; + struct eigrp_metrics metric; + struct eigrp_interface *ei2; + struct listnode *node, *nnode; + struct eigrp *eigrp = eigrp_lookup(); + + if (ei == NULL) + return 0; + + if (eigrp != NULL) + eigrp_adjust_sndbuflen(eigrp, ei->ifp->mtu); + else + zlog_warn("%s: eigrp_lookup () returned NULL", __func__); + eigrp_if_stream_set(ei); + + /* Set multicast memberships appropriately for new state. */ + eigrp_if_set_multicast(ei); + + thread_add_event(master, eigrp_hello_timer, ei, (1), NULL); + + /*Prepare metrics*/ + metric.bandwith = + eigrp_bandwidth_to_scaled(EIGRP_IF_PARAM(ei, bandwidth)); + metric.delay = eigrp_delay_to_scaled(EIGRP_IF_PARAM(ei, delay)); + metric.load = EIGRP_IF_PARAM(ei, load); + metric.reliability = EIGRP_IF_PARAM(ei, reliability); + metric.mtu[0] = 0xDC; + metric.mtu[1] = 0x05; + metric.mtu[2] = 0x00; + metric.hop_count = 0; + metric.flags = 0; + metric.tag = 0; + + /*Add connected entry to topology table*/ + + struct prefix_ipv4 dest_addr; + + dest_addr.family = AF_INET; + dest_addr.prefix = ei->connected->address->u.prefix4; + dest_addr.prefixlen = ei->connected->address->prefixlen; + apply_mask_ipv4(&dest_addr); + pe = eigrp_topology_table_lookup_ipv4(eigrp->topology_table, + &dest_addr); + + if (pe == NULL) { + pe = eigrp_prefix_entry_new(); + pe->serno = eigrp->serno; + pe->destination_ipv4 = prefix_ipv4_new(); + prefix_copy((struct prefix *)pe->destination_ipv4, + (struct prefix *)&dest_addr); + pe->af = AF_INET; + pe->nt = EIGRP_TOPOLOGY_TYPE_CONNECTED; + + pe->state = EIGRP_FSM_STATE_PASSIVE; + pe->fdistance = eigrp_calculate_metrics(eigrp, metric); + pe->req_action |= EIGRP_FSM_NEED_UPDATE; + eigrp_prefix_entry_add(eigrp->topology_table, pe); + listnode_add(eigrp->topology_changes_internalIPV4, pe); + } + ne = eigrp_neighbor_entry_new(); + ne->ei = ei; + ne->reported_metric = metric; + ne->total_metric = metric; + ne->distance = eigrp_calculate_metrics(eigrp, metric); + ne->reported_distance = 0; + ne->prefix = pe; + ne->adv_router = eigrp->neighbor_self; + ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG; + eigrp_neighbor_entry_add(pe, ne); + + for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, ei2)) { + if (ei2->nbrs->count != 0) { + eigrp_update_send(ei2); + } + } + + pe->req_action &= ~EIGRP_FSM_NEED_UPDATE; + listnode_delete(eigrp->topology_changes_internalIPV4, pe); + + return 1; } -int -eigrp_if_down (struct eigrp_interface *ei) +int eigrp_if_down(struct eigrp_interface *ei) { - struct listnode *node, *nnode; - struct eigrp_neighbor *nbr; + struct listnode *node, *nnode; + struct eigrp_neighbor *nbr; - if (ei == NULL) - return 0; + if (ei == NULL) + return 0; - /* Shutdown packet reception and sending */ - if(ei->t_hello) - THREAD_OFF (ei->t_hello); + /* Shutdown packet reception and sending */ + if (ei->t_hello) + THREAD_OFF(ei->t_hello); - eigrp_if_stream_unset (ei); + eigrp_if_stream_unset(ei); - /*Set infinite metrics to routes learned by this interface and start query process*/ - for (ALL_LIST_ELEMENTS (ei->nbrs, node, nnode, nbr)) - { - eigrp_nbr_delete(nbr); - } + /*Set infinite metrics to routes learned by this interface and start + * query process*/ + for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) { + eigrp_nbr_delete(nbr); + } - return 1; + return 1; } -void -eigrp_if_stream_set (struct eigrp_interface *ei) +void eigrp_if_stream_set(struct eigrp_interface *ei) { - /* set output fifo queue. */ - if (ei->obuf == NULL) - ei->obuf = eigrp_fifo_new (); + /* set output fifo queue. */ + if (ei->obuf == NULL) + ei->obuf = eigrp_fifo_new(); } -void -eigrp_if_stream_unset (struct eigrp_interface *ei) +void eigrp_if_stream_unset(struct eigrp_interface *ei) { - struct eigrp *eigrp = ei->eigrp; - - if (ei->obuf) - { - eigrp_fifo_free (ei->obuf); - ei->obuf = NULL; - - if (ei->on_write_q) - { - listnode_delete (eigrp->oi_write_q, ei); - if (list_isempty (eigrp->oi_write_q)) - thread_cancel (eigrp->t_write); - ei->on_write_q = 0; - } - } + struct eigrp *eigrp = ei->eigrp; + + if (ei->obuf) { + eigrp_fifo_free(ei->obuf); + ei->obuf = NULL; + + if (ei->on_write_q) { + listnode_delete(eigrp->oi_write_q, ei); + if (list_isempty(eigrp->oi_write_q)) + thread_cancel(eigrp->t_write); + ei->on_write_q = 0; + } + } } -void -eigrp_if_set_multicast (struct eigrp_interface *ei) +void eigrp_if_set_multicast(struct eigrp_interface *ei) { - if ((EIGRP_IF_PASSIVE_STATUS (ei) == EIGRP_IF_ACTIVE)) - { - /* The interface should belong to the EIGRP-all-routers group. */ - if (!EI_MEMBER_CHECK (ei, MEMBER_ALLROUTERS) - && (eigrp_if_add_allspfrouters (ei->eigrp, ei->address, - ei->ifp->ifindex) >= 0)) - /* Set the flag only if the system call to join succeeded. */ - EI_MEMBER_JOINED (ei, MEMBER_ALLROUTERS); - } - else - { - /* The interface should NOT belong to the EIGRP-all-routers group. */ - if (EI_MEMBER_CHECK (ei, MEMBER_ALLROUTERS)) - { - /* Only actually drop if this is the last reference */ - if (EI_MEMBER_COUNT (ei, MEMBER_ALLROUTERS) == 1) - eigrp_if_drop_allspfrouters (ei->eigrp, ei->address, - ei->ifp->ifindex); - /* Unset the flag regardless of whether the system call to leave - the group succeeded, since it's much safer to assume that - we are not a member. */ - EI_MEMBER_LEFT (ei, MEMBER_ALLROUTERS); - } - } + if ((EIGRP_IF_PASSIVE_STATUS(ei) == EIGRP_IF_ACTIVE)) { + /* The interface should belong to the EIGRP-all-routers group. + */ + if (!EI_MEMBER_CHECK(ei, MEMBER_ALLROUTERS) + && (eigrp_if_add_allspfrouters(ei->eigrp, ei->address, + ei->ifp->ifindex) + >= 0)) + /* Set the flag only if the system call to join + * succeeded. */ + EI_MEMBER_JOINED(ei, MEMBER_ALLROUTERS); + } else { + /* The interface should NOT belong to the EIGRP-all-routers + * group. */ + if (EI_MEMBER_CHECK(ei, MEMBER_ALLROUTERS)) { + /* Only actually drop if this is the last reference */ + if (EI_MEMBER_COUNT(ei, MEMBER_ALLROUTERS) == 1) + eigrp_if_drop_allspfrouters(ei->eigrp, + ei->address, + ei->ifp->ifindex); + /* Unset the flag regardless of whether the system call + to leave + the group succeeded, since it's much safer to assume + that + we are not a member. */ + EI_MEMBER_LEFT(ei, MEMBER_ALLROUTERS); + } + } } -u_char -eigrp_default_iftype (struct interface *ifp) +u_char eigrp_default_iftype(struct interface *ifp) { - if (if_is_pointopoint (ifp)) - return EIGRP_IFTYPE_POINTOPOINT; - else if (if_is_loopback (ifp)) - return EIGRP_IFTYPE_LOOPBACK; - else - return EIGRP_IFTYPE_BROADCAST; + if (if_is_pointopoint(ifp)) + return EIGRP_IFTYPE_POINTOPOINT; + else if (if_is_loopback(ifp)) + return EIGRP_IFTYPE_LOOPBACK; + else + return EIGRP_IFTYPE_BROADCAST; } -void -eigrp_if_free (struct eigrp_interface *ei, int source) +void eigrp_if_free(struct eigrp_interface *ei, int source) { - struct prefix_ipv4 dest_addr; - struct eigrp_prefix_entry *pe; - struct eigrp *eigrp = eigrp_lookup (); - - if (source == INTERFACE_DOWN_BY_VTY) - { - THREAD_OFF (ei->t_hello); - eigrp_hello_send(ei,EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL); - } - - dest_addr.family = AF_INET; - dest_addr.prefix = ei->connected->address->u.prefix4; - dest_addr.prefixlen = ei->connected->address->prefixlen; - apply_mask_ipv4(&dest_addr); - pe = eigrp_topology_table_lookup_ipv4 (eigrp->topology_table, &dest_addr); - if (pe) - eigrp_prefix_entry_delete (eigrp->topology_table, pe); - - eigrp_if_down (ei); - - list_delete (ei->nbrs); - eigrp_delete_from_if (ei->ifp, ei); - listnode_delete (ei->eigrp->eiflist, ei); - - thread_cancel_event (master, ei); - - memset (ei, 0, sizeof (*ei)); - XFREE (MTYPE_EIGRP_IF, ei); + struct prefix_ipv4 dest_addr; + struct eigrp_prefix_entry *pe; + struct eigrp *eigrp = eigrp_lookup(); + + if (source == INTERFACE_DOWN_BY_VTY) { + THREAD_OFF(ei->t_hello); + eigrp_hello_send(ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL); + } + + dest_addr.family = AF_INET; + dest_addr.prefix = ei->connected->address->u.prefix4; + dest_addr.prefixlen = ei->connected->address->prefixlen; + apply_mask_ipv4(&dest_addr); + pe = eigrp_topology_table_lookup_ipv4(eigrp->topology_table, + &dest_addr); + if (pe) + eigrp_prefix_entry_delete(eigrp->topology_table, pe); + + eigrp_if_down(ei); + + list_delete(ei->nbrs); + eigrp_delete_from_if(ei->ifp, ei); + listnode_delete(ei->eigrp->eiflist, ei); + + thread_cancel_event(master, ei); + + memset(ei, 0, sizeof(*ei)); + XFREE(MTYPE_EIGRP_IF, ei); } -static void -eigrp_delete_from_if (struct interface *ifp, struct eigrp_interface *ei) +static void eigrp_delete_from_if(struct interface *ifp, + struct eigrp_interface *ei) { - struct route_node *rn; - struct prefix p; - - p = *ei->address; - p.prefixlen = IPV4_MAX_PREFIXLEN; - - rn = route_node_lookup (IF_OIFS (ei->ifp), &p); - assert (rn); - assert (rn->info); - rn->info = NULL; - route_unlock_node (rn); - route_unlock_node (rn); + struct route_node *rn; + struct prefix p; + + p = *ei->address; + p.prefixlen = IPV4_MAX_PREFIXLEN; + + rn = route_node_lookup(IF_OIFS(ei->ifp), &p); + assert(rn); + assert(rn->info); + rn->info = NULL; + route_unlock_node(rn); + route_unlock_node(rn); } /* Simulate down/up on the interface. This is needed, for example, when the MTU changes. */ -void -eigrp_if_reset (struct interface *ifp) +void eigrp_if_reset(struct interface *ifp) { - struct route_node *rn; + struct route_node *rn; - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - { - struct eigrp_interface *ei; + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct eigrp_interface *ei; - if ((ei = rn->info) == NULL) - continue; + if ((ei = rn->info) == NULL) + continue; - eigrp_if_down (ei); - eigrp_if_up (ei); - } + eigrp_if_down(ei); + eigrp_if_up(ei); + } } -struct eigrp_interface * -eigrp_if_lookup_by_local_addr (struct eigrp *eigrp, struct interface *ifp, - struct in_addr address) +struct eigrp_interface *eigrp_if_lookup_by_local_addr(struct eigrp *eigrp, + struct interface *ifp, + struct in_addr address) { - struct listnode *node; - struct eigrp_interface *ei; + struct listnode *node; + struct eigrp_interface *ei; - for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei)) - { - if (ifp && ei->ifp != ifp) - continue; + for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) { + if (ifp && ei->ifp != ifp) + continue; - if (IPV4_ADDR_SAME (&address, &ei->address->u.prefix4)) - return ei; - } + if (IPV4_ADDR_SAME(&address, &ei->address->u.prefix4)) + return ei; + } - return NULL; + return NULL; } /** @@ -531,92 +509,84 @@ eigrp_if_lookup_by_local_addr (struct eigrp *eigrp, struct interface *ifp, * @par * Function is used for lookup interface by name. */ -struct eigrp_interface * -eigrp_if_lookup_by_name (struct eigrp *eigrp, const char *if_name) +struct eigrp_interface *eigrp_if_lookup_by_name(struct eigrp *eigrp, + const char *if_name) { - struct eigrp_interface *ei; - struct listnode *node; - - /* iterate over all eigrp interfaces */ - for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei)) - { - /* compare int name with eigrp interface's name */ - if(strcmp(ei->ifp->name, if_name) == 0) - { - return ei; - } - } - - return NULL; + struct eigrp_interface *ei; + struct listnode *node; + + /* iterate over all eigrp interfaces */ + for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) { + /* compare int name with eigrp interface's name */ + if (strcmp(ei->ifp->name, if_name) == 0) { + return ei; + } + } + + return NULL; } /* determine receiving interface by ifp and source address */ -struct eigrp_interface * -eigrp_if_lookup_recv_if (struct eigrp *eigrp, struct in_addr src, - struct interface *ifp) +struct eigrp_interface *eigrp_if_lookup_recv_if(struct eigrp *eigrp, + struct in_addr src, + struct interface *ifp) { - struct route_node *rn; - struct prefix_ipv4 addr; - struct eigrp_interface *ei, *match; + struct route_node *rn; + struct prefix_ipv4 addr; + struct eigrp_interface *ei, *match; - addr.family = AF_INET; - addr.prefix = src; - addr.prefixlen = IPV4_MAX_BITLEN; + addr.family = AF_INET; + addr.prefix = src; + addr.prefixlen = IPV4_MAX_BITLEN; - match = NULL; + match = NULL; - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - { - ei = rn->info; + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + ei = rn->info; - if (!ei) /* oi can be NULL for PtP aliases */ - continue; + if (!ei) /* oi can be NULL for PtP aliases */ + continue; - if (if_is_loopback (ei->ifp)) - continue; + if (if_is_loopback(ei->ifp)) + continue; - if (prefix_match (CONNECTED_PREFIX (ei->connected), - (struct prefix *) &addr)) - { - if ((match == NULL) - || (match->address->prefixlen < ei->address->prefixlen)) - match = ei; - } - } + if (prefix_match(CONNECTED_PREFIX(ei->connected), + (struct prefix *)&addr)) { + if ((match == NULL) || (match->address->prefixlen + < ei->address->prefixlen)) + match = ei; + } + } - return match; + return match; } -u_int32_t -eigrp_bandwidth_to_scaled (u_int32_t bandwidth) +u_int32_t eigrp_bandwidth_to_scaled(u_int32_t bandwidth) { - uint64_t temp_bandwidth = (256ull * 10000000) / bandwidth; + uint64_t temp_bandwidth = (256ull * 10000000) / bandwidth; - temp_bandwidth = - temp_bandwidth < EIGRP_MAX_METRIC ? temp_bandwidth : EIGRP_MAX_METRIC; + temp_bandwidth = temp_bandwidth < EIGRP_MAX_METRIC ? temp_bandwidth + : EIGRP_MAX_METRIC; - return (u_int32_t) temp_bandwidth; + return (u_int32_t)temp_bandwidth; } -u_int32_t -eigrp_scaled_to_bandwidth (u_int32_t scaled) +u_int32_t eigrp_scaled_to_bandwidth(u_int32_t scaled) { - uint64_t temp_scaled = scaled * (256ull * 10000000); + uint64_t temp_scaled = scaled * (256ull * 10000000); - temp_scaled = - temp_scaled < EIGRP_MAX_METRIC ? temp_scaled : EIGRP_MAX_METRIC; + temp_scaled = + temp_scaled < EIGRP_MAX_METRIC ? temp_scaled : EIGRP_MAX_METRIC; - return (u_int32_t) temp_scaled; + return (u_int32_t)temp_scaled; } -u_int32_t -eigrp_delay_to_scaled (u_int32_t delay) +u_int32_t eigrp_delay_to_scaled(u_int32_t delay) { - return delay * 256; + return delay * 256; } -u_int32_t -eigrp_scaled_to_delay (u_int32_t scaled) +u_int32_t eigrp_scaled_to_delay(u_int32_t scaled) { - return scaled / 256; + return scaled / 256; } diff --git a/eigrpd/eigrp_interface.h b/eigrpd/eigrp_interface.h index 0c57f0cbd..df5c7d395 100644 --- a/eigrpd/eigrp_interface.h +++ b/eigrpd/eigrp_interface.h @@ -33,40 +33,41 @@ #define _ZEBRA_EIGRP_INTERFACE_H_ /*Prototypes*/ -extern void eigrp_if_init (void); -extern int eigrp_if_new_hook (struct interface *); -extern int eigrp_if_delete_hook (struct interface *); +extern void eigrp_if_init(void); +extern int eigrp_if_new_hook(struct interface *); +extern int eigrp_if_delete_hook(struct interface *); -extern void eigrp_del_if_params (struct eigrp_if_params *); -extern struct eigrp_if_params *eigrp_new_if_params (void); -extern struct eigrp_interface * eigrp_if_new (struct eigrp *, struct interface *, - struct prefix *); -extern struct eigrp_interface * eigrp_if_table_lookup (struct interface *, - struct prefix *); -extern struct eigrp_if_params *eigrp_lookup_if_params (struct interface *, - struct in_addr); -extern int eigrp_if_up (struct eigrp_interface *); -extern void eigrp_if_stream_set (struct eigrp_interface *); -extern void eigrp_if_set_multicast (struct eigrp_interface *); -extern u_char eigrp_default_iftype (struct interface *); -extern void eigrp_if_free (struct eigrp_interface *, int); -extern int eigrp_if_down (struct eigrp_interface *); -extern void eigrp_if_stream_unset (struct eigrp_interface *); +extern void eigrp_del_if_params(struct eigrp_if_params *); +extern struct eigrp_if_params *eigrp_new_if_params(void); +extern struct eigrp_interface *eigrp_if_new(struct eigrp *, struct interface *, + struct prefix *); +extern struct eigrp_interface *eigrp_if_table_lookup(struct interface *, + struct prefix *); +extern struct eigrp_if_params *eigrp_lookup_if_params(struct interface *, + struct in_addr); +extern int eigrp_if_up(struct eigrp_interface *); +extern void eigrp_if_stream_set(struct eigrp_interface *); +extern void eigrp_if_set_multicast(struct eigrp_interface *); +extern u_char eigrp_default_iftype(struct interface *); +extern void eigrp_if_free(struct eigrp_interface *, int); +extern int eigrp_if_down(struct eigrp_interface *); +extern void eigrp_if_stream_unset(struct eigrp_interface *); -extern struct eigrp_interface *eigrp_if_lookup_by_local_addr (struct eigrp *, - struct interface *, - struct in_addr); -extern struct eigrp_interface *eigrp_if_lookup_by_name (struct eigrp *, const char *); -struct eigrp_interface * eigrp_if_lookup_recv_if (struct eigrp *, struct in_addr, - struct interface *); +extern struct eigrp_interface *eigrp_if_lookup_by_local_addr(struct eigrp *, + struct interface *, + struct in_addr); +extern struct eigrp_interface *eigrp_if_lookup_by_name(struct eigrp *, + const char *); +struct eigrp_interface *eigrp_if_lookup_recv_if(struct eigrp *, struct in_addr, + struct interface *); /* Simulate down/up on the interface. */ -extern void eigrp_if_reset (struct interface *); +extern void eigrp_if_reset(struct interface *); -extern u_int32_t eigrp_bandwidth_to_scaled (u_int32_t); -extern u_int32_t eigrp_scaled_to_bandwidth (u_int32_t); -extern u_int32_t eigrp_delay_to_scaled (u_int32_t); -extern u_int32_t eigrp_scaled_to_delay (u_int32_t); +extern u_int32_t eigrp_bandwidth_to_scaled(u_int32_t); +extern u_int32_t eigrp_scaled_to_bandwidth(u_int32_t); +extern u_int32_t eigrp_delay_to_scaled(u_int32_t); +extern u_int32_t eigrp_scaled_to_delay(u_int32_t); #endif /* ZEBRA_EIGRP_INTERFACE_H_ */ diff --git a/eigrpd/eigrp_macros.h b/eigrpd/eigrp_macros.h index 08c2fc34c..fdb84673d 100644 --- a/eigrpd/eigrp_macros.h +++ b/eigrpd/eigrp_macros.h @@ -39,16 +39,18 @@ #define UNSET_IF_PARAM(S, P) ((S)->P##__config) = 0 #define EIGRP_IF_PARAM_CONFIGURED(S, P) ((S) && (S)->P##__config) -#define EIGRP_IF_PARAM(O, P) \ - (EIGRP_IF_PARAM_CONFIGURED ((O)->params, P)?\ - (O)->params->P:IF_DEF_PARAMS((O)->ifp)->P) +#define EIGRP_IF_PARAM(O, P) \ + (EIGRP_IF_PARAM_CONFIGURED((O)->params, P) \ + ? (O)->params->P \ + : IF_DEF_PARAMS((O)->ifp)->P) -#define EIGRP_IF_PASSIVE_STATUS(O) \ - (EIGRP_IF_PARAM_CONFIGURED((O)->params, passive_interface) ? \ - (O)->params->passive_interface : \ - (EIGRP_IF_PARAM_CONFIGURED(IF_DEF_PARAMS((O)->ifp), passive_interface) ? \ - IF_DEF_PARAMS((O)->ifp)->passive_interface : \ - (O)->eigrp->passive_interface_default)) +#define EIGRP_IF_PASSIVE_STATUS(O) \ + (EIGRP_IF_PARAM_CONFIGURED((O)->params, passive_interface) \ + ? (O)->params->passive_interface \ + : (EIGRP_IF_PARAM_CONFIGURED(IF_DEF_PARAMS((O)->ifp), \ + passive_interface) \ + ? IF_DEF_PARAMS((O)->ifp)->passive_interface \ + : (O)->eigrp->passive_interface_default)) //------------------------------------------------------------------------------------------------------------------------------------ @@ -60,25 +62,25 @@ /*Macros for EIGRP interface multicast membership*/ #define EI_MEMBER_FLAG(M) (1 << (M)) #define EI_MEMBER_COUNT(O,M) (IF_EIGRP_IF_INFO(ei->ifp)->membership_counts[(M)]) -#define EI_MEMBER_CHECK(O,M) \ - (CHECK_FLAG((O)->multicast_memberships, EI_MEMBER_FLAG(M))) -#define EI_MEMBER_JOINED(O,M) \ - do { \ - SET_FLAG ((O)->multicast_memberships, EI_MEMBER_FLAG(M)); \ - IF_EIGRP_IF_INFO((O)->ifp)->membership_counts[(M)]++; \ - } while (0) -#define EI_MEMBER_LEFT(O,M) \ - do { \ - UNSET_FLAG ((O)->multicast_memberships, EI_MEMBER_FLAG(M)); \ - IF_EIGRP_IF_INFO((O)->ifp)->membership_counts[(M)]--; \ - } while (0) +#define EI_MEMBER_CHECK(O, M) \ + (CHECK_FLAG((O)->multicast_memberships, EI_MEMBER_FLAG(M))) +#define EI_MEMBER_JOINED(O, M) \ + do { \ + SET_FLAG((O)->multicast_memberships, EI_MEMBER_FLAG(M)); \ + IF_EIGRP_IF_INFO((O)->ifp)->membership_counts[(M)]++; \ + } while (0) +#define EI_MEMBER_LEFT(O, M) \ + do { \ + UNSET_FLAG((O)->multicast_memberships, EI_MEMBER_FLAG(M)); \ + IF_EIGRP_IF_INFO((O)->ifp)->membership_counts[(M)]--; \ + } while (0) //----------------------------------------------------------------------------------------------------------------------------------- /* Topology Macros */ /* FSM macros*/ -#define EIGRP_FSM_EVENT_SCHEDULE(I,E) \ - thread_add_event (master, eigrp_fsm_event, (I), (E)) +#define EIGRP_FSM_EVENT_SCHEDULE(I, E) \ + thread_add_event(master, eigrp_fsm_event, (I), (E)) #endif /* _ZEBRA_EIGRP_MACROS_H_ */ diff --git a/eigrpd/eigrp_main.c b/eigrpd/eigrp_main.c index 08a1cb659..bc8bbb445 100644 --- a/eigrpd/eigrp_main.c +++ b/eigrpd/eigrp_main.c @@ -67,164 +67,146 @@ //#include "eigrpd/eigrp_routemap.h" /* eigprd privileges */ -zebra_capabilities_t _caps_p [] = -{ - ZCAP_NET_RAW, - ZCAP_BIND, - ZCAP_NET_ADMIN, +zebra_capabilities_t _caps_p[] = { + ZCAP_NET_RAW, ZCAP_BIND, ZCAP_NET_ADMIN, }; -struct zebra_privs_t eigrpd_privs = -{ -#if defined (FRR_USER) && defined (FRR_GROUP) - .user = FRR_USER, - .group = FRR_GROUP, +struct zebra_privs_t eigrpd_privs = { +#if defined(FRR_USER) && defined(FRR_GROUP) + .user = FRR_USER, + .group = FRR_GROUP, #endif -#if defined (VTY_GROUP) - .vty_group = VTY_GROUP, +#if defined(VTY_GROUP) + .vty_group = VTY_GROUP, #endif - .caps_p = _caps_p, - .cap_num_p = array_size (_caps_p), - .cap_num_i = 0 -}; + .caps_p = _caps_p, + .cap_num_p = array_size(_caps_p), + .cap_num_i = 0}; /* EIGRPd options. */ -struct option longopts[] = - { - { 0 } - }; +struct option longopts[] = {{0}}; /* Master of threads. */ struct thread_master *master; /* SIGHUP handler. */ -static void -sighup (void) +static void sighup(void) { - zlog_info ("SIGHUP received"); + zlog_info("SIGHUP received"); } /* SIGINT / SIGTERM handler. */ -static void -sigint (void) +static void sigint(void) { - zlog_notice ("Terminating on signal"); - eigrp_terminate (); + zlog_notice("Terminating on signal"); + eigrp_terminate(); } /* SIGUSR1 handler. */ -static void -sigusr1 (void) +static void sigusr1(void) { - zlog_rotate (); + zlog_rotate(); } -struct quagga_signal_t eigrp_signals[] = -{ - { - .signal = SIGHUP, - .handler = &sighup, - }, - { - .signal = SIGUSR1, - .handler = &sigusr1, - }, - { - .signal = SIGINT, - .handler = &sigint, - }, - { - .signal = SIGTERM, - .handler = &sigint, - }, +struct quagga_signal_t eigrp_signals[] = { + { + .signal = SIGHUP, + .handler = &sighup, + }, + { + .signal = SIGUSR1, + .handler = &sigusr1, + }, + { + .signal = SIGINT, + .handler = &sigint, + }, + { + .signal = SIGTERM, + .handler = &sigint, + }, }; -FRR_DAEMON_INFO(eigrpd, EIGRP, - .vty_port = EIGRP_VTY_PORT, +FRR_DAEMON_INFO(eigrpd, EIGRP, .vty_port = EIGRP_VTY_PORT, - .proghelp = "Implementation of the EIGRP routing protocol.", + .proghelp = "Implementation of the EIGRP routing protocol.", - .signals = eigrp_signals, - .n_signals = array_size(eigrp_signals), + .signals = eigrp_signals, + .n_signals = array_size(eigrp_signals), - .privs = &eigrpd_privs, - ) + .privs = &eigrpd_privs, ) /* EIGRPd main routine. */ -int -main (int argc, char **argv, char **envp) +int main(int argc, char **argv, char **envp) { - frr_preinit (&eigrpd_di, argc, argv); - frr_opt_add ("", longopts, ""); - - while (1) - { - int opt; - - opt = frr_getopt (argc, argv, NULL); - - if (opt == EOF) - break; - - switch (opt) - { - case 0: - break; - default: - frr_help_exit (1); - break; - } - } - - /* EIGRP master init. */ - eigrp_master_init (); - eigrp_om->master = frr_init(); - master = eigrp_om->master; - - vrf_init (NULL, NULL, NULL, NULL); - - /*EIGRPd init*/ - eigrp_if_init (); - eigrp_zebra_init (); - eigrp_debug_init (); - - /* Get configuration file. */ - /* EIGRP VTY inits */ - eigrp_vty_init (); - keychain_init(); - eigrp_vty_show_init (); - eigrp_vty_if_init (); + frr_preinit(&eigrpd_di, argc, argv); + frr_opt_add("", longopts, ""); + + while (1) { + int opt; + + opt = frr_getopt(argc, argv, NULL); + + if (opt == EOF) + break; + + switch (opt) { + case 0: + break; + default: + frr_help_exit(1); + break; + } + } + + /* EIGRP master init. */ + eigrp_master_init(); + eigrp_om->master = frr_init(); + master = eigrp_om->master; + + vrf_init(NULL, NULL, NULL, NULL); + + /*EIGRPd init*/ + eigrp_if_init(); + eigrp_zebra_init(); + eigrp_debug_init(); + + /* Get configuration file. */ + /* EIGRP VTY inits */ + eigrp_vty_init(); + keychain_init(); + eigrp_vty_show_init(); + eigrp_vty_if_init(); #ifdef HAVE_SNMP - eigrp_snmp_init (); + eigrp_snmp_init(); #endif /* HAVE_SNMP */ - /* Access list install. */ - access_list_init (); - access_list_add_hook (eigrp_distribute_update_all_wrapper); - access_list_delete_hook (eigrp_distribute_update_all_wrapper); - - /* Prefix list initialize.*/ - prefix_list_init (); - prefix_list_add_hook (eigrp_distribute_update_all); - prefix_list_delete_hook (eigrp_distribute_update_all); - - /*eigrp_route_map_init(); - route_map_add_hook (eigrp_rmap_update); - route_map_delete_hook (eigrp_rmap_update);*/ - /*if_rmap_init (EIGRP_NODE); - if_rmap_hook_add (eigrp_if_rmap_update); - if_rmap_hook_delete (eigrp_if_rmap_update);*/ - - /* Distribute list install. */ - distribute_list_init (EIGRP_NODE); - distribute_list_add_hook (eigrp_distribute_update); - distribute_list_delete_hook (eigrp_distribute_update); - - frr_config_fork (); - frr_run(master); - - /* Not reached. */ - return (0); - + /* Access list install. */ + access_list_init(); + access_list_add_hook(eigrp_distribute_update_all_wrapper); + access_list_delete_hook(eigrp_distribute_update_all_wrapper); + + /* Prefix list initialize.*/ + prefix_list_init(); + prefix_list_add_hook(eigrp_distribute_update_all); + prefix_list_delete_hook(eigrp_distribute_update_all); + + /*eigrp_route_map_init(); + route_map_add_hook (eigrp_rmap_update); + route_map_delete_hook (eigrp_rmap_update);*/ + /*if_rmap_init (EIGRP_NODE); + if_rmap_hook_add (eigrp_if_rmap_update); + if_rmap_hook_delete (eigrp_if_rmap_update);*/ + + /* Distribute list install. */ + distribute_list_init(EIGRP_NODE); + distribute_list_add_hook(eigrp_distribute_update); + distribute_list_delete_hook(eigrp_distribute_update); + + frr_config_fork(); + frr_run(master); + + /* Not reached. */ + return (0); } diff --git a/eigrpd/eigrp_memory.c b/eigrpd/eigrp_memory.c index 4aa76018a..a8f603d2e 100644 --- a/eigrpd/eigrp_memory.c +++ b/eigrpd/eigrp_memory.c @@ -26,17 +26,17 @@ #include "eigrp_memory.h" DEFINE_MGROUP(EIGRPD, "eigrpd") -DEFINE_MTYPE(EIGRPD, EIGRP_TOP, "EIGRP structure") -DEFINE_MTYPE(EIGRPD, EIGRP_IF, "EIGRP interface") -DEFINE_MTYPE(EIGRPD, EIGRP_NEIGHBOR, "EIGRP neighbor") -DEFINE_MTYPE(EIGRPD, EIGRP_IF_PARAMS, "EIGRP Interface Parameters") -DEFINE_MTYPE(EIGRPD, EIGRP_IF_INFO, "EIGRP Interface Information") -DEFINE_MTYPE(EIGRPD, EIGRP_FIFO, "EIGRP FIFO") -DEFINE_MTYPE(EIGRPD, EIGRP_PACKET, "EIGRP Packet") -DEFINE_MTYPE(EIGRPD, EIGRP_IPV4_INT_TLV, "EIGRP IPv4 TLV") -DEFINE_MTYPE(EIGRPD, EIGRP_SEQ_TLV, "EIGRP SEQ TLV") -DEFINE_MTYPE(EIGRPD, EIGRP_AUTH_TLV, "EIGRP AUTH TLV") +DEFINE_MTYPE(EIGRPD, EIGRP_TOP, "EIGRP structure") +DEFINE_MTYPE(EIGRPD, EIGRP_IF, "EIGRP interface") +DEFINE_MTYPE(EIGRPD, EIGRP_NEIGHBOR, "EIGRP neighbor") +DEFINE_MTYPE(EIGRPD, EIGRP_IF_PARAMS, "EIGRP Interface Parameters") +DEFINE_MTYPE(EIGRPD, EIGRP_IF_INFO, "EIGRP Interface Information") +DEFINE_MTYPE(EIGRPD, EIGRP_FIFO, "EIGRP FIFO") +DEFINE_MTYPE(EIGRPD, EIGRP_PACKET, "EIGRP Packet") +DEFINE_MTYPE(EIGRPD, EIGRP_IPV4_INT_TLV, "EIGRP IPv4 TLV") +DEFINE_MTYPE(EIGRPD, EIGRP_SEQ_TLV, "EIGRP SEQ TLV") +DEFINE_MTYPE(EIGRPD, EIGRP_AUTH_TLV, "EIGRP AUTH TLV") DEFINE_MTYPE(EIGRPD, EIGRP_AUTH_SHA256_TLV, "EIGRP SHA TLV") -DEFINE_MTYPE(EIGRPD, EIGRP_PREFIX_ENTRY, "EIGRP Prefix") -DEFINE_MTYPE(EIGRPD, EIGRP_NEIGHBOR_ENTRY, "EIGRP Neighbor Entry") -DEFINE_MTYPE(EIGRPD, EIGRP_FSM_MSG, "EIGRP FSM Message") +DEFINE_MTYPE(EIGRPD, EIGRP_PREFIX_ENTRY, "EIGRP Prefix") +DEFINE_MTYPE(EIGRPD, EIGRP_NEIGHBOR_ENTRY, "EIGRP Neighbor Entry") +DEFINE_MTYPE(EIGRPD, EIGRP_FSM_MSG, "EIGRP FSM Message") diff --git a/eigrpd/eigrp_memory.h b/eigrpd/eigrp_memory.h index cd29f1725..b8c85a49b 100644 --- a/eigrpd/eigrp_memory.h +++ b/eigrpd/eigrp_memory.h @@ -39,5 +39,5 @@ DECLARE_MTYPE(EIGRP_AUTH_SHA256_TLV) DECLARE_MTYPE(EIGRP_PREFIX_ENTRY) DECLARE_MTYPE(EIGRP_NEIGHBOR_ENTRY) DECLARE_MTYPE(EIGRP_FSM_MSG) - + #endif /* _FRR_EIGRP_MEMORY_H */ diff --git a/eigrpd/eigrp_neighbor.c b/eigrpd/eigrp_neighbor.c index bf3fc216c..d5fc6a299 100644 --- a/eigrpd/eigrp_neighbor.c +++ b/eigrpd/eigrp_neighbor.c @@ -54,21 +54,20 @@ #include "eigrpd/eigrp_topology.h" #include "eigrpd/eigrp_memory.h" -struct eigrp_neighbor * -eigrp_nbr_new (struct eigrp_interface *ei) +struct eigrp_neighbor *eigrp_nbr_new(struct eigrp_interface *ei) { - struct eigrp_neighbor *nbr; + struct eigrp_neighbor *nbr; - /* Allcate new neighbor. */ - nbr = XCALLOC (MTYPE_EIGRP_NEIGHBOR, sizeof (struct eigrp_neighbor)); + /* Allcate new neighbor. */ + nbr = XCALLOC(MTYPE_EIGRP_NEIGHBOR, sizeof(struct eigrp_neighbor)); - /* Relate neighbor to the interface. */ - nbr->ei = ei; + /* Relate neighbor to the interface. */ + nbr->ei = ei; - /* Set default values. */ - eigrp_nbr_state_set (nbr, EIGRP_NEIGHBOR_DOWN); + /* Set default values. */ + eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN); - return nbr; + return nbr; } /** @@ -78,41 +77,39 @@ eigrp_nbr_new (struct eigrp_interface *ei) * @par * Create a new neighbor structure and initalize it. */ -static struct eigrp_neighbor * -eigrp_nbr_add (struct eigrp_interface *ei, struct eigrp_header *eigrph, - struct ip *iph) +static struct eigrp_neighbor *eigrp_nbr_add(struct eigrp_interface *ei, + struct eigrp_header *eigrph, + struct ip *iph) { - struct eigrp_neighbor *nbr; + struct eigrp_neighbor *nbr; - nbr = eigrp_nbr_new (ei); - nbr->src = iph->ip_src; + nbr = eigrp_nbr_new(ei); + nbr->src = iph->ip_src; - // if (IS_DEBUG_EIGRP_EVENT) - // zlog_debug("NSM[%s:%s]: start", IF_NAME (nbr->oi), - // inet_ntoa (nbr->router_id)); + // if (IS_DEBUG_EIGRP_EVENT) + // zlog_debug("NSM[%s:%s]: start", IF_NAME (nbr->oi), + // inet_ntoa (nbr->router_id)); - return nbr; + return nbr; } -struct eigrp_neighbor * -eigrp_nbr_get (struct eigrp_interface *ei, struct eigrp_header *eigrph, - struct ip *iph) +struct eigrp_neighbor *eigrp_nbr_get(struct eigrp_interface *ei, + struct eigrp_header *eigrph, + struct ip *iph) { - struct eigrp_neighbor *nbr; - struct listnode *node, *nnode; + struct eigrp_neighbor *nbr; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (ei->nbrs, node, nnode, nbr)) - { - if (iph->ip_src.s_addr == nbr->src.s_addr) - { - return nbr; - } - } + for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) { + if (iph->ip_src.s_addr == nbr->src.s_addr) { + return nbr; + } + } - nbr = eigrp_nbr_add (ei, eigrph, iph); - listnode_add (ei->nbrs, nbr); + nbr = eigrp_nbr_add(ei, eigrph, iph); + listnode_add(ei->nbrs, nbr); - return nbr; + return nbr; } /** @@ -127,21 +124,19 @@ eigrp_nbr_get (struct eigrp_interface *ei, struct eigrp_header *eigrph, * Function is used for neighbor lookup by address * in specified interface. */ -struct eigrp_neighbor * -eigrp_nbr_lookup_by_addr (struct eigrp_interface *ei, struct in_addr *addr) +struct eigrp_neighbor *eigrp_nbr_lookup_by_addr(struct eigrp_interface *ei, + struct in_addr *addr) { - struct eigrp_neighbor *nbr; - struct listnode *node, *nnode; - - for (ALL_LIST_ELEMENTS (ei->nbrs, node, nnode, nbr)) - { - if (addr->s_addr == nbr->src.s_addr) - { - return nbr; - } - } - - return NULL; + struct eigrp_neighbor *nbr; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) { + if (addr->s_addr == nbr->src.s_addr) { + return nbr; + } + } + + return NULL; } /** @@ -156,188 +151,173 @@ eigrp_nbr_lookup_by_addr (struct eigrp_interface *ei, struct in_addr *addr) * Function is used for neighbor lookup by address * in whole EIGRP process. */ -struct eigrp_neighbor * -eigrp_nbr_lookup_by_addr_process (struct eigrp *eigrp, struct in_addr nbr_addr) +struct eigrp_neighbor *eigrp_nbr_lookup_by_addr_process(struct eigrp *eigrp, + struct in_addr nbr_addr) { - struct eigrp_interface *ei; - struct listnode *node, *node2, *nnode2; - struct eigrp_neighbor *nbr; - - /* iterate over all eigrp interfaces */ - for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei)) - { - /* iterate over all neighbors on eigrp interface */ - for (ALL_LIST_ELEMENTS (ei->nbrs, node2, nnode2, nbr)) - { - /* compare if neighbor address is same as arg address */ - if (nbr->src.s_addr == nbr_addr.s_addr) - { - return nbr; - } - } - } - - return NULL; + struct eigrp_interface *ei; + struct listnode *node, *node2, *nnode2; + struct eigrp_neighbor *nbr; + + /* iterate over all eigrp interfaces */ + for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) { + /* iterate over all neighbors on eigrp interface */ + for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) { + /* compare if neighbor address is same as arg address */ + if (nbr->src.s_addr == nbr_addr.s_addr) { + return nbr; + } + } + } + + return NULL; } /* Delete specified EIGRP neighbor from interface. */ -void -eigrp_nbr_delete (struct eigrp_neighbor *nbr) +void eigrp_nbr_delete(struct eigrp_neighbor *nbr) { - eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN); - if (nbr->ei) - eigrp_topology_neighbor_down(nbr->ei->eigrp, nbr); - - /* Cancel all events. *//* Thread lookup cost would be negligible. */ - thread_cancel_event (master, nbr); - eigrp_fifo_free (nbr->multicast_queue); - eigrp_fifo_free (nbr->retrans_queue); - THREAD_OFF (nbr->t_holddown); - - if (nbr->ei) - listnode_delete (nbr->ei->nbrs,nbr); - XFREE (MTYPE_EIGRP_NEIGHBOR, nbr); + eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN); + if (nbr->ei) + eigrp_topology_neighbor_down(nbr->ei->eigrp, nbr); + + /* Cancel all events. */ /* Thread lookup cost would be negligible. */ + thread_cancel_event(master, nbr); + eigrp_fifo_free(nbr->multicast_queue); + eigrp_fifo_free(nbr->retrans_queue); + THREAD_OFF(nbr->t_holddown); + + if (nbr->ei) + listnode_delete(nbr->ei->nbrs, nbr); + XFREE(MTYPE_EIGRP_NEIGHBOR, nbr); } -int -holddown_timer_expired (struct thread *thread) +int holddown_timer_expired(struct thread *thread) { - struct eigrp_neighbor *nbr; + struct eigrp_neighbor *nbr; - nbr = THREAD_ARG (thread); + nbr = THREAD_ARG(thread); - zlog_info ("Neighbor %s (%s) is down: holding time expired", - inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); - nbr->state = EIGRP_NEIGHBOR_DOWN; - eigrp_nbr_delete (nbr); + zlog_info("Neighbor %s (%s) is down: holding time expired", + inet_ntoa(nbr->src), + ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); + nbr->state = EIGRP_NEIGHBOR_DOWN; + eigrp_nbr_delete(nbr); - return 0; + return 0; } -u_char -eigrp_nbr_state_get (struct eigrp_neighbor *nbr) +u_char eigrp_nbr_state_get(struct eigrp_neighbor *nbr) { - return(nbr->state); + return (nbr->state); } -void -eigrp_nbr_state_set (struct eigrp_neighbor *nbr, u_char state) +void eigrp_nbr_state_set(struct eigrp_neighbor *nbr, u_char state) { - nbr->state = state; - - if (eigrp_nbr_state_get(nbr) == EIGRP_NEIGHBOR_DOWN) - { - // reset all the seq/ack counters - nbr->recv_sequence_number = 0; - nbr->init_sequence_number = 0; - nbr->retrans_counter = 0; - - // Kvalues - nbr->K1 = EIGRP_K1_DEFAULT; - nbr->K2 = EIGRP_K2_DEFAULT; - nbr->K3 = EIGRP_K3_DEFAULT; - nbr->K4 = EIGRP_K4_DEFAULT; - nbr->K5 = EIGRP_K5_DEFAULT; - nbr->K6 = EIGRP_K6_DEFAULT; - - // hold time.. - nbr->v_holddown = EIGRP_HOLD_INTERVAL_DEFAULT; - THREAD_OFF(nbr->t_holddown); - - /* out with the old */ - if (nbr->multicast_queue) - eigrp_fifo_free (nbr->multicast_queue); - if (nbr->retrans_queue) - eigrp_fifo_free (nbr->retrans_queue); - - /* in with the new */ - nbr->retrans_queue = eigrp_fifo_new (); - nbr->multicast_queue = eigrp_fifo_new (); - - nbr->crypt_seqnum = 0; - } + nbr->state = state; + + if (eigrp_nbr_state_get(nbr) == EIGRP_NEIGHBOR_DOWN) { + // reset all the seq/ack counters + nbr->recv_sequence_number = 0; + nbr->init_sequence_number = 0; + nbr->retrans_counter = 0; + + // Kvalues + nbr->K1 = EIGRP_K1_DEFAULT; + nbr->K2 = EIGRP_K2_DEFAULT; + nbr->K3 = EIGRP_K3_DEFAULT; + nbr->K4 = EIGRP_K4_DEFAULT; + nbr->K5 = EIGRP_K5_DEFAULT; + nbr->K6 = EIGRP_K6_DEFAULT; + + // hold time.. + nbr->v_holddown = EIGRP_HOLD_INTERVAL_DEFAULT; + THREAD_OFF(nbr->t_holddown); + + /* out with the old */ + if (nbr->multicast_queue) + eigrp_fifo_free(nbr->multicast_queue); + if (nbr->retrans_queue) + eigrp_fifo_free(nbr->retrans_queue); + + /* in with the new */ + nbr->retrans_queue = eigrp_fifo_new(); + nbr->multicast_queue = eigrp_fifo_new(); + + nbr->crypt_seqnum = 0; + } } -const char * -eigrp_nbr_state_str (struct eigrp_neighbor *nbr) +const char *eigrp_nbr_state_str(struct eigrp_neighbor *nbr) { - const char *state; - switch (nbr->state) - { - case EIGRP_NEIGHBOR_DOWN: - state = "Down"; - break; - case EIGRP_NEIGHBOR_PENDING: - state = "Waiting for Init"; - break; - case EIGRP_NEIGHBOR_UP: - state = "Up"; - break; - default: - state = "Unknown"; - break; - } - - return(state); + const char *state; + switch (nbr->state) { + case EIGRP_NEIGHBOR_DOWN: + state = "Down"; + break; + case EIGRP_NEIGHBOR_PENDING: + state = "Waiting for Init"; + break; + case EIGRP_NEIGHBOR_UP: + state = "Up"; + break; + default: + state = "Unknown"; + break; + } + + return (state); } -void -eigrp_nbr_state_update (struct eigrp_neighbor *nbr) +void eigrp_nbr_state_update(struct eigrp_neighbor *nbr) { - switch (nbr->state) - { - case EIGRP_NEIGHBOR_DOWN: - { - /*Start Hold Down Timer for neighbor*/ - // THREAD_OFF(nbr->t_holddown); - // THREAD_TIMER_ON(master, nbr->t_holddown, holddown_timer_expired, - // nbr, nbr->v_holddown); - break; - } - case EIGRP_NEIGHBOR_PENDING: - { - /*Reset Hold Down Timer for neighbor*/ - THREAD_OFF(nbr->t_holddown); - thread_add_timer(master, holddown_timer_expired, nbr, - nbr->v_holddown, &nbr->t_holddown); - break; - } - case EIGRP_NEIGHBOR_UP: - { - /*Reset Hold Down Timer for neighbor*/ - THREAD_OFF(nbr->t_holddown); - thread_add_timer(master, holddown_timer_expired, nbr, - nbr->v_holddown, &nbr->t_holddown); - break; - } - } + switch (nbr->state) { + case EIGRP_NEIGHBOR_DOWN: { + /*Start Hold Down Timer for neighbor*/ + // THREAD_OFF(nbr->t_holddown); + // THREAD_TIMER_ON(master, nbr->t_holddown, + // holddown_timer_expired, + // nbr, nbr->v_holddown); + break; + } + case EIGRP_NEIGHBOR_PENDING: { + /*Reset Hold Down Timer for neighbor*/ + THREAD_OFF(nbr->t_holddown); + thread_add_timer(master, holddown_timer_expired, nbr, + nbr->v_holddown, &nbr->t_holddown); + break; + } + case EIGRP_NEIGHBOR_UP: { + /*Reset Hold Down Timer for neighbor*/ + THREAD_OFF(nbr->t_holddown); + thread_add_timer(master, holddown_timer_expired, nbr, + nbr->v_holddown, &nbr->t_holddown); + break; + } + } } -int eigrp_nbr_count_get(void){ - struct eigrp_interface *iface; - struct listnode *node, *node2, *nnode2; - struct eigrp_neighbor *nbr; - struct eigrp *eigrp = eigrp_lookup(); - u_int32_t counter; - - if (eigrp == NULL) - { - zlog_debug("EIGRP Routing Process not enabled"); - return 0; - } - - counter=0; - for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, iface)) - { - for (ALL_LIST_ELEMENTS(iface->nbrs, node2, nnode2, nbr)) - { - if (nbr->state == EIGRP_NEIGHBOR_UP){ - counter++; - } - } - } - return counter; +int eigrp_nbr_count_get(void) +{ + struct eigrp_interface *iface; + struct listnode *node, *node2, *nnode2; + struct eigrp_neighbor *nbr; + struct eigrp *eigrp = eigrp_lookup(); + u_int32_t counter; + + if (eigrp == NULL) { + zlog_debug("EIGRP Routing Process not enabled"); + return 0; + } + + counter = 0; + for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, iface)) { + for (ALL_LIST_ELEMENTS(iface->nbrs, node2, nnode2, nbr)) { + if (nbr->state == EIGRP_NEIGHBOR_UP) { + counter++; + } + } + } + return counter; } /** @@ -354,27 +334,26 @@ int eigrp_nbr_count_get(void){ */ void eigrp_nbr_hard_restart(struct eigrp_neighbor *nbr, struct vty *vty) { - if(nbr == NULL) - { - zlog_err("Nbr Hard restart: Neighbor not specified."); - return; - } - - zlog_debug ("Neighbor %s (%s) is down: manually cleared", - inet_ntoa (nbr->src), - ifindex2ifname (nbr->ei->ifp->ifindex, VRF_DEFAULT)); - if(vty != NULL) - { - vty_time_print (vty, 0); - vty_out (vty, "Neighbor %s (%s) is down: manually cleared\n", - inet_ntoa (nbr->src), - ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); - } - - /* send Hello with Peer Termination TLV */ - eigrp_hello_send(nbr->ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN_NBR, &(nbr->src)); - /* set neighbor to DOWN */ - nbr->state = EIGRP_NEIGHBOR_DOWN; - /* delete neighbor */ - eigrp_nbr_delete (nbr); + if (nbr == NULL) { + zlog_err("Nbr Hard restart: Neighbor not specified."); + return; + } + + zlog_debug("Neighbor %s (%s) is down: manually cleared", + inet_ntoa(nbr->src), + ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); + if (vty != NULL) { + vty_time_print(vty, 0); + vty_out(vty, "Neighbor %s (%s) is down: manually cleared\n", + inet_ntoa(nbr->src), + ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); + } + + /* send Hello with Peer Termination TLV */ + eigrp_hello_send(nbr->ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN_NBR, + &(nbr->src)); + /* set neighbor to DOWN */ + nbr->state = EIGRP_NEIGHBOR_DOWN; + /* delete neighbor */ + eigrp_nbr_delete(nbr); } diff --git a/eigrpd/eigrp_neighbor.h b/eigrpd/eigrp_neighbor.h index 66fa0e71b..006aa9ab7 100644 --- a/eigrpd/eigrp_neighbor.h +++ b/eigrpd/eigrp_neighbor.h @@ -34,21 +34,23 @@ /* Prototypes */ extern struct eigrp_neighbor *eigrp_nbr_get(struct eigrp_interface *, - struct eigrp_header *, - struct ip *); -extern struct eigrp_neighbor *eigrp_nbr_new (struct eigrp_interface *); + struct eigrp_header *, struct ip *); +extern struct eigrp_neighbor *eigrp_nbr_new(struct eigrp_interface *); extern void eigrp_nbr_delete(struct eigrp_neighbor *); extern int holddown_timer_expired(struct thread *); -extern int eigrp_neighborship_check(struct eigrp_neighbor *,struct TLV_Parameter_Type *); +extern int eigrp_neighborship_check(struct eigrp_neighbor *, + struct TLV_Parameter_Type *); extern void eigrp_nbr_state_update(struct eigrp_neighbor *); extern void eigrp_nbr_state_set(struct eigrp_neighbor *, u_char state); extern u_char eigrp_nbr_state_get(struct eigrp_neighbor *); extern int eigrp_nbr_count_get(void); extern const char *eigrp_nbr_state_str(struct eigrp_neighbor *); -extern struct eigrp_neighbor *eigrp_nbr_lookup_by_addr (struct eigrp_interface *, struct in_addr *); -extern struct eigrp_neighbor *eigrp_nbr_lookup_by_addr_process (struct eigrp *, struct in_addr); +extern struct eigrp_neighbor *eigrp_nbr_lookup_by_addr(struct eigrp_interface *, + struct in_addr *); +extern struct eigrp_neighbor *eigrp_nbr_lookup_by_addr_process(struct eigrp *, + struct in_addr); extern void eigrp_nbr_hard_restart(struct eigrp_neighbor *nbr, struct vty *vty); #endif /* _ZEBRA_EIGRP_NEIGHBOR_H */ diff --git a/eigrpd/eigrp_network.c b/eigrpd/eigrp_network.c index 74cb6de18..80610e04a 100644 --- a/eigrpd/eigrp_network.c +++ b/eigrpd/eigrp_network.c @@ -49,412 +49,405 @@ extern struct zebra_privs_t eigrpd_privs; #include "eigrpd/eigrp_vty.h" #include "eigrpd/eigrp_network.h" -static int -eigrp_network_match_iface(const struct connected *, const struct prefix *); -static void -eigrp_network_run_interface(struct eigrp *, struct prefix *, struct interface *); +static int eigrp_network_match_iface(const struct connected *, + const struct prefix *); +static void eigrp_network_run_interface(struct eigrp *, struct prefix *, + struct interface *); -int -eigrp_sock_init(void) +int eigrp_sock_init(void) { - int eigrp_sock; - int ret, hincl = 1; - - if (eigrpd_privs.change(ZPRIVS_RAISE)) - zlog_err("eigrp_sock_init: could not raise privs, %s", - safe_strerror(errno)); - - eigrp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_EIGRPIGP); - if (eigrp_sock < 0) - { - int save_errno = errno; - if (eigrpd_privs.change(ZPRIVS_LOWER)) - zlog_err("eigrp_sock_init: could not lower privs, %s", - safe_strerror(errno)); - zlog_err("eigrp_read_sock_init: socket: %s", safe_strerror(save_errno)); - exit(1); - } + int eigrp_sock; + int ret, hincl = 1; + + if (eigrpd_privs.change(ZPRIVS_RAISE)) + zlog_err("eigrp_sock_init: could not raise privs, %s", + safe_strerror(errno)); + + eigrp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_EIGRPIGP); + if (eigrp_sock < 0) { + int save_errno = errno; + if (eigrpd_privs.change(ZPRIVS_LOWER)) + zlog_err("eigrp_sock_init: could not lower privs, %s", + safe_strerror(errno)); + zlog_err("eigrp_read_sock_init: socket: %s", + safe_strerror(save_errno)); + exit(1); + } #ifdef IP_HDRINCL - /* we will include IP header with packet */ - ret = setsockopt(eigrp_sock, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof(hincl)); - if (ret < 0) - { - int save_errno = errno; - if (eigrpd_privs.change(ZPRIVS_LOWER)) - zlog_err("eigrp_sock_init: could not lower privs, %s", - safe_strerror(errno)); - zlog_warn("Can't set IP_HDRINCL option for fd %d: %s", eigrp_sock, - safe_strerror(save_errno)); - - } -#elif defined (IPTOS_PREC_INTERNETCONTROL) + /* we will include IP header with packet */ + ret = setsockopt(eigrp_sock, IPPROTO_IP, IP_HDRINCL, &hincl, + sizeof(hincl)); + if (ret < 0) { + int save_errno = errno; + if (eigrpd_privs.change(ZPRIVS_LOWER)) + zlog_err("eigrp_sock_init: could not lower privs, %s", + safe_strerror(errno)); + zlog_warn("Can't set IP_HDRINCL option for fd %d: %s", + eigrp_sock, safe_strerror(save_errno)); + } +#elif defined(IPTOS_PREC_INTERNETCONTROL) #warning "IP_HDRINCL not available on this system" #warning "using IPTOS_PREC_INTERNETCONTROL" - ret = setsockopt_ipv4_tos (eigrp_sock, IPTOS_PREC_INTERNETCONTROL); - if (ret < 0) - { - int save_errno = errno; - if ( eigrpd_privs.change (ZPRIVS_LOWER) ) - zlog_err ("eigrpd_sock_init: could not lower privs, %s", - safe_strerror (errno) ); - zlog_warn ("can't set sockopt IP_TOS %d to socket %d: %s", - tos, eigrp_sock, safe_strerror (save_errno)); - close (eigrp_sock); /* Prevent sd leak. */ - return ret; - } + ret = setsockopt_ipv4_tos(eigrp_sock, IPTOS_PREC_INTERNETCONTROL); + if (ret < 0) { + int save_errno = errno; + if (eigrpd_privs.change(ZPRIVS_LOWER)) + zlog_err("eigrpd_sock_init: could not lower privs, %s", + safe_strerror(errno)); + zlog_warn("can't set sockopt IP_TOS %d to socket %d: %s", tos, + eigrp_sock, safe_strerror(save_errno)); + close(eigrp_sock); /* Prevent sd leak. */ + return ret; + } #else /* !IPTOS_PREC_INTERNETCONTROL */ #warning "IP_HDRINCL not available, nor is IPTOS_PREC_INTERNETCONTROL" - zlog_warn ("IP_HDRINCL option not available"); + zlog_warn("IP_HDRINCL option not available"); #endif /* IP_HDRINCL */ - ret = setsockopt_ifindex(AF_INET, eigrp_sock, 1); + ret = setsockopt_ifindex(AF_INET, eigrp_sock, 1); - if (ret < 0) - zlog_warn("Can't set pktinfo option for fd %d", eigrp_sock); + if (ret < 0) + zlog_warn("Can't set pktinfo option for fd %d", eigrp_sock); - if (eigrpd_privs.change(ZPRIVS_LOWER)) - { - zlog_err("eigrp_sock_init: could not lower privs, %s", - safe_strerror(errno)); - } + if (eigrpd_privs.change(ZPRIVS_LOWER)) { + zlog_err("eigrp_sock_init: could not lower privs, %s", + safe_strerror(errno)); + } - return eigrp_sock; + return eigrp_sock; } -void -eigrp_adjust_sndbuflen(struct eigrp * eigrp, unsigned int buflen) +void eigrp_adjust_sndbuflen(struct eigrp *eigrp, unsigned int buflen) { - int newbuflen; - /* Check if any work has to be done at all. */ - if (eigrp->maxsndbuflen >= buflen) - return; - if (eigrpd_privs.change(ZPRIVS_RAISE)) - zlog_err("%s: could not raise privs, %s", __func__, safe_strerror(errno)); - - /* Now we try to set SO_SNDBUF to what our caller has requested - * (the MTU of a newly added interface). However, if the OS has - * truncated the actual buffer size to somewhat less size, try - * to detect it and update our records appropriately. The OS - * may allocate more buffer space, than requested, this isn't - * a error. - */ - setsockopt_so_sendbuf(eigrp->fd, buflen); - newbuflen = getsockopt_so_sendbuf(eigrp->fd); - if (newbuflen < 0 || newbuflen < (int) buflen) - zlog_warn("%s: tried to set SO_SNDBUF to %u, but got %d", __func__, buflen, - newbuflen); - if (newbuflen >= 0) - eigrp->maxsndbuflen = (unsigned int) newbuflen; - else - zlog_warn("%s: failed to get SO_SNDBUF", __func__); - if (eigrpd_privs.change(ZPRIVS_LOWER)) - zlog_err("%s: could not lower privs, %s", __func__, safe_strerror(errno)); + int newbuflen; + /* Check if any work has to be done at all. */ + if (eigrp->maxsndbuflen >= buflen) + return; + if (eigrpd_privs.change(ZPRIVS_RAISE)) + zlog_err("%s: could not raise privs, %s", __func__, + safe_strerror(errno)); + + /* Now we try to set SO_SNDBUF to what our caller has requested + * (the MTU of a newly added interface). However, if the OS has + * truncated the actual buffer size to somewhat less size, try + * to detect it and update our records appropriately. The OS + * may allocate more buffer space, than requested, this isn't + * a error. + */ + setsockopt_so_sendbuf(eigrp->fd, buflen); + newbuflen = getsockopt_so_sendbuf(eigrp->fd); + if (newbuflen < 0 || newbuflen < (int)buflen) + zlog_warn("%s: tried to set SO_SNDBUF to %u, but got %d", + __func__, buflen, newbuflen); + if (newbuflen >= 0) + eigrp->maxsndbuflen = (unsigned int)newbuflen; + else + zlog_warn("%s: failed to get SO_SNDBUF", __func__); + if (eigrpd_privs.change(ZPRIVS_LOWER)) + zlog_err("%s: could not lower privs, %s", __func__, + safe_strerror(errno)); } -int -eigrp_if_ipmulticast(struct eigrp *top, struct prefix *p, unsigned int ifindex) +int eigrp_if_ipmulticast(struct eigrp *top, struct prefix *p, + unsigned int ifindex) { - u_char val; - int ret, len; - - val = 0; - len = sizeof(val); - - /* Prevent receiving self-origined multicast packets. */ - ret = setsockopt(top->fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void *) &val, len); - if (ret < 0) - zlog_warn("can't setsockopt IP_MULTICAST_LOOP (0) for fd %d: %s", top->fd, - safe_strerror(errno)); - - /* Explicitly set multicast ttl to 1 -- endo. */ - val = 1; - ret = setsockopt(top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *) &val, len); - if (ret < 0) - zlog_warn("can't setsockopt IP_MULTICAST_TTL (1) for fd %d: %s", top->fd, - safe_strerror(errno)); - - ret = setsockopt_ipv4_multicast_if(top->fd, p->u.prefix4, ifindex); - if (ret < 0) - zlog_warn("can't setsockopt IP_MULTICAST_IF (fd %d, addr %s, " - "ifindex %u): %s", top->fd, inet_ntoa(p->u.prefix4), ifindex, - safe_strerror(errno)); - - return ret; + u_char val; + int ret, len; + + val = 0; + len = sizeof(val); + + /* Prevent receiving self-origined multicast packets. */ + ret = setsockopt(top->fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void *)&val, + len); + if (ret < 0) + zlog_warn( + "can't setsockopt IP_MULTICAST_LOOP (0) for fd %d: %s", + top->fd, safe_strerror(errno)); + + /* Explicitly set multicast ttl to 1 -- endo. */ + val = 1; + ret = setsockopt(top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val, + len); + if (ret < 0) + zlog_warn("can't setsockopt IP_MULTICAST_TTL (1) for fd %d: %s", + top->fd, safe_strerror(errno)); + + ret = setsockopt_ipv4_multicast_if(top->fd, p->u.prefix4, ifindex); + if (ret < 0) + zlog_warn( + "can't setsockopt IP_MULTICAST_IF (fd %d, addr %s, " + "ifindex %u): %s", + top->fd, inet_ntoa(p->u.prefix4), ifindex, + safe_strerror(errno)); + + return ret; } /* Join to the EIGRP multicast group. */ -int -eigrp_if_add_allspfrouters(struct eigrp *top, struct prefix *p, - unsigned int ifindex) +int eigrp_if_add_allspfrouters(struct eigrp *top, struct prefix *p, + unsigned int ifindex) { - int ret; - - ret = setsockopt_ipv4_multicast(top->fd, IP_ADD_MEMBERSHIP, p->u.prefix4, - htonl(EIGRP_MULTICAST_ADDRESS), ifindex); - if (ret < 0) - zlog_warn("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " - "ifindex %u, AllSPFRouters): %s; perhaps a kernel limit " - "on # of multicast group memberships has been exceeded?", top->fd, - inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); - else - zlog_debug("interface %s [%u] join EIGRP Multicast group.", - inet_ntoa(p->u.prefix4), ifindex); - - return ret; + int ret; + + ret = setsockopt_ipv4_multicast( + top->fd, IP_ADD_MEMBERSHIP, p->u.prefix4, + htonl(EIGRP_MULTICAST_ADDRESS), ifindex); + if (ret < 0) + zlog_warn( + "can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " + "ifindex %u, AllSPFRouters): %s; perhaps a kernel limit " + "on # of multicast group memberships has been exceeded?", + top->fd, inet_ntoa(p->u.prefix4), ifindex, + safe_strerror(errno)); + else + zlog_debug("interface %s [%u] join EIGRP Multicast group.", + inet_ntoa(p->u.prefix4), ifindex); + + return ret; } -int -eigrp_if_drop_allspfrouters(struct eigrp *top, struct prefix *p, - unsigned int ifindex) +int eigrp_if_drop_allspfrouters(struct eigrp *top, struct prefix *p, + unsigned int ifindex) { - int ret; - - ret = setsockopt_ipv4_multicast(top->fd, IP_DROP_MEMBERSHIP, p->u.prefix4, - htonl(EIGRP_MULTICAST_ADDRESS), ifindex); - if (ret < 0) - zlog_warn("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " - "ifindex %u, AllSPFRouters): %s", top->fd, inet_ntoa(p->u.prefix4), - ifindex, safe_strerror(errno)); - else - zlog_debug("interface %s [%u] leave EIGRP Multicast group.", - inet_ntoa(p->u.prefix4), ifindex); - - return ret; + int ret; + + ret = setsockopt_ipv4_multicast( + top->fd, IP_DROP_MEMBERSHIP, p->u.prefix4, + htonl(EIGRP_MULTICAST_ADDRESS), ifindex); + if (ret < 0) + zlog_warn( + "can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " + "ifindex %u, AllSPFRouters): %s", + top->fd, inet_ntoa(p->u.prefix4), ifindex, + safe_strerror(errno)); + else + zlog_debug("interface %s [%u] leave EIGRP Multicast group.", + inet_ntoa(p->u.prefix4), ifindex); + + return ret; } -int -eigrp_network_set(struct eigrp *eigrp, struct prefix_ipv4 *p) +int eigrp_network_set(struct eigrp *eigrp, struct prefix_ipv4 *p) { - struct route_node *rn; - struct interface *ifp; - struct listnode *node; - - rn = route_node_get(eigrp->networks, (struct prefix *) p); - if (rn->info) - { - /* There is already same network statement. */ - route_unlock_node(rn); - return 0; - } - - struct prefix_ipv4 *pref = prefix_ipv4_new(); - PREFIX_COPY_IPV4(pref,p); - rn->info = (void *) pref; - - /* Schedule Router ID Update. */ - if (eigrp->router_id == 0) - eigrp_router_id_update(eigrp); - /* Run network config now. */ - /* Get target interface. */ - for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) - { - zlog_debug("Setting up %s", ifp->name); - eigrp_network_run_interface(eigrp, (struct prefix *) p, ifp); - } - return 1; + struct route_node *rn; + struct interface *ifp; + struct listnode *node; + + rn = route_node_get(eigrp->networks, (struct prefix *)p); + if (rn->info) { + /* There is already same network statement. */ + route_unlock_node(rn); + return 0; + } + + struct prefix_ipv4 *pref = prefix_ipv4_new(); + PREFIX_COPY_IPV4(pref, p); + rn->info = (void *)pref; + + /* Schedule Router ID Update. */ + if (eigrp->router_id == 0) + eigrp_router_id_update(eigrp); + /* Run network config now. */ + /* Get target interface. */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + zlog_debug("Setting up %s", ifp->name); + eigrp_network_run_interface(eigrp, (struct prefix *)p, ifp); + } + return 1; } /* Check whether interface matches given network * returns: 1, true. 0, false */ -static int -eigrp_network_match_iface(const struct connected *co, const struct prefix *net) +static int eigrp_network_match_iface(const struct connected *co, + const struct prefix *net) { - /* new approach: more elegant and conceptually clean */ - return prefix_match_network_statement(net, CONNECTED_PREFIX (co)); + /* new approach: more elegant and conceptually clean */ + return prefix_match_network_statement(net, CONNECTED_PREFIX(co)); } -static void -eigrp_network_run_interface(struct eigrp *eigrp, struct prefix *p, - struct interface *ifp) +static void eigrp_network_run_interface(struct eigrp *eigrp, struct prefix *p, + struct interface *ifp) { - struct listnode *cnode; - struct connected *co; - - /* if interface prefix is match specified prefix, - then create socket and join multicast group. */ - for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, co)) - { - - if (CHECK_FLAG (co->flags,ZEBRA_IFA_SECONDARY)) - continue; - - if (p->family == co->address->family - && !eigrp_if_table_lookup(ifp, co->address) - && eigrp_network_match_iface(co, p)) - { - struct eigrp_interface *ei; - - ei = eigrp_if_new(eigrp, ifp, co->address); - ei->connected = co; - - ei->params = eigrp_lookup_if_params(ifp, ei->address->u.prefix4); - - /* Relate eigrp interface to eigrp instance. */ - ei->eigrp = eigrp; - - /* update network type as interface flag */ - /* If network type is specified previously, - skip network type setting. */ - ei->type = IF_DEF_PARAMS (ifp)->type; - - /* if router_id is not configured, dont bring up - * interfaces. - * eigrp_router_id_update() will call eigrp_if_update - * whenever r-id is configured instead. - */ - if (if_is_operative(ifp)) - eigrp_if_up(ei); - } - } + struct listnode *cnode; + struct connected *co; + + /* if interface prefix is match specified prefix, + then create socket and join multicast group. */ + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, co)) { + + if (CHECK_FLAG(co->flags, ZEBRA_IFA_SECONDARY)) + continue; + + if (p->family == co->address->family + && !eigrp_if_table_lookup(ifp, co->address) + && eigrp_network_match_iface(co, p)) { + struct eigrp_interface *ei; + + ei = eigrp_if_new(eigrp, ifp, co->address); + ei->connected = co; + + ei->params = eigrp_lookup_if_params( + ifp, ei->address->u.prefix4); + + /* Relate eigrp interface to eigrp instance. */ + ei->eigrp = eigrp; + + /* update network type as interface flag */ + /* If network type is specified previously, + skip network type setting. */ + ei->type = IF_DEF_PARAMS(ifp)->type; + + /* if router_id is not configured, dont bring up + * interfaces. + * eigrp_router_id_update() will call eigrp_if_update + * whenever r-id is configured instead. + */ + if (if_is_operative(ifp)) + eigrp_if_up(ei); + } + } } -void -eigrp_if_update(struct interface *ifp) +void eigrp_if_update(struct interface *ifp) { - struct listnode *node, *nnode; - struct route_node *rn; - struct eigrp *eigrp; - - /* - * In the event there are multiple eigrp autonymnous systems running, - * we need to check eac one and add the interface as approperate - */ - for (ALL_LIST_ELEMENTS(eigrp_om->eigrp, node, nnode, eigrp)) - { - /* EIGRP must be on and Router-ID must be configured. */ - if (!eigrp || eigrp->router_id == 0) - continue; - - /* Run each network for this interface. */ - for (rn = route_top(eigrp->networks); rn; rn = route_next(rn)) - if (rn->info != NULL) - { - eigrp_network_run_interface(eigrp, &rn->p, ifp); - } - } + struct listnode *node, *nnode; + struct route_node *rn; + struct eigrp *eigrp; + + /* + * In the event there are multiple eigrp autonymnous systems running, + * we need to check eac one and add the interface as approperate + */ + for (ALL_LIST_ELEMENTS(eigrp_om->eigrp, node, nnode, eigrp)) { + /* EIGRP must be on and Router-ID must be configured. */ + if (!eigrp || eigrp->router_id == 0) + continue; + + /* Run each network for this interface. */ + for (rn = route_top(eigrp->networks); rn; rn = route_next(rn)) + if (rn->info != NULL) { + eigrp_network_run_interface(eigrp, &rn->p, ifp); + } + } } -int -eigrp_network_unset(struct eigrp *eigrp, struct prefix_ipv4 *p) +int eigrp_network_unset(struct eigrp *eigrp, struct prefix_ipv4 *p) { - struct route_node *rn; - struct listnode *node, *nnode; - struct eigrp_interface *ei; - struct prefix *pref; - - rn = route_node_lookup(eigrp->networks, (struct prefix *) p); - if (rn == NULL) - return 0; - - pref = rn->info; - route_unlock_node (rn); - - if (!IPV4_ADDR_SAME (&pref->u.prefix4, &p->prefix)) - return 0; - - prefix_ipv4_free(rn->info); - rn->info = NULL; - route_unlock_node(rn); /* initial reference */ - - /* Find interfaces that not configured already. */ - for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, ei)) - { - int found = 0; - struct connected *co = ei->connected; - - for (rn = route_top(eigrp->networks); rn; rn = route_next(rn)) - { - if (rn->info == NULL) - continue; - - if (eigrp_network_match_iface(co, &rn->p)) - { - found = 1; - route_unlock_node(rn); - break; - } - } - - if (found == 0) - { - eigrp_if_free(ei, INTERFACE_DOWN_BY_VTY); - } - } - - return 1; + struct route_node *rn; + struct listnode *node, *nnode; + struct eigrp_interface *ei; + struct prefix *pref; + + rn = route_node_lookup(eigrp->networks, (struct prefix *)p); + if (rn == NULL) + return 0; + + pref = rn->info; + route_unlock_node(rn); + + if (!IPV4_ADDR_SAME(&pref->u.prefix4, &p->prefix)) + return 0; + + prefix_ipv4_free(rn->info); + rn->info = NULL; + route_unlock_node(rn); /* initial reference */ + + /* Find interfaces that not configured already. */ + for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, ei)) { + int found = 0; + struct connected *co = ei->connected; + + for (rn = route_top(eigrp->networks); rn; rn = route_next(rn)) { + if (rn->info == NULL) + continue; + + if (eigrp_network_match_iface(co, &rn->p)) { + found = 1; + route_unlock_node(rn); + break; + } + } + + if (found == 0) { + eigrp_if_free(ei, INTERFACE_DOWN_BY_VTY); + } + } + + return 1; } -u_int32_t -eigrp_calculate_metrics(struct eigrp *eigrp, struct eigrp_metrics metric) +u_int32_t eigrp_calculate_metrics(struct eigrp *eigrp, + struct eigrp_metrics metric) { - uint64_t temp_metric; - temp_metric = 0; - - if(metric.delay == EIGRP_MAX_METRIC) - return EIGRP_MAX_METRIC; - - // EIGRP Metric = {K1*BW+[(K2*BW)/(256-load)]+(K3*delay)}*{K5/(reliability+K4)} - - if (eigrp->k_values[0]) - temp_metric += (eigrp->k_values[0] * metric.bandwith); - if (eigrp->k_values[1]) - temp_metric += ((eigrp->k_values[1] * metric.bandwith) - / (256 - metric.load)); - if (eigrp->k_values[2]) - temp_metric += (eigrp->k_values[2] * metric.delay); - if (eigrp->k_values[3] && !eigrp->k_values[4]) - temp_metric *= eigrp->k_values[3]; - if (!eigrp->k_values[3] && eigrp->k_values[4]) - temp_metric *= (eigrp->k_values[4] / metric.reliability); - if (eigrp->k_values[3] && eigrp->k_values[4]) - temp_metric *= ((eigrp->k_values[4] / metric.reliability) - + eigrp->k_values[3]); - - if (temp_metric <= EIGRP_MAX_METRIC) - return (u_int32_t) temp_metric; - else - return EIGRP_MAX_METRIC; + uint64_t temp_metric; + temp_metric = 0; + + if (metric.delay == EIGRP_MAX_METRIC) + return EIGRP_MAX_METRIC; + + // EIGRP Metric = + // {K1*BW+[(K2*BW)/(256-load)]+(K3*delay)}*{K5/(reliability+K4)} + + if (eigrp->k_values[0]) + temp_metric += (eigrp->k_values[0] * metric.bandwith); + if (eigrp->k_values[1]) + temp_metric += ((eigrp->k_values[1] * metric.bandwith) + / (256 - metric.load)); + if (eigrp->k_values[2]) + temp_metric += (eigrp->k_values[2] * metric.delay); + if (eigrp->k_values[3] && !eigrp->k_values[4]) + temp_metric *= eigrp->k_values[3]; + if (!eigrp->k_values[3] && eigrp->k_values[4]) + temp_metric *= (eigrp->k_values[4] / metric.reliability); + if (eigrp->k_values[3] && eigrp->k_values[4]) + temp_metric *= ((eigrp->k_values[4] / metric.reliability) + + eigrp->k_values[3]); + + if (temp_metric <= EIGRP_MAX_METRIC) + return (u_int32_t)temp_metric; + else + return EIGRP_MAX_METRIC; } -u_int32_t -eigrp_calculate_total_metrics(struct eigrp *eigrp, - struct eigrp_neighbor_entry *entry) +u_int32_t eigrp_calculate_total_metrics(struct eigrp *eigrp, + struct eigrp_neighbor_entry *entry) { - entry->total_metric = entry->reported_metric; - uint64_t temp_delay = (uint64_t) entry->total_metric.delay - + (uint64_t) eigrp_delay_to_scaled (EIGRP_IF_PARAM (entry->ei, delay)); - entry->total_metric.delay = - temp_delay > EIGRP_MAX_METRIC ? EIGRP_MAX_METRIC : (u_int32_t) temp_delay; - - u_int32_t bw = eigrp_bandwidth_to_scaled (EIGRP_IF_PARAM (entry->ei,bandwidth)); - entry->total_metric.bandwith = - entry->total_metric.bandwith > bw ? bw : entry->total_metric.bandwith; - - return eigrp_calculate_metrics(eigrp, entry->total_metric); + entry->total_metric = entry->reported_metric; + uint64_t temp_delay = (uint64_t)entry->total_metric.delay + + (uint64_t)eigrp_delay_to_scaled( + EIGRP_IF_PARAM(entry->ei, delay)); + entry->total_metric.delay = temp_delay > EIGRP_MAX_METRIC + ? EIGRP_MAX_METRIC + : (u_int32_t)temp_delay; + + u_int32_t bw = + eigrp_bandwidth_to_scaled(EIGRP_IF_PARAM(entry->ei, bandwidth)); + entry->total_metric.bandwith = entry->total_metric.bandwith > bw + ? bw + : entry->total_metric.bandwith; + + return eigrp_calculate_metrics(eigrp, entry->total_metric); } -u_char -eigrp_metrics_is_same(struct eigrp_metrics metric1, - struct eigrp_metrics metric2) +u_char eigrp_metrics_is_same(struct eigrp_metrics metric1, + struct eigrp_metrics metric2) { - if ((metric1.bandwith == metric2.bandwith) - && (metric1.delay == metric2.delay) - && (metric1.hop_count == metric2.hop_count) - && (metric1.load == metric2.load) - && (metric1.reliability == metric2.reliability) - && (metric1.mtu[0] == metric2.mtu[0]) - && (metric1.mtu[1] == metric2.mtu[1]) - && (metric1.mtu[2] == metric2.mtu[2])) - return 1; - - return 0; // if different + if ((metric1.bandwith == metric2.bandwith) + && (metric1.delay == metric2.delay) + && (metric1.hop_count == metric2.hop_count) + && (metric1.load == metric2.load) + && (metric1.reliability == metric2.reliability) + && (metric1.mtu[0] == metric2.mtu[0]) + && (metric1.mtu[1] == metric2.mtu[1]) + && (metric1.mtu[2] == metric2.mtu[2])) + return 1; + + return 0; // if different } -void -eigrp_external_routes_refresh (struct eigrp *eigrp, int type) +void eigrp_external_routes_refresh(struct eigrp *eigrp, int type) { - } - diff --git a/eigrpd/eigrp_network.h b/eigrpd/eigrp_network.h index 82ac455c9..e38f7ded4 100644 --- a/eigrpd/eigrp_network.h +++ b/eigrpd/eigrp_network.h @@ -30,22 +30,23 @@ /* Prototypes */ -extern int eigrp_sock_init (void); -extern int eigrp_if_ipmulticast (struct eigrp *, struct prefix *, unsigned int); -extern int eigrp_network_set (struct eigrp *, struct prefix_ipv4 *); -extern int eigrp_network_unset (struct eigrp *eigrp, struct prefix_ipv4 *p); +extern int eigrp_sock_init(void); +extern int eigrp_if_ipmulticast(struct eigrp *, struct prefix *, unsigned int); +extern int eigrp_network_set(struct eigrp *, struct prefix_ipv4 *); +extern int eigrp_network_unset(struct eigrp *eigrp, struct prefix_ipv4 *p); -extern int eigrp_hello_timer (struct thread *); -extern void eigrp_if_update (struct interface *); -extern int eigrp_if_add_allspfrouters (struct eigrp *, struct prefix *, - unsigned int); -extern int eigrp_if_drop_allspfrouters (struct eigrp *top, struct prefix *p, - unsigned int ifindex); -extern void eigrp_adjust_sndbuflen (struct eigrp *, unsigned int); +extern int eigrp_hello_timer(struct thread *); +extern void eigrp_if_update(struct interface *); +extern int eigrp_if_add_allspfrouters(struct eigrp *, struct prefix *, + unsigned int); +extern int eigrp_if_drop_allspfrouters(struct eigrp *top, struct prefix *p, + unsigned int ifindex); +extern void eigrp_adjust_sndbuflen(struct eigrp *, unsigned int); -extern u_int32_t eigrp_calculate_metrics (struct eigrp *, struct eigrp_metrics); -extern u_int32_t eigrp_calculate_total_metrics (struct eigrp *, struct eigrp_neighbor_entry *); +extern u_int32_t eigrp_calculate_metrics(struct eigrp *, struct eigrp_metrics); +extern u_int32_t eigrp_calculate_total_metrics(struct eigrp *, + struct eigrp_neighbor_entry *); extern u_char eigrp_metrics_is_same(struct eigrp_metrics, struct eigrp_metrics); -extern void eigrp_external_routes_refresh (struct eigrp *, int); +extern void eigrp_external_routes_refresh(struct eigrp *, int); #endif /* EIGRP_NETWORK_H_ */ diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index f481dffa9..f20ec0ad1 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -57,252 +57,244 @@ #include "eigrpd/eigrp_memory.h" /* Packet Type String. */ -const struct message eigrp_packet_type_str[] = - { - { EIGRP_OPC_UPDATE, "Update"}, - { EIGRP_OPC_REQUEST, "Request"}, - { EIGRP_OPC_QUERY, "Query"}, - { EIGRP_OPC_REPLY, "Reply"}, - { EIGRP_OPC_HELLO, "Hello"}, - { EIGRP_OPC_IPXSAP, "IPX-SAP"}, - { EIGRP_OPC_PROBE, "Probe"}, - { EIGRP_OPC_ACK, "Ack"}, - { EIGRP_OPC_SIAQUERY, "SIAQuery"}, - { EIGRP_OPC_SIAREPLY, "SIAReply"}, - { 0 } -}; +const struct message eigrp_packet_type_str[] = { + {EIGRP_OPC_UPDATE, "Update"}, + {EIGRP_OPC_REQUEST, "Request"}, + {EIGRP_OPC_QUERY, "Query"}, + {EIGRP_OPC_REPLY, "Reply"}, + {EIGRP_OPC_HELLO, "Hello"}, + {EIGRP_OPC_IPXSAP, "IPX-SAP"}, + {EIGRP_OPC_PROBE, "Probe"}, + {EIGRP_OPC_ACK, "Ack"}, + {EIGRP_OPC_SIAQUERY, "SIAQuery"}, + {EIGRP_OPC_SIAREPLY, "SIAReply"}, + {0}}; static unsigned char zeropad[16] = {0}; /* Forward function reference*/ -static struct stream * eigrp_recv_packet (int, struct interface **, struct stream *); -static int eigrp_verify_header (struct stream *, struct eigrp_interface *, struct ip *, - struct eigrp_header *); -static int eigrp_check_network_mask (struct eigrp_interface *, struct in_addr); - -static int eigrp_retrans_count_exceeded(struct eigrp_packet *ep, struct eigrp_neighbor *nbr) +static struct stream *eigrp_recv_packet(int, struct interface **, + struct stream *); +static int eigrp_verify_header(struct stream *, struct eigrp_interface *, + struct ip *, struct eigrp_header *); +static int eigrp_check_network_mask(struct eigrp_interface *, struct in_addr); + +static int eigrp_retrans_count_exceeded(struct eigrp_packet *ep, + struct eigrp_neighbor *nbr) { - return 1; + return 1; } -int -eigrp_make_md5_digest (struct eigrp_interface *ei, struct stream *s, u_char flags) +int eigrp_make_md5_digest(struct eigrp_interface *ei, struct stream *s, + u_char flags) { - struct key *key = NULL; - struct keychain *keychain; - - unsigned char digest[EIGRP_AUTH_TYPE_MD5_LEN]; - MD5_CTX ctx; - u_char *ibuf; - size_t backup_get, backup_end; - struct TLV_MD5_Authentication_Type *auth_TLV; - - ibuf = s->data; - backup_end = s->endp; - backup_get = s->getp; - - auth_TLV = eigrp_authTLV_MD5_new(); - - stream_set_getp(s,EIGRP_HEADER_LEN); - stream_get(auth_TLV,s,EIGRP_AUTH_MD5_TLV_SIZE); - stream_set_getp(s, backup_get); - - keychain = keychain_lookup(IF_DEF_PARAMS (ei->ifp)->auth_keychain); - if(keychain) - key = key_lookup_for_send(keychain); - else - { - eigrp_authTLV_MD5_free(auth_TLV); - return EIGRP_AUTH_TYPE_NONE; - } - - memset(&ctx, 0, sizeof(ctx)); - MD5Init(&ctx); - - /* Generate a digest. Each situation needs different handling */ - if(flags & EIGRP_AUTH_BASIC_HELLO_FLAG) - { - MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE); - MD5Update(&ctx, key->string, strlen(key->string)); - if(strlen(key->string) < 16) - MD5Update(&ctx, zeropad, 16 - strlen(key->string)); - } - else if(flags & EIGRP_AUTH_UPDATE_INIT_FLAG) - { - MD5Update(&ctx, ibuf, EIGRP_MD5_UPDATE_INIT_COMPUTE); - } - else if(flags & EIGRP_AUTH_UPDATE_FLAG) - { - MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE); - MD5Update(&ctx, key->string, strlen(key->string)); - if(strlen(key->string) < 16) - MD5Update(&ctx, zeropad, 16 - strlen(key->string)); - if(backup_end > (EIGRP_HEADER_LEN + EIGRP_AUTH_MD5_TLV_SIZE)) - { - MD5Update(&ctx, ibuf + (EIGRP_HEADER_LEN + EIGRP_AUTH_MD5_TLV_SIZE), - backup_end - 20 - (EIGRP_HEADER_LEN + EIGRP_AUTH_MD5_TLV_SIZE)); - } - } - - MD5Final(digest, &ctx); - - /* Append md5 digest to the end of the stream. */ - memcpy(auth_TLV->digest,digest,EIGRP_AUTH_TYPE_MD5_LEN); - - stream_set_endp(s,EIGRP_HEADER_LEN); - stream_put(s,auth_TLV,EIGRP_AUTH_MD5_TLV_SIZE); - stream_set_endp(s, backup_end); - - eigrp_authTLV_MD5_free(auth_TLV); - return EIGRP_AUTH_TYPE_MD5_LEN; + struct key *key = NULL; + struct keychain *keychain; + + unsigned char digest[EIGRP_AUTH_TYPE_MD5_LEN]; + MD5_CTX ctx; + u_char *ibuf; + size_t backup_get, backup_end; + struct TLV_MD5_Authentication_Type *auth_TLV; + + ibuf = s->data; + backup_end = s->endp; + backup_get = s->getp; + + auth_TLV = eigrp_authTLV_MD5_new(); + + stream_set_getp(s, EIGRP_HEADER_LEN); + stream_get(auth_TLV, s, EIGRP_AUTH_MD5_TLV_SIZE); + stream_set_getp(s, backup_get); + + keychain = keychain_lookup(IF_DEF_PARAMS(ei->ifp)->auth_keychain); + if (keychain) + key = key_lookup_for_send(keychain); + else { + eigrp_authTLV_MD5_free(auth_TLV); + return EIGRP_AUTH_TYPE_NONE; + } + + memset(&ctx, 0, sizeof(ctx)); + MD5Init(&ctx); + + /* Generate a digest. Each situation needs different handling */ + if (flags & EIGRP_AUTH_BASIC_HELLO_FLAG) { + MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE); + MD5Update(&ctx, key->string, strlen(key->string)); + if (strlen(key->string) < 16) + MD5Update(&ctx, zeropad, 16 - strlen(key->string)); + } else if (flags & EIGRP_AUTH_UPDATE_INIT_FLAG) { + MD5Update(&ctx, ibuf, EIGRP_MD5_UPDATE_INIT_COMPUTE); + } else if (flags & EIGRP_AUTH_UPDATE_FLAG) { + MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE); + MD5Update(&ctx, key->string, strlen(key->string)); + if (strlen(key->string) < 16) + MD5Update(&ctx, zeropad, 16 - strlen(key->string)); + if (backup_end > (EIGRP_HEADER_LEN + EIGRP_AUTH_MD5_TLV_SIZE)) { + MD5Update(&ctx, + ibuf + (EIGRP_HEADER_LEN + + EIGRP_AUTH_MD5_TLV_SIZE), + backup_end - 20 + - (EIGRP_HEADER_LEN + + EIGRP_AUTH_MD5_TLV_SIZE)); + } + } + + MD5Final(digest, &ctx); + + /* Append md5 digest to the end of the stream. */ + memcpy(auth_TLV->digest, digest, EIGRP_AUTH_TYPE_MD5_LEN); + + stream_set_endp(s, EIGRP_HEADER_LEN); + stream_put(s, auth_TLV, EIGRP_AUTH_MD5_TLV_SIZE); + stream_set_endp(s, backup_end); + + eigrp_authTLV_MD5_free(auth_TLV); + return EIGRP_AUTH_TYPE_MD5_LEN; } -int -eigrp_check_md5_digest (struct stream *s, - struct TLV_MD5_Authentication_Type *authTLV,struct eigrp_neighbor *nbr, u_char flags) +int eigrp_check_md5_digest(struct stream *s, + struct TLV_MD5_Authentication_Type *authTLV, + struct eigrp_neighbor *nbr, u_char flags) { - MD5_CTX ctx; - unsigned char digest[EIGRP_AUTH_TYPE_MD5_LEN]; - struct key *key = NULL; - struct keychain *keychain; - u_char *ibuf; - size_t backup_end; - struct TLV_MD5_Authentication_Type *auth_TLV; - struct eigrp_header *eigrph; - - if (nbr && ntohl(nbr->crypt_seqnum) > ntohl(authTLV->key_sequence)) - { - zlog_warn ("interface %s: eigrp_check_md5 bad sequence %d (expect %d)", - IF_NAME (nbr->ei), - ntohl(authTLV->key_sequence), - ntohl(nbr->crypt_seqnum)); - return 0; - } - - eigrph = (struct eigrp_header *) s->data; - eigrph->checksum = 0; - - auth_TLV =(struct TLV_MD5_Authentication_Type *) (s->data + EIGRP_HEADER_LEN); - memset(auth_TLV->digest, 0, sizeof(auth_TLV->digest)); - - ibuf = s->data; - backup_end = s->endp; - - keychain = keychain_lookup(IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain); - if(keychain) - key = key_lookup_for_send(keychain); - - memset(&ctx, 0, sizeof(ctx)); - MD5Init(&ctx); - - /* Generate a digest. Each situation needs different handling */ - if(flags & EIGRP_AUTH_BASIC_HELLO_FLAG) - { - MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE); - MD5Update(&ctx, key->string, strlen(key->string)); - if(strlen(key->string) < 16) - MD5Update(&ctx, zeropad, 16 - strlen(key->string)); - } - else if(flags & EIGRP_AUTH_UPDATE_INIT_FLAG) - { - MD5Update(&ctx, ibuf, EIGRP_MD5_UPDATE_INIT_COMPUTE); - } - else if(flags & EIGRP_AUTH_UPDATE_FLAG) - { - MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE); - MD5Update(&ctx, key->string, strlen(key->string)); - if(strlen(key->string) < 16) - MD5Update(&ctx, zeropad, 16 - strlen(key->string)); - if(backup_end > (EIGRP_HEADER_LEN + EIGRP_AUTH_MD5_TLV_SIZE)) - { - MD5Update(&ctx, ibuf + (EIGRP_HEADER_LEN + EIGRP_AUTH_MD5_TLV_SIZE), - backup_end - 20 - (EIGRP_HEADER_LEN + EIGRP_AUTH_MD5_TLV_SIZE)); - } - } - - MD5Final(digest, &ctx); - - /* compare the two */ - if (memcmp (authTLV->digest, digest, EIGRP_AUTH_TYPE_MD5_LEN) == 0) - { - zlog_debug("VSETKO OK"); - } - else - { - zlog_warn ("interface %s: eigrp_check_md5 checksum mismatch", - IF_NAME (nbr->ei)); - return 0; - } - - /* save neighbor's crypt_seqnum */ - nbr->crypt_seqnum = authTLV->key_sequence; - - return 1; + MD5_CTX ctx; + unsigned char digest[EIGRP_AUTH_TYPE_MD5_LEN]; + struct key *key = NULL; + struct keychain *keychain; + u_char *ibuf; + size_t backup_end; + struct TLV_MD5_Authentication_Type *auth_TLV; + struct eigrp_header *eigrph; + + if (nbr && ntohl(nbr->crypt_seqnum) > ntohl(authTLV->key_sequence)) { + zlog_warn( + "interface %s: eigrp_check_md5 bad sequence %d (expect %d)", + IF_NAME(nbr->ei), ntohl(authTLV->key_sequence), + ntohl(nbr->crypt_seqnum)); + return 0; + } + + eigrph = (struct eigrp_header *)s->data; + eigrph->checksum = 0; + + auth_TLV = (struct TLV_MD5_Authentication_Type *)(s->data + + EIGRP_HEADER_LEN); + memset(auth_TLV->digest, 0, sizeof(auth_TLV->digest)); + + ibuf = s->data; + backup_end = s->endp; + + keychain = keychain_lookup(IF_DEF_PARAMS(nbr->ei->ifp)->auth_keychain); + if (keychain) + key = key_lookup_for_send(keychain); + + memset(&ctx, 0, sizeof(ctx)); + MD5Init(&ctx); + + /* Generate a digest. Each situation needs different handling */ + if (flags & EIGRP_AUTH_BASIC_HELLO_FLAG) { + MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE); + MD5Update(&ctx, key->string, strlen(key->string)); + if (strlen(key->string) < 16) + MD5Update(&ctx, zeropad, 16 - strlen(key->string)); + } else if (flags & EIGRP_AUTH_UPDATE_INIT_FLAG) { + MD5Update(&ctx, ibuf, EIGRP_MD5_UPDATE_INIT_COMPUTE); + } else if (flags & EIGRP_AUTH_UPDATE_FLAG) { + MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE); + MD5Update(&ctx, key->string, strlen(key->string)); + if (strlen(key->string) < 16) + MD5Update(&ctx, zeropad, 16 - strlen(key->string)); + if (backup_end > (EIGRP_HEADER_LEN + EIGRP_AUTH_MD5_TLV_SIZE)) { + MD5Update(&ctx, + ibuf + (EIGRP_HEADER_LEN + + EIGRP_AUTH_MD5_TLV_SIZE), + backup_end - 20 + - (EIGRP_HEADER_LEN + + EIGRP_AUTH_MD5_TLV_SIZE)); + } + } + + MD5Final(digest, &ctx); + + /* compare the two */ + if (memcmp(authTLV->digest, digest, EIGRP_AUTH_TYPE_MD5_LEN) == 0) { + zlog_debug("VSETKO OK"); + } else { + zlog_warn("interface %s: eigrp_check_md5 checksum mismatch", + IF_NAME(nbr->ei)); + return 0; + } + + /* save neighbor's crypt_seqnum */ + nbr->crypt_seqnum = authTLV->key_sequence; + + return 1; } -int -eigrp_make_sha256_digest (struct eigrp_interface *ei, struct stream *s, u_char flags) +int eigrp_make_sha256_digest(struct eigrp_interface *ei, struct stream *s, + u_char flags) { - struct key *key = NULL; - struct keychain *keychain; - char *source_ip; + struct key *key = NULL; + struct keychain *keychain; + char *source_ip; - unsigned char digest[EIGRP_AUTH_TYPE_SHA256_LEN]; - unsigned char buffer[1 + PLAINTEXT_LENGTH + 45 + 1] = { 0 }; - HMAC_SHA256_CTX ctx; - void *ibuf; - size_t backup_get, backup_end; - struct TLV_SHA256_Authentication_Type *auth_TLV; + unsigned char digest[EIGRP_AUTH_TYPE_SHA256_LEN]; + unsigned char buffer[1 + PLAINTEXT_LENGTH + 45 + 1] = {0}; + HMAC_SHA256_CTX ctx; + void *ibuf; + size_t backup_get, backup_end; + struct TLV_SHA256_Authentication_Type *auth_TLV; - ibuf = s->data; - backup_end = s->endp; - backup_get = s->getp; + ibuf = s->data; + backup_end = s->endp; + backup_get = s->getp; - auth_TLV = eigrp_authTLV_SHA256_new (); + auth_TLV = eigrp_authTLV_SHA256_new(); - stream_set_getp(s,EIGRP_HEADER_LEN); - stream_get(auth_TLV,s,EIGRP_AUTH_SHA256_TLV_SIZE); - stream_set_getp(s, backup_get); + stream_set_getp(s, EIGRP_HEADER_LEN); + stream_get(auth_TLV, s, EIGRP_AUTH_SHA256_TLV_SIZE); + stream_set_getp(s, backup_get); - keychain = keychain_lookup(IF_DEF_PARAMS (ei->ifp)->auth_keychain); - if(keychain) - key = key_lookup_for_send(keychain); + keychain = keychain_lookup(IF_DEF_PARAMS(ei->ifp)->auth_keychain); + if (keychain) + key = key_lookup_for_send(keychain); - // saved_len[index] = strnzcpyn(saved_key[index], key, - // PLAINTEXT_LENGTH + 1); + // saved_len[index] = strnzcpyn(saved_key[index], key, + // PLAINTEXT_LENGTH + 1); - source_ip = calloc(16, sizeof(char)); - inet_ntop(AF_INET, &ei->address->u.prefix4, source_ip, 16); + source_ip = calloc(16, sizeof(char)); + inet_ntop(AF_INET, &ei->address->u.prefix4, source_ip, 16); - memset(&ctx, 0, sizeof(ctx)); - buffer[0] = '\n'; - memcpy(buffer + 1, key, strlen (key->string)); - memcpy(buffer + 1 + strlen(key->string), source_ip, strlen(source_ip)); - HMAC__SHA256_Init(&ctx, buffer, 1 + strlen (key->string) + strlen(source_ip)); - HMAC__SHA256_Update(&ctx, ibuf, strlen(ibuf)); - HMAC__SHA256_Final(digest, &ctx); + memset(&ctx, 0, sizeof(ctx)); + buffer[0] = '\n'; + memcpy(buffer + 1, key, strlen(key->string)); + memcpy(buffer + 1 + strlen(key->string), source_ip, strlen(source_ip)); + HMAC__SHA256_Init(&ctx, buffer, + 1 + strlen(key->string) + strlen(source_ip)); + HMAC__SHA256_Update(&ctx, ibuf, strlen(ibuf)); + HMAC__SHA256_Final(digest, &ctx); - /* Put hmac-sha256 digest to it's place */ - memcpy(auth_TLV->digest,digest,EIGRP_AUTH_TYPE_SHA256_LEN); + /* Put hmac-sha256 digest to it's place */ + memcpy(auth_TLV->digest, digest, EIGRP_AUTH_TYPE_SHA256_LEN); - stream_set_endp(s,EIGRP_HEADER_LEN); - stream_put(s,auth_TLV,EIGRP_AUTH_SHA256_TLV_SIZE); - stream_set_endp(s, backup_end); + stream_set_endp(s, EIGRP_HEADER_LEN); + stream_put(s, auth_TLV, EIGRP_AUTH_SHA256_TLV_SIZE); + stream_set_endp(s, backup_end); - eigrp_authTLV_SHA256_free(auth_TLV); - free(source_ip); + eigrp_authTLV_SHA256_free(auth_TLV); + free(source_ip); - return EIGRP_AUTH_TYPE_SHA256_LEN; + return EIGRP_AUTH_TYPE_SHA256_LEN; } -int -eigrp_check_sha256_digest (struct stream *s, - struct TLV_SHA256_Authentication_Type *authTLV, - struct eigrp_neighbor *nbr, u_char flags) +int eigrp_check_sha256_digest(struct stream *s, + struct TLV_SHA256_Authentication_Type *authTLV, + struct eigrp_neighbor *nbr, u_char flags) { - return 1; + return 1; } /* @@ -311,1109 +303,1083 @@ eigrp_check_sha256_digest (struct stream *s, * This routing dumps the contents of the IP packet either received or * built by EIGRP. */ -static void -eigrp_packet_dump (struct stream *s) +static void eigrp_packet_dump(struct stream *s) { - // not yet... - return; + // not yet... + return; } -int -eigrp_write (struct thread *thread) +int eigrp_write(struct thread *thread) { - struct eigrp *eigrp = THREAD_ARG(thread); - struct eigrp_header *eigrph; - struct eigrp_interface *ei; - struct eigrp_packet *ep; - struct sockaddr_in sa_dst; - struct ip iph; - struct msghdr msg; - struct iovec iov[2]; - u_int16_t opcode = 0; - - int ret; - int flags = 0; - struct listnode *node; + struct eigrp *eigrp = THREAD_ARG(thread); + struct eigrp_header *eigrph; + struct eigrp_interface *ei; + struct eigrp_packet *ep; + struct sockaddr_in sa_dst; + struct ip iph; + struct msghdr msg; + struct iovec iov[2]; + u_int16_t opcode = 0; + + int ret; + int flags = 0; + struct listnode *node; #ifdef WANT_EIGRP_WRITE_FRAGMENT - static u_int16_t ipid = 0; + static u_int16_t ipid = 0; #endif /* WANT_EIGRP_WRITE_FRAGMENT */ + /* $FRR indent$ */ +/* clang-format off */ #define EIGRP_WRITE_IPHL_SHIFT 2 - eigrp->t_write = NULL; + eigrp->t_write = NULL; - node = listhead(eigrp->oi_write_q); - assert(node); - ei = listgetdata(node); - assert(ei); + node = listhead(eigrp->oi_write_q); + assert(node); + ei = listgetdata(node); + assert(ei); #ifdef WANT_EIGRP_WRITE_FRAGMENT - /* seed ipid static with low order bits of time */ - if (ipid == 0) - ipid = (time(NULL) & 0xffff); + /* seed ipid static with low order bits of time */ + if (ipid == 0) + ipid = (time(NULL) & 0xffff); #endif /* WANT_EIGRP_WRITE_FRAGMENT */ - /* Get one packet from queue. */ - ep = eigrp_fifo_head(ei->obuf); - assert(ep); - assert(ep->length >= EIGRP_HEADER_LEN); + /* Get one packet from queue. */ + ep = eigrp_fifo_head(ei->obuf); + assert(ep); + assert(ep->length >= EIGRP_HEADER_LEN); - if (ep->dst.s_addr == htonl(EIGRP_MULTICAST_ADDRESS)) - eigrp_if_ipmulticast(eigrp, ei->address, ei->ifp->ifindex); + if (ep->dst.s_addr == htonl(EIGRP_MULTICAST_ADDRESS)) + eigrp_if_ipmulticast(eigrp, ei->address, ei->ifp->ifindex); - memset(&iph, 0, sizeof(struct ip)); - memset(&sa_dst, 0, sizeof(sa_dst)); + memset(&iph, 0, sizeof(struct ip)); + memset(&sa_dst, 0, sizeof(sa_dst)); - sa_dst.sin_family = AF_INET; + sa_dst.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sa_dst.sin_len = sizeof(sa_dst); + sa_dst.sin_len = sizeof(sa_dst); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - sa_dst.sin_addr = ep->dst; - sa_dst.sin_port = htons(0); - - /* Set DONTROUTE flag if dst is unicast. */ - if (!IN_MULTICAST(htonl(ep->dst.s_addr))) - flags = MSG_DONTROUTE; - - iph.ip_hl = sizeof(struct ip) >> EIGRP_WRITE_IPHL_SHIFT; - /* it'd be very strange for header to not be 4byte-word aligned but.. */ - if (sizeof(struct ip) > (unsigned int)(iph.ip_hl << EIGRP_WRITE_IPHL_SHIFT)) - iph.ip_hl++; /* we presume sizeof struct ip cant overflow ip_hl.. */ - - iph.ip_v = IPVERSION; - iph.ip_tos = IPTOS_PREC_INTERNETCONTROL; - iph.ip_len = (iph.ip_hl << EIGRP_WRITE_IPHL_SHIFT) + ep->length; - -#if defined (__DragonFly__) - /* - * DragonFly's raw socket expects ip_len/ip_off in network byte order. - */ - iph.ip_len = htons(iph.ip_len); + sa_dst.sin_addr = ep->dst; + sa_dst.sin_port = htons(0); + + /* Set DONTROUTE flag if dst is unicast. */ + if (!IN_MULTICAST(htonl(ep->dst.s_addr))) + flags = MSG_DONTROUTE; + + iph.ip_hl = sizeof(struct ip) >> EIGRP_WRITE_IPHL_SHIFT; + /* it'd be very strange for header to not be 4byte-word aligned but.. */ + if (sizeof(struct ip) + > (unsigned int)(iph.ip_hl << EIGRP_WRITE_IPHL_SHIFT)) + iph.ip_hl++; /* we presume sizeof struct ip cant overflow + ip_hl.. */ + + iph.ip_v = IPVERSION; + iph.ip_tos = IPTOS_PREC_INTERNETCONTROL; + iph.ip_len = (iph.ip_hl << EIGRP_WRITE_IPHL_SHIFT) + ep->length; + +#if defined(__DragonFly__) + /* + * DragonFly's raw socket expects ip_len/ip_off in network byte order. + */ + iph.ip_len = htons(iph.ip_len); #endif - iph.ip_off = 0; - iph.ip_ttl = EIGRP_IP_TTL; - iph.ip_p = IPPROTO_EIGRPIGP; - iph.ip_sum = 0; - iph.ip_src.s_addr = ei->address->u.prefix4.s_addr; - iph.ip_dst.s_addr = ep->dst.s_addr; - - memset(&msg, 0, sizeof(msg)); - msg.msg_name = (caddr_t) &sa_dst; - msg.msg_namelen = sizeof(sa_dst); - msg.msg_iov = iov; - msg.msg_iovlen = 2; - - iov[0].iov_base = (char*)&iph; - iov[0].iov_len = iph.ip_hl << EIGRP_WRITE_IPHL_SHIFT; - iov[1].iov_base = STREAM_PNT(ep->s); - iov[1].iov_len = ep->length; - - /* send final fragment (could be first) */ - sockopt_iphdrincl_swab_htosys(&iph); - ret = sendmsg(eigrp->fd, &msg, flags); - sockopt_iphdrincl_swab_systoh(&iph); - - if (IS_DEBUG_EIGRP_TRANSMIT(0, SEND)) - { - eigrph = (struct eigrp_header *) STREAM_DATA(ep->s); - opcode = eigrph->opcode; - zlog_debug("Sending [%s] to [%s] via [%s] ret [%d].", - lookup_msg(eigrp_packet_type_str, opcode, NULL), - inet_ntoa(ep->dst), - IF_NAME(ei), ret); - } - - if (ret < 0) - zlog_warn("*** sendmsg in eigrp_write failed to %s, " - "id %d, off %d, len %d, interface %s, mtu %u: %s", - inet_ntoa(iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len, ei->ifp->name, - ei->ifp->mtu, safe_strerror(errno)); - - /* Show debug sending packet. */ - if (IS_DEBUG_EIGRP_TRANSMIT(0, SEND) && (IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL))) - { - zlog_debug("-----------------------------------------------------"); - eigrp_ip_header_dump(&iph); - stream_set_getp(ep->s, 0); - eigrp_packet_dump(ep->s); - zlog_debug("-----------------------------------------------------"); - } - - /* Now delete packet from queue. */ - eigrp_packet_delete(ei); - - if (eigrp_fifo_head(ei->obuf) == NULL) - { - ei->on_write_q = 0; - list_delete_node(eigrp->oi_write_q, node); - } - - /* If packets still remain in queue, call write thread. */ - if (!list_isempty(eigrp->oi_write_q)) { - eigrp->t_write = NULL; - thread_add_write(master, eigrp_write, eigrp, eigrp->fd, &eigrp->t_write); - } - - return 0; + iph.ip_off = 0; + iph.ip_ttl = EIGRP_IP_TTL; + iph.ip_p = IPPROTO_EIGRPIGP; + iph.ip_sum = 0; + iph.ip_src.s_addr = ei->address->u.prefix4.s_addr; + iph.ip_dst.s_addr = ep->dst.s_addr; + + memset(&msg, 0, sizeof(msg)); + msg.msg_name = (caddr_t)&sa_dst; + msg.msg_namelen = sizeof(sa_dst); + msg.msg_iov = iov; + msg.msg_iovlen = 2; + + iov[0].iov_base = (char *)&iph; + iov[0].iov_len = iph.ip_hl << EIGRP_WRITE_IPHL_SHIFT; + iov[1].iov_base = STREAM_PNT(ep->s); + iov[1].iov_len = ep->length; + + /* send final fragment (could be first) */ + sockopt_iphdrincl_swab_htosys(&iph); + ret = sendmsg(eigrp->fd, &msg, flags); + sockopt_iphdrincl_swab_systoh(&iph); + + if (IS_DEBUG_EIGRP_TRANSMIT(0, SEND)) { + eigrph = (struct eigrp_header *)STREAM_DATA(ep->s); + opcode = eigrph->opcode; + zlog_debug("Sending [%s] to [%s] via [%s] ret [%d].", + lookup_msg(eigrp_packet_type_str, opcode, NULL), + inet_ntoa(ep->dst), IF_NAME(ei), ret); + } + + if (ret < 0) + zlog_warn( + "*** sendmsg in eigrp_write failed to %s, " + "id %d, off %d, len %d, interface %s, mtu %u: %s", + inet_ntoa(iph.ip_dst), iph.ip_id, iph.ip_off, + iph.ip_len, ei->ifp->name, ei->ifp->mtu, + safe_strerror(errno)); + + /* Show debug sending packet. */ + if (IS_DEBUG_EIGRP_TRANSMIT(0, SEND) + && (IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL))) { + zlog_debug( + "-----------------------------------------------------"); + eigrp_ip_header_dump(&iph); + stream_set_getp(ep->s, 0); + eigrp_packet_dump(ep->s); + zlog_debug( + "-----------------------------------------------------"); + } + + /* Now delete packet from queue. */ + eigrp_packet_delete(ei); + + if (eigrp_fifo_head(ei->obuf) == NULL) { + ei->on_write_q = 0; + list_delete_node(eigrp->oi_write_q, node); + } + + /* If packets still remain in queue, call write thread. */ + if (!list_isempty(eigrp->oi_write_q)) { + eigrp->t_write = NULL; + thread_add_write(master, eigrp_write, eigrp, eigrp->fd, + &eigrp->t_write); + } + + return 0; } /* Starting point of packet process function. */ -int -eigrp_read (struct thread *thread) +int eigrp_read(struct thread *thread) { - int ret; - struct stream *ibuf; - struct eigrp *eigrp; - struct eigrp_interface *ei; - struct ip *iph; - struct eigrp_header *eigrph; - struct interface *ifp; - struct eigrp_neighbor *nbr; - - u_int16_t opcode = 0; - u_int16_t length = 0; - - /* first of all get interface pointer. */ - eigrp = THREAD_ARG(thread); - - /* prepare for next packet. */ - eigrp->t_read = NULL; - thread_add_read(master, eigrp_read, eigrp, eigrp->fd, &eigrp->t_read); - - stream_reset(eigrp->ibuf); - if (!(ibuf = eigrp_recv_packet(eigrp->fd, &ifp, eigrp->ibuf))) - { - /* This raw packet is known to be at least as big as its IP header. */ - return -1; - } - - /* Note that there should not be alignment problems with this assignment - because this is at the beginning of the stream data buffer. */ - iph = (struct ip *)STREAM_DATA(ibuf); - - //Substract IPv4 header size from EIGRP Packet itself - if(iph->ip_v == 4) - length = (iph->ip_len) - 20U; - - - /* IP Header dump. */ - if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV) && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL)) - eigrp_ip_header_dump(iph); - - /* Note that sockopt_iphdrincl_swab_systoh was called in eigrp_recv_packet. */ - if (ifp == NULL) - { - struct connected *c; - /* Handle cases where the platform does not support retrieving the ifindex, - and also platforms (such as Solaris 8) that claim to support ifindex - retrieval but do not. */ - c = if_lookup_address((void *)&iph->ip_src, AF_INET, VRF_DEFAULT); - - if (c == NULL) - return 0; - - ifp = c->ifp; - } - - /* associate packet with eigrp interface */ - ei = eigrp_if_lookup_recv_if(eigrp, iph->ip_src, ifp); - - /* eigrp_verify_header() relies on a valid "ei" and thus can be called only - after the checks below are passed. These checks in turn access the - fields of unverified "eigrph" structure for their own purposes and - must remain very accurate in doing this. - */ - if (!ei) - return 0; - - /* Self-originated packet should be discarded silently. */ - if (eigrp_if_lookup_by_local_addr(eigrp, NULL, iph->ip_src) || - (IPV4_ADDR_SAME(&iph->ip_src.s_addr, &ei->address->u.prefix4))) - { - if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) - zlog_debug("eigrp_read[%s]: Dropping self-originated packet", - inet_ntoa(iph->ip_src)); - return 0; - } - - /* Advance from IP header to EIGRP header (iph->ip_hl has been verified - by eigrp_recv_packet() to be correct). */ - - stream_forward_getp(ibuf, (iph->ip_hl * 4)); - eigrph = (struct eigrp_header *) STREAM_PNT(ibuf); - - if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV) && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL)) - eigrp_header_dump(eigrph); - - // if (MSG_OK != eigrp_packet_examin(eigrph, stream_get_endp(ibuf) - stream_get_getp(ibuf))) - // return -1; - - /* Now it is safe to access all fields of EIGRP packet header. */ - /* associate packet with eigrp interface */ - ei = eigrp_if_lookup_recv_if(eigrp, iph->ip_src, ifp); - - /* eigrp_verify_header() relies on a valid "ei" and thus can be called only - after the checks below are passed. These checks in turn access the - fields of unverified "eigrph" structure for their own purposes and - must remain very accurate in doing this. - */ - if (!ei) - return 0; - - /* If incoming interface is passive one, ignore it. */ - if (ei && EIGRP_IF_PASSIVE_STATUS(ei) == EIGRP_IF_PASSIVE) - { - char buf[3][INET_ADDRSTRLEN]; - - if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) - zlog_debug("ignoring packet from router %s sent to %s, " - "received on a passive interface, %s", - inet_ntop(AF_INET, &eigrph->vrid, buf[0], sizeof(buf[0])), - inet_ntop(AF_INET, &iph->ip_dst, buf[1], sizeof(buf[1])), - inet_ntop(AF_INET, &ei->address->u.prefix4, - buf[2], sizeof(buf[2]))); - - if (iph->ip_dst.s_addr == htonl(EIGRP_MULTICAST_ADDRESS)) - { - /* Try to fix multicast membership. - * Some OS:es may have problems in this area, - * make sure it is removed. - */ - EI_MEMBER_JOINED(ei, MEMBER_ALLROUTERS); - eigrp_if_set_multicast(ei); - } - return 0; - } - - /* else it must be a local eigrp interface, check it was received on - * correct link - */ - else if (ei->ifp != ifp) - { - if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) - zlog_warn("Packet from [%s] received on wrong link %s", - inet_ntoa(iph->ip_src), ifp->name); - return 0; - } - - /* Verify more EIGRP header fields. */ - ret = eigrp_verify_header(ibuf, ei, iph, eigrph); - if (ret < 0) - { - if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) - zlog_debug("eigrp_read[%s]: Header check failed, dropping.", - inet_ntoa(iph->ip_src)); - return ret; - } - - /* calcualte the eigrp packet length, and move the pounter to the - start of the eigrp TLVs */ - opcode = eigrph->opcode; - - if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) - zlog_debug("Received [%s] length [%u] via [%s] src [%s] dst [%s]", - lookup_msg(eigrp_packet_type_str, opcode, NULL), length, - IF_NAME(ei), inet_ntoa(iph->ip_src), inet_ntoa(iph->ip_dst)); - - /* Read rest of the packet and call each sort of packet routine. */ - stream_forward_getp(ibuf, EIGRP_HEADER_LEN); - - /* New testing block of code for handling Acks */ - if (ntohl(eigrph->ack) != 0) - { - nbr = eigrp_nbr_get(ei, eigrph, iph); - - /* neighbor must be valid, eigrp_nbr_get creates if none existed */ - assert(nbr); - - struct eigrp_packet *ep; - - ep = eigrp_fifo_tail(nbr->retrans_queue); - if (ep) - { - if (ntohl(eigrph->ack) == ep->sequence_number) - { - if((nbr->state == EIGRP_NEIGHBOR_PENDING) && - (ntohl(eigrph->ack) == nbr->init_sequence_number)) - { - eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_UP); - zlog_info("Neighbor adjacency became full"); - nbr->init_sequence_number = 0; - nbr->recv_sequence_number = ntohl(eigrph->sequence); - eigrp_update_send_EOT(nbr); - } - ep = eigrp_fifo_pop_tail(nbr->retrans_queue); - eigrp_packet_free(ep); - if (nbr->retrans_queue->count > 0) - { - eigrp_send_packet_reliably(nbr); - } - } - } - ep = eigrp_fifo_tail(nbr->multicast_queue); - if (ep) - { - if (ntohl(eigrph->ack) == ep->sequence_number) - { - ep = eigrp_fifo_pop_tail(nbr->multicast_queue); - eigrp_packet_free(ep); - if (nbr->multicast_queue->count > 0) - { - eigrp_send_packet_reliably(nbr); - } - } - } - } - - - switch (opcode) - { - case EIGRP_OPC_HELLO: - eigrp_hello_receive(eigrp, iph, eigrph, ibuf, ei, length); - break; - case EIGRP_OPC_PROBE: - // eigrp_probe_receive(eigrp, iph, eigrph, ibuf, ei, length); - break; - case EIGRP_OPC_QUERY: - eigrp_query_receive(eigrp, iph, eigrph, ibuf, ei, length); - break; - case EIGRP_OPC_REPLY: - eigrp_reply_receive(eigrp, iph, eigrph, ibuf, ei, length); - break; - case EIGRP_OPC_REQUEST: - // eigrp_request_receive(eigrp, iph, eigrph, ibuf, ei, length); - break; - case EIGRP_OPC_SIAQUERY: - eigrp_query_receive(eigrp, iph, eigrph, ibuf, ei, length); - break; - case EIGRP_OPC_SIAREPLY: - eigrp_reply_receive(eigrp, iph, eigrph, ibuf, ei, length); - break; - case EIGRP_OPC_UPDATE: - eigrp_update_receive(eigrp, iph, eigrph, ibuf, ei, length); - break; - default: - zlog_warn("interface %s: EIGRP packet header type %d unsupported", - IF_NAME(ei), opcode); - break; - } - - return 0; + int ret; + struct stream *ibuf; + struct eigrp *eigrp; + struct eigrp_interface *ei; + struct ip *iph; + struct eigrp_header *eigrph; + struct interface *ifp; + struct eigrp_neighbor *nbr; + + u_int16_t opcode = 0; + u_int16_t length = 0; + + /* first of all get interface pointer. */ + eigrp = THREAD_ARG(thread); + + /* prepare for next packet. */ + eigrp->t_read = NULL; + thread_add_read(master, eigrp_read, eigrp, eigrp->fd, &eigrp->t_read); + + stream_reset(eigrp->ibuf); + if (!(ibuf = eigrp_recv_packet(eigrp->fd, &ifp, eigrp->ibuf))) { + /* This raw packet is known to be at least as big as its IP + * header. */ + return -1; + } + + /* Note that there should not be alignment problems with this assignment + because this is at the beginning of the stream data buffer. */ + iph = (struct ip *)STREAM_DATA(ibuf); + + // Substract IPv4 header size from EIGRP Packet itself + if (iph->ip_v == 4) + length = (iph->ip_len) - 20U; + + + /* IP Header dump. */ + if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV) + && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL)) + eigrp_ip_header_dump(iph); + + /* Note that sockopt_iphdrincl_swab_systoh was called in + * eigrp_recv_packet. */ + if (ifp == NULL) { + struct connected *c; + /* Handle cases where the platform does not support retrieving + the ifindex, + and also platforms (such as Solaris 8) that claim to support + ifindex + retrieval but do not. */ + c = if_lookup_address((void *)&iph->ip_src, AF_INET, + VRF_DEFAULT); + + if (c == NULL) + return 0; + + ifp = c->ifp; + } + + /* associate packet with eigrp interface */ + ei = eigrp_if_lookup_recv_if(eigrp, iph->ip_src, ifp); + + /* eigrp_verify_header() relies on a valid "ei" and thus can be called + only + after the checks below are passed. These checks in turn access the + fields of unverified "eigrph" structure for their own purposes and + must remain very accurate in doing this. + */ + if (!ei) + return 0; + + /* Self-originated packet should be discarded silently. */ + if (eigrp_if_lookup_by_local_addr(eigrp, NULL, iph->ip_src) + || (IPV4_ADDR_SAME(&iph->ip_src.s_addr, &ei->address->u.prefix4))) { + if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) + zlog_debug( + "eigrp_read[%s]: Dropping self-originated packet", + inet_ntoa(iph->ip_src)); + return 0; + } + + /* Advance from IP header to EIGRP header (iph->ip_hl has been verified + by eigrp_recv_packet() to be correct). */ + + stream_forward_getp(ibuf, (iph->ip_hl * 4)); + eigrph = (struct eigrp_header *)STREAM_PNT(ibuf); + + if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV) + && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL)) + eigrp_header_dump(eigrph); + + // if (MSG_OK != eigrp_packet_examin(eigrph, stream_get_endp(ibuf) - + // stream_get_getp(ibuf))) + // return -1; + + /* Now it is safe to access all fields of EIGRP packet header. */ + /* associate packet with eigrp interface */ + ei = eigrp_if_lookup_recv_if(eigrp, iph->ip_src, ifp); + + /* eigrp_verify_header() relies on a valid "ei" and thus can be called + only + after the checks below are passed. These checks in turn access the + fields of unverified "eigrph" structure for their own purposes and + must remain very accurate in doing this. + */ + if (!ei) + return 0; + + /* If incoming interface is passive one, ignore it. */ + if (ei && EIGRP_IF_PASSIVE_STATUS(ei) == EIGRP_IF_PASSIVE) { + char buf[3][INET_ADDRSTRLEN]; + + if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) + zlog_debug( + "ignoring packet from router %s sent to %s, " + "received on a passive interface, %s", + inet_ntop(AF_INET, &eigrph->vrid, buf[0], + sizeof(buf[0])), + inet_ntop(AF_INET, &iph->ip_dst, buf[1], + sizeof(buf[1])), + inet_ntop(AF_INET, &ei->address->u.prefix4, + buf[2], sizeof(buf[2]))); + + if (iph->ip_dst.s_addr == htonl(EIGRP_MULTICAST_ADDRESS)) { + /* Try to fix multicast membership. + * Some OS:es may have problems in this area, + * make sure it is removed. + */ + EI_MEMBER_JOINED(ei, MEMBER_ALLROUTERS); + eigrp_if_set_multicast(ei); + } + return 0; + } + + /* else it must be a local eigrp interface, check it was received on + * correct link + */ + else if (ei->ifp != ifp) { + if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) + zlog_warn("Packet from [%s] received on wrong link %s", + inet_ntoa(iph->ip_src), ifp->name); + return 0; + } + + /* Verify more EIGRP header fields. */ + ret = eigrp_verify_header(ibuf, ei, iph, eigrph); + if (ret < 0) { + if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) + zlog_debug( + "eigrp_read[%s]: Header check failed, dropping.", + inet_ntoa(iph->ip_src)); + return ret; + } + + /* calcualte the eigrp packet length, and move the pounter to the + start of the eigrp TLVs */ + opcode = eigrph->opcode; + + if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) + zlog_debug( + "Received [%s] length [%u] via [%s] src [%s] dst [%s]", + lookup_msg(eigrp_packet_type_str, opcode, NULL), length, + IF_NAME(ei), inet_ntoa(iph->ip_src), + inet_ntoa(iph->ip_dst)); + + /* Read rest of the packet and call each sort of packet routine. */ + stream_forward_getp(ibuf, EIGRP_HEADER_LEN); + + /* New testing block of code for handling Acks */ + if (ntohl(eigrph->ack) != 0) { + nbr = eigrp_nbr_get(ei, eigrph, iph); + + /* neighbor must be valid, eigrp_nbr_get creates if none existed + */ + assert(nbr); + + struct eigrp_packet *ep; + + ep = eigrp_fifo_tail(nbr->retrans_queue); + if (ep) { + if (ntohl(eigrph->ack) == ep->sequence_number) { + if ((nbr->state == EIGRP_NEIGHBOR_PENDING) + && (ntohl(eigrph->ack) + == nbr->init_sequence_number)) { + eigrp_nbr_state_set(nbr, + EIGRP_NEIGHBOR_UP); + zlog_info( + "Neighbor adjacency became full"); + nbr->init_sequence_number = 0; + nbr->recv_sequence_number = + ntohl(eigrph->sequence); + eigrp_update_send_EOT(nbr); + } + ep = eigrp_fifo_pop_tail(nbr->retrans_queue); + eigrp_packet_free(ep); + if (nbr->retrans_queue->count > 0) { + eigrp_send_packet_reliably(nbr); + } + } + } + ep = eigrp_fifo_tail(nbr->multicast_queue); + if (ep) { + if (ntohl(eigrph->ack) == ep->sequence_number) { + ep = eigrp_fifo_pop_tail(nbr->multicast_queue); + eigrp_packet_free(ep); + if (nbr->multicast_queue->count > 0) { + eigrp_send_packet_reliably(nbr); + } + } + } + } + + + switch (opcode) { + case EIGRP_OPC_HELLO: + eigrp_hello_receive(eigrp, iph, eigrph, ibuf, ei, length); + break; + case EIGRP_OPC_PROBE: + // eigrp_probe_receive(eigrp, iph, eigrph, ibuf, ei, + // length); + break; + case EIGRP_OPC_QUERY: + eigrp_query_receive(eigrp, iph, eigrph, ibuf, ei, length); + break; + case EIGRP_OPC_REPLY: + eigrp_reply_receive(eigrp, iph, eigrph, ibuf, ei, length); + break; + case EIGRP_OPC_REQUEST: + // eigrp_request_receive(eigrp, iph, eigrph, ibuf, ei, + // length); + break; + case EIGRP_OPC_SIAQUERY: + eigrp_query_receive(eigrp, iph, eigrph, ibuf, ei, length); + break; + case EIGRP_OPC_SIAREPLY: + eigrp_reply_receive(eigrp, iph, eigrph, ibuf, ei, length); + break; + case EIGRP_OPC_UPDATE: + eigrp_update_receive(eigrp, iph, eigrph, ibuf, ei, length); + break; + default: + zlog_warn( + "interface %s: EIGRP packet header type %d unsupported", + IF_NAME(ei), opcode); + break; + } + + return 0; } -static struct stream * -eigrp_recv_packet (int fd, struct interface **ifp, struct stream *ibuf) +static struct stream *eigrp_recv_packet(int fd, struct interface **ifp, + struct stream *ibuf) { - int ret; - struct ip *iph; - u_int16_t ip_len; - unsigned int ifindex = 0; - struct iovec iov; - /* Header and data both require alignment. */ - char buff[CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())]; - struct msghdr msgh; - - memset(&msgh, 0, sizeof(struct msghdr)); - msgh.msg_iov = &iov; - msgh.msg_iovlen = 1; - msgh.msg_control = (caddr_t) buff; - msgh.msg_controllen = sizeof(buff); - - ret = stream_recvmsg(ibuf, fd, &msgh, 0, (EIGRP_PACKET_MAX_LEN + 1)); - if (ret < 0) - { - zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno)); - return NULL; - } - if ((unsigned int) ret < sizeof(iph)) /* ret must be > 0 now */ - { - zlog_warn("eigrp_recv_packet: discarding runt packet of length %d " - "(ip header size is %u)", ret, (u_int) sizeof(iph)); - return NULL; - } - - /* Note that there should not be alignment problems with this assignment - because this is at the beginning of the stream data buffer. */ - iph = (struct ip *) STREAM_DATA(ibuf); - sockopt_iphdrincl_swab_systoh(iph); - - ip_len = iph->ip_len; - -#if !defined (GNU_LINUX) && (OpenBSD < 200311) && (__FreeBSD_version < 1000000) - /* - * Kernel network code touches incoming IP header parameters, - * before protocol specific processing. - * - * 1) Convert byteorder to host representation. - * --> ip_len, ip_id, ip_off - * - * 2) Adjust ip_len to strip IP header size! - * --> If user process receives entire IP packet via RAW - * socket, it must consider adding IP header size to - * the "ip_len" field of "ip" structure. - * - * For more details, see . - */ - ip_len = ip_len + (iph->ip_hl << 2); + int ret; + struct ip *iph; + u_int16_t ip_len; + unsigned int ifindex = 0; + struct iovec iov; + /* Header and data both require alignment. */ + char buff[CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())]; + struct msghdr msgh; + + memset(&msgh, 0, sizeof(struct msghdr)); + msgh.msg_iov = &iov; + msgh.msg_iovlen = 1; + msgh.msg_control = (caddr_t)buff; + msgh.msg_controllen = sizeof(buff); + + ret = stream_recvmsg(ibuf, fd, &msgh, 0, (EIGRP_PACKET_MAX_LEN + 1)); + if (ret < 0) { + zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno)); + return NULL; + } + if ((unsigned int)ret < sizeof(iph)) /* ret must be > 0 now */ + { + zlog_warn( + "eigrp_recv_packet: discarding runt packet of length %d " + "(ip header size is %u)", + ret, (u_int)sizeof(iph)); + return NULL; + } + + /* Note that there should not be alignment problems with this assignment + because this is at the beginning of the stream data buffer. */ + iph = (struct ip *)STREAM_DATA(ibuf); + sockopt_iphdrincl_swab_systoh(iph); + + ip_len = iph->ip_len; + +#if !defined(GNU_LINUX) && (OpenBSD < 200311) && (__FreeBSD_version < 1000000) + /* + * Kernel network code touches incoming IP header parameters, + * before protocol specific processing. + * + * 1) Convert byteorder to host representation. + * --> ip_len, ip_id, ip_off + * + * 2) Adjust ip_len to strip IP header size! + * --> If user process receives entire IP packet via RAW + * socket, it must consider adding IP header size to + * the "ip_len" field of "ip" structure. + * + * For more details, see . + */ + ip_len = ip_len + (iph->ip_hl << 2); #endif -#if defined (__DragonFly__) - /* - * in DragonFly's raw socket, ip_len/ip_off are read - * in network byte order. - * As OpenBSD < 200311 adjust ip_len to strip IP header size! - */ - ip_len = ntohs(iph->ip_len) + (iph->ip_hl << 2); +#if defined(__DragonFly__) + /* + * in DragonFly's raw socket, ip_len/ip_off are read + * in network byte order. + * As OpenBSD < 200311 adjust ip_len to strip IP header size! + */ + ip_len = ntohs(iph->ip_len) + (iph->ip_hl << 2); #endif - ifindex = getsockopt_ifindex(AF_INET, &msgh); + ifindex = getsockopt_ifindex(AF_INET, &msgh); - *ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); + *ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); - if (ret != ip_len) - { - zlog_warn("eigrp_recv_packet read length mismatch: ip_len is %d, " - "but recvmsg returned %d", ip_len, ret); - return NULL; - } + if (ret != ip_len) { + zlog_warn( + "eigrp_recv_packet read length mismatch: ip_len is %d, " + "but recvmsg returned %d", + ip_len, ret); + return NULL; + } - return ibuf; + return ibuf; } -struct eigrp_fifo * -eigrp_fifo_new (void) +struct eigrp_fifo *eigrp_fifo_new(void) { - struct eigrp_fifo *new; + struct eigrp_fifo *new; - new = XCALLOC(MTYPE_EIGRP_FIFO, sizeof(struct eigrp_fifo)); - return new; + new = XCALLOC(MTYPE_EIGRP_FIFO, sizeof(struct eigrp_fifo)); + return new; } /* Free eigrp packet fifo. */ -void -eigrp_fifo_free (struct eigrp_fifo *fifo) +void eigrp_fifo_free(struct eigrp_fifo *fifo) { - struct eigrp_packet *ep; - struct eigrp_packet *next; - - for (ep = fifo->head; ep; ep = next) - { - next = ep->next; - eigrp_packet_free(ep); - } - fifo->head = fifo->tail = NULL; - fifo->count = 0; - - XFREE(MTYPE_EIGRP_FIFO, fifo); + struct eigrp_packet *ep; + struct eigrp_packet *next; + + for (ep = fifo->head; ep; ep = next) { + next = ep->next; + eigrp_packet_free(ep); + } + fifo->head = fifo->tail = NULL; + fifo->count = 0; + + XFREE(MTYPE_EIGRP_FIFO, fifo); } /* Free eigrp fifo entries without destroying fifo itself*/ -void -eigrp_fifo_reset (struct eigrp_fifo *fifo) +void eigrp_fifo_reset(struct eigrp_fifo *fifo) { - struct eigrp_packet *ep; - struct eigrp_packet *next; - - for (ep = fifo->head; ep; ep = next) - { - next = ep->next; - eigrp_packet_free(ep); - } - fifo->head = fifo->tail = NULL; - fifo->count = 0; + struct eigrp_packet *ep; + struct eigrp_packet *next; + + for (ep = fifo->head; ep; ep = next) { + next = ep->next; + eigrp_packet_free(ep); + } + fifo->head = fifo->tail = NULL; + fifo->count = 0; } -struct eigrp_packet * -eigrp_packet_new (size_t size) +struct eigrp_packet *eigrp_packet_new(size_t size) { - struct eigrp_packet *new; + struct eigrp_packet *new; - new = XCALLOC(MTYPE_EIGRP_PACKET, sizeof(struct eigrp_packet)); - new->s = stream_new(size); - new->retrans_counter = 0; + new = XCALLOC(MTYPE_EIGRP_PACKET, sizeof(struct eigrp_packet)); + new->s = stream_new(size); + new->retrans_counter = 0; - return new; + return new; } -void -eigrp_send_packet_reliably (struct eigrp_neighbor *nbr) +void eigrp_send_packet_reliably(struct eigrp_neighbor *nbr) { - struct eigrp_packet *ep; - - ep = eigrp_fifo_tail(nbr->retrans_queue); - - if (ep) - { - struct eigrp_packet *duplicate; - duplicate = eigrp_packet_duplicate(ep, nbr); - /* Add packet to the top of the interface output queue*/ - eigrp_fifo_push_head(nbr->ei->obuf, duplicate); - - /*Start retransmission timer*/ - thread_add_timer(master, eigrp_unack_packet_retrans, nbr, - EIGRP_PACKET_RETRANS_TIME, &ep->t_retrans_timer); - - /*Increment sequence number counter*/ - nbr->ei->eigrp->sequence_number++; - - /* Hook thread to write packet. */ - if (nbr->ei->on_write_q == 0) - { - listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei); - nbr->ei->on_write_q = 1; - } - thread_add_write(master, eigrp_write, nbr->ei->eigrp, nbr->ei->eigrp->fd, - &nbr->ei->eigrp->t_write); - } + struct eigrp_packet *ep; + + ep = eigrp_fifo_tail(nbr->retrans_queue); + + if (ep) { + struct eigrp_packet *duplicate; + duplicate = eigrp_packet_duplicate(ep, nbr); + /* Add packet to the top of the interface output queue*/ + eigrp_fifo_push_head(nbr->ei->obuf, duplicate); + + /*Start retransmission timer*/ + thread_add_timer(master, eigrp_unack_packet_retrans, nbr, + EIGRP_PACKET_RETRANS_TIME, + &ep->t_retrans_timer); + + /*Increment sequence number counter*/ + nbr->ei->eigrp->sequence_number++; + + /* Hook thread to write packet. */ + if (nbr->ei->on_write_q == 0) { + listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei); + nbr->ei->on_write_q = 1; + } + thread_add_write(master, eigrp_write, nbr->ei->eigrp, + nbr->ei->eigrp->fd, &nbr->ei->eigrp->t_write); + } } /* Calculate EIGRP checksum */ -void -eigrp_packet_checksum (struct eigrp_interface *ei, struct stream *s, - u_int16_t length) +void eigrp_packet_checksum(struct eigrp_interface *ei, struct stream *s, + u_int16_t length) { - struct eigrp_header *eigrph; + struct eigrp_header *eigrph; - eigrph = (struct eigrp_header *) STREAM_DATA(s); + eigrph = (struct eigrp_header *)STREAM_DATA(s); - /* Calculate checksum. */ - eigrph->checksum = in_cksum(eigrph, length); + /* Calculate checksum. */ + eigrph->checksum = in_cksum(eigrph, length); } /* Make EIGRP header. */ -void -eigrp_packet_header_init (int type, struct eigrp_interface *ei, struct stream *s, - u_int32_t flags, u_int32_t sequence, u_int32_t ack) +void eigrp_packet_header_init(int type, struct eigrp_interface *ei, + struct stream *s, u_int32_t flags, + u_int32_t sequence, u_int32_t ack) { - struct eigrp_header *eigrph; + struct eigrp_header *eigrph; - eigrph = (struct eigrp_header *) STREAM_DATA(s); + eigrph = (struct eigrp_header *)STREAM_DATA(s); - eigrph->version = (u_char) EIGRP_HEADER_VERSION; - eigrph->opcode = (u_char) type; - eigrph->checksum = 0; + eigrph->version = (u_char)EIGRP_HEADER_VERSION; + eigrph->opcode = (u_char)type; + eigrph->checksum = 0; - eigrph->vrid = htons(ei->eigrp->vrid); - eigrph->ASNumber = htons(ei->eigrp->AS); - eigrph->ack = htonl(ack); - eigrph->sequence = htonl(sequence); - // if(flags == EIGRP_INIT_FLAG) - // eigrph->sequence = htonl(3); - eigrph->flags = htonl(flags); + eigrph->vrid = htons(ei->eigrp->vrid); + eigrph->ASNumber = htons(ei->eigrp->AS); + eigrph->ack = htonl(ack); + eigrph->sequence = htonl(sequence); + // if(flags == EIGRP_INIT_FLAG) + // eigrph->sequence = htonl(3); + eigrph->flags = htonl(flags); - if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) - zlog_debug("Packet Header Init Seq [%u] Ack [%u]", - htonl(eigrph->sequence), htonl(eigrph->ack)); + if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) + zlog_debug("Packet Header Init Seq [%u] Ack [%u]", + htonl(eigrph->sequence), htonl(eigrph->ack)); - stream_forward_endp(s, EIGRP_HEADER_LEN); + stream_forward_endp(s, EIGRP_HEADER_LEN); } /* Add new packet to head of fifo. */ -void -eigrp_fifo_push_head (struct eigrp_fifo *fifo, struct eigrp_packet *ep) +void eigrp_fifo_push_head(struct eigrp_fifo *fifo, struct eigrp_packet *ep) { - ep->next = fifo->head; - ep->previous = NULL; + ep->next = fifo->head; + ep->previous = NULL; - if (fifo->tail == NULL) - fifo->tail = ep; + if (fifo->tail == NULL) + fifo->tail = ep; - if (fifo->count != 0) - fifo->head->previous = ep; + if (fifo->count != 0) + fifo->head->previous = ep; - fifo->head = ep; + fifo->head = ep; - fifo->count++; + fifo->count++; } /* Return first fifo entry. */ -struct eigrp_packet * -eigrp_fifo_head (struct eigrp_fifo *fifo) +struct eigrp_packet *eigrp_fifo_head(struct eigrp_fifo *fifo) { - return fifo->head; + return fifo->head; } /* Return last fifo entry. */ -struct eigrp_packet * -eigrp_fifo_tail (struct eigrp_fifo *fifo) +struct eigrp_packet *eigrp_fifo_tail(struct eigrp_fifo *fifo) { - return fifo->tail; + return fifo->tail; } -void -eigrp_packet_delete (struct eigrp_interface *ei) +void eigrp_packet_delete(struct eigrp_interface *ei) { - struct eigrp_packet *ep; + struct eigrp_packet *ep; - ep = eigrp_fifo_pop (ei->obuf); + ep = eigrp_fifo_pop(ei->obuf); - if (ep) - eigrp_packet_free(ep); + if (ep) + eigrp_packet_free(ep); } /* Delete first packet from fifo. */ -struct eigrp_packet * -eigrp_fifo_pop (struct eigrp_fifo *fifo) +struct eigrp_packet *eigrp_fifo_pop(struct eigrp_fifo *fifo) { - struct eigrp_packet *ep; + struct eigrp_packet *ep; - ep = fifo->head; + ep = fifo->head; - if (ep) - { - fifo->head = ep->next; + if (ep) { + fifo->head = ep->next; - if (fifo->head == NULL) - fifo->tail = NULL; - else - fifo->head->previous = NULL; + if (fifo->head == NULL) + fifo->tail = NULL; + else + fifo->head->previous = NULL; - fifo->count--; - } + fifo->count--; + } - return ep; + return ep; } -void -eigrp_packet_free (struct eigrp_packet *ep) +void eigrp_packet_free(struct eigrp_packet *ep) { - if (ep->s) - stream_free(ep->s); + if (ep->s) + stream_free(ep->s); - THREAD_OFF(ep->t_retrans_timer); + THREAD_OFF(ep->t_retrans_timer); - XFREE(MTYPE_EIGRP_PACKET, ep); + XFREE(MTYPE_EIGRP_PACKET, ep); - ep = NULL; + ep = NULL; } /* EIGRP Header verification. */ -static int -eigrp_verify_header (struct stream *ibuf, struct eigrp_interface *ei, - struct ip *iph, struct eigrp_header *eigrph) +static int eigrp_verify_header(struct stream *ibuf, struct eigrp_interface *ei, + struct ip *iph, struct eigrp_header *eigrph) { - /* Check network mask, Silently discarded. */ - if (!eigrp_check_network_mask(ei, iph->ip_src)) - { - zlog_warn("interface %s: eigrp_read network address is not same [%s]", - IF_NAME(ei), inet_ntoa(iph->ip_src)); - return -1; - } - // - // /* Check authentication. The function handles logging actions, where required. */ - // if (! eigrp_check_auth(ei, eigrph)) - // return -1; - - return 0; + /* Check network mask, Silently discarded. */ + if (!eigrp_check_network_mask(ei, iph->ip_src)) { + zlog_warn( + "interface %s: eigrp_read network address is not same [%s]", + IF_NAME(ei), inet_ntoa(iph->ip_src)); + return -1; + } + // + // /* Check authentication. The function handles logging actions, where + // required. */ + // if (! eigrp_check_auth(ei, eigrph)) + // return -1; + + return 0; } /* Unbound socket will accept any Raw IP packets if proto is matched. To prevent it, compare src IP address and i/f address with masking i/f network mask. */ -static int -eigrp_check_network_mask (struct eigrp_interface *ei, struct in_addr ip_src) +static int eigrp_check_network_mask(struct eigrp_interface *ei, + struct in_addr ip_src) { - struct in_addr mask, me, him; + struct in_addr mask, me, him; - if (ei->type == EIGRP_IFTYPE_POINTOPOINT) - return 1; + if (ei->type == EIGRP_IFTYPE_POINTOPOINT) + return 1; - masklen2ip(ei->address->prefixlen, &mask); + masklen2ip(ei->address->prefixlen, &mask); - me.s_addr = ei->address->u.prefix4.s_addr & mask.s_addr; - him.s_addr = ip_src.s_addr & mask.s_addr; + me.s_addr = ei->address->u.prefix4.s_addr & mask.s_addr; + him.s_addr = ip_src.s_addr & mask.s_addr; - if (IPV4_ADDR_SAME(&me, &him)) - return 1; + if (IPV4_ADDR_SAME(&me, &him)) + return 1; - return 0; + return 0; } -int -eigrp_unack_packet_retrans (struct thread *thread) +int eigrp_unack_packet_retrans(struct thread *thread) { - struct eigrp_neighbor *nbr; - nbr = (struct eigrp_neighbor *) THREAD_ARG(thread); - - struct eigrp_packet *ep; - ep = eigrp_fifo_tail(nbr->retrans_queue); - - if (ep) - { - struct eigrp_packet *duplicate; - duplicate = eigrp_packet_duplicate(ep, nbr); - - /* Add packet to the top of the interface output queue*/ - eigrp_fifo_push_head(nbr->ei->obuf, duplicate); - - ep->retrans_counter++; - if(ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX) - return eigrp_retrans_count_exceeded(ep, nbr); - - /*Start retransmission timer*/ - ep->t_retrans_timer = NULL; - thread_add_timer(master, eigrp_unack_packet_retrans, nbr, EIGRP_PACKET_RETRANS_TIME, - &ep->t_retrans_timer); - - /* Hook thread to write packet. */ - if (nbr->ei->on_write_q == 0) - { - listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei); - nbr->ei->on_write_q = 1; - } - thread_add_write(master, eigrp_write, nbr->ei->eigrp, nbr->ei->eigrp->fd, - &nbr->ei->eigrp->t_write); - } - - return 0; + struct eigrp_neighbor *nbr; + nbr = (struct eigrp_neighbor *)THREAD_ARG(thread); + + struct eigrp_packet *ep; + ep = eigrp_fifo_tail(nbr->retrans_queue); + + if (ep) { + struct eigrp_packet *duplicate; + duplicate = eigrp_packet_duplicate(ep, nbr); + + /* Add packet to the top of the interface output queue*/ + eigrp_fifo_push_head(nbr->ei->obuf, duplicate); + + ep->retrans_counter++; + if (ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX) + return eigrp_retrans_count_exceeded(ep, nbr); + + /*Start retransmission timer*/ + ep->t_retrans_timer = NULL; + thread_add_timer(master, eigrp_unack_packet_retrans, nbr, + EIGRP_PACKET_RETRANS_TIME, + &ep->t_retrans_timer); + + /* Hook thread to write packet. */ + if (nbr->ei->on_write_q == 0) { + listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei); + nbr->ei->on_write_q = 1; + } + thread_add_write(master, eigrp_write, nbr->ei->eigrp, + nbr->ei->eigrp->fd, &nbr->ei->eigrp->t_write); + } + + return 0; } -int -eigrp_unack_multicast_packet_retrans (struct thread *thread) +int eigrp_unack_multicast_packet_retrans(struct thread *thread) { - struct eigrp_neighbor *nbr; - nbr = (struct eigrp_neighbor *) THREAD_ARG(thread); - - struct eigrp_packet *ep; - ep = eigrp_fifo_tail(nbr->multicast_queue); - - if (ep) - { - struct eigrp_packet *duplicate; - duplicate = eigrp_packet_duplicate(ep, nbr); - /* Add packet to the top of the interface output queue*/ - eigrp_fifo_push_head(nbr->ei->obuf, duplicate); - - ep->retrans_counter++; - if(ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX) - return eigrp_retrans_count_exceeded(ep, nbr); - - /*Start retransmission timer*/ - ep->t_retrans_timer = NULL; - thread_add_timer(master, eigrp_unack_multicast_packet_retrans, nbr, EIGRP_PACKET_RETRANS_TIME, - &ep->t_retrans_timer); - - /* Hook thread to write packet. */ - if (nbr->ei->on_write_q == 0) - { - listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei); - nbr->ei->on_write_q = 1; - } - thread_add_write(master, eigrp_write, nbr->ei->eigrp, nbr->ei->eigrp->fd, - &nbr->ei->eigrp->t_write); - } - - return 0; + struct eigrp_neighbor *nbr; + nbr = (struct eigrp_neighbor *)THREAD_ARG(thread); + + struct eigrp_packet *ep; + ep = eigrp_fifo_tail(nbr->multicast_queue); + + if (ep) { + struct eigrp_packet *duplicate; + duplicate = eigrp_packet_duplicate(ep, nbr); + /* Add packet to the top of the interface output queue*/ + eigrp_fifo_push_head(nbr->ei->obuf, duplicate); + + ep->retrans_counter++; + if (ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX) + return eigrp_retrans_count_exceeded(ep, nbr); + + /*Start retransmission timer*/ + ep->t_retrans_timer = NULL; + thread_add_timer(master, eigrp_unack_multicast_packet_retrans, + nbr, EIGRP_PACKET_RETRANS_TIME, + &ep->t_retrans_timer); + + /* Hook thread to write packet. */ + if (nbr->ei->on_write_q == 0) { + listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei); + nbr->ei->on_write_q = 1; + } + thread_add_write(master, eigrp_write, nbr->ei->eigrp, + nbr->ei->eigrp->fd, &nbr->ei->eigrp->t_write); + } + + return 0; } /* Get packet from tail of fifo. */ -struct eigrp_packet * -eigrp_fifo_pop_tail (struct eigrp_fifo *fifo) +struct eigrp_packet *eigrp_fifo_pop_tail(struct eigrp_fifo *fifo) { - struct eigrp_packet *ep; + struct eigrp_packet *ep; - ep = fifo->tail; + ep = fifo->tail; - if (ep) - { - fifo->tail = ep->previous; + if (ep) { + fifo->tail = ep->previous; - if (fifo->tail == NULL) - fifo->head = NULL; - else - fifo->tail->next = NULL; + if (fifo->tail == NULL) + fifo->head = NULL; + else + fifo->tail->next = NULL; - fifo->count--; - } + fifo->count--; + } - return ep; + return ep; } -struct eigrp_packet * -eigrp_packet_duplicate (struct eigrp_packet *old, struct eigrp_neighbor *nbr) +struct eigrp_packet *eigrp_packet_duplicate(struct eigrp_packet *old, + struct eigrp_neighbor *nbr) { - struct eigrp_packet *new; + struct eigrp_packet *new; - new = eigrp_packet_new(nbr->ei->ifp->mtu); - new->length = old->length; - new->retrans_counter = old->retrans_counter; - new->dst = old->dst; - new->sequence_number = old->sequence_number; - stream_copy(new->s, old->s); + new = eigrp_packet_new(nbr->ei->ifp->mtu); + new->length = old->length; + new->retrans_counter = old->retrans_counter; + new->dst = old->dst; + new->sequence_number = old->sequence_number; + stream_copy(new->s, old->s); - return new; + return new; } -struct TLV_IPv4_Internal_type * -eigrp_read_ipv4_tlv (struct stream *s) +struct TLV_IPv4_Internal_type *eigrp_read_ipv4_tlv(struct stream *s) { - struct TLV_IPv4_Internal_type *tlv; - - tlv = eigrp_IPv4_InternalTLV_new (); - - tlv->type = stream_getw(s); - tlv->length = stream_getw(s); - tlv->forward.s_addr = stream_getl(s); - tlv->metric.delay = stream_getl(s); - tlv->metric.bandwith = stream_getl(s); - tlv->metric.mtu[0] = stream_getc(s); - tlv->metric.mtu[1] = stream_getc(s); - tlv->metric.mtu[2] = stream_getc(s); - tlv->metric.hop_count = stream_getc(s); - tlv->metric.reliability = stream_getc(s); - tlv->metric.load = stream_getc(s); - tlv->metric.tag = stream_getc(s); - tlv->metric.flags = stream_getc(s); - - tlv->prefix_length = stream_getc(s); - - if (tlv->prefix_length <= 8) - { - tlv->destination_part[0] = stream_getc(s); - tlv->destination.s_addr = (tlv->destination_part[0]); - } - else if (tlv->prefix_length > 8 && tlv->prefix_length <= 16) - { - tlv->destination_part[0] = stream_getc(s); - tlv->destination_part[1] = stream_getc(s); - tlv->destination.s_addr = ((tlv->destination_part[1] << 8) - + tlv->destination_part[0]); - } - else if (tlv->prefix_length > 16 && tlv->prefix_length <= 24) - { - tlv->destination_part[0] = stream_getc(s); - tlv->destination_part[1] = stream_getc(s); - tlv->destination_part[2] = stream_getc(s); - tlv->destination.s_addr = ((tlv->destination_part[2] << 16) + - (tlv->destination_part[1] << 8) + - tlv->destination_part[0]); - } - else if (tlv->prefix_length > 24 && tlv->prefix_length <= 32) - { - tlv->destination_part[0] = stream_getc(s); - tlv->destination_part[1] = stream_getc(s); - tlv->destination_part[2] = stream_getc(s); - tlv->destination_part[3] = stream_getc(s); - tlv->destination.s_addr = ((tlv->destination_part[3] << 24) + - (tlv->destination_part[2] << 16) + - (tlv->destination_part[1] << 8) + - tlv->destination_part[0]); - } - return tlv; + struct TLV_IPv4_Internal_type *tlv; + + tlv = eigrp_IPv4_InternalTLV_new(); + + tlv->type = stream_getw(s); + tlv->length = stream_getw(s); + tlv->forward.s_addr = stream_getl(s); + tlv->metric.delay = stream_getl(s); + tlv->metric.bandwith = stream_getl(s); + tlv->metric.mtu[0] = stream_getc(s); + tlv->metric.mtu[1] = stream_getc(s); + tlv->metric.mtu[2] = stream_getc(s); + tlv->metric.hop_count = stream_getc(s); + tlv->metric.reliability = stream_getc(s); + tlv->metric.load = stream_getc(s); + tlv->metric.tag = stream_getc(s); + tlv->metric.flags = stream_getc(s); + + tlv->prefix_length = stream_getc(s); + + if (tlv->prefix_length <= 8) { + tlv->destination_part[0] = stream_getc(s); + tlv->destination.s_addr = (tlv->destination_part[0]); + } else if (tlv->prefix_length > 8 && tlv->prefix_length <= 16) { + tlv->destination_part[0] = stream_getc(s); + tlv->destination_part[1] = stream_getc(s); + tlv->destination.s_addr = ((tlv->destination_part[1] << 8) + + tlv->destination_part[0]); + } else if (tlv->prefix_length > 16 && tlv->prefix_length <= 24) { + tlv->destination_part[0] = stream_getc(s); + tlv->destination_part[1] = stream_getc(s); + tlv->destination_part[2] = stream_getc(s); + tlv->destination.s_addr = ((tlv->destination_part[2] << 16) + + (tlv->destination_part[1] << 8) + + tlv->destination_part[0]); + } else if (tlv->prefix_length > 24 && tlv->prefix_length <= 32) { + tlv->destination_part[0] = stream_getc(s); + tlv->destination_part[1] = stream_getc(s); + tlv->destination_part[2] = stream_getc(s); + tlv->destination_part[3] = stream_getc(s); + tlv->destination.s_addr = ((tlv->destination_part[3] << 24) + + (tlv->destination_part[2] << 16) + + (tlv->destination_part[1] << 8) + + tlv->destination_part[0]); + } + return tlv; } -u_int16_t -eigrp_add_internalTLV_to_stream (struct stream *s, - struct eigrp_prefix_entry *pe) +u_int16_t eigrp_add_internalTLV_to_stream(struct stream *s, + struct eigrp_prefix_entry *pe) { - u_int16_t length; - - stream_putw(s, EIGRP_TLV_IPv4_INT); - if (pe->destination_ipv4->prefixlen <= 8) - { - stream_putw(s, 0x001A); - length = 0x001A; - } - if ((pe->destination_ipv4->prefixlen > 8) - && (pe->destination_ipv4->prefixlen <= 16)) - { - stream_putw(s, 0x001B); - length = 0x001B; - } - if ((pe->destination_ipv4->prefixlen > 16) - && (pe->destination_ipv4->prefixlen <= 24)) - { - stream_putw(s, 0x001C); - length = 0x001C; - } - if (pe->destination_ipv4->prefixlen > 24) - { - stream_putw(s, 0x001D); - length = 0x001D; - } - - stream_putl(s, 0x00000000); - - /*Metric*/ - stream_putl(s, pe->reported_metric.delay); - stream_putl(s, pe->reported_metric.bandwith); - stream_putc(s, pe->reported_metric.mtu[2]); - stream_putc(s, pe->reported_metric.mtu[1]); - stream_putc(s, pe->reported_metric.mtu[0]); - stream_putc(s, pe->reported_metric.hop_count); - stream_putc(s, pe->reported_metric.reliability); - stream_putc(s, pe->reported_metric.load); - stream_putc(s, pe->reported_metric.tag); - stream_putc(s, pe->reported_metric.flags); - - stream_putc(s, pe->destination_ipv4->prefixlen); - - if (pe->destination_ipv4->prefixlen <= 8) - { - stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF); - } - if ((pe->destination_ipv4->prefixlen > 8) - && (pe->destination_ipv4->prefixlen <= 16)) - { - stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF); - stream_putc(s, (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF); - } - if ((pe->destination_ipv4->prefixlen > 16) - && (pe->destination_ipv4->prefixlen <= 24)) - { - stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF); - stream_putc(s, (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF); - stream_putc(s, (pe->destination_ipv4->prefix.s_addr >> 16) & 0xFF); - } - if (pe->destination_ipv4->prefixlen > 24) - { - stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF); - stream_putc(s, (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF); - stream_putc(s, (pe->destination_ipv4->prefix.s_addr >> 16) & 0xFF); - stream_putc(s, (pe->destination_ipv4->prefix.s_addr >> 24) & 0xFF); - } - - return length; + u_int16_t length; + + stream_putw(s, EIGRP_TLV_IPv4_INT); + if (pe->destination_ipv4->prefixlen <= 8) { + stream_putw(s, 0x001A); + length = 0x001A; + } + if ((pe->destination_ipv4->prefixlen > 8) + && (pe->destination_ipv4->prefixlen <= 16)) { + stream_putw(s, 0x001B); + length = 0x001B; + } + if ((pe->destination_ipv4->prefixlen > 16) + && (pe->destination_ipv4->prefixlen <= 24)) { + stream_putw(s, 0x001C); + length = 0x001C; + } + if (pe->destination_ipv4->prefixlen > 24) { + stream_putw(s, 0x001D); + length = 0x001D; + } + + stream_putl(s, 0x00000000); + + /*Metric*/ + stream_putl(s, pe->reported_metric.delay); + stream_putl(s, pe->reported_metric.bandwith); + stream_putc(s, pe->reported_metric.mtu[2]); + stream_putc(s, pe->reported_metric.mtu[1]); + stream_putc(s, pe->reported_metric.mtu[0]); + stream_putc(s, pe->reported_metric.hop_count); + stream_putc(s, pe->reported_metric.reliability); + stream_putc(s, pe->reported_metric.load); + stream_putc(s, pe->reported_metric.tag); + stream_putc(s, pe->reported_metric.flags); + + stream_putc(s, pe->destination_ipv4->prefixlen); + + if (pe->destination_ipv4->prefixlen <= 8) { + stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF); + } + if ((pe->destination_ipv4->prefixlen > 8) + && (pe->destination_ipv4->prefixlen <= 16)) { + stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF); + stream_putc(s, + (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF); + } + if ((pe->destination_ipv4->prefixlen > 16) + && (pe->destination_ipv4->prefixlen <= 24)) { + stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF); + stream_putc(s, + (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF); + stream_putc(s, + (pe->destination_ipv4->prefix.s_addr >> 16) & 0xFF); + } + if (pe->destination_ipv4->prefixlen > 24) { + stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF); + stream_putc(s, + (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF); + stream_putc(s, + (pe->destination_ipv4->prefix.s_addr >> 16) & 0xFF); + stream_putc(s, + (pe->destination_ipv4->prefix.s_addr >> 24) & 0xFF); + } + + return length; } -u_int16_t -eigrp_add_authTLV_MD5_to_stream (struct stream *s, - struct eigrp_interface *ei) +u_int16_t eigrp_add_authTLV_MD5_to_stream(struct stream *s, + struct eigrp_interface *ei) { - struct key *key; - struct keychain *keychain; - struct TLV_MD5_Authentication_Type *authTLV; - - authTLV = eigrp_authTLV_MD5_new(); - - authTLV->type = htons(EIGRP_TLV_AUTH); - authTLV->length = htons(EIGRP_AUTH_MD5_TLV_SIZE); - authTLV->auth_type = htons(EIGRP_AUTH_TYPE_MD5); - authTLV->auth_length = htons(EIGRP_AUTH_TYPE_MD5_LEN); - authTLV->key_sequence = 0; - memset(authTLV->Nullpad,0,sizeof(authTLV->Nullpad)); - - keychain = keychain_lookup(IF_DEF_PARAMS (ei->ifp)->auth_keychain); - if(keychain) - key = key_lookup_for_send(keychain); - else - { - free(IF_DEF_PARAMS (ei->ifp)->auth_keychain); - IF_DEF_PARAMS (ei->ifp)->auth_keychain = NULL; - eigrp_authTLV_MD5_free(authTLV); - return 0; - } - - if(key) - { - authTLV->key_id = htonl(key->index); - memset(authTLV->digest,0,EIGRP_AUTH_TYPE_MD5_LEN); - stream_put(s,authTLV, sizeof(struct TLV_MD5_Authentication_Type)); - eigrp_authTLV_MD5_free(authTLV); - return EIGRP_AUTH_MD5_TLV_SIZE; - } - - eigrp_authTLV_MD5_free(authTLV); - - return 0; + struct key *key; + struct keychain *keychain; + struct TLV_MD5_Authentication_Type *authTLV; + + authTLV = eigrp_authTLV_MD5_new(); + + authTLV->type = htons(EIGRP_TLV_AUTH); + authTLV->length = htons(EIGRP_AUTH_MD5_TLV_SIZE); + authTLV->auth_type = htons(EIGRP_AUTH_TYPE_MD5); + authTLV->auth_length = htons(EIGRP_AUTH_TYPE_MD5_LEN); + authTLV->key_sequence = 0; + memset(authTLV->Nullpad, 0, sizeof(authTLV->Nullpad)); + + keychain = keychain_lookup(IF_DEF_PARAMS(ei->ifp)->auth_keychain); + if (keychain) + key = key_lookup_for_send(keychain); + else { + free(IF_DEF_PARAMS(ei->ifp)->auth_keychain); + IF_DEF_PARAMS(ei->ifp)->auth_keychain = NULL; + eigrp_authTLV_MD5_free(authTLV); + return 0; + } + + if (key) { + authTLV->key_id = htonl(key->index); + memset(authTLV->digest, 0, EIGRP_AUTH_TYPE_MD5_LEN); + stream_put(s, authTLV, + sizeof(struct TLV_MD5_Authentication_Type)); + eigrp_authTLV_MD5_free(authTLV); + return EIGRP_AUTH_MD5_TLV_SIZE; + } + + eigrp_authTLV_MD5_free(authTLV); + + return 0; } -u_int16_t -eigrp_add_authTLV_SHA256_to_stream (struct stream *s, - struct eigrp_interface *ei) +u_int16_t eigrp_add_authTLV_SHA256_to_stream(struct stream *s, + struct eigrp_interface *ei) { - struct key *key; - struct keychain *keychain; - struct TLV_SHA256_Authentication_Type *authTLV; - - authTLV = eigrp_authTLV_SHA256_new(); - - authTLV->type = htons(EIGRP_TLV_AUTH); - authTLV->length = htons(EIGRP_AUTH_SHA256_TLV_SIZE); - authTLV->auth_type = htons(EIGRP_AUTH_TYPE_SHA256); - authTLV->auth_length = htons(EIGRP_AUTH_TYPE_SHA256_LEN); - authTLV->key_sequence = 0; - memset(authTLV->Nullpad,0,sizeof(authTLV->Nullpad)); - - keychain = keychain_lookup(IF_DEF_PARAMS (ei->ifp)->auth_keychain); - if(keychain) - key = key_lookup_for_send(keychain); - else - { - free(IF_DEF_PARAMS (ei->ifp)->auth_keychain); - IF_DEF_PARAMS (ei->ifp)->auth_keychain = NULL; - eigrp_authTLV_SHA256_free(authTLV); - return 0; - } - - if(key) - { - authTLV->key_id = 0; - memset(authTLV->digest,0,EIGRP_AUTH_TYPE_SHA256_LEN); - stream_put(s,authTLV, sizeof(struct TLV_SHA256_Authentication_Type)); - eigrp_authTLV_SHA256_free(authTLV); - return EIGRP_AUTH_SHA256_TLV_SIZE; - } - - eigrp_authTLV_SHA256_free(authTLV); - - return 0; + struct key *key; + struct keychain *keychain; + struct TLV_SHA256_Authentication_Type *authTLV; + + authTLV = eigrp_authTLV_SHA256_new(); + + authTLV->type = htons(EIGRP_TLV_AUTH); + authTLV->length = htons(EIGRP_AUTH_SHA256_TLV_SIZE); + authTLV->auth_type = htons(EIGRP_AUTH_TYPE_SHA256); + authTLV->auth_length = htons(EIGRP_AUTH_TYPE_SHA256_LEN); + authTLV->key_sequence = 0; + memset(authTLV->Nullpad, 0, sizeof(authTLV->Nullpad)); + + keychain = keychain_lookup(IF_DEF_PARAMS(ei->ifp)->auth_keychain); + if (keychain) + key = key_lookup_for_send(keychain); + else { + free(IF_DEF_PARAMS(ei->ifp)->auth_keychain); + IF_DEF_PARAMS(ei->ifp)->auth_keychain = NULL; + eigrp_authTLV_SHA256_free(authTLV); + return 0; + } + + if (key) { + authTLV->key_id = 0; + memset(authTLV->digest, 0, EIGRP_AUTH_TYPE_SHA256_LEN); + stream_put(s, authTLV, + sizeof(struct TLV_SHA256_Authentication_Type)); + eigrp_authTLV_SHA256_free(authTLV); + return EIGRP_AUTH_SHA256_TLV_SIZE; + } + + eigrp_authTLV_SHA256_free(authTLV); + + return 0; } -struct TLV_MD5_Authentication_Type * -eigrp_authTLV_MD5_new () +struct TLV_MD5_Authentication_Type *eigrp_authTLV_MD5_new() { - struct TLV_MD5_Authentication_Type *new; + struct TLV_MD5_Authentication_Type *new; - new = XCALLOC(MTYPE_EIGRP_AUTH_TLV, sizeof(struct TLV_MD5_Authentication_Type)); + new = XCALLOC(MTYPE_EIGRP_AUTH_TLV, + sizeof(struct TLV_MD5_Authentication_Type)); - return new; + return new; } -void -eigrp_authTLV_MD5_free (struct TLV_MD5_Authentication_Type *authTLV) +void eigrp_authTLV_MD5_free(struct TLV_MD5_Authentication_Type *authTLV) { - XFREE(MTYPE_EIGRP_AUTH_TLV, authTLV); + XFREE(MTYPE_EIGRP_AUTH_TLV, authTLV); } -struct TLV_SHA256_Authentication_Type * -eigrp_authTLV_SHA256_new () +struct TLV_SHA256_Authentication_Type *eigrp_authTLV_SHA256_new() { - struct TLV_SHA256_Authentication_Type *new; + struct TLV_SHA256_Authentication_Type *new; - new = XCALLOC(MTYPE_EIGRP_AUTH_SHA256_TLV, sizeof(struct TLV_SHA256_Authentication_Type)); + new = XCALLOC(MTYPE_EIGRP_AUTH_SHA256_TLV, + sizeof(struct TLV_SHA256_Authentication_Type)); - return new; + return new; } -void -eigrp_authTLV_SHA256_free (struct TLV_SHA256_Authentication_Type *authTLV) +void eigrp_authTLV_SHA256_free(struct TLV_SHA256_Authentication_Type *authTLV) { - XFREE(MTYPE_EIGRP_AUTH_SHA256_TLV, authTLV); + XFREE(MTYPE_EIGRP_AUTH_SHA256_TLV, authTLV); } -struct TLV_IPv4_Internal_type * -eigrp_IPv4_InternalTLV_new () +struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new() { - struct TLV_IPv4_Internal_type *new; + struct TLV_IPv4_Internal_type *new; - new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV,sizeof(struct TLV_IPv4_Internal_type)); + new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV, + sizeof(struct TLV_IPv4_Internal_type)); - return new; + return new; } -void -eigrp_IPv4_InternalTLV_free (struct TLV_IPv4_Internal_type *IPv4_InternalTLV) +void eigrp_IPv4_InternalTLV_free( + struct TLV_IPv4_Internal_type *IPv4_InternalTLV) { - XFREE(MTYPE_EIGRP_IPV4_INT_TLV, IPv4_InternalTLV); + XFREE(MTYPE_EIGRP_IPV4_INT_TLV, IPv4_InternalTLV); } -struct TLV_Sequence_Type * -eigrp_SequenceTLV_new () +struct TLV_Sequence_Type *eigrp_SequenceTLV_new() { - struct TLV_Sequence_Type *new; + struct TLV_Sequence_Type *new; - new = XCALLOC(MTYPE_EIGRP_SEQ_TLV,sizeof(struct TLV_Sequence_Type)); + new = XCALLOC(MTYPE_EIGRP_SEQ_TLV, sizeof(struct TLV_Sequence_Type)); - return new; + return new; } diff --git a/eigrpd/eigrp_packet.h b/eigrpd/eigrp_packet.h index 0996eb2ff..2f607e5ca 100644 --- a/eigrpd/eigrp_packet.h +++ b/eigrpd/eigrp_packet.h @@ -33,108 +33,130 @@ #define _ZEBRA_EIGRP_PACKET_H /*Prototypes*/ -extern int eigrp_read (struct thread *); -extern int eigrp_write (struct thread *); - -extern struct eigrp_packet *eigrp_packet_new (size_t); -extern struct eigrp_packet *eigrp_packet_duplicate (struct eigrp_packet *, struct eigrp_neighbor *); -extern void eigrp_packet_free (struct eigrp_packet *); -extern void eigrp_packet_delete (struct eigrp_interface *); -extern void eigrp_packet_header_init (int, struct eigrp_interface *, struct stream *, - u_int32_t, u_int32_t, u_int32_t); -extern void eigrp_packet_checksum (struct eigrp_interface *, struct stream *, u_int16_t); - -extern struct eigrp_fifo *eigrp_fifo_new (void); -extern struct eigrp_packet *eigrp_fifo_head (struct eigrp_fifo *); -extern struct eigrp_packet *eigrp_fifo_tail (struct eigrp_fifo *); -extern struct eigrp_packet *eigrp_fifo_pop (struct eigrp_fifo *); -extern struct eigrp_packet *eigrp_fifo_pop_tail (struct eigrp_fifo *); -extern void eigrp_fifo_push_head (struct eigrp_fifo *, struct eigrp_packet *); -extern void eigrp_fifo_free (struct eigrp_fifo *); -extern void eigrp_fifo_reset (struct eigrp_fifo *); - -extern void eigrp_send_packet_reliably (struct eigrp_neighbor *); - -extern struct TLV_IPv4_Internal_type *eigrp_read_ipv4_tlv (struct stream *); -extern u_int16_t eigrp_add_internalTLV_to_stream (struct stream *, struct eigrp_prefix_entry *); -extern u_int16_t eigrp_add_authTLV_MD5_to_stream (struct stream *, struct eigrp_interface *); -extern u_int16_t eigrp_add_authTLV_SHA256_to_stream (struct stream *, struct eigrp_interface *); - -extern int eigrp_unack_packet_retrans (struct thread *); -extern int eigrp_unack_multicast_packet_retrans (struct thread *); +extern int eigrp_read(struct thread *); +extern int eigrp_write(struct thread *); + +extern struct eigrp_packet *eigrp_packet_new(size_t); +extern struct eigrp_packet *eigrp_packet_duplicate(struct eigrp_packet *, + struct eigrp_neighbor *); +extern void eigrp_packet_free(struct eigrp_packet *); +extern void eigrp_packet_delete(struct eigrp_interface *); +extern void eigrp_packet_header_init(int, struct eigrp_interface *, + struct stream *, u_int32_t, u_int32_t, + u_int32_t); +extern void eigrp_packet_checksum(struct eigrp_interface *, struct stream *, + u_int16_t); + +extern struct eigrp_fifo *eigrp_fifo_new(void); +extern struct eigrp_packet *eigrp_fifo_head(struct eigrp_fifo *); +extern struct eigrp_packet *eigrp_fifo_tail(struct eigrp_fifo *); +extern struct eigrp_packet *eigrp_fifo_pop(struct eigrp_fifo *); +extern struct eigrp_packet *eigrp_fifo_pop_tail(struct eigrp_fifo *); +extern void eigrp_fifo_push_head(struct eigrp_fifo *, struct eigrp_packet *); +extern void eigrp_fifo_free(struct eigrp_fifo *); +extern void eigrp_fifo_reset(struct eigrp_fifo *); + +extern void eigrp_send_packet_reliably(struct eigrp_neighbor *); + +extern struct TLV_IPv4_Internal_type *eigrp_read_ipv4_tlv(struct stream *); +extern u_int16_t eigrp_add_internalTLV_to_stream(struct stream *, + struct eigrp_prefix_entry *); +extern u_int16_t eigrp_add_authTLV_MD5_to_stream(struct stream *, + struct eigrp_interface *); +extern u_int16_t eigrp_add_authTLV_SHA256_to_stream(struct stream *, + struct eigrp_interface *); + +extern int eigrp_unack_packet_retrans(struct thread *); +extern int eigrp_unack_multicast_packet_retrans(struct thread *); /* * untill there is reason to have their own header, these externs are found in * eigrp_hello.c */ -extern void eigrp_hello_send (struct eigrp_interface *, u_char, struct in_addr *); -extern void eigrp_hello_send_ack (struct eigrp_neighbor *); -extern void eigrp_hello_receive (struct eigrp *, struct ip *, struct eigrp_header *, - struct stream *, struct eigrp_interface *, int); -extern int eigrp_hello_timer (struct thread *); +extern void eigrp_hello_send(struct eigrp_interface *, u_char, + struct in_addr *); +extern void eigrp_hello_send_ack(struct eigrp_neighbor *); +extern void eigrp_hello_receive(struct eigrp *, struct ip *, + struct eigrp_header *, struct stream *, + struct eigrp_interface *, int); +extern int eigrp_hello_timer(struct thread *); /* * These externs are found in eigrp_update.c */ -extern void eigrp_update_send (struct eigrp_interface *); -extern void eigrp_update_receive (struct eigrp *, struct ip *, struct eigrp_header *, - struct stream *, struct eigrp_interface *, int); -extern void eigrp_update_send_all (struct eigrp *, struct eigrp_interface *); -extern void eigrp_update_send_init (struct eigrp_neighbor *); -extern void eigrp_update_send_EOT (struct eigrp_neighbor *); +extern void eigrp_update_send(struct eigrp_interface *); +extern void eigrp_update_receive(struct eigrp *, struct ip *, + struct eigrp_header *, struct stream *, + struct eigrp_interface *, int); +extern void eigrp_update_send_all(struct eigrp *, struct eigrp_interface *); +extern void eigrp_update_send_init(struct eigrp_neighbor *); +extern void eigrp_update_send_EOT(struct eigrp_neighbor *); extern int eigrp_update_send_GR_thread(struct thread *); -extern void eigrp_update_send_GR (struct eigrp_neighbor *, enum GR_type, struct vty *); -extern void eigrp_update_send_interface_GR (struct eigrp_interface *, enum GR_type, struct vty *); -extern void eigrp_update_send_process_GR (struct eigrp *, enum GR_type, struct vty *); +extern void eigrp_update_send_GR(struct eigrp_neighbor *, enum GR_type, + struct vty *); +extern void eigrp_update_send_interface_GR(struct eigrp_interface *, + enum GR_type, struct vty *); +extern void eigrp_update_send_process_GR(struct eigrp *, enum GR_type, + struct vty *); /* * These externs are found in eigrp_query.c */ -extern void eigrp_send_query (struct eigrp_interface *); -extern void eigrp_query_receive (struct eigrp *, struct ip *, struct eigrp_header *, - struct stream *, struct eigrp_interface *, int); -extern u_int32_t eigrp_query_send_all (struct eigrp *); +extern void eigrp_send_query(struct eigrp_interface *); +extern void eigrp_query_receive(struct eigrp *, struct ip *, + struct eigrp_header *, struct stream *, + struct eigrp_interface *, int); +extern u_int32_t eigrp_query_send_all(struct eigrp *); /* * These externs are found in eigrp_reply.c */ -extern void eigrp_send_reply (struct eigrp_neighbor *, struct eigrp_prefix_entry *); -extern void eigrp_reply_receive (struct eigrp *, struct ip *, struct eigrp_header *, - struct stream *, struct eigrp_interface *, int); +extern void eigrp_send_reply(struct eigrp_neighbor *, + struct eigrp_prefix_entry *); +extern void eigrp_reply_receive(struct eigrp *, struct ip *, + struct eigrp_header *, struct stream *, + struct eigrp_interface *, int); /* * These externs are found in eigrp_siaquery.c */ -extern void eigrp_send_siaquery (struct eigrp_neighbor *, struct eigrp_prefix_entry *); -extern void eigrp_siaquery_receive (struct eigrp *, struct ip *, struct eigrp_header *, - struct stream *, struct eigrp_interface *, int); +extern void eigrp_send_siaquery(struct eigrp_neighbor *, + struct eigrp_prefix_entry *); +extern void eigrp_siaquery_receive(struct eigrp *, struct ip *, + struct eigrp_header *, struct stream *, + struct eigrp_interface *, int); /* * These externs are found in eigrp_siareply.c */ -extern void eigrp_send_siareply (struct eigrp_neighbor *, struct eigrp_prefix_entry *); -extern void eigrp_siareply_receive (struct eigrp *, struct ip *, struct eigrp_header *, - struct stream *, struct eigrp_interface *, int); - -extern struct TLV_MD5_Authentication_Type *eigrp_authTLV_MD5_new (void); -extern void eigrp_authTLV_MD5_free (struct TLV_MD5_Authentication_Type *); -extern struct TLV_SHA256_Authentication_Type *eigrp_authTLV_SHA256_new (void); -extern void eigrp_authTLV_SHA256_free (struct TLV_SHA256_Authentication_Type *); - -extern int eigrp_make_md5_digest (struct eigrp_interface *, struct stream *, - u_char); -extern int eigrp_check_md5_digest (struct stream *, struct TLV_MD5_Authentication_Type *, - struct eigrp_neighbor *, u_char); -extern int eigrp_make_sha256_digest (struct eigrp_interface *, struct stream *, u_char); -extern int eigrp_check_sha256_digest (struct stream *, struct TLV_SHA256_Authentication_Type *, - struct eigrp_neighbor *, u_char ); - - -extern struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new (void); -extern void eigrp_IPv4_InternalTLV_free (struct TLV_IPv4_Internal_type *); - -extern struct TLV_Sequence_Type *eigrp_SequenceTLV_new (void); +extern void eigrp_send_siareply(struct eigrp_neighbor *, + struct eigrp_prefix_entry *); +extern void eigrp_siareply_receive(struct eigrp *, struct ip *, + struct eigrp_header *, struct stream *, + struct eigrp_interface *, int); + +extern struct TLV_MD5_Authentication_Type *eigrp_authTLV_MD5_new(void); +extern void eigrp_authTLV_MD5_free(struct TLV_MD5_Authentication_Type *); +extern struct TLV_SHA256_Authentication_Type *eigrp_authTLV_SHA256_new(void); +extern void eigrp_authTLV_SHA256_free(struct TLV_SHA256_Authentication_Type *); + +extern int eigrp_make_md5_digest(struct eigrp_interface *, struct stream *, + u_char); +extern int eigrp_check_md5_digest(struct stream *, + struct TLV_MD5_Authentication_Type *, + struct eigrp_neighbor *, u_char); +extern int eigrp_make_sha256_digest(struct eigrp_interface *, struct stream *, + u_char); +extern int eigrp_check_sha256_digest(struct stream *, + struct TLV_SHA256_Authentication_Type *, + struct eigrp_neighbor *, u_char); + + +extern struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new(void); +extern void eigrp_IPv4_InternalTLV_free(struct TLV_IPv4_Internal_type *); + +extern struct TLV_Sequence_Type *eigrp_SequenceTLV_new(void); extern const struct message eigrp_packet_type_str[]; extern const size_t eigrp_packet_type_str_max; diff --git a/eigrpd/eigrp_query.c b/eigrpd/eigrp_query.c index 1d308d2be..653eae258 100644 --- a/eigrpd/eigrp_query.c +++ b/eigrpd/eigrp_query.c @@ -54,180 +54,168 @@ #include "eigrpd/eigrp_fsm.h" #include "eigrpd/eigrp_memory.h" -u_int32_t -eigrp_query_send_all (struct eigrp *eigrp) +u_int32_t eigrp_query_send_all(struct eigrp *eigrp) { - struct eigrp_interface *iface; - struct listnode *node, *node2, *nnode2; - struct eigrp_prefix_entry *pe; - u_int32_t counter; - - if (eigrp == NULL) - { - zlog_debug("EIGRP Routing Process not enabled"); - return 0; - } - - counter=0; - for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, iface)) - { - eigrp_send_query(iface); - counter++; - } - - for (ALL_LIST_ELEMENTS(eigrp->topology_changes_internalIPV4, node2, nnode2, pe)) - { - if(pe->req_action & EIGRP_FSM_NEED_QUERY) - { - pe->req_action &= ~EIGRP_FSM_NEED_QUERY; - listnode_delete(eigrp->topology_changes_internalIPV4, pe); - } - } - - return counter; + struct eigrp_interface *iface; + struct listnode *node, *node2, *nnode2; + struct eigrp_prefix_entry *pe; + u_int32_t counter; + + if (eigrp == NULL) { + zlog_debug("EIGRP Routing Process not enabled"); + return 0; + } + + counter = 0; + for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, iface)) { + eigrp_send_query(iface); + counter++; + } + + for (ALL_LIST_ELEMENTS(eigrp->topology_changes_internalIPV4, node2, + nnode2, pe)) { + if (pe->req_action & EIGRP_FSM_NEED_QUERY) { + pe->req_action &= ~EIGRP_FSM_NEED_QUERY; + listnode_delete(eigrp->topology_changes_internalIPV4, + pe); + } + } + + return counter; } /*EIGRP QUERY read function*/ -void -eigrp_query_receive (struct eigrp *eigrp, struct ip *iph, struct eigrp_header *eigrph, - struct stream * s, struct eigrp_interface *ei, int size) +void eigrp_query_receive(struct eigrp *eigrp, struct ip *iph, + struct eigrp_header *eigrph, struct stream *s, + struct eigrp_interface *ei, int size) { - struct eigrp_neighbor *nbr; - struct TLV_IPv4_Internal_type *tlv; - - u_int16_t type; - - /* increment statistics. */ - ei->query_in++; - - /* get neighbor struct */ - nbr = eigrp_nbr_get(ei, eigrph, iph); - - /* neighbor must be valid, eigrp_nbr_get creates if none existed */ - assert(nbr); - - nbr->recv_sequence_number = ntohl(eigrph->sequence); - - while (s->endp > s->getp) - { - type = stream_getw(s); - if (type == EIGRP_TLV_IPv4_INT) - { - struct prefix_ipv4 dest_addr; - - stream_set_getp(s, s->getp - sizeof(u_int16_t)); - - tlv = eigrp_read_ipv4_tlv(s); - - dest_addr.family = AF_INET; - dest_addr.prefix = tlv->destination; - dest_addr.prefixlen = tlv->prefix_length; - struct eigrp_prefix_entry *dest = - eigrp_topology_table_lookup_ipv4(eigrp->topology_table, &dest_addr); - - /* If the destination exists (it should, but one never know)*/ - if (dest != NULL) - { - struct eigrp_fsm_action_message *msg; - msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct eigrp_fsm_action_message)); - struct eigrp_neighbor_entry *entry = - eigrp_prefix_entry_lookup(dest->entries, nbr); - msg->packet_type = EIGRP_OPC_QUERY; - msg->eigrp = eigrp; - msg->data_type = EIGRP_TLV_IPv4_INT; - msg->adv_router = nbr; - msg->data.ipv4_int_type = tlv; - msg->entry = entry; - msg->prefix = dest; - int event = eigrp_get_fsm_event(msg); - eigrp_fsm_event(msg, event); - } - eigrp_IPv4_InternalTLV_free (tlv); - } - } - eigrp_hello_send_ack(nbr); - eigrp_query_send_all(eigrp); - eigrp_update_send_all(eigrp,nbr->ei); + struct eigrp_neighbor *nbr; + struct TLV_IPv4_Internal_type *tlv; + + u_int16_t type; + + /* increment statistics. */ + ei->query_in++; + + /* get neighbor struct */ + nbr = eigrp_nbr_get(ei, eigrph, iph); + + /* neighbor must be valid, eigrp_nbr_get creates if none existed */ + assert(nbr); + + nbr->recv_sequence_number = ntohl(eigrph->sequence); + + while (s->endp > s->getp) { + type = stream_getw(s); + if (type == EIGRP_TLV_IPv4_INT) { + struct prefix_ipv4 dest_addr; + + stream_set_getp(s, s->getp - sizeof(u_int16_t)); + + tlv = eigrp_read_ipv4_tlv(s); + + dest_addr.family = AF_INET; + dest_addr.prefix = tlv->destination; + dest_addr.prefixlen = tlv->prefix_length; + struct eigrp_prefix_entry *dest = + eigrp_topology_table_lookup_ipv4( + eigrp->topology_table, &dest_addr); + + /* If the destination exists (it should, but one never + * know)*/ + if (dest != NULL) { + struct eigrp_fsm_action_message *msg; + msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, + sizeof(struct + eigrp_fsm_action_message)); + struct eigrp_neighbor_entry *entry = + eigrp_prefix_entry_lookup(dest->entries, + nbr); + msg->packet_type = EIGRP_OPC_QUERY; + msg->eigrp = eigrp; + msg->data_type = EIGRP_TLV_IPv4_INT; + msg->adv_router = nbr; + msg->data.ipv4_int_type = tlv; + msg->entry = entry; + msg->prefix = dest; + int event = eigrp_get_fsm_event(msg); + eigrp_fsm_event(msg, event); + } + eigrp_IPv4_InternalTLV_free(tlv); + } + } + eigrp_hello_send_ack(nbr); + eigrp_query_send_all(eigrp); + eigrp_update_send_all(eigrp, nbr->ei); } -void -eigrp_send_query (struct eigrp_interface *ei) +void eigrp_send_query(struct eigrp_interface *ei) { - struct eigrp_packet *ep; - u_int16_t length = EIGRP_HEADER_LEN; - struct listnode *node, *nnode, *node2, *nnode2; - struct eigrp_neighbor *nbr; - struct eigrp_prefix_entry *pe; - char has_tlv; - bool ep_saved = false; - - ep = eigrp_packet_new(ei->ifp->mtu); - - /* Prepare EIGRP INIT UPDATE header */ - eigrp_packet_header_init(EIGRP_OPC_QUERY, ei, ep->s, 0, - ei->eigrp->sequence_number, 0); - - // encode Authentication TLV, if needed - if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && - (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL)) - { - length += eigrp_add_authTLV_MD5_to_stream(ep->s,ei); - } - - has_tlv = 0; - for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node, nnode, pe)) - { - if(pe->req_action & EIGRP_FSM_NEED_QUERY) - { - length += eigrp_add_internalTLV_to_stream(ep->s, pe); - for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) - { - if(nbr->state == EIGRP_NEIGHBOR_UP) - { - listnode_add(pe->rij, nbr); - has_tlv = 1; - } - } - } - } - - if(!has_tlv) - { - eigrp_packet_free(ep); - return; - } - - if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && - (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL)) - { - eigrp_make_md5_digest(ei,ep->s, EIGRP_AUTH_UPDATE_FLAG); - } - - /* EIGRP Checksum */ - eigrp_packet_checksum(ei, ep->s, length); - - ep->length = length; - ep->dst.s_addr = htonl(EIGRP_MULTICAST_ADDRESS); - - /*This ack number we await from neighbor*/ - ep->sequence_number = ei->eigrp->sequence_number; - - for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) - { - if (nbr->state == EIGRP_NEIGHBOR_UP) - { - /*Put packet to retransmission queue*/ - eigrp_fifo_push_head(nbr->retrans_queue, ep); - ep_saved = true; - - if (nbr->retrans_queue->count == 1) - { - eigrp_send_packet_reliably(nbr); - } - } - } - - if (!ep_saved) - eigrp_packet_free(ep); + struct eigrp_packet *ep; + u_int16_t length = EIGRP_HEADER_LEN; + struct listnode *node, *nnode, *node2, *nnode2; + struct eigrp_neighbor *nbr; + struct eigrp_prefix_entry *pe; + char has_tlv; + bool ep_saved = false; + + ep = eigrp_packet_new(ei->ifp->mtu); + + /* Prepare EIGRP INIT UPDATE header */ + eigrp_packet_header_init(EIGRP_OPC_QUERY, ei, ep->s, 0, + ei->eigrp->sequence_number, 0); + + // encode Authentication TLV, if needed + if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) + && (IF_DEF_PARAMS(ei->ifp)->auth_keychain != NULL)) { + length += eigrp_add_authTLV_MD5_to_stream(ep->s, ei); + } + + has_tlv = 0; + for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node, + nnode, pe)) { + if (pe->req_action & EIGRP_FSM_NEED_QUERY) { + length += eigrp_add_internalTLV_to_stream(ep->s, pe); + for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) { + if (nbr->state == EIGRP_NEIGHBOR_UP) { + listnode_add(pe->rij, nbr); + has_tlv = 1; + } + } + } + } + + if (!has_tlv) { + eigrp_packet_free(ep); + return; + } + + if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) + && (IF_DEF_PARAMS(ei->ifp)->auth_keychain != NULL)) { + eigrp_make_md5_digest(ei, ep->s, EIGRP_AUTH_UPDATE_FLAG); + } + + /* EIGRP Checksum */ + eigrp_packet_checksum(ei, ep->s, length); + + ep->length = length; + ep->dst.s_addr = htonl(EIGRP_MULTICAST_ADDRESS); + + /*This ack number we await from neighbor*/ + ep->sequence_number = ei->eigrp->sequence_number; + + for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) { + if (nbr->state == EIGRP_NEIGHBOR_UP) { + /*Put packet to retransmission queue*/ + eigrp_fifo_push_head(nbr->retrans_queue, ep); + ep_saved = true; + + if (nbr->retrans_queue->count == 1) { + eigrp_send_packet_reliably(nbr); + } + } + } + + if (!ep_saved) + eigrp_packet_free(ep); } diff --git a/eigrpd/eigrp_reply.c b/eigrpd/eigrp_reply.c index 4e3ed66a0..4eb08c60d 100644 --- a/eigrpd/eigrp_reply.c +++ b/eigrpd/eigrp_reply.c @@ -60,190 +60,200 @@ #include "eigrpd/eigrp_fsm.h" #include "eigrpd/eigrp_memory.h" -void -eigrp_send_reply (struct eigrp_neighbor *nbr, struct eigrp_prefix_entry *pe) +void eigrp_send_reply(struct eigrp_neighbor *nbr, struct eigrp_prefix_entry *pe) { - struct eigrp_packet *ep; - u_int16_t length = EIGRP_HEADER_LEN; - - struct access_list *alist; - struct prefix_list *plist; - struct access_list *alist_i; - struct prefix_list *plist_i; - struct eigrp *e; - struct eigrp_prefix_entry *pe2; - - //TODO: Work in progress - /* Filtering */ - /* get list from eigrp process */ - e = eigrp_lookup(); - pe2 = XCALLOC(MTYPE_EIGRP_PREFIX_ENTRY, sizeof(struct eigrp_prefix_entry)); - memcpy(pe2,pe,sizeof(struct eigrp_prefix_entry)); - /* Get access-lists and prefix-lists from process and interface */ - alist = e->list[EIGRP_FILTER_OUT]; - plist = e->prefix[EIGRP_FILTER_OUT]; - alist_i = nbr->ei->list[EIGRP_FILTER_OUT]; - plist_i = nbr->ei->prefix[EIGRP_FILTER_OUT]; - zlog_info("REPLY Send: Filtering"); - - zlog_info("REPLY SEND Prefix: %s", inet_ntoa(nbr->src)); - /* Check if any list fits */ - if ((alist && - access_list_apply (alist, (struct prefix *) pe2->destination_ipv4) == FILTER_DENY) || - (plist && prefix_list_apply (plist, (struct prefix *) pe2->destination_ipv4) == PREFIX_DENY)|| - (alist_i && access_list_apply (alist_i, (struct prefix *) pe2->destination_ipv4) == FILTER_DENY)|| - (plist_i && prefix_list_apply (plist_i, (struct prefix *) pe2->destination_ipv4) == PREFIX_DENY)) - { - zlog_info("REPLY SEND: Setting Metric to max"); - pe2->reported_metric.delay = EIGRP_MAX_METRIC; - - } - else - { - zlog_info("REPLY SEND: Not setting metric"); - } - - /* - * End of filtering - */ - - ep = eigrp_packet_new(nbr->ei->ifp->mtu); - - /* Prepare EIGRP INIT UPDATE header */ - eigrp_packet_header_init(EIGRP_OPC_REPLY, nbr->ei, ep->s, 0, - nbr->ei->eigrp->sequence_number, 0); - - // encode Authentication TLV, if needed - if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && - (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL)) - { - length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei); - } - - - length += eigrp_add_internalTLV_to_stream(ep->s, pe2); - - if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && - (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL)) - { - eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_FLAG); - } - - /* EIGRP Checksum */ - eigrp_packet_checksum(nbr->ei, ep->s, length); - - ep->length = length; - ep->dst.s_addr = nbr->src.s_addr; - - /*This ack number we await from neighbor*/ - ep->sequence_number = nbr->ei->eigrp->sequence_number; - - /*Put packet to retransmission queue*/ - eigrp_fifo_push_head(nbr->retrans_queue, ep); - - if (nbr->retrans_queue->count == 1) - { - eigrp_send_packet_reliably(nbr); - } - - XFREE(MTYPE_EIGRP_PREFIX_ENTRY, pe2); + struct eigrp_packet *ep; + u_int16_t length = EIGRP_HEADER_LEN; + + struct access_list *alist; + struct prefix_list *plist; + struct access_list *alist_i; + struct prefix_list *plist_i; + struct eigrp *e; + struct eigrp_prefix_entry *pe2; + + // TODO: Work in progress + /* Filtering */ + /* get list from eigrp process */ + e = eigrp_lookup(); + pe2 = XCALLOC(MTYPE_EIGRP_PREFIX_ENTRY, + sizeof(struct eigrp_prefix_entry)); + memcpy(pe2, pe, sizeof(struct eigrp_prefix_entry)); + /* Get access-lists and prefix-lists from process and interface */ + alist = e->list[EIGRP_FILTER_OUT]; + plist = e->prefix[EIGRP_FILTER_OUT]; + alist_i = nbr->ei->list[EIGRP_FILTER_OUT]; + plist_i = nbr->ei->prefix[EIGRP_FILTER_OUT]; + zlog_info("REPLY Send: Filtering"); + + zlog_info("REPLY SEND Prefix: %s", inet_ntoa(nbr->src)); + /* Check if any list fits */ + if ((alist + && access_list_apply(alist, (struct prefix *)pe2->destination_ipv4) + == FILTER_DENY) + || (plist + && prefix_list_apply(plist, + (struct prefix *)pe2->destination_ipv4) + == PREFIX_DENY) + || (alist_i + && access_list_apply(alist_i, + (struct prefix *)pe2->destination_ipv4) + == FILTER_DENY) + || (plist_i + && prefix_list_apply(plist_i, + (struct prefix *)pe2->destination_ipv4) + == PREFIX_DENY)) { + zlog_info("REPLY SEND: Setting Metric to max"); + pe2->reported_metric.delay = EIGRP_MAX_METRIC; + + } else { + zlog_info("REPLY SEND: Not setting metric"); + } + + /* + * End of filtering + */ + + ep = eigrp_packet_new(nbr->ei->ifp->mtu); + + /* Prepare EIGRP INIT UPDATE header */ + eigrp_packet_header_init(EIGRP_OPC_REPLY, nbr->ei, ep->s, 0, + nbr->ei->eigrp->sequence_number, 0); + + // encode Authentication TLV, if needed + if ((IF_DEF_PARAMS(nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) + && (IF_DEF_PARAMS(nbr->ei->ifp)->auth_keychain != NULL)) { + length += eigrp_add_authTLV_MD5_to_stream(ep->s, nbr->ei); + } + + + length += eigrp_add_internalTLV_to_stream(ep->s, pe2); + + if ((IF_DEF_PARAMS(nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) + && (IF_DEF_PARAMS(nbr->ei->ifp)->auth_keychain != NULL)) { + eigrp_make_md5_digest(nbr->ei, ep->s, EIGRP_AUTH_UPDATE_FLAG); + } + + /* EIGRP Checksum */ + eigrp_packet_checksum(nbr->ei, ep->s, length); + + ep->length = length; + ep->dst.s_addr = nbr->src.s_addr; + + /*This ack number we await from neighbor*/ + ep->sequence_number = nbr->ei->eigrp->sequence_number; + + /*Put packet to retransmission queue*/ + eigrp_fifo_push_head(nbr->retrans_queue, ep); + + if (nbr->retrans_queue->count == 1) { + eigrp_send_packet_reliably(nbr); + } + + XFREE(MTYPE_EIGRP_PREFIX_ENTRY, pe2); } /*EIGRP REPLY read function*/ -void -eigrp_reply_receive (struct eigrp *eigrp, struct ip *iph, struct eigrp_header *eigrph, - struct stream * s, struct eigrp_interface *ei, int size) +void eigrp_reply_receive(struct eigrp *eigrp, struct ip *iph, + struct eigrp_header *eigrph, struct stream *s, + struct eigrp_interface *ei, int size) { - struct eigrp_neighbor *nbr; - struct TLV_IPv4_Internal_type *tlv; - - struct access_list *alist; - struct prefix_list *plist; - struct access_list *alist_i; - struct prefix_list *plist_i; - struct eigrp *e; - - u_int16_t type; - - /* increment statistics. */ - ei->reply_in++; - - /* get neighbor struct */ - nbr = eigrp_nbr_get(ei, eigrph, iph); - - /* neighbor must be valid, eigrp_nbr_get creates if none existed */ - assert(nbr); - - nbr->recv_sequence_number = ntohl(eigrph->sequence); - - while (s->endp > s->getp) - { - type = stream_getw(s); - if (type == EIGRP_TLV_IPv4_INT) - { - struct prefix_ipv4 dest_addr; - - stream_set_getp(s, s->getp - sizeof(u_int16_t)); - - tlv = eigrp_read_ipv4_tlv(s); - - dest_addr.family = AF_INET; - dest_addr.prefix = tlv->destination; - dest_addr.prefixlen = tlv->prefix_length; - struct eigrp_prefix_entry *dest = - eigrp_topology_table_lookup_ipv4 (eigrp->topology_table, &dest_addr); - /* - * Destination must exists - */ - assert(dest); - - struct eigrp_fsm_action_message *msg; - msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct eigrp_fsm_action_message)); - struct eigrp_neighbor_entry *entry = - eigrp_prefix_entry_lookup(dest->entries, nbr); - - /* - * Filtering - */ - //TODO: Work in progress - /* get list from eigrp process */ - e = eigrp_lookup(); - /* Get access-lists and prefix-lists from process and interface */ - alist = e->list[EIGRP_FILTER_IN]; - plist = e->prefix[EIGRP_FILTER_IN]; - alist_i = ei->list[EIGRP_FILTER_IN]; - plist_i = ei->prefix[EIGRP_FILTER_IN]; - /* Check if any list fits */ - if ((alist && - access_list_apply (alist, (struct prefix *)&dest_addr) == FILTER_DENY) || - (plist && - prefix_list_apply (plist, (struct prefix *)&dest_addr) == PREFIX_DENY) || - (alist_i && - access_list_apply (alist_i, (struct prefix *)&dest_addr) == FILTER_DENY) || - (plist_i && - prefix_list_apply (plist_i, (struct prefix *)&dest_addr) == PREFIX_DENY)) - { - tlv->metric.delay = EIGRP_MAX_METRIC; - } - /* - * End of filtering - */ - - msg->packet_type = EIGRP_OPC_REPLY; - msg->eigrp = eigrp; - msg->data_type = EIGRP_TLV_IPv4_INT; - msg->adv_router = nbr; - msg->data.ipv4_int_type = tlv; - msg->entry = entry; - msg->prefix = dest; - int event = eigrp_get_fsm_event(msg); - eigrp_fsm_event(msg, event); - - - eigrp_IPv4_InternalTLV_free (tlv); - } - } - eigrp_hello_send_ack(nbr); + struct eigrp_neighbor *nbr; + struct TLV_IPv4_Internal_type *tlv; + + struct access_list *alist; + struct prefix_list *plist; + struct access_list *alist_i; + struct prefix_list *plist_i; + struct eigrp *e; + + u_int16_t type; + + /* increment statistics. */ + ei->reply_in++; + + /* get neighbor struct */ + nbr = eigrp_nbr_get(ei, eigrph, iph); + + /* neighbor must be valid, eigrp_nbr_get creates if none existed */ + assert(nbr); + + nbr->recv_sequence_number = ntohl(eigrph->sequence); + + while (s->endp > s->getp) { + type = stream_getw(s); + if (type == EIGRP_TLV_IPv4_INT) { + struct prefix_ipv4 dest_addr; + + stream_set_getp(s, s->getp - sizeof(u_int16_t)); + + tlv = eigrp_read_ipv4_tlv(s); + + dest_addr.family = AF_INET; + dest_addr.prefix = tlv->destination; + dest_addr.prefixlen = tlv->prefix_length; + struct eigrp_prefix_entry *dest = + eigrp_topology_table_lookup_ipv4( + eigrp->topology_table, &dest_addr); + /* + * Destination must exists + */ + assert(dest); + + struct eigrp_fsm_action_message *msg; + msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, + sizeof(struct eigrp_fsm_action_message)); + struct eigrp_neighbor_entry *entry = + eigrp_prefix_entry_lookup(dest->entries, nbr); + + /* + * Filtering + */ + // TODO: Work in progress + /* get list from eigrp process */ + e = eigrp_lookup(); + /* Get access-lists and prefix-lists from process and + * interface */ + alist = e->list[EIGRP_FILTER_IN]; + plist = e->prefix[EIGRP_FILTER_IN]; + alist_i = ei->list[EIGRP_FILTER_IN]; + plist_i = ei->prefix[EIGRP_FILTER_IN]; + /* Check if any list fits */ + if ((alist + && access_list_apply(alist, + (struct prefix *)&dest_addr) + == FILTER_DENY) + || (plist + && prefix_list_apply( + plist, (struct prefix *)&dest_addr) + == PREFIX_DENY) + || (alist_i + && access_list_apply( + alist_i, (struct prefix *)&dest_addr) + == FILTER_DENY) + || (plist_i + && prefix_list_apply( + plist_i, (struct prefix *)&dest_addr) + == PREFIX_DENY)) { + tlv->metric.delay = EIGRP_MAX_METRIC; + } + /* + * End of filtering + */ + + msg->packet_type = EIGRP_OPC_REPLY; + msg->eigrp = eigrp; + msg->data_type = EIGRP_TLV_IPv4_INT; + msg->adv_router = nbr; + msg->data.ipv4_int_type = tlv; + msg->entry = entry; + msg->prefix = dest; + int event = eigrp_get_fsm_event(msg); + eigrp_fsm_event(msg, event); + + + eigrp_IPv4_InternalTLV_free(tlv); + } + } + eigrp_hello_send_ack(nbr); } - diff --git a/eigrpd/eigrp_routemap.c b/eigrpd/eigrp_routemap.c index 1d85e7646..b645ed198 100644 --- a/eigrpd/eigrp_routemap.c +++ b/eigrpd/eigrp_routemap.c @@ -45,7 +45,7 @@ #include "command.h" #include "filter.h" #include "log.h" -#include "sockunion.h" /* for inet_aton () */ +#include "sockunion.h" /* for inet_aton () */ #include "plist.h" #include "eigrpd/eigrpd.h" @@ -54,774 +54,699 @@ #include "eigrpd/eigrp_macros.h" #include "eigrpd/eigrp_routemap.h" -void -eigrp_if_rmap_update (struct if_rmap *if_rmap) +void eigrp_if_rmap_update(struct if_rmap *if_rmap) { - struct interface *ifp; - struct eigrp_interface *ei, *ei2; - struct listnode *node, *nnode; - struct route_map *rmap; - struct eigrp *e; - - ifp = if_lookup_by_name (if_rmap->ifname); - if (ifp == NULL) - return; - - ei = NULL; - e = eigrp_lookup(); - for (ALL_LIST_ELEMENTS (e->eiflist, node, nnode, ei2)) - { - if(strcmp(ei2->ifp->name,ifp->name) == 0){ - ei = ei2; - break; - } - } - - if (if_rmap->routemap[IF_RMAP_IN]) - { - rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]); - if (rmap) - ei->routemap[IF_RMAP_IN] = rmap; - else - ei->routemap[IF_RMAP_IN] = NULL; - } - else - ei->routemap[EIGRP_FILTER_IN] = NULL; - - if (if_rmap->routemap[IF_RMAP_OUT]) - { - rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]); - if (rmap) - ei->routemap[IF_RMAP_OUT] = rmap; - else - ei->routemap[IF_RMAP_OUT] = NULL; - } - else - ei->routemap[EIGRP_FILTER_OUT] = NULL; + struct interface *ifp; + struct eigrp_interface *ei, *ei2; + struct listnode *node, *nnode; + struct route_map *rmap; + struct eigrp *e; + + ifp = if_lookup_by_name(if_rmap->ifname); + if (ifp == NULL) + return; + + ei = NULL; + e = eigrp_lookup(); + for (ALL_LIST_ELEMENTS(e->eiflist, node, nnode, ei2)) { + if (strcmp(ei2->ifp->name, ifp->name) == 0) { + ei = ei2; + break; + } + } + + if (if_rmap->routemap[IF_RMAP_IN]) { + rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_IN]); + if (rmap) + ei->routemap[IF_RMAP_IN] = rmap; + else + ei->routemap[IF_RMAP_IN] = NULL; + } else + ei->routemap[EIGRP_FILTER_IN] = NULL; + + if (if_rmap->routemap[IF_RMAP_OUT]) { + rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_OUT]); + if (rmap) + ei->routemap[IF_RMAP_OUT] = rmap; + else + ei->routemap[IF_RMAP_OUT] = NULL; + } else + ei->routemap[EIGRP_FILTER_OUT] = NULL; } -void -eigrp_if_rmap_update_interface (struct interface *ifp) +void eigrp_if_rmap_update_interface(struct interface *ifp) { - struct if_rmap *if_rmap; + struct if_rmap *if_rmap; - if_rmap = if_rmap_lookup (ifp->name); - if (if_rmap) - eigrp_if_rmap_update (if_rmap); + if_rmap = if_rmap_lookup(ifp->name); + if (if_rmap) + eigrp_if_rmap_update(if_rmap); } -void -eigrp_routemap_update_redistribute (void) +void eigrp_routemap_update_redistribute(void) { - int i; - struct eigrp *e; - - e = eigrp_lookup(); - - if (e) - { - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - if (e->route_map[i].name) - e->route_map[i].map = - route_map_lookup_by_name (e->route_map[i].name); - } - } + int i; + struct eigrp *e; + + e = eigrp_lookup(); + + if (e) { + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (e->route_map[i].name) + e->route_map[i].map = route_map_lookup_by_name( + e->route_map[i].name); + } + } } /* ARGSUSED */ -void -eigrp_rmap_update (const char *notused) +void eigrp_rmap_update(const char *notused) { - struct interface *ifp; - struct listnode *node, *nnode; + struct interface *ifp; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp)) - eigrp_if_rmap_update_interface (ifp); + for (ALL_LIST_ELEMENTS(iflist, node, nnode, ifp)) + eigrp_if_rmap_update_interface(ifp); - eigrp_routemap_update_redistribute (); + eigrp_routemap_update_redistribute(); } /* Add eigrp route map rule. */ -static int -eigrp_route_match_add (struct vty *vty, struct route_map_index *index, - const char *command, const char *arg) +static int eigrp_route_match_add(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg) { - int ret; - ret = route_map_add_match (index, command, arg); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% Can't find rule.\n"); - return CMD_WARNING_CONFIG_FAILED; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Argument is malformed.\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - return CMD_SUCCESS; + int ret; + ret = route_map_add_match(index, command, arg); + if (ret) { + switch (ret) { + case RMAP_RULE_MISSING: + vty_out(vty, "%% Can't find rule.\n"); + return CMD_WARNING_CONFIG_FAILED; + case RMAP_COMPILE_ERROR: + vty_out(vty, "%% Argument is malformed.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + return CMD_SUCCESS; } /* Delete rip route map rule. */ -static int -eigrp_route_match_delete (struct vty *vty, struct route_map_index *index, - const char *command, const char *arg) +static int eigrp_route_match_delete(struct vty *vty, + struct route_map_index *index, + const char *command, const char *arg) { - int ret; - ret = route_map_delete_match (index, command, arg); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% Can't find rule.\n"); - return CMD_WARNING_CONFIG_FAILED; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Argument is malformed.\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - return CMD_SUCCESS; + int ret; + ret = route_map_delete_match(index, command, arg); + if (ret) { + switch (ret) { + case RMAP_RULE_MISSING: + vty_out(vty, "%% Can't find rule.\n"); + return CMD_WARNING_CONFIG_FAILED; + case RMAP_COMPILE_ERROR: + vty_out(vty, "%% Argument is malformed.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + return CMD_SUCCESS; } /* Add eigrp route map rule. */ -static int -eigrp_route_set_add (struct vty *vty, struct route_map_index *index, - const char *command, const char *arg) +static int eigrp_route_set_add(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg) { - int ret; - - ret = route_map_add_set (index, command, arg); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% Can't find rule.\n"); - return CMD_WARNING_CONFIG_FAILED; - case RMAP_COMPILE_ERROR: - /* rip, ripng and other protocols share the set metric command - but only values from 0 to 16 are valid for rip and ripng - if metric is out of range for rip and ripng, it is not for - other protocols. Do not return an error */ - if (strcmp(command, "metric")) { - vty_out (vty, "%% Argument is malformed.\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - } - return CMD_SUCCESS; + int ret; + + ret = route_map_add_set(index, command, arg); + if (ret) { + switch (ret) { + case RMAP_RULE_MISSING: + vty_out(vty, "%% Can't find rule.\n"); + return CMD_WARNING_CONFIG_FAILED; + case RMAP_COMPILE_ERROR: + /* rip, ripng and other protocols share the set metric + command + but only values from 0 to 16 are valid for rip and + ripng + if metric is out of range for rip and ripng, it is + not for + other protocols. Do not return an error */ + if (strcmp(command, "metric")) { + vty_out(vty, "%% Argument is malformed.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + } + return CMD_SUCCESS; } /* Delete eigrp route map rule. */ -static int -eigrp_route_set_delete (struct vty *vty, struct route_map_index *index, - const char *command, const char *arg) +static int eigrp_route_set_delete(struct vty *vty, + struct route_map_index *index, + const char *command, const char *arg) { - int ret; - - ret = route_map_delete_set (index, command, arg); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% Can't find rule.\n"); - return CMD_WARNING_CONFIG_FAILED; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Argument is malformed.\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - return CMD_SUCCESS; + int ret; + + ret = route_map_delete_set(index, command, arg); + if (ret) { + switch (ret) { + case RMAP_RULE_MISSING: + vty_out(vty, "%% Can't find rule.\n"); + return CMD_WARNING_CONFIG_FAILED; + case RMAP_COMPILE_ERROR: + vty_out(vty, "%% Argument is malformed.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + return CMD_SUCCESS; } /* Hook function for updating route_map assignment. */ /* ARGSUSED */ -void -eigrp_route_map_update (const char *notused) +void eigrp_route_map_update(const char *notused) { - int i; - struct eigrp *e; - e = eigrp_lookup(); - - if (e) - { - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - if (e->route_map[i].name) - e->route_map[i].map = - route_map_lookup_by_name (e->route_map[i].name); - } - } + int i; + struct eigrp *e; + e = eigrp_lookup(); + + if (e) { + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (e->route_map[i].name) + e->route_map[i].map = route_map_lookup_by_name( + e->route_map[i].name); + } + } } - /* `match metric METRIC' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_metric (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_metric(void *rule, struct prefix *prefix, + route_map_object_t type, + void *object) { - // u_int32_t *metric; - // u_int32_t check; - // struct rip_info *rinfo; - // struct eigrp_neighbor_entry *te; - // struct eigrp_prefix_entry *pe; - // struct listnode *node, *node2, *nnode, *nnode2; - // struct eigrp *e; - // - // e = eigrp_lookup(); - // - // if (type == RMAP_EIGRP) - // { - // metric = rule; - // rinfo = object; - // - // /* If external metric is available, the route-map should - // work on this one (for redistribute purpose) */ - // /*check = (rinfo->external_metric) ? rinfo->external_metric : - // rinfo->metric;*/ - // - // if (check == *metric) - // return RMAP_MATCH; - // else - // return RMAP_NOMATCH; - // } - return RMAP_NOMATCH; + // u_int32_t *metric; + // u_int32_t check; + // struct rip_info *rinfo; + // struct eigrp_neighbor_entry *te; + // struct eigrp_prefix_entry *pe; + // struct listnode *node, *node2, *nnode, *nnode2; + // struct eigrp *e; + // + // e = eigrp_lookup(); + // + // if (type == RMAP_EIGRP) + // { + // metric = rule; + // rinfo = object; + // + // /* If external metric is available, the route-map should + // work on this one (for redistribute purpose) */ + // /*check = (rinfo->external_metric) ? rinfo->external_metric : + // rinfo->metric;*/ + // + // if (check == *metric) + // return RMAP_MATCH; + // else + // return RMAP_NOMATCH; + // } + return RMAP_NOMATCH; } /* Route map `match metric' match statement. `arg' is METRIC value */ -static void * -route_match_metric_compile (const char *arg) +static void *route_match_metric_compile(const char *arg) { - // u_int32_t *metric; - // - // metric = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); - // *metric = atoi (arg); - // - // if(*metric > 0) - // return metric; - // - // XFREE (MTYPE_ROUTE_MAP_COMPILED, metric); - return NULL; + // u_int32_t *metric; + // + // metric = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); + // *metric = atoi (arg); + // + // if(*metric > 0) + // return metric; + // + // XFREE (MTYPE_ROUTE_MAP_COMPILED, metric); + return NULL; } /* Free route map's compiled `match metric' value. */ -static void -route_match_metric_free (void *rule) +static void route_match_metric_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for metric matching. */ -struct route_map_rule_cmd route_match_metric_cmd = -{ - "metric", - route_match_metric, - route_match_metric_compile, - route_match_metric_free -}; +struct route_map_rule_cmd route_match_metric_cmd = { + "metric", route_match_metric, route_match_metric_compile, + route_match_metric_free}; /* `match interface IFNAME' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_interface (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_interface(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - // struct rip_info *rinfo; - // struct interface *ifp; - // char *ifname; - // - // if (type == RMAP_EIGRP) - // { - // ifname = rule; - // ifp = if_lookup_by_name(ifname); - // - // if (!ifp) - // return RMAP_NOMATCH; - // - // rinfo = object; - // - // /*if (rinfo->ifindex_out == ifp->ifindex || rinfo->ifindex == ifp->ifindex) - // return RMAP_MATCH; - // else - // return RMAP_NOMATCH;*/ - // } - return RMAP_NOMATCH; + // struct rip_info *rinfo; + // struct interface *ifp; + // char *ifname; + // + // if (type == RMAP_EIGRP) + // { + // ifname = rule; + // ifp = if_lookup_by_name(ifname); + // + // if (!ifp) + // return RMAP_NOMATCH; + // + // rinfo = object; + // + // /*if (rinfo->ifindex_out == ifp->ifindex || rinfo->ifindex == + // ifp->ifindex) + // return RMAP_MATCH; + // else + // return RMAP_NOMATCH;*/ + // } + return RMAP_NOMATCH; } /* Route map `match interface' match statement. `arg' is IFNAME value */ /* XXX I don`t know if I need to check does interface exist? */ -static void * -route_match_interface_compile (const char *arg) +static void *route_match_interface_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `match interface' value. */ -static void -route_match_interface_free (void *rule) +static void route_match_interface_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for interface matching. */ -struct route_map_rule_cmd route_match_interface_cmd = -{ - "interface", - route_match_interface, - route_match_interface_compile, - route_match_interface_free -}; +struct route_map_rule_cmd route_match_interface_cmd = { + "interface", route_match_interface, route_match_interface_compile, + route_match_interface_free}; /* `match ip next-hop IP_ACCESS_LIST' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_ip_next_hop (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_ip_next_hop(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - // struct access_list *alist; - // struct rip_info *rinfo; - // struct prefix_ipv4 p; - // - // if (type == RMAP_EIGRP) - // { - // rinfo = object; - // p.family = AF_INET; - // /*p.prefix = (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from;*/ - // p.prefixlen = IPV4_MAX_BITLEN; - // - // alist = access_list_lookup (AFI_IP, (char *) rule); - // if (alist == NULL) - // return RMAP_NOMATCH; - // - // return (access_list_apply (alist, &p) == FILTER_DENY ? - // RMAP_NOMATCH : RMAP_MATCH); - // } - return RMAP_NOMATCH; + // struct access_list *alist; + // struct rip_info *rinfo; + // struct prefix_ipv4 p; + // + // if (type == RMAP_EIGRP) + // { + // rinfo = object; + // p.family = AF_INET; + // /*p.prefix = (rinfo->nexthop.s_addr) ? rinfo->nexthop : + // rinfo->from;*/ + // p.prefixlen = IPV4_MAX_BITLEN; + // + // alist = access_list_lookup (AFI_IP, (char *) rule); + // if (alist == NULL) + // return RMAP_NOMATCH; + // + // return (access_list_apply (alist, &p) == FILTER_DENY ? + // RMAP_NOMATCH : RMAP_MATCH); + // } + return RMAP_NOMATCH; } /* Route map `ip next-hop' match statement. `arg' should be access-list name. */ -static void * -route_match_ip_next_hop_compile (const char *arg) +static void *route_match_ip_next_hop_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `. */ -static void -route_match_ip_next_hop_free (void *rule) +static void route_match_ip_next_hop_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip next-hop matching. */ -static struct route_map_rule_cmd route_match_ip_next_hop_cmd = - { - "ip next-hop", - route_match_ip_next_hop, - route_match_ip_next_hop_compile, - route_match_ip_next_hop_free - }; +static struct route_map_rule_cmd route_match_ip_next_hop_cmd = { + "ip next-hop", route_match_ip_next_hop, route_match_ip_next_hop_compile, + route_match_ip_next_hop_free}; /* `match ip next-hop prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - // struct prefix_list *plist; - // struct rip_info *rinfo; - // struct prefix_ipv4 p; - // - // if (type == RMAP_EIGRP) - // { - // rinfo = object; - // p.family = AF_INET; - // /*p.prefix = (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from;*/ - // p.prefixlen = IPV4_MAX_BITLEN; - // - // plist = prefix_list_lookup (AFI_IP, (char *) rule); - // if (plist == NULL) - // return RMAP_NOMATCH; - // - // return (prefix_list_apply (plist, &p) == PREFIX_DENY ? - // RMAP_NOMATCH : RMAP_MATCH); - // } - return RMAP_NOMATCH; + // struct prefix_list *plist; + // struct rip_info *rinfo; + // struct prefix_ipv4 p; + // + // if (type == RMAP_EIGRP) + // { + // rinfo = object; + // p.family = AF_INET; + // /*p.prefix = (rinfo->nexthop.s_addr) ? rinfo->nexthop : + // rinfo->from;*/ + // p.prefixlen = IPV4_MAX_BITLEN; + // + // plist = prefix_list_lookup (AFI_IP, (char *) rule); + // if (plist == NULL) + // return RMAP_NOMATCH; + // + // return (prefix_list_apply (plist, &p) == PREFIX_DENY ? + // RMAP_NOMATCH : RMAP_MATCH); + // } + return RMAP_NOMATCH; } -static void * -route_match_ip_next_hop_prefix_list_compile (const char *arg) +static void *route_match_ip_next_hop_prefix_list_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ip_next_hop_prefix_list_free (void *rule) +static void route_match_ip_next_hop_prefix_list_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = -{ - "ip next-hop prefix-list", - route_match_ip_next_hop_prefix_list, - route_match_ip_next_hop_prefix_list_compile, - route_match_ip_next_hop_prefix_list_free -}; +static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = { + "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list, + route_match_ip_next_hop_prefix_list_compile, + route_match_ip_next_hop_prefix_list_free}; /* `match ip address IP_ACCESS_LIST' */ /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t -route_match_ip_address (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_ip_address(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct access_list *alist; - - if (type == RMAP_EIGRP) - { - alist = access_list_lookup (AFI_IP, (char *) rule); - if (alist == NULL) - return RMAP_NOMATCH; - - return (access_list_apply (alist, prefix) == FILTER_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; + struct access_list *alist; + + if (type == RMAP_EIGRP) { + alist = access_list_lookup(AFI_IP, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; + + return (access_list_apply(alist, prefix) == FILTER_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } + return RMAP_NOMATCH; } /* Route map `ip address' match statement. `arg' should be access-list name. */ -static void * -route_match_ip_address_compile (const char *arg) +static void *route_match_ip_address_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `ip address' value. */ -static void -route_match_ip_address_free (void *rule) +static void route_match_ip_address_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip address matching. */ -static struct route_map_rule_cmd route_match_ip_address_cmd = - { - "ip address", - route_match_ip_address, - route_match_ip_address_compile, - route_match_ip_address_free - }; +static struct route_map_rule_cmd route_match_ip_address_cmd = { + "ip address", route_match_ip_address, route_match_ip_address_compile, + route_match_ip_address_free}; /* `match ip address prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_address_prefix_list (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - struct prefix_list *plist; - - if (type == RMAP_EIGRP) - { - plist = prefix_list_lookup (AFI_IP, (char *) rule); - if (plist == NULL) - return RMAP_NOMATCH; - - return (prefix_list_apply (plist, prefix) == PREFIX_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; + struct prefix_list *plist; + + if (type == RMAP_EIGRP) { + plist = prefix_list_lookup(AFI_IP, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; + + return (prefix_list_apply(plist, prefix) == PREFIX_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } + return RMAP_NOMATCH; } -static void * -route_match_ip_address_prefix_list_compile (const char *arg) +static void *route_match_ip_address_prefix_list_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ip_address_prefix_list_free (void *rule) +static void route_match_ip_address_prefix_list_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = - { - "ip address prefix-list", - route_match_ip_address_prefix_list, - route_match_ip_address_prefix_list_compile, - route_match_ip_address_prefix_list_free - }; +static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { + "ip address prefix-list", route_match_ip_address_prefix_list, + route_match_ip_address_prefix_list_compile, + route_match_ip_address_prefix_list_free}; /* `match tag TAG' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_tag (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_tag(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - // u_short *tag; - // struct rip_info *rinfo; - // - // if (type == RMAP_EIGRP) - // { - // tag = rule; - // rinfo = object; - // - // /* The information stored by rinfo is host ordered. */ - // /*if (rinfo->tag == *tag) - // return RMAP_MATCH; - // else - // return RMAP_NOMATCH;*/ - // } - return RMAP_NOMATCH; + // u_short *tag; + // struct rip_info *rinfo; + // + // if (type == RMAP_EIGRP) + // { + // tag = rule; + // rinfo = object; + // + // /* The information stored by rinfo is host ordered. */ + // /*if (rinfo->tag == *tag) + // return RMAP_MATCH; + // else + // return RMAP_NOMATCH;*/ + // } + return RMAP_NOMATCH; } /* Route map `match tag' match statement. `arg' is TAG value */ -static void * -route_match_tag_compile (const char *arg) +static void *route_match_tag_compile(const char *arg) { - // u_short *tag; - // - // tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); - // *tag = atoi (arg); - // - // return tag; + // u_short *tag; + // + // tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); + // *tag = atoi (arg); + // + // return tag; } /* Free route map's compiled `match tag' value. */ -static void -route_match_tag_free (void *rule) +static void route_match_tag_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for tag matching. */ -struct route_map_rule_cmd route_match_tag_cmd = - { - "tag", - route_match_tag, - route_match_tag_compile, - route_match_tag_free - }; +struct route_map_rule_cmd route_match_tag_cmd = { + "tag", route_match_tag, route_match_tag_compile, route_match_tag_free}; /* Set metric to attribute. */ -static route_map_result_t -route_set_metric (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, + route_map_object_t type, + void *object) { - // if (type == RMAP_RIP) - // { - // struct rip_metric_modifier *mod; - // struct rip_info *rinfo; - // - // mod = rule; - // rinfo = object; - // - // /*if (mod->type == metric_increment) - // rinfo->metric_out += mod->metric; - // else if (mod->type == metric_decrement) - // rinfo->metric_out -= mod->metric; - // else if (mod->type == metric_absolute) - // rinfo->metric_out = mod->metric; - // - // if ((signed int)rinfo->metric_out < 1) - // rinfo->metric_out = 1; - // if (rinfo->metric_out > RIP_METRIC_INFINITY) - // rinfo->metric_out = RIP_METRIC_INFINITY;*/ - // - // rinfo->metric_set = 1; - // } - return RMAP_OKAY; + // if (type == RMAP_RIP) + // { + // struct rip_metric_modifier *mod; + // struct rip_info *rinfo; + // + // mod = rule; + // rinfo = object; + // + // /*if (mod->type == metric_increment) + // rinfo->metric_out += mod->metric; + // else if (mod->type == metric_decrement) + // rinfo->metric_out -= mod->metric; + // else if (mod->type == metric_absolute) + // rinfo->metric_out = mod->metric; + // + // if ((signed int)rinfo->metric_out < 1) + // rinfo->metric_out = 1; + // if (rinfo->metric_out > RIP_METRIC_INFINITY) + // rinfo->metric_out = RIP_METRIC_INFINITY;*/ + // + // rinfo->metric_set = 1; + // } + return RMAP_OKAY; } /* set metric compilation. */ -static void * -route_set_metric_compile (const char *arg) +static void *route_set_metric_compile(const char *arg) { - // int len; - // const char *pnt; - // int type; - // long metric; - // char *endptr = NULL; - // struct rip_metric_modifier *mod; - // - // len = strlen (arg); - // pnt = arg; - // - // if (len == 0) - // return NULL; - // - // /* Examine first character. */ - // if (arg[0] == '+') - // { - // //type = metric_increment; - // pnt++; - // } - // else if (arg[0] == '-') - // { - // //type = metric_decrement; - // pnt++; - // } - // /*else - // type = metric_absolute;*/ - // - // /* Check beginning with digit string. */ - // if (*pnt < '0' || *pnt > '9') - // return NULL; - // - // /* Convert string to integer. */ - // metric = strtol (pnt, &endptr, 10); - // - // if (metric == LONG_MAX || *endptr != '\0') - // return NULL; - // /*if (metric < 0 || metric > RIP_METRIC_INFINITY) - // return NULL;*/ - // - // mod = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, - // sizeof (struct rip_metric_modifier)); - // mod->type = type; - // mod->metric = metric; - - // return mod; + // int len; + // const char *pnt; + // int type; + // long metric; + // char *endptr = NULL; + // struct rip_metric_modifier *mod; + // + // len = strlen (arg); + // pnt = arg; + // + // if (len == 0) + // return NULL; + // + // /* Examine first character. */ + // if (arg[0] == '+') + // { + // //type = metric_increment; + // pnt++; + // } + // else if (arg[0] == '-') + // { + // //type = metric_decrement; + // pnt++; + // } + // /*else + // type = metric_absolute;*/ + // + // /* Check beginning with digit string. */ + // if (*pnt < '0' || *pnt > '9') + // return NULL; + // + // /* Convert string to integer. */ + // metric = strtol (pnt, &endptr, 10); + // + // if (metric == LONG_MAX || *endptr != '\0') + // return NULL; + // /*if (metric < 0 || metric > RIP_METRIC_INFINITY) + // return NULL;*/ + // + // mod = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, + // sizeof (struct rip_metric_modifier)); + // mod->type = type; + // mod->metric = metric; + + // return mod; } /* Free route map's compiled `set metric' value. */ -static void -route_set_metric_free (void *rule) +static void route_set_metric_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Set metric rule structure. */ -static struct route_map_rule_cmd route_set_metric_cmd = - { - "metric", - route_set_metric, - route_set_metric_compile, - route_set_metric_free, - }; +static struct route_map_rule_cmd route_set_metric_cmd = { + "metric", route_set_metric, route_set_metric_compile, + route_set_metric_free, +}; /* `set ip next-hop IP_ADDRESS' */ /* Set nexthop to object. ojbect must be pointer to struct attr. */ -static route_map_result_t -route_set_ip_nexthop (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_ip_nexthop(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - // struct in_addr *address; - // struct rip_info *rinfo; - // - // if(type == RMAP_RIP) - // { - // /* Fetch routemap's rule information. */ - // address = rule; - // rinfo = object; - // - // /* Set next hop value. */ - // rinfo->nexthop_out = *address; - // } - - return RMAP_OKAY; + // struct in_addr *address; + // struct rip_info *rinfo; + // + // if(type == RMAP_RIP) + // { + // /* Fetch routemap's rule information. */ + // address = rule; + // rinfo = object; + // + // /* Set next hop value. */ + // rinfo->nexthop_out = *address; + // } + + return RMAP_OKAY; } /* Route map `ip nexthop' compile function. Given string is converted to struct in_addr structure. */ -static void * -route_set_ip_nexthop_compile (const char *arg) +static void *route_set_ip_nexthop_compile(const char *arg) { - // int ret; - // struct in_addr *address; - // - // address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr)); - // - // ret = inet_aton (arg, address); - // - // if (ret == 0) - // { - // XFREE (MTYPE_ROUTE_MAP_COMPILED, address); - // return NULL; - // } - // - // return address; + // int ret; + // struct in_addr *address; + // + // address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct + // in_addr)); + // + // ret = inet_aton (arg, address); + // + // if (ret == 0) + // { + // XFREE (MTYPE_ROUTE_MAP_COMPILED, address); + // return NULL; + // } + // + // return address; } /* Free route map's compiled `ip nexthop' value. */ -static void -route_set_ip_nexthop_free (void *rule) +static void route_set_ip_nexthop_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip nexthop set. */ -static struct route_map_rule_cmd route_set_ip_nexthop_cmd = - { - "ip next-hop", - route_set_ip_nexthop, - route_set_ip_nexthop_compile, - route_set_ip_nexthop_free - }; +static struct route_map_rule_cmd route_set_ip_nexthop_cmd = { + "ip next-hop", route_set_ip_nexthop, route_set_ip_nexthop_compile, + route_set_ip_nexthop_free}; /* `set tag TAG' */ /* Set tag to object. ojbect must be pointer to struct attr. */ -static route_map_result_t -route_set_tag (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_tag(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - // u_short *tag; - // struct rip_info *rinfo; - // - // if(type == RMAP_RIP) - // { - // /* Fetch routemap's rule information. */ - // tag = rule; - // rinfo = object; - // - // /* Set next hop value. */ - // rinfo->tag_out = *tag; - // } - - return RMAP_OKAY; + // u_short *tag; + // struct rip_info *rinfo; + // + // if(type == RMAP_RIP) + // { + // /* Fetch routemap's rule information. */ + // tag = rule; + // rinfo = object; + // + // /* Set next hop value. */ + // rinfo->tag_out = *tag; + // } + + return RMAP_OKAY; } /* Route map `tag' compile function. Given string is converted to u_short. */ -static void * -route_set_tag_compile (const char *arg) +static void *route_set_tag_compile(const char *arg) { - // u_short *tag; - // - // tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); - // *tag = atoi (arg); - // - // return tag; + // u_short *tag; + // + // tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); + // *tag = atoi (arg); + // + // return tag; } /* Free route map's compiled `ip nexthop' value. */ -static void -route_set_tag_free (void *rule) +static void route_set_tag_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for tag set. */ -static struct route_map_rule_cmd route_set_tag_cmd = - { - "tag", - route_set_tag, - route_set_tag_compile, - route_set_tag_free - }; +static struct route_map_rule_cmd route_set_tag_cmd = { + "tag", route_set_tag, route_set_tag_compile, route_set_tag_free}; #define MATCH_STR "Match values from routing table\n" #define SET_STR "Set values in destination routing protocol\n" @@ -833,7 +758,7 @@ DEFUN (match_metric, "Match metric of route\n" "Metric value\n") { - return eigrp_route_match_add (vty, vty->index, "metric", argv[0]); + return eigrp_route_match_add(vty, vty->index, "metric", argv[0]); } DEFUN (no_match_metric, @@ -843,19 +768,17 @@ DEFUN (no_match_metric, MATCH_STR "Match metric of route\n") { - if (argc == 0) - return eigrp_route_match_delete (vty, vty->index, "metric", NULL); + if (argc == 0) + return eigrp_route_match_delete(vty, vty->index, "metric", + NULL); - return eigrp_route_match_delete (vty, vty->index, "metric", argv[0]); + return eigrp_route_match_delete(vty, vty->index, "metric", argv[0]); } -ALIAS (no_match_metric, - no_match_metric_val_cmd, - "no match metric <0-4294967295>", - NO_STR - MATCH_STR - "Match metric of route\n" - "Metric value\n") +ALIAS(no_match_metric, no_match_metric_val_cmd, + "no match metric <0-4294967295>", NO_STR MATCH_STR + "Match metric of route\n" + "Metric value\n") DEFUN (match_interface, match_interface_cmd, @@ -864,7 +787,7 @@ DEFUN (match_interface, "Match first hop interface of route\n" "Interface name\n") { - return eigrp_route_match_add (vty, vty->index, "interface", argv[0]); + return eigrp_route_match_add(vty, vty->index, "interface", argv[0]); } DEFUN (no_match_interface, @@ -874,19 +797,17 @@ DEFUN (no_match_interface, MATCH_STR "Match first hop interface of route\n") { - if (argc == 0) - return eigrp_route_match_delete (vty, vty->index, "interface", NULL); + if (argc == 0) + return eigrp_route_match_delete(vty, vty->index, "interface", + NULL); - return eigrp_route_match_delete (vty, vty->index, "interface", argv[0]); + return eigrp_route_match_delete(vty, vty->index, "interface", argv[0]); } -ALIAS (no_match_interface, - no_match_interface_val_cmd, - "no match interface WORD", - NO_STR - MATCH_STR - "Match first hop interface of route\n" - "Interface name\n") +ALIAS(no_match_interface, no_match_interface_val_cmd, "no match interface WORD", + NO_STR MATCH_STR + "Match first hop interface of route\n" + "Interface name\n") DEFUN (match_ip_next_hop, match_ip_next_hop_cmd, @@ -898,7 +819,7 @@ DEFUN (match_ip_next_hop, "IP access-list number (expanded range)\n" "IP Access-list name\n") { - return eigrp_route_match_add (vty, vty->index, "ip next-hop", argv[0]); + return eigrp_route_match_add(vty, vty->index, "ip next-hop", argv[0]); } DEFUN (no_match_ip_next_hop, @@ -909,22 +830,20 @@ DEFUN (no_match_ip_next_hop, IP_STR "Match next-hop address of route\n") { - if (argc == 0) - return eigrp_route_match_delete (vty, vty->index, "ip next-hop", NULL); + if (argc == 0) + return eigrp_route_match_delete(vty, vty->index, "ip next-hop", + NULL); - return eigrp_route_match_delete (vty, vty->index, "ip next-hop", argv[0]); + return eigrp_route_match_delete(vty, vty->index, "ip next-hop", + argv[0]); } -ALIAS (no_match_ip_next_hop, - no_match_ip_next_hop_val_cmd, - "no match ip next-hop (<1-199>|<1300-2699>|WORD)", - NO_STR - MATCH_STR - IP_STR - "Match next-hop address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" - "IP Access-list name\n") +ALIAS(no_match_ip_next_hop, no_match_ip_next_hop_val_cmd, + "no match ip next-hop (<1-199>|<1300-2699>|WORD)", NO_STR MATCH_STR IP_STR + "Match next-hop address of route\n" + "IP access-list number\n" + "IP access-list number (expanded range)\n" + "IP Access-list name\n") DEFUN (match_ip_next_hop_prefix_list, match_ip_next_hop_prefix_list_cmd, @@ -935,7 +854,8 @@ DEFUN (match_ip_next_hop_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - return eigrp_route_match_add (vty, vty->index, "ip next-hop prefix-list", argv[0]); + return eigrp_route_match_add(vty, vty->index, "ip next-hop prefix-list", + argv[0]); } DEFUN (no_match_ip_next_hop_prefix_list, @@ -947,21 +867,20 @@ DEFUN (no_match_ip_next_hop_prefix_list, "Match next-hop address of route\n" "Match entries of prefix-lists\n") { - if (argc == 0) - return eigrp_route_match_delete (vty, vty->index, "ip next-hop prefix-list", NULL); + if (argc == 0) + return eigrp_route_match_delete( + vty, vty->index, "ip next-hop prefix-list", NULL); - return eigrp_route_match_delete (vty, vty->index, "ip next-hop prefix-list", argv[0]); + return eigrp_route_match_delete(vty, vty->index, + "ip next-hop prefix-list", argv[0]); } -ALIAS (no_match_ip_next_hop_prefix_list, - no_match_ip_next_hop_prefix_list_val_cmd, - "no match ip next-hop prefix-list WORD", - NO_STR - MATCH_STR - IP_STR - "Match next-hop address of route\n" - "Match entries of prefix-lists\n" - "IP prefix-list name\n") +ALIAS(no_match_ip_next_hop_prefix_list, + no_match_ip_next_hop_prefix_list_val_cmd, + "no match ip next-hop prefix-list WORD", NO_STR MATCH_STR IP_STR + "Match next-hop address of route\n" + "Match entries of prefix-lists\n" + "IP prefix-list name\n") DEFUN (match_ip_address, match_ip_address_cmd, @@ -973,7 +892,7 @@ DEFUN (match_ip_address, "IP access-list number (expanded range)\n" "IP Access-list name\n") { - return eigrp_route_match_add (vty, vty->index, "ip address", argv[0]); + return eigrp_route_match_add(vty, vty->index, "ip address", argv[0]); } DEFUN (no_match_ip_address, @@ -984,22 +903,19 @@ DEFUN (no_match_ip_address, IP_STR "Match address of route\n") { - if (argc == 0) - return eigrp_route_match_delete (vty, vty->index, "ip address", NULL); + if (argc == 0) + return eigrp_route_match_delete(vty, vty->index, "ip address", + NULL); - return eigrp_route_match_delete (vty, vty->index, "ip address", argv[0]); + return eigrp_route_match_delete(vty, vty->index, "ip address", argv[0]); } -ALIAS (no_match_ip_address, - no_match_ip_address_val_cmd, - "no match ip address (<1-199>|<1300-2699>|WORD)", - NO_STR - MATCH_STR - IP_STR - "Match address of route\n" - "IP access-list number\n" - "IP access-list number (expanded range)\n" - "IP Access-list name\n") +ALIAS(no_match_ip_address, no_match_ip_address_val_cmd, + "no match ip address (<1-199>|<1300-2699>|WORD)", NO_STR MATCH_STR IP_STR + "Match address of route\n" + "IP access-list number\n" + "IP access-list number (expanded range)\n" + "IP Access-list name\n") DEFUN (match_ip_address_prefix_list, match_ip_address_prefix_list_cmd, @@ -1010,7 +926,8 @@ DEFUN (match_ip_address_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - return eigrp_route_match_add (vty, vty->index, "ip address prefix-list", argv[0]); + return eigrp_route_match_add(vty, vty->index, "ip address prefix-list", + argv[0]); } DEFUN (no_match_ip_address_prefix_list, @@ -1022,21 +939,19 @@ DEFUN (no_match_ip_address_prefix_list, "Match address of route\n" "Match entries of prefix-lists\n") { - if (argc == 0) - return eigrp_route_match_delete (vty, vty->index, "ip address prefix-list", NULL); + if (argc == 0) + return eigrp_route_match_delete(vty, vty->index, + "ip address prefix-list", NULL); - return eigrp_route_match_delete (vty, vty->index, "ip address prefix-list", argv[0]); + return eigrp_route_match_delete(vty, vty->index, + "ip address prefix-list", argv[0]); } -ALIAS (no_match_ip_address_prefix_list, - no_match_ip_address_prefix_list_val_cmd, - "no match ip address prefix-list WORD", - NO_STR - MATCH_STR - IP_STR - "Match address of route\n" - "Match entries of prefix-lists\n" - "IP prefix-list name\n") +ALIAS(no_match_ip_address_prefix_list, no_match_ip_address_prefix_list_val_cmd, + "no match ip address prefix-list WORD", NO_STR MATCH_STR IP_STR + "Match address of route\n" + "Match entries of prefix-lists\n" + "IP prefix-list name\n") DEFUN (match_tag, match_tag_cmd, @@ -1045,7 +960,7 @@ DEFUN (match_tag, "Match tag of route\n" "Metric value\n") { - return eigrp_route_match_add (vty, vty->index, "tag", argv[0]); + return eigrp_route_match_add(vty, vty->index, "tag", argv[0]); } DEFUN (no_match_tag, @@ -1055,19 +970,16 @@ DEFUN (no_match_tag, MATCH_STR "Match tag of route\n") { - if (argc == 0) - return eigrp_route_match_delete (vty, vty->index, "tag", NULL); + if (argc == 0) + return eigrp_route_match_delete(vty, vty->index, "tag", NULL); - return eigrp_route_match_delete (vty, vty->index, "tag", argv[0]); + return eigrp_route_match_delete(vty, vty->index, "tag", argv[0]); } -ALIAS (no_match_tag, - no_match_tag_val_cmd, - "no match tag <0-65535>", - NO_STR - MATCH_STR - "Match tag of route\n" - "Metric value\n") +ALIAS(no_match_tag, no_match_tag_val_cmd, "no match tag <0-65535>", + NO_STR MATCH_STR + "Match tag of route\n" + "Metric value\n") /* set functions */ @@ -1078,15 +990,12 @@ DEFUN (set_metric, "Metric value for destination routing protocol\n" "Metric value\n") { - return eigrp_route_set_add (vty, vty->index, "metric", argv[0]); + return eigrp_route_set_add(vty, vty->index, "metric", argv[0]); } -ALIAS (set_metric, - set_metric_addsub_cmd, - "set metric <+/-metric>", - SET_STR - "Metric value for destination routing protocol\n" - "Add or subtract metric\n") +ALIAS(set_metric, set_metric_addsub_cmd, "set metric <+/-metric>", SET_STR + "Metric value for destination routing protocol\n" + "Add or subtract metric\n") DEFUN (no_set_metric, no_set_metric_cmd, @@ -1095,20 +1004,17 @@ DEFUN (no_set_metric, SET_STR "Metric value for destination routing protocol\n") { - if (argc == 0) - return eigrp_route_set_delete (vty, vty->index, "metric", NULL); + if (argc == 0) + return eigrp_route_set_delete(vty, vty->index, "metric", NULL); - return eigrp_route_set_delete (vty, vty->index, "metric", argv[0]); + return eigrp_route_set_delete(vty, vty->index, "metric", argv[0]); } -ALIAS (no_set_metric, - no_set_metric_val_cmd, - "no set metric (<0-4294967295>|<+/-metric>)", - NO_STR - SET_STR - "Metric value for destination routing protocol\n" - "Metric value\n" - "Add or subtract metric\n") +ALIAS(no_set_metric, no_set_metric_val_cmd, + "no set metric (<0-4294967295>|<+/-metric>)", NO_STR SET_STR + "Metric value for destination routing protocol\n" + "Metric value\n" + "Add or subtract metric\n") DEFUN (set_ip_nexthop, set_ip_nexthop_cmd, @@ -1118,17 +1024,16 @@ DEFUN (set_ip_nexthop, "Next hop address\n" "IP address of next hop\n") { - union sockunion su; - int ret; + union sockunion su; + int ret; - ret = str2sockunion (argv[0], &su); - if (ret < 0) - { - vty_out (vty, "%% Malformed next-hop address\n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = str2sockunion(argv[0], &su); + if (ret < 0) { + vty_out(vty, "%% Malformed next-hop address\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return eigrp_route_set_add (vty, vty->index, "ip next-hop", argv[0]); + return eigrp_route_set_add(vty, vty->index, "ip next-hop", argv[0]); } DEFUN (no_set_ip_nexthop, @@ -1139,20 +1044,17 @@ DEFUN (no_set_ip_nexthop, IP_STR "Next hop address\n") { - if (argc == 0) - return eigrp_route_set_delete (vty, vty->index, "ip next-hop", NULL); + if (argc == 0) + return eigrp_route_set_delete(vty, vty->index, "ip next-hop", + NULL); - return eigrp_route_set_delete (vty, vty->index, "ip next-hop", argv[0]); + return eigrp_route_set_delete(vty, vty->index, "ip next-hop", argv[0]); } -ALIAS (no_set_ip_nexthop, - no_set_ip_nexthop_val_cmd, - "no set ip next-hop A.B.C.D", - NO_STR - SET_STR - IP_STR - "Next hop address\n" - "IP address of next hop\n") +ALIAS(no_set_ip_nexthop, no_set_ip_nexthop_val_cmd, + "no set ip next-hop A.B.C.D", NO_STR SET_STR IP_STR + "Next hop address\n" + "IP address of next hop\n") DEFUN (set_tag, set_tag_cmd, @@ -1161,7 +1063,7 @@ DEFUN (set_tag, "Tag value for routing protocol\n" "Tag value\n") { - return eigrp_route_set_add (vty, vty->index, "tag", argv[0]); + return eigrp_route_set_add(vty, vty->index, "tag", argv[0]); } DEFUN (no_set_tag, @@ -1171,72 +1073,69 @@ DEFUN (no_set_tag, SET_STR "Tag value for routing protocol\n") { - if (argc == 0) - return eigrp_route_set_delete (vty, vty->index, "tag", NULL); + if (argc == 0) + return eigrp_route_set_delete(vty, vty->index, "tag", NULL); - return eigrp_route_set_delete (vty, vty->index, "tag", argv[0]); + return eigrp_route_set_delete(vty, vty->index, "tag", argv[0]); } -ALIAS (no_set_tag, - no_set_tag_val_cmd, - "no set tag <0-65535>", - NO_STR - SET_STR - "Tag value for routing protocol\n" - "Tag value\n") +ALIAS(no_set_tag, no_set_tag_val_cmd, "no set tag <0-65535>", NO_STR SET_STR + "Tag value for routing protocol\n" + "Tag value\n") /* Route-map init */ -void -eigrp_route_map_init () +void eigrp_route_map_init() { - route_map_init (); - route_map_init_vty (); - route_map_add_hook (eigrp_route_map_update); - route_map_delete_hook (eigrp_route_map_update); - - /*route_map_install_match (&route_match_metric_cmd); - route_map_install_match (&route_match_interface_cmd);*/ - /*route_map_install_match (&route_match_ip_next_hop_cmd); - route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd); - route_map_install_match (&route_match_ip_address_cmd); - route_map_install_match (&route_match_ip_address_prefix_list_cmd);*/ - /*route_map_install_match (&route_match_tag_cmd);*/ - - /*route_map_install_set (&route_set_metric_cmd); - route_map_install_set (&route_set_ip_nexthop_cmd); - route_map_install_set (&route_set_tag_cmd);*/ - - /*install_element (RMAP_NODE, &route_match_metric_cmd); - install_element (RMAP_NODE, &no_match_metric_cmd); - install_element (RMAP_NODE, &no_match_metric_val_cmd); - install_element (RMAP_NODE, &route_match_interface_cmd); - install_element (RMAP_NODE, &no_match_interface_cmd); - install_element (RMAP_NODE, &no_match_interface_val_cmd); - install_element (RMAP_NODE, &route_match_ip_next_hop_cmd); - install_element (RMAP_NODE, &no_match_ip_next_hop_cmd); - install_element (RMAP_NODE, &no_match_ip_next_hop_val_cmd); - install_element (RMAP_NODE, &route_match_ip_next_hop_prefix_list_cmd); - install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd); - install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_val_cmd);*/ - /*install_element (RMAP_NODE, &route_match_ip_address_cmd); - install_element (RMAP_NODE, &no_match_ip_address_cmd); - install_element (RMAP_NODE, &no_match_ip_address_val_cmd); - install_element (RMAP_NODE, &route_match_ip_address_prefix_list_cmd); - install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd); - install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);*/ - /*install_element (RMAP_NODE, &route_match_tag_cmd); - install_element (RMAP_NODE, &no_match_tag_cmd); - install_element (RMAP_NODE, &no_match_tag_val_cmd);*/ - - /*install_element (RMAP_NODE, &set_metric_cmd); - install_element (RMAP_NODE, &set_metric_addsub_cmd); - install_element (RMAP_NODE, &no_set_metric_cmd); - install_element (RMAP_NODE, &no_set_metric_val_cmd); - install_element (RMAP_NODE, &set_ip_nexthop_cmd); - install_element (RMAP_NODE, &no_set_ip_nexthop_cmd); - install_element (RMAP_NODE, &no_set_ip_nexthop_val_cmd); - install_element (RMAP_NODE, &set_tag_cmd); - install_element (RMAP_NODE, &no_set_tag_cmd); - install_element (RMAP_NODE, &no_set_tag_val_cmd);*/ + route_map_init(); + route_map_init_vty(); + route_map_add_hook(eigrp_route_map_update); + route_map_delete_hook(eigrp_route_map_update); + + /*route_map_install_match (&route_match_metric_cmd); + route_map_install_match (&route_match_interface_cmd);*/ + /*route_map_install_match (&route_match_ip_next_hop_cmd); + route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd); + route_map_install_match (&route_match_ip_address_cmd); + route_map_install_match (&route_match_ip_address_prefix_list_cmd);*/ + /*route_map_install_match (&route_match_tag_cmd);*/ + + /*route_map_install_set (&route_set_metric_cmd); + route_map_install_set (&route_set_ip_nexthop_cmd); + route_map_install_set (&route_set_tag_cmd);*/ + + /*install_element (RMAP_NODE, &route_match_metric_cmd); + install_element (RMAP_NODE, &no_match_metric_cmd); + install_element (RMAP_NODE, &no_match_metric_val_cmd); + install_element (RMAP_NODE, &route_match_interface_cmd); + install_element (RMAP_NODE, &no_match_interface_cmd); + install_element (RMAP_NODE, &no_match_interface_val_cmd); + install_element (RMAP_NODE, &route_match_ip_next_hop_cmd); + install_element (RMAP_NODE, &no_match_ip_next_hop_cmd); + install_element (RMAP_NODE, &no_match_ip_next_hop_val_cmd); + install_element (RMAP_NODE, &route_match_ip_next_hop_prefix_list_cmd); + install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd); + install_element (RMAP_NODE, + &no_match_ip_next_hop_prefix_list_val_cmd);*/ + /*install_element (RMAP_NODE, &route_match_ip_address_cmd); + install_element (RMAP_NODE, &no_match_ip_address_cmd); + install_element (RMAP_NODE, &no_match_ip_address_val_cmd); + install_element (RMAP_NODE, &route_match_ip_address_prefix_list_cmd); + install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd); + install_element (RMAP_NODE, + &no_match_ip_address_prefix_list_val_cmd);*/ + /*install_element (RMAP_NODE, &route_match_tag_cmd); + install_element (RMAP_NODE, &no_match_tag_cmd); + install_element (RMAP_NODE, &no_match_tag_val_cmd);*/ + + /*install_element (RMAP_NODE, &set_metric_cmd); + install_element (RMAP_NODE, &set_metric_addsub_cmd); + install_element (RMAP_NODE, &no_set_metric_cmd); + install_element (RMAP_NODE, &no_set_metric_val_cmd); + install_element (RMAP_NODE, &set_ip_nexthop_cmd); + install_element (RMAP_NODE, &no_set_ip_nexthop_cmd); + install_element (RMAP_NODE, &no_set_ip_nexthop_val_cmd); + install_element (RMAP_NODE, &set_tag_cmd); + install_element (RMAP_NODE, &no_set_tag_cmd); + install_element (RMAP_NODE, &no_set_tag_val_cmd);*/ } diff --git a/eigrpd/eigrp_routemap.h b/eigrpd/eigrp_routemap.h index 0fee25b9a..f378d88cd 100644 --- a/eigrpd/eigrp_routemap.h +++ b/eigrpd/eigrp_routemap.h @@ -8,11 +8,11 @@ #ifndef EIGRPD_EIGRP_ROUTEMAP_H_ #define EIGRPD_EIGRP_ROUTEMAP_H_ -extern void eigrp_route_map_update (const char *); -extern void eigrp_route_map_init (); -extern void eigrp_if_rmap_update (struct if_rmap *); -extern void eigrp_if_rmap_update_interface (struct interface *); -extern void eigrp_routemap_update_redistribute (void); -extern void eigrp_rmap_update (const char *); +extern void eigrp_route_map_update(const char *); +extern void eigrp_route_map_init(); +extern void eigrp_if_rmap_update(struct if_rmap *); +extern void eigrp_if_rmap_update_interface(struct interface *); +extern void eigrp_routemap_update_redistribute(void); +extern void eigrp_rmap_update(const char *); #endif /* EIGRPD_EIGRP_ROUTEMAP_H_ */ diff --git a/eigrpd/eigrp_siaquery.c b/eigrpd/eigrp_siaquery.c index d521a57ba..f16f49a33 100644 --- a/eigrpd/eigrp_siaquery.c +++ b/eigrpd/eigrp_siaquery.c @@ -55,113 +55,109 @@ #include "eigrpd/eigrp_memory.h" /*EIGRP SIA-QUERY read function*/ -void -eigrp_siaquery_receive (struct eigrp *eigrp, struct ip *iph, struct eigrp_header *eigrph, - struct stream * s, struct eigrp_interface *ei, int size) +void eigrp_siaquery_receive(struct eigrp *eigrp, struct ip *iph, + struct eigrp_header *eigrph, struct stream *s, + struct eigrp_interface *ei, int size) { - struct eigrp_neighbor *nbr; - struct TLV_IPv4_Internal_type *tlv; - - u_int16_t type; - - /* increment statistics. */ - ei->siaQuery_in++; - - /* get neighbor struct */ - nbr = eigrp_nbr_get(ei, eigrph, iph); - - /* neighbor must be valid, eigrp_nbr_get creates if none existed */ - assert(nbr); - - nbr->recv_sequence_number = ntohl(eigrph->sequence); - - while (s->endp > s->getp) - { - type = stream_getw(s); - if (type == EIGRP_TLV_IPv4_INT) - { - struct prefix_ipv4 dest_addr; - - stream_set_getp(s, s->getp - sizeof(u_int16_t)); - - tlv = eigrp_read_ipv4_tlv(s); - - dest_addr.family = AFI_IP; - dest_addr.prefix = tlv->destination; - dest_addr.prefixlen = tlv->prefix_length; - struct eigrp_prefix_entry *dest = - eigrp_topology_table_lookup_ipv4(eigrp->topology_table, &dest_addr); - - /* If the destination exists (it should, but one never know)*/ - if (dest != NULL) - { - struct eigrp_fsm_action_message *msg; - msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct eigrp_fsm_action_message)); - struct eigrp_neighbor_entry *entry = - eigrp_prefix_entry_lookup(dest->entries, nbr); - msg->packet_type = EIGRP_OPC_SIAQUERY; - msg->eigrp = eigrp; - msg->data_type = EIGRP_TLV_IPv4_INT; - msg->adv_router = nbr; - msg->data.ipv4_int_type = tlv; - msg->entry = entry; - msg->prefix = dest; - int event = eigrp_get_fsm_event(msg); - eigrp_fsm_event(msg, event); - } - eigrp_IPv4_InternalTLV_free (tlv); - } - } - eigrp_hello_send_ack(nbr); + struct eigrp_neighbor *nbr; + struct TLV_IPv4_Internal_type *tlv; + + u_int16_t type; + + /* increment statistics. */ + ei->siaQuery_in++; + + /* get neighbor struct */ + nbr = eigrp_nbr_get(ei, eigrph, iph); + + /* neighbor must be valid, eigrp_nbr_get creates if none existed */ + assert(nbr); + + nbr->recv_sequence_number = ntohl(eigrph->sequence); + + while (s->endp > s->getp) { + type = stream_getw(s); + if (type == EIGRP_TLV_IPv4_INT) { + struct prefix_ipv4 dest_addr; + + stream_set_getp(s, s->getp - sizeof(u_int16_t)); + + tlv = eigrp_read_ipv4_tlv(s); + + dest_addr.family = AFI_IP; + dest_addr.prefix = tlv->destination; + dest_addr.prefixlen = tlv->prefix_length; + struct eigrp_prefix_entry *dest = + eigrp_topology_table_lookup_ipv4( + eigrp->topology_table, &dest_addr); + + /* If the destination exists (it should, but one never + * know)*/ + if (dest != NULL) { + struct eigrp_fsm_action_message *msg; + msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, + sizeof(struct + eigrp_fsm_action_message)); + struct eigrp_neighbor_entry *entry = + eigrp_prefix_entry_lookup(dest->entries, + nbr); + msg->packet_type = EIGRP_OPC_SIAQUERY; + msg->eigrp = eigrp; + msg->data_type = EIGRP_TLV_IPv4_INT; + msg->adv_router = nbr; + msg->data.ipv4_int_type = tlv; + msg->entry = entry; + msg->prefix = dest; + int event = eigrp_get_fsm_event(msg); + eigrp_fsm_event(msg, event); + } + eigrp_IPv4_InternalTLV_free(tlv); + } + } + eigrp_hello_send_ack(nbr); } -void -eigrp_send_siaquery (struct eigrp_neighbor *nbr, struct eigrp_prefix_entry *pe) +void eigrp_send_siaquery(struct eigrp_neighbor *nbr, + struct eigrp_prefix_entry *pe) { - struct eigrp_packet *ep; - u_int16_t length = EIGRP_HEADER_LEN; - - ep = eigrp_packet_new(nbr->ei->ifp->mtu); - - /* Prepare EIGRP INIT UPDATE header */ - eigrp_packet_header_init(EIGRP_OPC_SIAQUERY, nbr->ei, ep->s, 0, - nbr->ei->eigrp->sequence_number, 0); - - // encode Authentication TLV, if needed - if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && - (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL)) - { - length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei); - } - - length += eigrp_add_internalTLV_to_stream(ep->s, pe); - - if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && - (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL)) - { - eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_FLAG); - } - - /* EIGRP Checksum */ - eigrp_packet_checksum(nbr->ei, ep->s, length); - - ep->length = length; - ep->dst.s_addr = nbr->src.s_addr; - - /*This ack number we await from neighbor*/ - ep->sequence_number = nbr->ei->eigrp->sequence_number; - - if (nbr->state == EIGRP_NEIGHBOR_UP) - { - /*Put packet to retransmission queue*/ - eigrp_fifo_push_head(nbr->retrans_queue, ep); - - if (nbr->retrans_queue->count == 1) - { - eigrp_send_packet_reliably(nbr); - } - } - else - eigrp_packet_free(ep); + struct eigrp_packet *ep; + u_int16_t length = EIGRP_HEADER_LEN; + + ep = eigrp_packet_new(nbr->ei->ifp->mtu); + + /* Prepare EIGRP INIT UPDATE header */ + eigrp_packet_header_init(EIGRP_OPC_SIAQUERY, nbr->ei, ep->s, 0, + nbr->ei->eigrp->sequence_number, 0); + + // encode Authentication TLV, if needed + if ((IF_DEF_PARAMS(nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) + && (IF_DEF_PARAMS(nbr->ei->ifp)->auth_keychain != NULL)) { + length += eigrp_add_authTLV_MD5_to_stream(ep->s, nbr->ei); + } + + length += eigrp_add_internalTLV_to_stream(ep->s, pe); + + if ((IF_DEF_PARAMS(nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) + && (IF_DEF_PARAMS(nbr->ei->ifp)->auth_keychain != NULL)) { + eigrp_make_md5_digest(nbr->ei, ep->s, EIGRP_AUTH_UPDATE_FLAG); + } + + /* EIGRP Checksum */ + eigrp_packet_checksum(nbr->ei, ep->s, length); + + ep->length = length; + ep->dst.s_addr = nbr->src.s_addr; + + /*This ack number we await from neighbor*/ + ep->sequence_number = nbr->ei->eigrp->sequence_number; + + if (nbr->state == EIGRP_NEIGHBOR_UP) { + /*Put packet to retransmission queue*/ + eigrp_fifo_push_head(nbr->retrans_queue, ep); + + if (nbr->retrans_queue->count == 1) { + eigrp_send_packet_reliably(nbr); + } + } else + eigrp_packet_free(ep); } diff --git a/eigrpd/eigrp_siareply.c b/eigrpd/eigrp_siareply.c index dbf451800..9a768566d 100644 --- a/eigrpd/eigrp_siareply.c +++ b/eigrpd/eigrp_siareply.c @@ -54,115 +54,109 @@ #include "eigrpd/eigrp_memory.h" /*EIGRP SIA-REPLY read function*/ -void -eigrp_siareply_receive (struct eigrp *eigrp, struct ip *iph, struct eigrp_header *eigrph, - struct stream * s, struct eigrp_interface *ei, int size) +void eigrp_siareply_receive(struct eigrp *eigrp, struct ip *iph, + struct eigrp_header *eigrph, struct stream *s, + struct eigrp_interface *ei, int size) { - struct eigrp_neighbor *nbr; - struct TLV_IPv4_Internal_type *tlv; - - u_int16_t type; - - /* increment statistics. */ - ei->siaReply_in++; - - /* get neighbor struct */ - nbr = eigrp_nbr_get(ei, eigrph, iph); - - /* neighbor must be valid, eigrp_nbr_get creates if none existed */ - assert(nbr); - - nbr->recv_sequence_number = ntohl(eigrph->sequence); - - while (s->endp > s->getp) - { - type = stream_getw(s); - if (type == EIGRP_TLV_IPv4_INT) - { - struct prefix_ipv4 dest_addr; - - stream_set_getp(s, s->getp - sizeof(u_int16_t)); - - tlv = eigrp_read_ipv4_tlv(s); - - dest_addr.family = AFI_IP; - dest_addr.prefix = tlv->destination; - dest_addr.prefixlen = tlv->prefix_length; - struct eigrp_prefix_entry *dest = - eigrp_topology_table_lookup_ipv4(eigrp->topology_table, &dest_addr); - - /* If the destination exists (it should, but one never know)*/ - if (dest != NULL) - { - struct eigrp_fsm_action_message *msg; - msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct eigrp_fsm_action_message)); - struct eigrp_neighbor_entry *entry = - eigrp_prefix_entry_lookup(dest->entries, nbr); - msg->packet_type = EIGRP_OPC_SIAQUERY; - msg->eigrp = eigrp; - msg->data_type = EIGRP_TLV_IPv4_INT; - msg->adv_router = nbr; - msg->data.ipv4_int_type = tlv; - msg->entry = entry; - msg->prefix = dest; - int event = eigrp_get_fsm_event(msg); - eigrp_fsm_event(msg, event); - } - eigrp_IPv4_InternalTLV_free (tlv); - } - } - eigrp_hello_send_ack(nbr); + struct eigrp_neighbor *nbr; + struct TLV_IPv4_Internal_type *tlv; + + u_int16_t type; + + /* increment statistics. */ + ei->siaReply_in++; + + /* get neighbor struct */ + nbr = eigrp_nbr_get(ei, eigrph, iph); + + /* neighbor must be valid, eigrp_nbr_get creates if none existed */ + assert(nbr); + + nbr->recv_sequence_number = ntohl(eigrph->sequence); + + while (s->endp > s->getp) { + type = stream_getw(s); + if (type == EIGRP_TLV_IPv4_INT) { + struct prefix_ipv4 dest_addr; + + stream_set_getp(s, s->getp - sizeof(u_int16_t)); + + tlv = eigrp_read_ipv4_tlv(s); + + dest_addr.family = AFI_IP; + dest_addr.prefix = tlv->destination; + dest_addr.prefixlen = tlv->prefix_length; + struct eigrp_prefix_entry *dest = + eigrp_topology_table_lookup_ipv4( + eigrp->topology_table, &dest_addr); + + /* If the destination exists (it should, but one never + * know)*/ + if (dest != NULL) { + struct eigrp_fsm_action_message *msg; + msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, + sizeof(struct + eigrp_fsm_action_message)); + struct eigrp_neighbor_entry *entry = + eigrp_prefix_entry_lookup(dest->entries, + nbr); + msg->packet_type = EIGRP_OPC_SIAQUERY; + msg->eigrp = eigrp; + msg->data_type = EIGRP_TLV_IPv4_INT; + msg->adv_router = nbr; + msg->data.ipv4_int_type = tlv; + msg->entry = entry; + msg->prefix = dest; + int event = eigrp_get_fsm_event(msg); + eigrp_fsm_event(msg, event); + } + eigrp_IPv4_InternalTLV_free(tlv); + } + } + eigrp_hello_send_ack(nbr); } -void -eigrp_send_siareply (struct eigrp_neighbor *nbr, struct eigrp_prefix_entry *pe) +void eigrp_send_siareply(struct eigrp_neighbor *nbr, + struct eigrp_prefix_entry *pe) { - struct eigrp_packet *ep; - u_int16_t length = EIGRP_HEADER_LEN; - - ep = eigrp_packet_new(nbr->ei->ifp->mtu); - - /* Prepare EIGRP INIT UPDATE header */ - eigrp_packet_header_init(EIGRP_OPC_SIAREPLY, nbr->ei, ep->s, 0, - nbr->ei->eigrp->sequence_number, 0); - - // encode Authentication TLV, if needed - if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && - (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL)) - { - length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei); - } - - length += eigrp_add_internalTLV_to_stream(ep->s, pe); - - if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && - (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL)) - { - eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_FLAG); - } - - /* EIGRP Checksum */ - eigrp_packet_checksum(nbr->ei, ep->s, length); - - ep->length = length; - ep->dst.s_addr = nbr->src.s_addr; - - /*This ack number we await from neighbor*/ - ep->sequence_number = nbr->ei->eigrp->sequence_number; - - if (nbr->state == EIGRP_NEIGHBOR_UP) - { - /*Put packet to retransmission queue*/ - eigrp_fifo_push_head(nbr->retrans_queue, ep); - - if (nbr->retrans_queue->count == 1) - { - eigrp_send_packet_reliably(nbr); - } - } - else - eigrp_packet_free(ep); -} + struct eigrp_packet *ep; + u_int16_t length = EIGRP_HEADER_LEN; + + ep = eigrp_packet_new(nbr->ei->ifp->mtu); + + /* Prepare EIGRP INIT UPDATE header */ + eigrp_packet_header_init(EIGRP_OPC_SIAREPLY, nbr->ei, ep->s, 0, + nbr->ei->eigrp->sequence_number, 0); + + // encode Authentication TLV, if needed + if ((IF_DEF_PARAMS(nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) + && (IF_DEF_PARAMS(nbr->ei->ifp)->auth_keychain != NULL)) { + length += eigrp_add_authTLV_MD5_to_stream(ep->s, nbr->ei); + } + + length += eigrp_add_internalTLV_to_stream(ep->s, pe); + if ((IF_DEF_PARAMS(nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) + && (IF_DEF_PARAMS(nbr->ei->ifp)->auth_keychain != NULL)) { + eigrp_make_md5_digest(nbr->ei, ep->s, EIGRP_AUTH_UPDATE_FLAG); + } + /* EIGRP Checksum */ + eigrp_packet_checksum(nbr->ei, ep->s, length); + + ep->length = length; + ep->dst.s_addr = nbr->src.s_addr; + + /*This ack number we await from neighbor*/ + ep->sequence_number = nbr->ei->eigrp->sequence_number; + + if (nbr->state == EIGRP_NEIGHBOR_UP) { + /*Put packet to retransmission queue*/ + eigrp_fifo_push_head(nbr->retrans_queue, ep); + + if (nbr->retrans_queue->count == 1) { + eigrp_send_packet_reliably(nbr); + } + } else + eigrp_packet_free(ep); +} diff --git a/eigrpd/eigrp_snmp.c b/eigrpd/eigrp_snmp.c index 4b8d1bb39..5647476a6 100644 --- a/eigrpd/eigrp_snmp.c +++ b/eigrpd/eigrp_snmp.c @@ -68,7 +68,7 @@ SNMP_LOCAL_VARIABLES #define EIGRPMIB 1,3,6,1,4,1,9,9,449,1 /* EIGRP-MIB instances. */ -oid eigrp_oid [] = { EIGRPMIB }; +oid eigrp_oid[] = {EIGRPMIB}; /* EIGRP VPN entry */ #define EIGRPVPNID 1 @@ -166,1223 +166,1242 @@ oid eigrp_oid [] = { EIGRPMIB }; #define INTERFACEINDEXORZERO ASN_INTEGER #define UINTEGER ASN_UNSIGNED - - - /* Hook functions. */ -static u_char *eigrpVpnEntry (struct variable *, oid *, size_t *, - int, size_t *, WriteMethod **); -static u_char *eigrpTraffStatsEntry (struct variable *, oid *, size_t *, int, - size_t *, WriteMethod **); -static u_char *eigrpTopologyEntry (struct variable *, oid *, size_t *, - int, size_t *, WriteMethod **); -static u_char *eigrpPeerEntry (struct variable *, oid *, size_t *, int, - size_t *, WriteMethod **); -static u_char *eigrpInterfaceEntry (struct variable *, oid *, size_t *, int, - size_t *, WriteMethod **); - - -struct variable eigrp_variables[] = - { - /* EIGRP vpn variables */ - {EIGRPVPNID, INTEGER, NOACCESS, eigrpVpnEntry, - 4, {1, 1, 1, 1}}, - {EIGRPVPNNAME, STRING, RONLY, eigrpVpnEntry, - 4, {1, 1, 1, 2}}, - - /* EIGRP traffic stats variables */ - {EIGRPASNUMBER, UINTEGER, NOACCESS, eigrpTraffStatsEntry, - 4, {2, 1, 1, 1}}, - {EIGRPNBRCOUNT, UINTEGER, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 2}}, - {EIGRPHELLOSSENT, COUNTER, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 3}}, - {EIGRPHELLOSRCVD, COUNTER, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 4}}, - {EIGRPUPDATESSENT, COUNTER, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 5}}, - {EIGRPUPDATESRCVD, COUNTER, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 6}}, - {EIGRPQUERIESSENT, COUNTER, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 7}}, - {EIGRPQUERIESRCVD, COUNTER, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 8}}, - {EIGRPREPLIESSENT, COUNTER, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 9}}, - {EIGRPREPLIESRCVD, COUNTER, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 10}}, - {EIGRPACKSSENT, COUNTER, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 11}}, - {EIGRPACKSRCVD, COUNTER, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 12}}, - {EIGRPINPUTQHIGHMARK, INTEGER, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 13}}, - {EIGRPINPUTQDROPS, COUNTER, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 14}}, - {EIGRPSIAQUERIESSENT, COUNTER, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 15}}, - {EIGRPSIAQUERIESRCVD, COUNTER, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 16}}, - {EIGRPASROUTERIDTYPE, IPADDRESSTYPE, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 17}}, - {EIGRPASROUTERID, IPADDRESS, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 18}}, - {EIGRPTOPOROUTES, COUNTER, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 19}}, - {EIGRPHEADSERIAL, COUNTER, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 20}}, - {EIGRPNEXTSERIAL, COUNTER, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 21}}, - {EIGRPXMITPENDREPLIES, INTEGER, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 22}}, - {EIGRPXMITDUMMIES, COUNTER, RONLY, eigrpTraffStatsEntry, - 4, {2, 1, 1, 23}}, - - /* EIGRP topology variables */ - {EIGRPDESTNETTYPE, IPADDRESSTYPE, NOACCESS, eigrpTopologyEntry, - 4, {3, 1, 1, 1}}, - {EIGRPDESTNET, IPADDRESSPREFIXLEN, NOACCESS, eigrpTopologyEntry, - 4, {3, 1, 1, 2}}, - {EIGRPDESTNETPREFIXLEN, IPADDRESSTYPE, NOACCESS, eigrpTopologyEntry, - 4, {3, 1, 1, 4}}, - {EIGRPACTIVE, INTEGER, RONLY, eigrpTopologyEntry, - 4, {3, 1, 1, 5}}, - {EIGRPSTUCKINACTIVE, INTEGER, RONLY, eigrpTopologyEntry, - 4, {3, 1, 1, 6}}, - {EIGRPDESTSUCCESSORS, INTEGER, RONLY, eigrpTopologyEntry, - 4, {3, 1, 1, 7}}, - {EIGRPFDISTANCE, INTEGER, RONLY, eigrpTopologyEntry, - 4, {3, 1, 1, 8}}, - {EIGRPROUTEORIGINTYPE, STRING, RONLY, eigrpTopologyEntry, - 4, {3, 1, 1, 9}}, - {EIGRPROUTEORIGINADDRTYPE, IPADDRESSTYPE, RONLY, eigrpTopologyEntry, - 4, {3, 1, 1, 10}}, - {EIGRPROUTEORIGINADDR, IPADDRESS, RONLY, eigrpTopologyEntry, - 4, {3, 1, 1, 11}}, - {EIGRPNEXTHOPADDRESSTYPE, IPADDRESSTYPE, RONLY, eigrpTopologyEntry, - 4, {3, 1, 1, 12}}, - {EIGRPNEXTHOPADDRESS, IPADDRESS, RONLY, eigrpTopologyEntry, - 4, {3, 1, 1, 13}}, - {EIGRPNEXTHOPINTERFACE, STRING, RONLY, eigrpTopologyEntry, - 4, {3, 1, 1, 14}}, - {EIGRPDISTANCE, INTEGER, RONLY, eigrpTopologyEntry, - 4, {3, 1, 1, 15}}, - {EIGRPREPORTDISTANCE, INTEGER, RONLY, eigrpTopologyEntry, - 4, {3, 1, 1, 16}}, - - /* EIGRP peer variables */ - {EIGRPHANDLE, INTEGER, NOACCESS, eigrpPeerEntry, - 4, {4, 1, 1, 1}}, - {EIGRPPEERADDRTYPE, IPADDRESSTYPE, RONLY, eigrpPeerEntry, - 4, {4, 1, 1, 2}}, - {EIGRPPEERADDR, IPADDRESS, RONLY, eigrpPeerEntry, - 4, {4, 1, 1, 3}}, - {EIGRPPEERIFINDEX, INTERFACEINDEXORZERO, RONLY, eigrpPeerEntry, - 4, {4, 1, 1, 4}}, - {EIGRPHOLDTIME, INTEGER, RONLY, eigrpPeerEntry, - 4, {4, 1, 1, 5}}, - {EIGRPUPTIME, STRING, RONLY, eigrpPeerEntry, - 4, {4, 1, 1, 6}}, - {EIGRPSRTT, INTEGER, RONLY, eigrpPeerEntry, - 4, {4, 1, 1, 7}}, - {EIGRPRTO, INTEGER, RONLY, eigrpPeerEntry, - 4, {4, 1, 1, 8}}, - {EIGRPPKTSENQUEUED, INTEGER, RONLY, eigrpPeerEntry, - 4, {4, 1, 1, 9}}, - {EIGRPLASTSEQ, INTEGER, RONLY, eigrpPeerEntry, - 4, {4, 1, 1, 10}}, - {EIGRPVERSION, STRING, RONLY, eigrpPeerEntry, - 4, {4, 1, 1, 11}}, - {EIGRPRETRANS, COUNTER, RONLY, eigrpPeerEntry, - 4, {4, 1, 1, 12}}, - {EIGRPRETRIES, INTEGER, RONLY, eigrpPeerEntry, - 4, {4, 1, 1, 13}}, - - /* EIGRP interface variables */ - {EIGRPPEERCOUNT, GAUGE, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 3}}, - {EIGRPXMITRELIABLEQ, GAUGE, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 4}}, - {EIGRPXMITUNRELIABLEQ, GAUGE, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 5}}, - {EIGRPMEANSRTT, INTEGER, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 6}}, - {EIGRPPACINGRELIABLE, INTEGER, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 7}}, - {EIGRPPACINGUNRELIABLE, INTEGER, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 8}}, - {EIGRPMFLOWTIMER, INTEGER, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 9}}, - {EIGRPPENDINGROUTES, GAUGE, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 10}}, - {EIGRPHELLOINTERVAL, INTEGER, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 11}}, - {EIGRPXMITNEXTSERIAL, COUNTER, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 12}}, - {EIGRPUMCASTS, COUNTER, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 13}}, - {EIGRPRMCASTS, COUNTER, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 14}}, - {EIGRPUUCASTS, COUNTER, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 15}}, - {EIGRPRUCASTS, COUNTER, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 16}}, - {EIGRPMCASTEXCEPTS, COUNTER, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 17}}, - {EIGRPCRPKTS, COUNTER, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 18}}, - {EIGRPACKSSUPPRESSED, COUNTER, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 19}}, - {EIGRPRETRANSSENT, COUNTER, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 20}}, - {EIGRPOOSRCVD, COUNTER, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 21}}, - {EIGRPAUTHMODE, INTEGER, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 22}}, - {EIGRPAUTHKEYCHAIN, STRING, RONLY, eigrpInterfaceEntry, - 4, {5, 1, 1, 23}} -}; - -static struct eigrp_neighbor * -eigrp_snmp_nbr_lookup (struct eigrp *eigrp, struct in_addr *nbr_addr, - unsigned int *ifindex) +static u_char *eigrpVpnEntry(struct variable *, oid *, size_t *, int, size_t *, + WriteMethod **); +static u_char *eigrpTraffStatsEntry(struct variable *, oid *, size_t *, int, + size_t *, WriteMethod **); +static u_char *eigrpTopologyEntry(struct variable *, oid *, size_t *, int, + size_t *, WriteMethod **); +static u_char *eigrpPeerEntry(struct variable *, oid *, size_t *, int, size_t *, + WriteMethod **); +static u_char *eigrpInterfaceEntry(struct variable *, oid *, size_t *, int, + size_t *, WriteMethod **); + + +struct variable eigrp_variables[] = { + /* EIGRP vpn variables */ + {EIGRPVPNID, INTEGER, NOACCESS, eigrpVpnEntry, 4, {1, 1, 1, 1}}, + {EIGRPVPNNAME, STRING, RONLY, eigrpVpnEntry, 4, {1, 1, 1, 2}}, + + /* EIGRP traffic stats variables */ + {EIGRPASNUMBER, + UINTEGER, + NOACCESS, + eigrpTraffStatsEntry, + 4, + {2, 1, 1, 1}}, + {EIGRPNBRCOUNT, UINTEGER, RONLY, eigrpTraffStatsEntry, 4, {2, 1, 1, 2}}, + {EIGRPHELLOSSENT, + COUNTER, + RONLY, + eigrpTraffStatsEntry, + 4, + {2, 1, 1, 3}}, + {EIGRPHELLOSRCVD, + COUNTER, + RONLY, + eigrpTraffStatsEntry, + 4, + {2, 1, 1, 4}}, + {EIGRPUPDATESSENT, + COUNTER, + RONLY, + eigrpTraffStatsEntry, + 4, + {2, 1, 1, 5}}, + {EIGRPUPDATESRCVD, + COUNTER, + RONLY, + eigrpTraffStatsEntry, + 4, + {2, 1, 1, 6}}, + {EIGRPQUERIESSENT, + COUNTER, + RONLY, + eigrpTraffStatsEntry, + 4, + {2, 1, 1, 7}}, + {EIGRPQUERIESRCVD, + COUNTER, + RONLY, + eigrpTraffStatsEntry, + 4, + {2, 1, 1, 8}}, + {EIGRPREPLIESSENT, + COUNTER, + RONLY, + eigrpTraffStatsEntry, + 4, + {2, 1, 1, 9}}, + {EIGRPREPLIESRCVD, + COUNTER, + RONLY, + eigrpTraffStatsEntry, + 4, + {2, 1, 1, 10}}, + {EIGRPACKSSENT, COUNTER, RONLY, eigrpTraffStatsEntry, 4, {2, 1, 1, 11}}, + {EIGRPACKSRCVD, COUNTER, RONLY, eigrpTraffStatsEntry, 4, {2, 1, 1, 12}}, + {EIGRPINPUTQHIGHMARK, + INTEGER, + RONLY, + eigrpTraffStatsEntry, + 4, + {2, 1, 1, 13}}, + {EIGRPINPUTQDROPS, + COUNTER, + RONLY, + eigrpTraffStatsEntry, + 4, + {2, 1, 1, 14}}, + {EIGRPSIAQUERIESSENT, + COUNTER, + RONLY, + eigrpTraffStatsEntry, + 4, + {2, 1, 1, 15}}, + {EIGRPSIAQUERIESRCVD, + COUNTER, + RONLY, + eigrpTraffStatsEntry, + 4, + {2, 1, 1, 16}}, + {EIGRPASROUTERIDTYPE, + IPADDRESSTYPE, + RONLY, + eigrpTraffStatsEntry, + 4, + {2, 1, 1, 17}}, + {EIGRPASROUTERID, + IPADDRESS, + RONLY, + eigrpTraffStatsEntry, + 4, + {2, 1, 1, 18}}, + {EIGRPTOPOROUTES, + COUNTER, + RONLY, + eigrpTraffStatsEntry, + 4, + {2, 1, 1, 19}}, + {EIGRPHEADSERIAL, + COUNTER, + RONLY, + eigrpTraffStatsEntry, + 4, + {2, 1, 1, 20}}, + {EIGRPNEXTSERIAL, + COUNTER, + RONLY, + eigrpTraffStatsEntry, + 4, + {2, 1, 1, 21}}, + {EIGRPXMITPENDREPLIES, + INTEGER, + RONLY, + eigrpTraffStatsEntry, + 4, + {2, 1, 1, 22}}, + {EIGRPXMITDUMMIES, + COUNTER, + RONLY, + eigrpTraffStatsEntry, + 4, + {2, 1, 1, 23}}, + + /* EIGRP topology variables */ + {EIGRPDESTNETTYPE, + IPADDRESSTYPE, + NOACCESS, + eigrpTopologyEntry, + 4, + {3, 1, 1, 1}}, + {EIGRPDESTNET, + IPADDRESSPREFIXLEN, + NOACCESS, + eigrpTopologyEntry, + 4, + {3, 1, 1, 2}}, + {EIGRPDESTNETPREFIXLEN, + IPADDRESSTYPE, + NOACCESS, + eigrpTopologyEntry, + 4, + {3, 1, 1, 4}}, + {EIGRPACTIVE, INTEGER, RONLY, eigrpTopologyEntry, 4, {3, 1, 1, 5}}, + {EIGRPSTUCKINACTIVE, + INTEGER, + RONLY, + eigrpTopologyEntry, + 4, + {3, 1, 1, 6}}, + {EIGRPDESTSUCCESSORS, + INTEGER, + RONLY, + eigrpTopologyEntry, + 4, + {3, 1, 1, 7}}, + {EIGRPFDISTANCE, INTEGER, RONLY, eigrpTopologyEntry, 4, {3, 1, 1, 8}}, + {EIGRPROUTEORIGINTYPE, + STRING, + RONLY, + eigrpTopologyEntry, + 4, + {3, 1, 1, 9}}, + {EIGRPROUTEORIGINADDRTYPE, + IPADDRESSTYPE, + RONLY, + eigrpTopologyEntry, + 4, + {3, 1, 1, 10}}, + {EIGRPROUTEORIGINADDR, + IPADDRESS, + RONLY, + eigrpTopologyEntry, + 4, + {3, 1, 1, 11}}, + {EIGRPNEXTHOPADDRESSTYPE, + IPADDRESSTYPE, + RONLY, + eigrpTopologyEntry, + 4, + {3, 1, 1, 12}}, + {EIGRPNEXTHOPADDRESS, + IPADDRESS, + RONLY, + eigrpTopologyEntry, + 4, + {3, 1, 1, 13}}, + {EIGRPNEXTHOPINTERFACE, + STRING, + RONLY, + eigrpTopologyEntry, + 4, + {3, 1, 1, 14}}, + {EIGRPDISTANCE, INTEGER, RONLY, eigrpTopologyEntry, 4, {3, 1, 1, 15}}, + {EIGRPREPORTDISTANCE, + INTEGER, + RONLY, + eigrpTopologyEntry, + 4, + {3, 1, 1, 16}}, + + /* EIGRP peer variables */ + {EIGRPHANDLE, INTEGER, NOACCESS, eigrpPeerEntry, 4, {4, 1, 1, 1}}, + {EIGRPPEERADDRTYPE, + IPADDRESSTYPE, + RONLY, + eigrpPeerEntry, + 4, + {4, 1, 1, 2}}, + {EIGRPPEERADDR, IPADDRESS, RONLY, eigrpPeerEntry, 4, {4, 1, 1, 3}}, + {EIGRPPEERIFINDEX, + INTERFACEINDEXORZERO, + RONLY, + eigrpPeerEntry, + 4, + {4, 1, 1, 4}}, + {EIGRPHOLDTIME, INTEGER, RONLY, eigrpPeerEntry, 4, {4, 1, 1, 5}}, + {EIGRPUPTIME, STRING, RONLY, eigrpPeerEntry, 4, {4, 1, 1, 6}}, + {EIGRPSRTT, INTEGER, RONLY, eigrpPeerEntry, 4, {4, 1, 1, 7}}, + {EIGRPRTO, INTEGER, RONLY, eigrpPeerEntry, 4, {4, 1, 1, 8}}, + {EIGRPPKTSENQUEUED, INTEGER, RONLY, eigrpPeerEntry, 4, {4, 1, 1, 9}}, + {EIGRPLASTSEQ, INTEGER, RONLY, eigrpPeerEntry, 4, {4, 1, 1, 10}}, + {EIGRPVERSION, STRING, RONLY, eigrpPeerEntry, 4, {4, 1, 1, 11}}, + {EIGRPRETRANS, COUNTER, RONLY, eigrpPeerEntry, 4, {4, 1, 1, 12}}, + {EIGRPRETRIES, INTEGER, RONLY, eigrpPeerEntry, 4, {4, 1, 1, 13}}, + + /* EIGRP interface variables */ + {EIGRPPEERCOUNT, GAUGE, RONLY, eigrpInterfaceEntry, 4, {5, 1, 1, 3}}, + {EIGRPXMITRELIABLEQ, + GAUGE, + RONLY, + eigrpInterfaceEntry, + 4, + {5, 1, 1, 4}}, + {EIGRPXMITUNRELIABLEQ, + GAUGE, + RONLY, + eigrpInterfaceEntry, + 4, + {5, 1, 1, 5}}, + {EIGRPMEANSRTT, INTEGER, RONLY, eigrpInterfaceEntry, 4, {5, 1, 1, 6}}, + {EIGRPPACINGRELIABLE, + INTEGER, + RONLY, + eigrpInterfaceEntry, + 4, + {5, 1, 1, 7}}, + {EIGRPPACINGUNRELIABLE, + INTEGER, + RONLY, + eigrpInterfaceEntry, + 4, + {5, 1, 1, 8}}, + {EIGRPMFLOWTIMER, INTEGER, RONLY, eigrpInterfaceEntry, 4, {5, 1, 1, 9}}, + {EIGRPPENDINGROUTES, + GAUGE, + RONLY, + eigrpInterfaceEntry, + 4, + {5, 1, 1, 10}}, + {EIGRPHELLOINTERVAL, + INTEGER, + RONLY, + eigrpInterfaceEntry, + 4, + {5, 1, 1, 11}}, + {EIGRPXMITNEXTSERIAL, + COUNTER, + RONLY, + eigrpInterfaceEntry, + 4, + {5, 1, 1, 12}}, + {EIGRPUMCASTS, COUNTER, RONLY, eigrpInterfaceEntry, 4, {5, 1, 1, 13}}, + {EIGRPRMCASTS, COUNTER, RONLY, eigrpInterfaceEntry, 4, {5, 1, 1, 14}}, + {EIGRPUUCASTS, COUNTER, RONLY, eigrpInterfaceEntry, 4, {5, 1, 1, 15}}, + {EIGRPRUCASTS, COUNTER, RONLY, eigrpInterfaceEntry, 4, {5, 1, 1, 16}}, + {EIGRPMCASTEXCEPTS, + COUNTER, + RONLY, + eigrpInterfaceEntry, + 4, + {5, 1, 1, 17}}, + {EIGRPCRPKTS, COUNTER, RONLY, eigrpInterfaceEntry, 4, {5, 1, 1, 18}}, + {EIGRPACKSSUPPRESSED, + COUNTER, + RONLY, + eigrpInterfaceEntry, + 4, + {5, 1, 1, 19}}, + {EIGRPRETRANSSENT, + COUNTER, + RONLY, + eigrpInterfaceEntry, + 4, + {5, 1, 1, 20}}, + {EIGRPOOSRCVD, COUNTER, RONLY, eigrpInterfaceEntry, 4, {5, 1, 1, 21}}, + {EIGRPAUTHMODE, INTEGER, RONLY, eigrpInterfaceEntry, 4, {5, 1, 1, 22}}, + {EIGRPAUTHKEYCHAIN, + STRING, + RONLY, + eigrpInterfaceEntry, + 4, + {5, 1, 1, 23}}}; + +static struct eigrp_neighbor *eigrp_snmp_nbr_lookup(struct eigrp *eigrp, + struct in_addr *nbr_addr, + unsigned int *ifindex) { - struct listnode *node, *nnode, *node2, *nnode2; - struct eigrp_interface *ei; - struct eigrp_neighbor *nbr; - - for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei)) - { - for (ALL_LIST_ELEMENTS (ei->nbrs, node2, nnode2, nbr)) - { - if (IPV4_ADDR_SAME (&nbr->src, nbr_addr)) - { - return nbr; - } - } - } - return NULL; + struct listnode *node, *nnode, *node2, *nnode2; + struct eigrp_interface *ei; + struct eigrp_neighbor *nbr; + + for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, ei)) { + for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) { + if (IPV4_ADDR_SAME(&nbr->src, nbr_addr)) { + return nbr; + } + } + } + return NULL; } static struct eigrp_neighbor * -eigrp_snmp_nbr_lookup_next (struct in_addr *nbr_addr, unsigned int *ifindex, - int first) +eigrp_snmp_nbr_lookup_next(struct in_addr *nbr_addr, unsigned int *ifindex, + int first) { - struct listnode *node, *nnode, *node2, *nnode2; - struct eigrp_interface *ei; - struct eigrp_neighbor *nbr; - struct route_node *rn; - struct eigrp_neighbor *min = NULL; - struct eigrp *eigrp = eigrp; - - eigrp = eigrp_lookup (); - - for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei)) - { - for (ALL_LIST_ELEMENTS (ei->nbrs, node2, nnode2, nbr)) - { - if (first) - { - if (! min) - min = nbr; - else if (ntohl (nbr->src.s_addr) < ntohl (min->src.s_addr)) - min = nbr; - } - else if (ntohl (nbr->src.s_addr) > ntohl (nbr_addr->s_addr)) - { - if (! min) - min = nbr; - else if (ntohl (nbr->src.s_addr) < ntohl (min->src.s_addr)) - min = nbr; - } - } - } - if (min) - { - *nbr_addr = min->src; - *ifindex = 0; - return min; - } - return NULL; + struct listnode *node, *nnode, *node2, *nnode2; + struct eigrp_interface *ei; + struct eigrp_neighbor *nbr; + struct route_node *rn; + struct eigrp_neighbor *min = NULL; + struct eigrp *eigrp = eigrp; + + eigrp = eigrp_lookup(); + + for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, ei)) { + for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) { + if (first) { + if (!min) + min = nbr; + else if (ntohl(nbr->src.s_addr) + < ntohl(min->src.s_addr)) + min = nbr; + } else if (ntohl(nbr->src.s_addr) + > ntohl(nbr_addr->s_addr)) { + if (!min) + min = nbr; + else if (ntohl(nbr->src.s_addr) + < ntohl(min->src.s_addr)) + min = nbr; + } + } + } + if (min) { + *nbr_addr = min->src; + *ifindex = 0; + return min; + } + return NULL; } -static struct eigrp_neighbor * -eigrpNbrLookup (struct variable *v, oid *name, size_t *length, - struct in_addr *nbr_addr, unsigned int *ifindex, int exact) +static struct eigrp_neighbor *eigrpNbrLookup(struct variable *v, oid *name, + size_t *length, + struct in_addr *nbr_addr, + unsigned int *ifindex, int exact) { - unsigned int len; - int first; - struct eigrp_neighbor *nbr; - struct eigrp *eigrp; - - eigrp = eigrp_lookup (); - - if (! eigrp) - return NULL; - - if (exact) - { - if (*length != v->namelen + IN_ADDR_SIZE + 1) - return NULL; - - oid2in_addr (name + v->namelen, IN_ADDR_SIZE, nbr_addr); - *ifindex = name[v->namelen + IN_ADDR_SIZE]; - - return eigrp_snmp_nbr_lookup (eigrp, nbr_addr, ifindex); - } - else - { - first = 0; - len = *length - v->namelen; - - if (len <= 0) - first = 1; - - if (len > IN_ADDR_SIZE) - len = IN_ADDR_SIZE; - - oid2in_addr (name + v->namelen, len, nbr_addr); - - len = *length - v->namelen - IN_ADDR_SIZE; - if (len >= 1) - *ifindex = name[v->namelen + IN_ADDR_SIZE]; - - nbr = eigrp_snmp_nbr_lookup_next (nbr_addr, ifindex, first); - - if (nbr) - { - *length = v->namelen + IN_ADDR_SIZE + 1; - oid_copy_addr (name + v->namelen, nbr_addr, IN_ADDR_SIZE); - name[v->namelen + IN_ADDR_SIZE] = *ifindex; - return nbr; - } - } - return NULL; + unsigned int len; + int first; + struct eigrp_neighbor *nbr; + struct eigrp *eigrp; + + eigrp = eigrp_lookup(); + + if (!eigrp) + return NULL; + + if (exact) { + if (*length != v->namelen + IN_ADDR_SIZE + 1) + return NULL; + + oid2in_addr(name + v->namelen, IN_ADDR_SIZE, nbr_addr); + *ifindex = name[v->namelen + IN_ADDR_SIZE]; + + return eigrp_snmp_nbr_lookup(eigrp, nbr_addr, ifindex); + } else { + first = 0; + len = *length - v->namelen; + + if (len <= 0) + first = 1; + + if (len > IN_ADDR_SIZE) + len = IN_ADDR_SIZE; + + oid2in_addr(name + v->namelen, len, nbr_addr); + + len = *length - v->namelen - IN_ADDR_SIZE; + if (len >= 1) + *ifindex = name[v->namelen + IN_ADDR_SIZE]; + + nbr = eigrp_snmp_nbr_lookup_next(nbr_addr, ifindex, first); + + if (nbr) { + *length = v->namelen + IN_ADDR_SIZE + 1; + oid_copy_addr(name + v->namelen, nbr_addr, + IN_ADDR_SIZE); + name[v->namelen + IN_ADDR_SIZE] = *ifindex; + return nbr; + } + } + return NULL; } -static u_char * -eigrpVpnEntry (struct variable *v, oid *name, size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *eigrpVpnEntry(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - struct eigrp *eigrp; - - eigrp = eigrp_lookup (); - - /* Check whether the instance identifier is valid */ - if (smux_header_generic (v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - /* Return the current value of the variable */ - switch (v->magic) - { - case EIGRPVPNID: /* 1 */ - /* The unique VPN identifier */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPVPNNAME: /* 2 */ - /* The name given to the VPN */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - default: - return NULL; - } - return NULL; + struct eigrp *eigrp; + + eigrp = eigrp_lookup(); + + /* Check whether the instance identifier is valid */ + if (smux_header_generic(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + /* Return the current value of the variable */ + switch (v->magic) { + case EIGRPVPNID: /* 1 */ + /* The unique VPN identifier */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPVPNNAME: /* 2 */ + /* The name given to the VPN */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + default: + return NULL; + } + return NULL; } -static uint32_t -eigrp_neighbor_count(struct eigrp *eigrp) +static uint32_t eigrp_neighbor_count(struct eigrp *eigrp) { - uint32_t count; - struct eigrp_interface *ei; - struct listnode *node, *node2, *nnode2; - struct eigrp_neighbor *nbr; - - if (eigrp == NULL) - { - return 0; - } - - count = 0; - for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei)) - { - for (ALL_LIST_ELEMENTS (ei->nbrs, node2, nnode2, nbr)) - { - if (nbr->state == EIGRP_NEIGHBOR_UP) - count++; - } - } - - return count; + uint32_t count; + struct eigrp_interface *ei; + struct listnode *node, *node2, *nnode2; + struct eigrp_neighbor *nbr; + + if (eigrp == NULL) { + return 0; + } + + count = 0; + for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) { + for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) { + if (nbr->state == EIGRP_NEIGHBOR_UP) + count++; + } + } + + return count; } -static u_char * -eigrpTraffStatsEntry (struct variable *v, oid *name, size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *eigrpTraffStatsEntry(struct variable *v, oid *name, + size_t *length, int exact, size_t *var_len, + WriteMethod **write_method) { - struct eigrp *eigrp; - struct eigrp_interface *ei; - struct listnode *node, *nnode; - int counter; - - eigrp = eigrp_lookup (); - - /* Check whether the instance identifier is valid */ - if (smux_header_generic (v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - /* Return the current value of the variable */ - switch (v->magic) - { - case EIGRPASNUMBER: /* 1 */ - /* AS-number of this EIGRP instance. */ - if (eigrp) - return SNMP_INTEGER (eigrp->AS); - else - return SNMP_INTEGER (0); - break; - case EIGRPNBRCOUNT: /* 2 */ - /* Neighbor count of this EIGRP instance */ - if (eigrp) - return SNMP_INTEGER (eigrp_neighbor_count (eigrp)); - else - return SNMP_INTEGER (0); - break; - case EIGRPHELLOSSENT: /* 3 */ - /* Hello packets output count */ - if (eigrp) - { - counter = 0; - for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei)) - { - counter += ei->hello_out; - } - return SNMP_INTEGER (counter); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPHELLOSRCVD: /* 4 */ - /* Hello packets input count */ - if (eigrp) - { - counter = 0; - for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei)) - { - counter += ei->hello_in; - } - return SNMP_INTEGER (counter); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPUPDATESSENT: /* 5 */ - /* Update packets output count */ - if (eigrp) - { - counter = 0; - for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei)) - { - counter += ei->update_out; - } - return SNMP_INTEGER (counter); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPUPDATESRCVD: /* 6 */ - /* Update packets input count */ - if (eigrp) - { - counter = 0; - for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei)) - { - counter += ei->update_in; - } - return SNMP_INTEGER (counter); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPQUERIESSENT: /* 7 */ - /* Querry packets output count */ - if (eigrp) - { - counter = 0; - for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei)) - { - counter += ei->query_out; - } - return SNMP_INTEGER (counter); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPQUERIESRCVD: /* 8 */ - /* Querry packets input count */ - if (eigrp) - { - counter = 0; - for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei)) - { - counter += ei->query_in; - } - return SNMP_INTEGER (counter); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPREPLIESSENT: /* 9 */ - /* Reply packets output count */ - if (eigrp) - { - counter = 0; - for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei)) - { - counter += ei->reply_out; - } - return SNMP_INTEGER (counter); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPREPLIESRCVD: /* 10 */ - /* Reply packets input count */ - if (eigrp) - { - counter = 0; - for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei)) - { - counter += ei->reply_in; - } - return SNMP_INTEGER (counter); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPACKSSENT: /* 11 */ - /* Acknowledgement packets output count */ - if (eigrp) - { - counter = 0; - for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei)) - { - counter += ei->ack_out; - } - return SNMP_INTEGER (counter); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPACKSRCVD: /* 12 */ - /* Acknowledgement packets input count */ - if (eigrp) - { - counter = 0; - for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei)) - { - counter += ei->ack_in; - } - return SNMP_INTEGER (counter); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPINPUTQHIGHMARK: /* 13 */ - /* The highest number of EIGRP packets in the input queue */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPINPUTQDROPS: /* 14 */ - /* The number of EIGRP packets dropped from the input queue */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPSIAQUERIESSENT: /* 15 */ - /* SIA querry packets output count */ - if (eigrp) - { - counter = 0; - for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei)) - { - counter += ei->siaQuery_out; - } - return SNMP_INTEGER (counter); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPSIAQUERIESRCVD: /* 16 */ - /* SIA querry packets input count */ - if (eigrp) - { - counter = 0; - for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei)) - { - counter += ei->siaQuery_in; - } - return SNMP_INTEGER (counter); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPASROUTERIDTYPE: /* 17 */ - /* Whether the router ID is set manually or automatically */ - if (eigrp) - if(eigrp->router_id_static!=0) - return SNMP_INTEGER(1); - else - return SNMP_INTEGER(1); - else - return SNMP_INTEGER (0); - break; - case EIGRPASROUTERID: /* 18 */ - /* Router ID for this EIGRP AS */ - if (eigrp) - if(eigrp->router_id_static!=0) - return SNMP_INTEGER (eigrp->router_id_static); - else - return SNMP_INTEGER (eigrp->router_id); - else - return SNMP_INTEGER (0); - break; - case EIGRPTOPOROUTES: /* 19 */ - /* The total number of EIGRP derived routes currently existing - in the topology table for the AS */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPHEADSERIAL: /* 20 */ - /* The serial number of the first route in the internal - sequence for an AS*/ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPNEXTSERIAL: /* 21 */ - /* The serial number that would be assigned to the next new - or changed route in the topology table for the AS*/ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPXMITPENDREPLIES: /* 22 */ - /* Total number of outstanding replies expected to queries - that have been sent to peers in the current AS*/ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPXMITDUMMIES: /* 23 */ - /* Total number of currently existing dummies associated with the AS*/ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - default: - return NULL; - } - return NULL; + struct eigrp *eigrp; + struct eigrp_interface *ei; + struct listnode *node, *nnode; + int counter; + + eigrp = eigrp_lookup(); + + /* Check whether the instance identifier is valid */ + if (smux_header_generic(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + /* Return the current value of the variable */ + switch (v->magic) { + case EIGRPASNUMBER: /* 1 */ + /* AS-number of this EIGRP instance. */ + if (eigrp) + return SNMP_INTEGER(eigrp->AS); + else + return SNMP_INTEGER(0); + break; + case EIGRPNBRCOUNT: /* 2 */ + /* Neighbor count of this EIGRP instance */ + if (eigrp) + return SNMP_INTEGER(eigrp_neighbor_count(eigrp)); + else + return SNMP_INTEGER(0); + break; + case EIGRPHELLOSSENT: /* 3 */ + /* Hello packets output count */ + if (eigrp) { + counter = 0; + for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, + ei)) { + counter += ei->hello_out; + } + return SNMP_INTEGER(counter); + } else + return SNMP_INTEGER(0); + break; + case EIGRPHELLOSRCVD: /* 4 */ + /* Hello packets input count */ + if (eigrp) { + counter = 0; + for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, + ei)) { + counter += ei->hello_in; + } + return SNMP_INTEGER(counter); + } else + return SNMP_INTEGER(0); + break; + case EIGRPUPDATESSENT: /* 5 */ + /* Update packets output count */ + if (eigrp) { + counter = 0; + for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, + ei)) { + counter += ei->update_out; + } + return SNMP_INTEGER(counter); + } else + return SNMP_INTEGER(0); + break; + case EIGRPUPDATESRCVD: /* 6 */ + /* Update packets input count */ + if (eigrp) { + counter = 0; + for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, + ei)) { + counter += ei->update_in; + } + return SNMP_INTEGER(counter); + } else + return SNMP_INTEGER(0); + break; + case EIGRPQUERIESSENT: /* 7 */ + /* Querry packets output count */ + if (eigrp) { + counter = 0; + for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, + ei)) { + counter += ei->query_out; + } + return SNMP_INTEGER(counter); + } else + return SNMP_INTEGER(0); + break; + case EIGRPQUERIESRCVD: /* 8 */ + /* Querry packets input count */ + if (eigrp) { + counter = 0; + for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, + ei)) { + counter += ei->query_in; + } + return SNMP_INTEGER(counter); + } else + return SNMP_INTEGER(0); + break; + case EIGRPREPLIESSENT: /* 9 */ + /* Reply packets output count */ + if (eigrp) { + counter = 0; + for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, + ei)) { + counter += ei->reply_out; + } + return SNMP_INTEGER(counter); + } else + return SNMP_INTEGER(0); + break; + case EIGRPREPLIESRCVD: /* 10 */ + /* Reply packets input count */ + if (eigrp) { + counter = 0; + for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, + ei)) { + counter += ei->reply_in; + } + return SNMP_INTEGER(counter); + } else + return SNMP_INTEGER(0); + break; + case EIGRPACKSSENT: /* 11 */ + /* Acknowledgement packets output count */ + if (eigrp) { + counter = 0; + for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, + ei)) { + counter += ei->ack_out; + } + return SNMP_INTEGER(counter); + } else + return SNMP_INTEGER(0); + break; + case EIGRPACKSRCVD: /* 12 */ + /* Acknowledgement packets input count */ + if (eigrp) { + counter = 0; + for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, + ei)) { + counter += ei->ack_in; + } + return SNMP_INTEGER(counter); + } else + return SNMP_INTEGER(0); + break; + case EIGRPINPUTQHIGHMARK: /* 13 */ + /* The highest number of EIGRP packets in the input queue */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPINPUTQDROPS: /* 14 */ + /* The number of EIGRP packets dropped from the input queue */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPSIAQUERIESSENT: /* 15 */ + /* SIA querry packets output count */ + if (eigrp) { + counter = 0; + for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, + ei)) { + counter += ei->siaQuery_out; + } + return SNMP_INTEGER(counter); + } else + return SNMP_INTEGER(0); + break; + case EIGRPSIAQUERIESRCVD: /* 16 */ + /* SIA querry packets input count */ + if (eigrp) { + counter = 0; + for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, + ei)) { + counter += ei->siaQuery_in; + } + return SNMP_INTEGER(counter); + } else + return SNMP_INTEGER(0); + break; + case EIGRPASROUTERIDTYPE: /* 17 */ + /* Whether the router ID is set manually or automatically */ + if (eigrp) + if (eigrp->router_id_static != 0) + return SNMP_INTEGER(1); + else + return SNMP_INTEGER(1); + else + return SNMP_INTEGER(0); + break; + case EIGRPASROUTERID: /* 18 */ + /* Router ID for this EIGRP AS */ + if (eigrp) + if (eigrp->router_id_static != 0) + return SNMP_INTEGER(eigrp->router_id_static); + else + return SNMP_INTEGER(eigrp->router_id); + else + return SNMP_INTEGER(0); + break; + case EIGRPTOPOROUTES: /* 19 */ + /* The total number of EIGRP derived routes currently existing + in the topology table for the AS */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPHEADSERIAL: /* 20 */ + /* The serial number of the first route in the internal + sequence for an AS*/ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPNEXTSERIAL: /* 21 */ + /* The serial number that would be assigned to the next new + or changed route in the topology table for the AS*/ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPXMITPENDREPLIES: /* 22 */ + /* Total number of outstanding replies expected to queries + that have been sent to peers in the current AS*/ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPXMITDUMMIES: /* 23 */ + /* Total number of currently existing dummies associated with + * the AS*/ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + default: + return NULL; + } + return NULL; } -static u_char * -eigrpTopologyEntry (struct variable *v, oid *name, size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *eigrpTopologyEntry(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - struct eigrp *eigrp; - struct eigrp_interface *ei; - struct listnode *node, *nnode; - - eigrp = eigrp_lookup (); - - /* Check whether the instance identifier is valid */ - if (smux_header_generic (v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - /* Return the current value of the variable */ - switch (v->magic) - { - case EIGRPDESTNETTYPE: /* 1 */ - /* The format of the destination IP network number for a single - route in the topology table*/ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPDESTNET: /* 2 */ - /* The destination IP network number for a single route in the topology table*/ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPDESTNETPREFIXLEN: /* 4 */ - /* The prefix length associated with the destination IP network address - for a single route in the topology table in the AS*/ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPACTIVE: /* 5 */ - /* A value of true(1) indicates the route to the destination network has failed - A value of false(2) indicates the route is stable (passive).*/ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPSTUCKINACTIVE: /* 6 */ - /* A value of true(1) indicates that that this route which is in active state - has not received any replies to queries for alternate paths */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPDESTSUCCESSORS: /* 7 */ - /* Next routing hop for a path to the destination IP network */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPFDISTANCE: /* 8 */ - /* Minimum distance from this router to the destination IP network */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPROUTEORIGINTYPE: /* 9 */ - /* Text string describing the internal origin of the EIGRP route */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPROUTEORIGINADDRTYPE: /* 10 */ - /* The format of the IP address defined as the origin of this - topology route entry */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPROUTEORIGINADDR: /* 11 */ - /* If the origin of the topology route entry is external to this router, - then this object is the IP address of the router from which it originated */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPNEXTHOPADDRESSTYPE: /* 12 */ - /* The format of the next hop IP address */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPNEXTHOPADDRESS: /* 13 */ - /* Next hop IP address for the route */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPNEXTHOPINTERFACE: /* 14 */ - /* The interface through which the next hop IP address is reached */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPDISTANCE: /* 15 */ - /* The computed distance to the destination network entry from this router */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPREPORTDISTANCE: /* 16 */ - /* The computed distance to the destination network in the topology entry - reported to this router by the originator of this route */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - default: - return NULL; - } - return NULL; + struct eigrp *eigrp; + struct eigrp_interface *ei; + struct listnode *node, *nnode; + + eigrp = eigrp_lookup(); + + /* Check whether the instance identifier is valid */ + if (smux_header_generic(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + /* Return the current value of the variable */ + switch (v->magic) { + case EIGRPDESTNETTYPE: /* 1 */ + /* The format of the destination IP network number for a single + route in the topology table*/ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPDESTNET: /* 2 */ + /* The destination IP network number for a single route in the + * topology table*/ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPDESTNETPREFIXLEN: /* 4 */ + /* The prefix length associated with the destination IP network + address + for a single route in the topology table in the AS*/ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPACTIVE: /* 5 */ + /* A value of true(1) indicates the route to the destination + network has failed + A value of false(2) indicates the route is stable + (passive).*/ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPSTUCKINACTIVE: /* 6 */ + /* A value of true(1) indicates that that this route which is in + active state + has not received any replies to queries for alternate paths + */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPDESTSUCCESSORS: /* 7 */ + /* Next routing hop for a path to the destination IP network */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPFDISTANCE: /* 8 */ + /* Minimum distance from this router to the destination IP + * network */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPROUTEORIGINTYPE: /* 9 */ + /* Text string describing the internal origin of the EIGRP route + */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPROUTEORIGINADDRTYPE: /* 10 */ + /* The format of the IP address defined as the origin of this + topology route entry */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPROUTEORIGINADDR: /* 11 */ + /* If the origin of the topology route entry is external to this + router, + then this object is the IP address of the router from which + it originated */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPNEXTHOPADDRESSTYPE: /* 12 */ + /* The format of the next hop IP address */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPNEXTHOPADDRESS: /* 13 */ + /* Next hop IP address for the route */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPNEXTHOPINTERFACE: /* 14 */ + /* The interface through which the next hop IP address is + * reached */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPDISTANCE: /* 15 */ + /* The computed distance to the destination network entry from + * this router */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPREPORTDISTANCE: /* 16 */ + /* The computed distance to the destination network in the + topology entry + reported to this router by the originator of this route */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + default: + return NULL; + } + return NULL; } -static u_char * -eigrpPeerEntry (struct variable *v, oid *name, size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *eigrpPeerEntry(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - struct eigrp *eigrp; - struct eigrp_interface *ei; - struct listnode *node, *nnode; - struct eigrp_neighbor *nbr; - struct in_addr nbr_addr; - unsigned int ifindex; - - eigrp = eigrp_lookup (); - - /* Check whether the instance identifier is valid */ - if (smux_header_generic (v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - memset (&nbr_addr, 0, sizeof (struct in_addr)); - ifindex = 0; - - nbr = eigrpNbrLookup (v, name, length, &nbr_addr, &ifindex, exact); - if (! nbr) - return NULL; - ei = nbr->ei; - if (! ei) - return NULL; - - /* Return the current value of the variable */ - switch (v->magic) - { - case EIGRPHANDLE: /* 1 */ - /* The unique internal identifier for the peer in the AS */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPPEERADDRTYPE: /* 2 */ - /* The format of the remote source IP address used by the peer */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPPEERADDR: /* 3 */ - /* The source IP address used by the peer */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPPEERIFINDEX: /* 4 */ - /* The ifIndex of the interface on this router */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPHOLDTIME: /* 5 */ - /* How much time must pass without receiving a hello packet from this - EIGRP peer before this router declares the peer down */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPUPTIME: /* 6 */ - /* The elapsed time since the EIGRP adjacency was first established */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPSRTT: /* 7 */ - /* The computed smooth round trip time for packets to and from the peer */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPRTO: /* 8 */ - /* The computed retransmission timeout for the peer */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPPKTSENQUEUED: /* 9 */ - /* The number of any EIGRP packets currently enqueued */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPLASTSEQ: /* 10 */ - /* sequence number of the last EIGRP packet sent to this peer */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPVERSION: /* 11 */ - /* The EIGRP version information reported by the remote peer */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPRETRANS: /* 12 */ - /* The cumulative number of retransmissions to this peer */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPRETRIES: /* 13 */ - /* The number of times the current unacknowledged packet has been retried */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - default: - return NULL; - } - return NULL; + struct eigrp *eigrp; + struct eigrp_interface *ei; + struct listnode *node, *nnode; + struct eigrp_neighbor *nbr; + struct in_addr nbr_addr; + unsigned int ifindex; + + eigrp = eigrp_lookup(); + + /* Check whether the instance identifier is valid */ + if (smux_header_generic(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + memset(&nbr_addr, 0, sizeof(struct in_addr)); + ifindex = 0; + + nbr = eigrpNbrLookup(v, name, length, &nbr_addr, &ifindex, exact); + if (!nbr) + return NULL; + ei = nbr->ei; + if (!ei) + return NULL; + + /* Return the current value of the variable */ + switch (v->magic) { + case EIGRPHANDLE: /* 1 */ + /* The unique internal identifier for the peer in the AS */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPPEERADDRTYPE: /* 2 */ + /* The format of the remote source IP address used by the peer + */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPPEERADDR: /* 3 */ + /* The source IP address used by the peer */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPPEERIFINDEX: /* 4 */ + /* The ifIndex of the interface on this router */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPHOLDTIME: /* 5 */ + /* How much time must pass without receiving a hello packet from + this + EIGRP peer before this router declares the peer down */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPUPTIME: /* 6 */ + /* The elapsed time since the EIGRP adjacency was first + * established */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPSRTT: /* 7 */ + /* The computed smooth round trip time for packets to and from + * the peer */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPRTO: /* 8 */ + /* The computed retransmission timeout for the peer */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPPKTSENQUEUED: /* 9 */ + /* The number of any EIGRP packets currently enqueued */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPLASTSEQ: /* 10 */ + /* sequence number of the last EIGRP packet sent to this peer */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPVERSION: /* 11 */ + /* The EIGRP version information reported by the remote peer */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPRETRANS: /* 12 */ + /* The cumulative number of retransmissions to this peer */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPRETRIES: /* 13 */ + /* The number of times the current unacknowledged packet has + * been retried */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + default: + return NULL; + } + return NULL; } -static u_char * -eigrpInterfaceEntry (struct variable *v, oid *name, size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *eigrpInterfaceEntry(struct variable *v, oid *name, + size_t *length, int exact, size_t *var_len, + WriteMethod **write_method) { - struct eigrp *eigrp; - struct eigrp_interface *ei; - struct listnode *node, *nnode; - struct keychain *keychain; - struct list *keylist; - int counter; - - eigrp = eigrp_lookup (); - - /* Check whether the instance identifier is valid */ - if (smux_header_generic (v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - /* Return the current value of the variable */ - switch (v->magic) - { - case EIGRPPEERCOUNT: /* 3 */ - /* The number of EIGRP adjacencies currently formed with - peers reached through this interface */ - if (eigrp) - { - return SNMP_INTEGER (eigrp_neighbor_count (eigrp)); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPXMITRELIABLEQ: /* 4 */ - /* The number of EIGRP packets currently waiting in the reliable - transport transmission queue */ - if (eigrp) - { - return SNMP_INTEGER (1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPXMITUNRELIABLEQ: /* 5 */ - /* The number of EIGRP packets currently waiting in the unreliable - transport transmission queue */ - if (eigrp) - { - return SNMP_INTEGER (1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPMEANSRTT: /* 6 */ - /* The average of all the computed smooth round trip time values - for a packet to and from all peers established on this interface */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPPACINGRELIABLE: /* 7 */ - /* The configured time interval between EIGRP packet transmissions */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPPACINGUNRELIABLE: /* 8 */ - /* The configured time interval between EIGRP packet transmissions - on the interface when the unreliable transport method is used */ - if (eigrp) - { - return SNMP_INTEGER (1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPMFLOWTIMER: /* 9 */ - /* The configured multicast flow control timer value */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPPENDINGROUTES: /* 10 */ - /* The number of queued EIGRP routing updates awaiting transmission */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPHELLOINTERVAL: /* 11 */ - /* The configured time interval between Hello packet transmissions */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPXMITNEXTSERIAL: /* 12 */ - /* The serial number of the next EIGRP packet that is to be queued - for transmission */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPUMCASTS: /* 13 */ - /* The total number of unreliable EIGRP multicast packets sent - on this interface */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPRMCASTS: /* 14 */ - /* The total number of reliable EIGRP multicast packets sent - on this interface */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPUUCASTS: /* 15 */ - /* The total number of unreliable EIGRP unicast packets sent - on this interface */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPRUCASTS: /* 16 */ - /* The total number of reliable EIGRP unicast packets sent - on this interface */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPMCASTEXCEPTS: /* 17 */ - /* The total number of EIGRP multicast exception transmissions */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPCRPKTS: /* 18 */ - /* The total number EIGRP Conditional-Receive packets sent on this interface */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPACKSSUPPRESSED: /* 19 */ - /* The total number of individual EIGRP acknowledgement packets that have been - suppressed and combined in an already enqueued outbound reliable packet on this interface */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPRETRANSSENT: /* 20 */ - /* The total number EIGRP packet retransmissions sent on the interface */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPOOSRCVD: /* 21 */ - /* The total number of out-of-sequence EIGRP packets received */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPAUTHMODE: /* 22 */ - /* The EIGRP authentication mode of the interface */ - if (eigrp) - { - return SNMP_INTEGER(1); - } - else - return SNMP_INTEGER (0); - break; - case EIGRPAUTHKEYCHAIN: /* 23 */ - /* The name of the authentication key-chain configured - on this interface. */ - keylist = keychain_list_get(); - for (ALL_LIST_ELEMENTS (keylist, node, nnode, keychain)) - { - return (u_char *) keychain->name; - } - if (eigrp && keychain) - { - *var_len = str_len (keychain->name); - return (u_char *) keychain->name; - } - else - return (u_char *) "TEST"; - break; - default: - return NULL; - } - return NULL; + struct eigrp *eigrp; + struct eigrp_interface *ei; + struct listnode *node, *nnode; + struct keychain *keychain; + struct list *keylist; + int counter; + + eigrp = eigrp_lookup(); + + /* Check whether the instance identifier is valid */ + if (smux_header_generic(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + /* Return the current value of the variable */ + switch (v->magic) { + case EIGRPPEERCOUNT: /* 3 */ + /* The number of EIGRP adjacencies currently formed with + peers reached through this interface */ + if (eigrp) { + return SNMP_INTEGER(eigrp_neighbor_count(eigrp)); + } else + return SNMP_INTEGER(0); + break; + case EIGRPXMITRELIABLEQ: /* 4 */ + /* The number of EIGRP packets currently waiting in the reliable + transport transmission queue */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPXMITUNRELIABLEQ: /* 5 */ + /* The number of EIGRP packets currently waiting in the + unreliable + transport transmission queue */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPMEANSRTT: /* 6 */ + /* The average of all the computed smooth round trip time values + for a packet to and from all peers established on this + interface */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPPACINGRELIABLE: /* 7 */ + /* The configured time interval between EIGRP packet + * transmissions */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPPACINGUNRELIABLE: /* 8 */ + /* The configured time interval between EIGRP packet + transmissions + on the interface when the unreliable transport method is used + */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPMFLOWTIMER: /* 9 */ + /* The configured multicast flow control timer value */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPPENDINGROUTES: /* 10 */ + /* The number of queued EIGRP routing updates awaiting + * transmission */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPHELLOINTERVAL: /* 11 */ + /* The configured time interval between Hello packet + * transmissions */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPXMITNEXTSERIAL: /* 12 */ + /* The serial number of the next EIGRP packet that is to be + queued + for transmission */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPUMCASTS: /* 13 */ + /* The total number of unreliable EIGRP multicast packets sent + on this interface */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPRMCASTS: /* 14 */ + /* The total number of reliable EIGRP multicast packets sent + on this interface */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPUUCASTS: /* 15 */ + /* The total number of unreliable EIGRP unicast packets sent + on this interface */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPRUCASTS: /* 16 */ + /* The total number of reliable EIGRP unicast packets sent + on this interface */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPMCASTEXCEPTS: /* 17 */ + /* The total number of EIGRP multicast exception transmissions + */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPCRPKTS: /* 18 */ + /* The total number EIGRP Conditional-Receive packets sent on + * this interface */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPACKSSUPPRESSED: /* 19 */ + /* The total number of individual EIGRP acknowledgement packets + that have been + suppressed and combined in an already enqueued outbound + reliable packet on this interface */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPRETRANSSENT: /* 20 */ + /* The total number EIGRP packet retransmissions sent on the + * interface */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPOOSRCVD: /* 21 */ + /* The total number of out-of-sequence EIGRP packets received */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPAUTHMODE: /* 22 */ + /* The EIGRP authentication mode of the interface */ + if (eigrp) { + return SNMP_INTEGER(1); + } else + return SNMP_INTEGER(0); + break; + case EIGRPAUTHKEYCHAIN: /* 23 */ + /* The name of the authentication key-chain configured + on this interface. */ + keylist = keychain_list_get(); + for (ALL_LIST_ELEMENTS(keylist, node, nnode, keychain)) { + return (u_char *)keychain->name; + } + if (eigrp && keychain) { + *var_len = str_len(keychain->name); + return (u_char *)keychain->name; + } else + return (u_char *)"TEST"; + break; + default: + return NULL; + } + return NULL; } /* Register EIGRP-MIB. */ -void -eigrp_snmp_init () +void eigrp_snmp_init() { - eigrp_snmp_iflist = list_new (); - smux_init (eigrp_om->master); - REGISTER_MIB("ciscoEigrpMIB", eigrp_variables, variable, eigrp_oid); + eigrp_snmp_iflist = list_new(); + smux_init(eigrp_om->master); + REGISTER_MIB("ciscoEigrpMIB", eigrp_variables, variable, eigrp_oid); } #endif diff --git a/eigrpd/eigrp_snmp.h b/eigrpd/eigrp_snmp.h index 559852d58..55114e605 100644 --- a/eigrpd/eigrp_snmp.h +++ b/eigrpd/eigrp_snmp.h @@ -29,7 +29,7 @@ #ifndef _ZEBRA_EIGRP_SNMP_H #define _ZEBRA_EIGRP_SNMP_H -extern void eigrp_snmp_init (void); +extern void eigrp_snmp_init(void); #endif /* _ZEBRA_EIGRP_SNMP_H */ diff --git a/eigrpd/eigrp_structs.h b/eigrpd/eigrp_structs.h index 4d307005c..6b3a14abc 100644 --- a/eigrpd/eigrp_structs.h +++ b/eigrpd/eigrp_structs.h @@ -38,192 +38,193 @@ #include "eigrpd/eigrp_macros.h" /* EIGRP master for system wide configuration and variables. */ -struct eigrp_master -{ - /* EIGRP instance. */ - struct list *eigrp; +struct eigrp_master { + /* EIGRP instance. */ + struct list *eigrp; - /* EIGRP thread master. */ - struct thread_master *master; + /* EIGRP thread master. */ + struct thread_master *master; - /* Zebra interface list. */ - struct list *iflist; + /* Zebra interface list. */ + struct list *iflist; - /* EIGRP start time. */ - time_t start_time; + /* EIGRP start time. */ + time_t start_time; - /* Various EIGRP global configuration. */ - u_char options; + /* Various EIGRP global configuration. */ + u_char options; #define EIGRP_MASTER_SHUTDOWN (1 << 0) /* deferred-shutdown */ }; -struct eigrp_metrics -{ - u_int32_t delay; - u_int32_t bandwith; - unsigned char mtu[3]; - u_char hop_count; - u_char reliability; - u_char load; - u_char tag; - u_char flags; +struct eigrp_metrics { + u_int32_t delay; + u_int32_t bandwith; + unsigned char mtu[3]; + u_char hop_count; + u_char reliability; + u_char load; + u_char tag; + u_char flags; }; -struct eigrp -{ - u_int16_t AS; /* Autonomous system number */ - u_int16_t vrid; /* Virtual Router ID */ - u_char k_values[6]; /*Array for K values configuration*/ - u_char variance; /*Metric variance multiplier*/ - u_char max_paths; /*Maximum allowed paths for 1 prefix*/ +struct eigrp { + u_int16_t AS; /* Autonomous system number */ + u_int16_t vrid; /* Virtual Router ID */ + u_char k_values[6]; /*Array for K values configuration*/ + u_char variance; /*Metric variance multiplier*/ + u_char max_paths; /*Maximum allowed paths for 1 prefix*/ - /*Name of this EIGRP instance*/ - char *name; + /*Name of this EIGRP instance*/ + char *name; - /* EIGRP Router ID. */ - u_int32_t router_id; /* Configured automatically. */ - u_int32_t router_id_static; /* Configured manually. */ + /* EIGRP Router ID. */ + u_int32_t router_id; /* Configured automatically. */ + u_int32_t router_id_static; /* Configured manually. */ - struct list *eiflist; /* eigrp interfaces */ - u_char passive_interface_default; /* passive-interface default */ + struct list *eiflist; /* eigrp interfaces */ + u_char passive_interface_default; /* passive-interface default */ - unsigned int fd; - unsigned int maxsndbuflen; + unsigned int fd; + unsigned int maxsndbuflen; - u_int32_t sequence_number; /*Global EIGRP sequence number*/ + u_int32_t sequence_number; /*Global EIGRP sequence number*/ - struct stream *ibuf; - struct list *oi_write_q; + struct stream *ibuf; + struct list *oi_write_q; - /*Threads*/ - struct thread *t_write; - struct thread *t_read; - struct thread *t_distribute; /* timer for distribute list */ + /*Threads*/ + struct thread *t_write; + struct thread *t_read; + struct thread *t_distribute; /* timer for distribute list */ - struct route_table *networks; /* EIGRP config networks. */ + struct route_table *networks; /* EIGRP config networks. */ - struct list *topology_table; + struct list *topology_table; - uint64_t serno; /* Global serial number counter for topology entry changes*/ - uint64_t serno_last_update; /* Highest serial number of information send by last update*/ - struct list *topology_changes_internalIPV4; - struct list *topology_changes_externalIPV4; + uint64_t serno; /* Global serial number counter for topology entry + changes*/ + uint64_t + serno_last_update; /* Highest serial number of information send + by last update*/ + struct list *topology_changes_internalIPV4; + struct list *topology_changes_externalIPV4; - /*Neighbor self*/ - struct eigrp_neighbor *neighbor_self; + /*Neighbor self*/ + struct eigrp_neighbor *neighbor_self; - /*Configured metric for redistributed routes*/ - struct eigrp_metrics dmetric[ZEBRA_ROUTE_MAX + 1]; - int redistribute; /* Num of redistributed protocols. */ + /*Configured metric for redistributed routes*/ + struct eigrp_metrics dmetric[ZEBRA_ROUTE_MAX + 1]; + int redistribute; /* Num of redistributed protocols. */ - /* Access-list. */ - struct access_list *list[EIGRP_FILTER_MAX]; - /* Prefix-list. */ - struct prefix_list *prefix[EIGRP_FILTER_MAX]; - /* Route-map. */ - struct route_map *routemap[EIGRP_FILTER_MAX]; + /* Access-list. */ + struct access_list *list[EIGRP_FILTER_MAX]; + /* Prefix-list. */ + struct prefix_list *prefix[EIGRP_FILTER_MAX]; + /* Route-map. */ + struct route_map *routemap[EIGRP_FILTER_MAX]; - /* For redistribute route map. */ - struct - { - char *name; - struct route_map *map; - int metric_config; - u_int32_t metric; - } route_map[ZEBRA_ROUTE_MAX]; + /* For redistribute route map. */ + struct { + char *name; + struct route_map *map; + int metric_config; + u_int32_t metric; + } route_map[ZEBRA_ROUTE_MAX]; - QOBJ_FIELDS + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(eigrp) //------------------------------------------------------------------------------------------------------------------------------------------ /*EIGRP interface structure*/ -struct eigrp_interface -{ - /* This interface's parent eigrp instance. */ - struct eigrp *eigrp; - - /* Interface data from zebra. */ - struct interface *ifp; - - /* Packet send buffer. */ - struct eigrp_fifo *obuf; /* Output queue */ - - /* To which multicast groups do we currently belong? */ - - /* Configured varables. */ - struct eigrp_if_params *params; - - u_char multicast_memberships; - - /* EIGRP Network Type. */ - u_char type; - - struct prefix *address; /* Interface prefix */ - struct connected *connected; /* Pointer to connected */ - - /* Neighbor information. */ - struct list *nbrs; /* EIGRP Neighbor List */ - - /* Threads. */ - struct thread *t_hello; /* timer */ - struct thread *t_distribute; /* timer for distribute list */ - - int on_write_q; - - /* Statistics fields. */ - u_int32_t hello_in; /* Hello message input count. */ - u_int32_t update_in; /* Update message input count. */ - u_int32_t query_in; /* Querry message input count. */ - u_int32_t reply_in; /* Reply message input count. */ - u_int32_t hello_out; /* Hello message output count. */ - u_int32_t update_out; /* Update message output count. */ - u_int32_t query_out; /* Query message output count. */ - u_int32_t reply_out; /* Reply message output count. */ - u_int32_t siaQuery_in; - u_int32_t siaQuery_out; - u_int32_t siaReply_in; - u_int32_t siaReply_out; - u_int32_t ack_out; - u_int32_t ack_in; - - u_int32_t crypt_seqnum; /* Cryptographic Sequence Number */ - - /* Access-list. */ - struct access_list *list[EIGRP_FILTER_MAX]; - /* Prefix-list. */ - struct prefix_list *prefix[EIGRP_FILTER_MAX]; - /* Route-map. */ - struct route_map *routemap[EIGRP_FILTER_MAX]; +struct eigrp_interface { + /* This interface's parent eigrp instance. */ + struct eigrp *eigrp; + + /* Interface data from zebra. */ + struct interface *ifp; + + /* Packet send buffer. */ + struct eigrp_fifo *obuf; /* Output queue */ + + /* To which multicast groups do we currently belong? */ + + /* Configured varables. */ + struct eigrp_if_params *params; + + u_char multicast_memberships; + + /* EIGRP Network Type. */ + u_char type; + + struct prefix *address; /* Interface prefix */ + struct connected *connected; /* Pointer to connected */ + + /* Neighbor information. */ + struct list *nbrs; /* EIGRP Neighbor List */ + + /* Threads. */ + struct thread *t_hello; /* timer */ + struct thread *t_distribute; /* timer for distribute list */ + + int on_write_q; + + /* Statistics fields. */ + u_int32_t hello_in; /* Hello message input count. */ + u_int32_t update_in; /* Update message input count. */ + u_int32_t query_in; /* Querry message input count. */ + u_int32_t reply_in; /* Reply message input count. */ + u_int32_t hello_out; /* Hello message output count. */ + u_int32_t update_out; /* Update message output count. */ + u_int32_t query_out; /* Query message output count. */ + u_int32_t reply_out; /* Reply message output count. */ + u_int32_t siaQuery_in; + u_int32_t siaQuery_out; + u_int32_t siaReply_in; + u_int32_t siaReply_out; + u_int32_t ack_out; + u_int32_t ack_in; + + u_int32_t crypt_seqnum; /* Cryptographic Sequence Number */ + + /* Access-list. */ + struct access_list *list[EIGRP_FILTER_MAX]; + /* Prefix-list. */ + struct prefix_list *prefix[EIGRP_FILTER_MAX]; + /* Route-map. */ + struct route_map *routemap[EIGRP_FILTER_MAX]; }; -struct eigrp_if_params -{ - DECLARE_IF_PARAM (u_char, passive_interface); /* EIGRP Interface is passive: no sending or receiving (no need to join multicast groups) */ - DECLARE_IF_PARAM (u_int32_t, v_hello); /* Hello Interval */ - DECLARE_IF_PARAM (u_int16_t, v_wait); /* Router Hold Time Interval */ - DECLARE_IF_PARAM (u_char, type); /* type of interface */ - DECLARE_IF_PARAM (u_int32_t, bandwidth); - DECLARE_IF_PARAM (u_int32_t, delay); - DECLARE_IF_PARAM (u_char, reliability); - DECLARE_IF_PARAM (u_char, load); - - DECLARE_IF_PARAM (char *, auth_keychain ); /* Associated keychain with interface*/ - DECLARE_IF_PARAM (int, auth_type); /* EIGRP authentication type */ +struct eigrp_if_params { + DECLARE_IF_PARAM(u_char, passive_interface); /* EIGRP Interface is + passive: no sending or + receiving (no need to + join multicast groups) + */ + DECLARE_IF_PARAM(u_int32_t, v_hello); /* Hello Interval */ + DECLARE_IF_PARAM(u_int16_t, v_wait); /* Router Hold Time Interval */ + DECLARE_IF_PARAM(u_char, type); /* type of interface */ + DECLARE_IF_PARAM(u_int32_t, bandwidth); + DECLARE_IF_PARAM(u_int32_t, delay); + DECLARE_IF_PARAM(u_char, reliability); + DECLARE_IF_PARAM(u_char, load); + + DECLARE_IF_PARAM(char *, + auth_keychain); /* Associated keychain with interface*/ + DECLARE_IF_PARAM(int, auth_type); /* EIGRP authentication type */ }; -enum -{ - MEMBER_ALLROUTERS = 0, MEMBER_MAX, +enum { MEMBER_ALLROUTERS = 0, + MEMBER_MAX, }; -struct eigrp_if_info -{ - struct eigrp_if_params *def_params; - struct route_table *params; - struct route_table *eifs; - unsigned int membership_counts[MEMBER_MAX]; /* multicast group refcnts */ +struct eigrp_if_info { + struct eigrp_if_params *def_params; + struct route_table *params; + struct route_table *eifs; + unsigned int + membership_counts[MEMBER_MAX]; /* multicast group refcnts */ }; //------------------------------------------------------------------------------------------------------------------------------------------ @@ -232,109 +233,105 @@ struct eigrp_if_info * when packet consists of multiple packet * chunks because of many route TLV * (all won't fit into one packet) */ -enum Packet_part_type -{ +enum Packet_part_type { EIGRP_PACKET_PART_NA, EIGRP_PACKET_PART_FIRST, EIGRP_PACKET_PART_LAST }; /* Neighbor Data Structure */ -struct eigrp_neighbor -{ - /* This neighbor's parent eigrp interface. */ - struct eigrp_interface *ei; +struct eigrp_neighbor { + /* This neighbor's parent eigrp interface. */ + struct eigrp_interface *ei; - /* EIGRP neighbor Information */ - u_char state; /* neigbor status. */ + /* EIGRP neighbor Information */ + u_char state; /* neigbor status. */ - u_int32_t recv_sequence_number; /* Last received sequence Number. */ - u_int32_t init_sequence_number; + u_int32_t recv_sequence_number; /* Last received sequence Number. */ + u_int32_t init_sequence_number; - /*If packet is unacknowledged, we try to send it again 16 times*/ - u_char retrans_counter; + /*If packet is unacknowledged, we try to send it again 16 times*/ + u_char retrans_counter; - struct in_addr src; /* Neighbor Src address. */ + struct in_addr src; /* Neighbor Src address. */ - u_char os_rel_major; // system version - just for show - u_char os_rel_minor; // system version - just for show - u_char tlv_rel_major; // eigrp version - tells us what TLV format to use - u_char tlv_rel_minor; // eigrp version - tells us what TLV format to use + u_char os_rel_major; // system version - just for show + u_char os_rel_minor; // system version - just for show + u_char tlv_rel_major; // eigrp version - tells us what TLV format to use + u_char tlv_rel_minor; // eigrp version - tells us what TLV format to use - u_char K1; - u_char K2; - u_char K3; - u_char K4; - u_char K5; - u_char K6; + u_char K1; + u_char K2; + u_char K3; + u_char K4; + u_char K5; + u_char K6; - /* Timer values. */ - u_int16_t v_holddown; + /* Timer values. */ + u_int16_t v_holddown; - /* Threads. */ - struct thread *t_holddown; - struct thread *t_nbr_send_gr; /* thread for sending multiple GR packet chunks */ + /* Threads. */ + struct thread *t_holddown; + struct thread *t_nbr_send_gr; /* thread for sending multiple GR packet + chunks */ - struct eigrp_fifo *retrans_queue; - struct eigrp_fifo *multicast_queue; + struct eigrp_fifo *retrans_queue; + struct eigrp_fifo *multicast_queue; - u_int32_t crypt_seqnum; /* Cryptographic Sequence Number. */ + u_int32_t crypt_seqnum; /* Cryptographic Sequence Number. */ - /* prefixes not received from neighbor during Graceful restart */ - struct list *nbr_gr_prefixes; - /* prefixes not yet send to neighbor during Graceful restart */ - struct list *nbr_gr_prefixes_send; - /* if packet is first or last during Graceful restart */ - enum Packet_part_type nbr_gr_packet_type; + /* prefixes not received from neighbor during Graceful restart */ + struct list *nbr_gr_prefixes; + /* prefixes not yet send to neighbor during Graceful restart */ + struct list *nbr_gr_prefixes_send; + /* if packet is first or last during Graceful restart */ + enum Packet_part_type nbr_gr_packet_type; }; //--------------------------------------------------------------------------------------------------------------------------------------------- -struct eigrp_packet -{ - struct eigrp_packet *next; - struct eigrp_packet *previous; +struct eigrp_packet { + struct eigrp_packet *next; + struct eigrp_packet *previous; - /* Pointer to data stream. */ - struct stream *s; + /* Pointer to data stream. */ + struct stream *s; - /* IP destination address. */ - struct in_addr dst; + /* IP destination address. */ + struct in_addr dst; - /*Packet retransmission thread*/ - struct thread *t_retrans_timer; + /*Packet retransmission thread*/ + struct thread *t_retrans_timer; - /*Packet retransmission counter*/ - u_char retrans_counter; + /*Packet retransmission counter*/ + u_char retrans_counter; - u_int32_t sequence_number; + u_int32_t sequence_number; - /* EIGRP packet length. */ - u_int16_t length; + /* EIGRP packet length. */ + u_int16_t length; }; -struct eigrp_fifo -{ - struct eigrp_packet *head; - struct eigrp_packet *tail; +struct eigrp_fifo { + struct eigrp_packet *head; + struct eigrp_packet *tail; - unsigned long count; + unsigned long count; }; -struct eigrp_header -{ - u_char version; - u_char opcode; - u_int16_t checksum; - u_int32_t flags; - u_int32_t sequence; - u_int32_t ack; - u_int16_t vrid; - u_int16_t ASNumber; - char *tlv[0]; +struct eigrp_header { + u_char version; + u_char opcode; + u_int16_t checksum; + u_int32_t flags; + u_int32_t sequence; + u_int32_t ack; + u_int16_t vrid; + u_int16_t ASNumber; + char *tlv[0]; -}__attribute__((packed)); +} __attribute__((packed)); /** @@ -346,187 +343,174 @@ struct eigrp_header * | | | | * +-----+------------------+ */ -struct eigrp_tlv_hdr_type -{ - u_int16_t type; - u_int16_t length; - uint8_t value[0]; -}__attribute__((packed)); - -struct TLV_Parameter_Type -{ - u_int16_t type; - u_int16_t length; - u_char K1; - u_char K2; - u_char K3; - u_char K4; - u_char K5; - u_char K6; - u_int16_t hold_time; -}__attribute__((packed)); - -struct TLV_MD5_Authentication_Type -{ - u_int16_t type; - u_int16_t length; - u_int16_t auth_type; - u_int16_t auth_length; - u_int32_t key_id; - u_int32_t key_sequence; - u_char Nullpad[8]; - u_char digest[EIGRP_AUTH_TYPE_MD5_LEN]; - -}__attribute__((packed)); - -struct TLV_SHA256_Authentication_Type -{ - u_int16_t type; - u_int16_t length; - u_int16_t auth_type; - u_int16_t auth_length; - u_int32_t key_id; - u_int32_t key_sequence; - u_char Nullpad[8]; - u_char digest[EIGRP_AUTH_TYPE_SHA256_LEN]; - -}__attribute__((packed)); - -struct TLV_Sequence_Type -{ - u_int16_t type; - u_int16_t length; - u_char addr_length; - struct in_addr *addresses; -}__attribute__((packed)); - -struct TLV_Next_Multicast_Sequence -{ - u_int16_t type; - u_int16_t length; - u_int32_t multicast_sequence; -}__attribute__((packed)); - -struct TLV_Software_Type -{ - u_int16_t type; - u_int16_t length; - u_char vender_major; - u_char vender_minor; - u_char eigrp_major; - u_char eigrp_minor; -}__attribute__((packed)); - -struct TLV_IPv4_Internal_type -{ - u_int16_t type; - u_int16_t length; - struct in_addr forward; - - /*Metrics*/ - struct eigrp_metrics metric; - - u_char prefix_length; - - unsigned char destination_part[4]; - struct in_addr destination; -}__attribute__((packed)); - -struct TLV_IPv4_External_type -{ - u_int16_t type; - u_int16_t length; - struct in_addr next_hop; - struct in_addr originating_router; - u_int32_t originating_as; - u_int32_t administrative_tag; - u_int32_t external_metric; - u_int16_t reserved; - u_char external_protocol; - u_char external_flags; - - /*Metrics*/ - struct eigrp_metrics metric; - - u_char prefix_length; - unsigned char destination_part[4]; - struct in_addr destination; -}__attribute__((packed)); +struct eigrp_tlv_hdr_type { + u_int16_t type; + u_int16_t length; + uint8_t value[0]; +} __attribute__((packed)); + +struct TLV_Parameter_Type { + u_int16_t type; + u_int16_t length; + u_char K1; + u_char K2; + u_char K3; + u_char K4; + u_char K5; + u_char K6; + u_int16_t hold_time; +} __attribute__((packed)); + +struct TLV_MD5_Authentication_Type { + u_int16_t type; + u_int16_t length; + u_int16_t auth_type; + u_int16_t auth_length; + u_int32_t key_id; + u_int32_t key_sequence; + u_char Nullpad[8]; + u_char digest[EIGRP_AUTH_TYPE_MD5_LEN]; + +} __attribute__((packed)); + +struct TLV_SHA256_Authentication_Type { + u_int16_t type; + u_int16_t length; + u_int16_t auth_type; + u_int16_t auth_length; + u_int32_t key_id; + u_int32_t key_sequence; + u_char Nullpad[8]; + u_char digest[EIGRP_AUTH_TYPE_SHA256_LEN]; + +} __attribute__((packed)); + +struct TLV_Sequence_Type { + u_int16_t type; + u_int16_t length; + u_char addr_length; + struct in_addr *addresses; +} __attribute__((packed)); + +struct TLV_Next_Multicast_Sequence { + u_int16_t type; + u_int16_t length; + u_int32_t multicast_sequence; +} __attribute__((packed)); + +struct TLV_Software_Type { + u_int16_t type; + u_int16_t length; + u_char vender_major; + u_char vender_minor; + u_char eigrp_major; + u_char eigrp_minor; +} __attribute__((packed)); + +struct TLV_IPv4_Internal_type { + u_int16_t type; + u_int16_t length; + struct in_addr forward; + + /*Metrics*/ + struct eigrp_metrics metric; + + u_char prefix_length; + + unsigned char destination_part[4]; + struct in_addr destination; +} __attribute__((packed)); + +struct TLV_IPv4_External_type { + u_int16_t type; + u_int16_t length; + struct in_addr next_hop; + struct in_addr originating_router; + u_int32_t originating_as; + u_int32_t administrative_tag; + u_int32_t external_metric; + u_int16_t reserved; + u_char external_protocol; + u_char external_flags; + + /*Metrics*/ + struct eigrp_metrics metric; + + u_char prefix_length; + unsigned char destination_part[4]; + struct in_addr destination; +} __attribute__((packed)); /* EIGRP Peer Termination TLV - used for hard restart */ -struct TLV_Peer_Termination_type -{ - u_int16_t type; - u_int16_t length; - u_char unknown; - u_int32_t neighbor_ip; +struct TLV_Peer_Termination_type { + u_int16_t type; + u_int16_t length; + u_char unknown; + u_int32_t neighbor_ip; } __attribute__((packed)); /* Who executed Graceful restart */ -enum GR_type -{ - EIGRP_GR_MANUAL, - EIGRP_GR_FILTER -}; +enum GR_type { EIGRP_GR_MANUAL, EIGRP_GR_FILTER }; //--------------------------------------------------------------------------------------------------------------------------------------------- /* EIGRP Topology table node structure */ -struct eigrp_prefix_entry -{ - struct list *entries, *rij; - u_int32_t fdistance; // FD - u_int32_t rdistance; // RD - u_int32_t distance; // D - struct eigrp_metrics reported_metric; // RD for sending - - u_char nt; //network type - u_char state; //route fsm state - u_char af; // address family - u_char req_action; // required action - - struct prefix_ipv4 *destination_ipv4; // pointer to struct with ipv4 address - struct prefix_ipv6 *destination_ipv6; // pointer to struct with ipv6 address - - //If network type is REMOTE_EXTERNAL, pointer will have reference to its external TLV - struct TLV_IPv4_External_type *extTLV; - - uint64_t serno; /*Serial number for this entry. Increased with each change of entry*/ +struct eigrp_prefix_entry { + struct list *entries, *rij; + u_int32_t fdistance; // FD + u_int32_t rdistance; // RD + u_int32_t distance; // D + struct eigrp_metrics reported_metric; // RD for sending + + u_char nt; // network type + u_char state; // route fsm state + u_char af; // address family + u_char req_action; // required action + + struct prefix_ipv4 + *destination_ipv4; // pointer to struct with ipv4 address + struct prefix_ipv6 + *destination_ipv6; // pointer to struct with ipv6 address + + // If network type is REMOTE_EXTERNAL, pointer will have reference to + // its external TLV + struct TLV_IPv4_External_type *extTLV; + + uint64_t serno; /*Serial number for this entry. Increased with each + change of entry*/ }; /* EIGRP Topology table record structure */ -struct eigrp_neighbor_entry -{ - struct eigrp_prefix_entry *prefix; - u_int32_t reported_distance; //distance reported by neighbor - u_int32_t distance; //sum of reported distance and link cost to advertised neighbor - - struct eigrp_metrics reported_metric; - struct eigrp_metrics total_metric; +struct eigrp_neighbor_entry { + struct eigrp_prefix_entry *prefix; + u_int32_t reported_distance; // distance reported by neighbor + u_int32_t distance; // sum of reported distance and link cost to + // advertised neighbor - struct eigrp_neighbor *adv_router; //ip address of advertising neighbor - u_char flags; //used for marking successor and FS + struct eigrp_metrics reported_metric; + struct eigrp_metrics total_metric; - struct eigrp_interface *ei; //pointer for case of connected entry + struct eigrp_neighbor *adv_router; // ip address of advertising neighbor + u_char flags; // used for marking successor and FS + struct eigrp_interface *ei; // pointer for case of connected entry }; //--------------------------------------------------------------------------------------------------------------------------------------------- /* EIGRP Finite State Machine */ -struct eigrp_fsm_action_message -{ - u_char packet_type; //UPDATE, QUERY, SIAQUERY, SIAREPLY - struct eigrp *eigrp; // which thread sent mesg - struct eigrp_neighbor *adv_router; //advertising neighbor - struct eigrp_neighbor_entry *entry; - struct eigrp_prefix_entry *prefix; - int data_type; // internal or external tlv type - union{ - struct TLV_IPv4_External_type *ipv4_ext_data; - struct TLV_IPv4_Internal_type *ipv4_int_type; - }data; +struct eigrp_fsm_action_message { + u_char packet_type; // UPDATE, QUERY, SIAQUERY, SIAREPLY + struct eigrp *eigrp; // which thread sent mesg + struct eigrp_neighbor *adv_router; // advertising neighbor + struct eigrp_neighbor_entry *entry; + struct eigrp_prefix_entry *prefix; + int data_type; // internal or external tlv type + union { + struct TLV_IPv4_External_type *ipv4_ext_data; + struct TLV_IPv4_Internal_type *ipv4_int_type; + } data; }; #endif /* _ZEBRA_EIGRP_STRUCTURES_H_ */ diff --git a/eigrpd/eigrp_topology.c b/eigrpd/eigrp_topology.c index 675031b75..ae1396eba 100644 --- a/eigrpd/eigrp_topology.c +++ b/eigrpd/eigrp_topology.c @@ -51,263 +51,239 @@ #include "eigrpd/eigrp_fsm.h" #include "eigrpd/eigrp_memory.h" -static int eigrp_prefix_entry_cmp(struct eigrp_prefix_entry *, struct eigrp_prefix_entry *); +static int eigrp_prefix_entry_cmp(struct eigrp_prefix_entry *, + struct eigrp_prefix_entry *); static void eigrp_prefix_entry_del(struct eigrp_prefix_entry *); static int eigrp_neighbor_entry_cmp(struct eigrp_neighbor_entry *, - struct eigrp_neighbor_entry *); + struct eigrp_neighbor_entry *); /* * Returns linkedlist used as topology table * cmp - assigned function for comparing topology nodes - * del - assigned function executed before deleting topology node by list function + * del - assigned function executed before deleting topology node by list + * function */ -struct list * -eigrp_topology_new() +struct list *eigrp_topology_new() { - struct list* new = list_new(); - new->cmp = (int - (*)(void *, void *)) eigrp_prefix_entry_cmp; - new->del = (void - (*)(void *)) eigrp_prefix_entry_del; + struct list *new = list_new(); + new->cmp = (int (*)(void *, void *))eigrp_prefix_entry_cmp; + new->del = (void (*)(void *))eigrp_prefix_entry_del; - return new; + return new; } /* * Topology node comparison */ -static int -eigrp_prefix_entry_cmp(struct eigrp_prefix_entry *node1, - struct eigrp_prefix_entry *node2) +static int eigrp_prefix_entry_cmp(struct eigrp_prefix_entry *node1, + struct eigrp_prefix_entry *node2) { - if (node1->af == AF_INET) - { - if (node2->af == AF_INET) - { - if (node1->destination_ipv4->prefix.s_addr - < node2->destination_ipv4->prefix.s_addr) - { - return -1; // if it belong above node2 - } - else - { - if (node1->destination_ipv4->prefix.s_addr - > node2->destination_ipv4->prefix.s_addr) - { - return 1; //if it belongs under node2 - } - else - { - return 0; // same value... ERROR...in case of adding same prefix again - } - } - } - else - { - return 1; - } - } - else - { // TODO check if the prefix dont exists - return 1; // add to end - } + if (node1->af == AF_INET) { + if (node2->af == AF_INET) { + if (node1->destination_ipv4->prefix.s_addr + < node2->destination_ipv4->prefix.s_addr) { + return -1; // if it belong above node2 + } else { + if (node1->destination_ipv4->prefix.s_addr + > node2->destination_ipv4->prefix.s_addr) { + return 1; // if it belongs under node2 + } else { + return 0; // same value... ERROR...in + // case of adding same prefix + // again + } + } + } else { + return 1; + } + } else { // TODO check if the prefix dont exists + return 1; // add to end + } } /* * Topology node delete */ -static void -eigrp_prefix_entry_del(struct eigrp_prefix_entry *node) +static void eigrp_prefix_entry_del(struct eigrp_prefix_entry *node) { - list_delete_all_node(node->entries); - list_free(node->entries); + list_delete_all_node(node->entries); + list_free(node->entries); } /* * Returns new created toplogy node * cmp - assigned function for comparing topology entry */ -struct eigrp_prefix_entry * -eigrp_prefix_entry_new() +struct eigrp_prefix_entry *eigrp_prefix_entry_new() { - struct eigrp_prefix_entry *new; - new = XCALLOC(MTYPE_EIGRP_PREFIX_ENTRY, sizeof(struct eigrp_prefix_entry)); - new->entries = list_new(); - new->rij = list_new(); - new->entries->cmp = (int (*)(void *, void *))eigrp_neighbor_entry_cmp; - new->distance = new->fdistance = new->rdistance = EIGRP_MAX_METRIC; - new->destination_ipv4 = NULL; - new->destination_ipv6 = NULL; - - return new; + struct eigrp_prefix_entry *new; + new = XCALLOC(MTYPE_EIGRP_PREFIX_ENTRY, + sizeof(struct eigrp_prefix_entry)); + new->entries = list_new(); + new->rij = list_new(); + new->entries->cmp = (int (*)(void *, void *))eigrp_neighbor_entry_cmp; + new->distance = new->fdistance = new->rdistance = EIGRP_MAX_METRIC; + new->destination_ipv4 = NULL; + new->destination_ipv6 = NULL; + + return new; } /* * Topology entry comparison */ -static int -eigrp_neighbor_entry_cmp(struct eigrp_neighbor_entry *entry1, - struct eigrp_neighbor_entry *entry2) +static int eigrp_neighbor_entry_cmp(struct eigrp_neighbor_entry *entry1, + struct eigrp_neighbor_entry *entry2) { - if (entry1->distance < entry2->distance) // parameter used in list_add_sort () - return -1; // actually set to sort by distance - if (entry1->distance > entry2->distance) - return 1; + if (entry1->distance + < entry2->distance) // parameter used in list_add_sort () + return -1; // actually set to sort by distance + if (entry1->distance > entry2->distance) + return 1; - return 0; + return 0; } /* * Returns new topology entry */ -struct eigrp_neighbor_entry * -eigrp_neighbor_entry_new() +struct eigrp_neighbor_entry *eigrp_neighbor_entry_new() { - struct eigrp_neighbor_entry *new; + struct eigrp_neighbor_entry *new; - new = XCALLOC(MTYPE_EIGRP_NEIGHBOR_ENTRY, - sizeof(struct eigrp_neighbor_entry)); - new->reported_distance = EIGRP_MAX_METRIC; - new->distance = EIGRP_MAX_METRIC; + new = XCALLOC(MTYPE_EIGRP_NEIGHBOR_ENTRY, + sizeof(struct eigrp_neighbor_entry)); + new->reported_distance = EIGRP_MAX_METRIC; + new->distance = EIGRP_MAX_METRIC; - return new; + return new; } /* * Freeing topology table list */ -void -eigrp_topology_free(struct list *list) +void eigrp_topology_free(struct list *list) { - list_free(list); + list_free(list); } /* * Deleting all topology nodes in table */ -void -eigrp_topology_cleanup(struct list *topology) +void eigrp_topology_cleanup(struct list *topology) { - assert(topology); + assert(topology); - eigrp_topology_delete_all(topology); + eigrp_topology_delete_all(topology); } /* * Adding topology node to topology table */ -void -eigrp_prefix_entry_add(struct list *topology, struct eigrp_prefix_entry *node) +void eigrp_prefix_entry_add(struct list *topology, + struct eigrp_prefix_entry *node) { - if (listnode_lookup(topology, node) == NULL) - { - listnode_add_sort(topology, node); - } + if (listnode_lookup(topology, node) == NULL) { + listnode_add_sort(topology, node); + } } /* * Adding topology entry to topology node */ -void -eigrp_neighbor_entry_add(struct eigrp_prefix_entry *node, - struct eigrp_neighbor_entry *entry) +void eigrp_neighbor_entry_add(struct eigrp_prefix_entry *node, + struct eigrp_neighbor_entry *entry) { - struct list *l = list_new (); + struct list *l = list_new(); - listnode_add (l, entry); + listnode_add(l, entry); - if (listnode_lookup (node->entries, entry) == NULL) - { - listnode_add_sort (node->entries, entry); - entry->prefix = node; + if (listnode_lookup(node->entries, entry) == NULL) { + listnode_add_sort(node->entries, entry); + entry->prefix = node; - eigrp_zebra_route_add (node->destination_ipv4, l); - } + eigrp_zebra_route_add(node->destination_ipv4, l); + } - list_delete (l); + list_delete(l); } /* * Deleting topology node from topology table */ -void -eigrp_prefix_entry_delete(struct list *topology, - struct eigrp_prefix_entry *node) +void eigrp_prefix_entry_delete(struct list *topology, + struct eigrp_prefix_entry *node) { - struct eigrp *eigrp = eigrp_lookup (); - - /* - * Emergency removal of the node from this list. - * Whatever it is. - */ - listnode_delete (eigrp->topology_changes_internalIPV4, node); - - if (listnode_lookup (topology, node) != NULL) - { - list_delete_all_node (node->entries); - list_free (node->entries); - list_free (node->rij); - listnode_delete (topology, node); - eigrp_zebra_route_delete (node->destination_ipv4); - XFREE (MTYPE_EIGRP_PREFIX_ENTRY,node); - } + struct eigrp *eigrp = eigrp_lookup(); + + /* + * Emergency removal of the node from this list. + * Whatever it is. + */ + listnode_delete(eigrp->topology_changes_internalIPV4, node); + + if (listnode_lookup(topology, node) != NULL) { + list_delete_all_node(node->entries); + list_free(node->entries); + list_free(node->rij); + listnode_delete(topology, node); + eigrp_zebra_route_delete(node->destination_ipv4); + XFREE(MTYPE_EIGRP_PREFIX_ENTRY, node); + } } /* * Deleting topology entry from topology node */ -void -eigrp_neighbor_entry_delete(struct eigrp_prefix_entry *node, - struct eigrp_neighbor_entry *entry) +void eigrp_neighbor_entry_delete(struct eigrp_prefix_entry *node, + struct eigrp_neighbor_entry *entry) { - if (listnode_lookup(node->entries, entry) != NULL) - { - listnode_delete(node->entries, entry); - eigrp_zebra_route_delete (node->destination_ipv4); - XFREE(MTYPE_EIGRP_NEIGHBOR_ENTRY,entry); - } + if (listnode_lookup(node->entries, entry) != NULL) { + listnode_delete(node->entries, entry); + eigrp_zebra_route_delete(node->destination_ipv4); + XFREE(MTYPE_EIGRP_NEIGHBOR_ENTRY, entry); + } } /* * Deleting all nodes from topology table */ -void -eigrp_topology_delete_all(struct list *topology) +void eigrp_topology_delete_all(struct list *topology) { - list_delete_all_node(topology); + list_delete_all_node(topology); } /* * Return 0 if topology is not empty * otherwise return 1 */ -unsigned int -eigrp_topology_table_isempty(struct list *topology) +unsigned int eigrp_topology_table_isempty(struct list *topology) { - if (topology->count) - return 1; - else - return 0; + if (topology->count) + return 1; + else + return 0; } struct eigrp_prefix_entry * eigrp_topology_table_lookup_ipv4(struct list *topology_table, - struct prefix_ipv4 * address) + struct prefix_ipv4 *address) { - struct eigrp_prefix_entry *data; - struct listnode *node; - for (ALL_LIST_ELEMENTS_RO(topology_table, node, data)) - { - if ((data->af == AF_INET) - && (data->destination_ipv4->prefix.s_addr == address->prefix.s_addr) - && (data->destination_ipv4->prefixlen == address->prefixlen)) - return data; - } - - return NULL; + struct eigrp_prefix_entry *data; + struct listnode *node; + for (ALL_LIST_ELEMENTS_RO(topology_table, node, data)) { + if ((data->af == AF_INET) + && (data->destination_ipv4->prefix.s_addr + == address->prefix.s_addr) + && (data->destination_ipv4->prefixlen + == address->prefixlen)) + return data; + } + + return NULL; } /* @@ -317,256 +293,236 @@ eigrp_topology_table_lookup_ipv4(struct list *topology_table, * That way we can clean up all the list_new and list_delete's * that we are doing. DBS */ -struct list * -eigrp_topology_get_successor(struct eigrp_prefix_entry *table_node) +struct list *eigrp_topology_get_successor(struct eigrp_prefix_entry *table_node) { - struct list *successors = list_new(); - struct eigrp_neighbor_entry *data; - struct listnode *node1, *node2; - - for (ALL_LIST_ELEMENTS(table_node->entries, node1, node2, data)) - { - if (data->flags & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG) - { - listnode_add(successors, data); - } - } - - /* - * If we have no successors return NULL - */ - if (!successors->count) - { - list_delete(successors); - successors = NULL; - } - - return successors; + struct list *successors = list_new(); + struct eigrp_neighbor_entry *data; + struct listnode *node1, *node2; + + for (ALL_LIST_ELEMENTS(table_node->entries, node1, node2, data)) { + if (data->flags & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG) { + listnode_add(successors, data); + } + } + + /* + * If we have no successors return NULL + */ + if (!successors->count) { + list_delete(successors); + successors = NULL; + } + + return successors; } struct list * eigrp_topology_get_successor_max(struct eigrp_prefix_entry *table_node, - unsigned int maxpaths) + unsigned int maxpaths) { - struct list *successors = eigrp_topology_get_successor(table_node); - - if (successors && successors->count > maxpaths) - { - do - { - struct listnode *node = listtail(successors); + struct list *successors = eigrp_topology_get_successor(table_node); - list_delete_node(successors, node); + if (successors && successors->count > maxpaths) { + do { + struct listnode *node = listtail(successors); - } while (successors->count > maxpaths); - } + list_delete_node(successors, node); - return successors; + } while (successors->count > maxpaths); + } + + return successors; } struct eigrp_neighbor_entry * eigrp_prefix_entry_lookup(struct list *entries, struct eigrp_neighbor *nbr) { - struct eigrp_neighbor_entry *data; - struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS(entries, node, nnode, data)) - { - if (data->adv_router == nbr) - { - return data; - } - } - - return NULL; + struct eigrp_neighbor_entry *data; + struct listnode *node, *nnode; + for (ALL_LIST_ELEMENTS(entries, node, nnode, data)) { + if (data->adv_router == nbr) { + return data; + } + } + + return NULL; } /* Lookup all prefixes from specified neighbor */ -struct list * -eigrp_neighbor_prefixes_lookup(struct eigrp *eigrp, struct eigrp_neighbor *nbr) +struct list *eigrp_neighbor_prefixes_lookup(struct eigrp *eigrp, + struct eigrp_neighbor *nbr) { - struct listnode *node1, *node11, *node2, *node22; - struct eigrp_prefix_entry *prefix; - struct eigrp_neighbor_entry *entry; - - /* create new empty list for prefixes storage */ - struct list *prefixes = list_new(); - - /* iterate over all prefixes in topology table */ - for (ALL_LIST_ELEMENTS(eigrp->topology_table, node1, node11, prefix)) - { - /* iterate over all neighbor entry in prefix */ - for (ALL_LIST_ELEMENTS(prefix->entries, node2, node22, entry)) - { - /* if entry is from specified neighbor, add to list */ - if (entry->adv_router == nbr) - { - listnode_add(prefixes, prefix); - } - } - } - - /* return list of prefixes from specified neighbor */ - return prefixes; + struct listnode *node1, *node11, *node2, *node22; + struct eigrp_prefix_entry *prefix; + struct eigrp_neighbor_entry *entry; + + /* create new empty list for prefixes storage */ + struct list *prefixes = list_new(); + + /* iterate over all prefixes in topology table */ + for (ALL_LIST_ELEMENTS(eigrp->topology_table, node1, node11, prefix)) { + /* iterate over all neighbor entry in prefix */ + for (ALL_LIST_ELEMENTS(prefix->entries, node2, node22, entry)) { + /* if entry is from specified neighbor, add to list */ + if (entry->adv_router == nbr) { + listnode_add(prefixes, prefix); + } + } + } + + /* return list of prefixes from specified neighbor */ + return prefixes; } -int -eigrp_topology_update_distance(struct eigrp_fsm_action_message *msg) +int eigrp_topology_update_distance(struct eigrp_fsm_action_message *msg) { - struct eigrp *eigrp = msg->eigrp; - struct eigrp_prefix_entry *prefix = msg->prefix; - struct eigrp_neighbor_entry *entry = msg->entry; - int change = 0; - assert(entry); - - struct TLV_IPv4_External_type *ext_data = NULL; - struct TLV_IPv4_Internal_type *int_data = NULL; - if (msg->data_type == EIGRP_TLV_IPv4_INT) - { - int_data = msg->data.ipv4_int_type; - if (eigrp_metrics_is_same(int_data->metric, entry->reported_metric)) - { - return 0; // No change - } - change = - entry->reported_distance - < eigrp_calculate_metrics(eigrp, int_data->metric) ? 1 : - entry->reported_distance - > eigrp_calculate_metrics(eigrp, int_data->metric) ? 2 : 3; // Increase : Decrease : No change - entry->reported_metric = int_data->metric; - entry->reported_distance = - eigrp_calculate_metrics(eigrp, int_data->metric); - entry->distance = eigrp_calculate_total_metrics(eigrp, entry); - } - else - { - ext_data = msg->data.ipv4_ext_data; - if (eigrp_metrics_is_same (ext_data->metric, entry->reported_metric)) - return 0; - } - /* - * Move to correct position in list according to new distance - */ - listnode_delete(prefix->entries, entry); - listnode_add_sort(prefix->entries, entry); - - return change; + struct eigrp *eigrp = msg->eigrp; + struct eigrp_prefix_entry *prefix = msg->prefix; + struct eigrp_neighbor_entry *entry = msg->entry; + int change = 0; + assert(entry); + + struct TLV_IPv4_External_type *ext_data = NULL; + struct TLV_IPv4_Internal_type *int_data = NULL; + if (msg->data_type == EIGRP_TLV_IPv4_INT) { + int_data = msg->data.ipv4_int_type; + if (eigrp_metrics_is_same(int_data->metric, + entry->reported_metric)) { + return 0; // No change + } + change = entry->reported_distance + < eigrp_calculate_metrics( + eigrp, int_data->metric) + ? 1 + : entry->reported_distance + > eigrp_calculate_metrics( + eigrp, + int_data->metric) + ? 2 + : 3; // Increase : Decrease : No + // change + entry->reported_metric = int_data->metric; + entry->reported_distance = + eigrp_calculate_metrics(eigrp, int_data->metric); + entry->distance = eigrp_calculate_total_metrics(eigrp, entry); + } else { + ext_data = msg->data.ipv4_ext_data; + if (eigrp_metrics_is_same(ext_data->metric, + entry->reported_metric)) + return 0; + } + /* + * Move to correct position in list according to new distance + */ + listnode_delete(prefix->entries, entry); + listnode_add_sort(prefix->entries, entry); + + return change; } -void -eigrp_topology_update_all_node_flags(struct eigrp *eigrp) +void eigrp_topology_update_all_node_flags(struct eigrp *eigrp) { - struct list *table = eigrp->topology_table; - struct eigrp_prefix_entry *data; - struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS(table, node, nnode, data)) - { - eigrp_topology_update_node_flags(data); - } + struct list *table = eigrp->topology_table; + struct eigrp_prefix_entry *data; + struct listnode *node, *nnode; + for (ALL_LIST_ELEMENTS(table, node, nnode, data)) { + eigrp_topology_update_node_flags(data); + } } -void -eigrp_topology_update_node_flags(struct eigrp_prefix_entry *dest) +void eigrp_topology_update_node_flags(struct eigrp_prefix_entry *dest) { - struct listnode *node; - struct eigrp_neighbor_entry *entry; - struct eigrp * eigrp = eigrp_lookup(); - - for (ALL_LIST_ELEMENTS_RO(dest->entries, node, entry)) - { - if (((uint64_t)entry->distance <= (uint64_t)(dest->distance*eigrp->variance)) && - entry->distance != EIGRP_MAX_METRIC) // is successor - { - entry->flags |= EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG; - entry->flags &= ~EIGRP_NEIGHBOR_ENTRY_FSUCCESSOR_FLAG; - } - else if (entry->reported_distance < dest->fdistance) // is feasible successor - { - entry->flags |= EIGRP_NEIGHBOR_ENTRY_FSUCCESSOR_FLAG; - entry->flags &= ~EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG; - } - else - { - entry->flags &= ~EIGRP_NEIGHBOR_ENTRY_FSUCCESSOR_FLAG; - entry->flags &= ~EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG; - } - } + struct listnode *node; + struct eigrp_neighbor_entry *entry; + struct eigrp *eigrp = eigrp_lookup(); + + for (ALL_LIST_ELEMENTS_RO(dest->entries, node, entry)) { + if (((uint64_t)entry->distance + <= (uint64_t)(dest->distance * eigrp->variance)) + && entry->distance != EIGRP_MAX_METRIC) // is successor + { + entry->flags |= EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG; + entry->flags &= ~EIGRP_NEIGHBOR_ENTRY_FSUCCESSOR_FLAG; + } else if (entry->reported_distance + < dest->fdistance) // is feasible successor + { + entry->flags |= EIGRP_NEIGHBOR_ENTRY_FSUCCESSOR_FLAG; + entry->flags &= ~EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG; + } else { + entry->flags &= ~EIGRP_NEIGHBOR_ENTRY_FSUCCESSOR_FLAG; + entry->flags &= ~EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG; + } + } } -void -eigrp_update_routing_table(struct eigrp_prefix_entry * prefix) +void eigrp_update_routing_table(struct eigrp_prefix_entry *prefix) { - struct eigrp *eigrp = eigrp_lookup(); - struct list *successors = eigrp_topology_get_successor_max(prefix, eigrp->max_paths); - struct listnode *node; - struct eigrp_neighbor_entry *entry; - - if (successors) - { - eigrp_zebra_route_add(prefix->destination_ipv4, successors); - for (ALL_LIST_ELEMENTS_RO (successors, node, entry)) - entry->flags |= EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG; - - list_delete(successors); - } - else - { - eigrp_zebra_route_delete(prefix->destination_ipv4); - for (ALL_LIST_ELEMENTS_RO (prefix->entries, node, entry)) - entry->flags &= ~EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG; - } + struct eigrp *eigrp = eigrp_lookup(); + struct list *successors = + eigrp_topology_get_successor_max(prefix, eigrp->max_paths); + struct listnode *node; + struct eigrp_neighbor_entry *entry; + + if (successors) { + eigrp_zebra_route_add(prefix->destination_ipv4, successors); + for (ALL_LIST_ELEMENTS_RO(successors, node, entry)) + entry->flags |= EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG; + + list_delete(successors); + } else { + eigrp_zebra_route_delete(prefix->destination_ipv4); + for (ALL_LIST_ELEMENTS_RO(prefix->entries, node, entry)) + entry->flags &= ~EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG; + } } -void -eigrp_topology_neighbor_down(struct eigrp *eigrp, struct eigrp_neighbor * nbr) +void eigrp_topology_neighbor_down(struct eigrp *eigrp, + struct eigrp_neighbor *nbr) { - struct listnode *node1, *node11, *node2, *node22; - struct eigrp_prefix_entry *prefix; - struct eigrp_neighbor_entry *entry; - - for (ALL_LIST_ELEMENTS(eigrp->topology_table, node1, node11, prefix)) - { - for (ALL_LIST_ELEMENTS(prefix->entries, node2, node22, entry)) - { - if (entry->adv_router == nbr) - { - struct eigrp_fsm_action_message *msg; - msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct eigrp_fsm_action_message)); - struct TLV_IPv4_Internal_type * tlv = eigrp_IPv4_InternalTLV_new(); - tlv->metric.delay = EIGRP_MAX_METRIC; - msg->packet_type = EIGRP_OPC_UPDATE; - msg->eigrp = eigrp; - msg->data_type = EIGRP_TLV_IPv4_INT; - msg->adv_router = nbr; - msg->data.ipv4_int_type = tlv; - msg->entry = entry; - msg->prefix = prefix; - int event = eigrp_get_fsm_event(msg); - eigrp_fsm_event(msg, event); - } - } - } - - eigrp_query_send_all(eigrp); - eigrp_update_send_all(eigrp,nbr->ei); - + struct listnode *node1, *node11, *node2, *node22; + struct eigrp_prefix_entry *prefix; + struct eigrp_neighbor_entry *entry; + + for (ALL_LIST_ELEMENTS(eigrp->topology_table, node1, node11, prefix)) { + for (ALL_LIST_ELEMENTS(prefix->entries, node2, node22, entry)) { + if (entry->adv_router == nbr) { + struct eigrp_fsm_action_message *msg; + msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, + sizeof(struct + eigrp_fsm_action_message)); + struct TLV_IPv4_Internal_type *tlv = + eigrp_IPv4_InternalTLV_new(); + tlv->metric.delay = EIGRP_MAX_METRIC; + msg->packet_type = EIGRP_OPC_UPDATE; + msg->eigrp = eigrp; + msg->data_type = EIGRP_TLV_IPv4_INT; + msg->adv_router = nbr; + msg->data.ipv4_int_type = tlv; + msg->entry = entry; + msg->prefix = prefix; + int event = eigrp_get_fsm_event(msg); + eigrp_fsm_event(msg, event); + } + } + } + + eigrp_query_send_all(eigrp); + eigrp_update_send_all(eigrp, nbr->ei); } -void -eigrp_update_topology_table_prefix(struct list * table, struct eigrp_prefix_entry * prefix) +void eigrp_update_topology_table_prefix(struct list *table, + struct eigrp_prefix_entry *prefix) { - struct listnode *node1, *node2; - - struct eigrp_neighbor_entry *entry; - for (ALL_LIST_ELEMENTS(prefix->entries, node1, node2, entry)) - { - if(entry->distance == EIGRP_MAX_METRIC) - { - eigrp_neighbor_entry_delete(prefix,entry); - } - } - if(prefix->distance == EIGRP_MAX_METRIC && prefix->nt != EIGRP_TOPOLOGY_TYPE_CONNECTED) - { - eigrp_prefix_entry_delete(table,prefix); - } + struct listnode *node1, *node2; + + struct eigrp_neighbor_entry *entry; + for (ALL_LIST_ELEMENTS(prefix->entries, node1, node2, entry)) { + if (entry->distance == EIGRP_MAX_METRIC) { + eigrp_neighbor_entry_delete(prefix, entry); + } + } + if (prefix->distance == EIGRP_MAX_METRIC + && prefix->nt != EIGRP_TOPOLOGY_TYPE_CONNECTED) { + eigrp_prefix_entry_delete(table, prefix); + } } diff --git a/eigrpd/eigrp_topology.h b/eigrpd/eigrp_topology.h index 4ddc71f6f..1340c8210 100644 --- a/eigrpd/eigrp_topology.h +++ b/eigrpd/eigrp_topology.h @@ -32,30 +32,39 @@ #ifndef _ZEBRA_EIGRP_TOPOLOGY_H #define _ZEBRA_EIGRP_TOPOLOGY_H - /* EIGRP Topology table related functions. */ -extern struct list *eigrp_topology_new (void); -extern void eigrp_topology_init (struct list*); -extern struct eigrp_prefix_entry *eigrp_prefix_entry_new (void); -extern struct eigrp_neighbor_entry *eigrp_neighbor_entry_new (void); -extern void eigrp_topology_free (struct list *); -extern void eigrp_topology_cleanup (struct list *); -extern void eigrp_prefix_entry_add (struct list *, struct eigrp_prefix_entry *); -extern void eigrp_neighbor_entry_add (struct eigrp_prefix_entry *, struct eigrp_neighbor_entry *); -extern void eigrp_prefix_entry_delete (struct list *, struct eigrp_prefix_entry *); -extern void eigrp_neighbor_entry_delete (struct eigrp_prefix_entry *, struct eigrp_neighbor_entry *); -extern void eigrp_topology_delete_all (struct list *); -extern unsigned int eigrp_topology_table_isempty (struct list *); -extern struct eigrp_prefix_entry *eigrp_topology_table_lookup_ipv4 (struct list *, struct prefix_ipv4 *); -extern struct list *eigrp_topology_get_successor (struct eigrp_prefix_entry *); -extern struct list *eigrp_topology_get_successor_max (struct eigrp_prefix_entry *pe, unsigned int maxpaths); -extern struct eigrp_neighbor_entry *eigrp_prefix_entry_lookup (struct list *, struct eigrp_neighbor *); -extern struct list *eigrp_neighbor_prefixes_lookup(struct eigrp *, struct eigrp_neighbor *); -extern void eigrp_topology_update_all_node_flags (struct eigrp *); -extern void eigrp_topology_update_node_flags (struct eigrp_prefix_entry *); -extern int eigrp_topology_update_distance ( struct eigrp_fsm_action_message *); +extern struct list *eigrp_topology_new(void); +extern void eigrp_topology_init(struct list *); +extern struct eigrp_prefix_entry *eigrp_prefix_entry_new(void); +extern struct eigrp_neighbor_entry *eigrp_neighbor_entry_new(void); +extern void eigrp_topology_free(struct list *); +extern void eigrp_topology_cleanup(struct list *); +extern void eigrp_prefix_entry_add(struct list *, struct eigrp_prefix_entry *); +extern void eigrp_neighbor_entry_add(struct eigrp_prefix_entry *, + struct eigrp_neighbor_entry *); +extern void eigrp_prefix_entry_delete(struct list *, + struct eigrp_prefix_entry *); +extern void eigrp_neighbor_entry_delete(struct eigrp_prefix_entry *, + struct eigrp_neighbor_entry *); +extern void eigrp_topology_delete_all(struct list *); +extern unsigned int eigrp_topology_table_isempty(struct list *); +extern struct eigrp_prefix_entry * +eigrp_topology_table_lookup_ipv4(struct list *, struct prefix_ipv4 *); +extern struct list *eigrp_topology_get_successor(struct eigrp_prefix_entry *); +extern struct list * +eigrp_topology_get_successor_max(struct eigrp_prefix_entry *pe, + unsigned int maxpaths); +extern struct eigrp_neighbor_entry * +eigrp_prefix_entry_lookup(struct list *, struct eigrp_neighbor *); +extern struct list *eigrp_neighbor_prefixes_lookup(struct eigrp *, + struct eigrp_neighbor *); +extern void eigrp_topology_update_all_node_flags(struct eigrp *); +extern void eigrp_topology_update_node_flags(struct eigrp_prefix_entry *); +extern int eigrp_topology_update_distance(struct eigrp_fsm_action_message *); extern void eigrp_update_routing_table(struct eigrp_prefix_entry *); -extern void eigrp_topology_neighbor_down(struct eigrp *, struct eigrp_neighbor *); -extern void eigrp_update_topology_table_prefix(struct list *, struct eigrp_prefix_entry * ); +extern void eigrp_topology_neighbor_down(struct eigrp *, + struct eigrp_neighbor *); +extern void eigrp_update_topology_table_prefix(struct list *, + struct eigrp_prefix_entry *); #endif diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index c37bf4bbc..3c2ce6ce4 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -67,7 +67,8 @@ * @fn remove_received_prefix_gr * * @param[in] nbr_prefixes List of neighbor prefixes - * @param[in] recv_prefix Prefix which needs to be removed from list + * @param[in] recv_prefix Prefix which needs to be removed from + * list * * @return void * @@ -75,28 +76,27 @@ * Function is used for removing received prefix * from list of neighbor prefixes */ -static void -remove_received_prefix_gr (struct list *nbr_prefixes, struct eigrp_prefix_entry *recv_prefix) +static void remove_received_prefix_gr(struct list *nbr_prefixes, + struct eigrp_prefix_entry *recv_prefix) { - struct listnode *node1, *node11; - struct eigrp_prefix_entry *prefix = NULL; - - /* iterate over all prefixes in list */ - for (ALL_LIST_ELEMENTS(nbr_prefixes, node1, node11, prefix)) - { - /* remove prefix from list if found */ - if (prefix == recv_prefix) - { - listnode_delete(nbr_prefixes, prefix); - } - } + struct listnode *node1, *node11; + struct eigrp_prefix_entry *prefix = NULL; + + /* iterate over all prefixes in list */ + for (ALL_LIST_ELEMENTS(nbr_prefixes, node1, node11, prefix)) { + /* remove prefix from list if found */ + if (prefix == recv_prefix) { + listnode_delete(nbr_prefixes, prefix); + } + } } /** * @fn eigrp_update_receive_GR_ask * * @param[in] eigrp EIGRP process - * @param[in] nbr Neighbor update of who we received + * @param[in] nbr Neighbor update of who we + * received * @param[in] nbr_prefixes Prefixes which weren't advertised * * @return void @@ -106,650 +106,673 @@ remove_received_prefix_gr (struct list *nbr_prefixes, struct eigrp_prefix_entry * weren't advertised by neighbor: * We will send message to FSM with prefix delay set to infinity. */ -static void -eigrp_update_receive_GR_ask (struct eigrp *eigrp, struct eigrp_neighbor *nbr, struct list *nbr_prefixes) +static void eigrp_update_receive_GR_ask(struct eigrp *eigrp, + struct eigrp_neighbor *nbr, + struct list *nbr_prefixes) { - struct listnode *node1; - struct eigrp_prefix_entry *prefix; - struct TLV_IPv4_Internal_type *tlv_max; - - /* iterate over all prefixes which weren't advertised by neighbor */ - for (ALL_LIST_ELEMENTS_RO(nbr_prefixes, node1, prefix)) - { - zlog_debug("GR receive: Neighbor not advertised %s/%d", - inet_ntoa(prefix->destination_ipv4->prefix), - prefix->destination_ipv4->prefixlen); - - /* create internal IPv4 TLV with infinite delay */ - tlv_max = eigrp_IPv4_InternalTLV_new(); - tlv_max->type = EIGRP_TLV_IPv4_INT; - tlv_max->length = 28U; - tlv_max->metric = prefix->reported_metric; - /* set delay to MAX */ - tlv_max->metric.delay = EIGRP_MAX_METRIC; - tlv_max->destination = prefix->destination_ipv4->prefix; - tlv_max->prefix_length = prefix->destination_ipv4->prefixlen; - - - /* prepare message for FSM */ - struct eigrp_fsm_action_message *fsm_msg; - fsm_msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct eigrp_fsm_action_message)); - - struct eigrp_neighbor_entry *entry = - eigrp_prefix_entry_lookup(prefix->entries, nbr); - - fsm_msg->packet_type = EIGRP_OPC_UPDATE; - fsm_msg->eigrp = eigrp; - fsm_msg->data_type = EIGRP_TLV_IPv4_INT; - fsm_msg->adv_router = nbr; - fsm_msg->data.ipv4_int_type = tlv_max; - fsm_msg->entry = entry; - fsm_msg->prefix = prefix; - - /* send message to FSM */ - int event = eigrp_get_fsm_event(fsm_msg); - eigrp_fsm_event(fsm_msg, event); - - /* free memory used by TLV */ - eigrp_IPv4_InternalTLV_free (tlv_max); - } + struct listnode *node1; + struct eigrp_prefix_entry *prefix; + struct TLV_IPv4_Internal_type *tlv_max; + + /* iterate over all prefixes which weren't advertised by neighbor */ + for (ALL_LIST_ELEMENTS_RO(nbr_prefixes, node1, prefix)) { + zlog_debug("GR receive: Neighbor not advertised %s/%d", + inet_ntoa(prefix->destination_ipv4->prefix), + prefix->destination_ipv4->prefixlen); + + /* create internal IPv4 TLV with infinite delay */ + tlv_max = eigrp_IPv4_InternalTLV_new(); + tlv_max->type = EIGRP_TLV_IPv4_INT; + tlv_max->length = 28U; + tlv_max->metric = prefix->reported_metric; + /* set delay to MAX */ + tlv_max->metric.delay = EIGRP_MAX_METRIC; + tlv_max->destination = prefix->destination_ipv4->prefix; + tlv_max->prefix_length = prefix->destination_ipv4->prefixlen; + + + /* prepare message for FSM */ + struct eigrp_fsm_action_message *fsm_msg; + fsm_msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, + sizeof(struct eigrp_fsm_action_message)); + + struct eigrp_neighbor_entry *entry = + eigrp_prefix_entry_lookup(prefix->entries, nbr); + + fsm_msg->packet_type = EIGRP_OPC_UPDATE; + fsm_msg->eigrp = eigrp; + fsm_msg->data_type = EIGRP_TLV_IPv4_INT; + fsm_msg->adv_router = nbr; + fsm_msg->data.ipv4_int_type = tlv_max; + fsm_msg->entry = entry; + fsm_msg->prefix = prefix; + + /* send message to FSM */ + int event = eigrp_get_fsm_event(fsm_msg); + eigrp_fsm_event(fsm_msg, event); + + /* free memory used by TLV */ + eigrp_IPv4_InternalTLV_free(tlv_max); + } } /* * EIGRP UPDATE read function */ -void -eigrp_update_receive (struct eigrp *eigrp, struct ip *iph, struct eigrp_header *eigrph, - struct stream * s, struct eigrp_interface *ei, int size) +void eigrp_update_receive(struct eigrp *eigrp, struct ip *iph, + struct eigrp_header *eigrph, struct stream *s, + struct eigrp_interface *ei, int size) { - struct eigrp_neighbor *nbr; - struct TLV_IPv4_Internal_type *tlv; - struct eigrp_prefix_entry *pe; - struct eigrp_neighbor_entry *ne; - u_int32_t flags; - u_int16_t type; - u_char same; - struct access_list *alist; - struct prefix_list *plist; - struct eigrp *e; - u_char graceful_restart; - u_char graceful_restart_final; - struct list *nbr_prefixes = NULL; - - /* increment statistics. */ - ei->update_in++; - - /* get neighbor struct */ - nbr = eigrp_nbr_get(ei, eigrph, iph); - - /* neighbor must be valid, eigrp_nbr_get creates if none existed */ - assert(nbr); - - flags = ntohl(eigrph->flags); - - if (flags & EIGRP_CR_FLAG) - { - return; - } - - same = 0; - graceful_restart = 0; - graceful_restart_final = 0; - if((nbr->recv_sequence_number) == (ntohl(eigrph->sequence))) - same = 1; - - nbr->recv_sequence_number = ntohl(eigrph->sequence); - if (IS_DEBUG_EIGRP_PACKET(0, RECV)) - zlog_debug("Processing Update size[%u] int(%s) nbr(%s) seq [%u] flags [%0x]", - size, ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT), - inet_ntoa(nbr->src), - nbr->recv_sequence_number, flags); - - - if((flags == (EIGRP_INIT_FLAG+EIGRP_RS_FLAG+EIGRP_EOT_FLAG)) && (!same)) - { - /* Graceful restart Update received with all routes */ - - zlog_info("Neighbor %s (%s) is resync: peer graceful-restart", - inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); - - /* get all prefixes from neighbor from topology table */ - nbr_prefixes = eigrp_neighbor_prefixes_lookup(eigrp, nbr); - graceful_restart = 1; - graceful_restart_final = 1; - } - else if((flags == (EIGRP_INIT_FLAG+EIGRP_RS_FLAG)) && (!same)) - { - /* Graceful restart Update received, routes also in next packet */ - - zlog_info("Neighbor %s (%s) is resync: peer graceful-restart", - inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); - - /* get all prefixes from neighbor from topology table */ - nbr_prefixes = eigrp_neighbor_prefixes_lookup(eigrp, nbr); - /* save prefixes to neighbor for later use */ - nbr->nbr_gr_prefixes = nbr_prefixes; - graceful_restart = 1; - graceful_restart_final = 0; - } - else if((flags == (EIGRP_EOT_FLAG)) && (!same)) - { - /* If there was INIT+RS Update packet before, - * consider this as GR EOT */ - - if(nbr->nbr_gr_prefixes != NULL) - { - /* this is final packet of GR */ - nbr_prefixes = nbr->nbr_gr_prefixes; - nbr->nbr_gr_prefixes = NULL; - - graceful_restart = 1; - graceful_restart_final = 1; - } - - } - else if((flags == (0)) && (!same)) - { - /* If there was INIT+RS Update packet before, - * consider this as GR not final packet */ - - if(nbr->nbr_gr_prefixes != NULL) - { - /* this is GR not final route packet */ - nbr_prefixes = nbr->nbr_gr_prefixes; - - graceful_restart = 1; - graceful_restart_final = 0; - } - - } - else if((flags & EIGRP_INIT_FLAG) && (!same)) - { /* When in pending state, send INIT update only if it wasn't - already sent before (only if init_sequence is 0) */ - if((nbr->state == EIGRP_NEIGHBOR_PENDING) && (nbr->init_sequence_number == 0)) - eigrp_update_send_init(nbr); - - if (nbr->state == EIGRP_NEIGHBOR_UP) - { - eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN); - eigrp_topology_neighbor_down(nbr->ei->eigrp,nbr); - nbr->recv_sequence_number = ntohl(eigrph->sequence); - zlog_info("Neighbor %s (%s) is down: peer restarted", - inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); - eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_PENDING); - zlog_info("Neighbor %s (%s) is pending: new adjacency", - inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); - eigrp_update_send_init(nbr); - } - } - - /*If there is topology information*/ - while (s->endp > s->getp) - { - type = stream_getw(s); - if (type == EIGRP_TLV_IPv4_INT) - { - struct prefix_ipv4 dest_addr; - - stream_set_getp(s, s->getp - sizeof(u_int16_t)); - - tlv = eigrp_read_ipv4_tlv(s); - - /*searching if destination exists */ - dest_addr.family = AF_INET; - dest_addr.prefix = tlv->destination; - dest_addr.prefixlen = tlv->prefix_length; - struct eigrp_prefix_entry *dest = - eigrp_topology_table_lookup_ipv4(eigrp->topology_table, &dest_addr); - - /*if exists it comes to DUAL*/ - if (dest != NULL) - { - /* remove received prefix from neighbor prefix list if in GR */ - if(graceful_restart) - remove_received_prefix_gr(nbr_prefixes, dest); - - struct eigrp_fsm_action_message *msg; - msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct eigrp_fsm_action_message)); - struct eigrp_neighbor_entry *entry = - eigrp_prefix_entry_lookup(dest->entries, nbr); - - msg->packet_type = EIGRP_OPC_UPDATE; - msg->eigrp = eigrp; - msg->data_type = EIGRP_TLV_IPv4_INT; - msg->adv_router = nbr; - msg->data.ipv4_int_type = tlv; - msg->entry = entry; - msg->prefix = dest; - int event = eigrp_get_fsm_event(msg); - eigrp_fsm_event(msg, event); - } - else - { - /*Here comes topology information save*/ - pe = eigrp_prefix_entry_new(); - pe->serno = eigrp->serno; - pe->destination_ipv4 = prefix_ipv4_new(); - prefix_copy((struct prefix *)pe->destination_ipv4, - (struct prefix *)&dest_addr); - pe->af = AF_INET; - pe->state = EIGRP_FSM_STATE_PASSIVE; - pe->nt = EIGRP_TOPOLOGY_TYPE_REMOTE; - - ne = eigrp_neighbor_entry_new(); - ne->ei = ei; - ne->adv_router = nbr; - ne->reported_metric = tlv->metric; - ne->reported_distance = - eigrp_calculate_metrics(eigrp, - tlv->metric); - /* - * Filtering - */ - e = eigrp_lookup(); - /* - * Check if there is any access-list on interface (IN direction) - * and set distance to max - */ - alist = ei->list[EIGRP_FILTER_IN]; - - /* Check if access-list fits */ - if (alist && - access_list_apply (alist, (struct prefix *)&dest_addr) == FILTER_DENY) - { - /* If yes, set reported metric to Max */ - ne->reported_metric.delay = EIGRP_MAX_METRIC; - } else { - ne->distance = eigrp_calculate_total_metrics(eigrp, ne); - } - - plist = e->prefix[EIGRP_FILTER_IN]; - - /* Check if prefix-list fits */ - if (plist && - prefix_list_apply (plist, (struct prefix *)&dest_addr) == PREFIX_DENY) - { - /* If yes, set reported metric to Max */ - ne->reported_metric.delay = EIGRP_MAX_METRIC; - } - - /*Get access-list from current interface */ - alist = ei->list[EIGRP_FILTER_IN]; - - /* Check if access-list fits */ - if (alist && - access_list_apply (alist, (struct prefix *)&dest_addr) == FILTER_DENY) - { - /* If yes, set reported metric to Max */ - ne->reported_metric.delay = EIGRP_MAX_METRIC; - } - - plist = ei->prefix[EIGRP_FILTER_IN]; - - /* Check if prefix-list fits */ - if (plist && - prefix_list_apply (plist, (struct prefix *)&dest_addr) == PREFIX_DENY) - { - /* If yes, set reported metric to Max */ - ne->reported_metric.delay = EIGRP_MAX_METRIC; - } - /* - * End of filtering - */ - - ne->distance = eigrp_calculate_total_metrics(eigrp, ne); - - pe->fdistance = pe->distance = pe->rdistance = - ne->distance; - ne->prefix = pe; - ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG; - - eigrp_prefix_entry_add(eigrp->topology_table, pe); - eigrp_neighbor_entry_add(pe, ne); - pe->distance = pe->fdistance = pe->rdistance = - ne->distance; - pe->reported_metric = ne->total_metric; - eigrp_topology_update_node_flags(pe); - - pe->req_action |= EIGRP_FSM_NEED_UPDATE; - listnode_add(eigrp->topology_changes_internalIPV4, pe); - } - eigrp_IPv4_InternalTLV_free (tlv); - } - } - - /* ask about prefixes not present in GR update, - * if this is final GR packet */ - if(graceful_restart_final) - { - eigrp_update_receive_GR_ask(eigrp, nbr, nbr_prefixes); - } - - /* - * We don't need to send separate Ack for INIT Update. INIT will be acked in EOT Update. - */ - if ((nbr->state == EIGRP_NEIGHBOR_UP) && !(flags == EIGRP_INIT_FLAG)) - { - eigrp_hello_send_ack(nbr); - } - - eigrp_query_send_all(eigrp); - eigrp_update_send_all(eigrp, ei); + struct eigrp_neighbor *nbr; + struct TLV_IPv4_Internal_type *tlv; + struct eigrp_prefix_entry *pe; + struct eigrp_neighbor_entry *ne; + u_int32_t flags; + u_int16_t type; + u_char same; + struct access_list *alist; + struct prefix_list *plist; + struct eigrp *e; + u_char graceful_restart; + u_char graceful_restart_final; + struct list *nbr_prefixes = NULL; + + /* increment statistics. */ + ei->update_in++; + + /* get neighbor struct */ + nbr = eigrp_nbr_get(ei, eigrph, iph); + + /* neighbor must be valid, eigrp_nbr_get creates if none existed */ + assert(nbr); + + flags = ntohl(eigrph->flags); + + if (flags & EIGRP_CR_FLAG) { + return; + } + + same = 0; + graceful_restart = 0; + graceful_restart_final = 0; + if ((nbr->recv_sequence_number) == (ntohl(eigrph->sequence))) + same = 1; + + nbr->recv_sequence_number = ntohl(eigrph->sequence); + if (IS_DEBUG_EIGRP_PACKET(0, RECV)) + zlog_debug( + "Processing Update size[%u] int(%s) nbr(%s) seq [%u] flags [%0x]", + size, + ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT), + inet_ntoa(nbr->src), nbr->recv_sequence_number, flags); + + + if ((flags == (EIGRP_INIT_FLAG + EIGRP_RS_FLAG + EIGRP_EOT_FLAG)) + && (!same)) { + /* Graceful restart Update received with all routes */ + + zlog_info("Neighbor %s (%s) is resync: peer graceful-restart", + inet_ntoa(nbr->src), + ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); + + /* get all prefixes from neighbor from topology table */ + nbr_prefixes = eigrp_neighbor_prefixes_lookup(eigrp, nbr); + graceful_restart = 1; + graceful_restart_final = 1; + } else if ((flags == (EIGRP_INIT_FLAG + EIGRP_RS_FLAG)) && (!same)) { + /* Graceful restart Update received, routes also in next packet + */ + + zlog_info("Neighbor %s (%s) is resync: peer graceful-restart", + inet_ntoa(nbr->src), + ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); + + /* get all prefixes from neighbor from topology table */ + nbr_prefixes = eigrp_neighbor_prefixes_lookup(eigrp, nbr); + /* save prefixes to neighbor for later use */ + nbr->nbr_gr_prefixes = nbr_prefixes; + graceful_restart = 1; + graceful_restart_final = 0; + } else if ((flags == (EIGRP_EOT_FLAG)) && (!same)) { + /* If there was INIT+RS Update packet before, + * consider this as GR EOT */ + + if (nbr->nbr_gr_prefixes != NULL) { + /* this is final packet of GR */ + nbr_prefixes = nbr->nbr_gr_prefixes; + nbr->nbr_gr_prefixes = NULL; + + graceful_restart = 1; + graceful_restart_final = 1; + } + + } else if ((flags == (0)) && (!same)) { + /* If there was INIT+RS Update packet before, + * consider this as GR not final packet */ + + if (nbr->nbr_gr_prefixes != NULL) { + /* this is GR not final route packet */ + nbr_prefixes = nbr->nbr_gr_prefixes; + + graceful_restart = 1; + graceful_restart_final = 0; + } + + } else if ((flags & EIGRP_INIT_FLAG) + && (!same)) { /* When in pending state, send INIT update only + if it wasn't + already sent before (only if init_sequence + is 0) */ + if ((nbr->state == EIGRP_NEIGHBOR_PENDING) + && (nbr->init_sequence_number == 0)) + eigrp_update_send_init(nbr); + + if (nbr->state == EIGRP_NEIGHBOR_UP) { + eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN); + eigrp_topology_neighbor_down(nbr->ei->eigrp, nbr); + nbr->recv_sequence_number = ntohl(eigrph->sequence); + zlog_info("Neighbor %s (%s) is down: peer restarted", + inet_ntoa(nbr->src), + ifindex2ifname(nbr->ei->ifp->ifindex, + VRF_DEFAULT)); + eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_PENDING); + zlog_info("Neighbor %s (%s) is pending: new adjacency", + inet_ntoa(nbr->src), + ifindex2ifname(nbr->ei->ifp->ifindex, + VRF_DEFAULT)); + eigrp_update_send_init(nbr); + } + } + + /*If there is topology information*/ + while (s->endp > s->getp) { + type = stream_getw(s); + if (type == EIGRP_TLV_IPv4_INT) { + struct prefix_ipv4 dest_addr; + + stream_set_getp(s, s->getp - sizeof(u_int16_t)); + + tlv = eigrp_read_ipv4_tlv(s); + + /*searching if destination exists */ + dest_addr.family = AF_INET; + dest_addr.prefix = tlv->destination; + dest_addr.prefixlen = tlv->prefix_length; + struct eigrp_prefix_entry *dest = + eigrp_topology_table_lookup_ipv4( + eigrp->topology_table, &dest_addr); + + /*if exists it comes to DUAL*/ + if (dest != NULL) { + /* remove received prefix from neighbor prefix + * list if in GR */ + if (graceful_restart) + remove_received_prefix_gr(nbr_prefixes, + dest); + + struct eigrp_fsm_action_message *msg; + msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, + sizeof(struct + eigrp_fsm_action_message)); + struct eigrp_neighbor_entry *entry = + eigrp_prefix_entry_lookup(dest->entries, + nbr); + + msg->packet_type = EIGRP_OPC_UPDATE; + msg->eigrp = eigrp; + msg->data_type = EIGRP_TLV_IPv4_INT; + msg->adv_router = nbr; + msg->data.ipv4_int_type = tlv; + msg->entry = entry; + msg->prefix = dest; + int event = eigrp_get_fsm_event(msg); + eigrp_fsm_event(msg, event); + } else { + /*Here comes topology information save*/ + pe = eigrp_prefix_entry_new(); + pe->serno = eigrp->serno; + pe->destination_ipv4 = prefix_ipv4_new(); + prefix_copy( + (struct prefix *)pe->destination_ipv4, + (struct prefix *)&dest_addr); + pe->af = AF_INET; + pe->state = EIGRP_FSM_STATE_PASSIVE; + pe->nt = EIGRP_TOPOLOGY_TYPE_REMOTE; + + ne = eigrp_neighbor_entry_new(); + ne->ei = ei; + ne->adv_router = nbr; + ne->reported_metric = tlv->metric; + ne->reported_distance = eigrp_calculate_metrics( + eigrp, tlv->metric); + /* + * Filtering + */ + e = eigrp_lookup(); + /* + * Check if there is any access-list on + * interface (IN direction) + * and set distance to max + */ + alist = ei->list[EIGRP_FILTER_IN]; + + /* Check if access-list fits */ + if (alist + && access_list_apply( + alist, + (struct prefix *)&dest_addr) + == FILTER_DENY) { + /* If yes, set reported metric to Max */ + ne->reported_metric.delay = + EIGRP_MAX_METRIC; + } else { + ne->distance = + eigrp_calculate_total_metrics( + eigrp, ne); + } + + plist = e->prefix[EIGRP_FILTER_IN]; + + /* Check if prefix-list fits */ + if (plist + && prefix_list_apply( + plist, + (struct prefix *)&dest_addr) + == PREFIX_DENY) { + /* If yes, set reported metric to Max */ + ne->reported_metric.delay = + EIGRP_MAX_METRIC; + } + + /*Get access-list from current interface */ + alist = ei->list[EIGRP_FILTER_IN]; + + /* Check if access-list fits */ + if (alist + && access_list_apply( + alist, + (struct prefix *)&dest_addr) + == FILTER_DENY) { + /* If yes, set reported metric to Max */ + ne->reported_metric.delay = + EIGRP_MAX_METRIC; + } + + plist = ei->prefix[EIGRP_FILTER_IN]; + + /* Check if prefix-list fits */ + if (plist + && prefix_list_apply( + plist, + (struct prefix *)&dest_addr) + == PREFIX_DENY) { + /* If yes, set reported metric to Max */ + ne->reported_metric.delay = + EIGRP_MAX_METRIC; + } + /* + * End of filtering + */ + + ne->distance = eigrp_calculate_total_metrics( + eigrp, ne); + + pe->fdistance = pe->distance = pe->rdistance = + ne->distance; + ne->prefix = pe; + ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG; + + eigrp_prefix_entry_add(eigrp->topology_table, + pe); + eigrp_neighbor_entry_add(pe, ne); + pe->distance = pe->fdistance = pe->rdistance = + ne->distance; + pe->reported_metric = ne->total_metric; + eigrp_topology_update_node_flags(pe); + + pe->req_action |= EIGRP_FSM_NEED_UPDATE; + listnode_add( + eigrp->topology_changes_internalIPV4, + pe); + } + eigrp_IPv4_InternalTLV_free(tlv); + } + } + + /* ask about prefixes not present in GR update, + * if this is final GR packet */ + if (graceful_restart_final) { + eigrp_update_receive_GR_ask(eigrp, nbr, nbr_prefixes); + } + + /* + * We don't need to send separate Ack for INIT Update. INIT will be + * acked in EOT Update. + */ + if ((nbr->state == EIGRP_NEIGHBOR_UP) && !(flags == EIGRP_INIT_FLAG)) { + eigrp_hello_send_ack(nbr); + } + + eigrp_query_send_all(eigrp); + eigrp_update_send_all(eigrp, ei); } /*send EIGRP Update packet*/ -void -eigrp_update_send_init (struct eigrp_neighbor *nbr) +void eigrp_update_send_init(struct eigrp_neighbor *nbr) { - struct eigrp_packet *ep; - u_int16_t length = EIGRP_HEADER_LEN; - - ep = eigrp_packet_new(nbr->ei->ifp->mtu); - - /* Prepare EIGRP INIT UPDATE header */ - if (IS_DEBUG_EIGRP_PACKET(0, RECV)) - zlog_debug("Enqueuing Update Init Seq [%u] Ack [%u]", - nbr->ei->eigrp->sequence_number, - nbr->recv_sequence_number); - - eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_INIT_FLAG, - nbr->ei->eigrp->sequence_number, - nbr->recv_sequence_number); - - // encode Authentication TLV, if needed - if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && - (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL)) - { - length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei); - eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_INIT_FLAG); - } - - /* EIGRP Checksum */ - eigrp_packet_checksum(nbr->ei, ep->s, length); - - ep->length = length; - ep->dst.s_addr = nbr->src.s_addr; - - /*This ack number we await from neighbor*/ - nbr->init_sequence_number = nbr->ei->eigrp->sequence_number; - ep->sequence_number = nbr->ei->eigrp->sequence_number; - if (IS_DEBUG_EIGRP_PACKET(0, RECV)) - zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]", - ep->length, ep->sequence_number, inet_ntoa(ep->dst)); - - /*Put packet to retransmission queue*/ - eigrp_fifo_push_head(nbr->retrans_queue, ep); - - if (nbr->retrans_queue->count == 1) - { - eigrp_send_packet_reliably(nbr); - } + struct eigrp_packet *ep; + u_int16_t length = EIGRP_HEADER_LEN; + + ep = eigrp_packet_new(nbr->ei->ifp->mtu); + + /* Prepare EIGRP INIT UPDATE header */ + if (IS_DEBUG_EIGRP_PACKET(0, RECV)) + zlog_debug("Enqueuing Update Init Seq [%u] Ack [%u]", + nbr->ei->eigrp->sequence_number, + nbr->recv_sequence_number); + + eigrp_packet_header_init( + EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_INIT_FLAG, + nbr->ei->eigrp->sequence_number, nbr->recv_sequence_number); + + // encode Authentication TLV, if needed + if ((IF_DEF_PARAMS(nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) + && (IF_DEF_PARAMS(nbr->ei->ifp)->auth_keychain != NULL)) { + length += eigrp_add_authTLV_MD5_to_stream(ep->s, nbr->ei); + eigrp_make_md5_digest(nbr->ei, ep->s, + EIGRP_AUTH_UPDATE_INIT_FLAG); + } + + /* EIGRP Checksum */ + eigrp_packet_checksum(nbr->ei, ep->s, length); + + ep->length = length; + ep->dst.s_addr = nbr->src.s_addr; + + /*This ack number we await from neighbor*/ + nbr->init_sequence_number = nbr->ei->eigrp->sequence_number; + ep->sequence_number = nbr->ei->eigrp->sequence_number; + if (IS_DEBUG_EIGRP_PACKET(0, RECV)) + zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]", + ep->length, ep->sequence_number, inet_ntoa(ep->dst)); + + /*Put packet to retransmission queue*/ + eigrp_fifo_push_head(nbr->retrans_queue, ep); + + if (nbr->retrans_queue->count == 1) { + eigrp_send_packet_reliably(nbr); + } } -void -eigrp_update_send_EOT (struct eigrp_neighbor *nbr) +void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) { - struct eigrp_packet *ep; - // struct eigrp_packet *ep_multicast; - u_int16_t length = EIGRP_HEADER_LEN; - struct eigrp_neighbor_entry *te; - struct eigrp_prefix_entry *pe; - struct listnode *node, *node2, *nnode, *nnode2; - struct access_list *alist; - struct prefix_list *plist; - struct access_list *alist_i; - struct prefix_list *plist_i; - struct eigrp *e; - struct prefix_ipv4 *dest_addr; - - ep = eigrp_packet_new(nbr->ei->ifp->mtu); - - /* Prepare EIGRP EOT UPDATE header */ - eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_EOT_FLAG, - nbr->ei->eigrp->sequence_number, - nbr->recv_sequence_number); - - // encode Authentication TLV, if needed - if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL)) - { - length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei); - } - - for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node, nnode, pe)) - { - for (ALL_LIST_ELEMENTS(pe->entries, node2, nnode2, te)) - { - if ((te->ei == nbr->ei) - && (te->prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE)) - continue; - - /* Get destination address from prefix */ - dest_addr = pe->destination_ipv4; - - /* - * Filtering - */ - //TODO: Work in progress - /* get list from eigrp process */ - e = eigrp_lookup(); - /* Get access-lists and prefix-lists from process and interface */ - alist = e->list[EIGRP_FILTER_OUT]; - plist = e->prefix[EIGRP_FILTER_OUT]; - alist_i = nbr->ei->list[EIGRP_FILTER_OUT]; - plist_i = nbr->ei->prefix[EIGRP_FILTER_OUT]; - - /* Check if any list fits */ - if ((alist && access_list_apply (alist, - (struct prefix *) dest_addr) == FILTER_DENY)|| - (plist && prefix_list_apply (plist, - (struct prefix *) dest_addr) == PREFIX_DENY)|| - (alist_i && access_list_apply (alist_i, - (struct prefix *) dest_addr) == FILTER_DENY)|| - (plist_i && prefix_list_apply (plist_i, - (struct prefix *) dest_addr) == PREFIX_DENY)) - { - zlog_info("PROC OUT EOT: Skipping"); - //pe->reported_metric.delay = EIGRP_MAX_METRIC; - zlog_info("PROC OUT EOT Prefix: %s", inet_ntoa(dest_addr->prefix)); - continue; - } else { - zlog_info("PROC OUT EOT: NENastavujem metriku "); - length += eigrp_add_internalTLV_to_stream(ep->s, pe); - } - /* - * End of filtering - */ - - /* NULL the pointer */ - dest_addr = NULL; - - } - } - - if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && - (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL)) - { - eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_FLAG); - } - - /* EIGRP Checksum */ - eigrp_packet_checksum(nbr->ei, ep->s, length); - - ep->length = length; - ep->dst.s_addr = nbr->src.s_addr; - - /*This ack number we await from neighbor*/ - ep->sequence_number = nbr->ei->eigrp->sequence_number; - - if (IS_DEBUG_EIGRP_PACKET(0, RECV)) - zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]", - ep->length, ep->sequence_number, inet_ntoa(ep->dst)); - - /*Put packet to retransmission queue*/ - eigrp_fifo_push_head(nbr->retrans_queue, ep); - - if (nbr->retrans_queue->count == 1) - { - eigrp_send_packet_reliably(nbr); - } + struct eigrp_packet *ep; + // struct eigrp_packet *ep_multicast; + u_int16_t length = EIGRP_HEADER_LEN; + struct eigrp_neighbor_entry *te; + struct eigrp_prefix_entry *pe; + struct listnode *node, *node2, *nnode, *nnode2; + struct access_list *alist; + struct prefix_list *plist; + struct access_list *alist_i; + struct prefix_list *plist_i; + struct eigrp *e; + struct prefix_ipv4 *dest_addr; + + ep = eigrp_packet_new(nbr->ei->ifp->mtu); + + /* Prepare EIGRP EOT UPDATE header */ + eigrp_packet_header_init( + EIGRP_OPC_UPDATE, nbr->ei, ep->s, EIGRP_EOT_FLAG, + nbr->ei->eigrp->sequence_number, nbr->recv_sequence_number); + + // encode Authentication TLV, if needed + if ((IF_DEF_PARAMS(nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) + && (IF_DEF_PARAMS(nbr->ei->ifp)->auth_keychain != NULL)) { + length += eigrp_add_authTLV_MD5_to_stream(ep->s, nbr->ei); + } + + for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node, nnode, + pe)) { + for (ALL_LIST_ELEMENTS(pe->entries, node2, nnode2, te)) { + if ((te->ei == nbr->ei) + && (te->prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE)) + continue; + + /* Get destination address from prefix */ + dest_addr = pe->destination_ipv4; + + /* + * Filtering + */ + // TODO: Work in progress + /* get list from eigrp process */ + e = eigrp_lookup(); + /* Get access-lists and prefix-lists from process and + * interface */ + alist = e->list[EIGRP_FILTER_OUT]; + plist = e->prefix[EIGRP_FILTER_OUT]; + alist_i = nbr->ei->list[EIGRP_FILTER_OUT]; + plist_i = nbr->ei->prefix[EIGRP_FILTER_OUT]; + + /* Check if any list fits */ + if ((alist + && access_list_apply(alist, + (struct prefix *)dest_addr) + == FILTER_DENY) + || (plist + && prefix_list_apply(plist, + (struct prefix *)dest_addr) + == PREFIX_DENY) + || (alist_i + && access_list_apply(alist_i, + (struct prefix *)dest_addr) + == FILTER_DENY) + || (plist_i + && prefix_list_apply(plist_i, + (struct prefix *)dest_addr) + == PREFIX_DENY)) { + zlog_info("PROC OUT EOT: Skipping"); + // pe->reported_metric.delay = EIGRP_MAX_METRIC; + zlog_info("PROC OUT EOT Prefix: %s", + inet_ntoa(dest_addr->prefix)); + continue; + } else { + zlog_info( + "PROC OUT EOT: NENastavujem metriku "); + length += eigrp_add_internalTLV_to_stream(ep->s, + pe); + } + /* + * End of filtering + */ + + /* NULL the pointer */ + dest_addr = NULL; + } + } + + if ((IF_DEF_PARAMS(nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) + && (IF_DEF_PARAMS(nbr->ei->ifp)->auth_keychain != NULL)) { + eigrp_make_md5_digest(nbr->ei, ep->s, EIGRP_AUTH_UPDATE_FLAG); + } + + /* EIGRP Checksum */ + eigrp_packet_checksum(nbr->ei, ep->s, length); + + ep->length = length; + ep->dst.s_addr = nbr->src.s_addr; + + /*This ack number we await from neighbor*/ + ep->sequence_number = nbr->ei->eigrp->sequence_number; + + if (IS_DEBUG_EIGRP_PACKET(0, RECV)) + zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]", + ep->length, ep->sequence_number, inet_ntoa(ep->dst)); + + /*Put packet to retransmission queue*/ + eigrp_fifo_push_head(nbr->retrans_queue, ep); + + if (nbr->retrans_queue->count == 1) { + eigrp_send_packet_reliably(nbr); + } } -void -eigrp_update_send (struct eigrp_interface *ei) +void eigrp_update_send(struct eigrp_interface *ei) { - struct eigrp_packet *ep; - struct listnode *node, *nnode; - struct eigrp_neighbor *nbr; - struct eigrp_prefix_entry *pe; - u_char has_tlv; - struct access_list *alist; - struct prefix_list *plist; - struct access_list *alist_i; - struct prefix_list *plist_i; - struct eigrp *e; - struct prefix_ipv4 *dest_addr; - bool packet_sent = false; - - u_int16_t length = EIGRP_HEADER_LEN; - - ep = eigrp_packet_new(ei->ifp->mtu); - - /* Prepare EIGRP INIT UPDATE header */ - eigrp_packet_header_init(EIGRP_OPC_UPDATE, ei, ep->s, 0, - ei->eigrp->sequence_number, 0); - - // encode Authentication TLV, if needed - if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && - (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL)) - { - length += eigrp_add_authTLV_MD5_to_stream(ep->s,ei); - } - - has_tlv = 0; - for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node, nnode, pe)) - { - if(pe->req_action & EIGRP_FSM_NEED_UPDATE) - { - /* Get destination address from prefix */ - dest_addr = pe->destination_ipv4; - - /* - * Filtering - */ - //TODO: Work in progress - /* get list from eigrp process */ - e = eigrp_lookup(); - /* Get access-lists and prefix-lists from process and interface */ - alist = e->list[EIGRP_FILTER_OUT]; - plist = e->prefix[EIGRP_FILTER_OUT]; - alist_i = ei->list[EIGRP_FILTER_OUT]; - plist_i = ei->prefix[EIGRP_FILTER_OUT]; - - /* Check if any list fits */ - if ((alist && access_list_apply (alist, - (struct prefix *) dest_addr) == FILTER_DENY)|| - (plist && prefix_list_apply (plist, - (struct prefix *) dest_addr) == PREFIX_DENY)|| - (alist_i && access_list_apply (alist_i, - (struct prefix *) dest_addr) == FILTER_DENY)|| - (plist_i && prefix_list_apply (plist_i, - (struct prefix *) dest_addr) == PREFIX_DENY)) - { - zlog_info("PROC OUT: Skipping"); - //pe->reported_metric.delay = EIGRP_MAX_METRIC; - zlog_info("PROC OUT Prefix: %s", inet_ntoa(dest_addr->prefix)); - continue; - } else { - zlog_info("PROC OUT: NENastavujem metriku "); - length += eigrp_add_internalTLV_to_stream(ep->s, pe); - has_tlv = 1; - } - /* - * End of filtering - */ - - /* NULL the pointer */ - dest_addr = NULL; - - } - } - - if(!has_tlv) - { - eigrp_packet_free(ep); - return; - } - - if((IF_DEF_PARAMS (ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) - && (IF_DEF_PARAMS (ei->ifp)->auth_keychain != NULL)) - { - eigrp_make_md5_digest(ei,ep->s, EIGRP_AUTH_UPDATE_FLAG); - } - - /* EIGRP Checksum */ - eigrp_packet_checksum(ei, ep->s, length); - ep->length = length; - - ep->dst.s_addr = htonl(EIGRP_MULTICAST_ADDRESS); - - /*This ack number we await from neighbor*/ - ep->sequence_number = ei->eigrp->sequence_number; - - if (IS_DEBUG_EIGRP_PACKET(0, RECV)) - zlog_debug("Enqueuing Update length[%u] Seq [%u]", - length, ep->sequence_number); - - for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) - { - if (nbr->state == EIGRP_NEIGHBOR_UP) - { - packet_sent = true; - /*Put packet to retransmission queue*/ - eigrp_fifo_push_head(nbr->retrans_queue, ep); - - if (nbr->retrans_queue->count == 1) - { - eigrp_send_packet_reliably(nbr); - } - } - } - - if (!packet_sent) - eigrp_packet_free(ep); + struct eigrp_packet *ep; + struct listnode *node, *nnode; + struct eigrp_neighbor *nbr; + struct eigrp_prefix_entry *pe; + u_char has_tlv; + struct access_list *alist; + struct prefix_list *plist; + struct access_list *alist_i; + struct prefix_list *plist_i; + struct eigrp *e; + struct prefix_ipv4 *dest_addr; + bool packet_sent = false; + + u_int16_t length = EIGRP_HEADER_LEN; + + ep = eigrp_packet_new(ei->ifp->mtu); + + /* Prepare EIGRP INIT UPDATE header */ + eigrp_packet_header_init(EIGRP_OPC_UPDATE, ei, ep->s, 0, + ei->eigrp->sequence_number, 0); + + // encode Authentication TLV, if needed + if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) + && (IF_DEF_PARAMS(ei->ifp)->auth_keychain != NULL)) { + length += eigrp_add_authTLV_MD5_to_stream(ep->s, ei); + } + + has_tlv = 0; + for (ALL_LIST_ELEMENTS(ei->eigrp->topology_changes_internalIPV4, node, + nnode, pe)) { + if (pe->req_action & EIGRP_FSM_NEED_UPDATE) { + /* Get destination address from prefix */ + dest_addr = pe->destination_ipv4; + + /* + * Filtering + */ + // TODO: Work in progress + /* get list from eigrp process */ + e = eigrp_lookup(); + /* Get access-lists and prefix-lists from process and + * interface */ + alist = e->list[EIGRP_FILTER_OUT]; + plist = e->prefix[EIGRP_FILTER_OUT]; + alist_i = ei->list[EIGRP_FILTER_OUT]; + plist_i = ei->prefix[EIGRP_FILTER_OUT]; + + /* Check if any list fits */ + if ((alist + && access_list_apply(alist, + (struct prefix *)dest_addr) + == FILTER_DENY) + || (plist + && prefix_list_apply(plist, + (struct prefix *)dest_addr) + == PREFIX_DENY) + || (alist_i + && access_list_apply(alist_i, + (struct prefix *)dest_addr) + == FILTER_DENY) + || (plist_i + && prefix_list_apply(plist_i, + (struct prefix *)dest_addr) + == PREFIX_DENY)) { + zlog_info("PROC OUT: Skipping"); + // pe->reported_metric.delay = EIGRP_MAX_METRIC; + zlog_info("PROC OUT Prefix: %s", + inet_ntoa(dest_addr->prefix)); + continue; + } else { + zlog_info("PROC OUT: NENastavujem metriku "); + length += eigrp_add_internalTLV_to_stream(ep->s, + pe); + has_tlv = 1; + } + /* + * End of filtering + */ + + /* NULL the pointer */ + dest_addr = NULL; + } + } + + if (!has_tlv) { + eigrp_packet_free(ep); + return; + } + + if ((IF_DEF_PARAMS(ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) + && (IF_DEF_PARAMS(ei->ifp)->auth_keychain != NULL)) { + eigrp_make_md5_digest(ei, ep->s, EIGRP_AUTH_UPDATE_FLAG); + } + + /* EIGRP Checksum */ + eigrp_packet_checksum(ei, ep->s, length); + ep->length = length; + + ep->dst.s_addr = htonl(EIGRP_MULTICAST_ADDRESS); + + /*This ack number we await from neighbor*/ + ep->sequence_number = ei->eigrp->sequence_number; + + if (IS_DEBUG_EIGRP_PACKET(0, RECV)) + zlog_debug("Enqueuing Update length[%u] Seq [%u]", length, + ep->sequence_number); + + for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) { + if (nbr->state == EIGRP_NEIGHBOR_UP) { + packet_sent = true; + /*Put packet to retransmission queue*/ + eigrp_fifo_push_head(nbr->retrans_queue, ep); + + if (nbr->retrans_queue->count == 1) { + eigrp_send_packet_reliably(nbr); + } + } + } + + if (!packet_sent) + eigrp_packet_free(ep); } -void -eigrp_update_send_all (struct eigrp *eigrp, struct eigrp_interface *exception) +void eigrp_update_send_all(struct eigrp *eigrp, + struct eigrp_interface *exception) { - struct eigrp_interface *iface; - struct listnode *node, *node2, *nnode2; - struct eigrp_prefix_entry *pe; - - for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, iface)) - { - if (iface != exception) - { - eigrp_update_send(iface); - } - } - - for (ALL_LIST_ELEMENTS(eigrp->topology_changes_internalIPV4, node2, nnode2, pe)) - { - if(pe->req_action & EIGRP_FSM_NEED_UPDATE) - { - pe->req_action &= ~EIGRP_FSM_NEED_UPDATE; - listnode_delete(eigrp->topology_changes_internalIPV4, pe); - zlog_debug("UPDATE COUNT: %d", eigrp->topology_changes_internalIPV4->count); - } - } + struct eigrp_interface *iface; + struct listnode *node, *node2, *nnode2; + struct eigrp_prefix_entry *pe; + + for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, iface)) { + if (iface != exception) { + eigrp_update_send(iface); + } + } + + for (ALL_LIST_ELEMENTS(eigrp->topology_changes_internalIPV4, node2, + nnode2, pe)) { + if (pe->req_action & EIGRP_FSM_NEED_UPDATE) { + pe->req_action &= ~EIGRP_FSM_NEED_UPDATE; + listnode_delete(eigrp->topology_changes_internalIPV4, + pe); + zlog_debug("UPDATE COUNT: %d", + eigrp->topology_changes_internalIPV4->count); + } + } } /** * @fn eigrp_update_send_GR_part * - * @param[in] nbr contains neighbor who would receive Graceful restart + * @param[in] nbr contains neighbor who would receive Graceful + * restart * * @return void * @@ -760,216 +783,215 @@ eigrp_update_send_all (struct eigrp *eigrp, struct eigrp_interface *exception) * * Uses nbr_gr_packet_type from neighbor. */ -static void -eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) +static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) { - struct eigrp_packet *ep; - u_int16_t length = EIGRP_HEADER_LEN; - struct listnode *node, *nnode; - struct eigrp_prefix_entry *pe; - struct prefix_ipv4 *dest_addr; - struct eigrp *e; - struct access_list *alist, *alist_i; - struct prefix_list *plist, *plist_i; - struct list *prefixes; - u_int32_t flags; - unsigned int send_prefixes; - struct TLV_IPv4_Internal_type *tlv_max; - - /* get prefixes to send to neighbor */ - prefixes = nbr->nbr_gr_prefixes_send; - - send_prefixes = 0; - length = EIGRP_HEADER_LEN; - - /* if there already were last packet chunk, we won't continue */ - if(nbr->nbr_gr_packet_type == EIGRP_PACKET_PART_LAST) - return; - - /* if this is first packet chunk, we need to decide, - * if there will be one or more chunks */ - if(nbr->nbr_gr_packet_type == EIGRP_PACKET_PART_FIRST) - { - if(prefixes->count <= EIGRP_TLV_MAX_IPv4) - { - /* there will be only one chunk */ - flags = EIGRP_INIT_FLAG + EIGRP_RS_FLAG + EIGRP_EOT_FLAG; - nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_LAST; - } - else - { - /* there will be more chunks */ - flags = EIGRP_INIT_FLAG + EIGRP_RS_FLAG; - nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_NA; - } - } - else - { - /* this is not first chunk, and we need to decide, - * if there will be more chunks */ - if(prefixes->count <= EIGRP_TLV_MAX_IPv4) - { - /* this is last chunk */ - flags = EIGRP_EOT_FLAG; - nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_LAST; - } - else - { - /* there will be more chunks */ - flags = 0; - nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_NA; - } - } - - ep = eigrp_packet_new(nbr->ei->ifp->mtu); - - /* Prepare EIGRP Graceful restart UPDATE header */ - eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, - flags, - nbr->ei->eigrp->sequence_number, - nbr->recv_sequence_number); - - // encode Authentication TLV, if needed - if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && - (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL)) - { - length += eigrp_add_authTLV_MD5_to_stream(ep->s,nbr->ei); - } - - for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node, nnode, pe)) - { - /* - * Filtering - */ - dest_addr = pe->destination_ipv4; - /* get list from eigrp process */ - e = eigrp_lookup(); - /* Get access-lists and prefix-lists from process and interface */ - alist = e->list[EIGRP_FILTER_OUT]; - plist = e->prefix[EIGRP_FILTER_OUT]; - alist_i = nbr->ei->list[EIGRP_FILTER_OUT]; - plist_i = nbr->ei->prefix[EIGRP_FILTER_OUT]; - - /* Check if any list fits */ - if ((alist && access_list_apply (alist, - (struct prefix *) dest_addr) == FILTER_DENY)|| - (plist && prefix_list_apply (plist, - (struct prefix *) dest_addr) == PREFIX_DENY)|| - (alist_i && access_list_apply (alist_i, - (struct prefix *) dest_addr) == FILTER_DENY)|| - (plist_i && prefix_list_apply (plist_i, - (struct prefix *) dest_addr) == PREFIX_DENY)) - { - /* do not send filtered route */ - zlog_info("Filtered prefix %s won't be sent out.", - inet_ntoa(dest_addr->prefix)); - } - else - { - /* sending route which wasn't filtered */ - length += eigrp_add_internalTLV_to_stream(ep->s, pe); - send_prefixes++; - } - - alist = e->list[EIGRP_FILTER_IN]; - plist = e->prefix[EIGRP_FILTER_IN]; - alist_i = nbr->ei->list[EIGRP_FILTER_IN]; - plist_i = nbr->ei->prefix[EIGRP_FILTER_IN]; - - /* Check if any list fits */ - if ((alist && access_list_apply (alist, - (struct prefix *) dest_addr) == FILTER_DENY)|| - (plist && prefix_list_apply (plist, - (struct prefix *) dest_addr) == PREFIX_DENY)|| - (alist_i && access_list_apply (alist_i, - (struct prefix *) dest_addr) == FILTER_DENY)|| - (plist_i && prefix_list_apply (plist_i, - (struct prefix *) dest_addr) == PREFIX_DENY)) - { - /* do not send filtered route */ - zlog_info("Filtered prefix %s will be removed.", - inet_ntoa(dest_addr->prefix)); - - tlv_max = eigrp_IPv4_InternalTLV_new(); - tlv_max->type = EIGRP_TLV_IPv4_INT; - tlv_max->length = 28U; - tlv_max->metric = pe->reported_metric; - /* set delay to MAX */ - tlv_max->metric.delay = EIGRP_MAX_METRIC; - tlv_max->destination = pe->destination_ipv4->prefix; - tlv_max->prefix_length = pe->destination_ipv4->prefixlen; - - /* prepare message for FSM */ - struct eigrp_fsm_action_message *fsm_msg; - fsm_msg = XCALLOC(MTYPE_EIGRP_FSM_MSG, - sizeof(struct eigrp_fsm_action_message)); - - struct eigrp_neighbor_entry *entry = - eigrp_prefix_entry_lookup(pe->entries, nbr); - - fsm_msg->packet_type = EIGRP_OPC_UPDATE; - fsm_msg->eigrp = e; - fsm_msg->data_type = EIGRP_TLV_IPv4_INT; - fsm_msg->adv_router = nbr; - fsm_msg->data.ipv4_int_type = tlv_max; - fsm_msg->entry = entry; - fsm_msg->prefix = pe; - - /* send message to FSM */ - int event = eigrp_get_fsm_event(fsm_msg); - eigrp_fsm_event(fsm_msg, event); - - /* free memory used by TLV */ - eigrp_IPv4_InternalTLV_free (tlv_max); - } - /* - * End of filtering - */ - - /* NULL the pointer */ - dest_addr = NULL; - - /* delete processed prefix from list */ - listnode_delete(prefixes, pe); - - /* if there are enough prefixes, send packet */ - if(send_prefixes >= EIGRP_TLV_MAX_IPv4) - break; - } - - /* compute Auth digest */ - if((IF_DEF_PARAMS (nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) && - (IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain != NULL)) - { - eigrp_make_md5_digest(nbr->ei,ep->s, EIGRP_AUTH_UPDATE_FLAG); - } - - /* EIGRP Checksum */ - eigrp_packet_checksum(nbr->ei, ep->s, length); - - ep->length = length; - ep->dst.s_addr = nbr->src.s_addr; - - /*This ack number we await from neighbor*/ - ep->sequence_number = nbr->ei->eigrp->sequence_number; - - if (IS_DEBUG_EIGRP_PACKET(0, RECV)) - zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]", - ep->length, ep->sequence_number, inet_ntoa(ep->dst)); - - /*Put packet to retransmission queue*/ - eigrp_fifo_push_head(nbr->retrans_queue, ep); - - if (nbr->retrans_queue->count == 1) - { - eigrp_send_packet_reliably(nbr); - } + struct eigrp_packet *ep; + u_int16_t length = EIGRP_HEADER_LEN; + struct listnode *node, *nnode; + struct eigrp_prefix_entry *pe; + struct prefix_ipv4 *dest_addr; + struct eigrp *e; + struct access_list *alist, *alist_i; + struct prefix_list *plist, *plist_i; + struct list *prefixes; + u_int32_t flags; + unsigned int send_prefixes; + struct TLV_IPv4_Internal_type *tlv_max; + + /* get prefixes to send to neighbor */ + prefixes = nbr->nbr_gr_prefixes_send; + + send_prefixes = 0; + length = EIGRP_HEADER_LEN; + + /* if there already were last packet chunk, we won't continue */ + if (nbr->nbr_gr_packet_type == EIGRP_PACKET_PART_LAST) + return; + + /* if this is first packet chunk, we need to decide, + * if there will be one or more chunks */ + if (nbr->nbr_gr_packet_type == EIGRP_PACKET_PART_FIRST) { + if (prefixes->count <= EIGRP_TLV_MAX_IPv4) { + /* there will be only one chunk */ + flags = EIGRP_INIT_FLAG + EIGRP_RS_FLAG + + EIGRP_EOT_FLAG; + nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_LAST; + } else { + /* there will be more chunks */ + flags = EIGRP_INIT_FLAG + EIGRP_RS_FLAG; + nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_NA; + } + } else { + /* this is not first chunk, and we need to decide, + * if there will be more chunks */ + if (prefixes->count <= EIGRP_TLV_MAX_IPv4) { + /* this is last chunk */ + flags = EIGRP_EOT_FLAG; + nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_LAST; + } else { + /* there will be more chunks */ + flags = 0; + nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_NA; + } + } + + ep = eigrp_packet_new(nbr->ei->ifp->mtu); + + /* Prepare EIGRP Graceful restart UPDATE header */ + eigrp_packet_header_init(EIGRP_OPC_UPDATE, nbr->ei, ep->s, flags, + nbr->ei->eigrp->sequence_number, + nbr->recv_sequence_number); + + // encode Authentication TLV, if needed + if ((IF_DEF_PARAMS(nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) + && (IF_DEF_PARAMS(nbr->ei->ifp)->auth_keychain != NULL)) { + length += eigrp_add_authTLV_MD5_to_stream(ep->s, nbr->ei); + } + + for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node, nnode, + pe)) { + /* + * Filtering + */ + dest_addr = pe->destination_ipv4; + /* get list from eigrp process */ + e = eigrp_lookup(); + /* Get access-lists and prefix-lists from process and interface + */ + alist = e->list[EIGRP_FILTER_OUT]; + plist = e->prefix[EIGRP_FILTER_OUT]; + alist_i = nbr->ei->list[EIGRP_FILTER_OUT]; + plist_i = nbr->ei->prefix[EIGRP_FILTER_OUT]; + + /* Check if any list fits */ + if ((alist + && access_list_apply(alist, (struct prefix *)dest_addr) + == FILTER_DENY) + || (plist + && prefix_list_apply(plist, (struct prefix *)dest_addr) + == PREFIX_DENY) + || (alist_i + && access_list_apply(alist_i, + (struct prefix *)dest_addr) + == FILTER_DENY) + || (plist_i + && prefix_list_apply(plist_i, + (struct prefix *)dest_addr) + == PREFIX_DENY)) { + /* do not send filtered route */ + zlog_info("Filtered prefix %s won't be sent out.", + inet_ntoa(dest_addr->prefix)); + } else { + /* sending route which wasn't filtered */ + length += eigrp_add_internalTLV_to_stream(ep->s, pe); + send_prefixes++; + } + + alist = e->list[EIGRP_FILTER_IN]; + plist = e->prefix[EIGRP_FILTER_IN]; + alist_i = nbr->ei->list[EIGRP_FILTER_IN]; + plist_i = nbr->ei->prefix[EIGRP_FILTER_IN]; + + /* Check if any list fits */ + if ((alist + && access_list_apply(alist, (struct prefix *)dest_addr) + == FILTER_DENY) + || (plist + && prefix_list_apply(plist, (struct prefix *)dest_addr) + == PREFIX_DENY) + || (alist_i + && access_list_apply(alist_i, + (struct prefix *)dest_addr) + == FILTER_DENY) + || (plist_i + && prefix_list_apply(plist_i, + (struct prefix *)dest_addr) + == PREFIX_DENY)) { + /* do not send filtered route */ + zlog_info("Filtered prefix %s will be removed.", + inet_ntoa(dest_addr->prefix)); + + tlv_max = eigrp_IPv4_InternalTLV_new(); + tlv_max->type = EIGRP_TLV_IPv4_INT; + tlv_max->length = 28U; + tlv_max->metric = pe->reported_metric; + /* set delay to MAX */ + tlv_max->metric.delay = EIGRP_MAX_METRIC; + tlv_max->destination = pe->destination_ipv4->prefix; + tlv_max->prefix_length = + pe->destination_ipv4->prefixlen; + + /* prepare message for FSM */ + struct eigrp_fsm_action_message *fsm_msg; + fsm_msg = XCALLOC( + MTYPE_EIGRP_FSM_MSG, + sizeof(struct eigrp_fsm_action_message)); + + struct eigrp_neighbor_entry *entry = + eigrp_prefix_entry_lookup(pe->entries, nbr); + + fsm_msg->packet_type = EIGRP_OPC_UPDATE; + fsm_msg->eigrp = e; + fsm_msg->data_type = EIGRP_TLV_IPv4_INT; + fsm_msg->adv_router = nbr; + fsm_msg->data.ipv4_int_type = tlv_max; + fsm_msg->entry = entry; + fsm_msg->prefix = pe; + + /* send message to FSM */ + int event = eigrp_get_fsm_event(fsm_msg); + eigrp_fsm_event(fsm_msg, event); + + /* free memory used by TLV */ + eigrp_IPv4_InternalTLV_free(tlv_max); + } + /* + * End of filtering + */ + + /* NULL the pointer */ + dest_addr = NULL; + + /* delete processed prefix from list */ + listnode_delete(prefixes, pe); + + /* if there are enough prefixes, send packet */ + if (send_prefixes >= EIGRP_TLV_MAX_IPv4) + break; + } + + /* compute Auth digest */ + if ((IF_DEF_PARAMS(nbr->ei->ifp)->auth_type == EIGRP_AUTH_TYPE_MD5) + && (IF_DEF_PARAMS(nbr->ei->ifp)->auth_keychain != NULL)) { + eigrp_make_md5_digest(nbr->ei, ep->s, EIGRP_AUTH_UPDATE_FLAG); + } + + /* EIGRP Checksum */ + eigrp_packet_checksum(nbr->ei, ep->s, length); + + ep->length = length; + ep->dst.s_addr = nbr->src.s_addr; + + /*This ack number we await from neighbor*/ + ep->sequence_number = nbr->ei->eigrp->sequence_number; + + if (IS_DEBUG_EIGRP_PACKET(0, RECV)) + zlog_debug("Enqueuing Update Init Len [%u] Seq [%u] Dest [%s]", + ep->length, ep->sequence_number, inet_ntoa(ep->dst)); + + /*Put packet to retransmission queue*/ + eigrp_fifo_push_head(nbr->retrans_queue, ep); + + if (nbr->retrans_queue->count == 1) { + eigrp_send_packet_reliably(nbr); + } } /** * @fn eigrp_update_send_GR_thread * - * @param[in] thread contains neighbor who would receive Graceful restart + * @param[in] thread contains neighbor who would receive + * Graceful restart * * @return int always 0 * @@ -979,42 +1001,41 @@ eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) * * Uses nbr_gr_packet_type and t_nbr_send_gr from neighbor. */ -int -eigrp_update_send_GR_thread(struct thread *thread) +int eigrp_update_send_GR_thread(struct thread *thread) { - struct eigrp_neighbor *nbr; - - /* get argument from thread */ - nbr = THREAD_ARG(thread); - /* remove this thread pointer */ - nbr->t_nbr_send_gr = NULL; - - /* if there is packet waiting in queue, - * schedule this thread again with small delay */ - if(nbr->retrans_queue->count > 0) - { - nbr->t_nbr_send_gr = NULL; - thread_add_timer_msec(master, eigrp_update_send_GR_thread, nbr, 10, - &nbr->t_nbr_send_gr); - return 0; - } - - /* send GR EIGRP packet chunk */ - eigrp_update_send_GR_part(nbr); - - /* if it wasn't last chunk, schedule this thread again */ - if(nbr->nbr_gr_packet_type != EIGRP_PACKET_PART_LAST) { - thread_execute(master, eigrp_update_send_GR_thread, nbr, 0); - nbr->t_nbr_send_gr = NULL; - } - - return 0; + struct eigrp_neighbor *nbr; + + /* get argument from thread */ + nbr = THREAD_ARG(thread); + /* remove this thread pointer */ + nbr->t_nbr_send_gr = NULL; + + /* if there is packet waiting in queue, + * schedule this thread again with small delay */ + if (nbr->retrans_queue->count > 0) { + nbr->t_nbr_send_gr = NULL; + thread_add_timer_msec(master, eigrp_update_send_GR_thread, nbr, + 10, &nbr->t_nbr_send_gr); + return 0; + } + + /* send GR EIGRP packet chunk */ + eigrp_update_send_GR_part(nbr); + + /* if it wasn't last chunk, schedule this thread again */ + if (nbr->nbr_gr_packet_type != EIGRP_PACKET_PART_LAST) { + thread_execute(master, eigrp_update_send_GR_thread, nbr, 0); + nbr->t_nbr_send_gr = NULL; + } + + return 0; } /** * @fn eigrp_update_send_GR * - * @param[in] nbr Neighbor who would receive Graceful restart + * @param[in] nbr Neighbor who would receive Graceful + * restart * @param[in] gr_type Who executed Graceful restart * @param[in] vty Virtual terminal for log output * @@ -1025,54 +1046,56 @@ eigrp_update_send_GR_thread(struct thread *thread) * Creates Update packet with INIT, RS, EOT flags and include * all route except those filtered */ -void -eigrp_update_send_GR (struct eigrp_neighbor *nbr, enum GR_type gr_type, struct vty *vty) +void eigrp_update_send_GR(struct eigrp_neighbor *nbr, enum GR_type gr_type, + struct vty *vty) { - struct eigrp_prefix_entry *pe2; - struct listnode *node2, *nnode2; - struct list *prefixes; - - if(gr_type == EIGRP_GR_FILTER) - { - /* function was called after applying filtration */ - zlog_info("Neighbor %s (%s) is resync: route configuration changed", - inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); - } - else if(gr_type == EIGRP_GR_MANUAL) - { - /* Graceful restart was called manually */ - zlog_info("Neighbor %s (%s) is resync: manually cleared", - inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); - - if(vty != NULL) - { - vty_time_print (vty, 0); - vty_out (vty, "Neighbor %s (%s) is resync: manually cleared\n", - inet_ntoa (nbr->src), - ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); - } - } - - prefixes = list_new(); - /* add all prefixes from topology table to list */ - for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node2, nnode2, pe2)) - { - listnode_add(prefixes, pe2); - } - - /* save prefixes to neighbor */ - nbr->nbr_gr_prefixes_send = prefixes; - /* indicate, that this is first GR Update packet chunk */ - nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_FIRST; - /* execute packet sending in thread */ - thread_execute(master, eigrp_update_send_GR_thread, nbr, 0); - nbr->t_nbr_send_gr = NULL; + struct eigrp_prefix_entry *pe2; + struct listnode *node2, *nnode2; + struct list *prefixes; + + if (gr_type == EIGRP_GR_FILTER) { + /* function was called after applying filtration */ + zlog_info( + "Neighbor %s (%s) is resync: route configuration changed", + inet_ntoa(nbr->src), + ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); + } else if (gr_type == EIGRP_GR_MANUAL) { + /* Graceful restart was called manually */ + zlog_info("Neighbor %s (%s) is resync: manually cleared", + inet_ntoa(nbr->src), + ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); + + if (vty != NULL) { + vty_time_print(vty, 0); + vty_out(vty, + "Neighbor %s (%s) is resync: manually cleared\n", + inet_ntoa(nbr->src), + ifindex2ifname(nbr->ei->ifp->ifindex, + VRF_DEFAULT)); + } + } + + prefixes = list_new(); + /* add all prefixes from topology table to list */ + for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node2, nnode2, + pe2)) { + listnode_add(prefixes, pe2); + } + + /* save prefixes to neighbor */ + nbr->nbr_gr_prefixes_send = prefixes; + /* indicate, that this is first GR Update packet chunk */ + nbr->nbr_gr_packet_type = EIGRP_PACKET_PART_FIRST; + /* execute packet sending in thread */ + thread_execute(master, eigrp_update_send_GR_thread, nbr, 0); + nbr->t_nbr_send_gr = NULL; } /** * @fn eigrp_update_send_interface_GR * - * @param[in] ei Interface to neighbors of which the GR is sent + * @param[in] ei Interface to neighbors of which the GR + * is sent * @param[in] gr_type Who executed Graceful restart * @param[in] vty Virtual terminal for log output * @@ -1082,18 +1105,17 @@ eigrp_update_send_GR (struct eigrp_neighbor *nbr, enum GR_type gr_type, struct v * Function used for sending Graceful restart Update packet * to all neighbors on specified interface. */ -void -eigrp_update_send_interface_GR (struct eigrp_interface *ei, enum GR_type gr_type, struct vty *vty) +void eigrp_update_send_interface_GR(struct eigrp_interface *ei, + enum GR_type gr_type, struct vty *vty) { - struct listnode *node; - struct eigrp_neighbor *nbr; - - /* iterate over all neighbors on eigrp interface */ - for (ALL_LIST_ELEMENTS_RO(ei->nbrs, node, nbr)) - { - /* send GR to neighbor */ - eigrp_update_send_GR(nbr, gr_type, vty); - } + struct listnode *node; + struct eigrp_neighbor *nbr; + + /* iterate over all neighbors on eigrp interface */ + for (ALL_LIST_ELEMENTS_RO(ei->nbrs, node, nbr)) { + /* send GR to neighbor */ + eigrp_update_send_GR(nbr, gr_type, vty); + } } /** @@ -1109,16 +1131,15 @@ eigrp_update_send_interface_GR (struct eigrp_interface *ei, enum GR_type gr_type * Function used for sending Graceful restart Update packet * to all neighbors in eigrp process. */ -void -eigrp_update_send_process_GR (struct eigrp *eigrp, enum GR_type gr_type, struct vty *vty) +void eigrp_update_send_process_GR(struct eigrp *eigrp, enum GR_type gr_type, + struct vty *vty) { - struct listnode *node; - struct eigrp_interface *ei; - - /* iterate over all eigrp interfaces */ - for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei)) - { - /* send GR to all neighbors on interface */ - eigrp_update_send_interface_GR(ei, gr_type, vty); - } + struct listnode *node; + struct eigrp_interface *ei; + + /* iterate over all eigrp interfaces */ + for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) { + /* send GR to all neighbors on interface */ + eigrp_update_send_interface_GR(ei, gr_type, vty); + } } diff --git a/eigrpd/eigrp_vty.c b/eigrpd/eigrp_vty.c index 293b7e0ef..13cd0ff05 100644 --- a/eigrpd/eigrp_vty.c +++ b/eigrpd/eigrp_vty.c @@ -55,162 +55,160 @@ #include "eigrpd/eigrp_dump.h" #include "eigrpd/eigrp_const.h" -static int -config_write_network (struct vty *vty, struct eigrp *eigrp) +static int config_write_network(struct vty *vty, struct eigrp *eigrp) { - struct route_node *rn; - int i; - - /* `network area' print. */ - for (rn = route_top (eigrp->networks); rn; rn = route_next (rn)) - if (rn->info) - { - /* Network print. */ - vty_out (vty, " network %s/%d \n", - inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen); - } - - if (eigrp->max_paths != EIGRP_MAX_PATHS_DEFAULT) - vty_out (vty, " maximum-paths %d\n", eigrp->max_paths); - - if (eigrp->variance != EIGRP_VARIANCE_DEFAULT) - vty_out (vty, " variance %d\n", eigrp->variance); - - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (i != zclient->redist_default && - vrf_bitmap_check (zclient->redist[AFI_IP][i], VRF_DEFAULT)) - vty_outln (vty, " redistribute %s", zebra_route_string(i)); - - /*Separate EIGRP configuration from the rest of the config*/ - vty_out (vty, "!\n"); - - return 0; + struct route_node *rn; + int i; + + /* `network area' print. */ + for (rn = route_top(eigrp->networks); rn; rn = route_next(rn)) + if (rn->info) { + /* Network print. */ + vty_out(vty, " network %s/%d \n", + inet_ntoa(rn->p.u.prefix4), rn->p.prefixlen); + } + + if (eigrp->max_paths != EIGRP_MAX_PATHS_DEFAULT) + vty_out(vty, " maximum-paths %d\n", eigrp->max_paths); + + if (eigrp->variance != EIGRP_VARIANCE_DEFAULT) + vty_out(vty, " variance %d\n", eigrp->variance); + + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (i != zclient->redist_default + && vrf_bitmap_check(zclient->redist[AFI_IP][i], + VRF_DEFAULT)) + vty_outln(vty, " redistribute %s", + zebra_route_string(i)); + + /*Separate EIGRP configuration from the rest of the config*/ + vty_out(vty, "!\n"); + + return 0; } -static int -config_write_interfaces (struct vty *vty, struct eigrp *eigrp) +static int config_write_interfaces(struct vty *vty, struct eigrp *eigrp) { - struct eigrp_interface *ei; - struct listnode *node; - - for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei)) - { - vty_out (vty, "interface %s\n", ei->ifp->name); - - if ((IF_DEF_PARAMS (ei->ifp)->auth_type) == EIGRP_AUTH_TYPE_MD5) - { - vty_out (vty, " ip authentication mode eigrp %d md5\n", eigrp->AS); - } - - if ((IF_DEF_PARAMS (ei->ifp)->auth_type) == EIGRP_AUTH_TYPE_SHA256) - { - vty_out (vty, " ip authentication mode eigrp %d hmac-sha-256\n", - eigrp->AS); - } - - if(IF_DEF_PARAMS (ei->ifp)->auth_keychain) - { - vty_out (vty, " ip authentication key-chain eigrp %d %s\n",eigrp->AS, - IF_DEF_PARAMS(ei->ifp)->auth_keychain); - } - - if ((IF_DEF_PARAMS (ei->ifp)->v_hello) != EIGRP_HELLO_INTERVAL_DEFAULT) - { - vty_out (vty, " ip hello-interval eigrp %d\n", - IF_DEF_PARAMS(ei->ifp)->v_hello); - } - - if ((IF_DEF_PARAMS (ei->ifp)->v_wait) != EIGRP_HOLD_INTERVAL_DEFAULT) - { - vty_out (vty, " ip hold-time eigrp %d\n", - IF_DEF_PARAMS(ei->ifp)->v_wait); - } - - /*Separate this EIGRP interface configuration from the others*/ - vty_out (vty, "!\n"); - } - - return 0; + struct eigrp_interface *ei; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) { + vty_out(vty, "interface %s\n", ei->ifp->name); + + if ((IF_DEF_PARAMS(ei->ifp)->auth_type) + == EIGRP_AUTH_TYPE_MD5) { + vty_out(vty, " ip authentication mode eigrp %d md5\n", + eigrp->AS); + } + + if ((IF_DEF_PARAMS(ei->ifp)->auth_type) + == EIGRP_AUTH_TYPE_SHA256) { + vty_out(vty, + " ip authentication mode eigrp %d hmac-sha-256\n", + eigrp->AS); + } + + if (IF_DEF_PARAMS(ei->ifp)->auth_keychain) { + vty_out(vty, + " ip authentication key-chain eigrp %d %s\n", + eigrp->AS, + IF_DEF_PARAMS(ei->ifp)->auth_keychain); + } + + if ((IF_DEF_PARAMS(ei->ifp)->v_hello) + != EIGRP_HELLO_INTERVAL_DEFAULT) { + vty_out(vty, " ip hello-interval eigrp %d\n", + IF_DEF_PARAMS(ei->ifp)->v_hello); + } + + if ((IF_DEF_PARAMS(ei->ifp)->v_wait) + != EIGRP_HOLD_INTERVAL_DEFAULT) { + vty_out(vty, " ip hold-time eigrp %d\n", + IF_DEF_PARAMS(ei->ifp)->v_wait); + } + + /*Separate this EIGRP interface configuration from the others*/ + vty_out(vty, "!\n"); + } + + return 0; } -static int -eigrp_write_interface (struct vty *vty) +static int eigrp_write_interface(struct vty *vty) { - struct listnode *node; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist(VRF_DEFAULT), node, ifp)) { - vty_out (vty, "interface %s\n",ifp->name); - - if (ifp->desc) - vty_out (vty, " description %s\n",ifp->desc); - - if (IF_DEF_PARAMS (ifp)->bandwidth != EIGRP_BANDWIDTH_DEFAULT) - vty_out (vty, " bandwidth %u\n",IF_DEF_PARAMS(ifp)->bandwidth); - if (IF_DEF_PARAMS (ifp)->delay != EIGRP_DELAY_DEFAULT) - vty_out (vty, " delay %u\n", IF_DEF_PARAMS(ifp)->delay); - if (IF_DEF_PARAMS (ifp)->v_hello != EIGRP_HELLO_INTERVAL_DEFAULT) - vty_out (vty, " ip hello-interval eigrp %u\n", - IF_DEF_PARAMS(ifp)->v_hello); - if (IF_DEF_PARAMS (ifp)->v_wait != EIGRP_HOLD_INTERVAL_DEFAULT) - vty_out (vty, " ip hold-time eigrp %u\n", - IF_DEF_PARAMS(ifp)->v_wait); - - vty_out (vty, "!\n"); - } - - return 0; + struct listnode *node; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + vty_out(vty, "interface %s\n", ifp->name); + + if (ifp->desc) + vty_out(vty, " description %s\n", ifp->desc); + + if (IF_DEF_PARAMS(ifp)->bandwidth != EIGRP_BANDWIDTH_DEFAULT) + vty_out(vty, " bandwidth %u\n", + IF_DEF_PARAMS(ifp)->bandwidth); + if (IF_DEF_PARAMS(ifp)->delay != EIGRP_DELAY_DEFAULT) + vty_out(vty, " delay %u\n", IF_DEF_PARAMS(ifp)->delay); + if (IF_DEF_PARAMS(ifp)->v_hello != EIGRP_HELLO_INTERVAL_DEFAULT) + vty_out(vty, " ip hello-interval eigrp %u\n", + IF_DEF_PARAMS(ifp)->v_hello); + if (IF_DEF_PARAMS(ifp)->v_wait != EIGRP_HOLD_INTERVAL_DEFAULT) + vty_out(vty, " ip hold-time eigrp %u\n", + IF_DEF_PARAMS(ifp)->v_wait); + + vty_out(vty, "!\n"); + } + + return 0; } /** * Writes distribute lists to config */ -static int -config_write_eigrp_distribute (struct vty *vty, struct eigrp *eigrp) +static int config_write_eigrp_distribute(struct vty *vty, struct eigrp *eigrp) { - int write=0; + int write = 0; - /* Distribute configuration. */ - write += config_write_distribute (vty); + /* Distribute configuration. */ + write += config_write_distribute(vty); - return write; + return write; } /** * Writes 'router eigrp' section to config */ -static int -config_write_eigrp_router (struct vty *vty, struct eigrp *eigrp) +static int config_write_eigrp_router(struct vty *vty, struct eigrp *eigrp) { - int write=0; + int write = 0; - /* `router eigrp' print. */ - vty_out (vty, "router eigrp %d\n", eigrp->AS); + /* `router eigrp' print. */ + vty_out(vty, "router eigrp %d\n", eigrp->AS); - write++; + write++; - if (!eigrp->networks) - return write; + if (!eigrp->networks) + return write; - /* Router ID print. */ - if (eigrp->router_id_static != 0) - { - struct in_addr router_id_static; - router_id_static.s_addr = htonl(eigrp->router_id_static); - vty_out (vty, " eigrp router-id %s\n", - inet_ntoa(router_id_static)); - } + /* Router ID print. */ + if (eigrp->router_id_static != 0) { + struct in_addr router_id_static; + router_id_static.s_addr = htonl(eigrp->router_id_static); + vty_out(vty, " eigrp router-id %s\n", + inet_ntoa(router_id_static)); + } - /* Network area print. */ - config_write_network (vty, eigrp); + /* Network area print. */ + config_write_network(vty, eigrp); - /* Distribute-list and default-information print. */ - config_write_eigrp_distribute (vty, eigrp); + /* Distribute-list and default-information print. */ + config_write_eigrp_distribute(vty, eigrp); - /*Separate EIGRP configuration from the rest of the config*/ - vty_out (vty, "!\n"); + /*Separate EIGRP configuration from the rest of the config*/ + vty_out(vty, "!\n"); - return write; + return write; } DEFUN_NOSH (router_eigrp, @@ -220,10 +218,10 @@ DEFUN_NOSH (router_eigrp, "Start EIGRP configuration\n" "AS Number to use\n") { - struct eigrp *eigrp = eigrp_get (argv[2]->arg); - VTY_PUSH_CONTEXT(EIGRP_NODE, eigrp); + struct eigrp *eigrp = eigrp_get(argv[2]->arg); + VTY_PUSH_CONTEXT(EIGRP_NODE, eigrp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_router_eigrp, @@ -234,20 +232,19 @@ DEFUN (no_router_eigrp, "EIGRP configuration\n" "AS number to use\n") { - vty->node = CONFIG_NODE; + vty->node = CONFIG_NODE; - struct eigrp *eigrp; + struct eigrp *eigrp; - eigrp = eigrp_lookup (); - if (eigrp->AS != atoi (argv[3]->arg)) - { - vty_out (vty,"%% Attempting to deconfigure non-existent AS\n"); - return CMD_WARNING_CONFIG_FAILED; - } + eigrp = eigrp_lookup(); + if (eigrp->AS != atoi(argv[3]->arg)) { + vty_out(vty, "%% Attempting to deconfigure non-existent AS\n"); + return CMD_WARNING_CONFIG_FAILED; + } - eigrp_finish_final (eigrp); + eigrp_finish_final(eigrp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (eigrp_router_id, @@ -257,10 +254,10 @@ DEFUN (eigrp_router_id, "Router ID for this EIGRP process\n" "EIGRP Router-ID in IP address format\n") { - //struct eigrp *eigrp = vty->index; - /*TODO: */ + // struct eigrp *eigrp = vty->index; + /*TODO: */ - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_eigrp_router_id, @@ -271,10 +268,10 @@ DEFUN (no_eigrp_router_id, "Router ID for this EIGRP process\n" "EIGRP Router-ID in IP address format\n") { - //struct eigrp *eigrp = vty->index; - /*TODO: */ + // struct eigrp *eigrp = vty->index; + /*TODO: */ - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (eigrp_passive_interface, @@ -283,17 +280,16 @@ DEFUN (eigrp_passive_interface, "Suppress routing updates on an interface\n" "Interface to suppress on\n") { - VTY_DECLVAR_CONTEXT(eigrp, eigrp); - struct eigrp_interface *ei; - struct listnode *node; - char *ifname = argv[1]->arg; - - for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei)) - { - if (strcmp (ifname, ei->ifp->name) == 0) - SET_IF_PARAM (IF_DEF_PARAMS (ei->ifp), passive_interface); - } - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(eigrp, eigrp); + struct eigrp_interface *ei; + struct listnode *node; + char *ifname = argv[1]->arg; + + for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) { + if (strcmp(ifname, ei->ifp->name) == 0) + SET_IF_PARAM(IF_DEF_PARAMS(ei->ifp), passive_interface); + } + return CMD_SUCCESS; } DEFUN (no_eigrp_passive_interface, @@ -303,18 +299,18 @@ DEFUN (no_eigrp_passive_interface, "Suppress routing updates on an interface\n" "Interface to suppress on\n") { - VTY_DECLVAR_CONTEXT(eigrp, eigrp); - struct eigrp_interface *ei; - struct listnode *node; - char *ifname = argv[2]->arg; - - for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei)) - { - if (strcmp (ifname, ei->ifp->name) == 0) - UNSET_IF_PARAM (IF_DEF_PARAMS (ei->ifp), passive_interface); - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(eigrp, eigrp); + struct eigrp_interface *ei; + struct listnode *node; + char *ifname = argv[2]->arg; + + for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) { + if (strcmp(ifname, ei->ifp->name) == 0) + UNSET_IF_PARAM(IF_DEF_PARAMS(ei->ifp), + passive_interface); + } + + return CMD_SUCCESS; } DEFUN (eigrp_timers_active, @@ -325,10 +321,10 @@ DEFUN (eigrp_timers_active, "Active state time limit in minutes\n" "Disable time limit for active state\n") { - //struct eigrp *eigrp = vty->index; - /*TODO: */ + // struct eigrp *eigrp = vty->index; + /*TODO: */ - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_eigrp_timers_active, @@ -340,10 +336,10 @@ DEFUN (no_eigrp_timers_active, "Active state time limit in minutes\n" "Disable time limit for active state\n") { - //struct eigrp *eigrp = vty->index; - /*TODO: */ + // struct eigrp *eigrp = vty->index; + /*TODO: */ - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -358,10 +354,10 @@ DEFUN (eigrp_metric_weights, "K4\n" "K5\n") { - //struct eigrp *eigrp = vty->index; - /*TODO: */ + // struct eigrp *eigrp = vty->index; + /*TODO: */ - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_eigrp_metric_weights, @@ -376,10 +372,10 @@ DEFUN (no_eigrp_metric_weights, "K4\n" "K5\n") { - //struct eigrp *eigrp = vty->index; - /*TODO: */ + // struct eigrp *eigrp = vty->index; + /*TODO: */ - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -389,21 +385,20 @@ DEFUN (eigrp_network, "Enable routing on an IP network\n" "EIGRP network prefix\n") { - VTY_DECLVAR_CONTEXT(eigrp, eigrp); - struct prefix_ipv4 p; - int ret; + VTY_DECLVAR_CONTEXT(eigrp, eigrp); + struct prefix_ipv4 p; + int ret; - str2prefix_ipv4(argv[1]->arg, &p); + str2prefix_ipv4(argv[1]->arg, &p); - ret = eigrp_network_set (eigrp, &p); + ret = eigrp_network_set(eigrp, &p); - if (ret == 0) - { - vty_out (vty, "There is already same network statement.\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret == 0) { + vty_out(vty, "There is already same network statement.\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_eigrp_network, @@ -413,21 +408,20 @@ DEFUN (no_eigrp_network, "Disable routing on an IP network\n" "EIGRP network prefix\n") { - VTY_DECLVAR_CONTEXT(eigrp, eigrp); - struct prefix_ipv4 p; - int ret; + VTY_DECLVAR_CONTEXT(eigrp, eigrp); + struct prefix_ipv4 p; + int ret; - str2prefix_ipv4(argv[2]->arg, &p); + str2prefix_ipv4(argv[2]->arg, &p); - ret = eigrp_network_unset (eigrp, &p); + ret = eigrp_network_unset(eigrp, &p); - if (ret == 0) - { - vty_out (vty,"Can't find specified network configuration.\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret == 0) { + vty_out(vty, "Can't find specified network configuration.\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (eigrp_neighbor, @@ -436,9 +430,9 @@ DEFUN (eigrp_neighbor, "Specify a neighbor router\n" "Neighbor address\n") { - //struct eigrp *eigrp = vty->index; + // struct eigrp *eigrp = vty->index; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_eigrp_neighbor, @@ -448,9 +442,9 @@ DEFUN (no_eigrp_neighbor, "Specify a neighbor router\n" "Neighbor address\n") { - //struct eigrp *eigrp = vty->index; + // struct eigrp *eigrp = vty->index; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_eigrp_topology, @@ -462,50 +456,49 @@ DEFUN (show_ip_eigrp_topology, "IP-EIGRP topology\n" "Show all links in topology table\n") { - struct eigrp *eigrp; - struct listnode *node, *node2; - struct eigrp_prefix_entry *tn; - struct eigrp_neighbor_entry *te; - int first; - - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, " EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } - - show_ip_eigrp_topology_header (vty, eigrp); - - for (ALL_LIST_ELEMENTS_RO (eigrp->topology_table, node, tn)) - { - first = 1; - for (ALL_LIST_ELEMENTS_RO (tn->entries, node2, te)) - { - if (argc == 5 || - (((te->flags & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG) == EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)|| - ((te->flags & EIGRP_NEIGHBOR_ENTRY_FSUCCESSOR_FLAG) == EIGRP_NEIGHBOR_ENTRY_FSUCCESSOR_FLAG))) - { - show_ip_eigrp_neighbor_entry (vty, eigrp, te, &first); - first = 0; - } - } - } - - return CMD_SUCCESS; + struct eigrp *eigrp; + struct listnode *node, *node2; + struct eigrp_prefix_entry *tn; + struct eigrp_neighbor_entry *te; + int first; + + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, " EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } + + show_ip_eigrp_topology_header(vty, eigrp); + + for (ALL_LIST_ELEMENTS_RO(eigrp->topology_table, node, tn)) { + first = 1; + for (ALL_LIST_ELEMENTS_RO(tn->entries, node2, te)) { + if (argc == 5 + || (((te->flags + & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG) + == EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG) + || ((te->flags + & EIGRP_NEIGHBOR_ENTRY_FSUCCESSOR_FLAG) + == EIGRP_NEIGHBOR_ENTRY_FSUCCESSOR_FLAG))) { + show_ip_eigrp_neighbor_entry(vty, eigrp, te, + &first); + first = 0; + } + } + } + + return CMD_SUCCESS; } -ALIAS (show_ip_eigrp_topology, - show_ip_eigrp_topology_detail_cmd, - "show ip eigrp topology ", - SHOW_STR - IP_STR - "IP-EIGRP show commands\n" - "IP-EIGRP topology\n" - "Netwok to display information about\n" - "IP prefix /, e.g., 192.168.0.0/16\n" - "Show all links in topology table\n" - "Show a summary of the topology table\n") +ALIAS(show_ip_eigrp_topology, show_ip_eigrp_topology_detail_cmd, + "show ip eigrp topology ", + SHOW_STR IP_STR + "IP-EIGRP show commands\n" + "IP-EIGRP topology\n" + "Netwok to display information about\n" + "IP prefix /, e.g., 192.168.0.0/16\n" + "Show all links in topology table\n" + "Show a summary of the topology table\n") DEFUN (show_ip_eigrp_interfaces, show_ip_eigrp_interfaces_cmd, @@ -517,40 +510,37 @@ DEFUN (show_ip_eigrp_interfaces, "Interface name to look at\n" "Detailed information\n") { - struct eigrp_interface *ei; - struct eigrp *eigrp; - struct listnode *node; - int idx = 0; - bool detail = false; - const char *ifname = NULL; - - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, "EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } - - if (argv_find (argv, argc, "IFNAME", &idx)) - ifname = argv[idx]->arg; - - if (argv_find (argv, argc, "detail", &idx)) - detail = true; - - if (!ifname) - show_ip_eigrp_interface_header (vty, eigrp); - - for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei)) - { - if (!ifname || strcmp (ei->ifp->name, ifname) == 0) - { - show_ip_eigrp_interface_sub (vty, eigrp, ei); - if (detail) - show_ip_eigrp_interface_detail (vty, eigrp, ei); - } - } - - return CMD_SUCCESS; + struct eigrp_interface *ei; + struct eigrp *eigrp; + struct listnode *node; + int idx = 0; + bool detail = false; + const char *ifname = NULL; + + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, "EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } + + if (argv_find(argv, argc, "IFNAME", &idx)) + ifname = argv[idx]->arg; + + if (argv_find(argv, argc, "detail", &idx)) + detail = true; + + if (!ifname) + show_ip_eigrp_interface_header(vty, eigrp); + + for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) { + if (!ifname || strcmp(ei->ifp->name, ifname) == 0) { + show_ip_eigrp_interface_sub(vty, eigrp, ei); + if (detail) + show_ip_eigrp_interface_detail(vty, eigrp, ei); + } + } + + return CMD_SUCCESS; } DEFUN (show_ip_eigrp_neighbors, @@ -563,41 +553,38 @@ DEFUN (show_ip_eigrp_neighbors, "Interface to show on\n" "Detailed Information\n") { - struct eigrp *eigrp; - struct eigrp_interface *ei; - struct listnode *node, *node2, *nnode2; - struct eigrp_neighbor *nbr; - bool detail = false; - int idx = 0; - const char *ifname = NULL; - - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, " EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } - - if (argv_find(argv, argc, "IFNAME", &idx)) - ifname = argv[idx]->arg; - - detail = (argv_find(argv, argc, "detail", &idx)); - - show_ip_eigrp_neighbor_header (vty, eigrp); - - for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei)) - { - if (!ifname || strcmp(ei->ifp->name, ifname) == 0) - { - for (ALL_LIST_ELEMENTS (ei->nbrs, node2, nnode2, nbr)) - { - if (detail || (nbr->state == EIGRP_NEIGHBOR_UP)) - show_ip_eigrp_neighbor_sub (vty, nbr, detail); - } - } - } - - return CMD_SUCCESS; + struct eigrp *eigrp; + struct eigrp_interface *ei; + struct listnode *node, *node2, *nnode2; + struct eigrp_neighbor *nbr; + bool detail = false; + int idx = 0; + const char *ifname = NULL; + + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, " EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } + + if (argv_find(argv, argc, "IFNAME", &idx)) + ifname = argv[idx]->arg; + + detail = (argv_find(argv, argc, "detail", &idx)); + + show_ip_eigrp_neighbor_header(vty, eigrp); + + for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) { + if (!ifname || strcmp(ei->ifp->name, ifname) == 0) { + for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) { + if (detail || (nbr->state == EIGRP_NEIGHBOR_UP)) + show_ip_eigrp_neighbor_sub(vty, nbr, + detail); + } + } + } + + return CMD_SUCCESS; } DEFUN (eigrp_if_delay, @@ -606,24 +593,23 @@ DEFUN (eigrp_if_delay, "Specify interface throughput delay\n" "Throughput delay (tens of microseconds)\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct eigrp *eigrp; - u_int32_t delay; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct eigrp *eigrp; + u_int32_t delay; - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, " EIGRP Routing Process not enabled\n"); + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, " EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } + return CMD_SUCCESS; + } - delay = atoi (argv[1]->arg); + delay = atoi(argv[1]->arg); - IF_DEF_PARAMS (ifp)->delay = delay; - eigrp_if_reset (ifp); + IF_DEF_PARAMS(ifp)->delay = delay; + eigrp_if_reset(ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_eigrp_if_delay, @@ -633,21 +619,20 @@ DEFUN (no_eigrp_if_delay, "Specify interface throughput delay\n" "Throughput delay (tens of microseconds)\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct eigrp *eigrp; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct eigrp *eigrp; - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, " EIGRP Routing Process not enabled\n"); + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, " EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } + return CMD_SUCCESS; + } - IF_DEF_PARAMS (ifp)->delay = EIGRP_DELAY_DEFAULT; - eigrp_if_reset (ifp); + IF_DEF_PARAMS(ifp)->delay = EIGRP_DELAY_DEFAULT; + eigrp_if_reset(ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (eigrp_if_bandwidth, @@ -657,23 +642,22 @@ DEFUN (eigrp_if_bandwidth, "Set bandwidth informational parameter\n" "Bandwidth in kilobits\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - u_int32_t bandwidth; - struct eigrp *eigrp; + VTY_DECLVAR_CONTEXT(interface, ifp); + u_int32_t bandwidth; + struct eigrp *eigrp; - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, " EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, " EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } - bandwidth = atoi (argv[1]->arg); + bandwidth = atoi(argv[1]->arg); - IF_DEF_PARAMS (ifp)->bandwidth = bandwidth; - eigrp_if_reset (ifp); + IF_DEF_PARAMS(ifp)->bandwidth = bandwidth; + eigrp_if_reset(ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_eigrp_if_bandwidth, @@ -684,20 +668,19 @@ DEFUN (no_eigrp_if_bandwidth, "Set bandwidth informational parameter\n" "Bandwidth in kilobits\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct eigrp *eigrp; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct eigrp *eigrp; - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, " EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, " EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } - IF_DEF_PARAMS (ifp)->bandwidth = EIGRP_BANDWIDTH_DEFAULT; - eigrp_if_reset (ifp); + IF_DEF_PARAMS(ifp)->bandwidth = EIGRP_BANDWIDTH_DEFAULT; + eigrp_if_reset(ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (eigrp_if_ip_hellointerval, @@ -708,22 +691,21 @@ DEFUN (eigrp_if_ip_hellointerval, "Enhanced Interior Gateway Routing Protocol (EIGRP)\n" "Seconds between hello transmissions\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - u_int32_t hello; - struct eigrp *eigrp; + VTY_DECLVAR_CONTEXT(interface, ifp); + u_int32_t hello; + struct eigrp *eigrp; - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, " EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, " EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } - hello = atoi (argv[3]->arg); + hello = atoi(argv[3]->arg); - IF_DEF_PARAMS (ifp)->v_hello = hello; + IF_DEF_PARAMS(ifp)->v_hello = hello; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_eigrp_if_ip_hellointerval, @@ -735,31 +717,29 @@ DEFUN (no_eigrp_if_ip_hellointerval, "Enhanced Interior Gateway Routing Protocol (EIGRP)\n" "Seconds between hello transmissions\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct eigrp *eigrp; - struct eigrp_interface *ei; - struct listnode *node, *nnode; - - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, " EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } - - IF_DEF_PARAMS (ifp)->v_hello = EIGRP_HELLO_INTERVAL_DEFAULT; - - for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei)) - { - if (ei->ifp == ifp) - { - THREAD_TIMER_OFF (ei->t_hello); - thread_add_timer (master, eigrp_hello_timer, ei, 1, &ei->t_hello); - break; - } - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct eigrp *eigrp; + struct eigrp_interface *ei; + struct listnode *node, *nnode; + + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, " EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } + + IF_DEF_PARAMS(ifp)->v_hello = EIGRP_HELLO_INTERVAL_DEFAULT; + + for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, ei)) { + if (ei->ifp == ifp) { + THREAD_TIMER_OFF(ei->t_hello); + thread_add_timer(master, eigrp_hello_timer, ei, 1, + &ei->t_hello); + break; + } + } + + return CMD_SUCCESS; } DEFUN (eigrp_if_ip_holdinterval, @@ -770,22 +750,21 @@ DEFUN (eigrp_if_ip_holdinterval, "Enhanced Interior Gateway Routing Protocol (EIGRP)\n" "Seconds before neighbor is considered down\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - u_int32_t hold; - struct eigrp *eigrp; + VTY_DECLVAR_CONTEXT(interface, ifp); + u_int32_t hold; + struct eigrp *eigrp; - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, " EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, " EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } - hold = atoi (argv[3]->arg); + hold = atoi(argv[3]->arg); - IF_DEF_PARAMS (ifp)->v_wait = hold; + IF_DEF_PARAMS(ifp)->v_wait = hold; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (eigrp_ip_summary_address, @@ -797,22 +776,21 @@ DEFUN (eigrp_ip_summary_address, "AS number\n" "Summary /, e.g. 192.168.0.0/16\n") { - //VTY_DECLVAR_CONTEXT(interface, ifp); - //u_int32_t AS; - struct eigrp *eigrp; + // VTY_DECLVAR_CONTEXT(interface, ifp); + // u_int32_t AS; + struct eigrp *eigrp; - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, " EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, " EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } - //AS = atoi (argv[3]->arg); + // AS = atoi (argv[3]->arg); - /*TODO: */ + /*TODO: */ - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_eigrp_ip_summary_address, @@ -825,22 +803,21 @@ DEFUN (no_eigrp_ip_summary_address, "AS number\n" "Summary /, e.g. 192.168.0.0/16\n") { - //VTY_DECLVAR_CONTEXT(interface, ifp); - //u_int32_t AS; - struct eigrp *eigrp; + // VTY_DECLVAR_CONTEXT(interface, ifp); + // u_int32_t AS; + struct eigrp *eigrp; - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, " EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, " EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } - //AS = atoi (argv[4]->arg); + // AS = atoi (argv[4]->arg); - /*TODO: */ + /*TODO: */ - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_eigrp_if_ip_holdinterval, @@ -852,40 +829,35 @@ DEFUN (no_eigrp_if_ip_holdinterval, "Enhanced Interior Gateway Routing Protocol (EIGRP)\n" "Seconds before neighbor is considered down\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct eigrp *eigrp; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct eigrp *eigrp; - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, " EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, " EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } - IF_DEF_PARAMS (ifp)->v_wait = EIGRP_HOLD_INTERVAL_DEFAULT; + IF_DEF_PARAMS(ifp)->v_wait = EIGRP_HOLD_INTERVAL_DEFAULT; - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -str2auth_type (const char *str, struct interface *ifp) +static int str2auth_type(const char *str, struct interface *ifp) { - /* Sanity check. */ - if (str == NULL) - return CMD_WARNING_CONFIG_FAILED; - - if(strncmp(str, "md5",3) == 0) - { - IF_DEF_PARAMS (ifp)->auth_type = EIGRP_AUTH_TYPE_MD5; - return CMD_SUCCESS; - } - else if(strncmp(str, "hmac-sha-256",12) == 0) - { - IF_DEF_PARAMS (ifp)->auth_type = EIGRP_AUTH_TYPE_SHA256; - return CMD_SUCCESS; - } - - return CMD_WARNING_CONFIG_FAILED; + /* Sanity check. */ + if (str == NULL) + return CMD_WARNING_CONFIG_FAILED; + + if (strncmp(str, "md5", 3) == 0) { + IF_DEF_PARAMS(ifp)->auth_type = EIGRP_AUTH_TYPE_MD5; + return CMD_SUCCESS; + } else if (strncmp(str, "hmac-sha-256", 12) == 0) { + IF_DEF_PARAMS(ifp)->auth_type = EIGRP_AUTH_TYPE_SHA256; + return CMD_SUCCESS; + } + + return CMD_WARNING_CONFIG_FAILED; } DEFUN (eigrp_authentication_mode, @@ -899,22 +871,21 @@ DEFUN (eigrp_authentication_mode, "Keyed message digest\n" "HMAC SHA256 algorithm \n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct eigrp *eigrp; - - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, " EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } - - // if(strncmp(argv[2], "md5",3)) - // IF_DEF_PARAMS (ifp)->auth_type = EIGRP_AUTH_TYPE_MD5; - // else if(strncmp(argv[2], "hmac-sha-256",12)) - // IF_DEF_PARAMS (ifp)->auth_type = EIGRP_AUTH_TYPE_SHA256; - - return str2auth_type(argv[5]->arg, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); + struct eigrp *eigrp; + + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, " EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } + + // if(strncmp(argv[2], "md5",3)) + // IF_DEF_PARAMS (ifp)->auth_type = EIGRP_AUTH_TYPE_MD5; + // else if(strncmp(argv[2], "hmac-sha-256",12)) + // IF_DEF_PARAMS (ifp)->auth_type = EIGRP_AUTH_TYPE_SHA256; + + return str2auth_type(argv[5]->arg, ifp); } DEFUN (no_eigrp_authentication_mode, @@ -929,19 +900,18 @@ DEFUN (no_eigrp_authentication_mode, "Keyed message digest\n" "HMAC SHA256 algorithm \n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct eigrp *eigrp; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct eigrp *eigrp; - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, " EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, " EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } - IF_DEF_PARAMS (ifp)->auth_type = EIGRP_AUTH_TYPE_NONE; + IF_DEF_PARAMS(ifp)->auth_type = EIGRP_AUTH_TYPE_NONE; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (eigrp_authentication_keychain, @@ -954,32 +924,29 @@ DEFUN (eigrp_authentication_keychain, "Autonomous system number\n" "Name of key-chain\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct eigrp *eigrp; - struct keychain *keychain; - - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, "EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } - - keychain = keychain_lookup (argv[4]->arg); - if(keychain != NULL) - { - if(IF_DEF_PARAMS (ifp)->auth_keychain) - { - free (IF_DEF_PARAMS (ifp)->auth_keychain); - IF_DEF_PARAMS (ifp)->auth_keychain = strdup(keychain->name); - } - else - IF_DEF_PARAMS (ifp)->auth_keychain = strdup(keychain->name); - } - else - vty_out (vty,"Key chain with specified name not found\n"); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct eigrp *eigrp; + struct keychain *keychain; + + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, "EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } + + keychain = keychain_lookup(argv[4]->arg); + if (keychain != NULL) { + if (IF_DEF_PARAMS(ifp)->auth_keychain) { + free(IF_DEF_PARAMS(ifp)->auth_keychain); + IF_DEF_PARAMS(ifp)->auth_keychain = + strdup(keychain->name); + } else + IF_DEF_PARAMS(ifp)->auth_keychain = + strdup(keychain->name); + } else + vty_out(vty, "Key chain with specified name not found\n"); + + return CMD_SUCCESS; } DEFUN (no_eigrp_authentication_keychain, @@ -993,27 +960,24 @@ DEFUN (no_eigrp_authentication_keychain, "Autonomous system number\n" "Name of key-chain\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct eigrp *eigrp; - - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, "EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } - - if((IF_DEF_PARAMS (ifp)->auth_keychain != NULL) && - (strcmp(IF_DEF_PARAMS (ifp)->auth_keychain,argv[5]->arg)==0)) - { - free (IF_DEF_PARAMS (ifp)->auth_keychain); - IF_DEF_PARAMS (ifp)->auth_keychain = NULL; - } - else - vty_out (vty, - "Key chain with specified name not configured on interface\n"); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct eigrp *eigrp; + + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, "EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } + + if ((IF_DEF_PARAMS(ifp)->auth_keychain != NULL) + && (strcmp(IF_DEF_PARAMS(ifp)->auth_keychain, argv[5]->arg) == 0)) { + free(IF_DEF_PARAMS(ifp)->auth_keychain); + IF_DEF_PARAMS(ifp)->auth_keychain = NULL; + } else + vty_out(vty, + "Key chain with specified name not configured on interface\n"); + + return CMD_SUCCESS; } DEFUN (eigrp_redistribute_source_metric, @@ -1029,20 +993,20 @@ DEFUN (eigrp_redistribute_source_metric, "EIGRP Effective bandwidth metric (Loading) where 255 is 100% loaded\n" "EIGRP MTU of the path\n") { - VTY_DECLVAR_CONTEXT(eigrp, eigrp); - struct eigrp_metrics metrics_from_command = { 0 }; - int source; - int idx = 0; + VTY_DECLVAR_CONTEXT(eigrp, eigrp); + struct eigrp_metrics metrics_from_command = {0}; + int source; + int idx = 0; - /* Get distribute source. */ - argv_find (argv, argc, "redistribute", &idx); - source = proto_redistnum(AFI_IP, argv[idx+1]->arg); - if (source < 0 ) - return CMD_WARNING_CONFIG_FAILED; + /* Get distribute source. */ + argv_find(argv, argc, "redistribute", &idx); + source = proto_redistnum(AFI_IP, argv[idx + 1]->arg); + if (source < 0) + return CMD_WARNING_CONFIG_FAILED; - /* Get metrics values */ + /* Get metrics values */ - return eigrp_redistribute_set (eigrp, source, metrics_from_command); + return eigrp_redistribute_set(eigrp, source, metrics_from_command); } DEFUN (no_eigrp_redistribute_source_metric, @@ -1059,19 +1023,19 @@ DEFUN (no_eigrp_redistribute_source_metric, "EIGRP Effective bandwidth metric (Loading) where 255 is 100% loaded\n" "EIGRP MTU of the path\n") { - VTY_DECLVAR_CONTEXT(eigrp, eigrp); - int source; - int idx = 0; + VTY_DECLVAR_CONTEXT(eigrp, eigrp); + int source; + int idx = 0; - /* Get distribute source. */ - argv_find (argv, argc, "redistribute", &idx); - source = proto_redistnum(AFI_IP, argv[idx+1]->arg); - if (source < 0 ) - return CMD_WARNING_CONFIG_FAILED; + /* Get distribute source. */ + argv_find(argv, argc, "redistribute", &idx); + source = proto_redistnum(AFI_IP, argv[idx + 1]->arg); + if (source < 0) + return CMD_WARNING_CONFIG_FAILED; - /* Get metrics values */ + /* Get metrics values */ - return eigrp_redistribute_unset (eigrp, source); + return eigrp_redistribute_unset(eigrp, source); } DEFUN (eigrp_variance, @@ -1080,22 +1044,21 @@ DEFUN (eigrp_variance, "Control load balancing variance\n" "Metric variance multiplier\n") { - struct eigrp *eigrp; - u_char variance; + struct eigrp *eigrp; + u_char variance; - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, "EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } - variance = atoi(argv[1]->arg); + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, "EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } + variance = atoi(argv[1]->arg); - eigrp->variance = variance; + eigrp->variance = variance; - /*TODO: */ + /*TODO: */ - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_eigrp_variance, @@ -1105,19 +1068,18 @@ DEFUN (no_eigrp_variance, "Control load balancing variance\n" "Metric variance multiplier\n") { - struct eigrp *eigrp; - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, "EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } + struct eigrp *eigrp; + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, "EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } - eigrp->variance = EIGRP_VARIANCE_DEFAULT; + eigrp->variance = EIGRP_VARIANCE_DEFAULT; - /*TODO: */ + /*TODO: */ - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (eigrp_maximum_paths, @@ -1126,23 +1088,22 @@ DEFUN (eigrp_maximum_paths, "Forward packets over multiple paths\n" "Number of paths\n") { - struct eigrp *eigrp; - u_char max; + struct eigrp *eigrp; + u_char max; - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, "EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, "EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } - max = atoi(argv[1]->arg); + max = atoi(argv[1]->arg); - eigrp->max_paths = max; + eigrp->max_paths = max; - /*TODO: */ + /*TODO: */ - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_eigrp_maximum_paths, @@ -1152,20 +1113,19 @@ DEFUN (no_eigrp_maximum_paths, "Forward packets over multiple paths\n" "Number of paths\n") { - struct eigrp *eigrp; + struct eigrp *eigrp; - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, "EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, "EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } - eigrp->max_paths = EIGRP_MAX_PATHS_DEFAULT; + eigrp->max_paths = EIGRP_MAX_PATHS_DEFAULT; - /*TODO: */ + /*TODO: */ - return CMD_SUCCESS; + return CMD_SUCCESS; } /* @@ -1179,47 +1139,47 @@ DEFUN (clear_ip_eigrp_neighbors, "Clear IP-EIGRP\n" "Clear IP-EIGRP neighbors\n") { - struct eigrp *eigrp; - struct eigrp_interface *ei; - struct listnode *node, *node2, *nnode2; - struct eigrp_neighbor *nbr; - - /* Check if eigrp process is enabled */ - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, " EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } - - /* iterate over all eigrp interfaces */ - for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei)) - { - /* send Goodbye Hello */ - eigrp_hello_send(ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL); - - /* iterate over all neighbors on eigrp interface */ - for (ALL_LIST_ELEMENTS (ei->nbrs, node2, nnode2, nbr)) - { - if (nbr->state != EIGRP_NEIGHBOR_DOWN) - { - zlog_debug ("Neighbor %s (%s) is down: manually cleared", - inet_ntoa (nbr->src), - ifindex2ifname (nbr->ei->ifp->ifindex, VRF_DEFAULT)); - vty_time_print (vty, 0); - vty_out (vty, "Neighbor %s (%s) is down: manually cleared\n", - inet_ntoa (nbr->src), - ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); - - /* set neighbor to DOWN */ - nbr->state = EIGRP_NEIGHBOR_DOWN; - /* delete neighbor */ - eigrp_nbr_delete (nbr); - } - } - } - - return CMD_SUCCESS; + struct eigrp *eigrp; + struct eigrp_interface *ei; + struct listnode *node, *node2, *nnode2; + struct eigrp_neighbor *nbr; + + /* Check if eigrp process is enabled */ + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, " EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } + + /* iterate over all eigrp interfaces */ + for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) { + /* send Goodbye Hello */ + eigrp_hello_send(ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL); + + /* iterate over all neighbors on eigrp interface */ + for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) { + if (nbr->state != EIGRP_NEIGHBOR_DOWN) { + zlog_debug( + "Neighbor %s (%s) is down: manually cleared", + inet_ntoa(nbr->src), + ifindex2ifname(nbr->ei->ifp->ifindex, + VRF_DEFAULT)); + vty_time_print(vty, 0); + vty_out(vty, + "Neighbor %s (%s) is down: manually cleared\n", + inet_ntoa(nbr->src), + ifindex2ifname(nbr->ei->ifp->ifindex, + VRF_DEFAULT)); + + /* set neighbor to DOWN */ + nbr->state = EIGRP_NEIGHBOR_DOWN; + /* delete neighbor */ + eigrp_nbr_delete(nbr); + } + } + } + + return CMD_SUCCESS; } /* @@ -1234,53 +1194,52 @@ DEFUN (clear_ip_eigrp_neighbors_int, "Clear IP-EIGRP neighbors\n" "Interface's name\n") { - struct eigrp *eigrp; - struct eigrp_interface *ei; - struct listnode *node2, *nnode2; - struct eigrp_neighbor *nbr; - int idx = 0; - - /* Check if eigrp process is enabled */ - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, " EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } - - /* lookup interface by specified name */ - argv_find(argv, argc, "IFNAME", &idx); - ei = eigrp_if_lookup_by_name(eigrp, argv[idx]->arg); - if(ei == NULL) - { - vty_out (vty, " Interface (%s) doesn't exist\n", argv[idx]->arg); - return CMD_WARNING; - } - - /* send Goodbye Hello */ - eigrp_hello_send(ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL); - - /* iterate over all neighbors on eigrp interface */ - for (ALL_LIST_ELEMENTS (ei->nbrs, node2, nnode2, nbr)) - { - if (nbr->state != EIGRP_NEIGHBOR_DOWN) - { - zlog_debug ("Neighbor %s (%s) is down: manually cleared", - inet_ntoa (nbr->src), - ifindex2ifname (nbr->ei->ifp->ifindex, VRF_DEFAULT)); - vty_time_print (vty, 0); - vty_out (vty, "Neighbor %s (%s) is down: manually cleared\n", - inet_ntoa (nbr->src), - ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); - - /* set neighbor to DOWN */ - nbr->state = EIGRP_NEIGHBOR_DOWN; - /* delete neighbor */ - eigrp_nbr_delete (nbr); - } - } - - return CMD_SUCCESS; + struct eigrp *eigrp; + struct eigrp_interface *ei; + struct listnode *node2, *nnode2; + struct eigrp_neighbor *nbr; + int idx = 0; + + /* Check if eigrp process is enabled */ + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, " EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } + + /* lookup interface by specified name */ + argv_find(argv, argc, "IFNAME", &idx); + ei = eigrp_if_lookup_by_name(eigrp, argv[idx]->arg); + if (ei == NULL) { + vty_out(vty, " Interface (%s) doesn't exist\n", argv[idx]->arg); + return CMD_WARNING; + } + + /* send Goodbye Hello */ + eigrp_hello_send(ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL); + + /* iterate over all neighbors on eigrp interface */ + for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) { + if (nbr->state != EIGRP_NEIGHBOR_DOWN) { + zlog_debug("Neighbor %s (%s) is down: manually cleared", + inet_ntoa(nbr->src), + ifindex2ifname(nbr->ei->ifp->ifindex, + VRF_DEFAULT)); + vty_time_print(vty, 0); + vty_out(vty, + "Neighbor %s (%s) is down: manually cleared\n", + inet_ntoa(nbr->src), + ifindex2ifname(nbr->ei->ifp->ifindex, + VRF_DEFAULT)); + + /* set neighbor to DOWN */ + nbr->state = EIGRP_NEIGHBOR_DOWN; + /* delete neighbor */ + eigrp_nbr_delete(nbr); + } + } + + return CMD_SUCCESS; } /* @@ -1295,34 +1254,32 @@ DEFUN (clear_ip_eigrp_neighbors_IP, "Clear IP-EIGRP neighbors\n" "IP-EIGRP neighbor address\n") { - struct eigrp *eigrp; - struct eigrp_neighbor *nbr; - struct in_addr nbr_addr; - - inet_aton(argv[4]->arg, &nbr_addr); - - /* Check if eigrp process is enabled */ - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, " EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } - - /* lookup neighbor in whole process */ - nbr = eigrp_nbr_lookup_by_addr_process(eigrp, nbr_addr); - - /* if neighbor doesn't exists, notify user and exit */ - if(nbr == NULL) - { - vty_out (vty, "Neighbor with entered address doesn't exists.\n"); - return CMD_WARNING; - } - - /* execute hard reset on neighbor */ - eigrp_nbr_hard_restart(nbr, vty); - - return CMD_SUCCESS; + struct eigrp *eigrp; + struct eigrp_neighbor *nbr; + struct in_addr nbr_addr; + + inet_aton(argv[4]->arg, &nbr_addr); + + /* Check if eigrp process is enabled */ + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, " EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } + + /* lookup neighbor in whole process */ + nbr = eigrp_nbr_lookup_by_addr_process(eigrp, nbr_addr); + + /* if neighbor doesn't exists, notify user and exit */ + if (nbr == NULL) { + vty_out(vty, "Neighbor with entered address doesn't exists.\n"); + return CMD_WARNING; + } + + /* execute hard reset on neighbor */ + eigrp_nbr_hard_restart(nbr, vty); + + return CMD_SUCCESS; } /* @@ -1337,20 +1294,19 @@ DEFUN (clear_ip_eigrp_neighbors_soft, "Clear IP-EIGRP neighbors\n" "Resync with peers without adjacency reset\n") { - struct eigrp *eigrp; + struct eigrp *eigrp; - /* Check if eigrp process is enabled */ - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, " EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } + /* Check if eigrp process is enabled */ + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, " EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } - /* execute graceful restart on all neighbors */ - eigrp_update_send_process_GR(eigrp, EIGRP_GR_MANUAL, vty); + /* execute graceful restart on all neighbors */ + eigrp_update_send_process_GR(eigrp, EIGRP_GR_MANUAL, vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* @@ -1366,28 +1322,26 @@ DEFUN (clear_ip_eigrp_neighbors_int_soft, "Interface's name\n" "Resync with peer without adjacency reset\n") { - struct eigrp *eigrp; - struct eigrp_interface *ei; - - /* Check if eigrp process is enabled */ - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, " EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } - - /* lookup interface by specified name */ - ei = eigrp_if_lookup_by_name(eigrp, argv[4]->arg); - if(ei == NULL) - { - vty_out (vty, " Interface (%s) doesn't exist\n", argv[4]->arg); - return CMD_WARNING; - } - - /* execute graceful restart for all neighbors on interface */ - eigrp_update_send_interface_GR(ei, EIGRP_GR_MANUAL, vty); - return CMD_SUCCESS; + struct eigrp *eigrp; + struct eigrp_interface *ei; + + /* Check if eigrp process is enabled */ + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, " EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } + + /* lookup interface by specified name */ + ei = eigrp_if_lookup_by_name(eigrp, argv[4]->arg); + if (ei == NULL) { + vty_out(vty, " Interface (%s) doesn't exist\n", argv[4]->arg); + return CMD_WARNING; + } + + /* execute graceful restart for all neighbors on interface */ + eigrp_update_send_interface_GR(ei, EIGRP_GR_MANUAL, vty); + return CMD_SUCCESS; } /* @@ -1403,171 +1357,153 @@ DEFUN (clear_ip_eigrp_neighbors_IP_soft, "IP-EIGRP neighbor address\n" "Resync with peer without adjacency reset\n") { - struct eigrp *eigrp; - struct eigrp_neighbor *nbr; - struct in_addr nbr_addr; - - inet_aton(argv[4]->arg, &nbr_addr); - - /* Check if eigrp process is enabled */ - eigrp = eigrp_lookup (); - if (eigrp == NULL) - { - vty_out (vty, " EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } - - /* lookup neighbor in whole process */ - nbr = eigrp_nbr_lookup_by_addr_process(eigrp, nbr_addr); - - /* if neighbor doesn't exists, notify user and exit */ - if(nbr == NULL) - { - vty_out (vty, "Neighbor with entered address doesn't exists.\n"); - return CMD_WARNING; - } - - /* execute graceful restart on neighbor */ - eigrp_update_send_GR(nbr, EIGRP_GR_MANUAL, vty); - - return CMD_SUCCESS; + struct eigrp *eigrp; + struct eigrp_neighbor *nbr; + struct in_addr nbr_addr; + + inet_aton(argv[4]->arg, &nbr_addr); + + /* Check if eigrp process is enabled */ + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + vty_out(vty, " EIGRP Routing Process not enabled\n"); + return CMD_SUCCESS; + } + + /* lookup neighbor in whole process */ + nbr = eigrp_nbr_lookup_by_addr_process(eigrp, nbr_addr); + + /* if neighbor doesn't exists, notify user and exit */ + if (nbr == NULL) { + vty_out(vty, "Neighbor with entered address doesn't exists.\n"); + return CMD_WARNING; + } + + /* execute graceful restart on neighbor */ + eigrp_update_send_GR(nbr, EIGRP_GR_MANUAL, vty); + + return CMD_SUCCESS; } -static struct cmd_node eigrp_node = -{ - EIGRP_NODE, - "%s(config-router)# ", - 1 -}; +static struct cmd_node eigrp_node = {EIGRP_NODE, "%s(config-router)# ", 1}; /* Save EIGRP configuration */ -static int -eigrp_config_write (struct vty *vty) +static int eigrp_config_write(struct vty *vty) { - struct eigrp *eigrp; - - int write = 0; - - eigrp = eigrp_lookup (); - if (eigrp != NULL) - { - /* Writes 'router eigrp' section to config */ - config_write_eigrp_router (vty, eigrp); - - /* Interface config print */ - config_write_interfaces (vty, eigrp); -// -// /* static neighbor print. */ -// config_write_eigrp_nbr_nbma (vty, eigrp); -// -// /* Virtual-Link print. */ -// config_write_virtual_link (vty, eigrp); -// -// /* Default metric configuration. */ -// config_write_eigrp_default_metric (vty, eigrp); -// -// /* Distribute-list and default-information print. */ -// config_write_eigrp_distribute (vty, eigrp); -// -// /* Distance configuration. */ -// config_write_eigrp_distance (vty, eigrp) - } - - return write; + struct eigrp *eigrp; + + int write = 0; + + eigrp = eigrp_lookup(); + if (eigrp != NULL) { + /* Writes 'router eigrp' section to config */ + config_write_eigrp_router(vty, eigrp); + + /* Interface config print */ + config_write_interfaces(vty, eigrp); + // + // /* static neighbor print. */ + // config_write_eigrp_nbr_nbma (vty, eigrp); + // + // /* Virtual-Link print. */ + // config_write_virtual_link (vty, eigrp); + // + // /* Default metric configuration. */ + // config_write_eigrp_default_metric (vty, eigrp); + // + // /* Distribute-list and default-information print. */ + // config_write_eigrp_distribute (vty, eigrp); + // + // /* Distance configuration. */ + // config_write_eigrp_distance (vty, eigrp) + } + + return write; } -void -eigrp_vty_show_init (void) +void eigrp_vty_show_init(void) { - install_element (VIEW_NODE, &show_ip_eigrp_interfaces_cmd); - - install_element (VIEW_NODE, &show_ip_eigrp_neighbors_cmd); + install_element(VIEW_NODE, &show_ip_eigrp_interfaces_cmd); - install_element (VIEW_NODE, &show_ip_eigrp_topology_cmd); + install_element(VIEW_NODE, &show_ip_eigrp_neighbors_cmd); - install_element (VIEW_NODE, &show_ip_eigrp_topology_detail_cmd); + install_element(VIEW_NODE, &show_ip_eigrp_topology_cmd); + install_element(VIEW_NODE, &show_ip_eigrp_topology_detail_cmd); } /* eigrpd's interface node. */ -static struct cmd_node eigrp_interface_node = -{ - INTERFACE_NODE, - "%s(config-if)# ", - 1 -}; +static struct cmd_node eigrp_interface_node = {INTERFACE_NODE, + "%s(config-if)# ", 1}; -void -eigrp_vty_if_init (void) +void eigrp_vty_if_init(void) { - install_node (&eigrp_interface_node, eigrp_write_interface); - if_cmd_init(); - - /* Delay and bandwidth configuration commands*/ - install_element (INTERFACE_NODE, &eigrp_if_delay_cmd); - install_element (INTERFACE_NODE, &no_eigrp_if_delay_cmd); - install_element (INTERFACE_NODE, &eigrp_if_bandwidth_cmd); - install_element (INTERFACE_NODE, &no_eigrp_if_bandwidth_cmd); - - /*Hello-interval and hold-time interval configuration commands*/ - install_element (INTERFACE_NODE, &eigrp_if_ip_holdinterval_cmd); - install_element (INTERFACE_NODE, &no_eigrp_if_ip_holdinterval_cmd); - install_element (INTERFACE_NODE, &eigrp_if_ip_hellointerval_cmd); - install_element (INTERFACE_NODE, &no_eigrp_if_ip_hellointerval_cmd); - - /* "Authentication configuration commands */ - install_element (INTERFACE_NODE, &eigrp_authentication_mode_cmd); - install_element (INTERFACE_NODE, &no_eigrp_authentication_mode_cmd); - install_element (INTERFACE_NODE, &eigrp_authentication_keychain_cmd); - install_element (INTERFACE_NODE, &no_eigrp_authentication_keychain_cmd); - - /*EIGRP Summarization commands*/ - install_element (INTERFACE_NODE, &eigrp_ip_summary_address_cmd); - install_element (INTERFACE_NODE, &no_eigrp_ip_summary_address_cmd); + install_node(&eigrp_interface_node, eigrp_write_interface); + if_cmd_init(); + + /* Delay and bandwidth configuration commands*/ + install_element(INTERFACE_NODE, &eigrp_if_delay_cmd); + install_element(INTERFACE_NODE, &no_eigrp_if_delay_cmd); + install_element(INTERFACE_NODE, &eigrp_if_bandwidth_cmd); + install_element(INTERFACE_NODE, &no_eigrp_if_bandwidth_cmd); + + /*Hello-interval and hold-time interval configuration commands*/ + install_element(INTERFACE_NODE, &eigrp_if_ip_holdinterval_cmd); + install_element(INTERFACE_NODE, &no_eigrp_if_ip_holdinterval_cmd); + install_element(INTERFACE_NODE, &eigrp_if_ip_hellointerval_cmd); + install_element(INTERFACE_NODE, &no_eigrp_if_ip_hellointerval_cmd); + + /* "Authentication configuration commands */ + install_element(INTERFACE_NODE, &eigrp_authentication_mode_cmd); + install_element(INTERFACE_NODE, &no_eigrp_authentication_mode_cmd); + install_element(INTERFACE_NODE, &eigrp_authentication_keychain_cmd); + install_element(INTERFACE_NODE, &no_eigrp_authentication_keychain_cmd); + + /*EIGRP Summarization commands*/ + install_element(INTERFACE_NODE, &eigrp_ip_summary_address_cmd); + install_element(INTERFACE_NODE, &no_eigrp_ip_summary_address_cmd); } -static void -eigrp_vty_zebra_init (void) +static void eigrp_vty_zebra_init(void) { - install_element (EIGRP_NODE, &eigrp_redistribute_source_metric_cmd); - install_element (EIGRP_NODE, &no_eigrp_redistribute_source_metric_cmd); + install_element(EIGRP_NODE, &eigrp_redistribute_source_metric_cmd); + install_element(EIGRP_NODE, &no_eigrp_redistribute_source_metric_cmd); } /* Install EIGRP related vty commands. */ -void -eigrp_vty_init (void) +void eigrp_vty_init(void) { - install_node (&eigrp_node, eigrp_config_write); - - install_default (EIGRP_NODE); - - install_element (CONFIG_NODE, &router_eigrp_cmd); - install_element (CONFIG_NODE, &no_router_eigrp_cmd); - install_element (EIGRP_NODE, &eigrp_network_cmd); - install_element (EIGRP_NODE, &no_eigrp_network_cmd); - install_element (EIGRP_NODE, &eigrp_variance_cmd); - install_element (EIGRP_NODE, &no_eigrp_variance_cmd); - install_element (EIGRP_NODE, &eigrp_router_id_cmd); - install_element (EIGRP_NODE, &no_eigrp_router_id_cmd); - install_element (EIGRP_NODE, &eigrp_passive_interface_cmd); - install_element (EIGRP_NODE, &no_eigrp_passive_interface_cmd); - install_element (EIGRP_NODE, &eigrp_timers_active_cmd); - install_element (EIGRP_NODE, &no_eigrp_timers_active_cmd); - install_element (EIGRP_NODE, &eigrp_metric_weights_cmd); - install_element (EIGRP_NODE, &no_eigrp_metric_weights_cmd); - install_element (EIGRP_NODE, &eigrp_maximum_paths_cmd); - install_element (EIGRP_NODE, &no_eigrp_maximum_paths_cmd); - install_element (EIGRP_NODE, &eigrp_neighbor_cmd); - install_element (EIGRP_NODE, &no_eigrp_neighbor_cmd); - - /* commands for manual hard restart */ - install_element (ENABLE_NODE, &clear_ip_eigrp_neighbors_cmd); - install_element (ENABLE_NODE, &clear_ip_eigrp_neighbors_int_cmd); - install_element (ENABLE_NODE, &clear_ip_eigrp_neighbors_IP_cmd); - /* commands for manual graceful restart */ - install_element (ENABLE_NODE, &clear_ip_eigrp_neighbors_soft_cmd); - install_element (ENABLE_NODE, &clear_ip_eigrp_neighbors_int_soft_cmd); - install_element (ENABLE_NODE, &clear_ip_eigrp_neighbors_IP_soft_cmd); - - eigrp_vty_zebra_init (); + install_node(&eigrp_node, eigrp_config_write); + + install_default(EIGRP_NODE); + + install_element(CONFIG_NODE, &router_eigrp_cmd); + install_element(CONFIG_NODE, &no_router_eigrp_cmd); + install_element(EIGRP_NODE, &eigrp_network_cmd); + install_element(EIGRP_NODE, &no_eigrp_network_cmd); + install_element(EIGRP_NODE, &eigrp_variance_cmd); + install_element(EIGRP_NODE, &no_eigrp_variance_cmd); + install_element(EIGRP_NODE, &eigrp_router_id_cmd); + install_element(EIGRP_NODE, &no_eigrp_router_id_cmd); + install_element(EIGRP_NODE, &eigrp_passive_interface_cmd); + install_element(EIGRP_NODE, &no_eigrp_passive_interface_cmd); + install_element(EIGRP_NODE, &eigrp_timers_active_cmd); + install_element(EIGRP_NODE, &no_eigrp_timers_active_cmd); + install_element(EIGRP_NODE, &eigrp_metric_weights_cmd); + install_element(EIGRP_NODE, &no_eigrp_metric_weights_cmd); + install_element(EIGRP_NODE, &eigrp_maximum_paths_cmd); + install_element(EIGRP_NODE, &no_eigrp_maximum_paths_cmd); + install_element(EIGRP_NODE, &eigrp_neighbor_cmd); + install_element(EIGRP_NODE, &no_eigrp_neighbor_cmd); + + /* commands for manual hard restart */ + install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_cmd); + install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_int_cmd); + install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_IP_cmd); + /* commands for manual graceful restart */ + install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_soft_cmd); + install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_int_soft_cmd); + install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_IP_soft_cmd); + + eigrp_vty_zebra_init(); } diff --git a/eigrpd/eigrp_vty.h b/eigrpd/eigrp_vty.h index f78a46f62..3fbadf6df 100644 --- a/eigrpd/eigrp_vty.h +++ b/eigrpd/eigrp_vty.h @@ -32,10 +32,9 @@ #ifndef _QUAGGA_EIGRP_VTY_H #define _QUAGGA_EIGRP_VTY_H - /* Prototypes. */ -extern void eigrp_vty_init (void); -extern void eigrp_vty_show_init (void); -extern void eigrp_vty_if_init (void); +extern void eigrp_vty_init(void); +extern void eigrp_vty_show_init(void); +extern void eigrp_vty_if_init(void); #endif /* _Quagga_EIGRP_VTY_H_ */ diff --git a/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c index 38ce757cd..1ee1237f7 100644 --- a/eigrpd/eigrp_zebra.c +++ b/eigrpd/eigrp_zebra.c @@ -53,21 +53,21 @@ #include "eigrpd/eigrp_topology.h" #include "eigrpd/eigrp_fsm.h" -static int eigrp_interface_add (int , struct zclient *, zebra_size_t, vrf_id_t); -static int eigrp_interface_delete (int , struct zclient *, - zebra_size_t, vrf_id_t); -static int eigrp_interface_address_add (int, struct zclient *, - zebra_size_t, vrf_id_t vrf_id); -static int eigrp_interface_address_delete (int, struct zclient *, - zebra_size_t, vrf_id_t vrf_id); -static int eigrp_interface_state_up (int, struct zclient *, - zebra_size_t, vrf_id_t vrf_id); -static int eigrp_interface_state_down (int, struct zclient *, - zebra_size_t, vrf_id_t vrf_id); -static struct interface * zebra_interface_if_lookup (struct stream *); - -static int eigrp_zebra_read_ipv4 (int , struct zclient *, - zebra_size_t, vrf_id_t vrf_id); +static int eigrp_interface_add(int, struct zclient *, zebra_size_t, vrf_id_t); +static int eigrp_interface_delete(int, struct zclient *, zebra_size_t, + vrf_id_t); +static int eigrp_interface_address_add(int, struct zclient *, zebra_size_t, + vrf_id_t vrf_id); +static int eigrp_interface_address_delete(int, struct zclient *, zebra_size_t, + vrf_id_t vrf_id); +static int eigrp_interface_state_up(int, struct zclient *, zebra_size_t, + vrf_id_t vrf_id); +static int eigrp_interface_state_down(int, struct zclient *, zebra_size_t, + vrf_id_t vrf_id); +static struct interface *zebra_interface_if_lookup(struct stream *); + +static int eigrp_zebra_read_ipv4(int, struct zclient *, zebra_size_t, + vrf_id_t vrf_id); /* Zebra structure to hold current status. */ struct zclient *zclient = NULL; @@ -77,475 +77,455 @@ extern struct thread_master *master; struct in_addr router_id_zebra; /* Router-id update message from zebra. */ -static int -eigrp_router_id_update_zebra (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int eigrp_router_id_update_zebra(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct eigrp *eigrp; - struct prefix router_id; - zebra_router_id_update_read (zclient->ibuf,&router_id); + struct eigrp *eigrp; + struct prefix router_id; + zebra_router_id_update_read(zclient->ibuf, &router_id); - router_id_zebra = router_id.u.prefix4; + router_id_zebra = router_id.u.prefix4; - eigrp = eigrp_lookup (); + eigrp = eigrp_lookup(); - if (eigrp != NULL) - eigrp_router_id_update (eigrp); + if (eigrp != NULL) + eigrp_router_id_update(eigrp); - return 0; + return 0; } -static void -eigrp_zebra_connected (struct zclient *zclient) +static void eigrp_zebra_connected(struct zclient *zclient) { - zclient_send_reg_requests (zclient, VRF_DEFAULT); + zclient_send_reg_requests(zclient, VRF_DEFAULT); } -void -eigrp_zebra_init (void) +void eigrp_zebra_init(void) { - zclient = zclient_new (master); - - zclient_init (zclient, ZEBRA_ROUTE_EIGRP, 0); - zclient->zebra_connected = eigrp_zebra_connected; - zclient->router_id_update = eigrp_router_id_update_zebra; - zclient->interface_add = eigrp_interface_add; - zclient->interface_delete = eigrp_interface_delete; - zclient->interface_up = eigrp_interface_state_up; - zclient->interface_down = eigrp_interface_state_down; - zclient->interface_address_add = eigrp_interface_address_add; - zclient->interface_address_delete = eigrp_interface_address_delete; - zclient->redistribute_route_ipv4_add = eigrp_zebra_read_ipv4; - zclient->redistribute_route_ipv4_del = eigrp_zebra_read_ipv4; + zclient = zclient_new(master); + + zclient_init(zclient, ZEBRA_ROUTE_EIGRP, 0); + zclient->zebra_connected = eigrp_zebra_connected; + zclient->router_id_update = eigrp_router_id_update_zebra; + zclient->interface_add = eigrp_interface_add; + zclient->interface_delete = eigrp_interface_delete; + zclient->interface_up = eigrp_interface_state_up; + zclient->interface_down = eigrp_interface_state_down; + zclient->interface_address_add = eigrp_interface_address_add; + zclient->interface_address_delete = eigrp_interface_address_delete; + zclient->redistribute_route_ipv4_add = eigrp_zebra_read_ipv4; + zclient->redistribute_route_ipv4_del = eigrp_zebra_read_ipv4; } /* Zebra route add and delete treatment. */ -static int -eigrp_zebra_read_ipv4 (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int eigrp_zebra_read_ipv4(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv4 api; - struct prefix_ipv4 p; - struct eigrp *eigrp; - - s = zclient->ibuf; - - /* Type, flags, message. */ - api.type = stream_getc (s); - api.instance = stream_getw (s); - api.flags = stream_getc (s); - api.message = stream_getc (s); - - /* IPv4 prefix. */ - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = stream_getc (s); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); - - if (IPV4_NET127(ntohl(p.prefix.s_addr))) - return 0; - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) - { - api.nexthop_num = stream_getc (s); - stream_get_ipv4 (s); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) - { - api.ifindex_num = stream_getc (s); - /* XXX assert(api.ifindex_num == 1); */ - stream_getl (s); /* ifindex, unused */ - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc (s); - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl (s); - - eigrp = eigrp_lookup (); - if (eigrp == NULL) - return 0; - - if (command == ZEBRA_IPV4_ROUTE_ADD) - { - - } - else /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */ - { - - } - - return 0; + struct stream *s; + struct zapi_ipv4 api; + struct prefix_ipv4 p; + struct eigrp *eigrp; + + s = zclient->ibuf; + + /* Type, flags, message. */ + api.type = stream_getc(s); + api.instance = stream_getw(s); + api.flags = stream_getc(s); + api.message = stream_getc(s); + + /* IPv4 prefix. */ + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefixlen = stream_getc(s); + stream_get(&p.prefix, s, PSIZE(p.prefixlen)); + + if (IPV4_NET127(ntohl(p.prefix.s_addr))) + return 0; + + /* Nexthop, ifindex, distance, metric. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { + api.nexthop_num = stream_getc(s); + stream_get_ipv4(s); + } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { + api.ifindex_num = stream_getc(s); + /* XXX assert(api.ifindex_num == 1); */ + stream_getl(s); /* ifindex, unused */ + } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) + api.distance = stream_getc(s); + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) + api.metric = stream_getl(s); + + eigrp = eigrp_lookup(); + if (eigrp == NULL) + return 0; + + if (command == ZEBRA_IPV4_ROUTE_ADD) { + + } else /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */ + { + } + + return 0; } /* Inteface addition message from zebra. */ -static int -eigrp_interface_add (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int eigrp_interface_add(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; + struct interface *ifp; - ifp = zebra_interface_add_read (zclient->ibuf, vrf_id); + ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); - assert (ifp->info); + assert(ifp->info); - if (!EIGRP_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), type)) - { - SET_IF_PARAM (IF_DEF_PARAMS (ifp), type); - IF_DEF_PARAMS (ifp)->type = eigrp_default_iftype (ifp); - } + if (!EIGRP_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(ifp), type)) { + SET_IF_PARAM(IF_DEF_PARAMS(ifp), type); + IF_DEF_PARAMS(ifp)->type = eigrp_default_iftype(ifp); + } - eigrp_if_update (ifp); + eigrp_if_update(ifp); - return 0; + return 0; } -static int -eigrp_interface_delete (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int eigrp_interface_delete(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - struct stream *s; - struct route_node *rn; - - s = zclient->ibuf; - /* zebra_interface_state_read () updates interface structure in iflist */ - ifp = zebra_interface_state_read (s, vrf_id); - - if (ifp == NULL) - return 0; - - if (if_is_up (ifp)) - zlog_warn ("Zebra: got delete of %s, but interface is still up", - ifp->name); - - if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE)) - zlog_debug("Zebra: interface delete %s index %d flags %llx metric %d mtu %d", - ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, ifp->metric, ifp->mtu); - - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - if (rn->info) - eigrp_if_free ((struct eigrp_interface *) rn->info, INTERFACE_DOWN_BY_ZEBRA); - - ifp->ifindex = IFINDEX_INTERNAL; - return 0; + struct interface *ifp; + struct stream *s; + struct route_node *rn; + + s = zclient->ibuf; + /* zebra_interface_state_read () updates interface structure in iflist + */ + ifp = zebra_interface_state_read(s, vrf_id); + + if (ifp == NULL) + return 0; + + if (if_is_up(ifp)) + zlog_warn("Zebra: got delete of %s, but interface is still up", + ifp->name); + + if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) + zlog_debug( + "Zebra: interface delete %s index %d flags %llx metric %d mtu %d", + ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, + ifp->metric, ifp->mtu); + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) + if (rn->info) + eigrp_if_free((struct eigrp_interface *)rn->info, + INTERFACE_DOWN_BY_ZEBRA); + + ifp->ifindex = IFINDEX_INTERNAL; + return 0; } -static int -eigrp_interface_address_add (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int eigrp_interface_address_add(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct connected *c; + struct connected *c; - c = zebra_interface_address_read (command, zclient->ibuf, vrf_id); + c = zebra_interface_address_read(command, zclient->ibuf, vrf_id); - if (c == NULL) - return 0; + if (c == NULL) + return 0; - if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE)) - { - char buf[128]; - prefix2str (c->address, buf, sizeof (buf)); - zlog_debug ("Zebra: interface %s address add %s", c->ifp->name, buf); - } + if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) { + char buf[128]; + prefix2str(c->address, buf, sizeof(buf)); + zlog_debug("Zebra: interface %s address add %s", c->ifp->name, + buf); + } - eigrp_if_update (c->ifp); + eigrp_if_update(c->ifp); - return 0; + return 0; } -static int -eigrp_interface_address_delete (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int eigrp_interface_address_delete(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct connected *c; - struct interface *ifp; - struct eigrp_interface *ei; - struct route_node *rn; - struct prefix p; + struct connected *c; + struct interface *ifp; + struct eigrp_interface *ei; + struct route_node *rn; + struct prefix p; - c = zebra_interface_address_read (command, zclient->ibuf, vrf_id); + c = zebra_interface_address_read(command, zclient->ibuf, vrf_id); - if (c == NULL) - return 0; + if (c == NULL) + return 0; - if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE)) - { - char buf[128]; - prefix2str (c->address, buf, sizeof (buf)); - zlog_debug ("Zebra: interface %s address delete %s", c->ifp->name, buf); - } + if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) { + char buf[128]; + prefix2str(c->address, buf, sizeof(buf)); + zlog_debug("Zebra: interface %s address delete %s", + c->ifp->name, buf); + } - ifp = c->ifp; - p = *c->address; - p.prefixlen = IPV4_MAX_PREFIXLEN; + ifp = c->ifp; + p = *c->address; + p.prefixlen = IPV4_MAX_PREFIXLEN; - rn = route_node_lookup (IF_OIFS (ifp), &p); - if (!rn) - { - connected_free (c); - return 0; - } + rn = route_node_lookup(IF_OIFS(ifp), &p); + if (!rn) { + connected_free(c); + return 0; + } - assert (rn->info); - ei = rn->info; + assert(rn->info); + ei = rn->info; - /* Call interface hook functions to clean up */ - eigrp_if_free (ei, INTERFACE_DOWN_BY_ZEBRA); + /* Call interface hook functions to clean up */ + eigrp_if_free(ei, INTERFACE_DOWN_BY_ZEBRA); - connected_free (c); + connected_free(c); - return 0; + return 0; } -static int -eigrp_interface_state_up (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int eigrp_interface_state_up(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - struct eigrp_interface *ei; - struct route_node *rn; + struct interface *ifp; + struct eigrp_interface *ei; + struct route_node *rn; - ifp = zebra_interface_if_lookup (zclient->ibuf); + ifp = zebra_interface_if_lookup(zclient->ibuf); - if (ifp == NULL) - return 0; + if (ifp == NULL) + return 0; - /* Interface is already up. */ - if (if_is_operative (ifp)) - { - /* Temporarily keep ifp values. */ - struct interface if_tmp; - memcpy (&if_tmp, ifp, sizeof (struct interface)); + /* Interface is already up. */ + if (if_is_operative(ifp)) { + /* Temporarily keep ifp values. */ + struct interface if_tmp; + memcpy(&if_tmp, ifp, sizeof(struct interface)); - zebra_interface_if_set_value (zclient->ibuf, ifp); + zebra_interface_if_set_value(zclient->ibuf, ifp); - if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE)) - zlog_debug ("Zebra: Interface[%s] state update.", ifp->name); + if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) + zlog_debug("Zebra: Interface[%s] state update.", + ifp->name); - if (if_tmp.bandwidth != ifp->bandwidth) - { - if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE)) - zlog_debug ("Zebra: Interface[%s] bandwidth change %d -> %d.", - ifp->name, if_tmp.bandwidth, ifp->bandwidth); + if (if_tmp.bandwidth != ifp->bandwidth) { + if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) + zlog_debug( + "Zebra: Interface[%s] bandwidth change %d -> %d.", + ifp->name, if_tmp.bandwidth, + ifp->bandwidth); - // eigrp_if_recalculate_output_cost (ifp); - } + // eigrp_if_recalculate_output_cost (ifp); + } - if (if_tmp.mtu != ifp->mtu) - { - if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE)) - zlog_debug ("Zebra: Interface[%s] MTU change %u -> %u.", - ifp->name, if_tmp.mtu, ifp->mtu); + if (if_tmp.mtu != ifp->mtu) { + if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) + zlog_debug( + "Zebra: Interface[%s] MTU change %u -> %u.", + ifp->name, if_tmp.mtu, ifp->mtu); - /* Must reset the interface (simulate down/up) when MTU changes. */ - eigrp_if_reset (ifp); - } - return 0; - } + /* Must reset the interface (simulate down/up) when MTU + * changes. */ + eigrp_if_reset(ifp); + } + return 0; + } - zebra_interface_if_set_value (zclient->ibuf, ifp); + zebra_interface_if_set_value(zclient->ibuf, ifp); - if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE)) - zlog_debug ("Zebra: Interface[%s] state change to up.", ifp->name); + if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) + zlog_debug("Zebra: Interface[%s] state change to up.", + ifp->name); - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - { - if ((ei = rn->info) == NULL) - continue; + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + if ((ei = rn->info) == NULL) + continue; - eigrp_if_up (ei); - } + eigrp_if_up(ei); + } - return 0; + return 0; } -static int -eigrp_interface_state_down (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int eigrp_interface_state_down(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - struct eigrp_interface *ei; - struct route_node *node; + struct interface *ifp; + struct eigrp_interface *ei; + struct route_node *node; - ifp = zebra_interface_state_read (zclient->ibuf, vrf_id); + ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); - if (ifp == NULL) - return 0; + if (ifp == NULL) + return 0; - if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE)) - zlog_debug ("Zebra: Interface[%s] state change to down.", ifp->name); + if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) + zlog_debug("Zebra: Interface[%s] state change to down.", + ifp->name); - for (node = route_top (IF_OIFS (ifp)); node; node = route_next (node)) - { - if ((ei = node->info) == NULL) - continue; - eigrp_if_down (ei); - } + for (node = route_top(IF_OIFS(ifp)); node; node = route_next(node)) { + if ((ei = node->info) == NULL) + continue; + eigrp_if_down(ei); + } - return 0; + return 0; } -static struct interface * -zebra_interface_if_lookup (struct stream *s) +static struct interface *zebra_interface_if_lookup(struct stream *s) { - char ifname_tmp[INTERFACE_NAMSIZ]; + char ifname_tmp[INTERFACE_NAMSIZ]; - /* Read interface name. */ - stream_get (ifname_tmp, s, INTERFACE_NAMSIZ); + /* Read interface name. */ + stream_get(ifname_tmp, s, INTERFACE_NAMSIZ); - /* And look it up. */ - return if_lookup_by_name_len (ifname_tmp, - strnlen (ifname_tmp, INTERFACE_NAMSIZ), - VRF_DEFAULT); + /* And look it up. */ + return if_lookup_by_name_len( + ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ), VRF_DEFAULT); } -void -eigrp_zebra_route_add (struct prefix_ipv4 *p, struct list *successors) +void eigrp_zebra_route_add(struct prefix_ipv4 *p, struct list *successors) { - struct eigrp_neighbor_entry *te; - struct listnode *node; - u_char message; - u_char flags; - int psize; - struct stream *s; - - if (zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) - { - message = 0; - flags = 0; - - /* EIGRP pass nexthop and metric */ - SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP); - - /* Make packet. */ - s = zclient->obuf; - stream_reset (s); - - /* Put command, type, flags, message. */ - zclient_create_header (s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT); - stream_putc (s, ZEBRA_ROUTE_EIGRP); - stream_putw (s, 0); - stream_putl (s, flags); - stream_putc (s, message); - stream_putw (s, SAFI_UNICAST); - - /* Put prefix information. */ - psize = PSIZE (p->prefixlen); - stream_putc (s, p->prefixlen); - stream_write (s, (u_char *) & p->prefix, psize); - - /* Nexthop count. */ - stream_putc (s, successors->count); - - /* Nexthop, ifindex, distance and metric information. */ - for (ALL_LIST_ELEMENTS_RO (successors, node, te)) - { - if (te->adv_router->src.s_addr) - { - stream_putc (s, NEXTHOP_TYPE_IPV4_IFINDEX); - stream_put_in_addr (s, &te->adv_router->src); - } - else - stream_putc (s, NEXTHOP_TYPE_IFINDEX); - stream_putl (s, te->ei->ifp->ifindex); - } - - if (IS_DEBUG_EIGRP (zebra, ZEBRA_REDISTRIBUTE)) - { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug ("Zebra: Route add %s/%d nexthop %s", - inet_ntop(AF_INET, &p->prefix, buf[0], sizeof (buf[0])), - p->prefixlen, - inet_ntop(AF_INET, 0 /*&p->nexthop*/, buf[1], sizeof (buf[1]))); - } - - stream_putw_at (s, 0, stream_get_endp (s)); - - zclient_send_message (zclient); - } + struct eigrp_neighbor_entry *te; + struct listnode *node; + u_char message; + u_char flags; + int psize; + struct stream *s; + + if (zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) { + message = 0; + flags = 0; + + /* EIGRP pass nexthop and metric */ + SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP); + + /* Make packet. */ + s = zclient->obuf; + stream_reset(s); + + /* Put command, type, flags, message. */ + zclient_create_header(s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT); + stream_putc(s, ZEBRA_ROUTE_EIGRP); + stream_putw(s, 0); + stream_putl(s, flags); + stream_putc(s, message); + stream_putw(s, SAFI_UNICAST); + + /* Put prefix information. */ + psize = PSIZE(p->prefixlen); + stream_putc(s, p->prefixlen); + stream_write(s, (u_char *)&p->prefix, psize); + + /* Nexthop count. */ + stream_putc(s, successors->count); + + /* Nexthop, ifindex, distance and metric information. */ + for (ALL_LIST_ELEMENTS_RO(successors, node, te)) { + if (te->adv_router->src.s_addr) { + stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX); + stream_put_in_addr(s, &te->adv_router->src); + } else + stream_putc(s, NEXTHOP_TYPE_IFINDEX); + stream_putl(s, te->ei->ifp->ifindex); + } + + if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) { + char buf[2][INET_ADDRSTRLEN]; + zlog_debug("Zebra: Route add %s/%d nexthop %s", + inet_ntop(AF_INET, &p->prefix, buf[0], + sizeof(buf[0])), + p->prefixlen, + inet_ntop(AF_INET, 0 /*&p->nexthop*/, buf[1], + sizeof(buf[1]))); + } + + stream_putw_at(s, 0, stream_get_endp(s)); + + zclient_send_message(zclient); + } } -void -eigrp_zebra_route_delete (struct prefix_ipv4 *p) +void eigrp_zebra_route_delete(struct prefix_ipv4 *p) { - struct zapi_ipv4 api; - - if (zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) - { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_EIGRP; - api.instance = 0; - api.flags = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api); - - if (IS_DEBUG_EIGRP (zebra, ZEBRA_REDISTRIBUTE)) - { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug ("Zebra: Route del %s/%d nexthop %s", - inet_ntop (AF_INET, &p->prefix, buf[0], sizeof (buf[0])), - p->prefixlen, - inet_ntop (AF_INET, 0 /*&p->nexthop*/, buf[1], sizeof (buf[1]))); - } - } - - return; + struct zapi_ipv4 api; + + if (zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) { + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_EIGRP; + api.instance = 0; + api.flags = 0; + api.message = 0; + api.safi = SAFI_UNICAST; + zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api); + + if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) { + char buf[2][INET_ADDRSTRLEN]; + zlog_debug("Zebra: Route del %s/%d nexthop %s", + inet_ntop(AF_INET, &p->prefix, buf[0], + sizeof(buf[0])), + p->prefixlen, + inet_ntop(AF_INET, 0 /*&p->nexthop*/, buf[1], + sizeof(buf[1]))); + } + } + + return; } -int -eigrp_is_type_redistributed (int type) +int eigrp_is_type_redistributed(int type) { - return ((DEFAULT_ROUTE_TYPE (type)) ? - vrf_bitmap_check (zclient->default_information, VRF_DEFAULT) : - vrf_bitmap_check (zclient->redist[AFI_IP][type], VRF_DEFAULT)); + return ((DEFAULT_ROUTE_TYPE(type)) + ? vrf_bitmap_check(zclient->default_information, + VRF_DEFAULT) + : vrf_bitmap_check(zclient->redist[AFI_IP][type], + VRF_DEFAULT)); } -int -eigrp_redistribute_set (struct eigrp *eigrp, int type, struct eigrp_metrics metric) +int eigrp_redistribute_set(struct eigrp *eigrp, int type, + struct eigrp_metrics metric) { - if (eigrp_is_type_redistributed (type)) - { - if (eigrp_metrics_is_same(metric, eigrp->dmetric[type])) - { - eigrp->dmetric[type] = metric; - } + if (eigrp_is_type_redistributed(type)) { + if (eigrp_metrics_is_same(metric, eigrp->dmetric[type])) { + eigrp->dmetric[type] = metric; + } - eigrp_external_routes_refresh (eigrp, type); + eigrp_external_routes_refresh(eigrp, type); - // if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) - // zlog_debug ("Redistribute[%s]: Refresh Type[%d], Metric[%d]", - // eigrp_redist_string(type), - // metric_type (eigrp, type), metric_value (eigrp, type)); - return CMD_SUCCESS; - } + // if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) + // zlog_debug ("Redistribute[%s]: Refresh Type[%d], + // Metric[%d]", + // eigrp_redist_string(type), + // metric_type (eigrp, type), metric_value + // (eigrp, type)); + return CMD_SUCCESS; + } - eigrp->dmetric[type] = metric; + eigrp->dmetric[type] = metric; - zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, - AFI_IP, type, 0, VRF_DEFAULT); + zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type, 0, + VRF_DEFAULT); - ++eigrp->redistribute; + ++eigrp->redistribute; - return CMD_SUCCESS; + return CMD_SUCCESS; } -int -eigrp_redistribute_unset (struct eigrp *eigrp, int type) +int eigrp_redistribute_unset(struct eigrp *eigrp, int type) { - if (eigrp_is_type_redistributed (type)) - { - memset(&eigrp->dmetric[type], 0, sizeof(struct eigrp_metrics)); - zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, - AFI_IP, type, 0, VRF_DEFAULT); - --eigrp->redistribute; - } + if (eigrp_is_type_redistributed(type)) { + memset(&eigrp->dmetric[type], 0, sizeof(struct eigrp_metrics)); + zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, + type, 0, VRF_DEFAULT); + --eigrp->redistribute; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } - diff --git a/eigrpd/eigrp_zebra.h b/eigrpd/eigrp_zebra.h index 6151e3272..3281c4701 100644 --- a/eigrpd/eigrp_zebra.h +++ b/eigrpd/eigrp_zebra.h @@ -31,12 +31,12 @@ #include "vty.h" #include "vrf.h" -extern void eigrp_zebra_init (void); +extern void eigrp_zebra_init(void); -extern void eigrp_zebra_route_add (struct prefix_ipv4 *, struct list *); -extern void eigrp_zebra_route_delete (struct prefix_ipv4 *); -extern int eigrp_redistribute_set (struct eigrp *, int, struct eigrp_metrics); -extern int eigrp_redistribute_unset (struct eigrp *, int); -extern int eigrp_is_type_redistributed (int); +extern void eigrp_zebra_route_add(struct prefix_ipv4 *, struct list *); +extern void eigrp_zebra_route_delete(struct prefix_ipv4 *); +extern int eigrp_redistribute_set(struct eigrp *, int, struct eigrp_metrics); +extern int eigrp_redistribute_unset(struct eigrp *, int); +extern int eigrp_is_type_redistributed(int); #endif /* _ZEBRA_EIGRP_ZEBRA_H_ */ diff --git a/eigrpd/eigrpd.c b/eigrpd/eigrpd.c index 2fa8296ce..99d88b2d0 100644 --- a/eigrpd/eigrpd.c +++ b/eigrpd/eigrpd.c @@ -37,7 +37,7 @@ #include "memory.h" #include "stream.h" #include "log.h" -#include "sockunion.h" /* for inet_aton () */ +#include "sockunion.h" /* for inet_aton () */ #include "zclient.h" #include "plist.h" #include "sockopt.h" @@ -91,232 +91,218 @@ extern struct in_addr router_id_zebra; * This does not work for IPv6, and to make the code simpler, its * stored and processed internerall as a 32bit number */ -void -eigrp_router_id_update (struct eigrp *eigrp) +void eigrp_router_id_update(struct eigrp *eigrp) { - struct interface *ifp; - struct listnode *node; - u_int32_t router_id, router_id_old; + struct interface *ifp; + struct listnode *node; + u_int32_t router_id, router_id_old; - router_id_old = eigrp->router_id; + router_id_old = eigrp->router_id; - if (eigrp->router_id_static != 0) - router_id = eigrp->router_id_static; + if (eigrp->router_id_static != 0) + router_id = eigrp->router_id_static; - else if (eigrp->router_id != 0) - router_id = eigrp->router_id; + else if (eigrp->router_id != 0) + router_id = eigrp->router_id; - else - router_id = router_id_zebra.s_addr; + else + router_id = router_id_zebra.s_addr; - eigrp->router_id = router_id; - if (router_id_old != router_id) - { - // if (IS_DEBUG_EIGRP_EVENT) - // zlog_debug("Router-ID[NEW:%s]: Update", inet_ntoa(eigrp->router_id)); + eigrp->router_id = router_id; + if (router_id_old != router_id) { + // if (IS_DEBUG_EIGRP_EVENT) + // zlog_debug("Router-ID[NEW:%s]: Update", + // inet_ntoa(eigrp->router_id)); - /* update eigrp_interface's */ - for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) - eigrp_if_update(ifp); - } + /* update eigrp_interface's */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) + eigrp_if_update(ifp); + } } -void -eigrp_master_init () +void eigrp_master_init() { - struct timeval tv; + struct timeval tv; - memset(&eigrp_master, 0, sizeof(struct eigrp_master)); + memset(&eigrp_master, 0, sizeof(struct eigrp_master)); - eigrp_om = &eigrp_master; - eigrp_om->eigrp = list_new(); + eigrp_om = &eigrp_master; + eigrp_om->eigrp = list_new(); - monotime(&tv); - eigrp_om->start_time = tv.tv_sec; + monotime(&tv); + eigrp_om->start_time = tv.tv_sec; } /* Allocate new eigrp structure. */ -static struct eigrp * -eigrp_new (const char *AS) +static struct eigrp *eigrp_new(const char *AS) { - struct eigrp *eigrp = XCALLOC(MTYPE_EIGRP_TOP, sizeof (struct eigrp)); - int eigrp_socket; - - /* init information relevant to peers */ - eigrp->vrid = 0; - eigrp->AS = atoi(AS); - eigrp->router_id = 0L; - eigrp->router_id_static = 0L; - eigrp->sequence_number = 1; - - /*Configure default K Values for EIGRP Process*/ - eigrp->k_values[0] = EIGRP_K1_DEFAULT; - eigrp->k_values[1] = EIGRP_K2_DEFAULT; - eigrp->k_values[2] = EIGRP_K3_DEFAULT; - eigrp->k_values[3] = EIGRP_K4_DEFAULT; - eigrp->k_values[4] = EIGRP_K5_DEFAULT; - eigrp->k_values[5] = EIGRP_K6_DEFAULT; - - /* init internal data structures */ - eigrp->eiflist = list_new(); - eigrp->passive_interface_default = EIGRP_IF_ACTIVE; - eigrp->networks = route_table_init(); - - if ((eigrp_socket = eigrp_sock_init()) < 0) - { - zlog_err("eigrp_new: fatal error: eigrp_sock_init was unable to open " - "a socket"); - exit (1); - } - - eigrp->fd = eigrp_socket; - eigrp->maxsndbuflen = getsockopt_so_sendbuf(eigrp->fd); - - if ((eigrp->ibuf = stream_new(EIGRP_PACKET_MAX_LEN+1)) == NULL) - { - zlog_err("eigrp_new: fatal error: stream_new (%u) failed allocating ibuf", - EIGRP_PACKET_MAX_LEN+1); - exit(1); - } - - eigrp->t_read = NULL; - thread_add_read(master, eigrp_read, eigrp, eigrp->fd, &eigrp->t_read); - eigrp->oi_write_q = list_new(); - - eigrp->topology_table = eigrp_topology_new(); - - eigrp->neighbor_self = eigrp_nbr_new(NULL); - eigrp->neighbor_self->src.s_addr = INADDR_ANY; - - eigrp->variance = EIGRP_VARIANCE_DEFAULT; - eigrp->max_paths = EIGRP_MAX_PATHS_DEFAULT; - - eigrp->serno = 0; - eigrp->serno_last_update = 0; - eigrp->topology_changes_externalIPV4 = list_new (); - eigrp->topology_changes_internalIPV4 = list_new (); - - eigrp->list[EIGRP_FILTER_IN] = NULL; - eigrp->list[EIGRP_FILTER_OUT] = NULL; - - eigrp->prefix[EIGRP_FILTER_IN] = NULL; - eigrp->prefix[EIGRP_FILTER_OUT] = NULL; - - eigrp->routemap[EIGRP_FILTER_IN] = NULL; - eigrp->routemap[EIGRP_FILTER_OUT] = NULL; - - QOBJ_REG(eigrp, eigrp); - return eigrp; + struct eigrp *eigrp = XCALLOC(MTYPE_EIGRP_TOP, sizeof(struct eigrp)); + int eigrp_socket; + + /* init information relevant to peers */ + eigrp->vrid = 0; + eigrp->AS = atoi(AS); + eigrp->router_id = 0L; + eigrp->router_id_static = 0L; + eigrp->sequence_number = 1; + + /*Configure default K Values for EIGRP Process*/ + eigrp->k_values[0] = EIGRP_K1_DEFAULT; + eigrp->k_values[1] = EIGRP_K2_DEFAULT; + eigrp->k_values[2] = EIGRP_K3_DEFAULT; + eigrp->k_values[3] = EIGRP_K4_DEFAULT; + eigrp->k_values[4] = EIGRP_K5_DEFAULT; + eigrp->k_values[5] = EIGRP_K6_DEFAULT; + + /* init internal data structures */ + eigrp->eiflist = list_new(); + eigrp->passive_interface_default = EIGRP_IF_ACTIVE; + eigrp->networks = route_table_init(); + + if ((eigrp_socket = eigrp_sock_init()) < 0) { + zlog_err( + "eigrp_new: fatal error: eigrp_sock_init was unable to open " + "a socket"); + exit(1); + } + + eigrp->fd = eigrp_socket; + eigrp->maxsndbuflen = getsockopt_so_sendbuf(eigrp->fd); + + if ((eigrp->ibuf = stream_new(EIGRP_PACKET_MAX_LEN + 1)) == NULL) { + zlog_err( + "eigrp_new: fatal error: stream_new (%u) failed allocating ibuf", + EIGRP_PACKET_MAX_LEN + 1); + exit(1); + } + + eigrp->t_read = NULL; + thread_add_read(master, eigrp_read, eigrp, eigrp->fd, &eigrp->t_read); + eigrp->oi_write_q = list_new(); + + eigrp->topology_table = eigrp_topology_new(); + + eigrp->neighbor_self = eigrp_nbr_new(NULL); + eigrp->neighbor_self->src.s_addr = INADDR_ANY; + + eigrp->variance = EIGRP_VARIANCE_DEFAULT; + eigrp->max_paths = EIGRP_MAX_PATHS_DEFAULT; + + eigrp->serno = 0; + eigrp->serno_last_update = 0; + eigrp->topology_changes_externalIPV4 = list_new(); + eigrp->topology_changes_internalIPV4 = list_new(); + + eigrp->list[EIGRP_FILTER_IN] = NULL; + eigrp->list[EIGRP_FILTER_OUT] = NULL; + + eigrp->prefix[EIGRP_FILTER_IN] = NULL; + eigrp->prefix[EIGRP_FILTER_OUT] = NULL; + + eigrp->routemap[EIGRP_FILTER_IN] = NULL; + eigrp->routemap[EIGRP_FILTER_OUT] = NULL; + + QOBJ_REG(eigrp, eigrp); + return eigrp; } -static void -eigrp_add (struct eigrp *eigrp) +static void eigrp_add(struct eigrp *eigrp) { - listnode_add(eigrp_om->eigrp, eigrp); + listnode_add(eigrp_om->eigrp, eigrp); } -static void -eigrp_delete (struct eigrp *eigrp) +static void eigrp_delete(struct eigrp *eigrp) { - listnode_delete(eigrp_om->eigrp, eigrp); + listnode_delete(eigrp_om->eigrp, eigrp); } -struct eigrp * -eigrp_get (const char *AS) +struct eigrp *eigrp_get(const char *AS) { - struct eigrp *eigrp; + struct eigrp *eigrp; - eigrp = eigrp_lookup(); - if (eigrp == NULL) - { - eigrp = eigrp_new(AS); - eigrp_add(eigrp); - } + eigrp = eigrp_lookup(); + if (eigrp == NULL) { + eigrp = eigrp_new(AS); + eigrp_add(eigrp); + } - return eigrp; + return eigrp; } /* Shut down the entire process */ -void -eigrp_terminate (void) +void eigrp_terminate(void) { - struct eigrp *eigrp; - struct listnode *node, *nnode; + struct eigrp *eigrp; + struct listnode *node, *nnode; - /* shutdown already in progress */ - if (CHECK_FLAG(eigrp_om->options, EIGRP_MASTER_SHUTDOWN)) - return; + /* shutdown already in progress */ + if (CHECK_FLAG(eigrp_om->options, EIGRP_MASTER_SHUTDOWN)) + return; - SET_FLAG(eigrp_om->options, EIGRP_MASTER_SHUTDOWN); + SET_FLAG(eigrp_om->options, EIGRP_MASTER_SHUTDOWN); - /* exit immediately if EIGRP not actually running */ - if (listcount(eigrp_om->eigrp) == 0) - exit(0); + /* exit immediately if EIGRP not actually running */ + if (listcount(eigrp_om->eigrp) == 0) + exit(0); - for (ALL_LIST_ELEMENTS(eigrp_om->eigrp, node, nnode, eigrp)) - eigrp_finish(eigrp); + for (ALL_LIST_ELEMENTS(eigrp_om->eigrp, node, nnode, eigrp)) + eigrp_finish(eigrp); } -void -eigrp_finish (struct eigrp *eigrp) +void eigrp_finish(struct eigrp *eigrp) { - eigrp_finish_final(eigrp); - - /* eigrp being shut-down? If so, was this the last eigrp instance? */ - if (CHECK_FLAG(eigrp_om->options, EIGRP_MASTER_SHUTDOWN) - && (listcount(eigrp_om->eigrp) == 0)) - { - if (zclient) - { - zclient_stop (zclient); - zclient_free (zclient); + eigrp_finish_final(eigrp); + + /* eigrp being shut-down? If so, was this the last eigrp instance? */ + if (CHECK_FLAG(eigrp_om->options, EIGRP_MASTER_SHUTDOWN) + && (listcount(eigrp_om->eigrp) == 0)) { + if (zclient) { + zclient_stop(zclient); + zclient_free(zclient); + } + exit(0); } - exit(0); - } - return; + return; } /* Final cleanup of eigrp instance */ -void -eigrp_finish_final (struct eigrp *eigrp) +void eigrp_finish_final(struct eigrp *eigrp) { - struct eigrp_interface *ei; - struct eigrp_neighbor *nbr; - struct listnode *node, *nnode, *node2, *nnode2; - - for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei)) - { - for (ALL_LIST_ELEMENTS (ei->nbrs, node2, nnode2, nbr)) - eigrp_nbr_delete (nbr); - eigrp_if_free (ei, INTERFACE_DOWN_BY_FINAL); - } + struct eigrp_interface *ei; + struct eigrp_neighbor *nbr; + struct listnode *node, *nnode, *node2, *nnode2; + + for (ALL_LIST_ELEMENTS(eigrp->eiflist, node, nnode, ei)) { + for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) + eigrp_nbr_delete(nbr); + eigrp_if_free(ei, INTERFACE_DOWN_BY_FINAL); + } - THREAD_OFF (eigrp->t_write); - THREAD_OFF (eigrp->t_read); - close (eigrp->fd); + THREAD_OFF(eigrp->t_write); + THREAD_OFF(eigrp->t_read); + close(eigrp->fd); - list_delete(eigrp->eiflist); - list_delete(eigrp->oi_write_q); - list_delete(eigrp->topology_changes_externalIPV4); - list_delete(eigrp->topology_changes_internalIPV4); + list_delete(eigrp->eiflist); + list_delete(eigrp->oi_write_q); + list_delete(eigrp->topology_changes_externalIPV4); + list_delete(eigrp->topology_changes_internalIPV4); - eigrp_topology_cleanup(eigrp->topology_table); - eigrp_topology_free(eigrp->topology_table); + eigrp_topology_cleanup(eigrp->topology_table); + eigrp_topology_free(eigrp->topology_table); - eigrp_nbr_delete(eigrp->neighbor_self); + eigrp_nbr_delete(eigrp->neighbor_self); - eigrp_delete(eigrp); + eigrp_delete(eigrp); - XFREE(MTYPE_EIGRP_TOP,eigrp); + XFREE(MTYPE_EIGRP_TOP, eigrp); } /*Look for existing eigrp process*/ -struct eigrp * -eigrp_lookup (void) +struct eigrp *eigrp_lookup(void) { - if (listcount(eigrp_om->eigrp) == 0) - return NULL; + if (listcount(eigrp_om->eigrp) == 0) + return NULL; - return listgetdata(listhead(eigrp_om->eigrp)); + return listgetdata(listhead(eigrp_om->eigrp)); } diff --git a/eigrpd/eigrpd.h b/eigrpd/eigrpd.h index b3f233c58..5ec6c8e1f 100644 --- a/eigrpd/eigrpd.h +++ b/eigrpd/eigrpd.h @@ -43,12 +43,12 @@ extern struct thread_master *master; extern struct eigrp_master *eigrp_om; /* Prototypes */ - extern void eigrp_master_init (void); - extern void eigrp_terminate (void); - extern void eigrp_finish_final (struct eigrp *); - extern void eigrp_finish (struct eigrp *); - extern struct eigrp *eigrp_get (const char *); - extern struct eigrp *eigrp_lookup (void); - extern void eigrp_router_id_update (struct eigrp *); +extern void eigrp_master_init(void); +extern void eigrp_terminate(void); +extern void eigrp_finish_final(struct eigrp *); +extern void eigrp_finish(struct eigrp *); +extern struct eigrp *eigrp_get(const char *); +extern struct eigrp *eigrp_lookup(void); +extern void eigrp_router_id_update(struct eigrp *); #endif /* _ZEBRA_EIGRPD_H */ diff --git a/fpm/fpm.h b/fpm/fpm.h index 85285996c..ec1da6657 100644 --- a/fpm/fpm.h +++ b/fpm/fpm.h @@ -88,7 +88,7 @@ */ /* - * Local host as a default server for fpm connection + * Local host as a default server for fpm connection */ #define FPM_DEFAULT_IP (htonl (INADDR_LOOPBACK)) @@ -109,24 +109,23 @@ /* * Header that precedes each fpm message to/from the FPM. */ -typedef struct fpm_msg_hdr_t_ -{ - /* - * Protocol version. - */ - uint8_t version; - - /* - * Type of message, see below. - */ - uint8_t msg_type; - - /* - * Length of entire message, including the header, in network byte - * order. - */ - uint16_t msg_len; -} __attribute__ ((packed)) fpm_msg_hdr_t; +typedef struct fpm_msg_hdr_t_ { + /* + * Protocol version. + */ + uint8_t version; + + /* + * Type of message, see below. + */ + uint8_t msg_type; + + /* + * Length of entire message, including the header, in network byte + * order. + */ + uint16_t msg_len; +} __attribute__((packed)) fpm_msg_hdr_t; #ifdef __SUNPRO_C #pragma pack() @@ -138,19 +137,19 @@ typedef struct fpm_msg_hdr_t_ #define FPM_PROTO_VERSION 1 typedef enum fpm_msg_type_e_ { - FPM_MSG_TYPE_NONE = 0, - - /* - * Indicates that the payload is a completely formed netlink - * message. - * - * XXX Netlink cares about the alignment of messages. When any - * FPM_MSG_TYPE_NETLINK messages are sent over a channel, then all - * messages should be sized such that netlink alignment is - * maintained. - */ - FPM_MSG_TYPE_NETLINK = 1, - FPM_MSG_TYPE_PROTOBUF = 2, + FPM_MSG_TYPE_NONE = 0, + + /* + * Indicates that the payload is a completely formed netlink + * message. + * + * XXX Netlink cares about the alignment of messages. When any + * FPM_MSG_TYPE_NETLINK messages are sent over a channel, then all + * messages should be sized such that netlink alignment is + * maintained. + */ + FPM_MSG_TYPE_NETLINK = 1, + FPM_MSG_TYPE_PROTOBUF = 2, } fpm_msg_type_e; /* @@ -167,10 +166,9 @@ typedef enum fpm_msg_type_e_ { * * **NB**: Alignment is required only when netlink messages are used. */ -static inline size_t -fpm_msg_align (size_t len) +static inline size_t fpm_msg_align(size_t len) { - return (len + FPM_MSG_ALIGNTO - 1) & ~(FPM_MSG_ALIGNTO - 1); + return (len + FPM_MSG_ALIGNTO - 1) & ~(FPM_MSG_ALIGNTO - 1); } /* @@ -191,10 +189,9 @@ COMPILE_ASSERT(FPM_MSG_ALIGNTO == FPM_MSG_HDR_LEN); * The length value that should be placed in the msg_len field of the * header for a *payload* of size 'data_len'. */ -static inline size_t -fpm_data_len_to_msg_len (size_t data_len) +static inline size_t fpm_data_len_to_msg_len(size_t data_len) { - return data_len + FPM_MSG_HDR_LEN; + return data_len + FPM_MSG_HDR_LEN; } /* @@ -202,28 +199,25 @@ fpm_data_len_to_msg_len (size_t data_len) * * Pointer to the payload of the given fpm header. */ -static inline void * -fpm_msg_data (fpm_msg_hdr_t *hdr) +static inline void *fpm_msg_data(fpm_msg_hdr_t *hdr) { - return ((char*) hdr) + FPM_MSG_HDR_LEN; + return ((char *)hdr) + FPM_MSG_HDR_LEN; } /* * fpm_msg_len */ -static inline size_t -fpm_msg_len (const fpm_msg_hdr_t *hdr) +static inline size_t fpm_msg_len(const fpm_msg_hdr_t *hdr) { - return ntohs (hdr->msg_len); + return ntohs(hdr->msg_len); } /* * fpm_msg_data_len */ -static inline size_t -fpm_msg_data_len (const fpm_msg_hdr_t *hdr) +static inline size_t fpm_msg_data_len(const fpm_msg_hdr_t *hdr) { - return (fpm_msg_len (hdr) - FPM_MSG_HDR_LEN); + return (fpm_msg_len(hdr) - FPM_MSG_HDR_LEN); } /* @@ -231,23 +225,21 @@ fpm_msg_data_len (const fpm_msg_hdr_t *hdr) * * Move to the next message in a buffer. */ -static inline fpm_msg_hdr_t * -fpm_msg_next (fpm_msg_hdr_t *hdr, size_t *len) +static inline fpm_msg_hdr_t *fpm_msg_next(fpm_msg_hdr_t *hdr, size_t *len) { - size_t msg_len; + size_t msg_len; - msg_len = fpm_msg_len (hdr); + msg_len = fpm_msg_len(hdr); - if (len) { - if (*len < msg_len) - { - assert(0); - return NULL; - } - *len -= msg_len; - } + if (len) { + if (*len < msg_len) { + assert(0); + return NULL; + } + *len -= msg_len; + } - return (fpm_msg_hdr_t *) (((char*) hdr) + msg_len); + return (fpm_msg_hdr_t *)(((char *)hdr) + msg_len); } /* @@ -255,27 +247,26 @@ fpm_msg_next (fpm_msg_hdr_t *hdr, size_t *len) * * Returns TRUE if a message header looks well-formed. */ -static inline int -fpm_msg_hdr_ok (const fpm_msg_hdr_t *hdr) +static inline int fpm_msg_hdr_ok(const fpm_msg_hdr_t *hdr) { - size_t msg_len; + size_t msg_len; - if (hdr->msg_type == FPM_MSG_TYPE_NONE) - return 0; + if (hdr->msg_type == FPM_MSG_TYPE_NONE) + return 0; - msg_len = fpm_msg_len (hdr); + msg_len = fpm_msg_len(hdr); - if (msg_len < FPM_MSG_HDR_LEN || msg_len > FPM_MAX_MSG_LEN) - return 0; + if (msg_len < FPM_MSG_HDR_LEN || msg_len > FPM_MAX_MSG_LEN) + return 0; - /* - * Netlink messages must be aligned properly. - */ - if (hdr->msg_type == FPM_MSG_TYPE_NETLINK && - fpm_msg_align (msg_len) != msg_len) - return 0; + /* + * Netlink messages must be aligned properly. + */ + if (hdr->msg_type == FPM_MSG_TYPE_NETLINK + && fpm_msg_align(msg_len) != msg_len) + return 0; - return 1; + return 1; } /* @@ -285,25 +276,24 @@ fpm_msg_hdr_ok (const fpm_msg_hdr_t *hdr) * * @param len The length in bytes from 'hdr' to the end of the buffer. */ -static inline int -fpm_msg_ok (const fpm_msg_hdr_t *hdr, size_t len) +static inline int fpm_msg_ok(const fpm_msg_hdr_t *hdr, size_t len) { - if (len < FPM_MSG_HDR_LEN) - return 0; + if (len < FPM_MSG_HDR_LEN) + return 0; - if (!fpm_msg_hdr_ok (hdr)) - return 0; + if (!fpm_msg_hdr_ok(hdr)) + return 0; - if (fpm_msg_len (hdr) > len) - return 0; + if (fpm_msg_len(hdr) > len) + return 0; - return 1; + return 1; } // tcp maximum range #define TCP_MAX_PORT 65535 -// tcp minimum range +// tcp minimum range #define TCP_MIN_PORT 1 #endif /* _FPM_H */ diff --git a/fpm/fpm_pb.h b/fpm/fpm_pb.h index 2e5f3d052..2e265511f 100644 --- a/fpm/fpm_pb.h +++ b/fpm/fpm_pb.h @@ -38,25 +38,23 @@ * fpm__route_key__create */ #define fpm_route_key_create fpm__route_key__create -static inline Fpm__RouteKey * -fpm__route_key__create (qpb_allocator_t *allocator, struct prefix *prefix) +static inline Fpm__RouteKey *fpm__route_key__create(qpb_allocator_t *allocator, + struct prefix *prefix) { - Fpm__RouteKey *key; - - key = QPB_ALLOC (allocator, typeof (*key)); - if (!key) - { - return NULL; - } - fpm__route_key__init (key); - - key->prefix = qpb__l3_prefix__create (allocator, prefix); - if (!key->prefix) - { - return NULL; - } - - return key; + Fpm__RouteKey *key; + + key = QPB_ALLOC(allocator, typeof(*key)); + if (!key) { + return NULL; + } + fpm__route_key__init(key); + + key->prefix = qpb__l3_prefix__create(allocator, prefix); + if (!key->prefix) { + return NULL; + } + + return key; } #endif diff --git a/isisd/dict.c b/isisd/dict.c index 56676edaf..f09a8152a 100644 --- a/isisd/dict.c +++ b/isisd/dict.c @@ -24,7 +24,7 @@ /* * These macros provide short convenient names for structure members, * which are embellished with dict_ prefixes so that they are - * properly confined to the documented namespace. It's legal for a + * properly confined to the documented namespace. It's legal for a * program which uses dict to define, for instance, a macro called ``parent''. * Such a macro would interfere with the dnode_t struct definition. * In general, highly portable and reusable C modules which expose their @@ -67,26 +67,26 @@ static void dnode_free(dnode_t *node, void *context); static void rotate_left(dnode_t *upper) { - dnode_t *lower, *lowleft, *upparent; + dnode_t *lower, *lowleft, *upparent; - lower = upper->right; - upper->right = lowleft = lower->left; - lowleft->parent = upper; + lower = upper->right; + upper->right = lowleft = lower->left; + lowleft->parent = upper; - lower->parent = upparent = upper->parent; + lower->parent = upparent = upper->parent; - /* don't need to check for root node here because root->parent is - the sentinel nil node, and root->parent->left points back to root */ + /* don't need to check for root node here because root->parent is + the sentinel nil node, and root->parent->left points back to root */ - if (upper == upparent->left) { - upparent->left = lower; - } else { - assert (upper == upparent->right); - upparent->right = lower; - } + if (upper == upparent->left) { + upparent->left = lower; + } else { + assert(upper == upparent->right); + upparent->right = lower; + } - lower->left = upper; - upper->parent = lower; + lower->left = upper; + upper->parent = lower; } /* @@ -96,23 +96,23 @@ static void rotate_left(dnode_t *upper) static void rotate_right(dnode_t *upper) { - dnode_t *lower, *lowright, *upparent; + dnode_t *lower, *lowright, *upparent; - lower = upper->left; - upper->left = lowright = lower->right; - lowright->parent = upper; + lower = upper->left; + upper->left = lowright = lower->right; + lowright->parent = upper; - lower->parent = upparent = upper->parent; + lower->parent = upparent = upper->parent; - if (upper == upparent->right) { - upparent->right = lower; - } else { - assert (upper == upparent->left); - upparent->left = lower; - } + if (upper == upparent->right) { + upparent->right = lower; + } else { + assert(upper == upparent->left); + upparent->left = lower; + } - lower->right = upper; - upper->parent = lower; + lower->right = upper; + upper->parent = lower; } /* @@ -122,11 +122,11 @@ static void rotate_right(dnode_t *upper) static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil) { - if (node == nil) - return; - free_nodes(dict, node->left, nil); - free_nodes(dict, node->right, nil); - dict->freenode(node, dict->context); + if (node == nil) + return; + free_nodes(dict, node->left, nil); + free_nodes(dict, node->right, nil); + dict->freenode(node, dict->context); } /* @@ -135,29 +135,29 @@ static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil) * dict_next() successor function, verifying that the key of each node is * strictly lower than that of its successor, if duplicates are not allowed, * or lower or equal if duplicates are allowed. This function is used for - * debugging purposes. + * debugging purposes. */ static int verify_bintree(dict_t *dict) { - dnode_t *first, *next; + dnode_t *first, *next; - first = dict_first(dict); + first = dict_first(dict); - if (dict->dupes) { - while (first && (next = dict_next(dict, first))) { - if (dict->compare(first->key, next->key) > 0) - return 0; - first = next; - } - } else { - while (first && (next = dict_next(dict, first))) { - if (dict->compare(first->key, next->key) >= 0) - return 0; - first = next; + if (dict->dupes) { + while (first && (next = dict_next(dict, first))) { + if (dict->compare(first->key, next->key) > 0) + return 0; + first = next; + } + } else { + while (first && (next = dict_next(dict, first))) { + if (dict->compare(first->key, next->key) >= 0) + return 0; + first = next; + } } - } - return 1; + return 1; } @@ -176,27 +176,27 @@ static int verify_bintree(dict_t *dict) static unsigned int verify_redblack(dnode_t *nil, dnode_t *root) { - unsigned height_left, height_right; - - if (root != nil) { - height_left = verify_redblack(nil, root->left); - height_right = verify_redblack(nil, root->right); - if (height_left == 0 || height_right == 0) - return 0; - if (height_left != height_right) - return 0; - if (root->color == dnode_red) { - if (root->left->color != dnode_black) - return 0; - if (root->right->color != dnode_black) - return 0; - return height_left; + unsigned height_left, height_right; + + if (root != nil) { + height_left = verify_redblack(nil, root->left); + height_right = verify_redblack(nil, root->right); + if (height_left == 0 || height_right == 0) + return 0; + if (height_left != height_right) + return 0; + if (root->color == dnode_red) { + if (root->left->color != dnode_black) + return 0; + if (root->right->color != dnode_black) + return 0; + return height_left; + } + if (root->color != dnode_black) + return 0; + return height_left + 1; } - if (root->color != dnode_black) - return 0; - return height_left + 1; - } - return 1; + return 1; } /* @@ -207,11 +207,11 @@ static unsigned int verify_redblack(dnode_t *nil, dnode_t *root) static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root) { - if (root == nil) - return 0; - else - return 1 + verify_node_count(nil, root->left) - + verify_node_count(nil, root->right); + if (root == nil) + return 0; + else + return 1 + verify_node_count(nil, root->left) + + verify_node_count(nil, root->right); } /* @@ -223,12 +223,12 @@ static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root) static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node) { - if (root != nil) { - return root == node - || verify_dict_has_node(nil, root->left, node) - || verify_dict_has_node(nil, root->right, node); - } - return 0; + if (root != nil) { + return root == node + || verify_dict_has_node(nil, root->left, node) + || verify_dict_has_node(nil, root->right, node); + } + return 0; } @@ -238,37 +238,37 @@ static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node) dict_t *dict_create(dictcount_t maxcount, dict_comp_t comp) { - dict_t *new = XCALLOC(MTYPE_ISIS_DICT, sizeof(dict_t)); - - if (new) { - new->compare = comp; - new->allocnode = dnode_alloc; - new->freenode = dnode_free; - new->context = NULL; - new->nodecount = 0; - new->maxcount = maxcount; - new->nilnode.left = &new->nilnode; - new->nilnode.right = &new->nilnode; - new->nilnode.parent = &new->nilnode; - new->nilnode.color = dnode_black; - new->dupes = 0; - } - return new; + dict_t *new = XCALLOC(MTYPE_ISIS_DICT, sizeof(dict_t)); + + if (new) { + new->compare = comp; + new->allocnode = dnode_alloc; + new->freenode = dnode_free; + new->context = NULL; + new->nodecount = 0; + new->maxcount = maxcount; + new->nilnode.left = &new->nilnode; + new->nilnode.right = &new->nilnode; + new->nilnode.parent = &new->nilnode; + new->nilnode.color = dnode_black; + new->dupes = 0; + } + return new; } /* * Select a different set of node allocator routines. */ -void dict_set_allocator(dict_t *dict, dnode_alloc_t al, - dnode_free_t fr, void *context) +void dict_set_allocator(dict_t *dict, dnode_alloc_t al, dnode_free_t fr, + void *context) { - assert (dict_count(dict) == 0); - assert ((al == NULL && fr == NULL) || (al != NULL && fr != NULL)); + assert(dict_count(dict) == 0); + assert((al == NULL && fr == NULL) || (al != NULL && fr != NULL)); - dict->allocnode = al ? al : dnode_alloc; - dict->freenode = fr ? fr : dnode_free; - dict->context = context; + dict->allocnode = al ? al : dnode_alloc; + dict->freenode = fr ? fr : dnode_free; + dict->context = context; } /* @@ -278,8 +278,8 @@ void dict_set_allocator(dict_t *dict, dnode_alloc_t al, void dict_destroy(dict_t *dict) { - assert (dict_isempty(dict)); - XFREE(MTYPE_ISIS_DICT, dict); + assert(dict_isempty(dict)); + XFREE(MTYPE_ISIS_DICT, dict); } /* @@ -289,11 +289,11 @@ void dict_destroy(dict_t *dict) void dict_free_nodes(dict_t *dict) { - dnode_t *nil = dict_nil(dict), *root = dict_root(dict); - free_nodes(dict, root, nil); - dict->nodecount = 0; - dict->nilnode.left = &dict->nilnode; - dict->nilnode.right = &dict->nilnode; + dnode_t *nil = dict_nil(dict), *root = dict_root(dict); + free_nodes(dict, root, nil); + dict->nodecount = 0; + dict->nilnode.left = &dict->nilnode; + dict->nilnode.right = &dict->nilnode; } /* @@ -302,7 +302,7 @@ void dict_free_nodes(dict_t *dict) void dict_free(dict_t *dict) { - dict_free_nodes(dict); + dict_free_nodes(dict); } /* @@ -311,39 +311,39 @@ void dict_free(dict_t *dict) dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp) { - dict->compare = comp; - dict->allocnode = dnode_alloc; - dict->freenode = dnode_free; - dict->context = NULL; - dict->nodecount = 0; - dict->maxcount = maxcount; - dict->nilnode.left = &dict->nilnode; - dict->nilnode.right = &dict->nilnode; - dict->nilnode.parent = &dict->nilnode; - dict->nilnode.color = dnode_black; - dict->dupes = 0; - return dict; + dict->compare = comp; + dict->allocnode = dnode_alloc; + dict->freenode = dnode_free; + dict->context = NULL; + dict->nodecount = 0; + dict->maxcount = maxcount; + dict->nilnode.left = &dict->nilnode; + dict->nilnode.right = &dict->nilnode; + dict->nilnode.parent = &dict->nilnode; + dict->nilnode.color = dnode_black; + dict->dupes = 0; + return dict; } -/* +/* * Initialize a dictionary in the likeness of another dictionary */ void dict_init_like(dict_t *dict, const dict_t *template) { - dict->compare = template->compare; - dict->allocnode = template->allocnode; - dict->freenode = template->freenode; - dict->context = template->context; - dict->nodecount = 0; - dict->maxcount = template->maxcount; - dict->nilnode.left = &dict->nilnode; - dict->nilnode.right = &dict->nilnode; - dict->nilnode.parent = &dict->nilnode; - dict->nilnode.color = dnode_black; - dict->dupes = template->dupes; - - assert (dict_similar(dict, template)); + dict->compare = template->compare; + dict->allocnode = template->allocnode; + dict->freenode = template->freenode; + dict->context = template->context; + dict->nodecount = 0; + dict->maxcount = template->maxcount; + dict->nilnode.left = &dict->nilnode; + dict->nilnode.right = &dict->nilnode; + dict->nilnode.parent = &dict->nilnode; + dict->nilnode.color = dnode_black; + dict->dupes = template->dupes; + + assert(dict_similar(dict, template)); } /* @@ -352,11 +352,11 @@ void dict_init_like(dict_t *dict, const dict_t *template) static void dict_clear(dict_t *dict) { - dict->nodecount = 0; - dict->nilnode.left = &dict->nilnode; - dict->nilnode.right = &dict->nilnode; - dict->nilnode.parent = &dict->nilnode; - assert (dict->nilnode.color == dnode_black); + dict->nodecount = 0; + dict->nilnode.left = &dict->nilnode; + dict->nilnode.right = &dict->nilnode; + dict->nilnode.parent = &dict->nilnode; + assert(dict->nilnode.color == dnode_black); } @@ -365,31 +365,31 @@ static void dict_clear(dict_t *dict) * debugging purposes, and should be placed in assert statements. Just because * this function succeeds doesn't mean that the tree is not corrupt. Certain * corruptions in the tree may simply cause undefined behavior. - */ + */ int dict_verify(dict_t *dict) { - dnode_t *nil = dict_nil(dict), *root = dict_root(dict); + dnode_t *nil = dict_nil(dict), *root = dict_root(dict); - /* check that the sentinel node and root node are black */ - if (root->color != dnode_black) - return 0; - if (nil->color != dnode_black) - return 0; - if (nil->right != nil) - return 0; - /* nil->left is the root node; check that its parent pointer is nil */ - if (nil->left->parent != nil) - return 0; - /* perform a weak test that the tree is a binary search tree */ - if (!verify_bintree(dict)) - return 0; - /* verify that the tree is a red-black tree */ - if (!verify_redblack(nil, root)) - return 0; - if (verify_node_count(nil, root) != dict_count(dict)) - return 0; - return 1; + /* check that the sentinel node and root node are black */ + if (root->color != dnode_black) + return 0; + if (nil->color != dnode_black) + return 0; + if (nil->right != nil) + return 0; + /* nil->left is the root node; check that its parent pointer is nil */ + if (nil->left->parent != nil) + return 0; + /* perform a weak test that the tree is a binary search tree */ + if (!verify_bintree(dict)) + return 0; + /* verify that the tree is a red-black tree */ + if (!verify_redblack(nil, root)) + return 0; + if (verify_node_count(nil, root) != dict_count(dict)) + return 0; + return 1; } /* @@ -399,62 +399,64 @@ int dict_verify(dict_t *dict) int dict_similar(const dict_t *left, const dict_t *right) { - if (left->compare != right->compare) - return 0; + if (left->compare != right->compare) + return 0; - if (left->allocnode != right->allocnode) - return 0; + if (left->allocnode != right->allocnode) + return 0; - if (left->freenode != right->freenode) - return 0; + if (left->freenode != right->freenode) + return 0; - if (left->context != right->context) - return 0; + if (left->context != right->context) + return 0; - if (left->dupes != right->dupes) - return 0; + if (left->dupes != right->dupes) + return 0; - return 1; + return 1; } /* * Locate a node in the dictionary having the given key. - * If the node is not found, a null a pointer is returned (rather than + * If the node is not found, a null a pointer is returned (rather than * a pointer that dictionary's nil sentinel node), otherwise a pointer to the * located node is returned. */ dnode_t *dict_lookup(dict_t *dict, const void *key) { - dnode_t *root = dict_root(dict); - dnode_t *nil = dict_nil(dict); - dnode_t *saved; - int result; - - /* simple binary search adapted for trees that contain duplicate keys */ - - while (root != nil) { - result = dict->compare(key, root->key); - if (result < 0) - root = root->left; - else if (result > 0) - root = root->right; - else { - if (!dict->dupes) { /* no duplicates, return match */ - return root; - } else { /* could be dupes, find leftmost one */ - do { - saved = root; - root = root->left; - while (root != nil && dict->compare(key, root->key)) + dnode_t *root = dict_root(dict); + dnode_t *nil = dict_nil(dict); + dnode_t *saved; + int result; + + /* simple binary search adapted for trees that contain duplicate keys */ + + while (root != nil) { + result = dict->compare(key, root->key); + if (result < 0) + root = root->left; + else if (result > 0) root = root->right; - } while (root != nil); - return saved; - } + else { + if (!dict->dupes) { /* no duplicates, return match + */ + return root; + } else { /* could be dupes, find leftmost one */ + do { + saved = root; + root = root->left; + while (root != nil + && dict->compare(key, root->key)) + root = root->right; + } while (root != nil); + return saved; + } + } } - } - return NULL; + return NULL; } /* @@ -464,29 +466,29 @@ dnode_t *dict_lookup(dict_t *dict, const void *key) dnode_t *dict_lower_bound(dict_t *dict, const void *key) { - dnode_t *root = dict_root(dict); - dnode_t *nil = dict_nil(dict); - dnode_t *tentative = 0; - - while (root != nil) { - int result = dict->compare(key, root->key); - - if (result > 0) { - root = root->right; - } else if (result < 0) { - tentative = root; - root = root->left; - } else { - if (!dict->dupes) { - return root; - } else { - tentative = root; - root = root->left; - } - } - } - - return tentative; + dnode_t *root = dict_root(dict); + dnode_t *nil = dict_nil(dict); + dnode_t *tentative = 0; + + while (root != nil) { + int result = dict->compare(key, root->key); + + if (result > 0) { + root = root->right; + } else if (result < 0) { + tentative = root; + root = root->left; + } else { + if (!dict->dupes) { + return root; + } else { + tentative = root; + root = root->left; + } + } + } + + return tentative; } /* @@ -496,29 +498,29 @@ dnode_t *dict_lower_bound(dict_t *dict, const void *key) dnode_t *dict_upper_bound(dict_t *dict, const void *key) { - dnode_t *root = dict_root(dict); - dnode_t *nil = dict_nil(dict); - dnode_t *tentative = 0; - - while (root != nil) { - int result = dict->compare(key, root->key); - - if (result < 0) { - root = root->left; - } else if (result > 0) { - tentative = root; - root = root->right; - } else { - if (!dict->dupes) { - return root; - } else { - tentative = root; - root = root->right; - } - } - } - - return tentative; + dnode_t *root = dict_root(dict); + dnode_t *nil = dict_nil(dict); + dnode_t *tentative = 0; + + while (root != nil) { + int result = dict->compare(key, root->key); + + if (result < 0) { + root = root->left; + } else if (result > 0) { + tentative = root; + root = root->right; + } else { + if (!dict->dupes) { + return root; + } else { + tentative = root; + root = root->right; + } + } + } + + return tentative; } /* @@ -531,93 +533,96 @@ dnode_t *dict_upper_bound(dict_t *dict, const void *key) void dict_insert(dict_t *dict, dnode_t *node, const void *key) { - dnode_t *where = dict_root(dict), *nil = dict_nil(dict); - dnode_t *parent = nil, *uncle, *grandpa; - int result = -1; - - node->key = key; - - assert (!dict_isfull(dict)); - assert (!dict_contains(dict, node)); - assert (!dnode_is_in_a_dict(node)); + dnode_t *where = dict_root(dict), *nil = dict_nil(dict); + dnode_t *parent = nil, *uncle, *grandpa; + int result = -1; + + node->key = key; + + assert(!dict_isfull(dict)); + assert(!dict_contains(dict, node)); + assert(!dnode_is_in_a_dict(node)); + + /* basic binary tree insert */ + + while (where != nil) { + parent = where; + result = dict->compare(key, where->key); + /* trap attempts at duplicate key insertion unless it's + * explicitly allowed */ + assert(dict->dupes || result != 0); + if (result < 0) + where = where->left; + else + where = where->right; + } - /* basic binary tree insert */ + assert(where == nil); - while (where != nil) { - parent = where; - result = dict->compare(key, where->key); - /* trap attempts at duplicate key insertion unless it's explicitly allowed */ - assert (dict->dupes || result != 0); if (result < 0) - where = where->left; + parent->left = node; else - where = where->right; - } - - assert (where == nil); - - if (result < 0) - parent->left = node; - else - parent->right = node; - - node->parent = parent; - node->left = nil; - node->right = nil; - - dict->nodecount++; - - /* red black adjustments */ - - node->color = dnode_red; - - while (parent->color == dnode_red) { - grandpa = parent->parent; - if (parent == grandpa->left) { - uncle = grandpa->right; - if (uncle->color == dnode_red) { /* red parent, red uncle */ - parent->color = dnode_black; - uncle->color = dnode_black; - grandpa->color = dnode_red; - node = grandpa; - parent = grandpa->parent; - } else { /* red parent, black uncle */ - if (node == parent->right) { - rotate_left(parent); - parent = node; - assert (grandpa == parent->parent); - /* rotation between parent and child preserves grandpa */ - } - parent->color = dnode_black; - grandpa->color = dnode_red; - rotate_right(grandpa); - break; - } - } else { /* symmetric cases: parent == parent->parent->right */ - uncle = grandpa->left; - if (uncle->color == dnode_red) { - parent->color = dnode_black; - uncle->color = dnode_black; - grandpa->color = dnode_red; - node = grandpa; - parent = grandpa->parent; - } else { - if (node == parent->left) { - rotate_right(parent); - parent = node; - assert (grandpa == parent->parent); + parent->right = node; + + node->parent = parent; + node->left = nil; + node->right = nil; + + dict->nodecount++; + + /* red black adjustments */ + + node->color = dnode_red; + + while (parent->color == dnode_red) { + grandpa = parent->parent; + if (parent == grandpa->left) { + uncle = grandpa->right; + if (uncle->color + == dnode_red) { /* red parent, red uncle */ + parent->color = dnode_black; + uncle->color = dnode_black; + grandpa->color = dnode_red; + node = grandpa; + parent = grandpa->parent; + } else { /* red parent, black uncle */ + if (node == parent->right) { + rotate_left(parent); + parent = node; + assert(grandpa == parent->parent); + /* rotation between parent and child + * preserves grandpa */ + } + parent->color = dnode_black; + grandpa->color = dnode_red; + rotate_right(grandpa); + break; + } + } else { /* symmetric cases: parent == parent->parent->right */ + uncle = grandpa->left; + if (uncle->color == dnode_red) { + parent->color = dnode_black; + uncle->color = dnode_black; + grandpa->color = dnode_red; + node = grandpa; + parent = grandpa->parent; + } else { + if (node == parent->left) { + rotate_right(parent); + parent = node; + assert(grandpa == parent->parent); + } + parent->color = dnode_black; + grandpa->color = dnode_red; + rotate_left(grandpa); + break; + } } - parent->color = dnode_black; - grandpa->color = dnode_red; - rotate_left(grandpa); - break; - } } - } - dict_root(dict)->color = dnode_black; + dict_root(dict)->color = dnode_black; - assert (dict_verify(dict)); + assert(dict_verify(dict)); } /* @@ -628,172 +633,185 @@ void dict_insert(dict_t *dict, dnode_t *node, const void *key) dnode_t *dict_delete(dict_t *dict, dnode_t *delete) { - dnode_t *nil = dict_nil(dict), *child, *delparent = delete->parent; - - /* basic deletion */ - - assert (!dict_isempty(dict)); - assert (dict_contains(dict, delete)); - - /* - * If the node being deleted has two children, then we replace it with its - * successor (i.e. the leftmost node in the right subtree.) By doing this, - * we avoid the traditional algorithm under which the successor's key and - * value *only* move to the deleted node and the successor is spliced out - * from the tree. We cannot use this approach because the user may hold - * pointers to the successor, or nodes may be inextricably tied to some - * other structures by way of embedding, etc. So we must splice out the - * node we are given, not some other node, and must not move contents from - * one node to another behind the user's back. - */ - - if (delete->left != nil && delete->right != nil) { - dnode_t *next = dict_next(dict, delete); - assert (next); - dnode_t *nextparent = next->parent; - dnode_color_t nextcolor = next->color; - - assert (next != nil); - assert (next->parent != nil); - assert (next->left == nil); + dnode_t *nil = dict_nil(dict), *child, *delparent = delete->parent; - /* - * First, splice out the successor from the tree completely, by - * moving up its right child into its place. - */ + /* basic deletion */ - child = next->right; - child->parent = nextparent; - - if (nextparent->left == next) { - nextparent->left = child; - } else { - assert (nextparent->right == next); - nextparent->right = child; - } + assert(!dict_isempty(dict)); + assert(dict_contains(dict, delete)); /* - * Now that the successor has been extricated from the tree, install it - * in place of the node that we want deleted. + * If the node being deleted has two children, then we replace it with + * its + * successor (i.e. the leftmost node in the right subtree.) By doing + * this, + * we avoid the traditional algorithm under which the successor's key + * and + * value *only* move to the deleted node and the successor is spliced + * out + * from the tree. We cannot use this approach because the user may hold + * pointers to the successor, or nodes may be inextricably tied to some + * other structures by way of embedding, etc. So we must splice out the + * node we are given, not some other node, and must not move contents + * from + * one node to another behind the user's back. */ - next->parent = delparent; - next->left = delete->left; - next->right = delete->right; - next->left->parent = next; - next->right->parent = next; - next->color = delete->color; - delete->color = nextcolor; - - if (delparent->left == delete) { - delparent->left = next; - } else { - assert (delparent->right == delete); - delparent->right = next; - } - - } else { - assert (delete != nil); - assert (delete->left == nil || delete->right == nil); + if (delete->left != nil && delete->right != nil) { + dnode_t *next = dict_next(dict, delete); + assert(next); + dnode_t *nextparent = next->parent; + dnode_color_t nextcolor = next->color; - child = (delete->left != nil) ? delete->left : delete->right; + assert(next != nil); + assert(next->parent != nil); + assert(next->left == nil); - child->parent = delparent = delete->parent; - - if (delete == delparent->left) { - delparent->left = child; - } else { - assert (delete == delparent->right); - delparent->right = child; - } - } + /* + * First, splice out the successor from the tree completely, by + * moving up its right child into its place. + */ - delete->parent = NULL; - delete->right = NULL; - delete->left = NULL; + child = next->right; + child->parent = nextparent; - dict->nodecount--; + if (nextparent->left == next) { + nextparent->left = child; + } else { + assert(nextparent->right == next); + nextparent->right = child; + } - assert (verify_bintree(dict)); + /* + * Now that the successor has been extricated from the tree, + * install it + * in place of the node that we want deleted. + */ + + next->parent = delparent; + next->left = delete->left; + next->right = delete->right; + next->left->parent = next; + next->right->parent = next; + next->color = delete->color; + delete->color = nextcolor; + + if (delparent->left == delete) { + delparent->left = next; + } else { + assert(delparent->right == delete); + delparent->right = next; + } - /* red-black adjustments */ + } else { + assert(delete != nil); + assert(delete->left == nil || delete->right == nil); - if (delete->color == dnode_black) { - dnode_t *parent, *sister; + child = (delete->left != nil) ? delete->left : delete->right; - dict_root(dict)->color = dnode_red; + child->parent = delparent = delete->parent; - while (child->color == dnode_black) { - parent = child->parent; - if (child == parent->left) { - sister = parent->right; - assert (sister != nil); - if (sister->color == dnode_red) { - sister->color = dnode_black; - parent->color = dnode_red; - rotate_left(parent); - sister = parent->right; - assert (sister != nil); - } - if (sister->left->color == dnode_black - && sister->right->color == dnode_black) { - sister->color = dnode_red; - child = parent; + if (delete == delparent->left) { + delparent->left = child; } else { - if (sister->right->color == dnode_black) { - assert (sister->left->color == dnode_red); - sister->left->color = dnode_black; - sister->color = dnode_red; - rotate_right(sister); - sister = parent->right; - assert (sister != nil); - } - sister->color = parent->color; - sister->right->color = dnode_black; - parent->color = dnode_black; - rotate_left(parent); - break; - } - } else { /* symmetric case: child == child->parent->right */ - assert (child == parent->right); - sister = parent->left; - assert (sister != nil); - if (sister->color == dnode_red) { - sister->color = dnode_black; - parent->color = dnode_red; - rotate_right(parent); - sister = parent->left; - assert (sister != nil); + assert(delete == delparent->right); + delparent->right = child; } - if (sister->right->color == dnode_black - && sister->left->color == dnode_black) { - sister->color = dnode_red; - child = parent; - } else { - if (sister->left->color == dnode_black) { - assert (sister->right->color == dnode_red); - sister->right->color = dnode_black; - sister->color = dnode_red; - rotate_left(sister); - sister = parent->left; - assert (sister != nil); - } - sister->color = parent->color; - sister->left->color = dnode_black; - parent->color = dnode_black; - rotate_right(parent); - break; - } - } } - child->color = dnode_black; - dict_root(dict)->color = dnode_black; - } + delete->parent = NULL; + delete->right = NULL; + delete->left = NULL; + + dict->nodecount--; + + assert(verify_bintree(dict)); + + /* red-black adjustments */ + + if (delete->color == dnode_black) { + dnode_t *parent, *sister; + + dict_root(dict)->color = dnode_red; + + while (child->color == dnode_black) { + parent = child->parent; + if (child == parent->left) { + sister = parent->right; + assert(sister != nil); + if (sister->color == dnode_red) { + sister->color = dnode_black; + parent->color = dnode_red; + rotate_left(parent); + sister = parent->right; + assert(sister != nil); + } + if (sister->left->color == dnode_black + && sister->right->color == dnode_black) { + sister->color = dnode_red; + child = parent; + } else { + if (sister->right->color + == dnode_black) { + assert(sister->left->color + == dnode_red); + sister->left->color = + dnode_black; + sister->color = dnode_red; + rotate_right(sister); + sister = parent->right; + assert(sister != nil); + } + sister->color = parent->color; + sister->right->color = dnode_black; + parent->color = dnode_black; + rotate_left(parent); + break; + } + } else { /* symmetric case: child == + child->parent->right */ + assert(child == parent->right); + sister = parent->left; + assert(sister != nil); + if (sister->color == dnode_red) { + sister->color = dnode_black; + parent->color = dnode_red; + rotate_right(parent); + sister = parent->left; + assert(sister != nil); + } + if (sister->right->color == dnode_black + && sister->left->color == dnode_black) { + sister->color = dnode_red; + child = parent; + } else { + if (sister->left->color + == dnode_black) { + assert(sister->right->color + == dnode_red); + sister->right->color = + dnode_black; + sister->color = dnode_red; + rotate_left(sister); + sister = parent->left; + assert(sister != nil); + } + sister->color = parent->color; + sister->left->color = dnode_black; + parent->color = dnode_black; + rotate_right(parent); + break; + } + } + } + + child->color = dnode_black; + dict_root(dict)->color = dnode_black; + } - assert (dict_verify(dict)); + assert(dict_verify(dict)); - return delete; + return delete; } /* @@ -803,20 +821,20 @@ dnode_t *dict_delete(dict_t *dict, dnode_t *delete) int dict_alloc_insert(dict_t *dict, const void *key, void *data) { - dnode_t *node = dict->allocnode (dict->context); + dnode_t *node = dict->allocnode(dict->context); - if (node) { - dnode_init(node, data); - dict_insert(dict, node, key); - return 1; - } - return 0; + if (node) { + dnode_init(node, data); + dict_insert(dict, node, key); + return 1; + } + return 0; } void dict_delete_free(dict_t *dict, dnode_t *node) { - dict_delete(dict, node); - dict->freenode(node, dict->context); + dict_delete(dict, node); + dict->freenode(node, dict->context); } /* @@ -826,13 +844,13 @@ void dict_delete_free(dict_t *dict, dnode_t *node) dnode_t *dict_first(dict_t *dict) { - dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left; + dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left; - if (root != nil) - while ((left = root->left) != nil) - root = left; + if (root != nil) + while ((left = root->left) != nil) + root = left; - return (root == nil) ? NULL : root; + return (root == nil) ? NULL : root; } /* @@ -842,13 +860,13 @@ dnode_t *dict_first(dict_t *dict) dnode_t *dict_last(dict_t *dict) { - dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *right; + dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *right; - if (root != nil) - while ((right = root->right) != nil) - root = right; + if (root != nil) + while ((right = root->right) != nil) + root = right; - return (root == nil) ? NULL : root; + return (root == nil) ? NULL : root; } /* @@ -860,23 +878,23 @@ dnode_t *dict_last(dict_t *dict) dnode_t *dict_next(dict_t *dict, dnode_t *curr) { - dnode_t *nil = dict_nil(dict), *parent, *left; + dnode_t *nil = dict_nil(dict), *parent, *left; - if (curr->right != nil) { - curr = curr->right; - while ((left = curr->left) != nil) - curr = left; - return curr; - } - - parent = curr->parent; + if (curr->right != nil) { + curr = curr->right; + while ((left = curr->left) != nil) + curr = left; + return curr; + } - while (parent != nil && curr == parent->right) { - curr = parent; parent = curr->parent; - } - return (parent == nil) ? NULL : parent; + while (parent != nil && curr == parent->right) { + curr = parent; + parent = curr->parent; + } + + return (parent == nil) ? NULL : parent; } /* @@ -886,28 +904,28 @@ dnode_t *dict_next(dict_t *dict, dnode_t *curr) dnode_t *dict_prev(dict_t *dict, dnode_t *curr) { - dnode_t *nil = dict_nil(dict), *parent, *right; - - if (curr->left != nil) { - curr = curr->left; - while ((right = curr->right) != nil) - curr = right; - return curr; - } + dnode_t *nil = dict_nil(dict), *parent, *right; - parent = curr->parent; + if (curr->left != nil) { + curr = curr->left; + while ((right = curr->right) != nil) + curr = right; + return curr; + } - while (parent != nil && curr == parent->left) { - curr = parent; parent = curr->parent; - } - return (parent == nil) ? NULL : parent; + while (parent != nil && curr == parent->left) { + curr = parent; + parent = curr->parent; + } + + return (parent == nil) ? NULL : parent; } void dict_allow_dupes(dict_t *dict) { - dict->dupes = 1; + dict->dupes = 1; } #undef dict_count @@ -919,266 +937,266 @@ void dict_allow_dupes(dict_t *dict) dictcount_t dict_count(dict_t *dict) { - return dict->nodecount; + return dict->nodecount; } int dict_isempty(dict_t *dict) { - return dict->nodecount == 0; + return dict->nodecount == 0; } int dict_isfull(dict_t *dict) { - return dict->nodecount == dict->maxcount; + return dict->nodecount == dict->maxcount; } int dict_contains(dict_t *dict, dnode_t *node) { - return verify_dict_has_node(dict_nil(dict), dict_root(dict), node); + return verify_dict_has_node(dict_nil(dict), dict_root(dict), node); } static dnode_t *dnode_alloc(void *context) { - return XCALLOC(MTYPE_ISIS_DICT_NODE, sizeof(dnode_t)); + return XCALLOC(MTYPE_ISIS_DICT_NODE, sizeof(dnode_t)); } static void dnode_free(dnode_t *node, void *context) { - XFREE(MTYPE_ISIS_DICT_NODE, node); + XFREE(MTYPE_ISIS_DICT_NODE, node); } dnode_t *dnode_create(void *data) { - dnode_t *new = XCALLOC(MTYPE_ISIS_DICT_NODE, sizeof(dnode_t)); - if (new) { - new->data = data; - new->parent = NULL; - new->left = NULL; - new->right = NULL; - } - return new; + dnode_t *new = XCALLOC(MTYPE_ISIS_DICT_NODE, sizeof(dnode_t)); + if (new) { + new->data = data; + new->parent = NULL; + new->left = NULL; + new->right = NULL; + } + return new; } dnode_t *dnode_init(dnode_t *dnode, void *data) { - dnode->data = data; - dnode->parent = NULL; - dnode->left = NULL; - dnode->right = NULL; - return dnode; + dnode->data = data; + dnode->parent = NULL; + dnode->left = NULL; + dnode->right = NULL; + return dnode; } void dnode_destroy(dnode_t *dnode) { - assert (!dnode_is_in_a_dict(dnode)); - XFREE(MTYPE_ISIS_DICT_NODE, dnode); + assert(!dnode_is_in_a_dict(dnode)); + XFREE(MTYPE_ISIS_DICT_NODE, dnode); } void *dnode_get(dnode_t *dnode) { - return dnode->data; + return dnode->data; } const void *dnode_getkey(dnode_t *dnode) { - return dnode->key; + return dnode->key; } void dnode_put(dnode_t *dnode, void *data) { - dnode->data = data; + dnode->data = data; } int dnode_is_in_a_dict(dnode_t *dnode) { - return (dnode->parent && dnode->left && dnode->right); + return (dnode->parent && dnode->left && dnode->right); } void dict_process(dict_t *dict, void *context, dnode_process_t function) { - dnode_t *node = dict_first(dict), *next; - - while (node != NULL) { - /* check for callback function deleting */ - /* the next node from under us */ - assert (dict_contains(dict, node)); - next = dict_next(dict, node); - function(dict, node, context); - node = next; - } + dnode_t *node = dict_first(dict), *next; + + while (node != NULL) { + /* check for callback function deleting */ + /* the next node from under us */ + assert(dict_contains(dict, node)); + next = dict_next(dict, node); + function(dict, node, context); + node = next; + } } static void load_begin_internal(dict_load_t *load, dict_t *dict) { - load->dictptr = dict; - load->nilnode.left = &load->nilnode; - load->nilnode.right = &load->nilnode; + load->dictptr = dict; + load->nilnode.left = &load->nilnode; + load->nilnode.right = &load->nilnode; } void dict_load_begin(dict_load_t *load, dict_t *dict) { - assert (dict_isempty(dict)); - load_begin_internal(load, dict); + assert(dict_isempty(dict)); + load_begin_internal(load, dict); } void dict_load_next(dict_load_t *load, dnode_t *newnode, const void *key) { - dict_t *dict = load->dictptr; - dnode_t *nil = &load->nilnode; - - assert (!dnode_is_in_a_dict(newnode)); - assert (dict->nodecount < dict->maxcount); - - #ifndef NDEBUG - if (dict->nodecount > 0) { - if (dict->dupes) - assert (dict->compare(nil->left->key, key) <= 0); - else - assert (dict->compare(nil->left->key, key) < 0); - } - #endif - - newnode->key = key; - nil->right->left = newnode; - nil->right = newnode; - newnode->left = nil; - dict->nodecount++; + dict_t *dict = load->dictptr; + dnode_t *nil = &load->nilnode; + + assert(!dnode_is_in_a_dict(newnode)); + assert(dict->nodecount < dict->maxcount); + +#ifndef NDEBUG + if (dict->nodecount > 0) { + if (dict->dupes) + assert(dict->compare(nil->left->key, key) <= 0); + else + assert(dict->compare(nil->left->key, key) < 0); + } +#endif + + newnode->key = key; + nil->right->left = newnode; + nil->right = newnode; + newnode->left = nil; + dict->nodecount++; } void dict_load_end(dict_load_t *load) { - dict_t *dict = load->dictptr; - dnode_t *tree[DICT_DEPTH_MAX] = { 0 }; - dnode_t *curr, *dictnil = dict_nil(dict), *loadnil = &load->nilnode, *next; - dnode_t *complete = 0; - dictcount_t fullcount = DICTCOUNT_T_MAX, nodecount = dict->nodecount; - dictcount_t botrowcount; - unsigned baselevel = 0, level = 0, i; - - assert (dnode_red == 0 && dnode_black == 1); - - while (fullcount >= nodecount && fullcount) - fullcount >>= 1; - - botrowcount = nodecount - fullcount; - - for (curr = loadnil->left; curr != loadnil; curr = next) { - next = curr->left; - - if (complete == NULL && botrowcount-- == 0) { - assert (baselevel == 0); - assert (level == 0); - baselevel = level = 1; - complete = tree[0]; - - if (complete != 0) { - tree[0] = 0; - complete->right = dictnil; - while (tree[level] != 0) { - tree[level]->right = complete; - complete->parent = tree[level]; - complete = tree[level]; - tree[level++] = 0; + dict_t *dict = load->dictptr; + dnode_t *tree[DICT_DEPTH_MAX] = {0}; + dnode_t *curr, *dictnil = dict_nil(dict), *loadnil = &load->nilnode, + *next; + dnode_t *complete = 0; + dictcount_t fullcount = DICTCOUNT_T_MAX, nodecount = dict->nodecount; + dictcount_t botrowcount; + unsigned baselevel = 0, level = 0, i; + + assert(dnode_red == 0 && dnode_black == 1); + + while (fullcount >= nodecount && fullcount) + fullcount >>= 1; + + botrowcount = nodecount - fullcount; + + for (curr = loadnil->left; curr != loadnil; curr = next) { + next = curr->left; + + if (complete == NULL && botrowcount-- == 0) { + assert(baselevel == 0); + assert(level == 0); + baselevel = level = 1; + complete = tree[0]; + + if (complete != 0) { + tree[0] = 0; + complete->right = dictnil; + while (tree[level] != 0) { + tree[level]->right = complete; + complete->parent = tree[level]; + complete = tree[level]; + tree[level++] = 0; + } + } } - } - } - if (complete == NULL) { - curr->left = dictnil; - curr->right = dictnil; - curr->color = level % 2; - complete = curr; - - assert (level == baselevel); - while (tree[level] != 0) { - tree[level]->right = complete; - complete->parent = tree[level]; - complete = tree[level]; - tree[level++] = 0; - } - } else { - curr->left = complete; - curr->color = (level + 1) % 2; - complete->parent = curr; - tree[level] = curr; - complete = 0; - level = baselevel; + if (complete == NULL) { + curr->left = dictnil; + curr->right = dictnil; + curr->color = level % 2; + complete = curr; + + assert(level == baselevel); + while (tree[level] != 0) { + tree[level]->right = complete; + complete->parent = tree[level]; + complete = tree[level]; + tree[level++] = 0; + } + } else { + curr->left = complete; + curr->color = (level + 1) % 2; + complete->parent = curr; + tree[level] = curr; + complete = 0; + level = baselevel; + } } - } - if (complete == NULL) - complete = dictnil; + if (complete == NULL) + complete = dictnil; - for (i = 0; i < DICT_DEPTH_MAX; i++) { - if (tree[i] != 0) { - tree[i]->right = complete; - complete->parent = tree[i]; - complete = tree[i]; + for (i = 0; i < DICT_DEPTH_MAX; i++) { + if (tree[i] != 0) { + tree[i]->right = complete; + complete->parent = tree[i]; + complete = tree[i]; + } } - } - dictnil->color = dnode_black; - dictnil->right = dictnil; - complete->parent = dictnil; - complete->color = dnode_black; - dict_root(dict) = complete; + dictnil->color = dnode_black; + dictnil->right = dictnil; + complete->parent = dictnil; + complete->color = dnode_black; + dict_root(dict) = complete; - assert (dict_verify(dict)); + assert(dict_verify(dict)); } void dict_merge(dict_t *dest, dict_t *source) { - dict_load_t load; - dnode_t *leftnode = dict_first(dest), *rightnode = dict_first(source); - - assert (dict_similar(dest, source)); - - if (source == dest) - return; - - dest->nodecount = 0; - load_begin_internal(&load, dest); - - for (;;) { - if (leftnode != NULL && rightnode != NULL) { - if (dest->compare(leftnode->key, rightnode->key) < 0) - goto copyleft; - else - goto copyright; - } else if (leftnode != NULL) { - goto copyleft; - } else if (rightnode != NULL) { - goto copyright; - } else { - assert (leftnode == NULL && rightnode == NULL); - break; + dict_load_t load; + dnode_t *leftnode = dict_first(dest), *rightnode = dict_first(source); + + assert(dict_similar(dest, source)); + + if (source == dest) + return; + + dest->nodecount = 0; + load_begin_internal(&load, dest); + + for (;;) { + if (leftnode != NULL && rightnode != NULL) { + if (dest->compare(leftnode->key, rightnode->key) < 0) + goto copyleft; + else + goto copyright; + } else if (leftnode != NULL) { + goto copyleft; + } else if (rightnode != NULL) { + goto copyright; + } else { + assert(leftnode == NULL && rightnode == NULL); + break; + } + + copyleft : { + dnode_t *next = dict_next(dest, leftnode); +#ifndef NDEBUG + leftnode->left = + NULL; /* suppress assertion in dict_load_next */ +#endif + dict_load_next(&load, leftnode, leftnode->key); + leftnode = next; + continue; } - copyleft: - { - dnode_t *next = dict_next(dest, leftnode); - #ifndef NDEBUG - leftnode->left = NULL; /* suppress assertion in dict_load_next */ - #endif - dict_load_next(&load, leftnode, leftnode->key); - leftnode = next; - continue; + copyright : { + dnode_t *next = dict_next(source, rightnode); +#ifndef NDEBUG + rightnode->left = NULL; +#endif + dict_load_next(&load, rightnode, rightnode->key); + rightnode = next; + continue; } - - copyright: - { - dnode_t *next = dict_next(source, rightnode); - #ifndef NDEBUG - rightnode->left = NULL; - #endif - dict_load_next(&load, rightnode, rightnode->key); - rightnode = next; - continue; } - } - dict_clear(source); - dict_load_end(&load); + dict_clear(source); + dict_load_end(&load); } #ifdef KAZLIB_TEST_MAIN @@ -1192,54 +1210,54 @@ typedef char input_t[256]; static int tokenize(char *string, ...) { - char **tokptr; - va_list arglist; - int tokcount = 0; - - va_start(arglist, string); - tokptr = va_arg(arglist, char **); - while (tokptr) { - while (*string && isspace((unsigned char) *string)) - string++; - if (!*string) - break; - *tokptr = string; - while (*string && !isspace((unsigned char) *string)) - string++; + char **tokptr; + va_list arglist; + int tokcount = 0; + + va_start(arglist, string); tokptr = va_arg(arglist, char **); - tokcount++; - if (!*string) - break; - *string++ = 0; - } - va_end(arglist); - - return tokcount; + while (tokptr) { + while (*string && isspace((unsigned char)*string)) + string++; + if (!*string) + break; + *tokptr = string; + while (*string && !isspace((unsigned char)*string)) + string++; + tokptr = va_arg(arglist, char **); + tokcount++; + if (!*string) + break; + *string++ = 0; + } + va_end(arglist); + + return tokcount; } static int comparef(const void *key1, const void *key2) { - return strcmp(key1, key2); + return strcmp(key1, key2); } static char *dupstring(char *str) { - int sz = strlen(str) + 1; - char *new = XCALLOC(MTYPE_ISIS_TMP, sz); - if (new) - memcpy(new, str, sz); - return new; + int sz = strlen(str) + 1; + char *new = XCALLOC(MTYPE_ISIS_TMP, sz); + if (new) + memcpy(new, str, sz); + return new; } static dnode_t *new_node(void *c) { - static dnode_t few[5]; - static int count; + static dnode_t few[5]; + static int count; - if (count < 5) - return few + count++; + if (count < 5) + return few + count++; - return NULL; + return NULL; } static void del_node(dnode_t *n, void *c) @@ -1250,238 +1268,239 @@ static int prompt = 0; static void construct(dict_t *d) { - input_t in; - int done = 0; - dict_load_t dl; - dnode_t *dn; - char *tok1, *tok2, *val; - const char *key; - char *help = - "p turn prompt on\n" - "q finish construction\n" - "a add new entry\n"; - - if (!dict_isempty(d)) - puts("warning: dictionary not empty!"); - - dict_load_begin(&dl, d); - - while (!done) { - if (prompt) - putchar('>'); - fflush(stdout); - - if (!fgets(in, sizeof(input_t), stdin)) - break; - - switch (in[0]) { - case '?': - puts(help); - break; - case 'p': - prompt = 1; - break; - case 'q': - done = 1; - break; - case 'a': - if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) { - puts("what?"); - break; - } - key = dupstring(tok1); - val = dupstring(tok2); - dn = dnode_create(val); - - if (!key || !val || !dn) { - puts("out of memory"); - free((void *) key); - free(val); - if (dn) - dnode_destroy(dn); - } + input_t in; + int done = 0; + dict_load_t dl; + dnode_t *dn; + char *tok1, *tok2, *val; + const char *key; + char *help = + "p turn prompt on\n" + "q finish construction\n" + "a add new entry\n"; + + if (!dict_isempty(d)) + puts("warning: dictionary not empty!"); + + dict_load_begin(&dl, d); + + while (!done) { + if (prompt) + putchar('>'); + fflush(stdout); + + if (!fgets(in, sizeof(input_t), stdin)) + break; - dict_load_next(&dl, dn, key); - break; - default: - putchar('?'); - putchar('\n'); - break; + switch (in[0]) { + case '?': + puts(help); + break; + case 'p': + prompt = 1; + break; + case 'q': + done = 1; + break; + case 'a': + if (tokenize(in + 1, &tok1, &tok2, (char **)0) != 2) { + puts("what?"); + break; + } + key = dupstring(tok1); + val = dupstring(tok2); + dn = dnode_create(val); + + if (!key || !val || !dn) { + puts("out of memory"); + free((void *)key); + free(val); + if (dn) + dnode_destroy(dn); + } + + dict_load_next(&dl, dn, key); + break; + default: + putchar('?'); + putchar('\n'); + break; + } } - } - dict_load_end(&dl); + dict_load_end(&dl); } int main(void) { - input_t in; - dict_t darray[10]; - dict_t *d = &darray[0]; - dnode_t *dn; - int i; - char *tok1, *tok2, *val; - const char *key; - - char *help = - "a add value to dictionary\n" - "d delete value from dictionary\n" - "l lookup value in dictionary\n" - "( lookup lower bound\n" - ") lookup upper bound\n" - "# switch to alternate dictionary (0-9)\n" - "j merge two dictionaries\n" - "f free the whole dictionary\n" - "k allow duplicate keys\n" - "c show number of entries\n" - "t dump whole dictionary in sort order\n" - "m make dictionary out of sorted items\n" - "p turn prompt on\n" - "s switch to non-functioning allocator\n" - "q quit"; - - for (i = 0; i < 10; i++) - dict_init(&darray[i], DICTCOUNT_T_MAX, comparef); - - for (;;) { - if (prompt) - putchar('>'); - fflush(stdout); - - if (!fgets(in, sizeof(input_t), stdin)) - break; - - switch(in[0]) { - case '?': - puts(help); - break; - case 'a': - if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) { - puts("what?"); - break; - } - key = dupstring(tok1); - val = dupstring(tok2); - - if (!key || !val) { - puts("out of memory"); - free((void *) key); - free(val); - } + input_t in; + dict_t darray[10]; + dict_t *d = &darray[0]; + dnode_t *dn; + int i; + char *tok1, *tok2, *val; + const char *key; + + char *help = + "a add value to dictionary\n" + "d delete value from dictionary\n" + "l lookup value in dictionary\n" + "( lookup lower bound\n" + ") lookup upper bound\n" + "# switch to alternate dictionary (0-9)\n" + "j merge two dictionaries\n" + "f free the whole dictionary\n" + "k allow duplicate keys\n" + "c show number of entries\n" + "t dump whole dictionary in sort order\n" + "m make dictionary out of sorted items\n" + "p turn prompt on\n" + "s switch to non-functioning allocator\n" + "q quit"; + + for (i = 0; i < 10; i++) + dict_init(&darray[i], DICTCOUNT_T_MAX, comparef); + + for (;;) { + if (prompt) + putchar('>'); + fflush(stdout); + + if (!fgets(in, sizeof(input_t), stdin)) + break; - if (!dict_alloc_insert(d, key, val)) { - puts("dict_alloc_insert failed"); - free((void *) key); - free(val); - break; - } - break; - case 'd': - if (tokenize(in+1, &tok1, (char **) 0) != 1) { - puts("what?"); - break; - } - dn = dict_lookup(d, tok1); - if (!dn) { - puts("dict_lookup failed"); - break; - } - val = dnode_get(dn); - key = dnode_getkey(dn); - dict_delete_free(d, dn); - - free(val); - free((void *) key); - break; - case 'f': - dict_free(d); - break; - case 'l': - case '(': - case ')': - if (tokenize(in+1, &tok1, (char **) 0) != 1) { - puts("what?"); - break; - } - dn = 0; switch (in[0]) { + case '?': + puts(help); + break; + case 'a': + if (tokenize(in + 1, &tok1, &tok2, (char **)0) != 2) { + puts("what?"); + break; + } + key = dupstring(tok1); + val = dupstring(tok2); + + if (!key || !val) { + puts("out of memory"); + free((void *)key); + free(val); + } + + if (!dict_alloc_insert(d, key, val)) { + puts("dict_alloc_insert failed"); + free((void *)key); + free(val); + break; + } + break; + case 'd': + if (tokenize(in + 1, &tok1, (char **)0) != 1) { + puts("what?"); + break; + } + dn = dict_lookup(d, tok1); + if (!dn) { + puts("dict_lookup failed"); + break; + } + val = dnode_get(dn); + key = dnode_getkey(dn); + dict_delete_free(d, dn); + + free(val); + free((void *)key); + break; + case 'f': + dict_free(d); + break; case 'l': - dn = dict_lookup(d, tok1); - break; case '(': - dn = dict_lower_bound(d, tok1); - break; case ')': - dn = dict_upper_bound(d, tok1); - break; - } - if (!dn) { - puts("lookup failed"); - break; - } - val = dnode_get(dn); - puts(val); - break; - case 'm': - construct(d); - break; - case 'k': - dict_allow_dupes(d); - break; - case 'c': - printf("%lu\n", (unsigned long) dict_count(d)); - break; - case 't': - for (dn = dict_first(d); dn; dn = dict_next(d, dn)) { - printf("%s\t%s\n", (char *) dnode_getkey(dn), - (char *) dnode_get(dn)); - } - break; - case 'q': - exit(0); - break; - case '\0': - break; - case 'p': - prompt = 1; - break; - case 's': - dict_set_allocator(d, new_node, del_node, NULL); - break; - case '#': - if (tokenize(in+1, &tok1, (char **) 0) != 1) { - puts("what?"); - break; - } else { - int dictnum = atoi(tok1); - if (dictnum < 0 || dictnum > 9) { - puts("invalid number"); + if (tokenize(in + 1, &tok1, (char **)0) != 1) { + puts("what?"); + break; + } + dn = 0; + switch (in[0]) { + case 'l': + dn = dict_lookup(d, tok1); + break; + case '(': + dn = dict_lower_bound(d, tok1); + break; + case ')': + dn = dict_upper_bound(d, tok1); + break; + } + if (!dn) { + puts("lookup failed"); + break; + } + val = dnode_get(dn); + puts(val); break; - } - d = &darray[dictnum]; - } - break; - case 'j': - if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) { - puts("what?"); - break; - } else { - int dict1 = atoi(tok1), dict2 = atoi(tok2); - if (dict1 < 0 || dict1 > 9 || dict2 < 0 || dict2 > 9) { - puts("invalid number"); + case 'm': + construct(d); + break; + case 'k': + dict_allow_dupes(d); + break; + case 'c': + printf("%lu\n", (unsigned long)dict_count(d)); + break; + case 't': + for (dn = dict_first(d); dn; dn = dict_next(d, dn)) { + printf("%s\t%s\n", (char *)dnode_getkey(dn), + (char *)dnode_get(dn)); + } + break; + case 'q': + exit(0); + break; + case '\0': + break; + case 'p': + prompt = 1; + break; + case 's': + dict_set_allocator(d, new_node, del_node, NULL); + break; + case '#': + if (tokenize(in + 1, &tok1, (char **)0) != 1) { + puts("what?"); + break; + } else { + int dictnum = atoi(tok1); + if (dictnum < 0 || dictnum > 9) { + puts("invalid number"); + break; + } + d = &darray[dictnum]; + } + break; + case 'j': + if (tokenize(in + 1, &tok1, &tok2, (char **)0) != 2) { + puts("what?"); + break; + } else { + int dict1 = atoi(tok1), dict2 = atoi(tok2); + if (dict1 < 0 || dict1 > 9 || dict2 < 0 + || dict2 > 9) { + puts("invalid number"); + break; + } + dict_merge(&darray[dict1], &darray[dict2]); + } + break; + default: + putchar('?'); + putchar('\n'); break; - } - dict_merge(&darray[dict1], &darray[dict2]); } - break; - default: - putchar('?'); - putchar('\n'); - break; } - } - return 0; + return 0; } #endif diff --git a/isisd/dict.h b/isisd/dict.h index 93edb7d60..a5ee92231 100644 --- a/isisd/dict.h +++ b/isisd/dict.h @@ -41,12 +41,12 @@ typedef unsigned long dictcount_t; typedef enum { dnode_red, dnode_black } dnode_color_t; typedef struct dnode_t { - struct dnode_t *dict_left; - struct dnode_t *dict_right; - struct dnode_t *dict_parent; - dnode_color_t dict_color; - const void *dict_key; - void *dict_data; + struct dnode_t *dict_left; + struct dnode_t *dict_right; + struct dnode_t *dict_parent; + dnode_color_t dict_color; + const void *dict_key; + void *dict_data; } dnode_t; typedef int (*dict_comp_t)(const void *, const void *); @@ -54,21 +54,21 @@ typedef dnode_t *(*dnode_alloc_t)(void *); typedef void (*dnode_free_t)(dnode_t *, void *); typedef struct dict_t { - dnode_t dict_nilnode; - dictcount_t dict_nodecount; - dictcount_t dict_maxcount; - dict_comp_t dict_compare; - dnode_alloc_t dict_allocnode; - dnode_free_t dict_freenode; - void *dict_context; - int dict_dupes; + dnode_t dict_nilnode; + dictcount_t dict_nodecount; + dictcount_t dict_maxcount; + dict_comp_t dict_compare; + dnode_alloc_t dict_allocnode; + dnode_free_t dict_freenode; + void *dict_context; + int dict_dupes; } dict_t; typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *); typedef struct dict_load_t { - dict_t *dict_dictptr; - dnode_t dict_nilnode; + dict_t *dict_dictptr; + dnode_t dict_nilnode; } dict_load_t; extern dict_t *dict_create(dictcount_t, dict_comp_t); diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c index e4a4e0c42..d8cb32375 100644 --- a/isisd/isis_adjacency.c +++ b/isisd/isis_adjacency.c @@ -1,19 +1,19 @@ /* - * IS-IS Rout(e)ing protocol - isis_adjacency.c + * IS-IS Rout(e)ing protocol - isis_adjacency.c * handling of IS-IS adjacencies * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -51,512 +51,498 @@ extern struct isis *isis; -static struct isis_adjacency * -adj_alloc (const u_char *id) +static struct isis_adjacency *adj_alloc(const u_char *id) { - struct isis_adjacency *adj; + struct isis_adjacency *adj; - adj = XCALLOC (MTYPE_ISIS_ADJACENCY, sizeof (struct isis_adjacency)); - memcpy (adj->sysid, id, ISIS_SYS_ID_LEN); + adj = XCALLOC(MTYPE_ISIS_ADJACENCY, sizeof(struct isis_adjacency)); + memcpy(adj->sysid, id, ISIS_SYS_ID_LEN); - return adj; + return adj; } -struct isis_adjacency * -isis_new_adj (const u_char * id, const u_char * snpa, int level, - struct isis_circuit *circuit) +struct isis_adjacency *isis_new_adj(const u_char *id, const u_char *snpa, + int level, struct isis_circuit *circuit) { - struct isis_adjacency *adj; - int i; - - adj = adj_alloc (id); /* P2P kludge */ - - if (adj == NULL) - { - zlog_err ("Out of memory!"); - return NULL; - } - - if (snpa) { - memcpy (adj->snpa, snpa, ETH_ALEN); - } else { - memset (adj->snpa, ' ', ETH_ALEN); - } - - adj->circuit = circuit; - adj->level = level; - adj->flaps = 0; - adj->last_flap = time (NULL); - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - { - listnode_add (circuit->u.bc.adjdb[level - 1], adj); - adj->dischanges[level - 1] = 0; - for (i = 0; i < DIS_RECORDS; i++) /* clear N DIS state change records */ - { - adj->dis_record[(i * ISIS_LEVELS) + level - 1].dis - = ISIS_UNKNOWN_DIS; - adj->dis_record[(i * ISIS_LEVELS) + level - 1].last_dis_change - = time (NULL); + struct isis_adjacency *adj; + int i; + + adj = adj_alloc(id); /* P2P kludge */ + + if (adj == NULL) { + zlog_err("Out of memory!"); + return NULL; + } + + if (snpa) { + memcpy(adj->snpa, snpa, ETH_ALEN); + } else { + memset(adj->snpa, ' ', ETH_ALEN); } - } - return adj; + adj->circuit = circuit; + adj->level = level; + adj->flaps = 0; + adj->last_flap = time(NULL); + if (circuit->circ_type == CIRCUIT_T_BROADCAST) { + listnode_add(circuit->u.bc.adjdb[level - 1], adj); + adj->dischanges[level - 1] = 0; + for (i = 0; i < DIS_RECORDS; + i++) /* clear N DIS state change records */ + { + adj->dis_record[(i * ISIS_LEVELS) + level - 1].dis = + ISIS_UNKNOWN_DIS; + adj->dis_record[(i * ISIS_LEVELS) + level - 1] + .last_dis_change = time(NULL); + } + } + + return adj; } -struct isis_adjacency * -isis_adj_lookup (const u_char * sysid, struct list *adjdb) +struct isis_adjacency *isis_adj_lookup(const u_char *sysid, struct list *adjdb) { - struct isis_adjacency *adj; - struct listnode *node; + struct isis_adjacency *adj; + struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (adjdb, node, adj)) - if (memcmp (adj->sysid, sysid, ISIS_SYS_ID_LEN) == 0) - return adj; + for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj)) + if (memcmp(adj->sysid, sysid, ISIS_SYS_ID_LEN) == 0) + return adj; - return NULL; + return NULL; } -struct isis_adjacency * -isis_adj_lookup_snpa (const u_char * ssnpa, struct list *adjdb) +struct isis_adjacency *isis_adj_lookup_snpa(const u_char *ssnpa, + struct list *adjdb) { - struct listnode *node; - struct isis_adjacency *adj; + struct listnode *node; + struct isis_adjacency *adj; - for (ALL_LIST_ELEMENTS_RO (adjdb, node, adj)) - if (memcmp (adj->snpa, ssnpa, ETH_ALEN) == 0) - return adj; + for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj)) + if (memcmp(adj->snpa, ssnpa, ETH_ALEN) == 0) + return adj; - return NULL; + return NULL; } -void -isis_delete_adj (void *arg) +void isis_delete_adj(void *arg) { - struct isis_adjacency *adj = arg; + struct isis_adjacency *adj = arg; - if (!adj) - return; + if (!adj) + return; - THREAD_TIMER_OFF (adj->t_expire); + THREAD_TIMER_OFF(adj->t_expire); - /* remove from SPF trees */ - spftree_area_adj_del (adj->circuit->area, adj); + /* remove from SPF trees */ + spftree_area_adj_del(adj->circuit->area, adj); - if (adj->area_addrs) - list_delete (adj->area_addrs); - if (adj->ipv4_addrs) - list_delete (adj->ipv4_addrs); - if (adj->ipv6_addrs) - list_delete (adj->ipv6_addrs); + if (adj->area_addrs) + list_delete(adj->area_addrs); + if (adj->ipv4_addrs) + list_delete(adj->ipv4_addrs); + if (adj->ipv6_addrs) + list_delete(adj->ipv6_addrs); - adj_mt_finish(adj); + adj_mt_finish(adj); - XFREE (MTYPE_ISIS_ADJACENCY, adj); - return; + XFREE(MTYPE_ISIS_ADJACENCY, adj); + return; } -static const char * -adj_state2string (int state) +static const char *adj_state2string(int state) { - switch (state) - { - case ISIS_ADJ_INITIALIZING: - return "Initializing"; - case ISIS_ADJ_UP: - return "Up"; - case ISIS_ADJ_DOWN: - return "Down"; - default: - return "Unknown"; - } - - return NULL; /* not reached */ + switch (state) { + case ISIS_ADJ_INITIALIZING: + return "Initializing"; + case ISIS_ADJ_UP: + return "Up"; + case ISIS_ADJ_DOWN: + return "Down"; + default: + return "Unknown"; + } + + return NULL; /* not reached */ } -void -isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state new_state, - const char *reason) +void isis_adj_state_change(struct isis_adjacency *adj, + enum isis_adj_state new_state, const char *reason) { - int old_state; - int level; - struct isis_circuit *circuit; - bool del; - - old_state = adj->adj_state; - adj->adj_state = new_state; - - circuit = adj->circuit; - - if (isis->debugs & DEBUG_ADJ_PACKETS) - { - zlog_debug ("ISIS-Adj (%s): Adjacency state change %d->%d: %s", - circuit->area->area_tag, - old_state, new_state, reason ? reason : "unspecified"); - } - - if (circuit->area->log_adj_changes) - { - const char *adj_name; - struct isis_dynhn *dyn; - - dyn = dynhn_find_by_id (adj->sysid); - if (dyn) - adj_name = (const char *)dyn->name.name; - else - adj_name = sysid_print (adj->sysid); - - zlog_info ("%%ADJCHANGE: Adjacency to %s (%s) changed from %s to %s, %s", - adj_name, - adj->circuit->interface->name, - adj_state2string (old_state), - adj_state2string (new_state), - reason ? reason : "unspecified"); - } - - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - { - del = false; - for (level = IS_LEVEL_1; level <= IS_LEVEL_2; level++) - { - if ((adj->level & level) == 0) - continue; - if (new_state == ISIS_ADJ_UP) - { - circuit->upadjcount[level - 1]++; - isis_event_adjacency_state_change (adj, new_state); - /* update counter & timers for debugging purposes */ - adj->last_flap = time (NULL); - adj->flaps++; - } - else if (new_state == ISIS_ADJ_DOWN) - { - listnode_delete (circuit->u.bc.adjdb[level - 1], adj); - circuit->upadjcount[level - 1]--; - if (circuit->upadjcount[level - 1] == 0) - { - /* Clean lsp_queue when no adj is up. */ - if (circuit->lsp_queue) - list_delete_all_node (circuit->lsp_queue); - } - isis_event_adjacency_state_change (adj, new_state); - del = true; - } - - if (circuit->u.bc.lan_neighs[level - 1]) - { - list_delete_all_node (circuit->u.bc.lan_neighs[level - 1]); - isis_adj_build_neigh_list (circuit->u.bc.adjdb[level - 1], - circuit->u.bc.lan_neighs[level - 1]); - } - - /* On adjacency state change send new pseudo LSP if we are the DR */ - if (circuit->u.bc.is_dr[level - 1]) - lsp_regenerate_schedule_pseudo (circuit, level); - } - - if (del) - isis_delete_adj (adj); - - adj = NULL; - } - else if (circuit->circ_type == CIRCUIT_T_P2P) - { - del = false; - for (level = IS_LEVEL_1; level <= IS_LEVEL_2; level++) - { - if ((adj->level & level) == 0) - continue; - if (new_state == ISIS_ADJ_UP) - { - circuit->upadjcount[level - 1]++; - isis_event_adjacency_state_change (adj, new_state); - - if (adj->sys_type == ISIS_SYSTYPE_UNKNOWN) - send_hello (circuit, level); - - /* update counter & timers for debugging purposes */ - adj->last_flap = time (NULL); - adj->flaps++; - - /* 7.3.17 - going up on P2P -> send CSNP */ - /* FIXME: yup, I know its wrong... but i will do it! (for now) */ - send_csnp (circuit, level); - } - else if (new_state == ISIS_ADJ_DOWN) - { - if (adj->circuit->u.p2p.neighbor == adj) - adj->circuit->u.p2p.neighbor = NULL; - circuit->upadjcount[level - 1]--; - if (circuit->upadjcount[level - 1] == 0) - { - /* Clean lsp_queue when no adj is up. */ - if (circuit->lsp_queue) - list_delete_all_node (circuit->lsp_queue); - } - isis_event_adjacency_state_change (adj, new_state); - del = true; - } - } - - if (del) - isis_delete_adj (adj); - - adj = NULL; - } - - return; + int old_state; + int level; + struct isis_circuit *circuit; + bool del; + + old_state = adj->adj_state; + adj->adj_state = new_state; + + circuit = adj->circuit; + + if (isis->debugs & DEBUG_ADJ_PACKETS) { + zlog_debug("ISIS-Adj (%s): Adjacency state change %d->%d: %s", + circuit->area->area_tag, old_state, new_state, + reason ? reason : "unspecified"); + } + + if (circuit->area->log_adj_changes) { + const char *adj_name; + struct isis_dynhn *dyn; + + dyn = dynhn_find_by_id(adj->sysid); + if (dyn) + adj_name = (const char *)dyn->name.name; + else + adj_name = sysid_print(adj->sysid); + + zlog_info( + "%%ADJCHANGE: Adjacency to %s (%s) changed from %s to %s, %s", + adj_name, adj->circuit->interface->name, + adj_state2string(old_state), + adj_state2string(new_state), + reason ? reason : "unspecified"); + } + + if (circuit->circ_type == CIRCUIT_T_BROADCAST) { + del = false; + for (level = IS_LEVEL_1; level <= IS_LEVEL_2; level++) { + if ((adj->level & level) == 0) + continue; + if (new_state == ISIS_ADJ_UP) { + circuit->upadjcount[level - 1]++; + isis_event_adjacency_state_change(adj, + new_state); + /* update counter & timers for debugging + * purposes */ + adj->last_flap = time(NULL); + adj->flaps++; + } else if (new_state == ISIS_ADJ_DOWN) { + listnode_delete(circuit->u.bc.adjdb[level - 1], + adj); + circuit->upadjcount[level - 1]--; + if (circuit->upadjcount[level - 1] == 0) { + /* Clean lsp_queue when no adj is up. */ + if (circuit->lsp_queue) + list_delete_all_node( + circuit->lsp_queue); + } + isis_event_adjacency_state_change(adj, + new_state); + del = true; + } + + if (circuit->u.bc.lan_neighs[level - 1]) { + list_delete_all_node( + circuit->u.bc.lan_neighs[level - 1]); + isis_adj_build_neigh_list( + circuit->u.bc.adjdb[level - 1], + circuit->u.bc.lan_neighs[level - 1]); + } + + /* On adjacency state change send new pseudo LSP if we + * are the DR */ + if (circuit->u.bc.is_dr[level - 1]) + lsp_regenerate_schedule_pseudo(circuit, level); + } + + if (del) + isis_delete_adj(adj); + + adj = NULL; + } else if (circuit->circ_type == CIRCUIT_T_P2P) { + del = false; + for (level = IS_LEVEL_1; level <= IS_LEVEL_2; level++) { + if ((adj->level & level) == 0) + continue; + if (new_state == ISIS_ADJ_UP) { + circuit->upadjcount[level - 1]++; + isis_event_adjacency_state_change(adj, + new_state); + + if (adj->sys_type == ISIS_SYSTYPE_UNKNOWN) + send_hello(circuit, level); + + /* update counter & timers for debugging + * purposes */ + adj->last_flap = time(NULL); + adj->flaps++; + + /* 7.3.17 - going up on P2P -> send CSNP */ + /* FIXME: yup, I know its wrong... but i will do + * it! (for now) */ + send_csnp(circuit, level); + } else if (new_state == ISIS_ADJ_DOWN) { + if (adj->circuit->u.p2p.neighbor == adj) + adj->circuit->u.p2p.neighbor = NULL; + circuit->upadjcount[level - 1]--; + if (circuit->upadjcount[level - 1] == 0) { + /* Clean lsp_queue when no adj is up. */ + if (circuit->lsp_queue) + list_delete_all_node( + circuit->lsp_queue); + } + isis_event_adjacency_state_change(adj, + new_state); + del = true; + } + } + + if (del) + isis_delete_adj(adj); + + adj = NULL; + } + + return; } -void -isis_adj_print (struct isis_adjacency *adj) +void isis_adj_print(struct isis_adjacency *adj) { - struct isis_dynhn *dyn; - struct listnode *node; - struct in_addr *ipv4_addr; - struct in6_addr *ipv6_addr; - u_char ip6[INET6_ADDRSTRLEN]; - - if (!adj) - return; - dyn = dynhn_find_by_id (adj->sysid); - if (dyn) - zlog_debug ("%s", dyn->name.name); - - zlog_debug ("SystemId %20s SNPA %s, level %d\nHolding Time %d", - sysid_print (adj->sysid), snpa_print (adj->snpa), - adj->level, adj->hold_time); - if (adj->ipv4_addrs && listcount (adj->ipv4_addrs) > 0) - { - zlog_debug ("IPv4 Address(es):"); - - for (ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ipv4_addr)) - zlog_debug ("%s", inet_ntoa (*ipv4_addr)); - } - - if (adj->ipv6_addrs && listcount (adj->ipv6_addrs) > 0) - { - zlog_debug ("IPv6 Address(es):"); - for (ALL_LIST_ELEMENTS_RO (adj->ipv6_addrs, node, ipv6_addr)) - { - inet_ntop (AF_INET6, ipv6_addr, (char *)ip6, INET6_ADDRSTRLEN); - zlog_debug ("%s", ip6); + struct isis_dynhn *dyn; + struct listnode *node; + struct in_addr *ipv4_addr; + struct in6_addr *ipv6_addr; + u_char ip6[INET6_ADDRSTRLEN]; + + if (!adj) + return; + dyn = dynhn_find_by_id(adj->sysid); + if (dyn) + zlog_debug("%s", dyn->name.name); + + zlog_debug("SystemId %20s SNPA %s, level %d\nHolding Time %d", + sysid_print(adj->sysid), snpa_print(adj->snpa), adj->level, + adj->hold_time); + if (adj->ipv4_addrs && listcount(adj->ipv4_addrs) > 0) { + zlog_debug("IPv4 Address(es):"); + + for (ALL_LIST_ELEMENTS_RO(adj->ipv4_addrs, node, ipv4_addr)) + zlog_debug("%s", inet_ntoa(*ipv4_addr)); + } + + if (adj->ipv6_addrs && listcount(adj->ipv6_addrs) > 0) { + zlog_debug("IPv6 Address(es):"); + for (ALL_LIST_ELEMENTS_RO(adj->ipv6_addrs, node, ipv6_addr)) { + inet_ntop(AF_INET6, ipv6_addr, (char *)ip6, + INET6_ADDRSTRLEN); + zlog_debug("%s", ip6); + } } - } - zlog_debug ("Speaks: %s", nlpid2string (&adj->nlpids)); + zlog_debug("Speaks: %s", nlpid2string(&adj->nlpids)); - return; + return; } -int -isis_adj_expire (struct thread *thread) +int isis_adj_expire(struct thread *thread) { - struct isis_adjacency *adj; + struct isis_adjacency *adj; - /* - * Get the adjacency - */ - adj = THREAD_ARG (thread); - assert (adj); - adj->t_expire = NULL; + /* + * Get the adjacency + */ + adj = THREAD_ARG(thread); + assert(adj); + adj->t_expire = NULL; - /* trigger the adj expire event */ - isis_adj_state_change (adj, ISIS_ADJ_DOWN, "holding time expired"); + /* trigger the adj expire event */ + isis_adj_state_change(adj, ISIS_ADJ_DOWN, "holding time expired"); - return 0; + return 0; } /* * show isis neighbor [detail] */ -void -isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty, char detail) +void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty, + char detail) { - struct in6_addr *ipv6_addr; - u_char ip6[INET6_ADDRSTRLEN]; - struct in_addr *ip_addr; - time_t now; - struct isis_dynhn *dyn; - int level; - struct listnode *node; - - dyn = dynhn_find_by_id (adj->sysid); - if (dyn) - vty_out (vty, " %-20s", dyn->name.name); - else - vty_out (vty, " %-20s", sysid_print (adj->sysid)); - - if (detail == ISIS_UI_LEVEL_BRIEF) - { - if (adj->circuit) - vty_out (vty, "%-12s", adj->circuit->interface->name); - else - vty_out (vty, "NULL circuit!"); - vty_out (vty, "%-3u", adj->level); /* level */ - vty_out (vty, "%-13s", adj_state2string (adj->adj_state)); - now = time (NULL); - if (adj->last_upd) - vty_out (vty, "%-9llu", - (unsigned long long)adj->last_upd + adj->hold_time - now); - else - vty_out (vty, "- "); - vty_out (vty, "%-10s", snpa_print (adj->snpa)); - vty_out (vty, "\n"); - } - - if (detail == ISIS_UI_LEVEL_DETAIL) - { - level = adj->level; - vty_out (vty, "\n"); - if (adj->circuit) - vty_out (vty, " Interface: %s", adj->circuit->interface->name); - else - vty_out (vty, " Interface: NULL circuit"); - vty_out (vty, ", Level: %u", adj->level); /* level */ - vty_out (vty, ", State: %s", adj_state2string (adj->adj_state)); - now = time (NULL); - if (adj->last_upd) - vty_out (vty, ", Expires in %s", - time2string (adj->last_upd + adj->hold_time - now)); - else - vty_out (vty, ", Expires in %s", time2string (adj->hold_time)); - vty_out (vty, "\n"); - vty_out (vty, " Adjacency flaps: %u", adj->flaps); - vty_out (vty, ", Last: %s ago", time2string (now - adj->last_flap)); - vty_out (vty, "\n"); - vty_out (vty, " Circuit type: %s", circuit_t2string (adj->circuit_t)); - vty_out (vty, ", Speaks: %s", nlpid2string (&adj->nlpids)); - vty_out (vty, "\n"); - if (adj->mt_count != 1 || adj->mt_set[0] != ISIS_MT_IPV4_UNICAST) - { - vty_out (vty, " Topologies:\n"); - for (unsigned int i = 0; i < adj->mt_count; i++) - vty_out (vty, " %s\n", isis_mtid2str(adj->mt_set[i])); - } - vty_out (vty, " SNPA: %s", snpa_print (adj->snpa)); - if (adj->circuit && (adj->circuit->circ_type == CIRCUIT_T_BROADCAST)) - { - dyn = dynhn_find_by_id (adj->lanid); - if (dyn) - vty_out (vty, ", LAN id: %s.%02x", - dyn->name.name, adj->lanid[ISIS_SYS_ID_LEN]); - else - vty_out (vty, ", LAN id: %s.%02x", - sysid_print (adj->lanid), adj->lanid[ISIS_SYS_ID_LEN]); - - vty_out (vty, "\n"); - vty_out (vty, " LAN Priority: %u", adj->prio[adj->level - 1]); - - vty_out (vty, ", %s, DIS flaps: %u, Last: %s ago", - isis_disflag2string (adj->dis_record[ISIS_LEVELS + level - 1]. - dis), adj->dischanges[level - 1], - time2string (now - - (adj->dis_record[ISIS_LEVELS + level - 1]. - last_dis_change))); - } - vty_out (vty, "\n"); - - if (adj->area_addrs && listcount (adj->area_addrs) > 0) - { - struct area_addr *area_addr; - vty_out (vty, " Area Address(es):\n"); - for (ALL_LIST_ELEMENTS_RO (adj->area_addrs, node, area_addr)) - vty_out (vty, " %s\n", - isonet_print(area_addr->area_addr, area_addr->addr_len)); - } - if (adj->ipv4_addrs && listcount (adj->ipv4_addrs) > 0) - { - vty_out (vty, " IPv4 Address(es):\n"); - for (ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ip_addr)) - vty_out (vty, " %s\n", inet_ntoa(*ip_addr)); + struct in6_addr *ipv6_addr; + u_char ip6[INET6_ADDRSTRLEN]; + struct in_addr *ip_addr; + time_t now; + struct isis_dynhn *dyn; + int level; + struct listnode *node; + + dyn = dynhn_find_by_id(adj->sysid); + if (dyn) + vty_out(vty, " %-20s", dyn->name.name); + else + vty_out(vty, " %-20s", sysid_print(adj->sysid)); + + if (detail == ISIS_UI_LEVEL_BRIEF) { + if (adj->circuit) + vty_out(vty, "%-12s", adj->circuit->interface->name); + else + vty_out(vty, "NULL circuit!"); + vty_out(vty, "%-3u", adj->level); /* level */ + vty_out(vty, "%-13s", adj_state2string(adj->adj_state)); + now = time(NULL); + if (adj->last_upd) + vty_out(vty, "%-9llu", + (unsigned long long)adj->last_upd + + adj->hold_time - now); + else + vty_out(vty, "- "); + vty_out(vty, "%-10s", snpa_print(adj->snpa)); + vty_out(vty, "\n"); } - if (adj->ipv6_addrs && listcount (adj->ipv6_addrs) > 0) - { - vty_out (vty, " IPv6 Address(es):\n"); - for (ALL_LIST_ELEMENTS_RO (adj->ipv6_addrs, node, ipv6_addr)) - { - inet_ntop (AF_INET6, ipv6_addr, (char *)ip6, INET6_ADDRSTRLEN); - vty_out (vty, " %s\n", ip6); - } + + if (detail == ISIS_UI_LEVEL_DETAIL) { + level = adj->level; + vty_out(vty, "\n"); + if (adj->circuit) + vty_out(vty, " Interface: %s", + adj->circuit->interface->name); + else + vty_out(vty, " Interface: NULL circuit"); + vty_out(vty, ", Level: %u", adj->level); /* level */ + vty_out(vty, ", State: %s", adj_state2string(adj->adj_state)); + now = time(NULL); + if (adj->last_upd) + vty_out(vty, ", Expires in %s", + time2string(adj->last_upd + adj->hold_time + - now)); + else + vty_out(vty, ", Expires in %s", + time2string(adj->hold_time)); + vty_out(vty, "\n"); + vty_out(vty, " Adjacency flaps: %u", adj->flaps); + vty_out(vty, ", Last: %s ago", + time2string(now - adj->last_flap)); + vty_out(vty, "\n"); + vty_out(vty, " Circuit type: %s", + circuit_t2string(adj->circuit_t)); + vty_out(vty, ", Speaks: %s", nlpid2string(&adj->nlpids)); + vty_out(vty, "\n"); + if (adj->mt_count != 1 + || adj->mt_set[0] != ISIS_MT_IPV4_UNICAST) { + vty_out(vty, " Topologies:\n"); + for (unsigned int i = 0; i < adj->mt_count; i++) + vty_out(vty, " %s\n", + isis_mtid2str(adj->mt_set[i])); + } + vty_out(vty, " SNPA: %s", snpa_print(adj->snpa)); + if (adj->circuit + && (adj->circuit->circ_type == CIRCUIT_T_BROADCAST)) { + dyn = dynhn_find_by_id(adj->lanid); + if (dyn) + vty_out(vty, ", LAN id: %s.%02x", + dyn->name.name, + adj->lanid[ISIS_SYS_ID_LEN]); + else + vty_out(vty, ", LAN id: %s.%02x", + sysid_print(adj->lanid), + adj->lanid[ISIS_SYS_ID_LEN]); + + vty_out(vty, "\n"); + vty_out(vty, " LAN Priority: %u", + adj->prio[adj->level - 1]); + + vty_out(vty, ", %s, DIS flaps: %u, Last: %s ago", + isis_disflag2string( + adj->dis_record[ISIS_LEVELS + level - 1] + .dis), + adj->dischanges[level - 1], + time2string(now - (adj->dis_record[ISIS_LEVELS + + level - 1] + .last_dis_change))); + } + vty_out(vty, "\n"); + + if (adj->area_addrs && listcount(adj->area_addrs) > 0) { + struct area_addr *area_addr; + vty_out(vty, " Area Address(es):\n"); + for (ALL_LIST_ELEMENTS_RO(adj->area_addrs, node, + area_addr)) + vty_out(vty, " %s\n", + isonet_print(area_addr->area_addr, + area_addr->addr_len)); + } + if (adj->ipv4_addrs && listcount(adj->ipv4_addrs) > 0) { + vty_out(vty, " IPv4 Address(es):\n"); + for (ALL_LIST_ELEMENTS_RO(adj->ipv4_addrs, node, + ip_addr)) + vty_out(vty, " %s\n", inet_ntoa(*ip_addr)); + } + if (adj->ipv6_addrs && listcount(adj->ipv6_addrs) > 0) { + vty_out(vty, " IPv6 Address(es):\n"); + for (ALL_LIST_ELEMENTS_RO(adj->ipv6_addrs, node, + ipv6_addr)) { + inet_ntop(AF_INET6, ipv6_addr, (char *)ip6, + INET6_ADDRSTRLEN); + vty_out(vty, " %s\n", ip6); + } + } + vty_out(vty, "\n"); } - vty_out (vty, "\n"); - } - return; + return; } -void -isis_adj_build_neigh_list (struct list *adjdb, struct list *list) +void isis_adj_build_neigh_list(struct list *adjdb, struct list *list) { - struct isis_adjacency *adj; - struct listnode *node; - - if (!list) - { - zlog_warn ("isis_adj_build_neigh_list(): NULL list"); - return; - } - - for (ALL_LIST_ELEMENTS_RO (adjdb, node, adj)) - { - if (!adj) - { - zlog_warn ("isis_adj_build_neigh_list(): NULL adj"); - return; + struct isis_adjacency *adj; + struct listnode *node; + + if (!list) { + zlog_warn("isis_adj_build_neigh_list(): NULL list"); + return; } - if ((adj->adj_state == ISIS_ADJ_UP || - adj->adj_state == ISIS_ADJ_INITIALIZING)) - listnode_add (list, adj->snpa); - } - return; + for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj)) { + if (!adj) { + zlog_warn("isis_adj_build_neigh_list(): NULL adj"); + return; + } + + if ((adj->adj_state == ISIS_ADJ_UP + || adj->adj_state == ISIS_ADJ_INITIALIZING)) + listnode_add(list, adj->snpa); + } + return; } -void -isis_adj_build_up_list (struct list *adjdb, struct list *list) +void isis_adj_build_up_list(struct list *adjdb, struct list *list) { - struct isis_adjacency *adj; - struct listnode *node; - - if (adjdb == NULL) { - zlog_warn ("isis_adj_build_up_list(): adjacency DB is empty"); - return; - } - - if (!list) - { - zlog_warn ("isis_adj_build_up_list(): NULL list"); - return; - } - - for (ALL_LIST_ELEMENTS_RO (adjdb, node, adj)) - { - if (!adj) - { - zlog_warn ("isis_adj_build_up_list(): NULL adj"); - return; + struct isis_adjacency *adj; + struct listnode *node; + + if (adjdb == NULL) { + zlog_warn("isis_adj_build_up_list(): adjacency DB is empty"); + return; + } + + if (!list) { + zlog_warn("isis_adj_build_up_list(): NULL list"); + return; } - if (adj->adj_state == ISIS_ADJ_UP) - listnode_add (list, adj); - } + for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj)) { + if (!adj) { + zlog_warn("isis_adj_build_up_list(): NULL adj"); + return; + } - return; + if (adj->adj_state == ISIS_ADJ_UP) + listnode_add(list, adj); + } + + return; } -int -isis_adj_usage2levels(enum isis_adj_usage usage) +int isis_adj_usage2levels(enum isis_adj_usage usage) { - switch (usage) - { - case ISIS_ADJ_LEVEL1: - return IS_LEVEL_1; - case ISIS_ADJ_LEVEL2: - return IS_LEVEL_2; - case ISIS_ADJ_LEVEL1AND2: - return IS_LEVEL_1 | IS_LEVEL_2; - default: - break; - } - return 0; + switch (usage) { + case ISIS_ADJ_LEVEL1: + return IS_LEVEL_1; + case ISIS_ADJ_LEVEL2: + return IS_LEVEL_2; + case ISIS_ADJ_LEVEL1AND2: + return IS_LEVEL_1 | IS_LEVEL_2; + default: + break; + } + return 0; } diff --git a/isisd/isis_adjacency.h b/isisd/isis_adjacency.h index a81797bb1..9f4af1b45 100644 --- a/isisd/isis_adjacency.h +++ b/isisd/isis_adjacency.h @@ -1,20 +1,20 @@ /* - * IS-IS Rout(e)ing protocol - isis_adjacency.h + * IS-IS Rout(e)ing protocol - isis_adjacency.h * IS-IS adjacency handling * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -25,95 +25,90 @@ #ifndef _ZEBRA_ISIS_ADJACENCY_H #define _ZEBRA_ISIS_ADJACENCY_H -enum isis_adj_usage -{ - ISIS_ADJ_NONE, - ISIS_ADJ_LEVEL1, - ISIS_ADJ_LEVEL2, - ISIS_ADJ_LEVEL1AND2 +enum isis_adj_usage { + ISIS_ADJ_NONE, + ISIS_ADJ_LEVEL1, + ISIS_ADJ_LEVEL2, + ISIS_ADJ_LEVEL1AND2 }; -enum isis_system_type -{ - ISIS_SYSTYPE_UNKNOWN, - ISIS_SYSTYPE_ES, - ISIS_SYSTYPE_IS, - ISIS_SYSTYPE_L1_IS, - ISIS_SYSTYPE_L2_IS +enum isis_system_type { + ISIS_SYSTYPE_UNKNOWN, + ISIS_SYSTYPE_ES, + ISIS_SYSTYPE_IS, + ISIS_SYSTYPE_L1_IS, + ISIS_SYSTYPE_L2_IS }; -enum isis_adj_state -{ - ISIS_ADJ_UNKNOWN, - ISIS_ADJ_INITIALIZING, - ISIS_ADJ_UP, - ISIS_ADJ_DOWN +enum isis_adj_state { + ISIS_ADJ_UNKNOWN, + ISIS_ADJ_INITIALIZING, + ISIS_ADJ_UP, + ISIS_ADJ_DOWN }; /* * we use the following codes to give an indication _why_ * a specific adjacency is up or down */ -enum isis_adj_updown_reason -{ - ISIS_ADJ_REASON_SEENSELF, - ISIS_ADJ_REASON_AREA_MISMATCH, - ISIS_ADJ_REASON_HOLDTIMER_EXPIRED, - ISIS_ADJ_REASON_AUTH_FAILED, - ISIS_ADJ_REASON_CHECKSUM_FAILED +enum isis_adj_updown_reason { + ISIS_ADJ_REASON_SEENSELF, + ISIS_ADJ_REASON_AREA_MISMATCH, + ISIS_ADJ_REASON_HOLDTIMER_EXPIRED, + ISIS_ADJ_REASON_AUTH_FAILED, + ISIS_ADJ_REASON_CHECKSUM_FAILED }; #define DIS_RECORDS 8 /* keep the last 8 DIS state changes on record */ -struct isis_dis_record -{ - int dis; /* is our neighbor the DIS ? */ - time_t last_dis_change; /* timestamp for last dis change */ +struct isis_dis_record { + int dis; /* is our neighbor the DIS ? */ + time_t last_dis_change; /* timestamp for last dis change */ }; -struct isis_adjacency -{ - u_char snpa[ETH_ALEN]; /* NeighbourSNPAAddress */ - u_char sysid[ISIS_SYS_ID_LEN]; /* neighbourSystemIdentifier */ - u_char lanid[ISIS_SYS_ID_LEN + 1]; /* LAN id on bcast circuits */ - int dischanges[ISIS_LEVELS]; /* how many DIS changes ? */ - /* an array of N levels for M records */ - struct isis_dis_record dis_record[DIS_RECORDS * ISIS_LEVELS]; - enum isis_adj_state adj_state; /* adjacencyState */ - enum isis_adj_usage adj_usage; /* adjacencyUsage */ - struct list *area_addrs; /* areaAdressesOfNeighbour */ - struct nlpids nlpids; /* protocols spoken ... */ - struct list *ipv4_addrs; - struct in_addr router_address; - struct list *ipv6_addrs; - struct in6_addr router_address6; - u_char prio[ISIS_LEVELS]; /* priorityOfNeighbour for DIS */ - int circuit_t; /* from hello PDU hdr */ - int level; /* level (1 or 2) */ - enum isis_system_type sys_type; /* neighbourSystemType */ - u_int16_t hold_time; /* entryRemainingTime */ - u_int32_t last_upd; - u_int32_t last_flap; /* last time the adj flapped */ - int flaps; /* number of adjacency flaps */ - struct thread *t_expire; /* expire after hold_time */ - struct isis_circuit *circuit; /* back pointer */ - uint16_t *mt_set; /* Topologies this adjacency is valid for */ - unsigned int mt_count; /* Number of entries in mt_set */ +struct isis_adjacency { + u_char snpa[ETH_ALEN]; /* NeighbourSNPAAddress */ + u_char sysid[ISIS_SYS_ID_LEN]; /* neighbourSystemIdentifier */ + u_char lanid[ISIS_SYS_ID_LEN + 1]; /* LAN id on bcast circuits */ + int dischanges[ISIS_LEVELS]; /* how many DIS changes ? */ + /* an array of N levels for M records */ + struct isis_dis_record dis_record[DIS_RECORDS * ISIS_LEVELS]; + enum isis_adj_state adj_state; /* adjacencyState */ + enum isis_adj_usage adj_usage; /* adjacencyUsage */ + struct list *area_addrs; /* areaAdressesOfNeighbour */ + struct nlpids nlpids; /* protocols spoken ... */ + struct list *ipv4_addrs; + struct in_addr router_address; + struct list *ipv6_addrs; + struct in6_addr router_address6; + u_char prio[ISIS_LEVELS]; /* priorityOfNeighbour for DIS */ + int circuit_t; /* from hello PDU hdr */ + int level; /* level (1 or 2) */ + enum isis_system_type sys_type; /* neighbourSystemType */ + u_int16_t hold_time; /* entryRemainingTime */ + u_int32_t last_upd; + u_int32_t last_flap; /* last time the adj flapped */ + int flaps; /* number of adjacency flaps */ + struct thread *t_expire; /* expire after hold_time */ + struct isis_circuit *circuit; /* back pointer */ + uint16_t *mt_set; /* Topologies this adjacency is valid for */ + unsigned int mt_count; /* Number of entries in mt_set */ }; -struct isis_adjacency *isis_adj_lookup (const u_char * sysid, struct list *adjdb); -struct isis_adjacency *isis_adj_lookup_snpa (const u_char * ssnpa, - struct list *adjdb); -struct isis_adjacency *isis_new_adj (const u_char * id, const u_char * snpa, int level, - struct isis_circuit *circuit); -void isis_delete_adj (void *adj); -void isis_adj_state_change (struct isis_adjacency *adj, - enum isis_adj_state state, const char *reason); -void isis_adj_print (struct isis_adjacency *adj); -int isis_adj_expire (struct thread *thread); -void isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty, char detail); -void isis_adj_build_neigh_list (struct list *adjdb, struct list *list); -void isis_adj_build_up_list (struct list *adjdb, struct list *list); +struct isis_adjacency *isis_adj_lookup(const u_char *sysid, struct list *adjdb); +struct isis_adjacency *isis_adj_lookup_snpa(const u_char *ssnpa, + struct list *adjdb); +struct isis_adjacency *isis_new_adj(const u_char *id, const u_char *snpa, + int level, struct isis_circuit *circuit); +void isis_delete_adj(void *adj); +void isis_adj_state_change(struct isis_adjacency *adj, + enum isis_adj_state state, const char *reason); +void isis_adj_print(struct isis_adjacency *adj); +int isis_adj_expire(struct thread *thread); +void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty, + char detail); +void isis_adj_build_neigh_list(struct list *adjdb, struct list *list); +void isis_adj_build_up_list(struct list *adjdb, struct list *list); int isis_adj_usage2levels(enum isis_adj_usage usage); #endif /* ISIS_ADJACENCY_H */ diff --git a/isisd/isis_bpf.c b/isisd/isis_bpf.c index 4ebaa4a1e..69c2f941f 100644 --- a/isisd/isis_bpf.c +++ b/isisd/isis_bpf.c @@ -2,17 +2,17 @@ * IS-IS Rout(e)ing protocol - isis_bpf.c * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -48,15 +48,16 @@ extern struct zebra_privs_t isisd_privs; struct bpf_insn llcfilter[] = { - BPF_STMT (BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN), /* check first byte */ - BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 5), - BPF_STMT (BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 1), - BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 3), /* check second byte */ - BPF_STMT (BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 2), - BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0x03, 0, 1), /* check third byte */ - BPF_STMT (BPF_RET + BPF_K, (u_int) - 1), - BPF_STMT (BPF_RET + BPF_K, 0) -}; + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, + ETHER_HDR_LEN), /* check first byte */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 5), + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 1), + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, + 3), /* check second byte */ + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 2), + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x03, 0, 1), /* check third byte */ + BPF_STMT(BPF_RET + BPF_K, (u_int)-1), + BPF_STMT(BPF_RET + BPF_K, 0)}; u_int readblen = 0; u_char *readbuff = NULL; @@ -65,272 +66,250 @@ u_char *readbuff = NULL; * ISO 10589 - 8.4.8 */ -u_char ALL_L1_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x14 }; -u_char ALL_L2_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x15 }; -u_char ALL_ISS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x05 }; -u_char ALL_ESS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x04 }; +u_char ALL_L1_ISS[6] = {0x01, 0x80, 0xC2, 0x00, 0x00, 0x14}; +u_char ALL_L2_ISS[6] = {0x01, 0x80, 0xC2, 0x00, 0x00, 0x15}; +u_char ALL_ISS[6] = {0x09, 0x00, 0x2B, 0x00, 0x00, 0x05}; +u_char ALL_ESS[6] = {0x09, 0x00, 0x2B, 0x00, 0x00, 0x04}; static char sock_buff[8192]; -static int -open_bpf_dev (struct isis_circuit *circuit) +static int open_bpf_dev(struct isis_circuit *circuit) { - int i = 0, fd; - char bpfdev[128]; - struct ifreq ifr; - u_int blen, immediate; + int i = 0, fd; + char bpfdev[128]; + struct ifreq ifr; + u_int blen, immediate; #ifdef BIOCSSEESENT - u_int seesent; + u_int seesent; #endif - struct timeval timeout; - struct bpf_program bpf_prog; - - do - { - (void) snprintf (bpfdev, sizeof (bpfdev), "/dev/bpf%d", i++); - fd = open (bpfdev, O_RDWR); - } - while (fd < 0 && errno == EBUSY); - - if (fd < 0) - { - zlog_warn ("open_bpf_dev(): failed to create bpf socket: %s", - safe_strerror (errno)); - return ISIS_WARNING; - } - - zlog_debug ("Opened BPF device %s", bpfdev); - - memcpy (ifr.ifr_name, circuit->interface->name, sizeof (ifr.ifr_name)); - if (ioctl (fd, BIOCSETIF, (caddr_t) & ifr) < 0) - { - zlog_warn ("open_bpf_dev(): failed to bind to interface: %s", - safe_strerror (errno)); - return ISIS_WARNING; - } - - if (ioctl (fd, BIOCGBLEN, (caddr_t) & blen) < 0) - { - zlog_warn ("failed to get BPF buffer len"); - blen = circuit->interface->mtu; - } - - readblen = blen; - - if (readbuff == NULL) - readbuff = malloc (blen); - - zlog_debug ("BPF buffer len = %u", blen); - - /* BPF(4): reads return immediately upon packet reception. - * Otherwise, a read will block until either the kernel - * buffer becomes full or a timeout occurs. - */ - immediate = 1; - if (ioctl (fd, BIOCIMMEDIATE, (caddr_t) & immediate) < 0) - { - zlog_warn ("failed to set BPF dev to immediate mode"); - } + struct timeval timeout; + struct bpf_program bpf_prog; + + do { + (void)snprintf(bpfdev, sizeof(bpfdev), "/dev/bpf%d", i++); + fd = open(bpfdev, O_RDWR); + } while (fd < 0 && errno == EBUSY); + + if (fd < 0) { + zlog_warn("open_bpf_dev(): failed to create bpf socket: %s", + safe_strerror(errno)); + return ISIS_WARNING; + } + + zlog_debug("Opened BPF device %s", bpfdev); + + memcpy(ifr.ifr_name, circuit->interface->name, sizeof(ifr.ifr_name)); + if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) { + zlog_warn("open_bpf_dev(): failed to bind to interface: %s", + safe_strerror(errno)); + return ISIS_WARNING; + } + + if (ioctl(fd, BIOCGBLEN, (caddr_t)&blen) < 0) { + zlog_warn("failed to get BPF buffer len"); + blen = circuit->interface->mtu; + } + + readblen = blen; + + if (readbuff == NULL) + readbuff = malloc(blen); + + zlog_debug("BPF buffer len = %u", blen); + + /* BPF(4): reads return immediately upon packet reception. + * Otherwise, a read will block until either the kernel + * buffer becomes full or a timeout occurs. + */ + immediate = 1; + if (ioctl(fd, BIOCIMMEDIATE, (caddr_t)&immediate) < 0) { + zlog_warn("failed to set BPF dev to immediate mode"); + } #ifdef BIOCSSEESENT - /* - * We want to see only incoming packets - */ - seesent = 0; - if (ioctl (fd, BIOCSSEESENT, (caddr_t) & seesent) < 0) - { - zlog_warn ("failed to set BPF dev to incoming only mode"); - } + /* + * We want to see only incoming packets + */ + seesent = 0; + if (ioctl(fd, BIOCSSEESENT, (caddr_t)&seesent) < 0) { + zlog_warn("failed to set BPF dev to incoming only mode"); + } #endif - /* - * ...but all of them - */ - if (ioctl (fd, BIOCPROMISC) < 0) - { - zlog_warn ("failed to set BPF dev to promiscuous mode"); - } - - /* - * If the buffer length is smaller than our mtu, lets try to increase it - */ - if (blen < circuit->interface->mtu) - { - if (ioctl (fd, BIOCSBLEN, &circuit->interface->mtu) < 0) - { - zlog_warn ("failed to set BPF buffer len (%u to %u)", blen, - circuit->interface->mtu); + /* + * ...but all of them + */ + if (ioctl(fd, BIOCPROMISC) < 0) { + zlog_warn("failed to set BPF dev to promiscuous mode"); + } + + /* + * If the buffer length is smaller than our mtu, lets try to increase it + */ + if (blen < circuit->interface->mtu) { + if (ioctl(fd, BIOCSBLEN, &circuit->interface->mtu) < 0) { + zlog_warn("failed to set BPF buffer len (%u to %u)", + blen, circuit->interface->mtu); + } + } + + /* + * Set a timeout parameter - hope this helps select() + */ + timeout.tv_sec = 600; + timeout.tv_usec = 0; + if (ioctl(fd, BIOCSRTIMEOUT, (caddr_t)&timeout) < 0) { + zlog_warn("failed to set BPF device timeout"); + } + + /* + * And set the filter + */ + memset(&bpf_prog, 0, sizeof(struct bpf_program)); + bpf_prog.bf_len = 8; + bpf_prog.bf_insns = &(llcfilter[0]); + if (ioctl(fd, BIOCSETF, (caddr_t)&bpf_prog) < 0) { + zlog_warn("open_bpf_dev(): failed to install filter: %s", + safe_strerror(errno)); + return ISIS_WARNING; } - } - - /* - * Set a timeout parameter - hope this helps select() - */ - timeout.tv_sec = 600; - timeout.tv_usec = 0; - if (ioctl (fd, BIOCSRTIMEOUT, (caddr_t) & timeout) < 0) - { - zlog_warn ("failed to set BPF device timeout"); - } - - /* - * And set the filter - */ - memset (&bpf_prog, 0, sizeof (struct bpf_program)); - bpf_prog.bf_len = 8; - bpf_prog.bf_insns = &(llcfilter[0]); - if (ioctl (fd, BIOCSETF, (caddr_t) & bpf_prog) < 0) - { - zlog_warn ("open_bpf_dev(): failed to install filter: %s", - safe_strerror (errno)); - return ISIS_WARNING; - } - - assert (fd > 0); - - circuit->fd = fd; - - return ISIS_OK; + + assert(fd > 0); + + circuit->fd = fd; + + return ISIS_OK; } /* * Create the socket and set the tx/rx funcs */ -int -isis_sock_init (struct isis_circuit *circuit) +int isis_sock_init(struct isis_circuit *circuit) { - int retval = ISIS_OK; - - if (isisd_privs.change (ZPRIVS_RAISE)) - zlog_err ("%s: could not raise privs, %s", __func__, safe_strerror (errno)); - - retval = open_bpf_dev (circuit); - - if (retval != ISIS_OK) - { - zlog_warn ("%s: could not initialize the socket", __func__); - goto end; - } - - if (if_is_broadcast(circuit->interface)) - { - circuit->tx = isis_send_pdu_bcast; - circuit->rx = isis_recv_pdu_bcast; - } - else - { - zlog_warn ("isis_sock_init(): unknown circuit type"); - retval = ISIS_WARNING; - goto end; - } + int retval = ISIS_OK; + + if (isisd_privs.change(ZPRIVS_RAISE)) + zlog_err("%s: could not raise privs, %s", __func__, + safe_strerror(errno)); + + retval = open_bpf_dev(circuit); + + if (retval != ISIS_OK) { + zlog_warn("%s: could not initialize the socket", __func__); + goto end; + } + + if (if_is_broadcast(circuit->interface)) { + circuit->tx = isis_send_pdu_bcast; + circuit->rx = isis_recv_pdu_bcast; + } else { + zlog_warn("isis_sock_init(): unknown circuit type"); + retval = ISIS_WARNING; + goto end; + } end: - if (isisd_privs.change (ZPRIVS_LOWER)) - zlog_err ("%s: could not lower privs, %s", __func__, safe_strerror (errno)); + if (isisd_privs.change(ZPRIVS_LOWER)) + zlog_err("%s: could not lower privs, %s", __func__, + safe_strerror(errno)); - return retval; + return retval; } -int -isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa) +int isis_recv_pdu_bcast(struct isis_circuit *circuit, u_char *ssnpa) { - int bytesread = 0, bytestoread, offset, one = 1; - struct bpf_hdr *bpf_hdr; + int bytesread = 0, bytestoread, offset, one = 1; + struct bpf_hdr *bpf_hdr; - assert (circuit->fd > 0); + assert(circuit->fd > 0); - if (ioctl (circuit->fd, FIONREAD, (caddr_t) & bytestoread) < 0) - { - zlog_warn ("ioctl() FIONREAD failed: %s", safe_strerror (errno)); - } + if (ioctl(circuit->fd, FIONREAD, (caddr_t)&bytestoread) < 0) { + zlog_warn("ioctl() FIONREAD failed: %s", safe_strerror(errno)); + } - if (bytestoread) - { - bytesread = read (circuit->fd, readbuff, readblen); - } - if (bytesread < 0) - { - zlog_warn ("isis_recv_pdu_bcast(): read() failed: %s", - safe_strerror (errno)); - return ISIS_WARNING; - } + if (bytestoread) { + bytesread = read(circuit->fd, readbuff, readblen); + } + if (bytesread < 0) { + zlog_warn("isis_recv_pdu_bcast(): read() failed: %s", + safe_strerror(errno)); + return ISIS_WARNING; + } - if (bytesread == 0) - return ISIS_WARNING; + if (bytesread == 0) + return ISIS_WARNING; - bpf_hdr = (struct bpf_hdr *) readbuff; + bpf_hdr = (struct bpf_hdr *)readbuff; - assert (bpf_hdr->bh_caplen == bpf_hdr->bh_datalen); + assert(bpf_hdr->bh_caplen == bpf_hdr->bh_datalen); - offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETHER_HDR_LEN; + offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETHER_HDR_LEN; - /* then we lose the BPF, LLC and ethernet headers */ - stream_write (circuit->rcv_stream, readbuff + offset, - bpf_hdr->bh_caplen - LLC_LEN - ETHER_HDR_LEN); - stream_set_getp (circuit->rcv_stream, 0); + /* then we lose the BPF, LLC and ethernet headers */ + stream_write(circuit->rcv_stream, readbuff + offset, + bpf_hdr->bh_caplen - LLC_LEN - ETHER_HDR_LEN); + stream_set_getp(circuit->rcv_stream, 0); - memcpy (ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETHER_ADDR_LEN, - ETHER_ADDR_LEN); + memcpy(ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETHER_ADDR_LEN, + ETHER_ADDR_LEN); - if (ioctl (circuit->fd, BIOCFLUSH, &one) < 0) - zlog_warn ("Flushing failed: %s", safe_strerror (errno)); + if (ioctl(circuit->fd, BIOCFLUSH, &one) < 0) + zlog_warn("Flushing failed: %s", safe_strerror(errno)); - return ISIS_OK; + return ISIS_OK; } -int -isis_send_pdu_bcast (struct isis_circuit *circuit, int level) +int isis_send_pdu_bcast(struct isis_circuit *circuit, int level) { - struct ether_header *eth; - ssize_t written; - size_t buflen; - - buflen = stream_get_endp (circuit->snd_stream) + LLC_LEN + ETHER_HDR_LEN; - if (buflen > sizeof (sock_buff)) - { - zlog_warn ("isis_send_pdu_bcast: sock_buff size %zu is less than " - "output pdu size %zu on circuit %s", - sizeof (sock_buff), buflen, circuit->interface->name); - return ISIS_WARNING; - } - - stream_set_getp (circuit->snd_stream, 0); - - /* - * First the eth header - */ - eth = (struct ether_header *) sock_buff; - if (level == 1) - memcpy (eth->ether_dhost, ALL_L1_ISS, ETHER_ADDR_LEN); - else - memcpy (eth->ether_dhost, ALL_L2_ISS, ETHER_ADDR_LEN); - memcpy (eth->ether_shost, circuit->u.bc.snpa, ETHER_ADDR_LEN); - size_t frame_size = stream_get_endp(circuit->snd_stream) + LLC_LEN; - eth->ether_type = htons(isis_ethertype(frame_size)); - - /* - * Then the LLC - */ - sock_buff[ETHER_HDR_LEN] = ISO_SAP; - sock_buff[ETHER_HDR_LEN + 1] = ISO_SAP; - sock_buff[ETHER_HDR_LEN + 2] = 0x03; - - /* then we copy the data */ - memcpy (sock_buff + (LLC_LEN + ETHER_HDR_LEN), circuit->snd_stream->data, - stream_get_endp (circuit->snd_stream)); - - /* now we can send this */ - written = write (circuit->fd, sock_buff, buflen); - if (written < 0) - { - zlog_warn("IS-IS bpf: could not transmit packet on %s: %s", - circuit->interface->name, safe_strerror(errno)); - if (ERRNO_IO_RETRY(errno)) - return ISIS_WARNING; - return ISIS_ERROR; - } - - return ISIS_OK; + struct ether_header *eth; + ssize_t written; + size_t buflen; + + buflen = stream_get_endp(circuit->snd_stream) + LLC_LEN + ETHER_HDR_LEN; + if (buflen > sizeof(sock_buff)) { + zlog_warn( + "isis_send_pdu_bcast: sock_buff size %zu is less than " + "output pdu size %zu on circuit %s", + sizeof(sock_buff), buflen, circuit->interface->name); + return ISIS_WARNING; + } + + stream_set_getp(circuit->snd_stream, 0); + + /* + * First the eth header + */ + eth = (struct ether_header *)sock_buff; + if (level == 1) + memcpy(eth->ether_dhost, ALL_L1_ISS, ETHER_ADDR_LEN); + else + memcpy(eth->ether_dhost, ALL_L2_ISS, ETHER_ADDR_LEN); + memcpy(eth->ether_shost, circuit->u.bc.snpa, ETHER_ADDR_LEN); + size_t frame_size = stream_get_endp(circuit->snd_stream) + LLC_LEN; + eth->ether_type = htons(isis_ethertype(frame_size)); + + /* + * Then the LLC + */ + sock_buff[ETHER_HDR_LEN] = ISO_SAP; + sock_buff[ETHER_HDR_LEN + 1] = ISO_SAP; + sock_buff[ETHER_HDR_LEN + 2] = 0x03; + + /* then we copy the data */ + memcpy(sock_buff + (LLC_LEN + ETHER_HDR_LEN), circuit->snd_stream->data, + stream_get_endp(circuit->snd_stream)); + + /* now we can send this */ + written = write(circuit->fd, sock_buff, buflen); + if (written < 0) { + zlog_warn("IS-IS bpf: could not transmit packet on %s: %s", + circuit->interface->name, safe_strerror(errno)); + if (ERRNO_IO_RETRY(errno)) + return ISIS_WARNING; + return ISIS_ERROR; + } + + return ISIS_OK; } #endif /* ISIS_METHOD == ISIS_METHOD_BPF */ diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index d07ea27c4..72810532b 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -2,17 +2,17 @@ * IS-IS Rout(e)ing protocol - isis_circuit.h * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -71,1366 +71,1282 @@ int isis_interface_config_write(struct vty *); int isis_if_new_hook(struct interface *); int isis_if_delete_hook(struct interface *); -struct isis_circuit * -isis_circuit_new () +struct isis_circuit *isis_circuit_new() { - struct isis_circuit *circuit; - int i; - - circuit = XCALLOC (MTYPE_ISIS_CIRCUIT, sizeof (struct isis_circuit)); - if (circuit == NULL) - { - zlog_err ("Can't malloc isis circuit"); - return NULL; - } - - /* - * Default values - */ - circuit->is_type = IS_LEVEL_1_AND_2; - circuit->flags = 0; - circuit->pad_hellos = 1; - for (i = 0; i < 2; i++) - { - circuit->hello_interval[i] = DEFAULT_HELLO_INTERVAL; - circuit->hello_multiplier[i] = DEFAULT_HELLO_MULTIPLIER; - circuit->csnp_interval[i] = DEFAULT_CSNP_INTERVAL; - circuit->psnp_interval[i] = DEFAULT_PSNP_INTERVAL; - circuit->priority[i] = DEFAULT_PRIORITY; - circuit->metric[i] = DEFAULT_CIRCUIT_METRIC; - circuit->te_metric[i] = DEFAULT_CIRCUIT_METRIC; - } - - circuit->mtc = mpls_te_circuit_new(); - - circuit_mt_init(circuit); - - QOBJ_REG (circuit, isis_circuit); - - return circuit; + struct isis_circuit *circuit; + int i; + + circuit = XCALLOC(MTYPE_ISIS_CIRCUIT, sizeof(struct isis_circuit)); + if (circuit == NULL) { + zlog_err("Can't malloc isis circuit"); + return NULL; + } + + /* + * Default values + */ + circuit->is_type = IS_LEVEL_1_AND_2; + circuit->flags = 0; + circuit->pad_hellos = 1; + for (i = 0; i < 2; i++) { + circuit->hello_interval[i] = DEFAULT_HELLO_INTERVAL; + circuit->hello_multiplier[i] = DEFAULT_HELLO_MULTIPLIER; + circuit->csnp_interval[i] = DEFAULT_CSNP_INTERVAL; + circuit->psnp_interval[i] = DEFAULT_PSNP_INTERVAL; + circuit->priority[i] = DEFAULT_PRIORITY; + circuit->metric[i] = DEFAULT_CIRCUIT_METRIC; + circuit->te_metric[i] = DEFAULT_CIRCUIT_METRIC; + } + + circuit->mtc = mpls_te_circuit_new(); + + circuit_mt_init(circuit); + + QOBJ_REG(circuit, isis_circuit); + + return circuit; } -void -isis_circuit_del (struct isis_circuit *circuit) +void isis_circuit_del(struct isis_circuit *circuit) { - if (!circuit) - return; + if (!circuit) + return; - QOBJ_UNREG (circuit); + QOBJ_UNREG(circuit); - isis_circuit_if_unbind (circuit, circuit->interface); + isis_circuit_if_unbind(circuit, circuit->interface); - circuit_mt_finish(circuit); + circuit_mt_finish(circuit); - /* and lastly the circuit itself */ - XFREE (MTYPE_ISIS_CIRCUIT, circuit); + /* and lastly the circuit itself */ + XFREE(MTYPE_ISIS_CIRCUIT, circuit); - return; + return; } -void -isis_circuit_configure (struct isis_circuit *circuit, struct isis_area *area) +void isis_circuit_configure(struct isis_circuit *circuit, + struct isis_area *area) { - assert (area); - circuit->area = area; - - /* - * Whenever the is-type of an area is changed, the is-type of each circuit - * in that area is updated to a non-empty subset of the area is-type. - * Inversely, when configuring a new circuit, this property should be - * ensured as well. - */ - if (area->is_type != IS_LEVEL_1_AND_2) - circuit->is_type = area->is_type; - - /* - * Add the circuit into area - */ - listnode_add (area->circuit_list, circuit); - - circuit->idx = flags_get_index (&area->flags); - - return; + assert(area); + circuit->area = area; + + /* + * Whenever the is-type of an area is changed, the is-type of each + * circuit + * in that area is updated to a non-empty subset of the area is-type. + * Inversely, when configuring a new circuit, this property should be + * ensured as well. + */ + if (area->is_type != IS_LEVEL_1_AND_2) + circuit->is_type = area->is_type; + + /* + * Add the circuit into area + */ + listnode_add(area->circuit_list, circuit); + + circuit->idx = flags_get_index(&area->flags); + + return; } -void -isis_circuit_deconfigure (struct isis_circuit *circuit, struct isis_area *area) +void isis_circuit_deconfigure(struct isis_circuit *circuit, + struct isis_area *area) { - /* Free the index of SRM and SSN flags */ - flags_free_index (&area->flags, circuit->idx); - circuit->idx = 0; - /* Remove circuit from area */ - assert (circuit->area == area); - listnode_delete (area->circuit_list, circuit); - circuit->area = NULL; - - return; + /* Free the index of SRM and SSN flags */ + flags_free_index(&area->flags, circuit->idx); + circuit->idx = 0; + /* Remove circuit from area */ + assert(circuit->area == area); + listnode_delete(area->circuit_list, circuit); + circuit->area = NULL; + + return; } -struct isis_circuit * -circuit_lookup_by_ifp (struct interface *ifp, struct list *list) +struct isis_circuit *circuit_lookup_by_ifp(struct interface *ifp, + struct list *list) { - struct isis_circuit *circuit = NULL; - struct listnode *node; + struct isis_circuit *circuit = NULL; + struct listnode *node; - if (!list) - return NULL; + if (!list) + return NULL; - for (ALL_LIST_ELEMENTS_RO (list, node, circuit)) - if (circuit->interface == ifp) - { - assert (ifp->info == circuit); - return circuit; - } + for (ALL_LIST_ELEMENTS_RO(list, node, circuit)) + if (circuit->interface == ifp) { + assert(ifp->info == circuit); + return circuit; + } - return NULL; + return NULL; } -struct isis_circuit * -circuit_scan_by_ifp (struct interface *ifp) +struct isis_circuit *circuit_scan_by_ifp(struct interface *ifp) { - struct isis_area *area; - struct listnode *node; - struct isis_circuit *circuit; - - if (ifp->info) - return (struct isis_circuit *)ifp->info; - - if (isis->area_list) - { - for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area)) - { - circuit = circuit_lookup_by_ifp (ifp, area->circuit_list); - if (circuit) - return circuit; - } - } - return circuit_lookup_by_ifp (ifp, isis->init_circ_list); + struct isis_area *area; + struct listnode *node; + struct isis_circuit *circuit; + + if (ifp->info) + return (struct isis_circuit *)ifp->info; + + if (isis->area_list) { + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { + circuit = + circuit_lookup_by_ifp(ifp, area->circuit_list); + if (circuit) + return circuit; + } + } + return circuit_lookup_by_ifp(ifp, isis->init_circ_list); } -void -isis_circuit_add_addr (struct isis_circuit *circuit, - struct connected *connected) +void isis_circuit_add_addr(struct isis_circuit *circuit, + struct connected *connected) { - struct listnode *node; - struct prefix_ipv4 *ipv4; + struct listnode *node; + struct prefix_ipv4 *ipv4; #if defined(EXTREME_DEBUG) - char buf[PREFIX2STR_BUFFER]; + char buf[PREFIX2STR_BUFFER]; #endif - struct prefix_ipv6 *ipv6; + struct prefix_ipv6 *ipv6; - if (connected->address->family == AF_INET) - { - u_int32_t addr = connected->address->u.prefix4.s_addr; - addr = ntohl (addr); - if (IPV4_NET0(addr) || - IPV4_NET127(addr) || - IN_CLASSD(addr) || - IPV4_LINKLOCAL(addr)) - return; + if (connected->address->family == AF_INET) { + u_int32_t addr = connected->address->u.prefix4.s_addr; + addr = ntohl(addr); + if (IPV4_NET0(addr) || IPV4_NET127(addr) || IN_CLASSD(addr) + || IPV4_LINKLOCAL(addr)) + return; - for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, node, ipv4)) - if (prefix_same ((struct prefix *) ipv4, connected->address)) - return; + for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, node, ipv4)) + if (prefix_same((struct prefix *)ipv4, + connected->address)) + return; - ipv4 = prefix_ipv4_new (); - ipv4->prefixlen = connected->address->prefixlen; - ipv4->prefix = connected->address->u.prefix4; - listnode_add (circuit->ip_addrs, ipv4); + ipv4 = prefix_ipv4_new(); + ipv4->prefixlen = connected->address->prefixlen; + ipv4->prefix = connected->address->u.prefix4; + listnode_add(circuit->ip_addrs, ipv4); - /* Update MPLS TE Local IP address parameter */ - set_circuitparams_local_ipaddr (circuit->mtc, ipv4->prefix); + /* Update MPLS TE Local IP address parameter */ + set_circuitparams_local_ipaddr(circuit->mtc, ipv4->prefix); - if (circuit->area) - lsp_regenerate_schedule (circuit->area, circuit->is_type, 0); + if (circuit->area) + lsp_regenerate_schedule(circuit->area, circuit->is_type, + 0); #ifdef EXTREME_DEBUG - prefix2str (connected->address, buf, sizeof (buf)); - zlog_debug ("Added IP address %s to circuit %d", buf, - circuit->circuit_id); + prefix2str(connected->address, buf, sizeof(buf)); + zlog_debug("Added IP address %s to circuit %d", buf, + circuit->circuit_id); #endif /* EXTREME_DEBUG */ - } - if (connected->address->family == AF_INET6) - { - if (IN6_IS_ADDR_LOOPBACK(&connected->address->u.prefix6)) - return; - - for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_link, node, ipv6)) - if (prefix_same ((struct prefix *) ipv6, connected->address)) - return; - for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, node, ipv6)) - if (prefix_same ((struct prefix *) ipv6, connected->address)) - return; - - ipv6 = prefix_ipv6_new (); - ipv6->prefixlen = connected->address->prefixlen; - ipv6->prefix = connected->address->u.prefix6; - - if (IN6_IS_ADDR_LINKLOCAL (&ipv6->prefix)) - listnode_add (circuit->ipv6_link, ipv6); - else - listnode_add (circuit->ipv6_non_link, ipv6); - if (circuit->area) - lsp_regenerate_schedule (circuit->area, circuit->is_type, 0); + } + if (connected->address->family == AF_INET6) { + if (IN6_IS_ADDR_LOOPBACK(&connected->address->u.prefix6)) + return; + + for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_link, node, ipv6)) + if (prefix_same((struct prefix *)ipv6, + connected->address)) + return; + for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link, node, ipv6)) + if (prefix_same((struct prefix *)ipv6, + connected->address)) + return; + + ipv6 = prefix_ipv6_new(); + ipv6->prefixlen = connected->address->prefixlen; + ipv6->prefix = connected->address->u.prefix6; + + if (IN6_IS_ADDR_LINKLOCAL(&ipv6->prefix)) + listnode_add(circuit->ipv6_link, ipv6); + else + listnode_add(circuit->ipv6_non_link, ipv6); + if (circuit->area) + lsp_regenerate_schedule(circuit->area, circuit->is_type, + 0); #ifdef EXTREME_DEBUG - prefix2str (connected->address, buf, sizeof (buf)); - zlog_debug ("Added IPv6 address %s to circuit %d", buf, - circuit->circuit_id); + prefix2str(connected->address, buf, sizeof(buf)); + zlog_debug("Added IPv6 address %s to circuit %d", buf, + circuit->circuit_id); #endif /* EXTREME_DEBUG */ - } - return; + } + return; } -void -isis_circuit_del_addr (struct isis_circuit *circuit, - struct connected *connected) +void isis_circuit_del_addr(struct isis_circuit *circuit, + struct connected *connected) { - struct prefix_ipv4 *ipv4, *ip = NULL; - struct listnode *node; - char buf[PREFIX2STR_BUFFER]; - struct prefix_ipv6 *ipv6, *ip6 = NULL; - int found = 0; - - if (connected->address->family == AF_INET) - { - ipv4 = prefix_ipv4_new (); - ipv4->prefixlen = connected->address->prefixlen; - ipv4->prefix = connected->address->u.prefix4; - - for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, node, ip)) - if (prefix_same ((struct prefix *) ip, (struct prefix *) ipv4)) - break; - - if (ip) - { - listnode_delete (circuit->ip_addrs, ip); - if (circuit->area) - lsp_regenerate_schedule (circuit->area, circuit->is_type, 0); + struct prefix_ipv4 *ipv4, *ip = NULL; + struct listnode *node; + char buf[PREFIX2STR_BUFFER]; + struct prefix_ipv6 *ipv6, *ip6 = NULL; + int found = 0; + + if (connected->address->family == AF_INET) { + ipv4 = prefix_ipv4_new(); + ipv4->prefixlen = connected->address->prefixlen; + ipv4->prefix = connected->address->u.prefix4; + + for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, node, ip)) + if (prefix_same((struct prefix *)ip, + (struct prefix *)ipv4)) + break; + + if (ip) { + listnode_delete(circuit->ip_addrs, ip); + if (circuit->area) + lsp_regenerate_schedule(circuit->area, + circuit->is_type, 0); + } else { + prefix2str(connected->address, buf, sizeof(buf)); + zlog_warn( + "Nonexistant ip address %s removal attempt from \ + circuit %d", + buf, circuit->circuit_id); + zlog_warn("Current ip addresses on %s:", + circuit->interface->name); + for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, node, + ip)) { + prefix2str(ip, buf, sizeof(buf)); + zlog_warn(" %s", buf); + } + zlog_warn("End of addresses"); + } + + prefix_ipv4_free(ipv4); } - else - { - prefix2str (connected->address, buf, sizeof (buf)); - zlog_warn ("Nonexistant ip address %s removal attempt from \ - circuit %d", buf, circuit->circuit_id); - zlog_warn ("Current ip addresses on %s:", circuit->interface->name); - for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, node, ip)) - { - prefix2str(ip, buf, sizeof(buf)); - zlog_warn(" %s", buf); - } - zlog_warn("End of addresses"); + if (connected->address->family == AF_INET6) { + ipv6 = prefix_ipv6_new(); + ipv6->prefixlen = connected->address->prefixlen; + ipv6->prefix = connected->address->u.prefix6; + + if (IN6_IS_ADDR_LINKLOCAL(&ipv6->prefix)) { + for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_link, node, + ip6)) { + if (prefix_same((struct prefix *)ip6, + (struct prefix *)ipv6)) + break; + } + if (ip6) { + listnode_delete(circuit->ipv6_link, ip6); + found = 1; + } + } else { + for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link, node, + ip6)) { + if (prefix_same((struct prefix *)ip6, + (struct prefix *)ipv6)) + break; + } + if (ip6) { + listnode_delete(circuit->ipv6_non_link, ip6); + found = 1; + } + } + + if (!found) { + prefix2str(connected->address, buf, sizeof(buf)); + zlog_warn( + "Nonexitant ip address %s removal attempt from \ + circuit %d", + buf, circuit->circuit_id); + zlog_warn("Current ip addresses on %s:", + circuit->interface->name); + for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_link, node, + ip6)) { + prefix2str((struct prefix *)ip6, (char *)buf, + BUFSIZ); + zlog_warn(" %s", buf); + } + zlog_warn(" -----"); + for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link, node, + ip6)) { + prefix2str((struct prefix *)ip6, (char *)buf, + BUFSIZ); + zlog_warn(" %s", buf); + } + zlog_warn("End of addresses"); + } else if (circuit->area) + lsp_regenerate_schedule(circuit->area, circuit->is_type, + 0); + + prefix_ipv6_free(ipv6); } + return; +} - prefix_ipv4_free (ipv4); - } - if (connected->address->family == AF_INET6) - { - ipv6 = prefix_ipv6_new (); - ipv6->prefixlen = connected->address->prefixlen; - ipv6->prefix = connected->address->u.prefix6; - - if (IN6_IS_ADDR_LINKLOCAL (&ipv6->prefix)) - { - for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_link, node, ip6)) - { - if (prefix_same ((struct prefix *) ip6, (struct prefix *) ipv6)) - break; - } - if (ip6) - { - listnode_delete (circuit->ipv6_link, ip6); - found = 1; - } - } - else - { - for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, node, ip6)) - { - if (prefix_same ((struct prefix *) ip6, (struct prefix *) ipv6)) - break; - } - if (ip6) - { - listnode_delete (circuit->ipv6_non_link, ip6); - found = 1; - } +static u_char isis_circuit_id_gen(struct interface *ifp) +{ + u_char id = 0; + char ifname[16]; + unsigned int i; + int start = -1, end = -1; + + /* + * Get a stable circuit id from ifname. This makes + * the ifindex from flapping when netdevs are created + * and deleted on the fly. Note that this circuit id + * is used in pseudo lsps so it is better to be stable. + * The following code works on any reasonanle ifname + * like: eth1 or trk-1.1 etc. + */ + for (i = 0; i < strlen(ifp->name); i++) { + if (isdigit((unsigned char)ifp->name[i])) { + if (start < 0) { + start = i; + end = i + 1; + } else { + end = i + 1; + } + } else if (start >= 0) + break; } - if (!found) - { - prefix2str (connected->address, buf, sizeof (buf)); - zlog_warn ("Nonexitant ip address %s removal attempt from \ - circuit %d", buf, circuit->circuit_id); - zlog_warn ("Current ip addresses on %s:", circuit->interface->name); - for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_link, node, ip6)) - { - prefix2str((struct prefix*)ip6, (char *)buf, BUFSIZ); - zlog_warn(" %s", buf); - } - zlog_warn(" -----"); - for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link, node, ip6)) - { - prefix2str((struct prefix*)ip6, (char *)buf, BUFSIZ); - zlog_warn(" %s", buf); - } - zlog_warn("End of addresses"); + if ((start >= 0) && (end >= start) && (end - start) < 16) { + memset(ifname, 0, 16); + strncpy(ifname, &ifp->name[start], end - start); + id = (u_char)atoi(ifname); } - else if (circuit->area) - lsp_regenerate_schedule (circuit->area, circuit->is_type, 0); - prefix_ipv6_free (ipv6); - } - return; -} + /* Try to be unique. */ + if (!id) + id = (u_char)((ifp->ifindex & 0xff) | 0x80); -static u_char -isis_circuit_id_gen (struct interface *ifp) -{ - u_char id = 0; - char ifname[16]; - unsigned int i; - int start = -1, end = -1; - - /* - * Get a stable circuit id from ifname. This makes - * the ifindex from flapping when netdevs are created - * and deleted on the fly. Note that this circuit id - * is used in pseudo lsps so it is better to be stable. - * The following code works on any reasonanle ifname - * like: eth1 or trk-1.1 etc. - */ - for (i = 0; i < strlen (ifp->name); i++) - { - if (isdigit((unsigned char)ifp->name[i])) - { - if (start < 0) - { - start = i; - end = i + 1; - } - else - { - end = i + 1; - } - } - else if (start >= 0) - break; - } - - if ((start >= 0) && (end >= start) && (end - start) < 16) - { - memset (ifname, 0, 16); - strncpy (ifname, &ifp->name[start], end - start); - id = (u_char)atoi(ifname); - } - - /* Try to be unique. */ - if (!id) - id = (u_char)((ifp->ifindex & 0xff) | 0x80); - - return id; + return id; } -void -isis_circuit_if_add (struct isis_circuit *circuit, struct interface *ifp) +void isis_circuit_if_add(struct isis_circuit *circuit, struct interface *ifp) { - struct listnode *node, *nnode; - struct connected *conn; - - circuit->circuit_id = isis_circuit_id_gen (ifp); - - isis_circuit_if_bind (circuit, ifp); - /* isis_circuit_update_addrs (circuit, ifp); */ - - if (if_is_broadcast (ifp)) - { - if (circuit->circ_type_config == CIRCUIT_T_P2P) - circuit->circ_type = CIRCUIT_T_P2P; - else - circuit->circ_type = CIRCUIT_T_BROADCAST; - } - else if (if_is_pointopoint (ifp)) - { - circuit->circ_type = CIRCUIT_T_P2P; - } - else if (if_is_loopback (ifp)) - { - circuit->circ_type = CIRCUIT_T_LOOPBACK; - circuit->is_passive = 1; - } - else - { - /* It's normal in case of loopback etc. */ - if (isis->debugs & DEBUG_EVENTS) - zlog_debug ("isis_circuit_if_add: unsupported media"); - circuit->circ_type = CIRCUIT_T_UNKNOWN; - } - - circuit->ip_addrs = list_new (); - circuit->ipv6_link = list_new (); - circuit->ipv6_non_link = list_new (); - - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, conn)) - isis_circuit_add_addr (circuit, conn); - - return; + struct listnode *node, *nnode; + struct connected *conn; + + circuit->circuit_id = isis_circuit_id_gen(ifp); + + isis_circuit_if_bind(circuit, ifp); + /* isis_circuit_update_addrs (circuit, ifp); */ + + if (if_is_broadcast(ifp)) { + if (circuit->circ_type_config == CIRCUIT_T_P2P) + circuit->circ_type = CIRCUIT_T_P2P; + else + circuit->circ_type = CIRCUIT_T_BROADCAST; + } else if (if_is_pointopoint(ifp)) { + circuit->circ_type = CIRCUIT_T_P2P; + } else if (if_is_loopback(ifp)) { + circuit->circ_type = CIRCUIT_T_LOOPBACK; + circuit->is_passive = 1; + } else { + /* It's normal in case of loopback etc. */ + if (isis->debugs & DEBUG_EVENTS) + zlog_debug("isis_circuit_if_add: unsupported media"); + circuit->circ_type = CIRCUIT_T_UNKNOWN; + } + + circuit->ip_addrs = list_new(); + circuit->ipv6_link = list_new(); + circuit->ipv6_non_link = list_new(); + + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, conn)) + isis_circuit_add_addr(circuit, conn); + + return; } -void -isis_circuit_if_del (struct isis_circuit *circuit, struct interface *ifp) +void isis_circuit_if_del(struct isis_circuit *circuit, struct interface *ifp) { - struct listnode *node, *nnode; - struct connected *conn; - - assert (circuit->interface == ifp); - - /* destroy addresses */ - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, conn)) - isis_circuit_del_addr (circuit, conn); - - if (circuit->ip_addrs) - { - assert (listcount(circuit->ip_addrs) == 0); - list_delete (circuit->ip_addrs); - circuit->ip_addrs = NULL; - } - - if (circuit->ipv6_link) - { - assert (listcount(circuit->ipv6_link) == 0); - list_delete (circuit->ipv6_link); - circuit->ipv6_link = NULL; - } - - if (circuit->ipv6_non_link) - { - assert (listcount(circuit->ipv6_non_link) == 0); - list_delete (circuit->ipv6_non_link); - circuit->ipv6_non_link = NULL; - } - - circuit->circ_type = CIRCUIT_T_UNKNOWN; - circuit->circuit_id = 0; - - return; + struct listnode *node, *nnode; + struct connected *conn; + + assert(circuit->interface == ifp); + + /* destroy addresses */ + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, conn)) + isis_circuit_del_addr(circuit, conn); + + if (circuit->ip_addrs) { + assert(listcount(circuit->ip_addrs) == 0); + list_delete(circuit->ip_addrs); + circuit->ip_addrs = NULL; + } + + if (circuit->ipv6_link) { + assert(listcount(circuit->ipv6_link) == 0); + list_delete(circuit->ipv6_link); + circuit->ipv6_link = NULL; + } + + if (circuit->ipv6_non_link) { + assert(listcount(circuit->ipv6_non_link) == 0); + list_delete(circuit->ipv6_non_link); + circuit->ipv6_non_link = NULL; + } + + circuit->circ_type = CIRCUIT_T_UNKNOWN; + circuit->circuit_id = 0; + + return; } -void -isis_circuit_if_bind (struct isis_circuit *circuit, struct interface *ifp) +void isis_circuit_if_bind(struct isis_circuit *circuit, struct interface *ifp) { - assert (circuit != NULL); - assert (ifp != NULL); - if (circuit->interface) - assert (circuit->interface == ifp); - else - circuit->interface = ifp; - if (ifp->info) - assert (ifp->info == circuit); - else - ifp->info = circuit; - isis_link_params_update (circuit, ifp); + assert(circuit != NULL); + assert(ifp != NULL); + if (circuit->interface) + assert(circuit->interface == ifp); + else + circuit->interface = ifp; + if (ifp->info) + assert(ifp->info == circuit); + else + ifp->info = circuit; + isis_link_params_update(circuit, ifp); } -void -isis_circuit_if_unbind (struct isis_circuit *circuit, struct interface *ifp) +void isis_circuit_if_unbind(struct isis_circuit *circuit, struct interface *ifp) { - assert (circuit != NULL); - assert (ifp != NULL); - assert (circuit->interface == ifp); - assert (ifp->info == circuit); - circuit->interface = NULL; - ifp->info = NULL; + assert(circuit != NULL); + assert(ifp != NULL); + assert(circuit->interface == ifp); + assert(ifp->info == circuit); + circuit->interface = NULL; + ifp->info = NULL; } -static void -isis_circuit_update_all_srmflags (struct isis_circuit *circuit, int is_set) +static void isis_circuit_update_all_srmflags(struct isis_circuit *circuit, + int is_set) { - struct isis_area *area; - struct isis_lsp *lsp; - dnode_t *dnode, *dnode_next; - int level; - - assert (circuit); - area = circuit->area; - assert (area); - for (level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) - { - if (level & circuit->is_type) - { - if (area->lspdb[level - 1] && - dict_count (area->lspdb[level - 1]) > 0) - { - for (dnode = dict_first (area->lspdb[level - 1]); - dnode != NULL; dnode = dnode_next) - { - dnode_next = dict_next (area->lspdb[level - 1], dnode); - lsp = dnode_get (dnode); - if (is_set) - { - ISIS_SET_FLAG (lsp->SRMflags, circuit); - } - else - { - ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); - } - } - } - } - } + struct isis_area *area; + struct isis_lsp *lsp; + dnode_t *dnode, *dnode_next; + int level; + + assert(circuit); + area = circuit->area; + assert(area); + for (level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) { + if (level & circuit->is_type) { + if (area->lspdb[level - 1] + && dict_count(area->lspdb[level - 1]) > 0) { + for (dnode = dict_first(area->lspdb[level - 1]); + dnode != NULL; dnode = dnode_next) { + dnode_next = dict_next( + area->lspdb[level - 1], dnode); + lsp = dnode_get(dnode); + if (is_set) { + ISIS_SET_FLAG(lsp->SRMflags, + circuit); + } else { + ISIS_CLEAR_FLAG(lsp->SRMflags, + circuit); + } + } + } + } + } } -size_t -isis_circuit_pdu_size(struct isis_circuit *circuit) +size_t isis_circuit_pdu_size(struct isis_circuit *circuit) { - return ISO_MTU(circuit); + return ISO_MTU(circuit); } -void -isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream) +void isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream) { - size_t stream_size = isis_circuit_pdu_size(circuit); - - if (!*stream) - { - *stream = stream_new(stream_size); - } - else - { - if (STREAM_SIZE(*stream) != stream_size) - stream_resize(*stream, stream_size); - stream_reset(*stream); - } + size_t stream_size = isis_circuit_pdu_size(circuit); + + if (!*stream) { + *stream = stream_new(stream_size); + } else { + if (STREAM_SIZE(*stream) != stream_size) + stream_resize(*stream, stream_size); + stream_reset(*stream); + } } -void -isis_circuit_prepare (struct isis_circuit *circuit) +void isis_circuit_prepare(struct isis_circuit *circuit) { #ifdef GNU_LINUX - thread_add_read(master, isis_receive, circuit, circuit->fd, - &circuit->t_read); + thread_add_read(master, isis_receive, circuit, circuit->fd, + &circuit->t_read); #else - thread_add_timer_msec(master, isis_receive, circuit, - listcount(circuit->area->circuit_list) * 100, - &circuit->t_read); + thread_add_timer_msec(master, isis_receive, circuit, + listcount(circuit->area->circuit_list) * 100, + &circuit->t_read); #endif } -int -isis_circuit_up (struct isis_circuit *circuit) +int isis_circuit_up(struct isis_circuit *circuit) { - int retv; - - /* Set the flags for all the lsps of the circuit. */ - isis_circuit_update_all_srmflags (circuit, 1); - - if (circuit->state == C_STATE_UP) - return ISIS_OK; - - if (circuit->is_passive) - return ISIS_OK; - - if (circuit->area->lsp_mtu > isis_circuit_pdu_size(circuit)) - { - zlog_err("Interface MTU %zu on %s is too low to support area lsp mtu %u!", - isis_circuit_pdu_size(circuit), circuit->interface->name, - circuit->area->lsp_mtu); - isis_circuit_update_all_srmflags(circuit, 0); - return ISIS_ERROR; - } - - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - { - /* - * Get the Hardware Address - */ - if (circuit->interface->hw_addr_len != ETH_ALEN) - { - zlog_warn ("unsupported link layer"); - } - else - { - memcpy (circuit->u.bc.snpa, circuit->interface->hw_addr, ETH_ALEN); - } + int retv; + + /* Set the flags for all the lsps of the circuit. */ + isis_circuit_update_all_srmflags(circuit, 1); + + if (circuit->state == C_STATE_UP) + return ISIS_OK; + + if (circuit->is_passive) + return ISIS_OK; + + if (circuit->area->lsp_mtu > isis_circuit_pdu_size(circuit)) { + zlog_err( + "Interface MTU %zu on %s is too low to support area lsp mtu %u!", + isis_circuit_pdu_size(circuit), + circuit->interface->name, circuit->area->lsp_mtu); + isis_circuit_update_all_srmflags(circuit, 0); + return ISIS_ERROR; + } + + if (circuit->circ_type == CIRCUIT_T_BROADCAST) { + /* + * Get the Hardware Address + */ + if (circuit->interface->hw_addr_len != ETH_ALEN) { + zlog_warn("unsupported link layer"); + } else { + memcpy(circuit->u.bc.snpa, circuit->interface->hw_addr, + ETH_ALEN); + } #ifdef EXTREME_DEGUG - zlog_debug ("isis_circuit_if_add: if_id %d, isomtu %d snpa %s", - circuit->interface->ifindex, ISO_MTU (circuit), - snpa_print (circuit->u.bc.snpa)); + zlog_debug("isis_circuit_if_add: if_id %d, isomtu %d snpa %s", + circuit->interface->ifindex, ISO_MTU(circuit), + snpa_print(circuit->u.bc.snpa)); #endif /* EXTREME_DEBUG */ - circuit->u.bc.adjdb[0] = list_new (); - circuit->u.bc.adjdb[1] = list_new (); - - /* - * ISO 10589 - 8.4.1 Enabling of broadcast circuits - */ - - /* initilizing the hello sending threads - * for a broadcast IF - */ - - /* 8.4.1 a) commence sending of IIH PDUs */ - - if (circuit->is_type & IS_LEVEL_1) - { - thread_add_event(master, send_lan_l1_hello, circuit, 0, NULL); - circuit->u.bc.lan_neighs[0] = list_new (); - } - - if (circuit->is_type & IS_LEVEL_2) - { - thread_add_event(master, send_lan_l2_hello, circuit, 0, NULL); - circuit->u.bc.lan_neighs[1] = list_new (); - } - - /* 8.4.1 b) FIXME: solicit ES - 8.4.6 */ - /* 8.4.1 c) FIXME: listen for ESH PDUs */ - - /* 8.4.1 d) */ - /* dr election will commence in... */ - if (circuit->is_type & IS_LEVEL_1) - thread_add_timer(master, isis_run_dr_l1, circuit, - 2 * circuit->hello_interval[0], - &circuit->u.bc.t_run_dr[0]); - if (circuit->is_type & IS_LEVEL_2) - thread_add_timer(master, isis_run_dr_l2, circuit, - 2 * circuit->hello_interval[1], - &circuit->u.bc.t_run_dr[1]); - } - else - { - /* initializing the hello send threads - * for a ptp IF - */ - circuit->u.p2p.neighbor = NULL; - thread_add_event(master, send_p2p_hello, circuit, 0, NULL); - } - - /* initializing PSNP timers */ - if (circuit->is_type & IS_LEVEL_1) - thread_add_timer(master, send_l1_psnp, circuit, - isis_jitter(circuit->psnp_interval[0], PSNP_JITTER), - &circuit->t_send_psnp[0]); - - if (circuit->is_type & IS_LEVEL_2) - thread_add_timer(master, send_l2_psnp, circuit, - isis_jitter(circuit->psnp_interval[1], PSNP_JITTER), - &circuit->t_send_psnp[1]); - - /* unified init for circuits; ignore warnings below this level */ - retv = isis_sock_init (circuit); - if (retv != ISIS_OK) - { - isis_circuit_down (circuit); - return retv; - } - - /* initialize the circuit streams after opening connection */ - isis_circuit_stream(circuit, &circuit->rcv_stream); - isis_circuit_stream(circuit, &circuit->snd_stream); - - isis_circuit_prepare (circuit); - - circuit->lsp_queue = list_new (); - circuit->lsp_queue_last_cleared = time (NULL); - - return ISIS_OK; + circuit->u.bc.adjdb[0] = list_new(); + circuit->u.bc.adjdb[1] = list_new(); + + /* + * ISO 10589 - 8.4.1 Enabling of broadcast circuits + */ + + /* initilizing the hello sending threads + * for a broadcast IF + */ + + /* 8.4.1 a) commence sending of IIH PDUs */ + + if (circuit->is_type & IS_LEVEL_1) { + thread_add_event(master, send_lan_l1_hello, circuit, 0, + NULL); + circuit->u.bc.lan_neighs[0] = list_new(); + } + + if (circuit->is_type & IS_LEVEL_2) { + thread_add_event(master, send_lan_l2_hello, circuit, 0, + NULL); + circuit->u.bc.lan_neighs[1] = list_new(); + } + + /* 8.4.1 b) FIXME: solicit ES - 8.4.6 */ + /* 8.4.1 c) FIXME: listen for ESH PDUs */ + + /* 8.4.1 d) */ + /* dr election will commence in... */ + if (circuit->is_type & IS_LEVEL_1) + thread_add_timer(master, isis_run_dr_l1, circuit, + 2 * circuit->hello_interval[0], + &circuit->u.bc.t_run_dr[0]); + if (circuit->is_type & IS_LEVEL_2) + thread_add_timer(master, isis_run_dr_l2, circuit, + 2 * circuit->hello_interval[1], + &circuit->u.bc.t_run_dr[1]); + } else { + /* initializing the hello send threads + * for a ptp IF + */ + circuit->u.p2p.neighbor = NULL; + thread_add_event(master, send_p2p_hello, circuit, 0, NULL); + } + + /* initializing PSNP timers */ + if (circuit->is_type & IS_LEVEL_1) + thread_add_timer( + master, send_l1_psnp, circuit, + isis_jitter(circuit->psnp_interval[0], PSNP_JITTER), + &circuit->t_send_psnp[0]); + + if (circuit->is_type & IS_LEVEL_2) + thread_add_timer( + master, send_l2_psnp, circuit, + isis_jitter(circuit->psnp_interval[1], PSNP_JITTER), + &circuit->t_send_psnp[1]); + + /* unified init for circuits; ignore warnings below this level */ + retv = isis_sock_init(circuit); + if (retv != ISIS_OK) { + isis_circuit_down(circuit); + return retv; + } + + /* initialize the circuit streams after opening connection */ + isis_circuit_stream(circuit, &circuit->rcv_stream); + isis_circuit_stream(circuit, &circuit->snd_stream); + + isis_circuit_prepare(circuit); + + circuit->lsp_queue = list_new(); + circuit->lsp_queue_last_cleared = time(NULL); + + return ISIS_OK; } -void -isis_circuit_down (struct isis_circuit *circuit) +void isis_circuit_down(struct isis_circuit *circuit) { - if (circuit->state != C_STATE_UP) - return; - - /* Clear the flags for all the lsps of the circuit. */ - isis_circuit_update_all_srmflags (circuit, 0); - - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - { - /* destroy neighbour lists */ - if (circuit->u.bc.lan_neighs[0]) - { - list_delete (circuit->u.bc.lan_neighs[0]); - circuit->u.bc.lan_neighs[0] = NULL; - } - if (circuit->u.bc.lan_neighs[1]) - { - list_delete (circuit->u.bc.lan_neighs[1]); - circuit->u.bc.lan_neighs[1] = NULL; - } - /* destroy adjacency databases */ - if (circuit->u.bc.adjdb[0]) - { - circuit->u.bc.adjdb[0]->del = isis_delete_adj; - list_delete (circuit->u.bc.adjdb[0]); - circuit->u.bc.adjdb[0] = NULL; - } - if (circuit->u.bc.adjdb[1]) - { - circuit->u.bc.adjdb[1]->del = isis_delete_adj; - list_delete (circuit->u.bc.adjdb[1]); - circuit->u.bc.adjdb[1] = NULL; - } - if (circuit->u.bc.is_dr[0]) - { - isis_dr_resign (circuit, 1); - circuit->u.bc.is_dr[0] = 0; - } - memset (circuit->u.bc.l1_desig_is, 0, ISIS_SYS_ID_LEN + 1); - if (circuit->u.bc.is_dr[1]) - { - isis_dr_resign (circuit, 2); - circuit->u.bc.is_dr[1] = 0; - } - memset (circuit->u.bc.l2_desig_is, 0, ISIS_SYS_ID_LEN + 1); - memset (circuit->u.bc.snpa, 0, ETH_ALEN); - - THREAD_TIMER_OFF (circuit->u.bc.t_send_lan_hello[0]); - THREAD_TIMER_OFF (circuit->u.bc.t_send_lan_hello[1]); - THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[0]); - THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[1]); - THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[0]); - THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[1]); - circuit->lsp_regenerate_pending[0] = 0; - circuit->lsp_regenerate_pending[1] = 0; - } - else if (circuit->circ_type == CIRCUIT_T_P2P) - { - isis_delete_adj (circuit->u.p2p.neighbor); - circuit->u.p2p.neighbor = NULL; - THREAD_TIMER_OFF (circuit->u.p2p.t_send_p2p_hello); - } - - /* Cancel all active threads */ - THREAD_TIMER_OFF (circuit->t_send_csnp[0]); - THREAD_TIMER_OFF (circuit->t_send_csnp[1]); - THREAD_TIMER_OFF (circuit->t_send_psnp[0]); - THREAD_TIMER_OFF (circuit->t_send_psnp[1]); - THREAD_OFF (circuit->t_read); - - if (circuit->lsp_queue) - { - circuit->lsp_queue->del = NULL; - list_delete (circuit->lsp_queue); - circuit->lsp_queue = NULL; - } - - /* send one gratuitous hello to spead up convergence */ - if (circuit->is_type & IS_LEVEL_1) - send_hello (circuit, IS_LEVEL_1); - if (circuit->is_type & IS_LEVEL_2) - send_hello (circuit, IS_LEVEL_2); - - circuit->upadjcount[0] = 0; - circuit->upadjcount[1] = 0; - - /* close the socket */ - if (circuit->fd) - { - close (circuit->fd); - circuit->fd = 0; - } - - if (circuit->rcv_stream != NULL) - { - stream_free (circuit->rcv_stream); - circuit->rcv_stream = NULL; - } - - if (circuit->snd_stream != NULL) - { - stream_free (circuit->snd_stream); - circuit->snd_stream = NULL; - } - - thread_cancel_event (master, circuit); - - return; + if (circuit->state != C_STATE_UP) + return; + + /* Clear the flags for all the lsps of the circuit. */ + isis_circuit_update_all_srmflags(circuit, 0); + + if (circuit->circ_type == CIRCUIT_T_BROADCAST) { + /* destroy neighbour lists */ + if (circuit->u.bc.lan_neighs[0]) { + list_delete(circuit->u.bc.lan_neighs[0]); + circuit->u.bc.lan_neighs[0] = NULL; + } + if (circuit->u.bc.lan_neighs[1]) { + list_delete(circuit->u.bc.lan_neighs[1]); + circuit->u.bc.lan_neighs[1] = NULL; + } + /* destroy adjacency databases */ + if (circuit->u.bc.adjdb[0]) { + circuit->u.bc.adjdb[0]->del = isis_delete_adj; + list_delete(circuit->u.bc.adjdb[0]); + circuit->u.bc.adjdb[0] = NULL; + } + if (circuit->u.bc.adjdb[1]) { + circuit->u.bc.adjdb[1]->del = isis_delete_adj; + list_delete(circuit->u.bc.adjdb[1]); + circuit->u.bc.adjdb[1] = NULL; + } + if (circuit->u.bc.is_dr[0]) { + isis_dr_resign(circuit, 1); + circuit->u.bc.is_dr[0] = 0; + } + memset(circuit->u.bc.l1_desig_is, 0, ISIS_SYS_ID_LEN + 1); + if (circuit->u.bc.is_dr[1]) { + isis_dr_resign(circuit, 2); + circuit->u.bc.is_dr[1] = 0; + } + memset(circuit->u.bc.l2_desig_is, 0, ISIS_SYS_ID_LEN + 1); + memset(circuit->u.bc.snpa, 0, ETH_ALEN); + + THREAD_TIMER_OFF(circuit->u.bc.t_send_lan_hello[0]); + THREAD_TIMER_OFF(circuit->u.bc.t_send_lan_hello[1]); + THREAD_TIMER_OFF(circuit->u.bc.t_run_dr[0]); + THREAD_TIMER_OFF(circuit->u.bc.t_run_dr[1]); + THREAD_TIMER_OFF(circuit->u.bc.t_refresh_pseudo_lsp[0]); + THREAD_TIMER_OFF(circuit->u.bc.t_refresh_pseudo_lsp[1]); + circuit->lsp_regenerate_pending[0] = 0; + circuit->lsp_regenerate_pending[1] = 0; + } else if (circuit->circ_type == CIRCUIT_T_P2P) { + isis_delete_adj(circuit->u.p2p.neighbor); + circuit->u.p2p.neighbor = NULL; + THREAD_TIMER_OFF(circuit->u.p2p.t_send_p2p_hello); + } + + /* Cancel all active threads */ + THREAD_TIMER_OFF(circuit->t_send_csnp[0]); + THREAD_TIMER_OFF(circuit->t_send_csnp[1]); + THREAD_TIMER_OFF(circuit->t_send_psnp[0]); + THREAD_TIMER_OFF(circuit->t_send_psnp[1]); + THREAD_OFF(circuit->t_read); + + if (circuit->lsp_queue) { + circuit->lsp_queue->del = NULL; + list_delete(circuit->lsp_queue); + circuit->lsp_queue = NULL; + } + + /* send one gratuitous hello to spead up convergence */ + if (circuit->is_type & IS_LEVEL_1) + send_hello(circuit, IS_LEVEL_1); + if (circuit->is_type & IS_LEVEL_2) + send_hello(circuit, IS_LEVEL_2); + + circuit->upadjcount[0] = 0; + circuit->upadjcount[1] = 0; + + /* close the socket */ + if (circuit->fd) { + close(circuit->fd); + circuit->fd = 0; + } + + if (circuit->rcv_stream != NULL) { + stream_free(circuit->rcv_stream); + circuit->rcv_stream = NULL; + } + + if (circuit->snd_stream != NULL) { + stream_free(circuit->snd_stream); + circuit->snd_stream = NULL; + } + + thread_cancel_event(master, circuit); + + return; } -void -circuit_update_nlpids (struct isis_circuit *circuit) +void circuit_update_nlpids(struct isis_circuit *circuit) { - circuit->nlpids.count = 0; - - if (circuit->ip_router) - { - circuit->nlpids.nlpids[0] = NLPID_IP; - circuit->nlpids.count++; - } - if (circuit->ipv6_router) - { - circuit->nlpids.nlpids[circuit->nlpids.count] = NLPID_IPV6; - circuit->nlpids.count++; - } - return; + circuit->nlpids.count = 0; + + if (circuit->ip_router) { + circuit->nlpids.nlpids[0] = NLPID_IP; + circuit->nlpids.count++; + } + if (circuit->ipv6_router) { + circuit->nlpids.nlpids[circuit->nlpids.count] = NLPID_IPV6; + circuit->nlpids.count++; + } + return; } -void -isis_circuit_print_vty (struct isis_circuit *circuit, struct vty *vty, - char detail) +void isis_circuit_print_vty(struct isis_circuit *circuit, struct vty *vty, + char detail) { - if (detail == ISIS_UI_LEVEL_BRIEF) - { - vty_out (vty, " %-12s", circuit->interface->name); - vty_out (vty, "0x%-7x", circuit->circuit_id); - vty_out (vty, "%-9s", circuit_state2string (circuit->state)); - vty_out (vty, "%-9s", circuit_type2string (circuit->circ_type)); - vty_out (vty, "%-9s", circuit_t2string (circuit->is_type)); - vty_out (vty, "\n"); - } - - if (detail == ISIS_UI_LEVEL_DETAIL) - { - struct listnode *node; - struct prefix *ip_addr; - char buf[BUFSIZ]; - - vty_out (vty, " Interface: %s", circuit->interface->name); - vty_out (vty, ", State: %s", circuit_state2string (circuit->state)); - if (circuit->is_passive) - vty_out (vty, ", Passive"); - else - vty_out (vty, ", Active"); - vty_out (vty, ", Circuit Id: 0x%x", circuit->circuit_id); - vty_out (vty, "\n"); - vty_out (vty, " Type: %s", circuit_type2string (circuit->circ_type)); - vty_out (vty, ", Level: %s", circuit_t2string (circuit->is_type)); - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - vty_out (vty, ", SNPA: %-10s", snpa_print (circuit->u.bc.snpa)); - vty_out (vty, "\n"); - if (circuit->is_type & IS_LEVEL_1) - { - vty_out (vty, " Level-1 Information:\n"); - if (circuit->area->newmetric) - vty_out (vty, " Metric: %d", circuit->te_metric[0]); - else - vty_out (vty, " Metric: %d", - circuit->metric[0]); - if (!circuit->is_passive) - { - vty_out (vty, ", Active neighbors: %u\n", - circuit->upadjcount[0]); - vty_out (vty, " Hello interval: %u, " - "Holddown count: %u %s\n", - circuit->hello_interval[0], - circuit->hello_multiplier[0], - (circuit->pad_hellos ? "(pad)" : "(no-pad)")); - vty_out (vty, " CNSP interval: %u, " - "PSNP interval: %u\n", - circuit->csnp_interval[0], - circuit->psnp_interval[0]); - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - vty_out (vty, " LAN Priority: %u, %s\n", - circuit->priority[0], - (circuit->u.bc.is_dr[0] ? "is DIS" : "is not DIS")); - } - else - { - vty_out (vty, "\n"); - } - } - if (circuit->is_type & IS_LEVEL_2) - { - vty_out (vty, " Level-2 Information:\n"); - if (circuit->area->newmetric) - vty_out (vty, " Metric: %d", circuit->te_metric[1]); - else - vty_out (vty, " Metric: %d", - circuit->metric[1]); - if (!circuit->is_passive) - { - vty_out (vty, ", Active neighbors: %u\n", - circuit->upadjcount[1]); - vty_out (vty, " Hello interval: %u, " - "Holddown count: %u %s\n", - circuit->hello_interval[1], - circuit->hello_multiplier[1], - (circuit->pad_hellos ? "(pad)" : "(no-pad)")); - vty_out (vty, " CNSP interval: %u, " - "PSNP interval: %u\n", - circuit->csnp_interval[1], - circuit->psnp_interval[1]); - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - vty_out (vty, " LAN Priority: %u, %s\n", - circuit->priority[1], - (circuit->u.bc.is_dr[1] ? "is DIS" : "is not DIS")); - } - else - { - vty_out (vty, "\n"); - } - } - if (circuit->ip_addrs && listcount (circuit->ip_addrs) > 0) - { - vty_out (vty, " IP Prefix(es):\n"); - for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, node, ip_addr)) - { - prefix2str (ip_addr, buf, sizeof (buf)), - vty_out (vty, " %s\n", buf); - } - } - if (circuit->ipv6_link && listcount(circuit->ipv6_link) > 0) - { - vty_out (vty, " IPv6 Link-Locals:\n"); - for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_link, node, ip_addr)) - { - prefix2str(ip_addr, (char*)buf, BUFSIZ), - vty_out (vty, " %s\n", buf); - } - } - if (circuit->ipv6_non_link && listcount(circuit->ipv6_non_link) > 0) - { - vty_out (vty, " IPv6 Prefixes:\n"); - for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link, node, ip_addr)) - { - prefix2str(ip_addr, (char*)buf, BUFSIZ), - vty_out (vty, " %s\n", buf); - } - } - - vty_out (vty, "\n"); - } - return; + if (detail == ISIS_UI_LEVEL_BRIEF) { + vty_out(vty, " %-12s", circuit->interface->name); + vty_out(vty, "0x%-7x", circuit->circuit_id); + vty_out(vty, "%-9s", circuit_state2string(circuit->state)); + vty_out(vty, "%-9s", circuit_type2string(circuit->circ_type)); + vty_out(vty, "%-9s", circuit_t2string(circuit->is_type)); + vty_out(vty, "\n"); + } + + if (detail == ISIS_UI_LEVEL_DETAIL) { + struct listnode *node; + struct prefix *ip_addr; + char buf[BUFSIZ]; + + vty_out(vty, " Interface: %s", circuit->interface->name); + vty_out(vty, ", State: %s", + circuit_state2string(circuit->state)); + if (circuit->is_passive) + vty_out(vty, ", Passive"); + else + vty_out(vty, ", Active"); + vty_out(vty, ", Circuit Id: 0x%x", circuit->circuit_id); + vty_out(vty, "\n"); + vty_out(vty, " Type: %s", + circuit_type2string(circuit->circ_type)); + vty_out(vty, ", Level: %s", circuit_t2string(circuit->is_type)); + if (circuit->circ_type == CIRCUIT_T_BROADCAST) + vty_out(vty, ", SNPA: %-10s", + snpa_print(circuit->u.bc.snpa)); + vty_out(vty, "\n"); + if (circuit->is_type & IS_LEVEL_1) { + vty_out(vty, " Level-1 Information:\n"); + if (circuit->area->newmetric) + vty_out(vty, " Metric: %d", + circuit->te_metric[0]); + else + vty_out(vty, " Metric: %d", + circuit->metric[0]); + if (!circuit->is_passive) { + vty_out(vty, ", Active neighbors: %u\n", + circuit->upadjcount[0]); + vty_out(vty, + " Hello interval: %u, " + "Holddown count: %u %s\n", + circuit->hello_interval[0], + circuit->hello_multiplier[0], + (circuit->pad_hellos ? "(pad)" + : "(no-pad)")); + vty_out(vty, + " CNSP interval: %u, " + "PSNP interval: %u\n", + circuit->csnp_interval[0], + circuit->psnp_interval[0]); + if (circuit->circ_type == CIRCUIT_T_BROADCAST) + vty_out(vty, + " LAN Priority: %u, %s\n", + circuit->priority[0], + (circuit->u.bc.is_dr[0] + ? "is DIS" + : "is not DIS")); + } else { + vty_out(vty, "\n"); + } + } + if (circuit->is_type & IS_LEVEL_2) { + vty_out(vty, " Level-2 Information:\n"); + if (circuit->area->newmetric) + vty_out(vty, " Metric: %d", + circuit->te_metric[1]); + else + vty_out(vty, " Metric: %d", + circuit->metric[1]); + if (!circuit->is_passive) { + vty_out(vty, ", Active neighbors: %u\n", + circuit->upadjcount[1]); + vty_out(vty, + " Hello interval: %u, " + "Holddown count: %u %s\n", + circuit->hello_interval[1], + circuit->hello_multiplier[1], + (circuit->pad_hellos ? "(pad)" + : "(no-pad)")); + vty_out(vty, + " CNSP interval: %u, " + "PSNP interval: %u\n", + circuit->csnp_interval[1], + circuit->psnp_interval[1]); + if (circuit->circ_type == CIRCUIT_T_BROADCAST) + vty_out(vty, + " LAN Priority: %u, %s\n", + circuit->priority[1], + (circuit->u.bc.is_dr[1] + ? "is DIS" + : "is not DIS")); + } else { + vty_out(vty, "\n"); + } + } + if (circuit->ip_addrs && listcount(circuit->ip_addrs) > 0) { + vty_out(vty, " IP Prefix(es):\n"); + for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, node, + ip_addr)) { + prefix2str(ip_addr, buf, sizeof(buf)), + vty_out(vty, " %s\n", buf); + } + } + if (circuit->ipv6_link && listcount(circuit->ipv6_link) > 0) { + vty_out(vty, " IPv6 Link-Locals:\n"); + for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_link, node, + ip_addr)) { + prefix2str(ip_addr, (char *)buf, BUFSIZ), + vty_out(vty, " %s\n", buf); + } + } + if (circuit->ipv6_non_link + && listcount(circuit->ipv6_non_link) > 0) { + vty_out(vty, " IPv6 Prefixes:\n"); + for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link, node, + ip_addr)) { + prefix2str(ip_addr, (char *)buf, BUFSIZ), + vty_out(vty, " %s\n", buf); + } + } + + vty_out(vty, "\n"); + } + return; } -int -isis_interface_config_write (struct vty *vty) +int isis_interface_config_write(struct vty *vty) { - int write = 0; - struct listnode *node, *node2; - struct interface *ifp; - struct isis_area *area; - struct isis_circuit *circuit; - int i; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - if (ifp->ifindex == IFINDEX_DELETED) - continue; - - /* IF name */ - vty_out (vty, "interface %s\n", ifp->name); - write++; - /* IF desc */ - if (ifp->desc) - { - vty_out (vty, " description %s\n", ifp->desc); - write++; - } - /* ISIS Circuit */ - for (ALL_LIST_ELEMENTS_RO (isis->area_list, node2, area)) - { - circuit = circuit_lookup_by_ifp (ifp, area->circuit_list); - if (circuit == NULL) - continue; - if (circuit->ip_router) - { - vty_out (vty, " ip router isis %s\n",area->area_tag); - write++; - } - if (circuit->is_passive) - { - vty_out (vty, " isis passive\n"); - write++; - } - if (circuit->circ_type_config == CIRCUIT_T_P2P) - { - vty_out (vty, " isis network point-to-point\n"); - write++; - } - if (circuit->ipv6_router) - { - vty_out (vty, " ipv6 router isis %s\n",area->area_tag); - write++; - } - - /* ISIS - circuit type */ - if (circuit->is_type == IS_LEVEL_1) - { - vty_out (vty, " isis circuit-type level-1\n"); - write++; - } - else - { - if (circuit->is_type == IS_LEVEL_2) - { - vty_out (vty," isis circuit-type level-2-only\n"); - write++; - } - } - - /* ISIS - CSNP interval */ - if (circuit->csnp_interval[0] == circuit->csnp_interval[1]) - { - if (circuit->csnp_interval[0] != DEFAULT_CSNP_INTERVAL) - { - vty_out (vty, " isis csnp-interval %d\n", - circuit->csnp_interval[0]); - write++; - } - } - else - { - for (i = 0; i < 2; i++) - { - if (circuit->csnp_interval[i] != DEFAULT_CSNP_INTERVAL) - { - vty_out (vty, " isis csnp-interval %d level-%d\n", - circuit->csnp_interval[i], i + 1); - write++; - } - } - } - - /* ISIS - PSNP interval */ - if (circuit->psnp_interval[0] == circuit->psnp_interval[1]) - { - if (circuit->psnp_interval[0] != DEFAULT_PSNP_INTERVAL) - { - vty_out (vty, " isis psnp-interval %d\n", - circuit->psnp_interval[0]); - write++; - } - } - else - { - for (i = 0; i < 2; i++) - { - if (circuit->psnp_interval[i] != DEFAULT_PSNP_INTERVAL) - { - vty_out (vty, " isis psnp-interval %d level-%d\n", - circuit->psnp_interval[i], i + 1); - write++; - } - } - } - - /* ISIS - Hello padding - Defaults to true so only display if false */ - if (circuit->pad_hellos == 0) - { - vty_out (vty, " no isis hello padding\n"); - write++; - } - - /* ISIS - Hello interval */ - if (circuit->hello_interval[0] == circuit->hello_interval[1]) - { - if (circuit->hello_interval[0] != DEFAULT_HELLO_INTERVAL) - { - vty_out (vty, " isis hello-interval %d\n", - circuit->hello_interval[0]); - write++; - } - } - else - { - for (i = 0; i < 2; i++) - { - if (circuit->hello_interval[i] != DEFAULT_HELLO_INTERVAL) - { - vty_out (vty, " isis hello-interval %d level-%d\n", - circuit->hello_interval[i], i + 1); - write++; - } - } - } - - /* ISIS - Hello Multiplier */ - if (circuit->hello_multiplier[0] == circuit->hello_multiplier[1]) - { - if (circuit->hello_multiplier[0] != DEFAULT_HELLO_MULTIPLIER) - { - vty_out (vty, " isis hello-multiplier %d\n", - circuit->hello_multiplier[0]); - write++; - } - } - else - { - for (i = 0; i < 2; i++) - { - if (circuit->hello_multiplier[i] != DEFAULT_HELLO_MULTIPLIER) - { - vty_out (vty, " isis hello-multiplier %d level-%d\n", - circuit->hello_multiplier[i],i + 1); - write++; - } - } - } - - /* ISIS - Priority */ - if (circuit->priority[0] == circuit->priority[1]) - { - if (circuit->priority[0] != DEFAULT_PRIORITY) - { - vty_out (vty, " isis priority %d\n", - circuit->priority[0]); - write++; - } - } - else - { - for (i = 0; i < 2; i++) - { - if (circuit->priority[i] != DEFAULT_PRIORITY) - { - vty_out (vty, " isis priority %d level-%d\n", - circuit->priority[i], i + 1); - write++; - } - } - } - - /* ISIS - Metric */ - if (circuit->te_metric[0] == circuit->te_metric[1]) - { - if (circuit->te_metric[0] != DEFAULT_CIRCUIT_METRIC) - { - vty_out (vty, " isis metric %d\n",circuit->te_metric[0]); - write++; - } - } - else - { - for (i = 0; i < 2; i++) - { - if (circuit->te_metric[i] != DEFAULT_CIRCUIT_METRIC) - { - vty_out (vty, " isis metric %d level-%d\n", - circuit->te_metric[i], i + 1); - write++; - } - } - } - if (circuit->passwd.type == ISIS_PASSWD_TYPE_HMAC_MD5) - { - vty_out (vty, " isis password md5 %s\n", - circuit->passwd.passwd); - write++; - } - else if (circuit->passwd.type == ISIS_PASSWD_TYPE_CLEARTXT) - { - vty_out (vty, " isis password clear %s\n", - circuit->passwd.passwd); - write++; - } - write += circuit_write_mt_settings(circuit, vty); - } - vty_out (vty, "!\n"); - } - - return write; + int write = 0; + struct listnode *node, *node2; + struct interface *ifp; + struct isis_area *area; + struct isis_circuit *circuit; + int i; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + if (ifp->ifindex == IFINDEX_DELETED) + continue; + + /* IF name */ + vty_out(vty, "interface %s\n", ifp->name); + write++; + /* IF desc */ + if (ifp->desc) { + vty_out(vty, " description %s\n", ifp->desc); + write++; + } + /* ISIS Circuit */ + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node2, area)) { + circuit = + circuit_lookup_by_ifp(ifp, area->circuit_list); + if (circuit == NULL) + continue; + if (circuit->ip_router) { + vty_out(vty, " ip router isis %s\n", + area->area_tag); + write++; + } + if (circuit->is_passive) { + vty_out(vty, " isis passive\n"); + write++; + } + if (circuit->circ_type_config == CIRCUIT_T_P2P) { + vty_out(vty, " isis network point-to-point\n"); + write++; + } + if (circuit->ipv6_router) { + vty_out(vty, " ipv6 router isis %s\n", + area->area_tag); + write++; + } + + /* ISIS - circuit type */ + if (circuit->is_type == IS_LEVEL_1) { + vty_out(vty, " isis circuit-type level-1\n"); + write++; + } else { + if (circuit->is_type == IS_LEVEL_2) { + vty_out(vty, + " isis circuit-type level-2-only\n"); + write++; + } + } + + /* ISIS - CSNP interval */ + if (circuit->csnp_interval[0] + == circuit->csnp_interval[1]) { + if (circuit->csnp_interval[0] + != DEFAULT_CSNP_INTERVAL) { + vty_out(vty, " isis csnp-interval %d\n", + circuit->csnp_interval[0]); + write++; + } + } else { + for (i = 0; i < 2; i++) { + if (circuit->csnp_interval[i] + != DEFAULT_CSNP_INTERVAL) { + vty_out(vty, + " isis csnp-interval %d level-%d\n", + circuit->csnp_interval + [i], + i + 1); + write++; + } + } + } + + /* ISIS - PSNP interval */ + if (circuit->psnp_interval[0] + == circuit->psnp_interval[1]) { + if (circuit->psnp_interval[0] + != DEFAULT_PSNP_INTERVAL) { + vty_out(vty, " isis psnp-interval %d\n", + circuit->psnp_interval[0]); + write++; + } + } else { + for (i = 0; i < 2; i++) { + if (circuit->psnp_interval[i] + != DEFAULT_PSNP_INTERVAL) { + vty_out(vty, + " isis psnp-interval %d level-%d\n", + circuit->psnp_interval + [i], + i + 1); + write++; + } + } + } + + /* ISIS - Hello padding - Defaults to true so only + * display if false */ + if (circuit->pad_hellos == 0) { + vty_out(vty, " no isis hello padding\n"); + write++; + } + + /* ISIS - Hello interval */ + if (circuit->hello_interval[0] + == circuit->hello_interval[1]) { + if (circuit->hello_interval[0] + != DEFAULT_HELLO_INTERVAL) { + vty_out(vty, + " isis hello-interval %d\n", + circuit->hello_interval[0]); + write++; + } + } else { + for (i = 0; i < 2; i++) { + if (circuit->hello_interval[i] + != DEFAULT_HELLO_INTERVAL) { + vty_out(vty, + " isis hello-interval %d level-%d\n", + circuit->hello_interval + [i], + i + 1); + write++; + } + } + } + + /* ISIS - Hello Multiplier */ + if (circuit->hello_multiplier[0] + == circuit->hello_multiplier[1]) { + if (circuit->hello_multiplier[0] + != DEFAULT_HELLO_MULTIPLIER) { + vty_out(vty, + " isis hello-multiplier %d\n", + circuit->hello_multiplier[0]); + write++; + } + } else { + for (i = 0; i < 2; i++) { + if (circuit->hello_multiplier[i] + != DEFAULT_HELLO_MULTIPLIER) { + vty_out(vty, + " isis hello-multiplier %d level-%d\n", + circuit->hello_multiplier + [i], + i + 1); + write++; + } + } + } + + /* ISIS - Priority */ + if (circuit->priority[0] == circuit->priority[1]) { + if (circuit->priority[0] != DEFAULT_PRIORITY) { + vty_out(vty, " isis priority %d\n", + circuit->priority[0]); + write++; + } + } else { + for (i = 0; i < 2; i++) { + if (circuit->priority[i] + != DEFAULT_PRIORITY) { + vty_out(vty, + " isis priority %d level-%d\n", + circuit->priority[i], + i + 1); + write++; + } + } + } + + /* ISIS - Metric */ + if (circuit->te_metric[0] == circuit->te_metric[1]) { + if (circuit->te_metric[0] + != DEFAULT_CIRCUIT_METRIC) { + vty_out(vty, " isis metric %d\n", + circuit->te_metric[0]); + write++; + } + } else { + for (i = 0; i < 2; i++) { + if (circuit->te_metric[i] + != DEFAULT_CIRCUIT_METRIC) { + vty_out(vty, + " isis metric %d level-%d\n", + circuit->te_metric[i], + i + 1); + write++; + } + } + } + if (circuit->passwd.type == ISIS_PASSWD_TYPE_HMAC_MD5) { + vty_out(vty, " isis password md5 %s\n", + circuit->passwd.passwd); + write++; + } else if (circuit->passwd.type + == ISIS_PASSWD_TYPE_CLEARTXT) { + vty_out(vty, " isis password clear %s\n", + circuit->passwd.passwd); + write++; + } + write += circuit_write_mt_settings(circuit, vty); + } + vty_out(vty, "!\n"); + } + + return write; } -struct isis_circuit * -isis_circuit_create (struct isis_area *area, struct interface *ifp) +struct isis_circuit *isis_circuit_create(struct isis_area *area, + struct interface *ifp) { - struct isis_circuit *circuit = circuit_scan_by_ifp (ifp); - if (circuit && circuit->area) - return NULL; - circuit = isis_csm_state_change (ISIS_ENABLE, circuit, area); - if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP) - return circuit; - isis_circuit_if_bind (circuit, ifp); - return circuit; + struct isis_circuit *circuit = circuit_scan_by_ifp(ifp); + if (circuit && circuit->area) + return NULL; + circuit = isis_csm_state_change(ISIS_ENABLE, circuit, area); + if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP) + return circuit; + isis_circuit_if_bind(circuit, ifp); + return circuit; } -void -isis_circuit_af_set (struct isis_circuit *circuit, bool ip_router, bool ipv6_router) +void isis_circuit_af_set(struct isis_circuit *circuit, bool ip_router, + bool ipv6_router) { - struct isis_area *area = circuit->area; - bool change = circuit->ip_router != ip_router || circuit->ipv6_router != ipv6_router; - bool was_enabled = !!circuit->area; - - area->ip_circuits += ip_router - circuit->ip_router; - area->ipv6_circuits += ipv6_router - circuit->ipv6_router; - circuit->ip_router = ip_router; - circuit->ipv6_router = ipv6_router; - - if (!change) - return; - - circuit_update_nlpids (circuit); - - if (!ip_router && !ipv6_router) - isis_csm_state_change (ISIS_DISABLE, circuit, area); - else if (!was_enabled) - isis_csm_state_change (ISIS_ENABLE, circuit, area); - else - lsp_regenerate_schedule(circuit->area, circuit->is_type, 0); + struct isis_area *area = circuit->area; + bool change = circuit->ip_router != ip_router + || circuit->ipv6_router != ipv6_router; + bool was_enabled = !!circuit->area; + + area->ip_circuits += ip_router - circuit->ip_router; + area->ipv6_circuits += ipv6_router - circuit->ipv6_router; + circuit->ip_router = ip_router; + circuit->ipv6_router = ipv6_router; + + if (!change) + return; + + circuit_update_nlpids(circuit); + + if (!ip_router && !ipv6_router) + isis_csm_state_change(ISIS_DISABLE, circuit, area); + else if (!was_enabled) + isis_csm_state_change(ISIS_ENABLE, circuit, area); + else + lsp_regenerate_schedule(circuit->area, circuit->is_type, 0); } -int -isis_circuit_passive_set (struct isis_circuit *circuit, bool passive) +int isis_circuit_passive_set(struct isis_circuit *circuit, bool passive) { - if (circuit->is_passive == passive) - return 0; - - if (if_is_loopback (circuit->interface) && !passive) - return -1; - - if (circuit->state != C_STATE_UP) - { - circuit->is_passive = passive; - } - else - { - struct isis_area *area = circuit->area; - isis_csm_state_change (ISIS_DISABLE, circuit, area); - circuit->is_passive = passive; - isis_csm_state_change (ISIS_ENABLE, circuit, area); - } - - return 0; + if (circuit->is_passive == passive) + return 0; + + if (if_is_loopback(circuit->interface) && !passive) + return -1; + + if (circuit->state != C_STATE_UP) { + circuit->is_passive = passive; + } else { + struct isis_area *area = circuit->area; + isis_csm_state_change(ISIS_DISABLE, circuit, area); + circuit->is_passive = passive; + isis_csm_state_change(ISIS_ENABLE, circuit, area); + } + + return 0; } -int -isis_circuit_metric_set (struct isis_circuit *circuit, int level, int metric) +int isis_circuit_metric_set(struct isis_circuit *circuit, int level, int metric) { - assert (level == IS_LEVEL_1 || level == IS_LEVEL_2); - if (metric > MAX_WIDE_LINK_METRIC) - return -1; - if (circuit->area && circuit->area->oldmetric - && metric > MAX_NARROW_LINK_METRIC) - return -1; - - circuit->te_metric[level - 1] = metric; - circuit->metric[level - 1] = metric; - - if (circuit->area) - lsp_regenerate_schedule (circuit->area, level, 0); - return 0; + assert(level == IS_LEVEL_1 || level == IS_LEVEL_2); + if (metric > MAX_WIDE_LINK_METRIC) + return -1; + if (circuit->area && circuit->area->oldmetric + && metric > MAX_NARROW_LINK_METRIC) + return -1; + + circuit->te_metric[level - 1] = metric; + circuit->metric[level - 1] = metric; + + if (circuit->area) + lsp_regenerate_schedule(circuit->area, level, 0); + return 0; } -int -isis_circuit_passwd_unset (struct isis_circuit *circuit) +int isis_circuit_passwd_unset(struct isis_circuit *circuit) { - memset(&circuit->passwd, 0, sizeof(circuit->passwd)); - return 0; + memset(&circuit->passwd, 0, sizeof(circuit->passwd)); + return 0; } -static int -isis_circuit_passwd_set (struct isis_circuit *circuit, u_char passwd_type, const char *passwd) +static int isis_circuit_passwd_set(struct isis_circuit *circuit, + u_char passwd_type, const char *passwd) { - int len; + int len; - if (!passwd) - return -1; + if (!passwd) + return -1; - len = strlen(passwd); - if (len > 254) - return -1; + len = strlen(passwd); + if (len > 254) + return -1; - circuit->passwd.len = len; - strncpy((char *)circuit->passwd.passwd, passwd, 255); - circuit->passwd.type = passwd_type; - return 0; + circuit->passwd.len = len; + strncpy((char *)circuit->passwd.passwd, passwd, 255); + circuit->passwd.type = passwd_type; + return 0; } -int -isis_circuit_passwd_cleartext_set (struct isis_circuit *circuit, const char *passwd) +int isis_circuit_passwd_cleartext_set(struct isis_circuit *circuit, + const char *passwd) { - return isis_circuit_passwd_set (circuit, ISIS_PASSWD_TYPE_CLEARTXT, passwd); + return isis_circuit_passwd_set(circuit, ISIS_PASSWD_TYPE_CLEARTXT, + passwd); } -int -isis_circuit_passwd_hmac_md5_set (struct isis_circuit *circuit, const char *passwd) +int isis_circuit_passwd_hmac_md5_set(struct isis_circuit *circuit, + const char *passwd) { - return isis_circuit_passwd_set (circuit, ISIS_PASSWD_TYPE_HMAC_MD5, passwd); + return isis_circuit_passwd_set(circuit, ISIS_PASSWD_TYPE_HMAC_MD5, + passwd); } struct cmd_node interface_node = { - INTERFACE_NODE, - "%s(config-if)# ", - 1, + INTERFACE_NODE, "%s(config-if)# ", 1, }; -int -isis_circuit_circ_type_set(struct isis_circuit *circuit, int circ_type) +int isis_circuit_circ_type_set(struct isis_circuit *circuit, int circ_type) { - /* Changing the network type to/of loopback or unknown interfaces - * is not supported. */ - if (circ_type == CIRCUIT_T_UNKNOWN - || circ_type == CIRCUIT_T_LOOPBACK - || circuit->circ_type == CIRCUIT_T_LOOPBACK) - { - if (circuit->circ_type != circ_type) - return -1; - else - return 0; - } - - if (circuit->circ_type == circ_type) - return 0; - - if (circuit->state != C_STATE_UP) - { - circuit->circ_type = circ_type; - circuit->circ_type_config = circ_type; - } - else - { - struct isis_area *area = circuit->area; - if (circ_type == CIRCUIT_T_BROADCAST - && !if_is_broadcast(circuit->interface)) - return -1; - - isis_csm_state_change(ISIS_DISABLE, circuit, area); - circuit->circ_type = circ_type; - circuit->circ_type_config = circ_type; - isis_csm_state_change(ISIS_ENABLE, circuit, area); - } - return 0; + /* Changing the network type to/of loopback or unknown interfaces + * is not supported. */ + if (circ_type == CIRCUIT_T_UNKNOWN || circ_type == CIRCUIT_T_LOOPBACK + || circuit->circ_type == CIRCUIT_T_LOOPBACK) { + if (circuit->circ_type != circ_type) + return -1; + else + return 0; + } + + if (circuit->circ_type == circ_type) + return 0; + + if (circuit->state != C_STATE_UP) { + circuit->circ_type = circ_type; + circuit->circ_type_config = circ_type; + } else { + struct isis_area *area = circuit->area; + if (circ_type == CIRCUIT_T_BROADCAST + && !if_is_broadcast(circuit->interface)) + return -1; + + isis_csm_state_change(ISIS_DISABLE, circuit, area); + circuit->circ_type = circ_type; + circuit->circ_type_config = circ_type; + isis_csm_state_change(ISIS_ENABLE, circuit, area); + } + return 0; } -int -isis_circuit_mt_enabled_set (struct isis_circuit *circuit, uint16_t mtid, - bool enabled) +int isis_circuit_mt_enabled_set(struct isis_circuit *circuit, uint16_t mtid, + bool enabled) { - struct isis_circuit_mt_setting *setting; + struct isis_circuit_mt_setting *setting; - setting = circuit_get_mt_setting(circuit, mtid); - if (setting->enabled != enabled) - { - setting->enabled = enabled; - lsp_regenerate_schedule (circuit->area, IS_LEVEL_1 | IS_LEVEL_2, 0); - } + setting = circuit_get_mt_setting(circuit, mtid); + if (setting->enabled != enabled) { + setting->enabled = enabled; + lsp_regenerate_schedule(circuit->area, IS_LEVEL_1 | IS_LEVEL_2, + 0); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } -int -isis_if_new_hook (struct interface *ifp) +int isis_if_new_hook(struct interface *ifp) { - return 0; + return 0; } -int -isis_if_delete_hook (struct interface *ifp) +int isis_if_delete_hook(struct interface *ifp) { - struct isis_circuit *circuit; - /* Clean up the circuit data */ - if (ifp && ifp->info) - { - circuit = ifp->info; - isis_csm_state_change (IF_DOWN_FROM_Z, circuit, circuit->area); - isis_csm_state_change (ISIS_DISABLE, circuit, circuit->area); - } - - return 0; + struct isis_circuit *circuit; + /* Clean up the circuit data */ + if (ifp && ifp->info) { + circuit = ifp->info; + isis_csm_state_change(IF_DOWN_FROM_Z, circuit, circuit->area); + isis_csm_state_change(ISIS_DISABLE, circuit, circuit->area); + } + + return 0; } -void -isis_circuit_init () +void isis_circuit_init() { - /* Initialize Zebra interface data structure */ - if_add_hook (IF_NEW_HOOK, isis_if_new_hook); - if_add_hook (IF_DELETE_HOOK, isis_if_delete_hook); + /* Initialize Zebra interface data structure */ + if_add_hook(IF_NEW_HOOK, isis_if_new_hook); + if_add_hook(IF_DELETE_HOOK, isis_if_delete_hook); - /* Install interface node */ - install_node (&interface_node, isis_interface_config_write); - if_cmd_init (); + /* Install interface node */ + install_node(&interface_node, isis_interface_config_write); + if_cmd_init(); - isis_vty_init (); + isis_vty_init(); } diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h index 82ca7ca0d..5e523cd68 100644 --- a/isisd/isis_circuit.h +++ b/isisd/isis_circuit.h @@ -2,17 +2,17 @@ * IS-IS Rout(e)ing protocol - isis_circuit.h * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -32,162 +32,165 @@ #define CIRCUIT_MAX 255 -struct password -{ - struct password *next; - int len; - u_char *pass; +struct password { + struct password *next; + int len; + u_char *pass; }; -struct metric -{ - u_char metric_default; - u_char metric_error; - u_char metric_expense; - u_char metric_delay; +struct metric { + u_char metric_default; + u_char metric_error; + u_char metric_expense; + u_char metric_delay; }; -struct isis_bcast_info -{ - u_char snpa[ETH_ALEN]; /* SNPA of this circuit */ - char run_dr_elect[2]; /* Should we run dr election ? */ - struct thread *t_run_dr[2]; /* DR election thread */ - struct thread *t_send_lan_hello[2]; /* send LAN IIHs in this thread */ - struct list *adjdb[2]; /* adjacency dbs */ - struct list *lan_neighs[2]; /* list of lx neigh snpa */ - char is_dr[2]; /* Are we level x DR ? */ - u_char l1_desig_is[ISIS_SYS_ID_LEN + 1]; /* level-1 DR */ - u_char l2_desig_is[ISIS_SYS_ID_LEN + 1]; /* level-2 DR */ - struct thread *t_refresh_pseudo_lsp[2]; /* refresh pseudo-node LSPs */ +struct isis_bcast_info { + u_char snpa[ETH_ALEN]; /* SNPA of this circuit */ + char run_dr_elect[2]; /* Should we run dr election ? */ + struct thread *t_run_dr[2]; /* DR election thread */ + struct thread *t_send_lan_hello[2]; /* send LAN IIHs in this thread */ + struct list *adjdb[2]; /* adjacency dbs */ + struct list *lan_neighs[2]; /* list of lx neigh snpa */ + char is_dr[2]; /* Are we level x DR ? */ + u_char l1_desig_is[ISIS_SYS_ID_LEN + 1]; /* level-1 DR */ + u_char l2_desig_is[ISIS_SYS_ID_LEN + 1]; /* level-2 DR */ + struct thread *t_refresh_pseudo_lsp[2]; /* refresh pseudo-node LSPs */ }; -struct isis_p2p_info -{ - struct isis_adjacency *neighbor; - struct thread *t_send_p2p_hello; /* send P2P IIHs in this thread */ +struct isis_p2p_info { + struct isis_adjacency *neighbor; + struct thread *t_send_p2p_hello; /* send P2P IIHs in this thread */ }; -struct isis_circuit -{ - int state; - u_char circuit_id; /* l1/l2 p2p/bcast CircuitID */ - struct isis_area *area; /* back pointer to the area */ - struct interface *interface; /* interface info from z */ - int fd; /* IS-IS l1/2 socket */ - int sap_length; /* SAP length for DLPI */ - struct nlpids nlpids; - /* - * Threads - */ - struct thread *t_read; - struct thread *t_send_csnp[2]; - struct thread *t_send_psnp[2]; - struct list *lsp_queue; /* LSPs to be txed (both levels) */ - time_t lsp_queue_last_cleared;/* timestamp used to enforce transmit interval; - * for scalability, use one timestamp per - * circuit, instead of one per lsp per circuit - */ - /* there is no real point in two streams, just for programming kicker */ - int (*rx) (struct isis_circuit * circuit, u_char * ssnpa); - struct stream *rcv_stream; /* Stream for receiving */ - int (*tx) (struct isis_circuit * circuit, int level); - struct stream *snd_stream; /* Stream for sending */ - int idx; /* idx in S[RM|SN] flags */ +struct isis_circuit { + int state; + u_char circuit_id; /* l1/l2 p2p/bcast CircuitID */ + struct isis_area *area; /* back pointer to the area */ + struct interface *interface; /* interface info from z */ + int fd; /* IS-IS l1/2 socket */ + int sap_length; /* SAP length for DLPI */ + struct nlpids nlpids; + /* + * Threads + */ + struct thread *t_read; + struct thread *t_send_csnp[2]; + struct thread *t_send_psnp[2]; + struct list *lsp_queue; /* LSPs to be txed (both levels) */ + time_t lsp_queue_last_cleared; /* timestamp used to enforce transmit + * interval; + * for scalability, use one timestamp per + * circuit, instead of one per lsp per + * circuit + */ + /* there is no real point in two streams, just for programming kicker */ + int (*rx)(struct isis_circuit *circuit, u_char *ssnpa); + struct stream *rcv_stream; /* Stream for receiving */ + int (*tx)(struct isis_circuit *circuit, int level); + struct stream *snd_stream; /* Stream for sending */ + int idx; /* idx in S[RM|SN] flags */ + /* $FRR indent$ */ + /* clang-format off */ #define CIRCUIT_T_UNKNOWN 0 #define CIRCUIT_T_BROADCAST 1 #define CIRCUIT_T_P2P 2 #define CIRCUIT_T_LOOPBACK 3 - int circ_type; /* type of the physical interface */ - int circ_type_config; /* config type of the physical interface */ - union - { - struct isis_bcast_info bc; - struct isis_p2p_info p2p; - } u; - u_char priority[2]; /* l1/2 IS configured priority */ - int pad_hellos; /* add padding to Hello PDUs ? */ - char ext_domain; /* externalDomain (boolean) */ - int lsp_regenerate_pending[ISIS_LEVELS]; - /* - * Configurables - */ - struct isis_passwd passwd; /* Circuit rx/tx password */ - int is_type; /* circuit is type == level of circuit - * differentiated from circuit type (media) */ - u_int32_t hello_interval[2]; /* l1HelloInterval in msecs */ - u_int16_t hello_multiplier[2]; /* l1HelloMultiplier */ - u_int16_t csnp_interval[2]; /* level-1 csnp-interval in seconds */ - u_int16_t psnp_interval[2]; /* level-1 psnp-interval in seconds */ - u_int8_t metric[2]; - u_int32_t te_metric[2]; - struct mpls_te_circuit *mtc; /* Support for MPLS-TE parameters - see isis_te.[c,h] */ - int ip_router; /* Route IP ? */ - int is_passive; /* Is Passive ? */ - struct list *mt_settings; /* IS-IS MT Settings */ - struct list *ip_addrs; /* our IP addresses */ - int ipv6_router; /* Route IPv6 ? */ - struct list *ipv6_link; /* our link local IPv6 addresses */ - struct list *ipv6_non_link; /* our non-link local IPv6 addresses */ - u_int16_t upadjcount[2]; + int circ_type; /* type of the physical interface */ + int circ_type_config; /* config type of the physical interface */ + union { + struct isis_bcast_info bc; + struct isis_p2p_info p2p; + } u; + u_char priority[2]; /* l1/2 IS configured priority */ + int pad_hellos; /* add padding to Hello PDUs ? */ + char ext_domain; /* externalDomain (boolean) */ + int lsp_regenerate_pending[ISIS_LEVELS]; + /* + * Configurables + */ + struct isis_passwd passwd; /* Circuit rx/tx password */ + int is_type; /* circuit is type == level of circuit + * differentiated from circuit type (media) */ + u_int32_t hello_interval[2]; /* l1HelloInterval in msecs */ + u_int16_t hello_multiplier[2]; /* l1HelloMultiplier */ + u_int16_t csnp_interval[2]; /* level-1 csnp-interval in seconds */ + u_int16_t psnp_interval[2]; /* level-1 psnp-interval in seconds */ + u_int8_t metric[2]; + u_int32_t te_metric[2]; + struct mpls_te_circuit + *mtc; /* Support for MPLS-TE parameters - see isis_te.[c,h] */ + int ip_router; /* Route IP ? */ + int is_passive; /* Is Passive ? */ + struct list *mt_settings; /* IS-IS MT Settings */ + struct list *ip_addrs; /* our IP addresses */ + int ipv6_router; /* Route IPv6 ? */ + struct list *ipv6_link; /* our link local IPv6 addresses */ + struct list *ipv6_non_link; /* our non-link local IPv6 addresses */ + u_int16_t upadjcount[2]; #define ISIS_CIRCUIT_FLAPPED_AFTER_SPF 0x01 - u_char flags; - /* - * Counters as in 10589--11.2.5.9 - */ - u_int32_t adj_state_changes; /* changesInAdjacencyState */ - u_int32_t init_failures; /* intialisationFailures */ - u_int32_t ctrl_pdus_rxed; /* controlPDUsReceived */ - u_int32_t ctrl_pdus_txed; /* controlPDUsSent */ - u_int32_t desig_changes[2]; /* lanLxDesignatedIntermediateSystemChanges */ - u_int32_t rej_adjacencies; /* rejectedAdjacencies */ - - QOBJ_FIELDS + u_char flags; + /* + * Counters as in 10589--11.2.5.9 + */ + u_int32_t adj_state_changes; /* changesInAdjacencyState */ + u_int32_t init_failures; /* intialisationFailures */ + u_int32_t ctrl_pdus_rxed; /* controlPDUsReceived */ + u_int32_t ctrl_pdus_txed; /* controlPDUsSent */ + u_int32_t + desig_changes[2]; /* lanLxDesignatedIntermediateSystemChanges */ + u_int32_t rej_adjacencies; /* rejectedAdjacencies */ + + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(isis_circuit) -void isis_circuit_init (void); -struct isis_circuit *isis_circuit_new (void); -void isis_circuit_del (struct isis_circuit *circuit); -struct isis_circuit *circuit_lookup_by_ifp (struct interface *ifp, - struct list *list); -struct isis_circuit *circuit_scan_by_ifp (struct interface *ifp); -void isis_circuit_configure (struct isis_circuit *circuit, - struct isis_area *area); -void isis_circuit_deconfigure (struct isis_circuit *circuit, - struct isis_area *area); -void isis_circuit_if_add (struct isis_circuit *circuit, - struct interface *ifp); -void isis_circuit_if_del (struct isis_circuit *circuit, - struct interface *ifp); -void isis_circuit_if_bind (struct isis_circuit *circuit, - struct interface *ifp); -void isis_circuit_if_unbind (struct isis_circuit *circuit, - struct interface *ifp); -void isis_circuit_add_addr (struct isis_circuit *circuit, - struct connected *conn); -void isis_circuit_del_addr (struct isis_circuit *circuit, - struct connected *conn); -void isis_circuit_prepare (struct isis_circuit *circuit); -int isis_circuit_up (struct isis_circuit *circuit); -void isis_circuit_down (struct isis_circuit *); -void circuit_update_nlpids (struct isis_circuit *circuit); -void isis_circuit_print_vty (struct isis_circuit *circuit, struct vty *vty, - char detail); +void isis_circuit_init(void); +struct isis_circuit *isis_circuit_new(void); +void isis_circuit_del(struct isis_circuit *circuit); +struct isis_circuit *circuit_lookup_by_ifp(struct interface *ifp, + struct list *list); +struct isis_circuit *circuit_scan_by_ifp(struct interface *ifp); +void isis_circuit_configure(struct isis_circuit *circuit, + struct isis_area *area); +void isis_circuit_deconfigure(struct isis_circuit *circuit, + struct isis_area *area); +void isis_circuit_if_add(struct isis_circuit *circuit, struct interface *ifp); +void isis_circuit_if_del(struct isis_circuit *circuit, struct interface *ifp); +void isis_circuit_if_bind(struct isis_circuit *circuit, struct interface *ifp); +void isis_circuit_if_unbind(struct isis_circuit *circuit, + struct interface *ifp); +void isis_circuit_add_addr(struct isis_circuit *circuit, + struct connected *conn); +void isis_circuit_del_addr(struct isis_circuit *circuit, + struct connected *conn); +void isis_circuit_prepare(struct isis_circuit *circuit); +int isis_circuit_up(struct isis_circuit *circuit); +void isis_circuit_down(struct isis_circuit *); +void circuit_update_nlpids(struct isis_circuit *circuit); +void isis_circuit_print_vty(struct isis_circuit *circuit, struct vty *vty, + char detail); size_t isis_circuit_pdu_size(struct isis_circuit *circuit); void isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream); -struct isis_circuit *isis_circuit_create (struct isis_area *area, struct interface *ifp); -void isis_circuit_af_set (struct isis_circuit *circuit, bool ip_router, bool ipv6_router); -int isis_circuit_passive_set (struct isis_circuit *circuit, bool passive); -void isis_circuit_is_type_set (struct isis_circuit *circuit, int is_type); -int isis_circuit_circ_type_set (struct isis_circuit *circuit, int circ_type); - -int isis_circuit_metric_set (struct isis_circuit *circuit, int level, int metric); - -int isis_circuit_passwd_unset (struct isis_circuit *circuit); -int isis_circuit_passwd_cleartext_set (struct isis_circuit *circuit, const char *passwd); -int isis_circuit_passwd_hmac_md5_set (struct isis_circuit *circuit, const char *passwd); - -int isis_circuit_mt_enabled_set (struct isis_circuit *circuit, uint16_t mtid, bool enabled); +struct isis_circuit *isis_circuit_create(struct isis_area *area, + struct interface *ifp); +void isis_circuit_af_set(struct isis_circuit *circuit, bool ip_router, + bool ipv6_router); +int isis_circuit_passive_set(struct isis_circuit *circuit, bool passive); +void isis_circuit_is_type_set(struct isis_circuit *circuit, int is_type); +int isis_circuit_circ_type_set(struct isis_circuit *circuit, int circ_type); + +int isis_circuit_metric_set(struct isis_circuit *circuit, int level, + int metric); + +int isis_circuit_passwd_unset(struct isis_circuit *circuit); +int isis_circuit_passwd_cleartext_set(struct isis_circuit *circuit, + const char *passwd); +int isis_circuit_passwd_hmac_md5_set(struct isis_circuit *circuit, + const char *passwd); + +int isis_circuit_mt_enabled_set(struct isis_circuit *circuit, uint16_t mtid, + bool enabled); #endif /* _ZEBRA_ISIS_CIRCUIT_H */ diff --git a/isisd/isis_common.h b/isisd/isis_common.h index 6c827115b..ba6c5f876 100644 --- a/isisd/isis_common.h +++ b/isisd/isis_common.h @@ -1,19 +1,19 @@ /* - * IS-IS Rout(e)ing protocol - isis_common.h + * IS-IS Rout(e)ing protocol - isis_common.h * some common data structures * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -27,25 +27,23 @@ /* * Area Address */ -struct area_addr -{ - u_char addr_len; - u_char area_addr[20]; +struct area_addr { + u_char addr_len; + u_char area_addr[20]; }; -struct isis_passwd -{ - u_char len; +struct isis_passwd { + u_char len; #define ISIS_PASSWD_TYPE_UNUSED 0 #define ISIS_PASSWD_TYPE_CLEARTXT 1 #define ISIS_PASSWD_TYPE_HMAC_MD5 54 #define ISIS_PASSWD_TYPE_PRIVATE 255 - u_char type; - /* Authenticate SNPs? */ + u_char type; +/* Authenticate SNPs? */ #define SNP_AUTH_SEND 0x01 #define SNP_AUTH_RECV 0x02 - u_char snp_auth; - u_char passwd[255]; + u_char snp_auth; + u_char passwd[255]; }; /* @@ -53,19 +51,17 @@ struct isis_passwd * one struct for cache list * one struct for LSP TLV */ -struct hostname -{ - u_char namelen; - u_char name[255]; +struct hostname { + u_char namelen; + u_char name[255]; }; /* * Supported Protocol IDs */ -struct nlpids -{ - u_char count; - u_char nlpids[4]; /* FIXME: enough ? */ +struct nlpids { + u_char count; + u_char nlpids[4]; /* FIXME: enough ? */ }; #endif diff --git a/isisd/isis_constants.h b/isisd/isis_constants.h index b59d77bf3..4b5ff888b 100644 --- a/isisd/isis_constants.h +++ b/isisd/isis_constants.h @@ -1,18 +1,18 @@ /* - * IS-IS Rout(e)ing protocol - isis_constants.h + * IS-IS Rout(e)ing protocol - isis_constants.h * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -163,9 +163,9 @@ /* we need to be aware of the fact we are using ISO sized * packets, using isomtu = mtu - LLC_LEN */ -#define ISO_MTU(C) \ - ((if_is_broadcast ((C)->interface)) ? \ - (C->interface->mtu - LLC_LEN) : (C->interface->mtu)) +#define ISO_MTU(C) \ + ((if_is_broadcast((C)->interface)) ? (C->interface->mtu - LLC_LEN) \ + : (C->interface->mtu)) #ifndef ETH_ALEN #define ETH_ALEN 6 @@ -176,9 +176,9 @@ static inline uint16_t isis_ethertype(size_t len) { - if (len > MAX_LLC_LEN) - return ETHERTYPE_EXT_LLC; - return len; + if (len > MAX_LLC_LEN) + return ETHERTYPE_EXT_LLC; + return len; } #endif /* ISIS_CONSTANTS_H */ diff --git a/isisd/isis_csm.c b/isisd/isis_csm.c index 90272d68b..b0ccdee76 100644 --- a/isisd/isis_csm.c +++ b/isisd/isis_csm.c @@ -2,17 +2,17 @@ * IS-IS Rout(e)ing protocol - isis_csm.c * IS-IS circuit state machine * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -51,169 +51,165 @@ extern struct isis *isis; -static const char *csm_statestr[] = { - "C_STATE_NA", - "C_STATE_INIT", - "C_STATE_CONF", - "C_STATE_UP" -}; +static const char *csm_statestr[] = {"C_STATE_NA", "C_STATE_INIT", + "C_STATE_CONF", "C_STATE_UP"}; #define STATE2STR(S) csm_statestr[S] static const char *csm_eventstr[] = { - "NO_STATE", - "ISIS_ENABLE", - "IF_UP_FROM_Z", - "ISIS_DISABLE", - "IF_DOWN_FROM_Z", + "NO_STATE", "ISIS_ENABLE", "IF_UP_FROM_Z", + "ISIS_DISABLE", "IF_DOWN_FROM_Z", }; #define EVENT2STR(E) csm_eventstr[E] struct isis_circuit * -isis_csm_state_change (int event, struct isis_circuit *circuit, void *arg) +isis_csm_state_change(int event, struct isis_circuit *circuit, void *arg) { - int old_state; + int old_state; - old_state = circuit ? circuit->state : C_STATE_NA; - if (isis->debugs & DEBUG_EVENTS) - zlog_debug ("CSM_EVENT: %s", EVENT2STR (event)); + old_state = circuit ? circuit->state : C_STATE_NA; + if (isis->debugs & DEBUG_EVENTS) + zlog_debug("CSM_EVENT: %s", EVENT2STR(event)); - switch (old_state) - { - case C_STATE_NA: - if (circuit) - zlog_warn ("Non-null circuit while state C_STATE_NA"); - assert (circuit == NULL); - switch (event) - { - case ISIS_ENABLE: - circuit = isis_circuit_new (); - isis_circuit_configure (circuit, (struct isis_area *) arg); - circuit->state = C_STATE_CONF; - break; - case IF_UP_FROM_Z: - circuit = isis_circuit_new (); - isis_circuit_if_add (circuit, (struct interface *) arg); - listnode_add (isis->init_circ_list, circuit); - circuit->state = C_STATE_INIT; - break; - case ISIS_DISABLE: - zlog_warn ("circuit already disabled"); - break; - case IF_DOWN_FROM_Z: - zlog_warn ("circuit already disconnected"); - break; - } - break; - case C_STATE_INIT: - assert (circuit); - switch (event) - { - case ISIS_ENABLE: - isis_circuit_configure (circuit, (struct isis_area *) arg); - if (isis_circuit_up (circuit) != ISIS_OK) - { - isis_circuit_deconfigure (circuit, (struct isis_area *) arg); - break; - } - circuit->state = C_STATE_UP; - isis_event_circuit_state_change (circuit, circuit->area, 1); - listnode_delete (isis->init_circ_list, circuit); - break; - case IF_UP_FROM_Z: - assert (circuit); - zlog_warn ("circuit already connected"); - break; - case ISIS_DISABLE: - zlog_warn ("circuit already disabled"); - break; - case IF_DOWN_FROM_Z: - isis_circuit_if_del (circuit, (struct interface *) arg); - listnode_delete (isis->init_circ_list, circuit); - isis_circuit_del (circuit); - circuit = NULL; - break; - } - break; - case C_STATE_CONF: - assert (circuit); - switch (event) - { - case ISIS_ENABLE: - zlog_warn ("circuit already enabled"); - break; - case IF_UP_FROM_Z: - isis_circuit_if_add (circuit, (struct interface *) arg); - if (isis_circuit_up (circuit) != ISIS_OK) - { - zlog_err("Could not bring up %s because of invalid config.", - circuit->interface->name); - zlog_err("Clearing config for %s. Please re-examine it.", - circuit->interface->name); - if (circuit->ip_router) - { - circuit->ip_router = 0; - circuit->area->ip_circuits--; - } - if (circuit->ipv6_router) - { - circuit->ipv6_router = 0; - circuit->area->ipv6_circuits--; - } - circuit_update_nlpids(circuit); - isis_circuit_deconfigure(circuit, circuit->area); - listnode_add (isis->init_circ_list, circuit); - circuit->state = C_STATE_INIT; - break; - } - circuit->state = C_STATE_UP; - isis_event_circuit_state_change (circuit, circuit->area, 1); - break; - case ISIS_DISABLE: - isis_circuit_deconfigure (circuit, (struct isis_area *) arg); - isis_circuit_del (circuit); - circuit = NULL; - break; - case IF_DOWN_FROM_Z: - zlog_warn ("circuit already disconnected"); - break; - } - break; - case C_STATE_UP: - assert (circuit); - switch (event) - { - case ISIS_ENABLE: - zlog_warn ("circuit already configured"); - break; - case IF_UP_FROM_Z: - zlog_warn ("circuit already connected"); - break; - case ISIS_DISABLE: - isis_circuit_down (circuit); - isis_circuit_deconfigure (circuit, (struct isis_area *) arg); - circuit->state = C_STATE_INIT; - isis_event_circuit_state_change (circuit, - (struct isis_area *)arg, 0); - listnode_add (isis->init_circ_list, circuit); - break; - case IF_DOWN_FROM_Z: - isis_circuit_down (circuit); - isis_circuit_if_del (circuit, (struct interface *) arg); - circuit->state = C_STATE_CONF; - isis_event_circuit_state_change (circuit, circuit->area, 0); - break; - } - break; + switch (old_state) { + case C_STATE_NA: + if (circuit) + zlog_warn("Non-null circuit while state C_STATE_NA"); + assert(circuit == NULL); + switch (event) { + case ISIS_ENABLE: + circuit = isis_circuit_new(); + isis_circuit_configure(circuit, + (struct isis_area *)arg); + circuit->state = C_STATE_CONF; + break; + case IF_UP_FROM_Z: + circuit = isis_circuit_new(); + isis_circuit_if_add(circuit, (struct interface *)arg); + listnode_add(isis->init_circ_list, circuit); + circuit->state = C_STATE_INIT; + break; + case ISIS_DISABLE: + zlog_warn("circuit already disabled"); + break; + case IF_DOWN_FROM_Z: + zlog_warn("circuit already disconnected"); + break; + } + break; + case C_STATE_INIT: + assert(circuit); + switch (event) { + case ISIS_ENABLE: + isis_circuit_configure(circuit, + (struct isis_area *)arg); + if (isis_circuit_up(circuit) != ISIS_OK) { + isis_circuit_deconfigure( + circuit, (struct isis_area *)arg); + break; + } + circuit->state = C_STATE_UP; + isis_event_circuit_state_change(circuit, circuit->area, + 1); + listnode_delete(isis->init_circ_list, circuit); + break; + case IF_UP_FROM_Z: + assert(circuit); + zlog_warn("circuit already connected"); + break; + case ISIS_DISABLE: + zlog_warn("circuit already disabled"); + break; + case IF_DOWN_FROM_Z: + isis_circuit_if_del(circuit, (struct interface *)arg); + listnode_delete(isis->init_circ_list, circuit); + isis_circuit_del(circuit); + circuit = NULL; + break; + } + break; + case C_STATE_CONF: + assert(circuit); + switch (event) { + case ISIS_ENABLE: + zlog_warn("circuit already enabled"); + break; + case IF_UP_FROM_Z: + isis_circuit_if_add(circuit, (struct interface *)arg); + if (isis_circuit_up(circuit) != ISIS_OK) { + zlog_err( + "Could not bring up %s because of invalid config.", + circuit->interface->name); + zlog_err( + "Clearing config for %s. Please re-examine it.", + circuit->interface->name); + if (circuit->ip_router) { + circuit->ip_router = 0; + circuit->area->ip_circuits--; + } + if (circuit->ipv6_router) { + circuit->ipv6_router = 0; + circuit->area->ipv6_circuits--; + } + circuit_update_nlpids(circuit); + isis_circuit_deconfigure(circuit, + circuit->area); + listnode_add(isis->init_circ_list, circuit); + circuit->state = C_STATE_INIT; + break; + } + circuit->state = C_STATE_UP; + isis_event_circuit_state_change(circuit, circuit->area, + 1); + break; + case ISIS_DISABLE: + isis_circuit_deconfigure(circuit, + (struct isis_area *)arg); + isis_circuit_del(circuit); + circuit = NULL; + break; + case IF_DOWN_FROM_Z: + zlog_warn("circuit already disconnected"); + break; + } + break; + case C_STATE_UP: + assert(circuit); + switch (event) { + case ISIS_ENABLE: + zlog_warn("circuit already configured"); + break; + case IF_UP_FROM_Z: + zlog_warn("circuit already connected"); + break; + case ISIS_DISABLE: + isis_circuit_down(circuit); + isis_circuit_deconfigure(circuit, + (struct isis_area *)arg); + circuit->state = C_STATE_INIT; + isis_event_circuit_state_change( + circuit, (struct isis_area *)arg, 0); + listnode_add(isis->init_circ_list, circuit); + break; + case IF_DOWN_FROM_Z: + isis_circuit_down(circuit); + isis_circuit_if_del(circuit, (struct interface *)arg); + circuit->state = C_STATE_CONF; + isis_event_circuit_state_change(circuit, circuit->area, + 0); + break; + } + break; - default: - zlog_warn ("Invalid circuit state %d", old_state); - } + default: + zlog_warn("Invalid circuit state %d", old_state); + } - if (isis->debugs & DEBUG_EVENTS) - zlog_debug ("CSM_STATE_CHANGE: %s -> %s ", STATE2STR (old_state), - circuit ? STATE2STR (circuit->state) : STATE2STR (C_STATE_NA)); + if (isis->debugs & DEBUG_EVENTS) + zlog_debug("CSM_STATE_CHANGE: %s -> %s ", STATE2STR(old_state), + circuit ? STATE2STR(circuit->state) + : STATE2STR(C_STATE_NA)); - return circuit; + return circuit; } diff --git a/isisd/isis_csm.h b/isisd/isis_csm.h index a1e0f234f..53a5f9d5d 100644 --- a/isisd/isis_csm.h +++ b/isisd/isis_csm.h @@ -3,18 +3,18 @@ * IS-IS circuit state machine * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -40,8 +40,7 @@ #define ISIS_DISABLE 3 #define IF_DOWN_FROM_Z 4 -struct isis_circuit *isis_csm_state_change (int event, - struct isis_circuit *circuit, - void *arg); +struct isis_circuit * +isis_csm_state_change(int event, struct isis_circuit *circuit, void *arg); #endif /* _ZEBRA_ISIS_CSM_H */ diff --git a/isisd/isis_dlpi.c b/isisd/isis_dlpi.c index afd8a14f9..7ac8b54fa 100644 --- a/isisd/isis_dlpi.c +++ b/isisd/isis_dlpi.c @@ -2,17 +2,17 @@ * IS-IS Rout(e)ing protocol - isis_dlpi.c * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -49,37 +49,36 @@ extern struct zebra_privs_t isisd_privs; -static t_uscalar_t dlpi_ctl[1024]; /* DLPI control messages */ +static t_uscalar_t dlpi_ctl[1024]; /* DLPI control messages */ /* * Table 9 - Architectural constants for use with ISO 8802 subnetworks * ISO 10589 - 8.4.8 */ -u_char ALL_L1_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x14 }; -u_char ALL_L2_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x15 }; -u_char ALL_ISS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x05 }; -u_char ALL_ESS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x04 }; +u_char ALL_L1_ISS[6] = {0x01, 0x80, 0xC2, 0x00, 0x00, 0x14}; +u_char ALL_L2_ISS[6] = {0x01, 0x80, 0xC2, 0x00, 0x00, 0x15}; +u_char ALL_ISS[6] = {0x09, 0x00, 0x2B, 0x00, 0x00, 0x05}; +u_char ALL_ESS[6] = {0x09, 0x00, 0x2B, 0x00, 0x00, 0x04}; static u_char sock_buff[8192]; -static u_short pf_filter[] = -{ - ENF_PUSHWORD + 0, /* Get the SSAP/DSAP values */ - ENF_PUSHLIT | ENF_CAND, /* Check them */ - ISO_SAP | (ISO_SAP << 8), - ENF_PUSHWORD + 1, /* Get the control value */ - ENF_PUSHLIT | ENF_AND, /* Isolate it */ +static u_short pf_filter[] = { + ENF_PUSHWORD + 0, /* Get the SSAP/DSAP values */ + ENF_PUSHLIT | ENF_CAND, /* Check them */ + ISO_SAP | (ISO_SAP << 8), + ENF_PUSHWORD + 1, /* Get the control value */ + ENF_PUSHLIT | ENF_AND, /* Isolate it */ #ifdef _BIG_ENDIAN - 0xFF00, + 0xFF00, #else - 0x00FF, + 0x00FF, #endif - ENF_PUSHLIT | ENF_CAND, /* Test for expected value */ + ENF_PUSHLIT | ENF_CAND, /* Test for expected value */ #ifdef _BIG_ENDIAN - 0x0300 + 0x0300 #else - 0x0003 + 0x0003 #endif }; @@ -90,564 +89,530 @@ static u_short pf_filter[] = * interfaces plus the (optional; not needed) Solaris packet filter module. */ -static int -dlpisend (int fd, const void *cbuf, size_t cbuflen, - const void *dbuf, size_t dbuflen, int flags) +static int dlpisend(int fd, const void *cbuf, size_t cbuflen, const void *dbuf, + size_t dbuflen, int flags) { - const struct strbuf *ctlptr = NULL; - const struct strbuf *dataptr = NULL; - struct strbuf ctlbuf, databuf; - int rv; - - if (cbuf != NULL) - { - memset (&ctlbuf, 0, sizeof (ctlbuf)); - ctlbuf.len = cbuflen; - ctlbuf.buf = (void *)cbuf; - ctlptr = &ctlbuf; - } - - if (dbuf != NULL) - { - memset (&databuf, 0, sizeof (databuf)); - databuf.len = dbuflen; - databuf.buf = (void *)dbuf; - dataptr = &databuf; - } - - /* We assume this doesn't happen often and isn't operationally significant */ - rv = putmsg(fd, ctlptr, dataptr, flags); - if (rv == -1 && dbuf == NULL) - { - /* - * For actual PDU transmission - recognizable buf dbuf != NULL, - * the error is passed upwards and should not be printed here. - */ - zlog_debug ("%s: putmsg: %s", __func__, safe_strerror (errno)); - } - return rv; + const struct strbuf *ctlptr = NULL; + const struct strbuf *dataptr = NULL; + struct strbuf ctlbuf, databuf; + int rv; + + if (cbuf != NULL) { + memset(&ctlbuf, 0, sizeof(ctlbuf)); + ctlbuf.len = cbuflen; + ctlbuf.buf = (void *)cbuf; + ctlptr = &ctlbuf; + } + + if (dbuf != NULL) { + memset(&databuf, 0, sizeof(databuf)); + databuf.len = dbuflen; + databuf.buf = (void *)dbuf; + dataptr = &databuf; + } + + /* We assume this doesn't happen often and isn't operationally + * significant */ + rv = putmsg(fd, ctlptr, dataptr, flags); + if (rv == -1 && dbuf == NULL) { + /* + * For actual PDU transmission - recognizable buf dbuf != NULL, + * the error is passed upwards and should not be printed here. + */ + zlog_debug("%s: putmsg: %s", __func__, safe_strerror(errno)); + } + return rv; } -static ssize_t -dlpirctl (int fd) +static ssize_t dlpirctl(int fd) { - struct pollfd fds[1]; - struct strbuf ctlbuf, databuf; - int flags, retv; - - do - { - /* Poll is used here in case the device doesn't speak DLPI correctly */ - memset (fds, 0, sizeof (fds)); - fds[0].fd = fd; - fds[0].events = POLLIN | POLLPRI; - if (poll (fds, 1, 1000) <= 0) - return -1; - - memset (&ctlbuf, 0, sizeof (ctlbuf)); - memset (&databuf, 0, sizeof (databuf)); - ctlbuf.maxlen = sizeof (dlpi_ctl); - ctlbuf.buf = (void *)dlpi_ctl; - databuf.maxlen = sizeof (sock_buff); - databuf.buf = (void *)sock_buff; - flags = 0; - retv = getmsg (fd, &ctlbuf, &databuf, &flags); + struct pollfd fds[1]; + struct strbuf ctlbuf, databuf; + int flags, retv; + + do { + /* Poll is used here in case the device doesn't speak DLPI + * correctly */ + memset(fds, 0, sizeof(fds)); + fds[0].fd = fd; + fds[0].events = POLLIN | POLLPRI; + if (poll(fds, 1, 1000) <= 0) + return -1; + + memset(&ctlbuf, 0, sizeof(ctlbuf)); + memset(&databuf, 0, sizeof(databuf)); + ctlbuf.maxlen = sizeof(dlpi_ctl); + ctlbuf.buf = (void *)dlpi_ctl; + databuf.maxlen = sizeof(sock_buff); + databuf.buf = (void *)sock_buff; + flags = 0; + retv = getmsg(fd, &ctlbuf, &databuf, &flags); + + if (retv < 0) + return -1; + } while (ctlbuf.len == 0); + + if (!(retv & MORECTL)) { + while (retv & MOREDATA) { + flags = 0; + retv = getmsg(fd, NULL, &databuf, &flags); + } + return ctlbuf.len; + } - if (retv < 0) - return -1; - } - while (ctlbuf.len == 0); - - if (!(retv & MORECTL)) - { - while (retv & MOREDATA) - { - flags = 0; - retv = getmsg (fd, NULL, &databuf, &flags); + while (retv & MORECTL) { + flags = 0; + retv = getmsg(fd, &ctlbuf, &databuf, &flags); } - return ctlbuf.len; - } - - while (retv & MORECTL) - { - flags = 0; - retv = getmsg (fd, &ctlbuf, &databuf, &flags); - } - return -1; + return -1; } -static int -dlpiok (int fd, t_uscalar_t oprim) +static int dlpiok(int fd, t_uscalar_t oprim) { - int retv; - dl_ok_ack_t *doa = (dl_ok_ack_t *)dlpi_ctl; - - retv = dlpirctl (fd); - if (retv < (ssize_t)DL_OK_ACK_SIZE || doa->dl_primitive != DL_OK_ACK || - doa->dl_correct_primitive != oprim) - { - return -1; - } - else - { - return 0; - } + int retv; + dl_ok_ack_t *doa = (dl_ok_ack_t *)dlpi_ctl; + + retv = dlpirctl(fd); + if (retv < (ssize_t)DL_OK_ACK_SIZE || doa->dl_primitive != DL_OK_ACK + || doa->dl_correct_primitive != oprim) { + return -1; + } else { + return 0; + } } -static int -dlpiinfo (int fd) +static int dlpiinfo(int fd) { - dl_info_req_t dir; - ssize_t retv; - - memset (&dir, 0, sizeof (dir)); - dir.dl_primitive = DL_INFO_REQ; - /* Info_req uses M_PCPROTO. */ - dlpisend (fd, &dir, sizeof (dir), NULL, 0, RS_HIPRI); - retv = dlpirctl (fd); - if (retv < (ssize_t)DL_INFO_ACK_SIZE || dlpi_ctl[0] != DL_INFO_ACK) - return -1; - else - return retv; + dl_info_req_t dir; + ssize_t retv; + + memset(&dir, 0, sizeof(dir)); + dir.dl_primitive = DL_INFO_REQ; + /* Info_req uses M_PCPROTO. */ + dlpisend(fd, &dir, sizeof(dir), NULL, 0, RS_HIPRI); + retv = dlpirctl(fd); + if (retv < (ssize_t)DL_INFO_ACK_SIZE || dlpi_ctl[0] != DL_INFO_ACK) + return -1; + else + return retv; } -static int -dlpiopen (const char *devpath, ssize_t *acklen) +static int dlpiopen(const char *devpath, ssize_t *acklen) { - int fd, flags; - - fd = open (devpath, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (fd == -1) - return -1; - - /* All that we want is for the open itself to be non-blocking, not I/O. */ - flags = fcntl (fd, F_GETFL, 0); - if (flags != -1) - fcntl (fd, F_SETFL, flags & ~O_NONBLOCK); - - /* After opening, ask for information */ - if ((*acklen = dlpiinfo (fd)) == -1) - { - close (fd); - return -1; - } + int fd, flags; + + fd = open(devpath, O_RDWR | O_NONBLOCK | O_NOCTTY); + if (fd == -1) + return -1; + + /* All that we want is for the open itself to be non-blocking, not I/O. + */ + flags = fcntl(fd, F_GETFL, 0); + if (flags != -1) + fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); + + /* After opening, ask for information */ + if ((*acklen = dlpiinfo(fd)) == -1) { + close(fd); + return -1; + } - return fd; + return fd; } -static int -dlpiattach (int fd, int unit) +static int dlpiattach(int fd, int unit) { - dl_attach_req_t dar; + dl_attach_req_t dar; - memset (&dar, 0, sizeof (dar)); - dar.dl_primitive = DL_ATTACH_REQ; - dar.dl_ppa = unit; - dlpisend (fd, &dar, sizeof (dar), NULL, 0, 0); - return dlpiok (fd, dar.dl_primitive); + memset(&dar, 0, sizeof(dar)); + dar.dl_primitive = DL_ATTACH_REQ; + dar.dl_ppa = unit; + dlpisend(fd, &dar, sizeof(dar), NULL, 0, 0); + return dlpiok(fd, dar.dl_primitive); } -static int -dlpibind (int fd) +static int dlpibind(int fd) { - dl_bind_req_t dbr; - int retv; - dl_bind_ack_t *dba = (dl_bind_ack_t *)dlpi_ctl; - - memset (&dbr, 0, sizeof (dbr)); - dbr.dl_primitive = DL_BIND_REQ; - dbr.dl_service_mode = DL_CLDLS; - dlpisend (fd, &dbr, sizeof (dbr), NULL, 0, 0); - - retv = dlpirctl (fd); - if (retv < (ssize_t)DL_BIND_ACK_SIZE || dba->dl_primitive != DL_BIND_ACK) - return -1; - else - return 0; + dl_bind_req_t dbr; + int retv; + dl_bind_ack_t *dba = (dl_bind_ack_t *)dlpi_ctl; + + memset(&dbr, 0, sizeof(dbr)); + dbr.dl_primitive = DL_BIND_REQ; + dbr.dl_service_mode = DL_CLDLS; + dlpisend(fd, &dbr, sizeof(dbr), NULL, 0, 0); + + retv = dlpirctl(fd); + if (retv < (ssize_t)DL_BIND_ACK_SIZE + || dba->dl_primitive != DL_BIND_ACK) + return -1; + else + return 0; } -static int -dlpimcast (int fd, const u_char *mcaddr) +static int dlpimcast(int fd, const u_char *mcaddr) { - struct { - dl_enabmulti_req_t der; - u_char addr[ETHERADDRL]; - } dler; - - memset (&dler, 0, sizeof (dler)); - dler.der.dl_primitive = DL_ENABMULTI_REQ; - dler.der.dl_addr_length = sizeof (dler.addr); - dler.der.dl_addr_offset = dler.addr - (u_char *)&dler; - memcpy (dler.addr, mcaddr, sizeof (dler.addr)); - dlpisend (fd, &dler, sizeof (dler), NULL, 0, 0); - return dlpiok (fd, dler.der.dl_primitive); + struct { + dl_enabmulti_req_t der; + u_char addr[ETHERADDRL]; + } dler; + + memset(&dler, 0, sizeof(dler)); + dler.der.dl_primitive = DL_ENABMULTI_REQ; + dler.der.dl_addr_length = sizeof(dler.addr); + dler.der.dl_addr_offset = dler.addr - (u_char *)&dler; + memcpy(dler.addr, mcaddr, sizeof(dler.addr)); + dlpisend(fd, &dler, sizeof(dler), NULL, 0, 0); + return dlpiok(fd, dler.der.dl_primitive); } -static int -dlpiaddr (int fd, u_char *addr) +static int dlpiaddr(int fd, u_char *addr) { - dl_phys_addr_req_t dpar; - dl_phys_addr_ack_t *dpaa = (dl_phys_addr_ack_t *)dlpi_ctl; - int retv; - - memset (&dpar, 0, sizeof (dpar)); - dpar.dl_primitive = DL_PHYS_ADDR_REQ; - dpar.dl_addr_type = DL_CURR_PHYS_ADDR; - dlpisend (fd, &dpar, sizeof (dpar), NULL, 0, 0); - - retv = dlpirctl (fd); - if (retv < (ssize_t)DL_PHYS_ADDR_ACK_SIZE - || dpaa->dl_primitive != DL_PHYS_ADDR_ACK) - return -1; - - if (dpaa->dl_addr_offset < DL_PHYS_ADDR_ACK_SIZE || - dpaa->dl_addr_length != ETHERADDRL || - dpaa->dl_addr_offset + dpaa->dl_addr_length > (size_t)retv) - return -1; - - bcopy((char *)dpaa + dpaa->dl_addr_offset, addr, ETHERADDRL); - return 0; + dl_phys_addr_req_t dpar; + dl_phys_addr_ack_t *dpaa = (dl_phys_addr_ack_t *)dlpi_ctl; + int retv; + + memset(&dpar, 0, sizeof(dpar)); + dpar.dl_primitive = DL_PHYS_ADDR_REQ; + dpar.dl_addr_type = DL_CURR_PHYS_ADDR; + dlpisend(fd, &dpar, sizeof(dpar), NULL, 0, 0); + + retv = dlpirctl(fd); + if (retv < (ssize_t)DL_PHYS_ADDR_ACK_SIZE + || dpaa->dl_primitive != DL_PHYS_ADDR_ACK) + return -1; + + if (dpaa->dl_addr_offset < DL_PHYS_ADDR_ACK_SIZE + || dpaa->dl_addr_length != ETHERADDRL + || dpaa->dl_addr_offset + dpaa->dl_addr_length > (size_t)retv) + return -1; + + bcopy((char *)dpaa + dpaa->dl_addr_offset, addr, ETHERADDRL); + return 0; } -static int -open_dlpi_dev (struct isis_circuit *circuit) +static int open_dlpi_dev(struct isis_circuit *circuit) { - int fd = -1, unit, retval; - char devpath[MAXPATHLEN]; - dl_info_ack_t *dia = (dl_info_ack_t *)dlpi_ctl; - ssize_t acklen; - - /* Only broadcast-type are supported at the moment */ - if (circuit->circ_type != CIRCUIT_T_BROADCAST) - { - zlog_warn ("%s: non-broadcast interface %s", __func__, - circuit->interface->name); - return ISIS_WARNING; - } - - /* Try the vanity node first, if permitted */ - if (getenv("DLPI_DEVONLY") == NULL) - { - (void) snprintf (devpath, sizeof(devpath), "/dev/net/%s", - circuit->interface->name); - fd = dlpiopen (devpath, &acklen); - } - - /* Now try as an ordinary Style 1 node */ - if (fd == -1) - { - (void) snprintf (devpath, sizeof (devpath), "/dev/%s", - circuit->interface->name); - unit = -1; - fd = dlpiopen (devpath, &acklen); - } - - /* If that fails, try again as Style 2 */ - if (fd == -1) - { - char *cp; - - cp = devpath + strlen (devpath); - while (--cp >= devpath && isdigit(*cp)) - ; - unit = strtol(cp, NULL, 0); - *cp = '\0'; - fd = dlpiopen (devpath, &acklen); - - /* If that too fails, then the device really doesn't exist */ - if (fd == -1) - { - zlog_warn ("%s: unknown interface %s", __func__, - circuit->interface->name); - return ISIS_WARNING; + int fd = -1, unit, retval; + char devpath[MAXPATHLEN]; + dl_info_ack_t *dia = (dl_info_ack_t *)dlpi_ctl; + ssize_t acklen; + + /* Only broadcast-type are supported at the moment */ + if (circuit->circ_type != CIRCUIT_T_BROADCAST) { + zlog_warn("%s: non-broadcast interface %s", __func__, + circuit->interface->name); + return ISIS_WARNING; + } + + /* Try the vanity node first, if permitted */ + if (getenv("DLPI_DEVONLY") == NULL) { + (void)snprintf(devpath, sizeof(devpath), "/dev/net/%s", + circuit->interface->name); + fd = dlpiopen(devpath, &acklen); + } + + /* Now try as an ordinary Style 1 node */ + if (fd == -1) { + (void)snprintf(devpath, sizeof(devpath), "/dev/%s", + circuit->interface->name); + unit = -1; + fd = dlpiopen(devpath, &acklen); + } + + /* If that fails, try again as Style 2 */ + if (fd == -1) { + char *cp; + + cp = devpath + strlen(devpath); + while (--cp >= devpath && isdigit(*cp)) + ; + unit = strtol(cp, NULL, 0); + *cp = '\0'; + fd = dlpiopen(devpath, &acklen); + + /* If that too fails, then the device really doesn't exist */ + if (fd == -1) { + zlog_warn("%s: unknown interface %s", __func__, + circuit->interface->name); + return ISIS_WARNING; + } + + /* Double check the DLPI style */ + if (dia->dl_provider_style != DL_STYLE2) { + zlog_warn( + "open_dlpi_dev(): interface %s: %s is not style 2", + circuit->interface->name, devpath); + close(fd); + return ISIS_WARNING; + } + + /* If it succeeds, then we need to attach to the unit specified + */ + dlpiattach(fd, unit); + + /* Reget the information, as it may be different per node */ + if ((acklen = dlpiinfo(fd)) == -1) { + close(fd); + return ISIS_WARNING; + } + } else { + /* Double check the DLPI style */ + if (dia->dl_provider_style != DL_STYLE1) { + zlog_warn( + "open_dlpi_dev(): interface %s: %s is not style 1", + circuit->interface->name, devpath); + close(fd); + return ISIS_WARNING; + } } - /* Double check the DLPI style */ - if (dia->dl_provider_style != DL_STYLE2) - { - zlog_warn ("open_dlpi_dev(): interface %s: %s is not style 2", - circuit->interface->name, devpath); - close (fd); - return ISIS_WARNING; + /* Check that the interface we've got is the kind we expect */ + if ((dia->dl_sap_length != 2 && dia->dl_sap_length != -2) + || dia->dl_service_mode != DL_CLDLS + || dia->dl_addr_length != ETHERADDRL + 2 + || dia->dl_brdcst_addr_length != ETHERADDRL) { + zlog_warn("%s: unsupported interface type for %s", __func__, + circuit->interface->name); + close(fd); + return ISIS_WARNING; + } + switch (dia->dl_mac_type) { + case DL_CSMACD: + case DL_ETHER: + case DL_100VG: + case DL_100VGTPR: + case DL_ETH_CSMA: + case DL_100BT: + break; + default: + zlog_warn("%s: unexpected mac type on %s: %lld", __func__, + circuit->interface->name, + (long long)dia->dl_mac_type); + close(fd); + return ISIS_WARNING; + } + + circuit->sap_length = dia->dl_sap_length; + + /* + * The local hardware address is something that should be provided by + * way of + * sockaddr_dl for the interface, but isn't on Solaris. We set it here + * based + * on DLPI's reported address to avoid roto-tilling the world. + * (Note that isis_circuit_if_add on Solaris doesn't set the snpa.) + * + * Unfortunately, GLD is broken and doesn't provide the address after + * attach, + * so we need to be careful and use DL_PHYS_ADDR_REQ instead. + */ + if (dlpiaddr(fd, circuit->u.bc.snpa) == -1) { + zlog_warn( + "open_dlpi_dev(): interface %s: unable to get MAC address", + circuit->interface->name); + close(fd); + return ISIS_WARNING; } - /* If it succeeds, then we need to attach to the unit specified */ - dlpiattach (fd, unit); + /* Now bind to SAP 0. This gives us 802-type traffic. */ + if (dlpibind(fd) == -1) { + zlog_warn("%s: cannot bind SAP 0 on %s", __func__, + circuit->interface->name); + close(fd); + return ISIS_WARNING; + } - /* Reget the information, as it may be different per node */ - if ((acklen = dlpiinfo (fd)) == -1) - { - close (fd); - return ISIS_WARNING; + /* + * Join to multicast groups according to + * 8.4.2 - Broadcast subnetwork IIH PDUs + */ + retval = 0; + retval |= dlpimcast(fd, ALL_L1_ISS); + retval |= dlpimcast(fd, ALL_ISS); + retval |= dlpimcast(fd, ALL_L2_ISS); + + if (retval != 0) { + zlog_warn("%s: unable to join multicast on %s", __func__, + circuit->interface->name); + close(fd); + return ISIS_WARNING; } - } - else - { - /* Double check the DLPI style */ - if (dia->dl_provider_style != DL_STYLE1) - { - zlog_warn ("open_dlpi_dev(): interface %s: %s is not style 1", - circuit->interface->name, devpath); - close (fd); - return ISIS_WARNING; + + /* Push on the packet filter to avoid stray 802 packets */ + if (ioctl(fd, I_PUSH, "pfmod") == 0) { + struct packetfilt pfil; + struct strioctl sioc; + + pfil.Pf_Priority = 0; + pfil.Pf_FilterLen = sizeof(pf_filter) / sizeof(u_short); + memcpy(pfil.Pf_Filter, pf_filter, sizeof(pf_filter)); + /* pfmod does not support transparent ioctls */ + sioc.ic_cmd = PFIOCSETF; + sioc.ic_timout = 5; + sioc.ic_len = sizeof(struct packetfilt); + sioc.ic_dp = (char *)&pfil; + if (ioctl(fd, I_STR, &sioc) == -1) + zlog_warn("%s: could not perform PF_IOCSETF on %s", + __func__, circuit->interface->name); } - } - - /* Check that the interface we've got is the kind we expect */ - if ((dia->dl_sap_length != 2 && dia->dl_sap_length != -2) || - dia->dl_service_mode != DL_CLDLS || dia->dl_addr_length != ETHERADDRL + 2 || - dia->dl_brdcst_addr_length != ETHERADDRL) - { - zlog_warn ("%s: unsupported interface type for %s", __func__, - circuit->interface->name); - close (fd); - return ISIS_WARNING; - } - switch (dia->dl_mac_type) - { - case DL_CSMACD: - case DL_ETHER: - case DL_100VG: - case DL_100VGTPR: - case DL_ETH_CSMA: - case DL_100BT: - break; - default: - zlog_warn ("%s: unexpected mac type on %s: %lld", __func__, - circuit->interface->name, (long long)dia->dl_mac_type); - close (fd); - return ISIS_WARNING; - } - - circuit->sap_length = dia->dl_sap_length; - - /* - * The local hardware address is something that should be provided by way of - * sockaddr_dl for the interface, but isn't on Solaris. We set it here based - * on DLPI's reported address to avoid roto-tilling the world. - * (Note that isis_circuit_if_add on Solaris doesn't set the snpa.) - * - * Unfortunately, GLD is broken and doesn't provide the address after attach, - * so we need to be careful and use DL_PHYS_ADDR_REQ instead. - */ - if (dlpiaddr (fd, circuit->u.bc.snpa) == -1) - { - zlog_warn ("open_dlpi_dev(): interface %s: unable to get MAC address", - circuit->interface->name); - close (fd); - return ISIS_WARNING; - } - - /* Now bind to SAP 0. This gives us 802-type traffic. */ - if (dlpibind (fd) == -1) - { - zlog_warn ("%s: cannot bind SAP 0 on %s", __func__, - circuit->interface->name); - close (fd); - return ISIS_WARNING; - } - - /* - * Join to multicast groups according to - * 8.4.2 - Broadcast subnetwork IIH PDUs - */ - retval = 0; - retval |= dlpimcast (fd, ALL_L1_ISS); - retval |= dlpimcast (fd, ALL_ISS); - retval |= dlpimcast (fd, ALL_L2_ISS); - - if (retval != 0) - { - zlog_warn ("%s: unable to join multicast on %s", __func__, - circuit->interface->name); - close (fd); - return ISIS_WARNING; - } - - /* Push on the packet filter to avoid stray 802 packets */ - if (ioctl (fd, I_PUSH, "pfmod") == 0) - { - struct packetfilt pfil; - struct strioctl sioc; - - pfil.Pf_Priority = 0; - pfil.Pf_FilterLen = sizeof (pf_filter) / sizeof (u_short); - memcpy (pfil.Pf_Filter, pf_filter, sizeof (pf_filter)); - /* pfmod does not support transparent ioctls */ - sioc.ic_cmd = PFIOCSETF; - sioc.ic_timout = 5; - sioc.ic_len = sizeof (struct packetfilt); - sioc.ic_dp = (char *)&pfil; - if (ioctl (fd, I_STR, &sioc) == -1) - zlog_warn("%s: could not perform PF_IOCSETF on %s", - __func__, circuit->interface->name); - } - - circuit->fd = fd; - - return ISIS_OK; + + circuit->fd = fd; + + return ISIS_OK; } /* * Create the socket and set the tx/rx funcs */ -int -isis_sock_init (struct isis_circuit *circuit) +int isis_sock_init(struct isis_circuit *circuit) { - int retval = ISIS_OK; - - if (isisd_privs.change (ZPRIVS_RAISE)) - zlog_err ("%s: could not raise privs, %s", __func__, safe_strerror (errno)); - - retval = open_dlpi_dev (circuit); - - if (retval != ISIS_OK) - { - zlog_warn ("%s: could not initialize the socket", __func__); - goto end; - } - - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - { - circuit->tx = isis_send_pdu_bcast; - circuit->rx = isis_recv_pdu_bcast; - } - else - { - zlog_warn ("isis_sock_init(): unknown circuit type"); - retval = ISIS_WARNING; - goto end; - } + int retval = ISIS_OK; + + if (isisd_privs.change(ZPRIVS_RAISE)) + zlog_err("%s: could not raise privs, %s", __func__, + safe_strerror(errno)); + + retval = open_dlpi_dev(circuit); + + if (retval != ISIS_OK) { + zlog_warn("%s: could not initialize the socket", __func__); + goto end; + } + + if (circuit->circ_type == CIRCUIT_T_BROADCAST) { + circuit->tx = isis_send_pdu_bcast; + circuit->rx = isis_recv_pdu_bcast; + } else { + zlog_warn("isis_sock_init(): unknown circuit type"); + retval = ISIS_WARNING; + goto end; + } end: - if (isisd_privs.change (ZPRIVS_LOWER)) - zlog_err ("%s: could not lower privs, %s", __func__, safe_strerror (errno)); + if (isisd_privs.change(ZPRIVS_LOWER)) + zlog_err("%s: could not lower privs, %s", __func__, + safe_strerror(errno)); - return retval; + return retval; } -int -isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa) +int isis_recv_pdu_bcast(struct isis_circuit *circuit, u_char *ssnpa) { - struct pollfd fds[1]; - struct strbuf ctlbuf, databuf; - int flags, retv; - dl_unitdata_ind_t *dui = (dl_unitdata_ind_t *)dlpi_ctl; - - memset (fds, 0, sizeof (fds)); - fds[0].fd = circuit->fd; - fds[0].events = POLLIN | POLLPRI; - if (poll (fds, 1, 0) <= 0) - return ISIS_WARNING; - - memset (&ctlbuf, 0, sizeof (ctlbuf)); - memset (&databuf, 0, sizeof (databuf)); - ctlbuf.maxlen = sizeof (dlpi_ctl); - ctlbuf.buf = (void *)dlpi_ctl; - databuf.maxlen = sizeof (sock_buff); - databuf.buf = (void *)sock_buff; - flags = 0; - retv = getmsg (circuit->fd, &ctlbuf, &databuf, &flags); - - if (retv < 0) - { - zlog_warn ("isis_recv_pdu_bcast: getmsg failed: %s", - safe_strerror (errno)); - return ISIS_WARNING; - } - - if (retv & (MORECTL | MOREDATA)) - { - while (retv & (MORECTL | MOREDATA)) - { - flags = 0; - retv = getmsg (circuit->fd, &ctlbuf, &databuf, &flags); + struct pollfd fds[1]; + struct strbuf ctlbuf, databuf; + int flags, retv; + dl_unitdata_ind_t *dui = (dl_unitdata_ind_t *)dlpi_ctl; + + memset(fds, 0, sizeof(fds)); + fds[0].fd = circuit->fd; + fds[0].events = POLLIN | POLLPRI; + if (poll(fds, 1, 0) <= 0) + return ISIS_WARNING; + + memset(&ctlbuf, 0, sizeof(ctlbuf)); + memset(&databuf, 0, sizeof(databuf)); + ctlbuf.maxlen = sizeof(dlpi_ctl); + ctlbuf.buf = (void *)dlpi_ctl; + databuf.maxlen = sizeof(sock_buff); + databuf.buf = (void *)sock_buff; + flags = 0; + retv = getmsg(circuit->fd, &ctlbuf, &databuf, &flags); + + if (retv < 0) { + zlog_warn("isis_recv_pdu_bcast: getmsg failed: %s", + safe_strerror(errno)); + return ISIS_WARNING; + } + + if (retv & (MORECTL | MOREDATA)) { + while (retv & (MORECTL | MOREDATA)) { + flags = 0; + retv = getmsg(circuit->fd, &ctlbuf, &databuf, &flags); + } + return ISIS_WARNING; } - return ISIS_WARNING; - } - if (ctlbuf.len < (ssize_t)DL_UNITDATA_IND_SIZE || - dui->dl_primitive != DL_UNITDATA_IND) - return ISIS_WARNING; + if (ctlbuf.len < (ssize_t)DL_UNITDATA_IND_SIZE + || dui->dl_primitive != DL_UNITDATA_IND) + return ISIS_WARNING; - if (dui->dl_src_addr_length != ETHERADDRL + 2 || - dui->dl_src_addr_offset < DL_UNITDATA_IND_SIZE || - dui->dl_src_addr_offset + dui->dl_src_addr_length > (size_t)ctlbuf.len) - return ISIS_WARNING; + if (dui->dl_src_addr_length != ETHERADDRL + 2 + || dui->dl_src_addr_offset < DL_UNITDATA_IND_SIZE + || dui->dl_src_addr_offset + dui->dl_src_addr_length + > (size_t)ctlbuf.len) + return ISIS_WARNING; - memcpy (ssnpa, (char *)dui + dui->dl_src_addr_offset + - (circuit->sap_length > 0 ? circuit->sap_length : 0), ETHERADDRL); + memcpy(ssnpa, + (char *)dui + dui->dl_src_addr_offset + + (circuit->sap_length > 0 ? circuit->sap_length : 0), + ETHERADDRL); - if (databuf.len < LLC_LEN || sock_buff[0] != ISO_SAP || - sock_buff[1] != ISO_SAP || sock_buff[2] != 3) - return ISIS_WARNING; + if (databuf.len < LLC_LEN || sock_buff[0] != ISO_SAP + || sock_buff[1] != ISO_SAP || sock_buff[2] != 3) + return ISIS_WARNING; - stream_write (circuit->rcv_stream, sock_buff + LLC_LEN, - databuf.len - LLC_LEN); - stream_set_getp (circuit->rcv_stream, 0); + stream_write(circuit->rcv_stream, sock_buff + LLC_LEN, + databuf.len - LLC_LEN); + stream_set_getp(circuit->rcv_stream, 0); - return ISIS_OK; + return ISIS_OK; } -int -isis_send_pdu_bcast (struct isis_circuit *circuit, int level) +int isis_send_pdu_bcast(struct isis_circuit *circuit, int level) { - dl_unitdata_req_t *dur = (dl_unitdata_req_t *)dlpi_ctl; - char *dstaddr; - u_short *dstsap; - int buflen; - int rv; - - buflen = stream_get_endp (circuit->snd_stream) + LLC_LEN; - if ((size_t)buflen > sizeof (sock_buff)) - { - zlog_warn ("isis_send_pdu_bcast: sock_buff size %zu is less than " - "output pdu size %d on circuit %s", - sizeof (sock_buff), buflen, circuit->interface->name); - return ISIS_WARNING; - } - - stream_set_getp (circuit->snd_stream, 0); - - memset (dur, 0, sizeof (*dur)); - dur->dl_primitive = DL_UNITDATA_REQ; - dur->dl_dest_addr_length = ETHERADDRL + 2; - dur->dl_dest_addr_offset = sizeof (*dur); - - dstaddr = (char *)(dur + 1); - if (circuit->sap_length < 0) - { - dstsap = (u_short *)(dstaddr + ETHERADDRL); - } - else - { - dstsap = (u_short *)dstaddr; - dstaddr += circuit->sap_length; - } - if (level == 1) - memcpy (dstaddr, ALL_L1_ISS, ETHERADDRL); - else - memcpy (dstaddr, ALL_L2_ISS, ETHERADDRL); - /* Note: DLPI SAP values are in host byte order */ - *dstsap = buflen; - - sock_buff[0] = ISO_SAP; - sock_buff[1] = ISO_SAP; - sock_buff[2] = 0x03; - memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data, - stream_get_endp (circuit->snd_stream)); - rv = dlpisend(circuit->fd, dur, sizeof (*dur) + dur->dl_dest_addr_length, - sock_buff, buflen, 0); - if (rv < 0) - { - zlog_warn("IS-IS dlpi: could not transmit packet on %s: %s", - circuit->interface->name, safe_strerror(errno)); - if (ERRNO_IO_RETRY(errno)) - return ISIS_WARNING; - return ISIS_ERROR; - } - - return ISIS_OK; + dl_unitdata_req_t *dur = (dl_unitdata_req_t *)dlpi_ctl; + char *dstaddr; + u_short *dstsap; + int buflen; + int rv; + + buflen = stream_get_endp(circuit->snd_stream) + LLC_LEN; + if ((size_t)buflen > sizeof(sock_buff)) { + zlog_warn( + "isis_send_pdu_bcast: sock_buff size %zu is less than " + "output pdu size %d on circuit %s", + sizeof(sock_buff), buflen, circuit->interface->name); + return ISIS_WARNING; + } + + stream_set_getp(circuit->snd_stream, 0); + + memset(dur, 0, sizeof(*dur)); + dur->dl_primitive = DL_UNITDATA_REQ; + dur->dl_dest_addr_length = ETHERADDRL + 2; + dur->dl_dest_addr_offset = sizeof(*dur); + + dstaddr = (char *)(dur + 1); + if (circuit->sap_length < 0) { + dstsap = (u_short *)(dstaddr + ETHERADDRL); + } else { + dstsap = (u_short *)dstaddr; + dstaddr += circuit->sap_length; + } + if (level == 1) + memcpy(dstaddr, ALL_L1_ISS, ETHERADDRL); + else + memcpy(dstaddr, ALL_L2_ISS, ETHERADDRL); + /* Note: DLPI SAP values are in host byte order */ + *dstsap = buflen; + + sock_buff[0] = ISO_SAP; + sock_buff[1] = ISO_SAP; + sock_buff[2] = 0x03; + memcpy(sock_buff + LLC_LEN, circuit->snd_stream->data, + stream_get_endp(circuit->snd_stream)); + rv = dlpisend(circuit->fd, dur, sizeof(*dur) + dur->dl_dest_addr_length, + sock_buff, buflen, 0); + if (rv < 0) { + zlog_warn("IS-IS dlpi: could not transmit packet on %s: %s", + circuit->interface->name, safe_strerror(errno)); + if (ERRNO_IO_RETRY(errno)) + return ISIS_WARNING; + return ISIS_ERROR; + } + + return ISIS_OK; } #endif /* ISIS_METHOD == ISIS_METHOD_DLPI */ diff --git a/isisd/isis_dr.c b/isisd/isis_dr.c index 96cf8488d..3f532ecf8 100644 --- a/isisd/isis_dr.c +++ b/isisd/isis_dr.c @@ -1,19 +1,19 @@ /* * IS-IS Rout(e)ing protocol - isis_dr.c - * IS-IS designated router related routines + * IS-IS designated router related routines * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -47,321 +47,306 @@ #include "isisd/isis_dr.h" #include "isisd/isis_events.h" -const char * -isis_disflag2string (int disflag) +const char *isis_disflag2string(int disflag) { - switch (disflag) - { - case ISIS_IS_NOT_DIS: - return "is not DIS"; - case ISIS_IS_DIS: - return "is DIS"; - case ISIS_WAS_DIS: - return "was DIS"; - default: - return "unknown DIS state"; - } - return NULL; /* not reached */ + switch (disflag) { + case ISIS_IS_NOT_DIS: + return "is not DIS"; + case ISIS_IS_DIS: + return "is DIS"; + case ISIS_WAS_DIS: + return "was DIS"; + default: + return "unknown DIS state"; + } + return NULL; /* not reached */ } -int -isis_run_dr_l1 (struct thread *thread) +int isis_run_dr_l1(struct thread *thread) { - struct isis_circuit *circuit; + struct isis_circuit *circuit; - circuit = THREAD_ARG (thread); - assert (circuit); + circuit = THREAD_ARG(thread); + assert(circuit); - if (circuit->u.bc.run_dr_elect[0]) - zlog_warn ("isis_run_dr(): run_dr_elect already set for l1"); + if (circuit->u.bc.run_dr_elect[0]) + zlog_warn("isis_run_dr(): run_dr_elect already set for l1"); - circuit->u.bc.t_run_dr[0] = NULL; - circuit->u.bc.run_dr_elect[0] = 1; + circuit->u.bc.t_run_dr[0] = NULL; + circuit->u.bc.run_dr_elect[0] = 1; - return ISIS_OK; + return ISIS_OK; } -int -isis_run_dr_l2 (struct thread *thread) +int isis_run_dr_l2(struct thread *thread) { - struct isis_circuit *circuit; + struct isis_circuit *circuit; - circuit = THREAD_ARG (thread); - assert (circuit); + circuit = THREAD_ARG(thread); + assert(circuit); - if (circuit->u.bc.run_dr_elect[1]) - zlog_warn ("isis_run_dr(): run_dr_elect already set for l2"); + if (circuit->u.bc.run_dr_elect[1]) + zlog_warn("isis_run_dr(): run_dr_elect already set for l2"); - circuit->u.bc.t_run_dr[1] = NULL; - circuit->u.bc.run_dr_elect[1] = 1; + circuit->u.bc.t_run_dr[1] = NULL; + circuit->u.bc.run_dr_elect[1] = 1; - return ISIS_OK; + return ISIS_OK; } -static int -isis_check_dr_change (struct isis_adjacency *adj, int level) +static int isis_check_dr_change(struct isis_adjacency *adj, int level) { - int i; - - if (adj->dis_record[level - 1].dis != - adj->dis_record[(1 * ISIS_LEVELS) + level - 1].dis) - /* was there a DIS state transition ? */ - { - adj->dischanges[level - 1]++; - /* ok rotate the history list through */ - for (i = DIS_RECORDS - 1; i > 0; i--) + int i; + + if (adj->dis_record[level - 1].dis + != adj->dis_record[(1 * ISIS_LEVELS) + level - 1].dis) + /* was there a DIS state transition ? */ { - adj->dis_record[(i * ISIS_LEVELS) + level - 1].dis = - adj->dis_record[((i - 1) * ISIS_LEVELS) + level - 1].dis; - adj->dis_record[(i * ISIS_LEVELS) + level - 1].last_dis_change = - adj->dis_record[((i - 1) * ISIS_LEVELS) + level - - 1].last_dis_change; + adj->dischanges[level - 1]++; + /* ok rotate the history list through */ + for (i = DIS_RECORDS - 1; i > 0; i--) { + adj->dis_record[(i * ISIS_LEVELS) + level - 1].dis = + adj->dis_record[((i - 1) * ISIS_LEVELS) + level + - 1] + .dis; + adj->dis_record[(i * ISIS_LEVELS) + level - 1] + .last_dis_change = + adj->dis_record[((i - 1) * ISIS_LEVELS) + level + - 1] + .last_dis_change; + } } - } - return ISIS_OK; + return ISIS_OK; } -int -isis_dr_elect (struct isis_circuit *circuit, int level) +int isis_dr_elect(struct isis_circuit *circuit, int level) { - struct list *adjdb; - struct listnode *node; - struct isis_adjacency *adj, *adj_dr = NULL; - struct list *list = list_new (); - u_char own_prio; - int biggest_prio = -1; - int cmp_res, retval = ISIS_OK; - - own_prio = circuit->priority[level - 1]; - adjdb = circuit->u.bc.adjdb[level - 1]; - - if (!adjdb) - { - zlog_warn ("isis_dr_elect() adjdb == NULL"); - list_delete (list); - return ISIS_WARNING; - } - isis_adj_build_up_list (adjdb, list); - - /* - * Loop the adjacencies and find the one with the biggest priority - */ - for (ALL_LIST_ELEMENTS_RO (list, node, adj)) - { - /* clear flag for show output */ - adj->dis_record[level - 1].dis = ISIS_IS_NOT_DIS; - adj->dis_record[level - 1].last_dis_change = time (NULL); - - if (adj->prio[level - 1] > biggest_prio) - { - biggest_prio = adj->prio[level - 1]; - adj_dr = adj; + struct list *adjdb; + struct listnode *node; + struct isis_adjacency *adj, *adj_dr = NULL; + struct list *list = list_new(); + u_char own_prio; + int biggest_prio = -1; + int cmp_res, retval = ISIS_OK; + + own_prio = circuit->priority[level - 1]; + adjdb = circuit->u.bc.adjdb[level - 1]; + + if (!adjdb) { + zlog_warn("isis_dr_elect() adjdb == NULL"); + list_delete(list); + return ISIS_WARNING; } - else if (adj->prio[level - 1] == biggest_prio) - { - /* - * Comparison of MACs breaks a tie - */ - if (adj_dr) - { - cmp_res = memcmp (adj_dr->snpa, adj->snpa, ETH_ALEN); - if (cmp_res < 0) - { - adj_dr = adj; + isis_adj_build_up_list(adjdb, list); + + /* + * Loop the adjacencies and find the one with the biggest priority + */ + for (ALL_LIST_ELEMENTS_RO(list, node, adj)) { + /* clear flag for show output */ + adj->dis_record[level - 1].dis = ISIS_IS_NOT_DIS; + adj->dis_record[level - 1].last_dis_change = time(NULL); + + if (adj->prio[level - 1] > biggest_prio) { + biggest_prio = adj->prio[level - 1]; + adj_dr = adj; + } else if (adj->prio[level - 1] == biggest_prio) { + /* + * Comparison of MACs breaks a tie + */ + if (adj_dr) { + cmp_res = memcmp(adj_dr->snpa, adj->snpa, + ETH_ALEN); + if (cmp_res < 0) { + adj_dr = adj; + } + if (cmp_res == 0) + zlog_warn( + "isis_dr_elect(): multiple adjacencies with same SNPA"); + } else { + adj_dr = adj; + } } - if (cmp_res == 0) - zlog_warn - ("isis_dr_elect(): multiple adjacencies with same SNPA"); - } - else - { - adj_dr = adj; - } } - } - - if (!adj_dr) - { - /* - * Could not find the DR - means we are alone. Resign if we were DR. - */ - if (circuit->u.bc.is_dr[level - 1]) - retval = isis_dr_resign (circuit, level); - list_delete (list); - return retval; - } - - /* - * Now we have the DR adjacency, compare it to self - */ - if (adj_dr->prio[level - 1] < own_prio || - (adj_dr->prio[level - 1] == own_prio && - memcmp (adj_dr->snpa, circuit->u.bc.snpa, ETH_ALEN) < 0)) - { - adj_dr->dis_record[level - 1].dis = ISIS_IS_NOT_DIS; - adj_dr->dis_record[level - 1].last_dis_change = time (NULL); - - /* rotate the history log */ - for (ALL_LIST_ELEMENTS_RO (list, node, adj)) - isis_check_dr_change (adj, level); - - /* We are the DR, commence DR */ - if (circuit->u.bc.is_dr[level - 1] == 0 && listcount (list) > 0) - retval = isis_dr_commence (circuit, level); - } - else - { - /* ok we have found the DIS - lets mark the adjacency */ - /* set flag for show output */ - adj_dr->dis_record[level - 1].dis = ISIS_IS_DIS; - adj_dr->dis_record[level - 1].last_dis_change = time (NULL); - - /* now loop through a second time to check if there has been a DIS change - * if yes rotate the history log - */ - - for (ALL_LIST_ELEMENTS_RO (list, node, adj)) - isis_check_dr_change (adj, level); - - /* - * We are not DR - if we were -> resign - */ - if (circuit->u.bc.is_dr[level - 1]) - retval = isis_dr_resign (circuit, level); - } - list_delete (list); - return retval; + + if (!adj_dr) { + /* + * Could not find the DR - means we are alone. Resign if we were + * DR. + */ + if (circuit->u.bc.is_dr[level - 1]) + retval = isis_dr_resign(circuit, level); + list_delete(list); + return retval; + } + + /* + * Now we have the DR adjacency, compare it to self + */ + if (adj_dr->prio[level - 1] < own_prio + || (adj_dr->prio[level - 1] == own_prio + && memcmp(adj_dr->snpa, circuit->u.bc.snpa, ETH_ALEN) < 0)) { + adj_dr->dis_record[level - 1].dis = ISIS_IS_NOT_DIS; + adj_dr->dis_record[level - 1].last_dis_change = time(NULL); + + /* rotate the history log */ + for (ALL_LIST_ELEMENTS_RO(list, node, adj)) + isis_check_dr_change(adj, level); + + /* We are the DR, commence DR */ + if (circuit->u.bc.is_dr[level - 1] == 0 && listcount(list) > 0) + retval = isis_dr_commence(circuit, level); + } else { + /* ok we have found the DIS - lets mark the adjacency */ + /* set flag for show output */ + adj_dr->dis_record[level - 1].dis = ISIS_IS_DIS; + adj_dr->dis_record[level - 1].last_dis_change = time(NULL); + + /* now loop through a second time to check if there has been a + * DIS change + * if yes rotate the history log + */ + + for (ALL_LIST_ELEMENTS_RO(list, node, adj)) + isis_check_dr_change(adj, level); + + /* + * We are not DR - if we were -> resign + */ + if (circuit->u.bc.is_dr[level - 1]) + retval = isis_dr_resign(circuit, level); + } + list_delete(list); + return retval; } -int -isis_dr_resign (struct isis_circuit *circuit, int level) +int isis_dr_resign(struct isis_circuit *circuit, int level) { - u_char id[ISIS_SYS_ID_LEN + 2]; + u_char id[ISIS_SYS_ID_LEN + 2]; - zlog_debug ("isis_dr_resign l%d", level); + zlog_debug("isis_dr_resign l%d", level); - circuit->u.bc.is_dr[level - 1] = 0; - circuit->u.bc.run_dr_elect[level - 1] = 0; - THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[level - 1]); - THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[level - 1]); - circuit->lsp_regenerate_pending[level - 1] = 0; + circuit->u.bc.is_dr[level - 1] = 0; + circuit->u.bc.run_dr_elect[level - 1] = 0; + THREAD_TIMER_OFF(circuit->u.bc.t_run_dr[level - 1]); + THREAD_TIMER_OFF(circuit->u.bc.t_refresh_pseudo_lsp[level - 1]); + circuit->lsp_regenerate_pending[level - 1] = 0; - memcpy (id, isis->sysid, ISIS_SYS_ID_LEN); - LSP_PSEUDO_ID (id) = circuit->circuit_id; - LSP_FRAGMENT (id) = 0; - lsp_purge_pseudo (id, circuit, level); + memcpy(id, isis->sysid, ISIS_SYS_ID_LEN); + LSP_PSEUDO_ID(id) = circuit->circuit_id; + LSP_FRAGMENT(id) = 0; + lsp_purge_pseudo(id, circuit, level); - if (level == 1) - { - memset (circuit->u.bc.l1_desig_is, 0, ISIS_SYS_ID_LEN + 1); + if (level == 1) { + memset(circuit->u.bc.l1_desig_is, 0, ISIS_SYS_ID_LEN + 1); - THREAD_TIMER_OFF (circuit->t_send_csnp[0]); + THREAD_TIMER_OFF(circuit->t_send_csnp[0]); - thread_add_timer(master, isis_run_dr_l1, circuit, - 2 * circuit->hello_interval[0], - &circuit->u.bc.t_run_dr[0]); + thread_add_timer(master, isis_run_dr_l1, circuit, + 2 * circuit->hello_interval[0], + &circuit->u.bc.t_run_dr[0]); - thread_add_timer(master, send_l1_psnp, circuit, - isis_jitter(circuit->psnp_interval[level - 1], PSNP_JITTER), - &circuit->t_send_psnp[0]); - } - else - { - memset (circuit->u.bc.l2_desig_is, 0, ISIS_SYS_ID_LEN + 1); + thread_add_timer(master, send_l1_psnp, circuit, + isis_jitter(circuit->psnp_interval[level - 1], + PSNP_JITTER), + &circuit->t_send_psnp[0]); + } else { + memset(circuit->u.bc.l2_desig_is, 0, ISIS_SYS_ID_LEN + 1); - THREAD_TIMER_OFF (circuit->t_send_csnp[1]); + THREAD_TIMER_OFF(circuit->t_send_csnp[1]); - thread_add_timer(master, isis_run_dr_l2, circuit, - 2 * circuit->hello_interval[1], - &circuit->u.bc.t_run_dr[1]); + thread_add_timer(master, isis_run_dr_l2, circuit, + 2 * circuit->hello_interval[1], + &circuit->u.bc.t_run_dr[1]); - thread_add_timer(master, send_l2_psnp, circuit, - isis_jitter(circuit->psnp_interval[level - 1], PSNP_JITTER), - &circuit->t_send_psnp[1]); - } + thread_add_timer(master, send_l2_psnp, circuit, + isis_jitter(circuit->psnp_interval[level - 1], + PSNP_JITTER), + &circuit->t_send_psnp[1]); + } - thread_add_event(master, isis_event_dis_status_change, circuit, 0, NULL); + thread_add_event(master, isis_event_dis_status_change, circuit, 0, + NULL); - return ISIS_OK; + return ISIS_OK; } -int -isis_dr_commence (struct isis_circuit *circuit, int level) +int isis_dr_commence(struct isis_circuit *circuit, int level) { - u_char old_dr[ISIS_SYS_ID_LEN + 2]; - - if (isis->debugs & DEBUG_EVENTS) - zlog_debug ("isis_dr_commence l%d", level); - - /* Lets keep a pause in DR election */ - circuit->u.bc.run_dr_elect[level - 1] = 0; - if (level == 1) - thread_add_timer(master, isis_run_dr_l1, circuit, - 2 * circuit->hello_interval[0], - &circuit->u.bc.t_run_dr[0]); - else - thread_add_timer(master, isis_run_dr_l2, circuit, - 2 * circuit->hello_interval[1], - &circuit->u.bc.t_run_dr[1]); - circuit->u.bc.is_dr[level - 1] = 1; - - if (level == 1) - { - memcpy (old_dr, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1); - LSP_FRAGMENT (old_dr) = 0; - if (LSP_PSEUDO_ID (old_dr)) - { - /* there was a dr elected, purge its LSPs from the db */ - lsp_purge_pseudo (old_dr, circuit, level); - } - memcpy (circuit->u.bc.l1_desig_is, isis->sysid, ISIS_SYS_ID_LEN); - *(circuit->u.bc.l1_desig_is + ISIS_SYS_ID_LEN) = circuit->circuit_id; - - assert (circuit->circuit_id); /* must be non-zero */ - /* if (circuit->t_send_l1_psnp) - thread_cancel (circuit->t_send_l1_psnp); */ - lsp_generate_pseudo (circuit, 1); - - THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[0]); - thread_add_timer(master, isis_run_dr_l1, circuit, - 2 * circuit->hello_interval[0], - &circuit->u.bc.t_run_dr[0]); - - thread_add_timer(master, send_l1_csnp, circuit, - isis_jitter(circuit->csnp_interval[level - 1], CSNP_JITTER), - &circuit->t_send_csnp[0]); - - } - else - { - memcpy (old_dr, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1); - LSP_FRAGMENT (old_dr) = 0; - if (LSP_PSEUDO_ID (old_dr)) - { - /* there was a dr elected, purge its LSPs from the db */ - lsp_purge_pseudo (old_dr, circuit, level); + u_char old_dr[ISIS_SYS_ID_LEN + 2]; + + if (isis->debugs & DEBUG_EVENTS) + zlog_debug("isis_dr_commence l%d", level); + + /* Lets keep a pause in DR election */ + circuit->u.bc.run_dr_elect[level - 1] = 0; + if (level == 1) + thread_add_timer(master, isis_run_dr_l1, circuit, + 2 * circuit->hello_interval[0], + &circuit->u.bc.t_run_dr[0]); + else + thread_add_timer(master, isis_run_dr_l2, circuit, + 2 * circuit->hello_interval[1], + &circuit->u.bc.t_run_dr[1]); + circuit->u.bc.is_dr[level - 1] = 1; + + if (level == 1) { + memcpy(old_dr, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1); + LSP_FRAGMENT(old_dr) = 0; + if (LSP_PSEUDO_ID(old_dr)) { + /* there was a dr elected, purge its LSPs from the db */ + lsp_purge_pseudo(old_dr, circuit, level); + } + memcpy(circuit->u.bc.l1_desig_is, isis->sysid, ISIS_SYS_ID_LEN); + *(circuit->u.bc.l1_desig_is + ISIS_SYS_ID_LEN) = + circuit->circuit_id; + + assert(circuit->circuit_id); /* must be non-zero */ + /* if (circuit->t_send_l1_psnp) + thread_cancel (circuit->t_send_l1_psnp); */ + lsp_generate_pseudo(circuit, 1); + + THREAD_TIMER_OFF(circuit->u.bc.t_run_dr[0]); + thread_add_timer(master, isis_run_dr_l1, circuit, + 2 * circuit->hello_interval[0], + &circuit->u.bc.t_run_dr[0]); + + thread_add_timer(master, send_l1_csnp, circuit, + isis_jitter(circuit->csnp_interval[level - 1], + CSNP_JITTER), + &circuit->t_send_csnp[0]); + + } else { + memcpy(old_dr, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1); + LSP_FRAGMENT(old_dr) = 0; + if (LSP_PSEUDO_ID(old_dr)) { + /* there was a dr elected, purge its LSPs from the db */ + lsp_purge_pseudo(old_dr, circuit, level); + } + memcpy(circuit->u.bc.l2_desig_is, isis->sysid, ISIS_SYS_ID_LEN); + *(circuit->u.bc.l2_desig_is + ISIS_SYS_ID_LEN) = + circuit->circuit_id; + + assert(circuit->circuit_id); /* must be non-zero */ + /* if (circuit->t_send_l1_psnp) + thread_cancel (circuit->t_send_l1_psnp); */ + lsp_generate_pseudo(circuit, 2); + + THREAD_TIMER_OFF(circuit->u.bc.t_run_dr[1]); + thread_add_timer(master, isis_run_dr_l2, circuit, + 2 * circuit->hello_interval[1], + &circuit->u.bc.t_run_dr[1]); + + thread_add_timer(master, send_l2_csnp, circuit, + isis_jitter(circuit->csnp_interval[level - 1], + CSNP_JITTER), + &circuit->t_send_csnp[1]); } - memcpy (circuit->u.bc.l2_desig_is, isis->sysid, ISIS_SYS_ID_LEN); - *(circuit->u.bc.l2_desig_is + ISIS_SYS_ID_LEN) = circuit->circuit_id; - - assert (circuit->circuit_id); /* must be non-zero */ - /* if (circuit->t_send_l1_psnp) - thread_cancel (circuit->t_send_l1_psnp); */ - lsp_generate_pseudo (circuit, 2); - - THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[1]); - thread_add_timer(master, isis_run_dr_l2, circuit, - 2 * circuit->hello_interval[1], - &circuit->u.bc.t_run_dr[1]); - - thread_add_timer(master, send_l2_csnp, circuit, - isis_jitter(circuit->csnp_interval[level - 1], CSNP_JITTER), - &circuit->t_send_csnp[1]); - } - thread_add_event(master, isis_event_dis_status_change, circuit, 0, NULL); + thread_add_event(master, isis_event_dis_status_change, circuit, 0, + NULL); - return ISIS_OK; + return ISIS_OK; } diff --git a/isisd/isis_dr.h b/isisd/isis_dr.h index 801cd0e47..ed26558b0 100644 --- a/isisd/isis_dr.h +++ b/isisd/isis_dr.h @@ -1,19 +1,19 @@ /* * IS-IS Rout(e)ing protocol - isis_dr.h - * IS-IS designated router related routines + * IS-IS designated router related routines * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -24,19 +24,18 @@ #ifndef _ZEBRA_ISIS_DR_H #define _ZEBRA_ISIS_DR_H -int isis_run_dr_l1 (struct thread *thread); -int isis_run_dr_l2 (struct thread *thread); -int isis_dr_elect (struct isis_circuit *circuit, int level); -int isis_dr_resign (struct isis_circuit *circuit, int level); -int isis_dr_commence (struct isis_circuit *circuit, int level); -const char *isis_disflag2string (int disflag); +int isis_run_dr_l1(struct thread *thread); +int isis_run_dr_l2(struct thread *thread); +int isis_dr_elect(struct isis_circuit *circuit, int level); +int isis_dr_resign(struct isis_circuit *circuit, int level); +int isis_dr_commence(struct isis_circuit *circuit, int level); +const char *isis_disflag2string(int disflag); -enum isis_dis_state -{ - ISIS_IS_NOT_DIS, - ISIS_IS_DIS, - ISIS_WAS_DIS, - ISIS_UNKNOWN_DIS +enum isis_dis_state { + ISIS_IS_NOT_DIS, + ISIS_IS_DIS, + ISIS_WAS_DIS, + ISIS_UNKNOWN_DIS }; #endif /* _ZEBRA_ISIS_DR_H */ diff --git a/isisd/isis_dynhn.c b/isisd/isis_dynhn.c index 35d573d30..9249ad629 100644 --- a/isisd/isis_dynhn.c +++ b/isisd/isis_dynhn.c @@ -2,17 +2,17 @@ * IS-IS Rout(e)ing protocol - isis_dynhn.c * Dynamic hostname cache * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -44,107 +44,100 @@ extern struct host host; struct list *dyn_cache = NULL; -static int dyn_cache_cleanup (struct thread *); +static int dyn_cache_cleanup(struct thread *); -void -dyn_cache_init (void) +void dyn_cache_init(void) { - if (dyn_cache == NULL) - dyn_cache = list_new (); - thread_add_timer(master, dyn_cache_cleanup, NULL, 120, &isis->t_dync_clean); - return; + if (dyn_cache == NULL) + dyn_cache = list_new(); + thread_add_timer(master, dyn_cache_cleanup, NULL, 120, + &isis->t_dync_clean); + return; } -static int -dyn_cache_cleanup (struct thread *thread) +static int dyn_cache_cleanup(struct thread *thread) { - struct listnode *node, *nnode; - struct isis_dynhn *dyn; - time_t now = time (NULL); + struct listnode *node, *nnode; + struct isis_dynhn *dyn; + time_t now = time(NULL); - isis->t_dync_clean = NULL; + isis->t_dync_clean = NULL; - for (ALL_LIST_ELEMENTS (dyn_cache, node, nnode, dyn)) - { - if ((now - dyn->refresh) < MAX_LSP_LIFETIME) - continue; + for (ALL_LIST_ELEMENTS(dyn_cache, node, nnode, dyn)) { + if ((now - dyn->refresh) < MAX_LSP_LIFETIME) + continue; - list_delete_node (dyn_cache, node); - XFREE (MTYPE_ISIS_DYNHN, dyn); - } + list_delete_node(dyn_cache, node); + XFREE(MTYPE_ISIS_DYNHN, dyn); + } - thread_add_timer(master, dyn_cache_cleanup, NULL, 120, &isis->t_dync_clean); - return ISIS_OK; + thread_add_timer(master, dyn_cache_cleanup, NULL, 120, + &isis->t_dync_clean); + return ISIS_OK; } -struct isis_dynhn * -dynhn_find_by_id (const u_char * id) +struct isis_dynhn *dynhn_find_by_id(const u_char *id) { - struct listnode *node = NULL; - struct isis_dynhn *dyn = NULL; + struct listnode *node = NULL; + struct isis_dynhn *dyn = NULL; - for (ALL_LIST_ELEMENTS_RO (dyn_cache, node, dyn)) - if (memcmp (dyn->id, id, ISIS_SYS_ID_LEN) == 0) - return dyn; + for (ALL_LIST_ELEMENTS_RO(dyn_cache, node, dyn)) + if (memcmp(dyn->id, id, ISIS_SYS_ID_LEN) == 0) + return dyn; - return NULL; + return NULL; } -struct isis_dynhn * -dynhn_find_by_name (const char *hostname) +struct isis_dynhn *dynhn_find_by_name(const char *hostname) { - struct listnode *node = NULL; - struct isis_dynhn *dyn = NULL; + struct listnode *node = NULL; + struct isis_dynhn *dyn = NULL; - for (ALL_LIST_ELEMENTS_RO (dyn_cache, node, dyn)) - if (strncmp ((char *)dyn->name.name, hostname, 255) == 0) - return dyn; + for (ALL_LIST_ELEMENTS_RO(dyn_cache, node, dyn)) + if (strncmp((char *)dyn->name.name, hostname, 255) == 0) + return dyn; - return NULL; + return NULL; } -void -isis_dynhn_insert (const u_char * id, struct hostname *hostname, int level) +void isis_dynhn_insert(const u_char *id, struct hostname *hostname, int level) { - struct isis_dynhn *dyn; - - dyn = dynhn_find_by_id (id); - if (dyn) - { - memcpy (&dyn->name, hostname, hostname->namelen + 1); - memcpy (dyn->id, id, ISIS_SYS_ID_LEN); - dyn->refresh = time (NULL); - return; - } - dyn = XCALLOC (MTYPE_ISIS_DYNHN, sizeof (struct isis_dynhn)); - if (!dyn) - { - zlog_warn ("isis_dynhn_insert(): out of memory!"); - return; - } - - /* we also copy the length */ - memcpy (&dyn->name, hostname, hostname->namelen + 1); - memcpy (dyn->id, id, ISIS_SYS_ID_LEN); - dyn->refresh = time (NULL); - dyn->level = level; - - listnode_add (dyn_cache, dyn); - - return; + struct isis_dynhn *dyn; + + dyn = dynhn_find_by_id(id); + if (dyn) { + memcpy(&dyn->name, hostname, hostname->namelen + 1); + memcpy(dyn->id, id, ISIS_SYS_ID_LEN); + dyn->refresh = time(NULL); + return; + } + dyn = XCALLOC(MTYPE_ISIS_DYNHN, sizeof(struct isis_dynhn)); + if (!dyn) { + zlog_warn("isis_dynhn_insert(): out of memory!"); + return; + } + + /* we also copy the length */ + memcpy(&dyn->name, hostname, hostname->namelen + 1); + memcpy(dyn->id, id, ISIS_SYS_ID_LEN); + dyn->refresh = time(NULL); + dyn->level = level; + + listnode_add(dyn_cache, dyn); + + return; } -void -isis_dynhn_remove (const u_char * id) +void isis_dynhn_remove(const u_char *id) { - struct isis_dynhn *dyn; - - dyn = dynhn_find_by_id (id); - if (!dyn) - return; - listnode_delete (dyn_cache, dyn); - XFREE (MTYPE_ISIS_DYNHN, dyn); - return; + struct isis_dynhn *dyn; + + dyn = dynhn_find_by_id(id); + if (!dyn) + return; + listnode_delete(dyn_cache, dyn); + XFREE(MTYPE_ISIS_DYNHN, dyn); + return; } /* @@ -153,19 +146,19 @@ isis_dynhn_remove (const u_char * id) * 2 0000.0000.0002 bar-gw * * 0000.0000.0004 this-gw */ -void -dynhn_print_all (struct vty *vty) +void dynhn_print_all(struct vty *vty) { - struct listnode *node; - struct isis_dynhn *dyn; - - vty_out (vty, "Level System ID Dynamic Hostname\n"); - for (ALL_LIST_ELEMENTS_RO (dyn_cache, node, dyn)) - { - vty_out (vty, "%-7d", dyn->level); - vty_out (vty, "%-15s%-15s\n", sysid_print (dyn->id),dyn->name.name); - } - - vty_out (vty, " * %s %s\n", sysid_print (isis->sysid),unix_hostname()); - return; + struct listnode *node; + struct isis_dynhn *dyn; + + vty_out(vty, "Level System ID Dynamic Hostname\n"); + for (ALL_LIST_ELEMENTS_RO(dyn_cache, node, dyn)) { + vty_out(vty, "%-7d", dyn->level); + vty_out(vty, "%-15s%-15s\n", sysid_print(dyn->id), + dyn->name.name); + } + + vty_out(vty, " * %s %s\n", sysid_print(isis->sysid), + unix_hostname()); + return; } diff --git a/isisd/isis_dynhn.h b/isisd/isis_dynhn.h index c36d9a009..f3ca94d40 100644 --- a/isisd/isis_dynhn.h +++ b/isisd/isis_dynhn.h @@ -3,17 +3,17 @@ * Dynamic hostname cache * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -23,19 +23,18 @@ #ifndef _ZEBRA_ISIS_DYNHN_H #define _ZEBRA_ISIS_DYNHN_H -struct isis_dynhn -{ - u_char id[ISIS_SYS_ID_LEN]; - struct hostname name; - time_t refresh; - int level; +struct isis_dynhn { + u_char id[ISIS_SYS_ID_LEN]; + struct hostname name; + time_t refresh; + int level; }; -void dyn_cache_init (void); -void isis_dynhn_insert (const u_char * id, struct hostname *hostname, int level); -void isis_dynhn_remove (const u_char * id); -struct isis_dynhn *dynhn_find_by_id (const u_char * id); -struct isis_dynhn *dynhn_find_by_name (const char *hostname); -void dynhn_print_all (struct vty *vty); +void dyn_cache_init(void); +void isis_dynhn_insert(const u_char *id, struct hostname *hostname, int level); +void isis_dynhn_remove(const u_char *id); +struct isis_dynhn *dynhn_find_by_id(const u_char *id); +struct isis_dynhn *dynhn_find_by_name(const char *hostname); +void dynhn_print_all(struct vty *vty); #endif /* _ZEBRA_ISIS_DYNHN_H */ diff --git a/isisd/isis_events.c b/isisd/isis_events.c index 8011d2db9..9af256ba3 100644 --- a/isisd/isis_events.c +++ b/isisd/isis_events.c @@ -1,18 +1,18 @@ /* - * IS-IS Rout(e)ing protocol - isis_events.h + * IS-IS Rout(e)ing protocol - isis_events.h * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -50,7 +50,7 @@ #include "isisd/isis_events.h" #include "isisd/isis_spf.h" -/* debug isis-spf spf-events +/* debug isis-spf spf-events 4w4d: ISIS-Spf (tlt): L2 SPF needed, new adjacency, from 0x609229F4 4w4d: ISIS-Spf (tlt): L2, 0000.0000.0042.01-00 TLV contents changed, code 0x2 4w4d: ISIS-Spf (tlt): L2, new LSP 0 DEAD.BEEF.0043.00-00 @@ -58,222 +58,212 @@ 4w5d: ISIS-Spf (tlt): L2 SPF needed, periodic SPF, from 0x6091C844 */ -void -isis_event_circuit_state_change (struct isis_circuit *circuit, - struct isis_area *area, int up) +void isis_event_circuit_state_change(struct isis_circuit *circuit, + struct isis_area *area, int up) { - area->circuit_state_changes++; + area->circuit_state_changes++; - if (isis->debugs & DEBUG_EVENTS) - zlog_debug ("ISIS-Evt (%s) circuit %s", area->area_tag, - up ? "up" : "down"); + if (isis->debugs & DEBUG_EVENTS) + zlog_debug("ISIS-Evt (%s) circuit %s", area->area_tag, + up ? "up" : "down"); - /* - * Regenerate LSPs this affects - */ - lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 0); + /* + * Regenerate LSPs this affects + */ + lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 0); - return; + return; } -static void -circuit_commence_level (struct isis_circuit *circuit, int level) +static void circuit_commence_level(struct isis_circuit *circuit, int level) { - if (level == 1) - { - if (! circuit->is_passive) - thread_add_timer(master, send_l1_psnp, circuit, - isis_jitter(circuit->psnp_interval[0], PSNP_JITTER), - &circuit->t_send_psnp[0]); - - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - { - thread_add_timer(master, isis_run_dr_l1, circuit, - 2 * circuit->hello_interval[0], - &circuit->u.bc.t_run_dr[0]); - - thread_add_timer(master, send_lan_l1_hello, circuit, - isis_jitter(circuit->hello_interval[0], IIH_JITTER), - &circuit->u.bc.t_send_lan_hello[0]); - - circuit->u.bc.lan_neighs[0] = list_new (); + if (level == 1) { + if (!circuit->is_passive) + thread_add_timer(master, send_l1_psnp, circuit, + isis_jitter(circuit->psnp_interval[0], + PSNP_JITTER), + &circuit->t_send_psnp[0]); + + if (circuit->circ_type == CIRCUIT_T_BROADCAST) { + thread_add_timer(master, isis_run_dr_l1, circuit, + 2 * circuit->hello_interval[0], + &circuit->u.bc.t_run_dr[0]); + + thread_add_timer(master, send_lan_l1_hello, circuit, + isis_jitter(circuit->hello_interval[0], + IIH_JITTER), + &circuit->u.bc.t_send_lan_hello[0]); + + circuit->u.bc.lan_neighs[0] = list_new(); + } + } else { + if (!circuit->is_passive) + thread_add_timer(master, send_l2_psnp, circuit, + isis_jitter(circuit->psnp_interval[1], + PSNP_JITTER), + &circuit->t_send_psnp[1]); + + if (circuit->circ_type == CIRCUIT_T_BROADCAST) { + thread_add_timer(master, isis_run_dr_l2, circuit, + 2 * circuit->hello_interval[1], + &circuit->u.bc.t_run_dr[1]); + + thread_add_timer(master, send_lan_l2_hello, circuit, + isis_jitter(circuit->hello_interval[1], + IIH_JITTER), + &circuit->u.bc.t_send_lan_hello[1]); + + circuit->u.bc.lan_neighs[1] = list_new(); + } } - } - else - { - if (! circuit->is_passive) - thread_add_timer(master, send_l2_psnp, circuit, - isis_jitter(circuit->psnp_interval[1], PSNP_JITTER), - &circuit->t_send_psnp[1]); - - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - { - thread_add_timer(master, isis_run_dr_l2, circuit, - 2 * circuit->hello_interval[1], - &circuit->u.bc.t_run_dr[1]); - - thread_add_timer(master, send_lan_l2_hello, circuit, - isis_jitter(circuit->hello_interval[1], IIH_JITTER), - &circuit->u.bc.t_send_lan_hello[1]); - - circuit->u.bc.lan_neighs[1] = list_new (); - } - } - return; + return; } -static void -circuit_resign_level (struct isis_circuit *circuit, int level) +static void circuit_resign_level(struct isis_circuit *circuit, int level) { - int idx = level - 1; - - THREAD_TIMER_OFF (circuit->t_send_csnp[idx]); - THREAD_TIMER_OFF (circuit->t_send_psnp[idx]); - - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - { - THREAD_TIMER_OFF (circuit->u.bc.t_send_lan_hello[idx]); - THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[idx]); - THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[idx]); - circuit->lsp_regenerate_pending[idx] = 0; - circuit->u.bc.run_dr_elect[idx] = 0; - if (circuit->u.bc.lan_neighs[idx] != NULL) { - list_delete (circuit->u.bc.lan_neighs[idx]); - circuit->u.bc.lan_neighs[idx] = NULL; - } - } - - return; + int idx = level - 1; + + THREAD_TIMER_OFF(circuit->t_send_csnp[idx]); + THREAD_TIMER_OFF(circuit->t_send_psnp[idx]); + + if (circuit->circ_type == CIRCUIT_T_BROADCAST) { + THREAD_TIMER_OFF(circuit->u.bc.t_send_lan_hello[idx]); + THREAD_TIMER_OFF(circuit->u.bc.t_run_dr[idx]); + THREAD_TIMER_OFF(circuit->u.bc.t_refresh_pseudo_lsp[idx]); + circuit->lsp_regenerate_pending[idx] = 0; + circuit->u.bc.run_dr_elect[idx] = 0; + if (circuit->u.bc.lan_neighs[idx] != NULL) { + list_delete(circuit->u.bc.lan_neighs[idx]); + circuit->u.bc.lan_neighs[idx] = NULL; + } + } + + return; } -void -isis_circuit_is_type_set (struct isis_circuit *circuit, int newtype) +void isis_circuit_is_type_set(struct isis_circuit *circuit, int newtype) { - if (circuit->state != C_STATE_UP) - { - circuit->is_type = newtype; - return; - } - - if (isis->debugs & DEBUG_EVENTS) - zlog_debug ("ISIS-Evt (%s) circuit type change %s -> %s", - circuit->area->area_tag, - circuit_t2string (circuit->is_type), - circuit_t2string (newtype)); - - if (circuit->is_type == newtype) - return; /* No change */ - - if (!(newtype & circuit->area->is_type)) - { - zlog_err ("ISIS-Evt (%s) circuit type change - invalid level %s because" - " area is %s", circuit->area->area_tag, - circuit_t2string (newtype), - circuit_t2string (circuit->area->is_type)); - return; - } - - if (! circuit->is_passive) - { - switch (circuit->is_type) - { - case IS_LEVEL_1: - if (newtype == IS_LEVEL_2) - circuit_resign_level (circuit, 1); - circuit_commence_level (circuit, 2); - break; - case IS_LEVEL_1_AND_2: - if (newtype == IS_LEVEL_1) - circuit_resign_level (circuit, 2); - else - circuit_resign_level (circuit, 1); - break; - case IS_LEVEL_2: - if (newtype == IS_LEVEL_1) - circuit_resign_level (circuit, 2); - circuit_commence_level (circuit, 1); - break; - default: - break; - } - } - - circuit->is_type = newtype; - lsp_regenerate_schedule (circuit->area, IS_LEVEL_1 | IS_LEVEL_2, 0); - - return; + if (circuit->state != C_STATE_UP) { + circuit->is_type = newtype; + return; + } + + if (isis->debugs & DEBUG_EVENTS) + zlog_debug("ISIS-Evt (%s) circuit type change %s -> %s", + circuit->area->area_tag, + circuit_t2string(circuit->is_type), + circuit_t2string(newtype)); + + if (circuit->is_type == newtype) + return; /* No change */ + + if (!(newtype & circuit->area->is_type)) { + zlog_err( + "ISIS-Evt (%s) circuit type change - invalid level %s because" + " area is %s", + circuit->area->area_tag, circuit_t2string(newtype), + circuit_t2string(circuit->area->is_type)); + return; + } + + if (!circuit->is_passive) { + switch (circuit->is_type) { + case IS_LEVEL_1: + if (newtype == IS_LEVEL_2) + circuit_resign_level(circuit, 1); + circuit_commence_level(circuit, 2); + break; + case IS_LEVEL_1_AND_2: + if (newtype == IS_LEVEL_1) + circuit_resign_level(circuit, 2); + else + circuit_resign_level(circuit, 1); + break; + case IS_LEVEL_2: + if (newtype == IS_LEVEL_1) + circuit_resign_level(circuit, 2); + circuit_commence_level(circuit, 1); + break; + default: + break; + } + } + + circuit->is_type = newtype; + lsp_regenerate_schedule(circuit->area, IS_LEVEL_1 | IS_LEVEL_2, 0); + + return; } - /* 04/18/2002 by Gwak. */ - /************************************************************************** - * - * EVENTS for LSP generation - * - * 1) an Adajacency or Circuit Up/Down event - * 2) a chnage in Circuit metric - * 3) a change in Reachable Address metric - * 4) a change in manualAreaAddresses - * 5) a change in systemID - * 6) a change in DIS status - * 7) a chnage in the waiting status - * - * *********************************************************************** - * - * current support event - * - * 1) Adjacency Up/Down event - * 6) a change in DIS status - * - * ***********************************************************************/ - -void -isis_event_adjacency_state_change (struct isis_adjacency *adj, int newstate) +/* 04/18/2002 by Gwak. */ +/************************************************************************** + * + * EVENTS for LSP generation + * + * 1) an Adajacency or Circuit Up/Down event + * 2) a chnage in Circuit metric + * 3) a change in Reachable Address metric + * 4) a change in manualAreaAddresses + * 5) a change in systemID + * 6) a change in DIS status + * 7) a chnage in the waiting status + * + * *********************************************************************** + * + * current support event + * + * 1) Adjacency Up/Down event + * 6) a change in DIS status + * + * ***********************************************************************/ + +void isis_event_adjacency_state_change(struct isis_adjacency *adj, int newstate) { - /* adjacency state change event. - * - the only proto-type was supported */ + /* adjacency state change event. + * - the only proto-type was supported */ - /* invalid arguments */ - if (!adj || !adj->circuit || !adj->circuit->area) - return; + /* invalid arguments */ + if (!adj || !adj->circuit || !adj->circuit->area) + return; - if (isis->debugs & DEBUG_EVENTS) - zlog_debug ("ISIS-Evt (%s) Adjacency State change", - adj->circuit->area->area_tag); + if (isis->debugs & DEBUG_EVENTS) + zlog_debug("ISIS-Evt (%s) Adjacency State change", + adj->circuit->area->area_tag); - /* LSP generation again */ - lsp_regenerate_schedule (adj->circuit->area, IS_LEVEL_1 | IS_LEVEL_2, 0); + /* LSP generation again */ + lsp_regenerate_schedule(adj->circuit->area, IS_LEVEL_1 | IS_LEVEL_2, 0); - return; + return; } /* events supporting code */ -int -isis_event_dis_status_change (struct thread *thread) +int isis_event_dis_status_change(struct thread *thread) { - struct isis_circuit *circuit; + struct isis_circuit *circuit; - circuit = THREAD_ARG (thread); + circuit = THREAD_ARG(thread); - /* invalid arguments */ - if (!circuit || !circuit->area) - return 0; - if (isis->debugs & DEBUG_EVENTS) - zlog_debug ("ISIS-Evt (%s) DIS status change", circuit->area->area_tag); + /* invalid arguments */ + if (!circuit || !circuit->area) + return 0; + if (isis->debugs & DEBUG_EVENTS) + zlog_debug("ISIS-Evt (%s) DIS status change", + circuit->area->area_tag); - /* LSP generation again */ - lsp_regenerate_schedule (circuit->area, IS_LEVEL_1 | IS_LEVEL_2, 0); + /* LSP generation again */ + lsp_regenerate_schedule(circuit->area, IS_LEVEL_1 | IS_LEVEL_2, 0); - return 0; + return 0; } -void -isis_event_auth_failure (char *area_tag, const char *error_string, u_char *sysid) +void isis_event_auth_failure(char *area_tag, const char *error_string, + u_char *sysid) { - if (isis->debugs & DEBUG_EVENTS) - zlog_debug ("ISIS-Evt (%s) Authentication failure %s from %s", - area_tag, error_string, sysid_print (sysid)); + if (isis->debugs & DEBUG_EVENTS) + zlog_debug("ISIS-Evt (%s) Authentication failure %s from %s", + area_tag, error_string, sysid_print(sysid)); - return; + return; } diff --git a/isisd/isis_events.h b/isisd/isis_events.h index e9aa05db7..0ed2059c6 100644 --- a/isisd/isis_events.h +++ b/isisd/isis_events.h @@ -1,18 +1,18 @@ /* - * IS-IS Rout(e)ing protocol - isis_events.h + * IS-IS Rout(e)ing protocol - isis_events.h * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -25,17 +25,16 @@ /* * Events related to circuit */ -void isis_event_circuit_state_change (struct isis_circuit *circuit, - struct isis_area *area, int state); -void isis_event_circuit_type_change (struct isis_circuit *circuit, - int newtype); +void isis_event_circuit_state_change(struct isis_circuit *circuit, + struct isis_area *area, int state); +void isis_event_circuit_type_change(struct isis_circuit *circuit, int newtype); /* * Events related to adjacencies */ -void isis_event_adjacency_state_change (struct isis_adjacency *adj, - int newstate); +void isis_event_adjacency_state_change(struct isis_adjacency *adj, + int newstate); -int isis_event_dis_status_change (struct thread *thread); +int isis_event_dis_status_change(struct thread *thread); /* * Error events @@ -43,7 +42,7 @@ int isis_event_dis_status_change (struct thread *thread); #define AUTH_ERROR_TYPE_LSP 3 #define AUTH_ERROR_TYPE_SNP 2 #define AUTH_ERROR_TYPE_HELLO 1 -void isis_event_auth_failure (char *area_tag, const char *error_string, - u_char *sysid); +void isis_event_auth_failure(char *area_tag, const char *error_string, + u_char *sysid); #endif /* _ZEBRA_ISIS_EVENTS_H */ diff --git a/isisd/isis_flags.c b/isisd/isis_flags.c index 6c88cfeda..e28d90d3d 100644 --- a/isisd/isis_flags.c +++ b/isisd/isis_flags.c @@ -3,17 +3,17 @@ * Routines for manipulation of SSN and SRM flags * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -29,58 +29,49 @@ #include "isisd/isis_common.h" #include "isisd/isis_flags.h" -void -flags_initialize (struct flags *flags) +void flags_initialize(struct flags *flags) { - flags->maxindex = 0; - flags->free_idcs = NULL; + flags->maxindex = 0; + flags->free_idcs = NULL; } -long int -flags_get_index (struct flags *flags) +long int flags_get_index(struct flags *flags) { - struct listnode *node; - long int index; + struct listnode *node; + long int index; - if (flags->free_idcs == NULL || flags->free_idcs->count == 0) - { - index = flags->maxindex++; - } - else - { - node = listhead (flags->free_idcs); - index = (long int) listgetdata (node); - listnode_delete (flags->free_idcs, (void *) index); - index--; - } + if (flags->free_idcs == NULL || flags->free_idcs->count == 0) { + index = flags->maxindex++; + } else { + node = listhead(flags->free_idcs); + index = (long int)listgetdata(node); + listnode_delete(flags->free_idcs, (void *)index); + index--; + } - return index; + return index; } -void -flags_free_index (struct flags *flags, long int index) +void flags_free_index(struct flags *flags, long int index) { - if (index + 1 == flags->maxindex) - { - flags->maxindex--; - return; - } + if (index + 1 == flags->maxindex) { + flags->maxindex--; + return; + } - if (flags->free_idcs == NULL) - { - flags->free_idcs = list_new (); - } + if (flags->free_idcs == NULL) { + flags->free_idcs = list_new(); + } - listnode_add (flags->free_idcs, (void *) (index + 1)); + listnode_add(flags->free_idcs, (void *)(index + 1)); - return; + return; } -int -flags_any_set (u_int32_t * flags) +int flags_any_set(u_int32_t *flags) { - u_int32_t zero[ISIS_MAX_CIRCUITS]; - memset (zero, 0x00, ISIS_MAX_CIRCUITS * 4); + u_int32_t zero[ISIS_MAX_CIRCUITS]; + memset(zero, 0x00, ISIS_MAX_CIRCUITS * 4); - return bcmp (flags, zero, ISIS_MAX_CIRCUITS * 4); + return bcmp(flags, zero, ISIS_MAX_CIRCUITS * 4); } diff --git a/isisd/isis_flags.h b/isisd/isis_flags.h index ba11cf42b..c57f77880 100644 --- a/isisd/isis_flags.h +++ b/isisd/isis_flags.h @@ -3,17 +3,17 @@ * Routines for manipulation of SSN and SRM flags * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -31,38 +31,37 @@ /* * Flags structure for SSN and SRM flags */ -struct flags -{ - int maxindex; - struct list *free_idcs; +struct flags { + int maxindex; + struct list *free_idcs; }; -void flags_initialize (struct flags *flags); -long int flags_get_index (struct flags *flags); -void flags_free_index (struct flags *flags, long int index); -int flags_any_set (u_int32_t * flags); +void flags_initialize(struct flags *flags); +long int flags_get_index(struct flags *flags); +void flags_free_index(struct flags *flags, long int index); +int flags_any_set(u_int32_t *flags); -#define ISIS_SET_FLAG(F,C) \ - { \ - F[C->idx>>5] |= (1<<(C->idx & 0x1F)); \ - } +#define ISIS_SET_FLAG(F, C) \ + { \ + F[C->idx >> 5] |= (1 << (C->idx & 0x1F)); \ + } -#define ISIS_CLEAR_FLAG(F,C) \ - { \ - F[C->idx>>5] &= ~(1<<(C->idx & 0x1F)); \ - } +#define ISIS_CLEAR_FLAG(F, C) \ + { \ + F[C->idx >> 5] &= ~(1 << (C->idx & 0x1F)); \ + } #define ISIS_CHECK_FLAG(F, C) (F[(C)->idx>>5] & (1<<(C->idx & 0x1F))) /* sets all u_32int_t flags to 1 */ -#define ISIS_FLAGS_SET_ALL(FLAGS) \ - { \ - memset(FLAGS,0xFF,ISIS_MAX_CIRCUITS*4); \ - } +#define ISIS_FLAGS_SET_ALL(FLAGS) \ + { \ + memset(FLAGS, 0xFF, ISIS_MAX_CIRCUITS * 4); \ + } -#define ISIS_FLAGS_CLEAR_ALL(FLAGS) \ - { \ - memset(FLAGS,0x00,ISIS_MAX_CIRCUITS*4); \ - } +#define ISIS_FLAGS_CLEAR_ALL(FLAGS) \ + { \ + memset(FLAGS, 0x00, ISIS_MAX_CIRCUITS * 4); \ + } #endif /* _ZEBRA_ISIS_FLAGS_H */ diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index ed376058b..40c6141ab 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -3,18 +3,18 @@ * LSP processing * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * Copyright (C) 2013-2015 Christian Franke * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -56,2214 +56,2288 @@ #include "isisd/isis_mt.h" /* staticly assigned vars for printing purposes */ -char lsp_bits_string[200]; /* FIXME: enough ? */ +char lsp_bits_string[200]; /* FIXME: enough ? */ -static int lsp_l1_refresh (struct thread *thread); -static int lsp_l2_refresh (struct thread *thread); -static int lsp_l1_refresh_pseudo (struct thread *thread); -static int lsp_l2_refresh_pseudo (struct thread *thread); +static int lsp_l1_refresh(struct thread *thread); +static int lsp_l2_refresh(struct thread *thread); +static int lsp_l1_refresh_pseudo(struct thread *thread); +static int lsp_l2_refresh_pseudo(struct thread *thread); -int -lsp_id_cmp (u_char * id1, u_char * id2) +int lsp_id_cmp(u_char *id1, u_char *id2) { - return memcmp (id1, id2, ISIS_SYS_ID_LEN + 2); + return memcmp(id1, id2, ISIS_SYS_ID_LEN + 2); } -dict_t * -lsp_db_init (void) +dict_t *lsp_db_init(void) { - dict_t *dict; + dict_t *dict; - dict = dict_create (DICTCOUNT_T_MAX, (dict_comp_t) lsp_id_cmp); + dict = dict_create(DICTCOUNT_T_MAX, (dict_comp_t)lsp_id_cmp); - return dict; + return dict; } -struct isis_lsp * -lsp_search (u_char * id, dict_t * lspdb) +struct isis_lsp *lsp_search(u_char *id, dict_t *lspdb) { - dnode_t *node; + dnode_t *node; #ifdef EXTREME_DEBUG - dnode_t *dn; - - zlog_debug ("searching db"); - for (dn = dict_first (lspdb); dn; dn = dict_next (lspdb, dn)) - { - zlog_debug ("%s\t%pX", rawlspid_print ((u_char *) dnode_getkey (dn)), - dnode_get (dn)); - } + dnode_t *dn; + + zlog_debug("searching db"); + for (dn = dict_first(lspdb); dn; dn = dict_next(lspdb, dn)) { + zlog_debug("%s\t%pX", + rawlspid_print((u_char *)dnode_getkey(dn)), + dnode_get(dn)); + } #endif /* EXTREME DEBUG */ - node = dict_lookup (lspdb, id); + node = dict_lookup(lspdb, id); - if (node) - return (struct isis_lsp *) dnode_get (node); + if (node) + return (struct isis_lsp *)dnode_get(node); - return NULL; + return NULL; } -static void -lsp_clear_data (struct isis_lsp *lsp) +static void lsp_clear_data(struct isis_lsp *lsp) { - if (!lsp) - return; - - if (lsp->tlv_data.hostname) - isis_dynhn_remove (lsp->lsp_header->lsp_id); - - if (lsp->own_lsp) - { - if (lsp->tlv_data.nlpids) - XFREE (MTYPE_ISIS_TLV, lsp->tlv_data.nlpids); - if (lsp->tlv_data.hostname) - XFREE (MTYPE_ISIS_TLV, lsp->tlv_data.hostname); - if (lsp->tlv_data.router_id) - XFREE (MTYPE_ISIS_TLV, lsp->tlv_data.router_id); - } - - free_tlvs (&lsp->tlv_data); + if (!lsp) + return; + + if (lsp->tlv_data.hostname) + isis_dynhn_remove(lsp->lsp_header->lsp_id); + + if (lsp->own_lsp) { + if (lsp->tlv_data.nlpids) + XFREE(MTYPE_ISIS_TLV, lsp->tlv_data.nlpids); + if (lsp->tlv_data.hostname) + XFREE(MTYPE_ISIS_TLV, lsp->tlv_data.hostname); + if (lsp->tlv_data.router_id) + XFREE(MTYPE_ISIS_TLV, lsp->tlv_data.router_id); + } + + free_tlvs(&lsp->tlv_data); } -static void -lsp_destroy (struct isis_lsp *lsp) +static void lsp_destroy(struct isis_lsp *lsp) { - struct listnode *cnode, *lnode, *lnnode; - struct isis_lsp *lsp_in_list; - struct isis_circuit *circuit; - - if (!lsp) - return; - - if (lsp->area->circuit_list) { - for (ALL_LIST_ELEMENTS_RO (lsp->area->circuit_list, cnode, circuit)) - { - if (circuit->lsp_queue == NULL) - continue; - for (ALL_LIST_ELEMENTS (circuit->lsp_queue, lnode, lnnode, lsp_in_list)) - if (lsp_in_list == lsp) - list_delete_node(circuit->lsp_queue, lnode); - } - } - ISIS_FLAGS_CLEAR_ALL (lsp->SSNflags); - ISIS_FLAGS_CLEAR_ALL (lsp->SRMflags); - - lsp_clear_data (lsp); - - if (LSP_FRAGMENT (lsp->lsp_header->lsp_id) == 0 && lsp->lspu.frags) - { - list_delete (lsp->lspu.frags); - lsp->lspu.frags = NULL; - } - - isis_spf_schedule (lsp->area, lsp->level); - - if (lsp->pdu) - stream_free (lsp->pdu); - XFREE (MTYPE_ISIS_LSP, lsp); + struct listnode *cnode, *lnode, *lnnode; + struct isis_lsp *lsp_in_list; + struct isis_circuit *circuit; + + if (!lsp) + return; + + if (lsp->area->circuit_list) { + for (ALL_LIST_ELEMENTS_RO(lsp->area->circuit_list, cnode, + circuit)) { + if (circuit->lsp_queue == NULL) + continue; + for (ALL_LIST_ELEMENTS(circuit->lsp_queue, lnode, + lnnode, lsp_in_list)) + if (lsp_in_list == lsp) + list_delete_node(circuit->lsp_queue, + lnode); + } + } + ISIS_FLAGS_CLEAR_ALL(lsp->SSNflags); + ISIS_FLAGS_CLEAR_ALL(lsp->SRMflags); + + lsp_clear_data(lsp); + + if (LSP_FRAGMENT(lsp->lsp_header->lsp_id) == 0 && lsp->lspu.frags) { + list_delete(lsp->lspu.frags); + lsp->lspu.frags = NULL; + } + + isis_spf_schedule(lsp->area, lsp->level); + + if (lsp->pdu) + stream_free(lsp->pdu); + XFREE(MTYPE_ISIS_LSP, lsp); } -void -lsp_db_destroy (dict_t * lspdb) +void lsp_db_destroy(dict_t *lspdb) { - dnode_t *dnode, *next; - struct isis_lsp *lsp; - - dnode = dict_first (lspdb); - while (dnode) - { - next = dict_next (lspdb, dnode); - lsp = dnode_get (dnode); - lsp_destroy (lsp); - dict_delete_free (lspdb, dnode); - dnode = next; - } - - dict_free (lspdb); - - return; + dnode_t *dnode, *next; + struct isis_lsp *lsp; + + dnode = dict_first(lspdb); + while (dnode) { + next = dict_next(lspdb, dnode); + lsp = dnode_get(dnode); + lsp_destroy(lsp); + dict_delete_free(lspdb, dnode); + dnode = next; + } + + dict_free(lspdb); + + return; } /* * Remove all the frags belonging to the given lsp */ -static void -lsp_remove_frags (struct list *frags, dict_t * lspdb) +static void lsp_remove_frags(struct list *frags, dict_t *lspdb) { - dnode_t *dnode; - struct listnode *lnode, *lnnode; - struct isis_lsp *lsp; - - for (ALL_LIST_ELEMENTS (frags, lnode, lnnode, lsp)) - { - dnode = dict_lookup (lspdb, lsp->lsp_header->lsp_id); - lsp_destroy (lsp); - dnode_destroy (dict_delete (lspdb, dnode)); - } + dnode_t *dnode; + struct listnode *lnode, *lnnode; + struct isis_lsp *lsp; + + for (ALL_LIST_ELEMENTS(frags, lnode, lnnode, lsp)) { + dnode = dict_lookup(lspdb, lsp->lsp_header->lsp_id); + lsp_destroy(lsp); + dnode_destroy(dict_delete(lspdb, dnode)); + } - list_delete_all_node (frags); + list_delete_all_node(frags); - return; + return; } -void -lsp_search_and_destroy (u_char * id, dict_t * lspdb) +void lsp_search_and_destroy(u_char *id, dict_t *lspdb) { - dnode_t *node; - struct isis_lsp *lsp; - - node = dict_lookup (lspdb, id); - if (node) - { - node = dict_delete (lspdb, node); - lsp = dnode_get (node); - /* - * If this is a zero lsp, remove all the frags now - */ - if (LSP_FRAGMENT (lsp->lsp_header->lsp_id) == 0) - { - if (lsp->lspu.frags) - lsp_remove_frags (lsp->lspu.frags, lspdb); - } - else - { - /* - * else just remove this frag, from the zero lsps' frag list - */ - if (lsp->lspu.zero_lsp && lsp->lspu.zero_lsp->lspu.frags) - listnode_delete (lsp->lspu.zero_lsp->lspu.frags, lsp); - } - lsp_destroy (lsp); - dnode_destroy (node); - } + dnode_t *node; + struct isis_lsp *lsp; + + node = dict_lookup(lspdb, id); + if (node) { + node = dict_delete(lspdb, node); + lsp = dnode_get(node); + /* + * If this is a zero lsp, remove all the frags now + */ + if (LSP_FRAGMENT(lsp->lsp_header->lsp_id) == 0) { + if (lsp->lspu.frags) + lsp_remove_frags(lsp->lspu.frags, lspdb); + } else { + /* + * else just remove this frag, from the zero lsps' frag + * list + */ + if (lsp->lspu.zero_lsp + && lsp->lspu.zero_lsp->lspu.frags) + listnode_delete(lsp->lspu.zero_lsp->lspu.frags, + lsp); + } + lsp_destroy(lsp); + dnode_destroy(node); + } } /* * Compares a LSP to given values * Params are given in net order */ -int -lsp_compare (char *areatag, struct isis_lsp *lsp, u_int32_t seq_num, - u_int16_t checksum, u_int16_t rem_lifetime) +int lsp_compare(char *areatag, struct isis_lsp *lsp, u_int32_t seq_num, + u_int16_t checksum, u_int16_t rem_lifetime) { - /* no point in double ntohl on seqnum */ - if (lsp->lsp_header->seq_num == seq_num && - lsp->lsp_header->checksum == checksum && - /*comparing with 0, no need to do ntohl */ - ((lsp->lsp_header->rem_lifetime == 0 && rem_lifetime == 0) || - (lsp->lsp_header->rem_lifetime != 0 && rem_lifetime != 0))) - { - if (isis->debugs & DEBUG_SNP_PACKETS) - { - zlog_debug ("ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04x," - " lifetime %us", - areatag, - rawlspid_print (lsp->lsp_header->lsp_id), - ntohl (lsp->lsp_header->seq_num), - ntohs (lsp->lsp_header->checksum), - ntohs (lsp->lsp_header->rem_lifetime)); - zlog_debug ("ISIS-Snp (%s): is equal to ours seq 0x%08x," - " cksum 0x%04x, lifetime %us", - areatag, - ntohl (seq_num), ntohs (checksum), ntohs (rem_lifetime)); - } - return LSP_EQUAL; - } - - /* - * LSPs with identical checksums should only be treated as newer if: - * a) The current LSP has a remaining lifetime != 0 and the other LSP has a - * remaining lifetime == 0. In this case, we should participate in the purge - * and should not treat the current LSP with remaining lifetime == 0 as older. - * b) The LSP has an incorrect checksum. In this case, we need to react as given - * in 7.3.16.2. - */ - if (ntohl (seq_num) > ntohl (lsp->lsp_header->seq_num) - || (ntohl(seq_num) == ntohl(lsp->lsp_header->seq_num) - && ( (lsp->lsp_header->rem_lifetime != 0 - && rem_lifetime == 0) - || lsp->lsp_header->checksum != checksum))) - { - if (isis->debugs & DEBUG_SNP_PACKETS) - { - zlog_debug ("ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04x," - " lifetime %us", - areatag, - rawlspid_print (lsp->lsp_header->lsp_id), - ntohl (seq_num), ntohs (checksum), ntohs (rem_lifetime)); - zlog_debug ("ISIS-Snp (%s): is newer than ours seq 0x%08x, " - "cksum 0x%04x, lifetime %us", - areatag, - ntohl (lsp->lsp_header->seq_num), - ntohs (lsp->lsp_header->checksum), - ntohs (lsp->lsp_header->rem_lifetime)); - } - return LSP_NEWER; - } - if (isis->debugs & DEBUG_SNP_PACKETS) - { - zlog_debug - ("ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04x, lifetime %us", - areatag, rawlspid_print (lsp->lsp_header->lsp_id), ntohl (seq_num), - ntohs (checksum), ntohs (rem_lifetime)); - zlog_debug ("ISIS-Snp (%s): is older than ours seq 0x%08x," - " cksum 0x%04x, lifetime %us", areatag, - ntohl (lsp->lsp_header->seq_num), - ntohs (lsp->lsp_header->checksum), - ntohs (lsp->lsp_header->rem_lifetime)); - } - - return LSP_OLDER; + /* no point in double ntohl on seqnum */ + if (lsp->lsp_header->seq_num == seq_num + && lsp->lsp_header->checksum == checksum && + /*comparing with 0, no need to do ntohl */ + ((lsp->lsp_header->rem_lifetime == 0 && rem_lifetime == 0) + || (lsp->lsp_header->rem_lifetime != 0 && rem_lifetime != 0))) { + if (isis->debugs & DEBUG_SNP_PACKETS) { + zlog_debug( + "ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04x," + " lifetime %us", + areatag, + rawlspid_print(lsp->lsp_header->lsp_id), + ntohl(lsp->lsp_header->seq_num), + ntohs(lsp->lsp_header->checksum), + ntohs(lsp->lsp_header->rem_lifetime)); + zlog_debug( + "ISIS-Snp (%s): is equal to ours seq 0x%08x," + " cksum 0x%04x, lifetime %us", + areatag, ntohl(seq_num), ntohs(checksum), + ntohs(rem_lifetime)); + } + return LSP_EQUAL; + } + + /* + * LSPs with identical checksums should only be treated as newer if: + * a) The current LSP has a remaining lifetime != 0 and the other LSP + * has a + * remaining lifetime == 0. In this case, we should participate in + * the purge + * and should not treat the current LSP with remaining lifetime == 0 + * as older. + * b) The LSP has an incorrect checksum. In this case, we need to react + * as given + * in 7.3.16.2. + */ + if (ntohl(seq_num) > ntohl(lsp->lsp_header->seq_num) + || (ntohl(seq_num) == ntohl(lsp->lsp_header->seq_num) + && ((lsp->lsp_header->rem_lifetime != 0 && rem_lifetime == 0) + || lsp->lsp_header->checksum != checksum))) { + if (isis->debugs & DEBUG_SNP_PACKETS) { + zlog_debug( + "ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04x," + " lifetime %us", + areatag, + rawlspid_print(lsp->lsp_header->lsp_id), + ntohl(seq_num), ntohs(checksum), + ntohs(rem_lifetime)); + zlog_debug( + "ISIS-Snp (%s): is newer than ours seq 0x%08x, " + "cksum 0x%04x, lifetime %us", + areatag, ntohl(lsp->lsp_header->seq_num), + ntohs(lsp->lsp_header->checksum), + ntohs(lsp->lsp_header->rem_lifetime)); + } + return LSP_NEWER; + } + if (isis->debugs & DEBUG_SNP_PACKETS) { + zlog_debug( + "ISIS-Snp (%s): Compare LSP %s seq 0x%08x, cksum 0x%04x, lifetime %us", + areatag, rawlspid_print(lsp->lsp_header->lsp_id), + ntohl(seq_num), ntohs(checksum), ntohs(rem_lifetime)); + zlog_debug( + "ISIS-Snp (%s): is older than ours seq 0x%08x," + " cksum 0x%04x, lifetime %us", + areatag, ntohl(lsp->lsp_header->seq_num), + ntohs(lsp->lsp_header->checksum), + ntohs(lsp->lsp_header->rem_lifetime)); + } + + return LSP_OLDER; } -static void -lsp_auth_add (struct isis_lsp *lsp) +static void lsp_auth_add(struct isis_lsp *lsp) { - struct isis_passwd *passwd; - unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE]; - - /* - * Add the authentication info if its present - */ - (lsp->level == IS_LEVEL_1) ? (passwd = &lsp->area->area_passwd) : - (passwd = &lsp->area->domain_passwd); - switch (passwd->type) - { - /* Cleartext */ - case ISIS_PASSWD_TYPE_CLEARTXT: - memcpy (&lsp->tlv_data.auth_info, passwd, sizeof (struct isis_passwd)); - tlv_add_authinfo (passwd->type, passwd->len, passwd->passwd, lsp->pdu); - break; - - /* HMAC MD5 */ - case ISIS_PASSWD_TYPE_HMAC_MD5: - /* Remember where TLV is written so we can later - * overwrite the MD5 hash */ - lsp->auth_tlv_offset = stream_get_endp (lsp->pdu); - memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE); - lsp->tlv_data.auth_info.type = ISIS_PASSWD_TYPE_HMAC_MD5; - lsp->tlv_data.auth_info.len = ISIS_AUTH_MD5_SIZE; - memcpy (&lsp->tlv_data.auth_info.passwd, hmac_md5_hash, - ISIS_AUTH_MD5_SIZE); - tlv_add_authinfo (passwd->type, ISIS_AUTH_MD5_SIZE, hmac_md5_hash, - lsp->pdu); - break; - - default: - break; - } + struct isis_passwd *passwd; + unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE]; + + /* + * Add the authentication info if its present + */ + (lsp->level == IS_LEVEL_1) ? (passwd = &lsp->area->area_passwd) + : (passwd = &lsp->area->domain_passwd); + switch (passwd->type) { + /* Cleartext */ + case ISIS_PASSWD_TYPE_CLEARTXT: + memcpy(&lsp->tlv_data.auth_info, passwd, + sizeof(struct isis_passwd)); + tlv_add_authinfo(passwd->type, passwd->len, passwd->passwd, + lsp->pdu); + break; + + /* HMAC MD5 */ + case ISIS_PASSWD_TYPE_HMAC_MD5: + /* Remember where TLV is written so we can later + * overwrite the MD5 hash */ + lsp->auth_tlv_offset = stream_get_endp(lsp->pdu); + memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE); + lsp->tlv_data.auth_info.type = ISIS_PASSWD_TYPE_HMAC_MD5; + lsp->tlv_data.auth_info.len = ISIS_AUTH_MD5_SIZE; + memcpy(&lsp->tlv_data.auth_info.passwd, hmac_md5_hash, + ISIS_AUTH_MD5_SIZE); + tlv_add_authinfo(passwd->type, ISIS_AUTH_MD5_SIZE, + hmac_md5_hash, lsp->pdu); + break; + + default: + break; + } } -static void -lsp_auth_update (struct isis_lsp *lsp) +static void lsp_auth_update(struct isis_lsp *lsp) { - struct isis_passwd *passwd; - unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE]; - uint16_t checksum, rem_lifetime; - - /* For HMAC MD5 we need to recompute the md5 hash and store it */ - (lsp->level == IS_LEVEL_1) ? (passwd = &lsp->area->area_passwd) : - (passwd = &lsp->area->domain_passwd); - if (passwd->type != ISIS_PASSWD_TYPE_HMAC_MD5) - return; - - /* - * In transient conditions (when net is configured where authentication - * config and lsp regenerate schedule is not yet run), there could be - * an own_lsp with auth_tlv_offset set to 0. In such a case, simply - * return, when lsp_regenerate is run, lsp will have auth tlv. - */ - if (lsp->auth_tlv_offset == 0) - return; - - /* - * RFC 5304 set auth value, checksum and remaining lifetime to zero - * before computation and reset to old values after computation. - */ - checksum = lsp->lsp_header->checksum; - rem_lifetime = lsp->lsp_header->rem_lifetime; - lsp->lsp_header->checksum = 0; - lsp->lsp_header->rem_lifetime = 0; - /* Set the authentication value as well to zero */ - memset (STREAM_DATA (lsp->pdu) + lsp->auth_tlv_offset + 3, - 0, ISIS_AUTH_MD5_SIZE); - /* Compute autentication value */ - hmac_md5 (STREAM_DATA (lsp->pdu), stream_get_endp(lsp->pdu), - (unsigned char *) &passwd->passwd, passwd->len, - (unsigned char *) &hmac_md5_hash); - /* Copy the hash into the stream */ - memcpy (STREAM_DATA (lsp->pdu) + lsp->auth_tlv_offset + 3, - hmac_md5_hash, ISIS_AUTH_MD5_SIZE); - memcpy (&lsp->tlv_data.auth_info.passwd, hmac_md5_hash, - ISIS_AUTH_MD5_SIZE); - /* Copy back the checksum and remaining lifetime */ - lsp->lsp_header->checksum = checksum; - lsp->lsp_header->rem_lifetime = rem_lifetime; + struct isis_passwd *passwd; + unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE]; + uint16_t checksum, rem_lifetime; + + /* For HMAC MD5 we need to recompute the md5 hash and store it */ + (lsp->level == IS_LEVEL_1) ? (passwd = &lsp->area->area_passwd) + : (passwd = &lsp->area->domain_passwd); + if (passwd->type != ISIS_PASSWD_TYPE_HMAC_MD5) + return; + + /* + * In transient conditions (when net is configured where authentication + * config and lsp regenerate schedule is not yet run), there could be + * an own_lsp with auth_tlv_offset set to 0. In such a case, simply + * return, when lsp_regenerate is run, lsp will have auth tlv. + */ + if (lsp->auth_tlv_offset == 0) + return; + + /* + * RFC 5304 set auth value, checksum and remaining lifetime to zero + * before computation and reset to old values after computation. + */ + checksum = lsp->lsp_header->checksum; + rem_lifetime = lsp->lsp_header->rem_lifetime; + lsp->lsp_header->checksum = 0; + lsp->lsp_header->rem_lifetime = 0; + /* Set the authentication value as well to zero */ + memset(STREAM_DATA(lsp->pdu) + lsp->auth_tlv_offset + 3, 0, + ISIS_AUTH_MD5_SIZE); + /* Compute autentication value */ + hmac_md5(STREAM_DATA(lsp->pdu), stream_get_endp(lsp->pdu), + (unsigned char *)&passwd->passwd, passwd->len, + (unsigned char *)&hmac_md5_hash); + /* Copy the hash into the stream */ + memcpy(STREAM_DATA(lsp->pdu) + lsp->auth_tlv_offset + 3, hmac_md5_hash, + ISIS_AUTH_MD5_SIZE); + memcpy(&lsp->tlv_data.auth_info.passwd, hmac_md5_hash, + ISIS_AUTH_MD5_SIZE); + /* Copy back the checksum and remaining lifetime */ + lsp->lsp_header->checksum = checksum; + lsp->lsp_header->rem_lifetime = rem_lifetime; } -void -lsp_inc_seqnum (struct isis_lsp *lsp, u_int32_t seq_num) +void lsp_inc_seqnum(struct isis_lsp *lsp, u_int32_t seq_num) { - u_int32_t newseq; - - if (seq_num == 0 || ntohl (lsp->lsp_header->seq_num) > seq_num) - newseq = ntohl (lsp->lsp_header->seq_num) + 1; - else - newseq = seq_num + 1; - - lsp->lsp_header->seq_num = htonl (newseq); - - /* Recompute authentication and checksum information */ - lsp_auth_update (lsp); - /* ISO 10589 - 7.3.11 Generation of the checksum - * The checksum shall be computed over all fields in the LSP which appear - * after the Remaining Lifetime field. This field (and those appearing - * before it) are excluded so that the LSP may be aged by systems without - * requiring recomputation. - */ - fletcher_checksum(STREAM_DATA (lsp->pdu) + 12, - ntohs (lsp->lsp_header->pdu_len) - 12, 12); - - isis_spf_schedule (lsp->area, lsp->level); - - return; + u_int32_t newseq; + + if (seq_num == 0 || ntohl(lsp->lsp_header->seq_num) > seq_num) + newseq = ntohl(lsp->lsp_header->seq_num) + 1; + else + newseq = seq_num + 1; + + lsp->lsp_header->seq_num = htonl(newseq); + + /* Recompute authentication and checksum information */ + lsp_auth_update(lsp); + /* ISO 10589 - 7.3.11 Generation of the checksum + * The checksum shall be computed over all fields in the LSP which + * appear + * after the Remaining Lifetime field. This field (and those appearing + * before it) are excluded so that the LSP may be aged by systems + * without + * requiring recomputation. + */ + fletcher_checksum(STREAM_DATA(lsp->pdu) + 12, + ntohs(lsp->lsp_header->pdu_len) - 12, 12); + + isis_spf_schedule(lsp->area, lsp->level); + + return; } /* * Genetates checksum for LSP and its frags */ -static void -lsp_seqnum_update (struct isis_lsp *lsp0) +static void lsp_seqnum_update(struct isis_lsp *lsp0) { - struct isis_lsp *lsp; - struct listnode *node; + struct isis_lsp *lsp; + struct listnode *node; - lsp_inc_seqnum (lsp0, 0); + lsp_inc_seqnum(lsp0, 0); - if (!lsp0->lspu.frags) - return; + if (!lsp0->lspu.frags) + return; - for (ALL_LIST_ELEMENTS_RO (lsp0->lspu.frags, node, lsp)) - lsp_inc_seqnum (lsp, 0); + for (ALL_LIST_ELEMENTS_RO(lsp0->lspu.frags, node, lsp)) + lsp_inc_seqnum(lsp, 0); - return; + return; } -static u_int8_t -lsp_bits_generate (int level, int overload_bit, int attached_bit) +static u_int8_t lsp_bits_generate(int level, int overload_bit, int attached_bit) { - u_int8_t lsp_bits = 0; - if (level == IS_LEVEL_1) - lsp_bits = IS_LEVEL_1; - else - lsp_bits = IS_LEVEL_1_AND_2; - if (overload_bit) - lsp_bits |= overload_bit; - if (attached_bit) - lsp_bits |= attached_bit; - return lsp_bits; + u_int8_t lsp_bits = 0; + if (level == IS_LEVEL_1) + lsp_bits = IS_LEVEL_1; + else + lsp_bits = IS_LEVEL_1_AND_2; + if (overload_bit) + lsp_bits |= overload_bit; + if (attached_bit) + lsp_bits |= attached_bit; + return lsp_bits; } -static void -lsp_update_data (struct isis_lsp *lsp, struct stream *stream, - struct isis_area *area, int level) +static void lsp_update_data(struct isis_lsp *lsp, struct stream *stream, + struct isis_area *area, int level) { - uint32_t expected = 0, found; - int retval; - - /* free the old lsp data */ - lsp_clear_data (lsp); - - /* copying only the relevant part of our stream */ - if (lsp->pdu != NULL) - stream_free (lsp->pdu); - lsp->pdu = stream_dup (stream); - - /* setting pointers to the correct place */ - lsp->isis_header = (struct isis_fixed_hdr *) (STREAM_DATA (lsp->pdu)); - lsp->lsp_header = (struct isis_link_state_hdr *) (STREAM_DATA (lsp->pdu) + - ISIS_FIXED_HDR_LEN); - lsp->area = area; - lsp->level = level; - lsp->age_out = ZERO_AGE_LIFETIME; - lsp->installed = time (NULL); - /* - * Get LSP data i.e. TLVs - */ - expected |= TLVFLAG_AUTH_INFO; - expected |= TLVFLAG_AREA_ADDRS; - expected |= TLVFLAG_IS_NEIGHS; - expected |= TLVFLAG_NLPID; - if (area->dynhostname) - expected |= TLVFLAG_DYN_HOSTNAME; - if (area->newmetric) - { - expected |= TLVFLAG_TE_IS_NEIGHS; - expected |= TLVFLAG_TE_IPV4_REACHABILITY; - expected |= TLVFLAG_TE_ROUTER_ID; - } - expected |= TLVFLAG_MT_ROUTER_INFORMATION; - expected |= TLVFLAG_IPV4_ADDR; - expected |= TLVFLAG_IPV4_INT_REACHABILITY; - expected |= TLVFLAG_IPV4_EXT_REACHABILITY; - expected |= TLVFLAG_IPV6_ADDR; - expected |= TLVFLAG_IPV6_REACHABILITY; - - retval = parse_tlvs (area->area_tag, STREAM_DATA (lsp->pdu) + - ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN, - ntohs (lsp->lsp_header->pdu_len) - - ISIS_FIXED_HDR_LEN - ISIS_LSP_HDR_LEN, - &expected, &found, &lsp->tlv_data, - NULL); - if (retval != ISIS_OK) - { - zlog_warn ("Could not parse LSP"); - return; - } - - if ((found & TLVFLAG_DYN_HOSTNAME) && (area->dynhostname)) - { - isis_dynhn_insert (lsp->lsp_header->lsp_id, lsp->tlv_data.hostname, - (lsp->lsp_header->lsp_bits & LSPBIT_IST) == - IS_LEVEL_1_AND_2 ? IS_LEVEL_2 : IS_LEVEL_1); - } - - return; + uint32_t expected = 0, found; + int retval; + + /* free the old lsp data */ + lsp_clear_data(lsp); + + /* copying only the relevant part of our stream */ + if (lsp->pdu != NULL) + stream_free(lsp->pdu); + lsp->pdu = stream_dup(stream); + + /* setting pointers to the correct place */ + lsp->isis_header = (struct isis_fixed_hdr *)(STREAM_DATA(lsp->pdu)); + lsp->lsp_header = (struct isis_link_state_hdr *)(STREAM_DATA(lsp->pdu) + + ISIS_FIXED_HDR_LEN); + lsp->area = area; + lsp->level = level; + lsp->age_out = ZERO_AGE_LIFETIME; + lsp->installed = time(NULL); + /* + * Get LSP data i.e. TLVs + */ + expected |= TLVFLAG_AUTH_INFO; + expected |= TLVFLAG_AREA_ADDRS; + expected |= TLVFLAG_IS_NEIGHS; + expected |= TLVFLAG_NLPID; + if (area->dynhostname) + expected |= TLVFLAG_DYN_HOSTNAME; + if (area->newmetric) { + expected |= TLVFLAG_TE_IS_NEIGHS; + expected |= TLVFLAG_TE_IPV4_REACHABILITY; + expected |= TLVFLAG_TE_ROUTER_ID; + } + expected |= TLVFLAG_MT_ROUTER_INFORMATION; + expected |= TLVFLAG_IPV4_ADDR; + expected |= TLVFLAG_IPV4_INT_REACHABILITY; + expected |= TLVFLAG_IPV4_EXT_REACHABILITY; + expected |= TLVFLAG_IPV6_ADDR; + expected |= TLVFLAG_IPV6_REACHABILITY; + + retval = parse_tlvs(area->area_tag, + STREAM_DATA(lsp->pdu) + ISIS_FIXED_HDR_LEN + + ISIS_LSP_HDR_LEN, + ntohs(lsp->lsp_header->pdu_len) - ISIS_FIXED_HDR_LEN + - ISIS_LSP_HDR_LEN, + &expected, &found, &lsp->tlv_data, NULL); + if (retval != ISIS_OK) { + zlog_warn("Could not parse LSP"); + return; + } + + if ((found & TLVFLAG_DYN_HOSTNAME) && (area->dynhostname)) { + isis_dynhn_insert(lsp->lsp_header->lsp_id, + lsp->tlv_data.hostname, + (lsp->lsp_header->lsp_bits & LSPBIT_IST) + == IS_LEVEL_1_AND_2 + ? IS_LEVEL_2 + : IS_LEVEL_1); + } + + return; } -void -lsp_update (struct isis_lsp *lsp, struct stream *stream, - struct isis_area *area, int level) +void lsp_update(struct isis_lsp *lsp, struct stream *stream, + struct isis_area *area, int level) { - dnode_t *dnode = NULL; - - /* Remove old LSP from database. This is required since the - * lsp_update_data will free the lsp->pdu (which has the key, lsp_id) - * and will update it with the new data in the stream. */ - dnode = dict_lookup (area->lspdb[level - 1], lsp->lsp_header->lsp_id); - if (dnode) - dnode_destroy (dict_delete (area->lspdb[level - 1], dnode)); - - if (lsp->own_lsp) - { - zlog_err("ISIS-Upd (%s): BUG updating LSP %s still marked as own LSP", - area->area_tag, rawlspid_print(lsp->lsp_header->lsp_id)); - lsp_clear_data(lsp); - lsp->own_lsp = 0; - } - - /* rebuild the lsp data */ - lsp_update_data (lsp, stream, area, level); - - /* insert the lsp back into the database */ - lsp_insert (lsp, area->lspdb[level - 1]); + dnode_t *dnode = NULL; + + /* Remove old LSP from database. This is required since the + * lsp_update_data will free the lsp->pdu (which has the key, lsp_id) + * and will update it with the new data in the stream. */ + dnode = dict_lookup(area->lspdb[level - 1], lsp->lsp_header->lsp_id); + if (dnode) + dnode_destroy(dict_delete(area->lspdb[level - 1], dnode)); + + if (lsp->own_lsp) { + zlog_err( + "ISIS-Upd (%s): BUG updating LSP %s still marked as own LSP", + area->area_tag, + rawlspid_print(lsp->lsp_header->lsp_id)); + lsp_clear_data(lsp); + lsp->own_lsp = 0; + } + + /* rebuild the lsp data */ + lsp_update_data(lsp, stream, area, level); + + /* insert the lsp back into the database */ + lsp_insert(lsp, area->lspdb[level - 1]); } /* creation of LSP directly from what we received */ -struct isis_lsp * -lsp_new_from_stream_ptr (struct stream *stream, - u_int16_t pdu_len, struct isis_lsp *lsp0, - struct isis_area *area, int level) +struct isis_lsp *lsp_new_from_stream_ptr(struct stream *stream, + u_int16_t pdu_len, + struct isis_lsp *lsp0, + struct isis_area *area, int level) { - struct isis_lsp *lsp; - - lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp)); - lsp_update_data (lsp, stream, area, level); - - if (lsp0 == NULL) - { - /* - * zero lsp -> create the list for fragments - */ - lsp->lspu.frags = list_new (); - } - else - { - /* - * a fragment -> set the backpointer and add this to zero lsps frag list - */ - lsp->lspu.zero_lsp = lsp0; - listnode_add (lsp0->lspu.frags, lsp); - } - - return lsp; + struct isis_lsp *lsp; + + lsp = XCALLOC(MTYPE_ISIS_LSP, sizeof(struct isis_lsp)); + lsp_update_data(lsp, stream, area, level); + + if (lsp0 == NULL) { + /* + * zero lsp -> create the list for fragments + */ + lsp->lspu.frags = list_new(); + } else { + /* + * a fragment -> set the backpointer and add this to zero lsps + * frag list + */ + lsp->lspu.zero_lsp = lsp0; + listnode_add(lsp0->lspu.frags, lsp); + } + + return lsp; } -struct isis_lsp * -lsp_new(struct isis_area *area, u_char * lsp_id, - u_int16_t rem_lifetime, u_int32_t seq_num, - u_int8_t lsp_bits, u_int16_t checksum, int level) +struct isis_lsp *lsp_new(struct isis_area *area, u_char *lsp_id, + u_int16_t rem_lifetime, u_int32_t seq_num, + u_int8_t lsp_bits, u_int16_t checksum, int level) { - struct isis_lsp *lsp; - - lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp)); - lsp->area = area; - - lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu); - if (LSP_FRAGMENT (lsp_id) == 0) - lsp->lspu.frags = list_new (); - lsp->isis_header = (struct isis_fixed_hdr *) (STREAM_DATA (lsp->pdu)); - lsp->lsp_header = (struct isis_link_state_hdr *) - (STREAM_DATA (lsp->pdu) + ISIS_FIXED_HDR_LEN); - - /* at first we fill the FIXED HEADER */ - (level == IS_LEVEL_1) ? fill_fixed_hdr (lsp->isis_header, L1_LINK_STATE) : - fill_fixed_hdr (lsp->isis_header, L2_LINK_STATE); - - /* now for the LSP HEADER */ - /* Minimal LSP PDU size */ - lsp->lsp_header->pdu_len = htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); - memcpy (lsp->lsp_header->lsp_id, lsp_id, ISIS_SYS_ID_LEN + 2); - lsp->lsp_header->checksum = checksum; /* Provided in network order */ - lsp->lsp_header->seq_num = htonl (seq_num); - lsp->lsp_header->rem_lifetime = htons (rem_lifetime); - lsp->lsp_header->lsp_bits = lsp_bits; - lsp->level = level; - lsp->age_out = ZERO_AGE_LIFETIME; - - stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); - - if (isis->debugs & DEBUG_EVENTS) - zlog_debug ("New LSP with ID %s-%02x-%02x len %d seqnum %08x", - sysid_print (lsp_id), LSP_PSEUDO_ID (lsp->lsp_header->lsp_id), - LSP_FRAGMENT (lsp->lsp_header->lsp_id), - ntohl (lsp->lsp_header->pdu_len), - ntohl (lsp->lsp_header->seq_num)); - - return lsp; + struct isis_lsp *lsp; + + lsp = XCALLOC(MTYPE_ISIS_LSP, sizeof(struct isis_lsp)); + lsp->area = area; + + lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu); + if (LSP_FRAGMENT(lsp_id) == 0) + lsp->lspu.frags = list_new(); + lsp->isis_header = (struct isis_fixed_hdr *)(STREAM_DATA(lsp->pdu)); + lsp->lsp_header = (struct isis_link_state_hdr *)(STREAM_DATA(lsp->pdu) + + ISIS_FIXED_HDR_LEN); + + /* at first we fill the FIXED HEADER */ + (level == IS_LEVEL_1) ? fill_fixed_hdr(lsp->isis_header, L1_LINK_STATE) + : fill_fixed_hdr(lsp->isis_header, L2_LINK_STATE); + + /* now for the LSP HEADER */ + /* Minimal LSP PDU size */ + lsp->lsp_header->pdu_len = htons(ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); + memcpy(lsp->lsp_header->lsp_id, lsp_id, ISIS_SYS_ID_LEN + 2); + lsp->lsp_header->checksum = checksum; /* Provided in network order */ + lsp->lsp_header->seq_num = htonl(seq_num); + lsp->lsp_header->rem_lifetime = htons(rem_lifetime); + lsp->lsp_header->lsp_bits = lsp_bits; + lsp->level = level; + lsp->age_out = ZERO_AGE_LIFETIME; + + stream_forward_endp(lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); + + if (isis->debugs & DEBUG_EVENTS) + zlog_debug("New LSP with ID %s-%02x-%02x len %d seqnum %08x", + sysid_print(lsp_id), + LSP_PSEUDO_ID(lsp->lsp_header->lsp_id), + LSP_FRAGMENT(lsp->lsp_header->lsp_id), + ntohl(lsp->lsp_header->pdu_len), + ntohl(lsp->lsp_header->seq_num)); + + return lsp; } -void -lsp_insert (struct isis_lsp *lsp, dict_t * lspdb) +void lsp_insert(struct isis_lsp *lsp, dict_t *lspdb) { - dict_alloc_insert (lspdb, lsp->lsp_header->lsp_id, lsp); - if (lsp->lsp_header->seq_num != 0) - { - isis_spf_schedule (lsp->area, lsp->level); - } + dict_alloc_insert(lspdb, lsp->lsp_header->lsp_id, lsp); + if (lsp->lsp_header->seq_num != 0) { + isis_spf_schedule(lsp->area, lsp->level); + } } /* * Build a list of LSPs with non-zero ht bounded by start and stop ids */ -void -lsp_build_list_nonzero_ht (u_char * start_id, u_char * stop_id, - struct list *list, dict_t * lspdb) +void lsp_build_list_nonzero_ht(u_char *start_id, u_char *stop_id, + struct list *list, dict_t *lspdb) { - dnode_t *first, *last, *curr; + dnode_t *first, *last, *curr; - first = dict_lower_bound (lspdb, start_id); - if (!first) - return; + first = dict_lower_bound(lspdb, start_id); + if (!first) + return; - last = dict_upper_bound (lspdb, stop_id); + last = dict_upper_bound(lspdb, stop_id); - curr = first; + curr = first; - if (((struct isis_lsp *) (curr->dict_data))->lsp_header->rem_lifetime) - listnode_add (list, first->dict_data); + if (((struct isis_lsp *)(curr->dict_data))->lsp_header->rem_lifetime) + listnode_add(list, first->dict_data); - while (curr) - { - curr = dict_next (lspdb, curr); - if (curr && - ((struct isis_lsp *) (curr->dict_data))->lsp_header->rem_lifetime) - listnode_add (list, curr->dict_data); - if (curr == last) - break; - } + while (curr) { + curr = dict_next(lspdb, curr); + if (curr + && ((struct isis_lsp *)(curr->dict_data)) + ->lsp_header->rem_lifetime) + listnode_add(list, curr->dict_data); + if (curr == last) + break; + } - return; + return; } /* * Build a list of num_lsps LSPs bounded by start_id and stop_id. */ -void -lsp_build_list (u_char * start_id, u_char * stop_id, u_char num_lsps, - struct list *list, dict_t * lspdb) +void lsp_build_list(u_char *start_id, u_char *stop_id, u_char num_lsps, + struct list *list, dict_t *lspdb) { - u_char count; - dnode_t *first, *last, *curr; + u_char count; + dnode_t *first, *last, *curr; - first = dict_lower_bound (lspdb, start_id); - if (!first) - return; + first = dict_lower_bound(lspdb, start_id); + if (!first) + return; - last = dict_upper_bound (lspdb, stop_id); + last = dict_upper_bound(lspdb, stop_id); - curr = first; + curr = first; - listnode_add (list, first->dict_data); - count = 1; + listnode_add(list, first->dict_data); + count = 1; - while (curr) - { - curr = dict_next (lspdb, curr); - if (curr) - { - listnode_add (list, curr->dict_data); - count++; - } - if (count == num_lsps || curr == last) - break; - } + while (curr) { + curr = dict_next(lspdb, curr); + if (curr) { + listnode_add(list, curr->dict_data); + count++; + } + if (count == num_lsps || curr == last) + break; + } - return; + return; } /* * Build a list of LSPs with SSN flag set for the given circuit */ -void -lsp_build_list_ssn (struct isis_circuit *circuit, u_char num_lsps, - struct list *list, dict_t * lspdb) +void lsp_build_list_ssn(struct isis_circuit *circuit, u_char num_lsps, + struct list *list, dict_t *lspdb) { - dnode_t *dnode, *next; - struct isis_lsp *lsp; - u_char count = 0; - - dnode = dict_first (lspdb); - while (dnode != NULL) - { - next = dict_next (lspdb, dnode); - lsp = dnode_get (dnode); - if (ISIS_CHECK_FLAG (lsp->SSNflags, circuit)) - { - listnode_add (list, lsp); - ++count; - } - if (count == num_lsps) - break; - dnode = next; - } - - return; + dnode_t *dnode, *next; + struct isis_lsp *lsp; + u_char count = 0; + + dnode = dict_first(lspdb); + while (dnode != NULL) { + next = dict_next(lspdb, dnode); + lsp = dnode_get(dnode); + if (ISIS_CHECK_FLAG(lsp->SSNflags, circuit)) { + listnode_add(list, lsp); + ++count; + } + if (count == num_lsps) + break; + dnode = next; + } + + return; } -static void -lsp_set_time (struct isis_lsp *lsp) +static void lsp_set_time(struct isis_lsp *lsp) { - assert (lsp); + assert(lsp); - if (lsp->lsp_header->rem_lifetime == 0) - { - if (lsp->age_out > 0) - lsp->age_out--; - return; - } + if (lsp->lsp_header->rem_lifetime == 0) { + if (lsp->age_out > 0) + lsp->age_out--; + return; + } - lsp->lsp_header->rem_lifetime = - htons (ntohs (lsp->lsp_header->rem_lifetime) - 1); + lsp->lsp_header->rem_lifetime = + htons(ntohs(lsp->lsp_header->rem_lifetime) - 1); } -static void -lspid_print (u_char * lsp_id, u_char * trg, char dynhost, char frag) +static void lspid_print(u_char *lsp_id, u_char *trg, char dynhost, char frag) { - struct isis_dynhn *dyn = NULL; - u_char id[SYSID_STRLEN]; - - if (dynhost) - dyn = dynhn_find_by_id (lsp_id); - else - dyn = NULL; - - if (dyn) - sprintf ((char *)id, "%.14s", dyn->name.name); - else if (!memcmp (isis->sysid, lsp_id, ISIS_SYS_ID_LEN) && dynhost) - sprintf ((char *)id, "%.14s", unix_hostname ()); - else - memcpy (id, sysid_print (lsp_id), 15); - if (frag) - sprintf ((char *)trg, "%s.%02x-%02x", id, LSP_PSEUDO_ID (lsp_id), - LSP_FRAGMENT (lsp_id)); - else - sprintf ((char *)trg, "%s.%02x", id, LSP_PSEUDO_ID (lsp_id)); + struct isis_dynhn *dyn = NULL; + u_char id[SYSID_STRLEN]; + + if (dynhost) + dyn = dynhn_find_by_id(lsp_id); + else + dyn = NULL; + + if (dyn) + sprintf((char *)id, "%.14s", dyn->name.name); + else if (!memcmp(isis->sysid, lsp_id, ISIS_SYS_ID_LEN) && dynhost) + sprintf((char *)id, "%.14s", unix_hostname()); + else + memcpy(id, sysid_print(lsp_id), 15); + if (frag) + sprintf((char *)trg, "%s.%02x-%02x", id, LSP_PSEUDO_ID(lsp_id), + LSP_FRAGMENT(lsp_id)); + else + sprintf((char *)trg, "%s.%02x", id, LSP_PSEUDO_ID(lsp_id)); } /* Convert the lsp attribute bits to attribute string */ -const char * -lsp_bits2string (u_char * lsp_bits) +const char *lsp_bits2string(u_char *lsp_bits) { - char *pos = lsp_bits_string; + char *pos = lsp_bits_string; - if (!*lsp_bits) - return " none"; + if (!*lsp_bits) + return " none"; - /* we only focus on the default metric */ - pos += sprintf (pos, "%d/", - ISIS_MASK_LSP_ATT_DEFAULT_BIT (*lsp_bits) ? 1 : 0); + /* we only focus on the default metric */ + pos += sprintf(pos, "%d/", + ISIS_MASK_LSP_ATT_DEFAULT_BIT(*lsp_bits) ? 1 : 0); - pos += sprintf (pos, "%d/", - ISIS_MASK_LSP_PARTITION_BIT (*lsp_bits) ? 1 : 0); + pos += sprintf(pos, "%d/", + ISIS_MASK_LSP_PARTITION_BIT(*lsp_bits) ? 1 : 0); - pos += sprintf (pos, "%d", ISIS_MASK_LSP_OL_BIT (*lsp_bits) ? 1 : 0); + pos += sprintf(pos, "%d", ISIS_MASK_LSP_OL_BIT(*lsp_bits) ? 1 : 0); - *(pos) = '\0'; + *(pos) = '\0'; - return lsp_bits_string; + return lsp_bits_string; } /* this function prints the lsp on show isis database */ -void -lsp_print (struct isis_lsp *lsp, struct vty *vty, char dynhost) +void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost) { - u_char LSPid[255]; - char age_out[8]; - - lspid_print (lsp->lsp_header->lsp_id, LSPid, dynhost, 1); - vty_out (vty, "%-21s%c ", LSPid, lsp->own_lsp ? '*' : ' '); - vty_out (vty, "%5u ", ntohs (lsp->lsp_header->pdu_len)); - vty_out (vty, "0x%08x ", ntohl (lsp->lsp_header->seq_num)); - vty_out (vty, "0x%04x ", ntohs (lsp->lsp_header->checksum)); - if (ntohs (lsp->lsp_header->rem_lifetime) == 0) - { - snprintf (age_out, 8, "(%u)", lsp->age_out); - age_out[7] = '\0'; - vty_out (vty, "%7s ", age_out); - } - else - vty_out (vty, " %5u ", ntohs (lsp->lsp_header->rem_lifetime)); - vty_out (vty, "%s\n", - lsp_bits2string(&lsp->lsp_header->lsp_bits)); + u_char LSPid[255]; + char age_out[8]; + + lspid_print(lsp->lsp_header->lsp_id, LSPid, dynhost, 1); + vty_out(vty, "%-21s%c ", LSPid, lsp->own_lsp ? '*' : ' '); + vty_out(vty, "%5u ", ntohs(lsp->lsp_header->pdu_len)); + vty_out(vty, "0x%08x ", ntohl(lsp->lsp_header->seq_num)); + vty_out(vty, "0x%04x ", ntohs(lsp->lsp_header->checksum)); + if (ntohs(lsp->lsp_header->rem_lifetime) == 0) { + snprintf(age_out, 8, "(%u)", lsp->age_out); + age_out[7] = '\0'; + vty_out(vty, "%7s ", age_out); + } else + vty_out(vty, " %5u ", ntohs(lsp->lsp_header->rem_lifetime)); + vty_out(vty, "%s\n", lsp_bits2string(&lsp->lsp_header->lsp_bits)); } -static void -lsp_print_mt_reach(struct list *list, struct vty *vty, - char dynhost, uint16_t mtid) +static void lsp_print_mt_reach(struct list *list, struct vty *vty, char dynhost, + uint16_t mtid) { - struct listnode *node; - struct te_is_neigh *neigh; - - for (ALL_LIST_ELEMENTS_RO (list, node, neigh)) - { - u_char lspid[255]; - - lspid_print(neigh->neigh_id, lspid, dynhost, 0); - if (mtid == ISIS_MT_IPV4_UNICAST) - { - vty_out(vty, " Metric : %-8u IS-Extended : %s\n", - GET_TE_METRIC(neigh), lspid); - } - else - { - vty_out(vty, " Metric : %-8u MT-Reach : %s %s\n", - GET_TE_METRIC(neigh), lspid, - isis_mtid2str(mtid)); - } - if (IS_MPLS_TE(isisMplsTE)) - mpls_te_print_detail(vty, neigh); - } + struct listnode *node; + struct te_is_neigh *neigh; + + for (ALL_LIST_ELEMENTS_RO(list, node, neigh)) { + u_char lspid[255]; + + lspid_print(neigh->neigh_id, lspid, dynhost, 0); + if (mtid == ISIS_MT_IPV4_UNICAST) { + vty_out(vty, + " Metric : %-8u IS-Extended : %s\n", + GET_TE_METRIC(neigh), lspid); + } else { + vty_out(vty, + " Metric : %-8u MT-Reach : %s %s\n", + GET_TE_METRIC(neigh), lspid, + isis_mtid2str(mtid)); + } + if (IS_MPLS_TE(isisMplsTE)) + mpls_te_print_detail(vty, neigh); + } } -static void -lsp_print_mt_ipv6_reach(struct list *list, struct vty *vty, uint16_t mtid) +static void lsp_print_mt_ipv6_reach(struct list *list, struct vty *vty, + uint16_t mtid) { - struct listnode *node; - struct ipv6_reachability *ipv6_reach; - struct in6_addr in6; - u_char buff[BUFSIZ]; - - for (ALL_LIST_ELEMENTS_RO (list, node, ipv6_reach)) - { - memset (&in6, 0, sizeof (in6)); - memcpy (in6.s6_addr, ipv6_reach->prefix, - PSIZE (ipv6_reach->prefix_len)); - inet_ntop (AF_INET6, &in6, (char *)buff, BUFSIZ); - if (mtid == ISIS_MT_IPV4_UNICAST) - { - if ((ipv6_reach->control_info & - CTRL_INFO_DISTRIBUTION) == DISTRIBUTION_INTERNAL) - vty_out (vty, " Metric : %-8" PRIu32 " IPv6-Internal : %s/%d\n", - ntohl (ipv6_reach->metric), - buff, ipv6_reach->prefix_len); - else - vty_out (vty, " Metric : %-8" PRIu32 " IPv6-External : %s/%d\n", - ntohl (ipv6_reach->metric), - buff, ipv6_reach->prefix_len); - } - else - { - if ((ipv6_reach->control_info & - CTRL_INFO_DISTRIBUTION) == DISTRIBUTION_INTERNAL) - vty_out (vty, " Metric : %-8" PRIu32 " IPv6-MT-Int : %s/%d %s\n", - ntohl (ipv6_reach->metric), - buff, ipv6_reach->prefix_len, - isis_mtid2str(mtid)); - else - vty_out (vty, " Metric : %-8" PRIu32 " IPv6-MT-Ext : %s/%d %s\n", - ntohl (ipv6_reach->metric), - buff, ipv6_reach->prefix_len, - isis_mtid2str(mtid)); - } - } + struct listnode *node; + struct ipv6_reachability *ipv6_reach; + struct in6_addr in6; + u_char buff[BUFSIZ]; + + for (ALL_LIST_ELEMENTS_RO(list, node, ipv6_reach)) { + memset(&in6, 0, sizeof(in6)); + memcpy(in6.s6_addr, ipv6_reach->prefix, + PSIZE(ipv6_reach->prefix_len)); + inet_ntop(AF_INET6, &in6, (char *)buff, BUFSIZ); + if (mtid == ISIS_MT_IPV4_UNICAST) { + if ((ipv6_reach->control_info & CTRL_INFO_DISTRIBUTION) + == DISTRIBUTION_INTERNAL) + vty_out(vty, " Metric : %-8" PRIu32 + " IPv6-Internal : %s/%d\n", + ntohl(ipv6_reach->metric), buff, + ipv6_reach->prefix_len); + else + vty_out(vty, " Metric : %-8" PRIu32 + " IPv6-External : %s/%d\n", + ntohl(ipv6_reach->metric), buff, + ipv6_reach->prefix_len); + } else { + if ((ipv6_reach->control_info & CTRL_INFO_DISTRIBUTION) + == DISTRIBUTION_INTERNAL) + vty_out(vty, " Metric : %-8" PRIu32 + " IPv6-MT-Int : %s/%d %s\n", + ntohl(ipv6_reach->metric), buff, + ipv6_reach->prefix_len, + isis_mtid2str(mtid)); + else + vty_out(vty, " Metric : %-8" PRIu32 + " IPv6-MT-Ext : %s/%d %s\n", + ntohl(ipv6_reach->metric), buff, + ipv6_reach->prefix_len, + isis_mtid2str(mtid)); + } + } } -static void -lsp_print_mt_ipv4_reach(struct list *list, struct vty *vty, uint16_t mtid) +static void lsp_print_mt_ipv4_reach(struct list *list, struct vty *vty, + uint16_t mtid) { - struct listnode *node; - struct te_ipv4_reachability *te_ipv4_reach; - - for (ALL_LIST_ELEMENTS_RO (list, node, te_ipv4_reach)) - { - if (mtid == ISIS_MT_IPV4_UNICAST) - { - /* FIXME: There should be better way to output this stuff. */ - vty_out (vty, " Metric : %-8" PRIu32 " IPv4-Extended : %s/%d\n", - ntohl (te_ipv4_reach->te_metric), - inet_ntoa (newprefix2inaddr (&te_ipv4_reach->prefix_start, - te_ipv4_reach->control)), - te_ipv4_reach->control & 0x3F); - } - else - { - /* FIXME: There should be better way to output this stuff. */ - vty_out (vty, " Metric : %-8" PRIu32 " IPv4-MT : %s/%d %s\n", - ntohl (te_ipv4_reach->te_metric), - inet_ntoa (newprefix2inaddr (&te_ipv4_reach->prefix_start, - te_ipv4_reach->control)), - te_ipv4_reach->control & 0x3F, - isis_mtid2str(mtid)); - } - } + struct listnode *node; + struct te_ipv4_reachability *te_ipv4_reach; + + for (ALL_LIST_ELEMENTS_RO(list, node, te_ipv4_reach)) { + if (mtid == ISIS_MT_IPV4_UNICAST) { + /* FIXME: There should be better way to output this + * stuff. */ + vty_out(vty, " Metric : %-8" PRIu32 + " IPv4-Extended : %s/%d\n", + ntohl(te_ipv4_reach->te_metric), + inet_ntoa(newprefix2inaddr( + &te_ipv4_reach->prefix_start, + te_ipv4_reach->control)), + te_ipv4_reach->control & 0x3F); + } else { + /* FIXME: There should be better way to output this + * stuff. */ + vty_out(vty, " Metric : %-8" PRIu32 + " IPv4-MT : %s/%d %s\n", + ntohl(te_ipv4_reach->te_metric), + inet_ntoa(newprefix2inaddr( + &te_ipv4_reach->prefix_start, + te_ipv4_reach->control)), + te_ipv4_reach->control & 0x3F, + isis_mtid2str(mtid)); + } + } } -void -lsp_print_detail (struct isis_lsp *lsp, struct vty *vty, char dynhost) +void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost) { - struct area_addr *area_addr; - int i; - struct listnode *lnode; - struct is_neigh *is_neigh; - struct ipv4_reachability *ipv4_reach; - struct in_addr *ipv4_addr; - struct mt_router_info *mt_router_info; - struct tlv_mt_ipv6_reachs *mt_ipv6_reachs; - struct tlv_mt_neighbors *mt_is_neigh; - struct tlv_mt_ipv4_reachs *mt_ipv4_reachs; - u_char LSPid[255]; - u_char hostname[255]; - u_char ipv4_reach_prefix[20]; - u_char ipv4_reach_mask[20]; - u_char ipv4_address[20]; - - lspid_print (lsp->lsp_header->lsp_id, LSPid, dynhost, 1); - lsp_print (lsp, vty, dynhost); - - /* for all area address */ - if (lsp->tlv_data.area_addrs) - for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.area_addrs, lnode, area_addr)) - { - vty_out (vty, " Area Address: %s\n", - isonet_print(area_addr->area_addr, area_addr->addr_len)); - } - - /* for the nlpid tlv */ - if (lsp->tlv_data.nlpids) - { - for (i = 0; i < lsp->tlv_data.nlpids->count; i++) - { - switch (lsp->tlv_data.nlpids->nlpids[i]) - { - case NLPID_IP: - case NLPID_IPV6: - vty_out (vty, " NLPID : 0x%X\n", - lsp->tlv_data.nlpids->nlpids[i]); - break; - default: - vty_out (vty, " NLPID : %s\n", "unknown"); - break; - } - } - } - - for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.mt_router_info, lnode, mt_router_info)) - { - vty_out (vty, " MT : %s%s\n", - isis_mtid2str(mt_router_info->mtid), - mt_router_info->overload ? " (overload)" : ""); - } - - /* for the hostname tlv */ - if (lsp->tlv_data.hostname) - { - bzero (hostname, sizeof (hostname)); - memcpy (hostname, lsp->tlv_data.hostname->name, - lsp->tlv_data.hostname->namelen); - vty_out (vty, " Hostname : %s\n", hostname); - } - - /* authentication tlv */ - if (lsp->tlv_data.auth_info.type != ISIS_PASSWD_TYPE_UNUSED) - { - if (lsp->tlv_data.auth_info.type == ISIS_PASSWD_TYPE_HMAC_MD5) - vty_out (vty, " Auth type : md5\n"); - else if (lsp->tlv_data.auth_info.type == ISIS_PASSWD_TYPE_CLEARTXT) - vty_out (vty, " Auth type : clear text\n"); - } - - /* TE router id */ - if (lsp->tlv_data.router_id) - { - memcpy (ipv4_address, inet_ntoa (lsp->tlv_data.router_id->id), - sizeof (ipv4_address)); - vty_out (vty, " Router ID : %s\n", ipv4_address); - } - - if (lsp->tlv_data.ipv4_addrs) - for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_addrs, lnode, ipv4_addr)) - { - memcpy (ipv4_address, inet_ntoa (*ipv4_addr), sizeof (ipv4_address)); - vty_out (vty, " IPv4 Address: %s\n", ipv4_address); - } - - /* for the IS neighbor tlv */ - if (lsp->tlv_data.is_neighs) - for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, lnode, is_neigh)) - { - lspid_print (is_neigh->neigh_id, LSPid, dynhost, 0); - vty_out (vty, " Metric : %-8" PRIu8 " IS : %s\n", - is_neigh->metrics.metric_default, LSPid); - } - - /* for the internal reachable tlv */ - if (lsp->tlv_data.ipv4_int_reachs) - for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_int_reachs, lnode, - ipv4_reach)) - { - memcpy (ipv4_reach_prefix, inet_ntoa (ipv4_reach->prefix), - sizeof (ipv4_reach_prefix)); - memcpy (ipv4_reach_mask, inet_ntoa (ipv4_reach->mask), - sizeof (ipv4_reach_mask)); - vty_out (vty, " Metric : %-8" PRIu8 " IPv4-Internal : %s %s\n", - ipv4_reach->metrics.metric_default, ipv4_reach_prefix, - ipv4_reach_mask); - } - - /* for the external reachable tlv */ - if (lsp->tlv_data.ipv4_ext_reachs) - for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv4_ext_reachs, lnode, - ipv4_reach)) - { - memcpy (ipv4_reach_prefix, inet_ntoa (ipv4_reach->prefix), - sizeof (ipv4_reach_prefix)); - memcpy (ipv4_reach_mask, inet_ntoa (ipv4_reach->mask), - sizeof (ipv4_reach_mask)); - vty_out (vty, " Metric : %-8" PRIu8 " IPv4-External : %s %s\n", - ipv4_reach->metrics.metric_default, ipv4_reach_prefix, - ipv4_reach_mask); - } - - /* IPv6 tlv */ - lsp_print_mt_ipv6_reach(lsp->tlv_data.ipv6_reachs, vty, - ISIS_MT_IPV4_UNICAST); - - /* MT IPv6 reachability tlv */ - for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.mt_ipv6_reachs, lnode, mt_ipv6_reachs)) - lsp_print_mt_ipv6_reach(mt_ipv6_reachs->list, vty, mt_ipv6_reachs->mtid); - - /* TE IS neighbor tlv */ - lsp_print_mt_reach(lsp->tlv_data.te_is_neighs, vty, - dynhost, ISIS_MT_IPV4_UNICAST); - - /* MT IS neighbor tlv */ - for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.mt_is_neighs, lnode, mt_is_neigh)) - lsp_print_mt_reach(mt_is_neigh->list, vty, dynhost, mt_is_neigh->mtid); - - /* TE IPv4 tlv */ - lsp_print_mt_ipv4_reach(lsp->tlv_data.te_ipv4_reachs, vty, - ISIS_MT_IPV4_UNICAST); - - /* MT IPv4 reachability tlv */ - for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.mt_ipv4_reachs, lnode, mt_ipv4_reachs)) - lsp_print_mt_ipv4_reach(mt_ipv4_reachs->list, vty, mt_ipv4_reachs->mtid); - - vty_out (vty, "\n"); - - return; + struct area_addr *area_addr; + int i; + struct listnode *lnode; + struct is_neigh *is_neigh; + struct ipv4_reachability *ipv4_reach; + struct in_addr *ipv4_addr; + struct mt_router_info *mt_router_info; + struct tlv_mt_ipv6_reachs *mt_ipv6_reachs; + struct tlv_mt_neighbors *mt_is_neigh; + struct tlv_mt_ipv4_reachs *mt_ipv4_reachs; + u_char LSPid[255]; + u_char hostname[255]; + u_char ipv4_reach_prefix[20]; + u_char ipv4_reach_mask[20]; + u_char ipv4_address[20]; + + lspid_print(lsp->lsp_header->lsp_id, LSPid, dynhost, 1); + lsp_print(lsp, vty, dynhost); + + /* for all area address */ + if (lsp->tlv_data.area_addrs) + for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.area_addrs, lnode, + area_addr)) { + vty_out(vty, " Area Address: %s\n", + isonet_print(area_addr->area_addr, + area_addr->addr_len)); + } + + /* for the nlpid tlv */ + if (lsp->tlv_data.nlpids) { + for (i = 0; i < lsp->tlv_data.nlpids->count; i++) { + switch (lsp->tlv_data.nlpids->nlpids[i]) { + case NLPID_IP: + case NLPID_IPV6: + vty_out(vty, " NLPID : 0x%X\n", + lsp->tlv_data.nlpids->nlpids[i]); + break; + default: + vty_out(vty, " NLPID : %s\n", "unknown"); + break; + } + } + } + + for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.mt_router_info, lnode, + mt_router_info)) { + vty_out(vty, " MT : %s%s\n", + isis_mtid2str(mt_router_info->mtid), + mt_router_info->overload ? " (overload)" : ""); + } + + /* for the hostname tlv */ + if (lsp->tlv_data.hostname) { + bzero(hostname, sizeof(hostname)); + memcpy(hostname, lsp->tlv_data.hostname->name, + lsp->tlv_data.hostname->namelen); + vty_out(vty, " Hostname : %s\n", hostname); + } + + /* authentication tlv */ + if (lsp->tlv_data.auth_info.type != ISIS_PASSWD_TYPE_UNUSED) { + if (lsp->tlv_data.auth_info.type == ISIS_PASSWD_TYPE_HMAC_MD5) + vty_out(vty, " Auth type : md5\n"); + else if (lsp->tlv_data.auth_info.type + == ISIS_PASSWD_TYPE_CLEARTXT) + vty_out(vty, " Auth type : clear text\n"); + } + + /* TE router id */ + if (lsp->tlv_data.router_id) { + memcpy(ipv4_address, inet_ntoa(lsp->tlv_data.router_id->id), + sizeof(ipv4_address)); + vty_out(vty, " Router ID : %s\n", ipv4_address); + } + + if (lsp->tlv_data.ipv4_addrs) + for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.ipv4_addrs, lnode, + ipv4_addr)) { + memcpy(ipv4_address, inet_ntoa(*ipv4_addr), + sizeof(ipv4_address)); + vty_out(vty, " IPv4 Address: %s\n", ipv4_address); + } + + /* for the IS neighbor tlv */ + if (lsp->tlv_data.is_neighs) + for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.is_neighs, lnode, + is_neigh)) { + lspid_print(is_neigh->neigh_id, LSPid, dynhost, 0); + vty_out(vty, " Metric : %-8" PRIu8 + " IS : %s\n", + is_neigh->metrics.metric_default, LSPid); + } + + /* for the internal reachable tlv */ + if (lsp->tlv_data.ipv4_int_reachs) + for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.ipv4_int_reachs, lnode, + ipv4_reach)) { + memcpy(ipv4_reach_prefix, inet_ntoa(ipv4_reach->prefix), + sizeof(ipv4_reach_prefix)); + memcpy(ipv4_reach_mask, inet_ntoa(ipv4_reach->mask), + sizeof(ipv4_reach_mask)); + vty_out(vty, " Metric : %-8" PRIu8 + " IPv4-Internal : %s %s\n", + ipv4_reach->metrics.metric_default, + ipv4_reach_prefix, ipv4_reach_mask); + } + + /* for the external reachable tlv */ + if (lsp->tlv_data.ipv4_ext_reachs) + for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.ipv4_ext_reachs, lnode, + ipv4_reach)) { + memcpy(ipv4_reach_prefix, inet_ntoa(ipv4_reach->prefix), + sizeof(ipv4_reach_prefix)); + memcpy(ipv4_reach_mask, inet_ntoa(ipv4_reach->mask), + sizeof(ipv4_reach_mask)); + vty_out(vty, " Metric : %-8" PRIu8 + " IPv4-External : %s %s\n", + ipv4_reach->metrics.metric_default, + ipv4_reach_prefix, ipv4_reach_mask); + } + + /* IPv6 tlv */ + lsp_print_mt_ipv6_reach(lsp->tlv_data.ipv6_reachs, vty, + ISIS_MT_IPV4_UNICAST); + + /* MT IPv6 reachability tlv */ + for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.mt_ipv6_reachs, lnode, + mt_ipv6_reachs)) + lsp_print_mt_ipv6_reach(mt_ipv6_reachs->list, vty, + mt_ipv6_reachs->mtid); + + /* TE IS neighbor tlv */ + lsp_print_mt_reach(lsp->tlv_data.te_is_neighs, vty, dynhost, + ISIS_MT_IPV4_UNICAST); + + /* MT IS neighbor tlv */ + for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.mt_is_neighs, lnode, + mt_is_neigh)) + lsp_print_mt_reach(mt_is_neigh->list, vty, dynhost, + mt_is_neigh->mtid); + + /* TE IPv4 tlv */ + lsp_print_mt_ipv4_reach(lsp->tlv_data.te_ipv4_reachs, vty, + ISIS_MT_IPV4_UNICAST); + + /* MT IPv4 reachability tlv */ + for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.mt_ipv4_reachs, lnode, + mt_ipv4_reachs)) + lsp_print_mt_ipv4_reach(mt_ipv4_reachs->list, vty, + mt_ipv4_reachs->mtid); + + vty_out(vty, "\n"); + + return; } /* print all the lsps info in the local lspdb */ -int -lsp_print_all (struct vty *vty, dict_t * lspdb, char detail, char dynhost) +int lsp_print_all(struct vty *vty, dict_t *lspdb, char detail, char dynhost) { - dnode_t *node = dict_first (lspdb), *next; - int lsp_count = 0; - - if (detail == ISIS_UI_LEVEL_BRIEF) - { - while (node != NULL) - { - /* I think it is unnecessary, so I comment it out */ - /* dict_contains (lspdb, node); */ - next = dict_next (lspdb, node); - lsp_print (dnode_get (node), vty, dynhost); - node = next; - lsp_count++; - } - } - else if (detail == ISIS_UI_LEVEL_DETAIL) - { - while (node != NULL) - { - next = dict_next (lspdb, node); - lsp_print_detail (dnode_get (node), vty, dynhost); - node = next; - lsp_count++; - } - } - - return lsp_count; + dnode_t *node = dict_first(lspdb), *next; + int lsp_count = 0; + + if (detail == ISIS_UI_LEVEL_BRIEF) { + while (node != NULL) { + /* I think it is unnecessary, so I comment it out */ + /* dict_contains (lspdb, node); */ + next = dict_next(lspdb, node); + lsp_print(dnode_get(node), vty, dynhost); + node = next; + lsp_count++; + } + } else if (detail == ISIS_UI_LEVEL_DETAIL) { + while (node != NULL) { + next = dict_next(lspdb, node); + lsp_print_detail(dnode_get(node), vty, dynhost); + node = next; + lsp_count++; + } + } + + return lsp_count; } -static void -_lsp_tlv_fit (struct isis_lsp *lsp, struct list **from, struct list **to, - int frag_thold, - unsigned int tlv_build_func (struct list *, struct stream *, - void *arg), - void *arg) +static void _lsp_tlv_fit(struct isis_lsp *lsp, struct list **from, + struct list **to, int frag_thold, + unsigned int tlv_build_func(struct list *, + struct stream *, + void *arg), + void *arg) { - while (*from && listcount(*from)) - { - unsigned int count; - - count = tlv_build_func(*from, lsp->pdu, arg); - - if (listcount(*to) != 0 || count != listcount(*from)) - { - struct listnode *node, *nnode; - void *elem; - - for (ALL_LIST_ELEMENTS(*from, node, nnode, elem)) - { - if (!count) - break; - listnode_add (*to, elem); - list_delete_node (*from, node); - --count; - } - } - else - { - list_free (*to); - *to = *from; - *from = NULL; - } - } + while (*from && listcount(*from)) { + unsigned int count; + + count = tlv_build_func(*from, lsp->pdu, arg); + + if (listcount(*to) != 0 || count != listcount(*from)) { + struct listnode *node, *nnode; + void *elem; + + for (ALL_LIST_ELEMENTS(*from, node, nnode, elem)) { + if (!count) + break; + listnode_add(*to, elem); + list_delete_node(*from, node); + --count; + } + } else { + list_free(*to); + *to = *from; + *from = NULL; + } + } } -#define FRAG_THOLD(S,T) \ - ((STREAM_SIZE(S)*T)/100) +#define FRAG_THOLD(S, T) ((STREAM_SIZE(S) * T) / 100) /* stream*, area->lsp_frag_threshold, increment */ -#define FRAG_NEEDED(S,T,I) \ - (STREAM_SIZE(S)-STREAM_REMAIN(S)+(I) > FRAG_THOLD(S,T)) +#define FRAG_NEEDED(S, T, I) \ + (STREAM_SIZE(S) - STREAM_REMAIN(S) + (I) > FRAG_THOLD(S, T)) /* FIXME: It shouldn't be necessary to pass tlvsize here, TLVs can have * variable length (TE TLVs, sub TLVs). */ -static void -lsp_tlv_fit (struct isis_lsp *lsp, struct list **from, struct list **to, - int tlvsize, int frag_thold, - int tlv_build_func (struct list *, struct stream *)) +static void lsp_tlv_fit(struct isis_lsp *lsp, struct list **from, + struct list **to, int tlvsize, int frag_thold, + int tlv_build_func(struct list *, struct stream *)) { - int count, i; - - /* can we fit all ? */ - if (!FRAG_NEEDED (lsp->pdu, frag_thold, listcount (*from) * tlvsize + 2)) - { - tlv_build_func (*from, lsp->pdu); - if (listcount (*to) != 0) - { - struct listnode *node, *nextnode; - void *elem; - - for (ALL_LIST_ELEMENTS (*from, node, nextnode, elem)) - { - listnode_add (*to, elem); - list_delete_node (*from, node); - } - } - else - { - list_free (*to); - *to = *from; - *from = NULL; - } - } - else if (!FRAG_NEEDED (lsp->pdu, frag_thold, tlvsize + 2)) - { - /* fit all we can */ - count = FRAG_THOLD (lsp->pdu, frag_thold) - 2 - - (STREAM_SIZE (lsp->pdu) - STREAM_REMAIN (lsp->pdu)); - count = count / tlvsize; - if (count > (int)listcount (*from)) - count = listcount (*from); - for (i = 0; i < count; i++) - { - listnode_add (*to, listgetdata (listhead (*from))); - listnode_delete (*from, listgetdata (listhead (*from))); - } - tlv_build_func (*to, lsp->pdu); - } - lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu)); - return; + int count, i; + + /* can we fit all ? */ + if (!FRAG_NEEDED(lsp->pdu, frag_thold, + listcount(*from) * tlvsize + 2)) { + tlv_build_func(*from, lsp->pdu); + if (listcount(*to) != 0) { + struct listnode *node, *nextnode; + void *elem; + + for (ALL_LIST_ELEMENTS(*from, node, nextnode, elem)) { + listnode_add(*to, elem); + list_delete_node(*from, node); + } + } else { + list_free(*to); + *to = *from; + *from = NULL; + } + } else if (!FRAG_NEEDED(lsp->pdu, frag_thold, tlvsize + 2)) { + /* fit all we can */ + count = FRAG_THOLD(lsp->pdu, frag_thold) - 2 + - (STREAM_SIZE(lsp->pdu) - STREAM_REMAIN(lsp->pdu)); + count = count / tlvsize; + if (count > (int)listcount(*from)) + count = listcount(*from); + for (i = 0; i < count; i++) { + listnode_add(*to, listgetdata(listhead(*from))); + listnode_delete(*from, listgetdata(listhead(*from))); + } + tlv_build_func(*to, lsp->pdu); + } + lsp->lsp_header->pdu_len = htons(stream_get_endp(lsp->pdu)); + return; } -static u_int16_t -lsp_rem_lifetime (struct isis_area *area, int level) +static u_int16_t lsp_rem_lifetime(struct isis_area *area, int level) { - u_int16_t rem_lifetime; + u_int16_t rem_lifetime; - /* Add jitter to configured LSP lifetime */ - rem_lifetime = isis_jitter (area->max_lsp_lifetime[level - 1], - MAX_AGE_JITTER); + /* Add jitter to configured LSP lifetime */ + rem_lifetime = + isis_jitter(area->max_lsp_lifetime[level - 1], MAX_AGE_JITTER); - /* No jitter if the max refresh will be less than configure gen interval */ - /* N.B. this calucation is acceptable since rem_lifetime is in [332,65535] at - * this point */ - if (area->lsp_gen_interval[level - 1] > (rem_lifetime - 300)) - rem_lifetime = area->max_lsp_lifetime[level - 1]; + /* No jitter if the max refresh will be less than configure gen interval + */ + /* N.B. this calucation is acceptable since rem_lifetime is in + * [332,65535] at + * this point */ + if (area->lsp_gen_interval[level - 1] > (rem_lifetime - 300)) + rem_lifetime = area->max_lsp_lifetime[level - 1]; - return rem_lifetime; + return rem_lifetime; } -static u_int16_t -lsp_refresh_time (struct isis_lsp *lsp, u_int16_t rem_lifetime) +static u_int16_t lsp_refresh_time(struct isis_lsp *lsp, u_int16_t rem_lifetime) { - struct isis_area *area = lsp->area; - int level = lsp->level; - u_int16_t refresh_time; + struct isis_area *area = lsp->area; + int level = lsp->level; + u_int16_t refresh_time; - /* Add jitter to LSP refresh time */ - refresh_time = isis_jitter (area->lsp_refresh[level - 1], - MAX_LSP_GEN_JITTER); + /* Add jitter to LSP refresh time */ + refresh_time = + isis_jitter(area->lsp_refresh[level - 1], MAX_LSP_GEN_JITTER); - /* RFC 4444 : make sure the refresh time is at least less than 300 - * of the remaining lifetime and more than gen interval */ - if (refresh_time <= area->lsp_gen_interval[level - 1] || - refresh_time > (rem_lifetime - 300)) - refresh_time = rem_lifetime - 300; + /* RFC 4444 : make sure the refresh time is at least less than 300 + * of the remaining lifetime and more than gen interval */ + if (refresh_time <= area->lsp_gen_interval[level - 1] + || refresh_time > (rem_lifetime - 300)) + refresh_time = rem_lifetime - 300; - /* In cornercases, refresh_time might be <= lsp_gen_interval, however - * we accept this violation to satisfy refresh_time <= rem_lifetime - 300 */ + /* In cornercases, refresh_time might be <= lsp_gen_interval, however + * we accept this violation to satisfy refresh_time <= rem_lifetime - + * 300 */ - return refresh_time; + return refresh_time; } -static struct isis_lsp * -lsp_next_frag (u_char frag_num, struct isis_lsp *lsp0, struct isis_area *area, - int level) +static struct isis_lsp *lsp_next_frag(u_char frag_num, struct isis_lsp *lsp0, + struct isis_area *area, int level) { - struct isis_lsp *lsp; - u_char frag_id[ISIS_SYS_ID_LEN + 2]; - - memcpy (frag_id, lsp0->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 1); - LSP_FRAGMENT (frag_id) = frag_num; - /* FIXME add authentication TLV for fragment LSPs */ - lsp = lsp_search (frag_id, area->lspdb[level - 1]); - if (lsp) - { - /* Clear the TLVs */ - lsp_clear_data (lsp); - return lsp; - } - lsp = lsp_new (area, frag_id, ntohs(lsp0->lsp_header->rem_lifetime), 0, - lsp_bits_generate (level, area->overload_bit, - area->attached_bit), 0, level); - lsp->area = area; - lsp->own_lsp = 1; - lsp_insert (lsp, area->lspdb[level - 1]); - listnode_add (lsp0->lspu.frags, lsp); - lsp->lspu.zero_lsp = lsp0; - return lsp; + struct isis_lsp *lsp; + u_char frag_id[ISIS_SYS_ID_LEN + 2]; + + memcpy(frag_id, lsp0->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 1); + LSP_FRAGMENT(frag_id) = frag_num; + /* FIXME add authentication TLV for fragment LSPs */ + lsp = lsp_search(frag_id, area->lspdb[level - 1]); + if (lsp) { + /* Clear the TLVs */ + lsp_clear_data(lsp); + return lsp; + } + lsp = lsp_new(area, frag_id, ntohs(lsp0->lsp_header->rem_lifetime), 0, + lsp_bits_generate(level, area->overload_bit, + area->attached_bit), + 0, level); + lsp->area = area; + lsp->own_lsp = 1; + lsp_insert(lsp, area->lspdb[level - 1]); + listnode_add(lsp0->lspu.frags, lsp); + lsp->lspu.zero_lsp = lsp0; + return lsp; } -static void -lsp_build_ext_reach_ipv4(struct isis_lsp *lsp, struct isis_area *area, - struct tlvs *tlv_data) +static void lsp_build_ext_reach_ipv4(struct isis_lsp *lsp, + struct isis_area *area, + struct tlvs *tlv_data) { - struct route_table *er_table; - struct route_node *rn; - struct prefix_ipv4 *ipv4; - struct isis_ext_info *info; - struct ipv4_reachability *ipreach; - struct te_ipv4_reachability *te_ipreach; - - er_table = get_ext_reach(area, AF_INET, lsp->level); - if (!er_table) - return; - - for (rn = route_top(er_table); rn; rn = route_next(rn)) - { - if (!rn->info) - continue; - - ipv4 = (struct prefix_ipv4*)&rn->p; - info = rn->info; - if (area->oldmetric) - { - if (tlv_data->ipv4_ext_reachs == NULL) - { - tlv_data->ipv4_ext_reachs = list_new(); - tlv_data->ipv4_ext_reachs->del = free_tlv; - } - ipreach = XMALLOC(MTYPE_ISIS_TLV, sizeof(*ipreach)); - - ipreach->prefix.s_addr = ipv4->prefix.s_addr; - masklen2ip(ipv4->prefixlen, &ipreach->mask); - ipreach->prefix.s_addr &= ipreach->mask.s_addr; - - if ((info->metric & 0x3f) != info->metric) - ipreach->metrics.metric_default = 0x3f; - else - ipreach->metrics.metric_default = info->metric; - ipreach->metrics.metric_expense = METRICS_UNSUPPORTED; - ipreach->metrics.metric_error = METRICS_UNSUPPORTED; - ipreach->metrics.metric_delay = METRICS_UNSUPPORTED; - listnode_add(tlv_data->ipv4_ext_reachs, ipreach); - } - if (area->newmetric) - { - if (tlv_data->te_ipv4_reachs == NULL) - { - tlv_data->te_ipv4_reachs = list_new(); - tlv_data->te_ipv4_reachs->del = free_tlv; - } - te_ipreach = - XCALLOC(MTYPE_ISIS_TLV, - sizeof(*te_ipreach) - 1 + PSIZE(ipv4->prefixlen)); - if (info->metric > MAX_WIDE_PATH_METRIC) - te_ipreach->te_metric = htonl(MAX_WIDE_PATH_METRIC); - else - te_ipreach->te_metric = htonl(info->metric); - te_ipreach->control = ipv4->prefixlen & 0x3f; - memcpy(&te_ipreach->prefix_start, &ipv4->prefix.s_addr, - PSIZE(ipv4->prefixlen)); - listnode_add(tlv_data->te_ipv4_reachs, te_ipreach); - } - } + struct route_table *er_table; + struct route_node *rn; + struct prefix_ipv4 *ipv4; + struct isis_ext_info *info; + struct ipv4_reachability *ipreach; + struct te_ipv4_reachability *te_ipreach; + + er_table = get_ext_reach(area, AF_INET, lsp->level); + if (!er_table) + return; + + for (rn = route_top(er_table); rn; rn = route_next(rn)) { + if (!rn->info) + continue; + + ipv4 = (struct prefix_ipv4 *)&rn->p; + info = rn->info; + if (area->oldmetric) { + if (tlv_data->ipv4_ext_reachs == NULL) { + tlv_data->ipv4_ext_reachs = list_new(); + tlv_data->ipv4_ext_reachs->del = free_tlv; + } + ipreach = XMALLOC(MTYPE_ISIS_TLV, sizeof(*ipreach)); + + ipreach->prefix.s_addr = ipv4->prefix.s_addr; + masklen2ip(ipv4->prefixlen, &ipreach->mask); + ipreach->prefix.s_addr &= ipreach->mask.s_addr; + + if ((info->metric & 0x3f) != info->metric) + ipreach->metrics.metric_default = 0x3f; + else + ipreach->metrics.metric_default = info->metric; + ipreach->metrics.metric_expense = METRICS_UNSUPPORTED; + ipreach->metrics.metric_error = METRICS_UNSUPPORTED; + ipreach->metrics.metric_delay = METRICS_UNSUPPORTED; + listnode_add(tlv_data->ipv4_ext_reachs, ipreach); + } + if (area->newmetric) { + if (tlv_data->te_ipv4_reachs == NULL) { + tlv_data->te_ipv4_reachs = list_new(); + tlv_data->te_ipv4_reachs->del = free_tlv; + } + te_ipreach = XCALLOC(MTYPE_ISIS_TLV, + sizeof(*te_ipreach) - 1 + + PSIZE(ipv4->prefixlen)); + if (info->metric > MAX_WIDE_PATH_METRIC) + te_ipreach->te_metric = + htonl(MAX_WIDE_PATH_METRIC); + else + te_ipreach->te_metric = htonl(info->metric); + te_ipreach->control = ipv4->prefixlen & 0x3f; + memcpy(&te_ipreach->prefix_start, &ipv4->prefix.s_addr, + PSIZE(ipv4->prefixlen)); + listnode_add(tlv_data->te_ipv4_reachs, te_ipreach); + } + } } -static struct list * -tlv_get_ipv6_reach_list(struct isis_area *area, struct tlvs *tlv_data) +static struct list *tlv_get_ipv6_reach_list(struct isis_area *area, + struct tlvs *tlv_data) { - uint16_t mtid = isis_area_ipv6_topology(area); - if (mtid == ISIS_MT_IPV4_UNICAST) - { - if (!tlv_data->ipv6_reachs) - { - tlv_data->ipv6_reachs = list_new(); - tlv_data->ipv6_reachs->del = free_tlv; - } - return tlv_data->ipv6_reachs; - } - - struct tlv_mt_ipv6_reachs *reachs = tlvs_get_mt_ipv6_reachs(tlv_data, mtid); - return reachs->list; + uint16_t mtid = isis_area_ipv6_topology(area); + if (mtid == ISIS_MT_IPV4_UNICAST) { + if (!tlv_data->ipv6_reachs) { + tlv_data->ipv6_reachs = list_new(); + tlv_data->ipv6_reachs->del = free_tlv; + } + return tlv_data->ipv6_reachs; + } + + struct tlv_mt_ipv6_reachs *reachs = + tlvs_get_mt_ipv6_reachs(tlv_data, mtid); + return reachs->list; } -static void -lsp_build_ext_reach_ipv6(struct isis_lsp *lsp, struct isis_area *area, - struct tlvs *tlv_data) +static void lsp_build_ext_reach_ipv6(struct isis_lsp *lsp, + struct isis_area *area, + struct tlvs *tlv_data) { - struct route_table *er_table; - struct route_node *rn; - struct prefix_ipv6 *ipv6; - struct isis_ext_info *info; - struct ipv6_reachability *ip6reach; - struct list *reach_list = NULL; - - er_table = get_ext_reach(area, AF_INET6, lsp->level); - if (!er_table) - return; - - for (rn = route_top(er_table); rn; rn = route_next(rn)) - { - if (!rn->info) - continue; - - ipv6 = (struct prefix_ipv6*)&rn->p; - info = rn->info; - - if (!reach_list) - reach_list = tlv_get_ipv6_reach_list(area, tlv_data); - - ip6reach = XCALLOC(MTYPE_ISIS_TLV, sizeof(*ip6reach)); - if (info->metric > MAX_WIDE_PATH_METRIC) - ip6reach->metric = htonl(MAX_WIDE_PATH_METRIC); - else - ip6reach->metric = htonl(info->metric); - ip6reach->control_info = DISTRIBUTION_EXTERNAL; - ip6reach->prefix_len = ipv6->prefixlen; - memcpy(ip6reach->prefix, ipv6->prefix.s6_addr, sizeof(ip6reach->prefix)); - listnode_add(reach_list, ip6reach); - } + struct route_table *er_table; + struct route_node *rn; + struct prefix_ipv6 *ipv6; + struct isis_ext_info *info; + struct ipv6_reachability *ip6reach; + struct list *reach_list = NULL; + + er_table = get_ext_reach(area, AF_INET6, lsp->level); + if (!er_table) + return; + + for (rn = route_top(er_table); rn; rn = route_next(rn)) { + if (!rn->info) + continue; + + ipv6 = (struct prefix_ipv6 *)&rn->p; + info = rn->info; + + if (!reach_list) + reach_list = tlv_get_ipv6_reach_list(area, tlv_data); + + ip6reach = XCALLOC(MTYPE_ISIS_TLV, sizeof(*ip6reach)); + if (info->metric > MAX_WIDE_PATH_METRIC) + ip6reach->metric = htonl(MAX_WIDE_PATH_METRIC); + else + ip6reach->metric = htonl(info->metric); + ip6reach->control_info = DISTRIBUTION_EXTERNAL; + ip6reach->prefix_len = ipv6->prefixlen; + memcpy(ip6reach->prefix, ipv6->prefix.s6_addr, + sizeof(ip6reach->prefix)); + listnode_add(reach_list, ip6reach); + } } -static void -lsp_build_ext_reach (struct isis_lsp *lsp, struct isis_area *area, - struct tlvs *tlv_data) +static void lsp_build_ext_reach(struct isis_lsp *lsp, struct isis_area *area, + struct tlvs *tlv_data) { - lsp_build_ext_reach_ipv4(lsp, area, tlv_data); - lsp_build_ext_reach_ipv6(lsp, area, tlv_data); + lsp_build_ext_reach_ipv4(lsp, area, tlv_data); + lsp_build_ext_reach_ipv6(lsp, area, tlv_data); } /* - * Builds the LSP data part. This func creates a new frag whenever + * Builds the LSP data part. This func creates a new frag whenever * area->lsp_frag_threshold is exceeded. */ -static void -lsp_build (struct isis_lsp *lsp, struct isis_area *area) +static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) { - struct is_neigh *is_neigh; - struct te_is_neigh *te_is_neigh; - struct listnode *node, *ipnode; - int level = lsp->level; - struct isis_circuit *circuit; - struct prefix_ipv4 *ipv4; - struct ipv4_reachability *ipreach; - struct te_ipv4_reachability *te_ipreach; - struct isis_adjacency *nei; - struct prefix_ipv6 *ipv6, ip6prefix; - struct list *ipv6_reachs = NULL; - struct ipv6_reachability *ip6reach; - struct tlvs tlv_data; - struct isis_lsp *lsp0 = lsp; - struct in_addr *routerid; - uint32_t expected = 0, found = 0; - uint32_t metric; - u_char zero_id[ISIS_SYS_ID_LEN + 1]; - int retval = ISIS_OK; - char buf[BUFSIZ]; - - lsp_debug("ISIS (%s): Constructing local system LSP for level %d", area->area_tag, level); - - /* - * Building the zero lsp - */ - memset (zero_id, 0, ISIS_SYS_ID_LEN + 1); - - /* Reset stream endp. Stream is always there and on every LSP refresh only - * TLV part of it is overwritten. So we must seek past header we will not - * touch. */ - stream_reset (lsp->pdu); - stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); - - /* - * Add the authentication info if its present - */ - lsp_auth_add (lsp); - - /* - * First add the tlvs related to area - */ - - /* Area addresses */ - if (lsp->tlv_data.area_addrs == NULL) - lsp->tlv_data.area_addrs = list_new (); - list_add_list (lsp->tlv_data.area_addrs, area->area_addrs); - if (listcount (lsp->tlv_data.area_addrs) > 0) - tlv_add_area_addrs (lsp->tlv_data.area_addrs, lsp->pdu); - - /* Protocols Supported */ - if (area->ip_circuits > 0 || area->ipv6_circuits > 0) - { - lsp->tlv_data.nlpids = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct nlpids)); - lsp->tlv_data.nlpids->count = 0; - if (area->ip_circuits > 0) - { - lsp_debug("ISIS (%s): Found IPv4 circuit, adding IPv4 to NLPIDs", area->area_tag); - lsp->tlv_data.nlpids->count++; - lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP; - } - if (area->ipv6_circuits > 0) - { - lsp_debug("ISIS (%s): Found IPv6 circuit, adding IPv6 to NLPIDs", area->area_tag); - lsp->tlv_data.nlpids->count++; - lsp->tlv_data.nlpids->nlpids[lsp->tlv_data.nlpids->count - 1] = - NLPID_IPV6; - } - tlv_add_nlpid (lsp->tlv_data.nlpids, lsp->pdu); - } - - if (area_is_mt(area)) - { - lsp_debug("ISIS (%s): Adding MT router tlv...", area->area_tag); - lsp->tlv_data.mt_router_info = list_new(); - lsp->tlv_data.mt_router_info->del = free_tlv; - - struct isis_area_mt_setting **mt_settings; - unsigned int mt_count; - - mt_settings = area_mt_settings(area, &mt_count); - for (unsigned int i = 0; i < mt_count; i++) - { - struct mt_router_info *info; - - info = XCALLOC(MTYPE_ISIS_TLV, sizeof(*info)); - info->mtid = mt_settings[i]->mtid; - info->overload = mt_settings[i]->overload; - listnode_add(lsp->tlv_data.mt_router_info, info); - lsp_debug("ISIS (%s): MT %s", area->area_tag, isis_mtid2str(info->mtid)); - } - tlv_add_mt_router_info (lsp->tlv_data.mt_router_info, lsp->pdu); - } - else - { - lsp_debug("ISIS (%s): Not adding MT router tlv (disabled)", area->area_tag); - } - /* Dynamic Hostname */ - if (area->dynhostname) - { - const char *hostname = unix_hostname(); - size_t hostname_len = strlen(hostname); - - lsp->tlv_data.hostname = XMALLOC (MTYPE_ISIS_TLV, - sizeof (struct hostname)); - - strncpy((char *)lsp->tlv_data.hostname->name, hostname, - sizeof(lsp->tlv_data.hostname->name)); - if (hostname_len <= MAX_TLV_LEN) - lsp->tlv_data.hostname->namelen = hostname_len; - else - lsp->tlv_data.hostname->namelen = MAX_TLV_LEN; - - lsp_debug("ISIS (%s): Adding dynamic hostname '%.*s'", area->area_tag, - lsp->tlv_data.hostname->namelen, lsp->tlv_data.hostname->name); - tlv_add_dynamic_hostname (lsp->tlv_data.hostname, lsp->pdu); - } - else - { - lsp_debug("ISIS (%s): Not adding dynamic hostname (disabled)", area->area_tag); - } - - /* IPv4 address and TE router ID TLVs. In case of the first one we don't - * follow "C" vendor, but "J" vendor behavior - one IPv4 address is put into - * LSP and this address is same as router id. */ - if (isis->router_id != 0) - { - inet_ntop(AF_INET, &isis->router_id, buf, sizeof(buf)); - lsp_debug("ISIS (%s): Adding router ID %s as IPv4 tlv.", area->area_tag, buf); - if (lsp->tlv_data.ipv4_addrs == NULL) - { - lsp->tlv_data.ipv4_addrs = list_new (); - lsp->tlv_data.ipv4_addrs->del = free_tlv; - } - - routerid = XMALLOC (MTYPE_ISIS_TLV, sizeof (struct in_addr)); - routerid->s_addr = isis->router_id; - listnode_add (lsp->tlv_data.ipv4_addrs, routerid); - tlv_add_in_addr (routerid, lsp->pdu, IPV4_ADDR); - - /* Exactly same data is put into TE router ID TLV, but only if new style - * TLV's are in use. */ - if (area->newmetric) - { - lsp_debug("ISIS (%s): Adding router ID also as TE router ID tlv.", area->area_tag); - lsp->tlv_data.router_id = XMALLOC (MTYPE_ISIS_TLV, - sizeof (struct in_addr)); - lsp->tlv_data.router_id->id.s_addr = isis->router_id; - tlv_add_in_addr (&lsp->tlv_data.router_id->id, lsp->pdu, - TE_ROUTER_ID); - } - } - else - { - lsp_debug("ISIS (%s): Router ID is unset. Not adding tlv.", area->area_tag); - } - - memset (&tlv_data, 0, sizeof (struct tlvs)); - - lsp_debug("ISIS (%s): Adding circuit specific information.", area->area_tag); - - /* - * Then build lists of tlvs related to circuits - */ - for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit)) - { - if (!circuit->interface) - lsp_debug("ISIS (%s): Processing %s circuit %p with unknown interface", - area->area_tag, circuit_type2string(circuit->circ_type), circuit); - else - lsp_debug("ISIS (%s): Processing %s circuit %s", - area->area_tag, circuit_type2string(circuit->circ_type), circuit->interface->name); - - if (circuit->state != C_STATE_UP) - { - lsp_debug("ISIS (%s): Circuit is not up, ignoring.", area->area_tag); - continue; - } - - /* - * Add IPv4 internal reachability of this circuit - */ - if (circuit->ip_router && circuit->ip_addrs && - circuit->ip_addrs->count > 0) - { - lsp_debug("ISIS (%s): Circuit has IPv4 active, adding respective TLVs.", area->area_tag); - if (area->oldmetric) - { - if (tlv_data.ipv4_int_reachs == NULL) - { - tlv_data.ipv4_int_reachs = list_new (); - tlv_data.ipv4_int_reachs->del = free_tlv; + struct is_neigh *is_neigh; + struct te_is_neigh *te_is_neigh; + struct listnode *node, *ipnode; + int level = lsp->level; + struct isis_circuit *circuit; + struct prefix_ipv4 *ipv4; + struct ipv4_reachability *ipreach; + struct te_ipv4_reachability *te_ipreach; + struct isis_adjacency *nei; + struct prefix_ipv6 *ipv6, ip6prefix; + struct list *ipv6_reachs = NULL; + struct ipv6_reachability *ip6reach; + struct tlvs tlv_data; + struct isis_lsp *lsp0 = lsp; + struct in_addr *routerid; + uint32_t expected = 0, found = 0; + uint32_t metric; + u_char zero_id[ISIS_SYS_ID_LEN + 1]; + int retval = ISIS_OK; + char buf[BUFSIZ]; + + lsp_debug("ISIS (%s): Constructing local system LSP for level %d", + area->area_tag, level); + + /* + * Building the zero lsp + */ + memset(zero_id, 0, ISIS_SYS_ID_LEN + 1); + + /* Reset stream endp. Stream is always there and on every LSP refresh + * only + * TLV part of it is overwritten. So we must seek past header we will + * not + * touch. */ + stream_reset(lsp->pdu); + stream_forward_endp(lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); + + /* + * Add the authentication info if its present + */ + lsp_auth_add(lsp); + + /* + * First add the tlvs related to area + */ + + /* Area addresses */ + if (lsp->tlv_data.area_addrs == NULL) + lsp->tlv_data.area_addrs = list_new(); + list_add_list(lsp->tlv_data.area_addrs, area->area_addrs); + if (listcount(lsp->tlv_data.area_addrs) > 0) + tlv_add_area_addrs(lsp->tlv_data.area_addrs, lsp->pdu); + + /* Protocols Supported */ + if (area->ip_circuits > 0 || area->ipv6_circuits > 0) { + lsp->tlv_data.nlpids = + XCALLOC(MTYPE_ISIS_TLV, sizeof(struct nlpids)); + lsp->tlv_data.nlpids->count = 0; + if (area->ip_circuits > 0) { + lsp_debug( + "ISIS (%s): Found IPv4 circuit, adding IPv4 to NLPIDs", + area->area_tag); + lsp->tlv_data.nlpids->count++; + lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP; + } + if (area->ipv6_circuits > 0) { + lsp_debug( + "ISIS (%s): Found IPv6 circuit, adding IPv6 to NLPIDs", + area->area_tag); + lsp->tlv_data.nlpids->count++; + lsp->tlv_data.nlpids + ->nlpids[lsp->tlv_data.nlpids->count - 1] = + NLPID_IPV6; + } + tlv_add_nlpid(lsp->tlv_data.nlpids, lsp->pdu); + } + + if (area_is_mt(area)) { + lsp_debug("ISIS (%s): Adding MT router tlv...", area->area_tag); + lsp->tlv_data.mt_router_info = list_new(); + lsp->tlv_data.mt_router_info->del = free_tlv; + + struct isis_area_mt_setting **mt_settings; + unsigned int mt_count; + + mt_settings = area_mt_settings(area, &mt_count); + for (unsigned int i = 0; i < mt_count; i++) { + struct mt_router_info *info; + + info = XCALLOC(MTYPE_ISIS_TLV, sizeof(*info)); + info->mtid = mt_settings[i]->mtid; + info->overload = mt_settings[i]->overload; + listnode_add(lsp->tlv_data.mt_router_info, info); + lsp_debug("ISIS (%s): MT %s", area->area_tag, + isis_mtid2str(info->mtid)); } - for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, ipnode, ipv4)) - { - ipreach = - XMALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv4_reachability)); - ipreach->metrics.metric_default = circuit->metric[level - 1]; - ipreach->metrics.metric_expense = METRICS_UNSUPPORTED; - ipreach->metrics.metric_error = METRICS_UNSUPPORTED; - ipreach->metrics.metric_delay = METRICS_UNSUPPORTED; - masklen2ip (ipv4->prefixlen, &ipreach->mask); - ipreach->prefix.s_addr = ((ipreach->mask.s_addr) & - (ipv4->prefix.s_addr)); - inet_ntop(AF_INET, &ipreach->prefix.s_addr, buf, sizeof(buf)); - lsp_debug("ISIS (%s): Adding old-style IP reachability for %s/%d", - area->area_tag, buf, ipv4->prefixlen); - listnode_add (tlv_data.ipv4_int_reachs, ipreach); + tlv_add_mt_router_info(lsp->tlv_data.mt_router_info, lsp->pdu); + } else { + lsp_debug("ISIS (%s): Not adding MT router tlv (disabled)", + area->area_tag); + } + /* Dynamic Hostname */ + if (area->dynhostname) { + const char *hostname = unix_hostname(); + size_t hostname_len = strlen(hostname); + + lsp->tlv_data.hostname = + XMALLOC(MTYPE_ISIS_TLV, sizeof(struct hostname)); + + strncpy((char *)lsp->tlv_data.hostname->name, hostname, + sizeof(lsp->tlv_data.hostname->name)); + if (hostname_len <= MAX_TLV_LEN) + lsp->tlv_data.hostname->namelen = hostname_len; + else + lsp->tlv_data.hostname->namelen = MAX_TLV_LEN; + + lsp_debug("ISIS (%s): Adding dynamic hostname '%.*s'", + area->area_tag, lsp->tlv_data.hostname->namelen, + lsp->tlv_data.hostname->name); + tlv_add_dynamic_hostname(lsp->tlv_data.hostname, lsp->pdu); + } else { + lsp_debug("ISIS (%s): Not adding dynamic hostname (disabled)", + area->area_tag); + } + + /* IPv4 address and TE router ID TLVs. In case of the first one we don't + * follow "C" vendor, but "J" vendor behavior - one IPv4 address is put + * into + * LSP and this address is same as router id. */ + if (isis->router_id != 0) { + inet_ntop(AF_INET, &isis->router_id, buf, sizeof(buf)); + lsp_debug("ISIS (%s): Adding router ID %s as IPv4 tlv.", + area->area_tag, buf); + if (lsp->tlv_data.ipv4_addrs == NULL) { + lsp->tlv_data.ipv4_addrs = list_new(); + lsp->tlv_data.ipv4_addrs->del = free_tlv; } - } - if (area->newmetric) - { - if (tlv_data.te_ipv4_reachs == NULL) - { - tlv_data.te_ipv4_reachs = list_new (); - tlv_data.te_ipv4_reachs->del = free_tlv; + + routerid = XMALLOC(MTYPE_ISIS_TLV, sizeof(struct in_addr)); + routerid->s_addr = isis->router_id; + listnode_add(lsp->tlv_data.ipv4_addrs, routerid); + tlv_add_in_addr(routerid, lsp->pdu, IPV4_ADDR); + + /* Exactly same data is put into TE router ID TLV, but only if + * new style + * TLV's are in use. */ + if (area->newmetric) { + lsp_debug( + "ISIS (%s): Adding router ID also as TE router ID tlv.", + area->area_tag); + lsp->tlv_data.router_id = + XMALLOC(MTYPE_ISIS_TLV, sizeof(struct in_addr)); + lsp->tlv_data.router_id->id.s_addr = isis->router_id; + tlv_add_in_addr(&lsp->tlv_data.router_id->id, lsp->pdu, + TE_ROUTER_ID); } - for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, ipnode, ipv4)) - { - /* FIXME All this assumes that we have no sub TLVs. */ - te_ipreach = XCALLOC (MTYPE_ISIS_TLV, - sizeof (struct te_ipv4_reachability) + - ((ipv4->prefixlen + 7)/8) - 1); - - if (area->oldmetric) - te_ipreach->te_metric = htonl (circuit->metric[level - 1]); - else - te_ipreach->te_metric = htonl (circuit->te_metric[level - 1]); - - te_ipreach->control = (ipv4->prefixlen & 0x3F); - memcpy (&te_ipreach->prefix_start, &ipv4->prefix.s_addr, - (ipv4->prefixlen + 7)/8); - inet_ntop(AF_INET, &ipv4->prefix.s_addr, buf, sizeof(buf)); - lsp_debug("ISIS (%s): Adding te-style IP reachability for %s/%d", - area->area_tag, buf, ipv4->prefixlen); - listnode_add (tlv_data.te_ipv4_reachs, te_ipreach); + } else { + lsp_debug("ISIS (%s): Router ID is unset. Not adding tlv.", + area->area_tag); + } + + memset(&tlv_data, 0, sizeof(struct tlvs)); + + lsp_debug("ISIS (%s): Adding circuit specific information.", + area->area_tag); + + /* + * Then build lists of tlvs related to circuits + */ + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) { + if (!circuit->interface) + lsp_debug( + "ISIS (%s): Processing %s circuit %p with unknown interface", + area->area_tag, + circuit_type2string(circuit->circ_type), + circuit); + else + lsp_debug("ISIS (%s): Processing %s circuit %s", + area->area_tag, + circuit_type2string(circuit->circ_type), + circuit->interface->name); + + if (circuit->state != C_STATE_UP) { + lsp_debug("ISIS (%s): Circuit is not up, ignoring.", + area->area_tag); + continue; } - } - } - - /* - * Add IPv6 reachability of this circuit - */ - if (circuit->ipv6_router && circuit->ipv6_non_link && - circuit->ipv6_non_link->count > 0) - { - if (!ipv6_reachs) - ipv6_reachs = tlv_get_ipv6_reach_list(area, &tlv_data); - - for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, ipnode, ipv6)) - { - ip6reach = - XCALLOC (MTYPE_ISIS_TLV, sizeof (struct ipv6_reachability)); - - if (area->oldmetric) - ip6reach->metric = - htonl (circuit->metric[level - 1]); - else - ip6reach->metric = htonl (circuit->te_metric[level - 1]); - - ip6reach->control_info = 0; - ip6reach->prefix_len = ipv6->prefixlen; - memcpy(&ip6prefix, ipv6, sizeof(ip6prefix)); - apply_mask_ipv6(&ip6prefix); - - inet_ntop(AF_INET6, &ip6prefix.prefix.s6_addr, buf, sizeof(buf)); - lsp_debug("ISIS (%s): Adding IPv6 reachability for %s/%d", - area->area_tag, buf, ipv6->prefixlen); - - memcpy (ip6reach->prefix, ip6prefix.prefix.s6_addr, - sizeof (ip6reach->prefix)); - listnode_add (ipv6_reachs, ip6reach); - } - } - - switch (circuit->circ_type) - { - case CIRCUIT_T_BROADCAST: - if (level & circuit->is_type) - { - if (area->oldmetric) - { - if (tlv_data.is_neighs == NULL) - { - tlv_data.is_neighs = list_new (); - tlv_data.is_neighs->del = free_tlv; - } - is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh)); - if (level == IS_LEVEL_1) - memcpy (is_neigh->neigh_id, - circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1); - else - memcpy (is_neigh->neigh_id, - circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1); - is_neigh->metrics.metric_default = circuit->metric[level - 1]; - is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED; - is_neigh->metrics.metric_error = METRICS_UNSUPPORTED; - is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED; - if (!memcmp (is_neigh->neigh_id, zero_id, - ISIS_SYS_ID_LEN + 1)) - { - XFREE (MTYPE_ISIS_TLV, is_neigh); - lsp_debug("ISIS (%s): No DIS for circuit, not adding old-style IS neighbor.", - area->area_tag); - } - else - { - listnode_add (tlv_data.is_neighs, is_neigh); - lsp_debug("ISIS (%s): Adding DIS %s.%02x as old-style neighbor", - area->area_tag, sysid_print(is_neigh->neigh_id), - LSP_PSEUDO_ID(is_neigh->neigh_id)); - } + + /* + * Add IPv4 internal reachability of this circuit + */ + if (circuit->ip_router && circuit->ip_addrs + && circuit->ip_addrs->count > 0) { + lsp_debug( + "ISIS (%s): Circuit has IPv4 active, adding respective TLVs.", + area->area_tag); + if (area->oldmetric) { + if (tlv_data.ipv4_int_reachs == NULL) { + tlv_data.ipv4_int_reachs = list_new(); + tlv_data.ipv4_int_reachs->del = + free_tlv; + } + for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, + ipnode, ipv4)) { + ipreach = XMALLOC( + MTYPE_ISIS_TLV, + sizeof(struct + ipv4_reachability)); + ipreach->metrics.metric_default = + circuit->metric[level - 1]; + ipreach->metrics.metric_expense = + METRICS_UNSUPPORTED; + ipreach->metrics.metric_error = + METRICS_UNSUPPORTED; + ipreach->metrics.metric_delay = + METRICS_UNSUPPORTED; + masklen2ip(ipv4->prefixlen, + &ipreach->mask); + ipreach->prefix.s_addr = + ((ipreach->mask.s_addr) + & (ipv4->prefix.s_addr)); + inet_ntop(AF_INET, + &ipreach->prefix.s_addr, buf, + sizeof(buf)); + lsp_debug( + "ISIS (%s): Adding old-style IP reachability for %s/%d", + area->area_tag, buf, + ipv4->prefixlen); + listnode_add(tlv_data.ipv4_int_reachs, + ipreach); + } + } + if (area->newmetric) { + if (tlv_data.te_ipv4_reachs == NULL) { + tlv_data.te_ipv4_reachs = list_new(); + tlv_data.te_ipv4_reachs->del = free_tlv; + } + for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, + ipnode, ipv4)) { + /* FIXME All this assumes that we have + * no sub TLVs. */ + te_ipreach = XCALLOC( + MTYPE_ISIS_TLV, + sizeof(struct + te_ipv4_reachability) + + ((ipv4->prefixlen + 7) + / 8) + - 1); + + if (area->oldmetric) + te_ipreach->te_metric = htonl( + circuit->metric[level + - 1]); + else + te_ipreach->te_metric = htonl( + circuit->te_metric + [level - 1]); + + te_ipreach->control = + (ipv4->prefixlen & 0x3F); + memcpy(&te_ipreach->prefix_start, + &ipv4->prefix.s_addr, + (ipv4->prefixlen + 7) / 8); + inet_ntop(AF_INET, &ipv4->prefix.s_addr, + buf, sizeof(buf)); + lsp_debug( + "ISIS (%s): Adding te-style IP reachability for %s/%d", + area->area_tag, buf, + ipv4->prefixlen); + listnode_add(tlv_data.te_ipv4_reachs, + te_ipreach); + } + } } - if (area->newmetric) - { - if (tlv_data.te_is_neighs == NULL) - { - tlv_data.te_is_neighs = list_new (); - tlv_data.te_is_neighs->del = free_tlv; - } - te_is_neigh = XCALLOC (MTYPE_ISIS_TLV, - sizeof (struct te_is_neigh)); - if (level == IS_LEVEL_1) - memcpy (te_is_neigh->neigh_id, - circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1); - else - memcpy (te_is_neigh->neigh_id, - circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1); - if (area->oldmetric) - metric = circuit->metric[level - 1]; - else - metric = circuit->te_metric[level - 1]; - SET_TE_METRIC(te_is_neigh, metric); - if (!memcmp (te_is_neigh->neigh_id, zero_id, - ISIS_SYS_ID_LEN + 1)) - { - XFREE (MTYPE_ISIS_TLV, te_is_neigh); - lsp_debug("ISIS (%s): No DIS for circuit, not adding te-style IS neighbor.", - area->area_tag); - } - else - { - /* Check if MPLS_TE is activate */ - if (IS_MPLS_TE(isisMplsTE) && HAS_LINK_PARAMS(circuit->interface)) - /* Add SubTLVs & Adjust real size of SubTLVs */ - te_is_neigh->sub_tlvs_length = add_te_subtlvs(te_is_neigh->sub_tlvs, circuit->mtc); - else - /* Or keep only TE metric with no SubTLVs if MPLS_TE is off */ - te_is_neigh->sub_tlvs_length = 0; - - tlvs_add_mt_bcast(&tlv_data, circuit, level, te_is_neigh); - XFREE(MTYPE_ISIS_TLV, te_is_neigh); - } + + /* + * Add IPv6 reachability of this circuit + */ + if (circuit->ipv6_router && circuit->ipv6_non_link + && circuit->ipv6_non_link->count > 0) { + if (!ipv6_reachs) + ipv6_reachs = tlv_get_ipv6_reach_list( + area, &tlv_data); + + for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link, + ipnode, ipv6)) { + ip6reach = XCALLOC( + MTYPE_ISIS_TLV, + sizeof(struct ipv6_reachability)); + + if (area->oldmetric) + ip6reach->metric = htonl( + circuit->metric[level - 1]); + else + ip6reach->metric = htonl( + circuit->te_metric[level - 1]); + + ip6reach->control_info = 0; + ip6reach->prefix_len = ipv6->prefixlen; + memcpy(&ip6prefix, ipv6, sizeof(ip6prefix)); + apply_mask_ipv6(&ip6prefix); + + inet_ntop(AF_INET6, &ip6prefix.prefix.s6_addr, + buf, sizeof(buf)); + lsp_debug( + "ISIS (%s): Adding IPv6 reachability for %s/%d", + area->area_tag, buf, ipv6->prefixlen); + + memcpy(ip6reach->prefix, + ip6prefix.prefix.s6_addr, + sizeof(ip6reach->prefix)); + listnode_add(ipv6_reachs, ip6reach); + } } - } - else - { - lsp_debug("ISIS (%s): Circuit is not active for current level. Not adding IS neighbors", - area->area_tag); - } - break; - case CIRCUIT_T_P2P: - nei = circuit->u.p2p.neighbor; - if (nei && (level & nei->circuit_t)) - { - if (area->oldmetric) - { - if (tlv_data.is_neighs == NULL) - { - tlv_data.is_neighs = list_new (); - tlv_data.is_neighs->del = free_tlv; - } - is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh)); - memcpy (is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN); - is_neigh->metrics.metric_default = circuit->metric[level - 1]; - is_neigh->metrics.metric_expense = METRICS_UNSUPPORTED; - is_neigh->metrics.metric_error = METRICS_UNSUPPORTED; - is_neigh->metrics.metric_delay = METRICS_UNSUPPORTED; - listnode_add (tlv_data.is_neighs, is_neigh); - lsp_debug("ISIS (%s): Adding old-style is reach for %s", area->area_tag, - sysid_print(is_neigh->neigh_id)); + + switch (circuit->circ_type) { + case CIRCUIT_T_BROADCAST: + if (level & circuit->is_type) { + if (area->oldmetric) { + if (tlv_data.is_neighs == NULL) { + tlv_data.is_neighs = list_new(); + tlv_data.is_neighs->del = + free_tlv; + } + is_neigh = XCALLOC( + MTYPE_ISIS_TLV, + sizeof(struct is_neigh)); + if (level == IS_LEVEL_1) + memcpy(is_neigh->neigh_id, + circuit->u.bc + .l1_desig_is, + ISIS_SYS_ID_LEN + 1); + else + memcpy(is_neigh->neigh_id, + circuit->u.bc + .l2_desig_is, + ISIS_SYS_ID_LEN + 1); + is_neigh->metrics.metric_default = + circuit->metric[level - 1]; + is_neigh->metrics.metric_expense = + METRICS_UNSUPPORTED; + is_neigh->metrics.metric_error = + METRICS_UNSUPPORTED; + is_neigh->metrics.metric_delay = + METRICS_UNSUPPORTED; + if (!memcmp(is_neigh->neigh_id, zero_id, + ISIS_SYS_ID_LEN + 1)) { + XFREE(MTYPE_ISIS_TLV, is_neigh); + lsp_debug( + "ISIS (%s): No DIS for circuit, not adding old-style IS neighbor.", + area->area_tag); + } else { + listnode_add(tlv_data.is_neighs, + is_neigh); + lsp_debug( + "ISIS (%s): Adding DIS %s.%02x as old-style neighbor", + area->area_tag, + sysid_print( + is_neigh->neigh_id), + LSP_PSEUDO_ID( + is_neigh->neigh_id)); + } + } + if (area->newmetric) { + if (tlv_data.te_is_neighs == NULL) { + tlv_data.te_is_neighs = + list_new(); + tlv_data.te_is_neighs->del = + free_tlv; + } + te_is_neigh = XCALLOC( + MTYPE_ISIS_TLV, + sizeof(struct te_is_neigh)); + if (level == IS_LEVEL_1) + memcpy(te_is_neigh->neigh_id, + circuit->u.bc + .l1_desig_is, + ISIS_SYS_ID_LEN + 1); + else + memcpy(te_is_neigh->neigh_id, + circuit->u.bc + .l2_desig_is, + ISIS_SYS_ID_LEN + 1); + if (area->oldmetric) + metric = circuit->metric[level + - 1]; + else + metric = + circuit->te_metric[level + - 1]; + SET_TE_METRIC(te_is_neigh, metric); + if (!memcmp(te_is_neigh->neigh_id, + zero_id, + ISIS_SYS_ID_LEN + 1)) { + XFREE(MTYPE_ISIS_TLV, + te_is_neigh); + lsp_debug( + "ISIS (%s): No DIS for circuit, not adding te-style IS neighbor.", + area->area_tag); + } else { + /* Check if MPLS_TE is activate + */ + if (IS_MPLS_TE(isisMplsTE) + && HAS_LINK_PARAMS( + circuit->interface)) + /* Add SubTLVs & Adjust + * real size of SubTLVs + */ + te_is_neigh + ->sub_tlvs_length = add_te_subtlvs( + te_is_neigh + ->sub_tlvs, + circuit->mtc); + else + /* Or keep only TE + * metric with no + * SubTLVs if MPLS_TE is + * off */ + te_is_neigh + ->sub_tlvs_length = + 0; + + tlvs_add_mt_bcast( + &tlv_data, circuit, + level, te_is_neigh); + XFREE(MTYPE_ISIS_TLV, + te_is_neigh); + } + } + } else { + lsp_debug( + "ISIS (%s): Circuit is not active for current level. Not adding IS neighbors", + area->area_tag); + } + break; + case CIRCUIT_T_P2P: + nei = circuit->u.p2p.neighbor; + if (nei && (level & nei->circuit_t)) { + if (area->oldmetric) { + if (tlv_data.is_neighs == NULL) { + tlv_data.is_neighs = list_new(); + tlv_data.is_neighs->del = + free_tlv; + } + is_neigh = XCALLOC( + MTYPE_ISIS_TLV, + sizeof(struct is_neigh)); + memcpy(is_neigh->neigh_id, nei->sysid, + ISIS_SYS_ID_LEN); + is_neigh->metrics.metric_default = + circuit->metric[level - 1]; + is_neigh->metrics.metric_expense = + METRICS_UNSUPPORTED; + is_neigh->metrics.metric_error = + METRICS_UNSUPPORTED; + is_neigh->metrics.metric_delay = + METRICS_UNSUPPORTED; + listnode_add(tlv_data.is_neighs, + is_neigh); + lsp_debug( + "ISIS (%s): Adding old-style is reach for %s", + area->area_tag, + sysid_print( + is_neigh->neigh_id)); + } + if (area->newmetric) { + uint32_t metric; + + if (tlv_data.te_is_neighs == NULL) { + tlv_data.te_is_neighs = + list_new(); + tlv_data.te_is_neighs->del = + free_tlv; + } + te_is_neigh = XCALLOC( + MTYPE_ISIS_TLV, + sizeof(struct te_is_neigh)); + memcpy(te_is_neigh->neigh_id, + nei->sysid, ISIS_SYS_ID_LEN); + metric = circuit->te_metric[level - 1]; + SET_TE_METRIC(te_is_neigh, metric); + /* Check if MPLS_TE is activate */ + if (IS_MPLS_TE(isisMplsTE) + && HAS_LINK_PARAMS( + circuit->interface)) + /* Update Local and Remote IP + * address for MPLS TE circuit + * parameters */ + /* NOTE sure that it is the + * pertinent place for that + * updates */ + /* Local IP address could be + * updated in isis_circuit.c - + * isis_circuit_add_addr() */ + /* But, where update remote IP + * address ? in isis_pdu.c - + * process_p2p_hello() ? */ + + /* Add SubTLVs & Adjust real + * size of SubTLVs */ + te_is_neigh->sub_tlvs_length = + add_te_subtlvs( + te_is_neigh + ->sub_tlvs, + circuit->mtc); + else + /* Or keep only TE metric with + * no SubTLVs if MPLS_TE is off + */ + te_is_neigh->sub_tlvs_length = + 0; + + tlvs_add_mt_p2p(&tlv_data, circuit, + te_is_neigh); + XFREE(MTYPE_ISIS_TLV, te_is_neigh); + } + } else { + lsp_debug( + "ISIS (%s): No adjacency for given level on this circuit. Not adding IS neighbors", + area->area_tag); + } + break; + case CIRCUIT_T_LOOPBACK: + break; + default: + zlog_warn("lsp_area_create: unknown circuit type"); } - if (area->newmetric) - { - uint32_t metric; - - if (tlv_data.te_is_neighs == NULL) - { - tlv_data.te_is_neighs = list_new (); - tlv_data.te_is_neighs->del = free_tlv; - } - te_is_neigh = XCALLOC (MTYPE_ISIS_TLV, - sizeof (struct te_is_neigh)); - memcpy (te_is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN); - metric = circuit->te_metric[level - 1]; - SET_TE_METRIC(te_is_neigh, metric); - /* Check if MPLS_TE is activate */ - if (IS_MPLS_TE(isisMplsTE) && HAS_LINK_PARAMS(circuit->interface)) - /* Update Local and Remote IP address for MPLS TE circuit parameters */ - /* NOTE sure that it is the pertinent place for that updates */ - /* Local IP address could be updated in isis_circuit.c - isis_circuit_add_addr() */ - /* But, where update remote IP address ? in isis_pdu.c - process_p2p_hello() ? */ - - /* Add SubTLVs & Adjust real size of SubTLVs */ - te_is_neigh->sub_tlvs_length = add_te_subtlvs(te_is_neigh->sub_tlvs, circuit->mtc); - else - /* Or keep only TE metric with no SubTLVs if MPLS_TE is off */ - te_is_neigh->sub_tlvs_length = 0; - - tlvs_add_mt_p2p(&tlv_data, circuit, te_is_neigh); - XFREE(MTYPE_ISIS_TLV, te_is_neigh); + } + + lsp_build_ext_reach(lsp, area, &tlv_data); + + lsp_debug("ISIS (%s): LSP construction is complete. Serializing...", + area->area_tag); + + while (tlv_data.ipv4_int_reachs + && listcount(tlv_data.ipv4_int_reachs)) { + if (lsp->tlv_data.ipv4_int_reachs == NULL) + lsp->tlv_data.ipv4_int_reachs = list_new(); + lsp_tlv_fit(lsp, &tlv_data.ipv4_int_reachs, + &lsp->tlv_data.ipv4_int_reachs, IPV4_REACH_LEN, + area->lsp_frag_threshold, tlv_add_ipv4_int_reachs); + if (tlv_data.ipv4_int_reachs + && listcount(tlv_data.ipv4_int_reachs)) + lsp = lsp_next_frag( + LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0, + area, level); + } + + while (tlv_data.ipv4_ext_reachs + && listcount(tlv_data.ipv4_ext_reachs)) { + if (lsp->tlv_data.ipv4_ext_reachs == NULL) + lsp->tlv_data.ipv4_ext_reachs = list_new(); + lsp_tlv_fit(lsp, &tlv_data.ipv4_ext_reachs, + &lsp->tlv_data.ipv4_ext_reachs, IPV4_REACH_LEN, + area->lsp_frag_threshold, tlv_add_ipv4_ext_reachs); + if (tlv_data.ipv4_ext_reachs + && listcount(tlv_data.ipv4_ext_reachs)) + lsp = lsp_next_frag( + LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0, + area, level); + } + + while (tlv_data.te_ipv4_reachs && listcount(tlv_data.te_ipv4_reachs)) { + if (lsp->tlv_data.te_ipv4_reachs == NULL) + lsp->tlv_data.te_ipv4_reachs = list_new(); + _lsp_tlv_fit(lsp, &tlv_data.te_ipv4_reachs, + &lsp->tlv_data.te_ipv4_reachs, + area->lsp_frag_threshold, tlv_add_te_ipv4_reachs, + NULL); + if (tlv_data.te_ipv4_reachs + && listcount(tlv_data.te_ipv4_reachs)) + lsp = lsp_next_frag( + LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0, + area, level); + } + + struct tlv_mt_ipv4_reachs *mt_ipv4_reachs; + for (ALL_LIST_ELEMENTS_RO(tlv_data.mt_ipv4_reachs, node, + mt_ipv4_reachs)) { + while (mt_ipv4_reachs->list + && listcount(mt_ipv4_reachs->list)) { + struct tlv_mt_ipv4_reachs *frag_mt_ipv4_reachs; + + frag_mt_ipv4_reachs = tlvs_get_mt_ipv4_reachs( + &lsp->tlv_data, mt_ipv4_reachs->mtid); + _lsp_tlv_fit(lsp, &mt_ipv4_reachs->list, + &frag_mt_ipv4_reachs->list, + area->lsp_frag_threshold, + tlv_add_te_ipv4_reachs, + &mt_ipv4_reachs->mtid); + if (mt_ipv4_reachs->list + && listcount(mt_ipv4_reachs->list)) + lsp = lsp_next_frag( + LSP_FRAGMENT(lsp->lsp_header->lsp_id) + + 1, + lsp0, area, level); } - } - else - { - lsp_debug("ISIS (%s): No adjacency for given level on this circuit. Not adding IS neighbors", - area->area_tag); - } - break; - case CIRCUIT_T_LOOPBACK: - break; - default: - zlog_warn ("lsp_area_create: unknown circuit type"); - } - } - - lsp_build_ext_reach(lsp, area, &tlv_data); - - lsp_debug("ISIS (%s): LSP construction is complete. Serializing...", area->area_tag); - - while (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs)) - { - if (lsp->tlv_data.ipv4_int_reachs == NULL) - lsp->tlv_data.ipv4_int_reachs = list_new (); - lsp_tlv_fit (lsp, &tlv_data.ipv4_int_reachs, - &lsp->tlv_data.ipv4_int_reachs, - IPV4_REACH_LEN, area->lsp_frag_threshold, - tlv_add_ipv4_int_reachs); - if (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs)) - lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1, - lsp0, area, level); - } - - while (tlv_data.ipv4_ext_reachs && listcount (tlv_data.ipv4_ext_reachs)) - { - if (lsp->tlv_data.ipv4_ext_reachs == NULL) - lsp->tlv_data.ipv4_ext_reachs = list_new (); - lsp_tlv_fit (lsp, &tlv_data.ipv4_ext_reachs, - &lsp->tlv_data.ipv4_ext_reachs, - IPV4_REACH_LEN, area->lsp_frag_threshold, - tlv_add_ipv4_ext_reachs); - if (tlv_data.ipv4_ext_reachs && listcount (tlv_data.ipv4_ext_reachs)) - lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1, - lsp0, area, level); - } - - while (tlv_data.te_ipv4_reachs && listcount (tlv_data.te_ipv4_reachs)) - { - if (lsp->tlv_data.te_ipv4_reachs == NULL) - lsp->tlv_data.te_ipv4_reachs = list_new (); - _lsp_tlv_fit (lsp, &tlv_data.te_ipv4_reachs, &lsp->tlv_data.te_ipv4_reachs, - area->lsp_frag_threshold, tlv_add_te_ipv4_reachs, NULL); - if (tlv_data.te_ipv4_reachs && listcount (tlv_data.te_ipv4_reachs)) - lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1, - lsp0, area, level); - } - - struct tlv_mt_ipv4_reachs *mt_ipv4_reachs; - for (ALL_LIST_ELEMENTS_RO(tlv_data.mt_ipv4_reachs, node, mt_ipv4_reachs)) - { - while (mt_ipv4_reachs->list && listcount(mt_ipv4_reachs->list)) - { - struct tlv_mt_ipv4_reachs *frag_mt_ipv4_reachs; - - frag_mt_ipv4_reachs = tlvs_get_mt_ipv4_reachs(&lsp->tlv_data, mt_ipv4_reachs->mtid); - _lsp_tlv_fit (lsp, &mt_ipv4_reachs->list, &frag_mt_ipv4_reachs->list, - area->lsp_frag_threshold, tlv_add_te_ipv4_reachs, - &mt_ipv4_reachs->mtid); - if (mt_ipv4_reachs->list && listcount(mt_ipv4_reachs->list)) - lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1, - lsp0, area, level); - } - } - - while (tlv_data.ipv6_reachs && listcount (tlv_data.ipv6_reachs)) - { - if (lsp->tlv_data.ipv6_reachs == NULL) - lsp->tlv_data.ipv6_reachs = list_new (); - _lsp_tlv_fit (lsp, &tlv_data.ipv6_reachs, &lsp->tlv_data.ipv6_reachs, - area->lsp_frag_threshold, tlv_add_ipv6_reachs, NULL); - if (tlv_data.ipv6_reachs && listcount (tlv_data.ipv6_reachs)) - lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1, - lsp0, area, level); - } - - struct tlv_mt_ipv6_reachs *mt_ipv6_reachs; - for (ALL_LIST_ELEMENTS_RO(tlv_data.mt_ipv6_reachs, node, mt_ipv6_reachs)) - { - while (mt_ipv6_reachs->list && listcount(mt_ipv6_reachs->list)) - { - struct tlv_mt_ipv6_reachs *frag_mt_ipv6_reachs; - - frag_mt_ipv6_reachs = tlvs_get_mt_ipv6_reachs(&lsp->tlv_data, mt_ipv6_reachs->mtid); - _lsp_tlv_fit (lsp, &mt_ipv6_reachs->list, &frag_mt_ipv6_reachs->list, - area->lsp_frag_threshold, tlv_add_ipv6_reachs, - &mt_ipv6_reachs->mtid); - if (mt_ipv6_reachs->list && listcount(mt_ipv6_reachs->list)) - lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1, - lsp0, area, level); - } - } - - while (tlv_data.is_neighs && listcount (tlv_data.is_neighs)) - { - if (lsp->tlv_data.is_neighs == NULL) - lsp->tlv_data.is_neighs = list_new (); - lsp_tlv_fit (lsp, &tlv_data.is_neighs, - &lsp->tlv_data.is_neighs, - IS_NEIGHBOURS_LEN, area->lsp_frag_threshold, - tlv_add_is_neighs); - if (tlv_data.is_neighs && listcount (tlv_data.is_neighs)) - lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1, - lsp0, area, level); - } - - while (tlv_data.te_is_neighs && listcount (tlv_data.te_is_neighs)) - { - if (lsp->tlv_data.te_is_neighs == NULL) - lsp->tlv_data.te_is_neighs = list_new (); - _lsp_tlv_fit (lsp, &tlv_data.te_is_neighs, &lsp->tlv_data.te_is_neighs, - area->lsp_frag_threshold, tlv_add_te_is_neighs, NULL); - if (tlv_data.te_is_neighs && listcount (tlv_data.te_is_neighs)) - lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1, - lsp0, area, level); - } - - struct tlv_mt_neighbors *mt_neighs; - for (ALL_LIST_ELEMENTS_RO(tlv_data.mt_is_neighs, node, mt_neighs)) - { - while (mt_neighs->list && listcount(mt_neighs->list)) - { - struct tlv_mt_neighbors *frag_mt_neighs; - - frag_mt_neighs = tlvs_get_mt_neighbors(&lsp->tlv_data, mt_neighs->mtid); - _lsp_tlv_fit (lsp, &mt_neighs->list, &frag_mt_neighs->list, - area->lsp_frag_threshold, tlv_add_te_is_neighs, - &mt_neighs->mtid); - if (mt_neighs->list && listcount(mt_neighs->list)) - lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1, - lsp0, area, level); - } - } - - - lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu)); - - free_tlvs (&tlv_data); - - /* Validate the LSP */ - retval = parse_tlvs (area->area_tag, STREAM_DATA (lsp->pdu) + - ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN, - stream_get_endp (lsp->pdu) - - ISIS_FIXED_HDR_LEN - ISIS_LSP_HDR_LEN, - &expected, &found, &tlv_data, NULL); - assert (retval == ISIS_OK); - - return; + } + + while (tlv_data.ipv6_reachs && listcount(tlv_data.ipv6_reachs)) { + if (lsp->tlv_data.ipv6_reachs == NULL) + lsp->tlv_data.ipv6_reachs = list_new(); + _lsp_tlv_fit( + lsp, &tlv_data.ipv6_reachs, &lsp->tlv_data.ipv6_reachs, + area->lsp_frag_threshold, tlv_add_ipv6_reachs, NULL); + if (tlv_data.ipv6_reachs && listcount(tlv_data.ipv6_reachs)) + lsp = lsp_next_frag( + LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0, + area, level); + } + + struct tlv_mt_ipv6_reachs *mt_ipv6_reachs; + for (ALL_LIST_ELEMENTS_RO(tlv_data.mt_ipv6_reachs, node, + mt_ipv6_reachs)) { + while (mt_ipv6_reachs->list + && listcount(mt_ipv6_reachs->list)) { + struct tlv_mt_ipv6_reachs *frag_mt_ipv6_reachs; + + frag_mt_ipv6_reachs = tlvs_get_mt_ipv6_reachs( + &lsp->tlv_data, mt_ipv6_reachs->mtid); + _lsp_tlv_fit(lsp, &mt_ipv6_reachs->list, + &frag_mt_ipv6_reachs->list, + area->lsp_frag_threshold, + tlv_add_ipv6_reachs, + &mt_ipv6_reachs->mtid); + if (mt_ipv6_reachs->list + && listcount(mt_ipv6_reachs->list)) + lsp = lsp_next_frag( + LSP_FRAGMENT(lsp->lsp_header->lsp_id) + + 1, + lsp0, area, level); + } + } + + while (tlv_data.is_neighs && listcount(tlv_data.is_neighs)) { + if (lsp->tlv_data.is_neighs == NULL) + lsp->tlv_data.is_neighs = list_new(); + lsp_tlv_fit(lsp, &tlv_data.is_neighs, &lsp->tlv_data.is_neighs, + IS_NEIGHBOURS_LEN, area->lsp_frag_threshold, + tlv_add_is_neighs); + if (tlv_data.is_neighs && listcount(tlv_data.is_neighs)) + lsp = lsp_next_frag( + LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0, + area, level); + } + + while (tlv_data.te_is_neighs && listcount(tlv_data.te_is_neighs)) { + if (lsp->tlv_data.te_is_neighs == NULL) + lsp->tlv_data.te_is_neighs = list_new(); + _lsp_tlv_fit(lsp, &tlv_data.te_is_neighs, + &lsp->tlv_data.te_is_neighs, + area->lsp_frag_threshold, tlv_add_te_is_neighs, + NULL); + if (tlv_data.te_is_neighs && listcount(tlv_data.te_is_neighs)) + lsp = lsp_next_frag( + LSP_FRAGMENT(lsp->lsp_header->lsp_id) + 1, lsp0, + area, level); + } + + struct tlv_mt_neighbors *mt_neighs; + for (ALL_LIST_ELEMENTS_RO(tlv_data.mt_is_neighs, node, mt_neighs)) { + while (mt_neighs->list && listcount(mt_neighs->list)) { + struct tlv_mt_neighbors *frag_mt_neighs; + + frag_mt_neighs = tlvs_get_mt_neighbors(&lsp->tlv_data, + mt_neighs->mtid); + _lsp_tlv_fit(lsp, &mt_neighs->list, + &frag_mt_neighs->list, + area->lsp_frag_threshold, + tlv_add_te_is_neighs, &mt_neighs->mtid); + if (mt_neighs->list && listcount(mt_neighs->list)) + lsp = lsp_next_frag( + LSP_FRAGMENT(lsp->lsp_header->lsp_id) + + 1, + lsp0, area, level); + } + } + + + lsp->lsp_header->pdu_len = htons(stream_get_endp(lsp->pdu)); + + free_tlvs(&tlv_data); + + /* Validate the LSP */ + retval = parse_tlvs(area->area_tag, + STREAM_DATA(lsp->pdu) + ISIS_FIXED_HDR_LEN + + ISIS_LSP_HDR_LEN, + stream_get_endp(lsp->pdu) - ISIS_FIXED_HDR_LEN + - ISIS_LSP_HDR_LEN, + &expected, &found, &tlv_data, NULL); + assert(retval == ISIS_OK); + + return; } /* * 7.3.7 and 7.3.9 Generation on non-pseudonode LSPs */ -int -lsp_generate (struct isis_area *area, int level) +int lsp_generate(struct isis_area *area, int level) { - struct isis_lsp *oldlsp, *newlsp; - u_int32_t seq_num = 0; - u_char lspid[ISIS_SYS_ID_LEN + 2]; - u_int16_t rem_lifetime, refresh_time; - - if ((area == NULL) || (area->is_type & level) != level) - return ISIS_ERROR; - - memset (&lspid, 0, ISIS_SYS_ID_LEN + 2); - memcpy (&lspid, isis->sysid, ISIS_SYS_ID_LEN); - - /* only builds the lsp if the area shares the level */ - oldlsp = lsp_search (lspid, area->lspdb[level - 1]); - if (oldlsp) - { - /* FIXME: we should actually initiate a purge */ - seq_num = ntohl (oldlsp->lsp_header->seq_num); - lsp_search_and_destroy (oldlsp->lsp_header->lsp_id, - area->lspdb[level - 1]); - } - rem_lifetime = lsp_rem_lifetime (area, level); - newlsp = lsp_new (area, lspid, rem_lifetime, seq_num, - area->is_type | area->overload_bit | area->attached_bit, - 0, level); - newlsp->area = area; - newlsp->own_lsp = 1; - - lsp_insert (newlsp, area->lspdb[level - 1]); - /* build_lsp_data (newlsp, area); */ - lsp_build (newlsp, area); - /* time to calculate our checksum */ - lsp_seqnum_update (newlsp); - newlsp->last_generated = time(NULL); - lsp_set_all_srmflags (newlsp); - - refresh_time = lsp_refresh_time (newlsp, rem_lifetime); - - THREAD_TIMER_OFF (area->t_lsp_refresh[level - 1]); - area->lsp_regenerate_pending[level - 1] = 0; - if (level == IS_LEVEL_1) - thread_add_timer(master, lsp_l1_refresh, area, refresh_time, - &area->t_lsp_refresh[level - 1]); - else if (level == IS_LEVEL_2) - thread_add_timer(master, lsp_l2_refresh, area, refresh_time, - &area->t_lsp_refresh[level - 1]); - - if (isis->debugs & DEBUG_UPDATE_PACKETS) - { - zlog_debug ("ISIS-Upd (%s): Building L%d LSP %s, len %d, " - "seq 0x%08x, cksum 0x%04x, lifetime %us refresh %us", - area->area_tag, level, - rawlspid_print (newlsp->lsp_header->lsp_id), - ntohl (newlsp->lsp_header->pdu_len), - ntohl (newlsp->lsp_header->seq_num), - ntohs (newlsp->lsp_header->checksum), - ntohs (newlsp->lsp_header->rem_lifetime), - refresh_time); - } - sched_debug("ISIS (%s): Built L%d LSP. Set triggered regenerate to non-pending.", - area->area_tag, level); - - return ISIS_OK; + struct isis_lsp *oldlsp, *newlsp; + u_int32_t seq_num = 0; + u_char lspid[ISIS_SYS_ID_LEN + 2]; + u_int16_t rem_lifetime, refresh_time; + + if ((area == NULL) || (area->is_type & level) != level) + return ISIS_ERROR; + + memset(&lspid, 0, ISIS_SYS_ID_LEN + 2); + memcpy(&lspid, isis->sysid, ISIS_SYS_ID_LEN); + + /* only builds the lsp if the area shares the level */ + oldlsp = lsp_search(lspid, area->lspdb[level - 1]); + if (oldlsp) { + /* FIXME: we should actually initiate a purge */ + seq_num = ntohl(oldlsp->lsp_header->seq_num); + lsp_search_and_destroy(oldlsp->lsp_header->lsp_id, + area->lspdb[level - 1]); + } + rem_lifetime = lsp_rem_lifetime(area, level); + newlsp = + lsp_new(area, lspid, rem_lifetime, seq_num, + area->is_type | area->overload_bit | area->attached_bit, + 0, level); + newlsp->area = area; + newlsp->own_lsp = 1; + + lsp_insert(newlsp, area->lspdb[level - 1]); + /* build_lsp_data (newlsp, area); */ + lsp_build(newlsp, area); + /* time to calculate our checksum */ + lsp_seqnum_update(newlsp); + newlsp->last_generated = time(NULL); + lsp_set_all_srmflags(newlsp); + + refresh_time = lsp_refresh_time(newlsp, rem_lifetime); + + THREAD_TIMER_OFF(area->t_lsp_refresh[level - 1]); + area->lsp_regenerate_pending[level - 1] = 0; + if (level == IS_LEVEL_1) + thread_add_timer(master, lsp_l1_refresh, area, refresh_time, + &area->t_lsp_refresh[level - 1]); + else if (level == IS_LEVEL_2) + thread_add_timer(master, lsp_l2_refresh, area, refresh_time, + &area->t_lsp_refresh[level - 1]); + + if (isis->debugs & DEBUG_UPDATE_PACKETS) { + zlog_debug( + "ISIS-Upd (%s): Building L%d LSP %s, len %d, " + "seq 0x%08x, cksum 0x%04x, lifetime %us refresh %us", + area->area_tag, level, + rawlspid_print(newlsp->lsp_header->lsp_id), + ntohl(newlsp->lsp_header->pdu_len), + ntohl(newlsp->lsp_header->seq_num), + ntohs(newlsp->lsp_header->checksum), + ntohs(newlsp->lsp_header->rem_lifetime), refresh_time); + } + sched_debug( + "ISIS (%s): Built L%d LSP. Set triggered regenerate to non-pending.", + area->area_tag, level); + + return ISIS_OK; } /* * Search own LSPs, update holding time and set SRM */ -static int -lsp_regenerate (struct isis_area *area, int level) +static int lsp_regenerate(struct isis_area *area, int level) { - dict_t *lspdb; - struct isis_lsp *lsp, *frag; - struct listnode *node; - u_char lspid[ISIS_SYS_ID_LEN + 2]; - u_int16_t rem_lifetime, refresh_time; - - if ((area == NULL) || (area->is_type & level) != level) - return ISIS_ERROR; - - lspdb = area->lspdb[level - 1]; - - memset (lspid, 0, ISIS_SYS_ID_LEN + 2); - memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN); - - lsp = lsp_search (lspid, lspdb); - - if (!lsp) - { - zlog_err ("ISIS-Upd (%s): lsp_regenerate: no L%d LSP found!", - area->area_tag, level); - return ISIS_ERROR; - } - - lsp_clear_data (lsp); - lsp_build (lsp, area); - lsp->lsp_header->lsp_bits = lsp_bits_generate (level, area->overload_bit, - area->attached_bit); - rem_lifetime = lsp_rem_lifetime (area, level); - lsp->lsp_header->rem_lifetime = htons (rem_lifetime); - lsp_seqnum_update (lsp); - - lsp->last_generated = time (NULL); - lsp_set_all_srmflags (lsp); - for (ALL_LIST_ELEMENTS_RO (lsp->lspu.frags, node, frag)) - { - frag->lsp_header->lsp_bits = lsp_bits_generate (level, - area->overload_bit, - area->attached_bit); - /* Set the lifetime values of all the fragments to the same value, - * so that no fragment expires before the lsp is refreshed. - */ - frag->lsp_header->rem_lifetime = htons (rem_lifetime); - lsp_set_all_srmflags (frag); - } - - refresh_time = lsp_refresh_time (lsp, rem_lifetime); - if (level == IS_LEVEL_1) - thread_add_timer(master, lsp_l1_refresh, area, refresh_time, - &area->t_lsp_refresh[level - 1]); - else if (level == IS_LEVEL_2) - thread_add_timer(master, lsp_l2_refresh, area, refresh_time, - &area->t_lsp_refresh[level - 1]); - area->lsp_regenerate_pending[level - 1] = 0; - - if (isis->debugs & DEBUG_UPDATE_PACKETS) - { - zlog_debug ("ISIS-Upd (%s): Refreshing our L%d LSP %s, len %d, " - "seq 0x%08x, cksum 0x%04x, lifetime %us refresh %us", - area->area_tag, level, - rawlspid_print (lsp->lsp_header->lsp_id), - ntohl (lsp->lsp_header->pdu_len), - ntohl (lsp->lsp_header->seq_num), - ntohs (lsp->lsp_header->checksum), - ntohs (lsp->lsp_header->rem_lifetime), - refresh_time); - } - sched_debug("ISIS (%s): Rebuilt L%d LSP. Set triggered regenerate to non-pending.", - area->area_tag, level); - - return ISIS_OK; + dict_t *lspdb; + struct isis_lsp *lsp, *frag; + struct listnode *node; + u_char lspid[ISIS_SYS_ID_LEN + 2]; + u_int16_t rem_lifetime, refresh_time; + + if ((area == NULL) || (area->is_type & level) != level) + return ISIS_ERROR; + + lspdb = area->lspdb[level - 1]; + + memset(lspid, 0, ISIS_SYS_ID_LEN + 2); + memcpy(lspid, isis->sysid, ISIS_SYS_ID_LEN); + + lsp = lsp_search(lspid, lspdb); + + if (!lsp) { + zlog_err("ISIS-Upd (%s): lsp_regenerate: no L%d LSP found!", + area->area_tag, level); + return ISIS_ERROR; + } + + lsp_clear_data(lsp); + lsp_build(lsp, area); + lsp->lsp_header->lsp_bits = lsp_bits_generate(level, area->overload_bit, + area->attached_bit); + rem_lifetime = lsp_rem_lifetime(area, level); + lsp->lsp_header->rem_lifetime = htons(rem_lifetime); + lsp_seqnum_update(lsp); + + lsp->last_generated = time(NULL); + lsp_set_all_srmflags(lsp); + for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) { + frag->lsp_header->lsp_bits = lsp_bits_generate( + level, area->overload_bit, area->attached_bit); + /* Set the lifetime values of all the fragments to the same + * value, + * so that no fragment expires before the lsp is refreshed. + */ + frag->lsp_header->rem_lifetime = htons(rem_lifetime); + lsp_set_all_srmflags(frag); + } + + refresh_time = lsp_refresh_time(lsp, rem_lifetime); + if (level == IS_LEVEL_1) + thread_add_timer(master, lsp_l1_refresh, area, refresh_time, + &area->t_lsp_refresh[level - 1]); + else if (level == IS_LEVEL_2) + thread_add_timer(master, lsp_l2_refresh, area, refresh_time, + &area->t_lsp_refresh[level - 1]); + area->lsp_regenerate_pending[level - 1] = 0; + + if (isis->debugs & DEBUG_UPDATE_PACKETS) { + zlog_debug( + "ISIS-Upd (%s): Refreshing our L%d LSP %s, len %d, " + "seq 0x%08x, cksum 0x%04x, lifetime %us refresh %us", + area->area_tag, level, + rawlspid_print(lsp->lsp_header->lsp_id), + ntohl(lsp->lsp_header->pdu_len), + ntohl(lsp->lsp_header->seq_num), + ntohs(lsp->lsp_header->checksum), + ntohs(lsp->lsp_header->rem_lifetime), refresh_time); + } + sched_debug( + "ISIS (%s): Rebuilt L%d LSP. Set triggered regenerate to non-pending.", + area->area_tag, level); + + return ISIS_OK; } /* * Something has changed or periodic refresh -> regenerate LSP */ -static int -lsp_l1_refresh (struct thread *thread) +static int lsp_l1_refresh(struct thread *thread) { - struct isis_area *area; + struct isis_area *area; - area = THREAD_ARG (thread); - assert (area); + area = THREAD_ARG(thread); + assert(area); - area->t_lsp_refresh[0] = NULL; - area->lsp_regenerate_pending[0] = 0; + area->t_lsp_refresh[0] = NULL; + area->lsp_regenerate_pending[0] = 0; - if ((area->is_type & IS_LEVEL_1) == 0) - return ISIS_ERROR; + if ((area->is_type & IS_LEVEL_1) == 0) + return ISIS_ERROR; - sched_debug("ISIS (%s): LSP L1 refresh timer expired. Refreshing LSP...", area->area_tag); - return lsp_regenerate (area, IS_LEVEL_1); + sched_debug( + "ISIS (%s): LSP L1 refresh timer expired. Refreshing LSP...", + area->area_tag); + return lsp_regenerate(area, IS_LEVEL_1); } -static int -lsp_l2_refresh (struct thread *thread) +static int lsp_l2_refresh(struct thread *thread) { - struct isis_area *area; + struct isis_area *area; - area = THREAD_ARG (thread); - assert (area); + area = THREAD_ARG(thread); + assert(area); - area->t_lsp_refresh[1] = NULL; - area->lsp_regenerate_pending[1] = 0; + area->t_lsp_refresh[1] = NULL; + area->lsp_regenerate_pending[1] = 0; - if ((area->is_type & IS_LEVEL_2) == 0) - return ISIS_ERROR; + if ((area->is_type & IS_LEVEL_2) == 0) + return ISIS_ERROR; - sched_debug("ISIS (%s): LSP L2 refresh timer expired. Refreshing LSP...", area->area_tag); - return lsp_regenerate (area, IS_LEVEL_2); + sched_debug( + "ISIS (%s): LSP L2 refresh timer expired. Refreshing LSP...", + area->area_tag); + return lsp_regenerate(area, IS_LEVEL_2); } -int -lsp_regenerate_schedule (struct isis_area *area, int level, int all_pseudo) +int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo) { - struct isis_lsp *lsp; - u_char id[ISIS_SYS_ID_LEN + 2]; - time_t now, diff; - long timeout; - struct listnode *cnode; - struct isis_circuit *circuit; - int lvl; - - if (area == NULL) - return ISIS_ERROR; - - sched_debug("ISIS (%s): Scheduling regeneration of %s LSPs, %sincluding PSNs", - area->area_tag, circuit_t2string(level), all_pseudo ? "" : "not "); - - memcpy (id, isis->sysid, ISIS_SYS_ID_LEN); - LSP_PSEUDO_ID (id) = LSP_FRAGMENT (id) = 0; - now = time (NULL); - - for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++) - { - if (!((level & lvl) && (area->is_type & lvl))) - continue; - - sched_debug("ISIS (%s): Checking whether L%d needs to be scheduled", - area->area_tag, lvl); - - if (area->lsp_regenerate_pending[lvl - 1]) - { - struct timeval remain = thread_timer_remain(area->t_lsp_refresh[lvl - 1]); - sched_debug("ISIS (%s): Regeneration is already pending, nothing todo." - " (Due in %lld.%03lld seconds)", area->area_tag, - (long long)remain.tv_sec, (long long)remain.tv_usec / 1000); - continue; - } - - lsp = lsp_search (id, area->lspdb[lvl - 1]); - if (!lsp) - { - sched_debug("ISIS (%s): We do not have any LSPs to regenerate, nothing todo.", - area->area_tag); - continue; - } - - /* - * Throttle avoidance - */ - sched_debug("ISIS (%s): Will schedule regen timer. Last run was: %lld, Now is: %lld", - area->area_tag, (long long)lsp->last_generated, (long long)now); - THREAD_TIMER_OFF (area->t_lsp_refresh[lvl - 1]); - diff = now - lsp->last_generated; - if (diff < area->lsp_gen_interval[lvl - 1]) - { - timeout = 1000 * (area->lsp_gen_interval[lvl - 1] - diff); - sched_debug("ISIS (%s): Scheduling in %ld ms to match configured lsp_gen_interval", - area->area_tag, timeout); - } - else - { - /* - * lsps are not regenerated if lsp_regenerate function is called - * directly. However if the lsp_regenerate call is queued for - * later execution it works. - */ - timeout = 100; - sched_debug("ISIS (%s): Last generation was more than lsp_gen_interval ago." - " Scheduling for execution in %ld ms.", area->area_tag, timeout); - } - - area->lsp_regenerate_pending[lvl - 1] = 1; - if (lvl == IS_LEVEL_1) - { - thread_add_timer_msec(master, lsp_l1_refresh, area, timeout, - &area->t_lsp_refresh[lvl - 1]); - } - else if (lvl == IS_LEVEL_2) - { - thread_add_timer_msec(master, lsp_l2_refresh, area, timeout, - &area->t_lsp_refresh[lvl - 1]); - } - } - - if (all_pseudo) - { - for (ALL_LIST_ELEMENTS_RO (area->circuit_list, cnode, circuit)) - lsp_regenerate_schedule_pseudo (circuit, level); - } - - return ISIS_OK; + struct isis_lsp *lsp; + u_char id[ISIS_SYS_ID_LEN + 2]; + time_t now, diff; + long timeout; + struct listnode *cnode; + struct isis_circuit *circuit; + int lvl; + + if (area == NULL) + return ISIS_ERROR; + + sched_debug( + "ISIS (%s): Scheduling regeneration of %s LSPs, %sincluding PSNs", + area->area_tag, circuit_t2string(level), + all_pseudo ? "" : "not "); + + memcpy(id, isis->sysid, ISIS_SYS_ID_LEN); + LSP_PSEUDO_ID(id) = LSP_FRAGMENT(id) = 0; + now = time(NULL); + + for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++) { + if (!((level & lvl) && (area->is_type & lvl))) + continue; + + sched_debug( + "ISIS (%s): Checking whether L%d needs to be scheduled", + area->area_tag, lvl); + + if (area->lsp_regenerate_pending[lvl - 1]) { + struct timeval remain = thread_timer_remain( + area->t_lsp_refresh[lvl - 1]); + sched_debug( + "ISIS (%s): Regeneration is already pending, nothing todo." + " (Due in %lld.%03lld seconds)", + area->area_tag, (long long)remain.tv_sec, + (long long)remain.tv_usec / 1000); + continue; + } + + lsp = lsp_search(id, area->lspdb[lvl - 1]); + if (!lsp) { + sched_debug( + "ISIS (%s): We do not have any LSPs to regenerate, nothing todo.", + area->area_tag); + continue; + } + + /* + * Throttle avoidance + */ + sched_debug( + "ISIS (%s): Will schedule regen timer. Last run was: %lld, Now is: %lld", + area->area_tag, (long long)lsp->last_generated, + (long long)now); + THREAD_TIMER_OFF(area->t_lsp_refresh[lvl - 1]); + diff = now - lsp->last_generated; + if (diff < area->lsp_gen_interval[lvl - 1]) { + timeout = + 1000 * (area->lsp_gen_interval[lvl - 1] - diff); + sched_debug( + "ISIS (%s): Scheduling in %ld ms to match configured lsp_gen_interval", + area->area_tag, timeout); + } else { + /* + * lsps are not regenerated if lsp_regenerate function + * is called + * directly. However if the lsp_regenerate call is + * queued for + * later execution it works. + */ + timeout = 100; + sched_debug( + "ISIS (%s): Last generation was more than lsp_gen_interval ago." + " Scheduling for execution in %ld ms.", + area->area_tag, timeout); + } + + area->lsp_regenerate_pending[lvl - 1] = 1; + if (lvl == IS_LEVEL_1) { + thread_add_timer_msec(master, lsp_l1_refresh, area, + timeout, + &area->t_lsp_refresh[lvl - 1]); + } else if (lvl == IS_LEVEL_2) { + thread_add_timer_msec(master, lsp_l2_refresh, area, + timeout, + &area->t_lsp_refresh[lvl - 1]); + } + } + + if (all_pseudo) { + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit)) + lsp_regenerate_schedule_pseudo(circuit, level); + } + + return ISIS_OK; } /* @@ -2271,430 +2345,443 @@ lsp_regenerate_schedule (struct isis_area *area, int level, int all_pseudo) */ /* - * 7.3.8 and 7.3.10 Generation of level 1 and 2 pseudonode LSPs + * 7.3.8 and 7.3.10 Generation of level 1 and 2 pseudonode LSPs */ -static void -lsp_build_pseudo (struct isis_lsp *lsp, struct isis_circuit *circuit, - int level) +static void lsp_build_pseudo(struct isis_lsp *lsp, struct isis_circuit *circuit, + int level) { - struct isis_adjacency *adj; - struct is_neigh *is_neigh; - struct te_is_neigh *te_is_neigh; - struct es_neigh *es_neigh; - struct list *adj_list; - struct listnode *node; - struct isis_area *area = circuit->area; - - lsp_debug("ISIS (%s): Constructing pseudo LSP %s for interface %s level %d", - area->area_tag, rawlspid_print(lsp->lsp_header->lsp_id), - circuit->interface->name, level); - - lsp->level = level; - /* RFC3787 section 4 SHOULD not set overload bit in pseudo LSPs */ - lsp->lsp_header->lsp_bits = lsp_bits_generate (level, 0, - circuit->area->attached_bit); - - /* - * add self to IS neighbours - */ - if (circuit->area->oldmetric) - { - if (lsp->tlv_data.is_neighs == NULL) - { - lsp->tlv_data.is_neighs = list_new (); - lsp->tlv_data.is_neighs->del = free_tlv; - } - is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh)); - - memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN); - listnode_add (lsp->tlv_data.is_neighs, is_neigh); - lsp_debug("ISIS (%s): Adding %s.%02x as old-style neighbor (self)", - area->area_tag, sysid_print(is_neigh->neigh_id), - LSP_PSEUDO_ID(is_neigh->neigh_id)); - } - if (circuit->area->newmetric) - { - if (lsp->tlv_data.te_is_neighs == NULL) - { - lsp->tlv_data.te_is_neighs = list_new (); - lsp->tlv_data.te_is_neighs->del = free_tlv; - } - te_is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct te_is_neigh)); - - memcpy (&te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN); - listnode_add (lsp->tlv_data.te_is_neighs, te_is_neigh); - lsp_debug("ISIS (%s): Adding %s.%02x as te-style neighbor (self)", - area->area_tag, sysid_print(te_is_neigh->neigh_id), - LSP_PSEUDO_ID(te_is_neigh->neigh_id)); - } - - adj_list = list_new (); - isis_adj_build_up_list (circuit->u.bc.adjdb[level - 1], adj_list); - - for (ALL_LIST_ELEMENTS_RO (adj_list, node, adj)) - { - if (adj->level & level) - { - if ((level == IS_LEVEL_1 && adj->sys_type == ISIS_SYSTYPE_L1_IS) || - (level == IS_LEVEL_1 && adj->sys_type == ISIS_SYSTYPE_L2_IS && - adj->adj_usage == ISIS_ADJ_LEVEL1AND2) || - (level == IS_LEVEL_2 && adj->sys_type == ISIS_SYSTYPE_L2_IS)) - { - /* an IS neighbour -> add it */ - if (circuit->area->oldmetric) - { - is_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct is_neigh)); - - memcpy (&is_neigh->neigh_id, adj->sysid, ISIS_SYS_ID_LEN); - listnode_add (lsp->tlv_data.is_neighs, is_neigh); - lsp_debug("ISIS (%s): Adding %s.%02x as old-style neighbor (peer)", - area->area_tag, sysid_print(is_neigh->neigh_id), - LSP_PSEUDO_ID(is_neigh->neigh_id)); + struct isis_adjacency *adj; + struct is_neigh *is_neigh; + struct te_is_neigh *te_is_neigh; + struct es_neigh *es_neigh; + struct list *adj_list; + struct listnode *node; + struct isis_area *area = circuit->area; + + lsp_debug( + "ISIS (%s): Constructing pseudo LSP %s for interface %s level %d", + area->area_tag, rawlspid_print(lsp->lsp_header->lsp_id), + circuit->interface->name, level); + + lsp->level = level; + /* RFC3787 section 4 SHOULD not set overload bit in pseudo LSPs */ + lsp->lsp_header->lsp_bits = + lsp_bits_generate(level, 0, circuit->area->attached_bit); + + /* + * add self to IS neighbours + */ + if (circuit->area->oldmetric) { + if (lsp->tlv_data.is_neighs == NULL) { + lsp->tlv_data.is_neighs = list_new(); + lsp->tlv_data.is_neighs->del = free_tlv; } - if (circuit->area->newmetric) - { - te_is_neigh = XCALLOC (MTYPE_ISIS_TLV, - sizeof (struct te_is_neigh)); - memcpy (&te_is_neigh->neigh_id, adj->sysid, ISIS_SYS_ID_LEN); - listnode_add (lsp->tlv_data.te_is_neighs, te_is_neigh); - lsp_debug("ISIS (%s): Adding %s.%02x as te-style neighbor (peer)", - area->area_tag, sysid_print(te_is_neigh->neigh_id), - LSP_PSEUDO_ID(te_is_neigh->neigh_id)); + is_neigh = XCALLOC(MTYPE_ISIS_TLV, sizeof(struct is_neigh)); + + memcpy(&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN); + listnode_add(lsp->tlv_data.is_neighs, is_neigh); + lsp_debug( + "ISIS (%s): Adding %s.%02x as old-style neighbor (self)", + area->area_tag, sysid_print(is_neigh->neigh_id), + LSP_PSEUDO_ID(is_neigh->neigh_id)); + } + if (circuit->area->newmetric) { + if (lsp->tlv_data.te_is_neighs == NULL) { + lsp->tlv_data.te_is_neighs = list_new(); + lsp->tlv_data.te_is_neighs->del = free_tlv; } - } - else if (level == IS_LEVEL_1 && adj->sys_type == ISIS_SYSTYPE_ES) - { - /* an ES neigbour add it, if we are building level 1 LSP */ - /* FIXME: the tlv-format is hard to use here */ - if (lsp->tlv_data.es_neighs == NULL) - { - lsp->tlv_data.es_neighs = list_new (); - lsp->tlv_data.es_neighs->del = free_tlv; + te_is_neigh = + XCALLOC(MTYPE_ISIS_TLV, sizeof(struct te_is_neigh)); + + memcpy(&te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN); + listnode_add(lsp->tlv_data.te_is_neighs, te_is_neigh); + lsp_debug( + "ISIS (%s): Adding %s.%02x as te-style neighbor (self)", + area->area_tag, sysid_print(te_is_neigh->neigh_id), + LSP_PSEUDO_ID(te_is_neigh->neigh_id)); + } + + adj_list = list_new(); + isis_adj_build_up_list(circuit->u.bc.adjdb[level - 1], adj_list); + + for (ALL_LIST_ELEMENTS_RO(adj_list, node, adj)) { + if (adj->level & level) { + if ((level == IS_LEVEL_1 + && adj->sys_type == ISIS_SYSTYPE_L1_IS) + || (level == IS_LEVEL_1 + && adj->sys_type == ISIS_SYSTYPE_L2_IS + && adj->adj_usage == ISIS_ADJ_LEVEL1AND2) + || (level == IS_LEVEL_2 + && adj->sys_type == ISIS_SYSTYPE_L2_IS)) { + /* an IS neighbour -> add it */ + if (circuit->area->oldmetric) { + is_neigh = XCALLOC( + MTYPE_ISIS_TLV, + sizeof(struct is_neigh)); + + memcpy(&is_neigh->neigh_id, adj->sysid, + ISIS_SYS_ID_LEN); + listnode_add(lsp->tlv_data.is_neighs, + is_neigh); + lsp_debug( + "ISIS (%s): Adding %s.%02x as old-style neighbor (peer)", + area->area_tag, + sysid_print(is_neigh->neigh_id), + LSP_PSEUDO_ID( + is_neigh->neigh_id)); + } + if (circuit->area->newmetric) { + te_is_neigh = XCALLOC( + MTYPE_ISIS_TLV, + sizeof(struct te_is_neigh)); + memcpy(&te_is_neigh->neigh_id, + adj->sysid, ISIS_SYS_ID_LEN); + listnode_add(lsp->tlv_data.te_is_neighs, + te_is_neigh); + lsp_debug( + "ISIS (%s): Adding %s.%02x as te-style neighbor (peer)", + area->area_tag, + sysid_print( + te_is_neigh->neigh_id), + LSP_PSEUDO_ID( + te_is_neigh->neigh_id)); + } + } else if (level == IS_LEVEL_1 + && adj->sys_type == ISIS_SYSTYPE_ES) { + /* an ES neigbour add it, if we are building + * level 1 LSP */ + /* FIXME: the tlv-format is hard to use here */ + if (lsp->tlv_data.es_neighs == NULL) { + lsp->tlv_data.es_neighs = list_new(); + lsp->tlv_data.es_neighs->del = free_tlv; + } + es_neigh = XCALLOC(MTYPE_ISIS_TLV, + sizeof(struct es_neigh)); + + memcpy(&es_neigh->first_es_neigh, adj->sysid, + ISIS_SYS_ID_LEN); + listnode_add(lsp->tlv_data.es_neighs, es_neigh); + lsp_debug( + "ISIS (%s): Adding %s as ES neighbor (peer)", + area->area_tag, + sysid_print(es_neigh->first_es_neigh)); + } else { + lsp_debug( + "ISIS (%s): Ignoring neighbor %s, level does not match", + area->area_tag, + sysid_print(adj->sysid)); + } + } else { + lsp_debug( + "ISIS (%s): Ignoring neighbor %s, level does not intersect", + area->area_tag, sysid_print(adj->sysid)); } - es_neigh = XCALLOC (MTYPE_ISIS_TLV, sizeof (struct es_neigh)); - - memcpy (&es_neigh->first_es_neigh, adj->sysid, ISIS_SYS_ID_LEN); - listnode_add (lsp->tlv_data.es_neighs, es_neigh); - lsp_debug("ISIS (%s): Adding %s as ES neighbor (peer)", - area->area_tag, sysid_print(es_neigh->first_es_neigh)); - } - else - { - lsp_debug("ISIS (%s): Ignoring neighbor %s, level does not match", - area->area_tag, sysid_print(adj->sysid)); - } - } - else - { - lsp_debug("ISIS (%s): Ignoring neighbor %s, level does not intersect", - area->area_tag, sysid_print(adj->sysid)); - } - } - list_delete (adj_list); - - lsp_debug("ISIS (%s): Pseudo LSP construction is complete.", area->area_tag); - - /* Reset endp of stream to overwrite only TLV part of it. */ - stream_reset (lsp->pdu); - stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); - - /* - * Add the authentication info if it's present - */ - lsp_auth_add (lsp); - - if (lsp->tlv_data.is_neighs && listcount (lsp->tlv_data.is_neighs) > 0) - tlv_add_is_neighs (lsp->tlv_data.is_neighs, lsp->pdu); - - if (lsp->tlv_data.te_is_neighs && listcount (lsp->tlv_data.te_is_neighs) > 0) - tlv_add_te_is_neighs (lsp->tlv_data.te_is_neighs, lsp->pdu, NULL); - - if (lsp->tlv_data.es_neighs && listcount (lsp->tlv_data.es_neighs) > 0) - tlv_add_is_neighs (lsp->tlv_data.es_neighs, lsp->pdu); - - lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu)); - - /* Recompute authentication and checksum information */ - lsp_auth_update (lsp); - fletcher_checksum(STREAM_DATA (lsp->pdu) + 12, - ntohs (lsp->lsp_header->pdu_len) - 12, 12); - - return; + } + list_delete(adj_list); + + lsp_debug("ISIS (%s): Pseudo LSP construction is complete.", + area->area_tag); + + /* Reset endp of stream to overwrite only TLV part of it. */ + stream_reset(lsp->pdu); + stream_forward_endp(lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); + + /* + * Add the authentication info if it's present + */ + lsp_auth_add(lsp); + + if (lsp->tlv_data.is_neighs && listcount(lsp->tlv_data.is_neighs) > 0) + tlv_add_is_neighs(lsp->tlv_data.is_neighs, lsp->pdu); + + if (lsp->tlv_data.te_is_neighs + && listcount(lsp->tlv_data.te_is_neighs) > 0) + tlv_add_te_is_neighs(lsp->tlv_data.te_is_neighs, lsp->pdu, + NULL); + + if (lsp->tlv_data.es_neighs && listcount(lsp->tlv_data.es_neighs) > 0) + tlv_add_is_neighs(lsp->tlv_data.es_neighs, lsp->pdu); + + lsp->lsp_header->pdu_len = htons(stream_get_endp(lsp->pdu)); + + /* Recompute authentication and checksum information */ + lsp_auth_update(lsp); + fletcher_checksum(STREAM_DATA(lsp->pdu) + 12, + ntohs(lsp->lsp_header->pdu_len) - 12, 12); + + return; } -int -lsp_generate_pseudo (struct isis_circuit *circuit, int level) +int lsp_generate_pseudo(struct isis_circuit *circuit, int level) { - dict_t *lspdb = circuit->area->lspdb[level - 1]; - struct isis_lsp *lsp; - u_char lsp_id[ISIS_SYS_ID_LEN + 2]; - u_int16_t rem_lifetime, refresh_time; - - if ((circuit->is_type & level) != level || - (circuit->state != C_STATE_UP) || - (circuit->circ_type != CIRCUIT_T_BROADCAST) || - (circuit->u.bc.is_dr[level - 1] == 0)) - return ISIS_ERROR; - - memcpy (lsp_id, isis->sysid, ISIS_SYS_ID_LEN); - LSP_FRAGMENT (lsp_id) = 0; - LSP_PSEUDO_ID (lsp_id) = circuit->circuit_id; - - /* - * If for some reason have a pseudo LSP in the db already -> regenerate - */ - if (lsp_search (lsp_id, lspdb)) - return lsp_regenerate_schedule_pseudo (circuit, level); - - rem_lifetime = lsp_rem_lifetime (circuit->area, level); - /* RFC3787 section 4 SHOULD not set overload bit in pseudo LSPs */ - lsp = lsp_new (circuit->area, lsp_id, rem_lifetime, 1, - circuit->area->is_type | circuit->area->attached_bit, - 0, level); - lsp->area = circuit->area; - - lsp_build_pseudo (lsp, circuit, level); - - lsp->own_lsp = 1; - lsp_insert (lsp, lspdb); - lsp_set_all_srmflags (lsp); - - refresh_time = lsp_refresh_time (lsp, rem_lifetime); - THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[level - 1]); - circuit->lsp_regenerate_pending[level - 1] = 0; - if (level == IS_LEVEL_1) - thread_add_timer(master, lsp_l1_refresh_pseudo, circuit, refresh_time, - &circuit->u.bc.t_refresh_pseudo_lsp[level - 1]); - else if (level == IS_LEVEL_2) - thread_add_timer(master, lsp_l2_refresh_pseudo, circuit, refresh_time, - &circuit->u.bc.t_refresh_pseudo_lsp[level - 1]); - - if (isis->debugs & DEBUG_UPDATE_PACKETS) - { - zlog_debug ("ISIS-Upd (%s): Building L%d Pseudo LSP %s, len %d, " - "seq 0x%08x, cksum 0x%04x, lifetime %us, refresh %us", - circuit->area->area_tag, level, - rawlspid_print (lsp->lsp_header->lsp_id), - ntohl (lsp->lsp_header->pdu_len), - ntohl (lsp->lsp_header->seq_num), - ntohs (lsp->lsp_header->checksum), - ntohs (lsp->lsp_header->rem_lifetime), - refresh_time); - } - - return ISIS_OK; + dict_t *lspdb = circuit->area->lspdb[level - 1]; + struct isis_lsp *lsp; + u_char lsp_id[ISIS_SYS_ID_LEN + 2]; + u_int16_t rem_lifetime, refresh_time; + + if ((circuit->is_type & level) != level + || (circuit->state != C_STATE_UP) + || (circuit->circ_type != CIRCUIT_T_BROADCAST) + || (circuit->u.bc.is_dr[level - 1] == 0)) + return ISIS_ERROR; + + memcpy(lsp_id, isis->sysid, ISIS_SYS_ID_LEN); + LSP_FRAGMENT(lsp_id) = 0; + LSP_PSEUDO_ID(lsp_id) = circuit->circuit_id; + + /* + * If for some reason have a pseudo LSP in the db already -> regenerate + */ + if (lsp_search(lsp_id, lspdb)) + return lsp_regenerate_schedule_pseudo(circuit, level); + + rem_lifetime = lsp_rem_lifetime(circuit->area, level); + /* RFC3787 section 4 SHOULD not set overload bit in pseudo LSPs */ + lsp = lsp_new(circuit->area, lsp_id, rem_lifetime, 1, + circuit->area->is_type | circuit->area->attached_bit, 0, + level); + lsp->area = circuit->area; + + lsp_build_pseudo(lsp, circuit, level); + + lsp->own_lsp = 1; + lsp_insert(lsp, lspdb); + lsp_set_all_srmflags(lsp); + + refresh_time = lsp_refresh_time(lsp, rem_lifetime); + THREAD_TIMER_OFF(circuit->u.bc.t_refresh_pseudo_lsp[level - 1]); + circuit->lsp_regenerate_pending[level - 1] = 0; + if (level == IS_LEVEL_1) + thread_add_timer( + master, lsp_l1_refresh_pseudo, circuit, refresh_time, + &circuit->u.bc.t_refresh_pseudo_lsp[level - 1]); + else if (level == IS_LEVEL_2) + thread_add_timer( + master, lsp_l2_refresh_pseudo, circuit, refresh_time, + &circuit->u.bc.t_refresh_pseudo_lsp[level - 1]); + + if (isis->debugs & DEBUG_UPDATE_PACKETS) { + zlog_debug( + "ISIS-Upd (%s): Building L%d Pseudo LSP %s, len %d, " + "seq 0x%08x, cksum 0x%04x, lifetime %us, refresh %us", + circuit->area->area_tag, level, + rawlspid_print(lsp->lsp_header->lsp_id), + ntohl(lsp->lsp_header->pdu_len), + ntohl(lsp->lsp_header->seq_num), + ntohs(lsp->lsp_header->checksum), + ntohs(lsp->lsp_header->rem_lifetime), refresh_time); + } + + return ISIS_OK; } -static int -lsp_regenerate_pseudo (struct isis_circuit *circuit, int level) +static int lsp_regenerate_pseudo(struct isis_circuit *circuit, int level) { - dict_t *lspdb = circuit->area->lspdb[level - 1]; - struct isis_lsp *lsp; - u_char lsp_id[ISIS_SYS_ID_LEN + 2]; - u_int16_t rem_lifetime, refresh_time; - - if ((circuit->is_type & level) != level || - (circuit->state != C_STATE_UP) || - (circuit->circ_type != CIRCUIT_T_BROADCAST) || - (circuit->u.bc.is_dr[level - 1] == 0)) - return ISIS_ERROR; - - memcpy (lsp_id, isis->sysid, ISIS_SYS_ID_LEN); - LSP_PSEUDO_ID (lsp_id) = circuit->circuit_id; - LSP_FRAGMENT (lsp_id) = 0; - - lsp = lsp_search (lsp_id, lspdb); - - if (!lsp) - { - zlog_err ("lsp_regenerate_pseudo: no l%d LSP %s found!", - level, rawlspid_print (lsp_id)); - return ISIS_ERROR; - } - lsp_clear_data (lsp); - - lsp_build_pseudo (lsp, circuit, level); - - /* RFC3787 section 4 SHOULD not set overload bit in pseudo LSPs */ - lsp->lsp_header->lsp_bits = lsp_bits_generate (level, 0, - circuit->area->attached_bit); - rem_lifetime = lsp_rem_lifetime (circuit->area, level); - lsp->lsp_header->rem_lifetime = htons (rem_lifetime); - lsp_inc_seqnum (lsp, 0); - lsp->last_generated = time (NULL); - lsp_set_all_srmflags (lsp); - - refresh_time = lsp_refresh_time (lsp, rem_lifetime); - if (level == IS_LEVEL_1) - thread_add_timer(master, lsp_l1_refresh_pseudo, circuit, refresh_time, - &circuit->u.bc.t_refresh_pseudo_lsp[level - 1]); - else if (level == IS_LEVEL_2) - thread_add_timer(master, lsp_l2_refresh_pseudo, circuit, refresh_time, - &circuit->u.bc.t_refresh_pseudo_lsp[level - 1]); - - if (isis->debugs & DEBUG_UPDATE_PACKETS) - { - zlog_debug ("ISIS-Upd (%s): Refreshing L%d Pseudo LSP %s, len %d, " - "seq 0x%08x, cksum 0x%04x, lifetime %us, refresh %us", - circuit->area->area_tag, level, - rawlspid_print (lsp->lsp_header->lsp_id), - ntohl (lsp->lsp_header->pdu_len), - ntohl (lsp->lsp_header->seq_num), - ntohs (lsp->lsp_header->checksum), - ntohs (lsp->lsp_header->rem_lifetime), - refresh_time); - } - - return ISIS_OK; + dict_t *lspdb = circuit->area->lspdb[level - 1]; + struct isis_lsp *lsp; + u_char lsp_id[ISIS_SYS_ID_LEN + 2]; + u_int16_t rem_lifetime, refresh_time; + + if ((circuit->is_type & level) != level + || (circuit->state != C_STATE_UP) + || (circuit->circ_type != CIRCUIT_T_BROADCAST) + || (circuit->u.bc.is_dr[level - 1] == 0)) + return ISIS_ERROR; + + memcpy(lsp_id, isis->sysid, ISIS_SYS_ID_LEN); + LSP_PSEUDO_ID(lsp_id) = circuit->circuit_id; + LSP_FRAGMENT(lsp_id) = 0; + + lsp = lsp_search(lsp_id, lspdb); + + if (!lsp) { + zlog_err("lsp_regenerate_pseudo: no l%d LSP %s found!", level, + rawlspid_print(lsp_id)); + return ISIS_ERROR; + } + lsp_clear_data(lsp); + + lsp_build_pseudo(lsp, circuit, level); + + /* RFC3787 section 4 SHOULD not set overload bit in pseudo LSPs */ + lsp->lsp_header->lsp_bits = + lsp_bits_generate(level, 0, circuit->area->attached_bit); + rem_lifetime = lsp_rem_lifetime(circuit->area, level); + lsp->lsp_header->rem_lifetime = htons(rem_lifetime); + lsp_inc_seqnum(lsp, 0); + lsp->last_generated = time(NULL); + lsp_set_all_srmflags(lsp); + + refresh_time = lsp_refresh_time(lsp, rem_lifetime); + if (level == IS_LEVEL_1) + thread_add_timer( + master, lsp_l1_refresh_pseudo, circuit, refresh_time, + &circuit->u.bc.t_refresh_pseudo_lsp[level - 1]); + else if (level == IS_LEVEL_2) + thread_add_timer( + master, lsp_l2_refresh_pseudo, circuit, refresh_time, + &circuit->u.bc.t_refresh_pseudo_lsp[level - 1]); + + if (isis->debugs & DEBUG_UPDATE_PACKETS) { + zlog_debug( + "ISIS-Upd (%s): Refreshing L%d Pseudo LSP %s, len %d, " + "seq 0x%08x, cksum 0x%04x, lifetime %us, refresh %us", + circuit->area->area_tag, level, + rawlspid_print(lsp->lsp_header->lsp_id), + ntohl(lsp->lsp_header->pdu_len), + ntohl(lsp->lsp_header->seq_num), + ntohs(lsp->lsp_header->checksum), + ntohs(lsp->lsp_header->rem_lifetime), refresh_time); + } + + return ISIS_OK; } /* * Something has changed or periodic refresh -> regenerate pseudo LSP */ -static int -lsp_l1_refresh_pseudo (struct thread *thread) +static int lsp_l1_refresh_pseudo(struct thread *thread) { - struct isis_circuit *circuit; - u_char id[ISIS_SYS_ID_LEN + 2]; + struct isis_circuit *circuit; + u_char id[ISIS_SYS_ID_LEN + 2]; - circuit = THREAD_ARG (thread); + circuit = THREAD_ARG(thread); - circuit->u.bc.t_refresh_pseudo_lsp[0] = NULL; - circuit->lsp_regenerate_pending[0] = 0; + circuit->u.bc.t_refresh_pseudo_lsp[0] = NULL; + circuit->lsp_regenerate_pending[0] = 0; - if ((circuit->u.bc.is_dr[0] == 0) || - (circuit->is_type & IS_LEVEL_1) == 0) - { - memcpy (id, isis->sysid, ISIS_SYS_ID_LEN); - LSP_PSEUDO_ID (id) = circuit->circuit_id; - LSP_FRAGMENT (id) = 0; - lsp_purge_pseudo (id, circuit, IS_LEVEL_1); - return ISIS_ERROR; - } + if ((circuit->u.bc.is_dr[0] == 0) + || (circuit->is_type & IS_LEVEL_1) == 0) { + memcpy(id, isis->sysid, ISIS_SYS_ID_LEN); + LSP_PSEUDO_ID(id) = circuit->circuit_id; + LSP_FRAGMENT(id) = 0; + lsp_purge_pseudo(id, circuit, IS_LEVEL_1); + return ISIS_ERROR; + } - return lsp_regenerate_pseudo (circuit, IS_LEVEL_1); + return lsp_regenerate_pseudo(circuit, IS_LEVEL_1); } -static int -lsp_l2_refresh_pseudo (struct thread *thread) +static int lsp_l2_refresh_pseudo(struct thread *thread) { - struct isis_circuit *circuit; - u_char id[ISIS_SYS_ID_LEN + 2]; + struct isis_circuit *circuit; + u_char id[ISIS_SYS_ID_LEN + 2]; - circuit = THREAD_ARG (thread); + circuit = THREAD_ARG(thread); - circuit->u.bc.t_refresh_pseudo_lsp[1] = NULL; - circuit->lsp_regenerate_pending[1] = 0; + circuit->u.bc.t_refresh_pseudo_lsp[1] = NULL; + circuit->lsp_regenerate_pending[1] = 0; - if ((circuit->u.bc.is_dr[1] == 0) || - (circuit->is_type & IS_LEVEL_2) == 0) - { - memcpy (id, isis->sysid, ISIS_SYS_ID_LEN); - LSP_PSEUDO_ID (id) = circuit->circuit_id; - LSP_FRAGMENT (id) = 0; - lsp_purge_pseudo (id, circuit, IS_LEVEL_2); - return ISIS_ERROR; - } + if ((circuit->u.bc.is_dr[1] == 0) + || (circuit->is_type & IS_LEVEL_2) == 0) { + memcpy(id, isis->sysid, ISIS_SYS_ID_LEN); + LSP_PSEUDO_ID(id) = circuit->circuit_id; + LSP_FRAGMENT(id) = 0; + lsp_purge_pseudo(id, circuit, IS_LEVEL_2); + return ISIS_ERROR; + } - return lsp_regenerate_pseudo (circuit, IS_LEVEL_2); + return lsp_regenerate_pseudo(circuit, IS_LEVEL_2); } -int -lsp_regenerate_schedule_pseudo (struct isis_circuit *circuit, int level) +int lsp_regenerate_schedule_pseudo(struct isis_circuit *circuit, int level) { - struct isis_lsp *lsp; - u_char lsp_id[ISIS_SYS_ID_LEN + 2]; - time_t now, diff; - long timeout; - int lvl; - struct isis_area *area = circuit->area; - - if (circuit->circ_type != CIRCUIT_T_BROADCAST || - circuit->state != C_STATE_UP) - return ISIS_OK; - - sched_debug("ISIS (%s): Scheduling regeneration of %s pseudo LSP for interface %s", - area->area_tag, circuit_t2string(level), circuit->interface->name); - - memcpy (lsp_id, isis->sysid, ISIS_SYS_ID_LEN); - LSP_PSEUDO_ID (lsp_id) = circuit->circuit_id; - LSP_FRAGMENT (lsp_id) = 0; - now = time (NULL); - - for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++) - { - sched_debug("ISIS (%s): Checking whether L%d pseudo LSP needs to be scheduled", - area->area_tag, lvl); - - if (!((level & lvl) && (circuit->is_type & lvl))) - { - sched_debug("ISIS (%s): Level is not active on circuit", - area->area_tag); - continue; - } - - if (circuit->u.bc.is_dr[lvl - 1] == 0) - { - sched_debug("ISIS (%s): This IS is not DR, nothing to do.", - area->area_tag); - continue; - } - - if (circuit->lsp_regenerate_pending[lvl - 1]) - { - struct timeval remain = - thread_timer_remain(circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1]); - sched_debug("ISIS (%s): Regenerate is already pending, nothing todo." - " (Due in %lld.%03lld seconds)", area->area_tag, - (long long)remain.tv_sec, (long long)remain.tv_usec/1000); - continue; - } - - lsp = lsp_search (lsp_id, circuit->area->lspdb[lvl - 1]); - if (!lsp) - { - sched_debug("ISIS (%s): Pseudonode LSP does not exist yet, nothing to regenerate.", - area->area_tag); - continue; - } - - /* - * Throttle avoidance - */ - sched_debug("ISIS (%s): Will schedule PSN regen timer. Last run was: %lld, Now is: %lld", - area->area_tag, (long long)lsp->last_generated, (long long) now); - THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1]); - diff = now - lsp->last_generated; - if (diff < circuit->area->lsp_gen_interval[lvl - 1]) - { - timeout = 1000 * (circuit->area->lsp_gen_interval[lvl - 1] - diff); - sched_debug("ISIS (%s): Sechduling in %ld ms to match configured lsp_gen_interval", - area->area_tag, timeout); - } - else - { - timeout = 100; - sched_debug("ISIS (%s): Last generation was more than lsp_gen_interval ago." - " Scheduling for execution in %ld ms.", area->area_tag, timeout); - } - - circuit->lsp_regenerate_pending[lvl - 1] = 1; - - if (lvl == IS_LEVEL_1) - { - thread_add_timer_msec(master, lsp_l1_refresh_pseudo, circuit, - timeout, - &circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1]); - } - else if (lvl == IS_LEVEL_2) - { - thread_add_timer_msec(master, lsp_l2_refresh_pseudo, circuit, - timeout, - &circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1]); - } - } - - return ISIS_OK; + struct isis_lsp *lsp; + u_char lsp_id[ISIS_SYS_ID_LEN + 2]; + time_t now, diff; + long timeout; + int lvl; + struct isis_area *area = circuit->area; + + if (circuit->circ_type != CIRCUIT_T_BROADCAST + || circuit->state != C_STATE_UP) + return ISIS_OK; + + sched_debug( + "ISIS (%s): Scheduling regeneration of %s pseudo LSP for interface %s", + area->area_tag, circuit_t2string(level), + circuit->interface->name); + + memcpy(lsp_id, isis->sysid, ISIS_SYS_ID_LEN); + LSP_PSEUDO_ID(lsp_id) = circuit->circuit_id; + LSP_FRAGMENT(lsp_id) = 0; + now = time(NULL); + + for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++) { + sched_debug( + "ISIS (%s): Checking whether L%d pseudo LSP needs to be scheduled", + area->area_tag, lvl); + + if (!((level & lvl) && (circuit->is_type & lvl))) { + sched_debug("ISIS (%s): Level is not active on circuit", + area->area_tag); + continue; + } + + if (circuit->u.bc.is_dr[lvl - 1] == 0) { + sched_debug( + "ISIS (%s): This IS is not DR, nothing to do.", + area->area_tag); + continue; + } + + if (circuit->lsp_regenerate_pending[lvl - 1]) { + struct timeval remain = thread_timer_remain( + circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1]); + sched_debug( + "ISIS (%s): Regenerate is already pending, nothing todo." + " (Due in %lld.%03lld seconds)", + area->area_tag, (long long)remain.tv_sec, + (long long)remain.tv_usec / 1000); + continue; + } + + lsp = lsp_search(lsp_id, circuit->area->lspdb[lvl - 1]); + if (!lsp) { + sched_debug( + "ISIS (%s): Pseudonode LSP does not exist yet, nothing to regenerate.", + area->area_tag); + continue; + } + + /* + * Throttle avoidance + */ + sched_debug( + "ISIS (%s): Will schedule PSN regen timer. Last run was: %lld, Now is: %lld", + area->area_tag, (long long)lsp->last_generated, + (long long)now); + THREAD_TIMER_OFF(circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1]); + diff = now - lsp->last_generated; + if (diff < circuit->area->lsp_gen_interval[lvl - 1]) { + timeout = + 1000 * (circuit->area->lsp_gen_interval[lvl - 1] + - diff); + sched_debug( + "ISIS (%s): Sechduling in %ld ms to match configured lsp_gen_interval", + area->area_tag, timeout); + } else { + timeout = 100; + sched_debug( + "ISIS (%s): Last generation was more than lsp_gen_interval ago." + " Scheduling for execution in %ld ms.", + area->area_tag, timeout); + } + + circuit->lsp_regenerate_pending[lvl - 1] = 1; + + if (lvl == IS_LEVEL_1) { + thread_add_timer_msec( + master, lsp_l1_refresh_pseudo, circuit, timeout, + &circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1]); + } else if (lvl == IS_LEVEL_2) { + thread_add_timer_msec( + master, lsp_l2_refresh_pseudo, circuit, timeout, + &circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1]); + } + } + + return ISIS_OK; } /* @@ -2702,231 +2789,248 @@ lsp_regenerate_schedule_pseudo (struct isis_circuit *circuit, int level) * - set remaining lifetime * - set LSPs with SRMflag set for sending */ -int -lsp_tick (struct thread *thread) +int lsp_tick(struct thread *thread) { - struct isis_area *area; - struct isis_circuit *circuit; - struct isis_lsp *lsp; - struct list *lsp_list; - struct listnode *lspnode, *cnode; - dnode_t *dnode, *dnode_next; - int level; - u_int16_t rem_lifetime; - - lsp_list = list_new (); - - area = THREAD_ARG (thread); - assert (area); - area->t_tick = NULL; - thread_add_timer(master, lsp_tick, area, 1, &area->t_tick); - - /* - * Build a list of LSPs with (any) SRMflag set - * and removed the ones that have aged out - */ - for (level = 0; level < ISIS_LEVELS; level++) - { - if (area->lspdb[level] && dict_count (area->lspdb[level]) > 0) - { - for (dnode = dict_first (area->lspdb[level]); - dnode != NULL; dnode = dnode_next) - { - dnode_next = dict_next (area->lspdb[level], dnode); - lsp = dnode_get (dnode); - - /* - * The lsp rem_lifetime is kept at 0 for MaxAge or - * ZeroAgeLifetime depending on explicit purge or - * natural age out. So schedule spf only once when - * the first time rem_lifetime becomes 0. - */ - rem_lifetime = ntohs(lsp->lsp_header->rem_lifetime); - lsp_set_time (lsp); - - /* - * Schedule may run spf which should be done only after - * the lsp rem_lifetime becomes 0 for the first time. - * ISO 10589 - 7.3.16.4 first paragraph. - */ - if (rem_lifetime == 1 && lsp->lsp_header->seq_num != 0) - { - /* 7.3.16.4 a) set SRM flags on all */ - lsp_set_all_srmflags (lsp); - /* 7.3.16.4 b) retain only the header FIXME */ - /* 7.3.16.4 c) record the time to purge FIXME */ - /* run/schedule spf */ - /* isis_spf_schedule is called inside lsp_destroy() below; - * so it is not needed here. */ - /* isis_spf_schedule (lsp->area, lsp->level); */ - } - - if (lsp->age_out == 0) - { - zlog_debug ("ISIS-Upd (%s): L%u LSP %s seq 0x%08x aged out", - area->area_tag, - lsp->level, - rawlspid_print (lsp->lsp_header->lsp_id), - ntohl (lsp->lsp_header->seq_num)); - lsp_destroy (lsp); - lsp = NULL; - dict_delete_free (area->lspdb[level], dnode); - } - else if (flags_any_set (lsp->SRMflags)) - listnode_add (lsp_list, lsp); - } - - /* - * Send LSPs on circuits indicated by the SRMflags - */ - if (listcount (lsp_list) > 0) - { - for (ALL_LIST_ELEMENTS_RO (area->circuit_list, cnode, circuit)) - { - int diff = time (NULL) - circuit->lsp_queue_last_cleared; - if (circuit->lsp_queue == NULL || - diff < MIN_LSP_TRANS_INTERVAL) - continue; - for (ALL_LIST_ELEMENTS_RO (lsp_list, lspnode, lsp)) - { - if (circuit->upadjcount[lsp->level - 1] && - ISIS_CHECK_FLAG (lsp->SRMflags, circuit)) - { - /* Add the lsp only if it is not already in lsp - * queue */ - if (! listnode_lookup (circuit->lsp_queue, lsp)) - { - listnode_add (circuit->lsp_queue, lsp); - thread_add_event(master, send_lsp, circuit, 0, - NULL); - } - } - } - } - list_delete_all_node (lsp_list); - } - } - } - - list_delete (lsp_list); - - return ISIS_OK; + struct isis_area *area; + struct isis_circuit *circuit; + struct isis_lsp *lsp; + struct list *lsp_list; + struct listnode *lspnode, *cnode; + dnode_t *dnode, *dnode_next; + int level; + u_int16_t rem_lifetime; + + lsp_list = list_new(); + + area = THREAD_ARG(thread); + assert(area); + area->t_tick = NULL; + thread_add_timer(master, lsp_tick, area, 1, &area->t_tick); + + /* + * Build a list of LSPs with (any) SRMflag set + * and removed the ones that have aged out + */ + for (level = 0; level < ISIS_LEVELS; level++) { + if (area->lspdb[level] && dict_count(area->lspdb[level]) > 0) { + for (dnode = dict_first(area->lspdb[level]); + dnode != NULL; dnode = dnode_next) { + dnode_next = + dict_next(area->lspdb[level], dnode); + lsp = dnode_get(dnode); + + /* + * The lsp rem_lifetime is kept at 0 for MaxAge + * or + * ZeroAgeLifetime depending on explicit purge + * or + * natural age out. So schedule spf only once + * when + * the first time rem_lifetime becomes 0. + */ + rem_lifetime = + ntohs(lsp->lsp_header->rem_lifetime); + lsp_set_time(lsp); + + /* + * Schedule may run spf which should be done + * only after + * the lsp rem_lifetime becomes 0 for the first + * time. + * ISO 10589 - 7.3.16.4 first paragraph. + */ + if (rem_lifetime == 1 + && lsp->lsp_header->seq_num != 0) { + /* 7.3.16.4 a) set SRM flags on all */ + lsp_set_all_srmflags(lsp); + /* 7.3.16.4 b) retain only the header + * FIXME */ + /* 7.3.16.4 c) record the time to purge + * FIXME */ + /* run/schedule spf */ + /* isis_spf_schedule is called inside + * lsp_destroy() below; + * so it is not needed here. */ + /* isis_spf_schedule (lsp->area, + * lsp->level); */ + } + + if (lsp->age_out == 0) { + zlog_debug( + "ISIS-Upd (%s): L%u LSP %s seq 0x%08x aged out", + area->area_tag, lsp->level, + rawlspid_print( + lsp->lsp_header + ->lsp_id), + ntohl(lsp->lsp_header + ->seq_num)); + lsp_destroy(lsp); + lsp = NULL; + dict_delete_free(area->lspdb[level], + dnode); + } else if (flags_any_set(lsp->SRMflags)) + listnode_add(lsp_list, lsp); + } + + /* + * Send LSPs on circuits indicated by the SRMflags + */ + if (listcount(lsp_list) > 0) { + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, + cnode, circuit)) { + int diff = + time(NULL) + - circuit->lsp_queue_last_cleared; + if (circuit->lsp_queue == NULL + || diff < MIN_LSP_TRANS_INTERVAL) + continue; + for (ALL_LIST_ELEMENTS_RO( + lsp_list, lspnode, lsp)) { + if (circuit->upadjcount + [lsp->level - 1] + && ISIS_CHECK_FLAG( + lsp->SRMflags, + circuit)) { + /* Add the lsp only if + * it is not already in + * lsp + * queue */ + if (!listnode_lookup( + circuit->lsp_queue, + lsp)) { + listnode_add( + circuit->lsp_queue, + lsp); + thread_add_event( + master, + send_lsp, + circuit, + 0, + NULL); + } + } + } + } + list_delete_all_node(lsp_list); + } + } + } + + list_delete(lsp_list); + + return ISIS_OK; } -void -lsp_purge_pseudo (u_char * id, struct isis_circuit *circuit, int level) +void lsp_purge_pseudo(u_char *id, struct isis_circuit *circuit, int level) { - struct isis_lsp *lsp; - u_int16_t seq_num; - u_int8_t lsp_bits; - - lsp = lsp_search (id, circuit->area->lspdb[level - 1]); - if (!lsp) - return; - - /* store old values */ - seq_num = lsp->lsp_header->seq_num; - lsp_bits = lsp->lsp_header->lsp_bits; - - /* reset stream */ - lsp_clear_data (lsp); - stream_reset (lsp->pdu); - - /* update header */ - lsp->lsp_header->pdu_len = htons (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); - memcpy (lsp->lsp_header->lsp_id, id, ISIS_SYS_ID_LEN + 2); - lsp->lsp_header->checksum = 0; - lsp->lsp_header->seq_num = seq_num; - lsp->lsp_header->rem_lifetime = 0; - lsp->lsp_header->lsp_bits = lsp_bits; - lsp->level = level; - lsp->age_out = lsp->area->max_lsp_lifetime[level-1]; - stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); - - /* - * Add and update the authentication info if its present - */ - lsp_auth_add (lsp); - lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu)); - lsp_auth_update (lsp); - fletcher_checksum(STREAM_DATA (lsp->pdu) + 12, - ntohs (lsp->lsp_header->pdu_len) - 12, 12); - - lsp_set_all_srmflags (lsp); - - return; + struct isis_lsp *lsp; + u_int16_t seq_num; + u_int8_t lsp_bits; + + lsp = lsp_search(id, circuit->area->lspdb[level - 1]); + if (!lsp) + return; + + /* store old values */ + seq_num = lsp->lsp_header->seq_num; + lsp_bits = lsp->lsp_header->lsp_bits; + + /* reset stream */ + lsp_clear_data(lsp); + stream_reset(lsp->pdu); + + /* update header */ + lsp->lsp_header->pdu_len = htons(ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); + memcpy(lsp->lsp_header->lsp_id, id, ISIS_SYS_ID_LEN + 2); + lsp->lsp_header->checksum = 0; + lsp->lsp_header->seq_num = seq_num; + lsp->lsp_header->rem_lifetime = 0; + lsp->lsp_header->lsp_bits = lsp_bits; + lsp->level = level; + lsp->age_out = lsp->area->max_lsp_lifetime[level - 1]; + stream_forward_endp(lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); + + /* + * Add and update the authentication info if its present + */ + lsp_auth_add(lsp); + lsp->lsp_header->pdu_len = htons(stream_get_endp(lsp->pdu)); + lsp_auth_update(lsp); + fletcher_checksum(STREAM_DATA(lsp->pdu) + 12, + ntohs(lsp->lsp_header->pdu_len) - 12, 12); + + lsp_set_all_srmflags(lsp); + + return; } /* - * Purge own LSP that is received and we don't have. + * Purge own LSP that is received and we don't have. * -> Do as in 7.3.16.4 */ -void -lsp_purge_non_exist (int level, - struct isis_link_state_hdr *lsp_hdr, - struct isis_area *area) +void lsp_purge_non_exist(int level, struct isis_link_state_hdr *lsp_hdr, + struct isis_area *area) { - struct isis_lsp *lsp; - - /* - * We need to create the LSP to be purged - */ - lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp)); - lsp->area = area; - lsp->level = level; - lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu); - lsp->isis_header = (struct isis_fixed_hdr *) STREAM_DATA (lsp->pdu); - fill_fixed_hdr (lsp->isis_header, (lsp->level == IS_LEVEL_1) ? L1_LINK_STATE - : L2_LINK_STATE); - lsp->lsp_header = (struct isis_link_state_hdr *) (STREAM_DATA (lsp->pdu) + - ISIS_FIXED_HDR_LEN); - memcpy (lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN); - stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); - - /* - * Set the remaining lifetime to 0 - */ - lsp->lsp_header->rem_lifetime = 0; - - /* - * Add and update the authentication info if its present - */ - lsp_auth_add (lsp); - lsp_auth_update (lsp); - - /* - * Update the PDU length to header plus any authentication TLV. - */ - lsp->lsp_header->pdu_len = htons (stream_get_endp (lsp->pdu)); - - /* - * Put the lsp into LSPdb - */ - lsp_insert (lsp, area->lspdb[lsp->level - 1]); - - /* - * Send in to whole area - */ - lsp_set_all_srmflags (lsp); - - return; + struct isis_lsp *lsp; + + /* + * We need to create the LSP to be purged + */ + lsp = XCALLOC(MTYPE_ISIS_LSP, sizeof(struct isis_lsp)); + lsp->area = area; + lsp->level = level; + lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu); + lsp->isis_header = (struct isis_fixed_hdr *)STREAM_DATA(lsp->pdu); + fill_fixed_hdr(lsp->isis_header, + (lsp->level == IS_LEVEL_1) ? L1_LINK_STATE + : L2_LINK_STATE); + lsp->lsp_header = (struct isis_link_state_hdr *)(STREAM_DATA(lsp->pdu) + + ISIS_FIXED_HDR_LEN); + memcpy(lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN); + stream_forward_endp(lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); + + /* + * Set the remaining lifetime to 0 + */ + lsp->lsp_header->rem_lifetime = 0; + + /* + * Add and update the authentication info if its present + */ + lsp_auth_add(lsp); + lsp_auth_update(lsp); + + /* + * Update the PDU length to header plus any authentication TLV. + */ + lsp->lsp_header->pdu_len = htons(stream_get_endp(lsp->pdu)); + + /* + * Put the lsp into LSPdb + */ + lsp_insert(lsp, area->lspdb[lsp->level - 1]); + + /* + * Send in to whole area + */ + lsp_set_all_srmflags(lsp); + + return; } -void lsp_set_all_srmflags (struct isis_lsp *lsp) +void lsp_set_all_srmflags(struct isis_lsp *lsp) { - struct listnode *node; - struct isis_circuit *circuit; + struct listnode *node; + struct isis_circuit *circuit; - assert (lsp); + assert(lsp); - ISIS_FLAGS_CLEAR_ALL(lsp->SRMflags); + ISIS_FLAGS_CLEAR_ALL(lsp->SRMflags); - if (lsp->area) - { - struct list *circuit_list = lsp->area->circuit_list; - for (ALL_LIST_ELEMENTS_RO (circuit_list, node, circuit)) - { - ISIS_SET_FLAG(lsp->SRMflags, circuit); - } - } + if (lsp->area) { + struct list *circuit_list = lsp->area->circuit_list; + for (ALL_LIST_ELEMENTS_RO(circuit_list, node, circuit)) { + ISIS_SET_FLAG(lsp->SRMflags, circuit); + } + } } diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h index 0d1dd6740..7bec16271 100644 --- a/isisd/isis_lsp.h +++ b/isisd/isis_lsp.h @@ -1,19 +1,19 @@ /* - * IS-IS Rout(e)ing protocol - isis_lsp.h + * IS-IS Rout(e)ing protocol - isis_lsp.h * LSP processing * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -28,64 +28,58 @@ * System ID (Currently 6) (atleast for now). In order to support more * We will have to split the header into two parts, and for readability * sake it should better be avoided */ -struct isis_lsp -{ - struct isis_fixed_hdr *isis_header; /* normally equals pdu */ - struct isis_link_state_hdr *lsp_header; /* pdu + isis_header_len */ - struct stream *pdu; /* full pdu lsp */ - union - { - struct list *frags; - struct isis_lsp *zero_lsp; - } lspu; - u_int32_t auth_tlv_offset; /* authentication TLV position in the pdu */ - u_int32_t SRMflags[ISIS_MAX_CIRCUITS]; - u_int32_t SSNflags[ISIS_MAX_CIRCUITS]; - int level; /* L1 or L2? */ - int scheduled; /* scheduled for sending */ - time_t installed; - time_t last_generated; - int own_lsp; - /* used for 60 second counting when rem_lifetime is zero */ - int age_out; - struct isis_area *area; - struct tlvs tlv_data; /* Simplifies TLV access */ +struct isis_lsp { + struct isis_fixed_hdr *isis_header; /* normally equals pdu */ + struct isis_link_state_hdr *lsp_header; /* pdu + isis_header_len */ + struct stream *pdu; /* full pdu lsp */ + union { + struct list *frags; + struct isis_lsp *zero_lsp; + } lspu; + u_int32_t auth_tlv_offset; /* authentication TLV position in the pdu */ + u_int32_t SRMflags[ISIS_MAX_CIRCUITS]; + u_int32_t SSNflags[ISIS_MAX_CIRCUITS]; + int level; /* L1 or L2? */ + int scheduled; /* scheduled for sending */ + time_t installed; + time_t last_generated; + int own_lsp; + /* used for 60 second counting when rem_lifetime is zero */ + int age_out; + struct isis_area *area; + struct tlvs tlv_data; /* Simplifies TLV access */ }; -dict_t *lsp_db_init (void); -void lsp_db_destroy (dict_t * lspdb); -int lsp_tick (struct thread *thread); +dict_t *lsp_db_init(void); +void lsp_db_destroy(dict_t *lspdb); +int lsp_tick(struct thread *thread); -int lsp_generate (struct isis_area *area, int level); -int lsp_regenerate_schedule (struct isis_area *area, int level, - int all_pseudo); -int lsp_generate_pseudo (struct isis_circuit *circuit, int level); -int lsp_regenerate_schedule_pseudo (struct isis_circuit *circuit, int level); +int lsp_generate(struct isis_area *area, int level); +int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo); +int lsp_generate_pseudo(struct isis_circuit *circuit, int level); +int lsp_regenerate_schedule_pseudo(struct isis_circuit *circuit, int level); -struct isis_lsp *lsp_new (struct isis_area *area, u_char * lsp_id, - u_int16_t rem_lifetime, - u_int32_t seq_num, u_int8_t lsp_bits, - u_int16_t checksum, int level); -struct isis_lsp *lsp_new_from_stream_ptr (struct stream *stream, - u_int16_t pdu_len, - struct isis_lsp *lsp0, - struct isis_area *area, - int level); -void lsp_insert (struct isis_lsp *lsp, dict_t * lspdb); -struct isis_lsp *lsp_search (u_char * id, dict_t * lspdb); +struct isis_lsp *lsp_new(struct isis_area *area, u_char *lsp_id, + u_int16_t rem_lifetime, u_int32_t seq_num, + u_int8_t lsp_bits, u_int16_t checksum, int level); +struct isis_lsp *lsp_new_from_stream_ptr(struct stream *stream, + u_int16_t pdu_len, + struct isis_lsp *lsp0, + struct isis_area *area, int level); +void lsp_insert(struct isis_lsp *lsp, dict_t *lspdb); +struct isis_lsp *lsp_search(u_char *id, dict_t *lspdb); -void lsp_build_list (u_char * start_id, u_char * stop_id, u_char num_lsps, - struct list *list, dict_t * lspdb); -void lsp_build_list_nonzero_ht (u_char * start_id, u_char * stop_id, - struct list *list, dict_t * lspdb); -void lsp_build_list_ssn (struct isis_circuit *circuit, u_char num_lsps, - struct list *list, dict_t * lspdb); +void lsp_build_list(u_char *start_id, u_char *stop_id, u_char num_lsps, + struct list *list, dict_t *lspdb); +void lsp_build_list_nonzero_ht(u_char *start_id, u_char *stop_id, + struct list *list, dict_t *lspdb); +void lsp_build_list_ssn(struct isis_circuit *circuit, u_char num_lsps, + struct list *list, dict_t *lspdb); -void lsp_search_and_destroy (u_char * id, dict_t * lspdb); -void lsp_purge_pseudo (u_char * id, struct isis_circuit *circuit, int level); -void lsp_purge_non_exist (int level, - struct isis_link_state_hdr *lsp_hdr, - struct isis_area *area); +void lsp_search_and_destroy(u_char *id, dict_t *lspdb); +void lsp_purge_pseudo(u_char *id, struct isis_circuit *circuit, int level); +void lsp_purge_non_exist(int level, struct isis_link_state_hdr *lsp_hdr, + struct isis_area *area); #define LSP_EQUAL 1 #define LSP_NEWER 2 @@ -93,23 +87,22 @@ void lsp_purge_non_exist (int level, #define LSP_PSEUDO_ID(I) ((I)[ISIS_SYS_ID_LEN]) #define LSP_FRAGMENT(I) ((I)[ISIS_SYS_ID_LEN + 1]) -#define OWNLSPID(I) \ - memcpy ((I), isis->sysid, ISIS_SYS_ID_LEN);\ - (I)[ISIS_SYS_ID_LEN] = 0;\ - (I)[ISIS_SYS_ID_LEN + 1] = 0 -int lsp_id_cmp (u_char * id1, u_char * id2); -int lsp_compare (char *areatag, struct isis_lsp *lsp, u_int32_t seq_num, - u_int16_t checksum, u_int16_t rem_lifetime); -void lsp_update (struct isis_lsp *lsp, struct stream *stream, - struct isis_area *area, int level); -void lsp_inc_seqnum (struct isis_lsp *lsp, u_int32_t seq_num); -void lsp_print (struct isis_lsp *lsp, struct vty *vty, char dynhost); -void lsp_print_detail (struct isis_lsp *lsp, struct vty *vty, char dynhost); -int lsp_print_all (struct vty *vty, dict_t * lspdb, char detail, - char dynhost); -const char *lsp_bits2string (u_char *); +#define OWNLSPID(I) \ + memcpy((I), isis->sysid, ISIS_SYS_ID_LEN); \ + (I)[ISIS_SYS_ID_LEN] = 0; \ + (I)[ISIS_SYS_ID_LEN + 1] = 0 +int lsp_id_cmp(u_char *id1, u_char *id2); +int lsp_compare(char *areatag, struct isis_lsp *lsp, u_int32_t seq_num, + u_int16_t checksum, u_int16_t rem_lifetime); +void lsp_update(struct isis_lsp *lsp, struct stream *stream, + struct isis_area *area, int level); +void lsp_inc_seqnum(struct isis_lsp *lsp, u_int32_t seq_num); +void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost); +void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost); +int lsp_print_all(struct vty *vty, dict_t *lspdb, char detail, char dynhost); +const char *lsp_bits2string(u_char *); /* sets SRMflags for all active circuits of an lsp */ -void lsp_set_all_srmflags (struct isis_lsp *lsp); +void lsp_set_all_srmflags(struct isis_lsp *lsp); #endif /* ISIS_LSP */ diff --git a/isisd/isis_main.c b/isisd/isis_main.c index 674592f46..463e3abcf 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -2,17 +2,17 @@ * IS-IS Rout(e)ing protocol - isis_main.c * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -61,30 +61,24 @@ #define ISISD_VTY_PORT 2608 /* isisd privileges */ -zebra_capabilities_t _caps_p[] = { - ZCAP_NET_RAW, - ZCAP_BIND -}; +zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND}; struct zebra_privs_t isisd_privs = { #if defined(FRR_USER) - .user = FRR_USER, + .user = FRR_USER, #endif #if defined FRR_GROUP - .group = FRR_GROUP, + .group = FRR_GROUP, #endif #ifdef VTY_GROUP - .vty_group = VTY_GROUP, + .vty_group = VTY_GROUP, #endif - .caps_p = _caps_p, - .cap_num_p = sizeof (_caps_p) / sizeof (*_caps_p), - .cap_num_i = 0 -}; + .caps_p = _caps_p, + .cap_num_p = sizeof(_caps_p) / sizeof(*_caps_p), + .cap_num_i = 0}; /* isisd options */ -struct option longopts[] = { - {0} -}; +struct option longopts[] = {{0}}; /* Master of threads. */ struct thread_master *master; @@ -98,132 +92,122 @@ void sigterm(void); void sigusr1(void); -static __attribute__((__noreturn__)) void -terminate (int i) +static __attribute__((__noreturn__)) void terminate(int i) { - isis_zebra_stop (); - exit (i); + isis_zebra_stop(); + exit(i); } /* * Signal handlers */ -void -sighup (void) +void sighup(void) { - zlog_err ("SIGHUP/reload is not implemented for isisd"); - return; + zlog_err("SIGHUP/reload is not implemented for isisd"); + return; } -__attribute__((__noreturn__)) void -sigint (void) +__attribute__((__noreturn__)) void sigint(void) { - zlog_notice ("Terminating on signal SIGINT"); - terminate (0); + zlog_notice("Terminating on signal SIGINT"); + terminate(0); } -__attribute__((__noreturn__)) void -sigterm (void) +__attribute__((__noreturn__)) void sigterm(void) { - zlog_notice ("Terminating on signal SIGTERM"); - terminate (0); + zlog_notice("Terminating on signal SIGTERM"); + terminate(0); } -void -sigusr1 (void) +void sigusr1(void) { - zlog_debug ("SIGUSR1 received"); - zlog_rotate(); + zlog_debug("SIGUSR1 received"); + zlog_rotate(); } -struct quagga_signal_t isisd_signals[] = -{ - { - .signal = SIGHUP, - .handler = &sighup, - }, - { - .signal = SIGUSR1, - .handler = &sigusr1, - }, - { - .signal = SIGINT, - .handler = &sigint, - }, - { - .signal = SIGTERM, - .handler = &sigterm, - }, +struct quagga_signal_t isisd_signals[] = { + { + .signal = SIGHUP, + .handler = &sighup, + }, + { + .signal = SIGUSR1, + .handler = &sigusr1, + }, + { + .signal = SIGINT, + .handler = &sigint, + }, + { + .signal = SIGTERM, + .handler = &sigterm, + }, }; -FRR_DAEMON_INFO(isisd, ISIS, - .vty_port = ISISD_VTY_PORT, +FRR_DAEMON_INFO(isisd, ISIS, .vty_port = ISISD_VTY_PORT, - .proghelp = "Implementation of the IS-IS routing protocol.", - .copyright = "Copyright (c) 2001-2002 Sampo Saaristo," - " Ofer Wald and Hannes Gredler", + .proghelp = "Implementation of the IS-IS routing protocol.", + .copyright = + "Copyright (c) 2001-2002 Sampo Saaristo," + " Ofer Wald and Hannes Gredler", - .signals = isisd_signals, - .n_signals = array_size(isisd_signals), + .signals = isisd_signals, + .n_signals = array_size(isisd_signals), - .privs = &isisd_privs, -) + .privs = &isisd_privs, ) /* * Main routine of isisd. Parse arguments and handle IS-IS state machine. */ -int -main (int argc, char **argv, char **envp) +int main(int argc, char **argv, char **envp) { - int opt; + int opt; - frr_preinit (&isisd_di, argc, argv); - frr_opt_add ("", longopts, ""); + frr_preinit(&isisd_di, argc, argv); + frr_opt_add("", longopts, ""); - /* Command line argument treatment. */ - while (1) - { - opt = frr_getopt (argc, argv, NULL); + /* Command line argument treatment. */ + while (1) { + opt = frr_getopt(argc, argv, NULL); - if (opt == EOF) - break; + if (opt == EOF) + break; - switch (opt) - { - case 0: - break; - default: - frr_help_exit (1); - break; + switch (opt) { + case 0: + break; + default: + frr_help_exit(1); + break; + } } - } - - vty_config_lockless (); - /* thread master */ - master = frr_init (); - - /* - * initializations - */ - access_list_init(); - vrf_init (NULL, NULL, NULL, NULL); - prefix_list_init(); - isis_init (); - isis_circuit_init (); - isis_spf_cmds_init (); - isis_redist_init (); - isis_route_map_init(); - isis_mpls_te_init(); - - /* create the global 'isis' instance */ - isis_new (1); - - isis_zebra_init(master); - - frr_config_fork (); - frr_run (master); - - /* Not reached. */ - exit (0); + + vty_config_lockless(); + /* thread master */ + master = frr_init(); + + /* + * initializations + */ + access_list_init(); + vrf_init(NULL, NULL, NULL, NULL); + prefix_list_init(); + isis_init(); + isis_circuit_init(); + isis_spf_cmds_init(); + isis_redist_init(); + isis_route_map_init(); + isis_mpls_te_init(); + + /* create the global 'isis' instance */ + isis_new(1); + + isis_zebra_init(master); + + frr_config_fork(); + frr_run(master); + + /* Not reached. */ + exit(0); } diff --git a/isisd/isis_memory.c b/isisd/isis_memory.c index 101fdcc69..4ad26cf91 100644 --- a/isisd/isis_memory.c +++ b/isisd/isis_memory.c @@ -26,22 +26,22 @@ #include "isis_memory.h" DEFINE_MGROUP(ISISD, "isisd") -DEFINE_MTYPE(ISISD, ISIS, "ISIS") -DEFINE_MTYPE(ISISD, ISIS_TMP, "ISIS TMP") -DEFINE_MTYPE(ISISD, ISIS_CIRCUIT, "ISIS circuit") -DEFINE_MTYPE(ISISD, ISIS_LSP, "ISIS LSP") -DEFINE_MTYPE(ISISD, ISIS_ADJACENCY, "ISIS adjacency") -DEFINE_MTYPE(ISISD, ISIS_AREA, "ISIS area") -DEFINE_MTYPE(ISISD, ISIS_AREA_ADDR, "ISIS area address") -DEFINE_MTYPE(ISISD, ISIS_TLV, "ISIS TLV") -DEFINE_MTYPE(ISISD, ISIS_DYNHN, "ISIS dyn hostname") -DEFINE_MTYPE(ISISD, ISIS_SPFTREE, "ISIS SPFtree") -DEFINE_MTYPE(ISISD, ISIS_VERTEX, "ISIS vertex") -DEFINE_MTYPE(ISISD, ISIS_ROUTE_INFO, "ISIS route info") -DEFINE_MTYPE(ISISD, ISIS_NEXTHOP, "ISIS nexthop") -DEFINE_MTYPE(ISISD, ISIS_NEXTHOP6, "ISIS nexthop6") -DEFINE_MTYPE(ISISD, ISIS_DICT, "ISIS dictionary") -DEFINE_MTYPE(ISISD, ISIS_DICT_NODE, "ISIS dictionary node") -DEFINE_MTYPE(ISISD, ISIS_EXT_ROUTE, "ISIS redistributed route") -DEFINE_MTYPE(ISISD, ISIS_EXT_INFO, "ISIS redistributed route info") -DEFINE_MTYPE(ISISD, ISIS_MPLS_TE, "ISIS MPLS_TE parameters") +DEFINE_MTYPE(ISISD, ISIS, "ISIS") +DEFINE_MTYPE(ISISD, ISIS_TMP, "ISIS TMP") +DEFINE_MTYPE(ISISD, ISIS_CIRCUIT, "ISIS circuit") +DEFINE_MTYPE(ISISD, ISIS_LSP, "ISIS LSP") +DEFINE_MTYPE(ISISD, ISIS_ADJACENCY, "ISIS adjacency") +DEFINE_MTYPE(ISISD, ISIS_AREA, "ISIS area") +DEFINE_MTYPE(ISISD, ISIS_AREA_ADDR, "ISIS area address") +DEFINE_MTYPE(ISISD, ISIS_TLV, "ISIS TLV") +DEFINE_MTYPE(ISISD, ISIS_DYNHN, "ISIS dyn hostname") +DEFINE_MTYPE(ISISD, ISIS_SPFTREE, "ISIS SPFtree") +DEFINE_MTYPE(ISISD, ISIS_VERTEX, "ISIS vertex") +DEFINE_MTYPE(ISISD, ISIS_ROUTE_INFO, "ISIS route info") +DEFINE_MTYPE(ISISD, ISIS_NEXTHOP, "ISIS nexthop") +DEFINE_MTYPE(ISISD, ISIS_NEXTHOP6, "ISIS nexthop6") +DEFINE_MTYPE(ISISD, ISIS_DICT, "ISIS dictionary") +DEFINE_MTYPE(ISISD, ISIS_DICT_NODE, "ISIS dictionary node") +DEFINE_MTYPE(ISISD, ISIS_EXT_ROUTE, "ISIS redistributed route") +DEFINE_MTYPE(ISISD, ISIS_EXT_INFO, "ISIS redistributed route info") +DEFINE_MTYPE(ISISD, ISIS_MPLS_TE, "ISIS MPLS_TE parameters") diff --git a/isisd/isis_misc.c b/isisd/isis_misc.c index 3869159a0..16c789ff5 100644 --- a/isisd/isis_misc.c +++ b/isisd/isis_misc.c @@ -3,17 +3,17 @@ * Miscellanous routines * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -62,147 +62,121 @@ char nlpidstring[30]; /* * This converts the isonet to its printable format */ -const char * -isonet_print (const u_char * from, int len) +const char *isonet_print(const u_char *from, int len) { - int i = 0; - char *pos = isonet; - - if (!from) - return "unknown"; - - while (i < len) - { - if (i & 1) - { - sprintf (pos, "%02x", *(from + i)); - pos += 2; + int i = 0; + char *pos = isonet; + + if (!from) + return "unknown"; + + while (i < len) { + if (i & 1) { + sprintf(pos, "%02x", *(from + i)); + pos += 2; + } else { + if (i == (len - 1)) { /* No dot at the end of address */ + sprintf(pos, "%02x", *(from + i)); + pos += 2; + } else { + sprintf(pos, "%02x.", *(from + i)); + pos += 3; + } + } + i++; } - else - { - if (i == (len - 1)) - { /* No dot at the end of address */ - sprintf (pos, "%02x", *(from + i)); - pos += 2; - } - else - { - sprintf (pos, "%02x.", *(from + i)); - pos += 3; - } - } - i++; - } - *(pos) = '\0'; - return isonet; + *(pos) = '\0'; + return isonet; } /* * Returns 0 on error, length of buff on ok - * extract dot from the dotted str, and insert all the number in a buff + * extract dot from the dotted str, and insert all the number in a buff */ -int -dotformat2buff (u_char * buff, const char * dotted) +int dotformat2buff(u_char *buff, const char *dotted) { - int dotlen, len = 0; - const char *pos = dotted; - u_char number[3]; - int nextdotpos = 2; - - number[2] = '\0'; - dotlen = strlen(dotted); - if (dotlen > 50) - { - /* this can't be an iso net, its too long */ - return 0; - } - - while ((pos - dotted) < dotlen && len < 20) - { - if (*pos == '.') - { - /* we expect the . at 2, and than every 5 */ - if ((pos - dotted) != nextdotpos) - { - len = 0; - break; - } - nextdotpos += 5; - pos++; - continue; - } - /* we must have at least two chars left here */ - if (dotlen - (pos - dotted) < 2) - { - len = 0; - break; + int dotlen, len = 0; + const char *pos = dotted; + u_char number[3]; + int nextdotpos = 2; + + number[2] = '\0'; + dotlen = strlen(dotted); + if (dotlen > 50) { + /* this can't be an iso net, its too long */ + return 0; } - if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1)))) - { - memcpy (number, pos, 2); - pos += 2; + while ((pos - dotted) < dotlen && len < 20) { + if (*pos == '.') { + /* we expect the . at 2, and than every 5 */ + if ((pos - dotted) != nextdotpos) { + len = 0; + break; + } + nextdotpos += 5; + pos++; + continue; + } + /* we must have at least two chars left here */ + if (dotlen - (pos - dotted) < 2) { + len = 0; + break; + } + + if ((isxdigit((int)*pos)) && (isxdigit((int)*(pos + 1)))) { + memcpy(number, pos, 2); + pos += 2; + } else { + len = 0; + break; + } + + *(buff + len) = (char)strtol((char *)number, NULL, 16); + len++; } - else - { - len = 0; - break; - } - - *(buff + len) = (char) strtol ((char *)number, NULL, 16); - len++; - } - return len; + return len; } /* * conversion of XXXX.XXXX.XXXX to memory */ -int -sysid2buff (u_char * buff, const char * dotted) +int sysid2buff(u_char *buff, const char *dotted) { - int len = 0; - const char *pos = dotted; - u_char number[3]; - - number[2] = '\0'; - // surely not a sysid_string if not 14 length - if (strlen (dotted) != 14) - { - return 0; - } - - while (len < ISIS_SYS_ID_LEN) - { - if (*pos == '.') - { - /* the . is not positioned correctly */ - if (((pos - dotted) != 4) && ((pos - dotted) != 9)) - { - len = 0; - break; - } - pos++; - continue; - } - if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1)))) - { - memcpy (number, pos, 2); - pos += 2; - } - else - { - len = 0; - break; + int len = 0; + const char *pos = dotted; + u_char number[3]; + + number[2] = '\0'; + // surely not a sysid_string if not 14 length + if (strlen(dotted) != 14) { + return 0; } - *(buff + len) = (char) strtol ((char *)number, NULL, 16); - len++; - } - - return len; + while (len < ISIS_SYS_ID_LEN) { + if (*pos == '.') { + /* the . is not positioned correctly */ + if (((pos - dotted) != 4) && ((pos - dotted) != 9)) { + len = 0; + break; + } + pos++; + continue; + } + if ((isxdigit((int)*pos)) && (isxdigit((int)*(pos + 1)))) { + memcpy(number, pos, 2); + pos += 2; + } else { + len = 0; + break; + } + + *(buff + len) = (char)strtol((char *)number, NULL, 16); + len++; + } + return len; } /* @@ -210,280 +184,251 @@ sysid2buff (u_char * buff, const char * dotted) * into a string */ -char * -nlpid2string (struct nlpids *nlpids) +char *nlpid2string(struct nlpids *nlpids) { - char *pos = nlpidstring; - int i; - - for (i = 0; i < nlpids->count; i++) - { - switch (nlpids->nlpids[i]) - { - case NLPID_IP: - pos += sprintf (pos, "IPv4"); - break; - case NLPID_IPV6: - pos += sprintf (pos, "IPv6"); - break; - case NLPID_SNAP: - pos += sprintf (pos, "SNAP"); - break; - case NLPID_CLNP: - pos += sprintf (pos, "CLNP"); - break; - case NLPID_ESIS: - pos += sprintf (pos, "ES-IS"); - break; - default: - pos += sprintf (pos, "unknown"); - break; + char *pos = nlpidstring; + int i; + + for (i = 0; i < nlpids->count; i++) { + switch (nlpids->nlpids[i]) { + case NLPID_IP: + pos += sprintf(pos, "IPv4"); + break; + case NLPID_IPV6: + pos += sprintf(pos, "IPv6"); + break; + case NLPID_SNAP: + pos += sprintf(pos, "SNAP"); + break; + case NLPID_CLNP: + pos += sprintf(pos, "CLNP"); + break; + case NLPID_ESIS: + pos += sprintf(pos, "ES-IS"); + break; + default: + pos += sprintf(pos, "unknown"); + break; + } + if (nlpids->count - i > 1) + pos += sprintf(pos, ", "); } - if (nlpids->count - i > 1) - pos += sprintf (pos, ", "); - - } - *(pos) = '\0'; + *(pos) = '\0'; - return nlpidstring; + return nlpidstring; } /* * supports the given af ? */ -int -speaks (struct nlpids *nlpids, int family) +int speaks(struct nlpids *nlpids, int family) { - int i, speaks = 0; - - if (nlpids == (struct nlpids *) NULL) - return speaks; - for (i = 0; i < nlpids->count; i++) - { - if (family == AF_INET && nlpids->nlpids[i] == NLPID_IP) - speaks = 1; - if (family == AF_INET6 && nlpids->nlpids[i] == NLPID_IPV6) - speaks = 1; - } - - return speaks; + int i, speaks = 0; + + if (nlpids == (struct nlpids *)NULL) + return speaks; + for (i = 0; i < nlpids->count; i++) { + if (family == AF_INET && nlpids->nlpids[i] == NLPID_IP) + speaks = 1; + if (family == AF_INET6 && nlpids->nlpids[i] == NLPID_IPV6) + speaks = 1; + } + + return speaks; } /* * Returns 0 on error, IS-IS Circuit Type on ok */ -int -string2circuit_t (const char * str) +int string2circuit_t(const char *str) { - if (!str) - return 0; + if (!str) + return 0; - if (!strcmp (str, "level-1")) - return IS_LEVEL_1; + if (!strcmp(str, "level-1")) + return IS_LEVEL_1; - if (!strcmp (str, "level-2-only") || !strcmp (str, "level-2")) - return IS_LEVEL_2; + if (!strcmp(str, "level-2-only") || !strcmp(str, "level-2")) + return IS_LEVEL_2; - if (!strcmp (str, "level-1-2")) - return IS_LEVEL_1_AND_2; + if (!strcmp(str, "level-1-2")) + return IS_LEVEL_1_AND_2; - return 0; + return 0; } -const char * -circuit_state2string (int state) +const char *circuit_state2string(int state) { - switch (state) - { - case C_STATE_INIT: - return "Init"; - case C_STATE_CONF: - return "Config"; - case C_STATE_UP: - return "Up"; - default: - return "Unknown"; - } - return NULL; + switch (state) { + case C_STATE_INIT: + return "Init"; + case C_STATE_CONF: + return "Config"; + case C_STATE_UP: + return "Up"; + default: + return "Unknown"; + } + return NULL; } -const char * -circuit_type2string (int type) +const char *circuit_type2string(int type) { - switch (type) - { - case CIRCUIT_T_P2P: - return "p2p"; - case CIRCUIT_T_BROADCAST: - return "lan"; - case CIRCUIT_T_LOOPBACK: - return "loopback"; - default: - return "Unknown"; - } - return NULL; + switch (type) { + case CIRCUIT_T_P2P: + return "p2p"; + case CIRCUIT_T_BROADCAST: + return "lan"; + case CIRCUIT_T_LOOPBACK: + return "loopback"; + default: + return "Unknown"; + } + return NULL; } -const char * -circuit_t2string (int circuit_t) +const char *circuit_t2string(int circuit_t) { - switch (circuit_t) - { - case IS_LEVEL_1: - return "L1"; - case IS_LEVEL_2: - return "L2"; - case IS_LEVEL_1_AND_2: - return "L1L2"; - default: - return "??"; - } - - return NULL; /* not reached */ + switch (circuit_t) { + case IS_LEVEL_1: + return "L1"; + case IS_LEVEL_2: + return "L2"; + case IS_LEVEL_1_AND_2: + return "L1L2"; + default: + return "??"; + } + + return NULL; /* not reached */ } -const char * -syst2string (int type) +const char *syst2string(int type) { - switch (type) - { - case ISIS_SYSTYPE_ES: - return "ES"; - case ISIS_SYSTYPE_IS: - return "IS"; - case ISIS_SYSTYPE_L1_IS: - return "1"; - case ISIS_SYSTYPE_L2_IS: - return "2"; - default: - return "??"; - } - - return NULL; /* not reached */ + switch (type) { + case ISIS_SYSTYPE_ES: + return "ES"; + case ISIS_SYSTYPE_IS: + return "IS"; + case ISIS_SYSTYPE_L1_IS: + return "1"; + case ISIS_SYSTYPE_L2_IS: + return "2"; + default: + return "??"; + } + + return NULL; /* not reached */ } /* * Print functions - we print to static vars */ -const char * -snpa_print (const u_char * from) +const char *snpa_print(const u_char *from) { - int i = 0; - u_char *pos = (u_char *)snpa; - - if (!from) - return "unknown"; - - while (i < ETH_ALEN - 1) - { - if (i & 1) - { - sprintf ((char *)pos, "%02x.", *(from + i)); - pos += 3; + int i = 0; + u_char *pos = (u_char *)snpa; + + if (!from) + return "unknown"; + + while (i < ETH_ALEN - 1) { + if (i & 1) { + sprintf((char *)pos, "%02x.", *(from + i)); + pos += 3; + } else { + sprintf((char *)pos, "%02x", *(from + i)); + pos += 2; + } + i++; } - else - { - sprintf ((char *)pos, "%02x", *(from + i)); - pos += 2; - } - i++; - } - - sprintf ((char *)pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1))); - pos += 2; - *(pos) = '\0'; + sprintf((char *)pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1))); + pos += 2; + *(pos) = '\0'; - return snpa; + return snpa; } -const char * -sysid_print (const u_char * from) +const char *sysid_print(const u_char *from) { - int i = 0; - char *pos = sysid; - - if (!from) - return "unknown"; - - while (i < ISIS_SYS_ID_LEN - 1) - { - if (i & 1) - { - sprintf (pos, "%02x.", *(from + i)); - pos += 3; - } - else - { - sprintf (pos, "%02x", *(from + i)); - pos += 2; - + int i = 0; + char *pos = sysid; + + if (!from) + return "unknown"; + + while (i < ISIS_SYS_ID_LEN - 1) { + if (i & 1) { + sprintf(pos, "%02x.", *(from + i)); + pos += 3; + } else { + sprintf(pos, "%02x", *(from + i)); + pos += 2; + } + i++; } - i++; - } - sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1))); - pos += 2; - *(pos) = '\0'; + sprintf(pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1))); + pos += 2; + *(pos) = '\0'; - return sysid; + return sysid; } -const char * -rawlspid_print (const u_char * from) +const char *rawlspid_print(const u_char *from) { - char *pos = lspid; - if (!from) - return "unknown"; - memcpy (pos, sysid_print (from), 15); - pos += 14; - sprintf (pos, ".%02x", LSP_PSEUDO_ID (from)); - pos += 3; - sprintf (pos, "-%02x", LSP_FRAGMENT (from)); - pos += 3; - - *(pos) = '\0'; - - return lspid; + char *pos = lspid; + if (!from) + return "unknown"; + memcpy(pos, sysid_print(from), 15); + pos += 14; + sprintf(pos, ".%02x", LSP_PSEUDO_ID(from)); + pos += 3; + sprintf(pos, "-%02x", LSP_FRAGMENT(from)); + pos += 3; + + *(pos) = '\0'; + + return lspid; } -const char * -time2string (u_int32_t time) +const char *time2string(u_int32_t time) { - char *pos = datestring; - u_int32_t rest; - - if (time == 0) - return "-"; - - if (time / SECS_PER_YEAR) - pos += sprintf (pos, "%uY", time / SECS_PER_YEAR); - rest = time % SECS_PER_YEAR; - if (rest / SECS_PER_MONTH) - pos += sprintf (pos, "%uM", rest / SECS_PER_MONTH); - rest = rest % SECS_PER_MONTH; - if (rest / SECS_PER_WEEK) - pos += sprintf (pos, "%uw", rest / SECS_PER_WEEK); - rest = rest % SECS_PER_WEEK; - if (rest / SECS_PER_DAY) - pos += sprintf (pos, "%ud", rest / SECS_PER_DAY); - rest = rest % SECS_PER_DAY; - if (rest / SECS_PER_HOUR) - pos += sprintf (pos, "%uh", rest / SECS_PER_HOUR); - rest = rest % SECS_PER_HOUR; - if (rest / SECS_PER_MINUTE) - pos += sprintf (pos, "%um", rest / SECS_PER_MINUTE); - rest = rest % SECS_PER_MINUTE; - if (rest) - pos += sprintf (pos, "%us", rest); - - *(pos) = 0; - - return datestring; + char *pos = datestring; + u_int32_t rest; + + if (time == 0) + return "-"; + + if (time / SECS_PER_YEAR) + pos += sprintf(pos, "%uY", time / SECS_PER_YEAR); + rest = time % SECS_PER_YEAR; + if (rest / SECS_PER_MONTH) + pos += sprintf(pos, "%uM", rest / SECS_PER_MONTH); + rest = rest % SECS_PER_MONTH; + if (rest / SECS_PER_WEEK) + pos += sprintf(pos, "%uw", rest / SECS_PER_WEEK); + rest = rest % SECS_PER_WEEK; + if (rest / SECS_PER_DAY) + pos += sprintf(pos, "%ud", rest / SECS_PER_DAY); + rest = rest % SECS_PER_DAY; + if (rest / SECS_PER_HOUR) + pos += sprintf(pos, "%uh", rest / SECS_PER_HOUR); + rest = rest % SECS_PER_HOUR; + if (rest / SECS_PER_MINUTE) + pos += sprintf(pos, "%um", rest / SECS_PER_MINUTE); + rest = rest % SECS_PER_MINUTE; + if (rest) + pos += sprintf(pos, "%us", rest); + + *(pos) = 0; + + return datestring; } /* @@ -493,141 +438,137 @@ time2string (u_int32_t time) * first argument is the timer and the second is * the jitter */ -unsigned long -isis_jitter (unsigned long timer, unsigned long jitter) +unsigned long isis_jitter(unsigned long timer, unsigned long jitter) { - int j, k; + int j, k; - if (jitter >= 100) - return timer; + if (jitter >= 100) + return timer; - if (timer == 1) - return timer; - /* - * randomizing just the percent value provides - * no good random numbers - hence the spread - * to RANDOM_SPREAD (100000), which is ok as - * most IS-IS timers are no longer than 16 bit - */ + if (timer == 1) + return timer; + /* + * randomizing just the percent value provides + * no good random numbers - hence the spread + * to RANDOM_SPREAD (100000), which is ok as + * most IS-IS timers are no longer than 16 bit + */ - j = 1 + (int) ((RANDOM_SPREAD * random ()) / (RAND_MAX + 1.0)); + j = 1 + (int)((RANDOM_SPREAD * random()) / (RAND_MAX + 1.0)); - k = timer - (timer * (100 - jitter)) / 100; + k = timer - (timer * (100 - jitter)) / 100; - timer = timer - (k * j / RANDOM_SPREAD); + timer = timer - (k * j / RANDOM_SPREAD); - return timer; + return timer; } -struct in_addr -newprefix2inaddr (u_char * prefix_start, u_char prefix_masklen) +struct in_addr newprefix2inaddr(u_char *prefix_start, u_char prefix_masklen) { - memset (&new_prefix, 0, sizeof (new_prefix)); - memcpy (&new_prefix, prefix_start, (prefix_masklen & 0x3F) ? - ((((prefix_masklen & 0x3F) - 1) >> 3) + 1) : 0); - return new_prefix; + memset(&new_prefix, 0, sizeof(new_prefix)); + memcpy(&new_prefix, prefix_start, + (prefix_masklen & 0x3F) + ? ((((prefix_masklen & 0x3F) - 1) >> 3) + 1) + : 0); + return new_prefix; } /* * Returns host.name if any, otherwise * it returns the system hostname. */ -const char * -unix_hostname (void) +const char *unix_hostname(void) { - static struct utsname names; - const char *hostname; + static struct utsname names; + const char *hostname; - hostname = host.name; - if (!hostname) - { - uname (&names); - hostname = names.nodename; - } + hostname = host.name; + if (!hostname) { + uname(&names); + hostname = names.nodename; + } - return hostname; + return hostname; } /* * Returns the dynamic hostname associated with the passed system ID. * If no dynamic hostname found then returns formatted system ID. */ -const char * -print_sys_hostname (const u_char *sysid) +const char *print_sys_hostname(const u_char *sysid) { - struct isis_dynhn *dyn; + struct isis_dynhn *dyn; - if (!sysid) - return "nullsysid"; + if (!sysid) + return "nullsysid"; - /* For our system ID return our host name */ - if (memcmp(sysid, isis->sysid, ISIS_SYS_ID_LEN) == 0) - return unix_hostname(); + /* For our system ID return our host name */ + if (memcmp(sysid, isis->sysid, ISIS_SYS_ID_LEN) == 0) + return unix_hostname(); - dyn = dynhn_find_by_id (sysid); - if (dyn) - return (const char *)dyn->name.name; + dyn = dynhn_find_by_id(sysid); + if (dyn) + return (const char *)dyn->name.name; - return sysid_print (sysid); + return sysid_print(sysid); } /* * This function is a generic utility that logs data of given length. * Move this to a shared lib so that any protocol can use it. */ -void -zlog_dump_data (void *data, int len) +void zlog_dump_data(void *data, int len) { - int i; - unsigned char *p; - unsigned char c; - char bytestr[4]; - char addrstr[10]; - char hexstr[ 16*3 + 5]; - char charstr[16*1 + 5]; - - p = data; - memset (bytestr, 0, sizeof(bytestr)); - memset (addrstr, 0, sizeof(addrstr)); - memset (hexstr, 0, sizeof(hexstr)); - memset (charstr, 0, sizeof(charstr)); - - for (i = 1; i <= len; i++) - { - c = *p; - if (isalnum (c) == 0) - c = '.'; - - /* store address for this line */ - if ((i % 16) == 1) - snprintf (addrstr, sizeof(addrstr), "%p", p); - - /* store hex str (for left side) */ - snprintf (bytestr, sizeof (bytestr), "%02X ", *p); - strncat (hexstr, bytestr, sizeof (hexstr) - strlen (hexstr) - 1); - - /* store char str (for right side) */ - snprintf (bytestr, sizeof (bytestr), "%c", c); - strncat (charstr, bytestr, sizeof (charstr) - strlen (charstr) - 1); - - if ((i % 16) == 0) - { - /* line completed */ - zlog_debug ("[%8.8s] %-50.50s %s", addrstr, hexstr, charstr); - hexstr[0] = 0; - charstr[0] = 0; - } - else if ((i % 8) == 0) - { - /* half line: add whitespaces */ - strncat (hexstr, " ", sizeof (hexstr) - strlen (hexstr) - 1); - strncat (charstr, " ", sizeof (charstr) - strlen (charstr) - 1); - } - p++; /* next byte */ - } - - /* print rest of buffer if not empty */ - if (strlen (hexstr) > 0) - zlog_debug ("[%8.8s] %-50.50s %s", addrstr, hexstr, charstr); - return; + int i; + unsigned char *p; + unsigned char c; + char bytestr[4]; + char addrstr[10]; + char hexstr[16 * 3 + 5]; + char charstr[16 * 1 + 5]; + + p = data; + memset(bytestr, 0, sizeof(bytestr)); + memset(addrstr, 0, sizeof(addrstr)); + memset(hexstr, 0, sizeof(hexstr)); + memset(charstr, 0, sizeof(charstr)); + + for (i = 1; i <= len; i++) { + c = *p; + if (isalnum(c) == 0) + c = '.'; + + /* store address for this line */ + if ((i % 16) == 1) + snprintf(addrstr, sizeof(addrstr), "%p", p); + + /* store hex str (for left side) */ + snprintf(bytestr, sizeof(bytestr), "%02X ", *p); + strncat(hexstr, bytestr, sizeof(hexstr) - strlen(hexstr) - 1); + + /* store char str (for right side) */ + snprintf(bytestr, sizeof(bytestr), "%c", c); + strncat(charstr, bytestr, + sizeof(charstr) - strlen(charstr) - 1); + + if ((i % 16) == 0) { + /* line completed */ + zlog_debug("[%8.8s] %-50.50s %s", addrstr, hexstr, + charstr); + hexstr[0] = 0; + charstr[0] = 0; + } else if ((i % 8) == 0) { + /* half line: add whitespaces */ + strncat(hexstr, " ", + sizeof(hexstr) - strlen(hexstr) - 1); + strncat(charstr, " ", + sizeof(charstr) - strlen(charstr) - 1); + } + p++; /* next byte */ + } + + /* print rest of buffer if not empty */ + if (strlen(hexstr) > 0) + zlog_debug("[%8.8s] %-50.50s %s", addrstr, hexstr, charstr); + return; } diff --git a/isisd/isis_misc.h b/isisd/isis_misc.h index a71edd8e6..12ab0fac1 100644 --- a/isisd/isis_misc.h +++ b/isisd/isis_misc.h @@ -3,17 +3,17 @@ * Miscellanous routines * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -24,45 +24,44 @@ #ifndef _ZEBRA_ISIS_MISC_H #define _ZEBRA_ISIS_MISC_H -int string2circuit_t (const char *); -const char *circuit_t2string (int); -const char *circuit_state2string (int state); -const char *circuit_type2string (int type); -const char *syst2string (int); -struct in_addr newprefix2inaddr (u_char * prefix_start, - u_char prefix_masklen); +int string2circuit_t(const char *); +const char *circuit_t2string(int); +const char *circuit_state2string(int state); +const char *circuit_type2string(int type); +const char *syst2string(int); +struct in_addr newprefix2inaddr(u_char *prefix_start, u_char prefix_masklen); /* * Converting input to memory stored format * return value of 0 indicates wrong input */ -int dotformat2buff (u_char *, const char *); -int sysid2buff (u_char *, const char *); +int dotformat2buff(u_char *, const char *); +int sysid2buff(u_char *, const char *); /* * Printing functions */ -const char *isonet_print (const u_char *, int len); -const char *sysid_print (const u_char *); -const char *snpa_print (const u_char *); -const char *rawlspid_print (const u_char *); -const char *time2string (u_int32_t); +const char *isonet_print(const u_char *, int len); +const char *sysid_print(const u_char *); +const char *snpa_print(const u_char *); +const char *rawlspid_print(const u_char *); +const char *time2string(u_int32_t); /* typedef struct nlpids nlpids; */ -char *nlpid2string (struct nlpids *); -const char *print_sys_hostname (const u_char *sysid); -void zlog_dump_data (void *data, int len); +char *nlpid2string(struct nlpids *); +const char *print_sys_hostname(const u_char *sysid); +void zlog_dump_data(void *data, int len); /* * misc functions */ -int speaks (struct nlpids *nlpids, int family); -unsigned long isis_jitter (unsigned long timer, unsigned long jitter); -const char *unix_hostname (void); +int speaks(struct nlpids *nlpids, int family); +unsigned long isis_jitter(unsigned long timer, unsigned long jitter); +const char *unix_hostname(void); /* * macros */ -#define GETSYSID(A) (A->area_addr + (A->addr_len - \ - (ISIS_SYS_ID_LEN + ISIS_NSEL_LEN))) +#define GETSYSID(A) \ + (A->area_addr + (A->addr_len - (ISIS_SYS_ID_LEN + ISIS_NSEL_LEN))) /* used for calculating nice string representation instead of plain seconds */ @@ -73,11 +72,9 @@ const char *unix_hostname (void); #define SECS_PER_MONTH 2628000 #define SECS_PER_YEAR 31536000 -enum -{ - ISIS_UI_LEVEL_BRIEF, - ISIS_UI_LEVEL_DETAIL, - ISIS_UI_LEVEL_EXTENSIVE, +enum { ISIS_UI_LEVEL_BRIEF, + ISIS_UI_LEVEL_DETAIL, + ISIS_UI_LEVEL_EXTENSIVE, }; #endif diff --git a/isisd/isis_mt.c b/isisd/isis_mt.c index 26e02498b..46b57510a 100644 --- a/isisd/isis_mt.c +++ b/isisd/isis_mt.c @@ -33,59 +33,60 @@ DEFINE_MTYPE_STATIC(ISISD, MT_AREA_SETTING, "ISIS MT Area Setting") DEFINE_MTYPE_STATIC(ISISD, MT_CIRCUIT_SETTING, "ISIS MT Circuit Setting") DEFINE_MTYPE_STATIC(ISISD, MT_ADJ_INFO, "ISIS MT Adjacency Info") DEFINE_MTYPE_STATIC(ISISD, MT_NEIGHBORS, "ISIS MT Neighbors for TLV") -DEFINE_MTYPE_STATIC(ISISD, MT_IPV4_REACHS, "ISIS MT IPv4 Reachabilities for TLV") -DEFINE_MTYPE_STATIC(ISISD, MT_IPV6_REACHS, "ISIS MT IPv6 Reachabilities for TLV") +DEFINE_MTYPE_STATIC(ISISD, MT_IPV4_REACHS, + "ISIS MT IPv4 Reachabilities for TLV") +DEFINE_MTYPE_STATIC(ISISD, MT_IPV6_REACHS, + "ISIS MT IPv6 Reachabilities for TLV") uint16_t isis_area_ipv6_topology(struct isis_area *area) { - struct isis_area_mt_setting *area_mt_setting; - area_mt_setting = area_lookup_mt_setting(area, ISIS_MT_IPV6_UNICAST); + struct isis_area_mt_setting *area_mt_setting; + area_mt_setting = area_lookup_mt_setting(area, ISIS_MT_IPV6_UNICAST); - if (area_mt_setting && area_mt_setting->enabled) - return ISIS_MT_IPV6_UNICAST; - return ISIS_MT_IPV4_UNICAST; + if (area_mt_setting && area_mt_setting->enabled) + return ISIS_MT_IPV6_UNICAST; + return ISIS_MT_IPV4_UNICAST; } /* MT naming api */ const char *isis_mtid2str(uint16_t mtid) { - static char buf[sizeof("65535")]; - - switch(mtid) - { - case ISIS_MT_IPV4_UNICAST: - return "ipv4-unicast"; - case ISIS_MT_IPV4_MGMT: - return "ipv4-mgmt"; - case ISIS_MT_IPV6_UNICAST: - return "ipv6-unicast"; - case ISIS_MT_IPV4_MULTICAST: - return "ipv4-multicast"; - case ISIS_MT_IPV6_MULTICAST: - return "ipv6-multicast"; - case ISIS_MT_IPV6_MGMT: - return "ipv6-mgmt"; - default: - snprintf(buf, sizeof(buf), "%" PRIu16, mtid); - return buf; - } + static char buf[sizeof("65535")]; + + switch (mtid) { + case ISIS_MT_IPV4_UNICAST: + return "ipv4-unicast"; + case ISIS_MT_IPV4_MGMT: + return "ipv4-mgmt"; + case ISIS_MT_IPV6_UNICAST: + return "ipv6-unicast"; + case ISIS_MT_IPV4_MULTICAST: + return "ipv4-multicast"; + case ISIS_MT_IPV6_MULTICAST: + return "ipv6-multicast"; + case ISIS_MT_IPV6_MGMT: + return "ipv6-mgmt"; + default: + snprintf(buf, sizeof(buf), "%" PRIu16, mtid); + return buf; + } } uint16_t isis_str2mtid(const char *name) { - if (!strcmp(name,"ipv4-unicast")) - return ISIS_MT_IPV4_UNICAST; - if (!strcmp(name,"ipv4-mgmt")) - return ISIS_MT_IPV4_MGMT; - if (!strcmp(name,"ipv6-unicast")) - return ISIS_MT_IPV6_UNICAST; - if (!strcmp(name,"ipv4-multicast")) - return ISIS_MT_IPV4_MULTICAST; - if (!strcmp(name,"ipv6-multicast")) - return ISIS_MT_IPV6_MULTICAST; - if (!strcmp(name,"ipv6-mgmt")) - return ISIS_MT_IPV6_MGMT; - return -1; + if (!strcmp(name, "ipv4-unicast")) + return ISIS_MT_IPV4_UNICAST; + if (!strcmp(name, "ipv4-mgmt")) + return ISIS_MT_IPV4_MGMT; + if (!strcmp(name, "ipv6-unicast")) + return ISIS_MT_IPV6_UNICAST; + if (!strcmp(name, "ipv4-multicast")) + return ISIS_MT_IPV4_MULTICAST; + if (!strcmp(name, "ipv6-multicast")) + return ISIS_MT_IPV6_MULTICAST; + if (!strcmp(name, "ipv6-mgmt")) + return ISIS_MT_IPV6_MGMT; + return -1; } /* General MT settings api */ @@ -94,649 +95,603 @@ struct mt_setting { ISIS_MT_INFO_FIELDS; }; -static void * -lookup_mt_setting(struct list *mt_list, uint16_t mtid) +static void *lookup_mt_setting(struct list *mt_list, uint16_t mtid) { - struct listnode *node; - struct mt_setting *setting; + struct listnode *node; + struct mt_setting *setting; - for (ALL_LIST_ELEMENTS_RO(mt_list, node, setting)) - { - if (setting->mtid == mtid) - return setting; - } - return NULL; + for (ALL_LIST_ELEMENTS_RO(mt_list, node, setting)) { + if (setting->mtid == mtid) + return setting; + } + return NULL; } -static void -add_mt_setting(struct list **mt_list, void *setting) +static void add_mt_setting(struct list **mt_list, void *setting) { - if (!*mt_list) - *mt_list = list_new(); - listnode_add(*mt_list, setting); + if (!*mt_list) + *mt_list = list_new(); + listnode_add(*mt_list, setting); } /* Area specific MT settings api */ -struct isis_area_mt_setting* -area_lookup_mt_setting(struct isis_area *area, uint16_t mtid) +struct isis_area_mt_setting *area_lookup_mt_setting(struct isis_area *area, + uint16_t mtid) { - return lookup_mt_setting(area->mt_settings, mtid); + return lookup_mt_setting(area->mt_settings, mtid); } -struct isis_area_mt_setting* -area_new_mt_setting(struct isis_area *area, uint16_t mtid) +struct isis_area_mt_setting *area_new_mt_setting(struct isis_area *area, + uint16_t mtid) { - struct isis_area_mt_setting *setting; + struct isis_area_mt_setting *setting; - setting = XCALLOC(MTYPE_MT_AREA_SETTING, sizeof(*setting)); - setting->mtid = mtid; - return setting; + setting = XCALLOC(MTYPE_MT_AREA_SETTING, sizeof(*setting)); + setting->mtid = mtid; + return setting; } -static void -area_free_mt_setting(void *setting) +static void area_free_mt_setting(void *setting) { - XFREE(MTYPE_MT_AREA_SETTING, setting); + XFREE(MTYPE_MT_AREA_SETTING, setting); } -void -area_add_mt_setting(struct isis_area *area, struct isis_area_mt_setting *setting) +void area_add_mt_setting(struct isis_area *area, + struct isis_area_mt_setting *setting) { - add_mt_setting(&area->mt_settings, setting); + add_mt_setting(&area->mt_settings, setting); } -void -area_mt_init(struct isis_area *area) +void area_mt_init(struct isis_area *area) { - struct isis_area_mt_setting *v4_unicast_setting; + struct isis_area_mt_setting *v4_unicast_setting; - /* MTID 0 is always enabled */ - v4_unicast_setting = area_new_mt_setting(area, ISIS_MT_IPV4_UNICAST); - v4_unicast_setting->enabled = true; - add_mt_setting(&area->mt_settings, v4_unicast_setting); - area->mt_settings->del = area_free_mt_setting; + /* MTID 0 is always enabled */ + v4_unicast_setting = area_new_mt_setting(area, ISIS_MT_IPV4_UNICAST); + v4_unicast_setting->enabled = true; + add_mt_setting(&area->mt_settings, v4_unicast_setting); + area->mt_settings->del = area_free_mt_setting; } -void -area_mt_finish(struct isis_area *area) +void area_mt_finish(struct isis_area *area) { - list_delete(area->mt_settings); - area->mt_settings = NULL; + list_delete(area->mt_settings); + area->mt_settings = NULL; } -struct isis_area_mt_setting * -area_get_mt_setting(struct isis_area *area, uint16_t mtid) +struct isis_area_mt_setting *area_get_mt_setting(struct isis_area *area, + uint16_t mtid) { - struct isis_area_mt_setting *setting; + struct isis_area_mt_setting *setting; - setting = area_lookup_mt_setting(area, mtid); - if (!setting) - { - setting = area_new_mt_setting(area, mtid); - area_add_mt_setting(area, setting); - } - return setting; + setting = area_lookup_mt_setting(area, mtid); + if (!setting) { + setting = area_new_mt_setting(area, mtid); + area_add_mt_setting(area, setting); + } + return setting; } -int -area_write_mt_settings(struct isis_area *area, struct vty *vty) +int area_write_mt_settings(struct isis_area *area, struct vty *vty) { - int written = 0; - struct listnode *node; - struct isis_area_mt_setting *setting; + int written = 0; + struct listnode *node; + struct isis_area_mt_setting *setting; - for (ALL_LIST_ELEMENTS_RO(area->mt_settings, node, setting)) - { - const char *name = isis_mtid2str(setting->mtid); - if (name && setting->enabled) - { - if (setting->mtid == ISIS_MT_IPV4_UNICAST) - continue; /* always enabled, no need to write out config */ - vty_out (vty, " topology %s%s\n", name, - setting->overload ? " overload" : ""); - written++; - } - } - return written; + for (ALL_LIST_ELEMENTS_RO(area->mt_settings, node, setting)) { + const char *name = isis_mtid2str(setting->mtid); + if (name && setting->enabled) { + if (setting->mtid == ISIS_MT_IPV4_UNICAST) + continue; /* always enabled, no need to write + out config */ + vty_out(vty, " topology %s%s\n", name, + setting->overload ? " overload" : ""); + written++; + } + } + return written; } bool area_is_mt(struct isis_area *area) { - struct listnode *node, *node2; - struct isis_area_mt_setting *setting; - struct isis_circuit *circuit; - struct isis_circuit_mt_setting *csetting; + struct listnode *node, *node2; + struct isis_area_mt_setting *setting; + struct isis_circuit *circuit; + struct isis_circuit_mt_setting *csetting; - for (ALL_LIST_ELEMENTS_RO(area->mt_settings, node, setting)) - { - if (setting->enabled && setting->mtid != ISIS_MT_IPV4_UNICAST) - return true; - } - for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) - { - for (ALL_LIST_ELEMENTS_RO(circuit->mt_settings, node2, csetting)) - { - if (!csetting->enabled && csetting->mtid == ISIS_MT_IPV4_UNICAST) - return true; - } - } + for (ALL_LIST_ELEMENTS_RO(area->mt_settings, node, setting)) { + if (setting->enabled && setting->mtid != ISIS_MT_IPV4_UNICAST) + return true; + } + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) { + for (ALL_LIST_ELEMENTS_RO(circuit->mt_settings, node2, + csetting)) { + if (!csetting->enabled + && csetting->mtid == ISIS_MT_IPV4_UNICAST) + return true; + } + } - return false; + return false; } -struct isis_area_mt_setting** -area_mt_settings(struct isis_area *area, unsigned int *mt_count) +struct isis_area_mt_setting **area_mt_settings(struct isis_area *area, + unsigned int *mt_count) { - static unsigned int size = 0; - static struct isis_area_mt_setting **rv = NULL; + static unsigned int size = 0; + static struct isis_area_mt_setting **rv = NULL; - unsigned int count = 0; - struct listnode *node; - struct isis_area_mt_setting *setting; + unsigned int count = 0; + struct listnode *node; + struct isis_area_mt_setting *setting; - for (ALL_LIST_ELEMENTS_RO(area->mt_settings, node, setting)) - { - if (!setting->enabled) - continue; + for (ALL_LIST_ELEMENTS_RO(area->mt_settings, node, setting)) { + if (!setting->enabled) + continue; - count++; - if (count > size) - { - rv = XREALLOC(MTYPE_TMP, rv, count * sizeof(*rv)); - size = count; - } - rv[count-1] = setting; - } + count++; + if (count > size) { + rv = XREALLOC(MTYPE_TMP, rv, count * sizeof(*rv)); + size = count; + } + rv[count - 1] = setting; + } - *mt_count = count; - return rv; + *mt_count = count; + return rv; } /* Circuit specific MT settings api */ -struct isis_circuit_mt_setting* +struct isis_circuit_mt_setting * circuit_lookup_mt_setting(struct isis_circuit *circuit, uint16_t mtid) { - return lookup_mt_setting(circuit->mt_settings, mtid); + return lookup_mt_setting(circuit->mt_settings, mtid); } -struct isis_circuit_mt_setting* +struct isis_circuit_mt_setting * circuit_new_mt_setting(struct isis_circuit *circuit, uint16_t mtid) { - struct isis_circuit_mt_setting *setting; + struct isis_circuit_mt_setting *setting; - setting = XCALLOC(MTYPE_MT_CIRCUIT_SETTING, sizeof(*setting)); - setting->mtid = mtid; - setting->enabled = true; /* Enabled is default for circuit */ - return setting; + setting = XCALLOC(MTYPE_MT_CIRCUIT_SETTING, sizeof(*setting)); + setting->mtid = mtid; + setting->enabled = true; /* Enabled is default for circuit */ + return setting; } -static void -circuit_free_mt_setting(void *setting) +static void circuit_free_mt_setting(void *setting) { - XFREE(MTYPE_MT_CIRCUIT_SETTING, setting); + XFREE(MTYPE_MT_CIRCUIT_SETTING, setting); } -void -circuit_add_mt_setting(struct isis_circuit *circuit, - struct isis_circuit_mt_setting *setting) +void circuit_add_mt_setting(struct isis_circuit *circuit, + struct isis_circuit_mt_setting *setting) { - add_mt_setting(&circuit->mt_settings, setting); + add_mt_setting(&circuit->mt_settings, setting); } -void -circuit_mt_init(struct isis_circuit *circuit) +void circuit_mt_init(struct isis_circuit *circuit) { - circuit->mt_settings = list_new(); - circuit->mt_settings->del = circuit_free_mt_setting; + circuit->mt_settings = list_new(); + circuit->mt_settings->del = circuit_free_mt_setting; } -void -circuit_mt_finish(struct isis_circuit *circuit) +void circuit_mt_finish(struct isis_circuit *circuit) { - list_delete(circuit->mt_settings); - circuit->mt_settings = NULL; + list_delete(circuit->mt_settings); + circuit->mt_settings = NULL; } -struct isis_circuit_mt_setting* +struct isis_circuit_mt_setting * circuit_get_mt_setting(struct isis_circuit *circuit, uint16_t mtid) { - struct isis_circuit_mt_setting *setting; + struct isis_circuit_mt_setting *setting; - setting = circuit_lookup_mt_setting(circuit, mtid); - if (!setting) - { - setting = circuit_new_mt_setting(circuit, mtid); - circuit_add_mt_setting(circuit, setting); - } - return setting; + setting = circuit_lookup_mt_setting(circuit, mtid); + if (!setting) { + setting = circuit_new_mt_setting(circuit, mtid); + circuit_add_mt_setting(circuit, setting); + } + return setting; } -int -circuit_write_mt_settings(struct isis_circuit *circuit, struct vty *vty) +int circuit_write_mt_settings(struct isis_circuit *circuit, struct vty *vty) { - int written = 0; - struct listnode *node; - struct isis_circuit_mt_setting *setting; + int written = 0; + struct listnode *node; + struct isis_circuit_mt_setting *setting; - for (ALL_LIST_ELEMENTS_RO (circuit->mt_settings, node, setting)) - { - const char *name = isis_mtid2str(setting->mtid); - if (name && !setting->enabled) - { - vty_out (vty, " no isis topology %s\n", name); - written++; - } - } - return written; + for (ALL_LIST_ELEMENTS_RO(circuit->mt_settings, node, setting)) { + const char *name = isis_mtid2str(setting->mtid); + if (name && !setting->enabled) { + vty_out(vty, " no isis topology %s\n", name); + written++; + } + } + return written; } -struct isis_circuit_mt_setting** +struct isis_circuit_mt_setting ** circuit_mt_settings(struct isis_circuit *circuit, unsigned int *mt_count) { - static unsigned int size = 0; - static struct isis_circuit_mt_setting **rv = NULL; + static unsigned int size = 0; + static struct isis_circuit_mt_setting **rv = NULL; - struct isis_area_mt_setting **area_settings; - unsigned int area_count; + struct isis_area_mt_setting **area_settings; + unsigned int area_count; - unsigned int count = 0; + unsigned int count = 0; - struct listnode *node; - struct isis_circuit_mt_setting *setting; + struct listnode *node; + struct isis_circuit_mt_setting *setting; - area_settings = area_mt_settings(circuit->area, &area_count); + area_settings = area_mt_settings(circuit->area, &area_count); - for (unsigned int i = 0; i < area_count; i++) - { - for (ALL_LIST_ELEMENTS_RO(circuit->mt_settings, node, setting)) - { - if (setting->mtid != area_settings[i]->mtid) - continue; - break; - } - if (!setting) - setting = circuit_get_mt_setting(circuit, area_settings[i]->mtid); + for (unsigned int i = 0; i < area_count; i++) { + for (ALL_LIST_ELEMENTS_RO(circuit->mt_settings, node, + setting)) { + if (setting->mtid != area_settings[i]->mtid) + continue; + break; + } + if (!setting) + setting = circuit_get_mt_setting( + circuit, area_settings[i]->mtid); - if (!setting->enabled) - continue; + if (!setting->enabled) + continue; - count++; - if (count > size) - { - rv = XREALLOC(MTYPE_TMP, rv, count * sizeof(*rv)); - size = count; - } - rv[count-1] = setting; - } + count++; + if (count > size) { + rv = XREALLOC(MTYPE_TMP, rv, count * sizeof(*rv)); + size = count; + } + rv[count - 1] = setting; + } - *mt_count = count; - return rv; + *mt_count = count; + return rv; } /* ADJ specific MT API */ static void adj_mt_set(struct isis_adjacency *adj, unsigned int index, - uint16_t mtid) -{ - if (adj->mt_count < index + 1) - { - adj->mt_set = XREALLOC(MTYPE_MT_ADJ_INFO, adj->mt_set, - (index + 1) * sizeof(*adj->mt_set)); - adj->mt_count = index + 1; - } - adj->mt_set[index] = mtid; -} - -bool -tlvs_to_adj_mt_set(struct tlvs *tlvs, bool v4_usable, bool v6_usable, - struct isis_adjacency *adj) -{ - struct isis_circuit_mt_setting **mt_settings; - unsigned int circuit_mt_count; - - unsigned int intersect_count = 0; - - uint16_t *old_mt_set = NULL; - unsigned int old_mt_count; - - old_mt_count = adj->mt_count; - if (old_mt_count) - { - old_mt_set = XCALLOC(MTYPE_TMP, old_mt_count * sizeof(*old_mt_set)); - memcpy(old_mt_set, adj->mt_set, old_mt_count * sizeof(*old_mt_set)); - } - - mt_settings = circuit_mt_settings(adj->circuit, &circuit_mt_count); - for (unsigned int i = 0; i < circuit_mt_count; i++) - { - if (!tlvs->mt_router_info) - { - /* Other end does not have MT enabled */ - if (mt_settings[i]->mtid == ISIS_MT_IPV4_UNICAST && v4_usable) - adj_mt_set(adj, intersect_count++, ISIS_MT_IPV4_UNICAST); - } - else - { - struct listnode *node; - struct mt_router_info *info; - for (ALL_LIST_ELEMENTS_RO(tlvs->mt_router_info, node, info)) - { - if (mt_settings[i]->mtid == info->mtid) - { - bool usable; - switch (info->mtid) - { - case ISIS_MT_IPV4_UNICAST: - case ISIS_MT_IPV4_MGMT: - case ISIS_MT_IPV4_MULTICAST: - usable = v4_usable; - break; - case ISIS_MT_IPV6_UNICAST: - case ISIS_MT_IPV6_MGMT: - case ISIS_MT_IPV6_MULTICAST: - usable = v6_usable; - break; - default: - usable = true; - break; - } - if (usable) - adj_mt_set(adj, intersect_count++, info->mtid); - } - } - } - } - adj->mt_count = intersect_count; - - bool changed = false; - - if (adj->mt_count != old_mt_count) - changed = true; - - if (!changed && old_mt_count - && memcmp(adj->mt_set, old_mt_set, - old_mt_count * sizeof(*old_mt_set))) - changed = true; - - if (old_mt_count) - XFREE(MTYPE_TMP, old_mt_set); - - return changed; -} - -bool -adj_has_mt(struct isis_adjacency *adj, uint16_t mtid) -{ - for (unsigned int i = 0; i < adj->mt_count; i++) - if (adj->mt_set[i] == mtid) - return true; - return false; -} - -void -adj_mt_finish(struct isis_adjacency *adj) -{ - XFREE(MTYPE_MT_ADJ_INFO, adj->mt_set); - adj->mt_count = 0; + uint16_t mtid) +{ + if (adj->mt_count < index + 1) { + adj->mt_set = XREALLOC(MTYPE_MT_ADJ_INFO, adj->mt_set, + (index + 1) * sizeof(*adj->mt_set)); + adj->mt_count = index + 1; + } + adj->mt_set[index] = mtid; +} + +bool tlvs_to_adj_mt_set(struct tlvs *tlvs, bool v4_usable, bool v6_usable, + struct isis_adjacency *adj) +{ + struct isis_circuit_mt_setting **mt_settings; + unsigned int circuit_mt_count; + + unsigned int intersect_count = 0; + + uint16_t *old_mt_set = NULL; + unsigned int old_mt_count; + + old_mt_count = adj->mt_count; + if (old_mt_count) { + old_mt_set = + XCALLOC(MTYPE_TMP, old_mt_count * sizeof(*old_mt_set)); + memcpy(old_mt_set, adj->mt_set, + old_mt_count * sizeof(*old_mt_set)); + } + + mt_settings = circuit_mt_settings(adj->circuit, &circuit_mt_count); + for (unsigned int i = 0; i < circuit_mt_count; i++) { + if (!tlvs->mt_router_info) { + /* Other end does not have MT enabled */ + if (mt_settings[i]->mtid == ISIS_MT_IPV4_UNICAST + && v4_usable) + adj_mt_set(adj, intersect_count++, + ISIS_MT_IPV4_UNICAST); + } else { + struct listnode *node; + struct mt_router_info *info; + for (ALL_LIST_ELEMENTS_RO(tlvs->mt_router_info, node, + info)) { + if (mt_settings[i]->mtid == info->mtid) { + bool usable; + switch (info->mtid) { + case ISIS_MT_IPV4_UNICAST: + case ISIS_MT_IPV4_MGMT: + case ISIS_MT_IPV4_MULTICAST: + usable = v4_usable; + break; + case ISIS_MT_IPV6_UNICAST: + case ISIS_MT_IPV6_MGMT: + case ISIS_MT_IPV6_MULTICAST: + usable = v6_usable; + break; + default: + usable = true; + break; + } + if (usable) + adj_mt_set(adj, + intersect_count++, + info->mtid); + } + } + } + } + adj->mt_count = intersect_count; + + bool changed = false; + + if (adj->mt_count != old_mt_count) + changed = true; + + if (!changed && old_mt_count + && memcmp(adj->mt_set, old_mt_set, + old_mt_count * sizeof(*old_mt_set))) + changed = true; + + if (old_mt_count) + XFREE(MTYPE_TMP, old_mt_set); + + return changed; +} + +bool adj_has_mt(struct isis_adjacency *adj, uint16_t mtid) +{ + for (unsigned int i = 0; i < adj->mt_count; i++) + if (adj->mt_set[i] == mtid) + return true; + return false; +} + +void adj_mt_finish(struct isis_adjacency *adj) +{ + XFREE(MTYPE_MT_ADJ_INFO, adj->mt_set); + adj->mt_count = 0; } /* TLV Router info api */ -struct mt_router_info* -tlvs_lookup_mt_router_info(struct tlvs *tlvs, uint16_t mtid) +struct mt_router_info *tlvs_lookup_mt_router_info(struct tlvs *tlvs, + uint16_t mtid) { - return lookup_mt_setting(tlvs->mt_router_info, mtid); + return lookup_mt_setting(tlvs->mt_router_info, mtid); } /* TLV MT Neighbors api */ -struct tlv_mt_neighbors* -tlvs_lookup_mt_neighbors(struct tlvs *tlvs, uint16_t mtid) +struct tlv_mt_neighbors *tlvs_lookup_mt_neighbors(struct tlvs *tlvs, + uint16_t mtid) { - return lookup_mt_setting(tlvs->mt_is_neighs, mtid); + return lookup_mt_setting(tlvs->mt_is_neighs, mtid); } -static struct tlv_mt_neighbors* -tlvs_new_mt_neighbors(uint16_t mtid) +static struct tlv_mt_neighbors *tlvs_new_mt_neighbors(uint16_t mtid) { - struct tlv_mt_neighbors *rv; + struct tlv_mt_neighbors *rv; - rv = XCALLOC(MTYPE_MT_NEIGHBORS, sizeof(*rv)); - rv->mtid = mtid; - rv->list = list_new(); + rv = XCALLOC(MTYPE_MT_NEIGHBORS, sizeof(*rv)); + rv->mtid = mtid; + rv->list = list_new(); - return rv; + return rv; }; -static void -tlvs_free_mt_neighbors(void *arg) +static void tlvs_free_mt_neighbors(void *arg) { - struct tlv_mt_neighbors *neighbors = arg; + struct tlv_mt_neighbors *neighbors = arg; - if (neighbors && neighbors->list) - list_delete(neighbors->list); - XFREE(MTYPE_MT_NEIGHBORS, neighbors); + if (neighbors && neighbors->list) + list_delete(neighbors->list); + XFREE(MTYPE_MT_NEIGHBORS, neighbors); } -static void -tlvs_add_mt_neighbors(struct tlvs *tlvs, struct tlv_mt_neighbors *neighbors) +static void tlvs_add_mt_neighbors(struct tlvs *tlvs, + struct tlv_mt_neighbors *neighbors) { - add_mt_setting(&tlvs->mt_is_neighs, neighbors); - tlvs->mt_is_neighs->del = tlvs_free_mt_neighbors; + add_mt_setting(&tlvs->mt_is_neighs, neighbors); + tlvs->mt_is_neighs->del = tlvs_free_mt_neighbors; } -struct tlv_mt_neighbors* -tlvs_get_mt_neighbors(struct tlvs *tlvs, uint16_t mtid) +struct tlv_mt_neighbors *tlvs_get_mt_neighbors(struct tlvs *tlvs, uint16_t mtid) { - struct tlv_mt_neighbors *neighbors; + struct tlv_mt_neighbors *neighbors; - neighbors = tlvs_lookup_mt_neighbors(tlvs, mtid); - if (!neighbors) - { - neighbors = tlvs_new_mt_neighbors(mtid); - tlvs_add_mt_neighbors(tlvs, neighbors); - } - return neighbors; + neighbors = tlvs_lookup_mt_neighbors(tlvs, mtid); + if (!neighbors) { + neighbors = tlvs_new_mt_neighbors(mtid); + tlvs_add_mt_neighbors(tlvs, neighbors); + } + return neighbors; } /* TLV MT IPv4 reach api */ -struct tlv_mt_ipv4_reachs* -tlvs_lookup_mt_ipv4_reachs(struct tlvs *tlvs, uint16_t mtid) +struct tlv_mt_ipv4_reachs *tlvs_lookup_mt_ipv4_reachs(struct tlvs *tlvs, + uint16_t mtid) { - return lookup_mt_setting(tlvs->mt_ipv4_reachs, mtid); + return lookup_mt_setting(tlvs->mt_ipv4_reachs, mtid); } -static struct tlv_mt_ipv4_reachs* -tlvs_new_mt_ipv4_reachs(uint16_t mtid) +static struct tlv_mt_ipv4_reachs *tlvs_new_mt_ipv4_reachs(uint16_t mtid) { - struct tlv_mt_ipv4_reachs *rv; + struct tlv_mt_ipv4_reachs *rv; - rv = XCALLOC(MTYPE_MT_IPV4_REACHS, sizeof(*rv)); - rv->mtid = mtid; - rv->list = list_new(); + rv = XCALLOC(MTYPE_MT_IPV4_REACHS, sizeof(*rv)); + rv->mtid = mtid; + rv->list = list_new(); - return rv; + return rv; }; -static void -tlvs_free_mt_ipv4_reachs(void *arg) +static void tlvs_free_mt_ipv4_reachs(void *arg) { - struct tlv_mt_ipv4_reachs *reachs = arg; + struct tlv_mt_ipv4_reachs *reachs = arg; - if (reachs && reachs->list) - list_delete(reachs->list); - XFREE(MTYPE_MT_IPV4_REACHS, reachs); + if (reachs && reachs->list) + list_delete(reachs->list); + XFREE(MTYPE_MT_IPV4_REACHS, reachs); } -static void -tlvs_add_mt_ipv4_reachs(struct tlvs *tlvs, struct tlv_mt_ipv4_reachs *reachs) +static void tlvs_add_mt_ipv4_reachs(struct tlvs *tlvs, + struct tlv_mt_ipv4_reachs *reachs) { - add_mt_setting(&tlvs->mt_ipv4_reachs, reachs); - tlvs->mt_ipv4_reachs->del = tlvs_free_mt_ipv4_reachs; + add_mt_setting(&tlvs->mt_ipv4_reachs, reachs); + tlvs->mt_ipv4_reachs->del = tlvs_free_mt_ipv4_reachs; } -struct tlv_mt_ipv4_reachs* -tlvs_get_mt_ipv4_reachs(struct tlvs *tlvs, uint16_t mtid) +struct tlv_mt_ipv4_reachs *tlvs_get_mt_ipv4_reachs(struct tlvs *tlvs, + uint16_t mtid) { - struct tlv_mt_ipv4_reachs *reachs; + struct tlv_mt_ipv4_reachs *reachs; - reachs = tlvs_lookup_mt_ipv4_reachs(tlvs, mtid); - if (!reachs) - { - reachs = tlvs_new_mt_ipv4_reachs(mtid); - tlvs_add_mt_ipv4_reachs(tlvs, reachs); - } - return reachs; + reachs = tlvs_lookup_mt_ipv4_reachs(tlvs, mtid); + if (!reachs) { + reachs = tlvs_new_mt_ipv4_reachs(mtid); + tlvs_add_mt_ipv4_reachs(tlvs, reachs); + } + return reachs; } /* TLV MT IPv6 reach api */ -struct tlv_mt_ipv6_reachs* -tlvs_lookup_mt_ipv6_reachs(struct tlvs *tlvs, uint16_t mtid) +struct tlv_mt_ipv6_reachs *tlvs_lookup_mt_ipv6_reachs(struct tlvs *tlvs, + uint16_t mtid) { - return lookup_mt_setting(tlvs->mt_ipv6_reachs, mtid); + return lookup_mt_setting(tlvs->mt_ipv6_reachs, mtid); } -static struct tlv_mt_ipv6_reachs* -tlvs_new_mt_ipv6_reachs(uint16_t mtid) +static struct tlv_mt_ipv6_reachs *tlvs_new_mt_ipv6_reachs(uint16_t mtid) { - struct tlv_mt_ipv6_reachs *rv; + struct tlv_mt_ipv6_reachs *rv; - rv = XCALLOC(MTYPE_MT_IPV6_REACHS, sizeof(*rv)); - rv->mtid = mtid; - rv->list = list_new(); + rv = XCALLOC(MTYPE_MT_IPV6_REACHS, sizeof(*rv)); + rv->mtid = mtid; + rv->list = list_new(); - return rv; + return rv; }; -static void -tlvs_free_mt_ipv6_reachs(void *arg) +static void tlvs_free_mt_ipv6_reachs(void *arg) { - struct tlv_mt_ipv6_reachs *reachs = arg; + struct tlv_mt_ipv6_reachs *reachs = arg; - if (reachs && reachs->list) - list_delete(reachs->list); - XFREE(MTYPE_MT_IPV6_REACHS, reachs); + if (reachs && reachs->list) + list_delete(reachs->list); + XFREE(MTYPE_MT_IPV6_REACHS, reachs); } -static void -tlvs_add_mt_ipv6_reachs(struct tlvs *tlvs, struct tlv_mt_ipv6_reachs *reachs) +static void tlvs_add_mt_ipv6_reachs(struct tlvs *tlvs, + struct tlv_mt_ipv6_reachs *reachs) { - add_mt_setting(&tlvs->mt_ipv6_reachs, reachs); - tlvs->mt_ipv6_reachs->del = tlvs_free_mt_ipv6_reachs; + add_mt_setting(&tlvs->mt_ipv6_reachs, reachs); + tlvs->mt_ipv6_reachs->del = tlvs_free_mt_ipv6_reachs; } -struct tlv_mt_ipv6_reachs* -tlvs_get_mt_ipv6_reachs(struct tlvs *tlvs, uint16_t mtid) +struct tlv_mt_ipv6_reachs *tlvs_get_mt_ipv6_reachs(struct tlvs *tlvs, + uint16_t mtid) { - struct tlv_mt_ipv6_reachs *reachs; + struct tlv_mt_ipv6_reachs *reachs; - reachs = tlvs_lookup_mt_ipv6_reachs(tlvs, mtid); - if (!reachs) - { - reachs = tlvs_new_mt_ipv6_reachs(mtid); - tlvs_add_mt_ipv6_reachs(tlvs, reachs); - } - return reachs; + reachs = tlvs_lookup_mt_ipv6_reachs(tlvs, mtid); + if (!reachs) { + reachs = tlvs_new_mt_ipv6_reachs(mtid); + tlvs_add_mt_ipv6_reachs(tlvs, reachs); + } + return reachs; } -static void -mt_set_add(uint16_t **mt_set, unsigned int *size, - unsigned int *index, uint16_t mtid) +static void mt_set_add(uint16_t **mt_set, unsigned int *size, + unsigned int *index, uint16_t mtid) { - for (unsigned int i = 0; i < *index; i++) - { - if ((*mt_set)[i] == mtid) - return; - } + for (unsigned int i = 0; i < *index; i++) { + if ((*mt_set)[i] == mtid) + return; + } - if (*index >= *size) - { - *mt_set = XREALLOC(MTYPE_TMP, *mt_set, sizeof(**mt_set) * ((*index) + 1)); - *size = (*index) + 1; - } + if (*index >= *size) { + *mt_set = XREALLOC(MTYPE_TMP, *mt_set, + sizeof(**mt_set) * ((*index) + 1)); + *size = (*index) + 1; + } - (*mt_set)[*index] = mtid; - *index = (*index) + 1; + (*mt_set)[*index] = mtid; + *index = (*index) + 1; } -static uint16_t * -circuit_bcast_mt_set(struct isis_circuit *circuit, int level, - unsigned int *mt_count) +static uint16_t *circuit_bcast_mt_set(struct isis_circuit *circuit, int level, + unsigned int *mt_count) { - static uint16_t *rv; - static unsigned int size; - struct listnode *node; - struct isis_adjacency *adj; + static uint16_t *rv; + static unsigned int size; + struct listnode *node; + struct isis_adjacency *adj; - unsigned int count = 0; + unsigned int count = 0; - if (circuit->circ_type != CIRCUIT_T_BROADCAST) - { - *mt_count = 0; - return NULL; - } + if (circuit->circ_type != CIRCUIT_T_BROADCAST) { + *mt_count = 0; + return NULL; + } - for (ALL_LIST_ELEMENTS_RO(circuit->u.bc.adjdb[level - 1], node, adj)) - { - if (adj->adj_state != ISIS_ADJ_UP) - continue; - for (unsigned int i = 0; i < adj->mt_count; i++) - mt_set_add(&rv, &size, &count, adj->mt_set[i]); - } + for (ALL_LIST_ELEMENTS_RO(circuit->u.bc.adjdb[level - 1], node, adj)) { + if (adj->adj_state != ISIS_ADJ_UP) + continue; + for (unsigned int i = 0; i < adj->mt_count; i++) + mt_set_add(&rv, &size, &count, adj->mt_set[i]); + } - *mt_count = count; - return rv; + *mt_count = count; + return rv; } -static void -tlvs_add_mt_set(struct isis_area *area, - struct tlvs *tlvs, unsigned int mt_count, - uint16_t *mt_set, struct te_is_neigh *neigh) +static void tlvs_add_mt_set(struct isis_area *area, struct tlvs *tlvs, + unsigned int mt_count, uint16_t *mt_set, + struct te_is_neigh *neigh) { - for (unsigned int i = 0; i < mt_count; i++) - { - uint16_t mtid = mt_set[i]; - struct te_is_neigh *ne_copy; + for (unsigned int i = 0; i < mt_count; i++) { + uint16_t mtid = mt_set[i]; + struct te_is_neigh *ne_copy; - ne_copy = XCALLOC(MTYPE_ISIS_TLV, sizeof(*ne_copy)); - memcpy(ne_copy, neigh, sizeof(*ne_copy)); + ne_copy = XCALLOC(MTYPE_ISIS_TLV, sizeof(*ne_copy)); + memcpy(ne_copy, neigh, sizeof(*ne_copy)); - if (mt_set[i] == ISIS_MT_IPV4_UNICAST) - { - listnode_add(tlvs->te_is_neighs, ne_copy); - lsp_debug("ISIS (%s): Adding %s.%02x as te-style neighbor", - area->area_tag, sysid_print(ne_copy->neigh_id), - LSP_PSEUDO_ID(ne_copy->neigh_id)); - } - else - { - struct tlv_mt_neighbors *neighbors; + if (mt_set[i] == ISIS_MT_IPV4_UNICAST) { + listnode_add(tlvs->te_is_neighs, ne_copy); + lsp_debug( + "ISIS (%s): Adding %s.%02x as te-style neighbor", + area->area_tag, sysid_print(ne_copy->neigh_id), + LSP_PSEUDO_ID(ne_copy->neigh_id)); + } else { + struct tlv_mt_neighbors *neighbors; - neighbors = tlvs_get_mt_neighbors(tlvs, mtid); - neighbors->list->del = free_tlv; - listnode_add(neighbors->list, ne_copy); - lsp_debug("ISIS (%s): Adding %s.%02x as mt-style neighbor for %s", - area->area_tag, sysid_print(ne_copy->neigh_id), - LSP_PSEUDO_ID(ne_copy->neigh_id), isis_mtid2str(mtid)); - } - } + neighbors = tlvs_get_mt_neighbors(tlvs, mtid); + neighbors->list->del = free_tlv; + listnode_add(neighbors->list, ne_copy); + lsp_debug( + "ISIS (%s): Adding %s.%02x as mt-style neighbor for %s", + area->area_tag, sysid_print(ne_copy->neigh_id), + LSP_PSEUDO_ID(ne_copy->neigh_id), + isis_mtid2str(mtid)); + } + } } -void -tlvs_add_mt_bcast(struct tlvs *tlvs, struct isis_circuit *circuit, - int level, struct te_is_neigh *neigh) +void tlvs_add_mt_bcast(struct tlvs *tlvs, struct isis_circuit *circuit, + int level, struct te_is_neigh *neigh) { - unsigned int mt_count; - uint16_t *mt_set = circuit_bcast_mt_set(circuit, level, - &mt_count); + unsigned int mt_count; + uint16_t *mt_set = circuit_bcast_mt_set(circuit, level, &mt_count); - tlvs_add_mt_set(circuit->area, tlvs, mt_count, mt_set, neigh); -} - -void -tlvs_add_mt_p2p(struct tlvs *tlvs, struct isis_circuit *circuit, - struct te_is_neigh *neigh) + tlvs_add_mt_set(circuit->area, tlvs, mt_count, mt_set, neigh); +} + +void tlvs_add_mt_p2p(struct tlvs *tlvs, struct isis_circuit *circuit, + struct te_is_neigh *neigh) { - struct isis_adjacency *adj = circuit->u.p2p.neighbor; + struct isis_adjacency *adj = circuit->u.p2p.neighbor; - tlvs_add_mt_set(circuit->area, tlvs, adj->mt_count, adj->mt_set, neigh); + tlvs_add_mt_set(circuit->area, tlvs, adj->mt_count, adj->mt_set, neigh); } diff --git a/isisd/isis_mt.h b/isisd/isis_mt.h index e90f1756f..eec089228 100644 --- a/isisd/isis_mt.h +++ b/isisd/isis_mt.h @@ -32,52 +32,51 @@ #define ISIS_MT_IPV6_MULTICAST 4 #define ISIS_MT_IPV6_MGMT 5 -#define ISIS_MT_NAMES \ - "" - -#define ISIS_MT_DESCRIPTIONS \ - "IPv4 unicast topology\n" \ - "IPv4 management topology\n" \ - "IPv6 unicast topology\n" \ - "IPv4 multicast topology\n" \ - "IPv6 multicast topology\n" \ - "IPv6 management topology\n" - -#define ISIS_MT_INFO_FIELDS \ - uint16_t mtid; +#define ISIS_MT_NAMES \ + "" + +#define ISIS_MT_DESCRIPTIONS \ + "IPv4 unicast topology\n" \ + "IPv4 management topology\n" \ + "IPv6 unicast topology\n" \ + "IPv4 multicast topology\n" \ + "IPv6 multicast topology\n" \ + "IPv6 management topology\n" + +#define ISIS_MT_INFO_FIELDS uint16_t mtid; struct list; struct isis_area_mt_setting { - ISIS_MT_INFO_FIELDS - bool enabled; - bool overload; + ISIS_MT_INFO_FIELDS + bool enabled; + bool overload; }; struct isis_circuit_mt_setting { - ISIS_MT_INFO_FIELDS - bool enabled; + ISIS_MT_INFO_FIELDS + bool enabled; }; struct tlv_mt_neighbors { - ISIS_MT_INFO_FIELDS - struct list *list; + ISIS_MT_INFO_FIELDS + struct list *list; }; struct tlv_mt_ipv4_reachs { - ISIS_MT_INFO_FIELDS - struct list *list; + ISIS_MT_INFO_FIELDS + struct list *list; }; struct tlv_mt_ipv6_reachs { - ISIS_MT_INFO_FIELDS - struct list *list; + ISIS_MT_INFO_FIELDS + struct list *list; }; const char *isis_mtid2str(uint16_t mtid); @@ -91,55 +90,59 @@ struct te_is_neigh; uint16_t isis_area_ipv6_topology(struct isis_area *area); -struct mt_router_info* tlvs_lookup_mt_router_info(struct tlvs *tlvs, uint16_t mtid); +struct mt_router_info *tlvs_lookup_mt_router_info(struct tlvs *tlvs, + uint16_t mtid); -struct tlv_mt_neighbors* tlvs_lookup_mt_neighbors(struct tlvs *tlvs, uint16_t mtid); -struct tlv_mt_neighbors* tlvs_get_mt_neighbors(struct tlvs *tlvs, uint16_t mtid); +struct tlv_mt_neighbors *tlvs_lookup_mt_neighbors(struct tlvs *tlvs, + uint16_t mtid); +struct tlv_mt_neighbors *tlvs_get_mt_neighbors(struct tlvs *tlvs, + uint16_t mtid); -struct tlv_mt_ipv4_reachs* tlvs_lookup_mt_ipv4_reachs(struct tlvs *tlvs, uint16_t mtid); -struct tlv_mt_ipv4_reachs* tlvs_get_mt_ipv4_reachs(struct tlvs *tlvs, uint16_t mtid); +struct tlv_mt_ipv4_reachs *tlvs_lookup_mt_ipv4_reachs(struct tlvs *tlvs, + uint16_t mtid); +struct tlv_mt_ipv4_reachs *tlvs_get_mt_ipv4_reachs(struct tlvs *tlvs, + uint16_t mtid); -struct tlv_mt_ipv6_reachs* tlvs_lookup_mt_ipv6_reachs(struct tlvs *tlvs, uint16_t mtid); -struct tlv_mt_ipv6_reachs* tlvs_get_mt_ipv6_reachs(struct tlvs *tlvs, uint16_t mtid); +struct tlv_mt_ipv6_reachs *tlvs_lookup_mt_ipv6_reachs(struct tlvs *tlvs, + uint16_t mtid); +struct tlv_mt_ipv6_reachs *tlvs_get_mt_ipv6_reachs(struct tlvs *tlvs, + uint16_t mtid); -struct isis_area_mt_setting* area_lookup_mt_setting(struct isis_area *area, - uint16_t mtid); -struct isis_area_mt_setting* area_new_mt_setting(struct isis_area *area, - uint16_t mtid); +struct isis_area_mt_setting *area_lookup_mt_setting(struct isis_area *area, + uint16_t mtid); +struct isis_area_mt_setting *area_new_mt_setting(struct isis_area *area, + uint16_t mtid); void area_add_mt_setting(struct isis_area *area, - struct isis_area_mt_setting *setting); + struct isis_area_mt_setting *setting); void area_mt_init(struct isis_area *area); void area_mt_finish(struct isis_area *area); -struct isis_area_mt_setting* area_get_mt_setting(struct isis_area *area, - uint16_t mtid); +struct isis_area_mt_setting *area_get_mt_setting(struct isis_area *area, + uint16_t mtid); int area_write_mt_settings(struct isis_area *area, struct vty *vty); bool area_is_mt(struct isis_area *area); -struct isis_area_mt_setting** area_mt_settings(struct isis_area *area, - unsigned int *mt_count); - -struct isis_circuit_mt_setting* circuit_lookup_mt_setting( - struct isis_circuit *circuit, - uint16_t mtid); -struct isis_circuit_mt_setting* circuit_new_mt_setting( - struct isis_circuit *circuit, - uint16_t mtid); +struct isis_area_mt_setting **area_mt_settings(struct isis_area *area, + unsigned int *mt_count); + +struct isis_circuit_mt_setting * +circuit_lookup_mt_setting(struct isis_circuit *circuit, uint16_t mtid); +struct isis_circuit_mt_setting * +circuit_new_mt_setting(struct isis_circuit *circuit, uint16_t mtid); void circuit_add_mt_setting(struct isis_circuit *circuit, - struct isis_circuit_mt_setting *setting); + struct isis_circuit_mt_setting *setting); void circuit_mt_init(struct isis_circuit *circuit); void circuit_mt_finish(struct isis_circuit *circuit); -struct isis_circuit_mt_setting* circuit_get_mt_setting( - struct isis_circuit *circuit, - uint16_t mtid); +struct isis_circuit_mt_setting * +circuit_get_mt_setting(struct isis_circuit *circuit, uint16_t mtid); int circuit_write_mt_settings(struct isis_circuit *circuit, struct vty *vty); -struct isis_circuit_mt_setting** circuit_mt_settings(struct isis_circuit *circuit, - unsigned int *mt_count); +struct isis_circuit_mt_setting ** +circuit_mt_settings(struct isis_circuit *circuit, unsigned int *mt_count); bool tlvs_to_adj_mt_set(struct tlvs *tlvs, bool v4_usable, bool v6_usable, - struct isis_adjacency *adj); + struct isis_adjacency *adj); bool adj_has_mt(struct isis_adjacency *adj, uint16_t mtid); void adj_mt_finish(struct isis_adjacency *adj); void tlvs_add_mt_bcast(struct tlvs *tlvs, struct isis_circuit *circuit, - int level, struct te_is_neigh *neigh); + int level, struct te_is_neigh *neigh); void tlvs_add_mt_p2p(struct tlvs *tlvs, struct isis_circuit *circuit, - struct te_is_neigh *neigh); + struct te_is_neigh *neigh); #endif diff --git a/isisd/isis_network.h b/isisd/isis_network.h index 41788e69f..4b2531606 100644 --- a/isisd/isis_network.h +++ b/isisd/isis_network.h @@ -1,18 +1,18 @@ /* - * IS-IS Rout(e)ing protocol - isis_network.h + * IS-IS Rout(e)ing protocol - isis_network.h * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -27,11 +27,11 @@ extern u_char ALL_L1_ISYSTEMS[]; extern u_char ALL_L2_ISYSTEMS[]; -int isis_sock_init (struct isis_circuit *circuit); +int isis_sock_init(struct isis_circuit *circuit); -int isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa); -int isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa); -int isis_send_pdu_bcast (struct isis_circuit *circuit, int level); -int isis_send_pdu_p2p (struct isis_circuit *circuit, int level); +int isis_recv_pdu_bcast(struct isis_circuit *circuit, u_char *ssnpa); +int isis_recv_pdu_p2p(struct isis_circuit *circuit, u_char *ssnpa); +int isis_send_pdu_bcast(struct isis_circuit *circuit, int level); +int isis_send_pdu_p2p(struct isis_circuit *circuit, int level); #endif /* _ZEBRA_ISIS_NETWORK_H */ diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index d62682b10..a3706179a 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -1,19 +1,19 @@ /* - * IS-IS Rout(e)ing protocol - isis_pdu.c + * IS-IS Rout(e)ing protocol - isis_pdu.c * PDU processing * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -69,253 +69,238 @@ /* * Compares two sets of area addresses */ -static int -area_match (struct list *left, struct list *right) +static int area_match(struct list *left, struct list *right) { - struct area_addr *addr1, *addr2; - struct listnode *node1, *node2; - - for (ALL_LIST_ELEMENTS_RO (left, node1, addr1)) - { - for (ALL_LIST_ELEMENTS_RO (right, node2, addr2)) - { - if (addr1->addr_len == addr2->addr_len && - !memcmp (addr1->area_addr, addr2->area_addr, (int) addr1->addr_len)) - return 1; /* match */ - } - } + struct area_addr *addr1, *addr2; + struct listnode *node1, *node2; + + for (ALL_LIST_ELEMENTS_RO(left, node1, addr1)) { + for (ALL_LIST_ELEMENTS_RO(right, node2, addr2)) { + if (addr1->addr_len == addr2->addr_len + && !memcmp(addr1->area_addr, addr2->area_addr, + (int)addr1->addr_len)) + return 1; /* match */ + } + } - return 0; /* mismatch */ + return 0; /* mismatch */ } /* - * Checks whether we should accept a PDU of given level + * Checks whether we should accept a PDU of given level */ -static int -accept_level (int level, int circuit_t) +static int accept_level(int level, int circuit_t) { - int retval = ((circuit_t & level) == level); /* simple approach */ + int retval = ((circuit_t & level) == level); /* simple approach */ - return retval; + return retval; } /* * Verify authentication information * Support cleartext and HMAC MD5 authentication */ -static int -authentication_check (struct isis_passwd *remote, struct isis_passwd *local, - struct stream *stream, uint32_t auth_tlv_offset) +static int authentication_check(struct isis_passwd *remote, + struct isis_passwd *local, + struct stream *stream, uint32_t auth_tlv_offset) { - unsigned char digest[ISIS_AUTH_MD5_SIZE]; - - /* Auth fail () - passwd type mismatch */ - if (local->type != remote->type) - return ISIS_ERROR; - - switch (local->type) - { - /* No authentication required */ - case ISIS_PASSWD_TYPE_UNUSED: - break; - - /* Cleartext (ISO 10589) */ - case ISIS_PASSWD_TYPE_CLEARTXT: - /* Auth fail () - passwd len mismatch */ - if (remote->len != local->len) - return ISIS_ERROR; - return memcmp (local->passwd, remote->passwd, local->len); - - /* HMAC MD5 (RFC 3567) */ - case ISIS_PASSWD_TYPE_HMAC_MD5: - /* Auth fail () - passwd len mismatch */ - if (remote->len != ISIS_AUTH_MD5_SIZE) - return ISIS_ERROR; - /* Set the authentication value to 0 before the check */ - memset (STREAM_DATA (stream) + auth_tlv_offset + 3, 0, - ISIS_AUTH_MD5_SIZE); - /* Compute the digest */ - hmac_md5 (STREAM_DATA (stream), stream_get_endp (stream), - (unsigned char *) &(local->passwd), local->len, - (unsigned char *) &digest); - /* Copy back the authentication value after the check */ - memcpy (STREAM_DATA (stream) + auth_tlv_offset + 3, - remote->passwd, ISIS_AUTH_MD5_SIZE); - return memcmp (digest, remote->passwd, ISIS_AUTH_MD5_SIZE); - - default: - zlog_err ("Unsupported authentication type"); - return ISIS_ERROR; - } - - /* Authentication pass when no authentication is configured */ - return ISIS_OK; + unsigned char digest[ISIS_AUTH_MD5_SIZE]; + + /* Auth fail () - passwd type mismatch */ + if (local->type != remote->type) + return ISIS_ERROR; + + switch (local->type) { + /* No authentication required */ + case ISIS_PASSWD_TYPE_UNUSED: + break; + + /* Cleartext (ISO 10589) */ + case ISIS_PASSWD_TYPE_CLEARTXT: + /* Auth fail () - passwd len mismatch */ + if (remote->len != local->len) + return ISIS_ERROR; + return memcmp(local->passwd, remote->passwd, local->len); + + /* HMAC MD5 (RFC 3567) */ + case ISIS_PASSWD_TYPE_HMAC_MD5: + /* Auth fail () - passwd len mismatch */ + if (remote->len != ISIS_AUTH_MD5_SIZE) + return ISIS_ERROR; + /* Set the authentication value to 0 before the check */ + memset(STREAM_DATA(stream) + auth_tlv_offset + 3, 0, + ISIS_AUTH_MD5_SIZE); + /* Compute the digest */ + hmac_md5(STREAM_DATA(stream), stream_get_endp(stream), + (unsigned char *)&(local->passwd), local->len, + (unsigned char *)&digest); + /* Copy back the authentication value after the check */ + memcpy(STREAM_DATA(stream) + auth_tlv_offset + 3, + remote->passwd, ISIS_AUTH_MD5_SIZE); + return memcmp(digest, remote->passwd, ISIS_AUTH_MD5_SIZE); + + default: + zlog_err("Unsupported authentication type"); + return ISIS_ERROR; + } + + /* Authentication pass when no authentication is configured */ + return ISIS_OK; } -static int -lsp_authentication_check (struct stream *stream, struct isis_area *area, - int level, struct isis_passwd *passwd) +static int lsp_authentication_check(struct stream *stream, + struct isis_area *area, int level, + struct isis_passwd *passwd) { - struct isis_link_state_hdr *hdr; - uint32_t expected = 0, found = 0, auth_tlv_offset = 0; - uint16_t checksum, rem_lifetime, pdu_len; - struct tlvs tlvs; - int retval = ISIS_OK; - - hdr = (struct isis_link_state_hdr *) (STREAM_PNT (stream)); - pdu_len = ntohs (hdr->pdu_len); - expected |= TLVFLAG_AUTH_INFO; - auth_tlv_offset = stream_get_getp (stream) + ISIS_LSP_HDR_LEN; - retval = parse_tlvs (area->area_tag, STREAM_PNT (stream) + ISIS_LSP_HDR_LEN, - pdu_len - ISIS_FIXED_HDR_LEN - ISIS_LSP_HDR_LEN, - &expected, &found, &tlvs, &auth_tlv_offset); - - if (retval != ISIS_OK) - { - zlog_err ("ISIS-Upd (%s): Parse failed L%d LSP %s, seq 0x%08x, " - "cksum 0x%04x, lifetime %us, len %u", - area->area_tag, level, rawlspid_print (hdr->lsp_id), - ntohl (hdr->seq_num), ntohs (hdr->checksum), - ntohs (hdr->rem_lifetime), pdu_len); - if ((isis->debugs & DEBUG_UPDATE_PACKETS) && - (isis->debugs & DEBUG_PACKET_DUMP)) - zlog_dump_data (STREAM_DATA (stream), stream_get_endp (stream)); - return retval; - } + struct isis_link_state_hdr *hdr; + uint32_t expected = 0, found = 0, auth_tlv_offset = 0; + uint16_t checksum, rem_lifetime, pdu_len; + struct tlvs tlvs; + int retval = ISIS_OK; + + hdr = (struct isis_link_state_hdr *)(STREAM_PNT(stream)); + pdu_len = ntohs(hdr->pdu_len); + expected |= TLVFLAG_AUTH_INFO; + auth_tlv_offset = stream_get_getp(stream) + ISIS_LSP_HDR_LEN; + retval = parse_tlvs(area->area_tag, + STREAM_PNT(stream) + ISIS_LSP_HDR_LEN, + pdu_len - ISIS_FIXED_HDR_LEN - ISIS_LSP_HDR_LEN, + &expected, &found, &tlvs, &auth_tlv_offset); + + if (retval != ISIS_OK) { + zlog_err( + "ISIS-Upd (%s): Parse failed L%d LSP %s, seq 0x%08x, " + "cksum 0x%04x, lifetime %us, len %u", + area->area_tag, level, rawlspid_print(hdr->lsp_id), + ntohl(hdr->seq_num), ntohs(hdr->checksum), + ntohs(hdr->rem_lifetime), pdu_len); + if ((isis->debugs & DEBUG_UPDATE_PACKETS) + && (isis->debugs & DEBUG_PACKET_DUMP)) + zlog_dump_data(STREAM_DATA(stream), + stream_get_endp(stream)); + return retval; + } - if (!(found & TLVFLAG_AUTH_INFO)) - { - zlog_err ("No authentication tlv in LSP"); - return ISIS_ERROR; - } + if (!(found & TLVFLAG_AUTH_INFO)) { + zlog_err("No authentication tlv in LSP"); + return ISIS_ERROR; + } - if (tlvs.auth_info.type != ISIS_PASSWD_TYPE_CLEARTXT && - tlvs.auth_info.type != ISIS_PASSWD_TYPE_HMAC_MD5) - { - zlog_err ("Unknown authentication type in LSP"); - return ISIS_ERROR; - } + if (tlvs.auth_info.type != ISIS_PASSWD_TYPE_CLEARTXT + && tlvs.auth_info.type != ISIS_PASSWD_TYPE_HMAC_MD5) { + zlog_err("Unknown authentication type in LSP"); + return ISIS_ERROR; + } - /* - * RFC 5304 set checksum and remaining lifetime to zero before - * verification and reset to old values after verification. - */ - checksum = hdr->checksum; - rem_lifetime = hdr->rem_lifetime; - hdr->checksum = 0; - hdr->rem_lifetime = 0; - retval = authentication_check (&tlvs.auth_info, passwd, stream, - auth_tlv_offset); - hdr->checksum = checksum; - hdr->rem_lifetime = rem_lifetime; - - return retval; + /* + * RFC 5304 set checksum and remaining lifetime to zero before + * verification and reset to old values after verification. + */ + checksum = hdr->checksum; + rem_lifetime = hdr->rem_lifetime; + hdr->checksum = 0; + hdr->rem_lifetime = 0; + retval = authentication_check(&tlvs.auth_info, passwd, stream, + auth_tlv_offset); + hdr->checksum = checksum; + hdr->rem_lifetime = rem_lifetime; + + return retval; } /* * Processing helper functions */ -static void -del_addr (void *val) +static void del_addr(void *val) { - XFREE (MTYPE_ISIS_TMP, val); + XFREE(MTYPE_ISIS_TMP, val); } -static void -tlvs_to_adj_area_addrs (struct tlvs *tlvs, struct isis_adjacency *adj) +static void tlvs_to_adj_area_addrs(struct tlvs *tlvs, + struct isis_adjacency *adj) { - struct listnode *node; - struct area_addr *area_addr, *malloced; + struct listnode *node; + struct area_addr *area_addr, *malloced; - if (adj->area_addrs) - { - adj->area_addrs->del = del_addr; - list_delete (adj->area_addrs); - } - adj->area_addrs = list_new (); - if (tlvs->area_addrs) - { - for (ALL_LIST_ELEMENTS_RO (tlvs->area_addrs, node, area_addr)) - { - malloced = XMALLOC (MTYPE_ISIS_TMP, sizeof (struct area_addr)); - memcpy (malloced, area_addr, sizeof (struct area_addr)); - listnode_add (adj->area_addrs, malloced); - } - } + if (adj->area_addrs) { + adj->area_addrs->del = del_addr; + list_delete(adj->area_addrs); + } + adj->area_addrs = list_new(); + if (tlvs->area_addrs) { + for (ALL_LIST_ELEMENTS_RO(tlvs->area_addrs, node, area_addr)) { + malloced = XMALLOC(MTYPE_ISIS_TMP, + sizeof(struct area_addr)); + memcpy(malloced, area_addr, sizeof(struct area_addr)); + listnode_add(adj->area_addrs, malloced); + } + } } -static int -tlvs_to_adj_nlpids (struct tlvs *tlvs, struct isis_adjacency *adj) +static int tlvs_to_adj_nlpids(struct tlvs *tlvs, struct isis_adjacency *adj) { - int i; - struct nlpids *tlv_nlpids; + int i; + struct nlpids *tlv_nlpids; - if (tlvs->nlpids) - { + if (tlvs->nlpids) { - tlv_nlpids = tlvs->nlpids; - if (tlv_nlpids->count > array_size (adj->nlpids.nlpids)) - return 1; + tlv_nlpids = tlvs->nlpids; + if (tlv_nlpids->count > array_size(adj->nlpids.nlpids)) + return 1; - adj->nlpids.count = tlv_nlpids->count; + adj->nlpids.count = tlv_nlpids->count; - for (i = 0; i < tlv_nlpids->count; i++) - { - adj->nlpids.nlpids[i] = tlv_nlpids->nlpids[i]; + for (i = 0; i < tlv_nlpids->count; i++) { + adj->nlpids.nlpids[i] = tlv_nlpids->nlpids[i]; + } } - } - return 0; + return 0; } -static void -tlvs_to_adj_ipv4_addrs (struct tlvs *tlvs, struct isis_adjacency *adj) +static void tlvs_to_adj_ipv4_addrs(struct tlvs *tlvs, + struct isis_adjacency *adj) { - struct listnode *node; - struct in_addr *ipv4_addr, *malloced; + struct listnode *node; + struct in_addr *ipv4_addr, *malloced; - if (adj->ipv4_addrs) - { - adj->ipv4_addrs->del = del_addr; - list_delete (adj->ipv4_addrs); - } - adj->ipv4_addrs = list_new (); - if (tlvs->ipv4_addrs) - { - for (ALL_LIST_ELEMENTS_RO (tlvs->ipv4_addrs, node, ipv4_addr)) - { - malloced = XMALLOC (MTYPE_ISIS_TMP, sizeof (struct in_addr)); - memcpy (malloced, ipv4_addr, sizeof (struct in_addr)); - listnode_add (adj->ipv4_addrs, malloced); - } - } + if (adj->ipv4_addrs) { + adj->ipv4_addrs->del = del_addr; + list_delete(adj->ipv4_addrs); + } + adj->ipv4_addrs = list_new(); + if (tlvs->ipv4_addrs) { + for (ALL_LIST_ELEMENTS_RO(tlvs->ipv4_addrs, node, ipv4_addr)) { + malloced = + XMALLOC(MTYPE_ISIS_TMP, sizeof(struct in_addr)); + memcpy(malloced, ipv4_addr, sizeof(struct in_addr)); + listnode_add(adj->ipv4_addrs, malloced); + } + } } -static void -tlvs_to_adj_ipv6_addrs (struct tlvs *tlvs, struct isis_adjacency *adj) +static void tlvs_to_adj_ipv6_addrs(struct tlvs *tlvs, + struct isis_adjacency *adj) { - struct listnode *node; - struct in6_addr *ipv6_addr, *malloced; - - if (adj->ipv6_addrs) - { - adj->ipv6_addrs->del = del_addr; - list_delete (adj->ipv6_addrs); - } - adj->ipv6_addrs = list_new (); - if (tlvs->ipv6_addrs) - { - for (ALL_LIST_ELEMENTS_RO (tlvs->ipv6_addrs, node, ipv6_addr)) - { - malloced = XMALLOC (MTYPE_ISIS_TMP, sizeof (struct in6_addr)); - memcpy (malloced, ipv6_addr, sizeof (struct in6_addr)); - listnode_add (adj->ipv6_addrs, malloced); - } - } + struct listnode *node; + struct in6_addr *ipv6_addr, *malloced; + if (adj->ipv6_addrs) { + adj->ipv6_addrs->del = del_addr; + list_delete(adj->ipv6_addrs); + } + adj->ipv6_addrs = list_new(); + if (tlvs->ipv6_addrs) { + for (ALL_LIST_ELEMENTS_RO(tlvs->ipv6_addrs, node, ipv6_addr)) { + malloced = XMALLOC(MTYPE_ISIS_TMP, + sizeof(struct in6_addr)); + memcpy(malloced, ipv6_addr, sizeof(struct in6_addr)); + listnode_add(adj->ipv6_addrs, malloced); + } + } } /* - * RECEIVE SIDE + * RECEIVE SIDE */ /* @@ -324,584 +309,559 @@ tlvs_to_adj_ipv6_addrs (struct tlvs *tlvs, struct isis_adjacency *adj) * Section 8.2.5 - Receiving point-to-point IIH PDUs * */ -static int -process_p2p_hello (struct isis_circuit *circuit) +static int process_p2p_hello(struct isis_circuit *circuit) { - int retval = ISIS_OK; - struct isis_p2p_hello_hdr *hdr; - struct isis_adjacency *adj; - u_int32_t expected = 0, found = 0, auth_tlv_offset = 0; - uint16_t pdu_len; - struct tlvs tlvs; - int v4_usable = 0, v6_usable = 0; - - if (isis->debugs & DEBUG_ADJ_PACKETS) - { - zlog_debug ("ISIS-Adj (%s): Rcvd P2P IIH on %s, cirType %s, cirID %u", - circuit->area->area_tag, circuit->interface->name, - circuit_t2string (circuit->is_type), circuit->circuit_id); - if (isis->debugs & DEBUG_PACKET_DUMP) - zlog_dump_data (STREAM_DATA (circuit->rcv_stream), - stream_get_endp (circuit->rcv_stream)); - } - - if (circuit->circ_type != CIRCUIT_T_P2P) - { - zlog_warn ("p2p hello on non p2p circuit"); - return ISIS_WARNING; - } - - if ((stream_get_endp (circuit->rcv_stream) - - stream_get_getp (circuit->rcv_stream)) < ISIS_P2PHELLO_HDRLEN) - { - zlog_warn ("Packet too short"); - return ISIS_WARNING; - } - - /* 8.2.5.1 PDU acceptance tests */ - - /* 8.2.5.1 a) external domain untrue */ - /* FIXME: not useful at all? */ - - /* 8.2.5.1 b) ID Length mismatch */ - /* checked at the handle_pdu */ - - /* 8.2.5.2 IIH PDU Processing */ - - /* 8.2.5.2 a) 1) Maximum Area Addresses */ - /* Already checked, and can also be ommited */ - - /* - * Get the header - */ - hdr = (struct isis_p2p_hello_hdr *) STREAM_PNT (circuit->rcv_stream); - pdu_len = ntohs (hdr->pdu_len); - - if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_P2PHELLO_HDRLEN) || - pdu_len > ISO_MTU(circuit) || - pdu_len > stream_get_endp (circuit->rcv_stream)) - { - zlog_warn ("ISIS-Adj (%s): Rcvd P2P IIH from (%s) with " - "invalid pdu length %d", - circuit->area->area_tag, circuit->interface->name, pdu_len); - return ISIS_WARNING; - } - - /* - * Set the stream endp to PDU length, ignoring additional padding - * introduced by transport chips. - */ - if (pdu_len < stream_get_endp (circuit->rcv_stream)) - stream_set_endp (circuit->rcv_stream, pdu_len); - - stream_forward_getp (circuit->rcv_stream, ISIS_P2PHELLO_HDRLEN); - - /* - * Lets get the TLVS now - */ - expected |= TLVFLAG_AREA_ADDRS; - expected |= TLVFLAG_AUTH_INFO; - expected |= TLVFLAG_NLPID; - expected |= TLVFLAG_IPV4_ADDR; - expected |= TLVFLAG_IPV6_ADDR; - expected |= TLVFLAG_MT_ROUTER_INFORMATION; - - auth_tlv_offset = stream_get_getp (circuit->rcv_stream); - retval = parse_tlvs (circuit->area->area_tag, - STREAM_PNT (circuit->rcv_stream), - pdu_len - ISIS_P2PHELLO_HDRLEN - ISIS_FIXED_HDR_LEN, - &expected, &found, &tlvs, &auth_tlv_offset); - - if (retval > ISIS_WARNING) - { - zlog_warn ("parse_tlvs() failed"); - free_tlvs (&tlvs); - return retval; - }; - - if (!(found & TLVFLAG_AREA_ADDRS)) - { - zlog_warn ("No Area addresses TLV in P2P IS to IS hello"); - free_tlvs (&tlvs); - return ISIS_WARNING; - } + int retval = ISIS_OK; + struct isis_p2p_hello_hdr *hdr; + struct isis_adjacency *adj; + u_int32_t expected = 0, found = 0, auth_tlv_offset = 0; + uint16_t pdu_len; + struct tlvs tlvs; + int v4_usable = 0, v6_usable = 0; + + if (isis->debugs & DEBUG_ADJ_PACKETS) { + zlog_debug( + "ISIS-Adj (%s): Rcvd P2P IIH on %s, cirType %s, cirID %u", + circuit->area->area_tag, circuit->interface->name, + circuit_t2string(circuit->is_type), + circuit->circuit_id); + if (isis->debugs & DEBUG_PACKET_DUMP) + zlog_dump_data(STREAM_DATA(circuit->rcv_stream), + stream_get_endp(circuit->rcv_stream)); + } - if (!(found & TLVFLAG_NLPID)) - { - zlog_warn ("No supported protocols TLV in P2P IS to IS hello"); - free_tlvs (&tlvs); - return ISIS_WARNING; - } + if (circuit->circ_type != CIRCUIT_T_P2P) { + zlog_warn("p2p hello on non p2p circuit"); + return ISIS_WARNING; + } - /* 8.2.5.1 c) Authentication */ - if (circuit->passwd.type) - { - if (!(found & TLVFLAG_AUTH_INFO) || - authentication_check (&tlvs.auth_info, &circuit->passwd, - circuit->rcv_stream, auth_tlv_offset)) - { - isis_event_auth_failure (circuit->area->area_tag, - "P2P hello authentication failure", - hdr->source_id); - free_tlvs (&tlvs); - return ISIS_OK; - } - } + if ((stream_get_endp(circuit->rcv_stream) + - stream_get_getp(circuit->rcv_stream)) + < ISIS_P2PHELLO_HDRLEN) { + zlog_warn("Packet too short"); + return ISIS_WARNING; + } - /* - * check if both ends have an IPv4 address - */ - if (circuit->ip_addrs && listcount(circuit->ip_addrs) - && tlvs.ipv4_addrs && listcount(tlvs.ipv4_addrs)) - { - v4_usable = 1; - } + /* 8.2.5.1 PDU acceptance tests */ - if (found & TLVFLAG_IPV6_ADDR) - { - /* TBA: check that we have a linklocal ourselves? */ - struct listnode *node; - struct in6_addr *ip; - for (ALL_LIST_ELEMENTS_RO (tlvs.ipv6_addrs, node, ip)) - if (IN6_IS_ADDR_LINKLOCAL (ip)) - { - v6_usable = 1; - break; - } - - if (!v6_usable) - zlog_warn ("ISIS-Adj: IPv6 addresses present but no link-local " - "in P2P IIH from %s\n", circuit->interface->name); - } + /* 8.2.5.1 a) external domain untrue */ + /* FIXME: not useful at all? */ - if (!(found & (TLVFLAG_IPV4_ADDR | TLVFLAG_IPV6_ADDR))) - zlog_warn ("ISIS-Adj: neither IPv4 nor IPv6 addr in P2P IIH from %s\n", - circuit->interface->name); + /* 8.2.5.1 b) ID Length mismatch */ + /* checked at the handle_pdu */ - if (!v6_usable && !v4_usable) - { - free_tlvs (&tlvs); - return ISIS_WARNING; - } + /* 8.2.5.2 IIH PDU Processing */ - /* - * it's own p2p IIH PDU - discard - */ - if (!memcmp (hdr->source_id, isis->sysid, ISIS_SYS_ID_LEN)) - { - zlog_warn ("ISIS-Adj (%s): it's own IIH PDU - discarded", - circuit->area->area_tag); - free_tlvs (&tlvs); - return ISIS_WARNING; - } + /* 8.2.5.2 a) 1) Maximum Area Addresses */ + /* Already checked, and can also be ommited */ - /* - * My interpertation of the ISO, if no adj exists we will create one for - * the circuit - */ - adj = circuit->u.p2p.neighbor; - /* If an adjacency exists, check it is with the source of the hello - * packets */ - if (adj) - { - if (memcmp(hdr->source_id, adj->sysid, ISIS_SYS_ID_LEN)) - { - zlog_debug("hello source and adjacency do not match, set adj down\n"); - isis_adj_state_change (adj, ISIS_ADJ_DOWN, "adj do not exist"); - return 0; - } - } - if (!adj || adj->level != hdr->circuit_t) - { - if (!adj) - { - adj = isis_new_adj (hdr->source_id, NULL, hdr->circuit_t, circuit); - if (adj == NULL) - return ISIS_ERROR; - } - else - { - adj->level = hdr->circuit_t; - } - circuit->u.p2p.neighbor = adj; - /* Build lsp with the new neighbor entry when a new - * adjacency is formed. Set adjacency circuit type to - * IIH PDU header circuit type before lsp is regenerated - * when an adjacency is up. This will result in the new - * adjacency entry getting added to the lsp tlv neighbor list. - */ - adj->circuit_t = hdr->circuit_t; - isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL); - adj->sys_type = ISIS_SYSTYPE_UNKNOWN; - } + /* + * Get the header + */ + hdr = (struct isis_p2p_hello_hdr *)STREAM_PNT(circuit->rcv_stream); + pdu_len = ntohs(hdr->pdu_len); - /* 8.2.6 Monitoring point-to-point adjacencies */ - adj->hold_time = ntohs (hdr->hold_time); - adj->last_upd = time (NULL); + if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_P2PHELLO_HDRLEN) + || pdu_len > ISO_MTU(circuit) + || pdu_len > stream_get_endp(circuit->rcv_stream)) { + zlog_warn( + "ISIS-Adj (%s): Rcvd P2P IIH from (%s) with " + "invalid pdu length %d", + circuit->area->area_tag, circuit->interface->name, + pdu_len); + return ISIS_WARNING; + } - /* we do this now because the adj may not survive till the end... */ - tlvs_to_adj_area_addrs (&tlvs, adj); + /* + * Set the stream endp to PDU length, ignoring additional padding + * introduced by transport chips. + */ + if (pdu_len < stream_get_endp(circuit->rcv_stream)) + stream_set_endp(circuit->rcv_stream, pdu_len); + + stream_forward_getp(circuit->rcv_stream, ISIS_P2PHELLO_HDRLEN); + + /* + * Lets get the TLVS now + */ + expected |= TLVFLAG_AREA_ADDRS; + expected |= TLVFLAG_AUTH_INFO; + expected |= TLVFLAG_NLPID; + expected |= TLVFLAG_IPV4_ADDR; + expected |= TLVFLAG_IPV6_ADDR; + expected |= TLVFLAG_MT_ROUTER_INFORMATION; + + auth_tlv_offset = stream_get_getp(circuit->rcv_stream); + retval = parse_tlvs(circuit->area->area_tag, + STREAM_PNT(circuit->rcv_stream), + pdu_len - ISIS_P2PHELLO_HDRLEN - ISIS_FIXED_HDR_LEN, + &expected, &found, &tlvs, &auth_tlv_offset); + + if (retval > ISIS_WARNING) { + zlog_warn("parse_tlvs() failed"); + free_tlvs(&tlvs); + return retval; + }; + + if (!(found & TLVFLAG_AREA_ADDRS)) { + zlog_warn("No Area addresses TLV in P2P IS to IS hello"); + free_tlvs(&tlvs); + return ISIS_WARNING; + } - /* which protocol are spoken ??? */ - if (tlvs_to_adj_nlpids (&tlvs, adj)) - { - free_tlvs (&tlvs); - return ISIS_WARNING; - } + if (!(found & TLVFLAG_NLPID)) { + zlog_warn("No supported protocols TLV in P2P IS to IS hello"); + free_tlvs(&tlvs); + return ISIS_WARNING; + } - /* we need to copy addresses to the adj */ - if (found & TLVFLAG_IPV4_ADDR) - tlvs_to_adj_ipv4_addrs (&tlvs, adj); + /* 8.2.5.1 c) Authentication */ + if (circuit->passwd.type) { + if (!(found & TLVFLAG_AUTH_INFO) + || authentication_check(&tlvs.auth_info, &circuit->passwd, + circuit->rcv_stream, + auth_tlv_offset)) { + isis_event_auth_failure( + circuit->area->area_tag, + "P2P hello authentication failure", + hdr->source_id); + free_tlvs(&tlvs); + return ISIS_OK; + } + } - /* Update MPLS TE Remote IP address parameter if possible */ - if (IS_MPLS_TE(isisMplsTE) && circuit->mtc && IS_CIRCUIT_TE(circuit->mtc)) - if (adj->ipv4_addrs != NULL && listcount(adj->ipv4_addrs) != 0) - { - struct in_addr *ip_addr; - ip_addr = (struct in_addr *)listgetdata ((struct listnode *)listhead (adj->ipv4_addrs)); - set_circuitparams_rmt_ipaddr (circuit->mtc, *ip_addr); - } + /* + * check if both ends have an IPv4 address + */ + if (circuit->ip_addrs && listcount(circuit->ip_addrs) && tlvs.ipv4_addrs + && listcount(tlvs.ipv4_addrs)) { + v4_usable = 1; + } - if (found & TLVFLAG_IPV6_ADDR) - tlvs_to_adj_ipv6_addrs (&tlvs, adj); + if (found & TLVFLAG_IPV6_ADDR) { + /* TBA: check that we have a linklocal ourselves? */ + struct listnode *node; + struct in6_addr *ip; + for (ALL_LIST_ELEMENTS_RO(tlvs.ipv6_addrs, node, ip)) + if (IN6_IS_ADDR_LINKLOCAL(ip)) { + v6_usable = 1; + break; + } + + if (!v6_usable) + zlog_warn( + "ISIS-Adj: IPv6 addresses present but no link-local " + "in P2P IIH from %s\n", + circuit->interface->name); + } - bool mt_set_changed = tlvs_to_adj_mt_set(&tlvs, v4_usable, v6_usable, adj); + if (!(found & (TLVFLAG_IPV4_ADDR | TLVFLAG_IPV6_ADDR))) + zlog_warn( + "ISIS-Adj: neither IPv4 nor IPv6 addr in P2P IIH from %s\n", + circuit->interface->name); - /* lets take care of the expiry */ - THREAD_TIMER_OFF (adj->t_expire); - thread_add_timer(master, isis_adj_expire, adj, (long)adj->hold_time, - &adj->t_expire); + if (!v6_usable && !v4_usable) { + free_tlvs(&tlvs); + return ISIS_WARNING; + } - /* 8.2.5.2 a) a match was detected */ - if (area_match (circuit->area->area_addrs, tlvs.area_addrs)) - { - /* 8.2.5.2 a) 2) If the system is L1 - table 5 */ - if (circuit->area->is_type == IS_LEVEL_1) - { - switch (hdr->circuit_t) - { - case IS_LEVEL_1: - case IS_LEVEL_1_AND_2: - if (adj->adj_state != ISIS_ADJ_UP) - { - /* (4) adj state up */ - isis_adj_state_change (adj, ISIS_ADJ_UP, NULL); - /* (5) adj usage level 1 */ - adj->adj_usage = ISIS_ADJ_LEVEL1; - } - else if (adj->adj_usage == ISIS_ADJ_LEVEL1) - { - ; /* accept */ - } - break; - case IS_LEVEL_2: - if (adj->adj_state != ISIS_ADJ_UP) - { - /* (7) reject - wrong system type event */ - zlog_warn ("wrongSystemType"); - free_tlvs (&tlvs); - return ISIS_WARNING; /* Reject */ - } - else if (adj->adj_usage == ISIS_ADJ_LEVEL1) - { - /* (6) down - wrong system */ - isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); - } - break; - } + /* + * it's own p2p IIH PDU - discard + */ + if (!memcmp(hdr->source_id, isis->sysid, ISIS_SYS_ID_LEN)) { + zlog_warn("ISIS-Adj (%s): it's own IIH PDU - discarded", + circuit->area->area_tag); + free_tlvs(&tlvs); + return ISIS_WARNING; } - /* 8.2.5.2 a) 3) If the system is L1L2 - table 6 */ - if (circuit->area->is_type == IS_LEVEL_1_AND_2) - { - switch (hdr->circuit_t) - { - case IS_LEVEL_1: - if (adj->adj_state != ISIS_ADJ_UP) - { - /* (6) adj state up */ - isis_adj_state_change (adj, ISIS_ADJ_UP, NULL); - /* (7) adj usage level 1 */ - adj->adj_usage = ISIS_ADJ_LEVEL1; - } - else if (adj->adj_usage == ISIS_ADJ_LEVEL1) - { - ; /* accept */ - } - else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) || - (adj->adj_usage == ISIS_ADJ_LEVEL2)) - { - /* (8) down - wrong system */ - isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); - } - break; - case IS_LEVEL_2: - if (adj->adj_state != ISIS_ADJ_UP) - { - /* (6) adj state up */ - isis_adj_state_change (adj, ISIS_ADJ_UP, NULL); - /* (9) adj usage level 2 */ - adj->adj_usage = ISIS_ADJ_LEVEL2; - } - else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) || - (adj->adj_usage == ISIS_ADJ_LEVEL1AND2)) - { - /* (8) down - wrong system */ - isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); - } - else if (adj->adj_usage == ISIS_ADJ_LEVEL2) - { - ; /* Accept */ - } - break; - case IS_LEVEL_1_AND_2: - if (adj->adj_state != ISIS_ADJ_UP) - { - /* (6) adj state up */ - isis_adj_state_change (adj, ISIS_ADJ_UP, NULL); - /* (10) adj usage level 1 */ - adj->adj_usage = ISIS_ADJ_LEVEL1AND2; + /* + * My interpertation of the ISO, if no adj exists we will create one for + * the circuit + */ + adj = circuit->u.p2p.neighbor; + /* If an adjacency exists, check it is with the source of the hello + * packets */ + if (adj) { + if (memcmp(hdr->source_id, adj->sysid, ISIS_SYS_ID_LEN)) { + zlog_debug( + "hello source and adjacency do not match, set adj down\n"); + isis_adj_state_change(adj, ISIS_ADJ_DOWN, + "adj do not exist"); + return 0; } - else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) || - (adj->adj_usage == ISIS_ADJ_LEVEL2)) - { - /* (8) down - wrong system */ - isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); - } - else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2) - { - ; /* Accept */ + } + if (!adj || adj->level != hdr->circuit_t) { + if (!adj) { + adj = isis_new_adj(hdr->source_id, NULL, hdr->circuit_t, + circuit); + if (adj == NULL) + return ISIS_ERROR; + } else { + adj->level = hdr->circuit_t; } - break; - } + circuit->u.p2p.neighbor = adj; + /* Build lsp with the new neighbor entry when a new + * adjacency is formed. Set adjacency circuit type to + * IIH PDU header circuit type before lsp is regenerated + * when an adjacency is up. This will result in the new + * adjacency entry getting added to the lsp tlv neighbor list. + */ + adj->circuit_t = hdr->circuit_t; + isis_adj_state_change(adj, ISIS_ADJ_INITIALIZING, NULL); + adj->sys_type = ISIS_SYSTYPE_UNKNOWN; } - /* 8.2.5.2 a) 4) If the system is L2 - table 7 */ - if (circuit->area->is_type == IS_LEVEL_2) - { - switch (hdr->circuit_t) - { - case IS_LEVEL_1: - if (adj->adj_state != ISIS_ADJ_UP) - { - /* (5) reject - wrong system type event */ - zlog_warn ("wrongSystemType"); - free_tlvs (&tlvs); - return ISIS_WARNING; /* Reject */ - } - else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) || - (adj->adj_usage == ISIS_ADJ_LEVEL2)) - { - /* (6) down - wrong system */ - isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); - } - break; - case IS_LEVEL_1_AND_2: - case IS_LEVEL_2: - if (adj->adj_state != ISIS_ADJ_UP) - { - /* (7) adj state up */ - isis_adj_state_change (adj, ISIS_ADJ_UP, NULL); - /* (8) adj usage level 2 */ - adj->adj_usage = ISIS_ADJ_LEVEL2; - } - else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2) - { - /* (6) down - wrong system */ - isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); - } - else if (adj->adj_usage == ISIS_ADJ_LEVEL2) - { - ; /* Accept */ - } - break; - } + /* 8.2.6 Monitoring point-to-point adjacencies */ + adj->hold_time = ntohs(hdr->hold_time); + adj->last_upd = time(NULL); + + /* we do this now because the adj may not survive till the end... */ + tlvs_to_adj_area_addrs(&tlvs, adj); + + /* which protocol are spoken ??? */ + if (tlvs_to_adj_nlpids(&tlvs, adj)) { + free_tlvs(&tlvs); + return ISIS_WARNING; } - } - /* 8.2.5.2 b) if no match was detected */ - else if (listcount (circuit->area->area_addrs) > 0) - { - if (circuit->area->is_type == IS_LEVEL_1) - { - /* 8.2.5.2 b) 1) is_type L1 and adj is not up */ - if (adj->adj_state != ISIS_ADJ_UP) - { - isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch"); - /* 8.2.5.2 b) 2)is_type L1 and adj is up */ - } - else - { - isis_adj_state_change (adj, ISIS_ADJ_DOWN, - "Down - Area Mismatch"); - } - } - /* 8.2.5.2 b 3 If the system is L2 or L1L2 - table 8 */ - else - { - switch (hdr->circuit_t) - { - case IS_LEVEL_1: - if (adj->adj_state != ISIS_ADJ_UP) - { - /* (6) reject - Area Mismatch event */ - zlog_warn ("AreaMismatch"); - free_tlvs (&tlvs); - return ISIS_WARNING; /* Reject */ - } - else if (adj->adj_usage == ISIS_ADJ_LEVEL1) - { - /* (7) down - area mismatch */ - isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch"); + /* we need to copy addresses to the adj */ + if (found & TLVFLAG_IPV4_ADDR) + tlvs_to_adj_ipv4_addrs(&tlvs, adj); + + /* Update MPLS TE Remote IP address parameter if possible */ + if (IS_MPLS_TE(isisMplsTE) && circuit->mtc + && IS_CIRCUIT_TE(circuit->mtc)) + if (adj->ipv4_addrs != NULL + && listcount(adj->ipv4_addrs) != 0) { + struct in_addr *ip_addr; + ip_addr = (struct in_addr *)listgetdata( + (struct listnode *)listhead(adj->ipv4_addrs)); + set_circuitparams_rmt_ipaddr(circuit->mtc, *ip_addr); } - else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) || - (adj->adj_usage == ISIS_ADJ_LEVEL2)) - { - /* (7) down - wrong system */ - isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); + + if (found & TLVFLAG_IPV6_ADDR) + tlvs_to_adj_ipv6_addrs(&tlvs, adj); + + bool mt_set_changed = + tlvs_to_adj_mt_set(&tlvs, v4_usable, v6_usable, adj); + + /* lets take care of the expiry */ + THREAD_TIMER_OFF(adj->t_expire); + thread_add_timer(master, isis_adj_expire, adj, (long)adj->hold_time, + &adj->t_expire); + + /* 8.2.5.2 a) a match was detected */ + if (area_match(circuit->area->area_addrs, tlvs.area_addrs)) { + /* 8.2.5.2 a) 2) If the system is L1 - table 5 */ + if (circuit->area->is_type == IS_LEVEL_1) { + switch (hdr->circuit_t) { + case IS_LEVEL_1: + case IS_LEVEL_1_AND_2: + if (adj->adj_state != ISIS_ADJ_UP) { + /* (4) adj state up */ + isis_adj_state_change(adj, ISIS_ADJ_UP, + NULL); + /* (5) adj usage level 1 */ + adj->adj_usage = ISIS_ADJ_LEVEL1; + } else if (adj->adj_usage == ISIS_ADJ_LEVEL1) { + ; /* accept */ + } + break; + case IS_LEVEL_2: + if (adj->adj_state != ISIS_ADJ_UP) { + /* (7) reject - wrong system type event + */ + zlog_warn("wrongSystemType"); + free_tlvs(&tlvs); + return ISIS_WARNING; /* Reject */ + } else if (adj->adj_usage == ISIS_ADJ_LEVEL1) { + /* (6) down - wrong system */ + isis_adj_state_change(adj, + ISIS_ADJ_DOWN, + "Wrong System"); + } + break; + } } - break; - case IS_LEVEL_1_AND_2: - case IS_LEVEL_2: - if (adj->adj_state != ISIS_ADJ_UP) - { - /* (8) adj state up */ - isis_adj_state_change (adj, ISIS_ADJ_UP, NULL); - /* (9) adj usage level 2 */ - adj->adj_usage = ISIS_ADJ_LEVEL2; + + /* 8.2.5.2 a) 3) If the system is L1L2 - table 6 */ + if (circuit->area->is_type == IS_LEVEL_1_AND_2) { + switch (hdr->circuit_t) { + case IS_LEVEL_1: + if (adj->adj_state != ISIS_ADJ_UP) { + /* (6) adj state up */ + isis_adj_state_change(adj, ISIS_ADJ_UP, + NULL); + /* (7) adj usage level 1 */ + adj->adj_usage = ISIS_ADJ_LEVEL1; + } else if (adj->adj_usage == ISIS_ADJ_LEVEL1) { + ; /* accept */ + } else if ((adj->adj_usage + == ISIS_ADJ_LEVEL1AND2) + || (adj->adj_usage + == ISIS_ADJ_LEVEL2)) { + /* (8) down - wrong system */ + isis_adj_state_change(adj, + ISIS_ADJ_DOWN, + "Wrong System"); + } + break; + case IS_LEVEL_2: + if (adj->adj_state != ISIS_ADJ_UP) { + /* (6) adj state up */ + isis_adj_state_change(adj, ISIS_ADJ_UP, + NULL); + /* (9) adj usage level 2 */ + adj->adj_usage = ISIS_ADJ_LEVEL2; + } else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) + || (adj->adj_usage + == ISIS_ADJ_LEVEL1AND2)) { + /* (8) down - wrong system */ + isis_adj_state_change(adj, + ISIS_ADJ_DOWN, + "Wrong System"); + } else if (adj->adj_usage == ISIS_ADJ_LEVEL2) { + ; /* Accept */ + } + break; + case IS_LEVEL_1_AND_2: + if (adj->adj_state != ISIS_ADJ_UP) { + /* (6) adj state up */ + isis_adj_state_change(adj, ISIS_ADJ_UP, + NULL); + /* (10) adj usage level 1 */ + adj->adj_usage = ISIS_ADJ_LEVEL1AND2; + } else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) + || (adj->adj_usage + == ISIS_ADJ_LEVEL2)) { + /* (8) down - wrong system */ + isis_adj_state_change(adj, + ISIS_ADJ_DOWN, + "Wrong System"); + } else if (adj->adj_usage + == ISIS_ADJ_LEVEL1AND2) { + ; /* Accept */ + } + break; + } } - else if (adj->adj_usage == ISIS_ADJ_LEVEL1) - { - /* (7) down - wrong system */ - isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); + + /* 8.2.5.2 a) 4) If the system is L2 - table 7 */ + if (circuit->area->is_type == IS_LEVEL_2) { + switch (hdr->circuit_t) { + case IS_LEVEL_1: + if (adj->adj_state != ISIS_ADJ_UP) { + /* (5) reject - wrong system type event + */ + zlog_warn("wrongSystemType"); + free_tlvs(&tlvs); + return ISIS_WARNING; /* Reject */ + } else if ((adj->adj_usage + == ISIS_ADJ_LEVEL1AND2) + || (adj->adj_usage + == ISIS_ADJ_LEVEL2)) { + /* (6) down - wrong system */ + isis_adj_state_change(adj, + ISIS_ADJ_DOWN, + "Wrong System"); + } + break; + case IS_LEVEL_1_AND_2: + case IS_LEVEL_2: + if (adj->adj_state != ISIS_ADJ_UP) { + /* (7) adj state up */ + isis_adj_state_change(adj, ISIS_ADJ_UP, + NULL); + /* (8) adj usage level 2 */ + adj->adj_usage = ISIS_ADJ_LEVEL2; + } else if (adj->adj_usage + == ISIS_ADJ_LEVEL1AND2) { + /* (6) down - wrong system */ + isis_adj_state_change(adj, + ISIS_ADJ_DOWN, + "Wrong System"); + } else if (adj->adj_usage == ISIS_ADJ_LEVEL2) { + ; /* Accept */ + } + break; + } } - else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2) - { - if (hdr->circuit_t == IS_LEVEL_2) - { - /* (7) down - wrong system */ - isis_adj_state_change (adj, ISIS_ADJ_DOWN, - "Wrong System"); - } - else - { - /* (7) down - area mismatch */ - isis_adj_state_change (adj, ISIS_ADJ_DOWN, - "Area Mismatch"); - } + } + /* 8.2.5.2 b) if no match was detected */ + else if (listcount(circuit->area->area_addrs) > 0) { + if (circuit->area->is_type == IS_LEVEL_1) { + /* 8.2.5.2 b) 1) is_type L1 and adj is not up */ + if (adj->adj_state != ISIS_ADJ_UP) { + isis_adj_state_change(adj, ISIS_ADJ_DOWN, + "Area Mismatch"); + /* 8.2.5.2 b) 2)is_type L1 and adj is up */ + } else { + isis_adj_state_change(adj, ISIS_ADJ_DOWN, + "Down - Area Mismatch"); + } } - else if (adj->adj_usage == ISIS_ADJ_LEVEL2) - { - ; /* Accept */ + /* 8.2.5.2 b 3 If the system is L2 or L1L2 - table 8 */ + else { + switch (hdr->circuit_t) { + case IS_LEVEL_1: + if (adj->adj_state != ISIS_ADJ_UP) { + /* (6) reject - Area Mismatch event */ + zlog_warn("AreaMismatch"); + free_tlvs(&tlvs); + return ISIS_WARNING; /* Reject */ + } else if (adj->adj_usage == ISIS_ADJ_LEVEL1) { + /* (7) down - area mismatch */ + isis_adj_state_change(adj, + ISIS_ADJ_DOWN, + "Area Mismatch"); + + } else if ((adj->adj_usage + == ISIS_ADJ_LEVEL1AND2) + || (adj->adj_usage + == ISIS_ADJ_LEVEL2)) { + /* (7) down - wrong system */ + isis_adj_state_change(adj, + ISIS_ADJ_DOWN, + "Wrong System"); + } + break; + case IS_LEVEL_1_AND_2: + case IS_LEVEL_2: + if (adj->adj_state != ISIS_ADJ_UP) { + /* (8) adj state up */ + isis_adj_state_change(adj, ISIS_ADJ_UP, + NULL); + /* (9) adj usage level 2 */ + adj->adj_usage = ISIS_ADJ_LEVEL2; + } else if (adj->adj_usage == ISIS_ADJ_LEVEL1) { + /* (7) down - wrong system */ + isis_adj_state_change(adj, + ISIS_ADJ_DOWN, + "Wrong System"); + } else if (adj->adj_usage + == ISIS_ADJ_LEVEL1AND2) { + if (hdr->circuit_t == IS_LEVEL_2) { + /* (7) down - wrong system */ + isis_adj_state_change( + adj, ISIS_ADJ_DOWN, + "Wrong System"); + } else { + /* (7) down - area mismatch */ + isis_adj_state_change( + adj, ISIS_ADJ_DOWN, + "Area Mismatch"); + } + } else if (adj->adj_usage == ISIS_ADJ_LEVEL2) { + ; /* Accept */ + } + break; + } } - break; - } + } else { + /* down - area mismatch */ + isis_adj_state_change(adj, ISIS_ADJ_DOWN, "Area Mismatch"); } - } - else - { - /* down - area mismatch */ - isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch"); - } - if (adj->adj_state == ISIS_ADJ_UP && mt_set_changed) - { - lsp_regenerate_schedule(adj->circuit->area, - isis_adj_usage2levels(adj->adj_usage), 0); - } - - /* 8.2.5.2 c) if the action was up - comparing circuit IDs */ - /* FIXME - Missing parts */ + if (adj->adj_state == ISIS_ADJ_UP && mt_set_changed) { + lsp_regenerate_schedule(adj->circuit->area, + isis_adj_usage2levels(adj->adj_usage), + 0); + } - /* some of my own understanding of the ISO, why the heck does - * it not say what should I change the system_type to... - */ - switch (adj->adj_usage) - { - case ISIS_ADJ_LEVEL1: - adj->sys_type = ISIS_SYSTYPE_L1_IS; - break; - case ISIS_ADJ_LEVEL2: - adj->sys_type = ISIS_SYSTYPE_L2_IS; - break; - case ISIS_ADJ_LEVEL1AND2: - adj->sys_type = ISIS_SYSTYPE_L2_IS; - break; - case ISIS_ADJ_NONE: - adj->sys_type = ISIS_SYSTYPE_UNKNOWN; - break; - } + /* 8.2.5.2 c) if the action was up - comparing circuit IDs */ + /* FIXME - Missing parts */ + + /* some of my own understanding of the ISO, why the heck does + * it not say what should I change the system_type to... + */ + switch (adj->adj_usage) { + case ISIS_ADJ_LEVEL1: + adj->sys_type = ISIS_SYSTYPE_L1_IS; + break; + case ISIS_ADJ_LEVEL2: + adj->sys_type = ISIS_SYSTYPE_L2_IS; + break; + case ISIS_ADJ_LEVEL1AND2: + adj->sys_type = ISIS_SYSTYPE_L2_IS; + break; + case ISIS_ADJ_NONE: + adj->sys_type = ISIS_SYSTYPE_UNKNOWN; + break; + } - if (isis->debugs & DEBUG_ADJ_PACKETS) - { - zlog_debug ("ISIS-Adj (%s): Rcvd P2P IIH from (%s), cir type %s," - " cir id %02d, length %d", - circuit->area->area_tag, circuit->interface->name, - circuit_t2string (circuit->is_type), - circuit->circuit_id, pdu_len); - } + if (isis->debugs & DEBUG_ADJ_PACKETS) { + zlog_debug( + "ISIS-Adj (%s): Rcvd P2P IIH from (%s), cir type %s," + " cir id %02d, length %d", + circuit->area->area_tag, circuit->interface->name, + circuit_t2string(circuit->is_type), circuit->circuit_id, + pdu_len); + } - free_tlvs (&tlvs); + free_tlvs(&tlvs); - return retval; + return retval; } /* * Process IS-IS LAN Level 1/2 Hello PDU */ -static int -process_lan_hello (int level, struct isis_circuit *circuit, const u_char *ssnpa) +static int process_lan_hello(int level, struct isis_circuit *circuit, + const u_char *ssnpa) { - int retval = ISIS_OK; - struct isis_lan_hello_hdr hdr; - struct isis_adjacency *adj; - u_int32_t expected = 0, found = 0, auth_tlv_offset = 0; - struct tlvs tlvs; - u_char *snpa; - struct listnode *node; - int v4_usable = 0, v6_usable = 0; - - if (isis->debugs & DEBUG_ADJ_PACKETS) - { - zlog_debug ("ISIS-Adj (%s): Rcvd L%d LAN IIH on %s, cirType %s, " - "cirID %u", - circuit->area->area_tag, level, circuit->interface->name, - circuit_t2string (circuit->is_type), circuit->circuit_id); - if (isis->debugs & DEBUG_PACKET_DUMP) - zlog_dump_data (STREAM_DATA (circuit->rcv_stream), - stream_get_endp (circuit->rcv_stream)); - } + int retval = ISIS_OK; + struct isis_lan_hello_hdr hdr; + struct isis_adjacency *adj; + u_int32_t expected = 0, found = 0, auth_tlv_offset = 0; + struct tlvs tlvs; + u_char *snpa; + struct listnode *node; + int v4_usable = 0, v6_usable = 0; + + if (isis->debugs & DEBUG_ADJ_PACKETS) { + zlog_debug( + "ISIS-Adj (%s): Rcvd L%d LAN IIH on %s, cirType %s, " + "cirID %u", + circuit->area->area_tag, level, + circuit->interface->name, + circuit_t2string(circuit->is_type), + circuit->circuit_id); + if (isis->debugs & DEBUG_PACKET_DUMP) + zlog_dump_data(STREAM_DATA(circuit->rcv_stream), + stream_get_endp(circuit->rcv_stream)); + } - if (circuit->circ_type != CIRCUIT_T_BROADCAST) - { - zlog_warn ("lan hello on non broadcast circuit"); - return ISIS_WARNING; - } + if (circuit->circ_type != CIRCUIT_T_BROADCAST) { + zlog_warn("lan hello on non broadcast circuit"); + return ISIS_WARNING; + } - if ((stream_get_endp (circuit->rcv_stream) - - stream_get_getp (circuit->rcv_stream)) < ISIS_LANHELLO_HDRLEN) - { - zlog_warn ("Packet too short"); - return ISIS_WARNING; - } + if ((stream_get_endp(circuit->rcv_stream) + - stream_get_getp(circuit->rcv_stream)) + < ISIS_LANHELLO_HDRLEN) { + zlog_warn("Packet too short"); + return ISIS_WARNING; + } - if (circuit->ext_domain) - { - zlog_debug ("level %d LAN Hello received over circuit with " - "externalDomain = true", level); - return ISIS_WARNING; - } + if (circuit->ext_domain) { + zlog_debug( + "level %d LAN Hello received over circuit with " + "externalDomain = true", + level); + return ISIS_WARNING; + } - if (!accept_level (level, circuit->is_type)) - { - if (isis->debugs & DEBUG_ADJ_PACKETS) - { - zlog_debug ("ISIS-Adj (%s): Interface level mismatch, %s", - circuit->area->area_tag, circuit->interface->name); + if (!accept_level(level, circuit->is_type)) { + if (isis->debugs & DEBUG_ADJ_PACKETS) { + zlog_debug( + "ISIS-Adj (%s): Interface level mismatch, %s", + circuit->area->area_tag, + circuit->interface->name); + } + return ISIS_WARNING; } - return ISIS_WARNING; - } #if 0 /* Cisco's debug message compatability */ @@ -915,319 +875,304 @@ process_lan_hello (int level, struct isis_circuit *circuit, const u_char *ssnpa) return ISIS_WARNING; } #endif - /* - * Fill the header - */ - hdr.circuit_t = stream_getc (circuit->rcv_stream); - stream_get (hdr.source_id, circuit->rcv_stream, ISIS_SYS_ID_LEN); - hdr.hold_time = stream_getw (circuit->rcv_stream); - hdr.pdu_len = stream_getw (circuit->rcv_stream); - hdr.prio = stream_getc (circuit->rcv_stream); - stream_get (hdr.lan_id, circuit->rcv_stream, ISIS_SYS_ID_LEN + 1); - - if (hdr.pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_LANHELLO_HDRLEN) || - hdr.pdu_len > ISO_MTU(circuit) || - hdr.pdu_len > stream_get_endp (circuit->rcv_stream)) - { - zlog_warn ("ISIS-Adj (%s): Rcvd LAN IIH from (%s) with " - "invalid pdu length %d", - circuit->area->area_tag, circuit->interface->name, - hdr.pdu_len); - return ISIS_WARNING; - } + /* + * Fill the header + */ + hdr.circuit_t = stream_getc(circuit->rcv_stream); + stream_get(hdr.source_id, circuit->rcv_stream, ISIS_SYS_ID_LEN); + hdr.hold_time = stream_getw(circuit->rcv_stream); + hdr.pdu_len = stream_getw(circuit->rcv_stream); + hdr.prio = stream_getc(circuit->rcv_stream); + stream_get(hdr.lan_id, circuit->rcv_stream, ISIS_SYS_ID_LEN + 1); + + if (hdr.pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_LANHELLO_HDRLEN) + || hdr.pdu_len > ISO_MTU(circuit) + || hdr.pdu_len > stream_get_endp(circuit->rcv_stream)) { + zlog_warn( + "ISIS-Adj (%s): Rcvd LAN IIH from (%s) with " + "invalid pdu length %d", + circuit->area->area_tag, circuit->interface->name, + hdr.pdu_len); + return ISIS_WARNING; + } - /* - * Set the stream endp to PDU length, ignoring additional padding - * introduced by transport chips. - */ - if (hdr.pdu_len < stream_get_endp (circuit->rcv_stream)) - stream_set_endp (circuit->rcv_stream, hdr.pdu_len); - - if (hdr.circuit_t != IS_LEVEL_1 && - hdr.circuit_t != IS_LEVEL_2 && - hdr.circuit_t != IS_LEVEL_1_AND_2 && - (level & hdr.circuit_t) == 0) - { - zlog_err ("Level %d LAN Hello with Circuit Type %d", level, - hdr.circuit_t); - return ISIS_ERROR; - } + /* + * Set the stream endp to PDU length, ignoring additional padding + * introduced by transport chips. + */ + if (hdr.pdu_len < stream_get_endp(circuit->rcv_stream)) + stream_set_endp(circuit->rcv_stream, hdr.pdu_len); + + if (hdr.circuit_t != IS_LEVEL_1 && hdr.circuit_t != IS_LEVEL_2 + && hdr.circuit_t != IS_LEVEL_1_AND_2 + && (level & hdr.circuit_t) == 0) { + zlog_err("Level %d LAN Hello with Circuit Type %d", level, + hdr.circuit_t); + return ISIS_ERROR; + } - /* - * Then get the tlvs - */ - expected |= TLVFLAG_AUTH_INFO; - expected |= TLVFLAG_AREA_ADDRS; - expected |= TLVFLAG_LAN_NEIGHS; - expected |= TLVFLAG_NLPID; - expected |= TLVFLAG_IPV4_ADDR; - expected |= TLVFLAG_IPV6_ADDR; - expected |= TLVFLAG_MT_ROUTER_INFORMATION; - - auth_tlv_offset = stream_get_getp (circuit->rcv_stream); - retval = parse_tlvs (circuit->area->area_tag, - STREAM_PNT (circuit->rcv_stream), - hdr.pdu_len - ISIS_LANHELLO_HDRLEN - ISIS_FIXED_HDR_LEN, - &expected, &found, &tlvs, - &auth_tlv_offset); - - if (retval > ISIS_WARNING) - { - zlog_warn ("parse_tlvs() failed"); - goto out; - } + /* + * Then get the tlvs + */ + expected |= TLVFLAG_AUTH_INFO; + expected |= TLVFLAG_AREA_ADDRS; + expected |= TLVFLAG_LAN_NEIGHS; + expected |= TLVFLAG_NLPID; + expected |= TLVFLAG_IPV4_ADDR; + expected |= TLVFLAG_IPV6_ADDR; + expected |= TLVFLAG_MT_ROUTER_INFORMATION; + + auth_tlv_offset = stream_get_getp(circuit->rcv_stream); + retval = parse_tlvs( + circuit->area->area_tag, STREAM_PNT(circuit->rcv_stream), + hdr.pdu_len - ISIS_LANHELLO_HDRLEN - ISIS_FIXED_HDR_LEN, + &expected, &found, &tlvs, &auth_tlv_offset); + + if (retval > ISIS_WARNING) { + zlog_warn("parse_tlvs() failed"); + goto out; + } - if (!(found & TLVFLAG_AREA_ADDRS)) - { - zlog_warn ("No Area addresses TLV in Level %d LAN IS to IS hello", - level); - retval = ISIS_WARNING; - goto out; - } + if (!(found & TLVFLAG_AREA_ADDRS)) { + zlog_warn( + "No Area addresses TLV in Level %d LAN IS to IS hello", + level); + retval = ISIS_WARNING; + goto out; + } - if (!(found & TLVFLAG_NLPID)) - { - zlog_warn ("No supported protocols TLV in Level %d LAN IS to IS hello", - level); - retval = ISIS_WARNING; - goto out; - } + if (!(found & TLVFLAG_NLPID)) { + zlog_warn( + "No supported protocols TLV in Level %d LAN IS to IS hello", + level); + retval = ISIS_WARNING; + goto out; + } - /* Verify authentication, either cleartext of HMAC MD5 */ - if (circuit->passwd.type) - { - if (!(found & TLVFLAG_AUTH_INFO) || - authentication_check (&tlvs.auth_info, &circuit->passwd, - circuit->rcv_stream, auth_tlv_offset)) - { - isis_event_auth_failure (circuit->area->area_tag, - "LAN hello authentication failure", - hdr.source_id); - retval = ISIS_WARNING; - goto out; - } - } + /* Verify authentication, either cleartext of HMAC MD5 */ + if (circuit->passwd.type) { + if (!(found & TLVFLAG_AUTH_INFO) + || authentication_check(&tlvs.auth_info, &circuit->passwd, + circuit->rcv_stream, + auth_tlv_offset)) { + isis_event_auth_failure( + circuit->area->area_tag, + "LAN hello authentication failure", + hdr.source_id); + retval = ISIS_WARNING; + goto out; + } + } - if (!memcmp (hdr.source_id, isis->sysid, ISIS_SYS_ID_LEN)) - { - zlog_warn ("ISIS-Adj (%s): duplicate system ID on interface %s", - circuit->area->area_tag, circuit->interface->name); - return ISIS_WARNING; - } + if (!memcmp(hdr.source_id, isis->sysid, ISIS_SYS_ID_LEN)) { + zlog_warn("ISIS-Adj (%s): duplicate system ID on interface %s", + circuit->area->area_tag, circuit->interface->name); + return ISIS_WARNING; + } - /* - * Accept the level 1 adjacency only if a match between local and - * remote area addresses is found - */ - if (listcount (circuit->area->area_addrs) == 0 || - (level == IS_LEVEL_1 && - area_match (circuit->area->area_addrs, tlvs.area_addrs) == 0)) - { - if (isis->debugs & DEBUG_ADJ_PACKETS) - { - zlog_debug ("ISIS-Adj (%s): Area mismatch, level %d IIH on %s", - circuit->area->area_tag, level, - circuit->interface->name); + /* + * Accept the level 1 adjacency only if a match between local and + * remote area addresses is found + */ + if (listcount(circuit->area->area_addrs) == 0 + || (level == IS_LEVEL_1 + && area_match(circuit->area->area_addrs, tlvs.area_addrs) + == 0)) { + if (isis->debugs & DEBUG_ADJ_PACKETS) { + zlog_debug( + "ISIS-Adj (%s): Area mismatch, level %d IIH on %s", + circuit->area->area_tag, level, + circuit->interface->name); + } + retval = ISIS_OK; + goto out; } - retval = ISIS_OK; - goto out; - } - /* - * it's own IIH PDU - discard silently - */ - if (!memcmp (circuit->u.bc.snpa, ssnpa, ETH_ALEN)) - { - zlog_debug ("ISIS-Adj (%s): it's own IIH PDU - discarded", - circuit->area->area_tag); + /* + * it's own IIH PDU - discard silently + */ + if (!memcmp(circuit->u.bc.snpa, ssnpa, ETH_ALEN)) { + zlog_debug("ISIS-Adj (%s): it's own IIH PDU - discarded", + circuit->area->area_tag); - retval = ISIS_OK; - goto out; - } + retval = ISIS_OK; + goto out; + } - /* - * check if both ends have an IPv4 address - */ - if (circuit->ip_addrs && listcount(circuit->ip_addrs) - && tlvs.ipv4_addrs && listcount(tlvs.ipv4_addrs)) - { - v4_usable = 1; - } + /* + * check if both ends have an IPv4 address + */ + if (circuit->ip_addrs && listcount(circuit->ip_addrs) && tlvs.ipv4_addrs + && listcount(tlvs.ipv4_addrs)) { + v4_usable = 1; + } - if (found & TLVFLAG_IPV6_ADDR) - { - /* TBA: check that we have a linklocal ourselves? */ - struct listnode *node; - struct in6_addr *ip; - for (ALL_LIST_ELEMENTS_RO (tlvs.ipv6_addrs, node, ip)) - if (IN6_IS_ADDR_LINKLOCAL (ip)) - { - v6_usable = 1; - break; - } - - if (!v6_usable) - zlog_warn ("ISIS-Adj: IPv6 addresses present but no link-local " - "in LAN IIH from %s\n", circuit->interface->name); - } + if (found & TLVFLAG_IPV6_ADDR) { + /* TBA: check that we have a linklocal ourselves? */ + struct listnode *node; + struct in6_addr *ip; + for (ALL_LIST_ELEMENTS_RO(tlvs.ipv6_addrs, node, ip)) + if (IN6_IS_ADDR_LINKLOCAL(ip)) { + v6_usable = 1; + break; + } + + if (!v6_usable) + zlog_warn( + "ISIS-Adj: IPv6 addresses present but no link-local " + "in LAN IIH from %s\n", + circuit->interface->name); + } - if (!(found & (TLVFLAG_IPV4_ADDR | TLVFLAG_IPV6_ADDR))) - zlog_warn ("ISIS-Adj: neither IPv4 nor IPv6 addr in LAN IIH from %s\n", - circuit->interface->name); + if (!(found & (TLVFLAG_IPV4_ADDR | TLVFLAG_IPV6_ADDR))) + zlog_warn( + "ISIS-Adj: neither IPv4 nor IPv6 addr in LAN IIH from %s\n", + circuit->interface->name); - if (!v6_usable && !v4_usable) - { - free_tlvs (&tlvs); - return ISIS_WARNING; - } + if (!v6_usable && !v4_usable) { + free_tlvs(&tlvs); + return ISIS_WARNING; + } - adj = isis_adj_lookup (hdr.source_id, circuit->u.bc.adjdb[level - 1]); - if ((adj == NULL) || (memcmp(adj->snpa, ssnpa, ETH_ALEN)) || - (adj->level != level)) - { - if (!adj) - { - /* - * Do as in 8.4.2.5 - */ - adj = isis_new_adj (hdr.source_id, ssnpa, level, circuit); - if (adj == NULL) - { - retval = ISIS_ERROR; - goto out; - } - } - else - { - if (ssnpa) { - memcpy (adj->snpa, ssnpa, 6); - } else { - memset (adj->snpa, ' ', 6); - } - adj->level = level; - } - isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL); - - if (level == IS_LEVEL_1) - adj->sys_type = ISIS_SYSTYPE_L1_IS; - else - adj->sys_type = ISIS_SYSTYPE_L2_IS; - list_delete_all_node (circuit->u.bc.lan_neighs[level - 1]); - isis_adj_build_neigh_list (circuit->u.bc.adjdb[level - 1], - circuit->u.bc.lan_neighs[level - 1]); - } - - if(adj->dis_record[level-1].dis==ISIS_IS_DIS) - switch (level) - { - case 1: - if (memcmp (circuit->u.bc.l1_desig_is, hdr.lan_id, ISIS_SYS_ID_LEN + 1)) - { - thread_add_event(master, isis_event_dis_status_change, circuit, 0, - NULL); - memcpy (&circuit->u.bc.l1_desig_is, hdr.lan_id, - ISIS_SYS_ID_LEN + 1); - } - break; - case 2: - if (memcmp (circuit->u.bc.l2_desig_is, hdr.lan_id, ISIS_SYS_ID_LEN + 1)) - { - thread_add_event(master, isis_event_dis_status_change, circuit, 0, - NULL); - memcpy (&circuit->u.bc.l2_desig_is, hdr.lan_id, - ISIS_SYS_ID_LEN + 1); - } - break; - } - - adj->hold_time = hdr.hold_time; - adj->last_upd = time (NULL); - adj->prio[level - 1] = hdr.prio; - - memcpy (adj->lanid, hdr.lan_id, ISIS_SYS_ID_LEN + 1); - - tlvs_to_adj_area_addrs (&tlvs, adj); - - /* which protocol are spoken ??? */ - if (tlvs_to_adj_nlpids (&tlvs, adj)) - { - retval = ISIS_WARNING; - goto out; - } + adj = isis_adj_lookup(hdr.source_id, circuit->u.bc.adjdb[level - 1]); + if ((adj == NULL) || (memcmp(adj->snpa, ssnpa, ETH_ALEN)) + || (adj->level != level)) { + if (!adj) { + /* + * Do as in 8.4.2.5 + */ + adj = isis_new_adj(hdr.source_id, ssnpa, level, + circuit); + if (adj == NULL) { + retval = ISIS_ERROR; + goto out; + } + } else { + if (ssnpa) { + memcpy(adj->snpa, ssnpa, 6); + } else { + memset(adj->snpa, ' ', 6); + } + adj->level = level; + } + isis_adj_state_change(adj, ISIS_ADJ_INITIALIZING, NULL); - /* we need to copy addresses to the adj */ - if (found & TLVFLAG_IPV4_ADDR) - tlvs_to_adj_ipv4_addrs (&tlvs, adj); + if (level == IS_LEVEL_1) + adj->sys_type = ISIS_SYSTYPE_L1_IS; + else + adj->sys_type = ISIS_SYSTYPE_L2_IS; + list_delete_all_node(circuit->u.bc.lan_neighs[level - 1]); + isis_adj_build_neigh_list(circuit->u.bc.adjdb[level - 1], + circuit->u.bc.lan_neighs[level - 1]); + } - if (found & TLVFLAG_IPV6_ADDR) - tlvs_to_adj_ipv6_addrs (&tlvs, adj); + if (adj->dis_record[level - 1].dis == ISIS_IS_DIS) + switch (level) { + case 1: + if (memcmp(circuit->u.bc.l1_desig_is, hdr.lan_id, + ISIS_SYS_ID_LEN + 1)) { + thread_add_event(master, + isis_event_dis_status_change, + circuit, 0, NULL); + memcpy(&circuit->u.bc.l1_desig_is, hdr.lan_id, + ISIS_SYS_ID_LEN + 1); + } + break; + case 2: + if (memcmp(circuit->u.bc.l2_desig_is, hdr.lan_id, + ISIS_SYS_ID_LEN + 1)) { + thread_add_event(master, + isis_event_dis_status_change, + circuit, 0, NULL); + memcpy(&circuit->u.bc.l2_desig_is, hdr.lan_id, + ISIS_SYS_ID_LEN + 1); + } + break; + } - adj->circuit_t = hdr.circuit_t; + adj->hold_time = hdr.hold_time; + adj->last_upd = time(NULL); + adj->prio[level - 1] = hdr.prio; - bool mt_set_changed = tlvs_to_adj_mt_set(&tlvs, v4_usable, v6_usable, adj); + memcpy(adj->lanid, hdr.lan_id, ISIS_SYS_ID_LEN + 1); - /* lets take care of the expiry */ - THREAD_TIMER_OFF (adj->t_expire); - thread_add_timer(master, isis_adj_expire, adj, (long)adj->hold_time, - &adj->t_expire); + tlvs_to_adj_area_addrs(&tlvs, adj); - /* - * If the snpa for this circuit is found from LAN Neighbours TLV - * we have two-way communication -> adjacency can be put to state "up" - */ + /* which protocol are spoken ??? */ + if (tlvs_to_adj_nlpids(&tlvs, adj)) { + retval = ISIS_WARNING; + goto out; + } - if (found & TLVFLAG_LAN_NEIGHS) - { - if (adj->adj_state != ISIS_ADJ_UP) - { - for (ALL_LIST_ELEMENTS_RO (tlvs.lan_neighs, node, snpa)) - { - if (!memcmp (snpa, circuit->u.bc.snpa, ETH_ALEN)) - { - isis_adj_state_change (adj, ISIS_ADJ_UP, - "own SNPA found in LAN Neighbours TLV"); - } - } - } - else - { - int found = 0; - for (ALL_LIST_ELEMENTS_RO (tlvs.lan_neighs, node, snpa)) - if (!memcmp (snpa, circuit->u.bc.snpa, ETH_ALEN)) - { - found = 1; - break; - } - if (found == 0) - isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, - "own SNPA not found in LAN Neighbours TLV"); - } - } - else if (adj->adj_state == ISIS_ADJ_UP) - { - isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, - "no LAN Neighbours TLV found"); - } + /* we need to copy addresses to the adj */ + if (found & TLVFLAG_IPV4_ADDR) + tlvs_to_adj_ipv4_addrs(&tlvs, adj); + + if (found & TLVFLAG_IPV6_ADDR) + tlvs_to_adj_ipv6_addrs(&tlvs, adj); + + adj->circuit_t = hdr.circuit_t; + + bool mt_set_changed = + tlvs_to_adj_mt_set(&tlvs, v4_usable, v6_usable, adj); + + /* lets take care of the expiry */ + THREAD_TIMER_OFF(adj->t_expire); + thread_add_timer(master, isis_adj_expire, adj, (long)adj->hold_time, + &adj->t_expire); + + /* + * If the snpa for this circuit is found from LAN Neighbours TLV + * we have two-way communication -> adjacency can be put to state "up" + */ + + if (found & TLVFLAG_LAN_NEIGHS) { + if (adj->adj_state != ISIS_ADJ_UP) { + for (ALL_LIST_ELEMENTS_RO(tlvs.lan_neighs, node, + snpa)) { + if (!memcmp(snpa, circuit->u.bc.snpa, + ETH_ALEN)) { + isis_adj_state_change( + adj, ISIS_ADJ_UP, + "own SNPA found in LAN Neighbours TLV"); + } + } + } else { + int found = 0; + for (ALL_LIST_ELEMENTS_RO(tlvs.lan_neighs, node, snpa)) + if (!memcmp(snpa, circuit->u.bc.snpa, + ETH_ALEN)) { + found = 1; + break; + } + if (found == 0) + isis_adj_state_change( + adj, ISIS_ADJ_INITIALIZING, + "own SNPA not found in LAN Neighbours TLV"); + } + } else if (adj->adj_state == ISIS_ADJ_UP) { + isis_adj_state_change(adj, ISIS_ADJ_INITIALIZING, + "no LAN Neighbours TLV found"); + } - if (adj->adj_state == ISIS_ADJ_UP && mt_set_changed) - lsp_regenerate_schedule(adj->circuit->area, level, 0); + if (adj->adj_state == ISIS_ADJ_UP && mt_set_changed) + lsp_regenerate_schedule(adj->circuit->area, level, 0); out: - if (isis->debugs & DEBUG_ADJ_PACKETS) - { - zlog_debug ("ISIS-Adj (%s): Rcvd L%d LAN IIH from %s on %s, cirType %s, " - "cirID %u, length %zd", - circuit->area->area_tag, - level, snpa_print (ssnpa), circuit->interface->name, - circuit_t2string (circuit->is_type), - circuit->circuit_id, - stream_get_endp (circuit->rcv_stream)); - } + if (isis->debugs & DEBUG_ADJ_PACKETS) { + zlog_debug( + "ISIS-Adj (%s): Rcvd L%d LAN IIH from %s on %s, cirType %s, " + "cirID %u, length %zd", + circuit->area->area_tag, level, snpa_print(ssnpa), + circuit->interface->name, + circuit_t2string(circuit->is_type), circuit->circuit_id, + stream_get_endp(circuit->rcv_stream)); + } - free_tlvs (&tlvs); + free_tlvs(&tlvs); - return retval; + return retval; } /* @@ -1235,364 +1180,363 @@ out: * ISO - 10589 * Section 7.3.15.1 - Action on receipt of a link state PDU */ -static int -process_lsp (int level, struct isis_circuit *circuit, const u_char *ssnpa) +static int process_lsp(int level, struct isis_circuit *circuit, + const u_char *ssnpa) { - struct isis_link_state_hdr *hdr; - struct isis_adjacency *adj = NULL; - struct isis_lsp *lsp, *lsp0 = NULL; - int retval = ISIS_OK, comp = 0; - u_char lspid[ISIS_SYS_ID_LEN + 2]; - struct isis_passwd *passwd; - uint16_t pdu_len; - int lsp_confusion; - - if (isis->debugs & DEBUG_UPDATE_PACKETS) - { - zlog_debug ("ISIS-Upd (%s): Rcvd L%d LSP on %s, cirType %s, cirID %u", - circuit->area->area_tag, level, circuit->interface->name, - circuit_t2string (circuit->is_type), circuit->circuit_id); - if (isis->debugs & DEBUG_PACKET_DUMP) - zlog_dump_data (STREAM_DATA (circuit->rcv_stream), - stream_get_endp (circuit->rcv_stream)); - } - - if ((stream_get_endp (circuit->rcv_stream) - - stream_get_getp (circuit->rcv_stream)) < ISIS_LSP_HDR_LEN) - { - zlog_warn ("Packet too short"); - return ISIS_WARNING; - } - - /* Reference the header */ - hdr = (struct isis_link_state_hdr *) STREAM_PNT (circuit->rcv_stream); - pdu_len = ntohs (hdr->pdu_len); - - /* lsp length check */ - if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN) || - pdu_len > ISO_MTU(circuit) || - pdu_len > stream_get_endp (circuit->rcv_stream)) - { - zlog_debug ("ISIS-Upd (%s): LSP %s invalid LSP length %d", - circuit->area->area_tag, - rawlspid_print (hdr->lsp_id), pdu_len); - - return ISIS_WARNING; - } - - /* - * Set the stream endp to PDU length, ignoring additional padding - * introduced by transport chips. - */ - if (pdu_len < stream_get_endp (circuit->rcv_stream)) - stream_set_endp (circuit->rcv_stream, pdu_len); - - if (isis->debugs & DEBUG_UPDATE_PACKETS) - { - zlog_debug ("ISIS-Upd (%s): Rcvd L%d LSP %s, seq 0x%08x, cksum 0x%04x, " - "lifetime %us, len %u, on %s", - circuit->area->area_tag, - level, - rawlspid_print (hdr->lsp_id), - ntohl (hdr->seq_num), - ntohs (hdr->checksum), - ntohs (hdr->rem_lifetime), - pdu_len, - circuit->interface->name); - } - - /* lsp is_type check */ - if ((hdr->lsp_bits & IS_LEVEL_1_AND_2) != IS_LEVEL_1 && - (hdr->lsp_bits & IS_LEVEL_1_AND_2) != IS_LEVEL_1_AND_2) - { - zlog_debug ("ISIS-Upd (%s): LSP %s invalid LSP is type %x", - circuit->area->area_tag, - rawlspid_print (hdr->lsp_id), hdr->lsp_bits); - /* continue as per RFC1122 Be liberal in what you accept, and - * conservative in what you send */ - } - - /* Checksum sanity check - FIXME: move to correct place */ - /* 12 = sysid+pdu+remtime */ - if (iso_csum_verify (STREAM_PNT (circuit->rcv_stream) + 4, - pdu_len - 12, hdr->checksum, - offsetof(struct isis_link_state_hdr, checksum) - 4)) - { - zlog_debug ("ISIS-Upd (%s): LSP %s invalid LSP checksum 0x%04x", - circuit->area->area_tag, - rawlspid_print (hdr->lsp_id), ntohs (hdr->checksum)); - - return ISIS_WARNING; - } - - /* 7.3.15.1 a) 1 - external domain circuit will discard lsps */ - if (circuit->ext_domain) - { - zlog_debug - ("ISIS-Upd (%s): LSP %s received at level %d over circuit with " - "externalDomain = true", circuit->area->area_tag, - rawlspid_print (hdr->lsp_id), level); - - return ISIS_WARNING; - } - - /* 7.3.15.1 a) 2,3 - manualL2OnlyMode not implemented */ - if (!accept_level (level, circuit->is_type)) - { - zlog_debug ("ISIS-Upd (%s): LSP %s received at level %d over circuit of" - " type %s", - circuit->area->area_tag, - rawlspid_print (hdr->lsp_id), - level, circuit_t2string (circuit->is_type)); + struct isis_link_state_hdr *hdr; + struct isis_adjacency *adj = NULL; + struct isis_lsp *lsp, *lsp0 = NULL; + int retval = ISIS_OK, comp = 0; + u_char lspid[ISIS_SYS_ID_LEN + 2]; + struct isis_passwd *passwd; + uint16_t pdu_len; + int lsp_confusion; + + if (isis->debugs & DEBUG_UPDATE_PACKETS) { + zlog_debug( + "ISIS-Upd (%s): Rcvd L%d LSP on %s, cirType %s, cirID %u", + circuit->area->area_tag, level, + circuit->interface->name, + circuit_t2string(circuit->is_type), + circuit->circuit_id); + if (isis->debugs & DEBUG_PACKET_DUMP) + zlog_dump_data(STREAM_DATA(circuit->rcv_stream), + stream_get_endp(circuit->rcv_stream)); + } - return ISIS_WARNING; - } + if ((stream_get_endp(circuit->rcv_stream) + - stream_get_getp(circuit->rcv_stream)) + < ISIS_LSP_HDR_LEN) { + zlog_warn("Packet too short"); + return ISIS_WARNING; + } - /* 7.3.15.1 a) 4 - need to make sure IDLength matches */ + /* Reference the header */ + hdr = (struct isis_link_state_hdr *)STREAM_PNT(circuit->rcv_stream); + pdu_len = ntohs(hdr->pdu_len); - /* 7.3.15.1 a) 5 - maximum area match, can be ommited since we only use 3 */ + /* lsp length check */ + if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN) + || pdu_len > ISO_MTU(circuit) + || pdu_len > stream_get_endp(circuit->rcv_stream)) { + zlog_debug("ISIS-Upd (%s): LSP %s invalid LSP length %d", + circuit->area->area_tag, rawlspid_print(hdr->lsp_id), + pdu_len); - /* 7.3.15.1 a) 7 - password check */ - (level == IS_LEVEL_1) ? (passwd = &circuit->area->area_passwd) : - (passwd = &circuit->area->domain_passwd); - if (passwd->type) - { - if (lsp_authentication_check (circuit->rcv_stream, circuit->area, - level, passwd)) - { - isis_event_auth_failure (circuit->area->area_tag, - "LSP authentication failure", hdr->lsp_id); - return ISIS_WARNING; + return ISIS_WARNING; } - } - /* Find the LSP in our database and compare it to this Link State header */ - lsp = lsp_search (hdr->lsp_id, circuit->area->lspdb[level - 1]); - if (lsp) - comp = lsp_compare (circuit->area->area_tag, lsp, hdr->seq_num, - hdr->checksum, hdr->rem_lifetime); - if (lsp && (lsp->own_lsp)) - goto dontcheckadj; - - /* 7.3.15.1 a) 6 - Must check that we have an adjacency of the same level */ - /* for broadcast circuits, snpa should be compared */ - - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - { - adj = isis_adj_lookup_snpa (ssnpa, circuit->u.bc.adjdb[level - 1]); - if (!adj) - { - zlog_debug ("(%s): DS ======= LSP %s, seq 0x%08x, cksum 0x%04x, " - "lifetime %us on %s", - circuit->area->area_tag, - rawlspid_print (hdr->lsp_id), - ntohl (hdr->seq_num), - ntohs (hdr->checksum), - ntohs (hdr->rem_lifetime), circuit->interface->name); - return ISIS_WARNING; /* Silently discard */ + + /* + * Set the stream endp to PDU length, ignoring additional padding + * introduced by transport chips. + */ + if (pdu_len < stream_get_endp(circuit->rcv_stream)) + stream_set_endp(circuit->rcv_stream, pdu_len); + + if (isis->debugs & DEBUG_UPDATE_PACKETS) { + zlog_debug( + "ISIS-Upd (%s): Rcvd L%d LSP %s, seq 0x%08x, cksum 0x%04x, " + "lifetime %us, len %u, on %s", + circuit->area->area_tag, level, + rawlspid_print(hdr->lsp_id), ntohl(hdr->seq_num), + ntohs(hdr->checksum), ntohs(hdr->rem_lifetime), pdu_len, + circuit->interface->name); } - } - /* for non broadcast, we just need to find same level adj */ - else - { - /* If no adj, or no sharing of level */ - if (!circuit->u.p2p.neighbor) - { - return ISIS_OK; /* Silently discard */ + + /* lsp is_type check */ + if ((hdr->lsp_bits & IS_LEVEL_1_AND_2) != IS_LEVEL_1 + && (hdr->lsp_bits & IS_LEVEL_1_AND_2) != IS_LEVEL_1_AND_2) { + zlog_debug("ISIS-Upd (%s): LSP %s invalid LSP is type %x", + circuit->area->area_tag, rawlspid_print(hdr->lsp_id), + hdr->lsp_bits); + /* continue as per RFC1122 Be liberal in what you accept, and + * conservative in what you send */ } - else - { - if (((level == IS_LEVEL_1) && - (circuit->u.p2p.neighbor->adj_usage == ISIS_ADJ_LEVEL2)) || - ((level == IS_LEVEL_2) && - (circuit->u.p2p.neighbor->adj_usage == ISIS_ADJ_LEVEL1))) - return ISIS_WARNING; /* Silently discard */ + + /* Checksum sanity check - FIXME: move to correct place */ + /* 12 = sysid+pdu+remtime */ + if (iso_csum_verify(STREAM_PNT(circuit->rcv_stream) + 4, pdu_len - 12, + hdr->checksum, + offsetof(struct isis_link_state_hdr, checksum) + - 4)) { + zlog_debug("ISIS-Upd (%s): LSP %s invalid LSP checksum 0x%04x", + circuit->area->area_tag, rawlspid_print(hdr->lsp_id), + ntohs(hdr->checksum)); + + return ISIS_WARNING; } - } -dontcheckadj: - /* 7.3.15.1 a) 7 - Passwords for level 1 - not implemented */ + /* 7.3.15.1 a) 1 - external domain circuit will discard lsps */ + if (circuit->ext_domain) { + zlog_debug( + "ISIS-Upd (%s): LSP %s received at level %d over circuit with " + "externalDomain = true", + circuit->area->area_tag, rawlspid_print(hdr->lsp_id), + level); - /* 7.3.15.1 a) 8 - Passwords for level 2 - not implemented */ + return ISIS_WARNING; + } - /* 7.3.15.1 a) 9 - OriginatingLSPBufferSize - not implemented FIXME: do it */ + /* 7.3.15.1 a) 2,3 - manualL2OnlyMode not implemented */ + if (!accept_level(level, circuit->is_type)) { + zlog_debug( + "ISIS-Upd (%s): LSP %s received at level %d over circuit of" + " type %s", + circuit->area->area_tag, rawlspid_print(hdr->lsp_id), + level, circuit_t2string(circuit->is_type)); - /* 7.3.16.2 - If this is an LSP from another IS with identical seq_num but - * wrong checksum, initiate a purge. */ - if (lsp - && (lsp->lsp_header->seq_num == hdr->seq_num) - && (lsp->lsp_header->checksum != hdr->checksum)) - { - zlog_warn("ISIS-Upd (%s): LSP %s seq 0x%08x with confused checksum received.", - circuit->area->area_tag, rawlspid_print(hdr->lsp_id), - ntohl(hdr->seq_num)); - hdr->rem_lifetime = 0; - lsp_confusion = 1; - } - else - lsp_confusion = 0; + return ISIS_WARNING; + } - /* 7.3.15.1 b) - If the remaining life time is 0, we perform 7.3.16.4 */ - if (hdr->rem_lifetime == 0) - { - if (!lsp) - { - /* 7.3.16.4 a) 1) No LSP in db -> send an ack, but don't save */ - /* only needed on explicit update, eg - p2p */ - if (circuit->circ_type == CIRCUIT_T_P2P) - ack_lsp (hdr, circuit, level); - return retval; /* FIXME: do we need a purge? */ + /* 7.3.15.1 a) 4 - need to make sure IDLength matches */ + + /* 7.3.15.1 a) 5 - maximum area match, can be ommited since we only use + * 3 */ + + /* 7.3.15.1 a) 7 - password check */ + (level == IS_LEVEL_1) ? (passwd = &circuit->area->area_passwd) + : (passwd = &circuit->area->domain_passwd); + if (passwd->type) { + if (lsp_authentication_check(circuit->rcv_stream, circuit->area, + level, passwd)) { + isis_event_auth_failure(circuit->area->area_tag, + "LSP authentication failure", + hdr->lsp_id); + return ISIS_WARNING; + } } - else - { - if (memcmp (hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN)) - { - /* LSP by some other system -> do 7.3.16.4 b) */ - /* 7.3.16.4 b) 1) */ - if (comp == LSP_NEWER) - { - lsp_update (lsp, circuit->rcv_stream, circuit->area, level); - /* ii */ - lsp_set_all_srmflags (lsp); - /* v */ - ISIS_FLAGS_CLEAR_ALL (lsp->SSNflags); /* FIXME: OTHER than c */ - - /* For the case of lsp confusion, flood the purge back to its - * originator so that it can react. Otherwise, don't reflood - * through incoming circuit as usual */ - if (!lsp_confusion) - { - /* iii */ - ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); - /* iv */ - if (circuit->circ_type != CIRCUIT_T_BROADCAST) - ISIS_SET_FLAG (lsp->SSNflags, circuit); - } - } /* 7.3.16.4 b) 2) */ - else if (comp == LSP_EQUAL) - { - /* i */ - ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); - /* ii */ - if (circuit->circ_type != CIRCUIT_T_BROADCAST) - ISIS_SET_FLAG (lsp->SSNflags, circuit); - } /* 7.3.16.4 b) 3) */ - else - { - ISIS_SET_FLAG (lsp->SRMflags, circuit); - ISIS_CLEAR_FLAG (lsp->SSNflags, circuit); + /* Find the LSP in our database and compare it to this Link State header + */ + lsp = lsp_search(hdr->lsp_id, circuit->area->lspdb[level - 1]); + if (lsp) + comp = lsp_compare(circuit->area->area_tag, lsp, hdr->seq_num, + hdr->checksum, hdr->rem_lifetime); + if (lsp && (lsp->own_lsp)) + goto dontcheckadj; + + /* 7.3.15.1 a) 6 - Must check that we have an adjacency of the same + * level */ + /* for broadcast circuits, snpa should be compared */ + + if (circuit->circ_type == CIRCUIT_T_BROADCAST) { + adj = isis_adj_lookup_snpa(ssnpa, + circuit->u.bc.adjdb[level - 1]); + if (!adj) { + zlog_debug( + "(%s): DS ======= LSP %s, seq 0x%08x, cksum 0x%04x, " + "lifetime %us on %s", + circuit->area->area_tag, + rawlspid_print(hdr->lsp_id), + ntohl(hdr->seq_num), ntohs(hdr->checksum), + ntohs(hdr->rem_lifetime), + circuit->interface->name); + return ISIS_WARNING; /* Silently discard */ + } + } + /* for non broadcast, we just need to find same level adj */ + else { + /* If no adj, or no sharing of level */ + if (!circuit->u.p2p.neighbor) { + return ISIS_OK; /* Silently discard */ + } else { + if (((level == IS_LEVEL_1) + && (circuit->u.p2p.neighbor->adj_usage + == ISIS_ADJ_LEVEL2)) + || ((level == IS_LEVEL_2) + && (circuit->u.p2p.neighbor->adj_usage + == ISIS_ADJ_LEVEL1))) + return ISIS_WARNING; /* Silently discard */ } - } - else if (lsp->lsp_header->rem_lifetime != 0) - { - /* our own LSP -> 7.3.16.4 c) */ - if (comp == LSP_NEWER) - { - lsp_inc_seqnum (lsp, ntohl (hdr->seq_num)); - lsp_set_all_srmflags (lsp); - } - else - { - ISIS_SET_FLAG (lsp->SRMflags, circuit); - ISIS_CLEAR_FLAG (lsp->SSNflags, circuit); - } - if (isis->debugs & DEBUG_UPDATE_PACKETS) - zlog_debug ("ISIS-Upd (%s): (1) re-originating LSP %s new " - "seq 0x%08x", circuit->area->area_tag, - rawlspid_print (hdr->lsp_id), - ntohl (lsp->lsp_header->seq_num)); - } - } - return retval; - } - /* 7.3.15.1 c) - If this is our own lsp and we don't have it initiate a - * purge */ - if (memcmp (hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN) == 0) - { - if (!lsp) - { - /* 7.3.16.4: initiate a purge */ - lsp_purge_non_exist(level, hdr, circuit->area); - return ISIS_OK; } - /* 7.3.15.1 d) - If this is our own lsp and we have it */ - - /* In 7.3.16.1, If an Intermediate system R somewhere in the domain - * has information that the current sequence number for source S is - * "greater" than that held by S, ... */ - - if (ntohl (hdr->seq_num) > ntohl (lsp->lsp_header->seq_num)) - { - /* 7.3.16.1 */ - lsp_inc_seqnum (lsp, ntohl (hdr->seq_num)); - if (isis->debugs & DEBUG_UPDATE_PACKETS) - zlog_debug ("ISIS-Upd (%s): (2) re-originating LSP %s new seq " - "0x%08x", circuit->area->area_tag, - rawlspid_print (hdr->lsp_id), - ntohl (lsp->lsp_header->seq_num)); - } - /* If the received LSP is older or equal, - * resend the LSP which will act as ACK */ - lsp_set_all_srmflags (lsp); - } - else - { - /* 7.3.15.1 e) - This lsp originated on another system */ - /* 7.3.15.1 e) 1) LSP newer than the one in db or no LSP in db */ - if ((!lsp || comp == LSP_NEWER)) - { - /* - * If this lsp is a frag, need to see if we have zero lsp present - */ - if (LSP_FRAGMENT (hdr->lsp_id) != 0) - { - memcpy (lspid, hdr->lsp_id, ISIS_SYS_ID_LEN + 1); - LSP_FRAGMENT (lspid) = 0; - lsp0 = lsp_search (lspid, circuit->area->lspdb[level - 1]); - if (!lsp0) - { - zlog_debug ("Got lsp frag, while zero lsp not in database"); - return ISIS_OK; +dontcheckadj: + /* 7.3.15.1 a) 7 - Passwords for level 1 - not implemented */ + + /* 7.3.15.1 a) 8 - Passwords for level 2 - not implemented */ + + /* 7.3.15.1 a) 9 - OriginatingLSPBufferSize - not implemented FIXME: do + * it */ + + /* 7.3.16.2 - If this is an LSP from another IS with identical seq_num + * but + * wrong checksum, initiate a purge. */ + if (lsp && (lsp->lsp_header->seq_num == hdr->seq_num) + && (lsp->lsp_header->checksum != hdr->checksum)) { + zlog_warn( + "ISIS-Upd (%s): LSP %s seq 0x%08x with confused checksum received.", + circuit->area->area_tag, rawlspid_print(hdr->lsp_id), + ntohl(hdr->seq_num)); + hdr->rem_lifetime = 0; + lsp_confusion = 1; + } else + lsp_confusion = 0; + + /* 7.3.15.1 b) - If the remaining life time is 0, we perform 7.3.16.4 */ + if (hdr->rem_lifetime == 0) { + if (!lsp) { + /* 7.3.16.4 a) 1) No LSP in db -> send an ack, but don't + * save */ + /* only needed on explicit update, eg - p2p */ + if (circuit->circ_type == CIRCUIT_T_P2P) + ack_lsp(hdr, circuit, level); + return retval; /* FIXME: do we need a purge? */ + } else { + if (memcmp(hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN)) { + /* LSP by some other system -> do 7.3.16.4 b) */ + /* 7.3.16.4 b) 1) */ + if (comp == LSP_NEWER) { + lsp_update(lsp, circuit->rcv_stream, + circuit->area, level); + /* ii */ + lsp_set_all_srmflags(lsp); + /* v */ + ISIS_FLAGS_CLEAR_ALL( + lsp + ->SSNflags); /* FIXME: + OTHER + than c + */ + + /* For the case of lsp confusion, flood + * the purge back to its + * originator so that it can react. + * Otherwise, don't reflood + * through incoming circuit as usual */ + if (!lsp_confusion) { + /* iii */ + ISIS_CLEAR_FLAG(lsp->SRMflags, + circuit); + /* iv */ + if (circuit->circ_type + != CIRCUIT_T_BROADCAST) + ISIS_SET_FLAG( + lsp->SSNflags, + circuit); + } + } /* 7.3.16.4 b) 2) */ + else if (comp == LSP_EQUAL) { + /* i */ + ISIS_CLEAR_FLAG(lsp->SRMflags, circuit); + /* ii */ + if (circuit->circ_type + != CIRCUIT_T_BROADCAST) + ISIS_SET_FLAG(lsp->SSNflags, + circuit); + } /* 7.3.16.4 b) 3) */ + else { + ISIS_SET_FLAG(lsp->SRMflags, circuit); + ISIS_CLEAR_FLAG(lsp->SSNflags, circuit); + } + } else if (lsp->lsp_header->rem_lifetime != 0) { + /* our own LSP -> 7.3.16.4 c) */ + if (comp == LSP_NEWER) { + lsp_inc_seqnum(lsp, + ntohl(hdr->seq_num)); + lsp_set_all_srmflags(lsp); + } else { + ISIS_SET_FLAG(lsp->SRMflags, circuit); + ISIS_CLEAR_FLAG(lsp->SSNflags, circuit); + } + if (isis->debugs & DEBUG_UPDATE_PACKETS) + zlog_debug( + "ISIS-Upd (%s): (1) re-originating LSP %s new " + "seq 0x%08x", + circuit->area->area_tag, + rawlspid_print(hdr->lsp_id), + ntohl(lsp->lsp_header + ->seq_num)); + } } - } - /* i */ - if (!lsp) - { - lsp = lsp_new_from_stream_ptr (circuit->rcv_stream, - pdu_len, lsp0, - circuit->area, level); - lsp_insert (lsp, circuit->area->lspdb[level - 1]); - } - else /* exists, so we overwrite */ - { - lsp_update (lsp, circuit->rcv_stream, circuit->area, level); - } - /* ii */ - lsp_set_all_srmflags (lsp); - /* iii */ - ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); - - /* iv */ - if (circuit->circ_type != CIRCUIT_T_BROADCAST) - ISIS_SET_FLAG (lsp->SSNflags, circuit); - /* FIXME: v) */ - } - /* 7.3.15.1 e) 2) LSP equal to the one in db */ - else if (comp == LSP_EQUAL) - { - ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); - lsp_update (lsp, circuit->rcv_stream, circuit->area, level); - if (circuit->circ_type != CIRCUIT_T_BROADCAST) - ISIS_SET_FLAG (lsp->SSNflags, circuit); + return retval; } - /* 7.3.15.1 e) 3) LSP older than the one in db */ - else - { - ISIS_SET_FLAG (lsp->SRMflags, circuit); - ISIS_CLEAR_FLAG (lsp->SSNflags, circuit); + /* 7.3.15.1 c) - If this is our own lsp and we don't have it initiate a + * purge */ + if (memcmp(hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN) == 0) { + if (!lsp) { + /* 7.3.16.4: initiate a purge */ + lsp_purge_non_exist(level, hdr, circuit->area); + return ISIS_OK; + } + /* 7.3.15.1 d) - If this is our own lsp and we have it */ + + /* In 7.3.16.1, If an Intermediate system R somewhere in the + * domain + * has information that the current sequence number for source S + * is + * "greater" than that held by S, ... */ + + if (ntohl(hdr->seq_num) > ntohl(lsp->lsp_header->seq_num)) { + /* 7.3.16.1 */ + lsp_inc_seqnum(lsp, ntohl(hdr->seq_num)); + if (isis->debugs & DEBUG_UPDATE_PACKETS) + zlog_debug( + "ISIS-Upd (%s): (2) re-originating LSP %s new seq " + "0x%08x", + circuit->area->area_tag, + rawlspid_print(hdr->lsp_id), + ntohl(lsp->lsp_header->seq_num)); + } + /* If the received LSP is older or equal, + * resend the LSP which will act as ACK */ + lsp_set_all_srmflags(lsp); + } else { + /* 7.3.15.1 e) - This lsp originated on another system */ + + /* 7.3.15.1 e) 1) LSP newer than the one in db or no LSP in db + */ + if ((!lsp || comp == LSP_NEWER)) { + /* + * If this lsp is a frag, need to see if we have zero + * lsp present + */ + if (LSP_FRAGMENT(hdr->lsp_id) != 0) { + memcpy(lspid, hdr->lsp_id, ISIS_SYS_ID_LEN + 1); + LSP_FRAGMENT(lspid) = 0; + lsp0 = lsp_search( + lspid, circuit->area->lspdb[level - 1]); + if (!lsp0) { + zlog_debug( + "Got lsp frag, while zero lsp not in database"); + return ISIS_OK; + } + } + /* i */ + if (!lsp) { + lsp = lsp_new_from_stream_ptr( + circuit->rcv_stream, pdu_len, lsp0, + circuit->area, level); + lsp_insert(lsp, + circuit->area->lspdb[level - 1]); + } else /* exists, so we overwrite */ + { + lsp_update(lsp, circuit->rcv_stream, + circuit->area, level); + } + /* ii */ + lsp_set_all_srmflags(lsp); + /* iii */ + ISIS_CLEAR_FLAG(lsp->SRMflags, circuit); + + /* iv */ + if (circuit->circ_type != CIRCUIT_T_BROADCAST) + ISIS_SET_FLAG(lsp->SSNflags, circuit); + /* FIXME: v) */ + } + /* 7.3.15.1 e) 2) LSP equal to the one in db */ + else if (comp == LSP_EQUAL) { + ISIS_CLEAR_FLAG(lsp->SRMflags, circuit); + lsp_update(lsp, circuit->rcv_stream, circuit->area, + level); + if (circuit->circ_type != CIRCUIT_T_BROADCAST) + ISIS_SET_FLAG(lsp->SSNflags, circuit); + } + /* 7.3.15.1 e) 3) LSP older than the one in db */ + else { + ISIS_SET_FLAG(lsp->SRMflags, circuit); + ISIS_CLEAR_FLAG(lsp->SSNflags, circuit); + } } - } - return retval; + return retval; } /* @@ -1601,1570 +1545,1528 @@ dontcheckadj: * Section 7.3.15.2 - Action on receipt of a sequence numbers PDU */ -static int -process_snp (int snp_type, int level, struct isis_circuit *circuit, - const u_char *ssnpa) +static int process_snp(int snp_type, int level, struct isis_circuit *circuit, + const u_char *ssnpa) { - int retval = ISIS_OK; - int cmp, own_lsp; - char typechar = ' '; - uint16_t pdu_len; - struct isis_adjacency *adj; - struct isis_complete_seqnum_hdr *chdr = NULL; - struct isis_partial_seqnum_hdr *phdr = NULL; - uint32_t found = 0, expected = 0, auth_tlv_offset = 0; - struct isis_lsp *lsp; - struct lsp_entry *entry; - struct listnode *node, *nnode; - struct listnode *node2, *nnode2; - struct tlvs tlvs; - struct list *lsp_list = NULL; - struct isis_passwd *passwd; - - if (snp_type == ISIS_SNP_CSNP_FLAG) - { - /* getting the header info */ - typechar = 'C'; - chdr = - (struct isis_complete_seqnum_hdr *) STREAM_PNT (circuit->rcv_stream); - stream_forward_getp (circuit->rcv_stream, ISIS_CSNP_HDRLEN); - pdu_len = ntohs (chdr->pdu_len); - if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_CSNP_HDRLEN) || - pdu_len > ISO_MTU(circuit) || - pdu_len > stream_get_endp (circuit->rcv_stream)) - { - zlog_warn ("Received a CSNP with bogus length %d", pdu_len); - return ISIS_WARNING; - } - } - else - { - typechar = 'P'; - phdr = - (struct isis_partial_seqnum_hdr *) STREAM_PNT (circuit->rcv_stream); - stream_forward_getp (circuit->rcv_stream, ISIS_PSNP_HDRLEN); - pdu_len = ntohs (phdr->pdu_len); - if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_PSNP_HDRLEN) || - pdu_len > ISO_MTU(circuit) || - pdu_len > stream_get_endp (circuit->rcv_stream)) - { - zlog_warn ("Received a PSNP with bogus length %d", pdu_len); - return ISIS_WARNING; + int retval = ISIS_OK; + int cmp, own_lsp; + char typechar = ' '; + uint16_t pdu_len; + struct isis_adjacency *adj; + struct isis_complete_seqnum_hdr *chdr = NULL; + struct isis_partial_seqnum_hdr *phdr = NULL; + uint32_t found = 0, expected = 0, auth_tlv_offset = 0; + struct isis_lsp *lsp; + struct lsp_entry *entry; + struct listnode *node, *nnode; + struct listnode *node2, *nnode2; + struct tlvs tlvs; + struct list *lsp_list = NULL; + struct isis_passwd *passwd; + + if (snp_type == ISIS_SNP_CSNP_FLAG) { + /* getting the header info */ + typechar = 'C'; + chdr = (struct isis_complete_seqnum_hdr *)STREAM_PNT( + circuit->rcv_stream); + stream_forward_getp(circuit->rcv_stream, ISIS_CSNP_HDRLEN); + pdu_len = ntohs(chdr->pdu_len); + if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_CSNP_HDRLEN) + || pdu_len > ISO_MTU(circuit) + || pdu_len > stream_get_endp(circuit->rcv_stream)) { + zlog_warn("Received a CSNP with bogus length %d", + pdu_len); + return ISIS_WARNING; + } + } else { + typechar = 'P'; + phdr = (struct isis_partial_seqnum_hdr *)STREAM_PNT( + circuit->rcv_stream); + stream_forward_getp(circuit->rcv_stream, ISIS_PSNP_HDRLEN); + pdu_len = ntohs(phdr->pdu_len); + if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_PSNP_HDRLEN) + || pdu_len > ISO_MTU(circuit) + || pdu_len > stream_get_endp(circuit->rcv_stream)) { + zlog_warn("Received a PSNP with bogus length %d", + pdu_len); + return ISIS_WARNING; + } } - } - - /* - * Set the stream endp to PDU length, ignoring additional padding - * introduced by transport chips. - */ - if (pdu_len < stream_get_endp (circuit->rcv_stream)) - stream_set_endp (circuit->rcv_stream, pdu_len); - - /* 7.3.15.2 a) 1 - external domain circuit will discard snp pdu */ - if (circuit->ext_domain) - { - - zlog_debug ("ISIS-Snp (%s): Rcvd L%d %cSNP on %s, " - "skipping: circuit externalDomain = true", - circuit->area->area_tag, - level, typechar, circuit->interface->name); - - return ISIS_OK; - } - /* 7.3.15.2 a) 2,3 - manualL2OnlyMode not implemented */ - if (!accept_level (level, circuit->is_type)) - { - - zlog_debug ("ISIS-Snp (%s): Rcvd L%d %cSNP on %s, " - "skipping: circuit type %s does not match level %d", - circuit->area->area_tag, - level, - typechar, - circuit->interface->name, - circuit_t2string (circuit->is_type), level); + /* + * Set the stream endp to PDU length, ignoring additional padding + * introduced by transport chips. + */ + if (pdu_len < stream_get_endp(circuit->rcv_stream)) + stream_set_endp(circuit->rcv_stream, pdu_len); - return ISIS_OK; - } + /* 7.3.15.2 a) 1 - external domain circuit will discard snp pdu */ + if (circuit->ext_domain) { - /* 7.3.15.2 a) 4 - not applicable for CSNP only PSNPs on broadcast */ - if ((snp_type == ISIS_SNP_PSNP_FLAG) && - (circuit->circ_type == CIRCUIT_T_BROADCAST) && - (!circuit->u.bc.is_dr[level - 1])) - { - zlog_debug ("ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s, " - "skipping: we are not the DIS", - circuit->area->area_tag, - level, - typechar, snpa_print (ssnpa), circuit->interface->name); + zlog_debug( + "ISIS-Snp (%s): Rcvd L%d %cSNP on %s, " + "skipping: circuit externalDomain = true", + circuit->area->area_tag, level, typechar, + circuit->interface->name); - return ISIS_OK; - } + return ISIS_OK; + } - /* 7.3.15.2 a) 5 - need to make sure IDLength matches - already checked */ + /* 7.3.15.2 a) 2,3 - manualL2OnlyMode not implemented */ + if (!accept_level(level, circuit->is_type)) { - /* 7.3.15.2 a) 6 - maximum area match, can be ommited since we only use 3 - * - already checked */ + zlog_debug( + "ISIS-Snp (%s): Rcvd L%d %cSNP on %s, " + "skipping: circuit type %s does not match level %d", + circuit->area->area_tag, level, typechar, + circuit->interface->name, + circuit_t2string(circuit->is_type), level); - /* 7.3.15.2 a) 7 - Must check that we have an adjacency of the same level */ - /* for broadcast circuits, snpa should be compared */ - /* FIXME : Do we need to check SNPA? */ - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - { - if (snp_type == ISIS_SNP_CSNP_FLAG) - { - adj = - isis_adj_lookup (chdr->source_id, circuit->u.bc.adjdb[level - 1]); + return ISIS_OK; } - else - { - /* a psnp on a broadcast, how lovely of Juniper :) */ - adj = - isis_adj_lookup (phdr->source_id, circuit->u.bc.adjdb[level - 1]); - } - if (!adj) - return ISIS_OK; /* Silently discard */ - } - else - { - if (!circuit->u.p2p.neighbor) - { - zlog_warn ("no p2p neighbor on circuit %s", circuit->interface->name); - return ISIS_OK; /* Silently discard */ - } - } - - /* 7.3.15.2 a) 8 - Passwords for level 1 - not implemented */ - /* 7.3.15.2 a) 9 - Passwords for level 2 - not implemented */ + /* 7.3.15.2 a) 4 - not applicable for CSNP only PSNPs on broadcast */ + if ((snp_type == ISIS_SNP_PSNP_FLAG) + && (circuit->circ_type == CIRCUIT_T_BROADCAST) + && (!circuit->u.bc.is_dr[level - 1])) { + zlog_debug( + "ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s, " + "skipping: we are not the DIS", + circuit->area->area_tag, level, typechar, + snpa_print(ssnpa), circuit->interface->name); + + return ISIS_OK; + } - memset (&tlvs, 0, sizeof (struct tlvs)); + /* 7.3.15.2 a) 5 - need to make sure IDLength matches - already checked + */ + + /* 7.3.15.2 a) 6 - maximum area match, can be ommited since we only use + * 3 + * - already checked */ + + /* 7.3.15.2 a) 7 - Must check that we have an adjacency of the same + * level */ + /* for broadcast circuits, snpa should be compared */ + /* FIXME : Do we need to check SNPA? */ + if (circuit->circ_type == CIRCUIT_T_BROADCAST) { + if (snp_type == ISIS_SNP_CSNP_FLAG) { + adj = isis_adj_lookup(chdr->source_id, + circuit->u.bc.adjdb[level - 1]); + } else { + /* a psnp on a broadcast, how lovely of Juniper :) */ + adj = isis_adj_lookup(phdr->source_id, + circuit->u.bc.adjdb[level - 1]); + } + if (!adj) + return ISIS_OK; /* Silently discard */ + } else { + if (!circuit->u.p2p.neighbor) { + zlog_warn("no p2p neighbor on circuit %s", + circuit->interface->name); + return ISIS_OK; /* Silently discard */ + } + } - /* parse the SNP */ - expected |= TLVFLAG_LSP_ENTRIES; - expected |= TLVFLAG_AUTH_INFO; + /* 7.3.15.2 a) 8 - Passwords for level 1 - not implemented */ - auth_tlv_offset = stream_get_getp (circuit->rcv_stream); - retval = parse_tlvs (circuit->area->area_tag, - STREAM_PNT (circuit->rcv_stream), - pdu_len - stream_get_getp (circuit->rcv_stream), - &expected, &found, &tlvs, &auth_tlv_offset); + /* 7.3.15.2 a) 9 - Passwords for level 2 - not implemented */ - if (retval > ISIS_WARNING) - { - zlog_warn ("something went very wrong processing SNP"); - free_tlvs (&tlvs); - return retval; - } + memset(&tlvs, 0, sizeof(struct tlvs)); - if (level == IS_LEVEL_1) - passwd = &circuit->area->area_passwd; - else - passwd = &circuit->area->domain_passwd; + /* parse the SNP */ + expected |= TLVFLAG_LSP_ENTRIES; + expected |= TLVFLAG_AUTH_INFO; - if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_RECV)) - { - if (passwd->type) - { - if (!(found & TLVFLAG_AUTH_INFO) || - authentication_check (&tlvs.auth_info, passwd, - circuit->rcv_stream, auth_tlv_offset)) - { - isis_event_auth_failure (circuit->area->area_tag, - "SNP authentication" " failure", - phdr ? phdr->source_id : - chdr->source_id); - free_tlvs (&tlvs); - return ISIS_OK; - } - } - } + auth_tlv_offset = stream_get_getp(circuit->rcv_stream); + retval = parse_tlvs(circuit->area->area_tag, + STREAM_PNT(circuit->rcv_stream), + pdu_len - stream_get_getp(circuit->rcv_stream), + &expected, &found, &tlvs, &auth_tlv_offset); - /* debug isis snp-packets */ - if (isis->debugs & DEBUG_SNP_PACKETS) - { - zlog_debug ("ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s", - circuit->area->area_tag, - level, - typechar, snpa_print (ssnpa), circuit->interface->name); - if (tlvs.lsp_entries) - { - for (ALL_LIST_ELEMENTS_RO (tlvs.lsp_entries, node, entry)) - { - zlog_debug ("ISIS-Snp (%s): %cSNP entry %s, seq 0x%08x," - " cksum 0x%04x, lifetime %us", - circuit->area->area_tag, - typechar, - rawlspid_print (entry->lsp_id), - ntohl (entry->seq_num), - ntohs (entry->checksum), ntohs (entry->rem_lifetime)); - } + if (retval > ISIS_WARNING) { + zlog_warn("something went very wrong processing SNP"); + free_tlvs(&tlvs); + return retval; } - } - /* 7.3.15.2 b) Actions on LSP_ENTRIES reported */ - if (tlvs.lsp_entries) - { - for (ALL_LIST_ELEMENTS_RO (tlvs.lsp_entries, node, entry)) - { - lsp = lsp_search (entry->lsp_id, circuit->area->lspdb[level - 1]); - own_lsp = !memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN); - if (lsp) - { - /* 7.3.15.2 b) 1) is this LSP newer */ - cmp = lsp_compare (circuit->area->area_tag, lsp, entry->seq_num, - entry->checksum, entry->rem_lifetime); - /* 7.3.15.2 b) 2) if it equals, clear SRM on p2p */ - if (cmp == LSP_EQUAL) - { - /* if (circuit->circ_type != CIRCUIT_T_BROADCAST) */ - ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); - } - /* 7.3.15.2 b) 3) if it is older, clear SSN and set SRM */ - else if (cmp == LSP_OLDER) - { - ISIS_CLEAR_FLAG (lsp->SSNflags, circuit); - ISIS_SET_FLAG (lsp->SRMflags, circuit); - } - /* 7.3.15.2 b) 4) if it is newer, set SSN and clear SRM on p2p */ - else - { - if (own_lsp) - { - lsp_inc_seqnum (lsp, ntohl (entry->seq_num)); - ISIS_SET_FLAG (lsp->SRMflags, circuit); - } - else - { - ISIS_SET_FLAG (lsp->SSNflags, circuit); - /* if (circuit->circ_type != CIRCUIT_T_BROADCAST) */ - ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); - } - } - } + if (level == IS_LEVEL_1) + passwd = &circuit->area->area_passwd; else - { - /* 7.3.15.2 b) 5) if it was not found, and all of those are not 0, - * insert it and set SSN on it */ - if (entry->rem_lifetime && entry->checksum && entry->seq_num && - memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN)) - { - lsp = lsp_new(circuit->area, entry->lsp_id, - ntohs(entry->rem_lifetime), - 0, 0, entry->checksum, level); - lsp_insert (lsp, circuit->area->lspdb[level - 1]); - ISIS_FLAGS_CLEAR_ALL (lsp->SRMflags); - ISIS_SET_FLAG (lsp->SSNflags, circuit); - } - } - } - } + passwd = &circuit->area->domain_passwd; + + if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_RECV)) { + if (passwd->type) { + if (!(found & TLVFLAG_AUTH_INFO) + || authentication_check(&tlvs.auth_info, passwd, + circuit->rcv_stream, + auth_tlv_offset)) { + isis_event_auth_failure(circuit->area->area_tag, + "SNP authentication" + " failure", + phdr ? phdr->source_id + : chdr->source_id); + free_tlvs(&tlvs); + return ISIS_OK; + } + } + } - /* 7.3.15.2 c) on CSNP set SRM for all in range which were not reported */ - if (snp_type == ISIS_SNP_CSNP_FLAG) - { - /* - * Build a list from our own LSP db bounded with - * start_lsp_id and stop_lsp_id - */ - lsp_list = list_new (); - lsp_build_list_nonzero_ht (chdr->start_lsp_id, chdr->stop_lsp_id, - lsp_list, circuit->area->lspdb[level - 1]); - - /* Fixme: Find a better solution */ - if (tlvs.lsp_entries) - { - for (ALL_LIST_ELEMENTS (tlvs.lsp_entries, node, nnode, entry)) - { - for (ALL_LIST_ELEMENTS (lsp_list, node2, nnode2, lsp)) - { - if (lsp_id_cmp (lsp->lsp_header->lsp_id, entry->lsp_id) == 0) - { - list_delete_node (lsp_list, node2); - break; + /* debug isis snp-packets */ + if (isis->debugs & DEBUG_SNP_PACKETS) { + zlog_debug("ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s", + circuit->area->area_tag, level, typechar, + snpa_print(ssnpa), circuit->interface->name); + if (tlvs.lsp_entries) { + for (ALL_LIST_ELEMENTS_RO(tlvs.lsp_entries, node, + entry)) { + zlog_debug( + "ISIS-Snp (%s): %cSNP entry %s, seq 0x%08x," + " cksum 0x%04x, lifetime %us", + circuit->area->area_tag, typechar, + rawlspid_print(entry->lsp_id), + ntohl(entry->seq_num), + ntohs(entry->checksum), + ntohs(entry->rem_lifetime)); + } } - } - } } - /* on remaining LSPs we set SRM (neighbor knew not of) */ - for (ALL_LIST_ELEMENTS_RO (lsp_list, node, lsp)) - ISIS_SET_FLAG (lsp->SRMflags, circuit); - /* lets free it */ - list_delete (lsp_list); - } + /* 7.3.15.2 b) Actions on LSP_ENTRIES reported */ + if (tlvs.lsp_entries) { + for (ALL_LIST_ELEMENTS_RO(tlvs.lsp_entries, node, entry)) { + lsp = lsp_search(entry->lsp_id, + circuit->area->lspdb[level - 1]); + own_lsp = !memcmp(entry->lsp_id, isis->sysid, + ISIS_SYS_ID_LEN); + if (lsp) { + /* 7.3.15.2 b) 1) is this LSP newer */ + cmp = lsp_compare(circuit->area->area_tag, lsp, + entry->seq_num, + entry->checksum, + entry->rem_lifetime); + /* 7.3.15.2 b) 2) if it equals, clear SRM on p2p + */ + if (cmp == LSP_EQUAL) { + /* if (circuit->circ_type != + * CIRCUIT_T_BROADCAST) */ + ISIS_CLEAR_FLAG(lsp->SRMflags, circuit); + } + /* 7.3.15.2 b) 3) if it is older, clear SSN and + set SRM */ + else if (cmp == LSP_OLDER) { + ISIS_CLEAR_FLAG(lsp->SSNflags, circuit); + ISIS_SET_FLAG(lsp->SRMflags, circuit); + } + /* 7.3.15.2 b) 4) if it is newer, set SSN and + clear SRM on p2p */ + else { + if (own_lsp) { + lsp_inc_seqnum( + lsp, + ntohl(entry->seq_num)); + ISIS_SET_FLAG(lsp->SRMflags, + circuit); + } else { + ISIS_SET_FLAG(lsp->SSNflags, + circuit); + /* if (circuit->circ_type != + * CIRCUIT_T_BROADCAST) */ + ISIS_CLEAR_FLAG(lsp->SRMflags, + circuit); + } + } + } else { + /* 7.3.15.2 b) 5) if it was not found, and all + * of those are not 0, + * insert it and set SSN on it */ + if (entry->rem_lifetime && entry->checksum + && entry->seq_num + && memcmp(entry->lsp_id, isis->sysid, + ISIS_SYS_ID_LEN)) { + lsp = lsp_new( + circuit->area, entry->lsp_id, + ntohs(entry->rem_lifetime), 0, + 0, entry->checksum, level); + lsp_insert(lsp, + circuit->area + ->lspdb[level - 1]); + ISIS_FLAGS_CLEAR_ALL(lsp->SRMflags); + ISIS_SET_FLAG(lsp->SSNflags, circuit); + } + } + } + } - free_tlvs (&tlvs); - return retval; + /* 7.3.15.2 c) on CSNP set SRM for all in range which were not reported + */ + if (snp_type == ISIS_SNP_CSNP_FLAG) { + /* + * Build a list from our own LSP db bounded with + * start_lsp_id and stop_lsp_id + */ + lsp_list = list_new(); + lsp_build_list_nonzero_ht(chdr->start_lsp_id, chdr->stop_lsp_id, + lsp_list, + circuit->area->lspdb[level - 1]); + + /* Fixme: Find a better solution */ + if (tlvs.lsp_entries) { + for (ALL_LIST_ELEMENTS(tlvs.lsp_entries, node, nnode, + entry)) { + for (ALL_LIST_ELEMENTS(lsp_list, node2, nnode2, + lsp)) { + if (lsp_id_cmp(lsp->lsp_header->lsp_id, + entry->lsp_id) + == 0) { + list_delete_node(lsp_list, + node2); + break; + } + } + } + } + /* on remaining LSPs we set SRM (neighbor knew not of) */ + for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp)) + ISIS_SET_FLAG(lsp->SRMflags, circuit); + /* lets free it */ + list_delete(lsp_list); + } + + free_tlvs(&tlvs); + return retval; } -static int -process_csnp (int level, struct isis_circuit *circuit, const u_char *ssnpa) +static int process_csnp(int level, struct isis_circuit *circuit, + const u_char *ssnpa) { - if (isis->debugs & DEBUG_SNP_PACKETS) - { - zlog_debug ("ISIS-Snp (%s): Rcvd L%d CSNP on %s, cirType %s, cirID %u", - circuit->area->area_tag, level, circuit->interface->name, - circuit_t2string (circuit->is_type), circuit->circuit_id); - if (isis->debugs & DEBUG_PACKET_DUMP) - zlog_dump_data (STREAM_DATA (circuit->rcv_stream), - stream_get_endp (circuit->rcv_stream)); - } + if (isis->debugs & DEBUG_SNP_PACKETS) { + zlog_debug( + "ISIS-Snp (%s): Rcvd L%d CSNP on %s, cirType %s, cirID %u", + circuit->area->area_tag, level, + circuit->interface->name, + circuit_t2string(circuit->is_type), + circuit->circuit_id); + if (isis->debugs & DEBUG_PACKET_DUMP) + zlog_dump_data(STREAM_DATA(circuit->rcv_stream), + stream_get_endp(circuit->rcv_stream)); + } - /* Sanity check - FIXME: move to correct place */ - if ((stream_get_endp (circuit->rcv_stream) - - stream_get_getp (circuit->rcv_stream)) < ISIS_CSNP_HDRLEN) - { - zlog_warn ("Packet too short ( < %d)", ISIS_CSNP_HDRLEN); - return ISIS_WARNING; - } + /* Sanity check - FIXME: move to correct place */ + if ((stream_get_endp(circuit->rcv_stream) + - stream_get_getp(circuit->rcv_stream)) + < ISIS_CSNP_HDRLEN) { + zlog_warn("Packet too short ( < %d)", ISIS_CSNP_HDRLEN); + return ISIS_WARNING; + } - return process_snp (ISIS_SNP_CSNP_FLAG, level, circuit, ssnpa); + return process_snp(ISIS_SNP_CSNP_FLAG, level, circuit, ssnpa); } -static int -process_psnp (int level, struct isis_circuit *circuit, const u_char *ssnpa) +static int process_psnp(int level, struct isis_circuit *circuit, + const u_char *ssnpa) { - if (isis->debugs & DEBUG_SNP_PACKETS) - { - zlog_debug ("ISIS-Snp (%s): Rcvd L%d PSNP on %s, cirType %s, cirID %u", - circuit->area->area_tag, level, circuit->interface->name, - circuit_t2string (circuit->is_type), circuit->circuit_id); - if (isis->debugs & DEBUG_PACKET_DUMP) - zlog_dump_data (STREAM_DATA (circuit->rcv_stream), - stream_get_endp (circuit->rcv_stream)); - } + if (isis->debugs & DEBUG_SNP_PACKETS) { + zlog_debug( + "ISIS-Snp (%s): Rcvd L%d PSNP on %s, cirType %s, cirID %u", + circuit->area->area_tag, level, + circuit->interface->name, + circuit_t2string(circuit->is_type), + circuit->circuit_id); + if (isis->debugs & DEBUG_PACKET_DUMP) + zlog_dump_data(STREAM_DATA(circuit->rcv_stream), + stream_get_endp(circuit->rcv_stream)); + } - if ((stream_get_endp (circuit->rcv_stream) - - stream_get_getp (circuit->rcv_stream)) < ISIS_PSNP_HDRLEN) - { - zlog_warn ("Packet too short ( < %d)", ISIS_PSNP_HDRLEN); - return ISIS_WARNING; - } + if ((stream_get_endp(circuit->rcv_stream) + - stream_get_getp(circuit->rcv_stream)) + < ISIS_PSNP_HDRLEN) { + zlog_warn("Packet too short ( < %d)", ISIS_PSNP_HDRLEN); + return ISIS_WARNING; + } - return process_snp (ISIS_SNP_PSNP_FLAG, level, circuit, ssnpa); + return process_snp(ISIS_SNP_PSNP_FLAG, level, circuit, ssnpa); } /* * PDU Dispatcher */ -static int -isis_handle_pdu (struct isis_circuit *circuit, u_char * ssnpa) +static int isis_handle_pdu(struct isis_circuit *circuit, u_char *ssnpa) { - struct isis_fixed_hdr *hdr; + struct isis_fixed_hdr *hdr; - int retval = ISIS_OK; + int retval = ISIS_OK; - /* - * Let's first read data from stream to the header - */ - hdr = (struct isis_fixed_hdr *) STREAM_DATA (circuit->rcv_stream); + /* + * Let's first read data from stream to the header + */ + hdr = (struct isis_fixed_hdr *)STREAM_DATA(circuit->rcv_stream); - if ((hdr->idrp != ISO10589_ISIS) && (hdr->idrp != ISO9542_ESIS)) - { - zlog_err ("Not an IS-IS or ES-IS packet IDRP=%02x", hdr->idrp); - return ISIS_ERROR; - } + if ((hdr->idrp != ISO10589_ISIS) && (hdr->idrp != ISO9542_ESIS)) { + zlog_err("Not an IS-IS or ES-IS packet IDRP=%02x", hdr->idrp); + return ISIS_ERROR; + } - /* now we need to know if this is an ISO 9542 packet and - * take real good care of it, waaa! - */ - if (hdr->idrp == ISO9542_ESIS) - { - zlog_err ("No support for ES-IS packet IDRP=%02x", hdr->idrp); - return ISIS_ERROR; - } - stream_set_getp (circuit->rcv_stream, ISIS_FIXED_HDR_LEN); + /* now we need to know if this is an ISO 9542 packet and + * take real good care of it, waaa! + */ + if (hdr->idrp == ISO9542_ESIS) { + zlog_err("No support for ES-IS packet IDRP=%02x", hdr->idrp); + return ISIS_ERROR; + } + stream_set_getp(circuit->rcv_stream, ISIS_FIXED_HDR_LEN); - /* - * and then process it - */ + /* + * and then process it + */ - if (hdr->length < ISIS_MINIMUM_FIXED_HDR_LEN) - { - zlog_err ("Fixed header length = %d", hdr->length); - return ISIS_ERROR; - } + if (hdr->length < ISIS_MINIMUM_FIXED_HDR_LEN) { + zlog_err("Fixed header length = %d", hdr->length); + return ISIS_ERROR; + } - if (hdr->version1 != 1) - { - zlog_warn ("Unsupported ISIS version %u", hdr->version1); - return ISIS_WARNING; - } - /* either 6 or 0 */ - if ((hdr->id_len != 0) && (hdr->id_len != ISIS_SYS_ID_LEN)) - { - zlog_err - ("IDFieldLengthMismatch: ID Length field in a received PDU %u, " - "while the parameter for this IS is %u", hdr->id_len, - ISIS_SYS_ID_LEN); - return ISIS_ERROR; - } + if (hdr->version1 != 1) { + zlog_warn("Unsupported ISIS version %u", hdr->version1); + return ISIS_WARNING; + } + /* either 6 or 0 */ + if ((hdr->id_len != 0) && (hdr->id_len != ISIS_SYS_ID_LEN)) { + zlog_err( + "IDFieldLengthMismatch: ID Length field in a received PDU %u, " + "while the parameter for this IS is %u", + hdr->id_len, ISIS_SYS_ID_LEN); + return ISIS_ERROR; + } - if (hdr->version2 != 1) - { - zlog_warn ("Unsupported ISIS version %u", hdr->version2); - return ISIS_WARNING; - } + if (hdr->version2 != 1) { + zlog_warn("Unsupported ISIS version %u", hdr->version2); + return ISIS_WARNING; + } - if (circuit->is_passive) - { - zlog_warn ("Received ISIS PDU on passive circuit %s", - circuit->interface->name); - return ISIS_WARNING; - } + if (circuit->is_passive) { + zlog_warn("Received ISIS PDU on passive circuit %s", + circuit->interface->name); + return ISIS_WARNING; + } - /* either 3 or 0 */ - if ((hdr->max_area_addrs != 0) - && (hdr->max_area_addrs != isis->max_area_addrs)) - { - zlog_err ("maximumAreaAddressesMismatch: maximumAreaAdresses in a " - "received PDU %u while the parameter for this IS is %u", - hdr->max_area_addrs, isis->max_area_addrs); - return ISIS_ERROR; - } + /* either 3 or 0 */ + if ((hdr->max_area_addrs != 0) + && (hdr->max_area_addrs != isis->max_area_addrs)) { + zlog_err( + "maximumAreaAddressesMismatch: maximumAreaAdresses in a " + "received PDU %u while the parameter for this IS is %u", + hdr->max_area_addrs, isis->max_area_addrs); + return ISIS_ERROR; + } - switch (hdr->pdu_type) - { - case L1_LAN_HELLO: - retval = process_lan_hello (ISIS_LEVEL1, circuit, ssnpa); - break; - case L2_LAN_HELLO: - retval = process_lan_hello (ISIS_LEVEL2, circuit, ssnpa); - break; - case P2P_HELLO: - retval = process_p2p_hello (circuit); - break; - case L1_LINK_STATE: - retval = process_lsp (ISIS_LEVEL1, circuit, ssnpa); - break; - case L2_LINK_STATE: - retval = process_lsp (ISIS_LEVEL2, circuit, ssnpa); - break; - case L1_COMPLETE_SEQ_NUM: - retval = process_csnp (ISIS_LEVEL1, circuit, ssnpa); - break; - case L2_COMPLETE_SEQ_NUM: - retval = process_csnp (ISIS_LEVEL2, circuit, ssnpa); - break; - case L1_PARTIAL_SEQ_NUM: - retval = process_psnp (ISIS_LEVEL1, circuit, ssnpa); - break; - case L2_PARTIAL_SEQ_NUM: - retval = process_psnp (ISIS_LEVEL2, circuit, ssnpa); - break; - default: - return ISIS_ERROR; - } + switch (hdr->pdu_type) { + case L1_LAN_HELLO: + retval = process_lan_hello(ISIS_LEVEL1, circuit, ssnpa); + break; + case L2_LAN_HELLO: + retval = process_lan_hello(ISIS_LEVEL2, circuit, ssnpa); + break; + case P2P_HELLO: + retval = process_p2p_hello(circuit); + break; + case L1_LINK_STATE: + retval = process_lsp(ISIS_LEVEL1, circuit, ssnpa); + break; + case L2_LINK_STATE: + retval = process_lsp(ISIS_LEVEL2, circuit, ssnpa); + break; + case L1_COMPLETE_SEQ_NUM: + retval = process_csnp(ISIS_LEVEL1, circuit, ssnpa); + break; + case L2_COMPLETE_SEQ_NUM: + retval = process_csnp(ISIS_LEVEL2, circuit, ssnpa); + break; + case L1_PARTIAL_SEQ_NUM: + retval = process_psnp(ISIS_LEVEL1, circuit, ssnpa); + break; + case L2_PARTIAL_SEQ_NUM: + retval = process_psnp(ISIS_LEVEL2, circuit, ssnpa); + break; + default: + return ISIS_ERROR; + } - return retval; + return retval; } -int -isis_receive (struct thread *thread) +int isis_receive(struct thread *thread) { - struct isis_circuit *circuit; - u_char ssnpa[ETH_ALEN]; - int retval; + struct isis_circuit *circuit; + u_char ssnpa[ETH_ALEN]; + int retval; - /* - * Get the circuit - */ - circuit = THREAD_ARG (thread); - assert (circuit); + /* + * Get the circuit + */ + circuit = THREAD_ARG(thread); + assert(circuit); - circuit->t_read = NULL; + circuit->t_read = NULL; - isis_circuit_stream(circuit, &circuit->rcv_stream); + isis_circuit_stream(circuit, &circuit->rcv_stream); - retval = circuit->rx (circuit, ssnpa); + retval = circuit->rx(circuit, ssnpa); - if (retval == ISIS_OK) - retval = isis_handle_pdu (circuit, ssnpa); + if (retval == ISIS_OK) + retval = isis_handle_pdu(circuit, ssnpa); - /* - * prepare for next packet. - */ - if (!circuit->is_passive) - isis_circuit_prepare (circuit); + /* + * prepare for next packet. + */ + if (!circuit->is_passive) + isis_circuit_prepare(circuit); - return retval; + return retval; } - /* filling of the fixed isis header */ -void -fill_fixed_hdr (struct isis_fixed_hdr *hdr, u_char pdu_type) +/* filling of the fixed isis header */ +void fill_fixed_hdr(struct isis_fixed_hdr *hdr, u_char pdu_type) { - memset (hdr, 0, sizeof (struct isis_fixed_hdr)); - - hdr->idrp = ISO10589_ISIS; - - switch (pdu_type) - { - case L1_LAN_HELLO: - case L2_LAN_HELLO: - hdr->length = ISIS_LANHELLO_HDRLEN; - break; - case P2P_HELLO: - hdr->length = ISIS_P2PHELLO_HDRLEN; - break; - case L1_LINK_STATE: - case L2_LINK_STATE: - hdr->length = ISIS_LSP_HDR_LEN; - break; - case L1_COMPLETE_SEQ_NUM: - case L2_COMPLETE_SEQ_NUM: - hdr->length = ISIS_CSNP_HDRLEN; - break; - case L1_PARTIAL_SEQ_NUM: - case L2_PARTIAL_SEQ_NUM: - hdr->length = ISIS_PSNP_HDRLEN; - break; - default: - zlog_warn ("fill_fixed_hdr(): unknown pdu type %d", pdu_type); - return; - } - hdr->length += ISIS_FIXED_HDR_LEN; - hdr->pdu_type = pdu_type; - hdr->version1 = 1; - hdr->id_len = 0; /* ISIS_SYS_ID_LEN - 0==6 */ - hdr->version2 = 1; - hdr->max_area_addrs = 0; /* isis->max_area_addrs - 0==3 */ + memset(hdr, 0, sizeof(struct isis_fixed_hdr)); + + hdr->idrp = ISO10589_ISIS; + + switch (pdu_type) { + case L1_LAN_HELLO: + case L2_LAN_HELLO: + hdr->length = ISIS_LANHELLO_HDRLEN; + break; + case P2P_HELLO: + hdr->length = ISIS_P2PHELLO_HDRLEN; + break; + case L1_LINK_STATE: + case L2_LINK_STATE: + hdr->length = ISIS_LSP_HDR_LEN; + break; + case L1_COMPLETE_SEQ_NUM: + case L2_COMPLETE_SEQ_NUM: + hdr->length = ISIS_CSNP_HDRLEN; + break; + case L1_PARTIAL_SEQ_NUM: + case L2_PARTIAL_SEQ_NUM: + hdr->length = ISIS_PSNP_HDRLEN; + break; + default: + zlog_warn("fill_fixed_hdr(): unknown pdu type %d", pdu_type); + return; + } + hdr->length += ISIS_FIXED_HDR_LEN; + hdr->pdu_type = pdu_type; + hdr->version1 = 1; + hdr->id_len = 0; /* ISIS_SYS_ID_LEN - 0==6 */ + hdr->version2 = 1; + hdr->max_area_addrs = 0; /* isis->max_area_addrs - 0==3 */ } /* - * SEND SIDE + * SEND SIDE */ -static void -fill_fixed_hdr_andstream (struct isis_fixed_hdr *hdr, u_char pdu_type, - struct stream *stream) +static void fill_fixed_hdr_andstream(struct isis_fixed_hdr *hdr, + u_char pdu_type, struct stream *stream) { - fill_fixed_hdr (hdr, pdu_type); - - stream_putc (stream, hdr->idrp); - stream_putc (stream, hdr->length); - stream_putc (stream, hdr->version1); - stream_putc (stream, hdr->id_len); - stream_putc (stream, hdr->pdu_type); - stream_putc (stream, hdr->version2); - stream_putc (stream, hdr->reserved); - stream_putc (stream, hdr->max_area_addrs); - - return; + fill_fixed_hdr(hdr, pdu_type); + + stream_putc(stream, hdr->idrp); + stream_putc(stream, hdr->length); + stream_putc(stream, hdr->version1); + stream_putc(stream, hdr->id_len); + stream_putc(stream, hdr->pdu_type); + stream_putc(stream, hdr->version2); + stream_putc(stream, hdr->reserved); + stream_putc(stream, hdr->max_area_addrs); + + return; } -int -send_hello (struct isis_circuit *circuit, int level) +int send_hello(struct isis_circuit *circuit, int level) { - struct isis_fixed_hdr fixed_hdr; - struct isis_lan_hello_hdr hello_hdr; - struct isis_p2p_hello_hdr p2p_hello_hdr; - unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE]; - size_t len_pointer, length, auth_tlv_offset = 0; - u_int32_t interval; - int retval; - - if (circuit->is_passive) - return ISIS_OK; - - if (circuit->interface->mtu == 0) - { - zlog_warn ("circuit has zero MTU"); - return ISIS_WARNING; - } - - isis_circuit_stream(circuit, &circuit->snd_stream); - - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - if (level == IS_LEVEL_1) - fill_fixed_hdr_andstream (&fixed_hdr, L1_LAN_HELLO, - circuit->snd_stream); - else - fill_fixed_hdr_andstream (&fixed_hdr, L2_LAN_HELLO, - circuit->snd_stream); - else - fill_fixed_hdr_andstream (&fixed_hdr, P2P_HELLO, circuit->snd_stream); - - /* - * Fill LAN Level 1 or 2 Hello PDU header - */ - memset (&hello_hdr, 0, sizeof (struct isis_lan_hello_hdr)); - interval = circuit->hello_multiplier[level - 1] * - circuit->hello_interval[level - 1]; - if (interval > USHRT_MAX) - interval = USHRT_MAX; - hello_hdr.circuit_t = circuit->is_type; - memcpy (hello_hdr.source_id, isis->sysid, ISIS_SYS_ID_LEN); - hello_hdr.hold_time = htons ((u_int16_t) interval); - - hello_hdr.pdu_len = 0; /* Update the PDU Length later */ - len_pointer = stream_get_endp (circuit->snd_stream) + 3 + ISIS_SYS_ID_LEN; - - /* copy the shared part of the hello to the p2p hello if needed */ - if (circuit->circ_type == CIRCUIT_T_P2P) - { - memcpy (&p2p_hello_hdr, &hello_hdr, 5 + ISIS_SYS_ID_LEN); - p2p_hello_hdr.local_id = circuit->circuit_id; - /* FIXME: need better understanding */ - stream_put (circuit->snd_stream, &p2p_hello_hdr, ISIS_P2PHELLO_HDRLEN); - } - else - { - hello_hdr.prio = circuit->priority[level - 1]; - if (level == IS_LEVEL_1) - { - memcpy (hello_hdr.lan_id, circuit->u.bc.l1_desig_is, - ISIS_SYS_ID_LEN + 1); + struct isis_fixed_hdr fixed_hdr; + struct isis_lan_hello_hdr hello_hdr; + struct isis_p2p_hello_hdr p2p_hello_hdr; + unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE]; + size_t len_pointer, length, auth_tlv_offset = 0; + u_int32_t interval; + int retval; + + if (circuit->is_passive) + return ISIS_OK; + + if (circuit->interface->mtu == 0) { + zlog_warn("circuit has zero MTU"); + return ISIS_WARNING; } - else if (level == IS_LEVEL_2) - { - memcpy (hello_hdr.lan_id, circuit->u.bc.l2_desig_is, - ISIS_SYS_ID_LEN + 1); - } - stream_put (circuit->snd_stream, &hello_hdr, ISIS_LANHELLO_HDRLEN); - } - - /* - * Then the variable length part. - */ - - /* add circuit password */ - switch (circuit->passwd.type) - { - /* Cleartext */ - case ISIS_PASSWD_TYPE_CLEARTXT: - if (tlv_add_authinfo (circuit->passwd.type, circuit->passwd.len, - circuit->passwd.passwd, circuit->snd_stream)) - return ISIS_WARNING; - break; - - /* HMAC MD5 */ - case ISIS_PASSWD_TYPE_HMAC_MD5: - /* Remember where TLV is written so we can later overwrite the MD5 hash */ - auth_tlv_offset = stream_get_endp (circuit->snd_stream); - memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE); - if (tlv_add_authinfo (circuit->passwd.type, ISIS_AUTH_MD5_SIZE, - hmac_md5_hash, circuit->snd_stream)) - return ISIS_WARNING; - break; - - default: - break; - } - - /* Area Addresses TLV */ - if (listcount (circuit->area->area_addrs) == 0) - return ISIS_WARNING; - if (tlv_add_area_addrs (circuit->area->area_addrs, circuit->snd_stream)) - return ISIS_WARNING; - - /* LAN Neighbors TLV */ - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - { - if (level == IS_LEVEL_1 && circuit->u.bc.lan_neighs[0] && - listcount (circuit->u.bc.lan_neighs[0]) > 0) - if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[0], - circuit->snd_stream)) - return ISIS_WARNING; - if (level == IS_LEVEL_2 && circuit->u.bc.lan_neighs[1] && - listcount (circuit->u.bc.lan_neighs[1]) > 0) - if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[1], - circuit->snd_stream)) - return ISIS_WARNING; - } - - /* Protocols Supported TLV */ - if (circuit->nlpids.count > 0) - if (tlv_add_nlpid (&circuit->nlpids, circuit->snd_stream)) - return ISIS_WARNING; - /* IP interface Address TLV */ - if (circuit->ip_router && circuit->ip_addrs && - listcount (circuit->ip_addrs) > 0) - if (tlv_add_ip_addrs (circuit->ip_addrs, circuit->snd_stream)) - return ISIS_WARNING; - /* - * MT Supported TLV - * - * TLV gets included if no topology is enabled on the interface, - * if one topology other than #0 is enabled, or if multiple topologies - * are enabled. - */ - struct isis_circuit_mt_setting **mt_settings; - unsigned int mt_count; - - mt_settings = circuit_mt_settings(circuit, &mt_count); - if ((mt_count == 0 && area_is_mt(circuit->area)) - || (mt_count == 1 && mt_settings[0]->mtid != ISIS_MT_IPV4_UNICAST) - || (mt_count > 1)) - { - struct list *mt_info = list_new(); - mt_info->del = free_tlv; - - for (unsigned int i = 0; i < mt_count; i++) - { - struct mt_router_info *info; - - info = XCALLOC(MTYPE_ISIS_TLV, sizeof(*info)); - info->mtid = mt_settings[i]->mtid; - /* overload info is not valid in IIH, so it's not included here */ - listnode_add(mt_info, info); - } - tlv_add_mt_router_info (mt_info, circuit->snd_stream); - list_free(mt_info); - } + isis_circuit_stream(circuit, &circuit->snd_stream); - /* IPv6 Interface Address TLV */ - if (circuit->ipv6_router && circuit->ipv6_link && - listcount (circuit->ipv6_link) > 0) - if (tlv_add_ipv6_addrs (circuit->ipv6_link, circuit->snd_stream)) - return ISIS_WARNING; + if (circuit->circ_type == CIRCUIT_T_BROADCAST) + if (level == IS_LEVEL_1) + fill_fixed_hdr_andstream(&fixed_hdr, L1_LAN_HELLO, + circuit->snd_stream); + else + fill_fixed_hdr_andstream(&fixed_hdr, L2_LAN_HELLO, + circuit->snd_stream); + else + fill_fixed_hdr_andstream(&fixed_hdr, P2P_HELLO, + circuit->snd_stream); + + /* + * Fill LAN Level 1 or 2 Hello PDU header + */ + memset(&hello_hdr, 0, sizeof(struct isis_lan_hello_hdr)); + interval = circuit->hello_multiplier[level - 1] + * circuit->hello_interval[level - 1]; + if (interval > USHRT_MAX) + interval = USHRT_MAX; + hello_hdr.circuit_t = circuit->is_type; + memcpy(hello_hdr.source_id, isis->sysid, ISIS_SYS_ID_LEN); + hello_hdr.hold_time = htons((u_int16_t)interval); + + hello_hdr.pdu_len = 0; /* Update the PDU Length later */ + len_pointer = + stream_get_endp(circuit->snd_stream) + 3 + ISIS_SYS_ID_LEN; + + /* copy the shared part of the hello to the p2p hello if needed */ + if (circuit->circ_type == CIRCUIT_T_P2P) { + memcpy(&p2p_hello_hdr, &hello_hdr, 5 + ISIS_SYS_ID_LEN); + p2p_hello_hdr.local_id = circuit->circuit_id; + /* FIXME: need better understanding */ + stream_put(circuit->snd_stream, &p2p_hello_hdr, + ISIS_P2PHELLO_HDRLEN); + } else { + hello_hdr.prio = circuit->priority[level - 1]; + if (level == IS_LEVEL_1) { + memcpy(hello_hdr.lan_id, circuit->u.bc.l1_desig_is, + ISIS_SYS_ID_LEN + 1); + } else if (level == IS_LEVEL_2) { + memcpy(hello_hdr.lan_id, circuit->u.bc.l2_desig_is, + ISIS_SYS_ID_LEN + 1); + } + stream_put(circuit->snd_stream, &hello_hdr, + ISIS_LANHELLO_HDRLEN); + } - if (circuit->pad_hellos) - if (tlv_add_padding (circuit->snd_stream)) - return ISIS_WARNING; + /* + * Then the variable length part. + */ + + /* add circuit password */ + switch (circuit->passwd.type) { + /* Cleartext */ + case ISIS_PASSWD_TYPE_CLEARTXT: + if (tlv_add_authinfo(circuit->passwd.type, circuit->passwd.len, + circuit->passwd.passwd, + circuit->snd_stream)) + return ISIS_WARNING; + break; + + /* HMAC MD5 */ + case ISIS_PASSWD_TYPE_HMAC_MD5: + /* Remember where TLV is written so we can later overwrite the + * MD5 hash */ + auth_tlv_offset = stream_get_endp(circuit->snd_stream); + memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE); + if (tlv_add_authinfo(circuit->passwd.type, ISIS_AUTH_MD5_SIZE, + hmac_md5_hash, circuit->snd_stream)) + return ISIS_WARNING; + break; + + default: + break; + } - length = stream_get_endp (circuit->snd_stream); - /* Update PDU length */ - stream_putw_at (circuit->snd_stream, len_pointer, (u_int16_t) length); + /* Area Addresses TLV */ + if (listcount(circuit->area->area_addrs) == 0) + return ISIS_WARNING; + if (tlv_add_area_addrs(circuit->area->area_addrs, circuit->snd_stream)) + return ISIS_WARNING; + + /* LAN Neighbors TLV */ + if (circuit->circ_type == CIRCUIT_T_BROADCAST) { + if (level == IS_LEVEL_1 && circuit->u.bc.lan_neighs[0] + && listcount(circuit->u.bc.lan_neighs[0]) > 0) + if (tlv_add_lan_neighs(circuit->u.bc.lan_neighs[0], + circuit->snd_stream)) + return ISIS_WARNING; + if (level == IS_LEVEL_2 && circuit->u.bc.lan_neighs[1] + && listcount(circuit->u.bc.lan_neighs[1]) > 0) + if (tlv_add_lan_neighs(circuit->u.bc.lan_neighs[1], + circuit->snd_stream)) + return ISIS_WARNING; + } - /* For HMAC MD5 we need to compute the md5 hash and store it */ - if (circuit->passwd.type == ISIS_PASSWD_TYPE_HMAC_MD5) - { - hmac_md5 (STREAM_DATA (circuit->snd_stream), - stream_get_endp (circuit->snd_stream), - (unsigned char *) &circuit->passwd.passwd, circuit->passwd.len, - (unsigned char *) &hmac_md5_hash); - /* Copy the hash into the stream */ - memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3, - hmac_md5_hash, ISIS_AUTH_MD5_SIZE); - } + /* Protocols Supported TLV */ + if (circuit->nlpids.count > 0) + if (tlv_add_nlpid(&circuit->nlpids, circuit->snd_stream)) + return ISIS_WARNING; + /* IP interface Address TLV */ + if (circuit->ip_router && circuit->ip_addrs + && listcount(circuit->ip_addrs) > 0) + if (tlv_add_ip_addrs(circuit->ip_addrs, circuit->snd_stream)) + return ISIS_WARNING; + + /* + * MT Supported TLV + * + * TLV gets included if no topology is enabled on the interface, + * if one topology other than #0 is enabled, or if multiple topologies + * are enabled. + */ + struct isis_circuit_mt_setting **mt_settings; + unsigned int mt_count; + + mt_settings = circuit_mt_settings(circuit, &mt_count); + if ((mt_count == 0 && area_is_mt(circuit->area)) + || (mt_count == 1 && mt_settings[0]->mtid != ISIS_MT_IPV4_UNICAST) + || (mt_count > 1)) { + struct list *mt_info = list_new(); + mt_info->del = free_tlv; + + for (unsigned int i = 0; i < mt_count; i++) { + struct mt_router_info *info; + + info = XCALLOC(MTYPE_ISIS_TLV, sizeof(*info)); + info->mtid = mt_settings[i]->mtid; + /* overload info is not valid in IIH, so it's not + * included here */ + listnode_add(mt_info, info); + } + tlv_add_mt_router_info(mt_info, circuit->snd_stream); + list_free(mt_info); + } - if (isis->debugs & DEBUG_ADJ_PACKETS) - { - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - { - zlog_debug ("ISIS-Adj (%s): Sending L%d LAN IIH on %s, length %zd", - circuit->area->area_tag, level, circuit->interface->name, - length); + /* IPv6 Interface Address TLV */ + if (circuit->ipv6_router && circuit->ipv6_link + && listcount(circuit->ipv6_link) > 0) + if (tlv_add_ipv6_addrs(circuit->ipv6_link, circuit->snd_stream)) + return ISIS_WARNING; + + if (circuit->pad_hellos) + if (tlv_add_padding(circuit->snd_stream)) + return ISIS_WARNING; + + length = stream_get_endp(circuit->snd_stream); + /* Update PDU length */ + stream_putw_at(circuit->snd_stream, len_pointer, (u_int16_t)length); + + /* For HMAC MD5 we need to compute the md5 hash and store it */ + if (circuit->passwd.type == ISIS_PASSWD_TYPE_HMAC_MD5) { + hmac_md5(STREAM_DATA(circuit->snd_stream), + stream_get_endp(circuit->snd_stream), + (unsigned char *)&circuit->passwd.passwd, + circuit->passwd.len, (unsigned char *)&hmac_md5_hash); + /* Copy the hash into the stream */ + memcpy(STREAM_DATA(circuit->snd_stream) + auth_tlv_offset + 3, + hmac_md5_hash, ISIS_AUTH_MD5_SIZE); } - else - { - zlog_debug ("ISIS-Adj (%s): Sending P2P IIH on %s, length %zd", - circuit->area->area_tag, circuit->interface->name, - length); + + if (isis->debugs & DEBUG_ADJ_PACKETS) { + if (circuit->circ_type == CIRCUIT_T_BROADCAST) { + zlog_debug( + "ISIS-Adj (%s): Sending L%d LAN IIH on %s, length %zd", + circuit->area->area_tag, level, + circuit->interface->name, length); + } else { + zlog_debug( + "ISIS-Adj (%s): Sending P2P IIH on %s, length %zd", + circuit->area->area_tag, + circuit->interface->name, length); + } + if (isis->debugs & DEBUG_PACKET_DUMP) + zlog_dump_data(STREAM_DATA(circuit->snd_stream), + stream_get_endp(circuit->snd_stream)); } - if (isis->debugs & DEBUG_PACKET_DUMP) - zlog_dump_data (STREAM_DATA (circuit->snd_stream), - stream_get_endp (circuit->snd_stream)); - } - retval = circuit->tx (circuit, level); - if (retval != ISIS_OK) - zlog_err ("ISIS-Adj (%s): Send L%d IIH on %s failed", - circuit->area->area_tag, level, circuit->interface->name); + retval = circuit->tx(circuit, level); + if (retval != ISIS_OK) + zlog_err("ISIS-Adj (%s): Send L%d IIH on %s failed", + circuit->area->area_tag, level, + circuit->interface->name); - return retval; + return retval; } -int -send_lan_l1_hello (struct thread *thread) +int send_lan_l1_hello(struct thread *thread) { - struct isis_circuit *circuit; - int retval; - - circuit = THREAD_ARG (thread); - assert (circuit); - circuit->u.bc.t_send_lan_hello[0] = NULL; - - if (!(circuit->area->is_type & IS_LEVEL_1)) - { - zlog_warn ("ISIS-Hello (%s): Trying to send L1 IIH in L2-only area", - circuit->area->area_tag); - return 1; - } + struct isis_circuit *circuit; + int retval; + + circuit = THREAD_ARG(thread); + assert(circuit); + circuit->u.bc.t_send_lan_hello[0] = NULL; + + if (!(circuit->area->is_type & IS_LEVEL_1)) { + zlog_warn( + "ISIS-Hello (%s): Trying to send L1 IIH in L2-only area", + circuit->area->area_tag); + return 1; + } - if (circuit->u.bc.run_dr_elect[0]) - isis_dr_elect (circuit, 1); + if (circuit->u.bc.run_dr_elect[0]) + isis_dr_elect(circuit, 1); - retval = send_hello (circuit, 1); + retval = send_hello(circuit, 1); - /* set next timer thread */ - thread_add_timer(master, send_lan_l1_hello, circuit, - isis_jitter(circuit->hello_interval[0], IIH_JITTER), - &circuit->u.bc.t_send_lan_hello[0]); + /* set next timer thread */ + thread_add_timer(master, send_lan_l1_hello, circuit, + isis_jitter(circuit->hello_interval[0], IIH_JITTER), + &circuit->u.bc.t_send_lan_hello[0]); - return retval; + return retval; } -int -send_lan_l2_hello (struct thread *thread) +int send_lan_l2_hello(struct thread *thread) { - struct isis_circuit *circuit; - int retval; + struct isis_circuit *circuit; + int retval; - circuit = THREAD_ARG (thread); - assert (circuit); - circuit->u.bc.t_send_lan_hello[1] = NULL; + circuit = THREAD_ARG(thread); + assert(circuit); + circuit->u.bc.t_send_lan_hello[1] = NULL; - if (!(circuit->area->is_type & IS_LEVEL_2)) - { - zlog_warn ("ISIS-Hello (%s): Trying to send L2 IIH in L1 area", - circuit->area->area_tag); - return 1; - } + if (!(circuit->area->is_type & IS_LEVEL_2)) { + zlog_warn("ISIS-Hello (%s): Trying to send L2 IIH in L1 area", + circuit->area->area_tag); + return 1; + } - if (circuit->u.bc.run_dr_elect[1]) - isis_dr_elect (circuit, 2); + if (circuit->u.bc.run_dr_elect[1]) + isis_dr_elect(circuit, 2); - retval = send_hello (circuit, 2); + retval = send_hello(circuit, 2); - /* set next timer thread */ - thread_add_timer(master, send_lan_l2_hello, circuit, - isis_jitter(circuit->hello_interval[1], IIH_JITTER), - &circuit->u.bc.t_send_lan_hello[1]); + /* set next timer thread */ + thread_add_timer(master, send_lan_l2_hello, circuit, + isis_jitter(circuit->hello_interval[1], IIH_JITTER), + &circuit->u.bc.t_send_lan_hello[1]); - return retval; + return retval; } -int -send_p2p_hello (struct thread *thread) +int send_p2p_hello(struct thread *thread) { - struct isis_circuit *circuit; + struct isis_circuit *circuit; - circuit = THREAD_ARG (thread); - assert (circuit); - circuit->u.p2p.t_send_p2p_hello = NULL; + circuit = THREAD_ARG(thread); + assert(circuit); + circuit->u.p2p.t_send_p2p_hello = NULL; - send_hello (circuit, 1); + send_hello(circuit, 1); - /* set next timer thread */ - thread_add_timer(master, send_p2p_hello, circuit, - isis_jitter(circuit->hello_interval[1], IIH_JITTER), - &circuit->u.p2p.t_send_p2p_hello); + /* set next timer thread */ + thread_add_timer(master, send_p2p_hello, circuit, + isis_jitter(circuit->hello_interval[1], IIH_JITTER), + &circuit->u.p2p.t_send_p2p_hello); - return ISIS_OK; + return ISIS_OK; } -static int -build_csnp (int level, u_char * start, u_char * stop, struct list *lsps, - struct isis_circuit *circuit) +static int build_csnp(int level, u_char *start, u_char *stop, struct list *lsps, + struct isis_circuit *circuit) { - struct isis_fixed_hdr fixed_hdr; - struct isis_passwd *passwd; - unsigned long lenp; - u_int16_t length; - unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE]; - unsigned long auth_tlv_offset = 0; - int retval = ISIS_OK; - - isis_circuit_stream(circuit, &circuit->snd_stream); - - if (level == IS_LEVEL_1) - fill_fixed_hdr_andstream (&fixed_hdr, L1_COMPLETE_SEQ_NUM, - circuit->snd_stream); - else - fill_fixed_hdr_andstream (&fixed_hdr, L2_COMPLETE_SEQ_NUM, - circuit->snd_stream); - - /* - * Fill Level 1 or 2 Complete Sequence Numbers header - */ - - lenp = stream_get_endp (circuit->snd_stream); - stream_putw (circuit->snd_stream, 0); /* PDU length - when we know it */ - /* no need to send the source here, it is always us if we csnp */ - stream_put (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN); - /* with zero circuit id - ref 9.10, 9.11 */ - stream_putc (circuit->snd_stream, 0x00); - - stream_put (circuit->snd_stream, start, ISIS_SYS_ID_LEN + 2); - stream_put (circuit->snd_stream, stop, ISIS_SYS_ID_LEN + 2); - - /* - * And TLVs - */ - if (level == IS_LEVEL_1) - passwd = &circuit->area->area_passwd; - else - passwd = &circuit->area->domain_passwd; - - if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND)) - { - switch (passwd->type) - { - /* Cleartext */ - case ISIS_PASSWD_TYPE_CLEARTXT: - if (tlv_add_authinfo (ISIS_PASSWD_TYPE_CLEARTXT, passwd->len, - passwd->passwd, circuit->snd_stream)) - return ISIS_WARNING; - break; - - /* HMAC MD5 */ - case ISIS_PASSWD_TYPE_HMAC_MD5: - /* Remember where TLV is written so we can later overwrite the MD5 hash */ - auth_tlv_offset = stream_get_endp (circuit->snd_stream); - memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE); - if (tlv_add_authinfo (ISIS_PASSWD_TYPE_HMAC_MD5, ISIS_AUTH_MD5_SIZE, - hmac_md5_hash, circuit->snd_stream)) - return ISIS_WARNING; - break; - - default: - break; - } - } - - retval = tlv_add_lsp_entries (lsps, circuit->snd_stream); - if (retval != ISIS_OK) - return retval; - - length = (u_int16_t) stream_get_endp (circuit->snd_stream); - /* Update PU length */ - stream_putw_at (circuit->snd_stream, lenp, length); + struct isis_fixed_hdr fixed_hdr; + struct isis_passwd *passwd; + unsigned long lenp; + u_int16_t length; + unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE]; + unsigned long auth_tlv_offset = 0; + int retval = ISIS_OK; + + isis_circuit_stream(circuit, &circuit->snd_stream); + + if (level == IS_LEVEL_1) + fill_fixed_hdr_andstream(&fixed_hdr, L1_COMPLETE_SEQ_NUM, + circuit->snd_stream); + else + fill_fixed_hdr_andstream(&fixed_hdr, L2_COMPLETE_SEQ_NUM, + circuit->snd_stream); + + /* + * Fill Level 1 or 2 Complete Sequence Numbers header + */ + + lenp = stream_get_endp(circuit->snd_stream); + stream_putw(circuit->snd_stream, 0); /* PDU length - when we know it */ + /* no need to send the source here, it is always us if we csnp */ + stream_put(circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN); + /* with zero circuit id - ref 9.10, 9.11 */ + stream_putc(circuit->snd_stream, 0x00); + + stream_put(circuit->snd_stream, start, ISIS_SYS_ID_LEN + 2); + stream_put(circuit->snd_stream, stop, ISIS_SYS_ID_LEN + 2); + + /* + * And TLVs + */ + if (level == IS_LEVEL_1) + passwd = &circuit->area->area_passwd; + else + passwd = &circuit->area->domain_passwd; + + if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND)) { + switch (passwd->type) { + /* Cleartext */ + case ISIS_PASSWD_TYPE_CLEARTXT: + if (tlv_add_authinfo(ISIS_PASSWD_TYPE_CLEARTXT, + passwd->len, passwd->passwd, + circuit->snd_stream)) + return ISIS_WARNING; + break; + + /* HMAC MD5 */ + case ISIS_PASSWD_TYPE_HMAC_MD5: + /* Remember where TLV is written so we can later + * overwrite the MD5 hash */ + auth_tlv_offset = stream_get_endp(circuit->snd_stream); + memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE); + if (tlv_add_authinfo(ISIS_PASSWD_TYPE_HMAC_MD5, + ISIS_AUTH_MD5_SIZE, hmac_md5_hash, + circuit->snd_stream)) + return ISIS_WARNING; + break; + + default: + break; + } + } - /* For HMAC MD5 we need to compute the md5 hash and store it */ - if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND) && - passwd->type == ISIS_PASSWD_TYPE_HMAC_MD5) - { - hmac_md5 (STREAM_DATA (circuit->snd_stream), - stream_get_endp(circuit->snd_stream), - (unsigned char *) &passwd->passwd, passwd->len, - (unsigned char *) &hmac_md5_hash); - /* Copy the hash into the stream */ - memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3, - hmac_md5_hash, ISIS_AUTH_MD5_SIZE); - } + retval = tlv_add_lsp_entries(lsps, circuit->snd_stream); + if (retval != ISIS_OK) + return retval; + + length = (u_int16_t)stream_get_endp(circuit->snd_stream); + /* Update PU length */ + stream_putw_at(circuit->snd_stream, lenp, length); + + /* For HMAC MD5 we need to compute the md5 hash and store it */ + if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND) + && passwd->type == ISIS_PASSWD_TYPE_HMAC_MD5) { + hmac_md5(STREAM_DATA(circuit->snd_stream), + stream_get_endp(circuit->snd_stream), + (unsigned char *)&passwd->passwd, passwd->len, + (unsigned char *)&hmac_md5_hash); + /* Copy the hash into the stream */ + memcpy(STREAM_DATA(circuit->snd_stream) + auth_tlv_offset + 3, + hmac_md5_hash, ISIS_AUTH_MD5_SIZE); + } - return retval; + return retval; } /* * Count the maximum number of lsps that can be accomodated by a given size. */ -static uint16_t -get_max_lsp_count (uint16_t size) +static uint16_t get_max_lsp_count(uint16_t size) { - uint16_t tlv_count; - uint16_t lsp_count; - uint16_t remaining_size; + uint16_t tlv_count; + uint16_t lsp_count; + uint16_t remaining_size; - /* First count the full size TLVs */ - tlv_count = size / MAX_LSP_ENTRIES_TLV_SIZE; - lsp_count = tlv_count * (MAX_LSP_ENTRIES_TLV_SIZE / LSP_ENTRIES_LEN); + /* First count the full size TLVs */ + tlv_count = size / MAX_LSP_ENTRIES_TLV_SIZE; + lsp_count = tlv_count * (MAX_LSP_ENTRIES_TLV_SIZE / LSP_ENTRIES_LEN); - /* The last TLV, if any */ - remaining_size = size % MAX_LSP_ENTRIES_TLV_SIZE; - if (remaining_size - 2 >= LSP_ENTRIES_LEN) - lsp_count += (remaining_size - 2) / LSP_ENTRIES_LEN; + /* The last TLV, if any */ + remaining_size = size % MAX_LSP_ENTRIES_TLV_SIZE; + if (remaining_size - 2 >= LSP_ENTRIES_LEN) + lsp_count += (remaining_size - 2) / LSP_ENTRIES_LEN; - return lsp_count; + return lsp_count; } /* * Calculate the length of Authentication Info. TLV. */ -static uint16_t -auth_tlv_length (int level, struct isis_circuit *circuit) +static uint16_t auth_tlv_length(int level, struct isis_circuit *circuit) { - struct isis_passwd *passwd; - uint16_t length; - - if (level == IS_LEVEL_1) - passwd = &circuit->area->area_passwd; - else - passwd = &circuit->area->domain_passwd; - - /* Also include the length of TLV header */ - length = AUTH_INFO_HDRLEN; - if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND)) - { - switch (passwd->type) - { - /* Cleartext */ - case ISIS_PASSWD_TYPE_CLEARTXT: - length += passwd->len; - break; - - /* HMAC MD5 */ - case ISIS_PASSWD_TYPE_HMAC_MD5: - length += ISIS_AUTH_MD5_SIZE; - break; - - default: - break; - } - } + struct isis_passwd *passwd; + uint16_t length; + + if (level == IS_LEVEL_1) + passwd = &circuit->area->area_passwd; + else + passwd = &circuit->area->domain_passwd; + + /* Also include the length of TLV header */ + length = AUTH_INFO_HDRLEN; + if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND)) { + switch (passwd->type) { + /* Cleartext */ + case ISIS_PASSWD_TYPE_CLEARTXT: + length += passwd->len; + break; + + /* HMAC MD5 */ + case ISIS_PASSWD_TYPE_HMAC_MD5: + length += ISIS_AUTH_MD5_SIZE; + break; + + default: + break; + } + } - return length; + return length; } /* * Calculate the maximum number of lsps that can be accomodated in a CSNP/PSNP. */ -static uint16_t -max_lsps_per_snp (int snp_type, int level, struct isis_circuit *circuit) +static uint16_t max_lsps_per_snp(int snp_type, int level, + struct isis_circuit *circuit) { - int snp_hdr_len; - int auth_tlv_len; - uint16_t lsp_count; - - snp_hdr_len = ISIS_FIXED_HDR_LEN; - if (snp_type == ISIS_SNP_CSNP_FLAG) - snp_hdr_len += ISIS_CSNP_HDRLEN; - else - snp_hdr_len += ISIS_PSNP_HDRLEN; - - auth_tlv_len = auth_tlv_length (level, circuit); - lsp_count = get_max_lsp_count ( - stream_get_size (circuit->snd_stream) - snp_hdr_len - auth_tlv_len); - return lsp_count; + int snp_hdr_len; + int auth_tlv_len; + uint16_t lsp_count; + + snp_hdr_len = ISIS_FIXED_HDR_LEN; + if (snp_type == ISIS_SNP_CSNP_FLAG) + snp_hdr_len += ISIS_CSNP_HDRLEN; + else + snp_hdr_len += ISIS_PSNP_HDRLEN; + + auth_tlv_len = auth_tlv_length(level, circuit); + lsp_count = get_max_lsp_count(stream_get_size(circuit->snd_stream) + - snp_hdr_len - auth_tlv_len); + return lsp_count; } /* * FIXME: support multiple CSNPs */ -int -send_csnp (struct isis_circuit *circuit, int level) +int send_csnp(struct isis_circuit *circuit, int level) { - u_char start[ISIS_SYS_ID_LEN + 2]; - u_char stop[ISIS_SYS_ID_LEN + 2]; - struct list *list = NULL; - struct listnode *node; - struct isis_lsp *lsp; - u_char num_lsps, loop = 1; - int i, retval = ISIS_OK; + u_char start[ISIS_SYS_ID_LEN + 2]; + u_char stop[ISIS_SYS_ID_LEN + 2]; + struct list *list = NULL; + struct listnode *node; + struct isis_lsp *lsp; + u_char num_lsps, loop = 1; + int i, retval = ISIS_OK; + + if (circuit->area->lspdb[level - 1] == NULL + || dict_count(circuit->area->lspdb[level - 1]) == 0) + return retval; + + memset(start, 0x00, ISIS_SYS_ID_LEN + 2); + memset(stop, 0xff, ISIS_SYS_ID_LEN + 2); + + num_lsps = max_lsps_per_snp(ISIS_SNP_CSNP_FLAG, level, circuit); + + while (loop) { + list = list_new(); + lsp_build_list(start, stop, num_lsps, list, + circuit->area->lspdb[level - 1]); + /* + * Update the stop lsp_id before encoding this CSNP. + */ + if (listcount(list) < num_lsps) { + memset(stop, 0xff, ISIS_SYS_ID_LEN + 2); + } else { + node = listtail(list); + lsp = listgetdata(node); + memcpy(stop, lsp->lsp_header->lsp_id, + ISIS_SYS_ID_LEN + 2); + } - if (circuit->area->lspdb[level - 1] == NULL || - dict_count (circuit->area->lspdb[level - 1]) == 0) - return retval; + retval = build_csnp(level, start, stop, list, circuit); + if (retval != ISIS_OK) { + zlog_err("ISIS-Snp (%s): Build L%d CSNP on %s failed", + circuit->area->area_tag, level, + circuit->interface->name); + list_delete(list); + return retval; + } - memset (start, 0x00, ISIS_SYS_ID_LEN + 2); - memset (stop, 0xff, ISIS_SYS_ID_LEN + 2); + if (isis->debugs & DEBUG_SNP_PACKETS) { + zlog_debug( + "ISIS-Snp (%s): Sending L%d CSNP on %s, length %zd", + circuit->area->area_tag, level, + circuit->interface->name, + stream_get_endp(circuit->snd_stream)); + for (ALL_LIST_ELEMENTS_RO(list, node, lsp)) { + zlog_debug( + "ISIS-Snp (%s): CSNP entry %s, seq 0x%08x," + " cksum 0x%04x, lifetime %us", + circuit->area->area_tag, + rawlspid_print(lsp->lsp_header->lsp_id), + ntohl(lsp->lsp_header->seq_num), + ntohs(lsp->lsp_header->checksum), + ntohs(lsp->lsp_header->rem_lifetime)); + } + if (isis->debugs & DEBUG_PACKET_DUMP) + zlog_dump_data( + STREAM_DATA(circuit->snd_stream), + stream_get_endp(circuit->snd_stream)); + } - num_lsps = max_lsps_per_snp (ISIS_SNP_CSNP_FLAG, level, circuit); + retval = circuit->tx(circuit, level); + if (retval != ISIS_OK) { + zlog_err("ISIS-Snp (%s): Send L%d CSNP on %s failed", + circuit->area->area_tag, level, + circuit->interface->name); + list_delete(list); + return retval; + } - while (loop) - { - list = list_new (); - lsp_build_list (start, stop, num_lsps, list, - circuit->area->lspdb[level - 1]); - /* - * Update the stop lsp_id before encoding this CSNP. - */ - if (listcount (list) < num_lsps) - { - memset (stop, 0xff, ISIS_SYS_ID_LEN + 2); - } - else - { - node = listtail (list); - lsp = listgetdata (node); - memcpy (stop, lsp->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 2); - } - - retval = build_csnp (level, start, stop, list, circuit); - if (retval != ISIS_OK) - { - zlog_err ("ISIS-Snp (%s): Build L%d CSNP on %s failed", - circuit->area->area_tag, level, circuit->interface->name); - list_delete (list); - return retval; - } - - if (isis->debugs & DEBUG_SNP_PACKETS) - { - zlog_debug ("ISIS-Snp (%s): Sending L%d CSNP on %s, length %zd", - circuit->area->area_tag, level, circuit->interface->name, - stream_get_endp (circuit->snd_stream)); - for (ALL_LIST_ELEMENTS_RO (list, node, lsp)) - { - zlog_debug ("ISIS-Snp (%s): CSNP entry %s, seq 0x%08x," - " cksum 0x%04x, lifetime %us", - circuit->area->area_tag, - rawlspid_print (lsp->lsp_header->lsp_id), - ntohl (lsp->lsp_header->seq_num), - ntohs (lsp->lsp_header->checksum), - ntohs (lsp->lsp_header->rem_lifetime)); - } - if (isis->debugs & DEBUG_PACKET_DUMP) - zlog_dump_data (STREAM_DATA (circuit->snd_stream), - stream_get_endp (circuit->snd_stream)); - } - - retval = circuit->tx (circuit, level); - if (retval != ISIS_OK) - { - zlog_err ("ISIS-Snp (%s): Send L%d CSNP on %s failed", - circuit->area->area_tag, level, - circuit->interface->name); - list_delete (list); - return retval; - } - - /* - * Start lsp_id of the next CSNP should be one plus the - * stop lsp_id in this current CSNP. - */ - memcpy (start, stop, ISIS_SYS_ID_LEN + 2); - loop = 0; - for (i = ISIS_SYS_ID_LEN + 1; i >= 0; --i) - { - if (start[i] < (u_char)0xff) - { - start[i] += 1; - loop = 1; - break; - } - } - memset (stop, 0xff, ISIS_SYS_ID_LEN + 2); - list_delete (list); - } + /* + * Start lsp_id of the next CSNP should be one plus the + * stop lsp_id in this current CSNP. + */ + memcpy(start, stop, ISIS_SYS_ID_LEN + 2); + loop = 0; + for (i = ISIS_SYS_ID_LEN + 1; i >= 0; --i) { + if (start[i] < (u_char)0xff) { + start[i] += 1; + loop = 1; + break; + } + } + memset(stop, 0xff, ISIS_SYS_ID_LEN + 2); + list_delete(list); + } - return retval; + return retval; } -int -send_l1_csnp (struct thread *thread) +int send_l1_csnp(struct thread *thread) { - struct isis_circuit *circuit; - int retval = ISIS_OK; + struct isis_circuit *circuit; + int retval = ISIS_OK; - circuit = THREAD_ARG (thread); - assert (circuit); + circuit = THREAD_ARG(thread); + assert(circuit); - circuit->t_send_csnp[0] = NULL; + circuit->t_send_csnp[0] = NULL; - if (circuit->circ_type == CIRCUIT_T_BROADCAST && circuit->u.bc.is_dr[0]) - { - send_csnp (circuit, 1); - } - /* set next timer thread */ - thread_add_timer(master, send_l1_csnp, circuit, - isis_jitter(circuit->csnp_interval[0], CSNP_JITTER), - &circuit->t_send_csnp[0]); + if (circuit->circ_type == CIRCUIT_T_BROADCAST + && circuit->u.bc.is_dr[0]) { + send_csnp(circuit, 1); + } + /* set next timer thread */ + thread_add_timer(master, send_l1_csnp, circuit, + isis_jitter(circuit->csnp_interval[0], CSNP_JITTER), + &circuit->t_send_csnp[0]); - return retval; + return retval; } -int -send_l2_csnp (struct thread *thread) +int send_l2_csnp(struct thread *thread) { - struct isis_circuit *circuit; - int retval = ISIS_OK; + struct isis_circuit *circuit; + int retval = ISIS_OK; - circuit = THREAD_ARG (thread); - assert (circuit); + circuit = THREAD_ARG(thread); + assert(circuit); - circuit->t_send_csnp[1] = NULL; + circuit->t_send_csnp[1] = NULL; - if (circuit->circ_type == CIRCUIT_T_BROADCAST && circuit->u.bc.is_dr[1]) - { - send_csnp (circuit, 2); - } - /* set next timer thread */ - thread_add_timer(master, send_l2_csnp, circuit, - isis_jitter(circuit->csnp_interval[1], CSNP_JITTER), - &circuit->t_send_csnp[1]); + if (circuit->circ_type == CIRCUIT_T_BROADCAST + && circuit->u.bc.is_dr[1]) { + send_csnp(circuit, 2); + } + /* set next timer thread */ + thread_add_timer(master, send_l2_csnp, circuit, + isis_jitter(circuit->csnp_interval[1], CSNP_JITTER), + &circuit->t_send_csnp[1]); - return retval; + return retval; } -static int -build_psnp (int level, struct isis_circuit *circuit, struct list *lsps) +static int build_psnp(int level, struct isis_circuit *circuit, + struct list *lsps) { - struct isis_fixed_hdr fixed_hdr; - unsigned long lenp; - u_int16_t length; - struct isis_lsp *lsp; - struct isis_passwd *passwd; - struct listnode *node; - unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE]; - unsigned long auth_tlv_offset = 0; - int retval = ISIS_OK; - - isis_circuit_stream(circuit, &circuit->snd_stream); - - if (level == IS_LEVEL_1) - fill_fixed_hdr_andstream (&fixed_hdr, L1_PARTIAL_SEQ_NUM, - circuit->snd_stream); - else - fill_fixed_hdr_andstream (&fixed_hdr, L2_PARTIAL_SEQ_NUM, - circuit->snd_stream); - - /* - * Fill Level 1 or 2 Partial Sequence Numbers header - */ - lenp = stream_get_endp (circuit->snd_stream); - stream_putw (circuit->snd_stream, 0); /* PDU length - when we know it */ - stream_put (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN); - stream_putc (circuit->snd_stream, circuit->idx); - - /* - * And TLVs - */ - - if (level == IS_LEVEL_1) - passwd = &circuit->area->area_passwd; - else - passwd = &circuit->area->domain_passwd; - - if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND)) - { - switch (passwd->type) - { - /* Cleartext */ - case ISIS_PASSWD_TYPE_CLEARTXT: - if (tlv_add_authinfo (ISIS_PASSWD_TYPE_CLEARTXT, passwd->len, - passwd->passwd, circuit->snd_stream)) - return ISIS_WARNING; - break; - - /* HMAC MD5 */ - case ISIS_PASSWD_TYPE_HMAC_MD5: - /* Remember where TLV is written so we can later overwrite the MD5 hash */ - auth_tlv_offset = stream_get_endp (circuit->snd_stream); - memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE); - if (tlv_add_authinfo (ISIS_PASSWD_TYPE_HMAC_MD5, ISIS_AUTH_MD5_SIZE, - hmac_md5_hash, circuit->snd_stream)) - return ISIS_WARNING; - break; - - default: - break; - } - } - - retval = tlv_add_lsp_entries (lsps, circuit->snd_stream); - if (retval != ISIS_OK) - return retval; - - if (isis->debugs & DEBUG_SNP_PACKETS) - { - for (ALL_LIST_ELEMENTS_RO (lsps, node, lsp)) - { - zlog_debug ("ISIS-Snp (%s): PSNP entry %s, seq 0x%08x," - " cksum 0x%04x, lifetime %us", - circuit->area->area_tag, - rawlspid_print (lsp->lsp_header->lsp_id), - ntohl (lsp->lsp_header->seq_num), - ntohs (lsp->lsp_header->checksum), - ntohs (lsp->lsp_header->rem_lifetime)); - } - } + struct isis_fixed_hdr fixed_hdr; + unsigned long lenp; + u_int16_t length; + struct isis_lsp *lsp; + struct isis_passwd *passwd; + struct listnode *node; + unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE]; + unsigned long auth_tlv_offset = 0; + int retval = ISIS_OK; + + isis_circuit_stream(circuit, &circuit->snd_stream); + + if (level == IS_LEVEL_1) + fill_fixed_hdr_andstream(&fixed_hdr, L1_PARTIAL_SEQ_NUM, + circuit->snd_stream); + else + fill_fixed_hdr_andstream(&fixed_hdr, L2_PARTIAL_SEQ_NUM, + circuit->snd_stream); + + /* + * Fill Level 1 or 2 Partial Sequence Numbers header + */ + lenp = stream_get_endp(circuit->snd_stream); + stream_putw(circuit->snd_stream, 0); /* PDU length - when we know it */ + stream_put(circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN); + stream_putc(circuit->snd_stream, circuit->idx); + + /* + * And TLVs + */ + + if (level == IS_LEVEL_1) + passwd = &circuit->area->area_passwd; + else + passwd = &circuit->area->domain_passwd; + + if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND)) { + switch (passwd->type) { + /* Cleartext */ + case ISIS_PASSWD_TYPE_CLEARTXT: + if (tlv_add_authinfo(ISIS_PASSWD_TYPE_CLEARTXT, + passwd->len, passwd->passwd, + circuit->snd_stream)) + return ISIS_WARNING; + break; + + /* HMAC MD5 */ + case ISIS_PASSWD_TYPE_HMAC_MD5: + /* Remember where TLV is written so we can later + * overwrite the MD5 hash */ + auth_tlv_offset = stream_get_endp(circuit->snd_stream); + memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE); + if (tlv_add_authinfo(ISIS_PASSWD_TYPE_HMAC_MD5, + ISIS_AUTH_MD5_SIZE, hmac_md5_hash, + circuit->snd_stream)) + return ISIS_WARNING; + break; + + default: + break; + } + } - length = (u_int16_t) stream_get_endp (circuit->snd_stream); - /* Update PDU length */ - stream_putw_at (circuit->snd_stream, lenp, length); + retval = tlv_add_lsp_entries(lsps, circuit->snd_stream); + if (retval != ISIS_OK) + return retval; + + if (isis->debugs & DEBUG_SNP_PACKETS) { + for (ALL_LIST_ELEMENTS_RO(lsps, node, lsp)) { + zlog_debug( + "ISIS-Snp (%s): PSNP entry %s, seq 0x%08x," + " cksum 0x%04x, lifetime %us", + circuit->area->area_tag, + rawlspid_print(lsp->lsp_header->lsp_id), + ntohl(lsp->lsp_header->seq_num), + ntohs(lsp->lsp_header->checksum), + ntohs(lsp->lsp_header->rem_lifetime)); + } + } - /* For HMAC MD5 we need to compute the md5 hash and store it */ - if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND) && - passwd->type == ISIS_PASSWD_TYPE_HMAC_MD5) - { - hmac_md5 (STREAM_DATA (circuit->snd_stream), - stream_get_endp(circuit->snd_stream), - (unsigned char *) &passwd->passwd, passwd->len, - (unsigned char *) &hmac_md5_hash); - /* Copy the hash into the stream */ - memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3, - hmac_md5_hash, ISIS_AUTH_MD5_SIZE); - } + length = (u_int16_t)stream_get_endp(circuit->snd_stream); + /* Update PDU length */ + stream_putw_at(circuit->snd_stream, lenp, length); + + /* For HMAC MD5 we need to compute the md5 hash and store it */ + if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND) + && passwd->type == ISIS_PASSWD_TYPE_HMAC_MD5) { + hmac_md5(STREAM_DATA(circuit->snd_stream), + stream_get_endp(circuit->snd_stream), + (unsigned char *)&passwd->passwd, passwd->len, + (unsigned char *)&hmac_md5_hash); + /* Copy the hash into the stream */ + memcpy(STREAM_DATA(circuit->snd_stream) + auth_tlv_offset + 3, + hmac_md5_hash, ISIS_AUTH_MD5_SIZE); + } - return ISIS_OK; + return ISIS_OK; } /* * 7.3.15.4 action on expiration of partial SNP interval * level 1 */ -static int -send_psnp (int level, struct isis_circuit *circuit) +static int send_psnp(int level, struct isis_circuit *circuit) { - struct isis_lsp *lsp; - struct list *list = NULL; - struct listnode *node; - u_char num_lsps; - int retval = ISIS_OK; + struct isis_lsp *lsp; + struct list *list = NULL; + struct listnode *node; + u_char num_lsps; + int retval = ISIS_OK; - if (circuit->circ_type == CIRCUIT_T_BROADCAST && - circuit->u.bc.is_dr[level - 1]) - return ISIS_OK; + if (circuit->circ_type == CIRCUIT_T_BROADCAST + && circuit->u.bc.is_dr[level - 1]) + return ISIS_OK; - if (circuit->area->lspdb[level - 1] == NULL || - dict_count (circuit->area->lspdb[level - 1]) == 0) - return ISIS_OK; + if (circuit->area->lspdb[level - 1] == NULL + || dict_count(circuit->area->lspdb[level - 1]) == 0) + return ISIS_OK; - if (! circuit->snd_stream) - return ISIS_ERROR; + if (!circuit->snd_stream) + return ISIS_ERROR; - num_lsps = max_lsps_per_snp (ISIS_SNP_PSNP_FLAG, level, circuit); + num_lsps = max_lsps_per_snp(ISIS_SNP_PSNP_FLAG, level, circuit); - while (1) - { - list = list_new (); - lsp_build_list_ssn (circuit, num_lsps, list, - circuit->area->lspdb[level - 1]); - - if (listcount (list) == 0) - { - list_delete (list); - return ISIS_OK; - } - - retval = build_psnp (level, circuit, list); - if (retval != ISIS_OK) - { - zlog_err ("ISIS-Snp (%s): Build L%d PSNP on %s failed", - circuit->area->area_tag, level, circuit->interface->name); - list_delete (list); - return retval; - } - - if (isis->debugs & DEBUG_SNP_PACKETS) - { - zlog_debug ("ISIS-Snp (%s): Sending L%d PSNP on %s, length %zd", - circuit->area->area_tag, level, - circuit->interface->name, - stream_get_endp (circuit->snd_stream)); - if (isis->debugs & DEBUG_PACKET_DUMP) - zlog_dump_data (STREAM_DATA (circuit->snd_stream), - stream_get_endp (circuit->snd_stream)); - } - - retval = circuit->tx (circuit, level); - if (retval != ISIS_OK) - { - zlog_err ("ISIS-Snp (%s): Send L%d PSNP on %s failed", - circuit->area->area_tag, level, - circuit->interface->name); - list_delete (list); - return retval; - } - - /* - * sending succeeded, we can clear SSN flags of this circuit - * for the LSPs in list - */ - for (ALL_LIST_ELEMENTS_RO (list, node, lsp)) - ISIS_CLEAR_FLAG (lsp->SSNflags, circuit); - list_delete (list); - } + while (1) { + list = list_new(); + lsp_build_list_ssn(circuit, num_lsps, list, + circuit->area->lspdb[level - 1]); - return retval; + if (listcount(list) == 0) { + list_delete(list); + return ISIS_OK; + } + + retval = build_psnp(level, circuit, list); + if (retval != ISIS_OK) { + zlog_err("ISIS-Snp (%s): Build L%d PSNP on %s failed", + circuit->area->area_tag, level, + circuit->interface->name); + list_delete(list); + return retval; + } + + if (isis->debugs & DEBUG_SNP_PACKETS) { + zlog_debug( + "ISIS-Snp (%s): Sending L%d PSNP on %s, length %zd", + circuit->area->area_tag, level, + circuit->interface->name, + stream_get_endp(circuit->snd_stream)); + if (isis->debugs & DEBUG_PACKET_DUMP) + zlog_dump_data( + STREAM_DATA(circuit->snd_stream), + stream_get_endp(circuit->snd_stream)); + } + + retval = circuit->tx(circuit, level); + if (retval != ISIS_OK) { + zlog_err("ISIS-Snp (%s): Send L%d PSNP on %s failed", + circuit->area->area_tag, level, + circuit->interface->name); + list_delete(list); + return retval; + } + + /* + * sending succeeded, we can clear SSN flags of this circuit + * for the LSPs in list + */ + for (ALL_LIST_ELEMENTS_RO(list, node, lsp)) + ISIS_CLEAR_FLAG(lsp->SSNflags, circuit); + list_delete(list); + } + + return retval; } -int -send_l1_psnp (struct thread *thread) +int send_l1_psnp(struct thread *thread) { - struct isis_circuit *circuit; - int retval = ISIS_OK; + struct isis_circuit *circuit; + int retval = ISIS_OK; - circuit = THREAD_ARG (thread); - assert (circuit); + circuit = THREAD_ARG(thread); + assert(circuit); - circuit->t_send_psnp[0] = NULL; + circuit->t_send_psnp[0] = NULL; - send_psnp (1, circuit); - /* set next timer thread */ - thread_add_timer(master, send_l1_psnp, circuit, - isis_jitter(circuit->psnp_interval[0], PSNP_JITTER), - &circuit->t_send_psnp[0]); + send_psnp(1, circuit); + /* set next timer thread */ + thread_add_timer(master, send_l1_psnp, circuit, + isis_jitter(circuit->psnp_interval[0], PSNP_JITTER), + &circuit->t_send_psnp[0]); - return retval; + return retval; } /* * 7.3.15.4 action on expiration of partial SNP interval * level 2 */ -int -send_l2_psnp (struct thread *thread) +int send_l2_psnp(struct thread *thread) { - struct isis_circuit *circuit; - int retval = ISIS_OK; + struct isis_circuit *circuit; + int retval = ISIS_OK; - circuit = THREAD_ARG (thread); - assert (circuit); + circuit = THREAD_ARG(thread); + assert(circuit); - circuit->t_send_psnp[1] = NULL; + circuit->t_send_psnp[1] = NULL; - send_psnp (2, circuit); + send_psnp(2, circuit); - /* set next timer thread */ - thread_add_timer(master, send_l2_psnp, circuit, - isis_jitter(circuit->psnp_interval[1], PSNP_JITTER), - &circuit->t_send_psnp[1]); + /* set next timer thread */ + thread_add_timer(master, send_l2_psnp, circuit, + isis_jitter(circuit->psnp_interval[1], PSNP_JITTER), + &circuit->t_send_psnp[1]); - return retval; + return retval; } /* * ISO 10589 - 7.3.14.3 */ -int -send_lsp (struct thread *thread) +int send_lsp(struct thread *thread) { - struct isis_circuit *circuit; - struct isis_lsp *lsp; - struct listnode *node; - int clear_srm = 1; - int retval = ISIS_OK; - - circuit = THREAD_ARG (thread); - assert (circuit); - - if (!circuit->lsp_queue) - return ISIS_OK; - - node = listhead (circuit->lsp_queue); - - /* - * Handle case where there are no LSPs on the queue. This can - * happen, for instance, if an adjacency goes down before this - * thread gets a chance to run. - */ - if (!node) - return ISIS_OK; - - /* - * Delete LSP from lsp_queue. If it's still in queue, it is assumed - * as 'transmit pending', but send_lsp may never be called again. - * Retry will happen because SRM flag will not be cleared. - */ - lsp = listgetdata(node); - list_delete_node (circuit->lsp_queue, node); - - /* Set the last-cleared time if the queue is empty. */ - /* TODO: Is is possible that new lsps keep being added to the queue - * that the queue is never empty? */ - if (list_isempty (circuit->lsp_queue)) - circuit->lsp_queue_last_cleared = time (NULL); - - if (circuit->state != C_STATE_UP || circuit->is_passive == 1) - goto out; - - /* - * Do not send if levels do not match - */ - if (!(lsp->level & circuit->is_type)) - goto out; - - /* - * Do not send if we do not have adjacencies in state up on the circuit - */ - if (circuit->upadjcount[lsp->level - 1] == 0) - goto out; - - /* stream_copy will assert and stop program execution if LSP is larger than - * the circuit's MTU. So handle and log this case here. */ - if (stream_get_endp(lsp->pdu) > stream_get_size(circuit->snd_stream)) - { - zlog_err("ISIS-Upd (%s): Can't send L%d LSP %s, seq 0x%08x," - " cksum 0x%04x, lifetime %us on %s. LSP Size is %zu" - " while interface stream size is %zu.", - circuit->area->area_tag, lsp->level, - rawlspid_print(lsp->lsp_header->lsp_id), - ntohl(lsp->lsp_header->seq_num), - ntohs(lsp->lsp_header->checksum), - ntohs(lsp->lsp_header->rem_lifetime), - circuit->interface->name, - stream_get_endp(lsp->pdu), - stream_get_size(circuit->snd_stream)); - if (isis->debugs & DEBUG_PACKET_DUMP) - zlog_dump_data(STREAM_DATA(lsp->pdu), stream_get_endp(lsp->pdu)); - retval = ISIS_ERROR; - goto out; - } - - /* copy our lsp to the send buffer */ - stream_copy (circuit->snd_stream, lsp->pdu); + struct isis_circuit *circuit; + struct isis_lsp *lsp; + struct listnode *node; + int clear_srm = 1; + int retval = ISIS_OK; + + circuit = THREAD_ARG(thread); + assert(circuit); + + if (!circuit->lsp_queue) + return ISIS_OK; + + node = listhead(circuit->lsp_queue); + + /* + * Handle case where there are no LSPs on the queue. This can + * happen, for instance, if an adjacency goes down before this + * thread gets a chance to run. + */ + if (!node) + return ISIS_OK; + + /* + * Delete LSP from lsp_queue. If it's still in queue, it is assumed + * as 'transmit pending', but send_lsp may never be called again. + * Retry will happen because SRM flag will not be cleared. + */ + lsp = listgetdata(node); + list_delete_node(circuit->lsp_queue, node); + + /* Set the last-cleared time if the queue is empty. */ + /* TODO: Is is possible that new lsps keep being added to the queue + * that the queue is never empty? */ + if (list_isempty(circuit->lsp_queue)) + circuit->lsp_queue_last_cleared = time(NULL); + + if (circuit->state != C_STATE_UP || circuit->is_passive == 1) + goto out; + + /* + * Do not send if levels do not match + */ + if (!(lsp->level & circuit->is_type)) + goto out; + + /* + * Do not send if we do not have adjacencies in state up on the circuit + */ + if (circuit->upadjcount[lsp->level - 1] == 0) + goto out; + + /* stream_copy will assert and stop program execution if LSP is larger + * than + * the circuit's MTU. So handle and log this case here. */ + if (stream_get_endp(lsp->pdu) > stream_get_size(circuit->snd_stream)) { + zlog_err( + "ISIS-Upd (%s): Can't send L%d LSP %s, seq 0x%08x," + " cksum 0x%04x, lifetime %us on %s. LSP Size is %zu" + " while interface stream size is %zu.", + circuit->area->area_tag, lsp->level, + rawlspid_print(lsp->lsp_header->lsp_id), + ntohl(lsp->lsp_header->seq_num), + ntohs(lsp->lsp_header->checksum), + ntohs(lsp->lsp_header->rem_lifetime), + circuit->interface->name, stream_get_endp(lsp->pdu), + stream_get_size(circuit->snd_stream)); + if (isis->debugs & DEBUG_PACKET_DUMP) + zlog_dump_data(STREAM_DATA(lsp->pdu), + stream_get_endp(lsp->pdu)); + retval = ISIS_ERROR; + goto out; + } - if (isis->debugs & DEBUG_UPDATE_PACKETS) - { - zlog_debug - ("ISIS-Upd (%s): Sending L%d LSP %s, seq 0x%08x, cksum 0x%04x," - " lifetime %us on %s", circuit->area->area_tag, lsp->level, - rawlspid_print (lsp->lsp_header->lsp_id), - ntohl (lsp->lsp_header->seq_num), - ntohs (lsp->lsp_header->checksum), - ntohs (lsp->lsp_header->rem_lifetime), - circuit->interface->name); - if (isis->debugs & DEBUG_PACKET_DUMP) - zlog_dump_data (STREAM_DATA (circuit->snd_stream), - stream_get_endp (circuit->snd_stream)); - } + /* copy our lsp to the send buffer */ + stream_copy(circuit->snd_stream, lsp->pdu); + + if (isis->debugs & DEBUG_UPDATE_PACKETS) { + zlog_debug( + "ISIS-Upd (%s): Sending L%d LSP %s, seq 0x%08x, cksum 0x%04x," + " lifetime %us on %s", + circuit->area->area_tag, lsp->level, + rawlspid_print(lsp->lsp_header->lsp_id), + ntohl(lsp->lsp_header->seq_num), + ntohs(lsp->lsp_header->checksum), + ntohs(lsp->lsp_header->rem_lifetime), + circuit->interface->name); + if (isis->debugs & DEBUG_PACKET_DUMP) + zlog_dump_data(STREAM_DATA(circuit->snd_stream), + stream_get_endp(circuit->snd_stream)); + } - clear_srm = 0; - retval = circuit->tx (circuit, lsp->level); - if (retval != ISIS_OK) - { - zlog_err ("ISIS-Upd (%s): Send L%d LSP on %s failed %s", - circuit->area->area_tag, lsp->level, - circuit->interface->name, - (retval == ISIS_WARNING) ? "temporarily" : "permanently"); - } + clear_srm = 0; + retval = circuit->tx(circuit, lsp->level); + if (retval != ISIS_OK) { + zlog_err("ISIS-Upd (%s): Send L%d LSP on %s failed %s", + circuit->area->area_tag, lsp->level, + circuit->interface->name, + (retval == ISIS_WARNING) ? "temporarily" + : "permanently"); + } out: - if (clear_srm - || (retval == ISIS_OK && circuit->circ_type == CIRCUIT_T_BROADCAST) - || (retval != ISIS_OK && retval != ISIS_WARNING)) - { - /* SRM flag will trigger retransmission. We will not retransmit if we - * encountered a fatal error. - * On success, they should only be cleared if it's a broadcast circuit. - * On a P2P circuit, we will wait for the ack from the neighbor to clear - * the fag. - */ - ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); - } + if (clear_srm + || (retval == ISIS_OK && circuit->circ_type == CIRCUIT_T_BROADCAST) + || (retval != ISIS_OK && retval != ISIS_WARNING)) { + /* SRM flag will trigger retransmission. We will not retransmit + * if we + * encountered a fatal error. + * On success, they should only be cleared if it's a broadcast + * circuit. + * On a P2P circuit, we will wait for the ack from the neighbor + * to clear + * the fag. + */ + ISIS_CLEAR_FLAG(lsp->SRMflags, circuit); + } - return retval; + return retval; } -int -ack_lsp (struct isis_link_state_hdr *hdr, struct isis_circuit *circuit, - int level) +int ack_lsp(struct isis_link_state_hdr *hdr, struct isis_circuit *circuit, + int level) { - unsigned long lenp; - int retval; - u_int16_t length; - struct isis_fixed_hdr fixed_hdr; - - isis_circuit_stream(circuit, &circuit->snd_stream); - - // fill_llc_hdr (stream); - if (level == IS_LEVEL_1) - fill_fixed_hdr_andstream (&fixed_hdr, L1_PARTIAL_SEQ_NUM, - circuit->snd_stream); - else - fill_fixed_hdr_andstream (&fixed_hdr, L2_PARTIAL_SEQ_NUM, - circuit->snd_stream); - - - lenp = stream_get_endp (circuit->snd_stream); - stream_putw (circuit->snd_stream, 0); /* PDU length */ - stream_put (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN); - stream_putc (circuit->snd_stream, circuit->idx); - stream_putc (circuit->snd_stream, 9); /* code */ - stream_putc (circuit->snd_stream, 16); /* len */ - - stream_putw (circuit->snd_stream, ntohs (hdr->rem_lifetime)); - stream_put (circuit->snd_stream, hdr->lsp_id, ISIS_SYS_ID_LEN + 2); - stream_putl (circuit->snd_stream, ntohl (hdr->seq_num)); - stream_putw (circuit->snd_stream, ntohs (hdr->checksum)); - - length = (u_int16_t) stream_get_endp (circuit->snd_stream); - /* Update PDU length */ - stream_putw_at (circuit->snd_stream, lenp, length); - - retval = circuit->tx (circuit, level); - if (retval != ISIS_OK) - zlog_err ("ISIS-Upd (%s): Send L%d LSP PSNP on %s failed", - circuit->area->area_tag, level, - circuit->interface->name); - - return retval; + unsigned long lenp; + int retval; + u_int16_t length; + struct isis_fixed_hdr fixed_hdr; + + isis_circuit_stream(circuit, &circuit->snd_stream); + + // fill_llc_hdr (stream); + if (level == IS_LEVEL_1) + fill_fixed_hdr_andstream(&fixed_hdr, L1_PARTIAL_SEQ_NUM, + circuit->snd_stream); + else + fill_fixed_hdr_andstream(&fixed_hdr, L2_PARTIAL_SEQ_NUM, + circuit->snd_stream); + + + lenp = stream_get_endp(circuit->snd_stream); + stream_putw(circuit->snd_stream, 0); /* PDU length */ + stream_put(circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN); + stream_putc(circuit->snd_stream, circuit->idx); + stream_putc(circuit->snd_stream, 9); /* code */ + stream_putc(circuit->snd_stream, 16); /* len */ + + stream_putw(circuit->snd_stream, ntohs(hdr->rem_lifetime)); + stream_put(circuit->snd_stream, hdr->lsp_id, ISIS_SYS_ID_LEN + 2); + stream_putl(circuit->snd_stream, ntohl(hdr->seq_num)); + stream_putw(circuit->snd_stream, ntohs(hdr->checksum)); + + length = (u_int16_t)stream_get_endp(circuit->snd_stream); + /* Update PDU length */ + stream_putw_at(circuit->snd_stream, lenp, length); + + retval = circuit->tx(circuit, level); + if (retval != ISIS_OK) + zlog_err("ISIS-Upd (%s): Send L%d LSP PSNP on %s failed", + circuit->area->area_tag, level, + circuit->interface->name); + + return retval; } diff --git a/isisd/isis_pdu.h b/isisd/isis_pdu.h index e512b6b1b..fa8006cda 100644 --- a/isisd/isis_pdu.h +++ b/isisd/isis_pdu.h @@ -3,17 +3,17 @@ * PDU processing * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -49,16 +49,15 @@ * +-------+-------+-------+-------+-------+-------+-------+-------+ */ -struct esis_fixed_hdr -{ - u_char idrp; - u_char length; - u_char version; - u_char id_len; - u_char pdu_type; - u_int16_t holdtime; - u_int16_t checksum; -} __attribute__ ((packed)); +struct esis_fixed_hdr { + u_char idrp; + u_char length; + u_char version; + u_char id_len; + u_char pdu_type; + u_int16_t holdtime; + u_int16_t checksum; +} __attribute__((packed)); #define ESIS_FIXED_HDR_LEN 9 @@ -69,33 +68,32 @@ struct esis_fixed_hdr /* * IS to IS Fixed Header * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Intradomain Routeing Protocol Discriminator | + * | Intradomain Routeing Protocol Discriminator | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Length Indicator | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Version/Protocol ID extension | * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | R | R | R | PDU Type | + * | R | R | R | PDU Type | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Version | * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Reserved | * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Maximum Area Addresses | + * | Maximum Area Addresses | * +-------+-------+-------+-------+-------+-------+-------+-------+ */ -struct isis_fixed_hdr -{ - u_char idrp; - u_char length; - u_char version1; - u_char id_len; - u_char pdu_type; - u_char version2; - u_char reserved; - u_char max_area_addrs; -} __attribute__ ((packed)); +struct isis_fixed_hdr { + u_char idrp; + u_char length; + u_char version1; + u_char id_len; + u_char pdu_type; + u_char version2; + u_char reserved; + u_char max_area_addrs; +} __attribute__((packed)); #define ISIS_FIXED_HDR_LEN 8 @@ -110,26 +108,25 @@ struct isis_fixed_hdr * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Reserved | Circuit Type | 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ - * + Source ID + id_len + * + Source ID + id_len * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Holding Time | 2 + * | Holding Time | 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | PDU Length | 2 + * | PDU Length | 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | R | Priority | 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | LAN ID | id_len + 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ */ -struct isis_lan_hello_hdr -{ - u_char circuit_t; - u_char source_id[ISIS_SYS_ID_LEN]; - u_int16_t hold_time; - u_int16_t pdu_len; - u_char prio; - u_char lan_id[ISIS_SYS_ID_LEN + 1]; -} __attribute__ ((packed)); +struct isis_lan_hello_hdr { + u_char circuit_t; + u_char source_id[ISIS_SYS_ID_LEN]; + u_int16_t hold_time; + u_int16_t pdu_len; + u_char prio; + u_char lan_id[ISIS_SYS_ID_LEN + 1]; +} __attribute__((packed)); #define ISIS_LANHELLO_HDRLEN 19 #define P2P_HELLO 17 @@ -138,23 +135,22 @@ struct isis_lan_hello_hdr * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Reserved | Circuit Type | 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ - * + Source ID + id_len + * + Source ID + id_len * +-------+-------+-------+-------+-------+-------+-------+-------+ - * + Holding Time + 2 + * + Holding Time + 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ - * + PDU Length + 2 + * + PDU Length + 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | Local Circuit ID | 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ */ -struct isis_p2p_hello_hdr -{ - u_char circuit_t; - u_char source_id[ISIS_SYS_ID_LEN]; - u_int16_t hold_time; - u_int16_t pdu_len; - u_char local_id; -} __attribute__ ((packed)); +struct isis_p2p_hello_hdr { + u_char circuit_t; + u_char source_id[ISIS_SYS_ID_LEN]; + u_int16_t hold_time; + u_int16_t pdu_len; + u_char local_id; +} __attribute__((packed)); #define ISIS_P2PHELLO_HDRLEN 12 #define L1_LINK_STATE 18 @@ -164,7 +160,7 @@ struct isis_p2p_hello_hdr * +-------+-------+-------+-------+-------+-------+-------+-------+ * + PDU Length + 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ - * + Remaining Lifetime + 2 + * + Remaining Lifetime + 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ * | LSP ID | id_len + 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ @@ -175,15 +171,14 @@ struct isis_p2p_hello_hdr * | P | ATT |LSPDBOL| ISTYPE | * +-------+-------+-------+-------+-------+-------+-------+-------+ */ -struct isis_link_state_hdr -{ - u_int16_t pdu_len; - u_int16_t rem_lifetime; - u_char lsp_id[ISIS_SYS_ID_LEN + 2]; - u_int32_t seq_num; - u_int16_t checksum; - u_int8_t lsp_bits; -} __attribute__ ((packed)); +struct isis_link_state_hdr { + u_int16_t pdu_len; + u_int16_t rem_lifetime; + u_char lsp_id[ISIS_SYS_ID_LEN + 2]; + u_int32_t seq_num; + u_int16_t checksum; + u_int8_t lsp_bits; +} __attribute__((packed)); #define ISIS_LSP_HDR_LEN 19 /* @@ -191,7 +186,7 @@ struct isis_link_state_hdr * entry is LSP_ENTRIES_LEN (16) bytes long, the maximum number of LSP entries * can be accomodated in a TLV is * 255 / 16 = 15. - * + * * Therefore, the maximum length of the LSP Entries TLV is * 16 * 15 + 2 (header) = 242 bytes. */ @@ -202,7 +197,7 @@ struct isis_link_state_hdr /* * L1 and L2 IS to IS complete sequence numbers PDU header * +-------+-------+-------+-------+-------+-------+-------+-------+ - * + PDU Length + 2 + * + PDU Length + 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ * + Source ID + id_len + 1 * +-------+-------+-------+-------+-------+-------+-------+-------+ @@ -211,12 +206,11 @@ struct isis_link_state_hdr * + End LSP ID + id_len + 2 * +-------+-------+-------+-------+-------+-------+-------+-------+ */ -struct isis_complete_seqnum_hdr -{ - u_int16_t pdu_len; - u_char source_id[ISIS_SYS_ID_LEN + 1]; - u_char start_lsp_id[ISIS_SYS_ID_LEN + 2]; - u_char stop_lsp_id[ISIS_SYS_ID_LEN + 2]; +struct isis_complete_seqnum_hdr { + u_int16_t pdu_len; + u_char source_id[ISIS_SYS_ID_LEN + 1]; + u_char start_lsp_id[ISIS_SYS_ID_LEN + 2]; + u_char stop_lsp_id[ISIS_SYS_ID_LEN + 2]; }; #define ISIS_CSNP_HDRLEN 25 @@ -230,10 +224,9 @@ struct isis_complete_seqnum_hdr * + Source ID + id_len + 1 * +---------------------------------------------------------------+ */ -struct isis_partial_seqnum_hdr -{ - u_int16_t pdu_len; - u_char source_id[ISIS_SYS_ID_LEN + 1]; +struct isis_partial_seqnum_hdr { + u_int16_t pdu_len; + u_char source_id[ISIS_SYS_ID_LEN + 1]; }; #define ISIS_PSNP_HDRLEN 9 @@ -244,7 +237,7 @@ struct isis_partial_seqnum_hdr /* * Function for receiving IS-IS PDUs */ -int isis_receive (struct thread *thread); +int isis_receive(struct thread *thread); /* * calling arguments for snp_process () @@ -257,18 +250,18 @@ int isis_receive (struct thread *thread); /* * Sending functions */ -int send_lan_l1_hello (struct thread *thread); -int send_lan_l2_hello (struct thread *thread); -int send_p2p_hello (struct thread *thread); -int send_csnp (struct isis_circuit *circuit, int level); -int send_l1_csnp (struct thread *thread); -int send_l2_csnp (struct thread *thread); -int send_l1_psnp (struct thread *thread); -int send_l2_psnp (struct thread *thread); -int send_lsp (struct thread *thread); -int ack_lsp (struct isis_link_state_hdr *hdr, - struct isis_circuit *circuit, int level); -void fill_fixed_hdr (struct isis_fixed_hdr *hdr, u_char pdu_type); -int send_hello (struct isis_circuit *circuit, int level); +int send_lan_l1_hello(struct thread *thread); +int send_lan_l2_hello(struct thread *thread); +int send_p2p_hello(struct thread *thread); +int send_csnp(struct isis_circuit *circuit, int level); +int send_l1_csnp(struct thread *thread); +int send_l2_csnp(struct thread *thread); +int send_l1_psnp(struct thread *thread); +int send_l2_psnp(struct thread *thread); +int send_lsp(struct thread *thread); +int ack_lsp(struct isis_link_state_hdr *hdr, struct isis_circuit *circuit, + int level); +void fill_fixed_hdr(struct isis_fixed_hdr *hdr, u_char pdu_type); +int send_hello(struct isis_circuit *circuit, int level); #endif /* _ZEBRA_ISIS_PDU_H */ diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c index c5985dcd8..e24901b0d 100644 --- a/isisd/isis_pfpacket.c +++ b/isisd/isis_pfpacket.c @@ -2,17 +2,17 @@ * IS-IS Rout(e)ing protocol - isis_pfpacket.c * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -22,7 +22,7 @@ #include #if ISIS_METHOD == ISIS_METHOD_PFPACKET -#include /* the L2 protocols */ +#include /* the L2 protocols */ #include #include @@ -47,17 +47,17 @@ extern struct zebra_privs_t isisd_privs; /* tcpdump -i eth0 'isis' -dd */ -static struct sock_filter isisfilter[] = { -/* NB: we're in SOCK_DGRAM, so src/dst mac + length are stripped off! - * (OTOH it's a bit more lower-layer agnostic and might work over GRE?) */ -/* { 0x28, 0, 0, 0x0000000c - 14 }, */ -/* { 0x25, 5, 0, 0x000005dc }, */ - { 0x28, 0, 0, 0x0000000e - 14 }, - { 0x15, 0, 3, 0x0000fefe }, - { 0x30, 0, 0, 0x00000011 - 14 }, - { 0x15, 0, 1, 0x00000083 }, - { 0x6, 0, 0, 0x00040000 }, - { 0x6, 0, 0, 0x00000000 }, +static struct sock_filter isisfilter[] = + { + /* NB: we're in SOCK_DGRAM, so src/dst mac + length are stripped + * off! + * (OTOH it's a bit more lower-layer agnostic and might work + * over GRE?) */ + /* { 0x28, 0, 0, 0x0000000c - 14 }, */ + /* { 0x25, 5, 0, 0x000005dc }, */ + {0x28, 0, 0, 0x0000000e - 14}, {0x15, 0, 3, 0x0000fefe}, + {0x30, 0, 0, 0x00000011 - 14}, {0x15, 0, 1, 0x00000083}, + {0x6, 0, 0, 0x00040000}, {0x6, 0, 0, 0x00000000}, }; static struct sock_fprog bpf = { @@ -70,10 +70,10 @@ static struct sock_fprog bpf = { * ISO 10589 - 8.4.8 */ -u_char ALL_L1_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x14 }; -u_char ALL_L2_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x15 }; -u_char ALL_ISS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x05 }; -u_char ALL_ESS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x04 }; +u_char ALL_L1_ISS[6] = {0x01, 0x80, 0xC2, 0x00, 0x00, 0x14}; +u_char ALL_L2_ISS[6] = {0x01, 0x80, 0xC2, 0x00, 0x00, 0x15}; +u_char ALL_ISS[6] = {0x09, 0x00, 0x2B, 0x00, 0x00, 0x05}; +u_char ALL_ESS[6] = {0x09, 0x00, 0x2B, 0x00, 0x00, 0x04}; static uint8_t discard_buff[8192]; static uint8_t sock_buff[8192]; @@ -82,367 +82,346 @@ static uint8_t sock_buff[8192]; * if level is 0 we are joining p2p multicast * FIXME: and the p2p multicast being ??? */ -static int -isis_multicast_join (int fd, int registerto, int if_num) +static int isis_multicast_join(int fd, int registerto, int if_num) { - struct packet_mreq mreq; - - memset (&mreq, 0, sizeof (mreq)); - mreq.mr_ifindex = if_num; - if (registerto) - { - mreq.mr_type = PACKET_MR_MULTICAST; - mreq.mr_alen = ETH_ALEN; - if (registerto == 1) - memcpy (&mreq.mr_address, ALL_L1_ISS, ETH_ALEN); - else if (registerto == 2) - memcpy (&mreq.mr_address, ALL_L2_ISS, ETH_ALEN); - else if (registerto == 3) - memcpy (&mreq.mr_address, ALL_ISS, ETH_ALEN); - else - memcpy (&mreq.mr_address, ALL_ESS, ETH_ALEN); - - } - else - { - mreq.mr_type = PACKET_MR_ALLMULTI; - } + struct packet_mreq mreq; + + memset(&mreq, 0, sizeof(mreq)); + mreq.mr_ifindex = if_num; + if (registerto) { + mreq.mr_type = PACKET_MR_MULTICAST; + mreq.mr_alen = ETH_ALEN; + if (registerto == 1) + memcpy(&mreq.mr_address, ALL_L1_ISS, ETH_ALEN); + else if (registerto == 2) + memcpy(&mreq.mr_address, ALL_L2_ISS, ETH_ALEN); + else if (registerto == 3) + memcpy(&mreq.mr_address, ALL_ISS, ETH_ALEN); + else + memcpy(&mreq.mr_address, ALL_ESS, ETH_ALEN); + + } else { + mreq.mr_type = PACKET_MR_ALLMULTI; + } #ifdef EXTREME_DEBUG - zlog_debug ("isis_multicast_join(): fd=%d, reg_to=%d, if_num=%d, " - "address = %02x:%02x:%02x:%02x:%02x:%02x", - fd, registerto, if_num, mreq.mr_address[0], mreq.mr_address[1], - mreq.mr_address[2], mreq.mr_address[3], mreq.mr_address[4], - mreq.mr_address[5]); + zlog_debug( + "isis_multicast_join(): fd=%d, reg_to=%d, if_num=%d, " + "address = %02x:%02x:%02x:%02x:%02x:%02x", + fd, registerto, if_num, mreq.mr_address[0], mreq.mr_address[1], + mreq.mr_address[2], mreq.mr_address[3], mreq.mr_address[4], + mreq.mr_address[5]); #endif /* EXTREME_DEBUG */ - if (setsockopt (fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, - sizeof (struct packet_mreq))) - { - zlog_warn ("isis_multicast_join(): setsockopt(): %s", safe_strerror (errno)); - return ISIS_WARNING; - } - - return ISIS_OK; + if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, + sizeof(struct packet_mreq))) { + zlog_warn("isis_multicast_join(): setsockopt(): %s", + safe_strerror(errno)); + return ISIS_WARNING; + } + + return ISIS_OK; } -static int -open_packet_socket (struct isis_circuit *circuit) +static int open_packet_socket(struct isis_circuit *circuit) { - struct sockaddr_ll s_addr; - int fd, retval = ISIS_OK; - - fd = socket (PF_PACKET, SOCK_DGRAM, htons (ETH_P_ALL)); - if (fd < 0) - { - zlog_warn ("open_packet_socket(): socket() failed %s", - safe_strerror (errno)); - return ISIS_WARNING; - } - - if (setsockopt (fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof (bpf))) - { - zlog_warn ("open_packet_socket(): SO_ATTACH_FILTER failed: %s", - safe_strerror (errno)); - } - - /* - * Bind to the physical interface - */ - memset (&s_addr, 0, sizeof (struct sockaddr_ll)); - s_addr.sll_family = AF_PACKET; - s_addr.sll_protocol = htons (ETH_P_ALL); - s_addr.sll_ifindex = circuit->interface->ifindex; - - if (bind (fd, (struct sockaddr *) (&s_addr), - sizeof (struct sockaddr_ll)) < 0) - { - zlog_warn ("open_packet_socket(): bind() failed: %s", safe_strerror (errno)); - close (fd); - return ISIS_WARNING; - } - - circuit->fd = fd; - - if (if_is_broadcast (circuit->interface)) - { - /* - * Join to multicast groups - * according to - * 8.4.2 - Broadcast subnetwork IIH PDUs - * FIXME: is there a case only one will fail?? - */ - /* joining ALL_L1_ISS */ - retval |= isis_multicast_join (circuit->fd, 1, - circuit->interface->ifindex); - /* joining ALL_L2_ISS */ - retval |= isis_multicast_join (circuit->fd, 2, - circuit->interface->ifindex); - /* joining ALL_ISS (used in RFC 5309 p2p-over-lan as well) */ - retval |= isis_multicast_join (circuit->fd, 3, - circuit->interface->ifindex); - } - else - { - retval = - isis_multicast_join (circuit->fd, 0, circuit->interface->ifindex); - } - - return retval; + struct sockaddr_ll s_addr; + int fd, retval = ISIS_OK; + + fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)); + if (fd < 0) { + zlog_warn("open_packet_socket(): socket() failed %s", + safe_strerror(errno)); + return ISIS_WARNING; + } + + if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf))) { + zlog_warn("open_packet_socket(): SO_ATTACH_FILTER failed: %s", + safe_strerror(errno)); + } + + /* + * Bind to the physical interface + */ + memset(&s_addr, 0, sizeof(struct sockaddr_ll)); + s_addr.sll_family = AF_PACKET; + s_addr.sll_protocol = htons(ETH_P_ALL); + s_addr.sll_ifindex = circuit->interface->ifindex; + + if (bind(fd, (struct sockaddr *)(&s_addr), sizeof(struct sockaddr_ll)) + < 0) { + zlog_warn("open_packet_socket(): bind() failed: %s", + safe_strerror(errno)); + close(fd); + return ISIS_WARNING; + } + + circuit->fd = fd; + + if (if_is_broadcast(circuit->interface)) { + /* + * Join to multicast groups + * according to + * 8.4.2 - Broadcast subnetwork IIH PDUs + * FIXME: is there a case only one will fail?? + */ + /* joining ALL_L1_ISS */ + retval |= isis_multicast_join(circuit->fd, 1, + circuit->interface->ifindex); + /* joining ALL_L2_ISS */ + retval |= isis_multicast_join(circuit->fd, 2, + circuit->interface->ifindex); + /* joining ALL_ISS (used in RFC 5309 p2p-over-lan as well) */ + retval |= isis_multicast_join(circuit->fd, 3, + circuit->interface->ifindex); + } else { + retval = isis_multicast_join(circuit->fd, 0, + circuit->interface->ifindex); + } + + return retval; } /* * Create the socket and set the tx/rx funcs */ -int -isis_sock_init (struct isis_circuit *circuit) +int isis_sock_init(struct isis_circuit *circuit) { - int retval = ISIS_OK; - - if (isisd_privs.change (ZPRIVS_RAISE)) - zlog_err ("%s: could not raise privs, %s", __func__, safe_strerror (errno)); - - retval = open_packet_socket (circuit); - - if (retval != ISIS_OK) - { - zlog_warn ("%s: could not initialize the socket", __func__); - goto end; - } - - /* Assign Rx and Tx callbacks are based on real if type */ - if (if_is_broadcast (circuit->interface)) - { - circuit->tx = isis_send_pdu_bcast; - circuit->rx = isis_recv_pdu_bcast; - } - else if (if_is_pointopoint (circuit->interface)) - { - circuit->tx = isis_send_pdu_p2p; - circuit->rx = isis_recv_pdu_p2p; - } - else - { - zlog_warn ("isis_sock_init(): unknown circuit type"); - retval = ISIS_WARNING; - goto end; - } + int retval = ISIS_OK; + + if (isisd_privs.change(ZPRIVS_RAISE)) + zlog_err("%s: could not raise privs, %s", __func__, + safe_strerror(errno)); + + retval = open_packet_socket(circuit); + + if (retval != ISIS_OK) { + zlog_warn("%s: could not initialize the socket", __func__); + goto end; + } + + /* Assign Rx and Tx callbacks are based on real if type */ + if (if_is_broadcast(circuit->interface)) { + circuit->tx = isis_send_pdu_bcast; + circuit->rx = isis_recv_pdu_bcast; + } else if (if_is_pointopoint(circuit->interface)) { + circuit->tx = isis_send_pdu_p2p; + circuit->rx = isis_recv_pdu_p2p; + } else { + zlog_warn("isis_sock_init(): unknown circuit type"); + retval = ISIS_WARNING; + goto end; + } end: - if (isisd_privs.change (ZPRIVS_LOWER)) - zlog_err ("%s: could not lower privs, %s", __func__, safe_strerror (errno)); + if (isisd_privs.change(ZPRIVS_LOWER)) + zlog_err("%s: could not lower privs, %s", __func__, + safe_strerror(errno)); - return retval; + return retval; } -static inline int -llc_check (u_char * llc) +static inline int llc_check(u_char *llc) { - if (*llc != ISO_SAP || *(llc + 1) != ISO_SAP || *(llc + 2) != 3) - return 0; + if (*llc != ISO_SAP || *(llc + 1) != ISO_SAP || *(llc + 2) != 3) + return 0; - return 1; + return 1; } -int -isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa) +int isis_recv_pdu_bcast(struct isis_circuit *circuit, u_char *ssnpa) { - int bytesread, addr_len; - struct sockaddr_ll s_addr; - u_char llc[LLC_LEN]; - - addr_len = sizeof (s_addr); - - memset (&s_addr, 0, sizeof (struct sockaddr_ll)); - - bytesread = recvfrom (circuit->fd, (void *) &llc, - LLC_LEN, MSG_PEEK, - (struct sockaddr *) &s_addr, (socklen_t *) &addr_len); - - if ((bytesread < 0) || (s_addr.sll_ifindex != (int)circuit->interface->ifindex)) - { - if (bytesread < 0) - { - zlog_warn ("isis_recv_packet_bcast(): ifname %s, fd %d, " - "bytesread %d, recvfrom(): %s", - circuit->interface->name, circuit->fd, bytesread, - safe_strerror (errno)); - } - if (s_addr.sll_ifindex != (int)circuit->interface->ifindex) - { - zlog_warn("packet is received on multiple interfaces: " - "socket interface %d, circuit interface %d, " - "packet type %u", - s_addr.sll_ifindex, circuit->interface->ifindex, - s_addr.sll_pkttype); - } - - /* get rid of the packet */ - bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff), - MSG_DONTWAIT, (struct sockaddr *) &s_addr, - (socklen_t *) &addr_len); - - if (bytesread < 0) - zlog_warn ("isis_recv_pdu_bcast(): recvfrom() failed"); - - return ISIS_WARNING; - } - /* - * Filtering by llc field, discard packets sent by this host (other circuit) - */ - if (!llc_check (llc) || s_addr.sll_pkttype == PACKET_OUTGOING) - { - /* Read the packet into discard buff */ - bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff), - MSG_DONTWAIT, (struct sockaddr *) &s_addr, - (socklen_t *) &addr_len); - if (bytesread < 0) - zlog_warn ("isis_recv_pdu_bcast(): recvfrom() failed"); - return ISIS_WARNING; - } - - /* on lan we have to read to the static buff first */ - bytesread = recvfrom (circuit->fd, sock_buff, sizeof (sock_buff), MSG_DONTWAIT, - (struct sockaddr *) &s_addr, (socklen_t *) &addr_len); - if (bytesread < 0) - { - zlog_warn ("isis_recv_pdu_bcast(): recvfrom() failed"); - return ISIS_WARNING; - } - - /* then we lose the LLC */ - stream_write (circuit->rcv_stream, sock_buff + LLC_LEN, bytesread - LLC_LEN); - - memcpy (ssnpa, &s_addr.sll_addr, s_addr.sll_halen); - - return ISIS_OK; + int bytesread, addr_len; + struct sockaddr_ll s_addr; + u_char llc[LLC_LEN]; + + addr_len = sizeof(s_addr); + + memset(&s_addr, 0, sizeof(struct sockaddr_ll)); + + bytesread = + recvfrom(circuit->fd, (void *)&llc, LLC_LEN, MSG_PEEK, + (struct sockaddr *)&s_addr, (socklen_t *)&addr_len); + + if ((bytesread < 0) + || (s_addr.sll_ifindex != (int)circuit->interface->ifindex)) { + if (bytesread < 0) { + zlog_warn( + "isis_recv_packet_bcast(): ifname %s, fd %d, " + "bytesread %d, recvfrom(): %s", + circuit->interface->name, circuit->fd, + bytesread, safe_strerror(errno)); + } + if (s_addr.sll_ifindex != (int)circuit->interface->ifindex) { + zlog_warn( + "packet is received on multiple interfaces: " + "socket interface %d, circuit interface %d, " + "packet type %u", + s_addr.sll_ifindex, circuit->interface->ifindex, + s_addr.sll_pkttype); + } + + /* get rid of the packet */ + bytesread = recvfrom(circuit->fd, discard_buff, + sizeof(discard_buff), MSG_DONTWAIT, + (struct sockaddr *)&s_addr, + (socklen_t *)&addr_len); + + if (bytesread < 0) + zlog_warn("isis_recv_pdu_bcast(): recvfrom() failed"); + + return ISIS_WARNING; + } + /* + * Filtering by llc field, discard packets sent by this host (other + * circuit) + */ + if (!llc_check(llc) || s_addr.sll_pkttype == PACKET_OUTGOING) { + /* Read the packet into discard buff */ + bytesread = recvfrom(circuit->fd, discard_buff, + sizeof(discard_buff), MSG_DONTWAIT, + (struct sockaddr *)&s_addr, + (socklen_t *)&addr_len); + if (bytesread < 0) + zlog_warn("isis_recv_pdu_bcast(): recvfrom() failed"); + return ISIS_WARNING; + } + + /* on lan we have to read to the static buff first */ + bytesread = recvfrom(circuit->fd, sock_buff, sizeof(sock_buff), + MSG_DONTWAIT, (struct sockaddr *)&s_addr, + (socklen_t *)&addr_len); + if (bytesread < 0) { + zlog_warn("isis_recv_pdu_bcast(): recvfrom() failed"); + return ISIS_WARNING; + } + + /* then we lose the LLC */ + stream_write(circuit->rcv_stream, sock_buff + LLC_LEN, + bytesread - LLC_LEN); + + memcpy(ssnpa, &s_addr.sll_addr, s_addr.sll_halen); + + return ISIS_OK; } -int -isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa) +int isis_recv_pdu_p2p(struct isis_circuit *circuit, u_char *ssnpa) { - int bytesread, addr_len; - struct sockaddr_ll s_addr; - - memset (&s_addr, 0, sizeof (struct sockaddr_ll)); - addr_len = sizeof (s_addr); - - /* we can read directly to the stream */ - stream_recvfrom (circuit->rcv_stream, circuit->fd, - circuit->interface->mtu, 0, - (struct sockaddr *) &s_addr, - (socklen_t *) &addr_len); - - if (s_addr.sll_pkttype == PACKET_OUTGOING) - { - /* Read the packet into discard buff */ - bytesread = recvfrom (circuit->fd, discard_buff, sizeof (discard_buff), - MSG_DONTWAIT, (struct sockaddr *) &s_addr, - (socklen_t *) &addr_len); - if (bytesread < 0) - zlog_warn ("isis_recv_pdu_p2p(): recvfrom() failed"); - return ISIS_WARNING; - } - - /* If we don't have protocol type 0x00FE which is - * ISO over GRE we exit with pain :) - */ - if (ntohs (s_addr.sll_protocol) != 0x00FE) - { - zlog_warn ("isis_recv_pdu_p2p(): protocol mismatch(): %X", - ntohs (s_addr.sll_protocol)); - return ISIS_WARNING; - } - - memcpy (ssnpa, &s_addr.sll_addr, s_addr.sll_halen); - - return ISIS_OK; + int bytesread, addr_len; + struct sockaddr_ll s_addr; + + memset(&s_addr, 0, sizeof(struct sockaddr_ll)); + addr_len = sizeof(s_addr); + + /* we can read directly to the stream */ + stream_recvfrom(circuit->rcv_stream, circuit->fd, + circuit->interface->mtu, 0, (struct sockaddr *)&s_addr, + (socklen_t *)&addr_len); + + if (s_addr.sll_pkttype == PACKET_OUTGOING) { + /* Read the packet into discard buff */ + bytesread = recvfrom(circuit->fd, discard_buff, + sizeof(discard_buff), MSG_DONTWAIT, + (struct sockaddr *)&s_addr, + (socklen_t *)&addr_len); + if (bytesread < 0) + zlog_warn("isis_recv_pdu_p2p(): recvfrom() failed"); + return ISIS_WARNING; + } + + /* If we don't have protocol type 0x00FE which is + * ISO over GRE we exit with pain :) + */ + if (ntohs(s_addr.sll_protocol) != 0x00FE) { + zlog_warn("isis_recv_pdu_p2p(): protocol mismatch(): %X", + ntohs(s_addr.sll_protocol)); + return ISIS_WARNING; + } + + memcpy(ssnpa, &s_addr.sll_addr, s_addr.sll_halen); + + return ISIS_OK; } -int -isis_send_pdu_bcast (struct isis_circuit *circuit, int level) +int isis_send_pdu_bcast(struct isis_circuit *circuit, int level) { - struct msghdr msg; - struct iovec iov[2]; - - /* we need to do the LLC in here because of P2P circuits, which will - * not need it - */ - struct sockaddr_ll sa; - - stream_set_getp (circuit->snd_stream, 0); - memset (&sa, 0, sizeof (struct sockaddr_ll)); - sa.sll_family = AF_PACKET; - - size_t frame_size = stream_get_endp(circuit->snd_stream) + LLC_LEN; - sa.sll_protocol = htons(isis_ethertype(frame_size)); - sa.sll_ifindex = circuit->interface->ifindex; - sa.sll_halen = ETH_ALEN; - /* RFC5309 section 4.1 recommends ALL_ISS */ - if (circuit->circ_type == CIRCUIT_T_P2P) - memcpy (&sa.sll_addr, ALL_ISS, ETH_ALEN); - else if (level == 1) - memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN); - else - memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN); - - /* on a broadcast circuit */ - /* first we put the LLC in */ - sock_buff[0] = 0xFE; - sock_buff[1] = 0xFE; - sock_buff[2] = 0x03; - - memset (&msg, 0, sizeof (msg)); - msg.msg_name = &sa; - msg.msg_namelen = sizeof (struct sockaddr_ll); - msg.msg_iov = iov; - msg.msg_iovlen = 2; - iov[0].iov_base = sock_buff; - iov[0].iov_len = LLC_LEN; - iov[1].iov_base = circuit->snd_stream->data; - iov[1].iov_len = stream_get_endp (circuit->snd_stream); - - if (sendmsg(circuit->fd, &msg, 0) < 0) - { - zlog_warn("IS-IS pfpacket: could not transmit packet on %s: %s", - circuit->interface->name, safe_strerror(errno)); - if (ERRNO_IO_RETRY(errno)) - return ISIS_WARNING; - return ISIS_ERROR; - } - return ISIS_OK; + struct msghdr msg; + struct iovec iov[2]; + + /* we need to do the LLC in here because of P2P circuits, which will + * not need it + */ + struct sockaddr_ll sa; + + stream_set_getp(circuit->snd_stream, 0); + memset(&sa, 0, sizeof(struct sockaddr_ll)); + sa.sll_family = AF_PACKET; + + size_t frame_size = stream_get_endp(circuit->snd_stream) + LLC_LEN; + sa.sll_protocol = htons(isis_ethertype(frame_size)); + sa.sll_ifindex = circuit->interface->ifindex; + sa.sll_halen = ETH_ALEN; + /* RFC5309 section 4.1 recommends ALL_ISS */ + if (circuit->circ_type == CIRCUIT_T_P2P) + memcpy(&sa.sll_addr, ALL_ISS, ETH_ALEN); + else if (level == 1) + memcpy(&sa.sll_addr, ALL_L1_ISS, ETH_ALEN); + else + memcpy(&sa.sll_addr, ALL_L2_ISS, ETH_ALEN); + + /* on a broadcast circuit */ + /* first we put the LLC in */ + sock_buff[0] = 0xFE; + sock_buff[1] = 0xFE; + sock_buff[2] = 0x03; + + memset(&msg, 0, sizeof(msg)); + msg.msg_name = &sa; + msg.msg_namelen = sizeof(struct sockaddr_ll); + msg.msg_iov = iov; + msg.msg_iovlen = 2; + iov[0].iov_base = sock_buff; + iov[0].iov_len = LLC_LEN; + iov[1].iov_base = circuit->snd_stream->data; + iov[1].iov_len = stream_get_endp(circuit->snd_stream); + + if (sendmsg(circuit->fd, &msg, 0) < 0) { + zlog_warn("IS-IS pfpacket: could not transmit packet on %s: %s", + circuit->interface->name, safe_strerror(errno)); + if (ERRNO_IO_RETRY(errno)) + return ISIS_WARNING; + return ISIS_ERROR; + } + return ISIS_OK; } -int -isis_send_pdu_p2p (struct isis_circuit *circuit, int level) +int isis_send_pdu_p2p(struct isis_circuit *circuit, int level) { - struct sockaddr_ll sa; - ssize_t rv; - - stream_set_getp (circuit->snd_stream, 0); - memset (&sa, 0, sizeof (struct sockaddr_ll)); - sa.sll_family = AF_PACKET; - sa.sll_ifindex = circuit->interface->ifindex; - sa.sll_halen = ETH_ALEN; - if (level == 1) - memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN); - else - memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN); - - - /* lets try correcting the protocol */ - sa.sll_protocol = htons (0x00FE); - rv = sendto(circuit->fd, circuit->snd_stream->data, - stream_get_endp (circuit->snd_stream), 0, - (struct sockaddr *) &sa, - sizeof (struct sockaddr_ll)); - if (rv < 0) - { - zlog_warn("IS-IS pfpacket: could not transmit packet on %s: %s", - circuit->interface->name, safe_strerror(errno)); - if (ERRNO_IO_RETRY(errno)) - return ISIS_WARNING; - return ISIS_ERROR; - } - return ISIS_OK; + struct sockaddr_ll sa; + ssize_t rv; + + stream_set_getp(circuit->snd_stream, 0); + memset(&sa, 0, sizeof(struct sockaddr_ll)); + sa.sll_family = AF_PACKET; + sa.sll_ifindex = circuit->interface->ifindex; + sa.sll_halen = ETH_ALEN; + if (level == 1) + memcpy(&sa.sll_addr, ALL_L1_ISS, ETH_ALEN); + else + memcpy(&sa.sll_addr, ALL_L2_ISS, ETH_ALEN); + + + /* lets try correcting the protocol */ + sa.sll_protocol = htons(0x00FE); + rv = sendto(circuit->fd, circuit->snd_stream->data, + stream_get_endp(circuit->snd_stream), 0, + (struct sockaddr *)&sa, sizeof(struct sockaddr_ll)); + if (rv < 0) { + zlog_warn("IS-IS pfpacket: could not transmit packet on %s: %s", + circuit->interface->name, safe_strerror(errno)); + if (ERRNO_IO_RETRY(errno)) + return ISIS_WARNING; + return ISIS_ERROR; + } + return ISIS_OK; } #endif /* ISIS_METHOD == ISIS_METHOD_PFPACKET */ diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c index b3f29fd20..8e329494d 100644 --- a/isisd/isis_redist.c +++ b/isisd/isis_redist.c @@ -3,14 +3,14 @@ * * Copyright (C) 2013-2015 Christian Franke * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -43,514 +43,490 @@ #include "isisd/isis_route.h" #include "isisd/isis_zebra.h" -static int -redist_protocol(int family) +static int redist_protocol(int family) { - if (family == AF_INET) - return 0; - if (family == AF_INET6) - return 1; + if (family == AF_INET) + return 0; + if (family == AF_INET6) + return 1; - assert(!"Unsupported address family!"); - return 0; + assert(!"Unsupported address family!"); + return 0; } -static afi_t -afi_for_redist_protocol(int protocol) +static afi_t afi_for_redist_protocol(int protocol) { - if (protocol == 0) - return AFI_IP; - if (protocol == 1) - return AFI_IP6; + if (protocol == 0) + return AFI_IP; + if (protocol == 1) + return AFI_IP6; - assert(!"Unknown redist protocol!"); - return AFI_IP; + assert(!"Unknown redist protocol!"); + return AFI_IP; } -static int -is_default(struct prefix *p) +static int is_default(struct prefix *p) { - if (p->family == AF_INET) - if (p->u.prefix4.s_addr == 0 && p->prefixlen == 0) - return 1; - if (p->family == AF_INET6) - if (IN6_IS_ADDR_UNSPECIFIED(&p->u.prefix6) && p->prefixlen == 0) - return 1; - return 0; + if (p->family == AF_INET) + if (p->u.prefix4.s_addr == 0 && p->prefixlen == 0) + return 1; + if (p->family == AF_INET6) + if (IN6_IS_ADDR_UNSPECIFIED(&p->u.prefix6) && p->prefixlen == 0) + return 1; + return 0; } -static struct route_table* -get_ext_info(struct isis *i, int family) +static struct route_table *get_ext_info(struct isis *i, int family) { - int protocol = redist_protocol(family); + int protocol = redist_protocol(family); - return i->ext_info[protocol]; + return i->ext_info[protocol]; } -static struct isis_redist* -get_redist_settings(struct isis_area *area, int family, int type, int level) +static struct isis_redist *get_redist_settings(struct isis_area *area, + int family, int type, int level) { - int protocol = redist_protocol(family); + int protocol = redist_protocol(family); - return &area->redist_settings[protocol][type][level-1]; + return &area->redist_settings[protocol][type][level - 1]; } -struct route_table* -get_ext_reach(struct isis_area *area, int family, int level) +struct route_table *get_ext_reach(struct isis_area *area, int family, int level) { - int protocol = redist_protocol(family); + int protocol = redist_protocol(family); - return area->ext_reach[protocol][level-1]; + return area->ext_reach[protocol][level - 1]; } static struct route_node * isis_redist_route_node_create(route_table_delegate_t *delegate, - struct route_table *table) + struct route_table *table) { - struct route_node *node; - node = XCALLOC(MTYPE_ISIS_EXT_ROUTE, sizeof(*node)); - return node; + struct route_node *node; + node = XCALLOC(MTYPE_ISIS_EXT_ROUTE, sizeof(*node)); + return node; } -static void -isis_redist_route_node_destroy(route_table_delegate_t *delegate, - struct route_table *table, - struct route_node *node) +static void isis_redist_route_node_destroy(route_table_delegate_t *delegate, + struct route_table *table, + struct route_node *node) { - if (node->info) - XFREE(MTYPE_ISIS_EXT_INFO, node->info); - XFREE (MTYPE_ISIS_EXT_ROUTE, node); + if (node->info) + XFREE(MTYPE_ISIS_EXT_INFO, node->info); + XFREE(MTYPE_ISIS_EXT_ROUTE, node); } static route_table_delegate_t isis_redist_rt_delegate = { - .create_node = isis_redist_route_node_create, - .destroy_node = isis_redist_route_node_destroy -}; + .create_node = isis_redist_route_node_create, + .destroy_node = isis_redist_route_node_destroy}; /* Install external reachability information into a * specific area for a specific level. * Schedule an lsp regenerate if necessary */ -static void -isis_redist_install(struct isis_area *area, int level, - struct prefix *p, struct isis_ext_info *info) +static void isis_redist_install(struct isis_area *area, int level, + struct prefix *p, struct isis_ext_info *info) { - int family = p->family; - struct route_table *er_table = get_ext_reach(area, family, level); - struct route_node *er_node; - - if (!er_table) - { - zlog_warn("%s: External reachability table of area %s" - " is not initialized.", __func__, area->area_tag); - return; - } - - er_node = route_node_get(er_table, p); - if (er_node->info) - { - route_unlock_node(er_node); - - /* Don't update/reschedule lsp generation if nothing changed. */ - if (!memcmp(er_node->info, info, sizeof(*info))) - return; - } - else - { - er_node->info = XMALLOC(MTYPE_ISIS_EXT_INFO, sizeof(*info)); - } - - memcpy(er_node->info, info, sizeof(*info)); - lsp_regenerate_schedule(area, level, 0); + int family = p->family; + struct route_table *er_table = get_ext_reach(area, family, level); + struct route_node *er_node; + + if (!er_table) { + zlog_warn( + "%s: External reachability table of area %s" + " is not initialized.", + __func__, area->area_tag); + return; + } + + er_node = route_node_get(er_table, p); + if (er_node->info) { + route_unlock_node(er_node); + + /* Don't update/reschedule lsp generation if nothing changed. */ + if (!memcmp(er_node->info, info, sizeof(*info))) + return; + } else { + er_node->info = XMALLOC(MTYPE_ISIS_EXT_INFO, sizeof(*info)); + } + + memcpy(er_node->info, info, sizeof(*info)); + lsp_regenerate_schedule(area, level, 0); } /* Remove external reachability information from a * specific area for a specific level. * Schedule an lsp regenerate if necessary. */ -static void -isis_redist_uninstall(struct isis_area *area, int level, struct prefix *p) +static void isis_redist_uninstall(struct isis_area *area, int level, + struct prefix *p) { - int family = p->family; - struct route_table *er_table = get_ext_reach(area, family, level); - struct route_node *er_node; - - if (!er_table) - { - zlog_warn("%s: External reachability table of area %s" - " is not initialized.", __func__, area->area_tag); - return; - } - - er_node = route_node_lookup(er_table, p); - if (!er_node) - return; - else - route_unlock_node(er_node); - - if (!er_node->info) - return; - - XFREE(MTYPE_ISIS_EXT_INFO, er_node->info); - route_unlock_node(er_node); - lsp_regenerate_schedule(area, level, 0); + int family = p->family; + struct route_table *er_table = get_ext_reach(area, family, level); + struct route_node *er_node; + + if (!er_table) { + zlog_warn( + "%s: External reachability table of area %s" + " is not initialized.", + __func__, area->area_tag); + return; + } + + er_node = route_node_lookup(er_table, p); + if (!er_node) + return; + else + route_unlock_node(er_node); + + if (!er_node->info) + return; + + XFREE(MTYPE_ISIS_EXT_INFO, er_node->info); + route_unlock_node(er_node); + lsp_regenerate_schedule(area, level, 0); } /* Update external reachability info of area for a given level * and prefix, using the given redistribution settings. */ -static void -isis_redist_update_ext_reach(struct isis_area *area, int level, - struct isis_redist *redist, struct prefix *p, - struct isis_ext_info *info) +static void isis_redist_update_ext_reach(struct isis_area *area, int level, + struct isis_redist *redist, + struct prefix *p, + struct isis_ext_info *info) { - struct isis_ext_info area_info; - route_map_result_t map_ret; - - memcpy(&area_info, info, sizeof(area_info)); - if (redist->metric != 0xffffffff) - area_info.metric = redist->metric; - - if (redist->map_name) - { - map_ret = route_map_apply(redist->map, p, RMAP_ISIS, &area_info); - if (map_ret == RMAP_DENYMATCH) - area_info.distance = 255; - } - - /* Allow synthesized default routes only on always orignate */ - if (area_info.origin == DEFAULT_ROUTE - && redist->redist != DEFAULT_ORIGINATE_ALWAYS) - area_info.distance = 255; - - if (area_info.distance < 255) - isis_redist_install(area, level, p, &area_info); - else - isis_redist_uninstall(area, level, p); + struct isis_ext_info area_info; + route_map_result_t map_ret; + + memcpy(&area_info, info, sizeof(area_info)); + if (redist->metric != 0xffffffff) + area_info.metric = redist->metric; + + if (redist->map_name) { + map_ret = + route_map_apply(redist->map, p, RMAP_ISIS, &area_info); + if (map_ret == RMAP_DENYMATCH) + area_info.distance = 255; + } + + /* Allow synthesized default routes only on always orignate */ + if (area_info.origin == DEFAULT_ROUTE + && redist->redist != DEFAULT_ORIGINATE_ALWAYS) + area_info.distance = 255; + + if (area_info.distance < 255) + isis_redist_install(area, level, p, &area_info); + else + isis_redist_uninstall(area, level, p); } -static void -isis_redist_ensure_default(struct isis *isis, int family) +static void isis_redist_ensure_default(struct isis *isis, int family) { - struct prefix p; - struct route_table *ei_table = get_ext_info(isis, family); - struct route_node *ei_node; - struct isis_ext_info *info; - - if (family == AF_INET) - { - p.family = AF_INET; - p.prefixlen = 0; - memset(&p.u.prefix4, 0, sizeof(p.u.prefix4)); - } - else if (family == AF_INET6) - { - p.family = AF_INET6; - p.prefixlen = 0; - memset(&p.u.prefix6, 0, sizeof(p.u.prefix6)); - } - else - assert(!"Unknown family!"); - - ei_node = route_node_get(ei_table, &p); - if (ei_node->info) - { - route_unlock_node(ei_node); - return; - } - - ei_node->info = XCALLOC(MTYPE_ISIS_EXT_INFO, sizeof(struct isis_ext_info)); - - info = ei_node->info; - info->origin = DEFAULT_ROUTE; - info->distance = 254; - info->metric = MAX_WIDE_PATH_METRIC; + struct prefix p; + struct route_table *ei_table = get_ext_info(isis, family); + struct route_node *ei_node; + struct isis_ext_info *info; + + if (family == AF_INET) { + p.family = AF_INET; + p.prefixlen = 0; + memset(&p.u.prefix4, 0, sizeof(p.u.prefix4)); + } else if (family == AF_INET6) { + p.family = AF_INET6; + p.prefixlen = 0; + memset(&p.u.prefix6, 0, sizeof(p.u.prefix6)); + } else + assert(!"Unknown family!"); + + ei_node = route_node_get(ei_table, &p); + if (ei_node->info) { + route_unlock_node(ei_node); + return; + } + + ei_node->info = + XCALLOC(MTYPE_ISIS_EXT_INFO, sizeof(struct isis_ext_info)); + + info = ei_node->info; + info->origin = DEFAULT_ROUTE; + info->distance = 254; + info->metric = MAX_WIDE_PATH_METRIC; } /* Handle notification about route being added */ -void -isis_redist_add(int type, struct prefix *p, u_char distance, uint32_t metric) +void isis_redist_add(int type, struct prefix *p, u_char distance, + uint32_t metric) { - int family = p->family; - struct route_table *ei_table = get_ext_info(isis, family); - struct route_node *ei_node; - struct isis_ext_info *info; - struct listnode *node; - struct isis_area *area; - int level; - struct isis_redist *redist; - - char debug_buf[BUFSIZ]; - prefix2str(p, debug_buf, sizeof(debug_buf)); - - zlog_debug("%s: New route %s from %s.", __func__, debug_buf, - zebra_route_string(type)); - - if (!ei_table) - { - zlog_warn("%s: External information table not initialized.", - __func__); - return; - } - - ei_node = route_node_get(ei_table, p); - if (ei_node->info) - route_unlock_node(ei_node); - else - ei_node->info = XCALLOC(MTYPE_ISIS_EXT_INFO, sizeof(struct isis_ext_info)); - - info = ei_node->info; - info->origin = type; - info->distance = distance; - info->metric = metric; - - if (is_default(p)) - type = DEFAULT_ROUTE; - - for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) - for (level = 1; level <= ISIS_LEVELS; level++) - { - redist = get_redist_settings(area, family, type, level); - if (!redist->redist) - continue; - - isis_redist_update_ext_reach(area, level, redist, p, info); - } + int family = p->family; + struct route_table *ei_table = get_ext_info(isis, family); + struct route_node *ei_node; + struct isis_ext_info *info; + struct listnode *node; + struct isis_area *area; + int level; + struct isis_redist *redist; + + char debug_buf[BUFSIZ]; + prefix2str(p, debug_buf, sizeof(debug_buf)); + + zlog_debug("%s: New route %s from %s.", __func__, debug_buf, + zebra_route_string(type)); + + if (!ei_table) { + zlog_warn("%s: External information table not initialized.", + __func__); + return; + } + + ei_node = route_node_get(ei_table, p); + if (ei_node->info) + route_unlock_node(ei_node); + else + ei_node->info = XCALLOC(MTYPE_ISIS_EXT_INFO, + sizeof(struct isis_ext_info)); + + info = ei_node->info; + info->origin = type; + info->distance = distance; + info->metric = metric; + + if (is_default(p)) + type = DEFAULT_ROUTE; + + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) + for (level = 1; level <= ISIS_LEVELS; level++) { + redist = get_redist_settings(area, family, type, level); + if (!redist->redist) + continue; + + isis_redist_update_ext_reach(area, level, redist, p, + info); + } } -void -isis_redist_delete(int type, struct prefix *p) +void isis_redist_delete(int type, struct prefix *p) { - int family = p->family; - struct route_table *ei_table = get_ext_info(isis, family); - struct route_node *ei_node; - struct listnode *node; - struct isis_area *area; - int level; - struct isis_redist *redist; - - char debug_buf[BUFSIZ]; - prefix2str(p, debug_buf, sizeof(debug_buf)); - - zlog_debug("%s: Removing route %s from %s.", __func__, debug_buf, - zebra_route_string(type)); - - if (is_default(p)) - { - /* Don't remove default route but add synthetic route for use - * by "default-information originate always". Areas without the - * "always" setting will ignore routes with origin DEFAULT_ROUTE. */ - isis_redist_add(DEFAULT_ROUTE, p, 254, MAX_WIDE_PATH_METRIC); - return; - } - - if (!ei_table) - { - zlog_warn("%s: External information table not initialized.", - __func__); - return; - } - - ei_node = route_node_lookup(ei_table, p); - if (!ei_node || !ei_node->info) - { - char buf[BUFSIZ]; - prefix2str(p, buf, sizeof(buf)); - zlog_warn("%s: Got a delete for %s route %s, but that route" - " was never added.", __func__, zebra_route_string(type), - buf); - if (ei_node) - route_unlock_node(ei_node); - return; - } - route_unlock_node(ei_node); - - for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) - for (level = 1; level < ISIS_LEVELS; level++) - { - redist = get_redist_settings(area, family, type, level); - if (!redist->redist) - continue; - - isis_redist_uninstall(area, level, p); - } - - XFREE(MTYPE_ISIS_EXT_INFO, ei_node->info); - route_unlock_node(ei_node); + int family = p->family; + struct route_table *ei_table = get_ext_info(isis, family); + struct route_node *ei_node; + struct listnode *node; + struct isis_area *area; + int level; + struct isis_redist *redist; + + char debug_buf[BUFSIZ]; + prefix2str(p, debug_buf, sizeof(debug_buf)); + + zlog_debug("%s: Removing route %s from %s.", __func__, debug_buf, + zebra_route_string(type)); + + if (is_default(p)) { + /* Don't remove default route but add synthetic route for use + * by "default-information originate always". Areas without the + * "always" setting will ignore routes with origin + * DEFAULT_ROUTE. */ + isis_redist_add(DEFAULT_ROUTE, p, 254, MAX_WIDE_PATH_METRIC); + return; + } + + if (!ei_table) { + zlog_warn("%s: External information table not initialized.", + __func__); + return; + } + + ei_node = route_node_lookup(ei_table, p); + if (!ei_node || !ei_node->info) { + char buf[BUFSIZ]; + prefix2str(p, buf, sizeof(buf)); + zlog_warn( + "%s: Got a delete for %s route %s, but that route" + " was never added.", + __func__, zebra_route_string(type), buf); + if (ei_node) + route_unlock_node(ei_node); + return; + } + route_unlock_node(ei_node); + + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) + for (level = 1; level < ISIS_LEVELS; level++) { + redist = get_redist_settings(area, family, type, level); + if (!redist->redist) + continue; + + isis_redist_uninstall(area, level, p); + } + + XFREE(MTYPE_ISIS_EXT_INFO, ei_node->info); + route_unlock_node(ei_node); } -static void -isis_redist_routemap_set(struct isis_redist *redist, const char *routemap) +static void isis_redist_routemap_set(struct isis_redist *redist, + const char *routemap) { - if (redist->map_name) { - XFREE(MTYPE_ISIS, redist->map_name); - redist->map = NULL; - } - - if (routemap && strlen(routemap)) { - redist->map_name = XSTRDUP(MTYPE_ISIS, routemap); - redist->map = route_map_lookup_by_name(routemap); - } + if (redist->map_name) { + XFREE(MTYPE_ISIS, redist->map_name); + redist->map = NULL; + } + + if (routemap && strlen(routemap)) { + redist->map_name = XSTRDUP(MTYPE_ISIS, routemap); + redist->map = route_map_lookup_by_name(routemap); + } } -static void -isis_redist_update_zebra_subscriptions(struct isis *isis) +static void isis_redist_update_zebra_subscriptions(struct isis *isis) { - struct listnode *node; - struct isis_area *area; - int type; - int level; - int protocol; - - char do_subscribe[REDIST_PROTOCOL_COUNT][ZEBRA_ROUTE_MAX + 1]; - - memset(do_subscribe, 0, sizeof(do_subscribe)); - - for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) - for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++) - for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) - for (level = 0; level < ISIS_LEVELS; level++) - if (area->redist_settings[protocol][type][level].redist) - do_subscribe[protocol][type] = 1; - - for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++) - for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) - { - /* This field is actually controlling transmission of the IS-IS - * routes to Zebra and has nothing to do with redistribution, - * so skip it. */ - if (type == ZEBRA_ROUTE_ISIS) - continue; - - afi_t afi = afi_for_redist_protocol(protocol); - - if (do_subscribe[protocol][type]) - isis_zebra_redistribute_set(afi, type); - else - isis_zebra_redistribute_unset(afi, type); - } + struct listnode *node; + struct isis_area *area; + int type; + int level; + int protocol; + + char do_subscribe[REDIST_PROTOCOL_COUNT][ZEBRA_ROUTE_MAX + 1]; + + memset(do_subscribe, 0, sizeof(do_subscribe)); + + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) + for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++) + for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) + for (level = 0; level < ISIS_LEVELS; level++) + if (area->redist_settings[protocol] + [type] + [level].redist) + do_subscribe[protocol][type] = + 1; + + for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++) + for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) { + /* This field is actually controlling transmission of + * the IS-IS + * routes to Zebra and has nothing to do with + * redistribution, + * so skip it. */ + if (type == ZEBRA_ROUTE_ISIS) + continue; + + afi_t afi = afi_for_redist_protocol(protocol); + + if (do_subscribe[protocol][type]) + isis_zebra_redistribute_set(afi, type); + else + isis_zebra_redistribute_unset(afi, type); + } } -static void -isis_redist_set(struct isis_area *area, int level, - int family, int type, uint32_t metric, - const char *routemap, int originate_type) +static void isis_redist_set(struct isis_area *area, int level, int family, + int type, uint32_t metric, const char *routemap, + int originate_type) { - int protocol = redist_protocol(family); - struct isis_redist *redist = get_redist_settings(area, family, type, level); - int i; - struct route_table *ei_table; - struct route_node *rn; - struct isis_ext_info *info; - - redist->redist = (type == DEFAULT_ROUTE) ? originate_type : 1; - redist->metric = metric; - isis_redist_routemap_set(redist, routemap); - - if (!area->ext_reach[protocol][level-1]) - { - area->ext_reach[protocol][level-1] = - route_table_init_with_delegate(&isis_redist_rt_delegate); - } - - for (i = 0; i < REDIST_PROTOCOL_COUNT; i++) - if (!area->isis->ext_info[i]) - { - area->isis->ext_info[i] = - route_table_init_with_delegate(&isis_redist_rt_delegate); - } - - isis_redist_update_zebra_subscriptions(area->isis); - - if (type == DEFAULT_ROUTE && originate_type == DEFAULT_ORIGINATE_ALWAYS) - isis_redist_ensure_default(area->isis, family); - - ei_table = get_ext_info(area->isis, family); - for (rn = route_top(ei_table); rn; rn = route_next(rn)) - { - if (!rn->info) - continue; - info = rn->info; - - if (type == DEFAULT_ROUTE) - { - if (!is_default(&rn->p)) - continue; - } - else - { - if (info->origin != type) - continue; - } - - isis_redist_update_ext_reach(area, level, redist, &rn->p, info); - } + int protocol = redist_protocol(family); + struct isis_redist *redist = + get_redist_settings(area, family, type, level); + int i; + struct route_table *ei_table; + struct route_node *rn; + struct isis_ext_info *info; + + redist->redist = (type == DEFAULT_ROUTE) ? originate_type : 1; + redist->metric = metric; + isis_redist_routemap_set(redist, routemap); + + if (!area->ext_reach[protocol][level - 1]) { + area->ext_reach[protocol][level - 1] = + route_table_init_with_delegate( + &isis_redist_rt_delegate); + } + + for (i = 0; i < REDIST_PROTOCOL_COUNT; i++) + if (!area->isis->ext_info[i]) { + area->isis->ext_info[i] = + route_table_init_with_delegate( + &isis_redist_rt_delegate); + } + + isis_redist_update_zebra_subscriptions(area->isis); + + if (type == DEFAULT_ROUTE && originate_type == DEFAULT_ORIGINATE_ALWAYS) + isis_redist_ensure_default(area->isis, family); + + ei_table = get_ext_info(area->isis, family); + for (rn = route_top(ei_table); rn; rn = route_next(rn)) { + if (!rn->info) + continue; + info = rn->info; + + if (type == DEFAULT_ROUTE) { + if (!is_default(&rn->p)) + continue; + } else { + if (info->origin != type) + continue; + } + + isis_redist_update_ext_reach(area, level, redist, &rn->p, info); + } } -static void -isis_redist_unset(struct isis_area *area, int level, - int family, int type) +static void isis_redist_unset(struct isis_area *area, int level, int family, + int type) { - struct isis_redist *redist = get_redist_settings(area, family, type, level); - struct route_table *er_table = get_ext_reach(area, family, level); - struct route_node *rn; - struct isis_ext_info *info; - - if (!redist->redist) - return; - - redist->redist = 0; - if (!er_table) - { - zlog_warn("%s: External reachability table uninitialized.", __func__); - return; - } - - for (rn = route_top(er_table); rn; rn = route_next(rn)) - { - if (!rn->info) - continue; - info = rn->info; - - if (type == DEFAULT_ROUTE) - { - if (!is_default(&rn->p)) - continue; - } - else - { - if (info->origin != type) - continue; - } - - XFREE(MTYPE_ISIS_EXT_INFO, rn->info); - route_unlock_node(rn); - } - - lsp_regenerate_schedule(area, level, 0); - isis_redist_update_zebra_subscriptions(area->isis); + struct isis_redist *redist = + get_redist_settings(area, family, type, level); + struct route_table *er_table = get_ext_reach(area, family, level); + struct route_node *rn; + struct isis_ext_info *info; + + if (!redist->redist) + return; + + redist->redist = 0; + if (!er_table) { + zlog_warn("%s: External reachability table uninitialized.", + __func__); + return; + } + + for (rn = route_top(er_table); rn; rn = route_next(rn)) { + if (!rn->info) + continue; + info = rn->info; + + if (type == DEFAULT_ROUTE) { + if (!is_default(&rn->p)) + continue; + } else { + if (info->origin != type) + continue; + } + + XFREE(MTYPE_ISIS_EXT_INFO, rn->info); + route_unlock_node(rn); + } + + lsp_regenerate_schedule(area, level, 0); + isis_redist_update_zebra_subscriptions(area->isis); } -void -isis_redist_area_finish(struct isis_area *area) +void isis_redist_area_finish(struct isis_area *area) { - int protocol; - int level; - int type; - - for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++) - for (level = 0; level < ISIS_LEVELS; level++) - { - for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) - { - struct isis_redist *redist; - - redist = &area->redist_settings[protocol][type][level]; - redist->redist = 0; - if (redist->map_name) - XFREE(MTYPE_ISIS, redist->map_name); - } - route_table_finish(area->ext_reach[protocol][level]); - } - - isis_redist_update_zebra_subscriptions(area->isis); + int protocol; + int level; + int type; + + for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++) + for (level = 0; level < ISIS_LEVELS; level++) { + for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) { + struct isis_redist *redist; + + redist = &area->redist_settings[protocol][type] + [level]; + redist->redist = 0; + if (redist->map_name) + XFREE(MTYPE_ISIS, redist->map_name); + } + route_table_finish(area->ext_reach[protocol][level]); + } + + isis_redist_update_zebra_subscriptions(area->isis); } DEFUN (isis_redistribute, @@ -567,67 +543,63 @@ DEFUN (isis_redistribute, "Route map reference\n" "Pointer to route-map entries\n") { - int idx_afi = 1; - int idx_protocol = 2; - int idx_level = 3; - int idx_metric_rmap = 4; - VTY_DECLVAR_CONTEXT (isis_area, area); - int family; - int afi; - int type; - int level; - unsigned long metric; - const char *routemap = NULL; - - family = str2family(argv[idx_afi]->text); - if (family < 0) - return CMD_WARNING_CONFIG_FAILED; - - afi = family2afi(family); - if (!afi) - return CMD_WARNING_CONFIG_FAILED; - - type = proto_redistnum(afi, argv[idx_protocol]->text); - if (type < 0) - return CMD_WARNING_CONFIG_FAILED; - - if (!strcmp("level-1", argv[idx_level]->arg)) - level = 1; - else if (!strcmp("level-2", argv[idx_level]->arg)) - level = 2; - else - return CMD_WARNING_CONFIG_FAILED; - - if ((area->is_type & level) != level) - { - vty_out (vty, "Node is not a level-%d IS\n", level); - return CMD_WARNING_CONFIG_FAILED; - } - - metric = 0xffffffff; - routemap = NULL; - - if (argc > idx_metric_rmap + 1) - { - if (argv[idx_metric_rmap + 1]->arg[0] == '\0') - return CMD_WARNING_CONFIG_FAILED; - - if (strmatch(argv[idx_metric_rmap]->text, "metric")) - { - char *endp; - metric = strtoul(argv[idx_metric_rmap + 1]->arg, &endp, 10); - - if (*endp != '\0') - return CMD_WARNING_CONFIG_FAILED; - } - else - { - routemap = argv[idx_metric_rmap + 1]->arg; - } - } - - isis_redist_set(area, level, family, type, metric, routemap, 0); - return 0; + int idx_afi = 1; + int idx_protocol = 2; + int idx_level = 3; + int idx_metric_rmap = 4; + VTY_DECLVAR_CONTEXT(isis_area, area); + int family; + int afi; + int type; + int level; + unsigned long metric; + const char *routemap = NULL; + + family = str2family(argv[idx_afi]->text); + if (family < 0) + return CMD_WARNING_CONFIG_FAILED; + + afi = family2afi(family); + if (!afi) + return CMD_WARNING_CONFIG_FAILED; + + type = proto_redistnum(afi, argv[idx_protocol]->text); + if (type < 0) + return CMD_WARNING_CONFIG_FAILED; + + if (!strcmp("level-1", argv[idx_level]->arg)) + level = 1; + else if (!strcmp("level-2", argv[idx_level]->arg)) + level = 2; + else + return CMD_WARNING_CONFIG_FAILED; + + if ((area->is_type & level) != level) { + vty_out(vty, "Node is not a level-%d IS\n", level); + return CMD_WARNING_CONFIG_FAILED; + } + + metric = 0xffffffff; + routemap = NULL; + + if (argc > idx_metric_rmap + 1) { + if (argv[idx_metric_rmap + 1]->arg[0] == '\0') + return CMD_WARNING_CONFIG_FAILED; + + if (strmatch(argv[idx_metric_rmap]->text, "metric")) { + char *endp; + metric = strtoul(argv[idx_metric_rmap + 1]->arg, &endp, + 10); + + if (*endp != '\0') + return CMD_WARNING_CONFIG_FAILED; + } else { + routemap = argv[idx_metric_rmap + 1]->arg; + } + } + + isis_redist_set(area, level, family, type, metric, routemap, 0); + return 0; } DEFUN (no_isis_redistribute, @@ -641,31 +613,31 @@ DEFUN (no_isis_redistribute, "Redistribute into level-1\n" "Redistribute into level-2\n") { - int idx_afi = 2; - int idx_protocol = 3; - int idx_level = 4; - VTY_DECLVAR_CONTEXT (isis_area, area); - int type; - int level; - int family; - int afi; - - family = str2family(argv[idx_afi]->arg); - if (family < 0) - return CMD_WARNING_CONFIG_FAILED; - - afi = family2afi(family); - if (!afi) - return CMD_WARNING_CONFIG_FAILED; - - type = proto_redistnum(afi, argv[idx_protocol]->text); - if (type < 0) - return CMD_WARNING_CONFIG_FAILED; - - level = strmatch ("level-1", argv[idx_level]->text) ? 1 : 2; - - isis_redist_unset(area, level, family, type); - return 0; + int idx_afi = 2; + int idx_protocol = 3; + int idx_level = 4; + VTY_DECLVAR_CONTEXT(isis_area, area); + int type; + int level; + int family; + int afi; + + family = str2family(argv[idx_afi]->arg); + if (family < 0) + return CMD_WARNING_CONFIG_FAILED; + + afi = family2afi(family); + if (!afi) + return CMD_WARNING_CONFIG_FAILED; + + type = proto_redistnum(afi, argv[idx_protocol]->text); + if (type < 0) + return CMD_WARNING_CONFIG_FAILED; + + level = strmatch("level-1", argv[idx_level]->text) ? 1 : 2; + + isis_redist_unset(area, level, family, type); + return 0; } DEFUN (isis_default_originate, @@ -683,52 +655,51 @@ DEFUN (isis_default_originate, "Route map reference\n" "Pointer to route-map entries\n") { - int idx_afi = 2; - int idx_level = 3; - int idx_always = 4; - int idx_metric_rmap = 4; - VTY_DECLVAR_CONTEXT (isis_area, area); - int family; - int originate_type = DEFAULT_ORIGINATE; - int level; - unsigned long metric = 0xffffffff; - const char *routemap = NULL; - - family = str2family(argv[idx_afi]->text); - if (family < 0) - return CMD_WARNING_CONFIG_FAILED; - - level = strmatch ("level-1", argv[idx_level]->text) ? 1 : 2; - - if ((area->is_type & level) != level) - { - vty_out (vty, "Node is not a level-%d IS\n", level); - return CMD_WARNING_CONFIG_FAILED; - } - - if (argc > idx_always && strmatch (argv[idx_always]->text, "always")) - { - originate_type = DEFAULT_ORIGINATE_ALWAYS; - idx_metric_rmap++; - } - - if (argc > idx_metric_rmap) - { - if (strmatch(argv[idx_metric_rmap]->text, "metric")) - metric = strtoul(argv[idx_metric_rmap + 1]->arg, NULL, 10); - else - routemap = argv[idx_metric_rmap + 1]->arg; - } - - if (family == AF_INET6 && originate_type != DEFAULT_ORIGINATE_ALWAYS) - { - vty_out (vty, - "Zebra doesn't implement default-originate for IPv6 yet\n"); - vty_out (vty, "so use with care or use default-originate always.\n"); - } - - isis_redist_set(area, level, family, DEFAULT_ROUTE, metric, routemap, originate_type); - return 0; + int idx_afi = 2; + int idx_level = 3; + int idx_always = 4; + int idx_metric_rmap = 4; + VTY_DECLVAR_CONTEXT(isis_area, area); + int family; + int originate_type = DEFAULT_ORIGINATE; + int level; + unsigned long metric = 0xffffffff; + const char *routemap = NULL; + + family = str2family(argv[idx_afi]->text); + if (family < 0) + return CMD_WARNING_CONFIG_FAILED; + + level = strmatch("level-1", argv[idx_level]->text) ? 1 : 2; + + if ((area->is_type & level) != level) { + vty_out(vty, "Node is not a level-%d IS\n", level); + return CMD_WARNING_CONFIG_FAILED; + } + + if (argc > idx_always && strmatch(argv[idx_always]->text, "always")) { + originate_type = DEFAULT_ORIGINATE_ALWAYS; + idx_metric_rmap++; + } + + if (argc > idx_metric_rmap) { + if (strmatch(argv[idx_metric_rmap]->text, "metric")) + metric = strtoul(argv[idx_metric_rmap + 1]->arg, NULL, + 10); + else + routemap = argv[idx_metric_rmap + 1]->arg; + } + + if (family == AF_INET6 && originate_type != DEFAULT_ORIGINATE_ALWAYS) { + vty_out(vty, + "Zebra doesn't implement default-originate for IPv6 yet\n"); + vty_out(vty, + "so use with care or use default-originate always.\n"); + } + + isis_redist_set(area, level, family, DEFAULT_ROUTE, metric, routemap, + originate_type); + return 0; } DEFUN (no_isis_default_originate, @@ -742,90 +713,86 @@ DEFUN (no_isis_default_originate, "Distribute default route into level-1\n" "Distribute default route into level-2\n") { - int idx_afi = 3; - int idx_level = 4; - VTY_DECLVAR_CONTEXT (isis_area, area); - int family; - int level; - - family = str2family(argv[idx_afi]->text); - if (family < 0) - return CMD_WARNING_CONFIG_FAILED; - - if (strmatch ("level-1", argv[idx_level]->text)) - level = 1; - else if (strmatch ("level-2", argv[idx_level]->text)) - level = 2; - else - return CMD_WARNING_CONFIG_FAILED; - - isis_redist_unset(area, level, family, DEFAULT_ROUTE); - return 0; + int idx_afi = 3; + int idx_level = 4; + VTY_DECLVAR_CONTEXT(isis_area, area); + int family; + int level; + + family = str2family(argv[idx_afi]->text); + if (family < 0) + return CMD_WARNING_CONFIG_FAILED; + + if (strmatch("level-1", argv[idx_level]->text)) + level = 1; + else if (strmatch("level-2", argv[idx_level]->text)) + level = 2; + else + return CMD_WARNING_CONFIG_FAILED; + + isis_redist_unset(area, level, family, DEFAULT_ROUTE); + return 0; } -int -isis_redist_config_write(struct vty *vty, struct isis_area *area, - int family) +int isis_redist_config_write(struct vty *vty, struct isis_area *area, + int family) { - int type; - int level; - int write = 0; - struct isis_redist *redist; - const char *family_str; - - if (family == AF_INET) - family_str = "ipv4"; - else if (family == AF_INET6) - family_str = "ipv6"; - else - return 0; - - for (type = 0; type < ZEBRA_ROUTE_MAX; type++) - { - if (type == ZEBRA_ROUTE_ISIS) - continue; - - for (level = 1; level <= ISIS_LEVELS; level++) - { - redist = get_redist_settings(area, family, type, level); - if (!redist->redist) - continue; - vty_out(vty, " redistribute %s %s level-%d", - family_str, zebra_route_string(type), level); - if (redist->metric != 0xffffffff) - vty_out(vty, " metric %u", redist->metric); - if (redist->map_name) - vty_out(vty, " route-map %s", redist->map_name); - vty_out (vty, "\n"); - write++; - } - } - - for (level = 1; level <= ISIS_LEVELS; level++) - { - redist = get_redist_settings(area, family, DEFAULT_ROUTE, level); - if (!redist->redist) - continue; - vty_out(vty, " default-information originate %s level-%d", - family_str, level); - if (redist->redist == DEFAULT_ORIGINATE_ALWAYS) - vty_out(vty, " always"); - if (redist->metric != 0xffffffff) - vty_out(vty, " metric %u", redist->metric); - if (redist->map_name) - vty_out(vty, " route-map %s", redist->map_name); - vty_out (vty, "\n"); - write++; - } - - return write; + int type; + int level; + int write = 0; + struct isis_redist *redist; + const char *family_str; + + if (family == AF_INET) + family_str = "ipv4"; + else if (family == AF_INET6) + family_str = "ipv6"; + else + return 0; + + for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { + if (type == ZEBRA_ROUTE_ISIS) + continue; + + for (level = 1; level <= ISIS_LEVELS; level++) { + redist = get_redist_settings(area, family, type, level); + if (!redist->redist) + continue; + vty_out(vty, " redistribute %s %s level-%d", family_str, + zebra_route_string(type), level); + if (redist->metric != 0xffffffff) + vty_out(vty, " metric %u", redist->metric); + if (redist->map_name) + vty_out(vty, " route-map %s", redist->map_name); + vty_out(vty, "\n"); + write++; + } + } + + for (level = 1; level <= ISIS_LEVELS; level++) { + redist = + get_redist_settings(area, family, DEFAULT_ROUTE, level); + if (!redist->redist) + continue; + vty_out(vty, " default-information originate %s level-%d", + family_str, level); + if (redist->redist == DEFAULT_ORIGINATE_ALWAYS) + vty_out(vty, " always"); + if (redist->metric != 0xffffffff) + vty_out(vty, " metric %u", redist->metric); + if (redist->map_name) + vty_out(vty, " route-map %s", redist->map_name); + vty_out(vty, "\n"); + write++; + } + + return write; } -void -isis_redist_init(void) +void isis_redist_init(void) { - install_element(ISIS_NODE, &isis_redistribute_cmd); - install_element(ISIS_NODE, &no_isis_redistribute_cmd); - install_element(ISIS_NODE, &isis_default_originate_cmd); - install_element(ISIS_NODE, &no_isis_default_originate_cmd); + install_element(ISIS_NODE, &isis_redistribute_cmd); + install_element(ISIS_NODE, &no_isis_redistribute_cmd); + install_element(ISIS_NODE, &isis_default_originate_cmd); + install_element(ISIS_NODE, &no_isis_default_originate_cmd); } diff --git a/isisd/isis_redist.h b/isisd/isis_redist.h index 11b3c31e2..2bd40e849 100644 --- a/isisd/isis_redist.h +++ b/isisd/isis_redist.h @@ -3,14 +3,14 @@ * * Copyright (C) 2013-2015 Christian Franke * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -27,32 +27,30 @@ #define DEFAULT_ORIGINATE 1 #define DEFAULT_ORIGINATE_ALWAYS 2 -struct isis_ext_info -{ - int origin; - uint32_t metric; - u_char distance; +struct isis_ext_info { + int origin; + uint32_t metric; + u_char distance; }; -struct isis_redist -{ - int redist; - uint32_t metric; - char *map_name; - struct route_map *map; +struct isis_redist { + int redist; + uint32_t metric; + char *map_name; + struct route_map *map; }; struct isis_area; struct prefix; struct vty; -struct route_table *get_ext_reach(struct isis_area *area, - int family, int level); -void isis_redist_add(int type, struct prefix *p, - u_char distance, uint32_t metric); +struct route_table *get_ext_reach(struct isis_area *area, int family, + int level); +void isis_redist_add(int type, struct prefix *p, u_char distance, + uint32_t metric); void isis_redist_delete(int type, struct prefix *p); int isis_redist_config_write(struct vty *vty, struct isis_area *area, - int family); + int family); void isis_redist_init(void); void isis_redist_area_finish(struct isis_area *area); diff --git a/isisd/isis_route.c b/isisd/isis_route.c index bceb70ce0..afc4f6512 100644 --- a/isisd/isis_route.c +++ b/isisd/isis_route.c @@ -1,20 +1,20 @@ /* * IS-IS Rout(e)ing protocol - isis_route.c * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * * based on ../ospf6d/ospf6_route.[ch] * by Yasuhiro Ohara * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -49,502 +49,489 @@ #include "isis_route.h" #include "isis_zebra.h" -static struct isis_nexthop * -isis_nexthop_create (struct in_addr *ip, ifindex_t ifindex) +static struct isis_nexthop *isis_nexthop_create(struct in_addr *ip, + ifindex_t ifindex) { - struct listnode *node; - struct isis_nexthop *nexthop; + struct listnode *node; + struct isis_nexthop *nexthop; - for (ALL_LIST_ELEMENTS_RO (isis->nexthops, node, nexthop)) - { - if (nexthop->ifindex != ifindex) - continue; - if (ip && memcmp (&nexthop->ip, ip, sizeof (struct in_addr)) != 0) - continue; + for (ALL_LIST_ELEMENTS_RO(isis->nexthops, node, nexthop)) { + if (nexthop->ifindex != ifindex) + continue; + if (ip && memcmp(&nexthop->ip, ip, sizeof(struct in_addr)) != 0) + continue; - nexthop->lock++; - return nexthop; - } + nexthop->lock++; + return nexthop; + } - nexthop = XCALLOC (MTYPE_ISIS_NEXTHOP, sizeof (struct isis_nexthop)); + nexthop = XCALLOC(MTYPE_ISIS_NEXTHOP, sizeof(struct isis_nexthop)); - nexthop->ifindex = ifindex; - memcpy (&nexthop->ip, ip, sizeof (struct in_addr)); - listnode_add (isis->nexthops, nexthop); - nexthop->lock++; + nexthop->ifindex = ifindex; + memcpy(&nexthop->ip, ip, sizeof(struct in_addr)); + listnode_add(isis->nexthops, nexthop); + nexthop->lock++; - return nexthop; + return nexthop; } -static void -isis_nexthop_delete (struct isis_nexthop *nexthop) +static void isis_nexthop_delete(struct isis_nexthop *nexthop) { - nexthop->lock--; - if (nexthop->lock == 0) - { - listnode_delete (isis->nexthops, nexthop); - XFREE (MTYPE_ISIS_NEXTHOP, nexthop); - } - - return; + nexthop->lock--; + if (nexthop->lock == 0) { + listnode_delete(isis->nexthops, nexthop); + XFREE(MTYPE_ISIS_NEXTHOP, nexthop); + } + + return; } -static int -nexthoplookup (struct list *nexthops, struct in_addr *ip, - ifindex_t ifindex) +static int nexthoplookup(struct list *nexthops, struct in_addr *ip, + ifindex_t ifindex) { - struct listnode *node; - struct isis_nexthop *nh; + struct listnode *node; + struct isis_nexthop *nh; - for (ALL_LIST_ELEMENTS_RO (nexthops, node, nh)) - { - if (!(memcmp (ip, &nh->ip, sizeof (struct in_addr))) && - ifindex == nh->ifindex) - return 1; - } + for (ALL_LIST_ELEMENTS_RO(nexthops, node, nh)) { + if (!(memcmp(ip, &nh->ip, sizeof(struct in_addr))) + && ifindex == nh->ifindex) + return 1; + } - return 0; + return 0; } #ifdef EXTREME_DEBUG -static void -nexthop_print (struct isis_nexthop *nh) +static void nexthop_print(struct isis_nexthop *nh) { - u_char buf[BUFSIZ]; + u_char buf[BUFSIZ]; - inet_ntop (AF_INET, &nh->ip, (char *) buf, BUFSIZ); + inet_ntop(AF_INET, &nh->ip, (char *)buf, BUFSIZ); - zlog_debug (" %s %u", buf, nh->ifindex); + zlog_debug(" %s %u", buf, nh->ifindex); } -static void -nexthops_print (struct list *nhs) +static void nexthops_print(struct list *nhs) { - struct listnode *node; - struct isis_nexthop *nh; + struct listnode *node; + struct isis_nexthop *nh; - for (ALL_LIST_ELEMENTS_RO (nhs, node, nh)) - nexthop_print (nh); + for (ALL_LIST_ELEMENTS_RO(nhs, node, nh)) + nexthop_print(nh); } #endif /* EXTREME_DEBUG */ -static struct isis_nexthop6 * -isis_nexthop6_new (struct in6_addr *ip6, ifindex_t ifindex) +static struct isis_nexthop6 *isis_nexthop6_new(struct in6_addr *ip6, + ifindex_t ifindex) { - struct isis_nexthop6 *nexthop6; + struct isis_nexthop6 *nexthop6; - nexthop6 = XCALLOC (MTYPE_ISIS_NEXTHOP6, sizeof (struct isis_nexthop6)); + nexthop6 = XCALLOC(MTYPE_ISIS_NEXTHOP6, sizeof(struct isis_nexthop6)); - nexthop6->ifindex = ifindex; - memcpy (&nexthop6->ip6, ip6, sizeof (struct in6_addr)); - nexthop6->lock++; + nexthop6->ifindex = ifindex; + memcpy(&nexthop6->ip6, ip6, sizeof(struct in6_addr)); + nexthop6->lock++; - return nexthop6; + return nexthop6; } -static struct isis_nexthop6 * -isis_nexthop6_create (struct in6_addr *ip6, ifindex_t ifindex) +static struct isis_nexthop6 *isis_nexthop6_create(struct in6_addr *ip6, + ifindex_t ifindex) { - struct listnode *node; - struct isis_nexthop6 *nexthop6; - - for (ALL_LIST_ELEMENTS_RO (isis->nexthops6, node, nexthop6)) - { - if (nexthop6->ifindex != ifindex) - continue; - if (ip6 && memcmp (&nexthop6->ip6, ip6, sizeof (struct in6_addr)) != 0) - continue; - - nexthop6->lock++; - return nexthop6; - } + struct listnode *node; + struct isis_nexthop6 *nexthop6; + + for (ALL_LIST_ELEMENTS_RO(isis->nexthops6, node, nexthop6)) { + if (nexthop6->ifindex != ifindex) + continue; + if (ip6 + && memcmp(&nexthop6->ip6, ip6, sizeof(struct in6_addr)) + != 0) + continue; + + nexthop6->lock++; + return nexthop6; + } - nexthop6 = isis_nexthop6_new (ip6, ifindex); + nexthop6 = isis_nexthop6_new(ip6, ifindex); - return nexthop6; + return nexthop6; } -static void -isis_nexthop6_delete (struct isis_nexthop6 *nexthop6) +static void isis_nexthop6_delete(struct isis_nexthop6 *nexthop6) { - nexthop6->lock--; - if (nexthop6->lock == 0) - { - listnode_delete (isis->nexthops6, nexthop6); - XFREE (MTYPE_ISIS_NEXTHOP6, nexthop6); - } + nexthop6->lock--; + if (nexthop6->lock == 0) { + listnode_delete(isis->nexthops6, nexthop6); + XFREE(MTYPE_ISIS_NEXTHOP6, nexthop6); + } - return; + return; } -static int -nexthop6lookup (struct list *nexthops6, struct in6_addr *ip6, - ifindex_t ifindex) +static int nexthop6lookup(struct list *nexthops6, struct in6_addr *ip6, + ifindex_t ifindex) { - struct listnode *node; - struct isis_nexthop6 *nh6; + struct listnode *node; + struct isis_nexthop6 *nh6; - for (ALL_LIST_ELEMENTS_RO (nexthops6, node, nh6)) - { - if (!(memcmp (ip6, &nh6->ip6, sizeof (struct in6_addr))) && - ifindex == nh6->ifindex) - return 1; - } + for (ALL_LIST_ELEMENTS_RO(nexthops6, node, nh6)) { + if (!(memcmp(ip6, &nh6->ip6, sizeof(struct in6_addr))) + && ifindex == nh6->ifindex) + return 1; + } - return 0; + return 0; } #ifdef EXTREME_DEBUG -static void -nexthop6_print (struct isis_nexthop6 *nh6) +static void nexthop6_print(struct isis_nexthop6 *nh6) { - u_char buf[BUFSIZ]; + u_char buf[BUFSIZ]; - inet_ntop (AF_INET6, &nh6->ip6, (char *) buf, BUFSIZ); + inet_ntop(AF_INET6, &nh6->ip6, (char *)buf, BUFSIZ); - zlog_debug (" %s %u", buf, nh6->ifindex); + zlog_debug(" %s %u", buf, nh6->ifindex); } -static void -nexthops6_print (struct list *nhs6) +static void nexthops6_print(struct list *nhs6) { - struct listnode *node; - struct isis_nexthop6 *nh6; + struct listnode *node; + struct isis_nexthop6 *nh6; - for (ALL_LIST_ELEMENTS_RO (nhs6, node, nh6)) - nexthop6_print (nh6); + for (ALL_LIST_ELEMENTS_RO(nhs6, node, nh6)) + nexthop6_print(nh6); } #endif /* EXTREME_DEBUG */ -static void -adjinfo2nexthop (struct list *nexthops, struct isis_adjacency *adj) +static void adjinfo2nexthop(struct list *nexthops, struct isis_adjacency *adj) { - struct isis_nexthop *nh; - struct listnode *node; - struct in_addr *ipv4_addr; - - if (adj->ipv4_addrs == NULL) - return; - - for (ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ipv4_addr)) - { - if (!nexthoplookup (nexthops, ipv4_addr, - adj->circuit->interface->ifindex)) - { - nh = isis_nexthop_create (ipv4_addr, - adj->circuit->interface->ifindex); - nh->router_address = adj->router_address; - listnode_add (nexthops, nh); + struct isis_nexthop *nh; + struct listnode *node; + struct in_addr *ipv4_addr; + + if (adj->ipv4_addrs == NULL) + return; + + for (ALL_LIST_ELEMENTS_RO(adj->ipv4_addrs, node, ipv4_addr)) { + if (!nexthoplookup(nexthops, ipv4_addr, + adj->circuit->interface->ifindex)) { + nh = isis_nexthop_create( + ipv4_addr, adj->circuit->interface->ifindex); + nh->router_address = adj->router_address; + listnode_add(nexthops, nh); + } } - } } -static void -adjinfo2nexthop6 (struct list *nexthops6, struct isis_adjacency *adj) +static void adjinfo2nexthop6(struct list *nexthops6, struct isis_adjacency *adj) { - struct listnode *node; - struct in6_addr *ipv6_addr; - struct isis_nexthop6 *nh6; - - if (!adj->ipv6_addrs) - return; - - for (ALL_LIST_ELEMENTS_RO (adj->ipv6_addrs, node, ipv6_addr)) - { - if (!nexthop6lookup (nexthops6, ipv6_addr, - adj->circuit->interface->ifindex)) - { - nh6 = isis_nexthop6_create (ipv6_addr, - adj->circuit->interface->ifindex); - nh6->router_address6 = adj->router_address6; - listnode_add (nexthops6, nh6); + struct listnode *node; + struct in6_addr *ipv6_addr; + struct isis_nexthop6 *nh6; + + if (!adj->ipv6_addrs) + return; + + for (ALL_LIST_ELEMENTS_RO(adj->ipv6_addrs, node, ipv6_addr)) { + if (!nexthop6lookup(nexthops6, ipv6_addr, + adj->circuit->interface->ifindex)) { + nh6 = isis_nexthop6_create( + ipv6_addr, adj->circuit->interface->ifindex); + nh6->router_address6 = adj->router_address6; + listnode_add(nexthops6, nh6); + } } - } } -static struct isis_route_info * -isis_route_info_new (struct prefix *prefix, uint32_t cost, uint32_t depth, - struct list *adjacencies) +static struct isis_route_info *isis_route_info_new(struct prefix *prefix, + uint32_t cost, + uint32_t depth, + struct list *adjacencies) { - struct isis_route_info *rinfo; - struct isis_adjacency *adj; - struct listnode *node; - - rinfo = XCALLOC (MTYPE_ISIS_ROUTE_INFO, sizeof (struct isis_route_info)); - - if (prefix->family == AF_INET) - { - rinfo->nexthops = list_new (); - for (ALL_LIST_ELEMENTS_RO (adjacencies, node, adj)) - { - /* check for force resync this route */ - if (CHECK_FLAG (adj->circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF)) - SET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC); - /* update neighbor router address */ - if (depth == 2 && prefix->prefixlen == 32) - adj->router_address = prefix->u.prefix4; - adjinfo2nexthop (rinfo->nexthops, adj); - } - } - if (prefix->family == AF_INET6) - { - rinfo->nexthops6 = list_new (); - for (ALL_LIST_ELEMENTS_RO (adjacencies, node, adj)) - { - /* check for force resync this route */ - if (CHECK_FLAG (adj->circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF)) - SET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC); - /* update neighbor router address */ - if (depth == 2 && prefix->prefixlen == 128) - adj->router_address6 = prefix->u.prefix6; - adjinfo2nexthop6 (rinfo->nexthops6, adj); - } - } - - rinfo->cost = cost; - rinfo->depth = depth; - - return rinfo; + struct isis_route_info *rinfo; + struct isis_adjacency *adj; + struct listnode *node; + + rinfo = XCALLOC(MTYPE_ISIS_ROUTE_INFO, sizeof(struct isis_route_info)); + + if (prefix->family == AF_INET) { + rinfo->nexthops = list_new(); + for (ALL_LIST_ELEMENTS_RO(adjacencies, node, adj)) { + /* check for force resync this route */ + if (CHECK_FLAG(adj->circuit->flags, + ISIS_CIRCUIT_FLAPPED_AFTER_SPF)) + SET_FLAG(rinfo->flag, + ISIS_ROUTE_FLAG_ZEBRA_RESYNC); + /* update neighbor router address */ + if (depth == 2 && prefix->prefixlen == 32) + adj->router_address = prefix->u.prefix4; + adjinfo2nexthop(rinfo->nexthops, adj); + } + } + if (prefix->family == AF_INET6) { + rinfo->nexthops6 = list_new(); + for (ALL_LIST_ELEMENTS_RO(adjacencies, node, adj)) { + /* check for force resync this route */ + if (CHECK_FLAG(adj->circuit->flags, + ISIS_CIRCUIT_FLAPPED_AFTER_SPF)) + SET_FLAG(rinfo->flag, + ISIS_ROUTE_FLAG_ZEBRA_RESYNC); + /* update neighbor router address */ + if (depth == 2 && prefix->prefixlen == 128) + adj->router_address6 = prefix->u.prefix6; + adjinfo2nexthop6(rinfo->nexthops6, adj); + } + } + + rinfo->cost = cost; + rinfo->depth = depth; + + return rinfo; } -static void -isis_route_info_delete (struct isis_route_info *route_info) +static void isis_route_info_delete(struct isis_route_info *route_info) { - if (route_info->nexthops) - { - route_info->nexthops->del = (void (*)(void *)) isis_nexthop_delete; - list_delete (route_info->nexthops); - } - - if (route_info->nexthops6) - { - route_info->nexthops6->del = (void (*)(void *)) isis_nexthop6_delete; - list_delete (route_info->nexthops6); - } - - XFREE (MTYPE_ISIS_ROUTE_INFO, route_info); + if (route_info->nexthops) { + route_info->nexthops->del = + (void (*)(void *))isis_nexthop_delete; + list_delete(route_info->nexthops); + } + + if (route_info->nexthops6) { + route_info->nexthops6->del = + (void (*)(void *))isis_nexthop6_delete; + list_delete(route_info->nexthops6); + } + + XFREE(MTYPE_ISIS_ROUTE_INFO, route_info); } -static int -isis_route_info_same_attrib (struct isis_route_info *new, - struct isis_route_info *old) +static int isis_route_info_same_attrib(struct isis_route_info *new, + struct isis_route_info *old) { - if (new->cost != old->cost) - return 0; - if (new->depth != old->depth) - return 0; + if (new->cost != old->cost) + return 0; + if (new->depth != old->depth) + return 0; - return 1; + return 1; } -static int -isis_route_info_same (struct isis_route_info *new, - struct isis_route_info *old, u_char family) +static int isis_route_info_same(struct isis_route_info *new, + struct isis_route_info *old, u_char family) { - struct listnode *node; - struct isis_nexthop *nexthop; - struct isis_nexthop6 *nexthop6; - - if (!CHECK_FLAG (old->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) - return 0; - - if (CHECK_FLAG (new->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC)) - return 0; - - if (!isis_route_info_same_attrib (new, old)) - return 0; - - if (family == AF_INET) - { - for (ALL_LIST_ELEMENTS_RO (new->nexthops, node, nexthop)) - if (nexthoplookup (old->nexthops, &nexthop->ip, nexthop->ifindex) - == 0) - return 0; - - for (ALL_LIST_ELEMENTS_RO (old->nexthops, node, nexthop)) - if (nexthoplookup (new->nexthops, &nexthop->ip, nexthop->ifindex) - == 0) - return 0; - } - else if (family == AF_INET6) - { - for (ALL_LIST_ELEMENTS_RO (new->nexthops6, node, nexthop6)) - if (nexthop6lookup (old->nexthops6, &nexthop6->ip6, - nexthop6->ifindex) == 0) - return 0; - - for (ALL_LIST_ELEMENTS_RO (old->nexthops6, node, nexthop6)) - if (nexthop6lookup (new->nexthops6, &nexthop6->ip6, - nexthop6->ifindex) == 0) - return 0; - } - - return 1; + struct listnode *node; + struct isis_nexthop *nexthop; + struct isis_nexthop6 *nexthop6; + + if (!CHECK_FLAG(old->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) + return 0; + + if (CHECK_FLAG(new->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC)) + return 0; + + if (!isis_route_info_same_attrib(new, old)) + return 0; + + if (family == AF_INET) { + for (ALL_LIST_ELEMENTS_RO(new->nexthops, node, nexthop)) + if (nexthoplookup(old->nexthops, &nexthop->ip, + nexthop->ifindex) + == 0) + return 0; + + for (ALL_LIST_ELEMENTS_RO(old->nexthops, node, nexthop)) + if (nexthoplookup(new->nexthops, &nexthop->ip, + nexthop->ifindex) + == 0) + return 0; + } else if (family == AF_INET6) { + for (ALL_LIST_ELEMENTS_RO(new->nexthops6, node, nexthop6)) + if (nexthop6lookup(old->nexthops6, &nexthop6->ip6, + nexthop6->ifindex) + == 0) + return 0; + + for (ALL_LIST_ELEMENTS_RO(old->nexthops6, node, nexthop6)) + if (nexthop6lookup(new->nexthops6, &nexthop6->ip6, + nexthop6->ifindex) + == 0) + return 0; + } + + return 1; } -struct isis_route_info * -isis_route_create (struct prefix *prefix, u_int32_t cost, u_int32_t depth, - struct list *adjacencies, struct isis_area *area, - int level) +struct isis_route_info *isis_route_create(struct prefix *prefix, u_int32_t cost, + u_int32_t depth, + struct list *adjacencies, + struct isis_area *area, int level) { - struct route_node *route_node; - struct isis_route_info *rinfo_new, *rinfo_old, *route_info = NULL; - char buff[PREFIX2STR_BUFFER]; - u_char family; - - family = prefix->family; - /* for debugs */ - prefix2str (prefix, buff, sizeof (buff)); - - rinfo_new = isis_route_info_new (prefix, cost, depth, adjacencies); - - if (family == AF_INET) - route_node = route_node_get (area->route_table[level - 1], prefix); - else if (family == AF_INET6) - route_node = route_node_get (area->route_table6[level - 1], prefix); - else - { - isis_route_info_delete (rinfo_new); - return NULL; - } - - rinfo_old = route_node->info; - if (!rinfo_old) - { - if (isis->debugs & DEBUG_RTE_EVENTS) - zlog_debug ("ISIS-Rte (%s) route created: %s", area->area_tag, buff); - route_info = rinfo_new; - UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); - } - else - { - if (isis->debugs & DEBUG_RTE_EVENTS) - zlog_debug ("ISIS-Rte (%s) route already exists: %s", area->area_tag, - buff); - if (isis_route_info_same (rinfo_new, rinfo_old, family)) - { - if (isis->debugs & DEBUG_RTE_EVENTS) - zlog_debug ("ISIS-Rte (%s) route unchanged: %s", area->area_tag, - buff); - isis_route_info_delete (rinfo_new); - route_info = rinfo_old; - } - else - { - if (isis->debugs & DEBUG_RTE_EVENTS) - zlog_debug ("ISIS-Rte (%s) route changed: %s", area->area_tag, - buff); - isis_route_info_delete (rinfo_old); - route_info = rinfo_new; - UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); - } - } - - SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE); - route_node->info = route_info; - - return route_info; + struct route_node *route_node; + struct isis_route_info *rinfo_new, *rinfo_old, *route_info = NULL; + char buff[PREFIX2STR_BUFFER]; + u_char family; + + family = prefix->family; + /* for debugs */ + prefix2str(prefix, buff, sizeof(buff)); + + rinfo_new = isis_route_info_new(prefix, cost, depth, adjacencies); + + if (family == AF_INET) + route_node = + route_node_get(area->route_table[level - 1], prefix); + else if (family == AF_INET6) + route_node = + route_node_get(area->route_table6[level - 1], prefix); + else { + isis_route_info_delete(rinfo_new); + return NULL; + } + + rinfo_old = route_node->info; + if (!rinfo_old) { + if (isis->debugs & DEBUG_RTE_EVENTS) + zlog_debug("ISIS-Rte (%s) route created: %s", + area->area_tag, buff); + route_info = rinfo_new; + UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); + } else { + if (isis->debugs & DEBUG_RTE_EVENTS) + zlog_debug("ISIS-Rte (%s) route already exists: %s", + area->area_tag, buff); + if (isis_route_info_same(rinfo_new, rinfo_old, family)) { + if (isis->debugs & DEBUG_RTE_EVENTS) + zlog_debug("ISIS-Rte (%s) route unchanged: %s", + area->area_tag, buff); + isis_route_info_delete(rinfo_new); + route_info = rinfo_old; + } else { + if (isis->debugs & DEBUG_RTE_EVENTS) + zlog_debug("ISIS-Rte (%s) route changed: %s", + area->area_tag, buff); + isis_route_info_delete(rinfo_old); + route_info = rinfo_new; + UNSET_FLAG(route_info->flag, + ISIS_ROUTE_FLAG_ZEBRA_SYNCED); + } + } + + SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE); + route_node->info = route_info; + + return route_info; } -static void -isis_route_delete (struct prefix *prefix, struct route_table *table) +static void isis_route_delete(struct prefix *prefix, struct route_table *table) { - struct route_node *rode; - struct isis_route_info *rinfo; - char buff[PREFIX2STR_BUFFER]; - - /* for log */ - prefix2str (prefix, buff, sizeof (buff)); - - - rode = route_node_get (table, prefix); - rinfo = rode->info; - - if (rinfo == NULL) - { - if (isis->debugs & DEBUG_RTE_EVENTS) - zlog_debug ("ISIS-Rte: tried to delete non-existant route %s", buff); - return; - } - - if (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) - { - UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE); - if (isis->debugs & DEBUG_RTE_EVENTS) - zlog_debug ("ISIS-Rte: route delete %s", buff); - isis_zebra_route_update (prefix, rinfo); - } - isis_route_info_delete (rinfo); - rode->info = NULL; - - return; + struct route_node *rode; + struct isis_route_info *rinfo; + char buff[PREFIX2STR_BUFFER]; + + /* for log */ + prefix2str(prefix, buff, sizeof(buff)); + + + rode = route_node_get(table, prefix); + rinfo = rode->info; + + if (rinfo == NULL) { + if (isis->debugs & DEBUG_RTE_EVENTS) + zlog_debug( + "ISIS-Rte: tried to delete non-existant route %s", + buff); + return; + } + + if (CHECK_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) { + UNSET_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE); + if (isis->debugs & DEBUG_RTE_EVENTS) + zlog_debug("ISIS-Rte: route delete %s", buff); + isis_zebra_route_update(prefix, rinfo); + } + isis_route_info_delete(rinfo); + rode->info = NULL; + + return; } /* Validating routes in particular table. */ -static void -isis_route_validate_table (struct isis_area *area, struct route_table *table) +static void isis_route_validate_table(struct isis_area *area, + struct route_table *table) { - struct route_node *rnode, *drnode; - struct isis_route_info *rinfo; - char buff[PREFIX2STR_BUFFER]; - - for (rnode = route_top (table); rnode; rnode = route_next (rnode)) - { - if (rnode->info == NULL) - continue; - rinfo = rnode->info; - - if (isis->debugs & DEBUG_RTE_EVENTS) - { - prefix2str (&rnode->p, buff, sizeof (buff)); - zlog_debug ("ISIS-Rte (%s): route validate: %s %s %s %s", - area->area_tag, - (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED) ? - "synced" : "not-synced"), - (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC) ? - "resync" : "not-resync"), - (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE) ? - "active" : "inactive"), buff); + struct route_node *rnode, *drnode; + struct isis_route_info *rinfo; + char buff[PREFIX2STR_BUFFER]; + + for (rnode = route_top(table); rnode; rnode = route_next(rnode)) { + if (rnode->info == NULL) + continue; + rinfo = rnode->info; + + if (isis->debugs & DEBUG_RTE_EVENTS) { + prefix2str(&rnode->p, buff, sizeof(buff)); + zlog_debug( + "ISIS-Rte (%s): route validate: %s %s %s %s", + area->area_tag, + (CHECK_FLAG(rinfo->flag, + ISIS_ROUTE_FLAG_ZEBRA_SYNCED) + ? "synced" + : "not-synced"), + (CHECK_FLAG(rinfo->flag, + ISIS_ROUTE_FLAG_ZEBRA_RESYNC) + ? "resync" + : "not-resync"), + (CHECK_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE) + ? "active" + : "inactive"), + buff); + } + + isis_zebra_route_update(&rnode->p, rinfo); + if (!CHECK_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE)) { + /* Area is either L1 or L2 => we use level route tables + * directly for + * validating => no problems with deleting routes. */ + if (area->is_type != IS_LEVEL_1_AND_2) { + isis_route_delete(&rnode->p, table); + continue; + } + /* If area is L1L2, we work with merge table and + * therefore must + * delete node from level tables as well before deleting + * route info. + * FIXME: Is it performance problem? There has to be the + * better way. + * Like not to deal with it here at all (see the next + * comment)? */ + if (rnode->p.family == AF_INET) { + drnode = route_node_get(area->route_table[0], + &rnode->p); + if (drnode->info == rnode->info) + drnode->info = NULL; + drnode = route_node_get(area->route_table[1], + &rnode->p); + if (drnode->info == rnode->info) + drnode->info = NULL; + } + + if (rnode->p.family == AF_INET6) { + drnode = route_node_get(area->route_table6[0], + &rnode->p); + if (drnode->info == rnode->info) + drnode->info = NULL; + drnode = route_node_get(area->route_table6[1], + &rnode->p); + if (drnode->info == rnode->info) + drnode->info = NULL; + } + + isis_route_delete(&rnode->p, table); + } } - - isis_zebra_route_update (&rnode->p, rinfo); - if (!CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE)) - { - /* Area is either L1 or L2 => we use level route tables directly for - * validating => no problems with deleting routes. */ - if (area->is_type != IS_LEVEL_1_AND_2) - { - isis_route_delete (&rnode->p, table); - continue; - } - /* If area is L1L2, we work with merge table and therefore must - * delete node from level tables as well before deleting route info. - * FIXME: Is it performance problem? There has to be the better way. - * Like not to deal with it here at all (see the next comment)? */ - if (rnode->p.family == AF_INET) - { - drnode = route_node_get (area->route_table[0], &rnode->p); - if (drnode->info == rnode->info) - drnode->info = NULL; - drnode = route_node_get (area->route_table[1], &rnode->p); - if (drnode->info == rnode->info) - drnode->info = NULL; - } - - if (rnode->p.family == AF_INET6) - { - drnode = route_node_get (area->route_table6[0], &rnode->p); - if (drnode->info == rnode->info) - drnode->info = NULL; - drnode = route_node_get (area->route_table6[1], &rnode->p); - if (drnode->info == rnode->info) - drnode->info = NULL; - } - - isis_route_delete (&rnode->p, table); - } - } } /* Function to validate route tables for L1L2 areas. In this case we can't use @@ -557,106 +544,99 @@ isis_route_validate_table (struct isis_area *area, struct route_table *table) * * FIXME: Is it right place to do it at all? Maybe we should push both levels * to the RIB with different zebra route types and let RIB handle this? */ -static void -isis_route_validate_merge (struct isis_area *area, int family) +static void isis_route_validate_merge(struct isis_area *area, int family) { - struct route_table *table = NULL; - struct route_table *merge; - struct route_node *rnode, *mrnode; - - merge = route_table_init (); - - if (family == AF_INET) - table = area->route_table[0]; - else if (family == AF_INET6) - table = area->route_table6[0]; - else - { - zlog_warn ("ISIS-Rte (%s) %s called for unknown family %d", - area->area_tag, __func__, family); - route_table_finish(merge); - return; - } - - for (rnode = route_top (table); rnode; rnode = route_next (rnode)) - { - if (rnode->info == NULL) - continue; - mrnode = route_node_get (merge, &rnode->p); - mrnode->info = rnode->info; - } - - if (family == AF_INET) - table = area->route_table[1]; - else if (family == AF_INET6) - table = area->route_table6[1]; - - for (rnode = route_top (table); rnode; rnode = route_next (rnode)) - { - if (rnode->info == NULL) - continue; - mrnode = route_node_get (merge, &rnode->p); - if (mrnode->info != NULL) - continue; - mrnode->info = rnode->info; - } - - isis_route_validate_table (area, merge); - route_table_finish (merge); + struct route_table *table = NULL; + struct route_table *merge; + struct route_node *rnode, *mrnode; + + merge = route_table_init(); + + if (family == AF_INET) + table = area->route_table[0]; + else if (family == AF_INET6) + table = area->route_table6[0]; + else { + zlog_warn("ISIS-Rte (%s) %s called for unknown family %d", + area->area_tag, __func__, family); + route_table_finish(merge); + return; + } + + for (rnode = route_top(table); rnode; rnode = route_next(rnode)) { + if (rnode->info == NULL) + continue; + mrnode = route_node_get(merge, &rnode->p); + mrnode->info = rnode->info; + } + + if (family == AF_INET) + table = area->route_table[1]; + else if (family == AF_INET6) + table = area->route_table6[1]; + + for (rnode = route_top(table); rnode; rnode = route_next(rnode)) { + if (rnode->info == NULL) + continue; + mrnode = route_node_get(merge, &rnode->p); + if (mrnode->info != NULL) + continue; + mrnode->info = rnode->info; + } + + isis_route_validate_table(area, merge); + route_table_finish(merge); } /* Walk through route tables and propagate necessary changes into RIB. In case * of L1L2 area, level tables have to be merged at first. */ -void -isis_route_validate (struct isis_area *area) +void isis_route_validate(struct isis_area *area) { - struct listnode *node; - struct isis_circuit *circuit; - - if (area->is_type == IS_LEVEL_1) - isis_route_validate_table (area, area->route_table[0]); - else if (area->is_type == IS_LEVEL_2) - isis_route_validate_table (area, area->route_table[1]); - else - isis_route_validate_merge (area, AF_INET); - - if (area->is_type == IS_LEVEL_1) - isis_route_validate_table (area, area->route_table6[0]); - else if (area->is_type == IS_LEVEL_2) - isis_route_validate_table (area, area->route_table6[1]); - else - isis_route_validate_merge (area, AF_INET6); - - if (!area->circuit_list) { - return; - } - /* walk all circuits and reset any spf specific flags */ - for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit)) - UNSET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF); - - return; + struct listnode *node; + struct isis_circuit *circuit; + + if (area->is_type == IS_LEVEL_1) + isis_route_validate_table(area, area->route_table[0]); + else if (area->is_type == IS_LEVEL_2) + isis_route_validate_table(area, area->route_table[1]); + else + isis_route_validate_merge(area, AF_INET); + + if (area->is_type == IS_LEVEL_1) + isis_route_validate_table(area, area->route_table6[0]); + else if (area->is_type == IS_LEVEL_2) + isis_route_validate_table(area, area->route_table6[1]); + else + isis_route_validate_merge(area, AF_INET6); + + if (!area->circuit_list) { + return; + } + /* walk all circuits and reset any spf specific flags */ + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) + UNSET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF); + + return; } -void -isis_route_invalidate_table (struct isis_area *area, struct route_table *table) +void isis_route_invalidate_table(struct isis_area *area, + struct route_table *table) { - struct route_node *rode; - struct isis_route_info *rinfo; - for (rode = route_top (table); rode; rode = route_next (rode)) - { - if (rode->info == NULL) - continue; - rinfo = rode->info; - - UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE); - } + struct route_node *rode; + struct isis_route_info *rinfo; + for (rode = route_top(table); rode; rode = route_next(rode)) { + if (rode->info == NULL) + continue; + rinfo = rode->info; + + UNSET_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE); + } } -void -isis_route_invalidate (struct isis_area *area) +void isis_route_invalidate(struct isis_area *area) { - if (area->is_type & IS_LEVEL_1) - isis_route_invalidate_table (area, area->route_table[0]); - if (area->is_type & IS_LEVEL_2) - isis_route_invalidate_table (area, area->route_table[1]); + if (area->is_type & IS_LEVEL_1) + isis_route_invalidate_table(area, area->route_table[0]); + if (area->is_type & IS_LEVEL_2) + isis_route_invalidate_table(area, area->route_table[1]); } diff --git a/isisd/isis_route.h b/isisd/isis_route.h index 24bd786fa..6c7d9aea9 100644 --- a/isisd/isis_route.h +++ b/isisd/isis_route.h @@ -2,20 +2,20 @@ * IS-IS Rout(e)ing protocol - isis_route.h * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * * based on ../ospf6d/ospf6_route.[ch] * by Yasuhiro Ohara * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -25,42 +25,39 @@ #ifndef _ZEBRA_ISIS_ROUTE_H #define _ZEBRA_ISIS_ROUTE_H -struct isis_nexthop6 -{ - ifindex_t ifindex; - struct in6_addr ip6; - struct in6_addr router_address6; - unsigned int lock; +struct isis_nexthop6 { + ifindex_t ifindex; + struct in6_addr ip6; + struct in6_addr router_address6; + unsigned int lock; }; -struct isis_nexthop -{ - ifindex_t ifindex; - struct in_addr ip; - struct in_addr router_address; - unsigned int lock; +struct isis_nexthop { + ifindex_t ifindex; + struct in_addr ip; + struct in_addr router_address; + unsigned int lock; }; -struct isis_route_info -{ +struct isis_route_info { #define ISIS_ROUTE_FLAG_ACTIVE 0x01 /* active route for the prefix */ #define ISIS_ROUTE_FLAG_ZEBRA_SYNCED 0x02 /* set when route synced to zebra */ #define ISIS_ROUTE_FLAG_ZEBRA_RESYNC 0x04 /* set when route needs to sync */ - u_char flag; - u_int32_t cost; - u_int32_t depth; - struct list *nexthops; - struct list *nexthops6; + u_char flag; + u_int32_t cost; + u_int32_t depth; + struct list *nexthops; + struct list *nexthops6; }; -struct isis_route_info *isis_route_create (struct prefix *prefix, - u_int32_t cost, u_int32_t depth, - struct list *adjacencies, - struct isis_area *area, int level); +struct isis_route_info *isis_route_create(struct prefix *prefix, u_int32_t cost, + u_int32_t depth, + struct list *adjacencies, + struct isis_area *area, int level); -void isis_route_validate (struct isis_area *area); -void isis_route_invalidate_table (struct isis_area *area, - struct route_table *table); -void isis_route_invalidate (struct isis_area *area); +void isis_route_validate(struct isis_area *area); +void isis_route_invalidate_table(struct isis_area *area, + struct route_table *table); +void isis_route_invalidate(struct isis_area *area); #endif /* _ZEBRA_ISIS_ROUTE_H */ diff --git a/isisd/isis_routemap.c b/isisd/isis_routemap.c index cf4562dbc..44d7fa040 100644 --- a/isisd/isis_routemap.c +++ b/isisd/isis_routemap.c @@ -3,14 +3,14 @@ * * Copyright (C) 2013-2015 Christian Franke * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -50,229 +50,201 @@ #include "isis_zebra.h" #include "isis_routemap.h" -static route_map_result_t -route_match_ip_address(void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_ip_address(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct access_list *alist; + struct access_list *alist; - if (type != RMAP_ISIS) - return RMAP_NOMATCH; + if (type != RMAP_ISIS) + return RMAP_NOMATCH; - alist = access_list_lookup(AFI_IP, (char*)rule); - if (access_list_apply(alist, prefix) != FILTER_DENY) - return RMAP_MATCH; + alist = access_list_lookup(AFI_IP, (char *)rule); + if (access_list_apply(alist, prefix) != FILTER_DENY) + return RMAP_MATCH; - return RMAP_NOMATCH; + return RMAP_NOMATCH; } -static void * -route_match_ip_address_compile(const char *arg) +static void *route_match_ip_address_compile(const char *arg) { - return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ip_address_free(void *rule) +static void route_match_ip_address_free(void *rule) { - XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -static struct route_map_rule_cmd route_match_ip_address_cmd = -{ - "ip address", - route_match_ip_address, - route_match_ip_address_compile, - route_match_ip_address_free -}; +static struct route_map_rule_cmd route_match_ip_address_cmd = { + "ip address", route_match_ip_address, route_match_ip_address_compile, + route_match_ip_address_free}; /* ------------------------------------------------------------*/ static route_map_result_t route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, - route_map_object_t type, void *object) + route_map_object_t type, void *object) { - struct prefix_list *plist; + struct prefix_list *plist; - if (type != RMAP_ISIS) - return RMAP_NOMATCH; + if (type != RMAP_ISIS) + return RMAP_NOMATCH; - plist = prefix_list_lookup(AFI_IP, (char*)rule); - if (prefix_list_apply(plist, prefix) != PREFIX_DENY) - return RMAP_MATCH; + plist = prefix_list_lookup(AFI_IP, (char *)rule); + if (prefix_list_apply(plist, prefix) != PREFIX_DENY) + return RMAP_MATCH; - return RMAP_NOMATCH; + return RMAP_NOMATCH; } -static void * -route_match_ip_address_prefix_list_compile(const char *arg) +static void *route_match_ip_address_prefix_list_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ip_address_prefix_list_free (void *rule) +static void route_match_ip_address_prefix_list_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = -{ - "ip address prefix-list", - route_match_ip_address_prefix_list, - route_match_ip_address_prefix_list_compile, - route_match_ip_address_prefix_list_free -}; +struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { + "ip address prefix-list", route_match_ip_address_prefix_list, + route_match_ip_address_prefix_list_compile, + route_match_ip_address_prefix_list_free}; /* ------------------------------------------------------------*/ -static route_map_result_t -route_match_ipv6_address(void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_ipv6_address(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct access_list *alist; + struct access_list *alist; - if (type != RMAP_ISIS) - return RMAP_NOMATCH; + if (type != RMAP_ISIS) + return RMAP_NOMATCH; - alist = access_list_lookup(AFI_IP6, (char*)rule); - if (access_list_apply(alist, prefix) != FILTER_DENY) - return RMAP_MATCH; + alist = access_list_lookup(AFI_IP6, (char *)rule); + if (access_list_apply(alist, prefix) != FILTER_DENY) + return RMAP_MATCH; - return RMAP_NOMATCH; + return RMAP_NOMATCH; } -static void * -route_match_ipv6_address_compile(const char *arg) +static void *route_match_ipv6_address_compile(const char *arg) { - return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ipv6_address_free(void *rule) +static void route_match_ipv6_address_free(void *rule) { - XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -static struct route_map_rule_cmd route_match_ipv6_address_cmd = -{ - "ipv6 address", - route_match_ipv6_address, - route_match_ipv6_address_compile, - route_match_ipv6_address_free -}; +static struct route_map_rule_cmd route_match_ipv6_address_cmd = { + "ipv6 address", route_match_ipv6_address, + route_match_ipv6_address_compile, route_match_ipv6_address_free}; /* ------------------------------------------------------------*/ static route_map_result_t route_match_ipv6_address_prefix_list(void *rule, struct prefix *prefix, - route_map_object_t type, void *object) + route_map_object_t type, void *object) { - struct prefix_list *plist; + struct prefix_list *plist; - if (type != RMAP_ISIS) - return RMAP_NOMATCH; + if (type != RMAP_ISIS) + return RMAP_NOMATCH; - plist = prefix_list_lookup(AFI_IP6, (char*)rule); - if (prefix_list_apply(plist, prefix) != PREFIX_DENY) - return RMAP_MATCH; + plist = prefix_list_lookup(AFI_IP6, (char *)rule); + if (prefix_list_apply(plist, prefix) != PREFIX_DENY) + return RMAP_MATCH; - return RMAP_NOMATCH; + return RMAP_NOMATCH; } -static void * -route_match_ipv6_address_prefix_list_compile(const char *arg) +static void *route_match_ipv6_address_prefix_list_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ipv6_address_prefix_list_free (void *rule) +static void route_match_ipv6_address_prefix_list_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = -{ - "ipv6 address prefix-list", - route_match_ipv6_address_prefix_list, - route_match_ipv6_address_prefix_list_compile, - route_match_ipv6_address_prefix_list_free -}; +struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = { + "ipv6 address prefix-list", route_match_ipv6_address_prefix_list, + route_match_ipv6_address_prefix_list_compile, + route_match_ipv6_address_prefix_list_free}; /* ------------------------------------------------------------*/ -static route_map_result_t -route_set_metric(void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, + route_map_object_t type, + void *object) { - uint32_t *metric; - struct isis_ext_info *info; + uint32_t *metric; + struct isis_ext_info *info; - if (type == RMAP_ISIS) - { - metric = rule; - info = object; + if (type == RMAP_ISIS) { + metric = rule; + info = object; - info->metric = *metric; - } - return RMAP_OKAY; + info->metric = *metric; + } + return RMAP_OKAY; } -static void * -route_set_metric_compile(const char *arg) +static void *route_set_metric_compile(const char *arg) { - unsigned long metric; - char *endp; - uint32_t *ret; + unsigned long metric; + char *endp; + uint32_t *ret; - metric = strtoul(arg, &endp, 10); - if (arg[0] == '\0' || *endp != '\0' || metric > MAX_WIDE_PATH_METRIC) - return NULL; + metric = strtoul(arg, &endp, 10); + if (arg[0] == '\0' || *endp != '\0' || metric > MAX_WIDE_PATH_METRIC) + return NULL; - ret = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(*ret)); - *ret = metric; + ret = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(*ret)); + *ret = metric; - return ret; + return ret; } -static void -route_set_metric_free(void *rule) +static void route_set_metric_free(void *rule) { - XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -static struct route_map_rule_cmd route_set_metric_cmd = -{ - "metric", - route_set_metric, - route_set_metric_compile, - route_set_metric_free -}; - -void -isis_route_map_init(void) +static struct route_map_rule_cmd route_set_metric_cmd = { + "metric", route_set_metric, route_set_metric_compile, + route_set_metric_free}; + +void isis_route_map_init(void) { - route_map_init(); + route_map_init(); - route_map_match_ip_address_hook (generic_match_add); - route_map_no_match_ip_address_hook (generic_match_delete); + route_map_match_ip_address_hook(generic_match_add); + route_map_no_match_ip_address_hook(generic_match_delete); - route_map_match_ip_address_prefix_list_hook (generic_match_add); - route_map_no_match_ip_address_prefix_list_hook (generic_match_delete); + route_map_match_ip_address_prefix_list_hook(generic_match_add); + route_map_no_match_ip_address_prefix_list_hook(generic_match_delete); - route_map_match_ipv6_address_hook (generic_match_add); - route_map_no_match_ipv6_address_hook (generic_match_delete); + route_map_match_ipv6_address_hook(generic_match_add); + route_map_no_match_ipv6_address_hook(generic_match_delete); - route_map_match_ipv6_address_prefix_list_hook (generic_match_add); - route_map_no_match_ipv6_address_prefix_list_hook (generic_match_delete); + route_map_match_ipv6_address_prefix_list_hook(generic_match_add); + route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete); - route_map_set_metric_hook (generic_set_add); - route_map_no_set_metric_hook (generic_set_delete); + route_map_set_metric_hook(generic_set_add); + route_map_no_set_metric_hook(generic_set_delete); - route_map_install_match(&route_match_ip_address_cmd); - route_map_install_match(&route_match_ip_address_prefix_list_cmd); - route_map_install_match(&route_match_ipv6_address_cmd); - route_map_install_match(&route_match_ipv6_address_prefix_list_cmd); - route_map_install_set(&route_set_metric_cmd); + route_map_install_match(&route_match_ip_address_cmd); + route_map_install_match(&route_match_ip_address_prefix_list_cmd); + route_map_install_match(&route_match_ipv6_address_cmd); + route_map_install_match(&route_match_ipv6_address_prefix_list_cmd); + route_map_install_set(&route_set_metric_cmd); } diff --git a/isisd/isis_routemap.h b/isisd/isis_routemap.h index b0ff559ac..f1577666b 100644 --- a/isisd/isis_routemap.h +++ b/isisd/isis_routemap.h @@ -3,14 +3,14 @@ * * Copyright (C) 2013-2015 Christian Franke * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 4b5592c15..615c2eeaa 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -3,18 +3,18 @@ * The SPT algorithm * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * Copyright (C) 2017 Christian Franke * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -56,1319 +56,1311 @@ DEFINE_MTYPE_STATIC(ISISD, ISIS_SPF_RUN, "ISIS SPF Run Info"); struct isis_spf_run { - struct isis_area *area; - int level; + struct isis_area *area; + int level; }; /* 7.2.7 */ -static void -remove_excess_adjs (struct list *adjs) +static void remove_excess_adjs(struct list *adjs) { - struct listnode *node, *excess = NULL; - struct isis_adjacency *adj, *candidate = NULL; - int comp; - - for (ALL_LIST_ELEMENTS_RO (adjs, node, adj)) - { - if (excess == NULL) - excess = node; - candidate = listgetdata (excess); - - if (candidate->sys_type < adj->sys_type) - { - excess = node; - continue; - } - if (candidate->sys_type > adj->sys_type) - continue; + struct listnode *node, *excess = NULL; + struct isis_adjacency *adj, *candidate = NULL; + int comp; + + for (ALL_LIST_ELEMENTS_RO(adjs, node, adj)) { + if (excess == NULL) + excess = node; + candidate = listgetdata(excess); + + if (candidate->sys_type < adj->sys_type) { + excess = node; + continue; + } + if (candidate->sys_type > adj->sys_type) + continue; - comp = memcmp (candidate->sysid, adj->sysid, ISIS_SYS_ID_LEN); - if (comp > 0) - { - excess = node; - continue; - } - if (comp < 0) - continue; + comp = memcmp(candidate->sysid, adj->sysid, ISIS_SYS_ID_LEN); + if (comp > 0) { + excess = node; + continue; + } + if (comp < 0) + continue; - if (candidate->circuit->circuit_id > adj->circuit->circuit_id) - { - excess = node; - continue; - } + if (candidate->circuit->circuit_id > adj->circuit->circuit_id) { + excess = node; + continue; + } - if (candidate->circuit->circuit_id < adj->circuit->circuit_id) - continue; + if (candidate->circuit->circuit_id < adj->circuit->circuit_id) + continue; - comp = memcmp (candidate->snpa, adj->snpa, ETH_ALEN); - if (comp > 0) - { - excess = node; - continue; + comp = memcmp(candidate->snpa, adj->snpa, ETH_ALEN); + if (comp > 0) { + excess = node; + continue; + } } - } - list_delete_node (adjs, excess); + list_delete_node(adjs, excess); - return; + return; } -static const char * -vtype2string (enum vertextype vtype) +static const char *vtype2string(enum vertextype vtype) { - switch (vtype) - { - case VTYPE_PSEUDO_IS: - return "pseudo_IS"; - break; - case VTYPE_PSEUDO_TE_IS: - return "pseudo_TE-IS"; - break; - case VTYPE_NONPSEUDO_IS: - return "IS"; - break; - case VTYPE_NONPSEUDO_TE_IS: - return "TE-IS"; - break; - case VTYPE_ES: - return "ES"; - break; - case VTYPE_IPREACH_INTERNAL: - return "IP internal"; - break; - case VTYPE_IPREACH_EXTERNAL: - return "IP external"; - break; - case VTYPE_IPREACH_TE: - return "IP TE"; - break; - case VTYPE_IP6REACH_INTERNAL: - return "IP6 internal"; - break; - case VTYPE_IP6REACH_EXTERNAL: - return "IP6 external"; - break; - default: - return "UNKNOWN"; - } - return NULL; /* Not reached */ + switch (vtype) { + case VTYPE_PSEUDO_IS: + return "pseudo_IS"; + break; + case VTYPE_PSEUDO_TE_IS: + return "pseudo_TE-IS"; + break; + case VTYPE_NONPSEUDO_IS: + return "IS"; + break; + case VTYPE_NONPSEUDO_TE_IS: + return "TE-IS"; + break; + case VTYPE_ES: + return "ES"; + break; + case VTYPE_IPREACH_INTERNAL: + return "IP internal"; + break; + case VTYPE_IPREACH_EXTERNAL: + return "IP external"; + break; + case VTYPE_IPREACH_TE: + return "IP TE"; + break; + case VTYPE_IP6REACH_INTERNAL: + return "IP6 internal"; + break; + case VTYPE_IP6REACH_EXTERNAL: + return "IP6 external"; + break; + default: + return "UNKNOWN"; + } + return NULL; /* Not reached */ } -static const char * -vid2string (struct isis_vertex *vertex, char * buff, int size) +static const char *vid2string(struct isis_vertex *vertex, char *buff, int size) { - if (VTYPE_IS(vertex->type) || VTYPE_ES(vertex->type)) - { - return print_sys_hostname (vertex->N.id); - } - - if (VTYPE_IP(vertex->type)) - { - prefix2str ((struct prefix *) &vertex->N.prefix, buff, size); - return buff; - } - - return "UNKNOWN"; + if (VTYPE_IS(vertex->type) || VTYPE_ES(vertex->type)) { + return print_sys_hostname(vertex->N.id); + } + + if (VTYPE_IP(vertex->type)) { + prefix2str((struct prefix *)&vertex->N.prefix, buff, size); + return buff; + } + + return "UNKNOWN"; } -static struct isis_vertex * -isis_vertex_new (void *id, enum vertextype vtype) +static struct isis_vertex *isis_vertex_new(void *id, enum vertextype vtype) { - struct isis_vertex *vertex; - - vertex = XCALLOC (MTYPE_ISIS_VERTEX, sizeof (struct isis_vertex)); - - vertex->type = vtype; - - if (VTYPE_IS(vtype) || VTYPE_ES(vtype)) - { - memcpy (vertex->N.id, (u_char *) id, ISIS_SYS_ID_LEN + 1); - } - else if (VTYPE_IP(vtype)) - { - memcpy (&vertex->N.prefix, (struct prefix *) id, sizeof (struct prefix)); - } - else - { - zlog_err ("WTF!"); - } - - vertex->Adj_N = list_new (); - vertex->parents = list_new (); - vertex->children = list_new (); - - return vertex; + struct isis_vertex *vertex; + + vertex = XCALLOC(MTYPE_ISIS_VERTEX, sizeof(struct isis_vertex)); + + vertex->type = vtype; + + if (VTYPE_IS(vtype) || VTYPE_ES(vtype)) { + memcpy(vertex->N.id, (u_char *)id, ISIS_SYS_ID_LEN + 1); + } else if (VTYPE_IP(vtype)) { + memcpy(&vertex->N.prefix, (struct prefix *)id, + sizeof(struct prefix)); + } else { + zlog_err("WTF!"); + } + + vertex->Adj_N = list_new(); + vertex->parents = list_new(); + vertex->children = list_new(); + + return vertex; } -static void -isis_vertex_del (struct isis_vertex *vertex) +static void isis_vertex_del(struct isis_vertex *vertex) { - list_delete (vertex->Adj_N); - vertex->Adj_N = NULL; - list_delete (vertex->parents); - vertex->parents = NULL; - list_delete (vertex->children); - vertex->children = NULL; + list_delete(vertex->Adj_N); + vertex->Adj_N = NULL; + list_delete(vertex->parents); + vertex->parents = NULL; + list_delete(vertex->children); + vertex->children = NULL; - memset(vertex, 0, sizeof(struct isis_vertex)); - XFREE (MTYPE_ISIS_VERTEX, vertex); + memset(vertex, 0, sizeof(struct isis_vertex)); + XFREE(MTYPE_ISIS_VERTEX, vertex); - return; + return; } -static void -isis_vertex_adj_del (struct isis_vertex *vertex, struct isis_adjacency *adj) +static void isis_vertex_adj_del(struct isis_vertex *vertex, + struct isis_adjacency *adj) { - struct listnode *node, *nextnode; - if (!vertex) - return; - for (node = listhead (vertex->Adj_N); node; node = nextnode) - { - nextnode = listnextnode(node); - if (listgetdata(node) == adj) - list_delete_node(vertex->Adj_N, node); - } - return; + struct listnode *node, *nextnode; + if (!vertex) + return; + for (node = listhead(vertex->Adj_N); node; node = nextnode) { + nextnode = listnextnode(node); + if (listgetdata(node) == adj) + list_delete_node(vertex->Adj_N, node); + } + return; } -struct isis_spftree * -isis_spftree_new (struct isis_area *area) +struct isis_spftree *isis_spftree_new(struct isis_area *area) { - struct isis_spftree *tree; - - tree = XCALLOC (MTYPE_ISIS_SPFTREE, sizeof (struct isis_spftree)); - if (tree == NULL) - { - zlog_err ("ISIS-Spf: isis_spftree_new Out of memory!"); - return NULL; - } - - tree->tents = list_new (); - tree->paths = list_new (); - tree->area = area; - tree->last_run_timestamp = 0; - tree->last_run_duration = 0; - tree->runcount = 0; - return tree; + struct isis_spftree *tree; + + tree = XCALLOC(MTYPE_ISIS_SPFTREE, sizeof(struct isis_spftree)); + if (tree == NULL) { + zlog_err("ISIS-Spf: isis_spftree_new Out of memory!"); + return NULL; + } + + tree->tents = list_new(); + tree->paths = list_new(); + tree->area = area; + tree->last_run_timestamp = 0; + tree->last_run_duration = 0; + tree->runcount = 0; + return tree; } -void -isis_spftree_del (struct isis_spftree *spftree) +void isis_spftree_del(struct isis_spftree *spftree) { - spftree->tents->del = (void (*)(void *)) isis_vertex_del; - list_delete (spftree->tents); - spftree->tents = NULL; + spftree->tents->del = (void (*)(void *))isis_vertex_del; + list_delete(spftree->tents); + spftree->tents = NULL; - spftree->paths->del = (void (*)(void *)) isis_vertex_del; - list_delete (spftree->paths); - spftree->paths = NULL; + spftree->paths->del = (void (*)(void *))isis_vertex_del; + list_delete(spftree->paths); + spftree->paths = NULL; - XFREE (MTYPE_ISIS_SPFTREE, spftree); + XFREE(MTYPE_ISIS_SPFTREE, spftree); - return; + return; } -static void -isis_spftree_adj_del (struct isis_spftree *spftree, struct isis_adjacency *adj) +static void isis_spftree_adj_del(struct isis_spftree *spftree, + struct isis_adjacency *adj) { - struct listnode *node; - if (!adj) - return; - for (node = listhead (spftree->tents); node; node = listnextnode (node)) - isis_vertex_adj_del (listgetdata (node), adj); - for (node = listhead (spftree->paths); node; node = listnextnode (node)) - isis_vertex_adj_del (listgetdata (node), adj); - return; + struct listnode *node; + if (!adj) + return; + for (node = listhead(spftree->tents); node; node = listnextnode(node)) + isis_vertex_adj_del(listgetdata(node), adj); + for (node = listhead(spftree->paths); node; node = listnextnode(node)) + isis_vertex_adj_del(listgetdata(node), adj); + return; } -void -spftree_area_init (struct isis_area *area) +void spftree_area_init(struct isis_area *area) { - if (area->is_type & IS_LEVEL_1) - { - if (area->spftree[0] == NULL) - area->spftree[0] = isis_spftree_new (area); - if (area->spftree6[0] == NULL) - area->spftree6[0] = isis_spftree_new (area); - } - - if (area->is_type & IS_LEVEL_2) - { - if (area->spftree[1] == NULL) - area->spftree[1] = isis_spftree_new (area); - if (area->spftree6[1] == NULL) - area->spftree6[1] = isis_spftree_new (area); - } - - return; + if (area->is_type & IS_LEVEL_1) { + if (area->spftree[0] == NULL) + area->spftree[0] = isis_spftree_new(area); + if (area->spftree6[0] == NULL) + area->spftree6[0] = isis_spftree_new(area); + } + + if (area->is_type & IS_LEVEL_2) { + if (area->spftree[1] == NULL) + area->spftree[1] = isis_spftree_new(area); + if (area->spftree6[1] == NULL) + area->spftree6[1] = isis_spftree_new(area); + } + + return; } -void -spftree_area_del (struct isis_area *area) +void spftree_area_del(struct isis_area *area) { - if (area->is_type & IS_LEVEL_1) - { - if (area->spftree[0] != NULL) - { - isis_spftree_del (area->spftree[0]); - area->spftree[0] = NULL; - } - if (area->spftree6[0]) - { - isis_spftree_del (area->spftree6[0]); - area->spftree6[0] = NULL; - } - } - - if (area->is_type & IS_LEVEL_2) - { - if (area->spftree[1] != NULL) - { - isis_spftree_del (area->spftree[1]); - area->spftree[1] = NULL; - } - if (area->spftree6[1] != NULL) - { - isis_spftree_del (area->spftree6[1]); - area->spftree6[1] = NULL; - } - } - - return; + if (area->is_type & IS_LEVEL_1) { + if (area->spftree[0] != NULL) { + isis_spftree_del(area->spftree[0]); + area->spftree[0] = NULL; + } + if (area->spftree6[0]) { + isis_spftree_del(area->spftree6[0]); + area->spftree6[0] = NULL; + } + } + + if (area->is_type & IS_LEVEL_2) { + if (area->spftree[1] != NULL) { + isis_spftree_del(area->spftree[1]); + area->spftree[1] = NULL; + } + if (area->spftree6[1] != NULL) { + isis_spftree_del(area->spftree6[1]); + area->spftree6[1] = NULL; + } + } + + return; } -void -spftree_area_adj_del (struct isis_area *area, struct isis_adjacency *adj) +void spftree_area_adj_del(struct isis_area *area, struct isis_adjacency *adj) { - if (area->is_type & IS_LEVEL_1) - { - if (area->spftree[0] != NULL) - isis_spftree_adj_del (area->spftree[0], adj); - if (area->spftree6[0] != NULL) - isis_spftree_adj_del (area->spftree6[0], adj); - } - - if (area->is_type & IS_LEVEL_2) - { - if (area->spftree[1] != NULL) - isis_spftree_adj_del (area->spftree[1], adj); - if (area->spftree6[1] != NULL) - isis_spftree_adj_del (area->spftree6[1], adj); - } - - return; + if (area->is_type & IS_LEVEL_1) { + if (area->spftree[0] != NULL) + isis_spftree_adj_del(area->spftree[0], adj); + if (area->spftree6[0] != NULL) + isis_spftree_adj_del(area->spftree6[0], adj); + } + + if (area->is_type & IS_LEVEL_2) { + if (area->spftree[1] != NULL) + isis_spftree_adj_del(area->spftree[1], adj); + if (area->spftree6[1] != NULL) + isis_spftree_adj_del(area->spftree6[1], adj); + } + + return; } -/* - * Find the system LSP: returns the LSP in our LSP database +/* + * Find the system LSP: returns the LSP in our LSP database * associated with the given system ID. */ -static struct isis_lsp * -isis_root_system_lsp (struct isis_area *area, int level, u_char *sysid) +static struct isis_lsp *isis_root_system_lsp(struct isis_area *area, int level, + u_char *sysid) { - struct isis_lsp *lsp; - u_char lspid[ISIS_SYS_ID_LEN + 2]; - - memcpy (lspid, sysid, ISIS_SYS_ID_LEN); - LSP_PSEUDO_ID (lspid) = 0; - LSP_FRAGMENT (lspid) = 0; - lsp = lsp_search (lspid, area->lspdb[level - 1]); - if (lsp && lsp->lsp_header->rem_lifetime != 0) - return lsp; - return NULL; + struct isis_lsp *lsp; + u_char lspid[ISIS_SYS_ID_LEN + 2]; + + memcpy(lspid, sysid, ISIS_SYS_ID_LEN); + LSP_PSEUDO_ID(lspid) = 0; + LSP_FRAGMENT(lspid) = 0; + lsp = lsp_search(lspid, area->lspdb[level - 1]); + if (lsp && lsp->lsp_header->rem_lifetime != 0) + return lsp; + return NULL; } /* * Add this IS to the root of SPT */ -static struct isis_vertex * -isis_spf_add_root (struct isis_spftree *spftree, u_char *sysid) +static struct isis_vertex *isis_spf_add_root(struct isis_spftree *spftree, + u_char *sysid) { - struct isis_vertex *vertex; - struct isis_lsp *lsp; + struct isis_vertex *vertex; + struct isis_lsp *lsp; #ifdef EXTREME_DEBUG - char buff[PREFIX2STR_BUFFER]; + char buff[PREFIX2STR_BUFFER]; #endif /* EXTREME_DEBUG */ - u_char id[ISIS_SYS_ID_LEN + 1]; + u_char id[ISIS_SYS_ID_LEN + 1]; - memcpy(id, sysid, ISIS_SYS_ID_LEN); - LSP_PSEUDO_ID(id) = 0; + memcpy(id, sysid, ISIS_SYS_ID_LEN); + LSP_PSEUDO_ID(id) = 0; - lsp = isis_root_system_lsp (spftree->area, spftree->level, sysid); - if (lsp == NULL) - zlog_warn ("ISIS-Spf: could not find own l%d LSP!", spftree->level); + lsp = isis_root_system_lsp(spftree->area, spftree->level, sysid); + if (lsp == NULL) + zlog_warn("ISIS-Spf: could not find own l%d LSP!", + spftree->level); - vertex = isis_vertex_new (id, spftree->area->oldmetric ? VTYPE_NONPSEUDO_IS - : VTYPE_NONPSEUDO_TE_IS); - listnode_add (spftree->paths, vertex); + vertex = isis_vertex_new(id, + spftree->area->oldmetric + ? VTYPE_NONPSEUDO_IS + : VTYPE_NONPSEUDO_TE_IS); + listnode_add(spftree->paths, vertex); #ifdef EXTREME_DEBUG - zlog_debug ("ISIS-Spf: added this IS %s %s depth %d dist %d to PATHS", - vtype2string (vertex->type), vid2string (vertex, buff, sizeof (buff)), - vertex->depth, vertex->d_N); + zlog_debug("ISIS-Spf: added this IS %s %s depth %d dist %d to PATHS", + vtype2string(vertex->type), + vid2string(vertex, buff, sizeof(buff)), vertex->depth, + vertex->d_N); #endif /* EXTREME_DEBUG */ - return vertex; + return vertex; } -static struct isis_vertex * -isis_find_vertex (struct list *list, void *id, enum vertextype vtype) +static struct isis_vertex *isis_find_vertex(struct list *list, void *id, + enum vertextype vtype) { - struct listnode *node; - struct isis_vertex *vertex; - struct prefix *p1, *p2; - - for (ALL_LIST_ELEMENTS_RO (list, node, vertex)) - { - if (vertex->type != vtype) - continue; - if (VTYPE_IS(vertex->type) || VTYPE_ES(vertex->type)) - { - if (memcmp ((u_char *) id, vertex->N.id, ISIS_SYS_ID_LEN + 1) == 0) - return vertex; - } - if (VTYPE_IP(vertex->type)) - { - p1 = (struct prefix *) id; - p2 = (struct prefix *) &vertex->N.id; - if (p1->family == p2->family - && p1->prefixlen == p2->prefixlen - && !memcmp(&p1->u.prefix, &p2->u.prefix, PSIZE (p1->prefixlen))) - { - return vertex; - } - } - } - - return NULL; + struct listnode *node; + struct isis_vertex *vertex; + struct prefix *p1, *p2; + + for (ALL_LIST_ELEMENTS_RO(list, node, vertex)) { + if (vertex->type != vtype) + continue; + if (VTYPE_IS(vertex->type) || VTYPE_ES(vertex->type)) { + if (memcmp((u_char *)id, vertex->N.id, + ISIS_SYS_ID_LEN + 1) + == 0) + return vertex; + } + if (VTYPE_IP(vertex->type)) { + p1 = (struct prefix *)id; + p2 = (struct prefix *)&vertex->N.id; + if (p1->family == p2->family + && p1->prefixlen == p2->prefixlen + && !memcmp(&p1->u.prefix, &p2->u.prefix, + PSIZE(p1->prefixlen))) { + return vertex; + } + } + } + + return NULL; } /* * Compares vertizes for sorting in the TENT list. Returns true * if candidate should be considered before current, false otherwise. */ -static bool -tent_cmp (struct isis_vertex *current, struct isis_vertex *candidate) +static bool tent_cmp(struct isis_vertex *current, struct isis_vertex *candidate) { - if (current->d_N > candidate->d_N) - return true; + if (current->d_N > candidate->d_N) + return true; - if (current->d_N == candidate->d_N - && current->type > candidate->type) - return true; + if (current->d_N == candidate->d_N && current->type > candidate->type) + return true; - return false; + return false; } /* * Add a vertex to TENT sorted by cost and by vertextype on tie break situation */ -static struct isis_vertex * -isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype, - void *id, uint32_t cost, int depth, - struct isis_adjacency *adj, struct isis_vertex *parent) +static struct isis_vertex *isis_spf_add2tent(struct isis_spftree *spftree, + enum vertextype vtype, void *id, + uint32_t cost, int depth, + struct isis_adjacency *adj, + struct isis_vertex *parent) { - struct isis_vertex *vertex, *v; - struct listnode *node; - struct isis_adjacency *parent_adj; + struct isis_vertex *vertex, *v; + struct listnode *node; + struct isis_adjacency *parent_adj; #ifdef EXTREME_DEBUG - char buff[PREFIX2STR_BUFFER]; + char buff[PREFIX2STR_BUFFER]; #endif - assert (isis_find_vertex (spftree->paths, id, vtype) == NULL); - assert (isis_find_vertex (spftree->tents, id, vtype) == NULL); - vertex = isis_vertex_new (id, vtype); - vertex->d_N = cost; - vertex->depth = depth; - - if (parent) { - listnode_add (vertex->parents, parent); - if (listnode_lookup (parent->children, vertex) == NULL) - listnode_add (parent->children, vertex); - } - - if (parent && parent->Adj_N && listcount(parent->Adj_N) > 0) { - for (ALL_LIST_ELEMENTS_RO (parent->Adj_N, node, parent_adj)) - listnode_add (vertex->Adj_N, parent_adj); - } else if (adj) { - listnode_add (vertex->Adj_N, adj); - } + assert(isis_find_vertex(spftree->paths, id, vtype) == NULL); + assert(isis_find_vertex(spftree->tents, id, vtype) == NULL); + vertex = isis_vertex_new(id, vtype); + vertex->d_N = cost; + vertex->depth = depth; + + if (parent) { + listnode_add(vertex->parents, parent); + if (listnode_lookup(parent->children, vertex) == NULL) + listnode_add(parent->children, vertex); + } + + if (parent && parent->Adj_N && listcount(parent->Adj_N) > 0) { + for (ALL_LIST_ELEMENTS_RO(parent->Adj_N, node, parent_adj)) + listnode_add(vertex->Adj_N, parent_adj); + } else if (adj) { + listnode_add(vertex->Adj_N, adj); + } #ifdef EXTREME_DEBUG - zlog_debug ("ISIS-Spf: add to TENT %s %s %s depth %d dist %d adjcount %d", - print_sys_hostname (vertex->N.id), - vtype2string (vertex->type), vid2string (vertex, buff, sizeof (buff)), - vertex->depth, vertex->d_N, listcount(vertex->Adj_N)); + zlog_debug( + "ISIS-Spf: add to TENT %s %s %s depth %d dist %d adjcount %d", + print_sys_hostname(vertex->N.id), vtype2string(vertex->type), + vid2string(vertex, buff, sizeof(buff)), vertex->depth, + vertex->d_N, listcount(vertex->Adj_N)); #endif /* EXTREME_DEBUG */ - if (list_isempty (spftree->tents)) - { - listnode_add (spftree->tents, vertex); - return vertex; - } - - /* XXX: This cant use the standard ALL_LIST_ELEMENTS macro */ - for (node = listhead (spftree->tents); node; node = listnextnode (node)) - { - v = listgetdata (node); - if (tent_cmp(v, vertex)) - { - listnode_add_before (spftree->tents, node, vertex); - break; - } - } - - if (node == NULL) - listnode_add (spftree->tents, vertex); - - return vertex; -} + if (list_isempty(spftree->tents)) { + listnode_add(spftree->tents, vertex); + return vertex; + } -static void -isis_spf_add_local (struct isis_spftree *spftree, enum vertextype vtype, - void *id, struct isis_adjacency *adj, uint32_t cost, - struct isis_vertex *parent) -{ - struct isis_vertex *vertex; + /* XXX: This cant use the standard ALL_LIST_ELEMENTS macro */ + for (node = listhead(spftree->tents); node; node = listnextnode(node)) { + v = listgetdata(node); + if (tent_cmp(v, vertex)) { + listnode_add_before(spftree->tents, node, vertex); + break; + } + } - vertex = isis_find_vertex (spftree->tents, id, vtype); + if (node == NULL) + listnode_add(spftree->tents, vertex); - if (vertex) - { - /* C.2.5 c) */ - if (vertex->d_N == cost) - { - if (adj) - listnode_add (vertex->Adj_N, adj); - /* d) */ - if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS) - remove_excess_adjs (vertex->Adj_N); - if (parent && (listnode_lookup (vertex->parents, parent) == NULL)) - listnode_add (vertex->parents, parent); - if (parent && (listnode_lookup (parent->children, vertex) == NULL)) - listnode_add (parent->children, vertex); - return; - } - else if (vertex->d_N < cost) - { - /* e) do nothing */ - return; + return vertex; +} + +static void isis_spf_add_local(struct isis_spftree *spftree, + enum vertextype vtype, void *id, + struct isis_adjacency *adj, uint32_t cost, + struct isis_vertex *parent) +{ + struct isis_vertex *vertex; + + vertex = isis_find_vertex(spftree->tents, id, vtype); + + if (vertex) { + /* C.2.5 c) */ + if (vertex->d_N == cost) { + if (adj) + listnode_add(vertex->Adj_N, adj); + /* d) */ + if (listcount(vertex->Adj_N) > ISIS_MAX_PATH_SPLITS) + remove_excess_adjs(vertex->Adj_N); + if (parent && (listnode_lookup(vertex->parents, parent) + == NULL)) + listnode_add(vertex->parents, parent); + if (parent && (listnode_lookup(parent->children, vertex) + == NULL)) + listnode_add(parent->children, vertex); + return; + } else if (vertex->d_N < cost) { + /* e) do nothing */ + return; + } else { /* vertex->d_N > cost */ + /* f) */ + struct listnode *pnode, *pnextnode; + struct isis_vertex *pvertex; + listnode_delete(spftree->tents, vertex); + assert(listcount(vertex->children) == 0); + for (ALL_LIST_ELEMENTS(vertex->parents, pnode, + pnextnode, pvertex)) + listnode_delete(pvertex->children, vertex); + isis_vertex_del(vertex); + } } - else { /* vertex->d_N > cost */ - /* f) */ - struct listnode *pnode, *pnextnode; - struct isis_vertex *pvertex; - listnode_delete (spftree->tents, vertex); - assert (listcount (vertex->children) == 0); - for (ALL_LIST_ELEMENTS (vertex->parents, pnode, pnextnode, pvertex)) - listnode_delete(pvertex->children, vertex); - isis_vertex_del (vertex); - } - } - - isis_spf_add2tent (spftree, vtype, id, cost, 1, adj, parent); - return; + + isis_spf_add2tent(spftree, vtype, id, cost, 1, adj, parent); + return; } -static void -process_N (struct isis_spftree *spftree, enum vertextype vtype, void *id, - uint32_t dist, uint16_t depth, - struct isis_vertex *parent) +static void process_N(struct isis_spftree *spftree, enum vertextype vtype, + void *id, uint32_t dist, uint16_t depth, + struct isis_vertex *parent) { - struct isis_vertex *vertex; + struct isis_vertex *vertex; #ifdef EXTREME_DEBUG - char buff[PREFIX2STR_BUFFER]; + char buff[PREFIX2STR_BUFFER]; #endif - assert (spftree && parent); - - /* RFC3787 section 5.1 */ - if (spftree->area->newmetric == 1) - { - if (dist > MAX_WIDE_PATH_METRIC) - return; - } - /* C.2.6 b) */ - else if (spftree->area->oldmetric == 1) - { - if (dist > MAX_NARROW_PATH_METRIC) - return; - } - - /* c) */ - vertex = isis_find_vertex (spftree->paths, id, vtype); - if (vertex) - { + assert(spftree && parent); + + /* RFC3787 section 5.1 */ + if (spftree->area->newmetric == 1) { + if (dist > MAX_WIDE_PATH_METRIC) + return; + } + /* C.2.6 b) */ + else if (spftree->area->oldmetric == 1) { + if (dist > MAX_NARROW_PATH_METRIC) + return; + } + + /* c) */ + vertex = isis_find_vertex(spftree->paths, id, vtype); + if (vertex) { #ifdef EXTREME_DEBUG - zlog_debug ("ISIS-Spf: process_N %s %s %s dist %d already found from PATH", - print_sys_hostname (vertex->N.id), - vtype2string (vtype), vid2string (vertex, buff, sizeof (buff)), dist); + zlog_debug( + "ISIS-Spf: process_N %s %s %s dist %d already found from PATH", + print_sys_hostname(vertex->N.id), vtype2string(vtype), + vid2string(vertex, buff, sizeof(buff)), dist); #endif /* EXTREME_DEBUG */ - assert (dist >= vertex->d_N); - return; - } - - vertex = isis_find_vertex (spftree->tents, id, vtype); - /* d) */ - if (vertex) - { - /* 1) */ + assert(dist >= vertex->d_N); + return; + } + + vertex = isis_find_vertex(spftree->tents, id, vtype); + /* d) */ + if (vertex) { +/* 1) */ #ifdef EXTREME_DEBUG - zlog_debug ("ISIS-Spf: process_N %s %s %s dist %d parent %s adjcount %d", - print_sys_hostname (vertex->N.id), - vtype2string (vtype), vid2string (vertex, buff, sizeof (buff)), dist, - (parent ? print_sys_hostname (parent->N.id) : "null"), - (parent ? listcount (parent->Adj_N) : 0)); + zlog_debug( + "ISIS-Spf: process_N %s %s %s dist %d parent %s adjcount %d", + print_sys_hostname(vertex->N.id), vtype2string(vtype), + vid2string(vertex, buff, sizeof(buff)), dist, + (parent ? print_sys_hostname(parent->N.id) : "null"), + (parent ? listcount(parent->Adj_N) : 0)); #endif /* EXTREME_DEBUG */ - if (vertex->d_N == dist) - { - struct listnode *node; - struct isis_adjacency *parent_adj; - for (ALL_LIST_ELEMENTS_RO (parent->Adj_N, node, parent_adj)) - if (listnode_lookup(vertex->Adj_N, parent_adj) == NULL) - listnode_add (vertex->Adj_N, parent_adj); - /* 2) */ - if (listcount (vertex->Adj_N) > ISIS_MAX_PATH_SPLITS) - remove_excess_adjs (vertex->Adj_N); - if (listnode_lookup (vertex->parents, parent) == NULL) - listnode_add (vertex->parents, parent); - if (listnode_lookup (parent->children, vertex) == NULL) - listnode_add (parent->children, vertex); - /* 3) */ - return; - } - else if (vertex->d_N < dist) - { - return; - /* 4) */ - } - else - { - struct listnode *pnode, *pnextnode; - struct isis_vertex *pvertex; - listnode_delete (spftree->tents, vertex); - assert (listcount (vertex->children) == 0); - for (ALL_LIST_ELEMENTS (vertex->parents, pnode, pnextnode, pvertex)) - listnode_delete(pvertex->children, vertex); - isis_vertex_del (vertex); + if (vertex->d_N == dist) { + struct listnode *node; + struct isis_adjacency *parent_adj; + for (ALL_LIST_ELEMENTS_RO(parent->Adj_N, node, + parent_adj)) + if (listnode_lookup(vertex->Adj_N, parent_adj) + == NULL) + listnode_add(vertex->Adj_N, parent_adj); + /* 2) */ + if (listcount(vertex->Adj_N) > ISIS_MAX_PATH_SPLITS) + remove_excess_adjs(vertex->Adj_N); + if (listnode_lookup(vertex->parents, parent) == NULL) + listnode_add(vertex->parents, parent); + if (listnode_lookup(parent->children, vertex) == NULL) + listnode_add(parent->children, vertex); + /* 3) */ + return; + } else if (vertex->d_N < dist) { + return; + /* 4) */ + } else { + struct listnode *pnode, *pnextnode; + struct isis_vertex *pvertex; + listnode_delete(spftree->tents, vertex); + assert(listcount(vertex->children) == 0); + for (ALL_LIST_ELEMENTS(vertex->parents, pnode, + pnextnode, pvertex)) + listnode_delete(pvertex->children, vertex); + isis_vertex_del(vertex); + } } - } #ifdef EXTREME_DEBUG - zlog_debug ("ISIS-Spf: process_N add2tent %s %s dist %d parent %s", - print_sys_hostname(id), vtype2string (vtype), dist, - (parent ? print_sys_hostname (parent->N.id) : "null")); + zlog_debug("ISIS-Spf: process_N add2tent %s %s dist %d parent %s", + print_sys_hostname(id), vtype2string(vtype), dist, + (parent ? print_sys_hostname(parent->N.id) : "null")); #endif /* EXTREME_DEBUG */ - isis_spf_add2tent (spftree, vtype, id, dist, depth, NULL, parent); - return; + isis_spf_add2tent(spftree, vtype, id, dist, depth, NULL, parent); + return; } /* * C.2.6 Step 1 */ -static int -isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp, - uint32_t cost, uint16_t depth, - u_char *root_sysid, struct isis_vertex *parent) +static int isis_spf_process_lsp(struct isis_spftree *spftree, + struct isis_lsp *lsp, uint32_t cost, + uint16_t depth, u_char *root_sysid, + struct isis_vertex *parent) { - bool pseudo_lsp = LSP_PSEUDO_ID(lsp->lsp_header->lsp_id); - struct listnode *node, *fragnode = NULL; - uint32_t dist; - struct is_neigh *is_neigh; - struct te_is_neigh *te_is_neigh; - struct ipv4_reachability *ipreach; - struct te_ipv4_reachability *te_ipv4_reach; - enum vertextype vtype; - struct prefix prefix; - struct ipv6_reachability *ip6reach; - static const u_char null_sysid[ISIS_SYS_ID_LEN]; - struct mt_router_info *mt_router_info = NULL; - - if (spftree->mtid != ISIS_MT_IPV4_UNICAST) - mt_router_info = tlvs_lookup_mt_router_info(&lsp->tlv_data, spftree->mtid); - - if (!pseudo_lsp - && (spftree->mtid == ISIS_MT_IPV4_UNICAST && !speaks(lsp->tlv_data.nlpids, spftree->family)) - && !mt_router_info) - return ISIS_OK; + bool pseudo_lsp = LSP_PSEUDO_ID(lsp->lsp_header->lsp_id); + struct listnode *node, *fragnode = NULL; + uint32_t dist; + struct is_neigh *is_neigh; + struct te_is_neigh *te_is_neigh; + struct ipv4_reachability *ipreach; + struct te_ipv4_reachability *te_ipv4_reach; + enum vertextype vtype; + struct prefix prefix; + struct ipv6_reachability *ip6reach; + static const u_char null_sysid[ISIS_SYS_ID_LEN]; + struct mt_router_info *mt_router_info = NULL; + + if (spftree->mtid != ISIS_MT_IPV4_UNICAST) + mt_router_info = tlvs_lookup_mt_router_info(&lsp->tlv_data, + spftree->mtid); + + if (!pseudo_lsp && (spftree->mtid == ISIS_MT_IPV4_UNICAST + && !speaks(lsp->tlv_data.nlpids, spftree->family)) + && !mt_router_info) + return ISIS_OK; lspfragloop: - if (lsp->lsp_header->seq_num == 0) - { - zlog_warn ("isis_spf_process_lsp(): lsp with 0 seq_num - ignore"); - return ISIS_WARNING; - } + if (lsp->lsp_header->seq_num == 0) { + zlog_warn( + "isis_spf_process_lsp(): lsp with 0 seq_num - ignore"); + return ISIS_WARNING; + } #ifdef EXTREME_DEBUG - zlog_debug ("ISIS-Spf: process_lsp %s", print_sys_hostname(lsp->lsp_header->lsp_id)); + zlog_debug("ISIS-Spf: process_lsp %s", + print_sys_hostname(lsp->lsp_header->lsp_id)); #endif /* EXTREME_DEBUG */ - /* RFC3787 section 4 SHOULD ignore overload bit in pseudo LSPs */ - if (pseudo_lsp - || (spftree->mtid == ISIS_MT_IPV4_UNICAST && !ISIS_MASK_LSP_OL_BIT (lsp->lsp_header->lsp_bits)) - || (mt_router_info && !mt_router_info->overload)) - - { - if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST) - { - for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh)) - { - /* C.2.6 a) */ - /* Two way connectivity */ - if (!memcmp (is_neigh->neigh_id, root_sysid, ISIS_SYS_ID_LEN)) - continue; - if (!pseudo_lsp && !memcmp (is_neigh->neigh_id, null_sysid, ISIS_SYS_ID_LEN)) - continue; - dist = cost + is_neigh->metrics.metric_default; - process_N (spftree, LSP_PSEUDO_ID(is_neigh->neigh_id) ? VTYPE_PSEUDO_IS - : VTYPE_NONPSEUDO_IS, - (void *) is_neigh->neigh_id, dist, depth + 1, parent); - } - } - - struct list *te_is_neighs = NULL; - if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST) - { - te_is_neighs = lsp->tlv_data.te_is_neighs; - } - else - { - struct tlv_mt_neighbors *mt_neighbors; - mt_neighbors = tlvs_lookup_mt_neighbors(&lsp->tlv_data, spftree->mtid); - if (mt_neighbors) - te_is_neighs = mt_neighbors->list; - } - for (ALL_LIST_ELEMENTS_RO (te_is_neighs, node, te_is_neigh)) - { - if (!memcmp (te_is_neigh->neigh_id, root_sysid, ISIS_SYS_ID_LEN)) - continue; - if (!pseudo_lsp && !memcmp (te_is_neigh->neigh_id, null_sysid, ISIS_SYS_ID_LEN)) - continue; - dist = cost + GET_TE_METRIC(te_is_neigh); - process_N (spftree, LSP_PSEUDO_ID(te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS - : VTYPE_NONPSEUDO_TE_IS, - (void *) te_is_neigh->neigh_id, dist, depth + 1, parent); - } - } - - if (!pseudo_lsp - && spftree->family == AF_INET - && spftree->mtid == ISIS_MT_IPV4_UNICAST) - { - struct list *reachs[] = {lsp->tlv_data.ipv4_int_reachs, - lsp->tlv_data.ipv4_ext_reachs}; - - prefix.family = AF_INET; - for (unsigned int i = 0; i < array_size(reachs); i++) - { - vtype = (reachs[i] == lsp->tlv_data.ipv4_int_reachs) ? VTYPE_IPREACH_INTERNAL - : VTYPE_IPREACH_EXTERNAL; - for (ALL_LIST_ELEMENTS_RO (reachs[i], node, ipreach)) - { - dist = cost + ipreach->metrics.metric_default; - prefix.u.prefix4 = ipreach->prefix; - prefix.prefixlen = ip_masklen (ipreach->mask); - apply_mask (&prefix); - process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, - parent); - } - } - } - - if (!pseudo_lsp && spftree->family == AF_INET) - { - struct list *ipv4reachs = NULL; - - if (spftree->mtid == ISIS_MT_IPV4_UNICAST) - { - ipv4reachs = lsp->tlv_data.te_ipv4_reachs; - } - else - { - struct tlv_mt_ipv4_reachs *mt_reachs; - mt_reachs = tlvs_lookup_mt_ipv4_reachs(&lsp->tlv_data, spftree->mtid); - if (mt_reachs) - ipv4reachs = mt_reachs->list; - } - - prefix.family = AF_INET; - for (ALL_LIST_ELEMENTS_RO (ipv4reachs, node, te_ipv4_reach)) - { - assert ((te_ipv4_reach->control & 0x3F) <= IPV4_MAX_BITLEN); - - dist = cost + ntohl (te_ipv4_reach->te_metric); - prefix.u.prefix4 = newprefix2inaddr (&te_ipv4_reach->prefix_start, - te_ipv4_reach->control); - prefix.prefixlen = (te_ipv4_reach->control & 0x3F); - apply_mask (&prefix); - process_N (spftree, VTYPE_IPREACH_TE, (void *) &prefix, dist, depth + 1, - parent); - } - } - - if (!pseudo_lsp - && spftree->family == AF_INET6) - { - struct list *ipv6reachs = NULL; - - if (spftree->mtid == ISIS_MT_IPV4_UNICAST) - { - ipv6reachs = lsp->tlv_data.ipv6_reachs; - } - else - { - struct tlv_mt_ipv6_reachs *mt_reachs; - mt_reachs = tlvs_lookup_mt_ipv6_reachs(&lsp->tlv_data, spftree->mtid); - if (mt_reachs) - ipv6reachs = mt_reachs->list; - } - - prefix.family = AF_INET6; - for (ALL_LIST_ELEMENTS_RO (ipv6reachs, node, ip6reach)) - { - assert (ip6reach->prefix_len <= IPV6_MAX_BITLEN); - - dist = cost + ntohl(ip6reach->metric); - vtype = (ip6reach->control_info & CTRL_INFO_DISTRIBUTION) ? - VTYPE_IP6REACH_EXTERNAL : VTYPE_IP6REACH_INTERNAL; - prefix.prefixlen = ip6reach->prefix_len; - memcpy (&prefix.u.prefix6.s6_addr, ip6reach->prefix, - PSIZE (ip6reach->prefix_len)); - apply_mask (&prefix); - process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, - parent); - } - } - - if (fragnode == NULL) - fragnode = listhead (lsp->lspu.frags); - else - fragnode = listnextnode (fragnode); - - if (fragnode) - { - lsp = listgetdata (fragnode); - goto lspfragloop; - } - - return ISIS_OK; -} + /* RFC3787 section 4 SHOULD ignore overload bit in pseudo LSPs */ + if (pseudo_lsp || (spftree->mtid == ISIS_MT_IPV4_UNICAST + && !ISIS_MASK_LSP_OL_BIT(lsp->lsp_header->lsp_bits)) + || (mt_router_info && !mt_router_info->overload)) -static int -isis_spf_preload_tent (struct isis_spftree *spftree, - u_char *root_sysid, - struct isis_vertex *parent) -{ - struct isis_circuit *circuit; - struct listnode *cnode, *anode, *ipnode; - struct isis_adjacency *adj; - struct isis_lsp *lsp; - struct list *adj_list; - struct list *adjdb; - struct prefix_ipv4 *ipv4; - struct prefix prefix; - int retval = ISIS_OK; - u_char lsp_id[ISIS_SYS_ID_LEN + 2]; - static u_char null_lsp_id[ISIS_SYS_ID_LEN + 2]; - struct prefix_ipv6 *ipv6; - struct isis_circuit_mt_setting *circuit_mt; - - for (ALL_LIST_ELEMENTS_RO (spftree->area->circuit_list, cnode, circuit)) - { - circuit_mt = circuit_lookup_mt_setting(circuit, spftree->mtid); - if (circuit_mt && !circuit_mt->enabled) - continue; - if (circuit->state != C_STATE_UP) - continue; - if (!(circuit->is_type & spftree->level)) - continue; - if (spftree->family == AF_INET && !circuit->ip_router) - continue; - if (spftree->family == AF_INET6 && !circuit->ipv6_router) - continue; - /* - * Add IP(v6) addresses of this circuit - */ - if (spftree->family == AF_INET) { - prefix.family = AF_INET; - for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, ipnode, ipv4)) - { - prefix.u.prefix4 = ipv4->prefix; - prefix.prefixlen = ipv4->prefixlen; - apply_mask (&prefix); - isis_spf_add_local (spftree, VTYPE_IPREACH_INTERNAL, &prefix, - NULL, 0, parent); - } + if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST) { + for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.is_neighs, node, + is_neigh)) { + /* C.2.6 a) */ + /* Two way connectivity */ + if (!memcmp(is_neigh->neigh_id, root_sysid, + ISIS_SYS_ID_LEN)) + continue; + if (!pseudo_lsp + && !memcmp(is_neigh->neigh_id, null_sysid, + ISIS_SYS_ID_LEN)) + continue; + dist = cost + is_neigh->metrics.metric_default; + process_N(spftree, + LSP_PSEUDO_ID(is_neigh->neigh_id) + ? VTYPE_PSEUDO_IS + : VTYPE_NONPSEUDO_IS, + (void *)is_neigh->neigh_id, dist, + depth + 1, parent); + } + } + + struct list *te_is_neighs = NULL; + if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST) { + te_is_neighs = lsp->tlv_data.te_is_neighs; + } else { + struct tlv_mt_neighbors *mt_neighbors; + mt_neighbors = tlvs_lookup_mt_neighbors(&lsp->tlv_data, + spftree->mtid); + if (mt_neighbors) + te_is_neighs = mt_neighbors->list; + } + for (ALL_LIST_ELEMENTS_RO(te_is_neighs, node, te_is_neigh)) { + if (!memcmp(te_is_neigh->neigh_id, root_sysid, + ISIS_SYS_ID_LEN)) + continue; + if (!pseudo_lsp + && !memcmp(te_is_neigh->neigh_id, null_sysid, + ISIS_SYS_ID_LEN)) + continue; + dist = cost + GET_TE_METRIC(te_is_neigh); + process_N(spftree, + LSP_PSEUDO_ID(te_is_neigh->neigh_id) + ? VTYPE_PSEUDO_TE_IS + : VTYPE_NONPSEUDO_TE_IS, + (void *)te_is_neigh->neigh_id, dist, + depth + 1, parent); + } } - if (spftree->family == AF_INET6) - { - prefix.family = AF_INET6; - for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, ipnode, ipv6)) - { - prefix.prefixlen = ipv6->prefixlen; - prefix.u.prefix6 = ipv6->prefix; - apply_mask (&prefix); - isis_spf_add_local (spftree, VTYPE_IP6REACH_INTERNAL, - &prefix, NULL, 0, parent); - } + + if (!pseudo_lsp && spftree->family == AF_INET + && spftree->mtid == ISIS_MT_IPV4_UNICAST) { + struct list *reachs[] = {lsp->tlv_data.ipv4_int_reachs, + lsp->tlv_data.ipv4_ext_reachs}; + + prefix.family = AF_INET; + for (unsigned int i = 0; i < array_size(reachs); i++) { + vtype = (reachs[i] == lsp->tlv_data.ipv4_int_reachs) + ? VTYPE_IPREACH_INTERNAL + : VTYPE_IPREACH_EXTERNAL; + for (ALL_LIST_ELEMENTS_RO(reachs[i], node, ipreach)) { + dist = cost + ipreach->metrics.metric_default; + prefix.u.prefix4 = ipreach->prefix; + prefix.prefixlen = ip_masklen(ipreach->mask); + apply_mask(&prefix); + process_N(spftree, vtype, (void *)&prefix, dist, + depth + 1, parent); + } + } } - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - { - /* - * Add the adjacencies - */ - adj_list = list_new (); - adjdb = circuit->u.bc.adjdb[spftree->level - 1]; - isis_adj_build_up_list (adjdb, adj_list); - if (listcount (adj_list) == 0) - { - list_delete (adj_list); - if (isis->debugs & DEBUG_SPF_EVENTS) - zlog_debug ("ISIS-Spf: no L%d adjacencies on circuit %s", - spftree->level, circuit->interface->name); - continue; - } - for (ALL_LIST_ELEMENTS_RO (adj_list, anode, adj)) - { - if (!adj_has_mt(adj, spftree->mtid)) - continue; - if (spftree->mtid == ISIS_MT_IPV4_UNICAST && !speaks (&adj->nlpids, spftree->family)) - continue; - switch (adj->sys_type) - { - case ISIS_SYSTYPE_ES: - memcpy(lsp_id, adj->sysid, ISIS_SYS_ID_LEN); - LSP_PSEUDO_ID (lsp_id) = 0; - isis_spf_add_local (spftree, VTYPE_ES, lsp_id, adj, - circuit->te_metric[spftree->level - 1], - parent); - break; - case ISIS_SYSTYPE_IS: - case ISIS_SYSTYPE_L1_IS: - case ISIS_SYSTYPE_L2_IS: - memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN); - LSP_PSEUDO_ID (lsp_id) = 0; - LSP_FRAGMENT (lsp_id) = 0; - isis_spf_add_local (spftree, - spftree->area->oldmetric ? VTYPE_NONPSEUDO_IS - : VTYPE_NONPSEUDO_TE_IS, - lsp_id, adj, - circuit->te_metric[spftree->level - 1], - parent); - lsp = lsp_search (lsp_id, spftree->area->lspdb[spftree->level - 1]); - if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0) - zlog_warn ("ISIS-Spf: No LSP %s found for IS adjacency " - "L%d on %s (ID %u)", - rawlspid_print (lsp_id), spftree->level, - circuit->interface->name, circuit->circuit_id); - break; - case ISIS_SYSTYPE_UNKNOWN: - default: - zlog_warn ("isis_spf_preload_tent unknow adj type"); + + if (!pseudo_lsp && spftree->family == AF_INET) { + struct list *ipv4reachs = NULL; + + if (spftree->mtid == ISIS_MT_IPV4_UNICAST) { + ipv4reachs = lsp->tlv_data.te_ipv4_reachs; + } else { + struct tlv_mt_ipv4_reachs *mt_reachs; + mt_reachs = tlvs_lookup_mt_ipv4_reachs(&lsp->tlv_data, + spftree->mtid); + if (mt_reachs) + ipv4reachs = mt_reachs->list; + } + + prefix.family = AF_INET; + for (ALL_LIST_ELEMENTS_RO(ipv4reachs, node, te_ipv4_reach)) { + assert((te_ipv4_reach->control & 0x3F) + <= IPV4_MAX_BITLEN); + + dist = cost + ntohl(te_ipv4_reach->te_metric); + prefix.u.prefix4 = + newprefix2inaddr(&te_ipv4_reach->prefix_start, + te_ipv4_reach->control); + prefix.prefixlen = (te_ipv4_reach->control & 0x3F); + apply_mask(&prefix); + process_N(spftree, VTYPE_IPREACH_TE, (void *)&prefix, + dist, depth + 1, parent); } - } - list_delete (adj_list); - /* - * Add the pseudonode - */ - if (spftree->level == 1) - memcpy (lsp_id, circuit->u.bc.l1_desig_is, ISIS_SYS_ID_LEN + 1); - else - memcpy (lsp_id, circuit->u.bc.l2_desig_is, ISIS_SYS_ID_LEN + 1); - /* can happen during DR reboot */ - if (memcmp (lsp_id, null_lsp_id, ISIS_SYS_ID_LEN + 1) == 0) - { - if (isis->debugs & DEBUG_SPF_EVENTS) - zlog_debug ("ISIS-Spf: No L%d DR on %s (ID %d)", - spftree->level, circuit->interface->name, circuit->circuit_id); - continue; - } - adj = isis_adj_lookup (lsp_id, adjdb); - /* if no adj, we are the dis or error */ - if (!adj && !circuit->u.bc.is_dr[spftree->level - 1]) - { - zlog_warn ("ISIS-Spf: No adjacency found from root " - "to L%d DR %s on %s (ID %d)", - spftree->level, rawlspid_print (lsp_id), - circuit->interface->name, circuit->circuit_id); - continue; - } - lsp = lsp_search (lsp_id, spftree->area->lspdb[spftree->level - 1]); - if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0) - { - zlog_warn ("ISIS-Spf: No lsp (%p) found from root " - "to L%d DR %s on %s (ID %d)", - (void *)lsp, spftree->level, rawlspid_print (lsp_id), - circuit->interface->name, circuit->circuit_id); - continue; - } - isis_spf_process_lsp (spftree, lsp, - circuit->te_metric[spftree->level - 1], 0, - root_sysid, parent); } - else if (circuit->circ_type == CIRCUIT_T_P2P) - { - adj = circuit->u.p2p.neighbor; - if (!adj) - continue; - if (!adj_has_mt(adj, spftree->mtid)) - continue; - switch (adj->sys_type) - { - case ISIS_SYSTYPE_ES: - memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN); - LSP_PSEUDO_ID (lsp_id) = 0; - isis_spf_add_local (spftree, VTYPE_ES, lsp_id, adj, - circuit->te_metric[spftree->level - 1], - parent); - break; - case ISIS_SYSTYPE_IS: - case ISIS_SYSTYPE_L1_IS: - case ISIS_SYSTYPE_L2_IS: - memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN); - LSP_PSEUDO_ID (lsp_id) = 0; - LSP_FRAGMENT (lsp_id) = 0; - if (spftree->mtid != ISIS_MT_IPV4_UNICAST || speaks (&adj->nlpids, spftree->family)) - isis_spf_add_local (spftree, - spftree->area->oldmetric ? VTYPE_NONPSEUDO_IS - : VTYPE_NONPSEUDO_TE_IS, - lsp_id, - adj, circuit->te_metric[spftree->level - 1], - parent); - break; - case ISIS_SYSTYPE_UNKNOWN: - default: - zlog_warn ("isis_spf_preload_tent unknown adj type"); - break; - } + + if (!pseudo_lsp && spftree->family == AF_INET6) { + struct list *ipv6reachs = NULL; + + if (spftree->mtid == ISIS_MT_IPV4_UNICAST) { + ipv6reachs = lsp->tlv_data.ipv6_reachs; + } else { + struct tlv_mt_ipv6_reachs *mt_reachs; + mt_reachs = tlvs_lookup_mt_ipv6_reachs(&lsp->tlv_data, + spftree->mtid); + if (mt_reachs) + ipv6reachs = mt_reachs->list; + } + + prefix.family = AF_INET6; + for (ALL_LIST_ELEMENTS_RO(ipv6reachs, node, ip6reach)) { + assert(ip6reach->prefix_len <= IPV6_MAX_BITLEN); + + dist = cost + ntohl(ip6reach->metric); + vtype = (ip6reach->control_info + & CTRL_INFO_DISTRIBUTION) + ? VTYPE_IP6REACH_EXTERNAL + : VTYPE_IP6REACH_INTERNAL; + prefix.prefixlen = ip6reach->prefix_len; + memcpy(&prefix.u.prefix6.s6_addr, ip6reach->prefix, + PSIZE(ip6reach->prefix_len)); + apply_mask(&prefix); + process_N(spftree, vtype, (void *)&prefix, dist, + depth + 1, parent); + } } - else if (circuit->circ_type == CIRCUIT_T_LOOPBACK) - { - continue; - } - else - { - zlog_warn ("isis_spf_preload_tent unsupported media"); - retval = ISIS_WARNING; + + if (fragnode == NULL) + fragnode = listhead(lsp->lspu.frags); + else + fragnode = listnextnode(fragnode); + + if (fragnode) { + lsp = listgetdata(fragnode); + goto lspfragloop; + } + + return ISIS_OK; +} + +static int isis_spf_preload_tent(struct isis_spftree *spftree, + u_char *root_sysid, struct isis_vertex *parent) +{ + struct isis_circuit *circuit; + struct listnode *cnode, *anode, *ipnode; + struct isis_adjacency *adj; + struct isis_lsp *lsp; + struct list *adj_list; + struct list *adjdb; + struct prefix_ipv4 *ipv4; + struct prefix prefix; + int retval = ISIS_OK; + u_char lsp_id[ISIS_SYS_ID_LEN + 2]; + static u_char null_lsp_id[ISIS_SYS_ID_LEN + 2]; + struct prefix_ipv6 *ipv6; + struct isis_circuit_mt_setting *circuit_mt; + + for (ALL_LIST_ELEMENTS_RO(spftree->area->circuit_list, cnode, + circuit)) { + circuit_mt = circuit_lookup_mt_setting(circuit, spftree->mtid); + if (circuit_mt && !circuit_mt->enabled) + continue; + if (circuit->state != C_STATE_UP) + continue; + if (!(circuit->is_type & spftree->level)) + continue; + if (spftree->family == AF_INET && !circuit->ip_router) + continue; + if (spftree->family == AF_INET6 && !circuit->ipv6_router) + continue; + /* + * Add IP(v6) addresses of this circuit + */ + if (spftree->family == AF_INET) { + prefix.family = AF_INET; + for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, ipnode, + ipv4)) { + prefix.u.prefix4 = ipv4->prefix; + prefix.prefixlen = ipv4->prefixlen; + apply_mask(&prefix); + isis_spf_add_local(spftree, + VTYPE_IPREACH_INTERNAL, + &prefix, NULL, 0, parent); + } + } + if (spftree->family == AF_INET6) { + prefix.family = AF_INET6; + for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link, + ipnode, ipv6)) { + prefix.prefixlen = ipv6->prefixlen; + prefix.u.prefix6 = ipv6->prefix; + apply_mask(&prefix); + isis_spf_add_local(spftree, + VTYPE_IP6REACH_INTERNAL, + &prefix, NULL, 0, parent); + } + } + if (circuit->circ_type == CIRCUIT_T_BROADCAST) { + /* + * Add the adjacencies + */ + adj_list = list_new(); + adjdb = circuit->u.bc.adjdb[spftree->level - 1]; + isis_adj_build_up_list(adjdb, adj_list); + if (listcount(adj_list) == 0) { + list_delete(adj_list); + if (isis->debugs & DEBUG_SPF_EVENTS) + zlog_debug( + "ISIS-Spf: no L%d adjacencies on circuit %s", + spftree->level, + circuit->interface->name); + continue; + } + for (ALL_LIST_ELEMENTS_RO(adj_list, anode, adj)) { + if (!adj_has_mt(adj, spftree->mtid)) + continue; + if (spftree->mtid == ISIS_MT_IPV4_UNICAST + && !speaks(&adj->nlpids, spftree->family)) + continue; + switch (adj->sys_type) { + case ISIS_SYSTYPE_ES: + memcpy(lsp_id, adj->sysid, + ISIS_SYS_ID_LEN); + LSP_PSEUDO_ID(lsp_id) = 0; + isis_spf_add_local( + spftree, VTYPE_ES, lsp_id, adj, + circuit->te_metric + [spftree->level - 1], + parent); + break; + case ISIS_SYSTYPE_IS: + case ISIS_SYSTYPE_L1_IS: + case ISIS_SYSTYPE_L2_IS: + memcpy(lsp_id, adj->sysid, + ISIS_SYS_ID_LEN); + LSP_PSEUDO_ID(lsp_id) = 0; + LSP_FRAGMENT(lsp_id) = 0; + isis_spf_add_local( + spftree, + spftree->area->oldmetric + ? VTYPE_NONPSEUDO_IS + : VTYPE_NONPSEUDO_TE_IS, + lsp_id, adj, + circuit->te_metric + [spftree->level - 1], + parent); + lsp = lsp_search( + lsp_id, + spftree->area + ->lspdb[spftree->level + - 1]); + if (lsp == NULL + || lsp->lsp_header->rem_lifetime + == 0) + zlog_warn( + "ISIS-Spf: No LSP %s found for IS adjacency " + "L%d on %s (ID %u)", + rawlspid_print(lsp_id), + spftree->level, + circuit->interface->name, + circuit->circuit_id); + break; + case ISIS_SYSTYPE_UNKNOWN: + default: + zlog_warn( + "isis_spf_preload_tent unknow adj type"); + } + } + list_delete(adj_list); + /* + * Add the pseudonode + */ + if (spftree->level == 1) + memcpy(lsp_id, circuit->u.bc.l1_desig_is, + ISIS_SYS_ID_LEN + 1); + else + memcpy(lsp_id, circuit->u.bc.l2_desig_is, + ISIS_SYS_ID_LEN + 1); + /* can happen during DR reboot */ + if (memcmp(lsp_id, null_lsp_id, ISIS_SYS_ID_LEN + 1) + == 0) { + if (isis->debugs & DEBUG_SPF_EVENTS) + zlog_debug( + "ISIS-Spf: No L%d DR on %s (ID %d)", + spftree->level, + circuit->interface->name, + circuit->circuit_id); + continue; + } + adj = isis_adj_lookup(lsp_id, adjdb); + /* if no adj, we are the dis or error */ + if (!adj && !circuit->u.bc.is_dr[spftree->level - 1]) { + zlog_warn( + "ISIS-Spf: No adjacency found from root " + "to L%d DR %s on %s (ID %d)", + spftree->level, rawlspid_print(lsp_id), + circuit->interface->name, + circuit->circuit_id); + continue; + } + lsp = lsp_search( + lsp_id, + spftree->area->lspdb[spftree->level - 1]); + if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0) { + zlog_warn( + "ISIS-Spf: No lsp (%p) found from root " + "to L%d DR %s on %s (ID %d)", + (void *)lsp, spftree->level, + rawlspid_print(lsp_id), + circuit->interface->name, + circuit->circuit_id); + continue; + } + isis_spf_process_lsp( + spftree, lsp, + circuit->te_metric[spftree->level - 1], 0, + root_sysid, parent); + } else if (circuit->circ_type == CIRCUIT_T_P2P) { + adj = circuit->u.p2p.neighbor; + if (!adj) + continue; + if (!adj_has_mt(adj, spftree->mtid)) + continue; + switch (adj->sys_type) { + case ISIS_SYSTYPE_ES: + memcpy(lsp_id, adj->sysid, ISIS_SYS_ID_LEN); + LSP_PSEUDO_ID(lsp_id) = 0; + isis_spf_add_local( + spftree, VTYPE_ES, lsp_id, adj, + circuit->te_metric[spftree->level - 1], + parent); + break; + case ISIS_SYSTYPE_IS: + case ISIS_SYSTYPE_L1_IS: + case ISIS_SYSTYPE_L2_IS: + memcpy(lsp_id, adj->sysid, ISIS_SYS_ID_LEN); + LSP_PSEUDO_ID(lsp_id) = 0; + LSP_FRAGMENT(lsp_id) = 0; + if (spftree->mtid != ISIS_MT_IPV4_UNICAST + || speaks(&adj->nlpids, spftree->family)) + isis_spf_add_local( + spftree, + spftree->area->oldmetric + ? VTYPE_NONPSEUDO_IS + : VTYPE_NONPSEUDO_TE_IS, + lsp_id, adj, + circuit->te_metric + [spftree->level - 1], + parent); + break; + case ISIS_SYSTYPE_UNKNOWN: + default: + zlog_warn( + "isis_spf_preload_tent unknown adj type"); + break; + } + } else if (circuit->circ_type == CIRCUIT_T_LOOPBACK) { + continue; + } else { + zlog_warn("isis_spf_preload_tent unsupported media"); + retval = ISIS_WARNING; + } } - } - return retval; + return retval; } /* * The parent(s) for vertex is set when added to TENT list * now we just put the child pointer(s) in place */ -static void -add_to_paths (struct isis_spftree *spftree, struct isis_vertex *vertex) +static void add_to_paths(struct isis_spftree *spftree, + struct isis_vertex *vertex) { - char buff[PREFIX2STR_BUFFER]; + char buff[PREFIX2STR_BUFFER]; - if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type)) - return; - listnode_add (spftree->paths, vertex); + if (isis_find_vertex(spftree->paths, vertex->N.id, vertex->type)) + return; + listnode_add(spftree->paths, vertex); #ifdef EXTREME_DEBUG - zlog_debug ("ISIS-Spf: added %s %s %s depth %d dist %d to PATHS", - print_sys_hostname (vertex->N.id), - vtype2string (vertex->type), vid2string (vertex, buff, sizeof (buff)), - vertex->depth, vertex->d_N); + zlog_debug("ISIS-Spf: added %s %s %s depth %d dist %d to PATHS", + print_sys_hostname(vertex->N.id), vtype2string(vertex->type), + vid2string(vertex, buff, sizeof(buff)), vertex->depth, + vertex->d_N); #endif /* EXTREME_DEBUG */ - if (VTYPE_IP(vertex->type)) - { - if (listcount (vertex->Adj_N) > 0) - isis_route_create ((struct prefix *) &vertex->N.prefix, vertex->d_N, - vertex->depth, vertex->Adj_N, spftree->area, spftree->level); - else if (isis->debugs & DEBUG_SPF_EVENTS) - zlog_debug ("ISIS-Spf: no adjacencies do not install route for " - "%s depth %d dist %d", vid2string (vertex, buff, sizeof (buff)), - vertex->depth, vertex->d_N); - } - - return; + if (VTYPE_IP(vertex->type)) { + if (listcount(vertex->Adj_N) > 0) + isis_route_create((struct prefix *)&vertex->N.prefix, + vertex->d_N, vertex->depth, + vertex->Adj_N, spftree->area, + spftree->level); + else if (isis->debugs & DEBUG_SPF_EVENTS) + zlog_debug( + "ISIS-Spf: no adjacencies do not install route for " + "%s depth %d dist %d", + vid2string(vertex, buff, sizeof(buff)), + vertex->depth, vertex->d_N); + } + + return; } -static void -init_spt (struct isis_spftree *spftree, int mtid, int level, int family) +static void init_spt(struct isis_spftree *spftree, int mtid, int level, + int family) { - spftree->tents->del = spftree->paths->del = (void (*)(void *)) isis_vertex_del; - list_delete_all_node (spftree->tents); - list_delete_all_node (spftree->paths); - spftree->tents->del = spftree->paths->del = NULL; - - spftree->mtid = mtid; - spftree->level = level; - spftree->family = family; - return; + spftree->tents->del = spftree->paths->del = + (void (*)(void *))isis_vertex_del; + list_delete_all_node(spftree->tents); + list_delete_all_node(spftree->paths); + spftree->tents->del = spftree->paths->del = NULL; + + spftree->mtid = mtid; + spftree->level = level; + spftree->family = family; + return; } -static int -isis_run_spf (struct isis_area *area, int level, int family, u_char *sysid) +static int isis_run_spf(struct isis_area *area, int level, int family, + u_char *sysid) { - int retval = ISIS_OK; - struct listnode *node; - struct isis_vertex *vertex; - struct isis_vertex *root_vertex; - struct isis_spftree *spftree = NULL; - u_char lsp_id[ISIS_SYS_ID_LEN + 2]; - struct isis_lsp *lsp; - struct route_table *table = NULL; - struct timeval time_now; - unsigned long long start_time, end_time; - uint16_t mtid; - - /* Get time that can't roll backwards. */ - monotime(&time_now); - start_time = time_now.tv_sec; - start_time = (start_time * 1000000) + time_now.tv_usec; - - if (family == AF_INET) - spftree = area->spftree[level - 1]; - else if (family == AF_INET6) - spftree = area->spftree6[level - 1]; - assert (spftree); - assert (sysid); - - /* Make all routes in current route table inactive. */ - if (family == AF_INET) - table = area->route_table[level - 1]; - else if (family == AF_INET6) - table = area->route_table6[level - 1]; - - isis_route_invalidate_table (area, table); - - /* We only support ipv4-unicast and ipv6-unicast as topologies for now */ - if (family == AF_INET6) - mtid = isis_area_ipv6_topology(area); - else - mtid = ISIS_MT_IPV4_UNICAST; - - /* - * C.2.5 Step 0 - */ - init_spt (spftree, mtid, level, family); - /* a) */ - root_vertex = isis_spf_add_root (spftree, sysid); - /* b) */ - retval = isis_spf_preload_tent (spftree, sysid, root_vertex); - if (retval != ISIS_OK) - { - zlog_warn ("ISIS-Spf: failed to load TENT SPF-root:%s", print_sys_hostname(sysid)); - goto out; - } - - /* - * C.2.7 Step 2 - */ - if (listcount (spftree->tents) == 0) - { - zlog_warn ("ISIS-Spf: TENT is empty SPF-root:%s", print_sys_hostname(sysid)); - goto out; - } - - while (listcount (spftree->tents) > 0) - { - node = listhead (spftree->tents); - vertex = listgetdata (node); + int retval = ISIS_OK; + struct listnode *node; + struct isis_vertex *vertex; + struct isis_vertex *root_vertex; + struct isis_spftree *spftree = NULL; + u_char lsp_id[ISIS_SYS_ID_LEN + 2]; + struct isis_lsp *lsp; + struct route_table *table = NULL; + struct timeval time_now; + unsigned long long start_time, end_time; + uint16_t mtid; + + /* Get time that can't roll backwards. */ + monotime(&time_now); + start_time = time_now.tv_sec; + start_time = (start_time * 1000000) + time_now.tv_usec; + + if (family == AF_INET) + spftree = area->spftree[level - 1]; + else if (family == AF_INET6) + spftree = area->spftree6[level - 1]; + assert(spftree); + assert(sysid); + + /* Make all routes in current route table inactive. */ + if (family == AF_INET) + table = area->route_table[level - 1]; + else if (family == AF_INET6) + table = area->route_table6[level - 1]; + + isis_route_invalidate_table(area, table); + + /* We only support ipv4-unicast and ipv6-unicast as topologies for now + */ + if (family == AF_INET6) + mtid = isis_area_ipv6_topology(area); + else + mtid = ISIS_MT_IPV4_UNICAST; + + /* + * C.2.5 Step 0 + */ + init_spt(spftree, mtid, level, family); + /* a) */ + root_vertex = isis_spf_add_root(spftree, sysid); + /* b) */ + retval = isis_spf_preload_tent(spftree, sysid, root_vertex); + if (retval != ISIS_OK) { + zlog_warn("ISIS-Spf: failed to load TENT SPF-root:%s", + print_sys_hostname(sysid)); + goto out; + } + + /* + * C.2.7 Step 2 + */ + if (listcount(spftree->tents) == 0) { + zlog_warn("ISIS-Spf: TENT is empty SPF-root:%s", + print_sys_hostname(sysid)); + goto out; + } + + while (listcount(spftree->tents) > 0) { + node = listhead(spftree->tents); + vertex = listgetdata(node); #ifdef EXTREME_DEBUG - zlog_debug ("ISIS-Spf: get TENT node %s %s depth %d dist %d to PATHS", - print_sys_hostname (vertex->N.id), - vtype2string (vertex->type), vertex->depth, vertex->d_N); + zlog_debug( + "ISIS-Spf: get TENT node %s %s depth %d dist %d to PATHS", + print_sys_hostname(vertex->N.id), + vtype2string(vertex->type), vertex->depth, vertex->d_N); #endif /* EXTREME_DEBUG */ - /* Remove from tent list and add to paths list */ - list_delete_node (spftree->tents, node); - add_to_paths (spftree, vertex); - if (VTYPE_IS(vertex->type)) - { - memcpy (lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1); - LSP_FRAGMENT (lsp_id) = 0; - lsp = lsp_search (lsp_id, area->lspdb[level - 1]); - if (lsp && lsp->lsp_header->rem_lifetime != 0) - { - isis_spf_process_lsp (spftree, lsp, vertex->d_N, - vertex->depth, sysid, vertex); - } - else - { - zlog_warn ("ISIS-Spf: No LSP found for %s", - rawlspid_print (lsp_id)); - } + /* Remove from tent list and add to paths list */ + list_delete_node(spftree->tents, node); + add_to_paths(spftree, vertex); + if (VTYPE_IS(vertex->type)) { + memcpy(lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1); + LSP_FRAGMENT(lsp_id) = 0; + lsp = lsp_search(lsp_id, area->lspdb[level - 1]); + if (lsp && lsp->lsp_header->rem_lifetime != 0) { + isis_spf_process_lsp(spftree, lsp, vertex->d_N, + vertex->depth, sysid, + vertex); + } else { + zlog_warn("ISIS-Spf: No LSP found for %s", + rawlspid_print(lsp_id)); + } + } } - } out: - isis_route_validate (area); - spftree->runcount++; - spftree->last_run_timestamp = time (NULL); - monotime(&time_now); - end_time = time_now.tv_sec; - end_time = (end_time * 1000000) + time_now.tv_usec; - spftree->last_run_duration = end_time - start_time; - - return retval; + isis_route_validate(area); + spftree->runcount++; + spftree->last_run_timestamp = time(NULL); + monotime(&time_now); + end_time = time_now.tv_sec; + end_time = (end_time * 1000000) + time_now.tv_usec; + spftree->last_run_duration = end_time - start_time; + + return retval; } -static int -isis_run_spf_cb (struct thread *thread) +static int isis_run_spf_cb(struct thread *thread) { - struct isis_spf_run *run = THREAD_ARG (thread); - struct isis_area *area = run->area; - int level = run->level; - int retval = ISIS_OK; - - XFREE(MTYPE_ISIS_SPF_RUN, run); - area->spf_timer[level - 1] = NULL; - - if (!(area->is_type & level)) - { - if (isis->debugs & DEBUG_SPF_EVENTS) - zlog_warn ("ISIS-SPF (%s) area does not share level", - area->area_tag); - return ISIS_WARNING; - } - - if (isis->debugs & DEBUG_SPF_EVENTS) - zlog_debug ("ISIS-Spf (%s) L%d SPF needed, periodic SPF", - area->area_tag, level); - - if (area->ip_circuits) - retval = isis_run_spf (area, level, AF_INET, isis->sysid); - if (area->ipv6_circuits) - retval = isis_run_spf (area, level, AF_INET6, isis->sysid); - - return retval; -} + struct isis_spf_run *run = THREAD_ARG(thread); + struct isis_area *area = run->area; + int level = run->level; + int retval = ISIS_OK; + + XFREE(MTYPE_ISIS_SPF_RUN, run); + area->spf_timer[level - 1] = NULL; + + if (!(area->is_type & level)) { + if (isis->debugs & DEBUG_SPF_EVENTS) + zlog_warn("ISIS-SPF (%s) area does not share level", + area->area_tag); + return ISIS_WARNING; + } -static struct isis_spf_run* -isis_run_spf_arg(struct isis_area *area, int level) -{ - struct isis_spf_run *run = XMALLOC(MTYPE_ISIS_SPF_RUN, sizeof(*run)); + if (isis->debugs & DEBUG_SPF_EVENTS) + zlog_debug("ISIS-Spf (%s) L%d SPF needed, periodic SPF", + area->area_tag, level); - run->area = area; - run->level = level; + if (area->ip_circuits) + retval = isis_run_spf(area, level, AF_INET, isis->sysid); + if (area->ipv6_circuits) + retval = isis_run_spf(area, level, AF_INET6, isis->sysid); - return run; + return retval; } -int -isis_spf_schedule (struct isis_area *area, int level) +static struct isis_spf_run *isis_run_spf_arg(struct isis_area *area, int level) { - struct isis_spftree *spftree = area->spftree[level - 1]; - time_t now = time (NULL); - int diff = now - spftree->last_run_timestamp; - - assert (diff >= 0); - assert (area->is_type & level); - - if (isis->debugs & DEBUG_SPF_EVENTS) - zlog_debug ("ISIS-Spf (%s) L%d SPF schedule called, lastrun %d sec ago", - area->area_tag, level, diff); - - if (area->spf_delay_ietf[level - 1]) - { - /* Need to call schedule function also if spf delay is running to - * restart holdoff timer - compare draft-ietf-rtgwg-backoff-algo-04 */ - long delay = spf_backoff_schedule(area->spf_delay_ietf[level -1]); - if (area->spf_timer[level - 1]) - return ISIS_OK; - - thread_add_timer_msec (master, isis_run_spf_cb, - isis_run_spf_arg(area, level), - delay, &area->spf_timer[level-1]); - return ISIS_OK; - } - - if (area->spf_timer[level -1]) - return ISIS_OK; - - /* wait configured min_spf_interval before doing the SPF */ - if (diff >= area->min_spf_interval[level-1]) - { - int retval = ISIS_OK; - - if (area->ip_circuits) - retval = isis_run_spf (area, level, AF_INET, isis->sysid); - if (area->ipv6_circuits) - retval = isis_run_spf (area, level, AF_INET6, isis->sysid); - - return retval; - } - - thread_add_timer (master, isis_run_spf_cb, isis_run_spf_arg(area, level), - area->min_spf_interval[level-1] - diff, - &area->spf_timer[level-1]); - - if (isis->debugs & DEBUG_SPF_EVENTS) - zlog_debug ("ISIS-Spf (%s) L%d SPF scheduled %d sec from now", - area->area_tag, level, area->min_spf_interval[level-1] - diff); - - return ISIS_OK; + struct isis_spf_run *run = XMALLOC(MTYPE_ISIS_SPF_RUN, sizeof(*run)); + + run->area = area; + run->level = level; + + return run; } -static void -isis_print_paths (struct vty *vty, struct list *paths, u_char *root_sysid) +int isis_spf_schedule(struct isis_area *area, int level) { - struct listnode *node; - struct listnode *anode; - struct isis_vertex *vertex; - struct isis_adjacency *adj; - char buff[PREFIX2STR_BUFFER]; - - vty_out (vty, - "Vertex Type Metric Next-Hop Interface Parent\n"); - - for (ALL_LIST_ELEMENTS_RO (paths, node, vertex)) { - if (memcmp (vertex->N.id, root_sysid, ISIS_SYS_ID_LEN) == 0) { - vty_out (vty, "%-20s %-12s %-6s", print_sys_hostname (root_sysid), - "", ""); - vty_out (vty, "%-30s", ""); - } else { - int rows = 0; - vty_out (vty, "%-20s %-12s %-6u ", vid2string (vertex, buff, sizeof (buff)), - vtype2string (vertex->type), vertex->d_N); - for (ALL_LIST_ELEMENTS_RO (vertex->Adj_N, anode, adj)) { - if (adj) { - if (rows) { - vty_out (vty, "\n"); - vty_out (vty, "%-20s %-12s %-6s ", "", "", ""); - } - vty_out (vty, "%-20s %-9s ", - print_sys_hostname (adj->sysid), - adj->circuit->interface->name); - ++rows; - } + struct isis_spftree *spftree = area->spftree[level - 1]; + time_t now = time(NULL); + int diff = now - spftree->last_run_timestamp; + + assert(diff >= 0); + assert(area->is_type & level); + + if (isis->debugs & DEBUG_SPF_EVENTS) + zlog_debug( + "ISIS-Spf (%s) L%d SPF schedule called, lastrun %d sec ago", + area->area_tag, level, diff); + + if (area->spf_delay_ietf[level - 1]) { + /* Need to call schedule function also if spf delay is running + * to + * restart holdoff timer - compare + * draft-ietf-rtgwg-backoff-algo-04 */ + long delay = + spf_backoff_schedule(area->spf_delay_ietf[level - 1]); + if (area->spf_timer[level - 1]) + return ISIS_OK; + + thread_add_timer_msec(master, isis_run_spf_cb, + isis_run_spf_arg(area, level), delay, + &area->spf_timer[level - 1]); + return ISIS_OK; } - if (rows == 0) - vty_out (vty, "%-30s ", ""); - } - - /* Print list of parents for the ECMP DAG */ - if (listcount (vertex->parents) > 0) { - struct listnode *pnode; - struct isis_vertex *pvertex; - int rows = 0; - for (ALL_LIST_ELEMENTS_RO (vertex->parents, pnode, pvertex)) { - if (rows) { - vty_out (vty, "\n"); - vty_out (vty, "%-72s", ""); - } - vty_out (vty, "%s(%d)", - vid2string (pvertex, buff, sizeof (buff)), pvertex->type); - ++rows; + + if (area->spf_timer[level - 1]) + return ISIS_OK; + + /* wait configured min_spf_interval before doing the SPF */ + if (diff >= area->min_spf_interval[level - 1]) { + int retval = ISIS_OK; + + if (area->ip_circuits) + retval = + isis_run_spf(area, level, AF_INET, isis->sysid); + if (area->ipv6_circuits) + retval = isis_run_spf(area, level, AF_INET6, + isis->sysid); + + return retval; } - } else { - vty_out (vty, " NULL "); - } - vty_out (vty, "\n"); - } + thread_add_timer(master, isis_run_spf_cb, isis_run_spf_arg(area, level), + area->min_spf_interval[level - 1] - diff, + &area->spf_timer[level - 1]); + + if (isis->debugs & DEBUG_SPF_EVENTS) + zlog_debug("ISIS-Spf (%s) L%d SPF scheduled %d sec from now", + area->area_tag, level, + area->min_spf_interval[level - 1] - diff); + + return ISIS_OK; +} + +static void isis_print_paths(struct vty *vty, struct list *paths, + u_char *root_sysid) +{ + struct listnode *node; + struct listnode *anode; + struct isis_vertex *vertex; + struct isis_adjacency *adj; + char buff[PREFIX2STR_BUFFER]; + + vty_out(vty, + "Vertex Type Metric Next-Hop Interface Parent\n"); + + for (ALL_LIST_ELEMENTS_RO(paths, node, vertex)) { + if (memcmp(vertex->N.id, root_sysid, ISIS_SYS_ID_LEN) == 0) { + vty_out(vty, "%-20s %-12s %-6s", + print_sys_hostname(root_sysid), "", ""); + vty_out(vty, "%-30s", ""); + } else { + int rows = 0; + vty_out(vty, "%-20s %-12s %-6u ", + vid2string(vertex, buff, sizeof(buff)), + vtype2string(vertex->type), vertex->d_N); + for (ALL_LIST_ELEMENTS_RO(vertex->Adj_N, anode, adj)) { + if (adj) { + if (rows) { + vty_out(vty, "\n"); + vty_out(vty, + "%-20s %-12s %-6s ", "", + "", ""); + } + vty_out(vty, "%-20s %-9s ", + print_sys_hostname(adj->sysid), + adj->circuit->interface->name); + ++rows; + } + } + if (rows == 0) + vty_out(vty, "%-30s ", ""); + } + + /* Print list of parents for the ECMP DAG */ + if (listcount(vertex->parents) > 0) { + struct listnode *pnode; + struct isis_vertex *pvertex; + int rows = 0; + for (ALL_LIST_ELEMENTS_RO(vertex->parents, pnode, + pvertex)) { + if (rows) { + vty_out(vty, "\n"); + vty_out(vty, "%-72s", ""); + } + vty_out(vty, "%s(%d)", + vid2string(pvertex, buff, sizeof(buff)), + pvertex->type); + ++rows; + } + } else { + vty_out(vty, " NULL "); + } + + vty_out(vty, "\n"); + } } DEFUN (show_isis_topology, @@ -1380,56 +1372,57 @@ DEFUN (show_isis_topology, "Paths to all level-1 routers in the area\n" "Paths to all level-2 routers in the domain\n") { - int levels; - struct listnode *node; - struct isis_area *area; - - if (argc < 4) - levels = ISIS_LEVEL1|ISIS_LEVEL2; - else if (strmatch(argv[3]->text, "level-1")) - levels = ISIS_LEVEL1; - else - levels = ISIS_LEVEL2; - - if (!isis->area_list || isis->area_list->count == 0) - return CMD_SUCCESS; - - for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area)) - { - vty_out (vty, "Area %s:\n",area->area_tag ? area->area_tag : "null"); + int levels; + struct listnode *node; + struct isis_area *area; + + if (argc < 4) + levels = ISIS_LEVEL1 | ISIS_LEVEL2; + else if (strmatch(argv[3]->text, "level-1")) + levels = ISIS_LEVEL1; + else + levels = ISIS_LEVEL2; + + if (!isis->area_list || isis->area_list->count == 0) + return CMD_SUCCESS; + + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { + vty_out(vty, "Area %s:\n", + area->area_tag ? area->area_tag : "null"); + + for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) { + if ((level & levels) == 0) + continue; + + if (area->ip_circuits > 0 && area->spftree[level - 1] + && area->spftree[level - 1]->paths->count > 0) { + vty_out(vty, + "IS-IS paths to level-%d routers that speak IP\n", + level); + isis_print_paths( + vty, area->spftree[level - 1]->paths, + isis->sysid); + vty_out(vty, "\n"); + } + if (area->ipv6_circuits > 0 && area->spftree6[level - 1] + && area->spftree6[level - 1]->paths->count > 0) { + vty_out(vty, + "IS-IS paths to level-%d routers that speak IPv6\n", + level); + isis_print_paths( + vty, area->spftree6[level - 1]->paths, + isis->sysid); + vty_out(vty, "\n"); + } + } - for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) - { - if ((level & levels) == 0) - continue; - - if (area->ip_circuits > 0 && area->spftree[level-1] - && area->spftree[level-1]->paths->count > 0) - { - vty_out (vty, "IS-IS paths to level-%d routers that speak IP\n", - level); - isis_print_paths (vty, area->spftree[level-1]->paths, isis->sysid); - vty_out (vty, "\n"); - } - if (area->ipv6_circuits > 0 && area->spftree6[level-1] - && area->spftree6[level-1]->paths->count > 0) - { - vty_out (vty, - "IS-IS paths to level-%d routers that speak IPv6\n", - level); - isis_print_paths (vty, area->spftree6[level-1]->paths, isis->sysid); - vty_out (vty, "\n"); - } + vty_out(vty, "\n"); } - vty_out (vty, "\n"); - } - - return CMD_SUCCESS; + return CMD_SUCCESS; } -void -isis_spf_cmds_init () +void isis_spf_cmds_init() { - install_element (VIEW_NODE, &show_isis_topology_cmd); + install_element(VIEW_NODE, &show_isis_topology_cmd); } diff --git a/isisd/isis_spf.h b/isisd/isis_spf.h index 8c72f45c5..c7a505489 100644 --- a/isisd/isis_spf.h +++ b/isisd/isis_spf.h @@ -1,19 +1,19 @@ /* * IS-IS Rout(e)ing protocol - isis_spf.h - * IS-IS Shortest Path First algorithm + * IS-IS Shortest Path First algorithm * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -24,18 +24,17 @@ #ifndef _ZEBRA_ISIS_SPF_H #define _ZEBRA_ISIS_SPF_H -enum vertextype -{ - VTYPE_PSEUDO_IS = 1, - VTYPE_PSEUDO_TE_IS, - VTYPE_NONPSEUDO_IS, - VTYPE_NONPSEUDO_TE_IS, - VTYPE_ES, - VTYPE_IPREACH_INTERNAL, - VTYPE_IPREACH_EXTERNAL, - VTYPE_IPREACH_TE, - VTYPE_IP6REACH_INTERNAL, - VTYPE_IP6REACH_EXTERNAL +enum vertextype { + VTYPE_PSEUDO_IS = 1, + VTYPE_PSEUDO_TE_IS, + VTYPE_NONPSEUDO_IS, + VTYPE_NONPSEUDO_TE_IS, + VTYPE_ES, + VTYPE_IPREACH_INTERNAL, + VTYPE_IPREACH_EXTERNAL, + VTYPE_IPREACH_TE, + VTYPE_IP6REACH_INTERNAL, + VTYPE_IP6REACH_EXTERNAL }; #define VTYPE_IS(t) ((t) >= VTYPE_PSEUDO_IS && (t) <= VTYPE_NONPSEUDO_TE_IS) @@ -43,45 +42,41 @@ enum vertextype #define VTYPE_IP(t) ((t) >= VTYPE_IPREACH_INTERNAL && (t) <= VTYPE_IP6REACH_EXTERNAL) /* - * Triple + * Triple */ -struct isis_vertex -{ - enum vertextype type; +struct isis_vertex { + enum vertextype type; - union - { - u_char id[ISIS_SYS_ID_LEN + 1]; - struct prefix prefix; - } N; + union { + u_char id[ISIS_SYS_ID_LEN + 1]; + struct prefix prefix; + } N; - u_int32_t d_N; /* d(N) Distance from this IS */ - u_int16_t depth; /* The depth in the imaginary tree */ - struct list *Adj_N; /* {Adj(N)} next hop or neighbor list */ - struct list *parents; /* list of parents for ECMP */ - struct list *children; /* list of children used for tree dump */ + u_int32_t d_N; /* d(N) Distance from this IS */ + u_int16_t depth; /* The depth in the imaginary tree */ + struct list *Adj_N; /* {Adj(N)} next hop or neighbor list */ + struct list *parents; /* list of parents for ECMP */ + struct list *children; /* list of children used for tree dump */ }; -struct isis_spftree -{ - struct list *paths; /* the SPT */ - struct list *tents; /* TENT */ - struct isis_area *area; /* back pointer to area */ - unsigned int runcount; /* number of runs since uptime */ - time_t last_run_timestamp; /* last run timestamp for scheduling */ - time_t last_run_duration; /* last run duration in msec */ +struct isis_spftree { + struct list *paths; /* the SPT */ + struct list *tents; /* TENT */ + struct isis_area *area; /* back pointer to area */ + unsigned int runcount; /* number of runs since uptime */ + time_t last_run_timestamp; /* last run timestamp for scheduling */ + time_t last_run_duration; /* last run duration in msec */ - uint16_t mtid; - int family; - int level; + uint16_t mtid; + int family; + int level; }; -struct isis_spftree * isis_spftree_new (struct isis_area *area); -void isis_spftree_del (struct isis_spftree *spftree); -void spftree_area_init (struct isis_area *area); -void spftree_area_del (struct isis_area *area); -void spftree_area_adj_del (struct isis_area *area, - struct isis_adjacency *adj); -int isis_spf_schedule (struct isis_area *area, int level); -void isis_spf_cmds_init (void); +struct isis_spftree *isis_spftree_new(struct isis_area *area); +void isis_spftree_del(struct isis_spftree *spftree); +void spftree_area_init(struct isis_area *area); +void spftree_area_del(struct isis_area *area); +void spftree_area_adj_del(struct isis_area *area, struct isis_adjacency *adj); +int isis_spf_schedule(struct isis_area *area, int level); +void isis_spf_cmds_init(void); #endif /* _ZEBRA_ISIS_SPF_H */ diff --git a/isisd/isis_te.c b/isisd/isis_te.c index 271545744..5296d9948 100644 --- a/isisd/isis_te.c +++ b/isisd/isis_te.c @@ -61,1020 +61,1034 @@ /* Global varial for MPLS TE management */ struct isis_mpls_te isisMplsTE; -const char *mode2text[] = { "Disable", "Area", "AS", "Emulate" }; +const char *mode2text[] = {"Disable", "Area", "AS", "Emulate"}; /*------------------------------------------------------------------------* * Followings are control functions for MPLS-TE parameters management. *------------------------------------------------------------------------*/ /* Search MPLS TE Circuit context from Interface */ -static struct mpls_te_circuit * -lookup_mpls_params_by_ifp (struct interface *ifp) +static struct mpls_te_circuit *lookup_mpls_params_by_ifp(struct interface *ifp) { - struct isis_circuit *circuit; + struct isis_circuit *circuit; - if ((circuit = circuit_scan_by_ifp (ifp)) == NULL) - return NULL; + if ((circuit = circuit_scan_by_ifp(ifp)) == NULL) + return NULL; - return circuit->mtc; + return circuit->mtc; } /* Create new MPLS TE Circuit context */ -struct mpls_te_circuit * -mpls_te_circuit_new() +struct mpls_te_circuit *mpls_te_circuit_new() { - struct mpls_te_circuit *mtc; + struct mpls_te_circuit *mtc; - zlog_debug ("ISIS MPLS-TE: Create new MPLS TE Circuit context"); + zlog_debug("ISIS MPLS-TE: Create new MPLS TE Circuit context"); - mtc = XCALLOC(MTYPE_ISIS_MPLS_TE, sizeof (struct mpls_te_circuit)); + mtc = XCALLOC(MTYPE_ISIS_MPLS_TE, sizeof(struct mpls_te_circuit)); - if (mtc == NULL) - return NULL; + if (mtc == NULL) + return NULL; - mtc->status = disable; - mtc->type = STD_TE; - mtc->length = 0; - - return mtc; + mtc->status = disable; + mtc->type = STD_TE; + mtc->length = 0; + return mtc; } -/* Copy SUB TLVs parameters into a buffer - No space verification are performed */ +/* Copy SUB TLVs parameters into a buffer - No space verification are performed + */ /* Caller must verify before that there is enough free space in the buffer */ -u_char -add_te_subtlvs(u_char *buf, struct mpls_te_circuit *mtc) +u_char add_te_subtlvs(u_char *buf, struct mpls_te_circuit *mtc) { - u_char size, *tlvs = buf; - - zlog_debug ("ISIS MPLS-TE: Add TE Sub TLVs to buffer"); - - if (mtc == NULL) - { - zlog_debug("ISIS MPLS-TE: Abort! No MPLS TE Circuit available has been specified"); - return 0; - } - - /* Create buffer if not provided */ - if (buf == NULL) - { - zlog_debug("ISIS MPLS-TE: Abort! No Buffer has been specified"); - return 0; - } - - /* TE_SUBTLV_ADMIN_GRP */ - if (SUBTLV_TYPE(mtc->admin_grp) != 0) - { - size = SUBTLV_SIZE (&(mtc->admin_grp.header)); - memcpy(tlvs, &(mtc->admin_grp), size); - tlvs += size; - } - - /* TE_SUBTLV_LLRI */ - if (SUBTLV_TYPE(mtc->llri) != 0) - { - size = SUBTLV_SIZE (&(mtc->llri.header)); - memcpy(tlvs, &(mtc->llri), size); - tlvs += size; - } - - /* TE_SUBTLV_LCLIF_IPADDR */ - if (SUBTLV_TYPE(mtc->local_ipaddr) != 0) - { - size = SUBTLV_SIZE (&(mtc->local_ipaddr.header)); - memcpy(tlvs, &(mtc->local_ipaddr), size); - tlvs += size; - } - - /* TE_SUBTLV_RMTIF_IPADDR */ - if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0) - { - size = SUBTLV_SIZE (&(mtc->rmt_ipaddr.header)); - memcpy(tlvs, &(mtc->rmt_ipaddr), size); - tlvs += size; - } - - /* TE_SUBTLV_MAX_BW */ - if (SUBTLV_TYPE(mtc->max_bw) != 0) - { - size = SUBTLV_SIZE (&(mtc->max_bw.header)); - memcpy(tlvs, &(mtc->max_bw), size); - tlvs += size; - } - - /* TE_SUBTLV_MAX_RSV_BW */ - if (SUBTLV_TYPE(mtc->max_rsv_bw) != 0) - { - size = SUBTLV_SIZE (&(mtc->max_rsv_bw.header)); - memcpy(tlvs, &(mtc->max_rsv_bw), size); - tlvs += size; - } - - /* TE_SUBTLV_UNRSV_BW */ - if (SUBTLV_TYPE(mtc->unrsv_bw) != 0) - { - size = SUBTLV_SIZE (&(mtc->unrsv_bw.header)); - memcpy(tlvs, &(mtc->unrsv_bw), size); - tlvs += size; - } - - /* TE_SUBTLV_TE_METRIC */ - if (SUBTLV_TYPE(mtc->te_metric) != 0) - { - size = SUBTLV_SIZE (&(mtc->te_metric.header)); - memcpy(tlvs, &(mtc->te_metric), size); - tlvs += size; - } - - /* TE_SUBTLV_AV_DELAY */ - if (SUBTLV_TYPE(mtc->av_delay) != 0) - { - size = SUBTLV_SIZE (&(mtc->av_delay.header)); - memcpy(tlvs, &(mtc->av_delay), size); - tlvs += size; - } - - /* TE_SUBTLV_MM_DELAY */ - if (SUBTLV_TYPE(mtc->mm_delay) != 0) - { - size = SUBTLV_SIZE (&(mtc->mm_delay.header)); - memcpy(tlvs, &(mtc->mm_delay), size); - tlvs += size; - } - - /* TE_SUBTLV_DELAY_VAR */ - if (SUBTLV_TYPE(mtc->delay_var) != 0) - { - size = SUBTLV_SIZE (&(mtc->delay_var.header)); - memcpy(tlvs, &(mtc->delay_var), size); - tlvs += size; - } - - /* TE_SUBTLV_PKT_LOSS */ - if (SUBTLV_TYPE(mtc->pkt_loss) != 0) - { - size = SUBTLV_SIZE (&(mtc->pkt_loss.header)); - memcpy(tlvs, &(mtc->pkt_loss), size); - tlvs += size; - } - - /* TE_SUBTLV_RES_BW */ - if (SUBTLV_TYPE(mtc->res_bw) != 0) - { - size = SUBTLV_SIZE (&(mtc->res_bw.header)); - memcpy(tlvs, &(mtc->res_bw), size); - tlvs += size; - } - - /* TE_SUBTLV_AVA_BW */ - if (SUBTLV_TYPE(mtc->ava_bw) != 0) - { - size = SUBTLV_SIZE (&(mtc->ava_bw.header)); - memcpy(tlvs, &(mtc->ava_bw), size); - tlvs += size; - } - - /* TE_SUBTLV_USE_BW */ - if (SUBTLV_TYPE(mtc->use_bw) != 0) - { - size = SUBTLV_SIZE (&(mtc->use_bw.header)); - memcpy(tlvs, &(mtc->use_bw), size); - tlvs += size; - } - - /* Update SubTLVs length */ - mtc->length = subtlvs_len(mtc); - - zlog_debug("ISIS MPLS-TE: Add %d bytes length SubTLVs", mtc->length); - - return mtc->length; + u_char size, *tlvs = buf; + + zlog_debug("ISIS MPLS-TE: Add TE Sub TLVs to buffer"); + + if (mtc == NULL) { + zlog_debug( + "ISIS MPLS-TE: Abort! No MPLS TE Circuit available has been specified"); + return 0; + } + + /* Create buffer if not provided */ + if (buf == NULL) { + zlog_debug("ISIS MPLS-TE: Abort! No Buffer has been specified"); + return 0; + } + + /* TE_SUBTLV_ADMIN_GRP */ + if (SUBTLV_TYPE(mtc->admin_grp) != 0) { + size = SUBTLV_SIZE(&(mtc->admin_grp.header)); + memcpy(tlvs, &(mtc->admin_grp), size); + tlvs += size; + } + + /* TE_SUBTLV_LLRI */ + if (SUBTLV_TYPE(mtc->llri) != 0) { + size = SUBTLV_SIZE(&(mtc->llri.header)); + memcpy(tlvs, &(mtc->llri), size); + tlvs += size; + } + + /* TE_SUBTLV_LCLIF_IPADDR */ + if (SUBTLV_TYPE(mtc->local_ipaddr) != 0) { + size = SUBTLV_SIZE(&(mtc->local_ipaddr.header)); + memcpy(tlvs, &(mtc->local_ipaddr), size); + tlvs += size; + } + + /* TE_SUBTLV_RMTIF_IPADDR */ + if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0) { + size = SUBTLV_SIZE(&(mtc->rmt_ipaddr.header)); + memcpy(tlvs, &(mtc->rmt_ipaddr), size); + tlvs += size; + } + + /* TE_SUBTLV_MAX_BW */ + if (SUBTLV_TYPE(mtc->max_bw) != 0) { + size = SUBTLV_SIZE(&(mtc->max_bw.header)); + memcpy(tlvs, &(mtc->max_bw), size); + tlvs += size; + } + + /* TE_SUBTLV_MAX_RSV_BW */ + if (SUBTLV_TYPE(mtc->max_rsv_bw) != 0) { + size = SUBTLV_SIZE(&(mtc->max_rsv_bw.header)); + memcpy(tlvs, &(mtc->max_rsv_bw), size); + tlvs += size; + } + + /* TE_SUBTLV_UNRSV_BW */ + if (SUBTLV_TYPE(mtc->unrsv_bw) != 0) { + size = SUBTLV_SIZE(&(mtc->unrsv_bw.header)); + memcpy(tlvs, &(mtc->unrsv_bw), size); + tlvs += size; + } + + /* TE_SUBTLV_TE_METRIC */ + if (SUBTLV_TYPE(mtc->te_metric) != 0) { + size = SUBTLV_SIZE(&(mtc->te_metric.header)); + memcpy(tlvs, &(mtc->te_metric), size); + tlvs += size; + } + + /* TE_SUBTLV_AV_DELAY */ + if (SUBTLV_TYPE(mtc->av_delay) != 0) { + size = SUBTLV_SIZE(&(mtc->av_delay.header)); + memcpy(tlvs, &(mtc->av_delay), size); + tlvs += size; + } + + /* TE_SUBTLV_MM_DELAY */ + if (SUBTLV_TYPE(mtc->mm_delay) != 0) { + size = SUBTLV_SIZE(&(mtc->mm_delay.header)); + memcpy(tlvs, &(mtc->mm_delay), size); + tlvs += size; + } + + /* TE_SUBTLV_DELAY_VAR */ + if (SUBTLV_TYPE(mtc->delay_var) != 0) { + size = SUBTLV_SIZE(&(mtc->delay_var.header)); + memcpy(tlvs, &(mtc->delay_var), size); + tlvs += size; + } + + /* TE_SUBTLV_PKT_LOSS */ + if (SUBTLV_TYPE(mtc->pkt_loss) != 0) { + size = SUBTLV_SIZE(&(mtc->pkt_loss.header)); + memcpy(tlvs, &(mtc->pkt_loss), size); + tlvs += size; + } + + /* TE_SUBTLV_RES_BW */ + if (SUBTLV_TYPE(mtc->res_bw) != 0) { + size = SUBTLV_SIZE(&(mtc->res_bw.header)); + memcpy(tlvs, &(mtc->res_bw), size); + tlvs += size; + } + + /* TE_SUBTLV_AVA_BW */ + if (SUBTLV_TYPE(mtc->ava_bw) != 0) { + size = SUBTLV_SIZE(&(mtc->ava_bw.header)); + memcpy(tlvs, &(mtc->ava_bw), size); + tlvs += size; + } + + /* TE_SUBTLV_USE_BW */ + if (SUBTLV_TYPE(mtc->use_bw) != 0) { + size = SUBTLV_SIZE(&(mtc->use_bw.header)); + memcpy(tlvs, &(mtc->use_bw), size); + tlvs += size; + } + + /* Update SubTLVs length */ + mtc->length = subtlvs_len(mtc); + + zlog_debug("ISIS MPLS-TE: Add %d bytes length SubTLVs", mtc->length); + + return mtc->length; } /* Compute total Sub-TLVs size */ -u_char -subtlvs_len (struct mpls_te_circuit *mtc) +u_char subtlvs_len(struct mpls_te_circuit *mtc) { - int length = 0; + int length = 0; - /* Sanity Check */ - if (mtc == NULL) - return 0; + /* Sanity Check */ + if (mtc == NULL) + return 0; - /* TE_SUBTLV_ADMIN_GRP */ - if (SUBTLV_TYPE(mtc->admin_grp) != 0) - length += SUBTLV_SIZE (&(mtc->admin_grp.header)); + /* TE_SUBTLV_ADMIN_GRP */ + if (SUBTLV_TYPE(mtc->admin_grp) != 0) + length += SUBTLV_SIZE(&(mtc->admin_grp.header)); - /* TE_SUBTLV_LLRI */ - if (SUBTLV_TYPE(mtc->llri) != 0) - length += SUBTLV_SIZE (&mtc->llri.header); + /* TE_SUBTLV_LLRI */ + if (SUBTLV_TYPE(mtc->llri) != 0) + length += SUBTLV_SIZE(&mtc->llri.header); - /* TE_SUBTLV_LCLIF_IPADDR */ - if (SUBTLV_TYPE(mtc->local_ipaddr) != 0) - length += SUBTLV_SIZE (&mtc->local_ipaddr.header); + /* TE_SUBTLV_LCLIF_IPADDR */ + if (SUBTLV_TYPE(mtc->local_ipaddr) != 0) + length += SUBTLV_SIZE(&mtc->local_ipaddr.header); - /* TE_SUBTLV_RMTIF_IPADDR */ - if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0) - length += SUBTLV_SIZE (&mtc->rmt_ipaddr.header); + /* TE_SUBTLV_RMTIF_IPADDR */ + if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0) + length += SUBTLV_SIZE(&mtc->rmt_ipaddr.header); - /* TE_SUBTLV_MAX_BW */ - if (SUBTLV_TYPE(mtc->max_bw) != 0) - length += SUBTLV_SIZE (&mtc->max_bw.header); + /* TE_SUBTLV_MAX_BW */ + if (SUBTLV_TYPE(mtc->max_bw) != 0) + length += SUBTLV_SIZE(&mtc->max_bw.header); - /* TE_SUBTLV_MAX_RSV_BW */ - if (SUBTLV_TYPE(mtc->max_rsv_bw) != 0) - length += SUBTLV_SIZE (&mtc->max_rsv_bw.header); + /* TE_SUBTLV_MAX_RSV_BW */ + if (SUBTLV_TYPE(mtc->max_rsv_bw) != 0) + length += SUBTLV_SIZE(&mtc->max_rsv_bw.header); - /* TE_SUBTLV_UNRSV_BW */ - if (SUBTLV_TYPE(mtc->unrsv_bw) != 0) - length += SUBTLV_SIZE (&mtc->unrsv_bw.header); + /* TE_SUBTLV_UNRSV_BW */ + if (SUBTLV_TYPE(mtc->unrsv_bw) != 0) + length += SUBTLV_SIZE(&mtc->unrsv_bw.header); - /* TE_SUBTLV_TE_METRIC */ - if (SUBTLV_TYPE(mtc->te_metric) != 0) - length += SUBTLV_SIZE (&mtc->te_metric.header); + /* TE_SUBTLV_TE_METRIC */ + if (SUBTLV_TYPE(mtc->te_metric) != 0) + length += SUBTLV_SIZE(&mtc->te_metric.header); - /* TE_SUBTLV_AV_DELAY */ - if (SUBTLV_TYPE(mtc->av_delay) != 0) - length += SUBTLV_SIZE (&mtc->av_delay.header); + /* TE_SUBTLV_AV_DELAY */ + if (SUBTLV_TYPE(mtc->av_delay) != 0) + length += SUBTLV_SIZE(&mtc->av_delay.header); - /* TE_SUBTLV_MM_DELAY */ - if (SUBTLV_TYPE(mtc->mm_delay) != 0) - length += SUBTLV_SIZE (&mtc->mm_delay.header); + /* TE_SUBTLV_MM_DELAY */ + if (SUBTLV_TYPE(mtc->mm_delay) != 0) + length += SUBTLV_SIZE(&mtc->mm_delay.header); - /* TE_SUBTLV_DELAY_VAR */ - if (SUBTLV_TYPE(mtc->delay_var) != 0) - length += SUBTLV_SIZE (&mtc->delay_var.header); + /* TE_SUBTLV_DELAY_VAR */ + if (SUBTLV_TYPE(mtc->delay_var) != 0) + length += SUBTLV_SIZE(&mtc->delay_var.header); - /* TE_SUBTLV_PKT_LOSS */ - if (SUBTLV_TYPE(mtc->pkt_loss) != 0) - length += SUBTLV_SIZE (&mtc->pkt_loss.header); + /* TE_SUBTLV_PKT_LOSS */ + if (SUBTLV_TYPE(mtc->pkt_loss) != 0) + length += SUBTLV_SIZE(&mtc->pkt_loss.header); - /* TE_SUBTLV_RES_BW */ - if (SUBTLV_TYPE(mtc->res_bw) != 0) - length += SUBTLV_SIZE (&mtc->res_bw.header); + /* TE_SUBTLV_RES_BW */ + if (SUBTLV_TYPE(mtc->res_bw) != 0) + length += SUBTLV_SIZE(&mtc->res_bw.header); - /* TE_SUBTLV_AVA_BW */ - if (SUBTLV_TYPE(mtc->ava_bw) != 0) - length += SUBTLV_SIZE (&mtc->ava_bw.header); + /* TE_SUBTLV_AVA_BW */ + if (SUBTLV_TYPE(mtc->ava_bw) != 0) + length += SUBTLV_SIZE(&mtc->ava_bw.header); - /* TE_SUBTLV_USE_BW */ - if (SUBTLV_TYPE(mtc->use_bw) != 0) - length += SUBTLV_SIZE (&mtc->use_bw.header); + /* TE_SUBTLV_USE_BW */ + if (SUBTLV_TYPE(mtc->use_bw) != 0) + length += SUBTLV_SIZE(&mtc->use_bw.header); - /* Check that length is lower than the MAXIMUM SUBTLV size i.e. 256 */ - if (length > MAX_SUBTLV_SIZE) - { - mtc->length = 0; - return 0; - } + /* Check that length is lower than the MAXIMUM SUBTLV size i.e. 256 */ + if (length > MAX_SUBTLV_SIZE) { + mtc->length = 0; + return 0; + } - mtc->length = (u_char)length; + mtc->length = (u_char)length; - return mtc->length; + return mtc->length; } /* Following are various functions to set MPLS TE parameters */ -static void -set_circuitparams_admin_grp (struct mpls_te_circuit *mtc, u_int32_t admingrp) +static void set_circuitparams_admin_grp(struct mpls_te_circuit *mtc, + u_int32_t admingrp) { - SUBTLV_TYPE(mtc->admin_grp) = TE_SUBTLV_ADMIN_GRP; - SUBTLV_LEN(mtc->admin_grp) = SUBTLV_DEF_SIZE; - mtc->admin_grp.value = htonl(admingrp); - return; + SUBTLV_TYPE(mtc->admin_grp) = TE_SUBTLV_ADMIN_GRP; + SUBTLV_LEN(mtc->admin_grp) = SUBTLV_DEF_SIZE; + mtc->admin_grp.value = htonl(admingrp); + return; } -static void __attribute__ ((unused)) -set_circuitparams_llri (struct mpls_te_circuit *mtc, u_int32_t local, u_int32_t remote) +static void __attribute__((unused)) +set_circuitparams_llri(struct mpls_te_circuit *mtc, u_int32_t local, + u_int32_t remote) { - SUBTLV_TYPE(mtc->llri) = TE_SUBTLV_LLRI; - SUBTLV_LEN(mtc->llri) = TE_SUBTLV_LLRI_SIZE; - mtc->llri.local = htonl(local); - mtc->llri.remote = htonl(remote); + SUBTLV_TYPE(mtc->llri) = TE_SUBTLV_LLRI; + SUBTLV_LEN(mtc->llri) = TE_SUBTLV_LLRI_SIZE; + mtc->llri.local = htonl(local); + mtc->llri.remote = htonl(remote); } -void -set_circuitparams_local_ipaddr (struct mpls_te_circuit *mtc, struct in_addr addr) +void set_circuitparams_local_ipaddr(struct mpls_te_circuit *mtc, + struct in_addr addr) { - SUBTLV_TYPE(mtc->local_ipaddr) = TE_SUBTLV_LOCAL_IPADDR; - SUBTLV_LEN(mtc->local_ipaddr) = SUBTLV_DEF_SIZE; - mtc->local_ipaddr.value.s_addr = addr.s_addr; - return; + SUBTLV_TYPE(mtc->local_ipaddr) = TE_SUBTLV_LOCAL_IPADDR; + SUBTLV_LEN(mtc->local_ipaddr) = SUBTLV_DEF_SIZE; + mtc->local_ipaddr.value.s_addr = addr.s_addr; + return; } -void -set_circuitparams_rmt_ipaddr (struct mpls_te_circuit *mtc, struct in_addr addr) +void set_circuitparams_rmt_ipaddr(struct mpls_te_circuit *mtc, + struct in_addr addr) { - SUBTLV_TYPE(mtc->rmt_ipaddr) = TE_SUBTLV_RMT_IPADDR; - SUBTLV_LEN(mtc->rmt_ipaddr) = SUBTLV_DEF_SIZE; - mtc->rmt_ipaddr.value.s_addr = addr.s_addr; - return; + SUBTLV_TYPE(mtc->rmt_ipaddr) = TE_SUBTLV_RMT_IPADDR; + SUBTLV_LEN(mtc->rmt_ipaddr) = SUBTLV_DEF_SIZE; + mtc->rmt_ipaddr.value.s_addr = addr.s_addr; + return; } -static void -set_circuitparams_max_bw (struct mpls_te_circuit *mtc, float fp) +static void set_circuitparams_max_bw(struct mpls_te_circuit *mtc, float fp) { - SUBTLV_TYPE(mtc->max_bw) = TE_SUBTLV_MAX_BW; - SUBTLV_LEN(mtc->max_bw) = SUBTLV_DEF_SIZE; - mtc->max_bw.value = htonf(fp); - return; + SUBTLV_TYPE(mtc->max_bw) = TE_SUBTLV_MAX_BW; + SUBTLV_LEN(mtc->max_bw) = SUBTLV_DEF_SIZE; + mtc->max_bw.value = htonf(fp); + return; } -static void -set_circuitparams_max_rsv_bw (struct mpls_te_circuit *mtc, float fp) +static void set_circuitparams_max_rsv_bw(struct mpls_te_circuit *mtc, float fp) { - SUBTLV_TYPE(mtc->max_rsv_bw) = TE_SUBTLV_MAX_RSV_BW; - SUBTLV_LEN(mtc->max_rsv_bw) = SUBTLV_DEF_SIZE; - mtc->max_rsv_bw.value = htonf(fp); - return; + SUBTLV_TYPE(mtc->max_rsv_bw) = TE_SUBTLV_MAX_RSV_BW; + SUBTLV_LEN(mtc->max_rsv_bw) = SUBTLV_DEF_SIZE; + mtc->max_rsv_bw.value = htonf(fp); + return; } -static void -set_circuitparams_unrsv_bw (struct mpls_te_circuit *mtc, int priority, float fp) +static void set_circuitparams_unrsv_bw(struct mpls_te_circuit *mtc, + int priority, float fp) { - /* Note that TLV-length field is the size of array. */ - SUBTLV_TYPE(mtc->unrsv_bw) = TE_SUBTLV_UNRSV_BW; - SUBTLV_LEN(mtc->unrsv_bw) = TE_SUBTLV_UNRSV_SIZE; - mtc->unrsv_bw.value[priority] = htonf(fp); - return; + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->unrsv_bw) = TE_SUBTLV_UNRSV_BW; + SUBTLV_LEN(mtc->unrsv_bw) = TE_SUBTLV_UNRSV_SIZE; + mtc->unrsv_bw.value[priority] = htonf(fp); + return; } -static void -set_circuitparams_te_metric (struct mpls_te_circuit *mtc, u_int32_t te_metric) +static void set_circuitparams_te_metric(struct mpls_te_circuit *mtc, + u_int32_t te_metric) { - SUBTLV_TYPE(mtc->te_metric) = TE_SUBTLV_TE_METRIC; - SUBTLV_LEN(mtc->te_metric) = TE_SUBTLV_TE_METRIC_SIZE; - mtc->te_metric.value[0] = (te_metric >> 16) & 0xFF; - mtc->te_metric.value[1] = (te_metric >> 8) & 0xFF; - mtc->te_metric.value[2] = te_metric & 0xFF; - return; + SUBTLV_TYPE(mtc->te_metric) = TE_SUBTLV_TE_METRIC; + SUBTLV_LEN(mtc->te_metric) = TE_SUBTLV_TE_METRIC_SIZE; + mtc->te_metric.value[0] = (te_metric >> 16) & 0xFF; + mtc->te_metric.value[1] = (te_metric >> 8) & 0xFF; + mtc->te_metric.value[2] = te_metric & 0xFF; + return; } -static void -set_circuitparams_inter_as (struct mpls_te_circuit *mtc, struct in_addr addr, u_int32_t as) +static void set_circuitparams_inter_as(struct mpls_te_circuit *mtc, + struct in_addr addr, u_int32_t as) { - /* Set the Remote ASBR IP address and then the associated AS number */ - SUBTLV_TYPE(mtc->rip) = TE_SUBTLV_RIP; - SUBTLV_LEN(mtc->rip) = SUBTLV_DEF_SIZE; - mtc->rip.value.s_addr = addr.s_addr; + /* Set the Remote ASBR IP address and then the associated AS number */ + SUBTLV_TYPE(mtc->rip) = TE_SUBTLV_RIP; + SUBTLV_LEN(mtc->rip) = SUBTLV_DEF_SIZE; + mtc->rip.value.s_addr = addr.s_addr; - SUBTLV_TYPE(mtc->ras) = TE_SUBTLV_RAS; - SUBTLV_LEN(mtc->ras) = SUBTLV_DEF_SIZE; - mtc->ras.value = htonl(as); + SUBTLV_TYPE(mtc->ras) = TE_SUBTLV_RAS; + SUBTLV_LEN(mtc->ras) = SUBTLV_DEF_SIZE; + mtc->ras.value = htonl(as); } -static void -unset_circuitparams_inter_as (struct mpls_te_circuit *mtc) +static void unset_circuitparams_inter_as(struct mpls_te_circuit *mtc) { - /* Reset the Remote ASBR IP address and then the associated AS number */ - SUBTLV_TYPE(mtc->rip) = 0; - SUBTLV_LEN(mtc->rip) = 0; - mtc->rip.value.s_addr = 0; + /* Reset the Remote ASBR IP address and then the associated AS number */ + SUBTLV_TYPE(mtc->rip) = 0; + SUBTLV_LEN(mtc->rip) = 0; + mtc->rip.value.s_addr = 0; - SUBTLV_TYPE(mtc->ras) = 0; - SUBTLV_LEN(mtc->ras) = 0; - mtc->ras.value = 0; + SUBTLV_TYPE(mtc->ras) = 0; + SUBTLV_LEN(mtc->ras) = 0; + mtc->ras.value = 0; } -static void -set_circuitparams_av_delay (struct mpls_te_circuit *mtc, u_int32_t delay, u_char anormal) +static void set_circuitparams_av_delay(struct mpls_te_circuit *mtc, + u_int32_t delay, u_char anormal) { - u_int32_t tmp; - /* Note that TLV-length field is the size of array. */ - SUBTLV_TYPE(mtc->av_delay) = TE_SUBTLV_AV_DELAY; - SUBTLV_LEN(mtc->av_delay) = SUBTLV_DEF_SIZE; - tmp = delay & TE_EXT_MASK; - if (anormal) - tmp |= TE_EXT_ANORMAL; - mtc->av_delay.value = htonl(tmp); - return; + u_int32_t tmp; + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->av_delay) = TE_SUBTLV_AV_DELAY; + SUBTLV_LEN(mtc->av_delay) = SUBTLV_DEF_SIZE; + tmp = delay & TE_EXT_MASK; + if (anormal) + tmp |= TE_EXT_ANORMAL; + mtc->av_delay.value = htonl(tmp); + return; } -static void -set_circuitparams_mm_delay (struct mpls_te_circuit *mtc, u_int32_t low, u_int32_t high, u_char anormal) +static void set_circuitparams_mm_delay(struct mpls_te_circuit *mtc, + u_int32_t low, u_int32_t high, + u_char anormal) { - u_int32_t tmp; - /* Note that TLV-length field is the size of array. */ - SUBTLV_TYPE(mtc->mm_delay) = TE_SUBTLV_MM_DELAY; - SUBTLV_LEN(mtc->mm_delay) = TE_SUBTLV_MM_DELAY_SIZE; - tmp = low & TE_EXT_MASK; - if (anormal) - tmp |= TE_EXT_ANORMAL; - mtc->mm_delay.low = htonl(tmp); - mtc->mm_delay.high = htonl(high); - return; + u_int32_t tmp; + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->mm_delay) = TE_SUBTLV_MM_DELAY; + SUBTLV_LEN(mtc->mm_delay) = TE_SUBTLV_MM_DELAY_SIZE; + tmp = low & TE_EXT_MASK; + if (anormal) + tmp |= TE_EXT_ANORMAL; + mtc->mm_delay.low = htonl(tmp); + mtc->mm_delay.high = htonl(high); + return; } -static void -set_circuitparams_delay_var (struct mpls_te_circuit *mtc, u_int32_t jitter) +static void set_circuitparams_delay_var(struct mpls_te_circuit *mtc, + u_int32_t jitter) { - /* Note that TLV-length field is the size of array. */ - SUBTLV_TYPE(mtc->delay_var) = TE_SUBTLV_DELAY_VAR; - SUBTLV_LEN(mtc->delay_var) = SUBTLV_DEF_SIZE; - mtc->delay_var.value = htonl(jitter & TE_EXT_MASK); - return; + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->delay_var) = TE_SUBTLV_DELAY_VAR; + SUBTLV_LEN(mtc->delay_var) = SUBTLV_DEF_SIZE; + mtc->delay_var.value = htonl(jitter & TE_EXT_MASK); + return; } -static void -set_circuitparams_pkt_loss (struct mpls_te_circuit *mtc, u_int32_t loss, u_char anormal) +static void set_circuitparams_pkt_loss(struct mpls_te_circuit *mtc, + u_int32_t loss, u_char anormal) { - u_int32_t tmp; - /* Note that TLV-length field is the size of array. */ - SUBTLV_TYPE(mtc->pkt_loss) = TE_SUBTLV_PKT_LOSS; - SUBTLV_LEN(mtc->pkt_loss) = SUBTLV_DEF_SIZE; - tmp = loss & TE_EXT_MASK; - if (anormal) - tmp |= TE_EXT_ANORMAL; - mtc->pkt_loss.value = htonl(tmp); - return; + u_int32_t tmp; + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->pkt_loss) = TE_SUBTLV_PKT_LOSS; + SUBTLV_LEN(mtc->pkt_loss) = SUBTLV_DEF_SIZE; + tmp = loss & TE_EXT_MASK; + if (anormal) + tmp |= TE_EXT_ANORMAL; + mtc->pkt_loss.value = htonl(tmp); + return; } -static void -set_circuitparams_res_bw (struct mpls_te_circuit *mtc, float fp) +static void set_circuitparams_res_bw(struct mpls_te_circuit *mtc, float fp) { - /* Note that TLV-length field is the size of array. */ - SUBTLV_TYPE(mtc->res_bw) = TE_SUBTLV_RES_BW; - SUBTLV_LEN(mtc->res_bw) = SUBTLV_DEF_SIZE; - mtc->res_bw.value = htonf(fp); - return; + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->res_bw) = TE_SUBTLV_RES_BW; + SUBTLV_LEN(mtc->res_bw) = SUBTLV_DEF_SIZE; + mtc->res_bw.value = htonf(fp); + return; } -static void -set_circuitparams_ava_bw (struct mpls_te_circuit *mtc, float fp) +static void set_circuitparams_ava_bw(struct mpls_te_circuit *mtc, float fp) { - /* Note that TLV-length field is the size of array. */ - SUBTLV_TYPE(mtc->ava_bw) = TE_SUBTLV_AVA_BW; - SUBTLV_LEN(mtc->ava_bw) = SUBTLV_DEF_SIZE; - mtc->ava_bw.value = htonf(fp); - return; + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->ava_bw) = TE_SUBTLV_AVA_BW; + SUBTLV_LEN(mtc->ava_bw) = SUBTLV_DEF_SIZE; + mtc->ava_bw.value = htonf(fp); + return; } -static void -set_circuitparams_use_bw (struct mpls_te_circuit *mtc, float fp) +static void set_circuitparams_use_bw(struct mpls_te_circuit *mtc, float fp) { - /* Note that TLV-length field is the size of array. */ - SUBTLV_TYPE(mtc->use_bw) = TE_SUBTLV_USE_BW; - SUBTLV_LEN(mtc->use_bw) = SUBTLV_DEF_SIZE; - mtc->use_bw.value = htonf(fp); - return; + /* Note that TLV-length field is the size of array. */ + SUBTLV_TYPE(mtc->use_bw) = TE_SUBTLV_USE_BW; + SUBTLV_LEN(mtc->use_bw) = SUBTLV_DEF_SIZE; + mtc->use_bw.value = htonf(fp); + return; } /* Main initialization / update function of the MPLS TE Circuit context */ /* Call when interface TE Link parameters are modified */ -void -isis_link_params_update (struct isis_circuit *circuit, struct interface *ifp) +void isis_link_params_update(struct isis_circuit *circuit, + struct interface *ifp) { - int i; - struct prefix_ipv4 *addr; - struct mpls_te_circuit *mtc; - - /* Sanity Check */ - if ((circuit == NULL) || (ifp == NULL)) - return; - - zlog_info ("MPLS-TE: Initialize circuit parameters for interface %s", ifp->name); - - /* Check if MPLS TE Circuit context has not been already created */ - if (circuit->mtc == NULL) - circuit->mtc = mpls_te_circuit_new(); - - mtc = circuit->mtc; - - /* Fulfil MTC TLV from ifp TE Link parameters */ - if (HAS_LINK_PARAMS(ifp)) - { - mtc->status = enable; - /* STD_TE metrics */ - if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP)) - set_circuitparams_admin_grp (mtc, ifp->link_params->admin_grp); - else - SUBTLV_TYPE(mtc->admin_grp) = 0; - - /* If not already set, register local IP addr from ip_addr list if it exists */ - if (SUBTLV_TYPE(mtc->local_ipaddr) == 0) - { - if (circuit->ip_addrs != NULL && listcount(circuit->ip_addrs) != 0) - { - addr = (struct prefix_ipv4 *)listgetdata ((struct listnode *)listhead (circuit->ip_addrs)); - set_circuitparams_local_ipaddr (mtc, addr->prefix); - } - } - - /* If not already set, try to determine Remote IP addr if circuit is P2P */ - if ((SUBTLV_TYPE(mtc->rmt_ipaddr) == 0) && (circuit->circ_type == CIRCUIT_T_P2P)) - { - struct isis_adjacency *adj = circuit->u.p2p.neighbor; - if (adj->ipv4_addrs != NULL && listcount(adj->ipv4_addrs) != 0) - { - struct in_addr *ip_addr; - ip_addr = (struct in_addr *)listgetdata ((struct listnode *)listhead (adj->ipv4_addrs)); - set_circuitparams_rmt_ipaddr (mtc, *ip_addr); - } - } - - if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW)) - set_circuitparams_max_bw (mtc, ifp->link_params->max_bw); - else - SUBTLV_TYPE(mtc->max_bw) = 0; - - if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW)) - set_circuitparams_max_rsv_bw (mtc, ifp->link_params->max_rsv_bw); - else - SUBTLV_TYPE(mtc->max_rsv_bw) = 0; - - if (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW)) - for (i = 0; i < MAX_CLASS_TYPE; i++) - set_circuitparams_unrsv_bw (mtc, i, ifp->link_params->unrsv_bw[i]); - else - SUBTLV_TYPE(mtc->unrsv_bw) = 0; - - if (IS_PARAM_SET(ifp->link_params, LP_TE_METRIC)) - set_circuitparams_te_metric(mtc, ifp->link_params->te_metric); - else - SUBTLV_TYPE(mtc->te_metric) = 0; - - /* TE metric Extensions */ - if (IS_PARAM_SET(ifp->link_params, LP_DELAY)) - set_circuitparams_av_delay(mtc, ifp->link_params->av_delay, 0); - else - SUBTLV_TYPE(mtc->av_delay) = 0; - - if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY)) - set_circuitparams_mm_delay(mtc, ifp->link_params->min_delay, ifp->link_params->max_delay, 0); - else - SUBTLV_TYPE(mtc->mm_delay) = 0; - - if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR)) - set_circuitparams_delay_var(mtc, ifp->link_params->delay_var); - else - SUBTLV_TYPE(mtc->delay_var) = 0; - - if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS)) - set_circuitparams_pkt_loss(mtc, ifp->link_params->pkt_loss, 0); - else - SUBTLV_TYPE(mtc->pkt_loss) = 0; - - if (IS_PARAM_SET(ifp->link_params, LP_RES_BW)) - set_circuitparams_res_bw(mtc, ifp->link_params->res_bw); - else - SUBTLV_TYPE(mtc->res_bw) = 0; - - if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW)) - set_circuitparams_ava_bw(mtc, ifp->link_params->ava_bw); - else - SUBTLV_TYPE(mtc->ava_bw) = 0; - - if (IS_PARAM_SET(ifp->link_params, LP_USE_BW)) - set_circuitparams_use_bw(mtc, ifp->link_params->use_bw); - else - SUBTLV_TYPE(mtc->use_bw) = 0; - - /* INTER_AS */ - if (IS_PARAM_SET(ifp->link_params, LP_RMT_AS)) - set_circuitparams_inter_as(mtc, ifp->link_params->rmt_ip, ifp->link_params->rmt_as); - else - /* reset inter-as TE params */ - unset_circuitparams_inter_as (mtc); - - /* Compute total length of SUB TLVs */ - mtc->length = subtlvs_len(mtc); - - } - else - mtc->status = disable; - - /* Finally Update LSP */ + int i; + struct prefix_ipv4 *addr; + struct mpls_te_circuit *mtc; + + /* Sanity Check */ + if ((circuit == NULL) || (ifp == NULL)) + return; + + zlog_info("MPLS-TE: Initialize circuit parameters for interface %s", + ifp->name); + + /* Check if MPLS TE Circuit context has not been already created */ + if (circuit->mtc == NULL) + circuit->mtc = mpls_te_circuit_new(); + + mtc = circuit->mtc; + + /* Fulfil MTC TLV from ifp TE Link parameters */ + if (HAS_LINK_PARAMS(ifp)) { + mtc->status = enable; + /* STD_TE metrics */ + if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP)) + set_circuitparams_admin_grp( + mtc, ifp->link_params->admin_grp); + else + SUBTLV_TYPE(mtc->admin_grp) = 0; + + /* If not already set, register local IP addr from ip_addr list + * if it exists */ + if (SUBTLV_TYPE(mtc->local_ipaddr) == 0) { + if (circuit->ip_addrs != NULL + && listcount(circuit->ip_addrs) != 0) { + addr = (struct prefix_ipv4 *)listgetdata( + (struct listnode *)listhead( + circuit->ip_addrs)); + set_circuitparams_local_ipaddr(mtc, + addr->prefix); + } + } + + /* If not already set, try to determine Remote IP addr if + * circuit is P2P */ + if ((SUBTLV_TYPE(mtc->rmt_ipaddr) == 0) + && (circuit->circ_type == CIRCUIT_T_P2P)) { + struct isis_adjacency *adj = circuit->u.p2p.neighbor; + if (adj->ipv4_addrs != NULL + && listcount(adj->ipv4_addrs) != 0) { + struct in_addr *ip_addr; + ip_addr = (struct in_addr *)listgetdata( + (struct listnode *)listhead( + adj->ipv4_addrs)); + set_circuitparams_rmt_ipaddr(mtc, *ip_addr); + } + } + + if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW)) + set_circuitparams_max_bw(mtc, ifp->link_params->max_bw); + else + SUBTLV_TYPE(mtc->max_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW)) + set_circuitparams_max_rsv_bw( + mtc, ifp->link_params->max_rsv_bw); + else + SUBTLV_TYPE(mtc->max_rsv_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW)) + for (i = 0; i < MAX_CLASS_TYPE; i++) + set_circuitparams_unrsv_bw( + mtc, i, ifp->link_params->unrsv_bw[i]); + else + SUBTLV_TYPE(mtc->unrsv_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_TE_METRIC)) + set_circuitparams_te_metric( + mtc, ifp->link_params->te_metric); + else + SUBTLV_TYPE(mtc->te_metric) = 0; + + /* TE metric Extensions */ + if (IS_PARAM_SET(ifp->link_params, LP_DELAY)) + set_circuitparams_av_delay( + mtc, ifp->link_params->av_delay, 0); + else + SUBTLV_TYPE(mtc->av_delay) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY)) + set_circuitparams_mm_delay( + mtc, ifp->link_params->min_delay, + ifp->link_params->max_delay, 0); + else + SUBTLV_TYPE(mtc->mm_delay) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR)) + set_circuitparams_delay_var( + mtc, ifp->link_params->delay_var); + else + SUBTLV_TYPE(mtc->delay_var) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS)) + set_circuitparams_pkt_loss( + mtc, ifp->link_params->pkt_loss, 0); + else + SUBTLV_TYPE(mtc->pkt_loss) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_RES_BW)) + set_circuitparams_res_bw(mtc, ifp->link_params->res_bw); + else + SUBTLV_TYPE(mtc->res_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW)) + set_circuitparams_ava_bw(mtc, ifp->link_params->ava_bw); + else + SUBTLV_TYPE(mtc->ava_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_USE_BW)) + set_circuitparams_use_bw(mtc, ifp->link_params->use_bw); + else + SUBTLV_TYPE(mtc->use_bw) = 0; + + /* INTER_AS */ + if (IS_PARAM_SET(ifp->link_params, LP_RMT_AS)) + set_circuitparams_inter_as(mtc, + ifp->link_params->rmt_ip, + ifp->link_params->rmt_as); + else + /* reset inter-as TE params */ + unset_circuitparams_inter_as(mtc); + + /* Compute total length of SUB TLVs */ + mtc->length = subtlvs_len(mtc); + + } else + mtc->status = disable; + +/* Finally Update LSP */ #if 0 if (IS_MPLS_TE(isisMplsTE) && circuit->area) lsp_regenerate_schedule (circuit->area, circuit->is_type, 0); #endif - return; + return; } -void -isis_mpls_te_update (struct interface *ifp) +void isis_mpls_te_update(struct interface *ifp) { - struct isis_circuit *circuit; + struct isis_circuit *circuit; - /* Sanity Check */ - if (ifp == NULL) - return; + /* Sanity Check */ + if (ifp == NULL) + return; - /* Get circuit context from interface */ - if ((circuit = circuit_scan_by_ifp(ifp)) == NULL) - return; + /* Get circuit context from interface */ + if ((circuit = circuit_scan_by_ifp(ifp)) == NULL) + return; - /* Update TE TLVs ... */ - isis_link_params_update(circuit, ifp); + /* Update TE TLVs ... */ + isis_link_params_update(circuit, ifp); - /* ... and LSP */ - if (IS_MPLS_TE(isisMplsTE) && circuit->area) - lsp_regenerate_schedule (circuit->area, circuit->is_type, 0); + /* ... and LSP */ + if (IS_MPLS_TE(isisMplsTE) && circuit->area) + lsp_regenerate_schedule(circuit->area, circuit->is_type, 0); - return; + return; } /*------------------------------------------------------------------------* * Followings are vty session control functions. *------------------------------------------------------------------------*/ -static u_char -show_vty_subtlv_admin_grp (struct vty *vty, struct te_subtlv_admin_grp *tlv) +static u_char show_vty_subtlv_admin_grp(struct vty *vty, + struct te_subtlv_admin_grp *tlv) { - if (vty != NULL) - vty_out (vty, " Administrative Group: 0x%x\n", - (u_int32_t)ntohl(tlv->value)); - else - zlog_debug (" Administrative Group: 0x%x", - (u_int32_t) ntohl (tlv->value)); + if (vty != NULL) + vty_out(vty, " Administrative Group: 0x%x\n", + (u_int32_t)ntohl(tlv->value)); + else + zlog_debug(" Administrative Group: 0x%x", + (u_int32_t)ntohl(tlv->value)); - return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char -show_vty_subtlv_llri (struct vty *vty, struct te_subtlv_llri *tlv) +static u_char show_vty_subtlv_llri(struct vty *vty, struct te_subtlv_llri *tlv) { - if (vty != NULL) - { - vty_out (vty, " Link Local ID: %d\n",(u_int32_t)ntohl(tlv->local)); - vty_out (vty, " Link Remote ID: %d\n", - (u_int32_t)ntohl(tlv->remote)); - } - else - { - zlog_debug (" Link Local ID: %d", (u_int32_t) ntohl (tlv->local)); - zlog_debug (" Link Remote ID: %d", (u_int32_t) ntohl (tlv->remote)); - } - - return (SUBTLV_HDR_SIZE + TE_SUBTLV_LLRI_SIZE); + if (vty != NULL) { + vty_out(vty, " Link Local ID: %d\n", + (u_int32_t)ntohl(tlv->local)); + vty_out(vty, " Link Remote ID: %d\n", + (u_int32_t)ntohl(tlv->remote)); + } else { + zlog_debug(" Link Local ID: %d", + (u_int32_t)ntohl(tlv->local)); + zlog_debug(" Link Remote ID: %d", + (u_int32_t)ntohl(tlv->remote)); + } + + return (SUBTLV_HDR_SIZE + TE_SUBTLV_LLRI_SIZE); } -static u_char -show_vty_subtlv_local_ipaddr (struct vty *vty, struct te_subtlv_local_ipaddr *tlv) +static u_char show_vty_subtlv_local_ipaddr(struct vty *vty, + struct te_subtlv_local_ipaddr *tlv) { - if (vty != NULL) - vty_out (vty, " Local Interface IP Address(es): %s\n", - inet_ntoa(tlv->value)); - else - zlog_debug (" Local Interface IP Address(es): %s", inet_ntoa (tlv->value)); - - return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); + if (vty != NULL) + vty_out(vty, " Local Interface IP Address(es): %s\n", + inet_ntoa(tlv->value)); + else + zlog_debug(" Local Interface IP Address(es): %s", + inet_ntoa(tlv->value)); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char -show_vty_subtlv_rmt_ipaddr (struct vty *vty, struct te_subtlv_rmt_ipaddr *tlv) +static u_char show_vty_subtlv_rmt_ipaddr(struct vty *vty, + struct te_subtlv_rmt_ipaddr *tlv) { - if (vty != NULL) - vty_out (vty, " Remote Interface IP Address(es): %s\n", - inet_ntoa(tlv->value)); - else - zlog_debug (" Remote Interface IP Address(es): %s", inet_ntoa (tlv->value)); - - return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); + if (vty != NULL) + vty_out(vty, " Remote Interface IP Address(es): %s\n", + inet_ntoa(tlv->value)); + else + zlog_debug(" Remote Interface IP Address(es): %s", + inet_ntoa(tlv->value)); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char -show_vty_subtlv_max_bw (struct vty *vty, struct te_subtlv_max_bw *tlv) +static u_char show_vty_subtlv_max_bw(struct vty *vty, + struct te_subtlv_max_bw *tlv) { - float fval; + float fval; - fval = ntohf (tlv->value); + fval = ntohf(tlv->value); - if (vty != NULL) - vty_out (vty, " Maximum Bandwidth: %g (Bytes/sec)\n", fval); - else - zlog_debug (" Maximum Bandwidth: %g (Bytes/sec)", fval); + if (vty != NULL) + vty_out(vty, " Maximum Bandwidth: %g (Bytes/sec)\n", fval); + else + zlog_debug(" Maximum Bandwidth: %g (Bytes/sec)", fval); - return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char -show_vty_subtlv_max_rsv_bw (struct vty *vty, struct te_subtlv_max_rsv_bw *tlv) +static u_char show_vty_subtlv_max_rsv_bw(struct vty *vty, + struct te_subtlv_max_rsv_bw *tlv) { - float fval; + float fval; - fval = ntohf (tlv->value); + fval = ntohf(tlv->value); - if (vty != NULL) - vty_out (vty, " Maximum Reservable Bandwidth: %g (Bytes/sec)\n",fval); - else - zlog_debug (" Maximum Reservable Bandwidth: %g (Bytes/sec)", fval); + if (vty != NULL) + vty_out(vty, + " Maximum Reservable Bandwidth: %g (Bytes/sec)\n", + fval); + else + zlog_debug(" Maximum Reservable Bandwidth: %g (Bytes/sec)", + fval); - return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char -show_vty_subtlv_unrsv_bw (struct vty *vty, struct te_subtlv_unrsv_bw *tlv) +static u_char show_vty_subtlv_unrsv_bw(struct vty *vty, + struct te_subtlv_unrsv_bw *tlv) { - float fval1, fval2; - int i; - - if (vty != NULL) - vty_out (vty, " Unreserved Bandwidth:\n"); - else - zlog_debug (" Unreserved Bandwidth:"); - - for (i = 0; i < MAX_CLASS_TYPE; i+=2) - { - fval1 = ntohf (tlv->value[i]); - fval2 = ntohf (tlv->value[i+1]); - if (vty != NULL) - vty_out (vty, " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n", i, fval1, i+1, - fval2); - else - zlog_debug (" [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)", i, fval1, i+1, fval2); - } - - return (SUBTLV_HDR_SIZE + TE_SUBTLV_UNRSV_SIZE); + float fval1, fval2; + int i; + + if (vty != NULL) + vty_out(vty, " Unreserved Bandwidth:\n"); + else + zlog_debug(" Unreserved Bandwidth:"); + + for (i = 0; i < MAX_CLASS_TYPE; i += 2) { + fval1 = ntohf(tlv->value[i]); + fval2 = ntohf(tlv->value[i + 1]); + if (vty != NULL) + vty_out(vty, + " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n", + i, fval1, i + 1, fval2); + else + zlog_debug( + " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)", + i, fval1, i + 1, fval2); + } + + return (SUBTLV_HDR_SIZE + TE_SUBTLV_UNRSV_SIZE); } -static u_char -show_vty_subtlv_te_metric (struct vty *vty, struct te_subtlv_te_metric *tlv) +static u_char show_vty_subtlv_te_metric(struct vty *vty, + struct te_subtlv_te_metric *tlv) { - u_int32_t te_metric; + u_int32_t te_metric; - te_metric = tlv->value[2] | tlv->value[1] << 8 | tlv->value[0] << 16; - if (vty != NULL) - vty_out (vty, " Traffic Engineering Metric: %u\n", te_metric); - else - zlog_debug (" Traffic Engineering Metric: %u", te_metric); + te_metric = tlv->value[2] | tlv->value[1] << 8 | tlv->value[0] << 16; + if (vty != NULL) + vty_out(vty, " Traffic Engineering Metric: %u\n", te_metric); + else + zlog_debug(" Traffic Engineering Metric: %u", te_metric); - return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char -show_vty_subtlv_ras (struct vty *vty, struct te_subtlv_ras *tlv) +static u_char show_vty_subtlv_ras(struct vty *vty, struct te_subtlv_ras *tlv) { - if (vty != NULL) - vty_out (vty, " Inter-AS TE Remote AS number: %u\n", - ntohl(tlv->value)); - else - zlog_debug (" Inter-AS TE Remote AS number: %u", ntohl (tlv->value)); - - return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); + if (vty != NULL) + vty_out(vty, " Inter-AS TE Remote AS number: %u\n", + ntohl(tlv->value)); + else + zlog_debug(" Inter-AS TE Remote AS number: %u", + ntohl(tlv->value)); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char -show_vty_subtlv_rip (struct vty *vty, struct te_subtlv_rip *tlv) +static u_char show_vty_subtlv_rip(struct vty *vty, struct te_subtlv_rip *tlv) { - if (vty != NULL) - vty_out (vty, " Inter-AS TE Remote ASBR IP address: %s\n", - inet_ntoa(tlv->value)); - else - zlog_debug (" Inter-AS TE Remote ASBR IP address: %s", inet_ntoa (tlv->value)); - - return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); + if (vty != NULL) + vty_out(vty, " Inter-AS TE Remote ASBR IP address: %s\n", + inet_ntoa(tlv->value)); + else + zlog_debug(" Inter-AS TE Remote ASBR IP address: %s", + inet_ntoa(tlv->value)); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char -show_vty_subtlv_av_delay (struct vty *vty, struct te_subtlv_av_delay *tlv) +static u_char show_vty_subtlv_av_delay(struct vty *vty, + struct te_subtlv_av_delay *tlv) { - u_int32_t delay; - u_int32_t A; + u_int32_t delay; + u_int32_t A; - delay = (u_int32_t) ntohl (tlv->value) & TE_EXT_MASK; - A = (u_int32_t) ntohl (tlv->value) & TE_EXT_ANORMAL; + delay = (u_int32_t)ntohl(tlv->value) & TE_EXT_MASK; + A = (u_int32_t)ntohl(tlv->value) & TE_EXT_ANORMAL; - if (vty != NULL) - vty_out (vty, " %s Average Link Delay: %d (micro-sec)\n", A ? "Anomalous" : "Normal", - delay); - else - zlog_debug (" %s Average Link Delay: %d (micro-sec)", A ? "Anomalous" : "Normal", delay); + if (vty != NULL) + vty_out(vty, " %s Average Link Delay: %d (micro-sec)\n", + A ? "Anomalous" : "Normal", delay); + else + zlog_debug(" %s Average Link Delay: %d (micro-sec)", + A ? "Anomalous" : "Normal", delay); - return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char -show_vty_subtlv_mm_delay (struct vty *vty, struct te_subtlv_mm_delay *tlv) +static u_char show_vty_subtlv_mm_delay(struct vty *vty, + struct te_subtlv_mm_delay *tlv) { - u_int32_t low, high; - u_int32_t A; + u_int32_t low, high; + u_int32_t A; - low = (u_int32_t) ntohl (tlv->low) & TE_EXT_MASK; - A = (u_int32_t) ntohl (tlv->low) & TE_EXT_ANORMAL; - high = (u_int32_t) ntohl (tlv->high) & TE_EXT_MASK; + low = (u_int32_t)ntohl(tlv->low) & TE_EXT_MASK; + A = (u_int32_t)ntohl(tlv->low) & TE_EXT_ANORMAL; + high = (u_int32_t)ntohl(tlv->high) & TE_EXT_MASK; - if (vty != NULL) - vty_out (vty, " %s Min/Max Link Delay: %d / %d (micro-sec)\n", A ? "Anomalous" : "Normal", low, - high); - else - zlog_debug (" %s Min/Max Link Delay: %d / %d (micro-sec)", A ? "Anomalous" : "Normal", low, high); + if (vty != NULL) + vty_out(vty, " %s Min/Max Link Delay: %d / %d (micro-sec)\n", + A ? "Anomalous" : "Normal", low, high); + else + zlog_debug(" %s Min/Max Link Delay: %d / %d (micro-sec)", + A ? "Anomalous" : "Normal", low, high); - return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char -show_vty_subtlv_delay_var (struct vty *vty, struct te_subtlv_delay_var *tlv) +static u_char show_vty_subtlv_delay_var(struct vty *vty, + struct te_subtlv_delay_var *tlv) { - u_int32_t jitter; + u_int32_t jitter; - jitter = (u_int32_t) ntohl (tlv->value) & TE_EXT_MASK; + jitter = (u_int32_t)ntohl(tlv->value) & TE_EXT_MASK; - if (vty != NULL) - vty_out (vty, " Delay Variation: %d (micro-sec)\n", jitter); - else - zlog_debug (" Delay Variation: %d (micro-sec)", jitter); + if (vty != NULL) + vty_out(vty, " Delay Variation: %d (micro-sec)\n", jitter); + else + zlog_debug(" Delay Variation: %d (micro-sec)", jitter); - return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char -show_vty_subtlv_pkt_loss (struct vty *vty, struct te_subtlv_pkt_loss *tlv) +static u_char show_vty_subtlv_pkt_loss(struct vty *vty, + struct te_subtlv_pkt_loss *tlv) { - u_int32_t loss; - u_int32_t A; - float fval; - - loss = (u_int32_t) ntohl (tlv->value) & TE_EXT_MASK; - fval = (float) (loss * LOSS_PRECISION); - A = (u_int32_t) ntohl (tlv->value) & TE_EXT_ANORMAL; - - if (vty != NULL) - vty_out (vty, " %s Link Packet Loss: %g (%%)\n", A ? "Anomalous" : "Normal", - fval); - else - zlog_debug (" %s Link Packet Loss: %g (%%)", A ? "Anomalous" : "Normal", fval); - - return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); + u_int32_t loss; + u_int32_t A; + float fval; + + loss = (u_int32_t)ntohl(tlv->value) & TE_EXT_MASK; + fval = (float)(loss * LOSS_PRECISION); + A = (u_int32_t)ntohl(tlv->value) & TE_EXT_ANORMAL; + + if (vty != NULL) + vty_out(vty, " %s Link Packet Loss: %g (%%)\n", + A ? "Anomalous" : "Normal", fval); + else + zlog_debug(" %s Link Packet Loss: %g (%%)", + A ? "Anomalous" : "Normal", fval); + + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char -show_vty_subtlv_res_bw (struct vty *vty, struct te_subtlv_res_bw *tlv) +static u_char show_vty_subtlv_res_bw(struct vty *vty, + struct te_subtlv_res_bw *tlv) { - float fval; + float fval; - fval = ntohf(tlv->value); + fval = ntohf(tlv->value); - if (vty != NULL) - vty_out (vty, " Unidirectional Residual Bandwidth: %g (Bytes/sec)\n", - fval); - else - zlog_debug (" Unidirectional Residual Bandwidth: %g (Bytes/sec)", fval); + if (vty != NULL) + vty_out(vty, + " Unidirectional Residual Bandwidth: %g (Bytes/sec)\n", + fval); + else + zlog_debug( + " Unidirectional Residual Bandwidth: %g (Bytes/sec)", + fval); - return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char -show_vty_subtlv_ava_bw (struct vty *vty, struct te_subtlv_ava_bw *tlv) +static u_char show_vty_subtlv_ava_bw(struct vty *vty, + struct te_subtlv_ava_bw *tlv) { - float fval; + float fval; - fval = ntohf (tlv->value); + fval = ntohf(tlv->value); - if (vty != NULL) - vty_out (vty, " Unidirectional Available Bandwidth: %g (Bytes/sec)\n", - fval); - else - zlog_debug (" Unidirectional Available Bandwidth: %g (Bytes/sec)", fval); + if (vty != NULL) + vty_out(vty, + " Unidirectional Available Bandwidth: %g (Bytes/sec)\n", + fval); + else + zlog_debug( + " Unidirectional Available Bandwidth: %g (Bytes/sec)", + fval); - return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char -show_vty_subtlv_use_bw (struct vty *vty, struct te_subtlv_use_bw *tlv) +static u_char show_vty_subtlv_use_bw(struct vty *vty, + struct te_subtlv_use_bw *tlv) { - float fval; + float fval; - fval = ntohf (tlv->value); + fval = ntohf(tlv->value); - if (vty != NULL) - vty_out (vty, " Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n", - fval); - else - zlog_debug (" Unidirectional Utilized Bandwidth: %g (Bytes/sec)", fval); + if (vty != NULL) + vty_out(vty, + " Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n", + fval); + else + zlog_debug( + " Unidirectional Utilized Bandwidth: %g (Bytes/sec)", + fval); - return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); + return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE); } -static u_char -show_vty_unknown_tlv (struct vty *vty, struct subtlv_header *tlvh) +static u_char show_vty_unknown_tlv(struct vty *vty, struct subtlv_header *tlvh) { - int i, rtn = 1; - u_char *v = (u_char *)tlvh; - - if (vty != NULL) - { - if (tlvh->length != 0) - { - vty_out (vty, " Unknown TLV: [type(%#.2x), length(%#.2x)]\n", - tlvh->type, tlvh->length); - vty_out(vty, " Dump: [00]"); - rtn = 1; /* initialize end of line counter */ - for (i = 0; i < tlvh->length; i++) - { - vty_out (vty, " %#.2x", v[i]); - if (rtn == 8) - { - vty_out (vty, "\n [%.2x]", i + 1); - rtn = 1; - } - else - rtn++; - } - vty_out (vty, "\n"); - } - else - vty_out (vty, " Unknown TLV: [type(%#.2x), length(%#.2x)]\n", - tlvh->type, tlvh->length); - } - else - { - zlog_debug (" Unknown TLV: [type(%#.2x), length(%#.2x)]", - tlvh->type, tlvh->length); - } - - return SUBTLV_SIZE(tlvh); + int i, rtn = 1; + u_char *v = (u_char *)tlvh; + + if (vty != NULL) { + if (tlvh->length != 0) { + vty_out(vty, + " Unknown TLV: [type(%#.2x), length(%#.2x)]\n", + tlvh->type, tlvh->length); + vty_out(vty, " Dump: [00]"); + rtn = 1; /* initialize end of line counter */ + for (i = 0; i < tlvh->length; i++) { + vty_out(vty, " %#.2x", v[i]); + if (rtn == 8) { + vty_out(vty, "\n [%.2x]", + i + 1); + rtn = 1; + } else + rtn++; + } + vty_out(vty, "\n"); + } else + vty_out(vty, + " Unknown TLV: [type(%#.2x), length(%#.2x)]\n", + tlvh->type, tlvh->length); + } else { + zlog_debug(" Unknown TLV: [type(%#.2x), length(%#.2x)]", + tlvh->type, tlvh->length); + } + + return SUBTLV_SIZE(tlvh); } /* Main Show function */ -void -mpls_te_print_detail(struct vty *vty, struct te_is_neigh *te) +void mpls_te_print_detail(struct vty *vty, struct te_is_neigh *te) { - struct subtlv_header *tlvh; - u_int16_t sum = 0; - - zlog_debug ("ISIS MPLS-TE: Show database TE detail"); - - tlvh = (struct subtlv_header *)te->sub_tlvs; - - for (; sum < te->sub_tlvs_length; tlvh = SUBTLV_HDR_NEXT (tlvh)) - { - switch (tlvh->type) - { - case TE_SUBTLV_ADMIN_GRP: - sum += show_vty_subtlv_admin_grp (vty, (struct te_subtlv_admin_grp *)tlvh); - break; - case TE_SUBTLV_LLRI: - sum += show_vty_subtlv_llri (vty, (struct te_subtlv_llri *)tlvh); - break; - case TE_SUBTLV_LOCAL_IPADDR: - sum += show_vty_subtlv_local_ipaddr (vty, (struct te_subtlv_local_ipaddr *)tlvh); - break; - case TE_SUBTLV_RMT_IPADDR: - sum += show_vty_subtlv_rmt_ipaddr (vty, (struct te_subtlv_rmt_ipaddr *)tlvh); - break; - case TE_SUBTLV_MAX_BW: - sum += show_vty_subtlv_max_bw (vty, (struct te_subtlv_max_bw *)tlvh); - break; - case TE_SUBTLV_MAX_RSV_BW: - sum += show_vty_subtlv_max_rsv_bw (vty, (struct te_subtlv_max_rsv_bw *)tlvh); - break; - case TE_SUBTLV_UNRSV_BW: - sum += show_vty_subtlv_unrsv_bw (vty, (struct te_subtlv_unrsv_bw *)tlvh); - break; - case TE_SUBTLV_TE_METRIC: - sum += show_vty_subtlv_te_metric (vty, (struct te_subtlv_te_metric *)tlvh); - break; - case TE_SUBTLV_RAS: - sum += show_vty_subtlv_ras (vty, (struct te_subtlv_ras *)tlvh); - break; - case TE_SUBTLV_RIP: - sum += show_vty_subtlv_rip (vty, (struct te_subtlv_rip *)tlvh); - break; - case TE_SUBTLV_AV_DELAY: - sum += show_vty_subtlv_av_delay (vty, (struct te_subtlv_av_delay *)tlvh); - break; - case TE_SUBTLV_MM_DELAY: - sum += show_vty_subtlv_mm_delay (vty, (struct te_subtlv_mm_delay *)tlvh); - break; - case TE_SUBTLV_DELAY_VAR: - sum += show_vty_subtlv_delay_var (vty, (struct te_subtlv_delay_var *)tlvh); - break; - case TE_SUBTLV_PKT_LOSS: - sum += show_vty_subtlv_pkt_loss (vty, (struct te_subtlv_pkt_loss *)tlvh); - break; - case TE_SUBTLV_RES_BW: - sum += show_vty_subtlv_res_bw (vty, (struct te_subtlv_res_bw *)tlvh); - break; - case TE_SUBTLV_AVA_BW: - sum += show_vty_subtlv_ava_bw (vty, (struct te_subtlv_ava_bw *)tlvh); - break; - case TE_SUBTLV_USE_BW: - sum += show_vty_subtlv_use_bw (vty, (struct te_subtlv_use_bw *)tlvh); - break; - default: - sum += show_vty_unknown_tlv (vty, tlvh); - break; - } - } - return; + struct subtlv_header *tlvh; + u_int16_t sum = 0; + + zlog_debug("ISIS MPLS-TE: Show database TE detail"); + + tlvh = (struct subtlv_header *)te->sub_tlvs; + + for (; sum < te->sub_tlvs_length; tlvh = SUBTLV_HDR_NEXT(tlvh)) { + switch (tlvh->type) { + case TE_SUBTLV_ADMIN_GRP: + sum += show_vty_subtlv_admin_grp( + vty, (struct te_subtlv_admin_grp *)tlvh); + break; + case TE_SUBTLV_LLRI: + sum += show_vty_subtlv_llri( + vty, (struct te_subtlv_llri *)tlvh); + break; + case TE_SUBTLV_LOCAL_IPADDR: + sum += show_vty_subtlv_local_ipaddr( + vty, (struct te_subtlv_local_ipaddr *)tlvh); + break; + case TE_SUBTLV_RMT_IPADDR: + sum += show_vty_subtlv_rmt_ipaddr( + vty, (struct te_subtlv_rmt_ipaddr *)tlvh); + break; + case TE_SUBTLV_MAX_BW: + sum += show_vty_subtlv_max_bw( + vty, (struct te_subtlv_max_bw *)tlvh); + break; + case TE_SUBTLV_MAX_RSV_BW: + sum += show_vty_subtlv_max_rsv_bw( + vty, (struct te_subtlv_max_rsv_bw *)tlvh); + break; + case TE_SUBTLV_UNRSV_BW: + sum += show_vty_subtlv_unrsv_bw( + vty, (struct te_subtlv_unrsv_bw *)tlvh); + break; + case TE_SUBTLV_TE_METRIC: + sum += show_vty_subtlv_te_metric( + vty, (struct te_subtlv_te_metric *)tlvh); + break; + case TE_SUBTLV_RAS: + sum += show_vty_subtlv_ras( + vty, (struct te_subtlv_ras *)tlvh); + break; + case TE_SUBTLV_RIP: + sum += show_vty_subtlv_rip( + vty, (struct te_subtlv_rip *)tlvh); + break; + case TE_SUBTLV_AV_DELAY: + sum += show_vty_subtlv_av_delay( + vty, (struct te_subtlv_av_delay *)tlvh); + break; + case TE_SUBTLV_MM_DELAY: + sum += show_vty_subtlv_mm_delay( + vty, (struct te_subtlv_mm_delay *)tlvh); + break; + case TE_SUBTLV_DELAY_VAR: + sum += show_vty_subtlv_delay_var( + vty, (struct te_subtlv_delay_var *)tlvh); + break; + case TE_SUBTLV_PKT_LOSS: + sum += show_vty_subtlv_pkt_loss( + vty, (struct te_subtlv_pkt_loss *)tlvh); + break; + case TE_SUBTLV_RES_BW: + sum += show_vty_subtlv_res_bw( + vty, (struct te_subtlv_res_bw *)tlvh); + break; + case TE_SUBTLV_AVA_BW: + sum += show_vty_subtlv_ava_bw( + vty, (struct te_subtlv_ava_bw *)tlvh); + break; + case TE_SUBTLV_USE_BW: + sum += show_vty_subtlv_use_bw( + vty, (struct te_subtlv_use_bw *)tlvh); + break; + default: + sum += show_vty_unknown_tlv(vty, tlvh); + break; + } + } + return; } /* Specific MPLS TE router parameters write function */ -void -isis_mpls_te_config_write_router (struct vty *vty) +void isis_mpls_te_config_write_router(struct vty *vty) { - if (IS_MPLS_TE(isisMplsTE)) - { - vty_out (vty, " mpls-te on\n"); - vty_out (vty, " mpls-te router-address %s\n", - inet_ntoa(isisMplsTE.router_id)); - } - - return; + if (IS_MPLS_TE(isisMplsTE)) { + vty_out(vty, " mpls-te on\n"); + vty_out(vty, " mpls-te router-address %s\n", + inet_ntoa(isisMplsTE.router_id)); + } + + return; } @@ -1088,41 +1102,42 @@ DEFUN (isis_mpls_te_on, MPLS_TE_STR "Enable MPLS-TE functionality\n") { - struct listnode *node; - struct isis_circuit *circuit; - - if (IS_MPLS_TE(isisMplsTE)) - return CMD_SUCCESS; - - if (IS_DEBUG_ISIS(DEBUG_TE)) - zlog_debug ("ISIS MPLS-TE: OFF -> ON"); - - isisMplsTE.status = enable; - - /* - * Following code is intended to handle two cases; - * - * 1) MPLS-TE was disabled at startup time, but now become enabled. - * In this case, we must enable MPLS-TE Circuit regarding interface MPLS_TE flag - * 2) MPLS-TE was once enabled then disabled, and now enabled again. - */ - for (ALL_LIST_ELEMENTS_RO (isisMplsTE.cir_list, node, circuit)) - { - if (circuit->mtc == NULL || IS_FLOOD_AS (circuit->mtc->type)) - continue; - - if ((circuit->mtc->status == disable) - && HAS_LINK_PARAMS(circuit->interface)) - circuit->mtc->status = enable; - else - continue; - - /* Reoriginate STD_TE & GMPLS circuits */ - if (circuit->area) - lsp_regenerate_schedule (circuit->area, circuit->is_type, 0); - } - - return CMD_SUCCESS; + struct listnode *node; + struct isis_circuit *circuit; + + if (IS_MPLS_TE(isisMplsTE)) + return CMD_SUCCESS; + + if (IS_DEBUG_ISIS(DEBUG_TE)) + zlog_debug("ISIS MPLS-TE: OFF -> ON"); + + isisMplsTE.status = enable; + + /* + * Following code is intended to handle two cases; + * + * 1) MPLS-TE was disabled at startup time, but now become enabled. + * In this case, we must enable MPLS-TE Circuit regarding interface + * MPLS_TE flag + * 2) MPLS-TE was once enabled then disabled, and now enabled again. + */ + for (ALL_LIST_ELEMENTS_RO(isisMplsTE.cir_list, node, circuit)) { + if (circuit->mtc == NULL || IS_FLOOD_AS(circuit->mtc->type)) + continue; + + if ((circuit->mtc->status == disable) + && HAS_LINK_PARAMS(circuit->interface)) + circuit->mtc->status = enable; + else + continue; + + /* Reoriginate STD_TE & GMPLS circuits */ + if (circuit->area) + lsp_regenerate_schedule(circuit->area, circuit->is_type, + 0); + } + + return CMD_SUCCESS; } DEFUN (no_isis_mpls_te_on, @@ -1131,32 +1146,32 @@ DEFUN (no_isis_mpls_te_on, NO_STR "Disable the MPLS-TE functionality\n") { - struct listnode *node; - struct isis_circuit *circuit; + struct listnode *node; + struct isis_circuit *circuit; - if (isisMplsTE.status == disable) - return CMD_SUCCESS; + if (isisMplsTE.status == disable) + return CMD_SUCCESS; - if (IS_DEBUG_ISIS(DEBUG_TE)) - zlog_debug ("ISIS MPLS-TE: ON -> OFF"); + if (IS_DEBUG_ISIS(DEBUG_TE)) + zlog_debug("ISIS MPLS-TE: ON -> OFF"); - isisMplsTE.status = disable; + isisMplsTE.status = disable; - /* Flush LSP if circuit engage */ - for (ALL_LIST_ELEMENTS_RO (isisMplsTE.cir_list, node, circuit)) - { - if (circuit->mtc == NULL || (circuit->mtc->status == disable)) - continue; + /* Flush LSP if circuit engage */ + for (ALL_LIST_ELEMENTS_RO(isisMplsTE.cir_list, node, circuit)) { + if (circuit->mtc == NULL || (circuit->mtc->status == disable)) + continue; - /* disable MPLS_TE Circuit */ - circuit->mtc->status = disable; + /* disable MPLS_TE Circuit */ + circuit->mtc->status = disable; - /* Re-originate circuit without STD_TE & GMPLS parameters */ - if (circuit->area) - lsp_regenerate_schedule (circuit->area, circuit->is_type, 0); - } + /* Re-originate circuit without STD_TE & GMPLS parameters */ + if (circuit->area) + lsp_regenerate_schedule(circuit->area, circuit->is_type, + 0); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (isis_mpls_te_router_addr, @@ -1166,30 +1181,29 @@ DEFUN (isis_mpls_te_router_addr, "Stable IP address of the advertising router\n" "MPLS-TE router address in IPv4 address format\n") { - int idx_ipv4 = 2; - struct in_addr value; - struct listnode *node; - struct isis_area *area; - - if (! inet_aton (argv[idx_ipv4]->arg, &value)) - { - vty_out (vty, "Please specify Router-Addr by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - isisMplsTE.router_id.s_addr = value.s_addr; - - if (isisMplsTE.status == disable) - return CMD_SUCCESS; - - /* Update main Router ID in isis global structure */ - isis->router_id = value.s_addr; - /* And re-schedule LSP update */ - for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area)) - if (listcount (area->area_addrs) > 0) - lsp_regenerate_schedule (area, area->is_type, 0); - - return CMD_SUCCESS; + int idx_ipv4 = 2; + struct in_addr value; + struct listnode *node; + struct isis_area *area; + + if (!inet_aton(argv[idx_ipv4]->arg, &value)) { + vty_out(vty, "Please specify Router-Addr by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + isisMplsTE.router_id.s_addr = value.s_addr; + + if (isisMplsTE.status == disable) + return CMD_SUCCESS; + + /* Update main Router ID in isis global structure */ + isis->router_id = value.s_addr; + /* And re-schedule LSP update */ + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) + if (listcount(area->area_addrs) > 0) + lsp_regenerate_schedule(area, area->is_type, 0); + + return CMD_SUCCESS; } DEFUN (isis_mpls_te_inter_as, @@ -1201,8 +1215,8 @@ DEFUN (isis_mpls_te_inter_as, "AREA native mode self originate INTER-AS LSP with L1 and L2 flooding scope)\n" "AS native mode self originate INTER-AS LSP with L2 only flooding scope\n") { - vty_out (vty, "Not yet supported\n"); - return CMD_SUCCESS; + vty_out(vty, "Not yet supported\n"); + return CMD_SUCCESS; } DEFUN (no_isis_mpls_te_inter_as, @@ -1213,8 +1227,8 @@ DEFUN (no_isis_mpls_te_inter_as, "Disable MPLS-TE Inter-AS support\n") { - vty_out (vty, "Not yet supported\n"); - return CMD_SUCCESS; + vty_out(vty, "Not yet supported\n"); + return CMD_SUCCESS; } DEFUN (show_isis_mpls_te_router, @@ -1225,89 +1239,80 @@ DEFUN (show_isis_mpls_te_router, MPLS_TE_STR "Router information\n") { - if (IS_MPLS_TE(isisMplsTE)) - { - vty_out (vty, "--- MPLS-TE router parameters ---\n"); - - if (ntohs (isisMplsTE.router_id.s_addr) != 0) - vty_out (vty, " Router-Address: %s\n", - inet_ntoa(isisMplsTE.router_id)); - else - vty_out (vty, " N/A\n"); - } - else - vty_out (vty, " MPLS-TE is disable on this router\n"); - - return CMD_SUCCESS; + if (IS_MPLS_TE(isisMplsTE)) { + vty_out(vty, "--- MPLS-TE router parameters ---\n"); + + if (ntohs(isisMplsTE.router_id.s_addr) != 0) + vty_out(vty, " Router-Address: %s\n", + inet_ntoa(isisMplsTE.router_id)); + else + vty_out(vty, " N/A\n"); + } else + vty_out(vty, " MPLS-TE is disable on this router\n"); + + return CMD_SUCCESS; } -static void -show_mpls_te_sub (struct vty *vty, struct interface *ifp) +static void show_mpls_te_sub(struct vty *vty, struct interface *ifp) { - struct mpls_te_circuit *mtc; - - if ((IS_MPLS_TE(isisMplsTE)) - && ((mtc = lookup_mpls_params_by_ifp (ifp)) != NULL)) - { - /* Continue only if interface is not passive or support Inter-AS TEv2 */ - if (mtc->status != enable) - { - if (IS_INTER_AS(mtc->type)) - { - vty_out (vty, "-- Inter-AS TEv2 link parameters for %s --\n", - ifp->name); - } - else - { - /* MPLS-TE is not activate on this interface */ - /* or this interface is passive and Inter-AS TEv2 is not activate */ - vty_out (vty, " %s: MPLS-TE is disabled on this interface\n", - ifp->name); - return; - } - } - else - { - vty_out (vty, "-- MPLS-TE link parameters for %s --\n", - ifp->name); - } - - show_vty_subtlv_admin_grp (vty, &mtc->admin_grp); - - if (SUBTLV_TYPE(mtc->local_ipaddr) != 0) - show_vty_subtlv_local_ipaddr (vty, &mtc->local_ipaddr); - if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0) - show_vty_subtlv_rmt_ipaddr (vty, &mtc->rmt_ipaddr); - - show_vty_subtlv_max_bw (vty, &mtc->max_bw); - show_vty_subtlv_max_rsv_bw (vty, &mtc->max_rsv_bw); - show_vty_subtlv_unrsv_bw (vty, &mtc->unrsv_bw); - show_vty_subtlv_te_metric (vty, &mtc->te_metric); - - if (IS_INTER_AS(mtc->type)) - { - if (SUBTLV_TYPE(mtc->ras) != 0) - show_vty_subtlv_ras (vty, &mtc->ras); - if (SUBTLV_TYPE(mtc->rip) != 0) - show_vty_subtlv_rip (vty, &mtc->rip); - } - - show_vty_subtlv_av_delay (vty, &mtc->av_delay); - show_vty_subtlv_mm_delay (vty, &mtc->mm_delay); - show_vty_subtlv_delay_var (vty, &mtc->delay_var); - show_vty_subtlv_pkt_loss (vty, &mtc->pkt_loss); - show_vty_subtlv_res_bw (vty, &mtc->res_bw); - show_vty_subtlv_ava_bw (vty, &mtc->ava_bw); - show_vty_subtlv_use_bw (vty, &mtc->use_bw); - vty_out (vty, "---------------\n\n"); - } - else - { - vty_out (vty, " %s: MPLS-TE is disabled on this interface\n", - ifp->name); - } - - return; + struct mpls_te_circuit *mtc; + + if ((IS_MPLS_TE(isisMplsTE)) + && ((mtc = lookup_mpls_params_by_ifp(ifp)) != NULL)) { + /* Continue only if interface is not passive or support Inter-AS + * TEv2 */ + if (mtc->status != enable) { + if (IS_INTER_AS(mtc->type)) { + vty_out(vty, + "-- Inter-AS TEv2 link parameters for %s --\n", + ifp->name); + } else { + /* MPLS-TE is not activate on this interface */ + /* or this interface is passive and Inter-AS + * TEv2 is not activate */ + vty_out(vty, + " %s: MPLS-TE is disabled on this interface\n", + ifp->name); + return; + } + } else { + vty_out(vty, "-- MPLS-TE link parameters for %s --\n", + ifp->name); + } + + show_vty_subtlv_admin_grp(vty, &mtc->admin_grp); + + if (SUBTLV_TYPE(mtc->local_ipaddr) != 0) + show_vty_subtlv_local_ipaddr(vty, &mtc->local_ipaddr); + if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0) + show_vty_subtlv_rmt_ipaddr(vty, &mtc->rmt_ipaddr); + + show_vty_subtlv_max_bw(vty, &mtc->max_bw); + show_vty_subtlv_max_rsv_bw(vty, &mtc->max_rsv_bw); + show_vty_subtlv_unrsv_bw(vty, &mtc->unrsv_bw); + show_vty_subtlv_te_metric(vty, &mtc->te_metric); + + if (IS_INTER_AS(mtc->type)) { + if (SUBTLV_TYPE(mtc->ras) != 0) + show_vty_subtlv_ras(vty, &mtc->ras); + if (SUBTLV_TYPE(mtc->rip) != 0) + show_vty_subtlv_rip(vty, &mtc->rip); + } + + show_vty_subtlv_av_delay(vty, &mtc->av_delay); + show_vty_subtlv_mm_delay(vty, &mtc->mm_delay); + show_vty_subtlv_delay_var(vty, &mtc->delay_var); + show_vty_subtlv_pkt_loss(vty, &mtc->pkt_loss); + show_vty_subtlv_res_bw(vty, &mtc->res_bw); + show_vty_subtlv_ava_bw(vty, &mtc->ava_bw); + show_vty_subtlv_use_bw(vty, &mtc->use_bw); + vty_out(vty, "---------------\n\n"); + } else { + vty_out(vty, " %s: MPLS-TE is disabled on this interface\n", + ifp->name); + } + + return; } DEFUN (show_isis_mpls_te_interface, @@ -1319,52 +1324,51 @@ DEFUN (show_isis_mpls_te_interface, "Interface information\n" "Interface name\n") { - int idx_interface = 4; - struct interface *ifp; - struct listnode *node; - - /* Show All Interfaces. */ - if (argc == 4) - { - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - show_mpls_te_sub (vty, ifp); - } - /* Interface name is specified. */ - else - { - if ((ifp = if_lookup_by_name (argv[idx_interface]->arg, VRF_DEFAULT)) == NULL) - vty_out (vty, "No such interface name\n"); - else - show_mpls_te_sub (vty, ifp); - } - - return CMD_SUCCESS; + int idx_interface = 4; + struct interface *ifp; + struct listnode *node; + + /* Show All Interfaces. */ + if (argc == 4) { + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) + show_mpls_te_sub(vty, ifp); + } + /* Interface name is specified. */ + else { + if ((ifp = if_lookup_by_name(argv[idx_interface]->arg, + VRF_DEFAULT)) + == NULL) + vty_out(vty, "No such interface name\n"); + else + show_mpls_te_sub(vty, ifp); + } + + return CMD_SUCCESS; } /* Initialize MPLS_TE */ -void -isis_mpls_te_init (void) +void isis_mpls_te_init(void) { - zlog_debug("ISIS MPLS-TE: Initialize"); + zlog_debug("ISIS MPLS-TE: Initialize"); - /* Initialize MPLS_TE structure */ - isisMplsTE.status = disable; - isisMplsTE.level = 0; - isisMplsTE.inter_as = off; - isisMplsTE.interas_areaid.s_addr = 0; - isisMplsTE.cir_list = list_new(); - isisMplsTE.router_id.s_addr = 0; + /* Initialize MPLS_TE structure */ + isisMplsTE.status = disable; + isisMplsTE.level = 0; + isisMplsTE.inter_as = off; + isisMplsTE.interas_areaid.s_addr = 0; + isisMplsTE.cir_list = list_new(); + isisMplsTE.router_id.s_addr = 0; - /* Register new VTY commands */ - install_element (VIEW_NODE, &show_isis_mpls_te_router_cmd); - install_element (VIEW_NODE, &show_isis_mpls_te_interface_cmd); + /* Register new VTY commands */ + install_element(VIEW_NODE, &show_isis_mpls_te_router_cmd); + install_element(VIEW_NODE, &show_isis_mpls_te_interface_cmd); - install_element (ISIS_NODE, &isis_mpls_te_on_cmd); - install_element (ISIS_NODE, &no_isis_mpls_te_on_cmd); - install_element (ISIS_NODE, &isis_mpls_te_router_addr_cmd); - install_element (ISIS_NODE, &isis_mpls_te_inter_as_cmd); - install_element (ISIS_NODE, &no_isis_mpls_te_inter_as_cmd); + install_element(ISIS_NODE, &isis_mpls_te_on_cmd); + install_element(ISIS_NODE, &no_isis_mpls_te_on_cmd); + install_element(ISIS_NODE, &isis_mpls_te_router_addr_cmd); + install_element(ISIS_NODE, &isis_mpls_te_inter_as_cmd); + install_element(ISIS_NODE, &no_isis_mpls_te_inter_as_cmd); - return; + return; } diff --git a/isisd/isis_te.h b/isisd/isis_te.h index 3c99c9085..0bd076af1 100644 --- a/isisd/isis_te.h +++ b/isisd/isis_te.h @@ -76,10 +76,9 @@ * Following section defines subTLV (tag, length, value) structures, * used for Traffic Engineering. */ -struct subtlv_header -{ - u_char type; /* sub_TLV_XXX type (see above) */ - u_char length; /* Value portion only, in byte */ +struct subtlv_header { + u_char type; /* sub_TLV_XXX type (see above) */ + u_char length; /* Value portion only, in byte */ }; #define SUBTLV_HDR_SIZE 2 /* (sizeof (struct sub_tlv_header)) */ @@ -99,149 +98,140 @@ struct subtlv_header /* Link Sub-TLV: Resource Class/Color - RFC 5305 */ #define TE_SUBTLV_ADMIN_GRP 3 -struct te_subtlv_admin_grp -{ - struct subtlv_header header; /* Value length is 4 octets. */ - u_int32_t value; /* Admin. group membership. */ +struct te_subtlv_admin_grp { + struct subtlv_header header; /* Value length is 4 octets. */ + u_int32_t value; /* Admin. group membership. */ } __attribute__((__packed__)); /* Link Local/Remote Identifiers - RFC 5307 */ #define TE_SUBTLV_LLRI 4 #define TE_SUBTLV_LLRI_SIZE 8 -struct te_subtlv_llri -{ - struct subtlv_header header; /* Value length is 8 octets. */ - u_int32_t local; /* Link Local Identifier */ - u_int32_t remote; /* Link Remote Identifier */ +struct te_subtlv_llri { + struct subtlv_header header; /* Value length is 8 octets. */ + u_int32_t local; /* Link Local Identifier */ + u_int32_t remote; /* Link Remote Identifier */ } __attribute__((__packed__)); /* Link Sub-TLV: Local Interface IP Address - RFC 5305 */ #define TE_SUBTLV_LOCAL_IPADDR 6 -struct te_subtlv_local_ipaddr -{ - struct subtlv_header header; /* Value length is 4 x N octets. */ - struct in_addr value; /* Local IP address(es). */ +struct te_subtlv_local_ipaddr { + struct subtlv_header header; /* Value length is 4 x N octets. */ + struct in_addr value; /* Local IP address(es). */ } __attribute__((__packed__)); /* Link Sub-TLV: Neighbor Interface IP Address - RFC 5305 */ #define TE_SUBTLV_RMT_IPADDR 8 -struct te_subtlv_rmt_ipaddr -{ - struct subtlv_header header; /* Value length is 4 x N octets. */ - struct in_addr value; /* Neighbor's IP address(es). */ +struct te_subtlv_rmt_ipaddr { + struct subtlv_header header; /* Value length is 4 x N octets. */ + struct in_addr value; /* Neighbor's IP address(es). */ } __attribute__((__packed__)); /* Link Sub-TLV: Maximum Bandwidth - RFC 5305 */ #define TE_SUBTLV_MAX_BW 9 -struct te_subtlv_max_bw -{ - struct subtlv_header header; /* Value length is 4 octets. */ - float value; /* bytes/sec */ +struct te_subtlv_max_bw { + struct subtlv_header header; /* Value length is 4 octets. */ + float value; /* bytes/sec */ } __attribute__((__packed__)); /* Link Sub-TLV: Maximum Reservable Bandwidth - RFC 5305 */ #define TE_SUBTLV_MAX_RSV_BW 10 -struct te_subtlv_max_rsv_bw -{ - struct subtlv_header header; /* Value length is 4 octets. */ - float value; /* bytes/sec */ +struct te_subtlv_max_rsv_bw { + struct subtlv_header header; /* Value length is 4 octets. */ + float value; /* bytes/sec */ } __attribute__((__packed__)); /* Link Sub-TLV: Unreserved Bandwidth - RFC 5305 */ #define TE_SUBTLV_UNRSV_BW 11 #define TE_SUBTLV_UNRSV_SIZE 32 -struct te_subtlv_unrsv_bw -{ - struct subtlv_header header; /* Value length is 32 octets. */ - float value[8]; /* One for each priority level. */ +struct te_subtlv_unrsv_bw { + struct subtlv_header header; /* Value length is 32 octets. */ + float value[8]; /* One for each priority level. */ } __attribute__((__packed__)); /* Link Sub-TLV: Traffic Engineering Metric - RFC 5305 */ #define TE_SUBTLV_TE_METRIC 18 #define TE_SUBTLV_TE_METRIC_SIZE 3 -struct te_subtlv_te_metric -{ - struct subtlv_header header; /* Value length is 4 octets. */ - u_char value[3]; /* Link metric for TE purpose. */ +struct te_subtlv_te_metric { + struct subtlv_header header; /* Value length is 4 octets. */ + u_char value[3]; /* Link metric for TE purpose. */ } __attribute__((__packed__)); /* Remote AS Number sub-TLV - RFC5316 */ #define TE_SUBTLV_RAS 24 -struct te_subtlv_ras -{ - struct subtlv_header header; /* Value length is 4 octets. */ - u_int32_t value; /* Remote AS number */ +struct te_subtlv_ras { + struct subtlv_header header; /* Value length is 4 octets. */ + u_int32_t value; /* Remote AS number */ } __attribute__((__packed__)); /* IPv4 Remote ASBR ID Sub-TLV - RFC5316 */ #define TE_SUBTLV_RIP 25 -struct te_subtlv_rip -{ - struct subtlv_header header; /* Value length is 4 octets. */ - struct in_addr value; /* Remote ASBR IP address */ +struct te_subtlv_rip { + struct subtlv_header header; /* Value length is 4 octets. */ + struct in_addr value; /* Remote ASBR IP address */ } __attribute__((__packed__)); /* TE Metric Extensions - RFC 7810 */ /* Link Sub-TLV: Average Link Delay */ #define TE_SUBTLV_AV_DELAY 33 -struct te_subtlv_av_delay -{ - struct subtlv_header header; /* Value length is 4 bytes. */ - u_int32_t value; /* Average delay in micro-seconds only 24 bits => 0 ... 16777215 - with Anomalous Bit (A) as Upper most bit */ +struct te_subtlv_av_delay { + struct subtlv_header header; /* Value length is 4 bytes. */ + u_int32_t value; /* Average delay in micro-seconds only 24 bits => 0 ... + 16777215 + with Anomalous Bit (A) as Upper most bit */ } __attribute__((__packed__)); /* Link Sub-TLV: Low/High Link Delay */ #define TE_SUBTLV_MM_DELAY 34 #define TE_SUBTLV_MM_DELAY_SIZE 8 -struct te_subtlv_mm_delay -{ - struct subtlv_header header; /* Value length is 8 bytes. */ - u_int32_t low; /* low delay in micro-seconds only 24 bits => 0 ... 16777215 - with Anomalous Bit (A) as Upper most bit */ - u_int32_t high; /* high delay in micro-seconds only 24 bits => 0 ... 16777215 */ +struct te_subtlv_mm_delay { + struct subtlv_header header; /* Value length is 8 bytes. */ + u_int32_t low; /* low delay in micro-seconds only 24 bits => 0 ... + 16777215 + with Anomalous Bit (A) as Upper most bit */ + u_int32_t high; /* high delay in micro-seconds only 24 bits => 0 ... + 16777215 */ } __attribute__((__packed__)); /* Link Sub-TLV: Link Delay Variation i.e. Jitter */ #define TE_SUBTLV_DELAY_VAR 35 -struct te_subtlv_delay_var -{ - struct subtlv_header header; /* Value length is 4 bytes. */ - u_int32_t value; /* interval in micro-seconds only 24 bits => 0 ... 16777215 */ +struct te_subtlv_delay_var { + struct subtlv_header header; /* Value length is 4 bytes. */ + u_int32_t value; /* interval in micro-seconds only 24 bits => 0 ... + 16777215 */ } __attribute__((__packed__)); /* Link Sub-TLV: Routine Unidirectional Link Packet Loss */ #define TE_SUBTLV_PKT_LOSS 36 -struct te_subtlv_pkt_loss -{ - struct subtlv_header header; /* Value length is 4 bytes. */ - u_int32_t value; /* in percentage of total traffic only 24 bits (2^24 - 2) - with Anomalous Bit (A) as Upper most bit */ +struct te_subtlv_pkt_loss { + struct subtlv_header header; /* Value length is 4 bytes. */ + u_int32_t + value; /* in percentage of total traffic only 24 bits (2^24 - 2) + with Anomalous Bit (A) as Upper most bit */ } __attribute__((__packed__)); /* Link Sub-TLV: Unidirectional Residual Bandwidth */ /* Optional */ #define TE_SUBTLV_RES_BW 37 -struct te_subtlv_res_bw -{ - struct subtlv_header header; /* Value length is 4 bytes. */ - float value; /* bandwidth in IEEE floating point format with units in bytes per second */ +struct te_subtlv_res_bw { + struct subtlv_header header; /* Value length is 4 bytes. */ + float value; /* bandwidth in IEEE floating point format with units in + bytes per second */ } __attribute__((__packed__)); /* Link Sub-TLV: Unidirectional Available Bandwidth */ /* Optional */ #define TE_SUBTLV_AVA_BW 38 -struct te_subtlv_ava_bw -{ - struct subtlv_header header; /* Value length is 4 octets. */ - float value; /* bandwidth in IEEE floating point format with units in bytes per second */ +struct te_subtlv_ava_bw { + struct subtlv_header header; /* Value length is 4 octets. */ + float value; /* bandwidth in IEEE floating point format with units in + bytes per second */ } __attribute__((__packed__)); /* Link Sub-TLV: Unidirectional Utilized Bandwidth */ /* Optional */ #define TE_SUBTLV_USE_BW 39 -struct te_subtlv_use_bw -{ - struct subtlv_header header; /* Value length is 4 octets. */ - float value; /* bandwidth in IEEE floating point format with units in bytes per second */ +struct te_subtlv_use_bw { + struct subtlv_header header; /* Value length is 4 octets. */ + float value; /* bandwidth in IEEE floating point format with units in + bytes per second */ } __attribute__((__packed__)); #define TE_SUBTLV_MAX 40 /* Last SUBTLV + 1 */ @@ -256,75 +246,74 @@ typedef enum _interas_mode_t { off, region, as, emulate } interas_mode_t; #define IS_CIRCUIT_TE(c) (c->status == enable) /* Following structure are internal use only. */ -struct isis_mpls_te -{ - /* Status of MPLS-TE: enable or disable */ - status_t status; +struct isis_mpls_te { + /* Status of MPLS-TE: enable or disable */ + status_t status; - /* L1, L1-L2, L2-Only */ - u_int8_t level; + /* L1, L1-L2, L2-Only */ + u_int8_t level; - /* RFC5316 */ - interas_mode_t inter_as; - struct in_addr interas_areaid; + /* RFC5316 */ + interas_mode_t inter_as; + struct in_addr interas_areaid; - /* Circuit list on which TE are enable */ - struct list *cir_list; + /* Circuit list on which TE are enable */ + struct list *cir_list; - /* MPLS_TE router ID */ - struct in_addr router_id; + /* MPLS_TE router ID */ + struct in_addr router_id; }; extern struct isis_mpls_te isisMplsTE; -struct mpls_te_circuit -{ - - /* Status of MPLS-TE on this interface */ - status_t status; - - /* Type of MPLS-TE circuit: STD_TE(RFC5305), INTER_AS(RFC5316), INTER_AS_EMU(RFC5316 emulated) */ - u_int8_t type; - - /* Total size of sub_tlvs */ - u_char length; - - /* Store subTLV in network byte order. */ - /* RFC5305 */ - struct te_subtlv_admin_grp admin_grp; - /* RFC5307 */ - struct te_subtlv_llri llri; - /* RFC5305 */ - struct te_subtlv_local_ipaddr local_ipaddr; - struct te_subtlv_rmt_ipaddr rmt_ipaddr; - struct te_subtlv_max_bw max_bw; - struct te_subtlv_max_rsv_bw max_rsv_bw; - struct te_subtlv_unrsv_bw unrsv_bw; - struct te_subtlv_te_metric te_metric; - /* RFC5316 */ - struct te_subtlv_ras ras; - struct te_subtlv_rip rip; - /* RFC7810 */ - struct te_subtlv_av_delay av_delay; - struct te_subtlv_mm_delay mm_delay; - struct te_subtlv_delay_var delay_var; - struct te_subtlv_pkt_loss pkt_loss; - struct te_subtlv_res_bw res_bw; - struct te_subtlv_ava_bw ava_bw; - struct te_subtlv_use_bw use_bw; +struct mpls_te_circuit { + + /* Status of MPLS-TE on this interface */ + status_t status; + + /* Type of MPLS-TE circuit: STD_TE(RFC5305), INTER_AS(RFC5316), + * INTER_AS_EMU(RFC5316 emulated) */ + u_int8_t type; + + /* Total size of sub_tlvs */ + u_char length; + + /* Store subTLV in network byte order. */ + /* RFC5305 */ + struct te_subtlv_admin_grp admin_grp; + /* RFC5307 */ + struct te_subtlv_llri llri; + /* RFC5305 */ + struct te_subtlv_local_ipaddr local_ipaddr; + struct te_subtlv_rmt_ipaddr rmt_ipaddr; + struct te_subtlv_max_bw max_bw; + struct te_subtlv_max_rsv_bw max_rsv_bw; + struct te_subtlv_unrsv_bw unrsv_bw; + struct te_subtlv_te_metric te_metric; + /* RFC5316 */ + struct te_subtlv_ras ras; + struct te_subtlv_rip rip; + /* RFC7810 */ + struct te_subtlv_av_delay av_delay; + struct te_subtlv_mm_delay mm_delay; + struct te_subtlv_delay_var delay_var; + struct te_subtlv_pkt_loss pkt_loss; + struct te_subtlv_res_bw res_bw; + struct te_subtlv_ava_bw ava_bw; + struct te_subtlv_use_bw use_bw; }; /* Prototypes. */ -void isis_mpls_te_init (void); +void isis_mpls_te_init(void); struct mpls_te_circuit *mpls_te_circuit_new(void); void mpls_te_print_detail(struct vty *, struct te_is_neigh *); -void set_circuitparams_local_ipaddr (struct mpls_te_circuit *, struct in_addr); -void set_circuitparams_rmt_ipaddr (struct mpls_te_circuit *, struct in_addr); -u_char subtlvs_len (struct mpls_te_circuit *); +void set_circuitparams_local_ipaddr(struct mpls_te_circuit *, struct in_addr); +void set_circuitparams_rmt_ipaddr(struct mpls_te_circuit *, struct in_addr); +u_char subtlvs_len(struct mpls_te_circuit *); u_char add_te_subtlvs(u_char *, struct mpls_te_circuit *); u_char build_te_subtlvs(u_char *, struct isis_circuit *); void isis_link_params_update(struct isis_circuit *, struct interface *); void isis_mpls_te_update(struct interface *); -void isis_mpls_te_config_write_router (struct vty *); +void isis_mpls_te_config_write_router(struct vty *); #endif /* _ZEBRA_ISIS_MPLS_TE_H */ diff --git a/isisd/isis_tlv.c b/isisd/isis_tlv.c index 7ffa7509c..a295f4dd3 100644 --- a/isisd/isis_tlv.c +++ b/isisd/isis_tlv.c @@ -3,17 +3,17 @@ * IS-IS TLV related routines * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -45,1461 +45,1409 @@ #include "isisd/isis_te.h" #include "isisd/isis_mt.h" -void -free_tlv (void *val) +void free_tlv(void *val) { - XFREE (MTYPE_ISIS_TLV, val); + XFREE(MTYPE_ISIS_TLV, val); - return; + return; } /* * Called after parsing of a PDU. There shouldn't be any tlv's left, so this * is only a caution to avoid memory leaks */ -void -free_tlvs (struct tlvs *tlvs) +void free_tlvs(struct tlvs *tlvs) { - if (tlvs->area_addrs) - list_delete (tlvs->area_addrs); - if (tlvs->mt_router_info) - list_delete (tlvs->mt_router_info); - if (tlvs->is_neighs) - list_delete (tlvs->is_neighs); - if (tlvs->te_is_neighs) - list_delete (tlvs->te_is_neighs); - if (tlvs->mt_is_neighs) - list_delete (tlvs->mt_is_neighs); - if (tlvs->es_neighs) - list_delete (tlvs->es_neighs); - if (tlvs->lsp_entries) - list_delete (tlvs->lsp_entries); - if (tlvs->prefix_neighs) - list_delete (tlvs->prefix_neighs); - if (tlvs->lan_neighs) - list_delete (tlvs->lan_neighs); - if (tlvs->ipv4_addrs) - list_delete (tlvs->ipv4_addrs); - if (tlvs->ipv4_int_reachs) - list_delete (tlvs->ipv4_int_reachs); - if (tlvs->ipv4_ext_reachs) - list_delete (tlvs->ipv4_ext_reachs); - if (tlvs->te_ipv4_reachs) - list_delete (tlvs->te_ipv4_reachs); - if (tlvs->mt_ipv4_reachs) - list_delete (tlvs->mt_ipv4_reachs); - if (tlvs->ipv6_addrs) - list_delete (tlvs->ipv6_addrs); - if (tlvs->ipv6_reachs) - list_delete (tlvs->ipv6_reachs); - if (tlvs->mt_ipv6_reachs) - list_delete (tlvs->mt_ipv6_reachs); - - memset (tlvs, 0, sizeof (struct tlvs)); - - return; + if (tlvs->area_addrs) + list_delete(tlvs->area_addrs); + if (tlvs->mt_router_info) + list_delete(tlvs->mt_router_info); + if (tlvs->is_neighs) + list_delete(tlvs->is_neighs); + if (tlvs->te_is_neighs) + list_delete(tlvs->te_is_neighs); + if (tlvs->mt_is_neighs) + list_delete(tlvs->mt_is_neighs); + if (tlvs->es_neighs) + list_delete(tlvs->es_neighs); + if (tlvs->lsp_entries) + list_delete(tlvs->lsp_entries); + if (tlvs->prefix_neighs) + list_delete(tlvs->prefix_neighs); + if (tlvs->lan_neighs) + list_delete(tlvs->lan_neighs); + if (tlvs->ipv4_addrs) + list_delete(tlvs->ipv4_addrs); + if (tlvs->ipv4_int_reachs) + list_delete(tlvs->ipv4_int_reachs); + if (tlvs->ipv4_ext_reachs) + list_delete(tlvs->ipv4_ext_reachs); + if (tlvs->te_ipv4_reachs) + list_delete(tlvs->te_ipv4_reachs); + if (tlvs->mt_ipv4_reachs) + list_delete(tlvs->mt_ipv4_reachs); + if (tlvs->ipv6_addrs) + list_delete(tlvs->ipv6_addrs); + if (tlvs->ipv6_reachs) + list_delete(tlvs->ipv6_reachs); + if (tlvs->mt_ipv6_reachs) + list_delete(tlvs->mt_ipv6_reachs); + + memset(tlvs, 0, sizeof(struct tlvs)); + + return; } -static int -parse_mtid(uint16_t *mtid, bool read_mtid, - unsigned int *length, u_char **pnt) +static int parse_mtid(uint16_t *mtid, bool read_mtid, unsigned int *length, + u_char **pnt) { - if (!read_mtid) - { - *mtid = ISIS_MT_IPV4_UNICAST; - return ISIS_OK; - } - - uint16_t mtid_buf; - - if (*length < sizeof(mtid_buf)) - { - zlog_warn("ISIS-TLV: mt tlv too short to contain MT id"); - return ISIS_WARNING; - } - - memcpy(&mtid_buf, *pnt, sizeof(mtid_buf)); - *pnt += sizeof(mtid_buf); - *length -= sizeof(mtid_buf); - - *mtid = ntohs(mtid_buf) & ISIS_MT_MASK; - return ISIS_OK; + if (!read_mtid) { + *mtid = ISIS_MT_IPV4_UNICAST; + return ISIS_OK; + } + + uint16_t mtid_buf; + + if (*length < sizeof(mtid_buf)) { + zlog_warn("ISIS-TLV: mt tlv too short to contain MT id"); + return ISIS_WARNING; + } + + memcpy(&mtid_buf, *pnt, sizeof(mtid_buf)); + *pnt += sizeof(mtid_buf); + *length -= sizeof(mtid_buf); + + *mtid = ntohs(mtid_buf) & ISIS_MT_MASK; + return ISIS_OK; } -static int -parse_mt_is_neighs(struct tlvs *tlvs, bool read_mtid, - unsigned int length, u_char *pnt) +static int parse_mt_is_neighs(struct tlvs *tlvs, bool read_mtid, + unsigned int length, u_char *pnt) { - struct list *neigh_list; - uint16_t mtid; - int rv; - - rv = parse_mtid(&mtid, read_mtid, &length, &pnt); - if (rv != ISIS_OK) - return rv; - - if (mtid == ISIS_MT_IPV4_UNICAST) - { - if (!tlvs->te_is_neighs) - { - tlvs->te_is_neighs = list_new(); - tlvs->te_is_neighs->del = free_tlv; - } - neigh_list = tlvs->te_is_neighs; - } - else - { - struct tlv_mt_neighbors *neighbors; - - neighbors = tlvs_get_mt_neighbors(tlvs, mtid); - neighbors->list->del = free_tlv; - neigh_list = neighbors->list; - } - - while (length >= IS_NEIGHBOURS_LEN) - { - struct te_is_neigh *neigh = XCALLOC(MTYPE_ISIS_TLV, sizeof(*neigh)); - - memcpy(neigh, pnt, IS_NEIGHBOURS_LEN); - pnt += IS_NEIGHBOURS_LEN; - length -= IS_NEIGHBOURS_LEN; - - if (neigh->sub_tlvs_length > length) - { - zlog_warn("ISIS-TLV: neighbor subtlv length exceeds TLV size"); - XFREE(MTYPE_ISIS_TLV, neigh); - return ISIS_WARNING; - } - - memcpy(neigh->sub_tlvs, pnt, neigh->sub_tlvs_length); - pnt += neigh->sub_tlvs_length; - length -= neigh->sub_tlvs_length; - - listnode_add(neigh_list, neigh); - } - - if (length) - { - zlog_warn("ISIS-TLV: TE/MT neighor TLV has trailing data"); - return ISIS_WARNING; - } - - return ISIS_OK; + struct list *neigh_list; + uint16_t mtid; + int rv; + + rv = parse_mtid(&mtid, read_mtid, &length, &pnt); + if (rv != ISIS_OK) + return rv; + + if (mtid == ISIS_MT_IPV4_UNICAST) { + if (!tlvs->te_is_neighs) { + tlvs->te_is_neighs = list_new(); + tlvs->te_is_neighs->del = free_tlv; + } + neigh_list = tlvs->te_is_neighs; + } else { + struct tlv_mt_neighbors *neighbors; + + neighbors = tlvs_get_mt_neighbors(tlvs, mtid); + neighbors->list->del = free_tlv; + neigh_list = neighbors->list; + } + + while (length >= IS_NEIGHBOURS_LEN) { + struct te_is_neigh *neigh = + XCALLOC(MTYPE_ISIS_TLV, sizeof(*neigh)); + + memcpy(neigh, pnt, IS_NEIGHBOURS_LEN); + pnt += IS_NEIGHBOURS_LEN; + length -= IS_NEIGHBOURS_LEN; + + if (neigh->sub_tlvs_length > length) { + zlog_warn( + "ISIS-TLV: neighbor subtlv length exceeds TLV size"); + XFREE(MTYPE_ISIS_TLV, neigh); + return ISIS_WARNING; + } + + memcpy(neigh->sub_tlvs, pnt, neigh->sub_tlvs_length); + pnt += neigh->sub_tlvs_length; + length -= neigh->sub_tlvs_length; + + listnode_add(neigh_list, neigh); + } + + if (length) { + zlog_warn("ISIS-TLV: TE/MT neighor TLV has trailing data"); + return ISIS_WARNING; + } + + return ISIS_OK; } -static int -parse_mt_ipv4_reachs(struct tlvs *tlvs, bool read_mtid, - unsigned int length, u_char *pnt) +static int parse_mt_ipv4_reachs(struct tlvs *tlvs, bool read_mtid, + unsigned int length, u_char *pnt) { - struct list *reach_list; - uint16_t mtid; - int rv; - - rv = parse_mtid(&mtid, read_mtid, &length, &pnt); - if (rv != ISIS_OK) - return rv; - - if (mtid == ISIS_MT_IPV4_UNICAST) - { - if (!tlvs->te_ipv4_reachs) - { - tlvs->te_ipv4_reachs = list_new(); - tlvs->te_ipv4_reachs->del = free_tlv; - } - reach_list = tlvs->te_ipv4_reachs; - } - else - { - struct tlv_mt_ipv4_reachs *reachs; - - reachs = tlvs_get_mt_ipv4_reachs(tlvs, mtid); - reachs->list->del = free_tlv; - reach_list = reachs->list; - } - - while (length >= 5) /* Metric + Control */ - { - struct te_ipv4_reachability *reach = XCALLOC(MTYPE_ISIS_TLV, TE_IPV4_REACH_LEN); - - memcpy(reach, pnt, 5); /* Metric + Control */ - pnt += 5; - length -= 5; - - unsigned char prefixlen = reach->control & 0x3F; - - if (prefixlen > IPV4_MAX_BITLEN) - { - zlog_warn("ISIS-TLV: invalid IPv4 extended reachability prefix length %d", prefixlen); - XFREE(MTYPE_ISIS_TLV, reach); - return ISIS_WARNING; - } - - if (length < (unsigned int)PSIZE(prefixlen)) - { - zlog_warn("ISIS-TLV: invalid IPv4 extended reachability prefix too long for tlv"); - XFREE(MTYPE_ISIS_TLV, reach); - return ISIS_WARNING; - } - - memcpy(&reach->prefix_start, pnt, PSIZE(prefixlen)); - pnt += PSIZE(prefixlen); - length -= PSIZE(prefixlen); - - if (reach->control & TE_IPV4_HAS_SUBTLV) - { - if (length < 1) - { - zlog_warn("ISIS-TLV: invalid IPv4 extended reachability SubTLV missing"); - XFREE(MTYPE_ISIS_TLV, reach); - return ISIS_WARNING; - } - - u_char subtlv_len = *pnt; - pnt++; - length--; - - if (length < subtlv_len) - { - zlog_warn("ISIS-TLV: invalid IPv4 extended reachability SubTLVs have oversize"); - XFREE(MTYPE_ISIS_TLV, reach); - return ISIS_WARNING; - } - - /* Skip Sub-TLVs for now */ - pnt += subtlv_len; - length -= subtlv_len; - } - listnode_add(reach_list, reach); - } - - if (length) - { - zlog_warn("ISIS-TLV: TE/MT ipv4 reachability TLV has trailing data"); - return ISIS_WARNING; - } - - return ISIS_OK; + struct list *reach_list; + uint16_t mtid; + int rv; + + rv = parse_mtid(&mtid, read_mtid, &length, &pnt); + if (rv != ISIS_OK) + return rv; + + if (mtid == ISIS_MT_IPV4_UNICAST) { + if (!tlvs->te_ipv4_reachs) { + tlvs->te_ipv4_reachs = list_new(); + tlvs->te_ipv4_reachs->del = free_tlv; + } + reach_list = tlvs->te_ipv4_reachs; + } else { + struct tlv_mt_ipv4_reachs *reachs; + + reachs = tlvs_get_mt_ipv4_reachs(tlvs, mtid); + reachs->list->del = free_tlv; + reach_list = reachs->list; + } + + while (length >= 5) /* Metric + Control */ + { + struct te_ipv4_reachability *reach = + XCALLOC(MTYPE_ISIS_TLV, TE_IPV4_REACH_LEN); + + memcpy(reach, pnt, 5); /* Metric + Control */ + pnt += 5; + length -= 5; + + unsigned char prefixlen = reach->control & 0x3F; + + if (prefixlen > IPV4_MAX_BITLEN) { + zlog_warn( + "ISIS-TLV: invalid IPv4 extended reachability prefix length %d", + prefixlen); + XFREE(MTYPE_ISIS_TLV, reach); + return ISIS_WARNING; + } + + if (length < (unsigned int)PSIZE(prefixlen)) { + zlog_warn( + "ISIS-TLV: invalid IPv4 extended reachability prefix too long for tlv"); + XFREE(MTYPE_ISIS_TLV, reach); + return ISIS_WARNING; + } + + memcpy(&reach->prefix_start, pnt, PSIZE(prefixlen)); + pnt += PSIZE(prefixlen); + length -= PSIZE(prefixlen); + + if (reach->control & TE_IPV4_HAS_SUBTLV) { + if (length < 1) { + zlog_warn( + "ISIS-TLV: invalid IPv4 extended reachability SubTLV missing"); + XFREE(MTYPE_ISIS_TLV, reach); + return ISIS_WARNING; + } + + u_char subtlv_len = *pnt; + pnt++; + length--; + + if (length < subtlv_len) { + zlog_warn( + "ISIS-TLV: invalid IPv4 extended reachability SubTLVs have oversize"); + XFREE(MTYPE_ISIS_TLV, reach); + return ISIS_WARNING; + } + + /* Skip Sub-TLVs for now */ + pnt += subtlv_len; + length -= subtlv_len; + } + listnode_add(reach_list, reach); + } + + if (length) { + zlog_warn( + "ISIS-TLV: TE/MT ipv4 reachability TLV has trailing data"); + return ISIS_WARNING; + } + + return ISIS_OK; } -static int -parse_mt_ipv6_reachs(struct tlvs *tlvs, bool read_mtid, - unsigned int length, u_char *pnt) +static int parse_mt_ipv6_reachs(struct tlvs *tlvs, bool read_mtid, + unsigned int length, u_char *pnt) { - struct list *reach_list; - uint16_t mtid; - int rv; - - rv = parse_mtid(&mtid, read_mtid, &length, &pnt); - if (rv != ISIS_OK) - return rv; - - if (mtid == ISIS_MT_IPV4_UNICAST) - { - if (!tlvs->ipv6_reachs) - { - tlvs->ipv6_reachs = list_new(); - tlvs->ipv6_reachs->del = free_tlv; - } - reach_list = tlvs->ipv6_reachs; - } - else - { - struct tlv_mt_ipv6_reachs *reachs; - - reachs = tlvs_get_mt_ipv6_reachs(tlvs, mtid); - reachs->list->del = free_tlv; - reach_list = reachs->list; - } - - while (length >= 6) /* Metric + Control + Prefixlen */ - { - struct ipv6_reachability *reach = XCALLOC(MTYPE_ISIS_TLV, sizeof(*reach)); - - memcpy(reach, pnt, 6); /* Metric + Control + Prefixlen */ - pnt += 6; - length -= 6; - - if (reach->prefix_len > IPV6_MAX_BITLEN) - { - zlog_warn("ISIS-TLV: invalid IPv6 reachability prefix length %d", reach->prefix_len); - XFREE(MTYPE_ISIS_TLV, reach); - return ISIS_WARNING; - } - - if (length < (unsigned int)PSIZE(reach->prefix_len)) - { - zlog_warn("ISIS-TLV: invalid IPv6 reachability prefix too long for tlv"); - XFREE(MTYPE_ISIS_TLV, reach); - return ISIS_WARNING; - } - - memcpy(&reach->prefix, pnt, PSIZE(reach->prefix_len)); - pnt += PSIZE(reach->prefix_len); - length -= PSIZE(reach->prefix_len); - - if (reach->control_info & CTRL_INFO_SUBTLVS) - { - if (length < 1) - { - zlog_warn("ISIS-TLV: invalid IPv6 reachability SubTLV missing"); - XFREE(MTYPE_ISIS_TLV, reach); - return ISIS_WARNING; - } - - u_char subtlv_len = *pnt; - pnt++; - length--; - - if (length < subtlv_len) - { - zlog_warn("ISIS-TLV: invalid IPv6 reachability SubTLVs have oversize"); - XFREE(MTYPE_ISIS_TLV, reach); - return ISIS_WARNING; - } - - /* Skip Sub-TLVs for now */ - pnt += subtlv_len; - length -= subtlv_len; - } - listnode_add(reach_list, reach); - } - - if (length) - { - zlog_warn("ISIS-TLV: (MT) IPv6 reachability TLV has trailing data"); - return ISIS_WARNING; - } - - return ISIS_OK; + struct list *reach_list; + uint16_t mtid; + int rv; + + rv = parse_mtid(&mtid, read_mtid, &length, &pnt); + if (rv != ISIS_OK) + return rv; + + if (mtid == ISIS_MT_IPV4_UNICAST) { + if (!tlvs->ipv6_reachs) { + tlvs->ipv6_reachs = list_new(); + tlvs->ipv6_reachs->del = free_tlv; + } + reach_list = tlvs->ipv6_reachs; + } else { + struct tlv_mt_ipv6_reachs *reachs; + + reachs = tlvs_get_mt_ipv6_reachs(tlvs, mtid); + reachs->list->del = free_tlv; + reach_list = reachs->list; + } + + while (length >= 6) /* Metric + Control + Prefixlen */ + { + struct ipv6_reachability *reach = + XCALLOC(MTYPE_ISIS_TLV, sizeof(*reach)); + + memcpy(reach, pnt, 6); /* Metric + Control + Prefixlen */ + pnt += 6; + length -= 6; + + if (reach->prefix_len > IPV6_MAX_BITLEN) { + zlog_warn( + "ISIS-TLV: invalid IPv6 reachability prefix length %d", + reach->prefix_len); + XFREE(MTYPE_ISIS_TLV, reach); + return ISIS_WARNING; + } + + if (length < (unsigned int)PSIZE(reach->prefix_len)) { + zlog_warn( + "ISIS-TLV: invalid IPv6 reachability prefix too long for tlv"); + XFREE(MTYPE_ISIS_TLV, reach); + return ISIS_WARNING; + } + + memcpy(&reach->prefix, pnt, PSIZE(reach->prefix_len)); + pnt += PSIZE(reach->prefix_len); + length -= PSIZE(reach->prefix_len); + + if (reach->control_info & CTRL_INFO_SUBTLVS) { + if (length < 1) { + zlog_warn( + "ISIS-TLV: invalid IPv6 reachability SubTLV missing"); + XFREE(MTYPE_ISIS_TLV, reach); + return ISIS_WARNING; + } + + u_char subtlv_len = *pnt; + pnt++; + length--; + + if (length < subtlv_len) { + zlog_warn( + "ISIS-TLV: invalid IPv6 reachability SubTLVs have oversize"); + XFREE(MTYPE_ISIS_TLV, reach); + return ISIS_WARNING; + } + + /* Skip Sub-TLVs for now */ + pnt += subtlv_len; + length -= subtlv_len; + } + listnode_add(reach_list, reach); + } + + if (length) { + zlog_warn( + "ISIS-TLV: (MT) IPv6 reachability TLV has trailing data"); + return ISIS_WARNING; + } + + return ISIS_OK; } /* * Parses the tlvs found in the variant length part of the PDU. * Caller tells with flags in "expected" which TLV's it is interested in. */ -int -parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected, - u_int32_t * found, struct tlvs *tlvs, u_int32_t *auth_tlv_offset) +int parse_tlvs(char *areatag, u_char *stream, int size, u_int32_t *expected, + u_int32_t *found, struct tlvs *tlvs, u_int32_t *auth_tlv_offset) { - u_char type, length; - struct lan_neigh *lan_nei; - struct area_addr *area_addr; - struct is_neigh *is_nei; - struct es_neigh *es_nei; - struct lsp_entry *lsp_entry; - struct in_addr *ipv4_addr; - struct ipv4_reachability *ipv4_reach; - struct in6_addr *ipv6_addr; - int value_len, retval = ISIS_OK; - u_char *start = stream, *pnt = stream; - - *found = 0; - memset (tlvs, 0, sizeof (struct tlvs)); - - while (pnt < stream + size - 2) - { - type = *pnt; - length = *(pnt + 1); - pnt += 2; - value_len = 0; - if (pnt + length > stream + size) - { - zlog_warn ("ISIS-TLV (%s): TLV (type %d, length %d) exceeds packet " - "boundaries", areatag, type, length); - retval = ISIS_WARNING; - break; - } - switch (type) - { - case AREA_ADDRESSES: - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Address Length | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Area Address | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * : : - */ - *found |= TLVFLAG_AREA_ADDRS; + u_char type, length; + struct lan_neigh *lan_nei; + struct area_addr *area_addr; + struct is_neigh *is_nei; + struct es_neigh *es_nei; + struct lsp_entry *lsp_entry; + struct in_addr *ipv4_addr; + struct ipv4_reachability *ipv4_reach; + struct in6_addr *ipv6_addr; + int value_len, retval = ISIS_OK; + u_char *start = stream, *pnt = stream; + + *found = 0; + memset(tlvs, 0, sizeof(struct tlvs)); + + while (pnt < stream + size - 2) { + type = *pnt; + length = *(pnt + 1); + pnt += 2; + value_len = 0; + if (pnt + length > stream + size) { + zlog_warn( + "ISIS-TLV (%s): TLV (type %d, length %d) exceeds packet " + "boundaries", + areatag, type, length); + retval = ISIS_WARNING; + break; + } + switch (type) { + case AREA_ADDRESSES: + /* +-------+-------+-------+-------+-------+-------+-------+-------+ + * | Address Length | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | Area Address | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * : : + */ + *found |= TLVFLAG_AREA_ADDRS; #ifdef EXTREME_TLV_DEBUG - zlog_debug ("TLV Area Adresses len %d", length); + zlog_debug("TLV Area Adresses len %d", length); #endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_AREA_ADDRS) - { - while (length > value_len) - { - area_addr = (struct area_addr *) pnt; - value_len += area_addr->addr_len + 1; - pnt += area_addr->addr_len + 1; - if (!tlvs->area_addrs) - tlvs->area_addrs = list_new (); - listnode_add (tlvs->area_addrs, area_addr); - } - } - else - { - pnt += length; - } - break; - - case IS_NEIGHBOURS: - *found |= TLVFLAG_IS_NEIGHS; + if (*expected & TLVFLAG_AREA_ADDRS) { + while (length > value_len) { + area_addr = (struct area_addr *)pnt; + value_len += area_addr->addr_len + 1; + pnt += area_addr->addr_len + 1; + if (!tlvs->area_addrs) + tlvs->area_addrs = list_new(); + listnode_add(tlvs->area_addrs, + area_addr); + } + } else { + pnt += length; + } + break; + + case IS_NEIGHBOURS: + *found |= TLVFLAG_IS_NEIGHS; #ifdef EXTREME_TLV_DEBUG - zlog_debug ("ISIS-TLV (%s): IS Neighbours length %d", - areatag, length); + zlog_debug("ISIS-TLV (%s): IS Neighbours length %d", + areatag, length); #endif /* EXTREME_TLV_DEBUG */ - if (TLVFLAG_IS_NEIGHS & *expected) - { - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Virtual Flag | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - */ - pnt++; - value_len++; - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | 0 | I/E | Default Metric | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Delay Metric | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Expense Metric | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Error Metric | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Neighbour ID | - * +---------------------------------------------------------------+ - * : : - */ - while (length > value_len) - { - is_nei = (struct is_neigh *) pnt; - value_len += 4 + ISIS_SYS_ID_LEN + 1; - pnt += 4 + ISIS_SYS_ID_LEN + 1; - if (!tlvs->is_neighs) - tlvs->is_neighs = list_new (); - listnode_add (tlvs->is_neighs, is_nei); - } - } - else - { - pnt += length; - } - break; - - case TE_IS_NEIGHBOURS: - *found |= TLVFLAG_TE_IS_NEIGHS; + if (TLVFLAG_IS_NEIGHS & *expected) { + /* +-------+-------+-------+-------+-------+-------+-------+-------+ + * | Virtual Flag | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + */ + pnt++; + value_len++; + /* +-------+-------+-------+-------+-------+-------+-------+-------+ + * | 0 | I/E | Default + * Metric | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | S | I/E | Delay Metric + * | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | S | I/E | Expense + * Metric | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | S | I/E | Error Metric + * | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | Neighbour ID | + * +---------------------------------------------------------------+ + * : : + */ + while (length > value_len) { + is_nei = (struct is_neigh *)pnt; + value_len += 4 + ISIS_SYS_ID_LEN + 1; + pnt += 4 + ISIS_SYS_ID_LEN + 1; + if (!tlvs->is_neighs) + tlvs->is_neighs = list_new(); + listnode_add(tlvs->is_neighs, is_nei); + } + } else { + pnt += length; + } + break; + + case TE_IS_NEIGHBOURS: + *found |= TLVFLAG_TE_IS_NEIGHS; #ifdef EXTREME_TLV_DEBUG - zlog_debug ("ISIS-TLV (%s): Extended IS Neighbours length %d", - areatag, length); + zlog_debug( + "ISIS-TLV (%s): Extended IS Neighbours length %d", + areatag, length); #endif /* EXTREME_TLV_DEBUG */ - if (TLVFLAG_TE_IS_NEIGHS & *expected) - retval = parse_mt_is_neighs(tlvs, false, length, pnt); - pnt += length; - break; - - case MT_IS_NEIGHBOURS: - *found |= TLVFLAG_TE_IS_NEIGHS; + if (TLVFLAG_TE_IS_NEIGHS & *expected) + retval = parse_mt_is_neighs(tlvs, false, length, + pnt); + pnt += length; + break; + + case MT_IS_NEIGHBOURS: + *found |= TLVFLAG_TE_IS_NEIGHS; #ifdef EXTREME_TLV_DEBUG - zlog_debug ("ISIS-TLV (%s): MT IS Neighbours length %d", - areatag, length); + zlog_debug("ISIS-TLV (%s): MT IS Neighbours length %d", + areatag, length); #endif - if (TLVFLAG_TE_IS_NEIGHS & *expected) - retval = parse_mt_is_neighs(tlvs, true, length, pnt); - pnt += length; - break; - - case ES_NEIGHBOURS: - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | 0 | I/E | Default Metric | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Delay Metric | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Expense Metric | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Error Metric | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Neighbour ID | - * +---------------------------------------------------------------+ - * | Neighbour ID | - * +---------------------------------------------------------------+ - * : : - */ + if (TLVFLAG_TE_IS_NEIGHS & *expected) + retval = parse_mt_is_neighs(tlvs, true, length, + pnt); + pnt += length; + break; + + case ES_NEIGHBOURS: +/* +-------+-------+-------+-------+-------+-------+-------+-------+ + * | 0 | I/E | Default Metric | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | S | I/E | Delay Metric | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | S | I/E | Expense Metric | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | S | I/E | Error Metric | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | Neighbour ID | + * +---------------------------------------------------------------+ + * | Neighbour ID | + * +---------------------------------------------------------------+ + * : : + */ #ifdef EXTREME_TLV_DEBUG - zlog_debug ("ISIS-TLV (%s): ES Neighbours length %d", - areatag, length); + zlog_debug("ISIS-TLV (%s): ES Neighbours length %d", + areatag, length); #endif /* EXTREME_TLV_DEBUG */ - *found |= TLVFLAG_ES_NEIGHS; - if (*expected & TLVFLAG_ES_NEIGHS) - { - es_nei = (struct es_neigh *) pnt; - value_len += 4; - pnt += 4; - while (length > value_len) - { - /* FIXME FIXME FIXME - add to the list */ - /* sys_id->id = pnt; */ - value_len += ISIS_SYS_ID_LEN; - pnt += ISIS_SYS_ID_LEN; - /* if (!es_nei->neigh_ids) es_nei->neigh_ids = sysid; */ - } - if (!tlvs->es_neighs) - tlvs->es_neighs = list_new (); - listnode_add (tlvs->es_neighs, es_nei); - } - else - { - pnt += length; - } - break; - - case LAN_NEIGHBOURS: - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | LAN Address | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * : : - */ - *found |= TLVFLAG_LAN_NEIGHS; + *found |= TLVFLAG_ES_NEIGHS; + if (*expected & TLVFLAG_ES_NEIGHS) { + es_nei = (struct es_neigh *)pnt; + value_len += 4; + pnt += 4; + while (length > value_len) { + /* FIXME FIXME FIXME - add to the list + */ + /* sys_id->id = pnt; */ + value_len += ISIS_SYS_ID_LEN; + pnt += ISIS_SYS_ID_LEN; + /* if (!es_nei->neigh_ids) + * es_nei->neigh_ids = sysid; */ + } + if (!tlvs->es_neighs) + tlvs->es_neighs = list_new(); + listnode_add(tlvs->es_neighs, es_nei); + } else { + pnt += length; + } + break; + + case LAN_NEIGHBOURS: + /* +-------+-------+-------+-------+-------+-------+-------+-------+ + * | LAN Address | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * : : + */ + *found |= TLVFLAG_LAN_NEIGHS; #ifdef EXTREME_TLV_DEBUG - zlog_debug ("ISIS-TLV (%s): LAN Neigbours length %d", - areatag, length); + zlog_debug("ISIS-TLV (%s): LAN Neigbours length %d", + areatag, length); #endif /* EXTREME_TLV_DEBUG */ - if (TLVFLAG_LAN_NEIGHS & *expected) - { - while (length > value_len) - { - lan_nei = (struct lan_neigh *) pnt; - if (!tlvs->lan_neighs) - tlvs->lan_neighs = list_new (); - listnode_add (tlvs->lan_neighs, lan_nei); - value_len += ETH_ALEN; - pnt += ETH_ALEN; - } - } - else - { - pnt += length; - } - break; - - case PADDING: + if (TLVFLAG_LAN_NEIGHS & *expected) { + while (length > value_len) { + lan_nei = (struct lan_neigh *)pnt; + if (!tlvs->lan_neighs) + tlvs->lan_neighs = list_new(); + listnode_add(tlvs->lan_neighs, lan_nei); + value_len += ETH_ALEN; + pnt += ETH_ALEN; + } + } else { + pnt += length; + } + break; + + case PADDING: #ifdef EXTREME_TLV_DEBUG - zlog_debug ("TLV padding %d", length); + zlog_debug("TLV padding %d", length); #endif /* EXTREME_TLV_DEBUG */ - pnt += length; - break; - - case LSP_ENTRIES: - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Remaining Lifetime | 2 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | LSP ID | id+2 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | LSP Sequence Number | 4 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Checksum | 2 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - */ + pnt += length; + break; + + case LSP_ENTRIES: +/* +-------+-------+-------+-------+-------+-------+-------+-------+ + * | Remaining Lifetime | 2 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | LSP ID | id+2 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | LSP Sequence Number | 4 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | Checksum | 2 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + */ #ifdef EXTREME_TLV_DEBUG - zlog_debug ("ISIS-TLV (%s): LSP Entries length %d", areatag, length); + zlog_debug("ISIS-TLV (%s): LSP Entries length %d", + areatag, length); #endif /* EXTREME_TLV_DEBUG */ - *found |= TLVFLAG_LSP_ENTRIES; - if (TLVFLAG_LSP_ENTRIES & *expected) - { - while (length > value_len) - { - lsp_entry = (struct lsp_entry *) pnt; - value_len += 10 + ISIS_SYS_ID_LEN; - pnt += 10 + ISIS_SYS_ID_LEN; - if (!tlvs->lsp_entries) - tlvs->lsp_entries = list_new (); - listnode_add (tlvs->lsp_entries, lsp_entry); - } - } - else - { - pnt += length; - } - break; - - case CHECKSUM: - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | 16 bit fletcher CHECKSUM | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * : : - */ - *found |= TLVFLAG_CHECKSUM; + *found |= TLVFLAG_LSP_ENTRIES; + if (TLVFLAG_LSP_ENTRIES & *expected) { + while (length > value_len) { + lsp_entry = (struct lsp_entry *)pnt; + value_len += 10 + ISIS_SYS_ID_LEN; + pnt += 10 + ISIS_SYS_ID_LEN; + if (!tlvs->lsp_entries) + tlvs->lsp_entries = list_new(); + listnode_add(tlvs->lsp_entries, + lsp_entry); + } + } else { + pnt += length; + } + break; + + case CHECKSUM: + /* +-------+-------+-------+-------+-------+-------+-------+-------+ + * | 16 bit fletcher CHECKSUM | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * : : + */ + *found |= TLVFLAG_CHECKSUM; #ifdef EXTREME_TLV_DEBUG - zlog_debug ("ISIS-TLV (%s): Checksum length %d", areatag, length); + zlog_debug("ISIS-TLV (%s): Checksum length %d", areatag, + length); #endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_CHECKSUM) - { - tlvs->checksum = (struct checksum *) pnt; - } - pnt += length; - break; - - case PROTOCOLS_SUPPORTED: - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | NLPID | - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * : : - */ - *found |= TLVFLAG_NLPID; + if (*expected & TLVFLAG_CHECKSUM) { + tlvs->checksum = (struct checksum *)pnt; + } + pnt += length; + break; + + case PROTOCOLS_SUPPORTED: + /* +-------+-------+-------+-------+-------+-------+-------+-------+ + * | NLPID | + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * : : + */ + *found |= TLVFLAG_NLPID; #ifdef EXTREME_TLV_DEBUG - zlog_debug ("ISIS-TLV (%s): Protocols Supported length %d", - areatag, length); + zlog_debug( + "ISIS-TLV (%s): Protocols Supported length %d", + areatag, length); #endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_NLPID) - { - tlvs->nlpids = (struct nlpids *) (pnt - 1); - } - pnt += length; - break; - - case IPV4_ADDR: - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * + IP version 4 address + 4 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * : : - */ - *found |= TLVFLAG_IPV4_ADDR; + if (*expected & TLVFLAG_NLPID) { + tlvs->nlpids = (struct nlpids *)(pnt - 1); + } + pnt += length; + break; + + case IPV4_ADDR: + /* +-------+-------+-------+-------+-------+-------+-------+-------+ + * + IP version 4 address + 4 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * : : + */ + *found |= TLVFLAG_IPV4_ADDR; #ifdef EXTREME_TLV_DEBUG - zlog_debug ("ISIS-TLV (%s): IPv4 Address length %d", - areatag, length); + zlog_debug("ISIS-TLV (%s): IPv4 Address length %d", + areatag, length); #endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_IPV4_ADDR) - { - while (length > value_len) - { - ipv4_addr = (struct in_addr *) pnt; + if (*expected & TLVFLAG_IPV4_ADDR) { + while (length > value_len) { + ipv4_addr = (struct in_addr *)pnt; #ifdef EXTREME_TLV_DEBUG - zlog_debug ("ISIS-TLV (%s) : IP ADDR %s, pnt %p", areatag, - inet_ntoa (*ipv4_addr), pnt); + zlog_debug( + "ISIS-TLV (%s) : IP ADDR %s, pnt %p", + areatag, inet_ntoa(*ipv4_addr), + pnt); #endif /* EXTREME_TLV_DEBUG */ - if (!tlvs->ipv4_addrs) - tlvs->ipv4_addrs = list_new (); - listnode_add (tlvs->ipv4_addrs, ipv4_addr); - value_len += 4; - pnt += 4; - } - } - else - { - pnt += length; - } - break; - - case AUTH_INFO: - *found |= TLVFLAG_AUTH_INFO; + if (!tlvs->ipv4_addrs) + tlvs->ipv4_addrs = list_new(); + listnode_add(tlvs->ipv4_addrs, + ipv4_addr); + value_len += 4; + pnt += 4; + } + } else { + pnt += length; + } + break; + + case AUTH_INFO: + *found |= TLVFLAG_AUTH_INFO; #ifdef EXTREME_TLV_DEBUG - zlog_debug ("ISIS-TLV (%s): IS-IS Authentication Information", - areatag); + zlog_debug( + "ISIS-TLV (%s): IS-IS Authentication Information", + areatag); #endif - if (*expected & TLVFLAG_AUTH_INFO) - { - tlvs->auth_info.type = *pnt; - if (length == 0) - { - zlog_warn ("ISIS-TLV (%s): TLV (type %d, length %d) " - "incorrect.", areatag, type, length); - return ISIS_WARNING; - } - --length; - tlvs->auth_info.len = length; - pnt++; - memcpy (tlvs->auth_info.passwd, pnt, length); - /* Return the authentication tlv pos for later computation - * of MD5 (RFC 5304, 2) - */ - if (auth_tlv_offset) - *auth_tlv_offset += (pnt - start - 3); - pnt += length; - } - else - { - pnt += length; - } - break; - - case DYNAMIC_HOSTNAME: - *found |= TLVFLAG_DYN_HOSTNAME; + if (*expected & TLVFLAG_AUTH_INFO) { + tlvs->auth_info.type = *pnt; + if (length == 0) { + zlog_warn( + "ISIS-TLV (%s): TLV (type %d, length %d) " + "incorrect.", + areatag, type, length); + return ISIS_WARNING; + } + --length; + tlvs->auth_info.len = length; + pnt++; + memcpy(tlvs->auth_info.passwd, pnt, length); + /* Return the authentication tlv pos for later + * computation + * of MD5 (RFC 5304, 2) + */ + if (auth_tlv_offset) + *auth_tlv_offset += (pnt - start - 3); + pnt += length; + } else { + pnt += length; + } + break; + + case DYNAMIC_HOSTNAME: + *found |= TLVFLAG_DYN_HOSTNAME; #ifdef EXTREME_TLV_DEBUG - zlog_debug ("ISIS-TLV (%s): Dynamic Hostname length %d", - areatag, length); + zlog_debug("ISIS-TLV (%s): Dynamic Hostname length %d", + areatag, length); #endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_DYN_HOSTNAME) - { - /* the length is also included in the pointed struct */ - tlvs->hostname = (struct hostname *) (pnt - 1); - } - pnt += length; - break; - - case TE_ROUTER_ID: - /* +---------------------------------------------------------------+ - * + Router ID + 4 - * +---------------------------------------------------------------+ - */ - *found |= TLVFLAG_TE_ROUTER_ID; + if (*expected & TLVFLAG_DYN_HOSTNAME) { + /* the length is also included in the pointed + * struct */ + tlvs->hostname = (struct hostname *)(pnt - 1); + } + pnt += length; + break; + + case TE_ROUTER_ID: + /* +---------------------------------------------------------------+ + * + Router ID + 4 + * +---------------------------------------------------------------+ + */ + *found |= TLVFLAG_TE_ROUTER_ID; #ifdef EXTREME_TLV_DEBUG - zlog_debug ("ISIS-TLV (%s): TE Router ID %d", areatag, length); + zlog_debug("ISIS-TLV (%s): TE Router ID %d", areatag, + length); #endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_TE_ROUTER_ID) - tlvs->router_id = (struct te_router_id *) (pnt); - pnt += length; - break; - - case IPV4_INT_REACHABILITY: - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | 0 | I/E | Default Metric | 1 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Delay Metric | 1 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Expense Metric | 1 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Error Metric | 1 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | ip address | 4 - * +---------------------------------------------------------------+ - * | address mask | 4 - * +---------------------------------------------------------------+ - * : : - */ - *found |= TLVFLAG_IPV4_INT_REACHABILITY; + if (*expected & TLVFLAG_TE_ROUTER_ID) + tlvs->router_id = (struct te_router_id *)(pnt); + pnt += length; + break; + + case IPV4_INT_REACHABILITY: + /* +-------+-------+-------+-------+-------+-------+-------+-------+ + * | 0 | I/E | Default Metric | 1 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | S | I/E | Delay Metric | 1 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | S | I/E | Expense Metric | 1 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | S | I/E | Error Metric | 1 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | ip address | 4 + * +---------------------------------------------------------------+ + * | address mask | 4 + * +---------------------------------------------------------------+ + * : : + */ + *found |= TLVFLAG_IPV4_INT_REACHABILITY; #ifdef EXTREME_TLV_DEBUG - zlog_debug ("ISIS-TLV (%s): IPv4 internal Reachability length %d", - areatag, length); + zlog_debug( + "ISIS-TLV (%s): IPv4 internal Reachability length %d", + areatag, length); #endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_IPV4_INT_REACHABILITY) - { - while (length > value_len) - { - ipv4_reach = (struct ipv4_reachability *) pnt; - if (!tlvs->ipv4_int_reachs) - tlvs->ipv4_int_reachs = list_new (); - listnode_add (tlvs->ipv4_int_reachs, ipv4_reach); - value_len += 12; - pnt += 12; - } - } - else - { - pnt += length; - } - break; - - case IPV4_EXT_REACHABILITY: - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | 0 | I/E | Default Metric | 1 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Delay Metric | 1 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Expense Metric | 1 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | S | I/E | Error Metric | 1 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | ip address | 4 - * +---------------------------------------------------------------+ - * | address mask | 4 - * +---------------------------------------------------------------+ - * : : - */ - *found |= TLVFLAG_IPV4_EXT_REACHABILITY; + if (*expected & TLVFLAG_IPV4_INT_REACHABILITY) { + while (length > value_len) { + ipv4_reach = + (struct ipv4_reachability *)pnt; + if (!tlvs->ipv4_int_reachs) + tlvs->ipv4_int_reachs = + list_new(); + listnode_add(tlvs->ipv4_int_reachs, + ipv4_reach); + value_len += 12; + pnt += 12; + } + } else { + pnt += length; + } + break; + + case IPV4_EXT_REACHABILITY: + /* +-------+-------+-------+-------+-------+-------+-------+-------+ + * | 0 | I/E | Default Metric | 1 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | S | I/E | Delay Metric | 1 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | S | I/E | Expense Metric | 1 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | S | I/E | Error Metric | 1 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | ip address | 4 + * +---------------------------------------------------------------+ + * | address mask | 4 + * +---------------------------------------------------------------+ + * : : + */ + *found |= TLVFLAG_IPV4_EXT_REACHABILITY; #ifdef EXTREME_TLV_DEBUG - zlog_debug ("ISIS-TLV (%s): IPv4 external Reachability length %d", - areatag, length); + zlog_debug( + "ISIS-TLV (%s): IPv4 external Reachability length %d", + areatag, length); #endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_IPV4_EXT_REACHABILITY) - { - while (length > value_len) - { - ipv4_reach = (struct ipv4_reachability *) pnt; - if (!tlvs->ipv4_ext_reachs) - tlvs->ipv4_ext_reachs = list_new (); - listnode_add (tlvs->ipv4_ext_reachs, ipv4_reach); - value_len += 12; - pnt += 12; - } - } - else - { - pnt += length; - } - break; - - case TE_IPV4_REACHABILITY: - *found |= TLVFLAG_TE_IPV4_REACHABILITY; + if (*expected & TLVFLAG_IPV4_EXT_REACHABILITY) { + while (length > value_len) { + ipv4_reach = + (struct ipv4_reachability *)pnt; + if (!tlvs->ipv4_ext_reachs) + tlvs->ipv4_ext_reachs = + list_new(); + listnode_add(tlvs->ipv4_ext_reachs, + ipv4_reach); + value_len += 12; + pnt += 12; + } + } else { + pnt += length; + } + break; + + case TE_IPV4_REACHABILITY: + *found |= TLVFLAG_TE_IPV4_REACHABILITY; #ifdef EXTREME_TLV_DEBUG - zlog_debug ("ISIS-TLV (%s): IPv4 extended Reachability length %d", - areatag, length); + zlog_debug( + "ISIS-TLV (%s): IPv4 extended Reachability length %d", + areatag, length); #endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_TE_IPV4_REACHABILITY) - retval = parse_mt_ipv4_reachs(tlvs, false, length, pnt); - pnt += length; - break; - case MT_IPV4_REACHABILITY: - *found |= TLVFLAG_TE_IPV4_REACHABILITY; + if (*expected & TLVFLAG_TE_IPV4_REACHABILITY) + retval = parse_mt_ipv4_reachs(tlvs, false, + length, pnt); + pnt += length; + break; + case MT_IPV4_REACHABILITY: + *found |= TLVFLAG_TE_IPV4_REACHABILITY; #ifdef EXTREME_TLV_DEBUG - zlog_debug ("ISIS-TLV (%s): IPv4 MT Reachability length %d", - areatag, length); + zlog_debug( + "ISIS-TLV (%s): IPv4 MT Reachability length %d", + areatag, length); #endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_TE_IPV4_REACHABILITY) - retval = parse_mt_ipv4_reachs(tlvs, true, length, pnt); - pnt += length; - break; - case IPV6_ADDR: - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * + IP version 6 address + 16 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * : : - */ - *found |= TLVFLAG_IPV6_ADDR; + if (*expected & TLVFLAG_TE_IPV4_REACHABILITY) + retval = parse_mt_ipv4_reachs(tlvs, true, + length, pnt); + pnt += length; + break; + case IPV6_ADDR: + /* +-------+-------+-------+-------+-------+-------+-------+-------+ + * + IP version 6 address + 16 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * : : + */ + *found |= TLVFLAG_IPV6_ADDR; #ifdef EXTREME_TLV_DEBUG - zlog_debug ("ISIS-TLV (%s): IPv6 Address length %d", - areatag, length); + zlog_debug("ISIS-TLV (%s): IPv6 Address length %d", + areatag, length); #endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_IPV6_ADDR) - { - while (length > value_len) - { - ipv6_addr = (struct in6_addr *) pnt; - if (!tlvs->ipv6_addrs) - tlvs->ipv6_addrs = list_new (); - listnode_add (tlvs->ipv6_addrs, ipv6_addr); - value_len += 16; - pnt += 16; - } - } - else - { - pnt += length; - } - break; - - case IPV6_REACHABILITY: - *found |= TLVFLAG_IPV6_REACHABILITY; + if (*expected & TLVFLAG_IPV6_ADDR) { + while (length > value_len) { + ipv6_addr = (struct in6_addr *)pnt; + if (!tlvs->ipv6_addrs) + tlvs->ipv6_addrs = list_new(); + listnode_add(tlvs->ipv6_addrs, + ipv6_addr); + value_len += 16; + pnt += 16; + } + } else { + pnt += length; + } + break; + + case IPV6_REACHABILITY: + *found |= TLVFLAG_IPV6_REACHABILITY; #ifdef EXTREME_TLV_DEBUG - zlog_debug ("ISIS-TLV (%s): IPv6 Reachability length %d", - areatag, length); + zlog_debug("ISIS-TLV (%s): IPv6 Reachability length %d", + areatag, length); #endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_IPV6_REACHABILITY) - retval = parse_mt_ipv6_reachs(tlvs, false, length, pnt); - pnt += length; - break; - case MT_IPV6_REACHABILITY: - *found |= TLVFLAG_IPV6_REACHABILITY; + if (*expected & TLVFLAG_IPV6_REACHABILITY) + retval = parse_mt_ipv6_reachs(tlvs, false, + length, pnt); + pnt += length; + break; + case MT_IPV6_REACHABILITY: + *found |= TLVFLAG_IPV6_REACHABILITY; #ifdef EXTREME_TLV_DEBUG - zlog_debug ("ISIS-TLV (%s): IPv6 Reachability length %d", - areatag, length); + zlog_debug("ISIS-TLV (%s): IPv6 Reachability length %d", + areatag, length); #endif /* EXTREME_TLV_DEBUG */ - if (*expected & TLVFLAG_IPV6_REACHABILITY) - retval = parse_mt_ipv6_reachs(tlvs, true, length, pnt); - pnt += length; - break; - case WAY3_HELLO: - /* +---------------------------------------------------------------+ - * | Adjacency state | 1 - * +---------------------------------------------------------------+ - * | Extended Local Circuit ID | 4 - * +---------------------------------------------------------------+ - * | Neighbor System ID (If known) | 0-8 - * (probably 6) - * +---------------------------------------------------------------+ - * | Neighbor Local Circuit ID (If known) | 4 - * +---------------------------------------------------------------+ - */ - *found |= TLVFLAG_3WAY_HELLO; - if (*expected & TLVFLAG_3WAY_HELLO) - { - while (length > value_len) - { - /* FIXME: make this work */ -/* Adjacency State (one octet): - 0 = Up - 1 = Initializing - 2 = Down - Extended Local Circuit ID (four octets) - Neighbor System ID if known (zero to eight octets) - Neighbor Extended Local Circuit ID (four octets, if Neighbor - System ID is present) */ - pnt += length; - value_len += length; + if (*expected & TLVFLAG_IPV6_REACHABILITY) + retval = parse_mt_ipv6_reachs(tlvs, true, + length, pnt); + pnt += length; + break; + case WAY3_HELLO: + /* +---------------------------------------------------------------+ + * | Adjacency state | 1 + * +---------------------------------------------------------------+ + * | Extended Local Circuit ID | 4 + * +---------------------------------------------------------------+ + * | Neighbor System ID (If known) + * | 0-8 + * (probably 6) + * +---------------------------------------------------------------+ + * | Neighbor Local Circuit ID (If + * known) | 4 + * +---------------------------------------------------------------+ + */ + *found |= TLVFLAG_3WAY_HELLO; + if (*expected & TLVFLAG_3WAY_HELLO) { + while (length > value_len) { + /* FIXME: make this work */ + /* Adjacency State (one + octet): + 0 = Up + 1 = Initializing + 2 = Down + Extended Local Circuit ID + (four octets) + Neighbor System ID if known + (zero to eight octets) + Neighbor Extended Local + Circuit ID (four octets, if Neighbor + System ID is present) */ + pnt += length; + value_len += length; + } + } else { + pnt += length; + } + + break; + case GRACEFUL_RESTART: + /* +-------+-------+-------+-------+-------+-------+-------+-------+ + * | Reserved | SA | RA + * | RR | 1 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | Remaining Time | 2 + * +---------------------------------------------------------------+ + * | Restarting Neighbor ID (If known) + * | 0-8 + * +---------------------------------------------------------------+ + */ + *found |= TLVFLAG_GRACEFUL_RESTART; + if (*expected & TLVFLAG_GRACEFUL_RESTART) { + /* FIXME: make this work */ + } + pnt += length; + break; + + case MT_ROUTER_INFORMATION: + *found |= TLVFLAG_MT_ROUTER_INFORMATION; + if (*expected & TLVFLAG_MT_ROUTER_INFORMATION) { + if (!tlvs->mt_router_info) { + tlvs->mt_router_info = list_new(); + tlvs->mt_router_info->del = free_tlv; + } + while (length > value_len) { + uint16_t mt_info; + struct mt_router_info *info; + + if (value_len + sizeof(mt_info) + > length) { + zlog_warn( + "ISIS-TLV (%s): TLV 229 is truncated.", + areatag); + pnt += length - value_len; + break; + } + + memcpy(&mt_info, pnt, sizeof(mt_info)); + pnt += sizeof(mt_info); + value_len += sizeof(mt_info); + + mt_info = ntohs(mt_info); + info = XCALLOC(MTYPE_ISIS_TLV, + sizeof(*info)); + info->mtid = mt_info & ISIS_MT_MASK; + info->overload = + mt_info & ISIS_MT_OL_MASK; + listnode_add(tlvs->mt_router_info, + info); + } + } else { + pnt += length; + } + break; + default: + zlog_warn( + "ISIS-TLV (%s): unsupported TLV type %d, length %d", + areatag, type, length); + + pnt += length; + break; } - } - else - { - pnt += length; - } - - break; - case GRACEFUL_RESTART: - /* +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Reserved | SA | RA | RR | 1 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | Remaining Time | 2 - * +---------------------------------------------------------------+ - * | Restarting Neighbor ID (If known) | 0-8 - * +---------------------------------------------------------------+ - */ - *found |= TLVFLAG_GRACEFUL_RESTART; - if (*expected & TLVFLAG_GRACEFUL_RESTART) - { - /* FIXME: make this work */ - } - pnt += length; - break; - - case MT_ROUTER_INFORMATION: - *found |= TLVFLAG_MT_ROUTER_INFORMATION; - if (*expected & TLVFLAG_MT_ROUTER_INFORMATION) - { - if (!tlvs->mt_router_info) - { - tlvs->mt_router_info = list_new(); - tlvs->mt_router_info->del = free_tlv; - } - while (length > value_len) - { - uint16_t mt_info; - struct mt_router_info *info; - - if (value_len + sizeof(mt_info) > length) { - zlog_warn("ISIS-TLV (%s): TLV 229 is truncated.", areatag); - pnt += length - value_len; - break; - } - - memcpy(&mt_info, pnt, sizeof(mt_info)); - pnt += sizeof(mt_info); - value_len += sizeof(mt_info); - - mt_info = ntohs(mt_info); - info = XCALLOC(MTYPE_ISIS_TLV, sizeof(*info)); - info->mtid = mt_info & ISIS_MT_MASK; - info->overload = mt_info & ISIS_MT_OL_MASK; - listnode_add(tlvs->mt_router_info, info); - } - } - else - { - pnt += length; - } - break; - default: - zlog_warn ("ISIS-TLV (%s): unsupported TLV type %d, length %d", - areatag, type, length); - - pnt += length; - break; + /* Abort Parsing if error occured */ + if (retval != ISIS_OK) + return retval; } - /* Abort Parsing if error occured */ - if (retval != ISIS_OK) - return retval; - } - return retval; + return retval; } -int -add_tlv (u_char tag, u_char len, u_char * value, struct stream *stream) +int add_tlv(u_char tag, u_char len, u_char *value, struct stream *stream) { - if ((stream_get_size (stream) - stream_get_endp (stream)) < - (((unsigned)len) + 2)) - { - zlog_warn ("No room for TLV of type %d " - "(total size %d available %d required %d)", - tag, (int)stream_get_size (stream), - (int)(stream_get_size (stream) - stream_get_endp (stream)), - len+2); - return ISIS_WARNING; - } - - stream_putc (stream, tag); /* TAG */ - stream_putc (stream, len); /* LENGTH */ - stream_put (stream, value, (int) len); /* VALUE */ + if ((stream_get_size(stream) - stream_get_endp(stream)) + < (((unsigned)len) + 2)) { + zlog_warn( + "No room for TLV of type %d " + "(total size %d available %d required %d)", + tag, (int)stream_get_size(stream), + (int)(stream_get_size(stream) + - stream_get_endp(stream)), + len + 2); + return ISIS_WARNING; + } + + stream_putc(stream, tag); /* TAG */ + stream_putc(stream, len); /* LENGTH */ + stream_put(stream, value, (int)len); /* VALUE */ #ifdef EXTREME_DEBUG - zlog_debug ("Added TLV %d len %d", tag, len); + zlog_debug("Added TLV %d len %d", tag, len); #endif /* EXTREME DEBUG */ - return ISIS_OK; + return ISIS_OK; } -int -tlv_add_mt_router_info (struct list *mt_router_info, struct stream *stream) +int tlv_add_mt_router_info(struct list *mt_router_info, struct stream *stream) { - struct listnode *node; - struct mt_router_info *info; + struct listnode *node; + struct mt_router_info *info; - uint16_t value[127]; - uint16_t *pos = value; + uint16_t value[127]; + uint16_t *pos = value; - for (ALL_LIST_ELEMENTS_RO(mt_router_info, node, info)) - { - uint16_t mt_info; + for (ALL_LIST_ELEMENTS_RO(mt_router_info, node, info)) { + uint16_t mt_info; - mt_info = info->mtid; - if (info->overload) - mt_info |= ISIS_MT_OL_MASK; + mt_info = info->mtid; + if (info->overload) + mt_info |= ISIS_MT_OL_MASK; - *pos = htons(mt_info); - pos++; - } + *pos = htons(mt_info); + pos++; + } - return add_tlv(MT_ROUTER_INFORMATION, (pos - value) * sizeof(*pos), - (u_char*)value, stream); + return add_tlv(MT_ROUTER_INFORMATION, (pos - value) * sizeof(*pos), + (u_char *)value, stream); } -int -tlv_add_area_addrs (struct list *area_addrs, struct stream *stream) +int tlv_add_area_addrs(struct list *area_addrs, struct stream *stream) { - struct listnode *node; - struct area_addr *area_addr; - - u_char value[255]; - u_char *pos = value; - - for (ALL_LIST_ELEMENTS_RO (area_addrs, node, area_addr)) - { - if (pos - value + area_addr->addr_len > 255) - goto err; - *pos = area_addr->addr_len; - pos++; - memcpy (pos, area_addr->area_addr, (int) area_addr->addr_len); - pos += area_addr->addr_len; - } + struct listnode *node; + struct area_addr *area_addr; + + u_char value[255]; + u_char *pos = value; + + for (ALL_LIST_ELEMENTS_RO(area_addrs, node, area_addr)) { + if (pos - value + area_addr->addr_len > 255) + goto err; + *pos = area_addr->addr_len; + pos++; + memcpy(pos, area_addr->area_addr, (int)area_addr->addr_len); + pos += area_addr->addr_len; + } - return add_tlv (AREA_ADDRESSES, pos - value, value, stream); + return add_tlv(AREA_ADDRESSES, pos - value, value, stream); err: - zlog_warn ("tlv_add_area_addrs(): TLV longer than 255"); - return ISIS_WARNING; + zlog_warn("tlv_add_area_addrs(): TLV longer than 255"); + return ISIS_WARNING; } -int -tlv_add_is_neighs (struct list *is_neighs, struct stream *stream) +int tlv_add_is_neighs(struct list *is_neighs, struct stream *stream) { - struct listnode *node; - struct is_neigh *is_neigh; - u_char value[255]; - u_char *pos = value; - int retval; - - *pos = 0; /*is_neigh->virtual; */ - pos++; - - for (ALL_LIST_ELEMENTS_RO (is_neighs, node, is_neigh)) - { - if (pos - value + IS_NEIGHBOURS_LEN > 255) - { - retval = add_tlv (IS_NEIGHBOURS, pos - value, value, stream); - if (retval != ISIS_OK) - return retval; - pos = value; + struct listnode *node; + struct is_neigh *is_neigh; + u_char value[255]; + u_char *pos = value; + int retval; + + *pos = 0; /*is_neigh->virtual; */ + pos++; + + for (ALL_LIST_ELEMENTS_RO(is_neighs, node, is_neigh)) { + if (pos - value + IS_NEIGHBOURS_LEN > 255) { + retval = add_tlv(IS_NEIGHBOURS, pos - value, value, + stream); + if (retval != ISIS_OK) + return retval; + pos = value; + } + *pos = is_neigh->metrics.metric_default; + pos++; + *pos = is_neigh->metrics.metric_delay; + pos++; + *pos = is_neigh->metrics.metric_expense; + pos++; + *pos = is_neigh->metrics.metric_error; + pos++; + memcpy(pos, is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1); + pos += ISIS_SYS_ID_LEN + 1; } - *pos = is_neigh->metrics.metric_default; - pos++; - *pos = is_neigh->metrics.metric_delay; - pos++; - *pos = is_neigh->metrics.metric_expense; - pos++; - *pos = is_neigh->metrics.metric_error; - pos++; - memcpy (pos, is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1); - pos += ISIS_SYS_ID_LEN + 1; - } - - return add_tlv (IS_NEIGHBOURS, pos - value, value, stream); + + return add_tlv(IS_NEIGHBOURS, pos - value, value, stream); } -static size_t -max_tlv_size(struct stream *stream) +static size_t max_tlv_size(struct stream *stream) { - size_t avail = stream_get_size (stream) - stream_get_endp(stream); + size_t avail = stream_get_size(stream) - stream_get_endp(stream); - if (avail < 2) - return 0; + if (avail < 2) + return 0; - if (avail < 257) - return avail - 2; + if (avail < 257) + return avail - 2; - return 255; + return 255; } -unsigned int -tlv_add_te_is_neighs (struct list *te_is_neighs, struct stream *stream, void *arg) +unsigned int tlv_add_te_is_neighs(struct list *te_is_neighs, + struct stream *stream, void *arg) { - struct listnode *node; - struct te_is_neigh *te_is_neigh; - u_char value[255]; - u_char *pos = value; - uint16_t mtid = arg ? *(uint16_t*)arg : ISIS_MT_IPV4_UNICAST; - unsigned int consumed = 0; - size_t max_size = max_tlv_size(stream); - - if (mtid != ISIS_MT_IPV4_UNICAST) - { - uint16_t mtid_conversion = ntohs(mtid); - memcpy(pos, &mtid_conversion, sizeof(mtid_conversion)); - pos += sizeof(mtid_conversion); - } - - for (ALL_LIST_ELEMENTS_RO (te_is_neighs, node, te_is_neigh)) - { - /* FIXME: Check if Total SubTLVs size doesn't exceed 255 */ - if ((size_t)(pos - value) + IS_NEIGHBOURS_LEN + te_is_neigh->sub_tlvs_length > max_size) - break; - - memcpy (pos, te_is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1); - pos += ISIS_SYS_ID_LEN + 1; - memcpy (pos, te_is_neigh->te_metric, 3); - pos += 3; - /* Set the total size of Sub TLVs */ - *pos = te_is_neigh->sub_tlvs_length; - pos++; - /* Copy Sub TLVs if any */ - if (te_is_neigh->sub_tlvs_length > 0) - { - memcpy (pos, te_is_neigh->sub_tlvs, te_is_neigh->sub_tlvs_length); - pos += te_is_neigh->sub_tlvs_length; - } - consumed++; - } - - if (consumed) - { - int rv = add_tlv ((mtid != ISIS_MT_IPV4_UNICAST) ? MT_IS_NEIGHBOURS - : TE_IS_NEIGHBOURS, - pos - value, value, stream); - assert(rv == ISIS_OK); - } - return consumed; + struct listnode *node; + struct te_is_neigh *te_is_neigh; + u_char value[255]; + u_char *pos = value; + uint16_t mtid = arg ? *(uint16_t *)arg : ISIS_MT_IPV4_UNICAST; + unsigned int consumed = 0; + size_t max_size = max_tlv_size(stream); + + if (mtid != ISIS_MT_IPV4_UNICAST) { + uint16_t mtid_conversion = ntohs(mtid); + memcpy(pos, &mtid_conversion, sizeof(mtid_conversion)); + pos += sizeof(mtid_conversion); + } + + for (ALL_LIST_ELEMENTS_RO(te_is_neighs, node, te_is_neigh)) { + /* FIXME: Check if Total SubTLVs size doesn't exceed 255 */ + if ((size_t)(pos - value) + IS_NEIGHBOURS_LEN + + te_is_neigh->sub_tlvs_length + > max_size) + break; + + memcpy(pos, te_is_neigh->neigh_id, ISIS_SYS_ID_LEN + 1); + pos += ISIS_SYS_ID_LEN + 1; + memcpy(pos, te_is_neigh->te_metric, 3); + pos += 3; + /* Set the total size of Sub TLVs */ + *pos = te_is_neigh->sub_tlvs_length; + pos++; + /* Copy Sub TLVs if any */ + if (te_is_neigh->sub_tlvs_length > 0) { + memcpy(pos, te_is_neigh->sub_tlvs, + te_is_neigh->sub_tlvs_length); + pos += te_is_neigh->sub_tlvs_length; + } + consumed++; + } + + if (consumed) { + int rv = add_tlv((mtid != ISIS_MT_IPV4_UNICAST) + ? MT_IS_NEIGHBOURS + : TE_IS_NEIGHBOURS, + pos - value, value, stream); + assert(rv == ISIS_OK); + } + return consumed; } -int -tlv_add_lan_neighs (struct list *lan_neighs, struct stream *stream) +int tlv_add_lan_neighs(struct list *lan_neighs, struct stream *stream) { - struct listnode *node; - u_char *snpa; - u_char value[255]; - u_char *pos = value; - int retval; - - for (ALL_LIST_ELEMENTS_RO (lan_neighs, node, snpa)) - { - if (pos - value + ETH_ALEN > 255) - { - retval = add_tlv (LAN_NEIGHBOURS, pos - value, value, stream); - if (retval != ISIS_OK) - return retval; - pos = value; + struct listnode *node; + u_char *snpa; + u_char value[255]; + u_char *pos = value; + int retval; + + for (ALL_LIST_ELEMENTS_RO(lan_neighs, node, snpa)) { + if (pos - value + ETH_ALEN > 255) { + retval = add_tlv(LAN_NEIGHBOURS, pos - value, value, + stream); + if (retval != ISIS_OK) + return retval; + pos = value; + } + memcpy(pos, snpa, ETH_ALEN); + pos += ETH_ALEN; } - memcpy (pos, snpa, ETH_ALEN); - pos += ETH_ALEN; - } - return add_tlv (LAN_NEIGHBOURS, pos - value, value, stream); + return add_tlv(LAN_NEIGHBOURS, pos - value, value, stream); } -int -tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream) +int tlv_add_nlpid(struct nlpids *nlpids, struct stream *stream) { - return add_tlv (PROTOCOLS_SUPPORTED, nlpids->count, nlpids->nlpids, stream); + return add_tlv(PROTOCOLS_SUPPORTED, nlpids->count, nlpids->nlpids, + stream); } -int -tlv_add_authinfo (u_char auth_type, u_char auth_len, u_char *auth_value, - struct stream *stream) +int tlv_add_authinfo(u_char auth_type, u_char auth_len, u_char *auth_value, + struct stream *stream) { - u_char value[255]; - u_char *pos = value; - *pos++ = auth_type; - memcpy (pos, auth_value, auth_len); + u_char value[255]; + u_char *pos = value; + *pos++ = auth_type; + memcpy(pos, auth_value, auth_len); - return add_tlv (AUTH_INFO, auth_len + 1, value, stream); + return add_tlv(AUTH_INFO, auth_len + 1, value, stream); } -int -tlv_add_checksum (struct checksum *checksum, struct stream *stream) +int tlv_add_checksum(struct checksum *checksum, struct stream *stream) { - u_char value[255]; - u_char *pos = value; - return add_tlv (CHECKSUM, pos - value, value, stream); + u_char value[255]; + u_char *pos = value; + return add_tlv(CHECKSUM, pos - value, value, stream); } -int -tlv_add_ip_addrs (struct list *ip_addrs, struct stream *stream) +int tlv_add_ip_addrs(struct list *ip_addrs, struct stream *stream) { - struct listnode *node; - struct prefix_ipv4 *ipv4; - u_char value[255]; - u_char *pos = value; - - for (ALL_LIST_ELEMENTS_RO (ip_addrs, node, ipv4)) - { - if (pos - value + IPV4_MAX_BYTELEN > 255) - { - /* RFC 1195 s4.2: only one tuple of 63 allowed. */ - zlog_warn ("tlv_add_ip_addrs(): cutting off at 63 IP addresses"); - break; + struct listnode *node; + struct prefix_ipv4 *ipv4; + u_char value[255]; + u_char *pos = value; + + for (ALL_LIST_ELEMENTS_RO(ip_addrs, node, ipv4)) { + if (pos - value + IPV4_MAX_BYTELEN > 255) { + /* RFC 1195 s4.2: only one tuple of 63 allowed. */ + zlog_warn( + "tlv_add_ip_addrs(): cutting off at 63 IP addresses"); + break; + } + *(u_int32_t *)pos = ipv4->prefix.s_addr; + pos += IPV4_MAX_BYTELEN; } - *(u_int32_t *) pos = ipv4->prefix.s_addr; - pos += IPV4_MAX_BYTELEN; - } - return add_tlv (IPV4_ADDR, pos - value, value, stream); + return add_tlv(IPV4_ADDR, pos - value, value, stream); } /* Used to add TLV containing just one IPv4 address - either IPv4 address TLV * (in case of LSP) or TE router ID TLV. */ -int -tlv_add_in_addr (struct in_addr *addr, struct stream *stream, u_char tag) +int tlv_add_in_addr(struct in_addr *addr, struct stream *stream, u_char tag) { - u_char value[255]; - u_char *pos = value; - - memcpy (pos, addr, IPV4_MAX_BYTELEN); - pos += IPV4_MAX_BYTELEN; + u_char value[255]; + u_char *pos = value; + + memcpy(pos, addr, IPV4_MAX_BYTELEN); + pos += IPV4_MAX_BYTELEN; - return add_tlv (tag, pos - value, value, stream); + return add_tlv(tag, pos - value, value, stream); } -int -tlv_add_dynamic_hostname (struct hostname *hostname, struct stream *stream) +int tlv_add_dynamic_hostname(struct hostname *hostname, struct stream *stream) { - return add_tlv (DYNAMIC_HOSTNAME, hostname->namelen, hostname->name, - stream); + return add_tlv(DYNAMIC_HOSTNAME, hostname->namelen, hostname->name, + stream); } -int -tlv_add_lsp_entries (struct list *lsps, struct stream *stream) +int tlv_add_lsp_entries(struct list *lsps, struct stream *stream) { - struct listnode *node; - struct isis_lsp *lsp; - u_char value[255]; - u_char *pos = value; - int retval; - - for (ALL_LIST_ELEMENTS_RO (lsps, node, lsp)) - { - if (pos - value + LSP_ENTRIES_LEN > 255) - { - retval = add_tlv (LSP_ENTRIES, pos - value, value, stream); - if (retval != ISIS_OK) - return retval; - pos = value; + struct listnode *node; + struct isis_lsp *lsp; + u_char value[255]; + u_char *pos = value; + int retval; + + for (ALL_LIST_ELEMENTS_RO(lsps, node, lsp)) { + if (pos - value + LSP_ENTRIES_LEN > 255) { + retval = add_tlv(LSP_ENTRIES, pos - value, value, + stream); + if (retval != ISIS_OK) + return retval; + pos = value; + } + *((u_int16_t *)pos) = lsp->lsp_header->rem_lifetime; + pos += 2; + memcpy(pos, lsp->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 2); + pos += ISIS_SYS_ID_LEN + 2; + *((u_int32_t *)pos) = lsp->lsp_header->seq_num; + pos += 4; + *((u_int16_t *)pos) = lsp->lsp_header->checksum; + pos += 2; } - *((u_int16_t *) pos) = lsp->lsp_header->rem_lifetime; - pos += 2; - memcpy (pos, lsp->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 2); - pos += ISIS_SYS_ID_LEN + 2; - *((u_int32_t *) pos) = lsp->lsp_header->seq_num; - pos += 4; - *((u_int16_t *) pos) = lsp->lsp_header->checksum; - pos += 2; - } - - return add_tlv (LSP_ENTRIES, pos - value, value, stream); + + return add_tlv(LSP_ENTRIES, pos - value, value, stream); } -static int -tlv_add_ipv4_reachs (u_char tag, struct list *ipv4_reachs, struct stream *stream) +static int tlv_add_ipv4_reachs(u_char tag, struct list *ipv4_reachs, + struct stream *stream) { - struct listnode *node; - struct ipv4_reachability *reach; - u_char value[255]; - u_char *pos = value; - int retval; - - for (ALL_LIST_ELEMENTS_RO (ipv4_reachs, node, reach)) - { - if (pos - value + IPV4_REACH_LEN > 255) - { - retval = - add_tlv (tag, pos - value, value, stream); - if (retval != ISIS_OK) - return retval; - pos = value; + struct listnode *node; + struct ipv4_reachability *reach; + u_char value[255]; + u_char *pos = value; + int retval; + + for (ALL_LIST_ELEMENTS_RO(ipv4_reachs, node, reach)) { + if (pos - value + IPV4_REACH_LEN > 255) { + retval = add_tlv(tag, pos - value, value, stream); + if (retval != ISIS_OK) + return retval; + pos = value; + } + *pos = reach->metrics.metric_default; + pos++; + *pos = reach->metrics.metric_delay; + pos++; + *pos = reach->metrics.metric_expense; + pos++; + *pos = reach->metrics.metric_error; + pos++; + *(u_int32_t *)pos = reach->prefix.s_addr; + pos += IPV4_MAX_BYTELEN; + *(u_int32_t *)pos = reach->mask.s_addr; + pos += IPV4_MAX_BYTELEN; } - *pos = reach->metrics.metric_default; - pos++; - *pos = reach->metrics.metric_delay; - pos++; - *pos = reach->metrics.metric_expense; - pos++; - *pos = reach->metrics.metric_error; - pos++; - *(u_int32_t *) pos = reach->prefix.s_addr; - pos += IPV4_MAX_BYTELEN; - *(u_int32_t *) pos = reach->mask.s_addr; - pos += IPV4_MAX_BYTELEN; - } - - return add_tlv (tag, pos - value, value, stream); + + return add_tlv(tag, pos - value, value, stream); } -int -tlv_add_ipv4_int_reachs (struct list *ipv4_reachs, struct stream *stream) +int tlv_add_ipv4_int_reachs(struct list *ipv4_reachs, struct stream *stream) { - return tlv_add_ipv4_reachs(IPV4_INT_REACHABILITY, ipv4_reachs, stream); + return tlv_add_ipv4_reachs(IPV4_INT_REACHABILITY, ipv4_reachs, stream); } -int -tlv_add_ipv4_ext_reachs (struct list *ipv4_reachs, struct stream *stream) +int tlv_add_ipv4_ext_reachs(struct list *ipv4_reachs, struct stream *stream) { - return tlv_add_ipv4_reachs(IPV4_EXT_REACHABILITY, ipv4_reachs, stream); + return tlv_add_ipv4_reachs(IPV4_EXT_REACHABILITY, ipv4_reachs, stream); } -unsigned int -tlv_add_te_ipv4_reachs (struct list *te_ipv4_reachs, struct stream *stream, void *arg) +unsigned int tlv_add_te_ipv4_reachs(struct list *te_ipv4_reachs, + struct stream *stream, void *arg) { - struct listnode *node; - struct te_ipv4_reachability *te_reach; - u_char value[255]; - u_char *pos = value; - uint16_t mtid = arg ? *(uint16_t*)arg : ISIS_MT_IPV4_UNICAST; - unsigned int consumed = 0; - size_t max_size = max_tlv_size(stream); - - if (mtid != ISIS_MT_IPV4_UNICAST) - { - uint16_t mtid_conversion = ntohs(mtid); - memcpy(pos, &mtid_conversion, sizeof(mtid_conversion)); - pos += sizeof(mtid_conversion); - } - - for (ALL_LIST_ELEMENTS_RO (te_ipv4_reachs, node, te_reach)) - { - unsigned char prefixlen = te_reach->control & 0x3F; - - if ((size_t)(pos - value) + 5 + PSIZE(prefixlen) > max_size) - break; - - *(u_int32_t *) pos = te_reach->te_metric; - pos += 4; - *pos = te_reach->control; - pos++; - memcpy (pos, &te_reach->prefix_start, PSIZE(prefixlen)); - pos += PSIZE(prefixlen); - consumed++; - } - - if (consumed) - { - int rv = add_tlv ((mtid != ISIS_MT_IPV4_UNICAST) ? MT_IPV4_REACHABILITY - : TE_IPV4_REACHABILITY, - pos - value, value, stream); - assert(rv == ISIS_OK); - } - - return consumed; + struct listnode *node; + struct te_ipv4_reachability *te_reach; + u_char value[255]; + u_char *pos = value; + uint16_t mtid = arg ? *(uint16_t *)arg : ISIS_MT_IPV4_UNICAST; + unsigned int consumed = 0; + size_t max_size = max_tlv_size(stream); + + if (mtid != ISIS_MT_IPV4_UNICAST) { + uint16_t mtid_conversion = ntohs(mtid); + memcpy(pos, &mtid_conversion, sizeof(mtid_conversion)); + pos += sizeof(mtid_conversion); + } + + for (ALL_LIST_ELEMENTS_RO(te_ipv4_reachs, node, te_reach)) { + unsigned char prefixlen = te_reach->control & 0x3F; + + if ((size_t)(pos - value) + 5 + PSIZE(prefixlen) > max_size) + break; + + *(u_int32_t *)pos = te_reach->te_metric; + pos += 4; + *pos = te_reach->control; + pos++; + memcpy(pos, &te_reach->prefix_start, PSIZE(prefixlen)); + pos += PSIZE(prefixlen); + consumed++; + } + + if (consumed) { + int rv = add_tlv((mtid != ISIS_MT_IPV4_UNICAST) + ? MT_IPV4_REACHABILITY + : TE_IPV4_REACHABILITY, + pos - value, value, stream); + assert(rv == ISIS_OK); + } + + return consumed; } -int -tlv_add_ipv6_addrs (struct list *ipv6_addrs, struct stream *stream) +int tlv_add_ipv6_addrs(struct list *ipv6_addrs, struct stream *stream) { - struct listnode *node; - struct prefix_ipv6 *ipv6; - u_char value[255]; - u_char *pos = value; - int retval; - - for (ALL_LIST_ELEMENTS_RO (ipv6_addrs, node, ipv6)) - { - if (pos - value + IPV6_MAX_BYTELEN > 255) - { - retval = add_tlv (IPV6_ADDR, pos - value, value, stream); - if (retval != ISIS_OK) - return retval; - pos = value; + struct listnode *node; + struct prefix_ipv6 *ipv6; + u_char value[255]; + u_char *pos = value; + int retval; + + for (ALL_LIST_ELEMENTS_RO(ipv6_addrs, node, ipv6)) { + if (pos - value + IPV6_MAX_BYTELEN > 255) { + retval = add_tlv(IPV6_ADDR, pos - value, value, stream); + if (retval != ISIS_OK) + return retval; + pos = value; + } + memcpy(pos, ipv6->prefix.s6_addr, IPV6_MAX_BYTELEN); + pos += IPV6_MAX_BYTELEN; } - memcpy (pos, ipv6->prefix.s6_addr, IPV6_MAX_BYTELEN); - pos += IPV6_MAX_BYTELEN; - } - return add_tlv (IPV6_ADDR, pos - value, value, stream); + return add_tlv(IPV6_ADDR, pos - value, value, stream); } -unsigned int -tlv_add_ipv6_reachs (struct list *ipv6_reachs, struct stream *stream, void *arg) +unsigned int tlv_add_ipv6_reachs(struct list *ipv6_reachs, + struct stream *stream, void *arg) { - struct listnode *node; - struct ipv6_reachability *ip6reach; - u_char value[255]; - u_char *pos = value; - uint16_t mtid = arg ? *(uint16_t*)arg : ISIS_MT_IPV4_UNICAST; - unsigned int consumed = 0; - size_t max_size = max_tlv_size(stream); - - if (mtid != ISIS_MT_IPV4_UNICAST) - { - uint16_t mtid_conversion = ntohs(mtid); - memcpy(pos, &mtid_conversion, sizeof(mtid_conversion)); - pos += sizeof(mtid_conversion); - } - - for (ALL_LIST_ELEMENTS_RO (ipv6_reachs, node, ip6reach)) - { - if ((size_t)(pos - value) + 6 + PSIZE(ip6reach->prefix_len) > max_size) - break; - - *(uint32_t *)pos = ip6reach->metric; - pos += 4; - *pos = ip6reach->control_info; - pos++; - *pos = ip6reach->prefix_len; - pos++; - memcpy (pos, ip6reach->prefix, PSIZE(ip6reach->prefix_len)); - pos += PSIZE(ip6reach->prefix_len); - consumed++; - } - - if (consumed) - { - int rv = add_tlv ((mtid != ISIS_MT_IPV4_UNICAST) ? MT_IPV6_REACHABILITY - : IPV6_REACHABILITY, - pos - value, value, stream); - assert(rv == ISIS_OK); - } - - return consumed; + struct listnode *node; + struct ipv6_reachability *ip6reach; + u_char value[255]; + u_char *pos = value; + uint16_t mtid = arg ? *(uint16_t *)arg : ISIS_MT_IPV4_UNICAST; + unsigned int consumed = 0; + size_t max_size = max_tlv_size(stream); + + if (mtid != ISIS_MT_IPV4_UNICAST) { + uint16_t mtid_conversion = ntohs(mtid); + memcpy(pos, &mtid_conversion, sizeof(mtid_conversion)); + pos += sizeof(mtid_conversion); + } + + for (ALL_LIST_ELEMENTS_RO(ipv6_reachs, node, ip6reach)) { + if ((size_t)(pos - value) + 6 + PSIZE(ip6reach->prefix_len) + > max_size) + break; + + *(uint32_t *)pos = ip6reach->metric; + pos += 4; + *pos = ip6reach->control_info; + pos++; + *pos = ip6reach->prefix_len; + pos++; + memcpy(pos, ip6reach->prefix, PSIZE(ip6reach->prefix_len)); + pos += PSIZE(ip6reach->prefix_len); + consumed++; + } + + if (consumed) { + int rv = add_tlv((mtid != ISIS_MT_IPV4_UNICAST) + ? MT_IPV6_REACHABILITY + : IPV6_REACHABILITY, + pos - value, value, stream); + assert(rv == ISIS_OK); + } + + return consumed; } -int -tlv_add_padding (struct stream *stream) +int tlv_add_padding(struct stream *stream) { - int fullpads, i, left; - - /* - * How many times can we add full padding ? - */ - fullpads = (stream_get_size (stream) - stream_get_endp (stream)) / 257; - for (i = 0; i < fullpads; i++) - { - if (!stream_putc (stream, (u_char) PADDING)) /* TAG */ - goto err; - if (!stream_putc (stream, (u_char) 255)) /* LENGHT */ - goto err; - stream_put (stream, NULL, 255); /* zero padding */ - } - - left = stream_get_size (stream) - stream_get_endp (stream); - - if (left < 2) - return ISIS_OK; - - if (left == 2) - { - stream_putc (stream, PADDING); - stream_putc (stream, 0); - return ISIS_OK; - } - - stream_putc (stream, PADDING); - stream_putc (stream, left - 2); - stream_put (stream, NULL, left-2); - - return ISIS_OK; + int fullpads, i, left; + + /* + * How many times can we add full padding ? + */ + fullpads = (stream_get_size(stream) - stream_get_endp(stream)) / 257; + for (i = 0; i < fullpads; i++) { + if (!stream_putc(stream, (u_char)PADDING)) /* TAG */ + goto err; + if (!stream_putc(stream, (u_char)255)) /* LENGHT */ + goto err; + stream_put(stream, NULL, 255); /* zero padding */ + } + + left = stream_get_size(stream) - stream_get_endp(stream); + + if (left < 2) + return ISIS_OK; + + if (left == 2) { + stream_putc(stream, PADDING); + stream_putc(stream, 0); + return ISIS_OK; + } + + stream_putc(stream, PADDING); + stream_putc(stream, left - 2); + stream_put(stream, NULL, left - 2); + + return ISIS_OK; err: - zlog_warn ("tlv_add_padding(): no room for tlv"); - return ISIS_WARNING; + zlog_warn("tlv_add_padding(): no room for tlv"); + return ISIS_WARNING; } diff --git a/isisd/isis_tlv.h b/isisd/isis_tlv.h index e55e81bce..d06548519 100644 --- a/isisd/isis_tlv.h +++ b/isisd/isis_tlv.h @@ -3,17 +3,17 @@ * IS-IS TLV related routines * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -134,54 +134,49 @@ #define MAX_SUBTLV_SIZE 256 /* struct for neighbor */ -struct is_neigh -{ - struct metric metrics; - u_char neigh_id[ISIS_SYS_ID_LEN + 1]; +struct is_neigh { + struct metric metrics; + u_char neigh_id[ISIS_SYS_ID_LEN + 1]; }; /* struct for te metric */ -struct te_is_neigh -{ - u_char neigh_id[ISIS_SYS_ID_LEN + 1]; - u_char te_metric[3]; - u_char sub_tlvs_length; - /* Theorical Maximum SubTLVs is 256 because the sub_tlvs_length is 8 bits */ - /* Practically, 118 bytes are necessary to store all supported TE parameters */ - /* FIXME: A pointer will use less memory, but need to be free */ - /* which is hard to fix, especially within free_tlvs() function */ - /* and malloc() / free() as a CPU cost compared to the memory usage */ - u_char sub_tlvs[MAX_SUBTLV_SIZE]; /* SUB TLVs storage */ +struct te_is_neigh { + u_char neigh_id[ISIS_SYS_ID_LEN + 1]; + u_char te_metric[3]; + u_char sub_tlvs_length; + /* Theorical Maximum SubTLVs is 256 because the sub_tlvs_length is 8 + * bits */ + /* Practically, 118 bytes are necessary to store all supported TE + * parameters */ + /* FIXME: A pointer will use less memory, but need to be free */ + /* which is hard to fix, especially within free_tlvs() function */ + /* and malloc() / free() as a CPU cost compared to the memory usage */ + u_char sub_tlvs[MAX_SUBTLV_SIZE]; /* SUB TLVs storage */ }; /* Decode and encode three-octet metric into host byte order integer */ -#define GET_TE_METRIC(t) \ - (((unsigned)(t)->te_metric[0]<<16) | ((t)->te_metric[1]<<8) | \ - (t)->te_metric[2]) -#define SET_TE_METRIC(t, m) \ - (((t)->te_metric[0] = (m) >> 16), \ - ((t)->te_metric[1] = (m) >> 8), \ - ((t)->te_metric[2] = (m))) +#define GET_TE_METRIC(t) \ + (((unsigned)(t)->te_metric[0] << 16) | ((t)->te_metric[1] << 8) \ + | (t)->te_metric[2]) +#define SET_TE_METRIC(t, m) \ + (((t)->te_metric[0] = (m) >> 16), ((t)->te_metric[1] = (m) >> 8), \ + ((t)->te_metric[2] = (m))) /* struct for es neighbors */ -struct es_neigh -{ - struct metric metrics; - /* approximate position of first, we use the - * length ((uchar*)metric-1) to know all */ - u_char first_es_neigh[ISIS_SYS_ID_LEN]; - +struct es_neigh { + struct metric metrics; + /* approximate position of first, we use the + * length ((uchar*)metric-1) to know all */ + u_char first_es_neigh[ISIS_SYS_ID_LEN]; }; -struct partition_desig_level2_is -{ - struct list *isis_system_ids; +struct partition_desig_level2_is { + struct list *isis_system_ids; }; /* struct for lan neighbors */ -struct lan_neigh -{ - u_char LAN_addr[6]; +struct lan_neigh { + u_char LAN_addr[6]; }; #ifdef __SUNPRO_C @@ -189,60 +184,54 @@ struct lan_neigh #endif /* struct for LSP entry */ -struct lsp_entry -{ - u_int16_t rem_lifetime; - u_char lsp_id[ISIS_SYS_ID_LEN + 2]; - u_int32_t seq_num; - u_int16_t checksum; -} __attribute__ ((packed)); +struct lsp_entry { + u_int16_t rem_lifetime; + u_char lsp_id[ISIS_SYS_ID_LEN + 2]; + u_int32_t seq_num; + u_int16_t checksum; +} __attribute__((packed)); #ifdef __SUNPRO_C #pragma pack() #endif /* struct for checksum */ -struct checksum -{ - u_int16_t checksum; +struct checksum { + u_int16_t checksum; }; /* ipv4 reachability */ -struct ipv4_reachability -{ - struct metric metrics; - struct in_addr prefix; - struct in_addr mask; +struct ipv4_reachability { + struct metric metrics; + struct in_addr prefix; + struct in_addr mask; }; /* te router id */ -struct te_router_id -{ - struct in_addr id; +struct te_router_id { + struct in_addr id; }; /* te ipv4 reachability */ -struct te_ipv4_reachability -{ - u_int32_t te_metric; - u_char control; - u_char prefix_start; /* since this is variable length by nature it only */ -}; /* points to an approximate location */ +struct te_ipv4_reachability { + u_int32_t te_metric; + u_char control; + u_char prefix_start; /* since this is variable length by nature it only + */ +}; /* points to an approximate location */ #define TE_IPV4_HAS_SUBTLV (0x40) -struct idrp_info -{ - u_char len; - u_char *value; +struct idrp_info { + u_char len; + u_char *value; }; -struct ipv6_reachability -{ - u_int32_t metric; - u_char control_info; - u_char prefix_len; - u_char prefix[16]; +struct ipv6_reachability { + u_int32_t metric; + u_char control_info; + u_char prefix_len; + u_char prefix[16]; }; /* bits in control_info */ @@ -256,39 +245,37 @@ struct ipv6_reachability #define CTRL_INFO_SUBTLVS 0x20 -struct mt_router_info -{ - ISIS_MT_INFO_FIELDS - bool overload; +struct mt_router_info { + ISIS_MT_INFO_FIELDS + bool overload; }; /* * Pointer to each tlv type, filled by parse_tlvs() */ -struct tlvs -{ - struct checksum *checksum; - struct hostname *hostname; - struct nlpids *nlpids; - struct te_router_id *router_id; - struct list *area_addrs; - struct list *mt_router_info; - struct list *is_neighs; - struct list *te_is_neighs; - struct list *mt_is_neighs; - struct list *es_neighs; - struct list *lsp_entries; - struct list *prefix_neighs; - struct list *lan_neighs; - struct list *ipv4_addrs; - struct list *ipv4_int_reachs; - struct list *ipv4_ext_reachs; - struct list *te_ipv4_reachs; - struct list *mt_ipv4_reachs; - struct list *ipv6_addrs; - struct list *ipv6_reachs; - struct list *mt_ipv6_reachs; - struct isis_passwd auth_info; +struct tlvs { + struct checksum *checksum; + struct hostname *hostname; + struct nlpids *nlpids; + struct te_router_id *router_id; + struct list *area_addrs; + struct list *mt_router_info; + struct list *is_neighs; + struct list *te_is_neighs; + struct list *mt_is_neighs; + struct list *es_neighs; + struct list *lsp_entries; + struct list *prefix_neighs; + struct list *lan_neighs; + struct list *ipv4_addrs; + struct list *ipv4_int_reachs; + struct list *ipv4_ext_reachs; + struct list *te_ipv4_reachs; + struct list *mt_ipv4_reachs; + struct list *ipv6_addrs; + struct list *ipv6_reachs; + struct list *mt_ipv6_reachs; + struct isis_passwd auth_info; }; /* @@ -319,34 +306,35 @@ struct tlvs #define TLVFLAG_GRACEFUL_RESTART (1<<21) #define TLVFLAG_MT_ROUTER_INFORMATION (1<<22) -void init_tlvs (struct tlvs *tlvs, uint32_t expected); -void free_tlvs (struct tlvs *tlvs); -int parse_tlvs (char *areatag, u_char * stream, int size, - u_int32_t * expected, u_int32_t * found, struct tlvs *tlvs, - u_int32_t * auth_tlv_offset); -int add_tlv (u_char, u_char, u_char *, struct stream *); -void free_tlv (void *val); - -int tlv_add_mt_router_info (struct list *mt_router_info, struct stream *stream); -int tlv_add_area_addrs (struct list *area_addrs, struct stream *stream); -int tlv_add_is_neighs (struct list *is_neighs, struct stream *stream); -unsigned int tlv_add_te_is_neighs (struct list *te_is_neighs, struct stream *stream, void *arg); -int tlv_add_lan_neighs (struct list *lan_neighs, struct stream *stream); -int tlv_add_nlpid (struct nlpids *nlpids, struct stream *stream); -int tlv_add_checksum (struct checksum *checksum, struct stream *stream); -int tlv_add_authinfo (u_char auth_type, u_char authlen, u_char *auth_value, - struct stream *stream); -int tlv_add_ip_addrs (struct list *ip_addrs, struct stream *stream); -int tlv_add_in_addr (struct in_addr *, struct stream *stream, u_char tag); -int tlv_add_dynamic_hostname (struct hostname *hostname, - struct stream *stream); -int tlv_add_lsp_entries (struct list *lsps, struct stream *stream); -int tlv_add_ipv4_int_reachs (struct list *ipv4_reachs, struct stream *stream); -int tlv_add_ipv4_ext_reachs (struct list *ipv4_reachs, struct stream *stream); -unsigned int tlv_add_te_ipv4_reachs (struct list *te_ipv4_reachs, struct stream *stream, void *arg); -int tlv_add_ipv6_addrs (struct list *ipv6_addrs, struct stream *stream); -unsigned int tlv_add_ipv6_reachs (struct list *ipv6_reachs, struct stream *stream, void *arg); - -int tlv_add_padding (struct stream *stream); +void init_tlvs(struct tlvs *tlvs, uint32_t expected); +void free_tlvs(struct tlvs *tlvs); +int parse_tlvs(char *areatag, u_char *stream, int size, u_int32_t *expected, + u_int32_t *found, struct tlvs *tlvs, u_int32_t *auth_tlv_offset); +int add_tlv(u_char, u_char, u_char *, struct stream *); +void free_tlv(void *val); + +int tlv_add_mt_router_info(struct list *mt_router_info, struct stream *stream); +int tlv_add_area_addrs(struct list *area_addrs, struct stream *stream); +int tlv_add_is_neighs(struct list *is_neighs, struct stream *stream); +unsigned int tlv_add_te_is_neighs(struct list *te_is_neighs, + struct stream *stream, void *arg); +int tlv_add_lan_neighs(struct list *lan_neighs, struct stream *stream); +int tlv_add_nlpid(struct nlpids *nlpids, struct stream *stream); +int tlv_add_checksum(struct checksum *checksum, struct stream *stream); +int tlv_add_authinfo(u_char auth_type, u_char authlen, u_char *auth_value, + struct stream *stream); +int tlv_add_ip_addrs(struct list *ip_addrs, struct stream *stream); +int tlv_add_in_addr(struct in_addr *, struct stream *stream, u_char tag); +int tlv_add_dynamic_hostname(struct hostname *hostname, struct stream *stream); +int tlv_add_lsp_entries(struct list *lsps, struct stream *stream); +int tlv_add_ipv4_int_reachs(struct list *ipv4_reachs, struct stream *stream); +int tlv_add_ipv4_ext_reachs(struct list *ipv4_reachs, struct stream *stream); +unsigned int tlv_add_te_ipv4_reachs(struct list *te_ipv4_reachs, + struct stream *stream, void *arg); +int tlv_add_ipv6_addrs(struct list *ipv6_addrs, struct stream *stream); +unsigned int tlv_add_ipv6_reachs(struct list *ipv6_reachs, + struct stream *stream, void *arg); + +int tlv_add_padding(struct stream *stream); #endif /* _ZEBRA_ISIS_TLV_H */ diff --git a/isisd/isis_vty.c b/isisd/isis_vty.c index 157962dad..2a19465a0 100644 --- a/isisd/isis_vty.c +++ b/isisd/isis_vty.c @@ -2,18 +2,18 @@ * IS-IS Rout(e)ing protocol - isis_circuit.h * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * Copyright (C) 2016 David Lamparter, for NetDEF, Inc. * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -32,27 +32,23 @@ #include "isis_mt.h" #include "isisd.h" -static struct isis_circuit * -isis_circuit_lookup (struct vty *vty) +static struct isis_circuit *isis_circuit_lookup(struct vty *vty) { - struct interface *ifp = VTY_GET_CONTEXT(interface); - struct isis_circuit *circuit; + struct interface *ifp = VTY_GET_CONTEXT(interface); + struct isis_circuit *circuit; - if (!ifp) - { - vty_out (vty, "Invalid interface \n"); - return NULL; - } + if (!ifp) { + vty_out(vty, "Invalid interface \n"); + return NULL; + } - circuit = circuit_scan_by_ifp (ifp); - if (!circuit) - { - vty_out (vty, "ISIS is not enabled on circuit %s\n", - ifp->name); - return NULL; - } + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) { + vty_out(vty, "ISIS is not enabled on circuit %s\n", ifp->name); + return NULL; + } - return circuit; + return circuit; } DEFUN (ip_router_isis, @@ -63,48 +59,47 @@ DEFUN (ip_router_isis, "IS-IS Routing for IP\n" "Routing process tag\n") { - int idx_afi = 0; - int idx_word = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct isis_circuit *circuit; - struct isis_area *area; - const char *af = argv[idx_afi]->arg; - const char *area_tag = argv[idx_word]->arg; - - /* Prevent more than one area per circuit */ - circuit = circuit_scan_by_ifp (ifp); - if (circuit && circuit->area) - { - if (strcmp (circuit->area->area_tag, area_tag)) - { - vty_out (vty, "ISIS circuit is already defined on %s\n", - circuit->area->area_tag); - return CMD_ERR_NOTHING_TODO; - } - } - - area = isis_area_lookup (area_tag); - if (!area) - area = isis_area_create (area_tag); - - if (!circuit || !circuit->area) { - circuit = isis_circuit_create (area, ifp); - - if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP) - { - vty_out (vty, "Couldn't bring up interface, please check log.\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router; - if (af[2] != '\0') - ipv6 = true; - else - ip = true; - - isis_circuit_af_set (circuit, ip, ipv6); - return CMD_SUCCESS; + int idx_afi = 0; + int idx_word = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct isis_circuit *circuit; + struct isis_area *area; + const char *af = argv[idx_afi]->arg; + const char *area_tag = argv[idx_word]->arg; + + /* Prevent more than one area per circuit */ + circuit = circuit_scan_by_ifp(ifp); + if (circuit && circuit->area) { + if (strcmp(circuit->area->area_tag, area_tag)) { + vty_out(vty, "ISIS circuit is already defined on %s\n", + circuit->area->area_tag); + return CMD_ERR_NOTHING_TODO; + } + } + + area = isis_area_lookup(area_tag); + if (!area) + area = isis_area_create(area_tag); + + if (!circuit || !circuit->area) { + circuit = isis_circuit_create(area, ifp); + + if (circuit->state != C_STATE_CONF + && circuit->state != C_STATE_UP) { + vty_out(vty, + "Couldn't bring up interface, please check log.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router; + if (af[2] != '\0') + ipv6 = true; + else + ip = true; + + isis_circuit_af_set(circuit, ip, ipv6); + return CMD_SUCCESS; } DEFUN (ip6_router_isis, @@ -115,7 +110,7 @@ DEFUN (ip6_router_isis, "IS-IS Routing for IP\n" "Routing process tag\n") { - return ip_router_isis (self, vty, argc, argv); + return ip_router_isis(self, vty, argc, argv); } DEFUN (no_ip_router_isis, @@ -128,38 +123,35 @@ DEFUN (no_ip_router_isis, "IS-IS Routing for IP\n" "Routing process tag\n") { - int idx_afi = 1; - int idx_word = 4; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct isis_area *area; - struct isis_circuit *circuit; - const char *af = argv[idx_afi]->arg; - const char *area_tag = argv[idx_word]->arg; - - area = isis_area_lookup (area_tag); - if (!area) - { - vty_out (vty, "Can't find ISIS instance %s\n", - argv[idx_afi]->arg); - return CMD_ERR_NO_MATCH; - } - - circuit = circuit_lookup_by_ifp (ifp, area->circuit_list); - if (!circuit) - { - vty_out (vty, "ISIS is not enabled on circuit %s\n", - ifp->name); - return CMD_ERR_NO_MATCH; - } - - bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router; - if (af[2] != '\0') - ipv6 = false; - else - ip = false; - - isis_circuit_af_set (circuit, ip, ipv6); - return CMD_SUCCESS; + int idx_afi = 1; + int idx_word = 4; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct isis_area *area; + struct isis_circuit *circuit; + const char *af = argv[idx_afi]->arg; + const char *area_tag = argv[idx_word]->arg; + + area = isis_area_lookup(area_tag); + if (!area) { + vty_out(vty, "Can't find ISIS instance %s\n", + argv[idx_afi]->arg); + return CMD_ERR_NO_MATCH; + } + + circuit = circuit_lookup_by_ifp(ifp, area->circuit_list); + if (!circuit) { + vty_out(vty, "ISIS is not enabled on circuit %s\n", ifp->name); + return CMD_ERR_NO_MATCH; + } + + bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router; + if (af[2] != '\0') + ipv6 = false; + else + ip = false; + + isis_circuit_af_set(circuit, ip, ipv6); + return CMD_SUCCESS; } DEFUN (isis_passive, @@ -168,12 +160,12 @@ DEFUN (isis_passive, "IS-IS commands\n" "Configure the passive mode for interface\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - isis_circuit_passive_set (circuit, 1); - return CMD_SUCCESS; + isis_circuit_passive_set(circuit, 1); + return CMD_SUCCESS; } DEFUN (no_isis_passive, @@ -183,18 +175,17 @@ DEFUN (no_isis_passive, "IS-IS commands\n" "Configure the passive mode for interface\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - if (if_is_loopback (circuit->interface)) - { - vty_out (vty,"Can't set no passive for loopback interface\n"); - return CMD_ERR_AMBIGUOUS; - } + if (if_is_loopback(circuit->interface)) { + vty_out(vty, "Can't set no passive for loopback interface\n"); + return CMD_ERR_AMBIGUOUS; + } - isis_circuit_passive_set (circuit, 0); - return CMD_SUCCESS; + isis_circuit_passive_set(circuit, 0); + return CMD_SUCCESS; } DEFUN (isis_circuit_type, @@ -206,30 +197,28 @@ DEFUN (isis_circuit_type, "Level-1-2 adjacencies are formed\n" "Level-2 only adjacencies are formed\n") { - int idx_level = 2; - int is_type; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + int idx_level = 2; + int is_type; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - is_type = string2circuit_t (argv[idx_level]->arg); - if (!is_type) - { - vty_out (vty, "Unknown circuit-type \n"); - return CMD_ERR_AMBIGUOUS; - } + is_type = string2circuit_t(argv[idx_level]->arg); + if (!is_type) { + vty_out(vty, "Unknown circuit-type \n"); + return CMD_ERR_AMBIGUOUS; + } - if (circuit->state == C_STATE_UP && - circuit->area->is_type != IS_LEVEL_1_AND_2 && - circuit->area->is_type != is_type) - { - vty_out (vty, "Invalid circuit level for area %s.\n", - circuit->area->area_tag); - return CMD_ERR_AMBIGUOUS; - } - isis_circuit_is_type_set (circuit, is_type); + if (circuit->state == C_STATE_UP + && circuit->area->is_type != IS_LEVEL_1_AND_2 + && circuit->area->is_type != is_type) { + vty_out(vty, "Invalid circuit level for area %s.\n", + circuit->area->area_tag); + return CMD_ERR_AMBIGUOUS; + } + isis_circuit_is_type_set(circuit, is_type); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_isis_circuit_type, @@ -242,21 +231,21 @@ DEFUN (no_isis_circuit_type, "Level-1-2 adjacencies are formed\n" "Level-2 only adjacencies are formed\n") { - int is_type; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + int is_type; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - /* - * Set the circuits level to its default value - */ - if (circuit->state == C_STATE_UP) - is_type = circuit->area->is_type; - else - is_type = IS_LEVEL_1_AND_2; - isis_circuit_is_type_set (circuit, is_type); + /* + * Set the circuits level to its default value + */ + if (circuit->state == C_STATE_UP) + is_type = circuit->area->is_type; + else + is_type = IS_LEVEL_1_AND_2; + isis_circuit_is_type_set(circuit, is_type); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (isis_network, @@ -266,18 +255,17 @@ DEFUN (isis_network, "Set network type\n" "point-to-point network type\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_P2P)) - { - vty_out (vty, - "isis network point-to-point is valid only on broadcast interfaces\n"); - return CMD_ERR_AMBIGUOUS; - } + if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_P2P)) { + vty_out(vty, + "isis network point-to-point is valid only on broadcast interfaces\n"); + return CMD_ERR_AMBIGUOUS; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_isis_network, @@ -288,18 +276,17 @@ DEFUN (no_isis_network, "Set network type for circuit\n" "point-to-point network type\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_BROADCAST)) - { - vty_out (vty, - "isis network point-to-point is valid only on broadcast interfaces\n"); - return CMD_ERR_AMBIGUOUS; - } + if (isis_circuit_circ_type_set(circuit, CIRCUIT_T_BROADCAST)) { + vty_out(vty, + "isis network point-to-point is valid only on broadcast interfaces\n"); + return CMD_ERR_AMBIGUOUS; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (isis_passwd, @@ -311,24 +298,25 @@ DEFUN (isis_passwd, "Cleartext password\n" "Circuit password\n") { - int idx_encryption = 2; - int idx_word = 3; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - int rv; - if (!circuit) - return CMD_ERR_NO_MATCH; + int idx_encryption = 2; + int idx_word = 3; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + int rv; + if (!circuit) + return CMD_ERR_NO_MATCH; - if (argv[idx_encryption]->arg[0] == 'm') - rv = isis_circuit_passwd_hmac_md5_set(circuit, argv[idx_word]->arg); - else - rv = isis_circuit_passwd_cleartext_set(circuit, argv[idx_word]->arg); - if (rv) - { - vty_out (vty, "Too long circuit password (>254)\n"); - return CMD_ERR_AMBIGUOUS; - } + if (argv[idx_encryption]->arg[0] == 'm') + rv = isis_circuit_passwd_hmac_md5_set(circuit, + argv[idx_word]->arg); + else + rv = isis_circuit_passwd_cleartext_set(circuit, + argv[idx_word]->arg); + if (rv) { + vty_out(vty, "Too long circuit password (>254)\n"); + return CMD_ERR_AMBIGUOUS; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_isis_passwd, @@ -341,13 +329,13 @@ DEFUN (no_isis_passwd, "Cleartext password\n" "Circuit password\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - isis_circuit_passwd_unset(circuit); + isis_circuit_passwd_unset(circuit); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -358,24 +346,22 @@ DEFUN (isis_priority, "Set priority for Designated Router election\n" "Priority value\n") { - int idx_number = 2; - int prio; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + int idx_number = 2; + int prio; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - prio = atoi (argv[idx_number]->arg); - if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) - { - vty_out (vty, "Invalid priority %d - should be <0-127>\n", - prio); - return CMD_ERR_AMBIGUOUS; - } + prio = atoi(argv[idx_number]->arg); + if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) { + vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio); + return CMD_ERR_AMBIGUOUS; + } - circuit->priority[0] = prio; - circuit->priority[1] = prio; + circuit->priority[0] = prio; + circuit->priority[1] = prio; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_isis_priority, @@ -386,14 +372,14 @@ DEFUN (no_isis_priority, "Set priority for Designated Router election\n" "Priority value\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - circuit->priority[0] = DEFAULT_PRIORITY; - circuit->priority[1] = DEFAULT_PRIORITY; + circuit->priority[0] = DEFAULT_PRIORITY; + circuit->priority[1] = DEFAULT_PRIORITY; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -405,23 +391,21 @@ DEFUN (isis_priority_l1, "Priority value\n" "Specify priority for level-1 routing\n") { - int idx_number = 2; - int prio; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + int idx_number = 2; + int prio; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - prio = atoi (argv[idx_number]->arg); - if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) - { - vty_out (vty, "Invalid priority %d - should be <0-127>\n", - prio); - return CMD_ERR_AMBIGUOUS; - } + prio = atoi(argv[idx_number]->arg); + if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) { + vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio); + return CMD_ERR_AMBIGUOUS; + } - circuit->priority[0] = prio; + circuit->priority[0] = prio; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_isis_priority_l1, @@ -433,13 +417,13 @@ DEFUN (no_isis_priority_l1, "Priority value\n" "Specify priority for level-1 routing\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - circuit->priority[0] = DEFAULT_PRIORITY; + circuit->priority[0] = DEFAULT_PRIORITY; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -451,23 +435,21 @@ DEFUN (isis_priority_l2, "Priority value\n" "Specify priority for level-2 routing\n") { - int idx_number = 2; - int prio; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + int idx_number = 2; + int prio; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - prio = atoi (argv[idx_number]->arg); - if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) - { - vty_out (vty, "Invalid priority %d - should be <0-127>\n", - prio); - return CMD_ERR_AMBIGUOUS; - } + prio = atoi(argv[idx_number]->arg); + if (prio < MIN_PRIORITY || prio > MAX_PRIORITY) { + vty_out(vty, "Invalid priority %d - should be <0-127>\n", prio); + return CMD_ERR_AMBIGUOUS; + } - circuit->priority[1] = prio; + circuit->priority[1] = prio; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_isis_priority_l2, @@ -479,13 +461,13 @@ DEFUN (no_isis_priority_l2, "Priority value\n" "Specify priority for level-2 routing\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - circuit->priority[1] = DEFAULT_PRIORITY; + circuit->priority[1] = DEFAULT_PRIORITY; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -497,37 +479,37 @@ DEFUN (isis_metric, "Set default metric for circuit\n" "Default metric value\n") { - int idx_number = 2; - int met; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + int idx_number = 2; + int met; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - met = atoi (argv[idx_number]->arg); + met = atoi(argv[idx_number]->arg); - /* RFC3787 section 5.1 */ - if (circuit->area && circuit->area->oldmetric == 1 && - met > MAX_NARROW_LINK_METRIC) - { - vty_out (vty, "Invalid metric %d - should be <0-63> " - "when narrow metric type enabled\n", - met); - return CMD_ERR_AMBIGUOUS; - } + /* RFC3787 section 5.1 */ + if (circuit->area && circuit->area->oldmetric == 1 + && met > MAX_NARROW_LINK_METRIC) { + vty_out(vty, + "Invalid metric %d - should be <0-63> " + "when narrow metric type enabled\n", + met); + return CMD_ERR_AMBIGUOUS; + } - /* RFC4444 */ - if (circuit->area && circuit->area->newmetric == 1 && - met > MAX_WIDE_LINK_METRIC) - { - vty_out (vty, "Invalid metric %d - should be <0-16777215> " - "when wide metric type enabled\n", - met); - return CMD_ERR_AMBIGUOUS; - } + /* RFC4444 */ + if (circuit->area && circuit->area->newmetric == 1 + && met > MAX_WIDE_LINK_METRIC) { + vty_out(vty, + "Invalid metric %d - should be <0-16777215> " + "when wide metric type enabled\n", + met); + return CMD_ERR_AMBIGUOUS; + } - isis_circuit_metric_set (circuit, IS_LEVEL_1, met); - isis_circuit_metric_set (circuit, IS_LEVEL_2, met); - return CMD_SUCCESS; + isis_circuit_metric_set(circuit, IS_LEVEL_1, met); + isis_circuit_metric_set(circuit, IS_LEVEL_2, met); + return CMD_SUCCESS; } @@ -539,13 +521,13 @@ DEFUN (no_isis_metric, "Set default metric for circuit\n" "Default metric value\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - isis_circuit_metric_set (circuit, IS_LEVEL_1, DEFAULT_CIRCUIT_METRIC); - isis_circuit_metric_set (circuit, IS_LEVEL_2, DEFAULT_CIRCUIT_METRIC); - return CMD_SUCCESS; + isis_circuit_metric_set(circuit, IS_LEVEL_1, DEFAULT_CIRCUIT_METRIC); + isis_circuit_metric_set(circuit, IS_LEVEL_2, DEFAULT_CIRCUIT_METRIC); + return CMD_SUCCESS; } @@ -557,36 +539,36 @@ DEFUN (isis_metric_l1, "Default metric value\n" "Specify metric for level-1 routing\n") { - int idx_number = 2; - int met; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + int idx_number = 2; + int met; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - met = atoi (argv[idx_number]->arg); + met = atoi(argv[idx_number]->arg); - /* RFC3787 section 5.1 */ - if (circuit->area && circuit->area->oldmetric == 1 && - met > MAX_NARROW_LINK_METRIC) - { - vty_out (vty, "Invalid metric %d - should be <0-63> " - "when narrow metric type enabled\n", - met); - return CMD_ERR_AMBIGUOUS; - } + /* RFC3787 section 5.1 */ + if (circuit->area && circuit->area->oldmetric == 1 + && met > MAX_NARROW_LINK_METRIC) { + vty_out(vty, + "Invalid metric %d - should be <0-63> " + "when narrow metric type enabled\n", + met); + return CMD_ERR_AMBIGUOUS; + } - /* RFC4444 */ - if (circuit->area && circuit->area->newmetric == 1 && - met > MAX_WIDE_LINK_METRIC) - { - vty_out (vty, "Invalid metric %d - should be <0-16777215> " - "when wide metric type enabled\n", - met); - return CMD_ERR_AMBIGUOUS; - } + /* RFC4444 */ + if (circuit->area && circuit->area->newmetric == 1 + && met > MAX_WIDE_LINK_METRIC) { + vty_out(vty, + "Invalid metric %d - should be <0-16777215> " + "when wide metric type enabled\n", + met); + return CMD_ERR_AMBIGUOUS; + } - isis_circuit_metric_set (circuit, IS_LEVEL_1, met); - return CMD_SUCCESS; + isis_circuit_metric_set(circuit, IS_LEVEL_1, met); + return CMD_SUCCESS; } @@ -599,12 +581,12 @@ DEFUN (no_isis_metric_l1, "Default metric value\n" "Specify metric for level-1 routing\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - isis_circuit_metric_set (circuit, IS_LEVEL_1, DEFAULT_CIRCUIT_METRIC); - return CMD_SUCCESS; + isis_circuit_metric_set(circuit, IS_LEVEL_1, DEFAULT_CIRCUIT_METRIC); + return CMD_SUCCESS; } @@ -616,36 +598,36 @@ DEFUN (isis_metric_l2, "Default metric value\n" "Specify metric for level-2 routing\n") { - int idx_number = 2; - int met; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + int idx_number = 2; + int met; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - met = atoi (argv[idx_number]->arg); + met = atoi(argv[idx_number]->arg); - /* RFC3787 section 5.1 */ - if (circuit->area && circuit->area->oldmetric == 1 && - met > MAX_NARROW_LINK_METRIC) - { - vty_out (vty, "Invalid metric %d - should be <0-63> " - "when narrow metric type enabled\n", - met); - return CMD_ERR_AMBIGUOUS; - } + /* RFC3787 section 5.1 */ + if (circuit->area && circuit->area->oldmetric == 1 + && met > MAX_NARROW_LINK_METRIC) { + vty_out(vty, + "Invalid metric %d - should be <0-63> " + "when narrow metric type enabled\n", + met); + return CMD_ERR_AMBIGUOUS; + } - /* RFC4444 */ - if (circuit->area && circuit->area->newmetric == 1 && - met > MAX_WIDE_LINK_METRIC) - { - vty_out (vty, "Invalid metric %d - should be <0-16777215> " - "when wide metric type enabled\n", - met); - return CMD_ERR_AMBIGUOUS; - } + /* RFC4444 */ + if (circuit->area && circuit->area->newmetric == 1 + && met > MAX_WIDE_LINK_METRIC) { + vty_out(vty, + "Invalid metric %d - should be <0-16777215> " + "when wide metric type enabled\n", + met); + return CMD_ERR_AMBIGUOUS; + } - isis_circuit_metric_set (circuit, IS_LEVEL_2, met); - return CMD_SUCCESS; + isis_circuit_metric_set(circuit, IS_LEVEL_2, met); + return CMD_SUCCESS; } @@ -658,12 +640,12 @@ DEFUN (no_isis_metric_l2, "Default metric value\n" "Specify metric for level-2 routing\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - isis_circuit_metric_set (circuit, IS_LEVEL_2, DEFAULT_CIRCUIT_METRIC); - return CMD_SUCCESS; + isis_circuit_metric_set(circuit, IS_LEVEL_2, DEFAULT_CIRCUIT_METRIC); + return CMD_SUCCESS; } /* end of metrics */ @@ -675,24 +657,23 @@ DEFUN (isis_hello_interval, "Set Hello interval\n" "Holdtime 1 seconds, interval depends on multiplier\n") { - int idx_number = 2; - int interval; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + int idx_number = 2; + int interval; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - interval = atoi (argv[idx_number]->arg); - if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) - { - vty_out (vty, "Invalid hello-interval %d - should be <1-600>\n", - interval); - return CMD_ERR_AMBIGUOUS; - } + interval = atoi(argv[idx_number]->arg); + if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) { + vty_out(vty, "Invalid hello-interval %d - should be <1-600>\n", + interval); + return CMD_ERR_AMBIGUOUS; + } - circuit->hello_interval[0] = (u_int16_t) interval; - circuit->hello_interval[1] = (u_int16_t) interval; + circuit->hello_interval[0] = (u_int16_t)interval; + circuit->hello_interval[1] = (u_int16_t)interval; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -704,14 +685,14 @@ DEFUN (no_isis_hello_interval, "Set Hello interval\n" "Holdtime 1 second, interval depends on multiplier\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - circuit->hello_interval[0] = DEFAULT_HELLO_INTERVAL; - circuit->hello_interval[1] = DEFAULT_HELLO_INTERVAL; + circuit->hello_interval[0] = DEFAULT_HELLO_INTERVAL; + circuit->hello_interval[1] = DEFAULT_HELLO_INTERVAL; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -723,23 +704,22 @@ DEFUN (isis_hello_interval_l1, "Holdtime 1 second, interval depends on multiplier\n" "Specify hello-interval for level-1 IIHs\n") { - int idx_number = 2; - long interval; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + int idx_number = 2; + long interval; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - interval = atoi (argv[idx_number]->arg); - if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) - { - vty_out (vty, "Invalid hello-interval %ld - should be <1-600>\n", - interval); - return CMD_ERR_AMBIGUOUS; - } + interval = atoi(argv[idx_number]->arg); + if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) { + vty_out(vty, "Invalid hello-interval %ld - should be <1-600>\n", + interval); + return CMD_ERR_AMBIGUOUS; + } - circuit->hello_interval[0] = (u_int16_t) interval; + circuit->hello_interval[0] = (u_int16_t)interval; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -752,13 +732,13 @@ DEFUN (no_isis_hello_interval_l1, "Holdtime 1 second, interval depends on multiplier\n" "Specify hello-interval for level-1 IIHs\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - circuit->hello_interval[0] = DEFAULT_HELLO_INTERVAL; + circuit->hello_interval[0] = DEFAULT_HELLO_INTERVAL; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -770,23 +750,22 @@ DEFUN (isis_hello_interval_l2, "Holdtime 1 second, interval depends on multiplier\n" "Specify hello-interval for level-2 IIHs\n") { - int idx_number = 2; - long interval; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + int idx_number = 2; + long interval; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - interval = atoi (argv[idx_number]->arg); - if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) - { - vty_out (vty, "Invalid hello-interval %ld - should be <1-600>\n", - interval); - return CMD_ERR_AMBIGUOUS; - } + interval = atoi(argv[idx_number]->arg); + if (interval < MIN_HELLO_INTERVAL || interval > MAX_HELLO_INTERVAL) { + vty_out(vty, "Invalid hello-interval %ld - should be <1-600>\n", + interval); + return CMD_ERR_AMBIGUOUS; + } - circuit->hello_interval[1] = (u_int16_t) interval; + circuit->hello_interval[1] = (u_int16_t)interval; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -799,13 +778,13 @@ DEFUN (no_isis_hello_interval_l2, "Holdtime 1 second, interval depends on multiplier\n" "Specify hello-interval for level-2 IIHs\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - circuit->hello_interval[1] = DEFAULT_HELLO_INTERVAL; + circuit->hello_interval[1] = DEFAULT_HELLO_INTERVAL; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -816,24 +795,24 @@ DEFUN (isis_hello_multiplier, "Set multiplier for Hello holding time\n" "Hello multiplier value\n") { - int idx_number = 2; - int mult; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + int idx_number = 2; + int mult; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - mult = atoi (argv[idx_number]->arg); - if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER) - { - vty_out (vty, "Invalid hello-multiplier %d - should be <2-100>\n", - mult); - return CMD_ERR_AMBIGUOUS; - } + mult = atoi(argv[idx_number]->arg); + if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER) { + vty_out(vty, + "Invalid hello-multiplier %d - should be <2-100>\n", + mult); + return CMD_ERR_AMBIGUOUS; + } - circuit->hello_multiplier[0] = (u_int16_t) mult; - circuit->hello_multiplier[1] = (u_int16_t) mult; + circuit->hello_multiplier[0] = (u_int16_t)mult; + circuit->hello_multiplier[1] = (u_int16_t)mult; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -845,14 +824,14 @@ DEFUN (no_isis_hello_multiplier, "Set multiplier for Hello holding time\n" "Hello multiplier value\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - circuit->hello_multiplier[0] = DEFAULT_HELLO_MULTIPLIER; - circuit->hello_multiplier[1] = DEFAULT_HELLO_MULTIPLIER; + circuit->hello_multiplier[0] = DEFAULT_HELLO_MULTIPLIER; + circuit->hello_multiplier[1] = DEFAULT_HELLO_MULTIPLIER; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -864,23 +843,23 @@ DEFUN (isis_hello_multiplier_l1, "Hello multiplier value\n" "Specify hello multiplier for level-1 IIHs\n") { - int idx_number = 2; - int mult; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + int idx_number = 2; + int mult; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - mult = atoi (argv[idx_number]->arg); - if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER) - { - vty_out (vty, "Invalid hello-multiplier %d - should be <2-100>\n", - mult); - return CMD_ERR_AMBIGUOUS; - } + mult = atoi(argv[idx_number]->arg); + if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER) { + vty_out(vty, + "Invalid hello-multiplier %d - should be <2-100>\n", + mult); + return CMD_ERR_AMBIGUOUS; + } - circuit->hello_multiplier[0] = (u_int16_t) mult; + circuit->hello_multiplier[0] = (u_int16_t)mult; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -893,13 +872,13 @@ DEFUN (no_isis_hello_multiplier_l1, "Hello multiplier value\n" "Specify hello multiplier for level-1 IIHs\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - circuit->hello_multiplier[0] = DEFAULT_HELLO_MULTIPLIER; + circuit->hello_multiplier[0] = DEFAULT_HELLO_MULTIPLIER; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -911,23 +890,23 @@ DEFUN (isis_hello_multiplier_l2, "Hello multiplier value\n" "Specify hello multiplier for level-2 IIHs\n") { - int idx_number = 2; - int mult; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + int idx_number = 2; + int mult; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - mult = atoi (argv[idx_number]->arg); - if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER) - { - vty_out (vty, "Invalid hello-multiplier %d - should be <2-100>\n", - mult); - return CMD_ERR_AMBIGUOUS; - } + mult = atoi(argv[idx_number]->arg); + if (mult < MIN_HELLO_MULTIPLIER || mult > MAX_HELLO_MULTIPLIER) { + vty_out(vty, + "Invalid hello-multiplier %d - should be <2-100>\n", + mult); + return CMD_ERR_AMBIGUOUS; + } - circuit->hello_multiplier[1] = (u_int16_t) mult; + circuit->hello_multiplier[1] = (u_int16_t)mult; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -940,13 +919,13 @@ DEFUN (no_isis_hello_multiplier_l2, "Hello multiplier value\n" "Specify hello multiplier for level-2 IIHs\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - circuit->hello_multiplier[1] = DEFAULT_HELLO_MULTIPLIER; + circuit->hello_multiplier[1] = DEFAULT_HELLO_MULTIPLIER; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -957,13 +936,13 @@ DEFUN (isis_hello_padding, "Add padding to IS-IS hello packets\n" "Pad hello packets\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - circuit->pad_hellos = 1; + circuit->pad_hellos = 1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_isis_hello_padding, @@ -974,13 +953,13 @@ DEFUN (no_isis_hello_padding, "Add padding to IS-IS hello packets\n" "Pad hello packets\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - circuit->pad_hellos = 0; + circuit->pad_hellos = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (csnp_interval, @@ -990,24 +969,23 @@ DEFUN (csnp_interval, "Set CSNP interval in seconds\n" "CSNP interval value\n") { - int idx_number = 2; - unsigned long interval; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + int idx_number = 2; + unsigned long interval; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - interval = atol (argv[idx_number]->arg); - if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) - { - vty_out (vty, "Invalid csnp-interval %lu - should be <1-600>\n", - interval); - return CMD_ERR_AMBIGUOUS; - } + interval = atol(argv[idx_number]->arg); + if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) { + vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n", + interval); + return CMD_ERR_AMBIGUOUS; + } - circuit->csnp_interval[0] = (u_int16_t) interval; - circuit->csnp_interval[1] = (u_int16_t) interval; + circuit->csnp_interval[0] = (u_int16_t)interval; + circuit->csnp_interval[1] = (u_int16_t)interval; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1019,14 +997,14 @@ DEFUN (no_csnp_interval, "Set CSNP interval in seconds\n" "CSNP interval value\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - circuit->csnp_interval[0] = DEFAULT_CSNP_INTERVAL; - circuit->csnp_interval[1] = DEFAULT_CSNP_INTERVAL; + circuit->csnp_interval[0] = DEFAULT_CSNP_INTERVAL; + circuit->csnp_interval[1] = DEFAULT_CSNP_INTERVAL; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1038,23 +1016,22 @@ DEFUN (csnp_interval_l1, "CSNP interval value\n" "Specify interval for level-1 CSNPs\n") { - int idx_number = 2; - unsigned long interval; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + int idx_number = 2; + unsigned long interval; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - interval = atol (argv[idx_number]->arg); - if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) - { - vty_out (vty, "Invalid csnp-interval %lu - should be <1-600>\n", - interval); - return CMD_ERR_AMBIGUOUS; - } + interval = atol(argv[idx_number]->arg); + if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) { + vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n", + interval); + return CMD_ERR_AMBIGUOUS; + } - circuit->csnp_interval[0] = (u_int16_t) interval; + circuit->csnp_interval[0] = (u_int16_t)interval; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1067,13 +1044,13 @@ DEFUN (no_csnp_interval_l1, "CSNP interval value\n" "Specify interval for level-1 CSNPs\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - circuit->csnp_interval[0] = DEFAULT_CSNP_INTERVAL; + circuit->csnp_interval[0] = DEFAULT_CSNP_INTERVAL; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1085,23 +1062,22 @@ DEFUN (csnp_interval_l2, "CSNP interval value\n" "Specify interval for level-2 CSNPs\n") { - int idx_number = 2; - unsigned long interval; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + int idx_number = 2; + unsigned long interval; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - interval = atol (argv[idx_number]->arg); - if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) - { - vty_out (vty, "Invalid csnp-interval %lu - should be <1-600>\n", - interval); - return CMD_ERR_AMBIGUOUS; - } + interval = atol(argv[idx_number]->arg); + if (interval < MIN_CSNP_INTERVAL || interval > MAX_CSNP_INTERVAL) { + vty_out(vty, "Invalid csnp-interval %lu - should be <1-600>\n", + interval); + return CMD_ERR_AMBIGUOUS; + } - circuit->csnp_interval[1] = (u_int16_t) interval; + circuit->csnp_interval[1] = (u_int16_t)interval; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1114,13 +1090,13 @@ DEFUN (no_csnp_interval_l2, "CSNP interval value\n" "Specify interval for level-2 CSNPs\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - circuit->csnp_interval[1] = DEFAULT_CSNP_INTERVAL; + circuit->csnp_interval[1] = DEFAULT_CSNP_INTERVAL; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1131,24 +1107,23 @@ DEFUN (psnp_interval, "Set PSNP interval in seconds\n" "PSNP interval value\n") { - int idx_number = 2; - unsigned long interval; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + int idx_number = 2; + unsigned long interval; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - interval = atol (argv[idx_number]->arg); - if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) - { - vty_out (vty, "Invalid psnp-interval %lu - should be <1-120>\n", - interval); - return CMD_ERR_AMBIGUOUS; - } + interval = atol(argv[idx_number]->arg); + if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) { + vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n", + interval); + return CMD_ERR_AMBIGUOUS; + } - circuit->psnp_interval[0] = (u_int16_t) interval; - circuit->psnp_interval[1] = (u_int16_t) interval; + circuit->psnp_interval[0] = (u_int16_t)interval; + circuit->psnp_interval[1] = (u_int16_t)interval; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1160,14 +1135,14 @@ DEFUN (no_psnp_interval, "Set PSNP interval in seconds\n" "PSNP interval value\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - circuit->psnp_interval[0] = DEFAULT_PSNP_INTERVAL; - circuit->psnp_interval[1] = DEFAULT_PSNP_INTERVAL; + circuit->psnp_interval[0] = DEFAULT_PSNP_INTERVAL; + circuit->psnp_interval[1] = DEFAULT_PSNP_INTERVAL; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1179,23 +1154,22 @@ DEFUN (psnp_interval_l1, "PSNP interval value\n" "Specify interval for level-1 PSNPs\n") { - int idx_number = 2; - unsigned long interval; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + int idx_number = 2; + unsigned long interval; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - interval = atol (argv[idx_number]->arg); - if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) - { - vty_out (vty, "Invalid psnp-interval %lu - should be <1-120>\n", - interval); - return CMD_ERR_AMBIGUOUS; - } + interval = atol(argv[idx_number]->arg); + if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) { + vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n", + interval); + return CMD_ERR_AMBIGUOUS; + } - circuit->psnp_interval[0] = (u_int16_t) interval; + circuit->psnp_interval[0] = (u_int16_t)interval; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1208,13 +1182,13 @@ DEFUN (no_psnp_interval_l1, "PSNP interval value\n" "Specify interval for level-1 PSNPs\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - circuit->psnp_interval[0] = DEFAULT_PSNP_INTERVAL; + circuit->psnp_interval[0] = DEFAULT_PSNP_INTERVAL; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1226,23 +1200,22 @@ DEFUN (psnp_interval_l2, "PSNP interval value\n" "Specify interval for level-2 PSNPs\n") { - int idx_number = 2; - unsigned long interval; - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + int idx_number = 2; + unsigned long interval; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - interval = atol (argv[idx_number]->arg); - if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) - { - vty_out (vty, "Invalid psnp-interval %lu - should be <1-120>\n", - interval); - return CMD_ERR_AMBIGUOUS; - } + interval = atol(argv[idx_number]->arg); + if (interval < MIN_PSNP_INTERVAL || interval > MAX_PSNP_INTERVAL) { + vty_out(vty, "Invalid psnp-interval %lu - should be <1-120>\n", + interval); + return CMD_ERR_AMBIGUOUS; + } - circuit->psnp_interval[1] = (u_int16_t) interval; + circuit->psnp_interval[1] = (u_int16_t)interval; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1255,13 +1228,13 @@ DEFUN (no_psnp_interval_l2, "PSNP interval value\n" "Specify interval for level-2 PSNPs\n") { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; - circuit->psnp_interval[1] = DEFAULT_PSNP_INTERVAL; + circuit->psnp_interval[1] = DEFAULT_PSNP_INTERVAL; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (circuit_topology, @@ -1271,26 +1244,24 @@ DEFUN (circuit_topology, "Configure interface IS-IS topologies\n" ISIS_MT_DESCRIPTIONS) { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - const char *arg = argv[2]->arg; - uint16_t mtid = isis_str2mtid(arg); + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + const char *arg = argv[2]->arg; + uint16_t mtid = isis_str2mtid(arg); - if (circuit->area && circuit->area->oldmetric) - { - vty_out (vty, - "Multi topology IS-IS can only be used with wide metrics\n"); - return CMD_ERR_AMBIGUOUS; - } + if (circuit->area && circuit->area->oldmetric) { + vty_out(vty, + "Multi topology IS-IS can only be used with wide metrics\n"); + return CMD_ERR_AMBIGUOUS; + } - if (mtid == (uint16_t)-1) - { - vty_out (vty, "Don't know topology '%s'\n", arg); - return CMD_ERR_AMBIGUOUS; - } + if (mtid == (uint16_t)-1) { + vty_out(vty, "Don't know topology '%s'\n", arg); + return CMD_ERR_AMBIGUOUS; + } - return isis_circuit_mt_enabled_set(circuit, mtid, true); + return isis_circuit_mt_enabled_set(circuit, mtid, true); } DEFUN (no_circuit_topology, @@ -1301,64 +1272,57 @@ DEFUN (no_circuit_topology, "Configure interface IS-IS topologies\n" ISIS_MT_DESCRIPTIONS) { - struct isis_circuit *circuit = isis_circuit_lookup (vty); - if (!circuit) - return CMD_ERR_NO_MATCH; - const char *arg = argv[3]->arg; - uint16_t mtid = isis_str2mtid(arg); - - if (circuit->area && circuit->area->oldmetric) - { - vty_out (vty, - "Multi topology IS-IS can only be used with wide metrics\n"); - return CMD_ERR_AMBIGUOUS; - } - - if (mtid == (uint16_t)-1) - { - vty_out (vty, "Don't know topology '%s'\n", arg); - return CMD_ERR_AMBIGUOUS; - } - - return isis_circuit_mt_enabled_set(circuit, mtid, false); -} - -static int -validate_metric_style_narrow (struct vty *vty, struct isis_area *area) -{ - struct isis_circuit *circuit; - struct listnode *node; - - if (! vty) - return CMD_ERR_AMBIGUOUS; - - if (! area) - { - vty_out (vty, "ISIS area is invalid\n"); - return CMD_ERR_AMBIGUOUS; - } - - for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit)) - { - if ((area->is_type & IS_LEVEL_1) && - (circuit->is_type & IS_LEVEL_1) && - (circuit->te_metric[0] > MAX_NARROW_LINK_METRIC)) - { - vty_out (vty, "ISIS circuit %s metric is invalid\n", - circuit->interface->name); - return CMD_ERR_AMBIGUOUS; - } - if ((area->is_type & IS_LEVEL_2) && - (circuit->is_type & IS_LEVEL_2) && - (circuit->te_metric[1] > MAX_NARROW_LINK_METRIC)) - { - vty_out (vty, "ISIS circuit %s metric is invalid\n", - circuit->interface->name); - return CMD_ERR_AMBIGUOUS; - } - } - - return CMD_SUCCESS; + struct isis_circuit *circuit = isis_circuit_lookup(vty); + if (!circuit) + return CMD_ERR_NO_MATCH; + const char *arg = argv[3]->arg; + uint16_t mtid = isis_str2mtid(arg); + + if (circuit->area && circuit->area->oldmetric) { + vty_out(vty, + "Multi topology IS-IS can only be used with wide metrics\n"); + return CMD_ERR_AMBIGUOUS; + } + + if (mtid == (uint16_t)-1) { + vty_out(vty, "Don't know topology '%s'\n", arg); + return CMD_ERR_AMBIGUOUS; + } + + return isis_circuit_mt_enabled_set(circuit, mtid, false); +} + +static int validate_metric_style_narrow(struct vty *vty, struct isis_area *area) +{ + struct isis_circuit *circuit; + struct listnode *node; + + if (!vty) + return CMD_ERR_AMBIGUOUS; + + if (!area) { + vty_out(vty, "ISIS area is invalid\n"); + return CMD_ERR_AMBIGUOUS; + } + + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) { + if ((area->is_type & IS_LEVEL_1) + && (circuit->is_type & IS_LEVEL_1) + && (circuit->te_metric[0] > MAX_NARROW_LINK_METRIC)) { + vty_out(vty, "ISIS circuit %s metric is invalid\n", + circuit->interface->name); + return CMD_ERR_AMBIGUOUS; + } + if ((area->is_type & IS_LEVEL_2) + && (circuit->is_type & IS_LEVEL_2) + && (circuit->te_metric[1] > MAX_NARROW_LINK_METRIC)) { + vty_out(vty, "ISIS circuit %s metric is invalid\n", + circuit->interface->name); + return CMD_ERR_AMBIGUOUS; + } + } + + return CMD_SUCCESS; } DEFUN (metric_style, @@ -1369,34 +1333,32 @@ DEFUN (metric_style, "Send and accept both styles of TLVs during transition\n" "Use new style of TLVs to carry wider metric\n") { - int idx_metric_style = 1; - VTY_DECLVAR_CONTEXT (isis_area, area); - int ret; + int idx_metric_style = 1; + VTY_DECLVAR_CONTEXT(isis_area, area); + int ret; - if (strncmp (argv[idx_metric_style]->arg, "w", 1) == 0) - { - isis_area_metricstyle_set(area, false, true); - return CMD_SUCCESS; - } + if (strncmp(argv[idx_metric_style]->arg, "w", 1) == 0) { + isis_area_metricstyle_set(area, false, true); + return CMD_SUCCESS; + } - if (area_is_mt(area)) - { - vty_out (vty, - "Narrow metrics cannot be used while multi topology IS-IS is active\n"); - return CMD_ERR_AMBIGUOUS; - } + if (area_is_mt(area)) { + vty_out(vty, + "Narrow metrics cannot be used while multi topology IS-IS is active\n"); + return CMD_ERR_AMBIGUOUS; + } - ret = validate_metric_style_narrow (vty, area); - if (ret != CMD_SUCCESS) - return ret; + ret = validate_metric_style_narrow(vty, area); + if (ret != CMD_SUCCESS) + return ret; - if (strncmp (argv[idx_metric_style]->arg, "t", 1) == 0) - isis_area_metricstyle_set(area, true, true); - else if (strncmp (argv[idx_metric_style]->arg, "n", 1) == 0) - isis_area_metricstyle_set(area, true, false); - return CMD_SUCCESS; + if (strncmp(argv[idx_metric_style]->arg, "t", 1) == 0) + isis_area_metricstyle_set(area, true, true); + else if (strncmp(argv[idx_metric_style]->arg, "n", 1) == 0) + isis_area_metricstyle_set(area, true, false); + return CMD_SUCCESS; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_metric_style, @@ -1405,22 +1367,21 @@ DEFUN (no_metric_style, NO_STR "Use old-style (ISO 10589) or new-style packet formats\n") { - VTY_DECLVAR_CONTEXT (isis_area, area); - int ret; + VTY_DECLVAR_CONTEXT(isis_area, area); + int ret; - if (area_is_mt(area)) - { - vty_out (vty, - "Narrow metrics cannot be used while multi topology IS-IS is active\n"); - return CMD_ERR_AMBIGUOUS; - } + if (area_is_mt(area)) { + vty_out(vty, + "Narrow metrics cannot be used while multi topology IS-IS is active\n"); + return CMD_ERR_AMBIGUOUS; + } - ret = validate_metric_style_narrow (vty, area); - if (ret != CMD_SUCCESS) - return ret; + ret = validate_metric_style_narrow(vty, area); + if (ret != CMD_SUCCESS) + return ret; - isis_area_metricstyle_set(area, true, false); - return CMD_SUCCESS; + isis_area_metricstyle_set(area, true, false); + return CMD_SUCCESS; } DEFUN (set_overload_bit, @@ -1428,10 +1389,10 @@ DEFUN (set_overload_bit, "set-overload-bit", "Set overload bit to avoid any transit traffic\n") { - VTY_DECLVAR_CONTEXT (isis_area, area); + VTY_DECLVAR_CONTEXT(isis_area, area); - isis_area_overload_bit_set(area, true); - return CMD_SUCCESS; + isis_area_overload_bit_set(area, true); + return CMD_SUCCESS; } DEFUN (no_set_overload_bit, @@ -1440,10 +1401,10 @@ DEFUN (no_set_overload_bit, "Reset overload bit to accept transit traffic\n" "Reset overload bit\n") { - VTY_DECLVAR_CONTEXT (isis_area, area); + VTY_DECLVAR_CONTEXT(isis_area, area); - isis_area_overload_bit_set(area, false); - return CMD_SUCCESS; + isis_area_overload_bit_set(area, false); + return CMD_SUCCESS; } DEFUN (set_attached_bit, @@ -1451,10 +1412,10 @@ DEFUN (set_attached_bit, "set-attached-bit", "Set attached bit to identify as L1/L2 router for inter-area traffic\n") { - VTY_DECLVAR_CONTEXT (isis_area, area); + VTY_DECLVAR_CONTEXT(isis_area, area); - isis_area_attached_bit_set(area, true); - return CMD_SUCCESS; + isis_area_attached_bit_set(area, true); + return CMD_SUCCESS; } DEFUN (no_set_attached_bit, @@ -1463,10 +1424,10 @@ DEFUN (no_set_attached_bit, NO_STR "Reset attached bit\n") { - VTY_DECLVAR_CONTEXT (isis_area, area); + VTY_DECLVAR_CONTEXT(isis_area, area); - isis_area_attached_bit_set(area, false); - return CMD_SUCCESS; + isis_area_attached_bit_set(area, false); + return CMD_SUCCESS; } DEFUN (dynamic_hostname, @@ -1475,10 +1436,10 @@ DEFUN (dynamic_hostname, "Dynamic hostname for IS-IS\n" "Dynamic hostname\n") { - VTY_DECLVAR_CONTEXT (isis_area, area); + VTY_DECLVAR_CONTEXT(isis_area, area); - isis_area_dynhostname_set(area, true); - return CMD_SUCCESS; + isis_area_dynhostname_set(area, true); + return CMD_SUCCESS; } DEFUN (no_dynamic_hostname, @@ -1488,32 +1449,33 @@ DEFUN (no_dynamic_hostname, "Dynamic hostname for IS-IS\n" "Dynamic hostname\n") { - VTY_DECLVAR_CONTEXT (isis_area, area); + VTY_DECLVAR_CONTEXT(isis_area, area); - isis_area_dynhostname_set(area, false); - return CMD_SUCCESS; + isis_area_dynhostname_set(area, false); + return CMD_SUCCESS; } static int area_lsp_mtu_set(struct vty *vty, unsigned int lsp_mtu) { - VTY_DECLVAR_CONTEXT (isis_area, area); - struct listnode *node; - struct isis_circuit *circuit; + VTY_DECLVAR_CONTEXT(isis_area, area); + struct listnode *node; + struct isis_circuit *circuit; - for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) - { - if(circuit->state != C_STATE_INIT && circuit->state != C_STATE_UP) - continue; - if(lsp_mtu > isis_circuit_pdu_size(circuit)) - { - vty_out (vty, "ISIS area contains circuit %s, which has a maximum PDU size of %zu.\n", - circuit->interface->name,isis_circuit_pdu_size(circuit)); - return CMD_ERR_AMBIGUOUS; - } - } + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) { + if (circuit->state != C_STATE_INIT + && circuit->state != C_STATE_UP) + continue; + if (lsp_mtu > isis_circuit_pdu_size(circuit)) { + vty_out(vty, + "ISIS area contains circuit %s, which has a maximum PDU size of %zu.\n", + circuit->interface->name, + isis_circuit_pdu_size(circuit)); + return CMD_ERR_AMBIGUOUS; + } + } - isis_area_lsp_mtu_set(area, lsp_mtu); - return CMD_SUCCESS; + isis_area_lsp_mtu_set(area, lsp_mtu); + return CMD_SUCCESS; } DEFUN (area_lsp_mtu, @@ -1522,12 +1484,12 @@ DEFUN (area_lsp_mtu, "Configure the maximum size of generated LSPs\n" "Maximum size of generated LSPs\n") { - int idx_number = 1; - unsigned int lsp_mtu; + int idx_number = 1; + unsigned int lsp_mtu; - lsp_mtu = strtoul(argv[idx_number]->arg, NULL, 10); + lsp_mtu = strtoul(argv[idx_number]->arg, NULL, 10); - return area_lsp_mtu_set(vty, lsp_mtu); + return area_lsp_mtu_set(vty, lsp_mtu); } @@ -1538,7 +1500,7 @@ DEFUN (no_area_lsp_mtu, "Configure the maximum size of generated LSPs\n" "Maximum size of generated LSPs\n") { - return area_lsp_mtu_set(vty, DEFAULT_LSP_MTU); + return area_lsp_mtu_set(vty, DEFAULT_LSP_MTU); } @@ -1550,20 +1512,19 @@ DEFUN (is_type, "Act as both a station router and an area router\n" "Act as an area router only\n") { - int idx_level = 1; - VTY_DECLVAR_CONTEXT (isis_area, area); - int type; + int idx_level = 1; + VTY_DECLVAR_CONTEXT(isis_area, area); + int type; - type = string2circuit_t (argv[idx_level]->arg); - if (!type) - { - vty_out (vty, "Unknown IS level \n"); - return CMD_SUCCESS; - } + type = string2circuit_t(argv[idx_level]->arg); + if (!type) { + vty_out(vty, "Unknown IS level \n"); + return CMD_SUCCESS; + } - isis_area_is_type_set(area, type); + isis_area_is_type_set(area, type); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_is_type, @@ -1575,52 +1536,49 @@ DEFUN (no_is_type, "Act as both a station router and an area router\n" "Act as an area router only\n") { - VTY_DECLVAR_CONTEXT (isis_area, area); - int type; + VTY_DECLVAR_CONTEXT(isis_area, area); + int type; - /* - * Put the is-type back to defaults: - * - level-1-2 on first area - * - level-1 for the rest - */ - if (listgetdata (listhead (isis->area_list)) == area) - type = IS_LEVEL_1_AND_2; - else - type = IS_LEVEL_1; + /* + * Put the is-type back to defaults: + * - level-1-2 on first area + * - level-1 for the rest + */ + if (listgetdata(listhead(isis->area_list)) == area) + type = IS_LEVEL_1_AND_2; + else + type = IS_LEVEL_1; - isis_area_is_type_set(area, type); + isis_area_is_type_set(area, type); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -set_lsp_gen_interval (struct vty *vty, struct isis_area *area, - uint16_t interval, int level) +static int set_lsp_gen_interval(struct vty *vty, struct isis_area *area, + uint16_t interval, int level) { - int lvl; + int lvl; - for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) - { - if (!(lvl & level)) - continue; + for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) { + if (!(lvl & level)) + continue; - if (interval >= area->lsp_refresh[lvl-1]) - { - vty_out (vty, "LSP gen interval %us must be less than " - "the LSP refresh interval %us\n", - interval, area->lsp_refresh[lvl - 1]); - return CMD_ERR_AMBIGUOUS; - } - } + if (interval >= area->lsp_refresh[lvl - 1]) { + vty_out(vty, + "LSP gen interval %us must be less than " + "the LSP refresh interval %us\n", + interval, area->lsp_refresh[lvl - 1]); + return CMD_ERR_AMBIGUOUS; + } + } - for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) - { - if (!(lvl & level)) - continue; - area->lsp_gen_interval[lvl-1] = interval; - } + for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) { + if (!(lvl & level)) + continue; + area->lsp_gen_interval[lvl - 1] = interval; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (lsp_gen_interval, @@ -1631,21 +1589,21 @@ DEFUN (lsp_gen_interval, "Set interval for level 2 only\n" "Minimum interval in seconds\n") { - int idx = 0; - VTY_DECLVAR_CONTEXT (isis_area, area); - uint16_t interval; - int level; + int idx = 0; + VTY_DECLVAR_CONTEXT(isis_area, area); + uint16_t interval; + int level; - level = 0; - level |= argv_find (argv, argc, "level-1", &idx) ? IS_LEVEL_1 : 0; - level |= argv_find (argv, argc, "level-2", &idx) ? IS_LEVEL_2 : 0; - if (!level) - level = IS_LEVEL_1 | IS_LEVEL_2; + level = 0; + level |= argv_find(argv, argc, "level-1", &idx) ? IS_LEVEL_1 : 0; + level |= argv_find(argv, argc, "level-2", &idx) ? IS_LEVEL_2 : 0; + if (!level) + level = IS_LEVEL_1 | IS_LEVEL_2; - argv_find (argv, argc, "(1-120)", &idx); + argv_find(argv, argc, "(1-120)", &idx); - interval = atoi (argv[idx]->arg); - return set_lsp_gen_interval (vty, area, interval, level); + interval = atoi(argv[idx]->arg); + return set_lsp_gen_interval(vty, area, interval, level); } DEFUN (no_lsp_gen_interval, @@ -1657,19 +1615,19 @@ DEFUN (no_lsp_gen_interval, "Set interval for level 2 only\n" "Minimum interval in seconds\n") { - int idx = 0; - VTY_DECLVAR_CONTEXT (isis_area, area); - uint16_t interval; - int level; + int idx = 0; + VTY_DECLVAR_CONTEXT(isis_area, area); + uint16_t interval; + int level; - level = 0; - level |= argv_find (argv, argc, "level-1", &idx) ? IS_LEVEL_1 : 0; - level |= argv_find (argv, argc, "level-2", &idx) ? IS_LEVEL_2 : 0; - if (!level) - level = IS_LEVEL_1 | IS_LEVEL_2; + level = 0; + level |= argv_find(argv, argc, "level-1", &idx) ? IS_LEVEL_1 : 0; + level |= argv_find(argv, argc, "level-2", &idx) ? IS_LEVEL_2 : 0; + if (!level) + level = IS_LEVEL_1 | IS_LEVEL_2; - interval = DEFAULT_MIN_LSP_GEN_INTERVAL; - return set_lsp_gen_interval (vty, area, interval, level); + interval = DEFAULT_MIN_LSP_GEN_INTERVAL; + return set_lsp_gen_interval(vty, area, interval, level); } DEFUN (spf_interval, @@ -1678,15 +1636,15 @@ DEFUN (spf_interval, "Minimum interval between SPF calculations\n" "Minimum interval between consecutive SPFs in seconds\n") { - int idx_number = 1; - VTY_DECLVAR_CONTEXT (isis_area, area); - u_int16_t interval; + int idx_number = 1; + VTY_DECLVAR_CONTEXT(isis_area, area); + u_int16_t interval; - interval = atoi (argv[idx_number]->arg); - area->min_spf_interval[0] = interval; - area->min_spf_interval[1] = interval; + interval = atoi(argv[idx_number]->arg); + area->min_spf_interval[0] = interval; + area->min_spf_interval[1] = interval; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1699,12 +1657,12 @@ DEFUN (no_spf_interval, "Set interval for level 2 only\n" "Minimum interval between consecutive SPFs in seconds\n") { - VTY_DECLVAR_CONTEXT (isis_area, area); + VTY_DECLVAR_CONTEXT(isis_area, area); - area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL; - area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL; + area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL; + area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1715,14 +1673,14 @@ DEFUN (spf_interval_l1, "Set interval for level 1 only\n" "Minimum interval between consecutive SPFs in seconds\n") { - int idx_number = 2; - VTY_DECLVAR_CONTEXT (isis_area, area); - u_int16_t interval; + int idx_number = 2; + VTY_DECLVAR_CONTEXT(isis_area, area); + u_int16_t interval; - interval = atoi (argv[idx_number]->arg); - area->min_spf_interval[0] = interval; + interval = atoi(argv[idx_number]->arg); + area->min_spf_interval[0] = interval; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_spf_interval_l1, @@ -1732,11 +1690,11 @@ DEFUN (no_spf_interval_l1, "Minimum interval between SPF calculations\n" "Set interval for level 1 only\n") { - VTY_DECLVAR_CONTEXT (isis_area, area); + VTY_DECLVAR_CONTEXT(isis_area, area); - area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL; + area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1747,14 +1705,14 @@ DEFUN (spf_interval_l2, "Set interval for level 2 only\n" "Minimum interval between consecutive SPFs in seconds\n") { - int idx_number = 2; - VTY_DECLVAR_CONTEXT (isis_area, area); - u_int16_t interval; + int idx_number = 2; + VTY_DECLVAR_CONTEXT(isis_area, area); + u_int16_t interval; - interval = atoi (argv[idx_number]->arg); - area->min_spf_interval[1] = interval; + interval = atoi(argv[idx_number]->arg); + area->min_spf_interval[1] = interval; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_spf_interval_l2, @@ -1764,11 +1722,11 @@ DEFUN (no_spf_interval_l2, "Minimum interval between SPF calculations\n" "Set interval for level 2 only\n") { - VTY_DECLVAR_CONTEXT (isis_area, area); + VTY_DECLVAR_CONTEXT(isis_area, area); - area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL; + area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_spf_delay_ietf, @@ -1777,14 +1735,14 @@ DEFUN (no_spf_delay_ietf, NO_STR "IETF SPF delay algorithm\n") { - VTY_DECLVAR_CONTEXT (isis_area, area); + VTY_DECLVAR_CONTEXT(isis_area, area); - spf_backoff_free(area->spf_delay_ietf[0]); - spf_backoff_free(area->spf_delay_ietf[1]); - area->spf_delay_ietf[0] = NULL; - area->spf_delay_ietf[1] = NULL; + spf_backoff_free(area->spf_delay_ietf[0]); + spf_backoff_free(area->spf_delay_ietf[1]); + area->spf_delay_ietf[0] = NULL; + area->spf_delay_ietf[1] = NULL; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (spf_delay_ietf, @@ -1802,76 +1760,77 @@ DEFUN (spf_delay_ietf, "Maximum duration needed to learn all the events related to a single failure\n" "Maximum duration needed to learn all the events related to a single failure (in milliseconds)\n") { - VTY_DECLVAR_CONTEXT (isis_area, area); - - long init_delay = atol(argv[2]->arg); - long short_delay = atol(argv[4]->arg); - long long_delay = atol(argv[6]->arg); - long holddown = atol(argv[8]->arg); - long timetolearn = atol(argv[10]->arg); - - size_t bufsiz = strlen(area->area_tag) + sizeof("IS-IS Lx"); - char *buf = XCALLOC(MTYPE_TMP, bufsiz); - - snprintf(buf, bufsiz, "IS-IS %s L1", area->area_tag); - spf_backoff_free(area->spf_delay_ietf[0]); - area->spf_delay_ietf[0] = spf_backoff_new(master, buf, init_delay, - short_delay, long_delay, - holddown, timetolearn); - - snprintf(buf, bufsiz, "IS-IS %s L2", area->area_tag); - spf_backoff_free(area->spf_delay_ietf[1]); - area->spf_delay_ietf[1] = spf_backoff_new(master, buf, init_delay, - short_delay, long_delay, - holddown, timetolearn); - - XFREE(MTYPE_TMP, buf); - return CMD_SUCCESS; -} - -static int -area_max_lsp_lifetime_set(struct vty *vty, int level, - uint16_t interval) -{ - VTY_DECLVAR_CONTEXT (isis_area, area); - int lvl; - uint16_t refresh_interval = interval - 300; - int set_refresh_interval[ISIS_LEVELS] = {0, 0}; - - for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++) - { - if (!(lvl & level)) - continue; - - if (refresh_interval < area->lsp_refresh[lvl-1]) - { - vty_out (vty, "Level %d Max LSP lifetime %us must be 300s greater than " - "the configured LSP refresh interval %us\n", - lvl, interval, area->lsp_refresh[lvl - 1]); - vty_out (vty, "Automatically reducing level %d LSP refresh interval " - "to %us\n", lvl, refresh_interval); - set_refresh_interval[lvl-1] = 1; - - if (refresh_interval <= area->lsp_gen_interval[lvl-1]) - { - vty_out (vty, "LSP refresh interval %us must be greater than " - "the configured LSP gen interval %us\n", - refresh_interval,area->lsp_gen_interval[lvl - 1]); - return CMD_ERR_AMBIGUOUS; - } - } - } - - for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++) - { - if (!(lvl & level)) - continue; - isis_area_max_lsp_lifetime_set(area, lvl, interval); - if (set_refresh_interval[lvl-1]) - isis_area_lsp_refresh_set(area, lvl, refresh_interval); - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(isis_area, area); + + long init_delay = atol(argv[2]->arg); + long short_delay = atol(argv[4]->arg); + long long_delay = atol(argv[6]->arg); + long holddown = atol(argv[8]->arg); + long timetolearn = atol(argv[10]->arg); + + size_t bufsiz = strlen(area->area_tag) + sizeof("IS-IS Lx"); + char *buf = XCALLOC(MTYPE_TMP, bufsiz); + + snprintf(buf, bufsiz, "IS-IS %s L1", area->area_tag); + spf_backoff_free(area->spf_delay_ietf[0]); + area->spf_delay_ietf[0] = + spf_backoff_new(master, buf, init_delay, short_delay, + long_delay, holddown, timetolearn); + + snprintf(buf, bufsiz, "IS-IS %s L2", area->area_tag); + spf_backoff_free(area->spf_delay_ietf[1]); + area->spf_delay_ietf[1] = + spf_backoff_new(master, buf, init_delay, short_delay, + long_delay, holddown, timetolearn); + + XFREE(MTYPE_TMP, buf); + return CMD_SUCCESS; +} + +static int area_max_lsp_lifetime_set(struct vty *vty, int level, + uint16_t interval) +{ + VTY_DECLVAR_CONTEXT(isis_area, area); + int lvl; + uint16_t refresh_interval = interval - 300; + int set_refresh_interval[ISIS_LEVELS] = {0, 0}; + + for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++) { + if (!(lvl & level)) + continue; + + if (refresh_interval < area->lsp_refresh[lvl - 1]) { + vty_out(vty, + "Level %d Max LSP lifetime %us must be 300s greater than " + "the configured LSP refresh interval %us\n", + lvl, interval, area->lsp_refresh[lvl - 1]); + vty_out(vty, + "Automatically reducing level %d LSP refresh interval " + "to %us\n", + lvl, refresh_interval); + set_refresh_interval[lvl - 1] = 1; + + if (refresh_interval + <= area->lsp_gen_interval[lvl - 1]) { + vty_out(vty, + "LSP refresh interval %us must be greater than " + "the configured LSP gen interval %us\n", + refresh_interval, + area->lsp_gen_interval[lvl - 1]); + return CMD_ERR_AMBIGUOUS; + } + } + } + + for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++) { + if (!(lvl & level)) + continue; + isis_area_max_lsp_lifetime_set(area, lvl, interval); + if (set_refresh_interval[lvl - 1]) + isis_area_lsp_refresh_set(area, lvl, refresh_interval); + } + + return CMD_SUCCESS; } DEFUN (max_lsp_lifetime, @@ -1882,18 +1841,18 @@ DEFUN (max_lsp_lifetime, "Maximum LSP lifetime for Level 2 only\n" "LSP lifetime in seconds\n") { - int idx = 0; - unsigned int level = IS_LEVEL_1_AND_2; + int idx = 0; + unsigned int level = IS_LEVEL_1_AND_2; - if (argv_find (argv, argc, "level-1", &idx)) - level = IS_LEVEL_1; - else if (argv_find (argv, argc, "level-2", &idx)) - level = IS_LEVEL_2; + if (argv_find(argv, argc, "level-1", &idx)) + level = IS_LEVEL_1; + else if (argv_find(argv, argc, "level-2", &idx)) + level = IS_LEVEL_2; - argv_find (argv, argc, "(350-65535)", &idx); - int lifetime = atoi(argv[idx]->arg); + argv_find(argv, argc, "(350-65535)", &idx); + int lifetime = atoi(argv[idx]->arg); - return area_max_lsp_lifetime_set(vty, level, lifetime); + return area_max_lsp_lifetime_set(vty, level, lifetime); } @@ -1906,51 +1865,49 @@ DEFUN (no_max_lsp_lifetime, "Maximum LSP lifetime for Level 2 only\n" "LSP lifetime in seconds\n") { - int idx = 0; - unsigned int level = IS_LEVEL_1_AND_2; - - if (argv_find (argv, argc, "level-1", &idx)) - level = IS_LEVEL_1; - else if (argv_find (argv, argc, "level-2", &idx)) - level = IS_LEVEL_2; - - return area_max_lsp_lifetime_set(vty, level, DEFAULT_LSP_LIFETIME); -} - -static int -area_lsp_refresh_interval_set(struct vty *vty, int level, uint16_t interval) -{ - VTY_DECLVAR_CONTEXT (isis_area, area); - int lvl; - - for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) - { - if (!(lvl & level)) - continue; - if (interval <= area->lsp_gen_interval[lvl-1]) - { - vty_out (vty, "LSP refresh interval %us must be greater than " - "the configured LSP gen interval %us\n", - interval,area->lsp_gen_interval[lvl - 1]); - return CMD_ERR_AMBIGUOUS; - } - if (interval > (area->max_lsp_lifetime[lvl-1] - 300)) - { - vty_out (vty, "LSP refresh interval %us must be less than " - "the configured LSP lifetime %us less 300\n", - interval,area->max_lsp_lifetime[lvl - 1]); - return CMD_ERR_AMBIGUOUS; - } - } - - for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) - { - if (!(lvl & level)) - continue; - isis_area_lsp_refresh_set(area, lvl, interval); - } - - return CMD_SUCCESS; + int idx = 0; + unsigned int level = IS_LEVEL_1_AND_2; + + if (argv_find(argv, argc, "level-1", &idx)) + level = IS_LEVEL_1; + else if (argv_find(argv, argc, "level-2", &idx)) + level = IS_LEVEL_2; + + return area_max_lsp_lifetime_set(vty, level, DEFAULT_LSP_LIFETIME); +} + +static int area_lsp_refresh_interval_set(struct vty *vty, int level, + uint16_t interval) +{ + VTY_DECLVAR_CONTEXT(isis_area, area); + int lvl; + + for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) { + if (!(lvl & level)) + continue; + if (interval <= area->lsp_gen_interval[lvl - 1]) { + vty_out(vty, + "LSP refresh interval %us must be greater than " + "the configured LSP gen interval %us\n", + interval, area->lsp_gen_interval[lvl - 1]); + return CMD_ERR_AMBIGUOUS; + } + if (interval > (area->max_lsp_lifetime[lvl - 1] - 300)) { + vty_out(vty, + "LSP refresh interval %us must be less than " + "the configured LSP lifetime %us less 300\n", + interval, area->max_lsp_lifetime[lvl - 1]); + return CMD_ERR_AMBIGUOUS; + } + } + + for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; ++lvl) { + if (!(lvl & level)) + continue; + isis_area_lsp_refresh_set(area, lvl, interval); + } + + return CMD_SUCCESS; } DEFUN (lsp_refresh_interval, @@ -1961,17 +1918,17 @@ DEFUN (lsp_refresh_interval, "LSP refresh interval for Level 2 only\n" "LSP refresh interval in seconds\n") { - int idx = 0; - unsigned int level = IS_LEVEL_1_AND_2; - unsigned int interval = 0; + int idx = 0; + unsigned int level = IS_LEVEL_1_AND_2; + unsigned int interval = 0; - if (argv_find (argv, argc, "level-1", &idx)) - level = IS_LEVEL_1; - else if (argv_find (argv, argc, "level-2", &idx)) - level = IS_LEVEL_2; + if (argv_find(argv, argc, "level-1", &idx)) + level = IS_LEVEL_1; + else if (argv_find(argv, argc, "level-2", &idx)) + level = IS_LEVEL_2; - interval = atoi(argv[argc-1]->arg); - return area_lsp_refresh_interval_set(vty, level, interval); + interval = atoi(argv[argc - 1]->arg); + return area_lsp_refresh_interval_set(vty, level, interval); } DEFUN (no_lsp_refresh_interval, @@ -1983,33 +1940,32 @@ DEFUN (no_lsp_refresh_interval, "LSP refresh interval for Level 2 only\n" "LSP refresh interval in seconds\n") { - int idx = 0; - unsigned int level = IS_LEVEL_1_AND_2; + int idx = 0; + unsigned int level = IS_LEVEL_1_AND_2; - if (argv_find (argv, argc, "level-1", &idx)) - level = IS_LEVEL_1; - else if (argv_find (argv, argc, "level-2", &idx)) - level = IS_LEVEL_2; + if (argv_find(argv, argc, "level-1", &idx)) + level = IS_LEVEL_1; + else if (argv_find(argv, argc, "level-2", &idx)) + level = IS_LEVEL_2; - return area_lsp_refresh_interval_set(vty, level, DEFAULT_MAX_LSP_GEN_INTERVAL); + return area_lsp_refresh_interval_set(vty, level, + DEFAULT_MAX_LSP_GEN_INTERVAL); } -static int -area_passwd_set(struct vty *vty, int level, - int (*type_set)(struct isis_area *area, int level, - const char *passwd, u_char snp_auth), - const char *passwd, u_char snp_auth) +static int area_passwd_set(struct vty *vty, int level, + int (*type_set)(struct isis_area *area, int level, + const char *passwd, u_char snp_auth), + const char *passwd, u_char snp_auth) { - VTY_DECLVAR_CONTEXT (isis_area, area); + VTY_DECLVAR_CONTEXT(isis_area, area); - if (passwd && strlen(passwd) > 254) - { - vty_out (vty, "Too long area password (>254)\n"); - return CMD_ERR_AMBIGUOUS; - } + if (passwd && strlen(passwd) > 254) { + vty_out(vty, "Too long area password (>254)\n"); + return CMD_ERR_AMBIGUOUS; + } - type_set(area, level, passwd, snp_auth); - return CMD_SUCCESS; + type_set(area, level, passwd, snp_auth); + return CMD_SUCCESS; } @@ -2024,21 +1980,22 @@ DEFUN (area_passwd_md5, "Send but do not check PDUs on receiving\n" "Send and check PDUs on receiving\n") { - int idx_password = 0; - int idx_word = 2; - int idx_type = 5; - u_char snp_auth = 0; - int level = strmatch(argv[idx_password]->text, "domain-password") ? IS_LEVEL_2 : IS_LEVEL_1; + int idx_password = 0; + int idx_word = 2; + int idx_type = 5; + u_char snp_auth = 0; + int level = strmatch(argv[idx_password]->text, "domain-password") + ? IS_LEVEL_2 + : IS_LEVEL_1; - if (argc > 3) - { - snp_auth = SNP_AUTH_SEND; - if (strmatch(argv[idx_type]->text, "validate")) - snp_auth |= SNP_AUTH_RECV; - } + if (argc > 3) { + snp_auth = SNP_AUTH_SEND; + if (strmatch(argv[idx_type]->text, "validate")) + snp_auth |= SNP_AUTH_RECV; + } - return area_passwd_set(vty, level, isis_area_passwd_hmac_md5_set, - argv[idx_word]->arg, snp_auth); + return area_passwd_set(vty, level, isis_area_passwd_hmac_md5_set, + argv[idx_word]->arg, snp_auth); } DEFUN (domain_passwd_md5, @@ -2052,7 +2009,7 @@ DEFUN (domain_passwd_md5, "Send but do not check PDUs on receiving\n" "Send and check PDUs on receiving\n") { - return area_passwd_md5 (self, vty, argc, argv); + return area_passwd_md5(self, vty, argc, argv); } DEFUN (area_passwd_clear, @@ -2066,21 +2023,22 @@ DEFUN (area_passwd_clear, "Send but do not check PDUs on receiving\n" "Send and check PDUs on receiving\n") { - int idx_password = 0; - int idx_word = 2; - int idx_type = 5; - u_char snp_auth = 0; - int level = strmatch(argv[idx_password]->text, "domain-password") ? IS_LEVEL_2 : IS_LEVEL_1; + int idx_password = 0; + int idx_word = 2; + int idx_type = 5; + u_char snp_auth = 0; + int level = strmatch(argv[idx_password]->text, "domain-password") + ? IS_LEVEL_2 + : IS_LEVEL_1; - if (argc > 3) - { - snp_auth = SNP_AUTH_SEND; - if (strmatch (argv[idx_type]->text, "validate")) - snp_auth |= SNP_AUTH_RECV; - } + if (argc > 3) { + snp_auth = SNP_AUTH_SEND; + if (strmatch(argv[idx_type]->text, "validate")) + snp_auth |= SNP_AUTH_RECV; + } - return area_passwd_set(vty, level, isis_area_passwd_cleartext_set, - argv[idx_word]->arg, snp_auth); + return area_passwd_set(vty, level, isis_area_passwd_cleartext_set, + argv[idx_word]->arg, snp_auth); } DEFUN (domain_passwd_clear, @@ -2094,7 +2052,7 @@ DEFUN (domain_passwd_clear, "Send but do not check PDUs on receiving\n" "Send and check PDUs on receiving\n") { - return area_passwd_clear (self, vty, argc, argv); + return area_passwd_clear(self, vty, argc, argv); } DEFUN (no_area_passwd, @@ -2104,121 +2062,121 @@ DEFUN (no_area_passwd, "Configure the authentication password for an area\n" "Set the authentication password for a routing domain\n") { - int idx_password = 1; - int level = strmatch (argv[idx_password]->text, "domain-password") ? IS_LEVEL_2 : IS_LEVEL_1; - VTY_DECLVAR_CONTEXT (isis_area, area); + int idx_password = 1; + int level = strmatch(argv[idx_password]->text, "domain-password") + ? IS_LEVEL_2 + : IS_LEVEL_1; + VTY_DECLVAR_CONTEXT(isis_area, area); - return isis_area_passwd_unset (area, level); + return isis_area_passwd_unset(area, level); } -void -isis_vty_init (void) +void isis_vty_init(void) { - install_element (INTERFACE_NODE, &ip_router_isis_cmd); - install_element (INTERFACE_NODE, &ip6_router_isis_cmd); - install_element (INTERFACE_NODE, &no_ip_router_isis_cmd); - - install_element (INTERFACE_NODE, &isis_passive_cmd); - install_element (INTERFACE_NODE, &no_isis_passive_cmd); + install_element(INTERFACE_NODE, &ip_router_isis_cmd); + install_element(INTERFACE_NODE, &ip6_router_isis_cmd); + install_element(INTERFACE_NODE, &no_ip_router_isis_cmd); - install_element (INTERFACE_NODE, &isis_circuit_type_cmd); - install_element (INTERFACE_NODE, &no_isis_circuit_type_cmd); + install_element(INTERFACE_NODE, &isis_passive_cmd); + install_element(INTERFACE_NODE, &no_isis_passive_cmd); - install_element (INTERFACE_NODE, &isis_network_cmd); - install_element (INTERFACE_NODE, &no_isis_network_cmd); + install_element(INTERFACE_NODE, &isis_circuit_type_cmd); + install_element(INTERFACE_NODE, &no_isis_circuit_type_cmd); - install_element (INTERFACE_NODE, &isis_passwd_cmd); - install_element (INTERFACE_NODE, &no_isis_passwd_cmd); + install_element(INTERFACE_NODE, &isis_network_cmd); + install_element(INTERFACE_NODE, &no_isis_network_cmd); - install_element (INTERFACE_NODE, &isis_priority_cmd); - install_element (INTERFACE_NODE, &no_isis_priority_cmd); - install_element (INTERFACE_NODE, &isis_priority_l1_cmd); - install_element (INTERFACE_NODE, &no_isis_priority_l1_cmd); - install_element (INTERFACE_NODE, &isis_priority_l2_cmd); - install_element (INTERFACE_NODE, &no_isis_priority_l2_cmd); + install_element(INTERFACE_NODE, &isis_passwd_cmd); + install_element(INTERFACE_NODE, &no_isis_passwd_cmd); - install_element (INTERFACE_NODE, &isis_metric_cmd); - install_element (INTERFACE_NODE, &no_isis_metric_cmd); - install_element (INTERFACE_NODE, &isis_metric_l1_cmd); - install_element (INTERFACE_NODE, &no_isis_metric_l1_cmd); - install_element (INTERFACE_NODE, &isis_metric_l2_cmd); - install_element (INTERFACE_NODE, &no_isis_metric_l2_cmd); + install_element(INTERFACE_NODE, &isis_priority_cmd); + install_element(INTERFACE_NODE, &no_isis_priority_cmd); + install_element(INTERFACE_NODE, &isis_priority_l1_cmd); + install_element(INTERFACE_NODE, &no_isis_priority_l1_cmd); + install_element(INTERFACE_NODE, &isis_priority_l2_cmd); + install_element(INTERFACE_NODE, &no_isis_priority_l2_cmd); - install_element (INTERFACE_NODE, &isis_hello_interval_cmd); - install_element (INTERFACE_NODE, &no_isis_hello_interval_cmd); - install_element (INTERFACE_NODE, &isis_hello_interval_l1_cmd); - install_element (INTERFACE_NODE, &no_isis_hello_interval_l1_cmd); - install_element (INTERFACE_NODE, &isis_hello_interval_l2_cmd); - install_element (INTERFACE_NODE, &no_isis_hello_interval_l2_cmd); + install_element(INTERFACE_NODE, &isis_metric_cmd); + install_element(INTERFACE_NODE, &no_isis_metric_cmd); + install_element(INTERFACE_NODE, &isis_metric_l1_cmd); + install_element(INTERFACE_NODE, &no_isis_metric_l1_cmd); + install_element(INTERFACE_NODE, &isis_metric_l2_cmd); + install_element(INTERFACE_NODE, &no_isis_metric_l2_cmd); - install_element (INTERFACE_NODE, &isis_hello_multiplier_cmd); - install_element (INTERFACE_NODE, &no_isis_hello_multiplier_cmd); - install_element (INTERFACE_NODE, &isis_hello_multiplier_l1_cmd); - install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l1_cmd); - install_element (INTERFACE_NODE, &isis_hello_multiplier_l2_cmd); - install_element (INTERFACE_NODE, &no_isis_hello_multiplier_l2_cmd); + install_element(INTERFACE_NODE, &isis_hello_interval_cmd); + install_element(INTERFACE_NODE, &no_isis_hello_interval_cmd); + install_element(INTERFACE_NODE, &isis_hello_interval_l1_cmd); + install_element(INTERFACE_NODE, &no_isis_hello_interval_l1_cmd); + install_element(INTERFACE_NODE, &isis_hello_interval_l2_cmd); + install_element(INTERFACE_NODE, &no_isis_hello_interval_l2_cmd); - install_element (INTERFACE_NODE, &isis_hello_padding_cmd); - install_element (INTERFACE_NODE, &no_isis_hello_padding_cmd); + install_element(INTERFACE_NODE, &isis_hello_multiplier_cmd); + install_element(INTERFACE_NODE, &no_isis_hello_multiplier_cmd); + install_element(INTERFACE_NODE, &isis_hello_multiplier_l1_cmd); + install_element(INTERFACE_NODE, &no_isis_hello_multiplier_l1_cmd); + install_element(INTERFACE_NODE, &isis_hello_multiplier_l2_cmd); + install_element(INTERFACE_NODE, &no_isis_hello_multiplier_l2_cmd); - install_element (INTERFACE_NODE, &csnp_interval_cmd); - install_element (INTERFACE_NODE, &no_csnp_interval_cmd); - install_element (INTERFACE_NODE, &csnp_interval_l1_cmd); - install_element (INTERFACE_NODE, &no_csnp_interval_l1_cmd); - install_element (INTERFACE_NODE, &csnp_interval_l2_cmd); - install_element (INTERFACE_NODE, &no_csnp_interval_l2_cmd); + install_element(INTERFACE_NODE, &isis_hello_padding_cmd); + install_element(INTERFACE_NODE, &no_isis_hello_padding_cmd); - install_element (INTERFACE_NODE, &psnp_interval_cmd); - install_element (INTERFACE_NODE, &no_psnp_interval_cmd); - install_element (INTERFACE_NODE, &psnp_interval_l1_cmd); - install_element (INTERFACE_NODE, &no_psnp_interval_l1_cmd); - install_element (INTERFACE_NODE, &psnp_interval_l2_cmd); - install_element (INTERFACE_NODE, &no_psnp_interval_l2_cmd); + install_element(INTERFACE_NODE, &csnp_interval_cmd); + install_element(INTERFACE_NODE, &no_csnp_interval_cmd); + install_element(INTERFACE_NODE, &csnp_interval_l1_cmd); + install_element(INTERFACE_NODE, &no_csnp_interval_l1_cmd); + install_element(INTERFACE_NODE, &csnp_interval_l2_cmd); + install_element(INTERFACE_NODE, &no_csnp_interval_l2_cmd); - install_element (INTERFACE_NODE, &circuit_topology_cmd); - install_element (INTERFACE_NODE, &no_circuit_topology_cmd); + install_element(INTERFACE_NODE, &psnp_interval_cmd); + install_element(INTERFACE_NODE, &no_psnp_interval_cmd); + install_element(INTERFACE_NODE, &psnp_interval_l1_cmd); + install_element(INTERFACE_NODE, &no_psnp_interval_l1_cmd); + install_element(INTERFACE_NODE, &psnp_interval_l2_cmd); + install_element(INTERFACE_NODE, &no_psnp_interval_l2_cmd); - install_element (ISIS_NODE, &metric_style_cmd); - install_element (ISIS_NODE, &no_metric_style_cmd); + install_element(INTERFACE_NODE, &circuit_topology_cmd); + install_element(INTERFACE_NODE, &no_circuit_topology_cmd); - install_element (ISIS_NODE, &set_overload_bit_cmd); - install_element (ISIS_NODE, &no_set_overload_bit_cmd); + install_element(ISIS_NODE, &metric_style_cmd); + install_element(ISIS_NODE, &no_metric_style_cmd); - install_element (ISIS_NODE, &set_attached_bit_cmd); - install_element (ISIS_NODE, &no_set_attached_bit_cmd); + install_element(ISIS_NODE, &set_overload_bit_cmd); + install_element(ISIS_NODE, &no_set_overload_bit_cmd); - install_element (ISIS_NODE, &dynamic_hostname_cmd); - install_element (ISIS_NODE, &no_dynamic_hostname_cmd); + install_element(ISIS_NODE, &set_attached_bit_cmd); + install_element(ISIS_NODE, &no_set_attached_bit_cmd); - install_element (ISIS_NODE, &area_lsp_mtu_cmd); - install_element (ISIS_NODE, &no_area_lsp_mtu_cmd); + install_element(ISIS_NODE, &dynamic_hostname_cmd); + install_element(ISIS_NODE, &no_dynamic_hostname_cmd); - install_element (ISIS_NODE, &is_type_cmd); - install_element (ISIS_NODE, &no_is_type_cmd); + install_element(ISIS_NODE, &area_lsp_mtu_cmd); + install_element(ISIS_NODE, &no_area_lsp_mtu_cmd); - install_element (ISIS_NODE, &lsp_gen_interval_cmd); - install_element (ISIS_NODE, &no_lsp_gen_interval_cmd); + install_element(ISIS_NODE, &is_type_cmd); + install_element(ISIS_NODE, &no_is_type_cmd); - install_element (ISIS_NODE, &spf_interval_cmd); - install_element (ISIS_NODE, &no_spf_interval_cmd); - install_element (ISIS_NODE, &spf_interval_l1_cmd); - install_element (ISIS_NODE, &no_spf_interval_l1_cmd); - install_element (ISIS_NODE, &spf_interval_l2_cmd); - install_element (ISIS_NODE, &no_spf_interval_l2_cmd); + install_element(ISIS_NODE, &lsp_gen_interval_cmd); + install_element(ISIS_NODE, &no_lsp_gen_interval_cmd); - install_element (ISIS_NODE, &max_lsp_lifetime_cmd); - install_element (ISIS_NODE, &no_max_lsp_lifetime_cmd); + install_element(ISIS_NODE, &spf_interval_cmd); + install_element(ISIS_NODE, &no_spf_interval_cmd); + install_element(ISIS_NODE, &spf_interval_l1_cmd); + install_element(ISIS_NODE, &no_spf_interval_l1_cmd); + install_element(ISIS_NODE, &spf_interval_l2_cmd); + install_element(ISIS_NODE, &no_spf_interval_l2_cmd); - install_element (ISIS_NODE, &lsp_refresh_interval_cmd); - install_element (ISIS_NODE, &no_lsp_refresh_interval_cmd); - - install_element (ISIS_NODE, &area_passwd_md5_cmd); - install_element (ISIS_NODE, &area_passwd_clear_cmd); - install_element (ISIS_NODE, &domain_passwd_md5_cmd); - install_element (ISIS_NODE, &domain_passwd_clear_cmd); - install_element (ISIS_NODE, &no_area_passwd_cmd); - - install_element (ISIS_NODE, &spf_delay_ietf_cmd); - install_element (ISIS_NODE, &no_spf_delay_ietf_cmd); + install_element(ISIS_NODE, &max_lsp_lifetime_cmd); + install_element(ISIS_NODE, &no_max_lsp_lifetime_cmd); + install_element(ISIS_NODE, &lsp_refresh_interval_cmd); + install_element(ISIS_NODE, &no_lsp_refresh_interval_cmd); + + install_element(ISIS_NODE, &area_passwd_md5_cmd); + install_element(ISIS_NODE, &area_passwd_clear_cmd); + install_element(ISIS_NODE, &domain_passwd_md5_cmd); + install_element(ISIS_NODE, &domain_passwd_clear_cmd); + install_element(ISIS_NODE, &no_area_passwd_cmd); + + install_element(ISIS_NODE, &spf_delay_ietf_cmd); + install_element(ISIS_NODE, &no_spf_delay_ietf_cmd); } diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index af77250a0..18a59d1fc 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -1,19 +1,19 @@ /* - * IS-IS Rout(e)ing protocol - isis_zebra.c + * IS-IS Rout(e)ing protocol - isis_zebra.c * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * Copyright (C) 2013-2015 Christian Franke * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -54,676 +54,655 @@ struct zclient *zclient = NULL; /* Router-id update message from zebra. */ -static int -isis_router_id_update_zebra (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int isis_router_id_update_zebra(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct isis_area *area; - struct listnode *node; - struct prefix router_id; - - /* - * If ISIS TE is enable, TE Router ID is set through specific command. - * See mpls_te_router_addr() command in isis_te.c - */ - if (IS_MPLS_TE(isisMplsTE)) - return 0; - - zebra_router_id_update_read (zclient->ibuf, &router_id); - if (isis->router_id == router_id.u.prefix4.s_addr) - return 0; - - isis->router_id = router_id.u.prefix4.s_addr; - for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area)) - if (listcount (area->area_addrs) > 0) - lsp_regenerate_schedule (area, area->is_type, 0); - - return 0; + struct isis_area *area; + struct listnode *node; + struct prefix router_id; + + /* + * If ISIS TE is enable, TE Router ID is set through specific command. + * See mpls_te_router_addr() command in isis_te.c + */ + if (IS_MPLS_TE(isisMplsTE)) + return 0; + + zebra_router_id_update_read(zclient->ibuf, &router_id); + if (isis->router_id == router_id.u.prefix4.s_addr) + return 0; + + isis->router_id = router_id.u.prefix4.s_addr; + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) + if (listcount(area->area_addrs) > 0) + lsp_regenerate_schedule(area, area->is_type, 0); + + return 0; } -static int -isis_zebra_if_add (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int isis_zebra_if_add(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; + struct interface *ifp; - ifp = zebra_interface_add_read (zclient->ibuf, vrf_id); + ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); - if (isis->debugs & DEBUG_ZEBRA) - zlog_debug ("Zebra I/F add: %s index %d flags %ld metric %d mtu %d", - ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu); + if (isis->debugs & DEBUG_ZEBRA) + zlog_debug( + "Zebra I/F add: %s index %d flags %ld metric %d mtu %d", + ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, + ifp->mtu); - if (if_is_operative (ifp)) - isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp); + if (if_is_operative(ifp)) + isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp), + ifp); - return 0; + return 0; } -static int -isis_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int isis_zebra_if_del(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - struct stream *s; + struct interface *ifp; + struct stream *s; - s = zclient->ibuf; - ifp = zebra_interface_state_read (s, vrf_id); + s = zclient->ibuf; + ifp = zebra_interface_state_read(s, vrf_id); - if (!ifp) - return 0; + if (!ifp) + return 0; - if (if_is_operative (ifp)) - zlog_warn ("Zebra: got delete of %s, but interface is still up", - ifp->name); + if (if_is_operative(ifp)) + zlog_warn("Zebra: got delete of %s, but interface is still up", + ifp->name); - if (isis->debugs & DEBUG_ZEBRA) - zlog_debug ("Zebra I/F delete: %s index %d flags %ld metric %d mtu %d", - ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu); + if (isis->debugs & DEBUG_ZEBRA) + zlog_debug( + "Zebra I/F delete: %s index %d flags %ld metric %d mtu %d", + ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, + ifp->mtu); - isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp); + isis_csm_state_change(IF_DOWN_FROM_Z, circuit_scan_by_ifp(ifp), ifp); - /* Cannot call if_delete because we should retain the pseudo interface - in case there is configuration info attached to it. */ - if_delete_retain(ifp); + /* Cannot call if_delete because we should retain the pseudo interface + in case there is configuration info attached to it. */ + if_delete_retain(ifp); - ifp->ifindex = IFINDEX_DELETED; + ifp->ifindex = IFINDEX_DELETED; - return 0; + return 0; } -static int -isis_zebra_if_state_up (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int isis_zebra_if_state_up(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; + struct interface *ifp; - ifp = zebra_interface_state_read (zclient->ibuf, vrf_id); + ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); - if (ifp == NULL) - return 0; + if (ifp == NULL) + return 0; - isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp); + isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp), ifp); - return 0; + return 0; } -static int -isis_zebra_if_state_down (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int isis_zebra_if_state_down(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - struct isis_circuit *circuit; + struct interface *ifp; + struct isis_circuit *circuit; - ifp = zebra_interface_state_read (zclient->ibuf, vrf_id); + ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); - if (ifp == NULL) - return 0; + if (ifp == NULL) + return 0; - circuit = isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), - ifp); - if (circuit) - SET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF); + circuit = isis_csm_state_change(IF_DOWN_FROM_Z, + circuit_scan_by_ifp(ifp), ifp); + if (circuit) + SET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF); - return 0; + return 0; } -static int -isis_zebra_if_address_add (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int isis_zebra_if_address_add(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct connected *c; - struct prefix *p; - char buf[PREFIX2STR_BUFFER]; + struct connected *c; + struct prefix *p; + char buf[PREFIX2STR_BUFFER]; - c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD, - zclient->ibuf, vrf_id); + c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, + zclient->ibuf, vrf_id); - if (c == NULL) - return 0; + if (c == NULL) + return 0; - p = c->address; + p = c->address; - prefix2str (p, buf, sizeof (buf)); + prefix2str(p, buf, sizeof(buf)); #ifdef EXTREME_DEBUG - if (p->family == AF_INET) - zlog_debug ("connected IP address %s", buf); - if (p->family == AF_INET6) - zlog_debug ("connected IPv6 address %s", buf); + if (p->family == AF_INET) + zlog_debug("connected IP address %s", buf); + if (p->family == AF_INET6) + zlog_debug("connected IPv6 address %s", buf); #endif /* EXTREME_DEBUG */ - if (if_is_operative (c->ifp)) - isis_circuit_add_addr (circuit_scan_by_ifp (c->ifp), c); + if (if_is_operative(c->ifp)) + isis_circuit_add_addr(circuit_scan_by_ifp(c->ifp), c); - return 0; + return 0; } -static int -isis_zebra_if_address_del (int command, struct zclient *client, - zebra_size_t length, vrf_id_t vrf_id) +static int isis_zebra_if_address_del(int command, struct zclient *client, + zebra_size_t length, vrf_id_t vrf_id) { - struct connected *c; - struct interface *ifp; + struct connected *c; + struct interface *ifp; #ifdef EXTREME_DEBUG - struct prefix *p; - char buf[PREFIX2STR_BUFFER]; + struct prefix *p; + char buf[PREFIX2STR_BUFFER]; #endif /* EXTREME_DEBUG */ - c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE, - zclient->ibuf, vrf_id); + c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, + zclient->ibuf, vrf_id); - if (c == NULL) - return 0; + if (c == NULL) + return 0; - ifp = c->ifp; + ifp = c->ifp; #ifdef EXTREME_DEBUG - p = c->address; - prefix2str (p, buf, sizeof (buf)); + p = c->address; + prefix2str(p, buf, sizeof(buf)); - if (p->family == AF_INET) - zlog_debug ("disconnected IP address %s", buf); - if (p->family == AF_INET6) - zlog_debug ("disconnected IPv6 address %s", buf); + if (p->family == AF_INET) + zlog_debug("disconnected IP address %s", buf); + if (p->family == AF_INET6) + zlog_debug("disconnected IPv6 address %s", buf); #endif /* EXTREME_DEBUG */ - if (if_is_operative (ifp)) - isis_circuit_del_addr (circuit_scan_by_ifp (ifp), c); - connected_free (c); + if (if_is_operative(ifp)) + isis_circuit_del_addr(circuit_scan_by_ifp(ifp), c); + connected_free(c); - return 0; + return 0; } -static int -isis_zebra_link_params (int command, struct zclient *zclient, - zebra_size_t length) +static int isis_zebra_link_params(int command, struct zclient *zclient, + zebra_size_t length) { - struct interface *ifp; + struct interface *ifp; - ifp = zebra_interface_link_params_read (zclient->ibuf); + ifp = zebra_interface_link_params_read(zclient->ibuf); - if (ifp == NULL) - return 0; + if (ifp == NULL) + return 0; - /* Update TE TLV */ - isis_mpls_te_update(ifp); + /* Update TE TLV */ + isis_mpls_te_update(ifp); - return 0; + return 0; } -static void -isis_zebra_route_add_ipv4 (struct prefix *prefix, - struct isis_route_info *route_info) +static void isis_zebra_route_add_ipv4(struct prefix *prefix, + struct isis_route_info *route_info) { - u_char message; - u_int32_t flags; - int psize; - struct stream *stream; - struct isis_nexthop *nexthop; - struct listnode *node; - - if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) - return; - - if (vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], VRF_DEFAULT)) - { - message = 0; - flags = 0; - - SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG (message, ZAPI_MESSAGE_METRIC); + u_char message; + u_int32_t flags; + int psize; + struct stream *stream; + struct isis_nexthop *nexthop; + struct listnode *node; + + if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) + return; + + if (vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], + VRF_DEFAULT)) { + message = 0; + flags = 0; + + SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP); + SET_FLAG(message, ZAPI_MESSAGE_METRIC); #if 0 SET_FLAG (message, ZAPI_MESSAGE_DISTANCE); #endif - stream = zclient->obuf; - stream_reset (stream); - zclient_create_header (stream, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT); - /* type */ - stream_putc (stream, ZEBRA_ROUTE_ISIS); - /* instance */ - stream_putw (stream, 0); - /* flags */ - stream_putl (stream, flags); - /* message */ - stream_putc (stream, message); - /* SAFI */ - stream_putw (stream, SAFI_UNICAST); - /* prefix information */ - psize = PSIZE (prefix->prefixlen); - stream_putc (stream, prefix->prefixlen); - stream_write (stream, (u_char *) & prefix->u.prefix4, psize); - - stream_putc (stream, listcount (route_info->nexthops)); - - /* Nexthop, ifindex, distance and metric information */ - for (ALL_LIST_ELEMENTS_RO (route_info->nexthops, node, nexthop)) - { - /* FIXME: can it be ? */ - if (nexthop->ip.s_addr != INADDR_ANY) - { - stream_putc (stream, NEXTHOP_TYPE_IPV4_IFINDEX); - stream_put_in_addr (stream, &nexthop->ip); - stream_putl (stream, nexthop->ifindex); - } - else - { - stream_putc (stream, NEXTHOP_TYPE_IFINDEX); - stream_putl (stream, nexthop->ifindex); - } - } + stream = zclient->obuf; + stream_reset(stream); + zclient_create_header(stream, ZEBRA_IPV4_ROUTE_ADD, + VRF_DEFAULT); + /* type */ + stream_putc(stream, ZEBRA_ROUTE_ISIS); + /* instance */ + stream_putw(stream, 0); + /* flags */ + stream_putl(stream, flags); + /* message */ + stream_putc(stream, message); + /* SAFI */ + stream_putw(stream, SAFI_UNICAST); + /* prefix information */ + psize = PSIZE(prefix->prefixlen); + stream_putc(stream, prefix->prefixlen); + stream_write(stream, (u_char *)&prefix->u.prefix4, psize); + + stream_putc(stream, listcount(route_info->nexthops)); + + /* Nexthop, ifindex, distance and metric information */ + for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node, + nexthop)) { + /* FIXME: can it be ? */ + if (nexthop->ip.s_addr != INADDR_ANY) { + stream_putc(stream, NEXTHOP_TYPE_IPV4_IFINDEX); + stream_put_in_addr(stream, &nexthop->ip); + stream_putl(stream, nexthop->ifindex); + } else { + stream_putc(stream, NEXTHOP_TYPE_IFINDEX); + stream_putl(stream, nexthop->ifindex); + } + } #if 0 if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) stream_putc (stream, route_info->depth); #endif - if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) - stream_putl (stream, route_info->cost); - - stream_putw_at (stream, 0, stream_get_endp (stream)); - zclient_send_message(zclient); - SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); - UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC); - } + if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) + stream_putl(stream, route_info->cost); + + stream_putw_at(stream, 0, stream_get_endp(stream)); + zclient_send_message(zclient); + SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); + UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC); + } } -static void -isis_zebra_route_del_ipv4 (struct prefix *prefix, - struct isis_route_info *route_info) +static void isis_zebra_route_del_ipv4(struct prefix *prefix, + struct isis_route_info *route_info) { - struct zapi_ipv4 api; - struct prefix_ipv4 prefix4; - - if (vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], VRF_DEFAULT)) - { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_ISIS; - api.instance = 0; - api.flags = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - prefix4.family = AF_INET; - prefix4.prefixlen = prefix->prefixlen; - prefix4.prefix = prefix->u.prefix4; - zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, &prefix4, &api); - } - UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); - - return; + struct zapi_ipv4 api; + struct prefix_ipv4 prefix4; + + if (vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], + VRF_DEFAULT)) { + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_ISIS; + api.instance = 0; + api.flags = 0; + api.message = 0; + api.safi = SAFI_UNICAST; + prefix4.family = AF_INET; + prefix4.prefixlen = prefix->prefixlen; + prefix4.prefix = prefix->u.prefix4; + zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, &prefix4, + &api); + } + UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); + + return; } -static void -isis_zebra_route_add_ipv6 (struct prefix *prefix, - struct isis_route_info *route_info) +static void isis_zebra_route_add_ipv6(struct prefix *prefix, + struct isis_route_info *route_info) { - struct zapi_ipv6 api; - struct in6_addr **nexthop_list; - ifindex_t *ifindex_list; - struct isis_nexthop6 *nexthop6; - int i, size; - struct listnode *node; - struct prefix_ipv6 prefix6; - - if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) - return; - - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_ISIS; - api.instance = 0; - api.flags = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); - SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); - api.metric = route_info->cost; + struct zapi_ipv6 api; + struct in6_addr **nexthop_list; + ifindex_t *ifindex_list; + struct isis_nexthop6 *nexthop6; + int i, size; + struct listnode *node; + struct prefix_ipv6 prefix6; + + if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) + return; + + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_ISIS; + api.instance = 0; + api.flags = 0; + api.message = 0; + api.safi = SAFI_UNICAST; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = route_info->cost; #if 0 SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); api.distance = route_info->depth; #endif - api.nexthop_num = listcount (route_info->nexthops6); - api.ifindex_num = listcount (route_info->nexthops6); - - /* allocate memory for nexthop_list */ - size = sizeof (struct isis_nexthop6 *) * listcount (route_info->nexthops6); - nexthop_list = (struct in6_addr **) XMALLOC (MTYPE_ISIS_TMP, size); - if (!nexthop_list) - { - zlog_err ("isis_zebra_add_route_ipv6: out of memory!"); - return; - } - - /* allocate memory for ifindex_list */ - size = sizeof (unsigned int) * listcount (route_info->nexthops6); - ifindex_list = (ifindex_t *) XMALLOC (MTYPE_ISIS_TMP, size); - if (!ifindex_list) - { - zlog_err ("isis_zebra_add_route_ipv6: out of memory!"); - XFREE (MTYPE_ISIS_TMP, nexthop_list); - return; - } - - /* for each nexthop */ - i = 0; - for (ALL_LIST_ELEMENTS_RO (route_info->nexthops6, node, nexthop6)) - { - if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) && - !IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6)) - { - api.nexthop_num--; - api.ifindex_num--; - continue; + api.nexthop_num = listcount(route_info->nexthops6); + api.ifindex_num = listcount(route_info->nexthops6); + + /* allocate memory for nexthop_list */ + size = sizeof(struct isis_nexthop6 *) + * listcount(route_info->nexthops6); + nexthop_list = (struct in6_addr **)XMALLOC(MTYPE_ISIS_TMP, size); + if (!nexthop_list) { + zlog_err("isis_zebra_add_route_ipv6: out of memory!"); + return; } - nexthop_list[i] = &nexthop6->ip6; - ifindex_list[i] = nexthop6->ifindex; - i++; - } + /* allocate memory for ifindex_list */ + size = sizeof(unsigned int) * listcount(route_info->nexthops6); + ifindex_list = (ifindex_t *)XMALLOC(MTYPE_ISIS_TMP, size); + if (!ifindex_list) { + zlog_err("isis_zebra_add_route_ipv6: out of memory!"); + XFREE(MTYPE_ISIS_TMP, nexthop_list); + return; + } - api.nexthop = nexthop_list; - api.ifindex = ifindex_list; + /* for each nexthop */ + i = 0; + for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node, nexthop6)) { + if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6) + && !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) { + api.nexthop_num--; + api.ifindex_num--; + continue; + } + + nexthop_list[i] = &nexthop6->ip6; + ifindex_list[i] = nexthop6->ifindex; + i++; + } - if (api.nexthop_num && api.ifindex_num) - { - prefix6.family = AF_INET6; - prefix6.prefixlen = prefix->prefixlen; - memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr)); - zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, &prefix6, NULL, &api); - SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); - UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC); - } + api.nexthop = nexthop_list; + api.ifindex = ifindex_list; + + if (api.nexthop_num && api.ifindex_num) { + prefix6.family = AF_INET6; + prefix6.prefixlen = prefix->prefixlen; + memcpy(&prefix6.prefix, &prefix->u.prefix6, + sizeof(struct in6_addr)); + zapi_ipv6_route(ZEBRA_IPV6_ROUTE_ADD, zclient, &prefix6, NULL, + &api); + SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); + UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC); + } - XFREE (MTYPE_ISIS_TMP, nexthop_list); - XFREE (MTYPE_ISIS_TMP, ifindex_list); + XFREE(MTYPE_ISIS_TMP, nexthop_list); + XFREE(MTYPE_ISIS_TMP, ifindex_list); - return; + return; } -static void -isis_zebra_route_del_ipv6 (struct prefix *prefix, - struct isis_route_info *route_info) +static void isis_zebra_route_del_ipv6(struct prefix *prefix, + struct isis_route_info *route_info) { - struct zapi_ipv6 api; - struct in6_addr **nexthop_list; - ifindex_t *ifindex_list; - struct isis_nexthop6 *nexthop6; - int i, size; - struct listnode *node; - struct prefix_ipv6 prefix6; - - if (!CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) - return; - - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_ISIS; - api.instance = 0; - api.flags = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); - api.nexthop_num = listcount (route_info->nexthops6); - api.ifindex_num = listcount (route_info->nexthops6); - - /* allocate memory for nexthop_list */ - size = sizeof (struct isis_nexthop6 *) * listcount (route_info->nexthops6); - nexthop_list = (struct in6_addr **) XMALLOC (MTYPE_ISIS_TMP, size); - if (!nexthop_list) - { - zlog_err ("isis_zebra_route_del_ipv6: out of memory!"); - return; - } - - /* allocate memory for ifindex_list */ - size = sizeof (unsigned int) * listcount (route_info->nexthops6); - ifindex_list = (ifindex_t *) XMALLOC (MTYPE_ISIS_TMP, size); - if (!ifindex_list) - { - zlog_err ("isis_zebra_route_del_ipv6: out of memory!"); - XFREE (MTYPE_ISIS_TMP, nexthop_list); - return; - } - - /* for each nexthop */ - i = 0; - for (ALL_LIST_ELEMENTS_RO (route_info->nexthops6, node, nexthop6)) - { - if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) && - !IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6)) - { - api.nexthop_num--; - api.ifindex_num--; - continue; + struct zapi_ipv6 api; + struct in6_addr **nexthop_list; + ifindex_t *ifindex_list; + struct isis_nexthop6 *nexthop6; + int i, size; + struct listnode *node; + struct prefix_ipv6 prefix6; + + if (!CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED)) + return; + + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_ISIS; + api.instance = 0; + api.flags = 0; + api.message = 0; + api.safi = SAFI_UNICAST; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); + api.nexthop_num = listcount(route_info->nexthops6); + api.ifindex_num = listcount(route_info->nexthops6); + + /* allocate memory for nexthop_list */ + size = sizeof(struct isis_nexthop6 *) + * listcount(route_info->nexthops6); + nexthop_list = (struct in6_addr **)XMALLOC(MTYPE_ISIS_TMP, size); + if (!nexthop_list) { + zlog_err("isis_zebra_route_del_ipv6: out of memory!"); + return; + } + + /* allocate memory for ifindex_list */ + size = sizeof(unsigned int) * listcount(route_info->nexthops6); + ifindex_list = (ifindex_t *)XMALLOC(MTYPE_ISIS_TMP, size); + if (!ifindex_list) { + zlog_err("isis_zebra_route_del_ipv6: out of memory!"); + XFREE(MTYPE_ISIS_TMP, nexthop_list); + return; } - nexthop_list[i] = &nexthop6->ip6; - ifindex_list[i] = nexthop6->ifindex; - i++; - } - - api.nexthop = nexthop_list; - api.ifindex = ifindex_list; - - if (api.nexthop_num && api.ifindex_num) - { - prefix6.family = AF_INET6; - prefix6.prefixlen = prefix->prefixlen; - memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr)); - zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, &prefix6, NULL, &api); - UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); - } - - XFREE (MTYPE_ISIS_TMP, nexthop_list); - XFREE (MTYPE_ISIS_TMP, ifindex_list); + /* for each nexthop */ + i = 0; + for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node, nexthop6)) { + if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6) + && !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) { + api.nexthop_num--; + api.ifindex_num--; + continue; + } + + nexthop_list[i] = &nexthop6->ip6; + ifindex_list[i] = nexthop6->ifindex; + i++; + } + + api.nexthop = nexthop_list; + api.ifindex = ifindex_list; + + if (api.nexthop_num && api.ifindex_num) { + prefix6.family = AF_INET6; + prefix6.prefixlen = prefix->prefixlen; + memcpy(&prefix6.prefix, &prefix->u.prefix6, + sizeof(struct in6_addr)); + zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, &prefix6, + NULL, &api); + UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED); + } + + XFREE(MTYPE_ISIS_TMP, nexthop_list); + XFREE(MTYPE_ISIS_TMP, ifindex_list); } -void -isis_zebra_route_update (struct prefix *prefix, - struct isis_route_info *route_info) +void isis_zebra_route_update(struct prefix *prefix, + struct isis_route_info *route_info) { - if (zclient->sock < 0) - return; - - if ((prefix->family == AF_INET && !vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], VRF_DEFAULT)) || - (prefix->family == AF_INET6 && !vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_ISIS], VRF_DEFAULT))) - return; - - if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE)) - { - if (prefix->family == AF_INET) - isis_zebra_route_add_ipv4 (prefix, route_info); - else if (prefix->family == AF_INET6) - isis_zebra_route_add_ipv6 (prefix, route_info); - } - else - { - if (prefix->family == AF_INET) - isis_zebra_route_del_ipv4 (prefix, route_info); - else if (prefix->family == AF_INET6) - isis_zebra_route_del_ipv6 (prefix, route_info); - } - return; + if (zclient->sock < 0) + return; + + if ((prefix->family == AF_INET + && !vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], + VRF_DEFAULT)) + || (prefix->family == AF_INET6 + && !vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_ISIS], + VRF_DEFAULT))) + return; + + if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE)) { + if (prefix->family == AF_INET) + isis_zebra_route_add_ipv4(prefix, route_info); + else if (prefix->family == AF_INET6) + isis_zebra_route_add_ipv6(prefix, route_info); + } else { + if (prefix->family == AF_INET) + isis_zebra_route_del_ipv4(prefix, route_info); + else if (prefix->family == AF_INET6) + isis_zebra_route_del_ipv6(prefix, route_info); + } + return; } -static int -isis_zebra_read_ipv4 (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int isis_zebra_read_ipv4(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *stream; - struct zapi_ipv4 api; - struct prefix_ipv4 p; - struct prefix *p_generic = (struct prefix*)&p; - - stream = zclient->ibuf; - memset(&api, 0, sizeof(api)); - memset (&p, 0, sizeof (struct prefix_ipv4)); - - api.type = stream_getc (stream); - api.instance = stream_getw (stream); - api.flags = stream_getl (stream); - api.message = stream_getc (stream); - - p.family = AF_INET; - p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc (stream)); - stream_get (&p.prefix, stream, PSIZE (p.prefixlen)); - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) - { - api.nexthop_num = stream_getc (stream); - (void)stream_get_ipv4 (stream); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) - { - api.ifindex_num = stream_getc (stream); - stream_getl (stream); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc (stream); - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl (stream); - - /* - * Avoid advertising a false default reachability. (A default - * route installed by IS-IS gets redistributed from zebra back - * into IS-IS causing us to start advertising default reachabity - * without this check) - */ - if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS) - command = ZEBRA_IPV4_ROUTE_DELETE; - - if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) - isis_redist_add(api.type, p_generic, api.distance, api.metric); - else - isis_redist_delete(api.type, p_generic); - - return 0; + struct stream *stream; + struct zapi_ipv4 api; + struct prefix_ipv4 p; + struct prefix *p_generic = (struct prefix *)&p; + + stream = zclient->ibuf; + memset(&api, 0, sizeof(api)); + memset(&p, 0, sizeof(struct prefix_ipv4)); + + api.type = stream_getc(stream); + api.instance = stream_getw(stream); + api.flags = stream_getl(stream); + api.message = stream_getc(stream); + + p.family = AF_INET; + p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(stream)); + stream_get(&p.prefix, stream, PSIZE(p.prefixlen)); + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { + api.nexthop_num = stream_getc(stream); + (void)stream_get_ipv4(stream); + } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { + api.ifindex_num = stream_getc(stream); + stream_getl(stream); + } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) + api.distance = stream_getc(stream); + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) + api.metric = stream_getl(stream); + + /* + * Avoid advertising a false default reachability. (A default + * route installed by IS-IS gets redistributed from zebra back + * into IS-IS causing us to start advertising default reachabity + * without this check) + */ + if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS) + command = ZEBRA_IPV4_ROUTE_DELETE; + + if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) + isis_redist_add(api.type, p_generic, api.distance, api.metric); + else + isis_redist_delete(api.type, p_generic); + + return 0; } -static int -isis_zebra_read_ipv6 (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int isis_zebra_read_ipv6(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *stream; - struct zapi_ipv6 api; - struct prefix_ipv6 p; - struct prefix src_p; - struct prefix *p_generic = (struct prefix*)&p; - struct in6_addr nexthop; - unsigned long ifindex __attribute__((unused)); - - stream = zclient->ibuf; - memset(&api, 0, sizeof(api)); - memset(&p, 0, sizeof(struct prefix_ipv6)); - memset(&nexthop, 0, sizeof(nexthop)); - ifindex = 0; - - api.type = stream_getc(stream); - api.instance = stream_getw(stream); - api.flags = stream_getl(stream); - api.message = stream_getc(stream); - - p.family = AF_INET6; - p.prefixlen = stream_getc(stream); - stream_get(&p.prefix, stream, PSIZE(p.prefixlen)); - - memset(&src_p, 0, sizeof (struct prefix)); - src_p.family = AF_INET6; - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) - { - src_p.prefixlen = stream_getc(stream); - stream_get(&src_p.u.prefix6, stream, PSIZE (src_p.prefixlen)); - } - - if (src_p.prefixlen) - /* we completely ignore srcdest routes for now. */ - return 0; - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) - { - api.nexthop_num = stream_getc(stream); /* this is always 1 */ - stream_get(&nexthop, stream, sizeof(nexthop)); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) - { - api.ifindex_num = stream_getc(stream); - ifindex = stream_getl(stream); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc(stream); - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl(stream); - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl(stream); - - /* - * Avoid advertising a false default reachability. (A default - * route installed by IS-IS gets redistributed from zebra back - * into IS-IS causing us to start advertising default reachabity - * without this check) - */ - if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS) - command = ZEBRA_IPV6_ROUTE_DELETE; - - if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) - isis_redist_add(api.type, p_generic, api.distance, api.metric); - else - isis_redist_delete(api.type, p_generic); - - return 0; + struct stream *stream; + struct zapi_ipv6 api; + struct prefix_ipv6 p; + struct prefix src_p; + struct prefix *p_generic = (struct prefix *)&p; + struct in6_addr nexthop; + unsigned long ifindex __attribute__((unused)); + + stream = zclient->ibuf; + memset(&api, 0, sizeof(api)); + memset(&p, 0, sizeof(struct prefix_ipv6)); + memset(&nexthop, 0, sizeof(nexthop)); + ifindex = 0; + + api.type = stream_getc(stream); + api.instance = stream_getw(stream); + api.flags = stream_getl(stream); + api.message = stream_getc(stream); + + p.family = AF_INET6; + p.prefixlen = stream_getc(stream); + stream_get(&p.prefix, stream, PSIZE(p.prefixlen)); + + memset(&src_p, 0, sizeof(struct prefix)); + src_p.family = AF_INET6; + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { + src_p.prefixlen = stream_getc(stream); + stream_get(&src_p.u.prefix6, stream, PSIZE(src_p.prefixlen)); + } + + if (src_p.prefixlen) + /* we completely ignore srcdest routes for now. */ + return 0; + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { + api.nexthop_num = stream_getc(stream); /* this is always 1 */ + stream_get(&nexthop, stream, sizeof(nexthop)); + } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { + api.ifindex_num = stream_getc(stream); + ifindex = stream_getl(stream); + } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) + api.distance = stream_getc(stream); + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) + api.metric = stream_getl(stream); + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getl(stream); + + /* + * Avoid advertising a false default reachability. (A default + * route installed by IS-IS gets redistributed from zebra back + * into IS-IS causing us to start advertising default reachabity + * without this check) + */ + if (p.prefixlen == 0 && api.type == ZEBRA_ROUTE_ISIS) + command = ZEBRA_IPV6_ROUTE_DELETE; + + if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) + isis_redist_add(api.type, p_generic, api.distance, api.metric); + else + isis_redist_delete(api.type, p_generic); + + return 0; } -int -isis_distribute_list_update (int routetype) +int isis_distribute_list_update(int routetype) { - return 0; + return 0; } -void -isis_zebra_redistribute_set(afi_t afi, int type) +void isis_zebra_redistribute_set(afi_t afi, int type) { - if (type == DEFAULT_ROUTE) - zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, VRF_DEFAULT); - else - zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type, 0, VRF_DEFAULT); + if (type == DEFAULT_ROUTE) + zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, + zclient, VRF_DEFAULT); + else + zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type, + 0, VRF_DEFAULT); } -void -isis_zebra_redistribute_unset(afi_t afi, int type) +void isis_zebra_redistribute_unset(afi_t afi, int type) { - if (type == DEFAULT_ROUTE) - zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient, VRF_DEFAULT); - else - zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, type, 0, VRF_DEFAULT); + if (type == DEFAULT_ROUTE) + zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, + zclient, VRF_DEFAULT); + else + zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, + type, 0, VRF_DEFAULT); } -static void -isis_zebra_connected (struct zclient *zclient) +static void isis_zebra_connected(struct zclient *zclient) { - zclient_send_reg_requests (zclient, VRF_DEFAULT); + zclient_send_reg_requests(zclient, VRF_DEFAULT); } -void -isis_zebra_init (struct thread_master *master) +void isis_zebra_init(struct thread_master *master) { - zclient = zclient_new (master); - zclient_init (zclient, ZEBRA_ROUTE_ISIS, 0); - zclient->zebra_connected = isis_zebra_connected; - zclient->router_id_update = isis_router_id_update_zebra; - zclient->interface_add = isis_zebra_if_add; - zclient->interface_delete = isis_zebra_if_del; - zclient->interface_up = isis_zebra_if_state_up; - zclient->interface_down = isis_zebra_if_state_down; - zclient->interface_address_add = isis_zebra_if_address_add; - zclient->interface_address_delete = isis_zebra_if_address_del; - zclient->interface_link_params = isis_zebra_link_params; - zclient->redistribute_route_ipv4_add = isis_zebra_read_ipv4; - zclient->redistribute_route_ipv4_del = isis_zebra_read_ipv4; - zclient->redistribute_route_ipv6_add = isis_zebra_read_ipv6; - zclient->redistribute_route_ipv6_del = isis_zebra_read_ipv6; - - return; + zclient = zclient_new(master); + zclient_init(zclient, ZEBRA_ROUTE_ISIS, 0); + zclient->zebra_connected = isis_zebra_connected; + zclient->router_id_update = isis_router_id_update_zebra; + zclient->interface_add = isis_zebra_if_add; + zclient->interface_delete = isis_zebra_if_del; + zclient->interface_up = isis_zebra_if_state_up; + zclient->interface_down = isis_zebra_if_state_down; + zclient->interface_address_add = isis_zebra_if_address_add; + zclient->interface_address_delete = isis_zebra_if_address_del; + zclient->interface_link_params = isis_zebra_link_params; + zclient->redistribute_route_ipv4_add = isis_zebra_read_ipv4; + zclient->redistribute_route_ipv4_del = isis_zebra_read_ipv4; + zclient->redistribute_route_ipv6_add = isis_zebra_read_ipv6; + zclient->redistribute_route_ipv6_del = isis_zebra_read_ipv6; + + return; } -void -isis_zebra_stop (void) +void isis_zebra_stop(void) { - zclient_stop (zclient); - zclient_free (zclient); + zclient_stop(zclient); + zclient_free(zclient); } diff --git a/isisd/isis_zebra.h b/isisd/isis_zebra.h index 82d5a48d3..bd7bf2b5c 100644 --- a/isisd/isis_zebra.h +++ b/isisd/isis_zebra.h @@ -1,18 +1,18 @@ /* - * IS-IS Rout(e)ing protocol - isis_zebra.h + * IS-IS Rout(e)ing protocol - isis_zebra.h * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -27,9 +27,9 @@ extern struct zclient *zclient; void isis_zebra_init(struct thread_master *); void isis_zebra_stop(void); -void isis_zebra_route_update (struct prefix *prefix, - struct isis_route_info *route_info); -int isis_distribute_list_update (int routetype); +void isis_zebra_route_update(struct prefix *prefix, + struct isis_route_info *route_info); +int isis_distribute_list_update(int routetype); void isis_zebra_redistribute_set(afi_t afi, int type); void isis_zebra_redistribute_unset(afi_t afi, int type); diff --git a/isisd/isisd.c b/isisd/isisd.c index 473b6594e..8bbb5cf94 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -2,17 +2,17 @@ * IS-IS Rout(e)ing protocol - isisd.c * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -76,442 +76,412 @@ int clear_isis_neighbor_common(struct vty *, const char *id); int isis_config_write(struct vty *); +void isis_new(unsigned long process_id) +{ + isis = XCALLOC(MTYPE_ISIS, sizeof(struct isis)); + /* + * Default values + */ + isis->max_area_addrs = 3; + isis->process_id = process_id; + isis->router_id = 0; + isis->area_list = list_new(); + isis->init_circ_list = list_new(); + isis->uptime = time(NULL); + isis->nexthops = list_new(); + isis->nexthops6 = list_new(); + dyn_cache_init(); + /* + * uncomment the next line for full debugs + */ + /* isis->debugs = 0xFFFF; */ + isisMplsTE.status = disable; /* Only support TE metric */ + QOBJ_REG(isis, isis); +} + +struct isis_area *isis_area_create(const char *area_tag) +{ + struct isis_area *area; + + area = XCALLOC(MTYPE_ISIS_AREA, sizeof(struct isis_area)); + + /* + * The first instance is level-1-2 rest are level-1, unless otherwise + * configured + */ + if (listcount(isis->area_list) > 0) + area->is_type = IS_LEVEL_1; + else + area->is_type = IS_LEVEL_1_AND_2; + + /* + * intialize the databases + */ + if (area->is_type & IS_LEVEL_1) { + area->lspdb[0] = lsp_db_init(); + area->route_table[0] = route_table_init(); + area->route_table6[0] = route_table_init(); + } + if (area->is_type & IS_LEVEL_2) { + area->lspdb[1] = lsp_db_init(); + area->route_table[1] = route_table_init(); + area->route_table6[1] = route_table_init(); + } + + spftree_area_init(area); + + area->circuit_list = list_new(); + area->area_addrs = list_new(); + thread_add_timer(master, lsp_tick, area, 1, &area->t_tick); + flags_initialize(&area->flags); + + /* + * Default values + */ + area->max_lsp_lifetime[0] = DEFAULT_LSP_LIFETIME; /* 1200 */ + area->max_lsp_lifetime[1] = DEFAULT_LSP_LIFETIME; /* 1200 */ + area->lsp_refresh[0] = DEFAULT_MAX_LSP_GEN_INTERVAL; /* 900 */ + area->lsp_refresh[1] = DEFAULT_MAX_LSP_GEN_INTERVAL; /* 900 */ + area->lsp_gen_interval[0] = DEFAULT_MIN_LSP_GEN_INTERVAL; + area->lsp_gen_interval[1] = DEFAULT_MIN_LSP_GEN_INTERVAL; + area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL; + area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL; + area->dynhostname = 1; + area->oldmetric = 0; + area->newmetric = 1; + area->lsp_frag_threshold = 90; + area->lsp_mtu = DEFAULT_LSP_MTU; + + area_mt_init(area); -void -isis_new (unsigned long process_id) -{ - isis = XCALLOC (MTYPE_ISIS, sizeof (struct isis)); - /* - * Default values - */ - isis->max_area_addrs = 3; - isis->process_id = process_id; - isis->router_id = 0; - isis->area_list = list_new (); - isis->init_circ_list = list_new (); - isis->uptime = time (NULL); - isis->nexthops = list_new (); - isis->nexthops6 = list_new (); - dyn_cache_init (); - /* - * uncomment the next line for full debugs - */ - /* isis->debugs = 0xFFFF; */ - isisMplsTE.status = disable; /* Only support TE metric */ - QOBJ_REG (isis, isis); -} - -struct isis_area * -isis_area_create (const char *area_tag) -{ - struct isis_area *area; + area->area_tag = strdup(area_tag); + listnode_add(isis->area_list, area); + area->isis = isis; - area = XCALLOC (MTYPE_ISIS_AREA, sizeof (struct isis_area)); + QOBJ_REG(area, isis_area); - /* - * The first instance is level-1-2 rest are level-1, unless otherwise - * configured - */ - if (listcount (isis->area_list) > 0) - area->is_type = IS_LEVEL_1; - else - area->is_type = IS_LEVEL_1_AND_2; + return area; +} - /* - * intialize the databases - */ - if (area->is_type & IS_LEVEL_1) - { - area->lspdb[0] = lsp_db_init (); - area->route_table[0] = route_table_init (); - area->route_table6[0] = route_table_init (); - } - if (area->is_type & IS_LEVEL_2) - { - area->lspdb[1] = lsp_db_init (); - area->route_table[1] = route_table_init (); - area->route_table6[1] = route_table_init (); - } - - spftree_area_init (area); - - area->circuit_list = list_new (); - area->area_addrs = list_new (); - thread_add_timer(master, lsp_tick, area, 1, &area->t_tick); - flags_initialize (&area->flags); - - /* - * Default values - */ - area->max_lsp_lifetime[0] = DEFAULT_LSP_LIFETIME; /* 1200 */ - area->max_lsp_lifetime[1] = DEFAULT_LSP_LIFETIME; /* 1200 */ - area->lsp_refresh[0] = DEFAULT_MAX_LSP_GEN_INTERVAL; /* 900 */ - area->lsp_refresh[1] = DEFAULT_MAX_LSP_GEN_INTERVAL; /* 900 */ - area->lsp_gen_interval[0] = DEFAULT_MIN_LSP_GEN_INTERVAL; - area->lsp_gen_interval[1] = DEFAULT_MIN_LSP_GEN_INTERVAL; - area->min_spf_interval[0] = MINIMUM_SPF_INTERVAL; - area->min_spf_interval[1] = MINIMUM_SPF_INTERVAL; - area->dynhostname = 1; - area->oldmetric = 0; - area->newmetric = 1; - area->lsp_frag_threshold = 90; - area->lsp_mtu = DEFAULT_LSP_MTU; - - area_mt_init(area); - - area->area_tag = strdup (area_tag); - listnode_add (isis->area_list, area); - area->isis = isis; - - QOBJ_REG (area, isis_area); - - return area; -} - -struct isis_area * -isis_area_lookup (const char *area_tag) -{ - struct isis_area *area; - struct listnode *node; - - for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area)) - if ((area->area_tag == NULL && area_tag == NULL) || - (area->area_tag && area_tag - && strcmp (area->area_tag, area_tag) == 0)) - return area; - - return NULL; -} - -int -isis_area_get (struct vty *vty, const char *area_tag) -{ - struct isis_area *area; - - area = isis_area_lookup (area_tag); - - if (area) - { - VTY_PUSH_CONTEXT (ISIS_NODE, area); - return CMD_SUCCESS; - } - - area = isis_area_create (area_tag); - - if (isis->debugs & DEBUG_EVENTS) - zlog_debug ("New IS-IS area instance %s", area->area_tag); - - VTY_PUSH_CONTEXT (ISIS_NODE, area); - - return CMD_SUCCESS; -} - -int -isis_area_destroy (struct vty *vty, const char *area_tag) -{ - struct isis_area *area; - struct listnode *node, *nnode; - struct isis_circuit *circuit; - struct area_addr *addr; - - area = isis_area_lookup (area_tag); - - if (area == NULL) - { - vty_out (vty, "Can't find ISIS instance \n"); - return CMD_ERR_NO_MATCH; - } - - QOBJ_UNREG (area); - - if (area->circuit_list) - { - for (ALL_LIST_ELEMENTS (area->circuit_list, node, nnode, circuit)) - { - circuit->ip_router = 0; - circuit->ipv6_router = 0; - isis_csm_state_change (ISIS_DISABLE, circuit, area); - } - list_delete (area->circuit_list); - area->circuit_list = NULL; - } +struct isis_area *isis_area_lookup(const char *area_tag) +{ + struct isis_area *area; + struct listnode *node; - if (area->lspdb[0] != NULL) - { - lsp_db_destroy (area->lspdb[0]); - area->lspdb[0] = NULL; - } - if (area->lspdb[1] != NULL) - { - lsp_db_destroy (area->lspdb[1]); - area->lspdb[1] = NULL; - } + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) + if ((area->area_tag == NULL && area_tag == NULL) + || (area->area_tag && area_tag + && strcmp(area->area_tag, area_tag) == 0)) + return area; - spftree_area_del (area); + return NULL; +} - THREAD_TIMER_OFF(area->spf_timer[0]); - THREAD_TIMER_OFF(area->spf_timer[1]); +int isis_area_get(struct vty *vty, const char *area_tag) +{ + struct isis_area *area; - spf_backoff_free(area->spf_delay_ietf[0]); - spf_backoff_free(area->spf_delay_ietf[1]); + area = isis_area_lookup(area_tag); - /* invalidate and validate would delete all routes from zebra */ - isis_route_invalidate (area); - isis_route_validate (area); + if (area) { + VTY_PUSH_CONTEXT(ISIS_NODE, area); + return CMD_SUCCESS; + } + + area = isis_area_create(area_tag); - if (area->route_table[0]) - { - route_table_finish (area->route_table[0]); - area->route_table[0] = NULL; - } - if (area->route_table[1]) - { - route_table_finish (area->route_table[1]); - area->route_table[1] = NULL; - } - if (area->route_table6[0]) - { - route_table_finish (area->route_table6[0]); - area->route_table6[0] = NULL; - } - if (area->route_table6[1]) - { - route_table_finish (area->route_table6[1]); - area->route_table6[1] = NULL; - } + if (isis->debugs & DEBUG_EVENTS) + zlog_debug("New IS-IS area instance %s", area->area_tag); - isis_redist_area_finish(area); + VTY_PUSH_CONTEXT(ISIS_NODE, area); - for (ALL_LIST_ELEMENTS (area->area_addrs, node, nnode, addr)) - { - list_delete_node (area->area_addrs, node); - XFREE (MTYPE_ISIS_AREA_ADDR, addr); - } - area->area_addrs = NULL; - - THREAD_TIMER_OFF (area->t_tick); - THREAD_TIMER_OFF (area->t_lsp_refresh[0]); - THREAD_TIMER_OFF (area->t_lsp_refresh[1]); - - thread_cancel_event (master, area); + return CMD_SUCCESS; +} - listnode_delete (isis->area_list, area); - - free (area->area_tag); - - area_mt_finish(area); - - XFREE (MTYPE_ISIS_AREA, area); - - if (listcount (isis->area_list) == 0) - { - memset (isis->sysid, 0, ISIS_SYS_ID_LEN); - isis->sysid_set = 0; - } - - return CMD_SUCCESS; -} - -static void -area_set_mt_enabled(struct isis_area *area, uint16_t mtid, bool enabled) -{ - struct isis_area_mt_setting *setting; - - setting = area_get_mt_setting(area, mtid); - if (setting->enabled != enabled) - { - setting->enabled = enabled; - lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 0); - } -} - -static void -area_set_mt_overload(struct isis_area *area, uint16_t mtid, bool overload) -{ - struct isis_area_mt_setting *setting; - - setting = area_get_mt_setting(area, mtid); - if (setting->overload != overload) - { - setting->overload = overload; - if (setting->enabled) - lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 0); - } -} - -int -area_net_title (struct vty *vty, const char *net_title) +int isis_area_destroy(struct vty *vty, const char *area_tag) { - VTY_DECLVAR_CONTEXT (isis_area, area); - struct area_addr *addr; - struct area_addr *addrp; - struct listnode *node; + struct isis_area *area; + struct listnode *node, *nnode; + struct isis_circuit *circuit; + struct area_addr *addr; - u_char buff[255]; + area = isis_area_lookup(area_tag); + + if (area == NULL) { + vty_out(vty, "Can't find ISIS instance \n"); + return CMD_ERR_NO_MATCH; + } + + QOBJ_UNREG(area); + + if (area->circuit_list) { + for (ALL_LIST_ELEMENTS(area->circuit_list, node, nnode, + circuit)) { + circuit->ip_router = 0; + circuit->ipv6_router = 0; + isis_csm_state_change(ISIS_DISABLE, circuit, area); + } + list_delete(area->circuit_list); + area->circuit_list = NULL; + } + + if (area->lspdb[0] != NULL) { + lsp_db_destroy(area->lspdb[0]); + area->lspdb[0] = NULL; + } + if (area->lspdb[1] != NULL) { + lsp_db_destroy(area->lspdb[1]); + area->lspdb[1] = NULL; + } + + spftree_area_del(area); + + THREAD_TIMER_OFF(area->spf_timer[0]); + THREAD_TIMER_OFF(area->spf_timer[1]); + + spf_backoff_free(area->spf_delay_ietf[0]); + spf_backoff_free(area->spf_delay_ietf[1]); + + /* invalidate and validate would delete all routes from zebra */ + isis_route_invalidate(area); + isis_route_validate(area); + + if (area->route_table[0]) { + route_table_finish(area->route_table[0]); + area->route_table[0] = NULL; + } + if (area->route_table[1]) { + route_table_finish(area->route_table[1]); + area->route_table[1] = NULL; + } + if (area->route_table6[0]) { + route_table_finish(area->route_table6[0]); + area->route_table6[0] = NULL; + } + if (area->route_table6[1]) { + route_table_finish(area->route_table6[1]); + area->route_table6[1] = NULL; + } + + isis_redist_area_finish(area); + + for (ALL_LIST_ELEMENTS(area->area_addrs, node, nnode, addr)) { + list_delete_node(area->area_addrs, node); + XFREE(MTYPE_ISIS_AREA_ADDR, addr); + } + area->area_addrs = NULL; + + THREAD_TIMER_OFF(area->t_tick); + THREAD_TIMER_OFF(area->t_lsp_refresh[0]); + THREAD_TIMER_OFF(area->t_lsp_refresh[1]); + + thread_cancel_event(master, area); + + listnode_delete(isis->area_list, area); + + free(area->area_tag); + + area_mt_finish(area); + + XFREE(MTYPE_ISIS_AREA, area); + + if (listcount(isis->area_list) == 0) { + memset(isis->sysid, 0, ISIS_SYS_ID_LEN); + isis->sysid_set = 0; + } + + return CMD_SUCCESS; +} + +static void area_set_mt_enabled(struct isis_area *area, uint16_t mtid, + bool enabled) +{ + struct isis_area_mt_setting *setting; + + setting = area_get_mt_setting(area, mtid); + if (setting->enabled != enabled) { + setting->enabled = enabled; + lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 0); + } +} + +static void area_set_mt_overload(struct isis_area *area, uint16_t mtid, + bool overload) +{ + struct isis_area_mt_setting *setting; + + setting = area_get_mt_setting(area, mtid); + if (setting->overload != overload) { + setting->overload = overload; + if (setting->enabled) + lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, + 0); + } +} + +int area_net_title(struct vty *vty, const char *net_title) +{ + VTY_DECLVAR_CONTEXT(isis_area, area); + struct area_addr *addr; + struct area_addr *addrp; + struct listnode *node; - /* We check that we are not over the maximal number of addresses */ - if (listcount (area->area_addrs) >= isis->max_area_addrs) - { - vty_out (vty, "Maximum of area addresses (%d) already reached \n", - isis->max_area_addrs); - return CMD_ERR_NOTHING_TODO; - } - - addr = XMALLOC (MTYPE_ISIS_AREA_ADDR, sizeof (struct area_addr)); - addr->addr_len = dotformat2buff (buff, net_title); - memcpy (addr->area_addr, buff, addr->addr_len); + u_char buff[255]; + + /* We check that we are not over the maximal number of addresses */ + if (listcount(area->area_addrs) >= isis->max_area_addrs) { + vty_out(vty, + "Maximum of area addresses (%d) already reached \n", + isis->max_area_addrs); + return CMD_ERR_NOTHING_TODO; + } + + addr = XMALLOC(MTYPE_ISIS_AREA_ADDR, sizeof(struct area_addr)); + addr->addr_len = dotformat2buff(buff, net_title); + memcpy(addr->area_addr, buff, addr->addr_len); #ifdef EXTREME_DEBUG - zlog_debug ("added area address %s for area %s (address length %d)", - net_title, area->area_tag, addr->addr_len); + zlog_debug("added area address %s for area %s (address length %d)", + net_title, area->area_tag, addr->addr_len); #endif /* EXTREME_DEBUG */ - if (addr->addr_len < 8 || addr->addr_len > 20) - { - vty_out (vty, "area address must be at least 8..20 octets long (%d)\n", - addr->addr_len); - XFREE (MTYPE_ISIS_AREA_ADDR, addr); - return CMD_ERR_AMBIGUOUS; - } - - if (addr->area_addr[addr->addr_len-1] != 0) - { - vty_out (vty,"nsel byte (last byte) in area address must be 0\n"); - XFREE (MTYPE_ISIS_AREA_ADDR, addr); - return CMD_ERR_AMBIGUOUS; - } - - if (isis->sysid_set == 0) - { - /* - * First area address - get the SystemID for this router - */ - memcpy (isis->sysid, GETSYSID (addr), ISIS_SYS_ID_LEN); - isis->sysid_set = 1; - if (isis->debugs & DEBUG_EVENTS) - zlog_debug ("Router has SystemID %s", sysid_print (isis->sysid)); - } - else - { - /* - * Check that the SystemID portions match - */ - if (memcmp (isis->sysid, GETSYSID (addr), ISIS_SYS_ID_LEN)) - { - vty_out (vty, - "System ID must not change when defining additional area addresses\n"); - XFREE (MTYPE_ISIS_AREA_ADDR, addr); - return CMD_ERR_AMBIGUOUS; - } - - /* now we see that we don't already have this address */ - for (ALL_LIST_ELEMENTS_RO (area->area_addrs, node, addrp)) - { - if ((addrp->addr_len + ISIS_SYS_ID_LEN + ISIS_NSEL_LEN) != (addr->addr_len)) - continue; - if (!memcmp (addrp->area_addr, addr->area_addr, addr->addr_len)) - { - XFREE (MTYPE_ISIS_AREA_ADDR, addr); - return CMD_SUCCESS; /* silent fail */ - } - } - } - - /* - * Forget the systemID part of the address - */ - addr->addr_len -= (ISIS_SYS_ID_LEN + ISIS_NSEL_LEN); - listnode_add (area->area_addrs, addr); - - /* only now we can safely generate our LSPs for this area */ - if (listcount (area->area_addrs) > 0) - { - if (area->is_type & IS_LEVEL_1) - lsp_generate (area, IS_LEVEL_1); - if (area->is_type & IS_LEVEL_2) - lsp_generate (area, IS_LEVEL_2); - } - - return CMD_SUCCESS; -} - -int -area_clear_net_title (struct vty *vty, const char *net_title) -{ - VTY_DECLVAR_CONTEXT (isis_area, area); - struct area_addr addr, *addrp = NULL; - struct listnode *node; - u_char buff[255]; - - addr.addr_len = dotformat2buff (buff, net_title); - if (addr.addr_len < 8 || addr.addr_len > 20) - { - vty_out (vty, "Unsupported area address length %d, should be 8...20 \n", - addr.addr_len); - return CMD_ERR_AMBIGUOUS; - } - - memcpy (addr.area_addr, buff, (int) addr.addr_len); - - for (ALL_LIST_ELEMENTS_RO (area->area_addrs, node, addrp)) - if ((addrp->addr_len + ISIS_SYS_ID_LEN + 1) == addr.addr_len && - !memcmp (addrp->area_addr, addr.area_addr, addr.addr_len)) - break; - - if (!addrp) - { - vty_out (vty, "No area address %s for area %s \n", net_title, - area->area_tag); - return CMD_ERR_NO_MATCH; - } - - listnode_delete (area->area_addrs, addrp); - XFREE (MTYPE_ISIS_AREA_ADDR, addrp); - - /* - * Last area address - reset the SystemID for this router - */ - if (listcount (area->area_addrs) == 0) - { - memset (isis->sysid, 0, ISIS_SYS_ID_LEN); - isis->sysid_set = 0; - if (isis->debugs & DEBUG_EVENTS) - zlog_debug ("Router has no SystemID"); - } - - return CMD_SUCCESS; + if (addr->addr_len < 8 || addr->addr_len > 20) { + vty_out(vty, + "area address must be at least 8..20 octets long (%d)\n", + addr->addr_len); + XFREE(MTYPE_ISIS_AREA_ADDR, addr); + return CMD_ERR_AMBIGUOUS; + } + + if (addr->area_addr[addr->addr_len - 1] != 0) { + vty_out(vty, + "nsel byte (last byte) in area address must be 0\n"); + XFREE(MTYPE_ISIS_AREA_ADDR, addr); + return CMD_ERR_AMBIGUOUS; + } + + if (isis->sysid_set == 0) { + /* + * First area address - get the SystemID for this router + */ + memcpy(isis->sysid, GETSYSID(addr), ISIS_SYS_ID_LEN); + isis->sysid_set = 1; + if (isis->debugs & DEBUG_EVENTS) + zlog_debug("Router has SystemID %s", + sysid_print(isis->sysid)); + } else { + /* + * Check that the SystemID portions match + */ + if (memcmp(isis->sysid, GETSYSID(addr), ISIS_SYS_ID_LEN)) { + vty_out(vty, + "System ID must not change when defining additional area addresses\n"); + XFREE(MTYPE_ISIS_AREA_ADDR, addr); + return CMD_ERR_AMBIGUOUS; + } + + /* now we see that we don't already have this address */ + for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node, addrp)) { + if ((addrp->addr_len + ISIS_SYS_ID_LEN + ISIS_NSEL_LEN) + != (addr->addr_len)) + continue; + if (!memcmp(addrp->area_addr, addr->area_addr, + addr->addr_len)) { + XFREE(MTYPE_ISIS_AREA_ADDR, addr); + return CMD_SUCCESS; /* silent fail */ + } + } + } + + /* + * Forget the systemID part of the address + */ + addr->addr_len -= (ISIS_SYS_ID_LEN + ISIS_NSEL_LEN); + listnode_add(area->area_addrs, addr); + + /* only now we can safely generate our LSPs for this area */ + if (listcount(area->area_addrs) > 0) { + if (area->is_type & IS_LEVEL_1) + lsp_generate(area, IS_LEVEL_1); + if (area->is_type & IS_LEVEL_2) + lsp_generate(area, IS_LEVEL_2); + } + + return CMD_SUCCESS; +} + +int area_clear_net_title(struct vty *vty, const char *net_title) +{ + VTY_DECLVAR_CONTEXT(isis_area, area); + struct area_addr addr, *addrp = NULL; + struct listnode *node; + u_char buff[255]; + + addr.addr_len = dotformat2buff(buff, net_title); + if (addr.addr_len < 8 || addr.addr_len > 20) { + vty_out(vty, + "Unsupported area address length %d, should be 8...20 \n", + addr.addr_len); + return CMD_ERR_AMBIGUOUS; + } + + memcpy(addr.area_addr, buff, (int)addr.addr_len); + + for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node, addrp)) + if ((addrp->addr_len + ISIS_SYS_ID_LEN + 1) == addr.addr_len + && !memcmp(addrp->area_addr, addr.area_addr, addr.addr_len)) + break; + + if (!addrp) { + vty_out(vty, "No area address %s for area %s \n", net_title, + area->area_tag); + return CMD_ERR_NO_MATCH; + } + + listnode_delete(area->area_addrs, addrp); + XFREE(MTYPE_ISIS_AREA_ADDR, addrp); + + /* + * Last area address - reset the SystemID for this router + */ + if (listcount(area->area_addrs) == 0) { + memset(isis->sysid, 0, ISIS_SYS_ID_LEN); + isis->sysid_set = 0; + if (isis->debugs & DEBUG_EVENTS) + zlog_debug("Router has no SystemID"); + } + + return CMD_SUCCESS; } /* * 'show isis interface' command */ -int -show_isis_interface_common (struct vty *vty, const char *ifname, char detail) +int show_isis_interface_common(struct vty *vty, const char *ifname, char detail) { - struct listnode *anode, *cnode; - struct isis_area *area; - struct isis_circuit *circuit; + struct listnode *anode, *cnode; + struct isis_area *area; + struct isis_circuit *circuit; - if (!isis) - { - vty_out (vty, "IS-IS Routing Process not enabled\n"); - return CMD_SUCCESS; - } + if (!isis) { + vty_out(vty, "IS-IS Routing Process not enabled\n"); + return CMD_SUCCESS; + } - for (ALL_LIST_ELEMENTS_RO (isis->area_list, anode, area)) - { - vty_out (vty, "Area %s:\n", area->area_tag); + for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { + vty_out(vty, "Area %s:\n", area->area_tag); - if (detail == ISIS_UI_LEVEL_BRIEF) - vty_out (vty," Interface CircId State Type Level\n"); + if (detail == ISIS_UI_LEVEL_BRIEF) + vty_out(vty, + " Interface CircId State Type Level\n"); - for (ALL_LIST_ELEMENTS_RO (area->circuit_list, cnode, circuit)) - if (!ifname) - isis_circuit_print_vty (circuit, vty, detail); - else if (strcmp(circuit->interface->name, ifname) == 0) - isis_circuit_print_vty (circuit, vty, detail); - } + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit)) + if (!ifname) + isis_circuit_print_vty(circuit, vty, detail); + else if (strcmp(circuit->interface->name, ifname) == 0) + isis_circuit_print_vty(circuit, vty, detail); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_isis_interface, @@ -521,7 +491,7 @@ DEFUN (show_isis_interface, "ISIS network information\n" "ISIS interface\n") { - return show_isis_interface_common (vty, NULL, ISIS_UI_LEVEL_BRIEF); + return show_isis_interface_common(vty, NULL, ISIS_UI_LEVEL_BRIEF); } DEFUN (show_isis_interface_detail, @@ -532,7 +502,7 @@ DEFUN (show_isis_interface_detail, "ISIS interface\n" "show detailed information\n") { - return show_isis_interface_common (vty, NULL, ISIS_UI_LEVEL_DETAIL); + return show_isis_interface_common(vty, NULL, ISIS_UI_LEVEL_DETAIL); } DEFUN (show_isis_interface_arg, @@ -543,150 +513,146 @@ DEFUN (show_isis_interface_arg, "ISIS interface\n" "ISIS interface name\n") { - int idx_word = 3; - return show_isis_interface_common (vty, argv[idx_word]->arg, ISIS_UI_LEVEL_DETAIL); + int idx_word = 3; + return show_isis_interface_common(vty, argv[idx_word]->arg, + ISIS_UI_LEVEL_DETAIL); } /* * 'show isis neighbor' command */ -int -show_isis_neighbor_common (struct vty *vty, const char *id, char detail) -{ - struct listnode *anode, *cnode, *node; - struct isis_area *area; - struct isis_circuit *circuit; - struct list *adjdb; - struct isis_adjacency *adj; - struct isis_dynhn *dynhn; - u_char sysid[ISIS_SYS_ID_LEN]; - int i; - - if (!isis) - { - vty_out (vty, "IS-IS Routing Process not enabled\n"); - return CMD_SUCCESS; - } - - memset (sysid, 0, ISIS_SYS_ID_LEN); - if (id) - { - if (sysid2buff (sysid, id) == 0) - { - dynhn = dynhn_find_by_name (id); - if (dynhn == NULL) - { - vty_out (vty, "Invalid system id %s\n", id); - return CMD_SUCCESS; - } - memcpy (sysid, dynhn->id, ISIS_SYS_ID_LEN); - } - } - - for (ALL_LIST_ELEMENTS_RO (isis->area_list, anode, area)) - { - vty_out (vty, "Area %s:\n", area->area_tag); - - if (detail == ISIS_UI_LEVEL_BRIEF) - vty_out (vty, - " System Id Interface L State Holdtime SNPA\n"); - - for (ALL_LIST_ELEMENTS_RO (area->circuit_list, cnode, circuit)) - { - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - { - for (i = 0; i < 2; i++) - { - adjdb = circuit->u.bc.adjdb[i]; - if (adjdb && adjdb->count) - { - for (ALL_LIST_ELEMENTS_RO (adjdb, node, adj)) - if (!id || !memcmp (adj->sysid, sysid, - ISIS_SYS_ID_LEN)) - isis_adj_print_vty (adj, vty, detail); - } - } - } - else if (circuit->circ_type == CIRCUIT_T_P2P && - circuit->u.p2p.neighbor) - { - adj = circuit->u.p2p.neighbor; - if (!id || !memcmp (adj->sysid, sysid, ISIS_SYS_ID_LEN)) - isis_adj_print_vty (adj, vty, detail); - } - } - } - - return CMD_SUCCESS; +int show_isis_neighbor_common(struct vty *vty, const char *id, char detail) +{ + struct listnode *anode, *cnode, *node; + struct isis_area *area; + struct isis_circuit *circuit; + struct list *adjdb; + struct isis_adjacency *adj; + struct isis_dynhn *dynhn; + u_char sysid[ISIS_SYS_ID_LEN]; + int i; + + if (!isis) { + vty_out(vty, "IS-IS Routing Process not enabled\n"); + return CMD_SUCCESS; + } + + memset(sysid, 0, ISIS_SYS_ID_LEN); + if (id) { + if (sysid2buff(sysid, id) == 0) { + dynhn = dynhn_find_by_name(id); + if (dynhn == NULL) { + vty_out(vty, "Invalid system id %s\n", id); + return CMD_SUCCESS; + } + memcpy(sysid, dynhn->id, ISIS_SYS_ID_LEN); + } + } + + for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { + vty_out(vty, "Area %s:\n", area->area_tag); + + if (detail == ISIS_UI_LEVEL_BRIEF) + vty_out(vty, + " System Id Interface L State Holdtime SNPA\n"); + + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit)) { + if (circuit->circ_type == CIRCUIT_T_BROADCAST) { + for (i = 0; i < 2; i++) { + adjdb = circuit->u.bc.adjdb[i]; + if (adjdb && adjdb->count) { + for (ALL_LIST_ELEMENTS_RO( + adjdb, node, adj)) + if (!id + || !memcmp(adj->sysid, + sysid, + ISIS_SYS_ID_LEN)) + isis_adj_print_vty( + adj, + vty, + detail); + } + } + } else if (circuit->circ_type == CIRCUIT_T_P2P + && circuit->u.p2p.neighbor) { + adj = circuit->u.p2p.neighbor; + if (!id + || !memcmp(adj->sysid, sysid, + ISIS_SYS_ID_LEN)) + isis_adj_print_vty(adj, vty, detail); + } + } + } + + return CMD_SUCCESS; } /* * 'clear isis neighbor' command */ -int -clear_isis_neighbor_common (struct vty *vty, const char *id) -{ - struct listnode *anode, *cnode, *cnextnode, *node, *nnode; - struct isis_area *area; - struct isis_circuit *circuit; - struct list *adjdb; - struct isis_adjacency *adj; - struct isis_dynhn *dynhn; - u_char sysid[ISIS_SYS_ID_LEN]; - int i; - - if (!isis) - { - vty_out (vty, "IS-IS Routing Process not enabled\n"); - return CMD_SUCCESS; - } - - memset (sysid, 0, ISIS_SYS_ID_LEN); - if (id) - { - if (sysid2buff (sysid, id) == 0) - { - dynhn = dynhn_find_by_name (id); - if (dynhn == NULL) - { - vty_out (vty, "Invalid system id %s\n", id); - return CMD_SUCCESS; - } - memcpy (sysid, dynhn->id, ISIS_SYS_ID_LEN); - } - } - - for (ALL_LIST_ELEMENTS_RO (isis->area_list, anode, area)) - { - for (ALL_LIST_ELEMENTS (area->circuit_list, cnode, cnextnode, circuit)) - { - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - { - for (i = 0; i < 2; i++) - { - adjdb = circuit->u.bc.adjdb[i]; - if (adjdb && adjdb->count) - { - for (ALL_LIST_ELEMENTS (adjdb, node, nnode, adj)) - if (!id || !memcmp (adj->sysid, sysid, ISIS_SYS_ID_LEN)) - isis_adj_state_change (adj, ISIS_ADJ_DOWN, - "clear user request"); - } - } - } - else if (circuit->circ_type == CIRCUIT_T_P2P && - circuit->u.p2p.neighbor) - { - adj = circuit->u.p2p.neighbor; - if (!id || !memcmp (adj->sysid, sysid, ISIS_SYS_ID_LEN)) - isis_adj_state_change (adj, ISIS_ADJ_DOWN, - "clear user request"); - } - } - } - - return CMD_SUCCESS; +int clear_isis_neighbor_common(struct vty *vty, const char *id) +{ + struct listnode *anode, *cnode, *cnextnode, *node, *nnode; + struct isis_area *area; + struct isis_circuit *circuit; + struct list *adjdb; + struct isis_adjacency *adj; + struct isis_dynhn *dynhn; + u_char sysid[ISIS_SYS_ID_LEN]; + int i; + + if (!isis) { + vty_out(vty, "IS-IS Routing Process not enabled\n"); + return CMD_SUCCESS; + } + + memset(sysid, 0, ISIS_SYS_ID_LEN); + if (id) { + if (sysid2buff(sysid, id) == 0) { + dynhn = dynhn_find_by_name(id); + if (dynhn == NULL) { + vty_out(vty, "Invalid system id %s\n", id); + return CMD_SUCCESS; + } + memcpy(sysid, dynhn->id, ISIS_SYS_ID_LEN); + } + } + + for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { + for (ALL_LIST_ELEMENTS(area->circuit_list, cnode, cnextnode, + circuit)) { + if (circuit->circ_type == CIRCUIT_T_BROADCAST) { + for (i = 0; i < 2; i++) { + adjdb = circuit->u.bc.adjdb[i]; + if (adjdb && adjdb->count) { + for (ALL_LIST_ELEMENTS( + adjdb, node, nnode, + adj)) + if (!id + || !memcmp(adj->sysid, + sysid, + ISIS_SYS_ID_LEN)) + isis_adj_state_change( + adj, + ISIS_ADJ_DOWN, + "clear user request"); + } + } + } else if (circuit->circ_type == CIRCUIT_T_P2P + && circuit->u.p2p.neighbor) { + adj = circuit->u.p2p.neighbor; + if (!id + || !memcmp(adj->sysid, sysid, + ISIS_SYS_ID_LEN)) + isis_adj_state_change( + adj, ISIS_ADJ_DOWN, + "clear user request"); + } + } + } + + return CMD_SUCCESS; } DEFUN (show_isis_neighbor, @@ -696,7 +662,7 @@ DEFUN (show_isis_neighbor, "ISIS network information\n" "ISIS neighbor adjacencies\n") { - return show_isis_neighbor_common (vty, NULL, ISIS_UI_LEVEL_BRIEF); + return show_isis_neighbor_common(vty, NULL, ISIS_UI_LEVEL_BRIEF); } DEFUN (show_isis_neighbor_detail, @@ -707,7 +673,7 @@ DEFUN (show_isis_neighbor_detail, "ISIS neighbor adjacencies\n" "show detailed information\n") { - return show_isis_neighbor_common (vty, NULL, ISIS_UI_LEVEL_DETAIL); + return show_isis_neighbor_common(vty, NULL, ISIS_UI_LEVEL_DETAIL); } DEFUN (show_isis_neighbor_arg, @@ -718,8 +684,9 @@ DEFUN (show_isis_neighbor_arg, "ISIS neighbor adjacencies\n" "System id\n") { - int idx_word = 3; - return show_isis_neighbor_common (vty, argv[idx_word]->arg, ISIS_UI_LEVEL_DETAIL); + int idx_word = 3; + return show_isis_neighbor_common(vty, argv[idx_word]->arg, + ISIS_UI_LEVEL_DETAIL); } DEFUN (clear_isis_neighbor, @@ -729,7 +696,7 @@ DEFUN (clear_isis_neighbor, "Reset ISIS network information\n" "Reset ISIS neighbor adjacencies\n") { - return clear_isis_neighbor_common (vty, NULL); + return clear_isis_neighbor_common(vty, NULL); } DEFUN (clear_isis_neighbor_arg, @@ -740,52 +707,56 @@ DEFUN (clear_isis_neighbor_arg, "ISIS neighbor adjacencies\n" "System id\n") { - int idx_word = 3; - return clear_isis_neighbor_common (vty, argv[idx_word]->arg); + int idx_word = 3; + return clear_isis_neighbor_common(vty, argv[idx_word]->arg); } /* * 'isis debug', 'show debugging' */ -void -print_debug (struct vty *vty, int flags, int onoff) -{ - char onoffs[4]; - if (onoff) - strcpy (onoffs, "on"); - else - strcpy (onoffs, "off"); - - if (flags & DEBUG_ADJ_PACKETS) - vty_out (vty, "IS-IS Adjacency related packets debugging is %s\n", - onoffs); - if (flags & DEBUG_CHECKSUM_ERRORS) - vty_out (vty, "IS-IS checksum errors debugging is %s\n",onoffs); - if (flags & DEBUG_LOCAL_UPDATES) - vty_out (vty, "IS-IS local updates debugging is %s\n",onoffs); - if (flags & DEBUG_PROTOCOL_ERRORS) - vty_out (vty, "IS-IS protocol errors debugging is %s\n",onoffs); - if (flags & DEBUG_SNP_PACKETS) - vty_out (vty, "IS-IS CSNP/PSNP packets debugging is %s\n",onoffs); - if (flags & DEBUG_SPF_EVENTS) - vty_out (vty, "IS-IS SPF events debugging is %s\n", onoffs); - if (flags & DEBUG_SPF_STATS) - vty_out (vty, "IS-IS SPF Timing and Statistics Data debugging is %s\n", - onoffs); - if (flags & DEBUG_SPF_TRIGGERS) - vty_out (vty, "IS-IS SPF triggering events debugging is %s\n",onoffs); - if (flags & DEBUG_UPDATE_PACKETS) - vty_out (vty, "IS-IS Update related packet debugging is %s\n",onoffs); - if (flags & DEBUG_RTE_EVENTS) - vty_out (vty, "IS-IS Route related debuggin is %s\n",onoffs); - if (flags & DEBUG_EVENTS) - vty_out (vty, "IS-IS Event debugging is %s\n", onoffs); - if (flags & DEBUG_PACKET_DUMP) - vty_out (vty, "IS-IS Packet dump debugging is %s\n", onoffs); - if (flags & DEBUG_LSP_GEN) - vty_out (vty, "IS-IS LSP generation debugging is %s\n", onoffs); - if (flags & DEBUG_LSP_SCHED) - vty_out (vty, "IS-IS LSP scheduling debugging is %s\n", onoffs); +void print_debug(struct vty *vty, int flags, int onoff) +{ + char onoffs[4]; + if (onoff) + strcpy(onoffs, "on"); + else + strcpy(onoffs, "off"); + + if (flags & DEBUG_ADJ_PACKETS) + vty_out(vty, + "IS-IS Adjacency related packets debugging is %s\n", + onoffs); + if (flags & DEBUG_CHECKSUM_ERRORS) + vty_out(vty, "IS-IS checksum errors debugging is %s\n", onoffs); + if (flags & DEBUG_LOCAL_UPDATES) + vty_out(vty, "IS-IS local updates debugging is %s\n", onoffs); + if (flags & DEBUG_PROTOCOL_ERRORS) + vty_out(vty, "IS-IS protocol errors debugging is %s\n", onoffs); + if (flags & DEBUG_SNP_PACKETS) + vty_out(vty, "IS-IS CSNP/PSNP packets debugging is %s\n", + onoffs); + if (flags & DEBUG_SPF_EVENTS) + vty_out(vty, "IS-IS SPF events debugging is %s\n", onoffs); + if (flags & DEBUG_SPF_STATS) + vty_out(vty, + "IS-IS SPF Timing and Statistics Data debugging is %s\n", + onoffs); + if (flags & DEBUG_SPF_TRIGGERS) + vty_out(vty, "IS-IS SPF triggering events debugging is %s\n", + onoffs); + if (flags & DEBUG_UPDATE_PACKETS) + vty_out(vty, "IS-IS Update related packet debugging is %s\n", + onoffs); + if (flags & DEBUG_RTE_EVENTS) + vty_out(vty, "IS-IS Route related debuggin is %s\n", onoffs); + if (flags & DEBUG_EVENTS) + vty_out(vty, "IS-IS Event debugging is %s\n", onoffs); + if (flags & DEBUG_PACKET_DUMP) + vty_out(vty, "IS-IS Packet dump debugging is %s\n", onoffs); + if (flags & DEBUG_LSP_GEN) + vty_out(vty, "IS-IS LSP generation debugging is %s\n", onoffs); + if (flags & DEBUG_LSP_SCHED) + vty_out(vty, "IS-IS LSP scheduling debugging is %s\n", onoffs); } DEFUN (show_debugging, @@ -795,99 +766,80 @@ DEFUN (show_debugging, "State of each debugging option\n" ISIS_STR) { - if (isis->debugs) { - vty_out (vty, "IS-IS:\n"); - print_debug (vty, isis->debugs, 1); - } - return CMD_SUCCESS; + if (isis->debugs) { + vty_out(vty, "IS-IS:\n"); + print_debug(vty, isis->debugs, 1); + } + return CMD_SUCCESS; } /* Debug node. */ -static struct cmd_node debug_node = { - DEBUG_NODE, - "", - 1 -}; - -static int -config_write_debug (struct vty *vty) -{ - int write = 0; - int flags = isis->debugs; - - if (flags & DEBUG_ADJ_PACKETS) - { - vty_out (vty, "debug isis adj-packets\n"); - write++; - } - if (flags & DEBUG_CHECKSUM_ERRORS) - { - vty_out (vty, "debug isis checksum-errors\n"); - write++; - } - if (flags & DEBUG_LOCAL_UPDATES) - { - vty_out (vty, "debug isis local-updates\n"); - write++; - } - if (flags & DEBUG_PROTOCOL_ERRORS) - { - vty_out (vty, "debug isis protocol-errors\n"); - write++; - } - if (flags & DEBUG_SNP_PACKETS) - { - vty_out (vty, "debug isis snp-packets\n"); - write++; - } - if (flags & DEBUG_SPF_EVENTS) - { - vty_out (vty, "debug isis spf-events\n"); - write++; - } - if (flags & DEBUG_SPF_STATS) - { - vty_out (vty, "debug isis spf-statistics\n"); - write++; - } - if (flags & DEBUG_SPF_TRIGGERS) - { - vty_out (vty, "debug isis spf-triggers\n"); - write++; - } - if (flags & DEBUG_UPDATE_PACKETS) - { - vty_out (vty, "debug isis update-packets\n"); - write++; - } - if (flags & DEBUG_RTE_EVENTS) - { - vty_out (vty, "debug isis route-events\n"); - write++; - } - if (flags & DEBUG_EVENTS) - { - vty_out (vty, "debug isis events\n"); - write++; - } - if (flags & DEBUG_PACKET_DUMP) - { - vty_out (vty, "debug isis packet-dump\n"); - write++; - } - if (flags & DEBUG_LSP_GEN) - { - vty_out (vty, "debug isis lsp-gen\n"); - write++; - } - if (flags & DEBUG_LSP_SCHED) - { - vty_out (vty, "debug isis lsp-sched\n"); - write++; - } - write += spf_backoff_write_config(vty); - - return write; +static struct cmd_node debug_node = {DEBUG_NODE, "", 1}; + +static int config_write_debug(struct vty *vty) +{ + int write = 0; + int flags = isis->debugs; + + if (flags & DEBUG_ADJ_PACKETS) { + vty_out(vty, "debug isis adj-packets\n"); + write++; + } + if (flags & DEBUG_CHECKSUM_ERRORS) { + vty_out(vty, "debug isis checksum-errors\n"); + write++; + } + if (flags & DEBUG_LOCAL_UPDATES) { + vty_out(vty, "debug isis local-updates\n"); + write++; + } + if (flags & DEBUG_PROTOCOL_ERRORS) { + vty_out(vty, "debug isis protocol-errors\n"); + write++; + } + if (flags & DEBUG_SNP_PACKETS) { + vty_out(vty, "debug isis snp-packets\n"); + write++; + } + if (flags & DEBUG_SPF_EVENTS) { + vty_out(vty, "debug isis spf-events\n"); + write++; + } + if (flags & DEBUG_SPF_STATS) { + vty_out(vty, "debug isis spf-statistics\n"); + write++; + } + if (flags & DEBUG_SPF_TRIGGERS) { + vty_out(vty, "debug isis spf-triggers\n"); + write++; + } + if (flags & DEBUG_UPDATE_PACKETS) { + vty_out(vty, "debug isis update-packets\n"); + write++; + } + if (flags & DEBUG_RTE_EVENTS) { + vty_out(vty, "debug isis route-events\n"); + write++; + } + if (flags & DEBUG_EVENTS) { + vty_out(vty, "debug isis events\n"); + write++; + } + if (flags & DEBUG_PACKET_DUMP) { + vty_out(vty, "debug isis packet-dump\n"); + write++; + } + if (flags & DEBUG_LSP_GEN) { + vty_out(vty, "debug isis lsp-gen\n"); + write++; + } + if (flags & DEBUG_LSP_SCHED) { + vty_out(vty, "debug isis lsp-sched\n"); + write++; + } + write += spf_backoff_write_config(vty); + + return write; } DEFUN (debug_isis_adj, @@ -897,10 +849,10 @@ DEFUN (debug_isis_adj, "IS-IS information\n" "IS-IS Adjacency related packets\n") { - isis->debugs |= DEBUG_ADJ_PACKETS; - print_debug (vty, DEBUG_ADJ_PACKETS, 1); + isis->debugs |= DEBUG_ADJ_PACKETS; + print_debug(vty, DEBUG_ADJ_PACKETS, 1); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_debug_isis_adj, @@ -911,10 +863,10 @@ DEFUN (no_debug_isis_adj, "IS-IS information\n" "IS-IS Adjacency related packets\n") { - isis->debugs &= ~DEBUG_ADJ_PACKETS; - print_debug (vty, DEBUG_ADJ_PACKETS, 0); + isis->debugs &= ~DEBUG_ADJ_PACKETS; + print_debug(vty, DEBUG_ADJ_PACKETS, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_isis_csum, @@ -924,10 +876,10 @@ DEFUN (debug_isis_csum, "IS-IS information\n" "IS-IS LSP checksum errors\n") { - isis->debugs |= DEBUG_CHECKSUM_ERRORS; - print_debug (vty, DEBUG_CHECKSUM_ERRORS, 1); + isis->debugs |= DEBUG_CHECKSUM_ERRORS; + print_debug(vty, DEBUG_CHECKSUM_ERRORS, 1); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_debug_isis_csum, @@ -938,10 +890,10 @@ DEFUN (no_debug_isis_csum, "IS-IS information\n" "IS-IS LSP checksum errors\n") { - isis->debugs &= ~DEBUG_CHECKSUM_ERRORS; - print_debug (vty, DEBUG_CHECKSUM_ERRORS, 0); + isis->debugs &= ~DEBUG_CHECKSUM_ERRORS; + print_debug(vty, DEBUG_CHECKSUM_ERRORS, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_isis_lupd, @@ -951,10 +903,10 @@ DEFUN (debug_isis_lupd, "IS-IS information\n" "IS-IS local update packets\n") { - isis->debugs |= DEBUG_LOCAL_UPDATES; - print_debug (vty, DEBUG_LOCAL_UPDATES, 1); + isis->debugs |= DEBUG_LOCAL_UPDATES; + print_debug(vty, DEBUG_LOCAL_UPDATES, 1); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_debug_isis_lupd, @@ -965,10 +917,10 @@ DEFUN (no_debug_isis_lupd, "IS-IS information\n" "IS-IS local update packets\n") { - isis->debugs &= ~DEBUG_LOCAL_UPDATES; - print_debug (vty, DEBUG_LOCAL_UPDATES, 0); + isis->debugs &= ~DEBUG_LOCAL_UPDATES; + print_debug(vty, DEBUG_LOCAL_UPDATES, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_isis_err, @@ -978,10 +930,10 @@ DEFUN (debug_isis_err, "IS-IS information\n" "IS-IS LSP protocol errors\n") { - isis->debugs |= DEBUG_PROTOCOL_ERRORS; - print_debug (vty, DEBUG_PROTOCOL_ERRORS, 1); + isis->debugs |= DEBUG_PROTOCOL_ERRORS; + print_debug(vty, DEBUG_PROTOCOL_ERRORS, 1); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_debug_isis_err, @@ -992,10 +944,10 @@ DEFUN (no_debug_isis_err, "IS-IS information\n" "IS-IS LSP protocol errors\n") { - isis->debugs &= ~DEBUG_PROTOCOL_ERRORS; - print_debug (vty, DEBUG_PROTOCOL_ERRORS, 0); + isis->debugs &= ~DEBUG_PROTOCOL_ERRORS; + print_debug(vty, DEBUG_PROTOCOL_ERRORS, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_isis_snp, @@ -1005,10 +957,10 @@ DEFUN (debug_isis_snp, "IS-IS information\n" "IS-IS CSNP/PSNP packets\n") { - isis->debugs |= DEBUG_SNP_PACKETS; - print_debug (vty, DEBUG_SNP_PACKETS, 1); + isis->debugs |= DEBUG_SNP_PACKETS; + print_debug(vty, DEBUG_SNP_PACKETS, 1); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_debug_isis_snp, @@ -1019,10 +971,10 @@ DEFUN (no_debug_isis_snp, "IS-IS information\n" "IS-IS CSNP/PSNP packets\n") { - isis->debugs &= ~DEBUG_SNP_PACKETS; - print_debug (vty, DEBUG_SNP_PACKETS, 0); + isis->debugs &= ~DEBUG_SNP_PACKETS; + print_debug(vty, DEBUG_SNP_PACKETS, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_isis_upd, @@ -1032,10 +984,10 @@ DEFUN (debug_isis_upd, "IS-IS information\n" "IS-IS Update related packets\n") { - isis->debugs |= DEBUG_UPDATE_PACKETS; - print_debug (vty, DEBUG_UPDATE_PACKETS, 1); + isis->debugs |= DEBUG_UPDATE_PACKETS; + print_debug(vty, DEBUG_UPDATE_PACKETS, 1); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_debug_isis_upd, @@ -1046,10 +998,10 @@ DEFUN (no_debug_isis_upd, "IS-IS information\n" "IS-IS Update related packets\n") { - isis->debugs &= ~DEBUG_UPDATE_PACKETS; - print_debug (vty, DEBUG_UPDATE_PACKETS, 0); + isis->debugs &= ~DEBUG_UPDATE_PACKETS; + print_debug(vty, DEBUG_UPDATE_PACKETS, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_isis_spfevents, @@ -1059,10 +1011,10 @@ DEFUN (debug_isis_spfevents, "IS-IS information\n" "IS-IS Shortest Path First Events\n") { - isis->debugs |= DEBUG_SPF_EVENTS; - print_debug (vty, DEBUG_SPF_EVENTS, 1); + isis->debugs |= DEBUG_SPF_EVENTS; + print_debug(vty, DEBUG_SPF_EVENTS, 1); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_debug_isis_spfevents, @@ -1073,10 +1025,10 @@ DEFUN (no_debug_isis_spfevents, "IS-IS information\n" "IS-IS Shortest Path First Events\n") { - isis->debugs &= ~DEBUG_SPF_EVENTS; - print_debug (vty, DEBUG_SPF_EVENTS, 0); + isis->debugs &= ~DEBUG_SPF_EVENTS; + print_debug(vty, DEBUG_SPF_EVENTS, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_isis_spfstats, @@ -1086,10 +1038,10 @@ DEFUN (debug_isis_spfstats, "IS-IS information\n" "IS-IS SPF Timing and Statistic Data\n") { - isis->debugs |= DEBUG_SPF_STATS; - print_debug (vty, DEBUG_SPF_STATS, 1); + isis->debugs |= DEBUG_SPF_STATS; + print_debug(vty, DEBUG_SPF_STATS, 1); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_debug_isis_spfstats, @@ -1100,10 +1052,10 @@ DEFUN (no_debug_isis_spfstats, "IS-IS information\n" "IS-IS SPF Timing and Statistic Data\n") { - isis->debugs &= ~DEBUG_SPF_STATS; - print_debug (vty, DEBUG_SPF_STATS, 0); + isis->debugs &= ~DEBUG_SPF_STATS; + print_debug(vty, DEBUG_SPF_STATS, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_isis_spftrigg, @@ -1113,10 +1065,10 @@ DEFUN (debug_isis_spftrigg, "IS-IS information\n" "IS-IS SPF triggering events\n") { - isis->debugs |= DEBUG_SPF_TRIGGERS; - print_debug (vty, DEBUG_SPF_TRIGGERS, 1); + isis->debugs |= DEBUG_SPF_TRIGGERS; + print_debug(vty, DEBUG_SPF_TRIGGERS, 1); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_debug_isis_spftrigg, @@ -1127,10 +1079,10 @@ DEFUN (no_debug_isis_spftrigg, "IS-IS information\n" "IS-IS SPF triggering events\n") { - isis->debugs &= ~DEBUG_SPF_TRIGGERS; - print_debug (vty, DEBUG_SPF_TRIGGERS, 0); + isis->debugs &= ~DEBUG_SPF_TRIGGERS; + print_debug(vty, DEBUG_SPF_TRIGGERS, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_isis_rtevents, @@ -1140,10 +1092,10 @@ DEFUN (debug_isis_rtevents, "IS-IS information\n" "IS-IS Route related events\n") { - isis->debugs |= DEBUG_RTE_EVENTS; - print_debug (vty, DEBUG_RTE_EVENTS, 1); + isis->debugs |= DEBUG_RTE_EVENTS; + print_debug(vty, DEBUG_RTE_EVENTS, 1); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_debug_isis_rtevents, @@ -1154,10 +1106,10 @@ DEFUN (no_debug_isis_rtevents, "IS-IS information\n" "IS-IS Route related events\n") { - isis->debugs &= ~DEBUG_RTE_EVENTS; - print_debug (vty, DEBUG_RTE_EVENTS, 0); + isis->debugs &= ~DEBUG_RTE_EVENTS; + print_debug(vty, DEBUG_RTE_EVENTS, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_isis_events, @@ -1167,10 +1119,10 @@ DEFUN (debug_isis_events, "IS-IS information\n" "IS-IS Events\n") { - isis->debugs |= DEBUG_EVENTS; - print_debug (vty, DEBUG_EVENTS, 1); + isis->debugs |= DEBUG_EVENTS; + print_debug(vty, DEBUG_EVENTS, 1); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_debug_isis_events, @@ -1181,10 +1133,10 @@ DEFUN (no_debug_isis_events, "IS-IS information\n" "IS-IS Events\n") { - isis->debugs &= ~DEBUG_EVENTS; - print_debug (vty, DEBUG_EVENTS, 0); + isis->debugs &= ~DEBUG_EVENTS; + print_debug(vty, DEBUG_EVENTS, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_isis_packet_dump, @@ -1194,10 +1146,10 @@ DEFUN (debug_isis_packet_dump, "IS-IS information\n" "IS-IS packet dump\n") { - isis->debugs |= DEBUG_PACKET_DUMP; - print_debug (vty, DEBUG_PACKET_DUMP, 1); + isis->debugs |= DEBUG_PACKET_DUMP; + print_debug(vty, DEBUG_PACKET_DUMP, 1); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_debug_isis_packet_dump, @@ -1208,10 +1160,10 @@ DEFUN (no_debug_isis_packet_dump, "IS-IS information\n" "IS-IS packet dump\n") { - isis->debugs &= ~DEBUG_PACKET_DUMP; - print_debug (vty, DEBUG_PACKET_DUMP, 0); + isis->debugs &= ~DEBUG_PACKET_DUMP; + print_debug(vty, DEBUG_PACKET_DUMP, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_isis_lsp_gen, @@ -1221,10 +1173,10 @@ DEFUN (debug_isis_lsp_gen, "IS-IS information\n" "IS-IS generation of own LSPs\n") { - isis->debugs |= DEBUG_LSP_GEN; - print_debug (vty, DEBUG_LSP_GEN, 1); + isis->debugs |= DEBUG_LSP_GEN; + print_debug(vty, DEBUG_LSP_GEN, 1); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_debug_isis_lsp_gen, @@ -1235,10 +1187,10 @@ DEFUN (no_debug_isis_lsp_gen, "IS-IS information\n" "IS-IS generation of own LSPs\n") { - isis->debugs &= ~DEBUG_LSP_GEN; - print_debug (vty, DEBUG_LSP_GEN, 0); + isis->debugs &= ~DEBUG_LSP_GEN; + print_debug(vty, DEBUG_LSP_GEN, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_isis_lsp_sched, @@ -1248,10 +1200,10 @@ DEFUN (debug_isis_lsp_sched, "IS-IS information\n" "IS-IS scheduling of LSP generation\n") { - isis->debugs |= DEBUG_LSP_SCHED; - print_debug (vty, DEBUG_LSP_SCHED, 1); + isis->debugs |= DEBUG_LSP_SCHED; + print_debug(vty, DEBUG_LSP_SCHED, 1); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_debug_isis_lsp_sched, @@ -1262,10 +1214,10 @@ DEFUN (no_debug_isis_lsp_sched, "IS-IS information\n" "IS-IS scheduling of LSP generation\n") { - isis->debugs &= ~DEBUG_LSP_SCHED; - print_debug (vty, DEBUG_LSP_SCHED, 0); + isis->debugs &= ~DEBUG_LSP_SCHED; + print_debug(vty, DEBUG_LSP_SCHED, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_hostname, @@ -1275,32 +1227,30 @@ DEFUN (show_hostname, "IS-IS information\n" "IS-IS Dynamic hostname mapping\n") { - dynhn_print_all (vty); + dynhn_print_all(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static void -vty_out_timestr(struct vty *vty, time_t uptime) +static void vty_out_timestr(struct vty *vty, time_t uptime) { - struct tm *tm; - time_t difftime = time (NULL); - difftime -= uptime; - tm = gmtime (&difftime); + struct tm *tm; + time_t difftime = time(NULL); + difftime -= uptime; + tm = gmtime(&difftime); #define ONE_DAY_SECOND 60*60*24 #define ONE_WEEK_SECOND 60*60*24*7 - if (difftime < ONE_DAY_SECOND) - vty_out (vty, "%02d:%02d:%02d", - tm->tm_hour, tm->tm_min, tm->tm_sec); - else if (difftime < ONE_WEEK_SECOND) - vty_out (vty, "%dd%02dh%02dm", - tm->tm_yday, tm->tm_hour, tm->tm_min); - else - vty_out (vty, "%02dw%dd%02dh", - tm->tm_yday/7, - tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); - vty_out (vty, " ago"); + if (difftime < ONE_DAY_SECOND) + vty_out(vty, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, + tm->tm_sec); + else if (difftime < ONE_WEEK_SECOND) + vty_out(vty, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour, + tm->tm_min); + else + vty_out(vty, "%02dw%dd%02dh", tm->tm_yday / 7, + tm->tm_yday - ((tm->tm_yday / 7) * 7), tm->tm_hour); + vty_out(vty, " ago"); } DEFUN (show_isis_spf_ietf, @@ -1310,46 +1260,46 @@ DEFUN (show_isis_spf_ietf, "IS-IS information\n" "IS-IS SPF delay IETF information\n") { - if (!isis) - { - vty_out (vty, "ISIS is not running\n"); - return CMD_SUCCESS; - } - - struct listnode *node; - struct isis_area *area; - - for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area)) - { - vty_out (vty, "Area %s:\n",area->area_tag ? area->area_tag : "null"); - - for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) - { - if ((area->is_type & level) == 0) - continue; - - vty_out (vty, " Level-%d:\n", level); - vty_out (vty, " SPF delay status: "); - if (area->spf_timer[level -1]) - { - struct timeval remain = thread_timer_remain(area->spf_timer[level - 1]); - vty_out (vty, "Pending, due in %ld msec\n", - remain.tv_sec * 1000 + remain.tv_usec / 1000); - } - else - { - vty_out (vty, "Not scheduled\n"); - } - - if (area->spf_delay_ietf[level - 1]) { - vty_out (vty, " Using draft-ietf-rtgwg-backoff-algo-04\n"); - spf_backoff_show(area->spf_delay_ietf[level - 1], vty, " "); - } else { - vty_out (vty, " Using legacy backoff algo\n"); - } - } - } - return CMD_SUCCESS; + if (!isis) { + vty_out(vty, "ISIS is not running\n"); + return CMD_SUCCESS; + } + + struct listnode *node; + struct isis_area *area; + + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { + vty_out(vty, "Area %s:\n", + area->area_tag ? area->area_tag : "null"); + + for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) { + if ((area->is_type & level) == 0) + continue; + + vty_out(vty, " Level-%d:\n", level); + vty_out(vty, " SPF delay status: "); + if (area->spf_timer[level - 1]) { + struct timeval remain = thread_timer_remain( + area->spf_timer[level - 1]); + vty_out(vty, "Pending, due in %ld msec\n", + remain.tv_sec * 1000 + + remain.tv_usec / 1000); + } else { + vty_out(vty, "Not scheduled\n"); + } + + if (area->spf_delay_ietf[level - 1]) { + vty_out(vty, + " Using draft-ietf-rtgwg-backoff-algo-04\n"); + spf_backoff_show( + area->spf_delay_ietf[level - 1], vty, + " "); + } else { + vty_out(vty, " Using legacy backoff algo\n"); + } + } + } + return CMD_SUCCESS; } DEFUN (show_isis_summary, @@ -1357,88 +1307,90 @@ DEFUN (show_isis_summary, "show isis summary", SHOW_STR "IS-IS information\n" "IS-IS summary\n") { - struct listnode *node, *node2; - struct isis_area *area; - struct isis_spftree *spftree; - int level; - - if (isis == NULL) - { - vty_out (vty, "ISIS is not running\n"); - return CMD_SUCCESS; - } - - vty_out (vty, "Process Id : %ld\n",isis->process_id); - if (isis->sysid_set) - vty_out (vty, "System Id : %s\n",sysid_print(isis->sysid)); - - vty_out (vty, "Up time : "); - vty_out_timestr(vty, isis->uptime); - vty_out (vty, "\n"); - - if (isis->area_list) - vty_out (vty, "Number of areas : %d\n",isis->area_list->count); - - for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area)) - { - vty_out (vty, "Area %s:\n",area->area_tag ? area->area_tag : "null"); - - if (listcount (area->area_addrs) > 0) - { - struct area_addr *area_addr; - for (ALL_LIST_ELEMENTS_RO (area->area_addrs, node2, area_addr)) - { - vty_out (vty, " Net: %s\n", - isonet_print(area_addr->area_addr, area_addr->addr_len + ISIS_SYS_ID_LEN + 1)); - } - } - - for (level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) - { - if ((area->is_type & level) == 0) - continue; - - vty_out (vty, " Level-%d:\n", level); - spftree = area->spftree[level - 1]; - if (area->spf_timer[level - 1]) - vty_out (vty, " SPF: (pending)\n"); - else - vty_out (vty, " SPF:\n"); - - vty_out (vty, " minimum interval : %d", - area->min_spf_interval[level - 1]); - if (area->spf_delay_ietf[level - 1]) - vty_out (vty, " (not used, IETF SPF delay activated)"); - vty_out (vty, "\n"); - - vty_out (vty, " IPv4 route computation:\n"); - vty_out (vty, " last run elapsed : "); - vty_out_timestr(vty, spftree->last_run_timestamp); - vty_out (vty, "\n"); - - vty_out (vty, " last run duration : %u usec\n", - (u_int32_t)spftree->last_run_duration); - - vty_out (vty, " run count : %d\n", - spftree->runcount); - - spftree = area->spftree6[level - 1]; - vty_out (vty, " IPv6 route computation:\n"); - - vty_out (vty, " last run elapsed : "); - vty_out_timestr(vty, spftree->last_run_timestamp); - vty_out (vty, "\n"); - - vty_out (vty, " last run duration : %llu msec\n", - (unsigned long long)spftree->last_run_duration); - - vty_out (vty, " run count : %d\n", - spftree->runcount); - } - } - vty_out (vty, "\n"); - - return CMD_SUCCESS; + struct listnode *node, *node2; + struct isis_area *area; + struct isis_spftree *spftree; + int level; + + if (isis == NULL) { + vty_out(vty, "ISIS is not running\n"); + return CMD_SUCCESS; + } + + vty_out(vty, "Process Id : %ld\n", isis->process_id); + if (isis->sysid_set) + vty_out(vty, "System Id : %s\n", + sysid_print(isis->sysid)); + + vty_out(vty, "Up time : "); + vty_out_timestr(vty, isis->uptime); + vty_out(vty, "\n"); + + if (isis->area_list) + vty_out(vty, "Number of areas : %d\n", isis->area_list->count); + + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { + vty_out(vty, "Area %s:\n", + area->area_tag ? area->area_tag : "null"); + + if (listcount(area->area_addrs) > 0) { + struct area_addr *area_addr; + for (ALL_LIST_ELEMENTS_RO(area->area_addrs, node2, + area_addr)) { + vty_out(vty, " Net: %s\n", + isonet_print(area_addr->area_addr, + area_addr->addr_len + + ISIS_SYS_ID_LEN + + 1)); + } + } + + for (level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) { + if ((area->is_type & level) == 0) + continue; + + vty_out(vty, " Level-%d:\n", level); + spftree = area->spftree[level - 1]; + if (area->spf_timer[level - 1]) + vty_out(vty, " SPF: (pending)\n"); + else + vty_out(vty, " SPF:\n"); + + vty_out(vty, " minimum interval : %d", + area->min_spf_interval[level - 1]); + if (area->spf_delay_ietf[level - 1]) + vty_out(vty, + " (not used, IETF SPF delay activated)"); + vty_out(vty, "\n"); + + vty_out(vty, " IPv4 route computation:\n"); + vty_out(vty, " last run elapsed : "); + vty_out_timestr(vty, spftree->last_run_timestamp); + vty_out(vty, "\n"); + + vty_out(vty, " last run duration : %u usec\n", + (u_int32_t)spftree->last_run_duration); + + vty_out(vty, " run count : %d\n", + spftree->runcount); + + spftree = area->spftree6[level - 1]; + vty_out(vty, " IPv6 route computation:\n"); + + vty_out(vty, " last run elapsed : "); + vty_out_timestr(vty, spftree->last_run_timestamp); + vty_out(vty, "\n"); + + vty_out(vty, " last run duration : %llu msec\n", + (unsigned long long)spftree->last_run_duration); + + vty_out(vty, " run count : %d\n", + spftree->runcount); + } + } + vty_out(vty, "\n"); + + return CMD_SUCCESS; } /* @@ -1457,117 +1409,121 @@ DEFUN (show_isis_summary, * [ show isis database detail .- ] * [ show isis database detail .- ] */ -static int -show_isis_database (struct vty *vty, const char *argv, int ui_level) -{ - struct listnode *node; - struct isis_area *area; - struct isis_lsp *lsp; - struct isis_dynhn *dynhn; - const char *pos = argv; - u_char lspid[ISIS_SYS_ID_LEN+2]; - char sysid[255]; - u_char number[3]; - int level, lsp_count; - - if (isis->area_list->count == 0) - return CMD_SUCCESS; - - memset (&lspid, 0, ISIS_SYS_ID_LEN); - memset (&sysid, 0, 255); - - /* - * extract fragment and pseudo id from the string argv - * in the forms: - * (a) .- or - * (b) . or - * (c) or - * Where systemid is in the form: - * xxxx.xxxx.xxxx - */ - if (argv) - strncpy (sysid, argv, 254); - if (argv && strlen (argv) > 3) - { - pos = argv + strlen (argv) - 3; - if (strncmp (pos, "-", 1) == 0) - { - memcpy (number, ++pos, 2); - lspid[ISIS_SYS_ID_LEN+1] = (u_char) strtol ((char *)number, NULL, 16); - pos -= 4; - if (strncmp (pos, ".", 1) != 0) - return CMD_ERR_AMBIGUOUS; - } - if (strncmp (pos, ".", 1) == 0) - { - memcpy (number, ++pos, 2); - lspid[ISIS_SYS_ID_LEN] = (u_char) strtol ((char *)number, NULL, 16); - sysid[pos - argv - 1] = '\0'; - } - } - - for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area)) - { - vty_out (vty, "Area %s:\n",area->area_tag ? area->area_tag : "null"); - - for (level = 0; level < ISIS_LEVELS; level++) - { - if (area->lspdb[level] && dict_count (area->lspdb[level]) > 0) - { - lsp = NULL; - if (argv != NULL) - { - /* - * Try to find the lsp-id if the argv string is in - * the form hostname.- - */ - if (sysid2buff (lspid, sysid)) - { - lsp = lsp_search (lspid, area->lspdb[level]); - } - else if ((dynhn = dynhn_find_by_name (sysid))) - { - memcpy (lspid, dynhn->id, ISIS_SYS_ID_LEN); - lsp = lsp_search (lspid, area->lspdb[level]); - } - else if (strncmp(unix_hostname (), sysid, 15) == 0) - { - memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN); - lsp = lsp_search (lspid, area->lspdb[level]); - } - } - - if (lsp != NULL || argv == NULL) - { - vty_out (vty, "IS-IS Level-%d link-state database:\n", - level + 1); - - /* print the title in all cases */ - vty_out (vty, - "LSP ID PduLen SeqNumber Chksum Holdtime ATT/P/OL\n"); - } - - if (lsp) - { - if (ui_level == ISIS_UI_LEVEL_DETAIL) - lsp_print_detail (lsp, vty, area->dynhostname); - else - lsp_print (lsp, vty, area->dynhostname); - } - else if (argv == NULL) - { - lsp_count = lsp_print_all (vty, area->lspdb[level], - ui_level, - area->dynhostname); - - vty_out (vty, " %u LSPs\n\n", - lsp_count); - } - } - } - } - - return CMD_SUCCESS; +static int show_isis_database(struct vty *vty, const char *argv, int ui_level) +{ + struct listnode *node; + struct isis_area *area; + struct isis_lsp *lsp; + struct isis_dynhn *dynhn; + const char *pos = argv; + u_char lspid[ISIS_SYS_ID_LEN + 2]; + char sysid[255]; + u_char number[3]; + int level, lsp_count; + + if (isis->area_list->count == 0) + return CMD_SUCCESS; + + memset(&lspid, 0, ISIS_SYS_ID_LEN); + memset(&sysid, 0, 255); + + /* + * extract fragment and pseudo id from the string argv + * in the forms: + * (a) .- or + * (b) . or + * (c) or + * Where systemid is in the form: + * xxxx.xxxx.xxxx + */ + if (argv) + strncpy(sysid, argv, 254); + if (argv && strlen(argv) > 3) { + pos = argv + strlen(argv) - 3; + if (strncmp(pos, "-", 1) == 0) { + memcpy(number, ++pos, 2); + lspid[ISIS_SYS_ID_LEN + 1] = + (u_char)strtol((char *)number, NULL, 16); + pos -= 4; + if (strncmp(pos, ".", 1) != 0) + return CMD_ERR_AMBIGUOUS; + } + if (strncmp(pos, ".", 1) == 0) { + memcpy(number, ++pos, 2); + lspid[ISIS_SYS_ID_LEN] = + (u_char)strtol((char *)number, NULL, 16); + sysid[pos - argv - 1] = '\0'; + } + } + + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { + vty_out(vty, "Area %s:\n", + area->area_tag ? area->area_tag : "null"); + + for (level = 0; level < ISIS_LEVELS; level++) { + if (area->lspdb[level] + && dict_count(area->lspdb[level]) > 0) { + lsp = NULL; + if (argv != NULL) { + /* + * Try to find the lsp-id if the argv + * string is in + * the form + * hostname.- + */ + if (sysid2buff(lspid, sysid)) { + lsp = lsp_search( + lspid, + area->lspdb[level]); + } else if ((dynhn = dynhn_find_by_name( + sysid))) { + memcpy(lspid, dynhn->id, + ISIS_SYS_ID_LEN); + lsp = lsp_search( + lspid, + area->lspdb[level]); + } else if (strncmp(unix_hostname(), + sysid, 15) + == 0) { + memcpy(lspid, isis->sysid, + ISIS_SYS_ID_LEN); + lsp = lsp_search( + lspid, + area->lspdb[level]); + } + } + + if (lsp != NULL || argv == NULL) { + vty_out(vty, + "IS-IS Level-%d link-state database:\n", + level + 1); + + /* print the title in all cases */ + vty_out(vty, + "LSP ID PduLen SeqNumber Chksum Holdtime ATT/P/OL\n"); + } + + if (lsp) { + if (ui_level == ISIS_UI_LEVEL_DETAIL) + lsp_print_detail( + lsp, vty, + area->dynhostname); + else + lsp_print(lsp, vty, + area->dynhostname); + } else if (argv == NULL) { + lsp_count = lsp_print_all( + vty, area->lspdb[level], + ui_level, area->dynhostname); + + vty_out(vty, " %u LSPs\n\n", + lsp_count); + } + } + } + } + + return CMD_SUCCESS; } DEFUN (show_database, @@ -1579,14 +1535,16 @@ DEFUN (show_database, "Detailed information\n" "LSP ID\n") { - int idx = 0; - int uilevel = argv_find (argv, argc, "detail", &idx) ? ISIS_UI_LEVEL_DETAIL : ISIS_UI_LEVEL_BRIEF; - char *id = argv_find (argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL; - return show_isis_database (vty, id, uilevel); + int idx = 0; + int uilevel = argv_find(argv, argc, "detail", &idx) + ? ISIS_UI_LEVEL_DETAIL + : ISIS_UI_LEVEL_BRIEF; + char *id = argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL; + return show_isis_database(vty, id, uilevel); } -/* - * 'router isis' command +/* + * 'router isis' command */ DEFUN_NOSH (router_isis, router_isis_cmd, @@ -1595,20 +1553,20 @@ DEFUN_NOSH (router_isis, "ISO IS-IS\n" "ISO Routing area tag") { - int idx_word = 2; - return isis_area_get (vty, argv[idx_word]->arg); + int idx_word = 2; + return isis_area_get(vty, argv[idx_word]->arg); } -/* - *'no router isis' command +/* + *'no router isis' command */ DEFUN (no_router_isis, no_router_isis_cmd, "no router isis WORD", "no\n" ROUTER_STR "ISO IS-IS\n" "ISO Routing area tag") { - int idx_word = 3; - return isis_area_destroy (vty, argv[idx_word]->arg); + int idx_word = 3; + return isis_area_destroy(vty, argv[idx_word]->arg); } /* @@ -1620,8 +1578,8 @@ DEFUN (net, "A Network Entity Title for this process (OSI only)\n" "XX.XXXX. ... .XXX.XX Network entity title (NET)\n") { - int idx_word = 1; - return area_net_title (vty, argv[idx_word]->arg); + int idx_word = 1; + return area_net_title(vty, argv[idx_word]->arg); } /* @@ -1634,8 +1592,8 @@ DEFUN (no_net, "A Network Entity Title for this process (OSI only)\n" "XX.XXXX. ... .XXX.XX Network entity title (NET)\n") { - int idx_word = 2; - return area_clear_net_title (vty, argv[idx_word]->arg); + int idx_word = 2; + return area_clear_net_title(vty, argv[idx_word]->arg); } DEFUN (isis_topology, @@ -1645,32 +1603,29 @@ DEFUN (isis_topology, ISIS_MT_DESCRIPTIONS "Set overload bit for topology\n") { - VTY_DECLVAR_CONTEXT (isis_area, area); + VTY_DECLVAR_CONTEXT(isis_area, area); - const char *arg = argv[1]->arg; - uint16_t mtid = isis_str2mtid(arg); + const char *arg = argv[1]->arg; + uint16_t mtid = isis_str2mtid(arg); - if (area->oldmetric) - { - vty_out (vty, - "Multi topology IS-IS can only be used with wide metrics\n"); - return CMD_ERR_AMBIGUOUS; - } + if (area->oldmetric) { + vty_out(vty, + "Multi topology IS-IS can only be used with wide metrics\n"); + return CMD_ERR_AMBIGUOUS; + } - if (mtid == (uint16_t)-1) - { - vty_out (vty, "Don't know topology '%s'\n", arg); - return CMD_ERR_AMBIGUOUS; - } - if (mtid == ISIS_MT_IPV4_UNICAST) - { - vty_out (vty, "Cannot configure IPv4 unicast topology\n"); - return CMD_ERR_AMBIGUOUS; - } + if (mtid == (uint16_t)-1) { + vty_out(vty, "Don't know topology '%s'\n", arg); + return CMD_ERR_AMBIGUOUS; + } + if (mtid == ISIS_MT_IPV4_UNICAST) { + vty_out(vty, "Cannot configure IPv4 unicast topology\n"); + return CMD_ERR_AMBIGUOUS; + } - area_set_mt_enabled(area, mtid, true); - area_set_mt_overload(area, mtid, (argc == 3)); - return CMD_SUCCESS; + area_set_mt_enabled(area, mtid, true); + area_set_mt_overload(area, mtid, (argc == 3)); + return CMD_SUCCESS; } DEFUN (no_isis_topology, @@ -1681,274 +1636,253 @@ DEFUN (no_isis_topology, ISIS_MT_DESCRIPTIONS "Set overload bit for topology\n") { - VTY_DECLVAR_CONTEXT (isis_area, area); + VTY_DECLVAR_CONTEXT(isis_area, area); - const char *arg = argv[2]->arg; - uint16_t mtid = isis_str2mtid(arg); + const char *arg = argv[2]->arg; + uint16_t mtid = isis_str2mtid(arg); - if (area->oldmetric) - { - vty_out (vty, - "Multi topology IS-IS can only be used with wide metrics\n"); - return CMD_ERR_AMBIGUOUS; - } + if (area->oldmetric) { + vty_out(vty, + "Multi topology IS-IS can only be used with wide metrics\n"); + return CMD_ERR_AMBIGUOUS; + } - if (mtid == (uint16_t)-1) - { - vty_out (vty, "Don't know topology '%s'\n", arg); - return CMD_ERR_AMBIGUOUS; - } - if (mtid == ISIS_MT_IPV4_UNICAST) - { - vty_out (vty, "Cannot configure IPv4 unicast topology\n"); - return CMD_ERR_AMBIGUOUS; - } + if (mtid == (uint16_t)-1) { + vty_out(vty, "Don't know topology '%s'\n", arg); + return CMD_ERR_AMBIGUOUS; + } + if (mtid == ISIS_MT_IPV4_UNICAST) { + vty_out(vty, "Cannot configure IPv4 unicast topology\n"); + return CMD_ERR_AMBIGUOUS; + } - area_set_mt_enabled(area, mtid, false); - area_set_mt_overload(area, mtid, false); - return CMD_SUCCESS; + area_set_mt_enabled(area, mtid, false); + area_set_mt_overload(area, mtid, false); + return CMD_SUCCESS; } void isis_area_lsp_mtu_set(struct isis_area *area, unsigned int lsp_mtu) { - area->lsp_mtu = lsp_mtu; - lsp_regenerate_schedule(area, IS_LEVEL_1_AND_2, 1); + area->lsp_mtu = lsp_mtu; + lsp_regenerate_schedule(area, IS_LEVEL_1_AND_2, 1); +} + +static int isis_area_passwd_set(struct isis_area *area, int level, + u_char passwd_type, const char *passwd, + u_char snp_auth) +{ + struct isis_passwd *dest; + struct isis_passwd modified; + int len; + + assert((level == IS_LEVEL_1) || (level == IS_LEVEL_2)); + dest = (level == IS_LEVEL_1) ? &area->area_passwd + : &area->domain_passwd; + memset(&modified, 0, sizeof(modified)); + + if (passwd_type != ISIS_PASSWD_TYPE_UNUSED) { + if (!passwd) + return -1; + + len = strlen(passwd); + if (len > 254) + return -1; + + modified.len = len; + strncpy((char *)modified.passwd, passwd, 255); + modified.type = passwd_type; + modified.snp_auth = snp_auth; + } + + if (memcmp(&modified, dest, sizeof(modified))) { + memcpy(dest, &modified, sizeof(modified)); + lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 1); + } + + return 0; +} + +int isis_area_passwd_unset(struct isis_area *area, int level) +{ + return isis_area_passwd_set(area, level, ISIS_PASSWD_TYPE_UNUSED, NULL, + 0); +} + +int isis_area_passwd_cleartext_set(struct isis_area *area, int level, + const char *passwd, u_char snp_auth) +{ + return isis_area_passwd_set(area, level, ISIS_PASSWD_TYPE_CLEARTXT, + passwd, snp_auth); +} + +int isis_area_passwd_hmac_md5_set(struct isis_area *area, int level, + const char *passwd, u_char snp_auth) +{ + return isis_area_passwd_set(area, level, ISIS_PASSWD_TYPE_HMAC_MD5, + passwd, snp_auth); } -static int -isis_area_passwd_set(struct isis_area *area, int level, u_char passwd_type, - const char *passwd, u_char snp_auth) +static void area_resign_level(struct isis_area *area, int level) { - struct isis_passwd *dest; - struct isis_passwd modified; - int len; + if (area->lspdb[level - 1]) { + lsp_db_destroy(area->lspdb[level - 1]); + area->lspdb[level - 1] = NULL; + } + if (area->spftree[level - 1]) { + isis_spftree_del(area->spftree[level - 1]); + area->spftree[level - 1] = NULL; + } + if (area->spftree6[level - 1]) { + isis_spftree_del(area->spftree6[level - 1]); + area->spftree6[level - 1] = NULL; + } + THREAD_TIMER_OFF(area->spf_timer[level - 1]); + if (area->route_table[level - 1]) { + route_table_finish(area->route_table[level - 1]); + area->route_table[level - 1] = NULL; + } + if (area->route_table6[level - 1]) { + route_table_finish(area->route_table6[level - 1]); + area->route_table6[level - 1] = NULL; + } - assert((level == IS_LEVEL_1) || (level == IS_LEVEL_2)); - dest = (level == IS_LEVEL_1) ? &area->area_passwd : &area->domain_passwd; - memset(&modified, 0, sizeof(modified)); + sched_debug( + "ISIS (%s): Resigned from L%d - canceling LSP regeneration timer.", + area->area_tag, level); + THREAD_TIMER_OFF(area->t_lsp_refresh[level - 1]); + area->lsp_regenerate_pending[level - 1] = 0; +} - if (passwd_type != ISIS_PASSWD_TYPE_UNUSED) - { - if (!passwd) - return -1; +void isis_area_is_type_set(struct isis_area *area, int is_type) +{ + struct listnode *node; + struct isis_circuit *circuit; - len = strlen(passwd); - if (len > 254) - return -1; + if (isis->debugs & DEBUG_EVENTS) + zlog_debug("ISIS-Evt (%s) system type change %s -> %s", + area->area_tag, circuit_t2string(area->is_type), + circuit_t2string(is_type)); - modified.len = len; - strncpy((char*)modified.passwd, passwd, 255); - modified.type = passwd_type; - modified.snp_auth = snp_auth; - } - - if (memcmp(&modified, dest, sizeof(modified))) - { - memcpy(dest, &modified, sizeof(modified)); - lsp_regenerate_schedule(area, IS_LEVEL_1|IS_LEVEL_2, 1); - } - - return 0; -} - -int -isis_area_passwd_unset (struct isis_area *area, int level) -{ - return isis_area_passwd_set (area, level, ISIS_PASSWD_TYPE_UNUSED, NULL, 0); -} - -int -isis_area_passwd_cleartext_set (struct isis_area *area, int level, - const char *passwd, u_char snp_auth) -{ - return isis_area_passwd_set (area, level, ISIS_PASSWD_TYPE_CLEARTXT, - passwd, snp_auth); -} - -int -isis_area_passwd_hmac_md5_set (struct isis_area *area, int level, - const char *passwd, u_char snp_auth) -{ - return isis_area_passwd_set (area, level, ISIS_PASSWD_TYPE_HMAC_MD5, - passwd, snp_auth); -} - -static void -area_resign_level (struct isis_area *area, int level) -{ - if (area->lspdb[level - 1]) - { - lsp_db_destroy (area->lspdb[level - 1]); - area->lspdb[level - 1] = NULL; - } - if (area->spftree[level - 1]) - { - isis_spftree_del (area->spftree[level - 1]); - area->spftree[level - 1] = NULL; - } - if (area->spftree6[level - 1]) - { - isis_spftree_del (area->spftree6[level - 1]); - area->spftree6[level - 1] = NULL; - } - THREAD_TIMER_OFF(area->spf_timer[level - 1]); - if (area->route_table[level - 1]) - { - route_table_finish (area->route_table[level - 1]); - area->route_table[level - 1] = NULL; - } - if (area->route_table6[level - 1]) - { - route_table_finish (area->route_table6[level - 1]); - area->route_table6[level - 1] = NULL; - } - - sched_debug("ISIS (%s): Resigned from L%d - canceling LSP regeneration timer.", - area->area_tag, level); - THREAD_TIMER_OFF (area->t_lsp_refresh[level - 1]); - area->lsp_regenerate_pending[level - 1] = 0; -} - -void -isis_area_is_type_set(struct isis_area *area, int is_type) -{ - struct listnode *node; - struct isis_circuit *circuit; - - if (isis->debugs & DEBUG_EVENTS) - zlog_debug ("ISIS-Evt (%s) system type change %s -> %s", area->area_tag, - circuit_t2string (area->is_type), circuit_t2string (is_type)); - - if (area->is_type == is_type) - return; /* No change */ - - switch (area->is_type) - { - case IS_LEVEL_1: - if (is_type == IS_LEVEL_2) - area_resign_level (area, IS_LEVEL_1); - - if (area->lspdb[1] == NULL) - area->lspdb[1] = lsp_db_init (); - if (area->route_table[1] == NULL) - area->route_table[1] = route_table_init (); - if (area->route_table6[1] == NULL) - area->route_table6[1] = route_table_init (); - break; - - case IS_LEVEL_1_AND_2: - if (is_type == IS_LEVEL_1) - area_resign_level (area, IS_LEVEL_2); - else - area_resign_level (area, IS_LEVEL_1); - break; - - case IS_LEVEL_2: - if (is_type == IS_LEVEL_1) - area_resign_level (area, IS_LEVEL_2); - - if (area->lspdb[0] == NULL) - area->lspdb[0] = lsp_db_init (); - if (area->route_table[0] == NULL) - area->route_table[0] = route_table_init (); - if (area->route_table6[0] == NULL) - area->route_table6[0] = route_table_init (); - break; - - default: - break; - } - - area->is_type = is_type; - - /* override circuit's is_type */ - if (area->is_type != IS_LEVEL_1_AND_2) - { - for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit)) - isis_circuit_is_type_set (circuit, is_type); - } - - spftree_area_init (area); - - if (listcount (area->area_addrs) > 0) - { - if (is_type & IS_LEVEL_1) - lsp_generate (area, IS_LEVEL_1); - if (is_type & IS_LEVEL_2) - lsp_generate (area, IS_LEVEL_2); - } - lsp_regenerate_schedule (area, IS_LEVEL_1 | IS_LEVEL_2, 1); - - return; + if (area->is_type == is_type) + return; /* No change */ + + switch (area->is_type) { + case IS_LEVEL_1: + if (is_type == IS_LEVEL_2) + area_resign_level(area, IS_LEVEL_1); + + if (area->lspdb[1] == NULL) + area->lspdb[1] = lsp_db_init(); + if (area->route_table[1] == NULL) + area->route_table[1] = route_table_init(); + if (area->route_table6[1] == NULL) + area->route_table6[1] = route_table_init(); + break; + + case IS_LEVEL_1_AND_2: + if (is_type == IS_LEVEL_1) + area_resign_level(area, IS_LEVEL_2); + else + area_resign_level(area, IS_LEVEL_1); + break; + + case IS_LEVEL_2: + if (is_type == IS_LEVEL_1) + area_resign_level(area, IS_LEVEL_2); + + if (area->lspdb[0] == NULL) + area->lspdb[0] = lsp_db_init(); + if (area->route_table[0] == NULL) + area->route_table[0] = route_table_init(); + if (area->route_table6[0] == NULL) + area->route_table6[0] = route_table_init(); + break; + + default: + break; + } + + area->is_type = is_type; + + /* override circuit's is_type */ + if (area->is_type != IS_LEVEL_1_AND_2) { + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) + isis_circuit_is_type_set(circuit, is_type); + } + + spftree_area_init(area); + + if (listcount(area->area_addrs) > 0) { + if (is_type & IS_LEVEL_1) + lsp_generate(area, IS_LEVEL_1); + if (is_type & IS_LEVEL_2) + lsp_generate(area, IS_LEVEL_2); + } + lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 1); + + return; } void isis_area_metricstyle_set(struct isis_area *area, bool old_metric, bool new_metric) { - if (area->oldmetric != old_metric - || area->newmetric != new_metric) - { - area->oldmetric = old_metric; - area->newmetric = new_metric; - lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 1); - } + if (area->oldmetric != old_metric || area->newmetric != new_metric) { + area->oldmetric = old_metric; + area->newmetric = new_metric; + lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 1); + } } void isis_area_overload_bit_set(struct isis_area *area, bool overload_bit) { - char new_overload_bit = overload_bit ? LSPBIT_OL : 0; + char new_overload_bit = overload_bit ? LSPBIT_OL : 0; - if (new_overload_bit != area->overload_bit) - { - area->overload_bit = new_overload_bit; - lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 1); - } + if (new_overload_bit != area->overload_bit) { + area->overload_bit = new_overload_bit; + lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 1); + } } void isis_area_attached_bit_set(struct isis_area *area, bool attached_bit) { - char new_attached_bit = attached_bit ? LSPBIT_ATT : 0; + char new_attached_bit = attached_bit ? LSPBIT_ATT : 0; - if (new_attached_bit != area->attached_bit) - { - area->attached_bit = new_attached_bit; - lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 1); - } + if (new_attached_bit != area->attached_bit) { + area->attached_bit = new_attached_bit; + lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 1); + } } void isis_area_dynhostname_set(struct isis_area *area, bool dynhostname) { - if (area->dynhostname != dynhostname) - { - area->dynhostname = dynhostname; - lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 0); - } + if (area->dynhostname != dynhostname) { + area->dynhostname = dynhostname; + lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 0); + } } -void -isis_area_max_lsp_lifetime_set(struct isis_area *area, int level, - uint16_t max_lsp_lifetime) +void isis_area_max_lsp_lifetime_set(struct isis_area *area, int level, + uint16_t max_lsp_lifetime) { - assert((level == IS_LEVEL_1) || (level == IS_LEVEL_2)); + assert((level == IS_LEVEL_1) || (level == IS_LEVEL_2)); - if (area->max_lsp_lifetime[level-1] == max_lsp_lifetime) - return; + if (area->max_lsp_lifetime[level - 1] == max_lsp_lifetime) + return; - area->max_lsp_lifetime[level-1] = max_lsp_lifetime; - lsp_regenerate_schedule(area, level, 1); + area->max_lsp_lifetime[level - 1] = max_lsp_lifetime; + lsp_regenerate_schedule(area, level, 1); } -void -isis_area_lsp_refresh_set(struct isis_area *area, int level, - uint16_t lsp_refresh) +void isis_area_lsp_refresh_set(struct isis_area *area, int level, + uint16_t lsp_refresh) { - assert((level == IS_LEVEL_1) || (level == IS_LEVEL_2)); + assert((level == IS_LEVEL_1) || (level == IS_LEVEL_2)); - if (area->lsp_refresh[level-1] == lsp_refresh) - return; + if (area->lsp_refresh[level - 1] == lsp_refresh) + return; - area->lsp_refresh[level-1] = lsp_refresh; - lsp_regenerate_schedule(area, level, 1); + area->lsp_refresh[level - 1] = lsp_refresh; + lsp_regenerate_schedule(area, level, 1); } DEFUN (log_adj_changes, @@ -1956,11 +1890,11 @@ DEFUN (log_adj_changes, "log-adjacency-changes", "Log changes in adjacency state\n") { - VTY_DECLVAR_CONTEXT (isis_area, area); + VTY_DECLVAR_CONTEXT(isis_area, area); - area->log_adj_changes = 1; + area->log_adj_changes = 1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_log_adj_changes, @@ -1969,377 +1903,377 @@ DEFUN (no_log_adj_changes, NO_STR "Stop logging changes in adjacency state\n") { - VTY_DECLVAR_CONTEXT (isis_area, area); + VTY_DECLVAR_CONTEXT(isis_area, area); - area->log_adj_changes = 0; + area->log_adj_changes = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } /* IS-IS configuration write function */ -int -isis_config_write (struct vty *vty) -{ - int write = 0; - - if (isis != NULL) - { - struct isis_area *area; - struct listnode *node, *node2; - - for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area)) - { - /* ISIS - Area name */ - vty_out (vty, "router isis %s\n", area->area_tag); - write++; - /* ISIS - Net */ - if (listcount (area->area_addrs) > 0) - { - struct area_addr *area_addr; - for (ALL_LIST_ELEMENTS_RO (area->area_addrs, node2, area_addr)) - { - vty_out (vty, " net %s\n", - isonet_print(area_addr->area_addr, area_addr->addr_len + ISIS_SYS_ID_LEN + 1)); - write++; - } - } - /* ISIS - Dynamic hostname - Defaults to true so only display if - * false. */ - if (!area->dynhostname) - { - vty_out (vty, " no hostname dynamic\n"); - write++; - } - /* ISIS - Metric-Style - when true displays wide */ - if (area->newmetric) - { - if (!area->oldmetric) - vty_out (vty, " metric-style wide\n"); - else - vty_out (vty, " metric-style transition\n"); - write++; - } - else - { - vty_out (vty, " metric-style narrow\n"); - write++; - } - /* ISIS - overload-bit */ - if (area->overload_bit) - { - vty_out (vty, " set-overload-bit\n"); - write++; - } - /* ISIS - Area is-type (level-1-2 is default) */ - if (area->is_type == IS_LEVEL_1) - { - vty_out (vty, " is-type level-1\n"); - write++; - } - else if (area->is_type == IS_LEVEL_2) - { - vty_out (vty, " is-type level-2-only\n"); - write++; - } - write += isis_redist_config_write(vty, area, AF_INET); - write += isis_redist_config_write(vty, area, AF_INET6); - /* ISIS - Lsp generation interval */ - if (area->lsp_gen_interval[0] == area->lsp_gen_interval[1]) - { - if (area->lsp_gen_interval[0] != DEFAULT_MIN_LSP_GEN_INTERVAL) - { - vty_out (vty, " lsp-gen-interval %d\n", - area->lsp_gen_interval[0]); - write++; - } - } - else - { - if (area->lsp_gen_interval[0] != DEFAULT_MIN_LSP_GEN_INTERVAL) - { - vty_out (vty, " lsp-gen-interval level-1 %d\n", - area->lsp_gen_interval[0]); - write++; - } - if (area->lsp_gen_interval[1] != DEFAULT_MIN_LSP_GEN_INTERVAL) - { - vty_out (vty, " lsp-gen-interval level-2 %d\n", - area->lsp_gen_interval[1]); - write++; - } - } - /* ISIS - LSP lifetime */ - if (area->max_lsp_lifetime[0] == area->max_lsp_lifetime[1]) - { - if (area->max_lsp_lifetime[0] != DEFAULT_LSP_LIFETIME) - { - vty_out (vty, " max-lsp-lifetime %u\n", - area->max_lsp_lifetime[0]); - write++; - } - } - else - { - if (area->max_lsp_lifetime[0] != DEFAULT_LSP_LIFETIME) - { - vty_out (vty, " max-lsp-lifetime level-1 %u\n", - area->max_lsp_lifetime[0]); - write++; - } - if (area->max_lsp_lifetime[1] != DEFAULT_LSP_LIFETIME) - { - vty_out (vty, " max-lsp-lifetime level-2 %u\n", - area->max_lsp_lifetime[1]); - write++; - } - } - /* ISIS - LSP refresh interval */ - if (area->lsp_refresh[0] == area->lsp_refresh[1]) - { - if (area->lsp_refresh[0] != DEFAULT_MAX_LSP_GEN_INTERVAL) - { - vty_out (vty, " lsp-refresh-interval %u\n", - area->lsp_refresh[0]); - write++; - } - } - else - { - if (area->lsp_refresh[0] != DEFAULT_MAX_LSP_GEN_INTERVAL) - { - vty_out (vty, " lsp-refresh-interval level-1 %u\n", - area->lsp_refresh[0]); - write++; - } - if (area->lsp_refresh[1] != DEFAULT_MAX_LSP_GEN_INTERVAL) - { - vty_out (vty, " lsp-refresh-interval level-2 %u\n", - area->lsp_refresh[1]); - write++; - } - } - if (area->lsp_mtu != DEFAULT_LSP_MTU) - { - vty_out (vty, " lsp-mtu %u\n", area->lsp_mtu); - write++; - } - - /* Minimum SPF interval. */ - if (area->min_spf_interval[0] == area->min_spf_interval[1]) - { - if (area->min_spf_interval[0] != MINIMUM_SPF_INTERVAL) - { - vty_out (vty, " spf-interval %d\n", - area->min_spf_interval[0]); - write++; - } - } - else - { - if (area->min_spf_interval[0] != MINIMUM_SPF_INTERVAL) - { - vty_out (vty, " spf-interval level-1 %d\n", - area->min_spf_interval[0]); - write++; - } - if (area->min_spf_interval[1] != MINIMUM_SPF_INTERVAL) - { - vty_out (vty, " spf-interval level-2 %d\n", - area->min_spf_interval[1]); - write++; - } - } - - /* IETF SPF interval */ - if (area->spf_delay_ietf[0]) - { - vty_out (vty, " spf-delay-ietf init-delay %ld short-delay %ld long-delay %ld holddown %ld time-to-learn %ld\n", - spf_backoff_init_delay(area->spf_delay_ietf[0]), - spf_backoff_short_delay(area->spf_delay_ietf[0]), - spf_backoff_long_delay(area->spf_delay_ietf[0]), - spf_backoff_holddown(area->spf_delay_ietf[0]), - spf_backoff_timetolearn(area->spf_delay_ietf[0])); - write++; - } - - /* Authentication passwords. */ - if (area->area_passwd.type == ISIS_PASSWD_TYPE_HMAC_MD5) - { - vty_out(vty, " area-password md5 %s", area->area_passwd.passwd); - if (CHECK_FLAG(area->area_passwd.snp_auth, SNP_AUTH_SEND)) - { - vty_out(vty, " authenticate snp "); - if (CHECK_FLAG(area->area_passwd.snp_auth, SNP_AUTH_RECV)) - vty_out(vty, "validate"); - else - vty_out(vty, "send-only"); - } - vty_out (vty, "\n"); - write++; - } - else if (area->area_passwd.type == ISIS_PASSWD_TYPE_CLEARTXT) - { - vty_out(vty, " area-password clear %s", area->area_passwd.passwd); - if (CHECK_FLAG(area->area_passwd.snp_auth, SNP_AUTH_SEND)) - { - vty_out(vty, " authenticate snp "); - if (CHECK_FLAG(area->area_passwd.snp_auth, SNP_AUTH_RECV)) - vty_out(vty, "validate"); - else - vty_out(vty, "send-only"); - } - vty_out (vty, "\n"); - write++; - } - if (area->domain_passwd.type == ISIS_PASSWD_TYPE_HMAC_MD5) - { - vty_out(vty, " domain-password md5 %s", - area->domain_passwd.passwd); - if (CHECK_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_SEND)) - { - vty_out(vty, " authenticate snp "); - if (CHECK_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_RECV)) - vty_out(vty, "validate"); - else - vty_out(vty, "send-only"); - } - vty_out (vty, "\n"); - write++; - } - else if (area->domain_passwd.type == ISIS_PASSWD_TYPE_CLEARTXT) - { - vty_out(vty, " domain-password clear %s", - area->domain_passwd.passwd); - if (CHECK_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_SEND)) - { - vty_out(vty, " authenticate snp "); - if (CHECK_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_RECV)) - vty_out(vty, "validate"); - else - vty_out(vty, "send-only"); - } - vty_out (vty, "\n"); - write++; - } - - if (area->log_adj_changes) - { - vty_out (vty, " log-adjacency-changes\n"); - write++; - } - - write += area_write_mt_settings(area, vty); - } - isis_mpls_te_config_write_router(vty); - } - - return write; -} - -struct cmd_node isis_node = { - ISIS_NODE, - "%s(config-router)# ", - 1 -}; - -void -isis_init () -{ - /* Install IS-IS top node */ - install_node (&isis_node, isis_config_write); - - install_element (VIEW_NODE, &show_isis_summary_cmd); - - install_element (VIEW_NODE, &show_isis_spf_ietf_cmd); - - install_element (VIEW_NODE, &show_isis_interface_cmd); - install_element (VIEW_NODE, &show_isis_interface_detail_cmd); - install_element (VIEW_NODE, &show_isis_interface_arg_cmd); - - install_element (VIEW_NODE, &show_isis_neighbor_cmd); - install_element (VIEW_NODE, &show_isis_neighbor_detail_cmd); - install_element (VIEW_NODE, &show_isis_neighbor_arg_cmd); - install_element (VIEW_NODE, &clear_isis_neighbor_cmd); - install_element (VIEW_NODE, &clear_isis_neighbor_arg_cmd); - - install_element (VIEW_NODE, &show_hostname_cmd); - install_element (VIEW_NODE, &show_database_cmd); - - install_element (ENABLE_NODE, &show_debugging_isis_cmd); - - install_node (&debug_node, config_write_debug); - - install_element (ENABLE_NODE, &debug_isis_adj_cmd); - install_element (ENABLE_NODE, &no_debug_isis_adj_cmd); - install_element (ENABLE_NODE, &debug_isis_csum_cmd); - install_element (ENABLE_NODE, &no_debug_isis_csum_cmd); - install_element (ENABLE_NODE, &debug_isis_lupd_cmd); - install_element (ENABLE_NODE, &no_debug_isis_lupd_cmd); - install_element (ENABLE_NODE, &debug_isis_err_cmd); - install_element (ENABLE_NODE, &no_debug_isis_err_cmd); - install_element (ENABLE_NODE, &debug_isis_snp_cmd); - install_element (ENABLE_NODE, &no_debug_isis_snp_cmd); - install_element (ENABLE_NODE, &debug_isis_upd_cmd); - install_element (ENABLE_NODE, &no_debug_isis_upd_cmd); - install_element (ENABLE_NODE, &debug_isis_spfevents_cmd); - install_element (ENABLE_NODE, &no_debug_isis_spfevents_cmd); - install_element (ENABLE_NODE, &debug_isis_spfstats_cmd); - install_element (ENABLE_NODE, &no_debug_isis_spfstats_cmd); - install_element (ENABLE_NODE, &debug_isis_spftrigg_cmd); - install_element (ENABLE_NODE, &no_debug_isis_spftrigg_cmd); - install_element (ENABLE_NODE, &debug_isis_rtevents_cmd); - install_element (ENABLE_NODE, &no_debug_isis_rtevents_cmd); - install_element (ENABLE_NODE, &debug_isis_events_cmd); - install_element (ENABLE_NODE, &no_debug_isis_events_cmd); - install_element (ENABLE_NODE, &debug_isis_packet_dump_cmd); - install_element (ENABLE_NODE, &no_debug_isis_packet_dump_cmd); - install_element (ENABLE_NODE, &debug_isis_lsp_gen_cmd); - install_element (ENABLE_NODE, &no_debug_isis_lsp_gen_cmd); - install_element (ENABLE_NODE, &debug_isis_lsp_sched_cmd); - install_element (ENABLE_NODE, &no_debug_isis_lsp_sched_cmd); - - install_element (CONFIG_NODE, &debug_isis_adj_cmd); - install_element (CONFIG_NODE, &no_debug_isis_adj_cmd); - install_element (CONFIG_NODE, &debug_isis_csum_cmd); - install_element (CONFIG_NODE, &no_debug_isis_csum_cmd); - install_element (CONFIG_NODE, &debug_isis_lupd_cmd); - install_element (CONFIG_NODE, &no_debug_isis_lupd_cmd); - install_element (CONFIG_NODE, &debug_isis_err_cmd); - install_element (CONFIG_NODE, &no_debug_isis_err_cmd); - install_element (CONFIG_NODE, &debug_isis_snp_cmd); - install_element (CONFIG_NODE, &no_debug_isis_snp_cmd); - install_element (CONFIG_NODE, &debug_isis_upd_cmd); - install_element (CONFIG_NODE, &no_debug_isis_upd_cmd); - install_element (CONFIG_NODE, &debug_isis_spfevents_cmd); - install_element (CONFIG_NODE, &no_debug_isis_spfevents_cmd); - install_element (CONFIG_NODE, &debug_isis_spfstats_cmd); - install_element (CONFIG_NODE, &no_debug_isis_spfstats_cmd); - install_element (CONFIG_NODE, &debug_isis_spftrigg_cmd); - install_element (CONFIG_NODE, &no_debug_isis_spftrigg_cmd); - install_element (CONFIG_NODE, &debug_isis_rtevents_cmd); - install_element (CONFIG_NODE, &no_debug_isis_rtevents_cmd); - install_element (CONFIG_NODE, &debug_isis_events_cmd); - install_element (CONFIG_NODE, &no_debug_isis_events_cmd); - install_element (CONFIG_NODE, &debug_isis_packet_dump_cmd); - install_element (CONFIG_NODE, &no_debug_isis_packet_dump_cmd); - install_element (CONFIG_NODE, &debug_isis_lsp_gen_cmd); - install_element (CONFIG_NODE, &no_debug_isis_lsp_gen_cmd); - install_element (CONFIG_NODE, &debug_isis_lsp_sched_cmd); - install_element (CONFIG_NODE, &no_debug_isis_lsp_sched_cmd); - - install_element (CONFIG_NODE, &router_isis_cmd); - install_element (CONFIG_NODE, &no_router_isis_cmd); - - install_default (ISIS_NODE); - - install_element (ISIS_NODE, &net_cmd); - install_element (ISIS_NODE, &no_net_cmd); - - install_element (ISIS_NODE, &isis_topology_cmd); - install_element (ISIS_NODE, &no_isis_topology_cmd); - - install_element (ISIS_NODE, &log_adj_changes_cmd); - install_element (ISIS_NODE, &no_log_adj_changes_cmd); - - spf_backoff_cmd_init(); +int isis_config_write(struct vty *vty) +{ + int write = 0; + + if (isis != NULL) { + struct isis_area *area; + struct listnode *node, *node2; + + for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { + /* ISIS - Area name */ + vty_out(vty, "router isis %s\n", area->area_tag); + write++; + /* ISIS - Net */ + if (listcount(area->area_addrs) > 0) { + struct area_addr *area_addr; + for (ALL_LIST_ELEMENTS_RO(area->area_addrs, + node2, area_addr)) { + vty_out(vty, " net %s\n", + isonet_print( + area_addr->area_addr, + area_addr->addr_len + + ISIS_SYS_ID_LEN + + 1)); + write++; + } + } + /* ISIS - Dynamic hostname - Defaults to true so only + * display if + * false. */ + if (!area->dynhostname) { + vty_out(vty, " no hostname dynamic\n"); + write++; + } + /* ISIS - Metric-Style - when true displays wide */ + if (area->newmetric) { + if (!area->oldmetric) + vty_out(vty, " metric-style wide\n"); + else + vty_out(vty, + " metric-style transition\n"); + write++; + } else { + vty_out(vty, " metric-style narrow\n"); + write++; + } + /* ISIS - overload-bit */ + if (area->overload_bit) { + vty_out(vty, " set-overload-bit\n"); + write++; + } + /* ISIS - Area is-type (level-1-2 is default) */ + if (area->is_type == IS_LEVEL_1) { + vty_out(vty, " is-type level-1\n"); + write++; + } else if (area->is_type == IS_LEVEL_2) { + vty_out(vty, " is-type level-2-only\n"); + write++; + } + write += isis_redist_config_write(vty, area, AF_INET); + write += isis_redist_config_write(vty, area, AF_INET6); + /* ISIS - Lsp generation interval */ + if (area->lsp_gen_interval[0] + == area->lsp_gen_interval[1]) { + if (area->lsp_gen_interval[0] + != DEFAULT_MIN_LSP_GEN_INTERVAL) { + vty_out(vty, " lsp-gen-interval %d\n", + area->lsp_gen_interval[0]); + write++; + } + } else { + if (area->lsp_gen_interval[0] + != DEFAULT_MIN_LSP_GEN_INTERVAL) { + vty_out(vty, + " lsp-gen-interval level-1 %d\n", + area->lsp_gen_interval[0]); + write++; + } + if (area->lsp_gen_interval[1] + != DEFAULT_MIN_LSP_GEN_INTERVAL) { + vty_out(vty, + " lsp-gen-interval level-2 %d\n", + area->lsp_gen_interval[1]); + write++; + } + } + /* ISIS - LSP lifetime */ + if (area->max_lsp_lifetime[0] + == area->max_lsp_lifetime[1]) { + if (area->max_lsp_lifetime[0] + != DEFAULT_LSP_LIFETIME) { + vty_out(vty, " max-lsp-lifetime %u\n", + area->max_lsp_lifetime[0]); + write++; + } + } else { + if (area->max_lsp_lifetime[0] + != DEFAULT_LSP_LIFETIME) { + vty_out(vty, + " max-lsp-lifetime level-1 %u\n", + area->max_lsp_lifetime[0]); + write++; + } + if (area->max_lsp_lifetime[1] + != DEFAULT_LSP_LIFETIME) { + vty_out(vty, + " max-lsp-lifetime level-2 %u\n", + area->max_lsp_lifetime[1]); + write++; + } + } + /* ISIS - LSP refresh interval */ + if (area->lsp_refresh[0] == area->lsp_refresh[1]) { + if (area->lsp_refresh[0] + != DEFAULT_MAX_LSP_GEN_INTERVAL) { + vty_out(vty, + " lsp-refresh-interval %u\n", + area->lsp_refresh[0]); + write++; + } + } else { + if (area->lsp_refresh[0] + != DEFAULT_MAX_LSP_GEN_INTERVAL) { + vty_out(vty, + " lsp-refresh-interval level-1 %u\n", + area->lsp_refresh[0]); + write++; + } + if (area->lsp_refresh[1] + != DEFAULT_MAX_LSP_GEN_INTERVAL) { + vty_out(vty, + " lsp-refresh-interval level-2 %u\n", + area->lsp_refresh[1]); + write++; + } + } + if (area->lsp_mtu != DEFAULT_LSP_MTU) { + vty_out(vty, " lsp-mtu %u\n", area->lsp_mtu); + write++; + } + + /* Minimum SPF interval. */ + if (area->min_spf_interval[0] + == area->min_spf_interval[1]) { + if (area->min_spf_interval[0] + != MINIMUM_SPF_INTERVAL) { + vty_out(vty, " spf-interval %d\n", + area->min_spf_interval[0]); + write++; + } + } else { + if (area->min_spf_interval[0] + != MINIMUM_SPF_INTERVAL) { + vty_out(vty, + " spf-interval level-1 %d\n", + area->min_spf_interval[0]); + write++; + } + if (area->min_spf_interval[1] + != MINIMUM_SPF_INTERVAL) { + vty_out(vty, + " spf-interval level-2 %d\n", + area->min_spf_interval[1]); + write++; + } + } + + /* IETF SPF interval */ + if (area->spf_delay_ietf[0]) { + vty_out(vty, + " spf-delay-ietf init-delay %ld short-delay %ld long-delay %ld holddown %ld time-to-learn %ld\n", + spf_backoff_init_delay( + area->spf_delay_ietf[0]), + spf_backoff_short_delay( + area->spf_delay_ietf[0]), + spf_backoff_long_delay( + area->spf_delay_ietf[0]), + spf_backoff_holddown( + area->spf_delay_ietf[0]), + spf_backoff_timetolearn( + area->spf_delay_ietf[0])); + write++; + } + + /* Authentication passwords. */ + if (area->area_passwd.type + == ISIS_PASSWD_TYPE_HMAC_MD5) { + vty_out(vty, " area-password md5 %s", + area->area_passwd.passwd); + if (CHECK_FLAG(area->area_passwd.snp_auth, + SNP_AUTH_SEND)) { + vty_out(vty, " authenticate snp "); + if (CHECK_FLAG( + area->area_passwd.snp_auth, + SNP_AUTH_RECV)) + vty_out(vty, "validate"); + else + vty_out(vty, "send-only"); + } + vty_out(vty, "\n"); + write++; + } else if (area->area_passwd.type + == ISIS_PASSWD_TYPE_CLEARTXT) { + vty_out(vty, " area-password clear %s", + area->area_passwd.passwd); + if (CHECK_FLAG(area->area_passwd.snp_auth, + SNP_AUTH_SEND)) { + vty_out(vty, " authenticate snp "); + if (CHECK_FLAG( + area->area_passwd.snp_auth, + SNP_AUTH_RECV)) + vty_out(vty, "validate"); + else + vty_out(vty, "send-only"); + } + vty_out(vty, "\n"); + write++; + } + if (area->domain_passwd.type + == ISIS_PASSWD_TYPE_HMAC_MD5) { + vty_out(vty, " domain-password md5 %s", + area->domain_passwd.passwd); + if (CHECK_FLAG(area->domain_passwd.snp_auth, + SNP_AUTH_SEND)) { + vty_out(vty, " authenticate snp "); + if (CHECK_FLAG(area->domain_passwd + .snp_auth, + SNP_AUTH_RECV)) + vty_out(vty, "validate"); + else + vty_out(vty, "send-only"); + } + vty_out(vty, "\n"); + write++; + } else if (area->domain_passwd.type + == ISIS_PASSWD_TYPE_CLEARTXT) { + vty_out(vty, " domain-password clear %s", + area->domain_passwd.passwd); + if (CHECK_FLAG(area->domain_passwd.snp_auth, + SNP_AUTH_SEND)) { + vty_out(vty, " authenticate snp "); + if (CHECK_FLAG(area->domain_passwd + .snp_auth, + SNP_AUTH_RECV)) + vty_out(vty, "validate"); + else + vty_out(vty, "send-only"); + } + vty_out(vty, "\n"); + write++; + } + + if (area->log_adj_changes) { + vty_out(vty, " log-adjacency-changes\n"); + write++; + } + + write += area_write_mt_settings(area, vty); + } + isis_mpls_te_config_write_router(vty); + } + + return write; +} + +struct cmd_node isis_node = {ISIS_NODE, "%s(config-router)# ", 1}; + +void isis_init() +{ + /* Install IS-IS top node */ + install_node(&isis_node, isis_config_write); + + install_element(VIEW_NODE, &show_isis_summary_cmd); + + install_element(VIEW_NODE, &show_isis_spf_ietf_cmd); + + install_element(VIEW_NODE, &show_isis_interface_cmd); + install_element(VIEW_NODE, &show_isis_interface_detail_cmd); + install_element(VIEW_NODE, &show_isis_interface_arg_cmd); + + install_element(VIEW_NODE, &show_isis_neighbor_cmd); + install_element(VIEW_NODE, &show_isis_neighbor_detail_cmd); + install_element(VIEW_NODE, &show_isis_neighbor_arg_cmd); + install_element(VIEW_NODE, &clear_isis_neighbor_cmd); + install_element(VIEW_NODE, &clear_isis_neighbor_arg_cmd); + + install_element(VIEW_NODE, &show_hostname_cmd); + install_element(VIEW_NODE, &show_database_cmd); + + install_element(ENABLE_NODE, &show_debugging_isis_cmd); + + install_node(&debug_node, config_write_debug); + + install_element(ENABLE_NODE, &debug_isis_adj_cmd); + install_element(ENABLE_NODE, &no_debug_isis_adj_cmd); + install_element(ENABLE_NODE, &debug_isis_csum_cmd); + install_element(ENABLE_NODE, &no_debug_isis_csum_cmd); + install_element(ENABLE_NODE, &debug_isis_lupd_cmd); + install_element(ENABLE_NODE, &no_debug_isis_lupd_cmd); + install_element(ENABLE_NODE, &debug_isis_err_cmd); + install_element(ENABLE_NODE, &no_debug_isis_err_cmd); + install_element(ENABLE_NODE, &debug_isis_snp_cmd); + install_element(ENABLE_NODE, &no_debug_isis_snp_cmd); + install_element(ENABLE_NODE, &debug_isis_upd_cmd); + install_element(ENABLE_NODE, &no_debug_isis_upd_cmd); + install_element(ENABLE_NODE, &debug_isis_spfevents_cmd); + install_element(ENABLE_NODE, &no_debug_isis_spfevents_cmd); + install_element(ENABLE_NODE, &debug_isis_spfstats_cmd); + install_element(ENABLE_NODE, &no_debug_isis_spfstats_cmd); + install_element(ENABLE_NODE, &debug_isis_spftrigg_cmd); + install_element(ENABLE_NODE, &no_debug_isis_spftrigg_cmd); + install_element(ENABLE_NODE, &debug_isis_rtevents_cmd); + install_element(ENABLE_NODE, &no_debug_isis_rtevents_cmd); + install_element(ENABLE_NODE, &debug_isis_events_cmd); + install_element(ENABLE_NODE, &no_debug_isis_events_cmd); + install_element(ENABLE_NODE, &debug_isis_packet_dump_cmd); + install_element(ENABLE_NODE, &no_debug_isis_packet_dump_cmd); + install_element(ENABLE_NODE, &debug_isis_lsp_gen_cmd); + install_element(ENABLE_NODE, &no_debug_isis_lsp_gen_cmd); + install_element(ENABLE_NODE, &debug_isis_lsp_sched_cmd); + install_element(ENABLE_NODE, &no_debug_isis_lsp_sched_cmd); + + install_element(CONFIG_NODE, &debug_isis_adj_cmd); + install_element(CONFIG_NODE, &no_debug_isis_adj_cmd); + install_element(CONFIG_NODE, &debug_isis_csum_cmd); + install_element(CONFIG_NODE, &no_debug_isis_csum_cmd); + install_element(CONFIG_NODE, &debug_isis_lupd_cmd); + install_element(CONFIG_NODE, &no_debug_isis_lupd_cmd); + install_element(CONFIG_NODE, &debug_isis_err_cmd); + install_element(CONFIG_NODE, &no_debug_isis_err_cmd); + install_element(CONFIG_NODE, &debug_isis_snp_cmd); + install_element(CONFIG_NODE, &no_debug_isis_snp_cmd); + install_element(CONFIG_NODE, &debug_isis_upd_cmd); + install_element(CONFIG_NODE, &no_debug_isis_upd_cmd); + install_element(CONFIG_NODE, &debug_isis_spfevents_cmd); + install_element(CONFIG_NODE, &no_debug_isis_spfevents_cmd); + install_element(CONFIG_NODE, &debug_isis_spfstats_cmd); + install_element(CONFIG_NODE, &no_debug_isis_spfstats_cmd); + install_element(CONFIG_NODE, &debug_isis_spftrigg_cmd); + install_element(CONFIG_NODE, &no_debug_isis_spftrigg_cmd); + install_element(CONFIG_NODE, &debug_isis_rtevents_cmd); + install_element(CONFIG_NODE, &no_debug_isis_rtevents_cmd); + install_element(CONFIG_NODE, &debug_isis_events_cmd); + install_element(CONFIG_NODE, &no_debug_isis_events_cmd); + install_element(CONFIG_NODE, &debug_isis_packet_dump_cmd); + install_element(CONFIG_NODE, &no_debug_isis_packet_dump_cmd); + install_element(CONFIG_NODE, &debug_isis_lsp_gen_cmd); + install_element(CONFIG_NODE, &no_debug_isis_lsp_gen_cmd); + install_element(CONFIG_NODE, &debug_isis_lsp_sched_cmd); + install_element(CONFIG_NODE, &no_debug_isis_lsp_sched_cmd); + + install_element(CONFIG_NODE, &router_isis_cmd); + install_element(CONFIG_NODE, &no_router_isis_cmd); + + install_default(ISIS_NODE); + + install_element(ISIS_NODE, &net_cmd); + install_element(ISIS_NODE, &no_net_cmd); + + install_element(ISIS_NODE, &isis_topology_cmd); + install_element(ISIS_NODE, &no_isis_topology_cmd); + + install_element(ISIS_NODE, &log_adj_changes_cmd); + install_element(ISIS_NODE, &no_log_adj_changes_cmd); + + spf_backoff_cmd_init(); } diff --git a/isisd/isisd.h b/isisd/isisd.h index 9b6281866..1aacea881 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -1,18 +1,18 @@ /* - * IS-IS Rout(e)ing protocol - isisd.h + * IS-IS Rout(e)ing protocol - isisd.h * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -39,108 +39,110 @@ /* #define EXTREME_DEBUG */ /* #define EXTREME_TLV_DEBUG */ -struct isis -{ - u_long process_id; - int sysid_set; - u_char sysid[ISIS_SYS_ID_LEN]; /* SystemID for this IS */ - u_int32_t router_id; /* Router ID from zebra */ - struct list *area_list; /* list of IS-IS areas */ - struct list *init_circ_list; - struct list *nexthops; /* IPv4 next hops from this IS */ - struct list *nexthops6; /* IPv6 next hops from this IS */ - u_char max_area_addrs; /* maximumAreaAdresses */ - struct area_addr *man_area_addrs; /* manualAreaAddresses */ - u_int32_t debugs; /* bitmap for debug */ - time_t uptime; /* when did we start */ - struct thread *t_dync_clean; /* dynamic hostname cache cleanup thread */ - - struct route_table *ext_info[REDIST_PROTOCOL_COUNT]; - - QOBJ_FIELDS +struct isis { + u_long process_id; + int sysid_set; + u_char sysid[ISIS_SYS_ID_LEN]; /* SystemID for this IS */ + u_int32_t router_id; /* Router ID from zebra */ + struct list *area_list; /* list of IS-IS areas */ + struct list *init_circ_list; + struct list *nexthops; /* IPv4 next hops from this IS */ + struct list *nexthops6; /* IPv6 next hops from this IS */ + u_char max_area_addrs; /* maximumAreaAdresses */ + struct area_addr *man_area_addrs; /* manualAreaAddresses */ + u_int32_t debugs; /* bitmap for debug */ + time_t uptime; /* when did we start */ + struct thread *t_dync_clean; /* dynamic hostname cache cleanup thread */ + + struct route_table *ext_info[REDIST_PROTOCOL_COUNT]; + + QOBJ_FIELDS }; extern struct isis *isis; DECLARE_QOBJ_TYPE(isis_area) -struct isis_area -{ - struct isis *isis; /* back pointer */ - dict_t *lspdb[ISIS_LEVELS]; /* link-state dbs */ - struct isis_spftree *spftree[ISIS_LEVELS]; /* The v4 SPTs */ - struct route_table *route_table[ISIS_LEVELS]; /* IPv4 routes */ - struct isis_spftree *spftree6[ISIS_LEVELS]; /* The v6 SPTs */ - struct route_table *route_table6[ISIS_LEVELS]; /* IPv6 routes */ +struct isis_area { + struct isis *isis; /* back pointer */ + dict_t *lspdb[ISIS_LEVELS]; /* link-state dbs */ + struct isis_spftree *spftree[ISIS_LEVELS]; /* The v4 SPTs */ + struct route_table *route_table[ISIS_LEVELS]; /* IPv4 routes */ + struct isis_spftree *spftree6[ISIS_LEVELS]; /* The v6 SPTs */ + struct route_table *route_table6[ISIS_LEVELS]; /* IPv6 routes */ + /* $FRR indent$ */ +/* clang-format off */ #define DEFAULT_LSP_MTU 1497 - unsigned int lsp_mtu; /* Size of LSPs to generate */ - struct list *circuit_list; /* IS-IS circuits */ - struct flags flags; - struct thread *t_tick; /* LSP walker */ - struct thread *t_lsp_refresh[ISIS_LEVELS]; - /* t_lsp_refresh is used in two ways: - * a) regular refresh of LSPs - * b) (possibly throttled) updates to LSPs - * - * The lsp_regenerate_pending flag tracks whether the timer is active - * for the a) or the b) case. - * - * It is of utmost importance to clear this flag when the timer is - * rescheduled for normal refresh, because otherwise, updates will - * be delayed until the next regular refresh. - */ - int lsp_regenerate_pending[ISIS_LEVELS]; - - /* - * Configurables - */ - struct isis_passwd area_passwd; - struct isis_passwd domain_passwd; - /* do we support dynamic hostnames? */ - char dynhostname; - /* do we support new style metrics? */ - char newmetric; - char oldmetric; - /* identifies the routing instance */ - char *area_tag; - /* area addresses for this area */ - struct list *area_addrs; - u_int16_t max_lsp_lifetime[ISIS_LEVELS]; - char is_type; /* level-1 level-1-2 or level-2-only */ - /* are we overloaded? */ - char overload_bit; - /* L1/L2 router identifier for inter-area traffic */ - char attached_bit; - u_int16_t lsp_refresh[ISIS_LEVELS]; - /* minimum time allowed before lsp retransmission */ - u_int16_t lsp_gen_interval[ISIS_LEVELS]; - /* min interval between between consequtive SPFs */ - u_int16_t min_spf_interval[ISIS_LEVELS]; - /* the percentage of LSP mtu size used, before generating a new frag */ - int lsp_frag_threshold; - int ip_circuits; - /* logging adjacency changes? */ - u_char log_adj_changes; - /* multi topology settings */ - struct list *mt_settings; - int ipv6_circuits; - /* Counters */ - u_int32_t circuit_state_changes; - struct isis_redist redist_settings[REDIST_PROTOCOL_COUNT] - [ZEBRA_ROUTE_MAX + 1][ISIS_LEVELS]; - struct route_table *ext_reach[REDIST_PROTOCOL_COUNT][ISIS_LEVELS]; - - struct spf_backoff *spf_delay_ietf[ISIS_LEVELS]; /*Structure with IETF SPF algo parameters*/ - struct thread *spf_timer[ISIS_LEVELS]; - - QOBJ_FIELDS + unsigned int lsp_mtu; /* Size of LSPs to generate */ + struct list *circuit_list; /* IS-IS circuits */ + struct flags flags; + struct thread *t_tick; /* LSP walker */ + struct thread *t_lsp_refresh[ISIS_LEVELS]; + /* t_lsp_refresh is used in two ways: + * a) regular refresh of LSPs + * b) (possibly throttled) updates to LSPs + * + * The lsp_regenerate_pending flag tracks whether the timer is active + * for the a) or the b) case. + * + * It is of utmost importance to clear this flag when the timer is + * rescheduled for normal refresh, because otherwise, updates will + * be delayed until the next regular refresh. + */ + int lsp_regenerate_pending[ISIS_LEVELS]; + + /* + * Configurables + */ + struct isis_passwd area_passwd; + struct isis_passwd domain_passwd; + /* do we support dynamic hostnames? */ + char dynhostname; + /* do we support new style metrics? */ + char newmetric; + char oldmetric; + /* identifies the routing instance */ + char *area_tag; + /* area addresses for this area */ + struct list *area_addrs; + u_int16_t max_lsp_lifetime[ISIS_LEVELS]; + char is_type; /* level-1 level-1-2 or level-2-only */ + /* are we overloaded? */ + char overload_bit; + /* L1/L2 router identifier for inter-area traffic */ + char attached_bit; + u_int16_t lsp_refresh[ISIS_LEVELS]; + /* minimum time allowed before lsp retransmission */ + u_int16_t lsp_gen_interval[ISIS_LEVELS]; + /* min interval between between consequtive SPFs */ + u_int16_t min_spf_interval[ISIS_LEVELS]; + /* the percentage of LSP mtu size used, before generating a new frag */ + int lsp_frag_threshold; + int ip_circuits; + /* logging adjacency changes? */ + u_char log_adj_changes; + /* multi topology settings */ + struct list *mt_settings; + int ipv6_circuits; + /* Counters */ + u_int32_t circuit_state_changes; + struct isis_redist redist_settings[REDIST_PROTOCOL_COUNT] + [ZEBRA_ROUTE_MAX + 1][ISIS_LEVELS]; + struct route_table *ext_reach[REDIST_PROTOCOL_COUNT][ISIS_LEVELS]; + + struct spf_backoff *spf_delay_ietf[ISIS_LEVELS]; /*Structure with IETF + SPF algo + parameters*/ + struct thread *spf_timer[ISIS_LEVELS]; + + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(isis_area) -void isis_init (void); +void isis_init(void); void isis_new(unsigned long); struct isis_area *isis_area_create(const char *); -struct isis_area *isis_area_lookup (const char *); -int isis_area_get (struct vty *vty, const char *area_tag); +struct isis_area *isis_area_lookup(const char *); +int isis_area_get(struct vty *vty, const char *area_tag); void print_debug(struct vty *, int, int); void isis_area_overload_bit_set(struct isis_area *area, bool overload_bit); @@ -151,16 +153,16 @@ void isis_area_metricstyle_set(struct isis_area *area, bool old_metric, void isis_area_lsp_mtu_set(struct isis_area *area, unsigned int lsp_mtu); void isis_area_is_type_set(struct isis_area *area, int is_type); void isis_area_max_lsp_lifetime_set(struct isis_area *area, int level, - uint16_t max_lsp_lifetime); + uint16_t max_lsp_lifetime); void isis_area_lsp_refresh_set(struct isis_area *area, int level, uint16_t lsp_refresh); /* IS_LEVEL_1 sets area_passwd, IS_LEVEL_2 domain_passwd */ -int isis_area_passwd_unset (struct isis_area *area, int level); -int isis_area_passwd_cleartext_set (struct isis_area *area, int level, - const char *passwd, u_char snp_auth); -int isis_area_passwd_hmac_md5_set (struct isis_area *area, int level, - const char *passwd, u_char snp_auth); -void isis_vty_init (void); +int isis_area_passwd_unset(struct isis_area *area, int level); +int isis_area_passwd_cleartext_set(struct isis_area *area, int level, + const char *passwd, u_char snp_auth); +int isis_area_passwd_hmac_md5_set(struct isis_area *area, int level, + const char *passwd, u_char snp_auth); +void isis_vty_init(void); /* Master of threads. */ extern struct thread_master *master; @@ -181,21 +183,17 @@ extern struct thread_master *master; #define DEBUG_LSP_GEN (1<<13) #define DEBUG_LSP_SCHED (1<<14) -#define lsp_debug(...) \ - do \ - { \ - if (isis->debugs & DEBUG_LSP_GEN) \ - zlog_debug(__VA_ARGS__); \ - } \ - while (0) - -#define sched_debug(...) \ - do \ - { \ - if (isis->debugs & DEBUG_LSP_SCHED) \ - zlog_debug(__VA_ARGS__); \ - } \ - while (0) +#define lsp_debug(...) \ + do { \ + if (isis->debugs & DEBUG_LSP_GEN) \ + zlog_debug(__VA_ARGS__); \ + } while (0) + +#define sched_debug(...) \ + do { \ + if (isis->debugs & DEBUG_LSP_SCHED) \ + zlog_debug(__VA_ARGS__); \ + } while (0) #define DEBUG_TE (1<<13) diff --git a/isisd/iso_checksum.c b/isisd/iso_checksum.c index 70b6b91ed..e0a4ba370 100644 --- a/isisd/iso_checksum.c +++ b/isisd/iso_checksum.c @@ -3,17 +3,17 @@ * ISO checksum related routines * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -33,7 +33,7 @@ * sum a (mod 255) = 0 * 1 i * - * L + * L * sum (L-i+1)a (mod 255) = 0 * 1 i * @@ -45,30 +45,29 @@ * Based on Annex C.4 of ISO/IEC 8473 */ -int -iso_csum_verify (u_char * buffer, int len, uint16_t csum, int offset) +int iso_csum_verify(u_char *buffer, int len, uint16_t csum, int offset) { - u_int16_t checksum; - u_int32_t c0; - u_int32_t c1; + u_int16_t checksum; + u_int32_t c0; + u_int32_t c1; - c0 = csum & 0xff00; - c1 = csum & 0x00ff; + c0 = csum & 0xff00; + c1 = csum & 0x00ff; - /* - * If both are zero return correct - */ - if (c0 == 0 && c1 == 0) - return 0; + /* + * If both are zero return correct + */ + if (c0 == 0 && c1 == 0) + return 0; - /* - * If either, but not both are zero return incorrect - */ - if (c0 == 0 || c1 == 0) - return 1; + /* + * If either, but not both are zero return incorrect + */ + if (c0 == 0 || c1 == 0) + return 1; - checksum = fletcher_checksum(buffer, len, offset); - if (checksum == csum) - return 0; - return 1; + checksum = fletcher_checksum(buffer, len, offset); + if (checksum == csum) + return 0; + return 1; } diff --git a/isisd/iso_checksum.h b/isisd/iso_checksum.h index 50f6a7d56..5ba371fb4 100644 --- a/isisd/iso_checksum.h +++ b/isisd/iso_checksum.h @@ -3,17 +3,17 @@ * ISO checksum related routines * * Copyright (C) 2001,2002 Sampo Saaristo - * Tampere University of Technology + * Tampere University of Technology * Institute of Communications Engineering * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public Licenseas published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * - * This program is distributed in the hope that it will be useful,but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -23,6 +23,6 @@ #ifndef _ZEBRA_ISO_CSUM_H #define _ZEBRA_ISO_CSUM_H -int iso_csum_verify (u_char * buffer, int len, uint16_t csum, int offset); +int iso_csum_verify(u_char *buffer, int len, uint16_t csum, int offset); #endif /* _ZEBRA_ISO_CSUM_H */ diff --git a/lib/agentx.c b/lib/agentx.c index 30c03e6cf..f8845f146 100644 --- a/lib/agentx.c +++ b/lib/agentx.c @@ -40,136 +40,140 @@ static struct list *events = NULL; static void agentx_events_update(void); -static int -agentx_timeout(struct thread *t) +static int agentx_timeout(struct thread *t) { - timeout_thr = NULL; + timeout_thr = NULL; - snmp_timeout (); - run_alarms (); - netsnmp_check_outstanding_agent_requests (); - agentx_events_update (); - return 0; + snmp_timeout(); + run_alarms(); + netsnmp_check_outstanding_agent_requests(); + agentx_events_update(); + return 0; } -static int -agentx_read(struct thread *t) +static int agentx_read(struct thread *t) { - fd_set fds; - struct listnode *ln = THREAD_ARG (t); - list_delete_node (events, ln); + fd_set fds; + struct listnode *ln = THREAD_ARG(t); + list_delete_node(events, ln); - FD_ZERO (&fds); - FD_SET (THREAD_FD (t), &fds); - snmp_read (&fds); + FD_ZERO(&fds); + FD_SET(THREAD_FD(t), &fds); + snmp_read(&fds); - netsnmp_check_outstanding_agent_requests (); - agentx_events_update (); - return 0; + netsnmp_check_outstanding_agent_requests(); + agentx_events_update(); + return 0; } -static void -agentx_events_update(void) +static void agentx_events_update(void) { - int maxfd = 0; - int block = 1; - struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 }; - fd_set fds; - struct listnode *ln; - struct thread *thr; - int fd, thr_fd; - - THREAD_OFF (timeout_thr); - - FD_ZERO (&fds); - snmp_select_info (&maxfd, &fds, &timeout, &block); - - if (!block) { - timeout_thr = NULL; - thread_add_timer_tv(agentx_tm, agentx_timeout, NULL, &timeout, - &timeout_thr); - } - - ln = listhead (events); - thr = ln ? listgetdata (ln) : NULL; - thr_fd = thr ? THREAD_FD (thr) : -1; - - /* "two-pointer" / two-list simultaneous iteration - * ln/thr/thr_fd point to the next existing event listener to hit while - * fd counts to catch up */ - for (fd = 0; fd < maxfd; fd++) - { - /* caught up */ - if (thr_fd == fd) - { - struct listnode *nextln = listnextnode (ln); - if (!FD_ISSET (fd, &fds)) - { - thread_cancel (thr); - list_delete_node (events, ln); - } - ln = nextln; - thr = ln ? listgetdata (ln) : NULL; - thr_fd = thr ? THREAD_FD (thr) : -1; - } - /* need listener, but haven't hit one where it would be */ - else if (FD_ISSET (fd, &fds)) - { - struct listnode *newln; - thr = NULL; - thread_add_read(agentx_tm, agentx_read, NULL, fd, &thr); - newln = listnode_add_before (events, ln, thr); - thr->arg = newln; - } - } - - /* leftover event listeners at this point have fd > maxfd, delete them */ - while (ln) - { - struct listnode *nextln = listnextnode (ln); - thread_cancel (listgetdata (ln)); - list_delete_node (events, ln); - ln = nextln; - } + int maxfd = 0; + int block = 1; + struct timeval timeout = {.tv_sec = 0, .tv_usec = 0}; + fd_set fds; + struct listnode *ln; + struct thread *thr; + int fd, thr_fd; + + THREAD_OFF(timeout_thr); + + FD_ZERO(&fds); + snmp_select_info(&maxfd, &fds, &timeout, &block); + + if (!block) { + timeout_thr = NULL; + thread_add_timer_tv(agentx_tm, agentx_timeout, NULL, &timeout, + &timeout_thr); + } + + ln = listhead(events); + thr = ln ? listgetdata(ln) : NULL; + thr_fd = thr ? THREAD_FD(thr) : -1; + + /* "two-pointer" / two-list simultaneous iteration + * ln/thr/thr_fd point to the next existing event listener to hit while + * fd counts to catch up */ + for (fd = 0; fd < maxfd; fd++) { + /* caught up */ + if (thr_fd == fd) { + struct listnode *nextln = listnextnode(ln); + if (!FD_ISSET(fd, &fds)) { + thread_cancel(thr); + list_delete_node(events, ln); + } + ln = nextln; + thr = ln ? listgetdata(ln) : NULL; + thr_fd = thr ? THREAD_FD(thr) : -1; + } + /* need listener, but haven't hit one where it would be */ + else if (FD_ISSET(fd, &fds)) { + struct listnode *newln; + thr = NULL; + thread_add_read(agentx_tm, agentx_read, NULL, fd, &thr); + newln = listnode_add_before(events, ln, thr); + thr->arg = newln; + } + } + + /* leftover event listeners at this point have fd > maxfd, delete them + */ + while (ln) { + struct listnode *nextln = listnextnode(ln); + thread_cancel(listgetdata(ln)); + list_delete_node(events, ln); + ln = nextln; + } } /* AgentX node. */ -static struct cmd_node agentx_node = -{ - SMUX_NODE, - "", /* AgentX has no interface. */ - 1 -}; +static struct cmd_node agentx_node = {SMUX_NODE, + "", /* AgentX has no interface. */ + 1}; /* Logging NetSNMP messages */ -static int -agentx_log_callback(int major, int minor, - void *serverarg, void *clientarg) +static int agentx_log_callback(int major, int minor, void *serverarg, + void *clientarg) { - struct snmp_log_message *slm = (struct snmp_log_message *)serverarg; - char *msg = XSTRDUP(MTYPE_TMP, slm->msg); - if (msg) msg[strlen(msg)-1] = '\0'; - switch (slm->priority) - { - case LOG_EMERG: zlog_err ("snmp[emerg]: %s", msg?msg:slm->msg); break; - case LOG_ALERT: zlog_err ("snmp[alert]: %s", msg?msg:slm->msg); break; - case LOG_CRIT: zlog_err ("snmp[crit]: %s", msg?msg:slm->msg); break; - case LOG_ERR: zlog_err ("snmp[err]: %s", msg?msg:slm->msg); break; - case LOG_WARNING: zlog_warn ("snmp[warning]: %s", msg?msg:slm->msg); break; - case LOG_NOTICE: zlog_notice("snmp[notice]: %s", msg?msg:slm->msg); break; - case LOG_INFO: zlog_info ("snmp[info]: %s", msg?msg:slm->msg); break; - case LOG_DEBUG: zlog_debug ("snmp[debug]: %s", msg?msg:slm->msg); break; - } - XFREE(MTYPE_TMP, msg); - return SNMP_ERR_NOERROR; + struct snmp_log_message *slm = (struct snmp_log_message *)serverarg; + char *msg = XSTRDUP(MTYPE_TMP, slm->msg); + if (msg) + msg[strlen(msg) - 1] = '\0'; + switch (slm->priority) { + case LOG_EMERG: + zlog_err("snmp[emerg]: %s", msg ? msg : slm->msg); + break; + case LOG_ALERT: + zlog_err("snmp[alert]: %s", msg ? msg : slm->msg); + break; + case LOG_CRIT: + zlog_err("snmp[crit]: %s", msg ? msg : slm->msg); + break; + case LOG_ERR: + zlog_err("snmp[err]: %s", msg ? msg : slm->msg); + break; + case LOG_WARNING: + zlog_warn("snmp[warning]: %s", msg ? msg : slm->msg); + break; + case LOG_NOTICE: + zlog_notice("snmp[notice]: %s", msg ? msg : slm->msg); + break; + case LOG_INFO: + zlog_info("snmp[info]: %s", msg ? msg : slm->msg); + break; + case LOG_DEBUG: + zlog_debug("snmp[debug]: %s", msg ? msg : slm->msg); + break; + } + XFREE(MTYPE_TMP, msg); + return SNMP_ERR_NOERROR; } -static int -config_write_agentx (struct vty *vty) +static int config_write_agentx(struct vty *vty) { - if (agentx_enabled) - vty_out (vty, "agentx\n"); - return 1; + if (agentx_enabled) + vty_out(vty, "agentx\n"); + return 1; } DEFUN (agentx_enable, @@ -177,16 +181,15 @@ DEFUN (agentx_enable, "agentx", "SNMP AgentX protocol settings\n") { - if (!agentx_enabled) - { - init_snmp(FRR_SMUX_NAME); - events = list_new(); - agentx_events_update (); - agentx_enabled = 1; - return CMD_SUCCESS; - } - vty_out (vty, "SNMP AgentX already enabled\n"); - return CMD_SUCCESS; + if (!agentx_enabled) { + init_snmp(FRR_SMUX_NAME); + events = list_new(); + agentx_events_update(); + agentx_enabled = 1; + return CMD_SUCCESS; + } + vty_out(vty, "SNMP AgentX already enabled\n"); + return CMD_SUCCESS; } DEFUN (no_agentx, @@ -195,126 +198,119 @@ DEFUN (no_agentx, NO_STR "SNMP AgentX protocol settings\n") { - if (!agentx_enabled) return CMD_SUCCESS; - vty_out (vty, "SNMP AgentX support cannot be disabled once enabled\n"); - return CMD_WARNING_CONFIG_FAILED; + if (!agentx_enabled) + return CMD_SUCCESS; + vty_out(vty, "SNMP AgentX support cannot be disabled once enabled\n"); + return CMD_WARNING_CONFIG_FAILED; } -void -smux_init (struct thread_master *tm) +void smux_init(struct thread_master *tm) { - agentx_tm = tm; - - netsnmp_enable_subagent (); - snmp_disable_log (); - snmp_enable_calllog (); - snmp_register_callback (SNMP_CALLBACK_LIBRARY, - SNMP_CALLBACK_LOGGING, - agentx_log_callback, - NULL); - init_agent (FRR_SMUX_NAME); - - install_node (&agentx_node, config_write_agentx); - install_element (CONFIG_NODE, &agentx_enable_cmd); - install_element (CONFIG_NODE, &no_agentx_cmd); + agentx_tm = tm; + + netsnmp_enable_subagent(); + snmp_disable_log(); + snmp_enable_calllog(); + snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_LOGGING, + agentx_log_callback, NULL); + init_agent(FRR_SMUX_NAME); + + install_node(&agentx_node, config_write_agentx); + install_element(CONFIG_NODE, &agentx_enable_cmd); + install_element(CONFIG_NODE, &no_agentx_cmd); } -void -smux_register_mib (const char *descr, struct variable *var, - size_t width, int num, - oid name[], size_t namelen) +void smux_register_mib(const char *descr, struct variable *var, size_t width, + int num, oid name[], size_t namelen) { - register_mib (descr, var, width, num, name, namelen); + register_mib(descr, var, width, num, name, namelen); } -int -smux_trap (struct variable *vp, size_t vp_len, - const oid *ename, size_t enamelen, - const oid *name, size_t namelen, - const oid *iname, size_t inamelen, - const struct trap_object *trapobj, size_t trapobjlen, - u_char sptrap) +int smux_trap(struct variable *vp, size_t vp_len, const oid *ename, + size_t enamelen, const oid *name, size_t namelen, + const oid *iname, size_t inamelen, + const struct trap_object *trapobj, size_t trapobjlen, + u_char sptrap) { - oid objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 }; - size_t objid_snmptrap_len = sizeof objid_snmptrap / sizeof (oid); - oid notification_oid[MAX_OID_LEN]; - size_t notification_oid_len; - unsigned int i; - - netsnmp_variable_list *notification_vars = NULL; - if (!agentx_enabled) return 0; - - /* snmpTrapOID */ - oid_copy (notification_oid, ename, enamelen); - notification_oid[enamelen] = sptrap; - notification_oid_len = enamelen + 1; - snmp_varlist_add_variable (¬ification_vars, - objid_snmptrap, objid_snmptrap_len, - ASN_OBJECT_ID, - (u_char *) notification_oid, - notification_oid_len * sizeof(oid)); - - /* Provided bindings */ - for (i = 0; i < trapobjlen; i++) - { - unsigned int j; - oid oid[MAX_OID_LEN]; - size_t oid_len, onamelen; - u_char *val; - size_t val_len; - WriteMethod *wm = NULL; - struct variable cvp; - - /* Make OID. */ - if (trapobj[i].namelen > 0) - { - /* Columnar object */ - onamelen = trapobj[i].namelen; - oid_copy (oid, name, namelen); - oid_copy (oid + namelen, trapobj[i].name, onamelen); - oid_copy (oid + namelen + onamelen, iname, inamelen); - oid_len = namelen + onamelen + inamelen; - } - else - { - /* Scalar object */ - onamelen = trapobj[i].namelen * (-1); - oid_copy (oid, name, namelen); - oid_copy (oid + namelen, trapobj[i].name, onamelen); - oid[onamelen + namelen] = 0; - oid_len = namelen + onamelen + 1; - } - - /* Locate the appropriate function and type in the MIB registry. */ - for (j = 0; j < vp_len; j++) - { - if (oid_compare (trapobj[i].name, onamelen, vp[j].name, vp[j].namelen) != 0) - continue; - /* We found the appropriate variable in the MIB registry. */ - oid_copy(cvp.name, name, namelen); - oid_copy(cvp.name + namelen, vp[j].name, vp[j].namelen); - cvp.namelen = namelen + vp[j].namelen; - cvp.type = vp[j].type; - cvp.magic = vp[j].magic; - cvp.acl = vp[j].acl; - cvp.findVar = vp[j].findVar; - /* Grab the result. */ - val = cvp.findVar (&cvp, oid, &oid_len, 1, &val_len, &wm); - if (!val) break; - snmp_varlist_add_variable (¬ification_vars, - oid, oid_len, - vp[j].type, - val, - val_len); - break; + oid objid_snmptrap[] = {1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0}; + size_t objid_snmptrap_len = sizeof objid_snmptrap / sizeof(oid); + oid notification_oid[MAX_OID_LEN]; + size_t notification_oid_len; + unsigned int i; + + netsnmp_variable_list *notification_vars = NULL; + if (!agentx_enabled) + return 0; + + /* snmpTrapOID */ + oid_copy(notification_oid, ename, enamelen); + notification_oid[enamelen] = sptrap; + notification_oid_len = enamelen + 1; + snmp_varlist_add_variable(¬ification_vars, objid_snmptrap, + objid_snmptrap_len, ASN_OBJECT_ID, + (u_char *)notification_oid, + notification_oid_len * sizeof(oid)); + + /* Provided bindings */ + for (i = 0; i < trapobjlen; i++) { + unsigned int j; + oid oid[MAX_OID_LEN]; + size_t oid_len, onamelen; + u_char *val; + size_t val_len; + WriteMethod *wm = NULL; + struct variable cvp; + + /* Make OID. */ + if (trapobj[i].namelen > 0) { + /* Columnar object */ + onamelen = trapobj[i].namelen; + oid_copy(oid, name, namelen); + oid_copy(oid + namelen, trapobj[i].name, onamelen); + oid_copy(oid + namelen + onamelen, iname, inamelen); + oid_len = namelen + onamelen + inamelen; + } else { + /* Scalar object */ + onamelen = trapobj[i].namelen * (-1); + oid_copy(oid, name, namelen); + oid_copy(oid + namelen, trapobj[i].name, onamelen); + oid[onamelen + namelen] = 0; + oid_len = namelen + onamelen + 1; + } + + /* Locate the appropriate function and type in the MIB registry. + */ + for (j = 0; j < vp_len; j++) { + if (oid_compare(trapobj[i].name, onamelen, vp[j].name, + vp[j].namelen) + != 0) + continue; + /* We found the appropriate variable in the MIB + * registry. */ + oid_copy(cvp.name, name, namelen); + oid_copy(cvp.name + namelen, vp[j].name, vp[j].namelen); + cvp.namelen = namelen + vp[j].namelen; + cvp.type = vp[j].type; + cvp.magic = vp[j].magic; + cvp.acl = vp[j].acl; + cvp.findVar = vp[j].findVar; + /* Grab the result. */ + val = cvp.findVar(&cvp, oid, &oid_len, 1, &val_len, + &wm); + if (!val) + break; + snmp_varlist_add_variable(¬ification_vars, oid, + oid_len, vp[j].type, val, + val_len); + break; + } } - } - send_v2trap (notification_vars); - snmp_free_varbind (notification_vars); - agentx_events_update (); - return 1; + send_v2trap(notification_vars); + snmp_free_varbind(notification_vars); + agentx_events_update(); + return 1; } #endif /* SNMP_AGENTX */ diff --git a/lib/bfd.c b/lib/bfd.c index 4fbb93ebd..e8df42a1b 100644 --- a/lib/bfd.c +++ b/lib/bfd.c @@ -40,466 +40,432 @@ struct bfd_gbl bfd_gbl; /* * bfd_gbl_init - Initialize the BFD global structure */ -void -bfd_gbl_init(void) +void bfd_gbl_init(void) { - memset(&bfd_gbl, 0, sizeof (struct bfd_gbl)); + memset(&bfd_gbl, 0, sizeof(struct bfd_gbl)); } /* * bfd_gbl_exit - Called when daemon exits */ -void -bfd_gbl_exit(void) +void bfd_gbl_exit(void) { - SET_FLAG (bfd_gbl.flags, BFD_GBL_FLAG_IN_SHUTDOWN); + SET_FLAG(bfd_gbl.flags, BFD_GBL_FLAG_IN_SHUTDOWN); } /* * bfd_info_create - Allocate the BFD information */ -struct bfd_info * -bfd_info_create(void) +struct bfd_info *bfd_info_create(void) { - struct bfd_info *bfd_info; + struct bfd_info *bfd_info; - bfd_info = XCALLOC (MTYPE_BFD_INFO, sizeof (struct bfd_info)); - assert(bfd_info); + bfd_info = XCALLOC(MTYPE_BFD_INFO, sizeof(struct bfd_info)); + assert(bfd_info); - bfd_info->status = BFD_STATUS_UNKNOWN; - bfd_info->type = BFD_TYPE_NOT_CONFIGURED; - bfd_info->last_update = 0; - return bfd_info; + bfd_info->status = BFD_STATUS_UNKNOWN; + bfd_info->type = BFD_TYPE_NOT_CONFIGURED; + bfd_info->last_update = 0; + return bfd_info; } /* * bfd_info_free - Free the BFD information. */ -void -bfd_info_free(struct bfd_info **bfd_info) +void bfd_info_free(struct bfd_info **bfd_info) { - if (*bfd_info) - { - XFREE (MTYPE_BFD_INFO, *bfd_info); - *bfd_info = NULL; - } + if (*bfd_info) { + XFREE(MTYPE_BFD_INFO, *bfd_info); + *bfd_info = NULL; + } } /* * bfd_validate_param - Validate the BFD paramter information. */ -int -bfd_validate_param(struct vty *vty, const char *dm_str, const char *rx_str, - const char *tx_str, u_int8_t *dm_val, u_int32_t *rx_val, - u_int32_t *tx_val) +int bfd_validate_param(struct vty *vty, const char *dm_str, const char *rx_str, + const char *tx_str, u_int8_t *dm_val, u_int32_t *rx_val, + u_int32_t *tx_val) { - *dm_val = strtoul(dm_str, NULL, 10); - *rx_val = strtoul(rx_str, NULL, 10); - *tx_val = strtoul(tx_str, NULL, 10); - return CMD_SUCCESS; + *dm_val = strtoul(dm_str, NULL, 10); + *rx_val = strtoul(rx_str, NULL, 10); + *tx_val = strtoul(tx_str, NULL, 10); + return CMD_SUCCESS; } /* * bfd_set_param - Set the configured BFD paramter values */ -void -bfd_set_param (struct bfd_info **bfd_info, u_int32_t min_rx, u_int32_t min_tx, - u_int8_t detect_mult, int defaults, int *command) +void bfd_set_param(struct bfd_info **bfd_info, u_int32_t min_rx, + u_int32_t min_tx, u_int8_t detect_mult, int defaults, + int *command) { - if (!*bfd_info) - { - *bfd_info = bfd_info_create(); - *command = ZEBRA_BFD_DEST_REGISTER; - } - else - { - if (((*bfd_info)->required_min_rx != min_rx) || - ((*bfd_info)->desired_min_tx != min_tx) || - ((*bfd_info)->detect_mult != detect_mult)) - *command = ZEBRA_BFD_DEST_UPDATE; - } - - if (*command) - { - (*bfd_info)->required_min_rx = min_rx; - (*bfd_info)->desired_min_tx = min_tx; - (*bfd_info)->detect_mult = detect_mult; - } - - if (!defaults) - SET_FLAG ((*bfd_info)->flags, BFD_FLAG_PARAM_CFG); - else - UNSET_FLAG ((*bfd_info)->flags, BFD_FLAG_PARAM_CFG); + if (!*bfd_info) { + *bfd_info = bfd_info_create(); + *command = ZEBRA_BFD_DEST_REGISTER; + } else { + if (((*bfd_info)->required_min_rx != min_rx) + || ((*bfd_info)->desired_min_tx != min_tx) + || ((*bfd_info)->detect_mult != detect_mult)) + *command = ZEBRA_BFD_DEST_UPDATE; + } + + if (*command) { + (*bfd_info)->required_min_rx = min_rx; + (*bfd_info)->desired_min_tx = min_tx; + (*bfd_info)->detect_mult = detect_mult; + } + + if (!defaults) + SET_FLAG((*bfd_info)->flags, BFD_FLAG_PARAM_CFG); + else + UNSET_FLAG((*bfd_info)->flags, BFD_FLAG_PARAM_CFG); } /* * bfd_peer_sendmsg - Format and send a peer register/Unregister * command to Zebra to be forwarded to BFD */ -void -bfd_peer_sendmsg (struct zclient *zclient, struct bfd_info *bfd_info, - int family, void *dst_ip, void *src_ip, char *if_name, - int ttl, int multihop, int command, int set_flag, - vrf_id_t vrf_id) +void bfd_peer_sendmsg(struct zclient *zclient, struct bfd_info *bfd_info, + int family, void *dst_ip, void *src_ip, char *if_name, + int ttl, int multihop, int command, int set_flag, + vrf_id_t vrf_id) { - struct stream *s; - int ret; - int len; - - /* Individual reg/dereg messages are supressed during shutdown. */ - if (CHECK_FLAG (bfd_gbl.flags, BFD_GBL_FLAG_IN_SHUTDOWN)) - { - if (bfd_debug) - zlog_debug("%s: Suppressing BFD peer reg/dereg messages", __FUNCTION__); - return; - } - - /* Check socket. */ - if (!zclient || zclient->sock < 0) - { - if (bfd_debug) - zlog_debug("%s: Can't send BFD peer register, Zebra client not " - "established", __FUNCTION__); - return; - } - - s = zclient->obuf; - stream_reset (s); - zclient_create_header (s, command, vrf_id); - - stream_putl(s, getpid()); - - stream_putw(s, family); - switch (family) - { - case AF_INET: - stream_put_in_addr (s, (struct in_addr *)dst_ip); - break; - case AF_INET6: - stream_put(s, dst_ip, 16); - break; - default: - break; - } - - if (command != ZEBRA_BFD_DEST_DEREGISTER) - { - stream_putl(s, bfd_info->required_min_rx); - stream_putl(s, bfd_info->desired_min_tx); - stream_putc(s, bfd_info->detect_mult); - } - - if (multihop) - { - stream_putc(s, 1); - /* Multi-hop destination send the source IP address to BFD */ - if (src_ip) - { - stream_putw(s, family); - switch (family) - { - case AF_INET: - stream_put_in_addr (s, (struct in_addr *) src_ip); - break; - case AF_INET6: - stream_put(s, src_ip, 16); - break; - default: - break; - } - } - stream_putc(s, ttl); - } - else - { - stream_putc(s, 0); - if ((family == AF_INET6) && (src_ip)) - { - stream_putw(s, family); - stream_put(s, src_ip, 16); - } - if (if_name) - { - len = strlen(if_name); - stream_putc(s, len); - stream_put(s, if_name, len); - } - else - { - stream_putc(s, 0); - } - } - - stream_putw_at (s, 0, stream_get_endp (s)); - - ret = zclient_send_message(zclient); - - if (ret < 0) - { - if (bfd_debug) - zlog_debug("bfd_peer_sendmsg: zclient_send_message() failed"); - return; - } - - if (set_flag) - { - if (command == ZEBRA_BFD_DEST_REGISTER) - SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG); - else if (command == ZEBRA_BFD_DEST_DEREGISTER) - UNSET_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG); - } - - return; + struct stream *s; + int ret; + int len; + + /* Individual reg/dereg messages are supressed during shutdown. */ + if (CHECK_FLAG(bfd_gbl.flags, BFD_GBL_FLAG_IN_SHUTDOWN)) { + if (bfd_debug) + zlog_debug( + "%s: Suppressing BFD peer reg/dereg messages", + __FUNCTION__); + return; + } + + /* Check socket. */ + if (!zclient || zclient->sock < 0) { + if (bfd_debug) + zlog_debug( + "%s: Can't send BFD peer register, Zebra client not " + "established", + __FUNCTION__); + return; + } + + s = zclient->obuf; + stream_reset(s); + zclient_create_header(s, command, vrf_id); + + stream_putl(s, getpid()); + + stream_putw(s, family); + switch (family) { + case AF_INET: + stream_put_in_addr(s, (struct in_addr *)dst_ip); + break; + case AF_INET6: + stream_put(s, dst_ip, 16); + break; + default: + break; + } + + if (command != ZEBRA_BFD_DEST_DEREGISTER) { + stream_putl(s, bfd_info->required_min_rx); + stream_putl(s, bfd_info->desired_min_tx); + stream_putc(s, bfd_info->detect_mult); + } + + if (multihop) { + stream_putc(s, 1); + /* Multi-hop destination send the source IP address to BFD */ + if (src_ip) { + stream_putw(s, family); + switch (family) { + case AF_INET: + stream_put_in_addr(s, (struct in_addr *)src_ip); + break; + case AF_INET6: + stream_put(s, src_ip, 16); + break; + default: + break; + } + } + stream_putc(s, ttl); + } else { + stream_putc(s, 0); + if ((family == AF_INET6) && (src_ip)) { + stream_putw(s, family); + stream_put(s, src_ip, 16); + } + if (if_name) { + len = strlen(if_name); + stream_putc(s, len); + stream_put(s, if_name, len); + } else { + stream_putc(s, 0); + } + } + + stream_putw_at(s, 0, stream_get_endp(s)); + + ret = zclient_send_message(zclient); + + if (ret < 0) { + if (bfd_debug) + zlog_debug( + "bfd_peer_sendmsg: zclient_send_message() failed"); + return; + } + + if (set_flag) { + if (command == ZEBRA_BFD_DEST_REGISTER) + SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG); + else if (command == ZEBRA_BFD_DEST_DEREGISTER) + UNSET_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG); + } + + return; } /* * bfd_get_command_dbg_str - Convert command to a debug string. */ -const char * -bfd_get_command_dbg_str(int command) +const char *bfd_get_command_dbg_str(int command) { - switch (command) - { - case ZEBRA_BFD_DEST_REGISTER: - return "Register"; - case ZEBRA_BFD_DEST_DEREGISTER: - return "Deregister"; - case ZEBRA_BFD_DEST_UPDATE: - return "Update"; - default: - return "Unknown"; - } + switch (command) { + case ZEBRA_BFD_DEST_REGISTER: + return "Register"; + case ZEBRA_BFD_DEST_DEREGISTER: + return "Deregister"; + case ZEBRA_BFD_DEST_UPDATE: + return "Update"; + default: + return "Unknown"; + } } /* * bfd_get_peer_info - Extract the Peer information for which the BFD session * went down from the message sent from Zebra to clients. */ -struct interface * -bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp, - int *status, vrf_id_t vrf_id) +struct interface *bfd_get_peer_info(struct stream *s, struct prefix *dp, + struct prefix *sp, int *status, + vrf_id_t vrf_id) { - unsigned int ifindex; - struct interface *ifp = NULL; - int plen; - - /* Get interface index. */ - ifindex = stream_getl (s); - - /* Lookup index. */ - if (ifindex != 0) - { - ifp = if_lookup_by_index (ifindex, vrf_id); - if (ifp == NULL) - { - if (bfd_debug) - zlog_debug ("zebra_interface_bfd_read: " - "Can't find interface by ifindex: %d ", ifindex); - return NULL; - } - } - - /* Fetch destination address. */ - dp->family = stream_getc (s); - - plen = prefix_blen (dp); - stream_get (&dp->u.prefix, s, plen); - dp->prefixlen = stream_getc (s); - - /* Get BFD status. */ - *status = stream_getl (s); - - if (sp) - { - sp->family = stream_getc (s); - - plen = prefix_blen (sp); - stream_get (&sp->u.prefix, s, plen); - sp->prefixlen = stream_getc (s); - } - return ifp; + unsigned int ifindex; + struct interface *ifp = NULL; + int plen; + + /* Get interface index. */ + ifindex = stream_getl(s); + + /* Lookup index. */ + if (ifindex != 0) { + ifp = if_lookup_by_index(ifindex, vrf_id); + if (ifp == NULL) { + if (bfd_debug) + zlog_debug( + "zebra_interface_bfd_read: " + "Can't find interface by ifindex: %d ", + ifindex); + return NULL; + } + } + + /* Fetch destination address. */ + dp->family = stream_getc(s); + + plen = prefix_blen(dp); + stream_get(&dp->u.prefix, s, plen); + dp->prefixlen = stream_getc(s); + + /* Get BFD status. */ + *status = stream_getl(s); + + if (sp) { + sp->family = stream_getc(s); + + plen = prefix_blen(sp); + stream_get(&sp->u.prefix, s, plen); + sp->prefixlen = stream_getc(s); + } + return ifp; } /* * bfd_get_status_str - Convert BFD status to a display string. */ -const char * -bfd_get_status_str(int status) +const char *bfd_get_status_str(int status) { - switch (status) - { - case BFD_STATUS_DOWN: - return "Down"; - case BFD_STATUS_UP: - return "Up"; - case BFD_STATUS_UNKNOWN: - default: - return "Unknown"; - } + switch (status) { + case BFD_STATUS_DOWN: + return "Down"; + case BFD_STATUS_UP: + return "Up"; + case BFD_STATUS_UNKNOWN: + default: + return "Unknown"; + } } /* * bfd_last_update - Calculate the last BFD update time and convert it * into a dd:hh:mm:ss display format. */ -static void -bfd_last_update (time_t last_update, char *buf, size_t len) +static void bfd_last_update(time_t last_update, char *buf, size_t len) { - time_t curr; - time_t diff; - struct tm *tm; - struct timeval tv; - - /* If no BFD satatus update has ever been received, print `never'. */ - if (last_update == 0) - { - snprintf (buf, len, "never"); - return; - } - - /* Get current time. */ - monotime(&tv); - curr = tv.tv_sec; - diff = curr - last_update; - tm = gmtime (&diff); - - snprintf (buf, len, "%d:%02d:%02d:%02d", - tm->tm_yday, tm->tm_hour, tm->tm_min, tm->tm_sec); + time_t curr; + time_t diff; + struct tm *tm; + struct timeval tv; + + /* If no BFD satatus update has ever been received, print `never'. */ + if (last_update == 0) { + snprintf(buf, len, "never"); + return; + } + + /* Get current time. */ + monotime(&tv); + curr = tv.tv_sec; + diff = curr - last_update; + tm = gmtime(&diff); + + snprintf(buf, len, "%d:%02d:%02d:%02d", tm->tm_yday, tm->tm_hour, + tm->tm_min, tm->tm_sec); } /* * bfd_show_param - Show the BFD parameter information. */ -void -bfd_show_param(struct vty *vty, struct bfd_info *bfd_info, int bfd_tag, - int extra_space, u_char use_json, json_object *json_obj) +void bfd_show_param(struct vty *vty, struct bfd_info *bfd_info, int bfd_tag, + int extra_space, u_char use_json, json_object *json_obj) { - json_object *json_bfd = NULL; - - if (!bfd_info) - return; - - if (use_json) - { - if (bfd_tag) - json_bfd = json_object_new_object(); - else - json_bfd = json_obj; - - json_object_int_add(json_bfd, "detectMultiplier", bfd_info->detect_mult); - json_object_int_add(json_bfd, "rxMinInterval", bfd_info->required_min_rx); - json_object_int_add(json_bfd, "txMinInterval", bfd_info->desired_min_tx); - if (bfd_tag) - json_object_object_add(json_obj, "peerBfdInfo", json_bfd); - } - else - { - vty_out (vty, " %s%sDetect Mul: %d, Min Rx interval: %d," - " Min Tx interval: %d\n", - (extra_space) ? " ": "", (bfd_tag) ? "BFD: " : " ", - bfd_info->detect_mult, bfd_info->required_min_rx, - bfd_info->desired_min_tx); - } + json_object *json_bfd = NULL; + + if (!bfd_info) + return; + + if (use_json) { + if (bfd_tag) + json_bfd = json_object_new_object(); + else + json_bfd = json_obj; + + json_object_int_add(json_bfd, "detectMultiplier", + bfd_info->detect_mult); + json_object_int_add(json_bfd, "rxMinInterval", + bfd_info->required_min_rx); + json_object_int_add(json_bfd, "txMinInterval", + bfd_info->desired_min_tx); + if (bfd_tag) + json_object_object_add(json_obj, "peerBfdInfo", + json_bfd); + } else { + vty_out(vty, + " %s%sDetect Mul: %d, Min Rx interval: %d," + " Min Tx interval: %d\n", + (extra_space) ? " " : "", (bfd_tag) ? "BFD: " : " ", + bfd_info->detect_mult, bfd_info->required_min_rx, + bfd_info->desired_min_tx); + } } /* * bfd_show_status - Show the BFD status information. */ -static void -bfd_show_status(struct vty *vty, struct bfd_info *bfd_info, int bfd_tag, - int extra_space, u_char use_json, json_object *json_bfd) +static void bfd_show_status(struct vty *vty, struct bfd_info *bfd_info, + int bfd_tag, int extra_space, u_char use_json, + json_object *json_bfd) { - char time_buf[32]; - - if (!bfd_info) - return; - - bfd_last_update(bfd_info->last_update, time_buf, 32); - if (use_json) - { - json_object_string_add(json_bfd, "status", - bfd_get_status_str(bfd_info->status)); - json_object_string_add(json_bfd, "lastUpdate", time_buf); - } - else - { - vty_out (vty, " %s%sStatus: %s, Last update: %s\n", - (extra_space) ? " ": "", (bfd_tag) ? "BFD: " : " ", - bfd_get_status_str(bfd_info->status), time_buf); - } + char time_buf[32]; + + if (!bfd_info) + return; + + bfd_last_update(bfd_info->last_update, time_buf, 32); + if (use_json) { + json_object_string_add(json_bfd, "status", + bfd_get_status_str(bfd_info->status)); + json_object_string_add(json_bfd, "lastUpdate", time_buf); + } else { + vty_out(vty, " %s%sStatus: %s, Last update: %s\n", + (extra_space) ? " " : "", (bfd_tag) ? "BFD: " : " ", + bfd_get_status_str(bfd_info->status), time_buf); + } } /* * bfd_show_info - Show the BFD information. */ -void -bfd_show_info(struct vty *vty, struct bfd_info *bfd_info, int multihop, - int extra_space, u_char use_json, json_object *json_obj) +void bfd_show_info(struct vty *vty, struct bfd_info *bfd_info, int multihop, + int extra_space, u_char use_json, json_object *json_obj) { - json_object *json_bfd = NULL; - - if (!bfd_info) - return; - - if (use_json) - { - json_bfd = json_object_new_object(); - if (multihop) - json_object_string_add(json_bfd, "type", "multi hop"); - else - json_object_string_add(json_bfd, "type", "single hop"); - } - else - { - vty_out (vty, " %sBFD: Type: %s\n", (extra_space) ? " " : "", - (multihop) ? "multi hop" : "single hop"); - } - - bfd_show_param(vty, bfd_info, 0, extra_space, use_json, json_bfd); - bfd_show_status(vty, bfd_info, 0, extra_space, use_json, json_bfd); - - if (use_json) - json_object_object_add(json_obj, "peerBfdInfo", json_bfd); - else - vty_out (vty, "\n"); + json_object *json_bfd = NULL; + + if (!bfd_info) + return; + + if (use_json) { + json_bfd = json_object_new_object(); + if (multihop) + json_object_string_add(json_bfd, "type", "multi hop"); + else + json_object_string_add(json_bfd, "type", "single hop"); + } else { + vty_out(vty, " %sBFD: Type: %s\n", (extra_space) ? " " : "", + (multihop) ? "multi hop" : "single hop"); + } + + bfd_show_param(vty, bfd_info, 0, extra_space, use_json, json_bfd); + bfd_show_status(vty, bfd_info, 0, extra_space, use_json, json_bfd); + + if (use_json) + json_object_object_add(json_obj, "peerBfdInfo", json_bfd); + else + vty_out(vty, "\n"); } /* * bfd_client_sendmsg - Format and send a client register * command to Zebra to be forwarded to BFD */ -void -bfd_client_sendmsg (struct zclient *zclient, int command) +void bfd_client_sendmsg(struct zclient *zclient, int command) { - struct stream *s; - int ret; - - /* Check socket. */ - if (!zclient || zclient->sock < 0) - { - if (bfd_debug) - zlog_debug ("%s: Can't send BFD client register, Zebra client not " - "established", __FUNCTION__); - return; - } - - s = zclient->obuf; - stream_reset (s); - zclient_create_header (s, command, VRF_DEFAULT); - - stream_putl(s, getpid()); - - stream_putw_at (s, 0, stream_get_endp (s)); - - ret = zclient_send_message(zclient); - - if (ret < 0) - { - if (bfd_debug) - zlog_debug ("bfd_client_sendmsg %ld: zclient_send_message() failed", - (long) getpid()); - return; - } - - return; + struct stream *s; + int ret; + + /* Check socket. */ + if (!zclient || zclient->sock < 0) { + if (bfd_debug) + zlog_debug( + "%s: Can't send BFD client register, Zebra client not " + "established", + __FUNCTION__); + return; + } + + s = zclient->obuf; + stream_reset(s); + zclient_create_header(s, command, VRF_DEFAULT); + + stream_putl(s, getpid()); + + stream_putw_at(s, 0, stream_get_endp(s)); + + ret = zclient_send_message(zclient); + + if (ret < 0) { + if (bfd_debug) + zlog_debug( + "bfd_client_sendmsg %ld: zclient_send_message() failed", + (long)getpid()); + return; + } + + return; } diff --git a/lib/bfd.h b/lib/bfd.h index f23ff3bd8..6afb99442 100644 --- a/lib/bfd.h +++ b/lib/bfd.h @@ -36,9 +36,8 @@ #define BFD_MAX_DETECT_MULT 255 #define BFD_GBL_FLAG_IN_SHUTDOWN (1 << 0) /* The daemon in shutdown */ -struct bfd_gbl -{ - u_int16_t flags; +struct bfd_gbl { + u_int16_t flags; }; #define BFD_FLAG_PARAM_CFG (1 << 0) /* parameters have been configured */ @@ -50,67 +49,58 @@ struct bfd_gbl #define BFD_STATUS_UP (1 << 2) /* BFD session status is up */ enum bfd_sess_type { - BFD_TYPE_NOT_CONFIGURED, - BFD_TYPE_SINGLEHOP, - BFD_TYPE_MULTIHOP + BFD_TYPE_NOT_CONFIGURED, + BFD_TYPE_SINGLEHOP, + BFD_TYPE_MULTIHOP }; -struct bfd_info -{ - u_int16_t flags; - u_int8_t detect_mult; - u_int32_t desired_min_tx; - u_int32_t required_min_rx; - time_t last_update; - u_int8_t status; - enum bfd_sess_type type; +struct bfd_info { + u_int16_t flags; + u_int8_t detect_mult; + u_int32_t desired_min_tx; + u_int32_t required_min_rx; + time_t last_update; + u_int8_t status; + enum bfd_sess_type type; }; -extern struct bfd_info * -bfd_info_create(void); +extern struct bfd_info *bfd_info_create(void); -extern void -bfd_info_free(struct bfd_info **bfd_info); +extern void bfd_info_free(struct bfd_info **bfd_info); -extern int -bfd_validate_param(struct vty *vty, const char *dm_str, const char *rx_str, - const char *tx_str, u_int8_t *dm_val, u_int32_t *rx_val, - u_int32_t *tx_val); +extern int bfd_validate_param(struct vty *vty, const char *dm_str, + const char *rx_str, const char *tx_str, + u_int8_t *dm_val, u_int32_t *rx_val, + u_int32_t *tx_val); -extern void -bfd_set_param (struct bfd_info **bfd_info, u_int32_t min_rx, u_int32_t min_tx, - u_int8_t detect_mult, int defaults, int *command); -extern void -bfd_peer_sendmsg (struct zclient *zclient, struct bfd_info *bfd_info, - int family, void *dst_ip, void *src_ip, char *if_name, - int ttl, int multihop, int command, int set_flag, - vrf_id_t vrf_id); +extern void bfd_set_param(struct bfd_info **bfd_info, u_int32_t min_rx, + u_int32_t min_tx, u_int8_t detect_mult, int defaults, + int *command); +extern void bfd_peer_sendmsg(struct zclient *zclient, struct bfd_info *bfd_info, + int family, void *dst_ip, void *src_ip, + char *if_name, int ttl, int multihop, int command, + int set_flag, vrf_id_t vrf_id); -extern const char * -bfd_get_command_dbg_str(int command); +extern const char *bfd_get_command_dbg_str(int command); -extern struct interface * -bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp, - int *status, vrf_id_t vrf_id); +extern struct interface *bfd_get_peer_info(struct stream *s, struct prefix *dp, + struct prefix *sp, int *status, + vrf_id_t vrf_id); -const char * -bfd_get_status_str(int status); +const char *bfd_get_status_str(int status); -extern void -bfd_show_param(struct vty *vty, struct bfd_info *bfd_info, int bfd_tag, - int extra_space, u_char use_json, json_object *json_obj); +extern void bfd_show_param(struct vty *vty, struct bfd_info *bfd_info, + int bfd_tag, int extra_space, u_char use_json, + json_object *json_obj); -extern void -bfd_show_info(struct vty *vty, struct bfd_info *bfd_info, int multihop, - int extra_space, u_char use_json, json_object *json_obj); +extern void bfd_show_info(struct vty *vty, struct bfd_info *bfd_info, + int multihop, int extra_space, u_char use_json, + json_object *json_obj); -extern void -bfd_client_sendmsg (struct zclient *zclient, int command); +extern void bfd_client_sendmsg(struct zclient *zclient, int command); -extern void -bfd_gbl_init(void); +extern void bfd_gbl_init(void); -extern void -bfd_gbl_exit(void); +extern void bfd_gbl_exit(void); #endif /* _ZEBRA_BFD_H */ diff --git a/lib/bitfield.h b/lib/bitfield.h index 1e0b54731..0e031ccc4 100644 --- a/lib/bitfield.h +++ b/lib/bitfield.h @@ -62,42 +62,41 @@ typedef unsigned int word_t; * @N: number of bits to start with, which equates to how many * IDs can be allocated. */ -#define bf_init(v, N) \ - do { \ - (v).n = 0; \ - (v).m = ((N) / WORD_SIZE + 1); \ - (v).data = calloc(1, ((v).m * sizeof(word_t))); \ - } while (0) +#define bf_init(v, N) \ + do { \ + (v).n = 0; \ + (v).m = ((N) / WORD_SIZE + 1); \ + (v).data = calloc(1, ((v).m * sizeof(word_t))); \ + } while (0) /** * allocate and assign an id from bitfield v. */ -#define bf_assign_index(v, id) \ - do { \ - bf_find_bit(v, id); \ - bf_set_bit(v, id); \ - } while (0) +#define bf_assign_index(v, id) \ + do { \ + bf_find_bit(v, id); \ + bf_set_bit(v, id); \ + } while (0) /* * allocate and assign 0th bit in the bitfiled. */ -#define bf_assign_zero_index(v) \ - do { \ - int id = 0; \ - bf_assign_index(v, id); \ - } while (0) +#define bf_assign_zero_index(v) \ + do { \ + int id = 0; \ + bf_assign_index(v, id); \ + } while (0) /* * return an id to bitfield v */ -#define bf_release_index(v, id) \ - (v).data[bf_index(id)] &= ~(1 << (bf_offset(id))) +#define bf_release_index(v, id) \ + (v).data[bf_index(id)] &= ~(1 << (bf_offset(id))) /* * return 0th index back to bitfield */ -#define bf_release_zero_index(v) \ - bf_release_index(v, 0) +#define bf_release_zero_index(v) bf_release_index(v, 0) #define bf_index(b) ((b) / WORD_SIZE) #define bf_offset(b) ((b) % WORD_SIZE) @@ -106,42 +105,52 @@ typedef unsigned int word_t; * Set a bit in the array. If it fills up that word and we are * out of words, extend it by one more word. */ -#define bf_set_bit(v, b) \ - do { \ - size_t w = bf_index(b); \ - (v).data[w] |= 1 << (bf_offset(b)); \ - (v).n += ((v).data[w] == WORD_MAX); \ - if ((v).n == (v).m) { \ - (v).m = (v).m + 1; \ - (v).data = realloc((v).data, (v).m * sizeof(word_t)); \ - } \ - } while (0) +#define bf_set_bit(v, b) \ + do { \ + size_t w = bf_index(b); \ + (v).data[w] |= 1 << (bf_offset(b)); \ + (v).n += ((v).data[w] == WORD_MAX); \ + if ((v).n == (v).m) { \ + (v).m = (v).m + 1; \ + (v).data = realloc((v).data, (v).m * sizeof(word_t)); \ + } \ + } while (0) /* Find a clear bit in v and assign it to b. */ -#define bf_find_bit(v, b) \ - do { \ - word_t word = 0; \ - unsigned int w, sh; \ - for (w = 0; w <= (v).n; w++) { \ - if ((word = (v).data[w]) != WORD_MAX) break; \ - } \ - (b) = ((word & 0xFFFF) == 0xFFFF) << 4; word >>= (b); \ - sh = ((word & 0xFF) == 0xFF) << 3; word >>= sh; (b) |= sh; \ - sh = ((word & 0xF) == 0xF) << 2; word >>= sh; (b) |= sh; \ - sh = ((word & 0x3) == 0x3) << 1; word >>= sh; (b) |= sh; \ - sh = ((word & 0x1) == 0x1) << 0; word >>= sh; (b) |= sh; \ - (b) += (w * WORD_SIZE); \ - } while (0) +#define bf_find_bit(v, b) \ + do { \ + word_t word = 0; \ + unsigned int w, sh; \ + for (w = 0; w <= (v).n; w++) { \ + if ((word = (v).data[w]) != WORD_MAX) \ + break; \ + } \ + (b) = ((word & 0xFFFF) == 0xFFFF) << 4; \ + word >>= (b); \ + sh = ((word & 0xFF) == 0xFF) << 3; \ + word >>= sh; \ + (b) |= sh; \ + sh = ((word & 0xF) == 0xF) << 2; \ + word >>= sh; \ + (b) |= sh; \ + sh = ((word & 0x3) == 0x3) << 1; \ + word >>= sh; \ + (b) |= sh; \ + sh = ((word & 0x1) == 0x1) << 0; \ + word >>= sh; \ + (b) |= sh; \ + (b) += (w * WORD_SIZE); \ + } while (0) /* * Free the allocated memory for data * @v: an instance of bitfield_t struct. */ -#define bf_free(v) \ - do { \ - if ((v).data) { \ - free((v).data); \ - } \ - } while (0) +#define bf_free(v) \ + do { \ + if ((v).data) { \ + free((v).data); \ + } \ + } while (0) #endif diff --git a/lib/buffer.c b/lib/buffer.c index 5d458901e..a7c4fe4f2 100644 --- a/lib/buffer.c +++ b/lib/buffer.c @@ -1,5 +1,5 @@ /* - * Buffering of output and input. + * Buffering of output and input. * Copyright (C) 1998 Kunihiro Ishiguro * * This file is part of GNU Zebra. @@ -27,33 +27,31 @@ #include "network.h" #include -DEFINE_MTYPE_STATIC(LIB, BUFFER, "Buffer") +DEFINE_MTYPE_STATIC(LIB, BUFFER, "Buffer") DEFINE_MTYPE_STATIC(LIB, BUFFER_DATA, "Buffer data") /* Buffer master. */ -struct buffer -{ - /* Data list. */ - struct buffer_data *head; - struct buffer_data *tail; - - /* Size of each buffer_data chunk. */ - size_t size; +struct buffer { + /* Data list. */ + struct buffer_data *head; + struct buffer_data *tail; + + /* Size of each buffer_data chunk. */ + size_t size; }; /* Data container. */ -struct buffer_data -{ - struct buffer_data *next; +struct buffer_data { + struct buffer_data *next; - /* Location to add new data. */ - size_t cp; + /* Location to add new data. */ + size_t cp; - /* Pointer to data not yet flushed. */ - size_t sp; + /* Pointer to data not yet flushed. */ + size_t sp; - /* Actual data stream (variable length). */ - unsigned char data[]; /* real dimension is buffer->size */ + /* Actual data stream (variable length). */ + unsigned char data[]; /* real dimension is buffer->size */ }; /* It should always be true that: 0 <= sp <= cp <= size */ @@ -62,371 +60,349 @@ struct buffer_data next page boundery. */ #define BUFFER_SIZE_DEFAULT 4096 - #define BUFFER_DATA_FREE(D) XFREE(MTYPE_BUFFER_DATA, (D)) /* Make new buffer. */ -struct buffer * -buffer_new (size_t size) +struct buffer *buffer_new(size_t size) { - struct buffer *b; - - b = XCALLOC (MTYPE_BUFFER, sizeof (struct buffer)); - - if (size) - b->size = size; - else - { - static size_t default_size; - if (!default_size) - { - long pgsz = sysconf(_SC_PAGESIZE); - default_size = ((((BUFFER_SIZE_DEFAULT-1)/pgsz)+1)*pgsz); + struct buffer *b; + + b = XCALLOC(MTYPE_BUFFER, sizeof(struct buffer)); + + if (size) + b->size = size; + else { + static size_t default_size; + if (!default_size) { + long pgsz = sysconf(_SC_PAGESIZE); + default_size = ((((BUFFER_SIZE_DEFAULT - 1) / pgsz) + 1) + * pgsz); + } + b->size = default_size; } - b->size = default_size; - } - return b; + return b; } /* Free buffer. */ -void -buffer_free (struct buffer *b) +void buffer_free(struct buffer *b) { - buffer_reset(b); - XFREE (MTYPE_BUFFER, b); + buffer_reset(b); + XFREE(MTYPE_BUFFER, b); } /* Make string clone. */ -char * -buffer_getstr (struct buffer *b) +char *buffer_getstr(struct buffer *b) { - size_t totlen = 0; - struct buffer_data *data; - char *s; - char *p; - - for (data = b->head; data; data = data->next) - totlen += data->cp - data->sp; - if (!(s = XMALLOC(MTYPE_TMP, totlen+1))) - return NULL; - p = s; - for (data = b->head; data; data = data->next) - { - memcpy(p, data->data + data->sp, data->cp - data->sp); - p += data->cp - data->sp; - } - *p = '\0'; - return s; + size_t totlen = 0; + struct buffer_data *data; + char *s; + char *p; + + for (data = b->head; data; data = data->next) + totlen += data->cp - data->sp; + if (!(s = XMALLOC(MTYPE_TMP, totlen + 1))) + return NULL; + p = s; + for (data = b->head; data; data = data->next) { + memcpy(p, data->data + data->sp, data->cp - data->sp); + p += data->cp - data->sp; + } + *p = '\0'; + return s; } /* Return 1 if buffer is empty. */ -int -buffer_empty (struct buffer *b) +int buffer_empty(struct buffer *b) { - return (b->head == NULL); + return (b->head == NULL); } /* Clear and free all allocated data. */ -void -buffer_reset (struct buffer *b) +void buffer_reset(struct buffer *b) { - struct buffer_data *data; - struct buffer_data *next; - - for (data = b->head; data; data = next) - { - next = data->next; - BUFFER_DATA_FREE(data); - } - b->head = b->tail = NULL; + struct buffer_data *data; + struct buffer_data *next; + + for (data = b->head; data; data = next) { + next = data->next; + BUFFER_DATA_FREE(data); + } + b->head = b->tail = NULL; } /* Add buffer_data to the end of buffer. */ -static struct buffer_data * -buffer_add (struct buffer *b) +static struct buffer_data *buffer_add(struct buffer *b) { - struct buffer_data *d; + struct buffer_data *d; - d = XMALLOC(MTYPE_BUFFER_DATA, offsetof(struct buffer_data, data) + b->size); - d->cp = d->sp = 0; - d->next = NULL; + d = XMALLOC(MTYPE_BUFFER_DATA, + offsetof(struct buffer_data, data) + b->size); + d->cp = d->sp = 0; + d->next = NULL; - if (b->tail) - b->tail->next = d; - else - b->head = d; - b->tail = d; + if (b->tail) + b->tail->next = d; + else + b->head = d; + b->tail = d; - return d; + return d; } /* Write data to buffer. */ -void -buffer_put(struct buffer *b, const void *p, size_t size) +void buffer_put(struct buffer *b, const void *p, size_t size) { - struct buffer_data *data = b->tail; - const char *ptr = p; - - /* We use even last one byte of data buffer. */ - while (size) - { - size_t chunk; - - /* If there is no data buffer add it. */ - if (data == NULL || data->cp == b->size) - data = buffer_add (b); - - chunk = ((size <= (b->size - data->cp)) ? size : (b->size - data->cp)); - memcpy ((data->data + data->cp), ptr, chunk); - size -= chunk; - ptr += chunk; - data->cp += chunk; - } + struct buffer_data *data = b->tail; + const char *ptr = p; + + /* We use even last one byte of data buffer. */ + while (size) { + size_t chunk; + + /* If there is no data buffer add it. */ + if (data == NULL || data->cp == b->size) + data = buffer_add(b); + + chunk = ((size <= (b->size - data->cp)) ? size + : (b->size - data->cp)); + memcpy((data->data + data->cp), ptr, chunk); + size -= chunk; + ptr += chunk; + data->cp += chunk; + } } /* Insert character into the buffer. */ -void -buffer_putc (struct buffer *b, u_char c) +void buffer_putc(struct buffer *b, u_char c) { - buffer_put(b, &c, 1); + buffer_put(b, &c, 1); } /* Put string to the buffer. */ -void -buffer_putstr (struct buffer *b, const char *c) +void buffer_putstr(struct buffer *b, const char *c) { - buffer_put(b, c, strlen(c)); + buffer_put(b, c, strlen(c)); } /* Expand \n to \r\n */ -void -buffer_put_crlf(struct buffer *b, const void *origp, size_t origsize) +void buffer_put_crlf(struct buffer *b, const void *origp, size_t origsize) { - struct buffer_data *data = b->tail; - const char *p = origp, *end = p + origsize, *lf; - size_t size; - - lf = memchr(p, '\n', end - p); - - /* We use even last one byte of data buffer. */ - while (p < end) - { - size_t avail, chunk; - - /* If there is no data buffer add it. */ - if (data == NULL || data->cp == b->size) - data = buffer_add (b); - - size = (lf ? lf : end) - p; - avail = b->size - data->cp; - - chunk = (size <= avail) ? size : avail; - memcpy (data->data + data->cp, p, chunk); - - p += chunk; - data->cp += chunk; - - if (lf && size <= avail) - { - /* we just copied up to (including) a '\n' */ - if (data->cp == b->size) - data = buffer_add (b); - data->data[data->cp++] = '\r'; - if (data->cp == b->size) - data = buffer_add (b); - data->data[data->cp++] = '\n'; - - p++; - lf = memchr(p, '\n', end - p); - } - } + struct buffer_data *data = b->tail; + const char *p = origp, *end = p + origsize, *lf; + size_t size; + + lf = memchr(p, '\n', end - p); + + /* We use even last one byte of data buffer. */ + while (p < end) { + size_t avail, chunk; + + /* If there is no data buffer add it. */ + if (data == NULL || data->cp == b->size) + data = buffer_add(b); + + size = (lf ? lf : end) - p; + avail = b->size - data->cp; + + chunk = (size <= avail) ? size : avail; + memcpy(data->data + data->cp, p, chunk); + + p += chunk; + data->cp += chunk; + + if (lf && size <= avail) { + /* we just copied up to (including) a '\n' */ + if (data->cp == b->size) + data = buffer_add(b); + data->data[data->cp++] = '\r'; + if (data->cp == b->size) + data = buffer_add(b); + data->data[data->cp++] = '\n'; + + p++; + lf = memchr(p, '\n', end - p); + } + } } /* Keep flushing data to the fd until the buffer is empty or an error is encountered or the operation would block. */ -buffer_status_t -buffer_flush_all (struct buffer *b, int fd) +buffer_status_t buffer_flush_all(struct buffer *b, int fd) { - buffer_status_t ret; - struct buffer_data *head; - size_t head_sp; - - if (!b->head) - return BUFFER_EMPTY; - head_sp = (head = b->head)->sp; - /* Flush all data. */ - while ((ret = buffer_flush_available(b, fd)) == BUFFER_PENDING) - { - if ((b->head == head) && (head_sp == head->sp) && (errno != EINTR)) - /* No data was flushed, so kernel buffer must be full. */ - return ret; - head_sp = (head = b->head)->sp; - } + buffer_status_t ret; + struct buffer_data *head; + size_t head_sp; + + if (!b->head) + return BUFFER_EMPTY; + head_sp = (head = b->head)->sp; + /* Flush all data. */ + while ((ret = buffer_flush_available(b, fd)) == BUFFER_PENDING) { + if ((b->head == head) && (head_sp == head->sp) + && (errno != EINTR)) + /* No data was flushed, so kernel buffer must be full. + */ + return ret; + head_sp = (head = b->head)->sp; + } - return ret; + return ret; } /* Flush enough data to fill a terminal window of the given scene (used only by vty telnet interface). */ -buffer_status_t -buffer_flush_window (struct buffer *b, int fd, int width, int height, - int erase_flag, int no_more_flag) +buffer_status_t buffer_flush_window(struct buffer *b, int fd, int width, + int height, int erase_flag, + int no_more_flag) { - int nbytes; - int iov_alloc; - int iov_index; - struct iovec *iov; - struct iovec small_iov[3]; - char more[] = " --More-- "; - char erase[] = { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; - struct buffer_data *data; - int column; - - if (!b->head) - return BUFFER_EMPTY; - - if (height < 1) - { - zlog_warn("%s called with non-positive window height %d, forcing to 1", - __func__, height); - height = 1; - } - else if (height >= 2) - height--; - if (width < 1) - { - zlog_warn("%s called with non-positive window width %d, forcing to 1", - __func__, width); - width = 1; - } - - /* For erase and more data add two to b's buffer_data count.*/ - if (b->head->next == NULL) - { - iov_alloc = array_size(small_iov); - iov = small_iov; - } - else - { - iov_alloc = ((height*(width+2))/b->size)+10; - iov = XMALLOC(MTYPE_TMP, iov_alloc*sizeof(*iov)); - } - iov_index = 0; - - /* Previously print out is performed. */ - if (erase_flag) - { - iov[iov_index].iov_base = erase; - iov[iov_index].iov_len = sizeof erase; - iov_index++; - } - - /* Output data. */ - column = 1; /* Column position of next character displayed. */ - for (data = b->head; data && (height > 0); data = data->next) - { - size_t cp; - - cp = data->sp; - while ((cp < data->cp) && (height > 0)) - { - /* Calculate lines remaining and column position after displaying - this character. */ - if (data->data[cp] == '\r') - column = 1; - else if ((data->data[cp] == '\n') || (column == width)) - { - column = 1; - height--; - } - else - column++; - cp++; - } - iov[iov_index].iov_base = (char *)(data->data + data->sp); - iov[iov_index++].iov_len = cp-data->sp; - data->sp = cp; - - if (iov_index == iov_alloc) - /* This should not ordinarily happen. */ - { - iov_alloc *= 2; - if (iov != small_iov) - { - zlog_warn("%s: growing iov array to %d; " - "width %d, height %d, size %lu", - __func__, iov_alloc, width, height, (u_long)b->size); - iov = XREALLOC(MTYPE_TMP, iov, iov_alloc*sizeof(*iov)); - } - else - { - /* This should absolutely never occur. */ - zlog_err("%s: corruption detected: iov_small overflowed; " - "head %p, tail %p, head->next %p", - __func__, (void *)b->head, (void *)b->tail, - (void *)b->head->next); - iov = XMALLOC(MTYPE_TMP, iov_alloc*sizeof(*iov)); - memcpy(iov, small_iov, sizeof(small_iov)); - } + int nbytes; + int iov_alloc; + int iov_index; + struct iovec *iov; + struct iovec small_iov[3]; + char more[] = " --More-- "; + char erase[] = {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ', ' ', 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; + struct buffer_data *data; + int column; + + if (!b->head) + return BUFFER_EMPTY; + + if (height < 1) { + zlog_warn( + "%s called with non-positive window height %d, forcing to 1", + __func__, height); + height = 1; + } else if (height >= 2) + height--; + if (width < 1) { + zlog_warn( + "%s called with non-positive window width %d, forcing to 1", + __func__, width); + width = 1; } - } - /* In case of `more' display need. */ - if (b->tail && (b->tail->sp < b->tail->cp) && !no_more_flag) - { - iov[iov_index].iov_base = more; - iov[iov_index].iov_len = sizeof more; - iov_index++; - } + /* For erase and more data add two to b's buffer_data count.*/ + if (b->head->next == NULL) { + iov_alloc = array_size(small_iov); + iov = small_iov; + } else { + iov_alloc = ((height * (width + 2)) / b->size) + 10; + iov = XMALLOC(MTYPE_TMP, iov_alloc * sizeof(*iov)); + } + iov_index = 0; + + /* Previously print out is performed. */ + if (erase_flag) { + iov[iov_index].iov_base = erase; + iov[iov_index].iov_len = sizeof erase; + iov_index++; + } + + /* Output data. */ + column = 1; /* Column position of next character displayed. */ + for (data = b->head; data && (height > 0); data = data->next) { + size_t cp; + + cp = data->sp; + while ((cp < data->cp) && (height > 0)) { + /* Calculate lines remaining and column position after + displaying + this character. */ + if (data->data[cp] == '\r') + column = 1; + else if ((data->data[cp] == '\n') + || (column == width)) { + column = 1; + height--; + } else + column++; + cp++; + } + iov[iov_index].iov_base = (char *)(data->data + data->sp); + iov[iov_index++].iov_len = cp - data->sp; + data->sp = cp; + + if (iov_index == iov_alloc) + /* This should not ordinarily happen. */ + { + iov_alloc *= 2; + if (iov != small_iov) { + zlog_warn( + "%s: growing iov array to %d; " + "width %d, height %d, size %lu", + __func__, iov_alloc, width, height, + (u_long)b->size); + iov = XREALLOC(MTYPE_TMP, iov, + iov_alloc * sizeof(*iov)); + } else { + /* This should absolutely never occur. */ + zlog_err( + "%s: corruption detected: iov_small overflowed; " + "head %p, tail %p, head->next %p", + __func__, (void *)b->head, + (void *)b->tail, (void *)b->head->next); + iov = XMALLOC(MTYPE_TMP, + iov_alloc * sizeof(*iov)); + memcpy(iov, small_iov, sizeof(small_iov)); + } + } + } + + /* In case of `more' display need. */ + if (b->tail && (b->tail->sp < b->tail->cp) && !no_more_flag) { + iov[iov_index].iov_base = more; + iov[iov_index].iov_len = sizeof more; + iov_index++; + } #ifdef IOV_MAX - /* IOV_MAX are normally defined in , Posix.1g. - example: Solaris2.6 are defined IOV_MAX size at 16. */ - { - struct iovec *c_iov = iov; - nbytes = 0; /* Make sure it's initialized. */ - - while (iov_index > 0) - { - int iov_size; - - iov_size = ((iov_index > IOV_MAX) ? IOV_MAX : iov_index); - if ((nbytes = writev(fd, c_iov, iov_size)) < 0) - { - zlog_warn("%s: writev to fd %d failed: %s", - __func__, fd, safe_strerror(errno)); - break; - } - - /* move pointer io-vector */ - c_iov += iov_size; - iov_index -= iov_size; - } - } + /* IOV_MAX are normally defined in , Posix.1g. + example: Solaris2.6 are defined IOV_MAX size at 16. */ + { + struct iovec *c_iov = iov; + nbytes = 0; /* Make sure it's initialized. */ + + while (iov_index > 0) { + int iov_size; + + iov_size = + ((iov_index > IOV_MAX) ? IOV_MAX : iov_index); + if ((nbytes = writev(fd, c_iov, iov_size)) < 0) { + zlog_warn("%s: writev to fd %d failed: %s", + __func__, fd, safe_strerror(errno)); + break; + } + + /* move pointer io-vector */ + c_iov += iov_size; + iov_index -= iov_size; + } + } #else /* IOV_MAX */ - if ((nbytes = writev (fd, iov, iov_index)) < 0) - zlog_warn("%s: writev to fd %d failed: %s", - __func__, fd, safe_strerror(errno)); + if ((nbytes = writev(fd, iov, iov_index)) < 0) + zlog_warn("%s: writev to fd %d failed: %s", __func__, fd, + safe_strerror(errno)); #endif /* IOV_MAX */ - /* Free printed buffer data. */ - while (b->head && (b->head->sp == b->head->cp)) - { - struct buffer_data *del; - if (!(b->head = (del = b->head)->next)) - b->tail = NULL; - BUFFER_DATA_FREE(del); - } + /* Free printed buffer data. */ + while (b->head && (b->head->sp == b->head->cp)) { + struct buffer_data *del; + if (!(b->head = (del = b->head)->next)) + b->tail = NULL; + BUFFER_DATA_FREE(del); + } - if (iov != small_iov) - XFREE (MTYPE_TMP, iov); + if (iov != small_iov) + XFREE(MTYPE_TMP, iov); - return (nbytes < 0) ? BUFFER_ERROR : - (b->head ? BUFFER_PENDING : BUFFER_EMPTY); + return (nbytes < 0) ? BUFFER_ERROR + : (b->head ? BUFFER_PENDING : BUFFER_EMPTY); } /* This function (unlike other buffer_flush* functions above) is designed @@ -434,8 +410,7 @@ to work with non-blocking sockets. It does not attempt to write out all of the queued data, just a "big" chunk. It returns 0 if it was able to empty out the buffers completely, 1 if more flushing is required later, or -1 on a fatal write error. */ -buffer_status_t -buffer_flush_available(struct buffer *b, int fd) +buffer_status_t buffer_flush_available(struct buffer *b, int fd) { /* These are just reasonable values to make sure a significant amount of @@ -448,66 +423,63 @@ in one shot. */ #endif #define MAX_FLUSH 131072 - struct buffer_data *d; - size_t written; - struct iovec iov[MAX_CHUNKS]; - size_t iovcnt = 0; - size_t nbyte = 0; - - for (d = b->head; d && (iovcnt < MAX_CHUNKS) && (nbyte < MAX_FLUSH); - d = d->next, iovcnt++) - { - iov[iovcnt].iov_base = d->data+d->sp; - nbyte += (iov[iovcnt].iov_len = d->cp-d->sp); - } - - if (!nbyte) - /* No data to flush: should we issue a warning message? */ - return BUFFER_EMPTY; - - /* only place where written should be sign compared */ - if ((ssize_t)(written = writev(fd,iov,iovcnt)) < 0) - { - if (ERRNO_IO_RETRY(errno)) - /* Calling code should try again later. */ - return BUFFER_PENDING; - zlog_warn("%s: write error on fd %d: %s", - __func__, fd, safe_strerror(errno)); - return BUFFER_ERROR; - } - - /* Free printed buffer data. */ - while (written > 0) - { - struct buffer_data *d; - if (!(d = b->head)) - { - zlog_err("%s: corruption detected: buffer queue empty, " - "but written is %lu", __func__, (u_long)written); - break; - } - if (written < d->cp-d->sp) - { - d->sp += written; - return BUFFER_PENDING; + struct buffer_data *d; + size_t written; + struct iovec iov[MAX_CHUNKS]; + size_t iovcnt = 0; + size_t nbyte = 0; + + for (d = b->head; d && (iovcnt < MAX_CHUNKS) && (nbyte < MAX_FLUSH); + d = d->next, iovcnt++) { + iov[iovcnt].iov_base = d->data + d->sp; + nbyte += (iov[iovcnt].iov_len = d->cp - d->sp); } - written -= (d->cp-d->sp); - if (!(b->head = d->next)) - b->tail = NULL; - BUFFER_DATA_FREE(d); - } + if (!nbyte) + /* No data to flush: should we issue a warning message? */ + return BUFFER_EMPTY; + + /* only place where written should be sign compared */ + if ((ssize_t)(written = writev(fd, iov, iovcnt)) < 0) { + if (ERRNO_IO_RETRY(errno)) + /* Calling code should try again later. */ + return BUFFER_PENDING; + zlog_warn("%s: write error on fd %d: %s", __func__, fd, + safe_strerror(errno)); + return BUFFER_ERROR; + } + + /* Free printed buffer data. */ + while (written > 0) { + struct buffer_data *d; + if (!(d = b->head)) { + zlog_err( + "%s: corruption detected: buffer queue empty, " + "but written is %lu", + __func__, (u_long)written); + break; + } + if (written < d->cp - d->sp) { + d->sp += written; + return BUFFER_PENDING; + } + + written -= (d->cp - d->sp); + if (!(b->head = d->next)) + b->tail = NULL; + BUFFER_DATA_FREE(d); + } - return b->head ? BUFFER_PENDING : BUFFER_EMPTY; + return b->head ? BUFFER_PENDING : BUFFER_EMPTY; #undef MAX_CHUNKS #undef MAX_FLUSH } -buffer_status_t -buffer_write(struct buffer *b, int fd, const void *p, size_t size) +buffer_status_t buffer_write(struct buffer *b, int fd, const void *p, + size_t size) { - ssize_t nbytes; + ssize_t nbytes; #if 0 /* Should we attempt to drain any previously buffered data? This could help @@ -517,25 +489,25 @@ buffer_write(struct buffer *b, int fd, const void *p, size_t size) if (b->head && (buffer_flush_available(b, fd) == BUFFER_ERROR)) return BUFFER_ERROR; #endif - if (b->head) - /* Buffer is not empty, so do not attempt to write the new data. */ - nbytes = 0; - else if ((nbytes = write(fd, p, size)) < 0) - { - if (ERRNO_IO_RETRY(errno)) - nbytes = 0; - else - { - zlog_warn("%s: write error on fd %d: %s", - __func__, fd, safe_strerror(errno)); - return BUFFER_ERROR; + if (b->head) + /* Buffer is not empty, so do not attempt to write the new data. + */ + nbytes = 0; + else if ((nbytes = write(fd, p, size)) < 0) { + if (ERRNO_IO_RETRY(errno)) + nbytes = 0; + else { + zlog_warn("%s: write error on fd %d: %s", __func__, fd, + safe_strerror(errno)); + return BUFFER_ERROR; + } + } + /* Add any remaining data to the buffer. */ + { + size_t written = nbytes; + if (written < size) + buffer_put(b, ((const char *)p) + written, + size - written); } - } - /* Add any remaining data to the buffer. */ - { - size_t written = nbytes; - if (written < size) - buffer_put(b, ((const char *)p)+written, size-written); - } - return b->head ? BUFFER_PENDING : BUFFER_EMPTY; + return b->head ? BUFFER_PENDING : BUFFER_EMPTY; } diff --git a/lib/buffer.h b/lib/buffer.h index 059f2cf33..130c677da 100644 --- a/lib/buffer.h +++ b/lib/buffer.h @@ -1,5 +1,5 @@ /* - * Buffering to output and input. + * Buffering to output and input. * Copyright (C) 1998 Kunihiro Ishiguro * * This file is part of GNU Zebra. @@ -22,25 +22,24 @@ #ifndef _ZEBRA_BUFFER_H #define _ZEBRA_BUFFER_H - /* Create a new buffer. Memory will be allocated in chunks of the given size. If the argument is 0, the library will supply a reasonable default size suitable for buffering socket I/O. */ -extern struct buffer *buffer_new (size_t); +extern struct buffer *buffer_new(size_t); /* Free all data in the buffer. */ -extern void buffer_reset (struct buffer *); +extern void buffer_reset(struct buffer *); /* This function first calls buffer_reset to release all buffered data. Then it frees the struct buffer itself. */ -extern void buffer_free (struct buffer *); +extern void buffer_free(struct buffer *); /* Add the given data to the end of the buffer. */ -extern void buffer_put (struct buffer *, const void *, size_t); +extern void buffer_put(struct buffer *, const void *, size_t); /* Add a single character to the end of the buffer. */ -extern void buffer_putc (struct buffer *, u_char); +extern void buffer_putc(struct buffer *, u_char); /* Add a NUL-terminated string to the end of the buffer. */ -extern void buffer_putstr (struct buffer *, const char *); +extern void buffer_putstr(struct buffer *, const char *); /* Add given data, inline-expanding \n to \r\n */ extern void buffer_put_crlf(struct buffer *b, const void *p, size_t size); @@ -48,33 +47,33 @@ extern void buffer_put_crlf(struct buffer *b, const void *p, size_t size); single NUL-terminated string allocated using XMALLOC(MTYPE_TMP). Note that this function does not alter the state of the buffer, so the data is still inside waiting to be flushed. */ -char *buffer_getstr (struct buffer *); +char *buffer_getstr(struct buffer *); /* Returns 1 if there is no pending data in the buffer. Otherwise returns 0. */ -int buffer_empty (struct buffer *); +int buffer_empty(struct buffer *); -typedef enum - { - /* An I/O error occurred. The buffer should be destroyed and the - file descriptor should be closed. */ - BUFFER_ERROR = -1, +typedef enum { + /* An I/O error occurred. The buffer should be destroyed and the + file descriptor should be closed. */ + BUFFER_ERROR = -1, - /* The data was written successfully, and the buffer is now empty - (there is no pending data waiting to be flushed). */ - BUFFER_EMPTY = 0, + /* The data was written successfully, and the buffer is now empty + (there is no pending data waiting to be flushed). */ + BUFFER_EMPTY = 0, - /* There is pending data in the buffer waiting to be flushed. Please - try flushing the buffer when select indicates that the file descriptor - is writeable. */ - BUFFER_PENDING = 1 - } buffer_status_t; + /* There is pending data in the buffer waiting to be flushed. Please + try flushing the buffer when select indicates that the file + descriptor + is writeable. */ + BUFFER_PENDING = 1 +} buffer_status_t; /* Try to write this data to the file descriptor. Any data that cannot be written immediately is added to the buffer queue. */ -extern buffer_status_t buffer_write(struct buffer *, int fd, - const void *, size_t); +extern buffer_status_t buffer_write(struct buffer *, int fd, const void *, + size_t); -/* This function attempts to flush some (but perhaps not all) of +/* This function attempts to flush some (but perhaps not all) of the queued data to the given file descriptor. */ extern buffer_status_t buffer_flush_available(struct buffer *, int fd); @@ -84,12 +83,12 @@ extern buffer_status_t buffer_flush_available(struct buffer *, int fd); /* Call buffer_flush_available repeatedly until either all data has been flushed, or an I/O error has been encountered, or the operation would block. */ -extern buffer_status_t buffer_flush_all (struct buffer *, int fd); +extern buffer_status_t buffer_flush_all(struct buffer *, int fd); /* Attempt to write enough data to the given fd to fill a window of the given width and height (and remove the data written from the buffer). - If !no_more, then a message saying " --More-- " is appended. + If !no_more, then a message saying " --More-- " is appended. If erase is true, then first overwrite the previous " --More-- " message with spaces. @@ -97,7 +96,7 @@ extern buffer_status_t buffer_flush_all (struct buffer *, int fd); to return -1 (because the logic for handling the erase and more features is too complicated to retry the write later). */ -extern buffer_status_t buffer_flush_window (struct buffer *, int fd, int width, - int height, int erase, int no_more); +extern buffer_status_t buffer_flush_window(struct buffer *, int fd, int width, + int height, int erase, int no_more); #endif /* _ZEBRA_BUFFER_H */ diff --git a/lib/checksum.c b/lib/checksum.c index 3d6cd4579..8eef73e24 100644 --- a/lib/checksum.c +++ b/lib/checksum.c @@ -9,13 +9,13 @@ #include #include "checksum.h" -int /* return checksum in low-order 16 bits */ -in_cksum(void *parg, int nbytes) +int /* return checksum in low-order 16 bits */ + in_cksum(void *parg, int nbytes) { u_short *ptr = parg; - register long sum; /* assumes long == 32 bits */ - u_short oddbyte; - register u_short answer; /* assumes u_short == 16 bits */ + register long sum; /* assumes long == 32 bits */ + u_short oddbyte; + register u_short answer; /* assumes u_short == 16 bits */ /* * Our algorithm is simple, using a 32-bit accumulator (sum), @@ -24,15 +24,15 @@ in_cksum(void *parg, int nbytes) */ sum = 0; - while (nbytes > 1) { + while (nbytes > 1) { sum += *ptr++; nbytes -= 2; } - /* mop up an odd byte, if necessary */ + /* mop up an odd byte, if necessary */ if (nbytes == 1) { - oddbyte = 0; /* make sure top half is zero */ - *((u_char *) &oddbyte) = *(u_char *)ptr; /* one byte only */ + oddbyte = 0; /* make sure top half is zero */ + *((u_char *)&oddbyte) = *(u_char *)ptr; /* one byte only */ sum += oddbyte; } @@ -40,82 +40,80 @@ in_cksum(void *parg, int nbytes) * Add back carry outs from top 16 bits to low 16 bits. */ - sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */ - sum += (sum >> 16); /* add carry */ - answer = ~sum; /* ones-complement, then truncate to 16 bits */ - return(answer); + sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* ones-complement, then truncate to 16 bits */ + return (answer); } /* Fletcher Checksum -- Refer to RFC1008. */ #define MODX 4102U /* 5802 should be fine */ -/* To be consistent, offset is 0-based index, rather than the 1-based +/* To be consistent, offset is 0-based index, rather than the 1-based index required in the specification ISO 8473, Annex C.1 */ /* calling with offset == FLETCHER_CHECKSUM_VALIDATE will validate the checksum without modifying the buffer; a valid checksum returns 0 */ -u_int16_t -fletcher_checksum(u_char * buffer, const size_t len, const uint16_t offset) +u_int16_t fletcher_checksum(u_char *buffer, const size_t len, + const uint16_t offset) { - u_int8_t *p; - int x, y, c0, c1; - u_int16_t checksum = 0; - u_int16_t *csum; - size_t partial_len, i, left = len; - - if (offset != FLETCHER_CHECKSUM_VALIDATE) - /* Zero the csum in the packet. */ - { - assert (offset < (len - 1)); /* account for two bytes of checksum */ - csum = (u_int16_t *) (buffer + offset); - *(csum) = 0; - } - - p = buffer; - c0 = 0; - c1 = 0; - - while (left != 0) - { - partial_len = MIN(left, MODX); - - for (i = 0; i < partial_len; i++) + u_int8_t *p; + int x, y, c0, c1; + u_int16_t checksum = 0; + u_int16_t *csum; + size_t partial_len, i, left = len; + + if (offset != FLETCHER_CHECKSUM_VALIDATE) + /* Zero the csum in the packet. */ { - c0 = c0 + *(p++); - c1 += c0; + assert(offset + < (len - 1)); /* account for two bytes of checksum */ + csum = (u_int16_t *)(buffer + offset); + *(csum) = 0; } - c0 = c0 % 255; - c1 = c1 % 255; - - left -= partial_len; - } - - /* The cast is important, to ensure the mod is taken as a signed value. */ - x = (int)((len - offset - 1) * c0 - c1) % 255; - - if (x <= 0) - x += 255; - y = 510 - c0 - x; - if (y > 255) - y -= 255; - - if (offset == FLETCHER_CHECKSUM_VALIDATE) - { - checksum = (c1 << 8) + c0; - } - else - { - /* - * Now we write this to the packet. - * We could skip this step too, since the checksum returned would - * be stored into the checksum field by the caller. - */ - buffer[offset] = x; - buffer[offset + 1] = y; - - /* Take care of the endian issue */ - checksum = htons((x << 8) | (y & 0xFF)); - } - - return checksum; + p = buffer; + c0 = 0; + c1 = 0; + + while (left != 0) { + partial_len = MIN(left, MODX); + + for (i = 0; i < partial_len; i++) { + c0 = c0 + *(p++); + c1 += c0; + } + + c0 = c0 % 255; + c1 = c1 % 255; + + left -= partial_len; + } + + /* The cast is important, to ensure the mod is taken as a signed value. + */ + x = (int)((len - offset - 1) * c0 - c1) % 255; + + if (x <= 0) + x += 255; + y = 510 - c0 - x; + if (y > 255) + y -= 255; + + if (offset == FLETCHER_CHECKSUM_VALIDATE) { + checksum = (c1 << 8) + c0; + } else { + /* + * Now we write this to the packet. + * We could skip this step too, since the checksum returned + * would + * be stored into the checksum field by the caller. + */ + buffer[offset] = x; + buffer[offset + 1] = y; + + /* Take care of the endian issue */ + checksum = htons((x << 8) | (y & 0xFF)); + } + + return checksum; } diff --git a/lib/checksum.h b/lib/checksum.h index b310f744c..aecaaf6bc 100644 --- a/lib/checksum.h +++ b/lib/checksum.h @@ -1,3 +1,4 @@ extern int in_cksum(void *, int); #define FLETCHER_CHECKSUM_VALIDATE 0xffff -extern u_int16_t fletcher_checksum(u_char *, const size_t len, const uint16_t offset); +extern u_int16_t fletcher_checksum(u_char *, const size_t len, + const uint16_t offset); diff --git a/lib/clippy.c b/lib/clippy.c index 26ef24657..bcec6c2cc 100644 --- a/lib/clippy.c +++ b/lib/clippy.c @@ -75,8 +75,9 @@ int main(int argc, char **argv) *cr = ' '; fprintf(stderr, "clippy interactive shell\n(Python %s)\n", ver); free(ver); - PyRun_SimpleString("import rlcompleter, readline\n" - "readline.parse_and_bind('tab: complete')"); + PyRun_SimpleString( + "import rlcompleter, readline\n" + "readline.parse_and_bind('tab: complete')"); } if (PyRun_AnyFile(fp, pyfile)) { @@ -86,7 +87,7 @@ int main(int argc, char **argv) printf("unknown python failure (?)\n"); return 1; } - Py_Finalize(); + Py_Finalize(); #if PY_MAJOR_VERSION >= 3 for (int i = 1; i < argc; i++) @@ -106,15 +107,15 @@ int main(int argc, char **argv) #include "log.h" #include "zassert.h" -#define ZLOG_FUNC(FUNCNAME) \ -void FUNCNAME(const char *format, ...) \ -{ \ - va_list args; \ - va_start(args, format); \ - vfprintf (stderr, format, args); \ - fputs ("\n", stderr); \ - va_end(args); \ -} +#define ZLOG_FUNC(FUNCNAME) \ + void FUNCNAME(const char *format, ...) \ + { \ + va_list args; \ + va_start(args, format); \ + vfprintf(stderr, format, args); \ + fputs("\n", stderr); \ + va_end(args); \ + } ZLOG_FUNC(zlog_err) ZLOG_FUNC(zlog_warn) @@ -122,16 +123,16 @@ ZLOG_FUNC(zlog_info) ZLOG_FUNC(zlog_notice) ZLOG_FUNC(zlog_debug) -void -_zlog_assert_failed (const char *assertion, const char *file, - unsigned int line, const char *function) +void _zlog_assert_failed(const char *assertion, const char *file, + unsigned int line, const char *function) { - fprintf(stderr, "Assertion `%s' failed in file %s, line %u, function %s", + fprintf(stderr, + "Assertion `%s' failed in file %s, line %u, function %s", assertion, file, line, (function ? function : "?")); abort(); } -void memory_oom (size_t size, const char *name) +void memory_oom(size_t size, const char *name) { abort(); } diff --git a/lib/command.c b/lib/command.c index a631cf1c6..d97ad9db3 100644 --- a/lib/command.c +++ b/lib/command.c @@ -43,9 +43,9 @@ #include "qobj.h" #include "defaults.h" -DEFINE_MTYPE( LIB, HOST, "Host config") -DEFINE_MTYPE( LIB, STRVEC, "String vector") -DEFINE_MTYPE( LIB, COMPLETION, "Completion item") +DEFINE_MTYPE(LIB, HOST, "Host config") +DEFINE_MTYPE(LIB, STRVEC, "String vector") +DEFINE_MTYPE(LIB, COMPLETION, "Completion item") /* Command vector which includes some level of command lists. Normally each daemon maintains each own cmdvec. */ @@ -55,138 +55,118 @@ vector cmdvec = NULL; struct host host; /* Standard command node structures. */ -static struct cmd_node auth_node = -{ - AUTH_NODE, - "Password: ", +static struct cmd_node auth_node = { + AUTH_NODE, "Password: ", }; -static struct cmd_node view_node = -{ - VIEW_NODE, - "%s> ", +static struct cmd_node view_node = { + VIEW_NODE, "%s> ", }; -static struct cmd_node auth_enable_node = -{ - AUTH_ENABLE_NODE, - "Password: ", +static struct cmd_node auth_enable_node = { + AUTH_ENABLE_NODE, "Password: ", }; -static struct cmd_node enable_node = -{ - ENABLE_NODE, - "%s# ", +static struct cmd_node enable_node = { + ENABLE_NODE, "%s# ", }; -static struct cmd_node config_node = -{ - CONFIG_NODE, - "%s(config)# ", - 1 -}; +static struct cmd_node config_node = {CONFIG_NODE, "%s(config)# ", 1}; /* Default motd string. */ static const char *default_motd = FRR_DEFAULT_MOTD; static const struct facility_map { - int facility; - const char *name; - size_t match; -} syslog_facilities[] = - { - { LOG_KERN, "kern", 1 }, - { LOG_USER, "user", 2 }, - { LOG_MAIL, "mail", 1 }, - { LOG_DAEMON, "daemon", 1 }, - { LOG_AUTH, "auth", 1 }, - { LOG_SYSLOG, "syslog", 1 }, - { LOG_LPR, "lpr", 2 }, - { LOG_NEWS, "news", 1 }, - { LOG_UUCP, "uucp", 2 }, - { LOG_CRON, "cron", 1 }, + int facility; + const char *name; + size_t match; +} syslog_facilities[] = { + {LOG_KERN, "kern", 1}, + {LOG_USER, "user", 2}, + {LOG_MAIL, "mail", 1}, + {LOG_DAEMON, "daemon", 1}, + {LOG_AUTH, "auth", 1}, + {LOG_SYSLOG, "syslog", 1}, + {LOG_LPR, "lpr", 2}, + {LOG_NEWS, "news", 1}, + {LOG_UUCP, "uucp", 2}, + {LOG_CRON, "cron", 1}, #ifdef LOG_FTP - { LOG_FTP, "ftp", 1 }, + {LOG_FTP, "ftp", 1}, #endif - { LOG_LOCAL0, "local0", 6 }, - { LOG_LOCAL1, "local1", 6 }, - { LOG_LOCAL2, "local2", 6 }, - { LOG_LOCAL3, "local3", 6 }, - { LOG_LOCAL4, "local4", 6 }, - { LOG_LOCAL5, "local5", 6 }, - { LOG_LOCAL6, "local6", 6 }, - { LOG_LOCAL7, "local7", 6 }, - { 0, NULL, 0 }, - }; + {LOG_LOCAL0, "local0", 6}, + {LOG_LOCAL1, "local1", 6}, + {LOG_LOCAL2, "local2", 6}, + {LOG_LOCAL3, "local3", 6}, + {LOG_LOCAL4, "local4", 6}, + {LOG_LOCAL5, "local5", 6}, + {LOG_LOCAL6, "local6", 6}, + {LOG_LOCAL7, "local7", 6}, + {0, NULL, 0}, +}; -static const char * -facility_name(int facility) +static const char *facility_name(int facility) { - const struct facility_map *fm; + const struct facility_map *fm; - for (fm = syslog_facilities; fm->name; fm++) - if (fm->facility == facility) - return fm->name; - return ""; + for (fm = syslog_facilities; fm->name; fm++) + if (fm->facility == facility) + return fm->name; + return ""; } -static int -facility_match(const char *str) +static int facility_match(const char *str) { - const struct facility_map *fm; + const struct facility_map *fm; - for (fm = syslog_facilities; fm->name; fm++) - if (!strncmp(str,fm->name,fm->match)) - return fm->facility; - return -1; + for (fm = syslog_facilities; fm->name; fm++) + if (!strncmp(str, fm->name, fm->match)) + return fm->facility; + return -1; } -static int -level_match(const char *s) +static int level_match(const char *s) { - int level ; + int level; - for ( level = 0 ; zlog_priority [level] != NULL ; level ++ ) - if (!strncmp (s, zlog_priority[level], 2)) - return level; - return ZLOG_DISABLED; + for (level = 0; zlog_priority[level] != NULL; level++) + if (!strncmp(s, zlog_priority[level], 2)) + return level; + return ZLOG_DISABLED; } /* This is called from main when a daemon is invoked with -v or --version. */ -void -print_version (const char *progname) +void print_version(const char *progname) { - printf ("%s version %s\n", progname, FRR_VERSION); - printf ("%s\n", FRR_COPYRIGHT); - printf ("configured with:\n\t%s\n", FRR_CONFIG_ARGS); + printf("%s version %s\n", progname, FRR_VERSION); + printf("%s\n", FRR_COPYRIGHT); + printf("configured with:\n\t%s\n", FRR_CONFIG_ARGS); } /* Utility function to concatenate argv argument into a single string with inserting ' ' character between each argument. */ -char * -argv_concat (struct cmd_token **argv, int argc, int shift) -{ - int i; - size_t len; - char *str; - char *p; - - len = 0; - for (i = shift; i < argc; i++) - len += strlen(argv[i]->arg)+1; - if (!len) - return NULL; - p = str = XMALLOC(MTYPE_TMP, len); - for (i = shift; i < argc; i++) - { - size_t arglen; - memcpy(p, argv[i]->arg, (arglen = strlen(argv[i]->arg))); - p += arglen; - *p++ = ' '; - } - *(p-1) = '\0'; - return str; +char *argv_concat(struct cmd_token **argv, int argc, int shift) +{ + int i; + size_t len; + char *str; + char *p; + + len = 0; + for (i = shift; i < argc; i++) + len += strlen(argv[i]->arg) + 1; + if (!len) + return NULL; + p = str = XMALLOC(MTYPE_TMP, len); + for (i = shift; i < argc; i++) { + size_t arglen; + memcpy(p, argv[i]->arg, (arglen = strlen(argv[i]->arg))); + p += arglen; + *p++ = ' '; + } + *(p - 1) = '\0'; + return str; } /** @@ -199,41 +179,38 @@ argv_concat (struct cmd_token **argv, int argc, int shift) * index of the found token if it exists * @return 1 if found, 0 otherwise */ -int -argv_find (struct cmd_token **argv, int argc, const char *text, int *index) +int argv_find(struct cmd_token **argv, int argc, const char *text, int *index) { - int found = 0; - for (int i = *index; i < argc && found == 0; i++) - if ((found = strmatch (text, argv[i]->text))) - *index = i; - return found; + int found = 0; + for (int i = *index; i < argc && found == 0; i++) + if ((found = strmatch(text, argv[i]->text))) + *index = i; + return found; } -static unsigned int -cmd_hash_key (void *p) +static unsigned int cmd_hash_key(void *p) { - return (uintptr_t) p; + return (uintptr_t)p; } -static int -cmd_hash_cmp (const void *a, const void *b) +static int cmd_hash_cmp(const void *a, const void *b) { - return a == b; + return a == b; } /* Install top node of command vector. */ -void -install_node (struct cmd_node *node, - int (*func) (struct vty *)) +void install_node(struct cmd_node *node, int (*func)(struct vty *)) { - vector_set_index (cmdvec, node->node, node); - node->func = func; - node->cmdgraph = graph_new (); - node->cmd_vector = vector_init (VECTOR_MIN_SIZE); - // add start node - struct cmd_token *token = cmd_token_new (START_TKN, CMD_ATTR_NORMAL, NULL, NULL); - graph_new_node (node->cmdgraph, token, (void (*)(void *)) &cmd_token_del); - node->cmd_hash = hash_create (cmd_hash_key, cmd_hash_cmp, NULL); + vector_set_index(cmdvec, node->node, node); + node->func = func; + node->cmdgraph = graph_new(); + node->cmd_vector = vector_init(VECTOR_MIN_SIZE); + // add start node + struct cmd_token *token = + cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL); + graph_new_node(node->cmdgraph, token, + (void (*)(void *)) & cmd_token_del); + node->cmd_hash = hash_create(cmd_hash_key, cmd_hash_cmp, NULL); } /** @@ -245,308 +222,296 @@ install_node (struct cmd_node *node, * @param string to tokenize * @return tokenized string */ -vector -cmd_make_strvec (const char *string) +vector cmd_make_strvec(const char *string) { - if (!string) return NULL; + if (!string) + return NULL; - char *copy, *copystart; - copystart = copy = XSTRDUP (MTYPE_TMP, string); + char *copy, *copystart; + copystart = copy = XSTRDUP(MTYPE_TMP, string); - // skip leading whitespace - while (isspace ((int) *copy) && *copy != '\0') copy++; + // skip leading whitespace + while (isspace((int)*copy) && *copy != '\0') + copy++; - // if the entire string was whitespace or a comment, return - if (*copy == '\0' || *copy == '!' || *copy == '#') - { - XFREE (MTYPE_TMP, copystart); - return NULL; - } + // if the entire string was whitespace or a comment, return + if (*copy == '\0' || *copy == '!' || *copy == '#') { + XFREE(MTYPE_TMP, copystart); + return NULL; + } - vector strvec = vector_init (VECTOR_MIN_SIZE); - const char *delim = " \n\r\t", *tok = NULL; - while (copy) - { - tok = strsep (©, delim); - if (*tok != '\0') - vector_set (strvec, XSTRDUP (MTYPE_STRVEC, tok)); - } + vector strvec = vector_init(VECTOR_MIN_SIZE); + const char *delim = " \n\r\t", *tok = NULL; + while (copy) { + tok = strsep(©, delim); + if (*tok != '\0') + vector_set(strvec, XSTRDUP(MTYPE_STRVEC, tok)); + } - XFREE (MTYPE_TMP, copystart); - return strvec; + XFREE(MTYPE_TMP, copystart); + return strvec; } /* Free allocated string vector. */ -void -cmd_free_strvec (vector v) +void cmd_free_strvec(vector v) { - unsigned int i; - char *cp; + unsigned int i; + char *cp; - if (!v) - return; + if (!v) + return; - for (i = 0; i < vector_active (v); i++) - if ((cp = vector_slot (v, i)) != NULL) - XFREE (MTYPE_STRVEC, cp); + for (i = 0; i < vector_active(v); i++) + if ((cp = vector_slot(v, i)) != NULL) + XFREE(MTYPE_STRVEC, cp); - vector_free (v); + vector_free(v); } /* Return prompt character of specified node. */ -const char * -cmd_prompt (enum node_type node) +const char *cmd_prompt(enum node_type node) { - struct cmd_node *cnode; + struct cmd_node *cnode; - cnode = vector_slot (cmdvec, node); - return cnode->prompt; + cnode = vector_slot(cmdvec, node); + return cnode->prompt; } /* Install a command into a node. */ -void -install_element (enum node_type ntype, struct cmd_element *cmd) +void install_element(enum node_type ntype, struct cmd_element *cmd) { - struct cmd_node *cnode; + struct cmd_node *cnode; - /* cmd_init hasn't been called */ - if (!cmdvec) - { - fprintf (stderr, "%s called before cmd_init, breakage likely\n", - __func__); - return; - } + /* cmd_init hasn't been called */ + if (!cmdvec) { + fprintf(stderr, "%s called before cmd_init, breakage likely\n", + __func__); + return; + } - cnode = vector_slot (cmdvec, ntype); + cnode = vector_slot(cmdvec, ntype); - if (cnode == NULL) - { - fprintf (stderr, "Command node %d doesn't exist, please check it\n", - ntype); - fprintf (stderr, "Have you called install_node before this install_element?\n"); - exit (EXIT_FAILURE); - } + if (cnode == NULL) { + fprintf(stderr, + "Command node %d doesn't exist, please check it\n", + ntype); + fprintf(stderr, + "Have you called install_node before this install_element?\n"); + exit(EXIT_FAILURE); + } - if (hash_lookup (cnode->cmd_hash, cmd) != NULL) - { - fprintf (stderr, - "Multiple command installs to node %d of command:\n%s\n", - ntype, cmd->string); - return; - } + if (hash_lookup(cnode->cmd_hash, cmd) != NULL) { + fprintf(stderr, + "Multiple command installs to node %d of command:\n%s\n", + ntype, cmd->string); + return; + } - assert (hash_get (cnode->cmd_hash, cmd, hash_alloc_intern)); + assert(hash_get(cnode->cmd_hash, cmd, hash_alloc_intern)); - struct graph *graph = graph_new(); - struct cmd_token *token = cmd_token_new (START_TKN, CMD_ATTR_NORMAL, NULL, NULL); - graph_new_node (graph, token, (void (*)(void *)) &cmd_token_del); + struct graph *graph = graph_new(); + struct cmd_token *token = + cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL); + graph_new_node(graph, token, (void (*)(void *)) & cmd_token_del); - cmd_graph_parse (graph, cmd); - cmd_graph_names (graph); - cmd_graph_merge (cnode->cmdgraph, graph, +1); - graph_delete_graph (graph); + cmd_graph_parse(graph, cmd); + cmd_graph_names(graph); + cmd_graph_merge(cnode->cmdgraph, graph, +1); + graph_delete_graph(graph); - vector_set (cnode->cmd_vector, cmd); + vector_set(cnode->cmd_vector, cmd); - if (ntype == VIEW_NODE) - install_element (ENABLE_NODE, cmd); + if (ntype == VIEW_NODE) + install_element(ENABLE_NODE, cmd); } -void -uninstall_element (enum node_type ntype, struct cmd_element *cmd) +void uninstall_element(enum node_type ntype, struct cmd_element *cmd) { - struct cmd_node *cnode; + struct cmd_node *cnode; - /* cmd_init hasn't been called */ - if (!cmdvec) - { - fprintf (stderr, "%s called before cmd_init, breakage likely\n", - __func__); - return; - } + /* cmd_init hasn't been called */ + if (!cmdvec) { + fprintf(stderr, "%s called before cmd_init, breakage likely\n", + __func__); + return; + } - cnode = vector_slot (cmdvec, ntype); + cnode = vector_slot(cmdvec, ntype); - if (cnode == NULL) - { - fprintf (stderr, "Command node %d doesn't exist, please check it\n", - ntype); - fprintf (stderr, "Have you called install_node before this install_element?\n"); - exit (EXIT_FAILURE); - } + if (cnode == NULL) { + fprintf(stderr, + "Command node %d doesn't exist, please check it\n", + ntype); + fprintf(stderr, + "Have you called install_node before this install_element?\n"); + exit(EXIT_FAILURE); + } - if (hash_release (cnode->cmd_hash, cmd) == NULL) - { - fprintf (stderr, - "Trying to uninstall non-installed command (node %d):\n%s\n", - ntype, cmd->string); - return; - } + if (hash_release(cnode->cmd_hash, cmd) == NULL) { + fprintf(stderr, + "Trying to uninstall non-installed command (node %d):\n%s\n", + ntype, cmd->string); + return; + } - vector_unset_value (cnode->cmd_vector, cmd); + vector_unset_value(cnode->cmd_vector, cmd); - struct graph *graph = graph_new(); - struct cmd_token *token = cmd_token_new (START_TKN, CMD_ATTR_NORMAL, NULL, NULL); - graph_new_node (graph, token, (void (*)(void *)) &cmd_token_del); + struct graph *graph = graph_new(); + struct cmd_token *token = + cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL); + graph_new_node(graph, token, (void (*)(void *)) & cmd_token_del); - cmd_graph_parse (graph, cmd); - cmd_graph_names (graph); - cmd_graph_merge (cnode->cmdgraph, graph, -1); - graph_delete_graph (graph); + cmd_graph_parse(graph, cmd); + cmd_graph_names(graph); + cmd_graph_merge(cnode->cmdgraph, graph, -1); + graph_delete_graph(graph); - if (ntype == VIEW_NODE) - uninstall_element (ENABLE_NODE, cmd); + if (ntype == VIEW_NODE) + uninstall_element(ENABLE_NODE, cmd); } static const unsigned char itoa64[] = -"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; -static void -to64(char *s, long v, int n) +static void to64(char *s, long v, int n) { - while (--n >= 0) - { - *s++ = itoa64[v&0x3f]; - v >>= 6; - } + while (--n >= 0) { + *s++ = itoa64[v & 0x3f]; + v >>= 6; + } } -static char * -zencrypt (const char *passwd) +static char *zencrypt(const char *passwd) { - char salt[6]; - struct timeval tv; - char *crypt (const char *, const char *); + char salt[6]; + struct timeval tv; + char *crypt(const char *, const char *); - gettimeofday(&tv,0); + gettimeofday(&tv, 0); - to64(&salt[0], random(), 3); - to64(&salt[3], tv.tv_usec, 3); - salt[5] = '\0'; + to64(&salt[0], random(), 3); + to64(&salt[3], tv.tv_usec, 3); + salt[5] = '\0'; - return crypt (passwd, salt); + return crypt(passwd, salt); } /* This function write configuration of this host. */ -static int -config_write_host (struct vty *vty) -{ - if (host.name) - vty_out (vty, "hostname %s\n", host.name); - - if (host.encrypt) - { - if (host.password_encrypt) - vty_out (vty, "password 8 %s\n", host.password_encrypt); - if (host.enable_encrypt) - vty_out (vty, "enable password 8 %s\n", host.enable_encrypt); - } - else - { - if (host.password) - vty_out (vty, "password %s\n", host.password); - if (host.enable) - vty_out (vty, "enable password %s\n", host.enable); - } - - if (zlog_default->default_lvl != LOG_DEBUG) - { - vty_out (vty,"! N.B. The 'log trap' command is deprecated.\n"); - vty_out (vty, "log trap %s\n", - zlog_priority[zlog_default->default_lvl]); - } - - if (host.logfile && (zlog_default->maxlvl[ZLOG_DEST_FILE] != ZLOG_DISABLED)) - { - vty_out (vty, "log file %s", host.logfile); - if (zlog_default->maxlvl[ZLOG_DEST_FILE] != zlog_default->default_lvl) - vty_out (vty, " %s", - zlog_priority[zlog_default->maxlvl[ZLOG_DEST_FILE]]); - vty_out (vty, "\n"); - } - - if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != ZLOG_DISABLED) - { - vty_out (vty, "log stdout"); - if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != zlog_default->default_lvl) - vty_out (vty, " %s", - zlog_priority[zlog_default->maxlvl[ZLOG_DEST_STDOUT]]); - vty_out (vty, "\n"); - } - - if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED) - vty_out (vty,"no log monitor\n"); - else if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] != zlog_default->default_lvl) - vty_out (vty,"log monitor %s\n", - zlog_priority[zlog_default->maxlvl[ZLOG_DEST_MONITOR]]); - - if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED) - { - vty_out (vty, "log syslog"); - if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != zlog_default->default_lvl) - vty_out (vty, " %s", - zlog_priority[zlog_default->maxlvl[ZLOG_DEST_SYSLOG]]); - vty_out (vty, "\n"); - } - - if (zlog_default->facility != LOG_DAEMON) - vty_out (vty, "log facility %s\n", - facility_name(zlog_default->facility)); - - if (zlog_default->record_priority == 1) - vty_out (vty, "log record-priority\n"); - - if (zlog_default->timestamp_precision > 0) - vty_out (vty, "log timestamp precision %d\n", - zlog_default->timestamp_precision); - - if (host.advanced) - vty_out (vty, "service advanced-vty\n"); - - if (host.encrypt) - vty_out (vty, "service password-encryption\n"); - - if (host.lines >= 0) - vty_out (vty, "service terminal-length %d\n",host.lines); - - if (host.motdfile) - vty_out (vty, "banner motd file %s\n", host.motdfile); - else if (! host.motd) - vty_out (vty, "no banner motd\n"); - - return 1; +static int config_write_host(struct vty *vty) +{ + if (host.name) + vty_out(vty, "hostname %s\n", host.name); + + if (host.encrypt) { + if (host.password_encrypt) + vty_out(vty, "password 8 %s\n", host.password_encrypt); + if (host.enable_encrypt) + vty_out(vty, "enable password 8 %s\n", + host.enable_encrypt); + } else { + if (host.password) + vty_out(vty, "password %s\n", host.password); + if (host.enable) + vty_out(vty, "enable password %s\n", host.enable); + } + + if (zlog_default->default_lvl != LOG_DEBUG) { + vty_out(vty, "! N.B. The 'log trap' command is deprecated.\n"); + vty_out(vty, "log trap %s\n", + zlog_priority[zlog_default->default_lvl]); + } + + if (host.logfile + && (zlog_default->maxlvl[ZLOG_DEST_FILE] != ZLOG_DISABLED)) { + vty_out(vty, "log file %s", host.logfile); + if (zlog_default->maxlvl[ZLOG_DEST_FILE] + != zlog_default->default_lvl) + vty_out(vty, " %s", + zlog_priority + [zlog_default->maxlvl[ZLOG_DEST_FILE]]); + vty_out(vty, "\n"); + } + + if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != ZLOG_DISABLED) { + vty_out(vty, "log stdout"); + if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] + != zlog_default->default_lvl) + vty_out(vty, " %s", + zlog_priority[zlog_default->maxlvl + [ZLOG_DEST_STDOUT]]); + vty_out(vty, "\n"); + } + + if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED) + vty_out(vty, "no log monitor\n"); + else if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] + != zlog_default->default_lvl) + vty_out(vty, "log monitor %s\n", + zlog_priority[zlog_default->maxlvl[ZLOG_DEST_MONITOR]]); + + if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED) { + vty_out(vty, "log syslog"); + if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] + != zlog_default->default_lvl) + vty_out(vty, " %s", + zlog_priority[zlog_default->maxlvl + [ZLOG_DEST_SYSLOG]]); + vty_out(vty, "\n"); + } + + if (zlog_default->facility != LOG_DAEMON) + vty_out(vty, "log facility %s\n", + facility_name(zlog_default->facility)); + + if (zlog_default->record_priority == 1) + vty_out(vty, "log record-priority\n"); + + if (zlog_default->timestamp_precision > 0) + vty_out(vty, "log timestamp precision %d\n", + zlog_default->timestamp_precision); + + if (host.advanced) + vty_out(vty, "service advanced-vty\n"); + + if (host.encrypt) + vty_out(vty, "service password-encryption\n"); + + if (host.lines >= 0) + vty_out(vty, "service terminal-length %d\n", host.lines); + + if (host.motdfile) + vty_out(vty, "banner motd file %s\n", host.motdfile); + else if (!host.motd) + vty_out(vty, "no banner motd\n"); + + return 1; } /* Utility function for getting command graph. */ -static struct graph * -cmd_node_graph (vector v, enum node_type ntype) +static struct graph *cmd_node_graph(vector v, enum node_type ntype) { - struct cmd_node *cnode = vector_slot (v, ntype); - return cnode->cmdgraph; + struct cmd_node *cnode = vector_slot(v, ntype); + return cnode->cmdgraph; } -static int -cmd_try_do_shortcut (enum node_type node, char* first_word) { - if ( first_word != NULL && - node != AUTH_NODE && - node != VIEW_NODE && - node != AUTH_ENABLE_NODE && - 0 == strcmp( "do", first_word ) ) - return 1; - return 0; +static int cmd_try_do_shortcut(enum node_type node, char *first_word) +{ + if (first_word != NULL && node != AUTH_NODE && node != VIEW_NODE + && node != AUTH_ENABLE_NODE && 0 == strcmp("do", first_word)) + return 1; + return 0; } /** * Compare function for cmd_token. * Used with qsort to sort command completions. */ -static int -compare_completions (const void *fst, const void *snd) +static int compare_completions(const void *fst, const void *snd) { - struct cmd_token *first = *(struct cmd_token **) fst, - *secnd = *(struct cmd_token **) snd; - return strcmp (first->text, secnd->text); + struct cmd_token *first = *(struct cmd_token **)fst, + *secnd = *(struct cmd_token **)snd; + return strcmp(first->text, secnd->text); } /** @@ -557,51 +522,46 @@ compare_completions (const void *fst, const void *snd) * @param completions linked list of cmd_token * @return deduplicated and sorted vector with */ -vector -completions_to_vec (struct list *completions) -{ - vector comps = vector_init (VECTOR_MIN_SIZE); - - struct listnode *ln; - struct cmd_token *token, *cr = NULL; - unsigned int i, exists; - for (ALL_LIST_ELEMENTS_RO(completions,ln,token)) - { - if (token->type == END_TKN && (cr = token)) - continue; - - // linear search for token in completions vector - exists = 0; - for (i = 0; i < vector_active (comps) && !exists; i++) - { - struct cmd_token *curr = vector_slot (comps, i); +vector completions_to_vec(struct list *completions) +{ + vector comps = vector_init(VECTOR_MIN_SIZE); + + struct listnode *ln; + struct cmd_token *token, *cr = NULL; + unsigned int i, exists; + for (ALL_LIST_ELEMENTS_RO(completions, ln, token)) { + if (token->type == END_TKN && (cr = token)) + continue; + + // linear search for token in completions vector + exists = 0; + for (i = 0; i < vector_active(comps) && !exists; i++) { + struct cmd_token *curr = vector_slot(comps, i); #ifdef VTYSH_DEBUG - exists = !strcmp (curr->text, token->text) && - !strcmp (curr->desc, token->desc); + exists = !strcmp(curr->text, token->text) + && !strcmp(curr->desc, token->desc); #else - exists = !strcmp (curr->text, token->text); + exists = !strcmp(curr->text, token->text); #endif /* VTYSH_DEBUG */ - } + } - if (!exists) - vector_set (comps, token); - } + if (!exists) + vector_set(comps, token); + } - // sort completions - qsort (comps->index, - vector_active (comps), - sizeof (void *), - &compare_completions); + // sort completions + qsort(comps->index, vector_active(comps), sizeof(void *), + &compare_completions); - // make the first element, if it is present - if (cr) - { - vector_set_index (comps, vector_active (comps), NULL); - memmove (comps->index + 1, comps->index, (comps->alloced - 1) * sizeof (void *)); - vector_set_index (comps, 0, cr); - } + // make the first element, if it is present + if (cr) { + vector_set_index(comps, vector_active(comps), NULL); + memmove(comps->index + 1, comps->index, + (comps->alloced - 1) * sizeof(void *)); + vector_set_index(comps, 0, cr); + } - return comps; + return comps; } /** * Generates a vector of cmd_token representing possible completions @@ -612,151 +572,143 @@ completions_to_vec (struct list *completions) * @param status pointer to matcher status code * @return vector of struct cmd_token * with possible completions */ -static vector -cmd_complete_command_real (vector vline, struct vty *vty, int *status) +static vector cmd_complete_command_real(vector vline, struct vty *vty, + int *status) { - struct list *completions; - struct graph *cmdgraph = cmd_node_graph (cmdvec, vty->node); + struct list *completions; + struct graph *cmdgraph = cmd_node_graph(cmdvec, vty->node); - enum matcher_rv rv = command_complete (cmdgraph, vline, &completions); + enum matcher_rv rv = command_complete(cmdgraph, vline, &completions); - if (MATCHER_ERROR(rv)) - { - *status = CMD_ERR_NO_MATCH; - return NULL; - } + if (MATCHER_ERROR(rv)) { + *status = CMD_ERR_NO_MATCH; + return NULL; + } - vector comps = completions_to_vec (completions); - list_delete (completions); + vector comps = completions_to_vec(completions); + list_delete(completions); - // set status code appropriately - switch (vector_active (comps)) - { - case 0: - *status = CMD_ERR_NO_MATCH; - break; - case 1: - *status = CMD_COMPLETE_FULL_MATCH; - break; - default: - *status = CMD_COMPLETE_LIST_MATCH; - } + // set status code appropriately + switch (vector_active(comps)) { + case 0: + *status = CMD_ERR_NO_MATCH; + break; + case 1: + *status = CMD_COMPLETE_FULL_MATCH; + break; + default: + *status = CMD_COMPLETE_LIST_MATCH; + } - return comps; + return comps; } -vector -cmd_describe_command (vector vline, struct vty *vty, int *status) +vector cmd_describe_command(vector vline, struct vty *vty, int *status) { - vector ret; + vector ret; - if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) ) - { - enum node_type onode; - vector shifted_vline; - unsigned int index; + if (cmd_try_do_shortcut(vty->node, vector_slot(vline, 0))) { + enum node_type onode; + vector shifted_vline; + unsigned int index; - onode = vty->node; - vty->node = ENABLE_NODE; - /* We can try it on enable node, cos' the vty is authenticated */ + onode = vty->node; + vty->node = ENABLE_NODE; + /* We can try it on enable node, cos' the vty is authenticated + */ - shifted_vline = vector_init (vector_count(vline)); - /* use memcpy? */ - for (index = 1; index < vector_active (vline); index++) - { - vector_set_index (shifted_vline, index-1, vector_lookup(vline, index)); - } + shifted_vline = vector_init(vector_count(vline)); + /* use memcpy? */ + for (index = 1; index < vector_active(vline); index++) { + vector_set_index(shifted_vline, index - 1, + vector_lookup(vline, index)); + } - ret = cmd_complete_command_real (shifted_vline, vty, status); + ret = cmd_complete_command_real(shifted_vline, vty, status); - vector_free(shifted_vline); - vty->node = onode; - return ret; - } + vector_free(shifted_vline); + vty->node = onode; + return ret; + } - return cmd_complete_command_real (vline, vty, status); + return cmd_complete_command_real(vline, vty, status); } static struct list *varhandlers = NULL; -void -cmd_variable_complete (struct cmd_token *token, const char *arg, vector comps) -{ - struct listnode *ln; - const struct cmd_variable_handler *cvh; - size_t i, argsz; - vector tmpcomps; - - tmpcomps = arg ? vector_init (VECTOR_MIN_SIZE) : comps; - - for (ALL_LIST_ELEMENTS_RO(varhandlers, ln, cvh)) - { - if (cvh->tokenname && strcmp(cvh->tokenname, token->text)) - continue; - if (cvh->varname && (!token->varname || strcmp(cvh->varname, token->varname))) - continue; - cvh->completions(tmpcomps, token); - break; - } - - if (!arg) - return; - - argsz = strlen(arg); - for (i = vector_active(tmpcomps); i; i--) - { - char *item = vector_slot(tmpcomps, i - 1); - if (strlen(item) >= argsz - && !strncmp(item, arg, argsz)) - vector_set(comps, item); - else - XFREE(MTYPE_COMPLETION, item); - } - vector_free(tmpcomps); +void cmd_variable_complete(struct cmd_token *token, const char *arg, + vector comps) +{ + struct listnode *ln; + const struct cmd_variable_handler *cvh; + size_t i, argsz; + vector tmpcomps; + + tmpcomps = arg ? vector_init(VECTOR_MIN_SIZE) : comps; + + for (ALL_LIST_ELEMENTS_RO(varhandlers, ln, cvh)) { + if (cvh->tokenname && strcmp(cvh->tokenname, token->text)) + continue; + if (cvh->varname && (!token->varname + || strcmp(cvh->varname, token->varname))) + continue; + cvh->completions(tmpcomps, token); + break; + } + + if (!arg) + return; + + argsz = strlen(arg); + for (i = vector_active(tmpcomps); i; i--) { + char *item = vector_slot(tmpcomps, i - 1); + if (strlen(item) >= argsz && !strncmp(item, arg, argsz)) + vector_set(comps, item); + else + XFREE(MTYPE_COMPLETION, item); + } + vector_free(tmpcomps); } #define AUTOCOMP_INDENT 5 -char * -cmd_variable_comp2str(vector comps, unsigned short cols) +char *cmd_variable_comp2str(vector comps, unsigned short cols) { - size_t bsz = 16; - char *buf = XCALLOC(MTYPE_TMP, bsz); - int lc = AUTOCOMP_INDENT; - size_t cs = AUTOCOMP_INDENT; - size_t itemlen; - snprintf(buf, bsz, "%*s", AUTOCOMP_INDENT, ""); - for (size_t j = 0; j < vector_active (comps); j++) - { - char *item = vector_slot (comps, j); - itemlen = strlen(item); + size_t bsz = 16; + char *buf = XCALLOC(MTYPE_TMP, bsz); + int lc = AUTOCOMP_INDENT; + size_t cs = AUTOCOMP_INDENT; + size_t itemlen; + snprintf(buf, bsz, "%*s", AUTOCOMP_INDENT, ""); + for (size_t j = 0; j < vector_active(comps); j++) { + char *item = vector_slot(comps, j); + itemlen = strlen(item); - if (cs + itemlen + AUTOCOMP_INDENT + 3 >= bsz) - buf = XREALLOC(MTYPE_TMP, buf, (bsz *= 2)); + if (cs + itemlen + AUTOCOMP_INDENT + 3 >= bsz) + buf = XREALLOC(MTYPE_TMP, buf, (bsz *= 2)); - if (lc + itemlen + 1 >= cols) - { - cs += snprintf(&buf[cs], bsz - cs, "\n%*s", AUTOCOMP_INDENT, ""); - lc = AUTOCOMP_INDENT; - } + if (lc + itemlen + 1 >= cols) { + cs += snprintf(&buf[cs], bsz - cs, "\n%*s", + AUTOCOMP_INDENT, ""); + lc = AUTOCOMP_INDENT; + } - size_t written = snprintf(&buf[cs], bsz - cs, "%s ", item); - lc += written; - cs += written; - XFREE (MTYPE_COMPLETION, item); - vector_set_index (comps, j, NULL); - } - return buf; + size_t written = snprintf(&buf[cs], bsz - cs, "%s ", item); + lc += written; + cs += written; + XFREE(MTYPE_COMPLETION, item); + vector_set_index(comps, j, NULL); + } + return buf; } -void -cmd_variable_handler_register (const struct cmd_variable_handler *cvh) +void cmd_variable_handler_register(const struct cmd_variable_handler *cvh) { - if (!varhandlers) - return; + if (!varhandlers) + return; - for (; cvh->completions; cvh++) - listnode_add(varhandlers, (void *)cvh); + for (; cvh->completions; cvh++) + listnode_add(varhandlers, (void *)cvh); } DEFUN_HIDDEN (autocomplete, @@ -767,28 +719,27 @@ DEFUN_HIDDEN (autocomplete, "cmd_token->text\n" "cmd_token->varname\n") { - struct cmd_token tok; - vector comps = vector_init(32); - size_t i; + struct cmd_token tok; + vector comps = vector_init(32); + size_t i; - memset(&tok, 0, sizeof(tok)); - tok.type = atoi(argv[1]->arg); - tok.text = argv[2]->arg; - tok.varname = argv[3]->arg; - if (!strcmp(tok.varname, "-")) - tok.varname = NULL; + memset(&tok, 0, sizeof(tok)); + tok.type = atoi(argv[1]->arg); + tok.text = argv[2]->arg; + tok.varname = argv[3]->arg; + if (!strcmp(tok.varname, "-")) + tok.varname = NULL; - cmd_variable_complete(&tok, NULL, comps); + cmd_variable_complete(&tok, NULL, comps); - for (i = 0; i < vector_active(comps); i++) - { - char *text = vector_slot(comps, i); - vty_out(vty, "%s\n", text); - XFREE(MTYPE_COMPLETION, text); - } + for (i = 0; i < vector_active(comps); i++) { + char *text = vector_slot(comps, i); + vty_out(vty, "%s\n", text); + XFREE(MTYPE_COMPLETION, text); + } - vector_free(comps); - return CMD_SUCCESS; + vector_free(comps); + return CMD_SUCCESS; } /** @@ -803,196 +754,191 @@ DEFUN_HIDDEN (autocomplete, * @return set of valid strings for use with Readline as tab-completions. */ -char ** -cmd_complete_command (vector vline, struct vty *vty, int *status) -{ - char **ret = NULL; - int original_node = vty->node; - vector input_line = vector_init (vector_count (vline)); - - // if the first token is 'do' we'll want to execute the command in the enable node - int do_shortcut = cmd_try_do_shortcut (vty->node, vector_slot (vline, 0)); - vty->node = do_shortcut ? ENABLE_NODE : original_node; - - // construct the input line we'll be matching on - unsigned int offset = (do_shortcut) ? 1 : 0; - for (unsigned index = 0; index + offset < vector_active (vline); index++) - vector_set_index (input_line, index, vector_lookup (vline, index + offset)); - - // get token completions -- this is a copying operation - vector comps = NULL, initial_comps; - initial_comps = cmd_complete_command_real (input_line, vty, status); - - if (!MATCHER_ERROR (*status)) - { - assert (initial_comps); - // filter out everything that is not suitable for a tab-completion - comps = vector_init (VECTOR_MIN_SIZE); - for (unsigned int i = 0; i < vector_active(initial_comps); i++) - { - struct cmd_token *token = vector_slot (initial_comps, i); - if (token->type == WORD_TKN) - vector_set (comps, XSTRDUP (MTYPE_COMPLETION, token->text)); - else if (IS_VARYING_TOKEN(token->type)) - { - const char *ref = vector_lookup(vline, vector_active (vline) - 1); - cmd_variable_complete (token, ref, comps); - } - } - vector_free (initial_comps); - - // since we filtered results, we need to re-set status code - switch (vector_active (comps)) - { - case 0: - *status = CMD_ERR_NO_MATCH; - break; - case 1: - *status = CMD_COMPLETE_FULL_MATCH; - break; - default: - *status = CMD_COMPLETE_LIST_MATCH; - } - - // copy completions text into an array of char* - ret = XMALLOC (MTYPE_TMP, (vector_active (comps)+1) * sizeof (char *)); - unsigned int i; - for (i = 0; i < vector_active (comps); i++) - { - ret[i] = vector_slot (comps, i); - } - // set the last element to NULL, because this array is used in - // a Readline completion_generator function which expects NULL - // as a sentinel value - ret[i] = NULL; - vector_free (comps); - comps = NULL; - } - else if (initial_comps) - vector_free (initial_comps); - - // comps should always be null here - assert (!comps); - - // free the adjusted input line - vector_free (input_line); - - // reset vty->node to its original value - vty->node = original_node; - - return ret; +char **cmd_complete_command(vector vline, struct vty *vty, int *status) +{ + char **ret = NULL; + int original_node = vty->node; + vector input_line = vector_init(vector_count(vline)); + + // if the first token is 'do' we'll want to execute the command in the + // enable node + int do_shortcut = cmd_try_do_shortcut(vty->node, vector_slot(vline, 0)); + vty->node = do_shortcut ? ENABLE_NODE : original_node; + + // construct the input line we'll be matching on + unsigned int offset = (do_shortcut) ? 1 : 0; + for (unsigned index = 0; index + offset < vector_active(vline); index++) + vector_set_index(input_line, index, + vector_lookup(vline, index + offset)); + + // get token completions -- this is a copying operation + vector comps = NULL, initial_comps; + initial_comps = cmd_complete_command_real(input_line, vty, status); + + if (!MATCHER_ERROR(*status)) { + assert(initial_comps); + // filter out everything that is not suitable for a + // tab-completion + comps = vector_init(VECTOR_MIN_SIZE); + for (unsigned int i = 0; i < vector_active(initial_comps); + i++) { + struct cmd_token *token = vector_slot(initial_comps, i); + if (token->type == WORD_TKN) + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, + token->text)); + else if (IS_VARYING_TOKEN(token->type)) { + const char *ref = vector_lookup( + vline, vector_active(vline) - 1); + cmd_variable_complete(token, ref, comps); + } + } + vector_free(initial_comps); + + // since we filtered results, we need to re-set status code + switch (vector_active(comps)) { + case 0: + *status = CMD_ERR_NO_MATCH; + break; + case 1: + *status = CMD_COMPLETE_FULL_MATCH; + break; + default: + *status = CMD_COMPLETE_LIST_MATCH; + } + + // copy completions text into an array of char* + ret = XMALLOC(MTYPE_TMP, + (vector_active(comps) + 1) * sizeof(char *)); + unsigned int i; + for (i = 0; i < vector_active(comps); i++) { + ret[i] = vector_slot(comps, i); + } + // set the last element to NULL, because this array is used in + // a Readline completion_generator function which expects NULL + // as a sentinel value + ret[i] = NULL; + vector_free(comps); + comps = NULL; + } else if (initial_comps) + vector_free(initial_comps); + + // comps should always be null here + assert(!comps); + + // free the adjusted input line + vector_free(input_line); + + // reset vty->node to its original value + vty->node = original_node; + + return ret; } /* return parent node */ /* MUST eventually converge on CONFIG_NODE */ -enum node_type -node_parent ( enum node_type node ) -{ - enum node_type ret; - - assert (node > CONFIG_NODE); - - switch (node) - { - case BGP_VPNV4_NODE: - case BGP_VPNV6_NODE: - case BGP_VRF_POLICY_NODE: - case BGP_VNC_DEFAULTS_NODE: - case BGP_VNC_NVE_GROUP_NODE: - case BGP_VNC_L2_GROUP_NODE: - case BGP_IPV4_NODE: - case BGP_IPV4M_NODE: - case BGP_IPV4L_NODE: - case BGP_IPV6_NODE: - case BGP_IPV6M_NODE: - case BGP_EVPN_NODE: - case BGP_IPV6L_NODE: - ret = BGP_NODE; - break; - case BGP_EVPN_VNI_NODE: - ret = BGP_EVPN_NODE; - break; - case KEYCHAIN_KEY_NODE: - ret = KEYCHAIN_NODE; - break; - case LINK_PARAMS_NODE: - ret = INTERFACE_NODE; - break; - case LDP_IPV4_NODE: - case LDP_IPV6_NODE: - ret = LDP_NODE; - break; - case LDP_IPV4_IFACE_NODE: - ret = LDP_IPV4_NODE; - break; - case LDP_IPV6_IFACE_NODE: - ret = LDP_IPV6_NODE; - break; - case LDP_PSEUDOWIRE_NODE: - ret = LDP_L2VPN_NODE; - break; - default: - ret = CONFIG_NODE; - break; - } - - return ret; +enum node_type node_parent(enum node_type node) +{ + enum node_type ret; + + assert(node > CONFIG_NODE); + + switch (node) { + case BGP_VPNV4_NODE: + case BGP_VPNV6_NODE: + case BGP_VRF_POLICY_NODE: + case BGP_VNC_DEFAULTS_NODE: + case BGP_VNC_NVE_GROUP_NODE: + case BGP_VNC_L2_GROUP_NODE: + case BGP_IPV4_NODE: + case BGP_IPV4M_NODE: + case BGP_IPV4L_NODE: + case BGP_IPV6_NODE: + case BGP_IPV6M_NODE: + case BGP_EVPN_NODE: + case BGP_IPV6L_NODE: + ret = BGP_NODE; + break; + case BGP_EVPN_VNI_NODE: + ret = BGP_EVPN_NODE; + break; + case KEYCHAIN_KEY_NODE: + ret = KEYCHAIN_NODE; + break; + case LINK_PARAMS_NODE: + ret = INTERFACE_NODE; + break; + case LDP_IPV4_NODE: + case LDP_IPV6_NODE: + ret = LDP_NODE; + break; + case LDP_IPV4_IFACE_NODE: + ret = LDP_IPV4_NODE; + break; + case LDP_IPV6_IFACE_NODE: + ret = LDP_IPV6_NODE; + break; + case LDP_PSEUDOWIRE_NODE: + ret = LDP_L2VPN_NODE; + break; + default: + ret = CONFIG_NODE; + break; + } + + return ret; } /* Execute command by argument vline vector. */ -static int -cmd_execute_command_real (vector vline, - enum filter_type filter, - struct vty *vty, - const struct cmd_element **cmd) -{ - struct list *argv_list; - enum matcher_rv status; - const struct cmd_element *matched_element = NULL; - - struct graph *cmdgraph = cmd_node_graph (cmdvec, vty->node); - status = command_match (cmdgraph, vline, &argv_list, &matched_element); - - if (cmd) - *cmd = matched_element; - - // if matcher error, return corresponding CMD_ERR - if (MATCHER_ERROR(status)) - { - if (argv_list) - list_delete (argv_list); - switch (status) - { - case MATCHER_INCOMPLETE: - return CMD_ERR_INCOMPLETE; - case MATCHER_AMBIGUOUS: - return CMD_ERR_AMBIGUOUS; - default: - return CMD_ERR_NO_MATCH; - } - } - - // build argv array from argv list - struct cmd_token **argv = XMALLOC (MTYPE_TMP, argv_list->count * sizeof (struct cmd_token *)); - struct listnode *ln; - struct cmd_token *token; - unsigned int i = 0; - for (ALL_LIST_ELEMENTS_RO(argv_list,ln,token)) - argv[i++] = token; - - int argc = argv_list->count; - - int ret; - if (matched_element->daemon) - ret = CMD_SUCCESS_DAEMON; - else - ret = matched_element->func (matched_element, vty, argc, argv); - - // delete list and cmd_token's in it - list_delete (argv_list); - XFREE (MTYPE_TMP, argv); - - return ret; +static int cmd_execute_command_real(vector vline, enum filter_type filter, + struct vty *vty, + const struct cmd_element **cmd) +{ + struct list *argv_list; + enum matcher_rv status; + const struct cmd_element *matched_element = NULL; + + struct graph *cmdgraph = cmd_node_graph(cmdvec, vty->node); + status = command_match(cmdgraph, vline, &argv_list, &matched_element); + + if (cmd) + *cmd = matched_element; + + // if matcher error, return corresponding CMD_ERR + if (MATCHER_ERROR(status)) { + if (argv_list) + list_delete(argv_list); + switch (status) { + case MATCHER_INCOMPLETE: + return CMD_ERR_INCOMPLETE; + case MATCHER_AMBIGUOUS: + return CMD_ERR_AMBIGUOUS; + default: + return CMD_ERR_NO_MATCH; + } + } + + // build argv array from argv list + struct cmd_token **argv = XMALLOC( + MTYPE_TMP, argv_list->count * sizeof(struct cmd_token *)); + struct listnode *ln; + struct cmd_token *token; + unsigned int i = 0; + for (ALL_LIST_ELEMENTS_RO(argv_list, ln, token)) + argv[i++] = token; + + int argc = argv_list->count; + + int ret; + if (matched_element->daemon) + ret = CMD_SUCCESS_DAEMON; + else + ret = matched_element->func(matched_element, vty, argc, argv); + + // delete list and cmd_token's in it + list_delete(argv_list); + XFREE(MTYPE_TMP, argv); + + return ret; } /** @@ -1010,58 +956,59 @@ cmd_execute_command_real (vector vline, * @return The status of the command that has been executed or an error code * as to why no command could be executed. */ -int -cmd_execute_command (vector vline, struct vty *vty, - const struct cmd_element **cmd, - int vtysh) +int cmd_execute_command(vector vline, struct vty *vty, + const struct cmd_element **cmd, int vtysh) { - int ret, saved_ret = 0; - enum node_type onode, try_node; + int ret, saved_ret = 0; + enum node_type onode, try_node; - onode = try_node = vty->node; + onode = try_node = vty->node; - if (cmd_try_do_shortcut(vty->node, vector_slot(vline, 0))) - { - vector shifted_vline; - unsigned int index; + if (cmd_try_do_shortcut(vty->node, vector_slot(vline, 0))) { + vector shifted_vline; + unsigned int index; - vty->node = ENABLE_NODE; - /* We can try it on enable node, cos' the vty is authenticated */ + vty->node = ENABLE_NODE; + /* We can try it on enable node, cos' the vty is authenticated + */ - shifted_vline = vector_init (vector_count(vline)); - /* use memcpy? */ - for (index = 1; index < vector_active (vline); index++) - vector_set_index (shifted_vline, index-1, vector_lookup(vline, index)); + shifted_vline = vector_init(vector_count(vline)); + /* use memcpy? */ + for (index = 1; index < vector_active(vline); index++) + vector_set_index(shifted_vline, index - 1, + vector_lookup(vline, index)); - ret = cmd_execute_command_real (shifted_vline, FILTER_RELAXED, vty, cmd); + ret = cmd_execute_command_real(shifted_vline, FILTER_RELAXED, + vty, cmd); - vector_free(shifted_vline); - vty->node = onode; - return ret; - } + vector_free(shifted_vline); + vty->node = onode; + return ret; + } - saved_ret = ret = cmd_execute_command_real (vline, FILTER_RELAXED, vty, cmd); + saved_ret = ret = + cmd_execute_command_real(vline, FILTER_RELAXED, vty, cmd); - if (vtysh) - return saved_ret; + if (vtysh) + return saved_ret; - if (ret != CMD_SUCCESS && ret != CMD_WARNING) - { - /* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */ - while (vty->node > CONFIG_NODE) - { - try_node = node_parent(try_node); - vty->node = try_node; - ret = cmd_execute_command_real (vline, FILTER_RELAXED, vty, cmd); - if (ret == CMD_SUCCESS || ret == CMD_WARNING) - return ret; - } - /* no command succeeded, reset the vty to the original node */ - vty->node = onode; - } + if (ret != CMD_SUCCESS && ret != CMD_WARNING) { + /* This assumes all nodes above CONFIG_NODE are childs of + * CONFIG_NODE */ + while (vty->node > CONFIG_NODE) { + try_node = node_parent(try_node); + vty->node = try_node; + ret = cmd_execute_command_real(vline, FILTER_RELAXED, + vty, cmd); + if (ret == CMD_SUCCESS || ret == CMD_WARNING) + return ret; + } + /* no command succeeded, reset the vty to the original node */ + vty->node = onode; + } - /* return command status for original node */ - return saved_ret; + /* return command status for original node */ + return saved_ret; } /** @@ -1077,102 +1024,97 @@ cmd_execute_command (vector vline, struct vty *vty, * @return The status of the command that has been executed or an error code * as to why no command could be executed. */ -int -cmd_execute_command_strict (vector vline, struct vty *vty, - const struct cmd_element **cmd) +int cmd_execute_command_strict(vector vline, struct vty *vty, + const struct cmd_element **cmd) { - return cmd_execute_command_real(vline, FILTER_STRICT, vty, cmd); + return cmd_execute_command_real(vline, FILTER_STRICT, vty, cmd); } /** - * Parse one line of config, walking up the parse tree attempting to find a match + * Parse one line of config, walking up the parse tree attempting to find a + * match * * @param vty The vty context in which the command should be executed. * @param cmd Pointer where the struct cmd_element* of the match command * will be stored, if any. May be set to NULL if this info is * not needed. - * @param use_daemon Boolean to control whether or not we match on CMD_SUCCESS_DAEMON + * @param use_daemon Boolean to control whether or not we match on + * CMD_SUCCESS_DAEMON * or not. * @return The status of the command that has been executed or an error code * as to why no command could be executed. */ -int -command_config_read_one_line (struct vty *vty, const struct cmd_element **cmd, int use_daemon) +int command_config_read_one_line(struct vty *vty, + const struct cmd_element **cmd, int use_daemon) { - vector vline; - int saved_node; - int ret; + vector vline; + int saved_node; + int ret; - vline = cmd_make_strvec (vty->buf); + vline = cmd_make_strvec(vty->buf); - /* In case of comment line */ - if (vline == NULL) - return CMD_SUCCESS; + /* In case of comment line */ + if (vline == NULL) + return CMD_SUCCESS; - /* Execute configuration command : this is strict match */ - ret = cmd_execute_command_strict (vline, vty, cmd); + /* Execute configuration command : this is strict match */ + ret = cmd_execute_command_strict(vline, vty, cmd); - // Climb the tree and try the command again at each node - if (!(use_daemon && ret == CMD_SUCCESS_DAEMON) && - !(!use_daemon && ret == CMD_ERR_NOTHING_TODO) && - ret != CMD_SUCCESS && - ret != CMD_WARNING && - vty->node != CONFIG_NODE) { + // Climb the tree and try the command again at each node + if (!(use_daemon && ret == CMD_SUCCESS_DAEMON) + && !(!use_daemon && ret == CMD_ERR_NOTHING_TODO) + && ret != CMD_SUCCESS && ret != CMD_WARNING + && vty->node != CONFIG_NODE) { - saved_node = vty->node; + saved_node = vty->node; - while (!(use_daemon && ret == CMD_SUCCESS_DAEMON) && - !(!use_daemon && ret == CMD_ERR_NOTHING_TODO) && - ret != CMD_SUCCESS && - ret != CMD_WARNING && - vty->node > CONFIG_NODE) { - vty->node = node_parent(vty->node); - ret = cmd_execute_command_strict (vline, vty, cmd); - } + while (!(use_daemon && ret == CMD_SUCCESS_DAEMON) + && !(!use_daemon && ret == CMD_ERR_NOTHING_TODO) + && ret != CMD_SUCCESS && ret != CMD_WARNING + && vty->node > CONFIG_NODE) { + vty->node = node_parent(vty->node); + ret = cmd_execute_command_strict(vline, vty, cmd); + } - // If climbing the tree did not work then ignore the command and - // stay at the same node - if (!(use_daemon && ret == CMD_SUCCESS_DAEMON) && - !(!use_daemon && ret == CMD_ERR_NOTHING_TODO) && - ret != CMD_SUCCESS && - ret != CMD_WARNING) - { - vty->node = saved_node; - } - } + // If climbing the tree did not work then ignore the command and + // stay at the same node + if (!(use_daemon && ret == CMD_SUCCESS_DAEMON) + && !(!use_daemon && ret == CMD_ERR_NOTHING_TODO) + && ret != CMD_SUCCESS && ret != CMD_WARNING) { + vty->node = saved_node; + } + } - if (ret != CMD_SUCCESS && ret != CMD_WARNING) - memcpy (vty->error_buf, vty->buf, VTY_BUFSIZ); + if (ret != CMD_SUCCESS && ret != CMD_WARNING) + memcpy(vty->error_buf, vty->buf, VTY_BUFSIZ); - cmd_free_strvec (vline); + cmd_free_strvec(vline); - return ret; + return ret; } /* Configuration make from file. */ -int -config_from_file (struct vty *vty, FILE *fp, unsigned int *line_num) +int config_from_file(struct vty *vty, FILE *fp, unsigned int *line_num) { - int ret, error_ret=0; - *line_num = 0; + int ret, error_ret = 0; + *line_num = 0; - while (fgets (vty->buf, VTY_BUFSIZ, fp)) - { - if (!error_ret) - ++(*line_num); + while (fgets(vty->buf, VTY_BUFSIZ, fp)) { + if (!error_ret) + ++(*line_num); - ret = command_config_read_one_line (vty, NULL, 0); + ret = command_config_read_one_line(vty, NULL, 0); - if (ret != CMD_SUCCESS && ret != CMD_WARNING && - ret != CMD_ERR_NOTHING_TODO) - error_ret = ret; - } + if (ret != CMD_SUCCESS && ret != CMD_WARNING + && ret != CMD_ERR_NOTHING_TODO) + error_ret = ret; + } - if (error_ret) { - return error_ret; - } + if (error_ret) { + return error_ret; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Configuration from terminal */ @@ -1182,14 +1124,13 @@ DEFUN (config_terminal, "Configuration from vty interface\n" "Configuration terminal\n") { - if (vty_config_lock (vty)) - vty->node = CONFIG_NODE; - else - { - vty_out (vty, "VTY configuration is locked by other VTY\n"); - return CMD_WARNING_CONFIG_FAILED; - } - return CMD_SUCCESS; + if (vty_config_lock(vty)) + vty->node = CONFIG_NODE; + else { + vty_out(vty, "VTY configuration is locked by other VTY\n"); + return CMD_WARNING_CONFIG_FAILED; + } + return CMD_SUCCESS; } /* Enable command */ @@ -1198,14 +1139,14 @@ DEFUN (enable, "enable", "Turn on privileged mode command\n") { - /* If enable password is NULL, change to ENABLE_NODE */ - if ((host.enable == NULL && host.enable_encrypt == NULL) || - vty->type == VTY_SHELL_SERV) - vty->node = ENABLE_NODE; - else - vty->node = AUTH_ENABLE_NODE; + /* If enable password is NULL, change to ENABLE_NODE */ + if ((host.enable == NULL && host.enable_encrypt == NULL) + || vty->type == VTY_SHELL_SERV) + vty->node = ENABLE_NODE; + else + vty->node = AUTH_ENABLE_NODE; - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Disable command */ @@ -1214,9 +1155,9 @@ DEFUN (disable, "disable", "Turn off privileged mode command\n") { - if (vty->node == ENABLE_NODE) - vty->node = VIEW_NODE; - return CMD_SUCCESS; + if (vty->node == ENABLE_NODE) + vty->node = VIEW_NODE; + return CMD_SUCCESS; } /* Down vty node level. */ @@ -1225,87 +1166,85 @@ DEFUN (config_exit, "exit", "Exit current mode and down to previous mode\n") { - cmd_exit (vty); - return CMD_SUCCESS; -} - -void -cmd_exit (struct vty *vty) -{ - switch (vty->node) - { - case VIEW_NODE: - case ENABLE_NODE: - if (vty_shell (vty)) - exit (0); - else - vty->status = VTY_CLOSE; - break; - case CONFIG_NODE: - vty->node = ENABLE_NODE; - vty_config_unlock (vty); - break; - case INTERFACE_NODE: - case NS_NODE: - case VRF_NODE: - case ZEBRA_NODE: - case BGP_NODE: - case RIP_NODE: - case EIGRP_NODE: - case BABEL_NODE: - case RIPNG_NODE: - case OSPF_NODE: - case OSPF6_NODE: - case LDP_NODE: - case LDP_L2VPN_NODE: - case ISIS_NODE: - case KEYCHAIN_NODE: - case MASC_NODE: - case RMAP_NODE: - case PIM_NODE: - case VTY_NODE: - vty->node = CONFIG_NODE; - break; - case BGP_IPV4_NODE: - case BGP_IPV4M_NODE: - case BGP_IPV4L_NODE: - case BGP_VPNV4_NODE: - case BGP_VPNV6_NODE: - case BGP_VRF_POLICY_NODE: - case BGP_VNC_DEFAULTS_NODE: - case BGP_VNC_NVE_GROUP_NODE: - case BGP_VNC_L2_GROUP_NODE: - case BGP_IPV6_NODE: - case BGP_IPV6M_NODE: - case BGP_EVPN_NODE: - case BGP_IPV6L_NODE: - vty->node = BGP_NODE; - break; - case BGP_EVPN_VNI_NODE: - vty->node = BGP_EVPN_NODE; - break; - case LDP_IPV4_NODE: - case LDP_IPV6_NODE: - vty->node = LDP_NODE; - break; - case LDP_IPV4_IFACE_NODE: - vty->node = LDP_IPV4_NODE; - break; - case LDP_IPV6_IFACE_NODE: - vty->node = LDP_IPV6_NODE; - break; - case LDP_PSEUDOWIRE_NODE: - vty->node = LDP_L2VPN_NODE; - break; - case KEYCHAIN_KEY_NODE: - vty->node = KEYCHAIN_NODE; - break; - case LINK_PARAMS_NODE: - vty->node = INTERFACE_NODE; - break; - default: - break; - } + cmd_exit(vty); + return CMD_SUCCESS; +} + +void cmd_exit(struct vty *vty) +{ + switch (vty->node) { + case VIEW_NODE: + case ENABLE_NODE: + if (vty_shell(vty)) + exit(0); + else + vty->status = VTY_CLOSE; + break; + case CONFIG_NODE: + vty->node = ENABLE_NODE; + vty_config_unlock(vty); + break; + case INTERFACE_NODE: + case NS_NODE: + case VRF_NODE: + case ZEBRA_NODE: + case BGP_NODE: + case RIP_NODE: + case EIGRP_NODE: + case BABEL_NODE: + case RIPNG_NODE: + case OSPF_NODE: + case OSPF6_NODE: + case LDP_NODE: + case LDP_L2VPN_NODE: + case ISIS_NODE: + case KEYCHAIN_NODE: + case MASC_NODE: + case RMAP_NODE: + case PIM_NODE: + case VTY_NODE: + vty->node = CONFIG_NODE; + break; + case BGP_IPV4_NODE: + case BGP_IPV4M_NODE: + case BGP_IPV4L_NODE: + case BGP_VPNV4_NODE: + case BGP_VPNV6_NODE: + case BGP_VRF_POLICY_NODE: + case BGP_VNC_DEFAULTS_NODE: + case BGP_VNC_NVE_GROUP_NODE: + case BGP_VNC_L2_GROUP_NODE: + case BGP_IPV6_NODE: + case BGP_IPV6M_NODE: + case BGP_EVPN_NODE: + case BGP_IPV6L_NODE: + vty->node = BGP_NODE; + break; + case BGP_EVPN_VNI_NODE: + vty->node = BGP_EVPN_NODE; + break; + case LDP_IPV4_NODE: + case LDP_IPV6_NODE: + vty->node = LDP_NODE; + break; + case LDP_IPV4_IFACE_NODE: + vty->node = LDP_IPV4_NODE; + break; + case LDP_IPV6_IFACE_NODE: + vty->node = LDP_IPV6_NODE; + break; + case LDP_PSEUDOWIRE_NODE: + vty->node = LDP_L2VPN_NODE; + break; + case KEYCHAIN_KEY_NODE: + vty->node = KEYCHAIN_NODE; + break; + case LINK_PARAMS_NODE: + vty->node = INTERFACE_NODE; + break; + default: + break; + } } /* ALIAS_FIXME */ @@ -1314,7 +1253,7 @@ DEFUN (config_quit, "quit", "Exit current mode and down to previous mode\n") { - return config_exit (self, vty, argc, argv); + return config_exit(self, vty, argc, argv); } @@ -1324,60 +1263,59 @@ DEFUN (config_end, "end", "End current mode and change to enable mode.") { - switch (vty->node) - { - case VIEW_NODE: - case ENABLE_NODE: - /* Nothing to do. */ - break; - case CONFIG_NODE: - case INTERFACE_NODE: - case NS_NODE: - case VRF_NODE: - case ZEBRA_NODE: - case RIP_NODE: - case RIPNG_NODE: - case EIGRP_NODE: - case BABEL_NODE: - case BGP_NODE: - case BGP_VRF_POLICY_NODE: - case BGP_VNC_DEFAULTS_NODE: - case BGP_VNC_NVE_GROUP_NODE: - case BGP_VNC_L2_GROUP_NODE: - case BGP_VPNV4_NODE: - case BGP_VPNV6_NODE: - case BGP_IPV4_NODE: - case BGP_IPV4M_NODE: - case BGP_IPV4L_NODE: - case BGP_IPV6_NODE: - case BGP_IPV6M_NODE: - case BGP_EVPN_NODE: - case BGP_EVPN_VNI_NODE: - case BGP_IPV6L_NODE: - case RMAP_NODE: - case OSPF_NODE: - case OSPF6_NODE: - case LDP_NODE: - case LDP_IPV4_NODE: - case LDP_IPV6_NODE: - case LDP_IPV4_IFACE_NODE: - case LDP_IPV6_IFACE_NODE: - case LDP_L2VPN_NODE: - case LDP_PSEUDOWIRE_NODE: - case ISIS_NODE: - case KEYCHAIN_NODE: - case KEYCHAIN_KEY_NODE: - case MASC_NODE: - case PIM_NODE: - case VTY_NODE: - case LINK_PARAMS_NODE: - vty_config_unlock (vty); - vty->node = ENABLE_NODE; - break; - default: - break; - } - return CMD_SUCCESS; + switch (vty->node) { + case VIEW_NODE: + case ENABLE_NODE: + /* Nothing to do. */ + break; + case CONFIG_NODE: + case INTERFACE_NODE: + case NS_NODE: + case VRF_NODE: + case ZEBRA_NODE: + case RIP_NODE: + case RIPNG_NODE: + case EIGRP_NODE: + case BABEL_NODE: + case BGP_NODE: + case BGP_VRF_POLICY_NODE: + case BGP_VNC_DEFAULTS_NODE: + case BGP_VNC_NVE_GROUP_NODE: + case BGP_VNC_L2_GROUP_NODE: + case BGP_VPNV4_NODE: + case BGP_VPNV6_NODE: + case BGP_IPV4_NODE: + case BGP_IPV4M_NODE: + case BGP_IPV4L_NODE: + case BGP_IPV6_NODE: + case BGP_IPV6M_NODE: + case BGP_EVPN_NODE: + case BGP_EVPN_VNI_NODE: + case BGP_IPV6L_NODE: + case RMAP_NODE: + case OSPF_NODE: + case OSPF6_NODE: + case LDP_NODE: + case LDP_IPV4_NODE: + case LDP_IPV6_NODE: + case LDP_IPV4_IFACE_NODE: + case LDP_IPV6_IFACE_NODE: + case LDP_L2VPN_NODE: + case LDP_PSEUDOWIRE_NODE: + case ISIS_NODE: + case KEYCHAIN_NODE: + case KEYCHAIN_KEY_NODE: + case MASC_NODE: + case PIM_NODE: + case VTY_NODE: + case LINK_PARAMS_NODE: + vty_config_unlock(vty); + vty->node = ENABLE_NODE; + break; + default: + break; + } + return CMD_SUCCESS; } /* Show version. */ @@ -1387,13 +1325,12 @@ DEFUN (show_version, SHOW_STR "Displays zebra version\n") { - vty_out (vty, "%s %s (%s).\n", FRR_FULL_NAME, FRR_VERSION, - host.name ? host.name : ""); - vty_out (vty, "%s%s\n", FRR_COPYRIGHT, GIT_INFO); - vty_out (vty, "configured with:\n %s\n", - FRR_CONFIG_ARGS); + vty_out(vty, "%s %s (%s).\n", FRR_FULL_NAME, FRR_VERSION, + host.name ? host.name : ""); + vty_out(vty, "%s%s\n", FRR_COPYRIGHT, GIT_INFO); + vty_out(vty, "configured with:\n %s\n", FRR_CONFIG_ARGS); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* "Set" version ... ignore version tags */ @@ -1405,7 +1342,7 @@ DEFUN (frr_version_defaults, "set of configuration defaults used\n" "version string\n") { - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Help display function for all node. */ @@ -1414,8 +1351,8 @@ DEFUN (config_help, "help", "Description of the interactive help system\n") { - vty_out (vty, - "Quagga VTY provides advanced help feature. When you need help,\n\ + vty_out(vty, + "Quagga VTY provides advanced help feature. When you need help,\n\ anytime at the command line please press '?'.\n\ \n\ If nothing matches, the help list will be empty and you must backup\n\ @@ -1427,76 +1364,69 @@ argument.\n\ 2. Partial help is provided when an abbreviated argument is entered\n\ and you want to know what arguments match the input\n\ (e.g. 'show me?'.)\n\n"); - return CMD_SUCCESS; -} - -static void -permute (struct graph_node *start, struct vty *vty) -{ - static struct list *position = NULL; - if (!position) position = list_new (); - - struct cmd_token *stok = start->data; - struct graph_node *gnn; - struct listnode *ln; - - // recursive dfs - listnode_add (position, start); - for (unsigned int i = 0; i < vector_active (start->to); i++) - { - struct graph_node *gn = vector_slot (start->to, i); - struct cmd_token *tok = gn->data; - if (tok->attr == CMD_ATTR_HIDDEN || - tok->attr == CMD_ATTR_DEPRECATED) - continue; - else if (tok->type == END_TKN || gn == start) - { - vty_out (vty, " "); - for (ALL_LIST_ELEMENTS_RO (position,ln,gnn)) - { - struct cmd_token *tt = gnn->data; - if (tt->type < SPECIAL_TKN) - vty_out (vty, " %s", tt->text); - } - if (gn == start) - vty_out (vty, "..."); - vty_out (vty, "\n"); - } - else - { - bool skip = false; - if (stok->type == FORK_TKN && tok->type != FORK_TKN) - for (ALL_LIST_ELEMENTS_RO (position, ln, gnn)) - if (gnn == gn) - { - skip = true; - break; - } - if (!skip) - permute (gn, vty); - } - } - list_delete_node (position, listtail(position)); -} - -int -cmd_list_cmds (struct vty *vty, int do_permute) -{ - struct cmd_node *node = vector_slot (cmdvec, vty->node); - - if (do_permute) - permute (vector_slot (node->cmdgraph->nodes, 0), vty); - else - { - /* loop over all commands at this node */ - struct cmd_element *element = NULL; - for (unsigned int i = 0; i < vector_active(node->cmd_vector); i++) - if ((element = vector_slot (node->cmd_vector, i)) && - element->attr != CMD_ATTR_DEPRECATED && - element->attr != CMD_ATTR_HIDDEN) - vty_out (vty, " %s\n", element->string); - } - return CMD_SUCCESS; + return CMD_SUCCESS; +} + +static void permute(struct graph_node *start, struct vty *vty) +{ + static struct list *position = NULL; + if (!position) + position = list_new(); + + struct cmd_token *stok = start->data; + struct graph_node *gnn; + struct listnode *ln; + + // recursive dfs + listnode_add(position, start); + for (unsigned int i = 0; i < vector_active(start->to); i++) { + struct graph_node *gn = vector_slot(start->to, i); + struct cmd_token *tok = gn->data; + if (tok->attr == CMD_ATTR_HIDDEN + || tok->attr == CMD_ATTR_DEPRECATED) + continue; + else if (tok->type == END_TKN || gn == start) { + vty_out(vty, " "); + for (ALL_LIST_ELEMENTS_RO(position, ln, gnn)) { + struct cmd_token *tt = gnn->data; + if (tt->type < SPECIAL_TKN) + vty_out(vty, " %s", tt->text); + } + if (gn == start) + vty_out(vty, "..."); + vty_out(vty, "\n"); + } else { + bool skip = false; + if (stok->type == FORK_TKN && tok->type != FORK_TKN) + for (ALL_LIST_ELEMENTS_RO(position, ln, gnn)) + if (gnn == gn) { + skip = true; + break; + } + if (!skip) + permute(gn, vty); + } + } + list_delete_node(position, listtail(position)); +} + +int cmd_list_cmds(struct vty *vty, int do_permute) +{ + struct cmd_node *node = vector_slot(cmdvec, vty->node); + + if (do_permute) + permute(vector_slot(node->cmdgraph->nodes, 0), vty); + else { + /* loop over all commands at this node */ + struct cmd_element *element = NULL; + for (unsigned int i = 0; i < vector_active(node->cmd_vector); + i++) + if ((element = vector_slot(node->cmd_vector, i)) + && element->attr != CMD_ATTR_DEPRECATED + && element->attr != CMD_ATTR_HIDDEN) + vty_out(vty, " %s\n", element->string); + } + return CMD_SUCCESS; } /* Help display function for all node. */ @@ -1506,7 +1436,7 @@ DEFUN (config_list, "Print command list\n" "Print all possible command permutations\n") { - return cmd_list_cmds (vty, argc == 2); + return cmd_list_cmds(vty, argc == 2); } DEFUN (show_commandtree, @@ -1516,37 +1446,33 @@ DEFUN (show_commandtree, "Show command tree\n" "Permutations that we are interested in\n") { - return cmd_list_cmds (vty, argc == 3); + return cmd_list_cmds(vty, argc == 3); } -static void -vty_write_config (struct vty *vty) +static void vty_write_config(struct vty *vty) { - size_t i; - struct cmd_node *node; + size_t i; + struct cmd_node *node; - if (vty->type == VTY_TERM) - { - vty_out (vty, "\nCurrent configuration:\n"); - vty_out (vty, "!\n"); - } + if (vty->type == VTY_TERM) { + vty_out(vty, "\nCurrent configuration:\n"); + vty_out(vty, "!\n"); + } - vty_out (vty, "frr version %s\n", FRR_VER_SHORT); - vty_out (vty, "frr defaults %s\n", DFLT_NAME); - vty_out (vty, "!\n"); + vty_out(vty, "frr version %s\n", FRR_VER_SHORT); + vty_out(vty, "frr defaults %s\n", DFLT_NAME); + vty_out(vty, "!\n"); - for (i = 0; i < vector_active (cmdvec); i++) - if ((node = vector_slot (cmdvec, i)) && node->func - && (node->vtysh || vty->type != VTY_SHELL)) - { - if ((*node->func) (vty)) - vty_out (vty, "!\n"); - } + for (i = 0; i < vector_active(cmdvec); i++) + if ((node = vector_slot(cmdvec, i)) && node->func + && (node->vtysh || vty->type != VTY_SHELL)) { + if ((*node->func)(vty)) + vty_out(vty, "!\n"); + } - if (vty->type == VTY_TERM) - { - vty_out (vty, "end\n"); - } + if (vty->type == VTY_TERM) { + vty_out(vty, "end\n"); + } } /* Write current configuration into file. */ @@ -1559,123 +1485,118 @@ DEFUN (config_write, "Write configuration currently in memory\n" "Write configuration to terminal\n") { - int idx_type = 1; - int fd, dirfd; - char *config_file, *slash; - char *config_file_tmp = NULL; - char *config_file_sav = NULL; - int ret = CMD_WARNING; - struct vty *file_vty; - struct stat conf_stat; - - // if command was 'write terminal' or 'show running-config' - if (argc == 2 && (strmatch(argv[idx_type]->text, "terminal") || - strmatch(argv[0]->text, "show"))) - { - vty_write_config (vty); - return CMD_SUCCESS; - } - - if (host.noconfig) - return CMD_SUCCESS; - - /* Check and see if we are operating under vtysh configuration */ - if (host.config == NULL) - { - vty_out (vty,"Can't save to configuration file, using vtysh.\n"); - return CMD_WARNING; - } - - /* Get filename. */ - config_file = host.config; + int idx_type = 1; + int fd, dirfd; + char *config_file, *slash; + char *config_file_tmp = NULL; + char *config_file_sav = NULL; + int ret = CMD_WARNING; + struct vty *file_vty; + struct stat conf_stat; + + // if command was 'write terminal' or 'show running-config' + if (argc == 2 && (strmatch(argv[idx_type]->text, "terminal") + || strmatch(argv[0]->text, "show"))) { + vty_write_config(vty); + return CMD_SUCCESS; + } + + if (host.noconfig) + return CMD_SUCCESS; + + /* Check and see if we are operating under vtysh configuration */ + if (host.config == NULL) { + vty_out(vty, + "Can't save to configuration file, using vtysh.\n"); + return CMD_WARNING; + } + + /* Get filename. */ + config_file = host.config; #ifndef O_DIRECTORY #define O_DIRECTORY 0 #endif - slash = strrchr (config_file, '/'); - if (slash) - { - char *config_dir = XSTRDUP (MTYPE_TMP, config_file); - config_dir[slash - config_file] = '\0'; - dirfd = open(config_dir, O_DIRECTORY | O_RDONLY); - XFREE (MTYPE_TMP, config_dir); - } - else - dirfd = open(".", O_DIRECTORY | O_RDONLY); - /* if dirfd is invalid, directory sync fails, but we're still OK */ - - config_file_sav = - XMALLOC (MTYPE_TMP, strlen (config_file) + strlen (CONF_BACKUP_EXT) + 1); - strcpy (config_file_sav, config_file); - strcat (config_file_sav, CONF_BACKUP_EXT); - - - config_file_tmp = XMALLOC (MTYPE_TMP, strlen (config_file) + 8); - sprintf (config_file_tmp, "%s.XXXXXX", config_file); - - /* Open file to configuration write. */ - fd = mkstemp (config_file_tmp); - if (fd < 0) - { - vty_out (vty, "Can't open configuration file %s.\n",config_file_tmp); - goto finished; - } - if (fchmod (fd, CONFIGFILE_MASK) != 0) - { - vty_out (vty, "Can't chmod configuration file %s: %s (%d).\n", - config_file_tmp, safe_strerror(errno), errno); - goto finished; - } - - /* Make vty for configuration file. */ - file_vty = vty_new (); - file_vty->wfd = fd; - file_vty->type = VTY_FILE; - - /* Config file header print. */ - vty_out (file_vty, "!\n! Zebra configuration saved from vty\n! "); - vty_time_print (file_vty, 1); - vty_out (file_vty, "!\n"); - vty_write_config (file_vty); - vty_close (file_vty); - - if (stat(config_file, &conf_stat) >= 0) - { - if (unlink (config_file_sav) != 0) - if (errno != ENOENT) - { - vty_out (vty, "Can't unlink backup configuration file %s.\n", - config_file_sav); - goto finished; - } - if (link (config_file, config_file_sav) != 0) - { - vty_out (vty, "Can't backup old configuration file %s.\n", - config_file_sav); - goto finished; - } - if (dirfd >= 0) - fsync (dirfd); - } - if (rename (config_file_tmp, config_file) != 0) - { - vty_out (vty, "Can't save configuration file %s.\n",config_file); - goto finished; - } - if (dirfd >= 0) - fsync (dirfd); - - vty_out (vty, "Configuration saved to %s\n",config_file); - ret = CMD_SUCCESS; + slash = strrchr(config_file, '/'); + if (slash) { + char *config_dir = XSTRDUP(MTYPE_TMP, config_file); + config_dir[slash - config_file] = '\0'; + dirfd = open(config_dir, O_DIRECTORY | O_RDONLY); + XFREE(MTYPE_TMP, config_dir); + } else + dirfd = open(".", O_DIRECTORY | O_RDONLY); + /* if dirfd is invalid, directory sync fails, but we're still OK */ + + config_file_sav = XMALLOC( + MTYPE_TMP, strlen(config_file) + strlen(CONF_BACKUP_EXT) + 1); + strcpy(config_file_sav, config_file); + strcat(config_file_sav, CONF_BACKUP_EXT); + + + config_file_tmp = XMALLOC(MTYPE_TMP, strlen(config_file) + 8); + sprintf(config_file_tmp, "%s.XXXXXX", config_file); + + /* Open file to configuration write. */ + fd = mkstemp(config_file_tmp); + if (fd < 0) { + vty_out(vty, "Can't open configuration file %s.\n", + config_file_tmp); + goto finished; + } + if (fchmod(fd, CONFIGFILE_MASK) != 0) { + vty_out(vty, "Can't chmod configuration file %s: %s (%d).\n", + config_file_tmp, safe_strerror(errno), errno); + goto finished; + } + + /* Make vty for configuration file. */ + file_vty = vty_new(); + file_vty->wfd = fd; + file_vty->type = VTY_FILE; + + /* Config file header print. */ + vty_out(file_vty, "!\n! Zebra configuration saved from vty\n! "); + vty_time_print(file_vty, 1); + vty_out(file_vty, "!\n"); + vty_write_config(file_vty); + vty_close(file_vty); + + if (stat(config_file, &conf_stat) >= 0) { + if (unlink(config_file_sav) != 0) + if (errno != ENOENT) { + vty_out(vty, + "Can't unlink backup configuration file %s.\n", + config_file_sav); + goto finished; + } + if (link(config_file, config_file_sav) != 0) { + vty_out(vty, + "Can't backup old configuration file %s.\n", + config_file_sav); + goto finished; + } + if (dirfd >= 0) + fsync(dirfd); + } + if (rename(config_file_tmp, config_file) != 0) { + vty_out(vty, "Can't save configuration file %s.\n", + config_file); + goto finished; + } + if (dirfd >= 0) + fsync(dirfd); + + vty_out(vty, "Configuration saved to %s\n", config_file); + ret = CMD_SUCCESS; finished: - if (ret != CMD_SUCCESS) - unlink (config_file_tmp); - if (dirfd >= 0) - close (dirfd); - XFREE (MTYPE_TMP, config_file_tmp); - XFREE (MTYPE_TMP, config_file_sav); - return ret; + if (ret != CMD_SUCCESS) + unlink(config_file_tmp); + if (dirfd >= 0) + close(dirfd); + XFREE(MTYPE_TMP, config_file_tmp); + XFREE(MTYPE_TMP, config_file_sav); + return ret; } /* ALIAS_FIXME for 'write ' */ @@ -1685,7 +1606,7 @@ DEFUN (show_running_config, SHOW_STR "running configuration (same as write terminal/memory)\n") { - return config_write (self, vty, argc, argv); + return config_write(self, vty, argc, argv); } /* ALIAS_FIXME for 'write file' */ @@ -1696,9 +1617,9 @@ DEFUN (copy_runningconf_startupconf, "Copy running config to... \n" "Copy running config to startup config (same as write file)\n") { - if (!host.noconfig) - vty_write_config (vty); - return CMD_SUCCESS; + if (!host.noconfig) + vty_write_config(vty); + return CMD_SUCCESS; } /** -- **/ @@ -1709,44 +1630,41 @@ DEFUN (show_startup_config, SHOW_STR "Contents of startup configuration\n") { - char buf[BUFSIZ]; - FILE *confp; + char buf[BUFSIZ]; + FILE *confp; - if (host.noconfig) - return CMD_SUCCESS; - if (host.config == NULL) - return CMD_WARNING; + if (host.noconfig) + return CMD_SUCCESS; + if (host.config == NULL) + return CMD_WARNING; - confp = fopen (host.config, "r"); - if (confp == NULL) - { - vty_out (vty, "Can't open configuration file [%s] due to '%s'\n", - host.config, safe_strerror(errno)); - return CMD_WARNING; - } + confp = fopen(host.config, "r"); + if (confp == NULL) { + vty_out(vty, "Can't open configuration file [%s] due to '%s'\n", + host.config, safe_strerror(errno)); + return CMD_WARNING; + } - while (fgets (buf, BUFSIZ, confp)) - { - char *cp = buf; + while (fgets(buf, BUFSIZ, confp)) { + char *cp = buf; - while (*cp != '\r' && *cp != '\n' && *cp != '\0') - cp++; - *cp = '\0'; + while (*cp != '\r' && *cp != '\n' && *cp != '\0') + cp++; + *cp = '\0'; - vty_out (vty, "%s\n", buf); - } + vty_out(vty, "%s\n", buf); + } - fclose (confp); + fclose(confp); - return CMD_SUCCESS; + return CMD_SUCCESS; } -int -cmd_hostname_set (const char *hostname) +int cmd_hostname_set(const char *hostname) { - XFREE (MTYPE_HOST, host.name); - host.name = hostname ? XSTRDUP (MTYPE_HOST, hostname) : NULL; - return CMD_SUCCESS; + XFREE(MTYPE_HOST, host.name); + host.name = hostname ? XSTRDUP(MTYPE_HOST, hostname) : NULL; + return CMD_SUCCESS; } /* Hostname configuration */ @@ -1756,15 +1674,14 @@ DEFUN (config_hostname, "Set system's network name\n" "This system's network name\n") { - struct cmd_token *word = argv[1]; + struct cmd_token *word = argv[1]; - if (!isalpha((int) word->arg[0])) - { - vty_out (vty, "Please specify string starting with alphabet\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!isalpha((int)word->arg[0])) { + vty_out(vty, "Please specify string starting with alphabet\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return cmd_hostname_set (word->arg); + return cmd_hostname_set(word->arg); } DEFUN (config_no_hostname, @@ -1774,7 +1691,7 @@ DEFUN (config_no_hostname, "Reset system's network name\n" "Host name of this router\n") { - return cmd_hostname_set (NULL); + return cmd_hostname_set(NULL); } /* VTY interface password set. */ @@ -1785,40 +1702,39 @@ DEFUN (config_password, "Specifies a HIDDEN password will follow\n" "The password string\n") { - int idx_8 = 1; - int idx_word = 2; - if (argc == 3) // '8' was specified - { - if (host.password) - XFREE (MTYPE_HOST, host.password); - host.password = NULL; - if (host.password_encrypt) - XFREE (MTYPE_HOST, host.password_encrypt); - host.password_encrypt = XSTRDUP (MTYPE_HOST, argv[idx_word]->arg); - return CMD_SUCCESS; - } - - if (!isalnum (argv[idx_8]->arg[0])) - { - vty_out (vty, - "Please specify string starting with alphanumeric\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (host.password) - XFREE (MTYPE_HOST, host.password); - host.password = NULL; - - if (host.encrypt) - { - if (host.password_encrypt) - XFREE (MTYPE_HOST, host.password_encrypt); - host.password_encrypt = XSTRDUP (MTYPE_HOST, zencrypt (argv[idx_8]->arg)); - } - else - host.password = XSTRDUP (MTYPE_HOST, argv[idx_8]->arg); - - return CMD_SUCCESS; + int idx_8 = 1; + int idx_word = 2; + if (argc == 3) // '8' was specified + { + if (host.password) + XFREE(MTYPE_HOST, host.password); + host.password = NULL; + if (host.password_encrypt) + XFREE(MTYPE_HOST, host.password_encrypt); + host.password_encrypt = + XSTRDUP(MTYPE_HOST, argv[idx_word]->arg); + return CMD_SUCCESS; + } + + if (!isalnum(argv[idx_8]->arg[0])) { + vty_out(vty, + "Please specify string starting with alphanumeric\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (host.password) + XFREE(MTYPE_HOST, host.password); + host.password = NULL; + + if (host.encrypt) { + if (host.password_encrypt) + XFREE(MTYPE_HOST, host.password_encrypt); + host.password_encrypt = + XSTRDUP(MTYPE_HOST, zencrypt(argv[idx_8]->arg)); + } else + host.password = XSTRDUP(MTYPE_HOST, argv[idx_8]->arg); + + return CMD_SUCCESS; } /* VTY enable password set. */ @@ -1830,53 +1746,48 @@ DEFUN (config_enable_password, "Specifies a HIDDEN password will follow\n" "The HIDDEN 'enable' password string\n") { - int idx_8 = 2; - int idx_word = 3; - - /* Crypt type is specified. */ - if (argc == 4) - { - if (argv[idx_8]->arg[0] == '8') - { - if (host.enable) - XFREE (MTYPE_HOST, host.enable); - host.enable = NULL; - - if (host.enable_encrypt) - XFREE (MTYPE_HOST, host.enable_encrypt); - host.enable_encrypt = XSTRDUP (MTYPE_HOST, argv[idx_word]->arg); - - return CMD_SUCCESS; - } - else - { - vty_out (vty, "Unknown encryption type.\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - if (!isalnum (argv[idx_8]->arg[0])) - { - vty_out (vty, - "Please specify string starting with alphanumeric\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (host.enable) - XFREE (MTYPE_HOST, host.enable); - host.enable = NULL; - - /* Plain password input. */ - if (host.encrypt) - { - if (host.enable_encrypt) - XFREE (MTYPE_HOST, host.enable_encrypt); - host.enable_encrypt = XSTRDUP (MTYPE_HOST, zencrypt (argv[idx_8]->arg)); - } - else - host.enable = XSTRDUP (MTYPE_HOST, argv[idx_8]->arg); - - return CMD_SUCCESS; + int idx_8 = 2; + int idx_word = 3; + + /* Crypt type is specified. */ + if (argc == 4) { + if (argv[idx_8]->arg[0] == '8') { + if (host.enable) + XFREE(MTYPE_HOST, host.enable); + host.enable = NULL; + + if (host.enable_encrypt) + XFREE(MTYPE_HOST, host.enable_encrypt); + host.enable_encrypt = + XSTRDUP(MTYPE_HOST, argv[idx_word]->arg); + + return CMD_SUCCESS; + } else { + vty_out(vty, "Unknown encryption type.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + if (!isalnum(argv[idx_8]->arg[0])) { + vty_out(vty, + "Please specify string starting with alphanumeric\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (host.enable) + XFREE(MTYPE_HOST, host.enable); + host.enable = NULL; + + /* Plain password input. */ + if (host.encrypt) { + if (host.enable_encrypt) + XFREE(MTYPE_HOST, host.enable_encrypt); + host.enable_encrypt = + XSTRDUP(MTYPE_HOST, zencrypt(argv[idx_8]->arg)); + } else + host.enable = XSTRDUP(MTYPE_HOST, argv[idx_8]->arg); + + return CMD_SUCCESS; } /* VTY enable password delete. */ @@ -1887,15 +1798,15 @@ DEFUN (no_config_enable_password, "Modify enable password parameters\n" "Assign the privileged level password\n") { - if (host.enable) - XFREE (MTYPE_HOST, host.enable); - host.enable = NULL; + if (host.enable) + XFREE(MTYPE_HOST, host.enable); + host.enable = NULL; - if (host.enable_encrypt) - XFREE (MTYPE_HOST, host.enable_encrypt); - host.enable_encrypt = NULL; + if (host.enable_encrypt) + XFREE(MTYPE_HOST, host.enable_encrypt); + host.enable_encrypt = NULL; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (service_password_encrypt, @@ -1904,25 +1815,25 @@ DEFUN (service_password_encrypt, "Set up miscellaneous service\n" "Enable encrypted passwords\n") { - if (host.encrypt) - return CMD_SUCCESS; + if (host.encrypt) + return CMD_SUCCESS; - host.encrypt = 1; + host.encrypt = 1; - if (host.password) - { - if (host.password_encrypt) - XFREE (MTYPE_HOST, host.password_encrypt); - host.password_encrypt = XSTRDUP (MTYPE_HOST, zencrypt (host.password)); - } - if (host.enable) - { - if (host.enable_encrypt) - XFREE (MTYPE_HOST, host.enable_encrypt); - host.enable_encrypt = XSTRDUP (MTYPE_HOST, zencrypt (host.enable)); - } + if (host.password) { + if (host.password_encrypt) + XFREE(MTYPE_HOST, host.password_encrypt); + host.password_encrypt = + XSTRDUP(MTYPE_HOST, zencrypt(host.password)); + } + if (host.enable) { + if (host.enable_encrypt) + XFREE(MTYPE_HOST, host.enable_encrypt); + host.enable_encrypt = + XSTRDUP(MTYPE_HOST, zencrypt(host.enable)); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_service_password_encrypt, @@ -1932,20 +1843,20 @@ DEFUN (no_service_password_encrypt, "Set up miscellaneous service\n" "Enable encrypted passwords\n") { - if (! host.encrypt) - return CMD_SUCCESS; + if (!host.encrypt) + return CMD_SUCCESS; - host.encrypt = 0; + host.encrypt = 0; - if (host.password_encrypt) - XFREE (MTYPE_HOST, host.password_encrypt); - host.password_encrypt = NULL; + if (host.password_encrypt) + XFREE(MTYPE_HOST, host.password_encrypt); + host.password_encrypt = NULL; - if (host.enable_encrypt) - XFREE (MTYPE_HOST, host.enable_encrypt); - host.enable_encrypt = NULL; + if (host.enable_encrypt) + XFREE(MTYPE_HOST, host.enable_encrypt); + host.enable_encrypt = NULL; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (config_terminal_length, @@ -1955,11 +1866,11 @@ DEFUN (config_terminal_length, "Set number of lines on a screen\n" "Number of lines on screen (0 for no pausing)\n") { - int idx_number = 2; + int idx_number = 2; - vty->lines = atoi (argv[idx_number]->arg); + vty->lines = atoi(argv[idx_number]->arg); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (config_terminal_no_length, @@ -1969,8 +1880,8 @@ DEFUN (config_terminal_no_length, NO_STR "Set number of lines on a screen\n") { - vty->lines = -1; - return CMD_SUCCESS; + vty->lines = -1; + return CMD_SUCCESS; } DEFUN (service_terminal_length, @@ -1980,11 +1891,11 @@ DEFUN (service_terminal_length, "System wide terminal length configuration\n" "Number of lines of VTY (0 means no line control)\n") { - int idx_number = 2; + int idx_number = 2; - host.lines = atoi (argv[idx_number]->arg); + host.lines = atoi(argv[idx_number]->arg); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_service_terminal_length, @@ -1995,8 +1906,8 @@ DEFUN (no_service_terminal_length, "System wide terminal length configuration\n" "Number of lines of VTY (0 means no line control)\n") { - host.lines = -1; - return CMD_SUCCESS; + host.lines = -1; + return CMD_SUCCESS; } DEFUN_HIDDEN (do_echo, @@ -2005,13 +1916,13 @@ DEFUN_HIDDEN (do_echo, "Echo a message back to the vty\n" "The message to echo\n") { - char *message; + char *message; - vty_out (vty, "%s\n", - ((message = argv_concat(argv, argc, 1)) ? message : "")); - if (message) - XFREE(MTYPE_TMP, message); - return CMD_SUCCESS; + vty_out(vty, "%s\n", + ((message = argv_concat(argv, argc, 1)) ? message : "")); + if (message) + XFREE(MTYPE_TMP, message); + return CMD_SUCCESS; } DEFUN (config_logmsg, @@ -2021,19 +1932,20 @@ DEFUN (config_logmsg, LOG_LEVEL_DESC "The message to send\n") { - int idx_log_level = 1; - int idx_message = 2; - int level; - char *message; + int idx_log_level = 1; + int idx_message = 2; + int level; + char *message; - if ((level = level_match(argv[idx_log_level]->arg)) == ZLOG_DISABLED) - return CMD_ERR_NO_MATCH; + if ((level = level_match(argv[idx_log_level]->arg)) == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; - zlog(level, "%s", ((message = argv_concat(argv, argc, idx_message)) ? message : "")); - if (message) - XFREE(MTYPE_TMP, message); + zlog(level, "%s", + ((message = argv_concat(argv, argc, idx_message)) ? message : "")); + if (message) + XFREE(MTYPE_TMP, message); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_logging, @@ -2042,51 +1954,48 @@ DEFUN (show_logging, SHOW_STR "Show current logging configuration\n") { - struct zlog *zl = zlog_default; - - vty_out (vty, "Syslog logging: "); - if (zl->maxlvl[ZLOG_DEST_SYSLOG] == ZLOG_DISABLED) - vty_out (vty, "disabled"); - else - vty_out (vty, "level %s, facility %s, ident %s", - zlog_priority[zl->maxlvl[ZLOG_DEST_SYSLOG]], - facility_name(zl->facility), zl->ident); - vty_out (vty, "\n"); - - vty_out (vty, "Stdout logging: "); - if (zl->maxlvl[ZLOG_DEST_STDOUT] == ZLOG_DISABLED) - vty_out (vty, "disabled"); - else - vty_out (vty, "level %s", - zlog_priority[zl->maxlvl[ZLOG_DEST_STDOUT]]); - vty_out (vty, "\n"); - - vty_out (vty, "Monitor logging: "); - if (zl->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED) - vty_out (vty, "disabled"); - else - vty_out (vty, "level %s", - zlog_priority[zl->maxlvl[ZLOG_DEST_MONITOR]]); - vty_out (vty, "\n"); - - vty_out (vty, "File logging: "); - if ((zl->maxlvl[ZLOG_DEST_FILE] == ZLOG_DISABLED) || - !zl->fp) - vty_out (vty, "disabled"); - else - vty_out (vty, "level %s, filename %s", - zlog_priority[zl->maxlvl[ZLOG_DEST_FILE]], - zl->filename); - vty_out (vty, "\n"); - - vty_out (vty, "Protocol name: %s\n", - zl->protoname); - vty_out (vty, "Record priority: %s\n", - (zl->record_priority ? "enabled" : "disabled")); - vty_out (vty, "Timestamp precision: %d\n", - zl->timestamp_precision); - - return CMD_SUCCESS; + struct zlog *zl = zlog_default; + + vty_out(vty, "Syslog logging: "); + if (zl->maxlvl[ZLOG_DEST_SYSLOG] == ZLOG_DISABLED) + vty_out(vty, "disabled"); + else + vty_out(vty, "level %s, facility %s, ident %s", + zlog_priority[zl->maxlvl[ZLOG_DEST_SYSLOG]], + facility_name(zl->facility), zl->ident); + vty_out(vty, "\n"); + + vty_out(vty, "Stdout logging: "); + if (zl->maxlvl[ZLOG_DEST_STDOUT] == ZLOG_DISABLED) + vty_out(vty, "disabled"); + else + vty_out(vty, "level %s", + zlog_priority[zl->maxlvl[ZLOG_DEST_STDOUT]]); + vty_out(vty, "\n"); + + vty_out(vty, "Monitor logging: "); + if (zl->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED) + vty_out(vty, "disabled"); + else + vty_out(vty, "level %s", + zlog_priority[zl->maxlvl[ZLOG_DEST_MONITOR]]); + vty_out(vty, "\n"); + + vty_out(vty, "File logging: "); + if ((zl->maxlvl[ZLOG_DEST_FILE] == ZLOG_DISABLED) || !zl->fp) + vty_out(vty, "disabled"); + else + vty_out(vty, "level %s, filename %s", + zlog_priority[zl->maxlvl[ZLOG_DEST_FILE]], + zl->filename); + vty_out(vty, "\n"); + + vty_out(vty, "Protocol name: %s\n", zl->protoname); + vty_out(vty, "Record priority: %s\n", + (zl->record_priority ? "enabled" : "disabled")); + vty_out(vty, "Timestamp precision: %d\n", zl->timestamp_precision); + + return CMD_SUCCESS; } DEFUN (config_log_stdout, @@ -2096,19 +2005,18 @@ DEFUN (config_log_stdout, "Set stdout logging level\n" LOG_LEVEL_DESC) { - int idx_log_level = 2; + int idx_log_level = 2; - if (argc == idx_log_level) - { - zlog_set_level (ZLOG_DEST_STDOUT, zlog_default->default_lvl); - return CMD_SUCCESS; - } - int level; + if (argc == idx_log_level) { + zlog_set_level(ZLOG_DEST_STDOUT, zlog_default->default_lvl); + return CMD_SUCCESS; + } + int level; - if ((level = level_match(argv[idx_log_level]->arg)) == ZLOG_DISABLED) - return CMD_ERR_NO_MATCH; - zlog_set_level (ZLOG_DEST_STDOUT, level); - return CMD_SUCCESS; + if ((level = level_match(argv[idx_log_level]->arg)) == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; + zlog_set_level(ZLOG_DEST_STDOUT, level); + return CMD_SUCCESS; } DEFUN (no_config_log_stdout, @@ -2119,8 +2027,8 @@ DEFUN (no_config_log_stdout, "Cancel logging to stdout\n" LOG_LEVEL_DESC) { - zlog_set_level (ZLOG_DEST_STDOUT, ZLOG_DISABLED); - return CMD_SUCCESS; + zlog_set_level(ZLOG_DEST_STDOUT, ZLOG_DISABLED); + return CMD_SUCCESS; } DEFUN (config_log_monitor, @@ -2130,19 +2038,18 @@ DEFUN (config_log_monitor, "Set terminal line (monitor) logging level\n" LOG_LEVEL_DESC) { - int idx_log_level = 2; + int idx_log_level = 2; - if (argc == idx_log_level) - { - zlog_set_level (ZLOG_DEST_MONITOR, zlog_default->default_lvl); - return CMD_SUCCESS; - } - int level; + if (argc == idx_log_level) { + zlog_set_level(ZLOG_DEST_MONITOR, zlog_default->default_lvl); + return CMD_SUCCESS; + } + int level; - if ((level = level_match(argv[idx_log_level]->arg)) == ZLOG_DISABLED) - return CMD_ERR_NO_MATCH; - zlog_set_level (ZLOG_DEST_MONITOR, level); - return CMD_SUCCESS; + if ((level = level_match(argv[idx_log_level]->arg)) == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; + zlog_set_level(ZLOG_DEST_MONITOR, level); + return CMD_SUCCESS; } DEFUN (no_config_log_monitor, @@ -2153,62 +2060,56 @@ DEFUN (no_config_log_monitor, "Disable terminal line (monitor) logging\n" LOG_LEVEL_DESC) { - zlog_set_level (ZLOG_DEST_MONITOR, ZLOG_DISABLED); - return CMD_SUCCESS; + zlog_set_level(ZLOG_DEST_MONITOR, ZLOG_DISABLED); + return CMD_SUCCESS; } -static int -set_log_file(struct vty *vty, const char *fname, int loglevel) +static int set_log_file(struct vty *vty, const char *fname, int loglevel) { - int ret; - char *p = NULL; - const char *fullpath; + int ret; + char *p = NULL; + const char *fullpath; - /* Path detection. */ - if (! IS_DIRECTORY_SEP (*fname)) - { - char cwd[MAXPATHLEN+1]; - cwd[MAXPATHLEN] = '\0'; + /* Path detection. */ + if (!IS_DIRECTORY_SEP(*fname)) { + char cwd[MAXPATHLEN + 1]; + cwd[MAXPATHLEN] = '\0'; - if (getcwd (cwd, MAXPATHLEN) == NULL) - { - zlog_err ("config_log_file: Unable to alloc mem!"); - return CMD_WARNING_CONFIG_FAILED; - } + if (getcwd(cwd, MAXPATHLEN) == NULL) { + zlog_err("config_log_file: Unable to alloc mem!"); + return CMD_WARNING_CONFIG_FAILED; + } - if ( (p = XMALLOC (MTYPE_TMP, strlen (cwd) + strlen (fname) + 2)) - == NULL) - { - zlog_err ("config_log_file: Unable to alloc mem!"); - return CMD_WARNING_CONFIG_FAILED; - } - sprintf (p, "%s/%s", cwd, fname); - fullpath = p; - } - else - fullpath = fname; + if ((p = XMALLOC(MTYPE_TMP, strlen(cwd) + strlen(fname) + 2)) + == NULL) { + zlog_err("config_log_file: Unable to alloc mem!"); + return CMD_WARNING_CONFIG_FAILED; + } + sprintf(p, "%s/%s", cwd, fname); + fullpath = p; + } else + fullpath = fname; - ret = zlog_set_file (fullpath, loglevel); + ret = zlog_set_file(fullpath, loglevel); - if (p) - XFREE (MTYPE_TMP, p); + if (p) + XFREE(MTYPE_TMP, p); - if (!ret) - { - vty_out (vty, "can't open logfile %s\n", fname); - return CMD_WARNING_CONFIG_FAILED; - } + if (!ret) { + vty_out(vty, "can't open logfile %s\n", fname); + return CMD_WARNING_CONFIG_FAILED; + } - if (host.logfile) - XFREE (MTYPE_HOST, host.logfile); + if (host.logfile) + XFREE(MTYPE_HOST, host.logfile); - host.logfile = XSTRDUP (MTYPE_HOST, fname); + host.logfile = XSTRDUP(MTYPE_HOST, fname); #if defined(HAVE_CUMULUS) - if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED) - zlog_default->maxlvl[ZLOG_DEST_SYSLOG] = ZLOG_DISABLED; + if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED) + zlog_default->maxlvl[ZLOG_DEST_SYSLOG] = ZLOG_DISABLED; #endif - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (config_log_file, @@ -2219,17 +2120,17 @@ DEFUN (config_log_file, "Logging filename\n" LOG_LEVEL_DESC) { - int idx_filename = 2; - int idx_log_levels = 3; - if (argc == 4) - { - int level; - if ((level = level_match(argv[idx_log_levels]->arg)) == ZLOG_DISABLED) - return CMD_ERR_NO_MATCH; - return set_log_file(vty, argv[idx_filename]->arg, level); - } - else - return set_log_file(vty, argv[idx_filename]->arg, zlog_default->default_lvl); + int idx_filename = 2; + int idx_log_levels = 3; + if (argc == 4) { + int level; + if ((level = level_match(argv[idx_log_levels]->arg)) + == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; + return set_log_file(vty, argv[idx_filename]->arg, level); + } else + return set_log_file(vty, argv[idx_filename]->arg, + zlog_default->default_lvl); } DEFUN (no_config_log_file, @@ -2241,14 +2142,14 @@ DEFUN (no_config_log_file, "Logging file name\n" "Logging level\n") { - zlog_reset_file (); + zlog_reset_file(); - if (host.logfile) - XFREE (MTYPE_HOST, host.logfile); + if (host.logfile) + XFREE(MTYPE_HOST, host.logfile); - host.logfile = NULL; + host.logfile = NULL; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (config_log_syslog, @@ -2258,20 +2159,18 @@ DEFUN (config_log_syslog, "Set syslog logging level\n" LOG_LEVEL_DESC) { - int idx_log_levels = 2; - if (argc == 3) - { - int level; - if ((level = level_match (argv[idx_log_levels]->arg)) == ZLOG_DISABLED) - return CMD_ERR_NO_MATCH; - zlog_set_level (ZLOG_DEST_SYSLOG, level); - return CMD_SUCCESS; - } - else - { - zlog_set_level (ZLOG_DEST_SYSLOG, zlog_default->default_lvl); - return CMD_SUCCESS; - } + int idx_log_levels = 2; + if (argc == 3) { + int level; + if ((level = level_match(argv[idx_log_levels]->arg)) + == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; + zlog_set_level(ZLOG_DEST_SYSLOG, level); + return CMD_SUCCESS; + } else { + zlog_set_level(ZLOG_DEST_SYSLOG, zlog_default->default_lvl); + return CMD_SUCCESS; + } } DEFUN (no_config_log_syslog, @@ -2283,8 +2182,8 @@ DEFUN (no_config_log_syslog, LOG_FACILITY_DESC LOG_LEVEL_DESC) { - zlog_set_level (ZLOG_DEST_SYSLOG, ZLOG_DISABLED); - return CMD_SUCCESS; + zlog_set_level(ZLOG_DEST_SYSLOG, ZLOG_DISABLED); + return CMD_SUCCESS; } DEFUN (config_log_facility, @@ -2294,11 +2193,11 @@ DEFUN (config_log_facility, "Facility parameter for syslog messages\n" LOG_FACILITY_DESC) { - int idx_target = 2; - int facility = facility_match(argv[idx_target]->arg); + int idx_target = 2; + int facility = facility_match(argv[idx_target]->arg); - zlog_default->facility = facility; - return CMD_SUCCESS; + zlog_default->facility = facility; + return CMD_SUCCESS; } DEFUN (no_config_log_facility, @@ -2309,40 +2208,38 @@ DEFUN (no_config_log_facility, "Reset syslog facility to default (daemon)\n" LOG_FACILITY_DESC) { - zlog_default->facility = LOG_DAEMON; - return CMD_SUCCESS; + zlog_default->facility = LOG_DAEMON; + return CMD_SUCCESS; } -DEFUN_DEPRECATED (config_log_trap, - config_log_trap_cmd, - "log trap ", - "Logging control\n" - "(Deprecated) Set logging level and default for all destinations\n" - LOG_LEVEL_DESC) +DEFUN_DEPRECATED( + config_log_trap, config_log_trap_cmd, + "log trap ", + "Logging control\n" + "(Deprecated) Set logging level and default for all destinations\n" LOG_LEVEL_DESC) { - int new_level ; - int i; + int new_level; + int i; - if ((new_level = level_match(argv[2]->arg)) == ZLOG_DISABLED) - return CMD_ERR_NO_MATCH; + if ((new_level = level_match(argv[2]->arg)) == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; - zlog_default->default_lvl = new_level; - for (i = 0; i < ZLOG_NUM_DESTS; i++) - if (zlog_default->maxlvl[i] != ZLOG_DISABLED) - zlog_default->maxlvl[i] = new_level; - return CMD_SUCCESS; + zlog_default->default_lvl = new_level; + for (i = 0; i < ZLOG_NUM_DESTS; i++) + if (zlog_default->maxlvl[i] != ZLOG_DISABLED) + zlog_default->maxlvl[i] = new_level; + return CMD_SUCCESS; } -DEFUN_DEPRECATED (no_config_log_trap, - no_config_log_trap_cmd, - "no log trap [emergencies|alerts|critical|errors|warnings|notifications|informational|debugging]", - NO_STR - "Logging control\n" - "Permit all logging information\n" - LOG_LEVEL_DESC) +DEFUN_DEPRECATED( + no_config_log_trap, no_config_log_trap_cmd, + "no log trap [emergencies|alerts|critical|errors|warnings|notifications|informational|debugging]", + NO_STR + "Logging control\n" + "Permit all logging information\n" LOG_LEVEL_DESC) { - zlog_default->default_lvl = LOG_DEBUG; - return CMD_SUCCESS; + zlog_default->default_lvl = LOG_DEBUG; + return CMD_SUCCESS; } DEFUN (config_log_record_priority, @@ -2351,8 +2248,8 @@ DEFUN (config_log_record_priority, "Logging control\n" "Log the priority of the message within the message\n") { - zlog_default->record_priority = 1 ; - return CMD_SUCCESS; + zlog_default->record_priority = 1; + return CMD_SUCCESS; } DEFUN (no_config_log_record_priority, @@ -2362,8 +2259,8 @@ DEFUN (no_config_log_record_priority, "Logging control\n" "Do not log the priority of the message within the message\n") { - zlog_default->record_priority = 0 ; - return CMD_SUCCESS; + zlog_default->record_priority = 0; + return CMD_SUCCESS; } DEFUN (config_log_timestamp_precision, @@ -2374,9 +2271,10 @@ DEFUN (config_log_timestamp_precision, "Set the timestamp precision\n" "Number of subsecond digits\n") { - int idx_number = 3; - zlog_default->timestamp_precision = strtoul(argv[idx_number]->arg, NULL, 10); - return CMD_SUCCESS; + int idx_number = 3; + zlog_default->timestamp_precision = + strtoul(argv[idx_number]->arg, NULL, 10); + return CMD_SUCCESS; } DEFUN (no_config_log_timestamp_precision, @@ -2387,32 +2285,29 @@ DEFUN (no_config_log_timestamp_precision, "Timestamp configuration\n" "Reset the timestamp precision to the default value of 0\n") { - zlog_default->timestamp_precision = 0 ; - return CMD_SUCCESS; + zlog_default->timestamp_precision = 0; + return CMD_SUCCESS; } -int -cmd_banner_motd_file (const char *file) +int cmd_banner_motd_file(const char *file) { - int success = CMD_SUCCESS; - char p[PATH_MAX]; - char *rpath; - char *in; + int success = CMD_SUCCESS; + char p[PATH_MAX]; + char *rpath; + char *in; - rpath = realpath (file, p); - if (!rpath) - return CMD_ERR_NO_FILE; - in = strstr (rpath, SYSCONFDIR); - if (in == rpath) - { - if (host.motdfile) - XFREE (MTYPE_HOST, host.motdfile); - host.motdfile = XSTRDUP (MTYPE_HOST, file); - } - else - success = CMD_WARNING_CONFIG_FAILED; + rpath = realpath(file, p); + if (!rpath) + return CMD_ERR_NO_FILE; + in = strstr(rpath, SYSCONFDIR); + if (in == rpath) { + if (host.motdfile) + XFREE(MTYPE_HOST, host.motdfile); + host.motdfile = XSTRDUP(MTYPE_HOST, file); + } else + success = CMD_WARNING_CONFIG_FAILED; - return success; + return success; } DEFUN (banner_motd_file, @@ -2423,16 +2318,16 @@ DEFUN (banner_motd_file, "Banner from a file\n" "Filename\n") { - int idx_file = 3; - const char *filename = argv[idx_file]->arg; - int cmd = cmd_banner_motd_file (filename); + int idx_file = 3; + const char *filename = argv[idx_file]->arg; + int cmd = cmd_banner_motd_file(filename); - if (cmd == CMD_ERR_NO_FILE) - vty_out (vty, "%s does not exist", filename); - else if (cmd == CMD_WARNING_CONFIG_FAILED) - vty_out (vty, "%s must be in %s", filename, SYSCONFDIR); + if (cmd == CMD_ERR_NO_FILE) + vty_out(vty, "%s does not exist", filename); + else if (cmd == CMD_WARNING_CONFIG_FAILED) + vty_out(vty, "%s must be in %s", filename, SYSCONFDIR); - return cmd; + return cmd; } DEFUN (banner_motd_default, @@ -2442,8 +2337,8 @@ DEFUN (banner_motd_default, "Strings for motd\n" "Default string\n") { - host.motd = default_motd; - return CMD_SUCCESS; + host.motd = default_motd; + return CMD_SUCCESS; } DEFUN (no_banner_motd, @@ -2453,41 +2348,38 @@ DEFUN (no_banner_motd, "Set banner string\n" "Strings for motd\n") { - host.motd = NULL; - if (host.motdfile) - XFREE (MTYPE_HOST, host.motdfile); - host.motdfile = NULL; - return CMD_SUCCESS; + host.motd = NULL; + if (host.motdfile) + XFREE(MTYPE_HOST, host.motdfile); + host.motdfile = NULL; + return CMD_SUCCESS; } /* Set config filename. Called from vty.c */ -void -host_config_set (const char *filename) +void host_config_set(const char *filename) { - if (host.config) - XFREE (MTYPE_HOST, host.config); - host.config = XSTRDUP (MTYPE_HOST, filename); + if (host.config) + XFREE(MTYPE_HOST, host.config); + host.config = XSTRDUP(MTYPE_HOST, filename); } -const char * -host_config_get (void) +const char *host_config_get(void) { - return host.config; + return host.config; } -void -install_default (enum node_type node) +void install_default(enum node_type node) { - install_element (node, &config_exit_cmd); - install_element (node, &config_quit_cmd); - install_element (node, &config_end_cmd); - install_element (node, &config_help_cmd); - install_element (node, &config_list_cmd); + install_element(node, &config_exit_cmd); + install_element(node, &config_quit_cmd); + install_element(node, &config_end_cmd); + install_element(node, &config_help_cmd); + install_element(node, &config_list_cmd); - install_element (node, &config_write_cmd); - install_element (node, &show_running_config_cmd); + install_element(node, &config_write_cmd); + install_element(node, &show_running_config_cmd); - install_element (node, &autocomplete_cmd); + install_element(node, &autocomplete_cmd); } /* Initialize command interface. Install basic nodes and commands. @@ -2495,153 +2387,149 @@ install_default (enum node_type node) * terminal = 0 -- vtysh / no logging, no config control * terminal = 1 -- normal daemon * terminal = -1 -- watchfrr / no logging, but minimal config control */ -void -cmd_init (int terminal) -{ - qobj_init (); - - varhandlers = list_new (); - - /* Allocate initial top vector of commands. */ - cmdvec = vector_init (VECTOR_MIN_SIZE); - - /* Default host value settings. */ - host.name = NULL; - host.password = NULL; - host.enable = NULL; - host.logfile = NULL; - host.config = NULL; - host.noconfig = (terminal < 0); - host.lines = -1; - host.motd = default_motd; - host.motdfile = NULL; - - /* Install top nodes. */ - install_node (&view_node, NULL); - install_node (&enable_node, NULL); - install_node (&auth_node, NULL); - install_node (&auth_enable_node, NULL); - install_node (&config_node, config_write_host); - - /* Each node's basic commands. */ - install_element (VIEW_NODE, &show_version_cmd); - if (terminal) - { - install_element (VIEW_NODE, &config_list_cmd); - install_element (VIEW_NODE, &config_exit_cmd); - install_element (VIEW_NODE, &config_quit_cmd); - install_element (VIEW_NODE, &config_help_cmd); - install_element (VIEW_NODE, &config_enable_cmd); - install_element (VIEW_NODE, &config_terminal_length_cmd); - install_element (VIEW_NODE, &config_terminal_no_length_cmd); - install_element (VIEW_NODE, &show_logging_cmd); - install_element (VIEW_NODE, &show_commandtree_cmd); - install_element (VIEW_NODE, &echo_cmd); - install_element (VIEW_NODE, &autocomplete_cmd); - } - - if (terminal) - { - install_element (ENABLE_NODE, &config_end_cmd); - install_element (ENABLE_NODE, &config_disable_cmd); - install_element (ENABLE_NODE, &config_terminal_cmd); - install_element (ENABLE_NODE, ©_runningconf_startupconf_cmd); - install_element (ENABLE_NODE, &config_write_cmd); - install_element (ENABLE_NODE, &show_running_config_cmd); - } - install_element (ENABLE_NODE, &show_startup_config_cmd); - - if (terminal) - { - install_element (ENABLE_NODE, &config_logmsg_cmd); - install_default (CONFIG_NODE); - - thread_cmd_init (); - workqueue_cmd_init (); - hash_cmd_init (); - } - - install_element (CONFIG_NODE, &hostname_cmd); - install_element (CONFIG_NODE, &no_hostname_cmd); - install_element (CONFIG_NODE, &frr_version_defaults_cmd); - - if (terminal > 0) - { - install_element (CONFIG_NODE, &password_cmd); - install_element (CONFIG_NODE, &enable_password_cmd); - install_element (CONFIG_NODE, &no_enable_password_cmd); - - install_element (CONFIG_NODE, &config_log_stdout_cmd); - install_element (CONFIG_NODE, &no_config_log_stdout_cmd); - install_element (CONFIG_NODE, &config_log_monitor_cmd); - install_element (CONFIG_NODE, &no_config_log_monitor_cmd); - install_element (CONFIG_NODE, &config_log_file_cmd); - install_element (CONFIG_NODE, &no_config_log_file_cmd); - install_element (CONFIG_NODE, &config_log_syslog_cmd); - install_element (CONFIG_NODE, &no_config_log_syslog_cmd); - install_element (CONFIG_NODE, &config_log_facility_cmd); - install_element (CONFIG_NODE, &no_config_log_facility_cmd); - install_element (CONFIG_NODE, &config_log_trap_cmd); - install_element (CONFIG_NODE, &no_config_log_trap_cmd); - install_element (CONFIG_NODE, &config_log_record_priority_cmd); - install_element (CONFIG_NODE, &no_config_log_record_priority_cmd); - install_element (CONFIG_NODE, &config_log_timestamp_precision_cmd); - install_element (CONFIG_NODE, &no_config_log_timestamp_precision_cmd); - install_element (CONFIG_NODE, &service_password_encrypt_cmd); - install_element (CONFIG_NODE, &no_service_password_encrypt_cmd); - install_element (CONFIG_NODE, &banner_motd_default_cmd); - install_element (CONFIG_NODE, &banner_motd_file_cmd); - install_element (CONFIG_NODE, &no_banner_motd_cmd); - install_element (CONFIG_NODE, &service_terminal_length_cmd); - install_element (CONFIG_NODE, &no_service_terminal_length_cmd); - - vrf_install_commands (); - } +void cmd_init(int terminal) +{ + qobj_init(); + + varhandlers = list_new(); + + /* Allocate initial top vector of commands. */ + cmdvec = vector_init(VECTOR_MIN_SIZE); + + /* Default host value settings. */ + host.name = NULL; + host.password = NULL; + host.enable = NULL; + host.logfile = NULL; + host.config = NULL; + host.noconfig = (terminal < 0); + host.lines = -1; + host.motd = default_motd; + host.motdfile = NULL; + + /* Install top nodes. */ + install_node(&view_node, NULL); + install_node(&enable_node, NULL); + install_node(&auth_node, NULL); + install_node(&auth_enable_node, NULL); + install_node(&config_node, config_write_host); + + /* Each node's basic commands. */ + install_element(VIEW_NODE, &show_version_cmd); + if (terminal) { + install_element(VIEW_NODE, &config_list_cmd); + install_element(VIEW_NODE, &config_exit_cmd); + install_element(VIEW_NODE, &config_quit_cmd); + install_element(VIEW_NODE, &config_help_cmd); + install_element(VIEW_NODE, &config_enable_cmd); + install_element(VIEW_NODE, &config_terminal_length_cmd); + install_element(VIEW_NODE, &config_terminal_no_length_cmd); + install_element(VIEW_NODE, &show_logging_cmd); + install_element(VIEW_NODE, &show_commandtree_cmd); + install_element(VIEW_NODE, &echo_cmd); + install_element(VIEW_NODE, &autocomplete_cmd); + } + + if (terminal) { + install_element(ENABLE_NODE, &config_end_cmd); + install_element(ENABLE_NODE, &config_disable_cmd); + install_element(ENABLE_NODE, &config_terminal_cmd); + install_element(ENABLE_NODE, ©_runningconf_startupconf_cmd); + install_element(ENABLE_NODE, &config_write_cmd); + install_element(ENABLE_NODE, &show_running_config_cmd); + } + install_element(ENABLE_NODE, &show_startup_config_cmd); + + if (terminal) { + install_element(ENABLE_NODE, &config_logmsg_cmd); + install_default(CONFIG_NODE); + + thread_cmd_init(); + workqueue_cmd_init(); + hash_cmd_init(); + } + + install_element(CONFIG_NODE, &hostname_cmd); + install_element(CONFIG_NODE, &no_hostname_cmd); + install_element(CONFIG_NODE, &frr_version_defaults_cmd); + + if (terminal > 0) { + install_element(CONFIG_NODE, &password_cmd); + install_element(CONFIG_NODE, &enable_password_cmd); + install_element(CONFIG_NODE, &no_enable_password_cmd); + + install_element(CONFIG_NODE, &config_log_stdout_cmd); + install_element(CONFIG_NODE, &no_config_log_stdout_cmd); + install_element(CONFIG_NODE, &config_log_monitor_cmd); + install_element(CONFIG_NODE, &no_config_log_monitor_cmd); + install_element(CONFIG_NODE, &config_log_file_cmd); + install_element(CONFIG_NODE, &no_config_log_file_cmd); + install_element(CONFIG_NODE, &config_log_syslog_cmd); + install_element(CONFIG_NODE, &no_config_log_syslog_cmd); + install_element(CONFIG_NODE, &config_log_facility_cmd); + install_element(CONFIG_NODE, &no_config_log_facility_cmd); + install_element(CONFIG_NODE, &config_log_trap_cmd); + install_element(CONFIG_NODE, &no_config_log_trap_cmd); + install_element(CONFIG_NODE, &config_log_record_priority_cmd); + install_element(CONFIG_NODE, + &no_config_log_record_priority_cmd); + install_element(CONFIG_NODE, + &config_log_timestamp_precision_cmd); + install_element(CONFIG_NODE, + &no_config_log_timestamp_precision_cmd); + install_element(CONFIG_NODE, &service_password_encrypt_cmd); + install_element(CONFIG_NODE, &no_service_password_encrypt_cmd); + install_element(CONFIG_NODE, &banner_motd_default_cmd); + install_element(CONFIG_NODE, &banner_motd_file_cmd); + install_element(CONFIG_NODE, &no_banner_motd_cmd); + install_element(CONFIG_NODE, &service_terminal_length_cmd); + install_element(CONFIG_NODE, &no_service_terminal_length_cmd); + + vrf_install_commands(); + } #ifdef DEV_BUILD - grammar_sandbox_init(); + grammar_sandbox_init(); #endif } -void -cmd_terminate () -{ - struct cmd_node *cmd_node; - - if (cmdvec) - { - for (unsigned int i = 0; i < vector_active (cmdvec); i++) - if ((cmd_node = vector_slot (cmdvec, i)) != NULL) - { - // deleting the graph delets the cmd_element as well - graph_delete_graph (cmd_node->cmdgraph); - vector_free (cmd_node->cmd_vector); - hash_clean (cmd_node->cmd_hash, NULL); - hash_free (cmd_node->cmd_hash); - cmd_node->cmd_hash = NULL; - } - - vector_free (cmdvec); - cmdvec = NULL; - } - - if (host.name) - XFREE (MTYPE_HOST, host.name); - if (host.password) - XFREE (MTYPE_HOST, host.password); - if (host.password_encrypt) - XFREE (MTYPE_HOST, host.password_encrypt); - if (host.enable) - XFREE (MTYPE_HOST, host.enable); - if (host.enable_encrypt) - XFREE (MTYPE_HOST, host.enable_encrypt); - if (host.logfile) - XFREE (MTYPE_HOST, host.logfile); - if (host.motdfile) - XFREE (MTYPE_HOST, host.motdfile); - if (host.config) - XFREE (MTYPE_HOST, host.config); - - list_delete (varhandlers); - qobj_finish (); +void cmd_terminate() +{ + struct cmd_node *cmd_node; + + if (cmdvec) { + for (unsigned int i = 0; i < vector_active(cmdvec); i++) + if ((cmd_node = vector_slot(cmdvec, i)) != NULL) { + // deleting the graph delets the cmd_element as + // well + graph_delete_graph(cmd_node->cmdgraph); + vector_free(cmd_node->cmd_vector); + hash_clean(cmd_node->cmd_hash, NULL); + hash_free(cmd_node->cmd_hash); + cmd_node->cmd_hash = NULL; + } + + vector_free(cmdvec); + cmdvec = NULL; + } + + if (host.name) + XFREE(MTYPE_HOST, host.name); + if (host.password) + XFREE(MTYPE_HOST, host.password); + if (host.password_encrypt) + XFREE(MTYPE_HOST, host.password_encrypt); + if (host.enable) + XFREE(MTYPE_HOST, host.enable); + if (host.enable_encrypt) + XFREE(MTYPE_HOST, host.enable_encrypt); + if (host.logfile) + XFREE(MTYPE_HOST, host.logfile); + if (host.motdfile) + XFREE(MTYPE_HOST, host.motdfile); + if (host.config) + XFREE(MTYPE_HOST, host.config); + + list_delete(varhandlers); + qobj_finish(); } diff --git a/lib/command.h b/lib/command.h index 4c2c5716b..5d52fe3fc 100644 --- a/lib/command.h +++ b/lib/command.h @@ -37,132 +37,129 @@ DECLARE_MTYPE(COMPLETION) DECLARE_MTYPE(STRVEC) /* Host configuration variable */ -struct host -{ - /* Host name of this router. */ - char *name; +struct host { + /* Host name of this router. */ + char *name; - /* Password for vty interface. */ - char *password; - char *password_encrypt; + /* Password for vty interface. */ + char *password; + char *password_encrypt; - /* Enable password */ - char *enable; - char *enable_encrypt; + /* Enable password */ + char *enable; + char *enable_encrypt; - /* System wide terminal lines. */ - int lines; + /* System wide terminal lines. */ + int lines; - /* Log filename. */ - char *logfile; + /* Log filename. */ + char *logfile; - /* config file name of this host */ - char *config; - int noconfig; + /* config file name of this host */ + char *config; + int noconfig; - /* Flags for services */ - int advanced; - int encrypt; + /* Flags for services */ + int advanced; + int encrypt; - /* Banner configuration. */ - const char *motd; - char *motdfile; + /* Banner configuration. */ + const char *motd; + char *motdfile; }; /* There are some command levels which called from command node. */ -enum node_type -{ - AUTH_NODE, /* Authentication mode of vty interface. */ - VIEW_NODE, /* View node. Default mode of vty interface. */ - AUTH_ENABLE_NODE, /* Authentication mode for change enable. */ - ENABLE_NODE, /* Enable node. */ - CONFIG_NODE, /* Config node. Default mode of config file. */ - SERVICE_NODE, /* Service node. */ - DEBUG_NODE, /* Debug node. */ - VRF_DEBUG_NODE, /* Vrf Debug node. */ - DEBUG_VNC_NODE, /* Debug VNC node. */ - AAA_NODE, /* AAA node. */ - KEYCHAIN_NODE, /* Key-chain node. */ - KEYCHAIN_KEY_NODE, /* Key-chain key node. */ - NS_NODE, /* Logical-Router node. */ - VRF_NODE, /* VRF mode node. */ - INTERFACE_NODE, /* Interface mode node. */ - ZEBRA_NODE, /* zebra connection node. */ - TABLE_NODE, /* rtm_table selection node. */ - RIP_NODE, /* RIP protocol mode node. */ - RIPNG_NODE, /* RIPng protocol mode node. */ - BABEL_NODE, /* BABEL protocol mode node. */ - EIGRP_NODE, /* EIGRP protocol mode node. */ - BGP_NODE, /* BGP protocol mode which includes BGP4+ */ - BGP_VPNV4_NODE, /* BGP MPLS-VPN PE exchange. */ - BGP_VPNV6_NODE, /* BGP MPLS-VPN PE exchange. */ - BGP_IPV4_NODE, /* BGP IPv4 unicast address family. */ - BGP_IPV4M_NODE, /* BGP IPv4 multicast address family. */ - BGP_IPV4L_NODE, /* BGP IPv4 labeled unicast address family. */ - BGP_IPV6_NODE, /* BGP IPv6 address family */ - BGP_IPV6M_NODE, /* BGP IPv6 multicast address family. */ - BGP_IPV6L_NODE, /* BGP IPv6 labeled unicast address family. */ - BGP_VRF_POLICY_NODE, /* BGP VRF policy */ - BGP_VNC_DEFAULTS_NODE, /* BGP VNC nve defaults */ - BGP_VNC_NVE_GROUP_NODE, /* BGP VNC nve group */ - BGP_VNC_L2_GROUP_NODE, /* BGP VNC L2 group */ - RFP_DEFAULTS_NODE, /* RFP defaults node */ - BGP_EVPN_NODE, /* BGP EVPN node. */ - OSPF_NODE, /* OSPF protocol mode */ - OSPF6_NODE, /* OSPF protocol for IPv6 mode */ - LDP_NODE, /* LDP protocol mode */ - LDP_IPV4_NODE, /* LDP IPv4 address family */ - LDP_IPV6_NODE, /* LDP IPv6 address family */ - LDP_IPV4_IFACE_NODE, /* LDP IPv4 Interface */ - LDP_IPV6_IFACE_NODE, /* LDP IPv6 Interface */ - LDP_L2VPN_NODE, /* LDP L2VPN node */ - LDP_PSEUDOWIRE_NODE, /* LDP Pseudowire node */ - ISIS_NODE, /* ISIS protocol mode */ - PIM_NODE, /* PIM protocol mode */ - MASC_NODE, /* MASC for multicast. */ - IRDP_NODE, /* ICMP Router Discovery Protocol mode. */ - IP_NODE, /* Static ip route node. */ - ACCESS_NODE, /* Access list node. */ - PREFIX_NODE, /* Prefix list node. */ - ACCESS_IPV6_NODE, /* Access list node. */ - PREFIX_IPV6_NODE, /* Prefix list node. */ - AS_LIST_NODE, /* AS list node. */ - COMMUNITY_LIST_NODE, /* Community list node. */ - RMAP_NODE, /* Route map node. */ - SMUX_NODE, /* SNMP configuration node. */ - DUMP_NODE, /* Packet dump node. */ - FORWARDING_NODE, /* IP forwarding node. */ - PROTOCOL_NODE, /* protocol filtering node */ - MPLS_NODE, /* MPLS config node */ - VTY_NODE, /* Vty node. */ - LINK_PARAMS_NODE, /* Link-parameters node */ - BGP_EVPN_VNI_NODE, /* BGP EVPN VNI */ +enum node_type { + AUTH_NODE, /* Authentication mode of vty interface. */ + VIEW_NODE, /* View node. Default mode of vty interface. */ + AUTH_ENABLE_NODE, /* Authentication mode for change enable. */ + ENABLE_NODE, /* Enable node. */ + CONFIG_NODE, /* Config node. Default mode of config file. */ + SERVICE_NODE, /* Service node. */ + DEBUG_NODE, /* Debug node. */ + VRF_DEBUG_NODE, /* Vrf Debug node. */ + DEBUG_VNC_NODE, /* Debug VNC node. */ + AAA_NODE, /* AAA node. */ + KEYCHAIN_NODE, /* Key-chain node. */ + KEYCHAIN_KEY_NODE, /* Key-chain key node. */ + NS_NODE, /* Logical-Router node. */ + VRF_NODE, /* VRF mode node. */ + INTERFACE_NODE, /* Interface mode node. */ + ZEBRA_NODE, /* zebra connection node. */ + TABLE_NODE, /* rtm_table selection node. */ + RIP_NODE, /* RIP protocol mode node. */ + RIPNG_NODE, /* RIPng protocol mode node. */ + BABEL_NODE, /* BABEL protocol mode node. */ + EIGRP_NODE, /* EIGRP protocol mode node. */ + BGP_NODE, /* BGP protocol mode which includes BGP4+ */ + BGP_VPNV4_NODE, /* BGP MPLS-VPN PE exchange. */ + BGP_VPNV6_NODE, /* BGP MPLS-VPN PE exchange. */ + BGP_IPV4_NODE, /* BGP IPv4 unicast address family. */ + BGP_IPV4M_NODE, /* BGP IPv4 multicast address family. */ + BGP_IPV4L_NODE, /* BGP IPv4 labeled unicast address family. */ + BGP_IPV6_NODE, /* BGP IPv6 address family */ + BGP_IPV6M_NODE, /* BGP IPv6 multicast address family. */ + BGP_IPV6L_NODE, /* BGP IPv6 labeled unicast address family. */ + BGP_VRF_POLICY_NODE, /* BGP VRF policy */ + BGP_VNC_DEFAULTS_NODE, /* BGP VNC nve defaults */ + BGP_VNC_NVE_GROUP_NODE, /* BGP VNC nve group */ + BGP_VNC_L2_GROUP_NODE, /* BGP VNC L2 group */ + RFP_DEFAULTS_NODE, /* RFP defaults node */ + BGP_EVPN_NODE, /* BGP EVPN node. */ + OSPF_NODE, /* OSPF protocol mode */ + OSPF6_NODE, /* OSPF protocol for IPv6 mode */ + LDP_NODE, /* LDP protocol mode */ + LDP_IPV4_NODE, /* LDP IPv4 address family */ + LDP_IPV6_NODE, /* LDP IPv6 address family */ + LDP_IPV4_IFACE_NODE, /* LDP IPv4 Interface */ + LDP_IPV6_IFACE_NODE, /* LDP IPv6 Interface */ + LDP_L2VPN_NODE, /* LDP L2VPN node */ + LDP_PSEUDOWIRE_NODE, /* LDP Pseudowire node */ + ISIS_NODE, /* ISIS protocol mode */ + PIM_NODE, /* PIM protocol mode */ + MASC_NODE, /* MASC for multicast. */ + IRDP_NODE, /* ICMP Router Discovery Protocol mode. */ + IP_NODE, /* Static ip route node. */ + ACCESS_NODE, /* Access list node. */ + PREFIX_NODE, /* Prefix list node. */ + ACCESS_IPV6_NODE, /* Access list node. */ + PREFIX_IPV6_NODE, /* Prefix list node. */ + AS_LIST_NODE, /* AS list node. */ + COMMUNITY_LIST_NODE, /* Community list node. */ + RMAP_NODE, /* Route map node. */ + SMUX_NODE, /* SNMP configuration node. */ + DUMP_NODE, /* Packet dump node. */ + FORWARDING_NODE, /* IP forwarding node. */ + PROTOCOL_NODE, /* protocol filtering node */ + MPLS_NODE, /* MPLS config node */ + VTY_NODE, /* Vty node. */ + LINK_PARAMS_NODE, /* Link-parameters node */ + BGP_EVPN_VNI_NODE, /* BGP EVPN VNI */ }; /* Node which has some commands and prompt string and configuration function pointer . */ -struct cmd_node -{ - /* Node index. */ - enum node_type node; +struct cmd_node { + /* Node index. */ + enum node_type node; - /* Prompt character at vty interface. */ - const char *prompt; + /* Prompt character at vty interface. */ + const char *prompt; - /* Is this node's configuration goes to vtysh ? */ - int vtysh; + /* Is this node's configuration goes to vtysh ? */ + int vtysh; - /* Node's configuration write function */ - int (*func) (struct vty *); + /* Node's configuration write function */ + int (*func)(struct vty *); - /* Node's command graph */ - struct graph *cmdgraph; + /* Node's command graph */ + struct graph *cmdgraph; - /* Vector of this node's command list. */ - vector cmd_vector; + /* Vector of this node's command list. */ + vector cmd_vector; - /* Hashed index of command node list, for de-dupping primarily */ - struct hash *cmd_hash; + /* Hashed index of command node list, for de-dupping primarily */ + struct hash *cmd_hash; }; /* Return value of the commands. */ @@ -188,101 +185,108 @@ struct cmd_node #ifndef VTYSH_EXTRACT_PL /* helper defines for end-user DEFUN* macros */ -#define DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attrs, dnum) \ - static struct cmd_element cmdname = \ - { \ - .string = cmdstr, \ - .func = funcname, \ - .doc = helpstr, \ - .attr = attrs, \ - .daemon = dnum, \ - .name = #cmdname, \ - }; - -#define DEFUN_CMD_FUNC_DECL(funcname) \ - static int funcname (const struct cmd_element *, struct vty *, int, struct cmd_token *[]); - -#define DEFUN_CMD_FUNC_TEXT(funcname) \ - static int funcname \ - (const struct cmd_element *self __attribute__ ((unused)), \ - struct vty *vty __attribute__ ((unused)), \ - int argc __attribute__ ((unused)), \ - struct cmd_token *argv[] __attribute__ ((unused)) ) - -#define DEFPY(funcname, cmdname, cmdstr, helpstr) \ - DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \ - funcdecl_##funcname - -#define DEFUN(funcname, cmdname, cmdstr, helpstr) \ - DEFUN_CMD_FUNC_DECL(funcname) \ - DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \ - DEFUN_CMD_FUNC_TEXT(funcname) - -#define DEFUN_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \ - DEFUN_CMD_FUNC_DECL(funcname) \ - DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0) \ - DEFUN_CMD_FUNC_TEXT(funcname) - -#define DEFUN_HIDDEN(funcname, cmdname, cmdstr, helpstr) \ - DEFUN_ATTR (funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN) - -#define DEFUN_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \ - DEFUN_ATTR (funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED) \ +#define DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attrs, dnum) \ + static struct cmd_element cmdname = { \ + .string = cmdstr, \ + .func = funcname, \ + .doc = helpstr, \ + .attr = attrs, \ + .daemon = dnum, \ + .name = #cmdname, \ + }; + +#define DEFUN_CMD_FUNC_DECL(funcname) \ + static int funcname(const struct cmd_element *, struct vty *, int, \ + struct cmd_token *[]); + +#define DEFUN_CMD_FUNC_TEXT(funcname) \ + static int funcname(const struct cmd_element *self \ + __attribute__((unused)), \ + struct vty *vty __attribute__((unused)), \ + int argc __attribute__((unused)), \ + struct cmd_token *argv[] __attribute__((unused))) + +#define DEFPY(funcname, cmdname, cmdstr, helpstr) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \ + funcdecl_##funcname + +#define DEFUN(funcname, cmdname, cmdstr, helpstr) \ + DEFUN_CMD_FUNC_DECL(funcname) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \ + DEFUN_CMD_FUNC_TEXT(funcname) + +#define DEFUN_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \ + DEFUN_CMD_FUNC_DECL(funcname) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0) \ + DEFUN_CMD_FUNC_TEXT(funcname) + +#define DEFUN_HIDDEN(funcname, cmdname, cmdstr, helpstr) \ + DEFUN_ATTR(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN) + +#define DEFUN_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \ + DEFUN_ATTR(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED) /* DEFUN_NOSH for commands that vtysh should ignore */ -#define DEFUN_NOSH(funcname, cmdname, cmdstr, helpstr) \ - DEFUN(funcname, cmdname, cmdstr, helpstr) +#define DEFUN_NOSH(funcname, cmdname, cmdstr, helpstr) \ + DEFUN(funcname, cmdname, cmdstr, helpstr) /* DEFSH for vtysh. */ -#define DEFSH(daemon, cmdname, cmdstr, helpstr) \ - DEFUN_CMD_ELEMENT(NULL, cmdname, cmdstr, helpstr, 0, daemon) \ +#define DEFSH(daemon, cmdname, cmdstr, helpstr) \ + DEFUN_CMD_ELEMENT(NULL, cmdname, cmdstr, helpstr, 0, daemon) -#define DEFSH_HIDDEN(daemon, cmdname, cmdstr, helpstr) \ - DEFUN_CMD_ELEMENT(NULL, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, daemon) \ +#define DEFSH_HIDDEN(daemon, cmdname, cmdstr, helpstr) \ + DEFUN_CMD_ELEMENT(NULL, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, \ + daemon) /* DEFUN + DEFSH */ -#define DEFUNSH(daemon, funcname, cmdname, cmdstr, helpstr) \ - DEFUN_CMD_FUNC_DECL(funcname) \ - DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, daemon) \ - DEFUN_CMD_FUNC_TEXT(funcname) +#define DEFUNSH(daemon, funcname, cmdname, cmdstr, helpstr) \ + DEFUN_CMD_FUNC_DECL(funcname) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, daemon) \ + DEFUN_CMD_FUNC_TEXT(funcname) /* DEFUN + DEFSH with attributes */ -#define DEFUNSH_ATTR(daemon, funcname, cmdname, cmdstr, helpstr, attr) \ - DEFUN_CMD_FUNC_DECL(funcname) \ - DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, daemon) \ - DEFUN_CMD_FUNC_TEXT(funcname) +#define DEFUNSH_ATTR(daemon, funcname, cmdname, cmdstr, helpstr, attr) \ + DEFUN_CMD_FUNC_DECL(funcname) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, daemon) \ + DEFUN_CMD_FUNC_TEXT(funcname) -#define DEFUNSH_HIDDEN(daemon, funcname, cmdname, cmdstr, helpstr) \ - DEFUNSH_ATTR (daemon, funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN) +#define DEFUNSH_HIDDEN(daemon, funcname, cmdname, cmdstr, helpstr) \ + DEFUNSH_ATTR(daemon, funcname, cmdname, cmdstr, helpstr, \ + CMD_ATTR_HIDDEN) -#define DEFUNSH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \ - DEFUNSH_ATTR (daemon, funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED) +#define DEFUNSH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \ + DEFUNSH_ATTR(daemon, funcname, cmdname, cmdstr, helpstr, \ + CMD_ATTR_DEPRECATED) /* ALIAS macro which define existing command's alias. */ -#define ALIAS(funcname, cmdname, cmdstr, helpstr) \ - DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) +#define ALIAS(funcname, cmdname, cmdstr, helpstr) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) -#define ALIAS_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \ - DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0) +#define ALIAS_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0) -#define ALIAS_HIDDEN(funcname, cmdname, cmdstr, helpstr) \ - DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, 0) +#define ALIAS_HIDDEN(funcname, cmdname, cmdstr, helpstr) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, \ + 0) -#define ALIAS_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \ - DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED, 0) +#define ALIAS_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, \ + CMD_ATTR_DEPRECATED, 0) -#define ALIAS_SH(daemon, funcname, cmdname, cmdstr, helpstr) \ - DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, daemon) +#define ALIAS_SH(daemon, funcname, cmdname, cmdstr, helpstr) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, daemon) -#define ALIAS_SH_HIDDEN(daemon, funcname, cmdname, cmdstr, helpstr) \ - DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, daemon) +#define ALIAS_SH_HIDDEN(daemon, funcname, cmdname, cmdstr, helpstr) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, \ + daemon) -#define ALIAS_SH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \ - DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED, daemon) +#define ALIAS_SH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, \ + CMD_ATTR_DEPRECATED, daemon) #else /* VTYSH_EXTRACT_PL */ -#define DEFPY(funcname, cmdname, cmdstr, helpstr) \ - DEFUN(funcname, cmdname, cmdstr, helpstr) +#define DEFPY(funcname, cmdname, cmdstr, helpstr) \ + DEFUN(funcname, cmdname, cmdstr, helpstr) #endif /* VTYSH_EXTRACT_PL */ /* Some macroes */ @@ -332,8 +336,8 @@ struct cmd_node #define SECONDS_STR "Seconds\n" #define ROUTE_STR "Routing Table\n" #define PREFIX_LIST_STR "Build a prefix list\n" -#define OSPF6_DUMP_TYPE_LIST \ -"" +#define OSPF6_DUMP_TYPE_LIST \ + "" #define ISIS_STR "IS-IS information\n" #define AREA_TAG_STR "[area tag]\n" #define COMMUNITY_AANN_STR "Community number where AA and NN are (0-65535)\n" @@ -353,60 +357,67 @@ struct cmd_node #define NEIGHBOR_ADDR_STR3 "Neighbor address\nIPv6 address\nInterface name\n" /* Prototypes. */ -extern void install_node (struct cmd_node *, int (*) (struct vty *)); -extern void install_default (enum node_type); -extern void install_element (enum node_type, struct cmd_element *); +extern void install_node(struct cmd_node *, int (*)(struct vty *)); +extern void install_default(enum node_type); +extern void install_element(enum node_type, struct cmd_element *); /* known issue with uninstall_element: changes to cmd_token->attr (i.e. * deprecated/hidden) are not reversed. */ -extern void uninstall_element (enum node_type, struct cmd_element *); +extern void uninstall_element(enum node_type, struct cmd_element *); /* Concatenates argv[shift] through argv[argc-1] into a single NUL-terminated string with a space between each element (allocated using XMALLOC(MTYPE_TMP)). Returns NULL if shift >= argc. */ -extern char *argv_concat (struct cmd_token **argv, int argc, int shift); -extern int argv_find (struct cmd_token **argv, int argc, const char *text, int *index); - -extern vector cmd_make_strvec (const char *); -extern void cmd_free_strvec (vector); -extern vector cmd_describe_command (vector, struct vty *, int *status); -extern char **cmd_complete_command (vector, struct vty *, int *status); -extern const char *cmd_prompt (enum node_type); -extern int command_config_read_one_line (struct vty *vty, const struct cmd_element **, int use_config_node); -extern int config_from_file (struct vty *, FILE *, unsigned int *line_num); -extern enum node_type node_parent (enum node_type); -extern int cmd_execute_command (vector, struct vty *, const struct cmd_element **, int); -extern int cmd_execute_command_strict (vector, struct vty *, const struct cmd_element **); -extern void cmd_init (int); -extern void cmd_terminate (void); -extern void cmd_exit (struct vty *vty); -extern int cmd_list_cmds (struct vty *vty, int do_permute); - -extern int cmd_hostname_set (const char *hostname); +extern char *argv_concat(struct cmd_token **argv, int argc, int shift); +extern int argv_find(struct cmd_token **argv, int argc, const char *text, + int *index); + +extern vector cmd_make_strvec(const char *); +extern void cmd_free_strvec(vector); +extern vector cmd_describe_command(vector, struct vty *, int *status); +extern char **cmd_complete_command(vector, struct vty *, int *status); +extern const char *cmd_prompt(enum node_type); +extern int command_config_read_one_line(struct vty *vty, + const struct cmd_element **, + int use_config_node); +extern int config_from_file(struct vty *, FILE *, unsigned int *line_num); +extern enum node_type node_parent(enum node_type); +extern int cmd_execute_command(vector, struct vty *, + const struct cmd_element **, int); +extern int cmd_execute_command_strict(vector, struct vty *, + const struct cmd_element **); +extern void cmd_init(int); +extern void cmd_terminate(void); +extern void cmd_exit(struct vty *vty); +extern int cmd_list_cmds(struct vty *vty, int do_permute); + +extern int cmd_hostname_set(const char *hostname); /* NOT safe for general use; call this only if DEV_BUILD! */ -extern void grammar_sandbox_init (void); +extern void grammar_sandbox_init(void); -extern vector completions_to_vec (struct list *completions); +extern vector completions_to_vec(struct list *completions); /* Export typical functions. */ -extern const char *host_config_get (void); -extern void host_config_set (const char *); +extern const char *host_config_get(void); +extern void host_config_set(const char *); -extern void print_version (const char *); +extern void print_version(const char *); -extern int cmd_banner_motd_file (const char *); +extern int cmd_banner_motd_file(const char *); /* struct host global, ick */ extern struct host host; struct cmd_variable_handler { - const char *tokenname, *varname; - void (*completions)(vector out, struct cmd_token *token); + const char *tokenname, *varname; + void (*completions)(vector out, struct cmd_token *token); }; -extern void cmd_variable_complete (struct cmd_token *token, const char *arg, vector comps); -extern void cmd_variable_handler_register (const struct cmd_variable_handler *cvh); -extern char *cmd_variable_comp2str (vector comps, unsigned short cols); +extern void cmd_variable_complete(struct cmd_token *token, const char *arg, + vector comps); +extern void +cmd_variable_handler_register(const struct cmd_variable_handler *cvh); +extern char *cmd_variable_comp2str(vector comps, unsigned short cols); #endif /* _ZEBRA_COMMAND_H */ diff --git a/lib/command_graph.c b/lib/command_graph.c index 2ae294e5a..3efa4d5cf 100644 --- a/lib/command_graph.c +++ b/lib/command_graph.c @@ -27,199 +27,190 @@ #include "command_graph.h" DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command Tokens") -DEFINE_MTYPE_STATIC(LIB, CMD_DESC, "Command Token Text") -DEFINE_MTYPE_STATIC(LIB, CMD_TEXT, "Command Token Help") -DEFINE_MTYPE( LIB, CMD_ARG, "Command Argument") -DEFINE_MTYPE_STATIC(LIB, CMD_VAR, "Command Argument Name") - -struct cmd_token * -cmd_token_new (enum cmd_token_type type, u_char attr, - const char *text, const char *desc) +DEFINE_MTYPE_STATIC(LIB, CMD_DESC, "Command Token Text") +DEFINE_MTYPE_STATIC(LIB, CMD_TEXT, "Command Token Help") +DEFINE_MTYPE(LIB, CMD_ARG, "Command Argument") +DEFINE_MTYPE_STATIC(LIB, CMD_VAR, "Command Argument Name") + +struct cmd_token *cmd_token_new(enum cmd_token_type type, u_char attr, + const char *text, const char *desc) { - struct cmd_token *token = XCALLOC (MTYPE_CMD_TOKENS, sizeof (struct cmd_token)); - token->type = type; - token->attr = attr; - token->text = text ? XSTRDUP (MTYPE_CMD_TEXT, text) : NULL; - token->desc = desc ? XSTRDUP (MTYPE_CMD_DESC, desc) : NULL; - token->refcnt = 1; - token->arg = NULL; - token->allowrepeat = false; - token->varname = NULL; - - return token; + struct cmd_token *token = + XCALLOC(MTYPE_CMD_TOKENS, sizeof(struct cmd_token)); + token->type = type; + token->attr = attr; + token->text = text ? XSTRDUP(MTYPE_CMD_TEXT, text) : NULL; + token->desc = desc ? XSTRDUP(MTYPE_CMD_DESC, desc) : NULL; + token->refcnt = 1; + token->arg = NULL; + token->allowrepeat = false; + token->varname = NULL; + + return token; } -void -cmd_token_del (struct cmd_token *token) +void cmd_token_del(struct cmd_token *token) { - if (!token) return; + if (!token) + return; - XFREE (MTYPE_CMD_TEXT, token->text); - XFREE (MTYPE_CMD_DESC, token->desc); - XFREE (MTYPE_CMD_ARG, token->arg); - XFREE (MTYPE_CMD_VAR, token->varname); + XFREE(MTYPE_CMD_TEXT, token->text); + XFREE(MTYPE_CMD_DESC, token->desc); + XFREE(MTYPE_CMD_ARG, token->arg); + XFREE(MTYPE_CMD_VAR, token->varname); - XFREE (MTYPE_CMD_TOKENS, token); + XFREE(MTYPE_CMD_TOKENS, token); } -struct cmd_token * -cmd_token_dup (struct cmd_token *token) +struct cmd_token *cmd_token_dup(struct cmd_token *token) { - struct cmd_token *copy = cmd_token_new (token->type, token->attr, NULL, NULL); - copy->max = token->max; - copy->min = token->min; - copy->text = token->text ? XSTRDUP (MTYPE_CMD_TEXT, token->text) : NULL; - copy->desc = token->desc ? XSTRDUP (MTYPE_CMD_DESC, token->desc) : NULL; - copy->arg = token->arg ? XSTRDUP (MTYPE_CMD_ARG, token->arg) : NULL; - copy->varname = token->varname ? XSTRDUP (MTYPE_CMD_VAR, token->varname) : NULL; - - return copy; + struct cmd_token *copy = + cmd_token_new(token->type, token->attr, NULL, NULL); + copy->max = token->max; + copy->min = token->min; + copy->text = token->text ? XSTRDUP(MTYPE_CMD_TEXT, token->text) : NULL; + copy->desc = token->desc ? XSTRDUP(MTYPE_CMD_DESC, token->desc) : NULL; + copy->arg = token->arg ? XSTRDUP(MTYPE_CMD_ARG, token->arg) : NULL; + copy->varname = + token->varname ? XSTRDUP(MTYPE_CMD_VAR, token->varname) : NULL; + + return copy; } void cmd_token_varname_set(struct cmd_token *token, const char *varname) { - XFREE (MTYPE_CMD_VAR, token->varname); - if (!varname) - { - token->varname = NULL; - return; - } - - size_t len = strlen (varname), i; - token->varname = XMALLOC (MTYPE_CMD_VAR, len + 1); - - for (i = 0; i < len; i++) - switch (varname[i]) - { - case '-': - case '+': - case '*': - case ':': - token->varname[i] = '_'; - break; - default: - token->varname[i] = tolower (varname[i]); - } - token->varname[len] = '\0'; + XFREE(MTYPE_CMD_VAR, token->varname); + if (!varname) { + token->varname = NULL; + return; + } + + size_t len = strlen(varname), i; + token->varname = XMALLOC(MTYPE_CMD_VAR, len + 1); + + for (i = 0; i < len; i++) + switch (varname[i]) { + case '-': + case '+': + case '*': + case ':': + token->varname[i] = '_'; + break; + default: + token->varname[i] = tolower(varname[i]); + } + token->varname[len] = '\0'; } -static bool -cmd_nodes_link (struct graph_node *from, struct graph_node *to) +static bool cmd_nodes_link(struct graph_node *from, struct graph_node *to) { - for (size_t i = 0; i < vector_active (from->to); i++) - if (vector_slot (from->to, i) == to) - return true; - return false; + for (size_t i = 0; i < vector_active(from->to); i++) + if (vector_slot(from->to, i) == to) + return true; + return false; } -static bool cmd_nodes_equal (struct graph_node *ga, struct graph_node *gb); +static bool cmd_nodes_equal(struct graph_node *ga, struct graph_node *gb); /* returns a single node to be excluded as "next" from iteration * - for JOIN_TKN, never continue back to the FORK_TKN * - in all other cases, don't try the node itself (in case of "...") */ -static inline struct graph_node * -cmd_loopstop(struct graph_node *gn) +static inline struct graph_node *cmd_loopstop(struct graph_node *gn) { - struct cmd_token *tok = gn->data; - if (tok->type == JOIN_TKN) - return tok->forkjoin; - else - return gn; + struct cmd_token *tok = gn->data; + if (tok->type == JOIN_TKN) + return tok->forkjoin; + else + return gn; } -static bool -cmd_subgraph_equal (struct graph_node *ga, struct graph_node *gb, - struct graph_node *a_join) +static bool cmd_subgraph_equal(struct graph_node *ga, struct graph_node *gb, + struct graph_node *a_join) { - size_t i, j; - struct graph_node *a_fork, *b_fork; - a_fork = cmd_loopstop (ga); - b_fork = cmd_loopstop (gb); - - if (vector_active (ga->to) != vector_active (gb->to)) - return false; - for (i = 0; i < vector_active (ga->to); i++) - { - struct graph_node *cga = vector_slot (ga->to, i); - - for (j = 0; j < vector_active (gb->to); j++) - { - struct graph_node *cgb = vector_slot (gb->to, i); - - if (cga == a_fork && cgb != b_fork) - continue; - if (cga == a_fork && cgb == b_fork) - break; - - if (cmd_nodes_equal (cga, cgb)) - { - if (cga == a_join) - break; - if (cmd_subgraph_equal (cga, cgb, a_join)) - break; - } - } - if (j == vector_active (gb->to)) - return false; - } - return true; + size_t i, j; + struct graph_node *a_fork, *b_fork; + a_fork = cmd_loopstop(ga); + b_fork = cmd_loopstop(gb); + + if (vector_active(ga->to) != vector_active(gb->to)) + return false; + for (i = 0; i < vector_active(ga->to); i++) { + struct graph_node *cga = vector_slot(ga->to, i); + + for (j = 0; j < vector_active(gb->to); j++) { + struct graph_node *cgb = vector_slot(gb->to, i); + + if (cga == a_fork && cgb != b_fork) + continue; + if (cga == a_fork && cgb == b_fork) + break; + + if (cmd_nodes_equal(cga, cgb)) { + if (cga == a_join) + break; + if (cmd_subgraph_equal(cga, cgb, a_join)) + break; + } + } + if (j == vector_active(gb->to)) + return false; + } + return true; } /* deep compare -- for FORK_TKN, the entire subgraph is compared. * this is what's needed since we're not currently trying to partially * merge subgraphs */ -static bool -cmd_nodes_equal (struct graph_node *ga, struct graph_node *gb) +static bool cmd_nodes_equal(struct graph_node *ga, struct graph_node *gb) { - struct cmd_token *a = ga->data, *b = gb->data; - - if (a->type != b->type || a->allowrepeat != b->allowrepeat) - return false; - if (a->type < SPECIAL_TKN && strcmp (a->text, b->text)) - return false; - /* one a ..., the other not. */ - if (cmd_nodes_link (ga, ga) != cmd_nodes_link (gb, gb)) - return false; - if (!a->varname != !b->varname) - return false; - if (a->varname && strcmp (a->varname, b->varname)) - return false; - - switch (a->type) - { - case RANGE_TKN: - return a->min == b->min && a->max == b->max; - - case FORK_TKN: - /* one is keywords, the other just option or selector ... */ - if (cmd_nodes_link (a->forkjoin, ga) != cmd_nodes_link (b->forkjoin, gb)) - return false; - if (cmd_nodes_link (ga, a->forkjoin) != cmd_nodes_link (gb, b->forkjoin)) - return false; - return cmd_subgraph_equal (ga, gb, a->forkjoin); - - default: - return true; - } + struct cmd_token *a = ga->data, *b = gb->data; + + if (a->type != b->type || a->allowrepeat != b->allowrepeat) + return false; + if (a->type < SPECIAL_TKN && strcmp(a->text, b->text)) + return false; + /* one a ..., the other not. */ + if (cmd_nodes_link(ga, ga) != cmd_nodes_link(gb, gb)) + return false; + if (!a->varname != !b->varname) + return false; + if (a->varname && strcmp(a->varname, b->varname)) + return false; + + switch (a->type) { + case RANGE_TKN: + return a->min == b->min && a->max == b->max; + + case FORK_TKN: + /* one is keywords, the other just option or selector ... */ + if (cmd_nodes_link(a->forkjoin, ga) + != cmd_nodes_link(b->forkjoin, gb)) + return false; + if (cmd_nodes_link(ga, a->forkjoin) + != cmd_nodes_link(gb, b->forkjoin)) + return false; + return cmd_subgraph_equal(ga, gb, a->forkjoin); + + default: + return true; + } } -static void -cmd_fork_bump_attr (struct graph_node *gn, struct graph_node *join, - u_char attr) +static void cmd_fork_bump_attr(struct graph_node *gn, struct graph_node *join, + u_char attr) { - size_t i; - struct cmd_token *tok = gn->data; - struct graph_node *stop = cmd_loopstop (gn); - - tok->attr = attr; - for (i = 0; i < vector_active (gn->to); i++) - { - struct graph_node *next = vector_slot (gn->to, i); - if (next == stop || next == join) - continue; - cmd_fork_bump_attr (next, join, attr); - } + size_t i; + struct cmd_token *tok = gn->data; + struct graph_node *stop = cmd_loopstop(gn); + + tok->attr = attr; + for (i = 0; i < vector_active(gn->to); i++) { + struct graph_node *next = vector_slot(gn->to, i); + if (next == stop || next == join) + continue; + cmd_fork_bump_attr(next, join, attr); + } } /* move an entire subtree from the temporary graph resulting from @@ -227,250 +218,238 @@ cmd_fork_bump_attr (struct graph_node *gn, struct graph_node *join, * * this touches rather deeply into the graph code unfortunately. */ -static void -cmd_reparent_tree (struct graph *fromgraph, struct graph *tograph, - struct graph_node *node) +static void cmd_reparent_tree(struct graph *fromgraph, struct graph *tograph, + struct graph_node *node) { - struct graph_node *stop = cmd_loopstop (node); - size_t i; - - for (i = 0; i < vector_active (fromgraph->nodes); i++) - if (vector_slot (fromgraph->nodes, i) == node) - { - /* agressive iteration punching through subgraphs - may hit some - * nodes twice. reparent only if found on old graph */ - vector_unset (fromgraph->nodes, i); - vector_set (tograph->nodes, node); - break; - } - - for (i = 0; i < vector_active (node->to); i++) - { - struct graph_node *next = vector_slot (node->to, i); - if (next != stop) - cmd_reparent_tree (fromgraph, tograph, next); - } + struct graph_node *stop = cmd_loopstop(node); + size_t i; + + for (i = 0; i < vector_active(fromgraph->nodes); i++) + if (vector_slot(fromgraph->nodes, i) == node) { + /* agressive iteration punching through subgraphs - may + * hit some + * nodes twice. reparent only if found on old graph */ + vector_unset(fromgraph->nodes, i); + vector_set(tograph->nodes, node); + break; + } + + for (i = 0; i < vector_active(node->to); i++) { + struct graph_node *next = vector_slot(node->to, i); + if (next != stop) + cmd_reparent_tree(fromgraph, tograph, next); + } } -static void -cmd_free_recur (struct graph *graph, struct graph_node *node, - struct graph_node *stop) +static void cmd_free_recur(struct graph *graph, struct graph_node *node, + struct graph_node *stop) { - struct graph_node *next, *nstop; - - for (size_t i = vector_active (node->to); i; i--) - { - next = vector_slot (node->to, i - 1); - if (next == stop) - continue; - nstop = cmd_loopstop (next); - if (nstop != next) - cmd_free_recur (graph, next, nstop); - cmd_free_recur (graph, nstop, stop); - } - graph_delete_node (graph, node); + struct graph_node *next, *nstop; + + for (size_t i = vector_active(node->to); i; i--) { + next = vector_slot(node->to, i - 1); + if (next == stop) + continue; + nstop = cmd_loopstop(next); + if (nstop != next) + cmd_free_recur(graph, next, nstop); + cmd_free_recur(graph, nstop, stop); + } + graph_delete_node(graph, node); } -static void -cmd_free_node (struct graph *graph, struct graph_node *node) +static void cmd_free_node(struct graph *graph, struct graph_node *node) { - struct cmd_token *tok = node->data; - if (tok->type == JOIN_TKN) - cmd_free_recur (graph, tok->forkjoin, node); - graph_delete_node (graph, node); + struct cmd_token *tok = node->data; + if (tok->type == JOIN_TKN) + cmd_free_recur(graph, tok->forkjoin, node); + graph_delete_node(graph, node); } /* recursive graph merge. call with * old ~= new * (which holds true for old == START_TKN, new == START_TKN) */ -static void -cmd_merge_nodes (struct graph *oldgraph, struct graph *newgraph, - struct graph_node *old, struct graph_node *new, - int direction) +static void cmd_merge_nodes(struct graph *oldgraph, struct graph *newgraph, + struct graph_node *old, struct graph_node *new, + int direction) { - struct cmd_token *tok; - struct graph_node *old_skip, *new_skip; - old_skip = cmd_loopstop (old); - new_skip = cmd_loopstop (new); - - assert (direction == 1 || direction == -1); - - tok = old->data; - tok->refcnt += direction; - - size_t j, i; - for (j = 0; j < vector_active (new->to); j++) - { - struct graph_node *cnew = vector_slot (new->to, j); - if (cnew == new_skip) - continue; - - for (i = 0; i < vector_active (old->to); i++) - { - struct graph_node *cold = vector_slot (old->to, i); - if (cold == old_skip) - continue; - - if (cmd_nodes_equal (cold, cnew)) - { - struct cmd_token *told = cold->data, *tnew = cnew->data; - - if (told->type == END_TKN) - { - if (direction < 0) - { - graph_delete_node (oldgraph, vector_slot (cold->to, 0)); - graph_delete_node (oldgraph, cold); - } - else - /* force no-match handling to install END_TKN */ - i = vector_active (old->to); - break; - } - - /* the entire fork compared as equal, we continue after it. */ - if (told->type == FORK_TKN) - { - if (tnew->attr < told->attr && direction > 0) - cmd_fork_bump_attr (cold, told->forkjoin, tnew->attr); - /* XXX: no reverse bump on uninstall */ - told = (cold = told->forkjoin)->data; - tnew = (cnew = tnew->forkjoin)->data; - } - if (tnew->attr < told->attr) - told->attr = tnew->attr; - - cmd_merge_nodes (oldgraph, newgraph, cold, cnew, direction); - break; - } - } - /* nothing found => add new to old */ - if (i == vector_active (old->to) && direction > 0) - { - graph_remove_edge (new, cnew); - - cmd_reparent_tree (newgraph, oldgraph, cnew); - - graph_add_edge (old, cnew); - } - } - - if (!tok->refcnt) - cmd_free_node (oldgraph, old); + struct cmd_token *tok; + struct graph_node *old_skip, *new_skip; + old_skip = cmd_loopstop(old); + new_skip = cmd_loopstop(new); + + assert(direction == 1 || direction == -1); + + tok = old->data; + tok->refcnt += direction; + + size_t j, i; + for (j = 0; j < vector_active(new->to); j++) { + struct graph_node *cnew = vector_slot(new->to, j); + if (cnew == new_skip) + continue; + + for (i = 0; i < vector_active(old->to); i++) { + struct graph_node *cold = vector_slot(old->to, i); + if (cold == old_skip) + continue; + + if (cmd_nodes_equal(cold, cnew)) { + struct cmd_token *told = cold->data, + *tnew = cnew->data; + + if (told->type == END_TKN) { + if (direction < 0) { + graph_delete_node( + oldgraph, + vector_slot(cold->to, + 0)); + graph_delete_node(oldgraph, + cold); + } else + /* force no-match handling to + * install END_TKN */ + i = vector_active(old->to); + break; + } + + /* the entire fork compared as equal, we + * continue after it. */ + if (told->type == FORK_TKN) { + if (tnew->attr < told->attr + && direction > 0) + cmd_fork_bump_attr( + cold, told->forkjoin, + tnew->attr); + /* XXX: no reverse bump on uninstall */ + told = (cold = told->forkjoin)->data; + tnew = (cnew = tnew->forkjoin)->data; + } + if (tnew->attr < told->attr) + told->attr = tnew->attr; + + cmd_merge_nodes(oldgraph, newgraph, cold, cnew, + direction); + break; + } + } + /* nothing found => add new to old */ + if (i == vector_active(old->to) && direction > 0) { + graph_remove_edge(new, cnew); + + cmd_reparent_tree(newgraph, oldgraph, cnew); + + graph_add_edge(old, cnew); + } + } + + if (!tok->refcnt) + cmd_free_node(oldgraph, old); } -void -cmd_graph_merge (struct graph *old, struct graph *new, int direction) +void cmd_graph_merge(struct graph *old, struct graph *new, int direction) { - assert (vector_active (old->nodes) >= 1); - assert (vector_active (new->nodes) >= 1); + assert(vector_active(old->nodes) >= 1); + assert(vector_active(new->nodes) >= 1); - cmd_merge_nodes (old, new, - vector_slot (old->nodes, 0), vector_slot (new->nodes, 0), - direction); + cmd_merge_nodes(old, new, vector_slot(old->nodes, 0), + vector_slot(new->nodes, 0), direction); } -static void -cmd_node_names (struct graph_node *gn, struct graph_node *join, - const char *prevname) +static void cmd_node_names(struct graph_node *gn, struct graph_node *join, + const char *prevname) { - size_t i; - struct cmd_token *tok = gn->data, *jointok; - struct graph_node *stop = cmd_loopstop (gn); - - switch (tok->type) - { - case WORD_TKN: - prevname = tok->text; - break; - - case VARIABLE_TKN: - if (!tok->varname - && strcmp (tok->text, "WORD") - && strcmp (tok->text, "NAME")) - cmd_token_varname_set (tok, tok->text); - /* fallthrough */ - case RANGE_TKN: - case IPV4_TKN: - case IPV4_PREFIX_TKN: - case IPV6_TKN: - case IPV6_PREFIX_TKN: - if (!tok->varname && prevname) - cmd_token_varname_set (tok, prevname); - prevname = NULL; - break; - - case START_TKN: - case END_TKN: - case JOIN_TKN: - /* " WORD" -> word is not "bar" or "foo" */ - prevname = NULL; - break; - - case FORK_TKN: - /* apply "$name" */ - jointok = tok->forkjoin->data; - if (!jointok->varname) - break; - for (i = 0; i < vector_active (tok->forkjoin->from); i++) - { - struct graph_node *tail = vector_slot (tok->forkjoin->from, i); - struct cmd_token *tailtok = tail->data; - if (tail == gn || tailtok->varname) - continue; - cmd_token_varname_set (tailtok, jointok->varname); - } - break; - } - - for (i = 0; i < vector_active (gn->to); i++) - { - struct graph_node *next = vector_slot (gn->to, i); - if (next == stop || next == join) - continue; - cmd_node_names (next, join, prevname); - } - - if (tok->type == FORK_TKN && tok->forkjoin != join) - cmd_node_names (tok->forkjoin, join, NULL); + size_t i; + struct cmd_token *tok = gn->data, *jointok; + struct graph_node *stop = cmd_loopstop(gn); + + switch (tok->type) { + case WORD_TKN: + prevname = tok->text; + break; + + case VARIABLE_TKN: + if (!tok->varname && strcmp(tok->text, "WORD") + && strcmp(tok->text, "NAME")) + cmd_token_varname_set(tok, tok->text); + /* fallthrough */ + case RANGE_TKN: + case IPV4_TKN: + case IPV4_PREFIX_TKN: + case IPV6_TKN: + case IPV6_PREFIX_TKN: + if (!tok->varname && prevname) + cmd_token_varname_set(tok, prevname); + prevname = NULL; + break; + + case START_TKN: + case END_TKN: + case JOIN_TKN: + /* " WORD" -> word is not "bar" or "foo" */ + prevname = NULL; + break; + + case FORK_TKN: + /* apply "$name" */ + jointok = tok->forkjoin->data; + if (!jointok->varname) + break; + for (i = 0; i < vector_active(tok->forkjoin->from); i++) { + struct graph_node *tail = + vector_slot(tok->forkjoin->from, i); + struct cmd_token *tailtok = tail->data; + if (tail == gn || tailtok->varname) + continue; + cmd_token_varname_set(tailtok, jointok->varname); + } + break; + } + + for (i = 0; i < vector_active(gn->to); i++) { + struct graph_node *next = vector_slot(gn->to, i); + if (next == stop || next == join) + continue; + cmd_node_names(next, join, prevname); + } + + if (tok->type == FORK_TKN && tok->forkjoin != join) + cmd_node_names(tok->forkjoin, join, NULL); } -void -cmd_graph_names (struct graph *graph) +void cmd_graph_names(struct graph *graph) { - struct graph_node *start; - - assert (vector_active (graph->nodes) >= 1); - start = vector_slot (graph->nodes, 0); - - /* apply varname on initial "[no]" */ - do - { - if (vector_active (start->to) != 1) - break; - - struct graph_node *first = vector_slot (start->to, 0); - struct cmd_token *tok = first->data; - /* looking for an option with 2 choices, nothing or "no" */ - if (tok->type != FORK_TKN || vector_active (first->to) != 2) - break; - - struct graph_node *next0 = vector_slot (first->to, 0); - struct graph_node *next1 = vector_slot (first->to, 1); - /* one needs to be empty */ - if (next0 != tok->forkjoin && next1 != tok->forkjoin) - break; - - struct cmd_token *tok0 = next0->data; - struct cmd_token *tok1 = next1->data; - /* the other one needs to be "no" (only one will match here) */ - if ((tok0->type == WORD_TKN && !strcmp(tok0->text, "no"))) - cmd_token_varname_set (tok0, "no"); - if ((tok1->type == WORD_TKN && !strcmp(tok1->text, "no"))) - cmd_token_varname_set (tok1, "no"); - } - while (0); - - cmd_node_names (start, NULL, NULL); + struct graph_node *start; + + assert(vector_active(graph->nodes) >= 1); + start = vector_slot(graph->nodes, 0); + + /* apply varname on initial "[no]" */ + do { + if (vector_active(start->to) != 1) + break; + + struct graph_node *first = vector_slot(start->to, 0); + struct cmd_token *tok = first->data; + /* looking for an option with 2 choices, nothing or "no" */ + if (tok->type != FORK_TKN || vector_active(first->to) != 2) + break; + + struct graph_node *next0 = vector_slot(first->to, 0); + struct graph_node *next1 = vector_slot(first->to, 1); + /* one needs to be empty */ + if (next0 != tok->forkjoin && next1 != tok->forkjoin) + break; + + struct cmd_token *tok0 = next0->data; + struct cmd_token *tok1 = next1->data; + /* the other one needs to be "no" (only one will match here) */ + if ((tok0->type == WORD_TKN && !strcmp(tok0->text, "no"))) + cmd_token_varname_set(tok0, "no"); + if ((tok1->type == WORD_TKN && !strcmp(tok1->text, "no"))) + cmd_token_varname_set(tok1, "no"); + } while (0); + + cmd_node_names(start, NULL, NULL); } diff --git a/lib/command_graph.h b/lib/command_graph.h index a7a34a059..879148844 100644 --- a/lib/command_graph.h +++ b/lib/command_graph.h @@ -42,78 +42,75 @@ struct vty; * The type determines what kind of data the token can match (in the * matching use case) or hold (in the argv use case). */ -enum cmd_token_type -{ - WORD_TKN, // words - VARIABLE_TKN, // almost anything - RANGE_TKN, // integer range - IPV4_TKN, // IPV4 addresses - IPV4_PREFIX_TKN, // IPV4 network prefixes - IPV6_TKN, // IPV6 prefixes - IPV6_PREFIX_TKN, // IPV6 network prefixes - - /* plumbing types */ - FORK_TKN, // marks subgraph beginning - JOIN_TKN, // marks subgraph end - START_TKN, // first token in line - END_TKN, // last token in line - - SPECIAL_TKN = FORK_TKN, +enum cmd_token_type { + WORD_TKN, // words + VARIABLE_TKN, // almost anything + RANGE_TKN, // integer range + IPV4_TKN, // IPV4 addresses + IPV4_PREFIX_TKN, // IPV4 network prefixes + IPV6_TKN, // IPV6 prefixes + IPV6_PREFIX_TKN, // IPV6 network prefixes + + /* plumbing types */ + FORK_TKN, // marks subgraph beginning + JOIN_TKN, // marks subgraph end + START_TKN, // first token in line + END_TKN, // last token in line + + SPECIAL_TKN = FORK_TKN, }; #define IS_VARYING_TOKEN(x) ((x) >= VARIABLE_TKN && (x) < FORK_TKN) /* Command attributes */ -enum -{ - CMD_ATTR_NORMAL, - CMD_ATTR_DEPRECATED, - CMD_ATTR_HIDDEN, +enum { CMD_ATTR_NORMAL, + CMD_ATTR_DEPRECATED, + CMD_ATTR_HIDDEN, }; /* Comamand token struct. */ -struct cmd_token -{ - enum cmd_token_type type; // token type - uint8_t attr; // token attributes - bool allowrepeat; // matcher allowed to match token repetively? - uint32_t refcnt; - - char *text; // token text - char *desc; // token description - long long min, max; // for ranges - char *arg; // user input that matches this token - char *varname; - - struct graph_node *forkjoin; // paired FORK/JOIN for JOIN/FORK +struct cmd_token { + enum cmd_token_type type; // token type + uint8_t attr; // token attributes + bool allowrepeat; // matcher allowed to match token repetively? + uint32_t refcnt; + + char *text; // token text + char *desc; // token description + long long min, max; // for ranges + char *arg; // user input that matches this token + char *varname; + + struct graph_node *forkjoin; // paired FORK/JOIN for JOIN/FORK }; /* Structure of command element. */ -struct cmd_element -{ - const char *string; /* Command specification by string. */ - const char *doc; /* Documentation of this command. */ - int daemon; /* Daemon to which this command belong. */ - uint8_t attr; /* Command attributes */ +struct cmd_element { + const char *string; /* Command specification by string. */ + const char *doc; /* Documentation of this command. */ + int daemon; /* Daemon to which this command belong. */ + uint8_t attr; /* Command attributes */ - /* handler function for command */ - int (*func) (const struct cmd_element *, struct vty *, int, struct cmd_token *[]); + /* handler function for command */ + int (*func)(const struct cmd_element *, struct vty *, int, + struct cmd_token *[]); - const char *name; /* symbol name for debugging */ + const char *name; /* symbol name for debugging */ }; /* text for command */ #define CMD_CR_TEXT "" /* memory management for cmd_token */ -extern struct cmd_token *cmd_token_new (enum cmd_token_type, uint8_t attr, - const char *text, const char *desc); -extern struct cmd_token *cmd_token_dup (struct cmd_token *); -extern void cmd_token_del (struct cmd_token *); +extern struct cmd_token *cmd_token_new(enum cmd_token_type, uint8_t attr, + const char *text, const char *desc); +extern struct cmd_token *cmd_token_dup(struct cmd_token *); +extern void cmd_token_del(struct cmd_token *); extern void cmd_token_varname_set(struct cmd_token *token, const char *varname); -extern void cmd_graph_parse (struct graph *graph, struct cmd_element *cmd); -extern void cmd_graph_names (struct graph *graph); -extern void cmd_graph_merge (struct graph *old, struct graph *new, int direction); +extern void cmd_graph_parse(struct graph *graph, struct cmd_element *cmd); +extern void cmd_graph_names(struct graph *graph); +extern void cmd_graph_merge(struct graph *old, struct graph *new, + int direction); #endif /* _FRR_COMMAND_GRAPH_H */ diff --git a/lib/command_match.c b/lib/command_match.c index 5a57bb919..bc54f1bb0 100644 --- a/lib/command_match.c +++ b/lib/command_match.c @@ -36,108 +36,98 @@ DEFINE_MTYPE_STATIC(LIB, CMD_MATCHSTACK, "Command Match Stack") #define TM 0 #endif -#define trace_matcher(...) \ - do { if (TM) fprintf (stderr, __VA_ARGS__); } while (0); +#define trace_matcher(...) \ + do { \ + if (TM) \ + fprintf(stderr, __VA_ARGS__); \ + } while (0); /* matcher helper prototypes */ -static int -add_nexthops (struct list *, struct graph_node *, - struct graph_node **, size_t); +static int add_nexthops(struct list *, struct graph_node *, + struct graph_node **, size_t); -static struct list * -command_match_r (struct graph_node *, vector, unsigned int, - struct graph_node **); +static struct list *command_match_r(struct graph_node *, vector, unsigned int, + struct graph_node **); -static int -score_precedence (enum cmd_token_type); +static int score_precedence(enum cmd_token_type); -static enum match_type -min_match_level (enum cmd_token_type); +static enum match_type min_match_level(enum cmd_token_type); -static void -del_arglist (struct list *); +static void del_arglist(struct list *); -static struct cmd_token * -disambiguate_tokens (struct cmd_token *, struct cmd_token *, char *); +static struct cmd_token *disambiguate_tokens(struct cmd_token *, + struct cmd_token *, char *); -static struct list * -disambiguate (struct list *, struct list *, vector, unsigned int); +static struct list *disambiguate(struct list *, struct list *, vector, + unsigned int); -int -compare_completions (const void *, const void *); +int compare_completions(const void *, const void *); /* token matcher prototypes */ -static enum match_type -match_token (struct cmd_token *, char *); +static enum match_type match_token(struct cmd_token *, char *); -static enum match_type -match_ipv4 (const char *); +static enum match_type match_ipv4(const char *); -static enum match_type -match_ipv4_prefix (const char *); +static enum match_type match_ipv4_prefix(const char *); -static enum match_type -match_ipv6_prefix (const char *, bool); +static enum match_type match_ipv6_prefix(const char *, bool); -static enum match_type -match_range (struct cmd_token *, const char *); +static enum match_type match_range(struct cmd_token *, const char *); -static enum match_type -match_word (struct cmd_token *, const char *); +static enum match_type match_word(struct cmd_token *, const char *); -static enum match_type -match_variable (struct cmd_token *, const char *); +static enum match_type match_variable(struct cmd_token *, const char *); /* matching functions */ static enum matcher_rv matcher_rv; -enum matcher_rv -command_match (struct graph *cmdgraph, - vector vline, - struct list **argv, - const struct cmd_element **el) +enum matcher_rv command_match(struct graph *cmdgraph, vector vline, + struct list **argv, const struct cmd_element **el) { - struct graph_node *stack[MAXDEPTH]; - matcher_rv = MATCHER_NO_MATCH; - - // prepend a dummy token to match that pesky start node - vector vvline = vector_init (vline->alloced + 1); - vector_set_index (vvline, 0, (void *) XSTRDUP (MTYPE_TMP, "dummy")); - memcpy (vvline->index + 1, vline->index, sizeof (void *) * vline->alloced); - vvline->active = vline->active + 1; - - struct graph_node *start = vector_slot (cmdgraph->nodes, 0); - if ((*argv = command_match_r (start, vvline, 0, stack))) // successful match - { - struct listnode *head = listhead (*argv); - struct listnode *tail = listtail (*argv); - - // delete dummy start node - cmd_token_del ((struct cmd_token *) head->data); - list_delete_node (*argv, head); - - // get cmd_element out of list tail - *el = listgetdata (tail); - list_delete_node (*argv, tail); - - // now argv is an ordered list of cmd_token matching the user - // input, with each cmd_token->arg holding the corresponding input - assert (*el); - } - - if (!*el) { - trace_matcher ("No match\n"); - } - else { - trace_matcher ("Matched command\n->string %s\n->desc %s\n", (*el)->string, (*el)->doc); - } - - // free the leader token we alloc'd - XFREE (MTYPE_TMP, vector_slot (vvline, 0)); - // free vector - vector_free (vvline); - - return matcher_rv; + struct graph_node *stack[MAXDEPTH]; + matcher_rv = MATCHER_NO_MATCH; + + // prepend a dummy token to match that pesky start node + vector vvline = vector_init(vline->alloced + 1); + vector_set_index(vvline, 0, (void *)XSTRDUP(MTYPE_TMP, "dummy")); + memcpy(vvline->index + 1, vline->index, + sizeof(void *) * vline->alloced); + vvline->active = vline->active + 1; + + struct graph_node *start = vector_slot(cmdgraph->nodes, 0); + if ((*argv = command_match_r(start, vvline, 0, + stack))) // successful match + { + struct listnode *head = listhead(*argv); + struct listnode *tail = listtail(*argv); + + // delete dummy start node + cmd_token_del((struct cmd_token *)head->data); + list_delete_node(*argv, head); + + // get cmd_element out of list tail + *el = listgetdata(tail); + list_delete_node(*argv, tail); + + // now argv is an ordered list of cmd_token matching the user + // input, with each cmd_token->arg holding the corresponding + // input + assert(*el); + } + + if (!*el) { + trace_matcher("No match\n"); + } else { + trace_matcher("Matched command\n->string %s\n->desc %s\n", + (*el)->string, (*el)->doc); + } + + // free the leader token we alloc'd + XFREE(MTYPE_TMP, vector_slot(vvline, 0)); + // free vector + vector_free(vvline); + + return matcher_rv; } /** @@ -191,266 +181,272 @@ command_match (struct graph *cmdgraph, * * If no match was found, the return value is NULL. */ -static struct list * -command_match_r (struct graph_node *start, vector vline, unsigned int n, - struct graph_node **stack) +static struct list *command_match_r(struct graph_node *start, vector vline, + unsigned int n, struct graph_node **stack) { - assert (n < vector_active (vline)); + assert(n < vector_active(vline)); - // get the minimum match level that can count as a full match - struct cmd_token *token = start->data; - enum match_type minmatch = min_match_level (token->type); + // get the minimum match level that can count as a full match + struct cmd_token *token = start->data; + enum match_type minmatch = min_match_level(token->type); - /* check history/stack of tokens - * this disallows matching the same one more than once if there is a - * circle in the graph (used for keyword arguments) */ - if (n == MAXDEPTH) - return NULL; - if (!token->allowrepeat) - for (size_t s = 0; s < n; s++) - if (stack[s] == start) - return NULL; + /* check history/stack of tokens + * this disallows matching the same one more than once if there is a + * circle in the graph (used for keyword arguments) */ + if (n == MAXDEPTH) + return NULL; + if (!token->allowrepeat) + for (size_t s = 0; s < n; s++) + if (stack[s] == start) + return NULL; - // get the current operating input token - char *input_token = vector_slot (vline, n); + // get the current operating input token + char *input_token = vector_slot(vline, n); #ifdef TRACE_MATCHER - fprintf (stdout, "\"%-20s\" matches \"%-30s\" ? ", input_token, token->text); - enum match_type mt = match_token (token, input_token); - fprintf (stdout, "min: %d - ", minmatch); - switch (mt) - { - case trivial_match: - fprintf (stdout, "trivial_match "); - break; - case no_match: - fprintf (stdout, "no_match "); - break; - case partly_match: - fprintf (stdout, "partly_match "); - break; - case exact_match: - fprintf (stdout, "exact_match "); - break; - } - if (mt >= minmatch) fprintf (stdout, " MATCH"); - fprintf (stdout, "\n"); + fprintf(stdout, "\"%-20s\" matches \"%-30s\" ? ", input_token, + token->text); + enum match_type mt = match_token(token, input_token); + fprintf(stdout, "min: %d - ", minmatch); + switch (mt) { + case trivial_match: + fprintf(stdout, "trivial_match "); + break; + case no_match: + fprintf(stdout, "no_match "); + break; + case partly_match: + fprintf(stdout, "partly_match "); + break; + case exact_match: + fprintf(stdout, "exact_match "); + break; + } + if (mt >= minmatch) + fprintf(stdout, " MATCH"); + fprintf(stdout, "\n"); #endif - // if we don't match this node, die - if (match_token (token, input_token) < minmatch) - return NULL; - - stack[n] = start; - - // pointers for iterating linklist - struct listnode *ln; - struct graph_node *gn; - - // get all possible nexthops - struct list *next = list_new(); - add_nexthops (next, start, NULL, 0); - - // determine the best match - int ambiguous = 0; - struct list *currbest = NULL; - for (ALL_LIST_ELEMENTS_RO (next,ln,gn)) - { - // if we've matched all input we're looking for END_TKN - if (n+1 == vector_active (vline)) - { - struct cmd_token *tok = gn->data; - if (tok->type == END_TKN) - { - if (currbest) // there is more than one END_TKN in the follow set - { - ambiguous = 1; - break; - } - currbest = list_new(); - // node should have one child node with the element - struct graph_node *leaf = vector_slot (gn->to, 0); - // last node in the list will hold the cmd_element; - // this is important because list_delete() expects - // that all nodes have the same data type, so when - // deleting this list the last node must be - // manually deleted - struct cmd_element *el = leaf->data; - listnode_add (currbest, el); - currbest->del = (void (*)(void *)) &cmd_token_del; - // do not break immediately; continue walking through the follow set - // to ensure that there is exactly one END_TKN - } - continue; - } - - // else recurse on candidate child node - struct list *result = command_match_r (gn, vline, n+1, stack); - - // save the best match - if (result && currbest) - { - // pick the best of two matches - struct list *newbest = disambiguate (currbest, result, vline, n+1); - // set ambiguity flag - ambiguous = !newbest || (ambiguous && newbest == currbest); - // delete the unnecessary result - struct list *todelete = ((newbest && newbest == result) ? currbest : result); - del_arglist (todelete); - - currbest = newbest ? newbest : currbest; - } - else if (result) - currbest = result; - } - - if (currbest) - { - if (ambiguous) - { - del_arglist (currbest); - currbest = NULL; - matcher_rv = MATCHER_AMBIGUOUS; - } - else - { - // copy token, set arg and prepend to currbest - struct cmd_token *token = start->data; - struct cmd_token *copy = cmd_token_dup (token); - copy->arg = XSTRDUP (MTYPE_CMD_ARG, input_token); - listnode_add_before (currbest, currbest->head, copy); - matcher_rv = MATCHER_OK; - } - } - else if (n+1 == vector_active (vline) && matcher_rv == MATCHER_NO_MATCH) - matcher_rv = MATCHER_INCOMPLETE; - - // cleanup - list_delete (next); - - return currbest; + // if we don't match this node, die + if (match_token(token, input_token) < minmatch) + return NULL; + + stack[n] = start; + + // pointers for iterating linklist + struct listnode *ln; + struct graph_node *gn; + + // get all possible nexthops + struct list *next = list_new(); + add_nexthops(next, start, NULL, 0); + + // determine the best match + int ambiguous = 0; + struct list *currbest = NULL; + for (ALL_LIST_ELEMENTS_RO(next, ln, gn)) { + // if we've matched all input we're looking for END_TKN + if (n + 1 == vector_active(vline)) { + struct cmd_token *tok = gn->data; + if (tok->type == END_TKN) { + if (currbest) // there is more than one END_TKN + // in the follow set + { + ambiguous = 1; + break; + } + currbest = list_new(); + // node should have one child node with the + // element + struct graph_node *leaf = + vector_slot(gn->to, 0); + // last node in the list will hold the + // cmd_element; + // this is important because list_delete() + // expects + // that all nodes have the same data type, so + // when + // deleting this list the last node must be + // manually deleted + struct cmd_element *el = leaf->data; + listnode_add(currbest, el); + currbest->del = + (void (*)(void *)) & cmd_token_del; + // do not break immediately; continue walking + // through the follow set + // to ensure that there is exactly one END_TKN + } + continue; + } + + // else recurse on candidate child node + struct list *result = command_match_r(gn, vline, n + 1, stack); + + // save the best match + if (result && currbest) { + // pick the best of two matches + struct list *newbest = + disambiguate(currbest, result, vline, n + 1); + // set ambiguity flag + ambiguous = + !newbest || (ambiguous && newbest == currbest); + // delete the unnecessary result + struct list *todelete = + ((newbest && newbest == result) ? currbest + : result); + del_arglist(todelete); + + currbest = newbest ? newbest : currbest; + } else if (result) + currbest = result; + } + + if (currbest) { + if (ambiguous) { + del_arglist(currbest); + currbest = NULL; + matcher_rv = MATCHER_AMBIGUOUS; + } else { + // copy token, set arg and prepend to currbest + struct cmd_token *token = start->data; + struct cmd_token *copy = cmd_token_dup(token); + copy->arg = XSTRDUP(MTYPE_CMD_ARG, input_token); + listnode_add_before(currbest, currbest->head, copy); + matcher_rv = MATCHER_OK; + } + } else if (n + 1 == vector_active(vline) + && matcher_rv == MATCHER_NO_MATCH) + matcher_rv = MATCHER_INCOMPLETE; + + // cleanup + list_delete(next); + + return currbest; } -static void -stack_del (void *val) +static void stack_del(void *val) { - XFREE (MTYPE_CMD_MATCHSTACK, val); + XFREE(MTYPE_CMD_MATCHSTACK, val); } -enum matcher_rv -command_complete (struct graph *graph, - vector vline, - struct list **completions) +enum matcher_rv command_complete(struct graph *graph, vector vline, + struct list **completions) { - // pointer to next input token to match - char *input_token; - - struct list *current = list_new(), // current nodes to match input token against - *next = list_new(); // possible next hops after current input token - current->del = next->del = stack_del; - - // pointers used for iterating lists - struct graph_node **gstack, **newstack; - struct listnode *node; - - // add all children of start node to list - struct graph_node *start = vector_slot (graph->nodes, 0); - add_nexthops (next, start, &start, 0); - - unsigned int idx; - for (idx = 0; idx < vector_active (vline) && next->count > 0; idx++) - { - list_delete (current); - current = next; - next = list_new(); - next->del = stack_del; - - input_token = vector_slot (vline, idx); - - int exact_match_exists = 0; - for (ALL_LIST_ELEMENTS_RO (current,node,gstack)) - if (!exact_match_exists) - exact_match_exists = (match_token (gstack[0]->data, input_token) == exact_match); - else - break; - - for (ALL_LIST_ELEMENTS_RO (current,node,gstack)) - { - struct cmd_token *token = gstack[0]->data; - - if (token->attr == CMD_ATTR_HIDDEN || token->attr == CMD_ATTR_DEPRECATED) - continue; - - enum match_type minmatch = min_match_level (token->type); - trace_matcher ("\"%s\" matches \"%s\" (%d) ? ", - input_token, token->text, token->type); - - unsigned int last_token = (vector_active (vline) - 1 == idx); - enum match_type matchtype = match_token (token, input_token); - switch (matchtype) - { - // occurs when last token is whitespace - case trivial_match: - trace_matcher ("trivial_match\n"); - assert(last_token); - newstack = XMALLOC (MTYPE_CMD_MATCHSTACK, - sizeof(struct graph_node *)); - /* we're not recursing here, just the first element is OK */ - newstack[0] = gstack[0]; - listnode_add (next, newstack); - break; - case partly_match: - trace_matcher ("trivial_match\n"); - if (exact_match_exists && !last_token) - break; - /* fallthru */ - case exact_match: - trace_matcher ("exact_match\n"); - if (last_token) - { - newstack = XMALLOC (MTYPE_CMD_MATCHSTACK, - sizeof(struct graph_node *)); - /* same as above, not recursing on this */ - newstack[0] = gstack[0]; - listnode_add (next, newstack); - } - else if (matchtype >= minmatch) - add_nexthops (next, gstack[0], gstack, idx + 1); - break; - default: - trace_matcher ("no_match\n"); - break; - } - } - } - - /* Variable summary - * ----------------------------------------------------------------- - * token = last input token processed - * idx = index in `command` of last token processed - * current = set of all transitions from the previous input token - * next = set of all nodes reachable from all nodes in `matched` - */ - - matcher_rv = - idx == vector_active(vline) && next->count ? - MATCHER_OK : - MATCHER_NO_MATCH; - - *completions = NULL; - if (!MATCHER_ERROR(matcher_rv)) - { - // extract cmd_token into list - *completions = list_new (); - for (ALL_LIST_ELEMENTS_RO (next,node,gstack)) { - listnode_add (*completions, gstack[0]->data); - } - } - - list_delete (current); - list_delete (next); - - return matcher_rv; + // pointer to next input token to match + char *input_token; + + struct list * + current = + list_new(), // current nodes to match input token against + *next = list_new(); // possible next hops after current input + // token + current->del = next->del = stack_del; + + // pointers used for iterating lists + struct graph_node **gstack, **newstack; + struct listnode *node; + + // add all children of start node to list + struct graph_node *start = vector_slot(graph->nodes, 0); + add_nexthops(next, start, &start, 0); + + unsigned int idx; + for (idx = 0; idx < vector_active(vline) && next->count > 0; idx++) { + list_delete(current); + current = next; + next = list_new(); + next->del = stack_del; + + input_token = vector_slot(vline, idx); + + int exact_match_exists = 0; + for (ALL_LIST_ELEMENTS_RO(current, node, gstack)) + if (!exact_match_exists) + exact_match_exists = + (match_token(gstack[0]->data, + input_token) + == exact_match); + else + break; + + for (ALL_LIST_ELEMENTS_RO(current, node, gstack)) { + struct cmd_token *token = gstack[0]->data; + + if (token->attr == CMD_ATTR_HIDDEN + || token->attr == CMD_ATTR_DEPRECATED) + continue; + + enum match_type minmatch = min_match_level(token->type); + trace_matcher("\"%s\" matches \"%s\" (%d) ? ", + input_token, token->text, token->type); + + unsigned int last_token = + (vector_active(vline) - 1 == idx); + enum match_type matchtype = + match_token(token, input_token); + switch (matchtype) { + // occurs when last token is whitespace + case trivial_match: + trace_matcher("trivial_match\n"); + assert(last_token); + newstack = XMALLOC(MTYPE_CMD_MATCHSTACK, + sizeof(struct graph_node *)); + /* we're not recursing here, just the first + * element is OK */ + newstack[0] = gstack[0]; + listnode_add(next, newstack); + break; + case partly_match: + trace_matcher("trivial_match\n"); + if (exact_match_exists && !last_token) + break; + /* fallthru */ + case exact_match: + trace_matcher("exact_match\n"); + if (last_token) { + newstack = XMALLOC( + MTYPE_CMD_MATCHSTACK, + sizeof(struct graph_node *)); + /* same as above, not recursing on this + */ + newstack[0] = gstack[0]; + listnode_add(next, newstack); + } else if (matchtype >= minmatch) + add_nexthops(next, gstack[0], gstack, + idx + 1); + break; + default: + trace_matcher("no_match\n"); + break; + } + } + } + + /* Variable summary + * ----------------------------------------------------------------- + * token = last input token processed + * idx = index in `command` of last token processed + * current = set of all transitions from the previous input token + * next = set of all nodes reachable from all nodes in `matched` + */ + + matcher_rv = idx == vector_active(vline) && next->count + ? MATCHER_OK + : MATCHER_NO_MATCH; + + *completions = NULL; + if (!MATCHER_ERROR(matcher_rv)) { + // extract cmd_token into list + *completions = list_new(); + for (ALL_LIST_ELEMENTS_RO(next, node, gstack)) { + listnode_add(*completions, gstack[0]->data); + } + } + + list_delete(current); + list_delete(next); + + return matcher_rv; } /** @@ -466,48 +462,43 @@ command_complete (struct graph *graph, * NB: non-null "stack" means that new stacks will be added to "list" as * output, instead of direct node pointers! */ -static int -add_nexthops (struct list *list, struct graph_node *node, - struct graph_node **stack, size_t stackpos) +static int add_nexthops(struct list *list, struct graph_node *node, + struct graph_node **stack, size_t stackpos) { - int added = 0; - struct graph_node *child; - struct graph_node **nextstack; - for (unsigned int i = 0; i < vector_active (node->to); i++) - { - child = vector_slot (node->to, i); - size_t j; - struct cmd_token *token = child->data; - if (!token->allowrepeat && stack) - { - for (j = 0; j < stackpos; j++) - if (child == stack[j]) - break; - if (j != stackpos) - continue; - } - if (token->type >= SPECIAL_TKN && token->type != END_TKN) - { - added += add_nexthops (list, child, stack, stackpos); - } - else - { - if (stack) - { - nextstack = XMALLOC (MTYPE_CMD_MATCHSTACK, - (stackpos + 1) * sizeof(struct graph_node *)); - nextstack[0] = child; - memcpy(nextstack + 1, stack, stackpos * sizeof(struct graph_node *)); - - listnode_add (list, nextstack); - } - else - listnode_add (list, child); - added++; - } - } - - return added; + int added = 0; + struct graph_node *child; + struct graph_node **nextstack; + for (unsigned int i = 0; i < vector_active(node->to); i++) { + child = vector_slot(node->to, i); + size_t j; + struct cmd_token *token = child->data; + if (!token->allowrepeat && stack) { + for (j = 0; j < stackpos; j++) + if (child == stack[j]) + break; + if (j != stackpos) + continue; + } + if (token->type >= SPECIAL_TKN && token->type != END_TKN) { + added += add_nexthops(list, child, stack, stackpos); + } else { + if (stack) { + nextstack = XMALLOC( + MTYPE_CMD_MATCHSTACK, + (stackpos + 1) + * sizeof(struct graph_node *)); + nextstack[0] = child; + memcpy(nextstack + 1, stack, + stackpos * sizeof(struct graph_node *)); + + listnode_add(list, nextstack); + } else + listnode_add(list, child); + added++; + } + } + + return added; } /** @@ -517,20 +508,18 @@ add_nexthops (struct list *list, struct graph_node *node, * @param[in] type node type * @return minimum match level needed to for a token to fully match */ -static enum match_type -min_match_level (enum cmd_token_type type) +static enum match_type min_match_level(enum cmd_token_type type) { - switch (type) - { - // anything matches a start node, for the sake of recursion - case START_TKN: - return no_match; - // allowing words to partly match enables command abbreviation - case WORD_TKN: - return partly_match; - default: - return exact_match; - } + switch (type) { + // anything matches a start node, for the sake of recursion + case START_TKN: + return no_match; + // allowing words to partly match enables command abbreviation + case WORD_TKN: + return partly_match; + default: + return exact_match; + } } /** @@ -539,26 +528,24 @@ min_match_level (enum cmd_token_type type) * @param[in] type node type to score * @return precedence score */ -static int -score_precedence (enum cmd_token_type type) +static int score_precedence(enum cmd_token_type type) { - switch (type) - { - // some of these are mutually exclusive, so they share - // the same precedence value - case IPV4_TKN: - case IPV4_PREFIX_TKN: - case IPV6_TKN: - case IPV6_PREFIX_TKN: - case RANGE_TKN: - return 2; - case WORD_TKN: - return 3; - case VARIABLE_TKN: - return 4; - default: - return 10; - } + switch (type) { + // some of these are mutually exclusive, so they share + // the same precedence value + case IPV4_TKN: + case IPV4_PREFIX_TKN: + case IPV6_TKN: + case IPV6_PREFIX_TKN: + case RANGE_TKN: + return 2; + case WORD_TKN: + return 3; + case VARIABLE_TKN: + return 4; + default: + return 10; + } } /** @@ -569,29 +556,27 @@ score_precedence (enum cmd_token_type type) * @param[in] token the token being matched * @return the best-matching node, or NULL if the two are entirely ambiguous */ -static struct cmd_token * -disambiguate_tokens (struct cmd_token *first, - struct cmd_token *second, - char *input_token) +static struct cmd_token *disambiguate_tokens(struct cmd_token *first, + struct cmd_token *second, + char *input_token) { - // if the types are different, simply go off of type precedence - if (first->type != second->type) - { - int firstprec = score_precedence (first->type); - int secndprec = score_precedence (second->type); - if (firstprec != secndprec) - return firstprec < secndprec ? first : second; - else - return NULL; - } - - // if they're the same, return the more exact match - enum match_type fmtype = match_token (first, input_token); - enum match_type smtype = match_token (second, input_token); - if (fmtype != smtype) - return fmtype > smtype ? first : second; - - return NULL; + // if the types are different, simply go off of type precedence + if (first->type != second->type) { + int firstprec = score_precedence(first->type); + int secndprec = score_precedence(second->type); + if (firstprec != secndprec) + return firstprec < secndprec ? first : second; + else + return NULL; + } + + // if they're the same, return the more exact match + enum match_type fmtype = match_token(first, input_token); + enum match_type smtype = match_token(second, input_token); + if (fmtype != smtype) + return fmtype > smtype ? first : second; + + return NULL; } /** @@ -603,35 +588,29 @@ disambiguate_tokens (struct cmd_token *first, * @param[in] n index into vline to start comparing at * @return the best-matching list, or NULL if the two are entirely ambiguous */ -static struct list * -disambiguate (struct list *first, - struct list *second, - vector vline, - unsigned int n) +static struct list *disambiguate(struct list *first, struct list *second, + vector vline, unsigned int n) { - // doesn't make sense for these to be inequal length - assert (first->count == second->count); - assert (first->count == vector_active (vline) - n+1); - - struct listnode *fnode = listhead (first), - *snode = listhead (second); - struct cmd_token *ftok = listgetdata (fnode), - *stok = listgetdata (snode), - *best = NULL; - - // compare each token, if one matches better use that one - for (unsigned int i = n; i < vector_active (vline); i++) - { - char *token = vector_slot(vline, i); - if ((best = disambiguate_tokens (ftok, stok, token))) - return best == ftok ? first : second; - fnode = listnextnode (fnode); - snode = listnextnode (snode); - ftok = listgetdata (fnode); - stok = listgetdata (snode); - } - - return NULL; + // doesn't make sense for these to be inequal length + assert(first->count == second->count); + assert(first->count == vector_active(vline) - n + 1); + + struct listnode *fnode = listhead(first), *snode = listhead(second); + struct cmd_token *ftok = listgetdata(fnode), *stok = listgetdata(snode), + *best = NULL; + + // compare each token, if one matches better use that one + for (unsigned int i = n; i < vector_active(vline); i++) { + char *token = vector_slot(vline, i); + if ((best = disambiguate_tokens(ftok, stok, token))) + return best == ftok ? first : second; + fnode = listnextnode(fnode); + snode = listnextnode(snode); + ftok = listgetdata(fnode); + stok = listgetdata(snode); + } + + return NULL; } /* @@ -645,179 +624,165 @@ disambiguate (struct list *first, * * @param list the arglist to delete */ -static void -del_arglist (struct list *list) +static void del_arglist(struct list *list) { - // manually delete last node - struct listnode *tail = listtail (list); - tail->data = NULL; - list_delete_node (list, tail); + // manually delete last node + struct listnode *tail = listtail(list); + tail->data = NULL; + list_delete_node(list, tail); - // delete the rest of the list as usual - list_delete (list); + // delete the rest of the list as usual + list_delete(list); } /*---------- token level matching functions ----------*/ -static enum match_type -match_token (struct cmd_token *token, char *input_token) +static enum match_type match_token(struct cmd_token *token, char *input_token) { - // nothing trivially matches everything - if (!input_token) - return trivial_match; - - switch (token->type) { - case WORD_TKN: - return match_word (token, input_token); - case IPV4_TKN: - return match_ipv4 (input_token); - case IPV4_PREFIX_TKN: - return match_ipv4_prefix (input_token); - case IPV6_TKN: - return match_ipv6_prefix (input_token, false); - case IPV6_PREFIX_TKN: - return match_ipv6_prefix (input_token, true); - case RANGE_TKN: - return match_range (token, input_token); - case VARIABLE_TKN: - return match_variable (token, input_token); - case END_TKN: - default: - return no_match; - } + // nothing trivially matches everything + if (!input_token) + return trivial_match; + + switch (token->type) { + case WORD_TKN: + return match_word(token, input_token); + case IPV4_TKN: + return match_ipv4(input_token); + case IPV4_PREFIX_TKN: + return match_ipv4_prefix(input_token); + case IPV6_TKN: + return match_ipv6_prefix(input_token, false); + case IPV6_PREFIX_TKN: + return match_ipv6_prefix(input_token, true); + case RANGE_TKN: + return match_range(token, input_token); + case VARIABLE_TKN: + return match_variable(token, input_token); + case END_TKN: + default: + return no_match; + } } #define IPV4_ADDR_STR "0123456789." #define IPV4_PREFIX_STR "0123456789./" -static enum match_type -match_ipv4 (const char *str) +static enum match_type match_ipv4(const char *str) { - const char *sp; - int dots = 0, nums = 0; - char buf[4]; + const char *sp; + int dots = 0, nums = 0; + char buf[4]; + + for (;;) { + memset(buf, 0, sizeof(buf)); + sp = str; + while (*str != '\0') { + if (*str == '.') { + if (dots >= 3) + return no_match; + + if (*(str + 1) == '.') + return no_match; + + if (*(str + 1) == '\0') + return partly_match; + + dots++; + break; + } + if (!isdigit((int)*str)) + return no_match; + + str++; + } + + if (str - sp > 3) + return no_match; - for (;;) - { - memset (buf, 0, sizeof (buf)); - sp = str; - while (*str != '\0') - { - if (*str == '.') - { - if (dots >= 3) - return no_match; + strncpy(buf, sp, str - sp); + if (atoi(buf) > 255) + return no_match; - if (*(str + 1) == '.') - return no_match; + nums++; - if (*(str + 1) == '\0') - return partly_match; + if (*str == '\0') + break; + + str++; + } - dots++; - break; - } - if (!isdigit ((int) *str)) - return no_match; + if (nums < 4) + return partly_match; - str++; - } + return exact_match; +} - if (str - sp > 3) - return no_match; +static enum match_type match_ipv4_prefix(const char *str) +{ + const char *sp; + int dots = 0; + char buf[4]; - strncpy (buf, sp, str - sp); - if (atoi (buf) > 255) - return no_match; + for (;;) { + memset(buf, 0, sizeof(buf)); + sp = str; + while (*str != '\0' && *str != '/') { + if (*str == '.') { + if (dots == 3) + return no_match; - nums++; + if (*(str + 1) == '.' || *(str + 1) == '/') + return no_match; - if (*str == '\0') - break; + if (*(str + 1) == '\0') + return partly_match; - str++; - } + dots++; + break; + } - if (nums < 4) - return partly_match; + if (!isdigit((int)*str)) + return no_match; - return exact_match; -} + str++; + } -static enum match_type -match_ipv4_prefix (const char *str) -{ - const char *sp; - int dots = 0; - char buf[4]; - - for (;;) - { - memset (buf, 0, sizeof (buf)); - sp = str; - while (*str != '\0' && *str != '/') - { - if (*str == '.') - { - if (dots == 3) - return no_match; - - if (*(str + 1) == '.' || *(str + 1) == '/') - return no_match; - - if (*(str + 1) == '\0') - return partly_match; - - dots++; - break; - } - - if (!isdigit ((int) *str)) - return no_match; - - str++; - } - - if (str - sp > 3) - return no_match; - - strncpy (buf, sp, str - sp); - if (atoi (buf) > 255) - return no_match; - - if (dots == 3) - { - if (*str == '/') - { - if (*(str + 1) == '\0') - return partly_match; - - str++; - break; - } - else if (*str == '\0') - return partly_match; - } - - if (*str == '\0') - return partly_match; - - str++; - } - - sp = str; - while (*str != '\0') - { - if (!isdigit ((int) *str)) - return no_match; - - str++; - } - - if (atoi (sp) > 32) - return no_match; - - return exact_match; + if (str - sp > 3) + return no_match; + + strncpy(buf, sp, str - sp); + if (atoi(buf) > 255) + return no_match; + + if (dots == 3) { + if (*str == '/') { + if (*(str + 1) == '\0') + return partly_match; + + str++; + break; + } else if (*str == '\0') + return partly_match; + } + + if (*str == '\0') + return partly_match; + + str++; + } + + sp = str; + while (*str != '\0') { + if (!isdigit((int)*str)) + return no_match; + + str++; + } + + if (atoi(sp) > 32) + return no_match; + + return exact_match; } @@ -831,184 +796,171 @@ match_ipv4_prefix (const char *str) #define STATE_SLASH 6 #define STATE_MASK 7 -static enum match_type -match_ipv6_prefix (const char *str, bool prefix) +static enum match_type match_ipv6_prefix(const char *str, bool prefix) { - int state = STATE_START; - int colons = 0, nums = 0, double_colon = 0; - int mask; - const char *sp = NULL, *start = str; - char *endptr = NULL; + int state = STATE_START; + int colons = 0, nums = 0, double_colon = 0; + int mask; + const char *sp = NULL, *start = str; + char *endptr = NULL; - if (str == NULL) - return partly_match; + if (str == NULL) + return partly_match; - if (strspn (str, prefix ? IPV6_PREFIX_STR : IPV6_ADDR_STR) != strlen (str)) - return no_match; - - while (*str != '\0' && state != STATE_MASK) - { - switch (state) - { - case STATE_START: - if (*str == ':') - { - if (*(str + 1) != ':' && *(str + 1) != '\0') + if (strspn(str, prefix ? IPV6_PREFIX_STR : IPV6_ADDR_STR) + != strlen(str)) return no_match; - colons--; - state = STATE_COLON; - } - else - { - sp = str; - state = STATE_ADDR; - } - - continue; - case STATE_COLON: - colons++; - if (*(str + 1) == '/') - return no_match; - else if (*(str + 1) == ':') - state = STATE_DOUBLE; - else - { - sp = str + 1; - state = STATE_ADDR; - } - break; - case STATE_DOUBLE: - if (double_colon) - return no_match; - - if (*(str + 1) == ':') - return no_match; - else - { - if (*(str + 1) != '\0' && *(str + 1) != '/') - colons++; - sp = str + 1; - - if (*(str + 1) == '/') - state = STATE_SLASH; - else - state = STATE_ADDR; - } - - double_colon++; - nums += 1; - break; - case STATE_ADDR: - if (*(str + 1) == ':' || *(str + 1) == '.' - || *(str + 1) == '\0' || *(str + 1) == '/') - { - if (str - sp > 3) - return no_match; - - for (; sp <= str; sp++) - if (*sp == '/') - return no_match; - - nums++; - if (*(str + 1) == ':') - state = STATE_COLON; - else if (*(str + 1) == '.') - { - if (colons || double_colon) - state = STATE_DOT; - else - return no_match; + while (*str != '\0' && state != STATE_MASK) { + switch (state) { + case STATE_START: + if (*str == ':') { + if (*(str + 1) != ':' && *(str + 1) != '\0') + return no_match; + colons--; + state = STATE_COLON; + } else { + sp = str; + state = STATE_ADDR; + } + + continue; + case STATE_COLON: + colons++; + if (*(str + 1) == '/') + return no_match; + else if (*(str + 1) == ':') + state = STATE_DOUBLE; + else { + sp = str + 1; + state = STATE_ADDR; + } + break; + case STATE_DOUBLE: + if (double_colon) + return no_match; + + if (*(str + 1) == ':') + return no_match; + else { + if (*(str + 1) != '\0' && *(str + 1) != '/') + colons++; + sp = str + 1; + + if (*(str + 1) == '/') + state = STATE_SLASH; + else + state = STATE_ADDR; + } + + double_colon++; + nums += 1; + break; + case STATE_ADDR: + if (*(str + 1) == ':' || *(str + 1) == '.' + || *(str + 1) == '\0' || *(str + 1) == '/') { + if (str - sp > 3) + return no_match; + + for (; sp <= str; sp++) + if (*sp == '/') + return no_match; + + nums++; + + if (*(str + 1) == ':') + state = STATE_COLON; + else if (*(str + 1) == '.') { + if (colons || double_colon) + state = STATE_DOT; + else + return no_match; + } else if (*(str + 1) == '/') + state = STATE_SLASH; + } + break; + case STATE_DOT: + state = STATE_ADDR; + break; + case STATE_SLASH: + if (*(str + 1) == '\0') + return partly_match; + + state = STATE_MASK; + break; + default: + break; } - else if (*(str + 1) == '/') - state = STATE_SLASH; - } - break; - case STATE_DOT: - state = STATE_ADDR; - break; - case STATE_SLASH: - if (*(str + 1) == '\0') - return partly_match; - - state = STATE_MASK; - break; - default: - break; - } - if (nums > 11) - return no_match; + if (nums > 11) + return no_match; - if (colons > 7) - return no_match; + if (colons > 7) + return no_match; - str++; - } + str++; + } - if (!prefix) - { - struct sockaddr_in6 sin6_dummy; - int ret = inet_pton(AF_INET6, start, &sin6_dummy.sin6_addr); - return ret == 1 ? exact_match : partly_match; - } + if (!prefix) { + struct sockaddr_in6 sin6_dummy; + int ret = inet_pton(AF_INET6, start, &sin6_dummy.sin6_addr); + return ret == 1 ? exact_match : partly_match; + } - if (state < STATE_MASK) - return partly_match; + if (state < STATE_MASK) + return partly_match; - mask = strtol (str, &endptr, 10); - if (*endptr != '\0') - return no_match; + mask = strtol(str, &endptr, 10); + if (*endptr != '\0') + return no_match; - if (mask < 0 || mask > 128) - return no_match; + if (mask < 0 || mask > 128) + return no_match; - return exact_match; + return exact_match; } -static enum match_type -match_range (struct cmd_token *token, const char *str) +static enum match_type match_range(struct cmd_token *token, const char *str) { - assert (token->type == RANGE_TKN); + assert(token->type == RANGE_TKN); - char *endptr = NULL; - long long val; + char *endptr = NULL; + long long val; - val = strtoll (str, &endptr, 10); - if (*endptr != '\0') - return no_match; + val = strtoll(str, &endptr, 10); + if (*endptr != '\0') + return no_match; - if (val < token->min || val > token->max) - return no_match; - else - return exact_match; + if (val < token->min || val > token->max) + return no_match; + else + return exact_match; } -static enum match_type -match_word (struct cmd_token *token, const char *word) +static enum match_type match_word(struct cmd_token *token, const char *word) { - assert (token->type == WORD_TKN); + assert(token->type == WORD_TKN); - // if the passed token is 0 length, partly match - if (!strlen(word)) - return partly_match; + // if the passed token is 0 length, partly match + if (!strlen(word)) + return partly_match; - // if the passed token is strictly a prefix of the full word, partly match - if (strlen (word) < strlen (token->text)) - return !strncmp (token->text, word, strlen (word)) ? - partly_match : - no_match; + // if the passed token is strictly a prefix of the full word, partly + // match + if (strlen(word) < strlen(token->text)) + return !strncmp(token->text, word, strlen(word)) ? partly_match + : no_match; - // if they are the same length and exactly equal, exact match - else if (strlen (word) == strlen (token->text)) - return !strncmp (token->text, word, strlen (word)) ? exact_match : no_match; + // if they are the same length and exactly equal, exact match + else if (strlen(word) == strlen(token->text)) + return !strncmp(token->text, word, strlen(word)) ? exact_match + : no_match; - return no_match; + return no_match; } -static enum match_type -match_variable (struct cmd_token *token, const char *word) +static enum match_type match_variable(struct cmd_token *token, const char *word) { - assert (token->type == VARIABLE_TKN); - return exact_match; + assert(token->type == VARIABLE_TKN); + return exact_match; } diff --git a/lib/command_match.h b/lib/command_match.h index a04f60f0d..c636d2dd9 100644 --- a/lib/command_match.h +++ b/lib/command_match.h @@ -31,38 +31,31 @@ /* These definitions exist in command.c in the current engine but should be * relocated here in the new engine */ -enum filter_type -{ - FILTER_RELAXED, - FILTER_STRICT -}; +enum filter_type { FILTER_RELAXED, FILTER_STRICT }; /* matcher result value */ -enum matcher_rv -{ - MATCHER_NO_MATCH, - MATCHER_INCOMPLETE, - MATCHER_AMBIGUOUS, - MATCHER_OK, +enum matcher_rv { + MATCHER_NO_MATCH, + MATCHER_INCOMPLETE, + MATCHER_AMBIGUOUS, + MATCHER_OK, }; /* completion match types */ -enum match_type -{ - trivial_match, // the input is null - no_match, // the input does not match - partly_match, // the input matches but is incomplete - exact_match // the input matches and is complete +enum match_type { + trivial_match, // the input is null + no_match, // the input does not match + partly_match, // the input matches but is incomplete + exact_match // the input matches and is complete }; /* Defines which matcher_rv values constitute an error. Should be used with * matcher_rv return values to do basic error checking. */ -#define MATCHER_ERROR(matcher_rv) \ - ( (matcher_rv) == MATCHER_INCOMPLETE \ - || (matcher_rv) == MATCHER_NO_MATCH \ - || (matcher_rv) == MATCHER_AMBIGUOUS \ - ) +#define MATCHER_ERROR(matcher_rv) \ + ((matcher_rv) == MATCHER_INCOMPLETE \ + || (matcher_rv) == MATCHER_NO_MATCH \ + || (matcher_rv) == MATCHER_AMBIGUOUS) /** * Attempt to find an exact command match for a line of user input. @@ -79,11 +72,9 @@ enum match_type * safely deleted or modified; it is the instance initialized on startup. * @return matcher status */ -enum matcher_rv -command_match (struct graph *cmdgraph, - vector vline, - struct list **argv, - const struct cmd_element **element); +enum matcher_rv command_match(struct graph *cmdgraph, vector vline, + struct list **argv, + const struct cmd_element **element); /** * Compiles possible completions for a given line of user input. @@ -104,9 +95,7 @@ command_match (struct graph *cmdgraph, * of that element (e.g. 'encapv4', 'encapv6', etc for input 'en'). * @return matcher status */ -enum matcher_rv -command_complete (struct graph *cmdgraph, - vector vline, - struct list **completions); +enum matcher_rv command_complete(struct graph *cmdgraph, vector vline, + struct list **completions); #endif /* _ZEBRA_COMMAND_MATCH_H */ diff --git a/lib/command_py.c b/lib/command_py.c index 6621b0fa7..785d2ffa7 100644 --- a/lib/command_py.c +++ b/lib/command_py.c @@ -31,7 +31,8 @@ #include "clippy.h" struct wrap_graph; -static PyObject *graph_to_pyobj(struct wrap_graph *graph, struct graph_node *gn); +static PyObject *graph_to_pyobj(struct wrap_graph *graph, + struct graph_node *gn); /* * nodes are wrapped as follows: @@ -44,7 +45,7 @@ static PyObject *graph_to_pyobj(struct wrap_graph *graph, struct graph_node *gn) struct wrap_graph_node { PyObject_HEAD - bool allowrepeat; + bool allowrepeat; const char *type; bool deprecated; @@ -69,30 +70,29 @@ struct wrap_graph_node { struct wrap_graph { PyObject_HEAD - char *definition; + char *definition; struct graph *graph; struct wrap_graph_node **nodewrappers; }; static PyObject *refuse_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - PyErr_SetString(PyExc_ValueError, "cannot create instances of this type"); + PyErr_SetString(PyExc_ValueError, + "cannot create instances of this type"); return NULL; } -#define member(name, type) {(char *)#name, type, offsetof(struct wrap_graph_node, name), READONLY, \ - (char *)#name " (" #type ")"} +#define member(name, type) \ + { \ + (char *)#name, type, offsetof(struct wrap_graph_node, name), \ + READONLY, (char *)#name " (" #type ")" \ + } static PyMemberDef members_graph_node[] = { - member(allowrepeat, T_BOOL), - member(type, T_STRING), - member(deprecated, T_BOOL), - member(hidden, T_BOOL), - member(text, T_STRING), - member(desc, T_STRING), - member(min, T_LONGLONG), - member(max, T_LONGLONG), - member(varname, T_STRING), - {}, + member(allowrepeat, T_BOOL), member(type, T_STRING), + member(deprecated, T_BOOL), member(hidden, T_BOOL), + member(text, T_STRING), member(desc, T_STRING), + member(min, T_LONGLONG), member(max, T_LONGLONG), + member(varname, T_STRING), {}, }; #undef member @@ -106,7 +106,7 @@ static PyObject *graph_node_next(PyObject *self, PyObject *args) PyObject *pylist; if (wrap->node->data - && ((struct cmd_token *)wrap->node->data)->type == END_TKN) + && ((struct cmd_token *)wrap->node->data)->type == END_TKN) return PyList_New(0); pylist = PyList_New(vector_active(wrap->node->to)); for (size_t i = 0; i < vector_active(wrap->node->to); i++) { @@ -124,7 +124,7 @@ static PyObject *graph_node_join(PyObject *self, PyObject *args) struct wrap_graph_node *wrap = (struct wrap_graph_node *)self; if (!wrap->node->data - || ((struct cmd_token *)wrap->node->data)->type == END_TKN) + || ((struct cmd_token *)wrap->node->data)->type == END_TKN) Py_RETURN_NONE; struct cmd_token *tok = wrap->node->data; @@ -137,8 +137,7 @@ static PyObject *graph_node_join(PyObject *self, PyObject *args) static PyMethodDef methods_graph_node[] = { {"next", graph_node_next, METH_NOARGS, "outbound graph edge list"}, {"join", graph_node_join, METH_NOARGS, "outbound join node"}, - {} -}; + {}}; static void graph_node_wrap_free(void *arg) { @@ -148,18 +147,18 @@ static void graph_node_wrap_free(void *arg) } static PyTypeObject typeobj_graph_node = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "_clippy.GraphNode", - .tp_basicsize = sizeof(struct wrap_graph_node), - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_doc = "struct graph_node *", - .tp_new = refuse_new, - .tp_free = graph_node_wrap_free, - .tp_members = members_graph_node, - .tp_methods = methods_graph_node, + PyVarObject_HEAD_INIT(NULL, 0).tp_name = "_clippy.GraphNode", + .tp_basicsize = sizeof(struct wrap_graph_node), + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = "struct graph_node *", + .tp_new = refuse_new, + .tp_free = graph_node_wrap_free, + .tp_members = members_graph_node, + .tp_methods = methods_graph_node, }; -static PyObject *graph_to_pyobj(struct wrap_graph *wgraph, struct graph_node *gn) +static PyObject *graph_to_pyobj(struct wrap_graph *wgraph, + struct graph_node *gn) { struct wrap_graph_node *wrap; size_t i; @@ -177,7 +176,8 @@ static PyObject *graph_to_pyobj(struct wrap_graph *wgraph, struct graph_node *gn return obj; } - wrap = (struct wrap_graph_node *)typeobj_graph_node.tp_alloc(&typeobj_graph_node, 0); + wrap = (struct wrap_graph_node *)typeobj_graph_node.tp_alloc( + &typeobj_graph_node, 0); if (!wrap) return NULL; wgraph->nodewrappers[i] = wrap; @@ -192,21 +192,18 @@ static PyObject *graph_to_pyobj(struct wrap_graph *wgraph, struct graph_node *gn struct cmd_token *tok = gn->data; switch (tok->type) { #define item(x) case x: wrap->type = #x; break; - item(WORD_TKN) // words - item(VARIABLE_TKN) // almost anything - item(RANGE_TKN) // integer range - item(IPV4_TKN) // IPV4 addresses - item(IPV4_PREFIX_TKN) // IPV4 network prefixes - item(IPV6_TKN) // IPV6 prefixes - item(IPV6_PREFIX_TKN) // IPV6 network prefixes - - /* plumbing types */ - item(FORK_TKN) - item(JOIN_TKN) - item(START_TKN) - item(END_TKN) - default: - wrap->type = "???"; + item(WORD_TKN) // words + item(VARIABLE_TKN) // almost anything + item(RANGE_TKN) // integer range + item(IPV4_TKN) // IPV4 addresses + item(IPV4_PREFIX_TKN) // IPV4 network prefixes + item(IPV6_TKN) // IPV6 prefixes + item(IPV6_PREFIX_TKN) // IPV6 network prefixes + + /* plumbing types */ + item(FORK_TKN) item(JOIN_TKN) item(START_TKN) + item(END_TKN) default + : wrap->type = "???"; } wrap->deprecated = (tok->attr == CMD_ATTR_DEPRECATED); @@ -222,8 +219,11 @@ static PyObject *graph_to_pyobj(struct wrap_graph *wgraph, struct graph_node *gn return (PyObject *)wrap; } -#define member(name, type) {(char *)#name, type, offsetof(struct wrap_graph, name), READONLY, \ - (char *)#name " (" #type ")"} +#define member(name, type) \ + { \ + (char *)#name, type, offsetof(struct wrap_graph, name), \ + READONLY, (char *)#name " (" #type ")" \ + } static PyMemberDef members_graph[] = { member(definition, T_STRING), {}, @@ -240,10 +240,10 @@ static PyObject *graph_first(PyObject *self, PyObject *args) static PyMethodDef methods_graph[] = { {"first", graph_first, METH_NOARGS, "first graph node"}, - {} -}; + {}}; -static PyObject *graph_parse(PyTypeObject *type, PyObject *args, PyObject *kwds); +static PyObject *graph_parse(PyTypeObject *type, PyObject *args, + PyObject *kwds); static void graph_wrap_free(void *arg) { @@ -253,15 +253,14 @@ static void graph_wrap_free(void *arg) } static PyTypeObject typeobj_graph = { - PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "_clippy.Graph", - .tp_basicsize = sizeof(struct wrap_graph), - .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_doc = "struct graph *", - .tp_new = graph_parse, - .tp_free = graph_wrap_free, - .tp_members = members_graph, - .tp_methods = methods_graph, + PyVarObject_HEAD_INIT(NULL, 0).tp_name = "_clippy.Graph", + .tp_basicsize = sizeof(struct wrap_graph), + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = "struct graph *", + .tp_new = graph_parse, + .tp_free = graph_wrap_free, + .tp_members = members_graph, + .tp_methods = methods_graph, }; /* top call / entrypoint for python code */ @@ -269,34 +268,34 @@ static PyObject *graph_parse(PyTypeObject *type, PyObject *args, PyObject *kwds) { const char *def, *doc = NULL; struct wrap_graph *gwrap; - static const char *kwnames[] = { "cmddef", "doc", NULL }; + static const char *kwnames[] = {"cmddef", "doc", NULL}; gwrap = (struct wrap_graph *)typeobj_graph.tp_alloc(&typeobj_graph, 0); if (!gwrap) return NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s", (char **)kwnames, &def, &doc)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s", (char **)kwnames, + &def, &doc)) return NULL; - struct graph *graph = graph_new (); - struct cmd_token *token = cmd_token_new (START_TKN, 0, NULL, NULL); - graph_new_node (graph, token, (void (*)(void *)) &cmd_token_del); + struct graph *graph = graph_new(); + struct cmd_token *token = cmd_token_new(START_TKN, 0, NULL, NULL); + graph_new_node(graph, token, (void (*)(void *)) & cmd_token_del); - struct cmd_element cmd = { .string = def, .doc = doc }; - cmd_graph_parse (graph, &cmd); - cmd_graph_names (graph); + struct cmd_element cmd = {.string = def, .doc = doc}; + cmd_graph_parse(graph, &cmd); + cmd_graph_names(graph); gwrap->graph = graph; gwrap->definition = strdup(def); gwrap->nodewrappers = calloc(vector_active(graph->nodes), - sizeof (gwrap->nodewrappers[0])); + sizeof(gwrap->nodewrappers[0])); return (PyObject *)gwrap; } static PyMethodDef clippy_methods[] = { {"parse", clippy_parse, METH_VARARGS, "Parse a C file"}, - {NULL, NULL, 0, NULL} -}; + {NULL, NULL, 0, NULL}}; #if PY_MAJOR_VERSION >= 3 static struct PyModuleDef pymoddef_clippy = { @@ -310,14 +309,17 @@ static struct PyModuleDef pymoddef_clippy = { #define initret(val) return val; #else #define modcreate() Py_InitModule("_clippy", clippy_methods) -#define initret(val) do { \ - if (!val) Py_FatalError("initialization failure"); \ - return; } while (0) +#define initret(val) \ + do { \ + if (!val) \ + Py_FatalError("initialization failure"); \ + return; \ + } while (0) #endif PyMODINIT_FUNC command_py_init(void) { - PyObject* pymod; + PyObject *pymod; if (PyType_Ready(&typeobj_graph_node) < 0) initret(NULL); diff --git a/lib/csv.c b/lib/csv.c index bfe712bad..0ad5c74be 100644 --- a/lib/csv.c +++ b/lib/csv.c @@ -30,690 +30,665 @@ #define DEBUG_E 1 #define DEBUG_V 1 -#define log_error(fmt, ...) \ - do { if (DEBUG_E) fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, \ - __LINE__, __func__, ##__VA_ARGS__); } while (0) - -#define log_verbose(fmt, ...) \ - do { if (DEBUG_V) fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, \ - __LINE__, __func__, __VA_ARGS__); } while (0) +#define log_error(fmt, ...) \ + do { \ + if (DEBUG_E) \ + fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, \ + __LINE__, __func__, ##__VA_ARGS__); \ + } while (0) + +#define log_verbose(fmt, ...) \ + do { \ + if (DEBUG_V) \ + fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, \ + __LINE__, __func__, __VA_ARGS__); \ + } while (0) struct _csv_field_t_ { - TAILQ_ENTRY(_csv_field_t_) next_field; - char *field; - int field_len; + TAILQ_ENTRY(_csv_field_t_) next_field; + char *field; + int field_len; }; struct _csv_record_t_ { - TAILQ_HEAD(, _csv_field_t_) fields; - TAILQ_ENTRY(_csv_record_t_) next_record; - char *record; - int rec_len; + TAILQ_HEAD(, _csv_field_t_) fields; + TAILQ_ENTRY(_csv_record_t_) next_record; + char *record; + int rec_len; }; struct _csv_t_ { - TAILQ_HEAD(, _csv_record_t_) records; - char *buf; - int buflen; - int csv_len; - int pointer; - int num_recs; + TAILQ_HEAD(, _csv_record_t_) records; + char *buf; + int buflen; + int csv_len; + int pointer; + int num_recs; }; -int -csvlen (csv_t *csv) +int csvlen(csv_t *csv) { - return (csv->csv_len); + return (csv->csv_len); } -csv_t * -csv_init (csv_t *csv, - char *buf, - int buflen) +csv_t *csv_init(csv_t *csv, char *buf, int buflen) { - if (csv == NULL) { - csv = malloc(sizeof(csv_t)); - if (csv == NULL) { - log_error("CSV Malloc failed\n"); - return (NULL); - } - } - memset(csv, 0, sizeof(csv_t)); - - csv->buf = buf; - csv->buflen = buflen; - TAILQ_INIT(&(csv->records)); - return (csv); + if (csv == NULL) { + csv = malloc(sizeof(csv_t)); + if (csv == NULL) { + log_error("CSV Malloc failed\n"); + return (NULL); + } + } + memset(csv, 0, sizeof(csv_t)); + + csv->buf = buf; + csv->buflen = buflen; + TAILQ_INIT(&(csv->records)); + return (csv); } -void -csv_clean (csv_t *csv) +void csv_clean(csv_t *csv) { - csv_record_t *rec; - csv_record_t *rec_n; - - rec = TAILQ_FIRST(&(csv->records)); - while (rec != NULL) { - rec_n = TAILQ_NEXT(rec, next_record); - csv_remove_record(csv, rec); - rec = rec_n; - } + csv_record_t *rec; + csv_record_t *rec_n; + + rec = TAILQ_FIRST(&(csv->records)); + while (rec != NULL) { + rec_n = TAILQ_NEXT(rec, next_record); + csv_remove_record(csv, rec); + rec = rec_n; + } } -void -csv_free (csv_t *csv) +void csv_free(csv_t *csv) { - if (csv != NULL) { - free(csv); - } + if (csv != NULL) { + free(csv); + } } -static void -csv_init_record (csv_record_t *record) +static void csv_init_record(csv_record_t *record) { - TAILQ_INIT(&(record->fields)); - record->rec_len = 0; + TAILQ_INIT(&(record->fields)); + record->rec_len = 0; } -csv_record_t * -csv_record_iter (csv_t *csv) +csv_record_t *csv_record_iter(csv_t *csv) { - return(TAILQ_FIRST(&(csv->records))); + return (TAILQ_FIRST(&(csv->records))); } -csv_record_t * -csv_record_iter_next (csv_record_t *rec) +csv_record_t *csv_record_iter_next(csv_record_t *rec) { - if(!rec) return NULL; - return(TAILQ_NEXT(rec, next_record)); + if (!rec) + return NULL; + return (TAILQ_NEXT(rec, next_record)); } -char * -csv_field_iter (csv_record_t *rec, - csv_field_t **fld) +char *csv_field_iter(csv_record_t *rec, csv_field_t **fld) { - if(!rec) return NULL; - *fld = TAILQ_FIRST(&(rec->fields)); - return ((*fld)->field); + if (!rec) + return NULL; + *fld = TAILQ_FIRST(&(rec->fields)); + return ((*fld)->field); } -char * -csv_field_iter_next (csv_field_t **fld) +char *csv_field_iter_next(csv_field_t **fld) { - *fld = TAILQ_NEXT(*fld, next_field); - if ((*fld) == NULL) { - return (NULL); - } - return ((*fld)->field); + *fld = TAILQ_NEXT(*fld, next_field); + if ((*fld) == NULL) { + return (NULL); + } + return ((*fld)->field); } -int -csv_field_len(csv_field_t *fld) +int csv_field_len(csv_field_t *fld) { - if (fld) { - return fld->field_len; - } - return 0; + if (fld) { + return fld->field_len; + } + return 0; } -static void -csv_decode_record(csv_record_t *rec) +static void csv_decode_record(csv_record_t *rec) { - char *curr = rec->record; - char *field; - csv_field_t *fld; - - field = strpbrk(curr, ","); - while (field != NULL) { - fld = malloc(sizeof(csv_field_t)); - if (fld) { - TAILQ_INSERT_TAIL(&(rec->fields), fld, next_field); - fld->field = curr; - fld->field_len = field-curr; - } - curr = field + 1; - field = strpbrk(curr, ","); - } - field = strstr(curr, "\n"); - if (!field) - return; - - fld = malloc(sizeof(csv_field_t)); - if (fld) { - fld->field = curr; - fld->field_len = field-curr; - TAILQ_INSERT_TAIL(&(rec->fields), fld, next_field); - } + char *curr = rec->record; + char *field; + csv_field_t *fld; + + field = strpbrk(curr, ","); + while (field != NULL) { + fld = malloc(sizeof(csv_field_t)); + if (fld) { + TAILQ_INSERT_TAIL(&(rec->fields), fld, next_field); + fld->field = curr; + fld->field_len = field - curr; + } + curr = field + 1; + field = strpbrk(curr, ","); + } + field = strstr(curr, "\n"); + if (!field) + return; + + fld = malloc(sizeof(csv_field_t)); + if (fld) { + fld->field = curr; + fld->field_len = field - curr; + TAILQ_INSERT_TAIL(&(rec->fields), fld, next_field); + } } -static csv_field_t * -csv_add_field_to_record(csv_t *csv, - csv_record_t *rec, - char *col) +static csv_field_t *csv_add_field_to_record(csv_t *csv, csv_record_t *rec, + char *col) { - csv_field_t *fld; - char *str = rec->record; - int rlen = rec->rec_len; - int blen = csv->buflen; - - fld = malloc(sizeof(csv_field_t)); - if (!fld) { - log_error("field malloc failed\n"); - /* more cleanup needed */ - return (NULL); - } - TAILQ_INSERT_TAIL(&(rec->fields), fld, next_field); - fld->field = str+rlen; - fld->field_len = snprintf((str+rlen), (blen - rlen), "%s", col); - rlen += fld->field_len; - rec->rec_len = rlen; - return fld; + csv_field_t *fld; + char *str = rec->record; + int rlen = rec->rec_len; + int blen = csv->buflen; + + fld = malloc(sizeof(csv_field_t)); + if (!fld) { + log_error("field malloc failed\n"); + /* more cleanup needed */ + return (NULL); + } + TAILQ_INSERT_TAIL(&(rec->fields), fld, next_field); + fld->field = str + rlen; + fld->field_len = snprintf((str + rlen), (blen - rlen), "%s", col); + rlen += fld->field_len; + rec->rec_len = rlen; + return fld; } -csv_record_t * -csv_encode (csv_t *csv, - int count, - ...) +csv_record_t *csv_encode(csv_t *csv, int count, ...) { - int tempc; - va_list list; - char *buf = csv->buf; - int len = csv->buflen; - int pointer = csv->pointer; - char *str = NULL; - char *col; - csv_record_t *rec; - csv_field_t *fld; - - if (buf) { - str = buf + pointer; - } else { - /* allocate sufficient buffer */ - str = (char *)malloc(csv->buflen); - if (!str) { - log_error("field str malloc failed\n"); - return (NULL); - } - } - - va_start(list, count); - rec = malloc(sizeof(csv_record_t)); - if (!rec) { - log_error("record malloc failed\n"); - if (!buf) - free(str); - va_end(list); - return (NULL); - } - csv_init_record(rec); - rec->record = str; - TAILQ_INSERT_TAIL(&(csv->records), rec, next_record); - csv->num_recs++; - - /** - * Iterate through the fields passed as a variable list and add them - */ - for (tempc = 0; tempc < count; tempc++) { - col = va_arg(list, char *); - fld = csv_add_field_to_record(csv, rec, col); - if (!fld) { - log_error("fld malloc failed\n"); - csv_remove_record(csv, rec); - va_end(list); - return (NULL); - } - if (tempc < (count - 1)) { - rec->rec_len += snprintf((str+rec->rec_len), (len - rec->rec_len), ","); - } - } - rec->rec_len += snprintf((str+rec->rec_len), (len - rec->rec_len), "\n"); - va_end(list); - csv->csv_len += rec->rec_len; - csv->pointer += rec->rec_len; - return (rec); + int tempc; + va_list list; + char *buf = csv->buf; + int len = csv->buflen; + int pointer = csv->pointer; + char *str = NULL; + char *col; + csv_record_t *rec; + csv_field_t *fld; + + if (buf) { + str = buf + pointer; + } else { + /* allocate sufficient buffer */ + str = (char *)malloc(csv->buflen); + if (!str) { + log_error("field str malloc failed\n"); + return (NULL); + } + } + + va_start(list, count); + rec = malloc(sizeof(csv_record_t)); + if (!rec) { + log_error("record malloc failed\n"); + if (!buf) + free(str); + va_end(list); + return (NULL); + } + csv_init_record(rec); + rec->record = str; + TAILQ_INSERT_TAIL(&(csv->records), rec, next_record); + csv->num_recs++; + + /** + * Iterate through the fields passed as a variable list and add them + */ + for (tempc = 0; tempc < count; tempc++) { + col = va_arg(list, char *); + fld = csv_add_field_to_record(csv, rec, col); + if (!fld) { + log_error("fld malloc failed\n"); + csv_remove_record(csv, rec); + va_end(list); + return (NULL); + } + if (tempc < (count - 1)) { + rec->rec_len += snprintf((str + rec->rec_len), + (len - rec->rec_len), ","); + } + } + rec->rec_len += + snprintf((str + rec->rec_len), (len - rec->rec_len), "\n"); + va_end(list); + csv->csv_len += rec->rec_len; + csv->pointer += rec->rec_len; + return (rec); } -int -csv_num_records (csv_t *csv) +int csv_num_records(csv_t *csv) { - if (csv) { - return csv->num_recs; - } - return 0; + if (csv) { + return csv->num_recs; + } + return 0; } -csv_record_t * -csv_encode_record (csv_t *csv, - csv_record_t *rec, - int count, - ...) +csv_record_t *csv_encode_record(csv_t *csv, csv_record_t *rec, int count, ...) { - int tempc; - va_list list; - char *str; - char *col; - csv_field_t *fld = NULL; - int i; - - va_start(list, count); - str = csv_field_iter(rec, &fld); - for (tempc = 0; tempc < count; tempc++) { - col = va_arg(list, char *); - for (i = 0; i < fld->field_len; i++) { - str[i] = col[i]; - } - str = csv_field_iter_next(&fld); - } - va_end(list); - return (rec); + int tempc; + va_list list; + char *str; + char *col; + csv_field_t *fld = NULL; + int i; + + va_start(list, count); + str = csv_field_iter(rec, &fld); + for (tempc = 0; tempc < count; tempc++) { + col = va_arg(list, char *); + for (i = 0; i < fld->field_len; i++) { + str[i] = col[i]; + } + str = csv_field_iter_next(&fld); + } + va_end(list); + return (rec); } -csv_record_t * -csv_append_record (csv_t *csv, - csv_record_t *rec, - int count, - ...) +csv_record_t *csv_append_record(csv_t *csv, csv_record_t *rec, int count, ...) { - int tempc; - va_list list; - int len = csv->buflen, tlen; - char *str; - csv_field_t *fld; - char *col; - - if (csv->buf) { - /* not only works with discrete bufs */ - return NULL; - } - - if (!rec) { - /* create a new rec */ - rec = calloc(1, sizeof(csv_record_t)); - if (!rec) { - log_error("record malloc failed\n"); - return NULL; - } - csv_init_record(rec); - rec->record = calloc(1, csv->buflen); - if (!rec->record) { - log_error("field str malloc failed\n"); - free(rec); - return NULL; - } - csv_insert_record(csv, rec); - } - - str = rec->record; - - va_start(list, count); - - if (rec->rec_len && (str[rec->rec_len-1] == '\n')) - str[rec->rec_len-1] = ','; - - /** - * Iterate through the fields passed as a variable list and add them - */ - tlen = rec->rec_len; - for (tempc = 0; tempc < count; tempc++) { - col = va_arg(list, char *); - fld = csv_add_field_to_record(csv, rec, col); - if (!fld) { - log_error("fld malloc failed\n"); - break; - } - if (tempc < (count - 1)) { - rec->rec_len += snprintf((str+rec->rec_len), - (len - rec->rec_len), ","); - } - } - rec->rec_len += snprintf((str+rec->rec_len), - (len - rec->rec_len), "\n"); - va_end(list); - csv->csv_len += (rec->rec_len - tlen); - csv->pointer += (rec->rec_len - tlen); - return (rec); + int tempc; + va_list list; + int len = csv->buflen, tlen; + char *str; + csv_field_t *fld; + char *col; + + if (csv->buf) { + /* not only works with discrete bufs */ + return NULL; + } + + if (!rec) { + /* create a new rec */ + rec = calloc(1, sizeof(csv_record_t)); + if (!rec) { + log_error("record malloc failed\n"); + return NULL; + } + csv_init_record(rec); + rec->record = calloc(1, csv->buflen); + if (!rec->record) { + log_error("field str malloc failed\n"); + free(rec); + return NULL; + } + csv_insert_record(csv, rec); + } + + str = rec->record; + + va_start(list, count); + + if (rec->rec_len && (str[rec->rec_len - 1] == '\n')) + str[rec->rec_len - 1] = ','; + + /** + * Iterate through the fields passed as a variable list and add them + */ + tlen = rec->rec_len; + for (tempc = 0; tempc < count; tempc++) { + col = va_arg(list, char *); + fld = csv_add_field_to_record(csv, rec, col); + if (!fld) { + log_error("fld malloc failed\n"); + break; + } + if (tempc < (count - 1)) { + rec->rec_len += snprintf((str + rec->rec_len), + (len - rec->rec_len), ","); + } + } + rec->rec_len += + snprintf((str + rec->rec_len), (len - rec->rec_len), "\n"); + va_end(list); + csv->csv_len += (rec->rec_len - tlen); + csv->pointer += (rec->rec_len - tlen); + return (rec); } -int -csv_serialize(csv_t *csv, char *msgbuf, int msglen) +int csv_serialize(csv_t *csv, char *msgbuf, int msglen) { - csv_record_t *rec; - int offset = 0; + csv_record_t *rec; + int offset = 0; - if (!csv || !msgbuf) return -1; + if (!csv || !msgbuf) + return -1; - rec = csv_record_iter(csv); - while (rec != NULL) { - if ((offset + rec->rec_len) >= msglen) - return -1; - offset += sprintf(&msgbuf[offset], "%s", rec->record); - rec = csv_record_iter_next(rec); - } + rec = csv_record_iter(csv); + while (rec != NULL) { + if ((offset + rec->rec_len) >= msglen) + return -1; + offset += sprintf(&msgbuf[offset], "%s", rec->record); + rec = csv_record_iter_next(rec); + } - return 0; + return 0; } -void -csv_clone_record (csv_t *csv, csv_record_t *in_rec, csv_record_t **out_rec) +void csv_clone_record(csv_t *csv, csv_record_t *in_rec, csv_record_t **out_rec) { - char *curr; - csv_record_t *rec; - - /* first check if rec belongs to this csv */ - if(!csv_is_record_valid(csv, in_rec)){ - log_error("rec not in this csv\n"); - return; - } - - /* only works with csv with discrete bufs */ - if (csv->buf) { - log_error("un-supported for this csv type - single buf detected\n"); - return; - } - - /* create a new rec */ - rec = calloc(1, sizeof(csv_record_t)); - if (!rec) { - log_error("record malloc failed\n"); - return; - } - csv_init_record(rec); - curr = calloc(1, csv->buflen); - if (!curr) { - log_error("field str malloc failed\n"); - free(rec); - return; - } - rec->record = curr; - rec->rec_len = in_rec->rec_len; - strcpy(rec->record, in_rec->record); - - /* decode record into fields */ - csv_decode_record(rec); - - *out_rec = rec; + char *curr; + csv_record_t *rec; + + /* first check if rec belongs to this csv */ + if (!csv_is_record_valid(csv, in_rec)) { + log_error("rec not in this csv\n"); + return; + } + + /* only works with csv with discrete bufs */ + if (csv->buf) { + log_error( + "un-supported for this csv type - single buf detected\n"); + return; + } + + /* create a new rec */ + rec = calloc(1, sizeof(csv_record_t)); + if (!rec) { + log_error("record malloc failed\n"); + return; + } + csv_init_record(rec); + curr = calloc(1, csv->buflen); + if (!curr) { + log_error("field str malloc failed\n"); + free(rec); + return; + } + rec->record = curr; + rec->rec_len = in_rec->rec_len; + strcpy(rec->record, in_rec->record); + + /* decode record into fields */ + csv_decode_record(rec); + + *out_rec = rec; } -void -csv_remove_record (csv_t *csv, csv_record_t *rec) +void csv_remove_record(csv_t *csv, csv_record_t *rec) { - csv_field_t *fld, *p_fld; - - /* first check if rec belongs to this csv */ - if(!csv_is_record_valid(csv, rec)){ - log_error("rec not in this csv\n"); - return; - } - - /* remove fields */ - csv_field_iter(rec, &fld); - while(fld) { - p_fld = fld; - csv_field_iter_next(&fld); - TAILQ_REMOVE(&(rec->fields), p_fld, next_field); - free(p_fld); - } - - TAILQ_REMOVE(&(csv->records), rec, next_record); - - csv->num_recs--; - csv->csv_len -= rec->rec_len; - csv->pointer -= rec->rec_len; - if (!csv->buf) - free(rec->record); - free(rec); + csv_field_t *fld, *p_fld; + + /* first check if rec belongs to this csv */ + if (!csv_is_record_valid(csv, rec)) { + log_error("rec not in this csv\n"); + return; + } + + /* remove fields */ + csv_field_iter(rec, &fld); + while (fld) { + p_fld = fld; + csv_field_iter_next(&fld); + TAILQ_REMOVE(&(rec->fields), p_fld, next_field); + free(p_fld); + } + + TAILQ_REMOVE(&(csv->records), rec, next_record); + + csv->num_recs--; + csv->csv_len -= rec->rec_len; + csv->pointer -= rec->rec_len; + if (!csv->buf) + free(rec->record); + free(rec); } -void -csv_insert_record (csv_t *csv, csv_record_t *rec) +void csv_insert_record(csv_t *csv, csv_record_t *rec) { - /* first check if rec already in csv */ - if(csv_is_record_valid(csv, rec)){ - log_error("rec already in this csv\n"); - return; - } - - /* we can only insert records if no buf was supplied during csv init */ - if (csv->buf) { - log_error("un-supported for this csv type - single buf detected\n"); - return; - } - - /* do we go beyond the max buf set for this csv ?*/ - if ((csv->csv_len + rec->rec_len) > csv->buflen ) { - log_error("cannot insert - exceeded buf size\n"); - return; - } - - TAILQ_INSERT_TAIL(&(csv->records), rec, next_record); - csv->num_recs++; - csv->csv_len += rec->rec_len; - csv->pointer += rec->rec_len; + /* first check if rec already in csv */ + if (csv_is_record_valid(csv, rec)) { + log_error("rec already in this csv\n"); + return; + } + + /* we can only insert records if no buf was supplied during csv init */ + if (csv->buf) { + log_error( + "un-supported for this csv type - single buf detected\n"); + return; + } + + /* do we go beyond the max buf set for this csv ?*/ + if ((csv->csv_len + rec->rec_len) > csv->buflen) { + log_error("cannot insert - exceeded buf size\n"); + return; + } + + TAILQ_INSERT_TAIL(&(csv->records), rec, next_record); + csv->num_recs++; + csv->csv_len += rec->rec_len; + csv->pointer += rec->rec_len; } -csv_record_t * -csv_concat_record (csv_t *csv, - csv_record_t *rec1, - csv_record_t *rec2) +csv_record_t *csv_concat_record(csv_t *csv, csv_record_t *rec1, + csv_record_t *rec2) { - char *curr; - char *ret; - csv_record_t *rec; - - /* first check if rec1 and rec2 belong to this csv */ - if(!csv_is_record_valid(csv, rec1) || - !csv_is_record_valid(csv, rec2)) { - log_error("rec1 and/or rec2 invalid\n"); - return (NULL); - } - - /* we can only concat records if no buf was supplied during csv init */ - if (csv->buf) { - log_error("un-supported for this csv type - single buf detected\n"); - return (NULL); - } - - /* create a new rec */ - rec = calloc(1, sizeof(csv_record_t)); - if (!rec) { - log_error("record malloc failed\n"); - return (NULL); - } - csv_init_record(rec); - - curr = (char *)calloc(1, csv->buflen); - if (!curr) { - log_error("field str malloc failed\n"); - goto out_rec; - } - rec->record = curr; - - /* concat the record string */ - ret = strstr(rec1->record, "\n"); - if (!ret) { - log_error("rec1 str not properly formatted\n"); - goto out_curr; - } - - snprintf(curr, (int)(ret - rec1->record + 1), "%s", rec1->record); - strcat(curr, ","); - - ret = strstr(rec2->record, "\n"); - if (!ret) { - log_error("rec2 str not properly formatted\n"); - goto out_curr; - } - - snprintf((curr+strlen(curr)), (int)(ret - rec2->record + 1), "%s", - rec2->record); - strcat(curr, "\n"); - rec->rec_len = strlen(curr); - - /* paranoia */ - assert(csv->buflen > - (csv->csv_len - rec1->rec_len - rec2->rec_len + rec->rec_len)); - - /* decode record into fields */ - csv_decode_record(rec); - - /* now remove rec1 and rec2 and insert rec into this csv */ - csv_remove_record(csv, rec1); - csv_remove_record(csv, rec2); - csv_insert_record(csv, rec); - - return rec; + char *curr; + char *ret; + csv_record_t *rec; + + /* first check if rec1 and rec2 belong to this csv */ + if (!csv_is_record_valid(csv, rec1) + || !csv_is_record_valid(csv, rec2)) { + log_error("rec1 and/or rec2 invalid\n"); + return (NULL); + } + + /* we can only concat records if no buf was supplied during csv init */ + if (csv->buf) { + log_error( + "un-supported for this csv type - single buf detected\n"); + return (NULL); + } + + /* create a new rec */ + rec = calloc(1, sizeof(csv_record_t)); + if (!rec) { + log_error("record malloc failed\n"); + return (NULL); + } + csv_init_record(rec); + + curr = (char *)calloc(1, csv->buflen); + if (!curr) { + log_error("field str malloc failed\n"); + goto out_rec; + } + rec->record = curr; + + /* concat the record string */ + ret = strstr(rec1->record, "\n"); + if (!ret) { + log_error("rec1 str not properly formatted\n"); + goto out_curr; + } + + snprintf(curr, (int)(ret - rec1->record + 1), "%s", rec1->record); + strcat(curr, ","); + + ret = strstr(rec2->record, "\n"); + if (!ret) { + log_error("rec2 str not properly formatted\n"); + goto out_curr; + } + + snprintf((curr + strlen(curr)), (int)(ret - rec2->record + 1), "%s", + rec2->record); + strcat(curr, "\n"); + rec->rec_len = strlen(curr); + + /* paranoia */ + assert(csv->buflen + > (csv->csv_len - rec1->rec_len - rec2->rec_len + rec->rec_len)); + + /* decode record into fields */ + csv_decode_record(rec); + + /* now remove rec1 and rec2 and insert rec into this csv */ + csv_remove_record(csv, rec1); + csv_remove_record(csv, rec2); + csv_insert_record(csv, rec); + + return rec; out_curr: - free(curr); + free(curr); out_rec: - free(rec); - return NULL; + free(rec); + return NULL; } -void -csv_decode (csv_t *csv, char *inbuf) +void csv_decode(csv_t *csv, char *inbuf) { - char *buf; - char *pos; - csv_record_t *rec; - - buf = (inbuf)? inbuf:csv->buf; - pos = strpbrk(buf, "\n"); - while (pos != NULL) { - rec = calloc(1, sizeof(csv_record_t)); - if (!rec) - return; - csv_init_record(rec); - TAILQ_INSERT_TAIL(&(csv->records), rec, next_record); - csv->num_recs++; - if (csv->buf) - rec->record = buf; - else { - rec->record = calloc(1, csv->buflen); - if (!rec->record) { - log_error("field str malloc failed\n"); - return; - } - strncpy(rec->record, buf, pos-buf+1); - } - rec->rec_len = pos-buf+1; - /* decode record into fields */ - csv_decode_record(rec); - buf = pos+1; - pos = strpbrk(buf, "\n"); - } + char *buf; + char *pos; + csv_record_t *rec; + + buf = (inbuf) ? inbuf : csv->buf; + pos = strpbrk(buf, "\n"); + while (pos != NULL) { + rec = calloc(1, sizeof(csv_record_t)); + if (!rec) + return; + csv_init_record(rec); + TAILQ_INSERT_TAIL(&(csv->records), rec, next_record); + csv->num_recs++; + if (csv->buf) + rec->record = buf; + else { + rec->record = calloc(1, csv->buflen); + if (!rec->record) { + log_error("field str malloc failed\n"); + return; + } + strncpy(rec->record, buf, pos - buf + 1); + } + rec->rec_len = pos - buf + 1; + /* decode record into fields */ + csv_decode_record(rec); + buf = pos + 1; + pos = strpbrk(buf, "\n"); + } } -int -csv_is_record_valid(csv_t *csv, csv_record_t *in_rec) +int csv_is_record_valid(csv_t *csv, csv_record_t *in_rec) { - csv_record_t *rec; - int valid = 0; - - rec = csv_record_iter(csv); - while (rec) { - if(rec == in_rec) { - valid = 1; - break; - } - rec = csv_record_iter_next(rec); - } - - return valid; + csv_record_t *rec; + int valid = 0; + + rec = csv_record_iter(csv); + while (rec) { + if (rec == in_rec) { + valid = 1; + break; + } + rec = csv_record_iter_next(rec); + } + + return valid; } -void -csv_dump (csv_t *csv) +void csv_dump(csv_t *csv) { - csv_record_t *rec; - csv_field_t *fld; - char *str; - - rec = csv_record_iter(csv); - while (rec != NULL) { - str = csv_field_iter(rec, &fld); - while (str != NULL) { - fprintf(stderr, "%s\n", str); - str = csv_field_iter_next(&fld); - } - rec = csv_record_iter_next(rec); - } + csv_record_t *rec; + csv_field_t *fld; + char *str; + + rec = csv_record_iter(csv); + while (rec != NULL) { + str = csv_field_iter(rec, &fld); + while (str != NULL) { + fprintf(stderr, "%s\n", str); + str = csv_field_iter_next(&fld); + } + rec = csv_record_iter_next(rec); + } } #ifdef TEST_CSV -static int -get_memory_usage (pid_t pid) +static int get_memory_usage(pid_t pid) { - int fd, data, stack; - char buf[4096], status_child[BUFSIZ]; - char *vm; - - sprintf(status_child, "/proc/%d/status", pid); - if ((fd = open(status_child, O_RDONLY)) < 0) - return -1; - - read(fd, buf, 4095); - buf[4095] = '\0'; - close(fd); - - data = stack = 0; - - vm = strstr(buf, "VmData:"); - if (vm) { - sscanf(vm, "%*s %d", &data); - } - vm = strstr(buf, "VmStk:"); - if (vm) { - sscanf(vm, "%*s %d", &stack); - } - - return data + stack; + int fd, data, stack; + char buf[4096], status_child[BUFSIZ]; + char *vm; + + sprintf(status_child, "/proc/%d/status", pid); + if ((fd = open(status_child, O_RDONLY)) < 0) + return -1; + + read(fd, buf, 4095); + buf[4095] = '\0'; + close(fd); + + data = stack = 0; + + vm = strstr(buf, "VmData:"); + if (vm) { + sscanf(vm, "%*s %d", &data); + } + vm = strstr(buf, "VmStk:"); + if (vm) { + sscanf(vm, "%*s %d", &stack); + } + + return data + stack; } -int main () +int main() { - char buf[10000]; - csv_t csv; - int p; - int i, j; - csv_record_t *rec; - csv_field_t *fld; - char *str; - char hdr1[32], hdr2[32]; - - log_verbose("Mem: %ld\n", get_memory_usage(getpid())); - csv_init(&csv, buf, 256); - sprintf(hdr1, "%4u", 0); - sprintf(hdr2, "%4u", 1); - log_verbose("(%d/%d/%d/%d)\n", strlen(hdr1), - strlen(hdr2), atoi(hdr1), atoi(hdr2)); - rec = csv_encode(&csv, 2, hdr1, hdr2); - csv_encode(&csv, 4, "name", "age", "sex", "hei"); - csv_encode(&csv, 3, NULL, "0", NULL); - csv_encode(&csv, 2, "p", "35"); - for (i=0; i < 50; i++) { - csv_encode(&csv, 2, "p", "10"); - } - csv_encode(&csv, 2, "pdfadfadfadsadsaddfdfdsfdsd", - "35444554545454545"); - log_verbose("%s\n", buf); - sprintf(hdr1, "%4u", csv.csv_len); - sprintf(hdr2, "%4u", 1); - log_verbose("(%d/%d/%d/%d)\n", strlen(hdr1), - strlen(hdr2), atoi(hdr1), atoi(hdr2)); - rec = csv_encode_record(&csv, rec, 2, hdr1, hdr2); - log_verbose("(%d/%d)\n%s\n", rec->rec_len, csv.csv_len, buf); - - log_verbose("Mem: %ld\n", get_memory_usage(getpid())); - csv_clean(&csv); - log_verbose("Mem: %ld\n", get_memory_usage(getpid())); - csv_init(&csv, buf, 256); - csv_decode(&csv, NULL); - log_verbose("AFTER DECODE\n"); - csv_dump(&csv); - csv_clean(&csv); - log_verbose("Mem: %ld\n", get_memory_usage(getpid())); + char buf[10000]; + csv_t csv; + int p; + int i, j; + csv_record_t *rec; + csv_field_t *fld; + char *str; + char hdr1[32], hdr2[32]; + + log_verbose("Mem: %ld\n", get_memory_usage(getpid())); + csv_init(&csv, buf, 256); + sprintf(hdr1, "%4u", 0); + sprintf(hdr2, "%4u", 1); + log_verbose("(%d/%d/%d/%d)\n", strlen(hdr1), strlen(hdr2), atoi(hdr1), + atoi(hdr2)); + rec = csv_encode(&csv, 2, hdr1, hdr2); + csv_encode(&csv, 4, "name", "age", "sex", "hei"); + csv_encode(&csv, 3, NULL, "0", NULL); + csv_encode(&csv, 2, "p", "35"); + for (i = 0; i < 50; i++) { + csv_encode(&csv, 2, "p", "10"); + } + csv_encode(&csv, 2, "pdfadfadfadsadsaddfdfdsfdsd", "35444554545454545"); + log_verbose("%s\n", buf); + sprintf(hdr1, "%4u", csv.csv_len); + sprintf(hdr2, "%4u", 1); + log_verbose("(%d/%d/%d/%d)\n", strlen(hdr1), strlen(hdr2), atoi(hdr1), + atoi(hdr2)); + rec = csv_encode_record(&csv, rec, 2, hdr1, hdr2); + log_verbose("(%d/%d)\n%s\n", rec->rec_len, csv.csv_len, buf); + + log_verbose("Mem: %ld\n", get_memory_usage(getpid())); + csv_clean(&csv); + log_verbose("Mem: %ld\n", get_memory_usage(getpid())); + csv_init(&csv, buf, 256); + csv_decode(&csv, NULL); + log_verbose("AFTER DECODE\n"); + csv_dump(&csv); + csv_clean(&csv); + log_verbose("Mem: %ld\n", get_memory_usage(getpid())); } #endif diff --git a/lib/csv.h b/lib/csv.h index 3ee568578..3a0e5558c 100644 --- a/lib/csv.h +++ b/lib/csv.h @@ -78,7 +78,7 @@ typedef struct _csv_t_ csv_t; * Initialize the CSV structure (if necessary, allocate first). Point to * the passed string buffer. */ -csv_t * csv_init(csv_t *csv, char *buf, int buflen); +csv_t *csv_init(csv_t *csv, char *buf, int buflen); /** * Encode the variable list of arguments as CSV fields. The csv structure @@ -99,8 +99,7 @@ csv_record_t *csv_encode(csv_t *csv, int count, ...); * processes/nodes - e.g. the message header record can be rewritten AFTER * encoding all other records, with new information such as total length. */ -csv_record_t *csv_encode_record(csv_t *csv, csv_record_t *rec, - int count, ...); +csv_record_t *csv_encode_record(csv_t *csv, csv_record_t *rec, int count, ...); /** * Decode a CSV formatted string. The csv structure should have been @@ -149,7 +148,7 @@ int csv_is_record_valid(csv_t *csv, csv_record_t *in_rec); * rec1 and rec2 are removed */ csv_record_t *csv_concat_record(csv_t *csv, csv_record_t *rec1, - csv_record_t *rec2); + csv_record_t *rec2); /** * Remove a record from csv @@ -167,8 +166,7 @@ void csv_insert_record(csv_t *csv, csv_record_t *rec); * append fields to a record * Only works when csv has discrete record bufs */ -csv_record_t * -csv_append_record (csv_t *csv, csv_record_t *rec, int count, ...); +csv_record_t *csv_append_record(csv_t *csv, csv_record_t *rec, int count, ...); /** * Serialize contents of csv into string @@ -180,11 +178,11 @@ int csv_serialize(csv_t *csv, char *msgbuf, int msglen); * Clone a record. * Only works when csv has discrete record bufs */ -void csv_clone_record (csv_t *csv, csv_record_t *in_rec, csv_record_t **out_rec); +void csv_clone_record(csv_t *csv, csv_record_t *in_rec, csv_record_t **out_rec); /** * Return number of records */ -int csv_num_records (csv_t *csv); +int csv_num_records(csv_t *csv); #endif diff --git a/lib/distribute.c b/lib/distribute.c index 34ccfb4c7..25fcd9258 100644 --- a/lib/distribute.c +++ b/lib/distribute.c @@ -27,226 +27,216 @@ #include "distribute.h" #include "memory.h" -DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE, "Distribute list") +DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE, "Distribute list") DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE_IFNAME, "Dist-list ifname") -DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE_NAME, "Dist-list name") +DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE_NAME, "Dist-list name") /* Hash of distribute list. */ struct hash *disthash; /* Hook functions. */ -void (*distribute_add_hook) (struct distribute *); -void (*distribute_delete_hook) (struct distribute *); +void (*distribute_add_hook)(struct distribute *); +void (*distribute_delete_hook)(struct distribute *); -static struct distribute * -distribute_new (void) +static struct distribute *distribute_new(void) { - return XCALLOC (MTYPE_DISTRIBUTE, sizeof (struct distribute)); + return XCALLOC(MTYPE_DISTRIBUTE, sizeof(struct distribute)); } /* Free distribute object. */ -static void -distribute_free (struct distribute *dist) +static void distribute_free(struct distribute *dist) { - int i = 0; + int i = 0; - if (dist->ifname) - XFREE (MTYPE_DISTRIBUTE_IFNAME, dist->ifname); + if (dist->ifname) + XFREE(MTYPE_DISTRIBUTE_IFNAME, dist->ifname); - for (i = 0; i < DISTRIBUTE_MAX; i++) - if (dist->list[i]) - XFREE(MTYPE_DISTRIBUTE_NAME, dist->list[i]); + for (i = 0; i < DISTRIBUTE_MAX; i++) + if (dist->list[i]) + XFREE(MTYPE_DISTRIBUTE_NAME, dist->list[i]); - for (i = 0; i < DISTRIBUTE_MAX; i++) - if (dist->prefix[i]) - XFREE(MTYPE_DISTRIBUTE_NAME, dist->prefix[i]); + for (i = 0; i < DISTRIBUTE_MAX; i++) + if (dist->prefix[i]) + XFREE(MTYPE_DISTRIBUTE_NAME, dist->prefix[i]); - XFREE (MTYPE_DISTRIBUTE, dist); + XFREE(MTYPE_DISTRIBUTE, dist); } -static void -distribute_free_if_empty(struct distribute *dist) +static void distribute_free_if_empty(struct distribute *dist) { - int i; + int i; - for (i = 0; i < DISTRIBUTE_MAX; i++) - if (dist->list[i] != NULL || dist->prefix[i] != NULL) - return; + for (i = 0; i < DISTRIBUTE_MAX; i++) + if (dist->list[i] != NULL || dist->prefix[i] != NULL) + return; - hash_release (disthash, dist); - distribute_free (dist); + hash_release(disthash, dist); + distribute_free(dist); } /* Lookup interface's distribute list. */ -struct distribute * -distribute_lookup (const char *ifname) +struct distribute *distribute_lookup(const char *ifname) { - struct distribute key; - struct distribute *dist; + struct distribute key; + struct distribute *dist; - /* temporary reference */ - key.ifname = (ifname) ? XSTRDUP(MTYPE_DISTRIBUTE_IFNAME, ifname) : NULL; + /* temporary reference */ + key.ifname = (ifname) ? XSTRDUP(MTYPE_DISTRIBUTE_IFNAME, ifname) : NULL; - dist = hash_lookup (disthash, &key); + dist = hash_lookup(disthash, &key); - if (key.ifname) - XFREE(MTYPE_DISTRIBUTE_IFNAME, key.ifname); + if (key.ifname) + XFREE(MTYPE_DISTRIBUTE_IFNAME, key.ifname); - return dist; + return dist; } -void -distribute_list_add_hook (void (*func) (struct distribute *)) +void distribute_list_add_hook(void (*func)(struct distribute *)) { - distribute_add_hook = func; + distribute_add_hook = func; } -void -distribute_list_delete_hook (void (*func) (struct distribute *)) +void distribute_list_delete_hook(void (*func)(struct distribute *)) { - distribute_delete_hook = func; + distribute_delete_hook = func; } -static void * -distribute_hash_alloc (struct distribute *arg) +static void *distribute_hash_alloc(struct distribute *arg) { - struct distribute *dist; - - dist = distribute_new (); - if (arg->ifname) - dist->ifname = XSTRDUP (MTYPE_DISTRIBUTE_IFNAME, arg->ifname); - else - dist->ifname = NULL; - return dist; + struct distribute *dist; + + dist = distribute_new(); + if (arg->ifname) + dist->ifname = XSTRDUP(MTYPE_DISTRIBUTE_IFNAME, arg->ifname); + else + dist->ifname = NULL; + return dist; } /* Make new distribute list and push into hash. */ -static struct distribute * -distribute_get (const char *ifname) +static struct distribute *distribute_get(const char *ifname) { - struct distribute key; - struct distribute *ret; + struct distribute key; + struct distribute *ret; + + /* temporary reference */ + key.ifname = (ifname) ? XSTRDUP(MTYPE_DISTRIBUTE_IFNAME, ifname) : NULL; - /* temporary reference */ - key.ifname = (ifname) ? XSTRDUP(MTYPE_DISTRIBUTE_IFNAME, ifname) : NULL; - - ret = hash_get (disthash, &key, (void * (*) (void *))distribute_hash_alloc); + ret = hash_get(disthash, &key, + (void *(*)(void *))distribute_hash_alloc); - if (key.ifname) - XFREE(MTYPE_DISTRIBUTE_IFNAME, key.ifname); + if (key.ifname) + XFREE(MTYPE_DISTRIBUTE_IFNAME, key.ifname); - return ret; + return ret; } -static unsigned int -distribute_hash_make (void *arg) +static unsigned int distribute_hash_make(void *arg) { - const struct distribute *dist = arg; + const struct distribute *dist = arg; - return dist->ifname ? string_hash_make (dist->ifname) : 0; + return dist->ifname ? string_hash_make(dist->ifname) : 0; } /* If two distribute-list have same value then return 1 else return 0. This function is used by hash package. */ -static int -distribute_cmp (const struct distribute *dist1, const struct distribute *dist2) +static int distribute_cmp(const struct distribute *dist1, + const struct distribute *dist2) { - if (dist1->ifname && dist2->ifname) - if (strcmp (dist1->ifname, dist2->ifname) == 0) - return 1; - if (! dist1->ifname && ! dist2->ifname) - return 1; - return 0; + if (dist1->ifname && dist2->ifname) + if (strcmp(dist1->ifname, dist2->ifname) == 0) + return 1; + if (!dist1->ifname && !dist2->ifname) + return 1; + return 0; } /* Set access-list name to the distribute list. */ -static void -distribute_list_set (const char *ifname, enum distribute_type type, - const char *alist_name) +static void distribute_list_set(const char *ifname, enum distribute_type type, + const char *alist_name) { - struct distribute *dist; + struct distribute *dist; - dist = distribute_get (ifname); + dist = distribute_get(ifname); - if (dist->list[type]) - XFREE(MTYPE_DISTRIBUTE_NAME, dist->list[type]); - dist->list[type] = XSTRDUP(MTYPE_DISTRIBUTE_NAME, alist_name); + if (dist->list[type]) + XFREE(MTYPE_DISTRIBUTE_NAME, dist->list[type]); + dist->list[type] = XSTRDUP(MTYPE_DISTRIBUTE_NAME, alist_name); - /* Apply this distribute-list to the interface. */ - (*distribute_add_hook) (dist); + /* Apply this distribute-list to the interface. */ + (*distribute_add_hook)(dist); } /* Unset distribute-list. If matched distribute-list exist then return 1. */ -static int -distribute_list_unset (const char *ifname, enum distribute_type type, - const char *alist_name) +static int distribute_list_unset(const char *ifname, enum distribute_type type, + const char *alist_name) { - struct distribute *dist; + struct distribute *dist; - dist = distribute_lookup (ifname); - if (!dist) - return 0; + dist = distribute_lookup(ifname); + if (!dist) + return 0; - if (!dist->list[type]) - return 0; - if (strcmp (dist->list[type], alist_name) != 0) - return 0; + if (!dist->list[type]) + return 0; + if (strcmp(dist->list[type], alist_name) != 0) + return 0; - XFREE(MTYPE_DISTRIBUTE_NAME, dist->list[type]); - dist->list[type] = NULL; + XFREE(MTYPE_DISTRIBUTE_NAME, dist->list[type]); + dist->list[type] = NULL; - /* Apply this distribute-list to the interface. */ - (*distribute_delete_hook) (dist); + /* Apply this distribute-list to the interface. */ + (*distribute_delete_hook)(dist); - /* If all dist are NULL, then free distribute list. */ - distribute_free_if_empty(dist); - return 1; + /* If all dist are NULL, then free distribute list. */ + distribute_free_if_empty(dist); + return 1; } /* Set access-list name to the distribute list. */ -static void -distribute_list_prefix_set (const char *ifname, enum distribute_type type, - const char *plist_name) +static void distribute_list_prefix_set(const char *ifname, + enum distribute_type type, + const char *plist_name) { - struct distribute *dist; + struct distribute *dist; - dist = distribute_get (ifname); + dist = distribute_get(ifname); - if (dist->prefix[type]) - XFREE(MTYPE_DISTRIBUTE_NAME, dist->prefix[type]); - dist->prefix[type] = XSTRDUP(MTYPE_DISTRIBUTE_NAME, plist_name); + if (dist->prefix[type]) + XFREE(MTYPE_DISTRIBUTE_NAME, dist->prefix[type]); + dist->prefix[type] = XSTRDUP(MTYPE_DISTRIBUTE_NAME, plist_name); - /* Apply this distribute-list to the interface. */ - (*distribute_add_hook) (dist); + /* Apply this distribute-list to the interface. */ + (*distribute_add_hook)(dist); } /* Unset distribute-list. If matched distribute-list exist then return 1. */ -static int -distribute_list_prefix_unset (const char *ifname, enum distribute_type type, - const char *plist_name) +static int distribute_list_prefix_unset(const char *ifname, + enum distribute_type type, + const char *plist_name) { - struct distribute *dist; + struct distribute *dist; - dist = distribute_lookup (ifname); - if (!dist) - return 0; + dist = distribute_lookup(ifname); + if (!dist) + return 0; - if (!dist->prefix[type]) - return 0; - if (strcmp (dist->prefix[type], plist_name) != 0) - return 0; + if (!dist->prefix[type]) + return 0; + if (strcmp(dist->prefix[type], plist_name) != 0) + return 0; - XFREE(MTYPE_DISTRIBUTE_NAME, dist->prefix[type]); - dist->prefix[type] = NULL; + XFREE(MTYPE_DISTRIBUTE_NAME, dist->prefix[type]); + dist->prefix[type] = NULL; - /* Apply this distribute-list to the interface. */ - (*distribute_delete_hook) (dist); + /* Apply this distribute-list to the interface. */ + (*distribute_delete_hook)(dist); - /* If all dist are NULL, then free distribute list. */ - distribute_free_if_empty(dist); - return 1; + /* If all dist are NULL, then free distribute list. */ + distribute_free_if_empty(dist); + return 1; } DEFUN (distribute_list, @@ -259,25 +249,26 @@ DEFUN (distribute_list, "Filter outgoing routing updates\n" "Interface name\n") { - int prefix = (argv[1]->type == WORD_TKN) ? 1 : 0; + int prefix = (argv[1]->type == WORD_TKN) ? 1 : 0; + + /* Check of distribute list type. */ + enum distribute_type type = argv[2 + prefix]->arg[0] == 'i' + ? DISTRIBUTE_V4_IN + : DISTRIBUTE_V4_OUT; - /* Check of distribute list type. */ - enum distribute_type type = argv[2 + prefix]->arg[0] == 'i' ? - DISTRIBUTE_V4_IN : DISTRIBUTE_V4_OUT; + /* Set appropriate function call */ + void (*distfn)(const char *, enum distribute_type, const char *) = + prefix ? &distribute_list_prefix_set : &distribute_list_set; - /* Set appropriate function call */ - void (*distfn)(const char *, enum distribute_type, const char *) = prefix ? - &distribute_list_prefix_set : &distribute_list_set; - - /* if interface is present, get name */ - const char *ifname = NULL; - if (argv[argc - 1]->type == VARIABLE_TKN) - ifname = argv[argc - 1]->arg; + /* if interface is present, get name */ + const char *ifname = NULL; + if (argv[argc - 1]->type == VARIABLE_TKN) + ifname = argv[argc - 1]->arg; - /* Get interface name corresponding distribute list. */ - distfn (ifname, type, argv[1 + prefix]->arg); + /* Get interface name corresponding distribute list. */ + distfn(ifname, type, argv[1 + prefix]->arg); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_distribute_list, @@ -291,27 +282,28 @@ DEFUN (ipv6_distribute_list, "Filter outgoing routing updates\n" "Interface name\n") { - int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0; + int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0; - /* Check of distribute list type. */ - enum distribute_type type = argv[3 + prefix]->arg[0] == 'i' ? - DISTRIBUTE_V6_IN : DISTRIBUTE_V6_OUT; + /* Check of distribute list type. */ + enum distribute_type type = argv[3 + prefix]->arg[0] == 'i' + ? DISTRIBUTE_V6_IN + : DISTRIBUTE_V6_OUT; - /* Set appropriate function call */ - void (*distfn)(const char *, enum distribute_type, const char *) = prefix ? - &distribute_list_prefix_set : &distribute_list_set; - - /* if interface is present, get name */ - const char *ifname = NULL; - if (argv[argc - 1]->type == VARIABLE_TKN) - ifname = argv[argc - 1]->arg; + /* Set appropriate function call */ + void (*distfn)(const char *, enum distribute_type, const char *) = + prefix ? &distribute_list_prefix_set : &distribute_list_set; - /* Get interface name corresponding distribute list. */ - distfn (ifname, type, argv[1 + prefix]->arg); + /* if interface is present, get name */ + const char *ifname = NULL; + if (argv[argc - 1]->type == VARIABLE_TKN) + ifname = argv[argc - 1]->arg; - return CMD_SUCCESS; + /* Get interface name corresponding distribute list. */ + distfn(ifname, type, argv[1 + prefix]->arg); + + return CMD_SUCCESS; } - + DEFUN (no_distribute_list, no_distribute_list_cmd, "no [ipv6] distribute-list [prefix] WORD [WORD]", @@ -324,230 +316,237 @@ DEFUN (no_distribute_list, "Filter outgoing routing updates\n" "Interface name\n") { - int ipv6 = strmatch(argv[1]->text, "ipv6"); - int prefix = (argv[2 + ipv6]->type == WORD_TKN) ? 1 : 0; - - int idx_alname = 2 + ipv6 + prefix; - int idx_disttype = idx_alname + 1; - - /* Check of distribute list type. */ - enum distribute_type distin = (ipv6) ? DISTRIBUTE_V6_IN : DISTRIBUTE_V4_IN; - enum distribute_type distout = (ipv6) ? DISTRIBUTE_V6_OUT : DISTRIBUTE_V4_OUT; - - enum distribute_type type = argv[idx_disttype]->arg[0] == 'i' ? distin : distout; - - /* Set appropriate function call */ - int (*distfn)(const char *, enum distribute_type, const char *) = prefix ? - &distribute_list_prefix_unset : &distribute_list_unset; - - /* if interface is present, get name */ - const char *ifname = NULL; - if (argv[argc - 1]->type == VARIABLE_TKN) - ifname = argv[argc - 1]->arg; - /* Get interface name corresponding distribute list. */ - int ret = distfn (ifname, type, argv[2 + prefix]->arg); - - if (! ret) - { - vty_out (vty, "distribute list doesn't exist\n"); - return CMD_WARNING_CONFIG_FAILED; - } - return CMD_SUCCESS; + int ipv6 = strmatch(argv[1]->text, "ipv6"); + int prefix = (argv[2 + ipv6]->type == WORD_TKN) ? 1 : 0; + + int idx_alname = 2 + ipv6 + prefix; + int idx_disttype = idx_alname + 1; + + /* Check of distribute list type. */ + enum distribute_type distin = + (ipv6) ? DISTRIBUTE_V6_IN : DISTRIBUTE_V4_IN; + enum distribute_type distout = + (ipv6) ? DISTRIBUTE_V6_OUT : DISTRIBUTE_V4_OUT; + + enum distribute_type type = + argv[idx_disttype]->arg[0] == 'i' ? distin : distout; + + /* Set appropriate function call */ + int (*distfn)(const char *, enum distribute_type, const char *) = + prefix ? &distribute_list_prefix_unset : &distribute_list_unset; + + /* if interface is present, get name */ + const char *ifname = NULL; + if (argv[argc - 1]->type == VARIABLE_TKN) + ifname = argv[argc - 1]->arg; + /* Get interface name corresponding distribute list. */ + int ret = distfn(ifname, type, argv[2 + prefix]->arg); + + if (!ret) { + vty_out(vty, "distribute list doesn't exist\n"); + return CMD_WARNING_CONFIG_FAILED; + } + return CMD_SUCCESS; } -static int -distribute_print (struct vty *vty, char *tab[], int is_prefix, - enum distribute_type type, int has_print) +static int distribute_print(struct vty *vty, char *tab[], int is_prefix, + enum distribute_type type, int has_print) { - if (tab[type]) { - vty_out (vty, "%s %s%s", - has_print ? "," : "", - is_prefix ? "(prefix-list) " : "", - tab[type]); - return 1; - } - return has_print; + if (tab[type]) { + vty_out(vty, "%s %s%s", has_print ? "," : "", + is_prefix ? "(prefix-list) " : "", tab[type]); + return 1; + } + return has_print; } -int -config_show_distribute (struct vty *vty) +int config_show_distribute(struct vty *vty) { - unsigned int i; - int has_print = 0; - struct hash_backet *mp; - struct distribute *dist; - - /* Output filter configuration. */ - dist = distribute_lookup (NULL); - vty_out (vty, " Outgoing update filter list for all interface is"); - has_print = 0; - if (dist) - { - has_print = distribute_print(vty, dist->list, 0, - DISTRIBUTE_V4_OUT, has_print); - has_print = distribute_print(vty, dist->prefix, 1, - DISTRIBUTE_V4_OUT, has_print); - has_print = distribute_print(vty, dist->list, 0, - DISTRIBUTE_V6_OUT, has_print); - has_print = distribute_print(vty, dist->prefix, 1, - DISTRIBUTE_V6_OUT, has_print); - } - if (has_print) - vty_out (vty, "\n"); - else - vty_out (vty, " not set\n"); - - for (i = 0; i < disthash->size; i++) - for (mp = disthash->index[i]; mp; mp = mp->next) - { - dist = mp->data; - if (dist->ifname) - { - vty_out (vty, " %s filtered by", dist->ifname); - has_print = 0; - has_print = distribute_print(vty, dist->list, 0, - DISTRIBUTE_V4_OUT, has_print); - has_print = distribute_print(vty, dist->prefix, 1, - DISTRIBUTE_V4_OUT, has_print); - has_print = distribute_print(vty, dist->list, 0, - DISTRIBUTE_V6_OUT, has_print); - has_print = distribute_print(vty, dist->prefix, 1, - DISTRIBUTE_V6_OUT, has_print); - if (has_print) - vty_out (vty, "\n"); - else - vty_out (vty, " nothing\n"); - } - } - - - /* Input filter configuration. */ - dist = distribute_lookup (NULL); - vty_out (vty, " Incoming update filter list for all interface is"); - has_print = 0; - if (dist) - { - has_print = distribute_print(vty, dist->list, 0, - DISTRIBUTE_V4_IN, has_print); - has_print = distribute_print(vty, dist->prefix, 1, - DISTRIBUTE_V4_IN, has_print); - has_print = distribute_print(vty, dist->list, 0, - DISTRIBUTE_V6_IN, has_print); - has_print = distribute_print(vty, dist->prefix, 1, - DISTRIBUTE_V6_IN, has_print); - } - if (has_print) - vty_out (vty, "\n"); - else - vty_out (vty, " not set\n"); - - for (i = 0; i < disthash->size; i++) - for (mp = disthash->index[i]; mp; mp = mp->next) - { - dist = mp->data; - if (dist->ifname) - { - vty_out (vty, " %s filtered by", dist->ifname); - has_print = 0; - has_print = distribute_print(vty, dist->list, 0, - DISTRIBUTE_V4_IN, has_print); - has_print = distribute_print(vty, dist->prefix, 1, - DISTRIBUTE_V4_IN, has_print); - has_print = distribute_print(vty, dist->list, 0, - DISTRIBUTE_V6_IN, has_print); - has_print = distribute_print(vty, dist->prefix, 1, - DISTRIBUTE_V6_IN, has_print); - if (has_print) - vty_out (vty, "\n"); - else - vty_out (vty, " nothing\n"); - } - } - return 0; + unsigned int i; + int has_print = 0; + struct hash_backet *mp; + struct distribute *dist; + + /* Output filter configuration. */ + dist = distribute_lookup(NULL); + vty_out(vty, " Outgoing update filter list for all interface is"); + has_print = 0; + if (dist) { + has_print = distribute_print(vty, dist->list, 0, + DISTRIBUTE_V4_OUT, has_print); + has_print = distribute_print(vty, dist->prefix, 1, + DISTRIBUTE_V4_OUT, has_print); + has_print = distribute_print(vty, dist->list, 0, + DISTRIBUTE_V6_OUT, has_print); + has_print = distribute_print(vty, dist->prefix, 1, + DISTRIBUTE_V6_OUT, has_print); + } + if (has_print) + vty_out(vty, "\n"); + else + vty_out(vty, " not set\n"); + + for (i = 0; i < disthash->size; i++) + for (mp = disthash->index[i]; mp; mp = mp->next) { + dist = mp->data; + if (dist->ifname) { + vty_out(vty, " %s filtered by", + dist->ifname); + has_print = 0; + has_print = distribute_print(vty, dist->list, 0, + DISTRIBUTE_V4_OUT, + has_print); + has_print = distribute_print( + vty, dist->prefix, 1, DISTRIBUTE_V4_OUT, + has_print); + has_print = distribute_print(vty, dist->list, 0, + DISTRIBUTE_V6_OUT, + has_print); + has_print = distribute_print( + vty, dist->prefix, 1, DISTRIBUTE_V6_OUT, + has_print); + if (has_print) + vty_out(vty, "\n"); + else + vty_out(vty, " nothing\n"); + } + } + + + /* Input filter configuration. */ + dist = distribute_lookup(NULL); + vty_out(vty, " Incoming update filter list for all interface is"); + has_print = 0; + if (dist) { + has_print = distribute_print(vty, dist->list, 0, + DISTRIBUTE_V4_IN, has_print); + has_print = distribute_print(vty, dist->prefix, 1, + DISTRIBUTE_V4_IN, has_print); + has_print = distribute_print(vty, dist->list, 0, + DISTRIBUTE_V6_IN, has_print); + has_print = distribute_print(vty, dist->prefix, 1, + DISTRIBUTE_V6_IN, has_print); + } + if (has_print) + vty_out(vty, "\n"); + else + vty_out(vty, " not set\n"); + + for (i = 0; i < disthash->size; i++) + for (mp = disthash->index[i]; mp; mp = mp->next) { + dist = mp->data; + if (dist->ifname) { + vty_out(vty, " %s filtered by", + dist->ifname); + has_print = 0; + has_print = distribute_print(vty, dist->list, 0, + DISTRIBUTE_V4_IN, + has_print); + has_print = distribute_print( + vty, dist->prefix, 1, DISTRIBUTE_V4_IN, + has_print); + has_print = distribute_print(vty, dist->list, 0, + DISTRIBUTE_V6_IN, + has_print); + has_print = distribute_print( + vty, dist->prefix, 1, DISTRIBUTE_V6_IN, + has_print); + if (has_print) + vty_out(vty, "\n"); + else + vty_out(vty, " nothing\n"); + } + } + return 0; } /* Configuration write function. */ -int -config_write_distribute (struct vty *vty) +int config_write_distribute(struct vty *vty) { - unsigned int i; - int j; - int output, v6; - struct hash_backet *mp; - int write = 0; - - for (i = 0; i < disthash->size; i++) - for (mp = disthash->index[i]; mp; mp = mp->next) - { - struct distribute *dist; - - dist = mp->data; - - for (j = 0; j < DISTRIBUTE_MAX; j++) - if (dist->list[j]) { - output = j == DISTRIBUTE_V4_OUT || j == DISTRIBUTE_V6_OUT; - v6 = j == DISTRIBUTE_V6_IN || j == DISTRIBUTE_V6_OUT; - vty_out (vty, " %sdistribute-list %s %s %s\n", - v6 ? "ipv6 " : "", - dist->list[j], - output ? "out" : "in", - dist->ifname ? dist->ifname : ""); - write++; - } - - for (j = 0; j < DISTRIBUTE_MAX; j++) - if (dist->prefix[j]) { - output = j == DISTRIBUTE_V4_OUT || j == DISTRIBUTE_V6_OUT; - v6 = j == DISTRIBUTE_V6_IN || j == DISTRIBUTE_V6_OUT; - vty_out (vty, " %sdistribute-list prefix %s %s %s\n", - v6 ? "ipv6 " : "", - dist->prefix[j], - output ? "out" : "in", - dist->ifname ? dist->ifname : ""); - write++; - } - } - return write; + unsigned int i; + int j; + int output, v6; + struct hash_backet *mp; + int write = 0; + + for (i = 0; i < disthash->size; i++) + for (mp = disthash->index[i]; mp; mp = mp->next) { + struct distribute *dist; + + dist = mp->data; + + for (j = 0; j < DISTRIBUTE_MAX; j++) + if (dist->list[j]) { + output = j == DISTRIBUTE_V4_OUT + || j == DISTRIBUTE_V6_OUT; + v6 = j == DISTRIBUTE_V6_IN + || j == DISTRIBUTE_V6_OUT; + vty_out(vty, + " %sdistribute-list %s %s %s\n", + v6 ? "ipv6 " : "", + dist->list[j], + output ? "out" : "in", + dist->ifname ? dist->ifname + : ""); + write++; + } + + for (j = 0; j < DISTRIBUTE_MAX; j++) + if (dist->prefix[j]) { + output = j == DISTRIBUTE_V4_OUT + || j == DISTRIBUTE_V6_OUT; + v6 = j == DISTRIBUTE_V6_IN + || j == DISTRIBUTE_V6_OUT; + vty_out(vty, + " %sdistribute-list prefix %s %s %s\n", + v6 ? "ipv6 " : "", + dist->prefix[j], + output ? "out" : "in", + dist->ifname ? dist->ifname + : ""); + write++; + } + } + return write; } /* Clear all distribute list. */ -void -distribute_list_reset () +void distribute_list_reset() { - hash_clean (disthash, (void (*) (void *)) distribute_free); + hash_clean(disthash, (void (*)(void *))distribute_free); } /* Initialize distribute list related hash. */ -void -distribute_list_init (int node) +void distribute_list_init(int node) { - disthash = hash_create (distribute_hash_make, - (int (*) (const void *, const void *)) - distribute_cmp, NULL); - - /* vtysh command-extraction doesn't grok install_element(node, ) */ - if (node == RIP_NODE) { - install_element (RIP_NODE, &distribute_list_cmd); - install_element (RIP_NODE, &no_distribute_list_cmd); - } else if (node == RIPNG_NODE) { - install_element (RIPNG_NODE, &distribute_list_cmd); - install_element (RIPNG_NODE, &no_distribute_list_cmd); - } - - /* install v6 */ - if (node == RIPNG_NODE) { - install_element (RIPNG_NODE, &ipv6_distribute_list_cmd); - } - - /* TODO: install v4 syntax command for v6 only protocols. */ - /* if (node == RIPNG_NODE) { - * install_element (node, &ipv6_as_v4_distribute_list_all_cmd); - * install_element (node, &no_ipv6_as_v4_distribute_list_all_cmd); - * install_element (node, &ipv6_as_v4_distribute_list_cmd); - * install_element (node, &no_ipv6_as_v4_distribute_list_cmd); - * install_element (node, &ipv6_as_v4_distribute_list_prefix_all_cmd); - * install_element (node, &no_ipv6_as_v4_distribute_list_prefix_all_cmd); - * install_element (node, &ipv6_as_v4_distribute_list_prefix_cmd); - * install_element (node, &no_ipv6_as_v4_distribute_list_prefix_cmd); - }*/ + disthash = hash_create( + distribute_hash_make, + (int (*)(const void *, const void *))distribute_cmp, NULL); + + /* vtysh command-extraction doesn't grok install_element(node, ) */ + if (node == RIP_NODE) { + install_element(RIP_NODE, &distribute_list_cmd); + install_element(RIP_NODE, &no_distribute_list_cmd); + } else if (node == RIPNG_NODE) { + install_element(RIPNG_NODE, &distribute_list_cmd); + install_element(RIPNG_NODE, &no_distribute_list_cmd); + } + + /* install v6 */ + if (node == RIPNG_NODE) { + install_element(RIPNG_NODE, &ipv6_distribute_list_cmd); + } + + /* TODO: install v4 syntax command for v6 only protocols. */ + /* if (node == RIPNG_NODE) { + * install_element (node, &ipv6_as_v4_distribute_list_all_cmd); + * install_element (node, &no_ipv6_as_v4_distribute_list_all_cmd); + * install_element (node, &ipv6_as_v4_distribute_list_cmd); + * install_element (node, &no_ipv6_as_v4_distribute_list_cmd); + * install_element (node, &ipv6_as_v4_distribute_list_prefix_all_cmd); + * install_element (node, + &no_ipv6_as_v4_distribute_list_prefix_all_cmd); + * install_element (node, &ipv6_as_v4_distribute_list_prefix_cmd); + * install_element (node, &no_ipv6_as_v4_distribute_list_prefix_cmd); + }*/ } diff --git a/lib/distribute.h b/lib/distribute.h index 23d7cac57..35c5e0d6b 100644 --- a/lib/distribute.h +++ b/lib/distribute.h @@ -26,37 +26,37 @@ #include "filter.h" /* Disctirubte list types. */ -enum distribute_type -{ - DISTRIBUTE_V4_IN, - DISTRIBUTE_V6_IN, - DISTRIBUTE_V4_OUT, - DISTRIBUTE_V6_OUT, - DISTRIBUTE_MAX +enum distribute_type { + DISTRIBUTE_V4_IN, + DISTRIBUTE_V6_IN, + DISTRIBUTE_V4_OUT, + DISTRIBUTE_V6_OUT, + DISTRIBUTE_MAX }; -struct distribute -{ - /* Name of the interface. */ - char *ifname; +struct distribute { + /* Name of the interface. */ + char *ifname; - /* Filter name of `in' and `out' */ - char *list[DISTRIBUTE_MAX]; + /* Filter name of `in' and `out' */ + char *list[DISTRIBUTE_MAX]; - /* prefix-list name of `in' and `out' */ - char *prefix[DISTRIBUTE_MAX]; + /* prefix-list name of `in' and `out' */ + char *prefix[DISTRIBUTE_MAX]; }; /* Prototypes for distribute-list. */ -extern void distribute_list_init (int); -extern void distribute_list_reset (void); -extern void distribute_list_add_hook (void (*) (struct distribute *)); -extern void distribute_list_delete_hook (void (*) (struct distribute *)); -extern struct distribute *distribute_lookup (const char *); -extern int config_write_distribute (struct vty *); -extern int config_show_distribute (struct vty *); - -extern enum filter_type distribute_apply_in (struct interface *, struct prefix *); -extern enum filter_type distribute_apply_out (struct interface *, struct prefix *); +extern void distribute_list_init(int); +extern void distribute_list_reset(void); +extern void distribute_list_add_hook(void (*)(struct distribute *)); +extern void distribute_list_delete_hook(void (*)(struct distribute *)); +extern struct distribute *distribute_lookup(const char *); +extern int config_write_distribute(struct vty *); +extern int config_show_distribute(struct vty *); + +extern enum filter_type distribute_apply_in(struct interface *, + struct prefix *); +extern enum filter_type distribute_apply_out(struct interface *, + struct prefix *); #endif /* _ZEBRA_DISTRIBUTE_H */ diff --git a/lib/event_counter.c b/lib/event_counter.c index 0acd0a1f7..c520937a3 100644 --- a/lib/event_counter.c +++ b/lib/event_counter.c @@ -44,29 +44,28 @@ #include "event_counter.h" -void -event_counter_inc (struct event_counter *counter) +void event_counter_inc(struct event_counter *counter) { - counter->count++; - counter->last = time (NULL); + counter->count++; + counter->last = time(NULL); } -const char * -event_counter_format (const struct event_counter *counter) +const char *event_counter_format(const struct event_counter *counter) { - struct tm last_change_store; - struct tm *last_change; - char timebuf[sizeof ("Thu, 01 Jan 1970 00:00:00 +0000")]; - static char rv[20 + sizeof (" last: ") + sizeof (timebuf)]; + struct tm last_change_store; + struct tm *last_change; + char timebuf[sizeof("Thu, 01 Jan 1970 00:00:00 +0000")]; + static char rv[20 + sizeof(" last: ") + sizeof(timebuf)]; - last_change = localtime_r (&counter->last, &last_change_store); - if (!last_change || strftime (timebuf, sizeof (timebuf), - "%a, %d %b %Y %T %z", last_change) == 0) - { - strncpy (timebuf, "???", sizeof (timebuf)); - } + last_change = localtime_r(&counter->last, &last_change_store); + if (!last_change + || strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %T %z", + last_change) + == 0) { + strncpy(timebuf, "???", sizeof(timebuf)); + } - snprintf (rv, sizeof (rv), "%5llu last: %s", counter->count, - counter->last ? timebuf : "(never)"); - return rv; + snprintf(rv, sizeof(rv), "%5llu last: %s", counter->count, + counter->last ? timebuf : "(never)"); + return rv; } diff --git a/lib/event_counter.h b/lib/event_counter.h index 8c11e1028..de5dbc066 100644 --- a/lib/event_counter.h +++ b/lib/event_counter.h @@ -43,13 +43,12 @@ #ifndef _ZEBRA_EVENT_COUNTER_H #define _ZEBRA_EVENT_COUNTER_H -struct event_counter -{ - unsigned long long count; - time_t last; +struct event_counter { + unsigned long long count; + time_t last; }; -void event_counter_inc (struct event_counter *counter); -const char *event_counter_format (const struct event_counter *counter); +void event_counter_inc(struct event_counter *counter); +const char *event_counter_format(const struct event_counter *counter); #endif diff --git a/lib/fifo.h b/lib/fifo.h index 631556e78..f59e4dc6c 100644 --- a/lib/fifo.h +++ b/lib/fifo.h @@ -21,42 +21,38 @@ #define __LIB_FIFO_H__ /* FIFO -- first in first out structure and macros. */ -struct fifo -{ - struct fifo *next; - struct fifo *prev; +struct fifo { + struct fifo *next; + struct fifo *prev; }; -#define FIFO_INIT(F) \ - do { \ - struct fifo *Xfifo = (struct fifo *)(F); \ - Xfifo->next = Xfifo->prev = Xfifo; \ - } while (0) - -#define FIFO_ADD(F,N) \ - do { \ - struct fifo *Xfifo = (struct fifo *)(F); \ - struct fifo *Xnode = (struct fifo *)(N); \ - Xnode->next = Xfifo; \ - Xnode->prev = Xfifo->prev; \ - Xfifo->prev = Xfifo->prev->next = Xnode; \ - } while (0) - -#define FIFO_DEL(N) \ - do { \ - struct fifo *Xnode = (struct fifo *)(N); \ - Xnode->prev->next = Xnode->next; \ - Xnode->next->prev = Xnode->prev; \ - } while (0) - -#define FIFO_HEAD(F) \ - ((((struct fifo *)(F))->next == (struct fifo *)(F)) \ - ? NULL : (F)->next) - -#define FIFO_EMPTY(F) \ - (((struct fifo *)(F))->next == (struct fifo *)(F)) - -#define FIFO_TOP(F) \ - (FIFO_EMPTY(F) ? NULL : ((struct fifo *)(F))->next) +#define FIFO_INIT(F) \ + do { \ + struct fifo *Xfifo = (struct fifo *)(F); \ + Xfifo->next = Xfifo->prev = Xfifo; \ + } while (0) + +#define FIFO_ADD(F, N) \ + do { \ + struct fifo *Xfifo = (struct fifo *)(F); \ + struct fifo *Xnode = (struct fifo *)(N); \ + Xnode->next = Xfifo; \ + Xnode->prev = Xfifo->prev; \ + Xfifo->prev = Xfifo->prev->next = Xnode; \ + } while (0) + +#define FIFO_DEL(N) \ + do { \ + struct fifo *Xnode = (struct fifo *)(N); \ + Xnode->prev->next = Xnode->next; \ + Xnode->next->prev = Xnode->prev; \ + } while (0) + +#define FIFO_HEAD(F) \ + ((((struct fifo *)(F))->next == (struct fifo *)(F)) ? NULL : (F)->next) + +#define FIFO_EMPTY(F) (((struct fifo *)(F))->next == (struct fifo *)(F)) + +#define FIFO_TOP(F) (FIFO_EMPTY(F) ? NULL : ((struct fifo *)(F))->next) #endif /* __LIB_FIFO_H__ */ diff --git a/lib/filter.c b/lib/filter.c index c1e922f5b..0262234c7 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -30,475 +30,432 @@ #include "routemap.h" #include "libfrr.h" -DEFINE_MTYPE_STATIC(LIB, ACCESS_LIST, "Access List") +DEFINE_MTYPE_STATIC(LIB, ACCESS_LIST, "Access List") DEFINE_MTYPE_STATIC(LIB, ACCESS_LIST_STR, "Access List Str") -DEFINE_MTYPE_STATIC(LIB, ACCESS_FILTER, "Access Filter") - -struct filter_cisco -{ - /* Cisco access-list */ - int extended; - struct in_addr addr; - struct in_addr addr_mask; - struct in_addr mask; - struct in_addr mask_mask; +DEFINE_MTYPE_STATIC(LIB, ACCESS_FILTER, "Access Filter") + +struct filter_cisco { + /* Cisco access-list */ + int extended; + struct in_addr addr; + struct in_addr addr_mask; + struct in_addr mask; + struct in_addr mask_mask; }; -struct filter_zebra -{ - /* If this filter is "exact" match then this flag is set. */ - int exact; +struct filter_zebra { + /* If this filter is "exact" match then this flag is set. */ + int exact; - /* Prefix information. */ - struct prefix prefix; + /* Prefix information. */ + struct prefix prefix; }; /* Filter element of access list */ -struct filter -{ - /* For doubly linked list. */ - struct filter *next; - struct filter *prev; +struct filter { + /* For doubly linked list. */ + struct filter *next; + struct filter *prev; - /* Filter type information. */ - enum filter_type type; + /* Filter type information. */ + enum filter_type type; - /* Cisco access-list */ - int cisco; + /* Cisco access-list */ + int cisco; - union - { - struct filter_cisco cfilter; - struct filter_zebra zfilter; - } u; + union { + struct filter_cisco cfilter; + struct filter_zebra zfilter; + } u; }; /* List of access_list. */ -struct access_list_list -{ - struct access_list *head; - struct access_list *tail; +struct access_list_list { + struct access_list *head; + struct access_list *tail; }; /* Master structure of access_list. */ -struct access_master -{ - /* List of access_list which name is number. */ - struct access_list_list num; +struct access_master { + /* List of access_list which name is number. */ + struct access_list_list num; - /* List of access_list which name is string. */ - struct access_list_list str; + /* List of access_list which name is string. */ + struct access_list_list str; - /* Hook function which is executed when new access_list is added. */ - void (*add_hook) (struct access_list *); + /* Hook function which is executed when new access_list is added. */ + void (*add_hook)(struct access_list *); - /* Hook function which is executed when access_list is deleted. */ - void (*delete_hook) (struct access_list *); + /* Hook function which is executed when access_list is deleted. */ + void (*delete_hook)(struct access_list *); }; /* Static structure for IPv4 access_list's master. */ -static struct access_master access_master_ipv4 = -{ - {NULL, NULL}, - {NULL, NULL}, - NULL, - NULL, +static struct access_master access_master_ipv4 = { + {NULL, NULL}, + {NULL, NULL}, + NULL, + NULL, }; /* Static structure for IPv6 access_list's master. */ -static struct access_master access_master_ipv6 = -{ - {NULL, NULL}, - {NULL, NULL}, - NULL, - NULL, +static struct access_master access_master_ipv6 = { + {NULL, NULL}, + {NULL, NULL}, + NULL, + NULL, }; -static struct access_master * -access_master_get (afi_t afi) +static struct access_master *access_master_get(afi_t afi) { - if (afi == AFI_IP) - return &access_master_ipv4; - else if (afi == AFI_IP6) - return &access_master_ipv6; - return NULL; + if (afi == AFI_IP) + return &access_master_ipv4; + else if (afi == AFI_IP6) + return &access_master_ipv6; + return NULL; } /* Allocate new filter structure. */ -static struct filter * -filter_new (void) +static struct filter *filter_new(void) { - return (struct filter *) XCALLOC (MTYPE_ACCESS_FILTER, - sizeof (struct filter)); + return (struct filter *)XCALLOC(MTYPE_ACCESS_FILTER, + sizeof(struct filter)); } -static void -filter_free (struct filter *filter) +static void filter_free(struct filter *filter) { - XFREE (MTYPE_ACCESS_FILTER, filter); + XFREE(MTYPE_ACCESS_FILTER, filter); } /* Return string of filter_type. */ -static const char * -filter_type_str (struct filter *filter) -{ - switch (filter->type) - { - case FILTER_PERMIT: - return "permit"; - break; - case FILTER_DENY: - return "deny"; - break; - case FILTER_DYNAMIC: - return "dynamic"; - break; - default: - return ""; - break; - } +static const char *filter_type_str(struct filter *filter) +{ + switch (filter->type) { + case FILTER_PERMIT: + return "permit"; + break; + case FILTER_DENY: + return "deny"; + break; + case FILTER_DYNAMIC: + return "dynamic"; + break; + default: + return ""; + break; + } } /* If filter match to the prefix then return 1. */ -static int -filter_match_cisco (struct filter *mfilter, struct prefix *p) +static int filter_match_cisco(struct filter *mfilter, struct prefix *p) { - struct filter_cisco *filter; - struct in_addr mask; - u_int32_t check_addr; - u_int32_t check_mask; + struct filter_cisco *filter; + struct in_addr mask; + u_int32_t check_addr; + u_int32_t check_mask; - filter = &mfilter->u.cfilter; - check_addr = p->u.prefix4.s_addr & ~filter->addr_mask.s_addr; + filter = &mfilter->u.cfilter; + check_addr = p->u.prefix4.s_addr & ~filter->addr_mask.s_addr; - if (filter->extended) - { - masklen2ip (p->prefixlen, &mask); - check_mask = mask.s_addr & ~filter->mask_mask.s_addr; + if (filter->extended) { + masklen2ip(p->prefixlen, &mask); + check_mask = mask.s_addr & ~filter->mask_mask.s_addr; - if (memcmp (&check_addr, &filter->addr.s_addr, 4) == 0 - && memcmp (&check_mask, &filter->mask.s_addr, 4) == 0) - return 1; - } - else if (memcmp (&check_addr, &filter->addr.s_addr, 4) == 0) - return 1; + if (memcmp(&check_addr, &filter->addr.s_addr, 4) == 0 + && memcmp(&check_mask, &filter->mask.s_addr, 4) == 0) + return 1; + } else if (memcmp(&check_addr, &filter->addr.s_addr, 4) == 0) + return 1; - return 0; + return 0; } /* If filter match to the prefix then return 1. */ -static int -filter_match_zebra (struct filter *mfilter, struct prefix *p) +static int filter_match_zebra(struct filter *mfilter, struct prefix *p) { - struct filter_zebra *filter; + struct filter_zebra *filter; - filter = &mfilter->u.zfilter; + filter = &mfilter->u.zfilter; - if (filter->prefix.family == p->family) - { - if (filter->exact) - { - if (filter->prefix.prefixlen == p->prefixlen) - return prefix_match (&filter->prefix, p); - else - return 0; - } - else - return prefix_match (&filter->prefix, p); - } - else - return 0; + if (filter->prefix.family == p->family) { + if (filter->exact) { + if (filter->prefix.prefixlen == p->prefixlen) + return prefix_match(&filter->prefix, p); + else + return 0; + } else + return prefix_match(&filter->prefix, p); + } else + return 0; } /* Allocate new access list structure. */ -static struct access_list * -access_list_new (void) +static struct access_list *access_list_new(void) { - return (struct access_list *) XCALLOC (MTYPE_ACCESS_LIST, - sizeof (struct access_list)); + return (struct access_list *)XCALLOC(MTYPE_ACCESS_LIST, + sizeof(struct access_list)); } /* Free allocated access_list. */ -static void -access_list_free (struct access_list *access) +static void access_list_free(struct access_list *access) { - XFREE (MTYPE_ACCESS_LIST, access); + XFREE(MTYPE_ACCESS_LIST, access); } /* Delete access_list from access_master and free it. */ -static void -access_list_delete (struct access_list *access) +static void access_list_delete(struct access_list *access) { - struct filter *filter; - struct filter *next; - struct access_list_list *list; - struct access_master *master; + struct filter *filter; + struct filter *next; + struct access_list_list *list; + struct access_master *master; - for (filter = access->head; filter; filter = next) - { - next = filter->next; - filter_free (filter); - } + for (filter = access->head; filter; filter = next) { + next = filter->next; + filter_free(filter); + } - master = access->master; + master = access->master; - if (access->type == ACCESS_TYPE_NUMBER) - list = &master->num; - else - list = &master->str; + if (access->type == ACCESS_TYPE_NUMBER) + list = &master->num; + else + list = &master->str; - if (access->next) - access->next->prev = access->prev; - else - list->tail = access->prev; + if (access->next) + access->next->prev = access->prev; + else + list->tail = access->prev; - if (access->prev) - access->prev->next = access->next; - else - list->head = access->next; + if (access->prev) + access->prev->next = access->next; + else + list->head = access->next; - if (access->name) - XFREE (MTYPE_ACCESS_LIST_STR, access->name); + if (access->name) + XFREE(MTYPE_ACCESS_LIST_STR, access->name); - if (access->remark) - XFREE (MTYPE_TMP, access->remark); + if (access->remark) + XFREE(MTYPE_TMP, access->remark); - access_list_free (access); + access_list_free(access); } /* Insert new access list to list of access_list. Each acceess_list is sorted by the name. */ -static struct access_list * -access_list_insert (afi_t afi, const char *name) -{ - unsigned int i; - long number; - struct access_list *access; - struct access_list *point; - struct access_list_list *alist; - struct access_master *master; - - master = access_master_get (afi); - if (master == NULL) - return NULL; - - /* Allocate new access_list and copy given name. */ - access = access_list_new (); - access->name = XSTRDUP (MTYPE_ACCESS_LIST_STR, name); - access->master = master; - - /* If name is made by all digit character. We treat it as - number. */ - for (number = 0, i = 0; i < strlen (name); i++) - { - if (isdigit ((int) name[i])) - number = (number * 10) + (name[i] - '0'); - else - break; - } - - /* In case of name is all digit character */ - if (i == strlen (name)) - { - access->type = ACCESS_TYPE_NUMBER; - - /* Set access_list to number list. */ - alist = &master->num; - - for (point = alist->head; point; point = point->next) - if (atol (point->name) >= number) - break; - } - else - { - access->type = ACCESS_TYPE_STRING; - - /* Set access_list to string list. */ - alist = &master->str; - - /* Set point to insertion point. */ - for (point = alist->head; point; point = point->next) - if (strcmp (point->name, name) >= 0) - break; - } - - /* In case of this is the first element of master. */ - if (alist->head == NULL) - { - alist->head = alist->tail = access; - return access; - } - - /* In case of insertion is made at the tail of access_list. */ - if (point == NULL) - { - access->prev = alist->tail; - alist->tail->next = access; - alist->tail = access; - return access; - } - - /* In case of insertion is made at the head of access_list. */ - if (point == alist->head) - { - access->next = alist->head; - alist->head->prev = access; - alist->head = access; - return access; - } - - /* Insertion is made at middle of the access_list. */ - access->next = point; - access->prev = point->prev; - - if (point->prev) - point->prev->next = access; - point->prev = access; - - return access; +static struct access_list *access_list_insert(afi_t afi, const char *name) +{ + unsigned int i; + long number; + struct access_list *access; + struct access_list *point; + struct access_list_list *alist; + struct access_master *master; + + master = access_master_get(afi); + if (master == NULL) + return NULL; + + /* Allocate new access_list and copy given name. */ + access = access_list_new(); + access->name = XSTRDUP(MTYPE_ACCESS_LIST_STR, name); + access->master = master; + + /* If name is made by all digit character. We treat it as + number. */ + for (number = 0, i = 0; i < strlen(name); i++) { + if (isdigit((int)name[i])) + number = (number * 10) + (name[i] - '0'); + else + break; + } + + /* In case of name is all digit character */ + if (i == strlen(name)) { + access->type = ACCESS_TYPE_NUMBER; + + /* Set access_list to number list. */ + alist = &master->num; + + for (point = alist->head; point; point = point->next) + if (atol(point->name) >= number) + break; + } else { + access->type = ACCESS_TYPE_STRING; + + /* Set access_list to string list. */ + alist = &master->str; + + /* Set point to insertion point. */ + for (point = alist->head; point; point = point->next) + if (strcmp(point->name, name) >= 0) + break; + } + + /* In case of this is the first element of master. */ + if (alist->head == NULL) { + alist->head = alist->tail = access; + return access; + } + + /* In case of insertion is made at the tail of access_list. */ + if (point == NULL) { + access->prev = alist->tail; + alist->tail->next = access; + alist->tail = access; + return access; + } + + /* In case of insertion is made at the head of access_list. */ + if (point == alist->head) { + access->next = alist->head; + alist->head->prev = access; + alist->head = access; + return access; + } + + /* Insertion is made at middle of the access_list. */ + access->next = point; + access->prev = point->prev; + + if (point->prev) + point->prev->next = access; + point->prev = access; + + return access; } /* Lookup access_list from list of access_list by name. */ -struct access_list * -access_list_lookup (afi_t afi, const char *name) +struct access_list *access_list_lookup(afi_t afi, const char *name) { - struct access_list *access; - struct access_master *master; + struct access_list *access; + struct access_master *master; - if (name == NULL) - return NULL; + if (name == NULL) + return NULL; - master = access_master_get (afi); - if (master == NULL) - return NULL; + master = access_master_get(afi); + if (master == NULL) + return NULL; - for (access = master->num.head; access; access = access->next) - if (strcmp (access->name, name) == 0) - return access; + for (access = master->num.head; access; access = access->next) + if (strcmp(access->name, name) == 0) + return access; - for (access = master->str.head; access; access = access->next) - if (strcmp (access->name, name) == 0) - return access; + for (access = master->str.head; access; access = access->next) + if (strcmp(access->name, name) == 0) + return access; - return NULL; + return NULL; } /* Get access list from list of access_list. If there isn't matched access_list create new one and return it. */ -static struct access_list * -access_list_get (afi_t afi, const char *name) +static struct access_list *access_list_get(afi_t afi, const char *name) { - struct access_list *access; + struct access_list *access; - access = access_list_lookup (afi, name); - if (access == NULL) - access = access_list_insert (afi, name); - return access; + access = access_list_lookup(afi, name); + if (access == NULL) + access = access_list_insert(afi, name); + return access; } /* Apply access list to object (which should be struct prefix *). */ -enum filter_type -access_list_apply (struct access_list *access, void *object) +enum filter_type access_list_apply(struct access_list *access, void *object) { - struct filter *filter; - struct prefix *p; + struct filter *filter; + struct prefix *p; - p = (struct prefix *) object; + p = (struct prefix *)object; - if (access == NULL) - return FILTER_DENY; + if (access == NULL) + return FILTER_DENY; - for (filter = access->head; filter; filter = filter->next) - { - if (filter->cisco) - { - if (filter_match_cisco (filter, p)) - return filter->type; - } - else - { - if (filter_match_zebra (filter, p)) - return filter->type; + for (filter = access->head; filter; filter = filter->next) { + if (filter->cisco) { + if (filter_match_cisco(filter, p)) + return filter->type; + } else { + if (filter_match_zebra(filter, p)) + return filter->type; + } } - } - return FILTER_DENY; + return FILTER_DENY; } /* Add hook function. */ -void -access_list_add_hook (void (*func) (struct access_list *access)) +void access_list_add_hook(void (*func)(struct access_list *access)) { - access_master_ipv4.add_hook = func; - access_master_ipv6.add_hook = func; + access_master_ipv4.add_hook = func; + access_master_ipv6.add_hook = func; } /* Delete hook function. */ -void -access_list_delete_hook (void (*func) (struct access_list *access)) +void access_list_delete_hook(void (*func)(struct access_list *access)) { - access_master_ipv4.delete_hook = func; - access_master_ipv6.delete_hook = func; + access_master_ipv4.delete_hook = func; + access_master_ipv6.delete_hook = func; } /* Add new filter to the end of specified access_list. */ -static void -access_list_filter_add (struct access_list *access, struct filter *filter) +static void access_list_filter_add(struct access_list *access, + struct filter *filter) { - filter->next = NULL; - filter->prev = access->tail; + filter->next = NULL; + filter->prev = access->tail; - if (access->tail) - access->tail->next = filter; - else - access->head = filter; - access->tail = filter; + if (access->tail) + access->tail->next = filter; + else + access->head = filter; + access->tail = filter; - /* Run hook function. */ - if (access->master->add_hook) - (*access->master->add_hook) (access); - route_map_notify_dependencies(access->name, RMAP_EVENT_FILTER_ADDED); + /* Run hook function. */ + if (access->master->add_hook) + (*access->master->add_hook)(access); + route_map_notify_dependencies(access->name, RMAP_EVENT_FILTER_ADDED); } /* If access_list has no filter then return 1. */ -static int -access_list_empty (struct access_list *access) +static int access_list_empty(struct access_list *access) { - if (access->head == NULL && access->tail == NULL) - return 1; - else - return 0; + if (access->head == NULL && access->tail == NULL) + return 1; + else + return 0; } /* Delete filter from specified access_list. If there is hook function execute it. */ -static void -access_list_filter_delete (struct access_list *access, struct filter *filter) +static void access_list_filter_delete(struct access_list *access, + struct filter *filter) { - struct access_master *master; + struct access_master *master; - master = access->master; + master = access->master; - if (filter->next) - filter->next->prev = filter->prev; - else - access->tail = filter->prev; + if (filter->next) + filter->next->prev = filter->prev; + else + access->tail = filter->prev; - if (filter->prev) - filter->prev->next = filter->next; - else - access->head = filter->next; + if (filter->prev) + filter->prev->next = filter->next; + else + access->head = filter->next; - filter_free (filter); + filter_free(filter); - route_map_notify_dependencies(access->name, RMAP_EVENT_FILTER_DELETED); - /* Run hook function. */ - if (master->delete_hook) - (*master->delete_hook) (access); + route_map_notify_dependencies(access->name, RMAP_EVENT_FILTER_DELETED); + /* Run hook function. */ + if (master->delete_hook) + (*master->delete_hook)(access); - /* If access_list becomes empty delete it from access_master. */ - if (access_list_empty (access)) - access_list_delete (access); + /* If access_list becomes empty delete it from access_master. */ + if (access_list_empty(access)) + access_list_delete(access); } /* @@ -513,179 +470,165 @@ access_list_filter_delete (struct access_list *access, struct filter *filter) host A single host address */ -static struct filter * -filter_lookup_cisco (struct access_list *access, struct filter *mnew) +static struct filter *filter_lookup_cisco(struct access_list *access, + struct filter *mnew) +{ + struct filter *mfilter; + struct filter_cisco *filter; + struct filter_cisco *new; + + new = &mnew->u.cfilter; + + for (mfilter = access->head; mfilter; mfilter = mfilter->next) { + filter = &mfilter->u.cfilter; + + if (filter->extended) { + if (mfilter->type == mnew->type + && filter->addr.s_addr == new->addr.s_addr + && filter->addr_mask.s_addr == new->addr_mask.s_addr + && filter->mask.s_addr == new->mask.s_addr + && filter->mask_mask.s_addr + == new->mask_mask.s_addr) + return mfilter; + } else { + if (mfilter->type == mnew->type + && filter->addr.s_addr == new->addr.s_addr + && filter->addr_mask.s_addr + == new->addr_mask.s_addr) + return mfilter; + } + } + + return NULL; +} + +static struct filter *filter_lookup_zebra(struct access_list *access, + struct filter *mnew) { - struct filter *mfilter; - struct filter_cisco *filter; - struct filter_cisco *new; + struct filter *mfilter; + struct filter_zebra *filter; + struct filter_zebra *new; - new = &mnew->u.cfilter; + new = &mnew->u.zfilter; - for (mfilter = access->head; mfilter; mfilter = mfilter->next) - { - filter = &mfilter->u.cfilter; + for (mfilter = access->head; mfilter; mfilter = mfilter->next) { + filter = &mfilter->u.zfilter; - if (filter->extended) - { - if (mfilter->type == mnew->type - && filter->addr.s_addr == new->addr.s_addr - && filter->addr_mask.s_addr == new->addr_mask.s_addr - && filter->mask.s_addr == new->mask.s_addr - && filter->mask_mask.s_addr == new->mask_mask.s_addr) - return mfilter; + if (filter->exact == new->exact + && mfilter->type + == mnew->type &&prefix_same(&filter->prefix, + &new->prefix)) + return mfilter; } - else - { - if (mfilter->type == mnew->type - && filter->addr.s_addr == new->addr.s_addr - && filter->addr_mask.s_addr == new->addr_mask.s_addr) - return mfilter; + return NULL; +} + +static int vty_access_list_remark_unset(struct vty *vty, afi_t afi, + const char *name) +{ + struct access_list *access; + + access = access_list_lookup(afi, name); + if (!access) { + vty_out(vty, "%% access-list %s doesn't exist\n", name); + return CMD_WARNING_CONFIG_FAILED; + } + + if (access->remark) { + XFREE(MTYPE_TMP, access->remark); + access->remark = NULL; } - } - - return NULL; -} - -static struct filter * -filter_lookup_zebra (struct access_list *access, struct filter *mnew) -{ - struct filter *mfilter; - struct filter_zebra *filter; - struct filter_zebra *new; - - new = &mnew->u.zfilter; - - for (mfilter = access->head; mfilter; mfilter = mfilter->next) - { - filter = &mfilter->u.zfilter; - - if (filter->exact == new->exact - && mfilter->type == mnew->type - && prefix_same (&filter->prefix, &new->prefix)) - return mfilter; - } - return NULL; -} - -static int -vty_access_list_remark_unset (struct vty *vty, afi_t afi, const char *name) -{ - struct access_list *access; - - access = access_list_lookup (afi, name); - if (! access) - { - vty_out (vty, "%% access-list %s doesn't exist\n",name); - return CMD_WARNING_CONFIG_FAILED; - } - - if (access->remark) - { - XFREE (MTYPE_TMP, access->remark); - access->remark = NULL; - } - - if (access->head == NULL && access->tail == NULL && access->remark == NULL) - access_list_delete (access); - - return CMD_SUCCESS; -} - -static int -filter_set_cisco (struct vty *vty, const char *name_str, const char *type_str, - const char *addr_str, const char *addr_mask_str, - const char *mask_str, const char *mask_mask_str, - int extended, int set) -{ - int ret; - enum filter_type type; - struct filter *mfilter; - struct filter_cisco *filter; - struct access_list *access; - struct in_addr addr; - struct in_addr addr_mask; - struct in_addr mask; - struct in_addr mask_mask; - - /* Check of filter type. */ - if (strncmp (type_str, "p", 1) == 0) - type = FILTER_PERMIT; - else if (strncmp (type_str, "d", 1) == 0) - type = FILTER_DENY; - else - { - vty_out (vty, "%% filter type must be permit or deny\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ret = inet_aton (addr_str, &addr); - if (ret <= 0) - { - vty_out (vty,"%%Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ret = inet_aton (addr_mask_str, &addr_mask); - if (ret <= 0) - { - vty_out (vty,"%%Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (extended) - { - ret = inet_aton (mask_str, &mask); - if (ret <= 0) - { - vty_out (vty,"%%Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; + + if (access->head == NULL && access->tail == NULL + && access->remark == NULL) + access_list_delete(access); + + return CMD_SUCCESS; +} + +static int filter_set_cisco(struct vty *vty, const char *name_str, + const char *type_str, const char *addr_str, + const char *addr_mask_str, const char *mask_str, + const char *mask_mask_str, int extended, int set) +{ + int ret; + enum filter_type type; + struct filter *mfilter; + struct filter_cisco *filter; + struct access_list *access; + struct in_addr addr; + struct in_addr addr_mask; + struct in_addr mask; + struct in_addr mask_mask; + + /* Check of filter type. */ + if (strncmp(type_str, "p", 1) == 0) + type = FILTER_PERMIT; + else if (strncmp(type_str, "d", 1) == 0) + type = FILTER_DENY; + else { + vty_out(vty, "%% filter type must be permit or deny\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = inet_aton(addr_str, &addr); + if (ret <= 0) { + vty_out(vty, "%%Inconsistent address and mask\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = inet_aton(addr_mask_str, &addr_mask); + if (ret <= 0) { + vty_out(vty, "%%Inconsistent address and mask\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (extended) { + ret = inet_aton(mask_str, &mask); + if (ret <= 0) { + vty_out(vty, "%%Inconsistent address and mask\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = inet_aton(mask_mask_str, &mask_mask); + if (ret <= 0) { + vty_out(vty, "%%Inconsistent address and mask\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + mfilter = filter_new(); + mfilter->type = type; + mfilter->cisco = 1; + filter = &mfilter->u.cfilter; + filter->extended = extended; + filter->addr.s_addr = addr.s_addr & ~addr_mask.s_addr; + filter->addr_mask.s_addr = addr_mask.s_addr; + + if (extended) { + filter->mask.s_addr = mask.s_addr & ~mask_mask.s_addr; + filter->mask_mask.s_addr = mask_mask.s_addr; } - ret = inet_aton (mask_mask_str, &mask_mask); - if (ret <= 0) - { - vty_out (vty,"%%Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; + /* Install new filter to the access_list. */ + access = access_list_get(AFI_IP, name_str); + + if (set) { + if (filter_lookup_cisco(access, mfilter)) + filter_free(mfilter); + else + access_list_filter_add(access, mfilter); + } else { + struct filter *delete_filter; + + delete_filter = filter_lookup_cisco(access, mfilter); + if (delete_filter) + access_list_filter_delete(access, delete_filter); + + filter_free(mfilter); } - } - - mfilter = filter_new(); - mfilter->type = type; - mfilter->cisco = 1; - filter = &mfilter->u.cfilter; - filter->extended = extended; - filter->addr.s_addr = addr.s_addr & ~addr_mask.s_addr; - filter->addr_mask.s_addr = addr_mask.s_addr; - - if (extended) - { - filter->mask.s_addr = mask.s_addr & ~mask_mask.s_addr; - filter->mask_mask.s_addr = mask_mask.s_addr; - } - - /* Install new filter to the access_list. */ - access = access_list_get (AFI_IP, name_str); - - if (set) - { - if (filter_lookup_cisco (access, mfilter)) - filter_free (mfilter); - else - access_list_filter_add (access, mfilter); - } - else - { - struct filter *delete_filter; - - delete_filter = filter_lookup_cisco (access, mfilter); - if (delete_filter) - access_list_filter_delete (access, delete_filter); - - filter_free (mfilter); - } - - return CMD_SUCCESS; + + return CMD_SUCCESS; } /* Standard access-list */ @@ -700,12 +643,13 @@ DEFUN (access_list_standard, "Address to match\n" "Wildcard bits\n") { - int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 3; - int idx_ipv4_2 = 4; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, - NULL, NULL, 0, 1); + int idx_acl = 1; + int idx_permit_deny = 2; + int idx_ipv4 = 3; + int idx_ipv4_2 = 4; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + argv[idx_ipv4_2]->arg, NULL, NULL, 0, 1); } DEFUN (access_list_standard_nomask, @@ -718,11 +662,12 @@ DEFUN (access_list_standard_nomask, "Specify packets to forward\n" "Address to match\n") { - int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 3; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, "0.0.0.0", - NULL, NULL, 0, 1); + int idx_acl = 1; + int idx_permit_deny = 2; + int idx_ipv4 = 3; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + "0.0.0.0", NULL, NULL, 0, 1); } DEFUN (access_list_standard_host, @@ -736,11 +681,12 @@ DEFUN (access_list_standard_host, "A single host address\n" "Address to match\n") { - int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 4; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, "0.0.0.0", - NULL, NULL, 0, 1); + int idx_acl = 1; + int idx_permit_deny = 2; + int idx_ipv4 = 4; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + "0.0.0.0", NULL, NULL, 0, 1); } DEFUN (access_list_standard_any, @@ -753,10 +699,11 @@ DEFUN (access_list_standard_any, "Specify packets to forward\n" "Any source host\n") { - int idx_acl = 1; - int idx_permit_deny = 2; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", NULL, NULL, 0, 1); + int idx_acl = 1; + int idx_permit_deny = 2; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, "0.0.0.0", + "255.255.255.255", NULL, NULL, 0, 1); } DEFUN (no_access_list_standard, @@ -771,12 +718,13 @@ DEFUN (no_access_list_standard, "Address to match\n" "Wildcard bits\n") { - int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 4; - int idx_ipv4_2 = 5; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, - NULL, NULL, 0, 0); + int idx_acl = 2; + int idx_permit_deny = 3; + int idx_ipv4 = 4; + int idx_ipv4_2 = 5; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + argv[idx_ipv4_2]->arg, NULL, NULL, 0, 0); } DEFUN (no_access_list_standard_nomask, @@ -790,11 +738,12 @@ DEFUN (no_access_list_standard_nomask, "Specify packets to forward\n" "Address to match\n") { - int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 4; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, "0.0.0.0", - NULL, NULL, 0, 0); + int idx_acl = 2; + int idx_permit_deny = 3; + int idx_ipv4 = 4; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + "0.0.0.0", NULL, NULL, 0, 0); } DEFUN (no_access_list_standard_host, @@ -809,11 +758,12 @@ DEFUN (no_access_list_standard_host, "A single host address\n" "Address to match\n") { - int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 5; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, "0.0.0.0", - NULL, NULL, 0, 0); + int idx_acl = 2; + int idx_permit_deny = 3; + int idx_ipv4 = 5; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + "0.0.0.0", NULL, NULL, 0, 0); } DEFUN (no_access_list_standard_any, @@ -827,10 +777,11 @@ DEFUN (no_access_list_standard_any, "Specify packets to forward\n" "Any source host\n") { - int idx_acl = 2; - int idx_permit_deny = 3; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", NULL, NULL, 0, 0); + int idx_acl = 2; + int idx_permit_deny = 3; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, "0.0.0.0", + "255.255.255.255", NULL, NULL, 0, 0); } /* Extended access-list */ @@ -848,14 +799,16 @@ DEFUN (access_list_extended, "Destination address\n" "Destination Wildcard bits\n") { - int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 4; - int idx_ipv4_2 = 5; - int idx_ipv4_3 = 6; - int idx_ipv4_4 = 7; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, argv[idx_ipv4_3]->arg, argv[idx_ipv4_4]->arg, 1 ,1); + int idx_acl = 1; + int idx_permit_deny = 2; + int idx_ipv4 = 4; + int idx_ipv4_2 = 5; + int idx_ipv4_3 = 6; + int idx_ipv4_4 = 7; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + argv[idx_ipv4_2]->arg, argv[idx_ipv4_3]->arg, + argv[idx_ipv4_4]->arg, 1, 1); } DEFUN (access_list_extended_mask_any, @@ -871,13 +824,14 @@ DEFUN (access_list_extended_mask_any, "Source wildcard bits\n" "Any destination host\n") { - int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 4; - int idx_ipv4_2 = 5; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, "0.0.0.0", - "255.255.255.255", 1, 1); + int idx_acl = 1; + int idx_permit_deny = 2; + int idx_ipv4 = 4; + int idx_ipv4_2 = 5; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + argv[idx_ipv4_2]->arg, "0.0.0.0", + "255.255.255.255", 1, 1); } DEFUN (access_list_extended_any_mask, @@ -893,13 +847,14 @@ DEFUN (access_list_extended_any_mask, "Destination address\n" "Destination Wildcard bits\n") { - int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 5; - int idx_ipv4_2 = 6; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, 1, 1); + int idx_acl = 1; + int idx_permit_deny = 2; + int idx_ipv4 = 5; + int idx_ipv4_2 = 6; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, "0.0.0.0", + "255.255.255.255", argv[idx_ipv4]->arg, + argv[idx_ipv4_2]->arg, 1, 1); } DEFUN (access_list_extended_any_any, @@ -914,11 +869,11 @@ DEFUN (access_list_extended_any_any, "Any source host\n" "Any destination host\n") { - int idx_acl = 1; - int idx_permit_deny = 2; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", "0.0.0.0", - "255.255.255.255", 1, 1); + int idx_acl = 1; + int idx_permit_deny = 2; + return filter_set_cisco( + vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, "0.0.0.0", + "255.255.255.255", "0.0.0.0", "255.255.255.255", 1, 1); } DEFUN (access_list_extended_mask_host, @@ -935,14 +890,15 @@ DEFUN (access_list_extended_mask_host, "A single destination host\n" "Destination address\n") { - int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 4; - int idx_ipv4_2 = 5; - int idx_ipv4_3 = 7; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, argv[idx_ipv4_3]->arg, - "0.0.0.0", 1, 1); + int idx_acl = 1; + int idx_permit_deny = 2; + int idx_ipv4 = 4; + int idx_ipv4_2 = 5; + int idx_ipv4_3 = 7; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + argv[idx_ipv4_2]->arg, argv[idx_ipv4_3]->arg, + "0.0.0.0", 1, 1); } DEFUN (access_list_extended_host_mask, @@ -959,14 +915,15 @@ DEFUN (access_list_extended_host_mask, "Destination address\n" "Destination Wildcard bits\n") { - int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 5; - int idx_ipv4_2 = 6; - int idx_ipv4_3 = 7; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", argv[idx_ipv4_2]->arg, - argv[idx_ipv4_3]->arg, 1, 1); + int idx_acl = 1; + int idx_permit_deny = 2; + int idx_ipv4 = 5; + int idx_ipv4_2 = 6; + int idx_ipv4_3 = 7; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + "0.0.0.0", argv[idx_ipv4_2]->arg, + argv[idx_ipv4_3]->arg, 1, 1); } DEFUN (access_list_extended_host_host, @@ -983,13 +940,14 @@ DEFUN (access_list_extended_host_host, "A single destination host\n" "Destination address\n") { - int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 5; - int idx_ipv4_2 = 7; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", argv[idx_ipv4_2]->arg, - "0.0.0.0", 1, 1); + int idx_acl = 1; + int idx_permit_deny = 2; + int idx_ipv4 = 5; + int idx_ipv4_2 = 7; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + "0.0.0.0", argv[idx_ipv4_2]->arg, "0.0.0.0", 1, + 1); } DEFUN (access_list_extended_any_host, @@ -1005,12 +963,12 @@ DEFUN (access_list_extended_any_host, "A single destination host\n" "Destination address\n") { - int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 6; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", argv[idx_ipv4]->arg, - "0.0.0.0", 1, 1); + int idx_acl = 1; + int idx_permit_deny = 2; + int idx_ipv4 = 6; + return filter_set_cisco( + vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, "0.0.0.0", + "255.255.255.255", argv[idx_ipv4]->arg, "0.0.0.0", 1, 1); } DEFUN (access_list_extended_host_any, @@ -1026,12 +984,12 @@ DEFUN (access_list_extended_host_any, "Source address\n" "Any destination host\n") { - int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 5; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", "0.0.0.0", - "255.255.255.255", 1, 1); + int idx_acl = 1; + int idx_permit_deny = 2; + int idx_ipv4 = 5; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + "0.0.0.0", "0.0.0.0", "255.255.255.255", 1, 1); } DEFUN (no_access_list_extended, @@ -1049,14 +1007,16 @@ DEFUN (no_access_list_extended, "Destination address\n" "Destination Wildcard bits\n") { - int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 5; - int idx_ipv4_2 = 6; - int idx_ipv4_3 = 7; - int idx_ipv4_4 = 8; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, argv[idx_ipv4_3]->arg, argv[idx_ipv4_4]->arg, 1, 0); + int idx_acl = 2; + int idx_permit_deny = 3; + int idx_ipv4 = 5; + int idx_ipv4_2 = 6; + int idx_ipv4_3 = 7; + int idx_ipv4_4 = 8; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + argv[idx_ipv4_2]->arg, argv[idx_ipv4_3]->arg, + argv[idx_ipv4_4]->arg, 1, 0); } DEFUN (no_access_list_extended_mask_any, @@ -1073,13 +1033,14 @@ DEFUN (no_access_list_extended_mask_any, "Source wildcard bits\n" "Any destination host\n") { - int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 5; - int idx_ipv4_2 = 6; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, "0.0.0.0", - "255.255.255.255", 1, 0); + int idx_acl = 2; + int idx_permit_deny = 3; + int idx_ipv4 = 5; + int idx_ipv4_2 = 6; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + argv[idx_ipv4_2]->arg, "0.0.0.0", + "255.255.255.255", 1, 0); } DEFUN (no_access_list_extended_any_mask, @@ -1096,13 +1057,14 @@ DEFUN (no_access_list_extended_any_mask, "Destination address\n" "Destination Wildcard bits\n") { - int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 6; - int idx_ipv4_2 = 7; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, 1, 0); + int idx_acl = 2; + int idx_permit_deny = 3; + int idx_ipv4 = 6; + int idx_ipv4_2 = 7; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, "0.0.0.0", + "255.255.255.255", argv[idx_ipv4]->arg, + argv[idx_ipv4_2]->arg, 1, 0); } DEFUN (no_access_list_extended_any_any, @@ -1118,11 +1080,11 @@ DEFUN (no_access_list_extended_any_any, "Any source host\n" "Any destination host\n") { - int idx_acl = 2; - int idx_permit_deny = 3; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", "0.0.0.0", - "255.255.255.255", 1, 0); + int idx_acl = 2; + int idx_permit_deny = 3; + return filter_set_cisco( + vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, "0.0.0.0", + "255.255.255.255", "0.0.0.0", "255.255.255.255", 1, 0); } DEFUN (no_access_list_extended_mask_host, @@ -1140,14 +1102,15 @@ DEFUN (no_access_list_extended_mask_host, "A single destination host\n" "Destination address\n") { - int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 5; - int idx_ipv4_2 = 6; - int idx_ipv4_3 = 8; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, argv[idx_ipv4_3]->arg, - "0.0.0.0", 1, 0); + int idx_acl = 2; + int idx_permit_deny = 3; + int idx_ipv4 = 5; + int idx_ipv4_2 = 6; + int idx_ipv4_3 = 8; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + argv[idx_ipv4_2]->arg, argv[idx_ipv4_3]->arg, + "0.0.0.0", 1, 0); } DEFUN (no_access_list_extended_host_mask, @@ -1165,14 +1128,15 @@ DEFUN (no_access_list_extended_host_mask, "Destination address\n" "Destination Wildcard bits\n") { - int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 6; - int idx_ipv4_2 = 7; - int idx_ipv4_3 = 8; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", argv[idx_ipv4_2]->arg, - argv[idx_ipv4_3]->arg, 1, 0); + int idx_acl = 2; + int idx_permit_deny = 3; + int idx_ipv4 = 6; + int idx_ipv4_2 = 7; + int idx_ipv4_3 = 8; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + "0.0.0.0", argv[idx_ipv4_2]->arg, + argv[idx_ipv4_3]->arg, 1, 0); } DEFUN (no_access_list_extended_host_host, @@ -1190,13 +1154,14 @@ DEFUN (no_access_list_extended_host_host, "A single destination host\n" "Destination address\n") { - int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 6; - int idx_ipv4_2 = 8; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", argv[idx_ipv4_2]->arg, - "0.0.0.0", 1, 0); + int idx_acl = 2; + int idx_permit_deny = 3; + int idx_ipv4 = 6; + int idx_ipv4_2 = 8; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + "0.0.0.0", argv[idx_ipv4_2]->arg, "0.0.0.0", 1, + 0); } DEFUN (no_access_list_extended_any_host, @@ -1213,12 +1178,12 @@ DEFUN (no_access_list_extended_any_host, "A single destination host\n" "Destination address\n") { - int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 7; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", argv[idx_ipv4]->arg, - "0.0.0.0", 1, 0); + int idx_acl = 2; + int idx_permit_deny = 3; + int idx_ipv4 = 7; + return filter_set_cisco( + vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, "0.0.0.0", + "255.255.255.255", argv[idx_ipv4]->arg, "0.0.0.0", 1, 0); } DEFUN (no_access_list_extended_host_any, @@ -1235,97 +1200,89 @@ DEFUN (no_access_list_extended_host_any, "Source address\n" "Any destination host\n") { - int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 6; - return filter_set_cisco (vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", "0.0.0.0", - "255.255.255.255", 1, 0); -} - -static int -filter_set_zebra (struct vty *vty, const char *name_str, const char *type_str, - afi_t afi, const char *prefix_str, int exact, int set) -{ - int ret; - enum filter_type type; - struct filter *mfilter; - struct filter_zebra *filter; - struct access_list *access; - struct prefix p; - - if (strlen(name_str) > ACL_NAMSIZ) - { - vty_out (vty, "%% ACL name %s is invalid: length exceeds " - "%d characters\n", - name_str, ACL_NAMSIZ); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check of filter type. */ - if (strncmp (type_str, "p", 1) == 0) - type = FILTER_PERMIT; - else if (strncmp (type_str, "d", 1) == 0) - type = FILTER_DENY; - else - { - vty_out (vty, "filter type must be [permit|deny]\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check string format of prefix and prefixlen. */ - if (afi == AFI_IP) - { - ret = str2prefix_ipv4 (prefix_str, (struct prefix_ipv4 *)&p); - if (ret <= 0) - { - vty_out (vty,"IP address prefix/prefixlen is malformed\n"); - return CMD_WARNING_CONFIG_FAILED; + int idx_acl = 2; + int idx_permit_deny = 3; + int idx_ipv4 = 6; + return filter_set_cisco(vty, argv[idx_acl]->arg, + argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + "0.0.0.0", "0.0.0.0", "255.255.255.255", 1, 0); +} + +static int filter_set_zebra(struct vty *vty, const char *name_str, + const char *type_str, afi_t afi, + const char *prefix_str, int exact, int set) +{ + int ret; + enum filter_type type; + struct filter *mfilter; + struct filter_zebra *filter; + struct access_list *access; + struct prefix p; + + if (strlen(name_str) > ACL_NAMSIZ) { + vty_out(vty, + "%% ACL name %s is invalid: length exceeds " + "%d characters\n", + name_str, ACL_NAMSIZ); + return CMD_WARNING_CONFIG_FAILED; } - } - else if (afi == AFI_IP6) - { - ret = str2prefix_ipv6 (prefix_str, (struct prefix_ipv6 *) &p); - if (ret <= 0) - { - vty_out (vty,"IPv6 address prefix/prefixlen is malformed\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - else - return CMD_WARNING_CONFIG_FAILED; - - mfilter = filter_new (); - mfilter->type = type; - filter = &mfilter->u.zfilter; - prefix_copy (&filter->prefix, &p); - - /* "exact-match" */ - if (exact) - filter->exact = 1; - /* Install new filter to the access_list. */ - access = access_list_get (afi, name_str); - - if (set) - { - if (filter_lookup_zebra (access, mfilter)) - filter_free (mfilter); - else - access_list_filter_add (access, mfilter); - } - else - { - struct filter *delete_filter; - - delete_filter = filter_lookup_zebra (access, mfilter); - if (delete_filter) - access_list_filter_delete (access, delete_filter); + /* Check of filter type. */ + if (strncmp(type_str, "p", 1) == 0) + type = FILTER_PERMIT; + else if (strncmp(type_str, "d", 1) == 0) + type = FILTER_DENY; + else { + vty_out(vty, "filter type must be [permit|deny]\n"); + return CMD_WARNING_CONFIG_FAILED; + } - filter_free (mfilter); - } + /* Check string format of prefix and prefixlen. */ + if (afi == AFI_IP) { + ret = str2prefix_ipv4(prefix_str, (struct prefix_ipv4 *)&p); + if (ret <= 0) { + vty_out(vty, + "IP address prefix/prefixlen is malformed\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } else if (afi == AFI_IP6) { + ret = str2prefix_ipv6(prefix_str, (struct prefix_ipv6 *)&p); + if (ret <= 0) { + vty_out(vty, + "IPv6 address prefix/prefixlen is malformed\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } else + return CMD_WARNING_CONFIG_FAILED; + + mfilter = filter_new(); + mfilter->type = type; + filter = &mfilter->u.zfilter; + prefix_copy(&filter->prefix, &p); + + /* "exact-match" */ + if (exact) + filter->exact = 1; + + /* Install new filter to the access_list. */ + access = access_list_get(afi, name_str); + + if (set) { + if (filter_lookup_zebra(access, mfilter)) + filter_free(mfilter); + else + access_list_filter_add(access, mfilter); + } else { + struct filter *delete_filter; + + delete_filter = filter_lookup_zebra(access, mfilter); + if (delete_filter) + access_list_filter_delete(access, delete_filter); + + filter_free(mfilter); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (access_list_exact, @@ -1338,18 +1295,19 @@ DEFUN (access_list_exact, "Prefix to match. e.g. 10.0.0.0/8\n" "Exact match of the prefixes\n") { - int idx; - int exact = 0; - int idx_word = 1; - int idx_permit_deny = 2; - int idx_ipv4_prefixlen = 3; - idx = idx_ipv4_prefixlen; + int idx; + int exact = 0; + int idx_word = 1; + int idx_permit_deny = 2; + int idx_ipv4_prefixlen = 3; + idx = idx_ipv4_prefixlen; - if (argv_find (argv, argc, "exact-match", &idx)) - exact = 1; + if (argv_find(argv, argc, "exact-match", &idx)) + exact = 1; - return filter_set_zebra (vty, argv[idx_word]->arg, argv[idx_permit_deny]->arg, - AFI_IP, argv[idx_ipv4_prefixlen]->arg, exact, 1); + return filter_set_zebra(vty, argv[idx_word]->arg, + argv[idx_permit_deny]->arg, AFI_IP, + argv[idx_ipv4_prefixlen]->arg, exact, 1); } DEFUN (access_list_any, @@ -1361,9 +1319,11 @@ DEFUN (access_list_any, "Specify packets to forward\n" "Prefix to match. e.g. 10.0.0.0/8\n") { - int idx_word = 1; - int idx_permit_deny = 2; - return filter_set_zebra (vty, argv[idx_word]->arg, argv[idx_permit_deny]->arg, AFI_IP, "0.0.0.0/0", 0, 1); + int idx_word = 1; + int idx_permit_deny = 2; + return filter_set_zebra(vty, argv[idx_word]->arg, + argv[idx_permit_deny]->arg, AFI_IP, "0.0.0.0/0", + 0, 1); } DEFUN (no_access_list_exact, @@ -1377,17 +1337,19 @@ DEFUN (no_access_list_exact, "Prefix to match. e.g. 10.0.0.0/8\n" "Exact match of the prefixes\n") { - int idx; - int exact = 0; - int idx_word = 2; - int idx_permit_deny = 3; - int idx_ipv4_prefixlen = 4; - idx = idx_ipv4_prefixlen; + int idx; + int exact = 0; + int idx_word = 2; + int idx_permit_deny = 3; + int idx_ipv4_prefixlen = 4; + idx = idx_ipv4_prefixlen; - if (argv_find (argv, argc, "exact-match", &idx)) - exact = 1; + if (argv_find(argv, argc, "exact-match", &idx)) + exact = 1; - return filter_set_zebra (vty, argv[idx_word]->arg, argv[idx_permit_deny]->arg, AFI_IP, argv[idx_ipv4_prefixlen]->arg, exact, 0); + return filter_set_zebra(vty, argv[idx_word]->arg, + argv[idx_permit_deny]->arg, AFI_IP, + argv[idx_ipv4_prefixlen]->arg, exact, 0); } DEFUN (no_access_list_any, @@ -1400,9 +1362,11 @@ DEFUN (no_access_list_any, "Specify packets to forward\n" "Prefix to match. e.g. 10.0.0.0/8\n") { - int idx_word = 2; - int idx_permit_deny = 3; - return filter_set_zebra (vty, argv[idx_word]->arg, argv[idx_permit_deny]->arg, AFI_IP, "0.0.0.0/0", 0, 0); + int idx_word = 2; + int idx_permit_deny = 3; + return filter_set_zebra(vty, argv[idx_word]->arg, + argv[idx_permit_deny]->arg, AFI_IP, "0.0.0.0/0", + 0, 0); } DEFUN (no_access_list_all, @@ -1416,29 +1380,29 @@ DEFUN (no_access_list_all, "IP extended access list (expanded range)\n" "IP zebra access-list name\n") { - int idx_acl = 2; - struct access_list *access; - struct access_master *master; + int idx_acl = 2; + struct access_list *access; + struct access_master *master; - /* Looking up access_list. */ - access = access_list_lookup (AFI_IP, argv[idx_acl]->arg); - if (access == NULL) - { - vty_out (vty, "%% access-list %s doesn't exist\n",argv[idx_acl]->arg); - return CMD_WARNING_CONFIG_FAILED; - } + /* Looking up access_list. */ + access = access_list_lookup(AFI_IP, argv[idx_acl]->arg); + if (access == NULL) { + vty_out(vty, "%% access-list %s doesn't exist\n", + argv[idx_acl]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + + master = access->master; - master = access->master; + route_map_notify_dependencies(access->name, RMAP_EVENT_FILTER_DELETED); + /* Run hook function. */ + if (master->delete_hook) + (*master->delete_hook)(access); - route_map_notify_dependencies(access->name, RMAP_EVENT_FILTER_DELETED); - /* Run hook function. */ - if (master->delete_hook) - (*master->delete_hook) (access); - - /* Delete all filter from access-list. */ - access_list_delete (access); + /* Delete all filter from access-list. */ + access_list_delete(access); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (access_list_remark, @@ -1453,20 +1417,19 @@ DEFUN (access_list_remark, "Access list entry comment\n" "Comment up to 100 characters\n") { - int idx_acl = 1; - int idx_remark = 3; - struct access_list *access; + int idx_acl = 1; + int idx_remark = 3; + struct access_list *access; - access = access_list_get (AFI_IP, argv[idx_acl]->arg); + access = access_list_get(AFI_IP, argv[idx_acl]->arg); - if (access->remark) - { - XFREE (MTYPE_TMP, access->remark); - access->remark = NULL; - } - access->remark = argv_concat(argv, argc, idx_remark); + if (access->remark) { + XFREE(MTYPE_TMP, access->remark); + access->remark = NULL; + } + access->remark = argv_concat(argv, argc, idx_remark); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_access_list_remark, @@ -1481,8 +1444,8 @@ DEFUN (no_access_list_remark, "IP zebra access-list\n" "Access list entry comment\n") { - int idx_acl = 2; - return vty_access_list_remark_unset (vty, AFI_IP, argv[idx_acl]->arg); + int idx_acl = 2; + return vty_access_list_remark_unset(vty, AFI_IP, argv[idx_acl]->arg); } /* ALIAS_FIXME */ @@ -1499,7 +1462,7 @@ DEFUN (no_access_list_remark_comment, "Access list entry comment\n" "Comment up to 100 characters\n") { - return no_access_list_remark (self, vty, argc, argv); + return no_access_list_remark(self, vty, argc, argv); } DEFUN (ipv6_access_list_exact, @@ -1513,18 +1476,18 @@ DEFUN (ipv6_access_list_exact, "IPv6 prefix\n" "Exact match of the prefixes\n") { - int idx; - int exact = 0; - int idx_word = 2; - int idx_allow = 3; - int idx_addr = 4; - idx = idx_addr; + int idx; + int exact = 0; + int idx_word = 2; + int idx_allow = 3; + int idx_addr = 4; + idx = idx_addr; - if (argv_find (argv, argc, "exact-match", &idx)) - exact = 1; + if (argv_find(argv, argc, "exact-match", &idx)) + exact = 1; - return filter_set_zebra (vty, argv[idx_word]->arg, argv[idx_allow]->text, - AFI_IP6, argv[idx_addr]->arg, exact, 1); + return filter_set_zebra(vty, argv[idx_word]->arg, argv[idx_allow]->text, + AFI_IP6, argv[idx_addr]->arg, exact, 1); } DEFUN (ipv6_access_list_any, @@ -1537,9 +1500,11 @@ DEFUN (ipv6_access_list_any, "Specify packets to forward\n" "Any prefixi to match\n") { - int idx_word = 2; - int idx_permit_deny = 3; - return filter_set_zebra (vty, argv[idx_word]->arg, argv[idx_permit_deny]->arg, AFI_IP6, "::/0", 0, 1); + int idx_word = 2; + int idx_permit_deny = 3; + return filter_set_zebra(vty, argv[idx_word]->arg, + argv[idx_permit_deny]->arg, AFI_IP6, "::/0", 0, + 1); } DEFUN (no_ipv6_access_list_exact, @@ -1554,18 +1519,19 @@ DEFUN (no_ipv6_access_list_exact, "Prefix to match. e.g. 3ffe:506::/32\n" "Exact match of the prefixes\n") { - int idx; - int exact = 0; - int idx_word = 3; - int idx_permit_deny = 4; - int idx_ipv6_prefixlen = 5; - idx = idx_ipv6_prefixlen; + int idx; + int exact = 0; + int idx_word = 3; + int idx_permit_deny = 4; + int idx_ipv6_prefixlen = 5; + idx = idx_ipv6_prefixlen; - if (argv_find (argv, argc, "exact-match", &idx)) - exact = 1; + if (argv_find(argv, argc, "exact-match", &idx)) + exact = 1; - return filter_set_zebra (vty, argv[idx_word]->arg, argv[idx_permit_deny]->arg, - AFI_IP6, argv[idx_ipv6_prefixlen]->arg, exact, 0); + return filter_set_zebra(vty, argv[idx_word]->arg, + argv[idx_permit_deny]->arg, AFI_IP6, + argv[idx_ipv6_prefixlen]->arg, exact, 0); } DEFUN (no_ipv6_access_list_any, @@ -1579,9 +1545,11 @@ DEFUN (no_ipv6_access_list_any, "Specify packets to forward\n" "Any prefixi to match\n") { - int idx_word = 3; - int idx_permit_deny = 4; - return filter_set_zebra (vty, argv[idx_word]->arg, argv[idx_permit_deny]->arg, AFI_IP6, "::/0", 0, 0); + int idx_word = 3; + int idx_permit_deny = 4; + return filter_set_zebra(vty, argv[idx_word]->arg, + argv[idx_permit_deny]->arg, AFI_IP6, "::/0", 0, + 0); } @@ -1593,29 +1561,29 @@ DEFUN (no_ipv6_access_list_all, "Add an access list entry\n" "IPv6 zebra access-list\n") { - int idx_word = 3; - struct access_list *access; - struct access_master *master; + int idx_word = 3; + struct access_list *access; + struct access_master *master; - /* Looking up access_list. */ - access = access_list_lookup (AFI_IP6, argv[idx_word]->arg); - if (access == NULL) - { - vty_out (vty, "%% access-list %s doesn't exist\n",argv[idx_word]->arg); - return CMD_WARNING_CONFIG_FAILED; - } + /* Looking up access_list. */ + access = access_list_lookup(AFI_IP6, argv[idx_word]->arg); + if (access == NULL) { + vty_out(vty, "%% access-list %s doesn't exist\n", + argv[idx_word]->arg); + return CMD_WARNING_CONFIG_FAILED; + } - master = access->master; + master = access->master; - route_map_notify_dependencies(access->name, RMAP_EVENT_FILTER_DELETED); - /* Run hook function. */ - if (master->delete_hook) - (*master->delete_hook) (access); + route_map_notify_dependencies(access->name, RMAP_EVENT_FILTER_DELETED); + /* Run hook function. */ + if (master->delete_hook) + (*master->delete_hook)(access); - /* Delete all filter from access-list. */ - access_list_delete (access); + /* Delete all filter from access-list. */ + access_list_delete(access); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_access_list_remark, @@ -1627,20 +1595,19 @@ DEFUN (ipv6_access_list_remark, "Access list entry comment\n" "Comment up to 100 characters\n") { - int idx_word = 2; - int idx_line = 4; - struct access_list *access; + int idx_word = 2; + int idx_line = 4; + struct access_list *access; - access = access_list_get (AFI_IP6, argv[idx_word]->arg); + access = access_list_get(AFI_IP6, argv[idx_word]->arg); - if (access->remark) - { - XFREE (MTYPE_TMP, access->remark); - access->remark = NULL; - } - access->remark = argv_concat(argv, argc, idx_line); + if (access->remark) { + XFREE(MTYPE_TMP, access->remark); + access->remark = NULL; + } + access->remark = argv_concat(argv, argc, idx_line); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ipv6_access_list_remark, @@ -1652,8 +1619,8 @@ DEFUN (no_ipv6_access_list_remark, "IPv6 zebra access-list\n" "Access list entry comment\n") { - int idx_word = 3; - return vty_access_list_remark_unset (vty, AFI_IP6, argv[idx_word]->arg); + int idx_word = 3; + return vty_access_list_remark_unset(vty, AFI_IP6, argv[idx_word]->arg); } /* ALIAS_FIXME */ @@ -1667,115 +1634,116 @@ DEFUN (no_ipv6_access_list_remark_comment, "Access list entry comment\n" "Comment up to 100 characters\n") { - return no_ipv6_access_list_remark (self, vty, argc, argv); + return no_ipv6_access_list_remark(self, vty, argc, argv); } -void config_write_access_zebra (struct vty *, struct filter *); -void config_write_access_cisco (struct vty *, struct filter *); +void config_write_access_zebra(struct vty *, struct filter *); +void config_write_access_cisco(struct vty *, struct filter *); /* show access-list command. */ -static int -filter_show (struct vty *vty, const char *name, afi_t afi) -{ - struct access_list *access; - struct access_master *master; - struct filter *mfilter; - struct filter_cisco *filter; - int write = 0; - - master = access_master_get (afi); - if (master == NULL) - return 0; - - /* Print the name of the protocol */ - vty_out (vty, "%s:\n", frr_protoname); - - for (access = master->num.head; access; access = access->next) - { - if (name && strcmp (access->name, name) != 0) - continue; - - write = 1; - - for (mfilter = access->head; mfilter; mfilter = mfilter->next) - { - filter = &mfilter->u.cfilter; - - if (write) - { - vty_out (vty, "%s IP%s access list %s\n", - mfilter->cisco ? - (filter->extended ? "Extended" : "Standard") : "Zebra", - afi == AFI_IP6 ? "v6" : "", - access->name); - write = 0; - } - - vty_out (vty, " %s%s", filter_type_str (mfilter), - mfilter->type == FILTER_DENY ? " " : ""); - - if (! mfilter->cisco) - config_write_access_zebra (vty, mfilter); - else if (filter->extended) - config_write_access_cisco (vty, mfilter); - else - { - if (filter->addr_mask.s_addr == 0xffffffff) - vty_out (vty, " any\n"); - else - { - vty_out (vty, " %s", inet_ntoa (filter->addr)); - if (filter->addr_mask.s_addr != 0) - vty_out (vty, ", wildcard bits %s", inet_ntoa (filter->addr_mask)); - vty_out (vty, "\n"); +static int filter_show(struct vty *vty, const char *name, afi_t afi) +{ + struct access_list *access; + struct access_master *master; + struct filter *mfilter; + struct filter_cisco *filter; + int write = 0; + + master = access_master_get(afi); + if (master == NULL) + return 0; + + /* Print the name of the protocol */ + vty_out(vty, "%s:\n", frr_protoname); + + for (access = master->num.head; access; access = access->next) { + if (name && strcmp(access->name, name) != 0) + continue; + + write = 1; + + for (mfilter = access->head; mfilter; mfilter = mfilter->next) { + filter = &mfilter->u.cfilter; + + if (write) { + vty_out(vty, "%s IP%s access list %s\n", + mfilter->cisco ? (filter->extended + ? "Extended" + : "Standard") + : "Zebra", + afi == AFI_IP6 ? "v6" : "", + access->name); + write = 0; + } + + vty_out(vty, " %s%s", filter_type_str(mfilter), + mfilter->type == FILTER_DENY ? " " : ""); + + if (!mfilter->cisco) + config_write_access_zebra(vty, mfilter); + else if (filter->extended) + config_write_access_cisco(vty, mfilter); + else { + if (filter->addr_mask.s_addr == 0xffffffff) + vty_out(vty, " any\n"); + else { + vty_out(vty, " %s", + inet_ntoa(filter->addr)); + if (filter->addr_mask.s_addr != 0) + vty_out(vty, + ", wildcard bits %s", + inet_ntoa( + filter->addr_mask)); + vty_out(vty, "\n"); + } + } } - } } - } - - for (access = master->str.head; access; access = access->next) - { - if (name && strcmp (access->name, name) != 0) - continue; - - write = 1; - - for (mfilter = access->head; mfilter; mfilter = mfilter->next) - { - filter = &mfilter->u.cfilter; - - if (write) - { - vty_out (vty, "%s IP%s access list %s\n", - mfilter->cisco ? - (filter->extended ? "Extended" : "Standard") : "Zebra", - afi == AFI_IP6 ? "v6" : "", - access->name); - write = 0; - } - - vty_out (vty, " %s%s", filter_type_str (mfilter), - mfilter->type == FILTER_DENY ? " " : ""); - - if (! mfilter->cisco) - config_write_access_zebra (vty, mfilter); - else if (filter->extended) - config_write_access_cisco (vty, mfilter); - else - { - if (filter->addr_mask.s_addr == 0xffffffff) - vty_out (vty, " any\n"); - else - { - vty_out (vty, " %s", inet_ntoa (filter->addr)); - if (filter->addr_mask.s_addr != 0) - vty_out (vty, ", wildcard bits %s", inet_ntoa (filter->addr_mask)); - vty_out (vty, "\n"); + + for (access = master->str.head; access; access = access->next) { + if (name && strcmp(access->name, name) != 0) + continue; + + write = 1; + + for (mfilter = access->head; mfilter; mfilter = mfilter->next) { + filter = &mfilter->u.cfilter; + + if (write) { + vty_out(vty, "%s IP%s access list %s\n", + mfilter->cisco ? (filter->extended + ? "Extended" + : "Standard") + : "Zebra", + afi == AFI_IP6 ? "v6" : "", + access->name); + write = 0; + } + + vty_out(vty, " %s%s", filter_type_str(mfilter), + mfilter->type == FILTER_DENY ? " " : ""); + + if (!mfilter->cisco) + config_write_access_zebra(vty, mfilter); + else if (filter->extended) + config_write_access_cisco(vty, mfilter); + else { + if (filter->addr_mask.s_addr == 0xffffffff) + vty_out(vty, " any\n"); + else { + vty_out(vty, " %s", + inet_ntoa(filter->addr)); + if (filter->addr_mask.s_addr != 0) + vty_out(vty, + ", wildcard bits %s", + inet_ntoa( + filter->addr_mask)); + vty_out(vty, "\n"); + } + } } - } } - } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_access_list, @@ -1785,7 +1753,7 @@ DEFUN (show_ip_access_list, IP_STR "List IP access lists\n") { - return filter_show (vty, NULL, AFI_IP); + return filter_show(vty, NULL, AFI_IP); } DEFUN (show_ip_access_list_name, @@ -1800,8 +1768,8 @@ DEFUN (show_ip_access_list_name, "IP extended access list (expanded range)\n" "IP zebra access-list\n") { - int idx_acl = 3; - return filter_show (vty, argv[idx_acl]->arg, AFI_IP); + int idx_acl = 3; + return filter_show(vty, argv[idx_acl]->arg, AFI_IP); } DEFUN (show_ipv6_access_list, @@ -1811,7 +1779,7 @@ DEFUN (show_ipv6_access_list, IPV6_STR "List IPv6 access lists\n") { - return filter_show (vty, NULL, AFI_IP6); + return filter_show(vty, NULL, AFI_IP6); } DEFUN (show_ipv6_access_list_name, @@ -1822,307 +1790,270 @@ DEFUN (show_ipv6_access_list_name, "List IPv6 access lists\n" "IPv6 zebra access-list\n") { - int idx_word = 3; - return filter_show (vty, argv[idx_word]->arg, AFI_IP6); -} - -void -config_write_access_cisco (struct vty *vty, struct filter *mfilter) -{ - struct filter_cisco *filter; - - filter = &mfilter->u.cfilter; - - if (filter->extended) - { - vty_out (vty, " ip"); - if (filter->addr_mask.s_addr == 0xffffffff) - vty_out (vty, " any"); - else if (filter->addr_mask.s_addr == 0) - vty_out (vty, " host %s", inet_ntoa (filter->addr)); - else - { - vty_out (vty, " %s", inet_ntoa (filter->addr)); - vty_out (vty, " %s", inet_ntoa (filter->addr_mask)); - } - - if (filter->mask_mask.s_addr == 0xffffffff) - vty_out (vty, " any"); - else if (filter->mask_mask.s_addr == 0) - vty_out (vty, " host %s", inet_ntoa (filter->mask)); - else - { - vty_out (vty, " %s", inet_ntoa (filter->mask)); - vty_out (vty, " %s", inet_ntoa (filter->mask_mask)); - } - vty_out (vty, "\n"); - } - else - { - if (filter->addr_mask.s_addr == 0xffffffff) - vty_out (vty, " any\n"); - else - { - vty_out (vty, " %s", inet_ntoa (filter->addr)); - if (filter->addr_mask.s_addr != 0) - vty_out (vty, " %s", inet_ntoa (filter->addr_mask)); - vty_out (vty, "\n"); + int idx_word = 3; + return filter_show(vty, argv[idx_word]->arg, AFI_IP6); +} + +void config_write_access_cisco(struct vty *vty, struct filter *mfilter) +{ + struct filter_cisco *filter; + + filter = &mfilter->u.cfilter; + + if (filter->extended) { + vty_out(vty, " ip"); + if (filter->addr_mask.s_addr == 0xffffffff) + vty_out(vty, " any"); + else if (filter->addr_mask.s_addr == 0) + vty_out(vty, " host %s", inet_ntoa(filter->addr)); + else { + vty_out(vty, " %s", inet_ntoa(filter->addr)); + vty_out(vty, " %s", inet_ntoa(filter->addr_mask)); + } + + if (filter->mask_mask.s_addr == 0xffffffff) + vty_out(vty, " any"); + else if (filter->mask_mask.s_addr == 0) + vty_out(vty, " host %s", inet_ntoa(filter->mask)); + else { + vty_out(vty, " %s", inet_ntoa(filter->mask)); + vty_out(vty, " %s", inet_ntoa(filter->mask_mask)); + } + vty_out(vty, "\n"); + } else { + if (filter->addr_mask.s_addr == 0xffffffff) + vty_out(vty, " any\n"); + else { + vty_out(vty, " %s", inet_ntoa(filter->addr)); + if (filter->addr_mask.s_addr != 0) + vty_out(vty, " %s", + inet_ntoa(filter->addr_mask)); + vty_out(vty, "\n"); + } } - } } -void -config_write_access_zebra (struct vty *vty, struct filter *mfilter) +void config_write_access_zebra(struct vty *vty, struct filter *mfilter) { - struct filter_zebra *filter; - struct prefix *p; - char buf[BUFSIZ]; + struct filter_zebra *filter; + struct prefix *p; + char buf[BUFSIZ]; - filter = &mfilter->u.zfilter; - p = &filter->prefix; + filter = &mfilter->u.zfilter; + p = &filter->prefix; - if (p->prefixlen == 0 && ! filter->exact) - vty_out (vty, " any"); - else - vty_out (vty, " %s/%d%s", - inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), - p->prefixlen, - filter->exact ? " exact-match" : ""); + if (p->prefixlen == 0 && !filter->exact) + vty_out(vty, " any"); + else + vty_out(vty, " %s/%d%s", + inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), + p->prefixlen, filter->exact ? " exact-match" : ""); - vty_out (vty, "\n"); + vty_out(vty, "\n"); } -static int -config_write_access (struct vty *vty, afi_t afi) +static int config_write_access(struct vty *vty, afi_t afi) { - struct access_list *access; - struct access_master *master; - struct filter *mfilter; - int write = 0; + struct access_list *access; + struct access_master *master; + struct filter *mfilter; + int write = 0; - master = access_master_get (afi); - if (master == NULL) - return 0; + master = access_master_get(afi); + if (master == NULL) + return 0; - for (access = master->num.head; access; access = access->next) - { - if (access->remark) - { - vty_out (vty, "%saccess-list %s remark %s\n", - afi == AFI_IP ? "" : "ipv6 ", - access->name,access->remark); - write++; - } + for (access = master->num.head; access; access = access->next) { + if (access->remark) { + vty_out(vty, "%saccess-list %s remark %s\n", + afi == AFI_IP ? "" : "ipv6 ", access->name, + access->remark); + write++; + } - for (mfilter = access->head; mfilter; mfilter = mfilter->next) - { - vty_out (vty, "%saccess-list %s %s", - afi == AFI_IP ? "" : "ipv6 ", - access->name, - filter_type_str (mfilter)); + for (mfilter = access->head; mfilter; mfilter = mfilter->next) { + vty_out(vty, "%saccess-list %s %s", + afi == AFI_IP ? "" : "ipv6 ", access->name, + filter_type_str(mfilter)); - if (mfilter->cisco) - config_write_access_cisco (vty, mfilter); - else - config_write_access_zebra (vty, mfilter); + if (mfilter->cisco) + config_write_access_cisco(vty, mfilter); + else + config_write_access_zebra(vty, mfilter); - write++; - } - } - - for (access = master->str.head; access; access = access->next) - { - if (access->remark) - { - vty_out (vty, "%saccess-list %s remark %s\n", - afi == AFI_IP ? "" : "ipv6 ", - access->name,access->remark); - write++; + write++; + } } - for (mfilter = access->head; mfilter; mfilter = mfilter->next) - { - vty_out (vty, "%saccess-list %s %s", - afi == AFI_IP ? "" : "ipv6 ", - access->name, - filter_type_str (mfilter)); + for (access = master->str.head; access; access = access->next) { + if (access->remark) { + vty_out(vty, "%saccess-list %s remark %s\n", + afi == AFI_IP ? "" : "ipv6 ", access->name, + access->remark); + write++; + } + + for (mfilter = access->head; mfilter; mfilter = mfilter->next) { + vty_out(vty, "%saccess-list %s %s", + afi == AFI_IP ? "" : "ipv6 ", access->name, + filter_type_str(mfilter)); - if (mfilter->cisco) - config_write_access_cisco (vty, mfilter); - else - config_write_access_zebra (vty, mfilter); + if (mfilter->cisco) + config_write_access_cisco(vty, mfilter); + else + config_write_access_zebra(vty, mfilter); - write++; + write++; + } } - } - return write; + return write; } /* Access-list node. */ -static struct cmd_node access_node = -{ - ACCESS_NODE, - "", /* Access list has no interface. */ - 1 -}; +static struct cmd_node access_node = {ACCESS_NODE, + "", /* Access list has no interface. */ + 1}; -static int -config_write_access_ipv4 (struct vty *vty) +static int config_write_access_ipv4(struct vty *vty) { - return config_write_access (vty, AFI_IP); + return config_write_access(vty, AFI_IP); } -static void -access_list_reset_ipv4 (void) +static void access_list_reset_ipv4(void) { - struct access_list *access; - struct access_list *next; - struct access_master *master; + struct access_list *access; + struct access_list *next; + struct access_master *master; - master = access_master_get (AFI_IP); - if (master == NULL) - return; + master = access_master_get(AFI_IP); + if (master == NULL) + return; - for (access = master->num.head; access; access = next) - { - next = access->next; - access_list_delete (access); - } - for (access = master->str.head; access; access = next) - { - next = access->next; - access_list_delete (access); - } + for (access = master->num.head; access; access = next) { + next = access->next; + access_list_delete(access); + } + for (access = master->str.head; access; access = next) { + next = access->next; + access_list_delete(access); + } - assert (master->num.head == NULL); - assert (master->num.tail == NULL); + assert(master->num.head == NULL); + assert(master->num.tail == NULL); - assert (master->str.head == NULL); - assert (master->str.tail == NULL); + assert(master->str.head == NULL); + assert(master->str.tail == NULL); } /* Install vty related command. */ -static void -access_list_init_ipv4 (void) -{ - install_node (&access_node, config_write_access_ipv4); - - install_element (ENABLE_NODE, &show_ip_access_list_cmd); - install_element (ENABLE_NODE, &show_ip_access_list_name_cmd); - - /* Zebra access-list */ - install_element (CONFIG_NODE, &access_list_exact_cmd); - install_element (CONFIG_NODE, &access_list_any_cmd); - install_element (CONFIG_NODE, &no_access_list_exact_cmd); - install_element (CONFIG_NODE, &no_access_list_any_cmd); - - /* Standard access-list */ - install_element (CONFIG_NODE, &access_list_standard_cmd); - install_element (CONFIG_NODE, &access_list_standard_nomask_cmd); - install_element (CONFIG_NODE, &access_list_standard_host_cmd); - install_element (CONFIG_NODE, &access_list_standard_any_cmd); - install_element (CONFIG_NODE, &no_access_list_standard_cmd); - install_element (CONFIG_NODE, &no_access_list_standard_nomask_cmd); - install_element (CONFIG_NODE, &no_access_list_standard_host_cmd); - install_element (CONFIG_NODE, &no_access_list_standard_any_cmd); - - /* Extended access-list */ - install_element (CONFIG_NODE, &access_list_extended_cmd); - install_element (CONFIG_NODE, &access_list_extended_any_mask_cmd); - install_element (CONFIG_NODE, &access_list_extended_mask_any_cmd); - install_element (CONFIG_NODE, &access_list_extended_any_any_cmd); - install_element (CONFIG_NODE, &access_list_extended_host_mask_cmd); - install_element (CONFIG_NODE, &access_list_extended_mask_host_cmd); - install_element (CONFIG_NODE, &access_list_extended_host_host_cmd); - install_element (CONFIG_NODE, &access_list_extended_any_host_cmd); - install_element (CONFIG_NODE, &access_list_extended_host_any_cmd); - install_element (CONFIG_NODE, &no_access_list_extended_cmd); - install_element (CONFIG_NODE, &no_access_list_extended_any_mask_cmd); - install_element (CONFIG_NODE, &no_access_list_extended_mask_any_cmd); - install_element (CONFIG_NODE, &no_access_list_extended_any_any_cmd); - install_element (CONFIG_NODE, &no_access_list_extended_host_mask_cmd); - install_element (CONFIG_NODE, &no_access_list_extended_mask_host_cmd); - install_element (CONFIG_NODE, &no_access_list_extended_host_host_cmd); - install_element (CONFIG_NODE, &no_access_list_extended_any_host_cmd); - install_element (CONFIG_NODE, &no_access_list_extended_host_any_cmd); - - install_element (CONFIG_NODE, &access_list_remark_cmd); - install_element (CONFIG_NODE, &no_access_list_all_cmd); - install_element (CONFIG_NODE, &no_access_list_remark_cmd); - install_element (CONFIG_NODE, &no_access_list_remark_comment_cmd); -} - -static struct cmd_node access_ipv6_node = -{ - ACCESS_IPV6_NODE, - "", - 1 -}; - -static int -config_write_access_ipv6 (struct vty *vty) -{ - return config_write_access (vty, AFI_IP6); -} - -static void -access_list_reset_ipv6 (void) -{ - struct access_list *access; - struct access_list *next; - struct access_master *master; - - master = access_master_get (AFI_IP6); - if (master == NULL) - return; - - for (access = master->num.head; access; access = next) - { - next = access->next; - access_list_delete (access); - } - for (access = master->str.head; access; access = next) - { - next = access->next; - access_list_delete (access); - } +static void access_list_init_ipv4(void) +{ + install_node(&access_node, config_write_access_ipv4); + + install_element(ENABLE_NODE, &show_ip_access_list_cmd); + install_element(ENABLE_NODE, &show_ip_access_list_name_cmd); + + /* Zebra access-list */ + install_element(CONFIG_NODE, &access_list_exact_cmd); + install_element(CONFIG_NODE, &access_list_any_cmd); + install_element(CONFIG_NODE, &no_access_list_exact_cmd); + install_element(CONFIG_NODE, &no_access_list_any_cmd); + + /* Standard access-list */ + install_element(CONFIG_NODE, &access_list_standard_cmd); + install_element(CONFIG_NODE, &access_list_standard_nomask_cmd); + install_element(CONFIG_NODE, &access_list_standard_host_cmd); + install_element(CONFIG_NODE, &access_list_standard_any_cmd); + install_element(CONFIG_NODE, &no_access_list_standard_cmd); + install_element(CONFIG_NODE, &no_access_list_standard_nomask_cmd); + install_element(CONFIG_NODE, &no_access_list_standard_host_cmd); + install_element(CONFIG_NODE, &no_access_list_standard_any_cmd); + + /* Extended access-list */ + install_element(CONFIG_NODE, &access_list_extended_cmd); + install_element(CONFIG_NODE, &access_list_extended_any_mask_cmd); + install_element(CONFIG_NODE, &access_list_extended_mask_any_cmd); + install_element(CONFIG_NODE, &access_list_extended_any_any_cmd); + install_element(CONFIG_NODE, &access_list_extended_host_mask_cmd); + install_element(CONFIG_NODE, &access_list_extended_mask_host_cmd); + install_element(CONFIG_NODE, &access_list_extended_host_host_cmd); + install_element(CONFIG_NODE, &access_list_extended_any_host_cmd); + install_element(CONFIG_NODE, &access_list_extended_host_any_cmd); + install_element(CONFIG_NODE, &no_access_list_extended_cmd); + install_element(CONFIG_NODE, &no_access_list_extended_any_mask_cmd); + install_element(CONFIG_NODE, &no_access_list_extended_mask_any_cmd); + install_element(CONFIG_NODE, &no_access_list_extended_any_any_cmd); + install_element(CONFIG_NODE, &no_access_list_extended_host_mask_cmd); + install_element(CONFIG_NODE, &no_access_list_extended_mask_host_cmd); + install_element(CONFIG_NODE, &no_access_list_extended_host_host_cmd); + install_element(CONFIG_NODE, &no_access_list_extended_any_host_cmd); + install_element(CONFIG_NODE, &no_access_list_extended_host_any_cmd); + + install_element(CONFIG_NODE, &access_list_remark_cmd); + install_element(CONFIG_NODE, &no_access_list_all_cmd); + install_element(CONFIG_NODE, &no_access_list_remark_cmd); + install_element(CONFIG_NODE, &no_access_list_remark_comment_cmd); +} + +static struct cmd_node access_ipv6_node = {ACCESS_IPV6_NODE, "", 1}; + +static int config_write_access_ipv6(struct vty *vty) +{ + return config_write_access(vty, AFI_IP6); +} + +static void access_list_reset_ipv6(void) +{ + struct access_list *access; + struct access_list *next; + struct access_master *master; + + master = access_master_get(AFI_IP6); + if (master == NULL) + return; + + for (access = master->num.head; access; access = next) { + next = access->next; + access_list_delete(access); + } + for (access = master->str.head; access; access = next) { + next = access->next; + access_list_delete(access); + } - assert (master->num.head == NULL); - assert (master->num.tail == NULL); + assert(master->num.head == NULL); + assert(master->num.tail == NULL); - assert (master->str.head == NULL); - assert (master->str.tail == NULL); + assert(master->str.head == NULL); + assert(master->str.tail == NULL); } -static void -access_list_init_ipv6 (void) +static void access_list_init_ipv6(void) { - install_node (&access_ipv6_node, config_write_access_ipv6); + install_node(&access_ipv6_node, config_write_access_ipv6); - install_element (ENABLE_NODE, &show_ipv6_access_list_cmd); - install_element (ENABLE_NODE, &show_ipv6_access_list_name_cmd); + install_element(ENABLE_NODE, &show_ipv6_access_list_cmd); + install_element(ENABLE_NODE, &show_ipv6_access_list_name_cmd); - install_element (CONFIG_NODE, &ipv6_access_list_exact_cmd); - install_element (CONFIG_NODE, &ipv6_access_list_any_cmd); - install_element (CONFIG_NODE, &no_ipv6_access_list_exact_cmd); - install_element (CONFIG_NODE, &no_ipv6_access_list_any_cmd); + install_element(CONFIG_NODE, &ipv6_access_list_exact_cmd); + install_element(CONFIG_NODE, &ipv6_access_list_any_cmd); + install_element(CONFIG_NODE, &no_ipv6_access_list_exact_cmd); + install_element(CONFIG_NODE, &no_ipv6_access_list_any_cmd); - install_element (CONFIG_NODE, &no_ipv6_access_list_all_cmd); - install_element (CONFIG_NODE, &ipv6_access_list_remark_cmd); - install_element (CONFIG_NODE, &no_ipv6_access_list_remark_cmd); - install_element (CONFIG_NODE, &no_ipv6_access_list_remark_comment_cmd); + install_element(CONFIG_NODE, &no_ipv6_access_list_all_cmd); + install_element(CONFIG_NODE, &ipv6_access_list_remark_cmd); + install_element(CONFIG_NODE, &no_ipv6_access_list_remark_cmd); + install_element(CONFIG_NODE, &no_ipv6_access_list_remark_comment_cmd); } -void -access_list_init () +void access_list_init() { - access_list_init_ipv4 (); - access_list_init_ipv6(); + access_list_init_ipv4(); + access_list_init_ipv6(); } -void -access_list_reset () +void access_list_reset() { - access_list_reset_ipv4 (); - access_list_reset_ipv6(); + access_list_reset_ipv4(); + access_list_reset_ipv6(); } diff --git a/lib/filter.h b/lib/filter.h index 2c7001811..c02516409 100644 --- a/lib/filter.h +++ b/lib/filter.h @@ -33,42 +33,32 @@ #define FILTER_MAX 2 /* Filter type is made by `permit', `deny' and `dynamic'. */ -enum filter_type -{ - FILTER_DENY, - FILTER_PERMIT, - FILTER_DYNAMIC -}; +enum filter_type { FILTER_DENY, FILTER_PERMIT, FILTER_DYNAMIC }; -enum access_type -{ - ACCESS_TYPE_STRING, - ACCESS_TYPE_NUMBER -}; +enum access_type { ACCESS_TYPE_STRING, ACCESS_TYPE_NUMBER }; /* Access list */ -struct access_list -{ - char *name; - char *remark; +struct access_list { + char *name; + char *remark; - struct access_master *master; + struct access_master *master; - enum access_type type; + enum access_type type; - struct access_list *next; - struct access_list *prev; + struct access_list *next; + struct access_list *prev; - struct filter *head; - struct filter *tail; + struct filter *head; + struct filter *tail; }; /* Prototypes for access-list. */ -extern void access_list_init (void); -extern void access_list_reset (void); -extern void access_list_add_hook (void (*func)(struct access_list *)); -extern void access_list_delete_hook (void (*func)(struct access_list *)); -extern struct access_list *access_list_lookup (afi_t, const char *); -extern enum filter_type access_list_apply (struct access_list *, void *); +extern void access_list_init(void); +extern void access_list_reset(void); +extern void access_list_add_hook(void (*func)(struct access_list *)); +extern void access_list_delete_hook(void (*func)(struct access_list *)); +extern struct access_list *access_list_lookup(afi_t, const char *); +extern enum filter_type access_list_apply(struct access_list *, void *); #endif /* _ZEBRA_FILTER_H */ diff --git a/lib/frr_pthread.c b/lib/frr_pthread.c index 4b9bed452..8b23640fa 100644 --- a/lib/frr_pthread.c +++ b/lib/frr_pthread.c @@ -37,106 +37,107 @@ static pthread_mutex_t pthread_table_mtx = PTHREAD_MUTEX_INITIALIZER; /* pthread_table->hash_cmp */ static int pthread_table_hash_cmp(const void *value1, const void *value2) { - const struct frr_pthread *tq1 = value1; - const struct frr_pthread *tq2 = value2; + const struct frr_pthread *tq1 = value1; + const struct frr_pthread *tq2 = value2; - return (tq1->id == tq2->id); + return (tq1->id == tq2->id); } /* pthread_table->hash_key */ static unsigned int pthread_table_hash_key(void *value) { - return ((struct frr_pthread *)value)->id; + return ((struct frr_pthread *)value)->id; } /* ------------------------------------------------------------------------ */ void frr_pthread_init() { - pthread_mutex_lock(&pthread_table_mtx); - { - pthread_table = - hash_create(pthread_table_hash_key, pthread_table_hash_cmp, NULL); - } - pthread_mutex_unlock(&pthread_table_mtx); + pthread_mutex_lock(&pthread_table_mtx); + { + pthread_table = hash_create(pthread_table_hash_key, + pthread_table_hash_cmp, NULL); + } + pthread_mutex_unlock(&pthread_table_mtx); } void frr_pthread_finish() { - pthread_mutex_lock(&pthread_table_mtx); - { - hash_clean(pthread_table, (void (*)(void *))frr_pthread_destroy); - hash_free(pthread_table); - } - pthread_mutex_unlock(&pthread_table_mtx); + pthread_mutex_lock(&pthread_table_mtx); + { + hash_clean(pthread_table, + (void (*)(void *))frr_pthread_destroy); + hash_free(pthread_table); + } + pthread_mutex_unlock(&pthread_table_mtx); } struct frr_pthread *frr_pthread_new(const char *name, unsigned int id, - void *(*start_routine) (void *), - int (*stop_routine) (void **, struct frr_pthread *)) + void *(*start_routine)(void *), + int (*stop_routine)(void **, + struct frr_pthread *)) { - static struct frr_pthread holder = { 0 }; - struct frr_pthread *fpt = NULL; - - pthread_mutex_lock(&pthread_table_mtx); - { - holder.id = id; - - if (!hash_lookup(pthread_table, &holder)) { - struct frr_pthread *fpt = - XCALLOC(MTYPE_FRR_PTHREAD, - sizeof(struct frr_pthread)); - fpt->id = id; - fpt->master = thread_master_create(name); - fpt->start_routine = start_routine; - fpt->stop_routine = stop_routine; - fpt->name = XSTRDUP(MTYPE_FRR_PTHREAD, name); - - hash_get(pthread_table, fpt, hash_alloc_intern); - } - } - pthread_mutex_unlock(&pthread_table_mtx); - - return fpt; + static struct frr_pthread holder = {0}; + struct frr_pthread *fpt = NULL; + + pthread_mutex_lock(&pthread_table_mtx); + { + holder.id = id; + + if (!hash_lookup(pthread_table, &holder)) { + struct frr_pthread *fpt = XCALLOC( + MTYPE_FRR_PTHREAD, sizeof(struct frr_pthread)); + fpt->id = id; + fpt->master = thread_master_create(name); + fpt->start_routine = start_routine; + fpt->stop_routine = stop_routine; + fpt->name = XSTRDUP(MTYPE_FRR_PTHREAD, name); + + hash_get(pthread_table, fpt, hash_alloc_intern); + } + } + pthread_mutex_unlock(&pthread_table_mtx); + + return fpt; } void frr_pthread_destroy(struct frr_pthread *fpt) { - thread_master_free(fpt->master); - XFREE(MTYPE_FRR_PTHREAD, fpt->name); - XFREE(MTYPE_FRR_PTHREAD, fpt); + thread_master_free(fpt->master); + XFREE(MTYPE_FRR_PTHREAD, fpt->name); + XFREE(MTYPE_FRR_PTHREAD, fpt); } struct frr_pthread *frr_pthread_get(unsigned int id) { - static struct frr_pthread holder = { 0 }; - struct frr_pthread *fpt; + static struct frr_pthread holder = {0}; + struct frr_pthread *fpt; - pthread_mutex_lock(&pthread_table_mtx); - { - holder.id = id; - fpt = hash_lookup(pthread_table, &holder); - } - pthread_mutex_unlock(&pthread_table_mtx); + pthread_mutex_lock(&pthread_table_mtx); + { + holder.id = id; + fpt = hash_lookup(pthread_table, &holder); + } + pthread_mutex_unlock(&pthread_table_mtx); - return fpt; + return fpt; } -int frr_pthread_run(unsigned int id, const pthread_attr_t * attr, void *arg) +int frr_pthread_run(unsigned int id, const pthread_attr_t *attr, void *arg) { - struct frr_pthread *fpt = frr_pthread_get(id); - int ret; + struct frr_pthread *fpt = frr_pthread_get(id); + int ret; - if (!fpt) - return -1; + if (!fpt) + return -1; - ret = pthread_create(&fpt->thread, attr, fpt->start_routine, arg); + ret = pthread_create(&fpt->thread, attr, fpt->start_routine, arg); - /* Per pthread_create(3), the contents of fpt->thread are undefined if - * pthread_create() did not succeed. Reset this value to zero. */ - if (ret < 0) - memset(&fpt->thread, 0x00, sizeof(fpt->thread)); + /* Per pthread_create(3), the contents of fpt->thread are undefined if + * pthread_create() did not succeed. Reset this value to zero. */ + if (ret < 0) + memset(&fpt->thread, 0x00, sizeof(fpt->thread)); - return ret; + return ret; } /** @@ -148,15 +149,15 @@ int frr_pthread_run(unsigned int id, const pthread_attr_t * attr, void *arg) */ static int frr_pthread_stop_actual(struct frr_pthread *fpt, void **result) { - int ret = (*fpt->stop_routine) (result, fpt); - memset(&fpt->thread, 0x00, sizeof(fpt->thread)); - return ret; + int ret = (*fpt->stop_routine)(result, fpt); + memset(&fpt->thread, 0x00, sizeof(fpt->thread)); + return ret; } int frr_pthread_stop(unsigned int id, void **result) { - struct frr_pthread *fpt = frr_pthread_get(id); - return frr_pthread_stop_actual(fpt, result); + struct frr_pthread *fpt = frr_pthread_get(id); + return frr_pthread_stop_actual(fpt, result); } /** @@ -164,20 +165,20 @@ int frr_pthread_stop(unsigned int id, void **result) */ static void frr_pthread_stop_all_iter(struct hash_backet *hb, void *arg) { - struct frr_pthread *fpt = hb->data; - frr_pthread_stop_actual(fpt, NULL); + struct frr_pthread *fpt = hb->data; + frr_pthread_stop_actual(fpt, NULL); } void frr_pthread_stop_all() { - pthread_mutex_lock(&pthread_table_mtx); - { - hash_iterate(pthread_table, frr_pthread_stop_all_iter, NULL); - } - pthread_mutex_unlock(&pthread_table_mtx); + pthread_mutex_lock(&pthread_table_mtx); + { + hash_iterate(pthread_table, frr_pthread_stop_all_iter, NULL); + } + pthread_mutex_unlock(&pthread_table_mtx); } unsigned int frr_pthread_get_id() { - return next_id++; + return next_id++; } diff --git a/lib/frr_pthread.h b/lib/frr_pthread.h index 1a390b1e4..9dee5fcca 100644 --- a/lib/frr_pthread.h +++ b/lib/frr_pthread.h @@ -25,23 +25,23 @@ struct frr_pthread { - /* pthread id */ - pthread_t thread; + /* pthread id */ + pthread_t thread; - /* frr thread identifier */ - unsigned int id; + /* frr thread identifier */ + unsigned int id; - /* thread master for this pthread's thread.c event loop */ - struct thread_master *master; + /* thread master for this pthread's thread.c event loop */ + struct thread_master *master; - /* start routine */ - void *(*start_routine) (void *); + /* start routine */ + void *(*start_routine)(void *); - /* stop routine */ - int (*stop_routine) (void **, struct frr_pthread *); + /* stop routine */ + int (*stop_routine)(void **, struct frr_pthread *); - /* the (hopefully descriptive) name of this thread */ - char *name; + /* the (hopefully descriptive) name of this thread */ + char *name; }; /* Initializes this module. @@ -82,8 +82,9 @@ void frr_pthread_finish(void); * @return the created frr_pthread upon success, or NULL upon failure */ struct frr_pthread *frr_pthread_new(const char *name, unsigned int id, - void *(*start_routine) (void *), - int (*stop_routine) (void **, struct frr_pthread *)); + void *(*start_routine)(void *), + int (*stop_routine)(void **, + struct frr_pthread *)); /* Destroys an frr_pthread. * @@ -116,7 +117,7 @@ struct frr_pthread *frr_pthread_get(unsigned int id); * * @return see pthread_create(3) */ -int frr_pthread_run(unsigned int id, const pthread_attr_t * attr, void *arg); +int frr_pthread_run(unsigned int id, const pthread_attr_t *attr, void *arg); /* Stops an frr_pthread with a result. * diff --git a/lib/frratomic.h b/lib/frratomic.h index 183790aeb..4ae84c401 100644 --- a/lib/frratomic.h +++ b/lib/frratomic.h @@ -47,7 +47,8 @@ #define atomic_fetch_add_explicit __atomic_fetch_add #define atomic_fetch_sub_explicit __atomic_fetch_sub -#define atomic_compare_exchange_weak_explicit(atom, expect, desire, mem1, mem2) \ +#define atomic_compare_exchange_weak_explicit(atom, expect, desire, mem1, \ + mem2) \ __atomic_compare_exchange_n(atom, expect, desire, 1, mem1, mem2) /* gcc 4.1 and newer, @@ -55,7 +56,7 @@ * * __sync_swap isn't in gcc's documentation, but clang has it * - * note __sync_synchronize() + * note __sync_synchronize() */ #elif defined(HAVE___SYNC) @@ -68,48 +69,72 @@ #define memory_order_acq_rel 0 #define memory_order_seq_cst 0 -#define atomic_load_explicit(ptr, mem) \ - ({ __sync_synchronize(); \ - typeof(*ptr) rval = __sync_fetch_and_add((ptr), 0); \ - __sync_synchronize(); rval; }) -#define atomic_store_explicit(ptr, val, mem) \ - ({ __sync_synchronize(); \ - *(ptr) = (val); \ - __sync_synchronize(); (void)0; }) +#define atomic_load_explicit(ptr, mem) \ + ({ \ + __sync_synchronize(); \ + typeof(*ptr) rval = __sync_fetch_and_add((ptr), 0); \ + __sync_synchronize(); \ + rval; \ + }) +#define atomic_store_explicit(ptr, val, mem) \ + ({ \ + __sync_synchronize(); \ + *(ptr) = (val); \ + __sync_synchronize(); \ + (void)0; \ + }) #ifdef HAVE___SYNC_SWAP -#define atomic_exchange_explicit(ptr, val, mem) \ - ({ __sync_synchronize(); \ - typeof(*ptr) rval = __sync_swap((ptr, val), 0); \ - __sync_synchronize(); rval; }) +#define atomic_exchange_explicit(ptr, val, mem) \ + ({ \ + __sync_synchronize(); \ + typeof(*ptr) rval = __sync_swap((ptr, val), 0); \ + __sync_synchronize(); \ + rval; \ + }) #else /* !HAVE___SYNC_SWAP */ -#define atomic_exchange_explicit(ptr, val, mem) \ - ({ typeof(ptr) _ptr = (ptr); typeof(val) _val = (val); \ - __sync_synchronize(); \ - typeof(*ptr) old1, old2 = __sync_fetch_and_add(_ptr, 0); \ - do { \ - old1 = old2; \ - old2 = __sync_val_compare_and_swap (_ptr, old1, _val); \ - } while (old1 != old2); \ - __sync_synchronize(); \ - old2; \ +#define atomic_exchange_explicit(ptr, val, mem) \ + ({ \ + typeof(ptr) _ptr = (ptr); \ + typeof(val) _val = (val); \ + __sync_synchronize(); \ + typeof(*ptr) old1, old2 = __sync_fetch_and_add(_ptr, 0); \ + do { \ + old1 = old2; \ + old2 = __sync_val_compare_and_swap(_ptr, old1, _val); \ + } while (old1 != old2); \ + __sync_synchronize(); \ + old2; \ }) #endif /* !HAVE___SYNC_SWAP */ -#define atomic_fetch_add_explicit(ptr, val, mem) \ - ({ __sync_synchronize(); \ - typeof(*ptr) rval = __sync_fetch_and_add((ptr), (val)); \ - __sync_synchronize(); rval; }) -#define atomic_fetch_sub_explicit(ptr, val, mem) \ - ({ __sync_synchronize(); \ - typeof(*ptr) rval = __sync_fetch_and_sub((ptr), (val)); \ - __sync_synchronize(); rval; }) - -#define atomic_compare_exchange_weak_explicit(atom, expect, desire, mem1, mem2) \ - ({ typeof(atom) _atom = (atom); typeof(expect) _expect = (expect); \ - typeof(desire) _desire = (desire); \ - __sync_synchronize(); \ - typeof(*atom) rval = __sync_val_compare_and_swap(_atom, *_expect, _desire); \ - __sync_synchronize(); \ - bool ret = (rval == *_expect); *_expect = rval; ret; }) +#define atomic_fetch_add_explicit(ptr, val, mem) \ + ({ \ + __sync_synchronize(); \ + typeof(*ptr) rval = __sync_fetch_and_add((ptr), (val)); \ + __sync_synchronize(); \ + rval; \ + }) +#define atomic_fetch_sub_explicit(ptr, val, mem) \ + ({ \ + __sync_synchronize(); \ + typeof(*ptr) rval = __sync_fetch_and_sub((ptr), (val)); \ + __sync_synchronize(); \ + rval; \ + }) + +#define atomic_compare_exchange_weak_explicit(atom, expect, desire, mem1, \ + mem2) \ + ({ \ + typeof(atom) _atom = (atom); \ + typeof(expect) _expect = (expect); \ + typeof(desire) _desire = (desire); \ + __sync_synchronize(); \ + typeof(*atom) rval = \ + __sync_val_compare_and_swap(_atom, *_expect, _desire); \ + __sync_synchronize(); \ + bool ret = (rval == *_expect); \ + *_expect = rval; \ + ret; \ + }) #else /* !HAVE___ATOMIC && !HAVE_STDATOMIC_H */ #error no atomic functions... diff --git a/lib/getopt.c b/lib/getopt.c index d0ee43510..71799c9b6 100644 --- a/lib/getopt.c +++ b/lib/getopt.c @@ -35,9 +35,9 @@ #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ -# ifndef const +#ifndef const # define const -# endif +#endif #endif #include @@ -52,10 +52,10 @@ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 -# include -# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +#include +#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION # define ELIDE_CODE -# endif +#endif #endif #ifndef ELIDE_CODE @@ -63,29 +63,29 @@ /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ -#ifdef __GNU_LIBRARY__ +#ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ -# include -# include -#endif /* GNU C library. */ +#include +#include +#endif /* GNU C library. */ #ifdef VMS -# include -# if HAVE_STRING_H - 0 -# include -# endif +#include +#if HAVE_STRING_H - 0 +#include +#endif #endif #ifndef _ /* This is for other GNU distributions with internationalized messages. When compiling libc, the _ macro is predefined. */ -# ifdef HAVE_LIBINTL_H -# include +#ifdef HAVE_LIBINTL_H +#include # define _(msgid) gettext (msgid) -# else +#else # define _(msgid) (msgid) -# endif +#endif #endif /* This version of `getopt' appears to the caller like standard Unix `getopt' @@ -182,48 +182,42 @@ int optopt = '?'; of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return -1 with `optind' != ARGC. */ -static enum -{ - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER -} ordering; +static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; -#ifdef __GNU_LIBRARY__ +#ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ -# include +#include # define my_index strchr #else -# if HAVE_STRING_H -# include -# else -# include -# endif +#if HAVE_STRING_H +#include +#else +#include +#endif /* Avoid depending on library functions or files whose names are inconsistent. */ #ifndef getenv -extern char *getenv (); +extern char *getenv(); #endif -static char * -my_index (str, chr) - const char *str; - int chr; +static char *my_index(str, chr) const char *str; +int chr; { - while (*str) - { - if (*str == chr) - return (char *) str; - str++; - } - return 0; + while (*str) { + if (*str == chr) + return (char *)str; + str++; + } + return 0; } /* If using GCC, we can safely declare strlen this way. @@ -231,11 +225,11 @@ my_index (str, chr) #ifdef __GNUC__ /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. That was relevant to code that was here before. */ -# if (!defined __STDC__ || !__STDC__) && !defined strlen +#if (!defined __STDC__ || !__STDC__) && !defined strlen /* gcc with -traditional declares the built-in strlen to return int, and has done so at least since version 2.4.5. -- rms. */ -extern int strlen (const char *); -# endif /* not __STDC__ */ +extern int strlen(const char *); +#endif /* not __STDC__ */ #endif /* __GNUC__ */ #endif /* not __GNU_LIBRARY__ */ @@ -265,29 +259,27 @@ static char *const *original_argv; /* Make sure the environment variable bash 2.0 puts in the environment is valid for the getopt call we must make sure that the ARGV passed to getopt is that one passed to the process. */ -static void -__attribute__ ((unused)) -store_args_and_env (int argc, char *const *argv) +static void __attribute__((unused)) +store_args_and_env(int argc, char *const *argv) { - /* XXX This is no good solution. We should rather copy the args so - that we can compare them later. But we must not use malloc(3). */ - original_argc = argc; - original_argv = argv; + /* XXX This is no good solution. We should rather copy the args so + that we can compare them later. But we must not use malloc(3). */ + original_argc = argc; + original_argv = argv; } -# ifdef text_set_element -text_set_element (__libc_subinit, store_args_and_env); -# endif /* text_set_element */ - -# define SWAP_FLAGS(ch1, ch2) \ - if (nonoption_flags_len > 0) \ - { \ - char __tmp = __getopt_nonoption_flags[ch1]; \ - __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ - __getopt_nonoption_flags[ch2] = __tmp; \ - } -#else /* !_LIBC */ +#ifdef text_set_element +text_set_element(__libc_subinit, store_args_and_env); +#endif /* text_set_element */ + +#define SWAP_FLAGS(ch1, ch2) \ + if (nonoption_flags_len > 0) { \ + char __tmp = __getopt_nonoption_flags[ch1]; \ + __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ + __getopt_nonoption_flags[ch2] = __tmp; \ + } +#else /* !_LIBC */ # define SWAP_FLAGS(ch1, ch2) -#endif /* _LIBC */ +#endif /* _LIBC */ /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) @@ -299,158 +291,147 @@ text_set_element (__libc_subinit, store_args_and_env); the new indices of the non-options in ARGV after they are moved. */ #if defined __STDC__ && __STDC__ -static void exchange (char **); +static void exchange(char **); #endif -static void -exchange (argv) - char **argv; +static void exchange(argv) char **argv; { - int bottom = first_nonopt; - int middle = last_nonopt; - int top = optind; - char *tem; + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; - /* Exchange the shorter segment with the far end of the longer segment. - That puts the shorter segment into the right place. - It leaves the longer segment in the right place overall, - but it consists of two parts that need to be swapped next. */ +/* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ #ifdef _LIBC - /* First make sure the handling of the `__getopt_nonoption_flags' - string can work normally. Our top argument must be in the range - of the string. */ - if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) - { - /* We must extend the array. The user plays games with us and - presents new arguments. */ - char *new_str = malloc (top + 1); - if (new_str == NULL) - nonoption_flags_len = nonoption_flags_max_len = 0; - else - { - memset (__mempcpy (new_str, __getopt_nonoption_flags, - nonoption_flags_max_len), - '\0', top + 1 - nonoption_flags_max_len); - nonoption_flags_max_len = top + 1; - __getopt_nonoption_flags = new_str; + /* First make sure the handling of the `__getopt_nonoption_flags' + string can work normally. Our top argument must be in the range + of the string. */ + if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) { + /* We must extend the array. The user plays games with us and + presents new arguments. */ + char *new_str = malloc(top + 1); + if (new_str == NULL) + nonoption_flags_len = nonoption_flags_max_len = 0; + else { + memset(__mempcpy(new_str, __getopt_nonoption_flags, + nonoption_flags_max_len), + '\0', top + 1 - nonoption_flags_max_len); + nonoption_flags_max_len = top + 1; + __getopt_nonoption_flags = new_str; + } } - } #endif - while (top > middle && middle > bottom) - { - if (top - middle > middle - bottom) - { - /* Bottom segment is the short one. */ - int len = middle - bottom; - register int i; - - /* Swap it with the top part of the top segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); - } - /* Exclude the moved bottom segment from further swapping. */ - top -= len; - } - else - { - /* Top segment is the short one. */ - int len = top - middle; - register int i; - - /* Swap it with the bottom part of the bottom segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - SWAP_FLAGS (bottom + i, middle + i); - } - /* Exclude the moved top segment from further swapping. */ - bottom += len; + while (top > middle && middle > bottom) { + if (top - middle > middle - bottom) { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) { + tem = argv[bottom + i]; + argv[bottom + i] = + argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + SWAP_FLAGS(bottom + i, + top - (middle - bottom) + i); + } + /* Exclude the moved bottom segment from further + * swapping. */ + top -= len; + } else { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. + */ + for (i = 0; i < len; i++) { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + SWAP_FLAGS(bottom + i, middle + i); + } + /* Exclude the moved top segment from further swapping. + */ + bottom += len; + } } - } - /* Update records for the slots the non-options now occupy. */ + /* Update records for the slots the non-options now occupy. */ - first_nonopt += (optind - last_nonopt); - last_nonopt = optind; + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; } /* Initialize the internal data when the first call is made. */ #if defined __STDC__ && __STDC__ -static const char *_getopt_initialize (int, char *const *, const char *); +static const char *_getopt_initialize(int, char *const *, const char *); #endif -static const char * -_getopt_initialize (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; +static const char *_getopt_initialize(argc, argv, optstring) int argc; +char *const *argv; +const char *optstring; { - /* Start processing options with ARGV-element 1 (since ARGV-element 0 - is the program name); the sequence of previously skipped - non-option ARGV-elements is empty. */ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ - first_nonopt = last_nonopt = optind; + first_nonopt = last_nonopt = optind; - nextchar = NULL; + nextchar = NULL; - posixly_correct = getenv ("POSIXLY_CORRECT"); + posixly_correct = getenv("POSIXLY_CORRECT"); - /* Determine how to handle the ordering of options and nonoptions. */ + /* Determine how to handle the ordering of options and nonoptions. */ - if (optstring[0] == '-') - { - ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - ordering = REQUIRE_ORDER; - ++optstring; - } - else if (posixly_correct != NULL) - ordering = REQUIRE_ORDER; - else - ordering = PERMUTE; + if (optstring[0] == '-') { + ordering = RETURN_IN_ORDER; + ++optstring; + } else if (optstring[0] == '+') { + ordering = REQUIRE_ORDER; + ++optstring; + } else if (posixly_correct != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; #ifdef _LIBC - if (posixly_correct == NULL - && argc == original_argc && argv == original_argv) - { - if (nonoption_flags_max_len == 0) - { - if (__getopt_nonoption_flags == NULL - || __getopt_nonoption_flags[0] == '\0') - nonoption_flags_max_len = -1; - else - { - const char *orig_str = __getopt_nonoption_flags; - int len = nonoption_flags_max_len = strlen (orig_str); - if (nonoption_flags_max_len < argc) - nonoption_flags_max_len = argc; - __getopt_nonoption_flags = - (char *) malloc (nonoption_flags_max_len); - if (__getopt_nonoption_flags == NULL) - nonoption_flags_max_len = -1; - else - memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), - '\0', nonoption_flags_max_len - len); - } - } - nonoption_flags_len = nonoption_flags_max_len; - } - else - nonoption_flags_len = 0; + if (posixly_correct == NULL && argc == original_argc + && argv == original_argv) { + if (nonoption_flags_max_len == 0) { + if (__getopt_nonoption_flags == NULL + || __getopt_nonoption_flags[0] == '\0') + nonoption_flags_max_len = -1; + else { + const char *orig_str = __getopt_nonoption_flags; + int len = nonoption_flags_max_len = + strlen(orig_str); + if (nonoption_flags_max_len < argc) + nonoption_flags_max_len = argc; + __getopt_nonoption_flags = + (char *)malloc(nonoption_flags_max_len); + if (__getopt_nonoption_flags == NULL) + nonoption_flags_max_len = -1; + else + memset(__mempcpy( + __getopt_nonoption_flags, + orig_str, len), + '\0', + nonoption_flags_max_len - len); + } + } + nonoption_flags_len = nonoption_flags_max_len; + } else + nonoption_flags_len = 0; #endif - return optstring; + return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters @@ -509,548 +490,536 @@ _getopt_initialize (argc, argv, optstring) If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ -int -_getopt_internal (argc, argv, optstring, longopts, longind, long_only) - int argc; - char *const *argv; - const char *optstring; - const struct option *longopts; - int *longind; - int long_only; +int _getopt_internal(argc, argv, optstring, longopts, longind, + long_only) int argc; +char *const *argv; +const char *optstring; +const struct option *longopts; +int *longind; +int long_only; { - optarg = NULL; - - if (optind == 0 || !__getopt_initialized) - { - if (optind == 0) - optind = 1; /* Don't scan ARGV[0], the program name. */ - optstring = _getopt_initialize (argc, argv, optstring); - __getopt_initialized = 1; - } - - /* Test whether ARGV[optind] points to a non-option argument. - Either it does not have option syntax, or there is an environment flag - from the shell indicating it is not an option. The later information - is only used when the used in the GNU libc. */ + optarg = NULL; + + if (optind == 0 || !__getopt_initialized) { + if (optind == 0) + optind = 1; /* Don't scan ARGV[0], the program name. */ + optstring = _getopt_initialize(argc, argv, optstring); + __getopt_initialized = 1; + } + +/* Test whether ARGV[optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ #ifdef _LIBC -# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ - || (optind < nonoption_flags_len \ - && __getopt_nonoption_flags[optind] == '1')) +#define NONOPTION_P \ + (argv[optind][0] != '-' || argv[optind][1] == '\0' \ + || (optind < nonoption_flags_len \ + && __getopt_nonoption_flags[optind] == '1')) #else # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') #endif - if (nextchar == NULL || *nextchar == '\0') - { - /* Advance to the next ARGV-element. */ + if (nextchar == NULL || *nextchar == '\0') { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has + been + moved back by the user (who may also have changed the + arguments). */ + if (last_nonopt > optind) + last_nonopt = optind; + if (first_nonopt > optind) + first_nonopt = optind; + + if (ordering == PERMUTE) { + /* If we have just processed some options following some + non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt + && last_nonopt != optind) + exchange((char **)argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options + and extend the range of non-options previously + skipped. */ + + while (optind < argc && NONOPTION_P) + optind++; + last_nonopt = optind; + } - /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been - moved back by the user (who may also have changed the arguments). */ - if (last_nonopt > optind) - last_nonopt = optind; - if (first_nonopt > optind) - first_nonopt = optind; + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an + option, + then skip everything else like a non-option. */ - if (ordering == PERMUTE) - { - /* If we have just processed some options following some non-options, - exchange them so that the options come first. */ + if (optind != argc && !strcmp(argv[optind], "--")) { + optind++; - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (last_nonopt != optind) - first_nonopt = optind; + if (first_nonopt != last_nonopt + && last_nonopt != optind) + exchange((char **)argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; - /* Skip any additional non-options - and extend the range of non-options previously skipped. */ + optind = argc; + } - while (optind < argc && NONOPTION_P) - optind++; - last_nonopt = optind; - } + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. + */ + + if (optind == argc) { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest + them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return -1; + } - /* The special ARGV-element `--' means premature end of options. - Skip it like a null option, - then exchange with previous non-options as if it were an option, - then skip everything else like a non-option. */ + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it + by. */ - if (optind != argc && !strcmp (argv[optind], "--")) - { - optind++; + if (NONOPTION_P) { + if (ordering == REQUIRE_ORDER) + return -1; + optarg = argv[optind++]; + return 1; + } - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (first_nonopt == last_nonopt) - first_nonopt = optind; - last_nonopt = argc; + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ - optind = argc; + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); } - /* If we have done all the ARGV-elements, stop the scan - and back over any non-options that we skipped and permuted. */ - - if (optind == argc) - { - /* Set the next-arg-index to point at the non-options - that we previously skipped, so the caller will digest them. */ - if (first_nonopt != last_nonopt) - optind = first_nonopt; - return -1; - } + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] + || !my_index(optstring, argv[optind][1]))))) { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; + p++, option_index++) + if (!strncmp(p->name, nextchar, nameend - nextchar)) { + if ((unsigned int)(nameend - nextchar) + == (unsigned int)strlen(p->name)) { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } else if (pfound == NULL) { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } else + /* Second or later nonexact match found. + */ + ambig = 1; + } + + if (ambig && !exact) { + if (opterr) + fprintf(stderr, + _("%s: option `%s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen(nextchar); + optind++; + optopt = 0; + return '?'; + } - /* If we have come to a non-option and did not permute it, - either stop the scan or describe it to the caller and pass it by. */ + if (pfound != NULL) { + option_index = indfound; + optind++; + if (*nameend) { + /* Don't test has_arg with >, because some C + compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else { + if (opterr) { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf(stderr, + _("%s: option `--%s' doesn't allow an argument\n"), + argv[0], + pfound->name); + else + /* +option or -option */ + fprintf(stderr, + _("%s: option `%c%s' doesn't allow an argument\n"), + argv[0], + argv[optind - 1] + [0], + pfound->name); + } + + nextchar += strlen(nextchar); + + optopt = pfound->val; + return '?'; + } + } else if (pfound->has_arg == 1) { + if (optind < argc) + optarg = argv[optind++]; + else { + if (opterr) + fprintf(stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], + argv[optind - 1]); + nextchar += strlen(nextchar); + optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen(nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } - if (NONOPTION_P) - { - if (ordering == REQUIRE_ORDER) - return -1; - optarg = argv[optind++]; - return 1; + /* Can't find it as a long option. If this is not + getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' + || my_index(optstring, *nextchar) == NULL) { + if (opterr) { + if (argv[optind][1] == '-') + /* --option */ + fprintf(stderr, + _("%s: unrecognized option `--%s'\n"), + argv[0], nextchar); + else + /* +option or -option */ + fprintf(stderr, + _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[optind][0], + nextchar); + } + nextchar = (char *)""; + optind++; + optopt = 0; + return '?'; + } } - /* We have found another option-ARGV-element. - Skip the initial punctuation. */ - - nextchar = (argv[optind] + 1 - + (longopts != NULL && argv[optind][1] == '-')); - } - - /* Decode the current option-ARGV-element. */ - - /* Check whether the ARGV-element is a long option. - - If long_only and the ARGV-element has the form "-f", where f is - a valid short option, don't consider it an abbreviated form of - a long option that starts with f. Otherwise there would be no - way to give the -f short option. - - On the other hand, if there's a long option "fubar" and - the ARGV-element is "-fu", do consider that an abbreviation of - the long option, just like "--fu", and not "-f" with arg "u". - - This distinction seems to be the most useful approach. */ - - if (longopts != NULL - && (argv[optind][1] == '-' - || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = -1; - int option_index; - - for (nameend = nextchar; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) - { - if ((unsigned int) (nameend - nextchar) - == (unsigned int) strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - - if (ambig && !exact) - { - if (opterr) - fprintf (stderr, _("%s: option `%s' is ambiguous\n"), - argv[0], argv[optind]); - nextchar += strlen (nextchar); - optind++; - optopt = 0; - return '?'; - } + /* Look at and handle the next short option-character. */ - if (pfound != NULL) { - option_index = indfound; - optind++; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - optarg = nameend + 1; - else - { - if (opterr) - { - if (argv[optind - 1][1] == '-') - /* --option */ - fprintf (stderr, - _("%s: option `--%s' doesn't allow an argument\n"), - argv[0], pfound->name); - else - /* +option or -option */ - fprintf (stderr, - _("%s: option `%c%s' doesn't allow an argument\n"), - argv[0], argv[optind - 1][0], pfound->name); - } - - nextchar += strlen (nextchar); - - optopt = pfound->val; - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (opterr) - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); - nextchar += strlen (nextchar); - optopt = pfound->val; - return optstring[0] == ':' ? ':' : '?'; + char c = *nextchar++; + char *temp = my_index(optstring, c); + + /* Increment `optind' when we start to process its last + * character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') { + if (opterr) { + if (posixly_correct) + /* 1003.2 specifies the format of this + * message. */ + fprintf(stderr, + _("%s: illegal option -- %c\n"), + argv[0], c); + else + fprintf(stderr, + _("%s: invalid option -- %c\n"), + argv[0], c); + } + optopt = c; + return '?'; } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - - /* Can't find it as a long option. If this is not getopt_long_only, - or the option starts with '--' or is not a valid short - option, then it's an error. - Otherwise interpret it as a short option. */ - if (!long_only || argv[optind][1] == '-' - || my_index (optstring, *nextchar) == NULL) - { - if (opterr) - { - if (argv[optind][1] == '-') - /* --option */ - fprintf (stderr, _("%s: unrecognized option `--%s'\n"), - argv[0], nextchar); - else - /* +option or -option */ - fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), - argv[0], argv[optind][0], nextchar); - } - nextchar = (char *) ""; - optind++; - optopt = 0; - return '?'; - } - } - - /* Look at and handle the next short option-character. */ - - { - char c = *nextchar++; - char *temp = my_index (optstring, c); - - /* Increment `optind' when we start to process its last character. */ - if (*nextchar == '\0') - ++optind; - - if (temp == NULL || c == ':') - { - if (opterr) - { - if (posixly_correct) - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, _("%s: illegal option -- %c\n"), - argv[0], c); - else - fprintf (stderr, _("%s: invalid option -- %c\n"), - argv[0], c); - } - optopt = c; - return '?'; - } - /* Convenience. Treat POSIX -W foo same as long option --foo */ - if (temp[0] == 'W' && temp[1] == ';') - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = 0; - int option_index; - - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (opterr) - { - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, _("%s: option requires an argument -- %c\n"), - argv[0], c); - } - optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - return c; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - - /* optarg is now the argument, see if it's in the - table of longopts. */ - - for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) - { - if ((unsigned int) (nameend - nextchar) == strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';') { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if (*nextchar != '\0') { + optarg = nextchar; + /* If we end this ARGV-element by taking the + rest as an arg, + we must advance to the next element now. */ + optind++; + } else if (optind == argc) { + if (opterr) { + /* 1003.2 specifies the format of this + * message. */ + fprintf(stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt + as argument. */ + optarg = argv[optind++]; + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for (nextchar = nameend = optarg; + *nameend && *nameend != '='; nameend++) + /* Do nothing. */; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; + p++, option_index++) + if (!strncmp(p->name, nextchar, + nameend - nextchar)) { + if ((unsigned int)(nameend - nextchar) + == strlen(p->name)) { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } else if (pfound == NULL) { + /* First nonexact match found. + */ + pfound = p; + indfound = option_index; + } else + /* Second or later nonexact + * match found. */ + ambig = 1; + } + if (ambig && !exact) { + if (opterr) + fprintf(stderr, + _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen(nextchar); + optind++; + return '?'; + } + if (pfound != NULL) { + option_index = indfound; + if (*nameend) { + /* Don't test has_arg with >, because + some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else { + if (opterr) + fprintf(stderr, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], + pfound->name); + + nextchar += strlen(nextchar); + return '?'; + } + } else if (pfound->has_arg == 1) { + if (optind < argc) + optarg = argv[optind++]; + else { + if (opterr) + fprintf(stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], + argv[optind + - 1]); + nextchar += strlen(nextchar); + return optstring[0] == ':' + ? ':' + : '?'; + } + } + nextchar += strlen(nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + nextchar = NULL; + return 'W'; /* Let the application handle it. */ } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; + if (temp[1] == ':') { + if (temp[2] == ':') { + /* This is an option that accepts an argument + * optionally. */ + if (*nextchar != '\0') { + optarg = nextchar; + optind++; + } else + optarg = NULL; + nextchar = NULL; + } else { + /* This is an option that requires an argument. + */ + if (*nextchar != '\0') { + optarg = nextchar; + /* If we end this ARGV-element by taking + the rest as an arg, + we must advance to the next element + now. */ + optind++; + } else if (optind == argc) { + if (opterr) { + /* 1003.2 specifies the format + * of this message. */ + fprintf(stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } else + /* We already incremented `optind' once; + increment it again when taking next + ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - if (ambig && !exact) - { - if (opterr) - fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), - argv[0], argv[optind]); - nextchar += strlen (nextchar); - optind++; - return '?'; - } - if (pfound != NULL) - { - option_index = indfound; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - optarg = nameend + 1; - else - { - if (opterr) - fprintf (stderr, _("\ -%s: option `-W %s' doesn't allow an argument\n"), - argv[0], pfound->name); - - nextchar += strlen (nextchar); - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (opterr) - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); - nextchar += strlen (nextchar); - return optstring[0] == ':' ? ':' : '?'; - } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - nextchar = NULL; - return 'W'; /* Let the application handle it. */ - } - if (temp[1] == ':') - { - if (temp[2] == ':') - { - /* This is an option that accepts an argument optionally. */ - if (*nextchar != '\0') - { - optarg = nextchar; - optind++; - } - else - optarg = NULL; - nextchar = NULL; - } - else - { - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (opterr) - { - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, - _("%s: option requires an argument -- %c\n"), - argv[0], c); - } - optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - nextchar = NULL; - } - } - return c; - } + return c; + } } #ifdef REALLY_NEED_PLAIN_GETOPT -int -getopt (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; +int getopt(argc, argv, optstring) int argc; +char *const *argv; +const char *optstring; { - return _getopt_internal (argc, argv, optstring, - (const struct option *) 0, - (int *) 0, - 0); + return _getopt_internal(argc, argv, optstring, (const struct option *)0, + (int *)0, 0); } #endif /* REALLY_NEED_PLAIN_GETOPT */ -#endif /* Not ELIDE_CODE. */ +#endif /* Not ELIDE_CODE. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ -int -main (argc, argv) - int argc; - char **argv; +int main(argc, argv) int argc; +char **argv; { - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - - c = getopt (argc, argv, "abc:d:0123456789"); - if (c == -1) - break; - - switch (c) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); + int c; + int digit_optind = 0; + + while (1) { + int this_option_optind = optind ? optind : 1; + + c = getopt(argc, argv, "abc:d:0123456789"); + if (c == -1) + break; + + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 + && digit_optind != this_option_optind) + printf("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf("option %c\n", c); + break; + + case 'a': + printf("option a\n"); + break; + + case 'b': + printf("option b\n"); + break; + + case 'c': + printf("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf("?? getopt returned character code 0%o ??\n", c); + } } - } - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } + if (optind < argc) { + printf("non-option ARGV-elements: "); + while (optind < argc) + printf("%s ", argv[optind++]); + printf("\n"); + } - exit (0); + exit(0); } #endif /* TEST */ diff --git a/lib/getopt.h b/lib/getopt.h index cc38a45c2..138870d19 100644 --- a/lib/getopt.h +++ b/lib/getopt.h @@ -34,7 +34,7 @@ * to use the system version. */ -#ifdef __cplusplus +#ifdef __cplusplus extern "C" { #endif @@ -90,18 +90,17 @@ extern int optopt; one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ -struct option -{ -#if defined (__STDC__) && __STDC__ - const char *name; +struct option { +#if defined(__STDC__) && __STDC__ + const char *name; #else - char *name; + char *name; #endif - /* has_arg can't be an enum because some compilers complain about - type mismatches in all the code that assumes it is an int. */ - int has_arg; - int *flag; - int val; + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ @@ -110,7 +109,7 @@ struct option #define required_argument 1 #define optional_argument 2 -#if defined (__STDC__) && __STDC__ +#if defined(__STDC__) && __STDC__ #if REALLY_NEED_PLAIN_GETOPT @@ -120,39 +119,37 @@ struct option * should be written to define NONPOSIX_GETOPT_DEFINITION. */ #ifndef NONPOSIX_GETOPT_DEFINITION -extern int getopt (int argc, char *const *argv, const char *shortopts); -#else /* NONPOSIX_GETOPT_DEFINITION */ -extern int getopt (void); +extern int getopt(int argc, char *const *argv, const char *shortopts); +#else /* NONPOSIX_GETOPT_DEFINITION */ +extern int getopt(void); #endif /* NONPOSIX_GETOPT_DEFINITION */ #endif -extern int getopt_long (int argc, char *const *argv, const char *shortopts, - const struct option *longopts, int *longind); -extern int getopt_long_only (int argc, char *const *argv, - const char *shortopts, - const struct option *longopts, int *longind); +extern int getopt_long(int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); +extern int getopt_long_only(int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); /* Internal only. Users should not call this directly. */ -extern int _getopt_internal (int argc, char *const *argv, - const char *shortopts, - const struct option *longopts, int *longind, - int long_only); +extern int _getopt_internal(int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind, + int long_only); #else /* not __STDC__ */ #ifdef REALLY_NEED_PLAIN_GETOPT -extern int getopt (); +extern int getopt(); #endif /* REALLY_NEED_PLAIN_GETOPT */ -extern int getopt_long (); -extern int getopt_long_only (); +extern int getopt_long(); +extern int getopt_long_only(); -extern int _getopt_internal (); +extern int _getopt_internal(); #endif /* __STDC__ */ -#ifdef __cplusplus +#ifdef __cplusplus } #endif diff --git a/lib/getopt1.c b/lib/getopt1.c index 1873a197e..a7fe25307 100644 --- a/lib/getopt1.c +++ b/lib/getopt1.c @@ -58,19 +58,18 @@ #include #endif -#ifndef NULL +#ifndef NULL #define NULL 0 #endif -int -getopt_long (argc, argv, options, long_options, opt_index) - int argc; - char *const *argv; - const char *options; - const struct option *long_options; - int *opt_index; +int getopt_long(argc, argv, options, long_options, opt_index) int argc; +char *const *argv; +const char *options; +const struct option *long_options; +int *opt_index; { - return _getopt_internal (argc, argv, options, long_options, opt_index, 0); + return _getopt_internal(argc, argv, options, long_options, opt_index, + 0); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. @@ -78,110 +77,100 @@ getopt_long (argc, argv, options, long_options, opt_index) but does match a short option, it is parsed as a short option instead. */ -int -getopt_long_only (argc, argv, options, long_options, opt_index) - int argc; - char *const *argv; - const char *options; - const struct option *long_options; - int *opt_index; +int getopt_long_only(argc, argv, options, long_options, opt_index) int argc; +char *const *argv; +const char *options; +const struct option *long_options; +int *opt_index; { - return _getopt_internal (argc, argv, options, long_options, opt_index, 1); + return _getopt_internal(argc, argv, options, long_options, opt_index, + 1); } -#endif /* Not ELIDE_CODE. */ +#endif /* Not ELIDE_CODE. */ #ifdef TEST #include -int -main (argc, argv) - int argc; - char **argv; +int main(argc, argv) int argc; +char **argv; { - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - int option_index = 0; - static struct option long_options[] = - { - {"add", 1, 0, 0}, - {"append", 0, 0, 0}, - {"delete", 1, 0, 0}, - {"verbose", 0, 0, 0}, - {"create", 0, 0, 0}, - {"file", 1, 0, 0}, - {0, 0, 0, 0} - }; - - c = getopt_long (argc, argv, "abc:d:0123456789", - long_options, &option_index); - if (c == -1) - break; - - switch (c) - { - case 0: - printf ("option %s", long_options[option_index].name); - if (optarg) - printf (" with arg %s", optarg); - printf ("\n"); - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case 'd': - printf ("option d with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); + int c; + int digit_optind = 0; + + while (1) { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = { + {"add", 1, 0, 0}, {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, {"file", 1, 0, 0}, + {0, 0, 0, 0}}; + + c = getopt_long(argc, argv, "abc:d:0123456789", long_options, + &option_index); + if (c == -1) + break; + + switch (c) { + case 0: + printf("option %s", long_options[option_index].name); + if (optarg) + printf(" with arg %s", optarg); + printf("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 + && digit_optind != this_option_optind) + printf("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf("option %c\n", c); + break; + + case 'a': + printf("option a\n"); + break; + + case 'b': + printf("option b\n"); + break; + + case 'c': + printf("option c with value `%s'\n", optarg); + break; + + case 'd': + printf("option d with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf("?? getopt returned character code 0%o ??\n", c); + } } - } - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } + if (optind < argc) { + printf("non-option ARGV-elements: "); + while (optind < argc) + printf("%s ", argv[optind++]); + printf("\n"); + } - exit (0); + exit(0); } #endif /* TEST */ diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c index 9f4c071ab..8dd8d2e2b 100644 --- a/lib/grammar_sandbox.c +++ b/lib/grammar_sandbox.c @@ -36,25 +36,24 @@ DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command desc") #define MAXDEPTH 64 /** headers **/ -void -grammar_sandbox_init (void); -void -pretty_print_graph (struct vty *vty, struct graph_node *, int, int, struct graph_node **, size_t); -static void -pretty_print_dot (FILE *ofd, unsigned opts, struct graph_node *start, - struct graph_node **stack, size_t stackpos, - struct graph_node **visited, size_t *visitpos); -void -init_cmdgraph (struct vty *, struct graph **); +void grammar_sandbox_init(void); +void pretty_print_graph(struct vty *vty, struct graph_node *, int, int, + struct graph_node **, size_t); +static void pretty_print_dot(FILE *ofd, unsigned opts, struct graph_node *start, + struct graph_node **stack, size_t stackpos, + struct graph_node **visited, size_t *visitpos); +void init_cmdgraph(struct vty *, struct graph **); /** shim interface commands **/ struct graph *nodegraph = NULL, *nodegraph_free = NULL; -#define check_nodegraph() \ - do { if (!nodegraph) { \ - vty_out(vty, "nodegraph not initialized\n"); \ - return CMD_WARNING; \ - } } while (0) +#define check_nodegraph() \ + do { \ + if (!nodegraph) { \ + vty_out(vty, "nodegraph not initialized\n"); \ + return CMD_WARNING; \ + } \ + } while (0) DEFUN (grammar_test, grammar_test_cmd, @@ -63,27 +62,30 @@ DEFUN (grammar_test, "parse a command\n" "command to pass to new parser\n") { - check_nodegraph(); - - int idx_command = 2; - // make a string from tokenized command line - char *command = argv_concat (argv, argc, idx_command); - - // create cmd_element for parser - struct cmd_element *cmd = XCALLOC (MTYPE_CMD_TOKENS, sizeof (struct cmd_element)); - cmd->string = command; - cmd->doc = "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n"; - cmd->func = NULL; - - // parse the command and install it into the command graph - struct graph *graph = graph_new(); - struct cmd_token *token = cmd_token_new (START_TKN, CMD_ATTR_NORMAL, NULL, NULL); - graph_new_node (graph, token, (void (*)(void *)) &cmd_token_del); - - cmd_graph_parse (graph, cmd); - cmd_graph_merge (nodegraph, graph, +1); - - return CMD_SUCCESS; + check_nodegraph(); + + int idx_command = 2; + // make a string from tokenized command line + char *command = argv_concat(argv, argc, idx_command); + + // create cmd_element for parser + struct cmd_element *cmd = + XCALLOC(MTYPE_CMD_TOKENS, sizeof(struct cmd_element)); + cmd->string = command; + cmd->doc = + "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n"; + cmd->func = NULL; + + // parse the command and install it into the command graph + struct graph *graph = graph_new(); + struct cmd_token *token = + cmd_token_new(START_TKN, CMD_ATTR_NORMAL, NULL, NULL); + graph_new_node(graph, token, (void (*)(void *)) & cmd_token_del); + + cmd_graph_parse(graph, cmd); + cmd_graph_merge(nodegraph, graph, +1); + + return CMD_SUCCESS; } DEFUN (grammar_test_complete, @@ -93,57 +95,57 @@ DEFUN (grammar_test_complete, "attempt to complete input on DFA\n" "command to complete\n") { - check_nodegraph(); - - int idx_command = 2; - char *cmdstr = argv_concat (argv, argc, idx_command); - if (!cmdstr) - return CMD_SUCCESS; - - vector command = cmd_make_strvec (cmdstr); - if (!command) - { - XFREE (MTYPE_TMP, cmdstr); - return CMD_SUCCESS; - } - - // generate completions of user input - struct list *completions; - enum matcher_rv result = command_complete (nodegraph, command, &completions); - - // print completions or relevant error message - if (!MATCHER_ERROR(result)) - { - vector comps = completions_to_vec (completions); - struct cmd_token *tkn; - - // calculate length of longest tkn->text in completions - unsigned int width = 0, i = 0; - for (i = 0; i < vector_active (comps); i++) { - tkn = vector_slot (comps, i); - unsigned int len = strlen (tkn->text); - width = len > width ? len : width; - } - - // print completions - for (i = 0; i < vector_active (comps); i++) { - tkn = vector_slot (comps, i); - vty_out (vty, " %-*s %s\n", width, tkn->text, tkn->desc); - } - - for (i = 0; i < vector_active (comps); i++) - cmd_token_del ((struct cmd_token *) vector_slot (comps, i)); - vector_free (comps); - } - else - vty_out (vty, "%% No match\n"); - - // free resources - list_delete (completions); - cmd_free_strvec (command); - XFREE (MTYPE_TMP, cmdstr); - - return CMD_SUCCESS; + check_nodegraph(); + + int idx_command = 2; + char *cmdstr = argv_concat(argv, argc, idx_command); + if (!cmdstr) + return CMD_SUCCESS; + + vector command = cmd_make_strvec(cmdstr); + if (!command) { + XFREE(MTYPE_TMP, cmdstr); + return CMD_SUCCESS; + } + + // generate completions of user input + struct list *completions; + enum matcher_rv result = + command_complete(nodegraph, command, &completions); + + // print completions or relevant error message + if (!MATCHER_ERROR(result)) { + vector comps = completions_to_vec(completions); + struct cmd_token *tkn; + + // calculate length of longest tkn->text in completions + unsigned int width = 0, i = 0; + for (i = 0; i < vector_active(comps); i++) { + tkn = vector_slot(comps, i); + unsigned int len = strlen(tkn->text); + width = len > width ? len : width; + } + + // print completions + for (i = 0; i < vector_active(comps); i++) { + tkn = vector_slot(comps, i); + vty_out(vty, " %-*s %s\n", width, tkn->text, + tkn->desc); + } + + for (i = 0; i < vector_active(comps); i++) + cmd_token_del( + (struct cmd_token *)vector_slot(comps, i)); + vector_free(comps); + } else + vty_out(vty, "%% No match\n"); + + // free resources + list_delete(completions); + cmd_free_strvec(command); + XFREE(MTYPE_TMP, cmdstr); + + return CMD_SUCCESS; } DEFUN (grammar_test_match, @@ -153,62 +155,60 @@ DEFUN (grammar_test_match, "attempt to match input on DFA\n" "command to match\n") { - check_nodegraph(); - - int idx_command = 2; - if (argv[2]->arg[0] == '#') - return CMD_SUCCESS; - - char *cmdstr = argv_concat(argv, argc, idx_command); - if (!cmdstr) - return CMD_SUCCESS; - vector command = cmd_make_strvec (cmdstr); - if (!command) - { - XFREE (MTYPE_TMP, cmdstr); - return CMD_SUCCESS; - } - - struct list *argvv = NULL; - const struct cmd_element *element = NULL; - enum matcher_rv result = command_match (nodegraph, command, &argvv, &element); - - // print completions or relevant error message - if (element) - { - vty_out (vty, "Matched: %s\n", element->string); - struct listnode *ln; - struct cmd_token *token; - for (ALL_LIST_ELEMENTS_RO(argvv,ln,token)) - vty_out (vty, "%s -- %s\n", token->text, token->arg); - - vty_out (vty, "func: %p\n", element->func); - - list_delete (argvv); - } - else { - assert(MATCHER_ERROR(result)); - switch (result) { - case MATCHER_NO_MATCH: - vty_out (vty, "%% Unknown command\n"); - break; - case MATCHER_INCOMPLETE: - vty_out (vty, "%% Incomplete command\n"); - break; - case MATCHER_AMBIGUOUS: - vty_out (vty, "%% Ambiguous command\n"); - break; - default: - vty_out (vty, "%% Unknown error\n"); - break; - } - } - - // free resources - cmd_free_strvec (command); - XFREE (MTYPE_TMP, cmdstr); - - return CMD_SUCCESS; + check_nodegraph(); + + int idx_command = 2; + if (argv[2]->arg[0] == '#') + return CMD_SUCCESS; + + char *cmdstr = argv_concat(argv, argc, idx_command); + if (!cmdstr) + return CMD_SUCCESS; + vector command = cmd_make_strvec(cmdstr); + if (!command) { + XFREE(MTYPE_TMP, cmdstr); + return CMD_SUCCESS; + } + + struct list *argvv = NULL; + const struct cmd_element *element = NULL; + enum matcher_rv result = + command_match(nodegraph, command, &argvv, &element); + + // print completions or relevant error message + if (element) { + vty_out(vty, "Matched: %s\n", element->string); + struct listnode *ln; + struct cmd_token *token; + for (ALL_LIST_ELEMENTS_RO(argvv, ln, token)) + vty_out(vty, "%s -- %s\n", token->text, token->arg); + + vty_out(vty, "func: %p\n", element->func); + + list_delete(argvv); + } else { + assert(MATCHER_ERROR(result)); + switch (result) { + case MATCHER_NO_MATCH: + vty_out(vty, "%% Unknown command\n"); + break; + case MATCHER_INCOMPLETE: + vty_out(vty, "%% Incomplete command\n"); + break; + case MATCHER_AMBIGUOUS: + vty_out(vty, "%% Ambiguous command\n"); + break; + default: + vty_out(vty, "%% Unknown error\n"); + break; + } + } + + // free resources + cmd_free_strvec(command); + XFREE(MTYPE_TMP, cmdstr); + + return CMD_SUCCESS; } /** @@ -221,30 +221,33 @@ DEFUN (grammar_test_doc, "Test function for docstring\n" "Command end\n") { - check_nodegraph(); - - // create cmd_element with docstring - struct cmd_element *cmd = XCALLOC (MTYPE_CMD_TOKENS, sizeof (struct cmd_element)); - cmd->string = XSTRDUP (MTYPE_CMD_TOKENS, "test docstring (1-255) end VARIABLE [OPTION|set lol] . VARARG"); - cmd->doc = XSTRDUP (MTYPE_CMD_TOKENS, - "Test stuff\n" - "docstring thing\n" - "first example\n" - "second example\n" - "follow\n" - "random range\n" - "end thingy\n" - "variable\n" - "optional variable\n" - "optional set\n" - "optional lol\n" - "vararg!\n"); - cmd->func = NULL; - - // parse element - cmd_graph_parse (nodegraph, cmd); - - return CMD_SUCCESS; + check_nodegraph(); + + // create cmd_element with docstring + struct cmd_element *cmd = + XCALLOC(MTYPE_CMD_TOKENS, sizeof(struct cmd_element)); + cmd->string = XSTRDUP( + MTYPE_CMD_TOKENS, + "test docstring (1-255) end VARIABLE [OPTION|set lol] . VARARG"); + cmd->doc = XSTRDUP(MTYPE_CMD_TOKENS, + "Test stuff\n" + "docstring thing\n" + "first example\n" + "second example\n" + "follow\n" + "random range\n" + "end thingy\n" + "variable\n" + "optional variable\n" + "optional set\n" + "optional lol\n" + "vararg!\n"); + cmd->func = NULL; + + // parse element + cmd_graph_parse(nodegraph, cmd); + + return CMD_SUCCESS; } /** @@ -257,11 +260,12 @@ DEFUN (grammar_test_show, "print current accumulated DFA\n" "include docstrings\n") { - check_nodegraph(); + check_nodegraph(); - struct graph_node *stack[MAXDEPTH]; - pretty_print_graph (vty, vector_slot (nodegraph->nodes, 0), 0, argc >= 3, stack, 0); - return CMD_SUCCESS; + struct graph_node *stack[MAXDEPTH]; + pretty_print_graph(vty, vector_slot(nodegraph->nodes, 0), 0, argc >= 3, + stack, 0); + return CMD_SUCCESS; } DEFUN (grammar_test_dot, @@ -271,102 +275,93 @@ DEFUN (grammar_test_dot, "print current graph for dot\n" ".dot filename\n") { - check_nodegraph(); - - struct graph_node *stack[MAXDEPTH]; - struct graph_node *visited[MAXDEPTH*MAXDEPTH]; - size_t vpos = 0; - - FILE *ofd = fopen(argv[2]->arg, "w"); - if (!ofd) { - vty_out(vty, "%s: %s\r\n", argv[2]->arg, strerror(errno)); - return CMD_SUCCESS; - } - - fprintf(ofd, "digraph {\n graph [ rankdir = LR ];\n node [ fontname = \"Fira Mono\", fontsize = 9 ];\n\n"); - pretty_print_dot (ofd, 0, - vector_slot (nodegraph->nodes, 0), - stack, 0, visited, &vpos); - fprintf(ofd, "}\n"); - fclose(ofd); - return CMD_SUCCESS; + check_nodegraph(); + + struct graph_node *stack[MAXDEPTH]; + struct graph_node *visited[MAXDEPTH * MAXDEPTH]; + size_t vpos = 0; + + FILE *ofd = fopen(argv[2]->arg, "w"); + if (!ofd) { + vty_out(vty, "%s: %s\r\n", argv[2]->arg, strerror(errno)); + return CMD_SUCCESS; + } + + fprintf(ofd, + "digraph {\n graph [ rankdir = LR ];\n node [ fontname = \"Fira Mono\", fontsize = 9 ];\n\n"); + pretty_print_dot(ofd, 0, vector_slot(nodegraph->nodes, 0), stack, 0, + visited, &vpos); + fprintf(ofd, "}\n"); + fclose(ofd); + return CMD_SUCCESS; } -struct cmd_permute_item -{ - char *cmd; - struct cmd_element *el; +struct cmd_permute_item { + char *cmd; + struct cmd_element *el; }; -static void -cmd_permute_free (void *arg) +static void cmd_permute_free(void *arg) { - struct cmd_permute_item *i = arg; - XFREE (MTYPE_TMP, i->cmd); - XFREE (MTYPE_TMP, i); + struct cmd_permute_item *i = arg; + XFREE(MTYPE_TMP, i->cmd); + XFREE(MTYPE_TMP, i); } -static int -cmd_permute_cmp (void *a, void *b) +static int cmd_permute_cmp(void *a, void *b) { - struct cmd_permute_item *aa = a, *bb = b; - return strcmp (aa->cmd, bb->cmd); + struct cmd_permute_item *aa = a, *bb = b; + return strcmp(aa->cmd, bb->cmd); } -static void -cmd_graph_permute (struct list *out, struct graph_node **stack, - size_t stackpos, char *cmd) +static void cmd_graph_permute(struct list *out, struct graph_node **stack, + size_t stackpos, char *cmd) { - struct graph_node *gn = stack[stackpos]; - struct cmd_token *tok = gn->data; - char *appendp = cmd + strlen(cmd); - size_t i, j; - - if (tok->type < SPECIAL_TKN) - { - sprintf (appendp, "%s ", tok->text); - appendp += strlen (appendp); - } - else if (tok->type == END_TKN) - { - struct cmd_permute_item *i = XMALLOC (MTYPE_TMP, sizeof (*i)); - i->el = ((struct graph_node *)vector_slot (gn->to, 0))->data; - i->cmd = XSTRDUP (MTYPE_TMP, cmd); - i->cmd[strlen(cmd) - 1] = '\0'; - listnode_add_sort (out, i); - return; - } - - if (++stackpos == MAXDEPTH) - return; - - for (i = 0; i < vector_active (gn->to); i++) - { - struct graph_node *gnext = vector_slot (gn->to, i); - for (j = 0; j < stackpos; j++) - if (stack[j] == gnext) - break; - if (j != stackpos) - continue; - - stack[stackpos] = gnext; - *appendp = '\0'; - cmd_graph_permute (out, stack, stackpos, cmd); - } + struct graph_node *gn = stack[stackpos]; + struct cmd_token *tok = gn->data; + char *appendp = cmd + strlen(cmd); + size_t i, j; + + if (tok->type < SPECIAL_TKN) { + sprintf(appendp, "%s ", tok->text); + appendp += strlen(appendp); + } else if (tok->type == END_TKN) { + struct cmd_permute_item *i = XMALLOC(MTYPE_TMP, sizeof(*i)); + i->el = ((struct graph_node *)vector_slot(gn->to, 0))->data; + i->cmd = XSTRDUP(MTYPE_TMP, cmd); + i->cmd[strlen(cmd) - 1] = '\0'; + listnode_add_sort(out, i); + return; + } + + if (++stackpos == MAXDEPTH) + return; + + for (i = 0; i < vector_active(gn->to); i++) { + struct graph_node *gnext = vector_slot(gn->to, i); + for (j = 0; j < stackpos; j++) + if (stack[j] == gnext) + break; + if (j != stackpos) + continue; + + stack[stackpos] = gnext; + *appendp = '\0'; + cmd_graph_permute(out, stack, stackpos, cmd); + } } -static struct list * -cmd_graph_permutations (struct graph *graph) +static struct list *cmd_graph_permutations(struct graph *graph) { - char accumulate[2048] = ""; - struct graph_node *stack[MAXDEPTH]; - - struct list *rv = list_new (); - rv->cmp = cmd_permute_cmp; - rv->del = cmd_permute_free; - stack[0] = vector_slot (graph->nodes, 0); - cmd_graph_permute (rv, stack, 0, accumulate); - return rv; + char accumulate[2048] = ""; + struct graph_node *stack[MAXDEPTH]; + + struct list *rv = list_new(); + rv->cmp = cmd_permute_cmp; + rv->del = cmd_permute_free; + stack[0] = vector_slot(graph->nodes, 0); + cmd_graph_permute(rv, stack, 0, accumulate); + return rv; } extern vector cmdvec; @@ -379,70 +374,67 @@ DEFUN (grammar_findambig, "Print all permutations\n" "Scan all nodes\n") { - struct list *commands; - struct cmd_permute_item *prev = NULL, *cur = NULL; - struct listnode *ln; - int i, printall, scan, scannode = 0; - int ambig = 0; - - i = 0; - printall = argv_find (argv, argc, "printall", &i); - i = 0; - scan = argv_find (argv, argc, "nodescan", &i); - - if (scan && nodegraph_free) - { - graph_delete_graph (nodegraph_free); - nodegraph_free = NULL; - } - - if (!scan && !nodegraph) - { - vty_out(vty, "nodegraph uninitialized\r\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - do { - if (scan) - { - struct cmd_node *cnode = vector_slot (cmdvec, scannode++); - if (!cnode) - continue; - nodegraph = cnode->cmdgraph; - if (!nodegraph) - continue; - vty_out (vty, "scanning node %d\n", scannode - 1); - } - - commands = cmd_graph_permutations (nodegraph); - prev = NULL; - for (ALL_LIST_ELEMENTS_RO (commands, ln, cur)) - { - int same = prev && !strcmp (prev->cmd, cur->cmd); - if (printall && !same) - vty_out (vty, "'%s' [%x]\n", cur->cmd, cur->el->daemon); - if (same) - { - vty_out (vty, "'%s' AMBIGUOUS:\n", cur->cmd); - vty_out (vty, " %s\n '%s'\n", prev->el->name, - prev->el->string); - vty_out (vty, " %s\n '%s'\n", cur->el->name, - cur->el->string); - vty_out (vty, "\n"); - ambig++; - } - prev = cur; - } - list_delete (commands); - - vty_out (vty, "\n"); - } while (scan && scannode < LINK_PARAMS_NODE); - - vty_out (vty, "%d ambiguous commands found.\n", ambig); - - if (scan) - nodegraph = NULL; - return ambig == 0 ? CMD_SUCCESS : CMD_WARNING_CONFIG_FAILED; + struct list *commands; + struct cmd_permute_item *prev = NULL, *cur = NULL; + struct listnode *ln; + int i, printall, scan, scannode = 0; + int ambig = 0; + + i = 0; + printall = argv_find(argv, argc, "printall", &i); + i = 0; + scan = argv_find(argv, argc, "nodescan", &i); + + if (scan && nodegraph_free) { + graph_delete_graph(nodegraph_free); + nodegraph_free = NULL; + } + + if (!scan && !nodegraph) { + vty_out(vty, "nodegraph uninitialized\r\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + do { + if (scan) { + struct cmd_node *cnode = + vector_slot(cmdvec, scannode++); + if (!cnode) + continue; + nodegraph = cnode->cmdgraph; + if (!nodegraph) + continue; + vty_out(vty, "scanning node %d\n", scannode - 1); + } + + commands = cmd_graph_permutations(nodegraph); + prev = NULL; + for (ALL_LIST_ELEMENTS_RO(commands, ln, cur)) { + int same = prev && !strcmp(prev->cmd, cur->cmd); + if (printall && !same) + vty_out(vty, "'%s' [%x]\n", cur->cmd, + cur->el->daemon); + if (same) { + vty_out(vty, "'%s' AMBIGUOUS:\n", cur->cmd); + vty_out(vty, " %s\n '%s'\n", prev->el->name, + prev->el->string); + vty_out(vty, " %s\n '%s'\n", cur->el->name, + cur->el->string); + vty_out(vty, "\n"); + ambig++; + } + prev = cur; + } + list_delete(commands); + + vty_out(vty, "\n"); + } while (scan && scannode < LINK_PARAMS_NODE); + + vty_out(vty, "%d ambiguous commands found.\n", ambig); + + if (scan) + nodegraph = NULL; + return ambig == 0 ? CMD_SUCCESS : CMD_WARNING_CONFIG_FAILED; } DEFUN (grammar_init_graph, @@ -451,12 +443,12 @@ DEFUN (grammar_init_graph, GRAMMAR_STR "(re)initialize graph\n") { - if (nodegraph_free) - graph_delete_graph (nodegraph_free); - nodegraph_free = NULL; + if (nodegraph_free) + graph_delete_graph(nodegraph_free); + nodegraph_free = NULL; - init_cmdgraph (vty, &nodegraph); - return CMD_SUCCESS; + init_cmdgraph(vty, &nodegraph); + return CMD_SUCCESS; } DEFUN (grammar_access, @@ -466,55 +458,53 @@ DEFUN (grammar_access, "access node graph\n" "node number\n") { - if (nodegraph_free) - graph_delete_graph (nodegraph_free); - nodegraph_free = NULL; - - struct cmd_node *cnode; - - cnode = vector_slot (cmdvec, atoi (argv[2]->arg)); - if (!cnode) - { - vty_out (vty, "%% no such node\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - vty_out (vty, "node %d\n", (int)cnode->node); - nodegraph = cnode->cmdgraph; - return CMD_SUCCESS; + if (nodegraph_free) + graph_delete_graph(nodegraph_free); + nodegraph_free = NULL; + + struct cmd_node *cnode; + + cnode = vector_slot(cmdvec, atoi(argv[2]->arg)); + if (!cnode) { + vty_out(vty, "%% no such node\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + vty_out(vty, "node %d\n", (int)cnode->node); + nodegraph = cnode->cmdgraph; + return CMD_SUCCESS; } /* this is called in vtysh.c to set up the testing shim */ -void grammar_sandbox_init(void) { - // install all enable elements - install_element (ENABLE_NODE, &grammar_test_cmd); - install_element (ENABLE_NODE, &grammar_test_show_cmd); - install_element (ENABLE_NODE, &grammar_test_dot_cmd); - install_element (ENABLE_NODE, &grammar_test_match_cmd); - install_element (ENABLE_NODE, &grammar_test_complete_cmd); - install_element (ENABLE_NODE, &grammar_test_doc_cmd); - install_element (ENABLE_NODE, &grammar_findambig_cmd); - install_element (ENABLE_NODE, &grammar_init_graph_cmd); - install_element (ENABLE_NODE, &grammar_access_cmd); +void grammar_sandbox_init(void) +{ + // install all enable elements + install_element(ENABLE_NODE, &grammar_test_cmd); + install_element(ENABLE_NODE, &grammar_test_show_cmd); + install_element(ENABLE_NODE, &grammar_test_dot_cmd); + install_element(ENABLE_NODE, &grammar_test_match_cmd); + install_element(ENABLE_NODE, &grammar_test_complete_cmd); + install_element(ENABLE_NODE, &grammar_test_doc_cmd); + install_element(ENABLE_NODE, &grammar_findambig_cmd); + install_element(ENABLE_NODE, &grammar_init_graph_cmd); + install_element(ENABLE_NODE, &grammar_access_cmd); } #define item(x) { x, #x } -struct message tokennames[] = { - item(WORD_TKN), // words - item(VARIABLE_TKN), // almost anything - item(RANGE_TKN), // integer range - item(IPV4_TKN), // IPV4 addresses - item(IPV4_PREFIX_TKN), // IPV4 network prefixes - item(IPV6_TKN), // IPV6 prefixes - item(IPV6_PREFIX_TKN), // IPV6 network prefixes - - /* plumbing types */ - item(FORK_TKN), - item(JOIN_TKN), - item(START_TKN), // first token in line - item(END_TKN), // last token in line - { 0 } -}; +struct message tokennames[] = {item(WORD_TKN), // words + item(VARIABLE_TKN), // almost anything + item(RANGE_TKN), // integer range + item(IPV4_TKN), // IPV4 addresses + item(IPV4_PREFIX_TKN), // IPV4 network prefixes + item(IPV6_TKN), // IPV6 prefixes + item(IPV6_PREFIX_TKN), // IPV6 network prefixes + + /* plumbing types */ + item(FORK_TKN), + item(JOIN_TKN), + item(START_TKN), // first token in line + item(END_TKN), // last token in line + {0}}; /** * Pretty-prints a graph, assuming it is a tree. @@ -522,143 +512,155 @@ struct message tokennames[] = { * @param start the node to take as the root * @param level indent level for recursive calls, always pass 0 */ -void -pretty_print_graph (struct vty *vty, struct graph_node *start, int level, - int desc, struct graph_node **stack, size_t stackpos) +void pretty_print_graph(struct vty *vty, struct graph_node *start, int level, + int desc, struct graph_node **stack, size_t stackpos) { - // print this node - char tokennum[32]; - struct cmd_token *tok = start->data; - - snprintf(tokennum, sizeof(tokennum), "%d?", tok->type); - vty_out(vty, "%s", lookup_msg(tokennames, tok->type, NULL)); - if (tok->text) - vty_out(vty, ":\"%s\"", tok->text); - if (tok->varname) - vty_out(vty, " => %s", tok->varname); - if (desc) - vty_out(vty, " ?'%s'", tok->desc); - vty_out(vty, " "); - - if (stackpos == MAXDEPTH) - { - vty_out (vty, " -aborting! (depth limit)\n"); - return; - } - stack[stackpos++] = start; - - int numto = desc ? 2 : vector_active (start->to); - if (numto) - { - if (numto > 1) - vty_out (vty, "\n"); - for (unsigned int i = 0; i < vector_active (start->to); i++) - { - struct graph_node *adj = vector_slot (start->to, i); - // if we're listing multiple children, indent! - if (numto > 1) - for (int j = 0; j < level+1; j++) - vty_out(vty, " "); - // if this node is a vararg, just print * - if (adj == start) - vty_out(vty, "*"); - else if (((struct cmd_token *)adj->data)->type == END_TKN) - vty_out (vty, "--END\n"); - else { - size_t k; - for (k = 0; k < stackpos; k++) - if (stack[k] == adj) { - vty_out (vty, "< 1 ? level+1 : level, desc, stack, stackpos); - } - } - } - else - vty_out (vty, "\n"); + // print this node + char tokennum[32]; + struct cmd_token *tok = start->data; + + snprintf(tokennum, sizeof(tokennum), "%d?", tok->type); + vty_out(vty, "%s", lookup_msg(tokennames, tok->type, NULL)); + if (tok->text) + vty_out(vty, ":\"%s\"", tok->text); + if (tok->varname) + vty_out(vty, " => %s", tok->varname); + if (desc) + vty_out(vty, " ?'%s'", tok->desc); + vty_out(vty, " "); + + if (stackpos == MAXDEPTH) { + vty_out(vty, " -aborting! (depth limit)\n"); + return; + } + stack[stackpos++] = start; + + int numto = desc ? 2 : vector_active(start->to); + if (numto) { + if (numto > 1) + vty_out(vty, "\n"); + for (unsigned int i = 0; i < vector_active(start->to); i++) { + struct graph_node *adj = vector_slot(start->to, i); + // if we're listing multiple children, indent! + if (numto > 1) + for (int j = 0; j < level + 1; j++) + vty_out(vty, " "); + // if this node is a vararg, just print * + if (adj == start) + vty_out(vty, "*"); + else if (((struct cmd_token *)adj->data)->type + == END_TKN) + vty_out(vty, "--END\n"); + else { + size_t k; + for (k = 0; k < stackpos; k++) + if (stack[k] == adj) { + vty_out(vty, "< 1 ? level + 1 : level, + desc, stack, stackpos); + } + } + } else + vty_out(vty, "\n"); } -static void -pretty_print_dot (FILE *ofd, unsigned opts, struct graph_node *start, - struct graph_node **stack, size_t stackpos, - struct graph_node **visited, size_t *visitpos) +static void pretty_print_dot(FILE *ofd, unsigned opts, struct graph_node *start, + struct graph_node **stack, size_t stackpos, + struct graph_node **visited, size_t *visitpos) { - // print this node - char tokennum[32]; - struct cmd_token *tok = start->data; - const char *color; - - for (size_t i = 0; i < (*visitpos); i++) - if (visited[i] == start) - return; - visited[(*visitpos)++] = start; - if ((*visitpos) == MAXDEPTH*MAXDEPTH) - return; - - snprintf(tokennum, sizeof(tokennum), "%d?", tok->type); - fprintf(ofd, " n%p [ shape=box, label=<", start); - - fprintf(ofd, "%s", lookup_msg(tokennames, tok->type, NULL)); - if (tok->attr == CMD_ATTR_DEPRECATED) - fprintf(ofd, " (d)"); - else if (tok->attr == CMD_ATTR_HIDDEN) - fprintf(ofd, " (h)"); - if (tok->text) { - if (tok->type == WORD_TKN) - fprintf(ofd, "
\"%s\"", tok->text); - else - fprintf(ofd, "
%s", tok->text); - } -/* if (desc) - fprintf(ofd, " ?'%s'", tok->desc); */ - switch (tok->type) { - case START_TKN: color = "#ccffcc"; break; - case FORK_TKN: color = "#aaddff"; break; - case JOIN_TKN: color = "#ddaaff"; break; - case WORD_TKN: color = "#ffffff"; break; - default: color = "#ffffff"; break; - } - fprintf(ofd, ">, style = filled, fillcolor = \"%s\" ];\n", color); - - if (stackpos == MAXDEPTH) - return; - stack[stackpos++] = start; - - for (unsigned int i = 0; i < vector_active (start->to); i++) - { - struct graph_node *adj = vector_slot (start->to, i); - // if this node is a vararg, just print * - if (adj == start) { - fprintf(ofd, " n%p -> n%p;\n", start, start); - } else if (((struct cmd_token *)adj->data)->type == END_TKN) { - //struct cmd_token *et = adj->data; - fprintf(ofd, " n%p -> end%p;\n", start, adj); - fprintf(ofd, " end%p [ shape=box, label=, style = filled, fillcolor = \"#ffddaa\" ];\n", adj); - } else { - fprintf(ofd, " n%p -> n%p;\n", start, adj); - size_t k; - for (k = 0; k < stackpos; k++) - if (stack[k] == adj) - break; - if (k == stackpos) { - pretty_print_dot (ofd, opts, adj, stack, stackpos, visited, visitpos); - } - } - } + // print this node + char tokennum[32]; + struct cmd_token *tok = start->data; + const char *color; + + for (size_t i = 0; i < (*visitpos); i++) + if (visited[i] == start) + return; + visited[(*visitpos)++] = start; + if ((*visitpos) == MAXDEPTH * MAXDEPTH) + return; + + snprintf(tokennum, sizeof(tokennum), "%d?", tok->type); + fprintf(ofd, " n%p [ shape=box, label=<", start); + + fprintf(ofd, "%s", lookup_msg(tokennames, tok->type, NULL)); + if (tok->attr == CMD_ATTR_DEPRECATED) + fprintf(ofd, " (d)"); + else if (tok->attr == CMD_ATTR_HIDDEN) + fprintf(ofd, " (h)"); + if (tok->text) { + if (tok->type == WORD_TKN) + fprintf(ofd, + "
\"%s\"", + tok->text); + else + fprintf(ofd, "
%s", tok->text); + } + /* if (desc) + fprintf(ofd, " ?'%s'", tok->desc); */ + switch (tok->type) { + case START_TKN: + color = "#ccffcc"; + break; + case FORK_TKN: + color = "#aaddff"; + break; + case JOIN_TKN: + color = "#ddaaff"; + break; + case WORD_TKN: + color = "#ffffff"; + break; + default: + color = "#ffffff"; + break; + } + fprintf(ofd, ">, style = filled, fillcolor = \"%s\" ];\n", color); + + if (stackpos == MAXDEPTH) + return; + stack[stackpos++] = start; + + for (unsigned int i = 0; i < vector_active(start->to); i++) { + struct graph_node *adj = vector_slot(start->to, i); + // if this node is a vararg, just print * + if (adj == start) { + fprintf(ofd, " n%p -> n%p;\n", start, start); + } else if (((struct cmd_token *)adj->data)->type == END_TKN) { + // struct cmd_token *et = adj->data; + fprintf(ofd, " n%p -> end%p;\n", start, adj); + fprintf(ofd, + " end%p [ shape=box, label=, style = filled, fillcolor = \"#ffddaa\" ];\n", + adj); + } else { + fprintf(ofd, " n%p -> n%p;\n", start, adj); + size_t k; + for (k = 0; k < stackpos; k++) + if (stack[k] == adj) + break; + if (k == stackpos) { + pretty_print_dot(ofd, opts, adj, stack, + stackpos, visited, visitpos); + } + } + } } /** stuff that should go in command.c + command.h */ -void -init_cmdgraph (struct vty *vty, struct graph **graph) +void init_cmdgraph(struct vty *vty, struct graph **graph) { - // initialize graph, add start noe - *graph = graph_new (); - nodegraph_free = *graph; - struct cmd_token *token = cmd_token_new (START_TKN, 0, NULL, NULL); - graph_new_node (*graph, token, (void (*)(void *)) &cmd_token_del); - if (vty) - vty_out (vty, "initialized graph\n"); + // initialize graph, add start noe + *graph = graph_new(); + nodegraph_free = *graph; + struct cmd_token *token = cmd_token_new(START_TKN, 0, NULL, NULL); + graph_new_node(*graph, token, (void (*)(void *)) & cmd_token_del); + if (vty) + vty_out(vty, "initialized graph\n"); } diff --git a/lib/grammar_sandbox_main.c b/lib/grammar_sandbox_main.c index 02aefd603..c236d2c7b 100644 --- a/lib/grammar_sandbox_main.c +++ b/lib/grammar_sandbox_main.c @@ -28,37 +28,37 @@ static void vty_do_exit(void) { - printf ("\nend.\n"); - exit (0); + printf("\nend.\n"); + exit(0); } struct thread_master *master; int main(int argc, char **argv) { - struct thread thread; + struct thread thread; - master = thread_master_create(NULL); + master = thread_master_create(NULL); - openzlog ("grammar_sandbox", "NONE", 0, - LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); - zlog_set_level (ZLOG_DEST_SYSLOG, ZLOG_DISABLED); - zlog_set_level (ZLOG_DEST_STDOUT, LOG_DEBUG); - zlog_set_level (ZLOG_DEST_MONITOR, ZLOG_DISABLED); + openzlog("grammar_sandbox", "NONE", 0, LOG_CONS | LOG_NDELAY | LOG_PID, + LOG_DAEMON); + zlog_set_level(ZLOG_DEST_SYSLOG, ZLOG_DISABLED); + zlog_set_level(ZLOG_DEST_STDOUT, LOG_DEBUG); + zlog_set_level(ZLOG_DEST_MONITOR, ZLOG_DISABLED); - /* Library inits. */ - cmd_init (1); - host.name = strdup ("test"); + /* Library inits. */ + cmd_init(1); + host.name = strdup("test"); - vty_init (master); - memory_init (); + vty_init(master); + memory_init(); - vty_stdio (vty_do_exit); + vty_stdio(vty_do_exit); - /* Fetch next active thread. */ - while (thread_fetch (master, &thread)) - thread_call (&thread); + /* Fetch next active thread. */ + while (thread_fetch(master, &thread)) + thread_call(&thread); - /* Not reached. */ - exit (0); + /* Not reached. */ + exit(0); } diff --git a/lib/graph.c b/lib/graph.c index 6173b2084..945a58e68 100644 --- a/lib/graph.c +++ b/lib/graph.c @@ -24,124 +24,115 @@ #include "graph.h" #include "memory.h" -DEFINE_MTYPE_STATIC(LIB, GRAPH, "Graph") +DEFINE_MTYPE_STATIC(LIB, GRAPH, "Graph") DEFINE_MTYPE_STATIC(LIB, GRAPH_NODE, "Graph Node") -struct graph * -graph_new () +struct graph *graph_new() { - struct graph *graph = XCALLOC (MTYPE_GRAPH, sizeof(struct graph)); - graph->nodes = vector_init (VECTOR_MIN_SIZE); + struct graph *graph = XCALLOC(MTYPE_GRAPH, sizeof(struct graph)); + graph->nodes = vector_init(VECTOR_MIN_SIZE); - return graph; + return graph; } -struct graph_node * -graph_new_node (struct graph *graph, void *data, void (*del) (void*)) +struct graph_node *graph_new_node(struct graph *graph, void *data, + void (*del)(void *)) { - struct graph_node *node = - XCALLOC(MTYPE_GRAPH_NODE, sizeof(struct graph_node)); + struct graph_node *node = + XCALLOC(MTYPE_GRAPH_NODE, sizeof(struct graph_node)); - node->from = vector_init (VECTOR_MIN_SIZE); - node->to = vector_init (VECTOR_MIN_SIZE); - node->data = data; - node->del = del; + node->from = vector_init(VECTOR_MIN_SIZE); + node->to = vector_init(VECTOR_MIN_SIZE); + node->data = data; + node->del = del; - vector_set (graph->nodes, node); + vector_set(graph->nodes, node); - return node; + return node; } -static void -vector_remove (vector v, unsigned int ix) +static void vector_remove(vector v, unsigned int ix) { - if (ix >= v->active) - return; - - /* v->active is guaranteed >= 1 because ix can't be lower than 0 - * and v->active is > ix. */ - v->active--; - /* if ix == v->active--, we set the item to itself, then to NULL... - * still correct, no check neccessary. */ - v->index[ix] = v->index[v->active]; - v->index[v->active] = NULL; + if (ix >= v->active) + return; + + /* v->active is guaranteed >= 1 because ix can't be lower than 0 + * and v->active is > ix. */ + v->active--; + /* if ix == v->active--, we set the item to itself, then to NULL... + * still correct, no check neccessary. */ + v->index[ix] = v->index[v->active]; + v->index[v->active] = NULL; } -void -graph_delete_node (struct graph *graph, struct graph_node *node) +void graph_delete_node(struct graph *graph, struct graph_node *node) { - if (!node) return; - - // an adjacent node - struct graph_node *adj; - - // remove all edges from other nodes to us - for (unsigned int i = vector_active (node->from); i--; /**/) - { - adj = vector_slot (node->from, i); - graph_remove_edge (adj, node); - } - - // remove all edges from us to other nodes - for (unsigned int i = vector_active (node->to); i--; /**/) - { - adj = vector_slot (node->to, i); - graph_remove_edge (node, adj); - } - - // if there is a deletion callback, call it - if (node->del && node->data) - (*node->del) (node->data); - - // free adjacency lists - vector_free (node->to); - vector_free (node->from); - - // remove node from graph->nodes - for (unsigned int i = vector_active (graph->nodes); i--; /**/) - if (vector_slot (graph->nodes, i) == node) - { - vector_remove (graph->nodes, i); - break; - } - - // free the node itself - XFREE (MTYPE_GRAPH_NODE, node); + if (!node) + return; + + // an adjacent node + struct graph_node *adj; + + // remove all edges from other nodes to us + for (unsigned int i = vector_active(node->from); i--; /**/) { + adj = vector_slot(node->from, i); + graph_remove_edge(adj, node); + } + + // remove all edges from us to other nodes + for (unsigned int i = vector_active(node->to); i--; /**/) { + adj = vector_slot(node->to, i); + graph_remove_edge(node, adj); + } + + // if there is a deletion callback, call it + if (node->del && node->data) + (*node->del)(node->data); + + // free adjacency lists + vector_free(node->to); + vector_free(node->from); + + // remove node from graph->nodes + for (unsigned int i = vector_active(graph->nodes); i--; /**/) + if (vector_slot(graph->nodes, i) == node) { + vector_remove(graph->nodes, i); + break; + } + + // free the node itself + XFREE(MTYPE_GRAPH_NODE, node); } -struct graph_node * -graph_add_edge (struct graph_node *from, struct graph_node *to) +struct graph_node *graph_add_edge(struct graph_node *from, + struct graph_node *to) { - vector_set (from->to, to); - vector_set (to->from, from); - return to; + vector_set(from->to, to); + vector_set(to->from, from); + return to; } -void -graph_remove_edge (struct graph_node *from, struct graph_node *to) +void graph_remove_edge(struct graph_node *from, struct graph_node *to) { - // remove from from to->from - for (unsigned int i = vector_active (to->from); i--; /**/) - if (vector_slot (to->from, i) == from) - { - vector_remove (to->from, i); - break; - } - // remove to from from->to - for (unsigned int i = vector_active (from->to); i--; /**/) - if (vector_slot (from->to, i) == to) - { - vector_remove (from->to, i); - break; - } + // remove from from to->from + for (unsigned int i = vector_active(to->from); i--; /**/) + if (vector_slot(to->from, i) == from) { + vector_remove(to->from, i); + break; + } + // remove to from from->to + for (unsigned int i = vector_active(from->to); i--; /**/) + if (vector_slot(from->to, i) == to) { + vector_remove(from->to, i); + break; + } } -void -graph_delete_graph (struct graph *graph) +void graph_delete_graph(struct graph *graph) { - // delete each node in the graph - for (unsigned int i = vector_active (graph->nodes); i--; /**/) - graph_delete_node (graph, vector_slot (graph->nodes, i)); + // delete each node in the graph + for (unsigned int i = vector_active(graph->nodes); i--; /**/) + graph_delete_node(graph, vector_slot(graph->nodes, i)); - vector_free (graph->nodes); - XFREE (MTYPE_GRAPH, graph); + vector_free(graph->nodes); + XFREE(MTYPE_GRAPH, graph); } diff --git a/lib/graph.h b/lib/graph.h index d3973d4b0..10ee00fed 100644 --- a/lib/graph.h +++ b/lib/graph.h @@ -26,22 +26,19 @@ #include "vector.h" -struct graph -{ - vector nodes; +struct graph { + vector nodes; }; -struct graph_node -{ - vector from; // nodes which have edges to this node - vector to; // nodes which this node has edges to +struct graph_node { + vector from; // nodes which have edges to this node + vector to; // nodes which this node has edges to - void *data; // node data - void (*del) (void *data); // deletion callback + void *data; // node data + void (*del)(void *data); // deletion callback }; -struct graph * -graph_new (void); +struct graph *graph_new(void); /** * Creates a new node. @@ -51,8 +48,8 @@ graph_new (void); * @param[in] del data deletion callback * @return the new node */ -struct graph_node * -graph_new_node (struct graph *graph, void *data, void (*del) (void*)); +struct graph_node *graph_new_node(struct graph *graph, void *data, + void (*del)(void *)); /** * Deletes a node. @@ -66,8 +63,7 @@ graph_new_node (struct graph *graph, void *data, void (*del) (void*)); * @param[in] graph the graph this node belongs to * @param[out] node pointer to node to delete */ -void -graph_delete_node (struct graph *graph, struct graph_node *node); +void graph_delete_node(struct graph *graph, struct graph_node *node); /** * Makes a directed edge between two nodes. @@ -76,8 +72,8 @@ graph_delete_node (struct graph *graph, struct graph_node *node); * @param[in] to * @return to */ -struct graph_node * -graph_add_edge (struct graph_node *from, struct graph_node *to); +struct graph_node *graph_add_edge(struct graph_node *from, + struct graph_node *to); /** * Removes a directed edge between two nodes. @@ -85,8 +81,7 @@ graph_add_edge (struct graph_node *from, struct graph_node *to); * @param[in] from * @param[in] to */ -void -graph_remove_edge (struct graph_node *from, struct graph_node *to); +void graph_remove_edge(struct graph_node *from, struct graph_node *to); /** * Deletes a graph. @@ -94,7 +89,6 @@ graph_remove_edge (struct graph_node *from, struct graph_node *to); * * @param graph the graph to delete */ -void -graph_delete_graph (struct graph *graph); +void graph_delete_graph(struct graph *graph); #endif /* _ZEBRA_COMMAND_GRAPH_H */ diff --git a/lib/hash.c b/lib/hash.c index 7c355b2d8..7adbd908d 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -29,343 +29,323 @@ #include "command.h" #include "libfrr.h" -DEFINE_MTYPE( LIB, HASH, "Hash") -DEFINE_MTYPE( LIB, HASH_BACKET, "Hash Bucket") -DEFINE_MTYPE_STATIC(LIB, HASH_INDEX, "Hash Index") +DEFINE_MTYPE(LIB, HASH, "Hash") +DEFINE_MTYPE(LIB, HASH_BACKET, "Hash Bucket") +DEFINE_MTYPE_STATIC(LIB, HASH_INDEX, "Hash Index") pthread_mutex_t _hashes_mtx = PTHREAD_MUTEX_INITIALIZER; static struct list *_hashes; /* Allocate a new hash. */ -struct hash * -hash_create_size (unsigned int size, unsigned int (*hash_key) (void *), - int (*hash_cmp) (const void *, const void *), - const char *name) +struct hash *hash_create_size(unsigned int size, + unsigned int (*hash_key)(void *), + int (*hash_cmp)(const void *, const void *), + const char *name) { - struct hash *hash; - - assert ((size & (size-1)) == 0); - hash = XCALLOC (MTYPE_HASH, sizeof (struct hash)); - hash->index = XCALLOC (MTYPE_HASH_INDEX, - sizeof (struct hash_backet *) * size); - hash->size = size; - hash->no_expand = 0; - hash->hash_key = hash_key; - hash->hash_cmp = hash_cmp; - hash->count = 0; - hash->name = name ? XSTRDUP(MTYPE_HASH, name) : NULL; - hash->stats.empty = hash->size; - - pthread_mutex_lock (&_hashes_mtx); - { - if (!_hashes) - _hashes = list_new(); - - listnode_add (_hashes, hash); - } - pthread_mutex_unlock (&_hashes_mtx); - - return hash; + struct hash *hash; + + assert((size & (size - 1)) == 0); + hash = XCALLOC(MTYPE_HASH, sizeof(struct hash)); + hash->index = + XCALLOC(MTYPE_HASH_INDEX, sizeof(struct hash_backet *) * size); + hash->size = size; + hash->no_expand = 0; + hash->hash_key = hash_key; + hash->hash_cmp = hash_cmp; + hash->count = 0; + hash->name = name ? XSTRDUP(MTYPE_HASH, name) : NULL; + hash->stats.empty = hash->size; + + pthread_mutex_lock(&_hashes_mtx); + { + if (!_hashes) + _hashes = list_new(); + + listnode_add(_hashes, hash); + } + pthread_mutex_unlock(&_hashes_mtx); + + return hash; } /* Allocate a new hash with default hash size. */ -struct hash * -hash_create (unsigned int (*hash_key) (void *), - int (*hash_cmp) (const void *, const void *), - const char *name) +struct hash *hash_create(unsigned int (*hash_key)(void *), + int (*hash_cmp)(const void *, const void *), + const char *name) { - return hash_create_size (HASH_INITIAL_SIZE, hash_key, hash_cmp, name); + return hash_create_size(HASH_INITIAL_SIZE, hash_key, hash_cmp, name); } /* Utility function for hash_get(). When this function is specified as alloc_func, return arugment as it is. This function is used for intern already allocated value. */ -void * -hash_alloc_intern (void *arg) +void *hash_alloc_intern(void *arg) { - return arg; + return arg; } -#define hash_update_ssq(hz, old, new) \ - atomic_fetch_add_explicit(&hz->stats.ssq, (new + old)*(new - old),\ - memory_order_relaxed); +#define hash_update_ssq(hz, old, new) \ + atomic_fetch_add_explicit(&hz->stats.ssq, (new + old) * (new - old), \ + memory_order_relaxed); /* Expand hash if the chain length exceeds the threshold. */ -static void hash_expand (struct hash *hash) +static void hash_expand(struct hash *hash) { - unsigned int i, new_size, losers; - struct hash_backet *hb, *hbnext, **new_index; + unsigned int i, new_size, losers; + struct hash_backet *hb, *hbnext, **new_index; - new_size = hash->size * 2; - new_index = XCALLOC(MTYPE_HASH_INDEX, sizeof(struct hash_backet *) * new_size); - if (new_index == NULL) - return; + new_size = hash->size * 2; + new_index = XCALLOC(MTYPE_HASH_INDEX, + sizeof(struct hash_backet *) * new_size); + if (new_index == NULL) + return; - hash->stats.empty = new_size; + hash->stats.empty = new_size; - for (i = 0; i < hash->size; i++) - for (hb = hash->index[i]; hb; hb = hbnext) - { - unsigned int h = hb->key & (new_size - 1); + for (i = 0; i < hash->size; i++) + for (hb = hash->index[i]; hb; hb = hbnext) { + unsigned int h = hb->key & (new_size - 1); - hbnext = hb->next; - hb->next = new_index[h]; + hbnext = hb->next; + hb->next = new_index[h]; - int oldlen = hb->next ? hb->next->len : 0; - int newlen = oldlen + 1; + int oldlen = hb->next ? hb->next->len : 0; + int newlen = oldlen + 1; - if (newlen == 1) - hash->stats.empty--; - else - hb->next->len = 0; + if (newlen == 1) + hash->stats.empty--; + else + hb->next->len = 0; - hb->len = newlen; + hb->len = newlen; - hash_update_ssq(hash, oldlen, newlen); + hash_update_ssq(hash, oldlen, newlen); - new_index[h] = hb; - } + new_index[h] = hb; + } - /* Switch to new table */ - XFREE(MTYPE_HASH_INDEX, hash->index); - hash->size = new_size; - hash->index = new_index; + /* Switch to new table */ + XFREE(MTYPE_HASH_INDEX, hash->index); + hash->size = new_size; + hash->index = new_index; - /* Ideally, new index should have chains half as long as the original. - * If expansion didn't help, then not worth expanding again, - * the problem is the hash function. */ - losers = 0; - for (i = 0; i < hash->size; i++) - { - unsigned int len = hash->index[i] ? hash->index[i]->len : 0; + /* Ideally, new index should have chains half as long as the original. + * If expansion didn't help, then not worth expanding again, + * the problem is the hash function. */ + losers = 0; + for (i = 0; i < hash->size; i++) { + unsigned int len = hash->index[i] ? hash->index[i]->len : 0; - if (len > HASH_THRESHOLD/2) - ++losers; - if (len >= HASH_THRESHOLD) - hash->no_expand = 1; - } + if (len > HASH_THRESHOLD / 2) + ++losers; + if (len >= HASH_THRESHOLD) + hash->no_expand = 1; + } - if (losers > hash->count / 2) - hash->no_expand = 1; + if (losers > hash->count / 2) + hash->no_expand = 1; } /* Lookup and return hash backet in hash. If there is no corresponding hash backet and alloc_func is specified, create new hash backet. */ -void * -hash_get (struct hash *hash, void *data, void * (*alloc_func) (void *)) +void *hash_get(struct hash *hash, void *data, void *(*alloc_func)(void *)) { - unsigned int key; - unsigned int index; - void *newdata; - unsigned int len; - struct hash_backet *backet; - - key = (*hash->hash_key) (data); - index = key & (hash->size - 1); - len = 0; - - for (backet = hash->index[index]; backet != NULL; backet = backet->next) - { - if (backet->key == key && (*hash->hash_cmp) (backet->data, data)) - return backet->data; - ++len; - } - - if (alloc_func) - { - newdata = (*alloc_func) (data); - if (newdata == NULL) - return NULL; - - if (len > HASH_THRESHOLD && !hash->no_expand) - { - hash_expand (hash); - index = key & (hash->size - 1); + unsigned int key; + unsigned int index; + void *newdata; + unsigned int len; + struct hash_backet *backet; + + key = (*hash->hash_key)(data); + index = key & (hash->size - 1); + len = 0; + + for (backet = hash->index[index]; backet != NULL; + backet = backet->next) { + if (backet->key == key && (*hash->hash_cmp)(backet->data, data)) + return backet->data; + ++len; } - backet = XCALLOC (MTYPE_HASH_BACKET, sizeof (struct hash_backet)); - backet->data = newdata; - backet->key = key; - backet->next = hash->index[index]; - hash->index[index] = backet; - hash->count++; + if (alloc_func) { + newdata = (*alloc_func)(data); + if (newdata == NULL) + return NULL; - int oldlen = backet->next ? backet->next->len : 0; - int newlen = oldlen + 1; + if (len > HASH_THRESHOLD && !hash->no_expand) { + hash_expand(hash); + index = key & (hash->size - 1); + } - if (newlen == 1) - hash->stats.empty--; - else - backet->next->len = 0; + backet = XCALLOC(MTYPE_HASH_BACKET, sizeof(struct hash_backet)); + backet->data = newdata; + backet->key = key; + backet->next = hash->index[index]; + hash->index[index] = backet; + hash->count++; - backet->len = newlen; + int oldlen = backet->next ? backet->next->len : 0; + int newlen = oldlen + 1; - hash_update_ssq(hash, oldlen, newlen); + if (newlen == 1) + hash->stats.empty--; + else + backet->next->len = 0; - return backet->data; - } - return NULL; + backet->len = newlen; + + hash_update_ssq(hash, oldlen, newlen); + + return backet->data; + } + return NULL; } /* Hash lookup. */ -void * -hash_lookup (struct hash *hash, void *data) +void *hash_lookup(struct hash *hash, void *data) { - return hash_get (hash, data, NULL); + return hash_get(hash, data, NULL); } /* Simple Bernstein hash which is simple and fast for common case */ -unsigned int string_hash_make (const char *str) +unsigned int string_hash_make(const char *str) { - unsigned int hash = 0; + unsigned int hash = 0; - while (*str) - hash = (hash * 33) ^ (unsigned int) *str++; + while (*str) + hash = (hash * 33) ^ (unsigned int)*str++; - return hash; + return hash; } /* This function release registered value from specified hash. When release is successfully finished, return the data pointer in the hash backet. */ -void * -hash_release (struct hash *hash, void *data) +void *hash_release(struct hash *hash, void *data) { - void *ret; - unsigned int key; - unsigned int index; - struct hash_backet *backet; - struct hash_backet *pp; - - key = (*hash->hash_key) (data); - index = key & (hash->size - 1); - - for (backet = pp = hash->index[index]; backet; backet = backet->next) - { - if (backet->key == key && (*hash->hash_cmp) (backet->data, data)) - { - int oldlen = hash->index[index]->len; - int newlen = oldlen - 1; - - if (backet == pp) - hash->index[index] = backet->next; - else - pp->next = backet->next; - - if (hash->index[index]) - hash->index[index]->len = newlen; - else - hash->stats.empty++; - - hash_update_ssq(hash, oldlen, newlen); - - ret = backet->data; - XFREE (MTYPE_HASH_BACKET, backet); - hash->count--; - return ret; + void *ret; + unsigned int key; + unsigned int index; + struct hash_backet *backet; + struct hash_backet *pp; + + key = (*hash->hash_key)(data); + index = key & (hash->size - 1); + + for (backet = pp = hash->index[index]; backet; backet = backet->next) { + if (backet->key == key + && (*hash->hash_cmp)(backet->data, data)) { + int oldlen = hash->index[index]->len; + int newlen = oldlen - 1; + + if (backet == pp) + hash->index[index] = backet->next; + else + pp->next = backet->next; + + if (hash->index[index]) + hash->index[index]->len = newlen; + else + hash->stats.empty++; + + hash_update_ssq(hash, oldlen, newlen); + + ret = backet->data; + XFREE(MTYPE_HASH_BACKET, backet); + hash->count--; + return ret; + } + pp = backet; } - pp = backet; - } - return NULL; + return NULL; } /* Iterator function for hash. */ -void -hash_iterate (struct hash *hash, - void (*func) (struct hash_backet *, void *), void *arg) +void hash_iterate(struct hash *hash, void (*func)(struct hash_backet *, void *), + void *arg) { - unsigned int i; - struct hash_backet *hb; - struct hash_backet *hbnext; - - for (i = 0; i < hash->size; i++) - for (hb = hash->index[i]; hb; hb = hbnext) - { - /* get pointer to next hash backet here, in case (*func) - * decides to delete hb by calling hash_release - */ - hbnext = hb->next; - (*func) (hb, arg); - } + unsigned int i; + struct hash_backet *hb; + struct hash_backet *hbnext; + + for (i = 0; i < hash->size; i++) + for (hb = hash->index[i]; hb; hb = hbnext) { + /* get pointer to next hash backet here, in case (*func) + * decides to delete hb by calling hash_release + */ + hbnext = hb->next; + (*func)(hb, arg); + } } /* Iterator function for hash. */ -void -hash_walk (struct hash *hash, - int (*func) (struct hash_backet *, void *), void *arg) +void hash_walk(struct hash *hash, int (*func)(struct hash_backet *, void *), + void *arg) { - unsigned int i; - struct hash_backet *hb; - struct hash_backet *hbnext; - int ret = HASHWALK_CONTINUE; - - for (i = 0; i < hash->size; i++) - { - for (hb = hash->index[i]; hb; hb = hbnext) - { - /* get pointer to next hash backet here, in case (*func) - * decides to delete hb by calling hash_release - */ - hbnext = hb->next; - ret = (*func) (hb, arg); - if (ret == HASHWALK_ABORT) - return; + unsigned int i; + struct hash_backet *hb; + struct hash_backet *hbnext; + int ret = HASHWALK_CONTINUE; + + for (i = 0; i < hash->size; i++) { + for (hb = hash->index[i]; hb; hb = hbnext) { + /* get pointer to next hash backet here, in case (*func) + * decides to delete hb by calling hash_release + */ + hbnext = hb->next; + ret = (*func)(hb, arg); + if (ret == HASHWALK_ABORT) + return; + } } - } } /* Clean up hash. */ -void -hash_clean (struct hash *hash, void (*free_func) (void *)) +void hash_clean(struct hash *hash, void (*free_func)(void *)) { - unsigned int i; - struct hash_backet *hb; - struct hash_backet *next; + unsigned int i; + struct hash_backet *hb; + struct hash_backet *next; - for (i = 0; i < hash->size; i++) - { - for (hb = hash->index[i]; hb; hb = next) - { - next = hb->next; - - if (free_func) - (*free_func) (hb->data); + for (i = 0; i < hash->size; i++) { + for (hb = hash->index[i]; hb; hb = next) { + next = hb->next; + + if (free_func) + (*free_func)(hb->data); - XFREE (MTYPE_HASH_BACKET, hb); - hash->count--; + XFREE(MTYPE_HASH_BACKET, hb); + hash->count--; + } + hash->index[i] = NULL; } - hash->index[i] = NULL; - } - hash->stats.ssq = 0; - hash->stats.empty = hash->size; + hash->stats.ssq = 0; + hash->stats.empty = hash->size; } /* Free hash memory. You may call hash_clean before call this function. */ -void -hash_free (struct hash *hash) +void hash_free(struct hash *hash) { - pthread_mutex_lock (&_hashes_mtx); - { - if (_hashes) - { - listnode_delete (_hashes, hash); - if (_hashes->count == 0) - { - list_delete (_hashes); - _hashes = NULL; - } - } - } - pthread_mutex_unlock (&_hashes_mtx); - - if (hash->name) - XFREE (MTYPE_HASH, hash->name); - - XFREE (MTYPE_HASH_INDEX, hash->index); - XFREE (MTYPE_HASH, hash); + pthread_mutex_lock(&_hashes_mtx); + { + if (_hashes) { + listnode_delete(_hashes, hash); + if (_hashes->count == 0) { + list_delete(_hashes); + _hashes = NULL; + } + } + } + pthread_mutex_unlock(&_hashes_mtx); + + if (hash->name) + XFREE(MTYPE_HASH, hash->name); + + XFREE(MTYPE_HASH_INDEX, hash->index); + XFREE(MTYPE_HASH, hash); } @@ -378,111 +358,116 @@ DEFUN(show_hash_stats, "Statistics about hash tables\n" "Statistics about hash tables\n") { - struct hash *h; - struct listnode *ln; - struct ttable *tt = ttable_new (&ttable_styles[TTSTYLE_BLANK]); - - ttable_add_row (tt, "Hash table|Buckets|Entries|Empty|LF|SD|FLF|SD"); - tt->style.cell.lpad = 2; - tt->style.cell.rpad = 1; - tt->style.corner = '+'; - ttable_restyle (tt); - ttable_rowseps (tt, 0, BOTTOM, true, '-'); - - /* Summary statistics calculated are: - * - * - Load factor: This is the number of elements in the table divided by the - * number of buckets. Since this hash table implementation uses chaining, - * this value can be greater than 1. This number provides information on - * how 'full' the table is, but does not provide information on how evenly - * distributed the elements are. Notably, a load factor >= 1 does not imply - * that every bucket has an element; with a pathological hash function, all - * elements could be in a single bucket. - * - * - Full load factor: this is the number of elements in the table divided by - * the number of buckets that have some elements in them. - * - * - Std. Dev.: This is the standard deviation calculated from the relevant - * load factor. If the load factor is the mean of number of elements per - * bucket, the standard deviation measures how much any particular bucket - * is likely to deviate from the mean. As a rule of thumb this number - * should be less than 2, and ideally <= 1 for optimal performance. A - * number larger than 3 generally indicates a poor hash function. - */ - - double lf; // load factor - double flf; // full load factor - double var; // overall variance - double fvar; // full variance - double stdv; // overall stddev - double fstdv; // full stddev - - long double x2; // h->count ^ 2 - long double ldc; // (long double) h->count - long double full; // h->size - h->stats.empty - long double ssq; // ssq casted to long double - - pthread_mutex_lock (&_hashes_mtx); - if (!_hashes) - { - pthread_mutex_unlock (&_hashes_mtx); - vty_out (vty, "No hash tables in use.\n"); - return CMD_SUCCESS; - } - - for (ALL_LIST_ELEMENTS_RO (_hashes, ln, h)) - { - if (!h->name) - continue; - - ssq = (long double) h->stats.ssq; - x2 = powl(h->count, 2.0); - ldc = (long double) h->count; - full = h->size - h->stats.empty; - lf = h->count / (double) h->size; - flf = full ? h->count / (double) (full) : 0; - var = ldc ? (1.0 / ldc) * (ssq - x2 / ldc) : 0; - fvar = full ? (1.0 / full) * (ssq - x2 / full) : 0; - var = (var < .0001) ? 0 : var; - fvar = (fvar < .0001) ? 0 : fvar; - stdv = sqrt(var); - fstdv = sqrt(fvar); - - ttable_add_row (tt, "%s|%d|%ld|%.0f%%|%.2lf|%.2lf|%.2lf|%.2lf", h->name, - h->size, h->count, - (h->stats.empty / (double) h->size)*100, lf, stdv, flf, - fstdv); - } - pthread_mutex_unlock (&_hashes_mtx); - - /* display header */ - char header[] = "Showing hash table statistics for "; - char underln[sizeof(header) + strlen(frr_protonameinst)]; - memset (underln, '-', sizeof(underln)); - underln[sizeof(underln) - 1] = '\0'; - vty_out (vty, "%s%s\n", header, frr_protonameinst); - vty_out (vty, "%s\n", underln); - - vty_out (vty, "# allocated: %d\n", _hashes->count); - vty_out (vty, "# named: %d\n\n", tt->nrows - 1); - - if (tt->nrows > 1) - { - ttable_colseps (tt, 0, RIGHT, true, '|'); - char *table = ttable_dump (tt, "\n"); - vty_out (vty, "%s\n", table); - XFREE (MTYPE_TMP, table); - } - else - vty_out (vty, "No named hash tables to display.\n"); - - ttable_del (tt); - - return CMD_SUCCESS; + struct hash *h; + struct listnode *ln; + struct ttable *tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]); + + ttable_add_row(tt, "Hash table|Buckets|Entries|Empty|LF|SD|FLF|SD"); + tt->style.cell.lpad = 2; + tt->style.cell.rpad = 1; + tt->style.corner = '+'; + ttable_restyle(tt); + ttable_rowseps(tt, 0, BOTTOM, true, '-'); + + /* Summary statistics calculated are: + * + * - Load factor: This is the number of elements in the table divided by + * the + * number of buckets. Since this hash table implementation uses + * chaining, + * this value can be greater than 1. This number provides information + * on + * how 'full' the table is, but does not provide information on how + * evenly + * distributed the elements are. Notably, a load factor >= 1 does not + * imply + * that every bucket has an element; with a pathological hash + * function, all + * elements could be in a single bucket. + * + * - Full load factor: this is the number of elements in the table + * divided by + * the number of buckets that have some elements in them. + * + * - Std. Dev.: This is the standard deviation calculated from the + * relevant + * load factor. If the load factor is the mean of number of elements + * per + * bucket, the standard deviation measures how much any particular + * bucket + * is likely to deviate from the mean. As a rule of thumb this number + * should be less than 2, and ideally <= 1 for optimal performance. A + * number larger than 3 generally indicates a poor hash function. + */ + + double lf; // load factor + double flf; // full load factor + double var; // overall variance + double fvar; // full variance + double stdv; // overall stddev + double fstdv; // full stddev + + long double x2; // h->count ^ 2 + long double ldc; // (long double) h->count + long double full; // h->size - h->stats.empty + long double ssq; // ssq casted to long double + + pthread_mutex_lock(&_hashes_mtx); + if (!_hashes) { + pthread_mutex_unlock(&_hashes_mtx); + vty_out(vty, "No hash tables in use.\n"); + return CMD_SUCCESS; + } + + for (ALL_LIST_ELEMENTS_RO(_hashes, ln, h)) { + if (!h->name) + continue; + + ssq = (long double)h->stats.ssq; + x2 = powl(h->count, 2.0); + ldc = (long double)h->count; + full = h->size - h->stats.empty; + lf = h->count / (double)h->size; + flf = full ? h->count / (double)(full) : 0; + var = ldc ? (1.0 / ldc) * (ssq - x2 / ldc) : 0; + fvar = full ? (1.0 / full) * (ssq - x2 / full) : 0; + var = (var < .0001) ? 0 : var; + fvar = (fvar < .0001) ? 0 : fvar; + stdv = sqrt(var); + fstdv = sqrt(fvar); + + ttable_add_row(tt, "%s|%d|%ld|%.0f%%|%.2lf|%.2lf|%.2lf|%.2lf", + h->name, h->size, h->count, + (h->stats.empty / (double)h->size) * 100, lf, + stdv, flf, fstdv); + } + pthread_mutex_unlock(&_hashes_mtx); + + /* display header */ + char header[] = "Showing hash table statistics for "; + char underln[sizeof(header) + strlen(frr_protonameinst)]; + memset(underln, '-', sizeof(underln)); + underln[sizeof(underln) - 1] = '\0'; + vty_out(vty, "%s%s\n", header, frr_protonameinst); + vty_out(vty, "%s\n", underln); + + vty_out(vty, "# allocated: %d\n", _hashes->count); + vty_out(vty, "# named: %d\n\n", tt->nrows - 1); + + if (tt->nrows > 1) { + ttable_colseps(tt, 0, RIGHT, true, '|'); + char *table = ttable_dump(tt, "\n"); + vty_out(vty, "%s\n", table); + XFREE(MTYPE_TMP, table); + } else + vty_out(vty, "No named hash tables to display.\n"); + + ttable_del(tt); + + return CMD_SUCCESS; } -void -hash_cmd_init () +void hash_cmd_init() { - install_element (ENABLE_NODE, &show_hash_stats_cmd); + install_element(ENABLE_NODE, &show_hash_stats_cmd); } diff --git a/lib/hash.h b/lib/hash.h index 3b2671afa..ec3766eaa 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -27,88 +27,86 @@ DECLARE_MTYPE(HASH) DECLARE_MTYPE(HASH_BACKET) -/* Default hash table size. */ +/* Default hash table size. */ #define HASH_INITIAL_SIZE 256 /* initial number of backets. */ #define HASH_THRESHOLD 10 /* expand when backet. */ #define HASHWALK_CONTINUE 0 #define HASHWALK_ABORT -1 -struct hash_backet -{ - /* if this backet is the head of the linked listed, len denotes the number of - * elements in the list */ - int len; +struct hash_backet { + /* if this backet is the head of the linked listed, len denotes the + * number of + * elements in the list */ + int len; - /* Linked list. */ - struct hash_backet *next; + /* Linked list. */ + struct hash_backet *next; - /* Hash key. */ - unsigned int key; + /* Hash key. */ + unsigned int key; - /* Data. */ - void *data; + /* Data. */ + void *data; }; -struct hashstats -{ - /* number of empty hash buckets */ - _Atomic uint_fast32_t empty; - /* sum of squares of bucket length */ - _Atomic uint_fast32_t ssq; +struct hashstats { + /* number of empty hash buckets */ + _Atomic uint_fast32_t empty; + /* sum of squares of bucket length */ + _Atomic uint_fast32_t ssq; }; -struct hash -{ - /* Hash backet. */ - struct hash_backet **index; +struct hash { + /* Hash backet. */ + struct hash_backet **index; - /* Hash table size. Must be power of 2 */ - unsigned int size; + /* Hash table size. Must be power of 2 */ + unsigned int size; - /* If expansion failed. */ - int no_expand; + /* If expansion failed. */ + int no_expand; - /* Key make function. */ - unsigned int (*hash_key) (void *); + /* Key make function. */ + unsigned int (*hash_key)(void *); - /* Data compare function. */ - int (*hash_cmp) (const void *, const void *); + /* Data compare function. */ + int (*hash_cmp)(const void *, const void *); - /* Backet alloc. */ - unsigned long count; + /* Backet alloc. */ + unsigned long count; - struct hashstats stats; + struct hashstats stats; - /* hash name */ - char *name; + /* hash name */ + char *name; }; #define hashcount(X) ((X)->count) -extern struct hash *hash_create (unsigned int (*) (void *), - int (*) (const void *, const void *), - const char *); -extern struct hash *hash_create_size (unsigned int, unsigned int (*) (void *), - int (*) (const void *, const void *), - const char *); +extern struct hash *hash_create(unsigned int (*)(void *), + int (*)(const void *, const void *), + const char *); +extern struct hash *hash_create_size(unsigned int, unsigned int (*)(void *), + int (*)(const void *, const void *), + const char *); -extern void *hash_get (struct hash *, void *, void * (*) (void *)); -extern void *hash_alloc_intern (void *); -extern void *hash_lookup (struct hash *, void *); -extern void *hash_release (struct hash *, void *); +extern void *hash_get(struct hash *, void *, void *(*)(void *)); +extern void *hash_alloc_intern(void *); +extern void *hash_lookup(struct hash *, void *); +extern void *hash_release(struct hash *, void *); -extern void hash_iterate (struct hash *, - void (*) (struct hash_backet *, void *), void *); +extern void hash_iterate(struct hash *, void (*)(struct hash_backet *, void *), + void *); -extern void hash_walk (struct hash *, - int (*) (struct hash_backet *, void *), void *); +extern void hash_walk(struct hash *, int (*)(struct hash_backet *, void *), + void *); -extern void hash_clean (struct hash *, void (*) (void *)); -extern void hash_free (struct hash *); +extern void hash_clean(struct hash *, void (*)(void *)); +extern void hash_free(struct hash *); -extern unsigned int string_hash_make (const char *); +extern unsigned int string_hash_make(const char *); -extern void hash_cmd_init (void); +extern void hash_cmd_init(void); #endif /* _ZEBRA_HASH_H */ diff --git a/lib/hook.c b/lib/hook.c index 04d803cd8..2c877cbf4 100644 --- a/lib/hook.c +++ b/lib/hook.c @@ -39,18 +39,15 @@ void _hook_register(struct hook *hook, void *funcptr, void *arg, bool has_arg, hook->entries = he; } -void _hook_unregister(struct hook *hook, void *funcptr, - void *arg, bool has_arg) +void _hook_unregister(struct hook *hook, void *funcptr, void *arg, bool has_arg) { struct hookent *he, **prev; for (prev = &hook->entries; (he = *prev) != NULL; prev = &he->next) if (he->hookfn == funcptr && he->hookarg == arg - && he->has_arg == has_arg) - { + && he->has_arg == has_arg) { *prev = he->next; XFREE(MTYPE_HOOK_ENTRY, he); break; } } - diff --git a/lib/hook.h b/lib/hook.h index 0cb7ab5c7..4a5cee2fd 100644 --- a/lib/hook.h +++ b/lib/hook.h @@ -91,7 +91,7 @@ struct hookent { struct hookent *next; - void *hookfn; /* actually a function pointer */ + void *hookfn; /* actually a function pointer */ void *hookarg; bool has_arg; struct frrmod_runtime *module; @@ -111,29 +111,27 @@ struct hook { extern void _hook_register(struct hook *hook, void *funcptr, void *arg, bool has_arg, struct frrmod_runtime *module, const char *funcname); -#define hook_register(hookname, func) \ - _hook_register(&_hook_ ## hookname, \ - _hook_typecheck_ ## hookname (func), \ - NULL, false, THIS_MODULE, #func) -#define hook_register_arg(hookname, func, arg) \ - _hook_register(&_hook_ ## hookname, \ - _hook_typecheck_arg_ ## hookname (func), \ - arg, true, THIS_MODULE, #func) +#define hook_register(hookname, func) \ + _hook_register(&_hook_##hookname, _hook_typecheck_##hookname(func), \ + NULL, false, THIS_MODULE, #func) +#define hook_register_arg(hookname, func, arg) \ + _hook_register(&_hook_##hookname, \ + _hook_typecheck_arg_##hookname(func), arg, true, \ + THIS_MODULE, #func) extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg, bool has_arg); -#define hook_unregister(hookname, func) \ - _hook_unregister(&_hook_ ## hookname, \ - _hook_typecheck_ ## hookname (func), NULL, false) -#define hook_unregister_arg(hookname, func, arg) \ - _hook_unregister(&_hook_ ## hookname, \ - _hook_typecheck_arg_ ## hookname (func), arg, true) +#define hook_unregister(hookname, func) \ + _hook_unregister(&_hook_##hookname, _hook_typecheck_##hookname(func), \ + NULL, false) +#define hook_unregister_arg(hookname, func, arg) \ + _hook_unregister(&_hook_##hookname, \ + _hook_typecheck_arg_##hookname(func), arg, true) /* invoke hooks * this is private (static) to the file that has the DEFINE_HOOK statement */ -#define hook_call(hookname, ...) \ - hook_call_ ## hookname (__VA_ARGS__) +#define hook_call(hookname, ...) hook_call_##hookname(__VA_ARGS__) /* helpers to add the void * arg */ #define HOOK_ADDDEF(...) (void *hookarg , ## __VA_ARGS__) @@ -146,42 +144,44 @@ extern void _hook_unregister(struct hook *hook, void *funcptr, void *arg, * theoretically passlist is not neccessary, but let's keep things simple and * use exact same args on DECLARE and DEFINE. */ -#define DECLARE_HOOK(hookname, arglist, passlist) \ - extern struct hook _hook_ ## hookname; \ - __attribute__((unused)) \ - static void *_hook_typecheck_ ## hookname ( \ - int (*funcptr) arglist) { \ - return (void *)funcptr; } \ - __attribute__((unused)) \ - static void *_hook_typecheck_arg_ ## hookname ( \ - int (*funcptr) HOOK_ADDDEF arglist) { \ - return (void *)funcptr; } +#define DECLARE_HOOK(hookname, arglist, passlist) \ + extern struct hook _hook_##hookname; \ + __attribute__((unused)) static void *_hook_typecheck_##hookname( \ + int(*funcptr) arglist) \ + { \ + return (void *)funcptr; \ + } \ + __attribute__((unused)) static void *_hook_typecheck_arg_##hookname( \ + int(*funcptr) HOOK_ADDDEF arglist) \ + { \ + return (void *)funcptr; \ + } /* use in source file - contains hook-related definitions. */ -#define DEFINE_HOOK(hookname, arglist, passlist) \ - struct hook _hook_ ## hookname = { \ - .name = #hookname, \ - .entries = NULL, \ - }; \ - static int hook_call_ ## hookname arglist { \ - int hooksum = 0; \ - struct hookent *he = _hook_ ## hookname .entries; \ - void *hookarg; \ - union { \ - void *voidptr; \ - int (*fptr) arglist; \ - int (*farg) HOOK_ADDDEF arglist; \ - } hookp; \ - for (; he; he = he->next) { \ - hookarg = he->hookarg; \ - hookp.voidptr = he->hookfn; \ - if (!he->has_arg) \ - hooksum += hookp.fptr passlist; \ - else \ - hooksum += hookp.farg HOOK_ADDARG passlist; \ - } \ - return hooksum; \ +#define DEFINE_HOOK(hookname, arglist, passlist) \ + struct hook _hook_##hookname = { \ + .name = #hookname, .entries = NULL, \ + }; \ + static int hook_call_##hookname arglist \ + { \ + int hooksum = 0; \ + struct hookent *he = _hook_##hookname.entries; \ + void *hookarg; \ + union { \ + void *voidptr; \ + int(*fptr) arglist; \ + int(*farg) HOOK_ADDDEF arglist; \ + } hookp; \ + for (; he; he = he->next) { \ + hookarg = he->hookarg; \ + hookp.voidptr = he->hookfn; \ + if (!he->has_arg) \ + hooksum += hookp.fptr passlist; \ + else \ + hooksum += hookp.farg HOOK_ADDARG passlist; \ + } \ + return hooksum; \ } #endif /* _FRR_HOOK_H */ diff --git a/lib/if.c b/lib/if.c index 8b64aef9a..4e4534851 100644 --- a/lib/if.c +++ b/lib/if.c @@ -1,4 +1,4 @@ -/* +/* * Interface functions. * Copyright (C) 1997, 98 Kunihiro Ishiguro * @@ -34,11 +34,11 @@ #include "buffer.h" #include "log.h" -DEFINE_MTYPE( LIB, IF, "Interface") -DEFINE_MTYPE_STATIC(LIB, CONNECTED, "Connected") -DEFINE_MTYPE_STATIC(LIB, NBR_CONNECTED, "Neighbor Connected") -DEFINE_MTYPE( LIB, CONNECTED_LABEL, "Connected interface label") -DEFINE_MTYPE_STATIC(LIB, IF_LINK_PARAMS, "Informational Link Parameters") +DEFINE_MTYPE(LIB, IF, "Interface") +DEFINE_MTYPE_STATIC(LIB, CONNECTED, "Connected") +DEFINE_MTYPE_STATIC(LIB, NBR_CONNECTED, "Neighbor Connected") +DEFINE_MTYPE(LIB, CONNECTED_LABEL, "Connected interface label") +DEFINE_MTYPE_STATIC(LIB, IF_LINK_PARAMS, "Informational Link Parameters") DEFINE_QOBJ_TYPE(interface) @@ -46,11 +46,12 @@ DEFINE_QOBJ_TYPE(interface) int ptm_enable = 0; /* One for each program. This structure is needed to store hooks. */ -struct if_master -{ - int (*if_new_hook) (struct interface *); - int (*if_delete_hook) (struct interface *); -} if_master = {0,}; +struct if_master { + int (*if_new_hook)(struct interface *); + int (*if_delete_hook)(struct interface *); +} if_master = { + 0, +}; /* Compare interface names, returning an integer greater than, equal to, or * less than 0, (following the strcmp convention), according to the @@ -59,544 +60,516 @@ struct if_master * lexicographic by name, and then numeric by number. No number sorts * before all numbers. Examples: de0 < de1, de100 < fxp0 < xl0, devpty < * devpty0, de0 < del0 - */ -int -if_cmp_name_func (char *p1, char *p2) + */ +int if_cmp_name_func(char *p1, char *p2) { - unsigned int l1, l2; - long int x1, x2; - int res; - - while (*p1 && *p2) { - /* look up to any number */ - l1 = strcspn(p1, "0123456789"); - l2 = strcspn(p2, "0123456789"); - - /* name lengths are different -> compare names */ - if (l1 != l2) - return (strcmp(p1, p2)); - - /* Note that this relies on all numbers being less than all letters, so - * that de0 < del0. - */ - res = strncmp(p1, p2, l1); - - /* names are different -> compare them */ - if (res) - return res; - - /* with identical name part, go to numeric part */ - p1 += l1; - p2 += l1; - - if (!*p1) - return -1; - if (!*p2) - return 1; - - x1 = strtol(p1, &p1, 10); - x2 = strtol(p2, &p2, 10); - - /* let's compare numbers now */ - if (x1 < x2) - return -1; - if (x1 > x2) - return 1; - - /* numbers were equal, lets do it again.. - (it happens with name like "eth123.456:789") */ - } - if (*p1) - return 1; - if (*p2) - return -1; - return 0; + unsigned int l1, l2; + long int x1, x2; + int res; + + while (*p1 && *p2) { + /* look up to any number */ + l1 = strcspn(p1, "0123456789"); + l2 = strcspn(p2, "0123456789"); + + /* name lengths are different -> compare names */ + if (l1 != l2) + return (strcmp(p1, p2)); + + /* Note that this relies on all numbers being less than all + * letters, so + * that de0 < del0. + */ + res = strncmp(p1, p2, l1); + + /* names are different -> compare them */ + if (res) + return res; + + /* with identical name part, go to numeric part */ + p1 += l1; + p2 += l1; + + if (!*p1) + return -1; + if (!*p2) + return 1; + + x1 = strtol(p1, &p1, 10); + x2 = strtol(p2, &p2, 10); + + /* let's compare numbers now */ + if (x1 < x2) + return -1; + if (x1 > x2) + return 1; + + /* numbers were equal, lets do it again.. + (it happens with name like "eth123.456:789") */ + } + if (*p1) + return 1; + if (*p2) + return -1; + return 0; } -static int -if_cmp_func (struct interface *ifp1, struct interface *ifp2) +static int if_cmp_func(struct interface *ifp1, struct interface *ifp2) { - return if_cmp_name_func (ifp1->name, ifp2->name); + return if_cmp_name_func(ifp1->name, ifp2->name); } /* Create new interface structure. */ -struct interface * -if_create (const char *name, int namelen, vrf_id_t vrf_id) +struct interface *if_create(const char *name, int namelen, vrf_id_t vrf_id) { - struct interface *ifp; - struct list *intf_list = vrf_iflist_get (vrf_id); - - ifp = XCALLOC (MTYPE_IF, sizeof (struct interface)); - ifp->ifindex = IFINDEX_INTERNAL; - - assert (name); - assert (namelen <= INTERFACE_NAMSIZ); /* Need space for '\0' at end. */ - strncpy (ifp->name, name, namelen); - ifp->name[namelen] = '\0'; - ifp->vrf_id = vrf_id; - if (if_lookup_by_name (ifp->name, vrf_id) == NULL) - listnode_add_sort (intf_list, ifp); - else - zlog_err("if_create(%s): corruption detected -- interface with this " - "name exists already in VRF %u!", ifp->name, vrf_id); - ifp->connected = list_new (); - ifp->connected->del = (void (*) (void *)) connected_free; + struct interface *ifp; + struct list *intf_list = vrf_iflist_get(vrf_id); + + ifp = XCALLOC(MTYPE_IF, sizeof(struct interface)); + ifp->ifindex = IFINDEX_INTERNAL; + + assert(name); + assert(namelen <= INTERFACE_NAMSIZ); /* Need space for '\0' at end. */ + strncpy(ifp->name, name, namelen); + ifp->name[namelen] = '\0'; + ifp->vrf_id = vrf_id; + if (if_lookup_by_name(ifp->name, vrf_id) == NULL) + listnode_add_sort(intf_list, ifp); + else + zlog_err( + "if_create(%s): corruption detected -- interface with this " + "name exists already in VRF %u!", + ifp->name, vrf_id); + ifp->connected = list_new(); + ifp->connected->del = (void (*)(void *))connected_free; + + ifp->nbr_connected = list_new(); + ifp->nbr_connected->del = (void (*)(void *))nbr_connected_free; + + /* Enable Link-detection by default */ + SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION); + + QOBJ_REG(ifp, interface); + + if (if_master.if_new_hook) + (*if_master.if_new_hook)(ifp); - ifp->nbr_connected = list_new (); - ifp->nbr_connected->del = (void (*) (void *)) nbr_connected_free; - - /* Enable Link-detection by default */ - SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION); - - QOBJ_REG (ifp, interface); - - if (if_master.if_new_hook) - (*if_master.if_new_hook) (ifp); - - return ifp; + return ifp; } /* Create new interface structure. */ -void -if_update_to_new_vrf (struct interface *ifp, vrf_id_t vrf_id) +void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id) { - struct list *intf_list = vrf_iflist_get (vrf_id); - - /* remove interface from old master vrf list */ - if (vrf_iflist (ifp->vrf_id)) - listnode_delete (vrf_iflist (ifp->vrf_id), ifp); - - ifp->vrf_id = vrf_id; - if (if_lookup_by_name (ifp->name, vrf_id) == NULL) - listnode_add_sort (intf_list, ifp); - else - zlog_err("if_create(%s): corruption detected -- interface with this " - "name exists already in VRF %u!", ifp->name, vrf_id); - - return; + struct list *intf_list = vrf_iflist_get(vrf_id); + + /* remove interface from old master vrf list */ + if (vrf_iflist(ifp->vrf_id)) + listnode_delete(vrf_iflist(ifp->vrf_id), ifp); + + ifp->vrf_id = vrf_id; + if (if_lookup_by_name(ifp->name, vrf_id) == NULL) + listnode_add_sort(intf_list, ifp); + else + zlog_err( + "if_create(%s): corruption detected -- interface with this " + "name exists already in VRF %u!", + ifp->name, vrf_id); + + return; } /* Delete interface structure. */ -void -if_delete_retain (struct interface *ifp) +void if_delete_retain(struct interface *ifp) { - if (if_master.if_delete_hook) - (*if_master.if_delete_hook) (ifp); + if (if_master.if_delete_hook) + (*if_master.if_delete_hook)(ifp); - QOBJ_UNREG (ifp); + QOBJ_UNREG(ifp); - /* Free connected address list */ - list_delete_all_node (ifp->connected); + /* Free connected address list */ + list_delete_all_node(ifp->connected); - /* Free connected nbr address list */ - list_delete_all_node (ifp->nbr_connected); + /* Free connected nbr address list */ + list_delete_all_node(ifp->nbr_connected); } /* Delete and free interface structure. */ -void -if_delete (struct interface *ifp) +void if_delete(struct interface *ifp) { - listnode_delete (vrf_iflist (ifp->vrf_id), ifp); + listnode_delete(vrf_iflist(ifp->vrf_id), ifp); - if_delete_retain(ifp); + if_delete_retain(ifp); - list_free (ifp->connected); - list_free (ifp->nbr_connected); + list_free(ifp->connected); + list_free(ifp->nbr_connected); - if_link_params_free (ifp); + if_link_params_free(ifp); - XFREE (MTYPE_IF, ifp); + XFREE(MTYPE_IF, ifp); } /* Add hook to interface master. */ -void -if_add_hook (int type, int (*func)(struct interface *ifp)) +void if_add_hook(int type, int (*func)(struct interface *ifp)) { - switch (type) { - case IF_NEW_HOOK: - if_master.if_new_hook = func; - break; - case IF_DELETE_HOOK: - if_master.if_delete_hook = func; - break; - default: - break; - } + switch (type) { + case IF_NEW_HOOK: + if_master.if_new_hook = func; + break; + case IF_DELETE_HOOK: + if_master.if_delete_hook = func; + break; + default: + break; + } } /* Interface existance check by index. */ -struct interface * -if_lookup_by_index (ifindex_t ifindex, vrf_id_t vrf_id) +struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id) { - struct listnode *node; - struct interface *ifp; + struct listnode *node; + struct interface *ifp; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) - { - if (ifp->ifindex == ifindex) - return ifp; - } - return NULL; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) { + if (ifp->ifindex == ifindex) + return ifp; + } + return NULL; } -const char * -ifindex2ifname (ifindex_t ifindex, vrf_id_t vrf_id) +const char *ifindex2ifname(ifindex_t ifindex, vrf_id_t vrf_id) { - struct interface *ifp; + struct interface *ifp; - return ((ifp = if_lookup_by_index (ifindex, vrf_id)) != NULL) ? - ifp->name : "unknown"; + return ((ifp = if_lookup_by_index(ifindex, vrf_id)) != NULL) + ? ifp->name + : "unknown"; } -ifindex_t -ifname2ifindex (const char *name, vrf_id_t vrf_id) +ifindex_t ifname2ifindex(const char *name, vrf_id_t vrf_id) { - struct interface *ifp; + struct interface *ifp; - return ((ifp = if_lookup_by_name (name, vrf_id)) != NULL) ? ifp->ifindex - : IFINDEX_INTERNAL; + return ((ifp = if_lookup_by_name(name, vrf_id)) != NULL) + ? ifp->ifindex + : IFINDEX_INTERNAL; } /* Interface existance check by interface name. */ -struct interface * -if_lookup_by_name (const char *name, vrf_id_t vrf_id) +struct interface *if_lookup_by_name(const char *name, vrf_id_t vrf_id) { - struct listnode *node; - struct interface *ifp; - - if (name) - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) - { - if (strcmp(name, ifp->name) == 0) - return ifp; - } - return NULL; + struct listnode *node; + struct interface *ifp; + + if (name) + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) { + if (strcmp(name, ifp->name) == 0) + return ifp; + } + return NULL; } -struct interface * -if_lookup_by_name_all_vrf (const char *name) +struct interface *if_lookup_by_name_all_vrf(const char *name) { - struct vrf *vrf; - struct interface *ifp; + struct vrf *vrf; + struct interface *ifp; - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - { - ifp = if_lookup_by_name (name, vrf->vrf_id); - if (ifp) - return ifp; - } + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + { + ifp = if_lookup_by_name(name, vrf->vrf_id); + if (ifp) + return ifp; + } - return NULL; + return NULL; } -struct interface * -if_lookup_by_name_len (const char *name, size_t namelen, vrf_id_t vrf_id) +struct interface *if_lookup_by_name_len(const char *name, size_t namelen, + vrf_id_t vrf_id) { - struct listnode *node; - struct interface *ifp; + struct listnode *node; + struct interface *ifp; - if (namelen > INTERFACE_NAMSIZ) - return NULL; + if (namelen > INTERFACE_NAMSIZ) + return NULL; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) - { - if (!memcmp(name, ifp->name, namelen) && (ifp->name[namelen] == '\0')) - return ifp; - } - return NULL; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) { + if (!memcmp(name, ifp->name, namelen) + && (ifp->name[namelen] == '\0')) + return ifp; + } + return NULL; } /* Lookup interface by IPv4 address. */ -struct interface * -if_lookup_exact_address (void *src, int family, vrf_id_t vrf_id) +struct interface *if_lookup_exact_address(void *src, int family, + vrf_id_t vrf_id) { - struct listnode *node; - struct listnode *cnode; - struct interface *ifp; - struct prefix *p; - struct connected *c; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) - { - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) - { - p = c->address; - - if (p && (p->family == family)) - { - if (family == AF_INET) - { - if (IPV4_ADDR_SAME (&p->u.prefix4, (struct in_addr *)src)) - return ifp; - } - else if (family == AF_INET6) - { - if (IPV6_ADDR_SAME (&p->u.prefix6, (struct in6_addr *)src)) - return ifp; + struct listnode *node; + struct listnode *cnode; + struct interface *ifp; + struct prefix *p; + struct connected *c; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) { + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { + p = c->address; + + if (p && (p->family == family)) { + if (family == AF_INET) { + if (IPV4_ADDR_SAME( + &p->u.prefix4, + (struct in_addr *)src)) + return ifp; + } else if (family == AF_INET6) { + if (IPV6_ADDR_SAME( + &p->u.prefix6, + (struct in6_addr *)src)) + return ifp; + } + } } - } } - } - return NULL; + return NULL; } /* Lookup interface by IPv4 address. */ -struct connected * -if_lookup_address (void *matchaddr, int family, vrf_id_t vrf_id) +struct connected *if_lookup_address(void *matchaddr, int family, + vrf_id_t vrf_id) { - struct listnode *node; - struct prefix addr; - int bestlen = 0; - struct listnode *cnode; - struct interface *ifp; - struct connected *c; - struct connected *match; - - if (family == AF_INET) - { - addr.family = AF_INET; - addr.u.prefix4 = *((struct in_addr *)matchaddr); - addr.prefixlen = IPV4_MAX_BITLEN; - } - else if (family == AF_INET6) - { - addr.family = AF_INET6; - addr.u.prefix6 = *((struct in6_addr *)matchaddr); - addr.prefixlen = IPV6_MAX_BITLEN; - } + struct listnode *node; + struct prefix addr; + int bestlen = 0; + struct listnode *cnode; + struct interface *ifp; + struct connected *c; + struct connected *match; + + if (family == AF_INET) { + addr.family = AF_INET; + addr.u.prefix4 = *((struct in_addr *)matchaddr); + addr.prefixlen = IPV4_MAX_BITLEN; + } else if (family == AF_INET6) { + addr.family = AF_INET6; + addr.u.prefix6 = *((struct in6_addr *)matchaddr); + addr.prefixlen = IPV6_MAX_BITLEN; + } - match = NULL; + match = NULL; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) - { - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) - { - if (c->address && (c->address->family == AF_INET) && - prefix_match(CONNECTED_PREFIX(c), &addr) && - (c->address->prefixlen > bestlen)) - { - bestlen = c->address->prefixlen; - match = c; - } + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) { + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { + if (c->address && (c->address->family == AF_INET) + && prefix_match(CONNECTED_PREFIX(c), &addr) + && (c->address->prefixlen > bestlen)) { + bestlen = c->address->prefixlen; + match = c; + } + } } - } - return match; + return match; } /* Lookup interface by prefix */ -struct interface * -if_lookup_prefix (struct prefix *prefix, vrf_id_t vrf_id) +struct interface *if_lookup_prefix(struct prefix *prefix, vrf_id_t vrf_id) { - struct listnode *node; - struct listnode *cnode; - struct interface *ifp; - struct connected *c; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) - { - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) - { - if (prefix_cmp(c->address, prefix) == 0) - { - return ifp; - } - } - } - return NULL; + struct listnode *node; + struct listnode *cnode; + struct interface *ifp; + struct connected *c; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) { + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { + if (prefix_cmp(c->address, prefix) == 0) { + return ifp; + } + } + } + return NULL; } /* Get interface by name if given name interface doesn't exist create one. */ -struct interface * -if_get_by_name (const char *name, vrf_id_t vrf_id) +struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id) { - struct interface *ifp; + struct interface *ifp; - return ((ifp = if_lookup_by_name (name, vrf_id)) != NULL) ? ifp : - if_create (name, strlen(name), vrf_id); + return ((ifp = if_lookup_by_name(name, vrf_id)) != NULL) + ? ifp + : if_create(name, strlen(name), vrf_id); } -struct interface * -if_get_by_name_len (const char *name, size_t namelen, vrf_id_t vrf_id, int vty) +struct interface *if_get_by_name_len(const char *name, size_t namelen, + vrf_id_t vrf_id, int vty) { - struct interface *ifp; - struct vrf *vrf; - struct listnode *node; + struct interface *ifp; + struct vrf *vrf; + struct listnode *node; - ifp = if_lookup_by_name_len (name, namelen, vrf_id); - if (ifp) - return ifp; + ifp = if_lookup_by_name_len(name, namelen, vrf_id); + if (ifp) + return ifp; - /* Didn't find the interface on that vrf. Defined on a different one? */ - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - { - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf->vrf_id), node, ifp)) + /* Didn't find the interface on that vrf. Defined on a different one? */ + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) { - if (!memcmp(name, ifp->name, namelen) && (ifp->name[namelen] == '\0')) - { - /* Found a match. If the interface command was entered in vty without a - * VRF (passed as VRF_DEFAULT), accept the ifp we found. If a vrf was - * entered and there is a mismatch, reject it if from vty. If it came - * from the kernel by way of zclient, believe it and update - * the ifp accordingly. - */ - if (vty) - { - if (vrf_id == VRF_DEFAULT) - return ifp; - return NULL; - } - else - { - if_update_to_new_vrf (ifp, vrf_id); - return ifp; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf->vrf_id), node, ifp)) { + if (!memcmp(name, ifp->name, namelen) + && (ifp->name[namelen] == '\0')) { + /* Found a match. If the interface command was + * entered in vty without a + * VRF (passed as VRF_DEFAULT), accept the ifp + * we found. If a vrf was + * entered and there is a mismatch, reject it if + * from vty. If it came + * from the kernel by way of zclient, believe + * it and update + * the ifp accordingly. + */ + if (vty) { + if (vrf_id == VRF_DEFAULT) + return ifp; + return NULL; + } else { + if_update_to_new_vrf(ifp, vrf_id); + return ifp; + } + } } - } } - } - return (if_create (name, namelen, vrf_id)); + return (if_create(name, namelen, vrf_id)); } /* Does interface up ? */ -int -if_is_up (struct interface *ifp) +int if_is_up(struct interface *ifp) { - return ifp->flags & IFF_UP; + return ifp->flags & IFF_UP; } /* Is interface running? */ -int -if_is_running (struct interface *ifp) +int if_is_running(struct interface *ifp) { - return ifp->flags & IFF_RUNNING; + return ifp->flags & IFF_RUNNING; } /* Is the interface operative, eg. either UP & RUNNING or UP & !ZEBRA_INTERFACE_LINK_DETECTION and if ptm checking is enabled, then ptm check has passed */ -int -if_is_operative (struct interface *ifp) +int if_is_operative(struct interface *ifp) { - return ((ifp->flags & IFF_UP) && - (((ifp->flags & IFF_RUNNING) && - (ifp->ptm_status || !ifp->ptm_enable)) || - !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))); + return ((ifp->flags & IFF_UP) + && (((ifp->flags & IFF_RUNNING) + && (ifp->ptm_status || !ifp->ptm_enable)) + || !CHECK_FLAG(ifp->status, + ZEBRA_INTERFACE_LINKDETECTION))); } /* Is the interface operative, eg. either UP & RUNNING or UP & !ZEBRA_INTERFACE_LINK_DETECTION, without PTM check */ -int -if_is_no_ptm_operative (struct interface *ifp) +int if_is_no_ptm_operative(struct interface *ifp) { - return ((ifp->flags & IFF_UP) && - ((ifp->flags & IFF_RUNNING) || - !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))); + return ((ifp->flags & IFF_UP) + && ((ifp->flags & IFF_RUNNING) + || !CHECK_FLAG(ifp->status, + ZEBRA_INTERFACE_LINKDETECTION))); } /* Is this loopback interface ? */ -int -if_is_loopback (struct interface *ifp) +int if_is_loopback(struct interface *ifp) { - /* XXX: Do this better, eg what if IFF_WHATEVER means X on platform M - * but Y on platform N? - */ - return (ifp->flags & (IFF_LOOPBACK|IFF_NOXMIT|IFF_VIRTUAL)); + /* XXX: Do this better, eg what if IFF_WHATEVER means X on platform M + * but Y on platform N? + */ + return (ifp->flags & (IFF_LOOPBACK | IFF_NOXMIT | IFF_VIRTUAL)); } /* Does this interface support broadcast ? */ -int -if_is_broadcast (struct interface *ifp) +int if_is_broadcast(struct interface *ifp) { - return ifp->flags & IFF_BROADCAST; + return ifp->flags & IFF_BROADCAST; } /* Does this interface support broadcast ? */ -int -if_is_pointopoint (struct interface *ifp) +int if_is_pointopoint(struct interface *ifp) { - return ifp->flags & IFF_POINTOPOINT; + return ifp->flags & IFF_POINTOPOINT; } /* Does this interface support multicast ? */ -int -if_is_multicast (struct interface *ifp) +int if_is_multicast(struct interface *ifp) { - return ifp->flags & IFF_MULTICAST; + return ifp->flags & IFF_MULTICAST; } /* Printout flag information into log */ -const char * -if_flag_dump (unsigned long flag) +const char *if_flag_dump(unsigned long flag) { - int separator = 0; - static char logbuf[BUFSIZ]; - -#define IFF_OUT_LOG(X,STR) \ - if (flag & (X)) \ - { \ - if (separator) \ - strlcat (logbuf, ",", BUFSIZ); \ - else \ - separator = 1; \ - strlcat (logbuf, STR, BUFSIZ); \ - } + int separator = 0; + static char logbuf[BUFSIZ]; + +#define IFF_OUT_LOG(X, STR) \ + if (flag & (X)) { \ + if (separator) \ + strlcat(logbuf, ",", BUFSIZ); \ + else \ + separator = 1; \ + strlcat(logbuf, STR, BUFSIZ); \ + } - strlcpy (logbuf, "<", BUFSIZ); - IFF_OUT_LOG (IFF_UP, "UP"); - IFF_OUT_LOG (IFF_BROADCAST, "BROADCAST"); - IFF_OUT_LOG (IFF_DEBUG, "DEBUG"); - IFF_OUT_LOG (IFF_LOOPBACK, "LOOPBACK"); - IFF_OUT_LOG (IFF_POINTOPOINT, "POINTOPOINT"); - IFF_OUT_LOG (IFF_NOTRAILERS, "NOTRAILERS"); - IFF_OUT_LOG (IFF_RUNNING, "RUNNING"); - IFF_OUT_LOG (IFF_NOARP, "NOARP"); - IFF_OUT_LOG (IFF_PROMISC, "PROMISC"); - IFF_OUT_LOG (IFF_ALLMULTI, "ALLMULTI"); - IFF_OUT_LOG (IFF_OACTIVE, "OACTIVE"); - IFF_OUT_LOG (IFF_SIMPLEX, "SIMPLEX"); - IFF_OUT_LOG (IFF_LINK0, "LINK0"); - IFF_OUT_LOG (IFF_LINK1, "LINK1"); - IFF_OUT_LOG (IFF_LINK2, "LINK2"); - IFF_OUT_LOG (IFF_MULTICAST, "MULTICAST"); - IFF_OUT_LOG (IFF_NOXMIT, "NOXMIT"); - IFF_OUT_LOG (IFF_NORTEXCH, "NORTEXCH"); - IFF_OUT_LOG (IFF_VIRTUAL, "VIRTUAL"); - IFF_OUT_LOG (IFF_IPV4, "IPv4"); - IFF_OUT_LOG (IFF_IPV6, "IPv6"); - - strlcat (logbuf, ">", BUFSIZ); - - return logbuf; + strlcpy(logbuf, "<", BUFSIZ); + IFF_OUT_LOG(IFF_UP, "UP"); + IFF_OUT_LOG(IFF_BROADCAST, "BROADCAST"); + IFF_OUT_LOG(IFF_DEBUG, "DEBUG"); + IFF_OUT_LOG(IFF_LOOPBACK, "LOOPBACK"); + IFF_OUT_LOG(IFF_POINTOPOINT, "POINTOPOINT"); + IFF_OUT_LOG(IFF_NOTRAILERS, "NOTRAILERS"); + IFF_OUT_LOG(IFF_RUNNING, "RUNNING"); + IFF_OUT_LOG(IFF_NOARP, "NOARP"); + IFF_OUT_LOG(IFF_PROMISC, "PROMISC"); + IFF_OUT_LOG(IFF_ALLMULTI, "ALLMULTI"); + IFF_OUT_LOG(IFF_OACTIVE, "OACTIVE"); + IFF_OUT_LOG(IFF_SIMPLEX, "SIMPLEX"); + IFF_OUT_LOG(IFF_LINK0, "LINK0"); + IFF_OUT_LOG(IFF_LINK1, "LINK1"); + IFF_OUT_LOG(IFF_LINK2, "LINK2"); + IFF_OUT_LOG(IFF_MULTICAST, "MULTICAST"); + IFF_OUT_LOG(IFF_NOXMIT, "NOXMIT"); + IFF_OUT_LOG(IFF_NORTEXCH, "NORTEXCH"); + IFF_OUT_LOG(IFF_VIRTUAL, "VIRTUAL"); + IFF_OUT_LOG(IFF_IPV4, "IPv4"); + IFF_OUT_LOG(IFF_IPV6, "IPv6"); + + strlcat(logbuf, ">", BUFSIZ); + + return logbuf; #undef IFF_OUT_LOG } /* For debugging */ -static void -if_dump (const struct interface *ifp) +static void if_dump(const struct interface *ifp) { - struct listnode *node; - struct connected *c __attribute__((unused)); - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, c)) - zlog_info ("Interface %s vrf %u index %d metric %d mtu %d " - "mtu6 %d %s", - ifp->name, ifp->vrf_id, ifp->ifindex, ifp->metric, ifp->mtu, - ifp->mtu6, if_flag_dump (ifp->flags)); + struct listnode *node; + struct connected *c __attribute__((unused)); + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, c)) + zlog_info( + "Interface %s vrf %u index %d metric %d mtu %d " + "mtu6 %d %s", + ifp->name, ifp->vrf_id, ifp->ifindex, ifp->metric, + ifp->mtu, ifp->mtu6, if_flag_dump(ifp->flags)); } /* Interface printing for all interface. */ -void -if_dump_all (void) +void if_dump_all(void) { - struct vrf *vrf; - struct listnode *node; - void *p; - - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - if (vrf->iflist != NULL) - for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, p)) - if_dump (p); + struct vrf *vrf; + struct listnode *node; + void *p; + + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + if (vrf->iflist != NULL) + for (ALL_LIST_ELEMENTS_RO(vrf->iflist, node, p)) + if_dump(p); } DEFUN (interface_desc, @@ -605,14 +578,14 @@ DEFUN (interface_desc, "Interface specific description\n" "Characters describing this interface\n") { - int idx_line = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); + int idx_line = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); - if (ifp->desc) - XFREE (MTYPE_TMP, ifp->desc); - ifp->desc = argv_concat(argv, argc, idx_line); + if (ifp->desc) + XFREE(MTYPE_TMP, ifp->desc); + ifp->desc = argv_concat(argv, argc, idx_line); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_interface_desc, @@ -621,13 +594,13 @@ DEFUN (no_interface_desc, NO_STR "Interface specific description\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - if (ifp->desc) - XFREE (MTYPE_TMP, ifp->desc); - ifp->desc = NULL; + if (ifp->desc) + XFREE(MTYPE_TMP, ifp->desc); + ifp->desc = NULL; - return CMD_SUCCESS; + return CMD_SUCCESS; } #ifdef SUNOS_5 @@ -651,24 +624,24 @@ DEFUN (no_interface_desc, * if not: * - no idea, just get the name in its entirety. */ -static struct interface * -if_sunwzebra_get (const char *name, size_t nlen, vrf_id_t vrf_id) +static struct interface *if_sunwzebra_get(const char *name, size_t nlen, + vrf_id_t vrf_id) { - struct interface *ifp; - size_t seppos = 0; - - if ( (ifp = if_lookup_by_name_len (name, nlen, vrf_id)) != NULL) - return ifp; - - /* hunt the primary interface name... */ - while (seppos < nlen && name[seppos] != ':') - seppos++; - - /* Wont catch seperator as last char, e.g. 'foo0:' but thats invalid */ - if (seppos < nlen) - return if_get_by_name_len (name, seppos, vrf_id, 1); - else - return if_get_by_name_len (name, nlen, vrf_id, 1); + struct interface *ifp; + size_t seppos = 0; + + if ((ifp = if_lookup_by_name_len(name, nlen, vrf_id)) != NULL) + return ifp; + + /* hunt the primary interface name... */ + while (seppos < nlen && name[seppos] != ':') + seppos++; + + /* Wont catch seperator as last char, e.g. 'foo0:' but thats invalid */ + if (seppos < nlen) + return if_get_by_name_len(name, seppos, vrf_id, 1); + else + return if_get_by_name_len(name, nlen, vrf_id, 1); } #endif /* SUNOS_5 */ @@ -679,42 +652,41 @@ DEFUN (interface, "Interface's name\n" VRF_CMD_HELP_STR) { - int idx_ifname = 1; - int idx_vrf = 3; - const char *ifname = argv[idx_ifname]->arg; - const char *vrfname = (argc > 2) ? argv[idx_vrf]->arg : NULL; - - struct interface *ifp; - size_t sl; - vrf_id_t vrf_id = VRF_DEFAULT; - - if ((sl = strlen(ifname)) > INTERFACE_NAMSIZ) - { - vty_out (vty, "%% Interface name %s is invalid: length exceeds " - "%d characters\n", - ifname, INTERFACE_NAMSIZ); - return CMD_WARNING_CONFIG_FAILED; - } + int idx_ifname = 1; + int idx_vrf = 3; + const char *ifname = argv[idx_ifname]->arg; + const char *vrfname = (argc > 2) ? argv[idx_vrf]->arg : NULL; + + struct interface *ifp; + size_t sl; + vrf_id_t vrf_id = VRF_DEFAULT; + + if ((sl = strlen(ifname)) > INTERFACE_NAMSIZ) { + vty_out(vty, + "%% Interface name %s is invalid: length exceeds " + "%d characters\n", + ifname, INTERFACE_NAMSIZ); + return CMD_WARNING_CONFIG_FAILED; + } -/*Pending: need proper vrf name based lookup/(possible creation of VRF) - Imagine forward reference of a vrf by name in this interface config */ - if (vrfname) - VRF_GET_ID (vrf_id, vrfname); + /*Pending: need proper vrf name based lookup/(possible creation of VRF) + Imagine forward reference of a vrf by name in this interface config */ + if (vrfname) + VRF_GET_ID(vrf_id, vrfname); #ifdef SUNOS_5 - ifp = if_sunwzebra_get (ifname, sl, vrf_id); + ifp = if_sunwzebra_get(ifname, sl, vrf_id); #else - ifp = if_get_by_name_len (ifname, sl, vrf_id, 1); + ifp = if_get_by_name_len(ifname, sl, vrf_id, 1); #endif /* SUNOS_5 */ - if (!ifp) - { - vty_out (vty, "%% interface %s not in %s\n", ifname, vrfname); - return CMD_WARNING_CONFIG_FAILED; - } - VTY_PUSH_CONTEXT (INTERFACE_NODE, ifp); + if (!ifp) { + vty_out(vty, "%% interface %s not in %s\n", ifname, vrfname); + return CMD_WARNING_CONFIG_FAILED; + } + VTY_PUSH_CONTEXT(INTERFACE_NODE, ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_NOSH (no_interface, @@ -725,44 +697,41 @@ DEFUN_NOSH (no_interface, "Interface's name\n" VRF_CMD_HELP_STR) { - const char *ifname = argv[2]->arg; - const char *vrfname = (argc > 3) ? argv[3]->arg : NULL; + const char *ifname = argv[2]->arg; + const char *vrfname = (argc > 3) ? argv[3]->arg : NULL; - // deleting interface - struct interface *ifp; - vrf_id_t vrf_id = VRF_DEFAULT; + // deleting interface + struct interface *ifp; + vrf_id_t vrf_id = VRF_DEFAULT; - if (argc > 3) - VRF_GET_ID (vrf_id, vrfname); + if (argc > 3) + VRF_GET_ID(vrf_id, vrfname); - ifp = if_lookup_by_name (ifname, vrf_id); + ifp = if_lookup_by_name(ifname, vrf_id); - if (ifp == NULL) - { - vty_out (vty, "%% Interface %s does not exist\n", ifname); - return CMD_WARNING_CONFIG_FAILED; - } + if (ifp == NULL) { + vty_out(vty, "%% Interface %s does not exist\n", ifname); + return CMD_WARNING_CONFIG_FAILED; + } - if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) - { - vty_out (vty, "%% Only inactive interfaces can be deleted\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + vty_out(vty, "%% Only inactive interfaces can be deleted\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if_delete(ifp); + if_delete(ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } -void -if_cmd_init (void) +void if_cmd_init(void) { - install_element (CONFIG_NODE, &interface_cmd); - install_element (CONFIG_NODE, &no_interface_cmd); + install_element(CONFIG_NODE, &interface_cmd); + install_element(CONFIG_NODE, &no_interface_cmd); - install_default (INTERFACE_NODE); - install_element (INTERFACE_NODE, &interface_desc_cmd); - install_element (INTERFACE_NODE, &no_interface_desc_cmd); + install_default(INTERFACE_NODE); + install_element(INTERFACE_NODE, &interface_desc_cmd); + install_element(INTERFACE_NODE, &no_interface_desc_cmd); } #if 0 @@ -835,212 +804,199 @@ DEFUN (show_address_vrf_all, #endif /* Allocate connected structure. */ -struct connected * -connected_new (void) +struct connected *connected_new(void) { - return XCALLOC (MTYPE_CONNECTED, sizeof (struct connected)); + return XCALLOC(MTYPE_CONNECTED, sizeof(struct connected)); } /* Allocate nbr connected structure. */ -struct nbr_connected * -nbr_connected_new (void) +struct nbr_connected *nbr_connected_new(void) { - return XCALLOC (MTYPE_NBR_CONNECTED, sizeof (struct nbr_connected)); + return XCALLOC(MTYPE_NBR_CONNECTED, sizeof(struct nbr_connected)); } /* Free connected structure. */ -void -connected_free (struct connected *connected) +void connected_free(struct connected *connected) { - if (connected->address) - prefix_free (connected->address); + if (connected->address) + prefix_free(connected->address); - if (connected->destination) - prefix_free (connected->destination); + if (connected->destination) + prefix_free(connected->destination); - if (connected->label) - XFREE (MTYPE_CONNECTED_LABEL, connected->label); + if (connected->label) + XFREE(MTYPE_CONNECTED_LABEL, connected->label); - XFREE (MTYPE_CONNECTED, connected); + XFREE(MTYPE_CONNECTED, connected); } /* Free nbr connected structure. */ -void -nbr_connected_free (struct nbr_connected *connected) +void nbr_connected_free(struct nbr_connected *connected) { - if (connected->address) - prefix_free (connected->address); + if (connected->address) + prefix_free(connected->address); - XFREE (MTYPE_NBR_CONNECTED, connected); + XFREE(MTYPE_NBR_CONNECTED, connected); } /* If same interface nbr address already exists... */ -struct nbr_connected * -nbr_connected_check (struct interface *ifp, struct prefix *p) +struct nbr_connected *nbr_connected_check(struct interface *ifp, + struct prefix *p) { - struct nbr_connected *ifc; - struct listnode *node; + struct nbr_connected *ifc; + struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (ifp->nbr_connected, node, ifc)) - if (prefix_same (ifc->address, p)) - return ifc; + for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node, ifc)) + if (prefix_same(ifc->address, p)) + return ifc; - return NULL; + return NULL; } /* Print if_addr structure. */ -static void __attribute__ ((unused)) -connected_log (struct connected *connected, char *str) +static void __attribute__((unused)) +connected_log(struct connected *connected, char *str) { - struct prefix *p; - struct interface *ifp; - char logbuf[BUFSIZ]; - char buf[BUFSIZ]; - - ifp = connected->ifp; - p = connected->address; - - snprintf (logbuf, BUFSIZ, "%s interface %s vrf %u %s %s/%d ", - str, ifp->name, ifp->vrf_id, prefix_family_str (p), - inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), - p->prefixlen); - - p = connected->destination; - if (p) - { - strncat (logbuf, inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), - BUFSIZ - strlen(logbuf)); - } - zlog_info("%s", logbuf); + struct prefix *p; + struct interface *ifp; + char logbuf[BUFSIZ]; + char buf[BUFSIZ]; + + ifp = connected->ifp; + p = connected->address; + + snprintf(logbuf, BUFSIZ, "%s interface %s vrf %u %s %s/%d ", str, + ifp->name, ifp->vrf_id, prefix_family_str(p), + inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen); + + p = connected->destination; + if (p) { + strncat(logbuf, inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), + BUFSIZ - strlen(logbuf)); + } + zlog_info("%s", logbuf); } /* Print if_addr structure. */ -static void __attribute__ ((unused)) -nbr_connected_log (struct nbr_connected *connected, char *str) +static void __attribute__((unused)) +nbr_connected_log(struct nbr_connected *connected, char *str) { - struct prefix *p; - struct interface *ifp; - char logbuf[BUFSIZ]; - char buf[BUFSIZ]; + struct prefix *p; + struct interface *ifp; + char logbuf[BUFSIZ]; + char buf[BUFSIZ]; - ifp = connected->ifp; - p = connected->address; + ifp = connected->ifp; + p = connected->address; - snprintf (logbuf, BUFSIZ, "%s interface %s %s %s/%d ", - str, ifp->name, prefix_family_str (p), - inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), - p->prefixlen); + snprintf(logbuf, BUFSIZ, "%s interface %s %s %s/%d ", str, ifp->name, + prefix_family_str(p), + inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen); - zlog_info("%s", logbuf); + zlog_info("%s", logbuf); } /* If two connected address has same prefix return 1. */ -static int -connected_same_prefix (struct prefix *p1, struct prefix *p2) +static int connected_same_prefix(struct prefix *p1, struct prefix *p2) { - if (p1->family == p2->family) - { - if (p1->family == AF_INET && - IPV4_ADDR_SAME (&p1->u.prefix4, &p2->u.prefix4)) - return 1; - if (p1->family == AF_INET6 && - IPV6_ADDR_SAME (&p1->u.prefix6, &p2->u.prefix6)) - return 1; - } - return 0; + if (p1->family == p2->family) { + if (p1->family == AF_INET + && IPV4_ADDR_SAME(&p1->u.prefix4, &p2->u.prefix4)) + return 1; + if (p1->family == AF_INET6 + && IPV6_ADDR_SAME(&p1->u.prefix6, &p2->u.prefix6)) + return 1; + } + return 0; } -struct connected * -connected_lookup_prefix_exact (struct interface *ifp, struct prefix *p) +struct connected *connected_lookup_prefix_exact(struct interface *ifp, + struct prefix *p) { - struct listnode *node; - struct listnode *next; - struct connected *ifc; + struct listnode *node; + struct listnode *next; + struct connected *ifc; - for (node = listhead (ifp->connected); node; node = next) - { - ifc = listgetdata (node); - next = node->next; + for (node = listhead(ifp->connected); node; node = next) { + ifc = listgetdata(node); + next = node->next; - if (connected_same_prefix (ifc->address, p)) - return ifc; - } - return NULL; + if (connected_same_prefix(ifc->address, p)) + return ifc; + } + return NULL; } -struct connected * -connected_delete_by_prefix (struct interface *ifp, struct prefix *p) +struct connected *connected_delete_by_prefix(struct interface *ifp, + struct prefix *p) { - struct listnode *node; - struct listnode *next; - struct connected *ifc; - - /* In case of same prefix come, replace it with new one. */ - for (node = listhead (ifp->connected); node; node = next) - { - ifc = listgetdata (node); - next = node->next; - - if (connected_same_prefix (ifc->address, p)) - { - listnode_delete (ifp->connected, ifc); - return ifc; + struct listnode *node; + struct listnode *next; + struct connected *ifc; + + /* In case of same prefix come, replace it with new one. */ + for (node = listhead(ifp->connected); node; node = next) { + ifc = listgetdata(node); + next = node->next; + + if (connected_same_prefix(ifc->address, p)) { + listnode_delete(ifp->connected, ifc); + return ifc; + } } - } - return NULL; + return NULL; } /* Find the address on our side that will be used when packets are sent to dst. */ -struct connected * -connected_lookup_prefix (struct interface *ifp, struct prefix *addr) +struct connected *connected_lookup_prefix(struct interface *ifp, + struct prefix *addr) { - struct listnode *cnode; - struct connected *c; - struct connected *match; - - match = NULL; - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) - { - if (c->address && (c->address->family == addr->family) && - prefix_match(CONNECTED_PREFIX(c), addr) && - (!match || (c->address->prefixlen > match->address->prefixlen))) - match = c; - } - return match; + struct listnode *cnode; + struct connected *c; + struct connected *match; + + match = NULL; + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { + if (c->address && (c->address->family == addr->family) + && prefix_match(CONNECTED_PREFIX(c), addr) + && (!match + || (c->address->prefixlen > match->address->prefixlen))) + match = c; + } + return match; } -struct connected * -connected_add_by_prefix (struct interface *ifp, struct prefix *p, - struct prefix *destination) +struct connected *connected_add_by_prefix(struct interface *ifp, + struct prefix *p, + struct prefix *destination) { - struct connected *ifc; + struct connected *ifc; - /* Allocate new connected address. */ - ifc = connected_new (); - ifc->ifp = ifp; + /* Allocate new connected address. */ + ifc = connected_new(); + ifc->ifp = ifp; - /* Fetch interface address */ - ifc->address = prefix_new(); - memcpy (ifc->address, p, sizeof(struct prefix)); + /* Fetch interface address */ + ifc->address = prefix_new(); + memcpy(ifc->address, p, sizeof(struct prefix)); - /* Fetch dest address */ - if (destination) - { - ifc->destination = prefix_new(); - memcpy (ifc->destination, destination, sizeof(struct prefix)); - } + /* Fetch dest address */ + if (destination) { + ifc->destination = prefix_new(); + memcpy(ifc->destination, destination, sizeof(struct prefix)); + } - /* Add connected address to the interface. */ - listnode_add (ifp->connected, ifc); - return ifc; + /* Add connected address to the interface. */ + listnode_add(ifp->connected, ifc); + return ifc; } -#if 0 /* this route_table of struct connected's is unused - * however, it would be good to use a route_table rather than - * a list.. - */ +#if 0 /* this route_table of struct connected's is unused \ + * however, it would be good to use a route_table rather than \ + * a list.. \ + */ /* Interface looking up by interface's address. */ /* Interface's IPv4 address reverse lookup table. */ struct route_table *ifaddr_ipv4_table; @@ -1118,170 +1074,157 @@ ifaddr_ipv4_lookup (struct in_addr *addr, ifindex_t ifindex) static void if_autocomplete(vector comps, struct cmd_token *token) { - struct interface *ifp; - struct listnode *ln; - struct vrf *vrf = NULL; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - for (ALL_LIST_ELEMENTS_RO(vrf->iflist, ln, ifp)) - vector_set (comps, XSTRDUP (MTYPE_COMPLETION, ifp->name)); - } + struct interface *ifp; + struct listnode *ln; + struct vrf *vrf = NULL; + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + for (ALL_LIST_ELEMENTS_RO(vrf->iflist, ln, ifp)) + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, ifp->name)); + } } static const struct cmd_variable_handler if_var_handlers[] = { - { - /* "interface NAME" */ - .varname = "interface", - .completions = if_autocomplete - }, { - .tokenname = "IFNAME", - .completions = if_autocomplete - }, { - .tokenname = "INTERFACE", - .completions = if_autocomplete - }, { - .completions = NULL - } -}; + {/* "interface NAME" */ + .varname = "interface", + .completions = if_autocomplete}, + {.tokenname = "IFNAME", .completions = if_autocomplete}, + {.tokenname = "INTERFACE", .completions = if_autocomplete}, + {.completions = NULL}}; /* Initialize interface list. */ -void -if_init (struct list **intf_list) +void if_init(struct list **intf_list) { - *intf_list = list_new (); + *intf_list = list_new(); #if 0 ifaddr_ipv4_table = route_table_init (); #endif /* ifaddr_ipv4_table */ - (*intf_list)->cmp = (int (*)(void *, void *))if_cmp_func; + (*intf_list)->cmp = (int (*)(void *, void *))if_cmp_func; - cmd_variable_handler_register(if_var_handlers); + cmd_variable_handler_register(if_var_handlers); } -void -if_terminate (struct list **intf_list) +void if_terminate(struct list **intf_list) { - for (;;) - { - struct interface *ifp; + for (;;) { + struct interface *ifp; - ifp = listnode_head (*intf_list); - if (ifp == NULL) - break; + ifp = listnode_head(*intf_list); + if (ifp == NULL) + break; - if (ifp->node) - { - ifp->node->info = NULL; - route_unlock_node (ifp->node); - } + if (ifp->node) { + ifp->node->info = NULL; + route_unlock_node(ifp->node); + } - if_delete (ifp); - } + if_delete(ifp); + } - list_delete (*intf_list); - *intf_list = NULL; + list_delete(*intf_list); + *intf_list = NULL; } -const char * -if_link_type_str (enum zebra_link_type llt) +const char *if_link_type_str(enum zebra_link_type llt) { - switch (llt) - { + switch (llt) { #define llts(T,S) case (T): return (S) - llts(ZEBRA_LLT_UNKNOWN, "Unknown"); - llts(ZEBRA_LLT_ETHER, "Ethernet"); - llts(ZEBRA_LLT_EETHER, "Experimental Ethernet"); - llts(ZEBRA_LLT_AX25, "AX.25 Level 2"); - llts(ZEBRA_LLT_PRONET, "PROnet token ring"); - llts(ZEBRA_LLT_IEEE802, "IEEE 802.2 Ethernet/TR/TB"); - llts(ZEBRA_LLT_ARCNET, "ARCnet"); - llts(ZEBRA_LLT_APPLETLK, "AppleTalk"); - llts(ZEBRA_LLT_DLCI, "Frame Relay DLCI"); - llts(ZEBRA_LLT_ATM, "ATM"); - llts(ZEBRA_LLT_METRICOM, "Metricom STRIP"); - llts(ZEBRA_LLT_IEEE1394, "IEEE 1394 IPv4"); - llts(ZEBRA_LLT_EUI64, "EUI-64"); - llts(ZEBRA_LLT_INFINIBAND, "InfiniBand"); - llts(ZEBRA_LLT_SLIP, "SLIP"); - llts(ZEBRA_LLT_CSLIP, "Compressed SLIP"); - llts(ZEBRA_LLT_SLIP6, "SLIPv6"); - llts(ZEBRA_LLT_CSLIP6, "Compressed SLIPv6"); - llts(ZEBRA_LLT_ROSE, "ROSE packet radio"); - llts(ZEBRA_LLT_X25, "CCITT X.25"); - llts(ZEBRA_LLT_PPP, "PPP"); - llts(ZEBRA_LLT_CHDLC, "Cisco HDLC"); - llts(ZEBRA_LLT_RAWHDLC, "Raw HDLC"); - llts(ZEBRA_LLT_LAPB, "LAPB"); - llts(ZEBRA_LLT_IPIP, "IPIP Tunnel"); - llts(ZEBRA_LLT_IPIP6, "IPIP6 Tunnel"); - llts(ZEBRA_LLT_FRAD, "FRAD"); - llts(ZEBRA_LLT_SKIP, "SKIP vif"); - llts(ZEBRA_LLT_LOOPBACK, "Loopback"); - llts(ZEBRA_LLT_LOCALTLK, "Localtalk"); - llts(ZEBRA_LLT_FDDI, "FDDI"); - llts(ZEBRA_LLT_SIT, "IPv6-in-IPv4 SIT"); - llts(ZEBRA_LLT_IPDDP, "IP-in-DDP tunnel"); - llts(ZEBRA_LLT_IPGRE, "GRE over IP"); - llts(ZEBRA_LLT_PIMREG, "PIMSM registration"); - llts(ZEBRA_LLT_HIPPI, "HiPPI"); - llts(ZEBRA_LLT_IRDA, "IrDA"); - llts(ZEBRA_LLT_FCPP, "Fibre-Channel PtP"); - llts(ZEBRA_LLT_FCAL, "Fibre-Channel Arbitrated Loop"); - llts(ZEBRA_LLT_FCPL, "Fibre-Channel Public Loop"); - llts(ZEBRA_LLT_FCFABRIC, "Fibre-Channel Fabric"); - llts(ZEBRA_LLT_IEEE802_TR, "IEEE 802.2 Token Ring"); - llts(ZEBRA_LLT_IEEE80211, "IEEE 802.11"); - llts(ZEBRA_LLT_IEEE80211_RADIOTAP, "IEEE 802.11 Radiotap"); - llts(ZEBRA_LLT_IEEE802154, "IEEE 802.15.4"); - llts(ZEBRA_LLT_IEEE802154_PHY, "IEEE 802.15.4 Phy"); - default: - zlog_warn ("Unknown value %d", llt); - return "Unknown type!"; + llts(ZEBRA_LLT_UNKNOWN, "Unknown"); + llts(ZEBRA_LLT_ETHER, "Ethernet"); + llts(ZEBRA_LLT_EETHER, "Experimental Ethernet"); + llts(ZEBRA_LLT_AX25, "AX.25 Level 2"); + llts(ZEBRA_LLT_PRONET, "PROnet token ring"); + llts(ZEBRA_LLT_IEEE802, "IEEE 802.2 Ethernet/TR/TB"); + llts(ZEBRA_LLT_ARCNET, "ARCnet"); + llts(ZEBRA_LLT_APPLETLK, "AppleTalk"); + llts(ZEBRA_LLT_DLCI, "Frame Relay DLCI"); + llts(ZEBRA_LLT_ATM, "ATM"); + llts(ZEBRA_LLT_METRICOM, "Metricom STRIP"); + llts(ZEBRA_LLT_IEEE1394, "IEEE 1394 IPv4"); + llts(ZEBRA_LLT_EUI64, "EUI-64"); + llts(ZEBRA_LLT_INFINIBAND, "InfiniBand"); + llts(ZEBRA_LLT_SLIP, "SLIP"); + llts(ZEBRA_LLT_CSLIP, "Compressed SLIP"); + llts(ZEBRA_LLT_SLIP6, "SLIPv6"); + llts(ZEBRA_LLT_CSLIP6, "Compressed SLIPv6"); + llts(ZEBRA_LLT_ROSE, "ROSE packet radio"); + llts(ZEBRA_LLT_X25, "CCITT X.25"); + llts(ZEBRA_LLT_PPP, "PPP"); + llts(ZEBRA_LLT_CHDLC, "Cisco HDLC"); + llts(ZEBRA_LLT_RAWHDLC, "Raw HDLC"); + llts(ZEBRA_LLT_LAPB, "LAPB"); + llts(ZEBRA_LLT_IPIP, "IPIP Tunnel"); + llts(ZEBRA_LLT_IPIP6, "IPIP6 Tunnel"); + llts(ZEBRA_LLT_FRAD, "FRAD"); + llts(ZEBRA_LLT_SKIP, "SKIP vif"); + llts(ZEBRA_LLT_LOOPBACK, "Loopback"); + llts(ZEBRA_LLT_LOCALTLK, "Localtalk"); + llts(ZEBRA_LLT_FDDI, "FDDI"); + llts(ZEBRA_LLT_SIT, "IPv6-in-IPv4 SIT"); + llts(ZEBRA_LLT_IPDDP, "IP-in-DDP tunnel"); + llts(ZEBRA_LLT_IPGRE, "GRE over IP"); + llts(ZEBRA_LLT_PIMREG, "PIMSM registration"); + llts(ZEBRA_LLT_HIPPI, "HiPPI"); + llts(ZEBRA_LLT_IRDA, "IrDA"); + llts(ZEBRA_LLT_FCPP, "Fibre-Channel PtP"); + llts(ZEBRA_LLT_FCAL, "Fibre-Channel Arbitrated Loop"); + llts(ZEBRA_LLT_FCPL, "Fibre-Channel Public Loop"); + llts(ZEBRA_LLT_FCFABRIC, "Fibre-Channel Fabric"); + llts(ZEBRA_LLT_IEEE802_TR, "IEEE 802.2 Token Ring"); + llts(ZEBRA_LLT_IEEE80211, "IEEE 802.11"); + llts(ZEBRA_LLT_IEEE80211_RADIOTAP, "IEEE 802.11 Radiotap"); + llts(ZEBRA_LLT_IEEE802154, "IEEE 802.15.4"); + llts(ZEBRA_LLT_IEEE802154_PHY, "IEEE 802.15.4 Phy"); + default: + zlog_warn("Unknown value %d", llt); + return "Unknown type!"; #undef llts - } - return NULL; + } + return NULL; } -struct if_link_params * -if_link_params_get (struct interface *ifp) +struct if_link_params *if_link_params_get(struct interface *ifp) { - int i; + int i; - if (ifp->link_params != NULL) - return ifp->link_params; + if (ifp->link_params != NULL) + return ifp->link_params; - struct if_link_params *iflp = XCALLOC(MTYPE_IF_LINK_PARAMS, - sizeof (struct if_link_params)); - if (iflp == NULL) return NULL; + struct if_link_params *iflp = + XCALLOC(MTYPE_IF_LINK_PARAMS, sizeof(struct if_link_params)); + if (iflp == NULL) + return NULL; - /* Set TE metric equal to standard metric */ - iflp->te_metric = ifp->metric; + /* Set TE metric equal to standard metric */ + iflp->te_metric = ifp->metric; - /* Compute default bandwidth based on interface */ - iflp->default_bw = ((ifp->bandwidth ? ifp->bandwidth : DEFAULT_BANDWIDTH) - * TE_KILO_BIT / TE_BYTE); + /* Compute default bandwidth based on interface */ + iflp->default_bw = + ((ifp->bandwidth ? ifp->bandwidth : DEFAULT_BANDWIDTH) + * TE_KILO_BIT / TE_BYTE); - /* Set Max, Reservable and Unreserved Bandwidth */ - iflp->max_bw = iflp->default_bw; - iflp->max_rsv_bw = iflp->default_bw; - for (i = 0; i < MAX_CLASS_TYPE; i++) - iflp->unrsv_bw[i] = iflp->default_bw; + /* Set Max, Reservable and Unreserved Bandwidth */ + iflp->max_bw = iflp->default_bw; + iflp->max_rsv_bw = iflp->default_bw; + for (i = 0; i < MAX_CLASS_TYPE; i++) + iflp->unrsv_bw[i] = iflp->default_bw; - /* Update Link parameters status */ - iflp->lp_status = LP_TE_METRIC | LP_MAX_BW | LP_MAX_RSV_BW | LP_UNRSV_BW; + /* Update Link parameters status */ + iflp->lp_status = + LP_TE_METRIC | LP_MAX_BW | LP_MAX_RSV_BW | LP_UNRSV_BW; - /* Finally attach newly created Link Parameters */ - ifp->link_params = iflp; + /* Finally attach newly created Link Parameters */ + ifp->link_params = iflp; - return iflp; + return iflp; } -void -if_link_params_free (struct interface *ifp) +void if_link_params_free(struct interface *ifp) { - if (ifp->link_params == NULL) return; - XFREE(MTYPE_IF_LINK_PARAMS, ifp->link_params); - ifp->link_params = NULL; + if (ifp->link_params == NULL) + return; + XFREE(MTYPE_IF_LINK_PARAMS, ifp->link_params); + ifp->link_params = NULL; } diff --git a/lib/if.h b/lib/if.h index a061110a4..f80ac1917 100644 --- a/lib/if.h +++ b/lib/if.h @@ -37,56 +37,56 @@ DECLARE_MTYPE(CONNECTED_LABEL) * Some of the more obviously defunct technologies left out. */ enum zebra_link_type { - ZEBRA_LLT_UNKNOWN = 0, - ZEBRA_LLT_ETHER, - ZEBRA_LLT_EETHER, - ZEBRA_LLT_AX25, - ZEBRA_LLT_PRONET, - ZEBRA_LLT_IEEE802, - ZEBRA_LLT_ARCNET, - ZEBRA_LLT_APPLETLK, - ZEBRA_LLT_DLCI, - ZEBRA_LLT_ATM, - ZEBRA_LLT_METRICOM, - ZEBRA_LLT_IEEE1394, - ZEBRA_LLT_EUI64, - ZEBRA_LLT_INFINIBAND, - ZEBRA_LLT_SLIP, - ZEBRA_LLT_CSLIP, - ZEBRA_LLT_SLIP6, - ZEBRA_LLT_CSLIP6, - ZEBRA_LLT_RSRVD, - ZEBRA_LLT_ADAPT, - ZEBRA_LLT_ROSE, - ZEBRA_LLT_X25, - ZEBRA_LLT_PPP, - ZEBRA_LLT_CHDLC, - ZEBRA_LLT_LAPB, - ZEBRA_LLT_RAWHDLC, - ZEBRA_LLT_IPIP, - ZEBRA_LLT_IPIP6, - ZEBRA_LLT_FRAD, - ZEBRA_LLT_SKIP, - ZEBRA_LLT_LOOPBACK, - ZEBRA_LLT_LOCALTLK, - ZEBRA_LLT_FDDI, - ZEBRA_LLT_SIT, - ZEBRA_LLT_IPDDP, - ZEBRA_LLT_IPGRE, - ZEBRA_LLT_IP6GRE, - ZEBRA_LLT_PIMREG, - ZEBRA_LLT_HIPPI, - ZEBRA_LLT_ECONET, - ZEBRA_LLT_IRDA, - ZEBRA_LLT_FCPP, - ZEBRA_LLT_FCAL, - ZEBRA_LLT_FCPL, - ZEBRA_LLT_FCFABRIC, - ZEBRA_LLT_IEEE802_TR, - ZEBRA_LLT_IEEE80211, - ZEBRA_LLT_IEEE80211_RADIOTAP, - ZEBRA_LLT_IEEE802154, - ZEBRA_LLT_IEEE802154_PHY, + ZEBRA_LLT_UNKNOWN = 0, + ZEBRA_LLT_ETHER, + ZEBRA_LLT_EETHER, + ZEBRA_LLT_AX25, + ZEBRA_LLT_PRONET, + ZEBRA_LLT_IEEE802, + ZEBRA_LLT_ARCNET, + ZEBRA_LLT_APPLETLK, + ZEBRA_LLT_DLCI, + ZEBRA_LLT_ATM, + ZEBRA_LLT_METRICOM, + ZEBRA_LLT_IEEE1394, + ZEBRA_LLT_EUI64, + ZEBRA_LLT_INFINIBAND, + ZEBRA_LLT_SLIP, + ZEBRA_LLT_CSLIP, + ZEBRA_LLT_SLIP6, + ZEBRA_LLT_CSLIP6, + ZEBRA_LLT_RSRVD, + ZEBRA_LLT_ADAPT, + ZEBRA_LLT_ROSE, + ZEBRA_LLT_X25, + ZEBRA_LLT_PPP, + ZEBRA_LLT_CHDLC, + ZEBRA_LLT_LAPB, + ZEBRA_LLT_RAWHDLC, + ZEBRA_LLT_IPIP, + ZEBRA_LLT_IPIP6, + ZEBRA_LLT_FRAD, + ZEBRA_LLT_SKIP, + ZEBRA_LLT_LOOPBACK, + ZEBRA_LLT_LOCALTLK, + ZEBRA_LLT_FDDI, + ZEBRA_LLT_SIT, + ZEBRA_LLT_IPDDP, + ZEBRA_LLT_IPGRE, + ZEBRA_LLT_IP6GRE, + ZEBRA_LLT_PIMREG, + ZEBRA_LLT_HIPPI, + ZEBRA_LLT_ECONET, + ZEBRA_LLT_IRDA, + ZEBRA_LLT_FCPP, + ZEBRA_LLT_FCAL, + ZEBRA_LLT_FCPL, + ZEBRA_LLT_FCFABRIC, + ZEBRA_LLT_IEEE802_TR, + ZEBRA_LLT_IEEE80211, + ZEBRA_LLT_IEEE80211_RADIOTAP, + ZEBRA_LLT_IEEE802154, + ZEBRA_LLT_IEEE802154_PHY, }; /* @@ -105,34 +105,33 @@ enum zebra_link_type { typedef signed int ifindex_t; #ifdef HAVE_PROC_NET_DEV -struct if_stats -{ - unsigned long rx_packets; /* total packets received */ - unsigned long tx_packets; /* total packets transmitted */ - unsigned long rx_bytes; /* total bytes received */ - unsigned long tx_bytes; /* total bytes transmitted */ - unsigned long rx_errors; /* bad packets received */ - unsigned long tx_errors; /* packet transmit problems */ - unsigned long rx_dropped; /* no space in linux buffers */ - unsigned long tx_dropped; /* no space available in linux */ - unsigned long rx_multicast; /* multicast packets received */ - unsigned long rx_compressed; - unsigned long tx_compressed; - unsigned long collisions; - - /* detailed rx_errors: */ - unsigned long rx_length_errors; - unsigned long rx_over_errors; /* receiver ring buff overflow */ - unsigned long rx_crc_errors; /* recved pkt with crc error */ - unsigned long rx_frame_errors; /* recv'd frame alignment error */ - unsigned long rx_fifo_errors; /* recv'r fifo overrun */ - unsigned long rx_missed_errors; /* receiver missed packet */ - /* detailed tx_errors */ - unsigned long tx_aborted_errors; - unsigned long tx_carrier_errors; - unsigned long tx_fifo_errors; - unsigned long tx_heartbeat_errors; - unsigned long tx_window_errors; +struct if_stats { + unsigned long rx_packets; /* total packets received */ + unsigned long tx_packets; /* total packets transmitted */ + unsigned long rx_bytes; /* total bytes received */ + unsigned long tx_bytes; /* total bytes transmitted */ + unsigned long rx_errors; /* bad packets received */ + unsigned long tx_errors; /* packet transmit problems */ + unsigned long rx_dropped; /* no space in linux buffers */ + unsigned long tx_dropped; /* no space available in linux */ + unsigned long rx_multicast; /* multicast packets received */ + unsigned long rx_compressed; + unsigned long tx_compressed; + unsigned long collisions; + + /* detailed rx_errors: */ + unsigned long rx_length_errors; + unsigned long rx_over_errors; /* receiver ring buff overflow */ + unsigned long rx_crc_errors; /* recved pkt with crc error */ + unsigned long rx_frame_errors; /* recv'd frame alignment error */ + unsigned long rx_fifo_errors; /* recv'r fifo overrun */ + unsigned long rx_missed_errors; /* receiver missed packet */ + /* detailed tx_errors */ + unsigned long tx_aborted_errors; + unsigned long tx_carrier_errors; + unsigned long tx_fifo_errors; + unsigned long tx_heartbeat_errors; + unsigned long tx_window_errors; }; #endif /* HAVE_PROC_NET_DEV */ @@ -176,178 +175,185 @@ struct if_stats /* Link Parameters for Traffic Engineering */ struct if_link_params { - u_int32_t lp_status; /* Status of Link Parameters: */ - u_int32_t te_metric; /* Traffic Engineering metric */ - float default_bw; - float max_bw; /* Maximum Bandwidth */ - float max_rsv_bw; /* Maximum Reservable Bandwidth */ - float unrsv_bw[MAX_CLASS_TYPE]; /* Unreserved Bandwidth per Class Type (8) */ - u_int32_t admin_grp; /* Administrative group */ - u_int32_t rmt_as; /* Remote AS number */ - struct in_addr rmt_ip; /* Remote IP address */ - u_int32_t av_delay; /* Link Average Delay */ - u_int32_t min_delay; /* Link Min Delay */ - u_int32_t max_delay; /* Link Max Delay */ - u_int32_t delay_var; /* Link Delay Variation */ - float pkt_loss; /* Link Packet Loss */ - float res_bw; /* Residual Bandwidth */ - float ava_bw; /* Available Bandwidth */ - float use_bw; /* Utilized Bandwidth */ + u_int32_t lp_status; /* Status of Link Parameters: */ + u_int32_t te_metric; /* Traffic Engineering metric */ + float default_bw; + float max_bw; /* Maximum Bandwidth */ + float max_rsv_bw; /* Maximum Reservable Bandwidth */ + float unrsv_bw[MAX_CLASS_TYPE]; /* Unreserved Bandwidth per Class Type + (8) */ + u_int32_t admin_grp; /* Administrative group */ + u_int32_t rmt_as; /* Remote AS number */ + struct in_addr rmt_ip; /* Remote IP address */ + u_int32_t av_delay; /* Link Average Delay */ + u_int32_t min_delay; /* Link Min Delay */ + u_int32_t max_delay; /* Link Max Delay */ + u_int32_t delay_var; /* Link Delay Variation */ + float pkt_loss; /* Link Packet Loss */ + float res_bw; /* Residual Bandwidth */ + float ava_bw; /* Available Bandwidth */ + float use_bw; /* Utilized Bandwidth */ }; #define INTERFACE_LINK_PARAMS_SIZE sizeof(struct if_link_params) #define HAS_LINK_PARAMS(ifp) ((ifp)->link_params != NULL) /* Interface structure */ -struct interface -{ - /* Interface name. This should probably never be changed after the - interface is created, because the configuration info for this interface - is associated with this structure. For that reason, the interface - should also never be deleted (to avoid losing configuration info). - To delete, just set ifindex to IFINDEX_INTERNAL to indicate that the - interface does not exist in the kernel. - */ - char name[INTERFACE_NAMSIZ + 1]; - - /* Interface index (should be IFINDEX_INTERNAL for non-kernel or - deleted interfaces). */ - ifindex_t ifindex; +struct interface { + /* Interface name. This should probably never be changed after the + interface is created, because the configuration info for this + interface + is associated with this structure. For that reason, the interface + should also never be deleted (to avoid losing configuration info). + To delete, just set ifindex to IFINDEX_INTERNAL to indicate that the + interface does not exist in the kernel. + */ + char name[INTERFACE_NAMSIZ + 1]; + + /* Interface index (should be IFINDEX_INTERNAL for non-kernel or + deleted interfaces). */ + ifindex_t ifindex; #define IFINDEX_INTERNAL 0 #define IFINDEX_DELETED INT_MAX - /* Zebra internal interface status */ - u_char status; + /* Zebra internal interface status */ + u_char status; #define ZEBRA_INTERFACE_ACTIVE (1 << 0) #define ZEBRA_INTERFACE_SUB (1 << 1) #define ZEBRA_INTERFACE_LINKDETECTION (1 << 2) #define ZEBRA_INTERFACE_VRF_LOOPBACK (1 << 3) - /* Interface flags. */ - uint64_t flags; + /* Interface flags. */ + uint64_t flags; - /* Interface metric */ - uint32_t metric; + /* Interface metric */ + uint32_t metric; - /* Interface Speed in Mb/s */ - uint32_t speed; + /* Interface Speed in Mb/s */ + uint32_t speed; - /* Interface MTU. */ - unsigned int mtu; /* IPv4 MTU */ - unsigned int mtu6; /* IPv6 MTU - probably, but not neccessarily same as mtu */ + /* Interface MTU. */ + unsigned int mtu; /* IPv4 MTU */ + unsigned int + mtu6; /* IPv6 MTU - probably, but not neccessarily same as mtu + */ - /* Link-layer information and hardware address */ - enum zebra_link_type ll_type; - u_char hw_addr[INTERFACE_HWADDR_MAX]; - int hw_addr_len; + /* Link-layer information and hardware address */ + enum zebra_link_type ll_type; + u_char hw_addr[INTERFACE_HWADDR_MAX]; + int hw_addr_len; - /* interface bandwidth, kbits */ - unsigned int bandwidth; - - /* Link parameters for Traffic Engineering */ - struct if_link_params *link_params; + /* interface bandwidth, kbits */ + unsigned int bandwidth; - /* description of the interface. */ - char *desc; + /* Link parameters for Traffic Engineering */ + struct if_link_params *link_params; - /* Distribute list. */ - void *distribute_in; - void *distribute_out; + /* description of the interface. */ + char *desc; - /* Connected address list. */ - struct list *connected; + /* Distribute list. */ + void *distribute_in; + void *distribute_out; - /* Neighbor connected address list. */ - struct list *nbr_connected; + /* Connected address list. */ + struct list *connected; - /* Daemon specific interface data pointer. */ - void *info; + /* Neighbor connected address list. */ + struct list *nbr_connected; - char ptm_enable; /* Should we look at ptm_status ? */ - char ptm_status; + /* Daemon specific interface data pointer. */ + void *info; - /* Statistics fileds. */ + char ptm_enable; /* Should we look at ptm_status ? */ + char ptm_status; + +/* Statistics fileds. */ #ifdef HAVE_PROC_NET_DEV - struct if_stats stats; -#endif /* HAVE_PROC_NET_DEV */ + struct if_stats stats; +#endif /* HAVE_PROC_NET_DEV */ #ifdef HAVE_NET_RT_IFLIST - struct if_data stats; + struct if_data stats; #endif /* HAVE_NET_RT_IFLIST */ - struct route_node *node; - vrf_id_t vrf_id; + struct route_node *node; + vrf_id_t vrf_id; - QOBJ_FIELDS + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(interface) /* Connected address structure. */ -struct connected -{ - /* Attached interface. */ - struct interface *ifp; +struct connected { + /* Attached interface. */ + struct interface *ifp; - /* Flags for configuration. */ - u_char conf; + /* Flags for configuration. */ + u_char conf; #define ZEBRA_IFC_REAL (1 << 0) #define ZEBRA_IFC_CONFIGURED (1 << 1) #define ZEBRA_IFC_QUEUED (1 << 2) - /* - The ZEBRA_IFC_REAL flag should be set if and only if this address - exists in the kernel and is actually usable. (A case where it exists but - is not yet usable would be IPv6 with DAD) - The ZEBRA_IFC_CONFIGURED flag should be set if and only if this address - was configured by the user from inside quagga. - The ZEBRA_IFC_QUEUED flag should be set if and only if the address exists - in the kernel. It may and should be set although the address might not be - usable yet. (compare with ZEBRA_IFC_REAL) - */ - - /* Flags for connected address. */ - u_char flags; + /* + The ZEBRA_IFC_REAL flag should be set if and only if this address + exists in the kernel and is actually usable. (A case where it exists + but + is not yet usable would be IPv6 with DAD) + The ZEBRA_IFC_CONFIGURED flag should be set if and only if this + address + was configured by the user from inside quagga. + The ZEBRA_IFC_QUEUED flag should be set if and only if the address + exists + in the kernel. It may and should be set although the address might + not be + usable yet. (compare with ZEBRA_IFC_REAL) + */ + + /* Flags for connected address. */ + u_char flags; #define ZEBRA_IFA_SECONDARY (1 << 0) #define ZEBRA_IFA_PEER (1 << 1) #define ZEBRA_IFA_UNNUMBERED (1 << 2) - /* N.B. the ZEBRA_IFA_PEER flag should be set if and only if - a peer address has been configured. If this flag is set, - the destination field must contain the peer address. - Otherwise, if this flag is not set, the destination address - will either contain a broadcast address or be NULL. - */ - - /* Address of connected network. */ - struct prefix *address; - - /* Peer or Broadcast address, depending on whether ZEBRA_IFA_PEER is set. - Note: destination may be NULL if ZEBRA_IFA_PEER is not set. */ - struct prefix *destination; - - /* Label for Linux 2.2.X and upper. */ - char *label; + /* N.B. the ZEBRA_IFA_PEER flag should be set if and only if + a peer address has been configured. If this flag is set, + the destination field must contain the peer address. + Otherwise, if this flag is not set, the destination address + will either contain a broadcast address or be NULL. + */ + + /* Address of connected network. */ + struct prefix *address; + + /* Peer or Broadcast address, depending on whether ZEBRA_IFA_PEER is + set. + Note: destination may be NULL if ZEBRA_IFA_PEER is not set. */ + struct prefix *destination; + + /* Label for Linux 2.2.X and upper. */ + char *label; }; /* Nbr Connected address structure. */ -struct nbr_connected -{ - /* Attached interface. */ - struct interface *ifp; +struct nbr_connected { + /* Attached interface. */ + struct interface *ifp; - /* Address of connected network. */ - struct prefix *address; + /* Address of connected network. */ + struct prefix *address; }; /* Does the destination field contain a peer address? */ #define CONNECTED_PEER(C) CHECK_FLAG((C)->flags, ZEBRA_IFA_PEER) /* Prefix to insert into the RIB */ -#define CONNECTED_PREFIX(C) \ +#define CONNECTED_PREFIX(C) \ (CONNECTED_PEER(C) ? (C)->destination : (C)->address) /* Identifying address. We guess that if there's a peer address, but the local address is in the same prefix, then the local address may be unique. */ -#define CONNECTED_ID(C) \ - ((CONNECTED_PEER(C) && !prefix_match((C)->destination, (C)->address)) ?\ - (C)->destination : (C)->address) +#define CONNECTED_ID(C) \ + ((CONNECTED_PEER(C) && !prefix_match((C)->destination, (C)->address)) \ + ? (C)->destination \ + : (C)->address) /* Interface hook sort. */ #define IF_NEW_HOOK 0 @@ -391,65 +397,63 @@ struct nbr_connected #endif /* IFF_VIRTUAL */ /* Prototypes. */ -extern int if_cmp_name_func (char *, char *); - -extern void if_update_to_new_vrf (struct interface *, vrf_id_t vrf_id); -extern struct interface *if_create (const char *name, int namelen, - vrf_id_t vrf_id); -extern struct interface *if_lookup_by_index (ifindex_t, vrf_id_t vrf_id); -extern struct interface *if_lookup_exact_address (void *matchaddr, int family, - vrf_id_t vrf_id); -extern struct connected *if_lookup_address (void *matchaddr, int family, - vrf_id_t vrf_id); -extern struct interface *if_lookup_prefix (struct prefix *prefix, - vrf_id_t vrf_id); +extern int if_cmp_name_func(char *, char *); + +extern void if_update_to_new_vrf(struct interface *, vrf_id_t vrf_id); +extern struct interface *if_create(const char *name, int namelen, + vrf_id_t vrf_id); +extern struct interface *if_lookup_by_index(ifindex_t, vrf_id_t vrf_id); +extern struct interface *if_lookup_exact_address(void *matchaddr, int family, + vrf_id_t vrf_id); +extern struct connected *if_lookup_address(void *matchaddr, int family, + vrf_id_t vrf_id); +extern struct interface *if_lookup_prefix(struct prefix *prefix, + vrf_id_t vrf_id); /* These 3 functions are to be used when the ifname argument is terminated by a '\0' character: */ -extern struct interface *if_lookup_by_name_all_vrf (const char *ifname); -extern struct interface *if_lookup_by_name (const char *ifname, - vrf_id_t vrf_id); -extern struct interface *if_get_by_name (const char *ifname, - vrf_id_t vrf_id); +extern struct interface *if_lookup_by_name_all_vrf(const char *ifname); +extern struct interface *if_lookup_by_name(const char *ifname, vrf_id_t vrf_id); +extern struct interface *if_get_by_name(const char *ifname, vrf_id_t vrf_id); /* For these 2 functions, the namelen argument should be the precise length of the ifname string (not counting any optional trailing '\0' character). In most cases, strnlen should be used to calculate the namelen value. */ extern struct interface *if_lookup_by_name_len(const char *ifname, - size_t namelen, vrf_id_t vrf_id); -extern struct interface *if_get_by_name_len(const char *ifname, - size_t namelen, vrf_id_t vrf_id, int vty); + size_t namelen, vrf_id_t vrf_id); +extern struct interface *if_get_by_name_len(const char *ifname, size_t namelen, + vrf_id_t vrf_id, int vty); /* Delete the interface, but do not free the structure, and leave it in the - interface list. It is often advisable to leave the pseudo interface + interface list. It is often advisable to leave the pseudo interface structure because there may be configuration information attached. */ -extern void if_delete_retain (struct interface *); +extern void if_delete_retain(struct interface *); /* Delete and free the interface structure: calls if_delete_retain and then deletes it from the interface list and frees the structure. */ -extern void if_delete (struct interface *); - -extern int if_is_up (struct interface *); -extern int if_is_running (struct interface *); -extern int if_is_operative (struct interface *); -extern int if_is_no_ptm_operative (struct interface *); -extern int if_is_loopback (struct interface *); -extern int if_is_broadcast (struct interface *); -extern int if_is_pointopoint (struct interface *); -extern int if_is_multicast (struct interface *); -extern void if_add_hook (int, int (*)(struct interface *)); -extern void if_init (struct list **); -extern void if_cmd_init (void); -extern void if_terminate (struct list **); -extern void if_dump_all (void); +extern void if_delete(struct interface *); + +extern int if_is_up(struct interface *); +extern int if_is_running(struct interface *); +extern int if_is_operative(struct interface *); +extern int if_is_no_ptm_operative(struct interface *); +extern int if_is_loopback(struct interface *); +extern int if_is_broadcast(struct interface *); +extern int if_is_pointopoint(struct interface *); +extern int if_is_multicast(struct interface *); +extern void if_add_hook(int, int (*)(struct interface *)); +extern void if_init(struct list **); +extern void if_cmd_init(void); +extern void if_terminate(struct list **); +extern void if_dump_all(void); extern const char *if_flag_dump(unsigned long); -extern const char *if_link_type_str (enum zebra_link_type); +extern const char *if_link_type_str(enum zebra_link_type); /* Please use ifindex2ifname instead of if_indextoname where possible; ifindex2ifname uses internal interface info, whereas if_indextoname must make a system call. */ -extern const char *ifindex2ifname (ifindex_t, vrf_id_t vrf_id); +extern const char *ifindex2ifname(ifindex_t, vrf_id_t vrf_id); /* Please use ifname2ifindex instead of if_nametoindex where possible; ifname2ifindex uses internal interface info, whereas if_nametoindex must @@ -457,24 +461,23 @@ extern const char *ifindex2ifname (ifindex_t, vrf_id_t vrf_id); extern ifindex_t ifname2ifindex(const char *ifname, vrf_id_t vrf_id); /* Connected address functions. */ -extern struct connected *connected_new (void); -extern void connected_free (struct connected *); -extern void connected_add (struct interface *, struct connected *); -extern struct connected *connected_add_by_prefix (struct interface *, - struct prefix *, - struct prefix *); -extern struct connected *connected_delete_by_prefix (struct interface *, - struct prefix *); -extern struct connected *connected_lookup_prefix (struct interface *, - struct prefix *); -extern struct connected *connected_lookup_prefix_exact (struct interface *, - struct prefix *); -extern struct nbr_connected *nbr_connected_new (void); -extern void nbr_connected_free (struct nbr_connected *); -struct nbr_connected *nbr_connected_check (struct interface *, struct prefix *); +extern struct connected *connected_new(void); +extern void connected_free(struct connected *); +extern void connected_add(struct interface *, struct connected *); +extern struct connected * +connected_add_by_prefix(struct interface *, struct prefix *, struct prefix *); +extern struct connected *connected_delete_by_prefix(struct interface *, + struct prefix *); +extern struct connected *connected_lookup_prefix(struct interface *, + struct prefix *); +extern struct connected *connected_lookup_prefix_exact(struct interface *, + struct prefix *); +extern struct nbr_connected *nbr_connected_new(void); +extern void nbr_connected_free(struct nbr_connected *); +struct nbr_connected *nbr_connected_check(struct interface *, struct prefix *); /* link parameters */ -struct if_link_params *if_link_params_get (struct interface *); -void if_link_params_free (struct interface *); +struct if_link_params *if_link_params_get(struct interface *); +void if_link_params_free(struct interface *); #endif /* _ZEBRA_IF_H */ diff --git a/lib/if_rmap.c b/lib/if_rmap.c index a0c40d5af..968c087c3 100644 --- a/lib/if_rmap.c +++ b/lib/if_rmap.c @@ -26,186 +26,172 @@ #include "if.h" #include "if_rmap.h" -DEFINE_MTYPE_STATIC(LIB, IF_RMAP, "Interface route map") +DEFINE_MTYPE_STATIC(LIB, IF_RMAP, "Interface route map") DEFINE_MTYPE_STATIC(LIB, IF_RMAP_NAME, "I.f. route map name") struct hash *ifrmaphash; /* Hook functions. */ -static void (*if_rmap_add_hook) (struct if_rmap *) = NULL; -static void (*if_rmap_delete_hook) (struct if_rmap *) = NULL; +static void (*if_rmap_add_hook)(struct if_rmap *) = NULL; +static void (*if_rmap_delete_hook)(struct if_rmap *) = NULL; -static struct if_rmap * -if_rmap_new (void) +static struct if_rmap *if_rmap_new(void) { - struct if_rmap *new; + struct if_rmap *new; - new = XCALLOC (MTYPE_IF_RMAP, sizeof (struct if_rmap)); + new = XCALLOC(MTYPE_IF_RMAP, sizeof(struct if_rmap)); - return new; + return new; } -static void -if_rmap_free (struct if_rmap *if_rmap) +static void if_rmap_free(struct if_rmap *if_rmap) { - if (if_rmap->ifname) - XFREE (MTYPE_IF_RMAP_NAME, if_rmap->ifname); + if (if_rmap->ifname) + XFREE(MTYPE_IF_RMAP_NAME, if_rmap->ifname); - if (if_rmap->routemap[IF_RMAP_IN]) - XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); - if (if_rmap->routemap[IF_RMAP_OUT]) - XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); + if (if_rmap->routemap[IF_RMAP_IN]) + XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); + if (if_rmap->routemap[IF_RMAP_OUT]) + XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); - XFREE (MTYPE_IF_RMAP, if_rmap); + XFREE(MTYPE_IF_RMAP, if_rmap); } -struct if_rmap * -if_rmap_lookup (const char *ifname) +struct if_rmap *if_rmap_lookup(const char *ifname) { - struct if_rmap key; - struct if_rmap *if_rmap; + struct if_rmap key; + struct if_rmap *if_rmap; - /* temporary copy */ - key.ifname = (ifname) ? XSTRDUP (MTYPE_IF_RMAP_NAME, ifname) : NULL; + /* temporary copy */ + key.ifname = (ifname) ? XSTRDUP(MTYPE_IF_RMAP_NAME, ifname) : NULL; - if_rmap = hash_lookup (ifrmaphash, &key); - - if (key.ifname) - XFREE(MTYPE_IF_RMAP_NAME, key.ifname); + if_rmap = hash_lookup(ifrmaphash, &key); - return if_rmap; + if (key.ifname) + XFREE(MTYPE_IF_RMAP_NAME, key.ifname); + + return if_rmap; } -void -if_rmap_hook_add (void (*func) (struct if_rmap *)) +void if_rmap_hook_add(void (*func)(struct if_rmap *)) { - if_rmap_add_hook = func; + if_rmap_add_hook = func; } -void -if_rmap_hook_delete (void (*func) (struct if_rmap *)) +void if_rmap_hook_delete(void (*func)(struct if_rmap *)) { - if_rmap_delete_hook = func; + if_rmap_delete_hook = func; } -static void * -if_rmap_hash_alloc (void *arg) +static void *if_rmap_hash_alloc(void *arg) { - struct if_rmap *ifarg = (struct if_rmap *)arg; - struct if_rmap *if_rmap; + struct if_rmap *ifarg = (struct if_rmap *)arg; + struct if_rmap *if_rmap; - if_rmap = if_rmap_new (); - if_rmap->ifname = XSTRDUP (MTYPE_IF_RMAP_NAME, ifarg->ifname); + if_rmap = if_rmap_new(); + if_rmap->ifname = XSTRDUP(MTYPE_IF_RMAP_NAME, ifarg->ifname); - return if_rmap; + return if_rmap; } -static struct if_rmap * -if_rmap_get (const char *ifname) +static struct if_rmap *if_rmap_get(const char *ifname) { - struct if_rmap key; - struct if_rmap *ret; + struct if_rmap key; + struct if_rmap *ret; - /* temporary copy */ - key.ifname = (ifname) ? XSTRDUP (MTYPE_IF_RMAP_NAME, ifname) : NULL; + /* temporary copy */ + key.ifname = (ifname) ? XSTRDUP(MTYPE_IF_RMAP_NAME, ifname) : NULL; - ret = hash_get (ifrmaphash, &key, if_rmap_hash_alloc); + ret = hash_get(ifrmaphash, &key, if_rmap_hash_alloc); - if (key.ifname) - XFREE(MTYPE_IF_RMAP_NAME, key.ifname); + if (key.ifname) + XFREE(MTYPE_IF_RMAP_NAME, key.ifname); - return ret; + return ret; } -static unsigned int -if_rmap_hash_make (void *data) +static unsigned int if_rmap_hash_make(void *data) { - const struct if_rmap *if_rmap = data; + const struct if_rmap *if_rmap = data; - return string_hash_make (if_rmap->ifname); + return string_hash_make(if_rmap->ifname); } -static int -if_rmap_hash_cmp (const void *arg1, const void* arg2) +static int if_rmap_hash_cmp(const void *arg1, const void *arg2) { - const struct if_rmap *if_rmap1 = arg1; - const struct if_rmap *if_rmap2 = arg2; + const struct if_rmap *if_rmap1 = arg1; + const struct if_rmap *if_rmap2 = arg2; - return strcmp (if_rmap1->ifname, if_rmap2->ifname) == 0; + return strcmp(if_rmap1->ifname, if_rmap2->ifname) == 0; } -static struct if_rmap * -if_rmap_set (const char *ifname, enum if_rmap_type type, - const char *routemap_name) +static struct if_rmap *if_rmap_set(const char *ifname, enum if_rmap_type type, + const char *routemap_name) { - struct if_rmap *if_rmap; - - if_rmap = if_rmap_get (ifname); - - if (type == IF_RMAP_IN) - { - if (if_rmap->routemap[IF_RMAP_IN]) - XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); - if_rmap->routemap[IF_RMAP_IN] - = XSTRDUP (MTYPE_IF_RMAP_NAME, routemap_name); - } - if (type == IF_RMAP_OUT) - { - if (if_rmap->routemap[IF_RMAP_OUT]) - XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); - if_rmap->routemap[IF_RMAP_OUT] - = XSTRDUP (MTYPE_IF_RMAP_NAME, routemap_name); - } - - if (if_rmap_add_hook) - (*if_rmap_add_hook) (if_rmap); - - return if_rmap; + struct if_rmap *if_rmap; + + if_rmap = if_rmap_get(ifname); + + if (type == IF_RMAP_IN) { + if (if_rmap->routemap[IF_RMAP_IN]) + XFREE(MTYPE_IF_RMAP_NAME, + if_rmap->routemap[IF_RMAP_IN]); + if_rmap->routemap[IF_RMAP_IN] = + XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name); + } + if (type == IF_RMAP_OUT) { + if (if_rmap->routemap[IF_RMAP_OUT]) + XFREE(MTYPE_IF_RMAP_NAME, + if_rmap->routemap[IF_RMAP_OUT]); + if_rmap->routemap[IF_RMAP_OUT] = + XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name); + } + + if (if_rmap_add_hook) + (*if_rmap_add_hook)(if_rmap); + + return if_rmap; } -static int -if_rmap_unset (const char *ifname, enum if_rmap_type type, - const char *routemap_name) +static int if_rmap_unset(const char *ifname, enum if_rmap_type type, + const char *routemap_name) { - struct if_rmap *if_rmap; - - if_rmap = if_rmap_lookup (ifname); - if (!if_rmap) - return 0; - - if (type == IF_RMAP_IN) - { - if (!if_rmap->routemap[IF_RMAP_IN]) - return 0; - if (strcmp (if_rmap->routemap[IF_RMAP_IN], routemap_name) != 0) - return 0; - - XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); - if_rmap->routemap[IF_RMAP_IN] = NULL; - } - - if (type == IF_RMAP_OUT) - { - if (!if_rmap->routemap[IF_RMAP_OUT]) - return 0; - if (strcmp (if_rmap->routemap[IF_RMAP_OUT], routemap_name) != 0) - return 0; - - XFREE (MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); - if_rmap->routemap[IF_RMAP_OUT] = NULL; - } - - if (if_rmap_delete_hook) - (*if_rmap_delete_hook) (if_rmap); - - if (if_rmap->routemap[IF_RMAP_IN] == NULL && - if_rmap->routemap[IF_RMAP_OUT] == NULL) - { - hash_release (ifrmaphash, if_rmap); - if_rmap_free (if_rmap); - } - - return 1; + struct if_rmap *if_rmap; + + if_rmap = if_rmap_lookup(ifname); + if (!if_rmap) + return 0; + + if (type == IF_RMAP_IN) { + if (!if_rmap->routemap[IF_RMAP_IN]) + return 0; + if (strcmp(if_rmap->routemap[IF_RMAP_IN], routemap_name) != 0) + return 0; + + XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); + if_rmap->routemap[IF_RMAP_IN] = NULL; + } + + if (type == IF_RMAP_OUT) { + if (!if_rmap->routemap[IF_RMAP_OUT]) + return 0; + if (strcmp(if_rmap->routemap[IF_RMAP_OUT], routemap_name) != 0) + return 0; + + XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); + if_rmap->routemap[IF_RMAP_OUT] = NULL; + } + + if (if_rmap_delete_hook) + (*if_rmap_delete_hook)(if_rmap); + + if (if_rmap->routemap[IF_RMAP_IN] == NULL + && if_rmap->routemap[IF_RMAP_OUT] == NULL) { + hash_release(ifrmaphash, if_rmap); + if_rmap_free(if_rmap); + } + + return 1; } DEFUN (if_rmap, @@ -217,24 +203,23 @@ DEFUN (if_rmap, "Route map set for output filtering\n" "Route map interface name\n") { - int idx_rmap_name = 1; - int idx_in_out = 2; - int idx_ifname = 3; - enum if_rmap_type type; - - if (strncmp (argv[idx_in_out]->text, "in", 1) == 0) - type = IF_RMAP_IN; - else if (strncmp (argv[idx_in_out]->text, "out", 1) == 0) - type = IF_RMAP_OUT; - else - { - vty_out (vty, "route-map direction must be [in|out]\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if_rmap_set (argv[idx_ifname]->arg, type, argv[idx_rmap_name]->arg); - - return CMD_SUCCESS; + int idx_rmap_name = 1; + int idx_in_out = 2; + int idx_ifname = 3; + enum if_rmap_type type; + + if (strncmp(argv[idx_in_out]->text, "in", 1) == 0) + type = IF_RMAP_IN; + else if (strncmp(argv[idx_in_out]->text, "out", 1) == 0) + type = IF_RMAP_OUT; + else { + vty_out(vty, "route-map direction must be [in|out]\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if_rmap_set(argv[idx_ifname]->arg, type, argv[idx_rmap_name]->arg); + + return CMD_SUCCESS; } DEFUN (no_if_rmap, @@ -247,79 +232,72 @@ DEFUN (no_if_rmap, "Route map for output filtering\n" "Route map interface name\n") { - int idx_routemap_name = 2; - int idx_in_out = 3; - int idx_ifname = 4; - int ret; - enum if_rmap_type type; - - if (strncmp (argv[idx_in_out]->arg, "i", 1) == 0) - type = IF_RMAP_IN; - else if (strncmp (argv[idx_in_out]->arg, "o", 1) == 0) - type = IF_RMAP_OUT; - else - { - vty_out (vty, "route-map direction must be [in|out]\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ret = if_rmap_unset (argv[idx_ifname]->arg, type, argv[idx_routemap_name]->arg); - if (! ret) - { - vty_out (vty, "route-map doesn't exist\n"); - return CMD_WARNING_CONFIG_FAILED; - } - return CMD_SUCCESS; + int idx_routemap_name = 2; + int idx_in_out = 3; + int idx_ifname = 4; + int ret; + enum if_rmap_type type; + + if (strncmp(argv[idx_in_out]->arg, "i", 1) == 0) + type = IF_RMAP_IN; + else if (strncmp(argv[idx_in_out]->arg, "o", 1) == 0) + type = IF_RMAP_OUT; + else { + vty_out(vty, "route-map direction must be [in|out]\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = if_rmap_unset(argv[idx_ifname]->arg, type, + argv[idx_routemap_name]->arg); + if (!ret) { + vty_out(vty, "route-map doesn't exist\n"); + return CMD_WARNING_CONFIG_FAILED; + } + return CMD_SUCCESS; } /* Configuration write function. */ -int -config_write_if_rmap (struct vty *vty) +int config_write_if_rmap(struct vty *vty) { - unsigned int i; - struct hash_backet *mp; - int write = 0; - - for (i = 0; i < ifrmaphash->size; i++) - for (mp = ifrmaphash->index[i]; mp; mp = mp->next) - { - struct if_rmap *if_rmap; - - if_rmap = mp->data; - - if (if_rmap->routemap[IF_RMAP_IN]) - { - vty_out (vty, " route-map %s in %s\n", - if_rmap->routemap[IF_RMAP_IN], - if_rmap->ifname); - write++; - } - - if (if_rmap->routemap[IF_RMAP_OUT]) - { - vty_out (vty, " route-map %s out %s\n", - if_rmap->routemap[IF_RMAP_OUT], - if_rmap->ifname); - write++; - } - } - return write; + unsigned int i; + struct hash_backet *mp; + int write = 0; + + for (i = 0; i < ifrmaphash->size; i++) + for (mp = ifrmaphash->index[i]; mp; mp = mp->next) { + struct if_rmap *if_rmap; + + if_rmap = mp->data; + + if (if_rmap->routemap[IF_RMAP_IN]) { + vty_out(vty, " route-map %s in %s\n", + if_rmap->routemap[IF_RMAP_IN], + if_rmap->ifname); + write++; + } + + if (if_rmap->routemap[IF_RMAP_OUT]) { + vty_out(vty, " route-map %s out %s\n", + if_rmap->routemap[IF_RMAP_OUT], + if_rmap->ifname); + write++; + } + } + return write; } -void -if_rmap_reset () +void if_rmap_reset() { - hash_clean (ifrmaphash, (void (*) (void *)) if_rmap_free); + hash_clean(ifrmaphash, (void (*)(void *))if_rmap_free); } -void -if_rmap_init (int node) +void if_rmap_init(int node) { - ifrmaphash = hash_create (if_rmap_hash_make, if_rmap_hash_cmp, NULL); - if (node == RIPNG_NODE) { - } else if (node == RIP_NODE) { - install_element (RIP_NODE, &if_rmap_cmd); - install_element (RIP_NODE, &no_if_rmap_cmd); - } + ifrmaphash = hash_create(if_rmap_hash_make, if_rmap_hash_cmp, NULL); + if (node == RIPNG_NODE) { + } else if (node == RIP_NODE) { + install_element(RIP_NODE, &if_rmap_cmd); + install_element(RIP_NODE, &no_if_rmap_cmd); + } } diff --git a/lib/if_rmap.h b/lib/if_rmap.h index e38b5f7f7..4468b9fb9 100644 --- a/lib/if_rmap.h +++ b/lib/if_rmap.h @@ -21,26 +21,20 @@ #ifndef _ZEBRA_IF_RMAP_H #define _ZEBRA_IF_RMAP_H -enum if_rmap_type -{ - IF_RMAP_IN, - IF_RMAP_OUT, - IF_RMAP_MAX -}; +enum if_rmap_type { IF_RMAP_IN, IF_RMAP_OUT, IF_RMAP_MAX }; -struct if_rmap -{ - /* Name of the interface. */ - char *ifname; +struct if_rmap { + /* Name of the interface. */ + char *ifname; - char *routemap[IF_RMAP_MAX]; + char *routemap[IF_RMAP_MAX]; }; -extern void if_rmap_init (int); -extern void if_rmap_reset (void); -extern void if_rmap_hook_add (void (*) (struct if_rmap *)); -extern void if_rmap_hook_delete (void (*) (struct if_rmap *)); -extern struct if_rmap *if_rmap_lookup (const char *); -extern int config_write_if_rmap (struct vty *); +extern void if_rmap_init(int); +extern void if_rmap_reset(void); +extern void if_rmap_hook_add(void (*)(struct if_rmap *)); +extern void if_rmap_hook_delete(void (*)(struct if_rmap *)); +extern struct if_rmap *if_rmap_lookup(const char *); +extern int config_write_if_rmap(struct vty *); #endif /* _ZEBRA_IF_RMAP_H */ diff --git a/lib/imsg-buffer.c b/lib/imsg-buffer.c index a486fc17c..4068e31c5 100644 --- a/lib/imsg-buffer.c +++ b/lib/imsg-buffer.c @@ -21,14 +21,13 @@ #include "openbsd-queue.h" #include "imsg.h" -int ibuf_realloc(struct ibuf *, size_t); -void ibuf_enqueue(struct msgbuf *, struct ibuf *); -void ibuf_dequeue(struct msgbuf *, struct ibuf *); +int ibuf_realloc(struct ibuf *, size_t); +void ibuf_enqueue(struct msgbuf *, struct ibuf *); +void ibuf_dequeue(struct msgbuf *, struct ibuf *); -struct ibuf * -ibuf_open(size_t len) +struct ibuf *ibuf_open(size_t len) { - struct ibuf *buf; + struct ibuf *buf; if ((buf = calloc(1, sizeof(struct ibuf))) == NULL) return (NULL); @@ -42,10 +41,9 @@ ibuf_open(size_t len) return (buf); } -struct ibuf * -ibuf_dynamic(size_t len, size_t max) +struct ibuf *ibuf_dynamic(size_t len, size_t max) { - struct ibuf *buf; + struct ibuf *buf; if (max < len) return (NULL); @@ -59,10 +57,9 @@ ibuf_dynamic(size_t len, size_t max) return (buf); } -int -ibuf_realloc(struct ibuf *buf, size_t len) +int ibuf_realloc(struct ibuf *buf, size_t len) { - u_char *b; + u_char *b; /* on static buffers max is eq size and so the following fails */ if (buf->wpos + len > buf->max) { @@ -79,8 +76,7 @@ ibuf_realloc(struct ibuf *buf, size_t len) return (0); } -int -ibuf_add(struct ibuf *buf, const void *data, size_t len) +int ibuf_add(struct ibuf *buf, const void *data, size_t len) { if (buf->wpos + len > buf->size) if (ibuf_realloc(buf, len) == -1) @@ -91,10 +87,9 @@ ibuf_add(struct ibuf *buf, const void *data, size_t len) return (0); } -void * -ibuf_reserve(struct ibuf *buf, size_t len) +void *ibuf_reserve(struct ibuf *buf, size_t len) { - void *b; + void *b; if (buf->wpos + len > buf->size) if (ibuf_realloc(buf, len) == -1) @@ -105,8 +100,7 @@ ibuf_reserve(struct ibuf *buf, size_t len) return (b); } -void * -ibuf_seek(struct ibuf *buf, size_t pos, size_t len) +void *ibuf_seek(struct ibuf *buf, size_t pos, size_t len) { /* only allowed to seek in already written parts */ if (pos + len > buf->wpos) @@ -115,34 +109,31 @@ ibuf_seek(struct ibuf *buf, size_t pos, size_t len) return (buf->buf + pos); } -size_t -ibuf_size(struct ibuf *buf) +size_t ibuf_size(struct ibuf *buf) { return (buf->wpos); } -size_t -ibuf_left(struct ibuf *buf) +size_t ibuf_left(struct ibuf *buf) { return (buf->max - buf->wpos); } -void -ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf) +void ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf) { ibuf_enqueue(msgbuf, buf); } -int -ibuf_write(struct msgbuf *msgbuf) +int ibuf_write(struct msgbuf *msgbuf) { - struct iovec iov[IOV_MAX]; - struct ibuf *buf; - unsigned int i = 0; - ssize_t n; + struct iovec iov[IOV_MAX]; + struct ibuf *buf; + unsigned int i = 0; + ssize_t n; memset(&iov, 0, sizeof(iov)); - TAILQ_FOREACH(buf, &msgbuf->bufs, entry) { + TAILQ_FOREACH(buf, &msgbuf->bufs, entry) + { if (i >= IOV_MAX) break; iov[i].iov_base = buf->buf + buf->rpos; @@ -159,7 +150,7 @@ again: return (-1); } - if (n == 0) { /* connection closed */ + if (n == 0) { /* connection closed */ errno = 0; return (0); } @@ -169,8 +160,7 @@ again: return (1); } -void -ibuf_free(struct ibuf *buf) +void ibuf_free(struct ibuf *buf) { if (buf == NULL) return; @@ -178,21 +168,19 @@ ibuf_free(struct ibuf *buf) free(buf); } -void -msgbuf_init(struct msgbuf *msgbuf) +void msgbuf_init(struct msgbuf *msgbuf) { msgbuf->queued = 0; msgbuf->fd = -1; TAILQ_INIT(&msgbuf->bufs); } -void -msgbuf_drain(struct msgbuf *msgbuf, size_t n) +void msgbuf_drain(struct msgbuf *msgbuf, size_t n) { - struct ibuf *buf, *next; + struct ibuf *buf, *next; for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0; - buf = next) { + buf = next) { next = TAILQ_NEXT(buf, entry); if (buf->rpos + n >= buf->wpos) { n -= buf->wpos - buf->rpos; @@ -204,33 +192,32 @@ msgbuf_drain(struct msgbuf *msgbuf, size_t n) } } -void -msgbuf_clear(struct msgbuf *msgbuf) +void msgbuf_clear(struct msgbuf *msgbuf) { - struct ibuf *buf; + struct ibuf *buf; while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL) ibuf_dequeue(msgbuf, buf); } -int -msgbuf_write(struct msgbuf *msgbuf) +int msgbuf_write(struct msgbuf *msgbuf) { - struct iovec iov[IOV_MAX]; - struct ibuf *buf; - unsigned int i = 0; - ssize_t n; - struct msghdr msg; - struct cmsghdr *cmsg; + struct iovec iov[IOV_MAX]; + struct ibuf *buf; + unsigned int i = 0; + ssize_t n; + struct msghdr msg; + struct cmsghdr *cmsg; union { - struct cmsghdr hdr; - char buf[CMSG_SPACE(sizeof(int))]; + struct cmsghdr hdr; + char buf[CMSG_SPACE(sizeof(int))]; } cmsgbuf; memset(&iov, 0, sizeof(iov)); memset(&msg, 0, sizeof(msg)); memset(&cmsgbuf, 0, sizeof(cmsgbuf)); - TAILQ_FOREACH(buf, &msgbuf->bufs, entry) { + TAILQ_FOREACH(buf, &msgbuf->bufs, entry) + { if (i >= IOV_MAX) break; iov[i].iov_base = buf->buf + buf->rpos; @@ -262,7 +249,7 @@ again: return (-1); } - if (n == 0) { /* connection closed */ + if (n == 0) { /* connection closed */ errno = 0; return (0); } @@ -281,15 +268,13 @@ again: return (1); } -void -ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf) +void ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf) { TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry); msgbuf->queued++; } -void -ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf) +void ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf) { TAILQ_REMOVE(&msgbuf->bufs, buf, entry); diff --git a/lib/imsg.c b/lib/imsg.c index fc62c1373..10650f648 100644 --- a/lib/imsg.c +++ b/lib/imsg.c @@ -21,22 +21,21 @@ #include "openbsd-queue.h" #include "imsg.h" -int imsg_fd_overhead = 0; +int imsg_fd_overhead = 0; -int imsg_get_fd(struct imsgbuf *); +int imsg_get_fd(struct imsgbuf *); #ifndef __OpenBSD__ /* * The original code calls getdtablecount() which is OpenBSD specific. Use * available_fds() from OpenSMTPD instead. */ -static int -available_fds(unsigned int n) +static int available_fds(unsigned int n) { - unsigned int i; - int ret, fds[256]; + unsigned int i; + int ret, fds[256]; - if (n > (sizeof(fds)/sizeof(fds[0]))) + if (n > (sizeof(fds) / sizeof(fds[0]))) return (1); ret = 0; @@ -59,8 +58,7 @@ available_fds(unsigned int n) } #endif -void -imsg_init(struct imsgbuf *ibuf, int fd) +void imsg_init(struct imsgbuf *ibuf, int fd) { msgbuf_init(&ibuf->w); memset(&ibuf->r, 0, sizeof(ibuf->r)); @@ -70,19 +68,18 @@ imsg_init(struct imsgbuf *ibuf, int fd) TAILQ_INIT(&ibuf->fds); } -ssize_t -imsg_read(struct imsgbuf *ibuf) +ssize_t imsg_read(struct imsgbuf *ibuf) { - struct msghdr msg; - struct cmsghdr *cmsg; + struct msghdr msg; + struct cmsghdr *cmsg; union { struct cmsghdr hdr; - char buf[CMSG_SPACE(sizeof(int) * 1)]; + char buf[CMSG_SPACE(sizeof(int) * 1)]; } cmsgbuf; - struct iovec iov; - ssize_t n = -1; - int fd; - struct imsg_fd *ifd; + struct iovec iov; + ssize_t n = -1; + int fd; + struct imsg_fd *ifd; memset(&msg, 0, sizeof(msg)); memset(&cmsgbuf, 0, sizeof(cmsgbuf)); @@ -99,12 +96,14 @@ imsg_read(struct imsgbuf *ibuf) again: #ifdef __OpenBSD__ - if (getdtablecount() + imsg_fd_overhead + - (int)((CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int)) + if (getdtablecount() + imsg_fd_overhead + + (int)((CMSG_SPACE(sizeof(int)) - CMSG_SPACE(0)) + / sizeof(int)) >= getdtablesize()) { #else - if (available_fds(imsg_fd_overhead + - (CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int))) { + if (available_fds(imsg_fd_overhead + + (CMSG_SPACE(sizeof(int)) - CMSG_SPACE(0)) + / sizeof(int))) { #endif errno = EAGAIN; free(ifd); @@ -120,9 +119,9 @@ again: ibuf->r.wpos += n; for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; - cmsg = CMSG_NXTHDR(&msg, cmsg)) { - if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_RIGHTS) { + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level == SOL_SOCKET + && cmsg->cmsg_type == SCM_RIGHTS) { int i; int j; @@ -131,14 +130,15 @@ again: * padding rules, our control buffer might contain * more than one fd, and we must close them. */ - j = ((char *)cmsg + cmsg->cmsg_len - - (char *)CMSG_DATA(cmsg)) / sizeof(int); + j = ((char *)cmsg + cmsg->cmsg_len + - (char *)CMSG_DATA(cmsg)) + / sizeof(int); for (i = 0; i < j; i++) { fd = ((int *)CMSG_DATA(cmsg))[i]; if (ifd != NULL) { ifd->fd = fd; TAILQ_INSERT_TAIL(&ibuf->fds, ifd, - entry); + entry); ifd = NULL; } else close(fd); @@ -152,10 +152,9 @@ fail: return (n); } -ssize_t -imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) +ssize_t imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) { - size_t av, left, datalen; + size_t av, left, datalen; av = ibuf->r.wpos; @@ -163,8 +162,7 @@ imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) return (0); memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr)); - if (imsg->hdr.len < IMSG_HEADER_SIZE || - imsg->hdr.len > MAX_IMSGSIZE) { + if (imsg->hdr.len < IMSG_HEADER_SIZE || imsg->hdr.len > MAX_IMSGSIZE) { errno = ERANGE; return (-1); } @@ -183,7 +181,7 @@ imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) imsg->fd = -1; if (imsg->data) - memcpy(imsg->data, ibuf->r.rptr, datalen); + memcpy(imsg->data, ibuf->r.rptr, datalen); if (imsg->hdr.len < av) { left = av - imsg->hdr.len; @@ -195,11 +193,10 @@ imsg_get(struct imsgbuf *ibuf, struct imsg *imsg) return (datalen + IMSG_HEADER_SIZE); } -int -imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, - pid_t pid, int fd, const void *data, u_int16_t datalen) +int imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, + pid_t pid, int fd, const void *data, u_int16_t datalen) { - struct ibuf *wbuf; + struct ibuf *wbuf; if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL) return (-1); @@ -214,12 +211,11 @@ imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, return (1); } -int -imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, - pid_t pid, int fd, const struct iovec *iov, int iovcnt) +int imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, + pid_t pid, int fd, const struct iovec *iov, int iovcnt) { - struct ibuf *wbuf; - int i, datalen = 0; + struct ibuf *wbuf; + int i, datalen = 0; for (i = 0; i < iovcnt; i++) datalen += iov[i].iov_len; @@ -239,12 +235,11 @@ imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, } /* ARGSUSED */ -struct ibuf * -imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, - pid_t pid, u_int16_t datalen) +struct ibuf *imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, + pid_t pid, u_int16_t datalen) { - struct ibuf *wbuf; - struct imsg_hdr hdr; + struct ibuf *wbuf; + struct imsg_hdr hdr; datalen += IMSG_HEADER_SIZE; if (datalen > MAX_IMSGSIZE) { @@ -266,8 +261,7 @@ imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid, return (wbuf); } -int -imsg_add(struct ibuf *msg, const void *data, u_int16_t datalen) +int imsg_add(struct ibuf *msg, const void *data, u_int16_t datalen) { if (datalen) if (ibuf_add(msg, data, datalen) == -1) { @@ -277,10 +271,9 @@ imsg_add(struct ibuf *msg, const void *data, u_int16_t datalen) return (datalen); } -void -imsg_close(struct imsgbuf *ibuf, struct ibuf *msg) +void imsg_close(struct imsgbuf *ibuf, struct ibuf *msg) { - struct imsg_hdr *hdr; + struct imsg_hdr *hdr; hdr = (struct imsg_hdr *)msg->buf; @@ -293,17 +286,15 @@ imsg_close(struct imsgbuf *ibuf, struct ibuf *msg) ibuf_close(&ibuf->w, msg); } -void -imsg_free(struct imsg *imsg) +void imsg_free(struct imsg *imsg) { free(imsg->data); } -int -imsg_get_fd(struct imsgbuf *ibuf) +int imsg_get_fd(struct imsgbuf *ibuf) { - int fd; - struct imsg_fd *ifd; + int fd; + struct imsg_fd *ifd; if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL) return (-1); @@ -315,8 +306,7 @@ imsg_get_fd(struct imsgbuf *ibuf) return (fd); } -int -imsg_flush(struct imsgbuf *ibuf) +int imsg_flush(struct imsgbuf *ibuf) { while (ibuf->w.queued) if (msgbuf_write(&ibuf->w) <= 0) @@ -324,10 +314,9 @@ imsg_flush(struct imsgbuf *ibuf) return (0); } -void -imsg_clear(struct imsgbuf *ibuf) +void imsg_clear(struct imsgbuf *ibuf) { - int fd; + int fd; msgbuf_clear(&ibuf->w); while ((fd = imsg_get_fd(ibuf)) != -1) diff --git a/lib/imsg.h b/lib/imsg.h index d053d0195..ddaf71344 100644 --- a/lib/imsg.h +++ b/lib/imsg.h @@ -26,87 +26,87 @@ #define MAX_IMSGSIZE 16384 struct ibuf { - TAILQ_ENTRY(ibuf) entry; - u_char *buf; - size_t size; - size_t max; - size_t wpos; - size_t rpos; - int fd; + TAILQ_ENTRY(ibuf) entry; + u_char *buf; + size_t size; + size_t max; + size_t wpos; + size_t rpos; + int fd; }; struct msgbuf { - TAILQ_HEAD(, ibuf) bufs; - u_int32_t queued; - int fd; + TAILQ_HEAD(, ibuf) bufs; + u_int32_t queued; + int fd; }; struct ibuf_read { - u_char buf[IBUF_READ_SIZE]; - u_char *rptr; - size_t wpos; + u_char buf[IBUF_READ_SIZE]; + u_char *rptr; + size_t wpos; }; struct imsg_fd { - TAILQ_ENTRY(imsg_fd) entry; - int fd; + TAILQ_ENTRY(imsg_fd) entry; + int fd; }; struct imsgbuf { - TAILQ_HEAD(, imsg_fd) fds; - struct ibuf_read r; - struct msgbuf w; - int fd; - pid_t pid; + TAILQ_HEAD(, imsg_fd) fds; + struct ibuf_read r; + struct msgbuf w; + int fd; + pid_t pid; }; #define IMSGF_HASFD 1 struct imsg_hdr { - u_int32_t type; - u_int16_t len; - u_int16_t flags; - u_int32_t peerid; - u_int32_t pid; + u_int32_t type; + u_int16_t len; + u_int16_t flags; + u_int32_t peerid; + u_int32_t pid; }; struct imsg { - struct imsg_hdr hdr; - int fd; - void *data; + struct imsg_hdr hdr; + int fd; + void *data; }; /* buffer.c */ -struct ibuf *ibuf_open(size_t); -struct ibuf *ibuf_dynamic(size_t, size_t); -int ibuf_add(struct ibuf *, const void *, size_t); -void *ibuf_reserve(struct ibuf *, size_t); -void *ibuf_seek(struct ibuf *, size_t, size_t); -size_t ibuf_size(struct ibuf *); -size_t ibuf_left(struct ibuf *); -void ibuf_close(struct msgbuf *, struct ibuf *); -int ibuf_write(struct msgbuf *); -void ibuf_free(struct ibuf *); -void msgbuf_init(struct msgbuf *); -void msgbuf_clear(struct msgbuf *); -int msgbuf_write(struct msgbuf *); -void msgbuf_drain(struct msgbuf *, size_t); +struct ibuf *ibuf_open(size_t); +struct ibuf *ibuf_dynamic(size_t, size_t); +int ibuf_add(struct ibuf *, const void *, size_t); +void *ibuf_reserve(struct ibuf *, size_t); +void *ibuf_seek(struct ibuf *, size_t, size_t); +size_t ibuf_size(struct ibuf *); +size_t ibuf_left(struct ibuf *); +void ibuf_close(struct msgbuf *, struct ibuf *); +int ibuf_write(struct msgbuf *); +void ibuf_free(struct ibuf *); +void msgbuf_init(struct msgbuf *); +void msgbuf_clear(struct msgbuf *); +int msgbuf_write(struct msgbuf *); +void msgbuf_drain(struct msgbuf *, size_t); /* imsg.c */ -void imsg_init(struct imsgbuf *, int); -ssize_t imsg_read(struct imsgbuf *); -ssize_t imsg_get(struct imsgbuf *, struct imsg *); -int imsg_compose(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, - int, const void *, u_int16_t); -int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, - int, const struct iovec *, int); +void imsg_init(struct imsgbuf *, int); +ssize_t imsg_read(struct imsgbuf *); +ssize_t imsg_get(struct imsgbuf *, struct imsg *); +int imsg_compose(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, int, + const void *, u_int16_t); +int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, int, + const struct iovec *, int); struct ibuf *imsg_create(struct imsgbuf *, u_int32_t, u_int32_t, pid_t, - u_int16_t); -int imsg_add(struct ibuf *, const void *, u_int16_t); -void imsg_close(struct imsgbuf *, struct ibuf *); -void imsg_free(struct imsg *); -int imsg_flush(struct imsgbuf *); -void imsg_clear(struct imsgbuf *); + u_int16_t); +int imsg_add(struct ibuf *, const void *, u_int16_t); +void imsg_close(struct imsgbuf *, struct ibuf *); +void imsg_free(struct imsg *); +int imsg_flush(struct imsgbuf *); +void imsg_clear(struct imsgbuf *); #endif diff --git a/lib/ipaddr.h b/lib/ipaddr.h index ea98a1b74..98c28008d 100644 --- a/lib/ipaddr.h +++ b/lib/ipaddr.h @@ -28,22 +28,19 @@ /* * Generic IP address - union of IPv4 and IPv6 address. */ -enum ipaddr_type_t -{ - IPADDR_NONE = 0, - IPADDR_V4 = 1, /* IPv4 */ - IPADDR_V6 = 2, /* IPv6 */ +enum ipaddr_type_t { + IPADDR_NONE = 0, + IPADDR_V4 = 1, /* IPv4 */ + IPADDR_V6 = 2, /* IPv6 */ }; -struct ipaddr -{ - enum ipaddr_type_t ipa_type; - union - { - u_char addr; - struct in_addr _v4_addr; - struct in6_addr _v6_addr; - } ip; +struct ipaddr { + enum ipaddr_type_t ipa_type; + union { + u_char addr; + struct in_addr _v4_addr; + struct in6_addr _v6_addr; + } ip; #define ipaddr_v4 ip._v4_addr #define ipaddr_v6 ip._v6_addr }; @@ -55,40 +52,37 @@ struct ipaddr #define SET_IPADDR_V4(p) (p)->ipa_type = IPADDR_V4 #define SET_IPADDR_V6(p) (p)->ipa_type = IPADDR_V6 -static inline int -str2ipaddr (const char *str, struct ipaddr *ip) +static inline int str2ipaddr(const char *str, struct ipaddr *ip) { - int ret; + int ret; - memset (ip, 0, sizeof (struct ipaddr)); + memset(ip, 0, sizeof(struct ipaddr)); - ret = inet_pton (AF_INET, str, &ip->ipaddr_v4); - if (ret > 0) /* Valid IPv4 address. */ - { - ip->ipa_type = IPADDR_V4; - return 0; - } - ret = inet_pton (AF_INET6, str, &ip->ipaddr_v6); - if (ret > 0) /* Valid IPv6 address. */ - { - ip->ipa_type = IPADDR_V6; - return 0; - } + ret = inet_pton(AF_INET, str, &ip->ipaddr_v4); + if (ret > 0) /* Valid IPv4 address. */ + { + ip->ipa_type = IPADDR_V4; + return 0; + } + ret = inet_pton(AF_INET6, str, &ip->ipaddr_v6); + if (ret > 0) /* Valid IPv6 address. */ + { + ip->ipa_type = IPADDR_V6; + return 0; + } - return -1; + return -1; } -static inline char * -ipaddr2str (struct ipaddr *ip, char *buf, int size) +static inline char *ipaddr2str(struct ipaddr *ip, char *buf, int size) { - buf[0] = '\0'; - if (ip) - { - if (IS_IPADDR_V4(ip)) - inet_ntop (AF_INET, &ip->ip.addr, buf, size); - else if (IS_IPADDR_V6(ip)) - inet_ntop (AF_INET6, &ip->ip.addr, buf, size); - } - return buf; + buf[0] = '\0'; + if (ip) { + if (IS_IPADDR_V4(ip)) + inet_ntop(AF_INET, &ip->ip.addr, buf, size); + else if (IS_IPADDR_V6(ip)) + inet_ntop(AF_INET6, &ip->ip.addr, buf, size); + } + return buf; } #endif /* __IPADDR_H__ */ diff --git a/lib/jhash.c b/lib/jhash.c index 33589b64e..b943997b1 100644 --- a/lib/jhash.c +++ b/lib/jhash.c @@ -24,129 +24,138 @@ #define JHASH_GOLDEN_RATIO 0x9e3779b9 /* NOTE: Arguments are modified. */ -#define __jhash_mix(a, b, c) \ -{ \ - a -= b; a -= c; a ^= (c>>13); \ - b -= c; b -= a; b ^= (a<<8); \ - c -= a; c -= b; c ^= (b>>13); \ - a -= b; a -= c; a ^= (c>>12); \ - b -= c; b -= a; b ^= (a<<16); \ - c -= a; c -= b; c ^= (b>>5); \ - a -= b; a -= c; a ^= (c>>3); \ - b -= c; b -= a; b ^= (a<<10); \ - c -= a; c -= b; c ^= (b>>15); \ -} +#define __jhash_mix(a, b, c) \ + { \ + a -= b; \ + a -= c; \ + a ^= (c >> 13); \ + b -= c; \ + b -= a; \ + b ^= (a << 8); \ + c -= a; \ + c -= b; \ + c ^= (b >> 13); \ + a -= b; \ + a -= c; \ + a ^= (c >> 12); \ + b -= c; \ + b -= a; \ + b ^= (a << 16); \ + c -= a; \ + c -= b; \ + c ^= (b >> 5); \ + a -= b; \ + a -= c; \ + a ^= (c >> 3); \ + b -= c; \ + b -= a; \ + b ^= (a << 10); \ + c -= a; \ + c -= b; \ + c ^= (b >> 15); \ + } /* The most generic version, hashes an arbitrary sequence * of bytes. No alignment or length assumptions are made about * the input key. */ -u_int32_t -jhash (const void *key, u_int32_t length, u_int32_t initval) +u_int32_t jhash(const void *key, u_int32_t length, u_int32_t initval) { - u_int32_t a, b, c, len; - const u_int8_t *k = key; - - len = length; - a = b = JHASH_GOLDEN_RATIO; - c = initval; - - while (len >= 12) - { - a += - (k[0] + ((u_int32_t) k[1] << 8) + ((u_int32_t) k[2] << 16) + - ((u_int32_t) k[3] << 24)); - b += - (k[4] + ((u_int32_t) k[5] << 8) + ((u_int32_t) k[6] << 16) + - ((u_int32_t) k[7] << 24)); - c += - (k[8] + ((u_int32_t) k[9] << 8) + ((u_int32_t) k[10] << 16) + - ((u_int32_t) k[11] << 24)); - - __jhash_mix (a, b, c); - - k += 12; - len -= 12; - } - - c += length; - switch (len) - { - case 11: - c += ((u_int32_t) k[10] << 24); - /* fallthru */ - case 10: - c += ((u_int32_t) k[9] << 16); - /* fallthru */ - case 9: - c += ((u_int32_t) k[8] << 8); - /* fallthru */ - case 8: - b += ((u_int32_t) k[7] << 24); - /* fallthru */ - case 7: - b += ((u_int32_t) k[6] << 16); - /* fallthru */ - case 6: - b += ((u_int32_t) k[5] << 8); - /* fallthru */ - case 5: - b += k[4]; - /* fallthru */ - case 4: - a += ((u_int32_t) k[3] << 24); - /* fallthru */ - case 3: - a += ((u_int32_t) k[2] << 16); - /* fallthru */ - case 2: - a += ((u_int32_t) k[1] << 8); - /* fallthru */ - case 1: - a += k[0]; - }; - - __jhash_mix (a, b, c); - - return c; + u_int32_t a, b, c, len; + const u_int8_t *k = key; + + len = length; + a = b = JHASH_GOLDEN_RATIO; + c = initval; + + while (len >= 12) { + a += (k[0] + ((u_int32_t)k[1] << 8) + ((u_int32_t)k[2] << 16) + + ((u_int32_t)k[3] << 24)); + b += (k[4] + ((u_int32_t)k[5] << 8) + ((u_int32_t)k[6] << 16) + + ((u_int32_t)k[7] << 24)); + c += (k[8] + ((u_int32_t)k[9] << 8) + ((u_int32_t)k[10] << 16) + + ((u_int32_t)k[11] << 24)); + + __jhash_mix(a, b, c); + + k += 12; + len -= 12; + } + + c += length; + switch (len) { + case 11: + c += ((u_int32_t)k[10] << 24); + /* fallthru */ + case 10: + c += ((u_int32_t)k[9] << 16); + /* fallthru */ + case 9: + c += ((u_int32_t)k[8] << 8); + /* fallthru */ + case 8: + b += ((u_int32_t)k[7] << 24); + /* fallthru */ + case 7: + b += ((u_int32_t)k[6] << 16); + /* fallthru */ + case 6: + b += ((u_int32_t)k[5] << 8); + /* fallthru */ + case 5: + b += k[4]; + /* fallthru */ + case 4: + a += ((u_int32_t)k[3] << 24); + /* fallthru */ + case 3: + a += ((u_int32_t)k[2] << 16); + /* fallthru */ + case 2: + a += ((u_int32_t)k[1] << 8); + /* fallthru */ + case 1: + a += k[0]; + }; + + __jhash_mix(a, b, c); + + return c; } /* A special optimized version that handles 1 or more of u_int32_ts. * The length parameter here is the number of u_int32_ts in the key. */ -u_int32_t -jhash2 (const u_int32_t *k, u_int32_t length, u_int32_t initval) +u_int32_t jhash2(const u_int32_t *k, u_int32_t length, u_int32_t initval) { - u_int32_t a, b, c, len; - - a = b = JHASH_GOLDEN_RATIO; - c = initval; - len = length; - - while (len >= 3) - { - a += k[0]; - b += k[1]; - c += k[2]; - __jhash_mix (a, b, c); - k += 3; - len -= 3; - } - - c += length * 4; - - switch (len) - { - case 2: - b += k[1]; - /* fallthru */ - case 1: - a += k[0]; - }; - - __jhash_mix (a, b, c); - - return c; + u_int32_t a, b, c, len; + + a = b = JHASH_GOLDEN_RATIO; + c = initval; + len = length; + + while (len >= 3) { + a += k[0]; + b += k[1]; + c += k[2]; + __jhash_mix(a, b, c); + k += 3; + len -= 3; + } + + c += length * 4; + + switch (len) { + case 2: + b += k[1]; + /* fallthru */ + case 1: + a += k[0]; + }; + + __jhash_mix(a, b, c); + + return c; } @@ -156,26 +165,23 @@ jhash2 (const u_int32_t *k, u_int32_t length, u_int32_t initval) * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally * done at the end is not done here. */ -u_int32_t -jhash_3words (u_int32_t a, u_int32_t b, u_int32_t c, u_int32_t initval) +u_int32_t jhash_3words(u_int32_t a, u_int32_t b, u_int32_t c, u_int32_t initval) { - a += JHASH_GOLDEN_RATIO; - b += JHASH_GOLDEN_RATIO; - c += initval; + a += JHASH_GOLDEN_RATIO; + b += JHASH_GOLDEN_RATIO; + c += initval; - __jhash_mix (a, b, c); + __jhash_mix(a, b, c); - return c; + return c; } -u_int32_t -jhash_2words (u_int32_t a, u_int32_t b, u_int32_t initval) +u_int32_t jhash_2words(u_int32_t a, u_int32_t b, u_int32_t initval) { - return jhash_3words (a, b, 0, initval); + return jhash_3words(a, b, 0, initval); } -u_int32_t -jhash_1word (u_int32_t a, u_int32_t initval) +u_int32_t jhash_1word(u_int32_t a, u_int32_t initval) { - return jhash_3words (a, 0, 0, initval); + return jhash_3words(a, 0, 0, initval); } diff --git a/lib/jhash.h b/lib/jhash.h index 985ac94e0..74ce6a323 100644 --- a/lib/jhash.h +++ b/lib/jhash.h @@ -29,7 +29,8 @@ extern u_int32_t jhash(const void *key, u_int32_t length, u_int32_t initval); /* A special optimized version that handles 1 or more of u_int32_ts. * The length parameter here is the number of u_int32_ts in the key. */ -extern u_int32_t jhash2(const u_int32_t *k, u_int32_t length, u_int32_t initval); +extern u_int32_t jhash2(const u_int32_t *k, u_int32_t length, + u_int32_t initval); /* A special ultra-optimized versions that knows they are hashing exactly * 3, 2 or 1 word(s). @@ -37,7 +38,8 @@ extern u_int32_t jhash2(const u_int32_t *k, u_int32_t length, u_int32_t initval) * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally * done at the end is not done here. */ -extern u_int32_t jhash_3words(u_int32_t a, u_int32_t b, u_int32_t c, u_int32_t initval); +extern u_int32_t jhash_3words(u_int32_t a, u_int32_t b, u_int32_t c, + u_int32_t initval); extern u_int32_t jhash_2words(u_int32_t a, u_int32_t b, u_int32_t initval); extern u_int32_t jhash_1word(u_int32_t a, u_int32_t initval); diff --git a/lib/json.c b/lib/json.c index d8c97e448..40b6aadaa 100644 --- a/lib/json.c +++ b/lib/json.c @@ -28,70 +28,61 @@ * is the *last* keyword on the line no matter * what. */ -int -use_json (const int argc, struct cmd_token *argv[]) +int use_json(const int argc, struct cmd_token *argv[]) { - if (argc == 0) - return 0; + if (argc == 0) + return 0; - if (argv[argc-1]->arg && strmatch (argv[argc-1]->text, "json")) - return 1; + if (argv[argc - 1]->arg && strmatch(argv[argc - 1]->text, "json")) + return 1; - return 0; + return 0; } -void -json_object_string_add(struct json_object* obj, const char *key, - const char *s) +void json_object_string_add(struct json_object *obj, const char *key, + const char *s) { - json_object_object_add(obj, key, json_object_new_string(s)); + json_object_object_add(obj, key, json_object_new_string(s)); } -void -json_object_int_add(struct json_object* obj, const char *key, int64_t i) +void json_object_int_add(struct json_object *obj, const char *key, int64_t i) { #if defined(HAVE_JSON_C_JSON_H) - json_object_object_add(obj, key, json_object_new_int64(i)); + json_object_object_add(obj, key, json_object_new_int64(i)); #else - json_object_object_add(obj, key, json_object_new_int((int)i)); + json_object_object_add(obj, key, json_object_new_int((int)i)); #endif } -void -json_object_boolean_false_add(struct json_object* obj, const char *key) +void json_object_boolean_false_add(struct json_object *obj, const char *key) { - json_object_object_add(obj, key, json_object_new_boolean(0)); + json_object_object_add(obj, key, json_object_new_boolean(0)); } -void -json_object_boolean_true_add(struct json_object* obj, const char *key) +void json_object_boolean_true_add(struct json_object *obj, const char *key) { - json_object_object_add(obj, key, json_object_new_boolean(1)); + json_object_object_add(obj, key, json_object_new_boolean(1)); } -struct json_object* -json_object_lock(struct json_object *obj) +struct json_object *json_object_lock(struct json_object *obj) { - return json_object_get(obj); + return json_object_get(obj); } -void -json_object_free(struct json_object *obj) +void json_object_free(struct json_object *obj) { - json_object_put(obj); + json_object_put(obj); } #if !defined(HAVE_JSON_C_JSON_H) -int -json_object_object_get_ex(struct json_object *obj, - const char *key, - struct json_object **value) +int json_object_object_get_ex(struct json_object *obj, const char *key, + struct json_object **value) { - *value = json_object_object_get(obj, key); + *value = json_object_object_get(obj, key); - if (*value) - return 1; + if (*value) + return 1; - return 0; + return 0; } #endif diff --git a/lib/json.h b/lib/json.h index 86271703f..e3e55ab96 100644 --- a/lib/json.h +++ b/lib/json.h @@ -32,23 +32,22 @@ */ #define json_object_to_json_string_ext(A, B) json_object_to_json_string (A) -extern int json_object_object_get_ex(struct json_object *obj, - const char *key, - struct json_object **value); +extern int json_object_object_get_ex(struct json_object *obj, const char *key, + struct json_object **value); #endif #include "command.h" extern int use_json(const int argc, struct cmd_token *argv[]); -extern void json_object_string_add(struct json_object* obj, const char *key, - const char *s); -extern void json_object_int_add(struct json_object* obj, const char *key, - int64_t i); -extern void json_object_boolean_false_add(struct json_object* obj, - const char *key); -extern void json_object_boolean_true_add(struct json_object* obj, - const char *key); -extern struct json_object* json_object_lock(struct json_object *obj); +extern void json_object_string_add(struct json_object *obj, const char *key, + const char *s); +extern void json_object_int_add(struct json_object *obj, const char *key, + int64_t i); +extern void json_object_boolean_false_add(struct json_object *obj, + const char *key); +extern void json_object_boolean_true_add(struct json_object *obj, + const char *key); +extern struct json_object *json_object_lock(struct json_object *obj); extern void json_object_free(struct json_object *obj); #define JSON_STR "JavaScript Object Notation\n" diff --git a/lib/keychain.c b/lib/keychain.c index f768933b7..f0108e080 100644 --- a/lib/keychain.c +++ b/lib/keychain.c @@ -25,7 +25,7 @@ #include "linklist.h" #include "keychain.h" -DEFINE_MTYPE_STATIC(LIB, KEY, "Key") +DEFINE_MTYPE_STATIC(LIB, KEY, "Key") DEFINE_MTYPE_STATIC(LIB, KEYCHAIN, "Key chain") DEFINE_QOBJ_TYPE(keychain) @@ -34,210 +34,192 @@ DEFINE_QOBJ_TYPE(key) /* Master list of key chain. */ struct list *keychain_list; -static struct keychain * -keychain_new (void) +static struct keychain *keychain_new(void) { - struct keychain *keychain; - keychain = XCALLOC (MTYPE_KEYCHAIN, sizeof (struct keychain)); - QOBJ_REG (keychain, keychain); - return keychain; + struct keychain *keychain; + keychain = XCALLOC(MTYPE_KEYCHAIN, sizeof(struct keychain)); + QOBJ_REG(keychain, keychain); + return keychain; } -static void -keychain_free (struct keychain *keychain) +static void keychain_free(struct keychain *keychain) { - QOBJ_UNREG (keychain); - XFREE (MTYPE_KEYCHAIN, keychain); + QOBJ_UNREG(keychain); + XFREE(MTYPE_KEYCHAIN, keychain); } -static struct key * -key_new (void) +static struct key *key_new(void) { - struct key *key = XCALLOC (MTYPE_KEY, sizeof (struct key)); - QOBJ_REG (key, key); - return key; + struct key *key = XCALLOC(MTYPE_KEY, sizeof(struct key)); + QOBJ_REG(key, key); + return key; } -static void -key_free (struct key *key) +static void key_free(struct key *key) { - QOBJ_UNREG (key); - XFREE (MTYPE_KEY, key); + QOBJ_UNREG(key); + XFREE(MTYPE_KEY, key); } -struct keychain * -keychain_lookup (const char *name) +struct keychain *keychain_lookup(const char *name) { - struct listnode *node; - struct keychain *keychain; + struct listnode *node; + struct keychain *keychain; - if (name == NULL) - return NULL; + if (name == NULL) + return NULL; - for (ALL_LIST_ELEMENTS_RO (keychain_list, node, keychain)) - { - if (strcmp (keychain->name, name) == 0) - return keychain; - } - return NULL; + for (ALL_LIST_ELEMENTS_RO(keychain_list, node, keychain)) { + if (strcmp(keychain->name, name) == 0) + return keychain; + } + return NULL; } -static int -key_cmp_func (void *arg1, void *arg2) +static int key_cmp_func(void *arg1, void *arg2) { - const struct key *k1 = arg1; - const struct key *k2 = arg2; - - if (k1->index > k2->index) - return 1; - if (k1->index < k2->index) - return -1; - return 0; + const struct key *k1 = arg1; + const struct key *k2 = arg2; + + if (k1->index > k2->index) + return 1; + if (k1->index < k2->index) + return -1; + return 0; } -static void -key_delete_func (struct key *key) +static void key_delete_func(struct key *key) { - if (key->string) - free (key->string); - key_free (key); + if (key->string) + free(key->string); + key_free(key); } -static struct keychain * -keychain_get (const char *name) +static struct keychain *keychain_get(const char *name) { - struct keychain *keychain; + struct keychain *keychain; - keychain = keychain_lookup (name); + keychain = keychain_lookup(name); - if (keychain) - return keychain; + if (keychain) + return keychain; - keychain = keychain_new (); - keychain->name = XSTRDUP(MTYPE_KEYCHAIN, name); - keychain->key = list_new (); - keychain->key->cmp = (int (*)(void *, void *)) key_cmp_func; - keychain->key->del = (void (*)(void *)) key_delete_func; - listnode_add (keychain_list, keychain); + keychain = keychain_new(); + keychain->name = XSTRDUP(MTYPE_KEYCHAIN, name); + keychain->key = list_new(); + keychain->key->cmp = (int (*)(void *, void *))key_cmp_func; + keychain->key->del = (void (*)(void *))key_delete_func; + listnode_add(keychain_list, keychain); - return keychain; + return keychain; } -static void -keychain_delete (struct keychain *keychain) +static void keychain_delete(struct keychain *keychain) { - if (keychain->name) - XFREE(MTYPE_KEYCHAIN, keychain->name); + if (keychain->name) + XFREE(MTYPE_KEYCHAIN, keychain->name); - list_delete (keychain->key); - listnode_delete (keychain_list, keychain); - keychain_free (keychain); + list_delete(keychain->key); + listnode_delete(keychain_list, keychain); + keychain_free(keychain); } -static struct key * -key_lookup (const struct keychain *keychain, u_int32_t index) +static struct key *key_lookup(const struct keychain *keychain, u_int32_t index) { - struct listnode *node; - struct key *key; + struct listnode *node; + struct key *key; - for (ALL_LIST_ELEMENTS_RO (keychain->key, node, key)) - { - if (key->index == index) - return key; - } - return NULL; + for (ALL_LIST_ELEMENTS_RO(keychain->key, node, key)) { + if (key->index == index) + return key; + } + return NULL; } -struct key * -key_lookup_for_accept (const struct keychain *keychain, u_int32_t index) +struct key *key_lookup_for_accept(const struct keychain *keychain, + u_int32_t index) { - struct listnode *node; - struct key *key; - time_t now; - - now = time (NULL); - - for (ALL_LIST_ELEMENTS_RO (keychain->key, node, key)) - { - if (key->index >= index) - { - if (key->accept.start == 0) - return key; - - if (key->accept.start <= now) - if (key->accept.end >= now || key->accept.end == -1) - return key; + struct listnode *node; + struct key *key; + time_t now; + + now = time(NULL); + + for (ALL_LIST_ELEMENTS_RO(keychain->key, node, key)) { + if (key->index >= index) { + if (key->accept.start == 0) + return key; + + if (key->accept.start <= now) + if (key->accept.end >= now + || key->accept.end == -1) + return key; + } } - } - return NULL; + return NULL; } -struct key * -key_match_for_accept (const struct keychain *keychain, const char *auth_str) +struct key *key_match_for_accept(const struct keychain *keychain, + const char *auth_str) { - struct listnode *node; - struct key *key; - time_t now; - - now = time (NULL); - - for (ALL_LIST_ELEMENTS_RO (keychain->key, node, key)) - { - if (key->accept.start == 0 || - (key->accept.start <= now && - (key->accept.end >= now || key->accept.end == -1))) - if (strncmp (key->string, auth_str, 16) == 0) - return key; - } - return NULL; + struct listnode *node; + struct key *key; + time_t now; + + now = time(NULL); + + for (ALL_LIST_ELEMENTS_RO(keychain->key, node, key)) { + if (key->accept.start == 0 + || (key->accept.start <= now + && (key->accept.end >= now || key->accept.end == -1))) + if (strncmp(key->string, auth_str, 16) == 0) + return key; + } + return NULL; } -struct key * -key_lookup_for_send (const struct keychain *keychain) +struct key *key_lookup_for_send(const struct keychain *keychain) { - struct listnode *node; - struct key *key; - time_t now; + struct listnode *node; + struct key *key; + time_t now; - now = time (NULL); + now = time(NULL); - for (ALL_LIST_ELEMENTS_RO (keychain->key, node, key)) - { - if (key->send.start == 0) - return key; + for (ALL_LIST_ELEMENTS_RO(keychain->key, node, key)) { + if (key->send.start == 0) + return key; - if (key->send.start <= now) - if (key->send.end >= now || key->send.end == -1) - return key; - } - return NULL; + if (key->send.start <= now) + if (key->send.end >= now || key->send.end == -1) + return key; + } + return NULL; } -static struct key * -key_get (const struct keychain *keychain, u_int32_t index) +static struct key *key_get(const struct keychain *keychain, u_int32_t index) { - struct key *key; + struct key *key; - key = key_lookup (keychain, index); + key = key_lookup(keychain, index); - if (key) - return key; + if (key) + return key; - key = key_new (); - key->index = index; - listnode_add_sort (keychain->key, key); + key = key_new(); + key->index = index; + listnode_add_sort(keychain->key, key); - return key; + return key; } -static void -key_delete (struct keychain *keychain, struct key *key) +static void key_delete(struct keychain *keychain, struct key *key) { - listnode_delete (keychain->key, key); + listnode_delete(keychain->key, key); - if (key->string) - XFREE(MTYPE_KEY, key->string); - key_free (key); + if (key->string) + XFREE(MTYPE_KEY, key->string); + key_free(key); } DEFUN_NOSH (key_chain, @@ -247,13 +229,13 @@ DEFUN_NOSH (key_chain, "Key-chain management\n" "Key-chain name\n") { - int idx_word = 2; - struct keychain *keychain; + int idx_word = 2; + struct keychain *keychain; - keychain = keychain_get (argv[idx_word]->arg); - VTY_PUSH_CONTEXT (KEYCHAIN_NODE, keychain); + keychain = keychain_get(argv[idx_word]->arg); + VTY_PUSH_CONTEXT(KEYCHAIN_NODE, keychain); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_key_chain, @@ -264,20 +246,19 @@ DEFUN (no_key_chain, "Key-chain management\n" "Key-chain name\n") { - int idx_word = 3; - struct keychain *keychain; + int idx_word = 3; + struct keychain *keychain; - keychain = keychain_lookup (argv[idx_word]->arg); + keychain = keychain_lookup(argv[idx_word]->arg); - if (! keychain) - { - vty_out (vty, "Can't find keychain %s\n", argv[idx_word]->arg); - return CMD_WARNING_CONFIG_FAILED; - } + if (!keychain) { + vty_out(vty, "Can't find keychain %s\n", argv[idx_word]->arg); + return CMD_WARNING_CONFIG_FAILED; + } - keychain_delete (keychain); + keychain_delete(keychain); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_NOSH (key, @@ -286,16 +267,16 @@ DEFUN_NOSH (key, "Configure a key\n" "Key identifier number\n") { - int idx_number = 1; - VTY_DECLVAR_CONTEXT (keychain, keychain); - struct key *key; - u_int32_t index; - - index = strtoul (argv[idx_number]->arg, NULL, 10); - key = key_get (keychain, index); - VTY_PUSH_CONTEXT_SUB (KEYCHAIN_KEY_NODE, key); - - return CMD_SUCCESS; + int idx_number = 1; + VTY_DECLVAR_CONTEXT(keychain, keychain); + struct key *key; + u_int32_t index; + + index = strtoul(argv[idx_number]->arg, NULL, 10); + key = key_get(keychain, index); + VTY_PUSH_CONTEXT_SUB(KEYCHAIN_KEY_NODE, key); + + return CMD_SUCCESS; } DEFUN (no_key, @@ -305,24 +286,23 @@ DEFUN (no_key, "Delete a key\n" "Key identifier number\n") { - int idx_number = 2; - VTY_DECLVAR_CONTEXT (keychain, keychain); - struct key *key; - u_int32_t index; - - index = strtoul(argv[idx_number]->arg, NULL, 10); - key = key_lookup (keychain, index); - if (! key) - { - vty_out (vty, "Can't find key %d\n", index); - return CMD_WARNING_CONFIG_FAILED; - } - - key_delete (keychain, key); - - vty->node = KEYCHAIN_NODE; - - return CMD_SUCCESS; + int idx_number = 2; + VTY_DECLVAR_CONTEXT(keychain, keychain); + struct key *key; + u_int32_t index; + + index = strtoul(argv[idx_number]->arg, NULL, 10); + key = key_lookup(keychain, index); + if (!key) { + vty_out(vty, "Can't find key %d\n", index); + return CMD_WARNING_CONFIG_FAILED; + } + + key_delete(keychain, key); + + vty->node = KEYCHAIN_NODE; + + return CMD_SUCCESS; } DEFUN (key_string, @@ -331,14 +311,14 @@ DEFUN (key_string, "Set key string\n" "The key\n") { - int idx_line = 1; - VTY_DECLVAR_CONTEXT_SUB (key, key); + int idx_line = 1; + VTY_DECLVAR_CONTEXT_SUB(key, key); - if (key->string) - XFREE(MTYPE_KEY, key->string); - key->string = XSTRDUP(MTYPE_KEY, argv[idx_line]->arg); + if (key->string) + XFREE(MTYPE_KEY, key->string); + key->string = XSTRDUP(MTYPE_KEY, argv[idx_line]->arg); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_key_string, @@ -348,200 +328,181 @@ DEFUN (no_key_string, "Unset key string\n" "The key\n") { - VTY_DECLVAR_CONTEXT_SUB (key, key); + VTY_DECLVAR_CONTEXT_SUB(key, key); - if (key->string) - { - XFREE(MTYPE_KEY, key->string); - key->string = NULL; - } + if (key->string) { + XFREE(MTYPE_KEY, key->string); + key->string = NULL; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Convert HH:MM:SS MON DAY YEAR to time_t value. -1 is returned when given string is malformed. */ -static time_t -key_str2time (const char *time_str, const char *day_str, const char *month_str, - const char *year_str) +static time_t key_str2time(const char *time_str, const char *day_str, + const char *month_str, const char *year_str) { - int i = 0; - char *colon; - struct tm tm; - time_t time; - unsigned int sec, min, hour; - unsigned int day, month, year; - - const char *month_name[] = - { - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December", - NULL - }; - -#define _GET_LONG_RANGE(V,STR,MMCOND) \ -{ \ - unsigned long tmpl; \ - char *endptr = NULL; \ - tmpl = strtoul ((STR), &endptr, 10); \ - if (*endptr != '\0' || tmpl == ULONG_MAX) \ - return -1; \ - if (MMCOND) \ - return -1; \ - (V) = tmpl; \ -} -#define GET_LONG_RANGE(V,STR,MIN,MAX) \ - _GET_LONG_RANGE(V,STR,tmpl < (MIN) || tmpl > (MAX)) -#define GET_LONG_RANGE0(V,STR,MAX) \ - _GET_LONG_RANGE(V,STR,tmpl > (MAX)) - - /* Check hour field of time_str. */ - colon = strchr (time_str, ':'); - if (colon == NULL) - return -1; - *colon = '\0'; - - /* Hour must be between 0 and 23. */ - GET_LONG_RANGE0 (hour, time_str, 23); - - /* Check min field of time_str. */ - time_str = colon + 1; - colon = strchr (time_str, ':'); - if (*time_str == '\0' || colon == NULL) - return -1; - *colon = '\0'; - - /* Min must be between 0 and 59. */ - GET_LONG_RANGE0 (min, time_str, 59); - - /* Check sec field of time_str. */ - time_str = colon + 1; - if (*time_str == '\0') - return -1; - - /* Sec must be between 0 and 59. */ - GET_LONG_RANGE0 (sec, time_str, 59); - - /* Check day_str. Day must be <1-31>. */ - GET_LONG_RANGE (day, day_str, 1, 31); - - /* Check month_str. Month must match month_name. */ - month = 0; - if (strlen (month_str) >= 3) - for (i = 0; month_name[i]; i++) - if (strncmp (month_str, month_name[i], strlen (month_str)) == 0) - { - month = i; - break; + int i = 0; + char *colon; + struct tm tm; + time_t time; + unsigned int sec, min, hour; + unsigned int day, month, year; + + const char *month_name[] = { + "January", "February", "March", "April", "May", + "June", "July", "August", "September", "October", + "November", "December", NULL}; + +#define _GET_LONG_RANGE(V, STR, MMCOND) \ + { \ + unsigned long tmpl; \ + char *endptr = NULL; \ + tmpl = strtoul((STR), &endptr, 10); \ + if (*endptr != '\0' || tmpl == ULONG_MAX) \ + return -1; \ + if (MMCOND) \ + return -1; \ + (V) = tmpl; \ } - if (! month_name[i]) - return -1; - - /* Check year_str. Year must be <1993-2035>. */ - GET_LONG_RANGE (year, year_str, 1993, 2035); - - memset (&tm, 0, sizeof (struct tm)); - tm.tm_sec = sec; - tm.tm_min = min; - tm.tm_hour = hour; - tm.tm_mon = month; - tm.tm_mday = day; - tm.tm_year = year - 1900; - - time = mktime (&tm); - - return time; +#define GET_LONG_RANGE(V, STR, MIN, MAX) \ + _GET_LONG_RANGE(V, STR, tmpl<(MIN) || tmpl>(MAX)) +#define GET_LONG_RANGE0(V, STR, MAX) _GET_LONG_RANGE(V, STR, tmpl > (MAX)) + + /* Check hour field of time_str. */ + colon = strchr(time_str, ':'); + if (colon == NULL) + return -1; + *colon = '\0'; + + /* Hour must be between 0 and 23. */ + GET_LONG_RANGE0(hour, time_str, 23); + + /* Check min field of time_str. */ + time_str = colon + 1; + colon = strchr(time_str, ':'); + if (*time_str == '\0' || colon == NULL) + return -1; + *colon = '\0'; + + /* Min must be between 0 and 59. */ + GET_LONG_RANGE0(min, time_str, 59); + + /* Check sec field of time_str. */ + time_str = colon + 1; + if (*time_str == '\0') + return -1; + + /* Sec must be between 0 and 59. */ + GET_LONG_RANGE0(sec, time_str, 59); + + /* Check day_str. Day must be <1-31>. */ + GET_LONG_RANGE(day, day_str, 1, 31); + + /* Check month_str. Month must match month_name. */ + month = 0; + if (strlen(month_str) >= 3) + for (i = 0; month_name[i]; i++) + if (strncmp(month_str, month_name[i], strlen(month_str)) + == 0) { + month = i; + break; + } + if (!month_name[i]) + return -1; + + /* Check year_str. Year must be <1993-2035>. */ + GET_LONG_RANGE(year, year_str, 1993, 2035); + + memset(&tm, 0, sizeof(struct tm)); + tm.tm_sec = sec; + tm.tm_min = min; + tm.tm_hour = hour; + tm.tm_mon = month; + tm.tm_mday = day; + tm.tm_year = year - 1900; + + time = mktime(&tm); + + return time; #undef GET_LONG_RANGE } -static int -key_lifetime_set (struct vty *vty, struct key_range *krange, - const char *stime_str, const char *sday_str, - const char *smonth_str, const char *syear_str, - const char *etime_str, const char *eday_str, - const char *emonth_str, const char *eyear_str) +static int key_lifetime_set(struct vty *vty, struct key_range *krange, + const char *stime_str, const char *sday_str, + const char *smonth_str, const char *syear_str, + const char *etime_str, const char *eday_str, + const char *emonth_str, const char *eyear_str) { - time_t time_start; - time_t time_end; - - time_start = key_str2time (stime_str, sday_str, smonth_str, syear_str); - if (time_start < 0) - { - vty_out (vty, "Malformed time value\n"); - return CMD_WARNING_CONFIG_FAILED; - } - time_end = key_str2time (etime_str, eday_str, emonth_str, eyear_str); - - if (time_end < 0) - { - vty_out (vty, "Malformed time value\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (time_end <= time_start) - { - vty_out (vty, "Expire time is not later than start time\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - krange->start = time_start; - krange->end = time_end; - - return CMD_SUCCESS; + time_t time_start; + time_t time_end; + + time_start = key_str2time(stime_str, sday_str, smonth_str, syear_str); + if (time_start < 0) { + vty_out(vty, "Malformed time value\n"); + return CMD_WARNING_CONFIG_FAILED; + } + time_end = key_str2time(etime_str, eday_str, emonth_str, eyear_str); + + if (time_end < 0) { + vty_out(vty, "Malformed time value\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (time_end <= time_start) { + vty_out(vty, "Expire time is not later than start time\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + krange->start = time_start; + krange->end = time_end; + + return CMD_SUCCESS; } -static int -key_lifetime_duration_set (struct vty *vty, struct key_range *krange, - const char *stime_str, const char *sday_str, - const char *smonth_str, const char *syear_str, - const char *duration_str) +static int key_lifetime_duration_set(struct vty *vty, struct key_range *krange, + const char *stime_str, + const char *sday_str, + const char *smonth_str, + const char *syear_str, + const char *duration_str) { - time_t time_start; - u_int32_t duration; - - time_start = key_str2time (stime_str, sday_str, smonth_str, syear_str); - if (time_start < 0) - { - vty_out (vty, "Malformed time value\n"); - return CMD_WARNING_CONFIG_FAILED; - } - krange->start = time_start; - - duration = strtoul(duration_str, NULL, 10); - krange->duration = 1; - krange->end = time_start + duration; - - return CMD_SUCCESS; + time_t time_start; + u_int32_t duration; + + time_start = key_str2time(stime_str, sday_str, smonth_str, syear_str); + if (time_start < 0) { + vty_out(vty, "Malformed time value\n"); + return CMD_WARNING_CONFIG_FAILED; + } + krange->start = time_start; + + duration = strtoul(duration_str, NULL, 10); + krange->duration = 1; + krange->end = time_start + duration; + + return CMD_SUCCESS; } -static int -key_lifetime_infinite_set (struct vty *vty, struct key_range *krange, - const char *stime_str, const char *sday_str, - const char *smonth_str, const char *syear_str) +static int key_lifetime_infinite_set(struct vty *vty, struct key_range *krange, + const char *stime_str, + const char *sday_str, + const char *smonth_str, + const char *syear_str) { - time_t time_start; - - time_start = key_str2time (stime_str, sday_str, smonth_str, syear_str); - if (time_start < 0) - { - vty_out (vty, "Malformed time value\n"); - return CMD_WARNING_CONFIG_FAILED; - } - krange->start = time_start; - - krange->end = -1; - - return CMD_SUCCESS; + time_t time_start; + + time_start = key_str2time(stime_str, sday_str, smonth_str, syear_str); + if (time_start < 0) { + vty_out(vty, "Malformed time value\n"); + return CMD_WARNING_CONFIG_FAILED; + } + krange->start = time_start; + + krange->end = -1; + + return CMD_SUCCESS; } DEFUN (accept_lifetime_day_month_day_month, @@ -557,18 +518,21 @@ DEFUN (accept_lifetime_day_month_day_month, "Month of the year to expire\n" "Year to expire\n") { - int idx_hhmmss = 1; - int idx_number = 2; - int idx_month = 3; - int idx_number_2 = 4; - int idx_hhmmss_2 = 5; - int idx_number_3 = 6; - int idx_month_2 = 7; - int idx_number_4 = 8; - VTY_DECLVAR_CONTEXT_SUB (key, key); - - return key_lifetime_set (vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, argv[idx_month]->arg, - argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, argv[idx_month_2]->arg, argv[idx_number_4]->arg); + int idx_hhmmss = 1; + int idx_number = 2; + int idx_month = 3; + int idx_number_2 = 4; + int idx_hhmmss_2 = 5; + int idx_number_3 = 6; + int idx_month_2 = 7; + int idx_number_4 = 8; + VTY_DECLVAR_CONTEXT_SUB(key, key); + + return key_lifetime_set( + vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, + argv[idx_month]->arg, argv[idx_number_2]->arg, + argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, + argv[idx_month_2]->arg, argv[idx_number_4]->arg); } DEFUN (accept_lifetime_day_month_month_day, @@ -584,18 +548,21 @@ DEFUN (accept_lifetime_day_month_month_day, "Day of th month to expire\n" "Year to expire\n") { - int idx_hhmmss = 1; - int idx_number = 2; - int idx_month = 3; - int idx_number_2 = 4; - int idx_hhmmss_2 = 5; - int idx_month_2 = 6; - int idx_number_3 = 7; - int idx_number_4 = 8; - VTY_DECLVAR_CONTEXT_SUB (key, key); - - return key_lifetime_set (vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, argv[idx_month]->arg, - argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, argv[idx_month_2]->arg, argv[idx_number_4]->arg); + int idx_hhmmss = 1; + int idx_number = 2; + int idx_month = 3; + int idx_number_2 = 4; + int idx_hhmmss_2 = 5; + int idx_month_2 = 6; + int idx_number_3 = 7; + int idx_number_4 = 8; + VTY_DECLVAR_CONTEXT_SUB(key, key); + + return key_lifetime_set( + vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, + argv[idx_month]->arg, argv[idx_number_2]->arg, + argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, + argv[idx_month_2]->arg, argv[idx_number_4]->arg); } DEFUN (accept_lifetime_month_day_day_month, @@ -611,18 +578,21 @@ DEFUN (accept_lifetime_month_day_day_month, "Month of the year to expire\n" "Year to expire\n") { - int idx_hhmmss = 1; - int idx_month = 2; - int idx_number = 3; - int idx_number_2 = 4; - int idx_hhmmss_2 = 5; - int idx_number_3 = 6; - int idx_month_2 = 7; - int idx_number_4 = 8; - VTY_DECLVAR_CONTEXT_SUB (key, key); - - return key_lifetime_set (vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, argv[idx_month]->arg, - argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, argv[idx_month_2]->arg, argv[idx_number_4]->arg); + int idx_hhmmss = 1; + int idx_month = 2; + int idx_number = 3; + int idx_number_2 = 4; + int idx_hhmmss_2 = 5; + int idx_number_3 = 6; + int idx_month_2 = 7; + int idx_number_4 = 8; + VTY_DECLVAR_CONTEXT_SUB(key, key); + + return key_lifetime_set( + vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, + argv[idx_month]->arg, argv[idx_number_2]->arg, + argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, + argv[idx_month_2]->arg, argv[idx_number_4]->arg); } DEFUN (accept_lifetime_month_day_month_day, @@ -638,18 +608,21 @@ DEFUN (accept_lifetime_month_day_month_day, "Day of th month to expire\n" "Year to expire\n") { - int idx_hhmmss = 1; - int idx_month = 2; - int idx_number = 3; - int idx_number_2 = 4; - int idx_hhmmss_2 = 5; - int idx_month_2 = 6; - int idx_number_3 = 7; - int idx_number_4 = 8; - VTY_DECLVAR_CONTEXT_SUB (key, key); - - return key_lifetime_set (vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, argv[idx_month]->arg, - argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, argv[idx_month_2]->arg, argv[idx_number_4]->arg); + int idx_hhmmss = 1; + int idx_month = 2; + int idx_number = 3; + int idx_number_2 = 4; + int idx_hhmmss_2 = 5; + int idx_month_2 = 6; + int idx_number_3 = 7; + int idx_number_4 = 8; + VTY_DECLVAR_CONTEXT_SUB(key, key); + + return key_lifetime_set( + vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, + argv[idx_month]->arg, argv[idx_number_2]->arg, + argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, + argv[idx_month_2]->arg, argv[idx_number_4]->arg); } DEFUN (accept_lifetime_infinite_day_month, @@ -662,14 +635,15 @@ DEFUN (accept_lifetime_infinite_day_month, "Year to start\n" "Never expires") { - int idx_hhmmss = 1; - int idx_number = 2; - int idx_month = 3; - int idx_number_2 = 4; - VTY_DECLVAR_CONTEXT_SUB (key, key); - - return key_lifetime_infinite_set (vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, - argv[idx_month]->arg, argv[idx_number_2]->arg); + int idx_hhmmss = 1; + int idx_number = 2; + int idx_month = 3; + int idx_number_2 = 4; + VTY_DECLVAR_CONTEXT_SUB(key, key); + + return key_lifetime_infinite_set( + vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, + argv[idx_month]->arg, argv[idx_number_2]->arg); } DEFUN (accept_lifetime_infinite_month_day, @@ -682,14 +656,15 @@ DEFUN (accept_lifetime_infinite_month_day, "Year to start\n" "Never expires") { - int idx_hhmmss = 1; - int idx_month = 2; - int idx_number = 3; - int idx_number_2 = 4; - VTY_DECLVAR_CONTEXT_SUB (key, key); - - return key_lifetime_infinite_set (vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, - argv[idx_month]->arg, argv[idx_number_2]->arg); + int idx_hhmmss = 1; + int idx_month = 2; + int idx_number = 3; + int idx_number_2 = 4; + VTY_DECLVAR_CONTEXT_SUB(key, key); + + return key_lifetime_infinite_set( + vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, + argv[idx_month]->arg, argv[idx_number_2]->arg); } DEFUN (accept_lifetime_duration_day_month, @@ -703,15 +678,17 @@ DEFUN (accept_lifetime_duration_day_month, "Duration of the key\n" "Duration seconds\n") { - int idx_hhmmss = 1; - int idx_number = 2; - int idx_month = 3; - int idx_number_2 = 4; - int idx_number_3 = 6; - VTY_DECLVAR_CONTEXT_SUB (key, key); - - return key_lifetime_duration_set (vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, - argv[idx_month]->arg, argv[idx_number_2]->arg, argv[idx_number_3]->arg); + int idx_hhmmss = 1; + int idx_number = 2; + int idx_month = 3; + int idx_number_2 = 4; + int idx_number_3 = 6; + VTY_DECLVAR_CONTEXT_SUB(key, key); + + return key_lifetime_duration_set( + vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, + argv[idx_month]->arg, argv[idx_number_2]->arg, + argv[idx_number_3]->arg); } DEFUN (accept_lifetime_duration_month_day, @@ -725,15 +702,17 @@ DEFUN (accept_lifetime_duration_month_day, "Duration of the key\n" "Duration seconds\n") { - int idx_hhmmss = 1; - int idx_month = 2; - int idx_number = 3; - int idx_number_2 = 4; - int idx_number_3 = 6; - VTY_DECLVAR_CONTEXT_SUB (key, key); - - return key_lifetime_duration_set (vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, - argv[idx_month]->arg, argv[idx_number_2]->arg, argv[idx_number_3]->arg); + int idx_hhmmss = 1; + int idx_month = 2; + int idx_number = 3; + int idx_number_2 = 4; + int idx_number_3 = 6; + VTY_DECLVAR_CONTEXT_SUB(key, key); + + return key_lifetime_duration_set( + vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg, + argv[idx_month]->arg, argv[idx_number_2]->arg, + argv[idx_number_3]->arg); } DEFUN (send_lifetime_day_month_day_month, @@ -749,18 +728,21 @@ DEFUN (send_lifetime_day_month_day_month, "Month of the year to expire\n" "Year to expire\n") { - int idx_hhmmss = 1; - int idx_number = 2; - int idx_month = 3; - int idx_number_2 = 4; - int idx_hhmmss_2 = 5; - int idx_number_3 = 6; - int idx_month_2 = 7; - int idx_number_4 = 8; - VTY_DECLVAR_CONTEXT_SUB (key, key); - - return key_lifetime_set (vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, argv[idx_month]->arg, argv[idx_number_2]->arg, - argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, argv[idx_month_2]->arg, argv[idx_number_4]->arg); + int idx_hhmmss = 1; + int idx_number = 2; + int idx_month = 3; + int idx_number_2 = 4; + int idx_hhmmss_2 = 5; + int idx_number_3 = 6; + int idx_month_2 = 7; + int idx_number_4 = 8; + VTY_DECLVAR_CONTEXT_SUB(key, key); + + return key_lifetime_set( + vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, + argv[idx_month]->arg, argv[idx_number_2]->arg, + argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, + argv[idx_month_2]->arg, argv[idx_number_4]->arg); } DEFUN (send_lifetime_day_month_month_day, @@ -776,18 +758,21 @@ DEFUN (send_lifetime_day_month_month_day, "Day of th month to expire\n" "Year to expire\n") { - int idx_hhmmss = 1; - int idx_number = 2; - int idx_month = 3; - int idx_number_2 = 4; - int idx_hhmmss_2 = 5; - int idx_month_2 = 6; - int idx_number_3 = 7; - int idx_number_4 = 8; - VTY_DECLVAR_CONTEXT_SUB (key, key); - - return key_lifetime_set (vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, argv[idx_month]->arg, argv[idx_number_2]->arg, - argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, argv[idx_month_2]->arg, argv[idx_number_4]->arg); + int idx_hhmmss = 1; + int idx_number = 2; + int idx_month = 3; + int idx_number_2 = 4; + int idx_hhmmss_2 = 5; + int idx_month_2 = 6; + int idx_number_3 = 7; + int idx_number_4 = 8; + VTY_DECLVAR_CONTEXT_SUB(key, key); + + return key_lifetime_set( + vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, + argv[idx_month]->arg, argv[idx_number_2]->arg, + argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, + argv[idx_month_2]->arg, argv[idx_number_4]->arg); } DEFUN (send_lifetime_month_day_day_month, @@ -803,18 +788,21 @@ DEFUN (send_lifetime_month_day_day_month, "Month of the year to expire\n" "Year to expire\n") { - int idx_hhmmss = 1; - int idx_month = 2; - int idx_number = 3; - int idx_number_2 = 4; - int idx_hhmmss_2 = 5; - int idx_number_3 = 6; - int idx_month_2 = 7; - int idx_number_4 = 8; - VTY_DECLVAR_CONTEXT_SUB (key, key); - - return key_lifetime_set (vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, argv[idx_month]->arg, argv[idx_number_2]->arg, - argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, argv[idx_month_2]->arg, argv[idx_number_4]->arg); + int idx_hhmmss = 1; + int idx_month = 2; + int idx_number = 3; + int idx_number_2 = 4; + int idx_hhmmss_2 = 5; + int idx_number_3 = 6; + int idx_month_2 = 7; + int idx_number_4 = 8; + VTY_DECLVAR_CONTEXT_SUB(key, key); + + return key_lifetime_set( + vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, + argv[idx_month]->arg, argv[idx_number_2]->arg, + argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, + argv[idx_month_2]->arg, argv[idx_number_4]->arg); } DEFUN (send_lifetime_month_day_month_day, @@ -830,18 +818,21 @@ DEFUN (send_lifetime_month_day_month_day, "Day of th month to expire\n" "Year to expire\n") { - int idx_hhmmss = 1; - int idx_month = 2; - int idx_number = 3; - int idx_number_2 = 4; - int idx_hhmmss_2 = 5; - int idx_month_2 = 6; - int idx_number_3 = 7; - int idx_number_4 = 8; - VTY_DECLVAR_CONTEXT_SUB (key, key); - - return key_lifetime_set (vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, argv[idx_month]->arg, argv[idx_number_2]->arg, - argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, argv[idx_month_2]->arg, argv[idx_number_4]->arg); + int idx_hhmmss = 1; + int idx_month = 2; + int idx_number = 3; + int idx_number_2 = 4; + int idx_hhmmss_2 = 5; + int idx_month_2 = 6; + int idx_number_3 = 7; + int idx_number_4 = 8; + VTY_DECLVAR_CONTEXT_SUB(key, key); + + return key_lifetime_set( + vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, + argv[idx_month]->arg, argv[idx_number_2]->arg, + argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg, + argv[idx_month_2]->arg, argv[idx_number_4]->arg); } DEFUN (send_lifetime_infinite_day_month, @@ -854,14 +845,15 @@ DEFUN (send_lifetime_infinite_day_month, "Year to start\n" "Never expires") { - int idx_hhmmss = 1; - int idx_number = 2; - int idx_month = 3; - int idx_number_2 = 4; - VTY_DECLVAR_CONTEXT_SUB (key, key); - - return key_lifetime_infinite_set (vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, argv[idx_month]->arg, - argv[idx_number_2]->arg); + int idx_hhmmss = 1; + int idx_number = 2; + int idx_month = 3; + int idx_number_2 = 4; + VTY_DECLVAR_CONTEXT_SUB(key, key); + + return key_lifetime_infinite_set( + vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, + argv[idx_month]->arg, argv[idx_number_2]->arg); } DEFUN (send_lifetime_infinite_month_day, @@ -874,14 +866,15 @@ DEFUN (send_lifetime_infinite_month_day, "Year to start\n" "Never expires") { - int idx_hhmmss = 1; - int idx_month = 2; - int idx_number = 3; - int idx_number_2 = 4; - VTY_DECLVAR_CONTEXT_SUB (key, key); - - return key_lifetime_infinite_set (vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, argv[idx_month]->arg, - argv[idx_number_2]->arg); + int idx_hhmmss = 1; + int idx_month = 2; + int idx_number = 3; + int idx_number_2 = 4; + VTY_DECLVAR_CONTEXT_SUB(key, key); + + return key_lifetime_infinite_set( + vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, + argv[idx_month]->arg, argv[idx_number_2]->arg); } DEFUN (send_lifetime_duration_day_month, @@ -895,15 +888,17 @@ DEFUN (send_lifetime_duration_day_month, "Duration of the key\n" "Duration seconds\n") { - int idx_hhmmss = 1; - int idx_number = 2; - int idx_month = 3; - int idx_number_2 = 4; - int idx_number_3 = 6; - VTY_DECLVAR_CONTEXT_SUB (key, key); - - return key_lifetime_duration_set (vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, argv[idx_month]->arg, - argv[idx_number_2]->arg, argv[idx_number_3]->arg); + int idx_hhmmss = 1; + int idx_number = 2; + int idx_month = 3; + int idx_number_2 = 4; + int idx_number_3 = 6; + VTY_DECLVAR_CONTEXT_SUB(key, key); + + return key_lifetime_duration_set( + vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, + argv[idx_month]->arg, argv[idx_number_2]->arg, + argv[idx_number_3]->arg); } DEFUN (send_lifetime_duration_month_day, @@ -917,148 +912,156 @@ DEFUN (send_lifetime_duration_month_day, "Duration of the key\n" "Duration seconds\n") { - int idx_hhmmss = 1; - int idx_month = 2; - int idx_number = 3; - int idx_number_2 = 4; - int idx_number_3 = 6; - VTY_DECLVAR_CONTEXT_SUB (key, key); - - return key_lifetime_duration_set (vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, argv[idx_month]->arg, - argv[idx_number_2]->arg, argv[idx_number_3]->arg); + int idx_hhmmss = 1; + int idx_month = 2; + int idx_number = 3; + int idx_number_2 = 4; + int idx_number_3 = 6; + VTY_DECLVAR_CONTEXT_SUB(key, key); + + return key_lifetime_duration_set( + vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg, + argv[idx_month]->arg, argv[idx_number_2]->arg, + argv[idx_number_3]->arg); } -static struct cmd_node keychain_node = -{ - KEYCHAIN_NODE, - "%s(config-keychain)# ", - 1 -}; +static struct cmd_node keychain_node = {KEYCHAIN_NODE, "%s(config-keychain)# ", + 1}; -static struct cmd_node keychain_key_node = -{ - KEYCHAIN_KEY_NODE, - "%s(config-keychain-key)# ", - 1 -}; +static struct cmd_node keychain_key_node = {KEYCHAIN_KEY_NODE, + "%s(config-keychain-key)# ", 1}; -static int -keychain_strftime (char *buf, int bufsiz, time_t *time) +static int keychain_strftime(char *buf, int bufsiz, time_t *time) { - struct tm *tm; - size_t len; + struct tm *tm; + size_t len; - tm = localtime (time); + tm = localtime(time); - len = strftime (buf, bufsiz, "%T %b %d %Y", tm); + len = strftime(buf, bufsiz, "%T %b %d %Y", tm); - return len; + return len; } -static int -keychain_config_write (struct vty *vty) +static int keychain_config_write(struct vty *vty) { - struct keychain *keychain; - struct key *key; - struct listnode *node; - struct listnode *knode; - char buf[BUFSIZ]; - - for (ALL_LIST_ELEMENTS_RO (keychain_list, node, keychain)) - { - vty_out (vty, "key chain %s\n", keychain->name); - - for (ALL_LIST_ELEMENTS_RO (keychain->key, knode, key)) - { - vty_out (vty, " key %d\n", key->index); - - if (key->string) - vty_out (vty, " key-string %s\n", key->string); - - if (key->accept.start) - { - keychain_strftime (buf, BUFSIZ, &key->accept.start); - vty_out (vty, " accept-lifetime %s", buf); - - if (key->accept.end == -1) - vty_out (vty, " infinite"); - else if (key->accept.duration) - vty_out (vty, " duration %ld", - (long)(key->accept.end - key->accept.start)); - else - { - keychain_strftime (buf, BUFSIZ, &key->accept.end); - vty_out (vty, " %s", buf); - } - vty_out (vty, "\n"); - } - - if (key->send.start) - { - keychain_strftime (buf, BUFSIZ, &key->send.start); - vty_out (vty, " send-lifetime %s", buf); - - if (key->send.end == -1) - vty_out (vty, " infinite"); - else if (key->send.duration) - vty_out (vty, " duration %ld", (long)(key->send.end - key->send.start)); - else - { - keychain_strftime (buf, BUFSIZ, &key->send.end); - vty_out (vty, " %s", buf); + struct keychain *keychain; + struct key *key; + struct listnode *node; + struct listnode *knode; + char buf[BUFSIZ]; + + for (ALL_LIST_ELEMENTS_RO(keychain_list, node, keychain)) { + vty_out(vty, "key chain %s\n", keychain->name); + + for (ALL_LIST_ELEMENTS_RO(keychain->key, knode, key)) { + vty_out(vty, " key %d\n", key->index); + + if (key->string) + vty_out(vty, " key-string %s\n", key->string); + + if (key->accept.start) { + keychain_strftime(buf, BUFSIZ, + &key->accept.start); + vty_out(vty, " accept-lifetime %s", buf); + + if (key->accept.end == -1) + vty_out(vty, " infinite"); + else if (key->accept.duration) + vty_out(vty, " duration %ld", + (long)(key->accept.end + - key->accept.start)); + else { + keychain_strftime(buf, BUFSIZ, + &key->accept.end); + vty_out(vty, " %s", buf); + } + vty_out(vty, "\n"); + } + + if (key->send.start) { + keychain_strftime(buf, BUFSIZ, + &key->send.start); + vty_out(vty, " send-lifetime %s", buf); + + if (key->send.end == -1) + vty_out(vty, " infinite"); + else if (key->send.duration) + vty_out(vty, " duration %ld", + (long)(key->send.end + - key->send.start)); + else { + keychain_strftime(buf, BUFSIZ, + &key->send.end); + vty_out(vty, " %s", buf); + } + vty_out(vty, "\n"); + } } - vty_out (vty, "\n"); - } + vty_out(vty, "!\n"); } - vty_out (vty, "!\n"); - } - return 0; + return 0; } -void -keychain_init () +void keychain_init() { - keychain_list = list_new (); - - install_node (&keychain_node, keychain_config_write); - install_node (&keychain_key_node, NULL); - - install_default (KEYCHAIN_NODE); - install_default (KEYCHAIN_KEY_NODE); - - install_element (CONFIG_NODE, &key_chain_cmd); - install_element (CONFIG_NODE, &no_key_chain_cmd); - install_element (KEYCHAIN_NODE, &key_cmd); - install_element (KEYCHAIN_NODE, &no_key_cmd); - - install_element (KEYCHAIN_NODE, &key_chain_cmd); - install_element (KEYCHAIN_NODE, &no_key_chain_cmd); - - install_element (KEYCHAIN_KEY_NODE, &key_string_cmd); - install_element (KEYCHAIN_KEY_NODE, &no_key_string_cmd); - - install_element (KEYCHAIN_KEY_NODE, &key_chain_cmd); - install_element (KEYCHAIN_KEY_NODE, &no_key_chain_cmd); - - install_element (KEYCHAIN_KEY_NODE, &key_cmd); - install_element (KEYCHAIN_KEY_NODE, &no_key_cmd); - - install_element (KEYCHAIN_KEY_NODE, &accept_lifetime_day_month_day_month_cmd); - install_element (KEYCHAIN_KEY_NODE, &accept_lifetime_day_month_month_day_cmd); - install_element (KEYCHAIN_KEY_NODE, &accept_lifetime_month_day_day_month_cmd); - install_element (KEYCHAIN_KEY_NODE, &accept_lifetime_month_day_month_day_cmd); - install_element (KEYCHAIN_KEY_NODE, &accept_lifetime_infinite_day_month_cmd); - install_element (KEYCHAIN_KEY_NODE, &accept_lifetime_infinite_month_day_cmd); - install_element (KEYCHAIN_KEY_NODE, &accept_lifetime_duration_day_month_cmd); - install_element (KEYCHAIN_KEY_NODE, &accept_lifetime_duration_month_day_cmd); - - install_element (KEYCHAIN_KEY_NODE, &send_lifetime_day_month_day_month_cmd); - install_element (KEYCHAIN_KEY_NODE, &send_lifetime_day_month_month_day_cmd); - install_element (KEYCHAIN_KEY_NODE, &send_lifetime_month_day_day_month_cmd); - install_element (KEYCHAIN_KEY_NODE, &send_lifetime_month_day_month_day_cmd); - install_element (KEYCHAIN_KEY_NODE, &send_lifetime_infinite_day_month_cmd); - install_element (KEYCHAIN_KEY_NODE, &send_lifetime_infinite_month_day_cmd); - install_element (KEYCHAIN_KEY_NODE, &send_lifetime_duration_day_month_cmd); - install_element (KEYCHAIN_KEY_NODE, &send_lifetime_duration_month_day_cmd); + keychain_list = list_new(); + + install_node(&keychain_node, keychain_config_write); + install_node(&keychain_key_node, NULL); + + install_default(KEYCHAIN_NODE); + install_default(KEYCHAIN_KEY_NODE); + + install_element(CONFIG_NODE, &key_chain_cmd); + install_element(CONFIG_NODE, &no_key_chain_cmd); + install_element(KEYCHAIN_NODE, &key_cmd); + install_element(KEYCHAIN_NODE, &no_key_cmd); + + install_element(KEYCHAIN_NODE, &key_chain_cmd); + install_element(KEYCHAIN_NODE, &no_key_chain_cmd); + + install_element(KEYCHAIN_KEY_NODE, &key_string_cmd); + install_element(KEYCHAIN_KEY_NODE, &no_key_string_cmd); + + install_element(KEYCHAIN_KEY_NODE, &key_chain_cmd); + install_element(KEYCHAIN_KEY_NODE, &no_key_chain_cmd); + + install_element(KEYCHAIN_KEY_NODE, &key_cmd); + install_element(KEYCHAIN_KEY_NODE, &no_key_cmd); + + install_element(KEYCHAIN_KEY_NODE, + &accept_lifetime_day_month_day_month_cmd); + install_element(KEYCHAIN_KEY_NODE, + &accept_lifetime_day_month_month_day_cmd); + install_element(KEYCHAIN_KEY_NODE, + &accept_lifetime_month_day_day_month_cmd); + install_element(KEYCHAIN_KEY_NODE, + &accept_lifetime_month_day_month_day_cmd); + install_element(KEYCHAIN_KEY_NODE, + &accept_lifetime_infinite_day_month_cmd); + install_element(KEYCHAIN_KEY_NODE, + &accept_lifetime_infinite_month_day_cmd); + install_element(KEYCHAIN_KEY_NODE, + &accept_lifetime_duration_day_month_cmd); + install_element(KEYCHAIN_KEY_NODE, + &accept_lifetime_duration_month_day_cmd); + + install_element(KEYCHAIN_KEY_NODE, + &send_lifetime_day_month_day_month_cmd); + install_element(KEYCHAIN_KEY_NODE, + &send_lifetime_day_month_month_day_cmd); + install_element(KEYCHAIN_KEY_NODE, + &send_lifetime_month_day_day_month_cmd); + install_element(KEYCHAIN_KEY_NODE, + &send_lifetime_month_day_month_day_cmd); + install_element(KEYCHAIN_KEY_NODE, + &send_lifetime_infinite_day_month_cmd); + install_element(KEYCHAIN_KEY_NODE, + &send_lifetime_infinite_month_day_cmd); + install_element(KEYCHAIN_KEY_NODE, + &send_lifetime_duration_day_month_cmd); + install_element(KEYCHAIN_KEY_NODE, + &send_lifetime_duration_month_day_cmd); } diff --git a/lib/keychain.h b/lib/keychain.h index e6bdcc6f0..ab016f35c 100644 --- a/lib/keychain.h +++ b/lib/keychain.h @@ -23,41 +23,38 @@ #include "qobj.h" -struct keychain -{ - char *name; +struct keychain { + char *name; - struct list *key; + struct list *key; - QOBJ_FIELDS + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(keychain) -struct key_range -{ - time_t start; - time_t end; +struct key_range { + time_t start; + time_t end; - u_char duration; + u_char duration; }; -struct key -{ - u_int32_t index; +struct key { + u_int32_t index; - char *string; + char *string; - struct key_range send; - struct key_range accept; + struct key_range send; + struct key_range accept; - QOBJ_FIELDS + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(key) -extern void keychain_init (void); -extern struct keychain *keychain_lookup (const char *); -extern struct key *key_lookup_for_accept (const struct keychain *, u_int32_t); -extern struct key *key_match_for_accept (const struct keychain *, const char *); -extern struct key *key_lookup_for_send (const struct keychain *); +extern void keychain_init(void); +extern struct keychain *keychain_lookup(const char *); +extern struct key *key_lookup_for_accept(const struct keychain *, u_int32_t); +extern struct key *key_match_for_accept(const struct keychain *, const char *); +extern struct key *key_lookup_for_send(const struct keychain *); #endif /* _ZEBRA_KEYCHAIN_H */ diff --git a/lib/libfrr.c b/lib/libfrr.c index 8d816437c..022296b3f 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -30,7 +30,7 @@ #include "log_int.h" #include "module.h" -DEFINE_HOOK(frr_late_init, (struct thread_master *tm), (tm)) +DEFINE_HOOK(frr_late_init, (struct thread_master * tm), (tm)) const char frr_sysconfdir[] = SYSCONFDIR; const char frr_vtydir[] = DAEMON_VTY_DIR; @@ -69,14 +69,13 @@ static void opt_extend(const struct optspec *os) #define OPTION_MODULEDIR 1002 static const struct option lo_always[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'v' }, - { "daemon", no_argument, NULL, 'd' }, - { "module", no_argument, NULL, 'M' }, - { "vty_socket", required_argument, NULL, OPTION_VTYSOCK }, - { "moduledir", required_argument, NULL, OPTION_MODULEDIR }, - { NULL } -}; + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'v'}, + {"daemon", no_argument, NULL, 'd'}, + {"module", no_argument, NULL, 'M'}, + {"vty_socket", required_argument, NULL, OPTION_VTYSOCK}, + {"moduledir", required_argument, NULL, OPTION_MODULEDIR}, + {NULL}}; static const struct optspec os_always = { "hvdM:", " -h, --help Display this help and exit\n" @@ -85,60 +84,47 @@ static const struct optspec os_always = { " -M, --module Load specified module\n" " --vty_socket Override vty socket path\n" " --moduledir Override modules directory\n", - lo_always -}; + lo_always}; static const struct option lo_cfg_pid_dry[] = { - { "pid_file", required_argument, NULL, 'i' }, - { "config_file", required_argument, NULL, 'f' }, - { "dryrun", no_argument, NULL, 'C' }, - { NULL } -}; + {"pid_file", required_argument, NULL, 'i'}, + {"config_file", required_argument, NULL, 'f'}, + {"dryrun", no_argument, NULL, 'C'}, + {NULL}}; static const struct optspec os_cfg_pid_dry = { "f:i:C", " -f, --config_file Set configuration file name\n" " -i, --pid_file Set process identifier file name\n" " -C, --dryrun Check configuration for validity and exit\n", - lo_cfg_pid_dry -}; + lo_cfg_pid_dry}; static const struct option lo_zclient[] = { - { "socket", required_argument, NULL, 'z' }, - { NULL } -}; + {"socket", required_argument, NULL, 'z'}, + {NULL}}; static const struct optspec os_zclient = { - "z:", - " -z, --socket Set path of zebra socket\n", - lo_zclient -}; + "z:", " -z, --socket Set path of zebra socket\n", lo_zclient}; static const struct option lo_vty[] = { - { "vty_addr", required_argument, NULL, 'A'}, - { "vty_port", required_argument, NULL, 'P'}, - { NULL } -}; + {"vty_addr", required_argument, NULL, 'A'}, + {"vty_port", required_argument, NULL, 'P'}, + {NULL}}; static const struct optspec os_vty = { "A:P:", " -A, --vty_addr Set vty's bind address\n" " -P, --vty_port Set vty's port number\n", - lo_vty -}; + lo_vty}; -static const struct option lo_user[] = { - { "user", required_argument, NULL, 'u'}, - { "group", required_argument, NULL, 'g'}, - { NULL } -}; -static const struct optspec os_user = { - "u:g:", - " -u, --user User to run as\n" - " -g, --group Group to run as\n", - lo_user -}; +static const struct option lo_user[] = {{"user", required_argument, NULL, 'u'}, + {"group", required_argument, NULL, 'g'}, + {NULL}}; +static const struct optspec os_user = {"u:g:", + " -u, --user User to run as\n" + " -g, --group Group to run as\n", + lo_user}; static struct frr_daemon_info *di = NULL; @@ -164,18 +150,18 @@ void frr_preinit(struct frr_daemon_info *daemon, int argc, char **argv) opt_extend(&os_vty); snprintf(config_default, sizeof(config_default), "%s/%s.conf", - frr_sysconfdir, di->name); + frr_sysconfdir, di->name); snprintf(pidfile_default, sizeof(pidfile_default), "%s/%s.pid", - frr_vtydir, di->name); + frr_vtydir, di->name); strlcpy(frr_protoname, di->logname, sizeof(frr_protoname)); strlcpy(frr_protonameinst, di->logname, sizeof(frr_protonameinst)); } void frr_opt_add(const char *optstr, const struct option *longopts, - const char *helpstr) + const char *helpstr) { - const struct optspec main_opts = { optstr, helpstr, longopts }; + const struct optspec main_opts = {optstr, helpstr, longopts}; opt_extend(&main_opts); } @@ -190,11 +176,8 @@ void frr_help_exit(int status) di->printhelp(target); else fprintf(target, "Usage: %s [OPTION...]\n\n%s%s%s\n\n%s", - di->progname, - di->proghelp, - di->copyright ? "\n\n" : "", - di->copyright ? di->copyright : "", - comb_helpstr); + di->progname, di->proghelp, di->copyright ? "\n\n" : "", + di->copyright ? di->copyright : "", comb_helpstr); fprintf(target, "\nReport bugs to %s\n", FRR_BUG_ADDRESS); exit(status); } @@ -256,7 +239,8 @@ static int frr_opt(int opt) if (di->flags & FRR_NO_TCPVTY) return 1; if (vty_addr_set) { - fprintf(stderr, "-A option specified more than once!\n"); + fprintf(stderr, + "-A option specified more than once!\n"); errors++; break; } @@ -267,22 +251,25 @@ static int frr_opt(int opt) if (di->flags & FRR_NO_TCPVTY) return 1; if (vty_port_set) { - fprintf(stderr, "-P option specified more than once!\n"); + fprintf(stderr, + "-P option specified more than once!\n"); errors++; break; } vty_port_set = 1; di->vty_port = strtoul(optarg, &err, 0); if (*err || !*optarg) { - fprintf(stderr, "invalid port number \"%s\" for -P option\n", - optarg); + fprintf(stderr, + "invalid port number \"%s\" for -P option\n", + optarg); errors++; break; } break; case OPTION_VTYSOCK: if (di->vty_sock_path) { - fprintf(stderr, "--vty_socket option specified more than once!\n"); + fprintf(stderr, + "--vty_socket option specified more than once!\n"); errors++; break; } @@ -290,7 +277,8 @@ static int frr_opt(int opt) break; case OPTION_MODULEDIR: if (di->module_path) { - fprintf(stderr, "----moduledir option specified more than once!\n"); + fprintf(stderr, + "----moduledir option specified more than once!\n"); errors++; break; } @@ -312,7 +300,7 @@ static int frr_opt(int opt) return 0; } -int frr_getopt(int argc, char * const argv[], int *longindex) +int frr_getopt(int argc, char *const argv[], int *longindex) { int opt; int lidx; @@ -344,13 +332,13 @@ struct thread_master *frr_init(void) srandom(time(NULL)); if (di->instance) - snprintf(frr_protonameinst, sizeof(frr_protonameinst), - "%s[%u]", di->logname, di->instance); + snprintf(frr_protonameinst, sizeof(frr_protonameinst), "%s[%u]", + di->logname, di->instance); - openzlog (di->progname, di->logname, di->instance, - LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); + openzlog(di->progname, di->logname, di->instance, + LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON); #if defined(HAVE_CUMULUS) - zlog_set_level (ZLOG_DEST_SYSLOG, zlog_default->default_lvl); + zlog_set_level(ZLOG_DEST_SYSLOG, zlog_default->default_lvl); #endif frrmod_init(di->module); @@ -384,10 +372,11 @@ void frr_config_fork(void) hook_call(frr_late_init, master); if (di->instance) { - snprintf(config_default, sizeof(config_default), "%s/%s-%d.conf", - frr_sysconfdir, di->name, di->instance); - snprintf(pidfile_default, sizeof(pidfile_default), "%s/%s-%d.pid", - frr_vtydir, di->name, di->instance); + snprintf(config_default, sizeof(config_default), + "%s/%s-%d.conf", frr_sysconfdir, di->name, + di->instance); + snprintf(pidfile_default, sizeof(pidfile_default), + "%s/%s-%d.pid", frr_vtydir, di->name, di->instance); } vty_read_config(di->config_file, config_default); @@ -397,19 +386,19 @@ void frr_config_fork(void) exit(0); /* Daemonize. */ - if (di->daemon_mode && daemon (0, 0) < 0) { + if (di->daemon_mode && daemon(0, 0) < 0) { zlog_err("Zebra daemon failed: %s", strerror(errno)); exit(1); } if (!di->pid_file) di->pid_file = pidfile_default; - pid_output (di->pid_file); + pid_output(di->pid_file); } void frr_vty_serv(void) { - /* allow explicit override of vty_path in the future + /* allow explicit override of vty_path in the future * (not currently set anywhere) */ if (!di->vty_path) { const char *dir; @@ -417,11 +406,10 @@ void frr_vty_serv(void) if (di->instance) snprintf(vtypath_default, sizeof(vtypath_default), - "%s/%s-%d.vty", - dir, di->name, di->instance); + "%s/%s-%d.vty", dir, di->name, di->instance); else snprintf(vtypath_default, sizeof(vtypath_default), - "%s/%s.vty", dir, di->name); + "%s/%s.vty", dir, di->name); di->vty_path = vtypath_default; } @@ -437,14 +425,10 @@ void frr_run(struct thread_master *master) if (di->instance) snprintf(instanceinfo, sizeof(instanceinfo), "instance %u ", - di->instance); - - zlog_notice("%s %s starting: %svty@%d%s", - di->name, - FRR_VERSION, - instanceinfo, - di->vty_port, - di->startinfo); + di->instance); + + zlog_notice("%s %s starting: %svty@%d%s", di->name, FRR_VERSION, + instanceinfo, di->vty_port, di->startinfo); struct thread thread; while (thread_fetch(master, &thread)) diff --git a/lib/libfrr.h b/lib/libfrr.h index 832ff4486..0f6ed0cb0 100644 --- a/lib/libfrr.h +++ b/lib/libfrr.h @@ -74,30 +74,25 @@ struct frr_daemon_info { * upcoming module support) that need to place some per-daemon things. Each * daemon should have one of these. */ -#define FRR_DAEMON_INFO(execname, constname, ...) \ - static struct frr_daemon_info execname ##_di = { \ - .name = # execname, \ - .logname = # constname, \ - .module = THIS_MODULE, \ - __VA_ARGS__ \ - }; \ - FRR_COREMOD_SETUP( \ - .name = # execname, \ - .description = # execname " daemon", \ - .version = FRR_VERSION, \ - ) \ - /* end */ - -extern void frr_preinit(struct frr_daemon_info *daemon, - int argc, char **argv); -extern void frr_opt_add(const char *optstr, - const struct option *longopts, const char *helpstr); -extern int frr_getopt(int argc, char * const argv[], int *longindex); +#define FRR_DAEMON_INFO(execname, constname, ...) \ + static struct frr_daemon_info execname##_di = {.name = #execname, \ + .logname = #constname, \ + .module = THIS_MODULE, \ + __VA_ARGS__}; \ + FRR_COREMOD_SETUP(.name = #execname, \ + .description = #execname " daemon", \ + .version = FRR_VERSION, ) \ +/* end */ + +extern void frr_preinit(struct frr_daemon_info *daemon, int argc, char **argv); +extern void frr_opt_add(const char *optstr, const struct option *longopts, + const char *helpstr); +extern int frr_getopt(int argc, char *const argv[], int *longindex); extern void frr_help_exit(int status); extern struct thread_master *frr_init(void); -DECLARE_HOOK(frr_late_init, (struct thread_master *tm), (tm)) +DECLARE_HOOK(frr_late_init, (struct thread_master * tm), (tm)) extern void frr_config_fork(void); extern void frr_vty_serv(void); diff --git a/lib/linklist.c b/lib/linklist.c index 0aee54d44..c1b056d73 100644 --- a/lib/linklist.c +++ b/lib/linklist.c @@ -27,53 +27,48 @@ DEFINE_MTYPE_STATIC(LIB, LINK_LIST, "Link List") DEFINE_MTYPE_STATIC(LIB, LINK_NODE, "Link Node") /* Allocate new list. */ -struct list * -list_new (void) +struct list *list_new(void) { - return XCALLOC (MTYPE_LINK_LIST, sizeof (struct list)); + return XCALLOC(MTYPE_LINK_LIST, sizeof(struct list)); } /* Free list. */ -void -list_free (struct list *l) +void list_free(struct list *l) { - XFREE (MTYPE_LINK_LIST, l); + XFREE(MTYPE_LINK_LIST, l); } /* Allocate new listnode. Internal use only. */ -static struct listnode * -listnode_new (void) +static struct listnode *listnode_new(void) { - return XCALLOC (MTYPE_LINK_NODE, sizeof (struct listnode)); + return XCALLOC(MTYPE_LINK_NODE, sizeof(struct listnode)); } /* Free listnode. */ -static void -listnode_free (struct listnode *node) +static void listnode_free(struct listnode *node) { - XFREE (MTYPE_LINK_NODE, node); + XFREE(MTYPE_LINK_NODE, node); } /* Add new data to the list. */ -void -listnode_add (struct list *list, void *val) +void listnode_add(struct list *list, void *val) { - struct listnode *node; - - assert (val != NULL); - - node = listnode_new (); - - node->prev = list->tail; - node->data = val; - - if (list->head == NULL) - list->head = node; - else - list->tail->next = node; - list->tail = node; - - list->count++; + struct listnode *node; + + assert(val != NULL); + + node = listnode_new(); + + node->prev = list->tail; + node->data = val; + + if (list->head == NULL) + list->head = node; + else + list->tail->next = node; + list->tail = node; + + list->count++; } /* @@ -82,237 +77,216 @@ listnode_add (struct list *list, void *val) * list remains sorted. The new node is always inserted; there is no * notion of omitting duplicates. */ -void -listnode_add_sort (struct list *list, void *val) +void listnode_add_sort(struct list *list, void *val) { - struct listnode *n; - struct listnode *new; - - assert (val != NULL); - - new = listnode_new (); - new->data = val; - - if (list->cmp) - { - for (n = list->head; n; n = n->next) - { - if ((*list->cmp) (val, n->data) < 0) - { - new->next = n; - new->prev = n->prev; - - if (n->prev) - n->prev->next = new; - else - list->head = new; - n->prev = new; - list->count++; - return; - } + struct listnode *n; + struct listnode *new; + + assert(val != NULL); + + new = listnode_new(); + new->data = val; + + if (list->cmp) { + for (n = list->head; n; n = n->next) { + if ((*list->cmp)(val, n->data) < 0) { + new->next = n; + new->prev = n->prev; + + if (n->prev) + n->prev->next = new; + else + list->head = new; + n->prev = new; + list->count++; + return; + } + } } - } - new->prev = list->tail; + new->prev = list->tail; - if (list->tail) - list->tail->next = new; - else - list->head = new; + if (list->tail) + list->tail->next = new; + else + list->head = new; - list->tail = new; - list->count++; + list->tail = new; + list->count++; } -struct listnode * -listnode_add_after (struct list *list, struct listnode *pp, void *val) +struct listnode *listnode_add_after(struct list *list, struct listnode *pp, + void *val) { - struct listnode *nn; - - assert (val != NULL); - - nn = listnode_new (); - nn->data = val; - - if (pp == NULL) - { - if (list->head) - list->head->prev = nn; - else - list->tail = nn; - - nn->next = list->head; - nn->prev = pp; - - list->head = nn; - } - else - { - if (pp->next) - pp->next->prev = nn; - else - list->tail = nn; - - nn->next = pp->next; - nn->prev = pp; - - pp->next = nn; - } - list->count++; - return nn; + struct listnode *nn; + + assert(val != NULL); + + nn = listnode_new(); + nn->data = val; + + if (pp == NULL) { + if (list->head) + list->head->prev = nn; + else + list->tail = nn; + + nn->next = list->head; + nn->prev = pp; + + list->head = nn; + } else { + if (pp->next) + pp->next->prev = nn; + else + list->tail = nn; + + nn->next = pp->next; + nn->prev = pp; + + pp->next = nn; + } + list->count++; + return nn; } -struct listnode * -listnode_add_before (struct list *list, struct listnode *pp, void *val) +struct listnode *listnode_add_before(struct list *list, struct listnode *pp, + void *val) { - struct listnode *nn; - - assert (val != NULL); - - nn = listnode_new (); - nn->data = val; - - if (pp == NULL) - { - if (list->tail) - list->tail->next = nn; - else - list->head = nn; - - nn->prev = list->tail; - nn->next = pp; - - list->tail = nn; - } - else - { - if (pp->prev) - pp->prev->next = nn; - else - list->head = nn; - - nn->prev = pp->prev; - nn->next = pp; - - pp->prev = nn; - } - list->count++; - return nn; + struct listnode *nn; + + assert(val != NULL); + + nn = listnode_new(); + nn->data = val; + + if (pp == NULL) { + if (list->tail) + list->tail->next = nn; + else + list->head = nn; + + nn->prev = list->tail; + nn->next = pp; + + list->tail = nn; + } else { + if (pp->prev) + pp->prev->next = nn; + else + list->head = nn; + + nn->prev = pp->prev; + nn->next = pp; + + pp->prev = nn; + } + list->count++; + return nn; } /* Move given listnode to tail of the list */ -void -listnode_move_to_tail (struct list *l, struct listnode *n) +void listnode_move_to_tail(struct list *l, struct listnode *n) { - LISTNODE_DETACH(l,n); - LISTNODE_ATTACH(l,n); + LISTNODE_DETACH(l, n); + LISTNODE_ATTACH(l, n); } /* Delete specific date pointer from the list. */ -void -listnode_delete (struct list *list, void *val) +void listnode_delete(struct list *list, void *val) { - struct listnode *node; - - assert(list); - for (node = list->head; node; node = node->next) - { - if (node->data == val) - { - if (node->prev) - node->prev->next = node->next; - else - list->head = node->next; - - if (node->next) - node->next->prev = node->prev; - else - list->tail = node->prev; - - list->count--; - listnode_free (node); - return; + struct listnode *node; + + assert(list); + for (node = list->head; node; node = node->next) { + if (node->data == val) { + if (node->prev) + node->prev->next = node->next; + else + list->head = node->next; + + if (node->next) + node->next->prev = node->prev; + else + list->tail = node->prev; + + list->count--; + listnode_free(node); + return; + } } - } } /* Return first node's data if it is there. */ -void * -listnode_head (struct list *list) +void *listnode_head(struct list *list) { - struct listnode *node; + struct listnode *node; - assert(list); - node = list->head; + assert(list); + node = list->head; - if (node) - return node->data; - return NULL; + if (node) + return node->data; + return NULL; } /* Delete all listnode from the list. */ -void -list_delete_all_node (struct list *list) +void list_delete_all_node(struct list *list) { - struct listnode *node; - struct listnode *next; - - assert(list); - for (node = list->head; node; node = next) - { - next = node->next; - if (list->del) - (*list->del) (node->data); - listnode_free (node); - } - list->head = list->tail = NULL; - list->count = 0; + struct listnode *node; + struct listnode *next; + + assert(list); + for (node = list->head; node; node = next) { + next = node->next; + if (list->del) + (*list->del)(node->data); + listnode_free(node); + } + list->head = list->tail = NULL; + list->count = 0; } /* Delete all listnode then free list itself. */ -void -list_delete (struct list *list) +void list_delete(struct list *list) { - assert(list); - list_delete_all_node (list); - list_free (list); + assert(list); + list_delete_all_node(list); + list_free(list); } /* Lookup the node which has given data. */ -struct listnode * -listnode_lookup (struct list *list, void *data) +struct listnode *listnode_lookup(struct list *list, void *data) { - struct listnode *node; + struct listnode *node; - assert(list); - for (node = listhead(list); node; node = listnextnode (node)) - if (data == listgetdata (node)) - return node; - return NULL; + assert(list); + for (node = listhead(list); node; node = listnextnode(node)) + if (data == listgetdata(node)) + return node; + return NULL; } /* Delete the node from list. For ospfd and ospf6d. */ -void -list_delete_node (struct list *list, struct listnode *node) +void list_delete_node(struct list *list, struct listnode *node) { - if (node->prev) - node->prev->next = node->next; - else - list->head = node->next; - if (node->next) - node->next->prev = node->prev; - else - list->tail = node->prev; - list->count--; - listnode_free (node); + if (node->prev) + node->prev->next = node->next; + else + list->head = node->next; + if (node->next) + node->next->prev = node->prev; + else + list->tail = node->prev; + list->count--; + listnode_free(node); } /* ospf_spf.c */ -void -list_add_list (struct list *l, struct list *m) +void list_add_list(struct list *l, struct list *m) { - struct listnode *n; + struct listnode *n; - for (n = listhead (m); n; n = listnextnode (n)) - listnode_add (l, n->data); + for (n = listhead(m); n; n = listnextnode(n)) + listnode_add(l, n->data); } diff --git a/lib/linklist.h b/lib/linklist.h index 37ba396a7..9bd6e3849 100644 --- a/lib/linklist.h +++ b/lib/linklist.h @@ -24,33 +24,31 @@ /* listnodes must always contain data to be valid. Adding an empty node * to a list is invalid */ -struct listnode -{ - struct listnode *next; - struct listnode *prev; - - /* private member, use getdata() to retrieve, do not access directly */ - void *data; +struct listnode { + struct listnode *next; + struct listnode *prev; + + /* private member, use getdata() to retrieve, do not access directly */ + void *data; }; -struct list -{ - struct listnode *head; - struct listnode *tail; +struct list { + struct listnode *head; + struct listnode *tail; - /* invariant: count is the number of listnodes in the list */ - unsigned int count; + /* invariant: count is the number of listnodes in the list */ + unsigned int count; - /* - * Returns -1 if val1 < val2, 0 if equal?, 1 if val1 > val2. - * Used as definition of sorted for listnode_add_sort - */ - int (*cmp) (void *val1, void *val2); + /* + * Returns -1 if val1 < val2, 0 if equal?, 1 if val1 > val2. + * Used as definition of sorted for listnode_add_sort + */ + int (*cmp)(void *val1, void *val2); - /* callback to free user-owned data when listnode is deleted. supplying - * this callback is very much encouraged! - */ - void (*del) (void *val); + /* callback to free user-owned data when listnode is deleted. supplying + * this callback is very much encouraged! + */ + void (*del)(void *val); }; #define listnextnode(X) ((X) ? ((X)->next) : NULL) @@ -61,36 +59,39 @@ struct list #define listgetdata(X) (assert((X)->data != NULL), (X)->data) /* Prototypes. */ -extern struct list *list_new(void); /* encouraged: set list.del callback on new lists */ -extern void list_free (struct list *); - -extern void listnode_add (struct list *, void *); -extern void listnode_add_sort (struct list *, void *); -extern struct listnode *listnode_add_after (struct list *, struct listnode *, void *); -extern struct listnode *listnode_add_before (struct list *, struct listnode *, void *); -extern void listnode_move_to_tail (struct list *, struct listnode *); -extern void listnode_delete (struct list *, void *); -extern struct listnode *listnode_lookup (struct list *, void *); -extern void *listnode_head (struct list *); - -extern void list_delete (struct list *); -extern void list_delete_all_node (struct list *); +extern struct list * +list_new(void); /* encouraged: set list.del callback on new lists */ +extern void list_free(struct list *); + +extern void listnode_add(struct list *, void *); +extern void listnode_add_sort(struct list *, void *); +extern struct listnode *listnode_add_after(struct list *, struct listnode *, + void *); +extern struct listnode *listnode_add_before(struct list *, struct listnode *, + void *); +extern void listnode_move_to_tail(struct list *, struct listnode *); +extern void listnode_delete(struct list *, void *); +extern struct listnode *listnode_lookup(struct list *, void *); +extern void *listnode_head(struct list *); + +extern void list_delete(struct list *); +extern void list_delete_all_node(struct list *); /* For ospfd and ospf6d. */ -extern void list_delete_node (struct list *, struct listnode *); +extern void list_delete_node(struct list *, struct listnode *); /* For ospf_spf.c */ -extern void list_add_list (struct list *, struct list *); +extern void list_add_list(struct list *, struct list *); -/* List iteration macro. +/* List iteration macro. * Usage: for (ALL_LIST_ELEMENTS (...) { ... } * It is safe to delete the listnode using this macro. */ -#define ALL_LIST_ELEMENTS(list,node,nextnode,data) \ - (node) = listhead(list), ((data) = NULL); \ - (node) != NULL && \ - ((data) = listgetdata(node),(nextnode) = node->next, 1); \ - (node) = (nextnode), ((data) = NULL) +#define ALL_LIST_ELEMENTS(list, node, nextnode, data) \ + (node) = listhead(list), ((data) = NULL); \ + (node) != NULL \ + && ((data) = listgetdata(node), (nextnode) = node->next, 1); \ + (node) = (nextnode), ((data) = NULL) /* read-only list iteration macro. * Usage: as per ALL_LIST_ELEMENTS, but not safe to delete the listnode Only @@ -98,40 +99,40 @@ extern void list_add_list (struct list *, struct list *); * deleted in the body of the loop. Does not have forward-reference overhead * of previous macro. */ -#define ALL_LIST_ELEMENTS_RO(list,node,data) \ - (node) = listhead(list), ((data) = NULL);\ - (node) != NULL && ((data) = listgetdata(node), 1); \ - (node) = listnextnode(node), ((data) = NULL) +#define ALL_LIST_ELEMENTS_RO(list, node, data) \ + (node) = listhead(list), ((data) = NULL); \ + (node) != NULL && ((data) = listgetdata(node), 1); \ + (node) = listnextnode(node), ((data) = NULL) /* these *do not* cleanup list nodes and referenced data, as the functions * do - these macros simply {de,at}tach a listnode from/to a list. */ - + /* List node attach macro. */ -#define LISTNODE_ATTACH(L,N) \ - do { \ - (N)->prev = (L)->tail; \ - (N)->next = NULL; \ - if ((L)->head == NULL) \ - (L)->head = (N); \ - else \ - (L)->tail->next = (N); \ - (L)->tail = (N); \ - (L)->count++; \ - } while (0) +#define LISTNODE_ATTACH(L, N) \ + do { \ + (N)->prev = (L)->tail; \ + (N)->next = NULL; \ + if ((L)->head == NULL) \ + (L)->head = (N); \ + else \ + (L)->tail->next = (N); \ + (L)->tail = (N); \ + (L)->count++; \ + } while (0) /* List node detach macro. */ -#define LISTNODE_DETACH(L,N) \ - do { \ - if ((N)->prev) \ - (N)->prev->next = (N)->next; \ - else \ - (L)->head = (N)->next; \ - if ((N)->next) \ - (N)->next->prev = (N)->prev; \ - else \ - (L)->tail = (N)->prev; \ - (L)->count--; \ - } while (0) +#define LISTNODE_DETACH(L, N) \ + do { \ + if ((N)->prev) \ + (N)->prev->next = (N)->next; \ + else \ + (L)->head = (N)->next; \ + if ((N)->next) \ + (N)->next->prev = (N)->prev; \ + else \ + (L)->tail = (N)->prev; \ + (L)->count--; \ + } while (0) #endif /* _ZEBRA_LINKLIST_H */ diff --git a/lib/log.c b/lib/log.c index 0628b163b..28e086535 100644 --- a/lib/log.c +++ b/lib/log.c @@ -38,21 +38,13 @@ DEFINE_MTYPE_STATIC(LIB, ZLOG, "Logging") -static int logfile_fd = -1; /* Used in signal handler. */ +static int logfile_fd = -1; /* Used in signal handler. */ struct zlog *zlog_default = NULL; -const char *zlog_priority[] = -{ - "emergencies", - "alerts", - "critical", - "errors", - "warnings", - "notifications", - "informational", - "debugging", - NULL, +const char *zlog_priority[] = { + "emergencies", "alerts", "critical", "errors", "warnings", + "notifications", "informational", "debugging", NULL, }; /* @@ -77,12 +69,12 @@ const char *zlog_priority[] = * to go through and fix and test this code for correctness. * So just wrapper the bad behavior and move on. */ -static void write_wrapper (int fd, const void *buf, size_t count) +static void write_wrapper(int fd, const void *buf, size_t count) { - if (write (fd, buf, count) <= 0) - return; + if (write(fd, buf, count) <= 0) + return; - return; + return; } /** @@ -97,450 +89,425 @@ static void write_wrapper (int fd, const void *buf, size_t count) * @param nf the message to return if not found * @return the message */ -const char * -lookup_msg(const struct message *mz, int kz, const char *nf) +const char *lookup_msg(const struct message *mz, int kz, const char *nf) { - static struct message nt = { 0 }; - const char *rz = nf ? nf : "(no message found)"; - const struct message *pnt; - for (pnt = mz; memcmp(pnt, &nt, sizeof(struct message)); pnt++) - if (pnt->key == kz) { - rz = pnt->str ? pnt->str : rz; - break; - } - return rz; + static struct message nt = {0}; + const char *rz = nf ? nf : "(no message found)"; + const struct message *pnt; + for (pnt = mz; memcmp(pnt, &nt, sizeof(struct message)); pnt++) + if (pnt->key == kz) { + rz = pnt->str ? pnt->str : rz; + break; + } + return rz; } /* For time string format. */ -size_t -quagga_timestamp(int timestamp_precision, char *buf, size_t buflen) +size_t quagga_timestamp(int timestamp_precision, char *buf, size_t buflen) { - static struct { - time_t last; - size_t len; - char buf[28]; - } cache; - struct timeval clock; - - gettimeofday(&clock, NULL); - - /* first, we update the cache if the time has changed */ - if (cache.last != clock.tv_sec) - { - struct tm *tm; - cache.last = clock.tv_sec; - tm = localtime(&cache.last); - cache.len = strftime(cache.buf, sizeof(cache.buf), - "%Y/%m/%d %H:%M:%S", tm); - } - /* note: it's not worth caching the subsecond part, because - chances are that back-to-back calls are not sufficiently close together - for the clock not to have ticked forward */ - - if (buflen > cache.len) - { - memcpy(buf, cache.buf, cache.len); - if ((timestamp_precision > 0) && - (buflen > cache.len+1+timestamp_precision)) - { - /* should we worry about locale issues? */ - static const int divisor[] = {0, 100000, 10000, 1000, 100, 10, 1}; - int prec; - char *p = buf+cache.len+1+(prec = timestamp_precision); - *p-- = '\0'; - while (prec > 6) - /* this is unlikely to happen, but protect anyway */ - { - *p-- = '0'; - prec--; - } - clock.tv_usec /= divisor[prec]; - do - { - *p-- = '0'+(clock.tv_usec % 10); - clock.tv_usec /= 10; - } - while (--prec > 0); - *p = '.'; - return cache.len+1+timestamp_precision; + static struct { + time_t last; + size_t len; + char buf[28]; + } cache; + struct timeval clock; + + gettimeofday(&clock, NULL); + + /* first, we update the cache if the time has changed */ + if (cache.last != clock.tv_sec) { + struct tm *tm; + cache.last = clock.tv_sec; + tm = localtime(&cache.last); + cache.len = strftime(cache.buf, sizeof(cache.buf), + "%Y/%m/%d %H:%M:%S", tm); + } + /* note: it's not worth caching the subsecond part, because + chances are that back-to-back calls are not sufficiently close + together + for the clock not to have ticked forward */ + + if (buflen > cache.len) { + memcpy(buf, cache.buf, cache.len); + if ((timestamp_precision > 0) + && (buflen > cache.len + 1 + timestamp_precision)) { + /* should we worry about locale issues? */ + static const int divisor[] = {0, 100000, 10000, 1000, + 100, 10, 1}; + int prec; + char *p = buf + cache.len + 1 + + (prec = timestamp_precision); + *p-- = '\0'; + while (prec > 6) + /* this is unlikely to happen, but protect anyway */ + { + *p-- = '0'; + prec--; + } + clock.tv_usec /= divisor[prec]; + do { + *p-- = '0' + (clock.tv_usec % 10); + clock.tv_usec /= 10; + } while (--prec > 0); + *p = '.'; + return cache.len + 1 + timestamp_precision; + } + buf[cache.len] = '\0'; + return cache.len; } - buf[cache.len] = '\0'; - return cache.len; - } - if (buflen > 0) - buf[0] = '\0'; - return 0; + if (buflen > 0) + buf[0] = '\0'; + return 0; } /* Utility routine for current time printing. */ -static void -time_print(FILE *fp, struct timestamp_control *ctl) +static void time_print(FILE *fp, struct timestamp_control *ctl) { - if (!ctl->already_rendered) - { - ctl->len = quagga_timestamp(ctl->precision, ctl->buf, sizeof(ctl->buf)); - ctl->already_rendered = 1; - } - fprintf(fp, "%s ", ctl->buf); + if (!ctl->already_rendered) { + ctl->len = quagga_timestamp(ctl->precision, ctl->buf, + sizeof(ctl->buf)); + ctl->already_rendered = 1; + } + fprintf(fp, "%s ", ctl->buf); } - + /* va_list version of zlog. */ -void -vzlog (int priority, const char *format, va_list args) +void vzlog(int priority, const char *format, va_list args) { - char proto_str[32]; - int original_errno = errno; - struct timestamp_control tsctl; - tsctl.already_rendered = 0; - struct zlog *zl = zlog_default; - - /* When zlog_default is also NULL, use stderr for logging. */ - if (zl == NULL) - { - tsctl.precision = 0; - time_print(stderr, &tsctl); - fprintf (stderr, "%s: ", "unknown"); - vfprintf (stderr, format, args); - fprintf (stderr, "\n"); - fflush (stderr); - - /* In this case we return at here. */ - errno = original_errno; - return; - } - tsctl.precision = zl->timestamp_precision; - - /* Syslog output */ - if (priority <= zl->maxlvl[ZLOG_DEST_SYSLOG]) - { - va_list ac; - va_copy(ac, args); - vsyslog (priority|zlog_default->facility, format, ac); - va_end(ac); - } - - if (zl->instance) - sprintf (proto_str, "%s[%d]: ", zl->protoname, zl->instance); - else - sprintf (proto_str, "%s: ", zl->protoname); - - /* File output. */ - if ((priority <= zl->maxlvl[ZLOG_DEST_FILE]) && zl->fp) - { - va_list ac; - time_print (zl->fp, &tsctl); - if (zl->record_priority) - fprintf (zl->fp, "%s: ", zlog_priority[priority]); - fprintf (zl->fp, "%s", proto_str); - va_copy(ac, args); - vfprintf (zl->fp, format, ac); - va_end(ac); - fprintf (zl->fp, "\n"); - fflush (zl->fp); - } - - /* stdout output. */ - if (priority <= zl->maxlvl[ZLOG_DEST_STDOUT]) - { - va_list ac; - time_print (stdout, &tsctl); - if (zl->record_priority) - fprintf (stdout, "%s: ", zlog_priority[priority]); - fprintf (stdout, "%s", proto_str); - va_copy(ac, args); - vfprintf (stdout, format, ac); - va_end(ac); - fprintf (stdout, "\n"); - fflush (stdout); - } - - /* Terminal monitor. */ - if (priority <= zl->maxlvl[ZLOG_DEST_MONITOR]) - vty_log ((zl->record_priority ? zlog_priority[priority] : NULL), - proto_str, format, &tsctl, args); - - errno = original_errno; + char proto_str[32]; + int original_errno = errno; + struct timestamp_control tsctl; + tsctl.already_rendered = 0; + struct zlog *zl = zlog_default; + + /* When zlog_default is also NULL, use stderr for logging. */ + if (zl == NULL) { + tsctl.precision = 0; + time_print(stderr, &tsctl); + fprintf(stderr, "%s: ", "unknown"); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); + fflush(stderr); + + /* In this case we return at here. */ + errno = original_errno; + return; + } + tsctl.precision = zl->timestamp_precision; + + /* Syslog output */ + if (priority <= zl->maxlvl[ZLOG_DEST_SYSLOG]) { + va_list ac; + va_copy(ac, args); + vsyslog(priority | zlog_default->facility, format, ac); + va_end(ac); + } + + if (zl->instance) + sprintf(proto_str, "%s[%d]: ", zl->protoname, zl->instance); + else + sprintf(proto_str, "%s: ", zl->protoname); + + /* File output. */ + if ((priority <= zl->maxlvl[ZLOG_DEST_FILE]) && zl->fp) { + va_list ac; + time_print(zl->fp, &tsctl); + if (zl->record_priority) + fprintf(zl->fp, "%s: ", zlog_priority[priority]); + fprintf(zl->fp, "%s", proto_str); + va_copy(ac, args); + vfprintf(zl->fp, format, ac); + va_end(ac); + fprintf(zl->fp, "\n"); + fflush(zl->fp); + } + + /* stdout output. */ + if (priority <= zl->maxlvl[ZLOG_DEST_STDOUT]) { + va_list ac; + time_print(stdout, &tsctl); + if (zl->record_priority) + fprintf(stdout, "%s: ", zlog_priority[priority]); + fprintf(stdout, "%s", proto_str); + va_copy(ac, args); + vfprintf(stdout, format, ac); + va_end(ac); + fprintf(stdout, "\n"); + fflush(stdout); + } + + /* Terminal monitor. */ + if (priority <= zl->maxlvl[ZLOG_DEST_MONITOR]) + vty_log((zl->record_priority ? zlog_priority[priority] : NULL), + proto_str, format, &tsctl, args); + + errno = original_errno; } -int -vzlog_test (int priority) +int vzlog_test(int priority) { - struct zlog *zl = zlog_default; - - /* When zlog_default is also NULL, use stderr for logging. */ - if (zl == NULL) - { - return 1; - } - - /* Syslog output */ - if (priority <= zl->maxlvl[ZLOG_DEST_SYSLOG]) - { - return 1; - } - - /* File output. */ - if ((priority <= zl->maxlvl[ZLOG_DEST_FILE]) && zl->fp) - { - return 1; - } - - /* stdout output. */ - if (priority <= zl->maxlvl[ZLOG_DEST_STDOUT]) - { - return 1; - } - - /* Terminal monitor. */ - if (priority <= zl->maxlvl[ZLOG_DEST_MONITOR]) - return 1; - - return 0; + struct zlog *zl = zlog_default; + + /* When zlog_default is also NULL, use stderr for logging. */ + if (zl == NULL) { + return 1; + } + + /* Syslog output */ + if (priority <= zl->maxlvl[ZLOG_DEST_SYSLOG]) { + return 1; + } + + /* File output. */ + if ((priority <= zl->maxlvl[ZLOG_DEST_FILE]) && zl->fp) { + return 1; + } + + /* stdout output. */ + if (priority <= zl->maxlvl[ZLOG_DEST_STDOUT]) { + return 1; + } + + /* Terminal monitor. */ + if (priority <= zl->maxlvl[ZLOG_DEST_MONITOR]) + return 1; + + return 0; } -static char * -str_append(char *dst, int len, const char *src) +static char *str_append(char *dst, int len, const char *src) { - while ((len-- > 0) && *src) - *dst++ = *src++; - return dst; + while ((len-- > 0) && *src) + *dst++ = *src++; + return dst; } -static char * -num_append(char *s, int len, u_long x) +static char *num_append(char *s, int len, u_long x) { - char buf[30]; - char *t; - - if (!x) - return str_append(s,len,"0"); - *(t = &buf[sizeof(buf)-1]) = '\0'; - while (x && (t > buf)) - { - *--t = '0'+(x % 10); - x /= 10; - } - return str_append(s,len,t); + char buf[30]; + char *t; + + if (!x) + return str_append(s, len, "0"); + *(t = &buf[sizeof(buf) - 1]) = '\0'; + while (x && (t > buf)) { + *--t = '0' + (x % 10); + x /= 10; + } + return str_append(s, len, t); } #if defined(SA_SIGINFO) || defined(HAVE_STACK_TRACE) -static char * -hex_append(char *s, int len, u_long x) +static char *hex_append(char *s, int len, u_long x) { - char buf[30]; - char *t; - - if (!x) - return str_append(s,len,"0"); - *(t = &buf[sizeof(buf)-1]) = '\0'; - while (x && (t > buf)) - { - u_int cc = (x % 16); - *--t = ((cc < 10) ? ('0'+cc) : ('a'+cc-10)); - x /= 16; - } - return str_append(s,len,t); + char buf[30]; + char *t; + + if (!x) + return str_append(s, len, "0"); + *(t = &buf[sizeof(buf) - 1]) = '\0'; + while (x && (t > buf)) { + u_int cc = (x % 16); + *--t = ((cc < 10) ? ('0' + cc) : ('a' + cc - 10)); + x /= 16; + } + return str_append(s, len, t); } #endif /* Needs to be enhanced to support Solaris. */ -static int -syslog_connect(void) +static int syslog_connect(void) { #ifdef SUNOS_5 - return -1; + return -1; #else - int fd; - char *s; - struct sockaddr_un addr; + int fd; + char *s; + struct sockaddr_un addr; - if ((fd = socket(AF_UNIX,SOCK_DGRAM,0)) < 0) - return -1; - addr.sun_family = AF_UNIX; + if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) + return -1; + addr.sun_family = AF_UNIX; #ifdef _PATH_LOG #define SYSLOG_SOCKET_PATH _PATH_LOG #else #define SYSLOG_SOCKET_PATH "/dev/log" #endif - s = str_append(addr.sun_path,sizeof(addr.sun_path),SYSLOG_SOCKET_PATH); + s = str_append(addr.sun_path, sizeof(addr.sun_path), + SYSLOG_SOCKET_PATH); #undef SYSLOG_SOCKET_PATH - *s = '\0'; - if (connect(fd,(struct sockaddr *)&addr,sizeof(addr)) < 0) - { - close(fd); - return -1; - } - return fd; + *s = '\0'; + if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + close(fd); + return -1; + } + return fd; #endif } -static void -syslog_sigsafe(int priority, const char *msg, size_t msglen) +static void syslog_sigsafe(int priority, const char *msg, size_t msglen) { - static int syslog_fd = -1; - char buf[sizeof("<1234567890>ripngd[1234567890]: ")+msglen+50]; - char *s; + static int syslog_fd = -1; + char buf[sizeof("<1234567890>ripngd[1234567890]: ") + msglen + 50]; + char *s; - if ((syslog_fd < 0) && ((syslog_fd = syslog_connect()) < 0)) - return; + if ((syslog_fd < 0) && ((syslog_fd = syslog_connect()) < 0)) + return; #define LOC s,buf+sizeof(buf)-s - s = buf; - s = str_append(LOC,"<"); - s = num_append(LOC,priority); - s = str_append(LOC,">"); - /* forget about the timestamp, too difficult in a signal handler */ - s = str_append(LOC,zlog_default->ident); - if (zlog_default->syslog_options & LOG_PID) - { - s = str_append(LOC,"["); - s = num_append(LOC,getpid()); - s = str_append(LOC,"]"); - } - s = str_append(LOC,": "); - s = str_append(LOC,msg); - write_wrapper (syslog_fd,buf,s-buf); + s = buf; + s = str_append(LOC, "<"); + s = num_append(LOC, priority); + s = str_append(LOC, ">"); + /* forget about the timestamp, too difficult in a signal handler */ + s = str_append(LOC, zlog_default->ident); + if (zlog_default->syslog_options & LOG_PID) { + s = str_append(LOC, "["); + s = num_append(LOC, getpid()); + s = str_append(LOC, "]"); + } + s = str_append(LOC, ": "); + s = str_append(LOC, msg); + write_wrapper(syslog_fd, buf, s - buf); #undef LOC } -static int -open_crashlog(void) +static int open_crashlog(void) { #define CRASHLOG_PREFIX "/var/tmp/quagga." #define CRASHLOG_SUFFIX "crashlog" - if (zlog_default && zlog_default->ident) - { - /* Avoid strlen since it is not async-signal-safe. */ - const char *p; - size_t ilen; - - for (p = zlog_default->ident, ilen = 0; *p; p++) - ilen++; - { - char buf[sizeof(CRASHLOG_PREFIX)+ilen+sizeof(CRASHLOG_SUFFIX)+3]; - char *s = buf; + if (zlog_default && zlog_default->ident) { + /* Avoid strlen since it is not async-signal-safe. */ + const char *p; + size_t ilen; + + for (p = zlog_default->ident, ilen = 0; *p; p++) + ilen++; + { + char buf[sizeof(CRASHLOG_PREFIX) + ilen + + sizeof(CRASHLOG_SUFFIX) + 3]; + char *s = buf; #define LOC s,buf+sizeof(buf)-s - s = str_append(LOC, CRASHLOG_PREFIX); - s = str_append(LOC, zlog_default->ident); - s = str_append(LOC, "."); - s = str_append(LOC, CRASHLOG_SUFFIX); + s = str_append(LOC, CRASHLOG_PREFIX); + s = str_append(LOC, zlog_default->ident); + s = str_append(LOC, "."); + s = str_append(LOC, CRASHLOG_SUFFIX); #undef LOC - *s = '\0'; - return open(buf, O_WRONLY|O_CREAT|O_EXCL, LOGFILE_MASK); - } - } - return open(CRASHLOG_PREFIX CRASHLOG_SUFFIX, O_WRONLY|O_CREAT|O_EXCL, - LOGFILE_MASK); + *s = '\0'; + return open(buf, O_WRONLY | O_CREAT | O_EXCL, + LOGFILE_MASK); + } + } + return open(CRASHLOG_PREFIX CRASHLOG_SUFFIX, + O_WRONLY | O_CREAT | O_EXCL, LOGFILE_MASK); #undef CRASHLOG_SUFFIX #undef CRASHLOG_PREFIX } /* Note: the goal here is to use only async-signal-safe functions. */ -void -zlog_signal(int signo, const char *action +void zlog_signal(int signo, const char *action #ifdef SA_SIGINFO - , siginfo_t *siginfo, void *program_counter + , + siginfo_t *siginfo, void *program_counter #endif - ) + ) { - time_t now; - char buf[sizeof("DEFAULT: Received signal S at T (si_addr 0xP, PC 0xP); aborting...")+100]; - char *s = buf; - char *msgstart = buf; + time_t now; + char buf[sizeof("DEFAULT: Received signal S at T (si_addr 0xP, PC 0xP); aborting...") + + 100]; + char *s = buf; + char *msgstart = buf; #define LOC s,buf+sizeof(buf)-s - time(&now); - if (zlog_default) - { - s = str_append(LOC,zlog_default->protoname); - *s++ = ':'; - *s++ = ' '; - msgstart = s; - } - s = str_append(LOC,"Received signal "); - s = num_append(LOC,signo); - s = str_append(LOC," at "); - s = num_append(LOC,now); + time(&now); + if (zlog_default) { + s = str_append(LOC, zlog_default->protoname); + *s++ = ':'; + *s++ = ' '; + msgstart = s; + } + s = str_append(LOC, "Received signal "); + s = num_append(LOC, signo); + s = str_append(LOC, " at "); + s = num_append(LOC, now); #ifdef SA_SIGINFO - s = str_append(LOC," (si_addr 0x"); - s = hex_append(LOC,(u_long)(siginfo->si_addr)); - if (program_counter) - { - s = str_append(LOC,", PC 0x"); - s = hex_append(LOC,(u_long)program_counter); - } - s = str_append(LOC,"); "); -#else /* SA_SIGINFO */ - s = str_append(LOC,"; "); + s = str_append(LOC, " (si_addr 0x"); + s = hex_append(LOC, (u_long)(siginfo->si_addr)); + if (program_counter) { + s = str_append(LOC, ", PC 0x"); + s = hex_append(LOC, (u_long)program_counter); + } + s = str_append(LOC, "); "); +#else /* SA_SIGINFO */ + s = str_append(LOC, "; "); #endif /* SA_SIGINFO */ - s = str_append(LOC,action); - if (s < buf+sizeof(buf)) - *s++ = '\n'; + s = str_append(LOC, action); + if (s < buf + sizeof(buf)) + *s++ = '\n'; - /* N.B. implicit priority is most severe */ +/* N.B. implicit priority is most severe */ #define PRI LOG_CRIT #define DUMP(FD) write_wrapper(FD, buf, s-buf); - /* If no file logging configured, try to write to fallback log file. */ - if ((logfile_fd >= 0) || ((logfile_fd = open_crashlog()) >= 0)) - DUMP(logfile_fd) - if (!zlog_default) - DUMP(STDERR_FILENO) - else - { - if (PRI <= zlog_default->maxlvl[ZLOG_DEST_STDOUT]) - DUMP(STDOUT_FILENO) - /* Remove trailing '\n' for monitor and syslog */ - *--s = '\0'; - if (PRI <= zlog_default->maxlvl[ZLOG_DEST_MONITOR]) - vty_log_fixed(buf,s-buf); - if (PRI <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG]) - syslog_sigsafe(PRI|zlog_default->facility,msgstart,s-msgstart); - } + /* If no file logging configured, try to write to fallback log file. */ + if ((logfile_fd >= 0) || ((logfile_fd = open_crashlog()) >= 0)) + DUMP(logfile_fd) + if (!zlog_default) + DUMP(STDERR_FILENO) + else { + if (PRI <= zlog_default->maxlvl[ZLOG_DEST_STDOUT]) + DUMP(STDOUT_FILENO) + /* Remove trailing '\n' for monitor and syslog */ + *--s = '\0'; + if (PRI <= zlog_default->maxlvl[ZLOG_DEST_MONITOR]) + vty_log_fixed(buf, s - buf); + if (PRI <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG]) + syslog_sigsafe(PRI | zlog_default->facility, msgstart, + s - msgstart); + } #undef DUMP - zlog_backtrace_sigsafe(PRI, + zlog_backtrace_sigsafe(PRI, #ifdef SA_SIGINFO - program_counter + program_counter #else - NULL + NULL #endif - ); - - s = buf; - struct thread *tc; - tc = pthread_getspecific (thread_current); - if (!tc) - s = str_append (LOC, "no thread information available\n"); - else - { - s = str_append (LOC, "in thread "); - s = str_append (LOC, tc->funcname); - s = str_append (LOC, " scheduled from "); - s = str_append (LOC, tc->schedfrom); - s = str_append (LOC, ":"); - s = num_append (LOC, tc->schedfrom_line); - s = str_append (LOC, "\n"); - } + ); + + s = buf; + struct thread *tc; + tc = pthread_getspecific(thread_current); + if (!tc) + s = str_append(LOC, "no thread information available\n"); + else { + s = str_append(LOC, "in thread "); + s = str_append(LOC, tc->funcname); + s = str_append(LOC, " scheduled from "); + s = str_append(LOC, tc->schedfrom); + s = str_append(LOC, ":"); + s = num_append(LOC, tc->schedfrom_line); + s = str_append(LOC, "\n"); + } #define DUMP(FD) write_wrapper(FD, buf, s-buf); - /* If no file logging configured, try to write to fallback log file. */ - if (logfile_fd >= 0) - DUMP(logfile_fd) - if (!zlog_default) - DUMP(STDERR_FILENO) - else - { - if (PRI <= zlog_default->maxlvl[ZLOG_DEST_STDOUT]) - DUMP(STDOUT_FILENO) - /* Remove trailing '\n' for monitor and syslog */ - *--s = '\0'; - if (PRI <= zlog_default->maxlvl[ZLOG_DEST_MONITOR]) - vty_log_fixed(buf,s-buf); - if (PRI <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG]) - syslog_sigsafe(PRI|zlog_default->facility,msgstart,s-msgstart); - } + /* If no file logging configured, try to write to fallback log file. */ + if (logfile_fd >= 0) + DUMP(logfile_fd) + if (!zlog_default) + DUMP(STDERR_FILENO) + else { + if (PRI <= zlog_default->maxlvl[ZLOG_DEST_STDOUT]) + DUMP(STDOUT_FILENO) + /* Remove trailing '\n' for monitor and syslog */ + *--s = '\0'; + if (PRI <= zlog_default->maxlvl[ZLOG_DEST_MONITOR]) + vty_log_fixed(buf, s - buf); + if (PRI <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG]) + syslog_sigsafe(PRI | zlog_default->facility, msgstart, + s - msgstart); + } #undef DUMP #undef PRI @@ -549,144 +516,143 @@ zlog_signal(int signo, const char *action /* Log a backtrace using only async-signal-safe functions. Needs to be enhanced to support syslog logging. */ -void -zlog_backtrace_sigsafe(int priority, void *program_counter) +void zlog_backtrace_sigsafe(int priority, void *program_counter) { #ifdef HAVE_STACK_TRACE - static const char pclabel[] = "Program counter: "; - void *array[64]; - int size; - char buf[100]; - char *s, **bt = NULL; + static const char pclabel[] = "Program counter: "; + void *array[64]; + int size; + char buf[100]; + char *s, **bt = NULL; #define LOC s,buf+sizeof(buf)-s #ifdef HAVE_GLIBC_BACKTRACE - size = backtrace(array, array_size(array)); - if (size <= 0 || (size_t)size > array_size(array)) - return; - -#define DUMP(FD) { \ - if (program_counter) \ - { \ - write_wrapper(FD, pclabel, sizeof(pclabel)-1); \ - backtrace_symbols_fd(&program_counter, 1, FD); \ - } \ - write_wrapper(FD, buf, s-buf); \ - backtrace_symbols_fd(array, size, FD); \ -} + size = backtrace(array, array_size(array)); + if (size <= 0 || (size_t)size > array_size(array)) + return; + +#define DUMP(FD) \ + { \ + if (program_counter) { \ + write_wrapper(FD, pclabel, sizeof(pclabel) - 1); \ + backtrace_symbols_fd(&program_counter, 1, FD); \ + } \ + write_wrapper(FD, buf, s - buf); \ + backtrace_symbols_fd(array, size, FD); \ + } #elif defined(HAVE_PRINTSTACK) -#define DUMP(FD) { \ - if (program_counter) \ - write_wrapper((FD), pclabel, sizeof(pclabel)-1); \ - write_wrapper((FD), buf, s-buf); \ - printstack((FD)); \ -} +#define DUMP(FD) \ + { \ + if (program_counter) \ + write_wrapper((FD), pclabel, sizeof(pclabel) - 1); \ + write_wrapper((FD), buf, s - buf); \ + printstack((FD)); \ + } #endif /* HAVE_GLIBC_BACKTRACE, HAVE_PRINTSTACK */ - s = buf; - s = str_append(LOC,"Backtrace for "); - s = num_append(LOC,size); - s = str_append(LOC," stack frames:\n"); - - if ((logfile_fd >= 0) || ((logfile_fd = open_crashlog()) >= 0)) - DUMP(logfile_fd) - if (!zlog_default) - DUMP(STDERR_FILENO) - else - { - if (priority <= zlog_default->maxlvl[ZLOG_DEST_STDOUT]) - DUMP(STDOUT_FILENO) - /* Remove trailing '\n' for monitor and syslog */ - *--s = '\0'; - if (priority <= zlog_default->maxlvl[ZLOG_DEST_MONITOR]) - vty_log_fixed(buf,s-buf); - if (priority <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG]) - syslog_sigsafe(priority|zlog_default->facility,buf,s-buf); - { - int i; + s = buf; + s = str_append(LOC, "Backtrace for "); + s = num_append(LOC, size); + s = str_append(LOC, " stack frames:\n"); + + if ((logfile_fd >= 0) || ((logfile_fd = open_crashlog()) >= 0)) + DUMP(logfile_fd) + if (!zlog_default) + DUMP(STDERR_FILENO) + else { + if (priority <= zlog_default->maxlvl[ZLOG_DEST_STDOUT]) + DUMP(STDOUT_FILENO) + /* Remove trailing '\n' for monitor and syslog */ + *--s = '\0'; + if (priority <= zlog_default->maxlvl[ZLOG_DEST_MONITOR]) + vty_log_fixed(buf, s - buf); + if (priority <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG]) + syslog_sigsafe(priority | zlog_default->facility, buf, + s - buf); + { + int i; #ifdef HAVE_GLIBC_BACKTRACE - bt = backtrace_symbols(array, size); + bt = backtrace_symbols(array, size); #endif - /* Just print the function addresses. */ - for (i = 0; i < size; i++) - { - s = buf; - if (bt) - s = str_append(LOC, bt[i]); - else { - s = str_append(LOC,"[bt "); - s = num_append(LOC,i); - s = str_append(LOC,"] 0x"); - s = hex_append(LOC,(u_long)(array[i])); - } - *s = '\0'; - if (priority <= zlog_default->maxlvl[ZLOG_DEST_MONITOR]) - vty_log_fixed(buf,s-buf); - if (priority <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG]) - syslog_sigsafe(priority|zlog_default->facility,buf,s-buf); - } - if (bt) - free(bt); - } - } + /* Just print the function addresses. */ + for (i = 0; i < size; i++) { + s = buf; + if (bt) + s = str_append(LOC, bt[i]); + else { + s = str_append(LOC, "[bt "); + s = num_append(LOC, i); + s = str_append(LOC, "] 0x"); + s = hex_append(LOC, (u_long)(array[i])); + } + *s = '\0'; + if (priority + <= zlog_default->maxlvl[ZLOG_DEST_MONITOR]) + vty_log_fixed(buf, s - buf); + if (priority + <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG]) + syslog_sigsafe( + priority + | zlog_default + ->facility, + buf, s - buf); + } + if (bt) + free(bt); + } + } #undef DUMP #undef LOC #endif /* HAVE_STRACK_TRACE */ } -void -zlog_backtrace(int priority) +void zlog_backtrace(int priority) { #ifndef HAVE_GLIBC_BACKTRACE - zlog(priority, "No backtrace available on this platform."); + zlog(priority, "No backtrace available on this platform."); #else - void *array[20]; - int size, i; - char **strings; - - size = backtrace(array, array_size(array)); - if (size <= 0 || (size_t)size > array_size(array)) - { - zlog_err("Cannot get backtrace, returned invalid # of frames %d " - "(valid range is between 1 and %lu)", - size, (unsigned long)(array_size(array))); - return; - } - zlog(priority, "Backtrace for %d stack frames:", size); - if (!(strings = backtrace_symbols(array, size))) - { - zlog_err("Cannot get backtrace symbols (out of memory?)"); - for (i = 0; i < size; i++) - zlog(priority, "[bt %d] %p",i,array[i]); - } - else - { - for (i = 0; i < size; i++) - zlog(priority, "[bt %d] %s",i,strings[i]); - free(strings); - } + void *array[20]; + int size, i; + char **strings; + + size = backtrace(array, array_size(array)); + if (size <= 0 || (size_t)size > array_size(array)) { + zlog_err( + "Cannot get backtrace, returned invalid # of frames %d " + "(valid range is between 1 and %lu)", + size, (unsigned long)(array_size(array))); + return; + } + zlog(priority, "Backtrace for %d stack frames:", size); + if (!(strings = backtrace_symbols(array, size))) { + zlog_err("Cannot get backtrace symbols (out of memory?)"); + for (i = 0; i < size; i++) + zlog(priority, "[bt %d] %p", i, array[i]); + } else { + for (i = 0; i < size; i++) + zlog(priority, "[bt %d] %s", i, strings[i]); + free(strings); + } #endif /* HAVE_GLIBC_BACKTRACE */ } -void -zlog (int priority, const char *format, ...) +void zlog(int priority, const char *format, ...) { - va_list args; + va_list args; - va_start(args, format); - vzlog (priority, format, args); - va_end (args); + va_start(args, format); + vzlog(priority, format, args); + va_end(args); } -#define ZLOG_FUNC(FUNCNAME,PRIORITY) \ -void \ -FUNCNAME(const char *format, ...) \ -{ \ - va_list args; \ - va_start(args, format); \ - vzlog (PRIORITY, format, args); \ - va_end(args); \ -} +#define ZLOG_FUNC(FUNCNAME, PRIORITY) \ + void FUNCNAME(const char *format, ...) \ + { \ + va_list args; \ + va_start(args, format); \ + vzlog(PRIORITY, format, args); \ + va_end(args); \ + } ZLOG_FUNC(zlog_err, LOG_ERR) @@ -700,458 +666,444 @@ ZLOG_FUNC(zlog_debug, LOG_DEBUG) #undef ZLOG_FUNC -void zlog_thread_info (int log_level) +void zlog_thread_info(int log_level) { - struct thread *tc; - tc = pthread_getspecific (thread_current); - - if (tc) - zlog(log_level, "Current thread function %s, scheduled from " - "file %s, line %u", tc->funcname, - tc->schedfrom, tc->schedfrom_line); - else - zlog(log_level, "Current thread not known/applicable"); + struct thread *tc; + tc = pthread_getspecific(thread_current); + + if (tc) + zlog(log_level, + "Current thread function %s, scheduled from " + "file %s, line %u", + tc->funcname, tc->schedfrom, tc->schedfrom_line); + else + zlog(log_level, "Current thread not known/applicable"); } -void -_zlog_assert_failed (const char *assertion, const char *file, - unsigned int line, const char *function) +void _zlog_assert_failed(const char *assertion, const char *file, + unsigned int line, const char *function) { - /* Force fallback file logging? */ - if (zlog_default && !zlog_default->fp && - ((logfile_fd = open_crashlog()) >= 0) && - ((zlog_default->fp = fdopen(logfile_fd, "w")) != NULL)) - zlog_default->maxlvl[ZLOG_DEST_FILE] = LOG_ERR; - zlog(LOG_CRIT, "Assertion `%s' failed in file %s, line %u, function %s", - assertion,file,line,(function ? function : "?")); - zlog_backtrace(LOG_CRIT); - zlog_thread_info(LOG_CRIT); - log_memstats_stderr ("log"); - abort(); + /* Force fallback file logging? */ + if (zlog_default && !zlog_default->fp + && ((logfile_fd = open_crashlog()) >= 0) + && ((zlog_default->fp = fdopen(logfile_fd, "w")) != NULL)) + zlog_default->maxlvl[ZLOG_DEST_FILE] = LOG_ERR; + zlog(LOG_CRIT, "Assertion `%s' failed in file %s, line %u, function %s", + assertion, file, line, (function ? function : "?")); + zlog_backtrace(LOG_CRIT); + zlog_thread_info(LOG_CRIT); + log_memstats_stderr("log"); + abort(); } -void -memory_oom (size_t size, const char *name) +void memory_oom(size_t size, const char *name) { - zlog_err("out of memory: failed to allocate %zu bytes for %s" - "object", size, name); + zlog_err( + "out of memory: failed to allocate %zu bytes for %s" + "object", + size, name); zlog_backtrace(LOG_ERR); abort(); } /* Open log stream */ -void -openzlog (const char *progname, const char *protoname, u_short instance, - int syslog_flags, int syslog_facility) +void openzlog(const char *progname, const char *protoname, u_short instance, + int syslog_flags, int syslog_facility) { - struct zlog *zl; - u_int i; + struct zlog *zl; + u_int i; - zl = XCALLOC(MTYPE_ZLOG, sizeof (struct zlog)); + zl = XCALLOC(MTYPE_ZLOG, sizeof(struct zlog)); - zl->ident = progname; - zl->protoname = protoname; - zl->instance = instance; - zl->facility = syslog_facility; - zl->syslog_options = syslog_flags; + zl->ident = progname; + zl->protoname = protoname; + zl->instance = instance; + zl->facility = syslog_facility; + zl->syslog_options = syslog_flags; - /* Set default logging levels. */ - for (i = 0; i < array_size(zl->maxlvl); i++) - zl->maxlvl[i] = ZLOG_DISABLED; - zl->maxlvl[ZLOG_DEST_MONITOR] = LOG_DEBUG; - zl->default_lvl = LOG_DEBUG; + /* Set default logging levels. */ + for (i = 0; i < array_size(zl->maxlvl); i++) + zl->maxlvl[i] = ZLOG_DISABLED; + zl->maxlvl[ZLOG_DEST_MONITOR] = LOG_DEBUG; + zl->default_lvl = LOG_DEBUG; - openlog (progname, syslog_flags, zl->facility); - zlog_default = zl; + openlog(progname, syslog_flags, zl->facility); + zlog_default = zl; #ifdef HAVE_GLIBC_BACKTRACE - /* work around backtrace() using lazily resolved dynamically linked - * symbols, which will otherwise cause funny breakage in the SEGV handler. - * (particularly, the dynamic linker can call malloc(), which uses locks - * in programs linked with -pthread, thus can deadlock.) */ - void *bt[4]; - backtrace (bt, array_size(bt)); - free (backtrace_symbols (bt, 0)); - backtrace_symbols_fd (bt, 0, 0); + /* work around backtrace() using lazily resolved dynamically linked + * symbols, which will otherwise cause funny breakage in the SEGV + * handler. + * (particularly, the dynamic linker can call malloc(), which uses locks + * in programs linked with -pthread, thus can deadlock.) */ + void *bt[4]; + backtrace(bt, array_size(bt)); + free(backtrace_symbols(bt, 0)); + backtrace_symbols_fd(bt, 0, 0); #endif } -void -closezlog (void) +void closezlog(void) { - struct zlog *zl = zlog_default; + struct zlog *zl = zlog_default; - closelog(); + closelog(); - if (zl->fp != NULL) - fclose (zl->fp); + if (zl->fp != NULL) + fclose(zl->fp); - if (zl->filename != NULL) - XFREE(MTYPE_ZLOG, zl->filename); + if (zl->filename != NULL) + XFREE(MTYPE_ZLOG, zl->filename); - XFREE (MTYPE_ZLOG, zl); - zlog_default = NULL; + XFREE(MTYPE_ZLOG, zl); + zlog_default = NULL; } /* Called from command.c. */ -void -zlog_set_level (zlog_dest_t dest, int log_level) +void zlog_set_level(zlog_dest_t dest, int log_level) { - zlog_default->maxlvl[dest] = log_level; + zlog_default->maxlvl[dest] = log_level; } -int -zlog_set_file (const char *filename, int log_level) +int zlog_set_file(const char *filename, int log_level) { - struct zlog *zl = zlog_default; - FILE *fp; - mode_t oldumask; - - /* There is opend file. */ - zlog_reset_file (); - - /* Open file. */ - oldumask = umask (0777 & ~LOGFILE_MASK); - fp = fopen (filename, "a"); - umask(oldumask); - if (fp == NULL) - return 0; - - /* Set flags. */ - zl->filename = XSTRDUP(MTYPE_ZLOG, filename); - zl->maxlvl[ZLOG_DEST_FILE] = log_level; - zl->fp = fp; - logfile_fd = fileno(fp); - - return 1; + struct zlog *zl = zlog_default; + FILE *fp; + mode_t oldumask; + + /* There is opend file. */ + zlog_reset_file(); + + /* Open file. */ + oldumask = umask(0777 & ~LOGFILE_MASK); + fp = fopen(filename, "a"); + umask(oldumask); + if (fp == NULL) + return 0; + + /* Set flags. */ + zl->filename = XSTRDUP(MTYPE_ZLOG, filename); + zl->maxlvl[ZLOG_DEST_FILE] = log_level; + zl->fp = fp; + logfile_fd = fileno(fp); + + return 1; } /* Reset opend file. */ -int -zlog_reset_file (void) +int zlog_reset_file(void) { - struct zlog *zl = zlog_default; + struct zlog *zl = zlog_default; - if (zl->fp) - fclose (zl->fp); - zl->fp = NULL; - logfile_fd = -1; - zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED; + if (zl->fp) + fclose(zl->fp); + zl->fp = NULL; + logfile_fd = -1; + zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED; - if (zl->filename) - XFREE(MTYPE_ZLOG, zl->filename); - zl->filename = NULL; + if (zl->filename) + XFREE(MTYPE_ZLOG, zl->filename); + zl->filename = NULL; - return 1; + return 1; } /* Reopen log file. */ -int -zlog_rotate (void) +int zlog_rotate(void) { - struct zlog *zl = zlog_default; - int level; - - if (zl->fp) - fclose (zl->fp); - zl->fp = NULL; - logfile_fd = -1; - level = zl->maxlvl[ZLOG_DEST_FILE]; - zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED; - - if (zl->filename) - { - mode_t oldumask; - int save_errno; - - oldumask = umask (0777 & ~LOGFILE_MASK); - zl->fp = fopen (zl->filename, "a"); - save_errno = errno; - umask(oldumask); - if (zl->fp == NULL) - { - zlog_err("Log rotate failed: cannot open file %s for append: %s", - zl->filename, safe_strerror(save_errno)); - return -1; - } - logfile_fd = fileno(zl->fp); - zl->maxlvl[ZLOG_DEST_FILE] = level; - } - - return 1; + struct zlog *zl = zlog_default; + int level; + + if (zl->fp) + fclose(zl->fp); + zl->fp = NULL; + logfile_fd = -1; + level = zl->maxlvl[ZLOG_DEST_FILE]; + zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED; + + if (zl->filename) { + mode_t oldumask; + int save_errno; + + oldumask = umask(0777 & ~LOGFILE_MASK); + zl->fp = fopen(zl->filename, "a"); + save_errno = errno; + umask(oldumask); + if (zl->fp == NULL) { + zlog_err( + "Log rotate failed: cannot open file %s for append: %s", + zl->filename, safe_strerror(save_errno)); + return -1; + } + logfile_fd = fileno(zl->fp); + zl->maxlvl[ZLOG_DEST_FILE] = level; + } + + return 1; } /* Wrapper around strerror to handle case where it returns NULL. */ -const char * -safe_strerror(int errnum) +const char *safe_strerror(int errnum) { - const char *s = strerror(errnum); - return (s != NULL) ? s : "Unknown error"; + const char *s = strerror(errnum); + return (s != NULL) ? s : "Unknown error"; } #define DESC_ENTRY(T) [(T)] = { (T), (#T), '\0' } static const struct zebra_desc_table command_types[] = { - DESC_ENTRY (ZEBRA_INTERFACE_ADD), - DESC_ENTRY (ZEBRA_INTERFACE_DELETE), - DESC_ENTRY (ZEBRA_INTERFACE_ADDRESS_ADD), - DESC_ENTRY (ZEBRA_INTERFACE_ADDRESS_DELETE), - DESC_ENTRY (ZEBRA_INTERFACE_UP), - DESC_ENTRY (ZEBRA_INTERFACE_DOWN), - DESC_ENTRY (ZEBRA_IPV4_ROUTE_ADD), - DESC_ENTRY (ZEBRA_IPV4_ROUTE_DELETE), - DESC_ENTRY (ZEBRA_IPV6_ROUTE_ADD), - DESC_ENTRY (ZEBRA_IPV6_ROUTE_DELETE), - DESC_ENTRY (ZEBRA_REDISTRIBUTE_ADD), - DESC_ENTRY (ZEBRA_REDISTRIBUTE_DELETE), - DESC_ENTRY (ZEBRA_REDISTRIBUTE_DEFAULT_ADD), - DESC_ENTRY (ZEBRA_REDISTRIBUTE_DEFAULT_DELETE), - DESC_ENTRY (ZEBRA_ROUTER_ID_ADD), - DESC_ENTRY (ZEBRA_ROUTER_ID_DELETE), - DESC_ENTRY (ZEBRA_ROUTER_ID_UPDATE), - DESC_ENTRY (ZEBRA_HELLO), - DESC_ENTRY (ZEBRA_NEXTHOP_REGISTER), - DESC_ENTRY (ZEBRA_NEXTHOP_UNREGISTER), - DESC_ENTRY (ZEBRA_NEXTHOP_UPDATE), - DESC_ENTRY (ZEBRA_INTERFACE_NBR_ADDRESS_ADD), - DESC_ENTRY (ZEBRA_INTERFACE_NBR_ADDRESS_DELETE), - DESC_ENTRY (ZEBRA_INTERFACE_BFD_DEST_UPDATE), - DESC_ENTRY (ZEBRA_IMPORT_ROUTE_REGISTER), - DESC_ENTRY (ZEBRA_IMPORT_ROUTE_UNREGISTER), - DESC_ENTRY (ZEBRA_IMPORT_CHECK_UPDATE), - DESC_ENTRY (ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD), - DESC_ENTRY (ZEBRA_BFD_DEST_REGISTER), - DESC_ENTRY (ZEBRA_BFD_DEST_DEREGISTER), - DESC_ENTRY (ZEBRA_BFD_DEST_UPDATE), - DESC_ENTRY (ZEBRA_BFD_DEST_REPLAY), - DESC_ENTRY (ZEBRA_REDISTRIBUTE_IPV4_ADD), - DESC_ENTRY (ZEBRA_REDISTRIBUTE_IPV4_DEL), - DESC_ENTRY (ZEBRA_REDISTRIBUTE_IPV6_ADD), - DESC_ENTRY (ZEBRA_REDISTRIBUTE_IPV6_DEL), - DESC_ENTRY (ZEBRA_VRF_UNREGISTER), - DESC_ENTRY (ZEBRA_VRF_ADD), - DESC_ENTRY (ZEBRA_VRF_DELETE), - DESC_ENTRY (ZEBRA_INTERFACE_VRF_UPDATE), - DESC_ENTRY (ZEBRA_BFD_CLIENT_REGISTER), - DESC_ENTRY (ZEBRA_INTERFACE_ENABLE_RADV), - DESC_ENTRY (ZEBRA_INTERFACE_DISABLE_RADV), - DESC_ENTRY (ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB), - DESC_ENTRY (ZEBRA_INTERFACE_LINK_PARAMS), - DESC_ENTRY (ZEBRA_MPLS_LABELS_ADD), - DESC_ENTRY (ZEBRA_MPLS_LABELS_DELETE), - DESC_ENTRY (ZEBRA_IPV4_NEXTHOP_ADD), - DESC_ENTRY (ZEBRA_IPV4_NEXTHOP_DELETE), - DESC_ENTRY (ZEBRA_IPV6_NEXTHOP_ADD), - DESC_ENTRY (ZEBRA_IPV6_NEXTHOP_DELETE), - DESC_ENTRY (ZEBRA_IPMR_ROUTE_STATS), - DESC_ENTRY (ZEBRA_LABEL_MANAGER_CONNECT), - DESC_ENTRY (ZEBRA_GET_LABEL_CHUNK), - DESC_ENTRY (ZEBRA_RELEASE_LABEL_CHUNK), - DESC_ENTRY (ZEBRA_ADVERTISE_ALL_VNI), - DESC_ENTRY (ZEBRA_VNI_ADD), - DESC_ENTRY (ZEBRA_VNI_DEL), - DESC_ENTRY (ZEBRA_REMOTE_VTEP_ADD), - DESC_ENTRY (ZEBRA_REMOTE_VTEP_DEL), - DESC_ENTRY (ZEBRA_MACIP_ADD), - DESC_ENTRY (ZEBRA_MACIP_DEL), - DESC_ENTRY (ZEBRA_REMOTE_MACIP_ADD), - DESC_ENTRY (ZEBRA_REMOTE_MACIP_DEL), + DESC_ENTRY(ZEBRA_INTERFACE_ADD), + DESC_ENTRY(ZEBRA_INTERFACE_DELETE), + DESC_ENTRY(ZEBRA_INTERFACE_ADDRESS_ADD), + DESC_ENTRY(ZEBRA_INTERFACE_ADDRESS_DELETE), + DESC_ENTRY(ZEBRA_INTERFACE_UP), + DESC_ENTRY(ZEBRA_INTERFACE_DOWN), + DESC_ENTRY(ZEBRA_IPV4_ROUTE_ADD), + DESC_ENTRY(ZEBRA_IPV4_ROUTE_DELETE), + DESC_ENTRY(ZEBRA_IPV6_ROUTE_ADD), + DESC_ENTRY(ZEBRA_IPV6_ROUTE_DELETE), + DESC_ENTRY(ZEBRA_REDISTRIBUTE_ADD), + DESC_ENTRY(ZEBRA_REDISTRIBUTE_DELETE), + DESC_ENTRY(ZEBRA_REDISTRIBUTE_DEFAULT_ADD), + DESC_ENTRY(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE), + DESC_ENTRY(ZEBRA_ROUTER_ID_ADD), + DESC_ENTRY(ZEBRA_ROUTER_ID_DELETE), + DESC_ENTRY(ZEBRA_ROUTER_ID_UPDATE), + DESC_ENTRY(ZEBRA_HELLO), + DESC_ENTRY(ZEBRA_NEXTHOP_REGISTER), + DESC_ENTRY(ZEBRA_NEXTHOP_UNREGISTER), + DESC_ENTRY(ZEBRA_NEXTHOP_UPDATE), + DESC_ENTRY(ZEBRA_INTERFACE_NBR_ADDRESS_ADD), + DESC_ENTRY(ZEBRA_INTERFACE_NBR_ADDRESS_DELETE), + DESC_ENTRY(ZEBRA_INTERFACE_BFD_DEST_UPDATE), + DESC_ENTRY(ZEBRA_IMPORT_ROUTE_REGISTER), + DESC_ENTRY(ZEBRA_IMPORT_ROUTE_UNREGISTER), + DESC_ENTRY(ZEBRA_IMPORT_CHECK_UPDATE), + DESC_ENTRY(ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD), + DESC_ENTRY(ZEBRA_BFD_DEST_REGISTER), + DESC_ENTRY(ZEBRA_BFD_DEST_DEREGISTER), + DESC_ENTRY(ZEBRA_BFD_DEST_UPDATE), + DESC_ENTRY(ZEBRA_BFD_DEST_REPLAY), + DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV4_ADD), + DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV4_DEL), + DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV6_ADD), + DESC_ENTRY(ZEBRA_REDISTRIBUTE_IPV6_DEL), + DESC_ENTRY(ZEBRA_VRF_UNREGISTER), + DESC_ENTRY(ZEBRA_VRF_ADD), + DESC_ENTRY(ZEBRA_VRF_DELETE), + DESC_ENTRY(ZEBRA_INTERFACE_VRF_UPDATE), + DESC_ENTRY(ZEBRA_BFD_CLIENT_REGISTER), + DESC_ENTRY(ZEBRA_INTERFACE_ENABLE_RADV), + DESC_ENTRY(ZEBRA_INTERFACE_DISABLE_RADV), + DESC_ENTRY(ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB), + DESC_ENTRY(ZEBRA_INTERFACE_LINK_PARAMS), + DESC_ENTRY(ZEBRA_MPLS_LABELS_ADD), + DESC_ENTRY(ZEBRA_MPLS_LABELS_DELETE), + DESC_ENTRY(ZEBRA_IPV4_NEXTHOP_ADD), + DESC_ENTRY(ZEBRA_IPV4_NEXTHOP_DELETE), + DESC_ENTRY(ZEBRA_IPV6_NEXTHOP_ADD), + DESC_ENTRY(ZEBRA_IPV6_NEXTHOP_DELETE), + DESC_ENTRY(ZEBRA_IPMR_ROUTE_STATS), + DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT), + DESC_ENTRY(ZEBRA_GET_LABEL_CHUNK), + DESC_ENTRY(ZEBRA_RELEASE_LABEL_CHUNK), + DESC_ENTRY(ZEBRA_ADVERTISE_ALL_VNI), + DESC_ENTRY(ZEBRA_VNI_ADD), + DESC_ENTRY(ZEBRA_VNI_DEL), + DESC_ENTRY(ZEBRA_REMOTE_VTEP_ADD), + DESC_ENTRY(ZEBRA_REMOTE_VTEP_DEL), + DESC_ENTRY(ZEBRA_MACIP_ADD), + DESC_ENTRY(ZEBRA_MACIP_DEL), + DESC_ENTRY(ZEBRA_REMOTE_MACIP_ADD), + DESC_ENTRY(ZEBRA_REMOTE_MACIP_DEL), }; #undef DESC_ENTRY -static const struct zebra_desc_table unknown = { 0, "unknown", '?' }; +static const struct zebra_desc_table unknown = {0, "unknown", '?'}; -static const struct zebra_desc_table * -zroute_lookup(u_int zroute) +static const struct zebra_desc_table *zroute_lookup(u_int zroute) { - u_int i; - - if (zroute >= array_size(route_types)) - { - zlog_err("unknown zebra route type: %u", zroute); - return &unknown; - } - if (zroute == route_types[zroute].type) - return &route_types[zroute]; - for (i = 0; i < array_size(route_types); i++) - { - if (zroute == route_types[i].type) - { - zlog_warn("internal error: route type table out of order " - "while searching for %u, please notify developers", zroute); - return &route_types[i]; - } - } - zlog_err("internal error: cannot find route type %u in table!", zroute); - return &unknown; + u_int i; + + if (zroute >= array_size(route_types)) { + zlog_err("unknown zebra route type: %u", zroute); + return &unknown; + } + if (zroute == route_types[zroute].type) + return &route_types[zroute]; + for (i = 0; i < array_size(route_types); i++) { + if (zroute == route_types[i].type) { + zlog_warn( + "internal error: route type table out of order " + "while searching for %u, please notify developers", + zroute); + return &route_types[i]; + } + } + zlog_err("internal error: cannot find route type %u in table!", zroute); + return &unknown; } -const char * -zebra_route_string(u_int zroute) +const char *zebra_route_string(u_int zroute) { - return zroute_lookup(zroute)->string; + return zroute_lookup(zroute)->string; } -char -zebra_route_char(u_int zroute) +char zebra_route_char(u_int zroute) { - return zroute_lookup(zroute)->chr; + return zroute_lookup(zroute)->chr; } -const char * -zserv_command_string (unsigned int command) +const char *zserv_command_string(unsigned int command) { - if (command >= array_size(command_types)) - { - zlog_err ("unknown zserv command type: %u", command); - return unknown.string; - } - return command_types[command].string; + if (command >= array_size(command_types)) { + zlog_err("unknown zserv command type: %u", command); + return unknown.string; + } + return command_types[command].string; } -int -proto_name2num(const char *s) +int proto_name2num(const char *s) { - unsigned i; + unsigned i; - for (i=0; i= len) /* end of block, not really printing */ - s += sprintf(s, " "); - - else if(isprint((int)((const char *)mem)[j])) /* printable char */ - s += sprintf(s, "%c", 0xFF & ((const char *)mem)[j]); - - else /* other char */ - s += sprintf(s, "."); - } - s += sprintf(s, "\n"); - } - } - zlog_debug("\n%s", buf); +void zlog_hexdump(const void *mem, unsigned int len) +{ + unsigned long i = 0; + unsigned int j = 0; + unsigned int columns = 8; + char buf[(len * 4) + ((len / 4) * 20) + 30]; + char *s = buf; + + for (i = 0; i < len + ((len % columns) ? (columns - len % columns) : 0); + i++) { + /* print offset */ + if (i % columns == 0) + s += sprintf(s, "0x%016lx: ", (unsigned long)mem + i); + + /* print hex data */ + if (i < len) + s += sprintf(s, "%02x ", 0xFF & ((const char *)mem)[i]); + + /* end of block, just aligning for ASCII dump */ + else + s += sprintf(s, " "); + + /* print ASCII dump */ + if (i % columns == (columns - 1)) { + for (j = i - (columns - 1); j <= i; j++) { + if (j >= len) /* end of block, not really + printing */ + s += sprintf(s, " "); + + else if ( + isprint((int)((const char *)mem) + [j])) /* printable char + */ + s += sprintf( + s, "%c", + 0xFF & ((const char *)mem)[j]); + + else /* other char */ + s += sprintf(s, "."); + } + s += sprintf(s, "\n"); + } + } + zlog_debug("\n%s", buf); } -const char * -zlog_sanitize (char *buf, size_t bufsz, const void *in, size_t inlen) +const char *zlog_sanitize(char *buf, size_t bufsz, const void *in, size_t inlen) { - const char *inbuf = in; - char *pos = buf, *end = buf + bufsz; - const char *iend = inbuf + inlen; - - memset (buf, 0, bufsz); - for (; inbuf < iend; inbuf++) - { - /* don't write partial escape sequence */ - if (end - pos < 5) - break; - - if (*inbuf == '\n') - snprintf (pos, end - pos, "\\n"); - else if (*inbuf == '\r') - snprintf (pos, end - pos, "\\r"); - else if (*inbuf == '\t') - snprintf (pos, end - pos, "\\t"); - else if (*inbuf < ' ' || *inbuf == '"' || *inbuf >= 127) - snprintf (pos, end - pos, "\\x%02hhx", *inbuf); - else - *pos = *inbuf; - - pos += strlen (pos); - } - return buf; + const char *inbuf = in; + char *pos = buf, *end = buf + bufsz; + const char *iend = inbuf + inlen; + + memset(buf, 0, bufsz); + for (; inbuf < iend; inbuf++) { + /* don't write partial escape sequence */ + if (end - pos < 5) + break; + + if (*inbuf == '\n') + snprintf(pos, end - pos, "\\n"); + else if (*inbuf == '\r') + snprintf(pos, end - pos, "\\r"); + else if (*inbuf == '\t') + snprintf(pos, end - pos, "\\t"); + else if (*inbuf < ' ' || *inbuf == '"' || *inbuf >= 127) + snprintf(pos, end - pos, "\\x%02hhx", *inbuf); + else + *pos = *inbuf; + + pos += strlen(pos); + } + return buf; } diff --git a/lib/log.h b/lib/log.h index f8b1cd361..d872ce56d 100644 --- a/lib/log.h +++ b/lib/log.h @@ -46,28 +46,27 @@ to that logging destination. */ #define ZLOG_DISABLED (LOG_EMERG-1) -typedef enum -{ - ZLOG_DEST_SYSLOG = 0, - ZLOG_DEST_STDOUT, - ZLOG_DEST_MONITOR, - ZLOG_DEST_FILE +typedef enum { + ZLOG_DEST_SYSLOG = 0, + ZLOG_DEST_STDOUT, + ZLOG_DEST_MONITOR, + ZLOG_DEST_FILE } zlog_dest_t; #define ZLOG_NUM_DESTS (ZLOG_DEST_FILE+1) /* Message structure. */ -struct message -{ - int key; - const char *str; +struct message { + int key; + const char *str; }; /* Open zlog function */ -extern void openzlog (const char *progname, const char *protoname, - uint16_t instance, int syslog_options, int syslog_facility); +extern void openzlog(const char *progname, const char *protoname, + uint16_t instance, int syslog_options, + int syslog_facility); /* Close zlog function. */ -extern void closezlog (void); +extern void closezlog(void); /* GCC have printf type attribute check. */ #ifdef __GNUC__ @@ -77,29 +76,29 @@ extern void closezlog (void); #endif /* __GNUC__ */ /* Handy zlog functions. */ -extern void zlog_err (const char *format, ...) PRINTF_ATTRIBUTE(1, 2); -extern void zlog_warn (const char *format, ...) PRINTF_ATTRIBUTE(1, 2); -extern void zlog_info (const char *format, ...) PRINTF_ATTRIBUTE(1, 2); -extern void zlog_notice (const char *format, ...) PRINTF_ATTRIBUTE(1, 2); -extern void zlog_debug (const char *format, ...) PRINTF_ATTRIBUTE(1, 2); +extern void zlog_err(const char *format, ...) PRINTF_ATTRIBUTE(1, 2); +extern void zlog_warn(const char *format, ...) PRINTF_ATTRIBUTE(1, 2); +extern void zlog_info(const char *format, ...) PRINTF_ATTRIBUTE(1, 2); +extern void zlog_notice(const char *format, ...) PRINTF_ATTRIBUTE(1, 2); +extern void zlog_debug(const char *format, ...) PRINTF_ATTRIBUTE(1, 2); -extern void zlog_thread_info (int log_level); +extern void zlog_thread_info(int log_level); /* Set logging level for the given destination. If the log_level argument is ZLOG_DISABLED, then the destination is disabled. This function should not be used for file logging (use zlog_set_file or zlog_reset_file instead). */ -extern void zlog_set_level (zlog_dest_t, int log_level); +extern void zlog_set_level(zlog_dest_t, int log_level); /* Set logging to the given filename at the specified level. */ -extern int zlog_set_file (const char *filename, int log_level); +extern int zlog_set_file(const char *filename, int log_level); /* Disable file logging. */ -extern int zlog_reset_file (void); +extern int zlog_reset_file(void); /* Rotate log. */ -extern int zlog_rotate (void); +extern int zlog_rotate(void); -const char *lookup_msg (const struct message *mz, int kz, const char *nf); +const char *lookup_msg(const struct message *mz, int kz, const char *nf); /* Safe version of strerror -- never returns NULL. */ extern const char *safe_strerror(int errnum); @@ -107,9 +106,10 @@ extern const char *safe_strerror(int errnum); /* To be called when a fatal signal is caught. */ extern void zlog_signal(int signo, const char *action #ifdef SA_SIGINFO - , siginfo_t *siginfo, void *program_counter + , + siginfo_t *siginfo, void *program_counter #endif - ); + ); /* Log a backtrace. */ extern void zlog_backtrace(int priority); @@ -131,49 +131,51 @@ extern size_t quagga_timestamp(int timestamp_precision /* # subsecond digits */, char *buf, size_t buflen); extern void zlog_hexdump(const void *mem, unsigned int len); -extern const char *zlog_sanitize(char *buf, size_t bufsz, const void *in, size_t inlen); +extern const char *zlog_sanitize(char *buf, size_t bufsz, const void *in, + size_t inlen); -extern int vzlog_test (int priority); +extern int vzlog_test(int priority); /* structure useful for avoiding repeated rendering of the same timestamp */ struct timestamp_control { - size_t len; /* length of rendered timestamp */ - int precision; /* configuration parameter */ - int already_rendered; /* should be initialized to 0 */ - char buf[QUAGGA_TIMESTAMP_LEN]; /* will contain the rendered timestamp */ + size_t len; /* length of rendered timestamp */ + int precision; /* configuration parameter */ + int already_rendered; /* should be initialized to 0 */ + char buf[QUAGGA_TIMESTAMP_LEN]; /* will contain the rendered timestamp + */ }; /* Defines for use in command construction: */ -#define LOG_LEVEL_DESC \ - "System is unusable\n" \ - "Immediate action needed\n" \ - "Critical conditions\n" \ - "Error conditions\n" \ - "Warning conditions\n" \ - "Normal but significant conditions\n" \ - "Informational messages\n" \ - "Debugging messages\n" - -#define LOG_FACILITY_DESC \ - "Kernel\n" \ - "User process\n" \ - "Mail system\n" \ - "System daemons\n" \ - "Authorization system\n" \ - "Syslog itself\n" \ - "Line printer system\n" \ - "USENET news\n" \ - "Unix-to-Unix copy system\n" \ - "Cron/at facility\n" \ - "Local use\n" \ - "Local use\n" \ - "Local use\n" \ - "Local use\n" \ - "Local use\n" \ - "Local use\n" \ - "Local use\n" \ - "Local use\n" +#define LOG_LEVEL_DESC \ + "System is unusable\n" \ + "Immediate action needed\n" \ + "Critical conditions\n" \ + "Error conditions\n" \ + "Warning conditions\n" \ + "Normal but significant conditions\n" \ + "Informational messages\n" \ + "Debugging messages\n" + +#define LOG_FACILITY_DESC \ + "Kernel\n" \ + "User process\n" \ + "Mail system\n" \ + "System daemons\n" \ + "Authorization system\n" \ + "Syslog itself\n" \ + "Line printer system\n" \ + "USENET news\n" \ + "Unix-to-Unix copy system\n" \ + "Cron/at facility\n" \ + "Local use\n" \ + "Local use\n" \ + "Local use\n" \ + "Local use\n" \ + "Local use\n" \ + "Local use\n" \ + "Local use\n" \ + "Local use\n" #endif /* _ZEBRA_LOG_H */ diff --git a/lib/log_int.h b/lib/log_int.h index 7c93381cb..56823fb97 100644 --- a/lib/log_int.h +++ b/lib/log_int.h @@ -24,21 +24,20 @@ #include "log.h" -struct zlog -{ - const char *ident; /* daemon name (first arg to openlog) */ - const char *protoname; - u_short instance; - int maxlvl[ZLOG_NUM_DESTS]; /* maximum priority to send to associated - logging destination */ - int default_lvl; /* maxlvl to use if none is specified */ - FILE *fp; - char *filename; - int facility; /* as per syslog facility */ - int record_priority; /* should messages logged through stdio include the - priority of the message? */ - int syslog_options; /* 2nd arg to openlog */ - int timestamp_precision; /* # of digits of subsecond precision */ +struct zlog { + const char *ident; /* daemon name (first arg to openlog) */ + const char *protoname; + u_short instance; + int maxlvl[ZLOG_NUM_DESTS]; /* maximum priority to send to associated + logging destination */ + int default_lvl; /* maxlvl to use if none is specified */ + FILE *fp; + char *filename; + int facility; /* as per syslog facility */ + int record_priority; /* should messages logged through stdio include the + priority of the message? */ + int syslog_options; /* 2nd arg to openlog */ + int timestamp_precision; /* # of digits of subsecond precision */ }; /* Default logging strucutre. */ @@ -47,10 +46,7 @@ extern struct zlog *zlog_default; extern const char *zlog_priority[]; /* Generic function for zlog. */ -extern void vzlog (int priority, const char *format, va_list args); -extern void zlog (int priority, const char *format, ...) - PRINTF_ATTRIBUTE(2, 3); +extern void vzlog(int priority, const char *format, va_list args); +extern void zlog(int priority, const char *format, ...) PRINTF_ATTRIBUTE(2, 3); #endif /* _ZEBRA_LOG_PRIVATE_H */ - - diff --git a/lib/md5.c b/lib/md5.c index d758de2a2..cce67d7ec 100644 --- a/lib/md5.c +++ b/lib/md5.c @@ -49,29 +49,33 @@ #define H(X, Y, Z) ((X) ^ (Y) ^ (Z)) #define I(X, Y, Z) ((Y) ^ ((X) | (~Z))) -#define ROUND1(a, b, c, d, k, s, i) { \ - (a) = (a) + F((b), (c), (d)) + X[(k)] + T[(i)]; \ - (a) = SHIFT((a), (s)); \ - (a) = (b) + (a); \ -} +#define ROUND1(a, b, c, d, k, s, i) \ + { \ + (a) = (a) + F((b), (c), (d)) + X[(k)] + T[(i)]; \ + (a) = SHIFT((a), (s)); \ + (a) = (b) + (a); \ + } -#define ROUND2(a, b, c, d, k, s, i) { \ - (a) = (a) + G((b), (c), (d)) + X[(k)] + T[(i)]; \ - (a) = SHIFT((a), (s)); \ - (a) = (b) + (a); \ -} +#define ROUND2(a, b, c, d, k, s, i) \ + { \ + (a) = (a) + G((b), (c), (d)) + X[(k)] + T[(i)]; \ + (a) = SHIFT((a), (s)); \ + (a) = (b) + (a); \ + } -#define ROUND3(a, b, c, d, k, s, i) { \ - (a) = (a) + H((b), (c), (d)) + X[(k)] + T[(i)]; \ - (a) = SHIFT((a), (s)); \ - (a) = (b) + (a); \ -} +#define ROUND3(a, b, c, d, k, s, i) \ + { \ + (a) = (a) + H((b), (c), (d)) + X[(k)] + T[(i)]; \ + (a) = SHIFT((a), (s)); \ + (a) = (b) + (a); \ + } -#define ROUND4(a, b, c, d, k, s, i) { \ - (a) = (a) + I((b), (c), (d)) + X[(k)] + T[(i)]; \ - (a) = SHIFT((a), (s)); \ - (a) = (b) + (a); \ -} +#define ROUND4(a, b, c, d, k, s, i) \ + { \ + (a) = (a) + I((b), (c), (d)) + X[(k)] + T[(i)]; \ + (a) = SHIFT((a), (s)); \ + (a) = (b) + (a); \ + } #define Sa 7 #define Sb 12 @@ -100,40 +104,30 @@ /* Integer part of 4294967296 times abs(sin(i)), where i is in radians. */ static const uint32_t T[65] = { - 0, - 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, - 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, - 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, - 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, - - 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, - 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, - 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, - 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, - - 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, - 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, - 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, - 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, - - 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, - 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, - 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, - 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, + 0, 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, + 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, + 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x2441453, + 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, + 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, + 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, }; static const uint8_t md5_paddat[MD5_BUFLEN] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; -static void md5_calc (const uint8_t *, md5_ctxt *); +static void md5_calc(const uint8_t *, md5_ctxt *); void md5_init(md5_ctxt *ctxt) { @@ -143,7 +137,7 @@ void md5_init(md5_ctxt *ctxt) ctxt->md5_stb = MD5_B0; ctxt->md5_stc = MD5_C0; ctxt->md5_std = MD5_D0; - memset (ctxt->md5_buf, 0, sizeof(ctxt->md5_buf)); + memset(ctxt->md5_buf, 0, sizeof(ctxt->md5_buf)); } void md5_loop(md5_ctxt *ctxt, const void *vinput, uint len) @@ -155,17 +149,17 @@ void md5_loop(md5_ctxt *ctxt, const void *vinput, uint len) gap = MD5_BUFLEN - ctxt->md5_i; if (len >= gap) { - memcpy (ctxt->md5_buf + ctxt->md5_i, input, gap); + memcpy(ctxt->md5_buf + ctxt->md5_i, input, gap); md5_calc(ctxt->md5_buf, ctxt); for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN) { md5_calc((input + i), ctxt); } - + ctxt->md5_i = len - i; - memcpy (ctxt->md5_buf, (input + i), ctxt->md5_i); + memcpy(ctxt->md5_buf, (input + i), ctxt->md5_i); } else { - memcpy (ctxt->md5_buf + ctxt->md5_i, input, len); + memcpy(ctxt->md5_buf + ctxt->md5_i, input, len); ctxt->md5_i += len; } } @@ -174,33 +168,32 @@ void md5_pad(md5_ctxt *ctxt) { uint gap; - /* Don't count up padding. Keep md5_n. */ + /* Don't count up padding. Keep md5_n. */ gap = MD5_BUFLEN - ctxt->md5_i; if (gap > 8) { - memcpy (ctxt->md5_buf + ctxt->md5_i, md5_paddat, - gap - sizeof(ctxt->md5_n)); + memcpy(ctxt->md5_buf + ctxt->md5_i, md5_paddat, + gap - sizeof(ctxt->md5_n)); } else { /* including gap == 8 */ - memcpy (ctxt->md5_buf + ctxt->md5_i, md5_paddat, gap); - md5_calc (ctxt->md5_buf, ctxt); - memcpy (ctxt->md5_buf, md5_paddat + gap, - MD5_BUFLEN - sizeof(ctxt->md5_n)); + memcpy(ctxt->md5_buf + ctxt->md5_i, md5_paddat, gap); + md5_calc(ctxt->md5_buf, ctxt); + memcpy(ctxt->md5_buf, md5_paddat + gap, + MD5_BUFLEN - sizeof(ctxt->md5_n)); } - /* 8 byte word */ + /* 8 byte word */ if (BYTE_ORDER == LITTLE_ENDIAN) - memcpy (&ctxt->md5_buf[56], &ctxt->md5_n8[0], 8); - else - { - ctxt->md5_buf[56] = ctxt->md5_n8[7]; - ctxt->md5_buf[57] = ctxt->md5_n8[6]; - ctxt->md5_buf[58] = ctxt->md5_n8[5]; - ctxt->md5_buf[59] = ctxt->md5_n8[4]; - ctxt->md5_buf[60] = ctxt->md5_n8[3]; - ctxt->md5_buf[61] = ctxt->md5_n8[2]; - ctxt->md5_buf[62] = ctxt->md5_n8[1]; - ctxt->md5_buf[63] = ctxt->md5_n8[0]; - } + memcpy(&ctxt->md5_buf[56], &ctxt->md5_n8[0], 8); + else { + ctxt->md5_buf[56] = ctxt->md5_n8[7]; + ctxt->md5_buf[57] = ctxt->md5_n8[6]; + ctxt->md5_buf[58] = ctxt->md5_n8[5]; + ctxt->md5_buf[59] = ctxt->md5_n8[4]; + ctxt->md5_buf[60] = ctxt->md5_n8[3]; + ctxt->md5_buf[61] = ctxt->md5_n8[2]; + ctxt->md5_buf[62] = ctxt->md5_n8[1]; + ctxt->md5_buf[63] = ctxt->md5_n8[0]; + } md5_calc(ctxt->md5_buf, ctxt); } @@ -208,21 +201,28 @@ void md5_result(uint8_t *digest, md5_ctxt *ctxt) { /* 4 byte words */ if (BYTE_ORDER == LITTLE_ENDIAN) - memcpy (digest, &ctxt->md5_st8[0], 16); - else if (BYTE_ORDER == BIG_ENDIAN) - { - digest[ 0] = ctxt->md5_st8[ 3]; digest[ 1] = ctxt->md5_st8[ 2]; - digest[ 2] = ctxt->md5_st8[ 1]; digest[ 3] = ctxt->md5_st8[ 0]; - digest[ 4] = ctxt->md5_st8[ 7]; digest[ 5] = ctxt->md5_st8[ 6]; - digest[ 6] = ctxt->md5_st8[ 5]; digest[ 7] = ctxt->md5_st8[ 4]; - digest[ 8] = ctxt->md5_st8[11]; digest[ 9] = ctxt->md5_st8[10]; - digest[10] = ctxt->md5_st8[ 9]; digest[11] = ctxt->md5_st8[ 8]; - digest[12] = ctxt->md5_st8[15]; digest[13] = ctxt->md5_st8[14]; - digest[14] = ctxt->md5_st8[13]; digest[15] = ctxt->md5_st8[12]; - } + memcpy(digest, &ctxt->md5_st8[0], 16); + else if (BYTE_ORDER == BIG_ENDIAN) { + digest[0] = ctxt->md5_st8[3]; + digest[1] = ctxt->md5_st8[2]; + digest[2] = ctxt->md5_st8[1]; + digest[3] = ctxt->md5_st8[0]; + digest[4] = ctxt->md5_st8[7]; + digest[5] = ctxt->md5_st8[6]; + digest[6] = ctxt->md5_st8[5]; + digest[7] = ctxt->md5_st8[4]; + digest[8] = ctxt->md5_st8[11]; + digest[9] = ctxt->md5_st8[10]; + digest[10] = ctxt->md5_st8[9]; + digest[11] = ctxt->md5_st8[8]; + digest[12] = ctxt->md5_st8[15]; + digest[13] = ctxt->md5_st8[14]; + digest[14] = ctxt->md5_st8[13]; + digest[15] = ctxt->md5_st8[12]; + } } -static void md5_calc(const uint8_t *b64, md5_ctxt * ctxt) +static void md5_calc(const uint8_t *b64, md5_ctxt *ctxt) { uint32_t A = ctxt->md5_sta; uint32_t B = ctxt->md5_stb; @@ -233,65 +233,144 @@ static void md5_calc(const uint8_t *b64, md5_ctxt * ctxt) #elif (BYTE_ORDER == BIG_ENDIAN) uint32_t X[16]; - if (BYTE_ORDER == BIG_ENDIAN) - { - /* 4 byte words */ - /* what a brute force but fast! */ - uint8_t *y = (uint8_t *)X; - y[ 0] = b64[ 3]; y[ 1] = b64[ 2]; y[ 2] = b64[ 1]; y[ 3] = b64[ 0]; - y[ 4] = b64[ 7]; y[ 5] = b64[ 6]; y[ 6] = b64[ 5]; y[ 7] = b64[ 4]; - y[ 8] = b64[11]; y[ 9] = b64[10]; y[10] = b64[ 9]; y[11] = b64[ 8]; - y[12] = b64[15]; y[13] = b64[14]; y[14] = b64[13]; y[15] = b64[12]; - y[16] = b64[19]; y[17] = b64[18]; y[18] = b64[17]; y[19] = b64[16]; - y[20] = b64[23]; y[21] = b64[22]; y[22] = b64[21]; y[23] = b64[20]; - y[24] = b64[27]; y[25] = b64[26]; y[26] = b64[25]; y[27] = b64[24]; - y[28] = b64[31]; y[29] = b64[30]; y[30] = b64[29]; y[31] = b64[28]; - y[32] = b64[35]; y[33] = b64[34]; y[34] = b64[33]; y[35] = b64[32]; - y[36] = b64[39]; y[37] = b64[38]; y[38] = b64[37]; y[39] = b64[36]; - y[40] = b64[43]; y[41] = b64[42]; y[42] = b64[41]; y[43] = b64[40]; - y[44] = b64[47]; y[45] = b64[46]; y[46] = b64[45]; y[47] = b64[44]; - y[48] = b64[51]; y[49] = b64[50]; y[50] = b64[49]; y[51] = b64[48]; - y[52] = b64[55]; y[53] = b64[54]; y[54] = b64[53]; y[55] = b64[52]; - y[56] = b64[59]; y[57] = b64[58]; y[58] = b64[57]; y[59] = b64[56]; - y[60] = b64[63]; y[61] = b64[62]; y[62] = b64[61]; y[63] = b64[60]; - } + if (BYTE_ORDER == BIG_ENDIAN) { + /* 4 byte words */ + /* what a brute force but fast! */ + uint8_t *y = (uint8_t *)X; + y[0] = b64[3]; + y[1] = b64[2]; + y[2] = b64[1]; + y[3] = b64[0]; + y[4] = b64[7]; + y[5] = b64[6]; + y[6] = b64[5]; + y[7] = b64[4]; + y[8] = b64[11]; + y[9] = b64[10]; + y[10] = b64[9]; + y[11] = b64[8]; + y[12] = b64[15]; + y[13] = b64[14]; + y[14] = b64[13]; + y[15] = b64[12]; + y[16] = b64[19]; + y[17] = b64[18]; + y[18] = b64[17]; + y[19] = b64[16]; + y[20] = b64[23]; + y[21] = b64[22]; + y[22] = b64[21]; + y[23] = b64[20]; + y[24] = b64[27]; + y[25] = b64[26]; + y[26] = b64[25]; + y[27] = b64[24]; + y[28] = b64[31]; + y[29] = b64[30]; + y[30] = b64[29]; + y[31] = b64[28]; + y[32] = b64[35]; + y[33] = b64[34]; + y[34] = b64[33]; + y[35] = b64[32]; + y[36] = b64[39]; + y[37] = b64[38]; + y[38] = b64[37]; + y[39] = b64[36]; + y[40] = b64[43]; + y[41] = b64[42]; + y[42] = b64[41]; + y[43] = b64[40]; + y[44] = b64[47]; + y[45] = b64[46]; + y[46] = b64[45]; + y[47] = b64[44]; + y[48] = b64[51]; + y[49] = b64[50]; + y[50] = b64[49]; + y[51] = b64[48]; + y[52] = b64[55]; + y[53] = b64[54]; + y[54] = b64[53]; + y[55] = b64[52]; + y[56] = b64[59]; + y[57] = b64[58]; + y[58] = b64[57]; + y[59] = b64[56]; + y[60] = b64[63]; + y[61] = b64[62]; + y[62] = b64[61]; + y[63] = b64[60]; + } #endif - ROUND1(A, B, C, D, 0, Sa, 1); ROUND1(D, A, B, C, 1, Sb, 2); - ROUND1(C, D, A, B, 2, Sc, 3); ROUND1(B, C, D, A, 3, Sd, 4); - ROUND1(A, B, C, D, 4, Sa, 5); ROUND1(D, A, B, C, 5, Sb, 6); - ROUND1(C, D, A, B, 6, Sc, 7); ROUND1(B, C, D, A, 7, Sd, 8); - ROUND1(A, B, C, D, 8, Sa, 9); ROUND1(D, A, B, C, 9, Sb, 10); - ROUND1(C, D, A, B, 10, Sc, 11); ROUND1(B, C, D, A, 11, Sd, 12); - ROUND1(A, B, C, D, 12, Sa, 13); ROUND1(D, A, B, C, 13, Sb, 14); - ROUND1(C, D, A, B, 14, Sc, 15); ROUND1(B, C, D, A, 15, Sd, 16); - - ROUND2(A, B, C, D, 1, Se, 17); ROUND2(D, A, B, C, 6, Sf, 18); - ROUND2(C, D, A, B, 11, Sg, 19); ROUND2(B, C, D, A, 0, Sh, 20); - ROUND2(A, B, C, D, 5, Se, 21); ROUND2(D, A, B, C, 10, Sf, 22); - ROUND2(C, D, A, B, 15, Sg, 23); ROUND2(B, C, D, A, 4, Sh, 24); - ROUND2(A, B, C, D, 9, Se, 25); ROUND2(D, A, B, C, 14, Sf, 26); - ROUND2(C, D, A, B, 3, Sg, 27); ROUND2(B, C, D, A, 8, Sh, 28); - ROUND2(A, B, C, D, 13, Se, 29); ROUND2(D, A, B, C, 2, Sf, 30); - ROUND2(C, D, A, B, 7, Sg, 31); ROUND2(B, C, D, A, 12, Sh, 32); - - ROUND3(A, B, C, D, 5, Si, 33); ROUND3(D, A, B, C, 8, Sj, 34); - ROUND3(C, D, A, B, 11, Sk, 35); ROUND3(B, C, D, A, 14, Sl, 36); - ROUND3(A, B, C, D, 1, Si, 37); ROUND3(D, A, B, C, 4, Sj, 38); - ROUND3(C, D, A, B, 7, Sk, 39); ROUND3(B, C, D, A, 10, Sl, 40); - ROUND3(A, B, C, D, 13, Si, 41); ROUND3(D, A, B, C, 0, Sj, 42); - ROUND3(C, D, A, B, 3, Sk, 43); ROUND3(B, C, D, A, 6, Sl, 44); - ROUND3(A, B, C, D, 9, Si, 45); ROUND3(D, A, B, C, 12, Sj, 46); - ROUND3(C, D, A, B, 15, Sk, 47); ROUND3(B, C, D, A, 2, Sl, 48); - - ROUND4(A, B, C, D, 0, Sm, 49); ROUND4(D, A, B, C, 7, Sn, 50); - ROUND4(C, D, A, B, 14, So, 51); ROUND4(B, C, D, A, 5, Sp, 52); - ROUND4(A, B, C, D, 12, Sm, 53); ROUND4(D, A, B, C, 3, Sn, 54); - ROUND4(C, D, A, B, 10, So, 55); ROUND4(B, C, D, A, 1, Sp, 56); - ROUND4(A, B, C, D, 8, Sm, 57); ROUND4(D, A, B, C, 15, Sn, 58); - ROUND4(C, D, A, B, 6, So, 59); ROUND4(B, C, D, A, 13, Sp, 60); - ROUND4(A, B, C, D, 4, Sm, 61); ROUND4(D, A, B, C, 11, Sn, 62); - ROUND4(C, D, A, B, 2, So, 63); ROUND4(B, C, D, A, 9, Sp, 64); + ROUND1(A, B, C, D, 0, Sa, 1); + ROUND1(D, A, B, C, 1, Sb, 2); + ROUND1(C, D, A, B, 2, Sc, 3); + ROUND1(B, C, D, A, 3, Sd, 4); + ROUND1(A, B, C, D, 4, Sa, 5); + ROUND1(D, A, B, C, 5, Sb, 6); + ROUND1(C, D, A, B, 6, Sc, 7); + ROUND1(B, C, D, A, 7, Sd, 8); + ROUND1(A, B, C, D, 8, Sa, 9); + ROUND1(D, A, B, C, 9, Sb, 10); + ROUND1(C, D, A, B, 10, Sc, 11); + ROUND1(B, C, D, A, 11, Sd, 12); + ROUND1(A, B, C, D, 12, Sa, 13); + ROUND1(D, A, B, C, 13, Sb, 14); + ROUND1(C, D, A, B, 14, Sc, 15); + ROUND1(B, C, D, A, 15, Sd, 16); + + ROUND2(A, B, C, D, 1, Se, 17); + ROUND2(D, A, B, C, 6, Sf, 18); + ROUND2(C, D, A, B, 11, Sg, 19); + ROUND2(B, C, D, A, 0, Sh, 20); + ROUND2(A, B, C, D, 5, Se, 21); + ROUND2(D, A, B, C, 10, Sf, 22); + ROUND2(C, D, A, B, 15, Sg, 23); + ROUND2(B, C, D, A, 4, Sh, 24); + ROUND2(A, B, C, D, 9, Se, 25); + ROUND2(D, A, B, C, 14, Sf, 26); + ROUND2(C, D, A, B, 3, Sg, 27); + ROUND2(B, C, D, A, 8, Sh, 28); + ROUND2(A, B, C, D, 13, Se, 29); + ROUND2(D, A, B, C, 2, Sf, 30); + ROUND2(C, D, A, B, 7, Sg, 31); + ROUND2(B, C, D, A, 12, Sh, 32); + + ROUND3(A, B, C, D, 5, Si, 33); + ROUND3(D, A, B, C, 8, Sj, 34); + ROUND3(C, D, A, B, 11, Sk, 35); + ROUND3(B, C, D, A, 14, Sl, 36); + ROUND3(A, B, C, D, 1, Si, 37); + ROUND3(D, A, B, C, 4, Sj, 38); + ROUND3(C, D, A, B, 7, Sk, 39); + ROUND3(B, C, D, A, 10, Sl, 40); + ROUND3(A, B, C, D, 13, Si, 41); + ROUND3(D, A, B, C, 0, Sj, 42); + ROUND3(C, D, A, B, 3, Sk, 43); + ROUND3(B, C, D, A, 6, Sl, 44); + ROUND3(A, B, C, D, 9, Si, 45); + ROUND3(D, A, B, C, 12, Sj, 46); + ROUND3(C, D, A, B, 15, Sk, 47); + ROUND3(B, C, D, A, 2, Sl, 48); + + ROUND4(A, B, C, D, 0, Sm, 49); + ROUND4(D, A, B, C, 7, Sn, 50); + ROUND4(C, D, A, B, 14, So, 51); + ROUND4(B, C, D, A, 5, Sp, 52); + ROUND4(A, B, C, D, 12, Sm, 53); + ROUND4(D, A, B, C, 3, Sn, 54); + ROUND4(C, D, A, B, 10, So, 55); + ROUND4(B, C, D, A, 1, Sp, 56); + ROUND4(A, B, C, D, 8, Sm, 57); + ROUND4(D, A, B, C, 15, Sn, 58); + ROUND4(C, D, A, B, 6, So, 59); + ROUND4(B, C, D, A, 13, Sp, 60); + ROUND4(A, B, C, D, 4, Sm, 61); + ROUND4(D, A, B, C, 11, Sn, 62); + ROUND4(C, D, A, B, 2, So, 63); + ROUND4(B, C, D, A, 9, Sp, 64); ctxt->md5_sta += A; ctxt->md5_stb += B; @@ -300,74 +379,73 @@ static void md5_calc(const uint8_t *b64, md5_ctxt * ctxt) } /* From RFC 2104 */ -void -hmac_md5(text, text_len, key, key_len, digest) -unsigned char* text; /* pointer to data stream */ -int text_len; /* length of data stream */ -unsigned char* key; /* pointer to authentication key */ -int key_len; /* length of authentication key */ -uint8_t* digest; /* caller digest to be filled in */ +void hmac_md5(text, text_len, key, key_len, + digest) unsigned char *text; /* pointer to data stream */ +int text_len; /* length of data stream */ +unsigned char *key; /* pointer to authentication key */ +int key_len; /* length of authentication key */ +uint8_t *digest; /* caller digest to be filled in */ { - MD5_CTX context; - unsigned char k_ipad[65]; /* inner padding - - * key XORd with ipad - */ - unsigned char k_opad[65]; /* outer padding - - * key XORd with opad - */ - unsigned char tk[16]; - int i; - /* if key is longer than 64 bytes reset it to key=MD5(key) */ - if (key_len > 64) { - - MD5_CTX tctx; - - MD5Init(&tctx); - MD5Update(&tctx, key, key_len); - MD5Final(tk, &tctx); - - key = tk; - key_len = 16; - } - - /* - * the HMAC_MD5 transform looks like: - * - * MD5(K XOR opad, MD5(K XOR ipad, text)) - * - * where K is an n byte key - * ipad is the byte 0x36 repeated 64 times - * opad is the byte 0x5c repeated 64 times - * and text is the data being protected - */ - - /* start out by storing key in pads */ - bzero( k_ipad, sizeof k_ipad); - bzero( k_opad, sizeof k_opad); - bcopy( key, k_ipad, key_len); - bcopy( key, k_opad, key_len); - - /* XOR key with ipad and opad values */ - for (i=0; i<64; i++) { - k_ipad[i] ^= 0x36; - k_opad[i] ^= 0x5c; - } - /* - * perform inner MD5 - */ - MD5Init(&context); /* init context for 1st - * pass */ - MD5Update(&context, k_ipad, 64); /* start with inner pad */ - MD5Update(&context, text, text_len); /* then text of datagram */ - MD5Final((uint8_t *)digest, &context); /* finish up 1st pass */ - /* - * perform outer MD5 - */ - MD5Init(&context); /* init context for 2nd - * pass */ - MD5Update(&context, k_opad, 64); /* start with outer pad */ - MD5Update(&context, digest, 16); /* then results of 1st - * hash */ - MD5Final((uint8_t *)digest, &context); /* finish up 2nd pass */ + MD5_CTX context; + unsigned char k_ipad[65]; /* inner padding - + * key XORd with ipad + */ + unsigned char k_opad[65]; /* outer padding - + * key XORd with opad + */ + unsigned char tk[16]; + int i; + /* if key is longer than 64 bytes reset it to key=MD5(key) */ + if (key_len > 64) { + + MD5_CTX tctx; + + MD5Init(&tctx); + MD5Update(&tctx, key, key_len); + MD5Final(tk, &tctx); + + key = tk; + key_len = 16; + } + + /* + * the HMAC_MD5 transform looks like: + * + * MD5(K XOR opad, MD5(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected + */ + + /* start out by storing key in pads */ + bzero(k_ipad, sizeof k_ipad); + bzero(k_opad, sizeof k_opad); + bcopy(key, k_ipad, key_len); + bcopy(key, k_opad, key_len); + + /* XOR key with ipad and opad values */ + for (i = 0; i < 64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + /* + * perform inner MD5 + */ + MD5Init(&context); /* init context for 1st + * pass */ + MD5Update(&context, k_ipad, 64); /* start with inner pad */ + MD5Update(&context, text, text_len); /* then text of datagram */ + MD5Final((uint8_t *)digest, &context); /* finish up 1st pass */ + /* + * perform outer MD5 + */ + MD5Init(&context); /* init context for 2nd + * pass */ + MD5Update(&context, k_opad, 64); /* start with outer pad */ + MD5Update(&context, digest, 16); /* then results of 1st + * hash */ + MD5Final((uint8_t *)digest, &context); /* finish up 2nd pass */ } diff --git a/lib/md5.h b/lib/md5.h index 4e5ffbd9e..adc92d670 100644 --- a/lib/md5.h +++ b/lib/md5.h @@ -46,8 +46,8 @@ typedef struct { union { - uint32_t md5_state32[4]; - uint8_t md5_state8[16]; + uint32_t md5_state32[4]; + uint8_t md5_state8[16]; } md5_st; #define md5_sta md5_st.md5_state32[0] @@ -57,33 +57,33 @@ typedef struct { #define md5_st8 md5_st.md5_state8 union { - uint64_t md5_count64; - uint8_t md5_count8[8]; + uint64_t md5_count64; + uint8_t md5_count8[8]; } md5_count; #define md5_n md5_count.md5_count64 #define md5_n8 md5_count.md5_count8 - uint md5_i; - uint8_t md5_buf[MD5_BUFLEN]; + uint md5_i; + uint8_t md5_buf[MD5_BUFLEN]; } md5_ctxt; -extern void md5_init (md5_ctxt *); -extern void md5_loop (md5_ctxt *, const void *, u_int); -extern void md5_pad (md5_ctxt *); -extern void md5_result (uint8_t *, md5_ctxt *); +extern void md5_init(md5_ctxt *); +extern void md5_loop(md5_ctxt *, const void *, u_int); +extern void md5_pad(md5_ctxt *); +extern void md5_result(uint8_t *, md5_ctxt *); /* compatibility */ #define MD5_CTX md5_ctxt #define MD5Init(x) md5_init((x)) #define MD5Update(x, y, z) md5_loop((x), (y), (z)) -#define MD5Final(x, y) \ -do { \ - md5_pad((y)); \ - md5_result((x), (y)); \ -} while (0) +#define MD5Final(x, y) \ + do { \ + md5_pad((y)); \ + md5_result((x), (y)); \ + } while (0) /* From RFC 2104 */ -void hmac_md5(unsigned char* text, int text_len, unsigned char* key, - int key_len, uint8_t *digest); +void hmac_md5(unsigned char *text, int text_len, unsigned char *key, + int key_len, uint8_t *digest); #endif /* ! _LIBZEBRA_MD5_H_*/ diff --git a/lib/memory.c b/lib/memory.c index c6207adb9..0ccc20400 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -35,9 +35,11 @@ static inline void mt_count_alloc(struct memtype *mt, size_t size) oldsize = atomic_load_explicit(&mt->size, memory_order_relaxed); if (oldsize == 0) - oldsize = atomic_exchange_explicit(&mt->size, size, memory_order_relaxed); + oldsize = atomic_exchange_explicit(&mt->size, size, + memory_order_relaxed); if (oldsize != 0 && oldsize != size && oldsize != SIZE_VAR) - atomic_store_explicit(&mt->size, SIZE_VAR, memory_order_relaxed); + atomic_store_explicit(&mt->size, SIZE_VAR, + memory_order_relaxed); } static inline void mt_count_free(struct memtype *mt) @@ -111,23 +113,24 @@ static int qmem_exit_walker(void *arg, struct memgroup *mg, struct memtype *mt) struct exit_dump_args *eda = arg; if (!mt) { - fprintf(stderr, "%s: showing active allocations in " - "memory group %s\n", - eda->prefix, mg->name); + fprintf(stderr, + "%s: showing active allocations in " + "memory group %s\n", + eda->prefix, mg->name); } else if (mt->n_alloc) { char size[32]; eda->error++; snprintf(size, sizeof(size), "%10zu", mt->size); fprintf(stderr, "%s: memstats: %-30s: %6zu * %s\n", - eda->prefix, mt->name, mt->n_alloc, - mt->size == SIZE_VAR ? "(variably sized)" : size); + eda->prefix, mt->name, mt->n_alloc, + mt->size == SIZE_VAR ? "(variably sized)" : size); } return 0; } void log_memstats_stderr(const char *prefix) { - struct exit_dump_args eda = { .prefix = prefix, .error = 0 }; + struct exit_dump_args eda = {.prefix = prefix, .error = 0}; qmem_walk(qmem_exit_walker, &eda); } diff --git a/lib/memory.h b/lib/memory.h index 9e8803a8b..d5facad58 100644 --- a/lib/memory.h +++ b/lib/memory.h @@ -37,25 +37,25 @@ struct memgroup { }; #if defined(__clang__) -# if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5) +#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5) # define _RET_NONNULL , returns_nonnull -# endif +#endif # define _CONSTRUCTOR(x) constructor(x) #elif defined(__GNUC__) -# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9) +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9) # define _RET_NONNULL , returns_nonnull -# endif -# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) +#endif +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) # define _CONSTRUCTOR(x) constructor(x) # define _DESTRUCTOR(x) destructor(x) # define _ALLOC_SIZE(x) alloc_size(x) -# endif +#endif #endif #ifdef __sun /* Solaris doesn't do constructor priorities due to linker restrictions */ -# undef _CONSTRUCTOR -# undef _DESTRUCTOR +#undef _CONSTRUCTOR +#undef _DESTRUCTOR #endif #ifndef _RET_NONNULL @@ -96,81 +96,91 @@ struct memgroup { * but MGROUP_* aren't. */ -#define DECLARE_MGROUP(name) \ - extern struct memgroup _mg_##name; -#define DEFINE_MGROUP(mname, desc) \ - struct memgroup _mg_##mname \ - __attribute__ ((section (".data.mgroups"))) = { \ - .name = desc, \ - .types = NULL, .next = NULL, .insert = NULL, .ref = NULL, \ - }; \ - static void _mginit_##mname (void) \ - __attribute__ ((_CONSTRUCTOR (1000))); \ - static void _mginit_##mname (void) \ - { extern struct memgroup **mg_insert; \ - _mg_##mname.ref = mg_insert; \ - *mg_insert = &_mg_##mname; \ - mg_insert = &_mg_##mname.next; } \ - static void _mgfini_##mname (void) \ - __attribute__ ((_DESTRUCTOR (1000))); \ - static void _mgfini_##mname (void) \ - { if (_mg_##mname.next) \ - _mg_##mname.next->ref = _mg_##mname.ref; \ - *_mg_##mname.ref = _mg_##mname.next; } - - -#define DECLARE_MTYPE(name) \ - extern struct memtype _mt_##name; \ - static struct memtype * const MTYPE_ ## name = &_mt_##name; - -#define DEFINE_MTYPE_ATTR(group, mname, attr, desc) \ - attr struct memtype _mt_##mname \ - __attribute__ ((section (".data.mtypes"))) = { \ - .name = desc, \ - .next = NULL, .n_alloc = 0, .size = 0, .ref = NULL, \ - }; \ - static void _mtinit_##mname (void) \ - __attribute__ ((_CONSTRUCTOR (1001))); \ - static void _mtinit_##mname (void) \ - { if (_mg_##group.insert == NULL) \ - _mg_##group.insert = &_mg_##group.types; \ - _mt_##mname.ref = _mg_##group.insert; \ - *_mg_##group.insert = &_mt_##mname; \ - _mg_##group.insert = &_mt_##mname.next; } \ - static void _mtfini_##mname (void) \ - __attribute__ ((_DESTRUCTOR (1001))); \ - static void _mtfini_##mname (void) \ - { if (_mt_##mname.next) \ - _mt_##mname.next->ref = _mt_##mname.ref; \ - *_mt_##mname.ref = _mt_##mname.next; } - -#define DEFINE_MTYPE(group, name, desc) \ - DEFINE_MTYPE_ATTR(group, name, , desc) -#define DEFINE_MTYPE_STATIC(group, name, desc) \ - DEFINE_MTYPE_ATTR(group, name, static, desc) \ - static struct memtype * const MTYPE_ ## name = &_mt_##name; +#define DECLARE_MGROUP(name) extern struct memgroup _mg_##name; +#define DEFINE_MGROUP(mname, desc) \ + struct memgroup _mg_##mname \ + __attribute__((section(".data.mgroups"))) = { \ + .name = desc, \ + .types = NULL, \ + .next = NULL, \ + .insert = NULL, \ + .ref = NULL, \ + }; \ + static void _mginit_##mname(void) __attribute__((_CONSTRUCTOR(1000))); \ + static void _mginit_##mname(void) \ + { \ + extern struct memgroup **mg_insert; \ + _mg_##mname.ref = mg_insert; \ + *mg_insert = &_mg_##mname; \ + mg_insert = &_mg_##mname.next; \ + } \ + static void _mgfini_##mname(void) __attribute__((_DESTRUCTOR(1000))); \ + static void _mgfini_##mname(void) \ + { \ + if (_mg_##mname.next) \ + _mg_##mname.next->ref = _mg_##mname.ref; \ + *_mg_##mname.ref = _mg_##mname.next; \ + } + + +#define DECLARE_MTYPE(name) \ + extern struct memtype _mt_##name; \ + static struct memtype *const MTYPE_##name = &_mt_##name; + +#define DEFINE_MTYPE_ATTR(group, mname, attr, desc) \ + attr struct memtype _mt_##mname \ + __attribute__((section(".data.mtypes"))) = { \ + .name = desc, \ + .next = NULL, \ + .n_alloc = 0, \ + .size = 0, \ + .ref = NULL, \ + }; \ + static void _mtinit_##mname(void) __attribute__((_CONSTRUCTOR(1001))); \ + static void _mtinit_##mname(void) \ + { \ + if (_mg_##group.insert == NULL) \ + _mg_##group.insert = &_mg_##group.types; \ + _mt_##mname.ref = _mg_##group.insert; \ + *_mg_##group.insert = &_mt_##mname; \ + _mg_##group.insert = &_mt_##mname.next; \ + } \ + static void _mtfini_##mname(void) __attribute__((_DESTRUCTOR(1001))); \ + static void _mtfini_##mname(void) \ + { \ + if (_mt_##mname.next) \ + _mt_##mname.next->ref = _mt_##mname.ref; \ + *_mt_##mname.ref = _mt_##mname.next; \ + } + +#define DEFINE_MTYPE(group, name, desc) DEFINE_MTYPE_ATTR(group, name, , desc) +#define DEFINE_MTYPE_STATIC(group, name, desc) \ + DEFINE_MTYPE_ATTR(group, name, static, desc) \ + static struct memtype *const MTYPE_##name = &_mt_##name; DECLARE_MGROUP(LIB) DECLARE_MTYPE(TMP) extern void *qmalloc(struct memtype *mt, size_t size) - __attribute__ ((malloc, _ALLOC_SIZE(2), nonnull (1) _RET_NONNULL)); + __attribute__((malloc, _ALLOC_SIZE(2), nonnull(1) _RET_NONNULL)); extern void *qcalloc(struct memtype *mt, size_t size) - __attribute__ ((malloc, _ALLOC_SIZE(2), nonnull (1) _RET_NONNULL)); + __attribute__((malloc, _ALLOC_SIZE(2), nonnull(1) _RET_NONNULL)); extern void *qrealloc(struct memtype *mt, void *ptr, size_t size) - __attribute__ ((_ALLOC_SIZE(3), nonnull (1) _RET_NONNULL)); -extern void *qstrdup (struct memtype *mt, const char *str) - __attribute__ ((malloc, nonnull (1) _RET_NONNULL)); -extern void qfree(struct memtype *mt, void *ptr) - __attribute__ ((nonnull (1))); + __attribute__((_ALLOC_SIZE(3), nonnull(1) _RET_NONNULL)); +extern void *qstrdup(struct memtype *mt, const char *str) + __attribute__((malloc, nonnull(1) _RET_NONNULL)); +extern void qfree(struct memtype *mt, void *ptr) __attribute__((nonnull(1))); #define XMALLOC(mtype, size) qmalloc(mtype, size) #define XCALLOC(mtype, size) qcalloc(mtype, size) #define XREALLOC(mtype, ptr, size) qrealloc(mtype, ptr, size) #define XSTRDUP(mtype, str) qstrdup(mtype, str) -#define XFREE(mtype, ptr) do { qfree(mtype, ptr); ptr = NULL; } \ - while (0) +#define XFREE(mtype, ptr) \ + do { \ + qfree(mtype, ptr); \ + ptr = NULL; \ + } while (0) static inline size_t mtype_stats_alloc(struct memtype *mt) { diff --git a/lib/memory_vty.c b/lib/memory_vty.c index f65952e8a..972914bf2 100644 --- a/lib/memory_vty.c +++ b/lib/memory_vty.c @@ -38,33 +38,32 @@ #include "command.h" #ifdef HAVE_MALLINFO -static int -show_memory_mallinfo (struct vty *vty) +static int show_memory_mallinfo(struct vty *vty) { - struct mallinfo minfo = mallinfo(); - char buf[MTYPE_MEMSTR_LEN]; - - vty_out (vty, "System allocator statistics:\n"); - vty_out (vty, " Total heap allocated: %s\n", - mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.arena)); - vty_out (vty, " Holding block headers: %s\n", - mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.hblkhd)); - vty_out (vty, " Used small blocks: %s\n", - mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.usmblks)); - vty_out (vty, " Used ordinary blocks: %s\n", - mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.uordblks)); - vty_out (vty, " Free small blocks: %s\n", - mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.fsmblks)); - vty_out (vty, " Free ordinary blocks: %s\n", - mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.fordblks)); - vty_out (vty, " Ordinary blocks: %ld\n", - (unsigned long)minfo.ordblks); - vty_out (vty, " Small blocks: %ld\n", - (unsigned long)minfo.smblks); - vty_out (vty, " Holding blocks: %ld\n", - (unsigned long)minfo.hblks); - vty_out (vty,"(see system documentation for 'mallinfo' for meaning)\n"); - return 1; + struct mallinfo minfo = mallinfo(); + char buf[MTYPE_MEMSTR_LEN]; + + vty_out(vty, "System allocator statistics:\n"); + vty_out(vty, " Total heap allocated: %s\n", + mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.arena)); + vty_out(vty, " Holding block headers: %s\n", + mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.hblkhd)); + vty_out(vty, " Used small blocks: %s\n", + mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.usmblks)); + vty_out(vty, " Used ordinary blocks: %s\n", + mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.uordblks)); + vty_out(vty, " Free small blocks: %s\n", + mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.fsmblks)); + vty_out(vty, " Free ordinary blocks: %s\n", + mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.fordblks)); + vty_out(vty, " Ordinary blocks: %ld\n", + (unsigned long)minfo.ordblks); + vty_out(vty, " Small blocks: %ld\n", + (unsigned long)minfo.smblks); + vty_out(vty, " Holding blocks: %ld\n", + (unsigned long)minfo.hblks); + vty_out(vty, "(see system documentation for 'mallinfo' for meaning)\n"); + return 1; } #endif /* HAVE_MALLINFO */ @@ -72,14 +71,17 @@ static int qmem_walker(void *arg, struct memgroup *mg, struct memtype *mt) { struct vty *vty = arg; if (!mt) - vty_out (vty, "--- qmem %s ---\n", mg->name); + vty_out(vty, "--- qmem %s ---\n", mg->name); else { if (mt->n_alloc != 0) { char size[32]; snprintf(size, sizeof(size), "%6zu", mt->size); - vty_out (vty, "%-30s: %10zu %s\n", - mt->name, mt->n_alloc, - mt->size == 0 ? "" : mt->size == SIZE_VAR ? "(variably sized)" : size); + vty_out(vty, "%-30s: %10zu %s\n", mt->name, + mt->n_alloc, + mt->size == 0 ? "" + : mt->size == SIZE_VAR + ? "(variably sized)" + : size); } } return 0; @@ -93,11 +95,11 @@ DEFUN (show_memory, "Memory statistics\n") { #ifdef HAVE_MALLINFO - show_memory_mallinfo (vty); + show_memory_mallinfo(vty); #endif /* HAVE_MALLINFO */ - qmem_walk(qmem_walker, vty); - return CMD_SUCCESS; + qmem_walk(qmem_walker, vty); + return CMD_SUCCESS; } DEFUN (show_modules, @@ -106,47 +108,44 @@ DEFUN (show_modules, "Show running system information\n" "Loaded modules\n") { - struct frrmod_runtime *plug = frrmod_list; + struct frrmod_runtime *plug = frrmod_list; - vty_out (vty, "%-12s %-25s %s\n\n", - "Module Name", "Version", "Description"); - while (plug) - { - const struct frrmod_info *i = plug->info; + vty_out(vty, "%-12s %-25s %s\n\n", "Module Name", "Version", + "Description"); + while (plug) { + const struct frrmod_info *i = plug->info; - vty_out (vty, "%-12s %-25s %s\n", i->name, i->version,i->description); - if (plug->dl_handle) - { + vty_out(vty, "%-12s %-25s %s\n", i->name, i->version, + i->description); + if (plug->dl_handle) { #ifdef HAVE_DLINFO_ORIGIN - char origin[MAXPATHLEN] = ""; - dlinfo (plug->dl_handle, RTLD_DI_ORIGIN, &origin); -# ifdef HAVE_DLINFO_LINKMAP - const char *name; - struct link_map *lm = NULL; - dlinfo (plug->dl_handle, RTLD_DI_LINKMAP, &lm); - if (lm) - { - name = strrchr(lm->l_name, '/'); - name = name ? name + 1 : lm->l_name; - vty_out (vty, "\tfrom: %s/%s\n", origin, name); - } -# else - vty_out (vty, "\tfrom: %s \n", origin, plug->load_name); -# endif + char origin[MAXPATHLEN] = ""; + dlinfo(plug->dl_handle, RTLD_DI_ORIGIN, &origin); +#ifdef HAVE_DLINFO_LINKMAP + const char *name; + struct link_map *lm = NULL; + dlinfo(plug->dl_handle, RTLD_DI_LINKMAP, &lm); + if (lm) { + name = strrchr(lm->l_name, '/'); + name = name ? name + 1 : lm->l_name; + vty_out(vty, "\tfrom: %s/%s\n", origin, name); + } #else - vty_out (vty, "\tfrom: %s\n", plug->load_name); + vty_out(vty, "\tfrom: %s \n", origin, plug->load_name); #endif - } - plug = plug->next; - } - return CMD_SUCCESS; +#else + vty_out(vty, "\tfrom: %s\n", plug->load_name); +#endif + } + plug = plug->next; + } + return CMD_SUCCESS; } -void -memory_init (void) +void memory_init(void) { - install_element (VIEW_NODE, &show_memory_cmd); - install_element (VIEW_NODE, &show_modules_cmd); + install_element(VIEW_NODE, &show_memory_cmd); + install_element(VIEW_NODE, &show_modules_cmd); } /* Stats querying from users */ @@ -157,44 +156,39 @@ memory_init (void) * The pointer returned may be NULL (indicating an error) * or point to the given buffer, or point to static storage. */ -const char * -mtype_memstr (char *buf, size_t len, unsigned long bytes) +const char *mtype_memstr(char *buf, size_t len, unsigned long bytes) { - unsigned int m, k; - - /* easy cases */ - if (!bytes) - return "0 bytes"; - if (bytes == 1) - return "1 byte"; - - /* - * When we pass the 2gb barrier mallinfo() can no longer report - * correct data so it just does something odd... - * Reporting like Terrabytes of data. Which makes users... - * edgy.. yes edgy that's the term for it. - * So let's just give up gracefully - */ - if (bytes > 0x7fffffff) - return "> 2GB"; - - m = bytes >> 20; - k = bytes >> 10; - - if (m > 10) - { - if (bytes & (1 << 19)) - m++; - snprintf (buf, len, "%d MiB", m); - } - else if (k > 10) - { - if (bytes & (1 << 9)) - k++; - snprintf (buf, len, "%d KiB", k); - } - else - snprintf (buf, len, "%ld bytes", bytes); - - return buf; + unsigned int m, k; + + /* easy cases */ + if (!bytes) + return "0 bytes"; + if (bytes == 1) + return "1 byte"; + + /* + * When we pass the 2gb barrier mallinfo() can no longer report + * correct data so it just does something odd... + * Reporting like Terrabytes of data. Which makes users... + * edgy.. yes edgy that's the term for it. + * So let's just give up gracefully + */ + if (bytes > 0x7fffffff) + return "> 2GB"; + + m = bytes >> 20; + k = bytes >> 10; + + if (m > 10) { + if (bytes & (1 << 19)) + m++; + snprintf(buf, len, "%d MiB", m); + } else if (k > 10) { + if (bytes & (1 << 9)) + k++; + snprintf(buf, len, "%d KiB", k); + } else + snprintf(buf, len, "%ld bytes", bytes); + + return buf; } diff --git a/lib/memory_vty.h b/lib/memory_vty.h index a47c5d51b..b66c3b6d6 100644 --- a/lib/memory_vty.h +++ b/lib/memory_vty.h @@ -23,9 +23,9 @@ #include "memory.h" -extern void memory_init (void); +extern void memory_init(void); /* Human friendly string for given byte count */ #define MTYPE_MEMSTR_LEN 20 -extern const char *mtype_memstr (char *, size_t, unsigned long); +extern const char *mtype_memstr(char *, size_t, unsigned long); #endif /* _ZEBRA_MEMORY_VTY_H */ diff --git a/lib/module.c b/lib/module.c index 140fd87b9..beef79109 100644 --- a/lib/module.c +++ b/lib/module.c @@ -68,8 +68,8 @@ void frrmod_init(struct frrmod_runtime *modinfo) execname = modinfo->info->name; } -struct frrmod_runtime *frrmod_load(const char *spec, - const char *dir, char *err, size_t err_len) +struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, char *err, + size_t err_len) { void *handle = NULL; char name[PATH_MAX], fullpath[PATH_MAX], *args; @@ -83,13 +83,13 @@ struct frrmod_runtime *frrmod_load(const char *spec, if (!strchr(name, '/')) { if (!handle && execname) { - snprintf(fullpath, sizeof(fullpath), "%s/%s_%s.so", - dir, execname, name); + snprintf(fullpath, sizeof(fullpath), "%s/%s_%s.so", dir, + execname, name); handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL); } if (!handle) { - snprintf(fullpath, sizeof(fullpath), "%s/%s.so", - dir, name); + snprintf(fullpath, sizeof(fullpath), "%s/%s.so", dir, + name); handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL); } } @@ -100,8 +100,8 @@ struct frrmod_runtime *frrmod_load(const char *spec, if (!handle) { if (err) snprintf(err, err_len, - "loading module \"%s\" failed: %s", - name, dlerror()); + "loading module \"%s\" failed: %s", name, + dlerror()); return NULL; } @@ -110,8 +110,8 @@ struct frrmod_runtime *frrmod_load(const char *spec, dlclose(handle); if (err) snprintf(err, err_len, - "\"%s\" is not an FRR module: %s", - name, dlerror()); + "\"%s\" is not an FRR module: %s", name, + dlerror()); return NULL; } rtinfo = *rtinfop; @@ -124,9 +124,8 @@ struct frrmod_runtime *frrmod_load(const char *spec, if (rtinfo->finished_loading) { dlclose(handle); if (err) - snprintf(err, err_len, - "module \"%s\" already loaded", - name); + snprintf(err, err_len, "module \"%s\" already loaded", + name); goto out_fail; } @@ -134,8 +133,7 @@ struct frrmod_runtime *frrmod_load(const char *spec, dlclose(handle); if (err) snprintf(err, err_len, - "module \"%s\" initialisation failed", - name); + "module \"%s\" initialisation failed", name); goto out_fail; } diff --git a/lib/module.h b/lib/module.h index 01819f91e..e66e5cd65 100644 --- a/lib/module.h +++ b/lib/module.h @@ -27,9 +27,9 @@ #include #if !defined(__GNUC__) -# error module code needs GCC visibility extensions +#error module code needs GCC visibility extensions #elif __GNUC__ < 4 -# error module code needs GCC visibility extensions +#error module code needs GCC visibility extensions #else # define DSO_PUBLIC __attribute__ ((visibility ("default"))) # define DSO_SELF __attribute__ ((visibility ("protected"))) @@ -82,20 +82,20 @@ union _frrmod_runtime_u { extern union _frrmod_runtime_u _frrmod_this_module; #define THIS_MODULE (&_frrmod_this_module.r) -#define FRR_COREMOD_SETUP(...) \ - static const struct frrmod_info _frrmod_info = { __VA_ARGS__ }; \ - DSO_LOCAL union _frrmod_runtime_u _frrmod_this_module = { \ - .r.info = &_frrmod_info, \ +#define FRR_COREMOD_SETUP(...) \ + static const struct frrmod_info _frrmod_info = {__VA_ARGS__}; \ + DSO_LOCAL union _frrmod_runtime_u _frrmod_this_module = { \ + .r.info = &_frrmod_info, \ }; -#define FRR_MODULE_SETUP(...) \ - FRR_COREMOD_SETUP(__VA_ARGS__) \ +#define FRR_MODULE_SETUP(...) \ + FRR_COREMOD_SETUP(__VA_ARGS__) \ DSO_SELF struct frrmod_runtime *frr_module = &_frrmod_this_module.r; extern struct frrmod_runtime *frrmod_list; extern void frrmod_init(struct frrmod_runtime *modinfo); -extern struct frrmod_runtime *frrmod_load(const char *spec, - const char *dir, char *err, size_t err_len); +extern struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, + char *err, size_t err_len); #if 0 /* not implemented yet */ extern void frrmod_unload(struct frrmod_runtime *module); diff --git a/lib/monotime.h b/lib/monotime.h index ad44bf511..7bd338649 100644 --- a/lib/monotime.h +++ b/lib/monotime.h @@ -23,28 +23,30 @@ #ifndef TIMESPEC_TO_TIMEVAL /* should be in sys/time.h on BSD & Linux libcs */ -#define TIMESPEC_TO_TIMEVAL(tv, ts) do { \ - (tv)->tv_sec = (ts)->tv_sec; \ - (tv)->tv_usec = (ts)->tv_nsec / 1000; \ - } while (0) +#define TIMESPEC_TO_TIMEVAL(tv, ts) \ + do { \ + (tv)->tv_sec = (ts)->tv_sec; \ + (tv)->tv_usec = (ts)->tv_nsec / 1000; \ + } while (0) #endif #ifndef TIMEVAL_TO_TIMESPEC /* should be in sys/time.h on BSD & Linux libcs */ -#define TIMEVAL_TO_TIMESPEC(tv, ts) do { \ - (ts)->tv_sec = (tv)->tv_sec; \ - (ts)->tv_nsec = (tv)->tv_usec * 1000; \ - } while (0) +#define TIMEVAL_TO_TIMESPEC(tv, ts) \ + do { \ + (ts)->tv_sec = (tv)->tv_sec; \ + (ts)->tv_nsec = (tv)->tv_usec * 1000; \ + } while (0) #endif static inline time_t monotime(struct timeval *tvo) { - struct timespec ts; + struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - if (tvo) { - TIMESPEC_TO_TIMEVAL(tvo, &ts); - } - return ts.tv_sec; + clock_gettime(CLOCK_MONOTONIC, &ts); + if (tvo) { + TIMESPEC_TO_TIMEVAL(tvo, &ts); + } + return ts.tv_sec; } /* the following two return microseconds, not time_t! @@ -53,25 +55,25 @@ static inline time_t monotime(struct timeval *tvo) * code more readable */ static inline int64_t monotime_since(const struct timeval *ref, - struct timeval *out) + struct timeval *out) { - struct timeval tv; - monotime(&tv); - timersub(&tv, ref, &tv); - if (out) - *out = tv; - return (int64_t)tv.tv_sec * 1000000LL + tv.tv_usec; + struct timeval tv; + monotime(&tv); + timersub(&tv, ref, &tv); + if (out) + *out = tv; + return (int64_t)tv.tv_sec * 1000000LL + tv.tv_usec; } static inline int64_t monotime_until(const struct timeval *ref, - struct timeval *out) + struct timeval *out) { - struct timeval tv; - monotime(&tv); - timersub(ref, &tv, &tv); - if (out) - *out = tv; - return (int64_t)tv.tv_sec * 1000000LL + tv.tv_usec; + struct timeval tv; + monotime(&tv); + timersub(ref, &tv, &tv); + if (out) + *out = tv; + return (int64_t)tv.tv_sec * 1000000LL + tv.tv_usec; } #endif /* _FRR_MONOTIME_H */ diff --git a/lib/mpls.h b/lib/mpls.h index 20315df7d..025770d47 100644 --- a/lib/mpls.h +++ b/lib/mpls.h @@ -44,11 +44,12 @@ #define MPLS_DEFAULT_MIN_SRGB_LABEL 16000 #define MPLS_DEFAULT_MAX_SRGB_LABEL 23999 -#define IS_MPLS_RESERVED_LABEL(label) \ - (label >= MPLS_MIN_RESERVED_LABEL && label <= MPLS_MAX_RESERVED_LABEL) +#define IS_MPLS_RESERVED_LABEL(label) \ + (label >= MPLS_MIN_RESERVED_LABEL && label <= MPLS_MAX_RESERVED_LABEL) -#define IS_MPLS_UNRESERVED_LABEL(label) \ - (label >= MPLS_MIN_UNRESERVED_LABEL && label <= MPLS_MAX_UNRESERVED_LABEL) +#define IS_MPLS_UNRESERVED_LABEL(label) \ + (label >= MPLS_MIN_UNRESERVED_LABEL \ + && label <= MPLS_MAX_UNRESERVED_LABEL) /* Definitions for a MPLS label stack entry (RFC 3032). This encodes the * label, EXP, BOS and TTL fields. @@ -64,14 +65,11 @@ typedef unsigned int mpls_lse_t; #define MPLS_LS_TTL_MASK 0x000000FF #define MPLS_LS_TTL_SHIFT 0 -#define MPLS_LABEL_VALUE(lse) \ - ((lse & MPLS_LS_LABEL_MASK) >> MPLS_LS_LABEL_SHIFT) -#define MPLS_LABEL_EXP(lse) \ - ((lse & MPLS_LS_EXP_MASK) >> MPLS_LS_EXP_SHIFT) -#define MPLS_LABEL_BOS(lse) \ - ((lse & MPLS_LS_S_MASK) >> MPLS_LS_S_SHIFT) -#define MPLS_LABEL_TTL(lse) \ - ((lse & MPLS_LS_TTL_MASK) >> MPLS_LS_TTL_SHIFT) +#define MPLS_LABEL_VALUE(lse) \ + ((lse & MPLS_LS_LABEL_MASK) >> MPLS_LS_LABEL_SHIFT) +#define MPLS_LABEL_EXP(lse) ((lse & MPLS_LS_EXP_MASK) >> MPLS_LS_EXP_SHIFT) +#define MPLS_LABEL_BOS(lse) ((lse & MPLS_LS_S_MASK) >> MPLS_LS_S_SHIFT) +#define MPLS_LABEL_TTL(lse) ((lse & MPLS_LS_TTL_MASK) >> MPLS_LS_TTL_SHIFT) #define IS_MPLS_LABEL_BOS(ls) (MPLS_LABEL_BOS(ls) == 1) @@ -89,12 +87,11 @@ typedef unsigned int mpls_label_t; #define MPLS_INVALID_LABEL 0xFFFDFFFF /* LSP types. */ -enum lsp_types_t -{ - ZEBRA_LSP_NONE = 0, /* No LSP. */ - ZEBRA_LSP_STATIC = 1, /* Static LSP. */ - ZEBRA_LSP_LDP = 2, /* LDP LSP. */ - ZEBRA_LSP_BGP = 3 /* BGP LSP. */ +enum lsp_types_t { + ZEBRA_LSP_NONE = 0, /* No LSP. */ + ZEBRA_LSP_STATIC = 1, /* Static LSP. */ + ZEBRA_LSP_LDP = 2, /* LDP LSP. */ + ZEBRA_LSP_BGP = 3 /* BGP LSP. */ }; /* Functions for basic label operations. */ @@ -102,33 +99,31 @@ enum lsp_types_t /* Encode a label stack entry from fields; convert to network byte-order as * the Netlink interface expects MPLS labels to be in this format. */ -static inline mpls_lse_t -mpls_lse_encode (mpls_label_t label, u_int32_t ttl, - u_int32_t exp, u_int32_t bos) +static inline mpls_lse_t mpls_lse_encode(mpls_label_t label, u_int32_t ttl, + u_int32_t exp, u_int32_t bos) { - mpls_lse_t lse; - lse = htonl ((label << MPLS_LS_LABEL_SHIFT) | - (exp << MPLS_LS_EXP_SHIFT) | - (bos ? (1 << MPLS_LS_S_SHIFT) : 0) | - (ttl << MPLS_LS_TTL_SHIFT)); - return lse; + mpls_lse_t lse; + lse = htonl((label << MPLS_LS_LABEL_SHIFT) | (exp << MPLS_LS_EXP_SHIFT) + | (bos ? (1 << MPLS_LS_S_SHIFT) : 0) + | (ttl << MPLS_LS_TTL_SHIFT)); + return lse; } /* Extract the fields from a label stack entry after converting to host-byte * order. This is expected to be called only for messages received over the * Netlink interface. */ -static inline void -mpls_lse_decode (mpls_lse_t lse, mpls_label_t *label, - u_int32_t *ttl, u_int32_t *exp, u_int32_t *bos) +static inline void mpls_lse_decode(mpls_lse_t lse, mpls_label_t *label, + u_int32_t *ttl, u_int32_t *exp, + u_int32_t *bos) { - mpls_lse_t local_lse; + mpls_lse_t local_lse; - local_lse = ntohl (lse); - *label = MPLS_LABEL_VALUE(local_lse); - *exp = MPLS_LABEL_EXP(local_lse); - *bos = MPLS_LABEL_BOS(local_lse); - *ttl = MPLS_LABEL_TTL(local_lse); + local_lse = ntohl(lse); + *label = MPLS_LABEL_VALUE(local_lse); + *exp = MPLS_LABEL_EXP(local_lse); + *bos = MPLS_LABEL_BOS(local_lse); + *ttl = MPLS_LABEL_TTL(local_lse); } /* Invalid label index value (when used with BGP Prefix-SID). Should @@ -136,43 +131,41 @@ mpls_lse_decode (mpls_lse_t lse, mpls_label_t *label, */ #define MPLS_INVALID_LABEL_INDEX 0xFFFFFFFF - /* Printable string for labels (with consideration for reserved values). */ -static inline char * -label2str (mpls_label_t label, char *buf, size_t len) +static inline char *label2str(mpls_label_t label, char *buf, size_t len) { - switch(label) { - case MPLS_V4_EXP_NULL_LABEL: - strlcpy(buf, "IPv4 Explicit Null", len); - return(buf); - case MPLS_RA_LABEL: - strlcpy(buf, "Router Alert", len); - return(buf); - case MPLS_V6_EXP_NULL_LABEL: - strlcpy(buf, "IPv6 Explict Null", len); - return(buf); - case MPLS_IMP_NULL_LABEL: - strlcpy(buf, "implicit-null", len); - return(buf); - case MPLS_ENTROPY_LABEL_INDICATOR: - strlcpy(buf, "Entropy Label Indicator", len); - return(buf); - case MPLS_GAL_LABEL: - strlcpy(buf, "Generic Associated Channel", len); - return(buf); - case MPLS_OAM_ALERT_LABEL: - strlcpy(buf, "OAM Alert", len); - return(buf); - case MPLS_EXTENSION_LABEL: - strlcpy(buf, "Extension", len); - return(buf); - default: - if (label < 16) - snprintf(buf, len, "Reserved (%u)", label); - else - snprintf(buf, len, "%u", label); - return(buf); - } + switch (label) { + case MPLS_V4_EXP_NULL_LABEL: + strlcpy(buf, "IPv4 Explicit Null", len); + return (buf); + case MPLS_RA_LABEL: + strlcpy(buf, "Router Alert", len); + return (buf); + case MPLS_V6_EXP_NULL_LABEL: + strlcpy(buf, "IPv6 Explict Null", len); + return (buf); + case MPLS_IMP_NULL_LABEL: + strlcpy(buf, "implicit-null", len); + return (buf); + case MPLS_ENTROPY_LABEL_INDICATOR: + strlcpy(buf, "Entropy Label Indicator", len); + return (buf); + case MPLS_GAL_LABEL: + strlcpy(buf, "Generic Associated Channel", len); + return (buf); + case MPLS_OAM_ALERT_LABEL: + strlcpy(buf, "OAM Alert", len); + return (buf); + case MPLS_EXTENSION_LABEL: + strlcpy(buf, "Extension", len); + return (buf); + default: + if (label < 16) + snprintf(buf, len, "Reserved (%u)", label); + else + snprintf(buf, len, "%u", label); + return (buf); + } } /* constants used by ldpd */ @@ -180,7 +173,7 @@ label2str (mpls_label_t label, char *buf, size_t len) #define MPLS_LABEL_RTALERT 1 /* Router Alert Label */ #define MPLS_LABEL_IPV6NULL 2 /* IPv6 Explicit NULL Label */ #define MPLS_LABEL_IMPLNULL 3 /* Implicit NULL Label */ -/* MPLS_LABEL_RESERVED 4-15 */ /* Values 4-15 are reserved */ + /* MPLS_LABEL_RESERVED 4-15 */ /* Values 4-15 are reserved */ #define MPLS_LABEL_RESERVED_MAX 15 #define MPLS_LABEL_MAX ((1 << 20) - 1) diff --git a/lib/network.c b/lib/network.c index 3d2c63c89..3f72b7141 100644 --- a/lib/network.c +++ b/lib/network.c @@ -24,108 +24,97 @@ #include "network.h" /* Read nbytes from fd and store into ptr. */ -int -readn (int fd, u_char *ptr, int nbytes) +int readn(int fd, u_char *ptr, int nbytes) { - int nleft; - int nread; + int nleft; + int nread; - nleft = nbytes; + nleft = nbytes; - while (nleft > 0) - { - nread = read (fd, ptr, nleft); + while (nleft > 0) { + nread = read(fd, ptr, nleft); - if (nread < 0) - return (nread); - else - if (nread == 0) - break; + if (nread < 0) + return (nread); + else if (nread == 0) + break; - nleft -= nread; - ptr += nread; - } + nleft -= nread; + ptr += nread; + } - return nbytes - nleft; -} + return nbytes - nleft; +} /* Write nbytes from ptr to fd. */ -int -writen(int fd, const u_char *ptr, int nbytes) +int writen(int fd, const u_char *ptr, int nbytes) { - int nleft; - int nwritten; + int nleft; + int nwritten; - nleft = nbytes; + nleft = nbytes; - while (nleft > 0) - { - nwritten = write(fd, ptr, nleft); + while (nleft > 0) { + nwritten = write(fd, ptr, nleft); - if (nwritten < 0) - { - if (!ERRNO_IO_RETRY(errno)) - return nwritten; - } - if (nwritten == 0) - return (nwritten); + if (nwritten < 0) { + if (!ERRNO_IO_RETRY(errno)) + return nwritten; + } + if (nwritten == 0) + return (nwritten); - nleft -= nwritten; - ptr += nwritten; - } - return nbytes - nleft; + nleft -= nwritten; + ptr += nwritten; + } + return nbytes - nleft; } -int -set_nonblocking(int fd) +int set_nonblocking(int fd) { - int flags; - - /* According to the Single UNIX Spec, the return value for F_GETFL should - never be negative. */ - if ((flags = fcntl(fd, F_GETFL)) < 0) - { - zlog_warn("fcntl(F_GETFL) failed for fd %d: %s", - fd, safe_strerror(errno)); - return -1; - } - if (fcntl(fd, F_SETFL, (flags | O_NONBLOCK)) < 0) - { - zlog_warn("fcntl failed setting fd %d non-blocking: %s", - fd, safe_strerror(errno)); - return -1; - } - return 0; + int flags; + + /* According to the Single UNIX Spec, the return value for F_GETFL + should + never be negative. */ + if ((flags = fcntl(fd, F_GETFL)) < 0) { + zlog_warn("fcntl(F_GETFL) failed for fd %d: %s", fd, + safe_strerror(errno)); + return -1; + } + if (fcntl(fd, F_SETFL, (flags | O_NONBLOCK)) < 0) { + zlog_warn("fcntl failed setting fd %d non-blocking: %s", fd, + safe_strerror(errno)); + return -1; + } + return 0; } -int -set_cloexec(int fd) +int set_cloexec(int fd) { - int flags; - flags = fcntl(fd, F_GETFD, 0); - if (flags == -1) - return -1; - - flags |= FD_CLOEXEC; - if (fcntl(fd, F_SETFD, flags) == -1) - return -1; - return 0; + int flags; + flags = fcntl(fd, F_GETFD, 0); + if (flags == -1) + return -1; + + flags |= FD_CLOEXEC; + if (fcntl(fd, F_SETFD, flags) == -1) + return -1; + return 0; } -float -htonf (float host) +float htonf(float host) { - u_int32_t lu1, lu2; - float convert; + u_int32_t lu1, lu2; + float convert; - memcpy (&lu1, &host, sizeof (u_int32_t)); - lu2 = htonl (lu1); - memcpy (&convert, &lu2, sizeof (u_int32_t)); - return convert; + memcpy(&lu1, &host, sizeof(u_int32_t)); + lu2 = htonl(lu1); + memcpy(&convert, &lu2, sizeof(u_int32_t)); + return convert; } -float -ntohf (float net) +float ntohf(float net) { - return htonf (net); + return htonf(net); } diff --git a/lib/network.h b/lib/network.h index a6b8ed1e1..4faf992bc 100644 --- a/lib/network.h +++ b/lib/network.h @@ -25,8 +25,8 @@ /* Both readn and writen are deprecated and will be removed. They are not suitable for use with non-blocking file descriptors. */ -extern int readn (int, u_char *, int); -extern int writen (int, const u_char *, int); +extern int readn(int, u_char *, int); +extern int writen(int, const u_char *, int); /* Set the file descriptor to use non-blocking I/O. Returns 0 for success, -1 on error. */ @@ -35,10 +35,10 @@ extern int set_nonblocking(int fd); extern int set_cloexec(int fd); /* Does the I/O error indicate that the operation should be retried later? */ -#define ERRNO_IO_RETRY(EN) \ +#define ERRNO_IO_RETRY(EN) \ (((EN) == EAGAIN) || ((EN) == EWOULDBLOCK) || ((EN) == EINTR)) -extern float htonf (float); -extern float ntohf (float); +extern float htonf(float); +extern float ntohf(float); #endif /* _ZEBRA_NETWORK_H */ diff --git a/lib/nexthop.c b/lib/nexthop.c index e9ffea0a0..9b0c2d73f 100644 --- a/lib/nexthop.c +++ b/lib/nexthop.c @@ -32,216 +32,201 @@ #include "nexthop.h" #include "mpls.h" -DEFINE_MTYPE_STATIC(LIB, NEXTHOP, "Nexthop") -DEFINE_MTYPE_STATIC(LIB, NH_LABEL, "Nexthop label") +DEFINE_MTYPE_STATIC(LIB, NEXTHOP, "Nexthop") +DEFINE_MTYPE_STATIC(LIB, NH_LABEL, "Nexthop label") /* check if nexthops are same, non-recursive */ -int -nexthop_same_no_recurse (struct nexthop *next1, struct nexthop *next2) +int nexthop_same_no_recurse(struct nexthop *next1, struct nexthop *next2) { - if (next1->type != next2->type) - return 0; - - switch (next1->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4)) - return 0; - if (next1->ifindex && (next1->ifindex != next2->ifindex)) - return 0; - break; - case NEXTHOP_TYPE_IFINDEX: - if (next1->ifindex != next2->ifindex) - return 0; - break; - case NEXTHOP_TYPE_IPV6: - if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6)) - return 0; - break; - case NEXTHOP_TYPE_IPV6_IFINDEX: - if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6)) - return 0; - if (next1->ifindex != next2->ifindex) - return 0; - break; - default: - /* do nothing */ - break; - } - return 1; + if (next1->type != next2->type) + return 0; + + switch (next1->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + if (!IPV4_ADDR_SAME(&next1->gate.ipv4, &next2->gate.ipv4)) + return 0; + if (next1->ifindex && (next1->ifindex != next2->ifindex)) + return 0; + break; + case NEXTHOP_TYPE_IFINDEX: + if (next1->ifindex != next2->ifindex) + return 0; + break; + case NEXTHOP_TYPE_IPV6: + if (!IPV6_ADDR_SAME(&next1->gate.ipv6, &next2->gate.ipv6)) + return 0; + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + if (!IPV6_ADDR_SAME(&next1->gate.ipv6, &next2->gate.ipv6)) + return 0; + if (next1->ifindex != next2->ifindex) + return 0; + break; + default: + /* do nothing */ + break; + } + return 1; } /* * nexthop_type_to_str */ -const char * -nexthop_type_to_str (enum nexthop_types_t nh_type) +const char *nexthop_type_to_str(enum nexthop_types_t nh_type) { - static const char *desc[] = { - "none", - "Directly connected", - "IPv4 nexthop", - "IPv4 nexthop with ifindex", - "IPv6 nexthop", - "IPv6 nexthop with ifindex", - "Null0 nexthop", - }; - - return desc[nh_type]; + static const char *desc[] = { + "none", "Directly connected", + "IPv4 nexthop", "IPv4 nexthop with ifindex", + "IPv6 nexthop", "IPv6 nexthop with ifindex", + "Null0 nexthop", + }; + + return desc[nh_type]; } /* * Check if the labels match for the 2 nexthops specified. */ -int -nexthop_labels_match (struct nexthop *nh1, struct nexthop *nh2) +int nexthop_labels_match(struct nexthop *nh1, struct nexthop *nh2) { - struct nexthop_label *nhl1, *nhl2; + struct nexthop_label *nhl1, *nhl2; - nhl1 = nh1->nh_label; - nhl2 = nh2->nh_label; - if ((nhl1 && !nhl2) || (!nhl1 && nhl2)) - return 0; + nhl1 = nh1->nh_label; + nhl2 = nh2->nh_label; + if ((nhl1 && !nhl2) || (!nhl1 && nhl2)) + return 0; - if (nhl1->num_labels != nhl2->num_labels) - return 0; + if (nhl1->num_labels != nhl2->num_labels) + return 0; - if (memcmp (nhl1->label, nhl2->label, nhl1->num_labels)) - return 0; + if (memcmp(nhl1->label, nhl2->label, nhl1->num_labels)) + return 0; - return 1; + return 1; } -struct nexthop * -nexthop_new (void) +struct nexthop *nexthop_new(void) { - return XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); + return XCALLOC(MTYPE_NEXTHOP, sizeof(struct nexthop)); } /* Add nexthop to the end of a nexthop list. */ -void -nexthop_add (struct nexthop **target, struct nexthop *nexthop) +void nexthop_add(struct nexthop **target, struct nexthop *nexthop) { - struct nexthop *last; - - for (last = *target; last && last->next; last = last->next) - ; - if (last) - last->next = nexthop; - else - *target = nexthop; - nexthop->prev = last; + struct nexthop *last; + + for (last = *target; last && last->next; last = last->next) + ; + if (last) + last->next = nexthop; + else + *target = nexthop; + nexthop->prev = last; } -void -copy_nexthops (struct nexthop **tnh, struct nexthop *nh, struct nexthop *rparent) +void copy_nexthops(struct nexthop **tnh, struct nexthop *nh, + struct nexthop *rparent) { - struct nexthop *nexthop; - struct nexthop *nh1; - - for (nh1 = nh; nh1; nh1 = nh1->next) - { - nexthop = nexthop_new(); - nexthop->ifindex = nh->ifindex; - nexthop->type = nh->type; - nexthop->flags = nh->flags; - memcpy(&nexthop->gate, &nh->gate, sizeof(nh->gate)); - memcpy(&nexthop->src, &nh->src, sizeof(nh->src)); - memcpy(&nexthop->rmap_src, &nh->rmap_src, sizeof(nh->rmap_src)); - nexthop->rparent = rparent; - if (nh->nh_label) - nexthop_add_labels (nexthop, nh->nh_label_type, - nh->nh_label->num_labels, &nh->nh_label->label[0]); - nexthop_add(tnh, nexthop); - - if (CHECK_FLAG(nh1->flags, NEXTHOP_FLAG_RECURSIVE)) - copy_nexthops(&nexthop->resolved, nh1->resolved, nexthop); - } + struct nexthop *nexthop; + struct nexthop *nh1; + + for (nh1 = nh; nh1; nh1 = nh1->next) { + nexthop = nexthop_new(); + nexthop->ifindex = nh->ifindex; + nexthop->type = nh->type; + nexthop->flags = nh->flags; + memcpy(&nexthop->gate, &nh->gate, sizeof(nh->gate)); + memcpy(&nexthop->src, &nh->src, sizeof(nh->src)); + memcpy(&nexthop->rmap_src, &nh->rmap_src, sizeof(nh->rmap_src)); + nexthop->rparent = rparent; + if (nh->nh_label) + nexthop_add_labels(nexthop, nh->nh_label_type, + nh->nh_label->num_labels, + &nh->nh_label->label[0]); + nexthop_add(tnh, nexthop); + + if (CHECK_FLAG(nh1->flags, NEXTHOP_FLAG_RECURSIVE)) + copy_nexthops(&nexthop->resolved, nh1->resolved, + nexthop); + } } /* Free nexthop. */ -void -nexthop_free (struct nexthop *nexthop) +void nexthop_free(struct nexthop *nexthop) { - nexthop_del_labels (nexthop); - if (nexthop->resolved) - nexthops_free(nexthop->resolved); - XFREE (MTYPE_NEXTHOP, nexthop); + nexthop_del_labels(nexthop); + if (nexthop->resolved) + nexthops_free(nexthop->resolved); + XFREE(MTYPE_NEXTHOP, nexthop); } /* Frees a list of nexthops */ -void -nexthops_free (struct nexthop *nexthop) +void nexthops_free(struct nexthop *nexthop) { - struct nexthop *nh, *next; + struct nexthop *nh, *next; - for (nh = nexthop; nh; nh = next) - { - next = nh->next; - nexthop_free (nh); - } + for (nh = nexthop; nh; nh = next) { + next = nh->next; + nexthop_free(nh); + } } /* Update nexthop with label information. */ -void -nexthop_add_labels (struct nexthop *nexthop, enum lsp_types_t type, - u_int8_t num_labels, mpls_label_t *label) +void nexthop_add_labels(struct nexthop *nexthop, enum lsp_types_t type, + u_int8_t num_labels, mpls_label_t *label) { - struct nexthop_label *nh_label; - int i; - - nexthop->nh_label_type = type; - nh_label = XCALLOC (MTYPE_NH_LABEL, sizeof (struct nexthop_label) + - num_labels * sizeof (mpls_label_t)); - nh_label->num_labels = num_labels; - for (i = 0; i < num_labels; i++) - nh_label->label[i] = *(label + i); - nexthop->nh_label = nh_label; + struct nexthop_label *nh_label; + int i; + + nexthop->nh_label_type = type; + nh_label = XCALLOC(MTYPE_NH_LABEL, + sizeof(struct nexthop_label) + + num_labels * sizeof(mpls_label_t)); + nh_label->num_labels = num_labels; + for (i = 0; i < num_labels; i++) + nh_label->label[i] = *(label + i); + nexthop->nh_label = nh_label; } /* Free label information of nexthop, if present. */ -void -nexthop_del_labels (struct nexthop *nexthop) +void nexthop_del_labels(struct nexthop *nexthop) { - if (nexthop->nh_label) - { - XFREE (MTYPE_NH_LABEL, nexthop->nh_label); - nexthop->nh_label_type = ZEBRA_LSP_NONE; - } + if (nexthop->nh_label) { + XFREE(MTYPE_NH_LABEL, nexthop->nh_label); + nexthop->nh_label_type = ZEBRA_LSP_NONE; + } } -const char * -nexthop2str (struct nexthop *nexthop, char *str, int size) +const char *nexthop2str(struct nexthop *nexthop, char *str, int size) { - switch (nexthop->type) - { - case NEXTHOP_TYPE_IFINDEX: - snprintf (str, size, "if %u", nexthop->ifindex); - break; - case NEXTHOP_TYPE_IPV4: - snprintf (str, size, "%s", inet_ntoa (nexthop->gate.ipv4)); - break; - case NEXTHOP_TYPE_IPV4_IFINDEX: - snprintf (str, size, "%s if %u", - inet_ntoa (nexthop->gate.ipv4), nexthop->ifindex); - break; - case NEXTHOP_TYPE_IPV6: - snprintf (str, size, "%s", inet6_ntoa (nexthop->gate.ipv6)); - break; - case NEXTHOP_TYPE_IPV6_IFINDEX: - snprintf (str, size, "%s if %u", - inet6_ntoa (nexthop->gate.ipv6), nexthop->ifindex); - break; - case NEXTHOP_TYPE_BLACKHOLE: - snprintf (str, size, "blackhole"); - break; - default: - snprintf (str, size, "unknown"); - break; - } - - return str; + switch (nexthop->type) { + case NEXTHOP_TYPE_IFINDEX: + snprintf(str, size, "if %u", nexthop->ifindex); + break; + case NEXTHOP_TYPE_IPV4: + snprintf(str, size, "%s", inet_ntoa(nexthop->gate.ipv4)); + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + snprintf(str, size, "%s if %u", inet_ntoa(nexthop->gate.ipv4), + nexthop->ifindex); + break; + case NEXTHOP_TYPE_IPV6: + snprintf(str, size, "%s", inet6_ntoa(nexthop->gate.ipv6)); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + snprintf(str, size, "%s if %u", inet6_ntoa(nexthop->gate.ipv6), + nexthop->ifindex); + break; + case NEXTHOP_TYPE_BLACKHOLE: + snprintf(str, size, "blackhole"); + break; + default: + snprintf(str, size, "unknown"); + break; + } + + return str; } /* @@ -259,29 +244,27 @@ nexthop2str (struct nexthop *nexthop, char *str, int size) * left branch is 'resolved' and right branch is 'next': * https://en.wikipedia.org/wiki/Tree_traversal#/media/File:Sorted_binary_tree_preorder.svg */ -struct nexthop * -nexthop_next(struct nexthop *nexthop) +struct nexthop *nexthop_next(struct nexthop *nexthop) { - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - return nexthop->resolved; + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + return nexthop->resolved; - if (nexthop->next) - return nexthop->next; + if (nexthop->next) + return nexthop->next; - for (struct nexthop *par = nexthop->rparent; par; par = par->rparent) - if (par->next) - return par->next; + for (struct nexthop *par = nexthop->rparent; par; par = par->rparent) + if (par->next) + return par->next; - return NULL; + return NULL; } -unsigned int -nexthop_level(struct nexthop *nexthop) +unsigned int nexthop_level(struct nexthop *nexthop) { - unsigned int rv = 0; + unsigned int rv = 0; - for (struct nexthop *par = nexthop->rparent; par; par = par->rparent) - rv++; + for (struct nexthop *par = nexthop->rparent; par; par = par->rparent) + rv++; - return rv; + return rv; } diff --git a/lib/nexthop.h b/lib/nexthop.h index e9d937f94..e7804379f 100644 --- a/lib/nexthop.h +++ b/lib/nexthop.h @@ -30,40 +30,37 @@ #define NEXTHOP_STRLEN (INET6_ADDRSTRLEN + 30) union g_addr { - struct in_addr ipv4; - struct in6_addr ipv6; + struct in_addr ipv4; + struct in6_addr ipv6; }; -enum nexthop_types_t -{ - NEXTHOP_TYPE_IFINDEX = 1, /* Directly connected. */ - NEXTHOP_TYPE_IPV4, /* IPv4 nexthop. */ - NEXTHOP_TYPE_IPV4_IFINDEX, /* IPv4 nexthop with ifindex. */ - NEXTHOP_TYPE_IPV6, /* IPv6 nexthop. */ - NEXTHOP_TYPE_IPV6_IFINDEX, /* IPv6 nexthop with ifindex. */ - NEXTHOP_TYPE_BLACKHOLE, /* Null0 nexthop. */ +enum nexthop_types_t { + NEXTHOP_TYPE_IFINDEX = 1, /* Directly connected. */ + NEXTHOP_TYPE_IPV4, /* IPv4 nexthop. */ + NEXTHOP_TYPE_IPV4_IFINDEX, /* IPv4 nexthop with ifindex. */ + NEXTHOP_TYPE_IPV6, /* IPv6 nexthop. */ + NEXTHOP_TYPE_IPV6_IFINDEX, /* IPv6 nexthop with ifindex. */ + NEXTHOP_TYPE_BLACKHOLE, /* Null0 nexthop. */ }; /* Nexthop label structure. */ -struct nexthop_label -{ - u_int8_t num_labels; - u_int8_t reserved[3]; - mpls_label_t label[0]; /* 1 or more labels. */ +struct nexthop_label { + u_int8_t num_labels; + u_int8_t reserved[3]; + mpls_label_t label[0]; /* 1 or more labels. */ }; /* Nexthop structure. */ -struct nexthop -{ - struct nexthop *next; - struct nexthop *prev; +struct nexthop { + struct nexthop *next; + struct nexthop *prev; - /* Interface index. */ - ifindex_t ifindex; + /* Interface index. */ + ifindex_t ifindex; - enum nexthop_types_t type; + enum nexthop_types_t type; - u_char flags; + u_char flags; #define NEXTHOP_FLAG_ACTIVE (1 << 0) /* This nexthop is alive. */ #define NEXTHOP_FLAG_FIB (1 << 1) /* FIB nexthop. */ #define NEXTHOP_FLAG_RECURSIVE (1 << 2) /* Recursive nexthop. */ @@ -71,26 +68,26 @@ struct nexthop #define NEXTHOP_FLAG_MATCHED (1 << 4) /* Already matched vs a nexthop */ #define NEXTHOP_FLAG_FILTERED (1 << 5) /* rmap filtered, used by static only */ - /* Nexthop address */ - union g_addr gate; - union g_addr src; - union g_addr rmap_src; /* Src is set via routemap */ - - /* Nexthops obtained by recursive resolution. - * - * If the nexthop struct needs to be resolved recursively, - * NEXTHOP_FLAG_RECURSIVE will be set in flags and the nexthops - * obtained by recursive resolution will be added to `resolved'. - */ - struct nexthop *resolved; - /* Recursive parent */ - struct nexthop *rparent; - - /* Type of label(s), if any */ - enum lsp_types_t nh_label_type; - - /* Label(s) associated with this nexthop. */ - struct nexthop_label *nh_label; + /* Nexthop address */ + union g_addr gate; + union g_addr src; + union g_addr rmap_src; /* Src is set via routemap */ + + /* Nexthops obtained by recursive resolution. + * + * If the nexthop struct needs to be resolved recursively, + * NEXTHOP_FLAG_RECURSIVE will be set in flags and the nexthops + * obtained by recursive resolution will be added to `resolved'. + */ + struct nexthop *resolved; + /* Recursive parent */ + struct nexthop *rparent; + + /* Type of label(s), if any */ + enum lsp_types_t nh_label_type; + + /* Label(s) associated with this nexthop. */ + struct nexthop_label *nh_label; }; /* The following for loop allows to iterate over the nexthop @@ -101,37 +98,41 @@ struct nexthop * nexthop: The pointer to the current nexthop, either in the * top-level chain or in a resolved chain. */ -#define ALL_NEXTHOPS(head, nexthop) \ - (nexthop) = (head); (nexthop); (nexthop) = nexthop_next(nexthop) +#define ALL_NEXTHOPS(head, nexthop) \ + (nexthop) = (head); \ + (nexthop); \ + (nexthop) = nexthop_next(nexthop) extern int zebra_rnh_ip_default_route; extern int zebra_rnh_ipv6_default_route; -static inline int -nh_resolve_via_default(int family) +static inline int nh_resolve_via_default(int family) { - if (((family == AF_INET) && zebra_rnh_ip_default_route) || - ((family == AF_INET6) && zebra_rnh_ipv6_default_route)) - return 1; - else - return 0; + if (((family == AF_INET) && zebra_rnh_ip_default_route) + || ((family == AF_INET6) && zebra_rnh_ipv6_default_route)) + return 1; + else + return 0; } -struct nexthop *nexthop_new (void); -void nexthop_add (struct nexthop **target, struct nexthop *nexthop); +struct nexthop *nexthop_new(void); +void nexthop_add(struct nexthop **target, struct nexthop *nexthop); -void copy_nexthops (struct nexthop **tnh, struct nexthop *nh, struct nexthop *rparent); -void nexthop_free (struct nexthop *nexthop); -void nexthops_free (struct nexthop *nexthop); +void copy_nexthops(struct nexthop **tnh, struct nexthop *nh, + struct nexthop *rparent); +void nexthop_free(struct nexthop *nexthop); +void nexthops_free(struct nexthop *nexthop); -void nexthop_add_labels (struct nexthop *, enum lsp_types_t, u_int8_t, mpls_label_t *); -void nexthop_del_labels (struct nexthop *); +void nexthop_add_labels(struct nexthop *, enum lsp_types_t, u_int8_t, + mpls_label_t *); +void nexthop_del_labels(struct nexthop *); -extern const char *nexthop_type_to_str (enum nexthop_types_t nh_type); -extern int nexthop_same_no_recurse (struct nexthop *next1, struct nexthop *next2); -extern int nexthop_labels_match (struct nexthop *nh1, struct nexthop *nh2); +extern const char *nexthop_type_to_str(enum nexthop_types_t nh_type); +extern int nexthop_same_no_recurse(struct nexthop *next1, + struct nexthop *next2); +extern int nexthop_labels_match(struct nexthop *nh1, struct nexthop *nh2); -extern const char * nexthop2str (struct nexthop *nexthop, char *str, int size); +extern const char *nexthop2str(struct nexthop *nexthop, char *str, int size); extern struct nexthop *nexthop_next(struct nexthop *nexthop); extern unsigned int nexthop_level(struct nexthop *nexthop); #endif /*_LIB_NEXTHOP_H */ diff --git a/lib/ns.c b/lib/ns.c index 583fe95b7..5e03a43e2 100644 --- a/lib/ns.c +++ b/lib/ns.c @@ -22,7 +22,7 @@ #include #ifdef HAVE_NETNS -#undef _GNU_SOURCE +#undef _GNU_SOURCE #define _GNU_SOURCE #include @@ -36,15 +36,15 @@ #include "command.h" #include "vty.h" -DEFINE_MTYPE_STATIC(LIB, NS, "Logical-Router") -DEFINE_MTYPE_STATIC(LIB, NS_NAME, "Logical-Router Name") +DEFINE_MTYPE_STATIC(LIB, NS, "Logical-Router") +DEFINE_MTYPE_STATIC(LIB, NS_NAME, "Logical-Router Name") -static __inline int ns_compare (const struct ns *, const struct ns *); -static struct ns *ns_lookup (ns_id_t); +static __inline int ns_compare(const struct ns *, const struct ns *); +static struct ns *ns_lookup(ns_id_t); -RB_GENERATE (ns_head, ns, entry, ns_compare) +RB_GENERATE(ns_head, ns, entry, ns_compare) -struct ns_head ns_tree = RB_INITIALIZER (&ns_tree); +struct ns_head ns_tree = RB_INITIALIZER(&ns_tree); #ifndef CLONE_NEWNET #define CLONE_NEWNET 0x40000000 /* New network namespace (lo, device, names sockets, etc) */ @@ -54,10 +54,10 @@ struct ns_head ns_tree = RB_INITIALIZER (&ns_tree); static inline int setns(int fd, int nstype) { #ifdef __NR_setns - return syscall(__NR_setns, fd, nstype); + return syscall(__NR_setns, fd, nstype); #else - errno = ENOSYS; - return -1; + errno = ENOSYS; + return -1; #endif } #endif /* HAVE_SETNS */ @@ -67,7 +67,7 @@ static inline int setns(int fd, int nstype) #define NS_DEFAULT_NAME "/proc/self/ns/net" static int have_netns_enabled = -1; -#else /* !HAVE_NETNS */ +#else /* !HAVE_NETNS */ #define NS_DEFAULT_NAME "Default-logical-router" @@ -76,105 +76,100 @@ static int have_netns_enabled = -1; static int have_netns(void) { #ifdef HAVE_NETNS - if (have_netns_enabled < 0) - { - int fd = open (NS_DEFAULT_NAME, O_RDONLY); - - if (fd < 0) - have_netns_enabled = 0; - else - { - have_netns_enabled = 1; - close(fd); - } - } - return have_netns_enabled; + if (have_netns_enabled < 0) { + int fd = open(NS_DEFAULT_NAME, O_RDONLY); + + if (fd < 0) + have_netns_enabled = 0; + else { + have_netns_enabled = 1; + close(fd); + } + } + return have_netns_enabled; #else - return 0; + return 0; #endif } /* Holding NS hooks */ -struct ns_master -{ - int (*ns_new_hook) (ns_id_t, void **); - int (*ns_delete_hook) (ns_id_t, void **); - int (*ns_enable_hook) (ns_id_t, void **); - int (*ns_disable_hook) (ns_id_t, void **); -} ns_master = {0,}; - -static int ns_is_enabled (struct ns *ns); -static int ns_enable (struct ns *ns); -static void ns_disable (struct ns *ns); - -static __inline int -ns_compare(const struct ns *a, const struct ns *b) +struct ns_master { + int (*ns_new_hook)(ns_id_t, void **); + int (*ns_delete_hook)(ns_id_t, void **); + int (*ns_enable_hook)(ns_id_t, void **); + int (*ns_disable_hook)(ns_id_t, void **); +} ns_master = { + 0, +}; + +static int ns_is_enabled(struct ns *ns); +static int ns_enable(struct ns *ns); +static void ns_disable(struct ns *ns); + +static __inline int ns_compare(const struct ns *a, const struct ns *b) { - return (a->ns_id - b->ns_id); + return (a->ns_id - b->ns_id); } /* Get a NS. If not found, create one. */ -static struct ns * -ns_get (ns_id_t ns_id) +static struct ns *ns_get(ns_id_t ns_id) { - struct ns *ns; + struct ns *ns; - ns = ns_lookup (ns_id); - if (ns) - return (ns); + ns = ns_lookup(ns_id); + if (ns) + return (ns); - ns = XCALLOC (MTYPE_NS, sizeof (struct ns)); - ns->ns_id = ns_id; - ns->fd = -1; - RB_INSERT (ns_head, &ns_tree, ns); + ns = XCALLOC(MTYPE_NS, sizeof(struct ns)); + ns->ns_id = ns_id; + ns->fd = -1; + RB_INSERT(ns_head, &ns_tree, ns); - /* - * Initialize interfaces. - * - * I'm not sure if this belongs here or in - * the vrf code. - */ - // if_init (&ns->iflist); + /* + * Initialize interfaces. + * + * I'm not sure if this belongs here or in + * the vrf code. + */ + // if_init (&ns->iflist); - zlog_info ("NS %u is created.", ns_id); + zlog_info("NS %u is created.", ns_id); - if (ns_master.ns_new_hook) - (*ns_master.ns_new_hook) (ns_id, &ns->info); + if (ns_master.ns_new_hook) + (*ns_master.ns_new_hook)(ns_id, &ns->info); - return ns; + return ns; } /* Delete a NS. This is called in ns_terminate(). */ -static void -ns_delete (struct ns *ns) +static void ns_delete(struct ns *ns) { - zlog_info ("NS %u is to be deleted.", ns->ns_id); + zlog_info("NS %u is to be deleted.", ns->ns_id); - ns_disable (ns); + ns_disable(ns); - if (ns_master.ns_delete_hook) - (*ns_master.ns_delete_hook) (ns->ns_id, &ns->info); + if (ns_master.ns_delete_hook) + (*ns_master.ns_delete_hook)(ns->ns_id, &ns->info); - /* - * I'm not entirely sure if the vrf->iflist - * needs to be moved into here or not. - */ - //if_terminate (&ns->iflist); + /* + * I'm not entirely sure if the vrf->iflist + * needs to be moved into here or not. + */ + // if_terminate (&ns->iflist); - RB_REMOVE (ns_head, &ns_tree, ns); - if (ns->name) - XFREE (MTYPE_NS_NAME, ns->name); + RB_REMOVE(ns_head, &ns_tree, ns); + if (ns->name) + XFREE(MTYPE_NS_NAME, ns->name); - XFREE (MTYPE_NS, ns); + XFREE(MTYPE_NS, ns); } /* Look up a NS by identifier. */ -static struct ns * -ns_lookup (ns_id_t ns_id) +static struct ns *ns_lookup(ns_id_t ns_id) { - struct ns ns; - ns.ns_id = ns_id; - return (RB_FIND (ns_head, &ns_tree, &ns)); + struct ns ns; + ns.ns_id = ns_id; + return (RB_FIND(ns_head, &ns_tree, &ns)); } /* @@ -182,13 +177,12 @@ ns_lookup (ns_id_t ns_id) * is ready to allocate resources. Currently there's only one * type of resource: socket. */ -static int -ns_is_enabled (struct ns *ns) +static int ns_is_enabled(struct ns *ns) { - if (have_netns()) - return ns && ns->fd >= 0; - else - return ns && ns->fd == -2 && ns->ns_id == NS_DEFAULT; + if (have_netns()) + return ns && ns->fd >= 0; + else + return ns && ns->fd == -2 && ns->ns_id == NS_DEFAULT; } /* @@ -198,36 +192,34 @@ ns_is_enabled (struct ns *ns) * * RETURN: 1 - enabled successfully; otherwise, 0. */ -static int -ns_enable (struct ns *ns) +static int ns_enable(struct ns *ns) { - if (!ns_is_enabled (ns)) - { - if (have_netns()) { - ns->fd = open (ns->name, O_RDONLY); - } else { - ns->fd = -2; /* Remember that ns_enable_hook has been called */ - errno = -ENOTSUP; - } - - if (!ns_is_enabled (ns)) - { - zlog_err ("Can not enable NS %u: %s!", - ns->ns_id, safe_strerror (errno)); - return 0; - } - - if (have_netns()) - zlog_info ("NS %u is associated with NETNS %s.", - ns->ns_id, ns->name); - - zlog_info ("NS %u is enabled.", ns->ns_id); - if (ns_master.ns_enable_hook) - (*ns_master.ns_enable_hook) (ns->ns_id, &ns->info); - } - - return 1; + if (!ns_is_enabled(ns)) { + if (have_netns()) { + ns->fd = open(ns->name, O_RDONLY); + } else { + ns->fd = -2; /* Remember that ns_enable_hook has been + called */ + errno = -ENOTSUP; + } + + if (!ns_is_enabled(ns)) { + zlog_err("Can not enable NS %u: %s!", ns->ns_id, + safe_strerror(errno)); + return 0; + } + + if (have_netns()) + zlog_info("NS %u is associated with NETNS %s.", + ns->ns_id, ns->name); + + zlog_info("NS %u is enabled.", ns->ns_id); + if (ns_master.ns_enable_hook) + (*ns_master.ns_enable_hook)(ns->ns_id, &ns->info); + } + + return 1; } /* @@ -235,71 +227,66 @@ ns_enable (struct ns *ns) * The NS_DELETE_HOOK callback will be called to inform * that they must release the resources in the NS. */ -static void -ns_disable (struct ns *ns) +static void ns_disable(struct ns *ns) { - if (ns_is_enabled (ns)) - { - zlog_info ("NS %u is to be disabled.", ns->ns_id); + if (ns_is_enabled(ns)) { + zlog_info("NS %u is to be disabled.", ns->ns_id); - if (ns_master.ns_disable_hook) - (*ns_master.ns_disable_hook) (ns->ns_id, &ns->info); + if (ns_master.ns_disable_hook) + (*ns_master.ns_disable_hook)(ns->ns_id, &ns->info); - if (have_netns()) - close (ns->fd); + if (have_netns()) + close(ns->fd); - ns->fd = -1; - } + ns->fd = -1; + } } /* Add a NS hook. Please add hooks before calling ns_init(). */ -void -ns_add_hook (int type, int (*func)(ns_id_t, void **)) +void ns_add_hook(int type, int (*func)(ns_id_t, void **)) { - switch (type) { - case NS_NEW_HOOK: - ns_master.ns_new_hook = func; - break; - case NS_DELETE_HOOK: - ns_master.ns_delete_hook = func; - break; - case NS_ENABLE_HOOK: - ns_master.ns_enable_hook = func; - break; - case NS_DISABLE_HOOK: - ns_master.ns_disable_hook = func; - break; - default: - break; - } + switch (type) { + case NS_NEW_HOOK: + ns_master.ns_new_hook = func; + break; + case NS_DELETE_HOOK: + ns_master.ns_delete_hook = func; + break; + case NS_ENABLE_HOOK: + ns_master.ns_enable_hook = func; + break; + case NS_DISABLE_HOOK: + ns_master.ns_disable_hook = func; + break; + default: + break; + } } /* * NS realization with NETNS */ -static char * -ns_netns_pathname (struct vty *vty, const char *name) +static char *ns_netns_pathname(struct vty *vty, const char *name) { - static char pathname[PATH_MAX]; - char *result; - - if (name[0] == '/') /* absolute pathname */ - result = realpath (name, pathname); - else /* relevant pathname */ - { - char tmp_name[PATH_MAX]; - snprintf (tmp_name, PATH_MAX, "%s/%s", NS_RUN_DIR, name); - result = realpath (tmp_name, pathname); - } - - if (! result) - { - vty_out (vty, "Invalid pathname: %s\n",safe_strerror(errno)); - return NULL; - } - return pathname; + static char pathname[PATH_MAX]; + char *result; + + if (name[0] == '/') /* absolute pathname */ + result = realpath(name, pathname); + else /* relevant pathname */ + { + char tmp_name[PATH_MAX]; + snprintf(tmp_name, PATH_MAX, "%s/%s", NS_RUN_DIR, name); + result = realpath(tmp_name, pathname); + } + + if (!result) { + vty_out(vty, "Invalid pathname: %s\n", safe_strerror(errno)); + return NULL; + } + return pathname; } DEFUN_NOSH (ns_netns, @@ -310,36 +297,34 @@ DEFUN_NOSH (ns_netns, "The Name Space\n" "The file name in " NS_RUN_DIR ", or a full pathname\n") { - int idx_number = 1; - int idx_name = 3; - ns_id_t ns_id = NS_DEFAULT; - struct ns *ns = NULL; - char *pathname = ns_netns_pathname (vty, argv[idx_name]->arg); - - if (!pathname) - return CMD_WARNING_CONFIG_FAILED; - - ns_id = strtoul (argv[idx_number]->arg, NULL, 10); - ns = ns_get (ns_id); - - if (ns->name && strcmp (ns->name, pathname) != 0) - { - vty_out (vty, "NS %u is already configured with NETNS %s\n", - ns->ns_id, ns->name); - return CMD_WARNING_CONFIG_FAILED; - } - - if (!ns->name) - ns->name = XSTRDUP (MTYPE_NS_NAME, pathname); - - if (!ns_enable (ns)) - { - vty_out (vty, "Can not associate NS %u with NETNS %s\n", - ns->ns_id, ns->name); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + int idx_number = 1; + int idx_name = 3; + ns_id_t ns_id = NS_DEFAULT; + struct ns *ns = NULL; + char *pathname = ns_netns_pathname(vty, argv[idx_name]->arg); + + if (!pathname) + return CMD_WARNING_CONFIG_FAILED; + + ns_id = strtoul(argv[idx_number]->arg, NULL, 10); + ns = ns_get(ns_id); + + if (ns->name && strcmp(ns->name, pathname) != 0) { + vty_out(vty, "NS %u is already configured with NETNS %s\n", + ns->ns_id, ns->name); + return CMD_WARNING_CONFIG_FAILED; + } + + if (!ns->name) + ns->name = XSTRDUP(MTYPE_NS_NAME, pathname); + + if (!ns_enable(ns)) { + vty_out(vty, "Can not associate NS %u with NETNS %s\n", + ns->ns_id, ns->name); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } DEFUN (no_ns_netns, @@ -351,135 +336,119 @@ DEFUN (no_ns_netns, "The Name Space\n" "The file name in " NS_RUN_DIR ", or a full pathname\n") { - int idx_number = 2; - int idx_name = 4; - ns_id_t ns_id = NS_DEFAULT; - struct ns *ns = NULL; - char *pathname = ns_netns_pathname (vty, argv[idx_name]->arg); - - if (!pathname) - return CMD_WARNING_CONFIG_FAILED; - - ns_id = strtoul(argv[idx_number]->arg, NULL, 10); - ns = ns_lookup (ns_id); - - if (!ns) - { - vty_out (vty, "NS %u is not found\n", ns_id); - return CMD_SUCCESS; - } - - if (ns->name && strcmp (ns->name, pathname) != 0) - { - vty_out (vty, "Incorrect NETNS file name\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ns_disable (ns); - - if (ns->name) - { - XFREE (MTYPE_NS_NAME, ns->name); - ns->name = NULL; - } - - return CMD_SUCCESS; + int idx_number = 2; + int idx_name = 4; + ns_id_t ns_id = NS_DEFAULT; + struct ns *ns = NULL; + char *pathname = ns_netns_pathname(vty, argv[idx_name]->arg); + + if (!pathname) + return CMD_WARNING_CONFIG_FAILED; + + ns_id = strtoul(argv[idx_number]->arg, NULL, 10); + ns = ns_lookup(ns_id); + + if (!ns) { + vty_out(vty, "NS %u is not found\n", ns_id); + return CMD_SUCCESS; + } + + if (ns->name && strcmp(ns->name, pathname) != 0) { + vty_out(vty, "Incorrect NETNS file name\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ns_disable(ns); + + if (ns->name) { + XFREE(MTYPE_NS_NAME, ns->name); + ns->name = NULL; + } + + return CMD_SUCCESS; } /* NS node. */ -static struct cmd_node ns_node = -{ - NS_NODE, - "", /* NS node has no interface. */ - 1 -}; +static struct cmd_node ns_node = {NS_NODE, "", /* NS node has no interface. */ + 1}; /* NS configuration write function. */ -static int -ns_config_write (struct vty *vty) +static int ns_config_write(struct vty *vty) { - struct ns *ns; - int write = 0; + struct ns *ns; + int write = 0; - RB_FOREACH (ns, ns_head, &ns_tree) { - if (ns->ns_id == NS_DEFAULT || ns->name == NULL) - continue; + RB_FOREACH(ns, ns_head, &ns_tree) + { + if (ns->ns_id == NS_DEFAULT || ns->name == NULL) + continue; - vty_out (vty, "logical-router %u netns %s\n", ns->ns_id,ns->name); - write = 1; - } + vty_out(vty, "logical-router %u netns %s\n", ns->ns_id, + ns->name); + write = 1; + } - return write; + return write; } /* Initialize NS module. */ -void -ns_init (void) +void ns_init(void) { - struct ns *default_ns; - - /* The default NS always exists. */ - default_ns = ns_get (NS_DEFAULT); - if (!default_ns) - { - zlog_err ("ns_init: failed to create the default NS!"); - exit (1); - } - - /* Set the default NS name. */ - default_ns->name = XSTRDUP (MTYPE_NS_NAME, NS_DEFAULT_NAME); - - /* Enable the default NS. */ - if (!ns_enable (default_ns)) - { - zlog_err ("ns_init: failed to enable the default NS!"); - exit (1); - } - - if (have_netns()) - { - /* Install NS commands. */ - install_node (&ns_node, ns_config_write); - install_element (CONFIG_NODE, &ns_netns_cmd); - install_element (CONFIG_NODE, &no_ns_netns_cmd); - } + struct ns *default_ns; + + /* The default NS always exists. */ + default_ns = ns_get(NS_DEFAULT); + if (!default_ns) { + zlog_err("ns_init: failed to create the default NS!"); + exit(1); + } + + /* Set the default NS name. */ + default_ns->name = XSTRDUP(MTYPE_NS_NAME, NS_DEFAULT_NAME); + + /* Enable the default NS. */ + if (!ns_enable(default_ns)) { + zlog_err("ns_init: failed to enable the default NS!"); + exit(1); + } + + if (have_netns()) { + /* Install NS commands. */ + install_node(&ns_node, ns_config_write); + install_element(CONFIG_NODE, &ns_netns_cmd); + install_element(CONFIG_NODE, &no_ns_netns_cmd); + } } /* Terminate NS module. */ -void -ns_terminate (void) +void ns_terminate(void) { - struct ns *ns; + struct ns *ns; - while ((ns = RB_ROOT (ns_head, &ns_tree)) != NULL) - ns_delete (ns); + while ((ns = RB_ROOT(ns_head, &ns_tree)) != NULL) + ns_delete(ns); } /* Create a socket for the NS. */ -int -ns_socket (int domain, int type, int protocol, ns_id_t ns_id) +int ns_socket(int domain, int type, int protocol, ns_id_t ns_id) { - struct ns *ns = ns_lookup (ns_id); - int ret = -1; - - if (!ns_is_enabled (ns)) - { - errno = ENOSYS; - return -1; - } - - if (have_netns()) - { - ret = (ns_id != NS_DEFAULT) ? setns (ns->fd, CLONE_NEWNET) : 0; - if (ret >= 0) - { - ret = socket (domain, type, protocol); - if (ns_id != NS_DEFAULT) - setns (ns_lookup (NS_DEFAULT)->fd, CLONE_NEWNET); - } - } - else - ret = socket (domain, type, protocol); - - return ret; + struct ns *ns = ns_lookup(ns_id); + int ret = -1; + + if (!ns_is_enabled(ns)) { + errno = ENOSYS; + return -1; + } + + if (have_netns()) { + ret = (ns_id != NS_DEFAULT) ? setns(ns->fd, CLONE_NEWNET) : 0; + if (ret >= 0) { + ret = socket(domain, type, protocol); + if (ns_id != NS_DEFAULT) + setns(ns_lookup(NS_DEFAULT)->fd, CLONE_NEWNET); + } + } else + ret = socket(domain, type, protocol); + + return ret; } diff --git a/lib/ns.h b/lib/ns.h index 98fd3fa18..c492d6600 100644 --- a/lib/ns.h +++ b/lib/ns.h @@ -33,27 +33,26 @@ typedef u_int16_t ns_id_t; /* Default netns directory (Linux) */ #define NS_RUN_DIR "/var/run/netns" -struct ns -{ - RB_ENTRY(ns) entry; +struct ns { + RB_ENTRY(ns) entry; - /* Identifier, same as the vector index */ - ns_id_t ns_id; + /* Identifier, same as the vector index */ + ns_id_t ns_id; - /* Name */ - char *name; + /* Name */ + char *name; - /* File descriptor */ - int fd; + /* File descriptor */ + int fd; - /* Master list of interfaces belonging to this NS */ - struct list *iflist; + /* Master list of interfaces belonging to this NS */ + struct list *iflist; - /* User data */ - void *info; + /* User data */ + void *info; }; -RB_HEAD (ns_head, ns); -RB_PROTOTYPE (ns_head, ns, entry, ns_compare) +RB_HEAD(ns_head, ns); +RB_PROTOTYPE(ns_head, ns, entry, ns_compare) extern struct ns_head ns_tree; @@ -74,21 +73,20 @@ extern struct ns_head ns_tree; * - param 2: the address of the user data pointer (the user data * can be stored in or freed from there) */ -extern void ns_add_hook (int, int (*)(ns_id_t, void **)); +extern void ns_add_hook(int, int (*)(ns_id_t, void **)); /* * NS initializer/destructor */ /* Please add hooks before calling ns_init(). */ -extern void ns_init (void); -extern void ns_terminate (void); +extern void ns_init(void); +extern void ns_terminate(void); /* * NS utilities */ /* Create a socket serving for the given NS */ -extern int ns_socket (int, int, int, ns_id_t); +extern int ns_socket(int, int, int, ns_id_t); #endif /*_ZEBRA_NS_H*/ - diff --git a/lib/openbsd-queue.h b/lib/openbsd-queue.h index 5e81fdd13..e09cc3d4e 100644 --- a/lib/openbsd-queue.h +++ b/lib/openbsd-queue.h @@ -32,7 +32,7 @@ * @(#)queue.h 8.5 (Berkeley) 8/20/94 */ -#ifndef _SYS_QUEUE_H_ +#ifndef _SYS_QUEUE_H_ #define _SYS_QUEUE_H_ /* @@ -88,18 +88,20 @@ /* * Singly-linked List definitions. */ -#define SLIST_HEAD(name, type) \ -struct name { \ - struct type *slh_first; /* first element */ \ -} +#define SLIST_HEAD(name, type) \ + struct name { \ + struct type *slh_first; /* first element */ \ + } -#define SLIST_HEAD_INITIALIZER(head) \ - { NULL } +#define SLIST_HEAD_INITIALIZER(head) \ + { \ + NULL \ + } -#define SLIST_ENTRY(type) \ -struct { \ - struct type *sle_next; /* next element */ \ -} +#define SLIST_ENTRY(type) \ + struct { \ + struct type *sle_next; /* next element */ \ + } /* * Singly-linked List access methods. @@ -109,71 +111,77 @@ struct { \ #define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) #define SLIST_NEXT(elm, field) ((elm)->field.sle_next) -#define SLIST_FOREACH(var, head, field) \ - for((var) = SLIST_FIRST(head); \ - (var) != SLIST_END(head); \ - (var) = SLIST_NEXT(var, field)) +#define SLIST_FOREACH(var, head, field) \ + for ((var) = SLIST_FIRST(head); (var) != SLIST_END(head); \ + (var) = SLIST_NEXT(var, field)) -#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = SLIST_FIRST(head); \ - (var) && ((tvar) = SLIST_NEXT(var, field), 1); \ - (var) = (tvar)) +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST(head); \ + (var) && ((tvar) = SLIST_NEXT(var, field), 1); (var) = (tvar)) /* * Singly-linked List functions. */ -#define SLIST_INIT(head) { \ - SLIST_FIRST(head) = SLIST_END(head); \ -} - -#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ - (elm)->field.sle_next = (slistelm)->field.sle_next; \ - (slistelm)->field.sle_next = (elm); \ -} while (0) - -#define SLIST_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.sle_next = (head)->slh_first; \ - (head)->slh_first = (elm); \ -} while (0) - -#define SLIST_REMOVE_AFTER(elm, field) do { \ - (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ -} while (0) - -#define SLIST_REMOVE_HEAD(head, field) do { \ - (head)->slh_first = (head)->slh_first->field.sle_next; \ -} while (0) - -#define SLIST_REMOVE(head, elm, type, field) do { \ - if ((head)->slh_first == (elm)) { \ - SLIST_REMOVE_HEAD((head), field); \ - } else { \ - struct type *curelm = (head)->slh_first; \ - \ - while (curelm->field.sle_next != (elm)) \ - curelm = curelm->field.sle_next; \ - curelm->field.sle_next = \ - curelm->field.sle_next->field.sle_next; \ - } \ - _Q_INVALIDATE((elm)->field.sle_next); \ -} while (0) +#define SLIST_INIT(head) \ + { \ + SLIST_FIRST(head) = SLIST_END(head); \ + } + +#define SLIST_INSERT_AFTER(slistelm, elm, field) \ + do { \ + (elm)->field.sle_next = (slistelm)->field.sle_next; \ + (slistelm)->field.sle_next = (elm); \ + } while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) \ + do { \ + (elm)->field.sle_next = (head)->slh_first; \ + (head)->slh_first = (elm); \ + } while (0) + +#define SLIST_REMOVE_AFTER(elm, field) \ + do { \ + (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ + } while (0) + +#define SLIST_REMOVE_HEAD(head, field) \ + do { \ + (head)->slh_first = (head)->slh_first->field.sle_next; \ + } while (0) + +#define SLIST_REMOVE(head, elm, type, field) \ + do { \ + if ((head)->slh_first == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = (head)->slh_first; \ + \ + while (curelm->field.sle_next != (elm)) \ + curelm = curelm->field.sle_next; \ + curelm->field.sle_next = \ + curelm->field.sle_next->field.sle_next; \ + } \ + _Q_INVALIDATE((elm)->field.sle_next); \ + } while (0) /* * List definitions. */ -#define LIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define LIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} +#define LIST_HEAD(name, type) \ + struct name { \ + struct type *lh_first; /* first element */ \ + } + +#define LIST_HEAD_INITIALIZER(head) \ + { \ + NULL \ + } + +#define LIST_ENTRY(type) \ + struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ + } /* * List access methods. @@ -183,80 +191,87 @@ struct { \ #define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) #define LIST_NEXT(elm, field) ((elm)->field.le_next) -#define LIST_FOREACH(var, head, field) \ - for((var) = LIST_FIRST(head); \ - (var)!= LIST_END(head); \ - (var) = LIST_NEXT(var, field)) +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST(head); (var) != LIST_END(head); \ + (var) = LIST_NEXT(var, field)) -#define LIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = LIST_FIRST(head); \ - (var) && ((tvar) = LIST_NEXT(var, field), 1); \ - (var) = (tvar)) +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST(head); \ + (var) && ((tvar) = LIST_NEXT(var, field), 1); (var) = (tvar)) /* * List functions. */ -#define LIST_INIT(head) do { \ - LIST_FIRST(head) = LIST_END(head); \ -} while (0) - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ - if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ - (listelm)->field.le_next->field.le_prev = \ - &(elm)->field.le_next; \ - (listelm)->field.le_next = (elm); \ - (elm)->field.le_prev = &(listelm)->field.le_next; \ -} while (0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - (elm)->field.le_next = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &(elm)->field.le_next; \ -} while (0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.le_next = (head)->lh_first) != NULL) \ - (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ - (head)->lh_first = (elm); \ - (elm)->field.le_prev = &(head)->lh_first; \ -} while (0) - -#define LIST_REMOVE(elm, field) do { \ - if ((elm)->field.le_next != NULL) \ - (elm)->field.le_next->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = (elm)->field.le_next; \ - _Q_INVALIDATE((elm)->field.le_prev); \ - _Q_INVALIDATE((elm)->field.le_next); \ -} while (0) - -#define LIST_REPLACE(elm, elm2, field) do { \ - if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ - (elm2)->field.le_next->field.le_prev = \ - &(elm2)->field.le_next; \ - (elm2)->field.le_prev = (elm)->field.le_prev; \ - *(elm2)->field.le_prev = (elm2); \ - _Q_INVALIDATE((elm)->field.le_prev); \ - _Q_INVALIDATE((elm)->field.le_next); \ -} while (0) +#define LIST_INIT(head) \ + do { \ + LIST_FIRST(head) = LIST_END(head); \ + } while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) \ + do { \ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ + } while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) \ + do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + (elm)->field.le_next = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &(elm)->field.le_next; \ + } while (0) + +#define LIST_INSERT_HEAD(head, elm, field) \ + do { \ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \ + (head)->lh_first->field.le_prev = \ + &(elm)->field.le_next; \ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ + } while (0) + +#define LIST_REMOVE(elm, field) \ + do { \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ + _Q_INVALIDATE((elm)->field.le_prev); \ + _Q_INVALIDATE((elm)->field.le_next); \ + } while (0) + +#define LIST_REPLACE(elm, elm2, field) \ + do { \ + if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ + (elm2)->field.le_next->field.le_prev = \ + &(elm2)->field.le_next; \ + (elm2)->field.le_prev = (elm)->field.le_prev; \ + *(elm2)->field.le_prev = (elm2); \ + _Q_INVALIDATE((elm)->field.le_prev); \ + _Q_INVALIDATE((elm)->field.le_next); \ + } while (0) /* * Simple queue definitions. */ -#define SIMPLEQ_HEAD(name, type) \ -struct name { \ - struct type *sqh_first; /* first element */ \ - struct type **sqh_last; /* addr of last next element */ \ -} - -#define SIMPLEQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).sqh_first } - -#define SIMPLEQ_ENTRY(type) \ -struct { \ - struct type *sqe_next; /* next element */ \ -} +#define SIMPLEQ_HEAD(name, type) \ + struct name { \ + struct type *sqh_first; /* first element */ \ + struct type **sqh_last; /* addr of last next element */ \ + } + +#define SIMPLEQ_HEAD_INITIALIZER(head) \ + { \ + NULL, &(head).sqh_first \ + } + +#define SIMPLEQ_ENTRY(type) \ + struct { \ + struct type *sqe_next; /* next element */ \ + } /* * Simple queue access methods. @@ -266,158 +281,179 @@ struct { \ #define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) #define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) -#define SIMPLEQ_FOREACH(var, head, field) \ - for((var) = SIMPLEQ_FIRST(head); \ - (var) != SIMPLEQ_END(head); \ - (var) = SIMPLEQ_NEXT(var, field)) +#define SIMPLEQ_FOREACH(var, head, field) \ + for ((var) = SIMPLEQ_FIRST(head); (var) != SIMPLEQ_END(head); \ + (var) = SIMPLEQ_NEXT(var, field)) -#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = SIMPLEQ_FIRST(head); \ - (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \ - (var) = (tvar)) +#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SIMPLEQ_FIRST(head); \ + (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); (var) = (tvar)) /* * Simple queue functions. */ -#define SIMPLEQ_INIT(head) do { \ - (head)->sqh_first = NULL; \ - (head)->sqh_last = &(head)->sqh_first; \ -} while (0) - -#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (head)->sqh_first = (elm); \ -} while (0) - -#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.sqe_next = NULL; \ - *(head)->sqh_last = (elm); \ - (head)->sqh_last = &(elm)->field.sqe_next; \ -} while (0) - -#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (listelm)->field.sqe_next = (elm); \ -} while (0) - -#define SIMPLEQ_REMOVE_HEAD(head, field) do { \ - if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ - (head)->sqh_last = &(head)->sqh_first; \ -} while (0) - -#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ - if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \ - == NULL) \ - (head)->sqh_last = &(elm)->field.sqe_next; \ -} while (0) - -#define SIMPLEQ_CONCAT(head1, head2) do { \ - if (!SIMPLEQ_EMPTY((head2))) { \ - *(head1)->sqh_last = (head2)->sqh_first; \ - (head1)->sqh_last = (head2)->sqh_last; \ - SIMPLEQ_INIT((head2)); \ - } \ -} while (0) +#define SIMPLEQ_INIT(head) \ + do { \ + (head)->sqh_first = NULL; \ + (head)->sqh_last = &(head)->sqh_first; \ + } while (0) + +#define SIMPLEQ_INSERT_HEAD(head, elm, field) \ + do { \ + if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (head)->sqh_first = (elm); \ + } while (0) + +#define SIMPLEQ_INSERT_TAIL(head, elm, field) \ + do { \ + (elm)->field.sqe_next = NULL; \ + *(head)->sqh_last = (elm); \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + } while (0) + +#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) \ + do { \ + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) \ + == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (listelm)->field.sqe_next = (elm); \ + } while (0) + +#define SIMPLEQ_REMOVE_HEAD(head, field) \ + do { \ + if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) \ + == NULL) \ + (head)->sqh_last = &(head)->sqh_first; \ + } while (0) + +#define SIMPLEQ_REMOVE_AFTER(head, elm, field) \ + do { \ + if (((elm)->field.sqe_next = \ + (elm)->field.sqe_next->field.sqe_next) \ + == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + } while (0) + +#define SIMPLEQ_CONCAT(head1, head2) \ + do { \ + if (!SIMPLEQ_EMPTY((head2))) { \ + *(head1)->sqh_last = (head2)->sqh_first; \ + (head1)->sqh_last = (head2)->sqh_last; \ + SIMPLEQ_INIT((head2)); \ + } \ + } while (0) /* * XOR Simple queue definitions. */ -#define XSIMPLEQ_HEAD(name, type) \ -struct name { \ - struct type *sqx_first; /* first element */ \ - struct type **sqx_last; /* addr of last next element */ \ - unsigned long sqx_cookie; \ -} - -#define XSIMPLEQ_ENTRY(type) \ -struct { \ - struct type *sqx_next; /* next element */ \ -} +#define XSIMPLEQ_HEAD(name, type) \ + struct name { \ + struct type *sqx_first; /* first element */ \ + struct type **sqx_last; /* addr of last next element */ \ + unsigned long sqx_cookie; \ + } + +#define XSIMPLEQ_ENTRY(type) \ + struct { \ + struct type *sqx_next; /* next element */ \ + } /* * XOR Simple queue access methods. */ -#define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ \ - (unsigned long)(ptr))) +#define XSIMPLEQ_XOR(head, ptr) \ + ((__typeof(ptr))((head)->sqx_cookie ^ (unsigned long)(ptr))) #define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first)) #define XSIMPLEQ_END(head) NULL #define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head)) #define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next)) +#define XSIMPLEQ_FOREACH(var, head, field) \ + for ((var) = XSIMPLEQ_FIRST(head); (var) != XSIMPLEQ_END(head); \ + (var) = XSIMPLEQ_NEXT(head, var, field)) -#define XSIMPLEQ_FOREACH(var, head, field) \ - for ((var) = XSIMPLEQ_FIRST(head); \ - (var) != XSIMPLEQ_END(head); \ - (var) = XSIMPLEQ_NEXT(head, var, field)) - -#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = XSIMPLEQ_FIRST(head); \ - (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \ - (var) = (tvar)) +#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = XSIMPLEQ_FIRST(head); \ + (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \ + (var) = (tvar)) /* * XOR Simple queue functions. */ -#define XSIMPLEQ_INIT(head) do { \ - arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \ - (head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \ - (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ -} while (0) - -#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.sqx_next = (head)->sqx_first) == \ - XSIMPLEQ_XOR(head, NULL)) \ +#define XSIMPLEQ_INIT(head) \ + do { \ + arc4random_buf(&(head)->sqx_cookie, \ + sizeof((head)->sqx_cookie)); \ + (head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ + } while (0) + +#define XSIMPLEQ_INSERT_HEAD(head, elm, field) \ + do { \ + if (((elm)->field.sqx_next = (head)->sqx_first) \ + == XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = \ + XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ + (head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \ + } while (0) + +#define XSIMPLEQ_INSERT_TAIL(head, elm, field) \ + do { \ + (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \ + *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = \ + XSIMPLEQ_XOR(head, (elm)); \ (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ - (head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \ -} while (0) - -#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \ - *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \ - (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ -} while (0) - -#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == \ - XSIMPLEQ_XOR(head, NULL)) \ - (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ - (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \ -} while (0) - -#define XSIMPLEQ_REMOVE_HEAD(head, field) do { \ - if (((head)->sqx_first = XSIMPLEQ_XOR(head, \ - (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \ - (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ -} while (0) - -#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ - if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \ - (elm)->field.sqx_next)->field.sqx_next) \ - == XSIMPLEQ_XOR(head, NULL)) \ - (head)->sqx_last = \ - XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ -} while (0) + } while (0) + +#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) \ + do { \ + if (((elm)->field.sqx_next = (listelm)->field.sqx_next) \ + == XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = \ + XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ + (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \ + } while (0) + +#define XSIMPLEQ_REMOVE_HEAD(head, field) \ + do { \ + if (((head)->sqx_first = XSIMPLEQ_XOR(head, (head)->sqx_first) \ + ->field.sqx_next) \ + == XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = \ + XSIMPLEQ_XOR(head, &(head)->sqx_first); \ + } while (0) + +#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) \ + do { \ + if (((elm)->field.sqx_next = \ + XSIMPLEQ_XOR(head, (elm)->field.sqx_next) \ + ->field.sqx_next) \ + == XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = \ + XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ + } while (0) /* * Tail queue definitions. */ -#define TAILQ_HEAD(name, type) \ -struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ -} - -#define TAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first } - -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ -} +#define TAILQ_HEAD(name, type) \ + struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ + } + +#define TAILQ_HEAD_INITIALIZER(head) \ + { \ + NULL, &(head).tqh_first \ + } + +#define TAILQ_ENTRY(type) \ + struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ + } /* * Tail queue access methods. @@ -425,109 +461,115 @@ struct { \ #define TAILQ_FIRST(head) ((head)->tqh_first) #define TAILQ_END(head) NULL #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) -#define TAILQ_LAST(head, headname) \ +#define TAILQ_LAST(head, headname) \ (*(((struct headname *)((head)->tqh_last))->tqh_last)) /* XXX */ -#define TAILQ_PREV(elm, headname, field) \ +#define TAILQ_PREV(elm, headname, field) \ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) -#define TAILQ_EMPTY(head) \ - (TAILQ_FIRST(head) == TAILQ_END(head)) +#define TAILQ_EMPTY(head) (TAILQ_FIRST(head) == TAILQ_END(head)) -#define TAILQ_FOREACH(var, head, field) \ - for((var) = TAILQ_FIRST(head); \ - (var) != TAILQ_END(head); \ - (var) = TAILQ_NEXT(var, field)) +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST(head); (var) != TAILQ_END(head); \ + (var) = TAILQ_NEXT(var, field)) -#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = TAILQ_FIRST(head); \ - (var) != TAILQ_END(head) && \ - ((tvar) = TAILQ_NEXT(var, field), 1); \ - (var) = (tvar)) +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST(head); \ + (var) != TAILQ_END(head) && ((tvar) = TAILQ_NEXT(var, field), 1); \ + (var) = (tvar)) -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for((var) = TAILQ_LAST(head, headname); \ - (var) != TAILQ_END(head); \ - (var) = TAILQ_PREV(var, headname, field)) +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST(head, headname); (var) != TAILQ_END(head); \ + (var) = TAILQ_PREV(var, headname, field)) -#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ - for ((var) = TAILQ_LAST(head, headname); \ - (var) != TAILQ_END(head) && \ - ((tvar) = TAILQ_PREV(var, headname, field), 1); \ - (var) = (tvar)) +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST(head, headname); \ + (var) != TAILQ_END(head) \ + && ((tvar) = TAILQ_PREV(var, headname, field), 1); \ + (var) = (tvar)) /* * Tail queue functions. */ -#define TAILQ_INIT(head) do { \ - (head)->tqh_first = NULL; \ - (head)->tqh_last = &(head)->tqh_first; \ -} while (0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ - (head)->tqh_first->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (head)->tqh_first = (elm); \ - (elm)->field.tqe_prev = &(head)->tqh_first; \ -} while (0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.tqe_next = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &(elm)->field.tqe_next; \ -} while (0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ - (elm)->field.tqe_next->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (listelm)->field.tqe_next = (elm); \ - (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ -} while (0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - (elm)->field.tqe_next = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ -} while (0) - -#define TAILQ_REMOVE(head, elm, field) do { \ - if (((elm)->field.tqe_next) != NULL) \ - (elm)->field.tqe_next->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ - _Q_INVALIDATE((elm)->field.tqe_prev); \ - _Q_INVALIDATE((elm)->field.tqe_next); \ -} while (0) - -#define TAILQ_REPLACE(head, elm, elm2, field) do { \ - if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ - (elm2)->field.tqe_next->field.tqe_prev = \ - &(elm2)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm2)->field.tqe_next; \ - (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ - *(elm2)->field.tqe_prev = (elm2); \ - _Q_INVALIDATE((elm)->field.tqe_prev); \ - _Q_INVALIDATE((elm)->field.tqe_next); \ -} while (0) - -#define TAILQ_CONCAT(head1, head2, field) do { \ - if (!TAILQ_EMPTY(head2)) { \ - *(head1)->tqh_last = (head2)->tqh_first; \ - (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ - (head1)->tqh_last = (head2)->tqh_last; \ - TAILQ_INIT((head2)); \ - } \ -} while (0) - -#endif /* !_SYS_QUEUE_H_ */ +#define TAILQ_INIT(head) \ + do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ + } while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) \ + do { \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ + } while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) \ + do { \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + } while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) \ + do { \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) \ + != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ + } while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) \ + do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ + } while (0) + +#define TAILQ_REMOVE(head, elm, field) \ + do { \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ + _Q_INVALIDATE((elm)->field.tqe_prev); \ + _Q_INVALIDATE((elm)->field.tqe_next); \ + } while (0) + +#define TAILQ_REPLACE(head, elm, elm2, field) \ + do { \ + if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ + (elm2)->field.tqe_next->field.tqe_prev = \ + &(elm2)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm2)->field.tqe_next; \ + (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ + *(elm2)->field.tqe_prev = (elm2); \ + _Q_INVALIDATE((elm)->field.tqe_prev); \ + _Q_INVALIDATE((elm)->field.tqe_next); \ + } while (0) + +#define TAILQ_CONCAT(head1, head2, field) \ + do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = \ + (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + } \ + } while (0) + +#endif /* !_SYS_QUEUE_H_ */ diff --git a/lib/openbsd-tree.c b/lib/openbsd-tree.c index 7e753554c..5d77ac2a4 100644 --- a/lib/openbsd-tree.c +++ b/lib/openbsd-tree.c @@ -45,16 +45,14 @@ #include -static inline struct rb_entry * -rb_n2e(const struct rb_type *t, void *node) +static inline struct rb_entry *rb_n2e(const struct rb_type *t, void *node) { unsigned long addr = (unsigned long)node; return ((struct rb_entry *)(addr + t->t_offset)); } -static inline void * -rb_e2n(const struct rb_type *t, struct rb_entry *rbe) +static inline void *rb_e2n(const struct rb_type *t, struct rb_entry *rbe) { unsigned long addr = (unsigned long)rbe; @@ -68,37 +66,33 @@ rb_e2n(const struct rb_type *t, struct rb_entry *rbe) #define RBH_ROOT(_rbt) (_rbt)->rbt_root -static inline void -rbe_set(struct rb_entry *rbe, struct rb_entry *parent) +static inline void rbe_set(struct rb_entry *rbe, struct rb_entry *parent) { RBE_PARENT(rbe) = parent; RBE_LEFT(rbe) = RBE_RIGHT(rbe) = NULL; RBE_COLOR(rbe) = RB_RED; } -static inline void -rbe_set_blackred(struct rb_entry *black, struct rb_entry *red) +static inline void rbe_set_blackred(struct rb_entry *black, + struct rb_entry *red) { RBE_COLOR(black) = RB_BLACK; RBE_COLOR(red) = RB_RED; } -static inline void -rbe_augment(const struct rb_type *t, struct rb_entry *rbe) +static inline void rbe_augment(const struct rb_type *t, struct rb_entry *rbe) { (*t->t_augment)(rb_e2n(t, rbe)); } -static inline void -rbe_if_augment(const struct rb_type *t, struct rb_entry *rbe) +static inline void rbe_if_augment(const struct rb_type *t, struct rb_entry *rbe) { if (t->t_augment != NULL) rbe_augment(t, rbe); } -static inline void -rbe_rotate_left(const struct rb_type *t, struct rbt_tree *rbt, - struct rb_entry *rbe) +static inline void rbe_rotate_left(const struct rb_type *t, + struct rbt_tree *rbt, struct rb_entry *rbe) { struct rb_entry *parent; struct rb_entry *tmp; @@ -130,9 +124,8 @@ rbe_rotate_left(const struct rb_type *t, struct rbt_tree *rbt, } } -static inline void -rbe_rotate_right(const struct rb_type *t, struct rbt_tree *rbt, - struct rb_entry *rbe) +static inline void rbe_rotate_right(const struct rb_type *t, + struct rbt_tree *rbt, struct rb_entry *rbe) { struct rb_entry *parent; struct rb_entry *tmp; @@ -164,14 +157,13 @@ rbe_rotate_right(const struct rb_type *t, struct rbt_tree *rbt, } } -static inline void -rbe_insert_color(const struct rb_type *t, struct rbt_tree *rbt, - struct rb_entry *rbe) +static inline void rbe_insert_color(const struct rb_type *t, + struct rbt_tree *rbt, struct rb_entry *rbe) { struct rb_entry *parent, *gparent, *tmp; - while ((parent = RBE_PARENT(rbe)) != NULL && - RBE_COLOR(parent) == RB_RED) { + while ((parent = RBE_PARENT(rbe)) != NULL + && RBE_COLOR(parent) == RB_RED) { gparent = RBE_PARENT(parent); if (parent == RBE_LEFT(gparent)) { @@ -216,9 +208,10 @@ rbe_insert_color(const struct rb_type *t, struct rbt_tree *rbt, RBE_COLOR(RBH_ROOT(rbt)) = RB_BLACK; } -static inline void -rbe_remove_color(const struct rb_type *t, struct rbt_tree *rbt, - struct rb_entry *parent, struct rb_entry *rbe) +static inline void rbe_remove_color(const struct rb_type *t, + struct rbt_tree *rbt, + struct rb_entry *parent, + struct rb_entry *rbe) { struct rb_entry *tmp; @@ -226,8 +219,8 @@ rbe_remove_color(const struct rb_type *t, struct rbt_tree *rbt, if (parent == NULL) return; - while ((rbe == NULL || RBE_COLOR(rbe) == RB_BLACK) && - rbe != RBH_ROOT(rbt)) { + while ((rbe == NULL || RBE_COLOR(rbe) == RB_BLACK) + && rbe != RBH_ROOT(rbt)) { if (RBE_LEFT(parent) == rbe) { tmp = RBE_RIGHT(parent); if (RBE_COLOR(tmp) == RB_RED) { @@ -235,16 +228,16 @@ rbe_remove_color(const struct rb_type *t, struct rbt_tree *rbt, rbe_rotate_left(t, rbt, parent); tmp = RBE_RIGHT(parent); } - if ((RBE_LEFT(tmp) == NULL || - RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) && - (RBE_RIGHT(tmp) == NULL || - RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK)) { + if ((RBE_LEFT(tmp) == NULL + || RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) + && (RBE_RIGHT(tmp) == NULL + || RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK)) { RBE_COLOR(tmp) = RB_RED; rbe = parent; parent = RBE_PARENT(rbe); } else { - if (RBE_RIGHT(tmp) == NULL || - RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK) { + if (RBE_RIGHT(tmp) == NULL + || RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK) { struct rb_entry *oleft; oleft = RBE_LEFT(tmp); @@ -273,16 +266,16 @@ rbe_remove_color(const struct rb_type *t, struct rbt_tree *rbt, tmp = RBE_LEFT(parent); } - if ((RBE_LEFT(tmp) == NULL || - RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) && - (RBE_RIGHT(tmp) == NULL || - RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK)) { + if ((RBE_LEFT(tmp) == NULL + || RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) + && (RBE_RIGHT(tmp) == NULL + || RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK)) { RBE_COLOR(tmp) = RB_RED; rbe = parent; parent = RBE_PARENT(rbe); } else { - if (RBE_LEFT(tmp) == NULL || - RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) { + if (RBE_LEFT(tmp) == NULL + || RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) { struct rb_entry *oright; oright = RBE_RIGHT(tmp); @@ -392,8 +385,7 @@ color: return (old); } -void * -_rb_remove(const struct rb_type *t, struct rbt_tree *rbt, void *elm) +void *_rb_remove(const struct rb_type *t, struct rbt_tree *rbt, void *elm) { struct rb_entry *rbe = rb_n2e(t, elm); struct rb_entry *old; @@ -403,8 +395,7 @@ _rb_remove(const struct rb_type *t, struct rbt_tree *rbt, void *elm) return (old == NULL ? NULL : rb_e2n(t, old)); } -void * -_rb_insert(const struct rb_type *t, struct rbt_tree *rbt, void *elm) +void *_rb_insert(const struct rb_type *t, struct rbt_tree *rbt, void *elm) { struct rb_entry *rbe = rb_n2e(t, elm); struct rb_entry *tmp; @@ -444,8 +435,7 @@ _rb_insert(const struct rb_type *t, struct rbt_tree *rbt, void *elm) } /* Finds the node with the same key as elm */ -void * -_rb_find(const struct rb_type *t, struct rbt_tree *rbt, const void *key) +void *_rb_find(const struct rb_type *t, struct rbt_tree *rbt, const void *key) { struct rb_entry *tmp = RBH_ROOT(rbt); void *node; @@ -466,8 +456,7 @@ _rb_find(const struct rb_type *t, struct rbt_tree *rbt, const void *key) } /* Finds the first node greater than or equal to the search key */ -void * -_rb_nfind(const struct rb_type *t, struct rbt_tree *rbt, const void *key) +void *_rb_nfind(const struct rb_type *t, struct rbt_tree *rbt, const void *key) { struct rb_entry *tmp = RBH_ROOT(rbt); void *node; @@ -489,8 +478,7 @@ _rb_nfind(const struct rb_type *t, struct rbt_tree *rbt, const void *key) return (res); } -void * -_rb_next(const struct rb_type *t, void *elm) +void *_rb_next(const struct rb_type *t, void *elm) { struct rb_entry *rbe = rb_n2e(t, elm); @@ -499,12 +487,11 @@ _rb_next(const struct rb_type *t, void *elm) while (RBE_LEFT(rbe) != NULL) rbe = RBE_LEFT(rbe); } else { - if (RBE_PARENT(rbe) && - (rbe == RBE_LEFT(RBE_PARENT(rbe)))) + if (RBE_PARENT(rbe) && (rbe == RBE_LEFT(RBE_PARENT(rbe)))) rbe = RBE_PARENT(rbe); else { - while (RBE_PARENT(rbe) && - (rbe == RBE_RIGHT(RBE_PARENT(rbe)))) + while (RBE_PARENT(rbe) + && (rbe == RBE_RIGHT(RBE_PARENT(rbe)))) rbe = RBE_PARENT(rbe); rbe = RBE_PARENT(rbe); } @@ -513,8 +500,7 @@ _rb_next(const struct rb_type *t, void *elm) return (rbe == NULL ? NULL : rb_e2n(t, rbe)); } -void * -_rb_prev(const struct rb_type *t, void *elm) +void *_rb_prev(const struct rb_type *t, void *elm) { struct rb_entry *rbe = rb_n2e(t, elm); @@ -523,12 +509,11 @@ _rb_prev(const struct rb_type *t, void *elm) while (RBE_RIGHT(rbe)) rbe = RBE_RIGHT(rbe); } else { - if (RBE_PARENT(rbe) && - (rbe == RBE_RIGHT(RBE_PARENT(rbe)))) + if (RBE_PARENT(rbe) && (rbe == RBE_RIGHT(RBE_PARENT(rbe)))) rbe = RBE_PARENT(rbe); else { - while (RBE_PARENT(rbe) && - (rbe == RBE_LEFT(RBE_PARENT(rbe)))) + while (RBE_PARENT(rbe) + && (rbe == RBE_LEFT(RBE_PARENT(rbe)))) rbe = RBE_PARENT(rbe); rbe = RBE_PARENT(rbe); } @@ -537,16 +522,14 @@ _rb_prev(const struct rb_type *t, void *elm) return (rbe == NULL ? NULL : rb_e2n(t, rbe)); } -void * -_rb_root(const struct rb_type *t, struct rbt_tree *rbt) +void *_rb_root(const struct rb_type *t, struct rbt_tree *rbt) { struct rb_entry *rbe = RBH_ROOT(rbt); return (rbe == NULL ? rbe : rb_e2n(t, rbe)); } -void * -_rb_min(const struct rb_type *t, struct rbt_tree *rbt) +void *_rb_min(const struct rb_type *t, struct rbt_tree *rbt) { struct rb_entry *rbe = RBH_ROOT(rbt); struct rb_entry *parent = NULL; @@ -559,8 +542,7 @@ _rb_min(const struct rb_type *t, struct rbt_tree *rbt) return (parent == NULL ? NULL : rb_e2n(t, parent)); } -void * -_rb_max(const struct rb_type *t, struct rbt_tree *rbt) +void *_rb_max(const struct rb_type *t, struct rbt_tree *rbt) { struct rb_entry *rbe = RBH_ROOT(rbt); struct rb_entry *parent = NULL; @@ -573,32 +555,28 @@ _rb_max(const struct rb_type *t, struct rbt_tree *rbt) return (parent == NULL ? NULL : rb_e2n(t, parent)); } -void * -_rb_left(const struct rb_type *t, void *node) +void *_rb_left(const struct rb_type *t, void *node) { struct rb_entry *rbe = rb_n2e(t, node); rbe = RBE_LEFT(rbe); return (rbe == NULL ? NULL : rb_e2n(t, rbe)); } -void * -_rb_right(const struct rb_type *t, void *node) +void *_rb_right(const struct rb_type *t, void *node) { struct rb_entry *rbe = rb_n2e(t, node); rbe = RBE_RIGHT(rbe); return (rbe == NULL ? NULL : rb_e2n(t, rbe)); } -void * -_rb_parent(const struct rb_type *t, void *node) +void *_rb_parent(const struct rb_type *t, void *node) { struct rb_entry *rbe = rb_n2e(t, node); rbe = RBE_PARENT(rbe); return (rbe == NULL ? NULL : rb_e2n(t, rbe)); } -void -_rb_set_left(const struct rb_type *t, void *node, void *left) +void _rb_set_left(const struct rb_type *t, void *node, void *left) { struct rb_entry *rbe = rb_n2e(t, node); struct rb_entry *rbl = (left == NULL) ? NULL : rb_n2e(t, left); @@ -606,8 +584,7 @@ _rb_set_left(const struct rb_type *t, void *node, void *left) RBE_LEFT(rbe) = rbl; } -void -_rb_set_right(const struct rb_type *t, void *node, void *right) +void _rb_set_right(const struct rb_type *t, void *node, void *right) { struct rb_entry *rbe = rb_n2e(t, node); struct rb_entry *rbr = (right == NULL) ? NULL : rb_n2e(t, right); @@ -615,8 +592,7 @@ _rb_set_right(const struct rb_type *t, void *node, void *right) RBE_RIGHT(rbe) = rbr; } -void -_rb_set_parent(const struct rb_type *t, void *node, void *parent) +void _rb_set_parent(const struct rb_type *t, void *node, void *parent) { struct rb_entry *rbe = rb_n2e(t, node); struct rb_entry *rbp = (parent == NULL) ? NULL : rb_n2e(t, parent); @@ -624,21 +600,19 @@ _rb_set_parent(const struct rb_type *t, void *node, void *parent) RBE_PARENT(rbe) = rbp; } -void -_rb_poison(const struct rb_type *t, void *node, unsigned long poison) +void _rb_poison(const struct rb_type *t, void *node, unsigned long poison) { struct rb_entry *rbe = rb_n2e(t, node); RBE_PARENT(rbe) = RBE_LEFT(rbe) = RBE_RIGHT(rbe) = - (struct rb_entry *)poison; + (struct rb_entry *)poison; } -int -_rb_check(const struct rb_type *t, void *node, unsigned long poison) +int _rb_check(const struct rb_type *t, void *node, unsigned long poison) { struct rb_entry *rbe = rb_n2e(t, node); - return ((unsigned long)RBE_PARENT(rbe) == poison && - (unsigned long)RBE_LEFT(rbe) == poison && - (unsigned long)RBE_RIGHT(rbe) == poison); + return ((unsigned long)RBE_PARENT(rbe) == poison + && (unsigned long)RBE_LEFT(rbe) == poison + && (unsigned long)RBE_RIGHT(rbe) == poison); } diff --git a/lib/openbsd-tree.h b/lib/openbsd-tree.h index 22cb9252f..859f75167 100644 --- a/lib/openbsd-tree.h +++ b/lib/openbsd-tree.h @@ -24,7 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _SYS_TREE_H_ +#ifndef _SYS_TREE_H_ #define _SYS_TREE_H_ /* @@ -54,23 +54,26 @@ * The maximum height of a red-black tree is 2lg (n+1). */ -#define SPLAY_HEAD(name, type) \ -struct name { \ - struct type *sph_root; /* root of the tree */ \ -} +#define SPLAY_HEAD(name, type) \ + struct name { \ + struct type *sph_root; /* root of the tree */ \ + } -#define SPLAY_INITIALIZER(root) \ - { NULL } +#define SPLAY_INITIALIZER(root) \ + { \ + NULL \ + } -#define SPLAY_INIT(root) do { \ - (root)->sph_root = NULL; \ -} while (0) +#define SPLAY_INIT(root) \ + do { \ + (root)->sph_root = NULL; \ + } while (0) -#define SPLAY_ENTRY(type) \ -struct { \ - struct type *spe_left; /* left element */ \ - struct type *spe_right; /* right element */ \ -} +#define SPLAY_ENTRY(type) \ + struct { \ + struct type *spe_left; /* left element */ \ + struct type *spe_right; /* right element */ \ + } #define SPLAY_LEFT(elm, field) (elm)->field.spe_left #define SPLAY_RIGHT(elm, field) (elm)->field.spe_right @@ -78,197 +81,220 @@ struct { \ #define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) /* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ -#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ - SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ - SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ - (head)->sph_root = tmp; \ -} while (0) - -#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ - SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ - SPLAY_LEFT(tmp, field) = (head)->sph_root; \ - (head)->sph_root = tmp; \ -} while (0) - -#define SPLAY_LINKLEFT(head, tmp, field) do { \ - SPLAY_LEFT(tmp, field) = (head)->sph_root; \ - tmp = (head)->sph_root; \ - (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ -} while (0) - -#define SPLAY_LINKRIGHT(head, tmp, field) do { \ - SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ - tmp = (head)->sph_root; \ - (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ -} while (0) - -#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ - SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ - SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ - SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ - SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ -} while (0) +#define SPLAY_ROTATE_RIGHT(head, tmp, field) \ + do { \ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ + } while (0) + +#define SPLAY_ROTATE_LEFT(head, tmp, field) \ + do { \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ + } while (0) + +#define SPLAY_LINKLEFT(head, tmp, field) \ + do { \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ + } while (0) + +#define SPLAY_LINKRIGHT(head, tmp, field) \ + do { \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ + } while (0) + +#define SPLAY_ASSEMBLE(head, node, left, right, field) \ + do { \ + SPLAY_RIGHT(left, field) = \ + SPLAY_LEFT((head)->sph_root, field); \ + SPLAY_LEFT(right, field) = \ + SPLAY_RIGHT((head)->sph_root, field); \ + SPLAY_LEFT((head)->sph_root, field) = \ + SPLAY_RIGHT(node, field); \ + SPLAY_RIGHT((head)->sph_root, field) = \ + SPLAY_LEFT(node, field); \ + } while (0) /* Generates prototypes and inline functions */ -#define SPLAY_PROTOTYPE(name, type, field, cmp) \ -void name##_SPLAY(struct name *, struct type *); \ -void name##_SPLAY_MINMAX(struct name *, int); \ -struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ -struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ - \ -/* Finds the node with the same key as elm */ \ -static __inline struct type * \ -name##_SPLAY_FIND(struct name *head, struct type *elm) \ -{ \ - if (SPLAY_EMPTY(head)) \ - return(NULL); \ - name##_SPLAY(head, elm); \ - if ((cmp)(elm, (head)->sph_root) == 0) \ - return (head->sph_root); \ - return (NULL); \ -} \ - \ -static __inline struct type * \ -name##_SPLAY_NEXT(struct name *head, struct type *elm) \ -{ \ - name##_SPLAY(head, elm); \ - if (SPLAY_RIGHT(elm, field) != NULL) { \ - elm = SPLAY_RIGHT(elm, field); \ - while (SPLAY_LEFT(elm, field) != NULL) { \ - elm = SPLAY_LEFT(elm, field); \ - } \ - } else \ - elm = NULL; \ - return (elm); \ -} \ - \ -static __inline struct type * \ -name##_SPLAY_MIN_MAX(struct name *head, int val) \ -{ \ - name##_SPLAY_MINMAX(head, val); \ - return (SPLAY_ROOT(head)); \ -} +#define SPLAY_PROTOTYPE(name, type, field, cmp) \ + void name##_SPLAY(struct name *, struct type *); \ + void name##_SPLAY_MINMAX(struct name *, int); \ + struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ + struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ + \ + /* Finds the node with the same key as elm */ \ + static __inline struct type *name##_SPLAY_FIND(struct name *head, \ + struct type *elm) \ + { \ + if (SPLAY_EMPTY(head)) \ + return (NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) \ + return (head->sph_root); \ + return (NULL); \ + } \ + \ + static __inline struct type *name##_SPLAY_NEXT(struct name *head, \ + struct type *elm) \ + { \ + name##_SPLAY(head, elm); \ + if (SPLAY_RIGHT(elm, field) != NULL) { \ + elm = SPLAY_RIGHT(elm, field); \ + while (SPLAY_LEFT(elm, field) != NULL) { \ + elm = SPLAY_LEFT(elm, field); \ + } \ + } else \ + elm = NULL; \ + return (elm); \ + } \ + \ + static __inline struct type *name##_SPLAY_MIN_MAX(struct name *head, \ + int val) \ + { \ + name##_SPLAY_MINMAX(head, val); \ + return (SPLAY_ROOT(head)); \ + } /* Main splay operation. * Moves node close to the key of elm to top */ -#define SPLAY_GENERATE(name, type, field, cmp) \ -struct type * \ -name##_SPLAY_INSERT(struct name *head, struct type *elm) \ -{ \ - if (SPLAY_EMPTY(head)) { \ - SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ - } else { \ - int __comp; \ - name##_SPLAY(head, elm); \ - __comp = (cmp)(elm, (head)->sph_root); \ - if(__comp < 0) { \ - SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ - SPLAY_RIGHT(elm, field) = (head)->sph_root; \ - SPLAY_LEFT((head)->sph_root, field) = NULL; \ - } else if (__comp > 0) { \ - SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ - SPLAY_LEFT(elm, field) = (head)->sph_root; \ - SPLAY_RIGHT((head)->sph_root, field) = NULL; \ - } else \ - return ((head)->sph_root); \ - } \ - (head)->sph_root = (elm); \ - return (NULL); \ -} \ - \ -struct type * \ -name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ -{ \ - struct type *__tmp; \ - if (SPLAY_EMPTY(head)) \ - return (NULL); \ - name##_SPLAY(head, elm); \ - if ((cmp)(elm, (head)->sph_root) == 0) { \ - if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ - (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ - } else { \ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \ - (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ - name##_SPLAY(head, elm); \ - SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ - } \ - return (elm); \ - } \ - return (NULL); \ -} \ - \ -void \ -name##_SPLAY(struct name *head, struct type *elm) \ -{ \ - struct type __node, *__left, *__right, *__tmp; \ - int __comp; \ -\ - SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ - __left = __right = &__node; \ -\ - while ((__comp = (cmp)(elm, (head)->sph_root))) { \ - if (__comp < 0) { \ - __tmp = SPLAY_LEFT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if ((cmp)(elm, __tmp) < 0){ \ - SPLAY_ROTATE_RIGHT(head, __tmp, field); \ - if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ - break; \ - } \ - SPLAY_LINKLEFT(head, __right, field); \ - } else if (__comp > 0) { \ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if ((cmp)(elm, __tmp) > 0){ \ - SPLAY_ROTATE_LEFT(head, __tmp, field); \ - if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ - break; \ - } \ - SPLAY_LINKRIGHT(head, __left, field); \ - } \ - } \ - SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ -} \ - \ -/* Splay with either the minimum or the maximum element \ - * Used to find minimum or maximum element in tree. \ - */ \ -void name##_SPLAY_MINMAX(struct name *head, int __comp) \ -{ \ - struct type __node, *__left, *__right, *__tmp; \ -\ - SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ - __left = __right = &__node; \ -\ - while (1) { \ - if (__comp < 0) { \ - __tmp = SPLAY_LEFT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if (__comp < 0){ \ - SPLAY_ROTATE_RIGHT(head, __tmp, field); \ - if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ - break; \ - } \ - SPLAY_LINKLEFT(head, __right, field); \ - } else if (__comp > 0) { \ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if (__comp > 0) { \ - SPLAY_ROTATE_LEFT(head, __tmp, field); \ - if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ - break; \ - } \ - SPLAY_LINKRIGHT(head, __left, field); \ - } \ - } \ - SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ -} +#define SPLAY_GENERATE(name, type, field, cmp) \ + struct type *name##_SPLAY_INSERT(struct name *head, struct type *elm) \ + { \ + if (SPLAY_EMPTY(head)) { \ + SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = \ + NULL; \ + } else { \ + int __comp; \ + name##_SPLAY(head, elm); \ + __comp = (cmp)(elm, (head)->sph_root); \ + if (__comp < 0) { \ + SPLAY_LEFT(elm, field) = \ + SPLAY_LEFT((head)->sph_root, field); \ + SPLAY_RIGHT(elm, field) = (head)->sph_root; \ + SPLAY_LEFT((head)->sph_root, field) = NULL; \ + } else if (__comp > 0) { \ + SPLAY_RIGHT(elm, field) = \ + SPLAY_RIGHT((head)->sph_root, field); \ + SPLAY_LEFT(elm, field) = (head)->sph_root; \ + SPLAY_RIGHT((head)->sph_root, field) = NULL; \ + } else \ + return ((head)->sph_root); \ + } \ + (head)->sph_root = (elm); \ + return (NULL); \ + } \ + \ + struct type *name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ + { \ + struct type *__tmp; \ + if (SPLAY_EMPTY(head)) \ + return (NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) { \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ + (head)->sph_root = \ + SPLAY_RIGHT((head)->sph_root, field); \ + } else { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + (head)->sph_root = \ + SPLAY_LEFT((head)->sph_root, field); \ + name##_SPLAY(head, elm); \ + SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ + } \ + return (elm); \ + } \ + return (NULL); \ + } \ + \ + void name##_SPLAY(struct name *head, struct type *elm) \ + { \ + struct type __node, *__left, *__right, *__tmp; \ + int __comp; \ + \ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = \ + NULL; \ + __left = __right = &__node; \ + \ + while ((__comp = (cmp)(elm, (head)->sph_root))) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) < 0) { \ + SPLAY_ROTATE_RIGHT(head, __tmp, \ + field); \ + if (SPLAY_LEFT((head)->sph_root, \ + field) \ + == NULL) \ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) > 0) { \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, \ + field) \ + == NULL) \ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ + } \ + \ + /* Splay with either the minimum or the maximum element \ + * Used to find minimum or maximum element in tree. \ + */ \ + void name##_SPLAY_MINMAX(struct name *head, int __comp) \ + { \ + struct type __node, *__left, *__right, *__tmp; \ + \ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = \ + NULL; \ + __left = __right = &__node; \ + \ + while (1) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp < 0) { \ + SPLAY_ROTATE_RIGHT(head, __tmp, \ + field); \ + if (SPLAY_LEFT((head)->sph_root, \ + field) \ + == NULL) \ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp > 0) { \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, \ + field) \ + == NULL) \ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ + } #define SPLAY_NEGINF -1 #define SPLAY_INF 1 @@ -277,14 +303,13 @@ void name##_SPLAY_MINMAX(struct name *head, int __comp) \ #define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) #define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) #define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) -#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ - : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) -#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ - : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) - -#define SPLAY_FOREACH(x, name, head) \ - for ((x) = SPLAY_MIN(name, head); \ - (x) != NULL; \ +#define SPLAY_MIN(name, x) \ + (SPLAY_EMPTY(x) ? NULL : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) +#define SPLAY_MAX(name, x) \ + (SPLAY_EMPTY(x) ? NULL : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) + +#define SPLAY_FOREACH(x, name, head) \ + for ((x) = SPLAY_MIN(name, head); (x) != NULL; \ (x) = SPLAY_NEXT(name, head, x)) /* @@ -307,203 +332,197 @@ void name##_SPLAY_MINMAX(struct name *head, int __comp) \ #define RB_RED 1 struct rb_type { - int (*t_compare)(const void *, const void *); - void (*t_augment)(void *); - unsigned int t_offset; /* offset of rb_entry in type */ + int (*t_compare)(const void *, const void *); + void (*t_augment)(void *); + unsigned int t_offset; /* offset of rb_entry in type */ }; struct rbt_tree { - struct rb_entry *rbt_root; + struct rb_entry *rbt_root; }; struct rb_entry { - struct rb_entry *rbt_parent; - struct rb_entry *rbt_left; - struct rb_entry *rbt_right; - unsigned int rbt_color; + struct rb_entry *rbt_parent; + struct rb_entry *rbt_left; + struct rb_entry *rbt_right; + unsigned int rbt_color; }; -#define RB_HEAD(_name, _type) \ -struct _name { \ - struct rbt_tree rbh_root; \ -} +#define RB_HEAD(_name, _type) \ + struct _name { \ + struct rbt_tree rbh_root; \ + } #define RB_ENTRY(_type) struct rb_entry -static inline void -_rb_init(struct rbt_tree *rbt) +static inline void _rb_init(struct rbt_tree *rbt) { rbt->rbt_root = NULL; } -static inline int -_rb_empty(struct rbt_tree *rbt) +static inline int _rb_empty(struct rbt_tree *rbt) { return (rbt->rbt_root == NULL); } -void *_rb_insert(const struct rb_type *, struct rbt_tree *, void *); -void *_rb_remove(const struct rb_type *, struct rbt_tree *, void *); -void *_rb_find(const struct rb_type *, struct rbt_tree *, const void *); -void *_rb_nfind(const struct rb_type *, struct rbt_tree *, const void *); -void *_rb_root(const struct rb_type *, struct rbt_tree *); -void *_rb_min(const struct rb_type *, struct rbt_tree *); -void *_rb_max(const struct rb_type *, struct rbt_tree *); -void *_rb_next(const struct rb_type *, void *); -void *_rb_prev(const struct rb_type *, void *); -void *_rb_left(const struct rb_type *, void *); -void *_rb_right(const struct rb_type *, void *); -void *_rb_parent(const struct rb_type *, void *); -void _rb_set_left(const struct rb_type *, void *, void *); -void _rb_set_right(const struct rb_type *, void *, void *); -void _rb_set_parent(const struct rb_type *, void *, void *); -void _rb_poison(const struct rb_type *, void *, unsigned long); -int _rb_check(const struct rb_type *, void *, unsigned long); +void *_rb_insert(const struct rb_type *, struct rbt_tree *, void *); +void *_rb_remove(const struct rb_type *, struct rbt_tree *, void *); +void *_rb_find(const struct rb_type *, struct rbt_tree *, const void *); +void *_rb_nfind(const struct rb_type *, struct rbt_tree *, const void *); +void *_rb_root(const struct rb_type *, struct rbt_tree *); +void *_rb_min(const struct rb_type *, struct rbt_tree *); +void *_rb_max(const struct rb_type *, struct rbt_tree *); +void *_rb_next(const struct rb_type *, void *); +void *_rb_prev(const struct rb_type *, void *); +void *_rb_left(const struct rb_type *, void *); +void *_rb_right(const struct rb_type *, void *); +void *_rb_parent(const struct rb_type *, void *); +void _rb_set_left(const struct rb_type *, void *, void *); +void _rb_set_right(const struct rb_type *, void *, void *); +void _rb_set_parent(const struct rb_type *, void *, void *); +void _rb_poison(const struct rb_type *, void *, unsigned long); +int _rb_check(const struct rb_type *, void *, unsigned long); #define RB_INITIALIZER(_head) { { NULL } } -#define RB_PROTOTYPE(_name, _type, _field, _cmp) \ -extern const struct rb_type *const _name##_RB_TYPE; \ - \ -__attribute__((__unused__)) static inline void \ -_name##_RB_INIT(struct _name *head) \ -{ \ - _rb_init(&head->rbh_root); \ -} \ - \ -__attribute__((__unused__)) static inline struct _type * \ -_name##_RB_INSERT(struct _name *head, struct _type *elm) \ -{ \ - return _rb_insert(_name##_RB_TYPE, &head->rbh_root, elm); \ -} \ - \ -__attribute__((__unused__)) static inline struct _type * \ -_name##_RB_REMOVE(struct _name *head, struct _type *elm) \ -{ \ - return _rb_remove(_name##_RB_TYPE, &head->rbh_root, elm); \ -} \ - \ -__attribute__((__unused__)) static inline struct _type * \ -_name##_RB_FIND(struct _name *head, const struct _type *key) \ -{ \ - return _rb_find(_name##_RB_TYPE, &head->rbh_root, key); \ -} \ - \ -__attribute__((__unused__)) static inline struct _type * \ -_name##_RB_NFIND(struct _name *head, const struct _type *key) \ -{ \ - return _rb_nfind(_name##_RB_TYPE, &head->rbh_root, key); \ -} \ - \ -__attribute__((__unused__)) static inline struct _type * \ -_name##_RB_ROOT(struct _name *head) \ -{ \ - return _rb_root(_name##_RB_TYPE, &head->rbh_root); \ -} \ - \ -__attribute__((__unused__)) static inline int \ -_name##_RB_EMPTY(struct _name *head) \ -{ \ - return _rb_empty(&head->rbh_root); \ -} \ - \ -__attribute__((__unused__)) static inline struct _type * \ -_name##_RB_MIN(struct _name *head) \ -{ \ - return _rb_min(_name##_RB_TYPE, &head->rbh_root); \ -} \ - \ -__attribute__((__unused__)) static inline struct _type * \ -_name##_RB_MAX(struct _name *head) \ -{ \ - return _rb_max(_name##_RB_TYPE, &head->rbh_root); \ -} \ - \ -__attribute__((__unused__)) static inline struct _type * \ -_name##_RB_NEXT(struct _type *elm) \ -{ \ - return _rb_next(_name##_RB_TYPE, elm); \ -} \ - \ -__attribute__((__unused__)) static inline struct _type * \ -_name##_RB_PREV(struct _type *elm) \ -{ \ - return _rb_prev(_name##_RB_TYPE, elm); \ -} \ - \ -__attribute__((__unused__)) static inline struct _type * \ -_name##_RB_LEFT(struct _type *elm) \ -{ \ - return _rb_left(_name##_RB_TYPE, elm); \ -} \ - \ -__attribute__((__unused__)) static inline struct _type * \ -_name##_RB_RIGHT(struct _type *elm) \ -{ \ - return _rb_right(_name##_RB_TYPE, elm); \ -} \ - \ -__attribute__((__unused__)) static inline struct _type * \ -_name##_RB_PARENT(struct _type *elm) \ -{ \ - return _rb_parent(_name##_RB_TYPE, elm); \ -} \ - \ -__attribute__((__unused__)) static inline void \ -_name##_RB_SET_LEFT(struct _type *elm, struct _type *left) \ -{ \ - return _rb_set_left(_name##_RB_TYPE, elm, left); \ -} \ - \ -__attribute__((__unused__)) static inline void \ -_name##_RB_SET_RIGHT(struct _type *elm, struct _type *right) \ -{ \ - return _rb_set_right(_name##_RB_TYPE, elm, right); \ -} \ - \ -__attribute__((__unused__)) static inline void \ -_name##_RB_SET_PARENT(struct _type *elm, struct _type *parent) \ -{ \ - return _rb_set_parent(_name##_RB_TYPE, elm, parent); \ -} \ - \ -__attribute__((__unused__)) static inline void \ -_name##_RB_POISON(struct _type *elm, unsigned long poison) \ -{ \ - return _rb_poison(_name##_RB_TYPE, elm, poison); \ -} \ - \ -__attribute__((__unused__)) static inline int \ -_name##_RB_CHECK(struct _type *elm, unsigned long poison) \ -{ \ - return _rb_check(_name##_RB_TYPE, elm, poison); \ -} - -#define RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, _aug) \ -static int \ -_name##_RB_COMPARE(const void *lptr, const void *rptr) \ -{ \ - const struct _type *l = lptr, *r = rptr; \ - return _cmp(l, r); \ -} \ -static const struct rb_type _name##_RB_INFO = { \ - _name##_RB_COMPARE, \ - _aug, \ - offsetof(struct _type, _field), \ -}; \ -const struct rb_type *const _name##_RB_TYPE = &_name##_RB_INFO; - -#define RB_GENERATE_AUGMENT(_name, _type, _field, _cmp, _aug) \ -static void \ -_name##_RB_AUGMENT(void *ptr) \ -{ \ - struct _type *p = ptr; \ - return _aug(p); \ -} \ -RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, _name##_RB_AUGMENT) - -#define RB_GENERATE(_name, _type, _field, _cmp) \ - RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, NULL) +#define RB_PROTOTYPE(_name, _type, _field, _cmp) \ + extern const struct rb_type *const _name##_RB_TYPE; \ + \ + __attribute__((__unused__)) static inline void _name##_RB_INIT( \ + struct _name *head) \ + { \ + _rb_init(&head->rbh_root); \ + } \ + \ + __attribute__((__unused__)) static inline struct _type \ + *_name##_RB_INSERT(struct _name *head, struct _type *elm) \ + { \ + return _rb_insert(_name##_RB_TYPE, &head->rbh_root, elm); \ + } \ + \ + __attribute__((__unused__)) static inline struct _type \ + *_name##_RB_REMOVE(struct _name *head, struct _type *elm) \ + { \ + return _rb_remove(_name##_RB_TYPE, &head->rbh_root, elm); \ + } \ + \ + __attribute__((__unused__)) static inline struct _type \ + *_name##_RB_FIND(struct _name *head, const struct _type *key) \ + { \ + return _rb_find(_name##_RB_TYPE, &head->rbh_root, key); \ + } \ + \ + __attribute__((__unused__)) static inline struct _type \ + *_name##_RB_NFIND(struct _name *head, const struct _type *key) \ + { \ + return _rb_nfind(_name##_RB_TYPE, &head->rbh_root, key); \ + } \ + \ + __attribute__((__unused__)) static inline struct _type \ + *_name##_RB_ROOT(struct _name *head) \ + { \ + return _rb_root(_name##_RB_TYPE, &head->rbh_root); \ + } \ + \ + __attribute__((__unused__)) static inline int _name##_RB_EMPTY( \ + struct _name *head) \ + { \ + return _rb_empty(&head->rbh_root); \ + } \ + \ + __attribute__((__unused__)) static inline struct _type \ + *_name##_RB_MIN(struct _name *head) \ + { \ + return _rb_min(_name##_RB_TYPE, &head->rbh_root); \ + } \ + \ + __attribute__((__unused__)) static inline struct _type \ + *_name##_RB_MAX(struct _name *head) \ + { \ + return _rb_max(_name##_RB_TYPE, &head->rbh_root); \ + } \ + \ + __attribute__((__unused__)) static inline struct _type \ + *_name##_RB_NEXT(struct _type *elm) \ + { \ + return _rb_next(_name##_RB_TYPE, elm); \ + } \ + \ + __attribute__((__unused__)) static inline struct _type \ + *_name##_RB_PREV(struct _type *elm) \ + { \ + return _rb_prev(_name##_RB_TYPE, elm); \ + } \ + \ + __attribute__((__unused__)) static inline struct _type \ + *_name##_RB_LEFT(struct _type *elm) \ + { \ + return _rb_left(_name##_RB_TYPE, elm); \ + } \ + \ + __attribute__((__unused__)) static inline struct _type \ + *_name##_RB_RIGHT(struct _type *elm) \ + { \ + return _rb_right(_name##_RB_TYPE, elm); \ + } \ + \ + __attribute__((__unused__)) static inline struct _type \ + *_name##_RB_PARENT(struct _type *elm) \ + { \ + return _rb_parent(_name##_RB_TYPE, elm); \ + } \ + \ + __attribute__((__unused__)) static inline void _name##_RB_SET_LEFT( \ + struct _type *elm, struct _type *left) \ + { \ + return _rb_set_left(_name##_RB_TYPE, elm, left); \ + } \ + \ + __attribute__((__unused__)) static inline void _name##_RB_SET_RIGHT( \ + struct _type *elm, struct _type *right) \ + { \ + return _rb_set_right(_name##_RB_TYPE, elm, right); \ + } \ + \ + __attribute__((__unused__)) static inline void _name##_RB_SET_PARENT( \ + struct _type *elm, struct _type *parent) \ + { \ + return _rb_set_parent(_name##_RB_TYPE, elm, parent); \ + } \ + \ + __attribute__((__unused__)) static inline void _name##_RB_POISON( \ + struct _type *elm, unsigned long poison) \ + { \ + return _rb_poison(_name##_RB_TYPE, elm, poison); \ + } \ + \ + __attribute__((__unused__)) static inline int _name##_RB_CHECK( \ + struct _type *elm, unsigned long poison) \ + { \ + return _rb_check(_name##_RB_TYPE, elm, poison); \ + } + +#define RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, _aug) \ + static int _name##_RB_COMPARE(const void *lptr, const void *rptr) \ + { \ + const struct _type *l = lptr, *r = rptr; \ + return _cmp(l, r); \ + } \ + static const struct rb_type _name##_RB_INFO = { \ + _name##_RB_COMPARE, _aug, offsetof(struct _type, _field), \ + }; \ + const struct rb_type *const _name##_RB_TYPE = &_name##_RB_INFO; + +#define RB_GENERATE_AUGMENT(_name, _type, _field, _cmp, _aug) \ + static void _name##_RB_AUGMENT(void *ptr) \ + { \ + struct _type *p = ptr; \ + return _aug(p); \ + } \ + RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, _name##_RB_AUGMENT) + +#define RB_GENERATE(_name, _type, _field, _cmp) \ + RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, NULL) #define RB_INIT(_name, _head) _name##_RB_INIT(_head) #define RB_INSERT(_name, _head, _elm) _name##_RB_INSERT(_head, _elm) @@ -525,24 +544,20 @@ RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, _name##_RB_AUGMENT) #define RB_POISON(_name, _elm, _p) _name##_RB_POISON(_elm, _p) #define RB_CHECK(_name, _elm, _p) _name##_RB_CHECK(_elm, _p) -#define RB_FOREACH(_e, _name, _head) \ - for ((_e) = RB_MIN(_name, (_head)); \ - (_e) != NULL; \ +#define RB_FOREACH(_e, _name, _head) \ + for ((_e) = RB_MIN(_name, (_head)); (_e) != NULL; \ (_e) = RB_NEXT(_name, (_e))) -#define RB_FOREACH_SAFE(_e, _name, _head, _n) \ - for ((_e) = RB_MIN(_name, (_head)); \ - (_e) != NULL && ((_n) = RB_NEXT(_name, (_e)), 1); \ - (_e) = (_n)) +#define RB_FOREACH_SAFE(_e, _name, _head, _n) \ + for ((_e) = RB_MIN(_name, (_head)); \ + (_e) != NULL && ((_n) = RB_NEXT(_name, (_e)), 1); (_e) = (_n)) -#define RB_FOREACH_REVERSE(_e, _name, _head) \ - for ((_e) = RB_MAX(_name, (_head)); \ - (_e) != NULL; \ +#define RB_FOREACH_REVERSE(_e, _name, _head) \ + for ((_e) = RB_MAX(_name, (_head)); (_e) != NULL; \ (_e) = RB_PREV(_name, (_e))) -#define RB_FOREACH_REVERSE_SAFE(_e, _name, _head, _n) \ - for ((_e) = RB_MAX(_name, (_head)); \ - (_e) != NULL && ((_n) = RB_PREV(_name, (_e)), 1); \ - (_e) = (_n)) +#define RB_FOREACH_REVERSE_SAFE(_e, _name, _head, _n) \ + for ((_e) = RB_MAX(_name, (_head)); \ + (_e) != NULL && ((_n) = RB_PREV(_name, (_e)), 1); (_e) = (_n)) -#endif /* _SYS_TREE_H_ */ +#endif /* _SYS_TREE_H_ */ diff --git a/lib/pid_output.c b/lib/pid_output.c index 7369e23c2..e2e443415 100644 --- a/lib/pid_output.c +++ b/lib/pid_output.c @@ -27,53 +27,50 @@ #define PIDFILE_MASK 0644 -pid_t -pid_output (const char *path) +pid_t pid_output(const char *path) { - int tmp; - int fd; - pid_t pid; - char buf[16]; - struct flock lock; - mode_t oldumask; + int tmp; + int fd; + pid_t pid; + char buf[16]; + struct flock lock; + mode_t oldumask; - pid = getpid (); + pid = getpid(); - oldumask = umask(0777 & ~PIDFILE_MASK); - fd = open (path, O_RDWR | O_CREAT, PIDFILE_MASK); - if (fd < 0) - { - zlog_err("Can't create pid lock file %s (%s), exiting", - path, safe_strerror(errno)); - umask(oldumask); - exit(1); - } - else - { - size_t pidsize; + oldumask = umask(0777 & ~PIDFILE_MASK); + fd = open(path, O_RDWR | O_CREAT, PIDFILE_MASK); + if (fd < 0) { + zlog_err("Can't create pid lock file %s (%s), exiting", path, + safe_strerror(errno)); + umask(oldumask); + exit(1); + } else { + size_t pidsize; - umask(oldumask); - memset (&lock, 0, sizeof(lock)); + umask(oldumask); + memset(&lock, 0, sizeof(lock)); - set_cloexec(fd); + set_cloexec(fd); - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; - if (fcntl(fd, F_SETLK, &lock) < 0) - { - zlog_err("Could not lock pid_file %s, exiting", path); - exit(1); - } + if (fcntl(fd, F_SETLK, &lock) < 0) { + zlog_err("Could not lock pid_file %s, exiting", path); + exit(1); + } - sprintf (buf, "%d\n", (int) pid); - pidsize = strlen(buf); - if ((tmp = write (fd, buf, pidsize)) != (int)pidsize) - zlog_err("Could not write pid %d to pid_file %s, rc was %d: %s", - (int)pid,path,tmp,safe_strerror(errno)); - else if (ftruncate(fd, pidsize) < 0) - zlog_err("Could not truncate pid_file %s to %u bytes: %s", - path,(u_int)pidsize,safe_strerror(errno)); - } - return pid; + sprintf(buf, "%d\n", (int)pid); + pidsize = strlen(buf); + if ((tmp = write(fd, buf, pidsize)) != (int)pidsize) + zlog_err( + "Could not write pid %d to pid_file %s, rc was %d: %s", + (int)pid, path, tmp, safe_strerror(errno)); + else if (ftruncate(fd, pidsize) < 0) + zlog_err( + "Could not truncate pid_file %s to %u bytes: %s", + path, (u_int)pidsize, safe_strerror(errno)); + } + return pid; } diff --git a/lib/plist.c b/lib/plist.c index 96c60a489..d7a0db680 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -33,10 +33,10 @@ #include "plist_int.h" -DEFINE_MTYPE_STATIC(LIB, PREFIX_LIST, "Prefix List") -DEFINE_MTYPE_STATIC(LIB, MPREFIX_LIST_STR, "Prefix List Str") +DEFINE_MTYPE_STATIC(LIB, PREFIX_LIST, "Prefix List") +DEFINE_MTYPE_STATIC(LIB, MPREFIX_LIST_STR, "Prefix List Str") DEFINE_MTYPE_STATIC(LIB, PREFIX_LIST_ENTRY, "Prefix List Entry") -DEFINE_MTYPE_STATIC(LIB, PREFIX_LIST_TRIE, "Prefix List Trie Table") +DEFINE_MTYPE_STATIC(LIB, PREFIX_LIST_TRIE, "Prefix List Trie Table") /* not currently changeable, code assumes bytes further down */ #define PLC_BITS 8 @@ -59,1357 +59,1235 @@ struct pltrie_table { }; /* List of struct prefix_list. */ -struct prefix_list_list -{ - struct prefix_list *head; - struct prefix_list *tail; +struct prefix_list_list { + struct prefix_list *head; + struct prefix_list *tail; }; /* Master structure of prefix_list. */ -struct prefix_master -{ - /* List of prefix_list which name is number. */ - struct prefix_list_list num; +struct prefix_master { + /* List of prefix_list which name is number. */ + struct prefix_list_list num; - /* List of prefix_list which name is string. */ - struct prefix_list_list str; + /* List of prefix_list which name is string. */ + struct prefix_list_list str; - /* Whether sequential number is used. */ - int seqnum; + /* Whether sequential number is used. */ + int seqnum; - /* The latest update. */ - struct prefix_list *recent; + /* The latest update. */ + struct prefix_list *recent; - /* Hook function which is executed when new prefix_list is added. */ - void (*add_hook) (struct prefix_list *); + /* Hook function which is executed when new prefix_list is added. */ + void (*add_hook)(struct prefix_list *); - /* Hook function which is executed when prefix_list is deleted. */ - void (*delete_hook) (struct prefix_list *); + /* Hook function which is executed when prefix_list is deleted. */ + void (*delete_hook)(struct prefix_list *); - /* number of bytes that have a trie level */ - size_t trie_depth; + /* number of bytes that have a trie level */ + size_t trie_depth; }; /* Static structure of IPv4 prefix_list's master. */ -static struct prefix_master prefix_master_ipv4 = -{ - {NULL, NULL}, - {NULL, NULL}, - 1, - NULL, - NULL, - NULL, - PLC_MAXLEVELV4, +static struct prefix_master prefix_master_ipv4 = { + {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV4, }; /* Static structure of IPv6 prefix-list's master. */ -static struct prefix_master prefix_master_ipv6 = -{ - {NULL, NULL}, - {NULL, NULL}, - 1, - NULL, - NULL, - NULL, - PLC_MAXLEVELV6, +static struct prefix_master prefix_master_ipv6 = { + {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV6, }; /* Static structure of BGP ORF prefix_list's master. */ -static struct prefix_master prefix_master_orf_v4 = -{ - {NULL, NULL}, - {NULL, NULL}, - 1, - NULL, - NULL, - NULL, - PLC_MAXLEVELV4, +static struct prefix_master prefix_master_orf_v4 = { + {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV4, }; /* Static structure of BGP ORF prefix_list's master. */ -static struct prefix_master prefix_master_orf_v6 = -{ - {NULL, NULL}, - {NULL, NULL}, - 1, - NULL, - NULL, - NULL, - PLC_MAXLEVELV6, +static struct prefix_master prefix_master_orf_v6 = { + {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV6, }; -static struct prefix_master * -prefix_master_get (afi_t afi, int orf) +static struct prefix_master *prefix_master_get(afi_t afi, int orf) { - if (afi == AFI_IP) - return orf ? &prefix_master_orf_v4 : &prefix_master_ipv4; - if (afi == AFI_IP6) - return orf ? &prefix_master_orf_v6 : &prefix_master_ipv6; - return NULL; + if (afi == AFI_IP) + return orf ? &prefix_master_orf_v4 : &prefix_master_ipv4; + if (afi == AFI_IP6) + return orf ? &prefix_master_orf_v6 : &prefix_master_ipv6; + return NULL; } -const char *prefix_list_name (struct prefix_list *plist) +const char *prefix_list_name(struct prefix_list *plist) { - return plist->name; + return plist->name; } /* Lookup prefix_list from list of prefix_list by name. */ -static struct prefix_list * -prefix_list_lookup_do (afi_t afi, int orf, const char *name) +static struct prefix_list *prefix_list_lookup_do(afi_t afi, int orf, + const char *name) { - struct prefix_list *plist; - struct prefix_master *master; + struct prefix_list *plist; + struct prefix_master *master; - if (name == NULL) - return NULL; + if (name == NULL) + return NULL; - master = prefix_master_get (afi, orf); - if (master == NULL) - return NULL; + master = prefix_master_get(afi, orf); + if (master == NULL) + return NULL; - for (plist = master->num.head; plist; plist = plist->next) - if (strcmp (plist->name, name) == 0) - return plist; + for (plist = master->num.head; plist; plist = plist->next) + if (strcmp(plist->name, name) == 0) + return plist; - for (plist = master->str.head; plist; plist = plist->next) - if (strcmp (plist->name, name) == 0) - return plist; + for (plist = master->str.head; plist; plist = plist->next) + if (strcmp(plist->name, name) == 0) + return plist; - return NULL; + return NULL; } -struct prefix_list * -prefix_list_lookup (afi_t afi, const char *name) +struct prefix_list *prefix_list_lookup(afi_t afi, const char *name) { - return prefix_list_lookup_do (afi, 0, name); + return prefix_list_lookup_do(afi, 0, name); } -struct prefix_list * -prefix_bgp_orf_lookup (afi_t afi, const char *name) +struct prefix_list *prefix_bgp_orf_lookup(afi_t afi, const char *name) { - return prefix_list_lookup_do (afi, 1, name); + return prefix_list_lookup_do(afi, 1, name); } -static struct prefix_list * -prefix_list_new (void) +static struct prefix_list *prefix_list_new(void) { - struct prefix_list *new; + struct prefix_list *new; - new = XCALLOC (MTYPE_PREFIX_LIST, sizeof (struct prefix_list)); - return new; + new = XCALLOC(MTYPE_PREFIX_LIST, sizeof(struct prefix_list)); + return new; } -static void -prefix_list_free (struct prefix_list *plist) +static void prefix_list_free(struct prefix_list *plist) { - XFREE (MTYPE_PREFIX_LIST, plist); + XFREE(MTYPE_PREFIX_LIST, plist); } -static struct prefix_list_entry * -prefix_list_entry_new (void) +static struct prefix_list_entry *prefix_list_entry_new(void) { - struct prefix_list_entry *new; + struct prefix_list_entry *new; - new = XCALLOC (MTYPE_PREFIX_LIST_ENTRY, sizeof (struct prefix_list_entry)); - return new; + new = XCALLOC(MTYPE_PREFIX_LIST_ENTRY, + sizeof(struct prefix_list_entry)); + return new; } -static void -prefix_list_entry_free (struct prefix_list_entry *pentry) +static void prefix_list_entry_free(struct prefix_list_entry *pentry) { - XFREE (MTYPE_PREFIX_LIST_ENTRY, pentry); + XFREE(MTYPE_PREFIX_LIST_ENTRY, pentry); } /* Insert new prefix list to list of prefix_list. Each prefix_list is sorted by the name. */ -static struct prefix_list * -prefix_list_insert (afi_t afi, int orf, const char *name) -{ - unsigned int i; - long number; - struct prefix_list *plist; - struct prefix_list *point; - struct prefix_list_list *list; - struct prefix_master *master; - - master = prefix_master_get (afi, orf); - if (master == NULL) - return NULL; - - /* Allocate new prefix_list and copy given name. */ - plist = prefix_list_new (); - plist->name = XSTRDUP (MTYPE_MPREFIX_LIST_STR, name); - plist->master = master; - plist->trie = XCALLOC (MTYPE_PREFIX_LIST_TRIE, sizeof (struct pltrie_table)); - - /* If name is made by all digit character. We treat it as - number. */ - for (number = 0, i = 0; i < strlen (name); i++) - { - if (isdigit ((int) name[i])) - number = (number * 10) + (name[i] - '0'); - else - break; - } - - /* In case of name is all digit character */ - if (i == strlen (name)) - { - plist->type = PREFIX_TYPE_NUMBER; - - /* Set prefix_list to number list. */ - list = &master->num; - - for (point = list->head; point; point = point->next) - if (atol (point->name) >= number) - break; - } - else - { - plist->type = PREFIX_TYPE_STRING; - - /* Set prefix_list to string list. */ - list = &master->str; - - /* Set point to insertion point. */ - for (point = list->head; point; point = point->next) - if (strcmp (point->name, name) >= 0) - break; - } - - /* In case of this is the first element of master. */ - if (list->head == NULL) - { - list->head = list->tail = plist; - return plist; - } - - /* In case of insertion is made at the tail of access_list. */ - if (point == NULL) - { - plist->prev = list->tail; - list->tail->next = plist; - list->tail = plist; - return plist; - } - - /* In case of insertion is made at the head of access_list. */ - if (point == list->head) - { - plist->next = list->head; - list->head->prev = plist; - list->head = plist; - return plist; - } - - /* Insertion is made at middle of the access_list. */ - plist->next = point; - plist->prev = point->prev; - - if (point->prev) - point->prev->next = plist; - point->prev = plist; - - return plist; -} - -static struct prefix_list * -prefix_list_get (afi_t afi, int orf, const char *name) -{ - struct prefix_list *plist; - - plist = prefix_list_lookup_do (afi, orf, name); - - if (plist == NULL) - plist = prefix_list_insert (afi, orf, name); - return plist; -} - -static void prefix_list_trie_del (struct prefix_list *plist, - struct prefix_list_entry *pentry); +static struct prefix_list *prefix_list_insert(afi_t afi, int orf, + const char *name) +{ + unsigned int i; + long number; + struct prefix_list *plist; + struct prefix_list *point; + struct prefix_list_list *list; + struct prefix_master *master; + + master = prefix_master_get(afi, orf); + if (master == NULL) + return NULL; + + /* Allocate new prefix_list and copy given name. */ + plist = prefix_list_new(); + plist->name = XSTRDUP(MTYPE_MPREFIX_LIST_STR, name); + plist->master = master; + plist->trie = + XCALLOC(MTYPE_PREFIX_LIST_TRIE, sizeof(struct pltrie_table)); + + /* If name is made by all digit character. We treat it as + number. */ + for (number = 0, i = 0; i < strlen(name); i++) { + if (isdigit((int)name[i])) + number = (number * 10) + (name[i] - '0'); + else + break; + } -/* Delete prefix-list from prefix_list_master and free it. */ -static void -prefix_list_delete (struct prefix_list *plist) + /* In case of name is all digit character */ + if (i == strlen(name)) { + plist->type = PREFIX_TYPE_NUMBER; + + /* Set prefix_list to number list. */ + list = &master->num; + + for (point = list->head; point; point = point->next) + if (atol(point->name) >= number) + break; + } else { + plist->type = PREFIX_TYPE_STRING; + + /* Set prefix_list to string list. */ + list = &master->str; + + /* Set point to insertion point. */ + for (point = list->head; point; point = point->next) + if (strcmp(point->name, name) >= 0) + break; + } + + /* In case of this is the first element of master. */ + if (list->head == NULL) { + list->head = list->tail = plist; + return plist; + } + + /* In case of insertion is made at the tail of access_list. */ + if (point == NULL) { + plist->prev = list->tail; + list->tail->next = plist; + list->tail = plist; + return plist; + } + + /* In case of insertion is made at the head of access_list. */ + if (point == list->head) { + plist->next = list->head; + list->head->prev = plist; + list->head = plist; + return plist; + } + + /* Insertion is made at middle of the access_list. */ + plist->next = point; + plist->prev = point->prev; + + if (point->prev) + point->prev->next = plist; + point->prev = plist; + + return plist; +} + +static struct prefix_list *prefix_list_get(afi_t afi, int orf, const char *name) { - struct prefix_list_list *list; - struct prefix_master *master; - struct prefix_list_entry *pentry; - struct prefix_list_entry *next; + struct prefix_list *plist; + + plist = prefix_list_lookup_do(afi, orf, name); - /* If prefix-list contain prefix_list_entry free all of it. */ - for (pentry = plist->head; pentry; pentry = next) - { - next = pentry->next; - prefix_list_trie_del (plist, pentry); - prefix_list_entry_free (pentry); - plist->count--; - } + if (plist == NULL) + plist = prefix_list_insert(afi, orf, name); + return plist; +} - master = plist->master; +static void prefix_list_trie_del(struct prefix_list *plist, + struct prefix_list_entry *pentry); + +/* Delete prefix-list from prefix_list_master and free it. */ +static void prefix_list_delete(struct prefix_list *plist) +{ + struct prefix_list_list *list; + struct prefix_master *master; + struct prefix_list_entry *pentry; + struct prefix_list_entry *next; + + /* If prefix-list contain prefix_list_entry free all of it. */ + for (pentry = plist->head; pentry; pentry = next) { + next = pentry->next; + prefix_list_trie_del(plist, pentry); + prefix_list_entry_free(pentry); + plist->count--; + } - if (plist->type == PREFIX_TYPE_NUMBER) - list = &master->num; - else - list = &master->str; + master = plist->master; - if (plist->next) - plist->next->prev = plist->prev; - else - list->tail = plist->prev; + if (plist->type == PREFIX_TYPE_NUMBER) + list = &master->num; + else + list = &master->str; - if (plist->prev) - plist->prev->next = plist->next; - else - list->head = plist->next; + if (plist->next) + plist->next->prev = plist->prev; + else + list->tail = plist->prev; - if (plist->desc) - XFREE (MTYPE_TMP, plist->desc); + if (plist->prev) + plist->prev->next = plist->next; + else + list->head = plist->next; - /* Make sure master's recent changed prefix-list information is - cleared. */ - master->recent = NULL; + if (plist->desc) + XFREE(MTYPE_TMP, plist->desc); - route_map_notify_dependencies(plist->name, RMAP_EVENT_PLIST_DELETED); + /* Make sure master's recent changed prefix-list information is + cleared. */ + master->recent = NULL; - if (master->delete_hook) - (*master->delete_hook) (plist); + route_map_notify_dependencies(plist->name, RMAP_EVENT_PLIST_DELETED); - if (plist->name) - XFREE (MTYPE_MPREFIX_LIST_STR, plist->name); + if (master->delete_hook) + (*master->delete_hook)(plist); - XFREE (MTYPE_PREFIX_LIST_TRIE, plist->trie); + if (plist->name) + XFREE(MTYPE_MPREFIX_LIST_STR, plist->name); - prefix_list_free (plist); + XFREE(MTYPE_PREFIX_LIST_TRIE, plist->trie); + prefix_list_free(plist); } static struct prefix_list_entry * -prefix_list_entry_make (struct prefix *prefix, enum prefix_list_type type, - int seq, int le, int ge, int any) +prefix_list_entry_make(struct prefix *prefix, enum prefix_list_type type, + int seq, int le, int ge, int any) { - struct prefix_list_entry *pentry; + struct prefix_list_entry *pentry; - pentry = prefix_list_entry_new (); + pentry = prefix_list_entry_new(); - if (any) - pentry->any = 1; + if (any) + pentry->any = 1; - prefix_copy (&pentry->prefix, prefix); - pentry->type = type; - pentry->seq = seq; - pentry->le = le; - pentry->ge = ge; + prefix_copy(&pentry->prefix, prefix); + pentry->type = type; + pentry->seq = seq; + pentry->le = le; + pentry->ge = ge; - return pentry; + return pentry; } /* Add hook function. */ -void -prefix_list_add_hook (void (*func) (struct prefix_list *plist)) +void prefix_list_add_hook(void (*func)(struct prefix_list *plist)) { - prefix_master_ipv4.add_hook = func; - prefix_master_ipv6.add_hook = func; + prefix_master_ipv4.add_hook = func; + prefix_master_ipv6.add_hook = func; } /* Delete hook function. */ -void -prefix_list_delete_hook (void (*func) (struct prefix_list *plist)) +void prefix_list_delete_hook(void (*func)(struct prefix_list *plist)) { - prefix_master_ipv4.delete_hook = func; - prefix_master_ipv6.delete_hook = func; + prefix_master_ipv4.delete_hook = func; + prefix_master_ipv6.delete_hook = func; } /* Calculate new sequential number. */ -static int -prefix_new_seq_get (struct prefix_list *plist) +static int prefix_new_seq_get(struct prefix_list *plist) { - int maxseq; - int newseq; - struct prefix_list_entry *pentry; + int maxseq; + int newseq; + struct prefix_list_entry *pentry; - maxseq = newseq = 0; + maxseq = newseq = 0; - for (pentry = plist->head; pentry; pentry = pentry->next) - { - if (maxseq < pentry->seq) - maxseq = pentry->seq; - } + for (pentry = plist->head; pentry; pentry = pentry->next) { + if (maxseq < pentry->seq) + maxseq = pentry->seq; + } - newseq = ((maxseq / 5) * 5) + 5; - - return newseq; + newseq = ((maxseq / 5) * 5) + 5; + + return newseq; } /* Return prefix list entry which has same seq number. */ -static struct prefix_list_entry * -prefix_seq_check (struct prefix_list *plist, int seq) +static struct prefix_list_entry *prefix_seq_check(struct prefix_list *plist, + int seq) { - struct prefix_list_entry *pentry; + struct prefix_list_entry *pentry; - for (pentry = plist->head; pentry; pentry = pentry->next) - if (pentry->seq == seq) - return pentry; - return NULL; + for (pentry = plist->head; pentry; pentry = pentry->next) + if (pentry->seq == seq) + return pentry; + return NULL; } static struct prefix_list_entry * -prefix_list_entry_lookup (struct prefix_list *plist, struct prefix *prefix, - enum prefix_list_type type, int seq, int le, int ge) +prefix_list_entry_lookup(struct prefix_list *plist, struct prefix *prefix, + enum prefix_list_type type, int seq, int le, int ge) { - struct prefix_list_entry *pentry; + struct prefix_list_entry *pentry; - for (pentry = plist->head; pentry; pentry = pentry->next) - if (prefix_same (&pentry->prefix, prefix) && pentry->type == type) - { - if (seq >= 0 && pentry->seq != seq) - continue; + for (pentry = plist->head; pentry; pentry = pentry->next) + if (prefix_same(&pentry->prefix, prefix) + && pentry->type == type) { + if (seq >= 0 && pentry->seq != seq) + continue; - if (pentry->le != le) - continue; - if (pentry->ge != ge) - continue; + if (pentry->le != le) + continue; + if (pentry->ge != ge) + continue; - return pentry; - } + return pentry; + } - return NULL; + return NULL; } -static void -trie_walk_affected (size_t validbits, struct pltrie_table *table, uint8_t byte, - struct prefix_list_entry *object, - void (*fn)(struct prefix_list_entry *object, - struct prefix_list_entry **updptr)) +static void trie_walk_affected(size_t validbits, struct pltrie_table *table, + uint8_t byte, struct prefix_list_entry *object, + void (*fn)(struct prefix_list_entry *object, + struct prefix_list_entry **updptr)) { - uint8_t mask; - uint16_t bwalk; + uint8_t mask; + uint16_t bwalk; - if (validbits > PLC_BITS) - { - fn (object, &table->entries[byte].final_chain); - return; - } + if (validbits > PLC_BITS) { + fn(object, &table->entries[byte].final_chain); + return; + } - mask = (1 << (8 - validbits)) - 1; - for (bwalk = byte & ~mask; bwalk <= byte + mask; bwalk++) - { - fn (object, &table->entries[bwalk].up_chain); - } + mask = (1 << (8 - validbits)) - 1; + for (bwalk = byte & ~mask; bwalk <= byte + mask; bwalk++) { + fn(object, &table->entries[bwalk].up_chain); + } } -static void trie_uninstall_fn (struct prefix_list_entry *object, - struct prefix_list_entry **updptr) +static void trie_uninstall_fn(struct prefix_list_entry *object, + struct prefix_list_entry **updptr) { - for (; *updptr; updptr = &(*updptr)->next_best) - if (*updptr == object) - { - *updptr = object->next_best; - break; - } + for (; *updptr; updptr = &(*updptr)->next_best) + if (*updptr == object) { + *updptr = object->next_best; + break; + } } -static int -trie_table_empty (struct pltrie_table *table) +static int trie_table_empty(struct pltrie_table *table) { - size_t i; - for (i = 0; i < PLC_LEN; i++) - if (table->entries[i].next_table || table->entries[i].up_chain) - return 0; - return 1; + size_t i; + for (i = 0; i < PLC_LEN; i++) + if (table->entries[i].next_table || table->entries[i].up_chain) + return 0; + return 1; +} + +static void prefix_list_trie_del(struct prefix_list *plist, + struct prefix_list_entry *pentry) +{ + size_t depth, maxdepth = plist->master->trie_depth; + uint8_t *bytes = &pentry->prefix.u.prefix; + size_t validbits = pentry->prefix.prefixlen; + struct pltrie_table *table, **tables[PLC_MAXLEVEL]; + + table = plist->trie; + for (depth = 0; validbits > PLC_BITS && depth < maxdepth - 1; depth++) { + uint8_t byte = bytes[depth]; + assert(table->entries[byte].next_table); + + tables[depth + 1] = &table->entries[byte].next_table; + table = table->entries[byte].next_table; + + validbits -= PLC_BITS; + } + + trie_walk_affected(validbits, table, bytes[depth], pentry, + trie_uninstall_fn); + + for (; depth > 0; depth--) + if (trie_table_empty(*tables[depth])) { + XFREE(MTYPE_PREFIX_LIST_TRIE, *tables[depth]); + *tables[depth] = NULL; + } } -static void -prefix_list_trie_del (struct prefix_list *plist, - struct prefix_list_entry *pentry) + +static void prefix_list_entry_delete(struct prefix_list *plist, + struct prefix_list_entry *pentry, + int update_list) { - size_t depth, maxdepth = plist->master->trie_depth; - uint8_t *bytes = &pentry->prefix.u.prefix; - size_t validbits = pentry->prefix.prefixlen; - struct pltrie_table *table, **tables[PLC_MAXLEVEL]; + if (plist == NULL || pentry == NULL) + return; + + prefix_list_trie_del(plist, pentry); - table = plist->trie; - for (depth = 0; validbits > PLC_BITS && depth < maxdepth - 1; depth++) - { - uint8_t byte = bytes[depth]; - assert (table->entries[byte].next_table); + if (pentry->prev) + pentry->prev->next = pentry->next; + else + plist->head = pentry->next; + if (pentry->next) + pentry->next->prev = pentry->prev; + else + plist->tail = pentry->prev; - tables[depth + 1] = &table->entries[byte].next_table; - table = table->entries[byte].next_table; + prefix_list_entry_free(pentry); - validbits -= PLC_BITS; - } + plist->count--; - trie_walk_affected (validbits, table, bytes[depth], pentry, trie_uninstall_fn); + if (update_list) { + route_map_notify_dependencies(plist->name, + RMAP_EVENT_PLIST_DELETED); + if (plist->master->delete_hook) + (*plist->master->delete_hook)(plist); - for (; depth > 0; depth--) - if (trie_table_empty (*tables[depth])) - { - XFREE (MTYPE_PREFIX_LIST_TRIE, *tables[depth]); - *tables[depth] = NULL; - } + if (plist->head == NULL && plist->tail == NULL + && plist->desc == NULL) + prefix_list_delete(plist); + else + plist->master->recent = plist; + } } +static void trie_install_fn(struct prefix_list_entry *object, + struct prefix_list_entry **updptr) +{ + while (*updptr) { + if (*updptr == object) + return; + if ((*updptr)->prefix.prefixlen < object->prefix.prefixlen) + break; + if ((*updptr)->seq > object->seq) + break; + updptr = &(*updptr)->next_best; + } + + if (!object->next_best) + object->next_best = *updptr; + else + assert(object->next_best == *updptr || !*updptr); + + *updptr = object; +} -static void -prefix_list_entry_delete (struct prefix_list *plist, - struct prefix_list_entry *pentry, - int update_list) +static void prefix_list_trie_add(struct prefix_list *plist, + struct prefix_list_entry *pentry) { - if (plist == NULL || pentry == NULL) - return; + size_t depth = plist->master->trie_depth; + uint8_t *bytes = &pentry->prefix.u.prefix; + size_t validbits = pentry->prefix.prefixlen; + struct pltrie_table *table; + + table = plist->trie; + while (validbits > PLC_BITS && depth > 1) { + if (!table->entries[*bytes].next_table) + table->entries[*bytes].next_table = + XCALLOC(MTYPE_PREFIX_LIST_TRIE, + sizeof(struct pltrie_table)); + table = table->entries[*bytes].next_table; + bytes++; + depth--; + validbits -= PLC_BITS; + } - prefix_list_trie_del (plist, pentry); + trie_walk_affected(validbits, table, *bytes, pentry, trie_install_fn); +} - if (pentry->prev) - pentry->prev->next = pentry->next; - else - plist->head = pentry->next; - if (pentry->next) - pentry->next->prev = pentry->prev; - else - plist->tail = pentry->prev; +static void prefix_list_entry_add(struct prefix_list *plist, + struct prefix_list_entry *pentry) +{ + struct prefix_list_entry *replace; + struct prefix_list_entry *point; - prefix_list_entry_free (pentry); + /* Automatic asignment of seq no. */ + if (pentry->seq == -1) + pentry->seq = prefix_new_seq_get(plist); - plist->count--; + if (plist->tail && pentry->seq > plist->tail->seq) + point = NULL; + else { + /* Is there any same seq prefix list entry? */ + replace = prefix_seq_check(plist, pentry->seq); + if (replace) + prefix_list_entry_delete(plist, replace, 0); - if (update_list) - { - route_map_notify_dependencies(plist->name, RMAP_EVENT_PLIST_DELETED); - if (plist->master->delete_hook) - (*plist->master->delete_hook) (plist); + /* Check insert point. */ + for (point = plist->head; point; point = point->next) + if (point->seq >= pentry->seq) + break; + } + + /* In case of this is the first element of the list. */ + pentry->next = point; + + if (point) { + if (point->prev) + point->prev->next = pentry; + else + plist->head = pentry; + + pentry->prev = point->prev; + point->prev = pentry; + } else { + if (plist->tail) + plist->tail->next = pentry; + else + plist->head = pentry; + + pentry->prev = plist->tail; + plist->tail = pentry; + } - if (plist->head == NULL && plist->tail == NULL && plist->desc == NULL) - prefix_list_delete (plist); - else + prefix_list_trie_add(plist, pentry); + + /* Increment count. */ + plist->count++; + + /* Run hook function. */ + if (plist->master->add_hook) + (*plist->master->add_hook)(plist); + + route_map_notify_dependencies(plist->name, RMAP_EVENT_PLIST_ADDED); plist->master->recent = plist; - } -} - -static void trie_install_fn (struct prefix_list_entry *object, - struct prefix_list_entry **updptr) -{ - while (*updptr) - { - if (*updptr == object) - return; - if ((*updptr)->prefix.prefixlen < object->prefix.prefixlen) - break; - if ((*updptr)->seq > object->seq) - break; - updptr = &(*updptr)->next_best; - } - - if (!object->next_best) - object->next_best = *updptr; - else - assert (object->next_best == *updptr || !*updptr); - - *updptr = object; -} - -static void -prefix_list_trie_add (struct prefix_list *plist, - struct prefix_list_entry *pentry) -{ - size_t depth = plist->master->trie_depth; - uint8_t *bytes = &pentry->prefix.u.prefix; - size_t validbits = pentry->prefix.prefixlen; - struct pltrie_table *table; - - table = plist->trie; - while (validbits > PLC_BITS && depth > 1) - { - if (!table->entries[*bytes].next_table) - table->entries[*bytes].next_table = XCALLOC (MTYPE_PREFIX_LIST_TRIE, - sizeof(struct pltrie_table)); - table = table->entries[*bytes].next_table; - bytes++; - depth--; - validbits -= PLC_BITS; - } - - trie_walk_affected (validbits, table, *bytes, pentry, trie_install_fn); -} - -static void -prefix_list_entry_add (struct prefix_list *plist, - struct prefix_list_entry *pentry) -{ - struct prefix_list_entry *replace; - struct prefix_list_entry *point; - - /* Automatic asignment of seq no. */ - if (pentry->seq == -1) - pentry->seq = prefix_new_seq_get (plist); - - if (plist->tail && pentry->seq > plist->tail->seq) - point = NULL; - else - { - /* Is there any same seq prefix list entry? */ - replace = prefix_seq_check (plist, pentry->seq); - if (replace) - prefix_list_entry_delete (plist, replace, 0); - - /* Check insert point. */ - for (point = plist->head; point; point = point->next) - if (point->seq >= pentry->seq) - break; - } - - /* In case of this is the first element of the list. */ - pentry->next = point; - - if (point) - { - if (point->prev) - point->prev->next = pentry; - else - plist->head = pentry; - - pentry->prev = point->prev; - point->prev = pentry; - } - else - { - if (plist->tail) - plist->tail->next = pentry; - else - plist->head = pentry; - - pentry->prev = plist->tail; - plist->tail = pentry; - } - - prefix_list_trie_add (plist, pentry); - - /* Increment count. */ - plist->count++; - - /* Run hook function. */ - if (plist->master->add_hook) - (*plist->master->add_hook) (plist); - - route_map_notify_dependencies(plist->name, RMAP_EVENT_PLIST_ADDED); - plist->master->recent = plist; } /* Return string of prefix_list_type. */ -static const char * -prefix_list_type_str (struct prefix_list_entry *pentry) -{ - switch (pentry->type) - { - case PREFIX_PERMIT: - return "permit"; - case PREFIX_DENY: - return "deny"; - default: - return ""; - } -} - -static int -prefix_list_entry_match (struct prefix_list_entry *pentry, struct prefix *p) -{ - int ret; - - ret = prefix_match (&pentry->prefix, p); - if (! ret) - return 0; - - /* In case of le nor ge is specified, exact match is performed. */ - if (! pentry->le && ! pentry->ge) - { - if (pentry->prefix.prefixlen != p->prefixlen) - return 0; - } - else - { - if (pentry->le) - if (p->prefixlen > pentry->le) - return 0; - - if (pentry->ge) - if (p->prefixlen < pentry->ge) - return 0; - } - return 1; -} - -enum prefix_list_type -prefix_list_apply (struct prefix_list *plist, void *object) -{ - struct prefix_list_entry *pentry, *pbest = NULL; - - struct prefix *p = (struct prefix *) object; - uint8_t *byte = &p->u.prefix; - size_t depth; - size_t validbits = p->prefixlen; - struct pltrie_table *table; - - if (plist == NULL) - return PREFIX_DENY; - - if (plist->count == 0) - return PREFIX_PERMIT; - - depth = plist->master->trie_depth; - table = plist->trie; - while (1) - { - for (pentry = table->entries[*byte].up_chain; pentry; pentry = pentry->next_best) - { - if (pbest && pbest->seq < pentry->seq) - continue; - if (prefix_list_entry_match (pentry, p)) - pbest = pentry; - } - - if (validbits <= PLC_BITS) - break; - validbits -= PLC_BITS; - - if (--depth) - { - if (!table->entries[*byte].next_table) - break; - - table = table->entries[*byte].next_table; - byte++; - continue; - } - - for (pentry = table->entries[*byte].final_chain; pentry; pentry = pentry->next_best) - { - if (pbest && pbest->seq < pentry->seq) - continue; - if (prefix_list_entry_match (pentry, p)) - pbest = pentry; - } - break; - } - - if (pbest == NULL) - return PREFIX_DENY; - - return pbest->type; -} - -static void __attribute__ ((unused)) -prefix_list_print (struct prefix_list *plist) -{ - struct prefix_list_entry *pentry; - - if (plist == NULL) - return; - - printf ("ip prefix-list %s: %d entries\n", plist->name, plist->count); - - for (pentry = plist->head; pentry; pentry = pentry->next) - { - if (pentry->any) - printf ("any %s\n", prefix_list_type_str (pentry)); - else - { - struct prefix *p; - char buf[BUFSIZ]; - - p = &pentry->prefix; - - printf (" seq %u %s %s/%d", - pentry->seq, - prefix_list_type_str (pentry), - inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), - p->prefixlen); - if (pentry->ge) - printf (" ge %d", pentry->ge); - if (pentry->le) - printf (" le %d", pentry->le); - printf ("\n"); +static const char *prefix_list_type_str(struct prefix_list_entry *pentry) +{ + switch (pentry->type) { + case PREFIX_PERMIT: + return "permit"; + case PREFIX_DENY: + return "deny"; + default: + return ""; + } +} + +static int prefix_list_entry_match(struct prefix_list_entry *pentry, + struct prefix *p) +{ + int ret; + + ret = prefix_match(&pentry->prefix, p); + if (!ret) + return 0; + + /* In case of le nor ge is specified, exact match is performed. */ + if (!pentry->le && !pentry->ge) { + if (pentry->prefix.prefixlen != p->prefixlen) + return 0; + } else { + if (pentry->le) + if (p->prefixlen > pentry->le) + return 0; + + if (pentry->ge) + if (p->prefixlen < pentry->ge) + return 0; + } + return 1; +} + +enum prefix_list_type prefix_list_apply(struct prefix_list *plist, void *object) +{ + struct prefix_list_entry *pentry, *pbest = NULL; + + struct prefix *p = (struct prefix *)object; + uint8_t *byte = &p->u.prefix; + size_t depth; + size_t validbits = p->prefixlen; + struct pltrie_table *table; + + if (plist == NULL) + return PREFIX_DENY; + + if (plist->count == 0) + return PREFIX_PERMIT; + + depth = plist->master->trie_depth; + table = plist->trie; + while (1) { + for (pentry = table->entries[*byte].up_chain; pentry; + pentry = pentry->next_best) { + if (pbest && pbest->seq < pentry->seq) + continue; + if (prefix_list_entry_match(pentry, p)) + pbest = pentry; + } + + if (validbits <= PLC_BITS) + break; + validbits -= PLC_BITS; + + if (--depth) { + if (!table->entries[*byte].next_table) + break; + + table = table->entries[*byte].next_table; + byte++; + continue; + } + + for (pentry = table->entries[*byte].final_chain; pentry; + pentry = pentry->next_best) { + if (pbest && pbest->seq < pentry->seq) + continue; + if (prefix_list_entry_match(pentry, p)) + pbest = pentry; + } + break; + } + + if (pbest == NULL) + return PREFIX_DENY; + + return pbest->type; +} + +static void __attribute__((unused)) prefix_list_print(struct prefix_list *plist) +{ + struct prefix_list_entry *pentry; + + if (plist == NULL) + return; + + printf("ip prefix-list %s: %d entries\n", plist->name, plist->count); + + for (pentry = plist->head; pentry; pentry = pentry->next) { + if (pentry->any) + printf("any %s\n", prefix_list_type_str(pentry)); + else { + struct prefix *p; + char buf[BUFSIZ]; + + p = &pentry->prefix; + + printf(" seq %u %s %s/%d", pentry->seq, + prefix_list_type_str(pentry), + inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), + p->prefixlen); + if (pentry->ge) + printf(" ge %d", pentry->ge); + if (pentry->le) + printf(" le %d", pentry->le); + printf("\n"); + } } - } } /* Retrun 1 when plist already include pentry policy. */ static struct prefix_list_entry * -prefix_entry_dup_check (struct prefix_list *plist, - struct prefix_list_entry *new) -{ - size_t depth, maxdepth = plist->master->trie_depth; - uint8_t byte, *bytes = &new->prefix.u.prefix; - size_t validbits = new->prefix.prefixlen; - struct pltrie_table *table; - struct prefix_list_entry *pentry; - int seq = 0; - - if (new->seq == -1) - seq = prefix_new_seq_get (plist); - else - seq = new->seq; - - table = plist->trie; - for (depth = 0; validbits > PLC_BITS && depth < maxdepth - 1; depth++) - { - byte = bytes[depth]; - if (!table->entries[byte].next_table) - return NULL; - - table = table->entries[byte].next_table; - validbits -= PLC_BITS; - } - - byte = bytes[depth]; - if (validbits > PLC_BITS) - pentry = table->entries[byte].final_chain; - else - pentry = table->entries[byte].up_chain; - - for (; pentry; pentry = pentry->next_best) - { - if (prefix_same (&pentry->prefix, &new->prefix) - && pentry->type == new->type - && pentry->le == new->le - && pentry->ge == new->ge - && pentry->seq != seq) - return pentry; - } - return NULL; -} - -static int -vty_invalid_prefix_range (struct vty *vty, const char *prefix) -{ - vty_out (vty, "%% Invalid prefix range for %s, make sure: len < ge-value <= le-value\n", - prefix); - return CMD_WARNING_CONFIG_FAILED; -} - -static int -vty_prefix_list_install (struct vty *vty, afi_t afi, const char *name, - const char *seq, const char *typestr, - const char *prefix, const char *ge, const char *le) -{ - int ret; - enum prefix_list_type type; - struct prefix_list *plist; - struct prefix_list_entry *pentry; - struct prefix_list_entry *dup; - struct prefix p, p_tmp; - int any = 0; - int seqnum = -1; - int lenum = 0; - int genum = 0; - - /* Sequential number. */ - if (seq) - seqnum = atoi (seq); - - /* ge and le number */ - if (ge) - genum = atoi (ge); - if (le) - lenum = atoi (le); - - /* Check filter type. */ - if (strncmp ("permit", typestr, 1) == 0) - type = PREFIX_PERMIT; - else if (strncmp ("deny", typestr, 1) == 0) - type = PREFIX_DENY; - else - { - vty_out (vty, "%% prefix type must be permit or deny\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* "any" is special token for matching any IPv4 addresses. */ - switch (afi) - { - case AFI_IP: - if (strncmp ("any", prefix, strlen (prefix)) == 0) - { - ret = str2prefix_ipv4 ("0.0.0.0/0", (struct prefix_ipv4 *) &p); - genum = 0; - lenum = IPV4_MAX_BITLEN; - any = 1; +prefix_entry_dup_check(struct prefix_list *plist, struct prefix_list_entry *new) +{ + size_t depth, maxdepth = plist->master->trie_depth; + uint8_t byte, *bytes = &new->prefix.u.prefix; + size_t validbits = new->prefix.prefixlen; + struct pltrie_table *table; + struct prefix_list_entry *pentry; + int seq = 0; + + if (new->seq == -1) + seq = prefix_new_seq_get(plist); + else + seq = new->seq; + + table = plist->trie; + for (depth = 0; validbits > PLC_BITS && depth < maxdepth - 1; depth++) { + byte = bytes[depth]; + if (!table->entries[byte].next_table) + return NULL; + + table = table->entries[byte].next_table; + validbits -= PLC_BITS; } - else - ret = str2prefix_ipv4 (prefix, (struct prefix_ipv4 *) &p); - if (ret <= 0) - { - vty_out (vty, "%% Malformed IPv4 prefix\n"); - return CMD_WARNING_CONFIG_FAILED; + byte = bytes[depth]; + if (validbits > PLC_BITS) + pentry = table->entries[byte].final_chain; + else + pentry = table->entries[byte].up_chain; + + for (; pentry; pentry = pentry->next_best) { + if (prefix_same(&pentry->prefix, &new->prefix) + && pentry->type == new->type && pentry->le == new->le + && pentry->ge == new->ge && pentry->seq != seq) + return pentry; + } + return NULL; +} + +static int vty_invalid_prefix_range(struct vty *vty, const char *prefix) +{ + vty_out(vty, + "%% Invalid prefix range for %s, make sure: len < ge-value <= le-value\n", + prefix); + return CMD_WARNING_CONFIG_FAILED; +} + +static int vty_prefix_list_install(struct vty *vty, afi_t afi, const char *name, + const char *seq, const char *typestr, + const char *prefix, const char *ge, + const char *le) +{ + int ret; + enum prefix_list_type type; + struct prefix_list *plist; + struct prefix_list_entry *pentry; + struct prefix_list_entry *dup; + struct prefix p, p_tmp; + int any = 0; + int seqnum = -1; + int lenum = 0; + int genum = 0; + + /* Sequential number. */ + if (seq) + seqnum = atoi(seq); + + /* ge and le number */ + if (ge) + genum = atoi(ge); + if (le) + lenum = atoi(le); + + /* Check filter type. */ + if (strncmp("permit", typestr, 1) == 0) + type = PREFIX_PERMIT; + else if (strncmp("deny", typestr, 1) == 0) + type = PREFIX_DENY; + else { + vty_out(vty, "%% prefix type must be permit or deny\n"); + return CMD_WARNING_CONFIG_FAILED; } - /* make a copy to verify prefix matches mask length */ - prefix_copy (&p_tmp, &p); - apply_mask_ipv4 ((struct prefix_ipv4 *) &p_tmp); - - break; - case AFI_IP6: - if (strncmp ("any", prefix, strlen (prefix)) == 0) - { - ret = str2prefix_ipv6 ("::/0", (struct prefix_ipv6 *) &p); - genum = 0; - lenum = IPV6_MAX_BITLEN; - any = 1; + /* "any" is special token for matching any IPv4 addresses. */ + switch (afi) { + case AFI_IP: + if (strncmp("any", prefix, strlen(prefix)) == 0) { + ret = str2prefix_ipv4("0.0.0.0/0", + (struct prefix_ipv4 *)&p); + genum = 0; + lenum = IPV4_MAX_BITLEN; + any = 1; + } else + ret = str2prefix_ipv4(prefix, (struct prefix_ipv4 *)&p); + + if (ret <= 0) { + vty_out(vty, "%% Malformed IPv4 prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* make a copy to verify prefix matches mask length */ + prefix_copy(&p_tmp, &p); + apply_mask_ipv4((struct prefix_ipv4 *)&p_tmp); + + break; + case AFI_IP6: + if (strncmp("any", prefix, strlen(prefix)) == 0) { + ret = str2prefix_ipv6("::/0", (struct prefix_ipv6 *)&p); + genum = 0; + lenum = IPV6_MAX_BITLEN; + any = 1; + } else + ret = str2prefix_ipv6(prefix, (struct prefix_ipv6 *)&p); + + if (ret <= 0) { + vty_out(vty, "%% Malformed IPv6 prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* make a copy to verify prefix matches mask length */ + prefix_copy(&p_tmp, &p); + apply_mask_ipv6((struct prefix_ipv6 *)&p_tmp); + + break; + case AFI_L2VPN: + default: + vty_out(vty, "%% Unrecognized AFI (%d)\n", afi); + return CMD_WARNING_CONFIG_FAILED; + break; } - else - ret = str2prefix_ipv6 (prefix, (struct prefix_ipv6 *) &p); - if (ret <= 0) - { - vty_out (vty, "%% Malformed IPv6 prefix\n"); - return CMD_WARNING_CONFIG_FAILED; + /* If prefix has bits not under the mask, adjust it to fit */ + if (!prefix_same(&p_tmp, &p)) { + char buf[PREFIX2STR_BUFFER]; + char buf_tmp[PREFIX2STR_BUFFER]; + prefix2str(&p, buf, sizeof(buf)); + prefix2str(&p_tmp, buf_tmp, sizeof(buf_tmp)); + zlog_warn( + "Prefix-list %s prefix changed from %s to %s to match length", + name, buf, buf_tmp); + p = p_tmp; } - /* make a copy to verify prefix matches mask length */ - prefix_copy (&p_tmp, &p); - apply_mask_ipv6 ((struct prefix_ipv6 *) &p_tmp); - - break; - case AFI_L2VPN: - default: - vty_out (vty, "%% Unrecognized AFI (%d)\n", afi); - return CMD_WARNING_CONFIG_FAILED; - break; - } - - /* If prefix has bits not under the mask, adjust it to fit */ - if (!prefix_same (&p_tmp, &p)) - { - char buf[PREFIX2STR_BUFFER]; - char buf_tmp[PREFIX2STR_BUFFER]; - prefix2str(&p, buf, sizeof(buf)); - prefix2str(&p_tmp, buf_tmp, sizeof(buf_tmp)); - zlog_warn ("Prefix-list %s prefix changed from %s to %s to match length", - name, buf, buf_tmp); - p = p_tmp; - } - - /* ge and le check. */ - if (genum && (genum <= p.prefixlen)) - return vty_invalid_prefix_range (vty, prefix); - - if (lenum && (lenum <= p.prefixlen)) - return vty_invalid_prefix_range (vty, prefix); - - if (lenum && (genum > lenum)) - return vty_invalid_prefix_range (vty, prefix); - - if (genum && (lenum == (afi == AFI_IP ? 32 : 128))) - lenum = 0; - - /* Get prefix_list with name. */ - plist = prefix_list_get (afi, 0, name); - - /* Make prefix entry. */ - pentry = prefix_list_entry_make (&p, type, seqnum, lenum, genum, any); - - /* Check same policy. */ - dup = prefix_entry_dup_check (plist, pentry); - - if (dup) - { - prefix_list_entry_free (pentry); - return CMD_SUCCESS; - } - - /* Install new filter to the access_list. */ - prefix_list_entry_add (plist, pentry); - - return CMD_SUCCESS; -} - -static int -vty_prefix_list_uninstall (struct vty *vty, afi_t afi, const char *name, - const char *seq, const char *typestr, - const char *prefix, const char *ge, const char *le) -{ - int ret; - enum prefix_list_type type; - struct prefix_list *plist; - struct prefix_list_entry *pentry; - struct prefix p; - int seqnum = -1; - int lenum = 0; - int genum = 0; - - /* Check prefix list name. */ - plist = prefix_list_lookup (afi, name); - if (! plist) - { - vty_out (vty, "%% Can't find specified prefix-list\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Only prefix-list name specified, delete the entire prefix-list. */ - if (seq == NULL && typestr == NULL && prefix == NULL && - ge == NULL && le == NULL) - { - prefix_list_delete (plist); - return CMD_SUCCESS; - } - - /* We must have, at a minimum, both the type and prefix here */ - if ((typestr == NULL) || (prefix == NULL)) - { - vty_out (vty, "%% Both prefix and type required\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check sequence number. */ - if (seq) - seqnum = atoi (seq); - - /* ge and le number */ - if (ge) - genum = atoi (ge); - if (le) - lenum = atoi (le); - - /* Check of filter type. */ - if (strncmp ("permit", typestr, 1) == 0) - type = PREFIX_PERMIT; - else if (strncmp ("deny", typestr, 1) == 0) - type = PREFIX_DENY; - else - { - vty_out (vty, "%% prefix type must be permit or deny\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* "any" is special token for matching any IPv4 addresses. */ - if (afi == AFI_IP) - { - if (strncmp ("any", prefix, strlen (prefix)) == 0) - { - ret = str2prefix_ipv4 ("0.0.0.0/0", (struct prefix_ipv4 *) &p); - genum = 0; - lenum = IPV4_MAX_BITLEN; + /* ge and le check. */ + if (genum && (genum <= p.prefixlen)) + return vty_invalid_prefix_range(vty, prefix); + + if (lenum && (lenum <= p.prefixlen)) + return vty_invalid_prefix_range(vty, prefix); + + if (lenum && (genum > lenum)) + return vty_invalid_prefix_range(vty, prefix); + + if (genum && (lenum == (afi == AFI_IP ? 32 : 128))) + lenum = 0; + + /* Get prefix_list with name. */ + plist = prefix_list_get(afi, 0, name); + + /* Make prefix entry. */ + pentry = prefix_list_entry_make(&p, type, seqnum, lenum, genum, any); + + /* Check same policy. */ + dup = prefix_entry_dup_check(plist, pentry); + + if (dup) { + prefix_list_entry_free(pentry); + return CMD_SUCCESS; } - else - ret = str2prefix_ipv4 (prefix, (struct prefix_ipv4 *) &p); - if (ret <= 0) - { - vty_out (vty, "%% Malformed IPv4 prefix\n"); - return CMD_WARNING_CONFIG_FAILED; + /* Install new filter to the access_list. */ + prefix_list_entry_add(plist, pentry); + + return CMD_SUCCESS; +} + +static int vty_prefix_list_uninstall(struct vty *vty, afi_t afi, + const char *name, const char *seq, + const char *typestr, const char *prefix, + const char *ge, const char *le) +{ + int ret; + enum prefix_list_type type; + struct prefix_list *plist; + struct prefix_list_entry *pentry; + struct prefix p; + int seqnum = -1; + int lenum = 0; + int genum = 0; + + /* Check prefix list name. */ + plist = prefix_list_lookup(afi, name); + if (!plist) { + vty_out(vty, "%% Can't find specified prefix-list\n"); + return CMD_WARNING_CONFIG_FAILED; } - } - else if (afi == AFI_IP6) - { - if (strncmp ("any", prefix, strlen (prefix)) == 0) - { - ret = str2prefix_ipv6 ("::/0", (struct prefix_ipv6 *) &p); - genum = 0; - lenum = IPV6_MAX_BITLEN; + + /* Only prefix-list name specified, delete the entire prefix-list. */ + if (seq == NULL && typestr == NULL && prefix == NULL && ge == NULL + && le == NULL) { + prefix_list_delete(plist); + return CMD_SUCCESS; } - else - ret = str2prefix_ipv6 (prefix, (struct prefix_ipv6 *) &p); - if (ret <= 0) - { - vty_out (vty, "%% Malformed IPv6 prefix\n"); - return CMD_WARNING_CONFIG_FAILED; + /* We must have, at a minimum, both the type and prefix here */ + if ((typestr == NULL) || (prefix == NULL)) { + vty_out(vty, "%% Both prefix and type required\n"); + return CMD_WARNING_CONFIG_FAILED; } - } - /* Lookup prefix entry. */ - pentry = prefix_list_entry_lookup(plist, &p, type, seqnum, lenum, genum); + /* Check sequence number. */ + if (seq) + seqnum = atoi(seq); + + /* ge and le number */ + if (ge) + genum = atoi(ge); + if (le) + lenum = atoi(le); + + /* Check of filter type. */ + if (strncmp("permit", typestr, 1) == 0) + type = PREFIX_PERMIT; + else if (strncmp("deny", typestr, 1) == 0) + type = PREFIX_DENY; + else { + vty_out(vty, "%% prefix type must be permit or deny\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (pentry == NULL) - { - vty_out (vty, "%% Can't find specified prefix-list\n"); - return CMD_WARNING_CONFIG_FAILED; - } + /* "any" is special token for matching any IPv4 addresses. */ + if (afi == AFI_IP) { + if (strncmp("any", prefix, strlen(prefix)) == 0) { + ret = str2prefix_ipv4("0.0.0.0/0", + (struct prefix_ipv4 *)&p); + genum = 0; + lenum = IPV4_MAX_BITLEN; + } else + ret = str2prefix_ipv4(prefix, (struct prefix_ipv4 *)&p); + + if (ret <= 0) { + vty_out(vty, "%% Malformed IPv4 prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } else if (afi == AFI_IP6) { + if (strncmp("any", prefix, strlen(prefix)) == 0) { + ret = str2prefix_ipv6("::/0", (struct prefix_ipv6 *)&p); + genum = 0; + lenum = IPV6_MAX_BITLEN; + } else + ret = str2prefix_ipv6(prefix, (struct prefix_ipv6 *)&p); + + if (ret <= 0) { + vty_out(vty, "%% Malformed IPv6 prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } - /* Install new filter to the access_list. */ - prefix_list_entry_delete (plist, pentry, 1); + /* Lookup prefix entry. */ + pentry = + prefix_list_entry_lookup(plist, &p, type, seqnum, lenum, genum); - return CMD_SUCCESS; + if (pentry == NULL) { + vty_out(vty, "%% Can't find specified prefix-list\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Install new filter to the access_list. */ + prefix_list_entry_delete(plist, pentry, 1); + + return CMD_SUCCESS; } -static int -vty_prefix_list_desc_unset (struct vty *vty, afi_t afi, const char *name) +static int vty_prefix_list_desc_unset(struct vty *vty, afi_t afi, + const char *name) { - struct prefix_list *plist; + struct prefix_list *plist; - plist = prefix_list_lookup (afi, name); - if (! plist) - { - vty_out (vty, "%% Can't find specified prefix-list\n"); - return CMD_WARNING_CONFIG_FAILED; - } + plist = prefix_list_lookup(afi, name); + if (!plist) { + vty_out(vty, "%% Can't find specified prefix-list\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (plist->desc) - { - XFREE (MTYPE_TMP, plist->desc); - plist->desc = NULL; - } + if (plist->desc) { + XFREE(MTYPE_TMP, plist->desc); + plist->desc = NULL; + } - if (plist->head == NULL && plist->tail == NULL && plist->desc == NULL) - prefix_list_delete (plist); + if (plist->head == NULL && plist->tail == NULL && plist->desc == NULL) + prefix_list_delete(plist); - return CMD_SUCCESS; + return CMD_SUCCESS; } -enum display_type -{ - normal_display, - summary_display, - detail_display, - sequential_display, - longer_display, - first_match_display +enum display_type { + normal_display, + summary_display, + detail_display, + sequential_display, + longer_display, + first_match_display }; -static void -vty_show_prefix_entry (struct vty *vty, afi_t afi, struct prefix_list *plist, - struct prefix_master *master, enum display_type dtype, - int seqnum) -{ - struct prefix_list_entry *pentry; - - /* Print the name of the protocol */ - vty_out(vty, "%s: ", frr_protoname); - - if (dtype == normal_display) - { - vty_out (vty, "ip%s prefix-list %s: %d entries\n", - afi == AFI_IP ? "" : "v6", - plist->name, plist->count); - if (plist->desc) - vty_out (vty, " Description: %s\n", plist->desc); - } - else if (dtype == summary_display || dtype == detail_display) - { - vty_out (vty, "ip%s prefix-list %s:\n", - afi == AFI_IP ? "" : "v6", plist->name); - - if (plist->desc) - vty_out (vty, " Description: %s\n", plist->desc); - - vty_out (vty, " count: %d, range entries: %d, sequences: %u - %u\n", - plist->count, plist->rangecount, - plist->head ? plist->head->seq : 0, - plist->tail ? plist->tail->seq : 0); - } - - if (dtype != summary_display) - { - for (pentry = plist->head; pentry; pentry = pentry->next) - { - if (dtype == sequential_display && pentry->seq != seqnum) - continue; - - vty_out (vty, " "); - - if (master->seqnum) - vty_out (vty, "seq %u ", pentry->seq); - - vty_out (vty, "%s ", prefix_list_type_str (pentry)); - - if (pentry->any) - vty_out (vty, "any"); - else - { - struct prefix *p = &pentry->prefix; - char buf[BUFSIZ]; - - vty_out (vty, "%s/%d", - inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), - p->prefixlen); - - if (pentry->ge) - vty_out (vty, " ge %d", pentry->ge); - if (pentry->le) - vty_out (vty, " le %d", pentry->le); - } - - if (dtype == detail_display || dtype == sequential_display) - vty_out (vty, " (hit count: %ld, refcount: %ld)", - pentry->hitcnt, pentry->refcnt); - - vty_out (vty, "\n"); +static void vty_show_prefix_entry(struct vty *vty, afi_t afi, + struct prefix_list *plist, + struct prefix_master *master, + enum display_type dtype, int seqnum) +{ + struct prefix_list_entry *pentry; + + /* Print the name of the protocol */ + vty_out(vty, "%s: ", frr_protoname); + + if (dtype == normal_display) { + vty_out(vty, "ip%s prefix-list %s: %d entries\n", + afi == AFI_IP ? "" : "v6", plist->name, plist->count); + if (plist->desc) + vty_out(vty, " Description: %s\n", plist->desc); + } else if (dtype == summary_display || dtype == detail_display) { + vty_out(vty, "ip%s prefix-list %s:\n", + afi == AFI_IP ? "" : "v6", plist->name); + + if (plist->desc) + vty_out(vty, " Description: %s\n", plist->desc); + + vty_out(vty, + " count: %d, range entries: %d, sequences: %u - %u\n", + plist->count, plist->rangecount, + plist->head ? plist->head->seq : 0, + plist->tail ? plist->tail->seq : 0); } - } -} -static int -vty_show_prefix_list (struct vty *vty, afi_t afi, const char *name, - const char *seq, enum display_type dtype) -{ - struct prefix_list *plist; - struct prefix_master *master; - int seqnum = 0; + if (dtype != summary_display) { + for (pentry = plist->head; pentry; pentry = pentry->next) { + if (dtype == sequential_display + && pentry->seq != seqnum) + continue; - master = prefix_master_get (afi, 0); - if (master == NULL) - return CMD_WARNING; + vty_out(vty, " "); - if (seq) - seqnum = atoi (seq); + if (master->seqnum) + vty_out(vty, "seq %u ", pentry->seq); - if (name) - { - plist = prefix_list_lookup (afi, name); - if (! plist) - { - vty_out (vty, "%% Can't find specified prefix-list\n"); - return CMD_WARNING; - } - vty_show_prefix_entry (vty, afi, plist, master, dtype, seqnum); - } - else - { - if (dtype == detail_display || dtype == summary_display) - { - if (master->recent) - vty_out (vty, "Prefix-list with the last deletion/insertion: %s\n", - master->recent->name); - } + vty_out(vty, "%s ", prefix_list_type_str(pentry)); - for (plist = master->num.head; plist; plist = plist->next) - vty_show_prefix_entry (vty, afi, plist, master, dtype, seqnum); - - for (plist = master->str.head; plist; plist = plist->next) - vty_show_prefix_entry (vty, afi, plist, master, dtype, seqnum); - } - - return CMD_SUCCESS; -} - -static int -vty_show_prefix_list_prefix (struct vty *vty, afi_t afi, const char *name, - const char *prefix, enum display_type type) -{ - struct prefix_list *plist; - struct prefix_list_entry *pentry; - struct prefix p; - int ret; - int match; - - plist = prefix_list_lookup (afi, name); - if (! plist) - { - vty_out (vty, "%% Can't find specified prefix-list\n"); - return CMD_WARNING; - } - - ret = str2prefix (prefix, &p); - if (ret <= 0) - { - vty_out (vty, "%% prefix is malformed\n"); - return CMD_WARNING; - } - - for (pentry = plist->head; pentry; pentry = pentry->next) - { - match = 0; - - if (type == normal_display || type == first_match_display) - if (prefix_same (&p, &pentry->prefix)) - match = 1; - - if (type == longer_display) - if (prefix_match (&p, &pentry->prefix)) - match = 1; - - if (match) - { - vty_out (vty, " seq %u %s ", - pentry->seq, - prefix_list_type_str (pentry)); - - if (pentry->any) - vty_out (vty, "any"); - else - { - struct prefix *p = &pentry->prefix; - char buf[BUFSIZ]; - - vty_out (vty, "%s/%d", - inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), - p->prefixlen); - - if (pentry->ge) - vty_out (vty, " ge %d", pentry->ge); - if (pentry->le) - vty_out (vty, " le %d", pentry->le); - } - - if (type == normal_display || type == first_match_display) - vty_out (vty, " (hit count: %ld, refcount: %ld)", - pentry->hitcnt, pentry->refcnt); - - vty_out (vty, "\n"); - - if (type == first_match_display) - return CMD_SUCCESS; + if (pentry->any) + vty_out(vty, "any"); + else { + struct prefix *p = &pentry->prefix; + char buf[BUFSIZ]; + + vty_out(vty, "%s/%d", + inet_ntop(p->family, &p->u.prefix, buf, + BUFSIZ), + p->prefixlen); + + if (pentry->ge) + vty_out(vty, " ge %d", pentry->ge); + if (pentry->le) + vty_out(vty, " le %d", pentry->le); + } + + if (dtype == detail_display + || dtype == sequential_display) + vty_out(vty, " (hit count: %ld, refcount: %ld)", + pentry->hitcnt, pentry->refcnt); + + vty_out(vty, "\n"); + } } - } - return CMD_SUCCESS; } -static int -vty_clear_prefix_list (struct vty *vty, afi_t afi, const char *name, - const char *prefix) -{ - struct prefix_master *master; - struct prefix_list *plist; - struct prefix_list_entry *pentry; - int ret; - struct prefix p; +static int vty_show_prefix_list(struct vty *vty, afi_t afi, const char *name, + const char *seq, enum display_type dtype) +{ + struct prefix_list *plist; + struct prefix_master *master; + int seqnum = 0; + + master = prefix_master_get(afi, 0); + if (master == NULL) + return CMD_WARNING; + + if (seq) + seqnum = atoi(seq); + + if (name) { + plist = prefix_list_lookup(afi, name); + if (!plist) { + vty_out(vty, "%% Can't find specified prefix-list\n"); + return CMD_WARNING; + } + vty_show_prefix_entry(vty, afi, plist, master, dtype, seqnum); + } else { + if (dtype == detail_display || dtype == summary_display) { + if (master->recent) + vty_out(vty, + "Prefix-list with the last deletion/insertion: %s\n", + master->recent->name); + } + + for (plist = master->num.head; plist; plist = plist->next) + vty_show_prefix_entry(vty, afi, plist, master, dtype, + seqnum); + + for (plist = master->str.head; plist; plist = plist->next) + vty_show_prefix_entry(vty, afi, plist, master, dtype, + seqnum); + } - master = prefix_master_get (afi, 0); - if (master == NULL) - return CMD_WARNING; + return CMD_SUCCESS; +} - if (name == NULL && prefix == NULL) - { - for (plist = master->num.head; plist; plist = plist->next) - for (pentry = plist->head; pentry; pentry = pentry->next) - pentry->hitcnt = 0; +static int vty_show_prefix_list_prefix(struct vty *vty, afi_t afi, + const char *name, const char *prefix, + enum display_type type) +{ + struct prefix_list *plist; + struct prefix_list_entry *pentry; + struct prefix p; + int ret; + int match; - for (plist = master->str.head; plist; plist = plist->next) - for (pentry = plist->head; pentry; pentry = pentry->next) - pentry->hitcnt = 0; - } - else - { - plist = prefix_list_lookup (afi, name); - if (! plist) - { - vty_out (vty, "%% Can't find specified prefix-list\n"); - return CMD_WARNING; + plist = prefix_list_lookup(afi, name); + if (!plist) { + vty_out(vty, "%% Can't find specified prefix-list\n"); + return CMD_WARNING; } - if (prefix) - { - ret = str2prefix (prefix, &p); - if (ret <= 0) - { - vty_out (vty, "%% prefix is malformed\n"); - return CMD_WARNING; - } + ret = str2prefix(prefix, &p); + if (ret <= 0) { + vty_out(vty, "%% prefix is malformed\n"); + return CMD_WARNING; } - for (pentry = plist->head; pentry; pentry = pentry->next) - { - if (prefix) - { - if (prefix_match (&pentry->prefix, &p)) - pentry->hitcnt = 0; - } - else - pentry->hitcnt = 0; + for (pentry = plist->head; pentry; pentry = pentry->next) { + match = 0; + + if (type == normal_display || type == first_match_display) + if (prefix_same(&p, &pentry->prefix)) + match = 1; + + if (type == longer_display) + if (prefix_match(&p, &pentry->prefix)) + match = 1; + + if (match) { + vty_out(vty, " seq %u %s ", pentry->seq, + prefix_list_type_str(pentry)); + + if (pentry->any) + vty_out(vty, "any"); + else { + struct prefix *p = &pentry->prefix; + char buf[BUFSIZ]; + + vty_out(vty, "%s/%d", + inet_ntop(p->family, &p->u.prefix, buf, + BUFSIZ), + p->prefixlen); + + if (pentry->ge) + vty_out(vty, " ge %d", pentry->ge); + if (pentry->le) + vty_out(vty, " le %d", pentry->le); + } + + if (type == normal_display + || type == first_match_display) + vty_out(vty, " (hit count: %ld, refcount: %ld)", + pentry->hitcnt, pentry->refcnt); + + vty_out(vty, "\n"); + + if (type == first_match_display) + return CMD_SUCCESS; + } } - } - return CMD_SUCCESS; + return CMD_SUCCESS; +} + +static int vty_clear_prefix_list(struct vty *vty, afi_t afi, const char *name, + const char *prefix) +{ + struct prefix_master *master; + struct prefix_list *plist; + struct prefix_list_entry *pentry; + int ret; + struct prefix p; + + master = prefix_master_get(afi, 0); + if (master == NULL) + return CMD_WARNING; + + if (name == NULL && prefix == NULL) { + for (plist = master->num.head; plist; plist = plist->next) + for (pentry = plist->head; pentry; + pentry = pentry->next) + pentry->hitcnt = 0; + + for (plist = master->str.head; plist; plist = plist->next) + for (pentry = plist->head; pentry; + pentry = pentry->next) + pentry->hitcnt = 0; + } else { + plist = prefix_list_lookup(afi, name); + if (!plist) { + vty_out(vty, "%% Can't find specified prefix-list\n"); + return CMD_WARNING; + } + + if (prefix) { + ret = str2prefix(prefix, &p); + if (ret <= 0) { + vty_out(vty, "%% prefix is malformed\n"); + return CMD_WARNING; + } + } + + for (pentry = plist->head; pentry; pentry = pentry->next) { + if (prefix) { + if (prefix_match(&pentry->prefix, &p)) + pentry->hitcnt = 0; + } else + pentry->hitcnt = 0; + } + } + return CMD_SUCCESS; } #ifndef VTYSH_EXTRACT_PL @@ -1433,8 +1311,8 @@ DEFPY (ip_prefix_list, "Maximum prefix length to be matched\n" "Maximum prefix length\n") { - return vty_prefix_list_install (vty, AFI_IP, prefix_list, seq_str, action, - dest, ge_str, le_str); + return vty_prefix_list_install(vty, AFI_IP, prefix_list, seq_str, + action, dest, ge_str, le_str); } DEFPY (no_ip_prefix_list, @@ -1455,8 +1333,8 @@ DEFPY (no_ip_prefix_list, "Maximum prefix length to be matched\n" "Maximum prefix length\n") { - return vty_prefix_list_uninstall (vty, AFI_IP, prefix_list, seq_str, action, - dest, ge_str, le_str); + return vty_prefix_list_uninstall(vty, AFI_IP, prefix_list, seq_str, + action, dest, ge_str, le_str); } DEFPY (no_ip_prefix_list_all, @@ -1467,8 +1345,8 @@ DEFPY (no_ip_prefix_list_all, PREFIX_LIST_STR "Name of a prefix list\n") { - return vty_prefix_list_uninstall (vty, AFI_IP, prefix_list, NULL, NULL, - NULL, NULL, NULL); + return vty_prefix_list_uninstall(vty, AFI_IP, prefix_list, NULL, NULL, + NULL, NULL, NULL); } DEFPY (ip_prefix_list_sequence_number, @@ -1479,8 +1357,8 @@ DEFPY (ip_prefix_list_sequence_number, PREFIX_LIST_STR "Include/exclude sequence numbers in NVGEN\n") { - prefix_master_ipv4.seqnum = no ? 0 : 1; - return CMD_SUCCESS; + prefix_master_ipv4.seqnum = no ? 0 : 1; + return CMD_SUCCESS; } DEFUN (ip_prefix_list_description, @@ -1492,20 +1370,19 @@ DEFUN (ip_prefix_list_description, "Prefix-list specific description\n" "Up to 80 characters describing this prefix-list\n") { - int idx_word = 2; - int idx_line = 4; - struct prefix_list *plist; + int idx_word = 2; + int idx_line = 4; + struct prefix_list *plist; + + plist = prefix_list_get(AFI_IP, 0, argv[idx_word]->arg); - plist = prefix_list_get (AFI_IP, 0, argv[idx_word]->arg); - - if (plist->desc) - { - XFREE (MTYPE_TMP, plist->desc); - plist->desc = NULL; - } - plist->desc = argv_concat(argv, argc, idx_line); + if (plist->desc) { + XFREE(MTYPE_TMP, plist->desc); + plist->desc = NULL; + } + plist->desc = argv_concat(argv, argc, idx_line); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_prefix_list_description, @@ -1517,8 +1394,8 @@ DEFUN (no_ip_prefix_list_description, "Name of a prefix list\n" "Prefix-list specific description\n") { - int idx_word = 3; - return vty_prefix_list_desc_unset (vty, AFI_IP, argv[idx_word]->arg); + int idx_word = 3; + return vty_prefix_list_desc_unset(vty, AFI_IP, argv[idx_word]->arg); } /* ALIAS_FIXME */ @@ -1532,7 +1409,7 @@ DEFUN (no_ip_prefix_list_description_comment, "Prefix-list specific description\n" "Up to 80 characters describing this prefix-list\n") { - return no_ip_prefix_list_description (self, vty, argc, argv); + return no_ip_prefix_list_description(self, vty, argc, argv); } DEFPY (show_ip_prefix_list, @@ -1545,11 +1422,11 @@ DEFPY (show_ip_prefix_list, "sequence number of an entry\n" "Sequence number\n") { - enum display_type dtype = normal_display; - if (dseq) - dtype = sequential_display; + enum display_type dtype = normal_display; + if (dseq) + dtype = sequential_display; - return vty_show_prefix_list (vty, AFI_IP, prefix_list, arg_str, dtype); + return vty_show_prefix_list(vty, AFI_IP, prefix_list, arg_str, dtype); } DEFPY (show_ip_prefix_list_prefix, @@ -1563,13 +1440,14 @@ DEFPY (show_ip_prefix_list_prefix, "Lookup longer prefix\n" "First matched prefix\n") { - enum display_type dtype = normal_display; - if (dl) - dtype = longer_display; - else if (dfm) - dtype = first_match_display; + enum display_type dtype = normal_display; + if (dl) + dtype = longer_display; + else if (dfm) + dtype = first_match_display; - return vty_show_prefix_list_prefix (vty, AFI_IP, prefix_list, prefix_str, dtype); + return vty_show_prefix_list_prefix(vty, AFI_IP, prefix_list, prefix_str, + dtype); } DEFPY (show_ip_prefix_list_summary, @@ -1581,7 +1459,8 @@ DEFPY (show_ip_prefix_list_summary, "Summary of prefix lists\n" "Name of a prefix list\n") { - return vty_show_prefix_list (vty, AFI_IP, prefix_list, NULL, summary_display); + return vty_show_prefix_list(vty, AFI_IP, prefix_list, NULL, + summary_display); } DEFPY (show_ip_prefix_list_detail, @@ -1593,7 +1472,8 @@ DEFPY (show_ip_prefix_list_detail, "Detail of prefix lists\n" "Name of a prefix list\n") { - return vty_show_prefix_list (vty, AFI_IP, prefix_list, NULL, detail_display); + return vty_show_prefix_list(vty, AFI_IP, prefix_list, NULL, + detail_display); } DEFPY (clear_ip_prefix_list, @@ -1605,7 +1485,7 @@ DEFPY (clear_ip_prefix_list, "Name of a prefix list\n" "IP prefix /, e.g., 35.0.0.0/8\n") { - return vty_clear_prefix_list (vty, AFI_IP, prefix_list, prefix_str); + return vty_clear_prefix_list(vty, AFI_IP, prefix_list, prefix_str); } DEFPY (ipv6_prefix_list, @@ -1625,8 +1505,8 @@ DEFPY (ipv6_prefix_list, "Minimum prefix length to be matched\n" "Minimum prefix length\n") { - return vty_prefix_list_install (vty, AFI_IP6, prefix_list, seq_str, action, - dest, ge_str, le_str); + return vty_prefix_list_install(vty, AFI_IP6, prefix_list, seq_str, + action, dest, ge_str, le_str); } DEFPY (no_ipv6_prefix_list, @@ -1647,8 +1527,8 @@ DEFPY (no_ipv6_prefix_list, "Minimum prefix length to be matched\n" "Minimum prefix length\n") { - return vty_prefix_list_uninstall (vty, AFI_IP6, prefix_list, seq_str, action, - dest, ge_str, le_str); + return vty_prefix_list_uninstall(vty, AFI_IP6, prefix_list, seq_str, + action, dest, ge_str, le_str); } DEFPY (no_ipv6_prefix_list_all, @@ -1659,8 +1539,8 @@ DEFPY (no_ipv6_prefix_list_all, PREFIX_LIST_STR "Name of a prefix list\n") { - return vty_prefix_list_uninstall (vty, AFI_IP6, prefix_list, NULL, NULL, - NULL, NULL, NULL); + return vty_prefix_list_uninstall(vty, AFI_IP6, prefix_list, NULL, NULL, + NULL, NULL, NULL); } DEFPY (ipv6_prefix_list_sequence_number, @@ -1671,8 +1551,8 @@ DEFPY (ipv6_prefix_list_sequence_number, PREFIX_LIST_STR "Include/exclude sequence numbers in NVGEN\n") { - prefix_master_ipv6.seqnum = no ? 0 : 1; - return CMD_SUCCESS; + prefix_master_ipv6.seqnum = no ? 0 : 1; + return CMD_SUCCESS; } DEFUN (ipv6_prefix_list_description, @@ -1684,20 +1564,19 @@ DEFUN (ipv6_prefix_list_description, "Prefix-list specific description\n" "Up to 80 characters describing this prefix-list\n") { - int idx_word = 2; - int iddx_line = 4; - struct prefix_list *plist; + int idx_word = 2; + int iddx_line = 4; + struct prefix_list *plist; - plist = prefix_list_get (AFI_IP6, 0, argv[idx_word]->arg); - - if (plist->desc) - { - XFREE (MTYPE_TMP, plist->desc); - plist->desc = NULL; - } - plist->desc = argv_concat(argv, argc, iddx_line); + plist = prefix_list_get(AFI_IP6, 0, argv[idx_word]->arg); + + if (plist->desc) { + XFREE(MTYPE_TMP, plist->desc); + plist->desc = NULL; + } + plist->desc = argv_concat(argv, argc, iddx_line); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ipv6_prefix_list_description, @@ -1709,8 +1588,8 @@ DEFUN (no_ipv6_prefix_list_description, "Name of a prefix list\n" "Prefix-list specific description\n") { - int idx_word = 3; - return vty_prefix_list_desc_unset (vty, AFI_IP6, argv[idx_word]->arg); + int idx_word = 3; + return vty_prefix_list_desc_unset(vty, AFI_IP6, argv[idx_word]->arg); } /* ALIAS_FIXME */ @@ -1724,7 +1603,7 @@ DEFUN (no_ipv6_prefix_list_description_comment, "Prefix-list specific description\n" "Up to 80 characters describing this prefix-list\n") { - return no_ipv6_prefix_list_description (self, vty, argc, argv); + return no_ipv6_prefix_list_description(self, vty, argc, argv); } @@ -1738,11 +1617,11 @@ DEFPY (show_ipv6_prefix_list, "sequence number of an entry\n" "Sequence number\n") { - enum display_type dtype = normal_display; - if (dseq) - dtype = sequential_display; + enum display_type dtype = normal_display; + if (dseq) + dtype = sequential_display; - return vty_show_prefix_list (vty, AFI_IP6, prefix_list, arg_str, dtype); + return vty_show_prefix_list(vty, AFI_IP6, prefix_list, arg_str, dtype); } DEFPY (show_ipv6_prefix_list_prefix, @@ -1756,13 +1635,14 @@ DEFPY (show_ipv6_prefix_list_prefix, "Lookup longer prefix\n" "First matched prefix\n") { - enum display_type dtype = normal_display; - if (dl) - dtype = longer_display; - else if (dfm) - dtype = first_match_display; + enum display_type dtype = normal_display; + if (dl) + dtype = longer_display; + else if (dfm) + dtype = first_match_display; - return vty_show_prefix_list_prefix (vty, AFI_IP6, prefix_list, prefix_str, dtype); + return vty_show_prefix_list_prefix(vty, AFI_IP6, prefix_list, + prefix_str, dtype); } DEFPY (show_ipv6_prefix_list_summary, @@ -1774,7 +1654,8 @@ DEFPY (show_ipv6_prefix_list_summary, "Summary of prefix lists\n" "Name of a prefix list\n") { - return vty_show_prefix_list (vty, AFI_IP6, prefix_list, NULL, summary_display); + return vty_show_prefix_list(vty, AFI_IP6, prefix_list, NULL, + summary_display); } DEFPY (show_ipv6_prefix_list_detail, @@ -1786,7 +1667,8 @@ DEFPY (show_ipv6_prefix_list_detail, "Detail of prefix lists\n" "Name of a prefix list\n") { - return vty_show_prefix_list (vty, AFI_IP6, prefix_list, NULL, detail_display); + return vty_show_prefix_list(vty, AFI_IP6, prefix_list, NULL, + detail_display); } DEFPY (clear_ipv6_prefix_list, @@ -1798,440 +1680,408 @@ DEFPY (clear_ipv6_prefix_list, "Name of a prefix list\n" "IPv6 prefix /, e.g., 3ffe::/16\n") { - return vty_clear_prefix_list (vty, AFI_IP6, prefix_list, prefix_str); + return vty_clear_prefix_list(vty, AFI_IP6, prefix_list, prefix_str); } /* Configuration write function. */ -static int -config_write_prefix_afi (afi_t afi, struct vty *vty) -{ - struct prefix_list *plist; - struct prefix_list_entry *pentry; - struct prefix_master *master; - int write = 0; - - master = prefix_master_get (afi, 0); - if (master == NULL) - return 0; - - if (! master->seqnum) - { - vty_out (vty, "no ip%s prefix-list sequence-number\n", - afi == AFI_IP ? "" : "v6"); - vty_out (vty, "!\n"); - } - - for (plist = master->num.head; plist; plist = plist->next) - { - if (plist->desc) - { - vty_out (vty, "ip%s prefix-list %s description %s\n", - afi == AFI_IP ? "" : "v6", - plist->name, plist->desc); - write++; - } +static int config_write_prefix_afi(afi_t afi, struct vty *vty) +{ + struct prefix_list *plist; + struct prefix_list_entry *pentry; + struct prefix_master *master; + int write = 0; + + master = prefix_master_get(afi, 0); + if (master == NULL) + return 0; - for (pentry = plist->head; pentry; pentry = pentry->next) - { - vty_out (vty, "ip%s prefix-list %s ", - afi == AFI_IP ? "" : "v6", - plist->name); - - if (master->seqnum) - vty_out (vty, "seq %u ", pentry->seq); - - vty_out (vty, "%s ", prefix_list_type_str (pentry)); - - if (pentry->any) - vty_out (vty, "any"); - else - { - struct prefix *p = &pentry->prefix; - char buf[BUFSIZ]; - - vty_out (vty, "%s/%d", - inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), - p->prefixlen); - - if (pentry->ge) - vty_out (vty, " ge %d", pentry->ge); - if (pentry->le) - vty_out (vty, " le %d", pentry->le); - } - vty_out (vty, "\n"); - write++; + if (!master->seqnum) { + vty_out(vty, "no ip%s prefix-list sequence-number\n", + afi == AFI_IP ? "" : "v6"); + vty_out(vty, "!\n"); } - /* vty_out (vty, "!\n"); */ - } - - for (plist = master->str.head; plist; plist = plist->next) - { - if (plist->desc) - { - vty_out (vty, "ip%s prefix-list %s description %s\n", - afi == AFI_IP ? "" : "v6", - plist->name, plist->desc); - write++; + + for (plist = master->num.head; plist; plist = plist->next) { + if (plist->desc) { + vty_out(vty, "ip%s prefix-list %s description %s\n", + afi == AFI_IP ? "" : "v6", plist->name, + plist->desc); + write++; + } + + for (pentry = plist->head; pentry; pentry = pentry->next) { + vty_out(vty, "ip%s prefix-list %s ", + afi == AFI_IP ? "" : "v6", plist->name); + + if (master->seqnum) + vty_out(vty, "seq %u ", pentry->seq); + + vty_out(vty, "%s ", prefix_list_type_str(pentry)); + + if (pentry->any) + vty_out(vty, "any"); + else { + struct prefix *p = &pentry->prefix; + char buf[BUFSIZ]; + + vty_out(vty, "%s/%d", + inet_ntop(p->family, &p->u.prefix, buf, + BUFSIZ), + p->prefixlen); + + if (pentry->ge) + vty_out(vty, " ge %d", pentry->ge); + if (pentry->le) + vty_out(vty, " le %d", pentry->le); + } + vty_out(vty, "\n"); + write++; + } + /* vty_out (vty, "!\n"); */ } - for (pentry = plist->head; pentry; pentry = pentry->next) - { - vty_out (vty, "ip%s prefix-list %s ", - afi == AFI_IP ? "" : "v6", - plist->name); - - if (master->seqnum) - vty_out (vty, "seq %u ", pentry->seq); - - vty_out (vty, "%s", prefix_list_type_str (pentry)); - - if (pentry->any) - vty_out (vty, " any"); - else - { - struct prefix *p = &pentry->prefix; - char buf[BUFSIZ]; - - vty_out (vty, " %s/%d", - inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), - p->prefixlen); - - if (pentry->ge) - vty_out (vty, " ge %d", pentry->ge); - if (pentry->le) - vty_out (vty, " le %d", pentry->le); - } - vty_out (vty, "\n"); - write++; + for (plist = master->str.head; plist; plist = plist->next) { + if (plist->desc) { + vty_out(vty, "ip%s prefix-list %s description %s\n", + afi == AFI_IP ? "" : "v6", plist->name, + plist->desc); + write++; + } + + for (pentry = plist->head; pentry; pentry = pentry->next) { + vty_out(vty, "ip%s prefix-list %s ", + afi == AFI_IP ? "" : "v6", plist->name); + + if (master->seqnum) + vty_out(vty, "seq %u ", pentry->seq); + + vty_out(vty, "%s", prefix_list_type_str(pentry)); + + if (pentry->any) + vty_out(vty, " any"); + else { + struct prefix *p = &pentry->prefix; + char buf[BUFSIZ]; + + vty_out(vty, " %s/%d", + inet_ntop(p->family, &p->u.prefix, buf, + BUFSIZ), + p->prefixlen); + + if (pentry->ge) + vty_out(vty, " ge %d", pentry->ge); + if (pentry->le) + vty_out(vty, " le %d", pentry->le); + } + vty_out(vty, "\n"); + write++; + } } - } - - return write; + + return write; } -struct stream * -prefix_bgp_orf_entry (struct stream *s, struct prefix_list *plist, - u_char init_flag, u_char permit_flag, u_char deny_flag) +struct stream *prefix_bgp_orf_entry(struct stream *s, struct prefix_list *plist, + u_char init_flag, u_char permit_flag, + u_char deny_flag) { - struct prefix_list_entry *pentry; + struct prefix_list_entry *pentry; - if (! plist) - return s; + if (!plist) + return s; - for (pentry = plist->head; pentry; pentry = pentry->next) - { - u_char flag = init_flag; - struct prefix *p = &pentry->prefix; + for (pentry = plist->head; pentry; pentry = pentry->next) { + u_char flag = init_flag; + struct prefix *p = &pentry->prefix; - flag |= (pentry->type == PREFIX_PERMIT ? - permit_flag : deny_flag); - stream_putc (s, flag); - stream_putl (s, (u_int32_t)pentry->seq); - stream_putc (s, (u_char)pentry->ge); - stream_putc (s, (u_char)pentry->le); - stream_put_prefix (s, p); - } + flag |= (pentry->type == PREFIX_PERMIT ? permit_flag + : deny_flag); + stream_putc(s, flag); + stream_putl(s, (u_int32_t)pentry->seq); + stream_putc(s, (u_char)pentry->ge); + stream_putc(s, (u_char)pentry->le); + stream_put_prefix(s, p); + } - return s; + return s; } -int -prefix_bgp_orf_set (char *name, afi_t afi, struct orf_prefix *orfp, - int permit, int set) +int prefix_bgp_orf_set(char *name, afi_t afi, struct orf_prefix *orfp, + int permit, int set) { - struct prefix_list *plist; - struct prefix_list_entry *pentry; + struct prefix_list *plist; + struct prefix_list_entry *pentry; - /* ge and le value check */ - if (orfp->ge && orfp->ge <= orfp->p.prefixlen) - return CMD_WARNING_CONFIG_FAILED; - if (orfp->le && orfp->le <= orfp->p.prefixlen) - return CMD_WARNING_CONFIG_FAILED; - if (orfp->le && orfp->ge > orfp->le) - return CMD_WARNING_CONFIG_FAILED; + /* ge and le value check */ + if (orfp->ge && orfp->ge <= orfp->p.prefixlen) + return CMD_WARNING_CONFIG_FAILED; + if (orfp->le && orfp->le <= orfp->p.prefixlen) + return CMD_WARNING_CONFIG_FAILED; + if (orfp->le && orfp->ge > orfp->le) + return CMD_WARNING_CONFIG_FAILED; - if (orfp->ge && orfp->le == (afi == AFI_IP ? 32 : 128)) - orfp->le = 0; + if (orfp->ge && orfp->le == (afi == AFI_IP ? 32 : 128)) + orfp->le = 0; - plist = prefix_list_get (afi, 1, name); - if (! plist) - return CMD_WARNING_CONFIG_FAILED; + plist = prefix_list_get(afi, 1, name); + if (!plist) + return CMD_WARNING_CONFIG_FAILED; - if (set) - { - pentry = prefix_list_entry_make (&orfp->p, - (permit ? PREFIX_PERMIT : PREFIX_DENY), - orfp->seq, orfp->le, orfp->ge, 0); + if (set) { + pentry = prefix_list_entry_make( + &orfp->p, (permit ? PREFIX_PERMIT : PREFIX_DENY), + orfp->seq, orfp->le, orfp->ge, 0); - if (prefix_entry_dup_check (plist, pentry)) - { - prefix_list_entry_free (pentry); - return CMD_WARNING_CONFIG_FAILED; - } + if (prefix_entry_dup_check(plist, pentry)) { + prefix_list_entry_free(pentry); + return CMD_WARNING_CONFIG_FAILED; + } - prefix_list_entry_add (plist, pentry); - } - else - { - pentry = prefix_list_entry_lookup (plist, &orfp->p, - (permit ? PREFIX_PERMIT : PREFIX_DENY), - orfp->seq, orfp->le, orfp->ge); + prefix_list_entry_add(plist, pentry); + } else { + pentry = prefix_list_entry_lookup( + plist, &orfp->p, (permit ? PREFIX_PERMIT : PREFIX_DENY), + orfp->seq, orfp->le, orfp->ge); - if (! pentry) - return CMD_WARNING_CONFIG_FAILED; + if (!pentry) + return CMD_WARNING_CONFIG_FAILED; - prefix_list_entry_delete (plist, pentry, 1); - } + prefix_list_entry_delete(plist, pentry, 1); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } -void -prefix_bgp_orf_remove_all (afi_t afi, char *name) +void prefix_bgp_orf_remove_all(afi_t afi, char *name) { - struct prefix_list *plist; + struct prefix_list *plist; - plist = prefix_bgp_orf_lookup (afi, name); - if (plist) - prefix_list_delete (plist); + plist = prefix_bgp_orf_lookup(afi, name); + if (plist) + prefix_list_delete(plist); } /* return prefix count */ -int -prefix_bgp_show_prefix_list (struct vty *vty, afi_t afi, char *name, u_char use_json) -{ - struct prefix_list *plist; - struct prefix_list_entry *pentry; - json_object *json = NULL; - json_object *json_prefix = NULL; - json_object *json_list = NULL; - - plist = prefix_bgp_orf_lookup (afi, name); - if (! plist) - return 0; - - if (! vty) - return plist->count; - - if(use_json) - { - json = json_object_new_object(); - json_prefix = json_object_new_object(); - json_list = json_object_new_object(); - - json_object_int_add(json_prefix, "prefixListCounter", plist->count); - json_object_string_add(json_prefix, "prefixListName", plist->name); - - for (pentry = plist->head; pentry; pentry = pentry->next) - { - struct prefix *p = &pentry->prefix; - char buf_a[BUFSIZ]; - char buf_b[BUFSIZ]; - - sprintf(buf_a, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf_b, BUFSIZ), - p->prefixlen); - - json_object_int_add(json_list, "seq", pentry->seq); - json_object_string_add(json_list, "seqPrefixListType", prefix_list_type_str (pentry)); - - if (pentry->ge) - json_object_int_add(json_list, "ge", pentry->ge); - if (pentry->le) - json_object_int_add(json_list, "le", pentry->le); - - json_object_object_add(json_prefix, buf_a, json_list); - } - if (afi == AFI_IP) - json_object_object_add(json, "ipPrefixList", json_prefix); - else - json_object_object_add(json, "ipv6PrefixList", json_prefix); - - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - { - vty_out (vty, "ip%s prefix-list %s: %d entries\n", - afi == AFI_IP ? "" : "v6", - plist->name, plist->count); - - for (pentry = plist->head; pentry; pentry = pentry->next) - { - struct prefix *p = &pentry->prefix; - char buf[BUFSIZ]; - - vty_out (vty, " seq %u %s %s/%d", pentry->seq, - prefix_list_type_str (pentry), - inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), - p->prefixlen); - - if (pentry->ge) - vty_out (vty, " ge %d", pentry->ge); - if (pentry->le) - vty_out (vty, " le %d", pentry->le); - - vty_out (vty, "\n"); - } - } - return plist->count; -} - -static void -prefix_list_reset_afi (afi_t afi, int orf) -{ - struct prefix_list *plist; - struct prefix_list *next; - struct prefix_master *master; - - master = prefix_master_get (afi, orf); - if (master == NULL) - return; - - for (plist = master->num.head; plist; plist = next) - { - next = plist->next; - prefix_list_delete (plist); - } - for (plist = master->str.head; plist; plist = next) - { - next = plist->next; - prefix_list_delete (plist); - } - - assert (master->num.head == NULL); - assert (master->num.tail == NULL); - - assert (master->str.head == NULL); - assert (master->str.tail == NULL); - - master->seqnum = 1; - master->recent = NULL; +int prefix_bgp_show_prefix_list(struct vty *vty, afi_t afi, char *name, + u_char use_json) +{ + struct prefix_list *plist; + struct prefix_list_entry *pentry; + json_object *json = NULL; + json_object *json_prefix = NULL; + json_object *json_list = NULL; + + plist = prefix_bgp_orf_lookup(afi, name); + if (!plist) + return 0; + + if (!vty) + return plist->count; + + if (use_json) { + json = json_object_new_object(); + json_prefix = json_object_new_object(); + json_list = json_object_new_object(); + + json_object_int_add(json_prefix, "prefixListCounter", + plist->count); + json_object_string_add(json_prefix, "prefixListName", + plist->name); + + for (pentry = plist->head; pentry; pentry = pentry->next) { + struct prefix *p = &pentry->prefix; + char buf_a[BUFSIZ]; + char buf_b[BUFSIZ]; + + sprintf(buf_a, "%s/%d", + inet_ntop(p->family, &p->u.prefix, buf_b, + BUFSIZ), + p->prefixlen); + + json_object_int_add(json_list, "seq", pentry->seq); + json_object_string_add(json_list, "seqPrefixListType", + prefix_list_type_str(pentry)); + + if (pentry->ge) + json_object_int_add(json_list, "ge", + pentry->ge); + if (pentry->le) + json_object_int_add(json_list, "le", + pentry->le); + + json_object_object_add(json_prefix, buf_a, json_list); + } + if (afi == AFI_IP) + json_object_object_add(json, "ipPrefixList", + json_prefix); + else + json_object_object_add(json, "ipv6PrefixList", + json_prefix); + + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else { + vty_out(vty, "ip%s prefix-list %s: %d entries\n", + afi == AFI_IP ? "" : "v6", plist->name, plist->count); + + for (pentry = plist->head; pentry; pentry = pentry->next) { + struct prefix *p = &pentry->prefix; + char buf[BUFSIZ]; + + vty_out(vty, " seq %u %s %s/%d", pentry->seq, + prefix_list_type_str(pentry), + inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), + p->prefixlen); + + if (pentry->ge) + vty_out(vty, " ge %d", pentry->ge); + if (pentry->le) + vty_out(vty, " le %d", pentry->le); + + vty_out(vty, "\n"); + } + } + return plist->count; +} + +static void prefix_list_reset_afi(afi_t afi, int orf) +{ + struct prefix_list *plist; + struct prefix_list *next; + struct prefix_master *master; + + master = prefix_master_get(afi, orf); + if (master == NULL) + return; + + for (plist = master->num.head; plist; plist = next) { + next = plist->next; + prefix_list_delete(plist); + } + for (plist = master->str.head; plist; plist = next) { + next = plist->next; + prefix_list_delete(plist); + } + + assert(master->num.head == NULL); + assert(master->num.tail == NULL); + + assert(master->str.head == NULL); + assert(master->str.tail == NULL); + + master->seqnum = 1; + master->recent = NULL; } /* Prefix-list node. */ -static struct cmd_node prefix_node = -{ - PREFIX_NODE, - "", /* Prefix list has no interface. */ - 1 -}; +static struct cmd_node prefix_node = {PREFIX_NODE, + "", /* Prefix list has no interface. */ + 1}; -static int -config_write_prefix_ipv4 (struct vty *vty) +static int config_write_prefix_ipv4(struct vty *vty) { - return config_write_prefix_afi (AFI_IP, vty); + return config_write_prefix_afi(AFI_IP, vty); } -static void -plist_autocomplete_afi (afi_t afi, vector comps, struct cmd_token *token) +static void plist_autocomplete_afi(afi_t afi, vector comps, + struct cmd_token *token) { - struct prefix_list *plist; - struct prefix_master *master; + struct prefix_list *plist; + struct prefix_master *master; - master = prefix_master_get (afi, 0); - if (master == NULL) - return; + master = prefix_master_get(afi, 0); + if (master == NULL) + return; - for (plist = master->str.head; plist; plist = plist->next) - vector_set (comps, XSTRDUP (MTYPE_COMPLETION, plist->name)); - for (plist = master->num.head; plist; plist = plist->next) - vector_set (comps, XSTRDUP (MTYPE_COMPLETION, plist->name)); + for (plist = master->str.head; plist; plist = plist->next) + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, plist->name)); + for (plist = master->num.head; plist; plist = plist->next) + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, plist->name)); } -static void -plist_autocomplete(vector comps, struct cmd_token *token) +static void plist_autocomplete(vector comps, struct cmd_token *token) { - plist_autocomplete_afi (AFI_IP, comps, token); - plist_autocomplete_afi (AFI_IP6, comps, token); + plist_autocomplete_afi(AFI_IP, comps, token); + plist_autocomplete_afi(AFI_IP6, comps, token); } static const struct cmd_variable_handler plist_var_handlers[] = { - { - /* "prefix-list WORD" */ - .varname = "prefix_list", - .completions = plist_autocomplete - }, { - .completions = NULL - } -}; + {/* "prefix-list WORD" */ + .varname = "prefix_list", + .completions = plist_autocomplete}, + {.completions = NULL}}; -static void -prefix_list_init_ipv4 (void) +static void prefix_list_init_ipv4(void) { - install_node (&prefix_node, config_write_prefix_ipv4); + install_node(&prefix_node, config_write_prefix_ipv4); - install_element (CONFIG_NODE, &ip_prefix_list_cmd); - install_element (CONFIG_NODE, &no_ip_prefix_list_cmd); - install_element (CONFIG_NODE, &no_ip_prefix_list_all_cmd); + install_element(CONFIG_NODE, &ip_prefix_list_cmd); + install_element(CONFIG_NODE, &no_ip_prefix_list_cmd); + install_element(CONFIG_NODE, &no_ip_prefix_list_all_cmd); - install_element (CONFIG_NODE, &ip_prefix_list_description_cmd); - install_element (CONFIG_NODE, &no_ip_prefix_list_description_cmd); - install_element (CONFIG_NODE, &no_ip_prefix_list_description_comment_cmd); + install_element(CONFIG_NODE, &ip_prefix_list_description_cmd); + install_element(CONFIG_NODE, &no_ip_prefix_list_description_cmd); + install_element(CONFIG_NODE, + &no_ip_prefix_list_description_comment_cmd); - install_element (CONFIG_NODE, &ip_prefix_list_sequence_number_cmd); + install_element(CONFIG_NODE, &ip_prefix_list_sequence_number_cmd); - install_element (VIEW_NODE, &show_ip_prefix_list_cmd); - install_element (VIEW_NODE, &show_ip_prefix_list_prefix_cmd); - install_element (VIEW_NODE, &show_ip_prefix_list_summary_cmd); - install_element (VIEW_NODE, &show_ip_prefix_list_detail_cmd); + install_element(VIEW_NODE, &show_ip_prefix_list_cmd); + install_element(VIEW_NODE, &show_ip_prefix_list_prefix_cmd); + install_element(VIEW_NODE, &show_ip_prefix_list_summary_cmd); + install_element(VIEW_NODE, &show_ip_prefix_list_detail_cmd); - install_element (ENABLE_NODE, &clear_ip_prefix_list_cmd); + install_element(ENABLE_NODE, &clear_ip_prefix_list_cmd); } /* Prefix-list node. */ -static struct cmd_node prefix_ipv6_node = -{ - PREFIX_IPV6_NODE, - "", /* Prefix list has no interface. */ - 1 -}; +static struct cmd_node prefix_ipv6_node = { + PREFIX_IPV6_NODE, "", /* Prefix list has no interface. */ + 1}; -static int -config_write_prefix_ipv6 (struct vty *vty) +static int config_write_prefix_ipv6(struct vty *vty) { - return config_write_prefix_afi (AFI_IP6, vty); + return config_write_prefix_afi(AFI_IP6, vty); } -static void -prefix_list_init_ipv6 (void) +static void prefix_list_init_ipv6(void) { - install_node (&prefix_ipv6_node, config_write_prefix_ipv6); + install_node(&prefix_ipv6_node, config_write_prefix_ipv6); - install_element (CONFIG_NODE, &ipv6_prefix_list_cmd); - install_element (CONFIG_NODE, &no_ipv6_prefix_list_cmd); - install_element (CONFIG_NODE, &no_ipv6_prefix_list_all_cmd); + install_element(CONFIG_NODE, &ipv6_prefix_list_cmd); + install_element(CONFIG_NODE, &no_ipv6_prefix_list_cmd); + install_element(CONFIG_NODE, &no_ipv6_prefix_list_all_cmd); - install_element (CONFIG_NODE, &ipv6_prefix_list_description_cmd); - install_element (CONFIG_NODE, &no_ipv6_prefix_list_description_cmd); - install_element (CONFIG_NODE, &no_ipv6_prefix_list_description_comment_cmd); + install_element(CONFIG_NODE, &ipv6_prefix_list_description_cmd); + install_element(CONFIG_NODE, &no_ipv6_prefix_list_description_cmd); + install_element(CONFIG_NODE, + &no_ipv6_prefix_list_description_comment_cmd); - install_element (CONFIG_NODE, &ipv6_prefix_list_sequence_number_cmd); + install_element(CONFIG_NODE, &ipv6_prefix_list_sequence_number_cmd); - install_element (VIEW_NODE, &show_ipv6_prefix_list_cmd); - install_element (VIEW_NODE, &show_ipv6_prefix_list_prefix_cmd); - install_element (VIEW_NODE, &show_ipv6_prefix_list_summary_cmd); - install_element (VIEW_NODE, &show_ipv6_prefix_list_detail_cmd); + install_element(VIEW_NODE, &show_ipv6_prefix_list_cmd); + install_element(VIEW_NODE, &show_ipv6_prefix_list_prefix_cmd); + install_element(VIEW_NODE, &show_ipv6_prefix_list_summary_cmd); + install_element(VIEW_NODE, &show_ipv6_prefix_list_detail_cmd); - install_element (ENABLE_NODE, &clear_ipv6_prefix_list_cmd); + install_element(ENABLE_NODE, &clear_ipv6_prefix_list_cmd); } -void -prefix_list_init () +void prefix_list_init() { - cmd_variable_handler_register(plist_var_handlers); + cmd_variable_handler_register(plist_var_handlers); - prefix_list_init_ipv4 (); - prefix_list_init_ipv6 (); + prefix_list_init_ipv4(); + prefix_list_init_ipv6(); } -void -prefix_list_reset () +void prefix_list_reset() { - prefix_list_reset_afi (AFI_IP, 0); - prefix_list_reset_afi (AFI_IP6, 0); - prefix_list_reset_afi (AFI_IP, 1); - prefix_list_reset_afi (AFI_IP6, 1); + prefix_list_reset_afi(AFI_IP, 0); + prefix_list_reset_afi(AFI_IP6, 0); + prefix_list_reset_afi(AFI_IP, 1); + prefix_list_reset_afi(AFI_IP6, 1); } diff --git a/lib/plist.h b/lib/plist.h index 0f397ff01..73d8da509 100644 --- a/lib/plist.h +++ b/lib/plist.h @@ -27,38 +27,36 @@ #include "stream.h" #include "vty.h" -enum prefix_list_type -{ - PREFIX_DENY, - PREFIX_PERMIT, +enum prefix_list_type { + PREFIX_DENY, + PREFIX_PERMIT, }; struct prefix_list; -struct orf_prefix -{ - u_int32_t seq; - u_char ge; - u_char le; - struct prefix p; +struct orf_prefix { + u_int32_t seq; + u_char ge; + u_char le; + struct prefix p; }; /* Prototypes. */ -extern void prefix_list_init (void); -extern void prefix_list_reset (void); -extern void prefix_list_add_hook (void (*func) (struct prefix_list *)); -extern void prefix_list_delete_hook (void (*func) (struct prefix_list *)); - -extern const char *prefix_list_name (struct prefix_list *); -extern struct prefix_list *prefix_list_lookup (afi_t, const char *); -extern enum prefix_list_type prefix_list_apply (struct prefix_list *, void *); - -extern struct prefix_list *prefix_bgp_orf_lookup (afi_t, const char *); -extern struct stream * prefix_bgp_orf_entry (struct stream *, - struct prefix_list *, - u_char, u_char, u_char); -extern int prefix_bgp_orf_set (char *, afi_t, struct orf_prefix *, int, int); -extern void prefix_bgp_orf_remove_all (afi_t, char *); -extern int prefix_bgp_show_prefix_list (struct vty *, afi_t, char *, u_char); +extern void prefix_list_init(void); +extern void prefix_list_reset(void); +extern void prefix_list_add_hook(void (*func)(struct prefix_list *)); +extern void prefix_list_delete_hook(void (*func)(struct prefix_list *)); + +extern const char *prefix_list_name(struct prefix_list *); +extern struct prefix_list *prefix_list_lookup(afi_t, const char *); +extern enum prefix_list_type prefix_list_apply(struct prefix_list *, void *); + +extern struct prefix_list *prefix_bgp_orf_lookup(afi_t, const char *); +extern struct stream *prefix_bgp_orf_entry(struct stream *, + struct prefix_list *, u_char, u_char, + u_char); +extern int prefix_bgp_orf_set(char *, afi_t, struct orf_prefix *, int, int); +extern void prefix_bgp_orf_remove_all(afi_t, char *); +extern int prefix_bgp_show_prefix_list(struct vty *, afi_t, char *, u_char); #endif /* _QUAGGA_PLIST_H */ diff --git a/lib/plist_int.h b/lib/plist_int.h index e711d1256..aa81a3bce 100644 --- a/lib/plist_int.h +++ b/lib/plist_int.h @@ -22,56 +22,50 @@ #ifndef _QUAGGA_PLIST_INT_H #define _QUAGGA_PLIST_INT_H -enum prefix_name_type -{ - PREFIX_TYPE_STRING, - PREFIX_TYPE_NUMBER -}; +enum prefix_name_type { PREFIX_TYPE_STRING, PREFIX_TYPE_NUMBER }; struct pltrie_table; -struct prefix_list -{ - char *name; - char *desc; +struct prefix_list { + char *name; + char *desc; - struct prefix_master *master; + struct prefix_master *master; - enum prefix_name_type type; + enum prefix_name_type type; - int count; - int rangecount; + int count; + int rangecount; - struct prefix_list_entry *head; - struct prefix_list_entry *tail; + struct prefix_list_entry *head; + struct prefix_list_entry *tail; - struct pltrie_table *trie; + struct pltrie_table *trie; - struct prefix_list *next; - struct prefix_list *prev; + struct prefix_list *next; + struct prefix_list *prev; }; /* Each prefix-list's entry. */ -struct prefix_list_entry -{ - int seq; +struct prefix_list_entry { + int seq; - int le; - int ge; + int le; + int ge; - enum prefix_list_type type; + enum prefix_list_type type; - int any; - struct prefix prefix; + int any; + struct prefix prefix; - unsigned long refcnt; - unsigned long hitcnt; + unsigned long refcnt; + unsigned long hitcnt; - struct prefix_list_entry *next; - struct prefix_list_entry *prev; + struct prefix_list_entry *next; + struct prefix_list_entry *prev; - /* up the chain for best match search */ - struct prefix_list_entry *next_best; + /* up the chain for best match search */ + struct prefix_list_entry *next_best; }; #endif /* _QUAGGA_PLIST_INT_H */ diff --git a/lib/pqueue.c b/lib/pqueue.c index 2d9127b88..1565de216 100644 --- a/lib/pqueue.c +++ b/lib/pqueue.c @@ -23,7 +23,7 @@ #include "memory.h" #include "pqueue.h" -DEFINE_MTYPE_STATIC(LIB, PQUEUE, "Priority queue") +DEFINE_MTYPE_STATIC(LIB, PQUEUE, "Priority queue") DEFINE_MTYPE_STATIC(LIB, PQUEUE_DATA, "Priority queue data") /* priority queue using heap sort */ @@ -45,154 +45,143 @@ DEFINE_MTYPE_STATIC(LIB, PQUEUE_DATA, "Priority queue data") #define RIGHT_OF(x) (2 * x + 2) #define HAVE_CHILD(x,q) (x < (q)->size / 2) -void -trickle_up (int index, struct pqueue *queue) +void trickle_up(int index, struct pqueue *queue) { - void *tmp; - - /* Save current node as tmp node. */ - tmp = queue->array[index]; - - /* Continue until the node reaches top or the place where the parent - node should be upper than the tmp node. */ - while (index > 0 && - (*queue->cmp) (tmp, queue->array[PARENT_OF (index)]) < 0) - { - /* actually trickle up */ - queue->array[index] = queue->array[PARENT_OF (index)]; - if (queue->update != NULL) - (*queue->update) (queue->array[index], index); - index = PARENT_OF (index); - } - - /* Restore the tmp node to appropriate place. */ - queue->array[index] = tmp; - if (queue->update != NULL) - (*queue->update) (tmp, index); + void *tmp; + + /* Save current node as tmp node. */ + tmp = queue->array[index]; + + /* Continue until the node reaches top or the place where the parent + node should be upper than the tmp node. */ + while (index > 0 + && (*queue->cmp)(tmp, queue->array[PARENT_OF(index)]) < 0) { + /* actually trickle up */ + queue->array[index] = queue->array[PARENT_OF(index)]; + if (queue->update != NULL) + (*queue->update)(queue->array[index], index); + index = PARENT_OF(index); + } + + /* Restore the tmp node to appropriate place. */ + queue->array[index] = tmp; + if (queue->update != NULL) + (*queue->update)(tmp, index); } -void -trickle_down (int index, struct pqueue *queue) +void trickle_down(int index, struct pqueue *queue) { - void *tmp; - int which; - - /* Save current node as tmp node. */ - tmp = queue->array[index]; - - /* Continue until the node have at least one (left) child. */ - while (HAVE_CHILD (index, queue)) - { - /* If right child exists, and if the right child is more proper - to be moved upper. */ - if (RIGHT_OF (index) < queue->size && - (*queue->cmp) (queue->array[LEFT_OF (index)], - queue->array[RIGHT_OF (index)]) > 0) - which = RIGHT_OF (index); - else - which = LEFT_OF (index); - - /* If the tmp node should be upper than the child, break. */ - if ((*queue->cmp) (queue->array[which], tmp) > 0) - break; - - /* Actually trickle down the tmp node. */ - queue->array[index] = queue->array[which]; - if (queue->update != NULL) - (*queue->update) (queue->array[index], index); - index = which; - } - - /* Restore the tmp node to appropriate place. */ - queue->array[index] = tmp; - if (queue->update != NULL) - (*queue->update) (tmp, index); + void *tmp; + int which; + + /* Save current node as tmp node. */ + tmp = queue->array[index]; + + /* Continue until the node have at least one (left) child. */ + while (HAVE_CHILD(index, queue)) { + /* If right child exists, and if the right child is more proper + to be moved upper. */ + if (RIGHT_OF(index) < queue->size + && (*queue->cmp)(queue->array[LEFT_OF(index)], + queue->array[RIGHT_OF(index)]) + > 0) + which = RIGHT_OF(index); + else + which = LEFT_OF(index); + + /* If the tmp node should be upper than the child, break. */ + if ((*queue->cmp)(queue->array[which], tmp) > 0) + break; + + /* Actually trickle down the tmp node. */ + queue->array[index] = queue->array[which]; + if (queue->update != NULL) + (*queue->update)(queue->array[index], index); + index = which; + } + + /* Restore the tmp node to appropriate place. */ + queue->array[index] = tmp; + if (queue->update != NULL) + (*queue->update)(tmp, index); } -struct pqueue * -pqueue_create (void) +struct pqueue *pqueue_create(void) { - struct pqueue *queue; + struct pqueue *queue; - queue = XCALLOC (MTYPE_PQUEUE, sizeof (struct pqueue)); + queue = XCALLOC(MTYPE_PQUEUE, sizeof(struct pqueue)); - queue->array = XCALLOC (MTYPE_PQUEUE_DATA, - DATA_SIZE * PQUEUE_INIT_ARRAYSIZE); - queue->array_size = PQUEUE_INIT_ARRAYSIZE; + queue->array = + XCALLOC(MTYPE_PQUEUE_DATA, DATA_SIZE * PQUEUE_INIT_ARRAYSIZE); + queue->array_size = PQUEUE_INIT_ARRAYSIZE; - /* By default we want nothing to happen when a node changes. */ - queue->update = NULL; - return queue; + /* By default we want nothing to happen when a node changes. */ + queue->update = NULL; + return queue; } -void -pqueue_delete (struct pqueue *queue) +void pqueue_delete(struct pqueue *queue) { - XFREE (MTYPE_PQUEUE_DATA, queue->array); - XFREE (MTYPE_PQUEUE, queue); + XFREE(MTYPE_PQUEUE_DATA, queue->array); + XFREE(MTYPE_PQUEUE, queue); } -static int -pqueue_expand (struct pqueue *queue) +static int pqueue_expand(struct pqueue *queue) { - void **newarray; + void **newarray; - newarray = XCALLOC (MTYPE_PQUEUE_DATA, queue->array_size * DATA_SIZE * 2); - if (newarray == NULL) - return 0; + newarray = + XCALLOC(MTYPE_PQUEUE_DATA, queue->array_size * DATA_SIZE * 2); + if (newarray == NULL) + return 0; - memcpy (newarray, queue->array, queue->array_size * DATA_SIZE); + memcpy(newarray, queue->array, queue->array_size * DATA_SIZE); - XFREE (MTYPE_PQUEUE_DATA, queue->array); - queue->array = newarray; - queue->array_size *= 2; + XFREE(MTYPE_PQUEUE_DATA, queue->array); + queue->array = newarray; + queue->array_size *= 2; - return 1; + return 1; } -void -pqueue_enqueue (void *data, struct pqueue *queue) +void pqueue_enqueue(void *data, struct pqueue *queue) { - if (queue->size + 2 >= queue->array_size && ! pqueue_expand (queue)) - return; - - queue->array[queue->size] = data; - if (queue->update != NULL) - (*queue->update) (data, queue->size); - trickle_up (queue->size, queue); - queue->size ++; + if (queue->size + 2 >= queue->array_size && !pqueue_expand(queue)) + return; + + queue->array[queue->size] = data; + if (queue->update != NULL) + (*queue->update)(data, queue->size); + trickle_up(queue->size, queue); + queue->size++; } -void * -pqueue_dequeue (struct pqueue *queue) +void *pqueue_dequeue(struct pqueue *queue) { - void *data = queue->array[0]; - queue->array[0] = queue->array[--queue->size]; - trickle_down (0, queue); - return data; + void *data = queue->array[0]; + queue->array[0] = queue->array[--queue->size]; + trickle_down(0, queue); + return data; } -void -pqueue_remove_at (int index, struct pqueue *queue) +void pqueue_remove_at(int index, struct pqueue *queue) { - queue->array[index] = queue->array[--queue->size]; - - if (index > 0 - && (*queue->cmp) (queue->array[index], - queue->array[PARENT_OF(index)]) < 0) - { - trickle_up (index, queue); - } - else - { - trickle_down (index, queue); - } + queue->array[index] = queue->array[--queue->size]; + + if (index > 0 + && (*queue->cmp)(queue->array[index], + queue->array[PARENT_OF(index)]) + < 0) { + trickle_up(index, queue); + } else { + trickle_down(index, queue); + } } -void -pqueue_remove (void *data, struct pqueue *queue) +void pqueue_remove(void *data, struct pqueue *queue) { - for (int i = 0; i < queue->size; i++) - if (queue->array[i] == data) - pqueue_remove_at (i, queue); + for (int i = 0; i < queue->size; i++) + if (queue->array[i] == data) + pqueue_remove_at(i, queue); } diff --git a/lib/pqueue.h b/lib/pqueue.h index d87d91fdc..53e5aa833 100644 --- a/lib/pqueue.h +++ b/lib/pqueue.h @@ -21,27 +21,26 @@ #ifndef _ZEBRA_PQUEUE_H #define _ZEBRA_PQUEUE_H -struct pqueue -{ - void **array; - int array_size; - int size; - - int (*cmp) (void *, void *); - void (*update) (void * node, int actual_position); +struct pqueue { + void **array; + int array_size; + int size; + + int (*cmp)(void *, void *); + void (*update)(void *node, int actual_position); }; #define PQUEUE_INIT_ARRAYSIZE 32 -extern struct pqueue *pqueue_create (void); -extern void pqueue_delete (struct pqueue *queue); +extern struct pqueue *pqueue_create(void); +extern void pqueue_delete(struct pqueue *queue); -extern void pqueue_enqueue (void *data, struct pqueue *queue); -extern void *pqueue_dequeue (struct pqueue *queue); -extern void pqueue_remove_at (int index, struct pqueue *queue); -extern void pqueue_remove (void *data, struct pqueue *queue); +extern void pqueue_enqueue(void *data, struct pqueue *queue); +extern void *pqueue_dequeue(struct pqueue *queue); +extern void pqueue_remove_at(int index, struct pqueue *queue); +extern void pqueue_remove(void *data, struct pqueue *queue); -extern void trickle_down (int index, struct pqueue *queue); -extern void trickle_up (int index, struct pqueue *queue); +extern void trickle_down(int index, struct pqueue *queue); +extern void trickle_up(int index, struct pqueue *queue); #endif /* _ZEBRA_PQUEUE_H */ diff --git a/lib/prefix.c b/lib/prefix.c index f89b5a5ee..88b13cd99 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -31,140 +31,395 @@ DEFINE_MTYPE_STATIC(LIB, PREFIX, "Prefix") /* Maskbit. */ static const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, - 0xf8, 0xfc, 0xfe, 0xff}; - -static const struct in6_addr maskbytes6[] = -{ - /* /0 */ { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /1 */ { { { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /2 */ { { { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /3 */ { { { 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /4 */ { { { 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /5 */ { { { 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /6 */ { { { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /7 */ { { { 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /8 */ { { { 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /9 */ { { { 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /10 */ { { { 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /11 */ { { { 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /12 */ { { { 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /13 */ { { { 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /14 */ { { { 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /15 */ { { { 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /16 */ { { { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /17 */ { { { 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /18 */ { { { 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /19 */ { { { 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /20 */ { { { 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /21 */ { { { 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /22 */ { { { 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /23 */ { { { 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /24 */ { { { 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /25 */ { { { 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /26 */ { { { 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /27 */ { { { 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /28 */ { { { 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /29 */ { { { 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /30 */ { { { 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /31 */ { { { 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /32 */ { { { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /33 */ { { { 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /34 */ { { { 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /35 */ { { { 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /36 */ { { { 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /37 */ { { { 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /38 */ { { { 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /39 */ { { { 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /40 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /41 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /42 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /43 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /44 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /45 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /46 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /47 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /48 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /49 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /50 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /51 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /52 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /53 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /54 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /55 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /56 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /57 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /58 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /59 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /60 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /61 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /62 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /63 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /64 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /65 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /66 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /67 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /68 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /69 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /70 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /71 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /72 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /73 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /74 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /75 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /76 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /77 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /78 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /79 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /80 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /81 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /82 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /83 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /84 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /85 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /86 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /87 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /88 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, - /* /89 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00 } } }, - /* /90 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00 } } }, - /* /91 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00 } } }, - /* /92 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00 } } }, - /* /93 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00 } } }, - /* /94 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00 } } }, - /* /95 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00 } } }, - /* /96 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } } }, - /* /97 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00 } } }, - /* /98 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00 } } }, - /* /99 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00 } } }, - /* /100 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00 } } }, - /* /101 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00 } } }, - /* /102 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00 } } }, - /* /103 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00 } } }, - /* /104 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00 } } }, - /* /105 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00 } } }, - /* /106 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00 } } }, - /* /107 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00 } } }, - /* /108 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00 } } }, - /* /109 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00 } } }, - /* /110 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00 } } }, - /* /111 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00 } } }, - /* /112 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 } } }, - /* /113 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00 } } }, - /* /114 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00 } } }, - /* /115 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00 } } }, - /* /116 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00 } } }, - /* /117 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00 } } }, - /* /118 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00 } } }, - /* /119 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00 } } }, - /* /120 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 } } }, - /* /121 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80 } } }, - /* /122 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0 } } }, - /* /123 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0 } } }, - /* /124 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0 } } }, - /* /125 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8 } } }, - /* /126 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc } } }, - /* /127 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe } } }, - /* /128 */ { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } } -}; + 0xf8, 0xfc, 0xfe, 0xff}; + +static const struct in6_addr maskbytes6[] = { + /* /0 */ {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /1 */ + {{{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /2 */ + {{{0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /3 */ + {{{0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /4 */ + {{{0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /5 */ + {{{0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /6 */ + {{{0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /7 */ + {{{0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /8 */ + {{{0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /9 */ + {{{0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /10 */ + {{{0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /11 */ + {{{0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /12 */ + {{{0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /13 */ + {{{0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /14 */ + {{{0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /15 */ + {{{0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /16 */ + {{{0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /17 */ + {{{0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /18 */ + {{{0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /19 */ + {{{0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /20 */ + {{{0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /21 */ + {{{0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /22 */ + {{{0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /23 */ + {{{0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /24 */ + {{{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /25 */ + {{{0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /26 */ + {{{0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /27 */ + {{{0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /28 */ + {{{0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /29 */ + {{{0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /30 */ + {{{0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /31 */ + {{{0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /32 */ + {{{0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /33 */ + {{{0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /34 */ + {{{0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /35 */ + {{{0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /36 */ + {{{0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /37 */ + {{{0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /38 */ + {{{0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /39 */ + {{{0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /40 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /41 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /42 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /43 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /44 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /45 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /46 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /47 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /48 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /49 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /50 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /51 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /52 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /53 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /54 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /55 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /56 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /57 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /58 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /59 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /60 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /61 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /62 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /63 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /64 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /65 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /66 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /67 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /68 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /69 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /70 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /71 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /72 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /73 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /74 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /75 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /76 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /77 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /78 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /79 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /80 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /81 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /82 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /83 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /84 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /85 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /86 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /87 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /88 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00}}}, + /* /89 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x80, 0x00, 0x00, 0x00, 0x00}}}, + /* /90 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xc0, 0x00, 0x00, 0x00, 0x00}}}, + /* /91 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xe0, 0x00, 0x00, 0x00, 0x00}}}, + /* /92 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf0, 0x00, 0x00, 0x00, 0x00}}}, + /* /93 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf8, 0x00, 0x00, 0x00, 0x00}}}, + /* /94 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfc, 0x00, 0x00, 0x00, 0x00}}}, + /* /95 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0x00, 0x00, 0x00, 0x00}}}, + /* /96 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00}}}, + /* /97 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x80, 0x00, 0x00, 0x00}}}, + /* /98 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xc0, 0x00, 0x00, 0x00}}}, + /* /99 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xe0, 0x00, 0x00, 0x00}}}, + /* /100 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf0, 0x00, 0x00, 0x00}}}, + /* /101 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf8, 0x00, 0x00, 0x00}}}, + /* /102 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfc, 0x00, 0x00, 0x00}}}, + /* /103 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfe, 0x00, 0x00, 0x00}}}, + /* /104 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00}}}, + /* /105 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x80, 0x00, 0x00}}}, + /* /106 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xc0, 0x00, 0x00}}}, + /* /107 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xe0, 0x00, 0x00}}}, + /* /108 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf0, 0x00, 0x00}}}, + /* /109 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf8, 0x00, 0x00}}}, + /* /110 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfc, 0x00, 0x00}}}, + /* /111 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0x00, 0x00}}}, + /* /112 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x00}}}, + /* /113 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x80, 0x00}}}, + /* /114 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xc0, 0x00}}}, + /* /115 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xe0, 0x00}}}, + /* /116 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x00}}}, + /* /117 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf8, 0x00}}}, + /* /118 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfc, 0x00}}}, + /* /119 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0x00}}}, + /* /120 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00}}}, + /* /121 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x80}}}, + /* /122 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xc0}}}, + /* /123 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xe0}}}, + /* /124 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf0}}}, + /* /125 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf8}}}, + /* /126 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfc}}}, + /* /127 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfe}}}, + /* /128 */ + {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff}}}}; /* Number of bits in prefix type. */ #ifndef PNBBY @@ -173,178 +428,166 @@ static const struct in6_addr maskbytes6[] = #define MASKBIT(offset) ((0xff << (PNBBY - (offset))) & 0xff) -unsigned int -prefix_bit (const u_char *prefix, const u_char prefixlen) +unsigned int prefix_bit(const u_char *prefix, const u_char prefixlen) { - unsigned int offset = prefixlen / 8; - unsigned int shift = 7 - (prefixlen % 8); - - return (prefix[offset] >> shift) & 1; + unsigned int offset = prefixlen / 8; + unsigned int shift = 7 - (prefixlen % 8); + + return (prefix[offset] >> shift) & 1; } -unsigned int -prefix6_bit (const struct in6_addr *prefix, const u_char prefixlen) +unsigned int prefix6_bit(const struct in6_addr *prefix, const u_char prefixlen) { - return prefix_bit((const u_char *) &prefix->s6_addr, prefixlen); + return prefix_bit((const u_char *)&prefix->s6_addr, prefixlen); } -int -str2family(const char *string) +int str2family(const char *string) { - if (!strcmp("ipv4", string)) - return AF_INET; - else if (!strcmp("ipv6", string)) - return AF_INET6; - else if (!strcmp("ethernet", string)) - return AF_ETHERNET; - return -1; + if (!strcmp("ipv4", string)) + return AF_INET; + else if (!strcmp("ipv6", string)) + return AF_INET6; + else if (!strcmp("ethernet", string)) + return AF_ETHERNET; + return -1; } /* Address Famiy Identifier to Address Family converter. */ -int -afi2family (afi_t afi) +int afi2family(afi_t afi) { - if (afi == AFI_IP) - return AF_INET; - else if (afi == AFI_IP6) - return AF_INET6; - else if (afi == AFI_L2VPN) - return AF_ETHERNET; - return 0; + if (afi == AFI_IP) + return AF_INET; + else if (afi == AFI_IP6) + return AF_INET6; + else if (afi == AFI_L2VPN) + return AF_ETHERNET; + return 0; } -afi_t -family2afi (int family) +afi_t family2afi(int family) { - if (family == AF_INET) - return AFI_IP; - else if (family == AF_INET6) - return AFI_IP6; - else if (family == AF_ETHERNET) - return AFI_L2VPN; - return 0; + if (family == AF_INET) + return AFI_IP; + else if (family == AF_INET6) + return AFI_IP6; + else if (family == AF_ETHERNET) + return AFI_L2VPN; + return 0; } -const char * -afi2str(afi_t afi) +const char *afi2str(afi_t afi) { - switch (afi) { - case AFI_IP: - return "IPv4"; - case AFI_IP6: - return "IPv6"; - case AFI_L2VPN: - return "l2vpn"; - case AFI_MAX: - return "bad-value"; - default: - break; - } - return NULL; + switch (afi) { + case AFI_IP: + return "IPv4"; + case AFI_IP6: + return "IPv6"; + case AFI_L2VPN: + return "l2vpn"; + case AFI_MAX: + return "bad-value"; + default: + break; + } + return NULL; } -const char * -safi2str(safi_t safi) +const char *safi2str(safi_t safi) { - switch (safi) { - case SAFI_UNICAST: - return "unicast"; - case SAFI_MULTICAST: - return "multicast"; - case SAFI_MPLS_VPN: - return "vpn"; - case SAFI_ENCAP: - return "encap"; - case SAFI_EVPN: - return "evpn"; - case SAFI_LABELED_UNICAST: - return "labeled-unicast"; - } - return NULL; + switch (safi) { + case SAFI_UNICAST: + return "unicast"; + case SAFI_MULTICAST: + return "multicast"; + case SAFI_MPLS_VPN: + return "vpn"; + case SAFI_ENCAP: + return "encap"; + case SAFI_EVPN: + return "evpn"; + case SAFI_LABELED_UNICAST: + return "labeled-unicast"; + } + return NULL; } /* If n includes p prefix then return 1 else return 0. */ -int -prefix_match (const struct prefix *n, const struct prefix *p) +int prefix_match(const struct prefix *n, const struct prefix *p) { - int offset; - int shift; - const u_char *np, *pp; - - /* If n's prefix is longer than p's one return 0. */ - if (n->prefixlen > p->prefixlen) - return 0; - - /* Set both prefix's head pointer. */ - np = (const u_char *)&n->u.prefix; - pp = (const u_char *)&p->u.prefix; - - offset = n->prefixlen / PNBBY; - shift = n->prefixlen % PNBBY; - - if (shift) - if (maskbit[shift] & (np[offset] ^ pp[offset])) - return 0; - - while (offset--) - if (np[offset] != pp[offset]) - return 0; - return 1; + int offset; + int shift; + const u_char *np, *pp; + + /* If n's prefix is longer than p's one return 0. */ + if (n->prefixlen > p->prefixlen) + return 0; + + /* Set both prefix's head pointer. */ + np = (const u_char *)&n->u.prefix; + pp = (const u_char *)&p->u.prefix; + + offset = n->prefixlen / PNBBY; + shift = n->prefixlen % PNBBY; + + if (shift) + if (maskbit[shift] & (np[offset] ^ pp[offset])) + return 0; + + while (offset--) + if (np[offset] != pp[offset]) + return 0; + return 1; } /* If n includes p then return 1 else return 0. Prefix mask is not considered */ -int -prefix_match_network_statement (const struct prefix *n, const struct prefix *p) +int prefix_match_network_statement(const struct prefix *n, + const struct prefix *p) { - int offset; - int shift; - const u_char *np, *pp; + int offset; + int shift; + const u_char *np, *pp; - /* Set both prefix's head pointer. */ - np = (const u_char *)&n->u.prefix; - pp = (const u_char *)&p->u.prefix; + /* Set both prefix's head pointer. */ + np = (const u_char *)&n->u.prefix; + pp = (const u_char *)&p->u.prefix; - offset = n->prefixlen / PNBBY; - shift = n->prefixlen % PNBBY; + offset = n->prefixlen / PNBBY; + shift = n->prefixlen % PNBBY; - if (shift) - if (maskbit[shift] & (np[offset] ^ pp[offset])) - return 0; + if (shift) + if (maskbit[shift] & (np[offset] ^ pp[offset])) + return 0; - while (offset--) - if (np[offset] != pp[offset]) - return 0; - return 1; + while (offset--) + if (np[offset] != pp[offset]) + return 0; + return 1; } /* Copy prefix from src to dest. */ -void -prefix_copy (struct prefix *dest, const struct prefix *src) +void prefix_copy(struct prefix *dest, const struct prefix *src) { - dest->family = src->family; - dest->prefixlen = src->prefixlen; - - if (src->family == AF_INET) - dest->u.prefix4 = src->u.prefix4; - else if (src->family == AF_INET6) - dest->u.prefix6 = src->u.prefix6; - else if (src->family == AF_ETHERNET) - { - memcpy (&dest->u.prefix_evpn, &src->u.prefix_evpn, sizeof (struct evpn_addr)); - } - else if (src->family == AF_UNSPEC) - { - dest->u.lp.id = src->u.lp.id; - dest->u.lp.adv_router = src->u.lp.adv_router; - } - else - { - zlog_err("prefix_copy(): Unknown address family %d", src->family); - assert (0); - } + dest->family = src->family; + dest->prefixlen = src->prefixlen; + + if (src->family == AF_INET) + dest->u.prefix4 = src->u.prefix4; + else if (src->family == AF_INET6) + dest->u.prefix6 = src->u.prefix6; + else if (src->family == AF_ETHERNET) { + memcpy(&dest->u.prefix_evpn, &src->u.prefix_evpn, + sizeof(struct evpn_addr)); + } else if (src->family == AF_UNSPEC) { + dest->u.lp.id = src->u.lp.id; + dest->u.lp.adv_router = src->u.lp.adv_router; + } else { + zlog_err("prefix_copy(): Unknown address family %d", + src->family); + assert(0); + } } -/* +/* * Return 1 if the address/netmask contained in the prefix structure * is the same, and else return 0. For this routine, 'same' requires * that not only the prefix length and the network part be the same, @@ -352,28 +595,29 @@ prefix_copy (struct prefix *dest, const struct prefix *src) * the same. Note that this routine has the same return value sense * as '==' (which is different from prefix_cmp). */ -int -prefix_same (const struct prefix *p1, const struct prefix *p2) +int prefix_same(const struct prefix *p1, const struct prefix *p2) { - if ((p1 && !p2) || (!p1 && p2)) - return 0; - - if (!p1 && !p2) - return 1; - - if (p1->family == p2->family && p1->prefixlen == p2->prefixlen) - { - if (p1->family == AF_INET) - if (IPV4_ADDR_SAME (&p1->u.prefix4.s_addr, &p2->u.prefix4.s_addr)) - return 1; - if (p1->family == AF_INET6 ) - if (IPV6_ADDR_SAME (&p1->u.prefix6.s6_addr, &p2->u.prefix6.s6_addr)) - return 1; - if (p1->family == AF_ETHERNET ) - if (!memcmp (&p1->u.prefix_evpn, &p2->u.prefix_evpn, sizeof (struct evpn_addr))) - return 1; - } - return 0; + if ((p1 && !p2) || (!p1 && p2)) + return 0; + + if (!p1 && !p2) + return 1; + + if (p1->family == p2->family && p1->prefixlen == p2->prefixlen) { + if (p1->family == AF_INET) + if (IPV4_ADDR_SAME(&p1->u.prefix4.s_addr, + &p2->u.prefix4.s_addr)) + return 1; + if (p1->family == AF_INET6) + if (IPV6_ADDR_SAME(&p1->u.prefix6.s6_addr, + &p2->u.prefix6.s6_addr)) + return 1; + if (p1->family == AF_ETHERNET) + if (!memcmp(&p1->u.prefix_evpn, &p2->u.prefix_evpn, + sizeof(struct evpn_addr))) + return 1; + } + return 0; } /* @@ -386,31 +630,30 @@ prefix_same (const struct prefix *p1, const struct prefix *p2) * this routine has the same return sense as strcmp (which is different * from prefix_same). */ -int -prefix_cmp (const struct prefix *p1, const struct prefix *p2) +int prefix_cmp(const struct prefix *p1, const struct prefix *p2) { - int offset; - int shift; + int offset; + int shift; - /* Set both prefix's head pointer. */ - const u_char *pp1 = (const u_char *)&p1->u.prefix; - const u_char *pp2 = (const u_char *)&p2->u.prefix; + /* Set both prefix's head pointer. */ + const u_char *pp1 = (const u_char *)&p1->u.prefix; + const u_char *pp2 = (const u_char *)&p2->u.prefix; - if (p1->family != p2->family || p1->prefixlen != p2->prefixlen) - return 1; + if (p1->family != p2->family || p1->prefixlen != p2->prefixlen) + return 1; - offset = p1->prefixlen / PNBBY; - shift = p1->prefixlen % PNBBY; + offset = p1->prefixlen / PNBBY; + shift = p1->prefixlen % PNBBY; - if (shift) - if (maskbit[shift] & (pp1[offset] ^ pp2[offset])) - return 1; + if (shift) + if (maskbit[shift] & (pp1[offset] ^ pp2[offset])) + return 1; - while (offset--) - if (pp1[offset] != pp2[offset]) - return 1; + while (offset--) + if (pp1[offset] != pp2[offset]) + return 1; - return 0; + return 0; } /* @@ -419,727 +662,675 @@ prefix_cmp (const struct prefix *p1, const struct prefix *p2) * address families don't match, return -1; otherwise the return value is * in range 0 ... maximum prefix length for the address family. */ -int -prefix_common_bits (const struct prefix *p1, const struct prefix *p2) +int prefix_common_bits(const struct prefix *p1, const struct prefix *p2) { - int pos, bit; - int length = 0; - u_char xor; - - /* Set both prefix's head pointer. */ - const u_char *pp1 = (const u_char *)&p1->u.prefix; - const u_char *pp2 = (const u_char *)&p2->u.prefix; - - if (p1->family == AF_INET) - length = IPV4_MAX_BYTELEN; - if (p1->family == AF_INET6) - length = IPV6_MAX_BYTELEN; - if (p1->family == AF_ETHERNET) - length = 8 * sizeof (struct evpn_addr); - - if (p1->family != p2->family || !length) - return -1; - - for (pos = 0; pos < length; pos++) - if (pp1[pos] != pp2[pos]) - break; - if (pos == length) - return pos * 8; - - xor = pp1[pos] ^ pp2[pos]; - for (bit = 0; bit < 8; bit++) - if (xor & (1 << (7 - bit))) - break; - - return pos * 8 + bit; + int pos, bit; + int length = 0; + u_char xor ; + + /* Set both prefix's head pointer. */ + const u_char *pp1 = (const u_char *)&p1->u.prefix; + const u_char *pp2 = (const u_char *)&p2->u.prefix; + + if (p1->family == AF_INET) + length = IPV4_MAX_BYTELEN; + if (p1->family == AF_INET6) + length = IPV6_MAX_BYTELEN; + if (p1->family == AF_ETHERNET) + length = 8 * sizeof(struct evpn_addr); + + if (p1->family != p2->family || !length) + return -1; + + for (pos = 0; pos < length; pos++) + if (pp1[pos] != pp2[pos]) + break; + if (pos == length) + return pos * 8; + + xor = pp1[pos] ^ pp2[pos]; + for (bit = 0; bit < 8; bit++) + if (xor&(1 << (7 - bit))) + break; + + return pos * 8 + bit; } /* Return prefix family type string. */ -const char * -prefix_family_str (const struct prefix *p) +const char *prefix_family_str(const struct prefix *p) { - if (p->family == AF_INET) - return "inet"; - if (p->family == AF_INET6) - return "inet6"; - if (p->family == AF_ETHERNET) - return "ether"; - return "unspec"; + if (p->family == AF_INET) + return "inet"; + if (p->family == AF_INET6) + return "inet6"; + if (p->family == AF_ETHERNET) + return "ether"; + return "unspec"; } /* Allocate new prefix_ipv4 structure. */ -struct prefix_ipv4 * -prefix_ipv4_new () +struct prefix_ipv4 *prefix_ipv4_new() { - struct prefix_ipv4 *p; - - /* Call prefix_new to allocate a full-size struct prefix to avoid problems - where the struct prefix_ipv4 is cast to struct prefix and unallocated - bytes were being referenced (e.g. in structure assignments). */ - p = (struct prefix_ipv4 *)prefix_new(); - p->family = AF_INET; - return p; + struct prefix_ipv4 *p; + + /* Call prefix_new to allocate a full-size struct prefix to avoid + problems + where the struct prefix_ipv4 is cast to struct prefix and unallocated + bytes were being referenced (e.g. in structure assignments). */ + p = (struct prefix_ipv4 *)prefix_new(); + p->family = AF_INET; + return p; } /* Free prefix_ipv4 structure. */ -void -prefix_ipv4_free (struct prefix_ipv4 *p) +void prefix_ipv4_free(struct prefix_ipv4 *p) { - prefix_free((struct prefix *)p); + prefix_free((struct prefix *)p); } /* When string format is invalid return 0. */ -int -str2prefix_ipv4 (const char *str, struct prefix_ipv4 *p) +int str2prefix_ipv4(const char *str, struct prefix_ipv4 *p) { - int ret; - int plen; - char *pnt; - char *cp; - - /* Find slash inside string. */ - pnt = strchr (str, '/'); - - /* String doesn't contail slash. */ - if (pnt == NULL) - { - /* Convert string to prefix. */ - ret = inet_aton (str, &p->prefix); - if (ret == 0) - return 0; - - /* If address doesn't contain slash we assume it host address. */ - p->family = AF_INET; - p->prefixlen = IPV4_MAX_BITLEN; - - return ret; - } - else - { - cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1); - strncpy (cp, str, pnt - str); - *(cp + (pnt - str)) = '\0'; - ret = inet_aton (cp, &p->prefix); - XFREE (MTYPE_TMP, cp); - - /* Get prefix length. */ - plen = (u_char) atoi (++pnt); - if (plen > IPV4_MAX_PREFIXLEN) - return 0; - - p->family = AF_INET; - p->prefixlen = plen; - } + int ret; + int plen; + char *pnt; + char *cp; + + /* Find slash inside string. */ + pnt = strchr(str, '/'); + + /* String doesn't contail slash. */ + if (pnt == NULL) { + /* Convert string to prefix. */ + ret = inet_aton(str, &p->prefix); + if (ret == 0) + return 0; + + /* If address doesn't contain slash we assume it host address. + */ + p->family = AF_INET; + p->prefixlen = IPV4_MAX_BITLEN; + + return ret; + } else { + cp = XMALLOC(MTYPE_TMP, (pnt - str) + 1); + strncpy(cp, str, pnt - str); + *(cp + (pnt - str)) = '\0'; + ret = inet_aton(cp, &p->prefix); + XFREE(MTYPE_TMP, cp); + + /* Get prefix length. */ + plen = (u_char)atoi(++pnt); + if (plen > IPV4_MAX_PREFIXLEN) + return 0; + + p->family = AF_INET; + p->prefixlen = plen; + } - return ret; + return ret; } /* When string format is invalid return 0. */ -int -str2prefix_eth (const char *str, struct prefix_eth *p) +int str2prefix_eth(const char *str, struct prefix_eth *p) { - int ret = 0; - int plen = 48; - char *pnt; - char *cp = NULL; - const char *str_addr = str; - unsigned int a[6]; - int i; - - /* Find slash inside string. */ - pnt = strchr (str, '/'); - - if (pnt) - { - /* Get prefix length. */ - plen = (u_char) atoi (++pnt); - if (plen > 48) - { - ret = 0; - goto done; + int ret = 0; + int plen = 48; + char *pnt; + char *cp = NULL; + const char *str_addr = str; + unsigned int a[6]; + int i; + + /* Find slash inside string. */ + pnt = strchr(str, '/'); + + if (pnt) { + /* Get prefix length. */ + plen = (u_char)atoi(++pnt); + if (plen > 48) { + ret = 0; + goto done; + } + + cp = XMALLOC(MTYPE_TMP, (pnt - str) + 1); + strncpy(cp, str, pnt - str); + *(cp + (pnt - str)) = '\0'; + + str_addr = cp; } - cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1); - strncpy (cp, str, pnt - str); - *(cp + (pnt - str)) = '\0'; - - str_addr = cp; - } - - /* Convert string to prefix. */ - if (sscanf(str_addr, "%2x:%2x:%2x:%2x:%2x:%2x", - a+0, a+1, a+2, a+3, a+4, a+5) != 6) - { - ret = 0; - goto done; - } - for (i = 0; i < 6; ++i) - { - p->eth_addr.octet[i] = a[i] & 0xff; - } - p->prefixlen = plen; - p->family = AF_ETHERNET; - ret = 1; + /* Convert string to prefix. */ + if (sscanf(str_addr, "%2x:%2x:%2x:%2x:%2x:%2x", a + 0, a + 1, a + 2, + a + 3, a + 4, a + 5) + != 6) { + ret = 0; + goto done; + } + for (i = 0; i < 6; ++i) { + p->eth_addr.octet[i] = a[i] & 0xff; + } + p->prefixlen = plen; + p->family = AF_ETHERNET; + ret = 1; done: - if (cp) - XFREE (MTYPE_TMP, cp); + if (cp) + XFREE(MTYPE_TMP, cp); - return ret; + return ret; } /* Convert masklen into IP address's netmask (network byte order). */ -void -masklen2ip (const int masklen, struct in_addr *netmask) +void masklen2ip(const int masklen, struct in_addr *netmask) { - assert (masklen >= 0 && masklen <= IPV4_MAX_BITLEN); + assert(masklen >= 0 && masklen <= IPV4_MAX_BITLEN); - /* left shift is only defined for less than the size of the type. - * we unconditionally use long long in case the target platform - * has defined behaviour for << 32 (or has a 64-bit left shift) */ + /* left shift is only defined for less than the size of the type. + * we unconditionally use long long in case the target platform + * has defined behaviour for << 32 (or has a 64-bit left shift) */ - if (sizeof(unsigned long long) > 4) - netmask->s_addr = htonl(0xffffffffULL << (32 - masklen)); - else - netmask->s_addr = htonl(masklen ? 0xffffffffU << (32 - masklen) : 0); + if (sizeof(unsigned long long) > 4) + netmask->s_addr = htonl(0xffffffffULL << (32 - masklen)); + else + netmask->s_addr = + htonl(masklen ? 0xffffffffU << (32 - masklen) : 0); } /* Convert IP address's netmask into integer. We assume netmask is sequential one. Argument netmask should be network byte order. */ -u_char -ip_masklen (struct in_addr netmask) +u_char ip_masklen(struct in_addr netmask) { - uint32_t tmp = ~ntohl(netmask.s_addr); - if (tmp) - /* clz: count leading zeroes. sadly, the behaviour of this builtin - * is undefined for a 0 argument, even though most CPUs give 32 */ - return __builtin_clz(tmp); - else - return 32; + uint32_t tmp = ~ntohl(netmask.s_addr); + if (tmp) + /* clz: count leading zeroes. sadly, the behaviour of this + * builtin + * is undefined for a 0 argument, even though most CPUs give 32 + */ + return __builtin_clz(tmp); + else + return 32; } /* Apply mask to IPv4 prefix (network byte order). */ -void -apply_mask_ipv4 (struct prefix_ipv4 *p) +void apply_mask_ipv4(struct prefix_ipv4 *p) { - struct in_addr mask; - masklen2ip(p->prefixlen, &mask); - p->prefix.s_addr &= mask.s_addr; + struct in_addr mask; + masklen2ip(p->prefixlen, &mask); + p->prefix.s_addr &= mask.s_addr; } /* If prefix is 0.0.0.0/0 then return 1 else return 0. */ -int -prefix_ipv4_any (const struct prefix_ipv4 *p) +int prefix_ipv4_any(const struct prefix_ipv4 *p) { - return (p->prefix.s_addr == 0 && p->prefixlen == 0); + return (p->prefix.s_addr == 0 && p->prefixlen == 0); } /* Allocate a new ip version 6 route */ -struct prefix_ipv6 * -prefix_ipv6_new (void) +struct prefix_ipv6 *prefix_ipv6_new(void) { - struct prefix_ipv6 *p; + struct prefix_ipv6 *p; - /* Allocate a full-size struct prefix to avoid problems with structure - size mismatches. */ - p = (struct prefix_ipv6 *)prefix_new(); - p->family = AF_INET6; - return p; + /* Allocate a full-size struct prefix to avoid problems with structure + size mismatches. */ + p = (struct prefix_ipv6 *)prefix_new(); + p->family = AF_INET6; + return p; } /* Free prefix for IPv6. */ -void -prefix_ipv6_free (struct prefix_ipv6 *p) +void prefix_ipv6_free(struct prefix_ipv6 *p) { - prefix_free((struct prefix *)p); + prefix_free((struct prefix *)p); } /* If given string is valid return pin6 else return NULL */ -int -str2prefix_ipv6 (const char *str, struct prefix_ipv6 *p) +int str2prefix_ipv6(const char *str, struct prefix_ipv6 *p) { - char *pnt; - char *cp; - int ret; - - pnt = strchr (str, '/'); - - /* If string doesn't contain `/' treat it as host route. */ - if (pnt == NULL) - { - ret = inet_pton (AF_INET6, str, &p->prefix); - if (ret == 0) - return 0; - p->prefixlen = IPV6_MAX_BITLEN; - } - else - { - int plen; - - cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1); - strncpy (cp, str, pnt - str); - *(cp + (pnt - str)) = '\0'; - ret = inet_pton (AF_INET6, cp, &p->prefix); - XFREE (MTYPE_TMP, cp); - if (ret == 0) - return 0; - plen = (u_char) atoi (++pnt); - if (plen > IPV6_MAX_BITLEN) - return 0; - p->prefixlen = plen; - } - p->family = AF_INET6; + char *pnt; + char *cp; + int ret; + + pnt = strchr(str, '/'); + + /* If string doesn't contain `/' treat it as host route. */ + if (pnt == NULL) { + ret = inet_pton(AF_INET6, str, &p->prefix); + if (ret == 0) + return 0; + p->prefixlen = IPV6_MAX_BITLEN; + } else { + int plen; + + cp = XMALLOC(MTYPE_TMP, (pnt - str) + 1); + strncpy(cp, str, pnt - str); + *(cp + (pnt - str)) = '\0'; + ret = inet_pton(AF_INET6, cp, &p->prefix); + XFREE(MTYPE_TMP, cp); + if (ret == 0) + return 0; + plen = (u_char)atoi(++pnt); + if (plen > IPV6_MAX_BITLEN) + return 0; + p->prefixlen = plen; + } + p->family = AF_INET6; - return ret; + return ret; } /* Convert struct in6_addr netmask into integer. * FIXME return u_char as ip_maskleni() does. */ -int -ip6_masklen (struct in6_addr netmask) +int ip6_masklen(struct in6_addr netmask) { - int len = 0; - unsigned char val; - unsigned char *pnt; - - pnt = (unsigned char *) & netmask; - - while ((*pnt == 0xff) && len < IPV6_MAX_BITLEN) - { - len += 8; - pnt++; - } - - if (len < IPV6_MAX_BITLEN) - { - val = *pnt; - while (val) - { - len++; - val <<= 1; + int len = 0; + unsigned char val; + unsigned char *pnt; + + pnt = (unsigned char *)&netmask; + + while ((*pnt == 0xff) && len < IPV6_MAX_BITLEN) { + len += 8; + pnt++; } - } - return len; + + if (len < IPV6_MAX_BITLEN) { + val = *pnt; + while (val) { + len++; + val <<= 1; + } + } + return len; } -void -masklen2ip6 (const int masklen, struct in6_addr *netmask) +void masklen2ip6(const int masklen, struct in6_addr *netmask) { - assert (masklen >= 0 && masklen <= IPV6_MAX_BITLEN); - memcpy (netmask, maskbytes6 + masklen, sizeof (struct in6_addr)); + assert(masklen >= 0 && masklen <= IPV6_MAX_BITLEN); + memcpy(netmask, maskbytes6 + masklen, sizeof(struct in6_addr)); } -void -apply_mask_ipv6 (struct prefix_ipv6 *p) +void apply_mask_ipv6(struct prefix_ipv6 *p) { - u_char *pnt; - int index; - int offset; + u_char *pnt; + int index; + int offset; - index = p->prefixlen / 8; + index = p->prefixlen / 8; - if (index < 16) - { - pnt = (u_char *) &p->prefix; - offset = p->prefixlen % 8; + if (index < 16) { + pnt = (u_char *)&p->prefix; + offset = p->prefixlen % 8; - pnt[index] &= maskbit[offset]; - index++; + pnt[index] &= maskbit[offset]; + index++; - while (index < 16) - pnt[index++] = 0; - } + while (index < 16) + pnt[index++] = 0; + } } -void -apply_mask (struct prefix *p) +void apply_mask(struct prefix *p) { - switch (p->family) - { - case AF_INET: - apply_mask_ipv4 ((struct prefix_ipv4 *)p); - break; - case AF_INET6: - apply_mask_ipv6 ((struct prefix_ipv6 *)p); - break; - default: - break; - } - return; + switch (p->family) { + case AF_INET: + apply_mask_ipv4((struct prefix_ipv4 *)p); + break; + case AF_INET6: + apply_mask_ipv6((struct prefix_ipv6 *)p); + break; + default: + break; + } + return; } /* Utility function of convert between struct prefix <=> union sockunion. * FIXME This function isn't used anywhere. */ -struct prefix * -sockunion2prefix (const union sockunion *dest, - const union sockunion *mask) +struct prefix *sockunion2prefix(const union sockunion *dest, + const union sockunion *mask) { - if (dest->sa.sa_family == AF_INET) - { - struct prefix_ipv4 *p; - - p = prefix_ipv4_new (); - p->family = AF_INET; - p->prefix = dest->sin.sin_addr; - p->prefixlen = ip_masklen (mask->sin.sin_addr); - return (struct prefix *) p; - } - if (dest->sa.sa_family == AF_INET6) - { - struct prefix_ipv6 *p; - - p = prefix_ipv6_new (); - p->family = AF_INET6; - p->prefixlen = ip6_masklen (mask->sin6.sin6_addr); - memcpy (&p->prefix, &dest->sin6.sin6_addr, sizeof (struct in6_addr)); - return (struct prefix *) p; - } - return NULL; + if (dest->sa.sa_family == AF_INET) { + struct prefix_ipv4 *p; + + p = prefix_ipv4_new(); + p->family = AF_INET; + p->prefix = dest->sin.sin_addr; + p->prefixlen = ip_masklen(mask->sin.sin_addr); + return (struct prefix *)p; + } + if (dest->sa.sa_family == AF_INET6) { + struct prefix_ipv6 *p; + + p = prefix_ipv6_new(); + p->family = AF_INET6; + p->prefixlen = ip6_masklen(mask->sin6.sin6_addr); + memcpy(&p->prefix, &dest->sin6.sin6_addr, + sizeof(struct in6_addr)); + return (struct prefix *)p; + } + return NULL; } /* Utility function of convert between struct prefix <=> union sockunion. */ -struct prefix * -sockunion2hostprefix (const union sockunion *su, struct prefix *prefix) +struct prefix *sockunion2hostprefix(const union sockunion *su, + struct prefix *prefix) { - if (su->sa.sa_family == AF_INET) - { - struct prefix_ipv4 *p; - - p = prefix ? (struct prefix_ipv4 *) prefix : prefix_ipv4_new (); - p->family = AF_INET; - p->prefix = su->sin.sin_addr; - p->prefixlen = IPV4_MAX_BITLEN; - return (struct prefix *) p; - } - if (su->sa.sa_family == AF_INET6) - { - struct prefix_ipv6 *p; - - p = prefix ? (struct prefix_ipv6 *) prefix : prefix_ipv6_new (); - p->family = AF_INET6; - p->prefixlen = IPV6_MAX_BITLEN; - memcpy (&p->prefix, &su->sin6.sin6_addr, sizeof (struct in6_addr)); - return (struct prefix *) p; - } - return NULL; + if (su->sa.sa_family == AF_INET) { + struct prefix_ipv4 *p; + + p = prefix ? (struct prefix_ipv4 *)prefix : prefix_ipv4_new(); + p->family = AF_INET; + p->prefix = su->sin.sin_addr; + p->prefixlen = IPV4_MAX_BITLEN; + return (struct prefix *)p; + } + if (su->sa.sa_family == AF_INET6) { + struct prefix_ipv6 *p; + + p = prefix ? (struct prefix_ipv6 *)prefix : prefix_ipv6_new(); + p->family = AF_INET6; + p->prefixlen = IPV6_MAX_BITLEN; + memcpy(&p->prefix, &su->sin6.sin6_addr, + sizeof(struct in6_addr)); + return (struct prefix *)p; + } + return NULL; } -void -prefix2sockunion (const struct prefix *p, union sockunion *su) +void prefix2sockunion(const struct prefix *p, union sockunion *su) { - memset (su, 0, sizeof (*su)); - - su->sa.sa_family = p->family; - if (p->family == AF_INET) - su->sin.sin_addr = p->u.prefix4; - if (p->family == AF_INET6) - memcpy (&su->sin6.sin6_addr, &p->u.prefix6, sizeof (struct in6_addr)); + memset(su, 0, sizeof(*su)); + + su->sa.sa_family = p->family; + if (p->family == AF_INET) + su->sin.sin_addr = p->u.prefix4; + if (p->family == AF_INET6) + memcpy(&su->sin6.sin6_addr, &p->u.prefix6, + sizeof(struct in6_addr)); } -int -prefix_blen (const struct prefix *p) +int prefix_blen(const struct prefix *p) { - switch (p->family) - { - case AF_INET: - return IPV4_MAX_BYTELEN; - break; - case AF_INET6: - return IPV6_MAX_BYTELEN; - break; - case AF_ETHERNET: - return ETHER_ADDR_LEN; - } - return 0; + switch (p->family) { + case AF_INET: + return IPV4_MAX_BYTELEN; + break; + case AF_INET6: + return IPV6_MAX_BYTELEN; + break; + case AF_ETHERNET: + return ETHER_ADDR_LEN; + } + return 0; } /* Generic function for conversion string to struct prefix. */ -int -str2prefix (const char *str, struct prefix *p) +int str2prefix(const char *str, struct prefix *p) { - int ret; + int ret; - /* First we try to convert string to struct prefix_ipv4. */ - ret = str2prefix_ipv4 (str, (struct prefix_ipv4 *) p); - if (ret) - return ret; + /* First we try to convert string to struct prefix_ipv4. */ + ret = str2prefix_ipv4(str, (struct prefix_ipv4 *)p); + if (ret) + return ret; - /* Next we try to convert string to struct prefix_ipv6. */ - ret = str2prefix_ipv6 (str, (struct prefix_ipv6 *) p); - if (ret) - return ret; + /* Next we try to convert string to struct prefix_ipv6. */ + ret = str2prefix_ipv6(str, (struct prefix_ipv6 *)p); + if (ret) + return ret; - /* Next we try to convert string to struct prefix_eth. */ - ret = str2prefix_eth (str, (struct prefix_eth *) p); - if (ret) - return ret; + /* Next we try to convert string to struct prefix_eth. */ + ret = str2prefix_eth(str, (struct prefix_eth *)p); + if (ret) + return ret; - return 0; + return 0; } -static const char * -prefixeth2str (const struct prefix *p, char *str, int size) +static const char *prefixeth2str(const struct prefix *p, char *str, int size) { - u_char family; - char buf[PREFIX2STR_BUFFER]; - char buf2[ETHER_ADDR_STRLEN]; - - if (p->u.prefix_evpn.route_type == 2) - { - if (IS_EVPN_PREFIX_IPADDR_NONE((struct prefix_evpn *)p)) - snprintf (str, size, "[%d]:[%s]/%d", - p->u.prefix_evpn.route_type, - prefix_mac2str (&p->u.prefix_evpn.mac, buf2, sizeof (buf2)), - p->prefixlen); - else - { - family = IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p) ? \ - AF_INET : AF_INET6; - snprintf (str, size, "[%d]:[%s]:[%s]/%d", - p->u.prefix_evpn.route_type, - prefix_mac2str (&p->u.prefix_evpn.mac, buf2, sizeof (buf2)), - inet_ntop (family, &p->u.prefix_evpn.ip.ip.addr, - buf, PREFIX2STR_BUFFER), - p->prefixlen); - } - } - else if (p->u.prefix_evpn.route_type == 3) - { - family = IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p) ? \ - AF_INET : AF_INET6; - snprintf (str, size, "[%d]:[%s]/%d", - p->u.prefix_evpn.route_type, - inet_ntop (family, &p->u.prefix_evpn.ip.ip.addr, - buf, PREFIX2STR_BUFFER), - p->prefixlen); - } - else if (p->u.prefix_evpn.route_type == 5) - { - family = IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p) ? \ - AF_INET : AF_INET6; - snprintf (str, size, "[%d]:[%u][%s]/%d", - p->u.prefix_evpn.route_type, - p->u.prefix_evpn.eth_tag, - inet_ntop (family, &p->u.prefix_evpn.ip.ip.addr, - buf, PREFIX2STR_BUFFER), - p->prefixlen); - } - else - { - sprintf (str, "UNK AF_ETHER prefix"); - snprintf(str, size, "%02x:%02x:%02x:%02x:%02x:%02x/%d", - p->u.prefix_eth.octet[0], p->u.prefix_eth.octet[1], - p->u.prefix_eth.octet[2], p->u.prefix_eth.octet[3], - p->u.prefix_eth.octet[4], p->u.prefix_eth.octet[5], - p->prefixlen); - } - - return str; + u_char family; + char buf[PREFIX2STR_BUFFER]; + char buf2[ETHER_ADDR_STRLEN]; + + if (p->u.prefix_evpn.route_type == 2) { + if (IS_EVPN_PREFIX_IPADDR_NONE((struct prefix_evpn *)p)) + snprintf(str, size, "[%d]:[%s]/%d", + p->u.prefix_evpn.route_type, + prefix_mac2str(&p->u.prefix_evpn.mac, buf2, + sizeof(buf2)), + p->prefixlen); + else { + family = IS_EVPN_PREFIX_IPADDR_V4( + (struct prefix_evpn *)p) + ? AF_INET + : AF_INET6; + snprintf(str, size, "[%d]:[%s]:[%s]/%d", + p->u.prefix_evpn.route_type, + prefix_mac2str(&p->u.prefix_evpn.mac, buf2, + sizeof(buf2)), + inet_ntop(family, &p->u.prefix_evpn.ip.ip.addr, + buf, PREFIX2STR_BUFFER), + p->prefixlen); + } + } else if (p->u.prefix_evpn.route_type == 3) { + family = IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p) + ? AF_INET + : AF_INET6; + snprintf(str, size, "[%d]:[%s]/%d", p->u.prefix_evpn.route_type, + inet_ntop(family, &p->u.prefix_evpn.ip.ip.addr, buf, + PREFIX2STR_BUFFER), + p->prefixlen); + } else if (p->u.prefix_evpn.route_type == 5) { + family = IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p) + ? AF_INET + : AF_INET6; + snprintf(str, size, "[%d]:[%u][%s]/%d", + p->u.prefix_evpn.route_type, p->u.prefix_evpn.eth_tag, + inet_ntop(family, &p->u.prefix_evpn.ip.ip.addr, buf, + PREFIX2STR_BUFFER), + p->prefixlen); + } else { + sprintf(str, "UNK AF_ETHER prefix"); + snprintf(str, size, "%02x:%02x:%02x:%02x:%02x:%02x/%d", + p->u.prefix_eth.octet[0], p->u.prefix_eth.octet[1], + p->u.prefix_eth.octet[2], p->u.prefix_eth.octet[3], + p->u.prefix_eth.octet[4], p->u.prefix_eth.octet[5], + p->prefixlen); + } + + return str; } -const char * -prefix2str (union prefixconstptr pu, char *str, int size) +const char *prefix2str(union prefixconstptr pu, char *str, int size) { - const struct prefix *p = pu.p; - char buf[PREFIX2STR_BUFFER]; - - switch (p->family) - { - case AF_INET: - case AF_INET6: - snprintf (str, size, "%s/%d", - inet_ntop (p->family, &p->u.prefix, buf, PREFIX2STR_BUFFER), - p->prefixlen); - break; - - case AF_ETHERNET: - prefixeth2str (p, str, size); - break; - - default: - sprintf (str, "UNK prefix"); - break; - } - - return str; + const struct prefix *p = pu.p; + char buf[PREFIX2STR_BUFFER]; + + switch (p->family) { + case AF_INET: + case AF_INET6: + snprintf(str, size, "%s/%d", inet_ntop(p->family, &p->u.prefix, + buf, PREFIX2STR_BUFFER), + p->prefixlen); + break; + + case AF_ETHERNET: + prefixeth2str(p, str, size); + break; + + default: + sprintf(str, "UNK prefix"); + break; + } + + return str; } -struct prefix * -prefix_new () +struct prefix *prefix_new() { - struct prefix *p; + struct prefix *p; - p = XCALLOC (MTYPE_PREFIX, sizeof *p); - return p; + p = XCALLOC(MTYPE_PREFIX, sizeof *p); + return p; } /* Free prefix structure. */ -void -prefix_free (struct prefix *p) +void prefix_free(struct prefix *p) { - XFREE (MTYPE_PREFIX, p); + XFREE(MTYPE_PREFIX, p); } /* Utility function. Check the string only contains digit * character. * FIXME str.[c|h] would be better place for this function. */ -int -all_digit (const char *str) +int all_digit(const char *str) { - for (; *str != '\0'; str++) - if (!isdigit ((int) *str)) - return 0; - return 1; + for (; *str != '\0'; str++) + if (!isdigit((int)*str)) + return 0; + return 1; } /* Utility function to convert ipv4 prefixes to Classful prefixes */ -void apply_classful_mask_ipv4 (struct prefix_ipv4 *p) +void apply_classful_mask_ipv4(struct prefix_ipv4 *p) { - u_int32_t destination; - - destination = ntohl (p->prefix.s_addr); - - if (p->prefixlen == IPV4_MAX_PREFIXLEN); - /* do nothing for host routes */ - else if (IN_CLASSC (destination)) - { - p->prefixlen=24; - apply_mask_ipv4(p); - } - else if (IN_CLASSB(destination)) - { - p->prefixlen=16; - apply_mask_ipv4(p); - } - else - { - p->prefixlen=8; - apply_mask_ipv4(p); - } + u_int32_t destination; + + destination = ntohl(p->prefix.s_addr); + + if (p->prefixlen == IPV4_MAX_PREFIXLEN) + ; + /* do nothing for host routes */ + else if (IN_CLASSC(destination)) { + p->prefixlen = 24; + apply_mask_ipv4(p); + } else if (IN_CLASSB(destination)) { + p->prefixlen = 16; + apply_mask_ipv4(p); + } else { + p->prefixlen = 8; + apply_mask_ipv4(p); + } } -in_addr_t -ipv4_network_addr (in_addr_t hostaddr, int masklen) +in_addr_t ipv4_network_addr(in_addr_t hostaddr, int masklen) { - struct in_addr mask; + struct in_addr mask; - masklen2ip (masklen, &mask); - return hostaddr & mask.s_addr; + masklen2ip(masklen, &mask); + return hostaddr & mask.s_addr; } -in_addr_t -ipv4_broadcast_addr (in_addr_t hostaddr, int masklen) +in_addr_t ipv4_broadcast_addr(in_addr_t hostaddr, int masklen) { - struct in_addr mask; - - masklen2ip (masklen, &mask); - return (masklen != IPV4_MAX_PREFIXLEN-1) ? - /* normal case */ - (hostaddr | ~mask.s_addr) : - /* special case for /31 */ - (hostaddr ^ ~mask.s_addr); + struct in_addr mask; + + masklen2ip(masklen, &mask); + return (masklen != IPV4_MAX_PREFIXLEN - 1) ? + /* normal case */ + (hostaddr | ~mask.s_addr) + : + /* special case for /31 */ + (hostaddr ^ ~mask.s_addr); } -/* Utility function to convert ipv4 netmask to prefixes +/* Utility function to convert ipv4 netmask to prefixes ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16" ex.) "1.0.0.0" NULL => "1.0.0.0/8" */ -int -netmask_str2prefix_str (const char *net_str, const char *mask_str, - char *prefix_str) +int netmask_str2prefix_str(const char *net_str, const char *mask_str, + char *prefix_str) { - struct in_addr network; - struct in_addr mask; - u_char prefixlen; - u_int32_t destination; - int ret; - - ret = inet_aton (net_str, &network); - if (! ret) - return 0; - - if (mask_str) - { - ret = inet_aton (mask_str, &mask); - if (! ret) - return 0; - - prefixlen = ip_masklen (mask); - } - else - { - destination = ntohl (network.s_addr); - - if (network.s_addr == 0) - prefixlen = 0; - else if (IN_CLASSC (destination)) - prefixlen = 24; - else if (IN_CLASSB (destination)) - prefixlen = 16; - else if (IN_CLASSA (destination)) - prefixlen = 8; - else - return 0; - } + struct in_addr network; + struct in_addr mask; + u_char prefixlen; + u_int32_t destination; + int ret; + + ret = inet_aton(net_str, &network); + if (!ret) + return 0; + + if (mask_str) { + ret = inet_aton(mask_str, &mask); + if (!ret) + return 0; + + prefixlen = ip_masklen(mask); + } else { + destination = ntohl(network.s_addr); + + if (network.s_addr == 0) + prefixlen = 0; + else if (IN_CLASSC(destination)) + prefixlen = 24; + else if (IN_CLASSB(destination)) + prefixlen = 16; + else if (IN_CLASSA(destination)) + prefixlen = 8; + else + return 0; + } - sprintf (prefix_str, "%s/%d", net_str, prefixlen); + sprintf(prefix_str, "%s/%d", net_str, prefixlen); - return 1; + return 1; } /* Utility function for making IPv6 address string. */ -const char * -inet6_ntoa (struct in6_addr addr) +const char *inet6_ntoa(struct in6_addr addr) { - static char buf[INET6_ADDRSTRLEN]; + static char buf[INET6_ADDRSTRLEN]; - inet_ntop (AF_INET6, &addr, buf, INET6_ADDRSTRLEN); - return buf; + inet_ntop(AF_INET6, &addr, buf, INET6_ADDRSTRLEN); + return buf; } /* converts to internal representation of mac address - * returns 1 on success, 0 otherwise + * returns 1 on success, 0 otherwise * format accepted: AA:BB:CC:DD:EE:FF * if mac parameter is null, then check only */ int prefix_str2mac(const char *str, struct ethaddr *mac) { - unsigned int a[6]; - int i; - - if (!str) - return 0; - - if (sscanf (str, "%2x:%2x:%2x:%2x:%2x:%2x", - a + 0, a + 1, a + 2, a + 3, a + 4, a + 5) != 6) - { - /* error in incoming str length */ - return 0; - } - /* valid mac address */ - if (!mac) - return 1; - for (i = 0; i < 6; ++i) - mac->octet[i] = a[i] & 0xff; - return 1; + unsigned int a[6]; + int i; + + if (!str) + return 0; + + if (sscanf(str, "%2x:%2x:%2x:%2x:%2x:%2x", a + 0, a + 1, a + 2, a + 3, + a + 4, a + 5) + != 6) { + /* error in incoming str length */ + return 0; + } + /* valid mac address */ + if (!mac) + return 1; + for (i = 0; i < 6; ++i) + mac->octet[i] = a[i] & 0xff; + return 1; } char *prefix_mac2str(const struct ethaddr *mac, char *buf, int size) { - char *ptr; - - if (!mac) - return NULL; - if (!buf) - ptr = (char *)XMALLOC(MTYPE_TMP, ETHER_ADDR_STRLEN* sizeof(char)); - else - { - assert (size >= ETHER_ADDR_STRLEN); - ptr = buf; - } - snprintf(ptr, (ETHER_ADDR_STRLEN), - "%02x:%02x:%02x:%02x:%02x:%02x", (uint8_t) mac->octet[0], - (uint8_t) mac->octet[1], (uint8_t) mac->octet[2], (uint8_t) mac->octet[3], - (uint8_t) mac->octet[4], (uint8_t) mac->octet[5]); - return ptr; + char *ptr; + + if (!mac) + return NULL; + if (!buf) + ptr = (char *)XMALLOC(MTYPE_TMP, + ETHER_ADDR_STRLEN * sizeof(char)); + else { + assert(size >= ETHER_ADDR_STRLEN); + ptr = buf; + } + snprintf(ptr, (ETHER_ADDR_STRLEN), "%02x:%02x:%02x:%02x:%02x:%02x", + (uint8_t)mac->octet[0], (uint8_t)mac->octet[1], + (uint8_t)mac->octet[2], (uint8_t)mac->octet[3], + (uint8_t)mac->octet[4], (uint8_t)mac->octet[5]); + return ptr; } diff --git a/lib/prefix.h b/lib/prefix.h index 549798e92..ce13dcfa0 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -23,13 +23,13 @@ #define _ZEBRA_PREFIX_H #ifdef SUNOS_5 -# include +#include #else -# ifdef GNU_LINUX -# include -# else -# include -# endif +#ifdef GNU_LINUX +#include +#else +#include +#endif #endif #include "sockunion.h" #include "ipaddr.h" @@ -48,11 +48,11 @@ * own to simplify internal handling */ struct ethaddr { - u_char octet[ETHER_ADDR_LEN]; -} __attribute__ ((packed)); + u_char octet[ETHER_ADDR_LEN]; +} __attribute__((packed)); -/* length is the number of valuable bits of prefix structure +/* length is the number of valuable bits of prefix structure * 18 bytes is current length in structure, if address is ipv4 * 30 bytes is in case of ipv6 */ @@ -60,13 +60,12 @@ struct ethaddr { #define PREFIX_LEN_ROUTE_TYPE_5_IPV6 (30*8) /* EVPN address (RFC 7432) */ -struct evpn_addr -{ - u_char route_type; - u_char ip_prefix_length; - struct ethaddr mac; - uint32_t eth_tag; - struct ipaddr ip; +struct evpn_addr { + u_char route_type; + u_char ip_prefix_length; + struct ethaddr mac; + uint32_t eth_tag; + struct ipaddr ip; #if 0 union { @@ -100,89 +99,78 @@ struct evpn_addr #endif /* IPv4 and IPv6 unified prefix structure. */ -struct prefix -{ - u_char family; - u_char prefixlen; - union - { - u_char prefix; - struct in_addr prefix4; - struct in6_addr prefix6; - struct - { - struct in_addr id; - struct in_addr adv_router; - } lp; - struct ethaddr prefix_eth; /* AF_ETHERNET */ - u_char val[8]; - uintptr_t ptr; - struct evpn_addr prefix_evpn; - } u __attribute__ ((aligned (8))); +struct prefix { + u_char family; + u_char prefixlen; + union { + u_char prefix; + struct in_addr prefix4; + struct in6_addr prefix6; + struct { + struct in_addr id; + struct in_addr adv_router; + } lp; + struct ethaddr prefix_eth; /* AF_ETHERNET */ + u_char val[8]; + uintptr_t ptr; + struct evpn_addr prefix_evpn; + } u __attribute__((aligned(8))); }; /* IPv4 prefix structure. */ -struct prefix_ipv4 -{ - u_char family; - u_char prefixlen; - struct in_addr prefix __attribute__ ((aligned (8))); +struct prefix_ipv4 { + u_char family; + u_char prefixlen; + struct in_addr prefix __attribute__((aligned(8))); }; /* IPv6 prefix structure. */ -struct prefix_ipv6 -{ - u_char family; - u_char prefixlen; - struct in6_addr prefix __attribute__ ((aligned (8))); +struct prefix_ipv6 { + u_char family; + u_char prefixlen; + struct in6_addr prefix __attribute__((aligned(8))); }; -struct prefix_ls -{ - u_char family; - u_char prefixlen; - struct in_addr id __attribute__ ((aligned (8))); - struct in_addr adv_router; +struct prefix_ls { + u_char family; + u_char prefixlen; + struct in_addr id __attribute__((aligned(8))); + struct in_addr adv_router; }; /* Prefix for routing distinguisher. */ -struct prefix_rd -{ - u_char family; - u_char prefixlen; - u_char val[8] __attribute__ ((aligned (8))); +struct prefix_rd { + u_char family; + u_char prefixlen; + u_char val[8] __attribute__((aligned(8))); }; /* Prefix for ethernet. */ -struct prefix_eth -{ - u_char family; - u_char prefixlen; - struct ethaddr eth_addr __attribute__ ((aligned (8))); /* AF_ETHERNET */ +struct prefix_eth { + u_char family; + u_char prefixlen; + struct ethaddr eth_addr __attribute__((aligned(8))); /* AF_ETHERNET */ }; /* EVPN prefix structure. */ -struct prefix_evpn -{ - u_char family; - u_char prefixlen; - struct evpn_addr prefix __attribute__ ((aligned (8))); +struct prefix_evpn { + u_char family; + u_char prefixlen; + struct evpn_addr prefix __attribute__((aligned(8))); }; /* Prefix for a generic pointer */ -struct prefix_ptr -{ - u_char family; - u_char prefixlen; - uintptr_t prefix __attribute__ ((aligned (8))); +struct prefix_ptr { + u_char family; + u_char prefixlen; + uintptr_t prefix __attribute__((aligned(8))); }; -struct prefix_sg -{ - u_char family; - u_char prefixlen; - struct in_addr src __attribute__ ((aligned (8))); - struct in_addr grp; +struct prefix_sg { + u_char family; + u_char prefixlen; + struct in_addr src __attribute__((aligned(8))); + struct in_addr grp; }; /* helper to get type safety/avoid casts on calls @@ -190,21 +178,19 @@ struct prefix_sg * side, which strips type safety since the cast will accept any pointer * type.) */ -union prefixptr -{ - struct prefix *p; - struct prefix_ipv4 *p4; - struct prefix_ipv6 *p6; - struct prefix_evpn *evp; -} __attribute__ ((transparent_union)); - -union prefixconstptr -{ - const struct prefix *p; - const struct prefix_ipv4 *p4; - const struct prefix_ipv6 *p6; - const struct prefix_evpn *evp; -} __attribute__ ((transparent_union)); +union prefixptr { + struct prefix *p; + struct prefix_ipv4 *p4; + struct prefix_ipv6 *p6; + struct prefix_evpn *evp; +} __attribute__((transparent_union)); + +union prefixconstptr { + const struct prefix *p; + const struct prefix_ipv4 *p4; + const struct prefix_ipv6 *p6; + const struct prefix_evpn *evp; +} __attribute__((transparent_union)); #ifndef INET_ADDRSTRLEN #define INET_ADDRSTRLEN 16 @@ -262,115 +248,118 @@ union prefixconstptr /* Prototypes. */ extern int str2family(const char *); -extern int afi2family (afi_t); -extern afi_t family2afi (int); +extern int afi2family(afi_t); +extern afi_t family2afi(int); extern const char *safi2str(safi_t safi); extern const char *afi2str(afi_t afi); /* Check bit of the prefix. */ -extern unsigned int prefix_bit (const u_char *prefix, const u_char prefixlen); -extern unsigned int prefix6_bit (const struct in6_addr *prefix, const u_char prefixlen); +extern unsigned int prefix_bit(const u_char *prefix, const u_char prefixlen); +extern unsigned int prefix6_bit(const struct in6_addr *prefix, + const u_char prefixlen); -extern struct prefix *prefix_new (void); -extern void prefix_free (struct prefix *); -extern const char *prefix_family_str (const struct prefix *); -extern int prefix_blen (const struct prefix *); -extern int str2prefix (const char *, struct prefix *); +extern struct prefix *prefix_new(void); +extern void prefix_free(struct prefix *); +extern const char *prefix_family_str(const struct prefix *); +extern int prefix_blen(const struct prefix *); +extern int str2prefix(const char *, struct prefix *); #define PREFIX2STR_BUFFER PREFIX_STRLEN -extern const char *prefix2str (union prefixconstptr, char *, int); -extern int prefix_match (const struct prefix *, const struct prefix *); -extern int prefix_match_network_statement (const struct prefix *, const struct prefix *); -extern int prefix_same (const struct prefix *, const struct prefix *); -extern int prefix_cmp (const struct prefix *, const struct prefix *); -extern int prefix_common_bits (const struct prefix *, const struct prefix *); -extern void prefix_copy (struct prefix *dest, const struct prefix *src); -extern void apply_mask (struct prefix *); - -extern struct prefix *sockunion2prefix (const union sockunion *dest, - const union sockunion *mask); -extern struct prefix *sockunion2hostprefix (const union sockunion *, struct prefix *p); -extern void prefix2sockunion (const struct prefix *, union sockunion *); - -extern int str2prefix_eth (const char *, struct prefix_eth *); - -extern struct prefix_ipv4 *prefix_ipv4_new (void); -extern void prefix_ipv4_free (struct prefix_ipv4 *); -extern int str2prefix_ipv4 (const char *, struct prefix_ipv4 *); -extern void apply_mask_ipv4 (struct prefix_ipv4 *); - -#define PREFIX_COPY_IPV4(DST, SRC) \ +extern const char *prefix2str(union prefixconstptr, char *, int); +extern int prefix_match(const struct prefix *, const struct prefix *); +extern int prefix_match_network_statement(const struct prefix *, + const struct prefix *); +extern int prefix_same(const struct prefix *, const struct prefix *); +extern int prefix_cmp(const struct prefix *, const struct prefix *); +extern int prefix_common_bits(const struct prefix *, const struct prefix *); +extern void prefix_copy(struct prefix *dest, const struct prefix *src); +extern void apply_mask(struct prefix *); + +extern struct prefix *sockunion2prefix(const union sockunion *dest, + const union sockunion *mask); +extern struct prefix *sockunion2hostprefix(const union sockunion *, + struct prefix *p); +extern void prefix2sockunion(const struct prefix *, union sockunion *); + +extern int str2prefix_eth(const char *, struct prefix_eth *); + +extern struct prefix_ipv4 *prefix_ipv4_new(void); +extern void prefix_ipv4_free(struct prefix_ipv4 *); +extern int str2prefix_ipv4(const char *, struct prefix_ipv4 *); +extern void apply_mask_ipv4(struct prefix_ipv4 *); + +#define PREFIX_COPY_IPV4(DST, SRC) \ *((struct prefix_ipv4 *)(DST)) = *((const struct prefix_ipv4 *)(SRC)); -extern int prefix_ipv4_any (const struct prefix_ipv4 *); -extern void apply_classful_mask_ipv4 (struct prefix_ipv4 *); +extern int prefix_ipv4_any(const struct prefix_ipv4 *); +extern void apply_classful_mask_ipv4(struct prefix_ipv4 *); -extern u_char ip_masklen (struct in_addr); -extern void masklen2ip (const int, struct in_addr *); +extern u_char ip_masklen(struct in_addr); +extern void masklen2ip(const int, struct in_addr *); /* returns the network portion of the host address */ -extern in_addr_t ipv4_network_addr (in_addr_t hostaddr, int masklen); +extern in_addr_t ipv4_network_addr(in_addr_t hostaddr, int masklen); /* given the address of a host on a network and the network mask length, * calculate the broadcast address for that network; * special treatment for /31: returns the address of the other host * on the network by flipping the host bit */ -extern in_addr_t ipv4_broadcast_addr (in_addr_t hostaddr, int masklen); +extern in_addr_t ipv4_broadcast_addr(in_addr_t hostaddr, int masklen); -extern int netmask_str2prefix_str (const char *, const char *, char *); +extern int netmask_str2prefix_str(const char *, const char *, char *); -extern struct prefix_ipv6 *prefix_ipv6_new (void); -extern void prefix_ipv6_free (struct prefix_ipv6 *); -extern int str2prefix_ipv6 (const char *, struct prefix_ipv6 *); -extern void apply_mask_ipv6 (struct prefix_ipv6 *); +extern struct prefix_ipv6 *prefix_ipv6_new(void); +extern void prefix_ipv6_free(struct prefix_ipv6 *); +extern int str2prefix_ipv6(const char *, struct prefix_ipv6 *); +extern void apply_mask_ipv6(struct prefix_ipv6 *); -#define PREFIX_COPY_IPV6(DST, SRC) \ +#define PREFIX_COPY_IPV6(DST, SRC) \ *((struct prefix_ipv6 *)(DST)) = *((const struct prefix_ipv6 *)(SRC)); -extern int ip6_masklen (struct in6_addr); -extern void masklen2ip6 (const int, struct in6_addr *); +extern int ip6_masklen(struct in6_addr); +extern void masklen2ip6(const int, struct in6_addr *); -extern const char *inet6_ntoa (struct in6_addr); +extern const char *inet6_ntoa(struct in6_addr); extern int prefix_str2mac(const char *str, struct ethaddr *mac); extern char *prefix_mac2str(const struct ethaddr *mac, char *buf, int size); -static inline int ipv6_martian (struct in6_addr *addr) +static inline int ipv6_martian(struct in6_addr *addr) { - struct in6_addr localhost_addr; + struct in6_addr localhost_addr; - inet_pton (AF_INET6, "::1", &localhost_addr); + inet_pton(AF_INET6, "::1", &localhost_addr); - if (IPV6_ADDR_SAME(&localhost_addr, addr)) - return 1; + if (IPV6_ADDR_SAME(&localhost_addr, addr)) + return 1; - return 0; + return 0; } -extern int all_digit (const char *); +extern int all_digit(const char *); /* NOTE: This routine expects the address argument in network byte order. */ -static inline int ipv4_martian (struct in_addr *addr) +static inline int ipv4_martian(struct in_addr *addr) { - in_addr_t ip = ntohl(addr->s_addr); + in_addr_t ip = ntohl(addr->s_addr); - if (IPV4_NET0(ip) || IPV4_NET127(ip) || IPV4_CLASS_DE(ip)) { - return 1; - } - return 0; + if (IPV4_NET0(ip) || IPV4_NET127(ip) || IPV4_CLASS_DE(ip)) { + return 1; + } + return 0; } -static inline int -is_default_prefix (struct prefix *p) +static inline int is_default_prefix(struct prefix *p) { - if (!p) - return 0; + if (!p) + return 0; - if (((p->family == AF_INET) && (p->u.prefix4.s_addr == INADDR_ANY)) - || ((p->family == AF_INET6) && - !memcmp(&p->u.prefix6, &in6addr_any, sizeof (struct in6_addr)))) - return 1; + if (((p->family == AF_INET) && (p->u.prefix4.s_addr == INADDR_ANY)) + || ((p->family == AF_INET6) + && !memcmp(&p->u.prefix6, &in6addr_any, + sizeof(struct in6_addr)))) + return 1; - return 0; + return 0; } #endif /* _ZEBRA_PREFIX_H */ diff --git a/lib/privs.c b/lib/privs.c index 6b5dc9e1a..c97159611 100644 --- a/lib/privs.c +++ b/lib/privs.c @@ -1,4 +1,4 @@ -/* +/* * Zebra privileges. * * Copyright (C) 2003 Paul Jakma. @@ -39,18 +39,18 @@ DEFINE_MTYPE_STATIC(LIB, PRIVS, "Privilege information") * sets are mostly opaque, to hold a set of privileges, related in some way. * storage binds together a set of sets we're interested in. * (in reality: cap_value_t and priv_t are ints) - */ + */ #ifdef HAVE_LCAPS /* Linux doesn't have a 'set' type: a set of related privileges */ struct _pset { - int num; - cap_value_t *caps; + int num; + cap_value_t *caps; }; typedef cap_value_t pvalue_t; typedef struct _pset pset_t; typedef cap_t pstorage_t; -#elif defined (HAVE_SOLARIS_CAPABILITIES) +#elif defined(HAVE_SOLARIS_CAPABILITIES) typedef priv_t pvalue_t; typedef priv_set_t pset_t; typedef priv_set_t *pstorage_t; @@ -65,800 +65,817 @@ typedef priv_set_t *pstorage_t; static zebra_privs_current_t zprivs_null_state = ZPRIVS_RAISED; /* internal privileges state */ -static struct _zprivs_t -{ +static struct _zprivs_t { #ifdef HAVE_CAPABILITIES - pstorage_t caps; /* working storage */ - pset_t *syscaps_p; /* system-type requested permitted caps */ - pset_t *syscaps_i; /* system-type requested inheritable caps */ -#endif /* HAVE_CAPABILITIES */ - uid_t zuid, /* uid to run as */ - zsuid; /* saved uid */ - gid_t zgid; /* gid to run as */ - gid_t vtygrp; /* gid for vty sockets */ + pstorage_t caps; /* working storage */ + pset_t *syscaps_p; /* system-type requested permitted caps */ + pset_t *syscaps_i; /* system-type requested inheritable caps */ +#endif /* HAVE_CAPABILITIES */ + uid_t zuid, /* uid to run as */ + zsuid; /* saved uid */ + gid_t zgid; /* gid to run as */ + gid_t vtygrp; /* gid for vty sockets */ } zprivs_state; /* externally exported but not directly accessed functions */ #ifdef HAVE_CAPABILITIES -int zprivs_change_caps (zebra_privs_ops_t); -zebra_privs_current_t zprivs_state_caps (void); +int zprivs_change_caps(zebra_privs_ops_t); +zebra_privs_current_t zprivs_state_caps(void); #endif /* HAVE_CAPABILITIES */ -int zprivs_change_uid (zebra_privs_ops_t); -zebra_privs_current_t zprivs_state_uid (void); -int zprivs_change_null (zebra_privs_ops_t); -zebra_privs_current_t zprivs_state_null (void); +int zprivs_change_uid(zebra_privs_ops_t); +zebra_privs_current_t zprivs_state_uid(void); +int zprivs_change_null(zebra_privs_ops_t); +zebra_privs_current_t zprivs_state_null(void); #ifdef HAVE_CAPABILITIES /* internal capability API */ -static pset_t *zcaps2sys (zebra_capabilities_t *, int); -static void zprivs_caps_init (struct zebra_privs_t *); -static void zprivs_caps_terminate (void); +static pset_t *zcaps2sys(zebra_capabilities_t *, int); +static void zprivs_caps_init(struct zebra_privs_t *); +static void zprivs_caps_terminate(void); /* Map of Quagga abstract capabilities to system capabilities */ -static struct -{ - int num; - pvalue_t *system_caps; -} cap_map [ZCAP_MAX] = -{ +static struct { + int num; + pvalue_t *system_caps; +} cap_map[ZCAP_MAX] = { #ifdef HAVE_LCAPS /* Quagga -> Linux capabilities mappings */ - [ZCAP_SETID] = { 2, (pvalue_t []) { CAP_SETGID, - CAP_SETUID }, }, - [ZCAP_BIND] = { 1, (pvalue_t []) { CAP_NET_BIND_SERVICE }, }, - [ZCAP_NET_ADMIN] = { 1, (pvalue_t []) { CAP_NET_ADMIN }, }, - [ZCAP_NET_RAW] = { 1, (pvalue_t []) { CAP_NET_RAW }, }, - [ZCAP_CHROOT] = { 1, (pvalue_t []) { CAP_SYS_CHROOT, }, }, - [ZCAP_NICE] = { 1, (pvalue_t []) { CAP_SYS_NICE }, }, - [ZCAP_PTRACE] = { 1, (pvalue_t []) { CAP_SYS_PTRACE }, }, - [ZCAP_DAC_OVERRIDE] = { 1, (pvalue_t []) { CAP_DAC_OVERRIDE }, }, - [ZCAP_READ_SEARCH] = { 1, (pvalue_t []) { CAP_DAC_READ_SEARCH }, }, - [ZCAP_SYS_ADMIN] = { 1, (pvalue_t []) { CAP_SYS_ADMIN }, }, - [ZCAP_FOWNER] = { 1, (pvalue_t []) { CAP_FOWNER }, }, + [ZCAP_SETID] = + { + 2, (pvalue_t[]){CAP_SETGID, CAP_SETUID}, + }, + [ZCAP_BIND] = + { + 1, (pvalue_t[]){CAP_NET_BIND_SERVICE}, + }, + [ZCAP_NET_ADMIN] = + { + 1, (pvalue_t[]){CAP_NET_ADMIN}, + }, + [ZCAP_NET_RAW] = + { + 1, (pvalue_t[]){CAP_NET_RAW}, + }, + [ZCAP_CHROOT] = + { + 1, + (pvalue_t[]){ + CAP_SYS_CHROOT, + }, + }, + [ZCAP_NICE] = + { + 1, (pvalue_t[]){CAP_SYS_NICE}, + }, + [ZCAP_PTRACE] = + { + 1, (pvalue_t[]){CAP_SYS_PTRACE}, + }, + [ZCAP_DAC_OVERRIDE] = + { + 1, (pvalue_t[]){CAP_DAC_OVERRIDE}, + }, + [ZCAP_READ_SEARCH] = + { + 1, (pvalue_t[]){CAP_DAC_READ_SEARCH}, + }, + [ZCAP_SYS_ADMIN] = + { + 1, (pvalue_t[]){CAP_SYS_ADMIN}, + }, + [ZCAP_FOWNER] = + { + 1, (pvalue_t[]){CAP_FOWNER}, + }, #elif defined(HAVE_SOLARIS_CAPABILITIES) /* HAVE_LCAPS */ - /* Quagga -> Solaris privilege mappings */ - [ZCAP_SETID] = { 1, (pvalue_t []) { PRIV_PROC_SETID }, }, - [ZCAP_BIND] = { 1, (pvalue_t []) { PRIV_NET_PRIVADDR }, }, - /* IP_CONFIG is a subset of NET_CONFIG and is allowed in zones */ + /* Quagga -> Solaris privilege mappings */ + [ZCAP_SETID] = + { + 1, (pvalue_t[]){PRIV_PROC_SETID}, + }, + [ZCAP_BIND] = + { + 1, (pvalue_t[]){PRIV_NET_PRIVADDR}, + }, +/* IP_CONFIG is a subset of NET_CONFIG and is allowed in zones */ #ifdef PRIV_SYS_IP_CONFIG - [ZCAP_NET_ADMIN] = { 1, (pvalue_t []) { PRIV_SYS_IP_CONFIG }, }, + [ZCAP_NET_ADMIN] = + { + 1, (pvalue_t[]){PRIV_SYS_IP_CONFIG}, + }, #else - [ZCAP_NET_ADMIN] = { 1, (pvalue_t []) { PRIV_SYS_NET_CONFIG }, }, + [ZCAP_NET_ADMIN] = + { + 1, (pvalue_t[]){PRIV_SYS_NET_CONFIG}, + }, #endif - [ZCAP_NET_RAW] = { 2, (pvalue_t []) { PRIV_NET_RAWACCESS, - PRIV_NET_ICMPACCESS }, }, - [ZCAP_CHROOT] = { 1, (pvalue_t []) { PRIV_PROC_CHROOT }, }, - [ZCAP_NICE] = { 1, (pvalue_t []) { PRIV_PROC_PRIOCNTL }, }, - [ZCAP_PTRACE] = { 1, (pvalue_t []) { PRIV_PROC_SESSION }, }, - [ZCAP_DAC_OVERRIDE] = { 5, (pvalue_t []) { PRIV_FILE_DAC_EXECUTE, - PRIV_FILE_DAC_READ, - PRIV_FILE_DAC_SEARCH, - PRIV_FILE_DAC_WRITE, - PRIV_FILE_DAC_SEARCH }, }, - [ZCAP_READ_SEARCH] = { 2, (pvalue_t []) { PRIV_FILE_DAC_SEARCH, - PRIV_FILE_DAC_READ }, }, - [ZCAP_SYS_ADMIN] = { 1, (pvalue_t []) { PRIV_SYS_ADMIN }, }, - [ZCAP_FOWNER] = { 1, (pvalue_t []) { PRIV_FILE_OWNER }, }, + [ZCAP_NET_RAW] = + { + 2, (pvalue_t[]){PRIV_NET_RAWACCESS, + PRIV_NET_ICMPACCESS}, + }, + [ZCAP_CHROOT] = + { + 1, (pvalue_t[]){PRIV_PROC_CHROOT}, + }, + [ZCAP_NICE] = + { + 1, (pvalue_t[]){PRIV_PROC_PRIOCNTL}, + }, + [ZCAP_PTRACE] = + { + 1, (pvalue_t[]){PRIV_PROC_SESSION}, + }, + [ZCAP_DAC_OVERRIDE] = + { + 5, (pvalue_t[]){PRIV_FILE_DAC_EXECUTE, + PRIV_FILE_DAC_READ, + PRIV_FILE_DAC_SEARCH, + PRIV_FILE_DAC_WRITE, + PRIV_FILE_DAC_SEARCH}, + }, + [ZCAP_READ_SEARCH] = + { + 2, (pvalue_t[]){PRIV_FILE_DAC_SEARCH, + PRIV_FILE_DAC_READ}, + }, + [ZCAP_SYS_ADMIN] = + { + 1, (pvalue_t[]){PRIV_SYS_ADMIN}, + }, + [ZCAP_FOWNER] = + { + 1, (pvalue_t[]){PRIV_FILE_OWNER}, + }, #endif /* HAVE_SOLARIS_CAPABILITIES */ }; #ifdef HAVE_LCAPS /* Linux forms of capabilities methods */ /* convert zebras privileges to system capabilities */ -static pset_t * -zcaps2sys (zebra_capabilities_t *zcaps, int num) +static pset_t *zcaps2sys(zebra_capabilities_t *zcaps, int num) { - pset_t *syscaps; - int i, j = 0, count = 0; - - if (!num) - return NULL; - - /* first count up how many system caps we have */ - for (i= 0; i < num; i++) - count += cap_map[zcaps[i]].num; - - if ( (syscaps = XCALLOC (MTYPE_PRIVS, (sizeof(pset_t) * num))) == NULL) - { - fprintf (stderr, "%s: could not allocate syscaps!", __func__); - return NULL; - } - - syscaps->caps = XCALLOC (MTYPE_PRIVS, (sizeof (pvalue_t) * count)); - - if (!syscaps->caps) - { - fprintf (stderr, "%s: could not XCALLOC caps!", __func__); - return NULL; - } - - /* copy the capabilities over */ - count = 0; - for (i=0; i < num; i++) - for (j = 0; j < cap_map[zcaps[i]].num; j++) - syscaps->caps[count++] = cap_map[zcaps[i]].system_caps[j]; - - /* iterations above should be exact same as previous count, obviously.. */ - syscaps->num = count; - - return syscaps; + pset_t *syscaps; + int i, j = 0, count = 0; + + if (!num) + return NULL; + + /* first count up how many system caps we have */ + for (i = 0; i < num; i++) + count += cap_map[zcaps[i]].num; + + if ((syscaps = XCALLOC(MTYPE_PRIVS, (sizeof(pset_t) * num))) == NULL) { + fprintf(stderr, "%s: could not allocate syscaps!", __func__); + return NULL; + } + + syscaps->caps = XCALLOC(MTYPE_PRIVS, (sizeof(pvalue_t) * count)); + + if (!syscaps->caps) { + fprintf(stderr, "%s: could not XCALLOC caps!", __func__); + return NULL; + } + + /* copy the capabilities over */ + count = 0; + for (i = 0; i < num; i++) + for (j = 0; j < cap_map[zcaps[i]].num; j++) + syscaps->caps[count++] = + cap_map[zcaps[i]].system_caps[j]; + + /* iterations above should be exact same as previous count, obviously.. + */ + syscaps->num = count; + + return syscaps; } /* set or clear the effective capabilities to/from permitted */ -int -zprivs_change_caps (zebra_privs_ops_t op) +int zprivs_change_caps(zebra_privs_ops_t op) { - cap_flag_value_t cflag; - - /* should be no possibility of being called without valid caps */ - assert (zprivs_state.syscaps_p && zprivs_state.caps); - if (! (zprivs_state.syscaps_p && zprivs_state.caps)) - exit (1); - - if (op == ZPRIVS_RAISE) - cflag = CAP_SET; - else if (op == ZPRIVS_LOWER) - cflag = CAP_CLEAR; - else - return -1; - - if ( !cap_set_flag (zprivs_state.caps, CAP_EFFECTIVE, - zprivs_state.syscaps_p->num, - zprivs_state.syscaps_p->caps, - cflag)) - return cap_set_proc (zprivs_state.caps); - return -1; + cap_flag_value_t cflag; + + /* should be no possibility of being called without valid caps */ + assert(zprivs_state.syscaps_p && zprivs_state.caps); + if (!(zprivs_state.syscaps_p && zprivs_state.caps)) + exit(1); + + if (op == ZPRIVS_RAISE) + cflag = CAP_SET; + else if (op == ZPRIVS_LOWER) + cflag = CAP_CLEAR; + else + return -1; + + if (!cap_set_flag(zprivs_state.caps, CAP_EFFECTIVE, + zprivs_state.syscaps_p->num, + zprivs_state.syscaps_p->caps, cflag)) + return cap_set_proc(zprivs_state.caps); + return -1; } -zebra_privs_current_t -zprivs_state_caps (void) +zebra_privs_current_t zprivs_state_caps(void) { - int i; - cap_flag_value_t val; - - /* should be no possibility of being called without valid caps */ - assert (zprivs_state.syscaps_p && zprivs_state.caps); - if (! (zprivs_state.syscaps_p && zprivs_state.caps)) - exit (1); - - for (i=0; i < zprivs_state.syscaps_p->num; i++) - { - if ( cap_get_flag (zprivs_state.caps, zprivs_state.syscaps_p->caps[i], - CAP_EFFECTIVE, &val) ) - { - zlog_warn ("zprivs_state_caps: could not cap_get_flag, %s", - safe_strerror (errno) ); - return ZPRIVS_UNKNOWN; - } - if (val == CAP_SET) - return ZPRIVS_RAISED; - } - return ZPRIVS_LOWERED; + int i; + cap_flag_value_t val; + + /* should be no possibility of being called without valid caps */ + assert(zprivs_state.syscaps_p && zprivs_state.caps); + if (!(zprivs_state.syscaps_p && zprivs_state.caps)) + exit(1); + + for (i = 0; i < zprivs_state.syscaps_p->num; i++) { + if (cap_get_flag(zprivs_state.caps, + zprivs_state.syscaps_p->caps[i], CAP_EFFECTIVE, + &val)) { + zlog_warn( + "zprivs_state_caps: could not cap_get_flag, %s", + safe_strerror(errno)); + return ZPRIVS_UNKNOWN; + } + if (val == CAP_SET) + return ZPRIVS_RAISED; + } + return ZPRIVS_LOWERED; } -static void -zprivs_caps_init (struct zebra_privs_t *zprivs) +static void zprivs_caps_init(struct zebra_privs_t *zprivs) { - zprivs_state.syscaps_p = zcaps2sys (zprivs->caps_p, zprivs->cap_num_p); - zprivs_state.syscaps_i = zcaps2sys (zprivs->caps_i, zprivs->cap_num_i); - - /* Tell kernel we want caps maintained across uid changes */ - if ( prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1 ) - { - fprintf (stderr, "privs_init: could not set PR_SET_KEEPCAPS, %s\n", - safe_strerror (errno) ); - exit(1); - } - - /* we have caps, we have no need to ever change back the original user */ - /* only change uid if we don't have the correct one */ - if ((zprivs_state.zuid) && (zprivs_state.zsuid != zprivs_state.zuid)) - { - if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) ) - { - fprintf (stderr, "zprivs_init (cap): could not setreuid, %s\n", - safe_strerror (errno)); - exit (1); - } - } - - if ( !zprivs_state.syscaps_p ) - return; - - if ( !(zprivs_state.caps = cap_init()) ) - { - fprintf (stderr, "privs_init: failed to cap_init, %s\n", - safe_strerror (errno)); - exit (1); - } - - if ( cap_clear (zprivs_state.caps) ) - { - fprintf (stderr, "privs_init: failed to cap_clear, %s\n", - safe_strerror (errno)); - exit (1); - } - - /* set permitted caps */ - cap_set_flag(zprivs_state.caps, CAP_PERMITTED, - zprivs_state.syscaps_p->num, - zprivs_state.syscaps_p->caps, - CAP_SET); - - /* set inheritable caps, if any */ - if (zprivs_state.syscaps_i && zprivs_state.syscaps_i->num) - { - cap_set_flag(zprivs_state.caps, CAP_INHERITABLE, - zprivs_state.syscaps_i->num, - zprivs_state.syscaps_i->caps, - CAP_SET); - } - - /* apply caps. CAP_EFFECTIVE is cleared. we'll raise the caps as - * and when, and only when, they are needed. - */ - if ( cap_set_proc (zprivs_state.caps) ) - { - cap_t current_caps; - char *current_caps_text = NULL; - char *wanted_caps_text = NULL; - - fprintf(stderr, "privs_init: initial cap_set_proc failed: %s\n", - safe_strerror(errno)); - - current_caps = cap_get_proc(); - if (current_caps) - { - current_caps_text = cap_to_text(current_caps, NULL); - cap_free(current_caps); - } - - wanted_caps_text = cap_to_text(zprivs_state.caps, NULL); - fprintf(stderr, "Wanted caps: %s\n", wanted_caps_text ? wanted_caps_text : "???"); - fprintf(stderr, "Have caps: %s\n", current_caps_text ? current_caps_text : "???"); - if (current_caps_text) - cap_free(current_caps_text); - if (wanted_caps_text) - cap_free(wanted_caps_text); - - exit (1); - } - - /* set methods for the caller to use */ - zprivs->change = zprivs_change_caps; - zprivs->current_state = zprivs_state_caps; + zprivs_state.syscaps_p = zcaps2sys(zprivs->caps_p, zprivs->cap_num_p); + zprivs_state.syscaps_i = zcaps2sys(zprivs->caps_i, zprivs->cap_num_i); + + /* Tell kernel we want caps maintained across uid changes */ + if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) { + fprintf(stderr, + "privs_init: could not set PR_SET_KEEPCAPS, %s\n", + safe_strerror(errno)); + exit(1); + } + + /* we have caps, we have no need to ever change back the original user + */ + /* only change uid if we don't have the correct one */ + if ((zprivs_state.zuid) && (zprivs_state.zsuid != zprivs_state.zuid)) { + if (setreuid(zprivs_state.zuid, zprivs_state.zuid)) { + fprintf(stderr, + "zprivs_init (cap): could not setreuid, %s\n", + safe_strerror(errno)); + exit(1); + } + } + + if (!zprivs_state.syscaps_p) + return; + + if (!(zprivs_state.caps = cap_init())) { + fprintf(stderr, "privs_init: failed to cap_init, %s\n", + safe_strerror(errno)); + exit(1); + } + + if (cap_clear(zprivs_state.caps)) { + fprintf(stderr, "privs_init: failed to cap_clear, %s\n", + safe_strerror(errno)); + exit(1); + } + + /* set permitted caps */ + cap_set_flag(zprivs_state.caps, CAP_PERMITTED, + zprivs_state.syscaps_p->num, zprivs_state.syscaps_p->caps, + CAP_SET); + + /* set inheritable caps, if any */ + if (zprivs_state.syscaps_i && zprivs_state.syscaps_i->num) { + cap_set_flag(zprivs_state.caps, CAP_INHERITABLE, + zprivs_state.syscaps_i->num, + zprivs_state.syscaps_i->caps, CAP_SET); + } + + /* apply caps. CAP_EFFECTIVE is cleared. we'll raise the caps as + * and when, and only when, they are needed. + */ + if (cap_set_proc(zprivs_state.caps)) { + cap_t current_caps; + char *current_caps_text = NULL; + char *wanted_caps_text = NULL; + + fprintf(stderr, "privs_init: initial cap_set_proc failed: %s\n", + safe_strerror(errno)); + + current_caps = cap_get_proc(); + if (current_caps) { + current_caps_text = cap_to_text(current_caps, NULL); + cap_free(current_caps); + } + + wanted_caps_text = cap_to_text(zprivs_state.caps, NULL); + fprintf(stderr, "Wanted caps: %s\n", + wanted_caps_text ? wanted_caps_text : "???"); + fprintf(stderr, "Have caps: %s\n", + current_caps_text ? current_caps_text : "???"); + if (current_caps_text) + cap_free(current_caps_text); + if (wanted_caps_text) + cap_free(wanted_caps_text); + + exit(1); + } + + /* set methods for the caller to use */ + zprivs->change = zprivs_change_caps; + zprivs->current_state = zprivs_state_caps; } -static void -zprivs_caps_terminate (void) +static void zprivs_caps_terminate(void) { - /* clear all capabilities */ - if (zprivs_state.caps) - cap_clear (zprivs_state.caps); - - /* and boom, capabilities are gone forever */ - if ( cap_set_proc (zprivs_state.caps) ) - { - fprintf (stderr, "privs_terminate: cap_set_proc failed, %s", - safe_strerror (errno) ); - exit (1); - } - - /* free up private state */ - if (zprivs_state.syscaps_p->num) - { - XFREE (MTYPE_PRIVS, zprivs_state.syscaps_p->caps); - XFREE (MTYPE_PRIVS, zprivs_state.syscaps_p); - } - - if (zprivs_state.syscaps_i && zprivs_state.syscaps_i->num) - { - XFREE (MTYPE_PRIVS, zprivs_state.syscaps_i->caps); - XFREE (MTYPE_PRIVS, zprivs_state.syscaps_i); - } - - cap_free (zprivs_state.caps); + /* clear all capabilities */ + if (zprivs_state.caps) + cap_clear(zprivs_state.caps); + + /* and boom, capabilities are gone forever */ + if (cap_set_proc(zprivs_state.caps)) { + fprintf(stderr, "privs_terminate: cap_set_proc failed, %s", + safe_strerror(errno)); + exit(1); + } + + /* free up private state */ + if (zprivs_state.syscaps_p->num) { + XFREE(MTYPE_PRIVS, zprivs_state.syscaps_p->caps); + XFREE(MTYPE_PRIVS, zprivs_state.syscaps_p); + } + + if (zprivs_state.syscaps_i && zprivs_state.syscaps_i->num) { + XFREE(MTYPE_PRIVS, zprivs_state.syscaps_i->caps); + XFREE(MTYPE_PRIVS, zprivs_state.syscaps_i); + } + + cap_free(zprivs_state.caps); } -#elif defined (HAVE_SOLARIS_CAPABILITIES) /* !HAVE_LCAPS */ +#elif defined(HAVE_SOLARIS_CAPABILITIES) /* !HAVE_LCAPS */ -/* Solaris specific capability/privilege methods +/* Solaris specific capability/privilege methods * * Resources: * - the 'privileges' man page * - http://cvs.opensolaris.org - * - http://blogs.sun.com/roller/page/gbrunett?entry=privilege_enabling_set_id_programs1 + * - + * http://blogs.sun.com/roller/page/gbrunett?entry=privilege_enabling_set_id_programs1 */ -static pset_t * -zprivs_caps_minimal () +static pset_t *zprivs_caps_minimal() { - pset_t *minimal; + pset_t *minimal; - if ((minimal = priv_str_to_set("basic", ",", NULL)) == NULL) - { - fprintf (stderr, "%s: couldn't get basic set!\n", __func__); - exit (1); - } + if ((minimal = priv_str_to_set("basic", ",", NULL)) == NULL) { + fprintf(stderr, "%s: couldn't get basic set!\n", __func__); + exit(1); + } - /* create a minimal privilege set from the basic set */ - (void) priv_delset(minimal, PRIV_PROC_EXEC); - (void) priv_delset(minimal, PRIV_PROC_INFO); - (void) priv_delset(minimal, PRIV_PROC_SESSION); - (void) priv_delset(minimal, PRIV_FILE_LINK_ANY); + /* create a minimal privilege set from the basic set */ + (void)priv_delset(minimal, PRIV_PROC_EXEC); + (void)priv_delset(minimal, PRIV_PROC_INFO); + (void)priv_delset(minimal, PRIV_PROC_SESSION); + (void)priv_delset(minimal, PRIV_FILE_LINK_ANY); - return minimal; + return minimal; } /* convert zebras privileges to system capabilities */ -static pset_t * -zcaps2sys (zebra_capabilities_t *zcaps, int num) +static pset_t *zcaps2sys(zebra_capabilities_t *zcaps, int num) { - pset_t *syscaps; - int i, j = 0; - - if ((syscaps = priv_allocset()) == NULL) - { - fprintf (stderr, "%s: could not allocate syscaps!\n", __func__); - exit (1); - } - - priv_emptyset (syscaps); - - for (i=0; i < num; i++) - for (j = 0; j < cap_map[zcaps[i]].num; j++) - priv_addset (syscaps, cap_map[zcaps[i]].system_caps[j]); - - return syscaps; + pset_t *syscaps; + int i, j = 0; + + if ((syscaps = priv_allocset()) == NULL) { + fprintf(stderr, "%s: could not allocate syscaps!\n", __func__); + exit(1); + } + + priv_emptyset(syscaps); + + for (i = 0; i < num; i++) + for (j = 0; j < cap_map[zcaps[i]].num; j++) + priv_addset(syscaps, cap_map[zcaps[i]].system_caps[j]); + + return syscaps; } /* callback exported to users to RAISE and LOWER effective privileges * from nothing to the given permitted set and back down */ -int -zprivs_change_caps (zebra_privs_ops_t op) +int zprivs_change_caps(zebra_privs_ops_t op) { - pset_t *privset; - - /* should be no possibility of being called without valid caps */ - assert (zprivs_state.syscaps_p); - if (!zprivs_state.syscaps_p) - { - fprintf (stderr, "%s: Eek, missing privileged caps!", __func__); - exit (1); - } - - assert (zprivs_state.caps); - if (!zprivs_state.caps) - { - fprintf (stderr, "%s: Eek, missing caps!", __func__); - exit (1); - } - - /* to raise: copy original permitted as our working effective set - * to lower: copy regular effective set stored in zprivs_state.caps - */ - if (op == ZPRIVS_RAISE) - privset = zprivs_state.syscaps_p; - else if (op == ZPRIVS_LOWER) - privset = zprivs_state.caps; - else - return -1; - - if (setppriv (PRIV_SET, PRIV_EFFECTIVE, privset) != 0) - return -1; - - return 0; + pset_t *privset; + + /* should be no possibility of being called without valid caps */ + assert(zprivs_state.syscaps_p); + if (!zprivs_state.syscaps_p) { + fprintf(stderr, "%s: Eek, missing privileged caps!", __func__); + exit(1); + } + + assert(zprivs_state.caps); + if (!zprivs_state.caps) { + fprintf(stderr, "%s: Eek, missing caps!", __func__); + exit(1); + } + + /* to raise: copy original permitted as our working effective set + * to lower: copy regular effective set stored in zprivs_state.caps + */ + if (op == ZPRIVS_RAISE) + privset = zprivs_state.syscaps_p; + else if (op == ZPRIVS_LOWER) + privset = zprivs_state.caps; + else + return -1; + + if (setppriv(PRIV_SET, PRIV_EFFECTIVE, privset) != 0) + return -1; + + return 0; } /* Retrieve current privilege state, is it RAISED or LOWERED? */ -zebra_privs_current_t -zprivs_state_caps (void) +zebra_privs_current_t zprivs_state_caps(void) { - zebra_privs_current_t result; - pset_t *effective; - - if ( (effective = priv_allocset()) == NULL) - { - fprintf (stderr, "%s: failed to get priv_allocset! %s\n", __func__, - safe_strerror (errno)); - return ZPRIVS_UNKNOWN; - } - - if (getppriv (PRIV_EFFECTIVE, effective)) - { - fprintf (stderr, "%s: failed to get state! %s\n", __func__, - safe_strerror (errno)); - result = ZPRIVS_UNKNOWN; - } - else - { - if (priv_isequalset (effective, zprivs_state.syscaps_p)) - result = ZPRIVS_RAISED; - else if (priv_isequalset (effective, zprivs_state.caps)) - result = ZPRIVS_LOWERED; - else - result = ZPRIVS_UNKNOWN; - } - - priv_freeset (effective); - return result; + zebra_privs_current_t result; + pset_t *effective; + + if ((effective = priv_allocset()) == NULL) { + fprintf(stderr, "%s: failed to get priv_allocset! %s\n", + __func__, safe_strerror(errno)); + return ZPRIVS_UNKNOWN; + } + + if (getppriv(PRIV_EFFECTIVE, effective)) { + fprintf(stderr, "%s: failed to get state! %s\n", __func__, + safe_strerror(errno)); + result = ZPRIVS_UNKNOWN; + } else { + if (priv_isequalset(effective, zprivs_state.syscaps_p)) + result = ZPRIVS_RAISED; + else if (priv_isequalset(effective, zprivs_state.caps)) + result = ZPRIVS_LOWERED; + else + result = ZPRIVS_UNKNOWN; + } + + priv_freeset(effective); + return result; } -static void -zprivs_caps_init (struct zebra_privs_t *zprivs) +static void zprivs_caps_init(struct zebra_privs_t *zprivs) { - pset_t *basic; - pset_t *minimal; - - /* the specified sets */ - zprivs_state.syscaps_p = zcaps2sys (zprivs->caps_p, zprivs->cap_num_p); - zprivs_state.syscaps_i = zcaps2sys (zprivs->caps_i, zprivs->cap_num_i); - - /* nonsensical to have gotten here but not have capabilities */ - if (!zprivs_state.syscaps_p) - { - fprintf (stderr, "%s: capabilities enabled, " - "but no valid capabilities supplied\n", - __func__); - } - - /* We retain the basic set in our permitted set, as Linux has no - * equivalent. The basic set on Linux hence is implicit, always - * there. - */ - if ((basic = priv_str_to_set("basic", ",", NULL)) == NULL) - { - fprintf (stderr, "%s: couldn't get basic set!\n", __func__); - exit (1); - } - - /* Add the basic set to the permitted set */ - priv_union (basic, zprivs_state.syscaps_p); - priv_freeset (basic); - - /* Hey kernel, we know about privileges! - * this isn't strictly required, use of setppriv should have same effect - */ - if (setpflags (PRIV_AWARE, 1)) - { - fprintf (stderr, "%s: error setting PRIV_AWARE!, %s\n", __func__, - safe_strerror (errno) ); - exit (1); - } - - /* need either valid or empty sets for both p and i.. */ - assert (zprivs_state.syscaps_i && zprivs_state.syscaps_p); - - /* we have caps, we have no need to ever change back the original user - * change real, effective and saved to the specified user. - */ - /* only change uid if we don't have the correct one */ - if ((zprivs_state.zuid) && (zprivs_state.zsuid != zprivs_state.zuid)) - { - if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) ) - { - fprintf (stderr, "%s: could not setreuid, %s\n", - __func__, safe_strerror (errno)); - exit (1); - } - } - - /* set the permitted set */ - if (setppriv (PRIV_SET, PRIV_PERMITTED, zprivs_state.syscaps_p)) - { - fprintf (stderr, "%s: error setting permitted set!, %s\n", __func__, - safe_strerror (errno) ); - exit (1); - } - - /* set the inheritable set */ - if (setppriv (PRIV_SET, PRIV_INHERITABLE, zprivs_state.syscaps_i)) - { - fprintf (stderr, "%s: error setting inheritable set!, %s\n", __func__, - safe_strerror (errno) ); - exit (1); - } - - /* we need a minimal basic set for 'effective', potentially for inheritable too */ - minimal = zprivs_caps_minimal(); - - /* now set the effective set with a subset of basic privileges */ - if (setppriv (PRIV_SET, PRIV_EFFECTIVE, minimal)) - { - fprintf (stderr, "%s: error setting effective set!, %s\n", __func__, - safe_strerror (errno) ); - exit (1); - } - - /* we'll use the minimal set as our working-storage privset */ - zprivs_state.caps = minimal; - - /* set methods for the caller to use */ - zprivs->change = zprivs_change_caps; - zprivs->current_state = zprivs_state_caps; + pset_t *basic; + pset_t *minimal; + + /* the specified sets */ + zprivs_state.syscaps_p = zcaps2sys(zprivs->caps_p, zprivs->cap_num_p); + zprivs_state.syscaps_i = zcaps2sys(zprivs->caps_i, zprivs->cap_num_i); + + /* nonsensical to have gotten here but not have capabilities */ + if (!zprivs_state.syscaps_p) { + fprintf(stderr, + "%s: capabilities enabled, " + "but no valid capabilities supplied\n", + __func__); + } + + /* We retain the basic set in our permitted set, as Linux has no + * equivalent. The basic set on Linux hence is implicit, always + * there. + */ + if ((basic = priv_str_to_set("basic", ",", NULL)) == NULL) { + fprintf(stderr, "%s: couldn't get basic set!\n", __func__); + exit(1); + } + + /* Add the basic set to the permitted set */ + priv_union(basic, zprivs_state.syscaps_p); + priv_freeset(basic); + + /* Hey kernel, we know about privileges! + * this isn't strictly required, use of setppriv should have same effect + */ + if (setpflags(PRIV_AWARE, 1)) { + fprintf(stderr, "%s: error setting PRIV_AWARE!, %s\n", __func__, + safe_strerror(errno)); + exit(1); + } + + /* need either valid or empty sets for both p and i.. */ + assert(zprivs_state.syscaps_i && zprivs_state.syscaps_p); + + /* we have caps, we have no need to ever change back the original user + * change real, effective and saved to the specified user. + */ + /* only change uid if we don't have the correct one */ + if ((zprivs_state.zuid) && (zprivs_state.zsuid != zprivs_state.zuid)) { + if (setreuid(zprivs_state.zuid, zprivs_state.zuid)) { + fprintf(stderr, "%s: could not setreuid, %s\n", + __func__, safe_strerror(errno)); + exit(1); + } + } + + /* set the permitted set */ + if (setppriv(PRIV_SET, PRIV_PERMITTED, zprivs_state.syscaps_p)) { + fprintf(stderr, "%s: error setting permitted set!, %s\n", + __func__, safe_strerror(errno)); + exit(1); + } + + /* set the inheritable set */ + if (setppriv(PRIV_SET, PRIV_INHERITABLE, zprivs_state.syscaps_i)) { + fprintf(stderr, "%s: error setting inheritable set!, %s\n", + __func__, safe_strerror(errno)); + exit(1); + } + + /* we need a minimal basic set for 'effective', potentially for + * inheritable too */ + minimal = zprivs_caps_minimal(); + + /* now set the effective set with a subset of basic privileges */ + if (setppriv(PRIV_SET, PRIV_EFFECTIVE, minimal)) { + fprintf(stderr, "%s: error setting effective set!, %s\n", + __func__, safe_strerror(errno)); + exit(1); + } + + /* we'll use the minimal set as our working-storage privset */ + zprivs_state.caps = minimal; + + /* set methods for the caller to use */ + zprivs->change = zprivs_change_caps; + zprivs->current_state = zprivs_state_caps; } -static void -zprivs_caps_terminate (void) +static void zprivs_caps_terminate(void) { - assert (zprivs_state.caps); - - /* clear all capabilities by using working-storage privset */ - setppriv (PRIV_SET, PRIV_EFFECTIVE, zprivs_state.caps); - setppriv (PRIV_SET, PRIV_PERMITTED, zprivs_state.caps); - setppriv (PRIV_SET, PRIV_INHERITABLE, zprivs_state.caps); - - /* free up private state */ - if (zprivs_state.syscaps_p) - priv_freeset (zprivs_state.syscaps_p); - if (zprivs_state.syscaps_i) - priv_freeset (zprivs_state.syscaps_i); - - priv_freeset (zprivs_state.caps); + assert(zprivs_state.caps); + + /* clear all capabilities by using working-storage privset */ + setppriv(PRIV_SET, PRIV_EFFECTIVE, zprivs_state.caps); + setppriv(PRIV_SET, PRIV_PERMITTED, zprivs_state.caps); + setppriv(PRIV_SET, PRIV_INHERITABLE, zprivs_state.caps); + + /* free up private state */ + if (zprivs_state.syscaps_p) + priv_freeset(zprivs_state.syscaps_p); + if (zprivs_state.syscaps_i) + priv_freeset(zprivs_state.syscaps_i); + + priv_freeset(zprivs_state.caps); } #else /* !HAVE_LCAPS && ! HAVE_SOLARIS_CAPABILITIES */ #error "Neither Solaris nor Linux capabilities, dazed and confused..." #endif /* HAVE_LCAPS */ #endif /* HAVE_CAPABILITIES */ -int -zprivs_change_uid (zebra_privs_ops_t op) +int zprivs_change_uid(zebra_privs_ops_t op) { - if (zprivs_state.zsuid == zprivs_state.zuid) - return 0; - if (op == ZPRIVS_RAISE) - return seteuid (zprivs_state.zsuid); - else if (op == ZPRIVS_LOWER) - return seteuid (zprivs_state.zuid); - else - return -1; + if (zprivs_state.zsuid == zprivs_state.zuid) + return 0; + if (op == ZPRIVS_RAISE) + return seteuid(zprivs_state.zsuid); + else if (op == ZPRIVS_LOWER) + return seteuid(zprivs_state.zuid); + else + return -1; } -zebra_privs_current_t -zprivs_state_uid (void) +zebra_privs_current_t zprivs_state_uid(void) { - return ( (zprivs_state.zuid == geteuid()) ? ZPRIVS_LOWERED : ZPRIVS_RAISED); + return ((zprivs_state.zuid == geteuid()) ? ZPRIVS_LOWERED + : ZPRIVS_RAISED); } -int -zprivs_change_null (zebra_privs_ops_t op) +int zprivs_change_null(zebra_privs_ops_t op) { - return 0; + return 0; } -zebra_privs_current_t -zprivs_state_null (void) +zebra_privs_current_t zprivs_state_null(void) { - return zprivs_null_state; + return zprivs_null_state; } #ifndef HAVE_GETGROUPLIST /* Solaris 11 has no getgrouplist() */ -static int -getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups) +static int getgrouplist(const char *user, gid_t group, gid_t *groups, + int *ngroups) { - struct group *grp; - size_t usridx; - int pos = 0, ret; - - if (pos < *ngroups) - groups[pos] = group; - pos++; - - setgrent(); - while ((grp = getgrent())) - { - if (grp->gr_gid == group) - continue; - for (usridx = 0; grp->gr_mem[usridx] != NULL; usridx++) - if (!strcmp (grp->gr_mem[usridx], user)) - { - if (pos < *ngroups) - groups[pos] = grp->gr_gid; - pos++; - break; - } - } - endgrent(); - - ret = (pos <= *ngroups) ? pos : -1; - *ngroups = pos; - return ret; + struct group *grp; + size_t usridx; + int pos = 0, ret; + + if (pos < *ngroups) + groups[pos] = group; + pos++; + + setgrent(); + while ((grp = getgrent())) { + if (grp->gr_gid == group) + continue; + for (usridx = 0; grp->gr_mem[usridx] != NULL; usridx++) + if (!strcmp(grp->gr_mem[usridx], user)) { + if (pos < *ngroups) + groups[pos] = grp->gr_gid; + pos++; + break; + } + } + endgrent(); + + ret = (pos <= *ngroups) ? pos : -1; + *ngroups = pos; + return ret; } #endif /* HAVE_GETGROUPLIST */ -void -zprivs_init(struct zebra_privs_t *zprivs) +void zprivs_init(struct zebra_privs_t *zprivs) { - struct passwd *pwentry = NULL; - struct group *grentry = NULL; - gid_t groups[NGROUPS_MAX]; - int i, ngroups = 0; - int found = 0; - - if (!zprivs) - { - fprintf (stderr, "zprivs_init: called with NULL arg!\n"); - exit (1); - } - - if (zprivs->vty_group) - { - /* in a "NULL" setup, this is allowed to fail too, but still try. */ - if ((grentry = getgrnam (zprivs->vty_group))) - zprivs_state.vtygrp = grentry->gr_gid; - else - zprivs_state.vtygrp = (gid_t)-1; - } - - /* NULL privs */ - if (! (zprivs->user || zprivs->group - || zprivs->cap_num_p || zprivs->cap_num_i) ) - { - zprivs->change = zprivs_change_null; - zprivs->current_state = zprivs_state_null; - return; - } - - if (zprivs->user) - { - if ( (pwentry = getpwnam (zprivs->user)) == NULL ) - { - /* cant use log.h here as it depends on vty */ - fprintf (stderr, "privs_init: could not lookup user %s\n", - zprivs->user); - exit (1); - } - - zprivs_state.zuid = pwentry->pw_uid; - zprivs_state.zgid = pwentry->pw_gid; - } - - grentry = NULL; - - if (zprivs->group) - { - if ( (grentry = getgrnam (zprivs->group)) == NULL ) - { - fprintf (stderr, "privs_init: could not lookup group %s\n", - zprivs->group); - exit (1); - } - - zprivs_state.zgid = grentry->gr_gid; - } - - if (zprivs->user) - { - ngroups = sizeof(groups); - if (getgrouplist (zprivs->user, zprivs_state.zgid, groups, &ngroups) < 0) - { - /* cant use log.h here as it depends on vty */ - fprintf (stderr, "privs_init: could not getgrouplist for user %s\n", - zprivs->user); - exit (1); - } - } - - if (zprivs->vty_group) - /* Add the vty_group to the supplementary groups so it can be chowned to */ - { - if (zprivs_state.vtygrp == (gid_t)-1) - { - fprintf (stderr, "privs_init: could not lookup vty group %s\n", - zprivs->vty_group); - exit (1); - } - - for ( i = 0; i < ngroups; i++ ) - if ( groups[i] == zprivs_state.vtygrp ) - { - found++; - break; - } - - if (!found) - { - fprintf (stderr, "privs_init: user(%s) is not part of vty group specified(%s)\n", - zprivs->user, zprivs->vty_group); - exit (1); - } - if ( i >= ngroups && ngroups < (int) ZEBRA_NUM_OF(groups) ) - { - groups[i] = zprivs_state.vtygrp; - } - } - - zprivs_state.zsuid = geteuid(); /* initial uid */ - /* add groups only if we changed uid - otherwise skip */ - if ((ngroups) && (zprivs_state.zsuid != zprivs_state.zuid)) - { - if ( setgroups (ngroups, groups) ) - { - fprintf (stderr, "privs_init: could not setgroups, %s\n", - safe_strerror (errno) ); - exit (1); - } - } - - /* change gid only if we changed uid - otherwise skip */ - if ((zprivs_state.zgid) && (zprivs_state.zsuid != zprivs_state.zuid)) - { - /* change group now, forever. uid we do later */ - if ( setregid (zprivs_state.zgid, zprivs_state.zgid) ) - { - fprintf (stderr, "zprivs_init: could not setregid, %s\n", - safe_strerror (errno) ); - exit (1); - } - } - + struct passwd *pwentry = NULL; + struct group *grentry = NULL; + gid_t groups[NGROUPS_MAX]; + int i, ngroups = 0; + int found = 0; + + if (!zprivs) { + fprintf(stderr, "zprivs_init: called with NULL arg!\n"); + exit(1); + } + + if (zprivs->vty_group) { + /* in a "NULL" setup, this is allowed to fail too, but still + * try. */ + if ((grentry = getgrnam(zprivs->vty_group))) + zprivs_state.vtygrp = grentry->gr_gid; + else + zprivs_state.vtygrp = (gid_t)-1; + } + + /* NULL privs */ + if (!(zprivs->user || zprivs->group || zprivs->cap_num_p + || zprivs->cap_num_i)) { + zprivs->change = zprivs_change_null; + zprivs->current_state = zprivs_state_null; + return; + } + + if (zprivs->user) { + if ((pwentry = getpwnam(zprivs->user)) == NULL) { + /* cant use log.h here as it depends on vty */ + fprintf(stderr, + "privs_init: could not lookup user %s\n", + zprivs->user); + exit(1); + } + + zprivs_state.zuid = pwentry->pw_uid; + zprivs_state.zgid = pwentry->pw_gid; + } + + grentry = NULL; + + if (zprivs->group) { + if ((grentry = getgrnam(zprivs->group)) == NULL) { + fprintf(stderr, + "privs_init: could not lookup group %s\n", + zprivs->group); + exit(1); + } + + zprivs_state.zgid = grentry->gr_gid; + } + + if (zprivs->user) { + ngroups = sizeof(groups); + if (getgrouplist(zprivs->user, zprivs_state.zgid, groups, + &ngroups) + < 0) { + /* cant use log.h here as it depends on vty */ + fprintf(stderr, + "privs_init: could not getgrouplist for user %s\n", + zprivs->user); + exit(1); + } + } + + if (zprivs->vty_group) + /* Add the vty_group to the supplementary groups so it can be chowned to + */ + { + if (zprivs_state.vtygrp == (gid_t)-1) { + fprintf(stderr, + "privs_init: could not lookup vty group %s\n", + zprivs->vty_group); + exit(1); + } + + for (i = 0; i < ngroups; i++) + if (groups[i] == zprivs_state.vtygrp) { + found++; + break; + } + + if (!found) { + fprintf(stderr, + "privs_init: user(%s) is not part of vty group specified(%s)\n", + zprivs->user, zprivs->vty_group); + exit(1); + } + if (i >= ngroups && ngroups < (int)ZEBRA_NUM_OF(groups)) { + groups[i] = zprivs_state.vtygrp; + } + } + + zprivs_state.zsuid = geteuid(); /* initial uid */ + /* add groups only if we changed uid - otherwise skip */ + if ((ngroups) && (zprivs_state.zsuid != zprivs_state.zuid)) { + if (setgroups(ngroups, groups)) { + fprintf(stderr, "privs_init: could not setgroups, %s\n", + safe_strerror(errno)); + exit(1); + } + } + + /* change gid only if we changed uid - otherwise skip */ + if ((zprivs_state.zgid) && (zprivs_state.zsuid != zprivs_state.zuid)) { + /* change group now, forever. uid we do later */ + if (setregid(zprivs_state.zgid, zprivs_state.zgid)) { + fprintf(stderr, "zprivs_init: could not setregid, %s\n", + safe_strerror(errno)); + exit(1); + } + } + #ifdef HAVE_CAPABILITIES - zprivs_caps_init (zprivs); -#else /* !HAVE_CAPABILITIES */ - /* we dont have caps. we'll need to maintain rid and saved uid - * and change euid back to saved uid (who we presume has all neccessary - * privileges) whenever we are asked to raise our privileges. - * - * This is not worth that much security wise, but all we can do. - */ - zprivs_state.zsuid = geteuid(); - /* only change uid if we don't have the correct one */ - if (( zprivs_state.zuid ) && (zprivs_state.zsuid != zprivs_state.zuid)) - { - if ( setreuid (-1, zprivs_state.zuid) ) - { - fprintf (stderr, "privs_init (uid): could not setreuid, %s\n", - safe_strerror (errno)); - exit (1); - } - } - - zprivs->change = zprivs_change_uid; - zprivs->current_state = zprivs_state_uid; + zprivs_caps_init(zprivs); +#else /* !HAVE_CAPABILITIES */ + /* we dont have caps. we'll need to maintain rid and saved uid + * and change euid back to saved uid (who we presume has all neccessary + * privileges) whenever we are asked to raise our privileges. + * + * This is not worth that much security wise, but all we can do. + */ + zprivs_state.zsuid = geteuid(); + /* only change uid if we don't have the correct one */ + if ((zprivs_state.zuid) && (zprivs_state.zsuid != zprivs_state.zuid)) { + if (setreuid(-1, zprivs_state.zuid)) { + fprintf(stderr, + "privs_init (uid): could not setreuid, %s\n", + safe_strerror(errno)); + exit(1); + } + } + + zprivs->change = zprivs_change_uid; + zprivs->current_state = zprivs_state_uid; #endif /* HAVE_CAPABILITIES */ } -void -zprivs_terminate (struct zebra_privs_t *zprivs) +void zprivs_terminate(struct zebra_privs_t *zprivs) { - if (!zprivs) - { - fprintf (stderr, "%s: no privs struct given, terminating", __func__); - exit (0); - } - + if (!zprivs) { + fprintf(stderr, "%s: no privs struct given, terminating", + __func__); + exit(0); + } + #ifdef HAVE_CAPABILITIES - zprivs_caps_terminate(); -#else /* !HAVE_CAPABILITIES */ - /* only change uid if we don't have the correct one */ - if ((zprivs_state.zuid) && (zprivs_state.zsuid != zprivs_state.zuid)) - { - if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) ) - { - fprintf (stderr, "privs_terminate: could not setreuid, %s", - safe_strerror (errno) ); - exit (1); - } - } + zprivs_caps_terminate(); +#else /* !HAVE_CAPABILITIES */ + /* only change uid if we don't have the correct one */ + if ((zprivs_state.zuid) && (zprivs_state.zsuid != zprivs_state.zuid)) { + if (setreuid(zprivs_state.zuid, zprivs_state.zuid)) { + fprintf(stderr, + "privs_terminate: could not setreuid, %s", + safe_strerror(errno)); + exit(1); + } + } #endif /* HAVE_LCAPS */ - zprivs->change = zprivs_change_null; - zprivs->current_state = zprivs_state_null; - zprivs_null_state = ZPRIVS_LOWERED; - return; + zprivs->change = zprivs_change_null; + zprivs->current_state = zprivs_state_null; + zprivs_null_state = ZPRIVS_LOWERED; + return; } -void -zprivs_get_ids(struct zprivs_ids_t *ids) +void zprivs_get_ids(struct zprivs_ids_t *ids) { - ids->uid_priv = getuid(); - (zprivs_state.zuid) ? (ids->uid_normal = zprivs_state.zuid) - : (ids->uid_normal = -1); - (zprivs_state.zgid) ? (ids->gid_normal = zprivs_state.zgid) - : (ids->gid_normal = -1); - (zprivs_state.vtygrp) ? (ids->gid_vty = zprivs_state.vtygrp) - : (ids->gid_vty = -1); - - return; + ids->uid_priv = getuid(); + (zprivs_state.zuid) ? (ids->uid_normal = zprivs_state.zuid) + : (ids->uid_normal = -1); + (zprivs_state.zgid) ? (ids->gid_normal = zprivs_state.zgid) + : (ids->gid_normal = -1); + (zprivs_state.vtygrp) ? (ids->gid_vty = zprivs_state.vtygrp) + : (ids->gid_vty = -1); + + return; } diff --git a/lib/privs.h b/lib/privs.h index 9a5eb3bd6..c18fe78ad 100644 --- a/lib/privs.h +++ b/lib/privs.h @@ -1,4 +1,4 @@ -/* +/* * Zebra privileges header. * * Copyright (C) 2003 Paul Jakma. @@ -24,66 +24,60 @@ #define _ZEBRA_PRIVS_H /* list of zebra capabilities */ -typedef enum -{ - ZCAP_SETID, - ZCAP_BIND, - ZCAP_NET_ADMIN, - ZCAP_SYS_ADMIN, - ZCAP_NET_RAW, - ZCAP_CHROOT, - ZCAP_NICE, - ZCAP_PTRACE, - ZCAP_DAC_OVERRIDE, - ZCAP_READ_SEARCH, - ZCAP_FOWNER, - ZCAP_MAX +typedef enum { + ZCAP_SETID, + ZCAP_BIND, + ZCAP_NET_ADMIN, + ZCAP_SYS_ADMIN, + ZCAP_NET_RAW, + ZCAP_CHROOT, + ZCAP_NICE, + ZCAP_PTRACE, + ZCAP_DAC_OVERRIDE, + ZCAP_READ_SEARCH, + ZCAP_FOWNER, + ZCAP_MAX } zebra_capabilities_t; -typedef enum -{ - ZPRIVS_LOWERED, - ZPRIVS_RAISED, - ZPRIVS_UNKNOWN, +typedef enum { + ZPRIVS_LOWERED, + ZPRIVS_RAISED, + ZPRIVS_UNKNOWN, } zebra_privs_current_t; -typedef enum -{ - ZPRIVS_RAISE, - ZPRIVS_LOWER, +typedef enum { + ZPRIVS_RAISE, + ZPRIVS_LOWER, } zebra_privs_ops_t; -struct zebra_privs_t -{ - zebra_capabilities_t *caps_p; /* caps required for operation */ - zebra_capabilities_t *caps_i; /* caps to allow inheritance of */ - int cap_num_p; /* number of caps in arrays */ - int cap_num_i; - const char *user; /* user and group to run as */ - const char *group; - const char *vty_group; /* group to chown vty socket to */ - /* methods */ - int - (*change) (zebra_privs_ops_t); /* change privileges, 0 on success */ - zebra_privs_current_t - (*current_state) (void); /* current privilege state */ +struct zebra_privs_t { + zebra_capabilities_t *caps_p; /* caps required for operation */ + zebra_capabilities_t *caps_i; /* caps to allow inheritance of */ + int cap_num_p; /* number of caps in arrays */ + int cap_num_i; + const char *user; /* user and group to run as */ + const char *group; + const char *vty_group; /* group to chown vty socket to */ + /* methods */ + int (*change)(zebra_privs_ops_t); /* change privileges, 0 on success */ + zebra_privs_current_t (*current_state)( + void); /* current privilege state */ }; -struct zprivs_ids_t -{ - /* -1 is undefined */ - uid_t uid_priv; /* privileged uid */ - uid_t uid_normal; /* normal uid */ - gid_t gid_priv; /* privileged uid */ - gid_t gid_normal; /* normal uid */ - gid_t gid_vty; /* vty gid */ +struct zprivs_ids_t { + /* -1 is undefined */ + uid_t uid_priv; /* privileged uid */ + uid_t uid_normal; /* normal uid */ + gid_t gid_priv; /* privileged uid */ + gid_t gid_normal; /* normal uid */ + gid_t gid_vty; /* vty gid */ }; - /* initialise zebra privileges */ -extern void zprivs_init (struct zebra_privs_t *zprivs); - /* drop all and terminate privileges */ -extern void zprivs_terminate (struct zebra_privs_t *); - /* query for runtime uid's and gid's, eg vty needs this */ +/* initialise zebra privileges */ +extern void zprivs_init(struct zebra_privs_t *zprivs); +/* drop all and terminate privileges */ +extern void zprivs_terminate(struct zebra_privs_t *); +/* query for runtime uid's and gid's, eg vty needs this */ extern void zprivs_get_ids(struct zprivs_ids_t *); #endif /* _ZEBRA_PRIVS_H */ diff --git a/lib/ptm_lib.c b/lib/ptm_lib.c index 7181e2d89..f50d1e298 100644 --- a/lib/ptm_lib.c +++ b/lib/ptm_lib.c @@ -32,445 +32,433 @@ #define DEBUG_E 0 #define DEBUG_V 0 -#define ERRLOG(fmt, ...) \ - do { if (DEBUG_E) fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, \ - __LINE__, __func__, ##__VA_ARGS__); } while (0) - -#define DLOG(fmt, ...) \ - do { if (DEBUG_V) fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, \ - __LINE__, __func__, ##__VA_ARGS__); } while (0) +#define ERRLOG(fmt, ...) \ + do { \ + if (DEBUG_E) \ + fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, \ + __LINE__, __func__, ##__VA_ARGS__); \ + } while (0) + +#define DLOG(fmt, ...) \ + do { \ + if (DEBUG_V) \ + fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, \ + __LINE__, __func__, ##__VA_ARGS__); \ + } while (0) typedef struct ptm_lib_msg_ctxt_s { - int cmd_id; - csv_t *csv; - ptmlib_msg_type type; + int cmd_id; + csv_t *csv; + ptmlib_msg_type type; } ptm_lib_msg_ctxt_t; -static csv_record_t * -_ptm_lib_encode_header(csv_t *csv, - csv_record_t *rec, - int msglen, - int version, - int type, - int cmd_id, - char *client_name) +static csv_record_t *_ptm_lib_encode_header(csv_t *csv, csv_record_t *rec, + int msglen, int version, int type, + int cmd_id, char *client_name) { - char msglen_buf[16], vers_buf[16], type_buf[16], cmdid_buf[16]; - char client_buf[32]; - csv_record_t *rec1; - - sprintf(msglen_buf, "%4u", msglen); - sprintf(vers_buf, "%4u", version); - sprintf(type_buf, "%4u", type); - sprintf(cmdid_buf, "%4u", cmd_id); - snprintf(client_buf, 17, "%16.16s", client_name); - if (rec) { - rec1 = csv_encode_record(csv, rec, 5, msglen_buf, vers_buf, - type_buf, cmdid_buf, client_buf); - } else { - rec1 = csv_encode(csv, 5, msglen_buf, vers_buf, - type_buf, cmdid_buf, client_buf); - } - return (rec1); + char msglen_buf[16], vers_buf[16], type_buf[16], cmdid_buf[16]; + char client_buf[32]; + csv_record_t *rec1; + + sprintf(msglen_buf, "%4u", msglen); + sprintf(vers_buf, "%4u", version); + sprintf(type_buf, "%4u", type); + sprintf(cmdid_buf, "%4u", cmd_id); + snprintf(client_buf, 17, "%16.16s", client_name); + if (rec) { + rec1 = csv_encode_record(csv, rec, 5, msglen_buf, vers_buf, + type_buf, cmdid_buf, client_buf); + } else { + rec1 = csv_encode(csv, 5, msglen_buf, vers_buf, type_buf, + cmdid_buf, client_buf); + } + return (rec1); } -static int -_ptm_lib_decode_header (csv_t *csv, - int *msglen, - int *version, - int *type, - int *cmd_id, - char *client_name) +static int _ptm_lib_decode_header(csv_t *csv, int *msglen, int *version, + int *type, int *cmd_id, char *client_name) { - char *hdr; - csv_record_t *rec; - csv_field_t *fld; - int i, j; - - csv_decode(csv, NULL); - rec = csv_record_iter(csv); - if (rec == NULL) { - DLOG("malformed CSV\n"); - return (-1); - } - hdr = csv_field_iter(rec, &fld); - if (hdr == NULL) { - DLOG("malformed CSV\n"); - return (-1); - } - *msglen = atoi(hdr); - hdr = csv_field_iter_next(&fld); - if (hdr == NULL) { - DLOG("malformed CSV\n"); - return (-1); - } - *version = atoi(hdr); - hdr = csv_field_iter_next(&fld); - if (hdr == NULL) { - DLOG("malformed CSV\n"); - return (-1); - } - *type = atoi(hdr); - hdr = csv_field_iter_next(&fld); - if (hdr == NULL) { - DLOG("malformed CSV\n"); - return (-1); - } - *cmd_id = atoi(hdr); - hdr = csv_field_iter_next(&fld); - if (hdr == NULL) { - DLOG("malformed CSV\n"); - return (-1); - } - /* remove leading spaces */ - for (i = j = 0; i < csv_field_len(fld); i++) { - if (!isspace(hdr[i])) { - client_name[j] = hdr[i]; - j++; - } - } - client_name[j] = '\0'; - - return (0); + char *hdr; + csv_record_t *rec; + csv_field_t *fld; + int i, j; + + csv_decode(csv, NULL); + rec = csv_record_iter(csv); + if (rec == NULL) { + DLOG("malformed CSV\n"); + return (-1); + } + hdr = csv_field_iter(rec, &fld); + if (hdr == NULL) { + DLOG("malformed CSV\n"); + return (-1); + } + *msglen = atoi(hdr); + hdr = csv_field_iter_next(&fld); + if (hdr == NULL) { + DLOG("malformed CSV\n"); + return (-1); + } + *version = atoi(hdr); + hdr = csv_field_iter_next(&fld); + if (hdr == NULL) { + DLOG("malformed CSV\n"); + return (-1); + } + *type = atoi(hdr); + hdr = csv_field_iter_next(&fld); + if (hdr == NULL) { + DLOG("malformed CSV\n"); + return (-1); + } + *cmd_id = atoi(hdr); + hdr = csv_field_iter_next(&fld); + if (hdr == NULL) { + DLOG("malformed CSV\n"); + return (-1); + } + /* remove leading spaces */ + for (i = j = 0; i < csv_field_len(fld); i++) { + if (!isspace(hdr[i])) { + client_name[j] = hdr[i]; + j++; + } + } + client_name[j] = '\0'; + + return (0); } -int -ptm_lib_append_msg(ptm_lib_handle_t *hdl, void *ctxt, - const char *key, const char *val) +int ptm_lib_append_msg(ptm_lib_handle_t *hdl, void *ctxt, const char *key, + const char *val) { - ptm_lib_msg_ctxt_t *p_ctxt = ctxt; - csv_t *csv; - csv_record_t *mh_rec, *rec; - - if (!p_ctxt) { - ERRLOG("%s: no context \n", __FUNCTION__); - return -1; - } - - csv = p_ctxt->csv; - mh_rec = csv_record_iter(csv); - rec = csv_record_iter_next(mh_rec); - - /* append to the hdr record */ - rec = csv_append_record(csv, rec, 1, key); - if (!rec) { - ERRLOG("%s: Could not append key \n", __FUNCTION__); - return -1; - } - - rec = csv_record_iter_next(rec); - /* append to the data record */ - rec = csv_append_record(csv, rec, 1, val); - if (!rec) { - ERRLOG("%s: Could not append val \n", __FUNCTION__); - return -1; - } - - /* update the msg hdr */ - _ptm_lib_encode_header(csv, mh_rec, - (csvlen(csv) - PTMLIB_MSG_HDR_LEN), - PTMLIB_MSG_VERSION, p_ctxt->type, - p_ctxt->cmd_id, hdl->client_name); - - return 0; + ptm_lib_msg_ctxt_t *p_ctxt = ctxt; + csv_t *csv; + csv_record_t *mh_rec, *rec; + + if (!p_ctxt) { + ERRLOG("%s: no context \n", __FUNCTION__); + return -1; + } + + csv = p_ctxt->csv; + mh_rec = csv_record_iter(csv); + rec = csv_record_iter_next(mh_rec); + + /* append to the hdr record */ + rec = csv_append_record(csv, rec, 1, key); + if (!rec) { + ERRLOG("%s: Could not append key \n", __FUNCTION__); + return -1; + } + + rec = csv_record_iter_next(rec); + /* append to the data record */ + rec = csv_append_record(csv, rec, 1, val); + if (!rec) { + ERRLOG("%s: Could not append val \n", __FUNCTION__); + return -1; + } + + /* update the msg hdr */ + _ptm_lib_encode_header(csv, mh_rec, (csvlen(csv) - PTMLIB_MSG_HDR_LEN), + PTMLIB_MSG_VERSION, p_ctxt->type, p_ctxt->cmd_id, + hdl->client_name); + + return 0; } -int -ptm_lib_init_msg(ptm_lib_handle_t *hdl, int cmd_id, int type, - void *in_ctxt, void **out_ctxt) +int ptm_lib_init_msg(ptm_lib_handle_t *hdl, int cmd_id, int type, void *in_ctxt, + void **out_ctxt) { - ptm_lib_msg_ctxt_t *p_ctxt; - ptm_lib_msg_ctxt_t *p_in_ctxt = in_ctxt; - csv_t *csv; - csv_record_t *rec, *d_rec; - - /* Initialize csv for using discrete record buffers */ - csv = csv_init(NULL, NULL, PTMLIB_MSG_SZ); - - if (!csv) { - ERRLOG("%s: Could not allocate csv \n", __FUNCTION__); - return -1; - } - - rec = _ptm_lib_encode_header(csv, NULL, 0, - PTMLIB_MSG_VERSION, type, - cmd_id, hdl->client_name); - - if (!rec) { - ERRLOG("%s: Could not allocate record \n", __FUNCTION__); - csv_clean(csv); - csv_free(csv); - return -1; - } - - p_ctxt = calloc(1, sizeof(*p_ctxt)); - if (!p_ctxt) { - ERRLOG("%s: Could not allocate context \n", __FUNCTION__); - csv_clean(csv); - csv_free(csv); - return -1; - } - - p_ctxt->csv = csv; - p_ctxt->cmd_id = cmd_id; - p_ctxt->type = type; - - *(ptm_lib_msg_ctxt_t **)out_ctxt = p_ctxt; - - /* caller supplied a context to initialize with? */ - if (p_in_ctxt) { - /* insert the hdr rec */ - rec = csv_record_iter(p_in_ctxt->csv); - csv_clone_record (p_in_ctxt->csv, rec, &d_rec); - csv_insert_record (csv, d_rec); - /* insert the data rec */ - rec = csv_record_iter_next(rec); - csv_clone_record (p_in_ctxt->csv, rec, &d_rec); - csv_insert_record (csv, d_rec); - } - return 0; + ptm_lib_msg_ctxt_t *p_ctxt; + ptm_lib_msg_ctxt_t *p_in_ctxt = in_ctxt; + csv_t *csv; + csv_record_t *rec, *d_rec; + + /* Initialize csv for using discrete record buffers */ + csv = csv_init(NULL, NULL, PTMLIB_MSG_SZ); + + if (!csv) { + ERRLOG("%s: Could not allocate csv \n", __FUNCTION__); + return -1; + } + + rec = _ptm_lib_encode_header(csv, NULL, 0, PTMLIB_MSG_VERSION, type, + cmd_id, hdl->client_name); + + if (!rec) { + ERRLOG("%s: Could not allocate record \n", __FUNCTION__); + csv_clean(csv); + csv_free(csv); + return -1; + } + + p_ctxt = calloc(1, sizeof(*p_ctxt)); + if (!p_ctxt) { + ERRLOG("%s: Could not allocate context \n", __FUNCTION__); + csv_clean(csv); + csv_free(csv); + return -1; + } + + p_ctxt->csv = csv; + p_ctxt->cmd_id = cmd_id; + p_ctxt->type = type; + + *(ptm_lib_msg_ctxt_t **)out_ctxt = p_ctxt; + + /* caller supplied a context to initialize with? */ + if (p_in_ctxt) { + /* insert the hdr rec */ + rec = csv_record_iter(p_in_ctxt->csv); + csv_clone_record(p_in_ctxt->csv, rec, &d_rec); + csv_insert_record(csv, d_rec); + /* insert the data rec */ + rec = csv_record_iter_next(rec); + csv_clone_record(p_in_ctxt->csv, rec, &d_rec); + csv_insert_record(csv, d_rec); + } + return 0; } -int -ptm_lib_complete_msg(ptm_lib_handle_t *hdl, void *ctxt, - char *buf, int *len) +int ptm_lib_complete_msg(ptm_lib_handle_t *hdl, void *ctxt, char *buf, int *len) { - ptm_lib_msg_ctxt_t *p_ctxt = ctxt; - csv_t *csv; - csv_record_t *rec; - - if (!p_ctxt) { - ERRLOG("%s: no context \n", __FUNCTION__); - return -1; - } - - csv = p_ctxt->csv; - rec = csv_record_iter(csv); - - _ptm_lib_encode_header(csv, rec, - (csvlen(csv) - PTMLIB_MSG_HDR_LEN), - PTMLIB_MSG_VERSION, p_ctxt->type, - p_ctxt->cmd_id, hdl->client_name); - - /* parse csv contents into string */ - if (buf && len) { - if (csv_serialize(csv, buf, *len)) { - ERRLOG("%s: cannot serialize\n", __FUNCTION__); - return -1; - } - *len = csvlen(csv); - } - - csv_clean(csv); - csv_free(csv); - free(p_ctxt); - - return 0; + ptm_lib_msg_ctxt_t *p_ctxt = ctxt; + csv_t *csv; + csv_record_t *rec; + + if (!p_ctxt) { + ERRLOG("%s: no context \n", __FUNCTION__); + return -1; + } + + csv = p_ctxt->csv; + rec = csv_record_iter(csv); + + _ptm_lib_encode_header(csv, rec, (csvlen(csv) - PTMLIB_MSG_HDR_LEN), + PTMLIB_MSG_VERSION, p_ctxt->type, p_ctxt->cmd_id, + hdl->client_name); + + /* parse csv contents into string */ + if (buf && len) { + if (csv_serialize(csv, buf, *len)) { + ERRLOG("%s: cannot serialize\n", __FUNCTION__); + return -1; + } + *len = csvlen(csv); + } + + csv_clean(csv); + csv_free(csv); + free(p_ctxt); + + return 0; } -int -ptm_lib_find_key_in_msg(void *ctxt, const char *key, char *val) +int ptm_lib_find_key_in_msg(void *ctxt, const char *key, char *val) { - ptm_lib_msg_ctxt_t *p_ctxt = ctxt; - csv_t *csv = p_ctxt->csv; - csv_record_t *hrec, *drec; - csv_field_t *hfld, *dfld; - char *hstr, *dstr; - - /** - * skip over ptm hdr if present - * The next hdr is the keys (column name) - * The next hdr is the data - */ - if (csv_num_records(csv) > 2) { - hrec = csv_record_iter(csv); - hrec = csv_record_iter_next(hrec); - } else { - hrec = csv_record_iter(csv); - } - drec = csv_record_iter_next(hrec); - val[0] = '\0'; - for(hstr = csv_field_iter(hrec, &hfld), - dstr = csv_field_iter(drec, &dfld); - (hstr && dstr); - hstr = csv_field_iter_next(&hfld), - dstr = csv_field_iter_next(&dfld)) { - if (!strncmp(hstr, key, csv_field_len(hfld))) { - snprintf(val, csv_field_len(dfld)+1, "%s", dstr); - return 0; - } - } - - return -1; + ptm_lib_msg_ctxt_t *p_ctxt = ctxt; + csv_t *csv = p_ctxt->csv; + csv_record_t *hrec, *drec; + csv_field_t *hfld, *dfld; + char *hstr, *dstr; + + /** + * skip over ptm hdr if present + * The next hdr is the keys (column name) + * The next hdr is the data + */ + if (csv_num_records(csv) > 2) { + hrec = csv_record_iter(csv); + hrec = csv_record_iter_next(hrec); + } else { + hrec = csv_record_iter(csv); + } + drec = csv_record_iter_next(hrec); + val[0] = '\0'; + for (hstr = csv_field_iter(hrec, &hfld), + dstr = csv_field_iter(drec, &dfld); + (hstr && dstr); hstr = csv_field_iter_next(&hfld), + dstr = csv_field_iter_next(&dfld)) { + if (!strncmp(hstr, key, csv_field_len(hfld))) { + snprintf(val, csv_field_len(dfld) + 1, "%s", dstr); + return 0; + } + } + + return -1; } -static int -_ptm_lib_read_ptm_socket(int fd, char *buf, int len) +static int _ptm_lib_read_ptm_socket(int fd, char *buf, int len) { - int retries = 0, rc; - int bytes_read = 0; - - while (bytes_read != len) { - rc = recv(fd, (void *) (buf + bytes_read), (len - bytes_read), - MSG_DONTWAIT); - if (rc <= 0) { - if (errno && (errno != EAGAIN) && (errno != EWOULDBLOCK)) { - ERRLOG("fatal recv error(%s), closing connection, rc %d\n", - strerror(errno), rc); - return (rc); - } else { - if (retries++ < 2) { - usleep(10000); - continue; - } - DLOG("max retries - recv error(%d - %s) bytes read %d (%d)\n", - errno, strerror(errno), bytes_read, len); - return (bytes_read); - } - break; - } else { - bytes_read += rc; - } - } - - return bytes_read; + int retries = 0, rc; + int bytes_read = 0; + + while (bytes_read != len) { + rc = recv(fd, (void *)(buf + bytes_read), (len - bytes_read), + MSG_DONTWAIT); + if (rc <= 0) { + if (errno && (errno != EAGAIN) + && (errno != EWOULDBLOCK)) { + ERRLOG("fatal recv error(%s), closing connection, rc %d\n", + strerror(errno), rc); + return (rc); + } else { + if (retries++ < 2) { + usleep(10000); + continue; + } + DLOG("max retries - recv error(%d - %s) bytes read %d (%d)\n", + errno, strerror(errno), bytes_read, len); + return (bytes_read); + } + break; + } else { + bytes_read += rc; + } + } + + return bytes_read; } -int -ptm_lib_process_msg(ptm_lib_handle_t *hdl, int fd, - char *inbuf, int inlen, void *arg) +int ptm_lib_process_msg(ptm_lib_handle_t *hdl, int fd, char *inbuf, int inlen, + void *arg) { - int rc, len; - char client_name[32]; - int cmd_id, type, ver, msglen; - csv_t *csv; - ptm_lib_msg_ctxt_t *p_ctxt; - - len = _ptm_lib_read_ptm_socket(fd, inbuf, PTMLIB_MSG_HDR_LEN); - if (len <= 0) - return (len); - - csv = csv_init(NULL, inbuf, PTMLIB_MSG_HDR_LEN); - - if (!csv) { - DLOG("Cannot allocate csv for hdr\n"); - return (-1); - } - - rc = _ptm_lib_decode_header(csv, &msglen, &ver, &type, &cmd_id, client_name); - - csv_clean(csv); - csv_free(csv); - - if (rc < 0) { - /* could not decode the CSV - maybe its legacy cmd? - * get the entire cmd from the socket and see if we can process it - */ - if (len == PTMLIB_MSG_HDR_LEN) { - len += _ptm_lib_read_ptm_socket(fd, (inbuf+PTMLIB_MSG_HDR_LEN), - inlen - PTMLIB_MSG_HDR_LEN); - if (len <= 0) - return (len); - } - - inbuf[len] = '\0'; - /* we only support the get-status cmd */ - if (strcmp(inbuf, PTMLIB_CMD_GET_STATUS)) { - DLOG("unsupported legacy cmd %s\n", inbuf); - return (-1); - } - /* internally create a csv-style cmd */ - ptm_lib_init_msg(hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, (void *)&p_ctxt); - if (!p_ctxt) { - DLOG("couldnt allocate context\n"); - return (-1); - } - ptm_lib_append_msg(hdl, p_ctxt, "cmd", PTMLIB_CMD_GET_STATUS); - - } else { - - if (msglen > inlen) { - DLOG("msglen [%d] > inlen [%d]\n", msglen, inlen); - return -1; - } - - /* read the rest of the msg */ - len = _ptm_lib_read_ptm_socket(fd, inbuf, msglen); - if (len <= 0) { - return (len); - } - - inbuf[len] = '\0'; - - csv = csv_init(NULL, NULL, PTMLIB_MSG_SZ); - if (!csv) { - ERRLOG("Cannot allocate csv for msg\n"); - return -1; - } - - csv_decode(csv, inbuf); - p_ctxt = calloc(1, sizeof(*p_ctxt)); - if (!p_ctxt) { - ERRLOG("%s: Could not allocate context \n", __FUNCTION__); - csv_clean(csv); - csv_free(csv); - return -1; - } - - p_ctxt->csv = csv; - p_ctxt->cmd_id = cmd_id; - p_ctxt->type = type; - } - - switch(p_ctxt->type) { - case PTMLIB_MSG_TYPE_NOTIFICATION: - if (hdl->notify_cb) - hdl->notify_cb(arg, p_ctxt); - break; - case PTMLIB_MSG_TYPE_CMD: - if (hdl->cmd_cb) - hdl->cmd_cb(arg, p_ctxt); - break; - case PTMLIB_MSG_TYPE_RESPONSE: - if (hdl->response_cb) - hdl->response_cb(arg, p_ctxt); - break; - default: - return -1; - } - - csv_clean(p_ctxt->csv); - csv_free(p_ctxt->csv); - free(p_ctxt); - - return len; + int rc, len; + char client_name[32]; + int cmd_id, type, ver, msglen; + csv_t *csv; + ptm_lib_msg_ctxt_t *p_ctxt; + + len = _ptm_lib_read_ptm_socket(fd, inbuf, PTMLIB_MSG_HDR_LEN); + if (len <= 0) + return (len); + + csv = csv_init(NULL, inbuf, PTMLIB_MSG_HDR_LEN); + + if (!csv) { + DLOG("Cannot allocate csv for hdr\n"); + return (-1); + } + + rc = _ptm_lib_decode_header(csv, &msglen, &ver, &type, &cmd_id, + client_name); + + csv_clean(csv); + csv_free(csv); + + if (rc < 0) { + /* could not decode the CSV - maybe its legacy cmd? + * get the entire cmd from the socket and see if we can process + * it + */ + if (len == PTMLIB_MSG_HDR_LEN) { + len += _ptm_lib_read_ptm_socket( + fd, (inbuf + PTMLIB_MSG_HDR_LEN), + inlen - PTMLIB_MSG_HDR_LEN); + if (len <= 0) + return (len); + } + + inbuf[len] = '\0'; + /* we only support the get-status cmd */ + if (strcmp(inbuf, PTMLIB_CMD_GET_STATUS)) { + DLOG("unsupported legacy cmd %s\n", inbuf); + return (-1); + } + /* internally create a csv-style cmd */ + ptm_lib_init_msg(hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, + (void *)&p_ctxt); + if (!p_ctxt) { + DLOG("couldnt allocate context\n"); + return (-1); + } + ptm_lib_append_msg(hdl, p_ctxt, "cmd", PTMLIB_CMD_GET_STATUS); + + } else { + + if (msglen > inlen) { + DLOG("msglen [%d] > inlen [%d]\n", msglen, inlen); + return -1; + } + + /* read the rest of the msg */ + len = _ptm_lib_read_ptm_socket(fd, inbuf, msglen); + if (len <= 0) { + return (len); + } + + inbuf[len] = '\0'; + + csv = csv_init(NULL, NULL, PTMLIB_MSG_SZ); + if (!csv) { + ERRLOG("Cannot allocate csv for msg\n"); + return -1; + } + + csv_decode(csv, inbuf); + p_ctxt = calloc(1, sizeof(*p_ctxt)); + if (!p_ctxt) { + ERRLOG("%s: Could not allocate context \n", + __FUNCTION__); + csv_clean(csv); + csv_free(csv); + return -1; + } + + p_ctxt->csv = csv; + p_ctxt->cmd_id = cmd_id; + p_ctxt->type = type; + } + + switch (p_ctxt->type) { + case PTMLIB_MSG_TYPE_NOTIFICATION: + if (hdl->notify_cb) + hdl->notify_cb(arg, p_ctxt); + break; + case PTMLIB_MSG_TYPE_CMD: + if (hdl->cmd_cb) + hdl->cmd_cb(arg, p_ctxt); + break; + case PTMLIB_MSG_TYPE_RESPONSE: + if (hdl->response_cb) + hdl->response_cb(arg, p_ctxt); + break; + default: + return -1; + } + + csv_clean(p_ctxt->csv); + csv_free(p_ctxt->csv); + free(p_ctxt); + + return len; } -ptm_lib_handle_t * -ptm_lib_register(char *client_name, - ptm_cmd_cb cmd_cb, - ptm_notify_cb notify_cb, - ptm_response_cb response_cb) +ptm_lib_handle_t *ptm_lib_register(char *client_name, ptm_cmd_cb cmd_cb, + ptm_notify_cb notify_cb, + ptm_response_cb response_cb) { - ptm_lib_handle_t *hdl; + ptm_lib_handle_t *hdl; - hdl = calloc(1, sizeof(*hdl)); + hdl = calloc(1, sizeof(*hdl)); - if (hdl) { - strncpy(hdl->client_name, client_name, PTMLIB_MAXNAMELEN - 1); - hdl->cmd_cb = cmd_cb; - hdl->notify_cb = notify_cb; - hdl->response_cb = response_cb; - } + if (hdl) { + strncpy(hdl->client_name, client_name, PTMLIB_MAXNAMELEN - 1); + hdl->cmd_cb = cmd_cb; + hdl->notify_cb = notify_cb; + hdl->response_cb = response_cb; + } - return hdl; + return hdl; } -void -ptm_lib_deregister(ptm_lib_handle_t *hdl) +void ptm_lib_deregister(ptm_lib_handle_t *hdl) { - if (hdl) { - memset(hdl, 0x00, sizeof(*hdl)); - free(hdl); - } + if (hdl) { + memset(hdl, 0x00, sizeof(*hdl)); + free(hdl); + } } diff --git a/lib/ptm_lib.h b/lib/ptm_lib.h index 747ce349a..bc8fe4ac5 100644 --- a/lib/ptm_lib.h +++ b/lib/ptm_lib.h @@ -31,32 +31,33 @@ #define PTMLIB_CMD_STOP_BFD_SESS "stop-bfd-sess" typedef enum { - PTMLIB_MSG_TYPE_NOTIFICATION = 1, - PTMLIB_MSG_TYPE_CMD, - PTMLIB_MSG_TYPE_RESPONSE, + PTMLIB_MSG_TYPE_NOTIFICATION = 1, + PTMLIB_MSG_TYPE_CMD, + PTMLIB_MSG_TYPE_RESPONSE, } ptmlib_msg_type; typedef enum { - MODULE_BFD = 0, - MODULE_LLDP, - MODULE_MAX, + MODULE_BFD = 0, + MODULE_LLDP, + MODULE_MAX, } ptmlib_mod_type; -typedef int (*ptm_cmd_cb) (void *data, void *arg); -typedef int (*ptm_notify_cb) (void *data, void *arg); -typedef int (*ptm_response_cb) (void *data, void *arg); -typedef int (*ptm_log_cb) (void *data, void *arg,...); +typedef int (*ptm_cmd_cb)(void *data, void *arg); +typedef int (*ptm_notify_cb)(void *data, void *arg); +typedef int (*ptm_response_cb)(void *data, void *arg); +typedef int (*ptm_log_cb)(void *data, void *arg, ...); typedef struct ptm_lib_handle_s { - char client_name[PTMLIB_MAXNAMELEN]; - ptm_cmd_cb cmd_cb; - ptm_notify_cb notify_cb; - ptm_response_cb response_cb; + char client_name[PTMLIB_MAXNAMELEN]; + ptm_cmd_cb cmd_cb; + ptm_notify_cb notify_cb; + ptm_response_cb response_cb; } ptm_lib_handle_t; /* Prototypes */ int ptm_lib_process_msg(ptm_lib_handle_t *, int, char *, int, void *); -ptm_lib_handle_t *ptm_lib_register(char *, ptm_cmd_cb, ptm_notify_cb, ptm_response_cb); +ptm_lib_handle_t *ptm_lib_register(char *, ptm_cmd_cb, ptm_notify_cb, + ptm_response_cb); void ptm_lib_deregister(ptm_lib_handle_t *); int ptm_lib_find_key_in_msg(void *, const char *, char *); int ptm_lib_init_msg(ptm_lib_handle_t *, int, int, void *, void **); diff --git a/lib/qobj.c b/lib/qobj.c index 8fa816397..5f450ca0d 100644 --- a/lib/qobj.c +++ b/lib/qobj.c @@ -29,82 +29,82 @@ static pthread_rwlock_t nodes_lock; static struct hash *nodes = NULL; -static unsigned int qobj_key (void *data) +static unsigned int qobj_key(void *data) { - struct qobj_node *node = data; - return (unsigned int)node->nid; + struct qobj_node *node = data; + return (unsigned int)node->nid; } -static int qobj_cmp (const void *a, const void *b) +static int qobj_cmp(const void *a, const void *b) { - const struct qobj_node *na = a, *nb = b; - return na->nid == nb->nid; + const struct qobj_node *na = a, *nb = b; + return na->nid == nb->nid; } void qobj_reg(struct qobj_node *node, struct qobj_nodetype *type) { - node->type = type; - pthread_rwlock_wrlock (&nodes_lock); - do - { - node->nid = (uint64_t)random(); - node->nid ^= (uint64_t)random() << 32; - } - while (!node->nid || hash_get (nodes, node, hash_alloc_intern) != node); - pthread_rwlock_unlock (&nodes_lock); + node->type = type; + pthread_rwlock_wrlock(&nodes_lock); + do { + node->nid = (uint64_t)random(); + node->nid ^= (uint64_t)random() << 32; + } while (!node->nid + || hash_get(nodes, node, hash_alloc_intern) != node); + pthread_rwlock_unlock(&nodes_lock); } void qobj_unreg(struct qobj_node *node) { - pthread_rwlock_wrlock (&nodes_lock); - hash_release (nodes, node); - pthread_rwlock_unlock (&nodes_lock); + pthread_rwlock_wrlock(&nodes_lock); + hash_release(nodes, node); + pthread_rwlock_unlock(&nodes_lock); } struct qobj_node *qobj_get(uint64_t id) { - struct qobj_node dummy = { .nid = id }, *rv; - pthread_rwlock_rdlock (&nodes_lock); - rv = hash_lookup (nodes, &dummy); - pthread_rwlock_unlock (&nodes_lock); - return rv; + struct qobj_node dummy = {.nid = id}, *rv; + pthread_rwlock_rdlock(&nodes_lock); + rv = hash_lookup(nodes, &dummy); + pthread_rwlock_unlock(&nodes_lock); + return rv; } void *qobj_get_typed(uint64_t id, struct qobj_nodetype *type) { - struct qobj_node dummy = { .nid = id }; - struct qobj_node *node; - void *rv; + struct qobj_node dummy = {.nid = id}; + struct qobj_node *node; + void *rv; - pthread_rwlock_rdlock (&nodes_lock); - node = hash_lookup (nodes, &dummy); + pthread_rwlock_rdlock(&nodes_lock); + node = hash_lookup(nodes, &dummy); - /* note: we explicitly hold the lock until after we have checked the type. - * if the caller holds a lock that for example prevents the deletion of - * route-maps, we can still race against a delete of something that isn't - * a route-map. */ - if (!node || node->type != type) - rv = NULL; - else - rv = (char *)node - node->type->node_member_offset; + /* note: we explicitly hold the lock until after we have checked the + * type. + * if the caller holds a lock that for example prevents the deletion of + * route-maps, we can still race against a delete of something that + * isn't + * a route-map. */ + if (!node || node->type != type) + rv = NULL; + else + rv = (char *)node - node->type->node_member_offset; - pthread_rwlock_unlock (&nodes_lock); - return rv; + pthread_rwlock_unlock(&nodes_lock); + return rv; } -void qobj_init (void) +void qobj_init(void) { - if (!nodes) - { - pthread_rwlock_init (&nodes_lock, NULL); - nodes = hash_create (qobj_key, qobj_cmp, NULL); - } + if (!nodes) { + pthread_rwlock_init(&nodes_lock, NULL); + nodes = hash_create(qobj_key, qobj_cmp, NULL); + } } -void qobj_finish (void) +void qobj_finish(void) { - hash_clean (nodes, NULL); - hash_free (nodes); - nodes = NULL; - pthread_rwlock_destroy (&nodes_lock); + hash_clean(nodes, NULL); + hash_free(nodes); + nodes = NULL; + pthread_rwlock_destroy(&nodes_lock); } diff --git a/lib/qobj.h b/lib/qobj.h index c24bed4f6..b701eeec5 100644 --- a/lib/qobj.h +++ b/lib/qobj.h @@ -28,10 +28,10 @@ * this is intentional to prevent the struct from growing beyond the allocated * space. */ -#define RESERVED_SPACE_STRUCT(name, fieldname, size) \ - struct { \ - struct name fieldname; \ - char padding ## fieldname[size - sizeof(struct name)]; \ +#define RESERVED_SPACE_STRUCT(name, fieldname, size) \ + struct { \ + struct name fieldname; \ + char padding##fieldname[size - sizeof(struct name)]; \ }; /* don't need struct definitions for these here. code actually using @@ -47,12 +47,16 @@ */ #ifndef HAVE_QOBJ_NODETYPE_CLI #define HAVE_QOBJ_NODETYPE_CLI -1 -struct qobj_nodetype_cli { int dummy; }; +struct qobj_nodetype_cli { + int dummy; +}; #endif #ifndef HAVE_QOBJ_NODETYPE_CAPNP #define HAVE_QOBJ_NODETYPE_CAPNP -1 -struct qobj_nodetype_capnp { int dummy; }; +struct qobj_nodetype_capnp { + int dummy; +}; #endif /* each different kind of object will have a global variable of this type, @@ -71,15 +75,12 @@ struct qobj_node { struct qobj_nodetype *type; }; -#define QOBJ_FIELDS \ - struct qobj_node qobj_node; +#define QOBJ_FIELDS struct qobj_node qobj_node; /* call these at the end of any _create function (QOBJ_REG) * and beginning of any _destroy function (QOBJ_UNREG) */ -#define QOBJ_REG(n, structname) \ - qobj_reg(&n->qobj_node, &qobj_t_ ## structname) -#define QOBJ_UNREG(n) \ - qobj_unreg(&n->qobj_node) +#define QOBJ_REG(n, structname) qobj_reg(&n->qobj_node, &qobj_t_##structname) +#define QOBJ_UNREG(n) qobj_unreg(&n->qobj_node) /* internals - should not be directly used without a good reason * @@ -99,29 +100,29 @@ struct qobj_node *qobj_get(uint64_t id); void *qobj_get_typed(uint64_t id, struct qobj_nodetype *type); /* type declarations */ -#define DECLARE_QOBJ_TYPE(structname) \ - extern struct qobj_nodetype qobj_t_ ## structname; -#define DEFINE_QOBJ_TYPE(structname) \ - struct qobj_nodetype qobj_t_ ## structname = { \ - .node_member_offset = \ - (ptrdiff_t)offsetof(struct structname, qobj_node) \ - }; -#define DEFINE_QOBJ_TYPE_INIT(structname, ...) \ - struct qobj_nodetype qobj_t_ ## structname = { \ - .node_member_offset = \ - (ptrdiff_t)offsetof(struct structname, qobj_node), \ - __VA_ARGS__ \ - }; +#define DECLARE_QOBJ_TYPE(structname) \ + extern struct qobj_nodetype qobj_t_##structname; +#define DEFINE_QOBJ_TYPE(structname) \ + struct qobj_nodetype qobj_t_##structname = { \ + .node_member_offset = \ + (ptrdiff_t)offsetof(struct structname, qobj_node)}; +#define DEFINE_QOBJ_TYPE_INIT(structname, ...) \ + struct qobj_nodetype qobj_t_##structname = { \ + .node_member_offset = \ + (ptrdiff_t)offsetof(struct structname, qobj_node), \ + __VA_ARGS__}; /* ID dereference with typecheck. * will return NULL if id not found or wrong type. */ -#define QOBJ_GET_TYPESAFE(id, structname) \ - ((struct structname *)qobj_get_typed((id), &qobj_t_ ## structname)) +#define QOBJ_GET_TYPESAFE(id, structname) \ + ((struct structname *)qobj_get_typed((id), &qobj_t_##structname)) -#define QOBJ_ID(ptr) \ - ((ptr)->qobj_node.nid) -#define QOBJ_ID_0SAFE(ptr) \ - ({ typeof (ptr) _ptr = (ptr); _ptr ? _ptr->qobj_node.nid : 0ULL; }) +#define QOBJ_ID(ptr) ((ptr)->qobj_node.nid) +#define QOBJ_ID_0SAFE(ptr) \ + ({ \ + typeof(ptr) _ptr = (ptr); \ + _ptr ? _ptr->qobj_node.nid : 0ULL; \ + }) void qobj_init(void); void qobj_finish(void); diff --git a/lib/queue.h b/lib/queue.h index 48b363e24..658b602ba 100644 --- a/lib/queue.h +++ b/lib/queue.h @@ -103,9 +103,9 @@ #ifdef QUEUE_MACRO_DEBUG /* Store the last 2 places the queue element or head was altered */ struct qm_trace { - char * lastfile; + char *lastfile; int lastline; - char * prevfile; + char *prevfile; int prevline; }; @@ -113,19 +113,21 @@ struct qm_trace { #define TRASHIT(x) do {(x) = (void *)-1;} while (0) #define QMD_SAVELINK(name, link) void **name = (void *)&(link) -#define QMD_TRACE_HEAD(head) do { \ - (head)->trace.prevline = (head)->trace.lastline; \ - (head)->trace.prevfile = (head)->trace.lastfile; \ - (head)->trace.lastline = __LINE__; \ - (head)->trace.lastfile = __FILE__; \ -} while (0) - -#define QMD_TRACE_ELEM(elem) do { \ - (elem)->trace.prevline = (elem)->trace.lastline; \ - (elem)->trace.prevfile = (elem)->trace.lastfile; \ - (elem)->trace.lastline = __LINE__; \ - (elem)->trace.lastfile = __FILE__; \ -} while (0) +#define QMD_TRACE_HEAD(head) \ + do { \ + (head)->trace.prevline = (head)->trace.lastline; \ + (head)->trace.prevfile = (head)->trace.lastfile; \ + (head)->trace.lastline = __LINE__; \ + (head)->trace.lastfile = __FILE__; \ + } while (0) + +#define QMD_TRACE_ELEM(elem) \ + do { \ + (elem)->trace.prevline = (elem)->trace.lastline; \ + (elem)->trace.prevfile = (elem)->trace.lastfile; \ + (elem)->trace.lastline = __LINE__; \ + (elem)->trace.lastfile = __FILE__; \ + } while (0) #else #define QMD_TRACE_ELEM(elem) @@ -133,23 +135,25 @@ struct qm_trace { #define QMD_SAVELINK(name, link) #define TRACEBUF #define TRASHIT(x) -#endif /* QUEUE_MACRO_DEBUG */ +#endif /* QUEUE_MACRO_DEBUG */ /* * Singly-linked List declarations. */ -#define SLIST_HEAD(name, type) \ -struct name { \ - struct type *slh_first; /* first element */ \ -} +#define SLIST_HEAD(name, type) \ + struct name { \ + struct type *slh_first; /* first element */ \ + } -#define SLIST_HEAD_INITIALIZER(head) \ - { NULL } +#define SLIST_HEAD_INITIALIZER(head) \ + { \ + NULL \ + } -#define SLIST_ENTRY(type) \ -struct { \ - struct type *sle_next; /* next element */ \ -} +#define SLIST_ENTRY(type) \ + struct { \ + struct type *sle_next; /* next element */ \ + } /* * Singly-linked List functions. @@ -158,220 +162,241 @@ struct { \ #define SLIST_FIRST(head) ((head)->slh_first) -#define SLIST_FOREACH(var, head, field) \ - for ((var) = SLIST_FIRST((head)); \ - (var); \ - (var) = SLIST_NEXT((var), field)) +#define SLIST_FOREACH(var, head, field) \ + for ((var) = SLIST_FIRST((head)); (var); \ + (var) = SLIST_NEXT((var), field)) -#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = SLIST_FIRST((head)); \ - (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ - (var) = (tvar)) +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST((head)); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); (var) = (tvar)) -#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ - for ((varp) = &SLIST_FIRST((head)); \ - ((var) = *(varp)) != NULL; \ - (varp) = &SLIST_NEXT((var), field)) +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); ((var) = *(varp)) != NULL; \ + (varp) = &SLIST_NEXT((var), field)) -#define SLIST_INIT(head) do { \ - SLIST_FIRST((head)) = NULL; \ -} while (0) +#define SLIST_INIT(head) \ + do { \ + SLIST_FIRST((head)) = NULL; \ + } while (0) -#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ - SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ - SLIST_NEXT((slistelm), field) = (elm); \ -} while (0) +#define SLIST_INSERT_AFTER(slistelm, elm, field) \ + do { \ + SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ + SLIST_NEXT((slistelm), field) = (elm); \ + } while (0) -#define SLIST_INSERT_HEAD(head, elm, field) do { \ - SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ - SLIST_FIRST((head)) = (elm); \ -} while (0) +#define SLIST_INSERT_HEAD(head, elm, field) \ + do { \ + SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ + SLIST_FIRST((head)) = (elm); \ + } while (0) #define SLIST_NEXT(elm, field) ((elm)->field.sle_next) -#define SLIST_REMOVE(head, elm, type, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.sle_next); \ - if (SLIST_FIRST((head)) == (elm)) { \ - SLIST_REMOVE_HEAD((head), field); \ - } \ - else { \ - struct type *curelm = SLIST_FIRST((head)); \ - while (SLIST_NEXT(curelm, field) != (elm)) \ - curelm = SLIST_NEXT(curelm, field); \ - SLIST_REMOVE_AFTER(curelm, field); \ - } \ - TRASHIT(*oldnext); \ -} while (0) - -#define SLIST_REMOVE_AFTER(elm, field) do { \ - SLIST_NEXT(elm, field) = \ - SLIST_NEXT(SLIST_NEXT(elm, field), field); \ -} while (0) - -#define SLIST_REMOVE_HEAD(head, field) do { \ - SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ -} while (0) - -#define SLIST_SWAP(head1, head2, type) do { \ - struct type *swap_first = SLIST_FIRST(head1); \ - SLIST_FIRST(head1) = SLIST_FIRST(head2); \ - SLIST_FIRST(head2) = swap_first; \ -} while (0) +#define SLIST_REMOVE(head, elm, type, field) \ + do { \ + QMD_SAVELINK(oldnext, (elm)->field.sle_next); \ + if (SLIST_FIRST((head)) == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = SLIST_FIRST((head)); \ + while (SLIST_NEXT(curelm, field) != (elm)) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_REMOVE_AFTER(curelm, field); \ + } \ + TRASHIT(*oldnext); \ + } while (0) + +#define SLIST_REMOVE_AFTER(elm, field) \ + do { \ + SLIST_NEXT(elm, field) = \ + SLIST_NEXT(SLIST_NEXT(elm, field), field); \ + } while (0) + +#define SLIST_REMOVE_HEAD(head, field) \ + do { \ + SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ + } while (0) + +#define SLIST_SWAP(head1, head2, type) \ + do { \ + struct type *swap_first = SLIST_FIRST(head1); \ + SLIST_FIRST(head1) = SLIST_FIRST(head2); \ + SLIST_FIRST(head2) = swap_first; \ + } while (0) /* * Singly-linked Tail queue declarations. */ -#define STAILQ_HEAD(name, type) \ -struct name { \ - struct type *stqh_first;/* first element */ \ - struct type **stqh_last;/* addr of last next element */ \ -} - -#define STAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).stqh_first } - -#define STAILQ_ENTRY(type) \ -struct { \ - struct type *stqe_next; /* next element */ \ -} +#define STAILQ_HEAD(name, type) \ + struct name { \ + struct type *stqh_first; /* first element */ \ + struct type **stqh_last; /* addr of last next element */ \ + } + +#define STAILQ_HEAD_INITIALIZER(head) \ + { \ + NULL, &(head).stqh_first \ + } + +#define STAILQ_ENTRY(type) \ + struct { \ + struct type *stqe_next; /* next element */ \ + } /* * Singly-linked Tail queue functions. */ -#define STAILQ_CONCAT(head1, head2) do { \ - if (!STAILQ_EMPTY((head2))) { \ - *(head1)->stqh_last = (head2)->stqh_first; \ - (head1)->stqh_last = (head2)->stqh_last; \ - STAILQ_INIT((head2)); \ - } \ -} while (0) +#define STAILQ_CONCAT(head1, head2) \ + do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ + } while (0) #define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) #define STAILQ_FIRST(head) ((head)->stqh_first) -#define STAILQ_FOREACH(var, head, field) \ - for((var) = STAILQ_FIRST((head)); \ - (var); \ - (var) = STAILQ_NEXT((var), field)) - - -#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = STAILQ_FIRST((head)); \ - (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define STAILQ_INIT(head) do { \ - STAILQ_FIRST((head)) = NULL; \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ -} while (0) - -#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ - if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - STAILQ_NEXT((tqelm), field) = (elm); \ -} while (0) - -#define STAILQ_INSERT_HEAD(head, elm, field) do { \ - if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - STAILQ_FIRST((head)) = (elm); \ -} while (0) - -#define STAILQ_INSERT_TAIL(head, elm, field) do { \ - STAILQ_NEXT((elm), field) = NULL; \ - *(head)->stqh_last = (elm); \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ -} while (0) - -#define STAILQ_LAST(head, type, field) \ - (STAILQ_EMPTY((head)) ? \ - NULL : \ - ((struct type *)(void *) \ - ((char *)((head)->stqh_last) - __offsetof(struct type, field)))) +#define STAILQ_FOREACH(var, head, field) \ + for ((var) = STAILQ_FIRST((head)); (var); \ + (var) = STAILQ_NEXT((var), field)) + + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST((head)); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); (var) = (tvar)) + +#define STAILQ_INIT(head) \ + do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ + } while (0) + +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) \ + do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) \ + == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((tqelm), field) = (elm); \ + } while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) \ + do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) \ + == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ + } while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) \ + do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + } while (0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) \ + ? NULL \ + : ((struct type *)(void *)((char *)((head)->stqh_last) \ + - __offsetof(struct type, \ + field)))) #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) -#define STAILQ_REMOVE(head, elm, type, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ - if (STAILQ_FIRST((head)) == (elm)) { \ - STAILQ_REMOVE_HEAD((head), field); \ - } \ - else { \ - struct type *curelm = STAILQ_FIRST((head)); \ - while (STAILQ_NEXT(curelm, field) != (elm)) \ - curelm = STAILQ_NEXT(curelm, field); \ - STAILQ_REMOVE_AFTER(head, curelm, field); \ - } \ - TRASHIT(*oldnext); \ -} while (0) - -#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ - if ((STAILQ_NEXT(elm, field) = \ - STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ -} while (0) - -#define STAILQ_REMOVE_HEAD(head, field) do { \ - if ((STAILQ_FIRST((head)) = \ - STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ -} while (0) - -#define STAILQ_SWAP(head1, head2, type) do { \ - struct type *swap_first = STAILQ_FIRST(head1); \ - struct type **swap_last = (head1)->stqh_last; \ - STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ - (head1)->stqh_last = (head2)->stqh_last; \ - STAILQ_FIRST(head2) = swap_first; \ - (head2)->stqh_last = swap_last; \ - if (STAILQ_EMPTY(head1)) \ - (head1)->stqh_last = &STAILQ_FIRST(head1); \ - if (STAILQ_EMPTY(head2)) \ - (head2)->stqh_last = &STAILQ_FIRST(head2); \ -} while (0) +#define STAILQ_REMOVE(head, elm, type, field) \ + do { \ + QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = STAILQ_FIRST((head)); \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + STAILQ_REMOVE_AFTER(head, curelm, field); \ + } \ + TRASHIT(*oldnext); \ + } while (0) + +#define STAILQ_REMOVE_AFTER(head, elm, field) \ + do { \ + if ((STAILQ_NEXT(elm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) \ + == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + } while (0) + +#define STAILQ_REMOVE_HEAD(head, field) \ + do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) \ + == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ + } while (0) + +#define STAILQ_SWAP(head1, head2, type) \ + do { \ + struct type *swap_first = STAILQ_FIRST(head1); \ + struct type **swap_last = (head1)->stqh_last; \ + STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_FIRST(head2) = swap_first; \ + (head2)->stqh_last = swap_last; \ + if (STAILQ_EMPTY(head1)) \ + (head1)->stqh_last = &STAILQ_FIRST(head1); \ + if (STAILQ_EMPTY(head2)) \ + (head2)->stqh_last = &STAILQ_FIRST(head2); \ + } while (0) /* * List declarations. */ -#define LIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define LIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} +#define LIST_HEAD(name, type) \ + struct name { \ + struct type *lh_first; /* first element */ \ + } + +#define LIST_HEAD_INITIALIZER(head) \ + { \ + NULL \ + } + +#define LIST_ENTRY(type) \ + struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ + } /* * List functions. */ #if (defined(_KERNEL) && defined(INVARIANTS)) -#define QMD_LIST_CHECK_HEAD(head, field) do { \ - if (LIST_FIRST((head)) != NULL && \ - LIST_FIRST((head))->field.le_prev != \ - &LIST_FIRST((head))) \ - panic("Bad list head %p first->prev != head", (head)); \ -} while (0) - -#define QMD_LIST_CHECK_NEXT(elm, field) do { \ - if (LIST_NEXT((elm), field) != NULL && \ - LIST_NEXT((elm), field)->field.le_prev != \ - &((elm)->field.le_next)) \ - panic("Bad link elm %p next->prev != elm", (elm)); \ -} while (0) - -#define QMD_LIST_CHECK_PREV(elm, field) do { \ - if (*(elm)->field.le_prev != (elm)) \ - panic("Bad link elm %p prev->next != elm", (elm)); \ -} while (0) +#define QMD_LIST_CHECK_HEAD(head, field) \ + do { \ + if (LIST_FIRST((head)) != NULL \ + && LIST_FIRST((head))->field.le_prev \ + != &LIST_FIRST((head))) \ + panic("Bad list head %p first->prev != head", (head)); \ + } while (0) + +#define QMD_LIST_CHECK_NEXT(elm, field) \ + do { \ + if (LIST_NEXT((elm), field) != NULL \ + && LIST_NEXT((elm), field)->field.le_prev \ + != &((elm)->field.le_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ + } while (0) + +#define QMD_LIST_CHECK_PREV(elm, field) \ + do { \ + if (*(elm)->field.le_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ + } while (0) #else #define QMD_LIST_CHECK_HEAD(head, field) #define QMD_LIST_CHECK_NEXT(elm, field) @@ -382,117 +407,129 @@ struct { \ #define LIST_FIRST(head) ((head)->lh_first) -#define LIST_FOREACH(var, head, field) \ - for ((var) = LIST_FIRST((head)); \ - (var); \ - (var) = LIST_NEXT((var), field)) - -#define LIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = LIST_FIRST((head)); \ - (var) && ((tvar) = LIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define LIST_INIT(head) do { \ - LIST_FIRST((head)) = NULL; \ -} while (0) - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ - QMD_LIST_CHECK_NEXT(listelm, field); \ - if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ - LIST_NEXT((listelm), field)->field.le_prev = \ - &LIST_NEXT((elm), field); \ - LIST_NEXT((listelm), field) = (elm); \ - (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ -} while (0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ - QMD_LIST_CHECK_PREV(listelm, field); \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - LIST_NEXT((elm), field) = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ -} while (0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \ - QMD_LIST_CHECK_HEAD((head), field); \ - if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ - LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ - LIST_FIRST((head)) = (elm); \ - (elm)->field.le_prev = &LIST_FIRST((head)); \ -} while (0) +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST((head)); (var); (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); (var) = (tvar)) + +#define LIST_INIT(head) \ + do { \ + LIST_FIRST((head)) = NULL; \ + } while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) \ + do { \ + QMD_LIST_CHECK_NEXT(listelm, field); \ + if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) \ + != NULL) \ + LIST_NEXT((listelm), field)->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_NEXT((listelm), field) = (elm); \ + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ + } while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) \ + do { \ + QMD_LIST_CHECK_PREV(listelm, field); \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + LIST_NEXT((elm), field) = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ + } while (0) + +#define LIST_INSERT_HEAD(head, elm, field) \ + do { \ + QMD_LIST_CHECK_HEAD((head), field); \ + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ + LIST_FIRST((head))->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_FIRST((head)) = (elm); \ + (elm)->field.le_prev = &LIST_FIRST((head)); \ + } while (0) #define LIST_NEXT(elm, field) ((elm)->field.le_next) -#define LIST_REMOVE(elm, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.le_next); \ - QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ - QMD_LIST_CHECK_NEXT(elm, field); \ - QMD_LIST_CHECK_PREV(elm, field); \ - if (LIST_NEXT((elm), field) != NULL) \ - LIST_NEXT((elm), field)->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = LIST_NEXT((elm), field); \ - TRASHIT(*oldnext); \ - TRASHIT(*oldprev); \ -} while (0) - -#define LIST_SWAP(head1, head2, type, field) do { \ - struct type *swap_tmp = LIST_FIRST((head1)); \ - LIST_FIRST((head1)) = LIST_FIRST((head2)); \ - LIST_FIRST((head2)) = swap_tmp; \ - if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ - swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ - if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ - swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ -} while (0) +#define LIST_REMOVE(elm, field) \ + do { \ + QMD_SAVELINK(oldnext, (elm)->field.le_next); \ + QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ + QMD_LIST_CHECK_NEXT(elm, field); \ + QMD_LIST_CHECK_PREV(elm, field); \ + if (LIST_NEXT((elm), field) != NULL) \ + LIST_NEXT((elm), field)->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = LIST_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ + } while (0) + +#define LIST_SWAP(head1, head2, type, field) \ + do { \ + struct type *swap_tmp = LIST_FIRST((head1)); \ + LIST_FIRST((head1)) = LIST_FIRST((head2)); \ + LIST_FIRST((head2)) = swap_tmp; \ + if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ + if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ + } while (0) /* * Tail queue declarations. */ -#define TAILQ_HEAD(name, type) \ -struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ - TRACEBUF \ -} - -#define TAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first } - -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ - TRACEBUF \ -} +#define TAILQ_HEAD(name, type) \ + struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ + } + +#define TAILQ_HEAD_INITIALIZER(head) \ + { \ + NULL, &(head).tqh_first \ + } + +#define TAILQ_ENTRY(type) \ + struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ + } /* * Tail queue functions. */ #if (defined(_KERNEL) && defined(INVARIANTS)) -#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ - if (!TAILQ_EMPTY(head) && \ - TAILQ_FIRST((head))->field.tqe_prev != \ - &TAILQ_FIRST((head))) \ - panic("Bad tailq head %p first->prev != head", (head)); \ -} while (0) - -#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ - if (*(head)->tqh_last != NULL) \ - panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ -} while (0) - -#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ - if (TAILQ_NEXT((elm), field) != NULL && \ - TAILQ_NEXT((elm), field)->field.tqe_prev != \ - &((elm)->field.tqe_next)) \ - panic("Bad link elm %p next->prev != elm", (elm)); \ -} while (0) - -#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ - if (*(elm)->field.tqe_prev != (elm)) \ - panic("Bad link elm %p prev->next != elm", (elm)); \ -} while (0) +#define QMD_TAILQ_CHECK_HEAD(head, field) \ + do { \ + if (!TAILQ_EMPTY(head) \ + && TAILQ_FIRST((head))->field.tqe_prev \ + != &TAILQ_FIRST((head))) \ + panic("Bad tailq head %p first->prev != head", \ + (head)); \ + } while (0) + +#define QMD_TAILQ_CHECK_TAIL(head, field) \ + do { \ + if (*(head)->tqh_last != NULL) \ + panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ + } while (0) + +#define QMD_TAILQ_CHECK_NEXT(elm, field) \ + do { \ + if (TAILQ_NEXT((elm), field) != NULL \ + && TAILQ_NEXT((elm), field)->field.tqe_prev \ + != &((elm)->field.tqe_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ + } while (0) + +#define QMD_TAILQ_CHECK_PREV(elm, field) \ + do { \ + if (*(elm)->field.tqe_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ + } while (0) #else #define QMD_TAILQ_CHECK_HEAD(head, field) #define QMD_TAILQ_CHECK_TAIL(head, headname) @@ -500,136 +537,143 @@ struct { \ #define QMD_TAILQ_CHECK_PREV(elm, field) #endif /* (_KERNEL && INVARIANTS) */ -#define TAILQ_CONCAT(head1, head2, field) do { \ - if (!TAILQ_EMPTY(head2)) { \ - *(head1)->tqh_last = (head2)->tqh_first; \ - (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ - (head1)->tqh_last = (head2)->tqh_last; \ - TAILQ_INIT((head2)); \ - QMD_TRACE_HEAD(head1); \ - QMD_TRACE_HEAD(head2); \ - } \ -} while (0) +#define TAILQ_CONCAT(head1, head2, field) \ + do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = \ + (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + QMD_TRACE_HEAD(head1); \ + QMD_TRACE_HEAD(head2); \ + } \ + } while (0) #define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) #define TAILQ_FIRST(head) ((head)->tqh_first) -#define TAILQ_FOREACH(var, head, field) \ - for ((var) = TAILQ_FIRST((head)); \ - (var); \ - (var) = TAILQ_NEXT((var), field)) - -#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = TAILQ_FIRST((head)); \ - (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for ((var) = TAILQ_LAST((head), headname); \ - (var); \ - (var) = TAILQ_PREV((var), headname, field)) - -#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ - for ((var) = TAILQ_LAST((head), headname); \ - (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ - (var) = (tvar)) - -#define TAILQ_INIT(head) do { \ - TAILQ_FIRST((head)) = NULL; \ - (head)->tqh_last = &TAILQ_FIRST((head)); \ - QMD_TRACE_HEAD(head); \ -} while (0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - QMD_TAILQ_CHECK_NEXT(listelm, field); \ - if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else { \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_HEAD(head); \ - } \ - TAILQ_NEXT((listelm), field) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ - QMD_TRACE_ELEM(&(elm)->field); \ - QMD_TRACE_ELEM(&listelm->field); \ -} while (0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - QMD_TAILQ_CHECK_PREV(listelm, field); \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - TAILQ_NEXT((elm), field) = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_ELEM(&(elm)->field); \ - QMD_TRACE_ELEM(&listelm->field); \ -} while (0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ - QMD_TAILQ_CHECK_HEAD(head, field); \ - if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ - TAILQ_FIRST((head))->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - TAILQ_FIRST((head)) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ - QMD_TRACE_HEAD(head); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - QMD_TAILQ_CHECK_TAIL(head, field); \ - TAILQ_NEXT((elm), field) = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_HEAD(head); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_LAST(head, headname) \ +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST((head)); (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST((head)); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST((head), headname); (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_INIT(head) \ + do { \ + TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + } while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) \ + do { \ + QMD_TAILQ_CHECK_NEXT(listelm, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) \ + != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + } \ + TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ + } while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) \ + do { \ + QMD_TAILQ_CHECK_PREV(listelm, field); \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ + } while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) \ + do { \ + QMD_TAILQ_CHECK_HEAD(head, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ + TAILQ_FIRST((head))->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ + } while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) \ + do { \ + QMD_TAILQ_CHECK_TAIL(head, field); \ + TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ + } while (0) + +#define TAILQ_LAST(head, headname) \ (*(((struct headname *)((head)->tqh_last))->tqh_last)) #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) -#define TAILQ_PREV(elm, headname, field) \ +#define TAILQ_PREV(elm, headname, field) \ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) -#define TAILQ_REMOVE(head, elm, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ - QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ - QMD_TAILQ_CHECK_NEXT(elm, field); \ - QMD_TAILQ_CHECK_PREV(elm, field); \ - if ((TAILQ_NEXT((elm), field)) != NULL) \ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else { \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - QMD_TRACE_HEAD(head); \ - } \ - *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ - TRASHIT(*oldnext); \ - TRASHIT(*oldprev); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_SWAP(head1, head2, type, field) do { \ - struct type *swap_first = (head1)->tqh_first; \ - struct type **swap_last = (head1)->tqh_last; \ - (head1)->tqh_first = (head2)->tqh_first; \ - (head1)->tqh_last = (head2)->tqh_last; \ - (head2)->tqh_first = swap_first; \ - (head2)->tqh_last = swap_last; \ - if ((swap_first = (head1)->tqh_first) != NULL) \ - swap_first->field.tqe_prev = &(head1)->tqh_first; \ - else \ - (head1)->tqh_last = &(head1)->tqh_first; \ - if ((swap_first = (head2)->tqh_first) != NULL) \ - swap_first->field.tqe_prev = &(head2)->tqh_first; \ - else \ - (head2)->tqh_last = &(head2)->tqh_first; \ -} while (0) +#define TAILQ_REMOVE(head, elm, field) \ + do { \ + QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ + QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ + QMD_TAILQ_CHECK_NEXT(elm, field); \ + QMD_TAILQ_CHECK_PREV(elm, field); \ + if ((TAILQ_NEXT((elm), field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + QMD_TRACE_HEAD(head); \ + } \ + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ + QMD_TRACE_ELEM(&(elm)->field); \ + } while (0) + +#define TAILQ_SWAP(head1, head2, type, field) \ + do { \ + struct type *swap_first = (head1)->tqh_first; \ + struct type **swap_last = (head1)->tqh_last; \ + (head1)->tqh_first = (head2)->tqh_first; \ + (head1)->tqh_last = (head2)->tqh_last; \ + (head2)->tqh_first = swap_first; \ + (head2)->tqh_last = swap_last; \ + if ((swap_first = (head1)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head1)->tqh_first; \ + else \ + (head1)->tqh_last = &(head1)->tqh_first; \ + if ((swap_first = (head2)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head2)->tqh_first; \ + else \ + (head2)->tqh_last = &(head2)->tqh_first; \ + } while (0) #endif /* !_SYS_QUEUE_H_ */ diff --git a/lib/routemap.c b/lib/routemap.c index 9ceaa1115..3d1add25d 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -31,13 +31,13 @@ #include "hash.h" #include "libfrr.h" -DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP, "Route map") -DEFINE_MTYPE( LIB, ROUTE_MAP_NAME, "Route map name") -DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP_INDEX, "Route map index") -DEFINE_MTYPE( LIB, ROUTE_MAP_RULE, "Route map rule") +DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP, "Route map") +DEFINE_MTYPE(LIB, ROUTE_MAP_NAME, "Route map name") +DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP_INDEX, "Route map index") +DEFINE_MTYPE(LIB, ROUTE_MAP_RULE, "Route map rule") DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP_RULE_STR, "Route map rule str") -DEFINE_MTYPE( LIB, ROUTE_MAP_COMPILED, "Route map compiled") -DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP_DEP, "Route map dependency") +DEFINE_MTYPE(LIB, ROUTE_MAP_COMPILED, "Route map compiled") +DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP_DEP, "Route map dependency") DEFINE_QOBJ_TYPE(route_map_index) DEFINE_QOBJ_TYPE(route_map) @@ -48,1477 +48,1293 @@ static vector route_match_vec; /* Vector for route set rules. */ static vector route_set_vec; -struct route_map_match_set_hooks -{ - /* match interface */ - int (*match_interface) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* no match interface */ - int (*no_match_interface) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* match ip address */ - int (*match_ip_address) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* no match ip address */ - int (*no_match_ip_address) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* match ip address prefix list */ - int (*match_ip_address_prefix_list) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* no match ip address prefix list */ - int (*no_match_ip_address_prefix_list) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* match ip next hop */ - int (*match_ip_next_hop) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* no match ip next hop */ - int (*no_match_ip_next_hop) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* match ip next hop prefix list */ - int (*match_ip_next_hop_prefix_list) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* no match ip next hop prefix list */ - int (*no_match_ip_next_hop_prefix_list) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* match ipv6 address */ - int (*match_ipv6_address) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* no match ipv6 address */ - int (*no_match_ipv6_address) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - - /* match ipv6 address prefix list */ - int (*match_ipv6_address_prefix_list) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* no match ipv6 address prefix list */ - int (*no_match_ipv6_address_prefix_list) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* match metric */ - int (*match_metric) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* no match metric */ - int (*no_match_metric) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* match tag */ - int (*match_tag) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* no match tag */ - int (*no_match_tag) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - - /* set ip nexthop */ - int (*set_ip_nexthop) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg); - - /* no set ip nexthop */ - int (*no_set_ip_nexthop) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg); - - /* set ipv6 nexthop local */ - int (*set_ipv6_nexthop_local) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg); - - /* no set ipv6 nexthop local */ - int (*no_set_ipv6_nexthop_local) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg); - - /* set metric */ - int (*set_metric) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg); - - /* no set metric */ - int (*no_set_metric) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg); - - /* set tag */ - int (*set_tag) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg); - - /* no set tag */ - int (*no_set_tag) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg); - +struct route_map_match_set_hooks { + /* match interface */ + int (*match_interface)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* no match interface */ + int (*no_match_interface)(struct vty *vty, + struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* match ip address */ + int (*match_ip_address)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* no match ip address */ + int (*no_match_ip_address)(struct vty *vty, + struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* match ip address prefix list */ + int (*match_ip_address_prefix_list)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg, + route_map_event_t type); + + /* no match ip address prefix list */ + int (*no_match_ip_address_prefix_list)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg, + route_map_event_t type); + + /* match ip next hop */ + int (*match_ip_next_hop)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* no match ip next hop */ + int (*no_match_ip_next_hop)(struct vty *vty, + struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* match ip next hop prefix list */ + int (*match_ip_next_hop_prefix_list)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg, + route_map_event_t type); + + /* no match ip next hop prefix list */ + int (*no_match_ip_next_hop_prefix_list)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg, + route_map_event_t type); + + /* match ipv6 address */ + int (*match_ipv6_address)(struct vty *vty, + struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* no match ipv6 address */ + int (*no_match_ipv6_address)(struct vty *vty, + struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + + /* match ipv6 address prefix list */ + int (*match_ipv6_address_prefix_list)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg, + route_map_event_t type); + + /* no match ipv6 address prefix list */ + int (*no_match_ipv6_address_prefix_list)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg, + route_map_event_t type); + + /* match metric */ + int (*match_metric)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* no match metric */ + int (*no_match_metric)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* match tag */ + int (*match_tag)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* no match tag */ + int (*no_match_tag)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + + /* set ip nexthop */ + int (*set_ip_nexthop)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg); + + /* no set ip nexthop */ + int (*no_set_ip_nexthop)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg); + + /* set ipv6 nexthop local */ + int (*set_ipv6_nexthop_local)(struct vty *vty, + struct route_map_index *index, + const char *command, const char *arg); + + /* no set ipv6 nexthop local */ + int (*no_set_ipv6_nexthop_local)(struct vty *vty, + struct route_map_index *index, + const char *command, const char *arg); + + /* set metric */ + int (*set_metric)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg); + + /* no set metric */ + int (*no_set_metric)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg); + + /* set tag */ + int (*set_tag)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg); + + /* no set tag */ + int (*no_set_tag)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg); }; struct route_map_match_set_hooks rmap_match_set_hook; /* match interface */ -void -route_map_match_interface_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_match_interface_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.match_interface = func; + rmap_match_set_hook.match_interface = func; } /* no match interface */ -void -route_map_no_match_interface_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_no_match_interface_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.no_match_interface = func; + rmap_match_set_hook.no_match_interface = func; } /* match ip address */ -void -route_map_match_ip_address_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_match_ip_address_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.match_ip_address = func; + rmap_match_set_hook.match_ip_address = func; } /* no match ip address */ -void -route_map_no_match_ip_address_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_no_match_ip_address_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.no_match_ip_address = func; + rmap_match_set_hook.no_match_ip_address = func; } /* match ip address prefix list */ -void -route_map_match_ip_address_prefix_list_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_match_ip_address_prefix_list_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.match_ip_address_prefix_list = func; + rmap_match_set_hook.match_ip_address_prefix_list = func; } /* no match ip address prefix list */ -void -route_map_no_match_ip_address_prefix_list_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_no_match_ip_address_prefix_list_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.no_match_ip_address_prefix_list = func; + rmap_match_set_hook.no_match_ip_address_prefix_list = func; } /* match ip next hop */ -void -route_map_match_ip_next_hop_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_match_ip_next_hop_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.match_ip_next_hop = func; + rmap_match_set_hook.match_ip_next_hop = func; } /* no match ip next hop */ -void -route_map_no_match_ip_next_hop_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_no_match_ip_next_hop_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.no_match_ip_next_hop = func; + rmap_match_set_hook.no_match_ip_next_hop = func; } /* match ip next hop prefix list */ -void -route_map_match_ip_next_hop_prefix_list_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_match_ip_next_hop_prefix_list_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.match_ip_next_hop_prefix_list = func; + rmap_match_set_hook.match_ip_next_hop_prefix_list = func; } /* no match ip next hop prefix list */ -void -route_map_no_match_ip_next_hop_prefix_list_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_no_match_ip_next_hop_prefix_list_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.no_match_ip_next_hop_prefix_list = func; + rmap_match_set_hook.no_match_ip_next_hop_prefix_list = func; } /* match ipv6 address */ -void -route_map_match_ipv6_address_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_match_ipv6_address_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.match_ipv6_address = func; + rmap_match_set_hook.match_ipv6_address = func; } /* no match ipv6 address */ -void -route_map_no_match_ipv6_address_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_no_match_ipv6_address_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.no_match_ipv6_address = func; + rmap_match_set_hook.no_match_ipv6_address = func; } /* match ipv6 address prefix list */ -void -route_map_match_ipv6_address_prefix_list_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_match_ipv6_address_prefix_list_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.match_ipv6_address_prefix_list = func; + rmap_match_set_hook.match_ipv6_address_prefix_list = func; } /* no match ipv6 address prefix list */ -void -route_map_no_match_ipv6_address_prefix_list_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_no_match_ipv6_address_prefix_list_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.no_match_ipv6_address_prefix_list = func; + rmap_match_set_hook.no_match_ipv6_address_prefix_list = func; } /* match metric */ -void -route_map_match_metric_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_match_metric_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.match_metric = func; + rmap_match_set_hook.match_metric = func; } /* no match metric */ -void -route_map_no_match_metric_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_no_match_metric_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.no_match_metric = func; + rmap_match_set_hook.no_match_metric = func; } /* match tag */ -void -route_map_match_tag_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_match_tag_hook(int (*func)(struct vty *vty, + struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type)) { - rmap_match_set_hook.match_tag = func; + rmap_match_set_hook.match_tag = func; } /* no match tag */ -void -route_map_no_match_tag_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)) +void route_map_no_match_tag_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)) { - rmap_match_set_hook.no_match_tag = func; + rmap_match_set_hook.no_match_tag = func; } /* set ip nexthop */ -void -route_map_set_ip_nexthop_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)) +void route_map_set_ip_nexthop_hook(int (*func)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg)) { - rmap_match_set_hook.set_ip_nexthop = func; + rmap_match_set_hook.set_ip_nexthop = func; } /* no set ip nexthop */ -void -route_map_no_set_ip_nexthop_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)) +void route_map_no_set_ip_nexthop_hook(int (*func)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg)) { - rmap_match_set_hook.no_set_ip_nexthop = func; + rmap_match_set_hook.no_set_ip_nexthop = func; } /* set ipv6 nexthop local */ -void -route_map_set_ipv6_nexthop_local_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)) +void route_map_set_ipv6_nexthop_local_hook( + int (*func)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg)) { - rmap_match_set_hook.set_ipv6_nexthop_local = func; + rmap_match_set_hook.set_ipv6_nexthop_local = func; } /* no set ipv6 nexthop local */ -void -route_map_no_set_ipv6_nexthop_local_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)) +void route_map_no_set_ipv6_nexthop_local_hook( + int (*func)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg)) { - rmap_match_set_hook.no_set_ipv6_nexthop_local = func; + rmap_match_set_hook.no_set_ipv6_nexthop_local = func; } /* set metric */ -void -route_map_set_metric_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)) +void route_map_set_metric_hook(int (*func)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg)) { - rmap_match_set_hook.set_metric = func; + rmap_match_set_hook.set_metric = func; } /* no set metric */ -void -route_map_no_set_metric_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)) +void route_map_no_set_metric_hook(int (*func)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg)) { - rmap_match_set_hook.no_set_metric = func; + rmap_match_set_hook.no_set_metric = func; } /* set tag */ -void -route_map_set_tag_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)) +void route_map_set_tag_hook(int (*func)(struct vty *vty, + struct route_map_index *index, + const char *command, const char *arg)) { - rmap_match_set_hook.set_tag = func; + rmap_match_set_hook.set_tag = func; } /* no set tag */ -void -route_map_no_set_tag_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)) -{ - rmap_match_set_hook.no_set_tag = func; -} - -int -generic_match_add (struct vty *vty, struct route_map_index *index, - const char *command, const char *arg, - route_map_event_t type) -{ - int ret; - - ret = route_map_add_match (index, command, arg); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% [%s] Can't find rule.\n", frr_protonameinst); - return CMD_WARNING_CONFIG_FAILED; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% [%s] Argument form is unsupported or malformed.\n", - frr_protonameinst); - return CMD_WARNING_CONFIG_FAILED; - } - } - - if (type != RMAP_EVENT_MATCH_ADDED) - { - route_map_upd8_dependency (type, arg, index->map->name); - } - return CMD_SUCCESS; -} - -int -generic_match_delete (struct vty *vty, struct route_map_index *index, - const char *command, const char *arg, - route_map_event_t type) -{ - int ret; - char *dep_name = NULL; - const char *tmpstr; - char *rmap_name = NULL; - - if (type != RMAP_EVENT_MATCH_DELETED) - { - /* ignore the mundane, the types without any dependency */ - if (arg == NULL) - { - if ((tmpstr = route_map_get_match_arg(index, command)) != NULL) - dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr); - } - else - { - dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg); - } - rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name); - } - - ret = route_map_delete_match (index, command, dep_name); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% [%s] Can't find rule.\n", frr_protonameinst); - break; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% [%s] Argument form is unsupported or malformed.\n", - frr_protonameinst); - break; - } - if (dep_name) - XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); - if (rmap_name) - XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); - return CMD_WARNING_CONFIG_FAILED; - } - - if (type != RMAP_EVENT_MATCH_DELETED && dep_name) - route_map_upd8_dependency(type, dep_name, rmap_name); - - if (dep_name) - XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); - if (rmap_name) - XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); - - return CMD_SUCCESS; -} - -int -generic_set_add (struct vty *vty, struct route_map_index *index, - const char *command, const char *arg) -{ - int ret; - - ret = route_map_add_set (index, command, arg); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% [%s] Can't find rule.\n", frr_protonameinst); - return CMD_WARNING_CONFIG_FAILED; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% [%s] Argument form is unsupported or malformed.\n", - frr_protonameinst); - return CMD_WARNING_CONFIG_FAILED; - } - } - return CMD_SUCCESS; -} - -int -generic_set_delete (struct vty *vty, struct route_map_index *index, - const char *command, const char *arg) -{ - int ret; - - ret = route_map_delete_set (index, command, arg); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% [%s] Can't find rule.\n", frr_protonameinst); - return CMD_WARNING_CONFIG_FAILED; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% [%s] Argument form is unsupported or malformed.\n", - frr_protonameinst); - return CMD_WARNING_CONFIG_FAILED; - } - } - return CMD_SUCCESS; +void route_map_no_set_tag_hook(int (*func)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg)) +{ + rmap_match_set_hook.no_set_tag = func; } +int generic_match_add(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type) +{ + int ret; + + ret = route_map_add_match(index, command, arg); + if (ret) { + switch (ret) { + case RMAP_RULE_MISSING: + vty_out(vty, "%% [%s] Can't find rule.\n", + frr_protonameinst); + return CMD_WARNING_CONFIG_FAILED; + case RMAP_COMPILE_ERROR: + vty_out(vty, + "%% [%s] Argument form is unsupported or malformed.\n", + frr_protonameinst); + return CMD_WARNING_CONFIG_FAILED; + } + } -/* Route map rule. This rule has both `match' rule and `set' rule. */ -struct route_map_rule + if (type != RMAP_EVENT_MATCH_ADDED) { + route_map_upd8_dependency(type, arg, index->map->name); + } + return CMD_SUCCESS; +} + +int generic_match_delete(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type) +{ + int ret; + char *dep_name = NULL; + const char *tmpstr; + char *rmap_name = NULL; + + if (type != RMAP_EVENT_MATCH_DELETED) { + /* ignore the mundane, the types without any dependency */ + if (arg == NULL) { + if ((tmpstr = route_map_get_match_arg(index, command)) + != NULL) + dep_name = + XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr); + } else { + dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg); + } + rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name); + } + + ret = route_map_delete_match(index, command, dep_name); + if (ret) { + switch (ret) { + case RMAP_RULE_MISSING: + vty_out(vty, "%% [%s] Can't find rule.\n", + frr_protonameinst); + break; + case RMAP_COMPILE_ERROR: + vty_out(vty, + "%% [%s] Argument form is unsupported or malformed.\n", + frr_protonameinst); + break; + } + if (dep_name) + XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); + if (rmap_name) + XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); + return CMD_WARNING_CONFIG_FAILED; + } + + if (type != RMAP_EVENT_MATCH_DELETED && dep_name) + route_map_upd8_dependency(type, dep_name, rmap_name); + + if (dep_name) + XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); + if (rmap_name) + XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); + + return CMD_SUCCESS; +} + +int generic_set_add(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg) { - /* Rule type. */ - struct route_map_rule_cmd *cmd; + int ret; + + ret = route_map_add_set(index, command, arg); + if (ret) { + switch (ret) { + case RMAP_RULE_MISSING: + vty_out(vty, "%% [%s] Can't find rule.\n", + frr_protonameinst); + return CMD_WARNING_CONFIG_FAILED; + case RMAP_COMPILE_ERROR: + vty_out(vty, + "%% [%s] Argument form is unsupported or malformed.\n", + frr_protonameinst); + return CMD_WARNING_CONFIG_FAILED; + } + } + return CMD_SUCCESS; +} + +int generic_set_delete(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg) +{ + int ret; + + ret = route_map_delete_set(index, command, arg); + if (ret) { + switch (ret) { + case RMAP_RULE_MISSING: + vty_out(vty, "%% [%s] Can't find rule.\n", + frr_protonameinst); + return CMD_WARNING_CONFIG_FAILED; + case RMAP_COMPILE_ERROR: + vty_out(vty, + "%% [%s] Argument form is unsupported or malformed.\n", + frr_protonameinst); + return CMD_WARNING_CONFIG_FAILED; + } + } + return CMD_SUCCESS; +} + + +/* Route map rule. This rule has both `match' rule and `set' rule. */ +struct route_map_rule { + /* Rule type. */ + struct route_map_rule_cmd *cmd; - /* For pretty printing. */ - char *rule_str; + /* For pretty printing. */ + char *rule_str; - /* Pre-compiled match rule. */ - void *value; + /* Pre-compiled match rule. */ + void *value; - /* Linked list. */ - struct route_map_rule *next; - struct route_map_rule *prev; + /* Linked list. */ + struct route_map_rule *next; + struct route_map_rule *prev; }; /* Making route map list. */ -struct route_map_list -{ - struct route_map *head; - struct route_map *tail; +struct route_map_list { + struct route_map *head; + struct route_map *tail; - void (*add_hook) (const char *); - void (*delete_hook) (const char *); - void (*event_hook) (route_map_event_t, const char *); + void (*add_hook)(const char *); + void (*delete_hook)(const char *); + void (*event_hook)(route_map_event_t, const char *); }; /* Master list of route map. */ -static struct route_map_list route_map_master = { NULL, NULL, NULL, NULL, NULL }; +static struct route_map_list route_map_master = {NULL, NULL, NULL, NULL, NULL}; struct hash *route_map_master_hash = NULL; -static unsigned int -route_map_hash_key_make (void *p) +static unsigned int route_map_hash_key_make(void *p) { - const struct route_map *map = p; - return string_hash_make (map->name); + const struct route_map *map = p; + return string_hash_make(map->name); } -static int -route_map_hash_cmp(const void *p1, const void *p2) +static int route_map_hash_cmp(const void *p1, const void *p2) { - const struct route_map *map1 = p1; - const struct route_map *map2 = p2; + const struct route_map *map1 = p1; + const struct route_map *map2 = p2; - if (map1->deleted == map2->deleted) - { - if (map1->name && map2->name) - { - if (!strcmp (map1->name, map2->name)) - { - return 1; - } - } - else if (!map1->name && !map2->name) - { - return 1; - } - } + if (map1->deleted == map2->deleted) { + if (map1->name && map2->name) { + if (!strcmp(map1->name, map2->name)) { + return 1; + } + } else if (!map1->name && !map2->name) { + return 1; + } + } - return 0; + return 0; } -enum route_map_upd8_type - { - ROUTE_MAP_ADD = 1, - ROUTE_MAP_DEL, - }; +enum route_map_upd8_type { + ROUTE_MAP_ADD = 1, + ROUTE_MAP_DEL, +}; /* all possible route-map dependency types */ -enum route_map_dep_type - { - ROUTE_MAP_DEP_RMAP = 1, - ROUTE_MAP_DEP_CLIST, - ROUTE_MAP_DEP_ECLIST, - ROUTE_MAP_DEP_LCLIST, - ROUTE_MAP_DEP_PLIST, - ROUTE_MAP_DEP_ASPATH, - ROUTE_MAP_DEP_FILTER, - ROUTE_MAP_DEP_MAX, - }; - -struct route_map_dep -{ - char *dep_name; - struct hash *dep_rmap_hash; - struct hash *this_hash; /* ptr to the hash structure this is part of */ +enum route_map_dep_type { + ROUTE_MAP_DEP_RMAP = 1, + ROUTE_MAP_DEP_CLIST, + ROUTE_MAP_DEP_ECLIST, + ROUTE_MAP_DEP_LCLIST, + ROUTE_MAP_DEP_PLIST, + ROUTE_MAP_DEP_ASPATH, + ROUTE_MAP_DEP_FILTER, + ROUTE_MAP_DEP_MAX, +}; + +struct route_map_dep { + char *dep_name; + struct hash *dep_rmap_hash; + struct hash *this_hash; /* ptr to the hash structure this is part of */ }; /* Hashes maintaining dependency between various sublists used by route maps */ struct hash *route_map_dep_hash[ROUTE_MAP_DEP_MAX]; -static unsigned int route_map_dep_hash_make_key (void *p); -static int route_map_dep_hash_cmp (const void *p1, const void *p2); -static void route_map_clear_all_references (char *rmap_name); -static void route_map_rule_delete (struct route_map_rule_list *, - struct route_map_rule *); +static unsigned int route_map_dep_hash_make_key(void *p); +static int route_map_dep_hash_cmp(const void *p1, const void *p2); +static void route_map_clear_all_references(char *rmap_name); +static void route_map_rule_delete(struct route_map_rule_list *, + struct route_map_rule *); static int rmap_debug = 0; -static void -route_map_index_delete (struct route_map_index *, int); +static void route_map_index_delete(struct route_map_index *, int); /* New route map allocation. Please note route map's name must be specified. */ -static struct route_map * -route_map_new (const char *name) +static struct route_map *route_map_new(const char *name) { - struct route_map *new; + struct route_map *new; - new = XCALLOC (MTYPE_ROUTE_MAP, sizeof (struct route_map)); - new->name = XSTRDUP (MTYPE_ROUTE_MAP_NAME, name); - QOBJ_REG (new, route_map); - return new; + new = XCALLOC(MTYPE_ROUTE_MAP, sizeof(struct route_map)); + new->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name); + QOBJ_REG(new, route_map); + return new; } /* Add new name to route_map. */ -static struct route_map * -route_map_add (const char *name) -{ - struct route_map *map; - struct route_map_list *list; - - map = route_map_new (name); - list = &route_map_master; - - /* Add map to the hash */ - hash_get(route_map_master_hash, map, hash_alloc_intern); - - /* Add new entry to the head of the list to match how it is added in the - * hash table. This is to ensure that if the same route-map has been - * created more than once and then marked for deletion (which can happen - * if prior deletions haven't completed as BGP hasn't yet done the - * route-map processing), the order of the entities is the same in both - * the list and the hash table. Otherwise, since there is nothing to - * distinguish between the two entries, the wrong entry could get freed. - * TODO: This needs to be re-examined to handle it better - e.g., revive - * a deleted entry if the route-map is created again. - */ - map->prev = NULL; - map->next = list->head; - if (list->head) - list->head->prev = map; - list->head = map; - if (!list->tail) - list->tail = map; - - /* Execute hook. */ - if (route_map_master.add_hook) - { - (*route_map_master.add_hook) (name); - route_map_notify_dependencies(name, RMAP_EVENT_CALL_ADDED); - } - return map; +static struct route_map *route_map_add(const char *name) +{ + struct route_map *map; + struct route_map_list *list; + + map = route_map_new(name); + list = &route_map_master; + + /* Add map to the hash */ + hash_get(route_map_master_hash, map, hash_alloc_intern); + + /* Add new entry to the head of the list to match how it is added in the + * hash table. This is to ensure that if the same route-map has been + * created more than once and then marked for deletion (which can happen + * if prior deletions haven't completed as BGP hasn't yet done the + * route-map processing), the order of the entities is the same in both + * the list and the hash table. Otherwise, since there is nothing to + * distinguish between the two entries, the wrong entry could get freed. + * TODO: This needs to be re-examined to handle it better - e.g., revive + * a deleted entry if the route-map is created again. + */ + map->prev = NULL; + map->next = list->head; + if (list->head) + list->head->prev = map; + list->head = map; + if (!list->tail) + list->tail = map; + + /* Execute hook. */ + if (route_map_master.add_hook) { + (*route_map_master.add_hook)(name); + route_map_notify_dependencies(name, RMAP_EVENT_CALL_ADDED); + } + return map; } /* this is supposed to be called post processing by * the delete hook function. Don't invoke delete_hook * again in this routine. */ -static void -route_map_free_map (struct route_map *map) +static void route_map_free_map(struct route_map *map) { - struct route_map_list *list; - struct route_map_index *index; + struct route_map_list *list; + struct route_map_index *index; - if (map == NULL) - return; + if (map == NULL) + return; - while ((index = map->head) != NULL) - route_map_index_delete (index, 0); + while ((index = map->head) != NULL) + route_map_index_delete(index, 0); - list = &route_map_master; + list = &route_map_master; - QOBJ_UNREG (map); + QOBJ_UNREG(map); - if (map->next) - map->next->prev = map->prev; - else - list->tail = map->prev; + if (map->next) + map->next->prev = map->prev; + else + list->tail = map->prev; - if (map->prev) - map->prev->next = map->next; - else - list->head = map->next; + if (map->prev) + map->prev->next = map->next; + else + list->head = map->next; - hash_release(route_map_master_hash, map); - XFREE (MTYPE_ROUTE_MAP_NAME, map->name); - XFREE (MTYPE_ROUTE_MAP, map); + hash_release(route_map_master_hash, map); + XFREE(MTYPE_ROUTE_MAP_NAME, map->name); + XFREE(MTYPE_ROUTE_MAP, map); } /* Route map delete from list. */ -static void -route_map_delete (struct route_map *map) +static void route_map_delete(struct route_map *map) { - struct route_map_index *index; - char *name; + struct route_map_index *index; + char *name; - while ((index = map->head) != NULL) - route_map_index_delete (index, 0); + while ((index = map->head) != NULL) + route_map_index_delete(index, 0); - name = map->name; - map->head = NULL; + name = map->name; + map->head = NULL; - /* Clear all dependencies */ - route_map_clear_all_references(name); - map->deleted = 1; - /* Execute deletion hook. */ - if (route_map_master.delete_hook) - { - (*route_map_master.delete_hook) (name); - route_map_notify_dependencies(name, RMAP_EVENT_CALL_DELETED); - } + /* Clear all dependencies */ + route_map_clear_all_references(name); + map->deleted = 1; + /* Execute deletion hook. */ + if (route_map_master.delete_hook) { + (*route_map_master.delete_hook)(name); + route_map_notify_dependencies(name, RMAP_EVENT_CALL_DELETED); + } - if (!map->to_be_processed) - { - route_map_free_map (map); - } + if (!map->to_be_processed) { + route_map_free_map(map); + } } /* Lookup route map by route map name string. */ -struct route_map * -route_map_lookup_by_name (const char *name) +struct route_map *route_map_lookup_by_name(const char *name) { - struct route_map *map; - struct route_map tmp_map; + struct route_map *map; + struct route_map tmp_map; - if (!name) - return NULL; + if (!name) + return NULL; - // map.deleted is 0 via memset - memset(&tmp_map, 0, sizeof(struct route_map)); - tmp_map.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name); - map = hash_lookup(route_map_master_hash, &tmp_map); - XFREE(MTYPE_ROUTE_MAP_NAME, tmp_map.name); - return map; + // map.deleted is 0 via memset + memset(&tmp_map, 0, sizeof(struct route_map)); + tmp_map.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name); + map = hash_lookup(route_map_master_hash, &tmp_map); + XFREE(MTYPE_ROUTE_MAP_NAME, tmp_map.name); + return map; } -int -route_map_mark_updated (const char *name, int del_later) +int route_map_mark_updated(const char *name, int del_later) { - struct route_map *map; - int ret = -1; - struct route_map tmp_map; + struct route_map *map; + int ret = -1; + struct route_map tmp_map; - if (!name) - return (ret); + if (!name) + return (ret); - map = route_map_lookup_by_name(name); + map = route_map_lookup_by_name(name); - /* If we did not find the routemap with deleted=0 try again - * with deleted=1 - */ - if (!map) - { - memset(&tmp_map, 0, sizeof(struct route_map)); - tmp_map.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name); - tmp_map.deleted = 1; - map = hash_lookup(route_map_master_hash, &tmp_map); - XFREE(MTYPE_ROUTE_MAP_NAME, tmp_map.name); - } + /* If we did not find the routemap with deleted=0 try again + * with deleted=1 + */ + if (!map) { + memset(&tmp_map, 0, sizeof(struct route_map)); + tmp_map.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name); + tmp_map.deleted = 1; + map = hash_lookup(route_map_master_hash, &tmp_map); + XFREE(MTYPE_ROUTE_MAP_NAME, tmp_map.name); + } - if (map) - { - map->to_be_processed = 1; - ret = 0; - } + if (map) { + map->to_be_processed = 1; + ret = 0; + } - return(ret); + return (ret); } -int -route_map_clear_updated (struct route_map *map) +int route_map_clear_updated(struct route_map *map) { - int ret = -1; + int ret = -1; - if (map) - { - map->to_be_processed = 0; - if (map->deleted) - route_map_free_map(map); - } + if (map) { + map->to_be_processed = 0; + if (map->deleted) + route_map_free_map(map); + } - return (ret); + return (ret); } /* Lookup route map. If there isn't route map create one and return it. */ -static struct route_map * -route_map_get (const char *name) +static struct route_map *route_map_get(const char *name) { - struct route_map *map; + struct route_map *map; - map = route_map_lookup_by_name (name); - if (map == NULL) - map = route_map_add (name); + map = route_map_lookup_by_name(name); + if (map == NULL) + map = route_map_add(name); - return map; + return map; } -void -route_map_walk_update_list (int (*route_map_update_fn) (char *name)) +void route_map_walk_update_list(int (*route_map_update_fn)(char *name)) { - struct route_map *node; - struct route_map *nnode = NULL; + struct route_map *node; + struct route_map *nnode = NULL; - for (node = route_map_master.head; node; node = nnode) - { - if (node->to_be_processed) - { - /* DD: Should we add any thread yield code here */ - route_map_update_fn(node->name); - nnode = node->next; - route_map_clear_updated(node); + for (node = route_map_master.head; node; node = nnode) { + if (node->to_be_processed) { + /* DD: Should we add any thread yield code here */ + route_map_update_fn(node->name); + nnode = node->next; + route_map_clear_updated(node); + } else + nnode = node->next; } - else - nnode = node->next; - } } /* Return route map's type string. */ -static const char * -route_map_type_str (enum route_map_type type) -{ - switch (type) - { - case RMAP_PERMIT: - return "permit"; - break; - case RMAP_DENY: - return "deny"; - break; - default: - return ""; - break; - } +static const char *route_map_type_str(enum route_map_type type) +{ + switch (type) { + case RMAP_PERMIT: + return "permit"; + break; + case RMAP_DENY: + return "deny"; + break; + default: + return ""; + break; + } } -static int -route_map_empty (struct route_map *map) +static int route_map_empty(struct route_map *map) { - if (map->head == NULL && map->tail == NULL) - return 1; - else - return 0; + if (map->head == NULL && map->tail == NULL) + return 1; + else + return 0; } /* show route-map */ -static void -vty_show_route_map_entry (struct vty *vty, struct route_map *map) -{ - struct route_map_index *index; - struct route_map_rule *rule; - - vty_out (vty, "%s:\n", frr_protonameinst); - - for (index = map->head; index; index = index->next) - { - vty_out (vty, "route-map %s, %s, sequence %d\n", - map->name, route_map_type_str (index->type), - index->pref); - - /* Description */ - if (index->description) - vty_out (vty, " Description:\n %s\n", - index->description); - - /* Match clauses */ - vty_out (vty, " Match clauses:\n"); - for (rule = index->match_list.head; rule; rule = rule->next) - vty_out (vty, " %s %s\n", - rule->cmd->str, rule->rule_str); - - vty_out (vty, " Set clauses:\n"); - for (rule = index->set_list.head; rule; rule = rule->next) - vty_out (vty, " %s %s\n", - rule->cmd->str, rule->rule_str); - - /* Call clause */ - vty_out (vty, " Call clause:\n"); - if (index->nextrm) - vty_out (vty, " Call %s\n", index->nextrm); - - /* Exit Policy */ - vty_out (vty, " Action:\n"); - if (index->exitpolicy == RMAP_GOTO) - vty_out (vty, " Goto %d\n", index->nextpref); - else if (index->exitpolicy == RMAP_NEXT) - vty_out (vty, " Continue to next entry\n"); - else if (index->exitpolicy == RMAP_EXIT) - vty_out (vty, " Exit routemap\n"); - } -} - -static int -vty_show_route_map (struct vty *vty, const char *name) -{ - struct route_map *map; - - if (name) - { - map = route_map_lookup_by_name (name); - - if (map) - { - vty_show_route_map_entry (vty, map); - return CMD_SUCCESS; - } - else - { - vty_out (vty, "%s: 'route-map %s' not found\n", frr_protonameinst, - name); - return CMD_SUCCESS; - } - } - else - { - for (map = route_map_master.head; map; map = map->next) - if (!map->deleted) - vty_show_route_map_entry (vty, map); - } - return CMD_SUCCESS; +static void vty_show_route_map_entry(struct vty *vty, struct route_map *map) +{ + struct route_map_index *index; + struct route_map_rule *rule; + + vty_out(vty, "%s:\n", frr_protonameinst); + + for (index = map->head; index; index = index->next) { + vty_out(vty, "route-map %s, %s, sequence %d\n", map->name, + route_map_type_str(index->type), index->pref); + + /* Description */ + if (index->description) + vty_out(vty, " Description:\n %s\n", + index->description); + + /* Match clauses */ + vty_out(vty, " Match clauses:\n"); + for (rule = index->match_list.head; rule; rule = rule->next) + vty_out(vty, " %s %s\n", rule->cmd->str, + rule->rule_str); + + vty_out(vty, " Set clauses:\n"); + for (rule = index->set_list.head; rule; rule = rule->next) + vty_out(vty, " %s %s\n", rule->cmd->str, + rule->rule_str); + + /* Call clause */ + vty_out(vty, " Call clause:\n"); + if (index->nextrm) + vty_out(vty, " Call %s\n", index->nextrm); + + /* Exit Policy */ + vty_out(vty, " Action:\n"); + if (index->exitpolicy == RMAP_GOTO) + vty_out(vty, " Goto %d\n", index->nextpref); + else if (index->exitpolicy == RMAP_NEXT) + vty_out(vty, " Continue to next entry\n"); + else if (index->exitpolicy == RMAP_EXIT) + vty_out(vty, " Exit routemap\n"); + } +} + +static int vty_show_route_map(struct vty *vty, const char *name) +{ + struct route_map *map; + + if (name) { + map = route_map_lookup_by_name(name); + + if (map) { + vty_show_route_map_entry(vty, map); + return CMD_SUCCESS; + } else { + vty_out(vty, "%s: 'route-map %s' not found\n", + frr_protonameinst, name); + return CMD_SUCCESS; + } + } else { + for (map = route_map_master.head; map; map = map->next) + if (!map->deleted) + vty_show_route_map_entry(vty, map); + } + return CMD_SUCCESS; } /* New route map allocation. Please note route map's name must be specified. */ -static struct route_map_index * -route_map_index_new (void) +static struct route_map_index *route_map_index_new(void) { - struct route_map_index *new; + struct route_map_index *new; - new = XCALLOC (MTYPE_ROUTE_MAP_INDEX, sizeof (struct route_map_index)); - new->exitpolicy = RMAP_EXIT; /* Default to Cisco-style */ - QOBJ_REG (new, route_map_index); - return new; + new = XCALLOC(MTYPE_ROUTE_MAP_INDEX, sizeof(struct route_map_index)); + new->exitpolicy = RMAP_EXIT; /* Default to Cisco-style */ + QOBJ_REG(new, route_map_index); + return new; } /* Free route map index. */ -static void -route_map_index_delete (struct route_map_index *index, int notify) +static void route_map_index_delete(struct route_map_index *index, int notify) { - struct route_map_rule *rule; + struct route_map_rule *rule; - QOBJ_UNREG (index); + QOBJ_UNREG(index); - /* Free route match. */ - while ((rule = index->match_list.head) != NULL) - route_map_rule_delete (&index->match_list, rule); + /* Free route match. */ + while ((rule = index->match_list.head) != NULL) + route_map_rule_delete(&index->match_list, rule); - /* Free route set. */ - while ((rule = index->set_list.head) != NULL) - route_map_rule_delete (&index->set_list, rule); + /* Free route set. */ + while ((rule = index->set_list.head) != NULL) + route_map_rule_delete(&index->set_list, rule); - /* Remove index from route map list. */ - if (index->next) - index->next->prev = index->prev; - else - index->map->tail = index->prev; + /* Remove index from route map list. */ + if (index->next) + index->next->prev = index->prev; + else + index->map->tail = index->prev; - if (index->prev) - index->prev->next = index->next; - else - index->map->head = index->next; + if (index->prev) + index->prev->next = index->next; + else + index->map->head = index->next; - /* Free 'char *nextrm' if not NULL */ - if (index->nextrm) - XFREE (MTYPE_ROUTE_MAP_NAME, index->nextrm); + /* Free 'char *nextrm' if not NULL */ + if (index->nextrm) + XFREE(MTYPE_ROUTE_MAP_NAME, index->nextrm); - /* Execute event hook. */ - if (route_map_master.event_hook && notify) - { - (*route_map_master.event_hook) (RMAP_EVENT_INDEX_DELETED, - index->map->name); - route_map_notify_dependencies(index->map->name, RMAP_EVENT_CALL_ADDED); - } - XFREE (MTYPE_ROUTE_MAP_INDEX, index); + /* Execute event hook. */ + if (route_map_master.event_hook && notify) { + (*route_map_master.event_hook)(RMAP_EVENT_INDEX_DELETED, + index->map->name); + route_map_notify_dependencies(index->map->name, + RMAP_EVENT_CALL_ADDED); + } + XFREE(MTYPE_ROUTE_MAP_INDEX, index); } /* Lookup index from route map. */ -static struct route_map_index * -route_map_index_lookup (struct route_map *map, enum route_map_type type, - int pref) +static struct route_map_index *route_map_index_lookup(struct route_map *map, + enum route_map_type type, + int pref) { - struct route_map_index *index; + struct route_map_index *index; - for (index = map->head; index; index = index->next) - if ((index->type == type || type == RMAP_ANY) - && index->pref == pref) - return index; - return NULL; + for (index = map->head; index; index = index->next) + if ((index->type == type || type == RMAP_ANY) + && index->pref == pref) + return index; + return NULL; } /* Add new index to route map. */ static struct route_map_index * -route_map_index_add (struct route_map *map, enum route_map_type type, - int pref) -{ - struct route_map_index *index; - struct route_map_index *point; - - /* Allocate new route map inex. */ - index = route_map_index_new (); - index->map = map; - index->type = type; - index->pref = pref; - - /* Compare preference. */ - for (point = map->head; point; point = point->next) - if (point->pref >= pref) - break; - - if (map->head == NULL) - { - map->head = map->tail = index; - } - else if (point == NULL) - { - index->prev = map->tail; - map->tail->next = index; - map->tail = index; - } - else if (point == map->head) - { - index->next = map->head; - map->head->prev = index; - map->head = index; - } - else - { - index->next = point; - index->prev = point->prev; - if (point->prev) - point->prev->next = index; - point->prev = index; - } - - /* Execute event hook. */ - if (route_map_master.event_hook) - { - (*route_map_master.event_hook) (RMAP_EVENT_INDEX_ADDED, - map->name); - route_map_notify_dependencies (map->name, RMAP_EVENT_CALL_ADDED); - } - return index; +route_map_index_add(struct route_map *map, enum route_map_type type, int pref) +{ + struct route_map_index *index; + struct route_map_index *point; + + /* Allocate new route map inex. */ + index = route_map_index_new(); + index->map = map; + index->type = type; + index->pref = pref; + + /* Compare preference. */ + for (point = map->head; point; point = point->next) + if (point->pref >= pref) + break; + + if (map->head == NULL) { + map->head = map->tail = index; + } else if (point == NULL) { + index->prev = map->tail; + map->tail->next = index; + map->tail = index; + } else if (point == map->head) { + index->next = map->head; + map->head->prev = index; + map->head = index; + } else { + index->next = point; + index->prev = point->prev; + if (point->prev) + point->prev->next = index; + point->prev = index; + } + + /* Execute event hook. */ + if (route_map_master.event_hook) { + (*route_map_master.event_hook)(RMAP_EVENT_INDEX_ADDED, + map->name); + route_map_notify_dependencies(map->name, RMAP_EVENT_CALL_ADDED); + } + return index; } /* Get route map index. */ static struct route_map_index * -route_map_index_get (struct route_map *map, enum route_map_type type, - int pref) +route_map_index_get(struct route_map *map, enum route_map_type type, int pref) { - struct route_map_index *index; + struct route_map_index *index; - index = route_map_index_lookup (map, RMAP_ANY, pref); - if (index && index->type != type) - { - /* Delete index from route map. */ - route_map_index_delete (index, 1); - index = NULL; - } - if (index == NULL) - index = route_map_index_add (map, type, pref); - return index; + index = route_map_index_lookup(map, RMAP_ANY, pref); + if (index && index->type != type) { + /* Delete index from route map. */ + route_map_index_delete(index, 1); + index = NULL; + } + if (index == NULL) + index = route_map_index_add(map, type, pref); + return index; } /* New route map rule */ -static struct route_map_rule * -route_map_rule_new (void) +static struct route_map_rule *route_map_rule_new(void) { - struct route_map_rule *new; + struct route_map_rule *new; - new = XCALLOC (MTYPE_ROUTE_MAP_RULE, sizeof (struct route_map_rule)); - return new; + new = XCALLOC(MTYPE_ROUTE_MAP_RULE, sizeof(struct route_map_rule)); + return new; } /* Install rule command to the match list. */ -void -route_map_install_match (struct route_map_rule_cmd *cmd) +void route_map_install_match(struct route_map_rule_cmd *cmd) { - vector_set (route_match_vec, cmd); + vector_set(route_match_vec, cmd); } /* Install rule command to the set list. */ -void -route_map_install_set (struct route_map_rule_cmd *cmd) +void route_map_install_set(struct route_map_rule_cmd *cmd) { - vector_set (route_set_vec, cmd); + vector_set(route_set_vec, cmd); } /* Lookup rule command from match list. */ -static struct route_map_rule_cmd * -route_map_lookup_match (const char *name) +static struct route_map_rule_cmd *route_map_lookup_match(const char *name) { - unsigned int i; - struct route_map_rule_cmd *rule; + unsigned int i; + struct route_map_rule_cmd *rule; - for (i = 0; i < vector_active (route_match_vec); i++) - if ((rule = vector_slot (route_match_vec, i)) != NULL) - if (strcmp (rule->str, name) == 0) - return rule; - return NULL; + for (i = 0; i < vector_active(route_match_vec); i++) + if ((rule = vector_slot(route_match_vec, i)) != NULL) + if (strcmp(rule->str, name) == 0) + return rule; + return NULL; } /* Lookup rule command from set list. */ -static struct route_map_rule_cmd * -route_map_lookup_set (const char *name) +static struct route_map_rule_cmd *route_map_lookup_set(const char *name) { - unsigned int i; - struct route_map_rule_cmd *rule; + unsigned int i; + struct route_map_rule_cmd *rule; - for (i = 0; i < vector_active (route_set_vec); i++) - if ((rule = vector_slot (route_set_vec, i)) != NULL) - if (strcmp (rule->str, name) == 0) - return rule; - return NULL; + for (i = 0; i < vector_active(route_set_vec); i++) + if ((rule = vector_slot(route_set_vec, i)) != NULL) + if (strcmp(rule->str, name) == 0) + return rule; + return NULL; } /* Add match and set rule to rule list. */ -static void -route_map_rule_add (struct route_map_rule_list *list, - struct route_map_rule *rule) +static void route_map_rule_add(struct route_map_rule_list *list, + struct route_map_rule *rule) { - rule->next = NULL; - rule->prev = list->tail; - if (list->tail) - list->tail->next = rule; - else - list->head = rule; - list->tail = rule; + rule->next = NULL; + rule->prev = list->tail; + if (list->tail) + list->tail->next = rule; + else + list->head = rule; + list->tail = rule; } /* Delete rule from rule list. */ -static void -route_map_rule_delete (struct route_map_rule_list *list, - struct route_map_rule *rule) +static void route_map_rule_delete(struct route_map_rule_list *list, + struct route_map_rule *rule) { - if (rule->cmd->func_free) - (*rule->cmd->func_free) (rule->value); + if (rule->cmd->func_free) + (*rule->cmd->func_free)(rule->value); - if (rule->rule_str) - XFREE (MTYPE_ROUTE_MAP_RULE_STR, rule->rule_str); + if (rule->rule_str) + XFREE(MTYPE_ROUTE_MAP_RULE_STR, rule->rule_str); - if (rule->next) - rule->next->prev = rule->prev; - else - list->tail = rule->prev; - if (rule->prev) - rule->prev->next = rule->next; - else - list->head = rule->next; + if (rule->next) + rule->next->prev = rule->prev; + else + list->tail = rule->prev; + if (rule->prev) + rule->prev->next = rule->next; + else + list->head = rule->next; - XFREE (MTYPE_ROUTE_MAP_RULE, rule); + XFREE(MTYPE_ROUTE_MAP_RULE, rule); } /* strcmp wrapper function which don't crush even argument is NULL. */ -static int -rulecmp (const char *dst, const char *src) -{ - if (dst == NULL) - { - if (src == NULL) - return 0; - else - return 1; - } - else - { - if (src == NULL) +static int rulecmp(const char *dst, const char *src) +{ + if (dst == NULL) { + if (src == NULL) + return 0; + else + return 1; + } else { + if (src == NULL) + return 1; + else + return strcmp(dst, src); + } return 1; - else - return strcmp (dst, src); - } - return 1; } /* Use this to return the already specified argument for this match. This is * useful to get the specified argument with a route map match rule when the * rule is being deleted and the argument is not provided. */ -const char * -route_map_get_match_arg(struct route_map_index *index, const char *match_name) +const char *route_map_get_match_arg(struct route_map_index *index, + const char *match_name) { - struct route_map_rule *rule; - struct route_map_rule_cmd *cmd; + struct route_map_rule *rule; + struct route_map_rule_cmd *cmd; - /* First lookup rule for add match statement. */ - cmd = route_map_lookup_match (match_name); - if (cmd == NULL) - return NULL; + /* First lookup rule for add match statement. */ + cmd = route_map_lookup_match(match_name); + if (cmd == NULL) + return NULL; - for (rule = index->match_list.head; rule; rule = rule->next) - if (rule->cmd == cmd && rule->rule_str != NULL) - return (rule->rule_str); + for (rule = index->match_list.head; rule; rule = rule->next) + if (rule->cmd == cmd && rule->rule_str != NULL) + return (rule->rule_str); - return (NULL); + return (NULL); } /* Add match statement to route map. */ -int -route_map_add_match (struct route_map_index *index, const char *match_name, - const char *match_arg) -{ - struct route_map_rule *rule; - struct route_map_rule *next; - struct route_map_rule_cmd *cmd; - void *compile; - int replaced = 0; - - /* First lookup rule for add match statement. */ - cmd = route_map_lookup_match (match_name); - if (cmd == NULL) - return RMAP_RULE_MISSING; - - /* Next call compile function for this match statement. */ - if (cmd->func_compile) - { - compile= (*cmd->func_compile)(match_arg); - if (compile == NULL) - return RMAP_COMPILE_ERROR; - } - else - compile = NULL; - - /* If argument is completely same ignore it. */ - for (rule = index->match_list.head; rule; rule = next) - { - next = rule->next; - if (rule->cmd == cmd) - { - route_map_rule_delete (&index->match_list, rule); - replaced = 1; +int route_map_add_match(struct route_map_index *index, const char *match_name, + const char *match_arg) +{ + struct route_map_rule *rule; + struct route_map_rule *next; + struct route_map_rule_cmd *cmd; + void *compile; + int replaced = 0; + + /* First lookup rule for add match statement. */ + cmd = route_map_lookup_match(match_name); + if (cmd == NULL) + return RMAP_RULE_MISSING; + + /* Next call compile function for this match statement. */ + if (cmd->func_compile) { + compile = (*cmd->func_compile)(match_arg); + if (compile == NULL) + return RMAP_COMPILE_ERROR; + } else + compile = NULL; + + /* If argument is completely same ignore it. */ + for (rule = index->match_list.head; rule; rule = next) { + next = rule->next; + if (rule->cmd == cmd) { + route_map_rule_delete(&index->match_list, rule); + replaced = 1; + } } - } - /* Add new route map match rule. */ - rule = route_map_rule_new (); - rule->cmd = cmd; - rule->value = compile; - if (match_arg) - rule->rule_str = XSTRDUP (MTYPE_ROUTE_MAP_RULE_STR, match_arg); - else - rule->rule_str = NULL; + /* Add new route map match rule. */ + rule = route_map_rule_new(); + rule->cmd = cmd; + rule->value = compile; + if (match_arg) + rule->rule_str = XSTRDUP(MTYPE_ROUTE_MAP_RULE_STR, match_arg); + else + rule->rule_str = NULL; - /* Add new route match rule to linked list. */ - route_map_rule_add (&index->match_list, rule); + /* Add new route match rule to linked list. */ + route_map_rule_add(&index->match_list, rule); - /* Execute event hook. */ - if (route_map_master.event_hook) - { - (*route_map_master.event_hook) (replaced ? - RMAP_EVENT_MATCH_REPLACED: - RMAP_EVENT_MATCH_ADDED, - index->map->name); - route_map_notify_dependencies(index->map->name, RMAP_EVENT_CALL_ADDED); - } + /* Execute event hook. */ + if (route_map_master.event_hook) { + (*route_map_master.event_hook)( + replaced ? RMAP_EVENT_MATCH_REPLACED + : RMAP_EVENT_MATCH_ADDED, + index->map->name); + route_map_notify_dependencies(index->map->name, + RMAP_EVENT_CALL_ADDED); + } - return 0; + return 0; } /* Delete specified route match rule. */ -int -route_map_delete_match (struct route_map_index *index, const char *match_name, - const char *match_arg) -{ - struct route_map_rule *rule; - struct route_map_rule_cmd *cmd; - - cmd = route_map_lookup_match (match_name); - if (cmd == NULL) - return 1; - - for (rule = index->match_list.head; rule; rule = rule->next) - if (rule->cmd == cmd && - (rulecmp (rule->rule_str, match_arg) == 0 || match_arg == NULL)) - { - route_map_rule_delete (&index->match_list, rule); - /* Execute event hook. */ - if (route_map_master.event_hook) - { - (*route_map_master.event_hook) (RMAP_EVENT_MATCH_DELETED, - index->map->name); - route_map_notify_dependencies(index->map->name, RMAP_EVENT_CALL_ADDED); - } - return 0; - } - /* Can't find matched rule. */ - return 1; +int route_map_delete_match(struct route_map_index *index, + const char *match_name, const char *match_arg) +{ + struct route_map_rule *rule; + struct route_map_rule_cmd *cmd; + + cmd = route_map_lookup_match(match_name); + if (cmd == NULL) + return 1; + + for (rule = index->match_list.head; rule; rule = rule->next) + if (rule->cmd == cmd && (rulecmp(rule->rule_str, match_arg) == 0 + || match_arg == NULL)) { + route_map_rule_delete(&index->match_list, rule); + /* Execute event hook. */ + if (route_map_master.event_hook) { + (*route_map_master.event_hook)( + RMAP_EVENT_MATCH_DELETED, + index->map->name); + route_map_notify_dependencies( + index->map->name, + RMAP_EVENT_CALL_ADDED); + } + return 0; + } + /* Can't find matched rule. */ + return 1; } /* Add route-map set statement to the route map. */ -int -route_map_add_set (struct route_map_index *index, const char *set_name, - const char *set_arg) -{ - struct route_map_rule *rule; - struct route_map_rule *next; - struct route_map_rule_cmd *cmd; - void *compile; - int replaced = 0; - - cmd = route_map_lookup_set (set_name); - if (cmd == NULL) - return RMAP_RULE_MISSING; - - /* Next call compile function for this match statement. */ - if (cmd->func_compile) - { - compile= (*cmd->func_compile)(set_arg); - if (compile == NULL) - return RMAP_COMPILE_ERROR; - } - else - compile = NULL; - - /* Add by WJL. if old set command of same kind exist, delete it first - to ensure only one set command of same kind exist under a - route_map_index. */ - for (rule = index->set_list.head; rule; rule = next) - { - next = rule->next; - if (rule->cmd == cmd) - { - route_map_rule_delete (&index->set_list, rule); - replaced = 1; +int route_map_add_set(struct route_map_index *index, const char *set_name, + const char *set_arg) +{ + struct route_map_rule *rule; + struct route_map_rule *next; + struct route_map_rule_cmd *cmd; + void *compile; + int replaced = 0; + + cmd = route_map_lookup_set(set_name); + if (cmd == NULL) + return RMAP_RULE_MISSING; + + /* Next call compile function for this match statement. */ + if (cmd->func_compile) { + compile = (*cmd->func_compile)(set_arg); + if (compile == NULL) + return RMAP_COMPILE_ERROR; + } else + compile = NULL; + + /* Add by WJL. if old set command of same kind exist, delete it first + to ensure only one set command of same kind exist under a + route_map_index. */ + for (rule = index->set_list.head; rule; rule = next) { + next = rule->next; + if (rule->cmd == cmd) { + route_map_rule_delete(&index->set_list, rule); + replaced = 1; + } + } + + /* Add new route map match rule. */ + rule = route_map_rule_new(); + rule->cmd = cmd; + rule->value = compile; + if (set_arg) + rule->rule_str = XSTRDUP(MTYPE_ROUTE_MAP_RULE_STR, set_arg); + else + rule->rule_str = NULL; + + /* Add new route match rule to linked list. */ + route_map_rule_add(&index->set_list, rule); + + /* Execute event hook. */ + if (route_map_master.event_hook) { + (*route_map_master.event_hook)(replaced + ? RMAP_EVENT_SET_REPLACED + : RMAP_EVENT_SET_ADDED, + index->map->name); + route_map_notify_dependencies(index->map->name, + RMAP_EVENT_CALL_ADDED); } - } - - /* Add new route map match rule. */ - rule = route_map_rule_new (); - rule->cmd = cmd; - rule->value = compile; - if (set_arg) - rule->rule_str = XSTRDUP (MTYPE_ROUTE_MAP_RULE_STR, set_arg); - else - rule->rule_str = NULL; - - /* Add new route match rule to linked list. */ - route_map_rule_add (&index->set_list, rule); - - /* Execute event hook. */ - if (route_map_master.event_hook) - { - (*route_map_master.event_hook) (replaced ? - RMAP_EVENT_SET_REPLACED: - RMAP_EVENT_SET_ADDED, - index->map->name); - route_map_notify_dependencies(index->map->name, RMAP_EVENT_CALL_ADDED); - } - return 0; + return 0; } /* Delete route map set rule. */ -int -route_map_delete_set (struct route_map_index *index, const char *set_name, - const char *set_arg) -{ - struct route_map_rule *rule; - struct route_map_rule_cmd *cmd; - - cmd = route_map_lookup_set (set_name); - if (cmd == NULL) - return 1; - - for (rule = index->set_list.head; rule; rule = rule->next) - if ((rule->cmd == cmd) && - (rulecmp (rule->rule_str, set_arg) == 0 || set_arg == NULL)) - { - route_map_rule_delete (&index->set_list, rule); - /* Execute event hook. */ - if (route_map_master.event_hook) - { - (*route_map_master.event_hook) (RMAP_EVENT_SET_DELETED, - index->map->name); - route_map_notify_dependencies(index->map->name, RMAP_EVENT_CALL_ADDED); - } - return 0; - } - /* Can't find matched rule. */ - return 1; +int route_map_delete_set(struct route_map_index *index, const char *set_name, + const char *set_arg) +{ + struct route_map_rule *rule; + struct route_map_rule_cmd *cmd; + + cmd = route_map_lookup_set(set_name); + if (cmd == NULL) + return 1; + + for (rule = index->set_list.head; rule; rule = rule->next) + if ((rule->cmd == cmd) && (rulecmp(rule->rule_str, set_arg) == 0 + || set_arg == NULL)) { + route_map_rule_delete(&index->set_list, rule); + /* Execute event hook. */ + if (route_map_master.event_hook) { + (*route_map_master.event_hook)( + RMAP_EVENT_SET_DELETED, + index->map->name); + route_map_notify_dependencies( + index->map->name, + RMAP_EVENT_CALL_ADDED); + } + return 0; + } + /* Can't find matched rule. */ + return 1; } /* Apply route map's each index to the object. @@ -1526,20 +1342,20 @@ route_map_delete_set (struct route_map_index *index, const char *set_name, The matrix for a route-map looks like this: (note, this includes the description for the "NEXT" and "GOTO" frobs now - - Match | No Match - | + + Match | No Match + | permit action | cont - | + | ------------------+--------------- - | + | deny deny | cont - | - + | + action) -Apply Set statements, accept route -If Call statement is present jump to the specified route-map, if it - denies the route we finish. + denies the route we finish. -If NEXT is specified, goto NEXT statement -If GOTO is specified, goto the first clause where pref > nextpref -If nothing is specified, do as Cisco and finish @@ -1547,434 +1363,415 @@ route_map_delete_set (struct route_map_index *index, const char *set_name, -Route is denied by route-map. cont) -Goto Next index - + If we get no matches after we've processed all updates, then the route is dropped too. - + Some notes on the new "CALL", "NEXT" and "GOTO" call WORD - If this clause is matched, then the set statements - are executed and then we jump to route-map 'WORD'. If - this route-map denies the route, we finish, in other case we - do whatever the exit policy (EXIT, NEXT or GOTO) tells. + are executed and then we jump to route-map 'WORD'. If + this route-map denies the route, we finish, in other + case we + do whatever the exit policy (EXIT, NEXT or GOTO) tells. on-match next - If this clause is matched, then the set statements - are executed and then we drop through to the next clause + are executed and then we drop through to the next clause on-match goto n - If this clause is matched, then the set statments - are executed and then we goto the nth clause, or the - first clause greater than this. In order to ensure - route-maps *always* exit, you cannot jump backwards. - Sorry ;) - + are executed and then we goto the nth clause, or the + first clause greater than this. In order to ensure + route-maps *always* exit, you cannot jump backwards. + Sorry ;) + We need to make sure our route-map processing matches the above */ static route_map_result_t -route_map_apply_match (struct route_map_rule_list *match_list, - struct prefix *prefix, route_map_object_t type, - void *object) -{ - route_map_result_t ret = RMAP_NOMATCH; - struct route_map_rule *match; - - - /* Check all match rule and if there is no match rule, go to the - set statement. */ - if (!match_list->head) - ret = RMAP_MATCH; - else - { - for (match = match_list->head; match; match = match->next) - { - /* Try each match statement in turn, If any do not return - RMAP_MATCH, return, otherwise continue on to next match - statement. All match statements must match for end-result - to be a match. */ - ret = (*match->cmd->func_apply) (match->value, prefix, - type, object); - if (ret != RMAP_MATCH) - return ret; - } - } - return ret; +route_map_apply_match(struct route_map_rule_list *match_list, + struct prefix *prefix, route_map_object_t type, + void *object) +{ + route_map_result_t ret = RMAP_NOMATCH; + struct route_map_rule *match; + + + /* Check all match rule and if there is no match rule, go to the + set statement. */ + if (!match_list->head) + ret = RMAP_MATCH; + else { + for (match = match_list->head; match; match = match->next) { + /* Try each match statement in turn, If any do not + return + RMAP_MATCH, return, otherwise continue on to next + match + statement. All match statements must match for + end-result + to be a match. */ + ret = (*match->cmd->func_apply)(match->value, prefix, + type, object); + if (ret != RMAP_MATCH) + return ret; + } + } + return ret; } /* Apply route map to the object. */ -route_map_result_t -route_map_apply (struct route_map *map, struct prefix *prefix, - route_map_object_t type, void *object) -{ - static int recursion = 0; - int ret = 0; - struct route_map_index *index; - struct route_map_rule *set; - - if (recursion > RMAP_RECURSION_LIMIT) - { - zlog_warn("route-map recursion limit (%d) reached, discarding route", - RMAP_RECURSION_LIMIT); - recursion = 0; - return RMAP_DENYMATCH; - } - - if (map == NULL) - return RMAP_DENYMATCH; - - for (index = map->head; index; index = index->next) - { - /* Apply this index. */ - ret = route_map_apply_match (&index->match_list, prefix, type, object); - - /* Now we apply the matrix from above */ - if (ret == RMAP_NOMATCH) - /* 'cont' from matrix - continue to next route-map sequence */ - continue; - else if (ret == RMAP_MATCH) - { - if (index->type == RMAP_PERMIT) - /* 'action' */ - { - /* permit+match must execute sets */ - for (set = index->set_list.head; set; set = set->next) - ret = (*set->cmd->func_apply) (set->value, prefix, - type, object); - - /* Call another route-map if available */ - if (index->nextrm) - { - struct route_map *nextrm = - route_map_lookup_by_name (index->nextrm); - - if (nextrm) /* Target route-map found, jump to it */ - { - recursion++; - ret = route_map_apply (nextrm, prefix, type, object); - recursion--; - } - - /* If nextrm returned 'deny', finish. */ - if (ret == RMAP_DENYMATCH) - return ret; - } - - switch (index->exitpolicy) - { - case RMAP_EXIT: - return ret; - case RMAP_NEXT: - continue; - case RMAP_GOTO: - { - /* Find the next clause to jump to */ - struct route_map_index *next = index->next; - int nextpref = index->nextpref; - - while (next && next->pref < nextpref) - { - index = next; - next = next->next; - } - if (next == NULL) - { - /* No clauses match! */ - return ret; - } - } - } - } - else if (index->type == RMAP_DENY) - /* 'deny' */ - { - return RMAP_DENYMATCH; - } - } - } - /* Finally route-map does not match at all. */ - return RMAP_DENYMATCH; -} - -void -route_map_add_hook (void (*func) (const char *)) -{ - route_map_master.add_hook = func; -} - -void -route_map_delete_hook (void (*func) (const char *)) -{ - route_map_master.delete_hook = func; -} - -void -route_map_event_hook (void (*func) (route_map_event_t, const char *)) -{ - route_map_master.event_hook = func; +route_map_result_t route_map_apply(struct route_map *map, struct prefix *prefix, + route_map_object_t type, void *object) +{ + static int recursion = 0; + int ret = 0; + struct route_map_index *index; + struct route_map_rule *set; + + if (recursion > RMAP_RECURSION_LIMIT) { + zlog_warn( + "route-map recursion limit (%d) reached, discarding route", + RMAP_RECURSION_LIMIT); + recursion = 0; + return RMAP_DENYMATCH; + } + + if (map == NULL) + return RMAP_DENYMATCH; + + for (index = map->head; index; index = index->next) { + /* Apply this index. */ + ret = route_map_apply_match(&index->match_list, prefix, type, + object); + + /* Now we apply the matrix from above */ + if (ret == RMAP_NOMATCH) + /* 'cont' from matrix - continue to next route-map + * sequence */ + continue; + else if (ret == RMAP_MATCH) { + if (index->type == RMAP_PERMIT) + /* 'action' */ + { + /* permit+match must execute sets */ + for (set = index->set_list.head; set; + set = set->next) + ret = (*set->cmd->func_apply)( + set->value, prefix, type, + object); + + /* Call another route-map if available */ + if (index->nextrm) { + struct route_map *nextrm = + route_map_lookup_by_name( + index->nextrm); + + if (nextrm) /* Target route-map found, + jump to it */ + { + recursion++; + ret = route_map_apply( + nextrm, prefix, type, + object); + recursion--; + } + + /* If nextrm returned 'deny', finish. */ + if (ret == RMAP_DENYMATCH) + return ret; + } + + switch (index->exitpolicy) { + case RMAP_EXIT: + return ret; + case RMAP_NEXT: + continue; + case RMAP_GOTO: { + /* Find the next clause to jump to */ + struct route_map_index *next = + index->next; + int nextpref = index->nextpref; + + while (next && next->pref < nextpref) { + index = next; + next = next->next; + } + if (next == NULL) { + /* No clauses match! */ + return ret; + } + } + } + } else if (index->type == RMAP_DENY) + /* 'deny' */ + { + return RMAP_DENYMATCH; + } + } + } + /* Finally route-map does not match at all. */ + return RMAP_DENYMATCH; +} + +void route_map_add_hook(void (*func)(const char *)) +{ + route_map_master.add_hook = func; +} + +void route_map_delete_hook(void (*func)(const char *)) +{ + route_map_master.delete_hook = func; +} + +void route_map_event_hook(void (*func)(route_map_event_t, const char *)) +{ + route_map_master.event_hook = func; } /* Routines for route map dependency lists and dependency processing */ -static int -route_map_rmap_hash_cmp (const void *p1, const void *p2) +static int route_map_rmap_hash_cmp(const void *p1, const void *p2) { - return (strcmp((const char *)p1, (const char *)p2) == 0); + return (strcmp((const char *)p1, (const char *)p2) == 0); } -static int -route_map_dep_hash_cmp (const void *p1, const void *p2) +static int route_map_dep_hash_cmp(const void *p1, const void *p2) { - return (strcmp (((const struct route_map_dep *)p1)->dep_name, (const char *)p2) == 0); + return (strcmp(((const struct route_map_dep *)p1)->dep_name, + (const char *)p2) + == 0); } -static void -route_map_clear_reference(struct hash_backet *backet, void *arg) +static void route_map_clear_reference(struct hash_backet *backet, void *arg) { - struct route_map_dep *dep = (struct route_map_dep *)backet->data; - char *rmap_name; + struct route_map_dep *dep = (struct route_map_dep *)backet->data; + char *rmap_name; - if (dep && arg) - { - rmap_name = (char *)hash_release(dep->dep_rmap_hash, (void *)arg); - if (rmap_name) - { - XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); + if (dep && arg) { + rmap_name = + (char *)hash_release(dep->dep_rmap_hash, (void *)arg); + if (rmap_name) { + XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); + } + if (!dep->dep_rmap_hash->count) { + dep = hash_release(dep->this_hash, + (void *)dep->dep_name); + hash_free(dep->dep_rmap_hash); + XFREE(MTYPE_ROUTE_MAP_NAME, dep->dep_name); + XFREE(MTYPE_ROUTE_MAP_DEP, dep); + } } - if (!dep->dep_rmap_hash->count) - { - dep = hash_release(dep->this_hash, (void *)dep->dep_name); - hash_free(dep->dep_rmap_hash); - XFREE(MTYPE_ROUTE_MAP_NAME, dep->dep_name); - XFREE(MTYPE_ROUTE_MAP_DEP, dep); +} + +static void route_map_clear_all_references(char *rmap_name) +{ + int i; + + for (i = 1; i < ROUTE_MAP_DEP_MAX; i++) { + hash_iterate(route_map_dep_hash[i], route_map_clear_reference, + (void *)rmap_name); } - } } -static void -route_map_clear_all_references (char *rmap_name) +static void *route_map_dep_hash_alloc(void *p) { - int i; + char *dep_name = (char *)p; + struct route_map_dep *dep_entry; + + dep_entry = XCALLOC(MTYPE_ROUTE_MAP_DEP, sizeof(struct route_map_dep)); + dep_entry->dep_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, dep_name); + dep_entry->dep_rmap_hash = hash_create(route_map_dep_hash_make_key, + route_map_rmap_hash_cmp, NULL); + dep_entry->this_hash = NULL; + + return ((void *)dep_entry); +} - for (i = 1; i < ROUTE_MAP_DEP_MAX; i++) - { - hash_iterate(route_map_dep_hash[i], route_map_clear_reference, - (void *)rmap_name); - } +static void *route_map_name_hash_alloc(void *p) +{ + return ((void *)XSTRDUP(MTYPE_ROUTE_MAP_NAME, (const char *)p)); } -static void * -route_map_dep_hash_alloc(void *p) +static unsigned int route_map_dep_hash_make_key(void *p) { - char *dep_name = (char *)p; - struct route_map_dep *dep_entry; + return (string_hash_make((char *)p)); +} - dep_entry = XCALLOC(MTYPE_ROUTE_MAP_DEP, sizeof(struct route_map_dep)); - dep_entry->dep_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, dep_name); - dep_entry->dep_rmap_hash = hash_create(route_map_dep_hash_make_key, - route_map_rmap_hash_cmp, NULL); - dep_entry->this_hash = NULL; +static void route_map_print_dependency(struct hash_backet *backet, void *data) +{ + char *rmap_name = (char *)backet->data; + char *dep_name = (char *)data; - return((void *)dep_entry); + if (rmap_name) + zlog_debug("%s: Dependency for %s: %s", __FUNCTION__, dep_name, + rmap_name); } -static void * -route_map_name_hash_alloc(void *p) +static int route_map_dep_update(struct hash *dephash, const char *dep_name, + const char *rmap_name, route_map_event_t type) { - return((void *)XSTRDUP(MTYPE_ROUTE_MAP_NAME, (const char *)p)); + struct route_map_dep *dep = NULL; + char *ret_map_name; + char *dname, *rname; + int ret = 0; + + dname = XSTRDUP(MTYPE_ROUTE_MAP_NAME, dep_name); + rname = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name); + + switch (type) { + case RMAP_EVENT_PLIST_ADDED: + case RMAP_EVENT_CLIST_ADDED: + case RMAP_EVENT_ECLIST_ADDED: + case RMAP_EVENT_ASLIST_ADDED: + case RMAP_EVENT_LLIST_ADDED: + case RMAP_EVENT_CALL_ADDED: + case RMAP_EVENT_FILTER_ADDED: + if (rmap_debug) + zlog_debug("%s: Adding dependency for %s in %s", + __FUNCTION__, dep_name, rmap_name); + dep = (struct route_map_dep *)hash_get( + dephash, dname, route_map_dep_hash_alloc); + if (!dep) { + ret = -1; + goto out; + } + + if (!dep->this_hash) + dep->this_hash = dephash; + + hash_get(dep->dep_rmap_hash, rname, route_map_name_hash_alloc); + break; + case RMAP_EVENT_PLIST_DELETED: + case RMAP_EVENT_CLIST_DELETED: + case RMAP_EVENT_ECLIST_DELETED: + case RMAP_EVENT_ASLIST_DELETED: + case RMAP_EVENT_LLIST_DELETED: + case RMAP_EVENT_CALL_DELETED: + case RMAP_EVENT_FILTER_DELETED: + if (rmap_debug) + zlog_debug("%s: Deleting dependency for %s in %s", + __FUNCTION__, dep_name, rmap_name); + dep = (struct route_map_dep *)hash_get(dephash, dname, NULL); + if (!dep) { + goto out; + } + + ret_map_name = (char *)hash_release(dep->dep_rmap_hash, rname); + if (ret_map_name) + XFREE(MTYPE_ROUTE_MAP_NAME, ret_map_name); + + if (!dep->dep_rmap_hash->count) { + dep = hash_release(dephash, dname); + hash_free(dep->dep_rmap_hash); + XFREE(MTYPE_ROUTE_MAP_NAME, dep->dep_name); + XFREE(MTYPE_ROUTE_MAP_DEP, dep); + dep = NULL; + } + break; + default: + break; + } + + if (dep) { + if (rmap_debug) + hash_iterate(dep->dep_rmap_hash, + route_map_print_dependency, dname); + } + +out: + XFREE(MTYPE_ROUTE_MAP_NAME, rname); + XFREE(MTYPE_ROUTE_MAP_NAME, dname); + return ret; +} + +static struct hash *route_map_get_dep_hash(route_map_event_t event) +{ + struct hash *upd8_hash = NULL; + + switch (event) { + case RMAP_EVENT_PLIST_ADDED: + case RMAP_EVENT_PLIST_DELETED: + upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_PLIST]; + break; + case RMAP_EVENT_CLIST_ADDED: + case RMAP_EVENT_CLIST_DELETED: + upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_CLIST]; + break; + case RMAP_EVENT_ECLIST_ADDED: + case RMAP_EVENT_ECLIST_DELETED: + upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_ECLIST]; + break; + case RMAP_EVENT_ASLIST_ADDED: + case RMAP_EVENT_ASLIST_DELETED: + upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_ASPATH]; + break; + case RMAP_EVENT_LLIST_ADDED: + case RMAP_EVENT_LLIST_DELETED: + upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_LCLIST]; + break; + case RMAP_EVENT_CALL_ADDED: + case RMAP_EVENT_CALL_DELETED: + upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_RMAP]; + break; + case RMAP_EVENT_FILTER_ADDED: + case RMAP_EVENT_FILTER_DELETED: + upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_FILTER]; + break; + default: + upd8_hash = NULL; + break; + } + return (upd8_hash); } -static unsigned int -route_map_dep_hash_make_key (void *p) +static void route_map_process_dependency(struct hash_backet *backet, void *data) { - return (string_hash_make((char *)p)); + char *rmap_name; + route_map_event_t type = (route_map_event_t)(ptrdiff_t)data; + + rmap_name = (char *)backet->data; + + if (rmap_name) { + if (rmap_debug) + zlog_debug("%s: Notifying %s of dependency", + __FUNCTION__, rmap_name); + if (route_map_master.event_hook) + (*route_map_master.event_hook)(type, rmap_name); + } } -static void -route_map_print_dependency (struct hash_backet *backet, void *data) +void route_map_upd8_dependency(route_map_event_t type, const char *arg, + const char *rmap_name) { - char *rmap_name = (char *)backet->data; - char *dep_name = (char *)data; + struct hash *upd8_hash = NULL; - if (rmap_name) - zlog_debug("%s: Dependency for %s: %s", __FUNCTION__, dep_name, rmap_name); + if ((upd8_hash = route_map_get_dep_hash(type))) + route_map_dep_update(upd8_hash, arg, rmap_name, type); } -static int -route_map_dep_update (struct hash *dephash, const char *dep_name, - const char *rmap_name, - route_map_event_t type) +void route_map_notify_dependencies(const char *affected_name, + route_map_event_t event) { - struct route_map_dep *dep = NULL; - char *ret_map_name; - char *dname, *rname; - int ret = 0; - - dname = XSTRDUP(MTYPE_ROUTE_MAP_NAME, dep_name); - rname = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name); - - switch (type) - { - case RMAP_EVENT_PLIST_ADDED: - case RMAP_EVENT_CLIST_ADDED: - case RMAP_EVENT_ECLIST_ADDED: - case RMAP_EVENT_ASLIST_ADDED: - case RMAP_EVENT_LLIST_ADDED: - case RMAP_EVENT_CALL_ADDED: - case RMAP_EVENT_FILTER_ADDED: - if (rmap_debug) - zlog_debug("%s: Adding dependency for %s in %s", __FUNCTION__, - dep_name, rmap_name); - dep = (struct route_map_dep *) hash_get (dephash, dname, - route_map_dep_hash_alloc); - if (!dep) { - ret = -1; - goto out; - } - - if (!dep->this_hash) - dep->this_hash = dephash; - - hash_get(dep->dep_rmap_hash, rname, route_map_name_hash_alloc); - break; - case RMAP_EVENT_PLIST_DELETED: - case RMAP_EVENT_CLIST_DELETED: - case RMAP_EVENT_ECLIST_DELETED: - case RMAP_EVENT_ASLIST_DELETED: - case RMAP_EVENT_LLIST_DELETED: - case RMAP_EVENT_CALL_DELETED: - case RMAP_EVENT_FILTER_DELETED: - if (rmap_debug) - zlog_debug("%s: Deleting dependency for %s in %s", __FUNCTION__, - dep_name, rmap_name); - dep = (struct route_map_dep *) hash_get (dephash, dname, NULL); - if (!dep) { - goto out; - } - - ret_map_name = (char *)hash_release(dep->dep_rmap_hash, rname); - if (ret_map_name) - XFREE(MTYPE_ROUTE_MAP_NAME, ret_map_name); - - if (!dep->dep_rmap_hash->count) - { - dep = hash_release(dephash, dname); - hash_free(dep->dep_rmap_hash); - XFREE(MTYPE_ROUTE_MAP_NAME, dep->dep_name); - XFREE(MTYPE_ROUTE_MAP_DEP, dep); - dep = NULL; + struct route_map_dep *dep; + struct hash *upd8_hash; + char *name; + + if (!affected_name) + return; + + name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, affected_name); + + if ((upd8_hash = route_map_get_dep_hash(event)) == NULL) { + XFREE(MTYPE_ROUTE_MAP_NAME, name); + return; } - break; - default: - break; - } - - if (dep) - { - if (rmap_debug) - hash_iterate (dep->dep_rmap_hash, route_map_print_dependency, dname); - } - - out: - XFREE(MTYPE_ROUTE_MAP_NAME, rname); - XFREE(MTYPE_ROUTE_MAP_NAME, dname); - return ret; -} - -static struct hash * -route_map_get_dep_hash (route_map_event_t event) -{ - struct hash *upd8_hash = NULL; - - switch (event) - { - case RMAP_EVENT_PLIST_ADDED: - case RMAP_EVENT_PLIST_DELETED: - upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_PLIST]; - break; - case RMAP_EVENT_CLIST_ADDED: - case RMAP_EVENT_CLIST_DELETED: - upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_CLIST]; - break; - case RMAP_EVENT_ECLIST_ADDED: - case RMAP_EVENT_ECLIST_DELETED: - upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_ECLIST]; - break; - case RMAP_EVENT_ASLIST_ADDED: - case RMAP_EVENT_ASLIST_DELETED: - upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_ASPATH]; - break; - case RMAP_EVENT_LLIST_ADDED: - case RMAP_EVENT_LLIST_DELETED: - upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_LCLIST]; - break; - case RMAP_EVENT_CALL_ADDED: - case RMAP_EVENT_CALL_DELETED: - upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_RMAP]; - break; - case RMAP_EVENT_FILTER_ADDED: - case RMAP_EVENT_FILTER_DELETED: - upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_FILTER]; - break; - default: - upd8_hash = NULL; - break; - } - return (upd8_hash); -} - -static void -route_map_process_dependency (struct hash_backet *backet, void *data) -{ - char *rmap_name; - route_map_event_t type = (route_map_event_t)(ptrdiff_t)data; - - rmap_name = (char *)backet->data; - - if (rmap_name) - { - if (rmap_debug) - zlog_debug("%s: Notifying %s of dependency", __FUNCTION__, - rmap_name); - if (route_map_master.event_hook) - (*route_map_master.event_hook) (type, rmap_name); - } -} - -void -route_map_upd8_dependency (route_map_event_t type, const char *arg, - const char *rmap_name) -{ - struct hash *upd8_hash = NULL; - - if ((upd8_hash = route_map_get_dep_hash(type))) - route_map_dep_update (upd8_hash, arg, rmap_name, type); -} - -void -route_map_notify_dependencies (const char *affected_name, route_map_event_t event) -{ - struct route_map_dep *dep; - struct hash *upd8_hash; - char *name; - - if (!affected_name) - return; - - name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, affected_name); - - if ((upd8_hash = route_map_get_dep_hash(event)) == NULL) - { - XFREE (MTYPE_ROUTE_MAP_NAME, name); - return; - } - - dep = (struct route_map_dep *)hash_get (upd8_hash, name, - NULL); - if (dep) - { - if (!dep->this_hash) - dep->this_hash = upd8_hash; - - hash_iterate (dep->dep_rmap_hash, route_map_process_dependency, (void *)event); - } - - XFREE (MTYPE_ROUTE_MAP_NAME, name); + + dep = (struct route_map_dep *)hash_get(upd8_hash, name, NULL); + if (dep) { + if (!dep->this_hash) + dep->this_hash = upd8_hash; + + hash_iterate(dep->dep_rmap_hash, route_map_process_dependency, + (void *)event); + } + + XFREE(MTYPE_ROUTE_MAP_NAME, name); } @@ -1986,12 +1783,14 @@ DEFUN (match_interface, "match first hop interface of route\n" "Interface name\n") { - int idx_word = 2; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_word = 2; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.match_interface) - return rmap_match_set_hook.match_interface (vty, index, "interface", argv[idx_word]->arg, RMAP_EVENT_MATCH_ADDED); - return CMD_SUCCESS; + if (rmap_match_set_hook.match_interface) + return rmap_match_set_hook.match_interface( + vty, index, "interface", argv[idx_word]->arg, + RMAP_EVENT_MATCH_ADDED); + return CMD_SUCCESS; } DEFUN (no_match_interface, @@ -2002,12 +1801,14 @@ DEFUN (no_match_interface, "Match first hop interface of route\n" "Interface name\n") { - char *iface = (argc == 4) ? argv[3]->arg : NULL; - VTY_DECLVAR_CONTEXT (route_map_index, index); + char *iface = (argc == 4) ? argv[3]->arg : NULL; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.no_match_interface) - return rmap_match_set_hook.no_match_interface (vty, index, "interface", iface, RMAP_EVENT_MATCH_DELETED); - return CMD_SUCCESS; + if (rmap_match_set_hook.no_match_interface) + return rmap_match_set_hook.no_match_interface( + vty, index, "interface", iface, + RMAP_EVENT_MATCH_DELETED); + return CMD_SUCCESS; } @@ -2021,13 +1822,14 @@ DEFUN (match_ip_address, "IP access-list number (expanded range)\n" "IP Access-list name\n") { - int idx_acl = 3; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_acl = 3; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.match_ip_address) - return rmap_match_set_hook.match_ip_address (vty, index, "ip address", argv[idx_acl]->arg, - RMAP_EVENT_FILTER_ADDED); - return CMD_SUCCESS; + if (rmap_match_set_hook.match_ip_address) + return rmap_match_set_hook.match_ip_address( + vty, index, "ip address", argv[idx_acl]->arg, + RMAP_EVENT_FILTER_ADDED); + return CMD_SUCCESS; } @@ -2042,18 +1844,19 @@ DEFUN (no_match_ip_address, "IP access-list number (expanded range)\n" "IP Access-list name\n") { - int idx_word = 4; - VTY_DECLVAR_CONTEXT (route_map_index, index); - - if (rmap_match_set_hook.no_match_ip_address) - { - if (argc <= idx_word) - return rmap_match_set_hook.no_match_ip_address (vty, index, "ip address", NULL, - RMAP_EVENT_FILTER_DELETED); - return rmap_match_set_hook.no_match_ip_address (vty, index, "ip address", argv[idx_word]->arg, - RMAP_EVENT_FILTER_DELETED); - } - return CMD_SUCCESS; + int idx_word = 4; + VTY_DECLVAR_CONTEXT(route_map_index, index); + + if (rmap_match_set_hook.no_match_ip_address) { + if (argc <= idx_word) + return rmap_match_set_hook.no_match_ip_address( + vty, index, "ip address", NULL, + RMAP_EVENT_FILTER_DELETED); + return rmap_match_set_hook.no_match_ip_address( + vty, index, "ip address", argv[idx_word]->arg, + RMAP_EVENT_FILTER_DELETED); + } + return CMD_SUCCESS; } @@ -2066,13 +1869,14 @@ DEFUN (match_ip_address_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - int idx_word = 4; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_word = 4; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.match_ip_address_prefix_list) - return rmap_match_set_hook.match_ip_address_prefix_list (vty, index, "ip address prefix-list", - argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED); - return CMD_SUCCESS; + if (rmap_match_set_hook.match_ip_address_prefix_list) + return rmap_match_set_hook.match_ip_address_prefix_list( + vty, index, "ip address prefix-list", + argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED); + return CMD_SUCCESS; } @@ -2086,18 +1890,20 @@ DEFUN (no_match_ip_address_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - int idx_word = 5; - VTY_DECLVAR_CONTEXT (route_map_index, index); - - if (rmap_match_set_hook.no_match_ip_address_prefix_list) - { - if (argc <= idx_word) - return rmap_match_set_hook.no_match_ip_address_prefix_list (vty, index, "ip address prefix-list", - NULL, RMAP_EVENT_PLIST_DELETED); - return rmap_match_set_hook.no_match_ip_address_prefix_list(vty, index, "ip address prefix-list", - argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED); - } - return CMD_SUCCESS; + int idx_word = 5; + VTY_DECLVAR_CONTEXT(route_map_index, index); + + if (rmap_match_set_hook.no_match_ip_address_prefix_list) { + if (argc <= idx_word) + return rmap_match_set_hook + .no_match_ip_address_prefix_list( + vty, index, "ip address prefix-list", + NULL, RMAP_EVENT_PLIST_DELETED); + return rmap_match_set_hook.no_match_ip_address_prefix_list( + vty, index, "ip address prefix-list", + argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED); + } + return CMD_SUCCESS; } @@ -2111,13 +1917,14 @@ DEFUN (match_ip_next_hop, "IP access-list number (expanded range)\n" "IP Access-list name\n") { - int idx_acl = 3; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_acl = 3; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.match_ip_next_hop) - return rmap_match_set_hook.match_ip_next_hop (vty, index, "ip next-hop", argv[idx_acl]->arg, - RMAP_EVENT_FILTER_ADDED); - return CMD_SUCCESS; + if (rmap_match_set_hook.match_ip_next_hop) + return rmap_match_set_hook.match_ip_next_hop( + vty, index, "ip next-hop", argv[idx_acl]->arg, + RMAP_EVENT_FILTER_ADDED); + return CMD_SUCCESS; } @@ -2132,18 +1939,19 @@ DEFUN (no_match_ip_next_hop, "IP access-list number (expanded range)\n" "IP Access-list name\n") { - int idx_word = 4; - VTY_DECLVAR_CONTEXT (route_map_index, index); - - if (rmap_match_set_hook.no_match_ip_next_hop) - { - if (argc <= idx_word) - return rmap_match_set_hook.no_match_ip_next_hop (vty, index, "ip next-hop", NULL, - RMAP_EVENT_FILTER_DELETED); - return rmap_match_set_hook.no_match_ip_next_hop (vty, index, "ip next-hop", argv[idx_word]->arg, - RMAP_EVENT_FILTER_DELETED); - } - return CMD_SUCCESS; + int idx_word = 4; + VTY_DECLVAR_CONTEXT(route_map_index, index); + + if (rmap_match_set_hook.no_match_ip_next_hop) { + if (argc <= idx_word) + return rmap_match_set_hook.no_match_ip_next_hop( + vty, index, "ip next-hop", NULL, + RMAP_EVENT_FILTER_DELETED); + return rmap_match_set_hook.no_match_ip_next_hop( + vty, index, "ip next-hop", argv[idx_word]->arg, + RMAP_EVENT_FILTER_DELETED); + } + return CMD_SUCCESS; } @@ -2156,13 +1964,14 @@ DEFUN (match_ip_next_hop_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - int idx_word = 4; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_word = 4; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.match_ip_next_hop_prefix_list) - return rmap_match_set_hook.match_ip_next_hop_prefix_list (vty, index, "ip next-hop prefix-list", - argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED); - return CMD_SUCCESS; + if (rmap_match_set_hook.match_ip_next_hop_prefix_list) + return rmap_match_set_hook.match_ip_next_hop_prefix_list( + vty, index, "ip next-hop prefix-list", + argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED); + return CMD_SUCCESS; } DEFUN (no_match_ip_next_hop_prefix_list, @@ -2175,18 +1984,19 @@ DEFUN (no_match_ip_next_hop_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - int idx_word = 5; - VTY_DECLVAR_CONTEXT (route_map_index, index); - - if (rmap_match_set_hook.no_match_ip_next_hop) - { - if (argc <= idx_word) - return rmap_match_set_hook.no_match_ip_next_hop (vty, index, "ip next-hop prefix-list", - NULL, RMAP_EVENT_PLIST_DELETED); - return rmap_match_set_hook.no_match_ip_next_hop (vty, index, "ip next-hop prefix-list", - argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED); - } - return CMD_SUCCESS; + int idx_word = 5; + VTY_DECLVAR_CONTEXT(route_map_index, index); + + if (rmap_match_set_hook.no_match_ip_next_hop) { + if (argc <= idx_word) + return rmap_match_set_hook.no_match_ip_next_hop( + vty, index, "ip next-hop prefix-list", NULL, + RMAP_EVENT_PLIST_DELETED); + return rmap_match_set_hook.no_match_ip_next_hop( + vty, index, "ip next-hop prefix-list", + argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED); + } + return CMD_SUCCESS; } @@ -2198,13 +2008,14 @@ DEFUN (match_ipv6_address, "Match IPv6 address of route\n" "IPv6 access-list name\n") { - int idx_word = 3; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_word = 3; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.match_ipv6_address) - return rmap_match_set_hook.match_ipv6_address (vty, index, "ipv6 address", argv[idx_word]->arg, - RMAP_EVENT_FILTER_ADDED); - return CMD_SUCCESS; + if (rmap_match_set_hook.match_ipv6_address) + return rmap_match_set_hook.match_ipv6_address( + vty, index, "ipv6 address", argv[idx_word]->arg, + RMAP_EVENT_FILTER_ADDED); + return CMD_SUCCESS; } DEFUN (no_match_ipv6_address, @@ -2216,13 +2027,14 @@ DEFUN (no_match_ipv6_address, "Match IPv6 address of route\n" "IPv6 access-list name\n") { - int idx_word = 4; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_word = 4; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.no_match_ipv6_address) - return rmap_match_set_hook.no_match_ipv6_address (vty, index, "ipv6 address", argv[idx_word]->arg, - RMAP_EVENT_FILTER_DELETED); - return CMD_SUCCESS; + if (rmap_match_set_hook.no_match_ipv6_address) + return rmap_match_set_hook.no_match_ipv6_address( + vty, index, "ipv6 address", argv[idx_word]->arg, + RMAP_EVENT_FILTER_DELETED); + return CMD_SUCCESS; } @@ -2235,13 +2047,14 @@ DEFUN (match_ipv6_address_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - int idx_word = 4; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_word = 4; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.match_ipv6_address_prefix_list) - return rmap_match_set_hook.match_ipv6_address_prefix_list (vty, index, "ipv6 address prefix-list", - argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED); - return CMD_SUCCESS; + if (rmap_match_set_hook.match_ipv6_address_prefix_list) + return rmap_match_set_hook.match_ipv6_address_prefix_list( + vty, index, "ipv6 address prefix-list", + argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED); + return CMD_SUCCESS; } DEFUN (no_match_ipv6_address_prefix_list, @@ -2254,13 +2067,14 @@ DEFUN (no_match_ipv6_address_prefix_list, "Match entries of prefix-lists\n" "IP prefix-list name\n") { - int idx_word = 5; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_word = 5; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.no_match_ipv6_address_prefix_list) - return rmap_match_set_hook.no_match_ipv6_address_prefix_list(vty, index, "ipv6 address prefix-list", - argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED); - return CMD_SUCCESS; + if (rmap_match_set_hook.no_match_ipv6_address_prefix_list) + return rmap_match_set_hook.no_match_ipv6_address_prefix_list( + vty, index, "ipv6 address prefix-list", + argv[idx_word]->arg, RMAP_EVENT_PLIST_DELETED); + return CMD_SUCCESS; } @@ -2271,13 +2085,14 @@ DEFUN (match_metric, "Match metric of route\n" "Metric value\n") { - int idx_number = 2; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_number = 2; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.match_metric) - return rmap_match_set_hook.match_metric(vty, index, "metric", argv[idx_number]->arg, - RMAP_EVENT_MATCH_ADDED); - return CMD_SUCCESS; + if (rmap_match_set_hook.match_metric) + return rmap_match_set_hook.match_metric(vty, index, "metric", + argv[idx_number]->arg, + RMAP_EVENT_MATCH_ADDED); + return CMD_SUCCESS; } @@ -2289,19 +2104,19 @@ DEFUN (no_match_metric, "Match metric of route\n" "Metric value\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (route_map_index, index); - - if (rmap_match_set_hook.no_match_metric) - { - if (argc <= idx_number) - return rmap_match_set_hook.no_match_metric (vty, index, "metric", - NULL, RMAP_EVENT_MATCH_DELETED); - return rmap_match_set_hook.no_match_metric(vty, index, "metric", - argv[idx_number]->arg, - RMAP_EVENT_MATCH_DELETED); - } - return CMD_SUCCESS; + int idx_number = 3; + VTY_DECLVAR_CONTEXT(route_map_index, index); + + if (rmap_match_set_hook.no_match_metric) { + if (argc <= idx_number) + return rmap_match_set_hook.no_match_metric( + vty, index, "metric", NULL, + RMAP_EVENT_MATCH_DELETED); + return rmap_match_set_hook.no_match_metric( + vty, index, "metric", argv[idx_number]->arg, + RMAP_EVENT_MATCH_DELETED); + } + return CMD_SUCCESS; } @@ -2312,13 +2127,14 @@ DEFUN (match_tag, "Match tag of route\n" "Tag value\n") { - int idx_number = 2; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_number = 2; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.match_tag) - return rmap_match_set_hook.match_tag(vty, index, "tag", argv[idx_number]->arg, - RMAP_EVENT_MATCH_ADDED); - return CMD_SUCCESS; + if (rmap_match_set_hook.match_tag) + return rmap_match_set_hook.match_tag(vty, index, "tag", + argv[idx_number]->arg, + RMAP_EVENT_MATCH_ADDED); + return CMD_SUCCESS; } @@ -2330,16 +2146,17 @@ DEFUN (no_match_tag, "Match tag of route\n" "Tag value\n") { - VTY_DECLVAR_CONTEXT (route_map_index, index); + VTY_DECLVAR_CONTEXT(route_map_index, index); - int idx = 0; - char *arg = argv_find (argv, argc, "(1-4294967295)", &idx) ? - argv[idx]->arg : NULL; + int idx = 0; + char *arg = argv_find(argv, argc, "(1-4294967295)", &idx) + ? argv[idx]->arg + : NULL; - if (rmap_match_set_hook.no_match_tag) - return rmap_match_set_hook.no_match_tag (vty, index, "tag", arg, - RMAP_EVENT_MATCH_DELETED); - return CMD_SUCCESS; + if (rmap_match_set_hook.no_match_tag) + return rmap_match_set_hook.no_match_tag( + vty, index, "tag", arg, RMAP_EVENT_MATCH_DELETED); + return CMD_SUCCESS; } @@ -2351,28 +2168,27 @@ DEFUN (set_ip_nexthop, "Next hop address\n" "IP address of next hop\n") { - int idx_ipv4 = 3; - union sockunion su; - int ret; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_ipv4 = 3; + union sockunion su; + int ret; + VTY_DECLVAR_CONTEXT(route_map_index, index); - ret = str2sockunion (argv[idx_ipv4]->arg, &su); - if (ret < 0) - { - vty_out (vty, "%% Malformed nexthop address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (su.sin.sin_addr.s_addr == 0 || - IPV4_CLASS_DE(su.sin.sin_addr.s_addr)) - { - vty_out (vty, - "%% nexthop address cannot be 0.0.0.0, multicast or reserved\n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = str2sockunion(argv[idx_ipv4]->arg, &su); + if (ret < 0) { + vty_out(vty, "%% Malformed nexthop address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (su.sin.sin_addr.s_addr == 0 + || IPV4_CLASS_DE(su.sin.sin_addr.s_addr)) { + vty_out(vty, + "%% nexthop address cannot be 0.0.0.0, multicast or reserved\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (rmap_match_set_hook.set_ip_nexthop) - return rmap_match_set_hook.set_ip_nexthop(vty, index, "ip next-hop", argv[idx_ipv4]->arg); - return CMD_SUCCESS; + if (rmap_match_set_hook.set_ip_nexthop) + return rmap_match_set_hook.set_ip_nexthop( + vty, index, "ip next-hop", argv[idx_ipv4]->arg); + return CMD_SUCCESS; } @@ -2386,16 +2202,17 @@ DEFUN (no_set_ip_nexthop, "Use peer address (for BGP only)\n" "IP address of next hop\n") { - int idx_peer = 4; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_peer = 4; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.no_set_ip_nexthop) - { - if (argc <= idx_peer) - return rmap_match_set_hook.no_set_ip_nexthop (vty, index, "ip next-hop", NULL); - return rmap_match_set_hook.no_set_ip_nexthop (vty, index, "ip next-hop", argv[idx_peer]->arg); - } - return CMD_SUCCESS; + if (rmap_match_set_hook.no_set_ip_nexthop) { + if (argc <= idx_peer) + return rmap_match_set_hook.no_set_ip_nexthop( + vty, index, "ip next-hop", NULL); + return rmap_match_set_hook.no_set_ip_nexthop( + vty, index, "ip next-hop", argv[idx_peer]->arg); + } + return CMD_SUCCESS; } @@ -2408,26 +2225,25 @@ DEFUN (set_ipv6_nexthop_local, "IPv6 local address\n" "IPv6 address of next hop\n") { - int idx_ipv6 = 4; - struct in6_addr addr; - int ret; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_ipv6 = 4; + struct in6_addr addr; + int ret; + VTY_DECLVAR_CONTEXT(route_map_index, index); - ret = inet_pton (AF_INET6, argv[idx_ipv6]->arg, &addr); - if (!ret) - { - vty_out (vty, "%% Malformed nexthop address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (!IN6_IS_ADDR_LINKLOCAL(&addr)) - { - vty_out (vty, "%% Invalid link-local nexthop address\n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = inet_pton(AF_INET6, argv[idx_ipv6]->arg, &addr); + if (!ret) { + vty_out(vty, "%% Malformed nexthop address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (!IN6_IS_ADDR_LINKLOCAL(&addr)) { + vty_out(vty, "%% Invalid link-local nexthop address\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (rmap_match_set_hook.set_ipv6_nexthop_local) - return rmap_match_set_hook.set_ipv6_nexthop_local (vty, index, "ipv6 next-hop local", argv[idx_ipv6]->arg); - return CMD_SUCCESS; + if (rmap_match_set_hook.set_ipv6_nexthop_local) + return rmap_match_set_hook.set_ipv6_nexthop_local( + vty, index, "ipv6 next-hop local", argv[idx_ipv6]->arg); + return CMD_SUCCESS; } @@ -2441,16 +2257,17 @@ DEFUN (no_set_ipv6_nexthop_local, "IPv6 local address\n" "IPv6 address of next hop\n") { - int idx_ipv6 = 5; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_ipv6 = 5; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.no_set_ipv6_nexthop_local) - { - if (argc <= idx_ipv6) - return rmap_match_set_hook.no_set_ipv6_nexthop_local (vty, index, "ipv6 next-hop local", NULL); - return rmap_match_set_hook.no_set_ipv6_nexthop_local (vty, index, "ipv6 next-hop local", argv[5]->arg); - } - return CMD_SUCCESS; + if (rmap_match_set_hook.no_set_ipv6_nexthop_local) { + if (argc <= idx_ipv6) + return rmap_match_set_hook.no_set_ipv6_nexthop_local( + vty, index, "ipv6 next-hop local", NULL); + return rmap_match_set_hook.no_set_ipv6_nexthop_local( + vty, index, "ipv6 next-hop local", argv[5]->arg); + } + return CMD_SUCCESS; } DEFUN (set_metric, @@ -2465,15 +2282,17 @@ DEFUN (set_metric, "Add metric\n" "Subtract metric\n") { - int idx_number = 2; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_number = 2; + VTY_DECLVAR_CONTEXT(route_map_index, index); - const char *pass = (argv[idx_number]->type == RANGE_TKN) ? - argv[idx_number]->arg : argv[idx_number]->text; + const char *pass = (argv[idx_number]->type == RANGE_TKN) + ? argv[idx_number]->arg + : argv[idx_number]->text; - if (rmap_match_set_hook.set_metric) - return rmap_match_set_hook.set_metric (vty, index, "metric", pass); - return CMD_SUCCESS; + if (rmap_match_set_hook.set_metric) + return rmap_match_set_hook.set_metric(vty, index, "metric", + pass); + return CMD_SUCCESS; } @@ -2485,16 +2304,17 @@ DEFUN (no_set_metric, "Metric value for destination routing protocol\n" "Metric value\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (route_map_index, index); + int idx_number = 3; + VTY_DECLVAR_CONTEXT(route_map_index, index); - if (rmap_match_set_hook.no_set_metric) - { - if (argc <= idx_number) - return rmap_match_set_hook.no_set_metric (vty, index, "metric", NULL); - return rmap_match_set_hook.no_set_metric (vty, index, "metric", argv[idx_number]->arg); - } - return CMD_SUCCESS; + if (rmap_match_set_hook.no_set_metric) { + if (argc <= idx_number) + return rmap_match_set_hook.no_set_metric( + vty, index, "metric", NULL); + return rmap_match_set_hook.no_set_metric(vty, index, "metric", + argv[idx_number]->arg); + } + return CMD_SUCCESS; } @@ -2505,12 +2325,13 @@ DEFUN (set_tag, "Tag value for routing protocol\n" "Tag value\n") { - VTY_DECLVAR_CONTEXT (route_map_index, index); + VTY_DECLVAR_CONTEXT(route_map_index, index); - int idx_number = 2; - if (rmap_match_set_hook.set_tag) - return rmap_match_set_hook.set_tag (vty, index, "tag", argv[idx_number]->arg); - return CMD_SUCCESS; + int idx_number = 2; + if (rmap_match_set_hook.set_tag) + return rmap_match_set_hook.set_tag(vty, index, "tag", + argv[idx_number]->arg); + return CMD_SUCCESS; } @@ -2522,20 +2343,20 @@ DEFUN (no_set_tag, "Tag value for routing protocol\n" "Tag value\n") { - VTY_DECLVAR_CONTEXT (route_map_index, index); + VTY_DECLVAR_CONTEXT(route_map_index, index); - int idx_number = 3; - if (rmap_match_set_hook.no_set_tag) - { - if (argc <= idx_number) - return rmap_match_set_hook.no_set_tag (vty, index, "tag", NULL); - return rmap_match_set_hook.no_set_tag (vty, index, "tag", argv[idx_number]->arg); - } - return CMD_SUCCESS; + int idx_number = 3; + if (rmap_match_set_hook.no_set_tag) { + if (argc <= idx_number) + return rmap_match_set_hook.no_set_tag(vty, index, "tag", + NULL); + return rmap_match_set_hook.no_set_tag(vty, index, "tag", + argv[idx_number]->arg); + } + return CMD_SUCCESS; } - DEFUN_NOSH (route_map, route_map_cmd, "route-map WORD (1-65535)", @@ -2545,22 +2366,23 @@ DEFUN_NOSH (route_map, "Route map permits set operations\n" "Sequence to insert to/delete from existing route-map entry\n") { - int idx_word = 1; - int idx_permit_deny = 2; - int idx_number = 3; - struct route_map *map; - struct route_map_index *index; - char *endptr = NULL; - int permit = argv[idx_permit_deny]->arg[0] == 'p' ? RMAP_PERMIT : RMAP_DENY; - unsigned long pref = strtoul (argv[idx_number]->arg, &endptr, 10); - const char *mapname = argv[idx_word]->arg; + int idx_word = 1; + int idx_permit_deny = 2; + int idx_number = 3; + struct route_map *map; + struct route_map_index *index; + char *endptr = NULL; + int permit = + argv[idx_permit_deny]->arg[0] == 'p' ? RMAP_PERMIT : RMAP_DENY; + unsigned long pref = strtoul(argv[idx_number]->arg, &endptr, 10); + const char *mapname = argv[idx_word]->arg; - /* Get route map. */ - map = route_map_get (mapname); - index = route_map_index_get (map, permit, pref); + /* Get route map. */ + map = route_map_get(mapname); + index = route_map_index_get(map, permit, pref); - VTY_PUSH_CONTEXT (RMAP_NODE, index); - return CMD_SUCCESS; + VTY_PUSH_CONTEXT(RMAP_NODE, index); + return CMD_SUCCESS; } DEFUN (no_route_map_all, @@ -2570,20 +2392,19 @@ DEFUN (no_route_map_all, "Create route-map or enter route-map command mode\n" "Route map tag\n") { - int idx_word = 2; - const char *mapname = argv[idx_word]->arg; - struct route_map *map; + int idx_word = 2; + const char *mapname = argv[idx_word]->arg; + struct route_map *map; - map = route_map_lookup_by_name (mapname); - if (map == NULL) - { - vty_out (vty, "%% Could not find route-map %s\n", mapname); - return CMD_WARNING_CONFIG_FAILED; - } + map = route_map_lookup_by_name(mapname); + if (map == NULL) { + vty_out(vty, "%% Could not find route-map %s\n", mapname); + return CMD_WARNING_CONFIG_FAILED; + } - route_map_delete (map); + route_map_delete(map); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_route_map, @@ -2596,43 +2417,42 @@ DEFUN (no_route_map, "Route map permits set operations\n" "Sequence to insert to/delete from existing route-map entry\n") { - int idx_word = 2; - int idx_permit_deny = 3; - int idx_number = 4; - struct route_map *map; - struct route_map_index *index; - char *endptr = NULL; - int permit = strmatch (argv[idx_permit_deny]->text, "permit") ? - RMAP_PERMIT : RMAP_DENY; - const char *prefstr = argv[idx_number]->arg; - const char *mapname = argv[idx_word]->arg; - unsigned long pref = strtoul (prefstr, &endptr, 10); - - /* Existence check. */ - map = route_map_lookup_by_name (mapname); - if (map == NULL) - { - vty_out (vty, "%% Could not find route-map %s\n", mapname); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Lookup route map index. */ - index = route_map_index_lookup (map, permit, pref); - if (index == NULL) - { - vty_out (vty, "%% Could not find route-map entry %s %s\n", - mapname, prefstr); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Delete index from route map. */ - route_map_index_delete (index, 1); - - /* If this route rule is the last one, delete route map itself. */ - if (route_map_empty (map)) - route_map_delete (map); - - return CMD_SUCCESS; + int idx_word = 2; + int idx_permit_deny = 3; + int idx_number = 4; + struct route_map *map; + struct route_map_index *index; + char *endptr = NULL; + int permit = strmatch(argv[idx_permit_deny]->text, "permit") + ? RMAP_PERMIT + : RMAP_DENY; + const char *prefstr = argv[idx_number]->arg; + const char *mapname = argv[idx_word]->arg; + unsigned long pref = strtoul(prefstr, &endptr, 10); + + /* Existence check. */ + map = route_map_lookup_by_name(mapname); + if (map == NULL) { + vty_out(vty, "%% Could not find route-map %s\n", mapname); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Lookup route map index. */ + index = route_map_index_lookup(map, permit, pref); + if (index == NULL) { + vty_out(vty, "%% Could not find route-map entry %s %s\n", + mapname, prefstr); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Delete index from route map. */ + route_map_index_delete(index, 1); + + /* If this route rule is the last one, delete route map itself. */ + if (route_map_empty(map)) + route_map_delete(map); + + return CMD_SUCCESS; } DEFUN (rmap_onmatch_next, @@ -2641,19 +2461,19 @@ DEFUN (rmap_onmatch_next, "Exit policy on matches\n" "Next clause\n") { - struct route_map_index *index = VTY_GET_CONTEXT (route_map_index); - - if (index) - { - if (index->type == RMAP_DENY) - { - /* Under a deny clause, match means it's finished. No need to set next */ - vty_out (vty,"on-match next not supported under route-map deny\n"); - return CMD_WARNING_CONFIG_FAILED; - } - index->exitpolicy = RMAP_NEXT; - } - return CMD_SUCCESS; + struct route_map_index *index = VTY_GET_CONTEXT(route_map_index); + + if (index) { + if (index->type == RMAP_DENY) { + /* Under a deny clause, match means it's finished. No + * need to set next */ + vty_out(vty, + "on-match next not supported under route-map deny\n"); + return CMD_WARNING_CONFIG_FAILED; + } + index->exitpolicy = RMAP_NEXT; + } + return CMD_SUCCESS; } DEFUN (no_rmap_onmatch_next, @@ -2663,12 +2483,12 @@ DEFUN (no_rmap_onmatch_next, "Exit policy on matches\n" "Next clause\n") { - struct route_map_index *index = VTY_GET_CONTEXT (route_map_index); - - if (index) - index->exitpolicy = RMAP_EXIT; + struct route_map_index *index = VTY_GET_CONTEXT(route_map_index); + + if (index) + index->exitpolicy = RMAP_EXIT; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (rmap_onmatch_goto, @@ -2678,39 +2498,37 @@ DEFUN (rmap_onmatch_goto, "Goto Clause number\n" "Number\n") { - int idx = 0; - char *num = argv_find (argv, argc, "(1-65535)", &idx) ? argv[idx]->arg : NULL; - - struct route_map_index *index = VTY_GET_CONTEXT (route_map_index); - int d = 0; - - if (index) - { - if (index->type == RMAP_DENY) - { - /* Under a deny clause, match means it's finished. No need to go anywhere */ - vty_out (vty,"on-match goto not supported under route-map deny\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (num) - d = strtoul(num, NULL, 10); - else - d = index->pref + 1; - - if (d <= index->pref) - { - /* Can't allow you to do that, Dave */ - vty_out (vty, "can't jump backwards in route-maps\n"); - return CMD_WARNING_CONFIG_FAILED; - } - else - { - index->exitpolicy = RMAP_GOTO; - index->nextpref = d; + int idx = 0; + char *num = argv_find(argv, argc, "(1-65535)", &idx) ? argv[idx]->arg + : NULL; + + struct route_map_index *index = VTY_GET_CONTEXT(route_map_index); + int d = 0; + + if (index) { + if (index->type == RMAP_DENY) { + /* Under a deny clause, match means it's finished. No + * need to go anywhere */ + vty_out(vty, + "on-match goto not supported under route-map deny\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (num) + d = strtoul(num, NULL, 10); + else + d = index->pref + 1; + + if (d <= index->pref) { + /* Can't allow you to do that, Dave */ + vty_out(vty, "can't jump backwards in route-maps\n"); + return CMD_WARNING_CONFIG_FAILED; + } else { + index->exitpolicy = RMAP_GOTO; + index->nextpref = d; + } } - } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_rmap_onmatch_goto, @@ -2720,12 +2538,12 @@ DEFUN (no_rmap_onmatch_goto, "Exit policy on matches\n" "Goto Clause number\n") { - struct route_map_index *index = VTY_GET_CONTEXT (route_map_index); + struct route_map_index *index = VTY_GET_CONTEXT(route_map_index); - if (index) - index->exitpolicy = RMAP_EXIT; - - return CMD_SUCCESS; + if (index) + index->exitpolicy = RMAP_EXIT; + + return CMD_SUCCESS; } /* Cisco/GNU Zebra compatibility aliases */ @@ -2736,7 +2554,7 @@ DEFUN (rmap_continue, "Continue on a different entry within the route-map\n" "Route-map entry sequence number\n") { - return rmap_onmatch_goto (self, vty, argc, argv); + return rmap_onmatch_goto(self, vty, argc, argv); } /* ALIAS_FIXME */ @@ -2747,7 +2565,7 @@ DEFUN (no_rmap_continue, "Continue on a different entry within the route-map\n" "Route-map entry sequence number\n") { - return no_rmap_onmatch_goto (self, vty, argc, argv); + return no_rmap_onmatch_goto(self, vty, argc, argv); } @@ -2758,9 +2576,9 @@ DEFUN (rmap_show_name, "route-map information\n" "route-map name\n") { - int idx_word = 2; - const char *name = (argc == 3) ? argv[idx_word]->arg : NULL; - return vty_show_route_map (vty, name); + int idx_word = 2; + const char *name = (argc == 3) ? argv[idx_word]->arg : NULL; + return vty_show_route_map(vty, name); } DEFUN (rmap_call, @@ -2769,26 +2587,23 @@ DEFUN (rmap_call, "Jump to another Route-Map after match+set\n" "Target route-map name\n") { - int idx_word = 1; - struct route_map_index *index = VTY_GET_CONTEXT (route_map_index); - const char *rmap = argv[idx_word]->arg; + int idx_word = 1; + struct route_map_index *index = VTY_GET_CONTEXT(route_map_index); + const char *rmap = argv[idx_word]->arg; - assert(index); + assert(index); - if (index->nextrm) - { - route_map_upd8_dependency (RMAP_EVENT_CALL_DELETED, - index->nextrm, - index->map->name); - XFREE (MTYPE_ROUTE_MAP_NAME, index->nextrm); - } - index->nextrm = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap); + if (index->nextrm) { + route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED, + index->nextrm, index->map->name); + XFREE(MTYPE_ROUTE_MAP_NAME, index->nextrm); + } + index->nextrm = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); - /* Execute event hook. */ - route_map_upd8_dependency (RMAP_EVENT_CALL_ADDED, - index->nextrm, - index->map->name); - return CMD_SUCCESS; + /* Execute event hook. */ + route_map_upd8_dependency(RMAP_EVENT_CALL_ADDED, index->nextrm, + index->map->name); + return CMD_SUCCESS; } DEFUN (no_rmap_call, @@ -2797,18 +2612,16 @@ DEFUN (no_rmap_call, NO_STR "Jump to another Route-Map after match+set\n") { - struct route_map_index *index = VTY_GET_CONTEXT (route_map_index); + struct route_map_index *index = VTY_GET_CONTEXT(route_map_index); - if (index->nextrm) - { - route_map_upd8_dependency (RMAP_EVENT_CALL_DELETED, - index->nextrm, - index->map->name); - XFREE (MTYPE_ROUTE_MAP_NAME, index->nextrm); - index->nextrm = NULL; - } + if (index->nextrm) { + route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED, + index->nextrm, index->map->name); + XFREE(MTYPE_ROUTE_MAP_NAME, index->nextrm); + index->nextrm = NULL; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (rmap_description, @@ -2817,16 +2630,15 @@ DEFUN (rmap_description, "Route-map comment\n" "Comment describing this route-map rule\n") { - int idx_line = 1; - struct route_map_index *index = VTY_GET_CONTEXT (route_map_index); + int idx_line = 1; + struct route_map_index *index = VTY_GET_CONTEXT(route_map_index); - if (index) - { - if (index->description) - XFREE (MTYPE_TMP, index->description); - index->description = argv_concat (argv, argc, idx_line); - } - return CMD_SUCCESS; + if (index) { + if (index->description) + XFREE(MTYPE_TMP, index->description); + index->description = argv_concat(argv, argc, idx_line); + } + return CMD_SUCCESS; } DEFUN (no_rmap_description, @@ -2835,233 +2647,214 @@ DEFUN (no_rmap_description, NO_STR "Route-map comment\n") { - struct route_map_index *index = VTY_GET_CONTEXT (route_map_index); + struct route_map_index *index = VTY_GET_CONTEXT(route_map_index); - if (index) - { - if (index->description) - XFREE (MTYPE_TMP, index->description); - index->description = NULL; - } - return CMD_SUCCESS; + if (index) { + if (index->description) + XFREE(MTYPE_TMP, index->description); + index->description = NULL; + } + return CMD_SUCCESS; } /* Configuration write function. */ -static int -route_map_config_write (struct vty *vty) -{ - struct route_map *map; - struct route_map_index *index; - struct route_map_rule *rule; - int first = 1; - int write = 0; - - for (map = route_map_master.head; map; map = map->next) - for (index = map->head; index; index = index->next) - { - if (!first) - vty_out (vty, "!\n"); - else - first = 0; - - vty_out (vty, "route-map %s %s %d\n", - map->name, - route_map_type_str (index->type), - index->pref); - - if (index->description) - vty_out (vty, " description %s\n", index->description); - - for (rule = index->match_list.head; rule; rule = rule->next) - vty_out (vty, " match %s %s\n", rule->cmd->str, - rule->rule_str ? rule->rule_str : ""); - - for (rule = index->set_list.head; rule; rule = rule->next) - vty_out (vty, " set %s %s\n", rule->cmd->str, - rule->rule_str ? rule->rule_str : ""); - if (index->nextrm) - vty_out (vty, " call %s\n", index->nextrm); - if (index->exitpolicy == RMAP_GOTO) - vty_out (vty, " on-match goto %d\n", index->nextpref); - if (index->exitpolicy == RMAP_NEXT) - vty_out (vty," on-match next\n"); - - write++; - } - return write; +static int route_map_config_write(struct vty *vty) +{ + struct route_map *map; + struct route_map_index *index; + struct route_map_rule *rule; + int first = 1; + int write = 0; + + for (map = route_map_master.head; map; map = map->next) + for (index = map->head; index; index = index->next) { + if (!first) + vty_out(vty, "!\n"); + else + first = 0; + + vty_out(vty, "route-map %s %s %d\n", map->name, + route_map_type_str(index->type), index->pref); + + if (index->description) + vty_out(vty, " description %s\n", + index->description); + + for (rule = index->match_list.head; rule; + rule = rule->next) + vty_out(vty, " match %s %s\n", rule->cmd->str, + rule->rule_str ? rule->rule_str : ""); + + for (rule = index->set_list.head; rule; + rule = rule->next) + vty_out(vty, " set %s %s\n", rule->cmd->str, + rule->rule_str ? rule->rule_str : ""); + if (index->nextrm) + vty_out(vty, " call %s\n", index->nextrm); + if (index->exitpolicy == RMAP_GOTO) + vty_out(vty, " on-match goto %d\n", + index->nextpref); + if (index->exitpolicy == RMAP_NEXT) + vty_out(vty, " on-match next\n"); + + write++; + } + return write; } /* Route map node structure. */ -static struct cmd_node rmap_node = -{ - RMAP_NODE, - "%s(config-route-map)# ", - 1 -}; +static struct cmd_node rmap_node = {RMAP_NODE, "%s(config-route-map)# ", 1}; /* Common route map rules */ -void * -route_map_rule_tag_compile (const char *arg) +void *route_map_rule_tag_compile(const char *arg) { - unsigned long int tmp; - char *endptr; - route_tag_t *tag; + unsigned long int tmp; + char *endptr; + route_tag_t *tag; - errno = 0; - tmp = strtoul(arg, &endptr, 0); - if (arg[0] == '\0' || *endptr != '\0' || errno || tmp > ROUTE_TAG_MAX) - return NULL; + errno = 0; + tmp = strtoul(arg, &endptr, 0); + if (arg[0] == '\0' || *endptr != '\0' || errno || tmp > ROUTE_TAG_MAX) + return NULL; - tag = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(*tag)); - *tag = tmp; + tag = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(*tag)); + *tag = tmp; - return tag; + return tag; } -void -route_map_rule_tag_free (void *rule) +void route_map_rule_tag_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -void -route_map_finish (void) +void route_map_finish(void) { - int i; + int i; - vector_free (route_match_vec); - route_match_vec = NULL; - vector_free (route_set_vec); - route_set_vec = NULL; + vector_free(route_match_vec); + route_match_vec = NULL; + vector_free(route_set_vec); + route_set_vec = NULL; - /* cleanup route_map */ - while (route_map_master.head) - { - struct route_map *map = route_map_master.head; - map->to_be_processed = 0; - route_map_delete (map); - } + /* cleanup route_map */ + while (route_map_master.head) { + struct route_map *map = route_map_master.head; + map->to_be_processed = 0; + route_map_delete(map); + } - for (i = 1; i < ROUTE_MAP_DEP_MAX; i++) - { - hash_free(route_map_dep_hash[i]); - route_map_dep_hash[i] = NULL; - } + for (i = 1; i < ROUTE_MAP_DEP_MAX; i++) { + hash_free(route_map_dep_hash[i]); + route_map_dep_hash[i] = NULL; + } - hash_free (route_map_master_hash); - route_map_master_hash = NULL; + hash_free(route_map_master_hash); + route_map_master_hash = NULL; } static void rmap_autocomplete(vector comps, struct cmd_token *token) { - struct route_map *map; + struct route_map *map; - for (map = route_map_master.head; map; map = map->next) - vector_set (comps, XSTRDUP (MTYPE_COMPLETION, map->name)); + for (map = route_map_master.head; map; map = map->next) + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, map->name)); } static const struct cmd_variable_handler rmap_var_handlers[] = { - { - /* "route-map WORD" */ - .varname = "route_map", - .completions = rmap_autocomplete - }, { - .tokenname = "ROUTEMAP_NAME", - .completions = rmap_autocomplete - }, { - .tokenname = "RMAP_NAME", - .completions = rmap_autocomplete - }, { - .completions = NULL - } -}; + {/* "route-map WORD" */ + .varname = "route_map", + .completions = rmap_autocomplete}, + {.tokenname = "ROUTEMAP_NAME", .completions = rmap_autocomplete}, + {.tokenname = "RMAP_NAME", .completions = rmap_autocomplete}, + {.completions = NULL}}; /* Initialization of route map vector. */ -void -route_map_init (void) +void route_map_init(void) { - int i; + int i; + + /* Make vector for match and set. */ + route_match_vec = vector_init(1); + route_set_vec = vector_init(1); + route_map_master_hash = + hash_create(route_map_hash_key_make, route_map_hash_cmp, NULL); + + for (i = 1; i < ROUTE_MAP_DEP_MAX; i++) + route_map_dep_hash[i] = + hash_create(route_map_dep_hash_make_key, + route_map_dep_hash_cmp, NULL); - /* Make vector for match and set. */ - route_match_vec = vector_init (1); - route_set_vec = vector_init (1); - route_map_master_hash = hash_create(route_map_hash_key_make, route_map_hash_cmp, NULL); + cmd_variable_handler_register(rmap_var_handlers); - for (i = 1; i < ROUTE_MAP_DEP_MAX; i++) - route_map_dep_hash[i] = hash_create(route_map_dep_hash_make_key, - route_map_dep_hash_cmp, NULL); + /* Install route map top node. */ + install_node(&rmap_node, route_map_config_write); - cmd_variable_handler_register(rmap_var_handlers); + /* Install route map commands. */ + install_default(RMAP_NODE); + install_element(CONFIG_NODE, &route_map_cmd); + install_element(CONFIG_NODE, &no_route_map_cmd); + install_element(CONFIG_NODE, &no_route_map_all_cmd); - /* Install route map top node. */ - install_node (&rmap_node, route_map_config_write); + /* Install the on-match stuff */ + install_element(RMAP_NODE, &route_map_cmd); + install_element(RMAP_NODE, &rmap_onmatch_next_cmd); + install_element(RMAP_NODE, &no_rmap_onmatch_next_cmd); + install_element(RMAP_NODE, &rmap_onmatch_goto_cmd); + install_element(RMAP_NODE, &no_rmap_onmatch_goto_cmd); + install_element(RMAP_NODE, &rmap_continue_cmd); + install_element(RMAP_NODE, &no_rmap_continue_cmd); - /* Install route map commands. */ - install_default (RMAP_NODE); - install_element (CONFIG_NODE, &route_map_cmd); - install_element (CONFIG_NODE, &no_route_map_cmd); - install_element (CONFIG_NODE, &no_route_map_all_cmd); + /* Install the continue stuff (ALIAS of on-match). */ - /* Install the on-match stuff */ - install_element (RMAP_NODE, &route_map_cmd); - install_element (RMAP_NODE, &rmap_onmatch_next_cmd); - install_element (RMAP_NODE, &no_rmap_onmatch_next_cmd); - install_element (RMAP_NODE, &rmap_onmatch_goto_cmd); - install_element (RMAP_NODE, &no_rmap_onmatch_goto_cmd); - install_element (RMAP_NODE, &rmap_continue_cmd); - install_element (RMAP_NODE, &no_rmap_continue_cmd); - - /* Install the continue stuff (ALIAS of on-match). */ - - /* Install the call stuff. */ - install_element (RMAP_NODE, &rmap_call_cmd); - install_element (RMAP_NODE, &no_rmap_call_cmd); + /* Install the call stuff. */ + install_element(RMAP_NODE, &rmap_call_cmd); + install_element(RMAP_NODE, &no_rmap_call_cmd); - /* Install description commands. */ - install_element (RMAP_NODE, &rmap_description_cmd); - install_element (RMAP_NODE, &no_rmap_description_cmd); - - /* Install show command */ - install_element (ENABLE_NODE, &rmap_show_name_cmd); + /* Install description commands. */ + install_element(RMAP_NODE, &rmap_description_cmd); + install_element(RMAP_NODE, &no_rmap_description_cmd); - install_element (RMAP_NODE, &match_interface_cmd); - install_element (RMAP_NODE, &no_match_interface_cmd); + /* Install show command */ + install_element(ENABLE_NODE, &rmap_show_name_cmd); - install_element (RMAP_NODE, &match_ip_address_cmd); - install_element (RMAP_NODE, &no_match_ip_address_cmd); + install_element(RMAP_NODE, &match_interface_cmd); + install_element(RMAP_NODE, &no_match_interface_cmd); - install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd); - install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd); + install_element(RMAP_NODE, &match_ip_address_cmd); + install_element(RMAP_NODE, &no_match_ip_address_cmd); - install_element (RMAP_NODE, &match_ip_next_hop_cmd); - install_element (RMAP_NODE, &no_match_ip_next_hop_cmd); + install_element(RMAP_NODE, &match_ip_address_prefix_list_cmd); + install_element(RMAP_NODE, &no_match_ip_address_prefix_list_cmd); - install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd); - install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd); + install_element(RMAP_NODE, &match_ip_next_hop_cmd); + install_element(RMAP_NODE, &no_match_ip_next_hop_cmd); - install_element (RMAP_NODE, &match_ipv6_address_cmd); - install_element (RMAP_NODE, &no_match_ipv6_address_cmd); + install_element(RMAP_NODE, &match_ip_next_hop_prefix_list_cmd); + install_element(RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd); - install_element (RMAP_NODE, &match_ipv6_address_prefix_list_cmd); - install_element (RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd); + install_element(RMAP_NODE, &match_ipv6_address_cmd); + install_element(RMAP_NODE, &no_match_ipv6_address_cmd); - install_element (RMAP_NODE, &match_metric_cmd); - install_element (RMAP_NODE, &no_match_metric_cmd); + install_element(RMAP_NODE, &match_ipv6_address_prefix_list_cmd); + install_element(RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd); - install_element (RMAP_NODE, &match_tag_cmd); - install_element (RMAP_NODE, &no_match_tag_cmd); + install_element(RMAP_NODE, &match_metric_cmd); + install_element(RMAP_NODE, &no_match_metric_cmd); - install_element (RMAP_NODE, &set_ip_nexthop_cmd); - install_element (RMAP_NODE, &no_set_ip_nexthop_cmd); + install_element(RMAP_NODE, &match_tag_cmd); + install_element(RMAP_NODE, &no_match_tag_cmd); - install_element (RMAP_NODE, &set_ipv6_nexthop_local_cmd); - install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_cmd); + install_element(RMAP_NODE, &set_ip_nexthop_cmd); + install_element(RMAP_NODE, &no_set_ip_nexthop_cmd); - install_element (RMAP_NODE, &set_metric_cmd); - install_element (RMAP_NODE, &no_set_metric_cmd); + install_element(RMAP_NODE, &set_ipv6_nexthop_local_cmd); + install_element(RMAP_NODE, &no_set_ipv6_nexthop_local_cmd); - install_element (RMAP_NODE, &set_tag_cmd); - install_element (RMAP_NODE, &no_set_tag_cmd); + install_element(RMAP_NODE, &set_metric_cmd); + install_element(RMAP_NODE, &no_set_metric_cmd); + install_element(RMAP_NODE, &set_tag_cmd); + install_element(RMAP_NODE, &no_set_tag_cmd); } diff --git a/lib/routemap.h b/lib/routemap.h index f1937ac40..43af8dbcf 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -31,379 +31,312 @@ DECLARE_MTYPE(ROUTE_MAP_RULE) DECLARE_MTYPE(ROUTE_MAP_COMPILED) /* Route map's type. */ -enum route_map_type -{ - RMAP_PERMIT, - RMAP_DENY, - RMAP_ANY -}; - -typedef enum -{ - RMAP_MATCH, - RMAP_DENYMATCH, - RMAP_NOMATCH, - RMAP_ERROR, - RMAP_OKAY +enum route_map_type { RMAP_PERMIT, RMAP_DENY, RMAP_ANY }; + +typedef enum { + RMAP_MATCH, + RMAP_DENYMATCH, + RMAP_NOMATCH, + RMAP_ERROR, + RMAP_OKAY } route_map_result_t; -typedef enum -{ - RMAP_RIP, - RMAP_RIPNG, - RMAP_OSPF, - RMAP_OSPF6, - RMAP_BGP, - RMAP_ZEBRA, - RMAP_ISIS, +typedef enum { + RMAP_RIP, + RMAP_RIPNG, + RMAP_OSPF, + RMAP_OSPF6, + RMAP_BGP, + RMAP_ZEBRA, + RMAP_ISIS, } route_map_object_t; -typedef enum -{ - RMAP_EXIT, - RMAP_GOTO, - RMAP_NEXT -} route_map_end_t; - -typedef enum -{ - RMAP_EVENT_SET_ADDED, - RMAP_EVENT_SET_DELETED, - RMAP_EVENT_SET_REPLACED, - RMAP_EVENT_MATCH_ADDED, - RMAP_EVENT_MATCH_DELETED, - RMAP_EVENT_MATCH_REPLACED, - RMAP_EVENT_INDEX_ADDED, - RMAP_EVENT_INDEX_DELETED, - RMAP_EVENT_CALL_ADDED, /* call to another routemap added */ - RMAP_EVENT_CALL_DELETED, - RMAP_EVENT_PLIST_ADDED, - RMAP_EVENT_PLIST_DELETED, - RMAP_EVENT_CLIST_ADDED, - RMAP_EVENT_CLIST_DELETED, - RMAP_EVENT_ECLIST_ADDED, - RMAP_EVENT_ECLIST_DELETED, - RMAP_EVENT_LLIST_ADDED, - RMAP_EVENT_LLIST_DELETED, - RMAP_EVENT_ASLIST_ADDED, - RMAP_EVENT_ASLIST_DELETED, - RMAP_EVENT_FILTER_ADDED, - RMAP_EVENT_FILTER_DELETED, +typedef enum { RMAP_EXIT, RMAP_GOTO, RMAP_NEXT } route_map_end_t; + +typedef enum { + RMAP_EVENT_SET_ADDED, + RMAP_EVENT_SET_DELETED, + RMAP_EVENT_SET_REPLACED, + RMAP_EVENT_MATCH_ADDED, + RMAP_EVENT_MATCH_DELETED, + RMAP_EVENT_MATCH_REPLACED, + RMAP_EVENT_INDEX_ADDED, + RMAP_EVENT_INDEX_DELETED, + RMAP_EVENT_CALL_ADDED, /* call to another routemap added */ + RMAP_EVENT_CALL_DELETED, + RMAP_EVENT_PLIST_ADDED, + RMAP_EVENT_PLIST_DELETED, + RMAP_EVENT_CLIST_ADDED, + RMAP_EVENT_CLIST_DELETED, + RMAP_EVENT_ECLIST_ADDED, + RMAP_EVENT_ECLIST_DELETED, + RMAP_EVENT_LLIST_ADDED, + RMAP_EVENT_LLIST_DELETED, + RMAP_EVENT_ASLIST_ADDED, + RMAP_EVENT_ASLIST_DELETED, + RMAP_EVENT_FILTER_ADDED, + RMAP_EVENT_FILTER_DELETED, } route_map_event_t; /* Depth limit in RMAP recursion using RMAP_CALL. */ #define RMAP_RECURSION_LIMIT 10 /* Route map rule structure for matching and setting. */ -struct route_map_rule_cmd -{ - /* Route map rule name (e.g. as-path, metric) */ - const char *str; +struct route_map_rule_cmd { + /* Route map rule name (e.g. as-path, metric) */ + const char *str; - /* Function for value set or match. */ - route_map_result_t (*func_apply)(void *, struct prefix *, - route_map_object_t, void *); + /* Function for value set or match. */ + route_map_result_t (*func_apply)(void *, struct prefix *, + route_map_object_t, void *); - /* Compile argument and return result as void *. */ - void *(*func_compile)(const char *); + /* Compile argument and return result as void *. */ + void *(*func_compile)(const char *); - /* Free allocated value by func_compile (). */ - void (*func_free)(void *); + /* Free allocated value by func_compile (). */ + void (*func_free)(void *); }; /* Route map apply error. */ -enum -{ - /* Route map rule is missing. */ - RMAP_RULE_MISSING = 1, +enum { + /* Route map rule is missing. */ + RMAP_RULE_MISSING = 1, - /* Route map rule can't compile */ - RMAP_COMPILE_ERROR + /* Route map rule can't compile */ + RMAP_COMPILE_ERROR }; /* Route map rule list. */ -struct route_map_rule_list -{ - struct route_map_rule *head; - struct route_map_rule *tail; +struct route_map_rule_list { + struct route_map_rule *head; + struct route_map_rule *tail; }; /* Route map index structure. */ -struct route_map_index -{ - struct route_map *map; - char *description; +struct route_map_index { + struct route_map *map; + char *description; - /* Preference of this route map rule. */ - int pref; + /* Preference of this route map rule. */ + int pref; - /* Route map type permit or deny. */ - enum route_map_type type; + /* Route map type permit or deny. */ + enum route_map_type type; - /* Do we follow old rules, or hop forward? */ - route_map_end_t exitpolicy; + /* Do we follow old rules, or hop forward? */ + route_map_end_t exitpolicy; - /* If we're using "GOTO", to where do we go? */ - int nextpref; + /* If we're using "GOTO", to where do we go? */ + int nextpref; - /* If we're using "CALL", to which route-map do ew go? */ - char *nextrm; + /* If we're using "CALL", to which route-map do ew go? */ + char *nextrm; - /* Matching rule list. */ - struct route_map_rule_list match_list; - struct route_map_rule_list set_list; + /* Matching rule list. */ + struct route_map_rule_list match_list; + struct route_map_rule_list set_list; - /* Make linked list. */ - struct route_map_index *next; - struct route_map_index *prev; + /* Make linked list. */ + struct route_map_index *next; + struct route_map_index *prev; - QOBJ_FIELDS + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(route_map_index) /* Route map list structure. */ -struct route_map -{ - /* Name of route map. */ - char *name; +struct route_map { + /* Name of route map. */ + char *name; - /* Route map's rule. */ - struct route_map_index *head; - struct route_map_index *tail; + /* Route map's rule. */ + struct route_map_index *head; + struct route_map_index *tail; - /* Make linked list. */ - struct route_map *next; - struct route_map *prev; + /* Make linked list. */ + struct route_map *next; + struct route_map *prev; - /* Maintain update info */ - int to_be_processed; /* True if modification isn't acted on yet */ - int deleted; /* If 1, then this node will be deleted */ + /* Maintain update info */ + int to_be_processed; /* True if modification isn't acted on yet */ + int deleted; /* If 1, then this node will be deleted */ - QOBJ_FIELDS + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(route_map) /* Prototypes. */ -extern void route_map_init (void); -extern void route_map_finish (void); +extern void route_map_init(void); +extern void route_map_finish(void); /* Add match statement to route map. */ -extern int route_map_add_match (struct route_map_index *index, - const char *match_name, - const char *match_arg); +extern int route_map_add_match(struct route_map_index *index, + const char *match_name, const char *match_arg); /* Delete specified route match rule. */ -extern int route_map_delete_match (struct route_map_index *index, - const char *match_name, - const char *match_arg); +extern int route_map_delete_match(struct route_map_index *index, + const char *match_name, + const char *match_arg); -extern const char *route_map_get_match_arg (struct route_map_index *index, - const char *match_name); +extern const char *route_map_get_match_arg(struct route_map_index *index, + const char *match_name); /* Add route-map set statement to the route map. */ -extern int route_map_add_set (struct route_map_index *index, - const char *set_name, - const char *set_arg); +extern int route_map_add_set(struct route_map_index *index, + const char *set_name, const char *set_arg); /* Delete route map set rule. */ -extern int route_map_delete_set (struct route_map_index *index, - const char *set_name, - const char *set_arg); +extern int route_map_delete_set(struct route_map_index *index, + const char *set_name, const char *set_arg); /* Install rule command to the match list. */ -extern void route_map_install_match (struct route_map_rule_cmd *cmd); +extern void route_map_install_match(struct route_map_rule_cmd *cmd); /* Install rule command to the set list. */ -extern void route_map_install_set (struct route_map_rule_cmd *cmd); +extern void route_map_install_set(struct route_map_rule_cmd *cmd); /* Lookup route map by name. */ -extern struct route_map * route_map_lookup_by_name (const char *name); +extern struct route_map *route_map_lookup_by_name(const char *name); /* Apply route map to the object. */ -extern route_map_result_t route_map_apply (struct route_map *map, - struct prefix *, - route_map_object_t object_type, - void *object); - -extern void route_map_add_hook (void (*func) (const char *)); -extern void route_map_delete_hook (void (*func) (const char *)); -extern void route_map_event_hook (void (*func) (route_map_event_t, - const char *)); -extern int route_map_mark_updated (const char *name, int deleted); -extern int route_map_clear_updated (struct route_map *rmap); -extern void route_map_walk_update_list (int (*update_fn) (char *name)); -extern void route_map_upd8_dependency (route_map_event_t type, const char *arg, - const char *rmap_name); -extern void route_map_notify_dependencies (const char *affected_name, - route_map_event_t event); - -extern int generic_match_add (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); - -extern int generic_match_delete (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type); -extern int generic_set_add (struct vty *vty, struct route_map_index *index, - const char *command, const char *arg); -extern int generic_set_delete (struct vty *vty, struct route_map_index *index, - const char *command, const char *arg); +extern route_map_result_t route_map_apply(struct route_map *map, + struct prefix *, + route_map_object_t object_type, + void *object); + +extern void route_map_add_hook(void (*func)(const char *)); +extern void route_map_delete_hook(void (*func)(const char *)); +extern void route_map_event_hook(void (*func)(route_map_event_t, const char *)); +extern int route_map_mark_updated(const char *name, int deleted); +extern int route_map_clear_updated(struct route_map *rmap); +extern void route_map_walk_update_list(int (*update_fn)(char *name)); +extern void route_map_upd8_dependency(route_map_event_t type, const char *arg, + const char *rmap_name); +extern void route_map_notify_dependencies(const char *affected_name, + route_map_event_t event); + +extern int generic_match_add(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); + +extern int generic_match_delete(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg, + route_map_event_t type); +extern int generic_set_add(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg); +extern int generic_set_delete(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg); /* match interface */ -extern void route_map_match_interface_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)); +extern void route_map_match_interface_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)); /* no match interface */ -extern void route_map_no_match_interface_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)); +extern void route_map_no_match_interface_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)); /* match ip address */ -extern void route_map_match_ip_address_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)); +extern void route_map_match_ip_address_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)); /* no match ip address */ -extern void route_map_no_match_ip_address_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)); +extern void route_map_no_match_ip_address_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)); /* match ip address prefix list */ -extern void route_map_match_ip_address_prefix_list_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)); +extern void route_map_match_ip_address_prefix_list_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)); /* no match ip address prefix list */ -extern void route_map_no_match_ip_address_prefix_list_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)); +extern void route_map_no_match_ip_address_prefix_list_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)); /* match ip next hop */ -extern void route_map_match_ip_next_hop_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)); +extern void route_map_match_ip_next_hop_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)); /* no match ip next hop */ -extern void route_map_no_match_ip_next_hop_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)); +extern void route_map_no_match_ip_next_hop_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)); /* match ip next hop prefix list */ -extern void route_map_match_ip_next_hop_prefix_list_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)); +extern void route_map_match_ip_next_hop_prefix_list_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)); /* no match ip next hop prefix list */ -extern void route_map_no_match_ip_next_hop_prefix_list_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)); +extern void route_map_no_match_ip_next_hop_prefix_list_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)); /* match ipv6 address */ -extern void route_map_match_ipv6_address_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)); +extern void route_map_match_ipv6_address_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)); /* no match ipv6 address */ -extern void route_map_no_match_ipv6_address_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)); +extern void route_map_no_match_ipv6_address_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)); /* match ipv6 address prefix list */ -extern void route_map_match_ipv6_address_prefix_list_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)); +extern void route_map_match_ipv6_address_prefix_list_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)); /* no match ipv6 address prefix list */ -extern void route_map_no_match_ipv6_address_prefix_list_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)); +extern void route_map_no_match_ipv6_address_prefix_list_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)); /* match metric */ -extern void route_map_match_metric_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)); +extern void route_map_match_metric_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)); /* no match metric */ -extern void route_map_no_match_metric_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)); +extern void route_map_no_match_metric_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)); /* match tag */ -extern void route_map_match_tag_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)); +extern void route_map_match_tag_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)); /* no match tag */ -extern void route_map_no_match_tag_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg, - route_map_event_t type)); +extern void route_map_no_match_tag_hook(int (*func)( + struct vty *vty, struct route_map_index *index, const char *command, + const char *arg, route_map_event_t type)); /* set ip nexthop */ -extern void route_map_set_ip_nexthop_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)); +extern void route_map_set_ip_nexthop_hook( + int (*func)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg)); /* no set ip nexthop */ -extern void route_map_no_set_ip_nexthop_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)); +extern void route_map_no_set_ip_nexthop_hook( + int (*func)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg)); /* set ipv6 nexthop local */ -extern void route_map_set_ipv6_nexthop_local_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)); +extern void route_map_set_ipv6_nexthop_local_hook( + int (*func)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg)); /* no set ipv6 nexthop local */ -extern void route_map_no_set_ipv6_nexthop_local_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)); +extern void route_map_no_set_ipv6_nexthop_local_hook( + int (*func)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg)); /* set metric */ -extern void route_map_set_metric_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)); +extern void route_map_set_metric_hook(int (*func)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg)); /* no set metric */ -extern void route_map_no_set_metric_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)); +extern void route_map_no_set_metric_hook( + int (*func)(struct vty *vty, struct route_map_index *index, + const char *command, const char *arg)); /* set tag */ -extern void route_map_set_tag_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)); +extern void route_map_set_tag_hook(int (*func)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg)); /* no set tag */ -extern void route_map_no_set_tag_hook (int (*func) (struct vty *vty, - struct route_map_index *index, - const char *command, - const char *arg)); +extern void route_map_no_set_tag_hook(int (*func)(struct vty *vty, + struct route_map_index *index, + const char *command, + const char *arg)); -extern void *route_map_rule_tag_compile (const char *arg); -extern void route_map_rule_tag_free (void *rule); +extern void *route_map_rule_tag_compile(const char *arg); +extern void route_map_rule_tag_free(void *rule); #endif /* _ZEBRA_ROUTEMAP_H */ diff --git a/lib/sha256.c b/lib/sha256.c index f98a75882..a1b77901e 100644 --- a/lib/sha256.c +++ b/lib/sha256.c @@ -28,28 +28,26 @@ #include "sha256.h" #if !HAVE_DECL_BE32DEC -static inline uint32_t -be32dec(const void *pp) +static inline uint32_t be32dec(const void *pp) { - const uint8_t *p = (uint8_t const *)pp; + const uint8_t *p = (uint8_t const *)pp; - return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) + - ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24)); + return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) + + ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24)); } #else #include #endif #if !HAVE_DECL_BE32ENC -static inline void -be32enc(void *pp, uint32_t x) +static inline void be32enc(void *pp, uint32_t x) { - uint8_t * p = (uint8_t *)pp; + uint8_t *p = (uint8_t *)pp; - p[3] = x & 0xff; - p[2] = (x >> 8) & 0xff; - p[1] = (x >> 16) & 0xff; - p[0] = (x >> 24) & 0xff; + p[3] = x & 0xff; + p[2] = (x >> 8) & 0xff; + p[1] = (x >> 16) & 0xff; + p[0] = (x >> 24) & 0xff; } #else #include @@ -59,26 +57,24 @@ be32enc(void *pp, uint32_t x) * Encode a length len/4 vector of (uint32_t) into a length len vector of * (unsigned char) in big-endian form. Assumes len is a multiple of 4. */ -static void -be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len) +static void be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len) { - size_t i; + size_t i; - for (i = 0; i < len / 4; i++) - be32enc(dst + i * 4, src[i]); + for (i = 0; i < len / 4; i++) + be32enc(dst + i * 4, src[i]); } /* * Decode a big-endian length len vector of (unsigned char) into a length * len/4 vector of (uint32_t). Assumes len is a multiple of 4. */ -static void -be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len) +static void be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len) { - size_t i; + size_t i; - for (i = 0; i < len / 4; i++) - dst[i] = be32dec(src + i * 4); + for (i = 0; i < len / 4; i++) + dst[i] = be32dec(src + i * 4); } /* Elementary functions used by SHA256 */ @@ -92,287 +88,275 @@ be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len) #define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) /* SHA256 round function */ -#define RND(a, b, c, d, e, f, g, h, k) \ - t0 = h + S1(e) + Ch(e, f, g) + k; \ - t1 = S0(a) + Maj(a, b, c); \ - d += t0; \ - h = t0 + t1; +#define RND(a, b, c, d, e, f, g, h, k) \ + t0 = h + S1(e) + Ch(e, f, g) + k; \ + t1 = S0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; /* Adjusted round function for rotating state */ -#define RNDr(S, W, i, k) \ - RND(S[(64 - i) % 8], S[(65 - i) % 8], \ - S[(66 - i) % 8], S[(67 - i) % 8], \ - S[(68 - i) % 8], S[(69 - i) % 8], \ - S[(70 - i) % 8], S[(71 - i) % 8], \ - W[i] + k) +#define RNDr(S, W, i, k) \ + RND(S[(64 - i) % 8], S[(65 - i) % 8], S[(66 - i) % 8], \ + S[(67 - i) % 8], S[(68 - i) % 8], S[(69 - i) % 8], \ + S[(70 - i) % 8], S[(71 - i) % 8], W[i] + k) /* * SHA256 block compression function. The 256-bit state is transformed via * the 512-bit input block to produce a new state. */ -static void -SHA256_Transform(uint32_t * state, const unsigned char block[64]) +static void SHA256_Transform(uint32_t *state, const unsigned char block[64]) { - uint32_t W[64]; - uint32_t S[8]; - uint32_t t0, t1; - int i; - - /* 1. Prepare message schedule W. */ - be32dec_vect(W, block, 64); - for (i = 16; i < 64; i++) - W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16]; - - /* 2. Initialize working variables. */ - memcpy(S, state, 32); - - /* 3. Mix. */ - RNDr(S, W, 0, 0x428a2f98); - RNDr(S, W, 1, 0x71374491); - RNDr(S, W, 2, 0xb5c0fbcf); - RNDr(S, W, 3, 0xe9b5dba5); - RNDr(S, W, 4, 0x3956c25b); - RNDr(S, W, 5, 0x59f111f1); - RNDr(S, W, 6, 0x923f82a4); - RNDr(S, W, 7, 0xab1c5ed5); - RNDr(S, W, 8, 0xd807aa98); - RNDr(S, W, 9, 0x12835b01); - RNDr(S, W, 10, 0x243185be); - RNDr(S, W, 11, 0x550c7dc3); - RNDr(S, W, 12, 0x72be5d74); - RNDr(S, W, 13, 0x80deb1fe); - RNDr(S, W, 14, 0x9bdc06a7); - RNDr(S, W, 15, 0xc19bf174); - RNDr(S, W, 16, 0xe49b69c1); - RNDr(S, W, 17, 0xefbe4786); - RNDr(S, W, 18, 0x0fc19dc6); - RNDr(S, W, 19, 0x240ca1cc); - RNDr(S, W, 20, 0x2de92c6f); - RNDr(S, W, 21, 0x4a7484aa); - RNDr(S, W, 22, 0x5cb0a9dc); - RNDr(S, W, 23, 0x76f988da); - RNDr(S, W, 24, 0x983e5152); - RNDr(S, W, 25, 0xa831c66d); - RNDr(S, W, 26, 0xb00327c8); - RNDr(S, W, 27, 0xbf597fc7); - RNDr(S, W, 28, 0xc6e00bf3); - RNDr(S, W, 29, 0xd5a79147); - RNDr(S, W, 30, 0x06ca6351); - RNDr(S, W, 31, 0x14292967); - RNDr(S, W, 32, 0x27b70a85); - RNDr(S, W, 33, 0x2e1b2138); - RNDr(S, W, 34, 0x4d2c6dfc); - RNDr(S, W, 35, 0x53380d13); - RNDr(S, W, 36, 0x650a7354); - RNDr(S, W, 37, 0x766a0abb); - RNDr(S, W, 38, 0x81c2c92e); - RNDr(S, W, 39, 0x92722c85); - RNDr(S, W, 40, 0xa2bfe8a1); - RNDr(S, W, 41, 0xa81a664b); - RNDr(S, W, 42, 0xc24b8b70); - RNDr(S, W, 43, 0xc76c51a3); - RNDr(S, W, 44, 0xd192e819); - RNDr(S, W, 45, 0xd6990624); - RNDr(S, W, 46, 0xf40e3585); - RNDr(S, W, 47, 0x106aa070); - RNDr(S, W, 48, 0x19a4c116); - RNDr(S, W, 49, 0x1e376c08); - RNDr(S, W, 50, 0x2748774c); - RNDr(S, W, 51, 0x34b0bcb5); - RNDr(S, W, 52, 0x391c0cb3); - RNDr(S, W, 53, 0x4ed8aa4a); - RNDr(S, W, 54, 0x5b9cca4f); - RNDr(S, W, 55, 0x682e6ff3); - RNDr(S, W, 56, 0x748f82ee); - RNDr(S, W, 57, 0x78a5636f); - RNDr(S, W, 58, 0x84c87814); - RNDr(S, W, 59, 0x8cc70208); - RNDr(S, W, 60, 0x90befffa); - RNDr(S, W, 61, 0xa4506ceb); - RNDr(S, W, 62, 0xbef9a3f7); - RNDr(S, W, 63, 0xc67178f2); - - /* 4. Mix local working variables into global state */ - for (i = 0; i < 8; i++) - state[i] += S[i]; - - /* Clean the stack. */ - memset(W, 0, 256); - memset(S, 0, 32); - t0 = t1 = 0; + uint32_t W[64]; + uint32_t S[8]; + uint32_t t0, t1; + int i; + + /* 1. Prepare message schedule W. */ + be32dec_vect(W, block, 64); + for (i = 16; i < 64; i++) + W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16]; + + /* 2. Initialize working variables. */ + memcpy(S, state, 32); + + /* 3. Mix. */ + RNDr(S, W, 0, 0x428a2f98); + RNDr(S, W, 1, 0x71374491); + RNDr(S, W, 2, 0xb5c0fbcf); + RNDr(S, W, 3, 0xe9b5dba5); + RNDr(S, W, 4, 0x3956c25b); + RNDr(S, W, 5, 0x59f111f1); + RNDr(S, W, 6, 0x923f82a4); + RNDr(S, W, 7, 0xab1c5ed5); + RNDr(S, W, 8, 0xd807aa98); + RNDr(S, W, 9, 0x12835b01); + RNDr(S, W, 10, 0x243185be); + RNDr(S, W, 11, 0x550c7dc3); + RNDr(S, W, 12, 0x72be5d74); + RNDr(S, W, 13, 0x80deb1fe); + RNDr(S, W, 14, 0x9bdc06a7); + RNDr(S, W, 15, 0xc19bf174); + RNDr(S, W, 16, 0xe49b69c1); + RNDr(S, W, 17, 0xefbe4786); + RNDr(S, W, 18, 0x0fc19dc6); + RNDr(S, W, 19, 0x240ca1cc); + RNDr(S, W, 20, 0x2de92c6f); + RNDr(S, W, 21, 0x4a7484aa); + RNDr(S, W, 22, 0x5cb0a9dc); + RNDr(S, W, 23, 0x76f988da); + RNDr(S, W, 24, 0x983e5152); + RNDr(S, W, 25, 0xa831c66d); + RNDr(S, W, 26, 0xb00327c8); + RNDr(S, W, 27, 0xbf597fc7); + RNDr(S, W, 28, 0xc6e00bf3); + RNDr(S, W, 29, 0xd5a79147); + RNDr(S, W, 30, 0x06ca6351); + RNDr(S, W, 31, 0x14292967); + RNDr(S, W, 32, 0x27b70a85); + RNDr(S, W, 33, 0x2e1b2138); + RNDr(S, W, 34, 0x4d2c6dfc); + RNDr(S, W, 35, 0x53380d13); + RNDr(S, W, 36, 0x650a7354); + RNDr(S, W, 37, 0x766a0abb); + RNDr(S, W, 38, 0x81c2c92e); + RNDr(S, W, 39, 0x92722c85); + RNDr(S, W, 40, 0xa2bfe8a1); + RNDr(S, W, 41, 0xa81a664b); + RNDr(S, W, 42, 0xc24b8b70); + RNDr(S, W, 43, 0xc76c51a3); + RNDr(S, W, 44, 0xd192e819); + RNDr(S, W, 45, 0xd6990624); + RNDr(S, W, 46, 0xf40e3585); + RNDr(S, W, 47, 0x106aa070); + RNDr(S, W, 48, 0x19a4c116); + RNDr(S, W, 49, 0x1e376c08); + RNDr(S, W, 50, 0x2748774c); + RNDr(S, W, 51, 0x34b0bcb5); + RNDr(S, W, 52, 0x391c0cb3); + RNDr(S, W, 53, 0x4ed8aa4a); + RNDr(S, W, 54, 0x5b9cca4f); + RNDr(S, W, 55, 0x682e6ff3); + RNDr(S, W, 56, 0x748f82ee); + RNDr(S, W, 57, 0x78a5636f); + RNDr(S, W, 58, 0x84c87814); + RNDr(S, W, 59, 0x8cc70208); + RNDr(S, W, 60, 0x90befffa); + RNDr(S, W, 61, 0xa4506ceb); + RNDr(S, W, 62, 0xbef9a3f7); + RNDr(S, W, 63, 0xc67178f2); + + /* 4. Mix local working variables into global state */ + for (i = 0; i < 8; i++) + state[i] += S[i]; + + /* Clean the stack. */ + memset(W, 0, 256); + memset(S, 0, 32); + t0 = t1 = 0; } static unsigned char PAD[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* Add padding and terminating bit-count. */ -static void -SHA256_Pad(SHA256_CTX * ctx) +static void SHA256_Pad(SHA256_CTX *ctx) { - unsigned char len[8]; - uint32_t r, plen; - - /* - * Convert length to a vector of bytes -- we do this now rather - * than later because the length will change after we pad. - */ - be32enc_vect(len, ctx->count, 8); - - /* Add 1--64 bytes so that the resulting length is 56 mod 64 */ - r = (ctx->count[1] >> 3) & 0x3f; - plen = (r < 56) ? (56 - r) : (120 - r); - SHA256_Update(ctx, PAD, (size_t)plen); - - /* Add the terminating bit-count */ - SHA256_Update(ctx, len, 8); + unsigned char len[8]; + uint32_t r, plen; + + /* + * Convert length to a vector of bytes -- we do this now rather + * than later because the length will change after we pad. + */ + be32enc_vect(len, ctx->count, 8); + + /* Add 1--64 bytes so that the resulting length is 56 mod 64 */ + r = (ctx->count[1] >> 3) & 0x3f; + plen = (r < 56) ? (56 - r) : (120 - r); + SHA256_Update(ctx, PAD, (size_t)plen); + + /* Add the terminating bit-count */ + SHA256_Update(ctx, len, 8); } /* SHA-256 initialization. Begins a SHA-256 operation. */ -void -SHA256_Init(SHA256_CTX * ctx) +void SHA256_Init(SHA256_CTX *ctx) { - /* Zero bits processed so far */ - ctx->count[0] = ctx->count[1] = 0; - - /* Magic initialization constants */ - ctx->state[0] = 0x6A09E667; - ctx->state[1] = 0xBB67AE85; - ctx->state[2] = 0x3C6EF372; - ctx->state[3] = 0xA54FF53A; - ctx->state[4] = 0x510E527F; - ctx->state[5] = 0x9B05688C; - ctx->state[6] = 0x1F83D9AB; - ctx->state[7] = 0x5BE0CD19; + /* Zero bits processed so far */ + ctx->count[0] = ctx->count[1] = 0; + + /* Magic initialization constants */ + ctx->state[0] = 0x6A09E667; + ctx->state[1] = 0xBB67AE85; + ctx->state[2] = 0x3C6EF372; + ctx->state[3] = 0xA54FF53A; + ctx->state[4] = 0x510E527F; + ctx->state[5] = 0x9B05688C; + ctx->state[6] = 0x1F83D9AB; + ctx->state[7] = 0x5BE0CD19; } /* Add bytes into the hash */ -void -SHA256_Update(SHA256_CTX * ctx, const void *in, size_t len) +void SHA256_Update(SHA256_CTX *ctx, const void *in, size_t len) { - uint32_t bitlen[2]; - uint32_t r; - const unsigned char *src = in; - - /* Number of bytes left in the buffer from previous updates */ - r = (ctx->count[1] >> 3) & 0x3f; - - /* Convert the length into a number of bits */ - bitlen[1] = ((uint32_t)len) << 3; - bitlen[0] = (uint32_t)(len >> 29); - - /* Update number of bits */ - if ((ctx->count[1] += bitlen[1]) < bitlen[1]) - ctx->count[0]++; - ctx->count[0] += bitlen[0]; - - /* Handle the case where we don't need to perform any transforms */ - if (len < 64 - r) { - memcpy(&ctx->buf[r], src, len); - return; - } - - /* Finish the current block */ - memcpy(&ctx->buf[r], src, 64 - r); - SHA256_Transform(ctx->state, ctx->buf); - src += 64 - r; - len -= 64 - r; - - /* Perform complete blocks */ - while (len >= 64) { - SHA256_Transform(ctx->state, src); - src += 64; - len -= 64; - } - - /* Copy left over data into buffer */ - memcpy(ctx->buf, src, len); + uint32_t bitlen[2]; + uint32_t r; + const unsigned char *src = in; + + /* Number of bytes left in the buffer from previous updates */ + r = (ctx->count[1] >> 3) & 0x3f; + + /* Convert the length into a number of bits */ + bitlen[1] = ((uint32_t)len) << 3; + bitlen[0] = (uint32_t)(len >> 29); + + /* Update number of bits */ + if ((ctx->count[1] += bitlen[1]) < bitlen[1]) + ctx->count[0]++; + ctx->count[0] += bitlen[0]; + + /* Handle the case where we don't need to perform any transforms */ + if (len < 64 - r) { + memcpy(&ctx->buf[r], src, len); + return; + } + + /* Finish the current block */ + memcpy(&ctx->buf[r], src, 64 - r); + SHA256_Transform(ctx->state, ctx->buf); + src += 64 - r; + len -= 64 - r; + + /* Perform complete blocks */ + while (len >= 64) { + SHA256_Transform(ctx->state, src); + src += 64; + len -= 64; + } + + /* Copy left over data into buffer */ + memcpy(ctx->buf, src, len); } /* * SHA-256 finalization. Pads the input data, exports the hash value, * and clears the context state. */ -void -SHA256_Final(unsigned char digest[32], SHA256_CTX * ctx) +void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx) { - /* Add padding */ - SHA256_Pad(ctx); + /* Add padding */ + SHA256_Pad(ctx); - /* Write the hash */ - be32enc_vect(digest, ctx->state, 32); + /* Write the hash */ + be32enc_vect(digest, ctx->state, 32); - /* Clear the context state */ - memset((void *)ctx, 0, sizeof(*ctx)); + /* Clear the context state */ + memset((void *)ctx, 0, sizeof(*ctx)); } /* Initialize an HMAC-SHA256 operation with the given key. */ -void -HMAC__SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen) +void HMAC__SHA256_Init(HMAC_SHA256_CTX *ctx, const void *_K, size_t Klen) { - unsigned char pad[64]; - unsigned char khash[32]; - const unsigned char * K = _K; - size_t i; - - /* If Klen > 64, the key is really SHA256(K). */ - if (Klen > 64) { - SHA256_Init(&ctx->ictx); - SHA256_Update(&ctx->ictx, K, Klen); - SHA256_Final(khash, &ctx->ictx); - K = khash; - Klen = 32; - } - - /* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */ - SHA256_Init(&ctx->ictx); - memset(pad, 0x36, 64); - for (i = 0; i < Klen; i++) - pad[i] ^= K[i]; - SHA256_Update(&ctx->ictx, pad, 64); - - /* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */ - SHA256_Init(&ctx->octx); - memset(pad, 0x5c, 64); - for (i = 0; i < Klen; i++) - pad[i] ^= K[i]; - SHA256_Update(&ctx->octx, pad, 64); - - /* Clean the stack. */ - memset(khash, 0, 32); + unsigned char pad[64]; + unsigned char khash[32]; + const unsigned char *K = _K; + size_t i; + + /* If Klen > 64, the key is really SHA256(K). */ + if (Klen > 64) { + SHA256_Init(&ctx->ictx); + SHA256_Update(&ctx->ictx, K, Klen); + SHA256_Final(khash, &ctx->ictx); + K = khash; + Klen = 32; + } + + /* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */ + SHA256_Init(&ctx->ictx); + memset(pad, 0x36, 64); + for (i = 0; i < Klen; i++) + pad[i] ^= K[i]; + SHA256_Update(&ctx->ictx, pad, 64); + + /* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */ + SHA256_Init(&ctx->octx); + memset(pad, 0x5c, 64); + for (i = 0; i < Klen; i++) + pad[i] ^= K[i]; + SHA256_Update(&ctx->octx, pad, 64); + + /* Clean the stack. */ + memset(khash, 0, 32); } /* Add bytes to the HMAC-SHA256 operation. */ -void -HMAC__SHA256_Update(HMAC_SHA256_CTX * ctx, const void *in, size_t len) +void HMAC__SHA256_Update(HMAC_SHA256_CTX *ctx, const void *in, size_t len) { - /* Feed data to the inner SHA256 operation. */ - SHA256_Update(&ctx->ictx, in, len); + /* Feed data to the inner SHA256 operation. */ + SHA256_Update(&ctx->ictx, in, len); } /* Finish an HMAC-SHA256 operation. */ -void -HMAC__SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX * ctx) +void HMAC__SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX *ctx) { - unsigned char ihash[32]; + unsigned char ihash[32]; - /* Finish the inner SHA256 operation. */ - SHA256_Final(ihash, &ctx->ictx); + /* Finish the inner SHA256 operation. */ + SHA256_Final(ihash, &ctx->ictx); - /* Feed the inner hash to the outer SHA256 operation. */ - SHA256_Update(&ctx->octx, ihash, 32); + /* Feed the inner hash to the outer SHA256 operation. */ + SHA256_Update(&ctx->octx, ihash, 32); - /* Finish the outer SHA256 operation. */ - SHA256_Final(digest, &ctx->octx); + /* Finish the outer SHA256 operation. */ + SHA256_Final(digest, &ctx->octx); - /* Clean the stack. */ - memset(ihash, 0, 32); + /* Clean the stack. */ + memset(ihash, 0, 32); } /** @@ -380,54 +364,53 @@ HMAC__SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX * ctx) * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). */ -void -PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, - size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen) +void PBKDF2_SHA256(const uint8_t *passwd, size_t passwdlen, const uint8_t *salt, + size_t saltlen, uint64_t c, uint8_t *buf, size_t dkLen) { - HMAC_SHA256_CTX PShctx, hctx; - size_t i; - uint8_t ivec[4]; - uint8_t U[32]; - uint8_t T[32]; - uint64_t j; - int k; - size_t clen; - - /* Compute HMAC state after processing P and S. */ - HMAC__SHA256_Init(&PShctx, passwd, passwdlen); - HMAC__SHA256_Update(&PShctx, salt, saltlen); - - /* Iterate through the blocks. */ - for (i = 0; i * 32 < dkLen; i++) { - /* Generate INT(i + 1). */ - be32enc(ivec, (uint32_t)(i + 1)); - - /* Compute U_1 = PRF(P, S || INT(i)). */ - memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX)); - HMAC__SHA256_Update(&hctx, ivec, 4); - HMAC__SHA256_Final(U, &hctx); - - /* T_i = U_1 ... */ - memcpy(T, U, 32); - - for (j = 2; j <= c; j++) { - /* Compute U_j. */ - HMAC__SHA256_Init(&hctx, passwd, passwdlen); - HMAC__SHA256_Update(&hctx, U, 32); - HMAC__SHA256_Final(U, &hctx); - - /* ... xor U_j ... */ - for (k = 0; k < 32; k++) - T[k] ^= U[k]; - } - - /* Copy as many bytes as necessary into buf. */ - clen = dkLen - i * 32; - if (clen > 32) - clen = 32; - memcpy(&buf[i * 32], T, clen); - } - - /* Clean PShctx, since we never called _Final on it. */ - memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX)); + HMAC_SHA256_CTX PShctx, hctx; + size_t i; + uint8_t ivec[4]; + uint8_t U[32]; + uint8_t T[32]; + uint64_t j; + int k; + size_t clen; + + /* Compute HMAC state after processing P and S. */ + HMAC__SHA256_Init(&PShctx, passwd, passwdlen); + HMAC__SHA256_Update(&PShctx, salt, saltlen); + + /* Iterate through the blocks. */ + for (i = 0; i * 32 < dkLen; i++) { + /* Generate INT(i + 1). */ + be32enc(ivec, (uint32_t)(i + 1)); + + /* Compute U_1 = PRF(P, S || INT(i)). */ + memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX)); + HMAC__SHA256_Update(&hctx, ivec, 4); + HMAC__SHA256_Final(U, &hctx); + + /* T_i = U_1 ... */ + memcpy(T, U, 32); + + for (j = 2; j <= c; j++) { + /* Compute U_j. */ + HMAC__SHA256_Init(&hctx, passwd, passwdlen); + HMAC__SHA256_Update(&hctx, U, 32); + HMAC__SHA256_Final(U, &hctx); + + /* ... xor U_j ... */ + for (k = 0; k < 32; k++) + T[k] ^= U[k]; + } + + /* Copy as many bytes as necessary into buf. */ + clen = dkLen - i * 32; + if (clen > 32) + clen = 32; + memcpy(&buf[i * 32], T, clen); + } + + /* Clean PShctx, since we never called _Final on it. */ + memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX)); } diff --git a/lib/sha256.h b/lib/sha256.h index 502f3fc22..2473da7bd 100644 --- a/lib/sha256.h +++ b/lib/sha256.h @@ -30,29 +30,29 @@ #define _SHA256_H_ typedef struct SHA256Context { - uint32_t state[8]; - uint32_t count[2]; - unsigned char buf[64]; + uint32_t state[8]; + uint32_t count[2]; + unsigned char buf[64]; } SHA256_CTX; typedef struct HMAC_SHA256Context { - SHA256_CTX ictx; - SHA256_CTX octx; + SHA256_CTX ictx; + SHA256_CTX octx; } HMAC_SHA256_CTX; -void SHA256_Init(SHA256_CTX *); -void SHA256_Update(SHA256_CTX *, const void *, size_t); -void SHA256_Final(unsigned char [32], SHA256_CTX *); -void HMAC__SHA256_Init(HMAC_SHA256_CTX *, const void *, size_t); -void HMAC__SHA256_Update(HMAC_SHA256_CTX *, const void *, size_t); -void HMAC__SHA256_Final(unsigned char [32], HMAC_SHA256_CTX *); +void SHA256_Init(SHA256_CTX *); +void SHA256_Update(SHA256_CTX *, const void *, size_t); +void SHA256_Final(unsigned char[32], SHA256_CTX *); +void HMAC__SHA256_Init(HMAC_SHA256_CTX *, const void *, size_t); +void HMAC__SHA256_Update(HMAC_SHA256_CTX *, const void *, size_t); +void HMAC__SHA256_Final(unsigned char[32], HMAC_SHA256_CTX *); /** * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). */ -void PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t, - uint64_t, uint8_t *, size_t); +void PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t, + uint8_t *, size_t); #endif /* !_SHA256_H_ */ diff --git a/lib/sigevent.c b/lib/sigevent.c index e8c722b98..2a04fa23c 100644 --- a/lib/sigevent.c +++ b/lib/sigevent.c @@ -37,349 +37,331 @@ /* master signals descriptor struct */ -struct quagga_sigevent_master_t -{ - struct thread *t; +struct quagga_sigevent_master_t { + struct thread *t; + + struct quagga_signal_t *signals; + int sigc; - struct quagga_signal_t *signals; - int sigc; - - volatile sig_atomic_t caught; + volatile sig_atomic_t caught; } sigmaster; -/* Generic signal handler +/* Generic signal handler * Schedules signal event thread */ -static void -quagga_signal_handler (int signo) +static void quagga_signal_handler(int signo) { - int i; - struct quagga_signal_t *sig; - - for (i = 0; i < sigmaster.sigc; i++) - { - sig = &(sigmaster.signals[i]); - - if (sig->signal == signo) - sig->caught = 1; - } - - sigmaster.caught = 1; -} + int i; + struct quagga_signal_t *sig; + + for (i = 0; i < sigmaster.sigc; i++) { + sig = &(sigmaster.signals[i]); + + if (sig->signal == signo) + sig->caught = 1; + } + + sigmaster.caught = 1; +} /* check if signals have been caught and run appropriate handlers */ -int -quagga_sigevent_process (void) +int quagga_sigevent_process(void) { - struct quagga_signal_t *sig; - int i; + struct quagga_signal_t *sig; + int i; #ifdef SIGEVENT_BLOCK_SIGNALS - /* shouldnt need to block signals, but potentially may be needed */ - sigset_t newmask, oldmask; - - /* - * Block most signals, but be careful not to defer SIGTRAP because - * doing so breaks gdb, at least on NetBSD 2.0. Avoid asking to - * block SIGKILL, just because we shouldn't be able to do so. - */ - sigfillset (&newmask); - sigdelset (&newmask, SIGTRAP); - sigdelset (&newmask, SIGKILL); - - if ( (sigprocmask (SIG_BLOCK, &newmask, &oldmask)) < 0) - { - zlog_err ("quagga_signal_timer: couldnt block signals!"); - return -1; - } + /* shouldnt need to block signals, but potentially may be needed */ + sigset_t newmask, oldmask; + + /* + * Block most signals, but be careful not to defer SIGTRAP because + * doing so breaks gdb, at least on NetBSD 2.0. Avoid asking to + * block SIGKILL, just because we shouldn't be able to do so. + */ + sigfillset(&newmask); + sigdelset(&newmask, SIGTRAP); + sigdelset(&newmask, SIGKILL); + + if ((sigprocmask(SIG_BLOCK, &newmask, &oldmask)) < 0) { + zlog_err("quagga_signal_timer: couldnt block signals!"); + return -1; + } #endif /* SIGEVENT_BLOCK_SIGNALS */ - if (sigmaster.caught > 0) - { - sigmaster.caught = 0; - /* must not read or set sigmaster.caught after here, - * race condition with per-sig caught flags if one does - */ - - for (i = 0; i < sigmaster.sigc; i++) - { - sig = &(sigmaster.signals[i]); - - if (sig->caught > 0) - { - sig->caught = 0; - if (sig->handler) - sig->handler (); - } - } - } + if (sigmaster.caught > 0) { + sigmaster.caught = 0; + /* must not read or set sigmaster.caught after here, + * race condition with per-sig caught flags if one does + */ + + for (i = 0; i < sigmaster.sigc; i++) { + sig = &(sigmaster.signals[i]); + + if (sig->caught > 0) { + sig->caught = 0; + if (sig->handler) + sig->handler(); + } + } + } #ifdef SIGEVENT_BLOCK_SIGNALS - if ( sigprocmask (SIG_UNBLOCK, &oldmask, NULL) < 0 ); - return -1; + if (sigprocmask(SIG_UNBLOCK, &oldmask, NULL) < 0) + ; + return -1; #endif /* SIGEVENT_BLOCK_SIGNALS */ - return 0; + return 0; } #ifdef SIGEVENT_SCHEDULE_THREAD /* timer thread to check signals. Shouldnt be needed */ -int -quagga_signal_timer (struct thread *t) +int quagga_signal_timer(struct thread *t) { - struct quagga_sigevent_master_t *sigm; - struct quagga_signal_t *sig; - int i; - - sigm = THREAD_ARG (t); - sigm->t = NULL; - thread_add_timer(sigm->t->master, quagga_signal_timer, &sigmaster, QUAGGA_SIGNAL_TIMER_INTERVAL, - &sigm->t); - return quagga_sigevent_process (); + struct quagga_sigevent_master_t *sigm; + struct quagga_signal_t *sig; + int i; + + sigm = THREAD_ARG(t); + sigm->t = NULL; + thread_add_timer(sigm->t->master, quagga_signal_timer, &sigmaster, + QUAGGA_SIGNAL_TIMER_INTERVAL, &sigm->t); + return quagga_sigevent_process(); } #endif /* SIGEVENT_SCHEDULE_THREAD */ /* Initialization of signal handles. */ /* Signal wrapper. */ -static int -signal_set (int signo) +static int signal_set(int signo) { - int ret; - struct sigaction sig; - struct sigaction osig; - - sig.sa_handler = &quagga_signal_handler; - sigfillset (&sig.sa_mask); - sig.sa_flags = 0; - if (signo == SIGALRM) { + int ret; + struct sigaction sig; + struct sigaction osig; + + sig.sa_handler = &quagga_signal_handler; + sigfillset(&sig.sa_mask); + sig.sa_flags = 0; + if (signo == SIGALRM) { #ifdef SA_INTERRUPT - sig.sa_flags |= SA_INTERRUPT; /* SunOS */ + sig.sa_flags |= SA_INTERRUPT; /* SunOS */ #endif - } else { + } else { #ifdef SA_RESTART - sig.sa_flags |= SA_RESTART; + sig.sa_flags |= SA_RESTART; #endif /* SA_RESTART */ - } + } - ret = sigaction (signo, &sig, &osig); - if (ret < 0) - return ret; - else - return 0; + ret = sigaction(signo, &sig, &osig); + if (ret < 0) + return ret; + else + return 0; } #ifdef SA_SIGINFO /* XXX This function should be enhanced to support more platforms (it currently works only on Linux/x86). */ -static void * -program_counter(void *context) +static void *program_counter(void *context) { #ifdef HAVE_UCONTEXT_H #ifdef GNU_LINUX - /* these are from GNU libc, rather than Linux, strictly speaking */ -# if defined(REG_EIP) +/* these are from GNU libc, rather than Linux, strictly speaking */ +#if defined(REG_EIP) # define REG_INDEX REG_EIP -# elif defined(REG_RIP) +#elif defined(REG_RIP) # define REG_INDEX REG_RIP -# elif defined(__powerpc__) +#elif defined(__powerpc__) # define REG_INDEX 32 -# endif +#endif #elif defined(SUNOS_5) /* !GNU_LINUX */ # define REG_INDEX REG_PC -#endif /* GNU_LINUX */ +#endif /* GNU_LINUX */ #ifdef REG_INDEX -# ifdef HAVE_UCONTEXT_T_UC_MCONTEXT_GREGS +#ifdef HAVE_UCONTEXT_T_UC_MCONTEXT_GREGS # define REGS gregs[REG_INDEX] -# elif defined(HAVE_UCONTEXT_T_UC_MCONTEXT_UC_REGS) +#elif defined(HAVE_UCONTEXT_T_UC_MCONTEXT_UC_REGS) # define REGS uc_regs->gregs[REG_INDEX] -# endif /* HAVE_UCONTEXT_T_UC_MCONTEXT_GREGS */ +#endif /* HAVE_UCONTEXT_T_UC_MCONTEXT_GREGS */ #endif /* REG_INDEX */ #ifdef REGS - if (context) - return (void *)(((ucontext_t *)context)->uc_mcontext.REGS); -#elif defined(HAVE_UCONTEXT_T_UC_MCONTEXT_REGS__NIP) - /* older Linux / struct pt_regs ? */ - if (context) - return (void *)(((ucontext_t *)context)->uc_mcontext.regs->nip); + if (context) + return (void *)(((ucontext_t *)context)->uc_mcontext.REGS); +#elif defined(HAVE_UCONTEXT_T_UC_MCONTEXT_REGS__NIP) + /* older Linux / struct pt_regs ? */ + if (context) + return (void *)(((ucontext_t *)context)->uc_mcontext.regs->nip); #endif /* REGS */ #endif /* HAVE_UCONTEXT_H */ - return NULL; + return NULL; } #endif /* SA_SIGINFO */ -static void __attribute__ ((noreturn)) +static void __attribute__((noreturn)) exit_handler(int signo #ifdef SA_SIGINFO - , siginfo_t *siginfo, void *context + , + siginfo_t *siginfo, void *context #endif - ) + ) { - zlog_signal(signo, "exiting..." + zlog_signal(signo, "exiting..." #ifdef SA_SIGINFO - , siginfo, program_counter(context) + , + siginfo, program_counter(context) #endif - ); - _exit(128+signo); + ); + _exit(128 + signo); } -static void __attribute__ ((noreturn)) +static void __attribute__((noreturn)) core_handler(int signo #ifdef SA_SIGINFO - , siginfo_t *siginfo, void *context + , + siginfo_t *siginfo, void *context #endif - ) + ) { - /* make sure we don't hang in here. default for SIGALRM is terminate. - * - if we're in backtrace for more than a second, abort. */ - struct sigaction sa_default = { .sa_handler = SIG_DFL }; - sigaction (SIGALRM, &sa_default, NULL); + /* make sure we don't hang in here. default for SIGALRM is terminate. + * - if we're in backtrace for more than a second, abort. */ + struct sigaction sa_default = {.sa_handler = SIG_DFL}; + sigaction(SIGALRM, &sa_default, NULL); - sigset_t sigset; - sigemptyset (&sigset); - sigaddset (&sigset, SIGALRM); - sigprocmask (SIG_UNBLOCK, &sigset, NULL); + sigset_t sigset; + sigemptyset(&sigset); + sigaddset(&sigset, SIGALRM); + sigprocmask(SIG_UNBLOCK, &sigset, NULL); - alarm (1); + alarm(1); - zlog_signal(signo, "aborting..." + zlog_signal(signo, "aborting..." #ifdef SA_SIGINFO - , siginfo, program_counter(context) + , + siginfo, program_counter(context) #endif - ); - /* dump memory stats on core */ - log_memstats_stderr ("core_handler"); - abort(); + ); + /* dump memory stats on core */ + log_memstats_stderr("core_handler"); + abort(); } -static void -trap_default_signals(void) +static void trap_default_signals(void) { - static const int core_signals[] = { - SIGQUIT, - SIGILL, + static const int core_signals[] = { + SIGQUIT, SIGILL, #ifdef SIGEMT - SIGEMT, + SIGEMT, #endif - SIGFPE, - SIGBUS, - SIGSEGV, + SIGFPE, SIGBUS, SIGSEGV, #ifdef SIGSYS - SIGSYS, + SIGSYS, #endif #ifdef SIGXCPU - SIGXCPU, + SIGXCPU, #endif #ifdef SIGXFSZ - SIGXFSZ, + SIGXFSZ, #endif - }; - static const int exit_signals[] = { - SIGHUP, - SIGINT, - SIGALRM, - SIGTERM, - SIGUSR1, - SIGUSR2, + }; + static const int exit_signals[] = { + SIGHUP, SIGINT, SIGALRM, SIGTERM, SIGUSR1, SIGUSR2, #ifdef SIGPOLL - SIGPOLL, + SIGPOLL, #endif #ifdef SIGVTALRM - SIGVTALRM, + SIGVTALRM, #endif #ifdef SIGSTKFLT - SIGSTKFLT, + SIGSTKFLT, #endif - }; - static const int ignore_signals[] = { - SIGPIPE, - }; - static const struct { - const int *sigs; - u_int nsigs; - void (*handler)(int signo + }; + static const int ignore_signals[] = { + SIGPIPE, + }; + static const struct { + const int *sigs; + u_int nsigs; + void (*handler)(int signo #ifdef SA_SIGINFO - , siginfo_t *info, void *context + , + siginfo_t *info, void *context #endif - ); - } sigmap[] = { - { core_signals, array_size(core_signals), core_handler}, - { exit_signals, array_size(exit_signals), exit_handler}, - { ignore_signals, array_size(ignore_signals), NULL}, - }; - u_int i; - - for (i = 0; i < array_size(sigmap); i++) - { - u_int j; - - for (j = 0; j < sigmap[i].nsigs; j++) - { - struct sigaction oact; - if ((sigaction(sigmap[i].sigs[j],NULL,&oact) == 0) && - (oact.sa_handler == SIG_DFL)) - { - struct sigaction act; - sigfillset (&act.sa_mask); - if (sigmap[i].handler == NULL) - { - act.sa_handler = SIG_IGN; - act.sa_flags = 0; - } - else - { + ); + } sigmap[] = { + {core_signals, array_size(core_signals), core_handler}, + {exit_signals, array_size(exit_signals), exit_handler}, + {ignore_signals, array_size(ignore_signals), NULL}, + }; + u_int i; + + for (i = 0; i < array_size(sigmap); i++) { + u_int j; + + for (j = 0; j < sigmap[i].nsigs; j++) { + struct sigaction oact; + if ((sigaction(sigmap[i].sigs[j], NULL, &oact) == 0) + && (oact.sa_handler == SIG_DFL)) { + struct sigaction act; + sigfillset(&act.sa_mask); + if (sigmap[i].handler == NULL) { + act.sa_handler = SIG_IGN; + act.sa_flags = 0; + } else { #ifdef SA_SIGINFO - /* Request extra arguments to signal handler. */ - act.sa_sigaction = sigmap[i].handler; - act.sa_flags = SA_SIGINFO; + /* Request extra arguments to signal + * handler. */ + act.sa_sigaction = sigmap[i].handler; + act.sa_flags = SA_SIGINFO; #else - act.sa_handler = sigmap[i].handler; - act.sa_flags = 0; + act.sa_handler = sigmap[i].handler; + act.sa_flags = 0; #endif #ifdef SA_RESETHAND - /* don't try to print backtraces recursively */ - if (sigmap[i].handler == core_handler) - act.sa_flags |= SA_RESETHAND; + /* don't try to print backtraces + * recursively */ + if (sigmap[i].handler == core_handler) + act.sa_flags |= SA_RESETHAND; #endif - } - if (sigaction(sigmap[i].sigs[j],&act,NULL) < 0) - zlog_warn("Unable to set signal handler for signal %d: %s", - sigmap[i].sigs[j],safe_strerror(errno)); - - } - } - } + } + if (sigaction(sigmap[i].sigs[j], &act, NULL) + < 0) + zlog_warn( + "Unable to set signal handler for signal %d: %s", + sigmap[i].sigs[j], + safe_strerror(errno)); + } + } + } } -void -signal_init (struct thread_master *m, int sigc, - struct quagga_signal_t signals[]) +void signal_init(struct thread_master *m, int sigc, + struct quagga_signal_t signals[]) { - int i = 0; - struct quagga_signal_t *sig; - - /* First establish some default handlers that can be overridden by - the application. */ - trap_default_signals(); - - while (i < sigc) - { - sig = &signals[i]; - if ( signal_set (sig->signal) < 0 ) - exit (-1); - i++; - } - - sigmaster.sigc = sigc; - sigmaster.signals = signals; - -#ifdef SIGEVENT_SCHEDULE_THREAD - sigmaster.t = NULL; - thread_add_timer(m, quagga_signal_timer, &sigmaster, QUAGGA_SIGNAL_TIMER_INTERVAL, - &sigmaster.t); + int i = 0; + struct quagga_signal_t *sig; + + /* First establish some default handlers that can be overridden by + the application. */ + trap_default_signals(); + + while (i < sigc) { + sig = &signals[i]; + if (signal_set(sig->signal) < 0) + exit(-1); + i++; + } + + sigmaster.sigc = sigc; + sigmaster.signals = signals; + +#ifdef SIGEVENT_SCHEDULE_THREAD + sigmaster.t = NULL; + thread_add_timer(m, quagga_signal_timer, &sigmaster, + QUAGGA_SIGNAL_TIMER_INTERVAL, &sigmaster.t); #endif /* SIGEVENT_SCHEDULE_THREAD */ } diff --git a/lib/sigevent.h b/lib/sigevent.h index 08eb1ca41..d4ab5741a 100644 --- a/lib/sigevent.h +++ b/lib/sigevent.h @@ -1,4 +1,4 @@ -/* +/* * Quagga Signal handling header. * * Copyright (C) 2004 Paul Jakma. @@ -27,12 +27,11 @@ #define QUAGGA_SIGNAL_TIMER_INTERVAL 2L -struct quagga_signal_t -{ - int signal; /* signal number */ - void (*handler) (void); /* handler to call */ +struct quagga_signal_t { + int signal; /* signal number */ + void (*handler)(void); /* handler to call */ - volatile sig_atomic_t caught; /* private member */ + volatile sig_atomic_t caught; /* private member */ }; /* initialise sigevent system @@ -42,10 +41,10 @@ struct quagga_signal_t * - array of quagga_signal_t's describing signals to handle * and handlers to use for each signal */ -extern void signal_init (struct thread_master *m, int sigc, - struct quagga_signal_t *signals); +extern void signal_init(struct thread_master *m, int sigc, + struct quagga_signal_t *signals); /* check whether there are signals to handle, process any found */ -extern int quagga_sigevent_process (void); +extern int quagga_sigevent_process(void); #endif /* _QUAGGA_SIGNAL_H */ diff --git a/lib/skiplist.c b/lib/skiplist.c index fd772b64c..7acc78f56 100644 --- a/lib/skiplist.c +++ b/lib/skiplist.c @@ -1,5 +1,5 @@ /* - * Copyright 1990 William Pugh + * Copyright 1990 William Pugh * * Redistribution and use in source and binary forms, with or without * modification, are permitted. @@ -23,34 +23,34 @@ /* * Skip List impementation based on code from William Pugh. * ftp://ftp.cs.umd.edu/pub/skipLists/ - * + * * Skip Lists are a probabilistic alternative to balanced trees, as - * described in the June 1990 issue of CACM and were invented by - * William Pugh in 1987. - * - * This file contains source code to implement a dictionary using + * described in the June 1990 issue of CACM and were invented by + * William Pugh in 1987. + * + * This file contains source code to implement a dictionary using * skip lists and a test driver to test the routines. - * + * * A couple of comments about this implementation: * The routine randomLevel has been hard-coded to generate random * levels using p=0.25. It can be easily changed. - * + * * The insertion routine has been implemented so as to use the * dirty hack described in the CACM paper: if a random level is * generated that is more than the current maximum level, the * current maximum level plus one is used instead. - * + * * Levels start at zero and go up to MaxLevel (which is equal to * (MaxNumberOfLevels-1). - * + * * The run-time flag SKIPLIST_FLAG_ALLOW_DUPLICATES determines whether or * not duplicates are allowed for a given list. If set, duplicates are * allowed and act in a FIFO manner. If not set, an insertion of a value * already in the list updates the previously existing binding. - * + * * BitsInRandom is defined to be the number of bits returned by a call to * random(). For most all machines with 32-bit integers, this is 31 bits - * as currently set. + * as currently set. */ @@ -61,7 +61,7 @@ #include "vty.h" #include "skiplist.h" -DEFINE_MTYPE_STATIC(LIB, SKIP_LIST, "Skip List") +DEFINE_MTYPE_STATIC(LIB, SKIP_LIST, "Skip List") DEFINE_MTYPE_STATIC(LIB, SKIP_LIST_NODE, "Skip Node") #define BitsInRandom 31 @@ -72,256 +72,251 @@ DEFINE_MTYPE_STATIC(LIB, SKIP_LIST_NODE, "Skip Node") static int randomsLeft; static int randomBits; -static struct skiplist *skiplist_last_created; /* debugging hack */ +static struct skiplist *skiplist_last_created; /* debugging hack */ #if 1 -#define CHECKLAST(sl) do {\ - if ((sl)->header->forward[0] && !(sl)->last) assert(0); \ - if (!(sl)->header->forward[0] && (sl)->last) assert(0); \ -} while (0) +#define CHECKLAST(sl) \ + do { \ + if ((sl)->header->forward[0] && !(sl)->last) \ + assert(0); \ + if (!(sl)->header->forward[0] && (sl)->last) \ + assert(0); \ + } while (0) #else #define CHECKLAST(sl) #endif -static int -randomLevel() +static int randomLevel() { - register int level = 0; - register int b; + register int level = 0; + register int b; - do { - if (randomsLeft <= 0) { - randomBits = random(); - randomsLeft = BitsInRandom/2; - } - b = randomBits&3; - randomBits>>=2; - --randomsLeft; - - if (!b) { - level++; - if (level >= MaxLevel) - return MaxLevel; - } - } while (!b); - - return level; + do { + if (randomsLeft <= 0) { + randomBits = random(); + randomsLeft = BitsInRandom / 2; + } + b = randomBits & 3; + randomBits >>= 2; + --randomsLeft; + + if (!b) { + level++; + if (level >= MaxLevel) + return MaxLevel; + } + } while (!b); + + return level; } -static int -default_cmp(void *key1, void *key2) +static int default_cmp(void *key1, void *key2) { - if (key1 < key2) - return -1; - if (key1 > key2) - return 1; - return 0; + if (key1 < key2) + return -1; + if (key1 > key2) + return 1; + return 0; } -unsigned int -skiplist_count(struct skiplist *l) +unsigned int skiplist_count(struct skiplist *l) { - return l->count; + return l->count; } -struct skiplist * -skiplist_new( - int flags, - int (*cmp) (void *key1, void *key2), - void (*del) (void *val)) +struct skiplist *skiplist_new(int flags, int (*cmp)(void *key1, void *key2), + void (*del)(void *val)) { - struct skiplist *new; + struct skiplist *new; - new = XCALLOC (MTYPE_SKIP_LIST, sizeof (struct skiplist)); - assert(new); + new = XCALLOC(MTYPE_SKIP_LIST, sizeof(struct skiplist)); + assert(new); - new->level = 0; - new->count = 0; - new->header = newNodeOfLevel(MaxNumberOfLevels); - new->stats = newNodeOfLevel(MaxNumberOfLevels); + new->level = 0; + new->count = 0; + new->header = newNodeOfLevel(MaxNumberOfLevels); + new->stats = newNodeOfLevel(MaxNumberOfLevels); - new->flags = flags; - if (cmp) - new->cmp = cmp; - else - new->cmp = default_cmp; + new->flags = flags; + if (cmp) + new->cmp = cmp; + else + new->cmp = default_cmp; - if (del) - new->del = del; + if (del) + new->del = del; - skiplist_last_created = new; /* debug */ + skiplist_last_created = new; /* debug */ - return new; + return new; } -void -skiplist_free(struct skiplist *l) +void skiplist_free(struct skiplist *l) { - register struct skiplistnode *p, *q; + register struct skiplistnode *p, *q; - p = l->header; + p = l->header; - do { - q = p->forward[0]; - if (l->del && p != l->header) - (*l->del)(p->value); - XFREE(MTYPE_SKIP_LIST_NODE, p); - p = q; - } while (p); + do { + q = p->forward[0]; + if (l->del && p != l->header) + (*l->del)(p->value); + XFREE(MTYPE_SKIP_LIST_NODE, p); + p = q; + } while (p); - XFREE(MTYPE_SKIP_LIST_NODE, l->stats); - XFREE(MTYPE_SKIP_LIST, l); + XFREE(MTYPE_SKIP_LIST_NODE, l->stats); + XFREE(MTYPE_SKIP_LIST, l); } -int -skiplist_insert( - register struct skiplist *l, - register void *key, - register void *value) +int skiplist_insert(register struct skiplist *l, register void *key, + register void *value) { - register int k; - struct skiplistnode *update[MaxNumberOfLevels]; - register struct skiplistnode *p, *q; - - CHECKLAST(l); - -/* DEBUG */ - if (!key) { - zlog_err("%s: key is 0, value is %p", __func__, value); - } - - p = l->header; - k = l->level; - do { - while (q = p->forward[k], q && (*l->cmp)(q->key, key) < 0) p = q; - update[k] = p; - } while (--k >= 0); - - if (!(l->flags & SKIPLIST_FLAG_ALLOW_DUPLICATES) && - q && ((*l->cmp)(q->key, key) == 0)) { - - return -1; - } - - k = randomLevel(); - if (k>l->level) { - k = ++l->level; - update[k] = l->header; - } - - q = newNodeOfLevel(k); - q->key = key; - q->value = value; + register int k; + struct skiplistnode *update[MaxNumberOfLevels]; + register struct skiplistnode *p, *q; + + CHECKLAST(l); + + /* DEBUG */ + if (!key) { + zlog_err("%s: key is 0, value is %p", __func__, value); + } + + p = l->header; + k = l->level; + do { + while (q = p->forward[k], q && (*l->cmp)(q->key, key) < 0) + p = q; + update[k] = p; + } while (--k >= 0); + + if (!(l->flags & SKIPLIST_FLAG_ALLOW_DUPLICATES) && q + && ((*l->cmp)(q->key, key) == 0)) { + + return -1; + } + + k = randomLevel(); + if (k > l->level) { + k = ++l->level; + update[k] = l->header; + } + + q = newNodeOfLevel(k); + q->key = key; + q->value = value; #if SKIPLIST_0TIMER_DEBUG - q->flags = SKIPLIST_NODE_FLAG_INSERTED; /* debug */ + q->flags = SKIPLIST_NODE_FLAG_INSERTED; /* debug */ #endif - ++(l->stats->forward[k]); + ++(l->stats->forward[k]); #if SKIPLIST_DEBUG - zlog_debug("%s: incremented stats @%p:%d, now %ld", __func__, l, k, - l->stats->forward[k] - (struct skiplistnode *)NULL); + zlog_debug("%s: incremented stats @%p:%d, now %ld", __func__, l, k, + l->stats->forward[k] - (struct skiplistnode *)NULL); #endif - do { - p = update[k]; - q->forward[k] = p->forward[k]; - p->forward[k] = q; - } while(--k>=0); + do { + p = update[k]; + q->forward[k] = p->forward[k]; + p->forward[k] = q; + } while (--k >= 0); - /* - * If this is the last item in the list, update the "last" pointer - */ - if (!q->forward[0]) { - l->last = q; - } + /* + * If this is the last item in the list, update the "last" pointer + */ + if (!q->forward[0]) { + l->last = q; + } - ++(l->count); + ++(l->count); - CHECKLAST(l); + CHECKLAST(l); - return 0; + return 0; } -int -skiplist_delete( - register struct skiplist *l, - register void *key, - register void *value) /* used only if duplicates allowed */ +int skiplist_delete(register struct skiplist *l, register void *key, + register void *value) /* used only if duplicates allowed */ { - register int k,m; - struct skiplistnode *update[MaxNumberOfLevels]; - register struct skiplistnode *p, *q; - - CHECKLAST(l); - - /* to make debugging easier */ - for (k = 0; k < MaxNumberOfLevels; ++k) - update[k] = NULL; - - p = l->header; - k = m = l->level; - do { - while (q = p->forward[k], q && (*l->cmp)(q->key, key) < 0) p = q; - update[k] = p; - } while(--k>=0); - - if (l->flags & SKIPLIST_FLAG_ALLOW_DUPLICATES) { - while (q && ((*l->cmp)(q->key, key) == 0) && (q->value != value)) { - int i; - for (i = 0; i <= l->level; ++i) { - if (update[i]->forward[i] == q) - update[i] = q; - } - q = q->forward[0]; + register int k, m; + struct skiplistnode *update[MaxNumberOfLevels]; + register struct skiplistnode *p, *q; + + CHECKLAST(l); + + /* to make debugging easier */ + for (k = 0; k < MaxNumberOfLevels; ++k) + update[k] = NULL; + + p = l->header; + k = m = l->level; + do { + while (q = p->forward[k], q && (*l->cmp)(q->key, key) < 0) + p = q; + update[k] = p; + } while (--k >= 0); + + if (l->flags & SKIPLIST_FLAG_ALLOW_DUPLICATES) { + while (q && ((*l->cmp)(q->key, key) == 0) + && (q->value != value)) { + int i; + for (i = 0; i <= l->level; ++i) { + if (update[i]->forward[i] == q) + update[i] = q; + } + q = q->forward[0]; + } } - } - if (q && (*l->cmp)(q->key, key) == 0) { - if (!(l->flags & SKIPLIST_FLAG_ALLOW_DUPLICATES) || - (q->value == value)) { + if (q && (*l->cmp)(q->key, key) == 0) { + if (!(l->flags & SKIPLIST_FLAG_ALLOW_DUPLICATES) + || (q->value == value)) { - /* - * found node to delete - */ +/* + * found node to delete + */ #if SKIPLIST_0TIMER_DEBUG - q->flags &= ~SKIPLIST_NODE_FLAG_INSERTED; + q->flags &= ~SKIPLIST_NODE_FLAG_INSERTED; #endif - /* - * If we are deleting the last element of the list, - * update the list's "last" pointer. - */ - if (l->last == q) { - if (update[0] == l->header) - l->last = NULL; - else - l->last = update[0]; - } - - for(k=0; k<=m && (p=update[k])->forward[k] == q; k++) { - p->forward[k] = q->forward[k]; - } - --(l->stats->forward[k-1]); + /* + * If we are deleting the last element of the list, + * update the list's "last" pointer. + */ + if (l->last == q) { + if (update[0] == l->header) + l->last = NULL; + else + l->last = update[0]; + } + + for (k = 0; k <= m && (p = update[k])->forward[k] == q; + k++) { + p->forward[k] = q->forward[k]; + } + --(l->stats->forward[k - 1]); #if SKIPLIST_DEBUG - zlog_debug("%s: decremented stats @%p:%d, now %ld", - __func__, l, k-1, - l->stats->forward[k-1] - (struct skiplistnode *)NULL); + zlog_debug("%s: decremented stats @%p:%d, now %ld", + __func__, l, k - 1, + l->stats->forward[k - 1] + - (struct skiplistnode *)NULL); #endif - if (l->del) - (*l->del)(q->value); - XFREE(MTYPE_SKIP_LIST_NODE, q); - while( l->header->forward[m] == NULL && m > 0 ) - m--; - l->level = m; - CHECKLAST(l); - --(l->count); - return 0; + if (l->del) + (*l->del)(q->value); + XFREE(MTYPE_SKIP_LIST_NODE, q); + while (l->header->forward[m] == NULL && m > 0) + m--; + l->level = m; + CHECKLAST(l); + --(l->count); + return 0; + } } - } - CHECKLAST(l); - return -1; + CHECKLAST(l); + return -1; } /* @@ -330,44 +325,39 @@ skiplist_delete( * * Also set a cursor for use with skiplist_next_value. */ -int -skiplist_first_value( - register struct skiplist *l, /* in */ - register void *key, /* in */ - void **valuePointer, /* out */ - void **cursor) /* out */ +int skiplist_first_value(register struct skiplist *l, /* in */ + register void *key, /* in */ + void **valuePointer, /* out */ + void **cursor) /* out */ { - register int k; - register struct skiplistnode *p, *q; + register int k; + register struct skiplistnode *p, *q; - p = l->header; - k = l->level; + p = l->header; + k = l->level; - do { - while (q = p->forward[k], q && (*l->cmp)(q->key, key) < 0) - p = q; + do { + while (q = p->forward[k], q && (*l->cmp)(q->key, key) < 0) + p = q; - } while (--k >= 0); + } while (--k >= 0); - if (!q || (*l->cmp)(q->key, key)) - return -1; + if (!q || (*l->cmp)(q->key, key)) + return -1; - if (valuePointer) - *valuePointer = q->value; + if (valuePointer) + *valuePointer = q->value; - if (cursor) - *cursor = q; + if (cursor) + *cursor = q; - return 0; + return 0; } -int -skiplist_search( - register struct skiplist *l, - register void *key, - void **valuePointer) +int skiplist_search(register struct skiplist *l, register void *key, + void **valuePointer) { - return skiplist_first_value(l, key, valuePointer, NULL); + return skiplist_first_value(l, key, valuePointer, NULL); } @@ -380,306 +370,294 @@ skiplist_search( * do not correspond to a list element, or if they specify the * last element with the given key, -1 is returned. */ -int -skiplist_next_value( - register struct skiplist *l, /* in */ - register void *key, /* in */ - void **valuePointer, /* in/out */ - void **cursor) /* in/out */ +int skiplist_next_value(register struct skiplist *l, /* in */ + register void *key, /* in */ + void **valuePointer, /* in/out */ + void **cursor) /* in/out */ { - register int k,m; - register struct skiplistnode *p, *q; + register int k, m; + register struct skiplistnode *p, *q; - CHECKLAST(l); + CHECKLAST(l); - if (!(l->flags & SKIPLIST_FLAG_ALLOW_DUPLICATES)) { - return -1; - } + if (!(l->flags & SKIPLIST_FLAG_ALLOW_DUPLICATES)) { + return -1; + } - if (!cursor || !*cursor) { - p = l->header; - k = m = l->level; + if (!cursor || !*cursor) { + p = l->header; + k = m = l->level; + + /* + * Find matching key + */ + do { + while (q = p->forward[k], + q && (*l->cmp)(q->key, key) < 0) + p = q; + } while (--k >= 0); + + /* + * Find matching value + */ + while (q && ((*l->cmp)(q->key, key) == 0) + && (q->value != *valuePointer)) { + q = q->forward[0]; + } + + if (!q || ((*l->cmp)(q->key, key) != 0) + || (q->value != *valuePointer)) { + /* + * No matching value + */ + CHECKLAST(l); + return -1; + } + } else { + q = (struct skiplistnode *)*cursor; + } /* - * Find matching key + * Advance cursor */ - do { - while (q = p->forward[k], q && (*l->cmp)(q->key, key) < 0) - p = q; - } while(--k>=0); + q = q->forward[0]; - /* - * Find matching value + /* + * If we reached end-of-list or if the key is no longer the same, + * then return error */ - while (q && ((*l->cmp)(q->key, key) == 0) && (q->value != *valuePointer)) { - q = q->forward[0]; - } - - if (!q || ((*l->cmp)(q->key, key) != 0) || (q->value != *valuePointer)) { - /* - * No matching value - */ - CHECKLAST(l); - return -1; - } - } else { - q = (struct skiplistnode *)*cursor; - } - - /* - * Advance cursor - */ - q = q->forward[0]; - - /* - * If we reached end-of-list or if the key is no longer the same, - * then return error - */ - if (!q || ((*l->cmp)(q->key, key) != 0)) - return -1; + if (!q || ((*l->cmp)(q->key, key) != 0)) + return -1; - *valuePointer = q->value; - if (cursor) - *cursor = q; - CHECKLAST(l); - return 0; + *valuePointer = q->value; + if (cursor) + *cursor = q; + CHECKLAST(l); + return 0; } -int -skiplist_first( - register struct skiplist *l, - void **keyPointer, - void **valuePointer) +int skiplist_first(register struct skiplist *l, void **keyPointer, + void **valuePointer) { - register struct skiplistnode *p; + register struct skiplistnode *p; - CHECKLAST(l); - p = l->header->forward[0]; - if (!p) - return -1; + CHECKLAST(l); + p = l->header->forward[0]; + if (!p) + return -1; - if (keyPointer) - *keyPointer = p->key; + if (keyPointer) + *keyPointer = p->key; - if (valuePointer) - *valuePointer = p->value; + if (valuePointer) + *valuePointer = p->value; - CHECKLAST(l); + CHECKLAST(l); - return 0; + return 0; } -int -skiplist_last( - register struct skiplist *l, - void **keyPointer, - void **valuePointer) +int skiplist_last(register struct skiplist *l, void **keyPointer, + void **valuePointer) { - CHECKLAST(l); - if (l->last) { - if (keyPointer) - *keyPointer = l->last->key; - if (valuePointer) - *valuePointer = l->last->value; - return 0; - } - return -1; + CHECKLAST(l); + if (l->last) { + if (keyPointer) + *keyPointer = l->last->key; + if (valuePointer) + *valuePointer = l->last->value; + return 0; + } + return -1; } /* * true = empty */ -int -skiplist_empty( - register struct skiplist *l) +int skiplist_empty(register struct skiplist *l) { - CHECKLAST(l); - if (l->last) - return 0; - return 1; + CHECKLAST(l); + if (l->last) + return 0; + return 1; } -/* +/* * Use this to walk the list. Caller sets *cursor to NULL to obtain * first element. Return value of 0 indicates valid cursor/element * returned, otherwise NULL cursor arg or EOL. */ -int -skiplist_next( - register struct skiplist *l, /* in */ - void **keyPointer, /* out */ - void **valuePointer, /* out */ - void **cursor) /* in/out */ +int skiplist_next(register struct skiplist *l, /* in */ + void **keyPointer, /* out */ + void **valuePointer, /* out */ + void **cursor) /* in/out */ { - struct skiplistnode *p; + struct skiplistnode *p; - if (!cursor) - return -1; + if (!cursor) + return -1; - CHECKLAST(l); + CHECKLAST(l); - if (!*cursor) { - p = l->header->forward[0]; - } else { - p = *cursor; - p = p->forward[0]; - } - *cursor = p; + if (!*cursor) { + p = l->header->forward[0]; + } else { + p = *cursor; + p = p->forward[0]; + } + *cursor = p; - if (!p) - return -1; + if (!p) + return -1; - if (keyPointer) - *keyPointer = p->key; + if (keyPointer) + *keyPointer = p->key; - if (valuePointer) - *valuePointer = p->value; + if (valuePointer) + *valuePointer = p->value; - CHECKLAST(l); + CHECKLAST(l); - return 0; + return 0; } -int -skiplist_delete_first( - register struct skiplist *l) +int skiplist_delete_first(register struct skiplist *l) { - register int k; - register struct skiplistnode *p, *q; - int nodelevel = 0; - - CHECKLAST(l); + register int k; + register struct skiplistnode *p, *q; + int nodelevel = 0; - p = l->header; - q = l->header->forward[0]; + CHECKLAST(l); - if (!q) - return -1; - - for (k = l->level; k >= 0; --k) { - if (p->forward[k] == q) { - p->forward[k] = q->forward[k]; - if ((k == l->level) && (p->forward[k] == NULL) && (l->level > 0)) - --(l->level); - if (!nodelevel) - nodelevel = k; + p = l->header; + q = l->header->forward[0]; + + if (!q) + return -1; + + for (k = l->level; k >= 0; --k) { + if (p->forward[k] == q) { + p->forward[k] = q->forward[k]; + if ((k == l->level) && (p->forward[k] == NULL) + && (l->level > 0)) + --(l->level); + if (!nodelevel) + nodelevel = k; + } } - } #if SKIPLIST_0TIMER_DEBUG - q->flags &= ~SKIPLIST_NODE_FLAG_INSERTED; + q->flags &= ~SKIPLIST_NODE_FLAG_INSERTED; #endif - /* - * If we are deleting the last element of the list, - * update the list's "last" pointer. - */ - if (l->last == q) { - l->last = NULL; - } - - --(l->stats->forward[nodelevel]); + /* + * If we are deleting the last element of the list, + * update the list's "last" pointer. + */ + if (l->last == q) { + l->last = NULL; + } + + --(l->stats->forward[nodelevel]); #if SKIPLIST_DEBUG - zlog_debug("%s: decremented stats @%p:%d, now %ld", __func__, l, nodelevel, - l->stats->forward[nodelevel] - (struct skiplistnode *)NULL); + zlog_debug("%s: decremented stats @%p:%d, now %ld", __func__, l, + nodelevel, + l->stats->forward[nodelevel] - (struct skiplistnode *)NULL); #endif - if (l->del) - (*l->del)(q->value); + if (l->del) + (*l->del)(q->value); - XFREE(MTYPE_SKIP_LIST_NODE, q); + XFREE(MTYPE_SKIP_LIST_NODE, q); - CHECKLAST(l); + CHECKLAST(l); - --(l->count); + --(l->count); - return 0; + return 0; } -void -skiplist_debug(struct vty *vty, struct skiplist *l) +void skiplist_debug(struct vty *vty, struct skiplist *l) { - int i; - - if (!l) - l = skiplist_last_created; - vty_out (vty, "Skiplist %p has max level %d\n", l, l->level); - for (i = l->level; i >= 0; --i) - vty_out (vty, " @%d: %ld\n", - i,(long)((l->stats->forward[i]) - (struct skiplistnode *)NULL)); + int i; + + if (!l) + l = skiplist_last_created; + vty_out(vty, "Skiplist %p has max level %d\n", l, l->level); + for (i = l->level; i >= 0; --i) + vty_out(vty, " @%d: %ld\n", i, + (long)((l->stats->forward[i]) + - (struct skiplistnode *)NULL)); } -static void * -scramble(int i) +static void *scramble(int i) { - uintptr_t result; + uintptr_t result; - result = (i & 0xff) << 24; - result |= (i >> 8); + result = (i & 0xff) << 24; + result |= (i >> 8); - return (void *)result; + return (void *)result; } #define sampleSize 65536 -void -skiplist_test(struct vty *vty) { - struct skiplist *l; - register int i,k; - void *keys[sampleSize]; - void *v; - - zlog_debug("%s: entry", __func__); +void skiplist_test(struct vty *vty) +{ + struct skiplist *l; + register int i, k; + void *keys[sampleSize]; + void *v; - l= skiplist_new(SKIPLIST_FLAG_ALLOW_DUPLICATES, NULL, NULL); + zlog_debug("%s: entry", __func__); - zlog_debug("%s: skiplist_new returned %p", __func__, l); + l = skiplist_new(SKIPLIST_FLAG_ALLOW_DUPLICATES, NULL, NULL); - for (i=0; i < 4; i++) { + zlog_debug("%s: skiplist_new returned %p", __func__, l); - for (k=0; k < sampleSize; k++) { - if (!(k%1000)) { - zlog_debug("%s: (%d:%d)", __func__, i, k); - } - //keys[k] = (void *)random(); - keys[k] = (void *)scramble(k); - if (skiplist_insert(l, keys[k], keys[k])) - zlog_debug("error in insert #%d,#%d",i,k); - } + for (i = 0; i < 4; i++) { - zlog_debug("%s: inserts done", __func__); + for (k = 0; k < sampleSize; k++) { + if (!(k % 1000)) { + zlog_debug("%s: (%d:%d)", __func__, i, k); + } + // keys[k] = (void *)random(); + keys[k] = (void *)scramble(k); + if (skiplist_insert(l, keys[k], keys[k])) + zlog_debug("error in insert #%d,#%d", i, k); + } - for (k=0; k < sampleSize; k++) { + zlog_debug("%s: inserts done", __func__); - if (!(k % 1000)) - zlog_debug("[%d:%d]", i, k); - if (skiplist_search(l, keys[k], &v)) - zlog_debug("error in search #%d,#%d",i,k); + for (k = 0; k < sampleSize; k++) { - if (v != keys[k]) - zlog_debug("search returned wrong value"); - } + if (!(k % 1000)) + zlog_debug("[%d:%d]", i, k); + if (skiplist_search(l, keys[k], &v)) + zlog_debug("error in search #%d,#%d", i, k); + if (v != keys[k]) + zlog_debug("search returned wrong value"); + } - for (k=0; k < sampleSize; k++) { + for (k = 0; k < sampleSize; k++) { - if (!(k % 1000)) - zlog_debug("<%d:%d>", i, k); - if (skiplist_delete(l, keys[k], keys[k])) - zlog_debug("error in delete"); - keys[k] = (void *)scramble(k ^ 0xf0f0f0f0); - if (skiplist_insert(l, keys[k], keys[k])) - zlog_debug("error in insert #%d,#%d",i,k); - } + if (!(k % 1000)) + zlog_debug("<%d:%d>", i, k); + if (skiplist_delete(l, keys[k], keys[k])) + zlog_debug("error in delete"); + keys[k] = (void *)scramble(k ^ 0xf0f0f0f0); + if (skiplist_insert(l, keys[k], keys[k])) + zlog_debug("error in insert #%d,#%d", i, k); + } - for (k=0; k < sampleSize; k++) { + for (k = 0; k < sampleSize; k++) { - if (!(k % 1000)) - zlog_debug("{%d:%d}", i, k); - if (skiplist_delete_first(l)) - zlog_debug("error in delete_first"); + if (!(k % 1000)) + zlog_debug("{%d:%d}", i, k); + if (skiplist_delete_first(l)) + zlog_debug("error in delete_first"); + } } - } - skiplist_free(l); + skiplist_free(l); } - diff --git a/lib/skiplist.h b/lib/skiplist.h index 25775f754..a2e8c374b 100644 --- a/lib/skiplist.h +++ b/lib/skiplist.h @@ -1,5 +1,5 @@ /* - * Copyright 1990 William Pugh + * Copyright 1990 William Pugh * * Redistribution and use in source and binary forms, with or without * modification, are permitted. @@ -33,127 +33,93 @@ #define SKIPLIST_0TIMER_DEBUG 1 -/* +/* * skiplistnodes must always contain data to be valid. Adding an * empty node to a list is invalid */ -struct skiplistnode -{ - void *key; - void *value; +struct skiplistnode { + void *key; + void *value; #if SKIPLIST_0TIMER_DEBUG - int flags; + int flags; #define SKIPLIST_NODE_FLAG_INSERTED 0x00000001 #endif - struct skiplistnode *forward[1]; /* variable sized */ + struct skiplistnode *forward[1]; /* variable sized */ }; -struct skiplist -{ - int flags; +struct skiplist { + int flags; #define SKIPLIST_FLAG_ALLOW_DUPLICATES 0x00000001 - int level; /* max lvl (1 + current # of levels in list) */ - unsigned int count; - struct skiplistnode *header; - struct skiplistnode *stats; - struct skiplistnode *last; /* last real list item (NULL if empty list) */ - - /* - * Returns -1 if val1 < val2, 0 if equal?, 1 if val1 > val2. - * Used as definition of sorted for listnode_add_sort - */ - int (*cmp) (void *val1, void *val2); - - /* callback to free user-owned data when listnode is deleted. supplying - * this callback is very much encouraged! - */ - void (*del) (void *val); + int level; /* max lvl (1 + current # of levels in list) */ + unsigned int count; + struct skiplistnode *header; + struct skiplistnode *stats; + struct skiplistnode + *last; /* last real list item (NULL if empty list) */ + + /* + * Returns -1 if val1 < val2, 0 if equal?, 1 if val1 > val2. + * Used as definition of sorted for listnode_add_sort + */ + int (*cmp)(void *val1, void *val2); + + /* callback to free user-owned data when listnode is deleted. supplying + * this callback is very much encouraged! + */ + void (*del)(void *val); }; /* Prototypes. */ extern struct skiplist * -skiplist_new( /* encouraged: set list.del callback on new lists */ - int flags, - int (*cmp) (void *key1, void *key2), /* NULL => default cmp */ - void (*del) (void *val)); /* NULL => no auto val free */ - -extern void -skiplist_free (struct skiplist *); - -extern int -skiplist_insert( - register struct skiplist *l, - register void *key, - register void *value); - -extern int -skiplist_delete( - register struct skiplist *l, - register void *key, - register void *value); - -extern int -skiplist_search( - register struct skiplist *l, - register void *key, - void **valuePointer); - -extern int -skiplist_first_value( - register struct skiplist *l, /* in */ - register void *key, /* in */ - void **valuePointer, /* in/out */ - void **cursor); /* out */ - -extern int -skiplist_next_value( - register struct skiplist *l, /* in */ - register void *key, /* in */ - void **valuePointer, /* in/out */ - void **cursor); /* in/out */ - -extern int -skiplist_first( - register struct skiplist *l, - void **keyPointer, - void **valuePointer); - -extern int -skiplist_last( - register struct skiplist *l, - void **keyPointer, - void **valuePointer); - -extern int -skiplist_delete_first( - register struct skiplist *l); - -extern int -skiplist_next( - register struct skiplist *l, /* in */ - void **keyPointer, /* out */ - void **valuePointer, /* out */ - void **cursor); /* in/out */ - -extern int -skiplist_empty( - register struct skiplist *l); /* in */ - -extern unsigned int -skiplist_count( - register struct skiplist *l); /* in */ - -extern void -skiplist_debug( - struct vty *vty, - struct skiplist *l); - -extern void -skiplist_test( - struct vty *vty); +skiplist_new(/* encouraged: set list.del callback on new lists */ + int flags, + int (*cmp)(void *key1, void *key2), /* NULL => default cmp */ + void (*del)(void *val)); /* NULL => no auto val free */ + +extern void skiplist_free(struct skiplist *); + +extern int skiplist_insert(register struct skiplist *l, register void *key, + register void *value); + +extern int skiplist_delete(register struct skiplist *l, register void *key, + register void *value); + +extern int skiplist_search(register struct skiplist *l, register void *key, + void **valuePointer); + +extern int skiplist_first_value(register struct skiplist *l, /* in */ + register void *key, /* in */ + void **valuePointer, /* in/out */ + void **cursor); /* out */ + +extern int skiplist_next_value(register struct skiplist *l, /* in */ + register void *key, /* in */ + void **valuePointer, /* in/out */ + void **cursor); /* in/out */ + +extern int skiplist_first(register struct skiplist *l, void **keyPointer, + void **valuePointer); + +extern int skiplist_last(register struct skiplist *l, void **keyPointer, + void **valuePointer); + +extern int skiplist_delete_first(register struct skiplist *l); + +extern int skiplist_next(register struct skiplist *l, /* in */ + void **keyPointer, /* out */ + void **valuePointer, /* out */ + void **cursor); /* in/out */ + +extern int skiplist_empty(register struct skiplist *l); /* in */ + +extern unsigned int skiplist_count(register struct skiplist *l); /* in */ + +extern void skiplist_debug(struct vty *vty, struct skiplist *l); + +extern void skiplist_test(struct vty *vty); #endif /* _ZEBRA_SKIPLIST_H */ diff --git a/lib/smux.c b/lib/smux.c index d7d99cc8a..9a0063df2 100644 --- a/lib/smux.c +++ b/lib/smux.c @@ -53,30 +53,29 @@ #define SMUX_MAX_FAILURE 3 /* SNMP tree. */ -struct subtree -{ - /* Tree's oid. */ - oid name[MAX_OID_LEN]; - u_char name_len; +struct subtree { + /* Tree's oid. */ + oid name[MAX_OID_LEN]; + u_char name_len; - /* List of the variables. */ - struct variable *variables; + /* List of the variables. */ + struct variable *variables; - /* Length of the variables list. */ - int variables_num; + /* Length of the variables list. */ + int variables_num; - /* Width of the variables list. */ - int variables_width; + /* Width of the variables list. */ + int variables_width; - /* Registered flag. */ - int registered; + /* Registered flag. */ + int registered; }; #define min(A,B) ((A) < (B) ? (A) : (B)) -enum smux_event {SMUX_SCHEDULE, SMUX_CONNECT, SMUX_READ}; +enum smux_event { SMUX_SCHEDULE, SMUX_CONNECT, SMUX_READ }; -void smux_event (enum smux_event, int); +void smux_event(enum smux_event, int); /* SMUX socket. */ @@ -105,824 +104,810 @@ int debug_smux = 0; int fail = 0; /* SMUX node. */ -static struct cmd_node smux_node = -{ - SMUX_NODE, - "" /* SMUX has no interface. */ +static struct cmd_node smux_node = { + SMUX_NODE, "" /* SMUX has no interface. */ }; /* thread master */ static struct thread_master *smux_master; -static int -oid_compare_part (oid *o1, int o1_len, oid *o2, int o2_len) +static int oid_compare_part(oid *o1, int o1_len, oid *o2, int o2_len) { - int i; - - for (i = 0; i < min (o1_len, o2_len); i++) - { - if (o1[i] < o2[i]) - return -1; - else if (o1[i] > o2[i]) - return 1; - } - if (o1_len < o2_len) - return -1; - - return 0; + int i; + + for (i = 0; i < min(o1_len, o2_len); i++) { + if (o1[i] < o2[i]) + return -1; + else if (o1[i] > o2[i]) + return 1; + } + if (o1_len < o2_len) + return -1; + + return 0; } -static void -smux_oid_dump (const char *prefix, const oid *oid, size_t oid_len) +static void smux_oid_dump(const char *prefix, const oid *oid, size_t oid_len) { - unsigned int i; - int first = 1; - char buf[MAX_OID_LEN * 3]; - - buf[0] = '\0'; - - for (i = 0; i < oid_len; i++) - { - sprintf (buf + strlen (buf), "%s%d", first ? "" : ".", (int) oid[i]); - first = 0; - } - zlog_debug ("%s: %s", prefix, buf); + unsigned int i; + int first = 1; + char buf[MAX_OID_LEN * 3]; + + buf[0] = '\0'; + + for (i = 0; i < oid_len; i++) { + sprintf(buf + strlen(buf), "%s%d", first ? "" : ".", + (int)oid[i]); + first = 0; + } + zlog_debug("%s: %s", prefix, buf); } -static int -smux_socket (void) +static int smux_socket(void) { - int ret; - struct addrinfo hints, *res0, *res; - int gai; - int sock = 0; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - gai = getaddrinfo(NULL, "smux", &hints, &res0); - if (gai == EAI_SERVICE) - { - char servbuf[NI_MAXSERV]; - sprintf(servbuf,"%d",SMUX_PORT_DEFAULT); - servbuf[sizeof (servbuf) - 1] = '\0'; - gai = getaddrinfo(NULL, servbuf, &hints, &res0); - } - if (gai) - { - zlog_warn("Cannot locate loopback service smux"); - return -1; - } - for(res=res0; res; res=res->ai_next) - { - if (res->ai_family != AF_INET - && res->ai_family != AF_INET6 - ) - continue; - - sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if (sock < 0) - continue; - sockopt_reuseaddr (sock); - sockopt_reuseport (sock); - ret = connect (sock, res->ai_addr, res->ai_addrlen); - if (ret < 0) - { - close(sock); - sock = -1; - continue; + int ret; + struct addrinfo hints, *res0, *res; + int gai; + int sock = 0; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + gai = getaddrinfo(NULL, "smux", &hints, &res0); + if (gai == EAI_SERVICE) { + char servbuf[NI_MAXSERV]; + sprintf(servbuf, "%d", SMUX_PORT_DEFAULT); + servbuf[sizeof(servbuf) - 1] = '\0'; + gai = getaddrinfo(NULL, servbuf, &hints, &res0); + } + if (gai) { + zlog_warn("Cannot locate loopback service smux"); + return -1; + } + for (res = res0; res; res = res->ai_next) { + if (res->ai_family != AF_INET && res->ai_family != AF_INET6) + continue; + + sock = socket(res->ai_family, res->ai_socktype, + res->ai_protocol); + if (sock < 0) + continue; + sockopt_reuseaddr(sock); + sockopt_reuseport(sock); + ret = connect(sock, res->ai_addr, res->ai_addrlen); + if (ret < 0) { + close(sock); + sock = -1; + continue; + } + break; } - break; - } - freeaddrinfo(res0); - if (sock < 0) - zlog_warn ("Can't connect to SNMP agent with SMUX"); - return sock; + freeaddrinfo(res0); + if (sock < 0) + zlog_warn("Can't connect to SNMP agent with SMUX"); + return sock; } -static void -smux_getresp_send (oid objid[], size_t objid_len, long reqid, long errstat, - long errindex, u_char val_type, void *arg, size_t arg_len) +static void smux_getresp_send(oid objid[], size_t objid_len, long reqid, + long errstat, long errindex, u_char val_type, + void *arg, size_t arg_len) { - u_char buf[BUFSIZ]; - u_char *ptr, *h1, *h1e, *h2, *h2e; - size_t len, length; - - ptr = buf; - len = BUFSIZ; - length = len; - - if (debug_smux) - { - zlog_debug ("SMUX GETRSP send"); - zlog_debug ("SMUX GETRSP reqid: %ld", reqid); - } - - h1 = ptr; - /* Place holder h1 for complete sequence */ - ptr = asn_build_sequence (ptr, &len, (u_char) SMUX_GETRSP, 0); - h1e = ptr; - - ptr = asn_build_int (ptr, &len, - (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), - &reqid, sizeof (reqid)); - - if (debug_smux) - zlog_debug ("SMUX GETRSP errstat: %ld", errstat); - - ptr = asn_build_int (ptr, &len, - (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), - &errstat, sizeof (errstat)); - if (debug_smux) - zlog_debug ("SMUX GETRSP errindex: %ld", errindex); - - ptr = asn_build_int (ptr, &len, - (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), - &errindex, sizeof (errindex)); - - h2 = ptr; - /* Place holder h2 for one variable */ - ptr = asn_build_sequence (ptr, &len, - (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), - 0); - h2e = ptr; - - ptr = snmp_build_var_op (ptr, objid, &objid_len, - val_type, arg_len, arg, &len); - - /* Now variable size is known, fill in size */ - asn_build_sequence(h2,&length,(u_char)(ASN_SEQUENCE|ASN_CONSTRUCTOR),ptr-h2e); - - /* Fill in size of whole sequence */ - asn_build_sequence(h1,&length,(u_char)SMUX_GETRSP,ptr-h1e); - - if (debug_smux) - zlog_debug ("SMUX getresp send: %td", (ptr - buf)); - - send (smux_sock, buf, (ptr - buf), 0); + u_char buf[BUFSIZ]; + u_char *ptr, *h1, *h1e, *h2, *h2e; + size_t len, length; + + ptr = buf; + len = BUFSIZ; + length = len; + + if (debug_smux) { + zlog_debug("SMUX GETRSP send"); + zlog_debug("SMUX GETRSP reqid: %ld", reqid); + } + + h1 = ptr; + /* Place holder h1 for complete sequence */ + ptr = asn_build_sequence(ptr, &len, (u_char)SMUX_GETRSP, 0); + h1e = ptr; + + ptr = asn_build_int(ptr, &len, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE + | ASN_INTEGER), + &reqid, sizeof(reqid)); + + if (debug_smux) + zlog_debug("SMUX GETRSP errstat: %ld", errstat); + + ptr = asn_build_int(ptr, &len, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE + | ASN_INTEGER), + &errstat, sizeof(errstat)); + if (debug_smux) + zlog_debug("SMUX GETRSP errindex: %ld", errindex); + + ptr = asn_build_int(ptr, &len, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE + | ASN_INTEGER), + &errindex, sizeof(errindex)); + + h2 = ptr; + /* Place holder h2 for one variable */ + ptr = asn_build_sequence(ptr, &len, + (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), 0); + h2e = ptr; + + ptr = snmp_build_var_op(ptr, objid, &objid_len, val_type, arg_len, arg, + &len); + + /* Now variable size is known, fill in size */ + asn_build_sequence(h2, &length, + (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), ptr - h2e); + + /* Fill in size of whole sequence */ + asn_build_sequence(h1, &length, (u_char)SMUX_GETRSP, ptr - h1e); + + if (debug_smux) + zlog_debug("SMUX getresp send: %td", (ptr - buf)); + + send(smux_sock, buf, (ptr - buf), 0); } -static u_char * -smux_var (u_char *ptr, size_t len, oid objid[], size_t *objid_len, - size_t *var_val_len, - u_char *var_val_type, - void **var_value) +static u_char *smux_var(u_char *ptr, size_t len, oid objid[], size_t *objid_len, + size_t *var_val_len, u_char *var_val_type, + void **var_value) { - u_char type; - u_char val_type; - size_t val_len; - u_char *val; - - if (debug_smux) - zlog_debug ("SMUX var parse: len %zd", len); - - /* Parse header. */ - ptr = asn_parse_header (ptr, &len, &type); - - if (debug_smux) - { - zlog_debug ("SMUX var parse: type %d len %zd", type, len); - zlog_debug ("SMUX var parse: type must be %d", - (ASN_SEQUENCE | ASN_CONSTRUCTOR)); - } - - /* Parse var option. */ - *objid_len = MAX_OID_LEN; - ptr = snmp_parse_var_op(ptr, objid, objid_len, &val_type, - &val_len, &val, &len); - - if (var_val_len) - *var_val_len = val_len; - - if (var_value) - *var_value = (void*) val; - - if (var_val_type) - *var_val_type = val_type; - - /* Requested object id length is objid_len. */ - if (debug_smux) - smux_oid_dump ("Request OID", objid, *objid_len); - - if (debug_smux) - zlog_debug ("SMUX val_type: %d", val_type); - - /* Check request value type. */ - if (debug_smux) - switch (val_type) - { - case ASN_NULL: - /* In case of SMUX_GET or SMUX_GET_NEXT val_type is set to - ASN_NULL. */ - zlog_debug ("ASN_NULL"); - break; - - case ASN_INTEGER: - zlog_debug ("ASN_INTEGER"); - break; - case ASN_COUNTER: - case ASN_GAUGE: - case ASN_TIMETICKS: - case ASN_UINTEGER: - zlog_debug ("ASN_COUNTER"); - break; - case ASN_COUNTER64: - zlog_debug ("ASN_COUNTER64"); - break; - case ASN_IPADDRESS: - zlog_debug ("ASN_IPADDRESS"); - break; - case ASN_OCTET_STR: - zlog_debug ("ASN_OCTET_STR"); - break; - case ASN_OPAQUE: - case ASN_NSAP: - case ASN_OBJECT_ID: - zlog_debug ("ASN_OPAQUE"); - break; - case SNMP_NOSUCHOBJECT: - zlog_debug ("SNMP_NOSUCHOBJECT"); - break; - case SNMP_NOSUCHINSTANCE: - zlog_debug ("SNMP_NOSUCHINSTANCE"); - break; - case SNMP_ENDOFMIBVIEW: - zlog_debug ("SNMP_ENDOFMIBVIEW"); - break; - case ASN_BIT_STR: - zlog_debug ("ASN_BIT_STR"); - break; - default: - zlog_debug ("Unknown type"); - break; - } - return ptr; + u_char type; + u_char val_type; + size_t val_len; + u_char *val; + + if (debug_smux) + zlog_debug("SMUX var parse: len %zd", len); + + /* Parse header. */ + ptr = asn_parse_header(ptr, &len, &type); + + if (debug_smux) { + zlog_debug("SMUX var parse: type %d len %zd", type, len); + zlog_debug("SMUX var parse: type must be %d", + (ASN_SEQUENCE | ASN_CONSTRUCTOR)); + } + + /* Parse var option. */ + *objid_len = MAX_OID_LEN; + ptr = snmp_parse_var_op(ptr, objid, objid_len, &val_type, &val_len, + &val, &len); + + if (var_val_len) + *var_val_len = val_len; + + if (var_value) + *var_value = (void *)val; + + if (var_val_type) + *var_val_type = val_type; + + /* Requested object id length is objid_len. */ + if (debug_smux) + smux_oid_dump("Request OID", objid, *objid_len); + + if (debug_smux) + zlog_debug("SMUX val_type: %d", val_type); + + /* Check request value type. */ + if (debug_smux) + switch (val_type) { + case ASN_NULL: + /* In case of SMUX_GET or SMUX_GET_NEXT val_type is set + to + ASN_NULL. */ + zlog_debug("ASN_NULL"); + break; + + case ASN_INTEGER: + zlog_debug("ASN_INTEGER"); + break; + case ASN_COUNTER: + case ASN_GAUGE: + case ASN_TIMETICKS: + case ASN_UINTEGER: + zlog_debug("ASN_COUNTER"); + break; + case ASN_COUNTER64: + zlog_debug("ASN_COUNTER64"); + break; + case ASN_IPADDRESS: + zlog_debug("ASN_IPADDRESS"); + break; + case ASN_OCTET_STR: + zlog_debug("ASN_OCTET_STR"); + break; + case ASN_OPAQUE: + case ASN_NSAP: + case ASN_OBJECT_ID: + zlog_debug("ASN_OPAQUE"); + break; + case SNMP_NOSUCHOBJECT: + zlog_debug("SNMP_NOSUCHOBJECT"); + break; + case SNMP_NOSUCHINSTANCE: + zlog_debug("SNMP_NOSUCHINSTANCE"); + break; + case SNMP_ENDOFMIBVIEW: + zlog_debug("SNMP_ENDOFMIBVIEW"); + break; + case ASN_BIT_STR: + zlog_debug("ASN_BIT_STR"); + break; + default: + zlog_debug("Unknown type"); + break; + } + return ptr; } /* NOTE: all 3 functions (smux_set, smux_get & smux_getnext) are based on ucd-snmp smux and as such suppose, that the peer receives in the message only one variable. Fortunately, IBM seems to do the same in AIX. */ -static int -smux_set (oid *reqid, size_t *reqid_len, - u_char val_type, void *val, size_t val_len, int action) +static int smux_set(oid *reqid, size_t *reqid_len, u_char val_type, void *val, + size_t val_len, int action) { - int j; - struct subtree *subtree; - struct variable *v; - int subresult; - oid *suffix; - size_t suffix_len; - int result; - u_char *statP = NULL; - WriteMethod *write_method = NULL; - struct listnode *node, *nnode; - - /* Check */ - for (ALL_LIST_ELEMENTS (treelist, node, nnode, subtree)) - { - subresult = oid_compare_part (reqid, *reqid_len, - subtree->name, subtree->name_len); - - /* Subtree matched. */ - if (subresult == 0) - { - /* Prepare suffix. */ - suffix = reqid + subtree->name_len; - suffix_len = *reqid_len - subtree->name_len; - result = subresult; - - /* Check variables. */ - for (j = 0; j < subtree->variables_num; j++) - { - v = &subtree->variables[j]; - - /* Always check suffix */ - result = oid_compare_part (suffix, suffix_len, - v->name, v->namelen); - - /* This is exact match so result must be zero. */ - if (result == 0) - { - if (debug_smux) - zlog_debug ("SMUX function call index is %d", v->magic); - - statP = (*v->findVar) (v, suffix, &suffix_len, 1, - &val_len, &write_method); - - if (write_method) - { - return (*write_method)(action, val, val_type, val_len, - statP, suffix, suffix_len); - } - else - { - return SNMP_ERR_READONLY; - } - } - - /* If above execution is failed or oid is small (so - there is no further match). */ - if (result < 0) - return SNMP_ERR_NOSUCHNAME; - } - } - } - return SNMP_ERR_NOSUCHNAME; + int j; + struct subtree *subtree; + struct variable *v; + int subresult; + oid *suffix; + size_t suffix_len; + int result; + u_char *statP = NULL; + WriteMethod *write_method = NULL; + struct listnode *node, *nnode; + + /* Check */ + for (ALL_LIST_ELEMENTS(treelist, node, nnode, subtree)) { + subresult = oid_compare_part(reqid, *reqid_len, subtree->name, + subtree->name_len); + + /* Subtree matched. */ + if (subresult == 0) { + /* Prepare suffix. */ + suffix = reqid + subtree->name_len; + suffix_len = *reqid_len - subtree->name_len; + result = subresult; + + /* Check variables. */ + for (j = 0; j < subtree->variables_num; j++) { + v = &subtree->variables[j]; + + /* Always check suffix */ + result = oid_compare_part(suffix, suffix_len, + v->name, v->namelen); + + /* This is exact match so result must be zero. + */ + if (result == 0) { + if (debug_smux) + zlog_debug( + "SMUX function call index is %d", + v->magic); + + statP = (*v->findVar)( + v, suffix, &suffix_len, 1, + &val_len, &write_method); + + if (write_method) { + return (*write_method)( + action, val, val_type, + val_len, statP, suffix, + suffix_len); + } else { + return SNMP_ERR_READONLY; + } + } + + /* If above execution is failed or oid is small + (so + there is no further match). */ + if (result < 0) + return SNMP_ERR_NOSUCHNAME; + } + } + } + return SNMP_ERR_NOSUCHNAME; } -static int -smux_get (oid *reqid, size_t *reqid_len, int exact, - u_char *val_type,void **val, size_t *val_len) +static int smux_get(oid *reqid, size_t *reqid_len, int exact, u_char *val_type, + void **val, size_t *val_len) { - int j; - struct subtree *subtree; - struct variable *v; - int subresult; - oid *suffix; - size_t suffix_len; - int result; - WriteMethod *write_method=NULL; - struct listnode *node, *nnode; - - /* Check */ - for (ALL_LIST_ELEMENTS (treelist, node, nnode,subtree)) - { - subresult = oid_compare_part (reqid, *reqid_len, - subtree->name, subtree->name_len); - - /* Subtree matched. */ - if (subresult == 0) - { - /* Prepare suffix. */ - suffix = reqid + subtree->name_len; - suffix_len = *reqid_len - subtree->name_len; - result = subresult; - - /* Check variables. */ - for (j = 0; j < subtree->variables_num; j++) - { - v = &subtree->variables[j]; - - /* Always check suffix */ - result = oid_compare_part (suffix, suffix_len, - v->name, v->namelen); - - /* This is exact match so result must be zero. */ - if (result == 0) - { - if (debug_smux) - zlog_debug ("SMUX function call index is %d", v->magic); - - *val = (*v->findVar) (v, suffix, &suffix_len, exact, - val_len, &write_method); - - /* There is no instance. */ - if (*val == NULL) - return SNMP_NOSUCHINSTANCE; - - /* Call is suceed. */ - *val_type = v->type; - - return 0; + int j; + struct subtree *subtree; + struct variable *v; + int subresult; + oid *suffix; + size_t suffix_len; + int result; + WriteMethod *write_method = NULL; + struct listnode *node, *nnode; + + /* Check */ + for (ALL_LIST_ELEMENTS(treelist, node, nnode, subtree)) { + subresult = oid_compare_part(reqid, *reqid_len, subtree->name, + subtree->name_len); + + /* Subtree matched. */ + if (subresult == 0) { + /* Prepare suffix. */ + suffix = reqid + subtree->name_len; + suffix_len = *reqid_len - subtree->name_len; + result = subresult; + + /* Check variables. */ + for (j = 0; j < subtree->variables_num; j++) { + v = &subtree->variables[j]; + + /* Always check suffix */ + result = oid_compare_part(suffix, suffix_len, + v->name, v->namelen); + + /* This is exact match so result must be zero. + */ + if (result == 0) { + if (debug_smux) + zlog_debug( + "SMUX function call index is %d", + v->magic); + + *val = (*v->findVar)( + v, suffix, &suffix_len, exact, + val_len, &write_method); + + /* There is no instance. */ + if (*val == NULL) + return SNMP_NOSUCHINSTANCE; + + /* Call is suceed. */ + *val_type = v->type; + + return 0; + } + + /* If above execution is failed or oid is small + (so + there is no further match). */ + if (result < 0) + return SNMP_ERR_NOSUCHNAME; + } } - - /* If above execution is failed or oid is small (so - there is no further match). */ - if (result < 0) - return SNMP_ERR_NOSUCHNAME; - } } - } - return SNMP_ERR_NOSUCHNAME; + return SNMP_ERR_NOSUCHNAME; } -static int -smux_getnext (oid *reqid, size_t *reqid_len, int exact, - u_char *val_type,void **val, size_t *val_len) +static int smux_getnext(oid *reqid, size_t *reqid_len, int exact, + u_char *val_type, void **val, size_t *val_len) { - int j; - oid save[MAX_OID_LEN]; - int savelen = 0; - struct subtree *subtree; - struct variable *v; - int subresult; - oid *suffix; - size_t suffix_len; - int result; - WriteMethod *write_method=NULL; - struct listnode *node, *nnode; - - - /* Save incoming request. */ - oid_copy (save, reqid, *reqid_len); - savelen = *reqid_len; - - /* Check */ - for (ALL_LIST_ELEMENTS (treelist, node, nnode, subtree)) - { - subresult = oid_compare_part (reqid, *reqid_len, - subtree->name, subtree->name_len); - - /* If request is in the tree. The agent has to make sure we - only receive requests we have registered for. */ - /* Unfortunately, that's not true. In fact, a SMUX subagent has to - behave as if it manages the whole SNMP MIB tree itself. It's the - duty of the master agent to collect the best answer and return it - to the manager. See RFC 1227 chapter 3.1.6 for the glory details - :-). ucd-snmp really behaves bad here as it actually might ask - multiple times for the same GETNEXT request as it throws away the - answer when it expects it in a different subtree and might come - back later with the very same request. --jochen */ - - if (subresult <= 0) - { - /* Prepare suffix. */ - suffix = reqid + subtree->name_len; - suffix_len = *reqid_len - subtree->name_len; - if (subresult < 0) - { - oid_copy(reqid, subtree->name, subtree->name_len); - *reqid_len = subtree->name_len; - } - for (j = 0; j < subtree->variables_num; j++) - { - result = subresult; - v = &subtree->variables[j]; - - /* Next then check result >= 0. */ - if (result == 0) - result = oid_compare_part (suffix, suffix_len, - v->name, v->namelen); - - if (result <= 0) - { - if (debug_smux) - zlog_debug ("SMUX function call index is %d", v->magic); - if(result<0) - { - oid_copy(suffix, v->name, v->namelen); - suffix_len = v->namelen; - } - *val = (*v->findVar) (v, suffix, &suffix_len, exact, - val_len, &write_method); - *reqid_len = suffix_len + subtree->name_len; - if (*val) - { - *val_type = v->type; - return 0; - } + int j; + oid save[MAX_OID_LEN]; + int savelen = 0; + struct subtree *subtree; + struct variable *v; + int subresult; + oid *suffix; + size_t suffix_len; + int result; + WriteMethod *write_method = NULL; + struct listnode *node, *nnode; + + + /* Save incoming request. */ + oid_copy(save, reqid, *reqid_len); + savelen = *reqid_len; + + /* Check */ + for (ALL_LIST_ELEMENTS(treelist, node, nnode, subtree)) { + subresult = oid_compare_part(reqid, *reqid_len, subtree->name, + subtree->name_len); + + /* If request is in the tree. The agent has to make sure we + only receive requests we have registered for. */ + /* Unfortunately, that's not true. In fact, a SMUX subagent has + to + behave as if it manages the whole SNMP MIB tree itself. It's + the + duty of the master agent to collect the best answer and + return it + to the manager. See RFC 1227 chapter 3.1.6 for the glory + details + :-). ucd-snmp really behaves bad here as it actually might + ask + multiple times for the same GETNEXT request as it throws away + the + answer when it expects it in a different subtree and might + come + back later with the very same request. --jochen */ + + if (subresult <= 0) { + /* Prepare suffix. */ + suffix = reqid + subtree->name_len; + suffix_len = *reqid_len - subtree->name_len; + if (subresult < 0) { + oid_copy(reqid, subtree->name, + subtree->name_len); + *reqid_len = subtree->name_len; + } + for (j = 0; j < subtree->variables_num; j++) { + result = subresult; + v = &subtree->variables[j]; + + /* Next then check result >= 0. */ + if (result == 0) + result = oid_compare_part( + suffix, suffix_len, v->name, + v->namelen); + + if (result <= 0) { + if (debug_smux) + zlog_debug( + "SMUX function call index is %d", + v->magic); + if (result < 0) { + oid_copy(suffix, v->name, + v->namelen); + suffix_len = v->namelen; + } + *val = (*v->findVar)( + v, suffix, &suffix_len, exact, + val_len, &write_method); + *reqid_len = + suffix_len + subtree->name_len; + if (*val) { + *val_type = v->type; + return 0; + } + } + } } - } } - } - memcpy (reqid, save, savelen * sizeof(oid)); - *reqid_len = savelen; + memcpy(reqid, save, savelen * sizeof(oid)); + *reqid_len = savelen; - return SNMP_ERR_NOSUCHNAME; + return SNMP_ERR_NOSUCHNAME; } /* GET message header. */ -static u_char * -smux_parse_get_header (u_char *ptr, size_t *len, long *reqid) +static u_char *smux_parse_get_header(u_char *ptr, size_t *len, long *reqid) { - u_char type; - long errstat; - long errindex; + u_char type; + long errstat; + long errindex; - /* Request ID. */ - ptr = asn_parse_int (ptr, len, &type, reqid, sizeof (*reqid)); + /* Request ID. */ + ptr = asn_parse_int(ptr, len, &type, reqid, sizeof(*reqid)); - if (debug_smux) - zlog_debug ("SMUX GET reqid: %d len: %d", (int) *reqid, (int) *len); + if (debug_smux) + zlog_debug("SMUX GET reqid: %d len: %d", (int)*reqid, + (int)*len); - /* Error status. */ - ptr = asn_parse_int (ptr, len, &type, &errstat, sizeof (errstat)); + /* Error status. */ + ptr = asn_parse_int(ptr, len, &type, &errstat, sizeof(errstat)); - if (debug_smux) - zlog_debug ("SMUX GET errstat %ld len: %zd", errstat, *len); + if (debug_smux) + zlog_debug("SMUX GET errstat %ld len: %zd", errstat, *len); - /* Error index. */ - ptr = asn_parse_int (ptr, len, &type, &errindex, sizeof (errindex)); + /* Error index. */ + ptr = asn_parse_int(ptr, len, &type, &errindex, sizeof(errindex)); - if (debug_smux) - zlog_debug ("SMUX GET errindex %ld len: %zd", errindex, *len); + if (debug_smux) + zlog_debug("SMUX GET errindex %ld len: %zd", errindex, *len); - return ptr; + return ptr; } -static void -smux_parse_set (u_char *ptr, size_t len, int action) +static void smux_parse_set(u_char *ptr, size_t len, int action) { - long reqid; - oid oid[MAX_OID_LEN]; - size_t oid_len; - u_char val_type; - void *val; - size_t val_len; - int ret; - - if (debug_smux) - zlog_debug ("SMUX SET(%s) message parse: len %zd", - (RESERVE1 == action) ? "RESERVE1" : ((FREE == action) ? "FREE" : "COMMIT"), - len); - - /* Parse SET message header. */ - ptr = smux_parse_get_header (ptr, &len, &reqid); - - /* Parse SET message object ID. */ - ptr = smux_var (ptr, len, oid, &oid_len, &val_len, &val_type, &val); - - ret = smux_set (oid, &oid_len, val_type, val, val_len, action); - if (debug_smux) - zlog_debug ("SMUX SET ret %d", ret); - - /* Return result. */ - if (RESERVE1 == action) - smux_getresp_send (oid, oid_len, reqid, ret, 3, ASN_NULL, NULL, 0); + long reqid; + oid oid[MAX_OID_LEN]; + size_t oid_len; + u_char val_type; + void *val; + size_t val_len; + int ret; + + if (debug_smux) + zlog_debug("SMUX SET(%s) message parse: len %zd", + (RESERVE1 == action) + ? "RESERVE1" + : ((FREE == action) ? "FREE" : "COMMIT"), + len); + + /* Parse SET message header. */ + ptr = smux_parse_get_header(ptr, &len, &reqid); + + /* Parse SET message object ID. */ + ptr = smux_var(ptr, len, oid, &oid_len, &val_len, &val_type, &val); + + ret = smux_set(oid, &oid_len, val_type, val, val_len, action); + if (debug_smux) + zlog_debug("SMUX SET ret %d", ret); + + /* Return result. */ + if (RESERVE1 == action) + smux_getresp_send(oid, oid_len, reqid, ret, 3, ASN_NULL, NULL, + 0); } -static void -smux_parse_get (u_char *ptr, size_t len, int exact) +static void smux_parse_get(u_char *ptr, size_t len, int exact) { - long reqid; - oid oid[MAX_OID_LEN]; - size_t oid_len; - u_char val_type; - void *val; - size_t val_len; - int ret; - - if (debug_smux) - zlog_debug ("SMUX GET message parse: len %zd", len); - - /* Parse GET message header. */ - ptr = smux_parse_get_header (ptr, &len, &reqid); - - /* Parse GET message object ID. We needn't the value come */ - ptr = smux_var (ptr, len, oid, &oid_len, NULL, NULL, NULL); - - /* Traditional getstatptr. */ - if (exact) - ret = smux_get (oid, &oid_len, exact, &val_type, &val, &val_len); - else - ret = smux_getnext (oid, &oid_len, exact, &val_type, &val, &val_len); - - /* Return result. */ - if (ret == 0) - smux_getresp_send (oid, oid_len, reqid, 0, 0, val_type, val, val_len); - else - smux_getresp_send (oid, oid_len, reqid, ret, 3, ASN_NULL, NULL, 0); + long reqid; + oid oid[MAX_OID_LEN]; + size_t oid_len; + u_char val_type; + void *val; + size_t val_len; + int ret; + + if (debug_smux) + zlog_debug("SMUX GET message parse: len %zd", len); + + /* Parse GET message header. */ + ptr = smux_parse_get_header(ptr, &len, &reqid); + + /* Parse GET message object ID. We needn't the value come */ + ptr = smux_var(ptr, len, oid, &oid_len, NULL, NULL, NULL); + + /* Traditional getstatptr. */ + if (exact) + ret = smux_get(oid, &oid_len, exact, &val_type, &val, &val_len); + else + ret = smux_getnext(oid, &oid_len, exact, &val_type, &val, + &val_len); + + /* Return result. */ + if (ret == 0) + smux_getresp_send(oid, oid_len, reqid, 0, 0, val_type, val, + val_len); + else + smux_getresp_send(oid, oid_len, reqid, ret, 3, ASN_NULL, NULL, + 0); } /* Parse SMUX_CLOSE message. */ -static void -smux_parse_close (u_char *ptr, int len) +static void smux_parse_close(u_char *ptr, int len) { - long reason = 0; - - while (len--) - { - reason = (reason << 8) | (long) *ptr; - ptr++; - } - zlog_info ("SMUX_CLOSE with reason: %ld", reason); + long reason = 0; + + while (len--) { + reason = (reason << 8) | (long)*ptr; + ptr++; + } + zlog_info("SMUX_CLOSE with reason: %ld", reason); } /* SMUX_RRSP message. */ -static void -smux_parse_rrsp (u_char *ptr, size_t len) +static void smux_parse_rrsp(u_char *ptr, size_t len) { - u_char val; - long errstat; - - ptr = asn_parse_int (ptr, &len, &val, &errstat, sizeof (errstat)); + u_char val; + long errstat; - if (debug_smux) - zlog_debug ("SMUX_RRSP value: %d errstat: %ld", val, errstat); + ptr = asn_parse_int(ptr, &len, &val, &errstat, sizeof(errstat)); + + if (debug_smux) + zlog_debug("SMUX_RRSP value: %d errstat: %ld", val, errstat); } /* Parse SMUX message. */ -static int -smux_parse (u_char *ptr, size_t len) +static int smux_parse(u_char *ptr, size_t len) { - /* This buffer we'll use for SOUT message. We could allocate it with - malloc and save only static pointer/lenght, but IMHO static - buffer is a faster solusion. */ - static u_char sout_save_buff[SMUXMAXPKTSIZE]; - static int sout_save_len = 0; + /* This buffer we'll use for SOUT message. We could allocate it with + malloc and save only static pointer/lenght, but IMHO static + buffer is a faster solusion. */ + static u_char sout_save_buff[SMUXMAXPKTSIZE]; + static int sout_save_len = 0; - int len_income = len; /* see note below: YYY */ - u_char type; - u_char rollback; + int len_income = len; /* see note below: YYY */ + u_char type; + u_char rollback; - rollback = ptr[2]; /* important only for SMUX_SOUT */ + rollback = ptr[2]; /* important only for SMUX_SOUT */ process_rest: /* see note below: YYY */ - /* Parse SMUX message type and subsequent length. */ - ptr = asn_parse_header (ptr, &len, &type); - - if (debug_smux) - zlog_debug ("SMUX message received type: %d rest len: %zd", type, len); - - switch (type) - { - case SMUX_OPEN: - /* Open must be not send from SNMP agent. */ - zlog_warn ("SMUX_OPEN received: resetting connection."); - return -1; - break; - case SMUX_RREQ: - /* SMUX_RREQ message is invalid for us. */ - zlog_warn ("SMUX_RREQ received: resetting connection."); - return -1; - break; - case SMUX_SOUT: - /* SMUX_SOUT message is now valied for us. */ - if (debug_smux) - zlog_debug ("SMUX_SOUT(%s)", rollback ? "rollback" : "commit"); - - if (sout_save_len > 0) - { - smux_parse_set (sout_save_buff, sout_save_len, rollback ? FREE : COMMIT); - sout_save_len = 0; - } - else - zlog_warn ("SMUX_SOUT sout_save_len=%d - invalid", (int) sout_save_len); - - if (len_income > 3) - { - /* YYY: this strange code has to solve the "slow peer" - problem: When agent sends SMUX_SOUT message it doesn't - wait any responce and may send some next message to - subagent. Then the peer in 'smux_read()' will recieve - from socket the 'concatenated' buffer, contaning both - SMUX_SOUT message and the next one - (SMUX_GET/SMUX_GETNEXT/SMUX_GET). So we should check: if - the buffer is longer than 3 ( length of SMUX_SOUT ), we - must process the rest of it. This effect may be observed - if 'debug_smux' is set to '1' */ - ptr++; - len = len_income - 3; - goto process_rest; - } - break; - case SMUX_GETRSP: - /* SMUX_GETRSP message is invalid for us. */ - zlog_warn ("SMUX_GETRSP received: resetting connection."); - return -1; - break; - case SMUX_CLOSE: - /* Close SMUX connection. */ - if (debug_smux) - zlog_debug ("SMUX_CLOSE"); - smux_parse_close (ptr, len); - return -1; - break; - case SMUX_RRSP: - /* This is response for register message. */ - if (debug_smux) - zlog_debug ("SMUX_RRSP"); - smux_parse_rrsp (ptr, len); - break; - case SMUX_GET: - /* Exact request for object id. */ - if (debug_smux) - zlog_debug ("SMUX_GET"); - smux_parse_get (ptr, len, 1); - break; - case SMUX_GETNEXT: - /* Next request for object id. */ - if (debug_smux) - zlog_debug ("SMUX_GETNEXT"); - smux_parse_get (ptr, len, 0); - break; - case SMUX_SET: - /* SMUX_SET is supported with some limitations. */ - if (debug_smux) - zlog_debug ("SMUX_SET"); - - /* save the data for future SMUX_SOUT */ - memcpy (sout_save_buff, ptr, len); - sout_save_len = len; - smux_parse_set (ptr, len, RESERVE1); - break; - default: - zlog_info ("Unknown type: %d", type); - break; - } - return 0; + /* Parse SMUX message type and subsequent length. */ + ptr = asn_parse_header(ptr, &len, &type); + + if (debug_smux) + zlog_debug("SMUX message received type: %d rest len: %zd", type, + len); + + switch (type) { + case SMUX_OPEN: + /* Open must be not send from SNMP agent. */ + zlog_warn("SMUX_OPEN received: resetting connection."); + return -1; + break; + case SMUX_RREQ: + /* SMUX_RREQ message is invalid for us. */ + zlog_warn("SMUX_RREQ received: resetting connection."); + return -1; + break; + case SMUX_SOUT: + /* SMUX_SOUT message is now valied for us. */ + if (debug_smux) + zlog_debug("SMUX_SOUT(%s)", + rollback ? "rollback" : "commit"); + + if (sout_save_len > 0) { + smux_parse_set(sout_save_buff, sout_save_len, + rollback ? FREE : COMMIT); + sout_save_len = 0; + } else + zlog_warn("SMUX_SOUT sout_save_len=%d - invalid", + (int)sout_save_len); + + if (len_income > 3) { + /* YYY: this strange code has to solve the "slow peer" + problem: When agent sends SMUX_SOUT message it + doesn't + wait any responce and may send some next message to + subagent. Then the peer in 'smux_read()' will recieve + from socket the 'concatenated' buffer, contaning both + SMUX_SOUT message and the next one + (SMUX_GET/SMUX_GETNEXT/SMUX_GET). So we should check: + if + the buffer is longer than 3 ( length of SMUX_SOUT ), + we + must process the rest of it. This effect may be + observed + if 'debug_smux' is set to '1' */ + ptr++; + len = len_income - 3; + goto process_rest; + } + break; + case SMUX_GETRSP: + /* SMUX_GETRSP message is invalid for us. */ + zlog_warn("SMUX_GETRSP received: resetting connection."); + return -1; + break; + case SMUX_CLOSE: + /* Close SMUX connection. */ + if (debug_smux) + zlog_debug("SMUX_CLOSE"); + smux_parse_close(ptr, len); + return -1; + break; + case SMUX_RRSP: + /* This is response for register message. */ + if (debug_smux) + zlog_debug("SMUX_RRSP"); + smux_parse_rrsp(ptr, len); + break; + case SMUX_GET: + /* Exact request for object id. */ + if (debug_smux) + zlog_debug("SMUX_GET"); + smux_parse_get(ptr, len, 1); + break; + case SMUX_GETNEXT: + /* Next request for object id. */ + if (debug_smux) + zlog_debug("SMUX_GETNEXT"); + smux_parse_get(ptr, len, 0); + break; + case SMUX_SET: + /* SMUX_SET is supported with some limitations. */ + if (debug_smux) + zlog_debug("SMUX_SET"); + + /* save the data for future SMUX_SOUT */ + memcpy(sout_save_buff, ptr, len); + sout_save_len = len; + smux_parse_set(ptr, len, RESERVE1); + break; + default: + zlog_info("Unknown type: %d", type); + break; + } + return 0; } /* SMUX message read function. */ -static int -smux_read (struct thread *t) +static int smux_read(struct thread *t) { - int sock; - int len; - u_char buf[SMUXMAXPKTSIZE]; - int ret; - - /* Clear thread. */ - sock = THREAD_FD (t); - smux_read_thread = NULL; - - if (debug_smux) - zlog_debug ("SMUX read start"); - - /* Read message from SMUX socket. */ - len = recv (sock, buf, SMUXMAXPKTSIZE, 0); - - if (len < 0) - { - zlog_warn ("Can't read all SMUX packet: %s", safe_strerror (errno)); - close (sock); - smux_sock = -1; - smux_event (SMUX_CONNECT, 0); - return -1; - } - - if (len == 0) - { - zlog_warn ("SMUX connection closed: %d", sock); - close (sock); - smux_sock = -1; - smux_event (SMUX_CONNECT, 0); - return -1; - } - - if (debug_smux) - zlog_debug ("SMUX read len: %d", len); - - /* Parse the message. */ - ret = smux_parse (buf, len); - - if (ret < 0) - { - close (sock); - smux_sock = -1; - smux_event (SMUX_CONNECT, 0); - return -1; - } - - /* Regiser read thread. */ - smux_event (SMUX_READ, sock); - - return 0; + int sock; + int len; + u_char buf[SMUXMAXPKTSIZE]; + int ret; + + /* Clear thread. */ + sock = THREAD_FD(t); + smux_read_thread = NULL; + + if (debug_smux) + zlog_debug("SMUX read start"); + + /* Read message from SMUX socket. */ + len = recv(sock, buf, SMUXMAXPKTSIZE, 0); + + if (len < 0) { + zlog_warn("Can't read all SMUX packet: %s", + safe_strerror(errno)); + close(sock); + smux_sock = -1; + smux_event(SMUX_CONNECT, 0); + return -1; + } + + if (len == 0) { + zlog_warn("SMUX connection closed: %d", sock); + close(sock); + smux_sock = -1; + smux_event(SMUX_CONNECT, 0); + return -1; + } + + if (debug_smux) + zlog_debug("SMUX read len: %d", len); + + /* Parse the message. */ + ret = smux_parse(buf, len); + + if (ret < 0) { + close(sock); + smux_sock = -1; + smux_event(SMUX_CONNECT, 0); + return -1; + } + + /* Regiser read thread. */ + smux_event(SMUX_READ, sock); + + return 0; } -static int -smux_open (int sock) +static int smux_open(int sock) { - u_char buf[BUFSIZ]; - u_char *ptr; - size_t len; - long version; - const char progname[] = FRR_SMUX_NAME "-" FRR_VERSION; - - if (debug_smux) - { - smux_oid_dump ("SMUX open oid", smux_oid, smux_oid_len); - zlog_debug ("SMUX open progname: %s", progname); - zlog_debug ("SMUX open password: %s", smux_passwd); - } - - ptr = buf; - len = BUFSIZ; - - /* SMUX Header. As placeholder. */ - ptr = asn_build_header (ptr, &len, (u_char) SMUX_OPEN, 0); - - /* SMUX Open. */ - version = 0; - ptr = asn_build_int (ptr, &len, - (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), - &version, sizeof (version)); - - /* SMUX connection oid. */ - ptr = asn_build_objid (ptr, &len, - (u_char) - (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), - smux_oid, smux_oid_len); - - /* SMUX connection description. */ - ptr = asn_build_string (ptr, &len, - (u_char) - (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), - (const u_char *) progname, strlen (progname)); - - /* SMUX connection password. */ - ptr = asn_build_string (ptr, &len, - (u_char) - (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), - (u_char *)smux_passwd, strlen (smux_passwd)); - - /* Fill in real SMUX header. We exclude ASN header size (2). */ - len = BUFSIZ; - asn_build_header (buf, &len, (u_char) SMUX_OPEN, (ptr - buf) - 2); - - return send (sock, buf, (ptr - buf), 0); + u_char buf[BUFSIZ]; + u_char *ptr; + size_t len; + long version; + const char progname[] = FRR_SMUX_NAME "-" FRR_VERSION; + + if (debug_smux) { + smux_oid_dump("SMUX open oid", smux_oid, smux_oid_len); + zlog_debug("SMUX open progname: %s", progname); + zlog_debug("SMUX open password: %s", smux_passwd); + } + + ptr = buf; + len = BUFSIZ; + + /* SMUX Header. As placeholder. */ + ptr = asn_build_header(ptr, &len, (u_char)SMUX_OPEN, 0); + + /* SMUX Open. */ + version = 0; + ptr = asn_build_int(ptr, &len, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE + | ASN_INTEGER), + &version, sizeof(version)); + + /* SMUX connection oid. */ + ptr = asn_build_objid(ptr, &len, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE + | ASN_OBJECT_ID), + smux_oid, smux_oid_len); + + /* SMUX connection description. */ + ptr = asn_build_string(ptr, &len, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE + | ASN_OCTET_STR), + (const u_char *)progname, strlen(progname)); + + /* SMUX connection password. */ + ptr = asn_build_string(ptr, &len, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE + | ASN_OCTET_STR), + (u_char *)smux_passwd, strlen(smux_passwd)); + + /* Fill in real SMUX header. We exclude ASN header size (2). */ + len = BUFSIZ; + asn_build_header(buf, &len, (u_char)SMUX_OPEN, (ptr - buf) - 2); + + return send(sock, buf, (ptr - buf), 0); } /* `ename` is ignored. Instead of using the provided enterprise OID, @@ -930,399 +915,375 @@ smux_open (int sock) versions of Quagga. All other fields are used as they are intended. */ -int -smux_trap (struct variable *vp, size_t vp_len, - const oid *ename, size_t enamelen, - const oid *name, size_t namelen, - const oid *iname, size_t inamelen, - const struct trap_object *trapobj, size_t trapobjlen, - u_char sptrap) +int smux_trap(struct variable *vp, size_t vp_len, const oid *ename, + size_t enamelen, const oid *name, size_t namelen, + const oid *iname, size_t inamelen, + const struct trap_object *trapobj, size_t trapobjlen, + u_char sptrap) { - unsigned int i; - u_char buf[BUFSIZ]; - u_char *ptr; - size_t len, length; - struct in_addr addr; - unsigned long val; - u_char *h1, *h1e; - - ptr = buf; - len = BUFSIZ; - length = len; - - /* When SMUX connection is not established. */ - if (smux_sock < 0) - return 0; - - /* SMUX header. */ - ptr = asn_build_header (ptr, &len, (u_char) SMUX_TRAP, 0); - - /* Sub agent enterprise oid. */ - ptr = asn_build_objid (ptr, &len, - (u_char) - (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), - smux_oid, smux_oid_len); - - /* IP address. */ - addr.s_addr = 0; - ptr = asn_build_string (ptr, &len, - (u_char) - (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_IPADDRESS), - (u_char *)&addr, sizeof (addr)); - - /* Generic trap integer. */ - val = SNMP_TRAP_ENTERPRISESPECIFIC; - ptr = asn_build_int (ptr, &len, - (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), - (long *)&val, sizeof (val)); - - /* Specific trap integer. */ - val = sptrap; - ptr = asn_build_int (ptr, &len, - (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), - (long *)&val, sizeof (val)); - - /* Timeticks timestamp. */ - val = 0; - ptr = asn_build_unsigned_int (ptr, &len, - (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_TIMETICKS), - &val, sizeof (val)); - - /* Variables. */ - h1 = ptr; - ptr = asn_build_sequence (ptr, &len, - (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), - 0); - - - /* Iteration for each objects. */ - h1e = ptr; - for (i = 0; i < trapobjlen; i++) - { - int ret; - oid oid[MAX_OID_LEN]; - size_t oid_len; - void *val; - size_t val_len; - u_char val_type; - - /* Make OID. */ - if (trapobj[i].namelen > 0) - { - oid_copy (oid, name, namelen); - oid_copy (oid + namelen, trapobj[i].name, trapobj[i].namelen); - oid_copy (oid + namelen + trapobj[i].namelen, iname, inamelen); - oid_len = namelen + trapobj[i].namelen + inamelen; - } - else - { - oid_copy (oid, name, namelen); - oid_copy (oid + namelen, trapobj[i].name, trapobj[i].namelen * (-1)); - oid_len = namelen + trapobj[i].namelen * (-1) ; - } - - if (debug_smux) - { - smux_oid_dump ("Trap", name, namelen); - if (trapobj[i].namelen < 0) - smux_oid_dump ("Trap", - trapobj[i].name, (- 1) * (trapobj[i].namelen)); - else - { - smux_oid_dump ("Trap", trapobj[i].name, (trapobj[i].namelen)); - smux_oid_dump ("Trap", iname, inamelen); - } - smux_oid_dump ("Trap", oid, oid_len); - zlog_info ("BUFSIZ: %d // oid_len: %lu", BUFSIZ, (u_long)oid_len); - } - - ret = smux_get (oid, &oid_len, 1, &val_type, &val, &val_len); - - if (debug_smux) - zlog_debug ("smux_get result %d", ret); - - if (ret == 0) - ptr = snmp_build_var_op (ptr, oid, &oid_len, - val_type, val_len, val, &len); - } - - /* Now variable size is known, fill in size */ - asn_build_sequence(h1, &length, - (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), - ptr - h1e); - - /* Fill in size of whole sequence */ - len = BUFSIZ; - asn_build_header (buf, &len, (u_char) SMUX_TRAP, (ptr - buf) - 2); - - return send (smux_sock, buf, (ptr - buf), 0); + unsigned int i; + u_char buf[BUFSIZ]; + u_char *ptr; + size_t len, length; + struct in_addr addr; + unsigned long val; + u_char *h1, *h1e; + + ptr = buf; + len = BUFSIZ; + length = len; + + /* When SMUX connection is not established. */ + if (smux_sock < 0) + return 0; + + /* SMUX header. */ + ptr = asn_build_header(ptr, &len, (u_char)SMUX_TRAP, 0); + + /* Sub agent enterprise oid. */ + ptr = asn_build_objid(ptr, &len, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE + | ASN_OBJECT_ID), + smux_oid, smux_oid_len); + + /* IP address. */ + addr.s_addr = 0; + ptr = asn_build_string(ptr, &len, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE + | ASN_IPADDRESS), + (u_char *)&addr, sizeof(addr)); + + /* Generic trap integer. */ + val = SNMP_TRAP_ENTERPRISESPECIFIC; + ptr = asn_build_int(ptr, &len, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE + | ASN_INTEGER), + (long *)&val, sizeof(val)); + + /* Specific trap integer. */ + val = sptrap; + ptr = asn_build_int(ptr, &len, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE + | ASN_INTEGER), + (long *)&val, sizeof(val)); + + /* Timeticks timestamp. */ + val = 0; + ptr = asn_build_unsigned_int( + ptr, &len, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_TIMETICKS), &val, + sizeof(val)); + + /* Variables. */ + h1 = ptr; + ptr = asn_build_sequence(ptr, &len, + (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), 0); + + + /* Iteration for each objects. */ + h1e = ptr; + for (i = 0; i < trapobjlen; i++) { + int ret; + oid oid[MAX_OID_LEN]; + size_t oid_len; + void *val; + size_t val_len; + u_char val_type; + + /* Make OID. */ + if (trapobj[i].namelen > 0) { + oid_copy(oid, name, namelen); + oid_copy(oid + namelen, trapobj[i].name, + trapobj[i].namelen); + oid_copy(oid + namelen + trapobj[i].namelen, iname, + inamelen); + oid_len = namelen + trapobj[i].namelen + inamelen; + } else { + oid_copy(oid, name, namelen); + oid_copy(oid + namelen, trapobj[i].name, + trapobj[i].namelen * (-1)); + oid_len = namelen + trapobj[i].namelen * (-1); + } + + if (debug_smux) { + smux_oid_dump("Trap", name, namelen); + if (trapobj[i].namelen < 0) + smux_oid_dump("Trap", trapobj[i].name, + (-1) * (trapobj[i].namelen)); + else { + smux_oid_dump("Trap", trapobj[i].name, + (trapobj[i].namelen)); + smux_oid_dump("Trap", iname, inamelen); + } + smux_oid_dump("Trap", oid, oid_len); + zlog_info("BUFSIZ: %d // oid_len: %lu", BUFSIZ, + (u_long)oid_len); + } + + ret = smux_get(oid, &oid_len, 1, &val_type, &val, &val_len); + + if (debug_smux) + zlog_debug("smux_get result %d", ret); + + if (ret == 0) + ptr = snmp_build_var_op(ptr, oid, &oid_len, val_type, + val_len, val, &len); + } + + /* Now variable size is known, fill in size */ + asn_build_sequence(h1, &length, + (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), ptr - h1e); + + /* Fill in size of whole sequence */ + len = BUFSIZ; + asn_build_header(buf, &len, (u_char)SMUX_TRAP, (ptr - buf) - 2); + + return send(smux_sock, buf, (ptr - buf), 0); } -static int -smux_register (int sock) +static int smux_register(int sock) { - u_char buf[BUFSIZ]; - u_char *ptr; - int ret; - size_t len; - long priority; - long operation; - struct subtree *subtree; - struct listnode *node, *nnode; - - ret = 0; - - for (ALL_LIST_ELEMENTS (treelist, node, nnode, subtree)) - { - ptr = buf; - len = BUFSIZ; - - /* SMUX RReq Header. */ - ptr = asn_build_header (ptr, &len, (u_char) SMUX_RREQ, 0); - - /* Register MIB tree. */ - ptr = asn_build_objid (ptr, &len, - (u_char) - (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), - subtree->name, subtree->name_len); - - /* Priority. */ - priority = -1; - ptr = asn_build_int (ptr, &len, - (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), - &priority, sizeof (priority)); - - /* Operation. */ - operation = 2; /* Register R/W */ - ptr = asn_build_int (ptr, &len, - (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), - &operation, sizeof (operation)); - - if (debug_smux) - { - smux_oid_dump ("SMUX register oid", subtree->name, subtree->name_len); - zlog_debug ("SMUX register priority: %ld", priority); - zlog_debug ("SMUX register operation: %ld", operation); - } - - len = BUFSIZ; - asn_build_header (buf, &len, (u_char) SMUX_RREQ, (ptr - buf) - 2); - ret = send (sock, buf, (ptr - buf), 0); - if (ret < 0) - return ret; - } - return ret; + u_char buf[BUFSIZ]; + u_char *ptr; + int ret; + size_t len; + long priority; + long operation; + struct subtree *subtree; + struct listnode *node, *nnode; + + ret = 0; + + for (ALL_LIST_ELEMENTS(treelist, node, nnode, subtree)) { + ptr = buf; + len = BUFSIZ; + + /* SMUX RReq Header. */ + ptr = asn_build_header(ptr, &len, (u_char)SMUX_RREQ, 0); + + /* Register MIB tree. */ + ptr = asn_build_objid( + ptr, &len, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + subtree->name, subtree->name_len); + + /* Priority. */ + priority = -1; + ptr = asn_build_int( + ptr, &len, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + &priority, sizeof(priority)); + + /* Operation. */ + operation = 2; /* Register R/W */ + ptr = asn_build_int( + ptr, &len, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + &operation, sizeof(operation)); + + if (debug_smux) { + smux_oid_dump("SMUX register oid", subtree->name, + subtree->name_len); + zlog_debug("SMUX register priority: %ld", priority); + zlog_debug("SMUX register operation: %ld", operation); + } + + len = BUFSIZ; + asn_build_header(buf, &len, (u_char)SMUX_RREQ, (ptr - buf) - 2); + ret = send(sock, buf, (ptr - buf), 0); + if (ret < 0) + return ret; + } + return ret; } /* Try to connect to SNMP agent. */ -static int -smux_connect (struct thread *t) +static int smux_connect(struct thread *t) { - int ret; - - if (debug_smux) - zlog_debug ("SMUX connect try %d", fail + 1); - - /* Clear thread poner of myself. */ - smux_connect_thread = NULL; - - /* Make socket. Try to connect. */ - smux_sock = smux_socket (); - if (smux_sock < 0) - { - if (++fail < SMUX_MAX_FAILURE) - smux_event (SMUX_CONNECT, 0); - return 0; - } - - /* Send OPEN PDU. */ - ret = smux_open (smux_sock); - if (ret < 0) - { - zlog_warn ("SMUX open message send failed: %s", safe_strerror (errno)); - close (smux_sock); - smux_sock = -1; - if (++fail < SMUX_MAX_FAILURE) - smux_event (SMUX_CONNECT, 0); - return -1; - } - - /* Send any outstanding register PDUs. */ - ret = smux_register (smux_sock); - if (ret < 0) - { - zlog_warn ("SMUX register message send failed: %s", safe_strerror (errno)); - close (smux_sock); - smux_sock = -1; - if (++fail < SMUX_MAX_FAILURE) - smux_event (SMUX_CONNECT, 0); - return -1; - } - - /* Everything goes fine. */ - smux_event (SMUX_READ, smux_sock); - - return 0; + int ret; + + if (debug_smux) + zlog_debug("SMUX connect try %d", fail + 1); + + /* Clear thread poner of myself. */ + smux_connect_thread = NULL; + + /* Make socket. Try to connect. */ + smux_sock = smux_socket(); + if (smux_sock < 0) { + if (++fail < SMUX_MAX_FAILURE) + smux_event(SMUX_CONNECT, 0); + return 0; + } + + /* Send OPEN PDU. */ + ret = smux_open(smux_sock); + if (ret < 0) { + zlog_warn("SMUX open message send failed: %s", + safe_strerror(errno)); + close(smux_sock); + smux_sock = -1; + if (++fail < SMUX_MAX_FAILURE) + smux_event(SMUX_CONNECT, 0); + return -1; + } + + /* Send any outstanding register PDUs. */ + ret = smux_register(smux_sock); + if (ret < 0) { + zlog_warn("SMUX register message send failed: %s", + safe_strerror(errno)); + close(smux_sock); + smux_sock = -1; + if (++fail < SMUX_MAX_FAILURE) + smux_event(SMUX_CONNECT, 0); + return -1; + } + + /* Everything goes fine. */ + smux_event(SMUX_READ, smux_sock); + + return 0; } /* Clear all SMUX related resources. */ -static void -smux_stop (void) +static void smux_stop(void) { - if (smux_read_thread) - { - thread_cancel (smux_read_thread); - smux_read_thread = NULL; - } - - if (smux_connect_thread) - { - thread_cancel (smux_connect_thread); - smux_connect_thread = NULL; - } - - if (smux_sock >= 0) - { - close (smux_sock); - smux_sock = -1; - } -} + if (smux_read_thread) { + thread_cancel(smux_read_thread); + smux_read_thread = NULL; + } + if (smux_connect_thread) { + thread_cancel(smux_connect_thread); + smux_connect_thread = NULL; + } + if (smux_sock >= 0) { + close(smux_sock); + smux_sock = -1; + } +} -void -smux_event (enum smux_event event, int sock) + +void smux_event(enum smux_event event, int sock) { - switch (event) - { - case SMUX_SCHEDULE: - smux_connect_thread = NULL; - thread_add_event(smux_master, smux_connect, NULL, 0, - &smux_connect_thread); - break; - case SMUX_CONNECT: - smux_connect_thread = NULL; - thread_add_timer(smux_master, smux_connect, NULL, 10, - &smux_connect_thread); - break; - case SMUX_READ: - smux_read_thread = NULL; - thread_add_read(smux_master, smux_read, NULL, sock, &smux_read_thread); - break; - default: - break; - } + switch (event) { + case SMUX_SCHEDULE: + smux_connect_thread = NULL; + thread_add_event(smux_master, smux_connect, NULL, 0, + &smux_connect_thread); + break; + case SMUX_CONNECT: + smux_connect_thread = NULL; + thread_add_timer(smux_master, smux_connect, NULL, 10, + &smux_connect_thread); + break; + case SMUX_READ: + smux_read_thread = NULL; + thread_add_read(smux_master, smux_read, NULL, sock, + &smux_read_thread); + break; + default: + break; + } } -static int -smux_str2oid (const char *str, oid *oid, size_t *oid_len) +static int smux_str2oid(const char *str, oid *oid, size_t *oid_len) { - int len; - int val; - - len = 0; - val = 0; - *oid_len = 0; - - if (*str == '.') - str++; - if (*str == '\0') - return 0; - - while (1) - { - if (! isdigit (*str)) - return -1; - - while (isdigit (*str)) - { - val *= 10; - val += (*str - '0'); - str++; - } + int len; + int val; + + len = 0; + val = 0; + *oid_len = 0; + + if (*str == '.') + str++; + if (*str == '\0') + return 0; + + while (1) { + if (!isdigit(*str)) + return -1; + + while (isdigit(*str)) { + val *= 10; + val += (*str - '0'); + str++; + } - if (*str == '\0') - break; - if (*str != '.') - return -1; + if (*str == '\0') + break; + if (*str != '.') + return -1; - oid[len++] = val; - val = 0; - str++; - } + oid[len++] = val; + val = 0; + str++; + } - oid[len++] = val; - *oid_len = len; + oid[len++] = val; + *oid_len = len; - return 0; + return 0; } -static oid * -smux_oid_dup (oid *objid, size_t objid_len) +static oid *smux_oid_dup(oid *objid, size_t objid_len) { - oid *new; + oid *new; - new = XMALLOC (MTYPE_TMP, sizeof (oid) * objid_len); - oid_copy (new, objid, objid_len); + new = XMALLOC(MTYPE_TMP, sizeof(oid) * objid_len); + oid_copy(new, objid, objid_len); - return new; + return new; } -static int -smux_peer_oid (struct vty *vty, const char *oid_str, const char *passwd_str) +static int smux_peer_oid(struct vty *vty, const char *oid_str, + const char *passwd_str) { - int ret; - oid oid[MAX_OID_LEN]; - size_t oid_len; - - ret = smux_str2oid (oid_str, oid, &oid_len); - if (ret != 0) - { - vty_out (vty, "object ID malformed\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (smux_oid) - { - free (smux_oid); - smux_oid = NULL; - } - - /* careful, smux_passwd might point to string constant */ - if (smux_passwd) - { - free (smux_passwd); - smux_passwd = NULL; - } - - smux_oid = smux_oid_dup (oid, oid_len); - smux_oid_len = oid_len; - - if (passwd_str) - smux_passwd = strdup (passwd_str); - else - smux_passwd = strdup (""); - - return 0; + int ret; + oid oid[MAX_OID_LEN]; + size_t oid_len; + + ret = smux_str2oid(oid_str, oid, &oid_len); + if (ret != 0) { + vty_out(vty, "object ID malformed\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (smux_oid) { + free(smux_oid); + smux_oid = NULL; + } + + /* careful, smux_passwd might point to string constant */ + if (smux_passwd) { + free(smux_passwd); + smux_passwd = NULL; + } + + smux_oid = smux_oid_dup(oid, oid_len); + smux_oid_len = oid_len; + + if (passwd_str) + smux_passwd = strdup(passwd_str); + else + smux_passwd = strdup(""); + + return 0; } -static int -smux_peer_default (void) +static int smux_peer_default(void) { - if (smux_oid) - { - free (smux_oid); - smux_oid = NULL; - } - - /* careful, smux_passwd might be pointing at string constant */ - if (smux_passwd) - { - free (smux_passwd); - smux_passwd = NULL; - } - - return CMD_SUCCESS; + if (smux_oid) { + free(smux_oid); + smux_oid = NULL; + } + + /* careful, smux_passwd might be pointing at string constant */ + if (smux_passwd) { + free(smux_passwd); + smux_passwd = NULL; + } + + return CMD_SUCCESS; } DEFUN (smux_peer, @@ -1332,14 +1293,12 @@ DEFUN (smux_peer, "SNMP MUX peer settings\n" "Object ID used in SMUX peering\n") { - int idx_oid = 2; - if (smux_peer_oid (vty, argv[idx_oid]->arg, NULL) == 0) - { - smux_start(); - return CMD_SUCCESS; - } - else - return CMD_WARNING_CONFIG_FAILED; + int idx_oid = 2; + if (smux_peer_oid(vty, argv[idx_oid]->arg, NULL) == 0) { + smux_start(); + return CMD_SUCCESS; + } else + return CMD_WARNING_CONFIG_FAILED; } DEFUN (smux_peer_password, @@ -1350,14 +1309,12 @@ DEFUN (smux_peer_password, "SMUX peering object ID\n" "SMUX peering password\n") { - int idx_oid = 2; - if (smux_peer_oid (vty, argv[idx_oid]->arg, argv[3]->rg) == 0) - { - smux_start(); - return CMD_SUCCESS; - } - else - return CMD_WARNING_CONFIG_FAILED; + int idx_oid = 2; + if (smux_peer_oid(vty, argv[idx_oid]->arg, argv[3]->rg) == 0) { + smux_start(); + return CMD_SUCCESS; + } else + return CMD_WARNING_CONFIG_FAILED; } DEFUN (no_smux_peer, @@ -1369,84 +1326,77 @@ DEFUN (no_smux_peer, "SMUX peering object ID\n" "SMUX peering password\n") { - smux_stop(); - return smux_peer_default (); + smux_stop(); + return smux_peer_default(); } -static int -config_write_smux (struct vty *vty) +static int config_write_smux(struct vty *vty) { - int first = 1; - unsigned int i; - - if (smux_oid) - { - vty_out (vty, "smux peer "); - for (i = 0; i < smux_oid_len; i++) - { - vty_out (vty, "%s%d", first ? "" : ".", (int) smux_oid[i]); - first = 0; + int first = 1; + unsigned int i; + + if (smux_oid) { + vty_out(vty, "smux peer "); + for (i = 0; i < smux_oid_len; i++) { + vty_out(vty, "%s%d", first ? "" : ".", + (int)smux_oid[i]); + first = 0; + } + vty_out(vty, " %s\n", smux_passwd); } - vty_out (vty, " %s\n", smux_passwd); - } - return 0; + return 0; } /* Register subtree to smux master tree. */ -void -smux_register_mib (const char *descr, struct variable *var, - size_t width, int num, - oid name[], size_t namelen) +void smux_register_mib(const char *descr, struct variable *var, size_t width, + int num, oid name[], size_t namelen) { - struct subtree *tree; - - tree = (struct subtree *)malloc(sizeof(struct subtree)); - oid_copy (tree->name, name, namelen); - tree->name_len = namelen; - tree->variables = var; - tree->variables_num = num; - tree->variables_width = width; - tree->registered = 0; - listnode_add_sort(treelist, tree); + struct subtree *tree; + + tree = (struct subtree *)malloc(sizeof(struct subtree)); + oid_copy(tree->name, name, namelen); + tree->name_len = namelen; + tree->variables = var; + tree->variables_num = num; + tree->variables_width = width; + tree->registered = 0; + listnode_add_sort(treelist, tree); } /* Compare function to keep treelist sorted */ -static int -smux_tree_cmp(struct subtree *tree1, struct subtree *tree2) +static int smux_tree_cmp(struct subtree *tree1, struct subtree *tree2) { - return oid_compare(tree1->name, tree1->name_len, - tree2->name, tree2->name_len); + return oid_compare(tree1->name, tree1->name_len, tree2->name, + tree2->name_len); } /* Initialize some values then schedule first SMUX connection. */ -void -smux_init (struct thread_master *tm) +void smux_init(struct thread_master *tm) { - assert (tm); - /* copy callers thread master */ - smux_master = tm; - - /* Make MIB tree. */ - treelist = list_new(); - treelist->cmp = (int (*)(void *, void *))smux_tree_cmp; - - /* Install commands. */ - install_node (&smux_node, config_write_smux); - - install_element (CONFIG_NODE, &smux_peer_cmd); - install_element (CONFIG_NODE, &smux_peer_password_cmd); - install_element (CONFIG_NODE, &no_smux_peer_cmd); - install_element (CONFIG_NODE, &no_smux_peer_oid_cmd); - install_element (CONFIG_NODE, &no_smux_peer_oid_password_cmd); + assert(tm); + /* copy callers thread master */ + smux_master = tm; + + /* Make MIB tree. */ + treelist = list_new(); + treelist->cmp = (int (*)(void *, void *))smux_tree_cmp; + + /* Install commands. */ + install_node(&smux_node, config_write_smux); + + install_element(CONFIG_NODE, &smux_peer_cmd); + install_element(CONFIG_NODE, &smux_peer_password_cmd); + install_element(CONFIG_NODE, &no_smux_peer_cmd); + install_element(CONFIG_NODE, &no_smux_peer_oid_cmd); + install_element(CONFIG_NODE, &no_smux_peer_oid_password_cmd); } -void -smux_start(void) +void smux_start(void) { - /* Close any existing connections. */ - smux_stop(); + /* Close any existing connections. */ + smux_stop(); - /* Schedule first connection. */ - smux_event (SMUX_SCHEDULE, 0); + /* Schedule first connection. */ + smux_event(SMUX_SCHEDULE, 0); } #endif /* SNMP_SMUX */ diff --git a/lib/smux.h b/lib/smux.h index e94a7a9cc..987414c0d 100644 --- a/lib/smux.h +++ b/lib/smux.h @@ -41,43 +41,37 @@ #define IN_ADDR_SIZE sizeof(struct in_addr) #undef REGISTER_MIB -#define REGISTER_MIB(descr, var, vartype, theoid) \ - smux_register_mib(descr, (struct variable *)var, sizeof(struct vartype), \ - sizeof(var)/sizeof(struct vartype), \ - theoid, sizeof(theoid)/sizeof(oid)) - -struct trap_object -{ - int namelen; /* Negative if the object is not indexed */ - oid name[MAX_OID_LEN]; +#define REGISTER_MIB(descr, var, vartype, theoid) \ + smux_register_mib(descr, (struct variable *)var, \ + sizeof(struct vartype), \ + sizeof(var) / sizeof(struct vartype), theoid, \ + sizeof(theoid) / sizeof(oid)) + +struct trap_object { + int namelen; /* Negative if the object is not indexed */ + oid name[MAX_OID_LEN]; }; /* Declare SMUX return value. */ -#define SNMP_LOCAL_VARIABLES \ - static long snmp_int_val __attribute__ ((unused)); \ - static struct in_addr snmp_in_addr_val __attribute__ ((unused)); - -#define SNMP_INTEGER(V) \ - ( \ - *var_len = sizeof (snmp_int_val), \ - snmp_int_val = V, \ - (u_char *) &snmp_int_val \ - ) - -#define SNMP_IPADDRESS(V) \ - ( \ - *var_len = sizeof (struct in_addr), \ - snmp_in_addr_val = V, \ - (u_char *) &snmp_in_addr_val \ - ) - -extern void smux_init (struct thread_master *tm); -extern void smux_register_mib(const char *, struct variable *, - size_t, int, oid [], size_t); -extern int smux_header_generic (struct variable *, oid [], size_t *, - int, size_t *, WriteMethod **); -extern int smux_header_table (struct variable *, oid *, size_t *, - int, size_t *, WriteMethod **); +#define SNMP_LOCAL_VARIABLES \ + static long snmp_int_val __attribute__((unused)); \ + static struct in_addr snmp_in_addr_val __attribute__((unused)); + +#define SNMP_INTEGER(V) \ + (*var_len = sizeof(snmp_int_val), snmp_int_val = V, \ + (u_char *)&snmp_int_val) + +#define SNMP_IPADDRESS(V) \ + (*var_len = sizeof(struct in_addr), snmp_in_addr_val = V, \ + (u_char *)&snmp_in_addr_val) + +extern void smux_init(struct thread_master *tm); +extern void smux_register_mib(const char *, struct variable *, size_t, int, + oid[], size_t); +extern int smux_header_generic(struct variable *, oid[], size_t *, int, + size_t *, WriteMethod **); +extern int smux_header_table(struct variable *, oid *, size_t *, int, size_t *, + WriteMethod **); /* For traps, three OID are provided: @@ -100,16 +94,13 @@ extern int smux_header_table (struct variable *, oid *, size_t *, The use of the arguments may differ depending on the implementation used. */ -extern int smux_trap (struct variable *, size_t, - const oid *, size_t, - const oid *, size_t, - const oid *, size_t, - const struct trap_object *, size_t, - u_char); - -extern int oid_compare (const oid *, int, const oid *, int); -extern void oid2in_addr (oid [], int, struct in_addr *); -extern void *oid_copy (void *, const void *, size_t); -extern void oid_copy_addr (oid [], struct in_addr *, int); +extern int smux_trap(struct variable *, size_t, const oid *, size_t, + const oid *, size_t, const oid *, size_t, + const struct trap_object *, size_t, u_char); + +extern int oid_compare(const oid *, int, const oid *, int); +extern void oid2in_addr(oid[], int, struct in_addr *); +extern void *oid_copy(void *, const void *, size_t); +extern void oid_copy_addr(oid[], struct in_addr *, int); #endif /* _ZEBRA_SNMP_H */ diff --git a/lib/snmp.c b/lib/snmp.c index 7eb86e941..fefd7ba37 100644 --- a/lib/snmp.c +++ b/lib/snmp.c @@ -27,104 +27,96 @@ #define min(A,B) ((A) < (B) ? (A) : (B)) -int -oid_compare (const oid *o1, int o1_len, const oid *o2, int o2_len) +int oid_compare(const oid *o1, int o1_len, const oid *o2, int o2_len) { - int i; - - for (i = 0; i < min (o1_len, o2_len); i++) - { - if (o1[i] < o2[i]) - return -1; - else if (o1[i] > o2[i]) - return 1; - } - if (o1_len < o2_len) - return -1; - if (o1_len > o2_len) - return 1; - - return 0; + int i; + + for (i = 0; i < min(o1_len, o2_len); i++) { + if (o1[i] < o2[i]) + return -1; + else if (o1[i] > o2[i]) + return 1; + } + if (o1_len < o2_len) + return -1; + if (o1_len > o2_len) + return 1; + + return 0; } -void * -oid_copy (void *dest, const void *src, size_t size) +void *oid_copy(void *dest, const void *src, size_t size) { - return memcpy (dest, src, size * sizeof (oid)); + return memcpy(dest, src, size * sizeof(oid)); } -void -oid2in_addr (oid oid[], int len, struct in_addr *addr) +void oid2in_addr(oid oid[], int len, struct in_addr *addr) { - int i; - u_char *pnt; - - if (len == 0) - return; + int i; + u_char *pnt; - pnt = (u_char *) addr; + if (len == 0) + return; - for (i = 0; i < len; i++) - *pnt++ = oid[i]; + pnt = (u_char *)addr; + + for (i = 0; i < len; i++) + *pnt++ = oid[i]; } -void -oid_copy_addr (oid oid[], struct in_addr *addr, int len) +void oid_copy_addr(oid oid[], struct in_addr *addr, int len) { - int i; - u_char *pnt; - - if (len == 0) - return; + int i; + u_char *pnt; + + if (len == 0) + return; - pnt = (u_char *) addr; + pnt = (u_char *)addr; - for (i = 0; i < len; i++) - oid[i] = *pnt++; + for (i = 0; i < len; i++) + oid[i] = *pnt++; } -int -smux_header_generic (struct variable *v, oid *name, size_t *length, int exact, - size_t *var_len, WriteMethod **write_method) +int smux_header_generic(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, WriteMethod **write_method) { - oid fulloid[MAX_OID_LEN]; - int ret; + oid fulloid[MAX_OID_LEN]; + int ret; - oid_copy (fulloid, v->name, v->namelen); - fulloid[v->namelen] = 0; - /* Check against full instance. */ - ret = oid_compare (name, *length, fulloid, v->namelen + 1); + oid_copy(fulloid, v->name, v->namelen); + fulloid[v->namelen] = 0; + /* Check against full instance. */ + ret = oid_compare(name, *length, fulloid, v->namelen + 1); - /* Check single instance. */ - if ((exact && (ret != 0)) || (!exact && (ret >= 0))) - return MATCH_FAILED; + /* Check single instance. */ + if ((exact && (ret != 0)) || (!exact && (ret >= 0))) + return MATCH_FAILED; - /* In case of getnext, fill in full instance. */ - memcpy (name, fulloid, (v->namelen + 1) * sizeof (oid)); - *length = v->namelen + 1; + /* In case of getnext, fill in full instance. */ + memcpy(name, fulloid, (v->namelen + 1) * sizeof(oid)); + *length = v->namelen + 1; - *write_method = 0; - *var_len = sizeof(long); /* default to 'long' results */ + *write_method = 0; + *var_len = sizeof(long); /* default to 'long' results */ - return MATCH_SUCCEEDED; + return MATCH_SUCCEEDED; } -int -smux_header_table (struct variable *v, oid *name, size_t *length, int exact, - size_t *var_len, WriteMethod **write_method) +int smux_header_table(struct variable *v, oid *name, size_t *length, int exact, + size_t *var_len, WriteMethod **write_method) { - /* If the requested OID name is less than OID prefix we - handle, adjust it to our prefix. */ - if ((oid_compare (name, *length, v->name, v->namelen)) < 0) - { - if (exact) - return MATCH_FAILED; - oid_copy(name, v->name, v->namelen); - *length = v->namelen; - } - - *write_method = 0; - *var_len = sizeof(long); - - return MATCH_SUCCEEDED; + /* If the requested OID name is less than OID prefix we + handle, adjust it to our prefix. */ + if ((oid_compare(name, *length, v->name, v->namelen)) < 0) { + if (exact) + return MATCH_FAILED; + oid_copy(name, v->name, v->namelen); + *length = v->namelen; + } + + *write_method = 0; + *var_len = sizeof(long); + + return MATCH_SUCCEEDED; } diff --git a/lib/sockopt.c b/lib/sockopt.c index 83ea57483..d100991a3 100644 --- a/lib/sockopt.c +++ b/lib/sockopt.c @@ -28,173 +28,168 @@ #include "sockopt.h" #include "sockunion.h" -void -setsockopt_so_recvbuf (int sock, int size) +void setsockopt_so_recvbuf(int sock, int size) { - int orig_req = size; + int orig_req = size; - while (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size)) == -1) - size /= 2; + while (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) + == -1) + size /= 2; - if (size != orig_req) - zlog_warn ("%s: fd %d: SO_RCVBUF set to %d (requested %d)", __func__, sock, - size, orig_req); + if (size != orig_req) + zlog_warn("%s: fd %d: SO_RCVBUF set to %d (requested %d)", + __func__, sock, size, orig_req); } -void -setsockopt_so_sendbuf (const int sock, int size) +void setsockopt_so_sendbuf(const int sock, int size) { - int orig_req = size; + int orig_req = size; - while (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) == -1) - size /= 2; + while (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) + == -1) + size /= 2; - if (size != orig_req) - zlog_warn ("%s: fd %d: SO_SNDBUF set to %d (requested %d)", __func__, sock, - size, orig_req); + if (size != orig_req) + zlog_warn("%s: fd %d: SO_SNDBUF set to %d (requested %d)", + __func__, sock, size, orig_req); } -int -getsockopt_so_sendbuf (const int sock) +int getsockopt_so_sendbuf(const int sock) { - u_int32_t optval; - socklen_t optlen = sizeof (optval); - int ret = getsockopt (sock, SOL_SOCKET, SO_SNDBUF, - (char *)&optval, &optlen); - if (ret < 0) - { - zlog_err ("fd %d: can't getsockopt SO_SNDBUF: %d (%s)", - sock, errno, safe_strerror (errno)); - return ret; - } - return optval; + u_int32_t optval; + socklen_t optlen = sizeof(optval); + int ret = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&optval, + &optlen); + if (ret < 0) { + zlog_err("fd %d: can't getsockopt SO_SNDBUF: %d (%s)", sock, + errno, safe_strerror(errno)); + return ret; + } + return optval; } -static void * -getsockopt_cmsg_data (struct msghdr *msgh, int level, int type) +static void *getsockopt_cmsg_data(struct msghdr *msgh, int level, int type) { - struct cmsghdr *cmsg; - void *ptr = NULL; - - for (cmsg = ZCMSG_FIRSTHDR(msgh); - cmsg != NULL; - cmsg = CMSG_NXTHDR(msgh, cmsg)) - if (cmsg->cmsg_level == level && cmsg->cmsg_type) - return (ptr = CMSG_DATA(cmsg)); - - return NULL; + struct cmsghdr *cmsg; + void *ptr = NULL; + + for (cmsg = ZCMSG_FIRSTHDR(msgh); cmsg != NULL; + cmsg = CMSG_NXTHDR(msgh, cmsg)) + if (cmsg->cmsg_level == level && cmsg->cmsg_type) + return (ptr = CMSG_DATA(cmsg)); + + return NULL; } /* Set IPv6 packet info to the socket. */ -int -setsockopt_ipv6_pktinfo (int sock, int val) +int setsockopt_ipv6_pktinfo(int sock, int val) { - int ret; - -#ifdef IPV6_RECVPKTINFO /*2292bis-01*/ - ret = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val)); - if (ret < 0) - zlog_warn ("can't setsockopt IPV6_RECVPKTINFO : %s", safe_strerror (errno)); -#else /*RFC2292*/ - ret = setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, &val, sizeof(val)); - if (ret < 0) - zlog_warn ("can't setsockopt IPV6_PKTINFO : %s", safe_strerror (errno)); + int ret; + +#ifdef IPV6_RECVPKTINFO /*2292bis-01*/ + ret = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, + sizeof(val)); + if (ret < 0) + zlog_warn("can't setsockopt IPV6_RECVPKTINFO : %s", + safe_strerror(errno)); +#else /*RFC2292*/ + ret = setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, &val, sizeof(val)); + if (ret < 0) + zlog_warn("can't setsockopt IPV6_PKTINFO : %s", + safe_strerror(errno)); #endif /* INIA_IPV6 */ - return ret; + return ret; } /* Set multicast hops val to the socket. */ -int -setsockopt_ipv6_checksum (int sock, int val) +int setsockopt_ipv6_checksum(int sock, int val) { - int ret; + int ret; #ifdef GNU_LINUX - ret = setsockopt(sock, IPPROTO_RAW, IPV6_CHECKSUM, &val, sizeof(val)); + ret = setsockopt(sock, IPPROTO_RAW, IPV6_CHECKSUM, &val, sizeof(val)); #else - ret = setsockopt(sock, IPPROTO_IPV6, IPV6_CHECKSUM, &val, sizeof(val)); + ret = setsockopt(sock, IPPROTO_IPV6, IPV6_CHECKSUM, &val, sizeof(val)); #endif /* GNU_LINUX */ - if (ret < 0) - zlog_warn ("can't setsockopt IPV6_CHECKSUM"); - return ret; + if (ret < 0) + zlog_warn("can't setsockopt IPV6_CHECKSUM"); + return ret; } /* Set multicast hops val to the socket. */ -int -setsockopt_ipv6_multicast_hops (int sock, int val) +int setsockopt_ipv6_multicast_hops(int sock, int val) { - int ret; + int ret; - ret = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &val, sizeof(val)); - if (ret < 0) - zlog_warn ("can't setsockopt IPV6_MULTICAST_HOPS"); - return ret; + ret = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &val, + sizeof(val)); + if (ret < 0) + zlog_warn("can't setsockopt IPV6_MULTICAST_HOPS"); + return ret; } /* Set multicast hops val to the socket. */ -int -setsockopt_ipv6_unicast_hops (int sock, int val) +int setsockopt_ipv6_unicast_hops(int sock, int val) { - int ret; + int ret; - ret = setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &val, sizeof(val)); - if (ret < 0) - zlog_warn ("can't setsockopt IPV6_UNICAST_HOPS"); - return ret; + ret = setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &val, + sizeof(val)); + if (ret < 0) + zlog_warn("can't setsockopt IPV6_UNICAST_HOPS"); + return ret; } -int -setsockopt_ipv6_hoplimit (int sock, int val) +int setsockopt_ipv6_hoplimit(int sock, int val) { - int ret; - -#ifdef IPV6_RECVHOPLIMIT /*2292bis-01*/ - ret = setsockopt (sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &val, sizeof(val)); - if (ret < 0) - zlog_warn ("can't setsockopt IPV6_RECVHOPLIMIT"); -#else /*RFC2292*/ - ret = setsockopt (sock, IPPROTO_IPV6, IPV6_HOPLIMIT, &val, sizeof(val)); - if (ret < 0) - zlog_warn ("can't setsockopt IPV6_HOPLIMIT"); + int ret; + +#ifdef IPV6_RECVHOPLIMIT /*2292bis-01*/ + ret = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &val, + sizeof(val)); + if (ret < 0) + zlog_warn("can't setsockopt IPV6_RECVHOPLIMIT"); +#else /*RFC2292*/ + ret = setsockopt(sock, IPPROTO_IPV6, IPV6_HOPLIMIT, &val, sizeof(val)); + if (ret < 0) + zlog_warn("can't setsockopt IPV6_HOPLIMIT"); #endif - return ret; + return ret; } /* Set multicast loop zero to the socket. */ -int -setsockopt_ipv6_multicast_loop (int sock, int val) +int setsockopt_ipv6_multicast_loop(int sock, int val) { - int ret; - - ret = setsockopt (sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &val, - sizeof (val)); - if (ret < 0) - zlog_warn ("can't setsockopt IPV6_MULTICAST_LOOP"); - return ret; + int ret; + + ret = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &val, + sizeof(val)); + if (ret < 0) + zlog_warn("can't setsockopt IPV6_MULTICAST_LOOP"); + return ret; } -static int -getsockopt_ipv6_ifindex (struct msghdr *msgh) +static int getsockopt_ipv6_ifindex(struct msghdr *msgh) { - struct in6_pktinfo *pktinfo; - - pktinfo = getsockopt_cmsg_data (msgh, IPPROTO_IPV6, IPV6_PKTINFO); - - return pktinfo->ipi6_ifindex; + struct in6_pktinfo *pktinfo; + + pktinfo = getsockopt_cmsg_data(msgh, IPPROTO_IPV6, IPV6_PKTINFO); + + return pktinfo->ipi6_ifindex; } -int -setsockopt_ipv6_tclass(int sock, int tclass) +int setsockopt_ipv6_tclass(int sock, int tclass) { - int ret = 0; + int ret = 0; #ifdef IPV6_TCLASS /* RFC3542 */ - ret = setsockopt (sock, IPPROTO_IPV6, IPV6_TCLASS, &tclass, sizeof (tclass)); - if (ret < 0) - zlog_warn ("Can't set IPV6_TCLASS option for fd %d to %#x: %s", - sock, tclass, safe_strerror(errno)); + ret = setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS, &tclass, + sizeof(tclass)); + if (ret < 0) + zlog_warn("Can't set IPV6_TCLASS option for fd %d to %#x: %s", + sock, tclass, safe_strerror(errno)); #endif - return ret; + return ret; } /* @@ -218,238 +213,241 @@ setsockopt_ipv6_tclass(int sock, int tclass) * but this behavior should not be harmful if they behave the same way, * allow leaves, or implicitly leave all groups joined to down interfaces. */ -int -setsockopt_ipv4_multicast(int sock, - int optname, - struct in_addr if_addr, - unsigned int mcast_addr, - ifindex_t ifindex) +int setsockopt_ipv4_multicast(int sock, int optname, struct in_addr if_addr, + unsigned int mcast_addr, ifindex_t ifindex) { #ifdef HAVE_RFC3678 - struct group_req gr; - struct sockaddr_in *si; - int ret; - memset (&gr, 0, sizeof(gr)); - si = (struct sockaddr_in *)&gr.gr_group; - gr.gr_interface = ifindex; - si->sin_family = AF_INET; + struct group_req gr; + struct sockaddr_in *si; + int ret; + memset(&gr, 0, sizeof(gr)); + si = (struct sockaddr_in *)&gr.gr_group; + gr.gr_interface = ifindex; + si->sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - si->sin_len = sizeof(struct sockaddr_in); + si->sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - si->sin_addr.s_addr = mcast_addr; - ret = setsockopt(sock, IPPROTO_IP, (optname == IP_ADD_MEMBERSHIP) ? - MCAST_JOIN_GROUP : MCAST_LEAVE_GROUP, (void *)&gr, sizeof(gr)); - if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE)) - { - setsockopt(sock, IPPROTO_IP, MCAST_LEAVE_GROUP, (void *)&gr, sizeof(gr)); - ret = setsockopt(sock, IPPROTO_IP, MCAST_JOIN_GROUP, (void *)&gr, sizeof(gr)); - } - return ret; + si->sin_addr.s_addr = mcast_addr; + ret = setsockopt(sock, IPPROTO_IP, + (optname == IP_ADD_MEMBERSHIP) ? MCAST_JOIN_GROUP + : MCAST_LEAVE_GROUP, + (void *)&gr, sizeof(gr)); + if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) + && (errno == EADDRINUSE)) { + setsockopt(sock, IPPROTO_IP, MCAST_LEAVE_GROUP, (void *)&gr, + sizeof(gr)); + ret = setsockopt(sock, IPPROTO_IP, MCAST_JOIN_GROUP, + (void *)&gr, sizeof(gr)); + } + return ret; #elif defined(HAVE_STRUCT_IP_MREQN_IMR_IFINDEX) && !defined(__FreeBSD__) - struct ip_mreqn mreqn; - int ret; - - assert(optname == IP_ADD_MEMBERSHIP || optname == IP_DROP_MEMBERSHIP); - memset (&mreqn, 0, sizeof(mreqn)); - - mreqn.imr_multiaddr.s_addr = mcast_addr; - mreqn.imr_ifindex = ifindex; - - ret = setsockopt(sock, IPPROTO_IP, optname, - (void *)&mreqn, sizeof(mreqn)); - if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE)) - { - /* see above: handle possible problem when interface comes back up */ - char buf[1][INET_ADDRSTRLEN]; - zlog_info("setsockopt_ipv4_multicast attempting to drop and " - "re-add (fd %d, mcast %s, ifindex %u)", - sock, - inet_ntop(AF_INET, &mreqn.imr_multiaddr, - buf[0], sizeof(buf[0])), ifindex); - setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, - (void *)&mreqn, sizeof(mreqn)); - ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, - (void *)&mreqn, sizeof(mreqn)); - } - return ret; - - /* Example defines for another OS, boilerplate off other code in this - function, AND handle optname as per other sections for consistency !! */ - /* #elif defined(BOGON_NIX) && EXAMPLE_VERSION_CODE > -100000 */ - /* Add your favourite OS here! */ - -#elif defined(HAVE_BSD_STRUCT_IP_MREQ_HACK) /* #if OS_TYPE */ - /* standard BSD API */ - - struct ip_mreq mreq; - int ret; - - assert(optname == IP_ADD_MEMBERSHIP || optname == IP_DROP_MEMBERSHIP); - - - memset (&mreq, 0, sizeof(mreq)); - mreq.imr_multiaddr.s_addr = mcast_addr; + struct ip_mreqn mreqn; + int ret; + + assert(optname == IP_ADD_MEMBERSHIP || optname == IP_DROP_MEMBERSHIP); + memset(&mreqn, 0, sizeof(mreqn)); + + mreqn.imr_multiaddr.s_addr = mcast_addr; + mreqn.imr_ifindex = ifindex; + + ret = setsockopt(sock, IPPROTO_IP, optname, (void *)&mreqn, + sizeof(mreqn)); + if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) + && (errno == EADDRINUSE)) { + /* see above: handle possible problem when interface comes back + * up */ + char buf[1][INET_ADDRSTRLEN]; + zlog_info( + "setsockopt_ipv4_multicast attempting to drop and " + "re-add (fd %d, mcast %s, ifindex %u)", + sock, inet_ntop(AF_INET, &mreqn.imr_multiaddr, buf[0], + sizeof(buf[0])), + ifindex); + setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, (void *)&mreqn, + sizeof(mreqn)); + ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, + (void *)&mreqn, sizeof(mreqn)); + } + return ret; + +/* Example defines for another OS, boilerplate off other code in this + function, AND handle optname as per other sections for consistency !! */ +/* #elif defined(BOGON_NIX) && EXAMPLE_VERSION_CODE > -100000 */ +/* Add your favourite OS here! */ + +#elif defined(HAVE_BSD_STRUCT_IP_MREQ_HACK) /* #if OS_TYPE */ + /* standard BSD API */ + + struct ip_mreq mreq; + int ret; + + assert(optname == IP_ADD_MEMBERSHIP || optname == IP_DROP_MEMBERSHIP); + + + memset(&mreq, 0, sizeof(mreq)); + mreq.imr_multiaddr.s_addr = mcast_addr; #if !defined __OpenBSD__ - mreq.imr_interface.s_addr = htonl (ifindex); + mreq.imr_interface.s_addr = htonl(ifindex); #else - mreq.imr_interface.s_addr = if_addr.s_addr; + mreq.imr_interface.s_addr = if_addr.s_addr; #endif - ret = setsockopt (sock, IPPROTO_IP, optname, (void *)&mreq, sizeof(mreq)); - if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE)) - { - /* see above: handle possible problem when interface comes back up */ - char buf[1][INET_ADDRSTRLEN]; - zlog_info("setsockopt_ipv4_multicast attempting to drop and " - "re-add (fd %d, mcast %s, ifindex %u)", - sock, - inet_ntop(AF_INET, &mreq.imr_multiaddr, - buf[0], sizeof(buf[0])), ifindex); - setsockopt (sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, - (void *)&mreq, sizeof(mreq)); - ret = setsockopt (sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, - (void *)&mreq, sizeof(mreq)); - } - return ret; + ret = setsockopt(sock, IPPROTO_IP, optname, (void *)&mreq, + sizeof(mreq)); + if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) + && (errno == EADDRINUSE)) { + /* see above: handle possible problem when interface comes back + * up */ + char buf[1][INET_ADDRSTRLEN]; + zlog_info( + "setsockopt_ipv4_multicast attempting to drop and " + "re-add (fd %d, mcast %s, ifindex %u)", + sock, inet_ntop(AF_INET, &mreq.imr_multiaddr, buf[0], + sizeof(buf[0])), + ifindex); + setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, (void *)&mreq, + sizeof(mreq)); + ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, + (void *)&mreq, sizeof(mreq)); + } + return ret; #else - #error "Unsupported multicast API" +#error "Unsupported multicast API" #endif /* #if OS_TYPE */ - } /* * Set IP_MULTICAST_IF socket option in an OS-dependent manner. */ -int -setsockopt_ipv4_multicast_if(int sock, struct in_addr if_addr, - ifindex_t ifindex) +int setsockopt_ipv4_multicast_if(int sock, struct in_addr if_addr, + ifindex_t ifindex) { #ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX - struct ip_mreqn mreqn; - memset (&mreqn, 0, sizeof(mreqn)); + struct ip_mreqn mreqn; + memset(&mreqn, 0, sizeof(mreqn)); - mreqn.imr_ifindex = ifindex; - return setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (void *)&mreqn, sizeof(mreqn)); + mreqn.imr_ifindex = ifindex; + return setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (void *)&mreqn, + sizeof(mreqn)); - /* Example defines for another OS, boilerplate off other code in this - function */ - /* #elif defined(BOGON_NIX) && EXAMPLE_VERSION_CODE > -100000 */ - /* Add your favourite OS here! */ +/* Example defines for another OS, boilerplate off other code in this + function */ +/* #elif defined(BOGON_NIX) && EXAMPLE_VERSION_CODE > -100000 */ +/* Add your favourite OS here! */ #elif defined(HAVE_BSD_STRUCT_IP_MREQ_HACK) - struct in_addr m; + struct in_addr m; #if !defined __OpenBSD__ - m.s_addr = htonl (ifindex); + m.s_addr = htonl(ifindex); #else - m.s_addr = if_addr.s_addr; + m.s_addr = if_addr.s_addr; #endif - return setsockopt (sock, IPPROTO_IP, IP_MULTICAST_IF, (void *)&m, sizeof(m)); + return setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (void *)&m, + sizeof(m)); #elif defined(SUNOS_5) - char ifname[IF_NAMESIZE]; - struct ifaddrs *ifa, *ifap; - struct in_addr ifaddr; - - if (if_indextoname(ifindex, ifname) == NULL) - return -1; - - if (getifaddrs(&ifa) != 0) - return -1; - - for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) - { - struct sockaddr_in *sa; - - if (strcmp(ifap->ifa_name, ifname) != 0) - continue; - if (ifap->ifa_addr->sa_family != AF_INET) - continue; - sa = (struct sockaddr_in*)ifap->ifa_addr; - memcpy(&ifaddr, &sa->sin_addr, sizeof(ifaddr)); - break; - } - - freeifaddrs(ifa); - if (!ifap) /* This means we did not find an IP */ - return -1; - - return setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (void *)&ifaddr, sizeof(ifaddr)); + char ifname[IF_NAMESIZE]; + struct ifaddrs *ifa, *ifap; + struct in_addr ifaddr; + + if (if_indextoname(ifindex, ifname) == NULL) + return -1; + + if (getifaddrs(&ifa) != 0) + return -1; + + for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) { + struct sockaddr_in *sa; + + if (strcmp(ifap->ifa_name, ifname) != 0) + continue; + if (ifap->ifa_addr->sa_family != AF_INET) + continue; + sa = (struct sockaddr_in *)ifap->ifa_addr; + memcpy(&ifaddr, &sa->sin_addr, sizeof(ifaddr)); + break; + } + + freeifaddrs(ifa); + if (!ifap) /* This means we did not find an IP */ + return -1; + + return setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (void *)&ifaddr, + sizeof(ifaddr)); #else - #error "Unsupported multicast API" +#error "Unsupported multicast API" #endif } -int -setsockopt_ipv4_multicast_loop (int sock, u_char val) +int setsockopt_ipv4_multicast_loop(int sock, u_char val) { - int ret; + int ret; - ret = setsockopt (sock, IPPROTO_IP, IP_MULTICAST_LOOP, (void *) &val, - sizeof (val)); - if (ret < 0) - zlog_warn ("can't setsockopt IP_MULTICAST_LOOP"); + ret = setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, (void *)&val, + sizeof(val)); + if (ret < 0) + zlog_warn("can't setsockopt IP_MULTICAST_LOOP"); - return ret; + return ret; } -static int -setsockopt_ipv4_ifindex (int sock, ifindex_t val) +static int setsockopt_ipv4_ifindex(int sock, ifindex_t val) { - int ret; - -#if defined (IP_PKTINFO) - if ((ret = setsockopt (sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof (val))) < 0) - zlog_warn ("Can't set IP_PKTINFO option for fd %d to %d: %s", - sock,val,safe_strerror(errno)); -#elif defined (IP_RECVIF) - if ((ret = setsockopt (sock, IPPROTO_IP, IP_RECVIF, &val, sizeof (val))) < 0) - zlog_warn ("Can't set IP_RECVIF option for fd %d to %d: %s", - sock,val,safe_strerror(errno)); + int ret; + +#if defined(IP_PKTINFO) + if ((ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val))) + < 0) + zlog_warn("Can't set IP_PKTINFO option for fd %d to %d: %s", + sock, val, safe_strerror(errno)); +#elif defined(IP_RECVIF) + if ((ret = setsockopt(sock, IPPROTO_IP, IP_RECVIF, &val, sizeof(val))) + < 0) + zlog_warn("Can't set IP_RECVIF option for fd %d to %d: %s", + sock, val, safe_strerror(errno)); #else #warning "Neither IP_PKTINFO nor IP_RECVIF is available." #warning "Will not be able to receive link info." #warning "Things might be seriously broken.." - /* XXX Does this ever happen? Should there be a zlog_warn message here? */ - ret = -1; + /* XXX Does this ever happen? Should there be a zlog_warn message here? + */ + ret = -1; #endif - return ret; + return ret; } -int -setsockopt_ipv4_tos(int sock, int tos) +int setsockopt_ipv4_tos(int sock, int tos) { - int ret; + int ret; - ret = setsockopt (sock, IPPROTO_IP, IP_TOS, &tos, sizeof (tos)); - if (ret < 0) - zlog_warn ("Can't set IP_TOS option for fd %d to %#x: %s", - sock, tos, safe_strerror(errno)); - return ret; + ret = setsockopt(sock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); + if (ret < 0) + zlog_warn("Can't set IP_TOS option for fd %d to %#x: %s", sock, + tos, safe_strerror(errno)); + return ret; } -int -setsockopt_ifindex (int af, int sock, ifindex_t val) +int setsockopt_ifindex(int af, int sock, ifindex_t val) { - int ret = -1; - - switch (af) - { - case AF_INET: - ret = setsockopt_ipv4_ifindex (sock, val); - break; - case AF_INET6: - ret = setsockopt_ipv6_pktinfo (sock, val); - break; - default: - zlog_warn ("setsockopt_ifindex: unknown address family %d", af); - } - return ret; + int ret = -1; + + switch (af) { + case AF_INET: + ret = setsockopt_ipv4_ifindex(sock, val); + break; + case AF_INET6: + ret = setsockopt_ipv6_pktinfo(sock, val); + break; + default: + zlog_warn("setsockopt_ifindex: unknown address family %d", af); + } + return ret; } - + /* * Requires: msgh is not NULL and points to a valid struct msghdr, which * may or may not have control data about the incoming interface. @@ -457,225 +455,223 @@ setsockopt_ifindex (int af, int sock, ifindex_t val) * Returns the interface index (small integer >= 1) if it can be * determined, or else 0. */ -static ifindex_t -getsockopt_ipv4_ifindex (struct msghdr *msgh) +static ifindex_t getsockopt_ipv4_ifindex(struct msghdr *msgh) { - /* XXX: initialize to zero? (Always overwritten, so just cosmetic.) */ - ifindex_t ifindex = -1; + /* XXX: initialize to zero? (Always overwritten, so just cosmetic.) */ + ifindex_t ifindex = -1; #if defined(IP_PKTINFO) -/* Linux pktinfo based ifindex retrieval */ - struct in_pktinfo *pktinfo; - - pktinfo = - (struct in_pktinfo *)getsockopt_cmsg_data (msgh, IPPROTO_IP, IP_PKTINFO); - /* XXX Can pktinfo be NULL? Clean up post 0.98. */ - ifindex = pktinfo->ipi_ifindex; - + /* Linux pktinfo based ifindex retrieval */ + struct in_pktinfo *pktinfo; + + pktinfo = (struct in_pktinfo *)getsockopt_cmsg_data(msgh, IPPROTO_IP, + IP_PKTINFO); + /* XXX Can pktinfo be NULL? Clean up post 0.98. */ + ifindex = pktinfo->ipi_ifindex; + #elif defined(IP_RECVIF) - /* retrieval based on IP_RECVIF */ +/* retrieval based on IP_RECVIF */ #ifndef SUNOS_5 - /* BSD systems use a sockaddr_dl as the control message payload. */ - struct sockaddr_dl *sdl; + /* BSD systems use a sockaddr_dl as the control message payload. */ + struct sockaddr_dl *sdl; #else - /* SUNOS_5 uses an integer with the index. */ - ifindex_t *ifindex_p; + /* SUNOS_5 uses an integer with the index. */ + ifindex_t *ifindex_p; #endif /* SUNOS_5 */ #ifndef SUNOS_5 - /* BSD */ - sdl = - (struct sockaddr_dl *)getsockopt_cmsg_data (msgh, IPPROTO_IP, IP_RECVIF); - if (sdl != NULL) - ifindex = sdl->sdl_index; - else - ifindex = 0; + /* BSD */ + sdl = (struct sockaddr_dl *)getsockopt_cmsg_data(msgh, IPPROTO_IP, + IP_RECVIF); + if (sdl != NULL) + ifindex = sdl->sdl_index; + else + ifindex = 0; #else - /* - * Solaris. On Solaris 8, IP_RECVIF is defined, but the call to - * enable it fails with errno=99, and the struct msghdr has - * controllen 0. - */ - ifindex_p = (uint_t *)getsockopt_cmsg_data (msgh, IPPROTO_IP, IP_RECVIF); - if (ifindex_p != NULL) - ifindex = *ifindex_p; - else - ifindex = 0; + /* + * Solaris. On Solaris 8, IP_RECVIF is defined, but the call to + * enable it fails with errno=99, and the struct msghdr has + * controllen 0. + */ + ifindex_p = (uint_t *)getsockopt_cmsg_data(msgh, IPPROTO_IP, IP_RECVIF); + if (ifindex_p != NULL) + ifindex = *ifindex_p; + else + ifindex = 0; #endif /* SUNOS_5 */ #else - /* - * Neither IP_PKTINFO nor IP_RECVIF defined - warn at compile time. - * XXX Decide if this is a core service, or if daemons have to cope. - * Since Solaris 8 and OpenBSD seem not to provide it, it seems that - * daemons have to cope. - */ +/* + * Neither IP_PKTINFO nor IP_RECVIF defined - warn at compile time. + * XXX Decide if this is a core service, or if daemons have to cope. + * Since Solaris 8 and OpenBSD seem not to provide it, it seems that + * daemons have to cope. + */ #warning "getsockopt_ipv4_ifindex: Neither IP_PKTINFO nor IP_RECVIF defined." #warning "Some daemons may fail to operate correctly!" - ifindex = 0; + ifindex = 0; -#endif /* IP_PKTINFO */ +#endif /* IP_PKTINFO */ - return ifindex; + return ifindex; } /* return ifindex, 0 if none found */ -ifindex_t -getsockopt_ifindex (int af, struct msghdr *msgh) +ifindex_t getsockopt_ifindex(int af, struct msghdr *msgh) { - switch (af) - { - case AF_INET: - return (getsockopt_ipv4_ifindex (msgh)); - break; - case AF_INET6: - return (getsockopt_ipv6_ifindex (msgh)); - break; - default: - zlog_warn ("getsockopt_ifindex: unknown address family %d", af); - return 0; - } + switch (af) { + case AF_INET: + return (getsockopt_ipv4_ifindex(msgh)); + break; + case AF_INET6: + return (getsockopt_ipv6_ifindex(msgh)); + break; + default: + zlog_warn("getsockopt_ifindex: unknown address family %d", af); + return 0; + } } /* swab iph between order system uses for IP_HDRINCL and host order */ -void -sockopt_iphdrincl_swab_htosys (struct ip *iph) +void sockopt_iphdrincl_swab_htosys(struct ip *iph) { - /* BSD and derived take iph in network order, except for - * ip_len and ip_off - */ +/* BSD and derived take iph in network order, except for + * ip_len and ip_off + */ #ifndef HAVE_IP_HDRINCL_BSD_ORDER - iph->ip_len = htons(iph->ip_len); - iph->ip_off = htons(iph->ip_off); + iph->ip_len = htons(iph->ip_len); + iph->ip_off = htons(iph->ip_off); #endif /* HAVE_IP_HDRINCL_BSD_ORDER */ - iph->ip_id = htons(iph->ip_id); + iph->ip_id = htons(iph->ip_id); } -void -sockopt_iphdrincl_swab_systoh (struct ip *iph) +void sockopt_iphdrincl_swab_systoh(struct ip *iph) { #ifndef HAVE_IP_HDRINCL_BSD_ORDER - iph->ip_len = ntohs(iph->ip_len); - iph->ip_off = ntohs(iph->ip_off); + iph->ip_len = ntohs(iph->ip_len); + iph->ip_off = ntohs(iph->ip_off); #endif /* HAVE_IP_HDRINCL_BSD_ORDER */ - iph->ip_id = ntohs(iph->ip_id); + iph->ip_id = ntohs(iph->ip_id); } -int -sockopt_tcp_rtt (int sock) +int sockopt_tcp_rtt(int sock) { #ifdef TCP_INFO - struct tcp_info ti; - socklen_t len = sizeof(ti); + struct tcp_info ti; + socklen_t len = sizeof(ti); - if (getsockopt (sock, IPPROTO_TCP, TCP_INFO, &ti, &len) != 0) - return 0; + if (getsockopt(sock, IPPROTO_TCP, TCP_INFO, &ti, &len) != 0) + return 0; - return ti.tcpi_rtt / 1000; + return ti.tcpi_rtt / 1000; #else - return 0; + return 0; #endif } -int -sockopt_tcp_signature (int sock, union sockunion *su, const char *password) +int sockopt_tcp_signature(int sock, union sockunion *su, const char *password) { #if defined(HAVE_TCP_MD5_LINUX24) && defined(GNU_LINUX) - /* Support for the old Linux 2.4 TCP-MD5 patch, taken from Hasso Tepper's - * version of the Quagga patch (based on work by Rick Payne, and Bruce - * Simpson) - */ +/* Support for the old Linux 2.4 TCP-MD5 patch, taken from Hasso Tepper's + * version of the Quagga patch (based on work by Rick Payne, and Bruce + * Simpson) + */ #define TCP_MD5_AUTH 13 #define TCP_MD5_AUTH_ADD 1 #define TCP_MD5_AUTH_DEL 2 - struct tcp_rfc2385_cmd { - u_int8_t command; /* Command - Add/Delete */ - u_int32_t address; /* IPV4 address associated */ - u_int8_t keylen; /* MD5 Key len (do NOT assume 0 terminated ascii) */ - void *key; /* MD5 Key */ - } cmd; - struct in_addr *addr = &su->sin.sin_addr; - - cmd.command = (password != NULL ? TCP_MD5_AUTH_ADD : TCP_MD5_AUTH_DEL); - cmd.address = addr->s_addr; - cmd.keylen = (password != NULL ? strlen (password) : 0); - cmd.key = password; - - return setsockopt (sock, IPPROTO_TCP, TCP_MD5_AUTH, &cmd, sizeof cmd); - + struct tcp_rfc2385_cmd { + u_int8_t command; /* Command - Add/Delete */ + u_int32_t address; /* IPV4 address associated */ + u_int8_t keylen; /* MD5 Key len (do NOT assume 0 terminated + ascii) */ + void *key; /* MD5 Key */ + } cmd; + struct in_addr *addr = &su->sin.sin_addr; + + cmd.command = (password != NULL ? TCP_MD5_AUTH_ADD : TCP_MD5_AUTH_DEL); + cmd.address = addr->s_addr; + cmd.keylen = (password != NULL ? strlen(password) : 0); + cmd.key = password; + + return setsockopt(sock, IPPROTO_TCP, TCP_MD5_AUTH, &cmd, sizeof cmd); + #elif HAVE_DECL_TCP_MD5SIG - int ret; + int ret; #ifndef GNU_LINUX - /* - * XXX Need to do PF_KEY operation here to add/remove an SA entry, - * and add/remove an SP entry for this peer's packet flows also. - */ - int md5sig = password && *password ? 1 : 0; + /* + * XXX Need to do PF_KEY operation here to add/remove an SA entry, + * and add/remove an SP entry for this peer's packet flows also. + */ + int md5sig = password && *password ? 1 : 0; #else - int keylen = password ? strlen (password) : 0; - struct tcp_md5sig md5sig; - union sockunion *su2, *susock; - - /* Figure out whether the socket and the sockunion are the same family.. - * adding AF_INET to AF_INET6 needs to be v4 mapped, you'd think.. - */ - if (!(susock = sockunion_getsockname (sock))) - return -1; - - if (susock->sa.sa_family == su->sa.sa_family) - su2 = su; - else - { - /* oops.. */ - su2 = susock; - - if (su2->sa.sa_family == AF_INET) - { - sockunion_free (susock); - return 0; - } - - /* If this does not work, then all users of this sockopt will need to - * differentiate between IPv4 and IPv6, and keep seperate sockets for - * each. - * - * Sadly, it doesn't seem to work at present. It's unknown whether - * this is a bug or not. - */ - if (su2->sa.sa_family == AF_INET6 - && su->sa.sa_family == AF_INET) - { - su2->sin6.sin6_family = AF_INET6; - /* V4Map the address */ - memset (&su2->sin6.sin6_addr, 0, sizeof (struct in6_addr)); - su2->sin6.sin6_addr.s6_addr32[2] = htonl(0xffff); - memcpy (&su2->sin6.sin6_addr.s6_addr32[3], &su->sin.sin_addr, 4); - } - } - - memset (&md5sig, 0, sizeof (md5sig)); - memcpy (&md5sig.tcpm_addr, su2, sizeof (*su2)); - md5sig.tcpm_keylen = keylen; - if (keylen) - memcpy (md5sig.tcpm_key, password, keylen); - sockunion_free (susock); + int keylen = password ? strlen(password) : 0; + struct tcp_md5sig md5sig; + union sockunion *su2, *susock; + + /* Figure out whether the socket and the sockunion are the same family.. + * adding AF_INET to AF_INET6 needs to be v4 mapped, you'd think.. + */ + if (!(susock = sockunion_getsockname(sock))) + return -1; + + if (susock->sa.sa_family == su->sa.sa_family) + su2 = su; + else { + /* oops.. */ + su2 = susock; + + if (su2->sa.sa_family == AF_INET) { + sockunion_free(susock); + return 0; + } + + /* If this does not work, then all users of this sockopt will + * need to + * differentiate between IPv4 and IPv6, and keep seperate + * sockets for + * each. + * + * Sadly, it doesn't seem to work at present. It's unknown + * whether + * this is a bug or not. + */ + if (su2->sa.sa_family == AF_INET6 + && su->sa.sa_family == AF_INET) { + su2->sin6.sin6_family = AF_INET6; + /* V4Map the address */ + memset(&su2->sin6.sin6_addr, 0, + sizeof(struct in6_addr)); + su2->sin6.sin6_addr.s6_addr32[2] = htonl(0xffff); + memcpy(&su2->sin6.sin6_addr.s6_addr32[3], + &su->sin.sin_addr, 4); + } + } + + memset(&md5sig, 0, sizeof(md5sig)); + memcpy(&md5sig.tcpm_addr, su2, sizeof(*su2)); + md5sig.tcpm_keylen = keylen; + if (keylen) + memcpy(md5sig.tcpm_key, password, keylen); + sockunion_free(susock); #endif /* GNU_LINUX */ - if ((ret = setsockopt (sock, IPPROTO_TCP, TCP_MD5SIG, &md5sig, sizeof md5sig)) < 0) - { - /* ENOENT is harmless. It is returned when we clear a password for which - one was not previously set. */ - if (ENOENT == errno) - ret = 0; - else - zlog_err ("sockopt_tcp_signature: setsockopt(%d): %s", - sock, safe_strerror(errno)); - } - return ret; -#else /* HAVE_TCP_MD5SIG */ - return -2; + if ((ret = setsockopt(sock, IPPROTO_TCP, TCP_MD5SIG, &md5sig, + sizeof md5sig)) + < 0) { + /* ENOENT is harmless. It is returned when we clear a password + for which + one was not previously set. */ + if (ENOENT == errno) + ret = 0; + else + zlog_err("sockopt_tcp_signature: setsockopt(%d): %s", + sock, safe_strerror(errno)); + } + return ret; +#else /* HAVE_TCP_MD5SIG */ + return -2; #endif /* !HAVE_TCP_MD5SIG */ } diff --git a/lib/sockopt.h b/lib/sockopt.h index d31fcaa41..7be36222d 100644 --- a/lib/sockopt.h +++ b/lib/sockopt.h @@ -23,17 +23,17 @@ #include "sockunion.h" -extern void setsockopt_so_recvbuf (int sock, int size); -extern void setsockopt_so_sendbuf (const int sock, int size); -extern int getsockopt_so_sendbuf (const int sock); +extern void setsockopt_so_recvbuf(int sock, int size); +extern void setsockopt_so_sendbuf(const int sock, int size); +extern int getsockopt_so_sendbuf(const int sock); -extern int setsockopt_ipv6_pktinfo (int, int); -extern int setsockopt_ipv6_checksum (int, int); -extern int setsockopt_ipv6_multicast_hops (int, int); -extern int setsockopt_ipv6_unicast_hops (int, int); -extern int setsockopt_ipv6_hoplimit (int, int); -extern int setsockopt_ipv6_multicast_loop (int, int); -extern int setsockopt_ipv6_tclass (int, int); +extern int setsockopt_ipv6_pktinfo(int, int); +extern int setsockopt_ipv6_checksum(int, int); +extern int setsockopt_ipv6_multicast_hops(int, int); +extern int setsockopt_ipv6_unicast_hops(int, int); +extern int setsockopt_ipv6_hoplimit(int, int); +extern int setsockopt_ipv6_multicast_loop(int, int); +extern int setsockopt_ipv6_tclass(int, int); #define SOPT_SIZE_CMSG_PKTINFO_IPV6() (sizeof (struct in6_pktinfo)); @@ -43,19 +43,19 @@ extern int setsockopt_ipv6_tclass (int, int); * that is unaware of which method is in use. * These values are without any alignment needed (see CMSG_SPACE in RFC3542). */ -#if defined (IP_PKTINFO) +#if defined(IP_PKTINFO) /* Linux in_pktinfo. */ #define SOPT_SIZE_CMSG_PKTINFO_IPV4() (CMSG_SPACE(sizeof (struct in_pktinfo))) /* XXX This should perhaps be defined even if IP_PKTINFO is not. */ -#define SOPT_SIZE_CMSG_PKTINFO(af) \ +#define SOPT_SIZE_CMSG_PKTINFO(af) \ ((af == AF_INET) ? SOPT_SIZE_CMSG_PKTINFO_IPV4() \ : SOPT_SIZE_CMSG_PKTINFO_IPV6() #endif /* IP_PKTINFO */ -#if defined (IP_RECVIF) +#if defined(IP_RECVIF) /* BSD/Solaris */ -#if defined (SUNOS_5) +#if defined(SUNOS_5) #define SOPT_SIZE_CMSG_RECVIF_IPV4() (sizeof (uint_t)) #else #define SOPT_SIZE_CMSG_RECVIF_IPV4() (sizeof (struct sockaddr_dl)) @@ -63,39 +63,39 @@ extern int setsockopt_ipv6_tclass (int, int); #endif /* IP_RECVIF */ /* SOPT_SIZE_CMSG_IFINDEX_IPV4 - portable type */ -#if defined (SOPT_SIZE_CMSG_PKTINFO) +#if defined(SOPT_SIZE_CMSG_PKTINFO) #define SOPT_SIZE_CMSG_IFINDEX_IPV4() SOPT_SIZE_CMSG_PKTINFO_IPV4() -#elif defined (SOPT_SIZE_CMSG_RECVIF_IPV4) +#elif defined(SOPT_SIZE_CMSG_RECVIF_IPV4) #define SOPT_SIZE_CMSG_IFINDEX_IPV4() SOPT_SIZE_CMSG_RECVIF_IPV4() -#else /* Nothing available */ +#else /* Nothing available */ #define SOPT_SIZE_CMSG_IFINDEX_IPV4() (sizeof (char *)) #endif /* SOPT_SIZE_CMSG_IFINDEX_IPV4 */ -#define SOPT_SIZE_CMSG_IFINDEX(af) \ +#define SOPT_SIZE_CMSG_IFINDEX(af) \ (((af) == AF_INET) : SOPT_SIZE_CMSG_IFINDEX_IPV4() \ ? SOPT_SIZE_CMSG_PKTINFO_IPV6()) extern int setsockopt_ipv4_multicast_if(int sock, struct in_addr if_addr, ifindex_t ifindex); extern int setsockopt_ipv4_multicast(int sock, int optname, - struct in_addr if_addr, - unsigned int mcast_addr, - ifindex_t ifindex); -extern int setsockopt_ipv4_multicast_loop (int sock, u_char val); + struct in_addr if_addr, + unsigned int mcast_addr, + ifindex_t ifindex); +extern int setsockopt_ipv4_multicast_loop(int sock, u_char val); extern int setsockopt_ipv4_tos(int sock, int tos); /* Ask for, and get, ifindex, by whatever method is supported. */ -extern int setsockopt_ifindex (int, int, ifindex_t); -extern ifindex_t getsockopt_ifindex (int, struct msghdr *); +extern int setsockopt_ifindex(int, int, ifindex_t); +extern ifindex_t getsockopt_ifindex(int, struct msghdr *); -/* swab the fields in iph between the host order and system order expected +/* swab the fields in iph between the host order and system order expected * for IP_HDRINCL. */ -extern void sockopt_iphdrincl_swab_htosys (struct ip *iph); -extern void sockopt_iphdrincl_swab_systoh (struct ip *iph); +extern void sockopt_iphdrincl_swab_htosys(struct ip *iph); +extern void sockopt_iphdrincl_swab_systoh(struct ip *iph); -extern int sockopt_tcp_rtt (int); +extern int sockopt_tcp_rtt(int); extern int sockopt_tcp_signature(int sock, union sockunion *su, - const char *password); + const char *password); #endif /*_ZEBRA_SOCKOPT_H */ diff --git a/lib/sockunion.c b/lib/sockunion.c index 423ad2044..af0054d6b 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -29,715 +29,654 @@ DEFINE_MTYPE_STATIC(LIB, SOCKUNION, "Socket union") -const char * -inet_sutop (const union sockunion *su, char *str) -{ - switch (su->sa.sa_family) - { - case AF_INET: - inet_ntop (AF_INET, &su->sin.sin_addr, str, INET_ADDRSTRLEN); - break; - case AF_INET6: - inet_ntop (AF_INET6, &su->sin6.sin6_addr, str, INET6_ADDRSTRLEN); - break; - } - return str; +const char *inet_sutop(const union sockunion *su, char *str) +{ + switch (su->sa.sa_family) { + case AF_INET: + inet_ntop(AF_INET, &su->sin.sin_addr, str, INET_ADDRSTRLEN); + break; + case AF_INET6: + inet_ntop(AF_INET6, &su->sin6.sin6_addr, str, INET6_ADDRSTRLEN); + break; + } + return str; } -int -str2sockunion (const char *str, union sockunion *su) +int str2sockunion(const char *str, union sockunion *su) { - int ret; + int ret; - memset (su, 0, sizeof (union sockunion)); + memset(su, 0, sizeof(union sockunion)); - ret = inet_pton (AF_INET, str, &su->sin.sin_addr); - if (ret > 0) /* Valid IPv4 address format. */ - { - su->sin.sin_family = AF_INET; + ret = inet_pton(AF_INET, str, &su->sin.sin_addr); + if (ret > 0) /* Valid IPv4 address format. */ + { + su->sin.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - su->sin.sin_len = sizeof(struct sockaddr_in); + su->sin.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - return 0; - } - ret = inet_pton (AF_INET6, str, &su->sin6.sin6_addr); - if (ret > 0) /* Valid IPv6 address format. */ - { - su->sin6.sin6_family = AF_INET6; + return 0; + } + ret = inet_pton(AF_INET6, str, &su->sin6.sin6_addr); + if (ret > 0) /* Valid IPv6 address format. */ + { + su->sin6.sin6_family = AF_INET6; #ifdef SIN6_LEN - su->sin6.sin6_len = sizeof(struct sockaddr_in6); + su->sin6.sin6_len = sizeof(struct sockaddr_in6); #endif /* SIN6_LEN */ - return 0; - } - return -1; + return 0; + } + return -1; } -const char * -sockunion2str (const union sockunion *su, char *buf, size_t len) +const char *sockunion2str(const union sockunion *su, char *buf, size_t len) { - switch (sockunion_family(su)) - { - case AF_UNSPEC: - snprintf (buf, len, "(unspec)"); - return buf; - case AF_INET: - return inet_ntop (AF_INET, &su->sin.sin_addr, buf, len); - case AF_INET6: - return inet_ntop (AF_INET6, &su->sin6.sin6_addr, buf, len); - } - snprintf (buf, len, "(af %d)", sockunion_family(su)); - return buf; + switch (sockunion_family(su)) { + case AF_UNSPEC: + snprintf(buf, len, "(unspec)"); + return buf; + case AF_INET: + return inet_ntop(AF_INET, &su->sin.sin_addr, buf, len); + case AF_INET6: + return inet_ntop(AF_INET6, &su->sin6.sin6_addr, buf, len); + } + snprintf(buf, len, "(af %d)", sockunion_family(su)); + return buf; } -union sockunion * -sockunion_str2su (const char *str) +union sockunion *sockunion_str2su(const char *str) { - union sockunion *su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion)); - - if (!str2sockunion (str, su)) - return su; - - XFREE (MTYPE_SOCKUNION, su); - return NULL; + union sockunion *su = XCALLOC(MTYPE_SOCKUNION, sizeof(union sockunion)); + + if (!str2sockunion(str, su)) + return su; + + XFREE(MTYPE_SOCKUNION, su); + return NULL; } /* Convert IPv4 compatible IPv6 address to IPv4 address. */ -static void -sockunion_normalise_mapped (union sockunion *su) -{ - struct sockaddr_in sin; - - if (su->sa.sa_family == AF_INET6 - && IN6_IS_ADDR_V4MAPPED (&su->sin6.sin6_addr)) - { - memset (&sin, 0, sizeof (struct sockaddr_in)); - sin.sin_family = AF_INET; - sin.sin_port = su->sin6.sin6_port; - memcpy (&sin.sin_addr, ((char *)&su->sin6.sin6_addr) + 12, 4); - memcpy (su, &sin, sizeof (struct sockaddr_in)); - } +static void sockunion_normalise_mapped(union sockunion *su) +{ + struct sockaddr_in sin; + + if (su->sa.sa_family == AF_INET6 + && IN6_IS_ADDR_V4MAPPED(&su->sin6.sin6_addr)) { + memset(&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; + sin.sin_port = su->sin6.sin6_port; + memcpy(&sin.sin_addr, ((char *)&su->sin6.sin6_addr) + 12, 4); + memcpy(su, &sin, sizeof(struct sockaddr_in)); + } } /* return sockunion structure : this function should be revised. */ -static const char * -sockunion_log (const union sockunion *su, char *buf, size_t len) +static const char *sockunion_log(const union sockunion *su, char *buf, + size_t len) { - switch (su->sa.sa_family) - { - case AF_INET: - return inet_ntop(AF_INET, &su->sin.sin_addr, buf, len); + switch (su->sa.sa_family) { + case AF_INET: + return inet_ntop(AF_INET, &su->sin.sin_addr, buf, len); - case AF_INET6: - return inet_ntop(AF_INET6, &(su->sin6.sin6_addr), buf, len); - break; + case AF_INET6: + return inet_ntop(AF_INET6, &(su->sin6.sin6_addr), buf, len); + break; - default: - snprintf (buf, len, "af_unknown %d ", su->sa.sa_family); - return buf; - } + default: + snprintf(buf, len, "af_unknown %d ", su->sa.sa_family); + return buf; + } } /* Return socket of sockunion. */ -int -sockunion_socket (const union sockunion *su) +int sockunion_socket(const union sockunion *su) { - int sock; + int sock; - sock = socket (su->sa.sa_family, SOCK_STREAM, 0); - if (sock < 0) - { - char buf[SU_ADDRSTRLEN]; - zlog_warn("Can't make socket for %s : %s", - sockunion_log(su, buf, SU_ADDRSTRLEN), safe_strerror(errno)); - return -1; - } + sock = socket(su->sa.sa_family, SOCK_STREAM, 0); + if (sock < 0) { + char buf[SU_ADDRSTRLEN]; + zlog_warn("Can't make socket for %s : %s", + sockunion_log(su, buf, SU_ADDRSTRLEN), + safe_strerror(errno)); + return -1; + } - return sock; + return sock; } /* Return accepted new socket file descriptor. */ -int -sockunion_accept (int sock, union sockunion *su) +int sockunion_accept(int sock, union sockunion *su) { - socklen_t len; - int client_sock; + socklen_t len; + int client_sock; - len = sizeof (union sockunion); - client_sock = accept (sock, (struct sockaddr *) su, &len); - - sockunion_normalise_mapped (su); - return client_sock; + len = sizeof(union sockunion); + client_sock = accept(sock, (struct sockaddr *)su, &len); + + sockunion_normalise_mapped(su); + return client_sock; } /* Return sizeof union sockunion. */ -static int -sockunion_sizeof (const union sockunion *su) -{ - int ret; - - ret = 0; - switch (su->sa.sa_family) - { - case AF_INET: - ret = sizeof (struct sockaddr_in); - break; - case AF_INET6: - ret = sizeof (struct sockaddr_in6); - break; - } - return ret; +static int sockunion_sizeof(const union sockunion *su) +{ + int ret; + + ret = 0; + switch (su->sa.sa_family) { + case AF_INET: + ret = sizeof(struct sockaddr_in); + break; + case AF_INET6: + ret = sizeof(struct sockaddr_in6); + break; + } + return ret; } /* sockunion_connect returns -1 : error occured 0 : connect success 1 : connect is in progress */ -enum connect_result -sockunion_connect (int fd, const union sockunion *peersu, unsigned short port, - ifindex_t ifindex) -{ - int ret; - int val; - union sockunion su; - - memcpy (&su, peersu, sizeof (union sockunion)); - - switch (su.sa.sa_family) - { - case AF_INET: - su.sin.sin_port = port; - break; - case AF_INET6: - su.sin6.sin6_port = port; +enum connect_result sockunion_connect(int fd, const union sockunion *peersu, + unsigned short port, ifindex_t ifindex) +{ + int ret; + int val; + union sockunion su; + + memcpy(&su, peersu, sizeof(union sockunion)); + + switch (su.sa.sa_family) { + case AF_INET: + su.sin.sin_port = port; + break; + case AF_INET6: + su.sin6.sin6_port = port; #ifdef KAME - if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr) && ifindex) - { - su.sin6.sin6_scope_id = ifindex; - SET_IN6_LINKLOCAL_IFINDEX (su.sin6.sin6_addr, ifindex); - } + if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr) && ifindex) { + su.sin6.sin6_scope_id = ifindex; + SET_IN6_LINKLOCAL_IFINDEX(su.sin6.sin6_addr, ifindex); + } #endif /* KAME */ - break; - } - - /* Make socket non-block. */ - val = fcntl (fd, F_GETFL, 0); - fcntl (fd, F_SETFL, val|O_NONBLOCK); - - /* Call connect function. */ - ret = connect (fd, (struct sockaddr *) &su, sockunion_sizeof (&su)); - - /* Immediate success */ - if (ret == 0) - { - fcntl (fd, F_SETFL, val); - return connect_success; - } - - /* If connect is in progress then return 1 else it's real error. */ - if (ret < 0) - { - if (errno != EINPROGRESS) - { - char str[SU_ADDRSTRLEN]; - zlog_info ("can't connect to %s fd %d : %s", - sockunion_log (&su, str, sizeof str), - fd, safe_strerror (errno)); - return connect_error; + break; + } + + /* Make socket non-block. */ + val = fcntl(fd, F_GETFL, 0); + fcntl(fd, F_SETFL, val | O_NONBLOCK); + + /* Call connect function. */ + ret = connect(fd, (struct sockaddr *)&su, sockunion_sizeof(&su)); + + /* Immediate success */ + if (ret == 0) { + fcntl(fd, F_SETFL, val); + return connect_success; + } + + /* If connect is in progress then return 1 else it's real error. */ + if (ret < 0) { + if (errno != EINPROGRESS) { + char str[SU_ADDRSTRLEN]; + zlog_info("can't connect to %s fd %d : %s", + sockunion_log(&su, str, sizeof str), fd, + safe_strerror(errno)); + return connect_error; + } } - } - fcntl (fd, F_SETFL, val); + fcntl(fd, F_SETFL, val); - return connect_in_progress; + return connect_in_progress; } /* Make socket from sockunion union. */ -int -sockunion_stream_socket (union sockunion *su) +int sockunion_stream_socket(union sockunion *su) { - int sock; + int sock; - if (su->sa.sa_family == 0) - su->sa.sa_family = AF_INET_UNION; + if (su->sa.sa_family == 0) + su->sa.sa_family = AF_INET_UNION; - sock = socket (su->sa.sa_family, SOCK_STREAM, 0); + sock = socket(su->sa.sa_family, SOCK_STREAM, 0); - if (sock < 0) - zlog_warn("can't make socket sockunion_stream_socket"); + if (sock < 0) + zlog_warn("can't make socket sockunion_stream_socket"); - return sock; + return sock; } /* Bind socket to specified address. */ -int -sockunion_bind (int sock, union sockunion *su, unsigned short port, - union sockunion *su_addr) +int sockunion_bind(int sock, union sockunion *su, unsigned short port, + union sockunion *su_addr) { - int size = 0; - int ret; + int size = 0; + int ret; - if (su->sa.sa_family == AF_INET) - { - size = sizeof (struct sockaddr_in); - su->sin.sin_port = htons (port); + if (su->sa.sa_family == AF_INET) { + size = sizeof(struct sockaddr_in); + su->sin.sin_port = htons(port); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - su->sin.sin_len = size; + su->sin.sin_len = size; #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - if (su_addr == NULL) - sockunion2ip (su) = htonl (INADDR_ANY); - } - else if (su->sa.sa_family == AF_INET6) - { - size = sizeof (struct sockaddr_in6); - su->sin6.sin6_port = htons (port); + if (su_addr == NULL) + sockunion2ip(su) = htonl(INADDR_ANY); + } else if (su->sa.sa_family == AF_INET6) { + size = sizeof(struct sockaddr_in6); + su->sin6.sin6_port = htons(port); #ifdef SIN6_LEN - su->sin6.sin6_len = size; + su->sin6.sin6_len = size; #endif /* SIN6_LEN */ - if (su_addr == NULL) - { + if (su_addr == NULL) { #ifdef LINUX_IPV6 - memset (&su->sin6.sin6_addr, 0, sizeof (struct in6_addr)); + memset(&su->sin6.sin6_addr, 0, sizeof(struct in6_addr)); #else - su->sin6.sin6_addr = in6addr_any; + su->sin6.sin6_addr = in6addr_any; #endif /* LINUX_IPV6 */ + } } - } - ret = bind (sock, (struct sockaddr *)su, size); - if (ret < 0) - { - char buf[SU_ADDRSTRLEN]; - zlog_warn("can't bind socket for %s : %s", - sockunion_log(su, buf, SU_ADDRSTRLEN), safe_strerror(errno)); - } + ret = bind(sock, (struct sockaddr *)su, size); + if (ret < 0) { + char buf[SU_ADDRSTRLEN]; + zlog_warn("can't bind socket for %s : %s", + sockunion_log(su, buf, SU_ADDRSTRLEN), + safe_strerror(errno)); + } - return ret; + return ret; } -int -sockopt_reuseaddr (int sock) +int sockopt_reuseaddr(int sock) { - int ret; - int on = 1; + int ret; + int on = 1; - ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, - (void *) &on, sizeof (on)); - if (ret < 0) - { - zlog_warn("can't set sockopt SO_REUSEADDR to socket %d", sock); - return -1; - } - return 0; + ret = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, + sizeof(on)); + if (ret < 0) { + zlog_warn("can't set sockopt SO_REUSEADDR to socket %d", sock); + return -1; + } + return 0; } #ifdef SO_REUSEPORT -int -sockopt_reuseport (int sock) +int sockopt_reuseport(int sock) { - int ret; - int on = 1; + int ret; + int on = 1; - ret = setsockopt (sock, SOL_SOCKET, SO_REUSEPORT, - (void *) &on, sizeof (on)); - if (ret < 0) - { - zlog_warn("can't set sockopt SO_REUSEPORT to socket %d", sock); - return -1; - } - return 0; + ret = setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (void *)&on, + sizeof(on)); + if (ret < 0) { + zlog_warn("can't set sockopt SO_REUSEPORT to socket %d", sock); + return -1; + } + return 0; } #else -int -sockopt_reuseport (int sock) +int sockopt_reuseport(int sock) { - return 0; + return 0; } #endif /* 0 */ -int -sockopt_ttl (int family, int sock, int ttl) +int sockopt_ttl(int family, int sock, int ttl) { - int ret; + int ret; #ifdef IP_TTL - if (family == AF_INET) - { - ret = setsockopt (sock, IPPROTO_IP, IP_TTL, - (void *) &ttl, sizeof (int)); - if (ret < 0) - { - zlog_warn("can't set sockopt IP_TTL %d to socket %d", ttl, sock); - return -1; + if (family == AF_INET) { + ret = setsockopt(sock, IPPROTO_IP, IP_TTL, (void *)&ttl, + sizeof(int)); + if (ret < 0) { + zlog_warn("can't set sockopt IP_TTL %d to socket %d", + ttl, sock); + return -1; + } + return 0; } - return 0; - } #endif /* IP_TTL */ - if (family == AF_INET6) - { - ret = setsockopt (sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, - (void *) &ttl, sizeof (int)); - if (ret < 0) - { - zlog_warn("can't set sockopt IPV6_UNICAST_HOPS %d to socket %d", - ttl, sock); - return -1; + if (family == AF_INET6) { + ret = setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, + (void *)&ttl, sizeof(int)); + if (ret < 0) { + zlog_warn( + "can't set sockopt IPV6_UNICAST_HOPS %d to socket %d", + ttl, sock); + return -1; + } + return 0; } - return 0; - } - return 0; + return 0; } -int -sockopt_cork (int sock, int onoff) +int sockopt_cork(int sock, int onoff) { #ifdef TCP_CORK - return setsockopt (sock, IPPROTO_TCP, TCP_CORK, &onoff, sizeof(onoff)); + return setsockopt(sock, IPPROTO_TCP, TCP_CORK, &onoff, sizeof(onoff)); #else - return 0; + return 0; #endif } int sockopt_mark_default(int sock, int mark, struct zebra_privs_t *cap) { #ifdef SO_MARK - int ret; + int ret; - if ( cap->change (ZPRIVS_RAISE) ) - zlog_err ("routing_socket: Can't raise privileges"); + if (cap->change(ZPRIVS_RAISE)) + zlog_err("routing_socket: Can't raise privileges"); - ret = setsockopt(sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)); + ret = setsockopt(sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)); - if ( cap->change (ZPRIVS_LOWER) ) - zlog_err ("routing_socket: Can't lower privileges"); + if (cap->change(ZPRIVS_LOWER)) + zlog_err("routing_socket: Can't lower privileges"); - return ret; + return ret; #else - return 0; + return 0; #endif } -int -sockopt_minttl (int family, int sock, int minttl) +int sockopt_minttl(int family, int sock, int minttl) { #ifdef IP_MINTTL - if (family == AF_INET) - { - int ret = setsockopt (sock, IPPROTO_IP, IP_MINTTL, &minttl, sizeof(minttl)); - if (ret < 0) - zlog_warn("can't set sockopt IP_MINTTL to %d on socket %d: %s", - minttl, sock, safe_strerror(errno)); - return ret; - } + if (family == AF_INET) { + int ret = setsockopt(sock, IPPROTO_IP, IP_MINTTL, &minttl, + sizeof(minttl)); + if (ret < 0) + zlog_warn( + "can't set sockopt IP_MINTTL to %d on socket %d: %s", + minttl, sock, safe_strerror(errno)); + return ret; + } #endif /* IP_MINTTL */ #ifdef IPV6_MINHOPCOUNT - if (family == AF_INET6) - { - int ret = setsockopt (sock, IPPROTO_IPV6, IPV6_MINHOPCOUNT, &minttl, sizeof(minttl)); - if (ret < 0) - zlog_warn("can't set sockopt IPV6_MINHOPCOUNT to %d on socket %d: %s", - minttl, sock, safe_strerror(errno)); - return ret; - } + if (family == AF_INET6) { + int ret = setsockopt(sock, IPPROTO_IPV6, IPV6_MINHOPCOUNT, + &minttl, sizeof(minttl)); + if (ret < 0) + zlog_warn( + "can't set sockopt IPV6_MINHOPCOUNT to %d on socket %d: %s", + minttl, sock, safe_strerror(errno)); + return ret; + } #endif - errno = EOPNOTSUPP; - return -1; + errno = EOPNOTSUPP; + return -1; } -int -sockopt_v6only (int family, int sock) +int sockopt_v6only(int family, int sock) { - int ret, on = 1; + int ret, on = 1; #ifdef IPV6_V6ONLY - if (family == AF_INET6) - { - ret = setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, - (void *) &on, sizeof (int)); - if (ret < 0) - { - zlog_warn("can't set sockopt IPV6_V6ONLY " "to socket %d", - sock); - return -1; + if (family == AF_INET6) { + ret = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&on, + sizeof(int)); + if (ret < 0) { + zlog_warn( + "can't set sockopt IPV6_V6ONLY " + "to socket %d", + sock); + return -1; + } + return 0; } - return 0; - } #endif /* IPV6_V6ONLY */ - return 0; + return 0; } /* If same family and same prefix return 1. */ -int -sockunion_same (const union sockunion *su1, const union sockunion *su2) -{ - int ret = 0; - - if (su1->sa.sa_family != su2->sa.sa_family) - return 0; - - switch (su1->sa.sa_family) - { - case AF_INET: - ret = memcmp (&su1->sin.sin_addr, &su2->sin.sin_addr, - sizeof (struct in_addr)); - break; - case AF_INET6: - ret = memcmp (&su1->sin6.sin6_addr, &su2->sin6.sin6_addr, - sizeof (struct in6_addr)); - if ((ret == 0) && IN6_IS_ADDR_LINKLOCAL(&su1->sin6.sin6_addr)) - { - /* compare interface indices */ - if (su1->sin6.sin6_scope_id && su2->sin6.sin6_scope_id) - ret = (su1->sin6.sin6_scope_id == su2->sin6.sin6_scope_id) ? 0 : 1; +int sockunion_same(const union sockunion *su1, const union sockunion *su2) +{ + int ret = 0; + + if (su1->sa.sa_family != su2->sa.sa_family) + return 0; + + switch (su1->sa.sa_family) { + case AF_INET: + ret = memcmp(&su1->sin.sin_addr, &su2->sin.sin_addr, + sizeof(struct in_addr)); + break; + case AF_INET6: + ret = memcmp(&su1->sin6.sin6_addr, &su2->sin6.sin6_addr, + sizeof(struct in6_addr)); + if ((ret == 0) && IN6_IS_ADDR_LINKLOCAL(&su1->sin6.sin6_addr)) { + /* compare interface indices */ + if (su1->sin6.sin6_scope_id && su2->sin6.sin6_scope_id) + ret = (su1->sin6.sin6_scope_id + == su2->sin6.sin6_scope_id) + ? 0 + : 1; + } + break; } - break; - } - if (ret == 0) - return 1; - else - return 0; + if (ret == 0) + return 1; + else + return 0; } -unsigned int -sockunion_hash (const union sockunion *su) +unsigned int sockunion_hash(const union sockunion *su) { - switch (sockunion_family(su)) - { - case AF_INET: - return jhash_1word(su->sin.sin_addr.s_addr, 0); - case AF_INET6: - return jhash2(su->sin6.sin6_addr.s6_addr32, ZEBRA_NUM_OF(su->sin6.sin6_addr.s6_addr32), 0); - } - return 0; + switch (sockunion_family(su)) { + case AF_INET: + return jhash_1word(su->sin.sin_addr.s_addr, 0); + case AF_INET6: + return jhash2(su->sin6.sin6_addr.s6_addr32, + ZEBRA_NUM_OF(su->sin6.sin6_addr.s6_addr32), 0); + } + return 0; } -size_t -family2addrsize(int family) +size_t family2addrsize(int family) { - switch (family) - { - case AF_INET: - return sizeof(struct in_addr); - case AF_INET6: - return sizeof(struct in6_addr); - } - return 0; + switch (family) { + case AF_INET: + return sizeof(struct in_addr); + case AF_INET6: + return sizeof(struct in6_addr); + } + return 0; } -size_t -sockunion_get_addrlen(const union sockunion *su) +size_t sockunion_get_addrlen(const union sockunion *su) { - return family2addrsize(sockunion_family(su)); + return family2addrsize(sockunion_family(su)); } -const u_char * -sockunion_get_addr(const union sockunion *su) +const u_char *sockunion_get_addr(const union sockunion *su) { - switch (sockunion_family(su)) - { - case AF_INET: - return (const u_char *) &su->sin.sin_addr.s_addr; - case AF_INET6: - return (const u_char *) &su->sin6.sin6_addr; - } - return NULL; + switch (sockunion_family(su)) { + case AF_INET: + return (const u_char *)&su->sin.sin_addr.s_addr; + case AF_INET6: + return (const u_char *)&su->sin6.sin6_addr; + } + return NULL; } -void -sockunion_set(union sockunion *su, int family, const u_char *addr, size_t bytes) +void sockunion_set(union sockunion *su, int family, const u_char *addr, + size_t bytes) { - if (family2addrsize(family) != bytes) - return; + if (family2addrsize(family) != bytes) + return; - sockunion_family(su) = family; - switch (family) - { - case AF_INET: - memcpy(&su->sin.sin_addr.s_addr, addr, bytes); - break; - case AF_INET6: - memcpy(&su->sin6.sin6_addr, addr, bytes); - break; - } + sockunion_family(su) = family; + switch (family) { + case AF_INET: + memcpy(&su->sin.sin_addr.s_addr, addr, bytes); + break; + case AF_INET6: + memcpy(&su->sin6.sin6_addr, addr, bytes); + break; + } } /* After TCP connection is established. Get local address and port. */ -union sockunion * -sockunion_getsockname (int fd) -{ - int ret; - socklen_t len; - union - { - struct sockaddr sa; - struct sockaddr_in sin; - struct sockaddr_in6 sin6; - char tmp_buffer[128]; - } name; - union sockunion *su; - - memset (&name, 0, sizeof name); - len = sizeof name; - - ret = getsockname (fd, (struct sockaddr *)&name, &len); - if (ret < 0) - { - zlog_warn ("Can't get local address and port by getsockname: %s", - safe_strerror (errno)); - return NULL; - } - - if (name.sa.sa_family == AF_INET) - { - su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion)); - memcpy (su, &name, sizeof (struct sockaddr_in)); - return su; - } - if (name.sa.sa_family == AF_INET6) - { - su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion)); - memcpy (su, &name, sizeof (struct sockaddr_in6)); - sockunion_normalise_mapped (su); - return su; - } - return NULL; +union sockunion *sockunion_getsockname(int fd) +{ + int ret; + socklen_t len; + union { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + char tmp_buffer[128]; + } name; + union sockunion *su; + + memset(&name, 0, sizeof name); + len = sizeof name; + + ret = getsockname(fd, (struct sockaddr *)&name, &len); + if (ret < 0) { + zlog_warn("Can't get local address and port by getsockname: %s", + safe_strerror(errno)); + return NULL; + } + + if (name.sa.sa_family == AF_INET) { + su = XCALLOC(MTYPE_SOCKUNION, sizeof(union sockunion)); + memcpy(su, &name, sizeof(struct sockaddr_in)); + return su; + } + if (name.sa.sa_family == AF_INET6) { + su = XCALLOC(MTYPE_SOCKUNION, sizeof(union sockunion)); + memcpy(su, &name, sizeof(struct sockaddr_in6)); + sockunion_normalise_mapped(su); + return su; + } + return NULL; } /* After TCP connection is established. Get remote address and port. */ -union sockunion * -sockunion_getpeername (int fd) -{ - int ret; - socklen_t len; - union - { - struct sockaddr sa; - struct sockaddr_in sin; - struct sockaddr_in6 sin6; - char tmp_buffer[128]; - } name; - union sockunion *su; - - memset (&name, 0, sizeof name); - len = sizeof name; - ret = getpeername (fd, (struct sockaddr *)&name, &len); - if (ret < 0) - { - zlog_warn("Can't get remote address and port: %s", safe_strerror(errno)); - return NULL; - } - - if (name.sa.sa_family == AF_INET) - { - su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion)); - memcpy (su, &name, sizeof (struct sockaddr_in)); - return su; - } - if (name.sa.sa_family == AF_INET6) - { - su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion)); - memcpy (su, &name, sizeof (struct sockaddr_in6)); - sockunion_normalise_mapped (su); - return su; - } - return NULL; +union sockunion *sockunion_getpeername(int fd) +{ + int ret; + socklen_t len; + union { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + char tmp_buffer[128]; + } name; + union sockunion *su; + + memset(&name, 0, sizeof name); + len = sizeof name; + ret = getpeername(fd, (struct sockaddr *)&name, &len); + if (ret < 0) { + zlog_warn("Can't get remote address and port: %s", + safe_strerror(errno)); + return NULL; + } + + if (name.sa.sa_family == AF_INET) { + su = XCALLOC(MTYPE_SOCKUNION, sizeof(union sockunion)); + memcpy(su, &name, sizeof(struct sockaddr_in)); + return su; + } + if (name.sa.sa_family == AF_INET6) { + su = XCALLOC(MTYPE_SOCKUNION, sizeof(union sockunion)); + memcpy(su, &name, sizeof(struct sockaddr_in6)); + sockunion_normalise_mapped(su); + return su; + } + return NULL; } /* Print sockunion structure */ -static void __attribute__ ((unused)) -sockunion_print (const union sockunion *su) -{ - if (su == NULL) - return; - - switch (su->sa.sa_family) - { - case AF_INET: - printf ("%s\n", inet_ntoa (su->sin.sin_addr)); - break; - case AF_INET6: - { - char buf [SU_ADDRSTRLEN]; - - printf ("%s\n", inet_ntop (AF_INET6, &(su->sin6.sin6_addr), - buf, sizeof (buf))); - } - break; +static void __attribute__((unused)) sockunion_print(const union sockunion *su) +{ + if (su == NULL) + return; + + switch (su->sa.sa_family) { + case AF_INET: + printf("%s\n", inet_ntoa(su->sin.sin_addr)); + break; + case AF_INET6: { + char buf[SU_ADDRSTRLEN]; + + printf("%s\n", inet_ntop(AF_INET6, &(su->sin6.sin6_addr), buf, + sizeof(buf))); + } break; #ifdef AF_LINK - case AF_LINK: - { - struct sockaddr_dl *sdl; - - sdl = (struct sockaddr_dl *)&(su->sa); - printf ("link#%d\n", sdl->sdl_index); - } - break; + case AF_LINK: { + struct sockaddr_dl *sdl; + + sdl = (struct sockaddr_dl *)&(su->sa); + printf("link#%d\n", sdl->sdl_index); + } break; #endif /* AF_LINK */ - default: - printf ("af_unknown %d\n", su->sa.sa_family); - break; - } + default: + printf("af_unknown %d\n", su->sa.sa_family); + break; + } } -static int -in6addr_cmp (const struct in6_addr *addr1, const struct in6_addr *addr2) +static int in6addr_cmp(const struct in6_addr *addr1, + const struct in6_addr *addr2) { - unsigned int i; - const u_char *p1, *p2; + unsigned int i; + const u_char *p1, *p2; - p1 = (const u_char *)addr1; - p2 = (const u_char *)addr2; + p1 = (const u_char *)addr1; + p2 = (const u_char *)addr2; - for (i = 0; i < sizeof (struct in6_addr); i++) - { - if (p1[i] > p2[i]) - return 1; - else if (p1[i] < p2[i]) - return -1; - } - return 0; + for (i = 0; i < sizeof(struct in6_addr); i++) { + if (p1[i] > p2[i]) + return 1; + else if (p1[i] < p2[i]) + return -1; + } + return 0; } -int -sockunion_cmp (const union sockunion *su1, const union sockunion *su2) +int sockunion_cmp(const union sockunion *su1, const union sockunion *su2) { - if (su1->sa.sa_family > su2->sa.sa_family) - return 1; - if (su1->sa.sa_family < su2->sa.sa_family) - return -1; + if (su1->sa.sa_family > su2->sa.sa_family) + return 1; + if (su1->sa.sa_family < su2->sa.sa_family) + return -1; - if (su1->sa.sa_family == AF_INET) - { - if (ntohl (sockunion2ip (su1)) == ntohl (sockunion2ip (su2))) + if (su1->sa.sa_family == AF_INET) { + if (ntohl(sockunion2ip(su1)) == ntohl(sockunion2ip(su2))) + return 0; + if (ntohl(sockunion2ip(su1)) > ntohl(sockunion2ip(su2))) + return 1; + else + return -1; + } + if (su1->sa.sa_family == AF_INET6) + return in6addr_cmp(&su1->sin6.sin6_addr, &su2->sin6.sin6_addr); return 0; - if (ntohl (sockunion2ip (su1)) > ntohl (sockunion2ip (su2))) - return 1; - else - return -1; - } - if (su1->sa.sa_family == AF_INET6) - return in6addr_cmp (&su1->sin6.sin6_addr, &su2->sin6.sin6_addr); - return 0; } /* Duplicate sockunion. */ -union sockunion * -sockunion_dup (const union sockunion *su) +union sockunion *sockunion_dup(const union sockunion *su) { - union sockunion *dup = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion)); - memcpy (dup, su, sizeof (union sockunion)); - return dup; + union sockunion *dup = + XCALLOC(MTYPE_SOCKUNION, sizeof(union sockunion)); + memcpy(dup, su, sizeof(union sockunion)); + return dup; } -void -sockunion_free (union sockunion *su) +void sockunion_free(union sockunion *su) { - XFREE (MTYPE_SOCKUNION, su); + XFREE(MTYPE_SOCKUNION, su); } -void -sockunion_init (union sockunion *su) +void sockunion_init(union sockunion *su) { - memset(su, 0, sizeof(union sockunion)); + memset(su, 0, sizeof(union sockunion)); } diff --git a/lib/sockunion.h b/lib/sockunion.h index 98c3e0ade..7b1c7ba9c 100644 --- a/lib/sockunion.h +++ b/lib/sockunion.h @@ -28,22 +28,16 @@ #include #endif -union sockunion -{ - struct sockaddr sa; - struct sockaddr_in sin; - struct sockaddr_in6 sin6; +union sockunion { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; #ifdef __OpenBSD__ - struct sockaddr_mpls smpls; + struct sockaddr_mpls smpls; #endif }; -enum connect_result -{ - connect_error, - connect_success, - connect_in_progress -}; +enum connect_result { connect_error, connect_success, connect_in_progress }; /* Default address family. */ #define AF_INET_UNION AF_INET6 @@ -55,11 +49,11 @@ enum connect_result stack. */ #ifdef KAME #define IN6_LINKLOCAL_IFINDEX(a) ((a).s6_addr[2] << 8 | (a).s6_addr[3]) -#define SET_IN6_LINKLOCAL_IFINDEX(a, i) \ - do { \ - (a).s6_addr[2] = ((i) >> 8) & 0xff; \ - (a).s6_addr[3] = (i) & 0xff; \ - } while (0) +#define SET_IN6_LINKLOCAL_IFINDEX(a, i) \ + do { \ + (a).s6_addr[2] = ((i) >> 8) & 0xff; \ + (a).s6_addr[3] = (i)&0xff; \ + } while (0) #else #define IN6_LINKLOCAL_IFINDEX(a) #define SET_IN6_LINKLOCAL_IFINDEX(a, i) @@ -70,38 +64,38 @@ enum connect_result #define sockunion2ip(X) (X)->sin.sin_addr.s_addr /* Prototypes. */ -extern int str2sockunion (const char *, union sockunion *); -extern const char *sockunion2str (const union sockunion *, char *, size_t); -extern int sockunion_cmp (const union sockunion *, const union sockunion *); -extern int sockunion_same (const union sockunion *, const union sockunion *); -extern unsigned int sockunion_hash (const union sockunion *); +extern int str2sockunion(const char *, union sockunion *); +extern const char *sockunion2str(const union sockunion *, char *, size_t); +extern int sockunion_cmp(const union sockunion *, const union sockunion *); +extern int sockunion_same(const union sockunion *, const union sockunion *); +extern unsigned int sockunion_hash(const union sockunion *); extern size_t family2addrsize(int family); extern size_t sockunion_get_addrlen(const union sockunion *); extern const u_char *sockunion_get_addr(const union sockunion *); -extern void sockunion_set(union sockunion *, int family, const u_char *addr, size_t bytes); +extern void sockunion_set(union sockunion *, int family, const u_char *addr, + size_t bytes); -extern union sockunion *sockunion_str2su (const char *str); -extern int sockunion_accept (int sock, union sockunion *); -extern int sockunion_stream_socket (union sockunion *); -extern int sockopt_reuseaddr (int); -extern int sockopt_reuseport (int); -extern int sockopt_v6only (int family, int sock); -extern int sockunion_bind (int sock, union sockunion *, - unsigned short, union sockunion *); -extern int sockopt_ttl (int family, int sock, int ttl); -extern int sockopt_minttl (int family, int sock, int minttl); -extern int sockopt_cork (int sock, int onoff); +extern union sockunion *sockunion_str2su(const char *str); +extern int sockunion_accept(int sock, union sockunion *); +extern int sockunion_stream_socket(union sockunion *); +extern int sockopt_reuseaddr(int); +extern int sockopt_reuseport(int); +extern int sockopt_v6only(int family, int sock); +extern int sockunion_bind(int sock, union sockunion *, unsigned short, + union sockunion *); +extern int sockopt_ttl(int family, int sock, int ttl); +extern int sockopt_minttl(int family, int sock, int minttl); +extern int sockopt_cork(int sock, int onoff); extern int sockopt_mark_default(int sock, int mark, struct zebra_privs_t *); -extern int sockunion_socket (const union sockunion *su); -extern const char *inet_sutop (const union sockunion *su, char *str); -extern enum connect_result sockunion_connect (int fd, const union sockunion *su, - unsigned short port, - ifindex_t); -extern union sockunion *sockunion_getsockname (int); -extern union sockunion *sockunion_getpeername (int); -extern union sockunion *sockunion_dup (const union sockunion *); -extern void sockunion_free (union sockunion *); -extern void sockunion_init (union sockunion *); +extern int sockunion_socket(const union sockunion *su); +extern const char *inet_sutop(const union sockunion *su, char *str); +extern enum connect_result sockunion_connect(int fd, const union sockunion *su, + unsigned short port, ifindex_t); +extern union sockunion *sockunion_getsockname(int); +extern union sockunion *sockunion_getpeername(int); +extern union sockunion *sockunion_dup(const union sockunion *); +extern void sockunion_free(union sockunion *); +extern void sockunion_init(union sockunion *); #endif /* _ZEBRA_SOCKUNION_H */ diff --git a/lib/spf_backoff.c b/lib/spf_backoff.c index 10f00426c..d075e70d4 100644 --- a/lib/spf_backoff.c +++ b/lib/spf_backoff.c @@ -37,230 +37,216 @@ DEFINE_MTYPE_STATIC(LIB, SPF_BACKOFF, "SPF backoff") DEFINE_MTYPE_STATIC(LIB, SPF_BACKOFF_NAME, "SPF backoff name") static bool debug_spf_backoff = false; -#define backoff_debug(...) \ - do \ - { \ - if (debug_spf_backoff) \ - zlog_debug(__VA_ARGS__); \ - } \ - while (0) +#define backoff_debug(...) \ + do { \ + if (debug_spf_backoff) \ + zlog_debug(__VA_ARGS__); \ + } while (0) enum spf_backoff_state { - SPF_BACKOFF_QUIET, - SPF_BACKOFF_SHORT_WAIT, - SPF_BACKOFF_LONG_WAIT + SPF_BACKOFF_QUIET, + SPF_BACKOFF_SHORT_WAIT, + SPF_BACKOFF_LONG_WAIT }; struct spf_backoff { - struct thread_master *m; - - /* Timers as per draft */ - long init_delay; - long short_delay; - long long_delay; - long holddown; - long timetolearn; - - /* State machine */ - enum spf_backoff_state state; - struct thread *t_holddown; - struct thread *t_timetolearn; - - /* For debugging */ - char *name; - struct timeval first_event_time; - struct timeval last_event_time; + struct thread_master *m; + + /* Timers as per draft */ + long init_delay; + long short_delay; + long long_delay; + long holddown; + long timetolearn; + + /* State machine */ + enum spf_backoff_state state; + struct thread *t_holddown; + struct thread *t_timetolearn; + + /* For debugging */ + char *name; + struct timeval first_event_time; + struct timeval last_event_time; }; -static const char * -spf_backoff_state2str(enum spf_backoff_state state) +static const char *spf_backoff_state2str(enum spf_backoff_state state) { - switch (state) - { - case SPF_BACKOFF_QUIET: - return "QUIET"; - case SPF_BACKOFF_SHORT_WAIT: - return "SHORT_WAIT"; - case SPF_BACKOFF_LONG_WAIT: - return "LONG_WAIT"; - } - return "???"; + switch (state) { + case SPF_BACKOFF_QUIET: + return "QUIET"; + case SPF_BACKOFF_SHORT_WAIT: + return "SHORT_WAIT"; + case SPF_BACKOFF_LONG_WAIT: + return "LONG_WAIT"; + } + return "???"; } -struct spf_backoff * -spf_backoff_new(struct thread_master *m, - const char *name, - long init_delay, - long short_delay, - long long_delay, - long holddown, - long timetolearn) +struct spf_backoff *spf_backoff_new(struct thread_master *m, const char *name, + long init_delay, long short_delay, + long long_delay, long holddown, + long timetolearn) { - struct spf_backoff *rv; + struct spf_backoff *rv; - rv = XCALLOC(MTYPE_SPF_BACKOFF, sizeof(*rv)); - rv->m = m; + rv = XCALLOC(MTYPE_SPF_BACKOFF, sizeof(*rv)); + rv->m = m; - rv->init_delay = init_delay; - rv->short_delay = short_delay; - rv->long_delay = long_delay; - rv->holddown = holddown; - rv->timetolearn = timetolearn; + rv->init_delay = init_delay; + rv->short_delay = short_delay; + rv->long_delay = long_delay; + rv->holddown = holddown; + rv->timetolearn = timetolearn; - rv->state = SPF_BACKOFF_QUIET; + rv->state = SPF_BACKOFF_QUIET; - rv->name = XSTRDUP(MTYPE_SPF_BACKOFF_NAME, name); - return rv; + rv->name = XSTRDUP(MTYPE_SPF_BACKOFF_NAME, name); + return rv; } -void -spf_backoff_free(struct spf_backoff *backoff) +void spf_backoff_free(struct spf_backoff *backoff) { - if (!backoff) - return; + if (!backoff) + return; - THREAD_TIMER_OFF(backoff->t_holddown); - THREAD_TIMER_OFF(backoff->t_timetolearn); - XFREE(MTYPE_SPF_BACKOFF_NAME, backoff->name); + THREAD_TIMER_OFF(backoff->t_holddown); + THREAD_TIMER_OFF(backoff->t_timetolearn); + XFREE(MTYPE_SPF_BACKOFF_NAME, backoff->name); - XFREE(MTYPE_SPF_BACKOFF, backoff); + XFREE(MTYPE_SPF_BACKOFF, backoff); } -static int -spf_backoff_timetolearn_elapsed(struct thread *thread) +static int spf_backoff_timetolearn_elapsed(struct thread *thread) { - struct spf_backoff *backoff = THREAD_ARG(thread); + struct spf_backoff *backoff = THREAD_ARG(thread); - backoff->t_timetolearn = NULL; - backoff->state = SPF_BACKOFF_LONG_WAIT; - backoff_debug("SPF Back-off(%s) TIMETOLEARN elapsed, move to state %s", - backoff->name, spf_backoff_state2str(backoff->state)); - return 0; + backoff->t_timetolearn = NULL; + backoff->state = SPF_BACKOFF_LONG_WAIT; + backoff_debug("SPF Back-off(%s) TIMETOLEARN elapsed, move to state %s", + backoff->name, spf_backoff_state2str(backoff->state)); + return 0; } -static int -spf_backoff_holddown_elapsed(struct thread *thread) +static int spf_backoff_holddown_elapsed(struct thread *thread) { - struct spf_backoff *backoff = THREAD_ARG(thread); - - backoff->t_holddown = NULL; - THREAD_TIMER_OFF(backoff->t_timetolearn); - timerclear(&backoff->first_event_time); - backoff->state = SPF_BACKOFF_QUIET; - backoff_debug("SPF Back-off(%s) HOLDDOWN elapsed, move to state %s", - backoff->name, spf_backoff_state2str(backoff->state)); - return 0; + struct spf_backoff *backoff = THREAD_ARG(thread); + + backoff->t_holddown = NULL; + THREAD_TIMER_OFF(backoff->t_timetolearn); + timerclear(&backoff->first_event_time); + backoff->state = SPF_BACKOFF_QUIET; + backoff_debug("SPF Back-off(%s) HOLDDOWN elapsed, move to state %s", + backoff->name, spf_backoff_state2str(backoff->state)); + return 0; } long spf_backoff_schedule(struct spf_backoff *backoff) { - long rv; - struct timeval now; - - gettimeofday(&now, NULL); - - backoff_debug("SPF Back-off(%s) schedule called in state %s", - backoff->name, spf_backoff_state2str(backoff->state)); - - backoff->last_event_time = now; - - switch (backoff->state) - { - case SPF_BACKOFF_QUIET: - backoff->state = SPF_BACKOFF_SHORT_WAIT; - thread_add_timer_msec(backoff->m, spf_backoff_timetolearn_elapsed, - backoff, backoff->timetolearn, - &backoff->t_timetolearn); - thread_add_timer_msec(backoff->m, spf_backoff_holddown_elapsed, backoff, - backoff->holddown, &backoff->t_holddown); - backoff->first_event_time = now; - rv = backoff->init_delay; - break; - case SPF_BACKOFF_SHORT_WAIT: - case SPF_BACKOFF_LONG_WAIT: - THREAD_TIMER_OFF(backoff->t_holddown); - thread_add_timer_msec(backoff->m, spf_backoff_holddown_elapsed, backoff, - backoff->holddown, &backoff->t_holddown); - if (backoff->state == SPF_BACKOFF_SHORT_WAIT) - rv = backoff->short_delay; - else - rv = backoff->long_delay; - break; - default: - zlog_warn("SPF Back-off(%s) in unknown state", backoff->name); - rv = backoff->init_delay; - } - - backoff_debug("SPF Back-off(%s) changed state to %s and returned %ld delay", - backoff->name, spf_backoff_state2str(backoff->state), rv); - return rv; + long rv; + struct timeval now; + + gettimeofday(&now, NULL); + + backoff_debug("SPF Back-off(%s) schedule called in state %s", + backoff->name, spf_backoff_state2str(backoff->state)); + + backoff->last_event_time = now; + + switch (backoff->state) { + case SPF_BACKOFF_QUIET: + backoff->state = SPF_BACKOFF_SHORT_WAIT; + thread_add_timer_msec( + backoff->m, spf_backoff_timetolearn_elapsed, backoff, + backoff->timetolearn, &backoff->t_timetolearn); + thread_add_timer_msec(backoff->m, spf_backoff_holddown_elapsed, + backoff, backoff->holddown, + &backoff->t_holddown); + backoff->first_event_time = now; + rv = backoff->init_delay; + break; + case SPF_BACKOFF_SHORT_WAIT: + case SPF_BACKOFF_LONG_WAIT: + THREAD_TIMER_OFF(backoff->t_holddown); + thread_add_timer_msec(backoff->m, spf_backoff_holddown_elapsed, + backoff, backoff->holddown, + &backoff->t_holddown); + if (backoff->state == SPF_BACKOFF_SHORT_WAIT) + rv = backoff->short_delay; + else + rv = backoff->long_delay; + break; + default: + zlog_warn("SPF Back-off(%s) in unknown state", backoff->name); + rv = backoff->init_delay; + } + + backoff_debug( + "SPF Back-off(%s) changed state to %s and returned %ld delay", + backoff->name, spf_backoff_state2str(backoff->state), rv); + return rv; } -static const char * -timeval_format(struct timeval *tv) +static const char *timeval_format(struct timeval *tv) { - struct tm tm_store; - struct tm *tm; - static char timebuf[256]; + struct tm tm_store; + struct tm *tm; + static char timebuf[256]; - if (!tv->tv_sec && !tv->tv_usec) - return "(never)"; + if (!tv->tv_sec && !tv->tv_usec) + return "(never)"; - tm = localtime_r(&tv->tv_sec, &tm_store); - if (!tm || strftime(timebuf, sizeof(timebuf), - "%Z %a %Y-%m-%d %H:%M:%S", tm) == 0) - { - return "???"; - } + tm = localtime_r(&tv->tv_sec, &tm_store); + if (!tm + || strftime(timebuf, sizeof(timebuf), "%Z %a %Y-%m-%d %H:%M:%S", tm) + == 0) { + return "???"; + } - size_t offset = strlen(timebuf); - snprintf(timebuf + offset, sizeof(timebuf) - offset, ".%ld", tv->tv_usec); + size_t offset = strlen(timebuf); + snprintf(timebuf + offset, sizeof(timebuf) - offset, ".%ld", + tv->tv_usec); - return timebuf; + return timebuf; } -void -spf_backoff_show(struct spf_backoff *backoff, struct vty *vty, - const char *prefix) +void spf_backoff_show(struct spf_backoff *backoff, struct vty *vty, + const char *prefix) { - vty_out (vty, "%sCurrent state: %s\n", prefix, - spf_backoff_state2str(backoff->state)); - vty_out (vty, "%sInit timer: %ld msec\n", prefix, - backoff->init_delay); - vty_out (vty, "%sShort timer: %ld msec\n", prefix, - backoff->short_delay); - vty_out (vty, "%sLong timer: %ld msec\n", prefix, - backoff->long_delay); - vty_out (vty, "%sHolddown timer: %ld msec\n", prefix, - backoff->holddown); - if (backoff->t_holddown) - { - struct timeval remain = thread_timer_remain(backoff->t_holddown); - vty_out (vty, "%s Still runs for %ld msec\n", - prefix, remain.tv_sec * 1000 + remain.tv_usec / 1000); - } - else - { - vty_out (vty, "%s Inactive\n", prefix); - } - - vty_out (vty, "%sTimeToLearn timer: %ld msec\n", prefix, - backoff->timetolearn); - if (backoff->t_timetolearn) - { - struct timeval remain = thread_timer_remain(backoff->t_timetolearn); - vty_out (vty, "%s Still runs for %ld msec\n", - prefix, remain.tv_sec * 1000 + remain.tv_usec / 1000); - } - else - { - vty_out (vty, "%s Inactive\n", prefix); - } - - vty_out (vty, "%sFirst event: %s\n", prefix, - timeval_format(&backoff->first_event_time)); - vty_out (vty, "%sLast event: %s\n", prefix, - timeval_format(&backoff->last_event_time)); + vty_out(vty, "%sCurrent state: %s\n", prefix, + spf_backoff_state2str(backoff->state)); + vty_out(vty, "%sInit timer: %ld msec\n", prefix, + backoff->init_delay); + vty_out(vty, "%sShort timer: %ld msec\n", prefix, + backoff->short_delay); + vty_out(vty, "%sLong timer: %ld msec\n", prefix, + backoff->long_delay); + vty_out(vty, "%sHolddown timer: %ld msec\n", prefix, + backoff->holddown); + if (backoff->t_holddown) { + struct timeval remain = + thread_timer_remain(backoff->t_holddown); + vty_out(vty, "%s Still runs for %ld msec\n", + prefix, remain.tv_sec * 1000 + remain.tv_usec / 1000); + } else { + vty_out(vty, "%s Inactive\n", prefix); + } + + vty_out(vty, "%sTimeToLearn timer: %ld msec\n", prefix, + backoff->timetolearn); + if (backoff->t_timetolearn) { + struct timeval remain = + thread_timer_remain(backoff->t_timetolearn); + vty_out(vty, "%s Still runs for %ld msec\n", + prefix, remain.tv_sec * 1000 + remain.tv_usec / 1000); + } else { + vty_out(vty, "%s Inactive\n", prefix); + } + + vty_out(vty, "%sFirst event: %s\n", prefix, + timeval_format(&backoff->first_event_time)); + vty_out(vty, "%sLast event: %s\n", prefix, + timeval_format(&backoff->last_event_time)); } DEFUN(spf_backoff_debug, @@ -269,8 +255,8 @@ DEFUN(spf_backoff_debug, DEBUG_STR "SPF Back-off Debugging\n") { - debug_spf_backoff = true; - return CMD_SUCCESS; + debug_spf_backoff = true; + return CMD_SUCCESS; } DEFUN(no_spf_backoff_debug, @@ -280,59 +266,51 @@ DEFUN(no_spf_backoff_debug, DEBUG_STR "SPF Back-off Debugging\n") { - debug_spf_backoff = false; - return CMD_SUCCESS; + debug_spf_backoff = false; + return CMD_SUCCESS; } -int -spf_backoff_write_config(struct vty *vty) +int spf_backoff_write_config(struct vty *vty) { - int written = 0; + int written = 0; - if (debug_spf_backoff) - { - vty_out (vty, "debug spf-delay-ietf\n"); - written++; - } + if (debug_spf_backoff) { + vty_out(vty, "debug spf-delay-ietf\n"); + written++; + } - return written; + return written; } -void -spf_backoff_cmd_init(void) +void spf_backoff_cmd_init(void) { - install_element(ENABLE_NODE, &spf_backoff_debug_cmd); - install_element(CONFIG_NODE, &spf_backoff_debug_cmd); - install_element(ENABLE_NODE, &no_spf_backoff_debug_cmd); - install_element(CONFIG_NODE, &no_spf_backoff_debug_cmd); + install_element(ENABLE_NODE, &spf_backoff_debug_cmd); + install_element(CONFIG_NODE, &spf_backoff_debug_cmd); + install_element(ENABLE_NODE, &no_spf_backoff_debug_cmd); + install_element(CONFIG_NODE, &no_spf_backoff_debug_cmd); } -long -spf_backoff_init_delay(struct spf_backoff *backoff) +long spf_backoff_init_delay(struct spf_backoff *backoff) { - return backoff->init_delay; + return backoff->init_delay; } -long -spf_backoff_short_delay(struct spf_backoff *backoff) +long spf_backoff_short_delay(struct spf_backoff *backoff) { - return backoff->short_delay; + return backoff->short_delay; } -long -spf_backoff_long_delay(struct spf_backoff *backoff) +long spf_backoff_long_delay(struct spf_backoff *backoff) { - return backoff->long_delay; + return backoff->long_delay; } -long -spf_backoff_holddown(struct spf_backoff *backoff) +long spf_backoff_holddown(struct spf_backoff *backoff) { - return backoff->holddown; + return backoff->holddown; } -long -spf_backoff_timetolearn(struct spf_backoff *backoff) +long spf_backoff_timetolearn(struct spf_backoff *backoff) { - return backoff->timetolearn; + return backoff->timetolearn; } diff --git a/lib/spf_backoff.h b/lib/spf_backoff.h index 92bd46506..6de5804ac 100644 --- a/lib/spf_backoff.h +++ b/lib/spf_backoff.h @@ -30,13 +30,10 @@ struct spf_backoff; struct thread_master; struct vty; -struct spf_backoff *spf_backoff_new(struct thread_master *m, - const char *name, - long init_delay, - long short_delay, - long long_delay, - long holddown, - long timetolearn); +struct spf_backoff *spf_backoff_new(struct thread_master *m, const char *name, + long init_delay, long short_delay, + long long_delay, long holddown, + long timetolearn); void spf_backoff_free(struct spf_backoff *backoff); @@ -45,9 +42,8 @@ void spf_backoff_free(struct spf_backoff *backoff); long spf_backoff_schedule(struct spf_backoff *backoff); /* Shows status of SPF backoff instance */ -void spf_backoff_show(struct spf_backoff *backoff, - struct vty *vty, - const char *prefix); +void spf_backoff_show(struct spf_backoff *backoff, struct vty *vty, + const char *prefix); /* Writes out global SPF backoff debug config */ int spf_backoff_write_config(struct vty *vty); diff --git a/lib/srcdest_table.c b/lib/srcdest_table.c index 383cf00d4..a70574cff 100644 --- a/lib/srcdest_table.c +++ b/lib/srcdest_table.c @@ -32,59 +32,54 @@ DEFINE_MTYPE_STATIC(LIB, ROUTE_SRC_NODE, "Route source node") /* ----- functions to manage rnodes _with_ srcdest table ----- */ -struct srcdest_rnode -{ - /* must be first in structure for casting to/from route_node */ - ROUTE_NODE_FIELDS; +struct srcdest_rnode { + /* must be first in structure for casting to/from route_node */ + ROUTE_NODE_FIELDS; - struct route_table *src_table; + struct route_table *src_table; }; -static struct srcdest_rnode * -srcdest_rnode_from_rnode (struct route_node *rn) +static struct srcdest_rnode *srcdest_rnode_from_rnode(struct route_node *rn) { - assert (rnode_is_dstnode (rn)); - return (struct srcdest_rnode *) rn; + assert(rnode_is_dstnode(rn)); + return (struct srcdest_rnode *)rn; } -static struct route_node * -srcdest_rnode_to_rnode (struct srcdest_rnode *srn) +static struct route_node *srcdest_rnode_to_rnode(struct srcdest_rnode *srn) { - return (struct route_node *) srn; + return (struct route_node *)srn; } -static struct route_node * -srcdest_rnode_create (route_table_delegate_t *delegate, - struct route_table *table) +static struct route_node *srcdest_rnode_create(route_table_delegate_t *delegate, + struct route_table *table) { - struct srcdest_rnode *srn; - srn = XCALLOC (MTYPE_ROUTE_NODE, sizeof (struct srcdest_rnode)); - return srcdest_rnode_to_rnode(srn); + struct srcdest_rnode *srn; + srn = XCALLOC(MTYPE_ROUTE_NODE, sizeof(struct srcdest_rnode)); + return srcdest_rnode_to_rnode(srn); } -static void -srcdest_rnode_destroy (route_table_delegate_t *delegate, - struct route_table *table, struct route_node *rn) +static void srcdest_rnode_destroy(route_table_delegate_t *delegate, + struct route_table *table, + struct route_node *rn) { - struct srcdest_rnode *srn = srcdest_rnode_from_rnode(rn); - struct route_table *src_table; - - /* Clear route node's src_table here already, otherwise the - * deletion of the last node in the src_table will trigger - * another call to route_table_finish for the src_table. - * - * (Compare with srcdest_srcnode_destroy) - */ - src_table = srn->src_table; - srn->src_table = NULL; - route_table_finish(src_table); - XFREE (MTYPE_ROUTE_NODE, rn); + struct srcdest_rnode *srn = srcdest_rnode_from_rnode(rn); + struct route_table *src_table; + + /* Clear route node's src_table here already, otherwise the + * deletion of the last node in the src_table will trigger + * another call to route_table_finish for the src_table. + * + * (Compare with srcdest_srcnode_destroy) + */ + src_table = srn->src_table; + srn->src_table = NULL; + route_table_finish(src_table); + XFREE(MTYPE_ROUTE_NODE, rn); } route_table_delegate_t _srcdest_dstnode_delegate = { - .create_node = srcdest_rnode_create, - .destroy_node = srcdest_rnode_destroy -}; + .create_node = srcdest_rnode_create, + .destroy_node = srcdest_rnode_destroy}; /* ----- functions to manage rnodes _in_ srcdest table ----- */ @@ -94,218 +89,209 @@ route_table_delegate_t _srcdest_dstnode_delegate = { * destination prefix's route_node) */ static struct route_node * -srcdest_srcnode_create (route_table_delegate_t *delegate, - struct route_table *table) +srcdest_srcnode_create(route_table_delegate_t *delegate, + struct route_table *table) { - return XCALLOC (MTYPE_ROUTE_SRC_NODE, sizeof (struct route_node)); + return XCALLOC(MTYPE_ROUTE_SRC_NODE, sizeof(struct route_node)); } -static void -srcdest_srcnode_destroy (route_table_delegate_t *delegate, - struct route_table *table, struct route_node *rn) +static void srcdest_srcnode_destroy(route_table_delegate_t *delegate, + struct route_table *table, + struct route_node *rn) { - struct srcdest_rnode *srn; - - XFREE (MTYPE_ROUTE_SRC_NODE, rn); - - srn = table->info; - if (srn->src_table && route_table_count (srn->src_table) == 0) - { - /* deleting the route_table from inside destroy_node is ONLY - * permitted IF table->count is 0! see lib/table.c route_node_delete() - * for details */ - route_table_finish (srn->src_table); - srn->src_table = NULL; - - /* drop the ref we're holding in srcdest_node_get(). there might be - * non-srcdest routes, so the route_node may still exist. hence, it's - * important to clear src_table above. */ - route_unlock_node (srcdest_rnode_to_rnode (srn)); - } + struct srcdest_rnode *srn; + + XFREE(MTYPE_ROUTE_SRC_NODE, rn); + + srn = table->info; + if (srn->src_table && route_table_count(srn->src_table) == 0) { + /* deleting the route_table from inside destroy_node is ONLY + * permitted IF table->count is 0! see lib/table.c + * route_node_delete() + * for details */ + route_table_finish(srn->src_table); + srn->src_table = NULL; + + /* drop the ref we're holding in srcdest_node_get(). there + * might be + * non-srcdest routes, so the route_node may still exist. + * hence, it's + * important to clear src_table above. */ + route_unlock_node(srcdest_rnode_to_rnode(srn)); + } } route_table_delegate_t _srcdest_srcnode_delegate = { - .create_node = srcdest_srcnode_create, - .destroy_node = srcdest_srcnode_destroy -}; + .create_node = srcdest_srcnode_create, + .destroy_node = srcdest_srcnode_destroy}; /* NB: read comments in code for refcounting before using! */ -static struct route_node * -srcdest_srcnode_get (struct route_node *rn, struct prefix_ipv6 *src_p) +static struct route_node *srcdest_srcnode_get(struct route_node *rn, + struct prefix_ipv6 *src_p) { - struct srcdest_rnode *srn; - - if (!src_p || src_p->prefixlen == 0) - return rn; - - srn = srcdest_rnode_from_rnode (rn); - if (!srn->src_table) - { - /* this won't use srcdest_rnode, we're already on the source here */ - srn->src_table = route_table_init_with_delegate (&_srcdest_srcnode_delegate); - srn->src_table->info = srn; - - /* there is no route_unlock_node on the original rn here. - * The reference is kept for the src_table. */ - } - else - { - /* only keep 1 reference for the src_table, makes the refcounting - * more similar to the non-srcdest case. Either way after return from - * function, the only reference held is the one on the return value. - * - * We can safely drop our reference here because src_table is holding - * another reference, so this won't free rn */ - route_unlock_node (rn); - } - - return route_node_get (srn->src_table, (struct prefix *)src_p); + struct srcdest_rnode *srn; + + if (!src_p || src_p->prefixlen == 0) + return rn; + + srn = srcdest_rnode_from_rnode(rn); + if (!srn->src_table) { + /* this won't use srcdest_rnode, we're already on the source + * here */ + srn->src_table = route_table_init_with_delegate( + &_srcdest_srcnode_delegate); + srn->src_table->info = srn; + + /* there is no route_unlock_node on the original rn here. + * The reference is kept for the src_table. */ + } else { + /* only keep 1 reference for the src_table, makes the + * refcounting + * more similar to the non-srcdest case. Either way after + * return from + * function, the only reference held is the one on the return + * value. + * + * We can safely drop our reference here because src_table is + * holding + * another reference, so this won't free rn */ + route_unlock_node(rn); + } + + return route_node_get(srn->src_table, (struct prefix *)src_p); } -static struct route_node * -srcdest_srcnode_lookup (struct route_node *rn, struct prefix_ipv6 *src_p) +static struct route_node *srcdest_srcnode_lookup(struct route_node *rn, + struct prefix_ipv6 *src_p) { - struct srcdest_rnode *srn; + struct srcdest_rnode *srn; - if (!rn || !src_p || src_p->prefixlen == 0) - return rn; + if (!rn || !src_p || src_p->prefixlen == 0) + return rn; - /* We got this rn from a lookup, so its refcnt was incremented. As we won't - * return return rn from any point beyond here, we should decrement its refcnt. - */ - route_unlock_node (rn); + /* We got this rn from a lookup, so its refcnt was incremented. As we + * won't + * return return rn from any point beyond here, we should decrement its + * refcnt. + */ + route_unlock_node(rn); - srn = srcdest_rnode_from_rnode (rn); - if (!srn->src_table) - return NULL; + srn = srcdest_rnode_from_rnode(rn); + if (!srn->src_table) + return NULL; - return route_node_lookup (srn->src_table, (struct prefix *)src_p); + return route_node_lookup(srn->src_table, (struct prefix *)src_p); } /* ----- exported functions ----- */ -struct route_table * -srcdest_table_init(void) +struct route_table *srcdest_table_init(void) { - return route_table_init_with_delegate(&_srcdest_dstnode_delegate); + return route_table_init_with_delegate(&_srcdest_dstnode_delegate); } -struct route_node * -srcdest_route_next(struct route_node *rn) +struct route_node *srcdest_route_next(struct route_node *rn) { - struct route_node *next, *parent; - - /* For a non src-dest node, just return route_next */ - if (!(rnode_is_dstnode(rn) || rnode_is_srcnode(rn))) - return route_next(rn); - - if (rnode_is_dstnode(rn)) - { - /* This means the route_node is part of the top hierarchy - * and refers to a destination prefix. */ - struct srcdest_rnode *srn = srcdest_rnode_from_rnode(rn); - - if (srn->src_table) - next = route_top(srn->src_table); - else - next = NULL; - - if (next) - { - /* There is a source prefix. Return the node for it */ - route_unlock_node(rn); - return next; - } - else - { - /* There is no source prefix, just continue as usual */ - return route_next(rn); - } - } - - /* This part handles the case of iterating source nodes. */ - parent = route_lock_node(rn->table->info); - next = route_next(rn); - - if (next) - { - /* There is another source node, continue in the source table */ - route_unlock_node(parent); - return next; - } - else - { - /* The source table is complete, continue in the parent table */ - return route_next(parent); - } + struct route_node *next, *parent; + + /* For a non src-dest node, just return route_next */ + if (!(rnode_is_dstnode(rn) || rnode_is_srcnode(rn))) + return route_next(rn); + + if (rnode_is_dstnode(rn)) { + /* This means the route_node is part of the top hierarchy + * and refers to a destination prefix. */ + struct srcdest_rnode *srn = srcdest_rnode_from_rnode(rn); + + if (srn->src_table) + next = route_top(srn->src_table); + else + next = NULL; + + if (next) { + /* There is a source prefix. Return the node for it */ + route_unlock_node(rn); + return next; + } else { + /* There is no source prefix, just continue as usual */ + return route_next(rn); + } + } + + /* This part handles the case of iterating source nodes. */ + parent = route_lock_node(rn->table->info); + next = route_next(rn); + + if (next) { + /* There is another source node, continue in the source table */ + route_unlock_node(parent); + return next; + } else { + /* The source table is complete, continue in the parent table */ + return route_next(parent); + } } -struct route_node * -srcdest_rnode_get (struct route_table *table, union prefixptr dst_pu, - struct prefix_ipv6 *src_p) +struct route_node *srcdest_rnode_get(struct route_table *table, + union prefixptr dst_pu, + struct prefix_ipv6 *src_p) { - struct prefix_ipv6 *dst_p = dst_pu.p6; - struct route_node *rn; + struct prefix_ipv6 *dst_p = dst_pu.p6; + struct route_node *rn; - rn = route_node_get (table, (struct prefix *) dst_p); - return srcdest_srcnode_get (rn, src_p); + rn = route_node_get(table, (struct prefix *)dst_p); + return srcdest_srcnode_get(rn, src_p); } -struct route_node * -srcdest_rnode_lookup (struct route_table *table, union prefixptr dst_pu, - struct prefix_ipv6 *src_p) +struct route_node *srcdest_rnode_lookup(struct route_table *table, + union prefixptr dst_pu, + struct prefix_ipv6 *src_p) { - struct prefix_ipv6 *dst_p = dst_pu.p6; - struct route_node *rn; - struct route_node *srn; - - rn = route_node_lookup_maynull (table, (struct prefix *) dst_p); - srn = srcdest_srcnode_lookup (rn, src_p); - - if (rn != NULL && rn == srn && !rn->info) - { - /* Match the behavior of route_node_lookup and don't return an - * empty route-node for a dest-route */ - route_unlock_node(rn); - return NULL; - } - return srn; + struct prefix_ipv6 *dst_p = dst_pu.p6; + struct route_node *rn; + struct route_node *srn; + + rn = route_node_lookup_maynull(table, (struct prefix *)dst_p); + srn = srcdest_srcnode_lookup(rn, src_p); + + if (rn != NULL && rn == srn && !rn->info) { + /* Match the behavior of route_node_lookup and don't return an + * empty route-node for a dest-route */ + route_unlock_node(rn); + return NULL; + } + return srn; } -void -srcdest_rnode_prefixes (struct route_node *rn, struct prefix **p, - struct prefix **src_p) +void srcdest_rnode_prefixes(struct route_node *rn, struct prefix **p, + struct prefix **src_p) { - if (rnode_is_srcnode (rn)) - { - struct route_node *dst_rn = rn->table->info; - if (p) - *p = &dst_rn->p; - if (src_p) - *src_p = &rn->p; - } - else - { - if (p) - *p = &rn->p; - if (src_p) - *src_p = NULL; - } + if (rnode_is_srcnode(rn)) { + struct route_node *dst_rn = rn->table->info; + if (p) + *p = &dst_rn->p; + if (src_p) + *src_p = &rn->p; + } else { + if (p) + *p = &rn->p; + if (src_p) + *src_p = NULL; + } } -const char * -srcdest_rnode2str (struct route_node *rn, char *str, int size) +const char *srcdest_rnode2str(struct route_node *rn, char *str, int size) { - struct prefix *dst_p, *src_p; - char dst_buf[PREFIX_STRLEN], src_buf[PREFIX_STRLEN]; - - srcdest_rnode_prefixes(rn, &dst_p, &src_p); - - snprintf(str, size, "%s%s%s", - prefix2str(dst_p, dst_buf, sizeof(dst_buf)), - (src_p && src_p->prefixlen) ? " from " : "", - (src_p && src_p->prefixlen) ? prefix2str(src_p, src_buf, - sizeof(src_buf)) - : ""); - return str; + struct prefix *dst_p, *src_p; + char dst_buf[PREFIX_STRLEN], src_buf[PREFIX_STRLEN]; + + srcdest_rnode_prefixes(rn, &dst_p, &src_p); + + snprintf(str, size, "%s%s%s", + prefix2str(dst_p, dst_buf, sizeof(dst_buf)), + (src_p && src_p->prefixlen) ? " from " : "", + (src_p && src_p->prefixlen) + ? prefix2str(src_p, src_buf, sizeof(src_buf)) + : ""); + return str; } diff --git a/lib/srcdest_table.h b/lib/srcdest_table.h index 0d858d11a..669068a79 100644 --- a/lib/srcdest_table.h +++ b/lib/srcdest_table.h @@ -56,45 +56,39 @@ extern route_table_delegate_t _srcdest_srcnode_delegate; extern struct route_table *srcdest_table_init(void); extern struct route_node *srcdest_rnode_get(struct route_table *table, - union prefixptr dst_pu, - struct prefix_ipv6 *src_p); + union prefixptr dst_pu, + struct prefix_ipv6 *src_p); extern struct route_node *srcdest_rnode_lookup(struct route_table *table, - union prefixptr dst_pu, - struct prefix_ipv6 *src_p); -extern void srcdest_rnode_prefixes (struct route_node *rn, struct prefix **p, - struct prefix **src_p); -extern const char *srcdest_rnode2str(struct route_node *rn, char *str, int size); + union prefixptr dst_pu, + struct prefix_ipv6 *src_p); +extern void srcdest_rnode_prefixes(struct route_node *rn, struct prefix **p, + struct prefix **src_p); +extern const char *srcdest_rnode2str(struct route_node *rn, char *str, + int size); extern struct route_node *srcdest_route_next(struct route_node *rn); -static inline int -rnode_is_dstnode (struct route_node *rn) +static inline int rnode_is_dstnode(struct route_node *rn) { - return rn->table->delegate == &_srcdest_dstnode_delegate; + return rn->table->delegate == &_srcdest_dstnode_delegate; } -static inline int -rnode_is_srcnode (struct route_node *rn) +static inline int rnode_is_srcnode(struct route_node *rn) { - return rn->table->delegate == &_srcdest_srcnode_delegate; + return rn->table->delegate == &_srcdest_srcnode_delegate; } -static inline struct route_table * -srcdest_rnode_table (struct route_node *rn) +static inline struct route_table *srcdest_rnode_table(struct route_node *rn) { - if (rnode_is_srcnode (rn)) - { - struct route_node *dst_rn = rn->table->info; - return dst_rn->table; - } - else - { - return rn->table; - } + if (rnode_is_srcnode(rn)) { + struct route_node *dst_rn = rn->table->info; + return dst_rn->table; + } else { + return rn->table; + } } -static inline void * -srcdest_rnode_table_info (struct route_node *rn) +static inline void *srcdest_rnode_table_info(struct route_node *rn) { - return srcdest_rnode_table(rn)->info; + return srcdest_rnode_table(rn)->info; } #endif /* _ZEBRA_SRC_DEST_TABLE_H */ diff --git a/lib/stream.c b/lib/stream.c index 6163a5b3e..577fa257d 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -28,16 +28,14 @@ #include "prefix.h" #include "log.h" -DEFINE_MTYPE_STATIC(LIB, STREAM, "Stream") +DEFINE_MTYPE_STATIC(LIB, STREAM, "Stream") DEFINE_MTYPE_STATIC(LIB, STREAM_DATA, "Stream data") DEFINE_MTYPE_STATIC(LIB, STREAM_FIFO, "Stream FIFO") -/* Tests whether a position is valid */ -#define GETP_VALID(S,G) \ - ((G) <= (S)->endp) +/* Tests whether a position is valid */ +#define GETP_VALID(S, G) ((G) <= (S)->endp) #define PUT_AT_VALID(S,G) GETP_VALID(S,G) -#define ENDP_VALID(S,E) \ - ((E) <= (S)->size) +#define ENDP_VALID(S, E) ((E) <= (S)->size) /* asserting sanity checks. Following must be true before * stream functions are called: @@ -54,518 +52,471 @@ DEFINE_MTYPE_STATIC(LIB, STREAM_FIFO, "Stream FIFO") * It is valid to put to anywhere within the size of the stream, but only * using stream_put..._at() functions. */ -#define STREAM_WARN_OFFSETS(S) \ - zlog_warn ("&(struct stream): %p, size: %lu, getp: %lu, endp: %lu\n", \ - (void *)(S), \ - (unsigned long) (S)->size, \ - (unsigned long) (S)->getp, \ - (unsigned long) (S)->endp)\ - -#define STREAM_VERIFY_SANE(S) \ - do { \ - if ( !(GETP_VALID(S, (S)->getp) && ENDP_VALID(S, (S)->endp)) ) \ - STREAM_WARN_OFFSETS(S); \ - assert ( GETP_VALID(S, (S)->getp) ); \ - assert ( ENDP_VALID(S, (S)->endp) ); \ - } while (0) - -#define STREAM_BOUND_WARN(S, WHAT) \ - do { \ - zlog_warn ("%s: Attempt to %s out of bounds", __func__, (WHAT)); \ - STREAM_WARN_OFFSETS(S); \ - assert (0); \ - } while (0) +#define STREAM_WARN_OFFSETS(S) \ + zlog_warn("&(struct stream): %p, size: %lu, getp: %lu, endp: %lu\n", \ + (void *)(S), (unsigned long)(S)->size, \ + (unsigned long)(S)->getp, (unsigned long)(S)->endp) + +#define STREAM_VERIFY_SANE(S) \ + do { \ + if (!(GETP_VALID(S, (S)->getp) && ENDP_VALID(S, (S)->endp))) \ + STREAM_WARN_OFFSETS(S); \ + assert(GETP_VALID(S, (S)->getp)); \ + assert(ENDP_VALID(S, (S)->endp)); \ + } while (0) + +#define STREAM_BOUND_WARN(S, WHAT) \ + do { \ + zlog_warn("%s: Attempt to %s out of bounds", __func__, \ + (WHAT)); \ + STREAM_WARN_OFFSETS(S); \ + assert(0); \ + } while (0) /* XXX: Deprecated macro: do not use */ -#define CHECK_SIZE(S, Z) \ - do { \ - if (((S)->endp + (Z)) > (S)->size) \ - { \ - zlog_warn ("CHECK_SIZE: truncating requested size %lu\n", \ - (unsigned long) (Z)); \ - STREAM_WARN_OFFSETS(S); \ - (Z) = (S)->size - (S)->endp; \ - } \ - } while (0); +#define CHECK_SIZE(S, Z) \ + do { \ + if (((S)->endp + (Z)) > (S)->size) { \ + zlog_warn( \ + "CHECK_SIZE: truncating requested size %lu\n", \ + (unsigned long)(Z)); \ + STREAM_WARN_OFFSETS(S); \ + (Z) = (S)->size - (S)->endp; \ + } \ + } while (0); /* Make stream buffer. */ -struct stream * -stream_new (size_t size) +struct stream *stream_new(size_t size) { - struct stream *s; - - assert (size > 0); - - s = XCALLOC (MTYPE_STREAM, sizeof (struct stream)); - - if (s == NULL) - return s; - - if ( (s->data = XMALLOC (MTYPE_STREAM_DATA, size)) == NULL) - { - XFREE (MTYPE_STREAM, s); - return NULL; - } - - s->size = size; - return s; + struct stream *s; + + assert(size > 0); + + s = XCALLOC(MTYPE_STREAM, sizeof(struct stream)); + + if (s == NULL) + return s; + + if ((s->data = XMALLOC(MTYPE_STREAM_DATA, size)) == NULL) { + XFREE(MTYPE_STREAM, s); + return NULL; + } + + s->size = size; + return s; } /* Free it now. */ -void -stream_free (struct stream *s) +void stream_free(struct stream *s) { - if (!s) - return; - - XFREE (MTYPE_STREAM_DATA, s->data); - XFREE (MTYPE_STREAM, s); + if (!s) + return; + + XFREE(MTYPE_STREAM_DATA, s->data); + XFREE(MTYPE_STREAM, s); } -struct stream * -stream_copy (struct stream *new, struct stream *src) +struct stream *stream_copy(struct stream *new, struct stream *src) { - STREAM_VERIFY_SANE (src); - - assert (new != NULL); - assert (STREAM_SIZE(new) >= src->endp); - - new->endp = src->endp; - new->getp = src->getp; - - memcpy (new->data, src->data, src->endp); - - return new; + STREAM_VERIFY_SANE(src); + + assert(new != NULL); + assert(STREAM_SIZE(new) >= src->endp); + + new->endp = src->endp; + new->getp = src->getp; + + memcpy(new->data, src->data, src->endp); + + return new; } -struct stream * -stream_dup (struct stream *s) +struct stream *stream_dup(struct stream *s) { - struct stream *new; + struct stream *new; - STREAM_VERIFY_SANE (s); + STREAM_VERIFY_SANE(s); - if ( (new = stream_new (s->endp)) == NULL) - return NULL; + if ((new = stream_new(s->endp)) == NULL) + return NULL; - return (stream_copy (new, s)); + return (stream_copy(new, s)); } -struct stream * -stream_dupcat (struct stream *s1, struct stream *s2, size_t offset) +struct stream *stream_dupcat(struct stream *s1, struct stream *s2, + size_t offset) { - struct stream *new; + struct stream *new; - STREAM_VERIFY_SANE (s1); - STREAM_VERIFY_SANE (s2); + STREAM_VERIFY_SANE(s1); + STREAM_VERIFY_SANE(s2); - if ( (new = stream_new (s1->endp + s2->endp)) == NULL) - return NULL; + if ((new = stream_new(s1->endp + s2->endp)) == NULL) + return NULL; - memcpy (new->data, s1->data, offset); - memcpy (new->data + offset, s2->data, s2->endp); - memcpy (new->data + offset + s2->endp, s1->data + offset, - (s1->endp - offset)); - new->endp = s1->endp + s2->endp; - return new; + memcpy(new->data, s1->data, offset); + memcpy(new->data + offset, s2->data, s2->endp); + memcpy(new->data + offset + s2->endp, s1->data + offset, + (s1->endp - offset)); + new->endp = s1->endp + s2->endp; + return new; } -size_t -stream_resize (struct stream *s, size_t newsize) +size_t stream_resize(struct stream *s, size_t newsize) { - u_char *newdata; - STREAM_VERIFY_SANE (s); - - newdata = XREALLOC (MTYPE_STREAM_DATA, s->data, newsize); - - if (newdata == NULL) - return s->size; - - s->data = newdata; - s->size = newsize; - - if (s->endp > s->size) - s->endp = s->size; - if (s->getp > s->endp) - s->getp = s->endp; - - STREAM_VERIFY_SANE (s); - - return s->size; + u_char *newdata; + STREAM_VERIFY_SANE(s); + + newdata = XREALLOC(MTYPE_STREAM_DATA, s->data, newsize); + + if (newdata == NULL) + return s->size; + + s->data = newdata; + s->size = newsize; + + if (s->endp > s->size) + s->endp = s->size; + if (s->getp > s->endp) + s->getp = s->endp; + + STREAM_VERIFY_SANE(s); + + return s->size; } -size_t -stream_get_getp (struct stream *s) +size_t stream_get_getp(struct stream *s) { - STREAM_VERIFY_SANE(s); - return s->getp; + STREAM_VERIFY_SANE(s); + return s->getp; } -size_t -stream_get_endp (struct stream *s) +size_t stream_get_endp(struct stream *s) { - STREAM_VERIFY_SANE(s); - return s->endp; + STREAM_VERIFY_SANE(s); + return s->endp; } -size_t -stream_get_size (struct stream *s) +size_t stream_get_size(struct stream *s) { - STREAM_VERIFY_SANE(s); - return s->size; + STREAM_VERIFY_SANE(s); + return s->size; } /* Stream structre' stream pointer related functions. */ -void -stream_set_getp (struct stream *s, size_t pos) +void stream_set_getp(struct stream *s, size_t pos) { - STREAM_VERIFY_SANE(s); - - if (!GETP_VALID (s, pos)) - { - STREAM_BOUND_WARN (s, "set getp"); - pos = s->endp; - } - - s->getp = pos; + STREAM_VERIFY_SANE(s); + + if (!GETP_VALID(s, pos)) { + STREAM_BOUND_WARN(s, "set getp"); + pos = s->endp; + } + + s->getp = pos; } -void -stream_set_endp (struct stream *s, size_t pos) +void stream_set_endp(struct stream *s, size_t pos) { - STREAM_VERIFY_SANE(s); - - if (!ENDP_VALID(s, pos)) - { - STREAM_BOUND_WARN (s, "set endp"); - return; - } - - /* - * Make sure the current read pointer is not beyond the new endp. - */ - if (s->getp > pos) - { - STREAM_BOUND_WARN(s, "set endp"); - return; - } - - s->endp = pos; - STREAM_VERIFY_SANE(s); + STREAM_VERIFY_SANE(s); + + if (!ENDP_VALID(s, pos)) { + STREAM_BOUND_WARN(s, "set endp"); + return; + } + + /* + * Make sure the current read pointer is not beyond the new endp. + */ + if (s->getp > pos) { + STREAM_BOUND_WARN(s, "set endp"); + return; + } + + s->endp = pos; + STREAM_VERIFY_SANE(s); } /* Forward pointer. */ -void -stream_forward_getp (struct stream *s, size_t size) +void stream_forward_getp(struct stream *s, size_t size) { - STREAM_VERIFY_SANE(s); - - if (!GETP_VALID (s, s->getp + size)) - { - STREAM_BOUND_WARN (s, "seek getp"); - return; - } - - s->getp += size; + STREAM_VERIFY_SANE(s); + + if (!GETP_VALID(s, s->getp + size)) { + STREAM_BOUND_WARN(s, "seek getp"); + return; + } + + s->getp += size; } -void -stream_forward_endp (struct stream *s, size_t size) +void stream_forward_endp(struct stream *s, size_t size) { - STREAM_VERIFY_SANE(s); - - if (!ENDP_VALID (s, s->endp + size)) - { - STREAM_BOUND_WARN (s, "seek endp"); - return; - } - - s->endp += size; + STREAM_VERIFY_SANE(s); + + if (!ENDP_VALID(s, s->endp + size)) { + STREAM_BOUND_WARN(s, "seek endp"); + return; + } + + s->endp += size; } /* Copy from stream to destination. */ -void -stream_get (void *dst, struct stream *s, size_t size) +void stream_get(void *dst, struct stream *s, size_t size) { - STREAM_VERIFY_SANE(s); - - if (STREAM_READABLE(s) < size) - { - STREAM_BOUND_WARN (s, "get"); - return; - } - - memcpy (dst, s->data + s->getp, size); - s->getp += size; + STREAM_VERIFY_SANE(s); + + if (STREAM_READABLE(s) < size) { + STREAM_BOUND_WARN(s, "get"); + return; + } + + memcpy(dst, s->data + s->getp, size); + s->getp += size; } /* Get next character from the stream. */ -u_char -stream_getc (struct stream *s) +u_char stream_getc(struct stream *s) { - u_char c; - - STREAM_VERIFY_SANE (s); - - if (STREAM_READABLE(s) < sizeof (u_char)) - { - STREAM_BOUND_WARN (s, "get char"); - return 0; - } - c = s->data[s->getp++]; - - return c; + u_char c; + + STREAM_VERIFY_SANE(s); + + if (STREAM_READABLE(s) < sizeof(u_char)) { + STREAM_BOUND_WARN(s, "get char"); + return 0; + } + c = s->data[s->getp++]; + + return c; } /* Get next character from the stream. */ -u_char -stream_getc_from (struct stream *s, size_t from) +u_char stream_getc_from(struct stream *s, size_t from) { - u_char c; - - STREAM_VERIFY_SANE(s); - - if (!GETP_VALID (s, from + sizeof (u_char))) - { - STREAM_BOUND_WARN (s, "get char"); - return 0; - } - - c = s->data[from]; - - return c; + u_char c; + + STREAM_VERIFY_SANE(s); + + if (!GETP_VALID(s, from + sizeof(u_char))) { + STREAM_BOUND_WARN(s, "get char"); + return 0; + } + + c = s->data[from]; + + return c; } /* Get next word from the stream. */ -u_int16_t -stream_getw (struct stream *s) +u_int16_t stream_getw(struct stream *s) { - u_int16_t w; - - STREAM_VERIFY_SANE (s); - - if (STREAM_READABLE (s) < sizeof (u_int16_t)) - { - STREAM_BOUND_WARN (s, "get "); - return 0; - } - - w = s->data[s->getp++] << 8; - w |= s->data[s->getp++]; - - return w; + u_int16_t w; + + STREAM_VERIFY_SANE(s); + + if (STREAM_READABLE(s) < sizeof(u_int16_t)) { + STREAM_BOUND_WARN(s, "get "); + return 0; + } + + w = s->data[s->getp++] << 8; + w |= s->data[s->getp++]; + + return w; } /* Get next word from the stream. */ -u_int16_t -stream_getw_from (struct stream *s, size_t from) +u_int16_t stream_getw_from(struct stream *s, size_t from) { - u_int16_t w; - - STREAM_VERIFY_SANE(s); - - if (!GETP_VALID (s, from + sizeof (u_int16_t))) - { - STREAM_BOUND_WARN (s, "get "); - return 0; - } - - w = s->data[from++] << 8; - w |= s->data[from]; - - return w; + u_int16_t w; + + STREAM_VERIFY_SANE(s); + + if (!GETP_VALID(s, from + sizeof(u_int16_t))) { + STREAM_BOUND_WARN(s, "get "); + return 0; + } + + w = s->data[from++] << 8; + w |= s->data[from]; + + return w; } /* Get next 3-byte from the stream. */ -u_int32_t -stream_get3_from (struct stream *s, size_t from) +u_int32_t stream_get3_from(struct stream *s, size_t from) { - u_int32_t l; - - STREAM_VERIFY_SANE(s); - - if (!GETP_VALID (s, from + 3)) - { - STREAM_BOUND_WARN (s, "get 3byte"); - return 0; - } - - l = s->data[from++] << 16; - l |= s->data[from++] << 8; - l |= s->data[from]; - - return l; + u_int32_t l; + + STREAM_VERIFY_SANE(s); + + if (!GETP_VALID(s, from + 3)) { + STREAM_BOUND_WARN(s, "get 3byte"); + return 0; + } + + l = s->data[from++] << 16; + l |= s->data[from++] << 8; + l |= s->data[from]; + + return l; } -u_int32_t -stream_get3 (struct stream *s) +u_int32_t stream_get3(struct stream *s) { - u_int32_t l; - - STREAM_VERIFY_SANE(s); - - if (STREAM_READABLE (s) < 3) - { - STREAM_BOUND_WARN (s, "get 3byte"); - return 0; - } - - l = s->data[s->getp++] << 16; - l |= s->data[s->getp++] << 8; - l |= s->data[s->getp++]; - - return l; + u_int32_t l; + + STREAM_VERIFY_SANE(s); + + if (STREAM_READABLE(s) < 3) { + STREAM_BOUND_WARN(s, "get 3byte"); + return 0; + } + + l = s->data[s->getp++] << 16; + l |= s->data[s->getp++] << 8; + l |= s->data[s->getp++]; + + return l; } /* Get next long word from the stream. */ -u_int32_t -stream_getl_from (struct stream *s, size_t from) +u_int32_t stream_getl_from(struct stream *s, size_t from) { - u_int32_t l; - - STREAM_VERIFY_SANE(s); - - if (!GETP_VALID (s, from + sizeof (u_int32_t))) - { - STREAM_BOUND_WARN (s, "get long"); - return 0; - } - - l = s->data[from++] << 24; - l |= s->data[from++] << 16; - l |= s->data[from++] << 8; - l |= s->data[from]; - - return l; + u_int32_t l; + + STREAM_VERIFY_SANE(s); + + if (!GETP_VALID(s, from + sizeof(u_int32_t))) { + STREAM_BOUND_WARN(s, "get long"); + return 0; + } + + l = s->data[from++] << 24; + l |= s->data[from++] << 16; + l |= s->data[from++] << 8; + l |= s->data[from]; + + return l; } /* Copy from stream at specific location to destination. */ -void -stream_get_from (void *dst, struct stream *s, size_t from, size_t size) +void stream_get_from(void *dst, struct stream *s, size_t from, size_t size) { - STREAM_VERIFY_SANE(s); + STREAM_VERIFY_SANE(s); - if (!GETP_VALID (s, from + size)) - { - STREAM_BOUND_WARN (s, "get from"); - return; - } + if (!GETP_VALID(s, from + size)) { + STREAM_BOUND_WARN(s, "get from"); + return; + } - memcpy (dst, s->data + from, size); + memcpy(dst, s->data + from, size); } -u_int32_t -stream_getl (struct stream *s) +u_int32_t stream_getl(struct stream *s) { - u_int32_t l; - - STREAM_VERIFY_SANE(s); - - if (STREAM_READABLE (s) < sizeof (u_int32_t)) - { - STREAM_BOUND_WARN (s, "get long"); - return 0; - } - - l = s->data[s->getp++] << 24; - l |= s->data[s->getp++] << 16; - l |= s->data[s->getp++] << 8; - l |= s->data[s->getp++]; - - return l; + u_int32_t l; + + STREAM_VERIFY_SANE(s); + + if (STREAM_READABLE(s) < sizeof(u_int32_t)) { + STREAM_BOUND_WARN(s, "get long"); + return 0; + } + + l = s->data[s->getp++] << 24; + l |= s->data[s->getp++] << 16; + l |= s->data[s->getp++] << 8; + l |= s->data[s->getp++]; + + return l; } /* Get next quad word from the stream. */ -uint64_t -stream_getq_from (struct stream *s, size_t from) +uint64_t stream_getq_from(struct stream *s, size_t from) { - uint64_t q; - - STREAM_VERIFY_SANE(s); - - if (!GETP_VALID (s, from + sizeof (uint64_t))) - { - STREAM_BOUND_WARN (s, "get quad"); - return 0; - } - - q = ((uint64_t) s->data[from++]) << 56; - q |= ((uint64_t) s->data[from++]) << 48; - q |= ((uint64_t) s->data[from++]) << 40; - q |= ((uint64_t) s->data[from++]) << 32; - q |= ((uint64_t) s->data[from++]) << 24; - q |= ((uint64_t) s->data[from++]) << 16; - q |= ((uint64_t) s->data[from++]) << 8; - q |= ((uint64_t) s->data[from++]); - - return q; + uint64_t q; + + STREAM_VERIFY_SANE(s); + + if (!GETP_VALID(s, from + sizeof(uint64_t))) { + STREAM_BOUND_WARN(s, "get quad"); + return 0; + } + + q = ((uint64_t)s->data[from++]) << 56; + q |= ((uint64_t)s->data[from++]) << 48; + q |= ((uint64_t)s->data[from++]) << 40; + q |= ((uint64_t)s->data[from++]) << 32; + q |= ((uint64_t)s->data[from++]) << 24; + q |= ((uint64_t)s->data[from++]) << 16; + q |= ((uint64_t)s->data[from++]) << 8; + q |= ((uint64_t)s->data[from++]); + + return q; } -uint64_t -stream_getq (struct stream *s) +uint64_t stream_getq(struct stream *s) { - uint64_t q; - - STREAM_VERIFY_SANE(s); - - if (STREAM_READABLE (s) < sizeof (uint64_t)) - { - STREAM_BOUND_WARN (s, "get quad"); - return 0; - } - - q = ((uint64_t) s->data[s->getp++]) << 56; - q |= ((uint64_t) s->data[s->getp++]) << 48; - q |= ((uint64_t) s->data[s->getp++]) << 40; - q |= ((uint64_t) s->data[s->getp++]) << 32; - q |= ((uint64_t) s->data[s->getp++]) << 24; - q |= ((uint64_t) s->data[s->getp++]) << 16; - q |= ((uint64_t) s->data[s->getp++]) << 8; - q |= ((uint64_t) s->data[s->getp++]); - - return q; + uint64_t q; + + STREAM_VERIFY_SANE(s); + + if (STREAM_READABLE(s) < sizeof(uint64_t)) { + STREAM_BOUND_WARN(s, "get quad"); + return 0; + } + + q = ((uint64_t)s->data[s->getp++]) << 56; + q |= ((uint64_t)s->data[s->getp++]) << 48; + q |= ((uint64_t)s->data[s->getp++]) << 40; + q |= ((uint64_t)s->data[s->getp++]) << 32; + q |= ((uint64_t)s->data[s->getp++]) << 24; + q |= ((uint64_t)s->data[s->getp++]) << 16; + q |= ((uint64_t)s->data[s->getp++]) << 8; + q |= ((uint64_t)s->data[s->getp++]); + + return q; } /* Get next long word from the stream. */ -u_int32_t -stream_get_ipv4 (struct stream *s) +u_int32_t stream_get_ipv4(struct stream *s) { - u_int32_t l; - - STREAM_VERIFY_SANE(s); - - if (STREAM_READABLE (s) < sizeof(u_int32_t)) - { - STREAM_BOUND_WARN (s, "get ipv4"); - return 0; - } - - memcpy (&l, s->data + s->getp, sizeof(u_int32_t)); - s->getp += sizeof(u_int32_t); - - return l; + u_int32_t l; + + STREAM_VERIFY_SANE(s); + + if (STREAM_READABLE(s) < sizeof(u_int32_t)) { + STREAM_BOUND_WARN(s, "get ipv4"); + return 0; + } + + memcpy(&l, s->data + s->getp, sizeof(u_int32_t)); + s->getp += sizeof(u_int32_t); + + return l; } -float -stream_getf (struct stream *s) +float stream_getf(struct stream *s) { - union { - float r; - uint32_t d; - } u; - u.d = stream_getl (s); - return u.r; + union { + float r; + uint32_t d; + } u; + u.d = stream_getl(s); + return u.r; } -double -stream_getd (struct stream *s) +double stream_getd(struct stream *s) { - union { - double r; - uint64_t d; - } u; - u.d = stream_getq (s); - return u.r; + union { + double r; + uint64_t d; + } u; + u.d = stream_getq(s); + return u.r; } /* Copy to source to stream. @@ -575,455 +526,413 @@ stream_getd (struct stream *s) * * stream_write() is saner */ -void -stream_put (struct stream *s, const void *src, size_t size) +void stream_put(struct stream *s, const void *src, size_t size) { - /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */ - CHECK_SIZE(s, size); - - STREAM_VERIFY_SANE(s); - - if (STREAM_WRITEABLE (s) < size) - { - STREAM_BOUND_WARN (s, "put"); - return; - } - - if (src) - memcpy (s->data + s->endp, src, size); - else - memset (s->data + s->endp, 0, size); - - s->endp += size; + /* XXX: CHECK_SIZE has strange semantics. It should be deprecated */ + CHECK_SIZE(s, size); + + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE(s) < size) { + STREAM_BOUND_WARN(s, "put"); + return; + } + + if (src) + memcpy(s->data + s->endp, src, size); + else + memset(s->data + s->endp, 0, size); + + s->endp += size; } /* Put character to the stream. */ -int -stream_putc (struct stream *s, u_char c) +int stream_putc(struct stream *s, u_char c) { - STREAM_VERIFY_SANE(s); - - if (STREAM_WRITEABLE (s) < sizeof(u_char)) - { - STREAM_BOUND_WARN (s, "put"); - return 0; - } - - s->data[s->endp++] = c; - return sizeof (u_char); + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE(s) < sizeof(u_char)) { + STREAM_BOUND_WARN(s, "put"); + return 0; + } + + s->data[s->endp++] = c; + return sizeof(u_char); } /* Put word to the stream. */ -int -stream_putw (struct stream *s, u_int16_t w) +int stream_putw(struct stream *s, u_int16_t w) { - STREAM_VERIFY_SANE (s); - - if (STREAM_WRITEABLE (s) < sizeof (u_int16_t)) - { - STREAM_BOUND_WARN (s, "put"); - return 0; - } - - s->data[s->endp++] = (u_char)(w >> 8); - s->data[s->endp++] = (u_char) w; - - return 2; + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE(s) < sizeof(u_int16_t)) { + STREAM_BOUND_WARN(s, "put"); + return 0; + } + + s->data[s->endp++] = (u_char)(w >> 8); + s->data[s->endp++] = (u_char)w; + + return 2; } /* Put long word to the stream. */ -int -stream_put3 (struct stream *s, u_int32_t l) +int stream_put3(struct stream *s, u_int32_t l) { - STREAM_VERIFY_SANE (s); - - if (STREAM_WRITEABLE (s) < 3) - { - STREAM_BOUND_WARN (s, "put"); - return 0; - } - - s->data[s->endp++] = (u_char)(l >> 16); - s->data[s->endp++] = (u_char)(l >> 8); - s->data[s->endp++] = (u_char)l; - - return 3; + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE(s) < 3) { + STREAM_BOUND_WARN(s, "put"); + return 0; + } + + s->data[s->endp++] = (u_char)(l >> 16); + s->data[s->endp++] = (u_char)(l >> 8); + s->data[s->endp++] = (u_char)l; + + return 3; } /* Put long word to the stream. */ -int -stream_putl (struct stream *s, u_int32_t l) +int stream_putl(struct stream *s, u_int32_t l) { - STREAM_VERIFY_SANE (s); - - if (STREAM_WRITEABLE (s) < sizeof (u_int32_t)) - { - STREAM_BOUND_WARN (s, "put"); - return 0; - } - - s->data[s->endp++] = (u_char)(l >> 24); - s->data[s->endp++] = (u_char)(l >> 16); - s->data[s->endp++] = (u_char)(l >> 8); - s->data[s->endp++] = (u_char)l; - - return 4; + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE(s) < sizeof(u_int32_t)) { + STREAM_BOUND_WARN(s, "put"); + return 0; + } + + s->data[s->endp++] = (u_char)(l >> 24); + s->data[s->endp++] = (u_char)(l >> 16); + s->data[s->endp++] = (u_char)(l >> 8); + s->data[s->endp++] = (u_char)l; + + return 4; } /* Put quad word to the stream. */ -int -stream_putq (struct stream *s, uint64_t q) +int stream_putq(struct stream *s, uint64_t q) { - STREAM_VERIFY_SANE (s); - - if (STREAM_WRITEABLE (s) < sizeof (uint64_t)) - { - STREAM_BOUND_WARN (s, "put quad"); - return 0; - } - - s->data[s->endp++] = (u_char)(q >> 56); - s->data[s->endp++] = (u_char)(q >> 48); - s->data[s->endp++] = (u_char)(q >> 40); - s->data[s->endp++] = (u_char)(q >> 32); - s->data[s->endp++] = (u_char)(q >> 24); - s->data[s->endp++] = (u_char)(q >> 16); - s->data[s->endp++] = (u_char)(q >> 8); - s->data[s->endp++] = (u_char)q; - - return 8; + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE(s) < sizeof(uint64_t)) { + STREAM_BOUND_WARN(s, "put quad"); + return 0; + } + + s->data[s->endp++] = (u_char)(q >> 56); + s->data[s->endp++] = (u_char)(q >> 48); + s->data[s->endp++] = (u_char)(q >> 40); + s->data[s->endp++] = (u_char)(q >> 32); + s->data[s->endp++] = (u_char)(q >> 24); + s->data[s->endp++] = (u_char)(q >> 16); + s->data[s->endp++] = (u_char)(q >> 8); + s->data[s->endp++] = (u_char)q; + + return 8; } -int -stream_putf (struct stream *s, float f) +int stream_putf(struct stream *s, float f) { - union { - float i; - uint32_t o; - } u; - u.i = f; - return stream_putl (s, u.o); + union { + float i; + uint32_t o; + } u; + u.i = f; + return stream_putl(s, u.o); } -int -stream_putd (struct stream *s, double d) +int stream_putd(struct stream *s, double d) { - union { - double i; - uint64_t o; - } u; - u.i = d; - return stream_putq (s, u.o); + union { + double i; + uint64_t o; + } u; + u.i = d; + return stream_putq(s, u.o); } -int -stream_putc_at (struct stream *s, size_t putp, u_char c) +int stream_putc_at(struct stream *s, size_t putp, u_char c) { - STREAM_VERIFY_SANE(s); - - if (!PUT_AT_VALID (s, putp + sizeof (u_char))) - { - STREAM_BOUND_WARN (s, "put"); - return 0; - } - - s->data[putp] = c; - - return 1; + STREAM_VERIFY_SANE(s); + + if (!PUT_AT_VALID(s, putp + sizeof(u_char))) { + STREAM_BOUND_WARN(s, "put"); + return 0; + } + + s->data[putp] = c; + + return 1; } -int -stream_putw_at (struct stream *s, size_t putp, u_int16_t w) +int stream_putw_at(struct stream *s, size_t putp, u_int16_t w) { - STREAM_VERIFY_SANE(s); - - if (!PUT_AT_VALID (s, putp + sizeof (u_int16_t))) - { - STREAM_BOUND_WARN (s, "put"); - return 0; - } - - s->data[putp] = (u_char)(w >> 8); - s->data[putp + 1] = (u_char) w; - - return 2; + STREAM_VERIFY_SANE(s); + + if (!PUT_AT_VALID(s, putp + sizeof(u_int16_t))) { + STREAM_BOUND_WARN(s, "put"); + return 0; + } + + s->data[putp] = (u_char)(w >> 8); + s->data[putp + 1] = (u_char)w; + + return 2; } -int -stream_put3_at (struct stream *s, size_t putp, u_int32_t l) +int stream_put3_at(struct stream *s, size_t putp, u_int32_t l) { - STREAM_VERIFY_SANE(s); - - if (!PUT_AT_VALID (s, putp + 3)) - { - STREAM_BOUND_WARN (s, "put"); - return 0; - } - s->data[putp] = (u_char)(l >> 16); - s->data[putp + 1] = (u_char)(l >> 8); - s->data[putp + 2] = (u_char)l; - - return 3; + STREAM_VERIFY_SANE(s); + + if (!PUT_AT_VALID(s, putp + 3)) { + STREAM_BOUND_WARN(s, "put"); + return 0; + } + s->data[putp] = (u_char)(l >> 16); + s->data[putp + 1] = (u_char)(l >> 8); + s->data[putp + 2] = (u_char)l; + + return 3; } -int -stream_putl_at (struct stream *s, size_t putp, u_int32_t l) +int stream_putl_at(struct stream *s, size_t putp, u_int32_t l) { - STREAM_VERIFY_SANE(s); - - if (!PUT_AT_VALID (s, putp + sizeof (u_int32_t))) - { - STREAM_BOUND_WARN (s, "put"); - return 0; - } - s->data[putp] = (u_char)(l >> 24); - s->data[putp + 1] = (u_char)(l >> 16); - s->data[putp + 2] = (u_char)(l >> 8); - s->data[putp + 3] = (u_char)l; - - return 4; + STREAM_VERIFY_SANE(s); + + if (!PUT_AT_VALID(s, putp + sizeof(u_int32_t))) { + STREAM_BOUND_WARN(s, "put"); + return 0; + } + s->data[putp] = (u_char)(l >> 24); + s->data[putp + 1] = (u_char)(l >> 16); + s->data[putp + 2] = (u_char)(l >> 8); + s->data[putp + 3] = (u_char)l; + + return 4; } -int -stream_putq_at (struct stream *s, size_t putp, uint64_t q) +int stream_putq_at(struct stream *s, size_t putp, uint64_t q) { - STREAM_VERIFY_SANE(s); - - if (!PUT_AT_VALID (s, putp + sizeof (uint64_t))) - { - STREAM_BOUND_WARN (s, "put"); - return 0; - } - s->data[putp] = (u_char)(q >> 56); - s->data[putp + 1] = (u_char)(q >> 48); - s->data[putp + 2] = (u_char)(q >> 40); - s->data[putp + 3] = (u_char)(q >> 32); - s->data[putp + 4] = (u_char)(q >> 24); - s->data[putp + 5] = (u_char)(q >> 16); - s->data[putp + 6] = (u_char)(q >> 8); - s->data[putp + 7] = (u_char)q; - - return 8; + STREAM_VERIFY_SANE(s); + + if (!PUT_AT_VALID(s, putp + sizeof(uint64_t))) { + STREAM_BOUND_WARN(s, "put"); + return 0; + } + s->data[putp] = (u_char)(q >> 56); + s->data[putp + 1] = (u_char)(q >> 48); + s->data[putp + 2] = (u_char)(q >> 40); + s->data[putp + 3] = (u_char)(q >> 32); + s->data[putp + 4] = (u_char)(q >> 24); + s->data[putp + 5] = (u_char)(q >> 16); + s->data[putp + 6] = (u_char)(q >> 8); + s->data[putp + 7] = (u_char)q; + + return 8; } /* Put long word to the stream. */ -int -stream_put_ipv4 (struct stream *s, u_int32_t l) +int stream_put_ipv4(struct stream *s, u_int32_t l) { - STREAM_VERIFY_SANE(s); - - if (STREAM_WRITEABLE (s) < sizeof (u_int32_t)) - { - STREAM_BOUND_WARN (s, "put"); - return 0; - } - memcpy (s->data + s->endp, &l, sizeof (u_int32_t)); - s->endp += sizeof (u_int32_t); - - return sizeof (u_int32_t); + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE(s) < sizeof(u_int32_t)) { + STREAM_BOUND_WARN(s, "put"); + return 0; + } + memcpy(s->data + s->endp, &l, sizeof(u_int32_t)); + s->endp += sizeof(u_int32_t); + + return sizeof(u_int32_t); } /* Put long word to the stream. */ -int -stream_put_in_addr (struct stream *s, struct in_addr *addr) +int stream_put_in_addr(struct stream *s, struct in_addr *addr) { - STREAM_VERIFY_SANE(s); - - if (STREAM_WRITEABLE (s) < sizeof (u_int32_t)) - { - STREAM_BOUND_WARN (s, "put"); - return 0; - } - - memcpy (s->data + s->endp, addr, sizeof (u_int32_t)); - s->endp += sizeof (u_int32_t); - - return sizeof (u_int32_t); + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE(s) < sizeof(u_int32_t)) { + STREAM_BOUND_WARN(s, "put"); + return 0; + } + + memcpy(s->data + s->endp, addr, sizeof(u_int32_t)); + s->endp += sizeof(u_int32_t); + + return sizeof(u_int32_t); } /* Put in_addr at location in the stream. */ -int -stream_put_in_addr_at (struct stream *s, size_t putp, struct in_addr *addr) +int stream_put_in_addr_at(struct stream *s, size_t putp, struct in_addr *addr) { - STREAM_VERIFY_SANE(s); + STREAM_VERIFY_SANE(s); - if (!PUT_AT_VALID (s, putp + 4)) - { - STREAM_BOUND_WARN (s, "put"); - return 0; - } + if (!PUT_AT_VALID(s, putp + 4)) { + STREAM_BOUND_WARN(s, "put"); + return 0; + } - memcpy (&s->data[putp], addr, 4); - return 4; + memcpy(&s->data[putp], addr, 4); + return 4; } /* Put in6_addr at location in the stream. */ -int -stream_put_in6_addr_at (struct stream *s, size_t putp, struct in6_addr *addr) +int stream_put_in6_addr_at(struct stream *s, size_t putp, struct in6_addr *addr) { - STREAM_VERIFY_SANE(s); + STREAM_VERIFY_SANE(s); - if (!PUT_AT_VALID (s, putp + 16)) - { - STREAM_BOUND_WARN (s, "put"); - return 0; - } + if (!PUT_AT_VALID(s, putp + 16)) { + STREAM_BOUND_WARN(s, "put"); + return 0; + } - memcpy (&s->data[putp], addr, 16); - return 16; + memcpy(&s->data[putp], addr, 16); + return 16; } /* Put prefix by nlri type format. */ -int -stream_put_prefix_addpath (struct stream *s, struct prefix *p, - int addpath_encode, u_int32_t addpath_tx_id) +int stream_put_prefix_addpath(struct stream *s, struct prefix *p, + int addpath_encode, u_int32_t addpath_tx_id) { - size_t psize; - size_t psize_with_addpath; - - STREAM_VERIFY_SANE(s); - - psize = PSIZE (p->prefixlen); - - if (addpath_encode) - psize_with_addpath = psize + 4; - else - psize_with_addpath = psize; - - if (STREAM_WRITEABLE (s) < (psize_with_addpath + sizeof (u_char))) - { - STREAM_BOUND_WARN (s, "put"); - return 0; - } - - if (addpath_encode) - { - s->data[s->endp++] = (u_char)(addpath_tx_id >> 24); - s->data[s->endp++] = (u_char)(addpath_tx_id >> 16); - s->data[s->endp++] = (u_char)(addpath_tx_id >> 8); - s->data[s->endp++] = (u_char)addpath_tx_id; - } - - s->data[s->endp++] = p->prefixlen; - memcpy (s->data + s->endp, &p->u.prefix, psize); - s->endp += psize; - - return psize; + size_t psize; + size_t psize_with_addpath; + + STREAM_VERIFY_SANE(s); + + psize = PSIZE(p->prefixlen); + + if (addpath_encode) + psize_with_addpath = psize + 4; + else + psize_with_addpath = psize; + + if (STREAM_WRITEABLE(s) < (psize_with_addpath + sizeof(u_char))) { + STREAM_BOUND_WARN(s, "put"); + return 0; + } + + if (addpath_encode) { + s->data[s->endp++] = (u_char)(addpath_tx_id >> 24); + s->data[s->endp++] = (u_char)(addpath_tx_id >> 16); + s->data[s->endp++] = (u_char)(addpath_tx_id >> 8); + s->data[s->endp++] = (u_char)addpath_tx_id; + } + + s->data[s->endp++] = p->prefixlen; + memcpy(s->data + s->endp, &p->u.prefix, psize); + s->endp += psize; + + return psize; } -int -stream_put_prefix (struct stream *s, struct prefix *p) +int stream_put_prefix(struct stream *s, struct prefix *p) { - return stream_put_prefix_addpath (s, p, 0, 0); + return stream_put_prefix_addpath(s, p, 0, 0); } /* Put NLRI with label */ -int -stream_put_labeled_prefix (struct stream *s, struct prefix *p, mpls_label_t *label) +int stream_put_labeled_prefix(struct stream *s, struct prefix *p, + mpls_label_t *label) { - size_t psize; - u_char *label_pnt = (u_char *) label; + size_t psize; + u_char *label_pnt = (u_char *)label; - STREAM_VERIFY_SANE(s); + STREAM_VERIFY_SANE(s); - psize = PSIZE (p->prefixlen); + psize = PSIZE(p->prefixlen); - if (STREAM_WRITEABLE (s) < (psize + 3)) - { - STREAM_BOUND_WARN (s, "put"); - return 0; - } + if (STREAM_WRITEABLE(s) < (psize + 3)) { + STREAM_BOUND_WARN(s, "put"); + return 0; + } - stream_putc (s, (p->prefixlen + 24)); - stream_putc(s, label_pnt[0]); - stream_putc(s, label_pnt[1]); - stream_putc(s, label_pnt[2]); - memcpy (s->data + s->endp, &p->u.prefix, psize); - s->endp += psize; + stream_putc(s, (p->prefixlen + 24)); + stream_putc(s, label_pnt[0]); + stream_putc(s, label_pnt[1]); + stream_putc(s, label_pnt[2]); + memcpy(s->data + s->endp, &p->u.prefix, psize); + s->endp += psize; - return (psize + 3); + return (psize + 3); } /* Read size from fd. */ -int -stream_read (struct stream *s, int fd, size_t size) +int stream_read(struct stream *s, int fd, size_t size) { - int nbytes; - - STREAM_VERIFY_SANE(s); - - if (STREAM_WRITEABLE (s) < size) - { - STREAM_BOUND_WARN (s, "put"); - return 0; - } - - nbytes = readn (fd, s->data + s->endp, size); - - if (nbytes > 0) - s->endp += nbytes; - - return nbytes; + int nbytes; + + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE(s) < size) { + STREAM_BOUND_WARN(s, "put"); + return 0; + } + + nbytes = readn(fd, s->data + s->endp, size); + + if (nbytes > 0) + s->endp += nbytes; + + return nbytes; } -ssize_t -stream_read_try(struct stream *s, int fd, size_t size) +ssize_t stream_read_try(struct stream *s, int fd, size_t size) { - ssize_t nbytes; - - STREAM_VERIFY_SANE(s); - - if (STREAM_WRITEABLE(s) < size) - { - STREAM_BOUND_WARN (s, "put"); - /* Fatal (not transient) error, since retrying will not help - (stream is too small to contain the desired data). */ - return -1; - } - - if ((nbytes = read(fd, s->data + s->endp, size)) >= 0) - { - s->endp += nbytes; - return nbytes; - } - /* Error: was it transient (return -2) or fatal (return -1)? */ - if (ERRNO_IO_RETRY(errno)) - return -2; - zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno)); - return -1; + ssize_t nbytes; + + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE(s) < size) { + STREAM_BOUND_WARN(s, "put"); + /* Fatal (not transient) error, since retrying will not help + (stream is too small to contain the desired data). */ + return -1; + } + + if ((nbytes = read(fd, s->data + s->endp, size)) >= 0) { + s->endp += nbytes; + return nbytes; + } + /* Error: was it transient (return -2) or fatal (return -1)? */ + if (ERRNO_IO_RETRY(errno)) + return -2; + zlog_warn("%s: read failed on fd %d: %s", __func__, fd, + safe_strerror(errno)); + return -1; } /* Read up to size bytes into the stream from the fd, using recvmsgfrom * whose arguments match the remaining arguments to this function */ -ssize_t -stream_recvfrom (struct stream *s, int fd, size_t size, int flags, - struct sockaddr *from, socklen_t *fromlen) +ssize_t stream_recvfrom(struct stream *s, int fd, size_t size, int flags, + struct sockaddr *from, socklen_t *fromlen) { - ssize_t nbytes; - - STREAM_VERIFY_SANE(s); - - if (STREAM_WRITEABLE(s) < size) - { - STREAM_BOUND_WARN (s, "put"); - /* Fatal (not transient) error, since retrying will not help - (stream is too small to contain the desired data). */ - return -1; - } - - if ((nbytes = recvfrom (fd, s->data + s->endp, size, - flags, from, fromlen)) >= 0) - { - s->endp += nbytes; - return nbytes; - } - /* Error: was it transient (return -2) or fatal (return -1)? */ - if (ERRNO_IO_RETRY(errno)) - return -2; - zlog_warn("%s: read failed on fd %d: %s", __func__, fd, safe_strerror(errno)); - return -1; + ssize_t nbytes; + + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE(s) < size) { + STREAM_BOUND_WARN(s, "put"); + /* Fatal (not transient) error, since retrying will not help + (stream is too small to contain the desired data). */ + return -1; + } + + if ((nbytes = recvfrom(fd, s->data + s->endp, size, flags, from, + fromlen)) + >= 0) { + s->endp += nbytes; + return nbytes; + } + /* Error: was it transient (return -2) or fatal (return -1)? */ + if (ERRNO_IO_RETRY(errno)) + return -2; + zlog_warn("%s: read failed on fd %d: %s", __func__, fd, + safe_strerror(errno)); + return -1; } /* Read up to smaller of size or SIZE_REMAIN() bytes to the stream, starting @@ -1031,171 +940,156 @@ stream_recvfrom (struct stream *s, int fd, size_t size, int flags, * First iovec will be used to receive the data. * Stream need not be empty. */ -ssize_t -stream_recvmsg (struct stream *s, int fd, struct msghdr *msgh, int flags, - size_t size) +ssize_t stream_recvmsg(struct stream *s, int fd, struct msghdr *msgh, int flags, + size_t size) { - int nbytes; - struct iovec *iov; - - STREAM_VERIFY_SANE(s); - assert (msgh->msg_iovlen > 0); - - if (STREAM_WRITEABLE (s) < size) - { - STREAM_BOUND_WARN (s, "put"); - /* This is a logic error in the calling code: the stream is too small - to hold the desired data! */ - return -1; - } - - iov = &(msgh->msg_iov[0]); - iov->iov_base = (s->data + s->endp); - iov->iov_len = size; - - nbytes = recvmsg (fd, msgh, flags); - - if (nbytes > 0) - s->endp += nbytes; - - return nbytes; + int nbytes; + struct iovec *iov; + + STREAM_VERIFY_SANE(s); + assert(msgh->msg_iovlen > 0); + + if (STREAM_WRITEABLE(s) < size) { + STREAM_BOUND_WARN(s, "put"); + /* This is a logic error in the calling code: the stream is too + small + to hold the desired data! */ + return -1; + } + + iov = &(msgh->msg_iov[0]); + iov->iov_base = (s->data + s->endp); + iov->iov_len = size; + + nbytes = recvmsg(fd, msgh, flags); + + if (nbytes > 0) + s->endp += nbytes; + + return nbytes; } - + /* Write data to buffer. */ -size_t -stream_write (struct stream *s, const void *ptr, size_t size) +size_t stream_write(struct stream *s, const void *ptr, size_t size) { - CHECK_SIZE(s, size); + CHECK_SIZE(s, size); + + STREAM_VERIFY_SANE(s); + + if (STREAM_WRITEABLE(s) < size) { + STREAM_BOUND_WARN(s, "put"); + return 0; + } - STREAM_VERIFY_SANE(s); - - if (STREAM_WRITEABLE (s) < size) - { - STREAM_BOUND_WARN (s, "put"); - return 0; - } - - memcpy (s->data + s->endp, ptr, size); - s->endp += size; + memcpy(s->data + s->endp, ptr, size); + s->endp += size; - return size; + return size; } -/* Return current read pointer. +/* Return current read pointer. * DEPRECATED! * Use stream_get_pnt_to if you must, but decoding streams properly * is preferred */ -u_char * -stream_pnt (struct stream *s) +u_char *stream_pnt(struct stream *s) { - STREAM_VERIFY_SANE(s); - return s->data + s->getp; + STREAM_VERIFY_SANE(s); + return s->data + s->getp; } /* Check does this stream empty? */ -int -stream_empty (struct stream *s) +int stream_empty(struct stream *s) { - STREAM_VERIFY_SANE(s); + STREAM_VERIFY_SANE(s); - return (s->endp == 0); + return (s->endp == 0); } /* Reset stream. */ -void -stream_reset (struct stream *s) +void stream_reset(struct stream *s) { - STREAM_VERIFY_SANE (s); + STREAM_VERIFY_SANE(s); - s->getp = s->endp = 0; + s->getp = s->endp = 0; } /* Write stream contens to the file discriptor. */ -int -stream_flush (struct stream *s, int fd) +int stream_flush(struct stream *s, int fd) { - int nbytes; - - STREAM_VERIFY_SANE(s); - - nbytes = write (fd, s->data + s->getp, s->endp - s->getp); - - return nbytes; + int nbytes; + + STREAM_VERIFY_SANE(s); + + nbytes = write(fd, s->data + s->getp, s->endp - s->getp); + + return nbytes; } /* Stream first in first out queue. */ -struct stream_fifo * -stream_fifo_new (void) +struct stream_fifo *stream_fifo_new(void) { - struct stream_fifo *new; - - new = XCALLOC (MTYPE_STREAM_FIFO, sizeof (struct stream_fifo)); - return new; + struct stream_fifo *new; + + new = XCALLOC(MTYPE_STREAM_FIFO, sizeof(struct stream_fifo)); + return new; } /* Add new stream to fifo. */ -void -stream_fifo_push (struct stream_fifo *fifo, struct stream *s) +void stream_fifo_push(struct stream_fifo *fifo, struct stream *s) { - if (fifo->tail) - fifo->tail->next = s; - else - fifo->head = s; - - fifo->tail = s; - - fifo->count++; + if (fifo->tail) + fifo->tail->next = s; + else + fifo->head = s; + + fifo->tail = s; + + fifo->count++; } /* Delete first stream from fifo. */ -struct stream * -stream_fifo_pop (struct stream_fifo *fifo) +struct stream *stream_fifo_pop(struct stream_fifo *fifo) { - struct stream *s; - - s = fifo->head; + struct stream *s; + + s = fifo->head; - if (s) - { - fifo->head = s->next; + if (s) { + fifo->head = s->next; - if (fifo->head == NULL) - fifo->tail = NULL; + if (fifo->head == NULL) + fifo->tail = NULL; - fifo->count--; - } + fifo->count--; + } - return s; + return s; } /* Return first fifo entry. */ -struct stream * -stream_fifo_head (struct stream_fifo *fifo) +struct stream *stream_fifo_head(struct stream_fifo *fifo) { - return fifo->head; + return fifo->head; } -void -stream_fifo_clean (struct stream_fifo *fifo) +void stream_fifo_clean(struct stream_fifo *fifo) { - struct stream *s; - struct stream *next; - - for (s = fifo->head; s; s = next) - { - next = s->next; - stream_free (s); - } - fifo->head = fifo->tail = NULL; - fifo->count = 0; + struct stream *s; + struct stream *next; + + for (s = fifo->head; s; s = next) { + next = s->next; + stream_free(s); + } + fifo->head = fifo->tail = NULL; + fifo->count = 0; } -void -stream_fifo_free (struct stream_fifo *fifo) +void stream_fifo_free(struct stream_fifo *fifo) { - stream_fifo_clean (fifo); - XFREE (MTYPE_STREAM_FIFO, fifo); + stream_fifo_clean(fifo); + XFREE(MTYPE_STREAM_FIFO, fifo); } diff --git a/lib/stream.h b/lib/stream.h index c012cc459..33dd64c4a 100644 --- a/lib/stream.h +++ b/lib/stream.h @@ -78,7 +78,7 @@ * The stream is empty from endp to size. Without adjusting getp, there are * still endp-getp bytes of valid data to be read from the stream. * - * Methods are provided to get and put to/from the stream, as well as + * Methods are provided to get and put to/from the stream, as well as * retrieve the values of the 3 markers and manipulate the getp marker. * * Note: @@ -92,45 +92,42 @@ */ /* Stream buffer. */ -struct stream -{ - struct stream *next; - - /* Remainder is ***private*** to stream - * direct access is frowned upon! - * Use the appropriate functions/macros - */ - size_t getp; /* next get position */ - size_t endp; /* last valid data position */ - size_t size; /* size of data segment */ - unsigned char *data; /* data pointer */ +struct stream { + struct stream *next; + + /* Remainder is ***private*** to stream + * direct access is frowned upon! + * Use the appropriate functions/macros + */ + size_t getp; /* next get position */ + size_t endp; /* last valid data position */ + size_t size; /* size of data segment */ + unsigned char *data; /* data pointer */ }; /* First in first out queue structure. */ -struct stream_fifo -{ - size_t count; +struct stream_fifo { + size_t count; - struct stream *head; - struct stream *tail; + struct stream *head; + struct stream *tail; }; /* Utility macros. */ #define STREAM_SIZE(S) ((S)->size) - /* number of bytes which can still be written */ +/* number of bytes which can still be written */ #define STREAM_WRITEABLE(S) ((S)->size - (S)->endp) - /* number of bytes still to be read */ +/* number of bytes still to be read */ #define STREAM_READABLE(S) ((S)->endp - (S)->getp) -#define STREAM_CONCAT_REMAIN(S1, S2, size) \ - ((size) - (S1)->endp - (S2)->endp) +#define STREAM_CONCAT_REMAIN(S1, S2, size) ((size) - (S1)->endp - (S2)->endp) /* deprecated macros - do not use in new code */ #define STREAM_PNT(S) stream_pnt((S)) #define STREAM_DATA(S) ((S)->data) #define STREAM_REMAIN(S) STREAM_WRITEABLE((S)) -/* Stream prototypes. +/* Stream prototypes. * For stream_{put,get}S, the S suffix mean: * * c: character (unsigned byte) @@ -138,15 +135,15 @@ struct stream_fifo * l: long (two words) * q: quad (four words) */ -extern struct stream *stream_new (size_t); -extern void stream_free (struct stream *); -extern struct stream * stream_copy (struct stream *, struct stream *src); -extern struct stream *stream_dup (struct stream *); -extern size_t stream_resize (struct stream *, size_t); -extern size_t stream_get_getp (struct stream *); -extern size_t stream_get_endp (struct stream *); -extern size_t stream_get_size (struct stream *); -extern u_char *stream_get_data (struct stream *); +extern struct stream *stream_new(size_t); +extern void stream_free(struct stream *); +extern struct stream *stream_copy(struct stream *, struct stream *src); +extern struct stream *stream_dup(struct stream *); +extern size_t stream_resize(struct stream *, size_t); +extern size_t stream_get_getp(struct stream *); +extern size_t stream_get_endp(struct stream *); +extern size_t stream_get_size(struct stream *); +extern u_char *stream_get_data(struct stream *); /** * Create a new stream structure; copy offset bytes from s1 to the new @@ -156,59 +153,59 @@ extern u_char *stream_get_data (struct stream *); extern struct stream *stream_dupcat(struct stream *s1, struct stream *s2, size_t offset); -extern void stream_set_getp (struct stream *, size_t); -extern void stream_set_endp (struct stream *, size_t); -extern void stream_forward_getp (struct stream *, size_t); -extern void stream_forward_endp (struct stream *, size_t); +extern void stream_set_getp(struct stream *, size_t); +extern void stream_set_endp(struct stream *, size_t); +extern void stream_forward_getp(struct stream *, size_t); +extern void stream_forward_endp(struct stream *, size_t); /* steam_put: NULL source zeroes out size_t bytes of stream */ -extern void stream_put (struct stream *, const void *, size_t); -extern int stream_putc (struct stream *, u_char); -extern int stream_putc_at (struct stream *, size_t, u_char); -extern int stream_putw (struct stream *, u_int16_t); -extern int stream_putw_at (struct stream *, size_t, u_int16_t); -extern int stream_put3 (struct stream *, u_int32_t); -extern int stream_put3_at (struct stream *, size_t, u_int32_t); -extern int stream_putl (struct stream *, u_int32_t); -extern int stream_putl_at (struct stream *, size_t, u_int32_t); -extern int stream_putq (struct stream *, uint64_t); -extern int stream_putq_at (struct stream *, size_t, uint64_t); -extern int stream_put_ipv4 (struct stream *, u_int32_t); -extern int stream_put_in_addr (struct stream *, struct in_addr *); -extern int stream_put_in_addr_at (struct stream *, size_t, struct in_addr *); -extern int stream_put_in6_addr_at (struct stream *, size_t, struct in6_addr *); -extern int stream_put_prefix_addpath (struct stream *, struct prefix *, - int addpath_encode, - u_int32_t addpath_tx_id); -extern int stream_put_prefix (struct stream *, struct prefix *); -extern int stream_put_labeled_prefix (struct stream *, struct prefix *, - mpls_label_t *); -extern void stream_get (void *, struct stream *, size_t); -extern void stream_get_from (void *, struct stream *, size_t, size_t); -extern u_char stream_getc (struct stream *); -extern u_char stream_getc_from (struct stream *, size_t); -extern u_int16_t stream_getw (struct stream *); -extern u_int16_t stream_getw_from (struct stream *, size_t); -extern u_int32_t stream_get3 (struct stream *); -extern u_int32_t stream_get3_from (struct stream *, size_t); -extern u_int32_t stream_getl (struct stream *); -extern u_int32_t stream_getl_from (struct stream *, size_t); -extern uint64_t stream_getq (struct stream *); -extern uint64_t stream_getq_from (struct stream *, size_t); -extern u_int32_t stream_get_ipv4 (struct stream *); +extern void stream_put(struct stream *, const void *, size_t); +extern int stream_putc(struct stream *, u_char); +extern int stream_putc_at(struct stream *, size_t, u_char); +extern int stream_putw(struct stream *, u_int16_t); +extern int stream_putw_at(struct stream *, size_t, u_int16_t); +extern int stream_put3(struct stream *, u_int32_t); +extern int stream_put3_at(struct stream *, size_t, u_int32_t); +extern int stream_putl(struct stream *, u_int32_t); +extern int stream_putl_at(struct stream *, size_t, u_int32_t); +extern int stream_putq(struct stream *, uint64_t); +extern int stream_putq_at(struct stream *, size_t, uint64_t); +extern int stream_put_ipv4(struct stream *, u_int32_t); +extern int stream_put_in_addr(struct stream *, struct in_addr *); +extern int stream_put_in_addr_at(struct stream *, size_t, struct in_addr *); +extern int stream_put_in6_addr_at(struct stream *, size_t, struct in6_addr *); +extern int stream_put_prefix_addpath(struct stream *, struct prefix *, + int addpath_encode, + u_int32_t addpath_tx_id); +extern int stream_put_prefix(struct stream *, struct prefix *); +extern int stream_put_labeled_prefix(struct stream *, struct prefix *, + mpls_label_t *); +extern void stream_get(void *, struct stream *, size_t); +extern void stream_get_from(void *, struct stream *, size_t, size_t); +extern u_char stream_getc(struct stream *); +extern u_char stream_getc_from(struct stream *, size_t); +extern u_int16_t stream_getw(struct stream *); +extern u_int16_t stream_getw_from(struct stream *, size_t); +extern u_int32_t stream_get3(struct stream *); +extern u_int32_t stream_get3_from(struct stream *, size_t); +extern u_int32_t stream_getl(struct stream *); +extern u_int32_t stream_getl_from(struct stream *, size_t); +extern uint64_t stream_getq(struct stream *); +extern uint64_t stream_getq_from(struct stream *, size_t); +extern u_int32_t stream_get_ipv4(struct stream *); /* IEEE-754 floats */ -extern float stream_getf (struct stream *); -extern double stream_getd (struct stream *); -extern int stream_putf (struct stream *, float); -extern int stream_putd (struct stream *, double); +extern float stream_getf(struct stream *); +extern double stream_getd(struct stream *); +extern int stream_putf(struct stream *, float); +extern int stream_putd(struct stream *, double); #undef stream_read #undef stream_write -/* Deprecated: assumes blocking I/O. Will be removed. +/* Deprecated: assumes blocking I/O. Will be removed. Use stream_read_try instead. */ -extern int stream_read (struct stream *, int, size_t); +extern int stream_read(struct stream *, int, size_t); /* Read up to size bytes into the stream. Return code: @@ -220,27 +217,26 @@ extern int stream_read (struct stream *, int, size_t); */ extern ssize_t stream_read_try(struct stream *s, int fd, size_t size); -extern ssize_t stream_recvmsg (struct stream *s, int fd, struct msghdr *, - int flags, size_t size); -extern ssize_t stream_recvfrom (struct stream *s, int fd, size_t len, - int flags, struct sockaddr *from, - socklen_t *fromlen); -extern size_t stream_write (struct stream *, const void *, size_t); +extern ssize_t stream_recvmsg(struct stream *s, int fd, struct msghdr *, + int flags, size_t size); +extern ssize_t stream_recvfrom(struct stream *s, int fd, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen); +extern size_t stream_write(struct stream *, const void *, size_t); /* reset the stream. See Note above */ -extern void stream_reset (struct stream *); -extern int stream_flush (struct stream *, int); -extern int stream_empty (struct stream *); /* is the stream empty? */ +extern void stream_reset(struct stream *); +extern int stream_flush(struct stream *, int); +extern int stream_empty(struct stream *); /* is the stream empty? */ /* deprecated */ -extern u_char *stream_pnt (struct stream *); +extern u_char *stream_pnt(struct stream *); /* Stream fifo. */ -extern struct stream_fifo *stream_fifo_new (void); -extern void stream_fifo_push (struct stream_fifo *fifo, struct stream *s); -extern struct stream *stream_fifo_pop (struct stream_fifo *fifo); -extern struct stream *stream_fifo_head (struct stream_fifo *fifo); -extern void stream_fifo_clean (struct stream_fifo *fifo); -extern void stream_fifo_free (struct stream_fifo *fifo); +extern struct stream_fifo *stream_fifo_new(void); +extern void stream_fifo_push(struct stream_fifo *fifo, struct stream *s); +extern struct stream *stream_fifo_pop(struct stream_fifo *fifo); +extern struct stream *stream_fifo_head(struct stream_fifo *fifo); +extern void stream_fifo_clean(struct stream_fifo *fifo); +extern void stream_fifo_free(struct stream_fifo *fifo); #endif /* _ZEBRA_STREAM_H */ diff --git a/lib/strlcat.c b/lib/strlcat.c index 6fdb2a4a3..818630443 100644 --- a/lib/strlcat.c +++ b/lib/strlcat.c @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with the GNU C Library; if not, see - * . + * . */ /* adapted for Quagga from glibc patch submission originally from @@ -28,45 +28,42 @@ #ifndef HAVE_STRLCAT #undef strlcat -size_t -strlcat (char *__restrict dest, const char *__restrict src, size_t size); +size_t strlcat(char *__restrict dest, const char *__restrict src, size_t size); -size_t -strlcat (char *__restrict dest, const char *__restrict src, size_t size) +size_t strlcat(char *__restrict dest, const char *__restrict src, size_t size) { - size_t src_length = strlen (src); + size_t src_length = strlen(src); - /* Our implementation strlcat supports dest == NULL if size == 0 - (for consistency with snprintf and strlcpy), but strnlen does - not, so we have to cover this case explicitly. */ - if (size == 0) - return src_length; + /* Our implementation strlcat supports dest == NULL if size == 0 + (for consistency with snprintf and strlcpy), but strnlen does + not, so we have to cover this case explicitly. */ + if (size == 0) + return src_length; - size_t dest_length = strnlen (dest, size); - if (dest_length != size) - { - /* Copy at most the remaining number of characters in the - destination buffer. Leave for the NUL terminator. */ - size_t to_copy = size - dest_length - 1; - /* But not more than what is available in the source string. */ - if (to_copy > src_length) - to_copy = src_length; + size_t dest_length = strnlen(dest, size); + if (dest_length != size) { + /* Copy at most the remaining number of characters in the + destination buffer. Leave for the NUL terminator. */ + size_t to_copy = size - dest_length - 1; + /* But not more than what is available in the source string. */ + if (to_copy > src_length) + to_copy = src_length; - char *target = dest + dest_length; - memcpy (target, src, to_copy); - target[to_copy] = '\0'; - } + char *target = dest + dest_length; + memcpy(target, src, to_copy); + target[to_copy] = '\0'; + } - /* If the sum wraps around, we have more than SIZE_MAX + 2 bytes in - the two input strings (including both null terminators). If each - byte in the address space can be assigned a unique size_t value - (which the static_assert checks), then by the pigeonhole - principle, the two input strings must overlap, which is - undefined. */ +/* If the sum wraps around, we have more than SIZE_MAX + 2 bytes in + the two input strings (including both null terminators). If each + byte in the address space can be assigned a unique size_t value + (which the static_assert checks), then by the pigeonhole + principle, the two input strings must overlap, which is + undefined. */ #if __STDC_VERSION__ >= 201112L - _Static_assert (sizeof (uintptr_t) == sizeof (size_t), - "theoretical maximum object size covers address space"); + _Static_assert(sizeof(uintptr_t) == sizeof(size_t), + "theoretical maximum object size covers address space"); #endif - return dest_length + src_length; + return dest_length + src_length; } #endif /* HAVE_STRLCAT */ diff --git a/lib/strlcpy.c b/lib/strlcpy.c index 112c8180b..b7681754a 100644 --- a/lib/strlcpy.c +++ b/lib/strlcpy.c @@ -14,7 +14,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with the GNU C Library; if not, see - * . + * . */ /* adapted for Quagga from glibc patch submission originally from @@ -27,31 +27,27 @@ #ifndef HAVE_STRLCPY #undef strlcpy -size_t -strlcpy (char *__restrict dest, const char *__restrict src, size_t size); +size_t strlcpy(char *__restrict dest, const char *__restrict src, size_t size); -size_t -strlcpy (char *__restrict dest, const char *__restrict src, size_t size) +size_t strlcpy(char *__restrict dest, const char *__restrict src, size_t size) { - size_t src_length = strlen (src); + size_t src_length = strlen(src); - if (__builtin_expect (src_length >= size, 0)) - { - if (size > 0) - { - /* Copy the leading portion of the string. The last - character is subsequently overwritten with the NUL - terminator, but the destination size is usually a - multiple of a small power of two, so writing it twice - should be more efficient than copying an odd number of - bytes. */ - memcpy (dest, src, size); - dest[size - 1] = '\0'; - } - } - else - /* Copy the string and its terminating NUL character. */ - memcpy (dest, src, src_length + 1); - return src_length; + if (__builtin_expect(src_length >= size, 0)) { + if (size > 0) { + /* Copy the leading portion of the string. The last + character is subsequently overwritten with the NUL + terminator, but the destination size is usually a + multiple of a small power of two, so writing it twice + should be more efficient than copying an odd number + of + bytes. */ + memcpy(dest, src, size); + dest[size - 1] = '\0'; + } + } else + /* Copy the string and its terminating NUL character. */ + memcpy(dest, src, src_length + 1); + return src_length; } #endif /* HAVE_STRLCPY */ diff --git a/lib/systemd.c b/lib/systemd.c index 341de9eab..8a2a5eeac 100644 --- a/lib/systemd.c +++ b/lib/systemd.c @@ -32,65 +32,61 @@ * Wrapper this silliness if we * don't have systemd */ -void -systemd_send_information (const char *info) +void systemd_send_information(const char *info) { #if defined HAVE_SYSTEMD - sd_notify (0, info); + sd_notify(0, info); #else - return; + return; #endif } /* * A return of 0 means that we are not watchdoged */ -static int -systemd_get_watchdog_time (int the_process) +static int systemd_get_watchdog_time(int the_process) { #if defined HAVE_SYSTEMD - uint64_t usec; - char *watchdog = NULL; - int ret; - - ret = sd_watchdog_enabled (0, &usec); - - /* - * If return is 0 -> we don't want watchdog - * if return is < 0, some sort of failure occurred - */ - if (ret < 0) - return 0; - - /* - * systemd can return that this process - * is not the expected sender of the watchdog timer - * If we set the_process = 0 then we expect to - * be able to send the watchdog to systemd - * irrelevant of the pid of this process. - */ - if (ret == 0 && the_process) - return 0; - - if (ret == 0 && !the_process) - { - watchdog = getenv ("WATCHDOG_USEC"); - if (!watchdog) - return 0; - - usec = atol (watchdog); - } - - return (usec / 1000000)/ 3; + uint64_t usec; + char *watchdog = NULL; + int ret; + + ret = sd_watchdog_enabled(0, &usec); + + /* + * If return is 0 -> we don't want watchdog + * if return is < 0, some sort of failure occurred + */ + if (ret < 0) + return 0; + + /* + * systemd can return that this process + * is not the expected sender of the watchdog timer + * If we set the_process = 0 then we expect to + * be able to send the watchdog to systemd + * irrelevant of the pid of this process. + */ + if (ret == 0 && the_process) + return 0; + + if (ret == 0 && !the_process) { + watchdog = getenv("WATCHDOG_USEC"); + if (!watchdog) + return 0; + + usec = atol(watchdog); + } + + return (usec / 1000000) / 3; #else - return 0; + return 0; #endif } -void -systemd_send_stopping (void) +void systemd_send_stopping(void) { - systemd_send_information ("STOPPING=1"); + systemd_send_information("STOPPING=1"); } /* @@ -99,25 +95,24 @@ systemd_send_stopping (void) int wsecs = 0; struct thread_master *systemd_master = NULL; -static int -systemd_send_watchdog (struct thread *t) +static int systemd_send_watchdog(struct thread *t) { - systemd_send_information ("WATCHDOG=1"); + systemd_send_information("WATCHDOG=1"); - thread_add_timer(systemd_master, systemd_send_watchdog, NULL, wsecs, NULL); + thread_add_timer(systemd_master, systemd_send_watchdog, NULL, wsecs, + NULL); - return 1; + return 1; } -void -systemd_send_started (struct thread_master *m, int the_process) +void systemd_send_started(struct thread_master *m, int the_process) { - assert (m != NULL); + assert(m != NULL); - wsecs = systemd_get_watchdog_time(the_process); - systemd_master = m; + wsecs = systemd_get_watchdog_time(the_process); + systemd_master = m; - systemd_send_information ("READY=1"); - if (wsecs != 0) - thread_add_timer(m, systemd_send_watchdog, m, wsecs, NULL); + systemd_send_information("READY=1"); + if (wsecs != 0) + thread_add_timer(m, systemd_send_watchdog, m, wsecs, NULL); } diff --git a/lib/systemd.h b/lib/systemd.h index c048797cf..a13ea7bfd 100644 --- a/lib/systemd.h +++ b/lib/systemd.h @@ -28,13 +28,12 @@ * To turn on systemd compilation, use --enable-systemd on * configure run. */ -void systemd_send_information (const char *info); -void systemd_send_stopping (void); +void systemd_send_information(const char *info); +void systemd_send_stopping(void); /* * master - The struct thread_master * to use to schedule ourself * the_process - Should we send watchdog if we are not the requested * process? */ -void systemd_send_started (struct thread_master *master, int the_process); - +void systemd_send_started(struct thread_master *master, int the_process); diff --git a/lib/table.c b/lib/table.c index 1095b03b7..8e84d803e 100644 --- a/lib/table.c +++ b/lib/table.c @@ -29,510 +29,472 @@ #include "sockunion.h" #include "jhash.h" -DEFINE_MTYPE( LIB, ROUTE_TABLE, "Route table") -DEFINE_MTYPE( LIB, ROUTE_NODE, "Route node") +DEFINE_MTYPE(LIB, ROUTE_TABLE, "Route table") +DEFINE_MTYPE(LIB, ROUTE_NODE, "Route node") -static void route_node_delete (struct route_node *); -static void route_table_free (struct route_table *); +static void route_node_delete(struct route_node *); +static void route_table_free(struct route_table *); static unsigned route_table_hash_key(void *pp) { - struct prefix copy; + struct prefix copy; - /* make sure *all* unused bits are zero, particularly including alignment / - * padding and unused prefix bytes. */ - memset (©, 0, sizeof(copy)); - prefix_copy (©, (struct prefix *)pp); - return jhash (©, sizeof(copy), 0x55aa5a5a); + /* make sure *all* unused bits are zero, particularly including + * alignment / + * padding and unused prefix bytes. */ + memset(©, 0, sizeof(copy)); + prefix_copy(©, (struct prefix *)pp); + return jhash(©, sizeof(copy), 0x55aa5a5a); } static int route_table_hash_cmp(const void *a, const void *b) { - const struct prefix *pa = a, *pb = b; - return prefix_cmp(pa, pb) == 0; + const struct prefix *pa = a, *pb = b; + return prefix_cmp(pa, pb) == 0; } /* * route_table_init_with_delegate */ struct route_table * -route_table_init_with_delegate (route_table_delegate_t *delegate) +route_table_init_with_delegate(route_table_delegate_t *delegate) { - struct route_table *rt; + struct route_table *rt; - rt = XCALLOC (MTYPE_ROUTE_TABLE, sizeof (struct route_table)); - rt->delegate = delegate; - rt->hash = hash_create(route_table_hash_key, - route_table_hash_cmp, - "route table hash"); - return rt; + rt = XCALLOC(MTYPE_ROUTE_TABLE, sizeof(struct route_table)); + rt->delegate = delegate; + rt->hash = hash_create(route_table_hash_key, route_table_hash_cmp, + "route table hash"); + return rt; } -void -route_table_finish (struct route_table *rt) +void route_table_finish(struct route_table *rt) { - route_table_free (rt); + route_table_free(rt); } /* Allocate new route node. */ -static struct route_node * -route_node_new (struct route_table *table) +static struct route_node *route_node_new(struct route_table *table) { - return table->delegate->create_node (table->delegate, table); + return table->delegate->create_node(table->delegate, table); } /* Allocate new route node with prefix set. */ -static struct route_node * -route_node_set (struct route_table *table, const struct prefix *prefix) +static struct route_node *route_node_set(struct route_table *table, + const struct prefix *prefix) { - struct route_node *node, *inserted; - - node = route_node_new (table); + struct route_node *node, *inserted; - prefix_copy (&node->p, prefix); - node->table = table; + node = route_node_new(table); - inserted = hash_get (node->table->hash, node, hash_alloc_intern); - assert (inserted == node); + prefix_copy(&node->p, prefix); + node->table = table; - return node; + inserted = hash_get(node->table->hash, node, hash_alloc_intern); + assert(inserted == node); + + return node; } /* Free route node. */ -static void -route_node_free (struct route_table *table, struct route_node *node) +static void route_node_free(struct route_table *table, struct route_node *node) { - if (table->cleanup) - table->cleanup(table, node); - table->delegate->destroy_node (table->delegate, table, node); + if (table->cleanup) + table->cleanup(table, node); + table->delegate->destroy_node(table->delegate, table, node); } /* Free route table. */ -static void -route_table_free (struct route_table *rt) -{ - struct route_node *tmp_node; - struct route_node *node; - - if (rt == NULL) - return; - - hash_clean (rt->hash, NULL); - hash_free (rt->hash); - - node = rt->top; - - /* Bulk deletion of nodes remaining in this table. This function is not - called until workers have completed their dependency on this table. - A final route_unlock_node() will not be called for these nodes. */ - while (node) - { - if (node->l_left) - { - node = node->l_left; - continue; +static void route_table_free(struct route_table *rt) +{ + struct route_node *tmp_node; + struct route_node *node; + + if (rt == NULL) + return; + + hash_clean(rt->hash, NULL); + hash_free(rt->hash); + + node = rt->top; + + /* Bulk deletion of nodes remaining in this table. This function is not + called until workers have completed their dependency on this table. + A final route_unlock_node() will not be called for these nodes. */ + while (node) { + if (node->l_left) { + node = node->l_left; + continue; + } + + if (node->l_right) { + node = node->l_right; + continue; + } + + tmp_node = node; + node = node->parent; + + tmp_node->table->count--; + tmp_node->lock = 0; /* to cause assert if unlocked after this */ + route_node_free(rt, tmp_node); + + if (node != NULL) { + if (node->l_left == tmp_node) + node->l_left = NULL; + else + node->l_right = NULL; + } else { + break; + } } - if (node->l_right) - { - node = node->l_right; - continue; - } - - tmp_node = node; - node = node->parent; - - tmp_node->table->count--; - tmp_node->lock = 0; /* to cause assert if unlocked after this */ - route_node_free (rt, tmp_node); - - if (node != NULL) - { - if (node->l_left == tmp_node) - node->l_left = NULL; - else - node->l_right = NULL; - } - else - { - break; - } - } - - assert (rt->count == 0); + assert(rt->count == 0); - XFREE (MTYPE_ROUTE_TABLE, rt); - return; + XFREE(MTYPE_ROUTE_TABLE, rt); + return; } /* Utility mask array. */ -static const u_char maskbit[] = -{ - 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff -}; +static const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, + 0xf8, 0xfc, 0xfe, 0xff}; /* Common prefix route genaration. */ -static void -route_common (const struct prefix *n, const struct prefix *p, struct prefix *new) -{ - int i; - u_char diff; - u_char mask; - - const u_char *np = (const u_char *)&n->u.prefix; - const u_char *pp = (const u_char *)&p->u.prefix; - u_char *newp = (u_char *)&new->u.prefix; - - for (i = 0; i < p->prefixlen / 8; i++) - { - if (np[i] == pp[i]) - newp[i] = np[i]; - else - break; - } - - new->prefixlen = i * 8; - - if (new->prefixlen != p->prefixlen) - { - diff = np[i] ^ pp[i]; - mask = 0x80; - while (new->prefixlen < p->prefixlen && !(mask & diff)) - { - mask >>= 1; - new->prefixlen++; +static void route_common(const struct prefix *n, const struct prefix *p, + struct prefix *new) +{ + int i; + u_char diff; + u_char mask; + + const u_char *np = (const u_char *)&n->u.prefix; + const u_char *pp = (const u_char *)&p->u.prefix; + u_char *newp = (u_char *)&new->u.prefix; + + for (i = 0; i < p->prefixlen / 8; i++) { + if (np[i] == pp[i]) + newp[i] = np[i]; + else + break; + } + + new->prefixlen = i * 8; + + if (new->prefixlen != p->prefixlen) { + diff = np[i] ^ pp[i]; + mask = 0x80; + while (new->prefixlen < p->prefixlen && !(mask & diff)) { + mask >>= 1; + new->prefixlen++; + } + newp[i] = np[i] & maskbit[new->prefixlen % 8]; } - newp[i] = np[i] & maskbit[new->prefixlen % 8]; - } } -static void -set_link (struct route_node *node, struct route_node *new) +static void set_link(struct route_node *node, struct route_node *new) { - unsigned int bit = prefix_bit (&new->p.u.prefix, node->p.prefixlen); + unsigned int bit = prefix_bit(&new->p.u.prefix, node->p.prefixlen); - node->link[bit] = new; - new->parent = node; + node->link[bit] = new; + new->parent = node; } /* Lock node. */ -struct route_node * -route_lock_node (struct route_node *node) +struct route_node *route_lock_node(struct route_node *node) { - node->lock++; - return node; + node->lock++; + return node; } /* Unlock node. */ -void -route_unlock_node (struct route_node *node) +void route_unlock_node(struct route_node *node) { - assert (node->lock > 0); - node->lock--; + assert(node->lock > 0); + node->lock--; - if (node->lock == 0) - route_node_delete (node); + if (node->lock == 0) + route_node_delete(node); } /* Find matched prefix. */ -struct route_node * -route_node_match (const struct route_table *table, union prefixconstptr pu) +struct route_node *route_node_match(const struct route_table *table, + union prefixconstptr pu) { - const struct prefix *p = pu.p; - struct route_node *node; - struct route_node *matched; + const struct prefix *p = pu.p; + struct route_node *node; + struct route_node *matched; - matched = NULL; - node = table->top; + matched = NULL; + node = table->top; - /* Walk down tree. If there is matched route then store it to - matched. */ - while (node && node->p.prefixlen <= p->prefixlen && - prefix_match (&node->p, p)) - { - if (node->info) - matched = node; - - if (node->p.prefixlen == p->prefixlen) - break; - - node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)]; - } + /* Walk down tree. If there is matched route then store it to + matched. */ + while (node && node->p.prefixlen <= p->prefixlen + && prefix_match(&node->p, p)) { + if (node->info) + matched = node; - /* If matched route found, return it. */ - if (matched) - return route_lock_node (matched); + if (node->p.prefixlen == p->prefixlen) + break; - return NULL; + node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)]; + } + + /* If matched route found, return it. */ + if (matched) + return route_lock_node(matched); + + return NULL; } -struct route_node * -route_node_match_ipv4 (const struct route_table *table, - const struct in_addr *addr) +struct route_node *route_node_match_ipv4(const struct route_table *table, + const struct in_addr *addr) { - struct prefix_ipv4 p; + struct prefix_ipv4 p; - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = IPV4_MAX_PREFIXLEN; - p.prefix = *addr; + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefixlen = IPV4_MAX_PREFIXLEN; + p.prefix = *addr; - return route_node_match (table, (struct prefix *) &p); + return route_node_match(table, (struct prefix *)&p); } -struct route_node * -route_node_match_ipv6 (const struct route_table *table, - const struct in6_addr *addr) +struct route_node *route_node_match_ipv6(const struct route_table *table, + const struct in6_addr *addr) { - struct prefix_ipv6 p; + struct prefix_ipv6 p; - memset (&p, 0, sizeof (struct prefix_ipv6)); - p.family = AF_INET6; - p.prefixlen = IPV6_MAX_PREFIXLEN; - p.prefix = *addr; + memset(&p, 0, sizeof(struct prefix_ipv6)); + p.family = AF_INET6; + p.prefixlen = IPV6_MAX_PREFIXLEN; + p.prefix = *addr; - return route_node_match (table, (struct prefix *) &p); + return route_node_match(table, (struct prefix *)&p); } /* Lookup same prefix node. Return NULL when we can't find route. */ -struct route_node * -route_node_lookup (const struct route_table *table, union prefixconstptr pu) +struct route_node *route_node_lookup(const struct route_table *table, + union prefixconstptr pu) { - const struct prefix *p = pu.p; - struct route_node *node; + const struct prefix *p = pu.p; + struct route_node *node; - node = hash_get (table->hash, (void *)p, NULL); - return (node && node->info) ? route_lock_node (node) : NULL; + node = hash_get(table->hash, (void *)p, NULL); + return (node && node->info) ? route_lock_node(node) : NULL; } /* Lookup same prefix node. Return NULL when we can't find route. */ -struct route_node * -route_node_lookup_maynull (const struct route_table *table, union prefixconstptr pu) +struct route_node *route_node_lookup_maynull(const struct route_table *table, + union prefixconstptr pu) { - const struct prefix *p = pu.p; - struct route_node *node; + const struct prefix *p = pu.p; + struct route_node *node; - node = hash_get (table->hash, (void *)p, NULL); - return node ? route_lock_node (node) : NULL; + node = hash_get(table->hash, (void *)p, NULL); + return node ? route_lock_node(node) : NULL; } /* Add node to routing table. */ -struct route_node * -route_node_get (struct route_table *const table, union prefixconstptr pu) -{ - const struct prefix *p = pu.p; - struct route_node *new; - struct route_node *node; - struct route_node *match; - struct route_node *inserted; - u_char prefixlen = p->prefixlen; - const u_char *prefix = &p->u.prefix; - - node = hash_get (table->hash, (void *)p, NULL); - if (node && node->info) - return route_lock_node (node); - - match = NULL; - node = table->top; - while (node && node->p.prefixlen <= prefixlen && - prefix_match (&node->p, p)) - { - if (node->p.prefixlen == prefixlen) - return route_lock_node (node); - - match = node; - node = node->link[prefix_bit(prefix, node->p.prefixlen)]; - } - - if (node == NULL) - { - new = route_node_set (table, p); - if (match) - set_link (match, new); - else - table->top = new; - } - else - { - new = route_node_new (table); - route_common (&node->p, p, &new->p); - new->p.family = p->family; - new->table = table; - set_link (new, node); - inserted = hash_get (node->table->hash, new, hash_alloc_intern); - assert (inserted == new); - - if (match) - set_link (match, new); - else - table->top = new; - - if (new->p.prefixlen != p->prefixlen) - { - match = new; - new = route_node_set (table, p); - set_link (match, new); - table->count++; +struct route_node *route_node_get(struct route_table *const table, + union prefixconstptr pu) +{ + const struct prefix *p = pu.p; + struct route_node *new; + struct route_node *node; + struct route_node *match; + struct route_node *inserted; + u_char prefixlen = p->prefixlen; + const u_char *prefix = &p->u.prefix; + + node = hash_get(table->hash, (void *)p, NULL); + if (node && node->info) + return route_lock_node(node); + + match = NULL; + node = table->top; + while (node && node->p.prefixlen <= prefixlen + && prefix_match(&node->p, p)) { + if (node->p.prefixlen == prefixlen) + return route_lock_node(node); + + match = node; + node = node->link[prefix_bit(prefix, node->p.prefixlen)]; + } + + if (node == NULL) { + new = route_node_set(table, p); + if (match) + set_link(match, new); + else + table->top = new; + } else { + new = route_node_new(table); + route_common(&node->p, p, &new->p); + new->p.family = p->family; + new->table = table; + set_link(new, node); + inserted = hash_get(node->table->hash, new, hash_alloc_intern); + assert(inserted == new); + + if (match) + set_link(match, new); + else + table->top = new; + + if (new->p.prefixlen != p->prefixlen) { + match = new; + new = route_node_set(table, p); + set_link(match, new); + table->count++; + } } - } - table->count++; - route_lock_node (new); - - return new; + table->count++; + route_lock_node(new); + + return new; } /* Delete node from the routing table. */ -static void -route_node_delete (struct route_node *node) +static void route_node_delete(struct route_node *node) { - struct route_node *child; - struct route_node *parent; + struct route_node *child; + struct route_node *parent; - assert (node->lock == 0); - assert (node->info == NULL); + assert(node->lock == 0); + assert(node->info == NULL); - if (node->l_left && node->l_right) - return; + if (node->l_left && node->l_right) + return; - if (node->l_left) - child = node->l_left; - else - child = node->l_right; + if (node->l_left) + child = node->l_left; + else + child = node->l_right; - parent = node->parent; + parent = node->parent; - if (child) - child->parent = parent; + if (child) + child->parent = parent; - if (parent) - { - if (parent->l_left == node) - parent->l_left = child; - else - parent->l_right = child; - } - else - node->table->top = child; + if (parent) { + if (parent->l_left == node) + parent->l_left = child; + else + parent->l_right = child; + } else + node->table->top = child; - node->table->count--; + node->table->count--; - hash_release (node->table->hash, node); + hash_release(node->table->hash, node); - /* WARNING: FRAGILE CODE! - * route_node_free may have the side effect of free'ing the entire table. - * this is permitted only if table->count got decremented to zero above, - * because in that case parent will also be NULL, so that we won't try to - * delete a now-stale parent below. - * - * cf. srcdest_srcnode_destroy() in zebra/zebra_rib.c */ + /* WARNING: FRAGILE CODE! + * route_node_free may have the side effect of free'ing the entire + * table. + * this is permitted only if table->count got decremented to zero above, + * because in that case parent will also be NULL, so that we won't try + * to + * delete a now-stale parent below. + * + * cf. srcdest_srcnode_destroy() in zebra/zebra_rib.c */ - route_node_free (node->table, node); + route_node_free(node->table, node); - /* If parent node is stub then delete it also. */ - if (parent && parent->lock == 0) - route_node_delete (parent); + /* If parent node is stub then delete it also. */ + if (parent && parent->lock == 0) + route_node_delete(parent); } /* Get fist node and lock it. This function is useful when one want to lookup all the node exist in the routing table. */ -struct route_node * -route_top (struct route_table *table) +struct route_node *route_top(struct route_table *table) { - /* If there is no node in the routing table return NULL. */ - if (table->top == NULL) - return NULL; + /* If there is no node in the routing table return NULL. */ + if (table->top == NULL) + return NULL; - /* Lock the top node and return it. */ - route_lock_node (table->top); - return table->top; + /* Lock the top node and return it. */ + route_lock_node(table->top); + return table->top; } /* Unlock current node and lock next node then return it. */ -struct route_node * -route_next (struct route_node *node) -{ - struct route_node *next; - struct route_node *start; - - /* Node may be deleted from route_unlock_node so we have to preserve - next node's pointer. */ - - if (node->l_left) - { - next = node->l_left; - route_lock_node (next); - route_unlock_node (node); - return next; - } - if (node->l_right) - { - next = node->l_right; - route_lock_node (next); - route_unlock_node (node); - return next; - } - - start = node; - while (node->parent) - { - if (node->parent->l_left == node && node->parent->l_right) - { - next = node->parent->l_right; - route_lock_node (next); - route_unlock_node (start); - return next; +struct route_node *route_next(struct route_node *node) +{ + struct route_node *next; + struct route_node *start; + + /* Node may be deleted from route_unlock_node so we have to preserve + next node's pointer. */ + + if (node->l_left) { + next = node->l_left; + route_lock_node(next); + route_unlock_node(node); + return next; + } + if (node->l_right) { + next = node->l_right; + route_lock_node(next); + route_unlock_node(node); + return next; + } + + start = node; + while (node->parent) { + if (node->parent->l_left == node && node->parent->l_right) { + next = node->parent->l_right; + route_lock_node(next); + route_unlock_node(start); + return next; + } + node = node->parent; } - node = node->parent; - } - route_unlock_node (start); - return NULL; + route_unlock_node(start); + return NULL; } /* Unlock current node and lock next node until limit. */ -struct route_node * -route_next_until (struct route_node *node, const struct route_node *limit) -{ - struct route_node *next; - struct route_node *start; - - /* Node may be deleted from route_unlock_node so we have to preserve - next node's pointer. */ - - if (node->l_left) - { - next = node->l_left; - route_lock_node (next); - route_unlock_node (node); - return next; - } - if (node->l_right) - { - next = node->l_right; - route_lock_node (next); - route_unlock_node (node); - return next; - } - - start = node; - while (node->parent && node != limit) - { - if (node->parent->l_left == node && node->parent->l_right) - { - next = node->parent->l_right; - route_lock_node (next); - route_unlock_node (start); - return next; +struct route_node *route_next_until(struct route_node *node, + const struct route_node *limit) +{ + struct route_node *next; + struct route_node *start; + + /* Node may be deleted from route_unlock_node so we have to preserve + next node's pointer. */ + + if (node->l_left) { + next = node->l_left; + route_lock_node(next); + route_unlock_node(node); + return next; + } + if (node->l_right) { + next = node->l_right; + route_lock_node(next); + route_unlock_node(node); + return next; + } + + start = node; + while (node->parent && node != limit) { + if (node->parent->l_left == node && node->parent->l_right) { + next = node->parent->l_right; + route_lock_node(next); + route_unlock_node(start); + return next; + } + node = node->parent; } - node = node->parent; - } - route_unlock_node (start); - return NULL; + route_unlock_node(start); + return NULL; } -unsigned long -route_table_count (const struct route_table *table) +unsigned long route_table_count(const struct route_table *table) { - return table->count; + return table->count; } /** @@ -540,13 +502,12 @@ route_table_count (const struct route_table *table) * * Default function for creating a route node. */ -struct route_node * -route_node_create (route_table_delegate_t *delegate, - struct route_table *table) +struct route_node *route_node_create(route_table_delegate_t *delegate, + struct route_table *table) { - struct route_node *node; - node = XCALLOC (MTYPE_ROUTE_NODE, sizeof (struct route_node)); - return node; + struct route_node *node; + node = XCALLOC(MTYPE_ROUTE_NODE, sizeof(struct route_node)); + return node; } /** @@ -554,34 +515,30 @@ route_node_create (route_table_delegate_t *delegate, * * Default function for destroying a route node. */ -void -route_node_destroy (route_table_delegate_t *delegate, - struct route_table *table, struct route_node *node) +void route_node_destroy(route_table_delegate_t *delegate, + struct route_table *table, struct route_node *node) { - XFREE (MTYPE_ROUTE_NODE, node); + XFREE(MTYPE_ROUTE_NODE, node); } /* * Default delegate. */ static route_table_delegate_t default_delegate = { - .create_node = route_node_create, - .destroy_node = route_node_destroy -}; + .create_node = route_node_create, + .destroy_node = route_node_destroy}; -route_table_delegate_t * -route_table_get_default_delegate(void) +route_table_delegate_t *route_table_get_default_delegate(void) { - return &default_delegate; + return &default_delegate; } /* * route_table_init */ -struct route_table * -route_table_init (void) +struct route_table *route_table_init(void) { - return route_table_init_with_delegate (&default_delegate); + return route_table_init_with_delegate(&default_delegate); } /** @@ -589,63 +546,58 @@ route_table_init (void) * * Compare two prefixes according to the order in which they appear in * an iteration over a tree. - * + * * @return -1 if p1 occurs before p2 (p1 < p2) * 0 if the prefixes are identical (p1 == p2) * +1 if p1 occurs after p2 (p1 > p2) */ -int -route_table_prefix_iter_cmp (const struct prefix *p1, const struct prefix *p2) -{ - struct prefix common_space; - struct prefix *common = &common_space; - - if (p1->prefixlen <= p2->prefixlen) - { - if (prefix_match (p1, p2)) - { +int route_table_prefix_iter_cmp(const struct prefix *p1, + const struct prefix *p2) +{ + struct prefix common_space; + struct prefix *common = &common_space; + + if (p1->prefixlen <= p2->prefixlen) { + if (prefix_match(p1, p2)) { + + /* + * p1 contains p2, or is equal to it. + */ + return (p1->prefixlen == p2->prefixlen) ? 0 : -1; + } + } else { + + /* + * Check if p2 contains p1. + */ + if (prefix_match(p2, p1)) + return 1; + } - /* - * p1 contains p2, or is equal to it. - */ - return (p1->prefixlen == p2->prefixlen) ? 0 : -1; + route_common(p1, p2, common); + assert(common->prefixlen < p1->prefixlen); + assert(common->prefixlen < p2->prefixlen); + + /* + * Both prefixes are longer than the common prefix. + * + * We need to check the bit after the common prefixlen to determine + * which one comes later. + */ + if (prefix_bit(&p1->u.prefix, common->prefixlen)) { + + /* + * We branch to the right to get to p1 from the common prefix. + */ + assert(!prefix_bit(&p2->u.prefix, common->prefixlen)); + return 1; } - } - else - { - - /* - * Check if p2 contains p1. - */ - if (prefix_match (p2, p1)) - return 1; - } - - route_common (p1, p2, common); - assert (common->prefixlen < p1->prefixlen); - assert (common->prefixlen < p2->prefixlen); - - /* - * Both prefixes are longer than the common prefix. - * - * We need to check the bit after the common prefixlen to determine - * which one comes later. - */ - if (prefix_bit (&p1->u.prefix, common->prefixlen)) - { - - /* - * We branch to the right to get to p1 from the common prefix. - */ - assert (!prefix_bit (&p2->u.prefix, common->prefixlen)); - return 1; - } - - /* - * We branch to the right to get to p2 from the common prefix. - */ - assert (prefix_bit (&p2->u.prefix, common->prefixlen)); - return -1; + + /* + * We branch to the right to get to p2 from the common prefix. + */ + assert(prefix_bit(&p2->u.prefix, common->prefixlen)); + return -1; } /* @@ -654,18 +606,16 @@ route_table_prefix_iter_cmp (const struct prefix *p1, const struct prefix *p2) * Helper function that returns the first node that follows the nodes * in the sub-tree under 'node' in iteration order. */ -static struct route_node * -route_get_subtree_next (struct route_node *node) +static struct route_node *route_get_subtree_next(struct route_node *node) { - while (node->parent) - { - if (node->parent->l_left == node && node->parent->l_right) - return node->parent->l_right; + while (node->parent) { + if (node->parent->l_left == node && node->parent->l_right) + return node->parent->l_right; - node = node->parent; - } + node = node->parent; + } - return NULL; + return NULL; } /** @@ -677,99 +627,99 @@ route_get_subtree_next (struct route_node *node) * @see route_table_get_next */ static struct route_node * -route_table_get_next_internal (const struct route_table *table, - const struct prefix *p) -{ - struct route_node *node, *tmp_node; - int cmp; - - node = table->top; - - while (node) - { - int match; - - if (node->p.prefixlen < p->prefixlen) - match = prefix_match (&node->p, p); - else - match = prefix_match (p, &node->p); - - if (match) - { - if (node->p.prefixlen == p->prefixlen) - { - - /* - * The prefix p exists in the tree, just return the next - * node. - */ - route_lock_node (node); - node = route_next (node); - if (node) - route_unlock_node (node); - - return (node); - } - - if (node->p.prefixlen > p->prefixlen) - { - - /* - * Node is in the subtree of p, and hence greater than p. - */ - return node; - } - - /* - * p is in the sub-tree under node. - */ - tmp_node = node->link[prefix_bit (&p->u.prefix, node->p.prefixlen)]; - - if (tmp_node) - { - node = tmp_node; - continue; - } - - /* - * There are no nodes in the direction where p should be. If - * node has a right child, then it must be greater than p. - */ - if (node->l_right) - return node->l_right; - - /* - * No more children to follow, go upwards looking for the next - * node. - */ - return route_get_subtree_next (node); - } - - /* - * Neither node prefix nor 'p' contains the other. - */ - cmp = route_table_prefix_iter_cmp (&node->p, p); - if (cmp > 0) - { - - /* - * Node follows p in iteration order. Return it. - */ - return node; +route_table_get_next_internal(const struct route_table *table, + const struct prefix *p) +{ + struct route_node *node, *tmp_node; + int cmp; + + node = table->top; + + while (node) { + int match; + + if (node->p.prefixlen < p->prefixlen) + match = prefix_match(&node->p, p); + else + match = prefix_match(p, &node->p); + + if (match) { + if (node->p.prefixlen == p->prefixlen) { + + /* + * The prefix p exists in the tree, just return + * the next + * node. + */ + route_lock_node(node); + node = route_next(node); + if (node) + route_unlock_node(node); + + return (node); + } + + if (node->p.prefixlen > p->prefixlen) { + + /* + * Node is in the subtree of p, and hence + * greater than p. + */ + return node; + } + + /* + * p is in the sub-tree under node. + */ + tmp_node = node->link[prefix_bit(&p->u.prefix, + node->p.prefixlen)]; + + if (tmp_node) { + node = tmp_node; + continue; + } + + /* + * There are no nodes in the direction where p should + * be. If + * node has a right child, then it must be greater than + * p. + */ + if (node->l_right) + return node->l_right; + + /* + * No more children to follow, go upwards looking for + * the next + * node. + */ + return route_get_subtree_next(node); + } + + /* + * Neither node prefix nor 'p' contains the other. + */ + cmp = route_table_prefix_iter_cmp(&node->p, p); + if (cmp > 0) { + + /* + * Node follows p in iteration order. Return it. + */ + return node; + } + + assert(cmp < 0); + + /* + * Node and the subtree under it come before prefix p in + * iteration order. Prefix p and its sub-tree are not present in + * the tree. Go upwards and find the first node that follows the + * subtree. That node will also succeed p. + */ + return route_get_subtree_next(node); } - assert (cmp < 0); - - /* - * Node and the subtree under it come before prefix p in - * iteration order. Prefix p and its sub-tree are not present in - * the tree. Go upwards and find the first node that follows the - * subtree. That node will also succeed p. - */ - return route_get_subtree_next (node); - } - - return NULL; + return NULL; } /** @@ -778,30 +728,28 @@ route_table_get_next_internal (const struct route_table *table, * Find the node that occurs after the given prefix in order of * iteration. */ -struct route_node * -route_table_get_next (const struct route_table *table, union prefixconstptr pu) +struct route_node *route_table_get_next(const struct route_table *table, + union prefixconstptr pu) { - const struct prefix *p = pu.p; - struct route_node *node; + const struct prefix *p = pu.p; + struct route_node *node; - node = route_table_get_next_internal (table, p); - if (node) - { - assert (route_table_prefix_iter_cmp (&node->p, p) > 0); - route_lock_node (node); - } - return node; + node = route_table_get_next_internal(table, p); + if (node) { + assert(route_table_prefix_iter_cmp(&node->p, p) > 0); + route_lock_node(node); + } + return node; } /* * route_table_iter_init */ -void -route_table_iter_init (route_table_iter_t * iter, struct route_table *table) +void route_table_iter_init(route_table_iter_t *iter, struct route_table *table) { - memset (iter, 0, sizeof (*iter)); - iter->state = RT_ITER_STATE_INIT; - iter->table = table; + memset(iter, 0, sizeof(*iter)); + iter->state = RT_ITER_STATE_INIT; + iter->table = table; } /* @@ -812,34 +760,32 @@ route_table_iter_init (route_table_iter_t * iter, struct route_table *table) * An iteration can be resumed by just calling route_table_iter_next() * on the iterator. */ -void -route_table_iter_pause (route_table_iter_t * iter) -{ - switch (iter->state) - { - - case RT_ITER_STATE_INIT: - case RT_ITER_STATE_PAUSED: - case RT_ITER_STATE_DONE: - return; - - case RT_ITER_STATE_ITERATING: - - /* - * Save the prefix that we are currently at. The next call to - * route_table_iter_next() will return the node after this prefix - * in the tree. - */ - prefix_copy (&iter->pause_prefix, &iter->current->p); - route_unlock_node (iter->current); - iter->current = NULL; - iter->state = RT_ITER_STATE_PAUSED; - return; - - default: - assert (0); - } - +void route_table_iter_pause(route_table_iter_t *iter) +{ + switch (iter->state) { + + case RT_ITER_STATE_INIT: + case RT_ITER_STATE_PAUSED: + case RT_ITER_STATE_DONE: + return; + + case RT_ITER_STATE_ITERATING: + + /* + * Save the prefix that we are currently at. The next call to + * route_table_iter_next() will return the node after this + * prefix + * in the tree. + */ + prefix_copy(&iter->pause_prefix, &iter->current->p); + route_unlock_node(iter->current); + iter->current = NULL; + iter->state = RT_ITER_STATE_PAUSED; + return; + + default: + assert(0); + } } /* @@ -847,19 +793,17 @@ route_table_iter_pause (route_table_iter_t * iter) * * Release any resources held by the iterator. */ -void -route_table_iter_cleanup (route_table_iter_t * iter) -{ - if (iter->state == RT_ITER_STATE_ITERATING) - { - route_unlock_node (iter->current); - iter->current = NULL; - } - assert (!iter->current); - - /* - * Set the state to RT_ITER_STATE_DONE to make any - * route_table_iter_next() calls on this iterator return NULL. - */ - iter->state = RT_ITER_STATE_DONE; +void route_table_iter_cleanup(route_table_iter_t *iter) +{ + if (iter->state == RT_ITER_STATE_ITERATING) { + route_unlock_node(iter->current); + iter->current = NULL; + } + assert(!iter->current); + + /* + * Set the state to RT_ITER_STATE_DONE to make any + * route_table_iter_next() calls on this iterator return NULL. + */ + iter->state = RT_ITER_STATE_DONE; } diff --git a/lib/table.h b/lib/table.h index 79a32b59a..b7b402a59 100644 --- a/lib/table.h +++ b/lib/table.h @@ -41,36 +41,35 @@ struct route_table; */ typedef struct route_table_delegate_t_ route_table_delegate_t; -typedef struct route_node * (*route_table_create_node_func_t) - (route_table_delegate_t *, struct route_table *); +typedef struct route_node *(*route_table_create_node_func_t)( + route_table_delegate_t *, struct route_table *); -typedef void (*route_table_destroy_node_func_t) - (route_table_delegate_t *, struct route_table *, struct route_node *); +typedef void (*route_table_destroy_node_func_t)(route_table_delegate_t *, + struct route_table *, + struct route_node *); -struct route_table_delegate_t_ -{ - route_table_create_node_func_t create_node; - route_table_destroy_node_func_t destroy_node; +struct route_table_delegate_t_ { + route_table_create_node_func_t create_node; + route_table_destroy_node_func_t destroy_node; }; /* Routing table top structure. */ -struct route_table -{ - struct route_node *top; - struct hash *hash; - - /* - * Delegate that performs certain functions for this table. - */ - route_table_delegate_t *delegate; - void (*cleanup)(struct route_table *, struct route_node *); - - unsigned long count; - - /* - * User data. - */ - void *info; +struct route_table { + struct route_node *top; + struct hash *hash; + + /* + * Delegate that performs certain functions for this table. + */ + route_table_delegate_t *delegate; + void (*cleanup)(struct route_table *, struct route_node *); + + unsigned long count; + + /* + * User data. + */ + void *info; }; /* @@ -89,8 +88,9 @@ struct route_table #define table_internal(x) x #else #define table_rdonly(x) const x -#define table_internal(x) const x \ - __attribute__((deprecated("this should only be accessed by lib/table.c"))) +#define table_internal(x) \ + const x __attribute__( \ + (deprecated("this should only be accessed by lib/table.c"))) /* table_internal is for node->link and node->lock, once we have done * something about remaining accesses */ #endif @@ -111,29 +111,28 @@ struct route_table /* * Macro that defines all fields in a route node. */ -#define ROUTE_NODE_FIELDS \ - /* Actual prefix of this radix. */ \ - struct prefix p; \ - \ - /* Tree link. */ \ - struct route_table * table_rdonly(table); \ - struct route_node * table_rdonly(parent); \ - struct route_node * table_rdonly(link[2]); \ - \ - /* Lock of this radix */ \ - unsigned int table_rdonly(lock); \ - \ - /* Each node of route. */ \ - void *info; \ - \ - /* Aggregation. */ \ - void *aggregate; +#define ROUTE_NODE_FIELDS \ + /* Actual prefix of this radix. */ \ + struct prefix p; \ + \ + /* Tree link. */ \ + struct route_table *table_rdonly(table); \ + struct route_node *table_rdonly(parent); \ + struct route_node *table_rdonly(link[2]); \ + \ + /* Lock of this radix */ \ + unsigned int table_rdonly(lock); \ + \ + /* Each node of route. */ \ + void *info; \ + \ + /* Aggregation. */ \ + void *aggregate; /* Each routing entry. */ -struct route_node -{ - ROUTE_NODE_FIELDS +struct route_node { + ROUTE_NODE_FIELDS #define l_left link[0] #define l_right link[1] @@ -141,89 +140,86 @@ struct route_node typedef struct route_table_iter_t_ route_table_iter_t; -typedef enum -{ - RT_ITER_STATE_INIT, - RT_ITER_STATE_ITERATING, - RT_ITER_STATE_PAUSED, - RT_ITER_STATE_DONE +typedef enum { + RT_ITER_STATE_INIT, + RT_ITER_STATE_ITERATING, + RT_ITER_STATE_PAUSED, + RT_ITER_STATE_DONE } route_table_iter_state_t; /* * route_table_iter_t - * + * * Structure that holds state for iterating over a route table. */ -struct route_table_iter_t_ -{ +struct route_table_iter_t_ { - route_table_iter_state_t state; + route_table_iter_state_t state; - /* - * Routing table that we are iterating over. The caller must ensure - * that that table outlives the iterator. - */ - struct route_table *table; + /* + * Routing table that we are iterating over. The caller must ensure + * that that table outlives the iterator. + */ + struct route_table *table; - /* - * The node that the iterator is currently on. - */ - struct route_node *current; + /* + * The node that the iterator is currently on. + */ + struct route_node *current; - /* - * The last prefix that the iterator processed before it was paused. - */ - struct prefix pause_prefix; + /* + * The last prefix that the iterator processed before it was paused. + */ + struct prefix pause_prefix; }; /* Prototypes. */ -extern struct route_table *route_table_init (void); +extern struct route_table *route_table_init(void); extern struct route_table * -route_table_init_with_delegate (route_table_delegate_t *); - -extern route_table_delegate_t * -route_table_get_default_delegate(void); - -extern void route_table_finish (struct route_table *); -extern void route_unlock_node (struct route_node *node); -extern struct route_node *route_top (struct route_table *); -extern struct route_node *route_next (struct route_node *); -extern struct route_node *route_next_until (struct route_node *, - const struct route_node *); -extern struct route_node *route_node_get (struct route_table *const, - union prefixconstptr); -extern struct route_node *route_node_lookup (const struct route_table *, - union prefixconstptr); -extern struct route_node *route_node_lookup_maynull (const struct route_table *, - union prefixconstptr); -extern struct route_node *route_lock_node (struct route_node *node); -extern struct route_node *route_node_match (const struct route_table *, - union prefixconstptr); -extern struct route_node *route_node_match_ipv4 (const struct route_table *, - const struct in_addr *); -extern struct route_node *route_node_match_ipv6 (const struct route_table *, - const struct in6_addr *); - -extern unsigned long route_table_count (const struct route_table *); - -extern struct route_node *route_node_create (route_table_delegate_t *, - struct route_table *); -extern void route_node_destroy (route_table_delegate_t *, - struct route_table *, struct route_node *); - -extern struct route_node * -route_table_get_next (const struct route_table *table, union prefixconstptr pu); -extern int -route_table_prefix_iter_cmp (const struct prefix *p1, const struct prefix *p2); +route_table_init_with_delegate(route_table_delegate_t *); + +extern route_table_delegate_t *route_table_get_default_delegate(void); + +extern void route_table_finish(struct route_table *); +extern void route_unlock_node(struct route_node *node); +extern struct route_node *route_top(struct route_table *); +extern struct route_node *route_next(struct route_node *); +extern struct route_node *route_next_until(struct route_node *, + const struct route_node *); +extern struct route_node *route_node_get(struct route_table *const, + union prefixconstptr); +extern struct route_node *route_node_lookup(const struct route_table *, + union prefixconstptr); +extern struct route_node *route_node_lookup_maynull(const struct route_table *, + union prefixconstptr); +extern struct route_node *route_lock_node(struct route_node *node); +extern struct route_node *route_node_match(const struct route_table *, + union prefixconstptr); +extern struct route_node *route_node_match_ipv4(const struct route_table *, + const struct in_addr *); +extern struct route_node *route_node_match_ipv6(const struct route_table *, + const struct in6_addr *); + +extern unsigned long route_table_count(const struct route_table *); + +extern struct route_node *route_node_create(route_table_delegate_t *, + struct route_table *); +extern void route_node_destroy(route_table_delegate_t *, struct route_table *, + struct route_node *); + +extern struct route_node *route_table_get_next(const struct route_table *table, + union prefixconstptr pu); +extern int route_table_prefix_iter_cmp(const struct prefix *p1, + const struct prefix *p2); /* * Iterator functions. */ -extern void route_table_iter_init (route_table_iter_t *iter, - struct route_table *table); -extern void route_table_iter_pause (route_table_iter_t *iter); -extern void route_table_iter_cleanup (route_table_iter_t *iter); +extern void route_table_iter_init(route_table_iter_t *iter, + struct route_table *table); +extern void route_table_iter_pause(route_table_iter_t *iter); +extern void route_table_iter_cleanup(route_table_iter_t *iter); /* * Inline functions. @@ -234,48 +230,46 @@ extern void route_table_iter_cleanup (route_table_iter_t *iter); * * Get the next node in the tree. */ -static inline struct route_node * -route_table_iter_next (route_table_iter_t * iter) +static inline struct route_node *route_table_iter_next(route_table_iter_t *iter) { - struct route_node *node; + struct route_node *node; - switch (iter->state) - { + switch (iter->state) { - case RT_ITER_STATE_INIT: + case RT_ITER_STATE_INIT: - /* - * We're just starting the iteration. - */ - node = route_top (iter->table); - break; + /* + * We're just starting the iteration. + */ + node = route_top(iter->table); + break; - case RT_ITER_STATE_ITERATING: - node = route_next (iter->current); - break; + case RT_ITER_STATE_ITERATING: + node = route_next(iter->current); + break; - case RT_ITER_STATE_PAUSED: + case RT_ITER_STATE_PAUSED: - /* - * Start with the node following pause_prefix. - */ - node = route_table_get_next (iter->table, &iter->pause_prefix); - break; + /* + * Start with the node following pause_prefix. + */ + node = route_table_get_next(iter->table, &iter->pause_prefix); + break; - case RT_ITER_STATE_DONE: - return NULL; + case RT_ITER_STATE_DONE: + return NULL; - default: - assert (0); - } + default: + assert(0); + } - iter->current = node; - if (node) - iter->state = RT_ITER_STATE_ITERATING; - else - iter->state = RT_ITER_STATE_DONE; + iter->current = node; + if (node) + iter->state = RT_ITER_STATE_ITERATING; + else + iter->state = RT_ITER_STATE_DONE; - return node; + return node; } /* @@ -283,10 +277,9 @@ route_table_iter_next (route_table_iter_t * iter) * * Returns TRUE if the iteration is complete. */ -static inline int -route_table_iter_is_done (route_table_iter_t *iter) +static inline int route_table_iter_is_done(route_table_iter_t *iter) { - return iter->state == RT_ITER_STATE_DONE; + return iter->state == RT_ITER_STATE_DONE; } /* @@ -294,10 +287,9 @@ route_table_iter_is_done (route_table_iter_t *iter) * * Returns TRUE if this iterator has started iterating over the tree. */ -static inline int -route_table_iter_started (route_table_iter_t *iter) +static inline int route_table_iter_started(route_table_iter_t *iter) { - return iter->state != RT_ITER_STATE_INIT; + return iter->state != RT_ITER_STATE_INIT; } #endif /* _ZEBRA_TABLE_H */ diff --git a/lib/termtable.c b/lib/termtable.c index 283fa173d..f7aec4311 100644 --- a/lib/termtable.c +++ b/lib/termtable.c @@ -349,7 +349,7 @@ char *ttable_dump(struct ttable *tt, const char *newline) rsize = nl_len + (tt->style.border.right_on ? 1 : 0); right = XCALLOC(MTYPE_TTABLE, rsize); - memset (left, ' ', lsize); + memset(left, ' ', lsize); if (tt->style.border.left_on) left[lsize - 1] = tt->style.border.left; diff --git a/lib/termtable.h b/lib/termtable.h index 9ecb41659..ca5cc1df9 100644 --- a/lib/termtable.h +++ b/lib/termtable.h @@ -134,7 +134,7 @@ void ttable_cell_del(struct ttable_cell *cell); */ struct ttable_cell *ttable_insert_row(struct ttable *tt, unsigned int row, const char *format, ...) - PRINTF_ATTRIBUTE(3, 4); + PRINTF_ATTRIBUTE(3, 4); /** * Inserts a new row at the end of the table. * @@ -160,7 +160,7 @@ struct ttable_cell *ttable_insert_row(struct ttable *tt, unsigned int row, * columns were specified */ struct ttable_cell *ttable_add_row(struct ttable *tt, const char *format, ...) - PRINTF_ATTRIBUTE(2, 3); + PRINTF_ATTRIBUTE(2, 3); /** * Removes a row from the table. diff --git a/lib/thread.c b/lib/thread.c index 2c87c099d..5db470ef4 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -32,20 +32,20 @@ #include "sigevent.h" #include "network.h" -DEFINE_MTYPE_STATIC(LIB, THREAD, "Thread") +DEFINE_MTYPE_STATIC(LIB, THREAD, "Thread") DEFINE_MTYPE_STATIC(LIB, THREAD_MASTER, "Thread master") -DEFINE_MTYPE_STATIC(LIB, THREAD_STATS, "Thread stats") +DEFINE_MTYPE_STATIC(LIB, THREAD_STATS, "Thread stats") #if defined(__APPLE__) #include #include #endif -#define AWAKEN(m) \ - do { \ - static unsigned char wakebyte = 0x01; \ - write (m->io_pipe[1], &wakebyte, 1); \ - } while (0); +#define AWAKEN(m) \ + do { \ + static unsigned char wakebyte = 0x01; \ + write(m->io_pipe[1], &wakebyte, 1); \ + } while (0); /* control variable for initializer */ pthread_once_t init_once = PTHREAD_ONCE_INIT; @@ -56,204 +56,198 @@ static struct list *masters; /* CLI start ---------------------------------------------------------------- */ -static unsigned int -cpu_record_hash_key (struct cpu_thread_history *a) +static unsigned int cpu_record_hash_key(struct cpu_thread_history *a) { - return (uintptr_t) a->func; + return (uintptr_t)a->func; } -static int -cpu_record_hash_cmp (const struct cpu_thread_history *a, - const struct cpu_thread_history *b) +static int cpu_record_hash_cmp(const struct cpu_thread_history *a, + const struct cpu_thread_history *b) { - return a->func == b->func; + return a->func == b->func; } -static void * -cpu_record_hash_alloc (struct cpu_thread_history *a) +static void *cpu_record_hash_alloc(struct cpu_thread_history *a) { - struct cpu_thread_history *new; - new = XCALLOC (MTYPE_THREAD_STATS, sizeof (struct cpu_thread_history)); - new->func = a->func; - new->funcname = a->funcname; - return new; + struct cpu_thread_history *new; + new = XCALLOC(MTYPE_THREAD_STATS, sizeof(struct cpu_thread_history)); + new->func = a->func; + new->funcname = a->funcname; + return new; } -static void -cpu_record_hash_free (void *a) +static void cpu_record_hash_free(void *a) { - struct cpu_thread_history *hist = a; - - XFREE (MTYPE_THREAD_STATS, hist); + struct cpu_thread_history *hist = a; + + XFREE(MTYPE_THREAD_STATS, hist); } -static void -vty_out_cpu_thread_history(struct vty* vty, - struct cpu_thread_history *a) +static void vty_out_cpu_thread_history(struct vty *vty, + struct cpu_thread_history *a) { - vty_out(vty, "%5d %10ld.%03ld %9d %8ld %9ld %8ld %9ld", - a->total_active, a->cpu.total/1000, a->cpu.total%1000, a->total_calls, - a->cpu.total/a->total_calls, a->cpu.max, - a->real.total/a->total_calls, a->real.max); - vty_out (vty, " %c%c%c%c%c %s\n", - a->types & (1 << THREAD_READ) ? 'R':' ', - a->types & (1 << THREAD_WRITE) ? 'W':' ', - a->types & (1 << THREAD_TIMER) ? 'T':' ', - a->types & (1 << THREAD_EVENT) ? 'E':' ', - a->types & (1 << THREAD_EXECUTE) ? 'X':' ', - a->funcname); + vty_out(vty, "%5d %10ld.%03ld %9d %8ld %9ld %8ld %9ld", a->total_active, + a->cpu.total / 1000, a->cpu.total % 1000, a->total_calls, + a->cpu.total / a->total_calls, a->cpu.max, + a->real.total / a->total_calls, a->real.max); + vty_out(vty, " %c%c%c%c%c %s\n", + a->types & (1 << THREAD_READ) ? 'R' : ' ', + a->types & (1 << THREAD_WRITE) ? 'W' : ' ', + a->types & (1 << THREAD_TIMER) ? 'T' : ' ', + a->types & (1 << THREAD_EVENT) ? 'E' : ' ', + a->types & (1 << THREAD_EXECUTE) ? 'X' : ' ', a->funcname); } -static void -cpu_record_hash_print(struct hash_backet *bucket, void *args[]) +static void cpu_record_hash_print(struct hash_backet *bucket, void *args[]) { - struct cpu_thread_history *totals = args[0]; - struct vty *vty = args[1]; - thread_type *filter = args[2]; - - struct cpu_thread_history *a = bucket->data; - - if ( !(a->types & *filter) ) - return; - vty_out_cpu_thread_history(vty,a); - totals->total_active += a->total_active; - totals->total_calls += a->total_calls; - totals->real.total += a->real.total; - if (totals->real.max < a->real.max) - totals->real.max = a->real.max; - totals->cpu.total += a->cpu.total; - if (totals->cpu.max < a->cpu.max) - totals->cpu.max = a->cpu.max; + struct cpu_thread_history *totals = args[0]; + struct vty *vty = args[1]; + thread_type *filter = args[2]; + + struct cpu_thread_history *a = bucket->data; + + if (!(a->types & *filter)) + return; + vty_out_cpu_thread_history(vty, a); + totals->total_active += a->total_active; + totals->total_calls += a->total_calls; + totals->real.total += a->real.total; + if (totals->real.max < a->real.max) + totals->real.max = a->real.max; + totals->cpu.total += a->cpu.total; + if (totals->cpu.max < a->cpu.max) + totals->cpu.max = a->cpu.max; } -static void -cpu_record_print(struct vty *vty, thread_type filter) +static void cpu_record_print(struct vty *vty, thread_type filter) { - struct cpu_thread_history tmp; - void *args[3] = {&tmp, vty, &filter}; - struct thread_master *m; - struct listnode *ln; - - memset(&tmp, 0, sizeof tmp); - tmp.funcname = "TOTAL"; - tmp.types = filter; - - pthread_mutex_lock (&masters_mtx); - { - for (ALL_LIST_ELEMENTS_RO (masters, ln, m)) { - const char *name = m->name ? m->name : "main"; - - char underline[strlen(name) + 1]; - memset (underline, '-', sizeof (underline)); - underline[sizeof(underline)] = '\0'; - - vty_out (vty, "\n"); - vty_out(vty, "Showing statistics for pthread %s\n", name); - vty_out(vty, "-------------------------------%s\n", underline); - vty_out(vty, "%21s %18s %18s\n", "", "CPU (user+system):", "Real (wall-clock):"); - vty_out(vty, "Active Runtime(ms) Invoked Avg uSec Max uSecs"); - vty_out(vty, " Avg uSec Max uSecs"); - vty_out(vty, " Type Thread\n"); - - if (m->cpu_record->count) - hash_iterate(m->cpu_record, - (void (*)(struct hash_backet *, void *)) - cpu_record_hash_print, - args); - else - vty_out(vty, "No data to display yet.\n"); - - vty_out(vty, "\n"); - } - } - pthread_mutex_unlock (&masters_mtx); - - vty_out(vty, "\n"); - vty_out(vty, "Total thread statistics\n"); - vty_out(vty, "-------------------------\n"); - vty_out(vty, "%21s %18s %18s\n", "", "CPU (user+system):", "Real (wall-clock):"); - vty_out(vty, "Active Runtime(ms) Invoked Avg uSec Max uSecs"); - vty_out(vty, " Avg uSec Max uSecs"); - vty_out(vty, " Type Thread\n"); - - if (tmp.total_calls > 0) - vty_out_cpu_thread_history(vty, &tmp); + struct cpu_thread_history tmp; + void *args[3] = {&tmp, vty, &filter}; + struct thread_master *m; + struct listnode *ln; + + memset(&tmp, 0, sizeof tmp); + tmp.funcname = "TOTAL"; + tmp.types = filter; + + pthread_mutex_lock(&masters_mtx); + { + for (ALL_LIST_ELEMENTS_RO(masters, ln, m)) { + const char *name = m->name ? m->name : "main"; + + char underline[strlen(name) + 1]; + memset(underline, '-', sizeof(underline)); + underline[sizeof(underline)] = '\0'; + + vty_out(vty, "\n"); + vty_out(vty, "Showing statistics for pthread %s\n", + name); + vty_out(vty, "-------------------------------%s\n", + underline); + vty_out(vty, "%21s %18s %18s\n", "", + "CPU (user+system):", "Real (wall-clock):"); + vty_out(vty, + "Active Runtime(ms) Invoked Avg uSec Max uSecs"); + vty_out(vty, " Avg uSec Max uSecs"); + vty_out(vty, " Type Thread\n"); + + if (m->cpu_record->count) + hash_iterate( + m->cpu_record, + (void (*)(struct hash_backet *, + void *))cpu_record_hash_print, + args); + else + vty_out(vty, "No data to display yet.\n"); + + vty_out(vty, "\n"); + } + } + pthread_mutex_unlock(&masters_mtx); + + vty_out(vty, "\n"); + vty_out(vty, "Total thread statistics\n"); + vty_out(vty, "-------------------------\n"); + vty_out(vty, "%21s %18s %18s\n", "", + "CPU (user+system):", "Real (wall-clock):"); + vty_out(vty, "Active Runtime(ms) Invoked Avg uSec Max uSecs"); + vty_out(vty, " Avg uSec Max uSecs"); + vty_out(vty, " Type Thread\n"); + + if (tmp.total_calls > 0) + vty_out_cpu_thread_history(vty, &tmp); } -static void -cpu_record_hash_clear (struct hash_backet *bucket, void *args[]) +static void cpu_record_hash_clear(struct hash_backet *bucket, void *args[]) { - thread_type *filter = args[0]; - struct hash *cpu_record = args[1]; + thread_type *filter = args[0]; + struct hash *cpu_record = args[1]; + + struct cpu_thread_history *a = bucket->data; - struct cpu_thread_history *a = bucket->data; + if (!(a->types & *filter)) + return; - if ( !(a->types & *filter) ) - return; - - hash_release (cpu_record, bucket->data); + hash_release(cpu_record, bucket->data); } -static void -cpu_record_clear (thread_type filter) +static void cpu_record_clear(thread_type filter) { - thread_type *tmp = &filter; - struct thread_master *m; - struct listnode *ln; - - pthread_mutex_lock (&masters_mtx); - { - for (ALL_LIST_ELEMENTS_RO (masters, ln, m)) { - pthread_mutex_lock (&m->mtx); - { - void *args[2] = { tmp, m->cpu_record }; - hash_iterate (m->cpu_record, - (void (*) (struct hash_backet*,void*)) - cpu_record_hash_clear, - args); - } - pthread_mutex_unlock (&m->mtx); - } - } - pthread_mutex_unlock (&masters_mtx); + thread_type *tmp = &filter; + struct thread_master *m; + struct listnode *ln; + + pthread_mutex_lock(&masters_mtx); + { + for (ALL_LIST_ELEMENTS_RO(masters, ln, m)) { + pthread_mutex_lock(&m->mtx); + { + void *args[2] = {tmp, m->cpu_record}; + hash_iterate( + m->cpu_record, + (void (*)(struct hash_backet *, + void *))cpu_record_hash_clear, + args); + } + pthread_mutex_unlock(&m->mtx); + } + } + pthread_mutex_unlock(&masters_mtx); } -static thread_type -parse_filter (const char *filterstr) +static thread_type parse_filter(const char *filterstr) { - int i = 0; - int filter = 0; - - while (filterstr[i] != '\0') - { - switch (filterstr[i]) - { - case 'r': - case 'R': - filter |= (1 << THREAD_READ); - break; - case 'w': - case 'W': - filter |= (1 << THREAD_WRITE); - break; - case 't': - case 'T': - filter |= (1 << THREAD_TIMER); - break; - case 'e': - case 'E': - filter |= (1 << THREAD_EVENT); - break; - case 'x': - case 'X': - filter |= (1 << THREAD_EXECUTE); - break; - default: - break; - } - ++i; - } - return filter; + int i = 0; + int filter = 0; + + while (filterstr[i] != '\0') { + switch (filterstr[i]) { + case 'r': + case 'R': + filter |= (1 << THREAD_READ); + break; + case 'w': + case 'W': + filter |= (1 << THREAD_WRITE); + break; + case 't': + case 'T': + filter |= (1 << THREAD_TIMER); + break; + case 'e': + case 'E': + filter |= (1 << THREAD_EVENT); + break; + case 'x': + case 'X': + filter |= (1 << THREAD_EXECUTE); + break; + default: + break; + } + ++i; + } + return filter; } DEFUN (show_thread_cpu, @@ -264,20 +258,22 @@ DEFUN (show_thread_cpu, "Thread CPU usage\n" "Display filter (rwtexb)\n") { - thread_type filter = (thread_type) -1U; - int idx = 0; - - if (argv_find (argv, argc, "FILTER", &idx)) { - filter = parse_filter (argv[idx]->arg); - if (!filter) { - vty_out(vty, "Invalid filter \"%s\" specified; must contain at least" - "one of 'RWTEXB'\n", argv[idx]->arg); - return CMD_WARNING; - } - } - - cpu_record_print(vty, filter); - return CMD_SUCCESS; + thread_type filter = (thread_type)-1U; + int idx = 0; + + if (argv_find(argv, argc, "FILTER", &idx)) { + filter = parse_filter(argv[idx]->arg); + if (!filter) { + vty_out(vty, + "Invalid filter \"%s\" specified; must contain at least" + "one of 'RWTEXB'\n", + argv[idx]->arg); + return CMD_WARNING; + } + } + + cpu_record_print(vty, filter); + return CMD_SUCCESS; } DEFUN (clear_thread_cpu, @@ -288,253 +284,241 @@ DEFUN (clear_thread_cpu, "Thread CPU usage\n" "Display filter (rwtexb)\n") { - thread_type filter = (thread_type) -1U; - int idx = 0; - - if (argv_find (argv, argc, "FILTER", &idx)) { - filter = parse_filter (argv[idx]->arg); - if (!filter) { - vty_out(vty, "Invalid filter \"%s\" specified; must contain at least" - "one of 'RWTEXB'\n", argv[idx]->arg); - return CMD_WARNING; - } - } - - cpu_record_clear (filter); - return CMD_SUCCESS; + thread_type filter = (thread_type)-1U; + int idx = 0; + + if (argv_find(argv, argc, "FILTER", &idx)) { + filter = parse_filter(argv[idx]->arg); + if (!filter) { + vty_out(vty, + "Invalid filter \"%s\" specified; must contain at least" + "one of 'RWTEXB'\n", + argv[idx]->arg); + return CMD_WARNING; + } + } + + cpu_record_clear(filter); + return CMD_SUCCESS; } -void -thread_cmd_init (void) +void thread_cmd_init(void) { - install_element (VIEW_NODE, &show_thread_cpu_cmd); - install_element (ENABLE_NODE, &clear_thread_cpu_cmd); + install_element(VIEW_NODE, &show_thread_cpu_cmd); + install_element(ENABLE_NODE, &clear_thread_cpu_cmd); } /* CLI end ------------------------------------------------------------------ */ -static int -thread_timer_cmp(void *a, void *b) +static int thread_timer_cmp(void *a, void *b) { - struct thread *thread_a = a; - struct thread *thread_b = b; - - if (timercmp (&thread_a->u.sands, &thread_b->u.sands, <)) - return -1; - if (timercmp (&thread_a->u.sands, &thread_b->u.sands, >)) - return 1; - return 0; + struct thread *thread_a = a; + struct thread *thread_b = b; + + if (timercmp(&thread_a->u.sands, &thread_b->u.sands, <)) + return -1; + if (timercmp(&thread_a->u.sands, &thread_b->u.sands, >)) + return 1; + return 0; } -static void -thread_timer_update(void *node, int actual_position) +static void thread_timer_update(void *node, int actual_position) { - struct thread *thread = node; + struct thread *thread = node; - thread->index = actual_position; + thread->index = actual_position; } -static void -cancelreq_del (void *cr) +static void cancelreq_del(void *cr) { - XFREE (MTYPE_TMP, cr); + XFREE(MTYPE_TMP, cr); } /* initializer, only ever called once */ -static void initializer () +static void initializer() { - if (!masters) - masters = list_new(); + if (!masters) + masters = list_new(); - pthread_key_create (&thread_current, NULL); + pthread_key_create(&thread_current, NULL); } /* Allocate new thread master. */ -struct thread_master * -thread_master_create (const char *name) +struct thread_master *thread_master_create(const char *name) { - struct thread_master *rv; - struct rlimit limit; - - pthread_once (&init_once, &initializer); - - rv = XCALLOC (MTYPE_THREAD_MASTER, sizeof (struct thread_master)); - if (rv == NULL) - return NULL; - - /* Initialize master mutex */ - pthread_mutex_init (&rv->mtx, NULL); - pthread_cond_init (&rv->cancel_cond, NULL); - - /* Set name */ - rv->name = name ? XSTRDUP (MTYPE_THREAD_MASTER, name) : NULL; - - /* Initialize I/O task data structures */ - getrlimit(RLIMIT_NOFILE, &limit); - rv->fd_limit = (int)limit.rlim_cur; - rv->read = XCALLOC (MTYPE_THREAD, sizeof (struct thread *) * rv->fd_limit); - if (rv->read == NULL) - { - XFREE (MTYPE_THREAD_MASTER, rv); - return NULL; - } - rv->write = XCALLOC (MTYPE_THREAD, sizeof (struct thread *) * rv->fd_limit); - if (rv->write == NULL) - { - XFREE (MTYPE_THREAD, rv->read); - XFREE (MTYPE_THREAD_MASTER, rv); - return NULL; - } - - rv->cpu_record = hash_create ((unsigned int (*) (void *))cpu_record_hash_key, - (int (*) (const void *, const void *)) - cpu_record_hash_cmp, NULL); - - - /* Initialize the timer queues */ - rv->timer = pqueue_create(); - rv->timer->cmp = thread_timer_cmp; - rv->timer->update = thread_timer_update; - - /* Initialize thread_fetch() settings */ - rv->spin = true; - rv->handle_signals = true; - - /* Set pthread owner, should be updated by actual owner */ - rv->owner = pthread_self(); - rv->cancel_req = list_new (); - rv->cancel_req->del = cancelreq_del; - rv->canceled = true; - - /* Initialize pipe poker */ - pipe (rv->io_pipe); - set_nonblocking (rv->io_pipe[0]); - set_nonblocking (rv->io_pipe[1]); - - /* Initialize data structures for poll() */ - rv->handler.pfdsize = rv->fd_limit; - rv->handler.pfdcount = 0; - rv->handler.pfds = XCALLOC (MTYPE_THREAD_MASTER, - sizeof (struct pollfd) * rv->handler.pfdsize); - rv->handler.copy = XCALLOC (MTYPE_THREAD_MASTER, - sizeof (struct pollfd) * rv->handler.pfdsize); - - /* add to list */ - pthread_mutex_lock (&masters_mtx); - { - listnode_add (masters, rv); - } - pthread_mutex_unlock (&masters_mtx); - - return rv; + struct thread_master *rv; + struct rlimit limit; + + pthread_once(&init_once, &initializer); + + rv = XCALLOC(MTYPE_THREAD_MASTER, sizeof(struct thread_master)); + if (rv == NULL) + return NULL; + + /* Initialize master mutex */ + pthread_mutex_init(&rv->mtx, NULL); + pthread_cond_init(&rv->cancel_cond, NULL); + + /* Set name */ + rv->name = name ? XSTRDUP(MTYPE_THREAD_MASTER, name) : NULL; + + /* Initialize I/O task data structures */ + getrlimit(RLIMIT_NOFILE, &limit); + rv->fd_limit = (int)limit.rlim_cur; + rv->read = + XCALLOC(MTYPE_THREAD, sizeof(struct thread *) * rv->fd_limit); + if (rv->read == NULL) { + XFREE(MTYPE_THREAD_MASTER, rv); + return NULL; + } + rv->write = + XCALLOC(MTYPE_THREAD, sizeof(struct thread *) * rv->fd_limit); + if (rv->write == NULL) { + XFREE(MTYPE_THREAD, rv->read); + XFREE(MTYPE_THREAD_MASTER, rv); + return NULL; + } + + rv->cpu_record = hash_create( + (unsigned int (*)(void *))cpu_record_hash_key, + (int (*)(const void *, const void *))cpu_record_hash_cmp, NULL); + + + /* Initialize the timer queues */ + rv->timer = pqueue_create(); + rv->timer->cmp = thread_timer_cmp; + rv->timer->update = thread_timer_update; + + /* Initialize thread_fetch() settings */ + rv->spin = true; + rv->handle_signals = true; + + /* Set pthread owner, should be updated by actual owner */ + rv->owner = pthread_self(); + rv->cancel_req = list_new(); + rv->cancel_req->del = cancelreq_del; + rv->canceled = true; + + /* Initialize pipe poker */ + pipe(rv->io_pipe); + set_nonblocking(rv->io_pipe[0]); + set_nonblocking(rv->io_pipe[1]); + + /* Initialize data structures for poll() */ + rv->handler.pfdsize = rv->fd_limit; + rv->handler.pfdcount = 0; + rv->handler.pfds = XCALLOC(MTYPE_THREAD_MASTER, + sizeof(struct pollfd) * rv->handler.pfdsize); + rv->handler.copy = XCALLOC(MTYPE_THREAD_MASTER, + sizeof(struct pollfd) * rv->handler.pfdsize); + + /* add to list */ + pthread_mutex_lock(&masters_mtx); + { + listnode_add(masters, rv); + } + pthread_mutex_unlock(&masters_mtx); + + return rv; } /* Add a new thread to the list. */ -static void -thread_list_add (struct thread_list *list, struct thread *thread) +static void thread_list_add(struct thread_list *list, struct thread *thread) { - thread->next = NULL; - thread->prev = list->tail; - if (list->tail) - list->tail->next = thread; - else - list->head = thread; - list->tail = thread; - list->count++; + thread->next = NULL; + thread->prev = list->tail; + if (list->tail) + list->tail->next = thread; + else + list->head = thread; + list->tail = thread; + list->count++; } /* Delete a thread from the list. */ -static struct thread * -thread_list_delete (struct thread_list *list, struct thread *thread) +static struct thread *thread_list_delete(struct thread_list *list, + struct thread *thread) { - if (thread->next) - thread->next->prev = thread->prev; - else - list->tail = thread->prev; - if (thread->prev) - thread->prev->next = thread->next; - else - list->head = thread->next; - thread->next = thread->prev = NULL; - list->count--; - return thread; + if (thread->next) + thread->next->prev = thread->prev; + else + list->tail = thread->prev; + if (thread->prev) + thread->prev->next = thread->next; + else + list->head = thread->next; + thread->next = thread->prev = NULL; + list->count--; + return thread; } /* Thread list is empty or not. */ -static int -thread_empty (struct thread_list *list) +static int thread_empty(struct thread_list *list) { - return list->head ? 0 : 1; + return list->head ? 0 : 1; } /* Delete top of the list and return it. */ -static struct thread * -thread_trim_head (struct thread_list *list) +static struct thread *thread_trim_head(struct thread_list *list) { - if (!thread_empty (list)) - return thread_list_delete (list, list->head); - return NULL; + if (!thread_empty(list)) + return thread_list_delete(list, list->head); + return NULL; } /* Move thread to unuse list. */ -static void -thread_add_unuse (struct thread_master *m, struct thread *thread) +static void thread_add_unuse(struct thread_master *m, struct thread *thread) { - assert (m != NULL && thread != NULL); - assert (thread->next == NULL); - assert (thread->prev == NULL); - thread->ref = NULL; - - thread->type = THREAD_UNUSED; - thread->hist->total_active--; - thread_list_add (&m->unuse, thread); + assert(m != NULL && thread != NULL); + assert(thread->next == NULL); + assert(thread->prev == NULL); + thread->ref = NULL; + + thread->type = THREAD_UNUSED; + thread->hist->total_active--; + thread_list_add(&m->unuse, thread); } /* Free all unused thread. */ -static void -thread_list_free (struct thread_master *m, struct thread_list *list) +static void thread_list_free(struct thread_master *m, struct thread_list *list) { - struct thread *t; - struct thread *next; - - for (t = list->head; t; t = next) - { - next = t->next; - XFREE (MTYPE_THREAD, t); - list->count--; - m->alloc--; - } + struct thread *t; + struct thread *next; + + for (t = list->head; t; t = next) { + next = t->next; + XFREE(MTYPE_THREAD, t); + list->count--; + m->alloc--; + } } -static void -thread_array_free (struct thread_master *m, struct thread **thread_array) +static void thread_array_free(struct thread_master *m, + struct thread **thread_array) { - struct thread *t; - int index; - - for (index = 0; index < m->fd_limit; ++index) - { - t = thread_array[index]; - if (t) - { - thread_array[index] = NULL; - XFREE (MTYPE_THREAD, t); - m->alloc--; - } - } - XFREE (MTYPE_THREAD, thread_array); + struct thread *t; + int index; + + for (index = 0; index < m->fd_limit; ++index) { + t = thread_array[index]; + if (t) { + thread_array[index] = NULL; + XFREE(MTYPE_THREAD, t); + m->alloc--; + } + } + XFREE(MTYPE_THREAD, thread_array); } -static void -thread_queue_free (struct thread_master *m, struct pqueue *queue) +static void thread_queue_free(struct thread_master *m, struct pqueue *queue) { - int i; + int i; - for (i = 0; i < queue->size; i++) - XFREE(MTYPE_THREAD, queue->array[i]); + for (i = 0; i < queue->size; i++) + XFREE(MTYPE_THREAD, queue->array[i]); - m->alloc -= queue->size; - pqueue_delete(queue); + m->alloc -= queue->size; + pqueue_delete(queue); } /* @@ -545,359 +529,364 @@ thread_queue_free (struct thread_master *m, struct pqueue *queue) * If we are shutting down, Free up unused threads * So we can see if we forget to shut anything off */ -void -thread_master_free_unused (struct thread_master *m) +void thread_master_free_unused(struct thread_master *m) { - pthread_mutex_lock (&m->mtx); - { - struct thread *t; - while ((t = thread_trim_head(&m->unuse)) != NULL) - { - pthread_mutex_destroy (&t->mtx); - XFREE(MTYPE_THREAD, t); - } - } - pthread_mutex_unlock (&m->mtx); + pthread_mutex_lock(&m->mtx); + { + struct thread *t; + while ((t = thread_trim_head(&m->unuse)) != NULL) { + pthread_mutex_destroy(&t->mtx); + XFREE(MTYPE_THREAD, t); + } + } + pthread_mutex_unlock(&m->mtx); } /* Stop thread scheduler. */ -void -thread_master_free (struct thread_master *m) +void thread_master_free(struct thread_master *m) { - pthread_mutex_lock (&masters_mtx); - { - listnode_delete (masters, m); - } - pthread_mutex_unlock (&masters_mtx); - - thread_array_free (m, m->read); - thread_array_free (m, m->write); - thread_queue_free (m, m->timer); - thread_list_free (m, &m->event); - thread_list_free (m, &m->ready); - thread_list_free (m, &m->unuse); - pthread_mutex_destroy (&m->mtx); - close (m->io_pipe[0]); - close (m->io_pipe[1]); - list_delete (m->cancel_req); - - hash_clean (m->cpu_record, cpu_record_hash_free); - hash_free (m->cpu_record); - m->cpu_record = NULL; - - XFREE (MTYPE_THREAD_MASTER, m->handler.pfds); - XFREE (MTYPE_THREAD_MASTER, m->handler.copy); - XFREE (MTYPE_THREAD_MASTER, m); + pthread_mutex_lock(&masters_mtx); + { + listnode_delete(masters, m); + } + pthread_mutex_unlock(&masters_mtx); + + thread_array_free(m, m->read); + thread_array_free(m, m->write); + thread_queue_free(m, m->timer); + thread_list_free(m, &m->event); + thread_list_free(m, &m->ready); + thread_list_free(m, &m->unuse); + pthread_mutex_destroy(&m->mtx); + close(m->io_pipe[0]); + close(m->io_pipe[1]); + list_delete(m->cancel_req); + + hash_clean(m->cpu_record, cpu_record_hash_free); + hash_free(m->cpu_record); + m->cpu_record = NULL; + + XFREE(MTYPE_THREAD_MASTER, m->handler.pfds); + XFREE(MTYPE_THREAD_MASTER, m->handler.copy); + XFREE(MTYPE_THREAD_MASTER, m); } /* Return remain time in second. */ -unsigned long -thread_timer_remain_second (struct thread *thread) +unsigned long thread_timer_remain_second(struct thread *thread) { - int64_t remain; + int64_t remain; - pthread_mutex_lock (&thread->mtx); - { - remain = monotime_until(&thread->u.sands, NULL) / 1000000LL; - } - pthread_mutex_unlock (&thread->mtx); + pthread_mutex_lock(&thread->mtx); + { + remain = monotime_until(&thread->u.sands, NULL) / 1000000LL; + } + pthread_mutex_unlock(&thread->mtx); - return remain < 0 ? 0 : remain; + return remain < 0 ? 0 : remain; } #define debugargdef const char *funcname, const char *schedfrom, int fromln #define debugargpass funcname, schedfrom, fromln -struct timeval -thread_timer_remain(struct thread *thread) +struct timeval thread_timer_remain(struct thread *thread) { - struct timeval remain; - pthread_mutex_lock (&thread->mtx); - { - monotime_until(&thread->u.sands, &remain); - } - pthread_mutex_unlock (&thread->mtx); - return remain; + struct timeval remain; + pthread_mutex_lock(&thread->mtx); + { + monotime_until(&thread->u.sands, &remain); + } + pthread_mutex_unlock(&thread->mtx); + return remain; } /* Get new thread. */ -static struct thread * -thread_get (struct thread_master *m, u_char type, - int (*func) (struct thread *), void *arg, debugargdef) +static struct thread *thread_get(struct thread_master *m, u_char type, + int (*func)(struct thread *), void *arg, + debugargdef) { - struct thread *thread = thread_trim_head (&m->unuse); - struct cpu_thread_history tmp; - - if (! thread) - { - thread = XCALLOC (MTYPE_THREAD, sizeof (struct thread)); - /* mutex only needs to be initialized at struct creation. */ - pthread_mutex_init (&thread->mtx, NULL); - m->alloc++; - } - - thread->type = type; - thread->add_type = type; - thread->master = m; - thread->arg = arg; - thread->index = -1; - thread->yield = THREAD_YIELD_TIME_SLOT; /* default */ - thread->ref = NULL; - - /* - * So if the passed in funcname is not what we have - * stored that means the thread->hist needs to be - * updated. We keep the last one around in unused - * under the assumption that we are probably - * going to immediately allocate the same - * type of thread. - * This hopefully saves us some serious - * hash_get lookups. - */ - if (thread->funcname != funcname || - thread->func != func) - { - tmp.func = func; - tmp.funcname = funcname; - thread->hist = hash_get (m->cpu_record, &tmp, - (void * (*) (void *))cpu_record_hash_alloc); - } - thread->hist->total_active++; - thread->func = func; - thread->funcname = funcname; - thread->schedfrom = schedfrom; - thread->schedfrom_line = fromln; - - return thread; + struct thread *thread = thread_trim_head(&m->unuse); + struct cpu_thread_history tmp; + + if (!thread) { + thread = XCALLOC(MTYPE_THREAD, sizeof(struct thread)); + /* mutex only needs to be initialized at struct creation. */ + pthread_mutex_init(&thread->mtx, NULL); + m->alloc++; + } + + thread->type = type; + thread->add_type = type; + thread->master = m; + thread->arg = arg; + thread->index = -1; + thread->yield = THREAD_YIELD_TIME_SLOT; /* default */ + thread->ref = NULL; + + /* + * So if the passed in funcname is not what we have + * stored that means the thread->hist needs to be + * updated. We keep the last one around in unused + * under the assumption that we are probably + * going to immediately allocate the same + * type of thread. + * This hopefully saves us some serious + * hash_get lookups. + */ + if (thread->funcname != funcname || thread->func != func) { + tmp.func = func; + tmp.funcname = funcname; + thread->hist = + hash_get(m->cpu_record, &tmp, + (void *(*)(void *))cpu_record_hash_alloc); + } + thread->hist->total_active++; + thread->func = func; + thread->funcname = funcname; + thread->schedfrom = schedfrom; + thread->schedfrom_line = fromln; + + return thread; } -static int -fd_poll (struct thread_master *m, struct pollfd *pfds, nfds_t pfdsize, - nfds_t count, const struct timeval *timer_wait) +static int fd_poll(struct thread_master *m, struct pollfd *pfds, nfds_t pfdsize, + nfds_t count, const struct timeval *timer_wait) { - /* If timer_wait is null here, that means poll() should block indefinitely, - * unless the thread_master has overriden it by setting ->selectpoll_timeout. - * If the value is positive, it specifies the maximum number of milliseconds - * to wait. If the timeout is -1, it specifies that we should never wait and - * always return immediately even if no event is detected. If the value is - * zero, the behavior is default. */ - int timeout = -1; - - /* number of file descriptors with events */ - int num; - - if (timer_wait != NULL && m->selectpoll_timeout == 0) // use the default value - timeout = (timer_wait->tv_sec*1000) + (timer_wait->tv_usec/1000); - else if (m->selectpoll_timeout > 0) // use the user's timeout - timeout = m->selectpoll_timeout; - else if (m->selectpoll_timeout < 0) // effect a poll (return immediately) - timeout = 0; - - /* add poll pipe poker */ - assert (count + 1 < pfdsize); - pfds[count].fd = m->io_pipe[0]; - pfds[count].events = POLLIN; - pfds[count].revents = 0x00; - - num = poll (pfds, count + 1, timeout); - - unsigned char trash[64]; - if (num > 0 && pfds[count].revents != 0 && num--) - while (read (m->io_pipe[0], &trash, sizeof (trash)) > 0); - - return num; + /* If timer_wait is null here, that means poll() should block + * indefinitely, + * unless the thread_master has overriden it by setting + * ->selectpoll_timeout. + * If the value is positive, it specifies the maximum number of + * milliseconds + * to wait. If the timeout is -1, it specifies that we should never wait + * and + * always return immediately even if no event is detected. If the value + * is + * zero, the behavior is default. */ + int timeout = -1; + + /* number of file descriptors with events */ + int num; + + if (timer_wait != NULL + && m->selectpoll_timeout == 0) // use the default value + timeout = (timer_wait->tv_sec * 1000) + + (timer_wait->tv_usec / 1000); + else if (m->selectpoll_timeout > 0) // use the user's timeout + timeout = m->selectpoll_timeout; + else if (m->selectpoll_timeout + < 0) // effect a poll (return immediately) + timeout = 0; + + /* add poll pipe poker */ + assert(count + 1 < pfdsize); + pfds[count].fd = m->io_pipe[0]; + pfds[count].events = POLLIN; + pfds[count].revents = 0x00; + + num = poll(pfds, count + 1, timeout); + + unsigned char trash[64]; + if (num > 0 && pfds[count].revents != 0 && num--) + while (read(m->io_pipe[0], &trash, sizeof(trash)) > 0) + ; + + return num; } /* Add new read thread. */ -struct thread * -funcname_thread_add_read_write (int dir, struct thread_master *m, - int (*func) (struct thread *), void *arg, int fd, struct thread **t_ptr, - debugargdef) +struct thread *funcname_thread_add_read_write(int dir, struct thread_master *m, + int (*func)(struct thread *), + void *arg, int fd, + struct thread **t_ptr, + debugargdef) { - struct thread *thread = NULL; - - pthread_mutex_lock (&m->mtx); - { - if (t_ptr && *t_ptr) // thread is already scheduled; don't reschedule - { - pthread_mutex_unlock (&m->mtx); - return NULL; - } - - /* default to a new pollfd */ - nfds_t queuepos = m->handler.pfdcount; - - /* if we already have a pollfd for our file descriptor, find and use it */ - for (nfds_t i = 0; i < m->handler.pfdcount; i++) - if (m->handler.pfds[i].fd == fd) - { - queuepos = i; - break; - } - - /* make sure we have room for this fd + pipe poker fd */ - assert (queuepos + 1 < m->handler.pfdsize); - - thread = thread_get (m, dir, func, arg, debugargpass); - - m->handler.pfds[queuepos].fd = fd; - m->handler.pfds[queuepos].events |= (dir == THREAD_READ ? POLLIN : POLLOUT); - - if (queuepos == m->handler.pfdcount) - m->handler.pfdcount++; - - if (thread) - { - pthread_mutex_lock (&thread->mtx); - { - thread->u.fd = fd; - if (dir == THREAD_READ) - m->read[thread->u.fd] = thread; - else - m->write[thread->u.fd] = thread; - } - pthread_mutex_unlock (&thread->mtx); - - if (t_ptr) - { - *t_ptr = thread; - thread->ref = t_ptr; - } - } - - AWAKEN (m); - } - pthread_mutex_unlock (&m->mtx); - - return thread; + struct thread *thread = NULL; + + pthread_mutex_lock(&m->mtx); + { + if (t_ptr + && *t_ptr) // thread is already scheduled; don't reschedule + { + pthread_mutex_unlock(&m->mtx); + return NULL; + } + + /* default to a new pollfd */ + nfds_t queuepos = m->handler.pfdcount; + + /* if we already have a pollfd for our file descriptor, find and + * use it */ + for (nfds_t i = 0; i < m->handler.pfdcount; i++) + if (m->handler.pfds[i].fd == fd) { + queuepos = i; + break; + } + + /* make sure we have room for this fd + pipe poker fd */ + assert(queuepos + 1 < m->handler.pfdsize); + + thread = thread_get(m, dir, func, arg, debugargpass); + + m->handler.pfds[queuepos].fd = fd; + m->handler.pfds[queuepos].events |= + (dir == THREAD_READ ? POLLIN : POLLOUT); + + if (queuepos == m->handler.pfdcount) + m->handler.pfdcount++; + + if (thread) { + pthread_mutex_lock(&thread->mtx); + { + thread->u.fd = fd; + if (dir == THREAD_READ) + m->read[thread->u.fd] = thread; + else + m->write[thread->u.fd] = thread; + } + pthread_mutex_unlock(&thread->mtx); + + if (t_ptr) { + *t_ptr = thread; + thread->ref = t_ptr; + } + } + + AWAKEN(m); + } + pthread_mutex_unlock(&m->mtx); + + return thread; } static struct thread * -funcname_thread_add_timer_timeval (struct thread_master *m, - int (*func) (struct thread *), int type, void *arg, - struct timeval *time_relative, struct thread **t_ptr, debugargdef) +funcname_thread_add_timer_timeval(struct thread_master *m, + int (*func)(struct thread *), int type, + void *arg, struct timeval *time_relative, + struct thread **t_ptr, debugargdef) { - struct thread *thread; - struct pqueue *queue; - - assert (m != NULL); - - assert (type == THREAD_TIMER); - assert (time_relative); - - pthread_mutex_lock (&m->mtx); - { - if (t_ptr && *t_ptr) // thread is already scheduled; don't reschedule - { - pthread_mutex_unlock (&m->mtx); - return NULL; - } - - queue = m->timer; - thread = thread_get (m, type, func, arg, debugargpass); - - pthread_mutex_lock (&thread->mtx); - { - monotime(&thread->u.sands); - timeradd(&thread->u.sands, time_relative, &thread->u.sands); - pqueue_enqueue(thread, queue); - if (t_ptr) - { - *t_ptr = thread; - thread->ref = t_ptr; - } - } - pthread_mutex_unlock (&thread->mtx); - - AWAKEN (m); - } - pthread_mutex_unlock (&m->mtx); - - return thread; + struct thread *thread; + struct pqueue *queue; + + assert(m != NULL); + + assert(type == THREAD_TIMER); + assert(time_relative); + + pthread_mutex_lock(&m->mtx); + { + if (t_ptr + && *t_ptr) // thread is already scheduled; don't reschedule + { + pthread_mutex_unlock(&m->mtx); + return NULL; + } + + queue = m->timer; + thread = thread_get(m, type, func, arg, debugargpass); + + pthread_mutex_lock(&thread->mtx); + { + monotime(&thread->u.sands); + timeradd(&thread->u.sands, time_relative, + &thread->u.sands); + pqueue_enqueue(thread, queue); + if (t_ptr) { + *t_ptr = thread; + thread->ref = t_ptr; + } + } + pthread_mutex_unlock(&thread->mtx); + + AWAKEN(m); + } + pthread_mutex_unlock(&m->mtx); + + return thread; } /* Add timer event thread. */ -struct thread * -funcname_thread_add_timer (struct thread_master *m, - int (*func) (struct thread *), void *arg, long timer, - struct thread **t_ptr, debugargdef) +struct thread *funcname_thread_add_timer(struct thread_master *m, + int (*func)(struct thread *), + void *arg, long timer, + struct thread **t_ptr, debugargdef) { - struct timeval trel; + struct timeval trel; - assert (m != NULL); + assert(m != NULL); - trel.tv_sec = timer; - trel.tv_usec = 0; + trel.tv_sec = timer; + trel.tv_usec = 0; - return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, &trel, - t_ptr, debugargpass); + return funcname_thread_add_timer_timeval(m, func, THREAD_TIMER, arg, + &trel, t_ptr, debugargpass); } /* Add timer event thread with "millisecond" resolution */ -struct thread * -funcname_thread_add_timer_msec (struct thread_master *m, - int (*func) (struct thread *), void *arg, long timer, - struct thread **t_ptr, debugargdef) +struct thread *funcname_thread_add_timer_msec(struct thread_master *m, + int (*func)(struct thread *), + void *arg, long timer, + struct thread **t_ptr, + debugargdef) { - struct timeval trel; + struct timeval trel; - assert (m != NULL); + assert(m != NULL); - trel.tv_sec = timer / 1000; - trel.tv_usec = 1000*(timer % 1000); + trel.tv_sec = timer / 1000; + trel.tv_usec = 1000 * (timer % 1000); - return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, &trel, - t_ptr, debugargpass); + return funcname_thread_add_timer_timeval(m, func, THREAD_TIMER, arg, + &trel, t_ptr, debugargpass); } /* Add timer event thread with "millisecond" resolution */ -struct thread * -funcname_thread_add_timer_tv (struct thread_master *m, - int (*func) (struct thread *), void *arg, struct timeval *tv, - struct thread **t_ptr, debugargdef) +struct thread *funcname_thread_add_timer_tv(struct thread_master *m, + int (*func)(struct thread *), + void *arg, struct timeval *tv, + struct thread **t_ptr, debugargdef) { - return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, tv, - t_ptr, debugargpass); + return funcname_thread_add_timer_timeval(m, func, THREAD_TIMER, arg, tv, + t_ptr, debugargpass); } /* Add simple event thread. */ -struct thread * -funcname_thread_add_event (struct thread_master *m, - int (*func) (struct thread *), void *arg, int val, - struct thread **t_ptr, debugargdef) +struct thread *funcname_thread_add_event(struct thread_master *m, + int (*func)(struct thread *), + void *arg, int val, + struct thread **t_ptr, debugargdef) { - struct thread *thread; - - assert (m != NULL); - - pthread_mutex_lock (&m->mtx); - { - if (t_ptr && *t_ptr) // thread is already scheduled; don't reschedule - { - pthread_mutex_unlock (&m->mtx); - return NULL; - } - - thread = thread_get (m, THREAD_EVENT, func, arg, debugargpass); - pthread_mutex_lock (&thread->mtx); - { - thread->u.val = val; - thread_list_add (&m->event, thread); - } - pthread_mutex_unlock (&thread->mtx); - - if (t_ptr) - { - *t_ptr = thread; - thread->ref = t_ptr; - } - - AWAKEN (m); - } - pthread_mutex_unlock (&m->mtx); - - return thread; + struct thread *thread; + + assert(m != NULL); + + pthread_mutex_lock(&m->mtx); + { + if (t_ptr + && *t_ptr) // thread is already scheduled; don't reschedule + { + pthread_mutex_unlock(&m->mtx); + return NULL; + } + + thread = thread_get(m, THREAD_EVENT, func, arg, debugargpass); + pthread_mutex_lock(&thread->mtx); + { + thread->u.val = val; + thread_list_add(&m->event, thread); + } + pthread_mutex_unlock(&thread->mtx); + + if (t_ptr) { + *t_ptr = thread; + thread->ref = t_ptr; + } + + AWAKEN(m); + } + pthread_mutex_unlock(&m->mtx); + + return thread; } /* Thread cancellation ------------------------------------------------------ */ @@ -916,43 +905,42 @@ funcname_thread_add_event (struct thread_master *m, * - POLLIN * - POLLOUT */ -static void -thread_cancel_rw (struct thread_master *master, int fd, short state) +static void thread_cancel_rw(struct thread_master *master, int fd, short state) { - /* Cancel POLLHUP too just in case some bozo set it */ - state |= POLLHUP; - - /* find the index of corresponding pollfd */ - nfds_t i; - - for (i = 0; i < master->handler.pfdcount; i++) - if (master->handler.pfds[i].fd == fd) - break; - - /* NOT out event. */ - master->handler.pfds[i].events &= ~(state); - - /* If all events are canceled, delete / resize the pollfd array. */ - if (master->handler.pfds[i].events == 0) - { - memmove(master->handler.pfds + i, master->handler.pfds + i + 1, - (master->handler.pfdcount - i - 1) * sizeof (struct pollfd)); - master->handler.pfdcount--; - } - - /* If we have the same pollfd in the copy, perform the same operations, - * otherwise return. */ - if (i >= master->handler.copycount) - return; - - master->handler.copy[i].events &= ~(state); - - if (master->handler.copy[i].events == 0) - { - memmove(master->handler.copy + i, master->handler.copy + i + 1, - (master->handler.copycount - i - 1) * sizeof (struct pollfd)); - master->handler.copycount--; - } + /* Cancel POLLHUP too just in case some bozo set it */ + state |= POLLHUP; + + /* find the index of corresponding pollfd */ + nfds_t i; + + for (i = 0; i < master->handler.pfdcount; i++) + if (master->handler.pfds[i].fd == fd) + break; + + /* NOT out event. */ + master->handler.pfds[i].events &= ~(state); + + /* If all events are canceled, delete / resize the pollfd array. */ + if (master->handler.pfds[i].events == 0) { + memmove(master->handler.pfds + i, master->handler.pfds + i + 1, + (master->handler.pfdcount - i - 1) + * sizeof(struct pollfd)); + master->handler.pfdcount--; + } + + /* If we have the same pollfd in the copy, perform the same operations, + * otherwise return. */ + if (i >= master->handler.copycount) + return; + + master->handler.copy[i].events &= ~(state); + + if (master->handler.copy[i].events == 0) { + memmove(master->handler.copy + i, master->handler.copy + i + 1, + (master->handler.copycount - i - 1) + * sizeof(struct pollfd)); + master->handler.copycount--; + } } /** @@ -963,120 +951,109 @@ thread_cancel_rw (struct thread_master *master, int fd, short state) * @param master the thread master to process * @REQUIRE master->mtx */ -static void -do_thread_cancel (struct thread_master *master) +static void do_thread_cancel(struct thread_master *master) { - struct thread_list *list = NULL; - struct pqueue *queue = NULL; - struct thread **thread_array = NULL; - struct thread *thread; - - struct cancel_req *cr; - struct listnode *ln; - for (ALL_LIST_ELEMENTS_RO (master->cancel_req, ln, cr)) - { - /* If this is an event object cancellation, linear search through event - * list deleting any events which have the specified argument. We also - * need to check every thread in the ready queue. */ - if (cr->eventobj) - { - struct thread *t; - thread = master->event.head; - - while (thread) - { - t = thread; - thread = t->next; - - if (t->arg == cr->eventobj) - { - thread_list_delete (&master->event, t); - if (t->ref) - *t->ref = NULL; - thread_add_unuse (master, t); - } - } - - thread = master->ready.head; - while (thread) - { - t = thread; - thread = t->next; - - if (t->arg == cr->eventobj) - { - thread_list_delete (&master->ready, t); - if (t->ref) - *t->ref = NULL; - thread_add_unuse (master, t); - } - } - continue; - } - - /* The pointer varies depending on whether the cancellation request was - * made asynchronously or not. If it was, we need to check whether the - * thread even exists anymore before cancelling it. */ - thread = (cr->thread) ? cr->thread : *cr->threadref; - - if (!thread) - continue; - - /* Determine the appropriate queue to cancel the thread from */ - switch (thread->type) - { - case THREAD_READ: - thread_cancel_rw (master, thread->u.fd, POLLIN); - thread_array = master->read; - break; - case THREAD_WRITE: - thread_cancel_rw (master, thread->u.fd, POLLOUT); - thread_array = master->write; - break; - case THREAD_TIMER: - queue = master->timer; - break; - case THREAD_EVENT: - list = &master->event; - break; - case THREAD_READY: - list = &master->ready; - break; - default: - continue; - break; - } - - if (queue) - { - assert(thread->index >= 0); - pqueue_remove (thread, queue); - } - else if (list) - { - thread_list_delete (list, thread); - } - else if (thread_array) - { - thread_array[thread->u.fd] = NULL; - } - else - { - assert(!"Thread should be either in queue or list or array!"); - } - - if (thread->ref) - *thread->ref = NULL; - - thread_add_unuse (thread->master, thread); - } - - /* Delete and free all cancellation requests */ - list_delete_all_node (master->cancel_req); - - /* Wake up any threads which may be blocked in thread_cancel_async() */ - master->canceled = true; - pthread_cond_broadcast (&master->cancel_cond); + struct thread_list *list = NULL; + struct pqueue *queue = NULL; + struct thread **thread_array = NULL; + struct thread *thread; + + struct cancel_req *cr; + struct listnode *ln; + for (ALL_LIST_ELEMENTS_RO(master->cancel_req, ln, cr)) { + /* If this is an event object cancellation, linear search + * through event + * list deleting any events which have the specified argument. + * We also + * need to check every thread in the ready queue. */ + if (cr->eventobj) { + struct thread *t; + thread = master->event.head; + + while (thread) { + t = thread; + thread = t->next; + + if (t->arg == cr->eventobj) { + thread_list_delete(&master->event, t); + if (t->ref) + *t->ref = NULL; + thread_add_unuse(master, t); + } + } + + thread = master->ready.head; + while (thread) { + t = thread; + thread = t->next; + + if (t->arg == cr->eventobj) { + thread_list_delete(&master->ready, t); + if (t->ref) + *t->ref = NULL; + thread_add_unuse(master, t); + } + } + continue; + } + + /* The pointer varies depending on whether the cancellation + * request was + * made asynchronously or not. If it was, we need to check + * whether the + * thread even exists anymore before cancelling it. */ + thread = (cr->thread) ? cr->thread : *cr->threadref; + + if (!thread) + continue; + + /* Determine the appropriate queue to cancel the thread from */ + switch (thread->type) { + case THREAD_READ: + thread_cancel_rw(master, thread->u.fd, POLLIN); + thread_array = master->read; + break; + case THREAD_WRITE: + thread_cancel_rw(master, thread->u.fd, POLLOUT); + thread_array = master->write; + break; + case THREAD_TIMER: + queue = master->timer; + break; + case THREAD_EVENT: + list = &master->event; + break; + case THREAD_READY: + list = &master->ready; + break; + default: + continue; + break; + } + + if (queue) { + assert(thread->index >= 0); + pqueue_remove(thread, queue); + } else if (list) { + thread_list_delete(list, thread); + } else if (thread_array) { + thread_array[thread->u.fd] = NULL; + } else { + assert(!"Thread should be either in queue or list or array!"); + } + + if (thread->ref) + *thread->ref = NULL; + + thread_add_unuse(thread->master, thread); + } + + /* Delete and free all cancellation requests */ + list_delete_all_node(master->cancel_req); + + /* Wake up any threads which may be blocked in thread_cancel_async() */ + master->canceled = true; + pthread_cond_broadcast(&master->cancel_cond); } /** @@ -1087,19 +1064,19 @@ do_thread_cancel (struct thread_master *master) * @param m the thread_master to cancel from * @param arg the argument passed when creating the event */ -void -thread_cancel_event (struct thread_master *master, void *arg) +void thread_cancel_event(struct thread_master *master, void *arg) { - assert (master->owner == pthread_self()); - - pthread_mutex_lock (&master->mtx); - { - struct cancel_req *cr = XCALLOC (MTYPE_TMP, sizeof (struct cancel_req)); - cr->eventobj = arg; - listnode_add (master->cancel_req, cr); - do_thread_cancel(master); - } - pthread_mutex_unlock (&master->mtx); + assert(master->owner == pthread_self()); + + pthread_mutex_lock(&master->mtx); + { + struct cancel_req *cr = + XCALLOC(MTYPE_TMP, sizeof(struct cancel_req)); + cr->eventobj = arg; + listnode_add(master->cancel_req, cr); + do_thread_cancel(master); + } + pthread_mutex_unlock(&master->mtx); } /** @@ -1109,19 +1086,19 @@ thread_cancel_event (struct thread_master *master, void *arg) * * @param thread task to cancel */ -void -thread_cancel (struct thread *thread) +void thread_cancel(struct thread *thread) { - assert (thread->master->owner == pthread_self()); - - pthread_mutex_lock (&thread->master->mtx); - { - struct cancel_req *cr = XCALLOC (MTYPE_TMP, sizeof (struct cancel_req)); - cr->thread = thread; - listnode_add (thread->master->cancel_req, cr); - do_thread_cancel (thread->master); - } - pthread_mutex_unlock (&thread->master->mtx); + assert(thread->master->owner == pthread_self()); + + pthread_mutex_lock(&thread->master->mtx); + { + struct cancel_req *cr = + XCALLOC(MTYPE_TMP, sizeof(struct cancel_req)); + cr->thread = thread; + listnode_add(thread->master->cancel_req, cr); + do_thread_cancel(thread->master); + } + pthread_mutex_unlock(&thread->master->mtx); } /** @@ -1148,82 +1125,75 @@ thread_cancel (struct thread *thread) * @param thread pointer to thread to cancel * @param eventobj the event */ -void -thread_cancel_async (struct thread_master *master, struct thread **thread, - void *eventobj) +void thread_cancel_async(struct thread_master *master, struct thread **thread, + void *eventobj) { - assert (!(thread && eventobj) && (thread || eventobj)); - assert (master->owner != pthread_self()); - - pthread_mutex_lock (&master->mtx); - { - master->canceled = false; - - if (thread) - { - struct cancel_req *cr = - XCALLOC (MTYPE_TMP, sizeof (struct cancel_req)); - cr->threadref = thread; - listnode_add (master->cancel_req, cr); - } - else if (eventobj) - { - struct cancel_req *cr = - XCALLOC (MTYPE_TMP, sizeof (struct cancel_req)); - cr->eventobj = eventobj; - listnode_add (master->cancel_req, cr); - } - AWAKEN (master); - - while (!master->canceled) - pthread_cond_wait (&master->cancel_cond, &master->mtx); - } - pthread_mutex_unlock (&master->mtx); + assert(!(thread && eventobj) && (thread || eventobj)); + assert(master->owner != pthread_self()); + + pthread_mutex_lock(&master->mtx); + { + master->canceled = false; + + if (thread) { + struct cancel_req *cr = + XCALLOC(MTYPE_TMP, sizeof(struct cancel_req)); + cr->threadref = thread; + listnode_add(master->cancel_req, cr); + } else if (eventobj) { + struct cancel_req *cr = + XCALLOC(MTYPE_TMP, sizeof(struct cancel_req)); + cr->eventobj = eventobj; + listnode_add(master->cancel_req, cr); + } + AWAKEN(master); + + while (!master->canceled) + pthread_cond_wait(&master->cancel_cond, &master->mtx); + } + pthread_mutex_unlock(&master->mtx); } /* ------------------------------------------------------------------------- */ -static struct timeval * -thread_timer_wait (struct pqueue *queue, struct timeval *timer_val) +static struct timeval *thread_timer_wait(struct pqueue *queue, + struct timeval *timer_val) { - if (queue->size) - { - struct thread *next_timer = queue->array[0]; - monotime_until(&next_timer->u.sands, timer_val); - return timer_val; - } - return NULL; + if (queue->size) { + struct thread *next_timer = queue->array[0]; + monotime_until(&next_timer->u.sands, timer_val); + return timer_val; + } + return NULL; } -static struct thread * -thread_run (struct thread_master *m, struct thread *thread, - struct thread *fetch) +static struct thread *thread_run(struct thread_master *m, struct thread *thread, + struct thread *fetch) { - *fetch = *thread; - thread_add_unuse (m, thread); - return fetch; + *fetch = *thread; + thread_add_unuse(m, thread); + return fetch; } -static int -thread_process_io_helper (struct thread_master *m, struct thread *thread, - short state, int pos) +static int thread_process_io_helper(struct thread_master *m, + struct thread *thread, short state, int pos) { - struct thread **thread_array; - - if (!thread) - return 0; - - if (thread->type == THREAD_READ) - thread_array = m->read; - else - thread_array = m->write; - - thread_array[thread->u.fd] = NULL; - thread_list_add (&m->ready, thread); - thread->type = THREAD_READY; - /* if another pthread scheduled this file descriptor for the event we're - * responding to, no problem; we're getting to it now */ - thread->master->handler.pfds[pos].events &= ~(state); - return 1; + struct thread **thread_array; + + if (!thread) + return 0; + + if (thread->type == THREAD_READ) + thread_array = m->read; + else + thread_array = m->write; + + thread_array[thread->u.fd] = NULL; + thread_list_add(&m->ready, thread); + thread->type = THREAD_READY; + /* if another pthread scheduled this file descriptor for the event we're + * responding to, no problem; we're getting to it now */ + thread->master->handler.pfds[pos].events &= ~(state); + return 1; } /** @@ -1235,211 +1205,217 @@ thread_process_io_helper (struct thread_master *m, struct thread *thread, * @param m the thread master * @param num the number of active file descriptors (return value of poll()) */ -static void -thread_process_io (struct thread_master *m, unsigned int num) +static void thread_process_io(struct thread_master *m, unsigned int num) { - unsigned int ready = 0; - struct pollfd *pfds = m->handler.copy; - - for (nfds_t i = 0; i < m->handler.copycount && ready < num ; ++i) - { - /* no event for current fd? immediately continue */ - if (pfds[i].revents == 0) - continue; - - ready++; - - /* Unless someone has called thread_cancel from another pthread, the only - * thing that could have changed in m->handler.pfds while we were - * asleep is the .events field in a given pollfd. Barring thread_cancel() - * that value should be a superset of the values we have in our copy, so - * there's no need to update it. Similarily, barring deletion, the fd - * should still be a valid index into the master's pfds. */ - if (pfds[i].revents & (POLLIN | POLLHUP)) - thread_process_io_helper(m, m->read[pfds[i].fd], POLLIN, i); - if (pfds[i].revents & POLLOUT) - thread_process_io_helper(m, m->write[pfds[i].fd], POLLOUT, i); - - /* if one of our file descriptors is garbage, remove the same from - * both pfds + update sizes and index */ - if (pfds[i].revents & POLLNVAL) - { - memmove (m->handler.pfds + i, - m->handler.pfds + i + 1, - (m->handler.pfdcount - i - 1) * sizeof(struct pollfd)); - m->handler.pfdcount--; - - memmove (pfds + i, pfds + i + 1, - (m->handler.copycount - i - 1) * sizeof(struct pollfd)); - m->handler.copycount--; - - i--; - } - } + unsigned int ready = 0; + struct pollfd *pfds = m->handler.copy; + + for (nfds_t i = 0; i < m->handler.copycount && ready < num; ++i) { + /* no event for current fd? immediately continue */ + if (pfds[i].revents == 0) + continue; + + ready++; + + /* Unless someone has called thread_cancel from another pthread, + * the only + * thing that could have changed in m->handler.pfds while we + * were + * asleep is the .events field in a given pollfd. Barring + * thread_cancel() + * that value should be a superset of the values we have in our + * copy, so + * there's no need to update it. Similarily, barring deletion, + * the fd + * should still be a valid index into the master's pfds. */ + if (pfds[i].revents & (POLLIN | POLLHUP)) + thread_process_io_helper(m, m->read[pfds[i].fd], POLLIN, + i); + if (pfds[i].revents & POLLOUT) + thread_process_io_helper(m, m->write[pfds[i].fd], + POLLOUT, i); + + /* if one of our file descriptors is garbage, remove the same + * from + * both pfds + update sizes and index */ + if (pfds[i].revents & POLLNVAL) { + memmove(m->handler.pfds + i, m->handler.pfds + i + 1, + (m->handler.pfdcount - i - 1) + * sizeof(struct pollfd)); + m->handler.pfdcount--; + + memmove(pfds + i, pfds + i + 1, + (m->handler.copycount - i - 1) + * sizeof(struct pollfd)); + m->handler.copycount--; + + i--; + } + } } /* Add all timers that have popped to the ready list. */ -static unsigned int -thread_process_timers (struct pqueue *queue, struct timeval *timenow) +static unsigned int thread_process_timers(struct pqueue *queue, + struct timeval *timenow) { - struct thread *thread; - unsigned int ready = 0; - - while (queue->size) - { - thread = queue->array[0]; - if (timercmp (timenow, &thread->u.sands, <)) - return ready; - pqueue_dequeue(queue); - thread->type = THREAD_READY; - thread_list_add (&thread->master->ready, thread); - ready++; - } - return ready; + struct thread *thread; + unsigned int ready = 0; + + while (queue->size) { + thread = queue->array[0]; + if (timercmp(timenow, &thread->u.sands, <)) + return ready; + pqueue_dequeue(queue); + thread->type = THREAD_READY; + thread_list_add(&thread->master->ready, thread); + ready++; + } + return ready; } /* process a list en masse, e.g. for event thread lists */ -static unsigned int -thread_process (struct thread_list *list) +static unsigned int thread_process(struct thread_list *list) { - struct thread *thread; - struct thread *next; - unsigned int ready = 0; - - for (thread = list->head; thread; thread = next) - { - next = thread->next; - thread_list_delete (list, thread); - thread->type = THREAD_READY; - thread_list_add (&thread->master->ready, thread); - ready++; - } - return ready; + struct thread *thread; + struct thread *next; + unsigned int ready = 0; + + for (thread = list->head; thread; thread = next) { + next = thread->next; + thread_list_delete(list, thread); + thread->type = THREAD_READY; + thread_list_add(&thread->master->ready, thread); + ready++; + } + return ready; } /* Fetch next ready thread. */ -struct thread * -thread_fetch (struct thread_master *m, struct thread *fetch) +struct thread *thread_fetch(struct thread_master *m, struct thread *fetch) { - struct thread *thread = NULL; - struct timeval now; - struct timeval zerotime = { 0, 0 }; - struct timeval tv; - struct timeval *tw = NULL; - - int num = 0; - - do { - /* Handle signals if any */ - if (m->handle_signals) - quagga_sigevent_process (); - - pthread_mutex_lock (&m->mtx); - - /* Process any pending cancellation requests */ - do_thread_cancel (m); - - /* Post events to ready queue. This must come before the following block - * since events should occur immediately */ - thread_process (&m->event); - - /* If there are no tasks on the ready queue, we will poll() until a timer - * expires or we receive I/O, whichever comes first. The strategy for doing - * this is: - * - * - If there are events pending, set the poll() timeout to zero - * - If there are no events pending, but there are timers pending, set the - * timeout to the smallest remaining time on any timer - * - If there are neither timers nor events pending, but there are file - * descriptors pending, block indefinitely in poll() - * - If nothing is pending, it's time for the application to die - * - * In every case except the last, we need to hit poll() at least once per - * loop to avoid starvation by events */ - - if (m->ready.count == 0) - tw = thread_timer_wait (m->timer, &tv); - - if (m->ready.count != 0 || (tw && !timercmp (tw, &zerotime, >))) - tw = &zerotime; - - if (!tw && m->handler.pfdcount == 0) - { /* die */ - pthread_mutex_unlock (&m->mtx); - fetch = NULL; - break; - } - - /* Copy pollfd array + # active pollfds in it. Not necessary to copy - * the array size as this is fixed. */ - m->handler.copycount = m->handler.pfdcount; - memcpy (m->handler.copy, m->handler.pfds, - m->handler.copycount * sizeof (struct pollfd)); - - pthread_mutex_unlock (&m->mtx); - { - num = fd_poll (m, m->handler.copy, m->handler.pfdsize, - m->handler.copycount, tw); - } - pthread_mutex_lock (&m->mtx); - - /* Handle any errors received in poll() */ - if (num < 0) - { - if (errno == EINTR) - { - pthread_mutex_unlock (&m->mtx); - continue; /* loop around to signal handler */ - } - - /* else die */ - zlog_warn ("poll() error: %s", safe_strerror (errno)); - pthread_mutex_unlock (&m->mtx); - fetch = NULL; - break; - } - - /* Since we could have received more cancellation requests during poll(), process those */ - do_thread_cancel (m); - - /* Post timers to ready queue. */ - monotime(&now); - thread_process_timers (m->timer, &now); - - /* Post I/O to ready queue. */ - if (num > 0) - thread_process_io (m, num); - - /* If we have a ready task, break the loop and return it to the caller */ - if ((thread = thread_trim_head (&m->ready))) - { - fetch = thread_run (m, thread, fetch); - if (fetch->ref) - *fetch->ref = NULL; - } - - pthread_mutex_unlock (&m->mtx); - - } while (!thread && m->spin); - - return fetch; + struct thread *thread = NULL; + struct timeval now; + struct timeval zerotime = {0, 0}; + struct timeval tv; + struct timeval *tw = NULL; + + int num = 0; + + do { + /* Handle signals if any */ + if (m->handle_signals) + quagga_sigevent_process(); + + pthread_mutex_lock(&m->mtx); + + /* Process any pending cancellation requests */ + do_thread_cancel(m); + + /* Post events to ready queue. This must come before the + * following block + * since events should occur immediately */ + thread_process(&m->event); + + /* If there are no tasks on the ready queue, we will poll() + * until a timer + * expires or we receive I/O, whichever comes first. The + * strategy for doing + * this is: + * + * - If there are events pending, set the poll() timeout to zero + * - If there are no events pending, but there are timers + * pending, set the + * timeout to the smallest remaining time on any timer + * - If there are neither timers nor events pending, but there + * are file + * descriptors pending, block indefinitely in poll() + * - If nothing is pending, it's time for the application to die + * + * In every case except the last, we need to hit poll() at least + * once per + * loop to avoid starvation by events */ + + if (m->ready.count == 0) + tw = thread_timer_wait(m->timer, &tv); + + if (m->ready.count != 0 || (tw && !timercmp(tw, &zerotime, >))) + tw = &zerotime; + + if (!tw && m->handler.pfdcount == 0) { /* die */ + pthread_mutex_unlock(&m->mtx); + fetch = NULL; + break; + } + + /* Copy pollfd array + # active pollfds in it. Not necessary to + * copy + * the array size as this is fixed. */ + m->handler.copycount = m->handler.pfdcount; + memcpy(m->handler.copy, m->handler.pfds, + m->handler.copycount * sizeof(struct pollfd)); + + pthread_mutex_unlock(&m->mtx); + { + num = fd_poll(m, m->handler.copy, m->handler.pfdsize, + m->handler.copycount, tw); + } + pthread_mutex_lock(&m->mtx); + + /* Handle any errors received in poll() */ + if (num < 0) { + if (errno == EINTR) { + pthread_mutex_unlock(&m->mtx); + continue; /* loop around to signal handler */ + } + + /* else die */ + zlog_warn("poll() error: %s", safe_strerror(errno)); + pthread_mutex_unlock(&m->mtx); + fetch = NULL; + break; + } + + /* Since we could have received more cancellation requests + * during poll(), process those */ + do_thread_cancel(m); + + /* Post timers to ready queue. */ + monotime(&now); + thread_process_timers(m->timer, &now); + + /* Post I/O to ready queue. */ + if (num > 0) + thread_process_io(m, num); + + /* If we have a ready task, break the loop and return it to the + * caller */ + if ((thread = thread_trim_head(&m->ready))) { + fetch = thread_run(m, thread, fetch); + if (fetch->ref) + *fetch->ref = NULL; + } + + pthread_mutex_unlock(&m->mtx); + + } while (!thread && m->spin); + + return fetch; } -static unsigned long -timeval_elapsed (struct timeval a, struct timeval b) +static unsigned long timeval_elapsed(struct timeval a, struct timeval b) { - return (((a.tv_sec - b.tv_sec) * TIMER_SECOND_MICRO) - + (a.tv_usec - b.tv_usec)); + return (((a.tv_sec - b.tv_sec) * TIMER_SECOND_MICRO) + + (a.tv_usec - b.tv_usec)); } -unsigned long -thread_consumed_time (RUSAGE_T *now, RUSAGE_T *start, unsigned long *cputime) +unsigned long thread_consumed_time(RUSAGE_T *now, RUSAGE_T *start, + unsigned long *cputime) { - /* This is 'user + sys' time. */ - *cputime = timeval_elapsed (now->cpu.ru_utime, start->cpu.ru_utime) + - timeval_elapsed (now->cpu.ru_stime, start->cpu.ru_stime); - return timeval_elapsed (now->real, start->real); + /* This is 'user + sys' time. */ + *cputime = timeval_elapsed(now->cpu.ru_utime, start->cpu.ru_utime) + + timeval_elapsed(now->cpu.ru_stime, start->cpu.ru_stime); + return timeval_elapsed(now->real, start->real); } /* We should aim to yield after yield milliseconds, which defaults @@ -1449,110 +1425,103 @@ thread_consumed_time (RUSAGE_T *now, RUSAGE_T *start, unsigned long *cputime) contexts. The things to consider are whether the thread may have blocked (in which case wall time increases, but CPU time does not), or whether the system is heavily loaded with other processes competing - for CPU time. On balance, wall clock time seems to make sense. + for CPU time. On balance, wall clock time seems to make sense. Plus it has the added benefit that gettimeofday should be faster than calling getrusage. */ -int -thread_should_yield (struct thread *thread) +int thread_should_yield(struct thread *thread) { - int result; - pthread_mutex_lock (&thread->mtx); - { - result = monotime_since(&thread->real, NULL) > (int64_t)thread->yield; - } - pthread_mutex_unlock (&thread->mtx); - return result; + int result; + pthread_mutex_lock(&thread->mtx); + { + result = monotime_since(&thread->real, NULL) + > (int64_t)thread->yield; + } + pthread_mutex_unlock(&thread->mtx); + return result; } -void -thread_set_yield_time (struct thread *thread, unsigned long yield_time) +void thread_set_yield_time(struct thread *thread, unsigned long yield_time) { - pthread_mutex_lock (&thread->mtx); - { - thread->yield = yield_time; - } - pthread_mutex_unlock (&thread->mtx); + pthread_mutex_lock(&thread->mtx); + { + thread->yield = yield_time; + } + pthread_mutex_unlock(&thread->mtx); } -void -thread_getrusage (RUSAGE_T *r) +void thread_getrusage(RUSAGE_T *r) { - monotime(&r->real); - getrusage(RUSAGE_SELF, &(r->cpu)); + monotime(&r->real); + getrusage(RUSAGE_SELF, &(r->cpu)); } /* We check thread consumed time. If the system has getrusage, we'll use that to get in-depth stats on the performance of the thread in addition to wall clock time stats from gettimeofday. */ -void -thread_call (struct thread *thread) +void thread_call(struct thread *thread) { - unsigned long realtime, cputime; - RUSAGE_T before, after; + unsigned long realtime, cputime; + RUSAGE_T before, after; - GETRUSAGE (&before); - thread->real = before.real; + GETRUSAGE(&before); + thread->real = before.real; - pthread_setspecific (thread_current, thread); - (*thread->func) (thread); - pthread_setspecific (thread_current, NULL); + pthread_setspecific(thread_current, thread); + (*thread->func)(thread); + pthread_setspecific(thread_current, NULL); - GETRUSAGE (&after); + GETRUSAGE(&after); - realtime = thread_consumed_time (&after, &before, &cputime); - thread->hist->real.total += realtime; - if (thread->hist->real.max < realtime) - thread->hist->real.max = realtime; - thread->hist->cpu.total += cputime; - if (thread->hist->cpu.max < cputime) - thread->hist->cpu.max = cputime; + realtime = thread_consumed_time(&after, &before, &cputime); + thread->hist->real.total += realtime; + if (thread->hist->real.max < realtime) + thread->hist->real.max = realtime; + thread->hist->cpu.total += cputime; + if (thread->hist->cpu.max < cputime) + thread->hist->cpu.max = cputime; - ++(thread->hist->total_calls); - thread->hist->types |= (1 << thread->add_type); + ++(thread->hist->total_calls); + thread->hist->types |= (1 << thread->add_type); #ifdef CONSUMED_TIME_CHECK - if (realtime > CONSUMED_TIME_CHECK) - { - /* - * We have a CPU Hog on our hands. - * Whinge about it now, so we're aware this is yet another task - * to fix. - */ - zlog_warn ("SLOW THREAD: task %s (%lx) ran for %lums (cpu time %lums)", - thread->funcname, - (unsigned long) thread->func, - realtime/1000, cputime/1000); - } + if (realtime > CONSUMED_TIME_CHECK) { + /* + * We have a CPU Hog on our hands. + * Whinge about it now, so we're aware this is yet another task + * to fix. + */ + zlog_warn( + "SLOW THREAD: task %s (%lx) ran for %lums (cpu time %lums)", + thread->funcname, (unsigned long)thread->func, + realtime / 1000, cputime / 1000); + } #endif /* CONSUMED_TIME_CHECK */ } /* Execute thread */ -void -funcname_thread_execute (struct thread_master *m, - int (*func)(struct thread *), - void *arg, - int val, - debugargdef) +void funcname_thread_execute(struct thread_master *m, + int (*func)(struct thread *), void *arg, int val, + debugargdef) { - struct cpu_thread_history tmp; - struct thread dummy; + struct cpu_thread_history tmp; + struct thread dummy; - memset (&dummy, 0, sizeof (struct thread)); + memset(&dummy, 0, sizeof(struct thread)); - pthread_mutex_init (&dummy.mtx, NULL); - dummy.type = THREAD_EVENT; - dummy.add_type = THREAD_EXECUTE; - dummy.master = NULL; - dummy.arg = arg; - dummy.u.val = val; + pthread_mutex_init(&dummy.mtx, NULL); + dummy.type = THREAD_EVENT; + dummy.add_type = THREAD_EXECUTE; + dummy.master = NULL; + dummy.arg = arg; + dummy.u.val = val; - tmp.func = dummy.func = func; - tmp.funcname = dummy.funcname = funcname; - dummy.hist = hash_get (m->cpu_record, &tmp, - (void * (*) (void *))cpu_record_hash_alloc); + tmp.func = dummy.func = func; + tmp.funcname = dummy.funcname = funcname; + dummy.hist = hash_get(m->cpu_record, &tmp, + (void *(*)(void *))cpu_record_hash_alloc); - dummy.schedfrom = schedfrom; - dummy.schedfrom_line = fromln; + dummy.schedfrom = schedfrom; + dummy.schedfrom_line = fromln; - thread_call (&dummy); + thread_call(&dummy); } diff --git a/lib/thread.h b/lib/thread.h index ad923c413..c830446e1 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -26,114 +26,108 @@ #include #include "monotime.h" -struct rusage_t -{ - struct rusage cpu; - struct timeval real; +struct rusage_t { + struct rusage cpu; + struct timeval real; }; #define RUSAGE_T struct rusage_t #define GETRUSAGE(X) thread_getrusage(X) /* Linked list of thread. */ -struct thread_list -{ - struct thread *head; - struct thread *tail; - int count; +struct thread_list { + struct thread *head; + struct thread *tail; + int count; }; struct pqueue; -struct fd_handler -{ - /* number of pfd that fit in the allocated space of pfds. This is a constant - * and is the same for both pfds and copy. */ - nfds_t pfdsize; - - /* file descriptors to monitor for i/o */ - struct pollfd *pfds; - /* number of pollfds stored in pfds */ - nfds_t pfdcount; - - /* chunk used for temp copy of pollfds */ - struct pollfd *copy; - /* number of pollfds stored in copy */ - nfds_t copycount; +struct fd_handler { + /* number of pfd that fit in the allocated space of pfds. This is a + * constant + * and is the same for both pfds and copy. */ + nfds_t pfdsize; + + /* file descriptors to monitor for i/o */ + struct pollfd *pfds; + /* number of pollfds stored in pfds */ + nfds_t pfdcount; + + /* chunk used for temp copy of pollfds */ + struct pollfd *copy; + /* number of pollfds stored in copy */ + nfds_t copycount; }; struct cancel_req { - struct thread *thread; - void *eventobj; - struct thread **threadref; + struct thread *thread; + void *eventobj; + struct thread **threadref; }; /* Master of the theads. */ -struct thread_master -{ - char *name; - - struct thread **read; - struct thread **write; - struct pqueue *timer; - struct thread_list event; - struct thread_list ready; - struct thread_list unuse; - struct list *cancel_req; - bool canceled; - pthread_cond_t cancel_cond; - struct hash *cpu_record; - int io_pipe[2]; - int fd_limit; - struct fd_handler handler; - unsigned long alloc; - long selectpoll_timeout; - bool spin; - bool handle_signals; - pthread_mutex_t mtx; - pthread_t owner; +struct thread_master { + char *name; + + struct thread **read; + struct thread **write; + struct pqueue *timer; + struct thread_list event; + struct thread_list ready; + struct thread_list unuse; + struct list *cancel_req; + bool canceled; + pthread_cond_t cancel_cond; + struct hash *cpu_record; + int io_pipe[2]; + int fd_limit; + struct fd_handler handler; + unsigned long alloc; + long selectpoll_timeout; + bool spin; + bool handle_signals; + pthread_mutex_t mtx; + pthread_t owner; }; typedef unsigned char thread_type; /* Thread itself. */ -struct thread -{ - thread_type type; /* thread type */ - thread_type add_type; /* thread type */ - struct thread *next; /* next pointer of the thread */ - struct thread *prev; /* previous pointer of the thread */ - struct thread **ref; /* external reference (if given) */ - struct thread_master *master; /* pointer to the struct thread_master */ - int (*func) (struct thread *); /* event function */ - void *arg; /* event argument */ - union { - int val; /* second argument of the event. */ - int fd; /* file descriptor in case of r/w */ - struct timeval sands; /* rest of time sands value. */ - } u; - int index; /* queue position for timers */ - struct timeval real; - struct cpu_thread_history *hist; /* cache pointer to cpu_history */ - unsigned long yield; /* yield time in microseconds */ - const char *funcname; /* name of thread function */ - const char *schedfrom; /* source file thread was scheduled from */ - int schedfrom_line; /* line number of source file */ - pthread_mutex_t mtx; /* mutex for thread.c functions */ +struct thread { + thread_type type; /* thread type */ + thread_type add_type; /* thread type */ + struct thread *next; /* next pointer of the thread */ + struct thread *prev; /* previous pointer of the thread */ + struct thread **ref; /* external reference (if given) */ + struct thread_master *master; /* pointer to the struct thread_master */ + int (*func)(struct thread *); /* event function */ + void *arg; /* event argument */ + union { + int val; /* second argument of the event. */ + int fd; /* file descriptor in case of r/w */ + struct timeval sands; /* rest of time sands value. */ + } u; + int index; /* queue position for timers */ + struct timeval real; + struct cpu_thread_history *hist; /* cache pointer to cpu_history */ + unsigned long yield; /* yield time in microseconds */ + const char *funcname; /* name of thread function */ + const char *schedfrom; /* source file thread was scheduled from */ + int schedfrom_line; /* line number of source file */ + pthread_mutex_t mtx; /* mutex for thread.c functions */ }; -struct cpu_thread_history -{ - int (*func)(struct thread *); - unsigned int total_calls; - unsigned int total_active; - struct time_stats - { - unsigned long total, max; - } real; - struct time_stats cpu; - thread_type types; - const char *funcname; +struct cpu_thread_history { + int (*func)(struct thread *); + unsigned int total_calls; + unsigned int total_active; + struct time_stats { + unsigned long total, max; + } real; + struct time_stats cpu; + thread_type types; + const char *funcname; }; /* Struct timeval's tv_usec one second value. */ @@ -156,14 +150,13 @@ struct cpu_thread_history #define THREAD_FD(X) ((X)->u.fd) #define THREAD_VAL(X) ((X)->u.val) -#define THREAD_OFF(thread) \ - do { \ - if (thread) \ - { \ - thread_cancel (thread); \ - thread = NULL; \ - } \ - } while (0) +#define THREAD_OFF(thread) \ + do { \ + if (thread) { \ + thread_cancel(thread); \ + thread = NULL; \ + } \ + } while (0) #define THREAD_READ_OFF(thread) THREAD_OFF(thread) #define THREAD_WRITE_OFF(thread) THREAD_OFF(thread) @@ -180,43 +173,55 @@ struct cpu_thread_history #define thread_execute(m,f,a,v) funcname_thread_execute(m,f,a,v,#f,__FILE__,__LINE__) /* Prototypes. */ -extern struct thread_master *thread_master_create (const char *); -extern void thread_master_free (struct thread_master *); +extern struct thread_master *thread_master_create(const char *); +extern void thread_master_free(struct thread_master *); extern void thread_master_free_unused(struct thread_master *); -extern struct thread * funcname_thread_add_read_write (int dir, struct thread_master *, - int (*)(struct thread *), void *, int, struct thread **, debugargdef); - -extern struct thread * funcname_thread_add_timer (struct thread_master *, - int (*)(struct thread *), void *, long, struct thread **, debugargdef); - -extern struct thread * funcname_thread_add_timer_msec (struct thread_master *, - int (*)(struct thread *), void *, long, struct thread **, debugargdef); - -extern struct thread * funcname_thread_add_timer_tv (struct thread_master *, - int (*)(struct thread *), void *, struct timeval *, struct thread **, debugargdef); - -extern struct thread * funcname_thread_add_event (struct thread_master *, - int (*)(struct thread *), void *, int, struct thread **, debugargdef); - -extern void funcname_thread_execute (struct thread_master *, - int (*)(struct thread *), void *, int, debugargdef); +extern struct thread * +funcname_thread_add_read_write(int dir, struct thread_master *, + int (*)(struct thread *), void *, int, + struct thread **, debugargdef); + +extern struct thread *funcname_thread_add_timer(struct thread_master *, + int (*)(struct thread *), + void *, long, struct thread **, + debugargdef); + +extern struct thread * +funcname_thread_add_timer_msec(struct thread_master *, int (*)(struct thread *), + void *, long, struct thread **, debugargdef); + +extern struct thread *funcname_thread_add_timer_tv(struct thread_master *, + int (*)(struct thread *), + void *, struct timeval *, + struct thread **, + debugargdef); + +extern struct thread *funcname_thread_add_event(struct thread_master *, + int (*)(struct thread *), + void *, int, struct thread **, + debugargdef); + +extern void funcname_thread_execute(struct thread_master *, + int (*)(struct thread *), void *, int, + debugargdef); #undef debugargdef -extern void thread_cancel (struct thread *); -extern void thread_cancel_async (struct thread_master *, struct thread **, void *); -extern void thread_cancel_event (struct thread_master *, void *); -extern struct thread *thread_fetch (struct thread_master *, struct thread *); -extern void thread_call (struct thread *); -extern unsigned long thread_timer_remain_second (struct thread *); -extern struct timeval thread_timer_remain(struct thread*); -extern int thread_should_yield (struct thread *); +extern void thread_cancel(struct thread *); +extern void thread_cancel_async(struct thread_master *, struct thread **, + void *); +extern void thread_cancel_event(struct thread_master *, void *); +extern struct thread *thread_fetch(struct thread_master *, struct thread *); +extern void thread_call(struct thread *); +extern unsigned long thread_timer_remain_second(struct thread *); +extern struct timeval thread_timer_remain(struct thread *); +extern int thread_should_yield(struct thread *); /* set yield time for thread */ -extern void thread_set_yield_time (struct thread *, unsigned long); +extern void thread_set_yield_time(struct thread *, unsigned long); /* Internal libfrr exports */ -extern void thread_getrusage (RUSAGE_T *); -extern void thread_cmd_init (void); +extern void thread_getrusage(RUSAGE_T *); +extern void thread_cmd_init(void); /* Returns elapsed real (wall clock) time. */ extern unsigned long thread_consumed_time(RUSAGE_T *after, RUSAGE_T *before, diff --git a/lib/vector.c b/lib/vector.c index 110cd2915..e38ee57fc 100644 --- a/lib/vector.c +++ b/lib/vector.c @@ -23,175 +23,161 @@ #include "vector.h" #include "memory.h" -DEFINE_MTYPE_STATIC(LIB, VECTOR, "Vector") +DEFINE_MTYPE_STATIC(LIB, VECTOR, "Vector") DEFINE_MTYPE_STATIC(LIB, VECTOR_INDEX, "Vector index") /* Initialize vector : allocate memory and return vector. */ -vector -vector_init (unsigned int size) +vector vector_init(unsigned int size) { - vector v = XCALLOC (MTYPE_VECTOR, sizeof (struct _vector)); + vector v = XCALLOC(MTYPE_VECTOR, sizeof(struct _vector)); - /* allocate at least one slot */ - if (size == 0) - size = 1; + /* allocate at least one slot */ + if (size == 0) + size = 1; - v->alloced = size; - v->active = 0; - v->index = XCALLOC (MTYPE_VECTOR_INDEX, sizeof (void *) * size); - return v; + v->alloced = size; + v->active = 0; + v->index = XCALLOC(MTYPE_VECTOR_INDEX, sizeof(void *) * size); + return v; } -void -vector_free (vector v) +void vector_free(vector v) { - XFREE (MTYPE_VECTOR_INDEX, v->index); - XFREE (MTYPE_VECTOR, v); + XFREE(MTYPE_VECTOR_INDEX, v->index); + XFREE(MTYPE_VECTOR, v); } -vector -vector_copy (vector v) +vector vector_copy(vector v) { - unsigned int size; - vector new = XCALLOC (MTYPE_VECTOR, sizeof (struct _vector)); + unsigned int size; + vector new = XCALLOC(MTYPE_VECTOR, sizeof(struct _vector)); - new->active = v->active; - new->alloced = v->alloced; + new->active = v->active; + new->alloced = v->alloced; - size = sizeof (void *) * (v->alloced); - new->index = XCALLOC (MTYPE_VECTOR_INDEX, size); - memcpy (new->index, v->index, size); + size = sizeof(void *) * (v->alloced); + new->index = XCALLOC(MTYPE_VECTOR_INDEX, size); + memcpy(new->index, v->index, size); - return new; + return new; } /* Check assigned index, and if it runs short double index pointer */ -void -vector_ensure (vector v, unsigned int num) +void vector_ensure(vector v, unsigned int num) { - if (v->alloced > num) - return; - - v->index = XREALLOC (MTYPE_VECTOR_INDEX, - v->index, sizeof (void *) * (v->alloced * 2)); - memset (&v->index[v->alloced], 0, sizeof (void *) * v->alloced); - v->alloced *= 2; - - if (v->alloced <= num) - vector_ensure (v, num); + if (v->alloced > num) + return; + + v->index = XREALLOC(MTYPE_VECTOR_INDEX, v->index, + sizeof(void *) * (v->alloced * 2)); + memset(&v->index[v->alloced], 0, sizeof(void *) * v->alloced); + v->alloced *= 2; + + if (v->alloced <= num) + vector_ensure(v, num); } /* This function only returns next empty slot index. It dose not mean the slot's index memory is assigned, please call vector_ensure() after calling this function. */ -int -vector_empty_slot (vector v) +int vector_empty_slot(vector v) { - unsigned int i; + unsigned int i; - if (v->active == 0) - return 0; + if (v->active == 0) + return 0; - for (i = 0; i < v->active; i++) - if (v->index[i] == 0) - return i; + for (i = 0; i < v->active; i++) + if (v->index[i] == 0) + return i; - return i; + return i; } /* Set value to the smallest empty slot. */ -int -vector_set (vector v, void *val) +int vector_set(vector v, void *val) { - unsigned int i; + unsigned int i; - i = vector_empty_slot (v); - vector_ensure (v, i); + i = vector_empty_slot(v); + vector_ensure(v, i); - v->index[i] = val; + v->index[i] = val; - if (v->active <= i) - v->active = i + 1; + if (v->active <= i) + v->active = i + 1; - return i; + return i; } /* Set value to specified index slot. */ -int -vector_set_index (vector v, unsigned int i, void *val) +int vector_set_index(vector v, unsigned int i, void *val) { - vector_ensure (v, i); + vector_ensure(v, i); - v->index[i] = val; + v->index[i] = val; - if (v->active <= i) - v->active = i + 1; + if (v->active <= i) + v->active = i + 1; - return i; + return i; } /* Look up vector. */ -void * -vector_lookup (vector v, unsigned int i) +void *vector_lookup(vector v, unsigned int i) { - if (i >= v->active) - return NULL; - return v->index[i]; + if (i >= v->active) + return NULL; + return v->index[i]; } /* Lookup vector, ensure it. */ -void * -vector_lookup_ensure (vector v, unsigned int i) +void *vector_lookup_ensure(vector v, unsigned int i) { - vector_ensure (v, i); - return v->index[i]; + vector_ensure(v, i); + return v->index[i]; } /* Unset value at specified index slot. */ -void -vector_unset (vector v, unsigned int i) +void vector_unset(vector v, unsigned int i) { - if (i >= v->alloced) - return; + if (i >= v->alloced) + return; - v->index[i] = NULL; + v->index[i] = NULL; - if (i + 1 == v->active) - { - v->active--; - while (i && v->index[--i] == NULL && v->active--) - ; /* Is this ugly ? */ - } + if (i + 1 == v->active) { + v->active--; + while (i && v->index[--i] == NULL && v->active--) + ; /* Is this ugly ? */ + } } -void -vector_unset_value (vector v, void *val) +void vector_unset_value(vector v, void *val) { - size_t i; - - for (i = 0; i < v->active; i++) - if (v->index[i] == val) - { - v->index[i] = NULL; - break; - } - - if (i + 1 == v->active) - do - v->active--; - while (i && v->index[--i] == NULL); + size_t i; + + for (i = 0; i < v->active; i++) + if (v->index[i] == val) { + v->index[i] = NULL; + break; + } + + if (i + 1 == v->active) + do + v->active--; + while (i && v->index[--i] == NULL); } /* Count the number of not emplty slot. */ -unsigned int -vector_count (vector v) +unsigned int vector_count(vector v) { - unsigned int i; - unsigned count = 0; + unsigned int i; + unsigned count = 0; - for (i = 0; i < v->active; i++) - if (v->index[i] != NULL) - count++; + for (i = 0; i < v->active; i++) + if (v->index[i] != NULL) + count++; - return count; + return count; } diff --git a/lib/vector.h b/lib/vector.h index ab1d1e6aa..91f7d997d 100644 --- a/lib/vector.h +++ b/lib/vector.h @@ -25,11 +25,10 @@ #include "memory.h" /* struct for vector */ -struct _vector -{ - unsigned int active; /* number of active slots */ - unsigned int alloced; /* number of allocated slot */ - void **index; /* index to data */ +struct _vector { + unsigned int active; /* number of active slots */ + unsigned int alloced; /* number of allocated slot */ + void **index; /* index to data */ }; typedef struct _vector *vector; @@ -39,26 +38,26 @@ typedef struct _vector *vector; array expression. */ /* Reference slot at given index, caller must ensure slot is active */ #define vector_slot(V,I) ((V)->index[(I)]) -/* Number of active slots. +/* Number of active slots. * Note that this differs from vector_count() as it the count returned * will include any empty slots */ #define vector_active(V) ((V)->active) /* Prototypes. */ -extern vector vector_init (unsigned int size); -extern void vector_ensure (vector v, unsigned int num); -extern int vector_empty_slot (vector v); -extern int vector_set (vector v, void *val); -extern int vector_set_index (vector v, unsigned int i, void *val); -extern void vector_unset (vector v, unsigned int i); -extern void vector_unset_value (vector v, void *val); - -extern unsigned int vector_count (vector v); -extern void vector_free (vector v); -extern vector vector_copy (vector v); - -extern void *vector_lookup (vector, unsigned int); -extern void *vector_lookup_ensure (vector, unsigned int); +extern vector vector_init(unsigned int size); +extern void vector_ensure(vector v, unsigned int num); +extern int vector_empty_slot(vector v); +extern int vector_set(vector v, void *val); +extern int vector_set_index(vector v, unsigned int i, void *val); +extern void vector_unset(vector v, unsigned int i); +extern void vector_unset_value(vector v, void *val); + +extern unsigned int vector_count(vector v); +extern void vector_free(vector v); +extern vector vector_copy(vector v); + +extern void *vector_lookup(vector, unsigned int); +extern void *vector_lookup_ensure(vector, unsigned int); #endif /* _ZEBRA_VECTOR_H */ diff --git a/lib/vrf.c b/lib/vrf.c index e13e87898..6e70609b7 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -30,19 +30,19 @@ #include "memory.h" #include "command.h" -DEFINE_MTYPE_STATIC(LIB, VRF, "VRF") +DEFINE_MTYPE_STATIC(LIB, VRF, "VRF") DEFINE_MTYPE_STATIC(LIB, VRF_BITMAP, "VRF bit-map") DEFINE_QOBJ_TYPE(vrf) -static __inline int vrf_id_compare (const struct vrf *, const struct vrf *); -static __inline int vrf_name_compare (const struct vrf *, const struct vrf *); +static __inline int vrf_id_compare(const struct vrf *, const struct vrf *); +static __inline int vrf_name_compare(const struct vrf *, const struct vrf *); -RB_GENERATE (vrf_id_head, vrf, id_entry, vrf_id_compare); -RB_GENERATE (vrf_name_head, vrf, name_entry, vrf_name_compare); +RB_GENERATE(vrf_id_head, vrf, id_entry, vrf_id_compare); +RB_GENERATE(vrf_name_head, vrf, name_entry, vrf_name_compare); -struct vrf_id_head vrfs_by_id = RB_INITIALIZER (&vrfs_by_id); -struct vrf_name_head vrfs_by_name = RB_INITIALIZER (&vrfs_by_name); +struct vrf_id_head vrfs_by_id = RB_INITIALIZER(&vrfs_by_id); +struct vrf_name_head vrfs_by_name = RB_INITIALIZER(&vrfs_by_name); /* * Turn on/off debug code @@ -51,36 +51,34 @@ struct vrf_name_head vrfs_by_name = RB_INITIALIZER (&vrfs_by_name); int debug_vrf = 0; /* Holding VRF hooks */ -struct vrf_master -{ - int (*vrf_new_hook) (struct vrf *); - int (*vrf_delete_hook) (struct vrf *); - int (*vrf_enable_hook) (struct vrf *); - int (*vrf_disable_hook) (struct vrf *); -} vrf_master = {0,}; +struct vrf_master { + int (*vrf_new_hook)(struct vrf *); + int (*vrf_delete_hook)(struct vrf *); + int (*vrf_enable_hook)(struct vrf *); + int (*vrf_disable_hook)(struct vrf *); +} vrf_master = { + 0, +}; -static int vrf_is_enabled (struct vrf *vrf); -static void vrf_disable (struct vrf *vrf); +static int vrf_is_enabled(struct vrf *vrf); +static void vrf_disable(struct vrf *vrf); /* VRF list existance check by name. */ -struct vrf * -vrf_lookup_by_name (const char *name) +struct vrf *vrf_lookup_by_name(const char *name) { - struct vrf vrf; - strlcpy (vrf.name, name, sizeof (vrf.name)); - return (RB_FIND (vrf_name_head, &vrfs_by_name, &vrf)); + struct vrf vrf; + strlcpy(vrf.name, name, sizeof(vrf.name)); + return (RB_FIND(vrf_name_head, &vrfs_by_name, &vrf)); } -static __inline int -vrf_id_compare (const struct vrf *a, const struct vrf *b) +static __inline int vrf_id_compare(const struct vrf *a, const struct vrf *b) { - return (a->vrf_id - b->vrf_id); + return (a->vrf_id - b->vrf_id); } -static int -vrf_name_compare (const struct vrf *a, const struct vrf *b) +static int vrf_name_compare(const struct vrf *a, const struct vrf *b) { - return strcmp (a->name, b->name); + return strcmp(a->name, b->name); } /* Get a VRF. If not found, create one. @@ -90,104 +88,95 @@ vrf_name_compare (const struct vrf *a, const struct vrf *b) * Description: Please note that this routine can be called with just the name * and 0 vrf-id */ -struct vrf * -vrf_get (vrf_id_t vrf_id, const char *name) -{ - struct vrf *vrf = NULL; - int new = 0; - - if (debug_vrf) - zlog_debug ("VRF_GET: %s(%d)", name, vrf_id); - - /* Nothing to see, move along here */ - if (!name && vrf_id == VRF_UNKNOWN) - return NULL; - - /* Try to find VRF both by ID and name */ - if (vrf_id != VRF_UNKNOWN) - vrf = vrf_lookup_by_id (vrf_id); - if (! vrf && name) - vrf = vrf_lookup_by_name (name); - - if (vrf == NULL) - { - vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf)); - vrf->vrf_id = VRF_UNKNOWN; - if_init (&vrf->iflist); - QOBJ_REG (vrf, vrf); - new = 1; - - if (debug_vrf) - zlog_debug ("VRF(%u) %s is created.", - vrf_id, (name) ? name : "(NULL)"); - } - - /* Set identifier */ - if (vrf_id != VRF_UNKNOWN && vrf->vrf_id == VRF_UNKNOWN) - { - vrf->vrf_id = vrf_id; - RB_INSERT (vrf_id_head, &vrfs_by_id, vrf); - } - - /* Set name */ - if (name && vrf->name[0] != '\0' && strcmp (name, vrf->name)) - { - RB_REMOVE (vrf_name_head, &vrfs_by_name, vrf); - strlcpy (vrf->name, name, sizeof (vrf->name)); - RB_INSERT (vrf_name_head, &vrfs_by_name, vrf); - } - else if (name && vrf->name[0] == '\0') - { - strlcpy (vrf->name, name, sizeof (vrf->name)); - RB_INSERT (vrf_name_head, &vrfs_by_name, vrf); - } - - if (new && vrf_master.vrf_new_hook) - (*vrf_master.vrf_new_hook) (vrf); - - return vrf; +struct vrf *vrf_get(vrf_id_t vrf_id, const char *name) +{ + struct vrf *vrf = NULL; + int new = 0; + + if (debug_vrf) + zlog_debug("VRF_GET: %s(%d)", name, vrf_id); + + /* Nothing to see, move along here */ + if (!name && vrf_id == VRF_UNKNOWN) + return NULL; + + /* Try to find VRF both by ID and name */ + if (vrf_id != VRF_UNKNOWN) + vrf = vrf_lookup_by_id(vrf_id); + if (!vrf && name) + vrf = vrf_lookup_by_name(name); + + if (vrf == NULL) { + vrf = XCALLOC(MTYPE_VRF, sizeof(struct vrf)); + vrf->vrf_id = VRF_UNKNOWN; + if_init(&vrf->iflist); + QOBJ_REG(vrf, vrf); + new = 1; + + if (debug_vrf) + zlog_debug("VRF(%u) %s is created.", vrf_id, + (name) ? name : "(NULL)"); + } + + /* Set identifier */ + if (vrf_id != VRF_UNKNOWN && vrf->vrf_id == VRF_UNKNOWN) { + vrf->vrf_id = vrf_id; + RB_INSERT(vrf_id_head, &vrfs_by_id, vrf); + } + + /* Set name */ + if (name && vrf->name[0] != '\0' && strcmp(name, vrf->name)) { + RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf); + strlcpy(vrf->name, name, sizeof(vrf->name)); + RB_INSERT(vrf_name_head, &vrfs_by_name, vrf); + } else if (name && vrf->name[0] == '\0') { + strlcpy(vrf->name, name, sizeof(vrf->name)); + RB_INSERT(vrf_name_head, &vrfs_by_name, vrf); + } + + if (new &&vrf_master.vrf_new_hook) + (*vrf_master.vrf_new_hook)(vrf); + + return vrf; } /* Delete a VRF. This is called in vrf_terminate(). */ -void -vrf_delete (struct vrf *vrf) +void vrf_delete(struct vrf *vrf) { - if (debug_vrf) - zlog_debug ("VRF %u is to be deleted.", vrf->vrf_id); + if (debug_vrf) + zlog_debug("VRF %u is to be deleted.", vrf->vrf_id); - if (vrf_is_enabled (vrf)) - vrf_disable (vrf); + if (vrf_is_enabled(vrf)) + vrf_disable(vrf); - if (vrf_master.vrf_delete_hook) - (*vrf_master.vrf_delete_hook) (vrf); + if (vrf_master.vrf_delete_hook) + (*vrf_master.vrf_delete_hook)(vrf); - QOBJ_UNREG (vrf); - if_terminate (&vrf->iflist); + QOBJ_UNREG(vrf); + if_terminate(&vrf->iflist); - if (vrf->vrf_id != VRF_UNKNOWN) - RB_REMOVE (vrf_id_head, &vrfs_by_id, vrf); - if (vrf->name[0] != '\0') - RB_REMOVE (vrf_name_head, &vrfs_by_name, vrf); + if (vrf->vrf_id != VRF_UNKNOWN) + RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf); + if (vrf->name[0] != '\0') + RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf); - XFREE (MTYPE_VRF, vrf); + XFREE(MTYPE_VRF, vrf); } /* Look up a VRF by identifier. */ -struct vrf * -vrf_lookup_by_id (vrf_id_t vrf_id) +struct vrf *vrf_lookup_by_id(vrf_id_t vrf_id) { - struct vrf vrf; - vrf.vrf_id = vrf_id; - return (RB_FIND (vrf_id_head, &vrfs_by_id, &vrf)); + struct vrf vrf; + vrf.vrf_id = vrf_id; + return (RB_FIND(vrf_id_head, &vrfs_by_id, &vrf)); } /* * Check whether the VRF is enabled. */ -static int -vrf_is_enabled (struct vrf *vrf) +static int vrf_is_enabled(struct vrf *vrf) { - return vrf && CHECK_FLAG (vrf->status, VRF_ACTIVE); + return vrf && CHECK_FLAG(vrf->status, VRF_ACTIVE); } /* @@ -197,21 +186,20 @@ vrf_is_enabled (struct vrf *vrf) * * RETURN: 1 - enabled successfully; otherwise, 0. */ -int -vrf_enable (struct vrf *vrf) +int vrf_enable(struct vrf *vrf) { - if (vrf_is_enabled (vrf)) - return 1; + if (vrf_is_enabled(vrf)) + return 1; - if (debug_vrf) - zlog_debug ("VRF %u is enabled.", vrf->vrf_id); + if (debug_vrf) + zlog_debug("VRF %u is enabled.", vrf->vrf_id); - SET_FLAG (vrf->status, VRF_ACTIVE); + SET_FLAG(vrf->status, VRF_ACTIVE); - if (vrf_master.vrf_enable_hook) - (*vrf_master.vrf_enable_hook) (vrf); + if (vrf_master.vrf_enable_hook) + (*vrf_master.vrf_enable_hook)(vrf); - return 1; + return 1; } /* @@ -219,67 +207,62 @@ vrf_enable (struct vrf *vrf) * The VRF_DELETE_HOOK callback will be called to inform * that they must release the resources in the VRF. */ -static void -vrf_disable (struct vrf *vrf) +static void vrf_disable(struct vrf *vrf) { - if (! vrf_is_enabled (vrf)) - return; + if (!vrf_is_enabled(vrf)) + return; - UNSET_FLAG (vrf->status, VRF_ACTIVE); + UNSET_FLAG(vrf->status, VRF_ACTIVE); - if (debug_vrf) - zlog_debug ("VRF %u is to be disabled.", vrf->vrf_id); + if (debug_vrf) + zlog_debug("VRF %u is to be disabled.", vrf->vrf_id); - /* Till now, nothing to be done for the default VRF. */ - //Pending: see why this statement. + /* Till now, nothing to be done for the default VRF. */ + // Pending: see why this statement. - if (vrf_master.vrf_disable_hook) - (*vrf_master.vrf_disable_hook) (vrf); + if (vrf_master.vrf_disable_hook) + (*vrf_master.vrf_disable_hook)(vrf); } -vrf_id_t -vrf_name_to_id (const char *name) +vrf_id_t vrf_name_to_id(const char *name) { - struct vrf *vrf; - vrf_id_t vrf_id = VRF_DEFAULT; //Pending: need a way to return invalid id/ routine not used. + struct vrf *vrf; + vrf_id_t vrf_id = VRF_DEFAULT; // Pending: need a way to return invalid + // id/ routine not used. - vrf = vrf_lookup_by_name (name); - if (vrf) - vrf_id = vrf->vrf_id; + vrf = vrf_lookup_by_name(name); + if (vrf) + vrf_id = vrf->vrf_id; - return vrf_id; + return vrf_id; } /* Get the data pointer of the specified VRF. If not found, create one. */ -void * -vrf_info_get (vrf_id_t vrf_id) +void *vrf_info_get(vrf_id_t vrf_id) { - struct vrf *vrf = vrf_get (vrf_id, NULL); - return vrf->info; + struct vrf *vrf = vrf_get(vrf_id, NULL); + return vrf->info; } /* Look up the data pointer of the specified VRF. */ -void * -vrf_info_lookup (vrf_id_t vrf_id) +void *vrf_info_lookup(vrf_id_t vrf_id) { - struct vrf *vrf = vrf_lookup_by_id (vrf_id); - return vrf ? vrf->info : NULL; + struct vrf *vrf = vrf_lookup_by_id(vrf_id); + return vrf ? vrf->info : NULL; } /* Look up the interface list in a VRF. */ -struct list * -vrf_iflist (vrf_id_t vrf_id) +struct list *vrf_iflist(vrf_id_t vrf_id) { - struct vrf * vrf = vrf_lookup_by_id (vrf_id); - return vrf ? vrf->iflist : NULL; + struct vrf *vrf = vrf_lookup_by_id(vrf_id); + return vrf ? vrf->iflist : NULL; } /* Get the interface list of the specified VRF. Create one if not find. */ -struct list * -vrf_iflist_get (vrf_id_t vrf_id) +struct list *vrf_iflist_get(vrf_id_t vrf_id) { - struct vrf * vrf = vrf_get (vrf_id, NULL); - return vrf->iflist; + struct vrf *vrf = vrf_get(vrf_id, NULL); + return vrf->iflist; } /* @@ -287,177 +270,161 @@ vrf_iflist_get (vrf_id_t vrf_id) */ #define VRF_BITMAP_NUM_OF_GROUPS 8 -#define VRF_BITMAP_NUM_OF_BITS_IN_GROUP \ - (UINT16_MAX / VRF_BITMAP_NUM_OF_GROUPS) -#define VRF_BITMAP_NUM_OF_BYTES_IN_GROUP \ - (VRF_BITMAP_NUM_OF_BITS_IN_GROUP / CHAR_BIT + 1) /* +1 for ensure */ - -#define VRF_BITMAP_GROUP(_id) \ - ((_id) / VRF_BITMAP_NUM_OF_BITS_IN_GROUP) -#define VRF_BITMAP_BIT_OFFSET(_id) \ - ((_id) % VRF_BITMAP_NUM_OF_BITS_IN_GROUP) - -#define VRF_BITMAP_INDEX_IN_GROUP(_bit_offset) \ - ((_bit_offset) / CHAR_BIT) -#define VRF_BITMAP_FLAG(_bit_offset) \ - (((u_char)1) << ((_bit_offset) % CHAR_BIT)) - -struct vrf_bitmap -{ - u_char *groups[VRF_BITMAP_NUM_OF_GROUPS]; +#define VRF_BITMAP_NUM_OF_BITS_IN_GROUP (UINT16_MAX / VRF_BITMAP_NUM_OF_GROUPS) +#define VRF_BITMAP_NUM_OF_BYTES_IN_GROUP \ + (VRF_BITMAP_NUM_OF_BITS_IN_GROUP / CHAR_BIT + 1) /* +1 for ensure */ + +#define VRF_BITMAP_GROUP(_id) ((_id) / VRF_BITMAP_NUM_OF_BITS_IN_GROUP) +#define VRF_BITMAP_BIT_OFFSET(_id) ((_id) % VRF_BITMAP_NUM_OF_BITS_IN_GROUP) + +#define VRF_BITMAP_INDEX_IN_GROUP(_bit_offset) ((_bit_offset) / CHAR_BIT) +#define VRF_BITMAP_FLAG(_bit_offset) (((u_char)1) << ((_bit_offset) % CHAR_BIT)) + +struct vrf_bitmap { + u_char *groups[VRF_BITMAP_NUM_OF_GROUPS]; }; -vrf_bitmap_t -vrf_bitmap_init (void) +vrf_bitmap_t vrf_bitmap_init(void) { - return (vrf_bitmap_t) XCALLOC (MTYPE_VRF_BITMAP, sizeof (struct vrf_bitmap)); + return (vrf_bitmap_t)XCALLOC(MTYPE_VRF_BITMAP, + sizeof(struct vrf_bitmap)); } -void -vrf_bitmap_free (vrf_bitmap_t bmap) +void vrf_bitmap_free(vrf_bitmap_t bmap) { - struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap; - int i; + struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap; + int i; - if (bmap == VRF_BITMAP_NULL) - return; + if (bmap == VRF_BITMAP_NULL) + return; - for (i = 0; i < VRF_BITMAP_NUM_OF_GROUPS; i++) - if (bm->groups[i]) - XFREE (MTYPE_VRF_BITMAP, bm->groups[i]); + for (i = 0; i < VRF_BITMAP_NUM_OF_GROUPS; i++) + if (bm->groups[i]) + XFREE(MTYPE_VRF_BITMAP, bm->groups[i]); - XFREE (MTYPE_VRF_BITMAP, bm); + XFREE(MTYPE_VRF_BITMAP, bm); } -void -vrf_bitmap_set (vrf_bitmap_t bmap, vrf_id_t vrf_id) +void vrf_bitmap_set(vrf_bitmap_t bmap, vrf_id_t vrf_id) { - struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap; - u_char group = VRF_BITMAP_GROUP (vrf_id); - u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id); + struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap; + u_char group = VRF_BITMAP_GROUP(vrf_id); + u_char offset = VRF_BITMAP_BIT_OFFSET(vrf_id); - if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN) - return; + if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN) + return; - if (bm->groups[group] == NULL) - bm->groups[group] = XCALLOC (MTYPE_VRF_BITMAP, - VRF_BITMAP_NUM_OF_BYTES_IN_GROUP); + if (bm->groups[group] == NULL) + bm->groups[group] = XCALLOC(MTYPE_VRF_BITMAP, + VRF_BITMAP_NUM_OF_BYTES_IN_GROUP); - SET_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)], - VRF_BITMAP_FLAG (offset)); + SET_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)], + VRF_BITMAP_FLAG(offset)); } -void -vrf_bitmap_unset (vrf_bitmap_t bmap, vrf_id_t vrf_id) +void vrf_bitmap_unset(vrf_bitmap_t bmap, vrf_id_t vrf_id) { - struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap; - u_char group = VRF_BITMAP_GROUP (vrf_id); - u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id); + struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap; + u_char group = VRF_BITMAP_GROUP(vrf_id); + u_char offset = VRF_BITMAP_BIT_OFFSET(vrf_id); - if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN || - bm->groups[group] == NULL) - return; + if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN + || bm->groups[group] == NULL) + return; - UNSET_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)], - VRF_BITMAP_FLAG (offset)); + UNSET_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)], + VRF_BITMAP_FLAG(offset)); } -int -vrf_bitmap_check (vrf_bitmap_t bmap, vrf_id_t vrf_id) +int vrf_bitmap_check(vrf_bitmap_t bmap, vrf_id_t vrf_id) { - struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap; - u_char group = VRF_BITMAP_GROUP (vrf_id); - u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id); + struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap; + u_char group = VRF_BITMAP_GROUP(vrf_id); + u_char offset = VRF_BITMAP_BIT_OFFSET(vrf_id); - if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN || - bm->groups[group] == NULL) - return 0; + if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN + || bm->groups[group] == NULL) + return 0; - return CHECK_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)], - VRF_BITMAP_FLAG (offset)) ? 1 : 0; + return CHECK_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)], + VRF_BITMAP_FLAG(offset)) + ? 1 + : 0; } -static void -vrf_autocomplete (vector comps, struct cmd_token *token) +static void vrf_autocomplete(vector comps, struct cmd_token *token) { - struct vrf *vrf = NULL; + struct vrf *vrf = NULL; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if (vrf->vrf_id != 0) - vector_set (comps, XSTRDUP (MTYPE_COMPLETION, vrf->name)); - } + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if (vrf->vrf_id != 0) + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name)); + } } static const struct cmd_variable_handler vrf_var_handlers[] = { - { - .varname = "vrf", - .completions = vrf_autocomplete, - }, - { - .completions = NULL - }, + { + .varname = "vrf", + .completions = vrf_autocomplete, + }, + {.completions = NULL}, }; /* Initialize VRF module. */ -void -vrf_init (int (*create)(struct vrf *), - int (*enable)(struct vrf *), - int (*disable)(struct vrf *), - int (*delete)(struct vrf *)) -{ - struct vrf *default_vrf; - - if (debug_vrf) - zlog_debug ("%s: Initializing VRF subsystem", __PRETTY_FUNCTION__); - - vrf_master.vrf_new_hook = create; - vrf_master.vrf_enable_hook = enable; - vrf_master.vrf_disable_hook = disable; - vrf_master.vrf_delete_hook = delete; - - /* The default VRF always exists. */ - default_vrf = vrf_get (VRF_DEFAULT, VRF_DEFAULT_NAME); - if (!default_vrf) - { - zlog_err ("vrf_init: failed to create the default VRF!"); - exit (1); - } - - /* Enable the default VRF. */ - if (!vrf_enable (default_vrf)) - { - zlog_err ("vrf_init: failed to enable the default VRF!"); - exit (1); - } - - cmd_variable_handler_register (vrf_var_handlers); +void vrf_init(int (*create)(struct vrf *), int (*enable)(struct vrf *), + int (*disable)(struct vrf *), int (*delete)(struct vrf *)) +{ + struct vrf *default_vrf; + + if (debug_vrf) + zlog_debug("%s: Initializing VRF subsystem", + __PRETTY_FUNCTION__); + + vrf_master.vrf_new_hook = create; + vrf_master.vrf_enable_hook = enable; + vrf_master.vrf_disable_hook = disable; + vrf_master.vrf_delete_hook = delete; + + /* The default VRF always exists. */ + default_vrf = vrf_get(VRF_DEFAULT, VRF_DEFAULT_NAME); + if (!default_vrf) { + zlog_err("vrf_init: failed to create the default VRF!"); + exit(1); + } + + /* Enable the default VRF. */ + if (!vrf_enable(default_vrf)) { + zlog_err("vrf_init: failed to enable the default VRF!"); + exit(1); + } + + cmd_variable_handler_register(vrf_var_handlers); } /* Terminate VRF module. */ -void -vrf_terminate (void) +void vrf_terminate(void) { - struct vrf *vrf; + struct vrf *vrf; - if (debug_vrf) - zlog_debug ("%s: Shutting down vrf subsystem", __PRETTY_FUNCTION__); + if (debug_vrf) + zlog_debug("%s: Shutting down vrf subsystem", + __PRETTY_FUNCTION__); - while ((vrf = RB_ROOT (vrf_id_head, &vrfs_by_id)) != NULL) - vrf_delete (vrf); - while ((vrf = RB_ROOT (vrf_name_head, &vrfs_by_name)) != NULL) - vrf_delete (vrf); + while ((vrf = RB_ROOT(vrf_id_head, &vrfs_by_id)) != NULL) + vrf_delete(vrf); + while ((vrf = RB_ROOT(vrf_name_head, &vrfs_by_name)) != NULL) + vrf_delete(vrf); } /* Create a socket for the VRF. */ -int -vrf_socket (int domain, int type, int protocol, vrf_id_t vrf_id) +int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id) { - int ret = -1; + int ret = -1; - ret = socket (domain, type, protocol); + ret = socket(domain, type, protocol); - return ret; + return ret; } /* vrf CLI commands */ @@ -467,23 +434,23 @@ DEFUN_NOSH (vrf, "Select a VRF to configure\n" "VRF's name\n") { - int idx_name = 1; - const char *vrfname = argv[idx_name]->arg; - struct vrf *vrfp; + int idx_name = 1; + const char *vrfname = argv[idx_name]->arg; + struct vrf *vrfp; - if (strlen(vrfname) > VRF_NAMSIZ) - { - vty_out (vty, "%% VRF name %s is invalid: length exceeds " - "%d characters\n", - vrfname, VRF_NAMSIZ); - return CMD_WARNING_CONFIG_FAILED; - } + if (strlen(vrfname) > VRF_NAMSIZ) { + vty_out(vty, + "%% VRF name %s is invalid: length exceeds " + "%d characters\n", + vrfname, VRF_NAMSIZ); + return CMD_WARNING_CONFIG_FAILED; + } - vrfp = vrf_get (VRF_UNKNOWN, vrfname); + vrfp = vrf_get(VRF_UNKNOWN, vrfname); - VTY_PUSH_CONTEXT (VRF_NODE, vrfp); + VTY_PUSH_CONTEXT(VRF_NODE, vrfp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_NOSH (no_vrf, @@ -493,36 +460,29 @@ DEFUN_NOSH (no_vrf, "Delete a pseudo VRF's configuration\n" "VRF's name\n") { - const char *vrfname = argv[2]->arg; + const char *vrfname = argv[2]->arg; - struct vrf *vrfp; + struct vrf *vrfp; - vrfp = vrf_lookup_by_name (vrfname); + vrfp = vrf_lookup_by_name(vrfname); - if (vrfp == NULL) - { - vty_out (vty, "%% VRF %s does not exist\n", vrfname); - return CMD_WARNING_CONFIG_FAILED; - } + if (vrfp == NULL) { + vty_out(vty, "%% VRF %s does not exist\n", vrfname); + return CMD_WARNING_CONFIG_FAILED; + } - if (CHECK_FLAG (vrfp->status, VRF_ACTIVE)) - { - vty_out (vty, "%% Only inactive VRFs can be deleted\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (CHECK_FLAG(vrfp->status, VRF_ACTIVE)) { + vty_out(vty, "%% Only inactive VRFs can be deleted\n"); + return CMD_WARNING_CONFIG_FAILED; + } - vrf_delete(vrfp); + vrf_delete(vrfp); - return CMD_SUCCESS; + return CMD_SUCCESS; } -struct cmd_node vrf_node = -{ - VRF_NODE, - "%s(config-vrf)# ", - 1 -}; +struct cmd_node vrf_node = {VRF_NODE, "%s(config-vrf)# ", 1}; /* * Debug CLI for vrf's @@ -533,9 +493,9 @@ DEFUN (vrf_debug, DEBUG_STR "VRF Debugging\n") { - debug_vrf = 1; + debug_vrf = 1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_vrf_debug, @@ -545,43 +505,35 @@ DEFUN (no_vrf_debug, DEBUG_STR "VRF Debugging\n") { - debug_vrf = 0; + debug_vrf = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -vrf_write_host (struct vty *vty) +static int vrf_write_host(struct vty *vty) { - if (debug_vrf) - vty_out (vty, "debug vrf\n"); + if (debug_vrf) + vty_out(vty, "debug vrf\n"); - return 1; + return 1; } -static struct cmd_node vrf_debug_node = -{ - VRF_DEBUG_NODE, - "", - 1 -}; +static struct cmd_node vrf_debug_node = {VRF_DEBUG_NODE, "", 1}; -void -vrf_install_commands (void) +void vrf_install_commands(void) { - install_node (&vrf_debug_node, vrf_write_host); + install_node(&vrf_debug_node, vrf_write_host); - install_element (CONFIG_NODE, &vrf_debug_cmd); - install_element (ENABLE_NODE, &vrf_debug_cmd); - install_element (CONFIG_NODE, &no_vrf_debug_cmd); - install_element (ENABLE_NODE, &no_vrf_debug_cmd); + install_element(CONFIG_NODE, &vrf_debug_cmd); + install_element(ENABLE_NODE, &vrf_debug_cmd); + install_element(CONFIG_NODE, &no_vrf_debug_cmd); + install_element(ENABLE_NODE, &no_vrf_debug_cmd); } -void -vrf_cmd_init (int (*writefunc)(struct vty *vty)) +void vrf_cmd_init(int (*writefunc)(struct vty *vty)) { - install_element (CONFIG_NODE, &vrf_cmd); - install_element (CONFIG_NODE, &no_vrf_cmd); - install_node (&vrf_node, writefunc); - install_default (VRF_NODE); + install_element(CONFIG_NODE, &vrf_cmd); + install_element(CONFIG_NODE, &no_vrf_cmd); + install_node(&vrf_node, writefunc); + install_default(VRF_NODE); } diff --git a/lib/vrf.h b/lib/vrf.h index dcbc9b5e6..bdc0db9c9 100644 --- a/lib/vrf.h +++ b/lib/vrf.h @@ -37,11 +37,7 @@ /* Pending: May need to refine this. */ #ifndef IFLA_VRF_MAX -enum { - IFLA_VRF_UNSPEC, - IFLA_VRF_TABLE, - __IFLA_VRF_MAX -}; +enum { IFLA_VRF_UNSPEC, IFLA_VRF_TABLE, __IFLA_VRF_MAX }; #define IFLA_VRF_MAX (__IFLA_VRF_MAX - 1) #endif @@ -60,102 +56,97 @@ enum { * Pass some OS specific data up through * to the daemons */ -struct vrf_data -{ - union - { - struct { - uint32_t table_id; - } l; - }; +struct vrf_data { + union { + struct { + uint32_t table_id; + } l; + }; }; -struct vrf -{ - RB_ENTRY(vrf) id_entry, name_entry; +struct vrf { + RB_ENTRY(vrf) id_entry, name_entry; - /* Identifier, same as the vector index */ - vrf_id_t vrf_id; + /* Identifier, same as the vector index */ + vrf_id_t vrf_id; - /* Name */ - char name[VRF_NAMSIZ + 1]; + /* Name */ + char name[VRF_NAMSIZ + 1]; - /* Zebra internal VRF status */ - u_char status; + /* Zebra internal VRF status */ + u_char status; #define VRF_ACTIVE (1 << 0) - /* Master list of interfaces belonging to this VRF */ - struct list *iflist; + /* Master list of interfaces belonging to this VRF */ + struct list *iflist; - /* User data */ - void *info; + /* User data */ + void *info; - /* The table_id from the kernel */ - struct vrf_data data; + /* The table_id from the kernel */ + struct vrf_data data; - QOBJ_FIELDS + QOBJ_FIELDS }; -RB_HEAD (vrf_id_head, vrf); -RB_PROTOTYPE (vrf_id_head, vrf, id_entry, vrf_id_compare) -RB_HEAD (vrf_name_head, vrf); -RB_PROTOTYPE (vrf_name_head, vrf, name_entry, vrf_name_compare) +RB_HEAD(vrf_id_head, vrf); +RB_PROTOTYPE(vrf_id_head, vrf, id_entry, vrf_id_compare) +RB_HEAD(vrf_name_head, vrf); +RB_PROTOTYPE(vrf_name_head, vrf, name_entry, vrf_name_compare) DECLARE_QOBJ_TYPE(vrf) extern struct vrf_id_head vrfs_by_id; extern struct vrf_name_head vrfs_by_name; -extern struct vrf *vrf_lookup_by_id (vrf_id_t); -extern struct vrf *vrf_lookup_by_name (const char *); -extern struct vrf *vrf_get (vrf_id_t, const char *); -extern vrf_id_t vrf_name_to_id (const char *); - -#define VRF_GET_ID(V,NAME) \ - do { \ - struct vrf *vrf; \ - if (!(vrf = vrf_lookup_by_name(NAME))) \ - { \ - vty_out (vty, "%% VRF %s not found\n", NAME);\ - return CMD_WARNING; \ - } \ - if (vrf->vrf_id == VRF_UNKNOWN) \ - { \ - vty_out (vty, "%% VRF %s not active\n", NAME);\ - return CMD_WARNING; \ - } \ - (V) = vrf->vrf_id; \ - } while (0) +extern struct vrf *vrf_lookup_by_id(vrf_id_t); +extern struct vrf *vrf_lookup_by_name(const char *); +extern struct vrf *vrf_get(vrf_id_t, const char *); +extern vrf_id_t vrf_name_to_id(const char *); + +#define VRF_GET_ID(V, NAME) \ + do { \ + struct vrf *vrf; \ + if (!(vrf = vrf_lookup_by_name(NAME))) { \ + vty_out(vty, "%% VRF %s not found\n", NAME); \ + return CMD_WARNING; \ + } \ + if (vrf->vrf_id == VRF_UNKNOWN) { \ + vty_out(vty, "%% VRF %s not active\n", NAME); \ + return CMD_WARNING; \ + } \ + (V) = vrf->vrf_id; \ + } while (0) /* * Utilities to obtain the user data */ /* Get the data pointer of the specified VRF. If not found, create one. */ -extern void *vrf_info_get (vrf_id_t); +extern void *vrf_info_get(vrf_id_t); /* Look up the data pointer of the specified VRF. */ -extern void *vrf_info_lookup (vrf_id_t); +extern void *vrf_info_lookup(vrf_id_t); /* * Utilities to obtain the interface list */ /* Look up the interface list of the specified VRF. */ -extern struct list *vrf_iflist (vrf_id_t); +extern struct list *vrf_iflist(vrf_id_t); /* Get the interface list of the specified VRF. Create one if not find. */ -extern struct list *vrf_iflist_get (vrf_id_t); +extern struct list *vrf_iflist_get(vrf_id_t); /* * VRF bit-map: maintaining flags, one bit per VRF ID */ -typedef void * vrf_bitmap_t; +typedef void *vrf_bitmap_t; #define VRF_BITMAP_NULL NULL -extern vrf_bitmap_t vrf_bitmap_init (void); -extern void vrf_bitmap_free (vrf_bitmap_t); -extern void vrf_bitmap_set (vrf_bitmap_t, vrf_id_t); -extern void vrf_bitmap_unset (vrf_bitmap_t, vrf_id_t); -extern int vrf_bitmap_check (vrf_bitmap_t, vrf_id_t); +extern vrf_bitmap_t vrf_bitmap_init(void); +extern void vrf_bitmap_free(vrf_bitmap_t); +extern void vrf_bitmap_set(vrf_bitmap_t, vrf_id_t); +extern void vrf_bitmap_unset(vrf_bitmap_t, vrf_id_t); +extern int vrf_bitmap_check(vrf_bitmap_t, vrf_id_t); /* * VRF initializer/destructor @@ -177,27 +168,24 @@ extern int vrf_bitmap_check (vrf_bitmap_t, vrf_id_t); * delete -> Called back when a vrf is being deleted from * the system ( 2 and 3 ) above. */ -extern void vrf_init (int (*create)(struct vrf *), - int (*enable)(struct vrf *), - int (*disable)(struct vrf *), - int (*delete)(struct vrf *)); +extern void vrf_init(int (*create)(struct vrf *), int (*enable)(struct vrf *), + int (*disable)(struct vrf *), int (*delete)(struct vrf *)); /* * Call vrf_terminate when the protocol is being shutdown */ -extern void vrf_terminate (void); +extern void vrf_terminate(void); -extern void vrf_cmd_init (int (*writefunc)(struct vty *vty)); +extern void vrf_cmd_init(int (*writefunc)(struct vty *vty)); /* * VRF utilities */ /* Create a socket serving for the given VRF */ -extern int vrf_socket (int, int, int, vrf_id_t); +extern int vrf_socket(int, int, int, vrf_id_t); /* * VRF Debugging */ -extern void vrf_install_commands (void); +extern void vrf_install_commands(void); #endif /*_ZEBRA_VRF_H*/ - diff --git a/lib/vrf_int.h b/lib/vrf_int.h index f0301b767..d7fe73581 100644 --- a/lib/vrf_int.h +++ b/lib/vrf_int.h @@ -42,7 +42,7 @@ * Given a newly running vrf enable it to be used * by interested routing protocols */ -extern int vrf_enable (struct vrf *); +extern int vrf_enable(struct vrf *); /* * vrf_delete @@ -50,7 +50,6 @@ extern int vrf_enable (struct vrf *); * Given a vrf that is being deleted, delete it * from interested parties */ -extern void vrf_delete (struct vrf *); +extern void vrf_delete(struct vrf *); #endif - diff --git a/lib/vty.c b/lib/vty.c index be2f2a6e5..00579550e 100644 --- a/lib/vty.c +++ b/lib/vty.c @@ -39,25 +39,24 @@ #include #include -DEFINE_MTYPE_STATIC(LIB, VTY, "VTY") +DEFINE_MTYPE_STATIC(LIB, VTY, "VTY") DEFINE_MTYPE_STATIC(LIB, VTY_OUT_BUF, "VTY output buffer") -DEFINE_MTYPE_STATIC(LIB, VTY_HIST, "VTY history") +DEFINE_MTYPE_STATIC(LIB, VTY_HIST, "VTY history") /* Vty events */ -enum event -{ - VTY_SERV, - VTY_READ, - VTY_WRITE, - VTY_TIMEOUT_RESET, +enum event { + VTY_SERV, + VTY_READ, + VTY_WRITE, + VTY_TIMEOUT_RESET, #ifdef VTYSH - VTYSH_SERV, - VTYSH_READ, - VTYSH_WRITE + VTYSH_SERV, + VTYSH_READ, + VTYSH_WRITE #endif /* VTYSH */ }; -static void vty_event (enum event, int, struct vty *); +static void vty_event(enum event, int, struct vty *); /* Extern host structure from command.c */ extern struct host host; @@ -93,223 +92,206 @@ char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG; static int do_log_commands = 0; /* VTY standard output function. */ -int -vty_out (struct vty *vty, const char *format, ...) -{ - va_list args; - int len = 0; - int size = 1024; - char buf[1024]; - char *p = NULL; - - if (vty_shell (vty)) - { - va_start (args, format); - vprintf (format, args); - va_end (args); - } - else - { - /* Try to write to initial buffer. */ - va_start (args, format); - len = vsnprintf (buf, sizeof(buf), format, args); - va_end (args); - - /* Initial buffer is not enough. */ - if (len < 0 || len >= size) - { - while (1) - { - if (len > -1) - size = len + 1; - else - size = size * 2; - - p = XREALLOC (MTYPE_VTY_OUT_BUF, p, size); - if (! p) - return -1; - - va_start (args, format); - len = vsnprintf (p, size, format, args); - va_end (args); - - if (len > -1 && len < size) - break; - } - } - - /* When initial buffer is enough to store all output. */ - if (! p) - p = buf; - - /* Pointer p must point out buffer. */ - if (vty->type != VTY_TERM) - buffer_put (vty->obuf, (u_char *) p, len); - else - buffer_put_crlf (vty->obuf, (u_char *) p, len); - - /* If p is not different with buf, it is allocated buffer. */ - if (p != buf) - XFREE (MTYPE_VTY_OUT_BUF, p); - } - - return len; -} - -static int -vty_log_out (struct vty *vty, const char *level, const char *proto_str, - const char *format, struct timestamp_control *ctl, va_list va) -{ - int ret; - int len; - char buf[1024]; - - if (!ctl->already_rendered) - { - ctl->len = quagga_timestamp(ctl->precision, ctl->buf, sizeof(ctl->buf)); - ctl->already_rendered = 1; - } - if (ctl->len+1 >= sizeof(buf)) - return -1; - memcpy(buf, ctl->buf, len = ctl->len); - buf[len++] = ' '; - buf[len] = '\0'; - - if (level) - ret = snprintf(buf+len, sizeof(buf)-len, "%s: %s: ", level, proto_str); - else - ret = snprintf(buf+len, sizeof(buf)-len, "%s: ", proto_str); - if ((ret < 0) || ((size_t)(len += ret) >= sizeof(buf))) - return -1; - - if (((ret = vsnprintf(buf+len, sizeof(buf)-len, format, va)) < 0) || - ((size_t)((len += ret)+2) > sizeof(buf))) - return -1; - - buf[len++] = '\r'; - buf[len++] = '\n'; - - if (write(vty->wfd, buf, len) < 0) - { - if (ERRNO_IO_RETRY(errno)) - /* Kernel buffer is full, probably too much debugging output, so just - drop the data and ignore. */ - return -1; - /* Fatal I/O error. */ - vty->monitor = 0; /* disable monitoring to avoid infinite recursion */ - zlog_warn("%s: write failed to vty client fd %d, closing: %s", - __func__, vty->fd, safe_strerror(errno)); - buffer_reset(vty->obuf); - /* cannot call vty_close, because a parent routine may still try - to access the vty struct */ - vty->status = VTY_CLOSE; - shutdown(vty->fd, SHUT_RDWR); - return -1; - } - return 0; +int vty_out(struct vty *vty, const char *format, ...) +{ + va_list args; + int len = 0; + int size = 1024; + char buf[1024]; + char *p = NULL; + + if (vty_shell(vty)) { + va_start(args, format); + vprintf(format, args); + va_end(args); + } else { + /* Try to write to initial buffer. */ + va_start(args, format); + len = vsnprintf(buf, sizeof(buf), format, args); + va_end(args); + + /* Initial buffer is not enough. */ + if (len < 0 || len >= size) { + while (1) { + if (len > -1) + size = len + 1; + else + size = size * 2; + + p = XREALLOC(MTYPE_VTY_OUT_BUF, p, size); + if (!p) + return -1; + + va_start(args, format); + len = vsnprintf(p, size, format, args); + va_end(args); + + if (len > -1 && len < size) + break; + } + } + + /* When initial buffer is enough to store all output. */ + if (!p) + p = buf; + + /* Pointer p must point out buffer. */ + if (vty->type != VTY_TERM) + buffer_put(vty->obuf, (u_char *)p, len); + else + buffer_put_crlf(vty->obuf, (u_char *)p, len); + + /* If p is not different with buf, it is allocated buffer. */ + if (p != buf) + XFREE(MTYPE_VTY_OUT_BUF, p); + } + + return len; +} + +static int vty_log_out(struct vty *vty, const char *level, + const char *proto_str, const char *format, + struct timestamp_control *ctl, va_list va) +{ + int ret; + int len; + char buf[1024]; + + if (!ctl->already_rendered) { + ctl->len = quagga_timestamp(ctl->precision, ctl->buf, + sizeof(ctl->buf)); + ctl->already_rendered = 1; + } + if (ctl->len + 1 >= sizeof(buf)) + return -1; + memcpy(buf, ctl->buf, len = ctl->len); + buf[len++] = ' '; + buf[len] = '\0'; + + if (level) + ret = snprintf(buf + len, sizeof(buf) - len, "%s: %s: ", level, + proto_str); + else + ret = snprintf(buf + len, sizeof(buf) - len, "%s: ", proto_str); + if ((ret < 0) || ((size_t)(len += ret) >= sizeof(buf))) + return -1; + + if (((ret = vsnprintf(buf + len, sizeof(buf) - len, format, va)) < 0) + || ((size_t)((len += ret) + 2) > sizeof(buf))) + return -1; + + buf[len++] = '\r'; + buf[len++] = '\n'; + + if (write(vty->wfd, buf, len) < 0) { + if (ERRNO_IO_RETRY(errno)) + /* Kernel buffer is full, probably too much debugging + output, so just + drop the data and ignore. */ + return -1; + /* Fatal I/O error. */ + vty->monitor = + 0; /* disable monitoring to avoid infinite recursion */ + zlog_warn("%s: write failed to vty client fd %d, closing: %s", + __func__, vty->fd, safe_strerror(errno)); + buffer_reset(vty->obuf); + /* cannot call vty_close, because a parent routine may still try + to access the vty struct */ + vty->status = VTY_CLOSE; + shutdown(vty->fd, SHUT_RDWR); + return -1; + } + return 0; } /* Output current time to the vty. */ -void -vty_time_print (struct vty *vty, int cr) +void vty_time_print(struct vty *vty, int cr) { - char buf[QUAGGA_TIMESTAMP_LEN]; + char buf[QUAGGA_TIMESTAMP_LEN]; - if (quagga_timestamp(0, buf, sizeof(buf)) == 0) - { - zlog_info("quagga_timestamp error"); - return; - } - if (cr) - vty_out (vty, "%s\n", buf); - else - vty_out (vty, "%s ", buf); + if (quagga_timestamp(0, buf, sizeof(buf)) == 0) { + zlog_info("quagga_timestamp error"); + return; + } + if (cr) + vty_out(vty, "%s\n", buf); + else + vty_out(vty, "%s ", buf); - return; + return; } /* Say hello to vty interface. */ -void -vty_hello (struct vty *vty) -{ - if (host.motdfile) - { - FILE *f; - char buf[4096]; - - f = fopen (host.motdfile, "r"); - if (f) - { - while (fgets (buf, sizeof (buf), f)) - { - char *s; - /* work backwards to ignore trailling isspace() */ - for (s = buf + strlen (buf); (s > buf) && isspace ((int)*(s - 1)); - s--); - *s = '\0'; - vty_out (vty, "%s\n", buf); - } - fclose (f); - } - else - vty_out (vty, "MOTD file not found\n"); - } - else if (host.motd) - vty_out (vty, "%s", host.motd); +void vty_hello(struct vty *vty) +{ + if (host.motdfile) { + FILE *f; + char buf[4096]; + + f = fopen(host.motdfile, "r"); + if (f) { + while (fgets(buf, sizeof(buf), f)) { + char *s; + /* work backwards to ignore trailling isspace() + */ + for (s = buf + strlen(buf); + (s > buf) && isspace((int)*(s - 1)); s--) + ; + *s = '\0'; + vty_out(vty, "%s\n", buf); + } + fclose(f); + } else + vty_out(vty, "MOTD file not found\n"); + } else if (host.motd) + vty_out(vty, "%s", host.motd); } /* Put out prompt and wait input from user. */ -static void -vty_prompt (struct vty *vty) +static void vty_prompt(struct vty *vty) { - struct utsname names; - const char*hostname; + struct utsname names; + const char *hostname; - if (vty->type == VTY_TERM) - { - hostname = host.name; - if (!hostname) - { - uname (&names); - hostname = names.nodename; - } - vty_out (vty, cmd_prompt (vty->node), hostname); - } + if (vty->type == VTY_TERM) { + hostname = host.name; + if (!hostname) { + uname(&names); + hostname = names.nodename; + } + vty_out(vty, cmd_prompt(vty->node), hostname); + } } /* Send WILL TELOPT_ECHO to remote server. */ -static void -vty_will_echo (struct vty *vty) +static void vty_will_echo(struct vty *vty) { - unsigned char cmd[] = { IAC, WILL, TELOPT_ECHO, '\0' }; - vty_out (vty, "%s", cmd); + unsigned char cmd[] = {IAC, WILL, TELOPT_ECHO, '\0'}; + vty_out(vty, "%s", cmd); } /* Make suppress Go-Ahead telnet option. */ -static void -vty_will_suppress_go_ahead (struct vty *vty) +static void vty_will_suppress_go_ahead(struct vty *vty) { - unsigned char cmd[] = { IAC, WILL, TELOPT_SGA, '\0' }; - vty_out (vty, "%s", cmd); + unsigned char cmd[] = {IAC, WILL, TELOPT_SGA, '\0'}; + vty_out(vty, "%s", cmd); } /* Make don't use linemode over telnet. */ -static void -vty_dont_linemode (struct vty *vty) +static void vty_dont_linemode(struct vty *vty) { - unsigned char cmd[] = { IAC, DONT, TELOPT_LINEMODE, '\0' }; - vty_out (vty, "%s", cmd); + unsigned char cmd[] = {IAC, DONT, TELOPT_LINEMODE, '\0'}; + vty_out(vty, "%s", cmd); } /* Use window size. */ -static void -vty_do_window_size (struct vty *vty) +static void vty_do_window_size(struct vty *vty) { - unsigned char cmd[] = { IAC, DO, TELOPT_NAWS, '\0' }; - vty_out (vty, "%s", cmd); + unsigned char cmd[] = {IAC, DO, TELOPT_NAWS, '\0'}; + vty_out(vty, "%s", cmd); } -#if 0 /* Currently not used. */ +#if 0 /* Currently not used. */ /* Make don't use lflow vty interface. */ static void vty_dont_lflow_ahead (struct vty *vty) @@ -320,230 +302,214 @@ vty_dont_lflow_ahead (struct vty *vty) #endif /* 0 */ /* Allocate new vty struct. */ -struct vty * -vty_new () +struct vty *vty_new() { - struct vty *new = XCALLOC (MTYPE_VTY, sizeof (struct vty)); + struct vty *new = XCALLOC(MTYPE_VTY, sizeof(struct vty)); - new->obuf = buffer_new(0); /* Use default buffer size. */ - new->buf = XCALLOC (MTYPE_VTY, VTY_BUFSIZ); - new->error_buf = XCALLOC (MTYPE_VTY, VTY_BUFSIZ); - new->max = VTY_BUFSIZ; + new->obuf = buffer_new(0); /* Use default buffer size. */ + new->buf = XCALLOC(MTYPE_VTY, VTY_BUFSIZ); + new->error_buf = XCALLOC(MTYPE_VTY, VTY_BUFSIZ); + new->max = VTY_BUFSIZ; - return new; + return new; } /* Authentication of vty */ -static void -vty_auth (struct vty *vty, char *buf) -{ - char *passwd = NULL; - enum node_type next_node = 0; - int fail; - char *crypt (const char *, const char *); - - switch (vty->node) - { - case AUTH_NODE: - if (host.encrypt) - passwd = host.password_encrypt; - else - passwd = host.password; - if (host.advanced) - next_node = host.enable ? VIEW_NODE : ENABLE_NODE; - else - next_node = VIEW_NODE; - break; - case AUTH_ENABLE_NODE: - if (host.encrypt) - passwd = host.enable_encrypt; - else - passwd = host.enable; - next_node = ENABLE_NODE; - break; - } - - if (passwd) - { - if (host.encrypt) - fail = strcmp (crypt(buf, passwd), passwd); - else - fail = strcmp (buf, passwd); - } - else - fail = 1; - - if (! fail) - { - vty->fail = 0; - vty->node = next_node; /* Success ! */ - } - else - { - vty->fail++; - if (vty->fail >= 3) - { - if (vty->node == AUTH_NODE) - { - vty_out (vty, "%% Bad passwords, too many failures!\n"); - vty->status = VTY_CLOSE; - } - else - { - /* AUTH_ENABLE_NODE */ - vty->fail = 0; - vty_out (vty, "%% Bad enable passwords, too many failures!\n"); - vty->status = VTY_CLOSE; - } - } - } +static void vty_auth(struct vty *vty, char *buf) +{ + char *passwd = NULL; + enum node_type next_node = 0; + int fail; + char *crypt(const char *, const char *); + + switch (vty->node) { + case AUTH_NODE: + if (host.encrypt) + passwd = host.password_encrypt; + else + passwd = host.password; + if (host.advanced) + next_node = host.enable ? VIEW_NODE : ENABLE_NODE; + else + next_node = VIEW_NODE; + break; + case AUTH_ENABLE_NODE: + if (host.encrypt) + passwd = host.enable_encrypt; + else + passwd = host.enable; + next_node = ENABLE_NODE; + break; + } + + if (passwd) { + if (host.encrypt) + fail = strcmp(crypt(buf, passwd), passwd); + else + fail = strcmp(buf, passwd); + } else + fail = 1; + + if (!fail) { + vty->fail = 0; + vty->node = next_node; /* Success ! */ + } else { + vty->fail++; + if (vty->fail >= 3) { + if (vty->node == AUTH_NODE) { + vty_out(vty, + "%% Bad passwords, too many failures!\n"); + vty->status = VTY_CLOSE; + } else { + /* AUTH_ENABLE_NODE */ + vty->fail = 0; + vty_out(vty, + "%% Bad enable passwords, too many failures!\n"); + vty->status = VTY_CLOSE; + } + } + } } /* Command execution over the vty interface. */ -static int -vty_command (struct vty *vty, char *buf) -{ - int ret; - vector vline; - const char *protocolname; - char *cp = NULL; - - /* - * Log non empty command lines - */ - if (do_log_commands) - cp = buf; - if (cp != NULL) - { - /* Skip white spaces. */ - while (isspace ((int) *cp) && *cp != '\0') - cp++; - } - if (cp != NULL && *cp != '\0') - { - unsigned i; - char vty_str[VTY_BUFSIZ]; - char prompt_str[VTY_BUFSIZ]; - - /* format the base vty info */ - snprintf(vty_str, sizeof(vty_str), "vty[??]@%s", vty->address); - if (vty) - for (i = 0; i < vector_active (vtyvec); i++) - if (vty == vector_slot (vtyvec, i)) - { - snprintf(vty_str, sizeof(vty_str), "vty[%d]@%s", - i, vty->address); - break; - } - - /* format the prompt */ - snprintf(prompt_str, sizeof(prompt_str), cmd_prompt (vty->node), vty_str); - - /* now log the command */ - zlog_err("%s%s", prompt_str, buf); - } - /* Split readline string up into the vector */ - vline = cmd_make_strvec (buf); - - if (vline == NULL) - return CMD_SUCCESS; +static int vty_command(struct vty *vty, char *buf) +{ + int ret; + vector vline; + const char *protocolname; + char *cp = NULL; + + /* + * Log non empty command lines + */ + if (do_log_commands) + cp = buf; + if (cp != NULL) { + /* Skip white spaces. */ + while (isspace((int)*cp) && *cp != '\0') + cp++; + } + if (cp != NULL && *cp != '\0') { + unsigned i; + char vty_str[VTY_BUFSIZ]; + char prompt_str[VTY_BUFSIZ]; + + /* format the base vty info */ + snprintf(vty_str, sizeof(vty_str), "vty[??]@%s", vty->address); + if (vty) + for (i = 0; i < vector_active(vtyvec); i++) + if (vty == vector_slot(vtyvec, i)) { + snprintf(vty_str, sizeof(vty_str), + "vty[%d]@%s", i, vty->address); + break; + } + + /* format the prompt */ + snprintf(prompt_str, sizeof(prompt_str), cmd_prompt(vty->node), + vty_str); + + /* now log the command */ + zlog_err("%s%s", prompt_str, buf); + } + /* Split readline string up into the vector */ + vline = cmd_make_strvec(buf); + + if (vline == NULL) + return CMD_SUCCESS; #ifdef CONSUMED_TIME_CHECK - { - RUSAGE_T before; - RUSAGE_T after; - unsigned long realtime, cputime; + { + RUSAGE_T before; + RUSAGE_T after; + unsigned long realtime, cputime; - GETRUSAGE(&before); + GETRUSAGE(&before); #endif /* CONSUMED_TIME_CHECK */ - ret = cmd_execute_command (vline, vty, NULL, 0); + ret = cmd_execute_command(vline, vty, NULL, 0); - /* Get the name of the protocol if any */ - protocolname = frr_protoname; + /* Get the name of the protocol if any */ + protocolname = frr_protoname; #ifdef CONSUMED_TIME_CHECK - GETRUSAGE(&after); - if ((realtime = thread_consumed_time(&after, &before, &cputime)) > - CONSUMED_TIME_CHECK) - /* Warn about CPU hog that must be fixed. */ - zlog_warn("SLOW COMMAND: command took %lums (cpu time %lums): %s", - realtime/1000, cputime/1000, buf); - } + GETRUSAGE(&after); + if ((realtime = thread_consumed_time(&after, &before, &cputime)) + > CONSUMED_TIME_CHECK) + /* Warn about CPU hog that must be fixed. */ + zlog_warn( + "SLOW COMMAND: command took %lums (cpu time %lums): %s", + realtime / 1000, cputime / 1000, buf); + } #endif /* CONSUMED_TIME_CHECK */ - if (ret != CMD_SUCCESS) - switch (ret) - { - case CMD_WARNING: - if (vty->type == VTY_FILE) - vty_out (vty, "Warning...\n"); - break; - case CMD_ERR_AMBIGUOUS: - vty_out (vty, "%% Ambiguous command.\n"); - break; - case CMD_ERR_NO_MATCH: - vty_out (vty, "%% [%s] Unknown command: %s\n", protocolname, buf); - break; - case CMD_ERR_INCOMPLETE: - vty_out (vty, "%% Command incomplete.\n"); - break; - } - cmd_free_strvec (vline); - - return ret; + if (ret != CMD_SUCCESS) + switch (ret) { + case CMD_WARNING: + if (vty->type == VTY_FILE) + vty_out(vty, "Warning...\n"); + break; + case CMD_ERR_AMBIGUOUS: + vty_out(vty, "%% Ambiguous command.\n"); + break; + case CMD_ERR_NO_MATCH: + vty_out(vty, "%% [%s] Unknown command: %s\n", + protocolname, buf); + break; + case CMD_ERR_INCOMPLETE: + vty_out(vty, "%% Command incomplete.\n"); + break; + } + cmd_free_strvec(vline); + + return ret; } static const char telnet_backward_char = 0x08; static const char telnet_space_char = ' '; /* Basic function to write buffer to vty. */ -static void -vty_write (struct vty *vty, const char *buf, size_t nbytes) +static void vty_write(struct vty *vty, const char *buf, size_t nbytes) { - if ((vty->node == AUTH_NODE) || (vty->node == AUTH_ENABLE_NODE)) - return; + if ((vty->node == AUTH_NODE) || (vty->node == AUTH_ENABLE_NODE)) + return; - /* Should we do buffering here ? And make vty_flush (vty) ? */ - buffer_put (vty->obuf, buf, nbytes); + /* Should we do buffering here ? And make vty_flush (vty) ? */ + buffer_put(vty->obuf, buf, nbytes); } /* Basic function to insert character into vty. */ -static void -vty_self_insert (struct vty *vty, char c) +static void vty_self_insert(struct vty *vty, char c) { - int i; - int length; + int i; + int length; - if (vty->length + 1 >= VTY_BUFSIZ) - return; + if (vty->length + 1 >= VTY_BUFSIZ) + return; - length = vty->length - vty->cp; - memmove (&vty->buf[vty->cp + 1], &vty->buf[vty->cp], length); - vty->buf[vty->cp] = c; + length = vty->length - vty->cp; + memmove(&vty->buf[vty->cp + 1], &vty->buf[vty->cp], length); + vty->buf[vty->cp] = c; - vty_write (vty, &vty->buf[vty->cp], length + 1); - for (i = 0; i < length; i++) - vty_write (vty, &telnet_backward_char, 1); + vty_write(vty, &vty->buf[vty->cp], length + 1); + for (i = 0; i < length; i++) + vty_write(vty, &telnet_backward_char, 1); - vty->cp++; - vty->length++; + vty->cp++; + vty->length++; - vty->buf[vty->length] = '\0'; + vty->buf[vty->length] = '\0'; } /* Self insert character 'c' in overwrite mode. */ -static void -vty_self_insert_overwrite (struct vty *vty, char c) +static void vty_self_insert_overwrite(struct vty *vty, char c) { - if (vty->cp == vty->length) - { - vty_self_insert (vty, c); - return; - } + if (vty->cp == vty->length) { + vty_self_insert(vty, c); + return; + } - vty->buf[vty->cp++] = c; - vty_write (vty, &c, 1); + vty->buf[vty->cp++] = c; + vty_write(vty, &c, 1); } /** @@ -552,828 +518,773 @@ vty_self_insert_overwrite (struct vty *vty, char c) * If the resultant string would be larger than VTY_BUFSIZ it is * truncated to fit. */ -static void -vty_insert_word_overwrite (struct vty *vty, char *str) +static void vty_insert_word_overwrite(struct vty *vty, char *str) { - if (vty->cp == VTY_BUFSIZ) - return; + if (vty->cp == VTY_BUFSIZ) + return; - size_t nwrite = MIN ((int) strlen (str), VTY_BUFSIZ - vty->cp - 1); - memcpy (&vty->buf[vty->cp], str, nwrite); - vty->cp += nwrite; - vty->length = MAX (vty->cp, vty->length); - vty->buf[vty->length] = '\0'; - vty_write (vty, str, nwrite); + size_t nwrite = MIN((int)strlen(str), VTY_BUFSIZ - vty->cp - 1); + memcpy(&vty->buf[vty->cp], str, nwrite); + vty->cp += nwrite; + vty->length = MAX(vty->cp, vty->length); + vty->buf[vty->length] = '\0'; + vty_write(vty, str, nwrite); } /* Forward character. */ -static void -vty_forward_char (struct vty *vty) +static void vty_forward_char(struct vty *vty) { - if (vty->cp < vty->length) - { - vty_write (vty, &vty->buf[vty->cp], 1); - vty->cp++; - } + if (vty->cp < vty->length) { + vty_write(vty, &vty->buf[vty->cp], 1); + vty->cp++; + } } /* Backward character. */ -static void -vty_backward_char (struct vty *vty) +static void vty_backward_char(struct vty *vty) { - if (vty->cp > 0) - { - vty->cp--; - vty_write (vty, &telnet_backward_char, 1); - } + if (vty->cp > 0) { + vty->cp--; + vty_write(vty, &telnet_backward_char, 1); + } } /* Move to the beginning of the line. */ -static void -vty_beginning_of_line (struct vty *vty) +static void vty_beginning_of_line(struct vty *vty) { - while (vty->cp) - vty_backward_char (vty); + while (vty->cp) + vty_backward_char(vty); } /* Move to the end of the line. */ -static void -vty_end_of_line (struct vty *vty) +static void vty_end_of_line(struct vty *vty) { - while (vty->cp < vty->length) - vty_forward_char (vty); + while (vty->cp < vty->length) + vty_forward_char(vty); } -static void vty_kill_line_from_beginning (struct vty *); -static void vty_redraw_line (struct vty *); +static void vty_kill_line_from_beginning(struct vty *); +static void vty_redraw_line(struct vty *); /* Print command line history. This function is called from vty_next_line and vty_previous_line. */ -static void -vty_history_print (struct vty *vty) +static void vty_history_print(struct vty *vty) { - int length; + int length; - vty_kill_line_from_beginning (vty); + vty_kill_line_from_beginning(vty); - /* Get previous line from history buffer */ - length = strlen (vty->hist[vty->hp]); - memcpy (vty->buf, vty->hist[vty->hp], length); - vty->cp = vty->length = length; - vty->buf[vty->length] = '\0'; + /* Get previous line from history buffer */ + length = strlen(vty->hist[vty->hp]); + memcpy(vty->buf, vty->hist[vty->hp], length); + vty->cp = vty->length = length; + vty->buf[vty->length] = '\0'; - /* Redraw current line */ - vty_redraw_line (vty); + /* Redraw current line */ + vty_redraw_line(vty); } /* Show next command line history. */ -static void -vty_next_line (struct vty *vty) +static void vty_next_line(struct vty *vty) { - int try_index; + int try_index; - if (vty->hp == vty->hindex) - return; + if (vty->hp == vty->hindex) + return; - /* Try is there history exist or not. */ - try_index = vty->hp; - if (try_index == (VTY_MAXHIST - 1)) - try_index = 0; - else - try_index++; + /* Try is there history exist or not. */ + try_index = vty->hp; + if (try_index == (VTY_MAXHIST - 1)) + try_index = 0; + else + try_index++; - /* If there is not history return. */ - if (vty->hist[try_index] == NULL) - return; - else - vty->hp = try_index; + /* If there is not history return. */ + if (vty->hist[try_index] == NULL) + return; + else + vty->hp = try_index; - vty_history_print (vty); + vty_history_print(vty); } /* Show previous command line history. */ -static void -vty_previous_line (struct vty *vty) +static void vty_previous_line(struct vty *vty) { - int try_index; + int try_index; - try_index = vty->hp; - if (try_index == 0) - try_index = VTY_MAXHIST - 1; - else - try_index--; + try_index = vty->hp; + if (try_index == 0) + try_index = VTY_MAXHIST - 1; + else + try_index--; - if (vty->hist[try_index] == NULL) - return; - else - vty->hp = try_index; + if (vty->hist[try_index] == NULL) + return; + else + vty->hp = try_index; - vty_history_print (vty); + vty_history_print(vty); } /* This function redraw all of the command line character. */ -static void -vty_redraw_line (struct vty *vty) +static void vty_redraw_line(struct vty *vty) { - vty_write (vty, vty->buf, vty->length); - vty->cp = vty->length; + vty_write(vty, vty->buf, vty->length); + vty->cp = vty->length; } /* Forward word. */ -static void -vty_forward_word (struct vty *vty) +static void vty_forward_word(struct vty *vty) { - while (vty->cp != vty->length && vty->buf[vty->cp] != ' ') - vty_forward_char (vty); + while (vty->cp != vty->length && vty->buf[vty->cp] != ' ') + vty_forward_char(vty); - while (vty->cp != vty->length && vty->buf[vty->cp] == ' ') - vty_forward_char (vty); + while (vty->cp != vty->length && vty->buf[vty->cp] == ' ') + vty_forward_char(vty); } /* Backward word without skipping training space. */ -static void -vty_backward_pure_word (struct vty *vty) +static void vty_backward_pure_word(struct vty *vty) { - while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ') - vty_backward_char (vty); + while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ') + vty_backward_char(vty); } /* Backward word. */ -static void -vty_backward_word (struct vty *vty) +static void vty_backward_word(struct vty *vty) { - while (vty->cp > 0 && vty->buf[vty->cp - 1] == ' ') - vty_backward_char (vty); + while (vty->cp > 0 && vty->buf[vty->cp - 1] == ' ') + vty_backward_char(vty); - while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ') - vty_backward_char (vty); + while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ') + vty_backward_char(vty); } /* When '^D' is typed at the beginning of the line we move to the down level. */ -static void -vty_down_level (struct vty *vty) +static void vty_down_level(struct vty *vty) { - vty_out (vty, "\n"); - cmd_exit (vty); - vty_prompt (vty); - vty->cp = 0; + vty_out(vty, "\n"); + cmd_exit(vty); + vty_prompt(vty); + vty->cp = 0; } /* When '^Z' is received from vty, move down to the enable mode. */ -static void -vty_end_config (struct vty *vty) -{ - vty_out (vty, "\n"); - - switch (vty->node) - { - case VIEW_NODE: - case ENABLE_NODE: - /* Nothing to do. */ - break; - case CONFIG_NODE: - case INTERFACE_NODE: - case ZEBRA_NODE: - case RIP_NODE: - case RIPNG_NODE: - case EIGRP_NODE: - case BGP_NODE: - case BGP_VPNV4_NODE: - case BGP_VPNV6_NODE: - case BGP_VRF_POLICY_NODE: - case BGP_VNC_DEFAULTS_NODE: - case BGP_VNC_NVE_GROUP_NODE: - case BGP_VNC_L2_GROUP_NODE: - case BGP_IPV4_NODE: - case BGP_IPV4M_NODE: - case BGP_IPV4L_NODE: - case BGP_IPV6_NODE: - case BGP_IPV6M_NODE: - case BGP_EVPN_NODE: - case BGP_IPV6L_NODE: - case RMAP_NODE: - case OSPF_NODE: - case OSPF6_NODE: - case LDP_NODE: - case LDP_IPV4_NODE: - case LDP_IPV6_NODE: - case LDP_IPV4_IFACE_NODE: - case LDP_IPV6_IFACE_NODE: - case LDP_L2VPN_NODE: - case LDP_PSEUDOWIRE_NODE: - case ISIS_NODE: - case KEYCHAIN_NODE: - case KEYCHAIN_KEY_NODE: - case MASC_NODE: - case PIM_NODE: - case VTY_NODE: - case BGP_EVPN_VNI_NODE: - vty_config_unlock (vty); - vty->node = ENABLE_NODE; - break; - default: - /* Unknown node, we have to ignore it. */ - break; - } - - vty_prompt (vty); - vty->cp = 0; +static void vty_end_config(struct vty *vty) +{ + vty_out(vty, "\n"); + + switch (vty->node) { + case VIEW_NODE: + case ENABLE_NODE: + /* Nothing to do. */ + break; + case CONFIG_NODE: + case INTERFACE_NODE: + case ZEBRA_NODE: + case RIP_NODE: + case RIPNG_NODE: + case EIGRP_NODE: + case BGP_NODE: + case BGP_VPNV4_NODE: + case BGP_VPNV6_NODE: + case BGP_VRF_POLICY_NODE: + case BGP_VNC_DEFAULTS_NODE: + case BGP_VNC_NVE_GROUP_NODE: + case BGP_VNC_L2_GROUP_NODE: + case BGP_IPV4_NODE: + case BGP_IPV4M_NODE: + case BGP_IPV4L_NODE: + case BGP_IPV6_NODE: + case BGP_IPV6M_NODE: + case BGP_EVPN_NODE: + case BGP_IPV6L_NODE: + case RMAP_NODE: + case OSPF_NODE: + case OSPF6_NODE: + case LDP_NODE: + case LDP_IPV4_NODE: + case LDP_IPV6_NODE: + case LDP_IPV4_IFACE_NODE: + case LDP_IPV6_IFACE_NODE: + case LDP_L2VPN_NODE: + case LDP_PSEUDOWIRE_NODE: + case ISIS_NODE: + case KEYCHAIN_NODE: + case KEYCHAIN_KEY_NODE: + case MASC_NODE: + case PIM_NODE: + case VTY_NODE: + case BGP_EVPN_VNI_NODE: + vty_config_unlock(vty); + vty->node = ENABLE_NODE; + break; + default: + /* Unknown node, we have to ignore it. */ + break; + } + + vty_prompt(vty); + vty->cp = 0; } /* Delete a charcter at the current point. */ -static void -vty_delete_char (struct vty *vty) +static void vty_delete_char(struct vty *vty) { - int i; - int size; + int i; + int size; - if (vty->length == 0) - { - vty_down_level (vty); - return; - } + if (vty->length == 0) { + vty_down_level(vty); + return; + } - if (vty->cp == vty->length) - return; /* completion need here? */ + if (vty->cp == vty->length) + return; /* completion need here? */ - size = vty->length - vty->cp; + size = vty->length - vty->cp; - vty->length--; - memmove (&vty->buf[vty->cp], &vty->buf[vty->cp + 1], size - 1); - vty->buf[vty->length] = '\0'; + vty->length--; + memmove(&vty->buf[vty->cp], &vty->buf[vty->cp + 1], size - 1); + vty->buf[vty->length] = '\0'; - if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE) - return; + if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE) + return; - vty_write (vty, &vty->buf[vty->cp], size - 1); - vty_write (vty, &telnet_space_char, 1); + vty_write(vty, &vty->buf[vty->cp], size - 1); + vty_write(vty, &telnet_space_char, 1); - for (i = 0; i < size; i++) - vty_write (vty, &telnet_backward_char, 1); + for (i = 0; i < size; i++) + vty_write(vty, &telnet_backward_char, 1); } /* Delete a character before the point. */ -static void -vty_delete_backward_char (struct vty *vty) +static void vty_delete_backward_char(struct vty *vty) { - if (vty->cp == 0) - return; + if (vty->cp == 0) + return; - vty_backward_char (vty); - vty_delete_char (vty); + vty_backward_char(vty); + vty_delete_char(vty); } /* Kill rest of line from current point. */ -static void -vty_kill_line (struct vty *vty) +static void vty_kill_line(struct vty *vty) { - int i; - int size; + int i; + int size; - size = vty->length - vty->cp; + size = vty->length - vty->cp; - if (size == 0) - return; + if (size == 0) + return; - for (i = 0; i < size; i++) - vty_write (vty, &telnet_space_char, 1); - for (i = 0; i < size; i++) - vty_write (vty, &telnet_backward_char, 1); + for (i = 0; i < size; i++) + vty_write(vty, &telnet_space_char, 1); + for (i = 0; i < size; i++) + vty_write(vty, &telnet_backward_char, 1); - memset (&vty->buf[vty->cp], 0, size); - vty->length = vty->cp; + memset(&vty->buf[vty->cp], 0, size); + vty->length = vty->cp; } /* Kill line from the beginning. */ -static void -vty_kill_line_from_beginning (struct vty *vty) +static void vty_kill_line_from_beginning(struct vty *vty) { - vty_beginning_of_line (vty); - vty_kill_line (vty); + vty_beginning_of_line(vty); + vty_kill_line(vty); } /* Delete a word before the point. */ -static void -vty_forward_kill_word (struct vty *vty) +static void vty_forward_kill_word(struct vty *vty) { - while (vty->cp != vty->length && vty->buf[vty->cp] == ' ') - vty_delete_char (vty); - while (vty->cp != vty->length && vty->buf[vty->cp] != ' ') - vty_delete_char (vty); + while (vty->cp != vty->length && vty->buf[vty->cp] == ' ') + vty_delete_char(vty); + while (vty->cp != vty->length && vty->buf[vty->cp] != ' ') + vty_delete_char(vty); } /* Delete a word before the point. */ -static void -vty_backward_kill_word (struct vty *vty) +static void vty_backward_kill_word(struct vty *vty) { - while (vty->cp > 0 && vty->buf[vty->cp - 1] == ' ') - vty_delete_backward_char (vty); - while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ') - vty_delete_backward_char (vty); + while (vty->cp > 0 && vty->buf[vty->cp - 1] == ' ') + vty_delete_backward_char(vty); + while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ') + vty_delete_backward_char(vty); } /* Transpose chars before or at the point. */ -static void -vty_transpose_chars (struct vty *vty) +static void vty_transpose_chars(struct vty *vty) { - char c1, c2; + char c1, c2; - /* If length is short or point is near by the beginning of line then - return. */ - if (vty->length < 2 || vty->cp < 1) - return; + /* If length is short or point is near by the beginning of line then + return. */ + if (vty->length < 2 || vty->cp < 1) + return; - /* In case of point is located at the end of the line. */ - if (vty->cp == vty->length) - { - c1 = vty->buf[vty->cp - 1]; - c2 = vty->buf[vty->cp - 2]; + /* In case of point is located at the end of the line. */ + if (vty->cp == vty->length) { + c1 = vty->buf[vty->cp - 1]; + c2 = vty->buf[vty->cp - 2]; - vty_backward_char (vty); - vty_backward_char (vty); - vty_self_insert_overwrite (vty, c1); - vty_self_insert_overwrite (vty, c2); - } - else - { - c1 = vty->buf[vty->cp]; - c2 = vty->buf[vty->cp - 1]; + vty_backward_char(vty); + vty_backward_char(vty); + vty_self_insert_overwrite(vty, c1); + vty_self_insert_overwrite(vty, c2); + } else { + c1 = vty->buf[vty->cp]; + c2 = vty->buf[vty->cp - 1]; - vty_backward_char (vty); - vty_self_insert_overwrite (vty, c1); - vty_self_insert_overwrite (vty, c2); - } + vty_backward_char(vty); + vty_self_insert_overwrite(vty, c1); + vty_self_insert_overwrite(vty, c2); + } } /* Do completion at vty interface. */ -static void -vty_complete_command (struct vty *vty) -{ - int i; - int ret; - char **matched = NULL; - vector vline; - - if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE) - return; - - vline = cmd_make_strvec (vty->buf); - if (vline == NULL) - return; - - /* In case of 'help \t'. */ - if (isspace ((int) vty->buf[vty->length - 1])) - vector_set (vline, NULL); - - matched = cmd_complete_command (vline, vty, &ret); - - cmd_free_strvec (vline); - - vty_out (vty, "\n"); - switch (ret) - { - case CMD_ERR_AMBIGUOUS: - vty_out (vty, "%% Ambiguous command.\n"); - vty_prompt (vty); - vty_redraw_line (vty); - break; - case CMD_ERR_NO_MATCH: - /* vty_out (vty, "%% There is no matched command.\n"); */ - vty_prompt (vty); - vty_redraw_line (vty); - break; - case CMD_COMPLETE_FULL_MATCH: - if (!matched[0]) - { - /* 2016-11-28 equinox -- need to debug, SEGV here */ - vty_out (vty, "%% CLI BUG: FULL_MATCH with NULL str\n"); - vty_prompt (vty); - vty_redraw_line (vty); - break; - } - vty_prompt (vty); - vty_redraw_line (vty); - vty_backward_pure_word (vty); - vty_insert_word_overwrite (vty, matched[0]); - vty_self_insert (vty, ' '); - XFREE (MTYPE_COMPLETION, matched[0]); - break; - case CMD_COMPLETE_MATCH: - vty_prompt (vty); - vty_redraw_line (vty); - vty_backward_pure_word (vty); - vty_insert_word_overwrite (vty, matched[0]); - XFREE (MTYPE_COMPLETION, matched[0]); - break; - case CMD_COMPLETE_LIST_MATCH: - for (i = 0; matched[i] != NULL; i++) - { - if (i != 0 && ((i % 6) == 0)) - vty_out (vty, "\n"); - vty_out (vty, "%-10s ", matched[i]); - XFREE (MTYPE_COMPLETION, matched[i]); - } - vty_out (vty, "\n"); - - vty_prompt (vty); - vty_redraw_line (vty); - break; - case CMD_ERR_NOTHING_TODO: - vty_prompt (vty); - vty_redraw_line (vty); - break; - default: - break; - } - if (matched) - XFREE (MTYPE_TMP, matched); -} - -static void -vty_describe_fold (struct vty *vty, int cmd_width, - unsigned int desc_width, struct cmd_token *token) -{ - char *buf; - const char *cmd, *p; - int pos; - - cmd = token->text; - - if (desc_width <= 0) - { - vty_out (vty, " %-*s %s\n", cmd_width, cmd, token->desc); - return; - } - - buf = XCALLOC (MTYPE_TMP, strlen (token->desc) + 1); - - for (p = token->desc; strlen (p) > desc_width; p += pos + 1) - { - for (pos = desc_width; pos > 0; pos--) - if (*(p + pos) == ' ') - break; - - if (pos == 0) - break; - - strncpy (buf, p, pos); - buf[pos] = '\0'; - vty_out (vty, " %-*s %s\n", cmd_width, cmd, buf); - - cmd = ""; - } - - vty_out (vty, " %-*s %s\n", cmd_width, cmd, p); - - XFREE (MTYPE_TMP, buf); +static void vty_complete_command(struct vty *vty) +{ + int i; + int ret; + char **matched = NULL; + vector vline; + + if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE) + return; + + vline = cmd_make_strvec(vty->buf); + if (vline == NULL) + return; + + /* In case of 'help \t'. */ + if (isspace((int)vty->buf[vty->length - 1])) + vector_set(vline, NULL); + + matched = cmd_complete_command(vline, vty, &ret); + + cmd_free_strvec(vline); + + vty_out(vty, "\n"); + switch (ret) { + case CMD_ERR_AMBIGUOUS: + vty_out(vty, "%% Ambiguous command.\n"); + vty_prompt(vty); + vty_redraw_line(vty); + break; + case CMD_ERR_NO_MATCH: + /* vty_out (vty, "%% There is no matched command.\n"); */ + vty_prompt(vty); + vty_redraw_line(vty); + break; + case CMD_COMPLETE_FULL_MATCH: + if (!matched[0]) { + /* 2016-11-28 equinox -- need to debug, SEGV here */ + vty_out(vty, "%% CLI BUG: FULL_MATCH with NULL str\n"); + vty_prompt(vty); + vty_redraw_line(vty); + break; + } + vty_prompt(vty); + vty_redraw_line(vty); + vty_backward_pure_word(vty); + vty_insert_word_overwrite(vty, matched[0]); + vty_self_insert(vty, ' '); + XFREE(MTYPE_COMPLETION, matched[0]); + break; + case CMD_COMPLETE_MATCH: + vty_prompt(vty); + vty_redraw_line(vty); + vty_backward_pure_word(vty); + vty_insert_word_overwrite(vty, matched[0]); + XFREE(MTYPE_COMPLETION, matched[0]); + break; + case CMD_COMPLETE_LIST_MATCH: + for (i = 0; matched[i] != NULL; i++) { + if (i != 0 && ((i % 6) == 0)) + vty_out(vty, "\n"); + vty_out(vty, "%-10s ", matched[i]); + XFREE(MTYPE_COMPLETION, matched[i]); + } + vty_out(vty, "\n"); + + vty_prompt(vty); + vty_redraw_line(vty); + break; + case CMD_ERR_NOTHING_TODO: + vty_prompt(vty); + vty_redraw_line(vty); + break; + default: + break; + } + if (matched) + XFREE(MTYPE_TMP, matched); +} + +static void vty_describe_fold(struct vty *vty, int cmd_width, + unsigned int desc_width, struct cmd_token *token) +{ + char *buf; + const char *cmd, *p; + int pos; + + cmd = token->text; + + if (desc_width <= 0) { + vty_out(vty, " %-*s %s\n", cmd_width, cmd, token->desc); + return; + } + + buf = XCALLOC(MTYPE_TMP, strlen(token->desc) + 1); + + for (p = token->desc; strlen(p) > desc_width; p += pos + 1) { + for (pos = desc_width; pos > 0; pos--) + if (*(p + pos) == ' ') + break; + + if (pos == 0) + break; + + strncpy(buf, p, pos); + buf[pos] = '\0'; + vty_out(vty, " %-*s %s\n", cmd_width, cmd, buf); + + cmd = ""; + } + + vty_out(vty, " %-*s %s\n", cmd_width, cmd, p); + + XFREE(MTYPE_TMP, buf); } /* Describe matched command function. */ -static void -vty_describe_command (struct vty *vty) -{ - int ret; - vector vline; - vector describe; - unsigned int i, width, desc_width; - struct cmd_token *token, *token_cr = NULL; - - vline = cmd_make_strvec (vty->buf); - - /* In case of '> ?'. */ - if (vline == NULL) - { - vline = vector_init (1); - vector_set (vline, NULL); - } - else - if (isspace ((int) vty->buf[vty->length - 1])) - vector_set (vline, NULL); - - describe = cmd_describe_command (vline, vty, &ret); - - vty_out (vty, "\n"); - - /* Ambiguous error. */ - switch (ret) - { - case CMD_ERR_AMBIGUOUS: - vty_out (vty, "%% Ambiguous command.\n"); - goto out; - break; - case CMD_ERR_NO_MATCH: - vty_out (vty, "%% There is no matched command.\n"); - goto out; - break; - } - - /* Get width of command string. */ - width = 0; - for (i = 0; i < vector_active (describe); i++) - if ((token = vector_slot (describe, i)) != NULL) - { - unsigned int len; - - if (token->text[0] == '\0') - continue; - - len = strlen (token->text); - - if (width < len) - width = len; - } - - /* Get width of description string. */ - desc_width = vty->width - (width + 6); - - /* Print out description. */ - for (i = 0; i < vector_active (describe); i++) - if ((token = vector_slot (describe, i)) != NULL) - { - if (token->text[0] == '\0') - continue; - - if (strcmp (token->text, CMD_CR_TEXT) == 0) - { - token_cr = token; - continue; - } - - if (!token->desc) - vty_out (vty, " %-s\n", - token->text); - else if (desc_width >= strlen (token->desc)) - vty_out (vty, " %-*s %s\n", width, - token->text, - token->desc); - else - vty_describe_fold (vty, width, desc_width, token); - - if (IS_VARYING_TOKEN(token->type)) - { - const char *ref = vector_slot(vline, vector_active(vline) - 1); - - vector varcomps = vector_init (VECTOR_MIN_SIZE); - cmd_variable_complete (token, ref, varcomps); - - if (vector_active (varcomps) > 0) - { - char *ac = cmd_variable_comp2str(varcomps, vty->width); - vty_out(vty, "%s\n", ac); - XFREE(MTYPE_TMP, ac); - } - - vector_free(varcomps); - } +static void vty_describe_command(struct vty *vty) +{ + int ret; + vector vline; + vector describe; + unsigned int i, width, desc_width; + struct cmd_token *token, *token_cr = NULL; + + vline = cmd_make_strvec(vty->buf); + + /* In case of '> ?'. */ + if (vline == NULL) { + vline = vector_init(1); + vector_set(vline, NULL); + } else if (isspace((int)vty->buf[vty->length - 1])) + vector_set(vline, NULL); + + describe = cmd_describe_command(vline, vty, &ret); + + vty_out(vty, "\n"); + + /* Ambiguous error. */ + switch (ret) { + case CMD_ERR_AMBIGUOUS: + vty_out(vty, "%% Ambiguous command.\n"); + goto out; + break; + case CMD_ERR_NO_MATCH: + vty_out(vty, "%% There is no matched command.\n"); + goto out; + break; + } + + /* Get width of command string. */ + width = 0; + for (i = 0; i < vector_active(describe); i++) + if ((token = vector_slot(describe, i)) != NULL) { + unsigned int len; + + if (token->text[0] == '\0') + continue; + + len = strlen(token->text); + + if (width < len) + width = len; + } + + /* Get width of description string. */ + desc_width = vty->width - (width + 6); + + /* Print out description. */ + for (i = 0; i < vector_active(describe); i++) + if ((token = vector_slot(describe, i)) != NULL) { + if (token->text[0] == '\0') + continue; + + if (strcmp(token->text, CMD_CR_TEXT) == 0) { + token_cr = token; + continue; + } + + if (!token->desc) + vty_out(vty, " %-s\n", token->text); + else if (desc_width >= strlen(token->desc)) + vty_out(vty, " %-*s %s\n", width, token->text, + token->desc); + else + vty_describe_fold(vty, width, desc_width, + token); + + if (IS_VARYING_TOKEN(token->type)) { + const char *ref = vector_slot( + vline, vector_active(vline) - 1); + + vector varcomps = vector_init(VECTOR_MIN_SIZE); + cmd_variable_complete(token, ref, varcomps); + + if (vector_active(varcomps) > 0) { + char *ac = cmd_variable_comp2str( + varcomps, vty->width); + vty_out(vty, "%s\n", ac); + XFREE(MTYPE_TMP, ac); + } + + vector_free(varcomps); + } #if 0 vty_out (vty, " %-*s %s\n", width desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd, desc->str ? desc->str : ""); #endif /* 0 */ - } - - if ((token = token_cr)) - { - if (!token->desc) - vty_out (vty, " %-s\n", - token->text); - else if (desc_width >= strlen (token->desc)) - vty_out (vty, " %-*s %s\n", width, - token->text, - token->desc); - else - vty_describe_fold (vty, width, desc_width, token); - } + } + + if ((token = token_cr)) { + if (!token->desc) + vty_out(vty, " %-s\n", token->text); + else if (desc_width >= strlen(token->desc)) + vty_out(vty, " %-*s %s\n", width, token->text, + token->desc); + else + vty_describe_fold(vty, width, desc_width, token); + } out: - cmd_free_strvec (vline); - if (describe) - vector_free (describe); + cmd_free_strvec(vline); + if (describe) + vector_free(describe); - vty_prompt (vty); - vty_redraw_line (vty); + vty_prompt(vty); + vty_redraw_line(vty); } -static void -vty_clear_buf (struct vty *vty) +static void vty_clear_buf(struct vty *vty) { - memset (vty->buf, 0, vty->max); + memset(vty->buf, 0, vty->max); } /* ^C stop current input and do not add command line to the history. */ -static void -vty_stop_input (struct vty *vty) -{ - vty->cp = vty->length = 0; - vty_clear_buf (vty); - vty_out (vty, "\n"); - - switch (vty->node) - { - case VIEW_NODE: - case ENABLE_NODE: - /* Nothing to do. */ - break; - case CONFIG_NODE: - case INTERFACE_NODE: - case ZEBRA_NODE: - case RIP_NODE: - case RIPNG_NODE: - case EIGRP_NODE: - case BGP_NODE: - case RMAP_NODE: - case OSPF_NODE: - case OSPF6_NODE: - case LDP_NODE: - case LDP_IPV4_NODE: - case LDP_IPV6_NODE: - case LDP_IPV4_IFACE_NODE: - case LDP_IPV6_IFACE_NODE: - case LDP_L2VPN_NODE: - case LDP_PSEUDOWIRE_NODE: - case ISIS_NODE: - case KEYCHAIN_NODE: - case KEYCHAIN_KEY_NODE: - case MASC_NODE: - case PIM_NODE: - case VTY_NODE: - vty_config_unlock (vty); - vty->node = ENABLE_NODE; - break; - default: - /* Unknown node, we have to ignore it. */ - break; - } - vty_prompt (vty); - - /* Set history pointer to the latest one. */ - vty->hp = vty->hindex; +static void vty_stop_input(struct vty *vty) +{ + vty->cp = vty->length = 0; + vty_clear_buf(vty); + vty_out(vty, "\n"); + + switch (vty->node) { + case VIEW_NODE: + case ENABLE_NODE: + /* Nothing to do. */ + break; + case CONFIG_NODE: + case INTERFACE_NODE: + case ZEBRA_NODE: + case RIP_NODE: + case RIPNG_NODE: + case EIGRP_NODE: + case BGP_NODE: + case RMAP_NODE: + case OSPF_NODE: + case OSPF6_NODE: + case LDP_NODE: + case LDP_IPV4_NODE: + case LDP_IPV6_NODE: + case LDP_IPV4_IFACE_NODE: + case LDP_IPV6_IFACE_NODE: + case LDP_L2VPN_NODE: + case LDP_PSEUDOWIRE_NODE: + case ISIS_NODE: + case KEYCHAIN_NODE: + case KEYCHAIN_KEY_NODE: + case MASC_NODE: + case PIM_NODE: + case VTY_NODE: + vty_config_unlock(vty); + vty->node = ENABLE_NODE; + break; + default: + /* Unknown node, we have to ignore it. */ + break; + } + vty_prompt(vty); + + /* Set history pointer to the latest one. */ + vty->hp = vty->hindex; } /* Add current command line to the history buffer. */ -static void -vty_hist_add (struct vty *vty) +static void vty_hist_add(struct vty *vty) { - int index; + int index; - if (vty->length == 0) - return; + if (vty->length == 0) + return; - index = vty->hindex ? vty->hindex - 1 : VTY_MAXHIST - 1; + index = vty->hindex ? vty->hindex - 1 : VTY_MAXHIST - 1; - /* Ignore the same string as previous one. */ - if (vty->hist[index]) - if (strcmp (vty->buf, vty->hist[index]) == 0) - { - vty->hp = vty->hindex; - return; - } + /* Ignore the same string as previous one. */ + if (vty->hist[index]) + if (strcmp(vty->buf, vty->hist[index]) == 0) { + vty->hp = vty->hindex; + return; + } - /* Insert history entry. */ - if (vty->hist[vty->hindex]) - XFREE (MTYPE_VTY_HIST, vty->hist[vty->hindex]); - vty->hist[vty->hindex] = XSTRDUP (MTYPE_VTY_HIST, vty->buf); + /* Insert history entry. */ + if (vty->hist[vty->hindex]) + XFREE(MTYPE_VTY_HIST, vty->hist[vty->hindex]); + vty->hist[vty->hindex] = XSTRDUP(MTYPE_VTY_HIST, vty->buf); - /* History index rotation. */ - vty->hindex++; - if (vty->hindex == VTY_MAXHIST) - vty->hindex = 0; + /* History index rotation. */ + vty->hindex++; + if (vty->hindex == VTY_MAXHIST) + vty->hindex = 0; - vty->hp = vty->hindex; + vty->hp = vty->hindex; } /* #define TELNET_OPTION_DEBUG */ /* Get telnet window size. */ -static int -vty_telnet_option (struct vty *vty, unsigned char *buf, int nbytes) +static int vty_telnet_option(struct vty *vty, unsigned char *buf, int nbytes) { #ifdef TELNET_OPTION_DEBUG - int i; - - for (i = 0; i < nbytes; i++) - { - switch (buf[i]) - { - case IAC: - vty_out (vty, "IAC "); - break; - case WILL: - vty_out (vty, "WILL "); - break; - case WONT: - vty_out (vty, "WONT "); - break; - case DO: - vty_out (vty, "DO "); - break; - case DONT: - vty_out (vty, "DONT "); - break; - case SB: - vty_out (vty, "SB "); - break; - case SE: - vty_out (vty, "SE "); - break; - case TELOPT_ECHO: - vty_out (vty, "TELOPT_ECHO \n"); - break; - case TELOPT_SGA: - vty_out (vty, "TELOPT_SGA \n"); - break; - case TELOPT_NAWS: - vty_out (vty, "TELOPT_NAWS \n"); - break; - default: - vty_out (vty, "%x ", buf[i]); - break; - } - } - vty_out (vty, "\n"); + int i; + + for (i = 0; i < nbytes; i++) { + switch (buf[i]) { + case IAC: + vty_out(vty, "IAC "); + break; + case WILL: + vty_out(vty, "WILL "); + break; + case WONT: + vty_out(vty, "WONT "); + break; + case DO: + vty_out(vty, "DO "); + break; + case DONT: + vty_out(vty, "DONT "); + break; + case SB: + vty_out(vty, "SB "); + break; + case SE: + vty_out(vty, "SE "); + break; + case TELOPT_ECHO: + vty_out(vty, "TELOPT_ECHO \n"); + break; + case TELOPT_SGA: + vty_out(vty, "TELOPT_SGA \n"); + break; + case TELOPT_NAWS: + vty_out(vty, "TELOPT_NAWS \n"); + break; + default: + vty_out(vty, "%x ", buf[i]); + break; + } + } + vty_out(vty, "\n"); #endif /* TELNET_OPTION_DEBUG */ - switch (buf[0]) - { - case SB: - vty->sb_len = 0; - vty->iac_sb_in_progress = 1; - return 0; - break; - case SE: - { - if (!vty->iac_sb_in_progress) - return 0; - - if ((vty->sb_len == 0) || (vty->sb_buf[0] == '\0')) - { - vty->iac_sb_in_progress = 0; - return 0; - } - switch (vty->sb_buf[0]) - { - case TELOPT_NAWS: - if (vty->sb_len != TELNET_NAWS_SB_LEN) - zlog_warn("RFC 1073 violation detected: telnet NAWS option " - "should send %d characters, but we received %lu", - TELNET_NAWS_SB_LEN, (u_long)vty->sb_len); - else if (sizeof(vty->sb_buf) < TELNET_NAWS_SB_LEN) - zlog_err("Bug detected: sizeof(vty->sb_buf) %lu < %d, " - "too small to handle the telnet NAWS option", - (u_long)sizeof(vty->sb_buf), TELNET_NAWS_SB_LEN); - else - { - vty->width = ((vty->sb_buf[1] << 8)|vty->sb_buf[2]); - vty->height = ((vty->sb_buf[3] << 8)|vty->sb_buf[4]); + switch (buf[0]) { + case SB: + vty->sb_len = 0; + vty->iac_sb_in_progress = 1; + return 0; + break; + case SE: { + if (!vty->iac_sb_in_progress) + return 0; + + if ((vty->sb_len == 0) || (vty->sb_buf[0] == '\0')) { + vty->iac_sb_in_progress = 0; + return 0; + } + switch (vty->sb_buf[0]) { + case TELOPT_NAWS: + if (vty->sb_len != TELNET_NAWS_SB_LEN) + zlog_warn( + "RFC 1073 violation detected: telnet NAWS option " + "should send %d characters, but we received %lu", + TELNET_NAWS_SB_LEN, + (u_long)vty->sb_len); + else if (sizeof(vty->sb_buf) < TELNET_NAWS_SB_LEN) + zlog_err( + "Bug detected: sizeof(vty->sb_buf) %lu < %d, " + "too small to handle the telnet NAWS option", + (u_long)sizeof(vty->sb_buf), + TELNET_NAWS_SB_LEN); + else { + vty->width = ((vty->sb_buf[1] << 8) + | vty->sb_buf[2]); + vty->height = ((vty->sb_buf[3] << 8) + | vty->sb_buf[4]); #ifdef TELNET_OPTION_DEBUG - vty_out (vty, "TELNET NAWS window size negotiation completed: " - "width %d, height %d\n", - vty->width, vty->height); + vty_out(vty, + "TELNET NAWS window size negotiation completed: " + "width %d, height %d\n", + vty->width, vty->height); #endif - } - break; - } - vty->iac_sb_in_progress = 0; - return 0; - break; - } - default: - break; - } - return 1; + } + break; + } + vty->iac_sb_in_progress = 0; + return 0; + break; + } + default: + break; + } + return 1; } /* Execute current command line. */ -static int -vty_execute (struct vty *vty) +static int vty_execute(struct vty *vty) { - int ret; + int ret; - ret = CMD_SUCCESS; + ret = CMD_SUCCESS; - switch (vty->node) - { - case AUTH_NODE: - case AUTH_ENABLE_NODE: - vty_auth (vty, vty->buf); - break; - default: - ret = vty_command (vty, vty->buf); - if (vty->type == VTY_TERM) - vty_hist_add (vty); - break; - } + switch (vty->node) { + case AUTH_NODE: + case AUTH_ENABLE_NODE: + vty_auth(vty, vty->buf); + break; + default: + ret = vty_command(vty, vty->buf); + if (vty->type == VTY_TERM) + vty_hist_add(vty); + break; + } - /* Clear command line buffer. */ - vty->cp = vty->length = 0; - vty_clear_buf (vty); + /* Clear command line buffer. */ + vty->cp = vty->length = 0; + vty_clear_buf(vty); - if (vty->status != VTY_CLOSE ) - vty_prompt (vty); + if (vty->status != VTY_CLOSE) + vty_prompt(vty); - return ret; + return ret; } #define CONTROL(X) ((X) - '@') @@ -1382,397 +1293,368 @@ vty_execute (struct vty *vty) #define VTY_ESCAPE 2 /* Escape character command map. */ -static void -vty_escape_map (unsigned char c, struct vty *vty) -{ - switch (c) - { - case ('A'): - vty_previous_line (vty); - break; - case ('B'): - vty_next_line (vty); - break; - case ('C'): - vty_forward_char (vty); - break; - case ('D'): - vty_backward_char (vty); - break; - default: - break; - } - - /* Go back to normal mode. */ - vty->escape = VTY_NORMAL; +static void vty_escape_map(unsigned char c, struct vty *vty) +{ + switch (c) { + case ('A'): + vty_previous_line(vty); + break; + case ('B'): + vty_next_line(vty); + break; + case ('C'): + vty_forward_char(vty); + break; + case ('D'): + vty_backward_char(vty); + break; + default: + break; + } + + /* Go back to normal mode. */ + vty->escape = VTY_NORMAL; } /* Quit print out to the buffer. */ -static void -vty_buffer_reset (struct vty *vty) +static void vty_buffer_reset(struct vty *vty) { - buffer_reset (vty->obuf); - vty_prompt (vty); - vty_redraw_line (vty); + buffer_reset(vty->obuf); + vty_prompt(vty); + vty_redraw_line(vty); } /* Read data via vty socket. */ -static int -vty_read (struct thread *thread) -{ - int i; - int nbytes; - unsigned char buf[VTY_READ_BUFSIZ]; - - int vty_sock = THREAD_FD (thread); - struct vty *vty = THREAD_ARG (thread); - vty->t_read = NULL; - - /* Read raw data from socket */ - if ((nbytes = read (vty->fd, buf, VTY_READ_BUFSIZ)) <= 0) - { - if (nbytes < 0) - { - if (ERRNO_IO_RETRY(errno)) - { - vty_event (VTY_READ, vty_sock, vty); - return 0; - } - vty->monitor = 0; /* disable monitoring to avoid infinite recursion */ - zlog_warn("%s: read error on vty client fd %d, closing: %s", - __func__, vty->fd, safe_strerror(errno)); - buffer_reset(vty->obuf); - } - vty->status = VTY_CLOSE; - } - - for (i = 0; i < nbytes; i++) - { - if (buf[i] == IAC) - { - if (!vty->iac) - { - vty->iac = 1; - continue; - } - else - { - vty->iac = 0; - } - } - - if (vty->iac_sb_in_progress && !vty->iac) - { - if (vty->sb_len < sizeof(vty->sb_buf)) - vty->sb_buf[vty->sb_len] = buf[i]; - vty->sb_len++; - continue; - } - - if (vty->iac) - { - /* In case of telnet command */ - int ret = 0; - ret = vty_telnet_option (vty, buf + i, nbytes - i); - vty->iac = 0; - i += ret; - continue; - } - - - if (vty->status == VTY_MORE) - { - switch (buf[i]) - { - case CONTROL('C'): - case 'q': - case 'Q': - vty_buffer_reset (vty); - break; +static int vty_read(struct thread *thread) +{ + int i; + int nbytes; + unsigned char buf[VTY_READ_BUFSIZ]; + + int vty_sock = THREAD_FD(thread); + struct vty *vty = THREAD_ARG(thread); + vty->t_read = NULL; + + /* Read raw data from socket */ + if ((nbytes = read(vty->fd, buf, VTY_READ_BUFSIZ)) <= 0) { + if (nbytes < 0) { + if (ERRNO_IO_RETRY(errno)) { + vty_event(VTY_READ, vty_sock, vty); + return 0; + } + vty->monitor = 0; /* disable monitoring to avoid + infinite recursion */ + zlog_warn( + "%s: read error on vty client fd %d, closing: %s", + __func__, vty->fd, safe_strerror(errno)); + buffer_reset(vty->obuf); + } + vty->status = VTY_CLOSE; + } + + for (i = 0; i < nbytes; i++) { + if (buf[i] == IAC) { + if (!vty->iac) { + vty->iac = 1; + continue; + } else { + vty->iac = 0; + } + } + + if (vty->iac_sb_in_progress && !vty->iac) { + if (vty->sb_len < sizeof(vty->sb_buf)) + vty->sb_buf[vty->sb_len] = buf[i]; + vty->sb_len++; + continue; + } + + if (vty->iac) { + /* In case of telnet command */ + int ret = 0; + ret = vty_telnet_option(vty, buf + i, nbytes - i); + vty->iac = 0; + i += ret; + continue; + } + + + if (vty->status == VTY_MORE) { + switch (buf[i]) { + case CONTROL('C'): + case 'q': + case 'Q': + vty_buffer_reset(vty); + break; #if 0 /* More line does not work for "show ip bgp". */ case '\n': case '\r': vty->status = VTY_MORELINE; break; #endif - default: - break; - } - continue; - } - - /* Escape character. */ - if (vty->escape == VTY_ESCAPE) - { - vty_escape_map (buf[i], vty); - continue; - } - - /* Pre-escape status. */ - if (vty->escape == VTY_PRE_ESCAPE) - { - switch (buf[i]) - { - case '[': - vty->escape = VTY_ESCAPE; - break; - case 'b': - vty_backward_word (vty); - vty->escape = VTY_NORMAL; - break; - case 'f': - vty_forward_word (vty); - vty->escape = VTY_NORMAL; - break; - case 'd': - vty_forward_kill_word (vty); - vty->escape = VTY_NORMAL; - break; - case CONTROL('H'): - case 0x7f: - vty_backward_kill_word (vty); - vty->escape = VTY_NORMAL; - break; - default: - vty->escape = VTY_NORMAL; - break; - } - continue; - } - - switch (buf[i]) - { - case CONTROL('A'): - vty_beginning_of_line (vty); - break; - case CONTROL('B'): - vty_backward_char (vty); - break; - case CONTROL('C'): - vty_stop_input (vty); - break; - case CONTROL('D'): - vty_delete_char (vty); - break; - case CONTROL('E'): - vty_end_of_line (vty); - break; - case CONTROL('F'): - vty_forward_char (vty); - break; - case CONTROL('H'): - case 0x7f: - vty_delete_backward_char (vty); - break; - case CONTROL('K'): - vty_kill_line (vty); - break; - case CONTROL('N'): - vty_next_line (vty); - break; - case CONTROL('P'): - vty_previous_line (vty); - break; - case CONTROL('T'): - vty_transpose_chars (vty); - break; - case CONTROL('U'): - vty_kill_line_from_beginning (vty); - break; - case CONTROL('W'): - vty_backward_kill_word (vty); - break; - case CONTROL('Z'): - vty_end_config (vty); - break; - case '\n': - case '\r': - vty_out (vty, "\n"); - vty_execute (vty); - break; - case '\t': - vty_complete_command (vty); - break; - case '?': - if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE) - vty_self_insert (vty, buf[i]); - else - vty_describe_command (vty); - break; - case '\033': - if (i + 1 < nbytes && buf[i + 1] == '[') - { - vty->escape = VTY_ESCAPE; - i++; - } - else - vty->escape = VTY_PRE_ESCAPE; - break; - default: - if (buf[i] > 31 && buf[i] < 127) - vty_self_insert (vty, buf[i]); - break; - } - } - - /* Check status. */ - if (vty->status == VTY_CLOSE) - vty_close (vty); - else - { - vty_event (VTY_WRITE, vty->wfd, vty); - vty_event (VTY_READ, vty_sock, vty); - } - return 0; + default: + break; + } + continue; + } + + /* Escape character. */ + if (vty->escape == VTY_ESCAPE) { + vty_escape_map(buf[i], vty); + continue; + } + + /* Pre-escape status. */ + if (vty->escape == VTY_PRE_ESCAPE) { + switch (buf[i]) { + case '[': + vty->escape = VTY_ESCAPE; + break; + case 'b': + vty_backward_word(vty); + vty->escape = VTY_NORMAL; + break; + case 'f': + vty_forward_word(vty); + vty->escape = VTY_NORMAL; + break; + case 'd': + vty_forward_kill_word(vty); + vty->escape = VTY_NORMAL; + break; + case CONTROL('H'): + case 0x7f: + vty_backward_kill_word(vty); + vty->escape = VTY_NORMAL; + break; + default: + vty->escape = VTY_NORMAL; + break; + } + continue; + } + + switch (buf[i]) { + case CONTROL('A'): + vty_beginning_of_line(vty); + break; + case CONTROL('B'): + vty_backward_char(vty); + break; + case CONTROL('C'): + vty_stop_input(vty); + break; + case CONTROL('D'): + vty_delete_char(vty); + break; + case CONTROL('E'): + vty_end_of_line(vty); + break; + case CONTROL('F'): + vty_forward_char(vty); + break; + case CONTROL('H'): + case 0x7f: + vty_delete_backward_char(vty); + break; + case CONTROL('K'): + vty_kill_line(vty); + break; + case CONTROL('N'): + vty_next_line(vty); + break; + case CONTROL('P'): + vty_previous_line(vty); + break; + case CONTROL('T'): + vty_transpose_chars(vty); + break; + case CONTROL('U'): + vty_kill_line_from_beginning(vty); + break; + case CONTROL('W'): + vty_backward_kill_word(vty); + break; + case CONTROL('Z'): + vty_end_config(vty); + break; + case '\n': + case '\r': + vty_out(vty, "\n"); + vty_execute(vty); + break; + case '\t': + vty_complete_command(vty); + break; + case '?': + if (vty->node == AUTH_NODE + || vty->node == AUTH_ENABLE_NODE) + vty_self_insert(vty, buf[i]); + else + vty_describe_command(vty); + break; + case '\033': + if (i + 1 < nbytes && buf[i + 1] == '[') { + vty->escape = VTY_ESCAPE; + i++; + } else + vty->escape = VTY_PRE_ESCAPE; + break; + default: + if (buf[i] > 31 && buf[i] < 127) + vty_self_insert(vty, buf[i]); + break; + } + } + + /* Check status. */ + if (vty->status == VTY_CLOSE) + vty_close(vty); + else { + vty_event(VTY_WRITE, vty->wfd, vty); + vty_event(VTY_READ, vty_sock, vty); + } + return 0; } /* Flush buffer to the vty. */ -static int -vty_flush (struct thread *thread) -{ - int erase; - buffer_status_t flushrc; - int vty_sock = THREAD_FD (thread); - struct vty *vty = THREAD_ARG (thread); - - vty->t_write = NULL; - - /* Tempolary disable read thread. */ - if ((vty->lines == 0) && vty->t_read) - { - thread_cancel (vty->t_read); - vty->t_read = NULL; - } - - /* Function execution continue. */ - erase = ((vty->status == VTY_MORE || vty->status == VTY_MORELINE)); - - /* N.B. if width is 0, that means we don't know the window size. */ - if ((vty->lines == 0) || (vty->width == 0) || (vty->height == 0)) - flushrc = buffer_flush_available(vty->obuf, vty_sock); - else if (vty->status == VTY_MORELINE) - flushrc = buffer_flush_window(vty->obuf, vty_sock, vty->width, - 1, erase, 0); - else - flushrc = buffer_flush_window(vty->obuf, vty_sock, vty->width, - vty->lines >= 0 ? vty->lines : - vty->height, - erase, 0); - switch (flushrc) - { - case BUFFER_ERROR: - vty->monitor = 0; /* disable monitoring to avoid infinite recursion */ - zlog_warn("buffer_flush failed on vty client fd %d, closing", - vty->fd); - buffer_reset(vty->obuf); - vty_close(vty); - return 0; - case BUFFER_EMPTY: - if (vty->status == VTY_CLOSE) - vty_close (vty); - else - { - vty->status = VTY_NORMAL; - if (vty->lines == 0) - vty_event (VTY_READ, vty_sock, vty); - } - break; - case BUFFER_PENDING: - /* There is more data waiting to be written. */ - vty->status = VTY_MORE; - if (vty->lines == 0) - vty_event (VTY_WRITE, vty_sock, vty); - break; - } - - return 0; +static int vty_flush(struct thread *thread) +{ + int erase; + buffer_status_t flushrc; + int vty_sock = THREAD_FD(thread); + struct vty *vty = THREAD_ARG(thread); + + vty->t_write = NULL; + + /* Tempolary disable read thread. */ + if ((vty->lines == 0) && vty->t_read) { + thread_cancel(vty->t_read); + vty->t_read = NULL; + } + + /* Function execution continue. */ + erase = ((vty->status == VTY_MORE || vty->status == VTY_MORELINE)); + + /* N.B. if width is 0, that means we don't know the window size. */ + if ((vty->lines == 0) || (vty->width == 0) || (vty->height == 0)) + flushrc = buffer_flush_available(vty->obuf, vty_sock); + else if (vty->status == VTY_MORELINE) + flushrc = buffer_flush_window(vty->obuf, vty_sock, vty->width, + 1, erase, 0); + else + flushrc = buffer_flush_window( + vty->obuf, vty_sock, vty->width, + vty->lines >= 0 ? vty->lines : vty->height, erase, 0); + switch (flushrc) { + case BUFFER_ERROR: + vty->monitor = + 0; /* disable monitoring to avoid infinite recursion */ + zlog_warn("buffer_flush failed on vty client fd %d, closing", + vty->fd); + buffer_reset(vty->obuf); + vty_close(vty); + return 0; + case BUFFER_EMPTY: + if (vty->status == VTY_CLOSE) + vty_close(vty); + else { + vty->status = VTY_NORMAL; + if (vty->lines == 0) + vty_event(VTY_READ, vty_sock, vty); + } + break; + case BUFFER_PENDING: + /* There is more data waiting to be written. */ + vty->status = VTY_MORE; + if (vty->lines == 0) + vty_event(VTY_WRITE, vty_sock, vty); + break; + } + + return 0; } /* allocate and initialise vty */ -static struct vty * -vty_new_init (int vty_sock) -{ - struct vty *vty; - - vty = vty_new (); - vty->fd = vty_sock; - vty->wfd = vty_sock; - vty->type = VTY_TERM; - vty->node = AUTH_NODE; - vty->fail = 0; - vty->cp = 0; - vty_clear_buf (vty); - vty->length = 0; - memset (vty->hist, 0, sizeof (vty->hist)); - vty->hp = 0; - vty->hindex = 0; - vector_set_index (vtyvec, vty_sock, vty); - vty->status = VTY_NORMAL; - vty->lines = -1; - vty->iac = 0; - vty->iac_sb_in_progress = 0; - vty->sb_len = 0; - - return vty; +static struct vty *vty_new_init(int vty_sock) +{ + struct vty *vty; + + vty = vty_new(); + vty->fd = vty_sock; + vty->wfd = vty_sock; + vty->type = VTY_TERM; + vty->node = AUTH_NODE; + vty->fail = 0; + vty->cp = 0; + vty_clear_buf(vty); + vty->length = 0; + memset(vty->hist, 0, sizeof(vty->hist)); + vty->hp = 0; + vty->hindex = 0; + vector_set_index(vtyvec, vty_sock, vty); + vty->status = VTY_NORMAL; + vty->lines = -1; + vty->iac = 0; + vty->iac_sb_in_progress = 0; + vty->sb_len = 0; + + return vty; } /* Create new vty structure. */ -static struct vty * -vty_create (int vty_sock, union sockunion *su) -{ - char buf[SU_ADDRSTRLEN]; - struct vty *vty; - - sockunion2str(su, buf, SU_ADDRSTRLEN); - - /* Allocate new vty structure and set up default values. */ - vty = vty_new_init (vty_sock); - - /* configurable parameters not part of basic init */ - vty->v_timeout = vty_timeout_val; - strcpy (vty->address, buf); - if (no_password_check) - { - if (host.advanced) - vty->node = ENABLE_NODE; - else - vty->node = VIEW_NODE; - } - if (host.lines >= 0) - vty->lines = host.lines; - - if (! no_password_check) - { - /* Vty is not available if password isn't set. */ - if (host.password == NULL && host.password_encrypt == NULL) - { - vty_out (vty, "Vty password is not set.\n"); - vty->status = VTY_CLOSE; - vty_close (vty); - return NULL; - } - } - - /* Say hello to the world. */ - vty_hello (vty); - if (! no_password_check) - vty_out (vty, "\nUser Access Verification\n\n"); - - /* Setting up terminal. */ - vty_will_echo (vty); - vty_will_suppress_go_ahead (vty); - - vty_dont_linemode (vty); - vty_do_window_size (vty); - /* vty_dont_lflow_ahead (vty); */ - - vty_prompt (vty); - - /* Add read/write thread. */ - vty_event (VTY_WRITE, vty_sock, vty); - vty_event (VTY_READ, vty_sock, vty); - - return vty; +static struct vty *vty_create(int vty_sock, union sockunion *su) +{ + char buf[SU_ADDRSTRLEN]; + struct vty *vty; + + sockunion2str(su, buf, SU_ADDRSTRLEN); + + /* Allocate new vty structure and set up default values. */ + vty = vty_new_init(vty_sock); + + /* configurable parameters not part of basic init */ + vty->v_timeout = vty_timeout_val; + strcpy(vty->address, buf); + if (no_password_check) { + if (host.advanced) + vty->node = ENABLE_NODE; + else + vty->node = VIEW_NODE; + } + if (host.lines >= 0) + vty->lines = host.lines; + + if (!no_password_check) { + /* Vty is not available if password isn't set. */ + if (host.password == NULL && host.password_encrypt == NULL) { + vty_out(vty, "Vty password is not set.\n"); + vty->status = VTY_CLOSE; + vty_close(vty); + return NULL; + } + } + + /* Say hello to the world. */ + vty_hello(vty); + if (!no_password_check) + vty_out(vty, "\nUser Access Verification\n\n"); + + /* Setting up terminal. */ + vty_will_echo(vty); + vty_will_suppress_go_ahead(vty); + + vty_dont_linemode(vty); + vty_do_window_size(vty); + /* vty_dont_lflow_ahead (vty); */ + + vty_prompt(vty); + + /* Add read/write thread. */ + vty_event(VTY_WRITE, vty_sock, vty); + vty_event(VTY_READ, vty_sock, vty); + + return vty; } /* create vty for stdio */ @@ -1780,204 +1662,190 @@ static struct termios stdio_orig_termios; static struct vty *stdio_vty = NULL; static void (*stdio_vty_atclose)(void); -static void -vty_stdio_reset (void) +static void vty_stdio_reset(void) { - if (stdio_vty) - { - tcsetattr (0, TCSANOW, &stdio_orig_termios); - stdio_vty = NULL; + if (stdio_vty) { + tcsetattr(0, TCSANOW, &stdio_orig_termios); + stdio_vty = NULL; - if (stdio_vty_atclose) - stdio_vty_atclose (); - stdio_vty_atclose = NULL; - } + if (stdio_vty_atclose) + stdio_vty_atclose(); + stdio_vty_atclose = NULL; + } } -struct vty * -vty_stdio (void (*atclose)()) +struct vty *vty_stdio(void (*atclose)()) { - struct vty *vty; - struct termios termios; + struct vty *vty; + struct termios termios; - /* refuse creating two vtys on stdio */ - if (stdio_vty) - return NULL; + /* refuse creating two vtys on stdio */ + if (stdio_vty) + return NULL; - vty = stdio_vty = vty_new_init (0); - stdio_vty_atclose = atclose; - vty->wfd = 1; + vty = stdio_vty = vty_new_init(0); + stdio_vty_atclose = atclose; + vty->wfd = 1; - /* always have stdio vty in a known _unchangeable_ state, don't want config - * to have any effect here to make sure scripting this works as intended */ - vty->node = ENABLE_NODE; - vty->v_timeout = 0; - strcpy (vty->address, "console"); + /* always have stdio vty in a known _unchangeable_ state, don't want + * config + * to have any effect here to make sure scripting this works as intended + */ + vty->node = ENABLE_NODE; + vty->v_timeout = 0; + strcpy(vty->address, "console"); - if (!tcgetattr (0, &stdio_orig_termios)) - { - termios = stdio_orig_termios; - termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP - | INLCR | IGNCR | ICRNL | IXON); - termios.c_oflag &= ~OPOST; - termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); - termios.c_cflag &= ~(CSIZE | PARENB); - termios.c_cflag |= CS8; - tcsetattr (0, TCSANOW, &termios); - } + if (!tcgetattr(0, &stdio_orig_termios)) { + termios = stdio_orig_termios; + termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR + | IGNCR | ICRNL | IXON); + termios.c_oflag &= ~OPOST; + termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + termios.c_cflag &= ~(CSIZE | PARENB); + termios.c_cflag |= CS8; + tcsetattr(0, TCSANOW, &termios); + } - vty_prompt (vty); + vty_prompt(vty); - /* Add read/write thread. */ - vty_event (VTY_WRITE, 1, vty); - vty_event (VTY_READ, 0, vty); + /* Add read/write thread. */ + vty_event(VTY_WRITE, 1, vty); + vty_event(VTY_READ, 0, vty); - return vty; + return vty; } /* Accept connection from the network. */ -static int -vty_accept (struct thread *thread) -{ - int vty_sock; - union sockunion su; - int ret; - unsigned int on; - int accept_sock; - struct prefix p; - struct access_list *acl = NULL; - char buf[SU_ADDRSTRLEN]; - - accept_sock = THREAD_FD (thread); - - /* We continue hearing vty socket. */ - vty_event (VTY_SERV, accept_sock, NULL); - - memset (&su, 0, sizeof (union sockunion)); - - /* We can handle IPv4 or IPv6 socket. */ - vty_sock = sockunion_accept (accept_sock, &su); - if (vty_sock < 0) - { - zlog_warn ("can't accept vty socket : %s", safe_strerror (errno)); - return -1; - } - set_nonblocking(vty_sock); - set_cloexec(vty_sock); - - sockunion2hostprefix (&su, &p); - - /* VTY's accesslist apply. */ - if (p.family == AF_INET && vty_accesslist_name) - { - if ((acl = access_list_lookup (AFI_IP, vty_accesslist_name)) && - (access_list_apply (acl, &p) == FILTER_DENY)) - { - zlog_info ("Vty connection refused from %s", - sockunion2str (&su, buf, SU_ADDRSTRLEN)); - close (vty_sock); - - /* continue accepting connections */ - vty_event (VTY_SERV, accept_sock, NULL); - - return 0; - } - } - - /* VTY's ipv6 accesslist apply. */ - if (p.family == AF_INET6 && vty_ipv6_accesslist_name) - { - if ((acl = access_list_lookup (AFI_IP6, vty_ipv6_accesslist_name)) && - (access_list_apply (acl, &p) == FILTER_DENY)) - { - zlog_info ("Vty connection refused from %s", - sockunion2str (&su, buf, SU_ADDRSTRLEN)); - close (vty_sock); - - /* continue accepting connections */ - vty_event (VTY_SERV, accept_sock, NULL); - - return 0; - } - } - - on = 1; - ret = setsockopt (vty_sock, IPPROTO_TCP, TCP_NODELAY, - (char *) &on, sizeof (on)); - if (ret < 0) - zlog_info ("can't set sockopt to vty_sock : %s", - safe_strerror (errno)); - - zlog_info ("Vty connection from %s", - sockunion2str (&su, buf, SU_ADDRSTRLEN)); - - vty_create (vty_sock, &su); - - return 0; -} +static int vty_accept(struct thread *thread) +{ + int vty_sock; + union sockunion su; + int ret; + unsigned int on; + int accept_sock; + struct prefix p; + struct access_list *acl = NULL; + char buf[SU_ADDRSTRLEN]; + + accept_sock = THREAD_FD(thread); + + /* We continue hearing vty socket. */ + vty_event(VTY_SERV, accept_sock, NULL); + + memset(&su, 0, sizeof(union sockunion)); + + /* We can handle IPv4 or IPv6 socket. */ + vty_sock = sockunion_accept(accept_sock, &su); + if (vty_sock < 0) { + zlog_warn("can't accept vty socket : %s", safe_strerror(errno)); + return -1; + } + set_nonblocking(vty_sock); + set_cloexec(vty_sock); + + sockunion2hostprefix(&su, &p); + + /* VTY's accesslist apply. */ + if (p.family == AF_INET && vty_accesslist_name) { + if ((acl = access_list_lookup(AFI_IP, vty_accesslist_name)) + && (access_list_apply(acl, &p) == FILTER_DENY)) { + zlog_info("Vty connection refused from %s", + sockunion2str(&su, buf, SU_ADDRSTRLEN)); + close(vty_sock); + + /* continue accepting connections */ + vty_event(VTY_SERV, accept_sock, NULL); + + return 0; + } + } + + /* VTY's ipv6 accesslist apply. */ + if (p.family == AF_INET6 && vty_ipv6_accesslist_name) { + if ((acl = access_list_lookup(AFI_IP6, + vty_ipv6_accesslist_name)) + && (access_list_apply(acl, &p) == FILTER_DENY)) { + zlog_info("Vty connection refused from %s", + sockunion2str(&su, buf, SU_ADDRSTRLEN)); + close(vty_sock); + + /* continue accepting connections */ + vty_event(VTY_SERV, accept_sock, NULL); + + return 0; + } + } + + on = 1; + ret = setsockopt(vty_sock, IPPROTO_TCP, TCP_NODELAY, (char *)&on, + sizeof(on)); + if (ret < 0) + zlog_info("can't set sockopt to vty_sock : %s", + safe_strerror(errno)); + + zlog_info("Vty connection from %s", + sockunion2str(&su, buf, SU_ADDRSTRLEN)); + + vty_create(vty_sock, &su); + + return 0; +} + +static void vty_serv_sock_addrinfo(const char *hostname, unsigned short port) +{ + int ret; + struct addrinfo req; + struct addrinfo *ainfo; + struct addrinfo *ainfo_save; + int sock; + char port_str[BUFSIZ]; + + memset(&req, 0, sizeof(struct addrinfo)); + req.ai_flags = AI_PASSIVE; + req.ai_family = AF_UNSPEC; + req.ai_socktype = SOCK_STREAM; + sprintf(port_str, "%d", port); + port_str[sizeof(port_str) - 1] = '\0'; + + ret = getaddrinfo(hostname, port_str, &req, &ainfo); + + if (ret != 0) { + fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(ret)); + exit(1); + } + + ainfo_save = ainfo; + + do { + if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6) + continue; + + sock = socket(ainfo->ai_family, ainfo->ai_socktype, + ainfo->ai_protocol); + if (sock < 0) + continue; -static void -vty_serv_sock_addrinfo (const char *hostname, unsigned short port) -{ - int ret; - struct addrinfo req; - struct addrinfo *ainfo; - struct addrinfo *ainfo_save; - int sock; - char port_str[BUFSIZ]; - - memset (&req, 0, sizeof (struct addrinfo)); - req.ai_flags = AI_PASSIVE; - req.ai_family = AF_UNSPEC; - req.ai_socktype = SOCK_STREAM; - sprintf (port_str, "%d", port); - port_str[sizeof (port_str) - 1] = '\0'; - - ret = getaddrinfo (hostname, port_str, &req, &ainfo); - - if (ret != 0) - { - fprintf (stderr, "getaddrinfo failed: %s\n", gai_strerror (ret)); - exit (1); - } - - ainfo_save = ainfo; - - do - { - if (ainfo->ai_family != AF_INET - && ainfo->ai_family != AF_INET6 - ) - continue; - - sock = socket (ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol); - if (sock < 0) - continue; - - sockopt_v6only (ainfo->ai_family, sock); - sockopt_reuseaddr (sock); - sockopt_reuseport (sock); - set_cloexec (sock); - - ret = bind (sock, ainfo->ai_addr, ainfo->ai_addrlen); - if (ret < 0) - { - close (sock); /* Avoid sd leak. */ - continue; - } - - ret = listen (sock, 3); - if (ret < 0) - { - close (sock); /* Avoid sd leak. */ - continue; - } - - vty_event (VTY_SERV, sock, NULL); - } - while ((ainfo = ainfo->ai_next) != NULL); - - freeaddrinfo (ainfo_save); + sockopt_v6only(ainfo->ai_family, sock); + sockopt_reuseaddr(sock); + sockopt_reuseport(sock); + set_cloexec(sock); + + ret = bind(sock, ainfo->ai_addr, ainfo->ai_addrlen); + if (ret < 0) { + close(sock); /* Avoid sd leak. */ + continue; + } + + ret = listen(sock, 3); + if (ret < 0) { + close(sock); /* Avoid sd leak. */ + continue; + } + + vty_event(VTY_SERV, sock, NULL); + } while ((ainfo = ainfo->ai_next) != NULL); + + freeaddrinfo(ainfo_save); } #ifdef VTYSH @@ -1985,261 +1853,250 @@ vty_serv_sock_addrinfo (const char *hostname, unsigned short port) #include /* VTY shell UNIX domain socket. */ -static void -vty_serv_un (const char *path) -{ - int ret; - int sock, len; - struct sockaddr_un serv; - mode_t old_mask; - struct zprivs_ids_t ids; - - /* First of all, unlink existing socket */ - unlink (path); - - /* Set umask */ - old_mask = umask (0007); - - /* Make UNIX domain socket. */ - sock = socket (AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) - { - zlog_err("Cannot create unix stream socket: %s", safe_strerror(errno)); - return; - } - - /* Make server socket. */ - memset (&serv, 0, sizeof (struct sockaddr_un)); - serv.sun_family = AF_UNIX; - strlcpy (serv.sun_path, path, sizeof (serv.sun_path)); +static void vty_serv_un(const char *path) +{ + int ret; + int sock, len; + struct sockaddr_un serv; + mode_t old_mask; + struct zprivs_ids_t ids; + + /* First of all, unlink existing socket */ + unlink(path); + + /* Set umask */ + old_mask = umask(0007); + + /* Make UNIX domain socket. */ + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + zlog_err("Cannot create unix stream socket: %s", + safe_strerror(errno)); + return; + } + + /* Make server socket. */ + memset(&serv, 0, sizeof(struct sockaddr_un)); + serv.sun_family = AF_UNIX; + strlcpy(serv.sun_path, path, sizeof(serv.sun_path)); #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN - len = serv.sun_len = SUN_LEN(&serv); + len = serv.sun_len = SUN_LEN(&serv); #else - len = sizeof (serv.sun_family) + strlen (serv.sun_path); + len = sizeof(serv.sun_family) + strlen(serv.sun_path); #endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */ - set_cloexec (sock); + set_cloexec(sock); - ret = bind (sock, (struct sockaddr *) &serv, len); - if (ret < 0) - { - zlog_err("Cannot bind path %s: %s", path, safe_strerror(errno)); - close (sock); /* Avoid sd leak. */ - return; - } + ret = bind(sock, (struct sockaddr *)&serv, len); + if (ret < 0) { + zlog_err("Cannot bind path %s: %s", path, safe_strerror(errno)); + close(sock); /* Avoid sd leak. */ + return; + } - ret = listen (sock, 5); - if (ret < 0) - { - zlog_err("listen(fd %d) failed: %s", sock, safe_strerror(errno)); - close (sock); /* Avoid sd leak. */ - return; - } + ret = listen(sock, 5); + if (ret < 0) { + zlog_err("listen(fd %d) failed: %s", sock, + safe_strerror(errno)); + close(sock); /* Avoid sd leak. */ + return; + } - umask (old_mask); + umask(old_mask); - zprivs_get_ids(&ids); + zprivs_get_ids(&ids); - /* Hack: ids.gid_vty is actually a uint, but we stored -1 in it - earlier for the case when we don't need to chown the file - type casting it here to make a compare */ - if ((int)ids.gid_vty > 0) - { - /* set group of socket */ - if ( chown (path, -1, ids.gid_vty) ) - { - zlog_err ("vty_serv_un: could chown socket, %s", - safe_strerror (errno) ); - } - } + /* Hack: ids.gid_vty is actually a uint, but we stored -1 in it + earlier for the case when we don't need to chown the file + type casting it here to make a compare */ + if ((int)ids.gid_vty > 0) { + /* set group of socket */ + if (chown(path, -1, ids.gid_vty)) { + zlog_err("vty_serv_un: could chown socket, %s", + safe_strerror(errno)); + } + } - vty_event (VTYSH_SERV, sock, NULL); + vty_event(VTYSH_SERV, sock, NULL); } /* #define VTYSH_DEBUG 1 */ -static int -vtysh_accept (struct thread *thread) +static int vtysh_accept(struct thread *thread) { - int accept_sock; - int sock; - int client_len; - struct sockaddr_un client; - struct vty *vty; + int accept_sock; + int sock; + int client_len; + struct sockaddr_un client; + struct vty *vty; - accept_sock = THREAD_FD (thread); + accept_sock = THREAD_FD(thread); - vty_event (VTYSH_SERV, accept_sock, NULL); + vty_event(VTYSH_SERV, accept_sock, NULL); - memset (&client, 0, sizeof (struct sockaddr_un)); - client_len = sizeof (struct sockaddr_un); + memset(&client, 0, sizeof(struct sockaddr_un)); + client_len = sizeof(struct sockaddr_un); - sock = accept (accept_sock, (struct sockaddr *) &client, - (socklen_t *) &client_len); + sock = accept(accept_sock, (struct sockaddr *)&client, + (socklen_t *)&client_len); - if (sock < 0) - { - zlog_warn ("can't accept vty socket : %s", safe_strerror (errno)); - return -1; - } + if (sock < 0) { + zlog_warn("can't accept vty socket : %s", safe_strerror(errno)); + return -1; + } - if (set_nonblocking(sock) < 0) - { - zlog_warn ("vtysh_accept: could not set vty socket %d to non-blocking," - " %s, closing", sock, safe_strerror (errno)); - close (sock); - return -1; - } - set_cloexec(sock); + if (set_nonblocking(sock) < 0) { + zlog_warn( + "vtysh_accept: could not set vty socket %d to non-blocking," + " %s, closing", + sock, safe_strerror(errno)); + close(sock); + return -1; + } + set_cloexec(sock); #ifdef VTYSH_DEBUG - printf ("VTY shell accept\n"); + printf("VTY shell accept\n"); #endif /* VTYSH_DEBUG */ - vty = vty_new (); - vty->fd = sock; - vty->wfd = sock; - vty->type = VTY_SHELL_SERV; - vty->node = VIEW_NODE; - - vty_event (VTYSH_READ, sock, vty); - - return 0; -} - -static int -vtysh_flush(struct vty *vty) -{ - switch (buffer_flush_available(vty->obuf, vty->wfd)) - { - case BUFFER_PENDING: - vty_event(VTYSH_WRITE, vty->wfd, vty); - break; - case BUFFER_ERROR: - vty->monitor = 0; /* disable monitoring to avoid infinite recursion */ - zlog_warn("%s: write error to fd %d, closing", __func__, vty->fd); - buffer_reset(vty->obuf); - vty_close(vty); - return -1; - break; - case BUFFER_EMPTY: - break; - } - return 0; -} - -static int -vtysh_read (struct thread *thread) -{ - int ret; - int sock; - int nbytes; - struct vty *vty; - unsigned char buf[VTY_READ_BUFSIZ]; - unsigned char *p; - u_char header[4] = {0, 0, 0, 0}; - - sock = THREAD_FD (thread); - vty = THREAD_ARG (thread); - vty->t_read = NULL; - - if ((nbytes = read (sock, buf, VTY_READ_BUFSIZ)) <= 0) - { - if (nbytes < 0) - { - if (ERRNO_IO_RETRY(errno)) - { - vty_event (VTYSH_READ, sock, vty); - return 0; - } - vty->monitor = 0; /* disable monitoring to avoid infinite recursion */ - zlog_warn("%s: read failed on vtysh client fd %d, closing: %s", - __func__, sock, safe_strerror(errno)); - } - buffer_reset(vty->obuf); - vty_close (vty); + vty = vty_new(); + vty->fd = sock; + vty->wfd = sock; + vty->type = VTY_SHELL_SERV; + vty->node = VIEW_NODE; + + vty_event(VTYSH_READ, sock, vty); + + return 0; +} + +static int vtysh_flush(struct vty *vty) +{ + switch (buffer_flush_available(vty->obuf, vty->wfd)) { + case BUFFER_PENDING: + vty_event(VTYSH_WRITE, vty->wfd, vty); + break; + case BUFFER_ERROR: + vty->monitor = + 0; /* disable monitoring to avoid infinite recursion */ + zlog_warn("%s: write error to fd %d, closing", __func__, + vty->fd); + buffer_reset(vty->obuf); + vty_close(vty); + return -1; + break; + case BUFFER_EMPTY: + break; + } + return 0; +} + +static int vtysh_read(struct thread *thread) +{ + int ret; + int sock; + int nbytes; + struct vty *vty; + unsigned char buf[VTY_READ_BUFSIZ]; + unsigned char *p; + u_char header[4] = {0, 0, 0, 0}; + + sock = THREAD_FD(thread); + vty = THREAD_ARG(thread); + vty->t_read = NULL; + + if ((nbytes = read(sock, buf, VTY_READ_BUFSIZ)) <= 0) { + if (nbytes < 0) { + if (ERRNO_IO_RETRY(errno)) { + vty_event(VTYSH_READ, sock, vty); + return 0; + } + vty->monitor = 0; /* disable monitoring to avoid + infinite recursion */ + zlog_warn( + "%s: read failed on vtysh client fd %d, closing: %s", + __func__, sock, safe_strerror(errno)); + } + buffer_reset(vty->obuf); + vty_close(vty); #ifdef VTYSH_DEBUG - printf ("close vtysh\n"); + printf("close vtysh\n"); #endif /* VTYSH_DEBUG */ - return 0; - } + return 0; + } #ifdef VTYSH_DEBUG - printf ("line: %.*s\n", nbytes, buf); + printf("line: %.*s\n", nbytes, buf); #endif /* VTYSH_DEBUG */ - if (vty->length + nbytes >= VTY_BUFSIZ) - { - /* Clear command line buffer. */ - vty->cp = vty->length = 0; - vty_clear_buf (vty); - vty_out (vty, "%% Command is too long.\n"); - } - else - { - for (p = buf; p < buf+nbytes; p++) - { - vty->buf[vty->length++] = *p; - if (*p == '\0') - { - /* Pass this line to parser. */ - ret = vty_execute (vty); - /* Note that vty_execute clears the command buffer and resets - vty->length to 0. */ - - /* Return result. */ + if (vty->length + nbytes >= VTY_BUFSIZ) { + /* Clear command line buffer. */ + vty->cp = vty->length = 0; + vty_clear_buf(vty); + vty_out(vty, "%% Command is too long.\n"); + } else { + for (p = buf; p < buf + nbytes; p++) { + vty->buf[vty->length++] = *p; + if (*p == '\0') { + /* Pass this line to parser. */ + ret = vty_execute(vty); +/* Note that vty_execute clears the command buffer and resets + vty->length to 0. */ + +/* Return result. */ #ifdef VTYSH_DEBUG - printf ("result: %d\n", ret); - printf ("vtysh node: %d\n", vty->node); + printf("result: %d\n", ret); + printf("vtysh node: %d\n", vty->node); #endif /* VTYSH_DEBUG */ - /* hack for asynchronous "write integrated" - * - other commands in "buf" will be ditched - * - input during pending config-write is "unsupported" */ - if (ret == CMD_SUSPEND) - break; + /* hack for asynchronous "write integrated" + * - other commands in "buf" will be ditched + * - input during pending config-write is + * "unsupported" */ + if (ret == CMD_SUSPEND) + break; - /* warning: watchfrr hardcodes this result write */ - header[3] = ret; - buffer_put(vty->obuf, header, 4); + /* warning: watchfrr hardcodes this result write + */ + header[3] = ret; + buffer_put(vty->obuf, header, 4); - if (!vty->t_write && (vtysh_flush(vty) < 0)) - /* Try to flush results; exit if a write error occurs. */ - return 0; - } - } - } + if (!vty->t_write && (vtysh_flush(vty) < 0)) + /* Try to flush results; exit if a write + * error occurs. */ + return 0; + } + } + } - if (vty->status == VTY_CLOSE) - vty_close (vty); - else - vty_event (VTYSH_READ, sock, vty); + if (vty->status == VTY_CLOSE) + vty_close(vty); + else + vty_event(VTYSH_READ, sock, vty); - return 0; + return 0; } -static int -vtysh_write (struct thread *thread) +static int vtysh_write(struct thread *thread) { - struct vty *vty = THREAD_ARG (thread); + struct vty *vty = THREAD_ARG(thread); - vty->t_write = NULL; - vtysh_flush(vty); - return 0; + vty->t_write = NULL; + vtysh_flush(vty); + return 0; } #endif /* VTYSH */ /* Determine address family to bind. */ -void -vty_serv_sock (const char *addr, unsigned short port, const char *path) +void vty_serv_sock(const char *addr, unsigned short port, const char *path) { - /* If port is set to 0, do not listen on TCP/IP at all! */ - if (port) - vty_serv_sock_addrinfo (addr, port); + /* If port is set to 0, do not listen on TCP/IP at all! */ + if (port) + vty_serv_sock_addrinfo(addr, port); #ifdef VTYSH - vty_serv_un (path); + vty_serv_un(path); #endif /* VTYSH */ } @@ -2247,444 +2104,422 @@ vty_serv_sock (const char *addr, unsigned short port, const char *path) will be careful not to access the vty afterwards (since it has now been freed). This is safest from top-level functions (called directly by the thread dispatcher). */ -void -vty_close (struct vty *vty) +void vty_close(struct vty *vty) { - int i; - bool was_stdio = false; + int i; + bool was_stdio = false; - /* Cancel threads.*/ - if (vty->t_read) - thread_cancel (vty->t_read); - if (vty->t_write) - thread_cancel (vty->t_write); - if (vty->t_timeout) - thread_cancel (vty->t_timeout); + /* Cancel threads.*/ + if (vty->t_read) + thread_cancel(vty->t_read); + if (vty->t_write) + thread_cancel(vty->t_write); + if (vty->t_timeout) + thread_cancel(vty->t_timeout); - /* Flush buffer. */ - buffer_flush_all (vty->obuf, vty->wfd); + /* Flush buffer. */ + buffer_flush_all(vty->obuf, vty->wfd); - /* Free input buffer. */ - buffer_free (vty->obuf); + /* Free input buffer. */ + buffer_free(vty->obuf); - /* Free command history. */ - for (i = 0; i < VTY_MAXHIST; i++) - if (vty->hist[i]) - XFREE (MTYPE_VTY_HIST, vty->hist[i]); + /* Free command history. */ + for (i = 0; i < VTY_MAXHIST; i++) + if (vty->hist[i]) + XFREE(MTYPE_VTY_HIST, vty->hist[i]); - /* Unset vector. */ - vector_unset (vtyvec, vty->fd); + /* Unset vector. */ + vector_unset(vtyvec, vty->fd); - if (vty->wfd > 0 && vty->type == VTY_FILE) - fsync (vty->wfd); + if (vty->wfd > 0 && vty->type == VTY_FILE) + fsync(vty->wfd); - /* Close socket. */ - if (vty->fd > 0) - { - close (vty->fd); - if (vty->wfd > 0 && vty->wfd != vty->fd) - close (vty->wfd); - } - else - was_stdio = true; + /* Close socket. */ + if (vty->fd > 0) { + close(vty->fd); + if (vty->wfd > 0 && vty->wfd != vty->fd) + close(vty->wfd); + } else + was_stdio = true; - if (vty->buf) - XFREE (MTYPE_VTY, vty->buf); + if (vty->buf) + XFREE(MTYPE_VTY, vty->buf); - if (vty->error_buf) - XFREE (MTYPE_VTY, vty->error_buf); + if (vty->error_buf) + XFREE(MTYPE_VTY, vty->error_buf); - /* Check configure. */ - vty_config_unlock (vty); + /* Check configure. */ + vty_config_unlock(vty); - /* OK free vty. */ - XFREE (MTYPE_VTY, vty); + /* OK free vty. */ + XFREE(MTYPE_VTY, vty); - if (was_stdio) - vty_stdio_reset (); + if (was_stdio) + vty_stdio_reset(); } /* When time out occur output message then close connection. */ -static int -vty_timeout (struct thread *thread) +static int vty_timeout(struct thread *thread) { - struct vty *vty; + struct vty *vty; - vty = THREAD_ARG (thread); - vty->t_timeout = NULL; - vty->v_timeout = 0; + vty = THREAD_ARG(thread); + vty->t_timeout = NULL; + vty->v_timeout = 0; - /* Clear buffer*/ - buffer_reset (vty->obuf); - vty_out (vty, "\nVty connection is timed out.\n"); + /* Clear buffer*/ + buffer_reset(vty->obuf); + vty_out(vty, "\nVty connection is timed out.\n"); - /* Close connection. */ - vty->status = VTY_CLOSE; - vty_close (vty); + /* Close connection. */ + vty->status = VTY_CLOSE; + vty_close(vty); - return 0; + return 0; } /* Read up configuration file from file_name. */ -static void -vty_read_file (FILE *confp) -{ - int ret; - struct vty *vty; - unsigned int line_num = 0; - - vty = vty_new (); - vty->wfd = dup(STDERR_FILENO); /* vty_close() will close this */ - if (vty->wfd < 0) - { - /* Fine, we couldn't make a new fd. vty_close doesn't close stdout. */ - vty->wfd = STDOUT_FILENO; - } - vty->fd = STDIN_FILENO; - vty->type = VTY_FILE; - vty->node = CONFIG_NODE; - - /* Execute configuration file */ - ret = config_from_file (vty, confp, &line_num); - - /* Flush any previous errors before printing messages below */ - buffer_flush_all (vty->obuf, vty->fd); - - if ( !((ret == CMD_SUCCESS) || (ret == CMD_ERR_NOTHING_TODO)) ) - { - const char *message = NULL; - switch (ret) - { - case CMD_ERR_AMBIGUOUS: - message = "*** Error reading config: Ambiguous command."; - break; - case CMD_ERR_NO_MATCH: - message = "*** Error reading config: There is no such command."; - break; - } - fprintf (stderr, "%s\n", message); - zlog_err ("%s", message); - fprintf (stderr, "*** Error occurred processing line %u, below:\n%s\n", - line_num, vty->error_buf); - zlog_err ("*** Error occurred processing line %u, below:\n%s", - line_num, vty->error_buf); - } - - vty_close (vty); -} - -static FILE * -vty_use_backup_config (const char *fullpath) -{ - char *fullpath_sav, *fullpath_tmp; - FILE *ret = NULL; - int tmp, sav; - int c; - char buffer[512]; - - fullpath_sav = malloc (strlen (fullpath) + strlen (CONF_BACKUP_EXT) + 1); - strcpy (fullpath_sav, fullpath); - strcat (fullpath_sav, CONF_BACKUP_EXT); - - sav = open (fullpath_sav, O_RDONLY); - if (sav < 0) - { - free (fullpath_sav); - return NULL; - } - - fullpath_tmp = malloc (strlen (fullpath) + 8); - sprintf (fullpath_tmp, "%s.XXXXXX", fullpath); - - /* Open file to configuration write. */ - tmp = mkstemp (fullpath_tmp); - if (tmp < 0) - goto out_close_sav; - - if (fchmod (tmp, CONFIGFILE_MASK) != 0) - goto out_close; - - while((c = read (sav, buffer, 512)) > 0) - { - if (write (tmp, buffer, c) <= 0) - goto out_close; - } - close (sav); - close (tmp); - - if (rename (fullpath_tmp, fullpath) == 0) - ret = fopen (fullpath, "r"); - else - unlink (fullpath_tmp); - - if (0) - { -out_close: - close (tmp); - unlink (fullpath_tmp); -out_close_sav: - close (sav); - } - - free (fullpath_sav); - free (fullpath_tmp); - return ret; +static void vty_read_file(FILE *confp) +{ + int ret; + struct vty *vty; + unsigned int line_num = 0; + + vty = vty_new(); + vty->wfd = dup(STDERR_FILENO); /* vty_close() will close this */ + if (vty->wfd < 0) { + /* Fine, we couldn't make a new fd. vty_close doesn't close + * stdout. */ + vty->wfd = STDOUT_FILENO; + } + vty->fd = STDIN_FILENO; + vty->type = VTY_FILE; + vty->node = CONFIG_NODE; + + /* Execute configuration file */ + ret = config_from_file(vty, confp, &line_num); + + /* Flush any previous errors before printing messages below */ + buffer_flush_all(vty->obuf, vty->fd); + + if (!((ret == CMD_SUCCESS) || (ret == CMD_ERR_NOTHING_TODO))) { + const char *message = NULL; + switch (ret) { + case CMD_ERR_AMBIGUOUS: + message = + "*** Error reading config: Ambiguous command."; + break; + case CMD_ERR_NO_MATCH: + message = + "*** Error reading config: There is no such command."; + break; + } + fprintf(stderr, "%s\n", message); + zlog_err("%s", message); + fprintf(stderr, + "*** Error occurred processing line %u, below:\n%s\n", + line_num, vty->error_buf); + zlog_err("*** Error occurred processing line %u, below:\n%s", + line_num, vty->error_buf); + } + + vty_close(vty); +} + +static FILE *vty_use_backup_config(const char *fullpath) +{ + char *fullpath_sav, *fullpath_tmp; + FILE *ret = NULL; + int tmp, sav; + int c; + char buffer[512]; + + fullpath_sav = malloc(strlen(fullpath) + strlen(CONF_BACKUP_EXT) + 1); + strcpy(fullpath_sav, fullpath); + strcat(fullpath_sav, CONF_BACKUP_EXT); + + sav = open(fullpath_sav, O_RDONLY); + if (sav < 0) { + free(fullpath_sav); + return NULL; + } + + fullpath_tmp = malloc(strlen(fullpath) + 8); + sprintf(fullpath_tmp, "%s.XXXXXX", fullpath); + + /* Open file to configuration write. */ + tmp = mkstemp(fullpath_tmp); + if (tmp < 0) + goto out_close_sav; + + if (fchmod(tmp, CONFIGFILE_MASK) != 0) + goto out_close; + + while ((c = read(sav, buffer, 512)) > 0) { + if (write(tmp, buffer, c) <= 0) + goto out_close; + } + close(sav); + close(tmp); + + if (rename(fullpath_tmp, fullpath) == 0) + ret = fopen(fullpath, "r"); + else + unlink(fullpath_tmp); + + if (0) { + out_close: + close(tmp); + unlink(fullpath_tmp); + out_close_sav: + close(sav); + } + + free(fullpath_sav); + free(fullpath_tmp); + return ret; } /* Read up configuration file from file_name. */ -void -vty_read_config (const char *config_file, - char *config_default_dir) -{ - char cwd[MAXPATHLEN]; - FILE *confp = NULL; - const char *fullpath; - char *tmp = NULL; - - /* If -f flag specified. */ - if (config_file != NULL) - { - if (! IS_DIRECTORY_SEP (config_file[0])) - { - if (getcwd (cwd, MAXPATHLEN) == NULL) - { - fprintf (stderr, "Failure to determine Current Working Directory %d!\n", errno); - exit (1); - } - tmp = XMALLOC (MTYPE_TMP, - strlen (cwd) + strlen (config_file) + 2); - sprintf (tmp, "%s/%s", cwd, config_file); - fullpath = tmp; - } - else - fullpath = config_file; - - confp = fopen (fullpath, "r"); - - if (confp == NULL) - { - fprintf (stderr, "%s: failed to open configuration file %s: %s\n", - __func__, fullpath, safe_strerror (errno)); - - confp = vty_use_backup_config (fullpath); - if (confp) - fprintf (stderr, "WARNING: using backup configuration file!\n"); - else - { - fprintf (stderr, "can't open configuration file [%s]\n", - config_file); - exit(1); - } - } - } - else - { - - host_config_set (config_default_dir); +void vty_read_config(const char *config_file, char *config_default_dir) +{ + char cwd[MAXPATHLEN]; + FILE *confp = NULL; + const char *fullpath; + char *tmp = NULL; + + /* If -f flag specified. */ + if (config_file != NULL) { + if (!IS_DIRECTORY_SEP(config_file[0])) { + if (getcwd(cwd, MAXPATHLEN) == NULL) { + fprintf(stderr, + "Failure to determine Current Working Directory %d!\n", + errno); + exit(1); + } + tmp = XMALLOC(MTYPE_TMP, + strlen(cwd) + strlen(config_file) + 2); + sprintf(tmp, "%s/%s", cwd, config_file); + fullpath = tmp; + } else + fullpath = config_file; + + confp = fopen(fullpath, "r"); + + if (confp == NULL) { + fprintf(stderr, + "%s: failed to open configuration file %s: %s\n", + __func__, fullpath, safe_strerror(errno)); + + confp = vty_use_backup_config(fullpath); + if (confp) + fprintf(stderr, + "WARNING: using backup configuration file!\n"); + else { + fprintf(stderr, + "can't open configuration file [%s]\n", + config_file); + exit(1); + } + } + } else { + + host_config_set(config_default_dir); #ifdef VTYSH - int ret; - struct stat conf_stat; - - /* !!!!PLEASE LEAVE!!!! - * This is NEEDED for use with vtysh -b, or else you can get - * a real configuration food fight with a lot garbage in the - * merged configuration file it creates coming from the per - * daemon configuration files. This also allows the daemons - * to start if there default configuration file is not - * present or ignore them, as needed when using vtysh -b to - * configure the daemons at boot - MAG - */ - - /* Stat for vtysh Zebra.conf, if found startup and wait for - * boot configuration - */ - - if ( strstr(config_default_dir, "vtysh") == NULL) - { - ret = stat (integrate_default, &conf_stat); - if (ret >= 0) - goto tmp_free_and_out; - } + int ret; + struct stat conf_stat; + + /* !!!!PLEASE LEAVE!!!! + * This is NEEDED for use with vtysh -b, or else you can get + * a real configuration food fight with a lot garbage in the + * merged configuration file it creates coming from the per + * daemon configuration files. This also allows the daemons + * to start if there default configuration file is not + * present or ignore them, as needed when using vtysh -b to + * configure the daemons at boot - MAG + */ + + /* Stat for vtysh Zebra.conf, if found startup and wait for + * boot configuration + */ + + if (strstr(config_default_dir, "vtysh") == NULL) { + ret = stat(integrate_default, &conf_stat); + if (ret >= 0) + goto tmp_free_and_out; + } #endif /* VTYSH */ - confp = fopen (config_default_dir, "r"); - if (confp == NULL) - { - fprintf (stderr, "%s: failed to open configuration file %s: %s\n", - __func__, config_default_dir, safe_strerror (errno)); - - confp = vty_use_backup_config (config_default_dir); - if (confp) - { - fprintf (stderr, "WARNING: using backup configuration file!\n"); - fullpath = config_default_dir; - } - else - { - fprintf (stderr, "can't open configuration file [%s]\n", - config_default_dir); - goto tmp_free_and_out; - } - } - else - fullpath = config_default_dir; - } - - vty_read_file (confp); - - fclose (confp); - - host_config_set (fullpath); + confp = fopen(config_default_dir, "r"); + if (confp == NULL) { + fprintf(stderr, + "%s: failed to open configuration file %s: %s\n", + __func__, config_default_dir, + safe_strerror(errno)); + + confp = vty_use_backup_config(config_default_dir); + if (confp) { + fprintf(stderr, + "WARNING: using backup configuration file!\n"); + fullpath = config_default_dir; + } else { + fprintf(stderr, + "can't open configuration file [%s]\n", + config_default_dir); + goto tmp_free_and_out; + } + } else + fullpath = config_default_dir; + } + + vty_read_file(confp); + + fclose(confp); + + host_config_set(fullpath); tmp_free_and_out: - if (tmp) - XFREE (MTYPE_TMP, tmp); + if (tmp) + XFREE(MTYPE_TMP, tmp); } /* Small utility function which output log to the VTY. */ -void -vty_log (const char *level, const char *proto_str, - const char *format, struct timestamp_control *ctl, va_list va) +void vty_log(const char *level, const char *proto_str, const char *format, + struct timestamp_control *ctl, va_list va) { - unsigned int i; - struct vty *vty; + unsigned int i; + struct vty *vty; - if (!vtyvec) - return; + if (!vtyvec) + return; - for (i = 0; i < vector_active (vtyvec); i++) - if ((vty = vector_slot (vtyvec, i)) != NULL) - if (vty->monitor) - { - va_list ac; - va_copy(ac, va); - vty_log_out (vty, level, proto_str, format, ctl, ac); - va_end(ac); - } + for (i = 0; i < vector_active(vtyvec); i++) + if ((vty = vector_slot(vtyvec, i)) != NULL) + if (vty->monitor) { + va_list ac; + va_copy(ac, va); + vty_log_out(vty, level, proto_str, format, ctl, + ac); + va_end(ac); + } } /* Async-signal-safe version of vty_log for fixed strings. */ -void -vty_log_fixed (char *buf, size_t len) +void vty_log_fixed(char *buf, size_t len) { - unsigned int i; - struct iovec iov[2]; - char crlf[4] = "\r\n"; + unsigned int i; + struct iovec iov[2]; + char crlf[4] = "\r\n"; - /* vty may not have been initialised */ - if (!vtyvec) - return; + /* vty may not have been initialised */ + if (!vtyvec) + return; - iov[0].iov_base = buf; - iov[0].iov_len = len; - iov[1].iov_base = crlf; - iov[1].iov_len = 2; + iov[0].iov_base = buf; + iov[0].iov_len = len; + iov[1].iov_base = crlf; + iov[1].iov_len = 2; - for (i = 0; i < vector_active (vtyvec); i++) - { - struct vty *vty; - if (((vty = vector_slot (vtyvec, i)) != NULL) && vty->monitor) - /* N.B. We don't care about the return code, since process is - most likely just about to die anyway. */ - if (writev(vty->wfd, iov, 2) == -1) - { - fprintf(stderr, "Failure to writev: %d\n", errno); - exit(-1); - } - } + for (i = 0; i < vector_active(vtyvec); i++) { + struct vty *vty; + if (((vty = vector_slot(vtyvec, i)) != NULL) && vty->monitor) + /* N.B. We don't care about the return code, since + process is + most likely just about to die anyway. */ + if (writev(vty->wfd, iov, 2) == -1) { + fprintf(stderr, "Failure to writev: %d\n", + errno); + exit(-1); + } + } } -int -vty_config_lock (struct vty *vty) +int vty_config_lock(struct vty *vty) { - if (vty_config_is_lockless) - return 1; - if (vty_config == 0) - { - vty->config = 1; - vty_config = 1; - } - return vty->config; + if (vty_config_is_lockless) + return 1; + if (vty_config == 0) { + vty->config = 1; + vty_config = 1; + } + return vty->config; } -int -vty_config_unlock (struct vty *vty) +int vty_config_unlock(struct vty *vty) { - if (vty_config_is_lockless) - return 0; - if (vty_config == 1 && vty->config == 1) - { - vty->config = 0; - vty_config = 0; - } - return vty->config; + if (vty_config_is_lockless) + return 0; + if (vty_config == 1 && vty->config == 1) { + vty->config = 0; + vty_config = 0; + } + return vty->config; } -void -vty_config_lockless (void) +void vty_config_lockless(void) { - vty_config_is_lockless = 1; + vty_config_is_lockless = 1; } /* Master of the threads. */ static struct thread_master *vty_master; -static void -vty_event (enum event event, int sock, struct vty *vty) +static void vty_event(enum event event, int sock, struct vty *vty) { - struct thread *vty_serv_thread = NULL; + struct thread *vty_serv_thread = NULL; - switch (event) - { - case VTY_SERV: - vty_serv_thread = thread_add_read(vty_master, vty_accept, vty, sock, NULL); - vector_set_index (Vvty_serv_thread, sock, vty_serv_thread); - break; + switch (event) { + case VTY_SERV: + vty_serv_thread = thread_add_read(vty_master, vty_accept, vty, + sock, NULL); + vector_set_index(Vvty_serv_thread, sock, vty_serv_thread); + break; #ifdef VTYSH - case VTYSH_SERV: - vty_serv_thread = thread_add_read(vty_master, vtysh_accept, vty, sock, NULL); - vector_set_index (Vvty_serv_thread, sock, vty_serv_thread); - break; - case VTYSH_READ: - vty->t_read = NULL; - thread_add_read(vty_master, vtysh_read, vty, sock, &vty->t_read); - break; - case VTYSH_WRITE: - vty->t_write = NULL; - thread_add_write(vty_master, vtysh_write, vty, sock, &vty->t_write); - break; + case VTYSH_SERV: + vty_serv_thread = thread_add_read(vty_master, vtysh_accept, vty, + sock, NULL); + vector_set_index(Vvty_serv_thread, sock, vty_serv_thread); + break; + case VTYSH_READ: + vty->t_read = NULL; + thread_add_read(vty_master, vtysh_read, vty, sock, + &vty->t_read); + break; + case VTYSH_WRITE: + vty->t_write = NULL; + thread_add_write(vty_master, vtysh_write, vty, sock, + &vty->t_write); + break; #endif /* VTYSH */ - case VTY_READ: - vty->t_read = NULL; - thread_add_read(vty_master, vty_read, vty, sock, &vty->t_read); - - /* Time out treatment. */ - if (vty->v_timeout) - { - if (vty->t_timeout) - thread_cancel (vty->t_timeout); - vty->t_timeout = NULL; - thread_add_timer(vty_master, vty_timeout, vty, vty->v_timeout, - &vty->t_timeout); - } - break; - case VTY_WRITE: - thread_add_write(vty_master, vty_flush, vty, sock, &vty->t_write); - break; - case VTY_TIMEOUT_RESET: - if (vty->t_timeout) - { - thread_cancel (vty->t_timeout); - vty->t_timeout = NULL; - } - if (vty->v_timeout) - { - vty->t_timeout = NULL; - thread_add_timer(vty_master, vty_timeout, vty, vty->v_timeout, - &vty->t_timeout); - } - break; - } + case VTY_READ: + vty->t_read = NULL; + thread_add_read(vty_master, vty_read, vty, sock, &vty->t_read); + + /* Time out treatment. */ + if (vty->v_timeout) { + if (vty->t_timeout) + thread_cancel(vty->t_timeout); + vty->t_timeout = NULL; + thread_add_timer(vty_master, vty_timeout, vty, + vty->v_timeout, &vty->t_timeout); + } + break; + case VTY_WRITE: + thread_add_write(vty_master, vty_flush, vty, sock, + &vty->t_write); + break; + case VTY_TIMEOUT_RESET: + if (vty->t_timeout) { + thread_cancel(vty->t_timeout); + vty->t_timeout = NULL; + } + if (vty->v_timeout) { + vty->t_timeout = NULL; + thread_add_timer(vty_master, vty_timeout, vty, + vty->v_timeout, &vty->t_timeout); + } + break; + } } DEFUN_NOSH (config_who, @@ -2692,15 +2527,14 @@ DEFUN_NOSH (config_who, "who", "Display who is on vty\n") { - unsigned int i; - struct vty *v; + unsigned int i; + struct vty *v; - for (i = 0; i < vector_active (vtyvec); i++) - if ((v = vector_slot (vtyvec, i)) != NULL) - vty_out (vty, "%svty[%d] connected from %s.\n", - v->config ? "*" : " ", - i, v->address); - return CMD_SUCCESS; + for (i = 0; i < vector_active(vtyvec); i++) + if ((v = vector_slot(vtyvec, i)) != NULL) + vty_out(vty, "%svty[%d] connected from %s.\n", + v->config ? "*" : " ", i, v->address); + return CMD_SUCCESS; } /* Move to vty configuration mode. */ @@ -2710,32 +2544,31 @@ DEFUN_NOSH (line_vty, "Configure a terminal line\n" "Virtual terminal\n") { - vty->node = VTY_NODE; - return CMD_SUCCESS; + vty->node = VTY_NODE; + return CMD_SUCCESS; } /* Set time out value. */ -static int -exec_timeout (struct vty *vty, const char *min_str, const char *sec_str) +static int exec_timeout(struct vty *vty, const char *min_str, + const char *sec_str) { - unsigned long timeout = 0; + unsigned long timeout = 0; - /* min_str and sec_str are already checked by parser. So it must be - all digit string. */ - if (min_str) - { - timeout = strtol (min_str, NULL, 10); - timeout *= 60; - } - if (sec_str) - timeout += strtol (sec_str, NULL, 10); + /* min_str and sec_str are already checked by parser. So it must be + all digit string. */ + if (min_str) { + timeout = strtol(min_str, NULL, 10); + timeout *= 60; + } + if (sec_str) + timeout += strtol(sec_str, NULL, 10); - vty_timeout_val = timeout; - vty->v_timeout = timeout; - vty_event (VTY_TIMEOUT_RESET, 0, vty); + vty_timeout_val = timeout; + vty->v_timeout = timeout; + vty_event(VTY_TIMEOUT_RESET, 0, vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (exec_timeout_min, @@ -2744,8 +2577,8 @@ DEFUN (exec_timeout_min, "Set timeout value\n" "Timeout value in minutes\n") { - int idx_number = 1; - return exec_timeout (vty, argv[idx_number]->arg, NULL); + int idx_number = 1; + return exec_timeout(vty, argv[idx_number]->arg, NULL); } DEFUN (exec_timeout_sec, @@ -2755,9 +2588,10 @@ DEFUN (exec_timeout_sec, "Timeout in minutes\n" "Timeout in seconds\n") { - int idx_number = 1; - int idx_number_2 = 2; - return exec_timeout (vty, argv[idx_number]->arg, argv[idx_number_2]->arg); + int idx_number = 1; + int idx_number_2 = 2; + return exec_timeout(vty, argv[idx_number]->arg, + argv[idx_number_2]->arg); } DEFUN (no_exec_timeout, @@ -2766,7 +2600,7 @@ DEFUN (no_exec_timeout, NO_STR "Set the EXEC timeout\n") { - return exec_timeout (vty, NULL, NULL); + return exec_timeout(vty, NULL, NULL); } /* Set vty access class. */ @@ -2776,13 +2610,13 @@ DEFUN (vty_access_class, "Filter connections based on an IP access list\n" "IP access list\n") { - int idx_word = 1; - if (vty_accesslist_name) - XFREE(MTYPE_VTY, vty_accesslist_name); + int idx_word = 1; + if (vty_accesslist_name) + XFREE(MTYPE_VTY, vty_accesslist_name); - vty_accesslist_name = XSTRDUP(MTYPE_VTY, argv[idx_word]->arg); + vty_accesslist_name = XSTRDUP(MTYPE_VTY, argv[idx_word]->arg); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Clear vty access class. */ @@ -2793,19 +2627,19 @@ DEFUN (no_vty_access_class, "Filter connections based on an IP access list\n" "IP access list\n") { - int idx_word = 2; - const char *accesslist = (argc == 3) ? argv[idx_word]->arg : NULL; - if (! vty_accesslist_name || (argc == 3 && strcmp(vty_accesslist_name, accesslist))) - { - vty_out (vty,"Access-class is not currently applied to vty\n"); - return CMD_WARNING_CONFIG_FAILED; - } + int idx_word = 2; + const char *accesslist = (argc == 3) ? argv[idx_word]->arg : NULL; + if (!vty_accesslist_name + || (argc == 3 && strcmp(vty_accesslist_name, accesslist))) { + vty_out(vty, "Access-class is not currently applied to vty\n"); + return CMD_WARNING_CONFIG_FAILED; + } - XFREE(MTYPE_VTY, vty_accesslist_name); + XFREE(MTYPE_VTY, vty_accesslist_name); - vty_accesslist_name = NULL; + vty_accesslist_name = NULL; - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Set vty access class. */ @@ -2816,13 +2650,13 @@ DEFUN (vty_ipv6_access_class, "Filter connections based on an IP access list\n" "IPv6 access list\n") { - int idx_word = 2; - if (vty_ipv6_accesslist_name) - XFREE(MTYPE_VTY, vty_ipv6_accesslist_name); + int idx_word = 2; + if (vty_ipv6_accesslist_name) + XFREE(MTYPE_VTY, vty_ipv6_accesslist_name); - vty_ipv6_accesslist_name = XSTRDUP(MTYPE_VTY, argv[idx_word]->arg); + vty_ipv6_accesslist_name = XSTRDUP(MTYPE_VTY, argv[idx_word]->arg); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Clear vty access class. */ @@ -2834,21 +2668,21 @@ DEFUN (no_vty_ipv6_access_class, "Filter connections based on an IP access list\n" "IPv6 access list\n") { - int idx_word = 3; - const char *accesslist = (argc == 4) ? argv[idx_word]->arg : NULL; + int idx_word = 3; + const char *accesslist = (argc == 4) ? argv[idx_word]->arg : NULL; - if (! vty_ipv6_accesslist_name || - (argc == 4 && strcmp(vty_ipv6_accesslist_name, accesslist))) - { - vty_out (vty,"IPv6 access-class is not currently applied to vty\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!vty_ipv6_accesslist_name + || (argc == 4 && strcmp(vty_ipv6_accesslist_name, accesslist))) { + vty_out(vty, + "IPv6 access-class is not currently applied to vty\n"); + return CMD_WARNING_CONFIG_FAILED; + } - XFREE(MTYPE_VTY, vty_ipv6_accesslist_name); + XFREE(MTYPE_VTY, vty_ipv6_accesslist_name); - vty_ipv6_accesslist_name = NULL; + vty_ipv6_accesslist_name = NULL; - return CMD_SUCCESS; + return CMD_SUCCESS; } /* vty login. */ @@ -2857,8 +2691,8 @@ DEFUN (vty_login, "login", "Enable password checking\n") { - no_password_check = 0; - return CMD_SUCCESS; + no_password_check = 0; + return CMD_SUCCESS; } DEFUN (no_vty_login, @@ -2867,8 +2701,8 @@ DEFUN (no_vty_login, NO_STR "Enable password checking\n") { - no_password_check = 1; - return CMD_SUCCESS; + no_password_check = 1; + return CMD_SUCCESS; } DEFUN (service_advanced_vty, @@ -2877,8 +2711,8 @@ DEFUN (service_advanced_vty, "Set up miscellaneous service\n" "Enable advanced mode vty interface\n") { - host.advanced = 1; - return CMD_SUCCESS; + host.advanced = 1; + return CMD_SUCCESS; } DEFUN (no_service_advanced_vty, @@ -2888,8 +2722,8 @@ DEFUN (no_service_advanced_vty, "Set up miscellaneous service\n" "Enable advanced mode vty interface\n") { - host.advanced = 0; - return CMD_SUCCESS; + host.advanced = 0; + return CMD_SUCCESS; } DEFUN_NOSH (terminal_monitor, @@ -2898,8 +2732,8 @@ DEFUN_NOSH (terminal_monitor, "Set terminal line parameters\n" "Copy debug output to the current terminal line\n") { - vty->monitor = 1; - return CMD_SUCCESS; + vty->monitor = 1; + return CMD_SUCCESS; } DEFUN_NOSH (terminal_no_monitor, @@ -2909,8 +2743,8 @@ DEFUN_NOSH (terminal_no_monitor, NO_STR "Copy debug output to the current terminal line\n") { - vty->monitor = 0; - return CMD_SUCCESS; + vty->monitor = 0; + return CMD_SUCCESS; } DEFUN_NOSH (no_terminal_monitor, @@ -2920,7 +2754,7 @@ DEFUN_NOSH (no_terminal_monitor, "Set terminal line parameters\n" "Copy debug output to the current terminal line\n") { - return terminal_no_monitor (self, vty, argc, argv); + return terminal_no_monitor(self, vty, argc, argv); } @@ -2930,23 +2764,21 @@ DEFUN_NOSH (show_history, SHOW_STR "Display the session command history\n") { - int index; + int index; - for (index = vty->hindex + 1; index != vty->hindex;) - { - if (index == VTY_MAXHIST) - { - index = 0; - continue; - } + for (index = vty->hindex + 1; index != vty->hindex;) { + if (index == VTY_MAXHIST) { + index = 0; + continue; + } - if (vty->hist[index] != NULL) - vty_out (vty, " %s\n", vty->hist[index]); + if (vty->hist[index] != NULL) + vty_out(vty, " %s\n", vty->hist[index]); - index++; - } + index++; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* vty login. */ @@ -2956,197 +2788,178 @@ DEFUN (log_commands, "Logging control\n" "Log all commands (can't be unset without restart)\n") { - do_log_commands = 1; - return CMD_SUCCESS; + do_log_commands = 1; + return CMD_SUCCESS; } /* Display current configuration. */ -static int -vty_config_write (struct vty *vty) +static int vty_config_write(struct vty *vty) { - vty_out (vty, "line vty\n"); + vty_out(vty, "line vty\n"); - if (vty_accesslist_name) - vty_out (vty, " access-class %s\n", - vty_accesslist_name); + if (vty_accesslist_name) + vty_out(vty, " access-class %s\n", vty_accesslist_name); - if (vty_ipv6_accesslist_name) - vty_out (vty, " ipv6 access-class %s\n", - vty_ipv6_accesslist_name); + if (vty_ipv6_accesslist_name) + vty_out(vty, " ipv6 access-class %s\n", + vty_ipv6_accesslist_name); - /* exec-timeout */ - if (vty_timeout_val != VTY_TIMEOUT_DEFAULT) - vty_out (vty, " exec-timeout %ld %ld\n", - vty_timeout_val / 60, - vty_timeout_val % 60); + /* exec-timeout */ + if (vty_timeout_val != VTY_TIMEOUT_DEFAULT) + vty_out(vty, " exec-timeout %ld %ld\n", vty_timeout_val / 60, + vty_timeout_val % 60); - /* login */ - if (no_password_check) - vty_out (vty, " no login\n"); + /* login */ + if (no_password_check) + vty_out(vty, " no login\n"); - if (do_log_commands) - vty_out (vty, "log commands\n"); + if (do_log_commands) + vty_out(vty, "log commands\n"); - vty_out (vty, "!\n"); + vty_out(vty, "!\n"); - return CMD_SUCCESS; + return CMD_SUCCESS; } -struct cmd_node vty_node = -{ - VTY_NODE, - "%s(config-line)# ", - 1, +struct cmd_node vty_node = { + VTY_NODE, "%s(config-line)# ", 1, }; /* Reset all VTY status. */ -void -vty_reset () -{ - unsigned int i; - struct vty *vty; - struct thread *vty_serv_thread; - - for (i = 0; i < vector_active (vtyvec); i++) - if ((vty = vector_slot (vtyvec, i)) != NULL) - { - buffer_reset (vty->obuf); - vty->status = VTY_CLOSE; - vty_close (vty); - } - - for (i = 0; i < vector_active (Vvty_serv_thread); i++) - if ((vty_serv_thread = vector_slot (Vvty_serv_thread, i)) != NULL) - { - thread_cancel (vty_serv_thread); - vector_slot (Vvty_serv_thread, i) = NULL; - close (i); - } - - vty_timeout_val = VTY_TIMEOUT_DEFAULT; - - if (vty_accesslist_name) - { - XFREE(MTYPE_VTY, vty_accesslist_name); - vty_accesslist_name = NULL; - } - - if (vty_ipv6_accesslist_name) - { - XFREE(MTYPE_VTY, vty_ipv6_accesslist_name); - vty_ipv6_accesslist_name = NULL; - } +void vty_reset() +{ + unsigned int i; + struct vty *vty; + struct thread *vty_serv_thread; + + for (i = 0; i < vector_active(vtyvec); i++) + if ((vty = vector_slot(vtyvec, i)) != NULL) { + buffer_reset(vty->obuf); + vty->status = VTY_CLOSE; + vty_close(vty); + } + + for (i = 0; i < vector_active(Vvty_serv_thread); i++) + if ((vty_serv_thread = vector_slot(Vvty_serv_thread, i)) + != NULL) { + thread_cancel(vty_serv_thread); + vector_slot(Vvty_serv_thread, i) = NULL; + close(i); + } + + vty_timeout_val = VTY_TIMEOUT_DEFAULT; + + if (vty_accesslist_name) { + XFREE(MTYPE_VTY, vty_accesslist_name); + vty_accesslist_name = NULL; + } + + if (vty_ipv6_accesslist_name) { + XFREE(MTYPE_VTY, vty_ipv6_accesslist_name); + vty_ipv6_accesslist_name = NULL; + } } -static void -vty_save_cwd (void) +static void vty_save_cwd(void) { - char cwd[MAXPATHLEN]; - char *c; + char cwd[MAXPATHLEN]; + char *c; - c = getcwd (cwd, MAXPATHLEN); + c = getcwd(cwd, MAXPATHLEN); - if (!c) - { - /* - * At this point if these go wrong, more than likely - * the whole world is coming down around us - * Hence not worrying about it too much. - */ - if (!chdir (SYSCONFDIR)) - { - fprintf(stderr, "Failure to chdir to %s, errno: %d\n", SYSCONFDIR, errno); - exit(-1); - } - if (getcwd (cwd, MAXPATHLEN) == NULL) - { - fprintf(stderr, "Failure to getcwd, errno: %d\n", errno); - exit(-1); - } - } + if (!c) { + /* + * At this point if these go wrong, more than likely + * the whole world is coming down around us + * Hence not worrying about it too much. + */ + if (!chdir(SYSCONFDIR)) { + fprintf(stderr, "Failure to chdir to %s, errno: %d\n", + SYSCONFDIR, errno); + exit(-1); + } + if (getcwd(cwd, MAXPATHLEN) == NULL) { + fprintf(stderr, "Failure to getcwd, errno: %d\n", + errno); + exit(-1); + } + } - vty_cwd = XMALLOC (MTYPE_TMP, strlen (cwd) + 1); - strcpy (vty_cwd, cwd); + vty_cwd = XMALLOC(MTYPE_TMP, strlen(cwd) + 1); + strcpy(vty_cwd, cwd); } -char * -vty_get_cwd () +char *vty_get_cwd() { - return vty_cwd; + return vty_cwd; } -int -vty_shell (struct vty *vty) +int vty_shell(struct vty *vty) { - return vty->type == VTY_SHELL ? 1 : 0; + return vty->type == VTY_SHELL ? 1 : 0; } -int -vty_shell_serv (struct vty *vty) +int vty_shell_serv(struct vty *vty) { - return vty->type == VTY_SHELL_SERV ? 1 : 0; + return vty->type == VTY_SHELL_SERV ? 1 : 0; } -void -vty_init_vtysh () +void vty_init_vtysh() { - vtyvec = vector_init (VECTOR_MIN_SIZE); + vtyvec = vector_init(VECTOR_MIN_SIZE); } /* Install vty's own commands like `who' command. */ -void -vty_init (struct thread_master *master_thread) -{ - /* For further configuration read, preserve current directory. */ - vty_save_cwd (); - - vtyvec = vector_init (VECTOR_MIN_SIZE); - - vty_master = master_thread; - - atexit (vty_stdio_reset); - - /* Initilize server thread vector. */ - Vvty_serv_thread = vector_init (VECTOR_MIN_SIZE); - - /* Install bgp top node. */ - install_node (&vty_node, vty_config_write); - - install_element (VIEW_NODE, &config_who_cmd); - install_element (VIEW_NODE, &show_history_cmd); - install_element (CONFIG_NODE, &line_vty_cmd); - install_element (CONFIG_NODE, &service_advanced_vty_cmd); - install_element (CONFIG_NODE, &no_service_advanced_vty_cmd); - install_element (CONFIG_NODE, &show_history_cmd); - install_element (CONFIG_NODE, &log_commands_cmd); - install_element (ENABLE_NODE, &terminal_monitor_cmd); - install_element (ENABLE_NODE, &terminal_no_monitor_cmd); - install_element (ENABLE_NODE, &no_terminal_monitor_cmd); - - install_default (VTY_NODE); - install_element (VTY_NODE, &exec_timeout_min_cmd); - install_element (VTY_NODE, &exec_timeout_sec_cmd); - install_element (VTY_NODE, &no_exec_timeout_cmd); - install_element (VTY_NODE, &vty_access_class_cmd); - install_element (VTY_NODE, &no_vty_access_class_cmd); - install_element (VTY_NODE, &vty_login_cmd); - install_element (VTY_NODE, &no_vty_login_cmd); - install_element (VTY_NODE, &vty_ipv6_access_class_cmd); - install_element (VTY_NODE, &no_vty_ipv6_access_class_cmd); -} - -void -vty_terminate (void) -{ - if (vty_cwd) - XFREE (MTYPE_TMP, vty_cwd); - - if (vtyvec && Vvty_serv_thread) - { - vty_reset (); - vector_free (vtyvec); - vector_free (Vvty_serv_thread); - vtyvec = NULL; - Vvty_serv_thread = NULL; - } +void vty_init(struct thread_master *master_thread) +{ + /* For further configuration read, preserve current directory. */ + vty_save_cwd(); + + vtyvec = vector_init(VECTOR_MIN_SIZE); + + vty_master = master_thread; + + atexit(vty_stdio_reset); + + /* Initilize server thread vector. */ + Vvty_serv_thread = vector_init(VECTOR_MIN_SIZE); + + /* Install bgp top node. */ + install_node(&vty_node, vty_config_write); + + install_element(VIEW_NODE, &config_who_cmd); + install_element(VIEW_NODE, &show_history_cmd); + install_element(CONFIG_NODE, &line_vty_cmd); + install_element(CONFIG_NODE, &service_advanced_vty_cmd); + install_element(CONFIG_NODE, &no_service_advanced_vty_cmd); + install_element(CONFIG_NODE, &show_history_cmd); + install_element(CONFIG_NODE, &log_commands_cmd); + install_element(ENABLE_NODE, &terminal_monitor_cmd); + install_element(ENABLE_NODE, &terminal_no_monitor_cmd); + install_element(ENABLE_NODE, &no_terminal_monitor_cmd); + + install_default(VTY_NODE); + install_element(VTY_NODE, &exec_timeout_min_cmd); + install_element(VTY_NODE, &exec_timeout_sec_cmd); + install_element(VTY_NODE, &no_exec_timeout_cmd); + install_element(VTY_NODE, &vty_access_class_cmd); + install_element(VTY_NODE, &no_vty_access_class_cmd); + install_element(VTY_NODE, &vty_login_cmd); + install_element(VTY_NODE, &no_vty_login_cmd); + install_element(VTY_NODE, &vty_ipv6_access_class_cmd); + install_element(VTY_NODE, &no_vty_ipv6_access_class_cmd); +} + +void vty_terminate(void) +{ + if (vty_cwd) + XFREE(MTYPE_TMP, vty_cwd); + + if (vtyvec && Vvty_serv_thread) { + vty_reset(); + vector_free(vtyvec); + vector_free(Vvty_serv_thread); + vtyvec = NULL; + Vvty_serv_thread = NULL; + } } diff --git a/lib/vty.h b/lib/vty.h index 66450065f..0839f7fb6 100644 --- a/lib/vty.h +++ b/lib/vty.h @@ -30,150 +30,148 @@ #define VTY_MAXHIST 20 /* VTY struct. */ -struct vty -{ - /* File descripter of this vty. */ - int fd; +struct vty { + /* File descripter of this vty. */ + int fd; - /* output FD, to support stdin/stdout combination */ - int wfd; + /* output FD, to support stdin/stdout combination */ + int wfd; - /* Is this vty connect to file or not */ - enum {VTY_TERM, VTY_FILE, VTY_SHELL, VTY_SHELL_SERV} type; + /* Is this vty connect to file or not */ + enum { VTY_TERM, VTY_FILE, VTY_SHELL, VTY_SHELL_SERV } type; - /* Node status of this vty */ - int node; + /* Node status of this vty */ + int node; - /* Failure count */ - int fail; + /* Failure count */ + int fail; - /* Output buffer. */ - struct buffer *obuf; + /* Output buffer. */ + struct buffer *obuf; - /* Command input buffer */ - char *buf; + /* Command input buffer */ + char *buf; - /* Command input error buffer */ - char *error_buf; + /* Command input error buffer */ + char *error_buf; - /* Command cursor point */ - int cp; + /* Command cursor point */ + int cp; - /* Command length */ - int length; + /* Command length */ + int length; - /* Command max length. */ - int max; + /* Command max length. */ + int max; - /* Histry of command */ - char *hist[VTY_MAXHIST]; + /* Histry of command */ + char *hist[VTY_MAXHIST]; - /* History lookup current point */ - int hp; + /* History lookup current point */ + int hp; - /* History insert end point */ - int hindex; + /* History insert end point */ + int hindex; - /* qobj object ID (replacement for "index") */ - uint64_t qobj_index; + /* qobj object ID (replacement for "index") */ + uint64_t qobj_index; - /* qobj second-level object ID (replacement for "index_sub") */ - uint64_t qobj_index_sub; + /* qobj second-level object ID (replacement for "index_sub") */ + uint64_t qobj_index_sub; - /* For escape character. */ - unsigned char escape; + /* For escape character. */ + unsigned char escape; - /* Current vty status. */ - enum {VTY_NORMAL, VTY_CLOSE, VTY_MORE, VTY_MORELINE} status; + /* Current vty status. */ + enum { VTY_NORMAL, VTY_CLOSE, VTY_MORE, VTY_MORELINE } status; - /* IAC handling: was the last character received the - IAC (interpret-as-command) escape character (and therefore the next - character will be the command code)? Refer to Telnet RFC 854. */ - unsigned char iac; + /* IAC handling: was the last character received the + IAC (interpret-as-command) escape character (and therefore the next + character will be the command code)? Refer to Telnet RFC 854. */ + unsigned char iac; - /* IAC SB (option subnegotiation) handling */ - unsigned char iac_sb_in_progress; - /* At the moment, we care only about the NAWS (window size) negotiation, - and that requires just a 5-character buffer (RFC 1073): - <16-bit width> <16-bit height> */ + /* IAC SB (option subnegotiation) handling */ + unsigned char iac_sb_in_progress; +/* At the moment, we care only about the NAWS (window size) negotiation, + and that requires just a 5-character buffer (RFC 1073): + <16-bit width> <16-bit height> */ #define TELNET_NAWS_SB_LEN 5 - unsigned char sb_buf[TELNET_NAWS_SB_LEN]; - /* How many subnegotiation characters have we received? We just drop - those that do not fit in the buffer. */ - size_t sb_len; + unsigned char sb_buf[TELNET_NAWS_SB_LEN]; + /* How many subnegotiation characters have we received? We just drop + those that do not fit in the buffer. */ + size_t sb_len; - /* Window width/height. */ - int width; - int height; + /* Window width/height. */ + int width; + int height; - /* Configure lines. */ - int lines; + /* Configure lines. */ + int lines; - /* Terminal monitor. */ - int monitor; + /* Terminal monitor. */ + int monitor; - /* In configure mode. */ - int config; + /* In configure mode. */ + int config; - /* Read and write thread. */ - struct thread *t_read; - struct thread *t_write; + /* Read and write thread. */ + struct thread *t_read; + struct thread *t_write; - /* Timeout seconds and thread. */ - unsigned long v_timeout; - struct thread *t_timeout; + /* Timeout seconds and thread. */ + unsigned long v_timeout; + struct thread *t_timeout; - /* What address is this vty comming from. */ - char address[SU_ADDRSTRLEN]; + /* What address is this vty comming from. */ + char address[SU_ADDRSTRLEN]; }; -static inline void vty_push_context(struct vty *vty, - int node, uint64_t id) +static inline void vty_push_context(struct vty *vty, int node, uint64_t id) { - vty->node = node; - vty->qobj_index = id; + vty->node = node; + vty->qobj_index = id; } /* note: VTY_PUSH_CONTEXT(..., NULL) doesn't work, since it will try to * dereference "NULL->qobj_node.nid" */ -#define VTY_PUSH_CONTEXT(nodeval, ptr) \ +#define VTY_PUSH_CONTEXT(nodeval, ptr) \ vty_push_context(vty, nodeval, QOBJ_ID_0SAFE(ptr)) -#define VTY_PUSH_CONTEXT_NULL(nodeval) \ - vty_push_context(vty, nodeval, 0ULL) -#define VTY_PUSH_CONTEXT_SUB(nodeval, ptr) do { \ - vty->node = nodeval; \ - /* qobj_index stays untouched */ \ - vty->qobj_index_sub = QOBJ_ID_0SAFE(ptr); \ +#define VTY_PUSH_CONTEXT_NULL(nodeval) vty_push_context(vty, nodeval, 0ULL) +#define VTY_PUSH_CONTEXT_SUB(nodeval, ptr) \ + do { \ + vty->node = nodeval; \ + /* qobj_index stays untouched */ \ + vty->qobj_index_sub = QOBJ_ID_0SAFE(ptr); \ } while (0) /* can return NULL if context is invalid! */ -#define VTY_GET_CONTEXT(structname) \ +#define VTY_GET_CONTEXT(structname) \ QOBJ_GET_TYPESAFE(vty->qobj_index, structname) -#define VTY_GET_CONTEXT_SUB(structname) \ +#define VTY_GET_CONTEXT_SUB(structname) \ QOBJ_GET_TYPESAFE(vty->qobj_index_sub, structname) /* will return if ptr is NULL. */ -#define VTY_CHECK_CONTEXT(ptr) \ - if (!ptr) { \ - vty_out (vty, "Current configuration object was deleted " \ - "by another process.\n"); \ - return CMD_WARNING; \ +#define VTY_CHECK_CONTEXT(ptr) \ + if (!ptr) { \ + vty_out(vty, \ + "Current configuration object was deleted " \ + "by another process.\n"); \ + return CMD_WARNING; \ } /* struct structname *ptr = ; ptr will never be NULL. */ -#define VTY_DECLVAR_CONTEXT(structname, ptr) \ - struct structname *ptr = VTY_GET_CONTEXT(structname); \ +#define VTY_DECLVAR_CONTEXT(structname, ptr) \ + struct structname *ptr = VTY_GET_CONTEXT(structname); \ VTY_CHECK_CONTEXT(ptr); -#define VTY_DECLVAR_CONTEXT_SUB(structname, ptr) \ - struct structname *ptr = VTY_GET_CONTEXT_SUB(structname); \ +#define VTY_DECLVAR_CONTEXT_SUB(structname, ptr) \ + struct structname *ptr = VTY_GET_CONTEXT_SUB(structname); \ VTY_CHECK_CONTEXT(ptr); -struct vty_arg -{ - const char *name; - const char *value; - const char **argv; - int argc; +struct vty_arg { + const char *name; + const char *value; + const char **argv; + int argc; }; /* Integrated configuration file. */ @@ -184,10 +182,11 @@ struct vty_arg #define CPP_WARN_STR(X) #X #define CPP_WARN(text) _Pragma(CPP_WARN_STR(message __FILE__ ": " text)) -#elif (defined(__GNUC__) && \ - (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) || \ - (defined(__clang__) && \ - (__clang_major__ >= 4 || (__clang_major__ == 3 && __clang_minor__ >= 5))) +#elif (defined(__GNUC__) \ + && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) \ + || (defined(__clang__) \ + && (__clang_major__ >= 4 \ + || (__clang_major__ == 3 && __clang_minor__ >= 5))) #define CPP_WARN_STR(X) #X #define CPP_WARN(text) _Pragma(CPP_WARN_STR(GCC warning text)) @@ -195,27 +194,39 @@ struct vty_arg #define CPP_WARN(text) #endif -#define VNL "\n" \ - CPP_WARN("VNL has been replaced with \\n.") -#define VTYNL "\n" \ - CPP_WARN("VTYNL has been replaced with \\n.") -#define VTY_NEWLINE "\n" \ - CPP_WARN("VTY_NEWLINE has been replaced with \\n.") -#define VTY_GET_INTEGER(desc,v,str) {(v)=strtoul ((str), NULL, 10);} \ +#define VNL "\n" CPP_WARN("VNL has been replaced with \\n.") +#define VTYNL "\n" CPP_WARN("VTYNL has been replaced with \\n.") +#define VTY_NEWLINE "\n" CPP_WARN("VTY_NEWLINE has been replaced with \\n.") +#define VTY_GET_INTEGER(desc, v, str) \ + { \ + (v) = strtoul((str), NULL, 10); \ + } \ CPP_WARN("VTY_GET_INTEGER is no longer useful, use strtoul() or DEFPY.") -#define VTY_GET_INTEGER_RANGE(desc,v,str,min,max) {(v)=strtoul ((str), NULL, 10);} \ - CPP_WARN("VTY_GET_INTEGER_RANGE is no longer useful, use strtoul() or DEFPY.") -#define VTY_GET_ULONG(desc,v,str) {(v)=strtoul ((str), NULL, 10);} \ +#define VTY_GET_INTEGER_RANGE(desc, v, str, min, max) \ + { \ + (v) = strtoul((str), NULL, 10); \ + } \ + CPP_WARN( \ + "VTY_GET_INTEGER_RANGE is no longer useful, use strtoul() or DEFPY.") +#define VTY_GET_ULONG(desc, v, str) \ + { \ + (v) = strtoul((str), NULL, 10); \ + } \ CPP_WARN("VTY_GET_ULONG is no longer useful, use strtoul() or DEFPY.") -#define VTY_GET_ULL(desc,v,str) {(v)=strtoull ((str), NULL, 10);} \ +#define VTY_GET_ULL(desc, v, str) \ + { \ + (v) = strtoull((str), NULL, 10); \ + } \ CPP_WARN("VTY_GET_ULL is no longer useful, use strtoull() or DEFPY.") -#define VTY_GET_IPV4_ADDRESS(desc,v,str) inet_aton ((str), &(v)) \ - CPP_WARN("VTY_GET_IPV4_ADDRESS is no longer useful, use inet_aton() or DEFPY.") -#define VTY_GET_IPV4_PREFIX(desc,v,str) str2prefix_ipv4 ((str), &(v)) \ - CPP_WARN("VTY_GET_IPV4_PREFIX is no longer useful, use str2prefix_ipv4() or DEFPY.") -#define vty_outln(vty, str, ...) \ - vty_out(vty, str "\n", ## __VA_ARGS__) \ - CPP_WARN("vty_outln is no longer useful, use vty_out(...\\n...)") +#define VTY_GET_IPV4_ADDRESS(desc, v, str) \ + inet_aton((str), &(v)) CPP_WARN( \ + "VTY_GET_IPV4_ADDRESS is no longer useful, use inet_aton() or DEFPY.") +#define VTY_GET_IPV4_PREFIX(desc, v, str) \ + str2prefix_ipv4((str), &(v)) CPP_WARN( \ + "VTY_GET_IPV4_PREFIX is no longer useful, use str2prefix_ipv4() or DEFPY.") +#define vty_outln(vty, str, ...) \ + vty_out(vty, str "\n", ##__VA_ARGS__) CPP_WARN( \ + "vty_outln is no longer useful, use vty_out(...\\n...)") /* Default time out value */ #define VTY_TIMEOUT_DEFAULT 600 @@ -236,29 +247,29 @@ struct vty_arg extern char integrate_default[]; /* Prototypes. */ -extern void vty_init (struct thread_master *); -extern void vty_init_vtysh (void); -extern void vty_terminate (void); -extern void vty_reset (void); -extern struct vty *vty_new (void); -extern struct vty *vty_stdio (void (*atclose)(void)); -extern int vty_out (struct vty *, const char *, ...) PRINTF_ATTRIBUTE(2, 3); -extern void vty_read_config (const char *, char *); -extern void vty_time_print (struct vty *, int); -extern void vty_serv_sock (const char *, unsigned short, const char *); -extern void vty_close (struct vty *); -extern char *vty_get_cwd (void); -extern void vty_log (const char *level, const char *proto, - const char *fmt, struct timestamp_control *, va_list); -extern int vty_config_lock (struct vty *); -extern int vty_config_unlock (struct vty *); -extern void vty_config_lockless (void); -extern int vty_shell (struct vty *); -extern int vty_shell_serv (struct vty *); -extern void vty_hello (struct vty *); +extern void vty_init(struct thread_master *); +extern void vty_init_vtysh(void); +extern void vty_terminate(void); +extern void vty_reset(void); +extern struct vty *vty_new(void); +extern struct vty *vty_stdio(void (*atclose)(void)); +extern int vty_out(struct vty *, const char *, ...) PRINTF_ATTRIBUTE(2, 3); +extern void vty_read_config(const char *, char *); +extern void vty_time_print(struct vty *, int); +extern void vty_serv_sock(const char *, unsigned short, const char *); +extern void vty_close(struct vty *); +extern char *vty_get_cwd(void); +extern void vty_log(const char *level, const char *proto, const char *fmt, + struct timestamp_control *, va_list); +extern int vty_config_lock(struct vty *); +extern int vty_config_unlock(struct vty *); +extern void vty_config_lockless(void); +extern int vty_shell(struct vty *); +extern int vty_shell_serv(struct vty *); +extern void vty_hello(struct vty *); /* Send a fixed-size message to all vty terminal monitors; this should be an async-signal-safe function. */ -extern void vty_log_fixed (char *buf, size_t len); +extern void vty_log_fixed(char *buf, size_t len); #endif /* _ZEBRA_VTY_H */ diff --git a/lib/wheel.c b/lib/wheel.c index f273a2926..9f1f189b7 100644 --- a/lib/wheel.c +++ b/lib/wheel.c @@ -24,137 +24,128 @@ #include "wheel.h" #include "log.h" -DEFINE_MTYPE_STATIC(LIB, TIMER_WHEEL, "Timer Wheel") +DEFINE_MTYPE_STATIC(LIB, TIMER_WHEEL, "Timer Wheel") DEFINE_MTYPE_STATIC(LIB, TIMER_WHEEL_LIST, "Timer Wheel Slot List") static int debug_timer_wheel = 0; -static int -wheel_timer_thread (struct thread *t) +static int wheel_timer_thread(struct thread *t) { - struct listnode *node, *nextnode; - unsigned long long curr_slot; - unsigned int slots_to_skip = 1; - struct timer_wheel *wheel; - void *data; + struct listnode *node, *nextnode; + unsigned long long curr_slot; + unsigned int slots_to_skip = 1; + struct timer_wheel *wheel; + void *data; - wheel = THREAD_ARG(t); - THREAD_OFF(wheel->timer); + wheel = THREAD_ARG(t); + THREAD_OFF(wheel->timer); - wheel->curr_slot += wheel->slots_to_skip; + wheel->curr_slot += wheel->slots_to_skip; - curr_slot = wheel->curr_slot % wheel->slots; + curr_slot = wheel->curr_slot % wheel->slots; - if (debug_timer_wheel) - zlog_debug ("%s: Wheel Slot: %lld(%lld) count: %d", - __PRETTY_FUNCTION__, - wheel->curr_slot, - curr_slot, listcount(wheel->wheel_slot_lists[curr_slot])); + if (debug_timer_wheel) + zlog_debug("%s: Wheel Slot: %lld(%lld) count: %d", + __PRETTY_FUNCTION__, wheel->curr_slot, curr_slot, + listcount(wheel->wheel_slot_lists[curr_slot])); - for (ALL_LIST_ELEMENTS (wheel->wheel_slot_lists[curr_slot], node, nextnode, data)) - (*wheel->slot_run)(data); + for (ALL_LIST_ELEMENTS(wheel->wheel_slot_lists[curr_slot], node, + nextnode, data)) + (*wheel->slot_run)(data); - while (list_isempty(wheel->wheel_slot_lists[(curr_slot + slots_to_skip) % wheel->slots]) && - (curr_slot + slots_to_skip ) % wheel->slots != curr_slot) - slots_to_skip++; + while (list_isempty(wheel->wheel_slot_lists[(curr_slot + slots_to_skip) + % wheel->slots]) + && (curr_slot + slots_to_skip) % wheel->slots != curr_slot) + slots_to_skip++; - wheel->slots_to_skip = slots_to_skip; - thread_add_timer_msec(wheel->master, wheel_timer_thread, wheel, - wheel->nexttime * slots_to_skip, &wheel->timer); + wheel->slots_to_skip = slots_to_skip; + thread_add_timer_msec(wheel->master, wheel_timer_thread, wheel, + wheel->nexttime * slots_to_skip, &wheel->timer); - return 0; + return 0; } -struct timer_wheel * -wheel_init (struct thread_master *master, int period, size_t slots, - unsigned int (*slot_key) (void *), - void (*slot_run) (void *)) +struct timer_wheel *wheel_init(struct thread_master *master, int period, + size_t slots, unsigned int (*slot_key)(void *), + void (*slot_run)(void *)) { - struct timer_wheel *wheel; - size_t i; + struct timer_wheel *wheel; + size_t i; - wheel = XCALLOC(MTYPE_TIMER_WHEEL, sizeof (struct timer_wheel)); + wheel = XCALLOC(MTYPE_TIMER_WHEEL, sizeof(struct timer_wheel)); - wheel->slot_key = slot_key; - wheel->slot_run = slot_run; + wheel->slot_key = slot_key; + wheel->slot_run = slot_run; - wheel->period = period; - wheel->slots = slots; - wheel->curr_slot = 0; - wheel->master = master; - wheel->nexttime = period / slots; + wheel->period = period; + wheel->slots = slots; + wheel->curr_slot = 0; + wheel->master = master; + wheel->nexttime = period / slots; - wheel->wheel_slot_lists = XCALLOC(MTYPE_TIMER_WHEEL_LIST, - slots * sizeof (struct listnode *)); - for (i = 0; i < slots; i++) - wheel->wheel_slot_lists[i] = list_new (); + wheel->wheel_slot_lists = XCALLOC(MTYPE_TIMER_WHEEL_LIST, + slots * sizeof(struct listnode *)); + for (i = 0; i < slots; i++) + wheel->wheel_slot_lists[i] = list_new(); - thread_add_timer_msec(wheel->master, wheel_timer_thread, wheel, - wheel->nexttime, &wheel->timer); + thread_add_timer_msec(wheel->master, wheel_timer_thread, wheel, + wheel->nexttime, &wheel->timer); - return wheel; + return wheel; } -void -wheel_delete (struct timer_wheel *wheel) +void wheel_delete(struct timer_wheel *wheel) { - int i; + int i; - for (i = 0; i < wheel->slots; i++) - { - list_delete(wheel->wheel_slot_lists[i]); - } + for (i = 0; i < wheel->slots; i++) { + list_delete(wheel->wheel_slot_lists[i]); + } - THREAD_OFF(wheel->timer); - XFREE(MTYPE_TIMER_WHEEL_LIST, wheel->wheel_slot_lists); - XFREE(MTYPE_TIMER_WHEEL, wheel); + THREAD_OFF(wheel->timer); + XFREE(MTYPE_TIMER_WHEEL_LIST, wheel->wheel_slot_lists); + XFREE(MTYPE_TIMER_WHEEL, wheel); } -int -wheel_stop (struct timer_wheel *wheel) +int wheel_stop(struct timer_wheel *wheel) { - THREAD_OFF(wheel->timer); - return 0; + THREAD_OFF(wheel->timer); + return 0; } -int -wheel_start (struct timer_wheel *wheel) +int wheel_start(struct timer_wheel *wheel) { - if (!wheel->timer) - thread_add_timer_msec(wheel->master, wheel_timer_thread, wheel, - wheel->nexttime, &wheel->timer); + if (!wheel->timer) + thread_add_timer_msec(wheel->master, wheel_timer_thread, wheel, + wheel->nexttime, &wheel->timer); - return 0; + return 0; } -int -wheel_add_item (struct timer_wheel *wheel, void *item) +int wheel_add_item(struct timer_wheel *wheel, void *item) { - long long slot; + long long slot; - slot = (*wheel->slot_key)(item); + slot = (*wheel->slot_key)(item); - if (debug_timer_wheel) - zlog_debug ("%s: Inserting %p: %lld %lld", - __PRETTY_FUNCTION__, item, - slot, slot % wheel->slots); - listnode_add (wheel->wheel_slot_lists[slot % wheel->slots], item); + if (debug_timer_wheel) + zlog_debug("%s: Inserting %p: %lld %lld", __PRETTY_FUNCTION__, + item, slot, slot % wheel->slots); + listnode_add(wheel->wheel_slot_lists[slot % wheel->slots], item); - return 0; + return 0; } -int -wheel_remove_item (struct timer_wheel *wheel, void *item) +int wheel_remove_item(struct timer_wheel *wheel, void *item) { - long long slot; + long long slot; - slot = (*wheel->slot_key)(item); + slot = (*wheel->slot_key)(item); - if (debug_timer_wheel) - zlog_debug ("%s: Removing %p: %lld %lld", - __PRETTY_FUNCTION__, item, - slot, slot % wheel->slots); - listnode_delete (wheel->wheel_slot_lists[slot % wheel->slots], item); + if (debug_timer_wheel) + zlog_debug("%s: Removing %p: %lld %lld", __PRETTY_FUNCTION__, + item, slot, slot % wheel->slots); + listnode_delete(wheel->wheel_slot_lists[slot % wheel->slots], item); - return 0; + return 0; } diff --git a/lib/wheel.h b/lib/wheel.h index 07be79bf2..1f9f95ed3 100644 --- a/lib/wheel.h +++ b/lib/wheel.h @@ -20,23 +20,22 @@ #ifndef __WHEEL_H__ #define __WHEEL_H__ -struct timer_wheel -{ - struct thread_master *master; - int slots; - long long curr_slot; - unsigned int period; - unsigned int nexttime; - unsigned int slots_to_skip; +struct timer_wheel { + struct thread_master *master; + int slots; + long long curr_slot; + unsigned int period; + unsigned int nexttime; + unsigned int slots_to_skip; - struct list **wheel_slot_lists; - struct thread *timer; - /* - * Key to determine what slot the item belongs in - */ - unsigned int (*slot_key) (void *); + struct list **wheel_slot_lists; + struct thread *timer; + /* + * Key to determine what slot the item belongs in + */ + unsigned int (*slot_key)(void *); - void (*slot_run) (void *); + void (*slot_run)(void *); }; /* @@ -75,24 +74,24 @@ struct timer_wheel * and cause significant amount of time handling thread events instead * of running your code. */ -struct timer_wheel *wheel_init (struct thread_master *master, int period, size_t slots, - unsigned int (*slot_key) (void *), - void (*slot_run) (void *)); +struct timer_wheel *wheel_init(struct thread_master *master, int period, + size_t slots, unsigned int (*slot_key)(void *), + void (*slot_run)(void *)); /* * Delete the specified timer wheel created */ -void wheel_delete (struct timer_wheel *); +void wheel_delete(struct timer_wheel *); /* * Pause the Wheel from running */ -int wheel_stop (struct timer_wheel *wheel); +int wheel_stop(struct timer_wheel *wheel); /* * Start the wheel running again */ -int wheel_start (struct timer_wheel *wheel); +int wheel_start(struct timer_wheel *wheel); /* * wheel - The Timer wheel being modified @@ -102,7 +101,7 @@ int wheel_start (struct timer_wheel *wheel); * Add item to a slot setup by the slot_key, * possibly change next time pop. */ -int wheel_add_item (struct timer_wheel *wheel, void *item); +int wheel_add_item(struct timer_wheel *wheel, void *item); /* * wheel - The Timer wheel being modified. @@ -112,6 +111,6 @@ int wheel_add_item (struct timer_wheel *wheel, void *item); * Remove a item to a slot setup by the slot_key, * possibly change next time pop. */ -int wheel_remove_item (struct timer_wheel *wheel, void *item); +int wheel_remove_item(struct timer_wheel *wheel, void *item); #endif diff --git a/lib/workqueue.c b/lib/workqueue.c index 60119f1f4..612421c80 100644 --- a/lib/workqueue.c +++ b/lib/workqueue.c @@ -1,4 +1,4 @@ -/* +/* * Quagga Work Queue Support. * * Copyright (C) 2005 Sun Microsystems, Inc. @@ -28,7 +28,7 @@ #include "command.h" #include "log.h" -DEFINE_MTYPE(LIB, WORK_QUEUE, "Work queue") +DEFINE_MTYPE(LIB, WORK_QUEUE, "Work queue") DEFINE_MTYPE_STATIC(LIB, WORK_QUEUE_ITEM, "Work queue item") DEFINE_MTYPE_STATIC(LIB, WORK_QUEUE_NAME, "Work queue name string") @@ -41,145 +41,131 @@ static struct list *work_queues = &_work_queues; #define WORK_QUEUE_MIN_GRANULARITY 1 -static struct work_queue_item * -work_queue_item_new (struct work_queue *wq) +static struct work_queue_item *work_queue_item_new(struct work_queue *wq) { - struct work_queue_item *item; - assert (wq); + struct work_queue_item *item; + assert(wq); - item = XCALLOC (MTYPE_WORK_QUEUE_ITEM, - sizeof (struct work_queue_item)); - - return item; + item = XCALLOC(MTYPE_WORK_QUEUE_ITEM, sizeof(struct work_queue_item)); + + return item; } -static void -work_queue_item_free (struct work_queue_item *item) +static void work_queue_item_free(struct work_queue_item *item) { - XFREE (MTYPE_WORK_QUEUE_ITEM, item); - return; + XFREE(MTYPE_WORK_QUEUE_ITEM, item); + return; } /* create new work queue */ -struct work_queue * -work_queue_new (struct thread_master *m, const char *queue_name) +struct work_queue *work_queue_new(struct thread_master *m, + const char *queue_name) { - struct work_queue *new; - - new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct work_queue)); - - if (new == NULL) - return new; - - new->name = XSTRDUP (MTYPE_WORK_QUEUE_NAME, queue_name); - new->master = m; - SET_FLAG (new->flags, WQ_UNPLUGGED); - - if ( (new->items = list_new ()) == NULL) - { - XFREE (MTYPE_WORK_QUEUE_NAME, new->name); - XFREE (MTYPE_WORK_QUEUE, new); - - return NULL; - } - - new->items->del = (void (*)(void *)) work_queue_item_free; - - listnode_add (work_queues, new); - - new->cycles.granularity = WORK_QUEUE_MIN_GRANULARITY; - - /* Default values, can be overriden by caller */ - new->spec.hold = WORK_QUEUE_DEFAULT_HOLD; - new->spec.yield = THREAD_YIELD_TIME_SLOT; - - return new; + struct work_queue *new; + + new = XCALLOC(MTYPE_WORK_QUEUE, sizeof(struct work_queue)); + + if (new == NULL) + return new; + + new->name = XSTRDUP(MTYPE_WORK_QUEUE_NAME, queue_name); + new->master = m; + SET_FLAG(new->flags, WQ_UNPLUGGED); + + if ((new->items = list_new()) == NULL) { + XFREE(MTYPE_WORK_QUEUE_NAME, new->name); + XFREE(MTYPE_WORK_QUEUE, new); + + return NULL; + } + + new->items->del = (void (*)(void *))work_queue_item_free; + + listnode_add(work_queues, new); + + new->cycles.granularity = WORK_QUEUE_MIN_GRANULARITY; + + /* Default values, can be overriden by caller */ + new->spec.hold = WORK_QUEUE_DEFAULT_HOLD; + new->spec.yield = THREAD_YIELD_TIME_SLOT; + + return new; } -void -work_queue_free (struct work_queue *wq) +void work_queue_free(struct work_queue *wq) { - if (wq->thread != NULL) - thread_cancel(wq->thread); - - /* list_delete frees items via callback */ - list_delete (wq->items); - listnode_delete (work_queues, wq); - - XFREE (MTYPE_WORK_QUEUE_NAME, wq->name); - XFREE (MTYPE_WORK_QUEUE, wq); - return; + if (wq->thread != NULL) + thread_cancel(wq->thread); + + /* list_delete frees items via callback */ + list_delete(wq->items); + listnode_delete(work_queues, wq); + + XFREE(MTYPE_WORK_QUEUE_NAME, wq->name); + XFREE(MTYPE_WORK_QUEUE, wq); + return; } -bool -work_queue_is_scheduled (struct work_queue *wq) +bool work_queue_is_scheduled(struct work_queue *wq) { - return (wq->thread != NULL); + return (wq->thread != NULL); } -static int -work_queue_schedule (struct work_queue *wq, unsigned int delay) +static int work_queue_schedule(struct work_queue *wq, unsigned int delay) { - /* if appropriate, schedule work queue thread */ - if ( CHECK_FLAG (wq->flags, WQ_UNPLUGGED) - && (wq->thread == NULL) - && (listcount (wq->items) > 0) ) - { - wq->thread = NULL; - thread_add_timer_msec (wq->master, work_queue_run, wq, delay, - &wq->thread); - /* set thread yield time, if needed */ - if (wq->thread && wq->spec.yield != THREAD_YIELD_TIME_SLOT) - thread_set_yield_time (wq->thread, wq->spec.yield); - return 1; - } - else - return 0; + /* if appropriate, schedule work queue thread */ + if (CHECK_FLAG(wq->flags, WQ_UNPLUGGED) && (wq->thread == NULL) + && (listcount(wq->items) > 0)) { + wq->thread = NULL; + thread_add_timer_msec(wq->master, work_queue_run, wq, delay, + &wq->thread); + /* set thread yield time, if needed */ + if (wq->thread && wq->spec.yield != THREAD_YIELD_TIME_SLOT) + thread_set_yield_time(wq->thread, wq->spec.yield); + return 1; + } else + return 0; } - -void -work_queue_add (struct work_queue *wq, void *data) + +void work_queue_add(struct work_queue *wq, void *data) { - struct work_queue_item *item; - - assert (wq); - - if (!(item = work_queue_item_new (wq))) - { - zlog_err ("%s: unable to get new queue item", __func__); - return; - } - - item->data = data; - listnode_add (wq->items, item); - - work_queue_schedule (wq, wq->spec.hold); - - return; + struct work_queue_item *item; + + assert(wq); + + if (!(item = work_queue_item_new(wq))) { + zlog_err("%s: unable to get new queue item", __func__); + return; + } + + item->data = data; + listnode_add(wq->items, item); + + work_queue_schedule(wq, wq->spec.hold); + + return; } -static void -work_queue_item_remove (struct work_queue *wq, struct listnode *ln) +static void work_queue_item_remove(struct work_queue *wq, struct listnode *ln) { - struct work_queue_item *item = listgetdata (ln); + struct work_queue_item *item = listgetdata(ln); - assert (item && item->data); + assert(item && item->data); - /* call private data deletion callback if needed */ - if (wq->spec.del_item_data) - wq->spec.del_item_data (wq, item->data); + /* call private data deletion callback if needed */ + if (wq->spec.del_item_data) + wq->spec.del_item_data(wq, item->data); - list_delete_node (wq->items, ln); - work_queue_item_free (item); - - return; + list_delete_node(wq->items, ln); + work_queue_item_free(item); + + return; } -static void -work_queue_item_requeue (struct work_queue *wq, struct listnode *ln) +static void work_queue_item_requeue(struct work_queue *wq, struct listnode *ln) { - LISTNODE_DETACH (wq->items, ln); - LISTNODE_ATTACH (wq->items, ln); /* attach to end of list */ + LISTNODE_DETACH(wq->items, ln); + LISTNODE_ATTACH(wq->items, ln); /* attach to end of list */ } DEFUN (show_work_queues, @@ -188,227 +174,212 @@ DEFUN (show_work_queues, SHOW_STR "Work Queue information\n") { - struct listnode *node; - struct work_queue *wq; - - vty_out (vty, - "%c %8s %5s %8s %8s %21s\n", - ' ', "List","(ms) ","Q. Runs","Yields","Cycle Counts "); - vty_out (vty, - "%c %8s %5s %8s %8s %7s %6s %8s %6s %s\n", - 'P', - "Items", - "Hold", - "Total","Total", - "Best","Gran.","Total","Avg.", - "Name"); - - for (ALL_LIST_ELEMENTS_RO (work_queues, node, wq)) - { - vty_out (vty,"%c %8d %5d %8ld %8ld %7d %6d %8ld %6u %s\n", - (CHECK_FLAG (wq->flags, WQ_UNPLUGGED) ? ' ' : 'P'), - listcount (wq->items), - wq->spec.hold, - wq->runs, wq->yields, - wq->cycles.best, wq->cycles.granularity, wq->cycles.total, - (wq->runs) ? - (unsigned int) (wq->cycles.total / wq->runs) : 0, - wq->name); - } - - return CMD_SUCCESS; + struct listnode *node; + struct work_queue *wq; + + vty_out(vty, "%c %8s %5s %8s %8s %21s\n", ' ', "List", "(ms) ", + "Q. Runs", "Yields", "Cycle Counts "); + vty_out(vty, "%c %8s %5s %8s %8s %7s %6s %8s %6s %s\n", 'P', "Items", + "Hold", "Total", "Total", "Best", "Gran.", "Total", "Avg.", + "Name"); + + for (ALL_LIST_ELEMENTS_RO(work_queues, node, wq)) { + vty_out(vty, "%c %8d %5d %8ld %8ld %7d %6d %8ld %6u %s\n", + (CHECK_FLAG(wq->flags, WQ_UNPLUGGED) ? ' ' : 'P'), + listcount(wq->items), wq->spec.hold, wq->runs, + wq->yields, wq->cycles.best, wq->cycles.granularity, + wq->cycles.total, + (wq->runs) ? (unsigned int)(wq->cycles.total / wq->runs) + : 0, + wq->name); + } + + return CMD_SUCCESS; } -void -workqueue_cmd_init (void) +void workqueue_cmd_init(void) { - install_element (VIEW_NODE, &show_work_queues_cmd); + install_element(VIEW_NODE, &show_work_queues_cmd); } /* 'plug' a queue: Stop it from being scheduled, * ie: prevent the queue from draining. */ -void -work_queue_plug (struct work_queue *wq) +void work_queue_plug(struct work_queue *wq) { - if (wq->thread) - thread_cancel (wq->thread); - - wq->thread = NULL; - - UNSET_FLAG (wq->flags, WQ_UNPLUGGED); + if (wq->thread) + thread_cancel(wq->thread); + + wq->thread = NULL; + + UNSET_FLAG(wq->flags, WQ_UNPLUGGED); } /* unplug queue, schedule it again, if appropriate * Ie: Allow the queue to be drained again */ -void -work_queue_unplug (struct work_queue *wq) +void work_queue_unplug(struct work_queue *wq) { - SET_FLAG (wq->flags, WQ_UNPLUGGED); + SET_FLAG(wq->flags, WQ_UNPLUGGED); - /* if thread isnt already waiting, add one */ - work_queue_schedule (wq, wq->spec.hold); + /* if thread isnt already waiting, add one */ + work_queue_schedule(wq, wq->spec.hold); } /* timer thread to process a work queue * will reschedule itself if required, - * otherwise work_queue_item_add + * otherwise work_queue_item_add */ -int -work_queue_run (struct thread *thread) +int work_queue_run(struct thread *thread) { - struct work_queue *wq; - struct work_queue_item *item; - wq_item_status ret; - unsigned int cycles = 0; - struct listnode *node, *nnode; - char yielded = 0; - - wq = THREAD_ARG (thread); - wq->thread = NULL; - - assert (wq && wq->items); - - /* calculate cycle granularity: - * list iteration == 1 run - * listnode processing == 1 cycle - * granularity == # cycles between checks whether we should yield. - * - * granularity should be > 0, and can increase slowly after each run to - * provide some hysteris, but not past cycles.best or 2*cycles. - * - * Best: starts low, can only increase - * - * Granularity: starts at WORK_QUEUE_MIN_GRANULARITY, can be decreased - * if we run to end of time slot, can increase otherwise - * by a small factor. - * - * We could use just the average and save some work, however we want to be - * able to adjust quickly to CPU pressure. Average wont shift much if - * daemon has been running a long time. - */ - if (wq->cycles.granularity == 0) - wq->cycles.granularity = WORK_QUEUE_MIN_GRANULARITY; - - for (ALL_LIST_ELEMENTS (wq->items, node, nnode, item)) - { - assert (item && item->data); - - /* dont run items which are past their allowed retries */ - if (item->ran > wq->spec.max_retries) - { - /* run error handler, if any */ - if (wq->spec.errorfunc) - wq->spec.errorfunc (wq, item->data); - work_queue_item_remove (wq, node); - continue; - } - - /* run and take care of items that want to be retried immediately */ - do - { - ret = wq->spec.workfunc (wq, item->data); - item->ran++; - } - while ((ret == WQ_RETRY_NOW) - && (item->ran < wq->spec.max_retries)); - - switch (ret) - { - case WQ_QUEUE_BLOCKED: - { - /* decrement item->ran again, cause this isn't an item - * specific error, and fall through to WQ_RETRY_LATER - */ - item->ran--; - } - case WQ_RETRY_LATER: - { - goto stats; - } - case WQ_REQUEUE: - { - item->ran--; - work_queue_item_requeue (wq, node); - /* If a single node is being used with a meta-queue (e.g., zebra), - * update the next node as we don't want to exit the thread and - * reschedule it after every node. By definition, WQ_REQUEUE is - * meant to continue the processing; the yield logic will kick in - * to terminate the thread when time has exceeded. - */ - if (nnode == NULL) - nnode = node; - break; + struct work_queue *wq; + struct work_queue_item *item; + wq_item_status ret; + unsigned int cycles = 0; + struct listnode *node, *nnode; + char yielded = 0; + + wq = THREAD_ARG(thread); + wq->thread = NULL; + + assert(wq && wq->items); + + /* calculate cycle granularity: + * list iteration == 1 run + * listnode processing == 1 cycle + * granularity == # cycles between checks whether we should yield. + * + * granularity should be > 0, and can increase slowly after each run to + * provide some hysteris, but not past cycles.best or 2*cycles. + * + * Best: starts low, can only increase + * + * Granularity: starts at WORK_QUEUE_MIN_GRANULARITY, can be decreased + * if we run to end of time slot, can increase otherwise + * by a small factor. + * + * We could use just the average and save some work, however we want to + * be + * able to adjust quickly to CPU pressure. Average wont shift much if + * daemon has been running a long time. + */ + if (wq->cycles.granularity == 0) + wq->cycles.granularity = WORK_QUEUE_MIN_GRANULARITY; + + for (ALL_LIST_ELEMENTS(wq->items, node, nnode, item)) { + assert(item && item->data); + + /* dont run items which are past their allowed retries */ + if (item->ran > wq->spec.max_retries) { + /* run error handler, if any */ + if (wq->spec.errorfunc) + wq->spec.errorfunc(wq, item->data); + work_queue_item_remove(wq, node); + continue; + } + + /* run and take care of items that want to be retried + * immediately */ + do { + ret = wq->spec.workfunc(wq, item->data); + item->ran++; + } while ((ret == WQ_RETRY_NOW) + && (item->ran < wq->spec.max_retries)); + + switch (ret) { + case WQ_QUEUE_BLOCKED: { + /* decrement item->ran again, cause this isn't an item + * specific error, and fall through to WQ_RETRY_LATER + */ + item->ran--; + } + case WQ_RETRY_LATER: { + goto stats; + } + case WQ_REQUEUE: { + item->ran--; + work_queue_item_requeue(wq, node); + /* If a single node is being used with a meta-queue + * (e.g., zebra), + * update the next node as we don't want to exit the + * thread and + * reschedule it after every node. By definition, + * WQ_REQUEUE is + * meant to continue the processing; the yield logic + * will kick in + * to terminate the thread when time has exceeded. + */ + if (nnode == NULL) + nnode = node; + break; + } + case WQ_RETRY_NOW: + /* a RETRY_NOW that gets here has exceeded max_tries, same as + * ERROR */ + case WQ_ERROR: { + if (wq->spec.errorfunc) + wq->spec.errorfunc(wq, item); + } + /* fallthru */ + case WQ_SUCCESS: + default: { + work_queue_item_remove(wq, node); + break; + } + } + + /* completed cycle */ + cycles++; + + /* test if we should yield */ + if (!(cycles % wq->cycles.granularity) + && thread_should_yield(thread)) { + yielded = 1; + goto stats; + } } - case WQ_RETRY_NOW: - /* a RETRY_NOW that gets here has exceeded max_tries, same as ERROR */ - case WQ_ERROR: - { - if (wq->spec.errorfunc) - wq->spec.errorfunc (wq, item); - } - /* fallthru */ - case WQ_SUCCESS: - default: - { - work_queue_item_remove (wq, node); - break; - } - } - - /* completed cycle */ - cycles++; - - /* test if we should yield */ - if ( !(cycles % wq->cycles.granularity) - && thread_should_yield (thread)) - { - yielded = 1; - goto stats; - } - } stats: #define WQ_HYSTERESIS_FACTOR 4 - /* we yielded, check whether granularity should be reduced */ - if (yielded && (cycles < wq->cycles.granularity)) - { - wq->cycles.granularity = ((cycles > 0) ? cycles - : WORK_QUEUE_MIN_GRANULARITY); - } - /* otherwise, should granularity increase? */ - else if (cycles >= (wq->cycles.granularity)) - { - if (cycles > wq->cycles.best) - wq->cycles.best = cycles; - - /* along with yielded check, provides hysteresis for granularity */ - if (cycles > (wq->cycles.granularity * WQ_HYSTERESIS_FACTOR - * WQ_HYSTERESIS_FACTOR)) - wq->cycles.granularity *= WQ_HYSTERESIS_FACTOR; /* quick ramp-up */ - else if (cycles > (wq->cycles.granularity * WQ_HYSTERESIS_FACTOR)) - wq->cycles.granularity += WQ_HYSTERESIS_FACTOR; - } + /* we yielded, check whether granularity should be reduced */ + if (yielded && (cycles < wq->cycles.granularity)) { + wq->cycles.granularity = + ((cycles > 0) ? cycles : WORK_QUEUE_MIN_GRANULARITY); + } + /* otherwise, should granularity increase? */ + else if (cycles >= (wq->cycles.granularity)) { + if (cycles > wq->cycles.best) + wq->cycles.best = cycles; + + /* along with yielded check, provides hysteresis for granularity + */ + if (cycles > (wq->cycles.granularity * WQ_HYSTERESIS_FACTOR + * WQ_HYSTERESIS_FACTOR)) + wq->cycles.granularity *= + WQ_HYSTERESIS_FACTOR; /* quick ramp-up */ + else if (cycles + > (wq->cycles.granularity * WQ_HYSTERESIS_FACTOR)) + wq->cycles.granularity += WQ_HYSTERESIS_FACTOR; + } #undef WQ_HYSTERIS_FACTOR - - wq->runs++; - wq->cycles.total += cycles; - if (yielded) - wq->yields++; + + wq->runs++; + wq->cycles.total += cycles; + if (yielded) + wq->yields++; #if 0 printf ("%s: cycles %d, new: best %d, worst %d\n", __func__, cycles, wq->cycles.best, wq->cycles.granularity); #endif - - /* Is the queue done yet? If it is, call the completion callback. */ - if (listcount (wq->items) > 0) - work_queue_schedule (wq, 0); - else if (wq->spec.completion_func) - wq->spec.completion_func (wq); - - return 0; + + /* Is the queue done yet? If it is, call the completion callback. */ + if (listcount(wq->items) > 0) + work_queue_schedule(wq, 0); + else if (wq->spec.completion_func) + wq->spec.completion_func(wq); + + return 0; } diff --git a/lib/workqueue.h b/lib/workqueue.h index 45f02afc6..ff7f57690 100644 --- a/lib/workqueue.h +++ b/lib/workqueue.h @@ -1,4 +1,4 @@ -/* +/* * Quagga Work Queues. * * Copyright (C) 2005 Sun Microsystems, Inc. @@ -30,105 +30,104 @@ DECLARE_MTYPE(WORK_QUEUE) #define WORK_QUEUE_DEFAULT_HOLD 50 /* action value, for use by item processor and item error handlers */ -typedef enum -{ - WQ_SUCCESS = 0, - WQ_ERROR, /* Error, run error handler if provided */ - WQ_RETRY_NOW, /* retry immediately */ - WQ_RETRY_LATER, /* retry later, cease processing work queue */ - WQ_REQUEUE, /* requeue item, continue processing work queue */ - WQ_QUEUE_BLOCKED, /* Queue cant be processed at this time. - * Similar to WQ_RETRY_LATER, but doesn't penalise - * the particular item.. */ +typedef enum { + WQ_SUCCESS = 0, + WQ_ERROR, /* Error, run error handler if provided */ + WQ_RETRY_NOW, /* retry immediately */ + WQ_RETRY_LATER, /* retry later, cease processing work queue */ + WQ_REQUEUE, /* requeue item, continue processing work queue */ + WQ_QUEUE_BLOCKED, /* Queue cant be processed at this time. + * Similar to WQ_RETRY_LATER, but doesn't penalise + * the particular item.. */ } wq_item_status; /* A single work queue item, unsurprisingly */ -struct work_queue_item -{ - void *data; /* opaque data */ - unsigned short ran; /* # of times item has been run */ +struct work_queue_item { + void *data; /* opaque data */ + unsigned short ran; /* # of times item has been run */ }; #define WQ_UNPLUGGED (1 << 0) /* available for draining */ -struct work_queue -{ - /* Everything but the specification struct is private - * the following may be read - */ - struct thread_master *master; /* thread master */ - struct thread *thread; /* thread, if one is active */ - char *name; /* work queue name */ - - /* Specification for this work queue. - * Public, must be set before use by caller. May be modified at will. - */ - struct { - /* optional opaque user data, global to the queue. */ - void *data; - - /* work function to process items with: - * First argument is the workqueue queue. - * Second argument is the item data - */ - wq_item_status (*workfunc) (struct work_queue *, void *); - - /* error handling function, optional */ - void (*errorfunc) (struct work_queue *, struct work_queue_item *); - - /* callback to delete user specific item data */ - void (*del_item_data) (struct work_queue *, void *); - - /* completion callback, called when queue is emptied, optional */ - void (*completion_func) (struct work_queue *); - - /* max number of retries to make for item that errors */ - unsigned int max_retries; - - unsigned int hold; /* hold time for first run, in ms */ - - unsigned long yield; /* yield time in us for associated thread */ - } spec; - - /* remaining fields should be opaque to users */ - struct list *items; /* queue item list */ - unsigned long runs; /* runs count */ - unsigned long yields; /* yields count */ - - struct { - unsigned int best; - unsigned int granularity; - unsigned long total; - } cycles; /* cycle counts */ - - /* private state */ - u_int16_t flags; /* user set flag */ +struct work_queue { + /* Everything but the specification struct is private + * the following may be read + */ + struct thread_master *master; /* thread master */ + struct thread *thread; /* thread, if one is active */ + char *name; /* work queue name */ + + /* Specification for this work queue. + * Public, must be set before use by caller. May be modified at will. + */ + struct { + /* optional opaque user data, global to the queue. */ + void *data; + + /* work function to process items with: + * First argument is the workqueue queue. + * Second argument is the item data + */ + wq_item_status (*workfunc)(struct work_queue *, void *); + + /* error handling function, optional */ + void (*errorfunc)(struct work_queue *, + struct work_queue_item *); + + /* callback to delete user specific item data */ + void (*del_item_data)(struct work_queue *, void *); + + /* completion callback, called when queue is emptied, optional + */ + void (*completion_func)(struct work_queue *); + + /* max number of retries to make for item that errors */ + unsigned int max_retries; + + unsigned int hold; /* hold time for first run, in ms */ + + unsigned long + yield; /* yield time in us for associated thread */ + } spec; + + /* remaining fields should be opaque to users */ + struct list *items; /* queue item list */ + unsigned long runs; /* runs count */ + unsigned long yields; /* yields count */ + + struct { + unsigned int best; + unsigned int granularity; + unsigned long total; + } cycles; /* cycle counts */ + + /* private state */ + u_int16_t flags; /* user set flag */ }; /* User API */ -/* create a new work queue, of given name. +/* create a new work queue, of given name. * user must fill in the spec of the returned work queue before adding * anything to it */ -extern struct work_queue *work_queue_new (struct thread_master *, - const char *); +extern struct work_queue *work_queue_new(struct thread_master *, const char *); /* destroy work queue */ -extern void work_queue_free (struct work_queue *); +extern void work_queue_free(struct work_queue *); /* Add the supplied data as an item onto the workqueue */ -extern void work_queue_add (struct work_queue *, void *); +extern void work_queue_add(struct work_queue *, void *); /* plug the queue, ie prevent it from being drained / processed */ -extern void work_queue_plug (struct work_queue *wq); +extern void work_queue_plug(struct work_queue *wq); /* unplug the queue, allow it to be drained again */ -extern void work_queue_unplug (struct work_queue *wq); +extern void work_queue_unplug(struct work_queue *wq); -bool work_queue_is_scheduled (struct work_queue *); +bool work_queue_is_scheduled(struct work_queue *); /* Helpers, exported for thread.c and command.c */ -extern int work_queue_run (struct thread *); +extern int work_queue_run(struct thread *); -extern void workqueue_cmd_init (void); +extern void workqueue_cmd_init(void); #endif /* _QUAGGA_WORK_QUEUE_H */ diff --git a/lib/zassert.h b/lib/zassert.h index 082ad6789..5c06d933e 100644 --- a/lib/zassert.h +++ b/lib/zassert.h @@ -21,9 +21,9 @@ #ifndef _QUAGGA_ASSERT_H #define _QUAGGA_ASSERT_H -extern void _zlog_assert_failed (const char *assertion, const char *file, - unsigned int line, const char *function) - __attribute__ ((noreturn)); +extern void _zlog_assert_failed(const char *assertion, const char *file, + unsigned int line, const char *function) + __attribute__((noreturn)); #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define __ASSERT_FUNCTION __func__ @@ -33,9 +33,10 @@ extern void _zlog_assert_failed (const char *assertion, const char *file, #define __ASSERT_FUNCTION NULL #endif -#define zassert(EX) ((void)((EX) ? 0 : \ - (_zlog_assert_failed(#EX, __FILE__, __LINE__, \ - __ASSERT_FUNCTION), 0))) +#define zassert(EX) \ + ((void)((EX) ? 0 : (_zlog_assert_failed(#EX, __FILE__, __LINE__, \ + __ASSERT_FUNCTION), \ + 0))) #undef assert #define assert(EX) zassert(EX) diff --git a/lib/zclient.c b/lib/zclient.c index efe8f5662..a54d8749a 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -40,10 +40,10 @@ DEFINE_MTYPE_STATIC(LIB, ZCLIENT, "Zclient") DEFINE_MTYPE_STATIC(LIB, REDIST_INST, "Redistribution instance IDs") /* Zebra client events. */ -enum event {ZCLIENT_SCHEDULE, ZCLIENT_READ, ZCLIENT_CONNECT}; +enum event { ZCLIENT_SCHEDULE, ZCLIENT_READ, ZCLIENT_CONNECT }; /* Prototype for event manager. */ -static void zclient_event (enum event, struct zclient *); +static void zclient_event(enum event, struct zclient *); const char *zclient_serv_path = NULL; @@ -51,18 +51,17 @@ const char *zclient_serv_path = NULL; int zclient_debug = 0; /* Allocate zclient structure. */ -struct zclient * -zclient_new (struct thread_master *master) +struct zclient *zclient_new(struct thread_master *master) { - struct zclient *zclient; - zclient = XCALLOC (MTYPE_ZCLIENT, sizeof (struct zclient)); + struct zclient *zclient; + zclient = XCALLOC(MTYPE_ZCLIENT, sizeof(struct zclient)); - zclient->ibuf = stream_new (ZEBRA_MAX_PACKET_SIZ); - zclient->obuf = stream_new (ZEBRA_MAX_PACKET_SIZ); - zclient->wb = buffer_new(0); - zclient->master = master; + zclient->ibuf = stream_new(ZEBRA_MAX_PACKET_SIZ); + zclient->obuf = stream_new(ZEBRA_MAX_PACKET_SIZ); + zclient->wb = buffer_new(0); + zclient->master = master; - return zclient; + return zclient; } /* This function is only called when exiting, because @@ -70,162 +69,154 @@ zclient_new (struct thread_master *master) reference an invalid pointer if the structure was ever freed. Free zclient structure. */ -void -zclient_free (struct zclient *zclient) +void zclient_free(struct zclient *zclient) { - if (zclient->ibuf) - stream_free(zclient->ibuf); - if (zclient->obuf) - stream_free(zclient->obuf); - if (zclient->wb) - buffer_free(zclient->wb); - - XFREE (MTYPE_ZCLIENT, zclient); + if (zclient->ibuf) + stream_free(zclient->ibuf); + if (zclient->obuf) + stream_free(zclient->obuf); + if (zclient->wb) + buffer_free(zclient->wb); + + XFREE(MTYPE_ZCLIENT, zclient); } -u_short * -redist_check_instance (struct redist_proto *red, u_short instance) +u_short *redist_check_instance(struct redist_proto *red, u_short instance) { - struct listnode *node; - u_short *id; + struct listnode *node; + u_short *id; - if (!red->instances) - return NULL; + if (!red->instances) + return NULL; - for (ALL_LIST_ELEMENTS_RO (red->instances, node, id)) - if (*id == instance) - return id; + for (ALL_LIST_ELEMENTS_RO(red->instances, node, id)) + if (*id == instance) + return id; - return NULL; + return NULL; } -void -redist_add_instance (struct redist_proto *red, u_short instance) +void redist_add_instance(struct redist_proto *red, u_short instance) { - u_short *in; + u_short *in; - red->enabled = 1; + red->enabled = 1; - if (!red->instances) - red->instances = list_new(); + if (!red->instances) + red->instances = list_new(); - in = XMALLOC (MTYPE_REDIST_INST, sizeof(u_short)); - *in = instance; - listnode_add (red->instances, in); + in = XMALLOC(MTYPE_REDIST_INST, sizeof(u_short)); + *in = instance; + listnode_add(red->instances, in); } -void -redist_del_instance (struct redist_proto *red, u_short instance) +void redist_del_instance(struct redist_proto *red, u_short instance) { - u_short *id; - - id = redist_check_instance (red, instance); - if (! id) - return; - - listnode_delete(red->instances, id); - XFREE (MTYPE_REDIST_INST, id); - if (!red->instances->count) - { - red->enabled = 0; - list_free(red->instances); - red->instances = NULL; - } + u_short *id; + + id = redist_check_instance(red, instance); + if (!id) + return; + + listnode_delete(red->instances, id); + XFREE(MTYPE_REDIST_INST, id); + if (!red->instances->count) { + red->enabled = 0; + list_free(red->instances); + red->instances = NULL; + } } /* Stop zebra client services. */ -void -zclient_stop (struct zclient *zclient) +void zclient_stop(struct zclient *zclient) { - afi_t afi; - int i; - - if (zclient_debug) - zlog_debug ("zclient stopped"); - - /* Stop threads. */ - THREAD_OFF(zclient->t_read); - THREAD_OFF(zclient->t_connect); - THREAD_OFF(zclient->t_write); - - /* Reset streams. */ - stream_reset(zclient->ibuf); - stream_reset(zclient->obuf); - - /* Empty the write buffer. */ - buffer_reset(zclient->wb); - - /* Close socket. */ - if (zclient->sock >= 0) - { - close (zclient->sock); - zclient->sock = -1; - } - zclient->fail = 0; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - vrf_bitmap_free(zclient->redist[afi][i]); - zclient->redist[afi][i] = VRF_BITMAP_NULL; + afi_t afi; + int i; + + if (zclient_debug) + zlog_debug("zclient stopped"); + + /* Stop threads. */ + THREAD_OFF(zclient->t_read); + THREAD_OFF(zclient->t_connect); + THREAD_OFF(zclient->t_write); + + /* Reset streams. */ + stream_reset(zclient->ibuf); + stream_reset(zclient->obuf); + + /* Empty the write buffer. */ + buffer_reset(zclient->wb); + + /* Close socket. */ + if (zclient->sock >= 0) { + close(zclient->sock); + zclient->sock = -1; + } + zclient->fail = 0; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + vrf_bitmap_free(zclient->redist[afi][i]); + zclient->redist[afi][i] = VRF_BITMAP_NULL; + } + redist_del_instance( + &zclient->mi_redist[afi][zclient->redist_default], + zclient->instance); } - redist_del_instance(&zclient->mi_redist[afi][zclient->redist_default], - zclient->instance); - } - vrf_bitmap_free(zclient->default_information); - zclient->default_information = VRF_BITMAP_NULL; + vrf_bitmap_free(zclient->default_information); + zclient->default_information = VRF_BITMAP_NULL; } -void -zclient_reset (struct zclient *zclient) +void zclient_reset(struct zclient *zclient) { - afi_t afi; + afi_t afi; - zclient_stop (zclient); + zclient_stop(zclient); - for (afi = AFI_IP; afi < AFI_MAX; afi++) - redist_del_instance (&zclient->mi_redist[afi][zclient->redist_default], zclient->instance); + for (afi = AFI_IP; afi < AFI_MAX; afi++) + redist_del_instance( + &zclient->mi_redist[afi][zclient->redist_default], + zclient->instance); - zclient_init (zclient, zclient->redist_default, zclient->instance); + zclient_init(zclient, zclient->redist_default, zclient->instance); } #ifdef HAVE_TCP_ZEBRA /* Make socket to zebra daemon. Return zebra socket. */ -static int -zclient_socket(void) +static int zclient_socket(void) { - int sock; - int ret; - struct sockaddr_in serv; - - /* We should think about IPv6 connection. */ - sock = socket (AF_INET, SOCK_STREAM, 0); - if (sock < 0) - return -1; - - /* Make server socket. */ - memset (&serv, 0, sizeof (struct sockaddr_in)); - serv.sin_family = AF_INET; - serv.sin_port = htons (ZEBRA_PORT); + int sock; + int ret; + struct sockaddr_in serv; + + /* We should think about IPv6 connection. */ + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) + return -1; + + /* Make server socket. */ + memset(&serv, 0, sizeof(struct sockaddr_in)); + serv.sin_family = AF_INET; + serv.sin_port = htons(ZEBRA_PORT); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - serv.sin_len = sizeof (struct sockaddr_in); + serv.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - serv.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - - /* Connect to zebra. */ - ret = connect (sock, (struct sockaddr *) &serv, sizeof (serv)); - if (ret < 0) - { - if (zclient_debug) - zlog_warn ("%s connect failure: %d(%s)", __PRETTY_FUNCTION__, - errno, safe_strerror (errno)); - close (sock); - return -1; - } - return sock; + serv.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + /* Connect to zebra. */ + ret = connect(sock, (struct sockaddr *)&serv, sizeof(serv)); + if (ret < 0) { + if (zclient_debug) + zlog_warn("%s connect failure: %d(%s)", + __PRETTY_FUNCTION__, errno, + safe_strerror(errno)); + close(sock); + return -1; + } + return sock; } #else @@ -233,37 +224,36 @@ zclient_socket(void) /* For sockaddr_un. */ #include -static int -zclient_socket_un (const char *path) +static int zclient_socket_un(const char *path) { - int ret; - int sock, len; - struct sockaddr_un addr; - - sock = socket (AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) - return -1; - - /* Make server socket. */ - memset (&addr, 0, sizeof (struct sockaddr_un)); - addr.sun_family = AF_UNIX; - strncpy (addr.sun_path, path, strlen (path)); + int ret; + int sock, len; + struct sockaddr_un addr; + + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) + return -1; + + /* Make server socket. */ + memset(&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, path, strlen(path)); #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN - len = addr.sun_len = SUN_LEN(&addr); + len = addr.sun_len = SUN_LEN(&addr); #else - len = sizeof (addr.sun_family) + strlen (addr.sun_path); + len = sizeof(addr.sun_family) + strlen(addr.sun_path); #endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */ - ret = connect (sock, (struct sockaddr *) &addr, len); - if (ret < 0) - { - if (zclient_debug) - zlog_warn ("%s connect failure: %d(%s)", __PRETTY_FUNCTION__, - errno, safe_strerror (errno)); - close (sock); - return -1; - } - return sock; + ret = connect(sock, (struct sockaddr *)&addr, len); + if (ret < 0) { + if (zclient_debug) + zlog_warn("%s connect failure: %d(%s)", + __PRETTY_FUNCTION__, errno, + safe_strerror(errno)); + close(sock); + return -1; + } + return sock; } #endif /* HAVE_TCP_ZEBRA */ @@ -275,853 +265,864 @@ zclient_socket_un (const char *path) * @see zclient_init * @see zclient_new */ -int -zclient_socket_connect (struct zclient *zclient) +int zclient_socket_connect(struct zclient *zclient) { #ifdef HAVE_TCP_ZEBRA - zclient->sock = zclient_socket (); + zclient->sock = zclient_socket(); #else - zclient->sock = zclient_socket_un (zclient_serv_path_get()); + zclient->sock = zclient_socket_un(zclient_serv_path_get()); #endif - return zclient->sock; + return zclient->sock; } -static int -zclient_failed(struct zclient *zclient) +static int zclient_failed(struct zclient *zclient) { - zclient->fail++; - zclient_stop(zclient); - zclient_event(ZCLIENT_CONNECT, zclient); - return -1; + zclient->fail++; + zclient_stop(zclient); + zclient_event(ZCLIENT_CONNECT, zclient); + return -1; } -static int -zclient_flush_data(struct thread *thread) +static int zclient_flush_data(struct thread *thread) { - struct zclient *zclient = THREAD_ARG(thread); - - zclient->t_write = NULL; - if (zclient->sock < 0) - return -1; - switch (buffer_flush_available(zclient->wb, zclient->sock)) - { - case BUFFER_ERROR: - zlog_warn("%s: buffer_flush_available failed on zclient fd %d, closing", - __func__, zclient->sock); - return zclient_failed(zclient); - break; - case BUFFER_PENDING: - zclient->t_write = NULL; - thread_add_write(zclient->master, zclient_flush_data, zclient, zclient->sock, - &zclient->t_write); - break; - case BUFFER_EMPTY: - break; - } - return 0; + struct zclient *zclient = THREAD_ARG(thread); + + zclient->t_write = NULL; + if (zclient->sock < 0) + return -1; + switch (buffer_flush_available(zclient->wb, zclient->sock)) { + case BUFFER_ERROR: + zlog_warn( + "%s: buffer_flush_available failed on zclient fd %d, closing", + __func__, zclient->sock); + return zclient_failed(zclient); + break; + case BUFFER_PENDING: + zclient->t_write = NULL; + thread_add_write(zclient->master, zclient_flush_data, zclient, + zclient->sock, &zclient->t_write); + break; + case BUFFER_EMPTY: + break; + } + return 0; } -int -zclient_send_message(struct zclient *zclient) +int zclient_send_message(struct zclient *zclient) { - if (zclient->sock < 0) - return -1; - switch (buffer_write(zclient->wb, zclient->sock, STREAM_DATA(zclient->obuf), - stream_get_endp(zclient->obuf))) - { - case BUFFER_ERROR: - zlog_warn("%s: buffer_write failed to zclient fd %d, closing", - __func__, zclient->sock); - return zclient_failed(zclient); - break; - case BUFFER_EMPTY: - THREAD_OFF(zclient->t_write); - break; - case BUFFER_PENDING: - thread_add_write(zclient->master, zclient_flush_data, zclient, - zclient->sock, &zclient->t_write); - break; - } - return 0; + if (zclient->sock < 0) + return -1; + switch (buffer_write(zclient->wb, zclient->sock, + STREAM_DATA(zclient->obuf), + stream_get_endp(zclient->obuf))) { + case BUFFER_ERROR: + zlog_warn("%s: buffer_write failed to zclient fd %d, closing", + __func__, zclient->sock); + return zclient_failed(zclient); + break; + case BUFFER_EMPTY: + THREAD_OFF(zclient->t_write); + break; + case BUFFER_PENDING: + thread_add_write(zclient->master, zclient_flush_data, zclient, + zclient->sock, &zclient->t_write); + break; + } + return 0; } -void -zclient_create_header (struct stream *s, uint16_t command, vrf_id_t vrf_id) +void zclient_create_header(struct stream *s, uint16_t command, vrf_id_t vrf_id) { - /* length placeholder, caller can update */ - stream_putw (s, ZEBRA_HEADER_SIZE); - stream_putc (s, ZEBRA_HEADER_MARKER); - stream_putc (s, ZSERV_VERSION); - stream_putw (s, vrf_id); - stream_putw (s, command); + /* length placeholder, caller can update */ + stream_putw(s, ZEBRA_HEADER_SIZE); + stream_putc(s, ZEBRA_HEADER_MARKER); + stream_putc(s, ZSERV_VERSION); + stream_putw(s, vrf_id); + stream_putw(s, command); } -int -zclient_read_header (struct stream *s, int sock, u_int16_t *size, u_char *marker, - u_char *version, vrf_id_t *vrf_id, u_int16_t *cmd) +int zclient_read_header(struct stream *s, int sock, u_int16_t *size, + u_char *marker, u_char *version, vrf_id_t *vrf_id, + u_int16_t *cmd) { - if (stream_read (s, sock, ZEBRA_HEADER_SIZE) != ZEBRA_HEADER_SIZE) - return -1; - - *size = stream_getw (s) - ZEBRA_HEADER_SIZE; - *marker = stream_getc (s); - *version = stream_getc (s); - *vrf_id = stream_getw (s); - *cmd = stream_getw (s); - - if (*version != ZSERV_VERSION || *marker != ZEBRA_HEADER_MARKER) - { - zlog_err("%s: socket %d version mismatch, marker %d, version %d", - __func__, sock, *marker, *version); - return -1; - } - - if (*size && stream_read (s, sock, *size) != *size) - return -1; - - return 0; + if (stream_read(s, sock, ZEBRA_HEADER_SIZE) != ZEBRA_HEADER_SIZE) + return -1; + + *size = stream_getw(s) - ZEBRA_HEADER_SIZE; + *marker = stream_getc(s); + *version = stream_getc(s); + *vrf_id = stream_getw(s); + *cmd = stream_getw(s); + + if (*version != ZSERV_VERSION || *marker != ZEBRA_HEADER_MARKER) { + zlog_err( + "%s: socket %d version mismatch, marker %d, version %d", + __func__, sock, *marker, *version); + return -1; + } + + if (*size && stream_read(s, sock, *size) != *size) + return -1; + + return 0; } /* Send simple Zebra message. */ -static int -zebra_message_send (struct zclient *zclient, int command, vrf_id_t vrf_id) +static int zebra_message_send(struct zclient *zclient, int command, + vrf_id_t vrf_id) { - struct stream *s; + struct stream *s; - /* Get zclient output buffer. */ - s = zclient->obuf; - stream_reset (s); + /* Get zclient output buffer. */ + s = zclient->obuf; + stream_reset(s); - /* Send very simple command only Zebra message. */ - zclient_create_header (s, command, vrf_id); - - return zclient_send_message(zclient); + /* Send very simple command only Zebra message. */ + zclient_create_header(s, command, vrf_id); + + return zclient_send_message(zclient); } -static int -zebra_hello_send (struct zclient *zclient) +static int zebra_hello_send(struct zclient *zclient) { - struct stream *s; - - if (zclient->redist_default) - { - s = zclient->obuf; - stream_reset (s); - - /* The VRF ID in the HELLO message is always 0. */ - zclient_create_header (s, ZEBRA_HELLO, VRF_DEFAULT); - stream_putc (s, zclient->redist_default); - stream_putw (s, zclient->instance); - stream_putw_at (s, 0, stream_get_endp (s)); - return zclient_send_message(zclient); - } - - return 0; + struct stream *s; + + if (zclient->redist_default) { + s = zclient->obuf; + stream_reset(s); + + /* The VRF ID in the HELLO message is always 0. */ + zclient_create_header(s, ZEBRA_HELLO, VRF_DEFAULT); + stream_putc(s, zclient->redist_default); + stream_putw(s, zclient->instance); + stream_putw_at(s, 0, stream_get_endp(s)); + return zclient_send_message(zclient); + } + + return 0; } /* Send register requests to zebra daemon for the information in a VRF. */ -void -zclient_send_reg_requests (struct zclient *zclient, vrf_id_t vrf_id) +void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id) { - int i; - afi_t afi; - - /* zclient is disabled. */ - if (! zclient->enable) - return; - - /* If not connected to the zebra yet. */ - if (zclient->sock < 0) - return; - - if (zclient_debug) - zlog_debug ("%s: send register messages for VRF %u", __func__, vrf_id); - - /* We need router-id information. */ - zebra_message_send (zclient, ZEBRA_ROUTER_ID_ADD, vrf_id); - - /* We need interface information. */ - zebra_message_send (zclient, ZEBRA_INTERFACE_ADD, vrf_id); - - /* Set unwanted redistribute route. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - vrf_bitmap_set (zclient->redist[afi][zclient->redist_default], vrf_id); - - /* Flush all redistribute request. */ - if (vrf_id == VRF_DEFAULT) - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (zclient->mi_redist[afi][i].enabled) - { - struct listnode *node; - u_short *id; - - for (ALL_LIST_ELEMENTS_RO(zclient->mi_redist[afi][i].instances, node, id)) - if (!(i == zclient->redist_default && *id == zclient->instance)) - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, afi, i, - *id, VRF_DEFAULT); - } - - /* Flush all redistribute request. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (i != zclient->redist_default && - vrf_bitmap_check (zclient->redist[afi][i], vrf_id)) - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, afi, i, 0, vrf_id); - - /* If default information is needed. */ - if (vrf_bitmap_check (zclient->default_information, VRF_DEFAULT)) - zebra_message_send (zclient, ZEBRA_REDISTRIBUTE_DEFAULT_ADD, vrf_id); + int i; + afi_t afi; + + /* zclient is disabled. */ + if (!zclient->enable) + return; + + /* If not connected to the zebra yet. */ + if (zclient->sock < 0) + return; + + if (zclient_debug) + zlog_debug("%s: send register messages for VRF %u", __func__, + vrf_id); + + /* We need router-id information. */ + zebra_message_send(zclient, ZEBRA_ROUTER_ID_ADD, vrf_id); + + /* We need interface information. */ + zebra_message_send(zclient, ZEBRA_INTERFACE_ADD, vrf_id); + + /* Set unwanted redistribute route. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + vrf_bitmap_set(zclient->redist[afi][zclient->redist_default], + vrf_id); + + /* Flush all redistribute request. */ + if (vrf_id == VRF_DEFAULT) + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (zclient->mi_redist[afi][i].enabled) { + struct listnode *node; + u_short *id; + + for (ALL_LIST_ELEMENTS_RO( + zclient->mi_redist[afi][i] + .instances, + node, id)) + if (!(i == zclient->redist_default + && *id == zclient->instance)) + zebra_redistribute_send( + ZEBRA_REDISTRIBUTE_ADD, + zclient, afi, i, + *id, + VRF_DEFAULT); + } + + /* Flush all redistribute request. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (i != zclient->redist_default + && vrf_bitmap_check(zclient->redist[afi][i], + vrf_id)) + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, + zclient, afi, i, 0, + vrf_id); + + /* If default information is needed. */ + if (vrf_bitmap_check(zclient->default_information, VRF_DEFAULT)) + zebra_message_send(zclient, ZEBRA_REDISTRIBUTE_DEFAULT_ADD, + vrf_id); } /* Send unregister requests to zebra daemon for the information in a VRF. */ -void -zclient_send_dereg_requests (struct zclient *zclient, vrf_id_t vrf_id) +void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id) { - int i; - afi_t afi; - - /* zclient is disabled. */ - if (! zclient->enable) - return; - - /* If not connected to the zebra yet. */ - if (zclient->sock < 0) - return; - - if (zclient_debug) - zlog_debug ("%s: send deregister messages for VRF %u", __func__, vrf_id); - - /* We need router-id information. */ - zebra_message_send (zclient, ZEBRA_ROUTER_ID_DELETE, vrf_id); - - /* We need interface information. */ - zebra_message_send (zclient, ZEBRA_INTERFACE_DELETE, vrf_id); - - /* Set unwanted redistribute route. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - vrf_bitmap_set (zclient->redist[afi][zclient->redist_default], vrf_id); - - /* Flush all redistribute request. */ - if (vrf_id == VRF_DEFAULT) - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (zclient->mi_redist[afi][i].enabled) - { - struct listnode *node; - u_short *id; - - for (ALL_LIST_ELEMENTS_RO(zclient->mi_redist[afi][i].instances, node, id)) - if (!(i == zclient->redist_default && *id == zclient->instance)) - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, i, - *id, VRF_DEFAULT); - } - - /* Flush all redistribute request. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (i != zclient->redist_default && - vrf_bitmap_check (zclient->redist[afi][i], vrf_id)) - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, i, 0, vrf_id); - - /* If default information is needed. */ - if (vrf_bitmap_check (zclient->default_information, VRF_DEFAULT)) - zebra_message_send (zclient, ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, vrf_id); + int i; + afi_t afi; + + /* zclient is disabled. */ + if (!zclient->enable) + return; + + /* If not connected to the zebra yet. */ + if (zclient->sock < 0) + return; + + if (zclient_debug) + zlog_debug("%s: send deregister messages for VRF %u", __func__, + vrf_id); + + /* We need router-id information. */ + zebra_message_send(zclient, ZEBRA_ROUTER_ID_DELETE, vrf_id); + + /* We need interface information. */ + zebra_message_send(zclient, ZEBRA_INTERFACE_DELETE, vrf_id); + + /* Set unwanted redistribute route. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + vrf_bitmap_set(zclient->redist[afi][zclient->redist_default], + vrf_id); + + /* Flush all redistribute request. */ + if (vrf_id == VRF_DEFAULT) + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (zclient->mi_redist[afi][i].enabled) { + struct listnode *node; + u_short *id; + + for (ALL_LIST_ELEMENTS_RO( + zclient->mi_redist[afi][i] + .instances, + node, id)) + if (!(i == zclient->redist_default + && *id == zclient->instance)) + zebra_redistribute_send( + ZEBRA_REDISTRIBUTE_DELETE, + zclient, afi, i, + *id, + VRF_DEFAULT); + } + + /* Flush all redistribute request. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (i != zclient->redist_default + && vrf_bitmap_check(zclient->redist[afi][i], + vrf_id)) + zebra_redistribute_send( + ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, + i, 0, vrf_id); + + /* If default information is needed. */ + if (vrf_bitmap_check(zclient->default_information, VRF_DEFAULT)) + zebra_message_send(zclient, ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, + vrf_id); } /* Send request to zebra daemon to start or stop RA. */ -void -zclient_send_interface_radv_req (struct zclient *zclient, vrf_id_t vrf_id, - struct interface *ifp, int enable, int ra_interval) +void zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id, + struct interface *ifp, int enable, + int ra_interval) { - struct stream *s; + struct stream *s; - /* zclient is disabled. */ - if (!zclient->enable) - return; + /* zclient is disabled. */ + if (!zclient->enable) + return; - /* If not connected to the zebra yet. */ - if (zclient->sock < 0) - return; + /* If not connected to the zebra yet. */ + if (zclient->sock < 0) + return; - /* Form and send message. */ - s = zclient->obuf; - stream_reset (s); + /* Form and send message. */ + s = zclient->obuf; + stream_reset(s); - if (enable) - zclient_create_header (s, ZEBRA_INTERFACE_ENABLE_RADV, vrf_id); - else - zclient_create_header (s, ZEBRA_INTERFACE_DISABLE_RADV, vrf_id); + if (enable) + zclient_create_header(s, ZEBRA_INTERFACE_ENABLE_RADV, vrf_id); + else + zclient_create_header(s, ZEBRA_INTERFACE_DISABLE_RADV, vrf_id); - stream_putl (s, ifp->ifindex); - stream_putl (s, ra_interval); + stream_putl(s, ifp->ifindex); + stream_putl(s, ra_interval); - stream_putw_at (s, 0, stream_get_endp (s)); + stream_putw_at(s, 0, stream_get_endp(s)); - zclient_send_message(zclient); + zclient_send_message(zclient); } /* Make connection to zebra daemon. */ -int -zclient_start (struct zclient *zclient) +int zclient_start(struct zclient *zclient) { - if (zclient_debug) - zlog_info ("zclient_start is called"); - - /* zclient is disabled. */ - if (! zclient->enable) - return 0; - - /* If already connected to the zebra. */ - if (zclient->sock >= 0) - return 0; - - /* Check connect thread. */ - if (zclient->t_connect) - return 0; - - if (zclient_socket_connect(zclient) < 0) - { - if (zclient_debug) - zlog_debug ("zclient connection fail"); - zclient->fail++; - zclient_event (ZCLIENT_CONNECT, zclient); - return -1; - } + if (zclient_debug) + zlog_info("zclient_start is called"); + + /* zclient is disabled. */ + if (!zclient->enable) + return 0; + + /* If already connected to the zebra. */ + if (zclient->sock >= 0) + return 0; + + /* Check connect thread. */ + if (zclient->t_connect) + return 0; + + if (zclient_socket_connect(zclient) < 0) { + if (zclient_debug) + zlog_debug("zclient connection fail"); + zclient->fail++; + zclient_event(ZCLIENT_CONNECT, zclient); + return -1; + } - if (set_nonblocking(zclient->sock) < 0) - zlog_warn("%s: set_nonblocking(%d) failed", __func__, zclient->sock); + if (set_nonblocking(zclient->sock) < 0) + zlog_warn("%s: set_nonblocking(%d) failed", __func__, + zclient->sock); - /* Clear fail count. */ - zclient->fail = 0; - if (zclient_debug) - zlog_debug ("zclient connect success with socket [%d]", zclient->sock); + /* Clear fail count. */ + zclient->fail = 0; + if (zclient_debug) + zlog_debug("zclient connect success with socket [%d]", + zclient->sock); - /* Create read thread. */ - zclient_event (ZCLIENT_READ, zclient); + /* Create read thread. */ + zclient_event(ZCLIENT_READ, zclient); - zebra_hello_send (zclient); + zebra_hello_send(zclient); - /* Inform the successful connection. */ - if (zclient->zebra_connected) - (*zclient->zebra_connected) (zclient); + /* Inform the successful connection. */ + if (zclient->zebra_connected) + (*zclient->zebra_connected)(zclient); - return 0; + return 0; } /* Initialize zebra client. Argument redist_default is unwanted redistribute route type. */ -void -zclient_init (struct zclient *zclient, int redist_default, u_short instance) +void zclient_init(struct zclient *zclient, int redist_default, u_short instance) { - int afi, i; - - /* Enable zebra client connection by default. */ - zclient->enable = 1; - - /* Set -1 to the default socket value. */ - zclient->sock = -1; - - /* Clear redistribution flags. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - zclient->redist[afi][i] = vrf_bitmap_init(); - - /* Set unwanted redistribute route. bgpd does not need BGP route - redistribution. */ - zclient->redist_default = redist_default; - zclient->instance = instance; - /* Pending: make afi(s) an arg. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) - redist_add_instance (&zclient->mi_redist[afi][redist_default], instance); - - /* Set default-information redistribute to zero. */ - zclient->default_information = vrf_bitmap_init ();; - - if (zclient_debug) - zlog_debug ("zclient_start is called"); - - zclient_event (ZCLIENT_SCHEDULE, zclient); + int afi, i; + + /* Enable zebra client connection by default. */ + zclient->enable = 1; + + /* Set -1 to the default socket value. */ + zclient->sock = -1; + + /* Clear redistribution flags. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + zclient->redist[afi][i] = vrf_bitmap_init(); + + /* Set unwanted redistribute route. bgpd does not need BGP route + redistribution. */ + zclient->redist_default = redist_default; + zclient->instance = instance; + /* Pending: make afi(s) an arg. */ + for (afi = AFI_IP; afi < AFI_MAX; afi++) + redist_add_instance(&zclient->mi_redist[afi][redist_default], + instance); + + /* Set default-information redistribute to zero. */ + zclient->default_information = vrf_bitmap_init(); + ; + + if (zclient_debug) + zlog_debug("zclient_start is called"); + + zclient_event(ZCLIENT_SCHEDULE, zclient); } /* This function is a wrapper function for calling zclient_start from timer or event thread. */ -static int -zclient_connect (struct thread *t) +static int zclient_connect(struct thread *t) { - struct zclient *zclient; + struct zclient *zclient; - zclient = THREAD_ARG (t); - zclient->t_connect = NULL; + zclient = THREAD_ARG(t); + zclient->t_connect = NULL; - if (zclient_debug) - zlog_debug ("zclient_connect is called"); + if (zclient_debug) + zlog_debug("zclient_connect is called"); - return zclient_start (zclient); + return zclient_start(zclient); } - /* - * "xdr_encode"-like interface that allows daemon (client) to send - * a message to zebra server for a route that needs to be - * added/deleted to the kernel. Info about the route is specified - * by the caller in a struct zapi_ipv4. zapi_ipv4_read() then writes - * the info down the zclient socket using the stream_* functions. - * - * The corresponding read ("xdr_decode") function on the server - * side is zread_ipv4_add()/zread_ipv4_delete(). - * - * 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Length (2) | Command | Route Type | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | ZEBRA Flags | Message Flags | Prefix length | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Destination IPv4 Prefix for route | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Nexthop count | - * +-+-+-+-+-+-+-+-+ - * - * - * A number of IPv4 nexthop(s) or nexthop interface index(es) are then - * described, as per the Nexthop count. Each nexthop described as: - * - * +-+-+-+-+-+-+-+-+ - * | Nexthop Type | Set to one of ZEBRA_NEXTHOP_* - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | IPv4 Nexthop address or Interface Index number | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * Alternatively, if the flags field has ZEBRA_FLAG_BLACKHOLE or - * ZEBRA_FLAG_REJECT is set then Nexthop count is set to 1, then _no_ - * nexthop information is provided, and the message describes a prefix - * to blackhole or reject route. - * - * The original struct zapi_ipv4, zapi_ipv4_route() and zread_ipv4_*() - * infrastructure was built around the traditional (32-bit "gate OR - * ifindex") nexthop data unit. A special encoding can be used to feed - * onlink (64-bit "gate AND ifindex") nexthops into zapi_ipv4_route() - * using the same zapi_ipv4 structure. This is done by setting zapi_ipv4 - * fields as follows: - * - .message |= ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_ONLINK - * - .nexthop_num == .ifindex_num - * - .nexthop and .ifindex are filled with gate and ifindex parts of - * each compound nexthop, both in the same order - * - * zapi_ipv4_route() will produce two nexthop data units for each such - * interleaved 64-bit nexthop. On the zserv side of the socket it will be - * mapped to a singlle NEXTHOP_TYPE_IPV4_IFINDEX_OL RIB nexthop structure. - * - * If ZAPI_MESSAGE_DISTANCE is set, the distance value is written as a 1 - * byte value. - * - * If ZAPI_MESSAGE_METRIC is set, the metric value is written as an 8 - * byte value. - * - * If ZAPI_MESSAGE_TAG is set, the tag value is written as a 4 byte value - * - * If ZAPI_MESSAGE_MTU is set, the mtu value is written as a 4 byte value - * - * XXX: No attention paid to alignment. - */ -int -zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p, - struct zapi_ipv4 *api) +/* + * "xdr_encode"-like interface that allows daemon (client) to send + * a message to zebra server for a route that needs to be + * added/deleted to the kernel. Info about the route is specified + * by the caller in a struct zapi_ipv4. zapi_ipv4_read() then writes + * the info down the zclient socket using the stream_* functions. + * + * The corresponding read ("xdr_decode") function on the server + * side is zread_ipv4_add()/zread_ipv4_delete(). + * + * 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Length (2) | Command | Route Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | ZEBRA Flags | Message Flags | Prefix length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Destination IPv4 Prefix for route | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Nexthop count | + * +-+-+-+-+-+-+-+-+ + * + * + * A number of IPv4 nexthop(s) or nexthop interface index(es) are then + * described, as per the Nexthop count. Each nexthop described as: + * + * +-+-+-+-+-+-+-+-+ + * | Nexthop Type | Set to one of ZEBRA_NEXTHOP_* + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | IPv4 Nexthop address or Interface Index number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Alternatively, if the flags field has ZEBRA_FLAG_BLACKHOLE or + * ZEBRA_FLAG_REJECT is set then Nexthop count is set to 1, then _no_ + * nexthop information is provided, and the message describes a prefix + * to blackhole or reject route. + * + * The original struct zapi_ipv4, zapi_ipv4_route() and zread_ipv4_*() + * infrastructure was built around the traditional (32-bit "gate OR + * ifindex") nexthop data unit. A special encoding can be used to feed + * onlink (64-bit "gate AND ifindex") nexthops into zapi_ipv4_route() + * using the same zapi_ipv4 structure. This is done by setting zapi_ipv4 + * fields as follows: + * - .message |= ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_ONLINK + * - .nexthop_num == .ifindex_num + * - .nexthop and .ifindex are filled with gate and ifindex parts of + * each compound nexthop, both in the same order + * + * zapi_ipv4_route() will produce two nexthop data units for each such + * interleaved 64-bit nexthop. On the zserv side of the socket it will be + * mapped to a singlle NEXTHOP_TYPE_IPV4_IFINDEX_OL RIB nexthop structure. + * + * If ZAPI_MESSAGE_DISTANCE is set, the distance value is written as a 1 + * byte value. + * + * If ZAPI_MESSAGE_METRIC is set, the metric value is written as an 8 + * byte value. + * + * If ZAPI_MESSAGE_TAG is set, the tag value is written as a 4 byte value + * + * If ZAPI_MESSAGE_MTU is set, the mtu value is written as a 4 byte value + * + * XXX: No attention paid to alignment. + */ +int zapi_ipv4_route(u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p, + struct zapi_ipv4 *api) { - int i; - int psize; - struct stream *s; - - /* Reset stream. */ - s = zclient->obuf; - stream_reset (s); - - /* Some checks for labeled-unicast. The current expectation is that each - * nexthop is accompanied by a label in the case of labeled-unicast. - */ - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL) && - CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP)) - { - /* We expect prefixes installed with labels and the number to match - * the number of nexthops. - */ - assert (api->label_num == api->nexthop_num); - } - - zclient_create_header (s, cmd, api->vrf_id); - - /* Put type and nexthop. */ - stream_putc (s, api->type); - stream_putw (s, api->instance); - stream_putl (s, api->flags); - stream_putc (s, api->message); - stream_putw (s, api->safi); - - /* Put prefix information. */ - psize = PSIZE (p->prefixlen); - stream_putc (s, p->prefixlen); - stream_write (s, (u_char *) & p->prefix, psize); - - /* Nexthop, ifindex, distance and metric information. */ - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP)) - { - /* traditional 32-bit data units */ - if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE)) - { - stream_putc (s, 1); - stream_putc (s, NEXTHOP_TYPE_BLACKHOLE); - /* XXX assert(api->nexthop_num == 0); */ - /* XXX assert(api->ifindex_num == 0); */ - } - else - stream_putc (s, api->nexthop_num + api->ifindex_num); - - for (i = 0; i < api->nexthop_num; i++) - { - stream_putc (s, NEXTHOP_TYPE_IPV4); - stream_put_in_addr (s, api->nexthop[i]); - /* For labeled-unicast, each nexthop is followed by label. */ - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL)) - stream_putl (s, api->label[i]); - } - for (i = 0; i < api->ifindex_num; i++) - { - stream_putc (s, NEXTHOP_TYPE_IFINDEX); - stream_putl (s, api->ifindex[i]); - } - } - - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_DISTANCE)) - stream_putc (s, api->distance); - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC)) - stream_putl (s, api->metric); - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_TAG)) - stream_putl (s, api->tag); - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_MTU)) - stream_putl (s, api->mtu); - - /* Put length at the first point of the stream. */ - stream_putw_at (s, 0, stream_get_endp (s)); - - return zclient_send_message(zclient); + int i; + int psize; + struct stream *s; + + /* Reset stream. */ + s = zclient->obuf; + stream_reset(s); + + /* Some checks for labeled-unicast. The current expectation is that each + * nexthop is accompanied by a label in the case of labeled-unicast. + */ + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL) + && CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { + /* We expect prefixes installed with labels and the number to + * match + * the number of nexthops. + */ + assert(api->label_num == api->nexthop_num); + } + + zclient_create_header(s, cmd, api->vrf_id); + + /* Put type and nexthop. */ + stream_putc(s, api->type); + stream_putw(s, api->instance); + stream_putl(s, api->flags); + stream_putc(s, api->message); + stream_putw(s, api->safi); + + /* Put prefix information. */ + psize = PSIZE(p->prefixlen); + stream_putc(s, p->prefixlen); + stream_write(s, (u_char *)&p->prefix, psize); + + /* Nexthop, ifindex, distance and metric information. */ + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { + /* traditional 32-bit data units */ + if (CHECK_FLAG(api->flags, ZEBRA_FLAG_BLACKHOLE)) { + stream_putc(s, 1); + stream_putc(s, NEXTHOP_TYPE_BLACKHOLE); + /* XXX assert(api->nexthop_num == 0); */ + /* XXX assert(api->ifindex_num == 0); */ + } else + stream_putc(s, api->nexthop_num + api->ifindex_num); + + for (i = 0; i < api->nexthop_num; i++) { + stream_putc(s, NEXTHOP_TYPE_IPV4); + stream_put_in_addr(s, api->nexthop[i]); + /* For labeled-unicast, each nexthop is followed by + * label. */ + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)) + stream_putl(s, api->label[i]); + } + for (i = 0; i < api->ifindex_num; i++) { + stream_putc(s, NEXTHOP_TYPE_IFINDEX); + stream_putl(s, api->ifindex[i]); + } + } + + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE)) + stream_putc(s, api->distance); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC)) + stream_putl(s, api->metric); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG)) + stream_putl(s, api->tag); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU)) + stream_putl(s, api->mtu); + + /* Put length at the first point of the stream. */ + stream_putw_at(s, 0, stream_get_endp(s)); + + return zclient_send_message(zclient); } -int -zapi_ipv4_route_ipv6_nexthop (u_char cmd, struct zclient *zclient, - struct prefix_ipv4 *p, struct zapi_ipv6 *api) +int zapi_ipv4_route_ipv6_nexthop(u_char cmd, struct zclient *zclient, + struct prefix_ipv4 *p, struct zapi_ipv6 *api) { - int i; - int psize; - struct stream *s; - - /* Reset stream. */ - s = zclient->obuf; - stream_reset (s); - - /* Some checks for labeled-unicast. The current expectation is that each - * nexthop is accompanied by a label in the case of labeled-unicast. - */ - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL) && - CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP)) - { - /* We expect prefixes installed with labels and the number to match - * the number of nexthops. - */ - assert (api->label_num == api->nexthop_num); - } - - zclient_create_header (s, cmd, api->vrf_id); - - /* Put type and nexthop. */ - stream_putc (s, api->type); - stream_putw (s, api->instance); - stream_putl (s, api->flags); - stream_putc (s, api->message); - stream_putw (s, api->safi); - - /* Put prefix information. */ - psize = PSIZE (p->prefixlen); - stream_putc (s, p->prefixlen); - stream_write (s, (u_char *) & p->prefix, psize); - - /* Nexthop, ifindex, distance and metric information. */ - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP)) - { - if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE)) - { - stream_putc (s, 1); - stream_putc (s, NEXTHOP_TYPE_BLACKHOLE); - /* XXX assert(api->nexthop_num == 0); */ - /* XXX assert(api->ifindex_num == 0); */ - } - else - stream_putc (s, api->nexthop_num + api->ifindex_num); - - for (i = 0; i < api->nexthop_num; i++) - { - stream_putc (s, NEXTHOP_TYPE_IPV6); - stream_write (s, (u_char *)api->nexthop[i], 16); - /* For labeled-unicast, each nexthop is followed by label. */ - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL)) - stream_putl (s, api->label[i]); + int i; + int psize; + struct stream *s; + + /* Reset stream. */ + s = zclient->obuf; + stream_reset(s); + + /* Some checks for labeled-unicast. The current expectation is that each + * nexthop is accompanied by a label in the case of labeled-unicast. + */ + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL) + && CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { + /* We expect prefixes installed with labels and the number to + * match + * the number of nexthops. + */ + assert(api->label_num == api->nexthop_num); } - for (i = 0; i < api->ifindex_num; i++) - { - stream_putc (s, NEXTHOP_TYPE_IFINDEX); - stream_putl (s, api->ifindex[i]); + + zclient_create_header(s, cmd, api->vrf_id); + + /* Put type and nexthop. */ + stream_putc(s, api->type); + stream_putw(s, api->instance); + stream_putl(s, api->flags); + stream_putc(s, api->message); + stream_putw(s, api->safi); + + /* Put prefix information. */ + psize = PSIZE(p->prefixlen); + stream_putc(s, p->prefixlen); + stream_write(s, (u_char *)&p->prefix, psize); + + /* Nexthop, ifindex, distance and metric information. */ + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { + if (CHECK_FLAG(api->flags, ZEBRA_FLAG_BLACKHOLE)) { + stream_putc(s, 1); + stream_putc(s, NEXTHOP_TYPE_BLACKHOLE); + /* XXX assert(api->nexthop_num == 0); */ + /* XXX assert(api->ifindex_num == 0); */ + } else + stream_putc(s, api->nexthop_num + api->ifindex_num); + + for (i = 0; i < api->nexthop_num; i++) { + stream_putc(s, NEXTHOP_TYPE_IPV6); + stream_write(s, (u_char *)api->nexthop[i], 16); + /* For labeled-unicast, each nexthop is followed by + * label. */ + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)) + stream_putl(s, api->label[i]); + } + for (i = 0; i < api->ifindex_num; i++) { + stream_putc(s, NEXTHOP_TYPE_IFINDEX); + stream_putl(s, api->ifindex[i]); + } } - } - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_DISTANCE)) - stream_putc (s, api->distance); - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC)) - stream_putl (s, api->metric); - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_TAG)) - stream_putl (s, api->tag); - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_MTU)) - stream_putl (s, api->mtu); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE)) + stream_putc(s, api->distance); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC)) + stream_putl(s, api->metric); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG)) + stream_putl(s, api->tag); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU)) + stream_putl(s, api->mtu); - /* Put length at the first point of the stream. */ - stream_putw_at (s, 0, stream_get_endp (s)); + /* Put length at the first point of the stream. */ + stream_putw_at(s, 0, stream_get_endp(s)); - return zclient_send_message(zclient); + return zclient_send_message(zclient); } -int -zapi_ipv6_route (u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p, - struct prefix_ipv6 *src_p, struct zapi_ipv6 *api) +int zapi_ipv6_route(u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p, + struct prefix_ipv6 *src_p, struct zapi_ipv6 *api) { - int i; - int psize; - struct stream *s; - - /* either we have !SRCPFX && src_p == NULL, or SRCPFX && src_p != NULL */ - assert (!(api->message & ZAPI_MESSAGE_SRCPFX) == !src_p); - - /* Reset stream. */ - s = zclient->obuf; - stream_reset (s); - - /* Some checks for labeled-unicast. The current expectation is that each - * nexthop is accompanied by a label in the case of labeled-unicast. - */ - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL) && - CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP)) - { - /* We expect prefixes installed with labels and the number to match - * the number of nexthops. - */ - assert (api->label_num == api->nexthop_num); - } - - zclient_create_header (s, cmd, api->vrf_id); - - /* Put type and nexthop. */ - stream_putc (s, api->type); - stream_putw (s, api->instance); - stream_putl (s, api->flags); - stream_putc (s, api->message); - stream_putw (s, api->safi); - - /* Put prefix information. */ - psize = PSIZE (p->prefixlen); - stream_putc (s, p->prefixlen); - stream_write (s, (u_char *)&p->prefix, psize); - - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_SRCPFX)) - { - psize = PSIZE (src_p->prefixlen); - stream_putc (s, src_p->prefixlen); - stream_write (s, (u_char *)&src_p->prefix, psize); - } - - /* Nexthop, ifindex, distance and metric information. */ - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP)) - { - if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE)) - { - stream_putc (s, 1); - stream_putc (s, NEXTHOP_TYPE_BLACKHOLE); - /* XXX assert(api->nexthop_num == 0); */ - /* XXX assert(api->ifindex_num == 0); */ - } - else - stream_putc (s, api->nexthop_num + api->ifindex_num); - - for (i = 0; i < api->nexthop_num; i++) - { - stream_putc (s, NEXTHOP_TYPE_IPV6); - stream_write (s, (u_char *)api->nexthop[i], 16); - /* For labeled-unicast, each nexthop is followed by label. */ - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL)) - stream_putl (s, api->label[i]); + int i; + int psize; + struct stream *s; + + /* either we have !SRCPFX && src_p == NULL, or SRCPFX && src_p != NULL + */ + assert(!(api->message & ZAPI_MESSAGE_SRCPFX) == !src_p); + + /* Reset stream. */ + s = zclient->obuf; + stream_reset(s); + + /* Some checks for labeled-unicast. The current expectation is that each + * nexthop is accompanied by a label in the case of labeled-unicast. + */ + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL) + && CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { + /* We expect prefixes installed with labels and the number to + * match + * the number of nexthops. + */ + assert(api->label_num == api->nexthop_num); } - for (i = 0; i < api->ifindex_num; i++) - { - stream_putc (s, NEXTHOP_TYPE_IFINDEX); - stream_putl (s, api->ifindex[i]); + + zclient_create_header(s, cmd, api->vrf_id); + + /* Put type and nexthop. */ + stream_putc(s, api->type); + stream_putw(s, api->instance); + stream_putl(s, api->flags); + stream_putc(s, api->message); + stream_putw(s, api->safi); + + /* Put prefix information. */ + psize = PSIZE(p->prefixlen); + stream_putc(s, p->prefixlen); + stream_write(s, (u_char *)&p->prefix, psize); + + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) { + psize = PSIZE(src_p->prefixlen); + stream_putc(s, src_p->prefixlen); + stream_write(s, (u_char *)&src_p->prefix, psize); } - } - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_DISTANCE)) - stream_putc (s, api->distance); - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC)) - stream_putl (s, api->metric); - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_TAG)) - stream_putl (s, api->tag); - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_MTU)) - stream_putl (s, api->mtu); + /* Nexthop, ifindex, distance and metric information. */ + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { + if (CHECK_FLAG(api->flags, ZEBRA_FLAG_BLACKHOLE)) { + stream_putc(s, 1); + stream_putc(s, NEXTHOP_TYPE_BLACKHOLE); + /* XXX assert(api->nexthop_num == 0); */ + /* XXX assert(api->ifindex_num == 0); */ + } else + stream_putc(s, api->nexthop_num + api->ifindex_num); + + for (i = 0; i < api->nexthop_num; i++) { + stream_putc(s, NEXTHOP_TYPE_IPV6); + stream_write(s, (u_char *)api->nexthop[i], 16); + /* For labeled-unicast, each nexthop is followed by + * label. */ + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)) + stream_putl(s, api->label[i]); + } + for (i = 0; i < api->ifindex_num; i++) { + stream_putc(s, NEXTHOP_TYPE_IFINDEX); + stream_putl(s, api->ifindex[i]); + } + } - /* Put length at the first point of the stream. */ - stream_putw_at (s, 0, stream_get_endp (s)); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE)) + stream_putc(s, api->distance); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC)) + stream_putl(s, api->metric); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG)) + stream_putl(s, api->tag); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU)) + stream_putl(s, api->mtu); - return zclient_send_message(zclient); + /* Put length at the first point of the stream. */ + stream_putw_at(s, 0, stream_get_endp(s)); + + return zclient_send_message(zclient); } -int -zapi_route (u_char cmd, struct zclient *zclient, struct prefix *p, - struct prefix_ipv6 *src_p, struct zapi_route *api) +int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p, + struct prefix_ipv6 *src_p, struct zapi_route *api) { - int i; - int psize; - struct stream *s; - - /* either we have !SRCPFX && src_p == NULL, or SRCPFX && src_p != NULL */ - assert (!(api->message & ZAPI_MESSAGE_SRCPFX) == !src_p); - - /* Reset stream. */ - s = zclient->obuf; - stream_reset (s); - - zclient_create_header (s, cmd, api->vrf_id); - - /* Put type and nexthop. */ - stream_putc (s, api->type); - stream_putw (s, api->instance); - stream_putl (s, api->flags); - stream_putc (s, api->message); - stream_putw (s, api->safi); - - /* Put prefix information. */ - psize = PSIZE (p->prefixlen); - stream_putc (s, p->prefixlen); - stream_write (s, (u_char *)&p->u.prefix, psize); - - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_SRCPFX)) - { - psize = PSIZE (src_p->prefixlen); - stream_putc (s, src_p->prefixlen); - stream_write (s, (u_char *)&src_p->prefix, psize); - } - - /* Nexthop, ifindex, distance and metric information. */ - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP)) - { - stream_putc (s, api->nexthop_num); - - for (i = 0; i < api->nexthop_num; i++) - { - stream_putc (s, api->nexthop[i]->type); - switch (api->nexthop[i]->type) - { - case NEXTHOP_TYPE_BLACKHOLE: - break; - case NEXTHOP_TYPE_IPV4: - stream_put_in_addr (s, &api->nexthop[i]->gate.ipv4); - - /* For labeled-unicast, each nexthop is followed by label. */ - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL)) - stream_putl (s, api->nexthop[i]->nh_label->label[0]); - break; - case NEXTHOP_TYPE_IPV4_IFINDEX: - stream_put_in_addr (s, &api->nexthop[i]->gate.ipv4); - stream_putl (s, api->nexthop[i]->ifindex); - break; - case NEXTHOP_TYPE_IFINDEX: - stream_putl (s, api->nexthop[i]->ifindex); - break; - case NEXTHOP_TYPE_IPV6: - stream_write (s, (u_char *)&api->nexthop[i]->gate.ipv6, 16); - - /* For labeled-unicast, each nexthop is followed by label. */ - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL)) - stream_putl (s, api->nexthop[i]->nh_label->label[0]); - break; - case NEXTHOP_TYPE_IPV6_IFINDEX: - stream_write (s, (u_char *)&api->nexthop[i]->gate.ipv6, 16); - stream_putl (s, api->nexthop[i]->ifindex); - break; - } - } - } - - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_DISTANCE)) - stream_putc (s, api->distance); - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC)) - stream_putl (s, api->metric); - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_TAG)) - stream_putl (s, api->tag); - if (CHECK_FLAG (api->message, ZAPI_MESSAGE_MTU)) - stream_putl (s, api->mtu); - - /* Put length at the first point of the stream. */ - stream_putw_at (s, 0, stream_get_endp (s)); - - return zclient_send_message(zclient); + int i; + int psize; + struct stream *s; + + /* either we have !SRCPFX && src_p == NULL, or SRCPFX && src_p != NULL + */ + assert(!(api->message & ZAPI_MESSAGE_SRCPFX) == !src_p); + + /* Reset stream. */ + s = zclient->obuf; + stream_reset(s); + + zclient_create_header(s, cmd, api->vrf_id); + + /* Put type and nexthop. */ + stream_putc(s, api->type); + stream_putw(s, api->instance); + stream_putl(s, api->flags); + stream_putc(s, api->message); + stream_putw(s, api->safi); + + /* Put prefix information. */ + psize = PSIZE(p->prefixlen); + stream_putc(s, p->prefixlen); + stream_write(s, (u_char *)&p->u.prefix, psize); + + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) { + psize = PSIZE(src_p->prefixlen); + stream_putc(s, src_p->prefixlen); + stream_write(s, (u_char *)&src_p->prefix, psize); + } + + /* Nexthop, ifindex, distance and metric information. */ + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { + stream_putc(s, api->nexthop_num); + + for (i = 0; i < api->nexthop_num; i++) { + stream_putc(s, api->nexthop[i]->type); + switch (api->nexthop[i]->type) { + case NEXTHOP_TYPE_BLACKHOLE: + break; + case NEXTHOP_TYPE_IPV4: + stream_put_in_addr(s, + &api->nexthop[i]->gate.ipv4); + + /* For labeled-unicast, each nexthop is followed + * by label. */ + if (CHECK_FLAG(api->message, + ZAPI_MESSAGE_LABEL)) + stream_putl( + s, + api->nexthop[i] + ->nh_label->label[0]); + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + stream_put_in_addr(s, + &api->nexthop[i]->gate.ipv4); + stream_putl(s, api->nexthop[i]->ifindex); + break; + case NEXTHOP_TYPE_IFINDEX: + stream_putl(s, api->nexthop[i]->ifindex); + break; + case NEXTHOP_TYPE_IPV6: + stream_write( + s, + (u_char *)&api->nexthop[i]->gate.ipv6, + 16); + + /* For labeled-unicast, each nexthop is followed + * by label. */ + if (CHECK_FLAG(api->message, + ZAPI_MESSAGE_LABEL)) + stream_putl( + s, + api->nexthop[i] + ->nh_label->label[0]); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + stream_write( + s, + (u_char *)&api->nexthop[i]->gate.ipv6, + 16); + stream_putl(s, api->nexthop[i]->ifindex); + break; + } + } + } + + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE)) + stream_putc(s, api->distance); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC)) + stream_putl(s, api->metric); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG)) + stream_putl(s, api->tag); + if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU)) + stream_putl(s, api->mtu); + + /* Put length at the first point of the stream. */ + stream_putw_at(s, 0, stream_get_endp(s)); + + return zclient_send_message(zclient); } -/* +/* * send a ZEBRA_REDISTRIBUTE_ADD or ZEBRA_REDISTRIBUTE_DELETE * for the route type (ZEBRA_ROUTE_KERNEL etc.). The zebra server will - * then set/unset redist[type] in the client handle (a struct zserv) for the + * then set/unset redist[type] in the client handle (a struct zserv) for the * sending client */ -int -zebra_redistribute_send (int command, struct zclient *zclient, afi_t afi, int type, - u_short instance, vrf_id_t vrf_id) +int zebra_redistribute_send(int command, struct zclient *zclient, afi_t afi, + int type, u_short instance, vrf_id_t vrf_id) { - struct stream *s; - - s = zclient->obuf; - stream_reset(s); - - zclient_create_header (s, command, vrf_id); - stream_putc (s, afi); - stream_putc (s, type); - stream_putw (s, instance); - - stream_putw_at (s, 0, stream_get_endp (s)); - - return zclient_send_message(zclient); + struct stream *s; + + s = zclient->obuf; + stream_reset(s); + + zclient_create_header(s, command, vrf_id); + stream_putc(s, afi); + stream_putc(s, type); + stream_putw(s, instance); + + stream_putw_at(s, 0, stream_get_endp(s)); + + return zclient_send_message(zclient); } /* Get prefix in ZServ format; family should be filled in on prefix */ -static void -zclient_stream_get_prefix (struct stream *s, struct prefix *p) +static void zclient_stream_get_prefix(struct stream *s, struct prefix *p) { - size_t plen = prefix_blen (p); - u_char c; - p->prefixlen = 0; - - if (plen == 0) - return; - - stream_get (&p->u.prefix, s, plen); - c = stream_getc(s); - p->prefixlen = MIN(plen * 8, c); + size_t plen = prefix_blen(p); + u_char c; + p->prefixlen = 0; + + if (plen == 0) + return; + + stream_get(&p->u.prefix, s, plen); + c = stream_getc(s); + p->prefixlen = MIN(plen * 8, c); } /* Router-id update from zebra daemon. */ -void -zebra_router_id_update_read (struct stream *s, struct prefix *rid) +void zebra_router_id_update_read(struct stream *s, struct prefix *rid) { - /* Fetch interface address. */ - rid->family = stream_getc (s); - - zclient_stream_get_prefix (s, rid); + /* Fetch interface address. */ + rid->family = stream_getc(s); + + zclient_stream_get_prefix(s, rid); } /* Interface addition from zebra daemon. */ -/* +/* * The format of the message sent with type ZEBRA_INTERFACE_ADD or * ZEBRA_INTERFACE_DELETE from zebra to the client is: * 0 1 2 3 @@ -1164,228 +1165,218 @@ zebra_router_id_update_read (struct stream *s, struct prefix *rid) * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -static void -zclient_vrf_add (struct zclient *zclient, vrf_id_t vrf_id) +static void zclient_vrf_add(struct zclient *zclient, vrf_id_t vrf_id) { - struct vrf *vrf; - char vrfname_tmp[VRF_NAMSIZ]; - struct vrf_data data; + struct vrf *vrf; + char vrfname_tmp[VRF_NAMSIZ]; + struct vrf_data data; - stream_get (&data, zclient->ibuf, sizeof (struct vrf_data)); - /* Read interface name. */ - stream_get (vrfname_tmp, zclient->ibuf, VRF_NAMSIZ); + stream_get(&data, zclient->ibuf, sizeof(struct vrf_data)); + /* Read interface name. */ + stream_get(vrfname_tmp, zclient->ibuf, VRF_NAMSIZ); - /* Lookup/create vrf by vrf_id. */ - vrf = vrf_get (vrf_id, vrfname_tmp); - vrf->data = data; + /* Lookup/create vrf by vrf_id. */ + vrf = vrf_get(vrf_id, vrfname_tmp); + vrf->data = data; - vrf_enable (vrf); + vrf_enable(vrf); } -static void -zclient_vrf_delete (struct zclient *zclient, vrf_id_t vrf_id) +static void zclient_vrf_delete(struct zclient *zclient, vrf_id_t vrf_id) { - struct vrf *vrf; + struct vrf *vrf; - /* Lookup vrf by vrf_id. */ - vrf = vrf_lookup_by_id (vrf_id); + /* Lookup vrf by vrf_id. */ + vrf = vrf_lookup_by_id(vrf_id); - /* - * If a routing protocol doesn't know about a - * vrf that is about to be deleted. There is - * no point in attempting to delete it. - */ - if (!vrf) - return; + /* + * If a routing protocol doesn't know about a + * vrf that is about to be deleted. There is + * no point in attempting to delete it. + */ + if (!vrf) + return; - vrf_delete (vrf); + vrf_delete(vrf); } -struct interface * -zebra_interface_add_read (struct stream *s, vrf_id_t vrf_id) +struct interface *zebra_interface_add_read(struct stream *s, vrf_id_t vrf_id) { - struct interface *ifp; - char ifname_tmp[INTERFACE_NAMSIZ]; + struct interface *ifp; + char ifname_tmp[INTERFACE_NAMSIZ]; - /* Read interface name. */ - stream_get (ifname_tmp, s, INTERFACE_NAMSIZ); + /* Read interface name. */ + stream_get(ifname_tmp, s, INTERFACE_NAMSIZ); - /* Lookup/create interface by name. */ - ifp = if_get_by_name_len (ifname_tmp, - strnlen (ifname_tmp, INTERFACE_NAMSIZ), - vrf_id, 0); + /* Lookup/create interface by name. */ + ifp = if_get_by_name_len( + ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ), vrf_id, 0); - zebra_interface_if_set_value (s, ifp); + zebra_interface_if_set_value(s, ifp); - return ifp; + return ifp; } -/* +/* * Read interface up/down msg (ZEBRA_INTERFACE_UP/ZEBRA_INTERFACE_DOWN) * from zebra server. The format of this message is the same as * that sent for ZEBRA_INTERFACE_ADD/ZEBRA_INTERFACE_DELETE (see * comments for zebra_interface_add_read), except that no sockaddr_dl * is sent at the tail of the message. */ -struct interface * -zebra_interface_state_read (struct stream *s, vrf_id_t vrf_id) +struct interface *zebra_interface_state_read(struct stream *s, vrf_id_t vrf_id) { - struct interface *ifp; - char ifname_tmp[INTERFACE_NAMSIZ]; - - /* Read interface name. */ - stream_get (ifname_tmp, s, INTERFACE_NAMSIZ); - - /* Lookup this by interface index. */ - ifp = if_lookup_by_name_len (ifname_tmp, - strnlen (ifname_tmp, INTERFACE_NAMSIZ), - vrf_id); - if (ifp == NULL) - { - zlog_warn ("INTERFACE_STATE: Cannot find IF %s in VRF %d", - ifname_tmp, vrf_id); - return NULL; - } - - zebra_interface_if_set_value (s, ifp); - - return ifp; + struct interface *ifp; + char ifname_tmp[INTERFACE_NAMSIZ]; + + /* Read interface name. */ + stream_get(ifname_tmp, s, INTERFACE_NAMSIZ); + + /* Lookup this by interface index. */ + ifp = if_lookup_by_name_len( + ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ), vrf_id); + if (ifp == NULL) { + zlog_warn("INTERFACE_STATE: Cannot find IF %s in VRF %d", + ifname_tmp, vrf_id); + return NULL; + } + + zebra_interface_if_set_value(s, ifp); + + return ifp; } -static void -link_params_set_value(struct stream *s, struct if_link_params *iflp) +static void link_params_set_value(struct stream *s, struct if_link_params *iflp) { - if (iflp == NULL) - return; - - iflp->lp_status = stream_getl (s); - iflp->te_metric = stream_getl (s); - iflp->max_bw = stream_getf (s); - iflp->max_rsv_bw = stream_getf (s); - uint32_t bwclassnum = stream_getl (s); - { - unsigned int i; - for (i = 0; i < bwclassnum && i < MAX_CLASS_TYPE; i++) - iflp->unrsv_bw[i] = stream_getf (s); - if (i < bwclassnum) - zlog_err ("%s: received %d > %d (MAX_CLASS_TYPE) bw entries" - " - outdated library?", - __func__, bwclassnum, MAX_CLASS_TYPE); - } - iflp->admin_grp = stream_getl (s); - iflp->rmt_as = stream_getl (s); - iflp->rmt_ip.s_addr = stream_get_ipv4 (s); - - iflp->av_delay = stream_getl (s); - iflp->min_delay = stream_getl (s); - iflp->max_delay = stream_getl (s); - iflp->delay_var = stream_getl (s); - - iflp->pkt_loss = stream_getf (s); - iflp->res_bw = stream_getf (s); - iflp->ava_bw = stream_getf (s); - iflp->use_bw = stream_getf (s); + if (iflp == NULL) + return; + + iflp->lp_status = stream_getl(s); + iflp->te_metric = stream_getl(s); + iflp->max_bw = stream_getf(s); + iflp->max_rsv_bw = stream_getf(s); + uint32_t bwclassnum = stream_getl(s); + { + unsigned int i; + for (i = 0; i < bwclassnum && i < MAX_CLASS_TYPE; i++) + iflp->unrsv_bw[i] = stream_getf(s); + if (i < bwclassnum) + zlog_err( + "%s: received %d > %d (MAX_CLASS_TYPE) bw entries" + " - outdated library?", + __func__, bwclassnum, MAX_CLASS_TYPE); + } + iflp->admin_grp = stream_getl(s); + iflp->rmt_as = stream_getl(s); + iflp->rmt_ip.s_addr = stream_get_ipv4(s); + + iflp->av_delay = stream_getl(s); + iflp->min_delay = stream_getl(s); + iflp->max_delay = stream_getl(s); + iflp->delay_var = stream_getl(s); + + iflp->pkt_loss = stream_getf(s); + iflp->res_bw = stream_getf(s); + iflp->ava_bw = stream_getf(s); + iflp->use_bw = stream_getf(s); } -struct interface * -zebra_interface_link_params_read (struct stream *s) +struct interface *zebra_interface_link_params_read(struct stream *s) { - struct if_link_params *iflp; - ifindex_t ifindex; + struct if_link_params *iflp; + ifindex_t ifindex; - assert (s); + assert(s); - ifindex = stream_getl (s); + ifindex = stream_getl(s); - struct interface *ifp = if_lookup_by_index (ifindex, VRF_DEFAULT); + struct interface *ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); - if (ifp == NULL) - { - zlog_err ("%s: unknown ifindex %u, shouldn't happen", - __func__, ifindex); - return NULL; - } + if (ifp == NULL) { + zlog_err("%s: unknown ifindex %u, shouldn't happen", __func__, + ifindex); + return NULL; + } - if ((iflp = if_link_params_get (ifp)) == NULL) - return NULL; + if ((iflp = if_link_params_get(ifp)) == NULL) + return NULL; - link_params_set_value(s, iflp); + link_params_set_value(s, iflp); - return ifp; + return ifp; } -void -zebra_interface_if_set_value (struct stream *s, struct interface *ifp) +void zebra_interface_if_set_value(struct stream *s, struct interface *ifp) { - u_char link_params_status = 0; - - /* Read interface's index. */ - ifp->ifindex = stream_getl (s); - ifp->status = stream_getc (s); - - /* Read interface's value. */ - ifp->flags = stream_getq (s); - ifp->ptm_enable = stream_getc (s); - ifp->ptm_status = stream_getc (s); - ifp->metric = stream_getl (s); - ifp->speed = stream_getl (s); - ifp->mtu = stream_getl (s); - ifp->mtu6 = stream_getl (s); - ifp->bandwidth = stream_getl (s); - ifp->ll_type = stream_getl (s); - ifp->hw_addr_len = stream_getl (s); - if (ifp->hw_addr_len) - stream_get (ifp->hw_addr, s, MIN(ifp->hw_addr_len, INTERFACE_HWADDR_MAX)); - - /* Read Traffic Engineering status */ - link_params_status = stream_getc (s); - /* Then, Traffic Engineering parameters if any */ - if (link_params_status) - { - struct if_link_params *iflp = if_link_params_get (ifp); - link_params_set_value(s, iflp); - } + u_char link_params_status = 0; + + /* Read interface's index. */ + ifp->ifindex = stream_getl(s); + ifp->status = stream_getc(s); + + /* Read interface's value. */ + ifp->flags = stream_getq(s); + ifp->ptm_enable = stream_getc(s); + ifp->ptm_status = stream_getc(s); + ifp->metric = stream_getl(s); + ifp->speed = stream_getl(s); + ifp->mtu = stream_getl(s); + ifp->mtu6 = stream_getl(s); + ifp->bandwidth = stream_getl(s); + ifp->ll_type = stream_getl(s); + ifp->hw_addr_len = stream_getl(s); + if (ifp->hw_addr_len) + stream_get(ifp->hw_addr, s, + MIN(ifp->hw_addr_len, INTERFACE_HWADDR_MAX)); + + /* Read Traffic Engineering status */ + link_params_status = stream_getc(s); + /* Then, Traffic Engineering parameters if any */ + if (link_params_status) { + struct if_link_params *iflp = if_link_params_get(ifp); + link_params_set_value(s, iflp); + } } -size_t -zebra_interface_link_params_write (struct stream *s, struct interface *ifp) +size_t zebra_interface_link_params_write(struct stream *s, + struct interface *ifp) { - size_t w; - struct if_link_params *iflp; - int i; + size_t w; + struct if_link_params *iflp; + int i; - if (s == NULL || ifp == NULL || ifp->link_params == NULL) - return 0; + if (s == NULL || ifp == NULL || ifp->link_params == NULL) + return 0; - iflp = ifp->link_params; - w = 0; + iflp = ifp->link_params; + w = 0; - w += stream_putl (s, iflp->lp_status); + w += stream_putl(s, iflp->lp_status); - w += stream_putl (s, iflp->te_metric); - w += stream_putf (s, iflp->max_bw); - w += stream_putf (s, iflp->max_rsv_bw); + w += stream_putl(s, iflp->te_metric); + w += stream_putf(s, iflp->max_bw); + w += stream_putf(s, iflp->max_rsv_bw); - w += stream_putl (s, MAX_CLASS_TYPE); - for (i = 0; i < MAX_CLASS_TYPE; i++) - w += stream_putf (s, iflp->unrsv_bw[i]); + w += stream_putl(s, MAX_CLASS_TYPE); + for (i = 0; i < MAX_CLASS_TYPE; i++) + w += stream_putf(s, iflp->unrsv_bw[i]); - w += stream_putl (s, iflp->admin_grp); - w += stream_putl (s, iflp->rmt_as); - w += stream_put_in_addr (s, &iflp->rmt_ip); + w += stream_putl(s, iflp->admin_grp); + w += stream_putl(s, iflp->rmt_as); + w += stream_put_in_addr(s, &iflp->rmt_ip); - w += stream_putl (s, iflp->av_delay); - w += stream_putl (s, iflp->min_delay); - w += stream_putl (s, iflp->max_delay); - w += stream_putl (s, iflp->delay_var); + w += stream_putl(s, iflp->av_delay); + w += stream_putl(s, iflp->min_delay); + w += stream_putl(s, iflp->max_delay); + w += stream_putl(s, iflp->delay_var); - w += stream_putf (s, iflp->pkt_loss); - w += stream_putf (s, iflp->res_bw); - w += stream_putf (s, iflp->ava_bw); - w += stream_putf (s, iflp->use_bw); + w += stream_putf(s, iflp->pkt_loss); + w += stream_putf(s, iflp->res_bw); + w += stream_putf(s, iflp->ava_bw); + w += stream_putf(s, iflp->use_bw); - return w; + return w; } /* @@ -1419,91 +1410,87 @@ zebra_interface_link_params_write (struct stream *s, struct interface *ifp) * +-+-+-+-+-+-+-+-+ */ -static int -memconstant(const void *s, int c, size_t n) +static int memconstant(const void *s, int c, size_t n) { - const u_char *p = s; + const u_char *p = s; - while (n-- > 0) - if (*p++ != c) - return 0; - return 1; + while (n-- > 0) + if (*p++ != c) + return 0; + return 1; } -struct connected * -zebra_interface_address_read (int type, struct stream *s, vrf_id_t vrf_id) +struct connected *zebra_interface_address_read(int type, struct stream *s, + vrf_id_t vrf_id) { - ifindex_t ifindex; - struct interface *ifp; - struct connected *ifc; - struct prefix p, d, *dp; - int plen; - u_char ifc_flags; - - memset (&p, 0, sizeof(p)); - memset (&d, 0, sizeof(d)); - - /* Get interface index. */ - ifindex = stream_getl (s); - - /* Lookup index. */ - ifp = if_lookup_by_index (ifindex, vrf_id); - if (ifp == NULL) - { - zlog_warn ("INTERFACE_ADDRESS_%s: Cannot find IF %u in VRF %d", - (type == ZEBRA_INTERFACE_ADDRESS_ADD) ? "ADD" : "DEL", - ifindex, vrf_id); - return NULL; - } - - /* Fetch flag. */ - ifc_flags = stream_getc (s); - - /* Fetch interface address. */ - d.family = p.family = stream_getc (s); - plen = prefix_blen (&d); - - zclient_stream_get_prefix (s, &p); - - /* Fetch destination address. */ - stream_get (&d.u.prefix, s, plen); - - /* N.B. NULL destination pointers are encoded as all zeroes */ - dp = memconstant(&d.u.prefix,0,plen) ? NULL : &d; - - if (type == ZEBRA_INTERFACE_ADDRESS_ADD) - { - ifc = connected_lookup_prefix_exact (ifp, &p); - if (!ifc) - { - /* N.B. NULL destination pointers are encoded as all zeroes */ - ifc = connected_add_by_prefix(ifp, &p, dp); - } - if (ifc) - { - ifc->flags = ifc_flags; - if (ifc->destination) - ifc->destination->prefixlen = ifc->address->prefixlen; - else if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) - { - /* carp interfaces on OpenBSD with 0.0.0.0/0 as "peer" */ - char buf[PREFIX_STRLEN]; - zlog_warn("warning: interface %s address %s " - "with peer flag set, but no peer address!", - ifp->name, - prefix2str (ifc->address, buf, sizeof buf)); - UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER); - } - } - } - else - { - assert (type == ZEBRA_INTERFACE_ADDRESS_DELETE); - ifc = connected_delete_by_prefix(ifp, &p); - } - - return ifc; + ifindex_t ifindex; + struct interface *ifp; + struct connected *ifc; + struct prefix p, d, *dp; + int plen; + u_char ifc_flags; + + memset(&p, 0, sizeof(p)); + memset(&d, 0, sizeof(d)); + + /* Get interface index. */ + ifindex = stream_getl(s); + + /* Lookup index. */ + ifp = if_lookup_by_index(ifindex, vrf_id); + if (ifp == NULL) { + zlog_warn("INTERFACE_ADDRESS_%s: Cannot find IF %u in VRF %d", + (type == ZEBRA_INTERFACE_ADDRESS_ADD) ? "ADD" : "DEL", + ifindex, vrf_id); + return NULL; + } + + /* Fetch flag. */ + ifc_flags = stream_getc(s); + + /* Fetch interface address. */ + d.family = p.family = stream_getc(s); + plen = prefix_blen(&d); + + zclient_stream_get_prefix(s, &p); + + /* Fetch destination address. */ + stream_get(&d.u.prefix, s, plen); + + /* N.B. NULL destination pointers are encoded as all zeroes */ + dp = memconstant(&d.u.prefix, 0, plen) ? NULL : &d; + + if (type == ZEBRA_INTERFACE_ADDRESS_ADD) { + ifc = connected_lookup_prefix_exact(ifp, &p); + if (!ifc) { + /* N.B. NULL destination pointers are encoded as all + * zeroes */ + ifc = connected_add_by_prefix(ifp, &p, dp); + } + if (ifc) { + ifc->flags = ifc_flags; + if (ifc->destination) + ifc->destination->prefixlen = + ifc->address->prefixlen; + else if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) { + /* carp interfaces on OpenBSD with 0.0.0.0/0 as + * "peer" */ + char buf[PREFIX_STRLEN]; + zlog_warn( + "warning: interface %s address %s " + "with peer flag set, but no peer address!", + ifp->name, prefix2str(ifc->address, buf, + sizeof buf)); + UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER); + } + } + } else { + assert(type == ZEBRA_INTERFACE_ADDRESS_DELETE); + ifc = connected_delete_by_prefix(ifp, &p); + } + + return ifc; } /* @@ -1531,122 +1518,118 @@ zebra_interface_address_read (int type, struct stream *s, vrf_id_t vrf_id) * +-+-+-+-+-+-+-+-+ */ struct nbr_connected * -zebra_interface_nbr_address_read (int type, struct stream *s, vrf_id_t vrf_id) +zebra_interface_nbr_address_read(int type, struct stream *s, vrf_id_t vrf_id) { - unsigned int ifindex; - struct interface *ifp; - struct prefix p; - struct nbr_connected *ifc; - - /* Get interface index. */ - ifindex = stream_getl (s); - - /* Lookup index. */ - ifp = if_lookup_by_index (ifindex, vrf_id); - if (ifp == NULL) - { - zlog_warn ("INTERFACE_NBR_%s: Cannot find IF %u in VRF %d", - (type == ZEBRA_INTERFACE_NBR_ADDRESS_ADD) ? "ADD" : "DELETE", - ifindex, vrf_id); - return NULL; - } - - p.family = stream_getc (s); - stream_get (&p.u.prefix, s, prefix_blen (&p)); - p.prefixlen = stream_getc (s); - - if (type == ZEBRA_INTERFACE_NBR_ADDRESS_ADD) - { - /* Currently only supporting P2P links, so any new RA source address is - considered as the replacement of the previously learnt Link-Local address. */ - if (!(ifc = listnode_head(ifp->nbr_connected))) - { - ifc = nbr_connected_new (); - ifc->address = prefix_new (); - ifc->ifp = ifp; - listnode_add (ifp->nbr_connected, ifc); - } - - prefix_copy(ifc->address, &p); - } - else - { - assert (type == ZEBRA_INTERFACE_NBR_ADDRESS_DELETE); - - ifc = nbr_connected_check(ifp, &p); - if (ifc) - listnode_delete (ifp->nbr_connected, ifc); - } - - return ifc; + unsigned int ifindex; + struct interface *ifp; + struct prefix p; + struct nbr_connected *ifc; + + /* Get interface index. */ + ifindex = stream_getl(s); + + /* Lookup index. */ + ifp = if_lookup_by_index(ifindex, vrf_id); + if (ifp == NULL) { + zlog_warn("INTERFACE_NBR_%s: Cannot find IF %u in VRF %d", + (type == ZEBRA_INTERFACE_NBR_ADDRESS_ADD) ? "ADD" + : "DELETE", + ifindex, vrf_id); + return NULL; + } + + p.family = stream_getc(s); + stream_get(&p.u.prefix, s, prefix_blen(&p)); + p.prefixlen = stream_getc(s); + + if (type == ZEBRA_INTERFACE_NBR_ADDRESS_ADD) { + /* Currently only supporting P2P links, so any new RA source + address is + considered as the replacement of the previously learnt + Link-Local address. */ + if (!(ifc = listnode_head(ifp->nbr_connected))) { + ifc = nbr_connected_new(); + ifc->address = prefix_new(); + ifc->ifp = ifp; + listnode_add(ifp->nbr_connected, ifc); + } + + prefix_copy(ifc->address, &p); + } else { + assert(type == ZEBRA_INTERFACE_NBR_ADDRESS_DELETE); + + ifc = nbr_connected_check(ifp, &p); + if (ifc) + listnode_delete(ifp->nbr_connected, ifc); + } + + return ifc; } -struct interface * -zebra_interface_vrf_update_read (struct stream *s, vrf_id_t vrf_id, - vrf_id_t *new_vrf_id) +struct interface *zebra_interface_vrf_update_read(struct stream *s, + vrf_id_t vrf_id, + vrf_id_t *new_vrf_id) { - unsigned int ifindex; - struct interface *ifp; - vrf_id_t new_id = VRF_DEFAULT; - - /* Get interface index. */ - ifindex = stream_getl (s); - - /* Lookup interface. */ - ifp = if_lookup_by_index (ifindex, vrf_id); - if (ifp == NULL) - { - zlog_warn ("INTERFACE_VRF_UPDATE: Cannot find IF %u in VRF %d", - ifindex, vrf_id); - return NULL; - } - - /* Fetch new VRF Id. */ - new_id = stream_getw (s); - - *new_vrf_id = new_id; - return ifp; + unsigned int ifindex; + struct interface *ifp; + vrf_id_t new_id = VRF_DEFAULT; + + /* Get interface index. */ + ifindex = stream_getl(s); + + /* Lookup interface. */ + ifp = if_lookup_by_index(ifindex, vrf_id); + if (ifp == NULL) { + zlog_warn("INTERFACE_VRF_UPDATE: Cannot find IF %u in VRF %d", + ifindex, vrf_id); + return NULL; + } + + /* Fetch new VRF Id. */ + new_id = stream_getw(s); + + *new_vrf_id = new_id; + return ifp; } /* filter unwanted messages until the expected one arrives */ -static int -zclient_read_sync_response (struct zclient *zclient, u_int16_t expected_cmd) +static int zclient_read_sync_response(struct zclient *zclient, + u_int16_t expected_cmd) { - struct stream *s; - u_int16_t size; - u_char marker; - u_char version; - vrf_id_t vrf_id; - u_int16_t cmd; - fd_set readfds; - int ret; - - ret = 0; - cmd = expected_cmd + 1; - while (ret == 0 && cmd != expected_cmd) - { - s = zclient->ibuf; - stream_reset (s); - - /* wait until response arrives */ - FD_ZERO (&readfds); - FD_SET (zclient->sock, &readfds); - select (zclient->sock+1, &readfds, NULL, NULL, NULL); - if (!FD_ISSET(zclient->sock, &readfds)) - continue; - /* read response */ - ret = zclient_read_header (s, zclient->sock, &size, &marker, &version, - &vrf_id, &cmd); - if (zclient_debug) - zlog_debug ("%s: Response (%d bytes) received", __func__, size); - } - if (ret != 0) - { - zlog_err ("%s: Invalid Sync Message Reply", __func__); - return -1; - } - - return 0; + struct stream *s; + u_int16_t size; + u_char marker; + u_char version; + vrf_id_t vrf_id; + u_int16_t cmd; + fd_set readfds; + int ret; + + ret = 0; + cmd = expected_cmd + 1; + while (ret == 0 && cmd != expected_cmd) { + s = zclient->ibuf; + stream_reset(s); + + /* wait until response arrives */ + FD_ZERO(&readfds); + FD_SET(zclient->sock, &readfds); + select(zclient->sock + 1, &readfds, NULL, NULL, NULL); + if (!FD_ISSET(zclient->sock, &readfds)) + continue; + /* read response */ + ret = zclient_read_header(s, zclient->sock, &size, &marker, + &version, &vrf_id, &cmd); + if (zclient_debug) + zlog_debug("%s: Response (%d bytes) received", __func__, + size); + } + if (ret != 0) { + zlog_err("%s: Invalid Sync Message Reply", __func__); + return -1; + } + + return 0; } /** * Connect to label manager in a syncronous way @@ -1657,62 +1640,62 @@ zclient_read_sync_response (struct zclient *zclient, u_int16_t expected_cmd) * @param zclient Zclient used to connect to label manager (zebra) * @result Result of response */ -int -lm_label_manager_connect (struct zclient *zclient) +int lm_label_manager_connect(struct zclient *zclient) { - int ret; - struct stream *s; - u_char result; - - if (zclient_debug) - zlog_debug ("Connecting to Label Manager"); - - if (zclient->sock < 0) - return -1; - - /* send request */ - s = zclient->obuf; - stream_reset (s); - zclient_create_header (s, ZEBRA_LABEL_MANAGER_CONNECT, VRF_DEFAULT); - - /* proto */ - stream_putc (s, zclient->redist_default); - /* instance */ - stream_putw (s, zclient->instance); - - /* Put length at the first point of the stream. */ - stream_putw_at(s, 0, stream_get_endp(s)); - - ret = writen (zclient->sock, s->data, stream_get_endp (s)); - if (ret < 0) - { - zlog_err ("%s: can't write to zclient->sock", __func__); - close (zclient->sock); - zclient->sock = -1; - return -1; - } - if (ret == 0) - { - zlog_err ("%s: zclient->sock connection closed", __func__); - close (zclient->sock); - zclient->sock = -1; - return -1; - } - if (zclient_debug) - zlog_debug ("%s: Label manager connect request (%d bytes) sent", __func__, ret); - - /* read response */ - if (zclient_read_sync_response (zclient, ZEBRA_LABEL_MANAGER_CONNECT) != 0) - return -1; - - /* result */ - s = zclient->ibuf; - result = stream_getc(s); - if (zclient_debug) - zlog_debug ("%s: Label Manager connect response received, result %u", - __func__, result); - - return (int)result; + int ret; + struct stream *s; + u_char result; + + if (zclient_debug) + zlog_debug("Connecting to Label Manager"); + + if (zclient->sock < 0) + return -1; + + /* send request */ + s = zclient->obuf; + stream_reset(s); + zclient_create_header(s, ZEBRA_LABEL_MANAGER_CONNECT, VRF_DEFAULT); + + /* proto */ + stream_putc(s, zclient->redist_default); + /* instance */ + stream_putw(s, zclient->instance); + + /* Put length at the first point of the stream. */ + stream_putw_at(s, 0, stream_get_endp(s)); + + ret = writen(zclient->sock, s->data, stream_get_endp(s)); + if (ret < 0) { + zlog_err("%s: can't write to zclient->sock", __func__); + close(zclient->sock); + zclient->sock = -1; + return -1; + } + if (ret == 0) { + zlog_err("%s: zclient->sock connection closed", __func__); + close(zclient->sock); + zclient->sock = -1; + return -1; + } + if (zclient_debug) + zlog_debug("%s: Label manager connect request (%d bytes) sent", + __func__, ret); + + /* read response */ + if (zclient_read_sync_response(zclient, ZEBRA_LABEL_MANAGER_CONNECT) + != 0) + return -1; + + /* result */ + s = zclient->ibuf; + result = stream_getc(s); + if (zclient_debug) + zlog_debug( + "%s: Label Manager connect response received, result %u", + __func__, result); + + return (int)result; } /** @@ -1728,81 +1711,77 @@ lm_label_manager_connect (struct zclient *zclient) * @param end To write last assigned chunk label to * @result 0 on success, -1 otherwise */ -int -lm_get_label_chunk (struct zclient *zclient, u_char keep, uint32_t chunk_size, - uint32_t *start, uint32_t *end) +int lm_get_label_chunk(struct zclient *zclient, u_char keep, + uint32_t chunk_size, uint32_t *start, uint32_t *end) { - int ret; - struct stream *s; - u_char response_keep; - - if (zclient_debug) - zlog_debug ("Getting Label Chunk"); - - if (zclient->sock < 0) - return -1; - - /* send request */ - s = zclient->obuf; - stream_reset (s); - zclient_create_header (s, ZEBRA_GET_LABEL_CHUNK, VRF_DEFAULT); - /* keep */ - stream_putc (s, keep); - /* chunk size */ - stream_putl (s, chunk_size); - /* Put length at the first point of the stream. */ - stream_putw_at(s, 0, stream_get_endp(s)); - - ret = writen (zclient->sock, s->data, stream_get_endp (s)); - if (ret < 0) - { - zlog_err ("%s: can't write to zclient->sock", __func__); - close (zclient->sock); - zclient->sock = -1; - return -1; - } - if (ret == 0) - { - zlog_err ("%s: zclient->sock connection closed", __func__); - close (zclient->sock); - zclient->sock = -1; - return -1; - } - if (zclient_debug) - zlog_debug ("%s: Label chunk request (%d bytes) sent", __func__, ret); - - /* read response */ - if (zclient_read_sync_response (zclient, ZEBRA_GET_LABEL_CHUNK) != 0) - return -1; - - s = zclient->ibuf; - /* keep */ - response_keep = stream_getc(s); - /* start and end labels */ - *start = stream_getl(s); - *end = stream_getl(s); - - /* not owning this response */ - if (keep != response_keep) - { - zlog_err ("%s: Invalid Label chunk: %u - %u, keeps mismatch %u != %u", - __func__, *start, *end, keep, response_keep); - } - /* sanity */ - if (*start > *end - || *start < MPLS_MIN_UNRESERVED_LABEL - || *end > MPLS_MAX_UNRESERVED_LABEL) - { - zlog_err ("%s: Invalid Label chunk: %u - %u", __func__, - *start, *end); - return -1; - } - - if (zclient_debug) - zlog_debug ("Label Chunk assign: %u - %u (%u) ", - *start, *end, response_keep); - - return 0; + int ret; + struct stream *s; + u_char response_keep; + + if (zclient_debug) + zlog_debug("Getting Label Chunk"); + + if (zclient->sock < 0) + return -1; + + /* send request */ + s = zclient->obuf; + stream_reset(s); + zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, VRF_DEFAULT); + /* keep */ + stream_putc(s, keep); + /* chunk size */ + stream_putl(s, chunk_size); + /* Put length at the first point of the stream. */ + stream_putw_at(s, 0, stream_get_endp(s)); + + ret = writen(zclient->sock, s->data, stream_get_endp(s)); + if (ret < 0) { + zlog_err("%s: can't write to zclient->sock", __func__); + close(zclient->sock); + zclient->sock = -1; + return -1; + } + if (ret == 0) { + zlog_err("%s: zclient->sock connection closed", __func__); + close(zclient->sock); + zclient->sock = -1; + return -1; + } + if (zclient_debug) + zlog_debug("%s: Label chunk request (%d bytes) sent", __func__, + ret); + + /* read response */ + if (zclient_read_sync_response(zclient, ZEBRA_GET_LABEL_CHUNK) != 0) + return -1; + + s = zclient->ibuf; + /* keep */ + response_keep = stream_getc(s); + /* start and end labels */ + *start = stream_getl(s); + *end = stream_getl(s); + + /* not owning this response */ + if (keep != response_keep) { + zlog_err( + "%s: Invalid Label chunk: %u - %u, keeps mismatch %u != %u", + __func__, *start, *end, keep, response_keep); + } + /* sanity */ + if (*start > *end || *start < MPLS_MIN_UNRESERVED_LABEL + || *end > MPLS_MAX_UNRESERVED_LABEL) { + zlog_err("%s: Invalid Label chunk: %u - %u", __func__, *start, + *end); + return -1; + } + + if (zclient_debug) + zlog_debug("Label Chunk assign: %u - %u (%u) ", *start, *end, + response_keep); + + return 0; } /** @@ -1813,383 +1792,395 @@ lm_get_label_chunk (struct zclient *zclient, u_char keep, uint32_t chunk_size, * @param end Last label of chunk * @result 0 on success, -1 otherwise */ -int -lm_release_label_chunk (struct zclient *zclient, uint32_t start, uint32_t end) +int lm_release_label_chunk(struct zclient *zclient, uint32_t start, + uint32_t end) { - int ret; - struct stream *s; - - if (zclient_debug) - zlog_debug ("Releasing Label Chunk"); - - if (zclient->sock < 0) - return -1; - - /* send request */ - s = zclient->obuf; - stream_reset (s); - zclient_create_header (s, ZEBRA_RELEASE_LABEL_CHUNK, VRF_DEFAULT); - - /* start */ - stream_putl (s, start); - /* end */ - stream_putl (s, end); - - /* Put length at the first point of the stream. */ - stream_putw_at(s, 0, stream_get_endp(s)); - - ret = writen (zclient->sock, s->data, stream_get_endp (s)); - if (ret < 0) - { - zlog_err ("%s: can't write to zclient->sock", __func__); - close (zclient->sock); - zclient->sock = -1; - return -1; - } - if (ret == 0) - { - zlog_err ("%s: zclient->sock connection closed", __func__); - close (zclient->sock); - zclient->sock = -1; - return -1; - } - - return 0; + int ret; + struct stream *s; + + if (zclient_debug) + zlog_debug("Releasing Label Chunk"); + + if (zclient->sock < 0) + return -1; + + /* send request */ + s = zclient->obuf; + stream_reset(s); + zclient_create_header(s, ZEBRA_RELEASE_LABEL_CHUNK, VRF_DEFAULT); + + /* start */ + stream_putl(s, start); + /* end */ + stream_putl(s, end); + + /* Put length at the first point of the stream. */ + stream_putw_at(s, 0, stream_get_endp(s)); + + ret = writen(zclient->sock, s->data, stream_get_endp(s)); + if (ret < 0) { + zlog_err("%s: can't write to zclient->sock", __func__); + close(zclient->sock); + zclient->sock = -1; + return -1; + } + if (ret == 0) { + zlog_err("%s: zclient->sock connection closed", __func__); + close(zclient->sock); + zclient->sock = -1; + return -1; + } + + return 0; } /* Zebra client message read function. */ -static int -zclient_read (struct thread *thread) +static int zclient_read(struct thread *thread) { - size_t already; - uint16_t length, command; - uint8_t marker, version; - vrf_id_t vrf_id; - struct zclient *zclient; - - /* Get socket to zebra. */ - zclient = THREAD_ARG (thread); - zclient->t_read = NULL; - - /* Read zebra header (if we don't have it already). */ - if ((already = stream_get_endp(zclient->ibuf)) < ZEBRA_HEADER_SIZE) - { - ssize_t nbyte; - if (((nbyte = stream_read_try(zclient->ibuf, zclient->sock, - ZEBRA_HEADER_SIZE-already)) == 0) || - (nbyte == -1)) - { - if (zclient_debug) - zlog_debug ("zclient connection closed socket [%d].", zclient->sock); - return zclient_failed(zclient); + size_t already; + uint16_t length, command; + uint8_t marker, version; + vrf_id_t vrf_id; + struct zclient *zclient; + + /* Get socket to zebra. */ + zclient = THREAD_ARG(thread); + zclient->t_read = NULL; + + /* Read zebra header (if we don't have it already). */ + if ((already = stream_get_endp(zclient->ibuf)) < ZEBRA_HEADER_SIZE) { + ssize_t nbyte; + if (((nbyte = stream_read_try(zclient->ibuf, zclient->sock, + ZEBRA_HEADER_SIZE - already)) + == 0) + || (nbyte == -1)) { + if (zclient_debug) + zlog_debug( + "zclient connection closed socket [%d].", + zclient->sock); + return zclient_failed(zclient); + } + if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE - already)) { + /* Try again later. */ + zclient_event(ZCLIENT_READ, zclient); + return 0; + } + already = ZEBRA_HEADER_SIZE; } - if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE-already)) - { - /* Try again later. */ - zclient_event (ZCLIENT_READ, zclient); - return 0; + + /* Reset to read from the beginning of the incoming packet. */ + stream_set_getp(zclient->ibuf, 0); + + /* Fetch header values. */ + length = stream_getw(zclient->ibuf); + marker = stream_getc(zclient->ibuf); + version = stream_getc(zclient->ibuf); + vrf_id = stream_getw(zclient->ibuf); + command = stream_getw(zclient->ibuf); + + if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) { + zlog_err( + "%s: socket %d version mismatch, marker %d, version %d", + __func__, zclient->sock, marker, version); + return zclient_failed(zclient); } - already = ZEBRA_HEADER_SIZE; - } - - /* Reset to read from the beginning of the incoming packet. */ - stream_set_getp(zclient->ibuf, 0); - - /* Fetch header values. */ - length = stream_getw (zclient->ibuf); - marker = stream_getc (zclient->ibuf); - version = stream_getc (zclient->ibuf); - vrf_id = stream_getw (zclient->ibuf); - command = stream_getw (zclient->ibuf); - - if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) - { - zlog_err("%s: socket %d version mismatch, marker %d, version %d", - __func__, zclient->sock, marker, version); - return zclient_failed(zclient); - } - - if (length < ZEBRA_HEADER_SIZE) - { - zlog_err("%s: socket %d message length %u is less than %d ", - __func__, zclient->sock, length, ZEBRA_HEADER_SIZE); - return zclient_failed(zclient); - } - - /* Length check. */ - if (length > STREAM_SIZE(zclient->ibuf)) - { - struct stream *ns; - zlog_warn("%s: message size %u exceeds buffer size %lu, expanding...", - __func__, length, (u_long)STREAM_SIZE(zclient->ibuf)); - ns = stream_new(length); - stream_copy(ns, zclient->ibuf); - stream_free (zclient->ibuf); - zclient->ibuf = ns; - } - - /* Read rest of zebra packet. */ - if (already < length) - { - ssize_t nbyte; - if (((nbyte = stream_read_try(zclient->ibuf, zclient->sock, - length-already)) == 0) || - (nbyte == -1)) - { - if (zclient_debug) - zlog_debug("zclient connection closed socket [%d].", zclient->sock); - return zclient_failed(zclient); + + if (length < ZEBRA_HEADER_SIZE) { + zlog_err("%s: socket %d message length %u is less than %d ", + __func__, zclient->sock, length, ZEBRA_HEADER_SIZE); + return zclient_failed(zclient); } - if (nbyte != (ssize_t)(length-already)) - { - /* Try again later. */ - zclient_event (ZCLIENT_READ, zclient); - return 0; + + /* Length check. */ + if (length > STREAM_SIZE(zclient->ibuf)) { + struct stream *ns; + zlog_warn( + "%s: message size %u exceeds buffer size %lu, expanding...", + __func__, length, (u_long)STREAM_SIZE(zclient->ibuf)); + ns = stream_new(length); + stream_copy(ns, zclient->ibuf); + stream_free(zclient->ibuf); + zclient->ibuf = ns; + } + + /* Read rest of zebra packet. */ + if (already < length) { + ssize_t nbyte; + if (((nbyte = stream_read_try(zclient->ibuf, zclient->sock, + length - already)) + == 0) + || (nbyte == -1)) { + if (zclient_debug) + zlog_debug( + "zclient connection closed socket [%d].", + zclient->sock); + return zclient_failed(zclient); + } + if (nbyte != (ssize_t)(length - already)) { + /* Try again later. */ + zclient_event(ZCLIENT_READ, zclient); + return 0; + } + } + + length -= ZEBRA_HEADER_SIZE; + + if (zclient_debug) + zlog_debug("zclient 0x%p command 0x%x VRF %u\n", + (void *)zclient, command, vrf_id); + + switch (command) { + case ZEBRA_ROUTER_ID_UPDATE: + if (zclient->router_id_update) + (*zclient->router_id_update)(command, zclient, length, + vrf_id); + break; + case ZEBRA_VRF_ADD: + zclient_vrf_add(zclient, vrf_id); + break; + case ZEBRA_VRF_DELETE: + zclient_vrf_delete(zclient, vrf_id); + break; + case ZEBRA_INTERFACE_ADD: + if (zclient->interface_add) + (*zclient->interface_add)(command, zclient, length, + vrf_id); + break; + case ZEBRA_INTERFACE_DELETE: + if (zclient->interface_delete) + (*zclient->interface_delete)(command, zclient, length, + vrf_id); + break; + case ZEBRA_INTERFACE_ADDRESS_ADD: + if (zclient->interface_address_add) + (*zclient->interface_address_add)(command, zclient, + length, vrf_id); + break; + case ZEBRA_INTERFACE_ADDRESS_DELETE: + if (zclient->interface_address_delete) + (*zclient->interface_address_delete)(command, zclient, + length, vrf_id); + break; + case ZEBRA_INTERFACE_BFD_DEST_UPDATE: + if (zclient->interface_bfd_dest_update) + (*zclient->interface_bfd_dest_update)(command, zclient, + length, vrf_id); + break; + case ZEBRA_INTERFACE_NBR_ADDRESS_ADD: + if (zclient->interface_nbr_address_add) + (*zclient->interface_nbr_address_add)(command, zclient, + length, vrf_id); + break; + case ZEBRA_INTERFACE_NBR_ADDRESS_DELETE: + if (zclient->interface_nbr_address_delete) + (*zclient->interface_nbr_address_delete)( + command, zclient, length, vrf_id); + break; + case ZEBRA_INTERFACE_UP: + if (zclient->interface_up) + (*zclient->interface_up)(command, zclient, length, + vrf_id); + break; + case ZEBRA_INTERFACE_DOWN: + if (zclient->interface_down) + (*zclient->interface_down)(command, zclient, length, + vrf_id); + break; + case ZEBRA_INTERFACE_VRF_UPDATE: + if (zclient->interface_vrf_update) + (*zclient->interface_vrf_update)(command, zclient, + length, vrf_id); + break; + case ZEBRA_NEXTHOP_UPDATE: + if (zclient_debug) + zlog_debug("zclient rcvd nexthop update\n"); + if (zclient->nexthop_update) + (*zclient->nexthop_update)(command, zclient, length, + vrf_id); + break; + case ZEBRA_IMPORT_CHECK_UPDATE: + if (zclient_debug) + zlog_debug("zclient rcvd import check update\n"); + if (zclient->import_check_update) + (*zclient->import_check_update)(command, zclient, + length, vrf_id); + break; + case ZEBRA_BFD_DEST_REPLAY: + if (zclient->bfd_dest_replay) + (*zclient->bfd_dest_replay)(command, zclient, length, + vrf_id); + break; + case ZEBRA_REDISTRIBUTE_IPV4_ADD: + if (zclient->redistribute_route_ipv4_add) + (*zclient->redistribute_route_ipv4_add)( + command, zclient, length, vrf_id); + break; + case ZEBRA_REDISTRIBUTE_IPV4_DEL: + if (zclient->redistribute_route_ipv4_del) + (*zclient->redistribute_route_ipv4_del)( + command, zclient, length, vrf_id); + break; + case ZEBRA_REDISTRIBUTE_IPV6_ADD: + if (zclient->redistribute_route_ipv6_add) + (*zclient->redistribute_route_ipv6_add)( + command, zclient, length, vrf_id); + break; + case ZEBRA_REDISTRIBUTE_IPV6_DEL: + if (zclient->redistribute_route_ipv6_del) + (*zclient->redistribute_route_ipv6_del)( + command, zclient, length, vrf_id); + break; + case ZEBRA_INTERFACE_LINK_PARAMS: + if (zclient->interface_link_params) + (*zclient->interface_link_params)(command, zclient, + length); + break; + case ZEBRA_FEC_UPDATE: + if (zclient_debug) + zlog_debug("zclient rcvd fec update\n"); + if (zclient->fec_update) + (*zclient->fec_update)(command, zclient, length); + break; + case ZEBRA_VNI_ADD: + if (zclient->local_vni_add) + (*zclient->local_vni_add)(command, zclient, length, + vrf_id); + break; + case ZEBRA_VNI_DEL: + if (zclient->local_vni_del) + (*zclient->local_vni_del)(command, zclient, length, + vrf_id); + break; + case ZEBRA_MACIP_ADD: + if (zclient->local_macip_add) + (*zclient->local_macip_add)(command, zclient, length, + vrf_id); + break; + case ZEBRA_MACIP_DEL: + if (zclient->local_macip_del) + (*zclient->local_macip_del)(command, zclient, length, + vrf_id); + break; + default: + break; } - } - - length -= ZEBRA_HEADER_SIZE; - - if (zclient_debug) - zlog_debug("zclient 0x%p command 0x%x VRF %u\n", (void *)zclient, command, vrf_id); - - switch (command) - { - case ZEBRA_ROUTER_ID_UPDATE: - if (zclient->router_id_update) - (*zclient->router_id_update) (command, zclient, length, vrf_id); - break; - case ZEBRA_VRF_ADD: - zclient_vrf_add (zclient, vrf_id); - break; - case ZEBRA_VRF_DELETE: - zclient_vrf_delete (zclient, vrf_id); - break; - case ZEBRA_INTERFACE_ADD: - if (zclient->interface_add) - (*zclient->interface_add) (command, zclient, length, vrf_id); - break; - case ZEBRA_INTERFACE_DELETE: - if (zclient->interface_delete) - (*zclient->interface_delete) (command, zclient, length, vrf_id); - break; - case ZEBRA_INTERFACE_ADDRESS_ADD: - if (zclient->interface_address_add) - (*zclient->interface_address_add) (command, zclient, length, vrf_id); - break; - case ZEBRA_INTERFACE_ADDRESS_DELETE: - if (zclient->interface_address_delete) - (*zclient->interface_address_delete) (command, zclient, length, vrf_id); - break; - case ZEBRA_INTERFACE_BFD_DEST_UPDATE: - if (zclient->interface_bfd_dest_update) - (*zclient->interface_bfd_dest_update) (command, zclient, length, vrf_id); - break; - case ZEBRA_INTERFACE_NBR_ADDRESS_ADD: - if (zclient->interface_nbr_address_add) - (*zclient->interface_nbr_address_add) (command, zclient, length, vrf_id); - break; - case ZEBRA_INTERFACE_NBR_ADDRESS_DELETE: - if (zclient->interface_nbr_address_delete) - (*zclient->interface_nbr_address_delete) (command, zclient, length, vrf_id); - break; - case ZEBRA_INTERFACE_UP: - if (zclient->interface_up) - (*zclient->interface_up) (command, zclient, length, vrf_id); - break; - case ZEBRA_INTERFACE_DOWN: - if (zclient->interface_down) - (*zclient->interface_down) (command, zclient, length, vrf_id); - break; - case ZEBRA_INTERFACE_VRF_UPDATE: - if (zclient->interface_vrf_update) - (*zclient->interface_vrf_update) (command, zclient, length, vrf_id); - break; - case ZEBRA_NEXTHOP_UPDATE: - if (zclient_debug) - zlog_debug("zclient rcvd nexthop update\n"); - if (zclient->nexthop_update) - (*zclient->nexthop_update) (command, zclient, length, vrf_id); - break; - case ZEBRA_IMPORT_CHECK_UPDATE: - if (zclient_debug) - zlog_debug("zclient rcvd import check update\n"); - if (zclient->import_check_update) - (*zclient->import_check_update) (command, zclient, length, vrf_id); - break; - case ZEBRA_BFD_DEST_REPLAY: - if (zclient->bfd_dest_replay) - (*zclient->bfd_dest_replay) (command, zclient, length, vrf_id); - break; - case ZEBRA_REDISTRIBUTE_IPV4_ADD: - if (zclient->redistribute_route_ipv4_add) - (*zclient->redistribute_route_ipv4_add) (command, zclient, length, vrf_id); - break; - case ZEBRA_REDISTRIBUTE_IPV4_DEL: - if (zclient->redistribute_route_ipv4_del) - (*zclient->redistribute_route_ipv4_del) (command, zclient, length, vrf_id); - break; - case ZEBRA_REDISTRIBUTE_IPV6_ADD: - if (zclient->redistribute_route_ipv6_add) - (*zclient->redistribute_route_ipv6_add) (command, zclient, length, vrf_id); - break; - case ZEBRA_REDISTRIBUTE_IPV6_DEL: - if (zclient->redistribute_route_ipv6_del) - (*zclient->redistribute_route_ipv6_del) (command, zclient, length, vrf_id); - break; - case ZEBRA_INTERFACE_LINK_PARAMS: - if (zclient->interface_link_params) - (*zclient->interface_link_params) (command, zclient, length); - break; - case ZEBRA_FEC_UPDATE: - if (zclient_debug) - zlog_debug("zclient rcvd fec update\n"); - if (zclient->fec_update) - (*zclient->fec_update) (command, zclient, length); - break; - case ZEBRA_VNI_ADD: - if (zclient->local_vni_add) - (*zclient->local_vni_add) (command, zclient, length, vrf_id); - break; - case ZEBRA_VNI_DEL: - if (zclient->local_vni_del) - (*zclient->local_vni_del) (command, zclient, length, vrf_id); - break; - case ZEBRA_MACIP_ADD: - if (zclient->local_macip_add) - (*zclient->local_macip_add) (command, zclient, length, vrf_id); - break; - case ZEBRA_MACIP_DEL: - if (zclient->local_macip_del) - (*zclient->local_macip_del) (command, zclient, length, vrf_id); - break; - default: - break; - } - - if (zclient->sock < 0) - /* Connection was closed during packet processing. */ - return -1; - - /* Register read thread. */ - stream_reset(zclient->ibuf); - zclient_event (ZCLIENT_READ, zclient); - - return 0; + + if (zclient->sock < 0) + /* Connection was closed during packet processing. */ + return -1; + + /* Register read thread. */ + stream_reset(zclient->ibuf); + zclient_event(ZCLIENT_READ, zclient); + + return 0; } -void -zclient_redistribute (int command, struct zclient *zclient, afi_t afi, int type, - u_short instance, vrf_id_t vrf_id) +void zclient_redistribute(int command, struct zclient *zclient, afi_t afi, + int type, u_short instance, vrf_id_t vrf_id) { - if (instance) { - if (command == ZEBRA_REDISTRIBUTE_ADD) - { - if (redist_check_instance(&zclient->mi_redist[afi][type], instance)) - return; - redist_add_instance(&zclient->mi_redist[afi][type], instance); - } - else - { - if (!redist_check_instance(&zclient->mi_redist[afi][type], instance)) - return; - redist_del_instance(&zclient->mi_redist[afi][type], instance); - } - - } else { - if (command == ZEBRA_REDISTRIBUTE_ADD) - { - if (vrf_bitmap_check (zclient->redist[afi][type], vrf_id)) - return; - vrf_bitmap_set (zclient->redist[afi][type], vrf_id); - } - else - { - if (!vrf_bitmap_check (zclient->redist[afi][type], vrf_id)) - return; - vrf_bitmap_unset (zclient->redist[afi][type], vrf_id); - } - } - - if (zclient->sock > 0) - zebra_redistribute_send (command, zclient, afi, type, instance, vrf_id); + if (instance) { + if (command == ZEBRA_REDISTRIBUTE_ADD) { + if (redist_check_instance( + &zclient->mi_redist[afi][type], instance)) + return; + redist_add_instance(&zclient->mi_redist[afi][type], + instance); + } else { + if (!redist_check_instance( + &zclient->mi_redist[afi][type], instance)) + return; + redist_del_instance(&zclient->mi_redist[afi][type], + instance); + } + + } else { + if (command == ZEBRA_REDISTRIBUTE_ADD) { + if (vrf_bitmap_check(zclient->redist[afi][type], + vrf_id)) + return; + vrf_bitmap_set(zclient->redist[afi][type], vrf_id); + } else { + if (!vrf_bitmap_check(zclient->redist[afi][type], + vrf_id)) + return; + vrf_bitmap_unset(zclient->redist[afi][type], vrf_id); + } + } + + if (zclient->sock > 0) + zebra_redistribute_send(command, zclient, afi, type, instance, + vrf_id); } -void -zclient_redistribute_default (int command, struct zclient *zclient, - vrf_id_t vrf_id) +void zclient_redistribute_default(int command, struct zclient *zclient, + vrf_id_t vrf_id) { - if (command == ZEBRA_REDISTRIBUTE_DEFAULT_ADD) - { - if (vrf_bitmap_check (zclient->default_information, vrf_id)) - return; - vrf_bitmap_set (zclient->default_information, vrf_id); - } - else - { - if (!vrf_bitmap_check (zclient->default_information, vrf_id)) - return; - vrf_bitmap_unset (zclient->default_information, vrf_id); - } - - if (zclient->sock > 0) - zebra_message_send (zclient, command, vrf_id); + if (command == ZEBRA_REDISTRIBUTE_DEFAULT_ADD) { + if (vrf_bitmap_check(zclient->default_information, vrf_id)) + return; + vrf_bitmap_set(zclient->default_information, vrf_id); + } else { + if (!vrf_bitmap_check(zclient->default_information, vrf_id)) + return; + vrf_bitmap_unset(zclient->default_information, vrf_id); + } + + if (zclient->sock > 0) + zebra_message_send(zclient, command, vrf_id); } -static void -zclient_event (enum event event, struct zclient *zclient) +static void zclient_event(enum event event, struct zclient *zclient) { - switch (event) - { - case ZCLIENT_SCHEDULE: - thread_add_event(zclient->master, zclient_connect, zclient, 0, - &zclient->t_connect); - break; - case ZCLIENT_CONNECT: - if (zclient_debug) - zlog_debug ("zclient connect failures: %d schedule interval is now %d", - zclient->fail, zclient->fail < 3 ? 10 : 60); - thread_add_timer(zclient->master, zclient_connect, zclient, - zclient->fail < 3 ? 10 : 60, &zclient->t_connect); - break; - case ZCLIENT_READ: - zclient->t_read = NULL; - thread_add_read(zclient->master, zclient_read, zclient, zclient->sock, - &zclient->t_read); - break; - } + switch (event) { + case ZCLIENT_SCHEDULE: + thread_add_event(zclient->master, zclient_connect, zclient, 0, + &zclient->t_connect); + break; + case ZCLIENT_CONNECT: + if (zclient_debug) + zlog_debug( + "zclient connect failures: %d schedule interval is now %d", + zclient->fail, zclient->fail < 3 ? 10 : 60); + thread_add_timer(zclient->master, zclient_connect, zclient, + zclient->fail < 3 ? 10 : 60, + &zclient->t_connect); + break; + case ZCLIENT_READ: + zclient->t_read = NULL; + thread_add_read(zclient->master, zclient_read, zclient, + zclient->sock, &zclient->t_read); + break; + } } const char *zclient_serv_path_get() { - return zclient_serv_path ? zclient_serv_path : ZEBRA_SERV_PATH; + return zclient_serv_path ? zclient_serv_path : ZEBRA_SERV_PATH; } -void -zclient_serv_path_set (char *path) +void zclient_serv_path_set(char *path) { - struct stat sb; - - /* reset */ - zclient_serv_path = NULL; - - /* test if `path' is socket. don't set it otherwise. */ - if (stat(path, &sb) == -1) - { - zlog_warn ("%s: zebra socket `%s' does not exist", __func__, path); - return; - } - - if ((sb.st_mode & S_IFMT) != S_IFSOCK) - { - zlog_warn ("%s: `%s' is not unix socket, sir", __func__, path); - return; - } - - /* it seems that path is unix socket */ - zclient_serv_path = path; -} + struct stat sb; + /* reset */ + zclient_serv_path = NULL; + + /* test if `path' is socket. don't set it otherwise. */ + if (stat(path, &sb) == -1) { + zlog_warn("%s: zebra socket `%s' does not exist", __func__, + path); + return; + } + + if ((sb.st_mode & S_IFMT) != S_IFSOCK) { + zlog_warn("%s: `%s' is not unix socket, sir", __func__, path); + return; + } + + /* it seems that path is unix socket */ + zclient_serv_path = path; +} diff --git a/lib/zclient.h b/lib/zclient.h index c7cc857ef..efa5c32c1 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -38,148 +38,154 @@ /* Zebra message types. */ typedef enum { - ZEBRA_INTERFACE_ADD, - ZEBRA_INTERFACE_DELETE, - ZEBRA_INTERFACE_ADDRESS_ADD, - ZEBRA_INTERFACE_ADDRESS_DELETE, - ZEBRA_INTERFACE_UP, - ZEBRA_INTERFACE_DOWN, - ZEBRA_IPV4_ROUTE_ADD, - ZEBRA_IPV4_ROUTE_DELETE, - ZEBRA_IPV6_ROUTE_ADD, - ZEBRA_IPV6_ROUTE_DELETE, - ZEBRA_REDISTRIBUTE_ADD, - ZEBRA_REDISTRIBUTE_DELETE, - ZEBRA_REDISTRIBUTE_DEFAULT_ADD, - ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, - ZEBRA_ROUTER_ID_ADD, - ZEBRA_ROUTER_ID_DELETE, - ZEBRA_ROUTER_ID_UPDATE, - ZEBRA_HELLO, - ZEBRA_NEXTHOP_REGISTER, - ZEBRA_NEXTHOP_UNREGISTER, - ZEBRA_NEXTHOP_UPDATE, - ZEBRA_INTERFACE_NBR_ADDRESS_ADD, - ZEBRA_INTERFACE_NBR_ADDRESS_DELETE, - ZEBRA_INTERFACE_BFD_DEST_UPDATE, - ZEBRA_IMPORT_ROUTE_REGISTER, - ZEBRA_IMPORT_ROUTE_UNREGISTER, - ZEBRA_IMPORT_CHECK_UPDATE, - ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD, - ZEBRA_BFD_DEST_REGISTER, - ZEBRA_BFD_DEST_DEREGISTER, - ZEBRA_BFD_DEST_UPDATE, - ZEBRA_BFD_DEST_REPLAY, - ZEBRA_REDISTRIBUTE_IPV4_ADD, - ZEBRA_REDISTRIBUTE_IPV4_DEL, - ZEBRA_REDISTRIBUTE_IPV6_ADD, - ZEBRA_REDISTRIBUTE_IPV6_DEL, - ZEBRA_VRF_UNREGISTER, - ZEBRA_VRF_ADD, - ZEBRA_VRF_DELETE, - ZEBRA_INTERFACE_VRF_UPDATE, - ZEBRA_BFD_CLIENT_REGISTER, - ZEBRA_INTERFACE_ENABLE_RADV, - ZEBRA_INTERFACE_DISABLE_RADV, - ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, - ZEBRA_INTERFACE_LINK_PARAMS, - ZEBRA_MPLS_LABELS_ADD, - ZEBRA_MPLS_LABELS_DELETE, - ZEBRA_IPV4_NEXTHOP_ADD, - ZEBRA_IPV4_NEXTHOP_DELETE, - ZEBRA_IPV6_NEXTHOP_ADD, - ZEBRA_IPV6_NEXTHOP_DELETE, - ZEBRA_IPMR_ROUTE_STATS, - ZEBRA_LABEL_MANAGER_CONNECT, - ZEBRA_GET_LABEL_CHUNK, - ZEBRA_RELEASE_LABEL_CHUNK, - ZEBRA_FEC_REGISTER, - ZEBRA_FEC_UNREGISTER, - ZEBRA_FEC_UPDATE, - ZEBRA_ADVERTISE_ALL_VNI, - ZEBRA_VNI_ADD, - ZEBRA_VNI_DEL, - ZEBRA_REMOTE_VTEP_ADD, - ZEBRA_REMOTE_VTEP_DEL, - ZEBRA_MACIP_ADD, - ZEBRA_MACIP_DEL, - ZEBRA_REMOTE_MACIP_ADD, - ZEBRA_REMOTE_MACIP_DEL, + ZEBRA_INTERFACE_ADD, + ZEBRA_INTERFACE_DELETE, + ZEBRA_INTERFACE_ADDRESS_ADD, + ZEBRA_INTERFACE_ADDRESS_DELETE, + ZEBRA_INTERFACE_UP, + ZEBRA_INTERFACE_DOWN, + ZEBRA_IPV4_ROUTE_ADD, + ZEBRA_IPV4_ROUTE_DELETE, + ZEBRA_IPV6_ROUTE_ADD, + ZEBRA_IPV6_ROUTE_DELETE, + ZEBRA_REDISTRIBUTE_ADD, + ZEBRA_REDISTRIBUTE_DELETE, + ZEBRA_REDISTRIBUTE_DEFAULT_ADD, + ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, + ZEBRA_ROUTER_ID_ADD, + ZEBRA_ROUTER_ID_DELETE, + ZEBRA_ROUTER_ID_UPDATE, + ZEBRA_HELLO, + ZEBRA_NEXTHOP_REGISTER, + ZEBRA_NEXTHOP_UNREGISTER, + ZEBRA_NEXTHOP_UPDATE, + ZEBRA_INTERFACE_NBR_ADDRESS_ADD, + ZEBRA_INTERFACE_NBR_ADDRESS_DELETE, + ZEBRA_INTERFACE_BFD_DEST_UPDATE, + ZEBRA_IMPORT_ROUTE_REGISTER, + ZEBRA_IMPORT_ROUTE_UNREGISTER, + ZEBRA_IMPORT_CHECK_UPDATE, + ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD, + ZEBRA_BFD_DEST_REGISTER, + ZEBRA_BFD_DEST_DEREGISTER, + ZEBRA_BFD_DEST_UPDATE, + ZEBRA_BFD_DEST_REPLAY, + ZEBRA_REDISTRIBUTE_IPV4_ADD, + ZEBRA_REDISTRIBUTE_IPV4_DEL, + ZEBRA_REDISTRIBUTE_IPV6_ADD, + ZEBRA_REDISTRIBUTE_IPV6_DEL, + ZEBRA_VRF_UNREGISTER, + ZEBRA_VRF_ADD, + ZEBRA_VRF_DELETE, + ZEBRA_INTERFACE_VRF_UPDATE, + ZEBRA_BFD_CLIENT_REGISTER, + ZEBRA_INTERFACE_ENABLE_RADV, + ZEBRA_INTERFACE_DISABLE_RADV, + ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, + ZEBRA_INTERFACE_LINK_PARAMS, + ZEBRA_MPLS_LABELS_ADD, + ZEBRA_MPLS_LABELS_DELETE, + ZEBRA_IPV4_NEXTHOP_ADD, + ZEBRA_IPV4_NEXTHOP_DELETE, + ZEBRA_IPV6_NEXTHOP_ADD, + ZEBRA_IPV6_NEXTHOP_DELETE, + ZEBRA_IPMR_ROUTE_STATS, + ZEBRA_LABEL_MANAGER_CONNECT, + ZEBRA_GET_LABEL_CHUNK, + ZEBRA_RELEASE_LABEL_CHUNK, + ZEBRA_FEC_REGISTER, + ZEBRA_FEC_UNREGISTER, + ZEBRA_FEC_UPDATE, + ZEBRA_ADVERTISE_ALL_VNI, + ZEBRA_VNI_ADD, + ZEBRA_VNI_DEL, + ZEBRA_REMOTE_VTEP_ADD, + ZEBRA_REMOTE_VTEP_DEL, + ZEBRA_MACIP_ADD, + ZEBRA_MACIP_DEL, + ZEBRA_REMOTE_MACIP_ADD, + ZEBRA_REMOTE_MACIP_DEL, } zebra_message_types_t; -struct redist_proto -{ - u_char enabled; - struct list *instances; +struct redist_proto { + u_char enabled; + struct list *instances; }; /* Structure for the zebra client. */ -struct zclient -{ - /* The thread master we schedule ourselves on */ - struct thread_master *master; - - /* Socket to zebra daemon. */ - int sock; - - /* Flag of communication to zebra is enabled or not. Default is on. - This flag is disabled by `no router zebra' statement. */ - int enable; - - /* Connection failure count. */ - int fail; - - /* Input buffer for zebra message. */ - struct stream *ibuf; - - /* Output buffer for zebra message. */ - struct stream *obuf; - - /* Buffer of data waiting to be written to zebra. */ - struct buffer *wb; - - /* Read and connect thread. */ - struct thread *t_read; - struct thread *t_connect; - - /* Thread to write buffered data to zebra. */ - struct thread *t_write; - - /* Redistribute information. */ - u_char redist_default; /* clients protocol */ - u_short instance; - struct redist_proto mi_redist[AFI_MAX][ZEBRA_ROUTE_MAX]; - vrf_bitmap_t redist[AFI_MAX][ZEBRA_ROUTE_MAX]; - - /* Redistribute defauilt. */ - vrf_bitmap_t default_information; - - /* Pointer to the callback functions. */ - void (*zebra_connected) (struct zclient *); - int (*router_id_update) (int, struct zclient *, uint16_t, vrf_id_t); - int (*interface_add) (int, struct zclient *, uint16_t, vrf_id_t); - int (*interface_delete) (int, struct zclient *, uint16_t, vrf_id_t); - int (*interface_up) (int, struct zclient *, uint16_t, vrf_id_t); - int (*interface_down) (int, struct zclient *, uint16_t, vrf_id_t); - int (*interface_address_add) (int, struct zclient *, uint16_t, vrf_id_t); - int (*interface_address_delete) (int, struct zclient *, uint16_t, vrf_id_t); - int (*interface_link_params) (int, struct zclient *, uint16_t); - int (*interface_bfd_dest_update) (int, struct zclient *, uint16_t, vrf_id_t); - int (*interface_nbr_address_add) (int, struct zclient *, uint16_t, vrf_id_t); - int (*interface_nbr_address_delete) (int, struct zclient *, uint16_t, vrf_id_t); - int (*interface_vrf_update) (int, struct zclient *, uint16_t, vrf_id_t); - int (*nexthop_update) (int, struct zclient *, uint16_t, vrf_id_t); - int (*import_check_update) (int, struct zclient *, uint16_t, vrf_id_t); - int (*bfd_dest_replay) (int, struct zclient *, uint16_t, vrf_id_t); - int (*redistribute_route_ipv4_add) (int, struct zclient *, uint16_t, vrf_id_t); - int (*redistribute_route_ipv4_del) (int, struct zclient *, uint16_t, vrf_id_t); - int (*redistribute_route_ipv6_add) (int, struct zclient *, uint16_t, vrf_id_t); - int (*redistribute_route_ipv6_del) (int, struct zclient *, uint16_t, vrf_id_t); - int (*fec_update) (int, struct zclient *, uint16_t); - int (*local_vni_add) (int, struct zclient *, uint16_t, vrf_id_t); - int (*local_vni_del) (int, struct zclient *, uint16_t, vrf_id_t); - int (*local_macip_add) (int, struct zclient *, uint16_t, vrf_id_t); - int (*local_macip_del) (int, struct zclient *, uint16_t, vrf_id_t); +struct zclient { + /* The thread master we schedule ourselves on */ + struct thread_master *master; + + /* Socket to zebra daemon. */ + int sock; + + /* Flag of communication to zebra is enabled or not. Default is on. + This flag is disabled by `no router zebra' statement. */ + int enable; + + /* Connection failure count. */ + int fail; + + /* Input buffer for zebra message. */ + struct stream *ibuf; + + /* Output buffer for zebra message. */ + struct stream *obuf; + + /* Buffer of data waiting to be written to zebra. */ + struct buffer *wb; + + /* Read and connect thread. */ + struct thread *t_read; + struct thread *t_connect; + + /* Thread to write buffered data to zebra. */ + struct thread *t_write; + + /* Redistribute information. */ + u_char redist_default; /* clients protocol */ + u_short instance; + struct redist_proto mi_redist[AFI_MAX][ZEBRA_ROUTE_MAX]; + vrf_bitmap_t redist[AFI_MAX][ZEBRA_ROUTE_MAX]; + + /* Redistribute defauilt. */ + vrf_bitmap_t default_information; + + /* Pointer to the callback functions. */ + void (*zebra_connected)(struct zclient *); + int (*router_id_update)(int, struct zclient *, uint16_t, vrf_id_t); + int (*interface_add)(int, struct zclient *, uint16_t, vrf_id_t); + int (*interface_delete)(int, struct zclient *, uint16_t, vrf_id_t); + int (*interface_up)(int, struct zclient *, uint16_t, vrf_id_t); + int (*interface_down)(int, struct zclient *, uint16_t, vrf_id_t); + int (*interface_address_add)(int, struct zclient *, uint16_t, vrf_id_t); + int (*interface_address_delete)(int, struct zclient *, uint16_t, + vrf_id_t); + int (*interface_link_params)(int, struct zclient *, uint16_t); + int (*interface_bfd_dest_update)(int, struct zclient *, uint16_t, + vrf_id_t); + int (*interface_nbr_address_add)(int, struct zclient *, uint16_t, + vrf_id_t); + int (*interface_nbr_address_delete)(int, struct zclient *, uint16_t, + vrf_id_t); + int (*interface_vrf_update)(int, struct zclient *, uint16_t, vrf_id_t); + int (*nexthop_update)(int, struct zclient *, uint16_t, vrf_id_t); + int (*import_check_update)(int, struct zclient *, uint16_t, vrf_id_t); + int (*bfd_dest_replay)(int, struct zclient *, uint16_t, vrf_id_t); + int (*redistribute_route_ipv4_add)(int, struct zclient *, uint16_t, + vrf_id_t); + int (*redistribute_route_ipv4_del)(int, struct zclient *, uint16_t, + vrf_id_t); + int (*redistribute_route_ipv6_add)(int, struct zclient *, uint16_t, + vrf_id_t); + int (*redistribute_route_ipv6_del)(int, struct zclient *, uint16_t, + vrf_id_t); + int (*fec_update)(int, struct zclient *, uint16_t); + int (*local_vni_add)(int, struct zclient *, uint16_t, vrf_id_t); + int (*local_vni_del)(int, struct zclient *, uint16_t, vrf_id_t); + int (*local_macip_add)(int, struct zclient *, uint16_t, vrf_id_t); + int (*local_macip_del)(int, struct zclient *, uint16_t, vrf_id_t); }; /* Zebra API message flag. */ @@ -193,176 +199,180 @@ struct zclient #define ZAPI_MESSAGE_LABEL 0x80 /* Zserv protocol message header */ -struct zserv_header -{ - uint16_t length; - uint8_t marker; /* corresponds to command field in old zserv - * always set to 255 in new zserv. - */ - uint8_t version; +struct zserv_header { + uint16_t length; + uint8_t marker; /* corresponds to command field in old zserv + * always set to 255 in new zserv. + */ + uint8_t version; #define ZSERV_VERSION 4 - vrf_id_t vrf_id; - uint16_t command; + vrf_id_t vrf_id; + uint16_t command; }; -struct zapi_route -{ - u_char type; - u_short instance; +struct zapi_route { + u_char type; + u_short instance; - u_int32_t flags; + u_int32_t flags; - u_char message; + u_char message; - safi_t safi; + safi_t safi; - u_char nexthop_num; - struct nexthop **nexthop; + u_char nexthop_num; + struct nexthop **nexthop; - u_char distance; + u_char distance; - u_int32_t metric; + u_int32_t metric; - route_tag_t tag; + route_tag_t tag; - u_int32_t mtu; + u_int32_t mtu; - vrf_id_t vrf_id; + vrf_id_t vrf_id; }; /* Zebra IPv4 route message API. */ -struct zapi_ipv4 -{ - u_char type; - u_short instance; +struct zapi_ipv4 { + u_char type; + u_short instance; - u_int32_t flags; + u_int32_t flags; - u_char message; + u_char message; - safi_t safi; + safi_t safi; - u_char nexthop_num; - struct in_addr **nexthop; + u_char nexthop_num; + struct in_addr **nexthop; - u_char ifindex_num; - ifindex_t *ifindex; + u_char ifindex_num; + ifindex_t *ifindex; - u_char label_num; - unsigned int *label; + u_char label_num; + unsigned int *label; - u_char distance; + u_char distance; - u_int32_t metric; + u_int32_t metric; - route_tag_t tag; + route_tag_t tag; - u_int32_t mtu; + u_int32_t mtu; - vrf_id_t vrf_id; + vrf_id_t vrf_id; }; /* Prototypes of zebra client service functions. */ -extern struct zclient *zclient_new (struct thread_master *); -extern void zclient_init (struct zclient *, int, u_short); -extern int zclient_start (struct zclient *); -extern void zclient_stop (struct zclient *); -extern void zclient_reset (struct zclient *); -extern void zclient_free (struct zclient *); +extern struct zclient *zclient_new(struct thread_master *); +extern void zclient_init(struct zclient *, int, u_short); +extern int zclient_start(struct zclient *); +extern void zclient_stop(struct zclient *); +extern void zclient_reset(struct zclient *); +extern void zclient_free(struct zclient *); -extern int zclient_socket_connect (struct zclient *); -extern void zclient_serv_path_set (char *path); -extern const char *zclient_serv_path_get (void); +extern int zclient_socket_connect(struct zclient *); +extern void zclient_serv_path_set(char *path); +extern const char *zclient_serv_path_get(void); -extern u_short *redist_check_instance (struct redist_proto *, u_short); -extern void redist_add_instance (struct redist_proto *, u_short); -extern void redist_del_instance (struct redist_proto *, u_short); +extern u_short *redist_check_instance(struct redist_proto *, u_short); +extern void redist_add_instance(struct redist_proto *, u_short); +extern void redist_del_instance(struct redist_proto *, u_short); -extern void zclient_send_reg_requests (struct zclient *, vrf_id_t); -extern void zclient_send_dereg_requests (struct zclient *, vrf_id_t); +extern void zclient_send_reg_requests(struct zclient *, vrf_id_t); +extern void zclient_send_dereg_requests(struct zclient *, vrf_id_t); -extern void zclient_send_interface_radv_req (struct zclient *zclient, vrf_id_t vrf_id, - struct interface *ifp, int enable, int ra_interval); +extern void zclient_send_interface_radv_req(struct zclient *zclient, + vrf_id_t vrf_id, + struct interface *ifp, int enable, + int ra_interval); /* Send redistribute command to zebra daemon. Do not update zclient state. */ -extern int zebra_redistribute_send (int command, struct zclient *, afi_t, int type, u_short instance, vrf_id_t vrf_id); +extern int zebra_redistribute_send(int command, struct zclient *, afi_t, + int type, u_short instance, vrf_id_t vrf_id); /* If state has changed, update state and call zebra_redistribute_send. */ -extern void zclient_redistribute (int command, struct zclient *, afi_t, int type, - u_short instance, vrf_id_t vrf_id); +extern void zclient_redistribute(int command, struct zclient *, afi_t, int type, + u_short instance, vrf_id_t vrf_id); /* If state has changed, update state and send the command to zebra. */ -extern void zclient_redistribute_default (int command, struct zclient *, - vrf_id_t vrf_id); +extern void zclient_redistribute_default(int command, struct zclient *, + vrf_id_t vrf_id); /* Send the message in zclient->obuf to the zebra daemon (or enqueue it). Returns 0 for success or -1 on an I/O error. */ extern int zclient_send_message(struct zclient *); /* create header for command, length to be filled in by user later */ -extern void zclient_create_header (struct stream *, uint16_t, vrf_id_t); -extern int zclient_read_header (struct stream *s, int sock, u_int16_t *size, - u_char *marker, u_char *version, - vrf_id_t *vrf_id, u_int16_t *cmd); - -extern struct interface *zebra_interface_add_read (struct stream *, vrf_id_t); -extern struct interface *zebra_interface_state_read (struct stream *s, vrf_id_t); -extern struct connected *zebra_interface_address_read (int, struct stream *, vrf_id_t); -extern struct nbr_connected *zebra_interface_nbr_address_read (int, struct stream *, vrf_id_t); -extern struct interface * zebra_interface_vrf_update_read (struct stream *s, vrf_id_t vrf_id, - vrf_id_t *new_vrf_id); -extern void zebra_interface_if_set_value (struct stream *, struct interface *); -extern void zebra_router_id_update_read (struct stream *s, struct prefix *rid); -extern int zapi_ipv4_route (u_char, struct zclient *, struct prefix_ipv4 *, - struct zapi_ipv4 *); - -extern struct interface *zebra_interface_link_params_read (struct stream *); -extern size_t zebra_interface_link_params_write (struct stream *, - struct interface *); -extern int lm_label_manager_connect (struct zclient *zclient); -extern int lm_get_label_chunk (struct zclient *zclient, u_char keep, - uint32_t chunk_size, uint32_t *start, uint32_t *end); -extern int lm_release_label_chunk (struct zclient *zclient, uint32_t start, uint32_t end); +extern void zclient_create_header(struct stream *, uint16_t, vrf_id_t); +extern int zclient_read_header(struct stream *s, int sock, u_int16_t *size, + u_char *marker, u_char *version, + vrf_id_t *vrf_id, u_int16_t *cmd); + +extern struct interface *zebra_interface_add_read(struct stream *, vrf_id_t); +extern struct interface *zebra_interface_state_read(struct stream *s, vrf_id_t); +extern struct connected *zebra_interface_address_read(int, struct stream *, + vrf_id_t); +extern struct nbr_connected * +zebra_interface_nbr_address_read(int, struct stream *, vrf_id_t); +extern struct interface *zebra_interface_vrf_update_read(struct stream *s, + vrf_id_t vrf_id, + vrf_id_t *new_vrf_id); +extern void zebra_interface_if_set_value(struct stream *, struct interface *); +extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid); +extern int zapi_ipv4_route(u_char, struct zclient *, struct prefix_ipv4 *, + struct zapi_ipv4 *); + +extern struct interface *zebra_interface_link_params_read(struct stream *); +extern size_t zebra_interface_link_params_write(struct stream *, + struct interface *); +extern int lm_label_manager_connect(struct zclient *zclient); +extern int lm_get_label_chunk(struct zclient *zclient, u_char keep, + uint32_t chunk_size, uint32_t *start, + uint32_t *end); +extern int lm_release_label_chunk(struct zclient *zclient, uint32_t start, + uint32_t end); /* IPv6 prefix add and delete function prototype. */ -struct zapi_ipv6 -{ - u_char type; - u_short instance; +struct zapi_ipv6 { + u_char type; + u_short instance; - u_int32_t flags; + u_int32_t flags; - u_char message; + u_char message; - safi_t safi; + safi_t safi; - u_char nexthop_num; - struct in6_addr **nexthop; + u_char nexthop_num; + struct in6_addr **nexthop; - u_char ifindex_num; - ifindex_t *ifindex; + u_char ifindex_num; + ifindex_t *ifindex; - u_char label_num; - unsigned int *label; + u_char label_num; + unsigned int *label; - u_char distance; + u_char distance; - u_int32_t metric; + u_int32_t metric; - route_tag_t tag; + route_tag_t tag; - u_int32_t mtu; + u_int32_t mtu; - vrf_id_t vrf_id; + vrf_id_t vrf_id; }; -extern int zapi_ipv6_route (u_char cmd, struct zclient *zclient, - struct prefix_ipv6 *p, struct prefix_ipv6 *src_p, - struct zapi_ipv6 *api); -extern int zapi_ipv4_route_ipv6_nexthop (u_char, struct zclient *, - struct prefix_ipv4 *, struct zapi_ipv6 *); -extern int zapi_route (u_char cmd, struct zclient *zclient, - struct prefix *p, struct prefix_ipv6 *src_p, - struct zapi_route *api); +extern int zapi_ipv6_route(u_char cmd, struct zclient *zclient, + struct prefix_ipv6 *p, struct prefix_ipv6 *src_p, + struct zapi_ipv6 *api); +extern int zapi_ipv4_route_ipv6_nexthop(u_char, struct zclient *, + struct prefix_ipv4 *, + struct zapi_ipv6 *); +extern int zapi_route(u_char cmd, struct zclient *zclient, struct prefix *p, + struct prefix_ipv6 *src_p, struct zapi_route *api); #endif /* _ZEBRA_ZCLIENT_H */ diff --git a/lib/zebra.h b/lib/zebra.h index 7f2609c12..8e1c4db80 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -27,9 +27,9 @@ #ifdef SUNOS_5 #define _XPG4_2 -typedef unsigned int u_int32_t; -typedef unsigned short u_int16_t; -typedef unsigned char u_int8_t; +typedef unsigned int u_int32_t; +typedef unsigned short u_int16_t; +typedef unsigned char u_int8_t; #endif /* SUNOS_5 */ #include @@ -95,7 +95,7 @@ typedef unsigned char u_int8_t; #ifdef __va_copy #define va_copy(DST,SRC) __va_copy(DST,SRC) #else -/* Now we are desperate; this should work on many typical platforms. +/* Now we are desperate; this should work on many typical platforms. But this is slightly dangerous, because the standard does not require va_copy to be a macro. */ #define va_copy(DST,SRC) memcpy(&(DST), &(SRC), sizeof(va_list)) @@ -218,17 +218,17 @@ typedef unsigned char u_int8_t; #endif /* HAVE_GLIBC_BACKTRACE */ /* Local includes: */ -#if !(defined(__GNUC__) || defined(VTYSH_EXTRACT_PL)) +#if !(defined(__GNUC__) || defined(VTYSH_EXTRACT_PL)) #define __attribute__(x) -#endif /* !__GNUC__ || VTYSH_EXTRACT_PL */ +#endif /* !__GNUC__ || VTYSH_EXTRACT_PL */ #include "zassert.h" #ifndef HAVE_STRLCAT -size_t strlcat (char *__restrict dest, const char *__restrict src, size_t size); +size_t strlcat(char *__restrict dest, const char *__restrict src, size_t size); #endif #ifndef HAVE_STRLCPY -size_t strlcpy (char *__restrict dest, const char *__restrict src, size_t size); +size_t strlcpy(char *__restrict dest, const char *__restrict src, size_t size); #endif #ifdef HAVE_BROKEN_CMSG_FIRSTHDR @@ -236,13 +236,14 @@ size_t strlcpy (char *__restrict dest, const char *__restrict src, size_t size); please refer to http://bugzilla.quagga.net/show_bug.cgi?id=142 */ /* Check that msg_controllen is large enough. */ -#define ZCMSG_FIRSTHDR(mhdr) \ - (((size_t)((mhdr)->msg_controllen) >= sizeof(struct cmsghdr)) ? \ - CMSG_FIRSTHDR(mhdr) : (struct cmsghdr *)NULL) +#define ZCMSG_FIRSTHDR(mhdr) \ + (((size_t)((mhdr)->msg_controllen) >= sizeof(struct cmsghdr)) \ + ? CMSG_FIRSTHDR(mhdr) \ + : (struct cmsghdr *)NULL) #warning "CMSG_FIRSTHDR is broken on this platform, using a workaround" -#else /* HAVE_BROKEN_CMSG_FIRSTHDR */ +#else /* HAVE_BROKEN_CMSG_FIRSTHDR */ #define ZCMSG_FIRSTHDR(M) CMSG_FIRSTHDR(M) #endif /* HAVE_BROKEN_CMSG_FIRSTHDR */ @@ -254,7 +255,7 @@ size_t strlcpy (char *__restrict dest, const char *__restrict src, size_t size); #define PRINTF_ATTRIBUTE(a,b) #endif /* __GNUC__ */ -/* +/* * RFC 3542 defines several macros for using struct cmsghdr. * Here, we define those that are not present */ @@ -276,10 +277,10 @@ size_t strlcpy (char *__restrict dest, const char *__restrict src, size_t size); * version. */ #ifndef CMSG_SPACE -#define CMSG_SPACE(l) (_CMSG_DATA_ALIGN(sizeof(struct cmsghdr)) + \ - _CMSG_HDR_ALIGN(l)) +#define CMSG_SPACE(l) \ + (_CMSG_DATA_ALIGN(sizeof(struct cmsghdr)) + _CMSG_HDR_ALIGN(l)) #warning "assuming 4-byte alignment for CMSG_SPACE" -#endif /* CMSG_SPACE */ +#endif /* CMSG_SPACE */ #ifndef CMSG_LEN @@ -290,29 +291,28 @@ size_t strlcpy (char *__restrict dest, const char *__restrict src, size_t size); /* The definition of struct in_pktinfo is missing in old version of GLIBC 2.1 (Redhat 6.1). */ -#if defined (GNU_LINUX) && ! defined (HAVE_STRUCT_IN_PKTINFO) -struct in_pktinfo -{ - int ipi_ifindex; - struct in_addr ipi_spec_dst; - struct in_addr ipi_addr; +#if defined(GNU_LINUX) && !defined(HAVE_STRUCT_IN_PKTINFO) +struct in_pktinfo { + int ipi_ifindex; + struct in_addr ipi_spec_dst; + struct in_addr ipi_addr; }; #endif -/* +/* * IP_HDRINCL / struct ip byte order * * Linux: network byte order * *BSD: network, except for length and offset. (cf Stevens) * SunOS: nominally as per BSD. but bug: network order on LE. - * OpenBSD: network byte order, apart from older versions which are as per + * OpenBSD: network byte order, apart from older versions which are as per * *BSD */ -#if defined(__NetBSD__) \ - || (defined(__FreeBSD__) && (__FreeBSD_version < 1100030)) \ - || (defined(__OpenBSD__) && (OpenBSD < 200311)) \ - || (defined(__APPLE__)) \ - || (defined(SUNOS_5) && defined(WORDS_BIGENDIAN)) +#if defined(__NetBSD__) \ + || (defined(__FreeBSD__) && (__FreeBSD_version < 1100030)) \ + || (defined(__OpenBSD__) && (OpenBSD < 200311)) \ + || (defined(__APPLE__)) \ + || (defined(SUNOS_5) && defined(WORDS_BIGENDIAN)) #define HAVE_IP_HDRINCL_BSD_ORDER #endif @@ -327,7 +327,7 @@ struct in_pktinfo #if defined(WORDS_BIGENDIAN) #define BYTE_ORDER BIG_ENDIAN -#else /* !WORDS_BIGENDIAN */ +#else /* !WORDS_BIGENDIAN */ #define BYTE_ORDER LITTLE_ENDIAN #endif /* WORDS_BIGENDIAN */ @@ -338,17 +338,21 @@ struct in_pktinfo #ifdef MAX #undef MAX #endif -#define MAX(a, b) \ - ({ typeof (a) _a = (a); \ - typeof (b) _b = (b); \ - _a > _b ? _a : _b; }) +#define MAX(a, b) \ + ({ \ + typeof(a) _a = (a); \ + typeof(b) _b = (b); \ + _a > _b ? _a : _b; \ + }) #ifdef MIN #undef MIN #endif -#define MIN(a, b) \ - ({ typeof (a) _a = (a); \ - typeof (b) _b = (b); \ - _a < _b ? _a : _b; }) +#define MIN(a, b) \ + ({ \ + typeof(a) _a = (a); \ + typeof(b) _b = (b); \ + _a < _b ? _a : _b; \ + }) #define ZEBRA_NUM_OF(x) (sizeof (x) / sizeof (x[0])) @@ -377,7 +381,7 @@ struct in_pktinfo extern const char *zebra_route_string(unsigned int route_type); /* Map a route type to a char. For example, ZEBRA_ROUTE_RIPNG -> 'R'. */ extern char zebra_route_char(unsigned int route_type); -/* Map a zserv command type to the same string, +/* Map a zserv command type to the same string, * e.g. ZEBRA_INTERFACE_ADD -> "ZEBRA_INTERFACE_ADD" */ /* Map a protocol name to its number. e.g. ZEBRA_ROUTE_BGP->9*/ extern int proto_name2num(const char *s); @@ -386,7 +390,7 @@ extern int proto_name2num(const char *s); * an AFI value to restrict input */ extern int proto_redistnum(int afi, const char *s); -extern const char *zserv_command_string (unsigned int command); +extern const char *zserv_command_string(unsigned int command); #define strmatch(a,b) (!strcmp((a), (b))) @@ -409,12 +413,7 @@ extern const char *zserv_command_string (unsigned int command); #endif /* Address family numbers from RFC1700. */ -typedef enum { - AFI_IP = 1, - AFI_IP6 = 2, - AFI_L2VPN = 3, - AFI_MAX = 4 -} afi_t; +typedef enum { AFI_IP = 1, AFI_IP6 = 2, AFI_L2VPN = 3, AFI_MAX = 4 } afi_t; /* Subsequent Address Family Identifier. */ #define SAFI_UNICAST 1 @@ -444,12 +443,12 @@ typedef enum { * Note: Only useful (i.e., supported) values are defined below. */ typedef enum { - IANA_AFI_RESERVED = 0, - IANA_AFI_IPV4 = 1, - IANA_AFI_IPV6 = 2, - IANA_AFI_L2VPN = 25, - IANA_AFI_IPMR = 128, - IANA_AFI_IP6MR = 129 + IANA_AFI_RESERVED = 0, + IANA_AFI_IPV4 = 1, + IANA_AFI_IPV6 = 2, + IANA_AFI_L2VPN = 25, + IANA_AFI_IPMR = 128, + IANA_AFI_IP6MR = 129 } iana_afi_t; #define IANA_SAFI_RESERVED 0 @@ -491,60 +490,60 @@ typedef uint32_t route_tag_t; #define ROUTE_TAG_MAX UINT32_MAX #define ROUTE_TAG_PRI PRIu32 -static inline afi_t afi_iana2int (iana_afi_t afi) +static inline afi_t afi_iana2int(iana_afi_t afi) { - if (afi == IANA_AFI_IPV4) - return AFI_IP; - if (afi == IANA_AFI_IPV6) - return AFI_IP6; - if (afi == IANA_AFI_L2VPN) - return AFI_L2VPN; - return AFI_MAX; + if (afi == IANA_AFI_IPV4) + return AFI_IP; + if (afi == IANA_AFI_IPV6) + return AFI_IP6; + if (afi == IANA_AFI_L2VPN) + return AFI_L2VPN; + return AFI_MAX; } -static inline iana_afi_t afi_int2iana (afi_t afi) +static inline iana_afi_t afi_int2iana(afi_t afi) { - if (afi == AFI_IP) - return IANA_AFI_IPV4; - if (afi == AFI_IP6) - return IANA_AFI_IPV6; - if (afi == AFI_L2VPN) - return IANA_AFI_L2VPN; - return IANA_AFI_RESERVED; + if (afi == AFI_IP) + return IANA_AFI_IPV4; + if (afi == AFI_IP6) + return IANA_AFI_IPV6; + if (afi == AFI_L2VPN) + return IANA_AFI_L2VPN; + return IANA_AFI_RESERVED; } -static inline safi_t safi_iana2int (safi_t safi) +static inline safi_t safi_iana2int(safi_t safi) { - if (safi == IANA_SAFI_UNICAST) - return SAFI_UNICAST; - if (safi == IANA_SAFI_MULTICAST) - return SAFI_MULTICAST; - if (safi == IANA_SAFI_MPLS_VPN) - return SAFI_MPLS_VPN; - if (safi == IANA_SAFI_ENCAP) - return SAFI_ENCAP; - if (safi == IANA_SAFI_EVPN) - return SAFI_EVPN; - if (safi == IANA_SAFI_LABELED_UNICAST) - return SAFI_LABELED_UNICAST; - return SAFI_MAX; + if (safi == IANA_SAFI_UNICAST) + return SAFI_UNICAST; + if (safi == IANA_SAFI_MULTICAST) + return SAFI_MULTICAST; + if (safi == IANA_SAFI_MPLS_VPN) + return SAFI_MPLS_VPN; + if (safi == IANA_SAFI_ENCAP) + return SAFI_ENCAP; + if (safi == IANA_SAFI_EVPN) + return SAFI_EVPN; + if (safi == IANA_SAFI_LABELED_UNICAST) + return SAFI_LABELED_UNICAST; + return SAFI_MAX; } -static inline safi_t safi_int2iana (safi_t safi) +static inline safi_t safi_int2iana(safi_t safi) { - if (safi == SAFI_UNICAST) - return IANA_SAFI_UNICAST; - if (safi == SAFI_MULTICAST) - return IANA_SAFI_MULTICAST; - if (safi == SAFI_MPLS_VPN) - return IANA_SAFI_MPLS_VPN; - if (safi == SAFI_ENCAP) - return IANA_SAFI_ENCAP; - if (safi == SAFI_EVPN) - return IANA_SAFI_EVPN; - if (safi == SAFI_LABELED_UNICAST) - return IANA_SAFI_LABELED_UNICAST; - return IANA_SAFI_RESERVED; + if (safi == SAFI_UNICAST) + return IANA_SAFI_UNICAST; + if (safi == SAFI_MULTICAST) + return IANA_SAFI_MULTICAST; + if (safi == SAFI_MPLS_VPN) + return IANA_SAFI_MPLS_VPN; + if (safi == SAFI_ENCAP) + return IANA_SAFI_ENCAP; + if (safi == SAFI_EVPN) + return IANA_SAFI_EVPN; + if (safi == SAFI_LABELED_UNICAST) + return IANA_SAFI_LABELED_UNICAST; + return IANA_SAFI_RESERVED; } #endif /* _ZEBRA_H */ diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index 2e195d0af..f198ac4af 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -51,1068 +51,1034 @@ unsigned char conf_debug_ospf6_abr; -int -ospf6_is_router_abr (struct ospf6 *o) +int ospf6_is_router_abr(struct ospf6 *o) { - struct listnode *node; - struct ospf6_area *oa; - int area_count = 0; + struct listnode *node; + struct ospf6_area *oa; + int area_count = 0; - for (ALL_LIST_ELEMENTS_RO (o->area_list, node, oa)) - if (IS_AREA_ENABLED (oa)) - area_count++; + for (ALL_LIST_ELEMENTS_RO(o->area_list, node, oa)) + if (IS_AREA_ENABLED(oa)) + area_count++; - if (area_count > 1) - return 1; - return 0; + if (area_count > 1) + return 1; + return 0; } -static int -ospf6_abr_nexthops_belong_to_area (struct ospf6_route *route, - struct ospf6_area *area) +static int ospf6_abr_nexthops_belong_to_area(struct ospf6_route *route, + struct ospf6_area *area) { - struct ospf6_interface *oi; - - oi = ospf6_interface_lookup_by_ifindex (ospf6_route_get_first_nh_index(route)); - if (oi && oi->area && oi->area == area) - return 1; - else - return 0; + struct ospf6_interface *oi; + + oi = ospf6_interface_lookup_by_ifindex( + ospf6_route_get_first_nh_index(route)); + if (oi && oi->area && oi->area == area) + return 1; + else + return 0; } -static void -ospf6_abr_delete_route (struct ospf6_route *range, struct ospf6_route *summary, - struct ospf6_route_table *summary_table, - struct ospf6_lsa *old) +static void ospf6_abr_delete_route(struct ospf6_route *range, + struct ospf6_route *summary, + struct ospf6_route_table *summary_table, + struct ospf6_lsa *old) { - if (summary) - { - ospf6_route_remove (summary, summary_table); - } + if (summary) { + ospf6_route_remove(summary, summary_table); + } - if (old && !OSPF6_LSA_IS_MAXAGE (old)) - ospf6_lsa_purge (old); + if (old && !OSPF6_LSA_IS_MAXAGE(old)) + ospf6_lsa_purge(old); } -void -ospf6_abr_enable_area (struct ospf6_area *area) +void ospf6_abr_enable_area(struct ospf6_area *area) { - struct ospf6_area *oa; - struct listnode *node, *nnode; + struct ospf6_area *oa; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (area->ospf6->area_list, node, nnode, oa)) - /* update B bit for each area */ - OSPF6_ROUTER_LSA_SCHEDULE (oa); + for (ALL_LIST_ELEMENTS(area->ospf6->area_list, node, nnode, oa)) + /* update B bit for each area */ + OSPF6_ROUTER_LSA_SCHEDULE(oa); } -void -ospf6_abr_disable_area (struct ospf6_area *area) +void ospf6_abr_disable_area(struct ospf6_area *area) { - struct ospf6_area *oa; - struct ospf6_route *ro, *nro; - struct ospf6_lsa *old; - struct listnode *node, *nnode; - - /* Withdraw all summary prefixes previously originated */ - for (ro = ospf6_route_head (area->summary_prefix); ro; ro = nro) - { - nro = ospf6_route_next (ro); - old = ospf6_lsdb_lookup (ro->path.origin.type, ro->path.origin.id, - area->ospf6->router_id, area->lsdb); - if (old) - ospf6_lsa_purge (old); - ospf6_route_remove (ro, area->summary_prefix); - } - - /* Withdraw all summary router-routes previously originated */ - for (ro = ospf6_route_head (area->summary_router); ro; ro = nro) - { - nro = ospf6_route_next (ro); - old = ospf6_lsdb_lookup (ro->path.origin.type, ro->path.origin.id, - area->ospf6->router_id, area->lsdb); - if (old) - ospf6_lsa_purge (old); - ospf6_route_remove (ro, area->summary_router); - } - - /* Schedule Router-LSA for each area (ABR status may change) */ - for (ALL_LIST_ELEMENTS (area->ospf6->area_list, node, nnode, oa)) - /* update B bit for each area */ - OSPF6_ROUTER_LSA_SCHEDULE (oa); + struct ospf6_area *oa; + struct ospf6_route *ro, *nro; + struct ospf6_lsa *old; + struct listnode *node, *nnode; + + /* Withdraw all summary prefixes previously originated */ + for (ro = ospf6_route_head(area->summary_prefix); ro; ro = nro) { + nro = ospf6_route_next(ro); + old = ospf6_lsdb_lookup(ro->path.origin.type, + ro->path.origin.id, + area->ospf6->router_id, area->lsdb); + if (old) + ospf6_lsa_purge(old); + ospf6_route_remove(ro, area->summary_prefix); + } + + /* Withdraw all summary router-routes previously originated */ + for (ro = ospf6_route_head(area->summary_router); ro; ro = nro) { + nro = ospf6_route_next(ro); + old = ospf6_lsdb_lookup(ro->path.origin.type, + ro->path.origin.id, + area->ospf6->router_id, area->lsdb); + if (old) + ospf6_lsa_purge(old); + ospf6_route_remove(ro, area->summary_router); + } + + /* Schedule Router-LSA for each area (ABR status may change) */ + for (ALL_LIST_ELEMENTS(area->ospf6->area_list, node, nnode, oa)) + /* update B bit for each area */ + OSPF6_ROUTER_LSA_SCHEDULE(oa); } /* RFC 2328 12.4.3. Summary-LSAs */ /* Returns 1 if a summary LSA has been generated for the area */ /* This is used by the area/range logic to add/remove blackhole routes */ -int -ospf6_abr_originate_summary_to_area (struct ospf6_route *route, - struct ospf6_area *area) +int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, + struct ospf6_area *area) { - struct ospf6_lsa *lsa, *old = NULL; - struct ospf6_route *summary, *range = NULL; - struct ospf6_area *route_area; - char buffer[OSPF6_MAX_LSASIZE]; - struct ospf6_lsa_header *lsa_header; - caddr_t p; - struct ospf6_inter_prefix_lsa *prefix_lsa; - struct ospf6_inter_router_lsa *router_lsa; - struct ospf6_route_table *summary_table = NULL; - u_int16_t type; - char buf[PREFIX2STR_BUFFER]; - int is_debug = 0; - - /* Only destination type network, range or ASBR are considered */ - if (route->type != OSPF6_DEST_TYPE_NETWORK && - route->type != OSPF6_DEST_TYPE_RANGE && - ((route->type != OSPF6_DEST_TYPE_ROUTER) || - !CHECK_FLAG (route->path.router_bits, OSPF6_ROUTER_BIT_E))) - { - if (is_debug) - zlog_debug ("Route type is none of network, range nor ASBR, ignore"); - return 0; - } - - /* AS External routes are never considered */ - if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1 || - route->path.type == OSPF6_PATH_TYPE_EXTERNAL2) - { - if (is_debug) - zlog_debug ("Path type is external, skip"); - return 0; - } - - /* do not generate if the path's area is the same as target area */ - if (route->path.area_id == area->area_id) - { - if (is_debug) - zlog_debug ("The route is in the area itself, ignore"); - return 0; - } - - /* do not generate if the nexthops belongs to the target area */ - if (ospf6_abr_nexthops_belong_to_area (route, area)) - { - if (is_debug) - zlog_debug ("The route's nexthop is in the same area, ignore"); - return 0; - } - - if (route->type == OSPF6_DEST_TYPE_ROUTER) - { - if (ADV_ROUTER_IN_PREFIX (&route->prefix) == area->ospf6->router_id) - { - inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)), buf, - sizeof (buf)); - zlog_debug ("%s: Skipping ASBR announcement for ABR (%s)", __func__, - buf); - return 0; + struct ospf6_lsa *lsa, *old = NULL; + struct ospf6_route *summary, *range = NULL; + struct ospf6_area *route_area; + char buffer[OSPF6_MAX_LSASIZE]; + struct ospf6_lsa_header *lsa_header; + caddr_t p; + struct ospf6_inter_prefix_lsa *prefix_lsa; + struct ospf6_inter_router_lsa *router_lsa; + struct ospf6_route_table *summary_table = NULL; + u_int16_t type; + char buf[PREFIX2STR_BUFFER]; + int is_debug = 0; + + /* Only destination type network, range or ASBR are considered */ + if (route->type != OSPF6_DEST_TYPE_NETWORK + && route->type != OSPF6_DEST_TYPE_RANGE + && ((route->type != OSPF6_DEST_TYPE_ROUTER) + || !CHECK_FLAG(route->path.router_bits, OSPF6_ROUTER_BIT_E))) { + if (is_debug) + zlog_debug( + "Route type is none of network, range nor ASBR, ignore"); + return 0; } - } - - if (route->type == OSPF6_DEST_TYPE_ROUTER) - { - if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_ORIGINATE (INTER_ROUTER)) - { - is_debug++; - inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)), - buf, sizeof (buf)); - zlog_debug ("Originating summary in area %s for ASBR %s", - area->name, buf); - } - summary_table = area->summary_router; - } - else - { - if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_ORIGINATE (INTER_PREFIX)) - { - is_debug++; - prefix2str (&route->prefix, buf, sizeof (buf)); - zlog_debug ("Originating summary in area %s for %s", - area->name, buf); - } - summary_table = area->summary_prefix; - } - - summary = ospf6_route_lookup (&route->prefix, summary_table); - if (summary) - old = ospf6_lsdb_lookup (summary->path.origin.type, - summary->path.origin.id, - area->ospf6->router_id, area->lsdb); - - /* if this route has just removed, remove corresponding LSA */ - if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE)) - { - if (is_debug) - zlog_debug ("The route has just removed, purge previous LSA"); - - if (route->type == OSPF6_DEST_TYPE_RANGE) - { - /* Whether the route have active longer prefix */ - if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) - { - if (is_debug) - zlog_debug ("The range is not active. withdraw"); - - ospf6_abr_delete_route (route, summary, summary_table, old); - } + + /* AS External routes are never considered */ + if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1 + || route->path.type == OSPF6_PATH_TYPE_EXTERNAL2) { + if (is_debug) + zlog_debug("Path type is external, skip"); + return 0; } - else - if (old) - ospf6_lsa_purge (old); - - return 0; - } - - if ((route->type == OSPF6_DEST_TYPE_ROUTER) && IS_AREA_STUB(area)) - { - if (is_debug) - zlog_debug ("Area has been stubbed, purge Inter-Router LSA"); - - ospf6_abr_delete_route (route, summary, summary_table, old); - return 0; - } - - if (area->no_summary && (route->path.subtype != OSPF6_PATH_SUBTYPE_DEFAULT_RT)) - { - if (is_debug) - zlog_debug ("Area has been stubbed, purge prefix LSA"); - - ospf6_abr_delete_route (route, summary, summary_table, old); - return 0; - } - - /* do not generate if the route cost is greater or equal to LSInfinity */ - if (route->path.cost >= OSPF_LS_INFINITY) - { - /* When we're clearing the range route because all active prefixes - * under the range are gone, we set the range's cost to - * OSPF_AREA_RANGE_COST_UNSPEC, which is > OSPF_LS_INFINITY. We - * don't want to trigger the code here for that. This code is for - * handling routes that have gone to infinity. The range removal happens - * elsewhere. - */ - if ((route->type != OSPF6_DEST_TYPE_RANGE) && - (route->path.cost != OSPF_AREA_RANGE_COST_UNSPEC)) - { - if (is_debug) - zlog_debug ("The cost exceeds LSInfinity, withdraw"); - if (old) - ospf6_lsa_purge (old); - return 0; + + /* do not generate if the path's area is the same as target area */ + if (route->path.area_id == area->area_id) { + if (is_debug) + zlog_debug("The route is in the area itself, ignore"); + return 0; + } + + /* do not generate if the nexthops belongs to the target area */ + if (ospf6_abr_nexthops_belong_to_area(route, area)) { + if (is_debug) + zlog_debug( + "The route's nexthop is in the same area, ignore"); + return 0; + } + + if (route->type == OSPF6_DEST_TYPE_ROUTER) { + if (ADV_ROUTER_IN_PREFIX(&route->prefix) + == area->ospf6->router_id) { + inet_ntop(AF_INET, + &(ADV_ROUTER_IN_PREFIX(&route->prefix)), buf, + sizeof(buf)); + zlog_debug( + "%s: Skipping ASBR announcement for ABR (%s)", + __func__, buf); + return 0; + } + } + + if (route->type == OSPF6_DEST_TYPE_ROUTER) { + if (IS_OSPF6_DEBUG_ABR + || IS_OSPF6_DEBUG_ORIGINATE(INTER_ROUTER)) { + is_debug++; + inet_ntop(AF_INET, + &(ADV_ROUTER_IN_PREFIX(&route->prefix)), buf, + sizeof(buf)); + zlog_debug("Originating summary in area %s for ASBR %s", + area->name, buf); + } + summary_table = area->summary_router; + } else { + if (IS_OSPF6_DEBUG_ABR + || IS_OSPF6_DEBUG_ORIGINATE(INTER_PREFIX)) { + is_debug++; + prefix2str(&route->prefix, buf, sizeof(buf)); + zlog_debug("Originating summary in area %s for %s", + area->name, buf); + } + summary_table = area->summary_prefix; + } + + summary = ospf6_route_lookup(&route->prefix, summary_table); + if (summary) + old = ospf6_lsdb_lookup(summary->path.origin.type, + summary->path.origin.id, + area->ospf6->router_id, area->lsdb); + + /* if this route has just removed, remove corresponding LSA */ + if (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE)) { + if (is_debug) + zlog_debug( + "The route has just removed, purge previous LSA"); + + if (route->type == OSPF6_DEST_TYPE_RANGE) { + /* Whether the route have active longer prefix */ + if (!CHECK_FLAG(route->flag, + OSPF6_ROUTE_ACTIVE_SUMMARY)) { + if (is_debug) + zlog_debug( + "The range is not active. withdraw"); + + ospf6_abr_delete_route(route, summary, + summary_table, old); + } + } else if (old) + ospf6_lsa_purge(old); + + return 0; + } + + if ((route->type == OSPF6_DEST_TYPE_ROUTER) && IS_AREA_STUB(area)) { + if (is_debug) + zlog_debug( + "Area has been stubbed, purge Inter-Router LSA"); + + ospf6_abr_delete_route(route, summary, summary_table, old); + return 0; + } + + if (area->no_summary + && (route->path.subtype != OSPF6_PATH_SUBTYPE_DEFAULT_RT)) { + if (is_debug) + zlog_debug("Area has been stubbed, purge prefix LSA"); + + ospf6_abr_delete_route(route, summary, summary_table, old); + return 0; + } + + /* do not generate if the route cost is greater or equal to LSInfinity + */ + if (route->path.cost >= OSPF_LS_INFINITY) { + /* When we're clearing the range route because all active + * prefixes + * under the range are gone, we set the range's cost to + * OSPF_AREA_RANGE_COST_UNSPEC, which is > OSPF_LS_INFINITY. We + * don't want to trigger the code here for that. This code is + * for + * handling routes that have gone to infinity. The range removal + * happens + * elsewhere. + */ + if ((route->type != OSPF6_DEST_TYPE_RANGE) + && (route->path.cost != OSPF_AREA_RANGE_COST_UNSPEC)) { + if (is_debug) + zlog_debug( + "The cost exceeds LSInfinity, withdraw"); + if (old) + ospf6_lsa_purge(old); + return 0; + } + } + + /* if this is a route to ASBR */ + if (route->type == OSPF6_DEST_TYPE_ROUTER) { + /* Only the prefered best path is considered */ + if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_BEST)) { + if (is_debug) + zlog_debug( + "This is the secondary path to the ASBR, ignore"); + ospf6_abr_delete_route(route, summary, summary_table, + old); + return 0; + } + + /* Do not generate if the area is stub */ + /* XXX */ + } + + /* if this is an intra-area route, this may be suppressed by aggregation + */ + if (route->type == OSPF6_DEST_TYPE_NETWORK + && route->path.type == OSPF6_PATH_TYPE_INTRA) { + /* search for configured address range for the route's area */ + route_area = + ospf6_area_lookup(route->path.area_id, area->ospf6); + assert(route_area); + range = ospf6_route_lookup_bestmatch(&route->prefix, + route_area->range_table); + + /* ranges are ignored when originate backbone routes to transit + area. + Otherwise, if ranges are configured, the route is suppressed. + */ + if (range && !CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE) + && (route->path.area_id != OSPF_AREA_BACKBONE + || !IS_AREA_TRANSIT(area))) { + if (is_debug) { + prefix2str(&range->prefix, buf, sizeof(buf)); + zlog_debug("Suppressed by range %s of area %s", + buf, route_area->name); + } + ospf6_abr_delete_route(route, summary, summary_table, + old); + return 0; + } + } + + /* If this is a configured address range */ + if (route->type == OSPF6_DEST_TYPE_RANGE) { + /* If DoNotAdvertise is set */ + if (CHECK_FLAG(route->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) { + if (is_debug) + zlog_debug( + "This is the range with DoNotAdvertise set. ignore"); + ospf6_abr_delete_route(route, summary, summary_table, + old); + return 0; + } + + /* If there are no active prefixes in this range, remove */ + if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) { + if (is_debug) + zlog_debug("The range is not active. withdraw"); + ospf6_abr_delete_route(route, summary, summary_table, + old); + return 0; + } + } + + /* Check export list */ + if (EXPORT_NAME(area)) { + if (EXPORT_LIST(area) == NULL) + EXPORT_LIST(area) = + access_list_lookup(AFI_IP6, EXPORT_NAME(area)); + + if (EXPORT_LIST(area)) + if (access_list_apply(EXPORT_LIST(area), &route->prefix) + == FILTER_DENY) { + if (is_debug) { + inet_ntop(AF_INET, + &(ADV_ROUTER_IN_PREFIX( + &route->prefix)), + buf, sizeof(buf)); + zlog_debug( + "prefix %s was denied by export list", + buf); + } + return 0; + } + } + + /* Check filter-list */ + if (PREFIX_NAME_OUT(area)) { + if (PREFIX_LIST_OUT(area) == NULL) + PREFIX_LIST_OUT(area) = prefix_list_lookup( + AFI_IP6, PREFIX_NAME_OUT(area)); + + if (PREFIX_LIST_OUT(area)) + if (prefix_list_apply(PREFIX_LIST_OUT(area), + &route->prefix) + != PREFIX_PERMIT) { + if (is_debug) { + inet_ntop(AF_INET, + &(ADV_ROUTER_IN_PREFIX( + &route->prefix)), + buf, sizeof(buf)); + zlog_debug( + "prefix %s was denied by filter-list out", + buf); + } + return 0; + } } - } - - /* if this is a route to ASBR */ - if (route->type == OSPF6_DEST_TYPE_ROUTER) - { - /* Only the prefered best path is considered */ - if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST)) - { - if (is_debug) - zlog_debug ("This is the secondary path to the ASBR, ignore"); - ospf6_abr_delete_route (route, summary, summary_table, old); - return 0; - } - - /* Do not generate if the area is stub */ - /* XXX */ - } - - /* if this is an intra-area route, this may be suppressed by aggregation */ - if (route->type == OSPF6_DEST_TYPE_NETWORK && - route->path.type == OSPF6_PATH_TYPE_INTRA) - { - /* search for configured address range for the route's area */ - route_area = ospf6_area_lookup (route->path.area_id, area->ospf6); - assert (route_area); - range = ospf6_route_lookup_bestmatch (&route->prefix, - route_area->range_table); - - /* ranges are ignored when originate backbone routes to transit area. - Otherwise, if ranges are configured, the route is suppressed. */ - if (range && ! CHECK_FLAG (range->flag, OSPF6_ROUTE_REMOVE) && - (route->path.area_id != OSPF_AREA_BACKBONE || - ! IS_AREA_TRANSIT (area))) - { - if (is_debug) - { - prefix2str (&range->prefix, buf, sizeof (buf)); - zlog_debug ("Suppressed by range %s of area %s", - buf, route_area->name); - } - ospf6_abr_delete_route (route, summary, summary_table, old); - return 0; - } - } - - /* If this is a configured address range */ - if (route->type == OSPF6_DEST_TYPE_RANGE) - { - /* If DoNotAdvertise is set */ - if (CHECK_FLAG (route->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) - { - if (is_debug) - zlog_debug ("This is the range with DoNotAdvertise set. ignore"); - ospf6_abr_delete_route (route, summary, summary_table, old); - return 0; - } - - /* If there are no active prefixes in this range, remove */ - if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) - { - if (is_debug) - zlog_debug ("The range is not active. withdraw"); - ospf6_abr_delete_route (route, summary, summary_table, old); - return 0; - } - } - - /* Check export list */ - if (EXPORT_NAME (area)) - { - if (EXPORT_LIST (area) == NULL) - EXPORT_LIST (area) = - access_list_lookup (AFI_IP6, EXPORT_NAME (area)); - - if (EXPORT_LIST (area)) - if (access_list_apply (EXPORT_LIST (area), - &route->prefix) == FILTER_DENY) - { - if (is_debug) - { - inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)), - buf, sizeof(buf)); - zlog_debug ("prefix %s was denied by export list", buf); - } - return 0; - } - } - - /* Check filter-list */ - if (PREFIX_NAME_OUT (area)) - { - if (PREFIX_LIST_OUT (area) == NULL) - PREFIX_LIST_OUT (area) = - prefix_list_lookup(AFI_IP6, PREFIX_NAME_OUT (area)); - - if (PREFIX_LIST_OUT (area)) - if (prefix_list_apply (PREFIX_LIST_OUT (area), - &route->prefix) != PREFIX_PERMIT) - { - if (is_debug) - { - inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)), - buf, sizeof (buf)); - zlog_debug ("prefix %s was denied by filter-list out", buf); - } - return 0; - } - } - - /* the route is going to be originated. store it in area's summary_table */ - if (summary == NULL) - { - summary = ospf6_route_copy (route); - summary->path.origin.adv_router = area->ospf6->router_id; - - if (route->type == OSPF6_DEST_TYPE_ROUTER) - { - summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_ROUTER); - summary->path.origin.id = ADV_ROUTER_IN_PREFIX (&route->prefix); + + /* the route is going to be originated. store it in area's summary_table + */ + if (summary == NULL) { + summary = ospf6_route_copy(route); + summary->path.origin.adv_router = area->ospf6->router_id; + + if (route->type == OSPF6_DEST_TYPE_ROUTER) { + summary->path.origin.type = + htons(OSPF6_LSTYPE_INTER_ROUTER); + summary->path.origin.id = + ADV_ROUTER_IN_PREFIX(&route->prefix); + } else { + summary->path.origin.type = + htons(OSPF6_LSTYPE_INTER_PREFIX); + summary->path.origin.id = ospf6_new_ls_id( + summary->path.origin.type, + summary->path.origin.adv_router, area->lsdb); + } + summary = ospf6_route_add(summary, summary_table); + } else { + summary->type = route->type; + monotime(&summary->changed); } - else - { - summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX); - summary->path.origin.id = - ospf6_new_ls_id (summary->path.origin.type, - summary->path.origin.adv_router, area->lsdb); + + summary->path.router_bits = route->path.router_bits; + summary->path.options[0] = route->path.options[0]; + summary->path.options[1] = route->path.options[1]; + summary->path.options[2] = route->path.options[2]; + summary->path.prefix_options = route->path.prefix_options; + summary->path.area_id = area->area_id; + summary->path.type = OSPF6_PATH_TYPE_INTER; + summary->path.subtype = route->path.subtype; + summary->path.cost = route->path.cost; + /* summary->nexthop[0] = route->nexthop[0]; */ + + /* prepare buffer */ + memset(buffer, 0, sizeof(buffer)); + lsa_header = (struct ospf6_lsa_header *)buffer; + + if (route->type == OSPF6_DEST_TYPE_ROUTER) { + router_lsa = (struct ospf6_inter_router_lsa + *)((caddr_t)lsa_header + + sizeof(struct ospf6_lsa_header)); + p = (caddr_t)router_lsa + sizeof(struct ospf6_inter_router_lsa); + + /* Fill Inter-Area-Router-LSA */ + router_lsa->options[0] = route->path.options[0]; + router_lsa->options[1] = route->path.options[1]; + router_lsa->options[2] = route->path.options[2]; + OSPF6_ABR_SUMMARY_METRIC_SET(router_lsa, route->path.cost); + router_lsa->router_id = ADV_ROUTER_IN_PREFIX(&route->prefix); + type = htons(OSPF6_LSTYPE_INTER_ROUTER); + } else { + prefix_lsa = (struct ospf6_inter_prefix_lsa + *)((caddr_t)lsa_header + + sizeof(struct ospf6_lsa_header)); + p = (caddr_t)prefix_lsa + sizeof(struct ospf6_inter_prefix_lsa); + + /* Fill Inter-Area-Prefix-LSA */ + OSPF6_ABR_SUMMARY_METRIC_SET(prefix_lsa, route->path.cost); + prefix_lsa->prefix.prefix_length = route->prefix.prefixlen; + prefix_lsa->prefix.prefix_options = route->path.prefix_options; + + /* set Prefix */ + memcpy(p, &route->prefix.u.prefix6, + OSPF6_PREFIX_SPACE(route->prefix.prefixlen)); + ospf6_prefix_apply_mask(&prefix_lsa->prefix); + p += OSPF6_PREFIX_SPACE(route->prefix.prefixlen); + type = htons(OSPF6_LSTYPE_INTER_PREFIX); } - summary = ospf6_route_add (summary, summary_table); - } - else - { - summary->type = route->type; - monotime(&summary->changed); - } - - summary->path.router_bits = route->path.router_bits; - summary->path.options[0] = route->path.options[0]; - summary->path.options[1] = route->path.options[1]; - summary->path.options[2] = route->path.options[2]; - summary->path.prefix_options = route->path.prefix_options; - summary->path.area_id = area->area_id; - summary->path.type = OSPF6_PATH_TYPE_INTER; - summary->path.subtype = route->path.subtype; - summary->path.cost = route->path.cost; - /* summary->nexthop[0] = route->nexthop[0]; */ - - /* prepare buffer */ - memset (buffer, 0, sizeof (buffer)); - lsa_header = (struct ospf6_lsa_header *) buffer; - - if (route->type == OSPF6_DEST_TYPE_ROUTER) - { - router_lsa = (struct ospf6_inter_router_lsa *) - ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); - p = (caddr_t) router_lsa + sizeof (struct ospf6_inter_router_lsa); - - /* Fill Inter-Area-Router-LSA */ - router_lsa->options[0] = route->path.options[0]; - router_lsa->options[1] = route->path.options[1]; - router_lsa->options[2] = route->path.options[2]; - OSPF6_ABR_SUMMARY_METRIC_SET (router_lsa, route->path.cost); - router_lsa->router_id = ADV_ROUTER_IN_PREFIX (&route->prefix); - type = htons (OSPF6_LSTYPE_INTER_ROUTER); - } - else - { - prefix_lsa = (struct ospf6_inter_prefix_lsa *) - ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); - p = (caddr_t) prefix_lsa + sizeof (struct ospf6_inter_prefix_lsa); - - /* Fill Inter-Area-Prefix-LSA */ - OSPF6_ABR_SUMMARY_METRIC_SET (prefix_lsa, route->path.cost); - prefix_lsa->prefix.prefix_length = route->prefix.prefixlen; - prefix_lsa->prefix.prefix_options = route->path.prefix_options; - - /* set Prefix */ - memcpy (p, &route->prefix.u.prefix6, - OSPF6_PREFIX_SPACE (route->prefix.prefixlen)); - ospf6_prefix_apply_mask (&prefix_lsa->prefix); - p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen); - type = htons (OSPF6_LSTYPE_INTER_PREFIX); - } - - /* Fill LSA Header */ - lsa_header->age = 0; - lsa_header->type = type; - lsa_header->id = summary->path.origin.id; - lsa_header->adv_router = area->ospf6->router_id; - lsa_header->seqnum = - ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id, - lsa_header->adv_router, area->lsdb); - lsa_header->length = htons ((caddr_t) p - (caddr_t) lsa_header); - - /* LSA checksum */ - ospf6_lsa_checksum (lsa_header); - - /* create LSA */ - lsa = ospf6_lsa_create (lsa_header); - - /* Originate */ - ospf6_lsa_originate_area (lsa, area); - - return 1; + + /* Fill LSA Header */ + lsa_header->age = 0; + lsa_header->type = type; + lsa_header->id = summary->path.origin.id; + lsa_header->adv_router = area->ospf6->router_id; + lsa_header->seqnum = + ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id, + lsa_header->adv_router, area->lsdb); + lsa_header->length = htons((caddr_t)p - (caddr_t)lsa_header); + + /* LSA checksum */ + ospf6_lsa_checksum(lsa_header); + + /* create LSA */ + lsa = ospf6_lsa_create(lsa_header); + + /* Originate */ + ospf6_lsa_originate_area(lsa, area); + + return 1; } -void -ospf6_abr_range_reset_cost (struct ospf6 *ospf6) +void ospf6_abr_range_reset_cost(struct ospf6 *ospf6) { - struct listnode *node, *nnode; - struct ospf6_area *oa; - struct ospf6_route *range; - - for (ALL_LIST_ELEMENTS (ospf6->area_list, node, nnode, oa)) - for (range = ospf6_route_head (oa->range_table); range; - range = ospf6_route_next (range)) - OSPF6_ABR_RANGE_CLEAR_COST(range); + struct listnode *node, *nnode; + struct ospf6_area *oa; + struct ospf6_route *range; + + for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) + for (range = ospf6_route_head(oa->range_table); range; + range = ospf6_route_next(range)) + OSPF6_ABR_RANGE_CLEAR_COST(range); } -static inline u_int32_t -ospf6_abr_range_compute_cost (struct ospf6_route *range, struct ospf6 *o) +static inline u_int32_t ospf6_abr_range_compute_cost(struct ospf6_route *range, + struct ospf6 *o) { - struct ospf6_route *ro; - u_int32_t cost = 0; - - for (ro = ospf6_route_match_head (&range->prefix, o->route_table); - ro; ro = ospf6_route_match_next (&range->prefix, ro)) - { - if (ro->path.area_id == range->path.area_id && - (ro->path.type == OSPF6_PATH_TYPE_INTRA) && - ! CHECK_FLAG (ro->flag, OSPF6_ROUTE_REMOVE)) - cost = MAX (cost, ro->path.cost); - } - - return cost; + struct ospf6_route *ro; + u_int32_t cost = 0; + + for (ro = ospf6_route_match_head(&range->prefix, o->route_table); ro; + ro = ospf6_route_match_next(&range->prefix, ro)) { + if (ro->path.area_id == range->path.area_id + && (ro->path.type == OSPF6_PATH_TYPE_INTRA) + && !CHECK_FLAG(ro->flag, OSPF6_ROUTE_REMOVE)) + cost = MAX(cost, ro->path.cost); + } + + return cost; } static inline int -ospf6_abr_range_summary_needs_update (struct ospf6_route *range, - u_int32_t cost) +ospf6_abr_range_summary_needs_update(struct ospf6_route *range, u_int32_t cost) { - int redo_summary = 0; - - if (CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE)) - { - UNSET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY); - redo_summary = 1; - } - else if (CHECK_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) - { - if (range->path.cost != 0) - { - range->path.cost = 0; - redo_summary = 1; - } - } - else if (cost) - { - if ((OSPF6_PATH_COST_IS_CONFIGURED(range->path) && - range->path.cost != range->path.u.cost_config)) - { - range->path.cost = range->path.u.cost_config; - SET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY); - redo_summary = 1; + int redo_summary = 0; + + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE)) { + UNSET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY); + redo_summary = 1; + } else if (CHECK_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) { + if (range->path.cost != 0) { + range->path.cost = 0; + redo_summary = 1; + } + } else if (cost) { + if ((OSPF6_PATH_COST_IS_CONFIGURED(range->path) + && range->path.cost != range->path.u.cost_config)) { + range->path.cost = range->path.u.cost_config; + SET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY); + redo_summary = 1; + } else if (!OSPF6_PATH_COST_IS_CONFIGURED(range->path) + && range->path.cost != cost) { + range->path.cost = cost; + SET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY); + redo_summary = 1; + } + } else if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) { + /* Cost is zero, meaning no active range */ + UNSET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY); + range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC; + redo_summary = 1; } - else if (!OSPF6_PATH_COST_IS_CONFIGURED(range->path) && - range->path.cost != cost) - { - range->path.cost = cost; - SET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY); - redo_summary = 1; - } - } - else if (CHECK_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) - { - /* Cost is zero, meaning no active range */ - UNSET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY); - range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC; - redo_summary = 1; - } - - return (redo_summary); + + return (redo_summary); } -static void -ospf6_abr_range_update (struct ospf6_route *range) +static void ospf6_abr_range_update(struct ospf6_route *range) { - u_int32_t cost = 0; - struct listnode *node, *nnode; - struct ospf6_area *oa; - int summary_orig = 0; - - assert (range->type == OSPF6_DEST_TYPE_RANGE); - - /* update range's cost and active flag */ - cost = ospf6_abr_range_compute_cost (range, ospf6); - - /* Non-zero cost is a proxy for active longer prefixes in this range. - * If there are active routes covered by this range AND either the configured - * cost has changed or the summarized cost has changed then redo summaries. - * Alternately, if there are no longer active prefixes and there are - * summary announcements, withdraw those announcements. - * - * The don't advertise code relies on the path.cost being set to UNSPEC to - * work the first time. Subsequent times the path.cost is not 0 anyway if there - * were active ranges. - */ - - if (ospf6_abr_range_summary_needs_update (range, cost)) - { - for (ALL_LIST_ELEMENTS (ospf6->area_list, node, nnode, oa)) - summary_orig += ospf6_abr_originate_summary_to_area (range, oa); - - if (CHECK_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY) && summary_orig) - { - if (! CHECK_FLAG (range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) - { - if (IS_OSPF6_DEBUG_ABR) - zlog_debug ("Add discard route"); - - ospf6_zebra_add_discard (range); - } + u_int32_t cost = 0; + struct listnode *node, *nnode; + struct ospf6_area *oa; + int summary_orig = 0; + + assert(range->type == OSPF6_DEST_TYPE_RANGE); + + /* update range's cost and active flag */ + cost = ospf6_abr_range_compute_cost(range, ospf6); + + /* Non-zero cost is a proxy for active longer prefixes in this range. + * If there are active routes covered by this range AND either the + * configured + * cost has changed or the summarized cost has changed then redo + * summaries. + * Alternately, if there are no longer active prefixes and there are + * summary announcements, withdraw those announcements. + * + * The don't advertise code relies on the path.cost being set to UNSPEC + * to + * work the first time. Subsequent times the path.cost is not 0 anyway + * if there + * were active ranges. + */ + + if (ospf6_abr_range_summary_needs_update(range, cost)) { + for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) + summary_orig += + ospf6_abr_originate_summary_to_area(range, oa); + + if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY) + && summary_orig) { + if (!CHECK_FLAG(range->flag, + OSPF6_ROUTE_BLACKHOLE_ADDED)) { + if (IS_OSPF6_DEBUG_ABR) + zlog_debug("Add discard route"); + + ospf6_zebra_add_discard(range); + } + } else { + /* Summary removed or no summary generated as no + * specifics exist */ + if (CHECK_FLAG(range->flag, + OSPF6_ROUTE_BLACKHOLE_ADDED)) { + if (IS_OSPF6_DEBUG_ABR) + zlog_debug("Delete discard route"); + + ospf6_zebra_delete_discard(range); + } + } } - else - { - /* Summary removed or no summary generated as no specifics exist */ - if (CHECK_FLAG (range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) - { - if (IS_OSPF6_DEBUG_ABR) - zlog_debug ("Delete discard route"); - - ospf6_zebra_delete_discard (range); - } - } - } } -void -ospf6_abr_originate_summary (struct ospf6_route *route) +void ospf6_abr_originate_summary(struct ospf6_route *route) { - struct listnode *node, *nnode; - struct ospf6_area *oa; - struct ospf6_route *range = NULL; - - if (route->type == OSPF6_DEST_TYPE_NETWORK) - { - oa = ospf6_area_lookup (route->path.area_id, ospf6); - range = ospf6_route_lookup_bestmatch (&route->prefix, oa->range_table); - if (range) - { - ospf6_abr_range_update (range); + struct listnode *node, *nnode; + struct ospf6_area *oa; + struct ospf6_route *range = NULL; + + if (route->type == OSPF6_DEST_TYPE_NETWORK) { + oa = ospf6_area_lookup(route->path.area_id, ospf6); + range = ospf6_route_lookup_bestmatch(&route->prefix, + oa->range_table); + if (range) { + ospf6_abr_range_update(range); + } } - } - for (ALL_LIST_ELEMENTS (ospf6->area_list, node, nnode, oa)) - ospf6_abr_originate_summary_to_area (route, oa); + for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) + ospf6_abr_originate_summary_to_area(route, oa); } -void -ospf6_abr_defaults_to_stub (struct ospf6 *o) +void ospf6_abr_defaults_to_stub(struct ospf6 *o) { - struct listnode *node, *nnode; - struct ospf6_area *oa; - struct ospf6_route *def, *route; - - if (!o->backbone) - return; - - def = ospf6_route_create(); - def->type = OSPF6_DEST_TYPE_NETWORK; - def->prefix.family = AF_INET6; - def->prefix.prefixlen = 0; - memset (&def->prefix.u.prefix6, 0, sizeof(struct in6_addr)); - def->type = OSPF6_DEST_TYPE_NETWORK; - def->path.type = OSPF6_PATH_TYPE_INTER; - def->path.subtype = OSPF6_PATH_SUBTYPE_DEFAULT_RT; - def->path.area_id = o->backbone->area_id; - - for (ALL_LIST_ELEMENTS (ospf6->area_list, node, nnode, oa)) - { - if (!IS_AREA_STUB (oa)) - { - /* withdraw defaults when an area switches from stub to non-stub */ - route = ospf6_route_lookup (&def->prefix, oa->summary_prefix); - if (route && (route->path.subtype == def->path.subtype)) - { - if (IS_OSPF6_DEBUG_ABR) - zlog_debug ("Withdrawing default route from non-stubby area %s", - oa->name); - SET_FLAG (def->flag, OSPF6_ROUTE_REMOVE); - ospf6_abr_originate_summary_to_area (def, oa); - } - } - else - { - /* announce defaults to stubby areas */ - if (IS_OSPF6_DEBUG_ABR) - zlog_debug ("Announcing default route into stubby area %s", - oa->name); - UNSET_FLAG (def->flag, OSPF6_ROUTE_REMOVE); - ospf6_abr_originate_summary_to_area (def, oa); + struct listnode *node, *nnode; + struct ospf6_area *oa; + struct ospf6_route *def, *route; + + if (!o->backbone) + return; + + def = ospf6_route_create(); + def->type = OSPF6_DEST_TYPE_NETWORK; + def->prefix.family = AF_INET6; + def->prefix.prefixlen = 0; + memset(&def->prefix.u.prefix6, 0, sizeof(struct in6_addr)); + def->type = OSPF6_DEST_TYPE_NETWORK; + def->path.type = OSPF6_PATH_TYPE_INTER; + def->path.subtype = OSPF6_PATH_SUBTYPE_DEFAULT_RT; + def->path.area_id = o->backbone->area_id; + + for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) { + if (!IS_AREA_STUB(oa)) { + /* withdraw defaults when an area switches from stub to + * non-stub */ + route = ospf6_route_lookup(&def->prefix, + oa->summary_prefix); + if (route + && (route->path.subtype == def->path.subtype)) { + if (IS_OSPF6_DEBUG_ABR) + zlog_debug( + "Withdrawing default route from non-stubby area %s", + oa->name); + SET_FLAG(def->flag, OSPF6_ROUTE_REMOVE); + ospf6_abr_originate_summary_to_area(def, oa); + } + } else { + /* announce defaults to stubby areas */ + if (IS_OSPF6_DEBUG_ABR) + zlog_debug( + "Announcing default route into stubby area %s", + oa->name); + UNSET_FLAG(def->flag, OSPF6_ROUTE_REMOVE); + ospf6_abr_originate_summary_to_area(def, oa); + } } - } - ospf6_route_delete (def); + ospf6_route_delete(def); } /* RFC 2328 16.2. Calculating the inter-area routes */ -void -ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa) +void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) { - struct prefix prefix, abr_prefix; - struct ospf6_route_table *table = NULL; - struct ospf6_route *range, *route, *old = NULL; - struct ospf6_route *abr_entry; - u_char type = 0; - char options[3] = {0, 0, 0}; - u_int8_t prefix_options = 0; - u_int32_t cost = 0; - u_char router_bits = 0; - char buf[PREFIX2STR_BUFFER]; - int is_debug = 0; - struct ospf6_inter_prefix_lsa *prefix_lsa = NULL; - struct ospf6_inter_router_lsa *router_lsa = NULL; - - memset (&prefix, 0, sizeof (prefix)); - - if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX)) - { - if (IS_OSPF6_DEBUG_EXAMIN (INTER_PREFIX)) - { - is_debug++; - zlog_debug ("Examin %s in area %s", lsa->name, oa->name); - } - - prefix_lsa = (struct ospf6_inter_prefix_lsa *) - OSPF6_LSA_HEADER_END (lsa->header); - prefix.family = AF_INET6; - prefix.prefixlen = prefix_lsa->prefix.prefix_length; - ospf6_prefix_in6_addr (&prefix.u.prefix6, &prefix_lsa->prefix); - if (is_debug) - prefix2str (&prefix, buf, sizeof (buf)); - table = oa->ospf6->route_table; - type = OSPF6_DEST_TYPE_NETWORK; - prefix_options = prefix_lsa->prefix.prefix_options; - cost = OSPF6_ABR_SUMMARY_METRIC (prefix_lsa); - } - else if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER)) - { - if (IS_OSPF6_DEBUG_EXAMIN (INTER_ROUTER)) - { - is_debug++; - zlog_debug ("Examin %s in area %s", lsa->name, oa->name); - } - - router_lsa = (struct ospf6_inter_router_lsa *) - OSPF6_LSA_HEADER_END (lsa->header); - ospf6_linkstate_prefix (router_lsa->router_id, htonl (0), &prefix); - if (is_debug) - inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf)); - - table = oa->ospf6->brouter_table; - type = OSPF6_DEST_TYPE_ROUTER; - options[0] = router_lsa->options[0]; - options[1] = router_lsa->options[1]; - options[2] = router_lsa->options[2]; - cost = OSPF6_ABR_SUMMARY_METRIC (router_lsa); - SET_FLAG (router_bits, OSPF6_ROUTER_BIT_E); - } - else - assert (0); - - /* Find existing route */ - route = ospf6_route_lookup (&prefix, table); - if (route) - ospf6_route_lock (route); - while (route && ospf6_route_is_prefix (&prefix, route)) - { - if (route->path.area_id == oa->area_id && - route->path.origin.type == lsa->header->type && - route->path.origin.id == lsa->header->id && - route->path.origin.adv_router == lsa->header->adv_router && - ! CHECK_FLAG (route->flag, OSPF6_ROUTE_WAS_REMOVED)) - old = route; - route = ospf6_route_next (route); - } - if (route) - ospf6_route_unlock (route); - - /* (1) if cost == LSInfinity or if the LSA is MaxAge */ - if (cost == OSPF_LS_INFINITY) - { - if (is_debug) - zlog_debug ("cost is LS_INFINITY, ignore"); - if (old) - ospf6_route_remove (old, table); - return; - } - if (OSPF6_LSA_IS_MAXAGE (lsa)) - { - if (is_debug) - zlog_debug ("LSA is MaxAge, ignore"); - if (old) - ospf6_route_remove (old, table); - return; - } - - /* (2) if the LSA is self-originated, ignore */ - if (lsa->header->adv_router == oa->ospf6->router_id) - { - if (is_debug) - zlog_debug ("LSA is self-originated, ignore"); - if (old) - ospf6_route_remove (old, table); - return; - } - - /* (3) if the prefix is equal to an active configured address range */ - /* or if the NU bit is set in the prefix */ - if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX)) - { - range = ospf6_route_lookup (&prefix, oa->range_table); - if (range) - { - if (is_debug) - zlog_debug ("Prefix is equal to address range, ignore"); - if (old) - ospf6_route_remove (old, table); - return; - } - - if (CHECK_FLAG (prefix_lsa->prefix.prefix_options, - OSPF6_PREFIX_OPTION_NU) || - CHECK_FLAG (prefix_lsa->prefix.prefix_options, - OSPF6_PREFIX_OPTION_LA)) - { - if (is_debug) - zlog_debug ("Prefix has NU/LA bit set, ignore"); - if (old) - ospf6_route_remove (old, table); - return; + struct prefix prefix, abr_prefix; + struct ospf6_route_table *table = NULL; + struct ospf6_route *range, *route, *old = NULL; + struct ospf6_route *abr_entry; + u_char type = 0; + char options[3] = {0, 0, 0}; + u_int8_t prefix_options = 0; + u_int32_t cost = 0; + u_char router_bits = 0; + char buf[PREFIX2STR_BUFFER]; + int is_debug = 0; + struct ospf6_inter_prefix_lsa *prefix_lsa = NULL; + struct ospf6_inter_router_lsa *router_lsa = NULL; + + memset(&prefix, 0, sizeof(prefix)); + + if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) { + if (IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX)) { + is_debug++; + zlog_debug("Examin %s in area %s", lsa->name, oa->name); + } + + prefix_lsa = + (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END( + lsa->header); + prefix.family = AF_INET6; + prefix.prefixlen = prefix_lsa->prefix.prefix_length; + ospf6_prefix_in6_addr(&prefix.u.prefix6, &prefix_lsa->prefix); + if (is_debug) + prefix2str(&prefix, buf, sizeof(buf)); + table = oa->ospf6->route_table; + type = OSPF6_DEST_TYPE_NETWORK; + prefix_options = prefix_lsa->prefix.prefix_options; + cost = OSPF6_ABR_SUMMARY_METRIC(prefix_lsa); + } else if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) { + if (IS_OSPF6_DEBUG_EXAMIN(INTER_ROUTER)) { + is_debug++; + zlog_debug("Examin %s in area %s", lsa->name, oa->name); + } + + router_lsa = + (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END( + lsa->header); + ospf6_linkstate_prefix(router_lsa->router_id, htonl(0), + &prefix); + if (is_debug) + inet_ntop(AF_INET, &router_lsa->router_id, buf, + sizeof(buf)); + + table = oa->ospf6->brouter_table; + type = OSPF6_DEST_TYPE_ROUTER; + options[0] = router_lsa->options[0]; + options[1] = router_lsa->options[1]; + options[2] = router_lsa->options[2]; + cost = OSPF6_ABR_SUMMARY_METRIC(router_lsa); + SET_FLAG(router_bits, OSPF6_ROUTER_BIT_E); + } else + assert(0); + + /* Find existing route */ + route = ospf6_route_lookup(&prefix, table); + if (route) + ospf6_route_lock(route); + while (route && ospf6_route_is_prefix(&prefix, route)) { + if (route->path.area_id == oa->area_id + && route->path.origin.type == lsa->header->type + && route->path.origin.id == lsa->header->id + && route->path.origin.adv_router == lsa->header->adv_router + && !CHECK_FLAG(route->flag, OSPF6_ROUTE_WAS_REMOVED)) + old = route; + route = ospf6_route_next(route); + } + if (route) + ospf6_route_unlock(route); + + /* (1) if cost == LSInfinity or if the LSA is MaxAge */ + if (cost == OSPF_LS_INFINITY) { + if (is_debug) + zlog_debug("cost is LS_INFINITY, ignore"); + if (old) + ospf6_route_remove(old, table); + return; + } + if (OSPF6_LSA_IS_MAXAGE(lsa)) { + if (is_debug) + zlog_debug("LSA is MaxAge, ignore"); + if (old) + ospf6_route_remove(old, table); + return; + } + + /* (2) if the LSA is self-originated, ignore */ + if (lsa->header->adv_router == oa->ospf6->router_id) { + if (is_debug) + zlog_debug("LSA is self-originated, ignore"); + if (old) + ospf6_route_remove(old, table); + return; } - } - - if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER)) - { - /* To pass test suites */ - if (! OSPF6_OPT_ISSET (router_lsa->options, OSPF6_OPT_R) || - ! OSPF6_OPT_ISSET (router_lsa->options, OSPF6_OPT_V6)) - { - if (is_debug) - zlog_debug ("Prefix has NU/LA bit set, ignore"); - if (old) - ospf6_route_remove (old, table); - - return; + + /* (3) if the prefix is equal to an active configured address range */ + /* or if the NU bit is set in the prefix */ + if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) { + range = ospf6_route_lookup(&prefix, oa->range_table); + if (range) { + if (is_debug) + zlog_debug( + "Prefix is equal to address range, ignore"); + if (old) + ospf6_route_remove(old, table); + return; + } + + if (CHECK_FLAG(prefix_lsa->prefix.prefix_options, + OSPF6_PREFIX_OPTION_NU) + || CHECK_FLAG(prefix_lsa->prefix.prefix_options, + OSPF6_PREFIX_OPTION_LA)) { + if (is_debug) + zlog_debug("Prefix has NU/LA bit set, ignore"); + if (old) + ospf6_route_remove(old, table); + return; + } } - /* Avoid infinite recursion if someone has maliciously announced an - Inter-Router LSA for an ABR - */ - if (lsa->header->adv_router == router_lsa->router_id) - { - if (is_debug) - zlog_debug ("Ignorning Inter-Router LSA for an ABR (%s)", - buf); - if (old) - ospf6_route_remove (old, table); - - return; + + if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) { + /* To pass test suites */ + if (!OSPF6_OPT_ISSET(router_lsa->options, OSPF6_OPT_R) + || !OSPF6_OPT_ISSET(router_lsa->options, OSPF6_OPT_V6)) { + if (is_debug) + zlog_debug("Prefix has NU/LA bit set, ignore"); + if (old) + ospf6_route_remove(old, table); + + return; + } + /* Avoid infinite recursion if someone has maliciously announced + an + Inter-Router LSA for an ABR + */ + if (lsa->header->adv_router == router_lsa->router_id) { + if (is_debug) + zlog_debug( + "Ignorning Inter-Router LSA for an ABR (%s)", + buf); + if (old) + ospf6_route_remove(old, table); + + return; + } + } + + /* (4) if the routing table entry for the ABR does not exist */ + ospf6_linkstate_prefix(lsa->header->adv_router, htonl(0), &abr_prefix); + abr_entry = ospf6_route_lookup(&abr_prefix, oa->ospf6->brouter_table); + if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id + || CHECK_FLAG(abr_entry->flag, OSPF6_ROUTE_REMOVE) + || !CHECK_FLAG(abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B)) { + if (is_debug) + zlog_debug("ABR router entry does not exist, ignore"); + if (old) + ospf6_route_remove(old, table); + return; + } + + /* Check import list */ + if (IMPORT_NAME(oa)) { + if (IMPORT_LIST(oa) == NULL) + IMPORT_LIST(oa) = + access_list_lookup(AFI_IP6, IMPORT_NAME(oa)); + + if (IMPORT_LIST(oa)) + if (access_list_apply(IMPORT_LIST(oa), &prefix) + == FILTER_DENY) { + if (is_debug) + zlog_debug( + "Prefix was denied by import-list"); + if (old) + ospf6_route_remove(old, table); + return; + } + } + + /* Check input prefix-list */ + if (PREFIX_NAME_IN(oa)) { + if (PREFIX_LIST_IN(oa) == NULL) + PREFIX_LIST_IN(oa) = + prefix_list_lookup(AFI_IP6, PREFIX_NAME_IN(oa)); + + if (PREFIX_LIST_IN(oa)) + if (prefix_list_apply(PREFIX_LIST_IN(oa), &prefix) + != PREFIX_PERMIT) { + if (is_debug) + zlog_debug( + "Prefix was denied by prefix-list"); + if (old) + ospf6_route_remove(old, table); + return; + } + } + + /* (5),(6): the path preference is handled by the sorting + in the routing table. Always install the path by substituting + old route (if any). */ + if (old) + route = ospf6_route_copy(old); + else + route = ospf6_route_create(); + + route->type = type; + route->prefix = prefix; + route->path.origin.type = lsa->header->type; + route->path.origin.id = lsa->header->id; + route->path.origin.adv_router = lsa->header->adv_router; + route->path.router_bits = router_bits; + route->path.options[0] = options[0]; + route->path.options[1] = options[1]; + route->path.options[2] = options[2]; + route->path.prefix_options = prefix_options; + route->path.area_id = oa->area_id; + route->path.type = OSPF6_PATH_TYPE_INTER; + route->path.cost = abr_entry->path.cost + cost; + + ospf6_route_copy_nexthops(route, abr_entry); + + /* (7) If the routes are identical, copy the next hops over to existing + route. ospf6's route table implementation will otherwise string both + routes, but keep the older one as the best route since the routes + are identical. + */ + old = ospf6_route_lookup(&prefix, table); + + if (old && (ospf6_route_cmp(route, old) == 0)) { + ospf6_route_merge_nexthops(old, route); + /* Update RIB/FIB */ + if (table->hook_add) + (*table->hook_add)(old); + + /* Delete new route */ + ospf6_route_delete(route); + } else { + if (is_debug) + zlog_debug("Install route: %s", buf); + /* ospf6_ia_add_nw_route (table, &prefix, route); */ + ospf6_route_add(route, table); } - } - - /* (4) if the routing table entry for the ABR does not exist */ - ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &abr_prefix); - abr_entry = ospf6_route_lookup (&abr_prefix, oa->ospf6->brouter_table); - if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id || - CHECK_FLAG (abr_entry->flag, OSPF6_ROUTE_REMOVE) || - ! CHECK_FLAG (abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B)) - { - if (is_debug) - zlog_debug ("ABR router entry does not exist, ignore"); - if (old) - ospf6_route_remove (old, table); - return; - } - - /* Check import list */ - if (IMPORT_NAME (oa)) - { - if (IMPORT_LIST (oa) == NULL) - IMPORT_LIST (oa) = access_list_lookup (AFI_IP6, IMPORT_NAME (oa)); - - if (IMPORT_LIST (oa)) - if (access_list_apply (IMPORT_LIST (oa), &prefix) == FILTER_DENY) - { - if (is_debug) - zlog_debug ("Prefix was denied by import-list"); - if (old) - ospf6_route_remove (old, table); - return; - } - } - - /* Check input prefix-list */ - if (PREFIX_NAME_IN (oa)) - { - if (PREFIX_LIST_IN (oa) == NULL) - PREFIX_LIST_IN (oa) = prefix_list_lookup (AFI_IP6, PREFIX_NAME_IN (oa)); - - if (PREFIX_LIST_IN (oa)) - if (prefix_list_apply (PREFIX_LIST_IN (oa), &prefix) != PREFIX_PERMIT) - { - if (is_debug) - zlog_debug ("Prefix was denied by prefix-list"); - if (old) - ospf6_route_remove (old, table); - return; - } - } - - /* (5),(6): the path preference is handled by the sorting - in the routing table. Always install the path by substituting - old route (if any). */ - if (old) - route = ospf6_route_copy (old); - else - route = ospf6_route_create (); - - route->type = type; - route->prefix = prefix; - route->path.origin.type = lsa->header->type; - route->path.origin.id = lsa->header->id; - route->path.origin.adv_router = lsa->header->adv_router; - route->path.router_bits = router_bits; - route->path.options[0] = options[0]; - route->path.options[1] = options[1]; - route->path.options[2] = options[2]; - route->path.prefix_options = prefix_options; - route->path.area_id = oa->area_id; - route->path.type = OSPF6_PATH_TYPE_INTER; - route->path.cost = abr_entry->path.cost + cost; - - ospf6_route_copy_nexthops (route, abr_entry); - - /* (7) If the routes are identical, copy the next hops over to existing - route. ospf6's route table implementation will otherwise string both - routes, but keep the older one as the best route since the routes - are identical. - */ - old = ospf6_route_lookup (&prefix, table); - - if (old && (ospf6_route_cmp (route, old) == 0)) - { - ospf6_route_merge_nexthops (old, route); - /* Update RIB/FIB */ - if (table->hook_add) - (*table->hook_add) (old); - - /* Delete new route */ - ospf6_route_delete (route); - } - else - { - if (is_debug) - zlog_debug ("Install route: %s", buf); - /* ospf6_ia_add_nw_route (table, &prefix, route); */ - ospf6_route_add (route, table); - } } -void -ospf6_abr_examin_brouter (u_int32_t router_id) +void ospf6_abr_examin_brouter(u_int32_t router_id) { - struct ospf6_lsa *lsa; - struct ospf6_area *oa; - u_int16_t type; - - if (ospf6_is_router_abr (ospf6)) - oa = ospf6->backbone; - else - oa = listgetdata(listhead(ospf6->area_list)); - - /* - * It is possible to designate a non backbone - * area first. If that is the case safely - * fall out of this function. - */ - if (oa == NULL) - return; - - type = htons (OSPF6_LSTYPE_INTER_ROUTER); - for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa)) - ospf6_abr_examin_summary (lsa, oa); - - type = htons (OSPF6_LSTYPE_INTER_PREFIX); - for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa)) - ospf6_abr_examin_summary (lsa, oa); + struct ospf6_lsa *lsa; + struct ospf6_area *oa; + u_int16_t type; + + if (ospf6_is_router_abr(ospf6)) + oa = ospf6->backbone; + else + oa = listgetdata(listhead(ospf6->area_list)); + + /* + * It is possible to designate a non backbone + * area first. If that is the case safely + * fall out of this function. + */ + if (oa == NULL) + return; + + type = htons(OSPF6_LSTYPE_INTER_ROUTER); + for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa)) + ospf6_abr_examin_summary(lsa, oa); + + type = htons(OSPF6_LSTYPE_INTER_PREFIX); + for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa)) + ospf6_abr_examin_summary(lsa, oa); } -void -ospf6_abr_reimport (struct ospf6_area *oa) +void ospf6_abr_reimport(struct ospf6_area *oa) { - struct ospf6_lsa *lsa; - u_int16_t type; + struct ospf6_lsa *lsa; + u_int16_t type; - type = htons (OSPF6_LSTYPE_INTER_ROUTER); - for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) - ospf6_abr_examin_summary (lsa, oa); + type = htons(OSPF6_LSTYPE_INTER_ROUTER); + for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) + ospf6_abr_examin_summary(lsa, oa); - type = htons (OSPF6_LSTYPE_INTER_PREFIX); - for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) - ospf6_abr_examin_summary (lsa, oa); + type = htons(OSPF6_LSTYPE_INTER_PREFIX); + for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) + ospf6_abr_examin_summary(lsa, oa); } -void -ospf6_abr_prefix_resummarize (struct ospf6 *o) +void ospf6_abr_prefix_resummarize(struct ospf6 *o) { - struct ospf6_route *route; + struct ospf6_route *route; - if (IS_OSPF6_DEBUG_ABR) - zlog_debug ("Re-examining Inter-Prefix Summaries"); + if (IS_OSPF6_DEBUG_ABR) + zlog_debug("Re-examining Inter-Prefix Summaries"); - for (route = ospf6_route_head (o->route_table); route; - route = ospf6_route_next (route)) - ospf6_abr_originate_summary(route); + for (route = ospf6_route_head(o->route_table); route; + route = ospf6_route_next(route)) + ospf6_abr_originate_summary(route); - if (IS_OSPF6_DEBUG_ABR) - zlog_debug ("Finished re-examining Inter-Prefix Summaries"); + if (IS_OSPF6_DEBUG_ABR) + zlog_debug("Finished re-examining Inter-Prefix Summaries"); } /* Display functions */ -static char * -ospf6_inter_area_prefix_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf, - int buflen, int pos) +static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa, + char *buf, int buflen, + int pos) { - struct ospf6_inter_prefix_lsa *prefix_lsa; - struct in6_addr in6; - - if (lsa != NULL) - { - prefix_lsa = (struct ospf6_inter_prefix_lsa *) - OSPF6_LSA_HEADER_END (lsa->header); - - ospf6_prefix_in6_addr (&in6, &prefix_lsa->prefix); - if (buf) - { - inet_ntop (AF_INET6, &in6, buf, buflen); - sprintf (&buf[strlen(buf)], "/%d", prefix_lsa->prefix.prefix_length); + struct ospf6_inter_prefix_lsa *prefix_lsa; + struct in6_addr in6; + + if (lsa != NULL) { + prefix_lsa = + (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END( + lsa->header); + + ospf6_prefix_in6_addr(&in6, &prefix_lsa->prefix); + if (buf) { + inet_ntop(AF_INET6, &in6, buf, buflen); + sprintf(&buf[strlen(buf)], "/%d", + prefix_lsa->prefix.prefix_length); + } } - } - return (buf); + return (buf); } -static int -ospf6_inter_area_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) +static int ospf6_inter_area_prefix_lsa_show(struct vty *vty, + struct ospf6_lsa *lsa) { - struct ospf6_inter_prefix_lsa *prefix_lsa; - char buf[INET6_ADDRSTRLEN]; + struct ospf6_inter_prefix_lsa *prefix_lsa; + char buf[INET6_ADDRSTRLEN]; - prefix_lsa = (struct ospf6_inter_prefix_lsa *) - OSPF6_LSA_HEADER_END (lsa->header); + prefix_lsa = (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END( + lsa->header); - vty_out (vty, " Metric: %lu\n", - (u_long) OSPF6_ABR_SUMMARY_METRIC (prefix_lsa)); + vty_out(vty, " Metric: %lu\n", + (u_long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa)); - ospf6_prefix_options_printbuf (prefix_lsa->prefix.prefix_options, - buf, sizeof (buf)); - vty_out (vty, " Prefix Options: %s\n", buf); + ospf6_prefix_options_printbuf(prefix_lsa->prefix.prefix_options, buf, + sizeof(buf)); + vty_out(vty, " Prefix Options: %s\n", buf); - vty_out (vty, " Prefix: %s\n", - ospf6_inter_area_prefix_lsa_get_prefix_str (lsa, buf, sizeof(buf), - 0)); + vty_out(vty, " Prefix: %s\n", + ospf6_inter_area_prefix_lsa_get_prefix_str(lsa, buf, + sizeof(buf), 0)); - return 0; + return 0; } -static char * -ospf6_inter_area_router_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf, - int buflen, int pos) +static char *ospf6_inter_area_router_lsa_get_prefix_str(struct ospf6_lsa *lsa, + char *buf, int buflen, + int pos) { - struct ospf6_inter_router_lsa *router_lsa; + struct ospf6_inter_router_lsa *router_lsa; - if (lsa != NULL) - { - router_lsa = (struct ospf6_inter_router_lsa *) - OSPF6_LSA_HEADER_END (lsa->header); + if (lsa != NULL) { + router_lsa = + (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END( + lsa->header); - if (buf) - inet_ntop (AF_INET, &router_lsa->router_id, buf, buflen); - } + if (buf) + inet_ntop(AF_INET, &router_lsa->router_id, buf, buflen); + } - return (buf); + return (buf); } -static int -ospf6_inter_area_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) +static int ospf6_inter_area_router_lsa_show(struct vty *vty, + struct ospf6_lsa *lsa) { - struct ospf6_inter_router_lsa *router_lsa; - char buf[64]; + struct ospf6_inter_router_lsa *router_lsa; + char buf[64]; - router_lsa = (struct ospf6_inter_router_lsa *) - OSPF6_LSA_HEADER_END (lsa->header); + router_lsa = (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END( + lsa->header); - ospf6_options_printbuf (router_lsa->options, buf, sizeof (buf)); - vty_out (vty, " Options: %s\n", buf); - vty_out (vty, " Metric: %lu\n", - (u_long) OSPF6_ABR_SUMMARY_METRIC (router_lsa)); + ospf6_options_printbuf(router_lsa->options, buf, sizeof(buf)); + vty_out(vty, " Options: %s\n", buf); + vty_out(vty, " Metric: %lu\n", + (u_long)OSPF6_ABR_SUMMARY_METRIC(router_lsa)); - inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf)); - vty_out (vty, " Destination Router ID: %s\n", buf); + inet_ntop(AF_INET, &router_lsa->router_id, buf, sizeof(buf)); + vty_out(vty, " Destination Router ID: %s\n", buf); - return 0; + return 0; } /* Debug commands */ @@ -1124,8 +1090,8 @@ DEFUN (debug_ospf6_abr, "Debug OSPFv3 ABR function\n" ) { - OSPF6_DEBUG_ABR_ON (); - return CMD_SUCCESS; + OSPF6_DEBUG_ABR_ON(); + return CMD_SUCCESS; } DEFUN (no_debug_ospf6_abr, @@ -1137,50 +1103,43 @@ DEFUN (no_debug_ospf6_abr, "Debug OSPFv3 ABR function\n" ) { - OSPF6_DEBUG_ABR_OFF (); - return CMD_SUCCESS; + OSPF6_DEBUG_ABR_OFF(); + return CMD_SUCCESS; } -int -config_write_ospf6_debug_abr (struct vty *vty) +int config_write_ospf6_debug_abr(struct vty *vty) { - if (IS_OSPF6_DEBUG_ABR) - vty_out (vty, "debug ospf6 abr\n"); - return 0; + if (IS_OSPF6_DEBUG_ABR) + vty_out(vty, "debug ospf6 abr\n"); + return 0; } -void -install_element_ospf6_debug_abr (void) +void install_element_ospf6_debug_abr(void) { - install_element (ENABLE_NODE, &debug_ospf6_abr_cmd); - install_element (ENABLE_NODE, &no_debug_ospf6_abr_cmd); - install_element (CONFIG_NODE, &debug_ospf6_abr_cmd); - install_element (CONFIG_NODE, &no_debug_ospf6_abr_cmd); + install_element(ENABLE_NODE, &debug_ospf6_abr_cmd); + install_element(ENABLE_NODE, &no_debug_ospf6_abr_cmd); + install_element(CONFIG_NODE, &debug_ospf6_abr_cmd); + install_element(CONFIG_NODE, &no_debug_ospf6_abr_cmd); } -struct ospf6_lsa_handler inter_prefix_handler = -{ - OSPF6_LSTYPE_INTER_PREFIX, - "Inter-Prefix", - "IAP", - ospf6_inter_area_prefix_lsa_show, - ospf6_inter_area_prefix_lsa_get_prefix_str, +struct ospf6_lsa_handler inter_prefix_handler = { + OSPF6_LSTYPE_INTER_PREFIX, + "Inter-Prefix", + "IAP", + ospf6_inter_area_prefix_lsa_show, + ospf6_inter_area_prefix_lsa_get_prefix_str, }; -struct ospf6_lsa_handler inter_router_handler = -{ - OSPF6_LSTYPE_INTER_ROUTER, - "Inter-Router", - "IAR", - ospf6_inter_area_router_lsa_show, - ospf6_inter_area_router_lsa_get_prefix_str, +struct ospf6_lsa_handler inter_router_handler = { + OSPF6_LSTYPE_INTER_ROUTER, + "Inter-Router", + "IAR", + ospf6_inter_area_router_lsa_show, + ospf6_inter_area_router_lsa_get_prefix_str, }; -void -ospf6_abr_init (void) +void ospf6_abr_init(void) { - ospf6_install_lsa_handler (&inter_prefix_handler); - ospf6_install_lsa_handler (&inter_router_handler); + ospf6_install_lsa_handler(&inter_prefix_handler); + ospf6_install_lsa_handler(&inter_router_handler); } - - diff --git a/ospf6d/ospf6_abr.h b/ospf6d/ospf6_abr.h index 55d657cfc..61a6a7342 100644 --- a/ospf6d/ospf6_abr.h +++ b/ospf6d/ospf6_abr.h @@ -28,57 +28,55 @@ /* Debug option */ extern unsigned char conf_debug_ospf6_abr; -#define OSPF6_DEBUG_ABR_ON() \ - (conf_debug_ospf6_abr = 1) -#define OSPF6_DEBUG_ABR_OFF() \ - (conf_debug_ospf6_abr = 0) -#define IS_OSPF6_DEBUG_ABR \ - (conf_debug_ospf6_abr) +#define OSPF6_DEBUG_ABR_ON() (conf_debug_ospf6_abr = 1) +#define OSPF6_DEBUG_ABR_OFF() (conf_debug_ospf6_abr = 0) +#define IS_OSPF6_DEBUG_ABR (conf_debug_ospf6_abr) /* Inter-Area-Prefix-LSA */ #define OSPF6_INTER_PREFIX_LSA_MIN_SIZE 4U /* w/o IPv6 prefix */ -struct ospf6_inter_prefix_lsa -{ - u_int32_t metric; - struct ospf6_prefix prefix; +struct ospf6_inter_prefix_lsa { + u_int32_t metric; + struct ospf6_prefix prefix; }; /* Inter-Area-Router-LSA */ #define OSPF6_INTER_ROUTER_LSA_FIX_SIZE 12U -struct ospf6_inter_router_lsa -{ - u_char mbz; - u_char options[3]; - u_int32_t metric; - u_int32_t router_id; +struct ospf6_inter_router_lsa { + u_char mbz; + u_char options[3]; + u_int32_t metric; + u_int32_t router_id; }; #define OSPF6_ABR_SUMMARY_METRIC(E) (ntohl ((E)->metric & htonl (0x00ffffff))) -#define OSPF6_ABR_SUMMARY_METRIC_SET(E,C) \ - { (E)->metric &= htonl (0x00000000); \ - (E)->metric |= htonl (0x00ffffff) & htonl (C); } +#define OSPF6_ABR_SUMMARY_METRIC_SET(E, C) \ + { \ + (E)->metric &= htonl(0x00000000); \ + (E)->metric |= htonl(0x00ffffff) & htonl(C); \ + } #define OSPF6_ABR_RANGE_CLEAR_COST(range) (range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC) -extern int ospf6_is_router_abr (struct ospf6 *o); +extern int ospf6_is_router_abr(struct ospf6 *o); -extern void ospf6_abr_enable_area (struct ospf6_area *oa); -extern void ospf6_abr_disable_area (struct ospf6_area *oa); +extern void ospf6_abr_enable_area(struct ospf6_area *oa); +extern void ospf6_abr_disable_area(struct ospf6_area *oa); -extern int ospf6_abr_originate_summary_to_area (struct ospf6_route *route, - struct ospf6_area *area); -extern void ospf6_abr_originate_summary (struct ospf6_route *route); -extern void ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa); -extern void ospf6_abr_defaults_to_stub (struct ospf6 *); -extern void ospf6_abr_examin_brouter (u_int32_t router_id); -extern void ospf6_abr_reimport (struct ospf6_area *oa); -extern void ospf6_abr_range_reset_cost (struct ospf6 *ospf6); -extern void ospf6_abr_prefix_resummarize (struct ospf6 *ospf6); +extern int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, + struct ospf6_area *area); +extern void ospf6_abr_originate_summary(struct ospf6_route *route); +extern void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, + struct ospf6_area *oa); +extern void ospf6_abr_defaults_to_stub(struct ospf6 *); +extern void ospf6_abr_examin_brouter(u_int32_t router_id); +extern void ospf6_abr_reimport(struct ospf6_area *oa); +extern void ospf6_abr_range_reset_cost(struct ospf6 *ospf6); +extern void ospf6_abr_prefix_resummarize(struct ospf6 *ospf6); -extern int config_write_ospf6_debug_abr (struct vty *vty); -extern void install_element_ospf6_debug_abr (void); -extern int ospf6_abr_config_write (struct vty *vty); +extern int config_write_ospf6_debug_abr(struct vty *vty); +extern void install_element_ospf6_debug_abr(void); +extern int ospf6_abr_config_write(struct vty *vty); -extern void ospf6_abr_init (void); +extern void ospf6_abr_init(void); #endif /*OSPF6_ABR_H*/ diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c index 8e6408bf4..a4cc0bf42 100644 --- a/ospf6d/ospf6_area.c +++ b/ospf6d/ospf6_area.c @@ -45,163 +45,146 @@ #include "ospf6_asbr.h" #include "ospf6d.h" -int -ospf6_area_cmp (void *va, void *vb) +int ospf6_area_cmp(void *va, void *vb) { - struct ospf6_area *oa = (struct ospf6_area *) va; - struct ospf6_area *ob = (struct ospf6_area *) vb; - return (ntohl (oa->area_id) < ntohl (ob->area_id) ? -1 : 1); + struct ospf6_area *oa = (struct ospf6_area *)va; + struct ospf6_area *ob = (struct ospf6_area *)vb; + return (ntohl(oa->area_id) < ntohl(ob->area_id) ? -1 : 1); } /* schedule routing table recalculation */ -static void -ospf6_area_lsdb_hook_add (struct ospf6_lsa *lsa) -{ - switch (ntohs (lsa->header->type)) - { - case OSPF6_LSTYPE_ROUTER: - case OSPF6_LSTYPE_NETWORK: - if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type)) - { - zlog_debug ("Examin %s", lsa->name); - zlog_debug ("Schedule SPF Calculation for %s", - OSPF6_AREA (lsa->lsdb->data)->name); - } - ospf6_spf_schedule (OSPF6_PROCESS(OSPF6_AREA (lsa->lsdb->data)->ospf6), - ospf6_lsadd_to_spf_reason(lsa)); - break; - - case OSPF6_LSTYPE_INTRA_PREFIX: - ospf6_intra_prefix_lsa_add (lsa); - break; - - case OSPF6_LSTYPE_INTER_PREFIX: - case OSPF6_LSTYPE_INTER_ROUTER: - ospf6_abr_examin_summary (lsa, (struct ospf6_area *) lsa->lsdb->data); - break; - - default: - break; - } +static void ospf6_area_lsdb_hook_add(struct ospf6_lsa *lsa) +{ + switch (ntohs(lsa->header->type)) { + case OSPF6_LSTYPE_ROUTER: + case OSPF6_LSTYPE_NETWORK: + if (IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type)) { + zlog_debug("Examin %s", lsa->name); + zlog_debug("Schedule SPF Calculation for %s", + OSPF6_AREA(lsa->lsdb->data)->name); + } + ospf6_spf_schedule( + OSPF6_PROCESS(OSPF6_AREA(lsa->lsdb->data)->ospf6), + ospf6_lsadd_to_spf_reason(lsa)); + break; + + case OSPF6_LSTYPE_INTRA_PREFIX: + ospf6_intra_prefix_lsa_add(lsa); + break; + + case OSPF6_LSTYPE_INTER_PREFIX: + case OSPF6_LSTYPE_INTER_ROUTER: + ospf6_abr_examin_summary(lsa, + (struct ospf6_area *)lsa->lsdb->data); + break; + + default: + break; + } } -static void -ospf6_area_lsdb_hook_remove (struct ospf6_lsa *lsa) -{ - switch (ntohs (lsa->header->type)) - { - case OSPF6_LSTYPE_ROUTER: - case OSPF6_LSTYPE_NETWORK: - if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type)) - { - zlog_debug ("LSA disappearing: %s", lsa->name); - zlog_debug ("Schedule SPF Calculation for %s", - OSPF6_AREA (lsa->lsdb->data)->name); - } - ospf6_spf_schedule (OSPF6_PROCESS(OSPF6_AREA (lsa->lsdb->data)->ospf6), - ospf6_lsremove_to_spf_reason(lsa)); - break; - - case OSPF6_LSTYPE_INTRA_PREFIX: - ospf6_intra_prefix_lsa_remove (lsa); - break; - - case OSPF6_LSTYPE_INTER_PREFIX: - case OSPF6_LSTYPE_INTER_ROUTER: - ospf6_abr_examin_summary (lsa, (struct ospf6_area *) lsa->lsdb->data); - break; - - default: - break; - } +static void ospf6_area_lsdb_hook_remove(struct ospf6_lsa *lsa) +{ + switch (ntohs(lsa->header->type)) { + case OSPF6_LSTYPE_ROUTER: + case OSPF6_LSTYPE_NETWORK: + if (IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type)) { + zlog_debug("LSA disappearing: %s", lsa->name); + zlog_debug("Schedule SPF Calculation for %s", + OSPF6_AREA(lsa->lsdb->data)->name); + } + ospf6_spf_schedule( + OSPF6_PROCESS(OSPF6_AREA(lsa->lsdb->data)->ospf6), + ospf6_lsremove_to_spf_reason(lsa)); + break; + + case OSPF6_LSTYPE_INTRA_PREFIX: + ospf6_intra_prefix_lsa_remove(lsa); + break; + + case OSPF6_LSTYPE_INTER_PREFIX: + case OSPF6_LSTYPE_INTER_ROUTER: + ospf6_abr_examin_summary(lsa, + (struct ospf6_area *)lsa->lsdb->data); + break; + + default: + break; + } } -static void -ospf6_area_route_hook_add (struct ospf6_route *route) +static void ospf6_area_route_hook_add(struct ospf6_route *route) { - struct ospf6_route *copy = ospf6_route_copy (route); - ospf6_route_add (copy, ospf6->route_table); + struct ospf6_route *copy = ospf6_route_copy(route); + ospf6_route_add(copy, ospf6->route_table); } -static void -ospf6_area_route_hook_remove (struct ospf6_route *route) +static void ospf6_area_route_hook_remove(struct ospf6_route *route) { - struct ospf6_route *copy; + struct ospf6_route *copy; - copy = ospf6_route_lookup_identical (route, ospf6->route_table); - if (copy) - ospf6_route_remove (copy, ospf6->route_table); + copy = ospf6_route_lookup_identical(route, ospf6->route_table); + if (copy) + ospf6_route_remove(copy, ospf6->route_table); } -static void -ospf6_area_stub_update (struct ospf6_area *area) +static void ospf6_area_stub_update(struct ospf6_area *area) { - if (IS_AREA_STUB (area)) - { - if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER)) - zlog_debug ("Stubbing out area for if %s\n", area->name); - OSPF6_OPT_CLEAR (area->options, OSPF6_OPT_E); - } - else if (IS_AREA_ENABLED (area)) - { - if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER)) - zlog_debug ("Normal area for if %s\n", area->name); - OSPF6_OPT_SET (area->options, OSPF6_OPT_E); - ospf6_asbr_send_externals_to_area (area); - } - - OSPF6_ROUTER_LSA_SCHEDULE(area); + if (IS_AREA_STUB(area)) { + if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER)) + zlog_debug("Stubbing out area for if %s\n", area->name); + OSPF6_OPT_CLEAR(area->options, OSPF6_OPT_E); + } else if (IS_AREA_ENABLED(area)) { + if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER)) + zlog_debug("Normal area for if %s\n", area->name); + OSPF6_OPT_SET(area->options, OSPF6_OPT_E); + ospf6_asbr_send_externals_to_area(area); + } + + OSPF6_ROUTER_LSA_SCHEDULE(area); } -static int -ospf6_area_stub_set (struct ospf6 *ospf6, struct ospf6_area *area) +static int ospf6_area_stub_set(struct ospf6 *ospf6, struct ospf6_area *area) { - if (!IS_AREA_STUB(area)) - { - SET_FLAG (area->flag, OSPF6_AREA_STUB); - ospf6_area_stub_update (area); - } + if (!IS_AREA_STUB(area)) { + SET_FLAG(area->flag, OSPF6_AREA_STUB); + ospf6_area_stub_update(area); + } - return (1); + return (1); } -static void -ospf6_area_stub_unset (struct ospf6 *ospf6, struct ospf6_area *area) +static void ospf6_area_stub_unset(struct ospf6 *ospf6, struct ospf6_area *area) { - if (IS_AREA_STUB (area)) - { - UNSET_FLAG (area->flag, OSPF6_AREA_STUB); - ospf6_area_stub_update (area); - } + if (IS_AREA_STUB(area)) { + UNSET_FLAG(area->flag, OSPF6_AREA_STUB); + ospf6_area_stub_update(area); + } } -static void -ospf6_area_no_summary_set (struct ospf6 *ospf6, struct ospf6_area *area) +static void ospf6_area_no_summary_set(struct ospf6 *ospf6, + struct ospf6_area *area) { - if (area) - { - if (!area->no_summary) - { - area->no_summary = 1; - ospf6_abr_range_reset_cost (ospf6); - ospf6_abr_prefix_resummarize (ospf6); + if (area) { + if (!area->no_summary) { + area->no_summary = 1; + ospf6_abr_range_reset_cost(ospf6); + ospf6_abr_prefix_resummarize(ospf6); + } } - } } -static void -ospf6_area_no_summary_unset (struct ospf6 *ospf6, struct ospf6_area *area) +static void ospf6_area_no_summary_unset(struct ospf6 *ospf6, + struct ospf6_area *area) { - if (area) - { - if (area->no_summary) - { - area->no_summary = 0; - ospf6_abr_range_reset_cost (ospf6); - ospf6_abr_prefix_resummarize (ospf6); + if (area) { + if (area->no_summary) { + area->no_summary = 0; + ospf6_abr_range_reset_cost(ospf6); + ospf6_abr_prefix_resummarize(ospf6); + } } - } } /** @@ -211,221 +194,199 @@ ospf6_area_no_summary_unset (struct ospf6 *ospf6, struct ospf6_area *area) * @param o - ospf6 instance * @param df - display format for area ID */ -struct ospf6_area * -ospf6_area_create (u_int32_t area_id, struct ospf6 *o, int df) +struct ospf6_area *ospf6_area_create(u_int32_t area_id, struct ospf6 *o, int df) { - struct ospf6_area *oa; - - oa = XCALLOC (MTYPE_OSPF6_AREA, sizeof (struct ospf6_area)); - - switch (df) - { - case OSPF6_AREA_FMT_DECIMAL: - snprintf (oa->name, sizeof (oa->name), "%u", ntohl (area_id)); - break; - default: - case OSPF6_AREA_FMT_DOTTEDQUAD: - inet_ntop (AF_INET, &area_id, oa->name, sizeof (oa->name)); - break; - } - - oa->area_id = area_id; - oa->if_list = list_new (); - - oa->lsdb = ospf6_lsdb_create (oa); - oa->lsdb->hook_add = ospf6_area_lsdb_hook_add; - oa->lsdb->hook_remove = ospf6_area_lsdb_hook_remove; - oa->lsdb_self = ospf6_lsdb_create (oa); - - oa->spf_table = OSPF6_ROUTE_TABLE_CREATE (AREA, SPF_RESULTS); - oa->spf_table->scope = oa; - oa->route_table = OSPF6_ROUTE_TABLE_CREATE (AREA, ROUTES); - oa->route_table->scope = oa; - oa->route_table->hook_add = ospf6_area_route_hook_add; - oa->route_table->hook_remove = ospf6_area_route_hook_remove; - - oa->range_table = OSPF6_ROUTE_TABLE_CREATE (AREA, PREFIX_RANGES); - oa->range_table->scope = oa; - bf_init(oa->range_table->idspace, 32); - oa->summary_prefix = OSPF6_ROUTE_TABLE_CREATE (AREA, SUMMARY_PREFIXES); - oa->summary_prefix->scope = oa; - oa->summary_router = OSPF6_ROUTE_TABLE_CREATE (AREA, SUMMARY_ROUTERS); - oa->summary_router->scope = oa; - - /* set default options */ - if (CHECK_FLAG (o->flag, OSPF6_STUB_ROUTER)) - { - OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_V6); - OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_R); - } - else - { - OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6); - OSPF6_OPT_SET (oa->options, OSPF6_OPT_R); - } - - OSPF6_OPT_SET (oa->options, OSPF6_OPT_E); - - SET_FLAG (oa->flag, OSPF6_AREA_ACTIVE); - SET_FLAG (oa->flag, OSPF6_AREA_ENABLE); - - oa->ospf6 = o; - listnode_add_sort (o->area_list, oa); - - if (area_id == OSPF_AREA_BACKBONE) - { - o->backbone = oa; - } - - return oa; + struct ospf6_area *oa; + + oa = XCALLOC(MTYPE_OSPF6_AREA, sizeof(struct ospf6_area)); + + switch (df) { + case OSPF6_AREA_FMT_DECIMAL: + snprintf(oa->name, sizeof(oa->name), "%u", ntohl(area_id)); + break; + default: + case OSPF6_AREA_FMT_DOTTEDQUAD: + inet_ntop(AF_INET, &area_id, oa->name, sizeof(oa->name)); + break; + } + + oa->area_id = area_id; + oa->if_list = list_new(); + + oa->lsdb = ospf6_lsdb_create(oa); + oa->lsdb->hook_add = ospf6_area_lsdb_hook_add; + oa->lsdb->hook_remove = ospf6_area_lsdb_hook_remove; + oa->lsdb_self = ospf6_lsdb_create(oa); + + oa->spf_table = OSPF6_ROUTE_TABLE_CREATE(AREA, SPF_RESULTS); + oa->spf_table->scope = oa; + oa->route_table = OSPF6_ROUTE_TABLE_CREATE(AREA, ROUTES); + oa->route_table->scope = oa; + oa->route_table->hook_add = ospf6_area_route_hook_add; + oa->route_table->hook_remove = ospf6_area_route_hook_remove; + + oa->range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES); + oa->range_table->scope = oa; + bf_init(oa->range_table->idspace, 32); + oa->summary_prefix = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_PREFIXES); + oa->summary_prefix->scope = oa; + oa->summary_router = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_ROUTERS); + oa->summary_router->scope = oa; + + /* set default options */ + if (CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER)) { + OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_V6); + OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_R); + } else { + OSPF6_OPT_SET(oa->options, OSPF6_OPT_V6); + OSPF6_OPT_SET(oa->options, OSPF6_OPT_R); + } + + OSPF6_OPT_SET(oa->options, OSPF6_OPT_E); + + SET_FLAG(oa->flag, OSPF6_AREA_ACTIVE); + SET_FLAG(oa->flag, OSPF6_AREA_ENABLE); + + oa->ospf6 = o; + listnode_add_sort(o->area_list, oa); + + if (area_id == OSPF_AREA_BACKBONE) { + o->backbone = oa; + } + + return oa; } -void -ospf6_area_delete (struct ospf6_area *oa) +void ospf6_area_delete(struct ospf6_area *oa) { - struct listnode *n; - struct ospf6_interface *oi; + struct listnode *n; + struct ospf6_interface *oi; - /* The ospf6_interface structs store configuration - * information which should not be lost/reset when - * deleting an area. - * So just detach the interface from the area and - * keep it around. */ - for (ALL_LIST_ELEMENTS_RO (oa->if_list, n, oi)) - oi->area = NULL; + /* The ospf6_interface structs store configuration + * information which should not be lost/reset when + * deleting an area. + * So just detach the interface from the area and + * keep it around. */ + for (ALL_LIST_ELEMENTS_RO(oa->if_list, n, oi)) + oi->area = NULL; - list_delete (oa->if_list); + list_delete(oa->if_list); - ospf6_lsdb_delete (oa->lsdb); - ospf6_lsdb_delete (oa->lsdb_self); + ospf6_lsdb_delete(oa->lsdb); + ospf6_lsdb_delete(oa->lsdb_self); - ospf6_spf_table_finish (oa->spf_table); - ospf6_route_table_delete (oa->spf_table); - ospf6_route_table_delete (oa->route_table); + ospf6_spf_table_finish(oa->spf_table); + ospf6_route_table_delete(oa->spf_table); + ospf6_route_table_delete(oa->route_table); - ospf6_route_table_delete (oa->range_table); - ospf6_route_table_delete (oa->summary_prefix); - ospf6_route_table_delete (oa->summary_router); + ospf6_route_table_delete(oa->range_table); + ospf6_route_table_delete(oa->summary_prefix); + ospf6_route_table_delete(oa->summary_router); - listnode_delete (oa->ospf6->area_list, oa); - oa->ospf6 = NULL; + listnode_delete(oa->ospf6->area_list, oa); + oa->ospf6 = NULL; - /* free area */ - XFREE (MTYPE_OSPF6_AREA, oa); + /* free area */ + XFREE(MTYPE_OSPF6_AREA, oa); } -struct ospf6_area * -ospf6_area_lookup (u_int32_t area_id, struct ospf6 *ospf6) +struct ospf6_area *ospf6_area_lookup(u_int32_t area_id, struct ospf6 *ospf6) { - struct ospf6_area *oa; - struct listnode *n; + struct ospf6_area *oa; + struct listnode *n; - for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, n, oa)) - if (oa->area_id == area_id) - return oa; + for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) + if (oa->area_id == area_id) + return oa; - return (struct ospf6_area *) NULL; + return (struct ospf6_area *)NULL; } -void -ospf6_area_enable (struct ospf6_area *oa) +void ospf6_area_enable(struct ospf6_area *oa) { - struct listnode *node, *nnode; - struct ospf6_interface *oi; + struct listnode *node, *nnode; + struct ospf6_interface *oi; - SET_FLAG (oa->flag, OSPF6_AREA_ENABLE); + SET_FLAG(oa->flag, OSPF6_AREA_ENABLE); - for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi)) - ospf6_interface_enable (oi); - ospf6_abr_enable_area (oa); + for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) + ospf6_interface_enable(oi); + ospf6_abr_enable_area(oa); } -void -ospf6_area_disable (struct ospf6_area *oa) +void ospf6_area_disable(struct ospf6_area *oa) { - struct listnode *node, *nnode; - struct ospf6_interface *oi; + struct listnode *node, *nnode; + struct ospf6_interface *oi; - UNSET_FLAG (oa->flag, OSPF6_AREA_ENABLE); + UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE); - for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi)) - ospf6_interface_disable (oi); + for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) + ospf6_interface_disable(oi); - ospf6_abr_disable_area (oa); - ospf6_lsdb_remove_all (oa->lsdb); - ospf6_lsdb_remove_all (oa->lsdb_self); + ospf6_abr_disable_area(oa); + ospf6_lsdb_remove_all(oa->lsdb); + ospf6_lsdb_remove_all(oa->lsdb_self); - ospf6_spf_table_finish(oa->spf_table); - ospf6_route_remove_all(oa->route_table); + ospf6_spf_table_finish(oa->spf_table); + ospf6_route_remove_all(oa->route_table); - THREAD_OFF (oa->thread_router_lsa); - THREAD_OFF (oa->thread_intra_prefix_lsa); + THREAD_OFF(oa->thread_router_lsa); + THREAD_OFF(oa->thread_intra_prefix_lsa); } -void -ospf6_area_show (struct vty *vty, struct ospf6_area *oa) +void ospf6_area_show(struct vty *vty, struct ospf6_area *oa) { - struct listnode *i; - struct ospf6_interface *oi; - unsigned long result; - - if (!IS_AREA_STUB (oa)) - vty_out (vty, " Area %s\n", oa->name); - else - { - if (oa->no_summary) - { - vty_out (vty, " Area %s[Stub, No Summary]\n", oa->name); - } - else - { - vty_out (vty, " Area %s[Stub]\n", oa->name); - } - } - vty_out (vty, " Number of Area scoped LSAs is %u\n", - oa->lsdb->count); - - vty_out (vty, " Interface attached to this area:"); - for (ALL_LIST_ELEMENTS_RO (oa->if_list, i, oi)) - vty_out (vty, " %s", oi->interface->name); - vty_out (vty, "\n"); - - if (oa->ts_spf.tv_sec || oa->ts_spf.tv_usec) - { - result = monotime_since(&oa->ts_spf, NULL); - if (result/TIMER_SECOND_MICRO > 0) - { - vty_out (vty, "SPF last executed %ld.%lds ago\n", - result/TIMER_SECOND_MICRO, - result % TIMER_SECOND_MICRO); + struct listnode *i; + struct ospf6_interface *oi; + unsigned long result; + + if (!IS_AREA_STUB(oa)) + vty_out(vty, " Area %s\n", oa->name); + else { + if (oa->no_summary) { + vty_out(vty, " Area %s[Stub, No Summary]\n", oa->name); + } else { + vty_out(vty, " Area %s[Stub]\n", oa->name); + } } - else - { - vty_out (vty, "SPF last executed %ldus ago\n", - result); + vty_out(vty, " Number of Area scoped LSAs is %u\n", + oa->lsdb->count); + + vty_out(vty, " Interface attached to this area:"); + for (ALL_LIST_ELEMENTS_RO(oa->if_list, i, oi)) + vty_out(vty, " %s", oi->interface->name); + vty_out(vty, "\n"); + + if (oa->ts_spf.tv_sec || oa->ts_spf.tv_usec) { + result = monotime_since(&oa->ts_spf, NULL); + if (result / TIMER_SECOND_MICRO > 0) { + vty_out(vty, "SPF last executed %ld.%lds ago\n", + result / TIMER_SECOND_MICRO, + result % TIMER_SECOND_MICRO); + } else { + vty_out(vty, "SPF last executed %ldus ago\n", result); + } + } else + vty_out(vty, "SPF has not been run\n"); +} + + +#define OSPF6_CMD_AREA_GET(str, oa) \ + { \ + char *ep; \ + u_int32_t area_id = htonl(strtoul(str, &ep, 10)); \ + if (*ep && inet_pton(AF_INET, str, &area_id) != 1) { \ + vty_out(vty, "Malformed Area-ID: %s\n", str); \ + return CMD_SUCCESS; \ + } \ + int format = !*ep ? OSPF6_AREA_FMT_DECIMAL \ + : OSPF6_AREA_FMT_DOTTEDQUAD; \ + oa = ospf6_area_lookup(area_id, ospf6); \ + if (oa == NULL) \ + oa = ospf6_area_create(area_id, ospf6, format); \ } - } - else - vty_out (vty, "SPF has not been run\n"); -} - - -#define OSPF6_CMD_AREA_GET(str, oa) \ -{ \ - char *ep; \ - u_int32_t area_id = htonl (strtoul (str, &ep, 10)); \ - if (*ep && inet_pton (AF_INET, str, &area_id) != 1) \ - { \ - vty_out (vty, "Malformed Area-ID: %s\n", str); \ - return CMD_SUCCESS; \ - } \ - int format = !*ep ? OSPF6_AREA_FMT_DECIMAL : \ - OSPF6_AREA_FMT_DOTTEDQUAD; \ - oa = ospf6_area_lookup (area_id, ospf6); \ - if (oa == NULL) \ - oa = ospf6_area_create (area_id, ospf6, format); \ -} DEFUN (area_range, area_range_cmd, @@ -440,66 +401,58 @@ DEFUN (area_range, "User specified metric for this range\n" "Advertised metric for this range\n") { - int idx_ipv4 = 1; - int idx_ipv6_prefixlen = 3; - int idx_type = 4; - int ret; - struct ospf6_area *oa; - struct prefix prefix; - struct ospf6_route *range; - u_int32_t cost = OSPF_AREA_RANGE_COST_UNSPEC; - - OSPF6_CMD_AREA_GET (argv[idx_ipv4]->arg, oa); - - ret = str2prefix (argv[idx_ipv6_prefixlen]->arg, &prefix); - if (ret != 1 || prefix.family != AF_INET6) - { - vty_out (vty, "Malformed argument: %s\n", argv[idx_ipv6_prefixlen]->arg); - return CMD_SUCCESS; - } - - range = ospf6_route_lookup (&prefix, oa->range_table); - if (range == NULL) - { - range = ospf6_route_create (); - range->type = OSPF6_DEST_TYPE_RANGE; - range->prefix = prefix; - range->path.area_id = oa->area_id; - range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC; - } - - if (argc > idx_type) - { - if (strmatch (argv[idx_type]->text, "not-advertise")) - { - SET_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE); + int idx_ipv4 = 1; + int idx_ipv6_prefixlen = 3; + int idx_type = 4; + int ret; + struct ospf6_area *oa; + struct prefix prefix; + struct ospf6_route *range; + u_int32_t cost = OSPF_AREA_RANGE_COST_UNSPEC; + + OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa); + + ret = str2prefix(argv[idx_ipv6_prefixlen]->arg, &prefix); + if (ret != 1 || prefix.family != AF_INET6) { + vty_out(vty, "Malformed argument: %s\n", + argv[idx_ipv6_prefixlen]->arg); + return CMD_SUCCESS; } - else if (strmatch (argv[idx_type]->text, "advertise")) - { - UNSET_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE); + + range = ospf6_route_lookup(&prefix, oa->range_table); + if (range == NULL) { + range = ospf6_route_create(); + range->type = OSPF6_DEST_TYPE_RANGE; + range->prefix = prefix; + range->path.area_id = oa->area_id; + range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC; } - else - { - cost = strtoul(argv[5]->arg, NULL, 10); - UNSET_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE); + + if (argc > idx_type) { + if (strmatch(argv[idx_type]->text, "not-advertise")) { + SET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE); + } else if (strmatch(argv[idx_type]->text, "advertise")) { + UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE); + } else { + cost = strtoul(argv[5]->arg, NULL, 10); + UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE); + } } - } - range->path.u.cost_config = cost; + range->path.u.cost_config = cost; - zlog_debug ("%s: for prefix %s, flag = %x\n", __func__, argv[idx_ipv6_prefixlen]->arg, range->flag); - if (range->rnode == NULL) - { - ospf6_route_add (range, oa->range_table); - } + zlog_debug("%s: for prefix %s, flag = %x\n", __func__, + argv[idx_ipv6_prefixlen]->arg, range->flag); + if (range->rnode == NULL) { + ospf6_route_add(range, oa->range_table); + } - if (ospf6_is_router_abr (ospf6)) - { - /* Redo summaries if required */ - ospf6_abr_prefix_resummarize (ospf6); - } + if (ospf6_is_router_abr(ospf6)) { + /* Redo summaries if required */ + ospf6_abr_prefix_resummarize(ospf6); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_area_range, @@ -516,96 +469,91 @@ DEFUN (no_area_range, "User specified metric for this range\n" "Advertised metric for this range\n") { - int idx_ipv4 = 2; - int idx_ipv6 = 4; - int ret; - struct ospf6_area *oa; - struct prefix prefix; - struct ospf6_route *range, *route; - - OSPF6_CMD_AREA_GET (argv[idx_ipv4]->arg, oa); - - ret = str2prefix (argv[idx_ipv6]->arg, &prefix); - if (ret != 1 || prefix.family != AF_INET6) - { - vty_out (vty, "Malformed argument: %s\n", argv[idx_ipv6]->arg); - return CMD_SUCCESS; - } - - range = ospf6_route_lookup (&prefix, oa->range_table); - if (range == NULL) - { - vty_out (vty, "Range %s does not exists.\n", argv[idx_ipv6]->arg); - return CMD_SUCCESS; - } - - if (ospf6_is_router_abr(oa->ospf6)) - { - /* Blow away the aggregated LSA and route */ - SET_FLAG (range->flag, OSPF6_ROUTE_REMOVE); - - /* Redo summaries if required */ - for (route = ospf6_route_head (ospf6->route_table); route; - route = ospf6_route_next (route)) - ospf6_abr_originate_summary(route); - - /* purge the old aggregated summary LSA */ - ospf6_abr_originate_summary(range); - } - ospf6_route_remove (range, oa->range_table); - - return CMD_SUCCESS; -} + int idx_ipv4 = 2; + int idx_ipv6 = 4; + int ret; + struct ospf6_area *oa; + struct prefix prefix; + struct ospf6_route *range, *route; -void -ospf6_area_config_write (struct vty *vty) -{ - struct listnode *node; - struct ospf6_area *oa; - struct ospf6_route *range; - char buf[PREFIX2STR_BUFFER]; - - for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa)) - { - for (range = ospf6_route_head (oa->range_table); range; - range = ospf6_route_next (range)) - { - prefix2str (&range->prefix, buf, sizeof (buf)); - vty_out (vty, " area %s range %s", oa->name, buf); - - if (CHECK_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) - { - vty_out (vty, " not-advertise"); - } - else - { - // "advertise" is the default so we do not display it - if (range->path.u.cost_config != OSPF_AREA_RANGE_COST_UNSPEC) - vty_out (vty, " cost %d", range->path.u.cost_config); - } - vty_out (vty, "\n"); - - } - if (IS_AREA_STUB (oa)) - { - if (oa->no_summary) - vty_out (vty, " area %s stub no-summary\n", oa->name); - else - vty_out (vty, " area %s stub\n", oa->name); + OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, oa); + + ret = str2prefix(argv[idx_ipv6]->arg, &prefix); + if (ret != 1 || prefix.family != AF_INET6) { + vty_out(vty, "Malformed argument: %s\n", argv[idx_ipv6]->arg); + return CMD_SUCCESS; + } + + range = ospf6_route_lookup(&prefix, oa->range_table); + if (range == NULL) { + vty_out(vty, "Range %s does not exists.\n", + argv[idx_ipv6]->arg); + return CMD_SUCCESS; + } + + if (ospf6_is_router_abr(oa->ospf6)) { + /* Blow away the aggregated LSA and route */ + SET_FLAG(range->flag, OSPF6_ROUTE_REMOVE); + + /* Redo summaries if required */ + for (route = ospf6_route_head(ospf6->route_table); route; + route = ospf6_route_next(route)) + ospf6_abr_originate_summary(route); + + /* purge the old aggregated summary LSA */ + ospf6_abr_originate_summary(range); + } + ospf6_route_remove(range, oa->range_table); + + return CMD_SUCCESS; +} + +void ospf6_area_config_write(struct vty *vty) +{ + struct listnode *node; + struct ospf6_area *oa; + struct ospf6_route *range; + char buf[PREFIX2STR_BUFFER]; + + for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) { + for (range = ospf6_route_head(oa->range_table); range; + range = ospf6_route_next(range)) { + prefix2str(&range->prefix, buf, sizeof(buf)); + vty_out(vty, " area %s range %s", oa->name, buf); + + if (CHECK_FLAG(range->flag, + OSPF6_ROUTE_DO_NOT_ADVERTISE)) { + vty_out(vty, " not-advertise"); + } else { + // "advertise" is the default so we do not + // display it + if (range->path.u.cost_config + != OSPF_AREA_RANGE_COST_UNSPEC) + vty_out(vty, " cost %d", + range->path.u.cost_config); + } + vty_out(vty, "\n"); + } + if (IS_AREA_STUB(oa)) { + if (oa->no_summary) + vty_out(vty, " area %s stub no-summary\n", + oa->name); + else + vty_out(vty, " area %s stub\n", oa->name); + } + if (PREFIX_NAME_IN(oa)) + vty_out(vty, " area %s filter-list prefix %s in\n", + oa->name, PREFIX_NAME_IN(oa)); + if (PREFIX_NAME_OUT(oa)) + vty_out(vty, " area %s filter-list prefix %s out\n", + oa->name, PREFIX_NAME_OUT(oa)); + if (IMPORT_NAME(oa)) + vty_out(vty, " area %s import-list %s\n", oa->name, + IMPORT_NAME(oa)); + if (EXPORT_NAME(oa)) + vty_out(vty, " area %s export-list %s\n", oa->name, + EXPORT_NAME(oa)); } - if (PREFIX_NAME_IN (oa)) - vty_out (vty, " area %s filter-list prefix %s in\n", - oa->name, PREFIX_NAME_IN (oa)); - if (PREFIX_NAME_OUT (oa)) - vty_out (vty, " area %s filter-list prefix %s out\n", - oa->name, PREFIX_NAME_OUT (oa)); - if (IMPORT_NAME (oa)) - vty_out (vty, " area %s import-list %s\n", - oa->name, IMPORT_NAME (oa)); - if (EXPORT_NAME (oa)) - vty_out (vty, " area %s export-list %s\n", - oa->name, EXPORT_NAME (oa)); - } } DEFUN (area_filter_list, @@ -619,38 +567,35 @@ DEFUN (area_filter_list, "Filter networks sent to this area\n" "Filter networks sent from this area\n") { - char *inout = argv[argc - 1]->text; - char *areaid = argv[1]->arg; - char *plistname = argv[4]->arg; - - struct ospf6_area *area; - struct prefix_list *plist; - - OSPF6_CMD_AREA_GET (areaid, area); - - plist = prefix_list_lookup (AFI_IP6, plistname); - if (strmatch (inout, "in")) - { - PREFIX_LIST_IN (area) = plist; - if (PREFIX_NAME_IN (area)) - free (PREFIX_NAME_IN (area)); - - PREFIX_NAME_IN (area) = strdup (plistname); - ospf6_abr_reimport (area); - } - else - { - PREFIX_LIST_OUT (area) = plist; - if (PREFIX_NAME_OUT (area)) - free (PREFIX_NAME_OUT (area)); - - PREFIX_NAME_OUT (area) = strdup (plistname); - ospf6_abr_enable_area (area); - } - - return CMD_SUCCESS; + char *inout = argv[argc - 1]->text; + char *areaid = argv[1]->arg; + char *plistname = argv[4]->arg; + + struct ospf6_area *area; + struct prefix_list *plist; + + OSPF6_CMD_AREA_GET(areaid, area); + + plist = prefix_list_lookup(AFI_IP6, plistname); + if (strmatch(inout, "in")) { + PREFIX_LIST_IN(area) = plist; + if (PREFIX_NAME_IN(area)) + free(PREFIX_NAME_IN(area)); + + PREFIX_NAME_IN(area) = strdup(plistname); + ospf6_abr_reimport(area); + } else { + PREFIX_LIST_OUT(area) = plist; + if (PREFIX_NAME_OUT(area)) + free(PREFIX_NAME_OUT(area)); + + PREFIX_NAME_OUT(area) = strdup(plistname); + ospf6_abr_enable_area(area); + } + + return CMD_SUCCESS; } - + DEFUN (no_area_filter_list, no_area_filter_list_cmd, "no area A.B.C.D filter-list prefix WORD ", @@ -663,42 +608,39 @@ DEFUN (no_area_filter_list, "Filter networks sent to this area\n" "Filter networks sent from this area\n") { - char *inout = argv[argc - 1]->text; - char *areaid = argv[2]->arg; - char *plistname = argv[5]->arg; - - struct ospf6_area *area; - - OSPF6_CMD_AREA_GET (areaid, area); - - if (strmatch (inout, "in")) - { - if (PREFIX_NAME_IN (area)) - if (!strmatch (PREFIX_NAME_IN (area), plistname)) - return CMD_SUCCESS; - - PREFIX_LIST_IN (area) = NULL; - if (PREFIX_NAME_IN (area)) - free (PREFIX_NAME_IN (area)); - - PREFIX_NAME_IN (area) = NULL; - ospf6_abr_reimport (area); - } - else - { - if (PREFIX_NAME_OUT (area)) - if (!strmatch (PREFIX_NAME_OUT (area), plistname)) - return CMD_SUCCESS; - - PREFIX_LIST_OUT (area) = NULL; - if (PREFIX_NAME_OUT (area)) - free (PREFIX_NAME_OUT (area)); - - PREFIX_NAME_OUT (area) = NULL; - ospf6_abr_enable_area (area); - } - - return CMD_SUCCESS; + char *inout = argv[argc - 1]->text; + char *areaid = argv[2]->arg; + char *plistname = argv[5]->arg; + + struct ospf6_area *area; + + OSPF6_CMD_AREA_GET(areaid, area); + + if (strmatch(inout, "in")) { + if (PREFIX_NAME_IN(area)) + if (!strmatch(PREFIX_NAME_IN(area), plistname)) + return CMD_SUCCESS; + + PREFIX_LIST_IN(area) = NULL; + if (PREFIX_NAME_IN(area)) + free(PREFIX_NAME_IN(area)); + + PREFIX_NAME_IN(area) = NULL; + ospf6_abr_reimport(area); + } else { + if (PREFIX_NAME_OUT(area)) + if (!strmatch(PREFIX_NAME_OUT(area), plistname)) + return CMD_SUCCESS; + + PREFIX_LIST_OUT(area) = NULL; + if (PREFIX_NAME_OUT(area)) + free(PREFIX_NAME_OUT(area)); + + PREFIX_NAME_OUT(area) = NULL; + ospf6_abr_enable_area(area); + } + + return CMD_SUCCESS; } DEFUN (area_import_list, @@ -709,24 +651,24 @@ DEFUN (area_import_list, "Set the filter for networks from other areas announced to the specified one\n" "Name of the acess-list\n") { - int idx_ipv4 = 1; - int idx_name = 3; - struct ospf6_area *area; - struct access_list *list; + int idx_ipv4 = 1; + int idx_name = 3; + struct ospf6_area *area; + struct access_list *list; - OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area); + OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area); - list = access_list_lookup (AFI_IP6, argv[idx_name]->arg); + list = access_list_lookup(AFI_IP6, argv[idx_name]->arg); - IMPORT_LIST (area) = list; + IMPORT_LIST(area) = list; - if (IMPORT_NAME (area)) - free (IMPORT_NAME (area)); + if (IMPORT_NAME(area)) + free(IMPORT_NAME(area)); - IMPORT_NAME (area) = strdup (argv[idx_name]->arg); - ospf6_abr_reimport (area); + IMPORT_NAME(area) = strdup(argv[idx_name]->arg); + ospf6_abr_reimport(area); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_area_import_list, @@ -738,20 +680,20 @@ DEFUN (no_area_import_list, "Unset the filter for networks announced to other areas\n" "Name of the access-list\n") { - int idx_ipv4 = 2; - struct ospf6_area *area; + int idx_ipv4 = 2; + struct ospf6_area *area; - OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area); + OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area); - IMPORT_LIST (area) = 0; + IMPORT_LIST(area) = 0; - if (IMPORT_NAME (area)) - free (IMPORT_NAME (area)); + if (IMPORT_NAME(area)) + free(IMPORT_NAME(area)); - IMPORT_NAME (area) = NULL; - ospf6_abr_reimport (area); + IMPORT_NAME(area) = NULL; + ospf6_abr_reimport(area); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (area_export_list, @@ -762,24 +704,24 @@ DEFUN (area_export_list, "Set the filter for networks announced to other areas\n" "Name of the acess-list\n") { - int idx_ipv4 = 1; - int idx_name = 3; - struct ospf6_area *area; - struct access_list *list; + int idx_ipv4 = 1; + int idx_name = 3; + struct ospf6_area *area; + struct access_list *list; - OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area); + OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area); - list = access_list_lookup (AFI_IP6, argv[idx_name]->arg); + list = access_list_lookup(AFI_IP6, argv[idx_name]->arg); - EXPORT_LIST (area) = list; + EXPORT_LIST(area) = list; - if (EXPORT_NAME (area)) - free (EXPORT_NAME (area)); + if (EXPORT_NAME(area)) + free(EXPORT_NAME(area)); - EXPORT_NAME (area) = strdup (argv[idx_name]->arg); - ospf6_abr_enable_area (area); + EXPORT_NAME(area) = strdup(argv[idx_name]->arg); + ospf6_abr_enable_area(area); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_area_export_list, @@ -791,20 +733,20 @@ DEFUN (no_area_export_list, "Unset the filter for networks announced to other areas\n" "Name of the access-list\n") { - int idx_ipv4 = 2; - struct ospf6_area *area; + int idx_ipv4 = 2; + struct ospf6_area *area; - OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area); + OSPF6_CMD_AREA_GET(argv[idx_ipv4]->arg, area); - EXPORT_LIST (area) = 0; + EXPORT_LIST(area) = 0; - if (EXPORT_NAME (area)) - free (EXPORT_NAME (area)); + if (EXPORT_NAME(area)) + free(EXPORT_NAME(area)); - EXPORT_NAME (area) = NULL; - ospf6_abr_enable_area (area); + EXPORT_NAME(area) = NULL; + ospf6_abr_enable_area(area); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_spf_tree, @@ -816,30 +758,28 @@ DEFUN (show_ipv6_ospf6_spf_tree, "Shortest Path First caculation\n" "Show SPF tree\n") { - struct listnode *node; - struct ospf6_area *oa; - struct ospf6_vertex *root; - struct ospf6_route *route; - struct prefix prefix; - - OSPF6_CMD_CHECK_RUNNING (); - - ospf6_linkstate_prefix (ospf6->router_id, htonl (0), &prefix); - - for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa)) - { - route = ospf6_route_lookup (&prefix, oa->spf_table); - if (route == NULL) - { - vty_out (vty, "LS entry for root not found in area %s\n", - oa->name); - continue; - } - root = (struct ospf6_vertex *) route->route_option; - ospf6_spf_display_subtree (vty, "", 0, root); - } - - return CMD_SUCCESS; + struct listnode *node; + struct ospf6_area *oa; + struct ospf6_vertex *root; + struct ospf6_route *route; + struct prefix prefix; + + OSPF6_CMD_CHECK_RUNNING(); + + ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix); + + for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) { + route = ospf6_route_lookup(&prefix, oa->spf_table); + if (route == NULL) { + vty_out(vty, "LS entry for root not found in area %s\n", + oa->name); + continue; + } + root = (struct ospf6_vertex *)route->route_option; + ospf6_spf_display_subtree(vty, "", 0, root); + } + + return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_area_spf_tree, @@ -853,40 +793,37 @@ DEFUN (show_ipv6_ospf6_area_spf_tree, "Shortest Path First caculation\n" "Show SPF tree\n") { - int idx_ipv4 = 4; - u_int32_t area_id; - struct ospf6_area *oa; - struct ospf6_vertex *root; - struct ospf6_route *route; - struct prefix prefix; - - OSPF6_CMD_CHECK_RUNNING (); - - ospf6_linkstate_prefix (ospf6->router_id, htonl (0), &prefix); - - if (inet_pton (AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) - { - vty_out (vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg); - return CMD_SUCCESS; - } - oa = ospf6_area_lookup (area_id, ospf6); - if (oa == NULL) - { - vty_out (vty, "No such Area: %s\n", argv[idx_ipv4]->arg); - return CMD_SUCCESS; - } - - route = ospf6_route_lookup (&prefix, oa->spf_table); - if (route == NULL) - { - vty_out (vty, "LS entry for root not found in area %s\n", - oa->name); - return CMD_SUCCESS; - } - root = (struct ospf6_vertex *) route->route_option; - ospf6_spf_display_subtree (vty, "", 0, root); - - return CMD_SUCCESS; + int idx_ipv4 = 4; + u_int32_t area_id; + struct ospf6_area *oa; + struct ospf6_vertex *root; + struct ospf6_route *route; + struct prefix prefix; + + OSPF6_CMD_CHECK_RUNNING(); + + ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix); + + if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) { + vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg); + return CMD_SUCCESS; + } + oa = ospf6_area_lookup(area_id, ospf6); + if (oa == NULL) { + vty_out(vty, "No such Area: %s\n", argv[idx_ipv4]->arg); + return CMD_SUCCESS; + } + + route = ospf6_route_lookup(&prefix, oa->spf_table); + if (route == NULL) { + vty_out(vty, "LS entry for root not found in area %s\n", + oa->name); + return CMD_SUCCESS; + } + root = (struct ospf6_vertex *)route->route_option; + ospf6_spf_display_subtree(vty, "", 0, root); + + return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_simulate_spf_tree_root, @@ -901,56 +838,53 @@ DEFUN (show_ipv6_ospf6_simulate_spf_tree_root, "OSPF6 area parameters\n" OSPF6_AREA_ID_STR) { - int idx_ipv4 = 5; - int idx_ipv4_2 = 7; - u_int32_t area_id; - struct ospf6_area *oa; - struct ospf6_vertex *root; - struct ospf6_route *route; - struct prefix prefix; - u_int32_t router_id; - struct ospf6_route_table *spf_table; - unsigned char tmp_debug_ospf6_spf = 0; - - OSPF6_CMD_CHECK_RUNNING (); - - inet_pton (AF_INET, argv[idx_ipv4]->arg, &router_id); - ospf6_linkstate_prefix (router_id, htonl (0), &prefix); - - if (inet_pton (AF_INET, argv[idx_ipv4_2]->arg, &area_id) != 1) - { - vty_out (vty, "Malformed Area-ID: %s\n", argv[idx_ipv4_2]->arg); - return CMD_SUCCESS; - } - oa = ospf6_area_lookup (area_id, ospf6); - if (oa == NULL) - { - vty_out (vty, "No such Area: %s\n", argv[idx_ipv4_2]->arg); - return CMD_SUCCESS; - } - - tmp_debug_ospf6_spf = conf_debug_ospf6_spf; - conf_debug_ospf6_spf = 0; - - spf_table = OSPF6_ROUTE_TABLE_CREATE (NONE, SPF_RESULTS); - ospf6_spf_calculation (router_id, spf_table, oa); - - conf_debug_ospf6_spf = tmp_debug_ospf6_spf; - - route = ospf6_route_lookup (&prefix, spf_table); - if (route == NULL) - { - ospf6_spf_table_finish (spf_table); - ospf6_route_table_delete (spf_table); - return CMD_SUCCESS; - } - root = (struct ospf6_vertex *) route->route_option; - ospf6_spf_display_subtree (vty, "", 0, root); - - ospf6_spf_table_finish (spf_table); - ospf6_route_table_delete (spf_table); - - return CMD_SUCCESS; + int idx_ipv4 = 5; + int idx_ipv4_2 = 7; + u_int32_t area_id; + struct ospf6_area *oa; + struct ospf6_vertex *root; + struct ospf6_route *route; + struct prefix prefix; + u_int32_t router_id; + struct ospf6_route_table *spf_table; + unsigned char tmp_debug_ospf6_spf = 0; + + OSPF6_CMD_CHECK_RUNNING(); + + inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id); + ospf6_linkstate_prefix(router_id, htonl(0), &prefix); + + if (inet_pton(AF_INET, argv[idx_ipv4_2]->arg, &area_id) != 1) { + vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4_2]->arg); + return CMD_SUCCESS; + } + oa = ospf6_area_lookup(area_id, ospf6); + if (oa == NULL) { + vty_out(vty, "No such Area: %s\n", argv[idx_ipv4_2]->arg); + return CMD_SUCCESS; + } + + tmp_debug_ospf6_spf = conf_debug_ospf6_spf; + conf_debug_ospf6_spf = 0; + + spf_table = OSPF6_ROUTE_TABLE_CREATE(NONE, SPF_RESULTS); + ospf6_spf_calculation(router_id, spf_table, oa); + + conf_debug_ospf6_spf = tmp_debug_ospf6_spf; + + route = ospf6_route_lookup(&prefix, spf_table); + if (route == NULL) { + ospf6_spf_table_finish(spf_table); + ospf6_route_table_delete(spf_table); + return CMD_SUCCESS; + } + root = (struct ospf6_vertex *)route->route_option; + ospf6_spf_display_subtree(vty, "", 0, root); + + ospf6_spf_table_finish(spf_table); + ospf6_route_table_delete(spf_table); + + return CMD_SUCCESS; } DEFUN (ospf6_area_stub, @@ -961,20 +895,20 @@ DEFUN (ospf6_area_stub, "OSPF6 area ID as a decimal value\n" "Configure OSPF6 area as stub\n") { - int idx_ipv4_number = 1; - struct ospf6_area *area; + int idx_ipv4_number = 1; + struct ospf6_area *area; - OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area); + OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area); - if (!ospf6_area_stub_set (ospf6, area)) - { - vty_out (vty,"First deconfigure all virtual link through this area\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!ospf6_area_stub_set(ospf6, area)) { + vty_out(vty, + "First deconfigure all virtual link through this area\n"); + return CMD_WARNING_CONFIG_FAILED; + } - ospf6_area_no_summary_unset (ospf6, area); + ospf6_area_no_summary_unset(ospf6, area); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ospf6_area_stub_no_summary, @@ -986,20 +920,20 @@ DEFUN (ospf6_area_stub_no_summary, "Configure OSPF6 area as stub\n" "Do not inject inter-area routes into stub\n") { - int idx_ipv4_number = 1; - struct ospf6_area *area; + int idx_ipv4_number = 1; + struct ospf6_area *area; - OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area); + OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area); - if (!ospf6_area_stub_set (ospf6, area)) - { - vty_out (vty,"First deconfigure all virtual link through this area\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!ospf6_area_stub_set(ospf6, area)) { + vty_out(vty, + "First deconfigure all virtual link through this area\n"); + return CMD_WARNING_CONFIG_FAILED; + } - ospf6_area_no_summary_set (ospf6, area); + ospf6_area_no_summary_set(ospf6, area); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf6_area_stub, @@ -1011,15 +945,15 @@ DEFUN (no_ospf6_area_stub, "OSPF6 area ID as a decimal value\n" "Configure OSPF6 area as stub\n") { - int idx_ipv4_number = 2; - struct ospf6_area *area; + int idx_ipv4_number = 2; + struct ospf6_area *area; - OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area); + OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area); - ospf6_area_stub_unset (ospf6, area); - ospf6_area_no_summary_unset (ospf6, area); + ospf6_area_stub_unset(ospf6, area); + ospf6_area_no_summary_unset(ospf6, area); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf6_area_stub_no_summary, @@ -1032,40 +966,36 @@ DEFUN (no_ospf6_area_stub_no_summary, "Configure OSPF6 area as stub\n" "Do not inject inter-area routes into area\n") { - int idx_ipv4_number = 2; - struct ospf6_area *area; + int idx_ipv4_number = 2; + struct ospf6_area *area; - OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area); + OSPF6_CMD_AREA_GET(argv[idx_ipv4_number]->arg, area); - ospf6_area_stub_unset (ospf6, area); - ospf6_area_no_summary_unset (ospf6, area); + ospf6_area_stub_unset(ospf6, area); + ospf6_area_no_summary_unset(ospf6, area); - return CMD_SUCCESS; + return CMD_SUCCESS; } -void -ospf6_area_init (void) +void ospf6_area_init(void) { - install_element (VIEW_NODE, &show_ipv6_ospf6_spf_tree_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd); - - install_element (OSPF6_NODE, &area_range_cmd); - install_element (OSPF6_NODE, &no_area_range_cmd); - install_element (OSPF6_NODE, &ospf6_area_stub_no_summary_cmd); - install_element (OSPF6_NODE, &ospf6_area_stub_cmd); - install_element (OSPF6_NODE, &no_ospf6_area_stub_no_summary_cmd); - install_element (OSPF6_NODE, &no_ospf6_area_stub_cmd); + install_element(VIEW_NODE, &show_ipv6_ospf6_spf_tree_cmd); + install_element(VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd); + install_element(VIEW_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd); + install_element(OSPF6_NODE, &area_range_cmd); + install_element(OSPF6_NODE, &no_area_range_cmd); + install_element(OSPF6_NODE, &ospf6_area_stub_no_summary_cmd); + install_element(OSPF6_NODE, &ospf6_area_stub_cmd); + install_element(OSPF6_NODE, &no_ospf6_area_stub_no_summary_cmd); + install_element(OSPF6_NODE, &no_ospf6_area_stub_cmd); - install_element (OSPF6_NODE, &area_import_list_cmd); - install_element (OSPF6_NODE, &no_area_import_list_cmd); - install_element (OSPF6_NODE, &area_export_list_cmd); - install_element (OSPF6_NODE, &no_area_export_list_cmd); - install_element (OSPF6_NODE, &area_filter_list_cmd); - install_element (OSPF6_NODE, &no_area_filter_list_cmd); + install_element(OSPF6_NODE, &area_import_list_cmd); + install_element(OSPF6_NODE, &no_area_import_list_cmd); + install_element(OSPF6_NODE, &area_export_list_cmd); + install_element(OSPF6_NODE, &no_area_export_list_cmd); + install_element(OSPF6_NODE, &area_filter_list_cmd); + install_element(OSPF6_NODE, &no_area_filter_list_cmd); } - - diff --git a/ospf6d/ospf6_area.h b/ospf6d/ospf6_area.h index 86c68af17..4bc24a6dd 100644 --- a/ospf6d/ospf6_area.h +++ b/ospf6d/ospf6_area.h @@ -23,85 +23,81 @@ #include "ospf6_top.h" -struct ospf6_area -{ - /* Reference to Top data structure */ - struct ospf6 *ospf6; +struct ospf6_area { + /* Reference to Top data structure */ + struct ospf6 *ospf6; - /* Area-ID */ - u_int32_t area_id; + /* Area-ID */ + u_int32_t area_id; #define OSPF6_AREA_FMT_DOTTEDQUAD 1 #define OSPF6_AREA_FMT_DECIMAL 2 - /* Area-ID string */ - char name[16]; + /* Area-ID string */ + char name[16]; - /* flag */ - u_char flag; + /* flag */ + u_char flag; - /* OSPF Option */ - u_char options[3]; + /* OSPF Option */ + u_char options[3]; - /* Summary routes to be originated (includes Configured Address Ranges) */ - struct ospf6_route_table *range_table; - struct ospf6_route_table *summary_prefix; - struct ospf6_route_table *summary_router; + /* Summary routes to be originated (includes Configured Address Ranges) + */ + struct ospf6_route_table *range_table; + struct ospf6_route_table *summary_prefix; + struct ospf6_route_table *summary_router; - /* Area type */ - int no_summary; + /* Area type */ + int no_summary; - /* OSPF interface list */ - struct list *if_list; + /* OSPF interface list */ + struct list *if_list; - struct ospf6_lsdb *lsdb; - struct ospf6_lsdb *lsdb_self; + struct ospf6_lsdb *lsdb; + struct ospf6_lsdb *lsdb_self; - struct ospf6_route_table *spf_table; - struct ospf6_route_table *route_table; + struct ospf6_route_table *spf_table; + struct ospf6_route_table *route_table; - u_int32_t spf_calculation; /* SPF calculation count */ + u_int32_t spf_calculation; /* SPF calculation count */ - struct thread *thread_router_lsa; - struct thread *thread_intra_prefix_lsa; - u_int32_t router_lsa_size_limit; + struct thread *thread_router_lsa; + struct thread *thread_intra_prefix_lsa; + u_int32_t router_lsa_size_limit; - /* Area announce list */ - struct - { - char *name; - struct access_list *list; - } _export; + /* Area announce list */ + struct { + char *name; + struct access_list *list; + } _export; #define EXPORT_NAME(A) (A)->_export.name #define EXPORT_LIST(A) (A)->_export.list - /* Area acceptance list */ - struct - { - char *name; - struct access_list *list; - } import; + /* Area acceptance list */ + struct { + char *name; + struct access_list *list; + } import; #define IMPORT_NAME(A) (A)->import.name #define IMPORT_LIST(A) (A)->import.list - /* Type 3 LSA Area prefix-list */ - struct - { - char *name; - struct prefix_list *list; - } plist_in; + /* Type 3 LSA Area prefix-list */ + struct { + char *name; + struct prefix_list *list; + } plist_in; #define PREFIX_NAME_IN(A) (A)->plist_in.name #define PREFIX_LIST_IN(A) (A)->plist_in.list - struct - { - char *name; - struct prefix_list *list; - } plist_out; + struct { + char *name; + struct prefix_list *list; + } plist_out; #define PREFIX_NAME_OUT(A) (A)->plist_out.name #define PREFIX_LIST_OUT(A) (A)->plist_out.list - /* Time stamps. */ - struct timeval ts_spf; /* SPF calculation time stamp. */ + /* Time stamps. */ + struct timeval ts_spf; /* SPF calculation time stamp. */ }; #define OSPF6_AREA_ENABLE 0x01 @@ -115,18 +111,18 @@ struct ospf6_area #define IS_AREA_STUB(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_STUB)) /* prototypes */ -extern int ospf6_area_cmp (void *va, void *vb); +extern int ospf6_area_cmp(void *va, void *vb); -extern struct ospf6_area *ospf6_area_create (u_int32_t, struct ospf6 *, int); -extern void ospf6_area_delete (struct ospf6_area *); -extern struct ospf6_area *ospf6_area_lookup (u_int32_t, struct ospf6 *); +extern struct ospf6_area *ospf6_area_create(u_int32_t, struct ospf6 *, int); +extern void ospf6_area_delete(struct ospf6_area *); +extern struct ospf6_area *ospf6_area_lookup(u_int32_t, struct ospf6 *); -extern void ospf6_area_enable (struct ospf6_area *); -extern void ospf6_area_disable (struct ospf6_area *); +extern void ospf6_area_enable(struct ospf6_area *); +extern void ospf6_area_disable(struct ospf6_area *); -extern void ospf6_area_show (struct vty *, struct ospf6_area *); +extern void ospf6_area_show(struct vty *, struct ospf6_area *); -extern void ospf6_area_config_write (struct vty *vty); -extern void ospf6_area_init (void); +extern void ospf6_area_config_write(struct vty *vty); +extern void ospf6_area_init(void); #endif /* OSPF_AREA_H */ diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index 3404ba020..7f8341d0e 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -52,632 +52,584 @@ unsigned char conf_debug_ospf6_asbr = 0; #define ZROUTE_NAME(x) zebra_route_string(x) /* AS External LSA origination */ -static void -ospf6_as_external_lsa_originate (struct ospf6_route *route) +static void ospf6_as_external_lsa_originate(struct ospf6_route *route) { - char buffer[OSPF6_MAX_LSASIZE]; - struct ospf6_lsa_header *lsa_header; - struct ospf6_lsa *lsa; - struct ospf6_external_info *info = route->route_option; - - struct ospf6_as_external_lsa *as_external_lsa; - char buf[PREFIX2STR_BUFFER]; - caddr_t p; - - if (IS_OSPF6_DEBUG_ASBR || IS_OSPF6_DEBUG_ORIGINATE (AS_EXTERNAL)) - { - prefix2str (&route->prefix, buf, sizeof (buf)); - zlog_debug ("Originate AS-External-LSA for %s", buf); - } - - /* prepare buffer */ - memset (buffer, 0, sizeof (buffer)); - lsa_header = (struct ospf6_lsa_header *) buffer; - as_external_lsa = (struct ospf6_as_external_lsa *) - ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); - p = (caddr_t) - ((caddr_t) as_external_lsa + sizeof (struct ospf6_as_external_lsa)); - - /* Fill AS-External-LSA */ - /* Metric type */ - if (route->path.metric_type == 2) - SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E); - else - UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E); - - /* forwarding address */ - if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding)) - SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F); - else - UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F); - - /* external route tag */ - if (info->tag) - SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T); - else - UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T); - - /* Set metric */ - OSPF6_ASBR_METRIC_SET (as_external_lsa, route->path.cost); - - /* prefixlen */ - as_external_lsa->prefix.prefix_length = route->prefix.prefixlen; - - /* PrefixOptions */ - as_external_lsa->prefix.prefix_options = route->path.prefix_options; - - /* don't use refer LS-type */ - as_external_lsa->prefix.prefix_refer_lstype = htons (0); - - /* set Prefix */ - memcpy (p, &route->prefix.u.prefix6, - OSPF6_PREFIX_SPACE (route->prefix.prefixlen)); - ospf6_prefix_apply_mask (&as_external_lsa->prefix); - p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen); - - /* Forwarding address */ - if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F)) - { - memcpy (p, &info->forwarding, sizeof (struct in6_addr)); - p += sizeof (struct in6_addr); - } - - /* External Route Tag */ - if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T)) - { - route_tag_t network_order = htonl(info->tag); - - memcpy (p, &network_order, sizeof(network_order)); - p += sizeof(network_order); - } - - /* Fill LSA Header */ - lsa_header->age = 0; - lsa_header->type = htons (OSPF6_LSTYPE_AS_EXTERNAL); - lsa_header->id = route->path.origin.id; - lsa_header->adv_router = ospf6->router_id; - lsa_header->seqnum = - ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id, - lsa_header->adv_router, ospf6->lsdb); - lsa_header->length = htons ((caddr_t) p - (caddr_t) lsa_header); - - /* LSA checksum */ - ospf6_lsa_checksum (lsa_header); - - /* create LSA */ - lsa = ospf6_lsa_create (lsa_header); - - /* Originate */ - ospf6_lsa_originate_process (lsa, ospf6); + char buffer[OSPF6_MAX_LSASIZE]; + struct ospf6_lsa_header *lsa_header; + struct ospf6_lsa *lsa; + struct ospf6_external_info *info = route->route_option; + + struct ospf6_as_external_lsa *as_external_lsa; + char buf[PREFIX2STR_BUFFER]; + caddr_t p; + + if (IS_OSPF6_DEBUG_ASBR || IS_OSPF6_DEBUG_ORIGINATE(AS_EXTERNAL)) { + prefix2str(&route->prefix, buf, sizeof(buf)); + zlog_debug("Originate AS-External-LSA for %s", buf); + } + + /* prepare buffer */ + memset(buffer, 0, sizeof(buffer)); + lsa_header = (struct ospf6_lsa_header *)buffer; + as_external_lsa = (struct ospf6_as_external_lsa + *)((caddr_t)lsa_header + + sizeof(struct ospf6_lsa_header)); + p = (caddr_t)((caddr_t)as_external_lsa + + sizeof(struct ospf6_as_external_lsa)); + + /* Fill AS-External-LSA */ + /* Metric type */ + if (route->path.metric_type == 2) + SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E); + else + UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E); + + /* forwarding address */ + if (!IN6_IS_ADDR_UNSPECIFIED(&info->forwarding)) + SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F); + else + UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F); + + /* external route tag */ + if (info->tag) + SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T); + else + UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T); + + /* Set metric */ + OSPF6_ASBR_METRIC_SET(as_external_lsa, route->path.cost); + + /* prefixlen */ + as_external_lsa->prefix.prefix_length = route->prefix.prefixlen; + + /* PrefixOptions */ + as_external_lsa->prefix.prefix_options = route->path.prefix_options; + + /* don't use refer LS-type */ + as_external_lsa->prefix.prefix_refer_lstype = htons(0); + + /* set Prefix */ + memcpy(p, &route->prefix.u.prefix6, + OSPF6_PREFIX_SPACE(route->prefix.prefixlen)); + ospf6_prefix_apply_mask(&as_external_lsa->prefix); + p += OSPF6_PREFIX_SPACE(route->prefix.prefixlen); + + /* Forwarding address */ + if (CHECK_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F)) { + memcpy(p, &info->forwarding, sizeof(struct in6_addr)); + p += sizeof(struct in6_addr); + } + + /* External Route Tag */ + if (CHECK_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T)) { + route_tag_t network_order = htonl(info->tag); + + memcpy(p, &network_order, sizeof(network_order)); + p += sizeof(network_order); + } + + /* Fill LSA Header */ + lsa_header->age = 0; + lsa_header->type = htons(OSPF6_LSTYPE_AS_EXTERNAL); + lsa_header->id = route->path.origin.id; + lsa_header->adv_router = ospf6->router_id; + lsa_header->seqnum = + ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id, + lsa_header->adv_router, ospf6->lsdb); + lsa_header->length = htons((caddr_t)p - (caddr_t)lsa_header); + + /* LSA checksum */ + ospf6_lsa_checksum(lsa_header); + + /* create LSA */ + lsa = ospf6_lsa_create(lsa_header); + + /* Originate */ + ospf6_lsa_originate_process(lsa, ospf6); } -static route_tag_t -ospf6_as_external_lsa_get_tag (struct ospf6_lsa *lsa) +static route_tag_t ospf6_as_external_lsa_get_tag(struct ospf6_lsa *lsa) { - struct ospf6_as_external_lsa *external; - ptrdiff_t tag_offset; - route_tag_t network_order; + struct ospf6_as_external_lsa *external; + ptrdiff_t tag_offset; + route_tag_t network_order; - if (!lsa) - return 0; + if (!lsa) + return 0; - external = (struct ospf6_as_external_lsa *) - OSPF6_LSA_HEADER_END (lsa->header); + external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END( + lsa->header); - if (!CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T)) - return 0; + if (!CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_T)) + return 0; - tag_offset = sizeof(*external) + OSPF6_PREFIX_SPACE(external->prefix.prefix_length); - if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F)) - tag_offset += sizeof(struct in6_addr); + tag_offset = sizeof(*external) + + OSPF6_PREFIX_SPACE(external->prefix.prefix_length); + if (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_F)) + tag_offset += sizeof(struct in6_addr); - memcpy(&network_order, (caddr_t)external + tag_offset, sizeof(network_order)); - return ntohl(network_order); + memcpy(&network_order, (caddr_t)external + tag_offset, + sizeof(network_order)); + return ntohl(network_order); } -void -ospf6_asbr_lsa_add (struct ospf6_lsa *lsa) +void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa) { - struct ospf6_as_external_lsa *external; - struct prefix asbr_id; - struct ospf6_route *asbr_entry, *route; - char buf[PREFIX2STR_BUFFER]; - - external = (struct ospf6_as_external_lsa *) - OSPF6_LSA_HEADER_END (lsa->header); - - if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL)) - zlog_debug ("Calculate AS-External route for %s", lsa->name); - - if (lsa->header->adv_router == ospf6->router_id) - { - if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL)) - zlog_debug ("Ignore self-originated AS-External-LSA"); - return; - } - - if (OSPF6_ASBR_METRIC (external) == OSPF_LS_INFINITY) - { - if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL)) - zlog_debug ("Ignore LSA with LSInfinity Metric"); - return; - } - - if (CHECK_FLAG(external->prefix.prefix_options, OSPF6_PREFIX_OPTION_NU)) - { - if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL)) - zlog_debug ("Ignore LSA with NU bit set Metric"); - return; - } - - ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &asbr_id); - asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->brouter_table); - if (asbr_entry == NULL || - ! CHECK_FLAG (asbr_entry->path.router_bits, OSPF6_ROUTER_BIT_E)) - { - if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL)) - { - prefix2str (&asbr_id, buf, sizeof (buf)); - zlog_debug ("ASBR entry not found: %s", buf); - } - return; - } - - route = ospf6_route_create (); - route->type = OSPF6_DEST_TYPE_NETWORK; - route->prefix.family = AF_INET6; - route->prefix.prefixlen = external->prefix.prefix_length; - ospf6_prefix_in6_addr (&route->prefix.u.prefix6, &external->prefix); - - route->path.area_id = asbr_entry->path.area_id; - route->path.origin.type = lsa->header->type; - route->path.origin.id = lsa->header->id; - route->path.origin.adv_router = lsa->header->adv_router; - - route->path.prefix_options = external->prefix.prefix_options; - if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E)) - { - route->path.type = OSPF6_PATH_TYPE_EXTERNAL2; - route->path.metric_type = 2; - route->path.cost = asbr_entry->path.cost; - route->path.u.cost_e2 = OSPF6_ASBR_METRIC (external); - } - else - { - route->path.type = OSPF6_PATH_TYPE_EXTERNAL1; - route->path.metric_type = 1; - route->path.cost = asbr_entry->path.cost + OSPF6_ASBR_METRIC (external); - route->path.u.cost_e2 = 0; - } - - route->path.tag = ospf6_as_external_lsa_get_tag (lsa); - - ospf6_route_copy_nexthops (route, asbr_entry); - - if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL)) - { - prefix2str (&route->prefix, buf, sizeof (buf)); - zlog_debug ("AS-External route add: %s", buf); - } - - ospf6_route_add (route, ospf6->route_table); + struct ospf6_as_external_lsa *external; + struct prefix asbr_id; + struct ospf6_route *asbr_entry, *route; + char buf[PREFIX2STR_BUFFER]; + + external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END( + lsa->header); + + if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) + zlog_debug("Calculate AS-External route for %s", lsa->name); + + if (lsa->header->adv_router == ospf6->router_id) { + if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) + zlog_debug("Ignore self-originated AS-External-LSA"); + return; + } + + if (OSPF6_ASBR_METRIC(external) == OSPF_LS_INFINITY) { + if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) + zlog_debug("Ignore LSA with LSInfinity Metric"); + return; + } + + if (CHECK_FLAG(external->prefix.prefix_options, + OSPF6_PREFIX_OPTION_NU)) { + if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) + zlog_debug("Ignore LSA with NU bit set Metric"); + return; + } + + ospf6_linkstate_prefix(lsa->header->adv_router, htonl(0), &asbr_id); + asbr_entry = ospf6_route_lookup(&asbr_id, ospf6->brouter_table); + if (asbr_entry == NULL + || !CHECK_FLAG(asbr_entry->path.router_bits, OSPF6_ROUTER_BIT_E)) { + if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) { + prefix2str(&asbr_id, buf, sizeof(buf)); + zlog_debug("ASBR entry not found: %s", buf); + } + return; + } + + route = ospf6_route_create(); + route->type = OSPF6_DEST_TYPE_NETWORK; + route->prefix.family = AF_INET6; + route->prefix.prefixlen = external->prefix.prefix_length; + ospf6_prefix_in6_addr(&route->prefix.u.prefix6, &external->prefix); + + route->path.area_id = asbr_entry->path.area_id; + route->path.origin.type = lsa->header->type; + route->path.origin.id = lsa->header->id; + route->path.origin.adv_router = lsa->header->adv_router; + + route->path.prefix_options = external->prefix.prefix_options; + if (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_E)) { + route->path.type = OSPF6_PATH_TYPE_EXTERNAL2; + route->path.metric_type = 2; + route->path.cost = asbr_entry->path.cost; + route->path.u.cost_e2 = OSPF6_ASBR_METRIC(external); + } else { + route->path.type = OSPF6_PATH_TYPE_EXTERNAL1; + route->path.metric_type = 1; + route->path.cost = + asbr_entry->path.cost + OSPF6_ASBR_METRIC(external); + route->path.u.cost_e2 = 0; + } + + route->path.tag = ospf6_as_external_lsa_get_tag(lsa); + + ospf6_route_copy_nexthops(route, asbr_entry); + + if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) { + prefix2str(&route->prefix, buf, sizeof(buf)); + zlog_debug("AS-External route add: %s", buf); + } + + ospf6_route_add(route, ospf6->route_table); } -void -ospf6_asbr_lsa_remove (struct ospf6_lsa *lsa) +void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa) { - struct ospf6_as_external_lsa *external; - struct prefix prefix; - struct ospf6_route *route, *nroute; - char buf[PREFIX2STR_BUFFER]; - - external = (struct ospf6_as_external_lsa *) - OSPF6_LSA_HEADER_END (lsa->header); - - if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL)) - zlog_debug ("Withdraw AS-External route for %s", lsa->name); - - if (lsa->header->adv_router == ospf6->router_id) - { - if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL)) - zlog_debug ("Ignore self-originated AS-External-LSA"); - return; - } - - memset (&prefix, 0, sizeof (struct prefix)); - prefix.family = AF_INET6; - prefix.prefixlen = external->prefix.prefix_length; - ospf6_prefix_in6_addr (&prefix.u.prefix6, &external->prefix); - - route = ospf6_route_lookup (&prefix, ospf6->route_table); - if (route == NULL) - { - if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL)) - { - prefix2str (&prefix, buf, sizeof (buf)); - zlog_debug ("AS-External route %s not found", buf); - } - return; - } - - for (ospf6_route_lock (route); - route && ospf6_route_is_prefix (&prefix, route); - route = nroute) - { - nroute = ospf6_route_next (route); - if (route->type != OSPF6_DEST_TYPE_NETWORK) - continue; - if (route->path.origin.type != lsa->header->type) - continue; - if (route->path.origin.id != lsa->header->id) - continue; - if (route->path.origin.adv_router != lsa->header->adv_router) - continue; - - if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL)) - { - prefix2str (&route->prefix, buf, sizeof (buf)); - zlog_debug ("AS-External route remove: %s", buf); - } - ospf6_route_remove (route, ospf6->route_table); - } - if (route != NULL) - ospf6_route_unlock (route); + struct ospf6_as_external_lsa *external; + struct prefix prefix; + struct ospf6_route *route, *nroute; + char buf[PREFIX2STR_BUFFER]; + + external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END( + lsa->header); + + if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) + zlog_debug("Withdraw AS-External route for %s", lsa->name); + + if (lsa->header->adv_router == ospf6->router_id) { + if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) + zlog_debug("Ignore self-originated AS-External-LSA"); + return; + } + + memset(&prefix, 0, sizeof(struct prefix)); + prefix.family = AF_INET6; + prefix.prefixlen = external->prefix.prefix_length; + ospf6_prefix_in6_addr(&prefix.u.prefix6, &external->prefix); + + route = ospf6_route_lookup(&prefix, ospf6->route_table); + if (route == NULL) { + if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) { + prefix2str(&prefix, buf, sizeof(buf)); + zlog_debug("AS-External route %s not found", buf); + } + return; + } + + for (ospf6_route_lock(route); + route && ospf6_route_is_prefix(&prefix, route); route = nroute) { + nroute = ospf6_route_next(route); + if (route->type != OSPF6_DEST_TYPE_NETWORK) + continue; + if (route->path.origin.type != lsa->header->type) + continue; + if (route->path.origin.id != lsa->header->id) + continue; + if (route->path.origin.adv_router != lsa->header->adv_router) + continue; + + if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) { + prefix2str(&route->prefix, buf, sizeof(buf)); + zlog_debug("AS-External route remove: %s", buf); + } + ospf6_route_remove(route, ospf6->route_table); + } + if (route != NULL) + ospf6_route_unlock(route); } -void -ospf6_asbr_lsentry_add (struct ospf6_route *asbr_entry) +void ospf6_asbr_lsentry_add(struct ospf6_route *asbr_entry) { - struct ospf6_lsa *lsa; - u_int16_t type; - u_int32_t router; - - if (! CHECK_FLAG (asbr_entry->flag, OSPF6_ROUTE_BEST)) - { - char buf[16]; - inet_ntop (AF_INET, &ADV_ROUTER_IN_PREFIX (&asbr_entry->prefix), - buf, sizeof (buf)); - zlog_info ("ignore non-best path: lsentry %s add", buf); - return; - } - - type = htons (OSPF6_LSTYPE_AS_EXTERNAL); - router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix); - for (ALL_LSDB_TYPED_ADVRTR(ospf6->lsdb, type, router, lsa)) - { - if (! OSPF6_LSA_IS_MAXAGE (lsa)) - ospf6_asbr_lsa_add (lsa); - } + struct ospf6_lsa *lsa; + u_int16_t type; + u_int32_t router; + + if (!CHECK_FLAG(asbr_entry->flag, OSPF6_ROUTE_BEST)) { + char buf[16]; + inet_ntop(AF_INET, &ADV_ROUTER_IN_PREFIX(&asbr_entry->prefix), + buf, sizeof(buf)); + zlog_info("ignore non-best path: lsentry %s add", buf); + return; + } + + type = htons(OSPF6_LSTYPE_AS_EXTERNAL); + router = ospf6_linkstate_prefix_adv_router(&asbr_entry->prefix); + for (ALL_LSDB_TYPED_ADVRTR(ospf6->lsdb, type, router, lsa)) { + if (!OSPF6_LSA_IS_MAXAGE(lsa)) + ospf6_asbr_lsa_add(lsa); + } } -void -ospf6_asbr_lsentry_remove (struct ospf6_route *asbr_entry) +void ospf6_asbr_lsentry_remove(struct ospf6_route *asbr_entry) { - struct ospf6_lsa *lsa; - u_int16_t type; - u_int32_t router; - - type = htons (OSPF6_LSTYPE_AS_EXTERNAL); - router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix); - for (ALL_LSDB_TYPED_ADVRTR(ospf6->lsdb, type, router, lsa)) - ospf6_asbr_lsa_remove (lsa); + struct ospf6_lsa *lsa; + u_int16_t type; + u_int32_t router; + + type = htons(OSPF6_LSTYPE_AS_EXTERNAL); + router = ospf6_linkstate_prefix_adv_router(&asbr_entry->prefix); + for (ALL_LSDB_TYPED_ADVRTR(ospf6->lsdb, type, router, lsa)) + ospf6_asbr_lsa_remove(lsa); } - /* redistribute function */ -static void -ospf6_asbr_routemap_set (int type, const char *mapname) +static void ospf6_asbr_routemap_set(int type, const char *mapname) { - if (ospf6->rmap[type].name) - free (ospf6->rmap[type].name); - ospf6->rmap[type].name = strdup (mapname); - ospf6->rmap[type].map = route_map_lookup_by_name (mapname); + if (ospf6->rmap[type].name) + free(ospf6->rmap[type].name); + ospf6->rmap[type].name = strdup(mapname); + ospf6->rmap[type].map = route_map_lookup_by_name(mapname); } -static void -ospf6_asbr_routemap_unset (int type) +static void ospf6_asbr_routemap_unset(int type) { - if (ospf6->rmap[type].name) - free (ospf6->rmap[type].name); - ospf6->rmap[type].name = NULL; - ospf6->rmap[type].map = NULL; + if (ospf6->rmap[type].name) + free(ospf6->rmap[type].name); + ospf6->rmap[type].name = NULL; + ospf6->rmap[type].map = NULL; } -static void -ospf6_asbr_routemap_update (const char *mapname) +static void ospf6_asbr_routemap_update(const char *mapname) { - int type; - - if (ospf6 == NULL) - return; - - for (type = 0; type < ZEBRA_ROUTE_MAX; type++) - { - if (ospf6->rmap[type].name) - ospf6->rmap[type].map = - route_map_lookup_by_name (ospf6->rmap[type].name); - else - ospf6->rmap[type].map = NULL; - } + int type; + + if (ospf6 == NULL) + return; + + for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { + if (ospf6->rmap[type].name) + ospf6->rmap[type].map = route_map_lookup_by_name( + ospf6->rmap[type].name); + else + ospf6->rmap[type].map = NULL; + } } -int -ospf6_asbr_is_asbr (struct ospf6 *o) +int ospf6_asbr_is_asbr(struct ospf6 *o) { - return o->external_table->count; + return o->external_table->count; } -static void -ospf6_asbr_redistribute_set (int type) +static void ospf6_asbr_redistribute_set(int type) { - ospf6_zebra_redistribute (type); + ospf6_zebra_redistribute(type); } -static void -ospf6_asbr_redistribute_unset (int type) +static void ospf6_asbr_redistribute_unset(int type) { - struct ospf6_route *route; - struct ospf6_external_info *info; + struct ospf6_route *route; + struct ospf6_external_info *info; - ospf6_zebra_no_redistribute (type); + ospf6_zebra_no_redistribute(type); - for (route = ospf6_route_head (ospf6->external_table); route; - route = ospf6_route_next (route)) - { - info = route->route_option; - if (info->type != type) - continue; + for (route = ospf6_route_head(ospf6->external_table); route; + route = ospf6_route_next(route)) { + info = route->route_option; + if (info->type != type) + continue; - ospf6_asbr_redistribute_remove (info->type, 0, &route->prefix); - } + ospf6_asbr_redistribute_remove(info->type, 0, &route->prefix); + } - ospf6_asbr_routemap_unset (type); + ospf6_asbr_routemap_unset(type); } /* When an area is unstubified, flood all the external LSAs in the area */ -void -ospf6_asbr_send_externals_to_area (struct ospf6_area *oa) +void ospf6_asbr_send_externals_to_area(struct ospf6_area *oa) { - struct ospf6_lsa *lsa; - - for (ALL_LSDB(oa->ospf6->lsdb, lsa)) - { - if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL) - { - zlog_debug ("%s: Flooding AS-External LSA %s\n", __func__, lsa->name); - ospf6_flood_area (NULL, lsa, oa); + struct ospf6_lsa *lsa; + + for (ALL_LSDB(oa->ospf6->lsdb, lsa)) { + if (ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL) { + zlog_debug("%s: Flooding AS-External LSA %s\n", + __func__, lsa->name); + ospf6_flood_area(NULL, lsa, oa); + } } - } } -void -ospf6_asbr_redistribute_add (int type, ifindex_t ifindex, struct prefix *prefix, - u_int nexthop_num, struct in6_addr *nexthop, route_tag_t tag) +void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex, + struct prefix *prefix, u_int nexthop_num, + struct in6_addr *nexthop, route_tag_t tag) { - int ret; - struct ospf6_route troute; - struct ospf6_external_info tinfo; - struct ospf6_route *route, *match; - struct ospf6_external_info *info; - struct prefix prefix_id; - struct route_node *node; - char pbuf[PREFIX2STR_BUFFER], ibuf[16]; - struct listnode *lnode, *lnnode; - struct ospf6_area *oa; - - if (! ospf6_zebra_is_redistribute (type)) - return; - - if (IS_OSPF6_DEBUG_ASBR) - { - prefix2str (prefix, pbuf, sizeof (pbuf)); - zlog_debug ("Redistribute %s (%s)", pbuf, ZROUTE_NAME (type)); - } - - /* if route-map was specified but not found, do not advertise */ - if (ospf6->rmap[type].name) - { - if (ospf6->rmap[type].map == NULL) - ospf6_asbr_routemap_update (NULL); - if (ospf6->rmap[type].map == NULL) - { - zlog_warn ("route-map \"%s\" not found, suppress redistributing", - ospf6->rmap[type].name); - return; - } - } - - /* apply route-map */ - if (ospf6->rmap[type].map) - { - memset (&troute, 0, sizeof (troute)); - memset (&tinfo, 0, sizeof (tinfo)); - troute.route_option = &tinfo; - tinfo.ifindex = ifindex; - tinfo.tag = tag; - - ret = route_map_apply (ospf6->rmap[type].map, prefix, - RMAP_OSPF6, &troute); - if (ret == RMAP_DENYMATCH) - { - if (IS_OSPF6_DEBUG_ASBR) - zlog_debug ("Denied by route-map \"%s\"", ospf6->rmap[type].name); - return; - } - } - - match = ospf6_route_lookup (prefix, ospf6->external_table); - if (match) - { - info = match->route_option; - - /* copy result of route-map */ - if (ospf6->rmap[type].map) - { - if (troute.path.metric_type) - match->path.metric_type = troute.path.metric_type; - if (troute.path.cost) - match->path.cost = troute.path.cost; - if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding)) - memcpy (&info->forwarding, &tinfo.forwarding, - sizeof (struct in6_addr)); - info->tag = tinfo.tag; - } - else - { - /* If there is no route-map, simply update the tag */ - info->tag = tag; - } - - info->type = type; - - if (nexthop_num && nexthop) - ospf6_route_add_nexthop (match, ifindex, nexthop); - else - ospf6_route_add_nexthop (match, ifindex, NULL); - - /* create/update binding in external_id_table */ - prefix_id.family = AF_INET; - prefix_id.prefixlen = 32; - prefix_id.u.prefix4.s_addr = htonl (info->id); - node = route_node_get (ospf6->external_id_table, &prefix_id); - node->info = match; - - if (IS_OSPF6_DEBUG_ASBR) - { - inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf)); - zlog_debug ("Advertise as AS-External Id:%s", ibuf); - } - - match->path.origin.id = htonl (info->id); - ospf6_as_external_lsa_originate (match); - return; - } - - /* create new entry */ - route = ospf6_route_create (); - route->type = OSPF6_DEST_TYPE_NETWORK; - memcpy (&route->prefix, prefix, sizeof (struct prefix)); - - info = (struct ospf6_external_info *) - XCALLOC (MTYPE_OSPF6_EXTERNAL_INFO, sizeof (struct ospf6_external_info)); - route->route_option = info; - info->id = ospf6->external_id++; - - /* copy result of route-map */ - if (ospf6->rmap[type].map) - { - if (troute.path.metric_type) - route->path.metric_type = troute.path.metric_type; - if (troute.path.cost) - route->path.cost = troute.path.cost; - if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding)) - memcpy (&info->forwarding, &tinfo.forwarding, - sizeof (struct in6_addr)); - info->tag = tinfo.tag; - } - else - { - /* If there is no route-map, simply set the tag */ - info->tag = tag; - } - - info->type = type; - if (nexthop_num && nexthop) - ospf6_route_add_nexthop (route, ifindex, nexthop); - else - ospf6_route_add_nexthop (route, ifindex, NULL); - - /* create/update binding in external_id_table */ - prefix_id.family = AF_INET; - prefix_id.prefixlen = 32; - prefix_id.u.prefix4.s_addr = htonl (info->id); - node = route_node_get (ospf6->external_id_table, &prefix_id); - node->info = route; - - route = ospf6_route_add (route, ospf6->external_table); - route->route_option = info; - - if (IS_OSPF6_DEBUG_ASBR) - { - inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf)); - zlog_debug ("Advertise as AS-External Id:%s", ibuf); - } - - route->path.origin.id = htonl (info->id); - ospf6_as_external_lsa_originate (route); - - /* Router-Bit (ASBR Flag) may have to be updated */ - for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa)) - OSPF6_ROUTER_LSA_SCHEDULE (oa); + int ret; + struct ospf6_route troute; + struct ospf6_external_info tinfo; + struct ospf6_route *route, *match; + struct ospf6_external_info *info; + struct prefix prefix_id; + struct route_node *node; + char pbuf[PREFIX2STR_BUFFER], ibuf[16]; + struct listnode *lnode, *lnnode; + struct ospf6_area *oa; + + if (!ospf6_zebra_is_redistribute(type)) + return; + + if (IS_OSPF6_DEBUG_ASBR) { + prefix2str(prefix, pbuf, sizeof(pbuf)); + zlog_debug("Redistribute %s (%s)", pbuf, ZROUTE_NAME(type)); + } + + /* if route-map was specified but not found, do not advertise */ + if (ospf6->rmap[type].name) { + if (ospf6->rmap[type].map == NULL) + ospf6_asbr_routemap_update(NULL); + if (ospf6->rmap[type].map == NULL) { + zlog_warn( + "route-map \"%s\" not found, suppress redistributing", + ospf6->rmap[type].name); + return; + } + } + + /* apply route-map */ + if (ospf6->rmap[type].map) { + memset(&troute, 0, sizeof(troute)); + memset(&tinfo, 0, sizeof(tinfo)); + troute.route_option = &tinfo; + tinfo.ifindex = ifindex; + tinfo.tag = tag; + + ret = route_map_apply(ospf6->rmap[type].map, prefix, RMAP_OSPF6, + &troute); + if (ret == RMAP_DENYMATCH) { + if (IS_OSPF6_DEBUG_ASBR) + zlog_debug("Denied by route-map \"%s\"", + ospf6->rmap[type].name); + return; + } + } + + match = ospf6_route_lookup(prefix, ospf6->external_table); + if (match) { + info = match->route_option; + + /* copy result of route-map */ + if (ospf6->rmap[type].map) { + if (troute.path.metric_type) + match->path.metric_type = + troute.path.metric_type; + if (troute.path.cost) + match->path.cost = troute.path.cost; + if (!IN6_IS_ADDR_UNSPECIFIED(&tinfo.forwarding)) + memcpy(&info->forwarding, &tinfo.forwarding, + sizeof(struct in6_addr)); + info->tag = tinfo.tag; + } else { + /* If there is no route-map, simply update the tag */ + info->tag = tag; + } + + info->type = type; + + if (nexthop_num && nexthop) + ospf6_route_add_nexthop(match, ifindex, nexthop); + else + ospf6_route_add_nexthop(match, ifindex, NULL); + + /* create/update binding in external_id_table */ + prefix_id.family = AF_INET; + prefix_id.prefixlen = 32; + prefix_id.u.prefix4.s_addr = htonl(info->id); + node = route_node_get(ospf6->external_id_table, &prefix_id); + node->info = match; + + if (IS_OSPF6_DEBUG_ASBR) { + inet_ntop(AF_INET, &prefix_id.u.prefix4, ibuf, + sizeof(ibuf)); + zlog_debug("Advertise as AS-External Id:%s", ibuf); + } + + match->path.origin.id = htonl(info->id); + ospf6_as_external_lsa_originate(match); + return; + } + + /* create new entry */ + route = ospf6_route_create(); + route->type = OSPF6_DEST_TYPE_NETWORK; + memcpy(&route->prefix, prefix, sizeof(struct prefix)); + + info = (struct ospf6_external_info *)XCALLOC( + MTYPE_OSPF6_EXTERNAL_INFO, sizeof(struct ospf6_external_info)); + route->route_option = info; + info->id = ospf6->external_id++; + + /* copy result of route-map */ + if (ospf6->rmap[type].map) { + if (troute.path.metric_type) + route->path.metric_type = troute.path.metric_type; + if (troute.path.cost) + route->path.cost = troute.path.cost; + if (!IN6_IS_ADDR_UNSPECIFIED(&tinfo.forwarding)) + memcpy(&info->forwarding, &tinfo.forwarding, + sizeof(struct in6_addr)); + info->tag = tinfo.tag; + } else { + /* If there is no route-map, simply set the tag */ + info->tag = tag; + } + + info->type = type; + if (nexthop_num && nexthop) + ospf6_route_add_nexthop(route, ifindex, nexthop); + else + ospf6_route_add_nexthop(route, ifindex, NULL); + + /* create/update binding in external_id_table */ + prefix_id.family = AF_INET; + prefix_id.prefixlen = 32; + prefix_id.u.prefix4.s_addr = htonl(info->id); + node = route_node_get(ospf6->external_id_table, &prefix_id); + node->info = route; + + route = ospf6_route_add(route, ospf6->external_table); + route->route_option = info; + + if (IS_OSPF6_DEBUG_ASBR) { + inet_ntop(AF_INET, &prefix_id.u.prefix4, ibuf, sizeof(ibuf)); + zlog_debug("Advertise as AS-External Id:%s", ibuf); + } + + route->path.origin.id = htonl(info->id); + ospf6_as_external_lsa_originate(route); + + /* Router-Bit (ASBR Flag) may have to be updated */ + for (ALL_LIST_ELEMENTS(ospf6->area_list, lnode, lnnode, oa)) + OSPF6_ROUTER_LSA_SCHEDULE(oa); } -void -ospf6_asbr_redistribute_remove (int type, ifindex_t ifindex, - struct prefix *prefix) +void ospf6_asbr_redistribute_remove(int type, ifindex_t ifindex, + struct prefix *prefix) { - struct ospf6_route *match; - struct ospf6_external_info *info = NULL; - struct route_node *node; - struct ospf6_lsa *lsa; - struct prefix prefix_id; - char pbuf[PREFIX2STR_BUFFER], ibuf[16]; - struct listnode *lnode, *lnnode; - struct ospf6_area *oa; - - match = ospf6_route_lookup (prefix, ospf6->external_table); - if (match == NULL) - { - if (IS_OSPF6_DEBUG_ASBR) - { - prefix2str (prefix, pbuf, sizeof (pbuf)); - zlog_debug ("No such route %s to withdraw", pbuf); - } - return; - } - - info = match->route_option; - assert (info); - - if (info->type != type) - { - if (IS_OSPF6_DEBUG_ASBR) - { - prefix2str (prefix, pbuf, sizeof (pbuf)); - zlog_debug ("Original protocol mismatch: %s", pbuf); - } - return; - } - - if (IS_OSPF6_DEBUG_ASBR) - { - prefix2str (prefix, pbuf, sizeof (pbuf)); - inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf)); - zlog_debug ("Withdraw %s (AS-External Id:%s)", pbuf, ibuf); - } - - lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL), - htonl (info->id), ospf6->router_id, ospf6->lsdb); - if (lsa) - ospf6_lsa_purge (lsa); - - /* remove binding in external_id_table */ - prefix_id.family = AF_INET; - prefix_id.prefixlen = 32; - prefix_id.u.prefix4.s_addr = htonl (info->id); - node = route_node_lookup (ospf6->external_id_table, &prefix_id); - assert (node); - node->info = NULL; - route_unlock_node (node); - - ospf6_route_remove (match, ospf6->external_table); - XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info); - - /* Router-Bit (ASBR Flag) may have to be updated */ - for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa)) - OSPF6_ROUTER_LSA_SCHEDULE (oa); + struct ospf6_route *match; + struct ospf6_external_info *info = NULL; + struct route_node *node; + struct ospf6_lsa *lsa; + struct prefix prefix_id; + char pbuf[PREFIX2STR_BUFFER], ibuf[16]; + struct listnode *lnode, *lnnode; + struct ospf6_area *oa; + + match = ospf6_route_lookup(prefix, ospf6->external_table); + if (match == NULL) { + if (IS_OSPF6_DEBUG_ASBR) { + prefix2str(prefix, pbuf, sizeof(pbuf)); + zlog_debug("No such route %s to withdraw", pbuf); + } + return; + } + + info = match->route_option; + assert(info); + + if (info->type != type) { + if (IS_OSPF6_DEBUG_ASBR) { + prefix2str(prefix, pbuf, sizeof(pbuf)); + zlog_debug("Original protocol mismatch: %s", pbuf); + } + return; + } + + if (IS_OSPF6_DEBUG_ASBR) { + prefix2str(prefix, pbuf, sizeof(pbuf)); + inet_ntop(AF_INET, &prefix_id.u.prefix4, ibuf, sizeof(ibuf)); + zlog_debug("Withdraw %s (AS-External Id:%s)", pbuf, ibuf); + } + + lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL), + htonl(info->id), ospf6->router_id, ospf6->lsdb); + if (lsa) + ospf6_lsa_purge(lsa); + + /* remove binding in external_id_table */ + prefix_id.family = AF_INET; + prefix_id.prefixlen = 32; + prefix_id.u.prefix4.s_addr = htonl(info->id); + node = route_node_lookup(ospf6->external_id_table, &prefix_id); + assert(node); + node->info = NULL; + route_unlock_node(node); + + ospf6_route_remove(match, ospf6->external_table); + XFREE(MTYPE_OSPF6_EXTERNAL_INFO, info); + + /* Router-Bit (ASBR Flag) may have to be updated */ + for (ALL_LIST_ELEMENTS(ospf6->area_list, lnode, lnnode, oa)) + OSPF6_ROUTER_LSA_SCHEDULE(oa); } DEFUN (ospf6_redistribute, @@ -686,16 +638,16 @@ DEFUN (ospf6_redistribute, "Redistribute\n" FRR_REDIST_HELP_STR_OSPF6D) { - int type; + int type; - char *proto = argv[argc - 1]->text; - type = proto_redistnum(AFI_IP6, proto); - if (type < 0) - return CMD_WARNING_CONFIG_FAILED; + char *proto = argv[argc - 1]->text; + type = proto_redistnum(AFI_IP6, proto); + if (type < 0) + return CMD_WARNING_CONFIG_FAILED; - ospf6_asbr_redistribute_unset (type); - ospf6_asbr_redistribute_set (type); - return CMD_SUCCESS; + ospf6_asbr_redistribute_unset(type); + ospf6_asbr_redistribute_set(type); + return CMD_SUCCESS; } DEFUN (ospf6_redistribute_routemap, @@ -706,19 +658,19 @@ DEFUN (ospf6_redistribute_routemap, "Route map reference\n" "Route map name\n") { - int idx_protocol = 1; - int idx_word = 3; - int type; - - char *proto = argv[idx_protocol]->text; - type = proto_redistnum(AFI_IP6, proto); - if (type < 0) - return CMD_WARNING_CONFIG_FAILED; - - ospf6_asbr_redistribute_unset (type); - ospf6_asbr_routemap_set (type, argv[idx_word]->arg); - ospf6_asbr_redistribute_set (type); - return CMD_SUCCESS; + int idx_protocol = 1; + int idx_word = 3; + int type; + + char *proto = argv[idx_protocol]->text; + type = proto_redistnum(AFI_IP6, proto); + if (type < 0) + return CMD_WARNING_CONFIG_FAILED; + + ospf6_asbr_redistribute_unset(type); + ospf6_asbr_routemap_set(type, argv[idx_word]->arg); + ospf6_asbr_redistribute_set(type); + return CMD_SUCCESS; } DEFUN (no_ospf6_redistribute, @@ -730,364 +682,323 @@ DEFUN (no_ospf6_redistribute, "Route map reference\n" "Route map name\n") { - int idx_protocol = 2; - int type; + int idx_protocol = 2; + int type; - char *proto = argv[idx_protocol]->text; - type = proto_redistnum(AFI_IP6, proto); - if (type < 0) - return CMD_WARNING_CONFIG_FAILED; + char *proto = argv[idx_protocol]->text; + type = proto_redistnum(AFI_IP6, proto); + if (type < 0) + return CMD_WARNING_CONFIG_FAILED; - ospf6_asbr_redistribute_unset (type); + ospf6_asbr_redistribute_unset(type); - return CMD_SUCCESS; + return CMD_SUCCESS; } -int -ospf6_redistribute_config_write (struct vty *vty) +int ospf6_redistribute_config_write(struct vty *vty) { - int type; - - for (type = 0; type < ZEBRA_ROUTE_MAX; type++) - { - if (type == ZEBRA_ROUTE_OSPF6) - continue; - if (! ospf6_zebra_is_redistribute (type)) - continue; - - if (ospf6->rmap[type].name) - vty_out (vty, " redistribute %s route-map %s\n", - ZROUTE_NAME (type), ospf6->rmap[type].name); - else - vty_out (vty, " redistribute %s\n", - ZROUTE_NAME (type)); - } - - return 0; + int type; + + for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { + if (type == ZEBRA_ROUTE_OSPF6) + continue; + if (!ospf6_zebra_is_redistribute(type)) + continue; + + if (ospf6->rmap[type].name) + vty_out(vty, " redistribute %s route-map %s\n", + ZROUTE_NAME(type), ospf6->rmap[type].name); + else + vty_out(vty, " redistribute %s\n", ZROUTE_NAME(type)); + } + + return 0; } -static void -ospf6_redistribute_show_config (struct vty *vty) +static void ospf6_redistribute_show_config(struct vty *vty) { - int type; - int nroute[ZEBRA_ROUTE_MAX]; - int total; - struct ospf6_route *route; - struct ospf6_external_info *info; - - total = 0; - for (type = 0; type < ZEBRA_ROUTE_MAX; type++) - nroute[type] = 0; - for (route = ospf6_route_head (ospf6->external_table); route; - route = ospf6_route_next (route)) - { - info = route->route_option; - nroute[info->type]++; - total++; - } - - vty_out (vty, "Redistributing External Routes from:\n"); - for (type = 0; type < ZEBRA_ROUTE_MAX; type++) - { - if (type == ZEBRA_ROUTE_OSPF6) - continue; - if (! ospf6_zebra_is_redistribute (type)) - continue; - - if (ospf6->rmap[type].name) - vty_out (vty, " %d: %s with route-map \"%s\"%s\n", nroute[type], - ZROUTE_NAME (type), ospf6->rmap[type].name, - (ospf6->rmap[type].map ? "" : " (not found !)")); - else - vty_out (vty, " %d: %s\n", nroute[type], - ZROUTE_NAME (type)); - } - vty_out (vty, "Total %d routes\n", total); -} + int type; + int nroute[ZEBRA_ROUTE_MAX]; + int total; + struct ospf6_route *route; + struct ospf6_external_info *info; + + total = 0; + for (type = 0; type < ZEBRA_ROUTE_MAX; type++) + nroute[type] = 0; + for (route = ospf6_route_head(ospf6->external_table); route; + route = ospf6_route_next(route)) { + info = route->route_option; + nroute[info->type]++; + total++; + } + vty_out(vty, "Redistributing External Routes from:\n"); + for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { + if (type == ZEBRA_ROUTE_OSPF6) + continue; + if (!ospf6_zebra_is_redistribute(type)) + continue; + + if (ospf6->rmap[type].name) + vty_out(vty, " %d: %s with route-map \"%s\"%s\n", + nroute[type], ZROUTE_NAME(type), + ospf6->rmap[type].name, + (ospf6->rmap[type].map ? "" + : " (not found !)")); + else + vty_out(vty, " %d: %s\n", nroute[type], + ZROUTE_NAME(type)); + } + vty_out(vty, "Total %d routes\n", total); +} /* Routemap Functions */ static route_map_result_t -ospf6_routemap_rule_match_address_prefixlist (void *rule, - struct prefix *prefix, - route_map_object_t type, - void *object) +ospf6_routemap_rule_match_address_prefixlist(void *rule, struct prefix *prefix, + route_map_object_t type, + void *object) { - struct prefix_list *plist; + struct prefix_list *plist; - if (type != RMAP_OSPF6) - return RMAP_NOMATCH; + if (type != RMAP_OSPF6) + return RMAP_NOMATCH; - plist = prefix_list_lookup (AFI_IP6, (char *) rule); - if (plist == NULL) - return RMAP_NOMATCH; + plist = prefix_list_lookup(AFI_IP6, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; - return (prefix_list_apply (plist, prefix) == PREFIX_DENY ? - RMAP_NOMATCH : RMAP_MATCH); + return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH + : RMAP_MATCH); } static void * -ospf6_routemap_rule_match_address_prefixlist_compile (const char *arg) +ospf6_routemap_rule_match_address_prefixlist_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -ospf6_routemap_rule_match_address_prefixlist_free (void *rule) +static void ospf6_routemap_rule_match_address_prefixlist_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -struct route_map_rule_cmd -ospf6_routemap_rule_match_address_prefixlist_cmd = -{ - "ipv6 address prefix-list", - ospf6_routemap_rule_match_address_prefixlist, - ospf6_routemap_rule_match_address_prefixlist_compile, - ospf6_routemap_rule_match_address_prefixlist_free, +struct route_map_rule_cmd ospf6_routemap_rule_match_address_prefixlist_cmd = { + "ipv6 address prefix-list", + ospf6_routemap_rule_match_address_prefixlist, + ospf6_routemap_rule_match_address_prefixlist_compile, + ospf6_routemap_rule_match_address_prefixlist_free, }; /* `match interface IFNAME' */ /* Match function should return 1 if match is success else return zero. */ static route_map_result_t -ospf6_routemap_rule_match_interface (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +ospf6_routemap_rule_match_interface(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - struct interface *ifp; - struct ospf6_external_info *ei; + struct interface *ifp; + struct ospf6_external_info *ei; - if (type == RMAP_OSPF6) - { - ei = ((struct ospf6_route *) object)->route_option; - ifp = if_lookup_by_name ((char *)rule, VRF_DEFAULT); + if (type == RMAP_OSPF6) { + ei = ((struct ospf6_route *)object)->route_option; + ifp = if_lookup_by_name((char *)rule, VRF_DEFAULT); - if (ifp != NULL - && ei->ifindex == ifp->ifindex) - return RMAP_MATCH; - } + if (ifp != NULL && ei->ifindex == ifp->ifindex) + return RMAP_MATCH; + } - return RMAP_NOMATCH; + return RMAP_NOMATCH; } /* Route map `interface' match statement. `arg' should be interface name. */ -static void * -ospf6_routemap_rule_match_interface_compile (const char *arg) +static void *ospf6_routemap_rule_match_interface_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `interface' value. */ -static void -ospf6_routemap_rule_match_interface_free (void *rule) +static void ospf6_routemap_rule_match_interface_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for interface matching. */ -struct route_map_rule_cmd -ospf6_routemap_rule_match_interface_cmd = -{ - "interface", - ospf6_routemap_rule_match_interface, - ospf6_routemap_rule_match_interface_compile, - ospf6_routemap_rule_match_interface_free -}; +struct route_map_rule_cmd ospf6_routemap_rule_match_interface_cmd = { + "interface", ospf6_routemap_rule_match_interface, + ospf6_routemap_rule_match_interface_compile, + ospf6_routemap_rule_match_interface_free}; /* Match function for matching route tags */ -static route_map_result_t -ospf6_routemap_rule_match_tag (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t ospf6_routemap_rule_match_tag(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - route_tag_t *tag = rule; - struct ospf6_route *route = object; - struct ospf6_external_info *info = route->route_option; + route_tag_t *tag = rule; + struct ospf6_route *route = object; + struct ospf6_external_info *info = route->route_option; - if (type == RMAP_OSPF6 && info->tag == *tag) - return RMAP_MATCH; + if (type == RMAP_OSPF6 && info->tag == *tag) + return RMAP_MATCH; - return RMAP_NOMATCH; + return RMAP_NOMATCH; } -static struct route_map_rule_cmd -ospf6_routemap_rule_match_tag_cmd = -{ - "tag", - ospf6_routemap_rule_match_tag, - route_map_rule_tag_compile, - route_map_rule_tag_free, +static struct route_map_rule_cmd ospf6_routemap_rule_match_tag_cmd = { + "tag", ospf6_routemap_rule_match_tag, route_map_rule_tag_compile, + route_map_rule_tag_free, }; static route_map_result_t -ospf6_routemap_rule_set_metric_type (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +ospf6_routemap_rule_set_metric_type(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - char *metric_type = rule; - struct ospf6_route *route = object; + char *metric_type = rule; + struct ospf6_route *route = object; - if (type != RMAP_OSPF6) - return RMAP_OKAY; + if (type != RMAP_OSPF6) + return RMAP_OKAY; - if (strcmp (metric_type, "type-2") == 0) - route->path.metric_type = 2; - else - route->path.metric_type = 1; + if (strcmp(metric_type, "type-2") == 0) + route->path.metric_type = 2; + else + route->path.metric_type = 1; - return RMAP_OKAY; + return RMAP_OKAY; } -static void * -ospf6_routemap_rule_set_metric_type_compile (const char *arg) +static void *ospf6_routemap_rule_set_metric_type_compile(const char *arg) { - if (strcmp (arg, "type-2") && strcmp (arg, "type-1")) - return NULL; - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + if (strcmp(arg, "type-2") && strcmp(arg, "type-1")) + return NULL; + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -ospf6_routemap_rule_set_metric_type_free (void *rule) +static void ospf6_routemap_rule_set_metric_type_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -struct route_map_rule_cmd -ospf6_routemap_rule_set_metric_type_cmd = -{ - "metric-type", - ospf6_routemap_rule_set_metric_type, - ospf6_routemap_rule_set_metric_type_compile, - ospf6_routemap_rule_set_metric_type_free, +struct route_map_rule_cmd ospf6_routemap_rule_set_metric_type_cmd = { + "metric-type", ospf6_routemap_rule_set_metric_type, + ospf6_routemap_rule_set_metric_type_compile, + ospf6_routemap_rule_set_metric_type_free, }; static route_map_result_t -ospf6_routemap_rule_set_metric (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +ospf6_routemap_rule_set_metric(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - char *metric = rule; - struct ospf6_route *route = object; + char *metric = rule; + struct ospf6_route *route = object; - if (type != RMAP_OSPF6) - return RMAP_OKAY; + if (type != RMAP_OSPF6) + return RMAP_OKAY; - route->path.cost = atoi (metric); - return RMAP_OKAY; + route->path.cost = atoi(metric); + return RMAP_OKAY; } -static void * -ospf6_routemap_rule_set_metric_compile (const char *arg) +static void *ospf6_routemap_rule_set_metric_compile(const char *arg) { - u_int32_t metric; - char *endp; - metric = strtoul (arg, &endp, 0); - if (metric > OSPF_LS_INFINITY || *endp != '\0') - return NULL; - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + u_int32_t metric; + char *endp; + metric = strtoul(arg, &endp, 0); + if (metric > OSPF_LS_INFINITY || *endp != '\0') + return NULL; + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -ospf6_routemap_rule_set_metric_free (void *rule) +static void ospf6_routemap_rule_set_metric_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -struct route_map_rule_cmd -ospf6_routemap_rule_set_metric_cmd = -{ - "metric", - ospf6_routemap_rule_set_metric, - ospf6_routemap_rule_set_metric_compile, - ospf6_routemap_rule_set_metric_free, +struct route_map_rule_cmd ospf6_routemap_rule_set_metric_cmd = { + "metric", ospf6_routemap_rule_set_metric, + ospf6_routemap_rule_set_metric_compile, + ospf6_routemap_rule_set_metric_free, }; static route_map_result_t -ospf6_routemap_rule_set_forwarding (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +ospf6_routemap_rule_set_forwarding(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - char *forwarding = rule; - struct ospf6_route *route = object; - struct ospf6_external_info *info = route->route_option; + char *forwarding = rule; + struct ospf6_route *route = object; + struct ospf6_external_info *info = route->route_option; - if (type != RMAP_OSPF6) - return RMAP_OKAY; + if (type != RMAP_OSPF6) + return RMAP_OKAY; - if (inet_pton (AF_INET6, forwarding, &info->forwarding) != 1) - { - memset (&info->forwarding, 0, sizeof (struct in6_addr)); - return RMAP_ERROR; - } + if (inet_pton(AF_INET6, forwarding, &info->forwarding) != 1) { + memset(&info->forwarding, 0, sizeof(struct in6_addr)); + return RMAP_ERROR; + } - return RMAP_OKAY; + return RMAP_OKAY; } -static void * -ospf6_routemap_rule_set_forwarding_compile (const char *arg) +static void *ospf6_routemap_rule_set_forwarding_compile(const char *arg) { - struct in6_addr a; - if (inet_pton (AF_INET6, arg, &a) != 1) - return NULL; - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + struct in6_addr a; + if (inet_pton(AF_INET6, arg, &a) != 1) + return NULL; + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -ospf6_routemap_rule_set_forwarding_free (void *rule) +static void ospf6_routemap_rule_set_forwarding_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -struct route_map_rule_cmd -ospf6_routemap_rule_set_forwarding_cmd = -{ - "forwarding-address", - ospf6_routemap_rule_set_forwarding, - ospf6_routemap_rule_set_forwarding_compile, - ospf6_routemap_rule_set_forwarding_free, +struct route_map_rule_cmd ospf6_routemap_rule_set_forwarding_cmd = { + "forwarding-address", ospf6_routemap_rule_set_forwarding, + ospf6_routemap_rule_set_forwarding_compile, + ospf6_routemap_rule_set_forwarding_free, }; -static route_map_result_t -ospf6_routemap_rule_set_tag (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t ospf6_routemap_rule_set_tag(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - route_tag_t *tag = rule; - struct ospf6_route *route = object; - struct ospf6_external_info *info = route->route_option; + route_tag_t *tag = rule; + struct ospf6_route *route = object; + struct ospf6_external_info *info = route->route_option; - if (type != RMAP_OSPF6) - return RMAP_OKAY; + if (type != RMAP_OSPF6) + return RMAP_OKAY; - info->tag = *tag; - return RMAP_OKAY; + info->tag = *tag; + return RMAP_OKAY; } -static struct route_map_rule_cmd -ospf6_routemap_rule_set_tag_cmd = -{ - "tag", - ospf6_routemap_rule_set_tag, - route_map_rule_tag_compile, - route_map_rule_tag_free, +static struct route_map_rule_cmd ospf6_routemap_rule_set_tag_cmd = { + "tag", ospf6_routemap_rule_set_tag, route_map_rule_tag_compile, + route_map_rule_tag_free, }; -static int -route_map_command_status (struct vty *vty, int ret) +static int route_map_command_status(struct vty *vty, int ret) { - if (! ret) - return CMD_SUCCESS; - - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "OSPF6 Can't find rule.\n"); - break; - case RMAP_COMPILE_ERROR: - vty_out (vty, "OSPF6 Argument is malformed.\n"); - break; - default: - vty_out (vty, "OSPF6 route-map add set failed.\n"); - break; - } - return CMD_WARNING_CONFIG_FAILED; + if (!ret) + return CMD_SUCCESS; + + switch (ret) { + case RMAP_RULE_MISSING: + vty_out(vty, "OSPF6 Can't find rule.\n"); + break; + case RMAP_COMPILE_ERROR: + vty_out(vty, "OSPF6 Argument is malformed.\n"); + break; + default: + vty_out(vty, "OSPF6 route-map add set failed.\n"); + break; + } + return CMD_WARNING_CONFIG_FAILED; } /* add "set metric-type" */ @@ -1099,11 +1010,11 @@ DEFUN (ospf6_routemap_set_metric_type, "OSPF6 external type 1 metric\n" "OSPF6 external type 2 metric\n") { - VTY_DECLVAR_CONTEXT(route_map_index, route_map_index); - int idx_external = 2; - int ret = route_map_add_set (route_map_index, - "metric-type", argv[idx_external]->arg); - return route_map_command_status (vty, ret); + VTY_DECLVAR_CONTEXT(route_map_index, route_map_index); + int idx_external = 2; + int ret = route_map_add_set(route_map_index, "metric-type", + argv[idx_external]->arg); + return route_map_command_status(vty, ret); } /* delete "set metric-type" */ @@ -1116,11 +1027,10 @@ DEFUN (ospf6_routemap_no_set_metric_type, "OSPF6 external type 1 metric\n" "OSPF6 external type 2 metric\n") { - VTY_DECLVAR_CONTEXT(route_map_index, route_map_index); - char *ext = (argc == 4) ? argv[3]->text : NULL; - int ret = route_map_delete_set (route_map_index, - "metric-type", ext); - return route_map_command_status (vty, ret); + VTY_DECLVAR_CONTEXT(route_map_index, route_map_index); + char *ext = (argc == 4) ? argv[3]->text : NULL; + int ret = route_map_delete_set(route_map_index, "metric-type", ext); + return route_map_command_status(vty, ret); } /* add "set forwarding-address" */ @@ -1131,11 +1041,11 @@ DEFUN (ospf6_routemap_set_forwarding, "Forwarding Address\n" "IPv6 Address\n") { - VTY_DECLVAR_CONTEXT(route_map_index, route_map_index); - int idx_ipv6 = 2; - int ret = route_map_add_set (route_map_index, - "forwarding-address", argv[idx_ipv6]->arg); - return route_map_command_status (vty, ret); + VTY_DECLVAR_CONTEXT(route_map_index, route_map_index); + int idx_ipv6 = 2; + int ret = route_map_add_set(route_map_index, "forwarding-address", + argv[idx_ipv6]->arg); + return route_map_command_status(vty, ret); } /* delete "set forwarding-address" */ @@ -1147,154 +1057,158 @@ DEFUN (ospf6_routemap_no_set_forwarding, "Forwarding Address\n" "IPv6 Address\n") { - VTY_DECLVAR_CONTEXT(route_map_index, route_map_index); - int idx_ipv6 = 3; - int ret = route_map_delete_set (route_map_index, - "forwarding-address", argv[idx_ipv6]->arg); - return route_map_command_status (vty, ret); + VTY_DECLVAR_CONTEXT(route_map_index, route_map_index); + int idx_ipv6 = 3; + int ret = route_map_delete_set(route_map_index, "forwarding-address", + argv[idx_ipv6]->arg); + return route_map_command_status(vty, ret); } -static void -ospf6_routemap_init (void) +static void ospf6_routemap_init(void) { - route_map_init (); + route_map_init(); - route_map_add_hook (ospf6_asbr_routemap_update); - route_map_delete_hook (ospf6_asbr_routemap_update); + route_map_add_hook(ospf6_asbr_routemap_update); + route_map_delete_hook(ospf6_asbr_routemap_update); - route_map_set_metric_hook (generic_set_add); - route_map_no_set_metric_hook (generic_set_delete); + route_map_set_metric_hook(generic_set_add); + route_map_no_set_metric_hook(generic_set_delete); - route_map_match_tag_hook (generic_match_add); - route_map_no_match_tag_hook (generic_match_delete); + route_map_match_tag_hook(generic_match_add); + route_map_no_match_tag_hook(generic_match_delete); - route_map_match_ipv6_address_prefix_list_hook (generic_match_add); - route_map_no_match_ipv6_address_prefix_list_hook (generic_match_delete); + route_map_match_ipv6_address_prefix_list_hook(generic_match_add); + route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete); - route_map_match_interface_hook (generic_match_add); - route_map_no_match_interface_hook (generic_match_delete); + route_map_match_interface_hook(generic_match_add); + route_map_no_match_interface_hook(generic_match_delete); - route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd); - route_map_install_match (&ospf6_routemap_rule_match_interface_cmd); - route_map_install_match (&ospf6_routemap_rule_match_tag_cmd); + route_map_install_match( + &ospf6_routemap_rule_match_address_prefixlist_cmd); + route_map_install_match(&ospf6_routemap_rule_match_interface_cmd); + route_map_install_match(&ospf6_routemap_rule_match_tag_cmd); - route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd); - route_map_install_set (&ospf6_routemap_rule_set_metric_cmd); - route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd); - route_map_install_set (&ospf6_routemap_rule_set_tag_cmd); + route_map_install_set(&ospf6_routemap_rule_set_metric_type_cmd); + route_map_install_set(&ospf6_routemap_rule_set_metric_cmd); + route_map_install_set(&ospf6_routemap_rule_set_forwarding_cmd); + route_map_install_set(&ospf6_routemap_rule_set_tag_cmd); - /* ASE Metric Type (e.g. Type-1/Type-2) */ - install_element (RMAP_NODE, &ospf6_routemap_set_metric_type_cmd); - install_element (RMAP_NODE, &ospf6_routemap_no_set_metric_type_cmd); + /* ASE Metric Type (e.g. Type-1/Type-2) */ + install_element(RMAP_NODE, &ospf6_routemap_set_metric_type_cmd); + install_element(RMAP_NODE, &ospf6_routemap_no_set_metric_type_cmd); - /* ASE Metric */ - install_element (RMAP_NODE, &ospf6_routemap_set_forwarding_cmd); - install_element (RMAP_NODE, &ospf6_routemap_no_set_forwarding_cmd); + /* ASE Metric */ + install_element(RMAP_NODE, &ospf6_routemap_set_forwarding_cmd); + install_element(RMAP_NODE, &ospf6_routemap_no_set_forwarding_cmd); } /* Display functions */ -static char * -ospf6_as_external_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf, - int buflen, int pos) +static char *ospf6_as_external_lsa_get_prefix_str(struct ospf6_lsa *lsa, + char *buf, int buflen, + int pos) { - struct ospf6_as_external_lsa *external; - struct in6_addr in6; - int prefix_length = 0; - - if (lsa) - { - external = (struct ospf6_as_external_lsa *) - OSPF6_LSA_HEADER_END (lsa->header); - - if (pos == 0) - { - ospf6_prefix_in6_addr (&in6, &external->prefix); - prefix_length = external->prefix.prefix_length; - } - else { - in6 = *((struct in6_addr *) - ((caddr_t) external + sizeof (struct ospf6_as_external_lsa) + - OSPF6_PREFIX_SPACE (external->prefix.prefix_length))); + struct ospf6_as_external_lsa *external; + struct in6_addr in6; + int prefix_length = 0; + + if (lsa) { + external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END( + lsa->header); + + if (pos == 0) { + ospf6_prefix_in6_addr(&in6, &external->prefix); + prefix_length = external->prefix.prefix_length; + } else { + in6 = *((struct in6_addr + *)((caddr_t)external + + sizeof(struct + ospf6_as_external_lsa) + + OSPF6_PREFIX_SPACE( + external->prefix + .prefix_length))); + } + if (buf) { + inet_ntop(AF_INET6, &in6, buf, buflen); + if (prefix_length) + sprintf(&buf[strlen(buf)], "/%d", + prefix_length); + } } - if (buf) - { - inet_ntop (AF_INET6, &in6, buf, buflen); - if (prefix_length) - sprintf (&buf[strlen(buf)], "/%d", prefix_length); - } - } - return (buf); + return (buf); } -static int -ospf6_as_external_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) +static int ospf6_as_external_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) { - struct ospf6_as_external_lsa *external; - char buf[64]; - - assert (lsa->header); - external = (struct ospf6_as_external_lsa *) - OSPF6_LSA_HEADER_END (lsa->header); - - /* bits */ - snprintf (buf, sizeof (buf), "%c%c%c", - (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E) ? 'E' : '-'), - (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F) ? 'F' : '-'), - (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T) ? 'T' : '-')); - - vty_out (vty, " Bits: %s\n", buf); - vty_out (vty, " Metric: %5lu\n", (u_long) OSPF6_ASBR_METRIC (external)); - - ospf6_prefix_options_printbuf (external->prefix.prefix_options, - buf, sizeof (buf)); - vty_out (vty, " Prefix Options: %s\n", buf); - - vty_out (vty, " Referenced LSType: %d\n", - ntohs (external->prefix.prefix_refer_lstype)); - - vty_out (vty, " Prefix: %s\n", - ospf6_as_external_lsa_get_prefix_str (lsa, buf, sizeof(buf), 0)); - - /* Forwarding-Address */ - if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F)) - { - vty_out (vty, " Forwarding-Address: %s\n", - ospf6_as_external_lsa_get_prefix_str (lsa, buf, sizeof(buf), 1)); - } - - /* Tag */ - if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T)) - { - vty_out (vty, " Tag: %"ROUTE_TAG_PRI"\n", - ospf6_as_external_lsa_get_tag (lsa)); - } - - return 0; + struct ospf6_as_external_lsa *external; + char buf[64]; + + assert(lsa->header); + external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END( + lsa->header); + + /* bits */ + snprintf(buf, sizeof(buf), "%c%c%c", + (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_E) ? 'E' + : '-'), + (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_F) ? 'F' + : '-'), + (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_T) ? 'T' + : '-')); + + vty_out(vty, " Bits: %s\n", buf); + vty_out(vty, " Metric: %5lu\n", + (u_long)OSPF6_ASBR_METRIC(external)); + + ospf6_prefix_options_printbuf(external->prefix.prefix_options, buf, + sizeof(buf)); + vty_out(vty, " Prefix Options: %s\n", buf); + + vty_out(vty, " Referenced LSType: %d\n", + ntohs(external->prefix.prefix_refer_lstype)); + + vty_out(vty, " Prefix: %s\n", + ospf6_as_external_lsa_get_prefix_str(lsa, buf, sizeof(buf), 0)); + + /* Forwarding-Address */ + if (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_F)) { + vty_out(vty, " Forwarding-Address: %s\n", + ospf6_as_external_lsa_get_prefix_str(lsa, buf, + sizeof(buf), 1)); + } + + /* Tag */ + if (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_T)) { + vty_out(vty, " Tag: %" ROUTE_TAG_PRI "\n", + ospf6_as_external_lsa_get_tag(lsa)); + } + + return 0; } -static void -ospf6_asbr_external_route_show (struct vty *vty, struct ospf6_route *route) +static void ospf6_asbr_external_route_show(struct vty *vty, + struct ospf6_route *route) { - struct ospf6_external_info *info = route->route_option; - char prefix[PREFIX2STR_BUFFER], id[16], forwarding[64]; - u_int32_t tmp_id; - - prefix2str (&route->prefix, prefix, sizeof (prefix)); - tmp_id = ntohl (info->id); - inet_ntop (AF_INET, &tmp_id, id, sizeof (id)); - if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding)) - inet_ntop (AF_INET6, &info->forwarding, forwarding, sizeof (forwarding)); - else - snprintf (forwarding, sizeof (forwarding), ":: (ifindex %d)", - ospf6_route_get_first_nh_index (route)); - - vty_out (vty, "%c %-32s %-15s type-%d %5lu %s\n", - zebra_route_char(info->type), - prefix, id, route->path.metric_type, - (u_long) (route->path.metric_type == 2 ? - route->path.u.cost_e2 : route->path.cost), - forwarding); + struct ospf6_external_info *info = route->route_option; + char prefix[PREFIX2STR_BUFFER], id[16], forwarding[64]; + u_int32_t tmp_id; + + prefix2str(&route->prefix, prefix, sizeof(prefix)); + tmp_id = ntohl(info->id); + inet_ntop(AF_INET, &tmp_id, id, sizeof(id)); + if (!IN6_IS_ADDR_UNSPECIFIED(&info->forwarding)) + inet_ntop(AF_INET6, &info->forwarding, forwarding, + sizeof(forwarding)); + else + snprintf(forwarding, sizeof(forwarding), ":: (ifindex %d)", + ospf6_route_get_first_nh_index(route)); + + vty_out(vty, "%c %-32s %-15s type-%d %5lu %s\n", + zebra_route_char(info->type), prefix, id, + route->path.metric_type, + (u_long)(route->path.metric_type == 2 ? route->path.u.cost_e2 + : route->path.cost), + forwarding); } DEFUN (show_ipv6_ospf6_redistribute, @@ -1306,60 +1220,51 @@ DEFUN (show_ipv6_ospf6_redistribute, "redistributing External information\n" ) { - struct ospf6_route *route; + struct ospf6_route *route; - OSPF6_CMD_CHECK_RUNNING (); + OSPF6_CMD_CHECK_RUNNING(); - ospf6_redistribute_show_config (vty); + ospf6_redistribute_show_config(vty); - for (route = ospf6_route_head (ospf6->external_table); route; - route = ospf6_route_next (route)) - ospf6_asbr_external_route_show (vty, route); + for (route = ospf6_route_head(ospf6->external_table); route; + route = ospf6_route_next(route)) + ospf6_asbr_external_route_show(vty, route); - return CMD_SUCCESS; + return CMD_SUCCESS; } -struct ospf6_lsa_handler as_external_handler = -{ - OSPF6_LSTYPE_AS_EXTERNAL, - "AS-External", - "ASE", - ospf6_as_external_lsa_show, - ospf6_as_external_lsa_get_prefix_str -}; +struct ospf6_lsa_handler as_external_handler = { + OSPF6_LSTYPE_AS_EXTERNAL, "AS-External", "ASE", + ospf6_as_external_lsa_show, ospf6_as_external_lsa_get_prefix_str}; -void -ospf6_asbr_init (void) +void ospf6_asbr_init(void) { - ospf6_routemap_init (); + ospf6_routemap_init(); - ospf6_install_lsa_handler (&as_external_handler); + ospf6_install_lsa_handler(&as_external_handler); - install_element (VIEW_NODE, &show_ipv6_ospf6_redistribute_cmd); + install_element(VIEW_NODE, &show_ipv6_ospf6_redistribute_cmd); - install_element (OSPF6_NODE, &ospf6_redistribute_cmd); - install_element (OSPF6_NODE, &ospf6_redistribute_routemap_cmd); - install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd); + install_element(OSPF6_NODE, &ospf6_redistribute_cmd); + install_element(OSPF6_NODE, &ospf6_redistribute_routemap_cmd); + install_element(OSPF6_NODE, &no_ospf6_redistribute_cmd); } -void -ospf6_asbr_redistribute_reset (void) +void ospf6_asbr_redistribute_reset(void) { - int type; - - for (type = 0; type < ZEBRA_ROUTE_MAX; type++) - { - if (type == ZEBRA_ROUTE_OSPF6) - continue; - if (ospf6_zebra_is_redistribute (type)) - ospf6_asbr_redistribute_unset(type); - } + int type; + + for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { + if (type == ZEBRA_ROUTE_OSPF6) + continue; + if (ospf6_zebra_is_redistribute(type)) + ospf6_asbr_redistribute_unset(type); + } } -void -ospf6_asbr_terminate (void) +void ospf6_asbr_terminate(void) { - route_map_finish (); + route_map_finish(); } DEFUN (debug_ospf6_asbr, @@ -1370,8 +1275,8 @@ DEFUN (debug_ospf6_asbr, "Debug OSPFv3 ASBR function\n" ) { - OSPF6_DEBUG_ASBR_ON (); - return CMD_SUCCESS; + OSPF6_DEBUG_ASBR_ON(); + return CMD_SUCCESS; } DEFUN (no_debug_ospf6_asbr, @@ -1383,23 +1288,21 @@ DEFUN (no_debug_ospf6_asbr, "Debug OSPFv3 ASBR function\n" ) { - OSPF6_DEBUG_ASBR_OFF (); - return CMD_SUCCESS; + OSPF6_DEBUG_ASBR_OFF(); + return CMD_SUCCESS; } -int -config_write_ospf6_debug_asbr (struct vty *vty) +int config_write_ospf6_debug_asbr(struct vty *vty) { - if (IS_OSPF6_DEBUG_ASBR) - vty_out (vty, "debug ospf6 asbr\n"); - return 0; + if (IS_OSPF6_DEBUG_ASBR) + vty_out(vty, "debug ospf6 asbr\n"); + return 0; } -void -install_element_ospf6_debug_asbr () +void install_element_ospf6_debug_asbr() { - install_element (ENABLE_NODE, &debug_ospf6_asbr_cmd); - install_element (ENABLE_NODE, &no_debug_ospf6_asbr_cmd); - install_element (CONFIG_NODE, &debug_ospf6_asbr_cmd); - install_element (CONFIG_NODE, &no_debug_ospf6_asbr_cmd); + install_element(ENABLE_NODE, &debug_ospf6_asbr_cmd); + install_element(ENABLE_NODE, &no_debug_ospf6_asbr_cmd); + install_element(CONFIG_NODE, &debug_ospf6_asbr_cmd); + install_element(CONFIG_NODE, &no_debug_ospf6_asbr_cmd); } diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h index aaa3c72a4..73053452e 100644 --- a/ospf6d/ospf6_asbr.h +++ b/ospf6d/ospf6_asbr.h @@ -30,38 +30,33 @@ /* Debug option */ extern unsigned char conf_debug_ospf6_asbr; -#define OSPF6_DEBUG_ASBR_ON() \ - (conf_debug_ospf6_asbr = 1) -#define OSPF6_DEBUG_ASBR_OFF() \ - (conf_debug_ospf6_asbr = 0) -#define IS_OSPF6_DEBUG_ASBR \ - (conf_debug_ospf6_asbr) +#define OSPF6_DEBUG_ASBR_ON() (conf_debug_ospf6_asbr = 1) +#define OSPF6_DEBUG_ASBR_OFF() (conf_debug_ospf6_asbr = 0) +#define IS_OSPF6_DEBUG_ASBR (conf_debug_ospf6_asbr) -struct ospf6_external_info -{ - /* External route type */ - int type; +struct ospf6_external_info { + /* External route type */ + int type; - /* Originating Link State ID */ - u_int32_t id; + /* Originating Link State ID */ + u_int32_t id; - struct in6_addr forwarding; + struct in6_addr forwarding; - route_tag_t tag; + route_tag_t tag; - ifindex_t ifindex; + ifindex_t ifindex; }; /* AS-External-LSA */ #define OSPF6_AS_EXTERNAL_LSA_MIN_SIZE 4U /* w/o IPv6 prefix */ -struct ospf6_as_external_lsa -{ - u_int32_t bits_metric; - - struct ospf6_prefix prefix; - /* followed by none or one forwarding address */ - /* followed by none or one external route tag */ - /* followed by none or one referenced LS-ID */ +struct ospf6_as_external_lsa { + u_int32_t bits_metric; + + struct ospf6_prefix prefix; + /* followed by none or one forwarding address */ + /* followed by none or one external route tag */ + /* followed by none or one referenced LS-ID */ }; #define OSPF6_ASBR_BIT_T ntohl (0x01000000) @@ -69,32 +64,34 @@ struct ospf6_as_external_lsa #define OSPF6_ASBR_BIT_E ntohl (0x04000000) #define OSPF6_ASBR_METRIC(E) (ntohl ((E)->bits_metric & htonl (0x00ffffff))) -#define OSPF6_ASBR_METRIC_SET(E,C) \ - { (E)->bits_metric &= htonl (0xff000000); \ - (E)->bits_metric |= htonl (0x00ffffff) & htonl (C); } - -extern void ospf6_asbr_lsa_add (struct ospf6_lsa *lsa); -extern void ospf6_asbr_lsa_remove (struct ospf6_lsa *lsa); -extern void ospf6_asbr_lsentry_add (struct ospf6_route *asbr_entry); -extern void ospf6_asbr_lsentry_remove (struct ospf6_route *asbr_entry); - -extern int ospf6_asbr_is_asbr (struct ospf6 *o); -extern void ospf6_asbr_redistribute_add (int type, ifindex_t ifindex, - struct prefix *prefix, - u_int nexthop_num, - struct in6_addr *nexthop, - route_tag_t tag); -extern void ospf6_asbr_redistribute_remove (int type, ifindex_t ifindex, - struct prefix *prefix); - -extern int ospf6_redistribute_config_write (struct vty *vty); - -extern void ospf6_asbr_init (void); -extern void ospf6_asbr_redistribute_reset (void); -extern void ospf6_asbr_terminate (void); -extern void ospf6_asbr_send_externals_to_area (struct ospf6_area *); - -extern int config_write_ospf6_debug_asbr (struct vty *vty); -extern void install_element_ospf6_debug_asbr (void); +#define OSPF6_ASBR_METRIC_SET(E, C) \ + { \ + (E)->bits_metric &= htonl(0xff000000); \ + (E)->bits_metric |= htonl(0x00ffffff) & htonl(C); \ + } + +extern void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa); +extern void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa); +extern void ospf6_asbr_lsentry_add(struct ospf6_route *asbr_entry); +extern void ospf6_asbr_lsentry_remove(struct ospf6_route *asbr_entry); + +extern int ospf6_asbr_is_asbr(struct ospf6 *o); +extern void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex, + struct prefix *prefix, + u_int nexthop_num, + struct in6_addr *nexthop, + route_tag_t tag); +extern void ospf6_asbr_redistribute_remove(int type, ifindex_t ifindex, + struct prefix *prefix); + +extern int ospf6_redistribute_config_write(struct vty *vty); + +extern void ospf6_asbr_init(void); +extern void ospf6_asbr_redistribute_reset(void); +extern void ospf6_asbr_terminate(void); +extern void ospf6_asbr_send_externals_to_area(struct ospf6_area *); + +extern int config_write_ospf6_debug_asbr(struct vty *vty); +extern void install_element_ospf6_debug_asbr(void); #endif /* OSPF6_ASBR_H */ diff --git a/ospf6d/ospf6_bfd.c b/ospf6d/ospf6_bfd.c index f460bf065..fa0030b6d 100644 --- a/ospf6d/ospf6_bfd.c +++ b/ospf6d/ospf6_bfd.c @@ -47,22 +47,20 @@ extern struct zclient *zclient; /* * ospf6_bfd_info_free - Free BFD info structure */ -void -ospf6_bfd_info_free(void **bfd_info) +void ospf6_bfd_info_free(void **bfd_info) { - bfd_info_free((struct bfd_info **) bfd_info); + bfd_info_free((struct bfd_info **)bfd_info); } /* * ospf6_bfd_show_info - Show BFD info structure */ -void -ospf6_bfd_show_info(struct vty *vty, void *bfd_info, int param_only) +void ospf6_bfd_show_info(struct vty *vty, void *bfd_info, int param_only) { - if (param_only) - bfd_show_param(vty, bfd_info, 1, 0, 0, NULL); - else - bfd_show_info(vty, bfd_info, 0, 1, 0, NULL); + if (param_only) + bfd_show_param(vty, bfd_info, 1, 0, 0, NULL); + else + bfd_show_info(vty, bfd_info, 0, 1, 0, NULL); } /* @@ -70,45 +68,44 @@ ospf6_bfd_show_info(struct vty *vty, void *bfd_info, int param_only) * zebra for starting/stopping the monitoring of * the neighbor rechahability. */ -void -ospf6_bfd_reg_dereg_nbr (struct ospf6_neighbor *on, int command) +void ospf6_bfd_reg_dereg_nbr(struct ospf6_neighbor *on, int command) { - struct ospf6_interface *oi = on->ospf6_if; - struct interface *ifp = oi->interface; - struct bfd_info *bfd_info; - char src[64]; - - if (!oi->bfd_info || !on->bfd_info) - return; - bfd_info = (struct bfd_info *)oi->bfd_info; - - if (IS_OSPF6_DEBUG_ZEBRA(SEND)) - { - inet_ntop (AF_INET6, &on->linklocal_addr, src, sizeof (src)); - zlog_debug ("%s nbr (%s) with BFD", - bfd_get_command_dbg_str(command), src); - } - - bfd_peer_sendmsg (zclient, bfd_info, AF_INET6, &on->linklocal_addr, - on->ospf6_if->linklocal_addr, ifp->name, - 0, 0, command, 0, VRF_DEFAULT); - - if (command == ZEBRA_BFD_DEST_DEREGISTER) - bfd_info_free((struct bfd_info **)&on->bfd_info); + struct ospf6_interface *oi = on->ospf6_if; + struct interface *ifp = oi->interface; + struct bfd_info *bfd_info; + char src[64]; + + if (!oi->bfd_info || !on->bfd_info) + return; + bfd_info = (struct bfd_info *)oi->bfd_info; + + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) { + inet_ntop(AF_INET6, &on->linklocal_addr, src, sizeof(src)); + zlog_debug("%s nbr (%s) with BFD", + bfd_get_command_dbg_str(command), src); + } + + bfd_peer_sendmsg(zclient, bfd_info, AF_INET6, &on->linklocal_addr, + on->ospf6_if->linklocal_addr, ifp->name, 0, 0, command, + 0, VRF_DEFAULT); + + if (command == ZEBRA_BFD_DEST_DEREGISTER) + bfd_info_free((struct bfd_info **)&on->bfd_info); } /* * ospf6_bfd_trigger_event - Neighbor is registered/deregistered with BFD when * neighbor state is changed to/from 2way. */ -void -ospf6_bfd_trigger_event(struct ospf6_neighbor *on, int old_state, int state) +void ospf6_bfd_trigger_event(struct ospf6_neighbor *on, int old_state, + int state) { - if ((old_state < OSPF6_NEIGHBOR_TWOWAY) && (state >= OSPF6_NEIGHBOR_TWOWAY)) - ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_REGISTER); - else if ((old_state >= OSPF6_NEIGHBOR_TWOWAY) && - (state < OSPF6_NEIGHBOR_TWOWAY)) - ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_DEREGISTER); + if ((old_state < OSPF6_NEIGHBOR_TWOWAY) + && (state >= OSPF6_NEIGHBOR_TWOWAY)) + ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_REGISTER); + else if ((old_state >= OSPF6_NEIGHBOR_TWOWAY) + && (state < OSPF6_NEIGHBOR_TWOWAY)) + ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_DEREGISTER); } /* @@ -117,71 +114,66 @@ ospf6_bfd_trigger_event(struct ospf6_neighbor *on, int old_state, int state) * zebra for starting/stopping the monitoring of * the neighbor rechahability. */ -static void -ospf6_bfd_reg_dereg_all_nbr (struct ospf6_interface *oi, int command) +static void ospf6_bfd_reg_dereg_all_nbr(struct ospf6_interface *oi, int command) { - struct ospf6_neighbor *on; - struct listnode *node; - - for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, node, on)) - { - if (command == ZEBRA_BFD_DEST_REGISTER) - ospf6_bfd_info_nbr_create(oi, on); - - if (on->state < OSPF6_NEIGHBOR_TWOWAY) - { - if (command == ZEBRA_BFD_DEST_DEREGISTER) - bfd_info_free((struct bfd_info **)&on->bfd_info); - continue; - } - - ospf6_bfd_reg_dereg_nbr(on, command); - } + struct ospf6_neighbor *on; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, node, on)) { + if (command == ZEBRA_BFD_DEST_REGISTER) + ospf6_bfd_info_nbr_create(oi, on); + + if (on->state < OSPF6_NEIGHBOR_TWOWAY) { + if (command == ZEBRA_BFD_DEST_DEREGISTER) + bfd_info_free( + (struct bfd_info **)&on->bfd_info); + continue; + } + + ospf6_bfd_reg_dereg_nbr(on, command); + } } /* * ospf6_bfd_nbr_replay - Replay all the neighbors that have BFD enabled * to zebra */ -static int -ospf6_bfd_nbr_replay (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int ospf6_bfd_nbr_replay(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct listnode *inode, *nnode; - struct interface *ifp; - struct ospf6_interface *oi; - struct ospf6_neighbor *on; - char dst[64]; - - if (IS_OSPF6_DEBUG_ZEBRA(RECV)) - zlog_debug("Zebra: BFD Dest replay request"); - - /* Send the client registration */ - bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); - - /* Replay the neighbor, if BFD is enabled on the interface*/ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), inode, ifp)) - { - oi = (struct ospf6_interface *) ifp->info; - - if (!oi || !oi->bfd_info) - continue; - - for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, nnode, on)) - { - if (on->state < OSPF6_NEIGHBOR_TWOWAY) - continue; - - if (IS_OSPF6_DEBUG_ZEBRA(SEND)) - { - inet_ntop (AF_INET6, &on->linklocal_addr, dst, sizeof (dst)); - zlog_debug ("Replaying nbr (%s) to BFD", dst); - } - - ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_UPDATE); - } - } - return 0; + struct listnode *inode, *nnode; + struct interface *ifp; + struct ospf6_interface *oi; + struct ospf6_neighbor *on; + char dst[64]; + + if (IS_OSPF6_DEBUG_ZEBRA(RECV)) + zlog_debug("Zebra: BFD Dest replay request"); + + /* Send the client registration */ + bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); + + /* Replay the neighbor, if BFD is enabled on the interface*/ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), inode, ifp)) { + oi = (struct ospf6_interface *)ifp->info; + + if (!oi || !oi->bfd_info) + continue; + + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, nnode, on)) { + if (on->state < OSPF6_NEIGHBOR_TWOWAY) + continue; + + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) { + inet_ntop(AF_INET6, &on->linklocal_addr, dst, + sizeof(dst)); + zlog_debug("Replaying nbr (%s) to BFD", dst); + } + + ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_UPDATE); + } + } + return 0; } /* @@ -189,134 +181,129 @@ ospf6_bfd_nbr_replay (int command, struct zclient *zclient, zebra_size_t length, * has changed and bring down the neighbor * connectivity if BFD down is received. */ -static int -ospf6_bfd_interface_dest_update (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int ospf6_bfd_interface_dest_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - struct ospf6_interface *oi; - struct ospf6_neighbor *on; - struct prefix dp; - struct prefix sp; - struct listnode *node, *nnode; - char dst[64]; - int status; - int old_status; - struct bfd_info *bfd_info; - struct timeval tv; - - ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status, vrf_id); - - if ((ifp == NULL) || (dp.family != AF_INET6)) - return 0; - - if (IS_OSPF6_DEBUG_ZEBRA (RECV)) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str(&dp, buf, sizeof(buf)); - zlog_debug("Zebra: interface %s bfd destination %s %s", ifp->name, buf, - bfd_get_status_str(status)); - } - - - oi = (struct ospf6_interface *) ifp->info; - if (!oi || !oi->bfd_info) - return 0; - - for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) - { - if (memcmp(&(on->linklocal_addr), &dp.u.prefix6, sizeof(struct in6_addr))) - continue; - - if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) - { - inet_ntop (AF_INET6, &on->linklocal_addr, dst, sizeof (dst)); - zlog_debug ("[%s:%s]: BFD %s", ifp->name, dst, - bfd_get_status_str(status)); - } - - if (!on->bfd_info) - continue; - - bfd_info = (struct bfd_info *)on->bfd_info; - if (bfd_info->status == status) - continue; - - old_status = bfd_info->status; - bfd_info->status = status; - monotime(&tv); - bfd_info->last_update = tv.tv_sec; - - if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP)) - { - THREAD_OFF (on->inactivity_timer); - thread_add_event(master, inactivity_timer, on, 0, NULL); - } - } - - return 0; + struct interface *ifp; + struct ospf6_interface *oi; + struct ospf6_neighbor *on; + struct prefix dp; + struct prefix sp; + struct listnode *node, *nnode; + char dst[64]; + int status; + int old_status; + struct bfd_info *bfd_info; + struct timeval tv; + + ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status, vrf_id); + + if ((ifp == NULL) || (dp.family != AF_INET6)) + return 0; + + if (IS_OSPF6_DEBUG_ZEBRA(RECV)) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&dp, buf, sizeof(buf)); + zlog_debug("Zebra: interface %s bfd destination %s %s", + ifp->name, buf, bfd_get_status_str(status)); + } + + + oi = (struct ospf6_interface *)ifp->info; + if (!oi || !oi->bfd_info) + return 0; + + for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) { + if (memcmp(&(on->linklocal_addr), &dp.u.prefix6, + sizeof(struct in6_addr))) + continue; + + if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) { + inet_ntop(AF_INET6, &on->linklocal_addr, dst, + sizeof(dst)); + zlog_debug("[%s:%s]: BFD %s", ifp->name, dst, + bfd_get_status_str(status)); + } + + if (!on->bfd_info) + continue; + + bfd_info = (struct bfd_info *)on->bfd_info; + if (bfd_info->status == status) + continue; + + old_status = bfd_info->status; + bfd_info->status = status; + monotime(&tv); + bfd_info->last_update = tv.tv_sec; + + if ((status == BFD_STATUS_DOWN) + && (old_status == BFD_STATUS_UP)) { + THREAD_OFF(on->inactivity_timer); + thread_add_event(master, inactivity_timer, on, 0, NULL); + } + } + + return 0; } /* * ospf6_bfd_info_nbr_create - Create/update BFD information for a neighbor. */ -void -ospf6_bfd_info_nbr_create (struct ospf6_interface *oi, - struct ospf6_neighbor *on) +void ospf6_bfd_info_nbr_create(struct ospf6_interface *oi, + struct ospf6_neighbor *on) { - struct bfd_info *oi_bfd_info; - struct bfd_info *on_bfd_info; + struct bfd_info *oi_bfd_info; + struct bfd_info *on_bfd_info; - if (!oi->bfd_info) - return; + if (!oi->bfd_info) + return; - oi_bfd_info = (struct bfd_info *)oi->bfd_info; + oi_bfd_info = (struct bfd_info *)oi->bfd_info; - if (!on->bfd_info) - on->bfd_info = bfd_info_create(); + if (!on->bfd_info) + on->bfd_info = bfd_info_create(); - on_bfd_info = (struct bfd_info *)on->bfd_info; - on_bfd_info->detect_mult = oi_bfd_info->detect_mult; - on_bfd_info->desired_min_tx = oi_bfd_info->desired_min_tx; - on_bfd_info->required_min_rx = oi_bfd_info->required_min_rx; + on_bfd_info = (struct bfd_info *)on->bfd_info; + on_bfd_info->detect_mult = oi_bfd_info->detect_mult; + on_bfd_info->desired_min_tx = oi_bfd_info->desired_min_tx; + on_bfd_info->required_min_rx = oi_bfd_info->required_min_rx; } /* * ospf6_bfd_write_config - Write the interface BFD configuration. */ -void -ospf6_bfd_write_config(struct vty *vty, struct ospf6_interface *oi) +void ospf6_bfd_write_config(struct vty *vty, struct ospf6_interface *oi) { - struct bfd_info *bfd_info; + struct bfd_info *bfd_info; - if (!oi->bfd_info) - return; + if (!oi->bfd_info) + return; - bfd_info = (struct bfd_info *)oi->bfd_info; + bfd_info = (struct bfd_info *)oi->bfd_info; - if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) - vty_out (vty, " ipv6 ospf6 bfd %d %d %d\n", - bfd_info->detect_mult, bfd_info->required_min_rx, - bfd_info->desired_min_tx); - else - vty_out (vty, " ipv6 ospf6 bfd\n"); + if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) + vty_out(vty, " ipv6 ospf6 bfd %d %d %d\n", + bfd_info->detect_mult, bfd_info->required_min_rx, + bfd_info->desired_min_tx); + else + vty_out(vty, " ipv6 ospf6 bfd\n"); } /* * ospf6_bfd_if_param_set - Set the configured BFD paramter values for * interface. */ -static void -ospf6_bfd_if_param_set (struct ospf6_interface *oi, u_int32_t min_rx, - u_int32_t min_tx, u_int8_t detect_mult, - int defaults) +static void ospf6_bfd_if_param_set(struct ospf6_interface *oi, u_int32_t min_rx, + u_int32_t min_tx, u_int8_t detect_mult, + int defaults) { - int command = 0; + int command = 0; - bfd_set_param((struct bfd_info **)&(oi->bfd_info), min_rx, min_tx, detect_mult, - defaults, &command); - if (command) - ospf6_bfd_reg_dereg_all_nbr(oi, command); + bfd_set_param((struct bfd_info **)&(oi->bfd_info), min_rx, min_tx, + detect_mult, defaults, &command); + if (command) + ospf6_bfd_reg_dereg_all_nbr(oi, command); } DEFUN (ipv6_ospf6_bfd, @@ -327,18 +314,18 @@ DEFUN (ipv6_ospf6_bfd, "Enables BFD support\n" ) { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct ospf6_interface *oi; - assert (ifp); - - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - oi = ospf6_interface_create (ifp); - assert (oi); - - ospf6_bfd_if_param_set (oi, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, - BFD_DEF_DETECT_MULT, 1); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf6_interface *oi; + assert(ifp); + + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + assert(oi); + + ospf6_bfd_if_param_set(oi, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, + BFD_DEF_DETECT_MULT, 1); + return CMD_SUCCESS; } DEFUN (ipv6_ospf6_bfd_param, @@ -351,30 +338,32 @@ DEFUN (ipv6_ospf6_bfd_param, "Required min receive interval\n" "Desired min transmit interval\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_number = 3; - int idx_number_2 = 4; - int idx_number_3 = 5; - struct ospf6_interface *oi; - u_int32_t rx_val; - u_int32_t tx_val; - u_int8_t dm_val; - int ret; - - assert (ifp); - - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - oi = ospf6_interface_create (ifp); - assert (oi); - - if ((ret = bfd_validate_param (vty, argv[idx_number]->arg, argv[idx_number_2]->arg, argv[idx_number_3]->arg, &dm_val, - &rx_val, &tx_val)) != CMD_SUCCESS) - return ret; - - ospf6_bfd_if_param_set (oi, rx_val, tx_val, dm_val, 0); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_number = 3; + int idx_number_2 = 4; + int idx_number_3 = 5; + struct ospf6_interface *oi; + u_int32_t rx_val; + u_int32_t tx_val; + u_int8_t dm_val; + int ret; + + assert(ifp); + + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + assert(oi); + + if ((ret = bfd_validate_param( + vty, argv[idx_number]->arg, argv[idx_number_2]->arg, + argv[idx_number_3]->arg, &dm_val, &rx_val, &tx_val)) + != CMD_SUCCESS) + return ret; + + ospf6_bfd_if_param_set(oi, rx_val, tx_val, dm_val, 0); + + return CMD_SUCCESS; } DEFUN (no_ipv6_ospf6_bfd, @@ -386,35 +375,33 @@ DEFUN (no_ipv6_ospf6_bfd, "Disables BFD support\n" ) { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct ospf6_interface *oi; - assert (ifp); - - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - oi = ospf6_interface_create (ifp); - assert (oi); - - if (oi->bfd_info) - { - ospf6_bfd_reg_dereg_all_nbr(oi, ZEBRA_BFD_DEST_DEREGISTER); - bfd_info_free((struct bfd_info **)&(oi->bfd_info)); - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf6_interface *oi; + assert(ifp); + + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + assert(oi); + + if (oi->bfd_info) { + ospf6_bfd_reg_dereg_all_nbr(oi, ZEBRA_BFD_DEST_DEREGISTER); + bfd_info_free((struct bfd_info **)&(oi->bfd_info)); + } + + return CMD_SUCCESS; } -void -ospf6_bfd_init(void) +void ospf6_bfd_init(void) { - bfd_gbl_init(); + bfd_gbl_init(); - /* Initialize BFD client functions */ - zclient->interface_bfd_dest_update = ospf6_bfd_interface_dest_update; - zclient->bfd_dest_replay = ospf6_bfd_nbr_replay; + /* Initialize BFD client functions */ + zclient->interface_bfd_dest_update = ospf6_bfd_interface_dest_update; + zclient->bfd_dest_replay = ospf6_bfd_nbr_replay; - /* Install BFD command */ - install_element (INTERFACE_NODE, &ipv6_ospf6_bfd_cmd); - install_element (INTERFACE_NODE, &ipv6_ospf6_bfd_param_cmd); - install_element (INTERFACE_NODE, &no_ipv6_ospf6_bfd_cmd); + /* Install BFD command */ + install_element(INTERFACE_NODE, &ipv6_ospf6_bfd_cmd); + install_element(INTERFACE_NODE, &ipv6_ospf6_bfd_param_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ospf6_bfd_cmd); } diff --git a/ospf6d/ospf6_bfd.h b/ospf6d/ospf6_bfd.h index 913f7dcf4..19dff1ff7 100644 --- a/ospf6d/ospf6_bfd.h +++ b/ospf6d/ospf6_bfd.h @@ -23,25 +23,20 @@ #ifndef OSPF6_BFD_H #define OSPF6_BFD_H -extern void -ospf6_bfd_init(void); +extern void ospf6_bfd_init(void); -extern void -ospf6_bfd_trigger_event(struct ospf6_neighbor *nbr, int old_state, int state); +extern void ospf6_bfd_trigger_event(struct ospf6_neighbor *nbr, int old_state, + int state); -extern void -ospf6_bfd_write_config(struct vty *vty, struct ospf6_interface *oi); +extern void ospf6_bfd_write_config(struct vty *vty, struct ospf6_interface *oi); -extern void -ospf6_bfd_info_nbr_create (struct ospf6_interface *oi, - struct ospf6_neighbor *on); +extern void ospf6_bfd_info_nbr_create(struct ospf6_interface *oi, + struct ospf6_neighbor *on); -extern void -ospf6_bfd_info_free(void **bfd_info); +extern void ospf6_bfd_info_free(void **bfd_info); -extern void -ospf6_bfd_show_info(struct vty *vty, void *bfd_info, int param_only); +extern void ospf6_bfd_show_info(struct vty *vty, void *bfd_info, + int param_only); -extern void -ospf6_bfd_reg_dereg_nbr (struct ospf6_neighbor *on, int command); +extern void ospf6_bfd_reg_dereg_nbr(struct ospf6_neighbor *on, int command); #endif /* OSPF6_BFD_H */ diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c index f816c6f48..42716fbc7 100644 --- a/ospf6d/ospf6_flood.c +++ b/ospf6d/ospf6_flood.c @@ -43,963 +43,933 @@ unsigned char conf_debug_ospf6_flooding; -struct ospf6_lsdb * -ospf6_get_scoped_lsdb (struct ospf6_lsa *lsa) +struct ospf6_lsdb *ospf6_get_scoped_lsdb(struct ospf6_lsa *lsa) { - struct ospf6_lsdb *lsdb = NULL; - switch (OSPF6_LSA_SCOPE (lsa->header->type)) - { - case OSPF6_SCOPE_LINKLOCAL: - lsdb = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb; - break; - case OSPF6_SCOPE_AREA: - lsdb = OSPF6_AREA (lsa->lsdb->data)->lsdb; - break; - case OSPF6_SCOPE_AS: - lsdb = OSPF6_PROCESS (lsa->lsdb->data)->lsdb; - break; - default: - assert (0); - break; - } - return lsdb; + struct ospf6_lsdb *lsdb = NULL; + switch (OSPF6_LSA_SCOPE(lsa->header->type)) { + case OSPF6_SCOPE_LINKLOCAL: + lsdb = OSPF6_INTERFACE(lsa->lsdb->data)->lsdb; + break; + case OSPF6_SCOPE_AREA: + lsdb = OSPF6_AREA(lsa->lsdb->data)->lsdb; + break; + case OSPF6_SCOPE_AS: + lsdb = OSPF6_PROCESS(lsa->lsdb->data)->lsdb; + break; + default: + assert(0); + break; + } + return lsdb; } -struct ospf6_lsdb * -ospf6_get_scoped_lsdb_self (struct ospf6_lsa *lsa) +struct ospf6_lsdb *ospf6_get_scoped_lsdb_self(struct ospf6_lsa *lsa) { - struct ospf6_lsdb *lsdb_self = NULL; - switch (OSPF6_LSA_SCOPE (lsa->header->type)) - { - case OSPF6_SCOPE_LINKLOCAL: - lsdb_self = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb_self; - break; - case OSPF6_SCOPE_AREA: - lsdb_self = OSPF6_AREA (lsa->lsdb->data)->lsdb_self; - break; - case OSPF6_SCOPE_AS: - lsdb_self = OSPF6_PROCESS (lsa->lsdb->data)->lsdb_self; - break; - default: - assert (0); - break; - } - return lsdb_self; + struct ospf6_lsdb *lsdb_self = NULL; + switch (OSPF6_LSA_SCOPE(lsa->header->type)) { + case OSPF6_SCOPE_LINKLOCAL: + lsdb_self = OSPF6_INTERFACE(lsa->lsdb->data)->lsdb_self; + break; + case OSPF6_SCOPE_AREA: + lsdb_self = OSPF6_AREA(lsa->lsdb->data)->lsdb_self; + break; + case OSPF6_SCOPE_AS: + lsdb_self = OSPF6_PROCESS(lsa->lsdb->data)->lsdb_self; + break; + default: + assert(0); + break; + } + return lsdb_self; } -void -ospf6_lsa_originate (struct ospf6_lsa *lsa) +void ospf6_lsa_originate(struct ospf6_lsa *lsa) { - struct ospf6_lsa *old; - struct ospf6_lsdb *lsdb_self; - - /* find previous LSA */ - old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, - lsa->header->adv_router, lsa->lsdb); - - /* if the new LSA does not differ from previous, - suppress this update of the LSA */ - if (old && ! OSPF6_LSA_IS_DIFFER (lsa, old)) - { - if (IS_OSPF6_DEBUG_ORIGINATE_TYPE (lsa->header->type)) - zlog_debug ("Suppress updating LSA: %s", lsa->name); - ospf6_lsa_delete (lsa); - return; - } - - /* store it in the LSDB for self-originated LSAs */ - lsdb_self = ospf6_get_scoped_lsdb_self (lsa); - ospf6_lsdb_add (ospf6_lsa_copy (lsa), lsdb_self); - - lsa->refresh = NULL; - thread_add_timer(master, ospf6_lsa_refresh, lsa, OSPF_LS_REFRESH_TIME, - &lsa->refresh); - - if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type) || - IS_OSPF6_DEBUG_ORIGINATE_TYPE (lsa->header->type)) - { - zlog_debug ("LSA Originate:"); - ospf6_lsa_header_print (lsa); - } - - ospf6_install_lsa (lsa); - ospf6_flood (NULL, lsa); + struct ospf6_lsa *old; + struct ospf6_lsdb *lsdb_self; + + /* find previous LSA */ + old = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id, + lsa->header->adv_router, lsa->lsdb); + + /* if the new LSA does not differ from previous, + suppress this update of the LSA */ + if (old && !OSPF6_LSA_IS_DIFFER(lsa, old)) { + if (IS_OSPF6_DEBUG_ORIGINATE_TYPE(lsa->header->type)) + zlog_debug("Suppress updating LSA: %s", lsa->name); + ospf6_lsa_delete(lsa); + return; + } + + /* store it in the LSDB for self-originated LSAs */ + lsdb_self = ospf6_get_scoped_lsdb_self(lsa); + ospf6_lsdb_add(ospf6_lsa_copy(lsa), lsdb_self); + + lsa->refresh = NULL; + thread_add_timer(master, ospf6_lsa_refresh, lsa, OSPF_LS_REFRESH_TIME, + &lsa->refresh); + + if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type) + || IS_OSPF6_DEBUG_ORIGINATE_TYPE(lsa->header->type)) { + zlog_debug("LSA Originate:"); + ospf6_lsa_header_print(lsa); + } + + ospf6_install_lsa(lsa); + ospf6_flood(NULL, lsa); } -void -ospf6_lsa_originate_process (struct ospf6_lsa *lsa, - struct ospf6 *process) +void ospf6_lsa_originate_process(struct ospf6_lsa *lsa, struct ospf6 *process) { - lsa->lsdb = process->lsdb; - ospf6_lsa_originate (lsa); + lsa->lsdb = process->lsdb; + ospf6_lsa_originate(lsa); } -void -ospf6_lsa_originate_area (struct ospf6_lsa *lsa, - struct ospf6_area *oa) +void ospf6_lsa_originate_area(struct ospf6_lsa *lsa, struct ospf6_area *oa) { - lsa->lsdb = oa->lsdb; - ospf6_lsa_originate (lsa); + lsa->lsdb = oa->lsdb; + ospf6_lsa_originate(lsa); } -void -ospf6_lsa_originate_interface (struct ospf6_lsa *lsa, - struct ospf6_interface *oi) +void ospf6_lsa_originate_interface(struct ospf6_lsa *lsa, + struct ospf6_interface *oi) { - lsa->lsdb = oi->lsdb; - ospf6_lsa_originate (lsa); + lsa->lsdb = oi->lsdb; + ospf6_lsa_originate(lsa); } -void -ospf6_lsa_purge (struct ospf6_lsa *lsa) +void ospf6_lsa_purge(struct ospf6_lsa *lsa) { - struct ospf6_lsa *self; - struct ospf6_lsdb *lsdb_self; - - /* remove it from the LSDB for self-originated LSAs */ - lsdb_self = ospf6_get_scoped_lsdb_self (lsa); - self = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, - lsa->header->adv_router, lsdb_self); - if (self) - { - THREAD_OFF (self->expire); - THREAD_OFF (self->refresh); - ospf6_lsdb_remove (self, lsdb_self); - } - - ospf6_lsa_premature_aging (lsa); + struct ospf6_lsa *self; + struct ospf6_lsdb *lsdb_self; + + /* remove it from the LSDB for self-originated LSAs */ + lsdb_self = ospf6_get_scoped_lsdb_self(lsa); + self = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id, + lsa->header->adv_router, lsdb_self); + if (self) { + THREAD_OFF(self->expire); + THREAD_OFF(self->refresh); + ospf6_lsdb_remove(self, lsdb_self); + } + + ospf6_lsa_premature_aging(lsa); } -void -ospf6_increment_retrans_count (struct ospf6_lsa *lsa) +void ospf6_increment_retrans_count(struct ospf6_lsa *lsa) { - /* The LSA must be the original one (see the description - in ospf6_decrement_retrans_count () below) */ - lsa->retrans_count++; + /* The LSA must be the original one (see the description + in ospf6_decrement_retrans_count () below) */ + lsa->retrans_count++; } -void -ospf6_decrement_retrans_count (struct ospf6_lsa *lsa) +void ospf6_decrement_retrans_count(struct ospf6_lsa *lsa) { - struct ospf6_lsdb *lsdb; - struct ospf6_lsa *orig; - - /* The LSA must be on the retrans-list of a neighbor. It means - the "lsa" is a copied one, and we have to decrement the - retransmission count of the original one (instead of this "lsa"'s). - In order to find the original LSA, first we have to find - appropriate LSDB that have the original LSA. */ - lsdb = ospf6_get_scoped_lsdb (lsa); - - /* Find the original LSA of which the retrans_count should be decremented */ - orig = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, - lsa->header->adv_router, lsdb); - if (orig) - { - orig->retrans_count--; - assert (orig->retrans_count >= 0); - } + struct ospf6_lsdb *lsdb; + struct ospf6_lsa *orig; + + /* The LSA must be on the retrans-list of a neighbor. It means + the "lsa" is a copied one, and we have to decrement the + retransmission count of the original one (instead of this "lsa"'s). + In order to find the original LSA, first we have to find + appropriate LSDB that have the original LSA. */ + lsdb = ospf6_get_scoped_lsdb(lsa); + + /* Find the original LSA of which the retrans_count should be + * decremented */ + orig = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id, + lsa->header->adv_router, lsdb); + if (orig) { + orig->retrans_count--; + assert(orig->retrans_count >= 0); + } } /* RFC2328 section 13.2 Installing LSAs in the database */ -void -ospf6_install_lsa (struct ospf6_lsa *lsa) +void ospf6_install_lsa(struct ospf6_lsa *lsa) { - struct timeval now; - struct ospf6_lsa *old; - - if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type) || - IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type)) - zlog_debug ("Install LSA: %s", lsa->name); - - /* Remove the old instance from all neighbors' Link state - retransmission list (RFC2328 13.2 last paragraph) */ - old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, - lsa->header->adv_router, lsa->lsdb); - if (old) - { - THREAD_OFF (old->expire); - THREAD_OFF (old->refresh); - ospf6_flood_clear (old); - } - - monotime(&now); - if (! OSPF6_LSA_IS_MAXAGE (lsa)) { - lsa->expire = NULL; - thread_add_timer(master, ospf6_lsa_expire, lsa, OSPF_LSA_MAXAGE + lsa->birth.tv_sec - now.tv_sec, - &lsa->expire); - } - else - lsa->expire = NULL; - - if (OSPF6_LSA_IS_SEQWRAP(lsa) && - ! (CHECK_FLAG(lsa->flag,OSPF6_LSA_SEQWRAPPED) && - lsa->header->seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER))) - { - if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type)) - zlog_debug("lsa install wrapping: sequence 0x%x", - ntohl(lsa->header->seqnum)); - SET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED); - /* in lieu of premature_aging, since we do not want to recreate this lsa - * and/or mess with timers etc, we just want to wrap the sequence number - * and reflood the lsa before continuing. - * NOTE: Flood needs to be called right after this function call, by the - * caller - */ - lsa->header->seqnum = htonl (OSPF_MAX_SEQUENCE_NUMBER); - lsa->header->age = htons (OSPF_LSA_MAXAGE); - ospf6_lsa_checksum (lsa->header); - } - - /* actually install */ - lsa->installed = now; - ospf6_lsdb_add (lsa, lsa->lsdb); - - return; + struct timeval now; + struct ospf6_lsa *old; + + if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type) + || IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type)) + zlog_debug("Install LSA: %s", lsa->name); + + /* Remove the old instance from all neighbors' Link state + retransmission list (RFC2328 13.2 last paragraph) */ + old = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id, + lsa->header->adv_router, lsa->lsdb); + if (old) { + THREAD_OFF(old->expire); + THREAD_OFF(old->refresh); + ospf6_flood_clear(old); + } + + monotime(&now); + if (!OSPF6_LSA_IS_MAXAGE(lsa)) { + lsa->expire = NULL; + thread_add_timer(master, ospf6_lsa_expire, lsa, + OSPF_LSA_MAXAGE + lsa->birth.tv_sec + - now.tv_sec, + &lsa->expire); + } else + lsa->expire = NULL; + + if (OSPF6_LSA_IS_SEQWRAP(lsa) + && !(CHECK_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED) + && lsa->header->seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER))) { + if (IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type)) + zlog_debug("lsa install wrapping: sequence 0x%x", + ntohl(lsa->header->seqnum)); + SET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED); + /* in lieu of premature_aging, since we do not want to recreate + * this lsa + * and/or mess with timers etc, we just want to wrap the + * sequence number + * and reflood the lsa before continuing. + * NOTE: Flood needs to be called right after this function + * call, by the + * caller + */ + lsa->header->seqnum = htonl(OSPF_MAX_SEQUENCE_NUMBER); + lsa->header->age = htons(OSPF_LSA_MAXAGE); + ospf6_lsa_checksum(lsa->header); + } + + /* actually install */ + lsa->installed = now; + ospf6_lsdb_add(lsa, lsa->lsdb); + + return; } /* RFC2740 section 3.5.2. Sending Link State Update packets */ /* RFC2328 section 13.3 Next step in the flooding procedure */ -static void -ospf6_flood_interface (struct ospf6_neighbor *from, - struct ospf6_lsa *lsa, struct ospf6_interface *oi) +static void ospf6_flood_interface(struct ospf6_neighbor *from, + struct ospf6_lsa *lsa, + struct ospf6_interface *oi) { - struct listnode *node, *nnode; - struct ospf6_neighbor *on; - struct ospf6_lsa *req; - int retrans_added = 0; - int is_debug = 0; - - if (IS_OSPF6_DEBUG_FLOODING || - IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type)) - { - is_debug++; - zlog_debug ("Flooding on %s: %s", oi->interface->name, lsa->name); - } - - /* (1) For each neighbor */ - for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) - { - if (is_debug) - zlog_debug ("To neighbor %s", on->name); - - /* (a) if neighbor state < Exchange, examin next */ - if (on->state < OSPF6_NEIGHBOR_EXCHANGE) - { - if (is_debug) - zlog_debug ("Neighbor state less than ExChange, next neighbor"); - continue; - } - - /* (b) if neighbor not yet Full, check request-list */ - if (on->state != OSPF6_NEIGHBOR_FULL) - { - if (is_debug) - zlog_debug ("Neighbor not yet Full"); - - req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, - lsa->header->adv_router, on->request_list); - if (req == NULL) - { - if (is_debug) - zlog_debug ("Not on request-list for this neighbor"); - /* fall through */ - } - else - { - /* If new LSA less recent, examin next neighbor */ - if (ospf6_lsa_compare (lsa, req) > 0) - { - if (is_debug) - zlog_debug ("Requesting is older, next neighbor"); - continue; - } - - /* If the same instance, delete from request-list and - examin next neighbor */ - if (ospf6_lsa_compare (lsa, req) == 0) - { - if (is_debug) - zlog_debug ("Requesting the same, remove it, next neighbor"); - if (req == on->last_ls_req) - { - ospf6_lsa_unlock (req); - on->last_ls_req = NULL; - } - ospf6_lsdb_remove (req, on->request_list); - ospf6_check_nbr_loading (on); - continue; - } - - /* If the new LSA is more recent, delete from request-list */ - if (ospf6_lsa_compare (lsa, req) < 0) - { - if (is_debug) - zlog_debug ("Received is newer, remove requesting"); - if (req == on->last_ls_req) - { - ospf6_lsa_unlock (req); - on->last_ls_req = NULL; - } - ospf6_lsdb_remove (req, on->request_list); - ospf6_check_nbr_loading (on); - /* fall through */ - } - } - } - - /* (c) If the new LSA was received from this neighbor, - examin next neighbor */ - if (from == on) - { - if (is_debug) - zlog_debug ("Received is from the neighbor, next neighbor"); - continue; - } - - /* (d) add retrans-list, schedule retransmission */ - if (is_debug) - zlog_debug ("Add retrans-list of this neighbor"); - ospf6_increment_retrans_count (lsa); - ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); - thread_add_timer(master, ospf6_lsupdate_send_neighbor, on, on->ospf6_if->rxmt_interval, - &on->thread_send_lsupdate); - retrans_added++; - } - - /* (2) examin next interface if not added to retrans-list */ - if (retrans_added == 0) - { - if (is_debug) - zlog_debug ("No retransmission scheduled, next interface"); - return; - } - - /* (3) If the new LSA was received on this interface, - and it was from DR or BDR, examin next interface */ - if (from && from->ospf6_if == oi && - (from->router_id == oi->drouter || from->router_id == oi->bdrouter)) - { - if (is_debug) - zlog_debug ("Received is from the I/F's DR or BDR, next interface"); - return; - } - - /* (4) If the new LSA was received on this interface, - and the interface state is BDR, examin next interface */ - if (from && from->ospf6_if == oi) - { - if (oi->state == OSPF6_INTERFACE_BDR) - { - if (is_debug) - zlog_debug ("Received is from the I/F, itself BDR, next interface"); - return; + struct listnode *node, *nnode; + struct ospf6_neighbor *on; + struct ospf6_lsa *req; + int retrans_added = 0; + int is_debug = 0; + + if (IS_OSPF6_DEBUG_FLOODING + || IS_OSPF6_DEBUG_FLOOD_TYPE(lsa->header->type)) { + is_debug++; + zlog_debug("Flooding on %s: %s", oi->interface->name, + lsa->name); + } + + /* (1) For each neighbor */ + for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) { + if (is_debug) + zlog_debug("To neighbor %s", on->name); + + /* (a) if neighbor state < Exchange, examin next */ + if (on->state < OSPF6_NEIGHBOR_EXCHANGE) { + if (is_debug) + zlog_debug( + "Neighbor state less than ExChange, next neighbor"); + continue; + } + + /* (b) if neighbor not yet Full, check request-list */ + if (on->state != OSPF6_NEIGHBOR_FULL) { + if (is_debug) + zlog_debug("Neighbor not yet Full"); + + req = ospf6_lsdb_lookup( + lsa->header->type, lsa->header->id, + lsa->header->adv_router, on->request_list); + if (req == NULL) { + if (is_debug) + zlog_debug( + "Not on request-list for this neighbor"); + /* fall through */ + } else { + /* If new LSA less recent, examin next neighbor + */ + if (ospf6_lsa_compare(lsa, req) > 0) { + if (is_debug) + zlog_debug( + "Requesting is older, next neighbor"); + continue; + } + + /* If the same instance, delete from + request-list and + examin next neighbor */ + if (ospf6_lsa_compare(lsa, req) == 0) { + if (is_debug) + zlog_debug( + "Requesting the same, remove it, next neighbor"); + if (req == on->last_ls_req) { + ospf6_lsa_unlock(req); + on->last_ls_req = NULL; + } + ospf6_lsdb_remove(req, + on->request_list); + ospf6_check_nbr_loading(on); + continue; + } + + /* If the new LSA is more recent, delete from + * request-list */ + if (ospf6_lsa_compare(lsa, req) < 0) { + if (is_debug) + zlog_debug( + "Received is newer, remove requesting"); + if (req == on->last_ls_req) { + ospf6_lsa_unlock(req); + on->last_ls_req = NULL; + } + ospf6_lsdb_remove(req, + on->request_list); + ospf6_check_nbr_loading(on); + /* fall through */ + } + } + } + + /* (c) If the new LSA was received from this neighbor, + examin next neighbor */ + if (from == on) { + if (is_debug) + zlog_debug( + "Received is from the neighbor, next neighbor"); + continue; + } + + /* (d) add retrans-list, schedule retransmission */ + if (is_debug) + zlog_debug("Add retrans-list of this neighbor"); + ospf6_increment_retrans_count(lsa); + ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list); + thread_add_timer(master, ospf6_lsupdate_send_neighbor, on, + on->ospf6_if->rxmt_interval, + &on->thread_send_lsupdate); + retrans_added++; + } + + /* (2) examin next interface if not added to retrans-list */ + if (retrans_added == 0) { + if (is_debug) + zlog_debug( + "No retransmission scheduled, next interface"); + return; + } + + /* (3) If the new LSA was received on this interface, + and it was from DR or BDR, examin next interface */ + if (from && from->ospf6_if == oi + && (from->router_id == oi->drouter + || from->router_id == oi->bdrouter)) { + if (is_debug) + zlog_debug( + "Received is from the I/F's DR or BDR, next interface"); + return; + } + + /* (4) If the new LSA was received on this interface, + and the interface state is BDR, examin next interface */ + if (from && from->ospf6_if == oi) { + if (oi->state == OSPF6_INTERFACE_BDR) { + if (is_debug) + zlog_debug( + "Received is from the I/F, itself BDR, next interface"); + return; + } + SET_FLAG(lsa->flag, OSPF6_LSA_FLOODBACK); + } + + /* (5) flood the LSA out the interface. */ + if (is_debug) + zlog_debug("Schedule flooding for the interface"); + if ((oi->type == OSPF_IFTYPE_BROADCAST) + || (oi->type == OSPF_IFTYPE_POINTOPOINT)) { + ospf6_lsdb_add(ospf6_lsa_copy(lsa), oi->lsupdate_list); + thread_add_event(master, ospf6_lsupdate_send_interface, oi, 0, + &oi->thread_send_lsupdate); + } else { + /* reschedule retransmissions to all neighbors */ + for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) { + THREAD_OFF(on->thread_send_lsupdate); + on->thread_send_lsupdate = NULL; + thread_add_event(master, ospf6_lsupdate_send_neighbor, + on, 0, &on->thread_send_lsupdate); + } } - SET_FLAG(lsa->flag, OSPF6_LSA_FLOODBACK); - } - - /* (5) flood the LSA out the interface. */ - if (is_debug) - zlog_debug ("Schedule flooding for the interface"); - if ((oi->type == OSPF_IFTYPE_BROADCAST) || - (oi->type == OSPF_IFTYPE_POINTOPOINT)) - { - ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list); - thread_add_event(master, ospf6_lsupdate_send_interface, oi, 0, - &oi->thread_send_lsupdate); - } - else - { - /* reschedule retransmissions to all neighbors */ - for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) - { - THREAD_OFF (on->thread_send_lsupdate); - on->thread_send_lsupdate = NULL; - thread_add_event(master, ospf6_lsupdate_send_neighbor, on, 0, - &on->thread_send_lsupdate); - } - } } -void -ospf6_flood_area (struct ospf6_neighbor *from, - struct ospf6_lsa *lsa, struct ospf6_area *oa) +void ospf6_flood_area(struct ospf6_neighbor *from, struct ospf6_lsa *lsa, + struct ospf6_area *oa) { - struct listnode *node, *nnode; - struct ospf6_interface *oi; + struct listnode *node, *nnode; + struct ospf6_interface *oi; - for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi)) - { - if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL && - oi != OSPF6_INTERFACE (lsa->lsdb->data)) - continue; + for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) { + if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_LINKLOCAL + && oi != OSPF6_INTERFACE(lsa->lsdb->data)) + continue; #if 0 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS && ospf6_is_interface_virtual_link (oi)) continue; -#endif/*0*/ +#endif /*0*/ - ospf6_flood_interface (from, lsa, oi); - } + ospf6_flood_interface(from, lsa, oi); + } } -static void -ospf6_flood_process (struct ospf6_neighbor *from, - struct ospf6_lsa *lsa, struct ospf6 *process) +static void ospf6_flood_process(struct ospf6_neighbor *from, + struct ospf6_lsa *lsa, struct ospf6 *process) { - struct listnode *node, *nnode; - struct ospf6_area *oa; - - for (ALL_LIST_ELEMENTS (process->area_list, node, nnode, oa)) - { - if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA && - oa != OSPF6_AREA (lsa->lsdb->data)) - continue; - if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL && - oa != OSPF6_INTERFACE (lsa->lsdb->data)->area) - continue; - - if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL && - IS_AREA_STUB (oa)) - continue; - - ospf6_flood_area (from, lsa, oa); - } + struct listnode *node, *nnode; + struct ospf6_area *oa; + + for (ALL_LIST_ELEMENTS(process->area_list, node, nnode, oa)) { + if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_AREA + && oa != OSPF6_AREA(lsa->lsdb->data)) + continue; + if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_LINKLOCAL + && oa != OSPF6_INTERFACE(lsa->lsdb->data)->area) + continue; + + if (ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL + && IS_AREA_STUB(oa)) + continue; + + ospf6_flood_area(from, lsa, oa); + } } -void -ospf6_flood (struct ospf6_neighbor *from, struct ospf6_lsa *lsa) +void ospf6_flood(struct ospf6_neighbor *from, struct ospf6_lsa *lsa) { - ospf6_flood_process (from, lsa, ospf6); + ospf6_flood_process(from, lsa, ospf6); } -static void -ospf6_flood_clear_interface (struct ospf6_lsa *lsa, struct ospf6_interface *oi) +static void ospf6_flood_clear_interface(struct ospf6_lsa *lsa, + struct ospf6_interface *oi) { - struct listnode *node, *nnode; - struct ospf6_neighbor *on; - struct ospf6_lsa *rem; - - for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) - { - rem = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, - lsa->header->adv_router, on->retrans_list); - if (rem && ! ospf6_lsa_compare (rem, lsa)) - { - if (IS_OSPF6_DEBUG_FLOODING || - IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type)) - zlog_debug ("Remove %s from retrans_list of %s", - rem->name, on->name); - ospf6_decrement_retrans_count (rem); - ospf6_lsdb_remove (rem, on->retrans_list); - } - } + struct listnode *node, *nnode; + struct ospf6_neighbor *on; + struct ospf6_lsa *rem; + + for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) { + rem = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id, + lsa->header->adv_router, + on->retrans_list); + if (rem && !ospf6_lsa_compare(rem, lsa)) { + if (IS_OSPF6_DEBUG_FLOODING + || IS_OSPF6_DEBUG_FLOOD_TYPE(lsa->header->type)) + zlog_debug("Remove %s from retrans_list of %s", + rem->name, on->name); + ospf6_decrement_retrans_count(rem); + ospf6_lsdb_remove(rem, on->retrans_list); + } + } } -static void -ospf6_flood_clear_area (struct ospf6_lsa *lsa, struct ospf6_area *oa) +static void ospf6_flood_clear_area(struct ospf6_lsa *lsa, struct ospf6_area *oa) { - struct listnode *node, *nnode; - struct ospf6_interface *oi; + struct listnode *node, *nnode; + struct ospf6_interface *oi; - for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi)) - { - if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL && - oi != OSPF6_INTERFACE (lsa->lsdb->data)) - continue; + for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) { + if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_LINKLOCAL + && oi != OSPF6_INTERFACE(lsa->lsdb->data)) + continue; #if 0 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS && ospf6_is_interface_virtual_link (oi)) continue; -#endif/*0*/ +#endif /*0*/ - ospf6_flood_clear_interface (lsa, oi); - } + ospf6_flood_clear_interface(lsa, oi); + } } -static void -ospf6_flood_clear_process (struct ospf6_lsa *lsa, struct ospf6 *process) +static void ospf6_flood_clear_process(struct ospf6_lsa *lsa, + struct ospf6 *process) { - struct listnode *node, *nnode; - struct ospf6_area *oa; - - for (ALL_LIST_ELEMENTS (process->area_list, node, nnode, oa)) - { - if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA && - oa != OSPF6_AREA (lsa->lsdb->data)) - continue; - if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL && - oa != OSPF6_INTERFACE (lsa->lsdb->data)->area) - continue; - - if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL && - IS_AREA_STUB (oa)) - continue; - - ospf6_flood_clear_area (lsa, oa); - } + struct listnode *node, *nnode; + struct ospf6_area *oa; + + for (ALL_LIST_ELEMENTS(process->area_list, node, nnode, oa)) { + if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_AREA + && oa != OSPF6_AREA(lsa->lsdb->data)) + continue; + if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_LINKLOCAL + && oa != OSPF6_INTERFACE(lsa->lsdb->data)->area) + continue; + + if (ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL + && IS_AREA_STUB(oa)) + continue; + + ospf6_flood_clear_area(lsa, oa); + } } -void -ospf6_flood_clear (struct ospf6_lsa *lsa) +void ospf6_flood_clear(struct ospf6_lsa *lsa) { - ospf6_flood_clear_process (lsa, ospf6); + ospf6_flood_clear_process(lsa, ospf6); } /* RFC2328 13.5 (Table 19): Sending link state acknowledgements. */ -static void -ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent, - struct ospf6_neighbor *from) +static void ospf6_acknowledge_lsa_bdrouter(struct ospf6_lsa *lsa, + int ismore_recent, + struct ospf6_neighbor *from) { - struct ospf6_interface *oi; - int is_debug = 0; - - if (IS_OSPF6_DEBUG_FLOODING || - IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type)) - is_debug++; - - assert (from && from->ospf6_if); - oi = from->ospf6_if; - - /* LSA is more recent than database copy, but was not flooded - back out receiving interface. Delayed acknowledgement sent - if advertisement received from Designated Router, - otherwide do nothing. */ - if (ismore_recent < 0) - { - if (oi->drouter == from->router_id) - { - if (is_debug) - zlog_debug ("Delayed acknowledgement (BDR & MoreRecent & from DR)"); - /* Delayed acknowledgement */ - ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list); - thread_add_timer(master, ospf6_lsack_send_interface, oi, 3, - &oi->thread_send_lsack); - } - else - { - if (is_debug) - zlog_debug ("No acknowledgement (BDR & MoreRecent & ! from DR)"); - } - return; - } - - /* LSA is a duplicate, and was treated as an implied acknowledgement. - Delayed acknowledgement sent if advertisement received from - Designated Router, otherwise do nothing */ - if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) && - CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) - { - if (oi->drouter == from->router_id) - { - if (is_debug) - zlog_debug ("Delayed acknowledgement (BDR & Duplicate & ImpliedAck & from DR)"); - /* Delayed acknowledgement */ - ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list); - thread_add_timer(master, ospf6_lsack_send_interface, oi, 3, - &oi->thread_send_lsack); - } - else - { - if (is_debug) - zlog_debug ("No acknowledgement (BDR & Duplicate & ImpliedAck & ! from DR)"); - } - return; - } - - /* LSA is a duplicate, and was not treated as an implied acknowledgement. - Direct acknowledgement sent */ - if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) && - ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) - { - if (is_debug) - zlog_debug ("Direct acknowledgement (BDR & Duplicate)"); - ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list); - thread_add_event(master, ospf6_lsack_send_neighbor, from, 0, - &from->thread_send_lsack); - return; - } - - /* LSA's LS age is equal to Maxage, and there is no current instance - of the LSA in the link state database, and none of router's - neighbors are in states Exchange or Loading */ - /* Direct acknowledgement sent, but this case is handled in - early of ospf6_receive_lsa () */ + struct ospf6_interface *oi; + int is_debug = 0; + + if (IS_OSPF6_DEBUG_FLOODING + || IS_OSPF6_DEBUG_FLOOD_TYPE(lsa->header->type)) + is_debug++; + + assert(from && from->ospf6_if); + oi = from->ospf6_if; + + /* LSA is more recent than database copy, but was not flooded + back out receiving interface. Delayed acknowledgement sent + if advertisement received from Designated Router, + otherwide do nothing. */ + if (ismore_recent < 0) { + if (oi->drouter == from->router_id) { + if (is_debug) + zlog_debug( + "Delayed acknowledgement (BDR & MoreRecent & from DR)"); + /* Delayed acknowledgement */ + ospf6_lsdb_add(ospf6_lsa_copy(lsa), oi->lsack_list); + thread_add_timer(master, ospf6_lsack_send_interface, oi, + 3, &oi->thread_send_lsack); + } else { + if (is_debug) + zlog_debug( + "No acknowledgement (BDR & MoreRecent & ! from DR)"); + } + return; + } + + /* LSA is a duplicate, and was treated as an implied acknowledgement. + Delayed acknowledgement sent if advertisement received from + Designated Router, otherwise do nothing */ + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE) + && CHECK_FLAG(lsa->flag, OSPF6_LSA_IMPLIEDACK)) { + if (oi->drouter == from->router_id) { + if (is_debug) + zlog_debug( + "Delayed acknowledgement (BDR & Duplicate & ImpliedAck & from DR)"); + /* Delayed acknowledgement */ + ospf6_lsdb_add(ospf6_lsa_copy(lsa), oi->lsack_list); + thread_add_timer(master, ospf6_lsack_send_interface, oi, + 3, &oi->thread_send_lsack); + } else { + if (is_debug) + zlog_debug( + "No acknowledgement (BDR & Duplicate & ImpliedAck & ! from DR)"); + } + return; + } + + /* LSA is a duplicate, and was not treated as an implied + acknowledgement. + Direct acknowledgement sent */ + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE) + && !CHECK_FLAG(lsa->flag, OSPF6_LSA_IMPLIEDACK)) { + if (is_debug) + zlog_debug("Direct acknowledgement (BDR & Duplicate)"); + ospf6_lsdb_add(ospf6_lsa_copy(lsa), from->lsack_list); + thread_add_event(master, ospf6_lsack_send_neighbor, from, 0, + &from->thread_send_lsack); + return; + } + + /* LSA's LS age is equal to Maxage, and there is no current instance + of the LSA in the link state database, and none of router's + neighbors are in states Exchange or Loading */ + /* Direct acknowledgement sent, but this case is handled in + early of ospf6_receive_lsa () */ } -static void -ospf6_acknowledge_lsa_allother (struct ospf6_lsa *lsa, int ismore_recent, - struct ospf6_neighbor *from) +static void ospf6_acknowledge_lsa_allother(struct ospf6_lsa *lsa, + int ismore_recent, + struct ospf6_neighbor *from) { - struct ospf6_interface *oi; - int is_debug = 0; - - if (IS_OSPF6_DEBUG_FLOODING || - IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type)) - is_debug++; - - assert (from && from->ospf6_if); - oi = from->ospf6_if; - - /* LSA has been flood back out receiving interface. - No acknowledgement sent. */ - if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK)) - { - if (is_debug) - zlog_debug ("No acknowledgement (AllOther & FloodBack)"); - return; - } - - /* LSA is more recent than database copy, but was not flooded - back out receiving interface. Delayed acknowledgement sent. */ - if (ismore_recent < 0) - { - if (is_debug) - zlog_debug ("Delayed acknowledgement (AllOther & MoreRecent)"); - /* Delayed acknowledgement */ - ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list); - thread_add_timer(master, ospf6_lsack_send_interface, oi, 3, - &oi->thread_send_lsack); - return; - } - - /* LSA is a duplicate, and was treated as an implied acknowledgement. - No acknowledgement sent. */ - if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) && - CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) - { - if (is_debug) - zlog_debug ("No acknowledgement (AllOther & Duplicate & ImpliedAck)"); - return; - } - - /* LSA is a duplicate, and was not treated as an implied acknowledgement. - Direct acknowledgement sent */ - if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) && - ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) - { - if (is_debug) - zlog_debug ("Direct acknowledgement (AllOther & Duplicate)"); - ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list); - thread_add_event(master, ospf6_lsack_send_neighbor, from, 0, - &from->thread_send_lsack); - return; - } - - /* LSA's LS age is equal to Maxage, and there is no current instance - of the LSA in the link state database, and none of router's - neighbors are in states Exchange or Loading */ - /* Direct acknowledgement sent, but this case is handled in - early of ospf6_receive_lsa () */ + struct ospf6_interface *oi; + int is_debug = 0; + + if (IS_OSPF6_DEBUG_FLOODING + || IS_OSPF6_DEBUG_FLOOD_TYPE(lsa->header->type)) + is_debug++; + + assert(from && from->ospf6_if); + oi = from->ospf6_if; + + /* LSA has been flood back out receiving interface. + No acknowledgement sent. */ + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_FLOODBACK)) { + if (is_debug) + zlog_debug("No acknowledgement (AllOther & FloodBack)"); + return; + } + + /* LSA is more recent than database copy, but was not flooded + back out receiving interface. Delayed acknowledgement sent. */ + if (ismore_recent < 0) { + if (is_debug) + zlog_debug( + "Delayed acknowledgement (AllOther & MoreRecent)"); + /* Delayed acknowledgement */ + ospf6_lsdb_add(ospf6_lsa_copy(lsa), oi->lsack_list); + thread_add_timer(master, ospf6_lsack_send_interface, oi, 3, + &oi->thread_send_lsack); + return; + } + + /* LSA is a duplicate, and was treated as an implied acknowledgement. + No acknowledgement sent. */ + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE) + && CHECK_FLAG(lsa->flag, OSPF6_LSA_IMPLIEDACK)) { + if (is_debug) + zlog_debug( + "No acknowledgement (AllOther & Duplicate & ImpliedAck)"); + return; + } + + /* LSA is a duplicate, and was not treated as an implied + acknowledgement. + Direct acknowledgement sent */ + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE) + && !CHECK_FLAG(lsa->flag, OSPF6_LSA_IMPLIEDACK)) { + if (is_debug) + zlog_debug( + "Direct acknowledgement (AllOther & Duplicate)"); + ospf6_lsdb_add(ospf6_lsa_copy(lsa), from->lsack_list); + thread_add_event(master, ospf6_lsack_send_neighbor, from, 0, + &from->thread_send_lsack); + return; + } + + /* LSA's LS age is equal to Maxage, and there is no current instance + of the LSA in the link state database, and none of router's + neighbors are in states Exchange or Loading */ + /* Direct acknowledgement sent, but this case is handled in + early of ospf6_receive_lsa () */ } -static void -ospf6_acknowledge_lsa (struct ospf6_lsa *lsa, int ismore_recent, - struct ospf6_neighbor *from) +static void ospf6_acknowledge_lsa(struct ospf6_lsa *lsa, int ismore_recent, + struct ospf6_neighbor *from) { - struct ospf6_interface *oi; + struct ospf6_interface *oi; - assert (from && from->ospf6_if); - oi = from->ospf6_if; + assert(from && from->ospf6_if); + oi = from->ospf6_if; - if (oi->state == OSPF6_INTERFACE_BDR) - ospf6_acknowledge_lsa_bdrouter (lsa, ismore_recent, from); - else - ospf6_acknowledge_lsa_allother (lsa, ismore_recent, from); + if (oi->state == OSPF6_INTERFACE_BDR) + ospf6_acknowledge_lsa_bdrouter(lsa, ismore_recent, from); + else + ospf6_acknowledge_lsa_allother(lsa, ismore_recent, from); } /* RFC2328 section 13 (4): if MaxAge LSA and if we have no instance, and no neighbor is in states Exchange or Loading returns 1 if match this case, else returns 0 */ -static int -ospf6_is_maxage_lsa_drop (struct ospf6_lsa *lsa, struct ospf6_neighbor *from) +static int ospf6_is_maxage_lsa_drop(struct ospf6_lsa *lsa, + struct ospf6_neighbor *from) { - struct ospf6_neighbor *on; - struct ospf6_interface *oi; - struct ospf6_area *oa; - struct ospf6 *process = NULL; - struct listnode *i, *j, *k; - int count = 0; - - if (! OSPF6_LSA_IS_MAXAGE (lsa)) - return 0; - - if (ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, - lsa->header->adv_router, lsa->lsdb)) - return 0; - - process = from->ospf6_if->area->ospf6; - - for (ALL_LIST_ELEMENTS_RO (process->area_list, i, oa)) - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, k, on)) - if (on->state == OSPF6_NEIGHBOR_EXCHANGE || - on->state == OSPF6_NEIGHBOR_LOADING) - count++; - - if (count == 0) - return 1; - return 0; + struct ospf6_neighbor *on; + struct ospf6_interface *oi; + struct ospf6_area *oa; + struct ospf6 *process = NULL; + struct listnode *i, *j, *k; + int count = 0; + + if (!OSPF6_LSA_IS_MAXAGE(lsa)) + return 0; + + if (ospf6_lsdb_lookup(lsa->header->type, lsa->header->id, + lsa->header->adv_router, lsa->lsdb)) + return 0; + + process = from->ospf6_if->area->ospf6; + + for (ALL_LIST_ELEMENTS_RO(process->area_list, i, oa)) + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on)) + if (on->state == OSPF6_NEIGHBOR_EXCHANGE + || on->state == OSPF6_NEIGHBOR_LOADING) + count++; + + if (count == 0) + return 1; + return 0; } /* RFC2328 section 13 The Flooding Procedure */ -void -ospf6_receive_lsa (struct ospf6_neighbor *from, - struct ospf6_lsa_header *lsa_header) +void ospf6_receive_lsa(struct ospf6_neighbor *from, + struct ospf6_lsa_header *lsa_header) { - struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL; - int ismore_recent; - int is_debug = 0; - unsigned int time_delta_ms; - - ismore_recent = 1; - assert (from); - - /* make lsa structure for received lsa */ - new = ospf6_lsa_create (lsa_header); - - if (IS_OSPF6_DEBUG_FLOODING || - IS_OSPF6_DEBUG_FLOOD_TYPE (new->header->type)) - { - is_debug++; - zlog_debug ("LSA Receive from %s", from->name); - ospf6_lsa_header_print (new); - } - - /* (1) LSA Checksum */ - if (! ospf6_lsa_checksum_valid (new->header)) - { - if (is_debug) - zlog_debug ("Wrong LSA Checksum, discard"); - ospf6_lsa_delete (new); - return; - } - - /* (2) Examine the LSA's LS type. - RFC2470 3.5.1. Receiving Link State Update packets */ - if (IS_AREA_STUB (from->ospf6_if->area) && - OSPF6_LSA_SCOPE (new->header->type) == OSPF6_SCOPE_AS) - { - if (is_debug) - zlog_debug ("AS-External-LSA (or AS-scope LSA) in stub area, discard"); - ospf6_lsa_delete (new); - return; - } - - /* (3) LSA which have reserved scope is discarded - RFC2470 3.5.1. Receiving Link State Update packets */ - /* Flooding scope check. LSAs with unknown scope are discarded here. - Set appropriate LSDB for the LSA */ - switch (OSPF6_LSA_SCOPE (new->header->type)) - { - case OSPF6_SCOPE_LINKLOCAL: - new->lsdb = from->ospf6_if->lsdb; - break; - case OSPF6_SCOPE_AREA: - new->lsdb = from->ospf6_if->area->lsdb; - break; - case OSPF6_SCOPE_AS: - new->lsdb = from->ospf6_if->area->ospf6->lsdb; - break; - default: - if (is_debug) - zlog_debug ("LSA has reserved scope, discard"); - ospf6_lsa_delete (new); - return; - } - - /* (4) if MaxAge LSA and if we have no instance, and no neighbor - is in states Exchange or Loading */ - if (ospf6_is_maxage_lsa_drop (new, from)) - { - /* log */ - if (is_debug) - zlog_debug ("Drop MaxAge LSA with direct acknowledgement."); - - /* a) Acknowledge back to neighbor (Direct acknowledgement, 13.5) */ - ospf6_lsdb_add (ospf6_lsa_copy (new), from->lsack_list); - thread_add_event(master, ospf6_lsack_send_neighbor, from, 0, - &from->thread_send_lsack); - - /* b) Discard */ - ospf6_lsa_delete (new); - return; - } - - /* (5) */ - /* lookup the same database copy in lsdb */ - old = ospf6_lsdb_lookup (new->header->type, new->header->id, - new->header->adv_router, new->lsdb); - if (old) - { - ismore_recent = ospf6_lsa_compare (new, old); - if (ntohl (new->header->seqnum) == ntohl (old->header->seqnum)) - { - if (is_debug) - zlog_debug ("Received is duplicated LSA"); - SET_FLAG (new->flag, OSPF6_LSA_DUPLICATE); - } - } - - /* if no database copy or received is more recent */ - if (old == NULL || ismore_recent < 0) - { - /* in case we have no database copy */ - ismore_recent = -1; - - /* (a) MinLSArrival check */ - if (old) - { - struct timeval now, res; - monotime(&now); - timersub (&now, &old->installed, &res); - time_delta_ms = (res.tv_sec * 1000) + (int)(res.tv_usec/1000); - if (time_delta_ms < from->ospf6_if->area->ospf6->lsa_minarrival) - { - if (is_debug) - zlog_debug ("LSA can't be updated within MinLSArrival, %dms < %dms, discard", - time_delta_ms, from->ospf6_if->area->ospf6->lsa_minarrival); - ospf6_lsa_delete (new); - return; /* examin next lsa */ - } - } - - monotime(&new->received); - - if (is_debug) - zlog_debug ("Install, Flood, Possibly acknowledge the received LSA"); - - /* Remove older copies of this LSA from retx lists */ - if (old) - ospf6_flood_clear (old); - - /* (b) immediately flood and (c) remove from all retrans-list */ - /* Prevent self-originated LSA to be flooded. this is to make - reoriginated instance of the LSA not to be rejected by other routers - due to MinLSArrival. */ - if (new->header->adv_router != from->ospf6_if->area->ospf6->router_id) - ospf6_flood (from, new); - - /* (d), installing lsdb, which may cause routing - table calculation (replacing database copy) */ - ospf6_install_lsa (new); - - if (OSPF6_LSA_IS_MAXAGE (new)) - ospf6_maxage_remove (from->ospf6_if->area->ospf6); - - /* (e) possibly acknowledge */ - ospf6_acknowledge_lsa (new, ismore_recent, from); - - /* (f) Self Originated LSA, section 13.4 */ - if (new->header->adv_router == from->ospf6_if->area->ospf6->router_id) - { - /* Self-originated LSA (newer than ours) is received from - another router. We have to make a new instance of the LSA - or have to flush this LSA. */ - if (is_debug) - { - zlog_debug ("Newer instance of the self-originated LSA"); - zlog_debug ("Schedule reorigination"); - } - new->refresh = NULL; - thread_add_event(master, ospf6_lsa_refresh, new, 0, &new->refresh); - } - - return; - } - - /* (6) if there is instance on sending neighbor's request list */ - if (ospf6_lsdb_lookup (new->header->type, new->header->id, - new->header->adv_router, from->request_list)) - { - /* if no database copy, should go above state (5) */ - assert (old); - - if (is_debug) - { - zlog_debug ("Received is not newer, on the neighbor's request-list"); - zlog_debug ("BadLSReq, discard the received LSA"); - } - - /* BadLSReq */ - thread_add_event(master, bad_lsreq, from, 0, NULL); - - ospf6_lsa_delete (new); - return; - } - - /* (7) if neither one is more recent */ - if (ismore_recent == 0) - { - if (is_debug) - zlog_debug ("The same instance as database copy (neither recent)"); - - /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack */ - rem = ospf6_lsdb_lookup (new->header->type, new->header->id, - new->header->adv_router, from->retrans_list); - if (rem) - { - if (is_debug) - { - zlog_debug ("It is on the neighbor's retrans-list."); - zlog_debug ("Treat as an Implied acknowledgement"); - } - SET_FLAG (new->flag, OSPF6_LSA_IMPLIEDACK); - ospf6_decrement_retrans_count (rem); - ospf6_lsdb_remove (rem, from->retrans_list); - } - - if (is_debug) - zlog_debug ("Possibly acknowledge and then discard"); - - /* (b) possibly acknowledge */ - ospf6_acknowledge_lsa (new, ismore_recent, from); - - ospf6_lsa_delete (new); - return; - } - - /* (8) previous database copy is more recent */ - { - assert (old); - - /* If database copy is in 'Seqnumber Wrapping', - simply discard the received LSA */ - if (OSPF6_LSA_IS_MAXAGE (old) && - old->header->seqnum == htonl (OSPF_MAX_SEQUENCE_NUMBER)) - { - if (is_debug) - { - zlog_debug ("The LSA is in Seqnumber Wrapping"); - zlog_debug ("MaxAge & MaxSeqNum, discard"); - } - ospf6_lsa_delete (new); - return; - } - - /* Otherwise, Send database copy of this LSA to this neighbor */ - { - if (is_debug) - { - zlog_debug ("Database copy is more recent."); - zlog_debug ("Send back directly and then discard"); - } - - /* XXX, MinLSArrival check !? RFC 2328 13 (8) */ - - ospf6_lsdb_add (ospf6_lsa_copy (old), from->lsupdate_list); - thread_add_event(master, ospf6_lsupdate_send_neighbor, from, 0, - &from->thread_send_lsupdate); - ospf6_lsa_delete (new); - return; - } - return; - } + struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL; + int ismore_recent; + int is_debug = 0; + unsigned int time_delta_ms; + + ismore_recent = 1; + assert(from); + + /* make lsa structure for received lsa */ + new = ospf6_lsa_create(lsa_header); + + if (IS_OSPF6_DEBUG_FLOODING + || IS_OSPF6_DEBUG_FLOOD_TYPE(new->header->type)) { + is_debug++; + zlog_debug("LSA Receive from %s", from->name); + ospf6_lsa_header_print(new); + } + + /* (1) LSA Checksum */ + if (!ospf6_lsa_checksum_valid(new->header)) { + if (is_debug) + zlog_debug("Wrong LSA Checksum, discard"); + ospf6_lsa_delete(new); + return; + } + + /* (2) Examine the LSA's LS type. + RFC2470 3.5.1. Receiving Link State Update packets */ + if (IS_AREA_STUB(from->ospf6_if->area) + && OSPF6_LSA_SCOPE(new->header->type) == OSPF6_SCOPE_AS) { + if (is_debug) + zlog_debug( + "AS-External-LSA (or AS-scope LSA) in stub area, discard"); + ospf6_lsa_delete(new); + return; + } + + /* (3) LSA which have reserved scope is discarded + RFC2470 3.5.1. Receiving Link State Update packets */ + /* Flooding scope check. LSAs with unknown scope are discarded here. + Set appropriate LSDB for the LSA */ + switch (OSPF6_LSA_SCOPE(new->header->type)) { + case OSPF6_SCOPE_LINKLOCAL: + new->lsdb = from->ospf6_if->lsdb; + break; + case OSPF6_SCOPE_AREA: + new->lsdb = from->ospf6_if->area->lsdb; + break; + case OSPF6_SCOPE_AS: + new->lsdb = from->ospf6_if->area->ospf6->lsdb; + break; + default: + if (is_debug) + zlog_debug("LSA has reserved scope, discard"); + ospf6_lsa_delete(new); + return; + } + + /* (4) if MaxAge LSA and if we have no instance, and no neighbor + is in states Exchange or Loading */ + if (ospf6_is_maxage_lsa_drop(new, from)) { + /* log */ + if (is_debug) + zlog_debug( + "Drop MaxAge LSA with direct acknowledgement."); + + /* a) Acknowledge back to neighbor (Direct acknowledgement, + * 13.5) */ + ospf6_lsdb_add(ospf6_lsa_copy(new), from->lsack_list); + thread_add_event(master, ospf6_lsack_send_neighbor, from, 0, + &from->thread_send_lsack); + + /* b) Discard */ + ospf6_lsa_delete(new); + return; + } + + /* (5) */ + /* lookup the same database copy in lsdb */ + old = ospf6_lsdb_lookup(new->header->type, new->header->id, + new->header->adv_router, new->lsdb); + if (old) { + ismore_recent = ospf6_lsa_compare(new, old); + if (ntohl(new->header->seqnum) == ntohl(old->header->seqnum)) { + if (is_debug) + zlog_debug("Received is duplicated LSA"); + SET_FLAG(new->flag, OSPF6_LSA_DUPLICATE); + } + } + + /* if no database copy or received is more recent */ + if (old == NULL || ismore_recent < 0) { + /* in case we have no database copy */ + ismore_recent = -1; + + /* (a) MinLSArrival check */ + if (old) { + struct timeval now, res; + monotime(&now); + timersub(&now, &old->installed, &res); + time_delta_ms = + (res.tv_sec * 1000) + (int)(res.tv_usec / 1000); + if (time_delta_ms + < from->ospf6_if->area->ospf6->lsa_minarrival) { + if (is_debug) + zlog_debug( + "LSA can't be updated within MinLSArrival, %dms < %dms, discard", + time_delta_ms, + from->ospf6_if->area->ospf6 + ->lsa_minarrival); + ospf6_lsa_delete(new); + return; /* examin next lsa */ + } + } + + monotime(&new->received); + + if (is_debug) + zlog_debug( + "Install, Flood, Possibly acknowledge the received LSA"); + + /* Remove older copies of this LSA from retx lists */ + if (old) + ospf6_flood_clear(old); + + /* (b) immediately flood and (c) remove from all retrans-list */ + /* Prevent self-originated LSA to be flooded. this is to make + reoriginated instance of the LSA not to be rejected by other + routers + due to MinLSArrival. */ + if (new->header->adv_router + != from->ospf6_if->area->ospf6->router_id) + ospf6_flood(from, new); + + /* (d), installing lsdb, which may cause routing + table calculation (replacing database copy) */ + ospf6_install_lsa(new); + + if (OSPF6_LSA_IS_MAXAGE(new)) + ospf6_maxage_remove(from->ospf6_if->area->ospf6); + + /* (e) possibly acknowledge */ + ospf6_acknowledge_lsa(new, ismore_recent, from); + + /* (f) Self Originated LSA, section 13.4 */ + if (new->header->adv_router + == from->ospf6_if->area->ospf6->router_id) { + /* Self-originated LSA (newer than ours) is received + from + another router. We have to make a new instance of the + LSA + or have to flush this LSA. */ + if (is_debug) { + zlog_debug( + "Newer instance of the self-originated LSA"); + zlog_debug("Schedule reorigination"); + } + new->refresh = NULL; + thread_add_event(master, ospf6_lsa_refresh, new, 0, + &new->refresh); + } + + return; + } + + /* (6) if there is instance on sending neighbor's request list */ + if (ospf6_lsdb_lookup(new->header->type, new->header->id, + new->header->adv_router, from->request_list)) { + /* if no database copy, should go above state (5) */ + assert(old); + + if (is_debug) { + zlog_debug( + "Received is not newer, on the neighbor's request-list"); + zlog_debug("BadLSReq, discard the received LSA"); + } + + /* BadLSReq */ + thread_add_event(master, bad_lsreq, from, 0, NULL); + + ospf6_lsa_delete(new); + return; + } + + /* (7) if neither one is more recent */ + if (ismore_recent == 0) { + if (is_debug) + zlog_debug( + "The same instance as database copy (neither recent)"); + + /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack + */ + rem = ospf6_lsdb_lookup(new->header->type, new->header->id, + new->header->adv_router, + from->retrans_list); + if (rem) { + if (is_debug) { + zlog_debug( + "It is on the neighbor's retrans-list."); + zlog_debug( + "Treat as an Implied acknowledgement"); + } + SET_FLAG(new->flag, OSPF6_LSA_IMPLIEDACK); + ospf6_decrement_retrans_count(rem); + ospf6_lsdb_remove(rem, from->retrans_list); + } + + if (is_debug) + zlog_debug("Possibly acknowledge and then discard"); + + /* (b) possibly acknowledge */ + ospf6_acknowledge_lsa(new, ismore_recent, from); + + ospf6_lsa_delete(new); + return; + } + + /* (8) previous database copy is more recent */ + { + assert(old); + + /* If database copy is in 'Seqnumber Wrapping', + simply discard the received LSA */ + if (OSPF6_LSA_IS_MAXAGE(old) + && old->header->seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER)) { + if (is_debug) { + zlog_debug("The LSA is in Seqnumber Wrapping"); + zlog_debug("MaxAge & MaxSeqNum, discard"); + } + ospf6_lsa_delete(new); + return; + } + + /* Otherwise, Send database copy of this LSA to this neighbor */ + { + if (is_debug) { + zlog_debug("Database copy is more recent."); + zlog_debug( + "Send back directly and then discard"); + } + + /* XXX, MinLSArrival check !? RFC 2328 13 (8) */ + + ospf6_lsdb_add(ospf6_lsa_copy(old), + from->lsupdate_list); + thread_add_event(master, ospf6_lsupdate_send_neighbor, + from, 0, &from->thread_send_lsupdate); + ospf6_lsa_delete(new); + return; + } + return; + } } @@ -1011,8 +981,8 @@ DEFUN (debug_ospf6_flooding, "Debug OSPFv3 flooding function\n" ) { - OSPF6_DEBUG_FLOODING_ON (); - return CMD_SUCCESS; + OSPF6_DEBUG_FLOODING_ON(); + return CMD_SUCCESS; } DEFUN (no_debug_ospf6_flooding, @@ -1024,28 +994,21 @@ DEFUN (no_debug_ospf6_flooding, "Debug OSPFv3 flooding function\n" ) { - OSPF6_DEBUG_FLOODING_OFF (); - return CMD_SUCCESS; + OSPF6_DEBUG_FLOODING_OFF(); + return CMD_SUCCESS; } -int -config_write_ospf6_debug_flood (struct vty *vty) +int config_write_ospf6_debug_flood(struct vty *vty) { - if (IS_OSPF6_DEBUG_FLOODING) - vty_out (vty, "debug ospf6 flooding\n"); - return 0; + if (IS_OSPF6_DEBUG_FLOODING) + vty_out(vty, "debug ospf6 flooding\n"); + return 0; } -void -install_element_ospf6_debug_flood (void) +void install_element_ospf6_debug_flood(void) { - install_element (ENABLE_NODE, &debug_ospf6_flooding_cmd); - install_element (ENABLE_NODE, &no_debug_ospf6_flooding_cmd); - install_element (CONFIG_NODE, &debug_ospf6_flooding_cmd); - install_element (CONFIG_NODE, &no_debug_ospf6_flooding_cmd); + install_element(ENABLE_NODE, &debug_ospf6_flooding_cmd); + install_element(ENABLE_NODE, &no_debug_ospf6_flooding_cmd); + install_element(CONFIG_NODE, &debug_ospf6_flooding_cmd); + install_element(CONFIG_NODE, &no_debug_ospf6_flooding_cmd); } - - - - - diff --git a/ospf6d/ospf6_flood.h b/ospf6d/ospf6_flood.h index 72482cadf..610eefc80 100644 --- a/ospf6d/ospf6_flood.h +++ b/ospf6d/ospf6_flood.h @@ -23,45 +23,40 @@ /* Debug option */ extern unsigned char conf_debug_ospf6_flooding; -#define OSPF6_DEBUG_FLOODING_ON() \ - (conf_debug_ospf6_flooding = 1) -#define OSPF6_DEBUG_FLOODING_OFF() \ - (conf_debug_ospf6_flooding = 0) -#define IS_OSPF6_DEBUG_FLOODING \ - (conf_debug_ospf6_flooding) +#define OSPF6_DEBUG_FLOODING_ON() (conf_debug_ospf6_flooding = 1) +#define OSPF6_DEBUG_FLOODING_OFF() (conf_debug_ospf6_flooding = 0) +#define IS_OSPF6_DEBUG_FLOODING (conf_debug_ospf6_flooding) /* Function Prototypes */ -extern struct ospf6_lsdb *ospf6_get_scoped_lsdb (struct ospf6_lsa *lsa); -extern struct ospf6_lsdb *ospf6_get_scoped_lsdb_self (struct ospf6_lsa *lsa); +extern struct ospf6_lsdb *ospf6_get_scoped_lsdb(struct ospf6_lsa *lsa); +extern struct ospf6_lsdb *ospf6_get_scoped_lsdb_self(struct ospf6_lsa *lsa); /* origination & purging */ -extern void ospf6_lsa_originate (struct ospf6_lsa *lsa); -extern void ospf6_lsa_originate_process (struct ospf6_lsa *lsa, - struct ospf6 *process); -extern void ospf6_lsa_originate_area (struct ospf6_lsa *lsa, - struct ospf6_area *oa); -extern void ospf6_lsa_originate_interface (struct ospf6_lsa *lsa, - struct ospf6_interface *oi); -extern void ospf6_lsa_purge (struct ospf6_lsa *lsa); +extern void ospf6_lsa_originate(struct ospf6_lsa *lsa); +extern void ospf6_lsa_originate_process(struct ospf6_lsa *lsa, + struct ospf6 *process); +extern void ospf6_lsa_originate_area(struct ospf6_lsa *lsa, + struct ospf6_area *oa); +extern void ospf6_lsa_originate_interface(struct ospf6_lsa *lsa, + struct ospf6_interface *oi); +extern void ospf6_lsa_purge(struct ospf6_lsa *lsa); /* access method to retrans_count */ -extern void ospf6_increment_retrans_count (struct ospf6_lsa *lsa); -extern void ospf6_decrement_retrans_count (struct ospf6_lsa *lsa); +extern void ospf6_increment_retrans_count(struct ospf6_lsa *lsa); +extern void ospf6_decrement_retrans_count(struct ospf6_lsa *lsa); /* flooding & clear flooding */ -extern void ospf6_flood_clear (struct ospf6_lsa *lsa); -extern void ospf6_flood (struct ospf6_neighbor *from, struct ospf6_lsa *lsa); -extern void ospf6_flood_area (struct ospf6_neighbor *from, - struct ospf6_lsa *lsa, struct ospf6_area *oa); +extern void ospf6_flood_clear(struct ospf6_lsa *lsa); +extern void ospf6_flood(struct ospf6_neighbor *from, struct ospf6_lsa *lsa); +extern void ospf6_flood_area(struct ospf6_neighbor *from, struct ospf6_lsa *lsa, + struct ospf6_area *oa); /* receive & install */ -extern void ospf6_receive_lsa (struct ospf6_neighbor *from, - struct ospf6_lsa_header *header); -extern void ospf6_install_lsa (struct ospf6_lsa *lsa); +extern void ospf6_receive_lsa(struct ospf6_neighbor *from, + struct ospf6_lsa_header *header); +extern void ospf6_install_lsa(struct ospf6_lsa *lsa); -extern int config_write_ospf6_debug_flood (struct vty *vty); -extern void install_element_ospf6_debug_flood (void); +extern int config_write_ospf6_debug_flood(struct vty *vty); +extern void install_element_ospf6_debug_flood(void); #endif /* OSPF6_FLOOD_H */ - - diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index ab5b4f935..1d17a1c23 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -46,959 +46,922 @@ DEFINE_MTYPE_STATIC(OSPF6D, CFG_PLIST_NAME, "configured prefix list names") DEFINE_QOBJ_TYPE(ospf6_interface) DEFINE_HOOK(ospf6_interface_change, - (struct ospf6_interface *oi, int state, int old_state), - (oi, state, old_state)) + (struct ospf6_interface * oi, int state, int old_state), + (oi, state, old_state)) unsigned char conf_debug_ospf6_interface = 0; -const char *ospf6_interface_state_str[] = -{ - "None", - "Down", - "Loopback", - "Waiting", - "PointToPoint", - "DROther", - "BDR", - "DR", - NULL -}; +const char *ospf6_interface_state_str[] = { + "None", "Down", "Loopback", "Waiting", "PointToPoint", + "DROther", "BDR", "DR", NULL}; -struct ospf6_interface * -ospf6_interface_lookup_by_ifindex (ifindex_t ifindex) +struct ospf6_interface *ospf6_interface_lookup_by_ifindex(ifindex_t ifindex) { - struct ospf6_interface *oi; - struct interface *ifp; + struct ospf6_interface *oi; + struct interface *ifp; - ifp = if_lookup_by_index (ifindex, VRF_DEFAULT); - if (ifp == NULL) - return (struct ospf6_interface *) NULL; + ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); + if (ifp == NULL) + return (struct ospf6_interface *)NULL; - oi = (struct ospf6_interface *) ifp->info; - return oi; + oi = (struct ospf6_interface *)ifp->info; + return oi; } /* schedule routing table recalculation */ -static void -ospf6_interface_lsdb_hook (struct ospf6_lsa *lsa, unsigned int reason) +static void ospf6_interface_lsdb_hook(struct ospf6_lsa *lsa, + unsigned int reason) { - struct ospf6_interface *oi; - - if (lsa == NULL) - return; - - oi = lsa->lsdb->data; - switch (ntohs (lsa->header->type)) - { - case OSPF6_LSTYPE_LINK: - if (oi->state == OSPF6_INTERFACE_DR) - OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi); - if (oi->area) - ospf6_spf_schedule (oi->area->ospf6, reason); - break; - - default: - break; - } + struct ospf6_interface *oi; + + if (lsa == NULL) + return; + + oi = lsa->lsdb->data; + switch (ntohs(lsa->header->type)) { + case OSPF6_LSTYPE_LINK: + if (oi->state == OSPF6_INTERFACE_DR) + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi); + if (oi->area) + ospf6_spf_schedule(oi->area->ospf6, reason); + break; + + default: + break; + } } -static void -ospf6_interface_lsdb_hook_add (struct ospf6_lsa *lsa) +static void ospf6_interface_lsdb_hook_add(struct ospf6_lsa *lsa) { - ospf6_interface_lsdb_hook(lsa, ospf6_lsadd_to_spf_reason(lsa)); + ospf6_interface_lsdb_hook(lsa, ospf6_lsadd_to_spf_reason(lsa)); } -static void -ospf6_interface_lsdb_hook_remove (struct ospf6_lsa *lsa) +static void ospf6_interface_lsdb_hook_remove(struct ospf6_lsa *lsa) { - ospf6_interface_lsdb_hook(lsa, ospf6_lsremove_to_spf_reason(lsa)); + ospf6_interface_lsdb_hook(lsa, ospf6_lsremove_to_spf_reason(lsa)); } -static u_char -ospf6_default_iftype(struct interface *ifp) +static u_char ospf6_default_iftype(struct interface *ifp) { - if (if_is_pointopoint (ifp)) - return OSPF_IFTYPE_POINTOPOINT; - else if (if_is_loopback (ifp)) - return OSPF_IFTYPE_LOOPBACK; - else - return OSPF_IFTYPE_BROADCAST; + if (if_is_pointopoint(ifp)) + return OSPF_IFTYPE_POINTOPOINT; + else if (if_is_loopback(ifp)) + return OSPF_IFTYPE_LOOPBACK; + else + return OSPF_IFTYPE_BROADCAST; } -static u_int32_t -ospf6_interface_get_cost (struct ospf6_interface *oi) +static u_int32_t ospf6_interface_get_cost(struct ospf6_interface *oi) { - /* If all else fails, use default OSPF cost */ - u_int32_t cost; - u_int32_t bw, refbw; - - bw = oi->interface->bandwidth ? oi->interface->bandwidth : OSPF6_INTERFACE_BANDWIDTH; - refbw = ospf6 ? ospf6->ref_bandwidth : OSPF6_REFERENCE_BANDWIDTH; - - /* A specifed ip ospf cost overrides a calculated one. */ - if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_NOAUTOCOST)) - cost = oi->cost; - else - { - cost = (u_int32_t) ((double)refbw / (double)bw + (double)0.5); - if (cost < 1) cost = 1; - else if (cost > UINT32_MAX) cost = UINT32_MAX; - } - - return cost; + /* If all else fails, use default OSPF cost */ + u_int32_t cost; + u_int32_t bw, refbw; + + bw = oi->interface->bandwidth ? oi->interface->bandwidth + : OSPF6_INTERFACE_BANDWIDTH; + refbw = ospf6 ? ospf6->ref_bandwidth : OSPF6_REFERENCE_BANDWIDTH; + + /* A specifed ip ospf cost overrides a calculated one. */ + if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST)) + cost = oi->cost; + else { + cost = (u_int32_t)((double)refbw / (double)bw + (double)0.5); + if (cost < 1) + cost = 1; + else if (cost > UINT32_MAX) + cost = UINT32_MAX; + } + + return cost; } -static void -ospf6_interface_recalculate_cost (struct ospf6_interface *oi) +static void ospf6_interface_recalculate_cost(struct ospf6_interface *oi) { - u_int32_t newcost; - - newcost = ospf6_interface_get_cost (oi); - if (newcost == oi->cost) return; - oi->cost = newcost; - - /* update cost held in route_connected list in ospf6_interface */ - ospf6_interface_connected_route_update (oi->interface); - - /* execute LSA hooks */ - if (oi->area) - { - OSPF6_LINK_LSA_SCHEDULE (oi); - OSPF6_ROUTER_LSA_SCHEDULE (oi->area); - OSPF6_NETWORK_LSA_SCHEDULE (oi); - OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi); - OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area); - } + u_int32_t newcost; + + newcost = ospf6_interface_get_cost(oi); + if (newcost == oi->cost) + return; + oi->cost = newcost; + + /* update cost held in route_connected list in ospf6_interface */ + ospf6_interface_connected_route_update(oi->interface); + + /* execute LSA hooks */ + if (oi->area) { + OSPF6_LINK_LSA_SCHEDULE(oi); + OSPF6_ROUTER_LSA_SCHEDULE(oi->area); + OSPF6_NETWORK_LSA_SCHEDULE(oi); + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi); + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area); + } } /* Create new ospf6 interface structure */ -struct ospf6_interface * -ospf6_interface_create (struct interface *ifp) +struct ospf6_interface *ospf6_interface_create(struct interface *ifp) { - struct ospf6_interface *oi; - unsigned int iobuflen; - - oi = (struct ospf6_interface *) - XCALLOC (MTYPE_OSPF6_IF, sizeof (struct ospf6_interface)); - - if (!oi) - { - zlog_err ("Can't malloc ospf6_interface for ifindex %d", ifp->ifindex); - return (struct ospf6_interface *) NULL; - } - - oi->area = (struct ospf6_area *) NULL; - oi->neighbor_list = list_new (); - oi->neighbor_list->cmp = ospf6_neighbor_cmp; - oi->linklocal_addr = (struct in6_addr *) NULL; - oi->instance_id = OSPF6_INTERFACE_INSTANCE_ID; - oi->transdelay = OSPF6_INTERFACE_TRANSDELAY; - oi->priority = OSPF6_INTERFACE_PRIORITY; - - oi->hello_interval = OSPF_HELLO_INTERVAL_DEFAULT; - oi->dead_interval = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT; - oi->rxmt_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT; - oi->type = ospf6_default_iftype (ifp); - oi->state = OSPF6_INTERFACE_DOWN; - oi->flag = 0; - oi->mtu_ignore = 0; - oi->c_ifmtu = 0; - - /* Try to adjust I/O buffer size with IfMtu */ - oi->ifmtu = ifp->mtu6; - iobuflen = ospf6_iobuf_size (ifp->mtu6); - if (oi->ifmtu > iobuflen) - { - if (IS_OSPF6_DEBUG_INTERFACE) - zlog_debug ("Interface %s: IfMtu is adjusted to I/O buffer size: %d.", - ifp->name, iobuflen); - oi->ifmtu = iobuflen; - } - - QOBJ_REG (oi, ospf6_interface); - - oi->lsupdate_list = ospf6_lsdb_create (oi); - oi->lsack_list = ospf6_lsdb_create (oi); - oi->lsdb = ospf6_lsdb_create (oi); - oi->lsdb->hook_add = ospf6_interface_lsdb_hook_add; - oi->lsdb->hook_remove = ospf6_interface_lsdb_hook_remove; - oi->lsdb_self = ospf6_lsdb_create (oi); - - oi->route_connected = OSPF6_ROUTE_TABLE_CREATE (INTERFACE, CONNECTED_ROUTES); - oi->route_connected->scope = oi; - - /* link both */ - oi->interface = ifp; - ifp->info = oi; - - /* Compute cost. */ - oi->cost = ospf6_interface_get_cost(oi); - - return oi; + struct ospf6_interface *oi; + unsigned int iobuflen; + + oi = (struct ospf6_interface *)XCALLOC(MTYPE_OSPF6_IF, + sizeof(struct ospf6_interface)); + + if (!oi) { + zlog_err("Can't malloc ospf6_interface for ifindex %d", + ifp->ifindex); + return (struct ospf6_interface *)NULL; + } + + oi->area = (struct ospf6_area *)NULL; + oi->neighbor_list = list_new(); + oi->neighbor_list->cmp = ospf6_neighbor_cmp; + oi->linklocal_addr = (struct in6_addr *)NULL; + oi->instance_id = OSPF6_INTERFACE_INSTANCE_ID; + oi->transdelay = OSPF6_INTERFACE_TRANSDELAY; + oi->priority = OSPF6_INTERFACE_PRIORITY; + + oi->hello_interval = OSPF_HELLO_INTERVAL_DEFAULT; + oi->dead_interval = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT; + oi->rxmt_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT; + oi->type = ospf6_default_iftype(ifp); + oi->state = OSPF6_INTERFACE_DOWN; + oi->flag = 0; + oi->mtu_ignore = 0; + oi->c_ifmtu = 0; + + /* Try to adjust I/O buffer size with IfMtu */ + oi->ifmtu = ifp->mtu6; + iobuflen = ospf6_iobuf_size(ifp->mtu6); + if (oi->ifmtu > iobuflen) { + if (IS_OSPF6_DEBUG_INTERFACE) + zlog_debug( + "Interface %s: IfMtu is adjusted to I/O buffer size: %d.", + ifp->name, iobuflen); + oi->ifmtu = iobuflen; + } + + QOBJ_REG(oi, ospf6_interface); + + oi->lsupdate_list = ospf6_lsdb_create(oi); + oi->lsack_list = ospf6_lsdb_create(oi); + oi->lsdb = ospf6_lsdb_create(oi); + oi->lsdb->hook_add = ospf6_interface_lsdb_hook_add; + oi->lsdb->hook_remove = ospf6_interface_lsdb_hook_remove; + oi->lsdb_self = ospf6_lsdb_create(oi); + + oi->route_connected = + OSPF6_ROUTE_TABLE_CREATE(INTERFACE, CONNECTED_ROUTES); + oi->route_connected->scope = oi; + + /* link both */ + oi->interface = ifp; + ifp->info = oi; + + /* Compute cost. */ + oi->cost = ospf6_interface_get_cost(oi); + + return oi; } -void -ospf6_interface_delete (struct ospf6_interface *oi) +void ospf6_interface_delete(struct ospf6_interface *oi) { - struct listnode *node, *nnode; - struct ospf6_neighbor *on; + struct listnode *node, *nnode; + struct ospf6_neighbor *on; + + QOBJ_UNREG(oi); - QOBJ_UNREG (oi); + for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) + ospf6_neighbor_delete(on); - for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) - ospf6_neighbor_delete (on); - - list_delete (oi->neighbor_list); + list_delete(oi->neighbor_list); - THREAD_OFF (oi->thread_send_hello); - THREAD_OFF (oi->thread_send_lsupdate); - THREAD_OFF (oi->thread_send_lsack); + THREAD_OFF(oi->thread_send_hello); + THREAD_OFF(oi->thread_send_lsupdate); + THREAD_OFF(oi->thread_send_lsack); - ospf6_lsdb_remove_all (oi->lsdb); - ospf6_lsdb_remove_all (oi->lsupdate_list); - ospf6_lsdb_remove_all (oi->lsack_list); + ospf6_lsdb_remove_all(oi->lsdb); + ospf6_lsdb_remove_all(oi->lsupdate_list); + ospf6_lsdb_remove_all(oi->lsack_list); - ospf6_lsdb_delete (oi->lsdb); - ospf6_lsdb_delete (oi->lsdb_self); + ospf6_lsdb_delete(oi->lsdb); + ospf6_lsdb_delete(oi->lsdb_self); - ospf6_lsdb_delete (oi->lsupdate_list); - ospf6_lsdb_delete (oi->lsack_list); + ospf6_lsdb_delete(oi->lsupdate_list); + ospf6_lsdb_delete(oi->lsack_list); - ospf6_route_table_delete (oi->route_connected); + ospf6_route_table_delete(oi->route_connected); - /* cut link */ - oi->interface->info = NULL; + /* cut link */ + oi->interface->info = NULL; - /* plist_name */ - if (oi->plist_name) - XFREE (MTYPE_CFG_PLIST_NAME, oi->plist_name); + /* plist_name */ + if (oi->plist_name) + XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name); - ospf6_bfd_info_free(&(oi->bfd_info)); + ospf6_bfd_info_free(&(oi->bfd_info)); - XFREE (MTYPE_OSPF6_IF, oi); + XFREE(MTYPE_OSPF6_IF, oi); } -void -ospf6_interface_enable (struct ospf6_interface *oi) +void ospf6_interface_enable(struct ospf6_interface *oi) { - UNSET_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE); - ospf6_interface_state_update (oi->interface); + UNSET_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE); + ospf6_interface_state_update(oi->interface); } -void -ospf6_interface_disable (struct ospf6_interface *oi) +void ospf6_interface_disable(struct ospf6_interface *oi) { - SET_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE); + SET_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE); - thread_execute (master, interface_down, oi, 0); + thread_execute(master, interface_down, oi, 0); - ospf6_lsdb_remove_all (oi->lsdb); - ospf6_lsdb_remove_all (oi->lsdb_self); - ospf6_lsdb_remove_all (oi->lsupdate_list); - ospf6_lsdb_remove_all (oi->lsack_list); + ospf6_lsdb_remove_all(oi->lsdb); + ospf6_lsdb_remove_all(oi->lsdb_self); + ospf6_lsdb_remove_all(oi->lsupdate_list); + ospf6_lsdb_remove_all(oi->lsack_list); - THREAD_OFF (oi->thread_send_hello); - THREAD_OFF (oi->thread_send_lsupdate); - THREAD_OFF (oi->thread_send_lsack); + THREAD_OFF(oi->thread_send_hello); + THREAD_OFF(oi->thread_send_lsupdate); + THREAD_OFF(oi->thread_send_lsack); - THREAD_OFF (oi->thread_network_lsa); - THREAD_OFF (oi->thread_link_lsa); - THREAD_OFF (oi->thread_intra_prefix_lsa); + THREAD_OFF(oi->thread_network_lsa); + THREAD_OFF(oi->thread_link_lsa); + THREAD_OFF(oi->thread_intra_prefix_lsa); } static struct in6_addr * -ospf6_interface_get_linklocal_address (struct interface *ifp) +ospf6_interface_get_linklocal_address(struct interface *ifp) { - struct listnode *n; - struct connected *c; - struct in6_addr *l = (struct in6_addr *) NULL; - - /* for each connected address */ - for (ALL_LIST_ELEMENTS_RO (ifp->connected, n, c)) - { - /* if family not AF_INET6, ignore */ - if (c->address->family != AF_INET6) - continue; - - /* linklocal scope check */ - if (IN6_IS_ADDR_LINKLOCAL (&c->address->u.prefix6)) - l = &c->address->u.prefix6; - } - return l; + struct listnode *n; + struct connected *c; + struct in6_addr *l = (struct in6_addr *)NULL; + + /* for each connected address */ + for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) { + /* if family not AF_INET6, ignore */ + if (c->address->family != AF_INET6) + continue; + + /* linklocal scope check */ + if (IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6)) + l = &c->address->u.prefix6; + } + return l; } -void -ospf6_interface_if_add (struct interface *ifp) +void ospf6_interface_if_add(struct interface *ifp) { - struct ospf6_interface *oi; - unsigned int iobuflen; - - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - return; - - /* Try to adjust I/O buffer size with IfMtu */ - if (oi->ifmtu == 0) - oi->ifmtu = ifp->mtu6; - iobuflen = ospf6_iobuf_size (ifp->mtu6); - if (oi->ifmtu > iobuflen) - { - if (IS_OSPF6_DEBUG_INTERFACE) - zlog_debug ("Interface %s: IfMtu is adjusted to I/O buffer size: %d.", - ifp->name, iobuflen); - oi->ifmtu = iobuflen; - } - - /* interface start */ - ospf6_interface_state_update(oi->interface); + struct ospf6_interface *oi; + unsigned int iobuflen; + + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + return; + + /* Try to adjust I/O buffer size with IfMtu */ + if (oi->ifmtu == 0) + oi->ifmtu = ifp->mtu6; + iobuflen = ospf6_iobuf_size(ifp->mtu6); + if (oi->ifmtu > iobuflen) { + if (IS_OSPF6_DEBUG_INTERFACE) + zlog_debug( + "Interface %s: IfMtu is adjusted to I/O buffer size: %d.", + ifp->name, iobuflen); + oi->ifmtu = iobuflen; + } + + /* interface start */ + ospf6_interface_state_update(oi->interface); } -void -ospf6_interface_if_del (struct interface *ifp) +void ospf6_interface_if_del(struct interface *ifp) { - struct ospf6_interface *oi; + struct ospf6_interface *oi; - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - return; + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + return; - /* interface stop */ - if (oi->area) - thread_execute (master, interface_down, oi, 0); + /* interface stop */ + if (oi->area) + thread_execute(master, interface_down, oi, 0); - listnode_delete (oi->area->if_list, oi); - oi->area = (struct ospf6_area *) NULL; + listnode_delete(oi->area->if_list, oi); + oi->area = (struct ospf6_area *)NULL; - /* cut link */ - oi->interface = NULL; - ifp->info = NULL; + /* cut link */ + oi->interface = NULL; + ifp->info = NULL; - ospf6_interface_delete (oi); + ospf6_interface_delete(oi); } -void -ospf6_interface_state_update (struct interface *ifp) +void ospf6_interface_state_update(struct interface *ifp) { - struct ospf6_interface *oi; - unsigned int iobuflen; - - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - return; - if (oi->area == NULL) - return; - if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE)) - return; - - /* Adjust the mtu values if the kernel told us something new */ - if (ifp->mtu6 != oi->ifmtu) - { - /* If nothing configured, accept it and check for buffer size */ - if (!oi->c_ifmtu) - { - oi->ifmtu = ifp->mtu6; - iobuflen = ospf6_iobuf_size (ifp->mtu6); - if (oi->ifmtu > iobuflen) - { - if (IS_OSPF6_DEBUG_INTERFACE) - zlog_debug ("Interface %s: IfMtu is adjusted to I/O buffer size: %d.", - ifp->name, iobuflen); - oi->ifmtu = iobuflen; - } - } - else if (oi->c_ifmtu > ifp->mtu6) - { - oi->ifmtu = ifp->mtu6; - zlog_warn ("Configured mtu %u on %s overridden by kernel %u", - oi->c_ifmtu, ifp->name, ifp->mtu6); - } - else - oi->ifmtu = oi->c_ifmtu; - } - - if (if_is_operative (ifp) - && (ospf6_interface_get_linklocal_address(oi->interface) - || if_is_loopback(oi->interface))) - thread_add_event(master, interface_up, oi, 0, NULL); - else - thread_add_event(master, interface_down, oi, 0, NULL); - - return; + struct ospf6_interface *oi; + unsigned int iobuflen; + + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + return; + if (oi->area == NULL) + return; + if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) + return; + + /* Adjust the mtu values if the kernel told us something new */ + if (ifp->mtu6 != oi->ifmtu) { + /* If nothing configured, accept it and check for buffer size */ + if (!oi->c_ifmtu) { + oi->ifmtu = ifp->mtu6; + iobuflen = ospf6_iobuf_size(ifp->mtu6); + if (oi->ifmtu > iobuflen) { + if (IS_OSPF6_DEBUG_INTERFACE) + zlog_debug( + "Interface %s: IfMtu is adjusted to I/O buffer size: %d.", + ifp->name, iobuflen); + oi->ifmtu = iobuflen; + } + } else if (oi->c_ifmtu > ifp->mtu6) { + oi->ifmtu = ifp->mtu6; + zlog_warn( + "Configured mtu %u on %s overridden by kernel %u", + oi->c_ifmtu, ifp->name, ifp->mtu6); + } else + oi->ifmtu = oi->c_ifmtu; + } + + if (if_is_operative(ifp) + && (ospf6_interface_get_linklocal_address(oi->interface) + || if_is_loopback(oi->interface))) + thread_add_event(master, interface_up, oi, 0, NULL); + else + thread_add_event(master, interface_down, oi, 0, NULL); + + return; } -void -ospf6_interface_connected_route_update (struct interface *ifp) +void ospf6_interface_connected_route_update(struct interface *ifp) { - struct ospf6_interface *oi; - struct ospf6_route *route; - struct connected *c; - struct listnode *node, *nnode; - struct in6_addr nh_addr; - - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - return; - - /* reset linklocal pointer */ - oi->linklocal_addr = ospf6_interface_get_linklocal_address (ifp); - - /* if area is null, do not make connected-route list */ - if (oi->area == NULL) - return; - - if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE)) - return; - - /* update "route to advertise" interface route table */ - ospf6_route_remove_all (oi->route_connected); - - for (ALL_LIST_ELEMENTS (oi->interface->connected, node, nnode, c)) - { - if (c->address->family != AF_INET6) - continue; - - CONTINUE_IF_ADDRESS_LINKLOCAL (IS_OSPF6_DEBUG_INTERFACE, c->address); - CONTINUE_IF_ADDRESS_UNSPECIFIED (IS_OSPF6_DEBUG_INTERFACE, c->address); - CONTINUE_IF_ADDRESS_LOOPBACK (IS_OSPF6_DEBUG_INTERFACE, c->address); - CONTINUE_IF_ADDRESS_V4COMPAT (IS_OSPF6_DEBUG_INTERFACE, c->address); - CONTINUE_IF_ADDRESS_V4MAPPED (IS_OSPF6_DEBUG_INTERFACE, c->address); - - /* apply filter */ - if (oi->plist_name) - { - struct prefix_list *plist; - enum prefix_list_type ret; - char buf[PREFIX2STR_BUFFER]; - - prefix2str (c->address, buf, sizeof (buf)); - plist = prefix_list_lookup (AFI_IP6, oi->plist_name); - ret = prefix_list_apply (plist, (void *) c->address); - if (ret == PREFIX_DENY) - { - if (IS_OSPF6_DEBUG_INTERFACE) - zlog_debug ("%s on %s filtered by prefix-list %s ", - buf, oi->interface->name, oi->plist_name); - continue; - } - } - - route = ospf6_route_create (); - memcpy (&route->prefix, c->address, sizeof (struct prefix)); - apply_mask (&route->prefix); - route->type = OSPF6_DEST_TYPE_NETWORK; - route->path.area_id = oi->area->area_id; - route->path.type = OSPF6_PATH_TYPE_INTRA; - route->path.cost = oi->cost; - inet_pton (AF_INET6, "::1", &nh_addr); - ospf6_route_add_nexthop (route, oi->interface->ifindex, &nh_addr); - ospf6_route_add (route, oi->route_connected); - } - - /* create new Link-LSA */ - OSPF6_LINK_LSA_SCHEDULE (oi); - OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi); - OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area); + struct ospf6_interface *oi; + struct ospf6_route *route; + struct connected *c; + struct listnode *node, *nnode; + struct in6_addr nh_addr; + + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + return; + + /* reset linklocal pointer */ + oi->linklocal_addr = ospf6_interface_get_linklocal_address(ifp); + + /* if area is null, do not make connected-route list */ + if (oi->area == NULL) + return; + + if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) + return; + + /* update "route to advertise" interface route table */ + ospf6_route_remove_all(oi->route_connected); + + for (ALL_LIST_ELEMENTS(oi->interface->connected, node, nnode, c)) { + if (c->address->family != AF_INET6) + continue; + + CONTINUE_IF_ADDRESS_LINKLOCAL(IS_OSPF6_DEBUG_INTERFACE, + c->address); + CONTINUE_IF_ADDRESS_UNSPECIFIED(IS_OSPF6_DEBUG_INTERFACE, + c->address); + CONTINUE_IF_ADDRESS_LOOPBACK(IS_OSPF6_DEBUG_INTERFACE, + c->address); + CONTINUE_IF_ADDRESS_V4COMPAT(IS_OSPF6_DEBUG_INTERFACE, + c->address); + CONTINUE_IF_ADDRESS_V4MAPPED(IS_OSPF6_DEBUG_INTERFACE, + c->address); + + /* apply filter */ + if (oi->plist_name) { + struct prefix_list *plist; + enum prefix_list_type ret; + char buf[PREFIX2STR_BUFFER]; + + prefix2str(c->address, buf, sizeof(buf)); + plist = prefix_list_lookup(AFI_IP6, oi->plist_name); + ret = prefix_list_apply(plist, (void *)c->address); + if (ret == PREFIX_DENY) { + if (IS_OSPF6_DEBUG_INTERFACE) + zlog_debug( + "%s on %s filtered by prefix-list %s ", + buf, oi->interface->name, + oi->plist_name); + continue; + } + } + + route = ospf6_route_create(); + memcpy(&route->prefix, c->address, sizeof(struct prefix)); + apply_mask(&route->prefix); + route->type = OSPF6_DEST_TYPE_NETWORK; + route->path.area_id = oi->area->area_id; + route->path.type = OSPF6_PATH_TYPE_INTRA; + route->path.cost = oi->cost; + inet_pton(AF_INET6, "::1", &nh_addr); + ospf6_route_add_nexthop(route, oi->interface->ifindex, + &nh_addr); + ospf6_route_add(route, oi->route_connected); + } + + /* create new Link-LSA */ + OSPF6_LINK_LSA_SCHEDULE(oi); + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi); + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area); } -static void -ospf6_interface_state_change (u_char next_state, struct ospf6_interface *oi) +static void ospf6_interface_state_change(u_char next_state, + struct ospf6_interface *oi) { - u_char prev_state; - - prev_state = oi->state; - oi->state = next_state; - - if (prev_state == next_state) - return; - - /* log */ - if (IS_OSPF6_DEBUG_INTERFACE) - { - zlog_debug ("Interface state change %s: %s -> %s", oi->interface->name, - ospf6_interface_state_str[prev_state], - ospf6_interface_state_str[next_state]); - } - oi->state_change++; - - if ((prev_state == OSPF6_INTERFACE_DR || - prev_state == OSPF6_INTERFACE_BDR) && - (next_state != OSPF6_INTERFACE_DR && - next_state != OSPF6_INTERFACE_BDR)) - ospf6_sso (oi->interface->ifindex, &alldrouters6, IPV6_LEAVE_GROUP); - - if ((prev_state != OSPF6_INTERFACE_DR && - prev_state != OSPF6_INTERFACE_BDR) && - (next_state == OSPF6_INTERFACE_DR || - next_state == OSPF6_INTERFACE_BDR)) - ospf6_sso (oi->interface->ifindex, &alldrouters6, IPV6_JOIN_GROUP); - - OSPF6_ROUTER_LSA_SCHEDULE (oi->area); - if (next_state == OSPF6_INTERFACE_DOWN) - { - OSPF6_NETWORK_LSA_EXECUTE (oi); - OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT (oi); - OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area); - } - else if (prev_state == OSPF6_INTERFACE_DR || - next_state == OSPF6_INTERFACE_DR) - { - OSPF6_NETWORK_LSA_SCHEDULE (oi); - OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi); - OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area); - } - - hook_call(ospf6_interface_change, oi, next_state, prev_state); + u_char prev_state; + + prev_state = oi->state; + oi->state = next_state; + + if (prev_state == next_state) + return; + + /* log */ + if (IS_OSPF6_DEBUG_INTERFACE) { + zlog_debug("Interface state change %s: %s -> %s", + oi->interface->name, + ospf6_interface_state_str[prev_state], + ospf6_interface_state_str[next_state]); + } + oi->state_change++; + + if ((prev_state == OSPF6_INTERFACE_DR + || prev_state == OSPF6_INTERFACE_BDR) + && (next_state != OSPF6_INTERFACE_DR + && next_state != OSPF6_INTERFACE_BDR)) + ospf6_sso(oi->interface->ifindex, &alldrouters6, + IPV6_LEAVE_GROUP); + + if ((prev_state != OSPF6_INTERFACE_DR + && prev_state != OSPF6_INTERFACE_BDR) + && (next_state == OSPF6_INTERFACE_DR + || next_state == OSPF6_INTERFACE_BDR)) + ospf6_sso(oi->interface->ifindex, &alldrouters6, + IPV6_JOIN_GROUP); + + OSPF6_ROUTER_LSA_SCHEDULE(oi->area); + if (next_state == OSPF6_INTERFACE_DOWN) { + OSPF6_NETWORK_LSA_EXECUTE(oi); + OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi); + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area); + } else if (prev_state == OSPF6_INTERFACE_DR + || next_state == OSPF6_INTERFACE_DR) { + OSPF6_NETWORK_LSA_SCHEDULE(oi); + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi); + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area); + } + + hook_call(ospf6_interface_change, oi, next_state, prev_state); } /* DR Election, RFC2328 section 9.4 */ -#define IS_ELIGIBLE(n) \ - ((n)->state >= OSPF6_NEIGHBOR_TWOWAY && (n)->priority != 0) +#define IS_ELIGIBLE(n) \ + ((n)->state >= OSPF6_NEIGHBOR_TWOWAY && (n)->priority != 0) -static struct ospf6_neighbor * -better_bdrouter (struct ospf6_neighbor *a, struct ospf6_neighbor *b) +static struct ospf6_neighbor *better_bdrouter(struct ospf6_neighbor *a, + struct ospf6_neighbor *b) { - if ((a == NULL || ! IS_ELIGIBLE (a) || a->drouter == a->router_id) && - (b == NULL || ! IS_ELIGIBLE (b) || b->drouter == b->router_id)) - return NULL; - else if (a == NULL || ! IS_ELIGIBLE (a) || a->drouter == a->router_id) - return b; - else if (b == NULL || ! IS_ELIGIBLE (b) || b->drouter == b->router_id) - return a; - - if (a->bdrouter == a->router_id && b->bdrouter != b->router_id) - return a; - if (a->bdrouter != a->router_id && b->bdrouter == b->router_id) - return b; - - if (a->priority > b->priority) - return a; - if (a->priority < b->priority) - return b; - - if (ntohl (a->router_id) > ntohl (b->router_id)) - return a; - if (ntohl (a->router_id) < ntohl (b->router_id)) - return b; - - zlog_warn ("Router-ID duplicate ?"); - return a; + if ((a == NULL || !IS_ELIGIBLE(a) || a->drouter == a->router_id) + && (b == NULL || !IS_ELIGIBLE(b) || b->drouter == b->router_id)) + return NULL; + else if (a == NULL || !IS_ELIGIBLE(a) || a->drouter == a->router_id) + return b; + else if (b == NULL || !IS_ELIGIBLE(b) || b->drouter == b->router_id) + return a; + + if (a->bdrouter == a->router_id && b->bdrouter != b->router_id) + return a; + if (a->bdrouter != a->router_id && b->bdrouter == b->router_id) + return b; + + if (a->priority > b->priority) + return a; + if (a->priority < b->priority) + return b; + + if (ntohl(a->router_id) > ntohl(b->router_id)) + return a; + if (ntohl(a->router_id) < ntohl(b->router_id)) + return b; + + zlog_warn("Router-ID duplicate ?"); + return a; } -static struct ospf6_neighbor * -better_drouter (struct ospf6_neighbor *a, struct ospf6_neighbor *b) +static struct ospf6_neighbor *better_drouter(struct ospf6_neighbor *a, + struct ospf6_neighbor *b) { - if ((a == NULL || ! IS_ELIGIBLE (a) || a->drouter != a->router_id) && - (b == NULL || ! IS_ELIGIBLE (b) || b->drouter != b->router_id)) - return NULL; - else if (a == NULL || ! IS_ELIGIBLE (a) || a->drouter != a->router_id) - return b; - else if (b == NULL || ! IS_ELIGIBLE (b) || b->drouter != b->router_id) - return a; - - if (a->drouter == a->router_id && b->drouter != b->router_id) - return a; - if (a->drouter != a->router_id && b->drouter == b->router_id) - return b; - - if (a->priority > b->priority) - return a; - if (a->priority < b->priority) - return b; - - if (ntohl (a->router_id) > ntohl (b->router_id)) - return a; - if (ntohl (a->router_id) < ntohl (b->router_id)) - return b; - - zlog_warn ("Router-ID duplicate ?"); - return a; + if ((a == NULL || !IS_ELIGIBLE(a) || a->drouter != a->router_id) + && (b == NULL || !IS_ELIGIBLE(b) || b->drouter != b->router_id)) + return NULL; + else if (a == NULL || !IS_ELIGIBLE(a) || a->drouter != a->router_id) + return b; + else if (b == NULL || !IS_ELIGIBLE(b) || b->drouter != b->router_id) + return a; + + if (a->drouter == a->router_id && b->drouter != b->router_id) + return a; + if (a->drouter != a->router_id && b->drouter == b->router_id) + return b; + + if (a->priority > b->priority) + return a; + if (a->priority < b->priority) + return b; + + if (ntohl(a->router_id) > ntohl(b->router_id)) + return a; + if (ntohl(a->router_id) < ntohl(b->router_id)) + return b; + + zlog_warn("Router-ID duplicate ?"); + return a; } -static u_char -dr_election (struct ospf6_interface *oi) +static u_char dr_election(struct ospf6_interface *oi) { - struct listnode *node, *nnode; - struct ospf6_neighbor *on, *drouter, *bdrouter, myself; - struct ospf6_neighbor *best_drouter, *best_bdrouter; - u_char next_state = 0; - - drouter = bdrouter = NULL; - best_drouter = best_bdrouter = NULL; - - /* pseudo neighbor myself, including noting current DR/BDR (1) */ - memset (&myself, 0, sizeof (myself)); - inet_ntop (AF_INET, &oi->area->ospf6->router_id, myself.name, - sizeof (myself.name)); - myself.state = OSPF6_NEIGHBOR_TWOWAY; - myself.drouter = oi->drouter; - myself.bdrouter = oi->bdrouter; - myself.priority = oi->priority; - myself.router_id = oi->area->ospf6->router_id; - - /* Electing BDR (2) */ - for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) - bdrouter = better_bdrouter (bdrouter, on); - - best_bdrouter = bdrouter; - bdrouter = better_bdrouter (best_bdrouter, &myself); - - /* Electing DR (3) */ - for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) - drouter = better_drouter (drouter, on); - - best_drouter = drouter; - drouter = better_drouter (best_drouter, &myself); - if (drouter == NULL) - drouter = bdrouter; - - /* the router itself is newly/no longer DR/BDR (4) */ - if ((drouter == &myself && myself.drouter != myself.router_id) || - (drouter != &myself && myself.drouter == myself.router_id) || - (bdrouter == &myself && myself.bdrouter != myself.router_id) || - (bdrouter != &myself && myself.bdrouter == myself.router_id)) - { - myself.drouter = (drouter ? drouter->router_id : htonl (0)); - myself.bdrouter = (bdrouter ? bdrouter->router_id : htonl (0)); - - /* compatible to Electing BDR (2) */ - bdrouter = better_bdrouter (best_bdrouter, &myself); - - /* compatible to Electing DR (3) */ - drouter = better_drouter (best_drouter, &myself); - if (drouter == NULL) - drouter = bdrouter; - } - - /* Set interface state accordingly (5) */ - if (drouter && drouter == &myself) - next_state = OSPF6_INTERFACE_DR; - else if (bdrouter && bdrouter == &myself) - next_state = OSPF6_INTERFACE_BDR; - else - next_state = OSPF6_INTERFACE_DROTHER; - - /* If NBMA, schedule Start for each neighbor having priority of 0 (6) */ - /* XXX */ - - /* If DR or BDR change, invoke AdjOK? for each neighbor (7) */ - /* RFC 2328 section 12.4. Originating LSAs (3) will be handled - accordingly after AdjOK */ - if (oi->drouter != (drouter ? drouter->router_id : htonl (0)) || - oi->bdrouter != (bdrouter ? bdrouter->router_id : htonl (0))) - { - if (IS_OSPF6_DEBUG_INTERFACE) - zlog_debug ("DR Election on %s: DR: %s BDR: %s", oi->interface->name, - (drouter ? drouter->name : "0.0.0.0"), - (bdrouter ? bdrouter->name : "0.0.0.0")); - - for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, node, on)) - { - if (on->state < OSPF6_NEIGHBOR_TWOWAY) - continue; - /* Schedule AdjOK. */ - thread_add_event(master, adj_ok, on, 0, NULL); - } - } - - oi->drouter = (drouter ? drouter->router_id : htonl (0)); - oi->bdrouter = (bdrouter ? bdrouter->router_id : htonl (0)); - return next_state; + struct listnode *node, *nnode; + struct ospf6_neighbor *on, *drouter, *bdrouter, myself; + struct ospf6_neighbor *best_drouter, *best_bdrouter; + u_char next_state = 0; + + drouter = bdrouter = NULL; + best_drouter = best_bdrouter = NULL; + + /* pseudo neighbor myself, including noting current DR/BDR (1) */ + memset(&myself, 0, sizeof(myself)); + inet_ntop(AF_INET, &oi->area->ospf6->router_id, myself.name, + sizeof(myself.name)); + myself.state = OSPF6_NEIGHBOR_TWOWAY; + myself.drouter = oi->drouter; + myself.bdrouter = oi->bdrouter; + myself.priority = oi->priority; + myself.router_id = oi->area->ospf6->router_id; + + /* Electing BDR (2) */ + for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) + bdrouter = better_bdrouter(bdrouter, on); + + best_bdrouter = bdrouter; + bdrouter = better_bdrouter(best_bdrouter, &myself); + + /* Electing DR (3) */ + for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) + drouter = better_drouter(drouter, on); + + best_drouter = drouter; + drouter = better_drouter(best_drouter, &myself); + if (drouter == NULL) + drouter = bdrouter; + + /* the router itself is newly/no longer DR/BDR (4) */ + if ((drouter == &myself && myself.drouter != myself.router_id) + || (drouter != &myself && myself.drouter == myself.router_id) + || (bdrouter == &myself && myself.bdrouter != myself.router_id) + || (bdrouter != &myself && myself.bdrouter == myself.router_id)) { + myself.drouter = (drouter ? drouter->router_id : htonl(0)); + myself.bdrouter = (bdrouter ? bdrouter->router_id : htonl(0)); + + /* compatible to Electing BDR (2) */ + bdrouter = better_bdrouter(best_bdrouter, &myself); + + /* compatible to Electing DR (3) */ + drouter = better_drouter(best_drouter, &myself); + if (drouter == NULL) + drouter = bdrouter; + } + + /* Set interface state accordingly (5) */ + if (drouter && drouter == &myself) + next_state = OSPF6_INTERFACE_DR; + else if (bdrouter && bdrouter == &myself) + next_state = OSPF6_INTERFACE_BDR; + else + next_state = OSPF6_INTERFACE_DROTHER; + + /* If NBMA, schedule Start for each neighbor having priority of 0 (6) */ + /* XXX */ + + /* If DR or BDR change, invoke AdjOK? for each neighbor (7) */ + /* RFC 2328 section 12.4. Originating LSAs (3) will be handled + accordingly after AdjOK */ + if (oi->drouter != (drouter ? drouter->router_id : htonl(0)) + || oi->bdrouter != (bdrouter ? bdrouter->router_id : htonl(0))) { + if (IS_OSPF6_DEBUG_INTERFACE) + zlog_debug("DR Election on %s: DR: %s BDR: %s", + oi->interface->name, + (drouter ? drouter->name : "0.0.0.0"), + (bdrouter ? bdrouter->name : "0.0.0.0")); + + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, node, on)) { + if (on->state < OSPF6_NEIGHBOR_TWOWAY) + continue; + /* Schedule AdjOK. */ + thread_add_event(master, adj_ok, on, 0, NULL); + } + } + + oi->drouter = (drouter ? drouter->router_id : htonl(0)); + oi->bdrouter = (bdrouter ? bdrouter->router_id : htonl(0)); + return next_state; } /* Interface State Machine */ -int -interface_up (struct thread *thread) +int interface_up(struct thread *thread) { - struct ospf6_interface *oi; - - oi = (struct ospf6_interface *) THREAD_ARG (thread); - assert (oi && oi->interface); - - if (IS_OSPF6_DEBUG_INTERFACE) - zlog_debug ("Interface Event %s: [InterfaceUp]", - oi->interface->name); - - /* check physical interface is up */ - if (! if_is_operative (oi->interface)) - { - if (IS_OSPF6_DEBUG_INTERFACE) - zlog_debug ("Interface %s is down, can't execute [InterfaceUp]", - oi->interface->name); - return 0; - } - - /* check interface has a link-local address */ - if (! (ospf6_interface_get_linklocal_address(oi->interface) - || if_is_loopback(oi->interface))) - { - if (IS_OSPF6_DEBUG_INTERFACE) - zlog_debug ("Interface %s has no link local address, can't execute [InterfaceUp]", - oi->interface->name); - return 0; - } - - /* Recompute cost */ - ospf6_interface_recalculate_cost (oi); - - /* if already enabled, do nothing */ - if (oi->state > OSPF6_INTERFACE_DOWN) - { - if (IS_OSPF6_DEBUG_INTERFACE) - zlog_debug ("Interface %s already enabled", - oi->interface->name); - return 0; - } - - /* If no area assigned, return */ - if (oi->area == NULL) - { - zlog_debug ("%s: Not scheduleing Hello for %s as there is no area assigned yet", __func__, - oi->interface->name); - return 0; - } - - /* Join AllSPFRouters */ - if (ospf6_sso (oi->interface->ifindex, &allspfrouters6, IPV6_JOIN_GROUP) < 0) - { - if (oi->sso_try_cnt++ < OSPF6_INTERFACE_SSO_RETRY_MAX) - { - zlog_info("Scheduling %s for sso retry, trial count: %d", - oi->interface->name, oi->sso_try_cnt); - thread_add_timer(master, interface_up, oi, - OSPF6_INTERFACE_SSO_RETRY_INT, NULL); - } - return 0; - } - oi->sso_try_cnt = 0; /* Reset on success */ - - /* Update interface route */ - ospf6_interface_connected_route_update (oi->interface); - - /* Schedule Hello */ - if (! CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE) && - !if_is_loopback (oi->interface)) { - oi->thread_send_hello = NULL; - thread_add_event(master, ospf6_hello_send, oi, 0, &oi->thread_send_hello); - } - - /* decide next interface state */ - if ((if_is_pointopoint (oi->interface)) || - (oi->type == OSPF_IFTYPE_POINTOPOINT)) { - ospf6_interface_state_change (OSPF6_INTERFACE_POINTTOPOINT, oi); - } - else if (oi->priority == 0) - ospf6_interface_state_change (OSPF6_INTERFACE_DROTHER, oi); - else - { - ospf6_interface_state_change (OSPF6_INTERFACE_WAITING, oi); - thread_add_timer(master, wait_timer, oi, oi->dead_interval, NULL); - } - - return 0; + struct ospf6_interface *oi; + + oi = (struct ospf6_interface *)THREAD_ARG(thread); + assert(oi && oi->interface); + + if (IS_OSPF6_DEBUG_INTERFACE) + zlog_debug("Interface Event %s: [InterfaceUp]", + oi->interface->name); + + /* check physical interface is up */ + if (!if_is_operative(oi->interface)) { + if (IS_OSPF6_DEBUG_INTERFACE) + zlog_debug( + "Interface %s is down, can't execute [InterfaceUp]", + oi->interface->name); + return 0; + } + + /* check interface has a link-local address */ + if (!(ospf6_interface_get_linklocal_address(oi->interface) + || if_is_loopback(oi->interface))) { + if (IS_OSPF6_DEBUG_INTERFACE) + zlog_debug( + "Interface %s has no link local address, can't execute [InterfaceUp]", + oi->interface->name); + return 0; + } + + /* Recompute cost */ + ospf6_interface_recalculate_cost(oi); + + /* if already enabled, do nothing */ + if (oi->state > OSPF6_INTERFACE_DOWN) { + if (IS_OSPF6_DEBUG_INTERFACE) + zlog_debug("Interface %s already enabled", + oi->interface->name); + return 0; + } + + /* If no area assigned, return */ + if (oi->area == NULL) { + zlog_debug( + "%s: Not scheduleing Hello for %s as there is no area assigned yet", + __func__, oi->interface->name); + return 0; + } + + /* Join AllSPFRouters */ + if (ospf6_sso(oi->interface->ifindex, &allspfrouters6, IPV6_JOIN_GROUP) + < 0) { + if (oi->sso_try_cnt++ < OSPF6_INTERFACE_SSO_RETRY_MAX) { + zlog_info( + "Scheduling %s for sso retry, trial count: %d", + oi->interface->name, oi->sso_try_cnt); + thread_add_timer(master, interface_up, oi, + OSPF6_INTERFACE_SSO_RETRY_INT, NULL); + } + return 0; + } + oi->sso_try_cnt = 0; /* Reset on success */ + + /* Update interface route */ + ospf6_interface_connected_route_update(oi->interface); + + /* Schedule Hello */ + if (!CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE) + && !if_is_loopback(oi->interface)) { + oi->thread_send_hello = NULL; + thread_add_event(master, ospf6_hello_send, oi, 0, + &oi->thread_send_hello); + } + + /* decide next interface state */ + if ((if_is_pointopoint(oi->interface)) + || (oi->type == OSPF_IFTYPE_POINTOPOINT)) { + ospf6_interface_state_change(OSPF6_INTERFACE_POINTTOPOINT, oi); + } else if (oi->priority == 0) + ospf6_interface_state_change(OSPF6_INTERFACE_DROTHER, oi); + else { + ospf6_interface_state_change(OSPF6_INTERFACE_WAITING, oi); + thread_add_timer(master, wait_timer, oi, oi->dead_interval, + NULL); + } + + return 0; } -int -wait_timer (struct thread *thread) +int wait_timer(struct thread *thread) { - struct ospf6_interface *oi; + struct ospf6_interface *oi; - oi = (struct ospf6_interface *) THREAD_ARG (thread); - assert (oi && oi->interface); + oi = (struct ospf6_interface *)THREAD_ARG(thread); + assert(oi && oi->interface); - if (IS_OSPF6_DEBUG_INTERFACE) - zlog_debug ("Interface Event %s: [WaitTimer]", - oi->interface->name); + if (IS_OSPF6_DEBUG_INTERFACE) + zlog_debug("Interface Event %s: [WaitTimer]", + oi->interface->name); - if (oi->state == OSPF6_INTERFACE_WAITING) - ospf6_interface_state_change (dr_election (oi), oi); + if (oi->state == OSPF6_INTERFACE_WAITING) + ospf6_interface_state_change(dr_election(oi), oi); - return 0; + return 0; } -int -backup_seen (struct thread *thread) +int backup_seen(struct thread *thread) { - struct ospf6_interface *oi; + struct ospf6_interface *oi; - oi = (struct ospf6_interface *) THREAD_ARG (thread); - assert (oi && oi->interface); + oi = (struct ospf6_interface *)THREAD_ARG(thread); + assert(oi && oi->interface); - if (IS_OSPF6_DEBUG_INTERFACE) - zlog_debug ("Interface Event %s: [BackupSeen]", - oi->interface->name); + if (IS_OSPF6_DEBUG_INTERFACE) + zlog_debug("Interface Event %s: [BackupSeen]", + oi->interface->name); - if (oi->state == OSPF6_INTERFACE_WAITING) - ospf6_interface_state_change (dr_election (oi), oi); + if (oi->state == OSPF6_INTERFACE_WAITING) + ospf6_interface_state_change(dr_election(oi), oi); - return 0; + return 0; } -int -neighbor_change (struct thread *thread) +int neighbor_change(struct thread *thread) { - struct ospf6_interface *oi; + struct ospf6_interface *oi; - oi = (struct ospf6_interface *) THREAD_ARG (thread); - assert (oi && oi->interface); + oi = (struct ospf6_interface *)THREAD_ARG(thread); + assert(oi && oi->interface); - if (IS_OSPF6_DEBUG_INTERFACE) - zlog_debug ("Interface Event %s: [NeighborChange]", - oi->interface->name); + if (IS_OSPF6_DEBUG_INTERFACE) + zlog_debug("Interface Event %s: [NeighborChange]", + oi->interface->name); - if (oi->state == OSPF6_INTERFACE_DROTHER || - oi->state == OSPF6_INTERFACE_BDR || - oi->state == OSPF6_INTERFACE_DR) - ospf6_interface_state_change (dr_election (oi), oi); + if (oi->state == OSPF6_INTERFACE_DROTHER + || oi->state == OSPF6_INTERFACE_BDR + || oi->state == OSPF6_INTERFACE_DR) + ospf6_interface_state_change(dr_election(oi), oi); - return 0; + return 0; } -int -interface_down (struct thread *thread) +int interface_down(struct thread *thread) { - struct ospf6_interface *oi; - struct listnode *node, *nnode; - struct ospf6_neighbor *on; + struct ospf6_interface *oi; + struct listnode *node, *nnode; + struct ospf6_neighbor *on; - oi = (struct ospf6_interface *) THREAD_ARG (thread); - assert (oi && oi->interface); + oi = (struct ospf6_interface *)THREAD_ARG(thread); + assert(oi && oi->interface); - if (IS_OSPF6_DEBUG_INTERFACE) - zlog_debug ("Interface Event %s: [InterfaceDown]", - oi->interface->name); + if (IS_OSPF6_DEBUG_INTERFACE) + zlog_debug("Interface Event %s: [InterfaceDown]", + oi->interface->name); - /* Stop Hellos */ - THREAD_OFF (oi->thread_send_hello); + /* Stop Hellos */ + THREAD_OFF(oi->thread_send_hello); - /* Leave AllSPFRouters */ - if (oi->state > OSPF6_INTERFACE_DOWN) - ospf6_sso (oi->interface->ifindex, &allspfrouters6, IPV6_LEAVE_GROUP); + /* Leave AllSPFRouters */ + if (oi->state > OSPF6_INTERFACE_DOWN) + ospf6_sso(oi->interface->ifindex, &allspfrouters6, + IPV6_LEAVE_GROUP); - ospf6_interface_state_change (OSPF6_INTERFACE_DOWN, oi); + ospf6_interface_state_change(OSPF6_INTERFACE_DOWN, oi); - for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) - ospf6_neighbor_delete (on); - - list_delete_all_node (oi->neighbor_list); + for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) + ospf6_neighbor_delete(on); - /* When interface state is reset, also reset information about - * DR election, as it is no longer valid. */ - oi->drouter = oi->prev_drouter = htonl(0); - oi->bdrouter = oi->prev_bdrouter = htonl(0); - return 0; + list_delete_all_node(oi->neighbor_list); + + /* When interface state is reset, also reset information about + * DR election, as it is no longer valid. */ + oi->drouter = oi->prev_drouter = htonl(0); + oi->bdrouter = oi->prev_bdrouter = htonl(0); + return 0; } /* show specified interface structure */ -static int -ospf6_interface_show (struct vty *vty, struct interface *ifp) +static int ospf6_interface_show(struct vty *vty, struct interface *ifp) { - struct ospf6_interface *oi; - struct connected *c; - struct prefix *p; - struct listnode *i; - char strbuf[PREFIX2STR_BUFFER], drouter[32], bdrouter[32]; - const char *updown[3] = {"down", "up", NULL}; - const char *type; - struct timeval res, now; - char duration[32]; - struct ospf6_lsa *lsa; - - /* check physical interface type */ - if (if_is_loopback (ifp)) - type = "LOOPBACK"; - else if (if_is_broadcast (ifp)) - type = "BROADCAST"; - else if (if_is_pointopoint (ifp)) - type = "POINTOPOINT"; - else - type = "UNKNOWN"; - - vty_out (vty, "%s is %s, type %s\n", - ifp->name, updown[if_is_operative (ifp)], type); - vty_out (vty, " Interface ID: %d\n", ifp->ifindex); - - if (ifp->info == NULL) - { - vty_out (vty, " OSPF not enabled on this interface\n"); - return 0; - } - else - oi = (struct ospf6_interface *) ifp->info; - - vty_out (vty, " Internet Address:\n"); - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, i, c)) - { - p = c->address; - prefix2str (p, strbuf, sizeof (strbuf)); - switch (p->family) - { - case AF_INET: - vty_out (vty, " inet : %s\n", strbuf); - break; - case AF_INET6: - vty_out (vty, " inet6: %s\n", strbuf); - break; - default: - vty_out (vty, " ??? : %s\n", strbuf); - break; - } - } - - if (oi->area) - { - vty_out (vty, " Instance ID %d, Interface MTU %d (autodetect: %d)\n", - oi->instance_id, oi->ifmtu, ifp->mtu6); - vty_out (vty, " MTU mismatch detection: %s\n", oi->mtu_ignore ? - "disabled" : "enabled"); - inet_ntop (AF_INET, &oi->area->area_id, - strbuf, sizeof (strbuf)); - vty_out (vty, " Area ID %s, Cost %u\n", strbuf, oi->cost); - } - else - vty_out (vty, " Not Attached to Area\n"); - - vty_out (vty, " State %s, Transmit Delay %d sec, Priority %d\n", - ospf6_interface_state_str[oi->state], - oi->transdelay, oi->priority); - vty_out (vty, " Timer intervals configured:\n"); - vty_out (vty, " Hello %d, Dead %d, Retransmit %d\n", - oi->hello_interval, oi->dead_interval, oi->rxmt_interval); - - inet_ntop (AF_INET, &oi->drouter, drouter, sizeof (drouter)); - inet_ntop (AF_INET, &oi->bdrouter, bdrouter, sizeof (bdrouter)); - vty_out (vty, " DR: %s BDR: %s\n", drouter, bdrouter); - - vty_out (vty, " Number of I/F scoped LSAs is %u\n", - oi->lsdb->count); - - monotime(&now); - - timerclear (&res); - if (oi->thread_send_lsupdate) - timersub (&oi->thread_send_lsupdate->u.sands, &now, &res); - timerstring (&res, duration, sizeof (duration)); - vty_out (vty, " %d Pending LSAs for LSUpdate in Time %s [thread %s]\n", - oi->lsupdate_list->count, duration, - (oi->thread_send_lsupdate ? "on" : "off")); - for (ALL_LSDB(oi->lsupdate_list, lsa)) - vty_out (vty, " %s\n", lsa->name); - - timerclear (&res); - if (oi->thread_send_lsack) - timersub (&oi->thread_send_lsack->u.sands, &now, &res); - timerstring (&res, duration, sizeof (duration)); - vty_out (vty, " %d Pending LSAs for LSAck in Time %s [thread %s]\n", - oi->lsack_list->count, duration, - (oi->thread_send_lsack ? "on" : "off")); - for (ALL_LSDB(oi->lsack_list, lsa)) - vty_out (vty, " %s\n", lsa->name); - ospf6_bfd_show_info(vty, oi->bfd_info, 1); - return 0; + struct ospf6_interface *oi; + struct connected *c; + struct prefix *p; + struct listnode *i; + char strbuf[PREFIX2STR_BUFFER], drouter[32], bdrouter[32]; + const char *updown[3] = {"down", "up", NULL}; + const char *type; + struct timeval res, now; + char duration[32]; + struct ospf6_lsa *lsa; + + /* check physical interface type */ + if (if_is_loopback(ifp)) + type = "LOOPBACK"; + else if (if_is_broadcast(ifp)) + type = "BROADCAST"; + else if (if_is_pointopoint(ifp)) + type = "POINTOPOINT"; + else + type = "UNKNOWN"; + + vty_out(vty, "%s is %s, type %s\n", ifp->name, + updown[if_is_operative(ifp)], type); + vty_out(vty, " Interface ID: %d\n", ifp->ifindex); + + if (ifp->info == NULL) { + vty_out(vty, " OSPF not enabled on this interface\n"); + return 0; + } else + oi = (struct ospf6_interface *)ifp->info; + + vty_out(vty, " Internet Address:\n"); + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, i, c)) { + p = c->address; + prefix2str(p, strbuf, sizeof(strbuf)); + switch (p->family) { + case AF_INET: + vty_out(vty, " inet : %s\n", strbuf); + break; + case AF_INET6: + vty_out(vty, " inet6: %s\n", strbuf); + break; + default: + vty_out(vty, " ??? : %s\n", strbuf); + break; + } + } + + if (oi->area) { + vty_out(vty, + " Instance ID %d, Interface MTU %d (autodetect: %d)\n", + oi->instance_id, oi->ifmtu, ifp->mtu6); + vty_out(vty, " MTU mismatch detection: %s\n", + oi->mtu_ignore ? "disabled" : "enabled"); + inet_ntop(AF_INET, &oi->area->area_id, strbuf, sizeof(strbuf)); + vty_out(vty, " Area ID %s, Cost %u\n", strbuf, oi->cost); + } else + vty_out(vty, " Not Attached to Area\n"); + + vty_out(vty, " State %s, Transmit Delay %d sec, Priority %d\n", + ospf6_interface_state_str[oi->state], oi->transdelay, + oi->priority); + vty_out(vty, " Timer intervals configured:\n"); + vty_out(vty, " Hello %d, Dead %d, Retransmit %d\n", + oi->hello_interval, oi->dead_interval, oi->rxmt_interval); + + inet_ntop(AF_INET, &oi->drouter, drouter, sizeof(drouter)); + inet_ntop(AF_INET, &oi->bdrouter, bdrouter, sizeof(bdrouter)); + vty_out(vty, " DR: %s BDR: %s\n", drouter, bdrouter); + + vty_out(vty, " Number of I/F scoped LSAs is %u\n", oi->lsdb->count); + + monotime(&now); + + timerclear(&res); + if (oi->thread_send_lsupdate) + timersub(&oi->thread_send_lsupdate->u.sands, &now, &res); + timerstring(&res, duration, sizeof(duration)); + vty_out(vty, + " %d Pending LSAs for LSUpdate in Time %s [thread %s]\n", + oi->lsupdate_list->count, duration, + (oi->thread_send_lsupdate ? "on" : "off")); + for (ALL_LSDB(oi->lsupdate_list, lsa)) + vty_out(vty, " %s\n", lsa->name); + + timerclear(&res); + if (oi->thread_send_lsack) + timersub(&oi->thread_send_lsack->u.sands, &now, &res); + timerstring(&res, duration, sizeof(duration)); + vty_out(vty, " %d Pending LSAs for LSAck in Time %s [thread %s]\n", + oi->lsack_list->count, duration, + (oi->thread_send_lsack ? "on" : "off")); + for (ALL_LSDB(oi->lsack_list, lsa)) + vty_out(vty, " %s\n", lsa->name); + ospf6_bfd_show_info(vty, oi->bfd_info, 1); + return 0; } /* show interface */ @@ -1011,27 +974,24 @@ DEFUN (show_ipv6_ospf6_interface, INTERFACE_STR IFNAME_STR) { - int idx_ifname = 4; - struct interface *ifp; - struct listnode *i; - - if (argc == 5) - { - ifp = if_lookup_by_name (argv[idx_ifname]->arg, VRF_DEFAULT); - if (ifp == NULL) - { - vty_out (vty, "No such Interface: %s\n", argv[idx_ifname]->arg); - return CMD_WARNING; - } - ospf6_interface_show (vty, ifp); - } - else - { - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), i, ifp)) - ospf6_interface_show (vty, ifp); - } - - return CMD_SUCCESS; + int idx_ifname = 4; + struct interface *ifp; + struct listnode *i; + + if (argc == 5) { + ifp = if_lookup_by_name(argv[idx_ifname]->arg, VRF_DEFAULT); + if (ifp == NULL) { + vty_out(vty, "No such Interface: %s\n", + argv[idx_ifname]->arg); + return CMD_WARNING; + } + ospf6_interface_show(vty, ifp); + } else { + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), i, ifp)) + ospf6_interface_show(vty, ifp); + } + + return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_interface_ifname_prefix, @@ -1048,28 +1008,28 @@ DEFUN (show_ipv6_ospf6_interface_ifname_prefix, OSPF6_ROUTE_MATCH_STR "Display details of the prefixes\n") { - int idx_ifname = 4; - int idx_prefix = 6; - struct interface *ifp; - struct ospf6_interface *oi; - - ifp = if_lookup_by_name (argv[idx_ifname]->arg, VRF_DEFAULT); - if (ifp == NULL) - { - vty_out (vty, "No such Interface: %s\n", argv[idx_ifname]->arg); - return CMD_WARNING; - } - - oi = ifp->info; - if (oi == NULL) - { - vty_out (vty, "OSPFv3 is not enabled on %s\n", argv[idx_ifname]->arg); - return CMD_WARNING; - } - - ospf6_route_table_show (vty, idx_prefix, argc, argv, oi->route_connected); - - return CMD_SUCCESS; + int idx_ifname = 4; + int idx_prefix = 6; + struct interface *ifp; + struct ospf6_interface *oi; + + ifp = if_lookup_by_name(argv[idx_ifname]->arg, VRF_DEFAULT); + if (ifp == NULL) { + vty_out(vty, "No such Interface: %s\n", argv[idx_ifname]->arg); + return CMD_WARNING; + } + + oi = ifp->info; + if (oi == NULL) { + vty_out(vty, "OSPFv3 is not enabled on %s\n", + argv[idx_ifname]->arg); + return CMD_WARNING; + } + + ospf6_route_table_show(vty, idx_prefix, argc, argv, + oi->route_connected); + + return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_interface_prefix, @@ -1085,21 +1045,21 @@ DEFUN (show_ipv6_ospf6_interface_prefix, OSPF6_ROUTE_MATCH_STR "Display details of the prefixes\n") { - int idx_prefix = 5; - struct listnode *i; - struct ospf6_interface *oi; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), i, ifp)) - { - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - continue; - - ospf6_route_table_show (vty, idx_prefix, argc, argv, oi->route_connected); - } + int idx_prefix = 5; + struct listnode *i; + struct ospf6_interface *oi; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), i, ifp)) { + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + continue; + + ospf6_route_table_show(vty, idx_prefix, argc, argv, + oi->route_connected); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* interface variable set command */ @@ -1112,55 +1072,51 @@ DEFUN (ipv6_ospf6_ifmtu, "OSPFv3 Interface MTU\n" ) { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_number = 3; - struct ospf6_interface *oi; - unsigned int ifmtu, iobuflen; - struct listnode *node, *nnode; - struct ospf6_neighbor *on; - - assert (ifp); - - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - oi = ospf6_interface_create (ifp); - assert (oi); - - ifmtu = strtol (argv[idx_number]->arg, NULL, 10); - - if (oi->c_ifmtu == ifmtu) - return CMD_SUCCESS; - - if (ifp->mtu6 != 0 && ifp->mtu6 < ifmtu) - { - vty_out (vty, "%s's ospf6 ifmtu cannot go beyond physical mtu (%d)\n", - ifp->name, ifp->mtu6); - return CMD_WARNING_CONFIG_FAILED; - } - - if (oi->ifmtu < ifmtu) - { - iobuflen = ospf6_iobuf_size (ifmtu); - if (iobuflen < ifmtu) - { - vty_out (vty, "%s's ifmtu is adjusted to I/O buffer size (%d).\n", - ifp->name, iobuflen); - oi->ifmtu = oi->c_ifmtu = iobuflen; - } - else - oi->ifmtu = oi->c_ifmtu = ifmtu; - } - else - oi->ifmtu = oi->c_ifmtu = ifmtu; - - /* re-establish adjacencies */ - for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) - { - THREAD_OFF (on->inactivity_timer); - thread_add_event(master, inactivity_timer, on, 0, NULL); - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_number = 3; + struct ospf6_interface *oi; + unsigned int ifmtu, iobuflen; + struct listnode *node, *nnode; + struct ospf6_neighbor *on; + + assert(ifp); + + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + assert(oi); + + ifmtu = strtol(argv[idx_number]->arg, NULL, 10); + + if (oi->c_ifmtu == ifmtu) + return CMD_SUCCESS; + + if (ifp->mtu6 != 0 && ifp->mtu6 < ifmtu) { + vty_out(vty, + "%s's ospf6 ifmtu cannot go beyond physical mtu (%d)\n", + ifp->name, ifp->mtu6); + return CMD_WARNING_CONFIG_FAILED; + } + + if (oi->ifmtu < ifmtu) { + iobuflen = ospf6_iobuf_size(ifmtu); + if (iobuflen < ifmtu) { + vty_out(vty, + "%s's ifmtu is adjusted to I/O buffer size (%d).\n", + ifp->name, iobuflen); + oi->ifmtu = oi->c_ifmtu = iobuflen; + } else + oi->ifmtu = oi->c_ifmtu = ifmtu; + } else + oi->ifmtu = oi->c_ifmtu = ifmtu; + + /* re-establish adjacencies */ + for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) { + THREAD_OFF(on->inactivity_timer); + thread_add_event(master, inactivity_timer, on, 0, NULL); + } + + return CMD_SUCCESS; } DEFUN (no_ipv6_ospf6_ifmtu, @@ -1173,44 +1129,40 @@ DEFUN (no_ipv6_ospf6_ifmtu, "OSPFv3 Interface MTU\n" ) { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct ospf6_interface *oi; - unsigned int iobuflen; - struct listnode *node, *nnode; - struct ospf6_neighbor *on; - - assert (ifp); - - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - oi = ospf6_interface_create (ifp); - assert (oi); - - if (oi->ifmtu < ifp->mtu) - { - iobuflen = ospf6_iobuf_size (ifp->mtu); - if (iobuflen < ifp->mtu) - { - vty_out (vty, "%s's ifmtu is adjusted to I/O buffer size (%d).\n", - ifp->name, iobuflen); - oi->ifmtu = iobuflen; - } - else - oi->ifmtu = ifp->mtu; - } - else - oi->ifmtu = ifp->mtu; - - oi->c_ifmtu = 0; - - /* re-establish adjacencies */ - for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) - { - THREAD_OFF (on->inactivity_timer); - thread_add_event(master, inactivity_timer, on, 0, NULL); - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf6_interface *oi; + unsigned int iobuflen; + struct listnode *node, *nnode; + struct ospf6_neighbor *on; + + assert(ifp); + + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + assert(oi); + + if (oi->ifmtu < ifp->mtu) { + iobuflen = ospf6_iobuf_size(ifp->mtu); + if (iobuflen < ifp->mtu) { + vty_out(vty, + "%s's ifmtu is adjusted to I/O buffer size (%d).\n", + ifp->name, iobuflen); + oi->ifmtu = iobuflen; + } else + oi->ifmtu = ifp->mtu; + } else + oi->ifmtu = ifp->mtu; + + oi->c_ifmtu = 0; + + /* re-establish adjacencies */ + for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) { + THREAD_OFF(on->inactivity_timer); + thread_add_event(master, inactivity_timer, on, 0, NULL); + } + + return CMD_SUCCESS; } DEFUN (ipv6_ospf6_cost, @@ -1222,35 +1174,34 @@ DEFUN (ipv6_ospf6_cost, "Outgoing metric of this interface\n" ) { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_number = 3; - struct ospf6_interface *oi; - unsigned long int lcost; - - assert (ifp); - - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - oi = ospf6_interface_create (ifp); - assert (oi); - - lcost = strtol (argv[idx_number]->arg, NULL, 10); - - if (lcost > UINT32_MAX) - { - vty_out (vty, "Cost %ld is out of range\n", lcost); - return CMD_WARNING_CONFIG_FAILED; - } - - if (oi->cost == lcost) - return CMD_SUCCESS; - - oi->cost = lcost; - SET_FLAG (oi->flag, OSPF6_INTERFACE_NOAUTOCOST); - - ospf6_interface_recalculate_cost(oi); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_number = 3; + struct ospf6_interface *oi; + unsigned long int lcost; + + assert(ifp); + + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + assert(oi); + + lcost = strtol(argv[idx_number]->arg, NULL, 10); + + if (lcost > UINT32_MAX) { + vty_out(vty, "Cost %ld is out of range\n", lcost); + return CMD_WARNING_CONFIG_FAILED; + } + + if (oi->cost == lcost) + return CMD_SUCCESS; + + oi->cost = lcost; + SET_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST); + + ospf6_interface_recalculate_cost(oi); + + return CMD_SUCCESS; } DEFUN (no_ipv6_ospf6_cost, @@ -1262,20 +1213,20 @@ DEFUN (no_ipv6_ospf6_cost, "Calculate interface cost from bandwidth\n" ) { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct ospf6_interface *oi; - assert (ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf6_interface *oi; + assert(ifp); - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - oi = ospf6_interface_create (ifp); - assert (oi); + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + assert(oi); - UNSET_FLAG (oi->flag, OSPF6_INTERFACE_NOAUTOCOST); + UNSET_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST); - ospf6_interface_recalculate_cost(oi); + ospf6_interface_recalculate_cost(oi); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (auto_cost_reference_bandwidth, @@ -1285,30 +1236,29 @@ DEFUN (auto_cost_reference_bandwidth, "Use reference bandwidth method to assign OSPF cost\n" "The reference bandwidth in terms of Mbits per second\n") { - VTY_DECLVAR_CONTEXT(ospf6, o); - int idx_number = 2; - struct ospf6_area *oa; - struct ospf6_interface *oi; - struct listnode *i, *j; - u_int32_t refbw; - - refbw = strtol (argv[idx_number]->arg, NULL, 10); - if (refbw < 1 || refbw > 4294967) - { - vty_out (vty, "reference-bandwidth value is invalid\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* If reference bandwidth is changed. */ - if ((refbw) == o->ref_bandwidth) - return CMD_SUCCESS; - - o->ref_bandwidth = refbw; - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - ospf6_interface_recalculate_cost (oi); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(ospf6, o); + int idx_number = 2; + struct ospf6_area *oa; + struct ospf6_interface *oi; + struct listnode *i, *j; + u_int32_t refbw; + + refbw = strtol(argv[idx_number]->arg, NULL, 10); + if (refbw < 1 || refbw > 4294967) { + vty_out(vty, "reference-bandwidth value is invalid\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* If reference bandwidth is changed. */ + if ((refbw) == o->ref_bandwidth) + return CMD_SUCCESS; + + o->ref_bandwidth = refbw; + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) + ospf6_interface_recalculate_cost(oi); + + return CMD_SUCCESS; } DEFUN (no_auto_cost_reference_bandwidth, @@ -1319,20 +1269,20 @@ DEFUN (no_auto_cost_reference_bandwidth, "Use reference bandwidth method to assign OSPF cost\n" "The reference bandwidth in terms of Mbits per second\n") { - VTY_DECLVAR_CONTEXT(ospf6, o); - struct ospf6_area *oa; - struct ospf6_interface *oi; - struct listnode *i, *j; + VTY_DECLVAR_CONTEXT(ospf6, o); + struct ospf6_area *oa; + struct ospf6_interface *oi; + struct listnode *i, *j; - if (o->ref_bandwidth == OSPF6_REFERENCE_BANDWIDTH) - return CMD_SUCCESS; + if (o->ref_bandwidth == OSPF6_REFERENCE_BANDWIDTH) + return CMD_SUCCESS; - o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH; - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - ospf6_interface_recalculate_cost (oi); + o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH; + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) + ospf6_interface_recalculate_cost(oi); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1345,18 +1295,18 @@ DEFUN (ipv6_ospf6_hellointerval, SECONDS_STR ) { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_number = 3; - struct ospf6_interface *oi; - assert (ifp); - - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - oi = ospf6_interface_create (ifp); - assert (oi); - - oi->hello_interval = strtol (argv[idx_number]->arg, NULL, 10); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_number = 3; + struct ospf6_interface *oi; + assert(ifp); + + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + assert(oi); + + oi->hello_interval = strtol(argv[idx_number]->arg, NULL, 10); + return CMD_SUCCESS; } /* interface variable set command */ @@ -1369,18 +1319,18 @@ DEFUN (ipv6_ospf6_deadinterval, SECONDS_STR ) { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_number = 3; - struct ospf6_interface *oi; - assert (ifp); - - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - oi = ospf6_interface_create (ifp); - assert (oi); - - oi->dead_interval = strtol (argv[idx_number]->arg, NULL, 10); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_number = 3; + struct ospf6_interface *oi; + assert(ifp); + + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + assert(oi); + + oi->dead_interval = strtol(argv[idx_number]->arg, NULL, 10); + return CMD_SUCCESS; } /* interface variable set command */ @@ -1392,18 +1342,18 @@ DEFUN (ipv6_ospf6_transmitdelay, "Link state transmit delay\n" SECONDS_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_number = 3; - struct ospf6_interface *oi; - assert (ifp); - - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - oi = ospf6_interface_create (ifp); - assert (oi); - - oi->transdelay = strtol (argv[idx_number]->arg, NULL, 10); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_number = 3; + struct ospf6_interface *oi; + assert(ifp); + + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + assert(oi); + + oi->transdelay = strtol(argv[idx_number]->arg, NULL, 10); + return CMD_SUCCESS; } /* interface variable set command */ @@ -1416,18 +1366,18 @@ DEFUN (ipv6_ospf6_retransmitinterval, SECONDS_STR ) { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_number = 3; - struct ospf6_interface *oi; - assert (ifp); - - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - oi = ospf6_interface_create (ifp); - assert (oi); - - oi->rxmt_interval = strtol (argv[idx_number]->arg, NULL, 10); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_number = 3; + struct ospf6_interface *oi; + assert(ifp); + + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + assert(oi); + + oi->rxmt_interval = strtol(argv[idx_number]->arg, NULL, 10); + return CMD_SUCCESS; } /* interface variable set command */ @@ -1440,25 +1390,24 @@ DEFUN (ipv6_ospf6_priority, "Priority value\n" ) { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_number = 3; - struct ospf6_interface *oi; - assert (ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_number = 3; + struct ospf6_interface *oi; + assert(ifp); - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - oi = ospf6_interface_create (ifp); - assert (oi); + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + assert(oi); - oi->priority = strtol (argv[idx_number]->arg, NULL, 10); + oi->priority = strtol(argv[idx_number]->arg, NULL, 10); - if (oi->area && - (oi->state == OSPF6_INTERFACE_DROTHER || - oi->state == OSPF6_INTERFACE_BDR || - oi->state == OSPF6_INTERFACE_DR)) - ospf6_interface_state_change (dr_election (oi), oi); + if (oi->area && (oi->state == OSPF6_INTERFACE_DROTHER + || oi->state == OSPF6_INTERFACE_BDR + || oi->state == OSPF6_INTERFACE_DR)) + ospf6_interface_state_change(dr_election(oi), oi); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_ospf6_instance, @@ -1470,18 +1419,18 @@ DEFUN (ipv6_ospf6_instance, "Instance ID value\n" ) { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_number = 3; - struct ospf6_interface *oi; - assert (ifp); - - oi = (struct ospf6_interface *)ifp->info; - if (oi == NULL) - oi = ospf6_interface_create (ifp); - assert (oi); - - oi->instance_id = strtol (argv[idx_number]->arg, NULL, 10); - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_number = 3; + struct ospf6_interface *oi; + assert(ifp); + + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + assert(oi); + + oi->instance_id = strtol(argv[idx_number]->arg, NULL, 10); + return CMD_SUCCESS; } DEFUN (ipv6_ospf6_passive, @@ -1492,28 +1441,27 @@ DEFUN (ipv6_ospf6_passive, "Passive interface; no adjacency will be formed on this interface\n" ) { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct ospf6_interface *oi; - struct listnode *node, *nnode; - struct ospf6_neighbor *on; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf6_interface *oi; + struct listnode *node, *nnode; + struct ospf6_neighbor *on; - assert (ifp); + assert(ifp); - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - oi = ospf6_interface_create (ifp); - assert (oi); + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + assert(oi); - SET_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE); - THREAD_OFF (oi->thread_send_hello); + SET_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE); + THREAD_OFF(oi->thread_send_hello); - for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) - { - THREAD_OFF (on->inactivity_timer); - thread_add_event(master, inactivity_timer, on, 0, NULL); - } + for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) { + THREAD_OFF(on->inactivity_timer); + thread_add_event(master, inactivity_timer, on, 0, NULL); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ipv6_ospf6_passive, @@ -1525,21 +1473,22 @@ DEFUN (no_ipv6_ospf6_passive, "passive interface: No Adjacency will be formed on this I/F\n" ) { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct ospf6_interface *oi; - assert (ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf6_interface *oi; + assert(ifp); - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - oi = ospf6_interface_create (ifp); - assert (oi); + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + assert(oi); - UNSET_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE); - THREAD_OFF (oi->thread_send_hello); - oi->thread_send_hello = NULL; - thread_add_event(master, ospf6_hello_send, oi, 0, &oi->thread_send_hello); + UNSET_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE); + THREAD_OFF(oi->thread_send_hello); + oi->thread_send_hello = NULL; + thread_add_event(master, ospf6_hello_send, oi, 0, + &oi->thread_send_hello); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_ospf6_mtu_ignore, @@ -1550,18 +1499,18 @@ DEFUN (ipv6_ospf6_mtu_ignore, "Disable MTU mismatch detection on this interface\n" ) { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct ospf6_interface *oi; - assert (ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf6_interface *oi; + assert(ifp); - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - oi = ospf6_interface_create (ifp); - assert (oi); + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + assert(oi); - oi->mtu_ignore = 1; + oi->mtu_ignore = 1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ipv6_ospf6_mtu_ignore, @@ -1573,18 +1522,18 @@ DEFUN (no_ipv6_ospf6_mtu_ignore, "Disable MTU mismatch detection on this interface\n" ) { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct ospf6_interface *oi; - assert (ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf6_interface *oi; + assert(ifp); - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - oi = ospf6_interface_create (ifp); - assert (oi); + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + assert(oi); - oi->mtu_ignore = 0; + oi->mtu_ignore = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_ospf6_advertise_prefix_list, @@ -1597,34 +1546,32 @@ DEFUN (ipv6_ospf6_advertise_prefix_list, "Prefix list name\n" ) { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_word = 4; - struct ospf6_interface *oi; - assert (ifp); - - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - oi = ospf6_interface_create (ifp); - assert (oi); - - if (oi->plist_name) - XFREE (MTYPE_CFG_PLIST_NAME, oi->plist_name); - oi->plist_name = XSTRDUP (MTYPE_CFG_PLIST_NAME, argv[idx_word]->arg); - - ospf6_interface_connected_route_update (oi->interface); - - if (oi->area) - { - OSPF6_LINK_LSA_SCHEDULE (oi); - if (oi->state == OSPF6_INTERFACE_DR) - { - OSPF6_NETWORK_LSA_SCHEDULE (oi); - OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi); - } - OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area); - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_word = 4; + struct ospf6_interface *oi; + assert(ifp); + + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + assert(oi); + + if (oi->plist_name) + XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name); + oi->plist_name = XSTRDUP(MTYPE_CFG_PLIST_NAME, argv[idx_word]->arg); + + ospf6_interface_connected_route_update(oi->interface); + + if (oi->area) { + OSPF6_LINK_LSA_SCHEDULE(oi); + if (oi->state == OSPF6_INTERFACE_DR) { + OSPF6_NETWORK_LSA_SCHEDULE(oi); + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi); + } + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area); + } + + return CMD_SUCCESS; } DEFUN (no_ipv6_ospf6_advertise_prefix_list, @@ -1637,35 +1584,32 @@ DEFUN (no_ipv6_ospf6_advertise_prefix_list, "Filter prefix using prefix-list\n" ) { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct ospf6_interface *oi; - assert (ifp); - - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - oi = ospf6_interface_create (ifp); - assert (oi); - - if (oi->plist_name) - { - XFREE (MTYPE_CFG_PLIST_NAME, oi->plist_name); - oi->plist_name = NULL; - } - - ospf6_interface_connected_route_update (oi->interface); - - if (oi->area) - { - OSPF6_LINK_LSA_SCHEDULE (oi); - if (oi->state == OSPF6_INTERFACE_DR) - { - OSPF6_NETWORK_LSA_SCHEDULE (oi); - OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi); - } - OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area); - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf6_interface *oi; + assert(ifp); + + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + assert(oi); + + if (oi->plist_name) { + XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name); + oi->plist_name = NULL; + } + + ospf6_interface_connected_route_update(oi->interface); + + if (oi->area) { + OSPF6_LINK_LSA_SCHEDULE(oi); + if (oi->state == OSPF6_INTERFACE_DR) { + OSPF6_NETWORK_LSA_SCHEDULE(oi); + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi); + } + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area); + } + + return CMD_SUCCESS; } DEFUN (ipv6_ospf6_network, @@ -1678,37 +1622,34 @@ DEFUN (ipv6_ospf6_network, "Specify OSPF6 point-to-point network\n" ) { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_network = 3; - struct ospf6_interface *oi; - assert (ifp); - - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) { - oi = ospf6_interface_create (ifp); - } - assert (oi); - - if (strncmp (argv[idx_network]->arg, "b", 1) == 0) - { - if (oi->type == OSPF_IFTYPE_BROADCAST) - return CMD_SUCCESS; - - oi->type = OSPF_IFTYPE_BROADCAST; - } - else if (strncmp (argv[idx_network]->arg, "point-to-p", 10) == 0) - { - if (oi->type == OSPF_IFTYPE_POINTOPOINT) { - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_network = 3; + struct ospf6_interface *oi; + assert(ifp); + + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) { + oi = ospf6_interface_create(ifp); + } + assert(oi); + + if (strncmp(argv[idx_network]->arg, "b", 1) == 0) { + if (oi->type == OSPF_IFTYPE_BROADCAST) + return CMD_SUCCESS; + + oi->type = OSPF_IFTYPE_BROADCAST; + } else if (strncmp(argv[idx_network]->arg, "point-to-p", 10) == 0) { + if (oi->type == OSPF_IFTYPE_POINTOPOINT) { + return CMD_SUCCESS; + } + oi->type = OSPF_IFTYPE_POINTOPOINT; } - oi->type = OSPF_IFTYPE_POINTOPOINT; - } - /* Reset the interface */ - thread_add_event(master, interface_down, oi, 0, NULL); - thread_add_event(master, interface_up, oi, 0, NULL); + /* Reset the interface */ + thread_add_event(master, interface_down, oi, 0, NULL); + thread_add_event(master, interface_up, oi, 0, NULL); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ipv6_ospf6_network, @@ -1719,171 +1660,162 @@ DEFUN (no_ipv6_ospf6_network, OSPF6_STR "Set default network type\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct ospf6_interface *oi; - int type; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf6_interface *oi; + int type; - assert (ifp); + assert(ifp); - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) { - return CMD_SUCCESS; - } + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) { + return CMD_SUCCESS; + } - type = ospf6_default_iftype (ifp); - if (oi->type == type) - { - return CMD_SUCCESS; - } - oi->type = type; + type = ospf6_default_iftype(ifp); + if (oi->type == type) { + return CMD_SUCCESS; + } + oi->type = type; - /* Reset the interface */ - thread_add_event(master, interface_down, oi, 0, NULL); - thread_add_event(master, interface_up, oi, 0, NULL); + /* Reset the interface */ + thread_add_event(master, interface_down, oi, 0, NULL); + thread_add_event(master, interface_up, oi, 0, NULL); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -config_write_ospf6_interface (struct vty *vty) +static int config_write_ospf6_interface(struct vty *vty) { - struct listnode *i; - struct ospf6_interface *oi; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), i, ifp)) - { - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - continue; - - vty_out (vty, "interface %s\n", - oi->interface->name); - - if (ifp->desc) - vty_out (vty, " description %s\n", ifp->desc); - if (oi->c_ifmtu) - vty_out (vty, " ipv6 ospf6 ifmtu %d\n", oi->c_ifmtu); - - if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_NOAUTOCOST)) - vty_out (vty, " ipv6 ospf6 cost %d\n", - oi->cost); - - if (oi->hello_interval != OSPF6_INTERFACE_HELLO_INTERVAL) - vty_out (vty, " ipv6 ospf6 hello-interval %d\n", - oi->hello_interval); - - if (oi->dead_interval != OSPF6_INTERFACE_DEAD_INTERVAL) - vty_out (vty, " ipv6 ospf6 dead-interval %d\n", - oi->dead_interval); - - if (oi->rxmt_interval != OSPF6_INTERFACE_RXMT_INTERVAL) - vty_out (vty, " ipv6 ospf6 retransmit-interval %d\n", - oi->rxmt_interval); - - if (oi->priority != OSPF6_INTERFACE_PRIORITY) - vty_out (vty, " ipv6 ospf6 priority %d\n", - oi->priority); - - if (oi->transdelay != OSPF6_INTERFACE_TRANSDELAY) - vty_out (vty, " ipv6 ospf6 transmit-delay %d\n", - oi->transdelay); - - if (oi->instance_id != OSPF6_INTERFACE_INSTANCE_ID) - vty_out (vty, " ipv6 ospf6 instance-id %d\n", - oi->instance_id); - - if (oi->plist_name) - vty_out (vty, " ipv6 ospf6 advertise prefix-list %s\n", - oi->plist_name); - - if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE)) - vty_out (vty, " ipv6 ospf6 passive\n"); - - if (oi->mtu_ignore) - vty_out (vty, " ipv6 ospf6 mtu-ignore\n"); - - if (oi->type != ospf6_default_iftype(ifp)) - { - if (oi->type == OSPF_IFTYPE_POINTOPOINT) - vty_out (vty, " ipv6 ospf6 network point-to-point\n"); - else if (oi->type == OSPF_IFTYPE_BROADCAST) - vty_out (vty, " ipv6 ospf6 network broadcast\n"); - } - - ospf6_bfd_write_config(vty, oi); - - vty_out (vty, "!\n"); - } - return 0; + struct listnode *i; + struct ospf6_interface *oi; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), i, ifp)) { + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + continue; + + vty_out(vty, "interface %s\n", oi->interface->name); + + if (ifp->desc) + vty_out(vty, " description %s\n", ifp->desc); + if (oi->c_ifmtu) + vty_out(vty, " ipv6 ospf6 ifmtu %d\n", oi->c_ifmtu); + + if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST)) + vty_out(vty, " ipv6 ospf6 cost %d\n", oi->cost); + + if (oi->hello_interval != OSPF6_INTERFACE_HELLO_INTERVAL) + vty_out(vty, " ipv6 ospf6 hello-interval %d\n", + oi->hello_interval); + + if (oi->dead_interval != OSPF6_INTERFACE_DEAD_INTERVAL) + vty_out(vty, " ipv6 ospf6 dead-interval %d\n", + oi->dead_interval); + + if (oi->rxmt_interval != OSPF6_INTERFACE_RXMT_INTERVAL) + vty_out(vty, " ipv6 ospf6 retransmit-interval %d\n", + oi->rxmt_interval); + + if (oi->priority != OSPF6_INTERFACE_PRIORITY) + vty_out(vty, " ipv6 ospf6 priority %d\n", oi->priority); + + if (oi->transdelay != OSPF6_INTERFACE_TRANSDELAY) + vty_out(vty, " ipv6 ospf6 transmit-delay %d\n", + oi->transdelay); + + if (oi->instance_id != OSPF6_INTERFACE_INSTANCE_ID) + vty_out(vty, " ipv6 ospf6 instance-id %d\n", + oi->instance_id); + + if (oi->plist_name) + vty_out(vty, " ipv6 ospf6 advertise prefix-list %s\n", + oi->plist_name); + + if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE)) + vty_out(vty, " ipv6 ospf6 passive\n"); + + if (oi->mtu_ignore) + vty_out(vty, " ipv6 ospf6 mtu-ignore\n"); + + if (oi->type != ospf6_default_iftype(ifp)) { + if (oi->type == OSPF_IFTYPE_POINTOPOINT) + vty_out(vty, + " ipv6 ospf6 network point-to-point\n"); + else if (oi->type == OSPF_IFTYPE_BROADCAST) + vty_out(vty, " ipv6 ospf6 network broadcast\n"); + } + + ospf6_bfd_write_config(vty, oi); + + vty_out(vty, "!\n"); + } + return 0; } -static struct cmd_node interface_node = -{ - INTERFACE_NODE, - "%s(config-if)# ", - 1 /* VTYSH */ +static struct cmd_node interface_node = { + INTERFACE_NODE, "%s(config-if)# ", 1 /* VTYSH */ }; -void -ospf6_interface_init (void) +void ospf6_interface_init(void) { - /* Install interface node. */ - install_node (&interface_node, config_write_ospf6_interface); - if_cmd_init (); - - install_element (VIEW_NODE, &show_ipv6_ospf6_interface_prefix_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_interface_ifname_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_interface_ifname_prefix_cmd); - - install_element (INTERFACE_NODE, &ipv6_ospf6_cost_cmd); - install_element (INTERFACE_NODE, &no_ipv6_ospf6_cost_cmd); - install_element (INTERFACE_NODE, &ipv6_ospf6_ifmtu_cmd); - install_element (INTERFACE_NODE, &no_ipv6_ospf6_ifmtu_cmd); - install_element (INTERFACE_NODE, &ipv6_ospf6_deadinterval_cmd); - install_element (INTERFACE_NODE, &ipv6_ospf6_hellointerval_cmd); - install_element (INTERFACE_NODE, &ipv6_ospf6_priority_cmd); - install_element (INTERFACE_NODE, &ipv6_ospf6_retransmitinterval_cmd); - install_element (INTERFACE_NODE, &ipv6_ospf6_transmitdelay_cmd); - install_element (INTERFACE_NODE, &ipv6_ospf6_instance_cmd); - - install_element (INTERFACE_NODE, &ipv6_ospf6_passive_cmd); - install_element (INTERFACE_NODE, &no_ipv6_ospf6_passive_cmd); - - install_element (INTERFACE_NODE, &ipv6_ospf6_mtu_ignore_cmd); - install_element (INTERFACE_NODE, &no_ipv6_ospf6_mtu_ignore_cmd); - - install_element (INTERFACE_NODE, &ipv6_ospf6_advertise_prefix_list_cmd); - install_element (INTERFACE_NODE, &no_ipv6_ospf6_advertise_prefix_list_cmd); - - install_element (INTERFACE_NODE, &ipv6_ospf6_network_cmd); - install_element (INTERFACE_NODE, &no_ipv6_ospf6_network_cmd); - - /* reference bandwidth commands */ - install_element (OSPF6_NODE, &auto_cost_reference_bandwidth_cmd); - install_element (OSPF6_NODE, &no_auto_cost_reference_bandwidth_cmd); + /* Install interface node. */ + install_node(&interface_node, config_write_ospf6_interface); + if_cmd_init(); + + install_element(VIEW_NODE, &show_ipv6_ospf6_interface_prefix_cmd); + install_element(VIEW_NODE, &show_ipv6_ospf6_interface_ifname_cmd); + install_element(VIEW_NODE, + &show_ipv6_ospf6_interface_ifname_prefix_cmd); + + install_element(INTERFACE_NODE, &ipv6_ospf6_cost_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ospf6_cost_cmd); + install_element(INTERFACE_NODE, &ipv6_ospf6_ifmtu_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ospf6_ifmtu_cmd); + install_element(INTERFACE_NODE, &ipv6_ospf6_deadinterval_cmd); + install_element(INTERFACE_NODE, &ipv6_ospf6_hellointerval_cmd); + install_element(INTERFACE_NODE, &ipv6_ospf6_priority_cmd); + install_element(INTERFACE_NODE, &ipv6_ospf6_retransmitinterval_cmd); + install_element(INTERFACE_NODE, &ipv6_ospf6_transmitdelay_cmd); + install_element(INTERFACE_NODE, &ipv6_ospf6_instance_cmd); + + install_element(INTERFACE_NODE, &ipv6_ospf6_passive_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ospf6_passive_cmd); + + install_element(INTERFACE_NODE, &ipv6_ospf6_mtu_ignore_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ospf6_mtu_ignore_cmd); + + install_element(INTERFACE_NODE, &ipv6_ospf6_advertise_prefix_list_cmd); + install_element(INTERFACE_NODE, + &no_ipv6_ospf6_advertise_prefix_list_cmd); + + install_element(INTERFACE_NODE, &ipv6_ospf6_network_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ospf6_network_cmd); + + /* reference bandwidth commands */ + install_element(OSPF6_NODE, &auto_cost_reference_bandwidth_cmd); + install_element(OSPF6_NODE, &no_auto_cost_reference_bandwidth_cmd); } /* Clear the specified interface structure */ -static void -ospf6_interface_clear (struct vty *vty, struct interface *ifp) +static void ospf6_interface_clear(struct vty *vty, struct interface *ifp) { - struct ospf6_interface *oi; + struct ospf6_interface *oi; - if (!if_is_operative (ifp)) - return; + if (!if_is_operative(ifp)) + return; - if (ifp->info == NULL) - return; + if (ifp->info == NULL) + return; - oi = (struct ospf6_interface *) ifp->info; + oi = (struct ospf6_interface *)ifp->info; - if (IS_OSPF6_DEBUG_INTERFACE) - zlog_debug ("Interface %s: clear by reset", ifp->name); + if (IS_OSPF6_DEBUG_INTERFACE) + zlog_debug("Interface %s: clear by reset", ifp->name); - /* Reset the interface */ - thread_add_event(master, interface_down, oi, 0, NULL); - thread_add_event(master, interface_up, oi, 0, NULL); + /* Reset the interface */ + thread_add_event(master, interface_down, oi, 0, NULL); + thread_add_event(master, interface_up, oi, 0, NULL); } /* Clear interface */ @@ -1897,32 +1829,32 @@ DEFUN (clear_ipv6_ospf6_interface, IFNAME_STR ) { - int idx_ifname = 4; - struct interface *ifp; - struct listnode *node; - - if (argc == 4) /* Clear all the ospfv3 interfaces. */ - { - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - ospf6_interface_clear (vty, ifp); - } - else /* Interface name is specified. */ - { - if ((ifp = if_lookup_by_name (argv[idx_ifname]->arg, VRF_DEFAULT)) == NULL) - { - vty_out (vty, "No such Interface: %s\n", argv[idx_ifname]->arg); - return CMD_WARNING; - } - ospf6_interface_clear (vty, ifp); - } - - return CMD_SUCCESS; + int idx_ifname = 4; + struct interface *ifp; + struct listnode *node; + + if (argc == 4) /* Clear all the ospfv3 interfaces. */ + { + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) + ospf6_interface_clear(vty, ifp); + } else /* Interface name is specified. */ + { + if ((ifp = if_lookup_by_name(argv[idx_ifname]->arg, + VRF_DEFAULT)) + == NULL) { + vty_out(vty, "No such Interface: %s\n", + argv[idx_ifname]->arg); + return CMD_WARNING; + } + ospf6_interface_clear(vty, ifp); + } + + return CMD_SUCCESS; } -void -install_element_ospf6_clear_interface (void) +void install_element_ospf6_clear_interface(void) { - install_element (ENABLE_NODE, &clear_ipv6_ospf6_interface_cmd); + install_element(ENABLE_NODE, &clear_ipv6_ospf6_interface_cmd); } DEFUN (debug_ospf6_interface, @@ -1933,8 +1865,8 @@ DEFUN (debug_ospf6_interface, "Debug OSPFv3 Interface\n" ) { - OSPF6_DEBUG_INTERFACE_ON (); - return CMD_SUCCESS; + OSPF6_DEBUG_INTERFACE_ON(); + return CMD_SUCCESS; } DEFUN (no_debug_ospf6_interface, @@ -1946,25 +1878,21 @@ DEFUN (no_debug_ospf6_interface, "Debug OSPFv3 Interface\n" ) { - OSPF6_DEBUG_INTERFACE_OFF (); - return CMD_SUCCESS; + OSPF6_DEBUG_INTERFACE_OFF(); + return CMD_SUCCESS; } -int -config_write_ospf6_debug_interface (struct vty *vty) +int config_write_ospf6_debug_interface(struct vty *vty) { - if (IS_OSPF6_DEBUG_INTERFACE) - vty_out (vty, "debug ospf6 interface\n"); - return 0; + if (IS_OSPF6_DEBUG_INTERFACE) + vty_out(vty, "debug ospf6 interface\n"); + return 0; } -void -install_element_ospf6_debug_interface (void) +void install_element_ospf6_debug_interface(void) { - install_element (ENABLE_NODE, &debug_ospf6_interface_cmd); - install_element (ENABLE_NODE, &no_debug_ospf6_interface_cmd); - install_element (CONFIG_NODE, &debug_ospf6_interface_cmd); - install_element (CONFIG_NODE, &no_debug_ospf6_interface_cmd); + install_element(ENABLE_NODE, &debug_ospf6_interface_cmd); + install_element(ENABLE_NODE, &no_debug_ospf6_interface_cmd); + install_element(CONFIG_NODE, &debug_ospf6_interface_cmd); + install_element(CONFIG_NODE, &no_debug_ospf6_interface_cmd); } - - diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h index 327402d75..384413236 100644 --- a/ospf6d/ospf6_interface.h +++ b/ospf6d/ospf6_interface.h @@ -27,101 +27,97 @@ /* Debug option */ extern unsigned char conf_debug_ospf6_interface; -#define OSPF6_DEBUG_INTERFACE_ON() \ - (conf_debug_ospf6_interface = 1) -#define OSPF6_DEBUG_INTERFACE_OFF() \ - (conf_debug_ospf6_interface = 0) -#define IS_OSPF6_DEBUG_INTERFACE \ - (conf_debug_ospf6_interface) +#define OSPF6_DEBUG_INTERFACE_ON() (conf_debug_ospf6_interface = 1) +#define OSPF6_DEBUG_INTERFACE_OFF() (conf_debug_ospf6_interface = 0) +#define IS_OSPF6_DEBUG_INTERFACE (conf_debug_ospf6_interface) /* Interface structure */ -struct ospf6_interface -{ - /* IF info from zebra */ - struct interface *interface; +struct ospf6_interface { + /* IF info from zebra */ + struct interface *interface; - /* back pointer */ - struct ospf6_area *area; + /* back pointer */ + struct ospf6_area *area; - /* list of ospf6 neighbor */ - struct list *neighbor_list; + /* list of ospf6 neighbor */ + struct list *neighbor_list; - /* linklocal address of this I/F */ - struct in6_addr *linklocal_addr; + /* linklocal address of this I/F */ + struct in6_addr *linklocal_addr; - /* Interface ID; use interface->ifindex */ + /* Interface ID; use interface->ifindex */ - /* ospf6 instance id */ - u_char instance_id; + /* ospf6 instance id */ + u_char instance_id; - /* I/F transmission delay */ - u_int32_t transdelay; + /* I/F transmission delay */ + u_int32_t transdelay; - /* Network Type */ - u_char type; + /* Network Type */ + u_char type; - /* Router Priority */ - u_char priority; + /* Router Priority */ + u_char priority; - /* Time Interval */ - u_int16_t hello_interval; - u_int16_t dead_interval; - u_int32_t rxmt_interval; + /* Time Interval */ + u_int16_t hello_interval; + u_int16_t dead_interval; + u_int32_t rxmt_interval; - u_int32_t state_change; + u_int32_t state_change; - /* Cost */ - u_int32_t cost; + /* Cost */ + u_int32_t cost; - /* I/F MTU */ - u_int32_t ifmtu; + /* I/F MTU */ + u_int32_t ifmtu; - /* Configured MTU */ - u_int32_t c_ifmtu; + /* Configured MTU */ + u_int32_t c_ifmtu; - /* Interface State */ - u_char state; + /* Interface State */ + u_char state; - /* Interface socket setting trial counter, resets on success */ - u_char sso_try_cnt; + /* Interface socket setting trial counter, resets on success */ + u_char sso_try_cnt; - /* OSPF6 Interface flag */ - char flag; + /* OSPF6 Interface flag */ + char flag; - /* MTU mismatch check */ - u_char mtu_ignore; + /* MTU mismatch check */ + u_char mtu_ignore; - /* Decision of DR Election */ - u_int32_t drouter; - u_int32_t bdrouter; - u_int32_t prev_drouter; - u_int32_t prev_bdrouter; + /* Decision of DR Election */ + u_int32_t drouter; + u_int32_t bdrouter; + u_int32_t prev_drouter; + u_int32_t prev_bdrouter; - /* Linklocal LSA Database: includes Link-LSA */ - struct ospf6_lsdb *lsdb; - struct ospf6_lsdb *lsdb_self; + /* Linklocal LSA Database: includes Link-LSA */ + struct ospf6_lsdb *lsdb; + struct ospf6_lsdb *lsdb_self; - struct ospf6_lsdb *lsupdate_list; - struct ospf6_lsdb *lsack_list; + struct ospf6_lsdb *lsupdate_list; + struct ospf6_lsdb *lsack_list; - /* Ongoing Tasks */ - struct thread *thread_send_hello; - struct thread *thread_send_lsupdate; - struct thread *thread_send_lsack; + /* Ongoing Tasks */ + struct thread *thread_send_hello; + struct thread *thread_send_lsupdate; + struct thread *thread_send_lsack; - struct thread *thread_network_lsa; - struct thread *thread_link_lsa; - struct thread *thread_intra_prefix_lsa; + struct thread *thread_network_lsa; + struct thread *thread_link_lsa; + struct thread *thread_intra_prefix_lsa; - struct ospf6_route_table *route_connected; + struct ospf6_route_table *route_connected; - /* prefix-list name to filter connected prefix */ - char *plist_name; + /* prefix-list name to filter connected prefix */ + char *plist_name; - /* BFD information */ - void *bfd_info; + /* BFD information */ + void *bfd_info; - QOBJ_FIELDS + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(ospf6_interface) @@ -156,37 +152,36 @@ extern const char *ospf6_interface_state_str[]; #define OSPF6_INTERFACE_SSO_RETRY_INT 1 #define OSPF6_INTERFACE_SSO_RETRY_MAX 5 - /* Function Prototypes */ -extern struct ospf6_interface *ospf6_interface_lookup_by_ifindex (ifindex_t); -extern struct ospf6_interface *ospf6_interface_create (struct interface *); -extern void ospf6_interface_delete (struct ospf6_interface *); +extern struct ospf6_interface *ospf6_interface_lookup_by_ifindex(ifindex_t); +extern struct ospf6_interface *ospf6_interface_create(struct interface *); +extern void ospf6_interface_delete(struct ospf6_interface *); -extern void ospf6_interface_enable (struct ospf6_interface *); -extern void ospf6_interface_disable (struct ospf6_interface *); +extern void ospf6_interface_enable(struct ospf6_interface *); +extern void ospf6_interface_disable(struct ospf6_interface *); -extern void ospf6_interface_if_add (struct interface *); -extern void ospf6_interface_if_del (struct interface *); -extern void ospf6_interface_state_update (struct interface *); -extern void ospf6_interface_connected_route_update (struct interface *); +extern void ospf6_interface_if_add(struct interface *); +extern void ospf6_interface_if_del(struct interface *); +extern void ospf6_interface_state_update(struct interface *); +extern void ospf6_interface_connected_route_update(struct interface *); /* interface event */ -extern int interface_up (struct thread *); -extern int interface_down (struct thread *); -extern int wait_timer (struct thread *); -extern int backup_seen (struct thread *); -extern int neighbor_change (struct thread *); +extern int interface_up(struct thread *); +extern int interface_down(struct thread *); +extern int wait_timer(struct thread *); +extern int backup_seen(struct thread *); +extern int neighbor_change(struct thread *); -extern void ospf6_interface_init (void); +extern void ospf6_interface_init(void); -extern void install_element_ospf6_clear_interface (void); +extern void install_element_ospf6_clear_interface(void); -extern int config_write_ospf6_debug_interface (struct vty *vty); -extern void install_element_ospf6_debug_interface (void); +extern int config_write_ospf6_debug_interface(struct vty *vty); +extern void install_element_ospf6_debug_interface(void); DECLARE_HOOK(ospf6_interface_change, - (struct ospf6_interface *oi, int state, int old_state), - (oi, state, old_state)) + (struct ospf6_interface * oi, int state, int old_state), + (oi, state, old_state)) #endif /* OSPF6_INTERFACE_H */ diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index 0ab503d15..7c5c44fca 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -56,491 +56,481 @@ u_int32_t conf_debug_ospf6_brouter_specific_area_id; /* RFC2740 3.4.3.1 Router-LSA */ /******************************/ -static char * -ospf6_router_lsa_get_nbr_id (struct ospf6_lsa *lsa, char *buf, int buflen, - int pos) +static char *ospf6_router_lsa_get_nbr_id(struct ospf6_lsa *lsa, char *buf, + int buflen, int pos) { - struct ospf6_router_lsa *router_lsa; - struct ospf6_router_lsdesc *lsdesc; - char *start, *end; - char buf1[INET_ADDRSTRLEN], buf2[INET_ADDRSTRLEN]; - - if (lsa) - { - router_lsa = (struct ospf6_router_lsa *) - ((char *) lsa->header + sizeof (struct ospf6_lsa_header)); - start = (char *) router_lsa + sizeof (struct ospf6_router_lsa); - end = (char *) lsa->header + ntohs (lsa->header->length); - - lsdesc = (struct ospf6_router_lsdesc *) - (start + pos*(sizeof (struct ospf6_router_lsdesc))); - if ((char *)lsdesc < end) - { - if (buf && (buflen > INET_ADDRSTRLEN*2)) - { - inet_ntop (AF_INET, &lsdesc->neighbor_interface_id, - buf1, sizeof(buf1)); - inet_ntop (AF_INET, &lsdesc->neighbor_router_id, - buf2, sizeof(buf2)); - sprintf (buf, "%s/%s", buf2, buf1); - } + struct ospf6_router_lsa *router_lsa; + struct ospf6_router_lsdesc *lsdesc; + char *start, *end; + char buf1[INET_ADDRSTRLEN], buf2[INET_ADDRSTRLEN]; + + if (lsa) { + router_lsa = (struct ospf6_router_lsa + *)((char *)lsa->header + + sizeof(struct ospf6_lsa_header)); + start = (char *)router_lsa + sizeof(struct ospf6_router_lsa); + end = (char *)lsa->header + ntohs(lsa->header->length); + + lsdesc = (struct ospf6_router_lsdesc + *)(start + + pos * (sizeof(struct + ospf6_router_lsdesc))); + if ((char *)lsdesc < end) { + if (buf && (buflen > INET_ADDRSTRLEN * 2)) { + inet_ntop(AF_INET, + &lsdesc->neighbor_interface_id, buf1, + sizeof(buf1)); + inet_ntop(AF_INET, &lsdesc->neighbor_router_id, + buf2, sizeof(buf2)); + sprintf(buf, "%s/%s", buf2, buf1); + } + } else + return NULL; } - else - return NULL; - } - return buf; + return buf; } -static int -ospf6_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) +static int ospf6_router_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) { - char *start, *end, *current; - char buf[32], name[32], bits[16], options[32]; - struct ospf6_router_lsa *router_lsa; - struct ospf6_router_lsdesc *lsdesc; - - router_lsa = (struct ospf6_router_lsa *) - ((char *) lsa->header + sizeof (struct ospf6_lsa_header)); - - ospf6_capability_printbuf (router_lsa->bits, bits, sizeof (bits)); - ospf6_options_printbuf (router_lsa->options, options, sizeof (options)); - vty_out (vty, " Bits: %s Options: %s\n", bits, options); - - start = (char *) router_lsa + sizeof (struct ospf6_router_lsa); - end = (char *) lsa->header + ntohs (lsa->header->length); - for (current = start; current + sizeof (struct ospf6_router_lsdesc) <= end; - current += sizeof (struct ospf6_router_lsdesc)) - { - lsdesc = (struct ospf6_router_lsdesc *) current; - - if (lsdesc->type == OSPF6_ROUTER_LSDESC_POINTTOPOINT) - snprintf (name, sizeof (name), "Point-To-Point"); - else if (lsdesc->type == OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK) - snprintf (name, sizeof (name), "Transit-Network"); - else if (lsdesc->type == OSPF6_ROUTER_LSDESC_STUB_NETWORK) - snprintf (name, sizeof (name), "Stub-Network"); - else if (lsdesc->type == OSPF6_ROUTER_LSDESC_VIRTUAL_LINK) - snprintf (name, sizeof (name), "Virtual-Link"); - else - snprintf (name, sizeof (name), "Unknown (%#x)", lsdesc->type); - - vty_out (vty, " Type: %s Metric: %d\n", - name, ntohs (lsdesc->metric)); - vty_out (vty, " Interface ID: %s\n", - inet_ntop (AF_INET, &lsdesc->interface_id, - buf, sizeof (buf))); - vty_out (vty, " Neighbor Interface ID: %s\n", - inet_ntop (AF_INET, &lsdesc->neighbor_interface_id, - buf, sizeof (buf))); - vty_out (vty, " Neighbor Router ID: %s\n", - inet_ntop (AF_INET, &lsdesc->neighbor_router_id, - buf, sizeof (buf))); - } - return 0; + char *start, *end, *current; + char buf[32], name[32], bits[16], options[32]; + struct ospf6_router_lsa *router_lsa; + struct ospf6_router_lsdesc *lsdesc; + + router_lsa = + (struct ospf6_router_lsa *)((char *)lsa->header + + sizeof(struct ospf6_lsa_header)); + + ospf6_capability_printbuf(router_lsa->bits, bits, sizeof(bits)); + ospf6_options_printbuf(router_lsa->options, options, sizeof(options)); + vty_out(vty, " Bits: %s Options: %s\n", bits, options); + + start = (char *)router_lsa + sizeof(struct ospf6_router_lsa); + end = (char *)lsa->header + ntohs(lsa->header->length); + for (current = start; + current + sizeof(struct ospf6_router_lsdesc) <= end; + current += sizeof(struct ospf6_router_lsdesc)) { + lsdesc = (struct ospf6_router_lsdesc *)current; + + if (lsdesc->type == OSPF6_ROUTER_LSDESC_POINTTOPOINT) + snprintf(name, sizeof(name), "Point-To-Point"); + else if (lsdesc->type == OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK) + snprintf(name, sizeof(name), "Transit-Network"); + else if (lsdesc->type == OSPF6_ROUTER_LSDESC_STUB_NETWORK) + snprintf(name, sizeof(name), "Stub-Network"); + else if (lsdesc->type == OSPF6_ROUTER_LSDESC_VIRTUAL_LINK) + snprintf(name, sizeof(name), "Virtual-Link"); + else + snprintf(name, sizeof(name), "Unknown (%#x)", + lsdesc->type); + + vty_out(vty, " Type: %s Metric: %d\n", name, + ntohs(lsdesc->metric)); + vty_out(vty, " Interface ID: %s\n", + inet_ntop(AF_INET, &lsdesc->interface_id, buf, + sizeof(buf))); + vty_out(vty, " Neighbor Interface ID: %s\n", + inet_ntop(AF_INET, &lsdesc->neighbor_interface_id, buf, + sizeof(buf))); + vty_out(vty, " Neighbor Router ID: %s\n", + inet_ntop(AF_INET, &lsdesc->neighbor_router_id, buf, + sizeof(buf))); + } + return 0; } -static void -ospf6_router_lsa_options_set (struct ospf6_area *oa, - struct ospf6_router_lsa *router_lsa) +static void ospf6_router_lsa_options_set(struct ospf6_area *oa, + struct ospf6_router_lsa *router_lsa) { - OSPF6_OPT_CLEAR_ALL (router_lsa->options); - memcpy (router_lsa->options, oa->options, 3); - - if (ospf6_is_router_abr (ospf6)) - SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B); - else - UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B); - - if (!IS_AREA_STUB (oa) && ospf6_asbr_is_asbr (oa->ospf6)) - { - SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E); - } - else - { - UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E); - } - - UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_V); - UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_W); + OSPF6_OPT_CLEAR_ALL(router_lsa->options); + memcpy(router_lsa->options, oa->options, 3); + + if (ospf6_is_router_abr(ospf6)) + SET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_B); + else + UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_B); + + if (!IS_AREA_STUB(oa) && ospf6_asbr_is_asbr(oa->ospf6)) { + SET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_E); + } else { + UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_E); + } + + UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_V); + UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_W); } -int -ospf6_router_is_stub_router (struct ospf6_lsa *lsa) +int ospf6_router_is_stub_router(struct ospf6_lsa *lsa) { - struct ospf6_router_lsa *rtr_lsa; - - if (lsa != NULL && OSPF6_LSA_IS_TYPE (ROUTER, lsa)) - { - rtr_lsa = (struct ospf6_router_lsa *) - ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header)); - - if (!OSPF6_OPT_ISSET (rtr_lsa->options, OSPF6_OPT_R)) - { - return (OSPF6_IS_STUB_ROUTER); - } - else if (!OSPF6_OPT_ISSET (rtr_lsa->options, OSPF6_OPT_V6)) - { - return (OSPF6_IS_STUB_ROUTER_V6); + struct ospf6_router_lsa *rtr_lsa; + + if (lsa != NULL && OSPF6_LSA_IS_TYPE(ROUTER, lsa)) { + rtr_lsa = (struct ospf6_router_lsa + *)((caddr_t)lsa->header + + sizeof(struct ospf6_lsa_header)); + + if (!OSPF6_OPT_ISSET(rtr_lsa->options, OSPF6_OPT_R)) { + return (OSPF6_IS_STUB_ROUTER); + } else if (!OSPF6_OPT_ISSET(rtr_lsa->options, OSPF6_OPT_V6)) { + return (OSPF6_IS_STUB_ROUTER_V6); + } } - } - return (OSPF6_NOT_STUB_ROUTER); + return (OSPF6_NOT_STUB_ROUTER); } -int -ospf6_router_lsa_originate (struct thread *thread) +int ospf6_router_lsa_originate(struct thread *thread) { - struct ospf6_area *oa; - - char buffer [OSPF6_MAX_LSASIZE]; - struct ospf6_lsa_header *lsa_header; - struct ospf6_lsa *lsa; - - u_int32_t link_state_id = 0; - struct listnode *node, *nnode; - struct listnode *j; - struct ospf6_interface *oi; - struct ospf6_neighbor *on, *drouter = NULL; - struct ospf6_router_lsa *router_lsa; - struct ospf6_router_lsdesc *lsdesc; - u_int16_t type; - u_int32_t router; - int count; - - oa = (struct ospf6_area *) THREAD_ARG (thread); - oa->thread_router_lsa = NULL; - - if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER)) - zlog_debug ("Originate Router-LSA for Area %s", oa->name); - - memset (buffer, 0, sizeof (buffer)); - lsa_header = (struct ospf6_lsa_header *) buffer; - router_lsa = (struct ospf6_router_lsa *) - ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); - - ospf6_router_lsa_options_set (oa, router_lsa); - - /* describe links for each interfaces */ - lsdesc = (struct ospf6_router_lsdesc *) - ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa)); - - for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi)) - { - /* Interfaces in state Down or Loopback are not described */ - if (oi->state == OSPF6_INTERFACE_DOWN || - oi->state == OSPF6_INTERFACE_LOOPBACK) - continue; - - /* Nor are interfaces without any full adjacencies described */ - count = 0; - for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on)) - if (on->state == OSPF6_NEIGHBOR_FULL) - count++; - - if (count == 0) - continue; - - /* Multiple Router-LSA instance according to size limit setting */ - if ( (oa->router_lsa_size_limit != 0) - && ((size_t)((char *)lsdesc - buffer) - + sizeof (struct ospf6_router_lsdesc) - > oa->router_lsa_size_limit)) - { - if ((caddr_t) lsdesc == (caddr_t) router_lsa + - sizeof (struct ospf6_router_lsa)) - { - if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER)) - zlog_debug ("Size limit setting for Router-LSA too short"); - return 0; - } - - link_state_id ++; - } - - /* Point-to-Point interfaces */ - if (oi->type == OSPF_IFTYPE_POINTOPOINT) - { - for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on)) - { - if (on->state != OSPF6_NEIGHBOR_FULL) - continue; - - lsdesc->type = OSPF6_ROUTER_LSDESC_POINTTOPOINT; - lsdesc->metric = htons (oi->cost); - lsdesc->interface_id = htonl (oi->interface->ifindex); - lsdesc->neighbor_interface_id = htonl (on->ifindex); - lsdesc->neighbor_router_id = on->router_id; - - lsdesc++; - } - } - - /* Broadcast and NBMA interfaces */ - else if (oi->type == OSPF_IFTYPE_BROADCAST) - { - /* If this router is not DR, - and If this router not fully adjacent with DR, - this interface is not transit yet: ignore. */ - if (oi->state != OSPF6_INTERFACE_DR) - { - drouter = ospf6_neighbor_lookup (oi->drouter, oi); - if (drouter == NULL || drouter->state != OSPF6_NEIGHBOR_FULL) - continue; - } - - lsdesc->type = OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK; - lsdesc->metric = htons (oi->cost); - lsdesc->interface_id = htonl (oi->interface->ifindex); - if (oi->state != OSPF6_INTERFACE_DR) - { - lsdesc->neighbor_interface_id = htonl (drouter->ifindex); - lsdesc->neighbor_router_id = drouter->router_id; - } - else - { - lsdesc->neighbor_interface_id = htonl (oi->interface->ifindex); - lsdesc->neighbor_router_id = oi->area->ospf6->router_id; - } - - lsdesc++; - } - else - { - assert (0); /* Unknown interface type */ + struct ospf6_area *oa; + + char buffer[OSPF6_MAX_LSASIZE]; + struct ospf6_lsa_header *lsa_header; + struct ospf6_lsa *lsa; + + u_int32_t link_state_id = 0; + struct listnode *node, *nnode; + struct listnode *j; + struct ospf6_interface *oi; + struct ospf6_neighbor *on, *drouter = NULL; + struct ospf6_router_lsa *router_lsa; + struct ospf6_router_lsdesc *lsdesc; + u_int16_t type; + u_int32_t router; + int count; + + oa = (struct ospf6_area *)THREAD_ARG(thread); + oa->thread_router_lsa = NULL; + + if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER)) + zlog_debug("Originate Router-LSA for Area %s", oa->name); + + memset(buffer, 0, sizeof(buffer)); + lsa_header = (struct ospf6_lsa_header *)buffer; + router_lsa = + (struct ospf6_router_lsa *)((caddr_t)lsa_header + + sizeof(struct ospf6_lsa_header)); + + ospf6_router_lsa_options_set(oa, router_lsa); + + /* describe links for each interfaces */ + lsdesc = (struct ospf6_router_lsdesc + *)((caddr_t)router_lsa + + sizeof(struct ospf6_router_lsa)); + + for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) { + /* Interfaces in state Down or Loopback are not described */ + if (oi->state == OSPF6_INTERFACE_DOWN + || oi->state == OSPF6_INTERFACE_LOOPBACK) + continue; + + /* Nor are interfaces without any full adjacencies described */ + count = 0; + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, j, on)) + if (on->state == OSPF6_NEIGHBOR_FULL) + count++; + + if (count == 0) + continue; + + /* Multiple Router-LSA instance according to size limit setting + */ + if ((oa->router_lsa_size_limit != 0) + && ((size_t)((char *)lsdesc - buffer) + + sizeof(struct ospf6_router_lsdesc) + > oa->router_lsa_size_limit)) { + if ((caddr_t)lsdesc + == (caddr_t)router_lsa + + sizeof(struct ospf6_router_lsa)) { + if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER)) + zlog_debug( + "Size limit setting for Router-LSA too short"); + return 0; + } + + link_state_id++; + } + + /* Point-to-Point interfaces */ + if (oi->type == OSPF_IFTYPE_POINTOPOINT) { + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, j, on)) { + if (on->state != OSPF6_NEIGHBOR_FULL) + continue; + + lsdesc->type = OSPF6_ROUTER_LSDESC_POINTTOPOINT; + lsdesc->metric = htons(oi->cost); + lsdesc->interface_id = + htonl(oi->interface->ifindex); + lsdesc->neighbor_interface_id = + htonl(on->ifindex); + lsdesc->neighbor_router_id = on->router_id; + + lsdesc++; + } + } + + /* Broadcast and NBMA interfaces */ + else if (oi->type == OSPF_IFTYPE_BROADCAST) { + /* If this router is not DR, + and If this router not fully adjacent with DR, + this interface is not transit yet: ignore. */ + if (oi->state != OSPF6_INTERFACE_DR) { + drouter = + ospf6_neighbor_lookup(oi->drouter, oi); + if (drouter == NULL + || drouter->state != OSPF6_NEIGHBOR_FULL) + continue; + } + + lsdesc->type = OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK; + lsdesc->metric = htons(oi->cost); + lsdesc->interface_id = htonl(oi->interface->ifindex); + if (oi->state != OSPF6_INTERFACE_DR) { + lsdesc->neighbor_interface_id = + htonl(drouter->ifindex); + lsdesc->neighbor_router_id = drouter->router_id; + } else { + lsdesc->neighbor_interface_id = + htonl(oi->interface->ifindex); + lsdesc->neighbor_router_id = + oi->area->ospf6->router_id; + } + + lsdesc++; + } else { + assert(0); /* Unknown interface type */ + } + + /* Virtual links */ + /* xxx */ + /* Point-to-Multipoint interfaces */ + /* xxx */ + } + + /* Fill LSA Header */ + lsa_header->age = 0; + lsa_header->type = htons(OSPF6_LSTYPE_ROUTER); + lsa_header->id = htonl(link_state_id); + lsa_header->adv_router = oa->ospf6->router_id; + lsa_header->seqnum = + ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id, + lsa_header->adv_router, oa->lsdb); + lsa_header->length = htons((caddr_t)lsdesc - (caddr_t)buffer); + + /* LSA checksum */ + ospf6_lsa_checksum(lsa_header); + + /* create LSA */ + lsa = ospf6_lsa_create(lsa_header); + + /* Originate */ + ospf6_lsa_originate_area(lsa, oa); + + link_state_id++; + + /* Do premature-aging of rest, undesired Router-LSAs */ + type = ntohs(OSPF6_LSTYPE_ROUTER); + router = oa->ospf6->router_id; + count = 0; + for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router, lsa)) { + if (ntohl(lsa->header->id) < link_state_id) + continue; + ospf6_lsa_purge(lsa); + count++; } - /* Virtual links */ - /* xxx */ - /* Point-to-Multipoint interfaces */ - /* xxx */ - } - - /* Fill LSA Header */ - lsa_header->age = 0; - lsa_header->type = htons (OSPF6_LSTYPE_ROUTER); - lsa_header->id = htonl (link_state_id); - lsa_header->adv_router = oa->ospf6->router_id; - lsa_header->seqnum = - ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id, - lsa_header->adv_router, oa->lsdb); - lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer); - - /* LSA checksum */ - ospf6_lsa_checksum (lsa_header); - - /* create LSA */ - lsa = ospf6_lsa_create (lsa_header); - - /* Originate */ - ospf6_lsa_originate_area (lsa, oa); - - link_state_id ++; - - /* Do premature-aging of rest, undesired Router-LSAs */ - type = ntohs (OSPF6_LSTYPE_ROUTER); - router = oa->ospf6->router_id; - count = 0; - for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router, lsa)) - { - if (ntohl (lsa->header->id) < link_state_id) - continue; - ospf6_lsa_purge (lsa); - count++; - } - - /* - * Waiting till the LSA is actually removed from the database to trigger - * SPF delays network convergence. Unlike IPv4, for an ABR, when all - * interfaces associated with an area are gone, triggering an SPF right away - * helps convergence with inter-area routes. - */ - if (count && !link_state_id) - ospf6_spf_schedule (oa->ospf6, OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED); - - return 0; + /* + * Waiting till the LSA is actually removed from the database to trigger + * SPF delays network convergence. Unlike IPv4, for an ABR, when all + * interfaces associated with an area are gone, triggering an SPF right + * away + * helps convergence with inter-area routes. + */ + if (count && !link_state_id) + ospf6_spf_schedule(oa->ospf6, + OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED); + + return 0; } /*******************************/ /* RFC2740 3.4.3.2 Network-LSA */ /*******************************/ -static char * -ospf6_network_lsa_get_ar_id (struct ospf6_lsa *lsa, char *buf, int buflen, - int pos) +static char *ospf6_network_lsa_get_ar_id(struct ospf6_lsa *lsa, char *buf, + int buflen, int pos) { - char *start, *end, *current; - struct ospf6_network_lsa *network_lsa; - struct ospf6_network_lsdesc *lsdesc; - - if (lsa) - { - network_lsa = (struct ospf6_network_lsa *) - ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header)); - - start = (char *) network_lsa + sizeof (struct ospf6_network_lsa); - end = (char *) lsa->header + ntohs (lsa->header->length); - current = start + pos*(sizeof (struct ospf6_network_lsdesc)); - - if ((current + sizeof(struct ospf6_network_lsdesc)) <= end) - { - lsdesc = (struct ospf6_network_lsdesc *)current; - if (buf) - inet_ntop (AF_INET, &lsdesc->router_id, buf, buflen); + char *start, *end, *current; + struct ospf6_network_lsa *network_lsa; + struct ospf6_network_lsdesc *lsdesc; + + if (lsa) { + network_lsa = (struct ospf6_network_lsa + *)((caddr_t)lsa->header + + sizeof(struct ospf6_lsa_header)); + + start = (char *)network_lsa + sizeof(struct ospf6_network_lsa); + end = (char *)lsa->header + ntohs(lsa->header->length); + current = start + pos * (sizeof(struct ospf6_network_lsdesc)); + + if ((current + sizeof(struct ospf6_network_lsdesc)) <= end) { + lsdesc = (struct ospf6_network_lsdesc *)current; + if (buf) + inet_ntop(AF_INET, &lsdesc->router_id, buf, + buflen); + } else + return NULL; } - else - return NULL; - } - return (buf); + return (buf); } -static int -ospf6_network_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) +static int ospf6_network_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) { - char *start, *end, *current; - struct ospf6_network_lsa *network_lsa; - struct ospf6_network_lsdesc *lsdesc; - char buf[128], options[32]; - - network_lsa = (struct ospf6_network_lsa *) - ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header)); - - ospf6_options_printbuf (network_lsa->options, options, sizeof (options)); - vty_out (vty, " Options: %s\n", options); - - start = (char *) network_lsa + sizeof (struct ospf6_network_lsa); - end = (char *) lsa->header + ntohs (lsa->header->length); - for (current = start; current + sizeof (struct ospf6_network_lsdesc) <= end; - current += sizeof (struct ospf6_network_lsdesc)) - { - lsdesc = (struct ospf6_network_lsdesc *) current; - inet_ntop (AF_INET, &lsdesc->router_id, buf, sizeof (buf)); - vty_out (vty, " Attached Router: %s\n", buf); - } - return 0; + char *start, *end, *current; + struct ospf6_network_lsa *network_lsa; + struct ospf6_network_lsdesc *lsdesc; + char buf[128], options[32]; + + network_lsa = + (struct ospf6_network_lsa *)((caddr_t)lsa->header + + sizeof(struct ospf6_lsa_header)); + + ospf6_options_printbuf(network_lsa->options, options, sizeof(options)); + vty_out(vty, " Options: %s\n", options); + + start = (char *)network_lsa + sizeof(struct ospf6_network_lsa); + end = (char *)lsa->header + ntohs(lsa->header->length); + for (current = start; + current + sizeof(struct ospf6_network_lsdesc) <= end; + current += sizeof(struct ospf6_network_lsdesc)) { + lsdesc = (struct ospf6_network_lsdesc *)current; + inet_ntop(AF_INET, &lsdesc->router_id, buf, sizeof(buf)); + vty_out(vty, " Attached Router: %s\n", buf); + } + return 0; } -int -ospf6_network_lsa_originate (struct thread *thread) +int ospf6_network_lsa_originate(struct thread *thread) { - struct ospf6_interface *oi; - - char buffer [OSPF6_MAX_LSASIZE]; - struct ospf6_lsa_header *lsa_header; - - int count; - struct ospf6_lsa *old, *lsa; - struct ospf6_network_lsa *network_lsa; - struct ospf6_network_lsdesc *lsdesc; - struct ospf6_neighbor *on; - struct ospf6_link_lsa *link_lsa; - struct listnode *i; - u_int16_t type; - - oi = (struct ospf6_interface *) THREAD_ARG (thread); - oi->thread_network_lsa = NULL; - - /* The interface must be enabled until here. A Network-LSA of a - disabled interface (but was once enabled) should be flushed - by ospf6_lsa_refresh (), and does not come here. */ - assert (oi->area); - - old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_NETWORK), - htonl (oi->interface->ifindex), - oi->area->ospf6->router_id, oi->area->lsdb); - - /* Do not originate Network-LSA if not DR */ - if (oi->state != OSPF6_INTERFACE_DR) - { - if (old) - { - ospf6_lsa_purge (old); - /* - * Waiting till the LSA is actually removed from the database to - * trigger SPF delays network convergence. - */ - ospf6_spf_schedule (oi->area->ospf6, - OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED); + struct ospf6_interface *oi; + + char buffer[OSPF6_MAX_LSASIZE]; + struct ospf6_lsa_header *lsa_header; + + int count; + struct ospf6_lsa *old, *lsa; + struct ospf6_network_lsa *network_lsa; + struct ospf6_network_lsdesc *lsdesc; + struct ospf6_neighbor *on; + struct ospf6_link_lsa *link_lsa; + struct listnode *i; + u_int16_t type; + + oi = (struct ospf6_interface *)THREAD_ARG(thread); + oi->thread_network_lsa = NULL; + + /* The interface must be enabled until here. A Network-LSA of a + disabled interface (but was once enabled) should be flushed + by ospf6_lsa_refresh (), and does not come here. */ + assert(oi->area); + + old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_NETWORK), + htonl(oi->interface->ifindex), + oi->area->ospf6->router_id, oi->area->lsdb); + + /* Do not originate Network-LSA if not DR */ + if (oi->state != OSPF6_INTERFACE_DR) { + if (old) { + ospf6_lsa_purge(old); + /* + * Waiting till the LSA is actually removed from the + * database to + * trigger SPF delays network convergence. + */ + ospf6_spf_schedule( + oi->area->ospf6, + OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED); + } + return 0; + } + + if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK)) + zlog_debug("Originate Network-LSA for Interface %s", + oi->interface->name); + + /* If none of neighbor is adjacent to us */ + count = 0; + + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, i, on)) + if (on->state == OSPF6_NEIGHBOR_FULL) + count++; + + if (count == 0) { + if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK)) + zlog_debug("Interface stub, ignore"); + if (old) + ospf6_lsa_purge(old); + return 0; } - return 0; - } - - if (IS_OSPF6_DEBUG_ORIGINATE (NETWORK)) - zlog_debug ("Originate Network-LSA for Interface %s", oi->interface->name); - - /* If none of neighbor is adjacent to us */ - count = 0; - - for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on)) - if (on->state == OSPF6_NEIGHBOR_FULL) - count++; - - if (count == 0) - { - if (IS_OSPF6_DEBUG_ORIGINATE (NETWORK)) - zlog_debug ("Interface stub, ignore"); - if (old) - ospf6_lsa_purge (old); - return 0; - } - - /* prepare buffer */ - memset (buffer, 0, sizeof (buffer)); - lsa_header = (struct ospf6_lsa_header *) buffer; - network_lsa = (struct ospf6_network_lsa *) - ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); - - /* Collect the interface's Link-LSAs to describe - network's optional capabilities */ - type = htons (OSPF6_LSTYPE_LINK); - for (ALL_LSDB_TYPED(oi->lsdb, type, lsa)) - { - link_lsa = (struct ospf6_link_lsa *) - ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header)); - network_lsa->options[0] |= link_lsa->options[0]; - network_lsa->options[1] |= link_lsa->options[1]; - network_lsa->options[2] |= link_lsa->options[2]; - } - - lsdesc = (struct ospf6_network_lsdesc *) - ((caddr_t) network_lsa + sizeof (struct ospf6_network_lsa)); - - /* set Link Description to the router itself */ - lsdesc->router_id = oi->area->ospf6->router_id; - lsdesc++; - - /* Walk through the neighbors */ - for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on)) - { - if (on->state != OSPF6_NEIGHBOR_FULL) - continue; - - /* set this neighbor's Router-ID to LSA */ - lsdesc->router_id = on->router_id; - lsdesc++; - } - - /* Fill LSA Header */ - lsa_header->age = 0; - lsa_header->type = htons (OSPF6_LSTYPE_NETWORK); - lsa_header->id = htonl (oi->interface->ifindex); - lsa_header->adv_router = oi->area->ospf6->router_id; - lsa_header->seqnum = - ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id, - lsa_header->adv_router, oi->area->lsdb); - lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer); - - /* LSA checksum */ - ospf6_lsa_checksum (lsa_header); - - /* create LSA */ - lsa = ospf6_lsa_create (lsa_header); - - /* Originate */ - ospf6_lsa_originate_area (lsa, oi->area); - - return 0; + + /* prepare buffer */ + memset(buffer, 0, sizeof(buffer)); + lsa_header = (struct ospf6_lsa_header *)buffer; + network_lsa = + (struct ospf6_network_lsa *)((caddr_t)lsa_header + + sizeof(struct ospf6_lsa_header)); + + /* Collect the interface's Link-LSAs to describe + network's optional capabilities */ + type = htons(OSPF6_LSTYPE_LINK); + for (ALL_LSDB_TYPED(oi->lsdb, type, lsa)) { + link_lsa = (struct ospf6_link_lsa + *)((caddr_t)lsa->header + + sizeof(struct ospf6_lsa_header)); + network_lsa->options[0] |= link_lsa->options[0]; + network_lsa->options[1] |= link_lsa->options[1]; + network_lsa->options[2] |= link_lsa->options[2]; + } + + lsdesc = (struct ospf6_network_lsdesc + *)((caddr_t)network_lsa + + sizeof(struct ospf6_network_lsa)); + + /* set Link Description to the router itself */ + lsdesc->router_id = oi->area->ospf6->router_id; + lsdesc++; + + /* Walk through the neighbors */ + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, i, on)) { + if (on->state != OSPF6_NEIGHBOR_FULL) + continue; + + /* set this neighbor's Router-ID to LSA */ + lsdesc->router_id = on->router_id; + lsdesc++; + } + + /* Fill LSA Header */ + lsa_header->age = 0; + lsa_header->type = htons(OSPF6_LSTYPE_NETWORK); + lsa_header->id = htonl(oi->interface->ifindex); + lsa_header->adv_router = oi->area->ospf6->router_id; + lsa_header->seqnum = + ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id, + lsa_header->adv_router, oi->area->lsdb); + lsa_header->length = htons((caddr_t)lsdesc - (caddr_t)buffer); + + /* LSA checksum */ + ospf6_lsa_checksum(lsa_header); + + /* create LSA */ + lsa = ospf6_lsa_create(lsa_header); + + /* Originate */ + ospf6_lsa_originate_area(lsa, oi->area); + + return 0; } @@ -548,1152 +538,1107 @@ ospf6_network_lsa_originate (struct thread *thread) /* RFC2740 3.4.3.6 Link-LSA */ /****************************/ -static char * -ospf6_link_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf, int buflen, - int pos) +static char *ospf6_link_lsa_get_prefix_str(struct ospf6_lsa *lsa, char *buf, + int buflen, int pos) { - char *start, *end, *current; - struct ospf6_link_lsa *link_lsa; - struct in6_addr in6; - struct ospf6_prefix *prefix; - int cnt = 0, prefixnum; - - if (lsa) - { - link_lsa = (struct ospf6_link_lsa *) - ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header)); - - if (pos == 0) { - inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, buflen); - return (buf); - } - - prefixnum = ntohl (link_lsa->prefix_num); - if (pos > prefixnum) + char *start, *end, *current; + struct ospf6_link_lsa *link_lsa; + struct in6_addr in6; + struct ospf6_prefix *prefix; + int cnt = 0, prefixnum; + + if (lsa) { + link_lsa = (struct ospf6_link_lsa + *)((caddr_t)lsa->header + + sizeof(struct ospf6_lsa_header)); + + if (pos == 0) { + inet_ntop(AF_INET6, &link_lsa->linklocal_addr, buf, + buflen); + return (buf); + } + + prefixnum = ntohl(link_lsa->prefix_num); + if (pos > prefixnum) + return (NULL); + + start = (char *)link_lsa + sizeof(struct ospf6_link_lsa); + end = (char *)lsa->header + ntohs(lsa->header->length); + current = start; + + do { + prefix = (struct ospf6_prefix *)current; + if (prefix->prefix_length == 0 + || current + OSPF6_PREFIX_SIZE(prefix) > end) { + return (NULL); + } + + if (cnt < pos) { + current = + start + pos * OSPF6_PREFIX_SIZE(prefix); + cnt++; + } else { + memset(&in6, 0, sizeof(in6)); + memcpy(&in6, OSPF6_PREFIX_BODY(prefix), + OSPF6_PREFIX_SPACE( + prefix->prefix_length)); + inet_ntop(AF_INET6, &in6, buf, buflen); + return (buf); + } + } while (current <= end); + } return (NULL); - - start = (char *) link_lsa + sizeof (struct ospf6_link_lsa); - end = (char *) lsa->header + ntohs (lsa->header->length); - current = start; - - do - { - prefix = (struct ospf6_prefix *) current; - if (prefix->prefix_length == 0 || - current + OSPF6_PREFIX_SIZE (prefix) > end) - { - return (NULL); - } - - if (cnt < pos) - { - current = start + pos*OSPF6_PREFIX_SIZE(prefix); - cnt++; - } - else - { - memset (&in6, 0, sizeof (in6)); - memcpy (&in6, OSPF6_PREFIX_BODY (prefix), - OSPF6_PREFIX_SPACE (prefix->prefix_length)); - inet_ntop (AF_INET6, &in6, buf, buflen); - return (buf); - } - } while (current <= end); - } - return (NULL); } -static int -ospf6_link_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) +static int ospf6_link_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) { - char *start, *end, *current; - struct ospf6_link_lsa *link_lsa; - int prefixnum; - char buf[128], options[32]; - struct ospf6_prefix *prefix; - const char *p, *mc, *la, *nu; - struct in6_addr in6; - - link_lsa = (struct ospf6_link_lsa *) - ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header)); - - ospf6_options_printbuf (link_lsa->options, options, sizeof (options)); - inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf)); - prefixnum = ntohl (link_lsa->prefix_num); - - vty_out (vty, " Priority: %d Options: %s\n", - link_lsa->priority, options); - vty_out (vty, " LinkLocal Address: %s\n", buf); - vty_out (vty, " Number of Prefix: %d\n", prefixnum); - - start = (char *) link_lsa + sizeof (struct ospf6_link_lsa); - end = (char *) lsa->header + ntohs (lsa->header->length); - for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix)) - { - prefix = (struct ospf6_prefix *) current; - if (prefix->prefix_length == 0 || - current + OSPF6_PREFIX_SIZE (prefix) > end) - break; - - p = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_P) ? - "P" : "--"); - mc = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) ? - "MC" : "--"); - la = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) ? - "LA" : "--"); - nu = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ? - "NU" : "--"); - vty_out (vty, " Prefix Options: %s|%s|%s|%s\n", - p, mc, la, nu); - - memset (&in6, 0, sizeof (in6)); - memcpy (&in6, OSPF6_PREFIX_BODY (prefix), - OSPF6_PREFIX_SPACE (prefix->prefix_length)); - inet_ntop (AF_INET6, &in6, buf, sizeof (buf)); - vty_out (vty, " Prefix: %s/%d\n", - buf, prefix->prefix_length); - } - - return 0; + char *start, *end, *current; + struct ospf6_link_lsa *link_lsa; + int prefixnum; + char buf[128], options[32]; + struct ospf6_prefix *prefix; + const char *p, *mc, *la, *nu; + struct in6_addr in6; + + link_lsa = (struct ospf6_link_lsa *)((caddr_t)lsa->header + + sizeof(struct ospf6_lsa_header)); + + ospf6_options_printbuf(link_lsa->options, options, sizeof(options)); + inet_ntop(AF_INET6, &link_lsa->linklocal_addr, buf, sizeof(buf)); + prefixnum = ntohl(link_lsa->prefix_num); + + vty_out(vty, " Priority: %d Options: %s\n", link_lsa->priority, + options); + vty_out(vty, " LinkLocal Address: %s\n", buf); + vty_out(vty, " Number of Prefix: %d\n", prefixnum); + + start = (char *)link_lsa + sizeof(struct ospf6_link_lsa); + end = (char *)lsa->header + ntohs(lsa->header->length); + for (current = start; current < end; + current += OSPF6_PREFIX_SIZE(prefix)) { + prefix = (struct ospf6_prefix *)current; + if (prefix->prefix_length == 0 + || current + OSPF6_PREFIX_SIZE(prefix) > end) + break; + + p = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_P) + ? "P" + : "--"); + mc = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) + ? "MC" + : "--"); + la = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) + ? "LA" + : "--"); + nu = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) + ? "NU" + : "--"); + vty_out(vty, " Prefix Options: %s|%s|%s|%s\n", p, mc, la, + nu); + + memset(&in6, 0, sizeof(in6)); + memcpy(&in6, OSPF6_PREFIX_BODY(prefix), + OSPF6_PREFIX_SPACE(prefix->prefix_length)); + inet_ntop(AF_INET6, &in6, buf, sizeof(buf)); + vty_out(vty, " Prefix: %s/%d\n", buf, + prefix->prefix_length); + } + + return 0; } -int -ospf6_link_lsa_originate (struct thread *thread) +int ospf6_link_lsa_originate(struct thread *thread) { - struct ospf6_interface *oi; - - char buffer[OSPF6_MAX_LSASIZE]; - struct ospf6_lsa_header *lsa_header; - struct ospf6_lsa *old, *lsa; - - struct ospf6_link_lsa *link_lsa; - struct ospf6_route *route; - struct ospf6_prefix *op; - - oi = (struct ospf6_interface *) THREAD_ARG (thread); - oi->thread_link_lsa = NULL; - - assert (oi->area); - - /* find previous LSA */ - old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_LINK), - htonl (oi->interface->ifindex), - oi->area->ospf6->router_id, oi->lsdb); - - if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE)) - { - if (old) - ospf6_lsa_purge (old); - return 0; - } - - if (IS_OSPF6_DEBUG_ORIGINATE (LINK)) - zlog_debug ("Originate Link-LSA for Interface %s", oi->interface->name); - - /* can't make Link-LSA if linklocal address not set */ - if (oi->linklocal_addr == NULL) - { - if (IS_OSPF6_DEBUG_ORIGINATE (LINK)) - zlog_debug ("No Linklocal address on %s, defer originating", - oi->interface->name); - if (old) - ospf6_lsa_purge (old); - return 0; - } - - /* prepare buffer */ - memset (buffer, 0, sizeof (buffer)); - lsa_header = (struct ospf6_lsa_header *) buffer; - link_lsa = (struct ospf6_link_lsa *) - ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); - - /* Fill Link-LSA */ - link_lsa->priority = oi->priority; - memcpy (link_lsa->options, oi->area->options, 3); - memcpy (&link_lsa->linklocal_addr, oi->linklocal_addr, - sizeof (struct in6_addr)); - link_lsa->prefix_num = htonl (oi->route_connected->count); - - op = (struct ospf6_prefix *) - ((caddr_t) link_lsa + sizeof (struct ospf6_link_lsa)); - - /* connected prefix to advertise */ - for (route = ospf6_route_head (oi->route_connected); route; - route = ospf6_route_next (route)) - { - op->prefix_length = route->prefix.prefixlen; - op->prefix_options = route->path.prefix_options; - op->prefix_metric = htons (0); - memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6, - OSPF6_PREFIX_SPACE (op->prefix_length)); - op = OSPF6_PREFIX_NEXT (op); - } - - /* Fill LSA Header */ - lsa_header->age = 0; - lsa_header->type = htons (OSPF6_LSTYPE_LINK); - lsa_header->id = htonl (oi->interface->ifindex); - lsa_header->adv_router = oi->area->ospf6->router_id; - lsa_header->seqnum = - ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id, - lsa_header->adv_router, oi->lsdb); - lsa_header->length = htons ((caddr_t) op - (caddr_t) buffer); - - /* LSA checksum */ - ospf6_lsa_checksum (lsa_header); - - /* create LSA */ - lsa = ospf6_lsa_create (lsa_header); - - /* Originate */ - ospf6_lsa_originate_interface (lsa, oi); - - return 0; + struct ospf6_interface *oi; + + char buffer[OSPF6_MAX_LSASIZE]; + struct ospf6_lsa_header *lsa_header; + struct ospf6_lsa *old, *lsa; + + struct ospf6_link_lsa *link_lsa; + struct ospf6_route *route; + struct ospf6_prefix *op; + + oi = (struct ospf6_interface *)THREAD_ARG(thread); + oi->thread_link_lsa = NULL; + + assert(oi->area); + + /* find previous LSA */ + old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_LINK), + htonl(oi->interface->ifindex), + oi->area->ospf6->router_id, oi->lsdb); + + if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) { + if (old) + ospf6_lsa_purge(old); + return 0; + } + + if (IS_OSPF6_DEBUG_ORIGINATE(LINK)) + zlog_debug("Originate Link-LSA for Interface %s", + oi->interface->name); + + /* can't make Link-LSA if linklocal address not set */ + if (oi->linklocal_addr == NULL) { + if (IS_OSPF6_DEBUG_ORIGINATE(LINK)) + zlog_debug( + "No Linklocal address on %s, defer originating", + oi->interface->name); + if (old) + ospf6_lsa_purge(old); + return 0; + } + + /* prepare buffer */ + memset(buffer, 0, sizeof(buffer)); + lsa_header = (struct ospf6_lsa_header *)buffer; + link_lsa = (struct ospf6_link_lsa *)((caddr_t)lsa_header + + sizeof(struct ospf6_lsa_header)); + + /* Fill Link-LSA */ + link_lsa->priority = oi->priority; + memcpy(link_lsa->options, oi->area->options, 3); + memcpy(&link_lsa->linklocal_addr, oi->linklocal_addr, + sizeof(struct in6_addr)); + link_lsa->prefix_num = htonl(oi->route_connected->count); + + op = (struct ospf6_prefix *)((caddr_t)link_lsa + + sizeof(struct ospf6_link_lsa)); + + /* connected prefix to advertise */ + for (route = ospf6_route_head(oi->route_connected); route; + route = ospf6_route_next(route)) { + op->prefix_length = route->prefix.prefixlen; + op->prefix_options = route->path.prefix_options; + op->prefix_metric = htons(0); + memcpy(OSPF6_PREFIX_BODY(op), &route->prefix.u.prefix6, + OSPF6_PREFIX_SPACE(op->prefix_length)); + op = OSPF6_PREFIX_NEXT(op); + } + + /* Fill LSA Header */ + lsa_header->age = 0; + lsa_header->type = htons(OSPF6_LSTYPE_LINK); + lsa_header->id = htonl(oi->interface->ifindex); + lsa_header->adv_router = oi->area->ospf6->router_id; + lsa_header->seqnum = + ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id, + lsa_header->adv_router, oi->lsdb); + lsa_header->length = htons((caddr_t)op - (caddr_t)buffer); + + /* LSA checksum */ + ospf6_lsa_checksum(lsa_header); + + /* create LSA */ + lsa = ospf6_lsa_create(lsa_header); + + /* Originate */ + ospf6_lsa_originate_interface(lsa, oi); + + return 0; } /*****************************************/ /* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */ /*****************************************/ -static char * -ospf6_intra_prefix_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf, - int buflen, int pos) +static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa, + char *buf, int buflen, + int pos) { - char *start, *end, *current; - struct ospf6_intra_prefix_lsa *intra_prefix_lsa; - struct in6_addr in6; - int prefixnum, cnt = 0; - struct ospf6_prefix *prefix; - - if (lsa) - { - intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) - ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header)); - - prefixnum = ntohs (intra_prefix_lsa->prefix_num); - if (pos > prefixnum) - return (NULL); - - start = (char *) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa); - end = (char *) lsa->header + ntohs (lsa->header->length); - current = start; - - do - { - prefix = (struct ospf6_prefix *) current; - if (prefix->prefix_length == 0 || - current + OSPF6_PREFIX_SIZE (prefix) > end) - { - return NULL; - } - - if (cnt < pos) - { - current = start + pos*OSPF6_PREFIX_SIZE(prefix); - cnt++; - } - else - { - memset (&in6, 0, sizeof (in6)); - memcpy (&in6, OSPF6_PREFIX_BODY (prefix), - OSPF6_PREFIX_SPACE (prefix->prefix_length)); - inet_ntop (AF_INET6, &in6, buf, buflen); - sprintf(&buf[strlen(buf)], "/%d", prefix->prefix_length); - return (buf); - } - } while (current <= end); - } - return (buf); + char *start, *end, *current; + struct ospf6_intra_prefix_lsa *intra_prefix_lsa; + struct in6_addr in6; + int prefixnum, cnt = 0; + struct ospf6_prefix *prefix; + + if (lsa) { + intra_prefix_lsa = + (struct ospf6_intra_prefix_lsa + *)((caddr_t)lsa->header + + sizeof(struct ospf6_lsa_header)); + + prefixnum = ntohs(intra_prefix_lsa->prefix_num); + if (pos > prefixnum) + return (NULL); + + start = (char *)intra_prefix_lsa + + sizeof(struct ospf6_intra_prefix_lsa); + end = (char *)lsa->header + ntohs(lsa->header->length); + current = start; + + do { + prefix = (struct ospf6_prefix *)current; + if (prefix->prefix_length == 0 + || current + OSPF6_PREFIX_SIZE(prefix) > end) { + return NULL; + } + + if (cnt < pos) { + current = + start + pos * OSPF6_PREFIX_SIZE(prefix); + cnt++; + } else { + memset(&in6, 0, sizeof(in6)); + memcpy(&in6, OSPF6_PREFIX_BODY(prefix), + OSPF6_PREFIX_SPACE( + prefix->prefix_length)); + inet_ntop(AF_INET6, &in6, buf, buflen); + sprintf(&buf[strlen(buf)], "/%d", + prefix->prefix_length); + return (buf); + } + } while (current <= end); + } + return (buf); } -static int -ospf6_intra_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) +static int ospf6_intra_prefix_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) { - char *start, *end, *current; - struct ospf6_intra_prefix_lsa *intra_prefix_lsa; - int prefixnum; - char buf[128]; - struct ospf6_prefix *prefix; - char id[16], adv_router[16]; - const char *p, *mc, *la, *nu; - struct in6_addr in6; - - intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) - ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header)); - - prefixnum = ntohs (intra_prefix_lsa->prefix_num); - - vty_out (vty, " Number of Prefix: %d\n", prefixnum); - - inet_ntop (AF_INET, &intra_prefix_lsa->ref_id, id, sizeof (id)); - inet_ntop (AF_INET, &intra_prefix_lsa->ref_adv_router, - adv_router, sizeof (adv_router)); - vty_out (vty, " Reference: %s Id: %s Adv: %s\n", - ospf6_lstype_name (intra_prefix_lsa->ref_type), id, adv_router); - - start = (char *) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa); - end = (char *) lsa->header + ntohs (lsa->header->length); - for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix)) - { - prefix = (struct ospf6_prefix *) current; - if (prefix->prefix_length == 0 || - current + OSPF6_PREFIX_SIZE (prefix) > end) - break; - - p = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_P) ? - "P" : "--"); - mc = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) ? - "MC" : "--"); - la = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) ? - "LA" : "--"); - nu = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ? - "NU" : "--"); - vty_out (vty, " Prefix Options: %s|%s|%s|%s\n", - p, mc, la, nu); - - memset (&in6, 0, sizeof (in6)); - memcpy (&in6, OSPF6_PREFIX_BODY (prefix), - OSPF6_PREFIX_SPACE (prefix->prefix_length)); - inet_ntop (AF_INET6, &in6, buf, sizeof (buf)); - vty_out (vty, " Prefix: %s/%d\n", - buf, prefix->prefix_length); - } - - return 0; + char *start, *end, *current; + struct ospf6_intra_prefix_lsa *intra_prefix_lsa; + int prefixnum; + char buf[128]; + struct ospf6_prefix *prefix; + char id[16], adv_router[16]; + const char *p, *mc, *la, *nu; + struct in6_addr in6; + + intra_prefix_lsa = (struct ospf6_intra_prefix_lsa + *)((caddr_t)lsa->header + + sizeof(struct ospf6_lsa_header)); + + prefixnum = ntohs(intra_prefix_lsa->prefix_num); + + vty_out(vty, " Number of Prefix: %d\n", prefixnum); + + inet_ntop(AF_INET, &intra_prefix_lsa->ref_id, id, sizeof(id)); + inet_ntop(AF_INET, &intra_prefix_lsa->ref_adv_router, adv_router, + sizeof(adv_router)); + vty_out(vty, " Reference: %s Id: %s Adv: %s\n", + ospf6_lstype_name(intra_prefix_lsa->ref_type), id, adv_router); + + start = (char *)intra_prefix_lsa + + sizeof(struct ospf6_intra_prefix_lsa); + end = (char *)lsa->header + ntohs(lsa->header->length); + for (current = start; current < end; + current += OSPF6_PREFIX_SIZE(prefix)) { + prefix = (struct ospf6_prefix *)current; + if (prefix->prefix_length == 0 + || current + OSPF6_PREFIX_SIZE(prefix) > end) + break; + + p = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_P) + ? "P" + : "--"); + mc = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) + ? "MC" + : "--"); + la = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) + ? "LA" + : "--"); + nu = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) + ? "NU" + : "--"); + vty_out(vty, " Prefix Options: %s|%s|%s|%s\n", p, mc, la, + nu); + + memset(&in6, 0, sizeof(in6)); + memcpy(&in6, OSPF6_PREFIX_BODY(prefix), + OSPF6_PREFIX_SPACE(prefix->prefix_length)); + inet_ntop(AF_INET6, &in6, buf, sizeof(buf)); + vty_out(vty, " Prefix: %s/%d\n", buf, + prefix->prefix_length); + } + + return 0; } -int -ospf6_intra_prefix_lsa_originate_stub (struct thread *thread) +int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread) { - struct ospf6_area *oa; - - char buffer[OSPF6_MAX_LSASIZE]; - struct ospf6_lsa_header *lsa_header; - struct ospf6_lsa *old, *lsa; - - struct ospf6_intra_prefix_lsa *intra_prefix_lsa; - struct ospf6_interface *oi; - struct ospf6_neighbor *on; - struct ospf6_route *route; - struct ospf6_prefix *op; - struct listnode *i, *j; - int full_count = 0; - unsigned short prefix_num = 0; - char buf[PREFIX2STR_BUFFER]; - struct ospf6_route_table *route_advertise; - - oa = (struct ospf6_area *) THREAD_ARG (thread); - oa->thread_intra_prefix_lsa = NULL; - - /* find previous LSA */ - old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX), - htonl (0), oa->ospf6->router_id, oa->lsdb); - - if (! IS_AREA_ENABLED (oa)) - { - if (old) - ospf6_lsa_purge (old); - return 0; - } - - if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX)) - zlog_debug ("Originate Intra-Area-Prefix-LSA for area %s's stub prefix", - oa->name); - - /* prepare buffer */ - memset (buffer, 0, sizeof (buffer)); - lsa_header = (struct ospf6_lsa_header *) buffer; - intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) - ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); - - /* Fill Intra-Area-Prefix-LSA */ - intra_prefix_lsa->ref_type = htons (OSPF6_LSTYPE_ROUTER); - intra_prefix_lsa->ref_id = htonl (0); - intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id; - - route_advertise = ospf6_route_table_create (0, 0); - - for (ALL_LIST_ELEMENTS_RO (oa->if_list, i, oi)) - { - if (oi->state == OSPF6_INTERFACE_DOWN) - { - if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX)) - zlog_debug (" Interface %s is down, ignore", oi->interface->name); - continue; - } - - full_count = 0; - - for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on)) - if (on->state == OSPF6_NEIGHBOR_FULL) - full_count++; - - if (oi->state != OSPF6_INTERFACE_LOOPBACK && - oi->state != OSPF6_INTERFACE_POINTTOPOINT && - full_count != 0) - { - if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX)) - zlog_debug (" Interface %s is not stub, ignore", - oi->interface->name); - continue; - } - - if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX)) - zlog_debug (" Interface %s:", oi->interface->name); - - /* connected prefix to advertise */ - for (route = ospf6_route_head (oi->route_connected); route; - route = ospf6_route_best_next (route)) - { - if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX)) - { - prefix2str (&route->prefix, buf, sizeof (buf)); - zlog_debug (" include %s", buf); - } - ospf6_route_add (ospf6_route_copy (route), route_advertise); - } - } - - if (route_advertise->count == 0) - { - if (old) - ospf6_lsa_purge (old); - ospf6_route_table_delete (route_advertise); - return 0; - } - - /* put prefixes to advertise */ - prefix_num = 0; - op = (struct ospf6_prefix *) - ((caddr_t) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa)); - for (route = ospf6_route_head (route_advertise); route; - route = ospf6_route_best_next (route)) - { - op->prefix_length = route->prefix.prefixlen; - op->prefix_options = route->path.prefix_options; - op->prefix_metric = htons (route->path.cost); - memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6, - OSPF6_PREFIX_SPACE (op->prefix_length)); - op = OSPF6_PREFIX_NEXT (op); - prefix_num++; - } - - ospf6_route_table_delete (route_advertise); - - if (prefix_num == 0) - { - if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX)) - zlog_debug ("Quit to Advertise Intra-Prefix: no route to advertise"); - return 0; - } - - intra_prefix_lsa->prefix_num = htons (prefix_num); - - /* Fill LSA Header */ - lsa_header->age = 0; - lsa_header->type = htons (OSPF6_LSTYPE_INTRA_PREFIX); - lsa_header->id = htonl (0); - lsa_header->adv_router = oa->ospf6->router_id; - lsa_header->seqnum = - ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id, - lsa_header->adv_router, oa->lsdb); - lsa_header->length = htons ((caddr_t) op - (caddr_t) lsa_header); - - /* LSA checksum */ - ospf6_lsa_checksum (lsa_header); - - /* create LSA */ - lsa = ospf6_lsa_create (lsa_header); - - /* Originate */ - ospf6_lsa_originate_area (lsa, oa); - - return 0; + struct ospf6_area *oa; + + char buffer[OSPF6_MAX_LSASIZE]; + struct ospf6_lsa_header *lsa_header; + struct ospf6_lsa *old, *lsa; + + struct ospf6_intra_prefix_lsa *intra_prefix_lsa; + struct ospf6_interface *oi; + struct ospf6_neighbor *on; + struct ospf6_route *route; + struct ospf6_prefix *op; + struct listnode *i, *j; + int full_count = 0; + unsigned short prefix_num = 0; + char buf[PREFIX2STR_BUFFER]; + struct ospf6_route_table *route_advertise; + + oa = (struct ospf6_area *)THREAD_ARG(thread); + oa->thread_intra_prefix_lsa = NULL; + + /* find previous LSA */ + old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX), htonl(0), + oa->ospf6->router_id, oa->lsdb); + + if (!IS_AREA_ENABLED(oa)) { + if (old) + ospf6_lsa_purge(old); + return 0; + } + + if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX)) + zlog_debug( + "Originate Intra-Area-Prefix-LSA for area %s's stub prefix", + oa->name); + + /* prepare buffer */ + memset(buffer, 0, sizeof(buffer)); + lsa_header = (struct ospf6_lsa_header *)buffer; + intra_prefix_lsa = (struct ospf6_intra_prefix_lsa + *)((caddr_t)lsa_header + + sizeof(struct ospf6_lsa_header)); + + /* Fill Intra-Area-Prefix-LSA */ + intra_prefix_lsa->ref_type = htons(OSPF6_LSTYPE_ROUTER); + intra_prefix_lsa->ref_id = htonl(0); + intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id; + + route_advertise = ospf6_route_table_create(0, 0); + + for (ALL_LIST_ELEMENTS_RO(oa->if_list, i, oi)) { + if (oi->state == OSPF6_INTERFACE_DOWN) { + if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX)) + zlog_debug(" Interface %s is down, ignore", + oi->interface->name); + continue; + } + + full_count = 0; + + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, j, on)) + if (on->state == OSPF6_NEIGHBOR_FULL) + full_count++; + + if (oi->state != OSPF6_INTERFACE_LOOPBACK + && oi->state != OSPF6_INTERFACE_POINTTOPOINT + && full_count != 0) { + if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX)) + zlog_debug(" Interface %s is not stub, ignore", + oi->interface->name); + continue; + } + + if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX)) + zlog_debug(" Interface %s:", oi->interface->name); + + /* connected prefix to advertise */ + for (route = ospf6_route_head(oi->route_connected); route; + route = ospf6_route_best_next(route)) { + if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX)) { + prefix2str(&route->prefix, buf, sizeof(buf)); + zlog_debug(" include %s", buf); + } + ospf6_route_add(ospf6_route_copy(route), + route_advertise); + } + } + + if (route_advertise->count == 0) { + if (old) + ospf6_lsa_purge(old); + ospf6_route_table_delete(route_advertise); + return 0; + } + + /* put prefixes to advertise */ + prefix_num = 0; + op = (struct ospf6_prefix *)((caddr_t)intra_prefix_lsa + + sizeof(struct ospf6_intra_prefix_lsa)); + for (route = ospf6_route_head(route_advertise); route; + route = ospf6_route_best_next(route)) { + op->prefix_length = route->prefix.prefixlen; + op->prefix_options = route->path.prefix_options; + op->prefix_metric = htons(route->path.cost); + memcpy(OSPF6_PREFIX_BODY(op), &route->prefix.u.prefix6, + OSPF6_PREFIX_SPACE(op->prefix_length)); + op = OSPF6_PREFIX_NEXT(op); + prefix_num++; + } + + ospf6_route_table_delete(route_advertise); + + if (prefix_num == 0) { + if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX)) + zlog_debug( + "Quit to Advertise Intra-Prefix: no route to advertise"); + return 0; + } + + intra_prefix_lsa->prefix_num = htons(prefix_num); + + /* Fill LSA Header */ + lsa_header->age = 0; + lsa_header->type = htons(OSPF6_LSTYPE_INTRA_PREFIX); + lsa_header->id = htonl(0); + lsa_header->adv_router = oa->ospf6->router_id; + lsa_header->seqnum = + ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id, + lsa_header->adv_router, oa->lsdb); + lsa_header->length = htons((caddr_t)op - (caddr_t)lsa_header); + + /* LSA checksum */ + ospf6_lsa_checksum(lsa_header); + + /* create LSA */ + lsa = ospf6_lsa_create(lsa_header); + + /* Originate */ + ospf6_lsa_originate_area(lsa, oa); + + return 0; } -int -ospf6_intra_prefix_lsa_originate_transit (struct thread *thread) +int ospf6_intra_prefix_lsa_originate_transit(struct thread *thread) { - struct ospf6_interface *oi; - - char buffer[OSPF6_MAX_LSASIZE]; - struct ospf6_lsa_header *lsa_header; - struct ospf6_lsa *old, *lsa; - - struct ospf6_intra_prefix_lsa *intra_prefix_lsa; - struct ospf6_neighbor *on; - struct ospf6_route *route; - struct ospf6_prefix *op; - struct listnode *i; - int full_count = 0; - unsigned short prefix_num = 0; - struct ospf6_route_table *route_advertise; - struct ospf6_link_lsa *link_lsa; - char *start, *end, *current; - u_int16_t type; - char buf[PREFIX2STR_BUFFER]; - - oi = (struct ospf6_interface *) THREAD_ARG (thread); - oi->thread_intra_prefix_lsa = NULL; - - assert (oi->area); - - /* find previous LSA */ - old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX), - htonl (oi->interface->ifindex), - oi->area->ospf6->router_id, oi->area->lsdb); - - if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE)) - { - if (old) - ospf6_lsa_purge (old); - return 0; - } - - if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX)) - zlog_debug ("Originate Intra-Area-Prefix-LSA for interface %s's prefix", - oi->interface->name); - - /* prepare buffer */ - memset (buffer, 0, sizeof (buffer)); - lsa_header = (struct ospf6_lsa_header *) buffer; - intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) - ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); - - /* Fill Intra-Area-Prefix-LSA */ - intra_prefix_lsa->ref_type = htons (OSPF6_LSTYPE_NETWORK); - intra_prefix_lsa->ref_id = htonl (oi->interface->ifindex); - intra_prefix_lsa->ref_adv_router = oi->area->ospf6->router_id; - - if (oi->state != OSPF6_INTERFACE_DR) - { - if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX)) - zlog_debug (" Interface is not DR"); - if (old) - ospf6_lsa_purge (old); - return 0; - } - - full_count = 0; - for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on)) - if (on->state == OSPF6_NEIGHBOR_FULL) - full_count++; - - if (full_count == 0) - { - if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX)) - zlog_debug (" Interface is stub"); - if (old) - ospf6_lsa_purge (old); - return 0; - } - - /* connected prefix to advertise */ - route_advertise = ospf6_route_table_create (0, 0); - - type = ntohs (OSPF6_LSTYPE_LINK); - for (ALL_LSDB_TYPED(oi->lsdb, type, lsa)) - { - if (OSPF6_LSA_IS_MAXAGE (lsa)) - continue; - - if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX)) - zlog_debug (" include prefix from %s", lsa->name); - - if (lsa->header->adv_router != oi->area->ospf6->router_id) - { - on = ospf6_neighbor_lookup (lsa->header->adv_router, oi); - if (on == NULL || on->state != OSPF6_NEIGHBOR_FULL) - { - if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX)) - zlog_debug (" Neighbor not found or not Full, ignore"); - continue; - } - } - - link_lsa = (struct ospf6_link_lsa *) - ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header)); - - prefix_num = (unsigned short) ntohl (link_lsa->prefix_num); - start = (char *) link_lsa + sizeof (struct ospf6_link_lsa); - end = (char *) lsa->header + ntohs (lsa->header->length); - for (current = start; current < end && prefix_num; - current += OSPF6_PREFIX_SIZE (op)) - { - op = (struct ospf6_prefix *) current; - if (op->prefix_length == 0 || - current + OSPF6_PREFIX_SIZE (op) > end) - break; - - route = ospf6_route_create (); - - route->type = OSPF6_DEST_TYPE_NETWORK; - route->prefix.family = AF_INET6; - route->prefix.prefixlen = op->prefix_length; - memset (&route->prefix.u.prefix6, 0, sizeof (struct in6_addr)); - memcpy (&route->prefix.u.prefix6, OSPF6_PREFIX_BODY (op), - OSPF6_PREFIX_SPACE (op->prefix_length)); - - route->path.origin.type = lsa->header->type; - route->path.origin.id = lsa->header->id; - route->path.origin.adv_router = lsa->header->adv_router; - route->path.options[0] = link_lsa->options[0]; - route->path.options[1] = link_lsa->options[1]; - route->path.options[2] = link_lsa->options[2]; - route->path.prefix_options = op->prefix_options; - route->path.area_id = oi->area->area_id; - route->path.type = OSPF6_PATH_TYPE_INTRA; - - if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX)) - { - prefix2str (&route->prefix, buf, sizeof (buf)); - zlog_debug (" include %s", buf); - } - - ospf6_route_add (route, route_advertise); - prefix_num--; - } - if (current != end && IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX)) - zlog_debug ("Trailing garbage in %s", lsa->name); - } - - op = (struct ospf6_prefix *) - ((caddr_t) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa)); - - prefix_num = 0; - for (route = ospf6_route_head (route_advertise); route; - route = ospf6_route_best_next (route)) - { - op->prefix_length = route->prefix.prefixlen; - op->prefix_options = route->path.prefix_options; - op->prefix_metric = htons (0); - memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6, - OSPF6_PREFIX_SPACE (op->prefix_length)); - op = OSPF6_PREFIX_NEXT (op); - prefix_num++; - } - - ospf6_route_table_delete (route_advertise); - - if (prefix_num == 0) - { - if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX)) - zlog_debug ("Quit to Advertise Intra-Prefix: no route to advertise"); - return 0; - } - - intra_prefix_lsa->prefix_num = htons (prefix_num); - - /* Fill LSA Header */ - lsa_header->age = 0; - lsa_header->type = htons (OSPF6_LSTYPE_INTRA_PREFIX); - lsa_header->id = htonl (oi->interface->ifindex); - lsa_header->adv_router = oi->area->ospf6->router_id; - lsa_header->seqnum = - ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id, - lsa_header->adv_router, oi->area->lsdb); - lsa_header->length = htons ((caddr_t) op - (caddr_t) lsa_header); - - /* LSA checksum */ - ospf6_lsa_checksum (lsa_header); - - /* create LSA */ - lsa = ospf6_lsa_create (lsa_header); - - /* Originate */ - ospf6_lsa_originate_area (lsa, oi->area); - - return 0; + struct ospf6_interface *oi; + + char buffer[OSPF6_MAX_LSASIZE]; + struct ospf6_lsa_header *lsa_header; + struct ospf6_lsa *old, *lsa; + + struct ospf6_intra_prefix_lsa *intra_prefix_lsa; + struct ospf6_neighbor *on; + struct ospf6_route *route; + struct ospf6_prefix *op; + struct listnode *i; + int full_count = 0; + unsigned short prefix_num = 0; + struct ospf6_route_table *route_advertise; + struct ospf6_link_lsa *link_lsa; + char *start, *end, *current; + u_int16_t type; + char buf[PREFIX2STR_BUFFER]; + + oi = (struct ospf6_interface *)THREAD_ARG(thread); + oi->thread_intra_prefix_lsa = NULL; + + assert(oi->area); + + /* find previous LSA */ + old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX), + htonl(oi->interface->ifindex), + oi->area->ospf6->router_id, oi->area->lsdb); + + if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) { + if (old) + ospf6_lsa_purge(old); + return 0; + } + + if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX)) + zlog_debug( + "Originate Intra-Area-Prefix-LSA for interface %s's prefix", + oi->interface->name); + + /* prepare buffer */ + memset(buffer, 0, sizeof(buffer)); + lsa_header = (struct ospf6_lsa_header *)buffer; + intra_prefix_lsa = (struct ospf6_intra_prefix_lsa + *)((caddr_t)lsa_header + + sizeof(struct ospf6_lsa_header)); + + /* Fill Intra-Area-Prefix-LSA */ + intra_prefix_lsa->ref_type = htons(OSPF6_LSTYPE_NETWORK); + intra_prefix_lsa->ref_id = htonl(oi->interface->ifindex); + intra_prefix_lsa->ref_adv_router = oi->area->ospf6->router_id; + + if (oi->state != OSPF6_INTERFACE_DR) { + if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX)) + zlog_debug(" Interface is not DR"); + if (old) + ospf6_lsa_purge(old); + return 0; + } + + full_count = 0; + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, i, on)) + if (on->state == OSPF6_NEIGHBOR_FULL) + full_count++; + + if (full_count == 0) { + if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX)) + zlog_debug(" Interface is stub"); + if (old) + ospf6_lsa_purge(old); + return 0; + } + + /* connected prefix to advertise */ + route_advertise = ospf6_route_table_create(0, 0); + + type = ntohs(OSPF6_LSTYPE_LINK); + for (ALL_LSDB_TYPED(oi->lsdb, type, lsa)) { + if (OSPF6_LSA_IS_MAXAGE(lsa)) + continue; + + if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX)) + zlog_debug(" include prefix from %s", lsa->name); + + if (lsa->header->adv_router != oi->area->ospf6->router_id) { + on = ospf6_neighbor_lookup(lsa->header->adv_router, oi); + if (on == NULL || on->state != OSPF6_NEIGHBOR_FULL) { + if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX)) + zlog_debug( + " Neighbor not found or not Full, ignore"); + continue; + } + } + + link_lsa = (struct ospf6_link_lsa + *)((caddr_t)lsa->header + + sizeof(struct ospf6_lsa_header)); + + prefix_num = (unsigned short)ntohl(link_lsa->prefix_num); + start = (char *)link_lsa + sizeof(struct ospf6_link_lsa); + end = (char *)lsa->header + ntohs(lsa->header->length); + for (current = start; current < end && prefix_num; + current += OSPF6_PREFIX_SIZE(op)) { + op = (struct ospf6_prefix *)current; + if (op->prefix_length == 0 + || current + OSPF6_PREFIX_SIZE(op) > end) + break; + + route = ospf6_route_create(); + + route->type = OSPF6_DEST_TYPE_NETWORK; + route->prefix.family = AF_INET6; + route->prefix.prefixlen = op->prefix_length; + memset(&route->prefix.u.prefix6, 0, + sizeof(struct in6_addr)); + memcpy(&route->prefix.u.prefix6, OSPF6_PREFIX_BODY(op), + OSPF6_PREFIX_SPACE(op->prefix_length)); + + route->path.origin.type = lsa->header->type; + route->path.origin.id = lsa->header->id; + route->path.origin.adv_router = lsa->header->adv_router; + route->path.options[0] = link_lsa->options[0]; + route->path.options[1] = link_lsa->options[1]; + route->path.options[2] = link_lsa->options[2]; + route->path.prefix_options = op->prefix_options; + route->path.area_id = oi->area->area_id; + route->path.type = OSPF6_PATH_TYPE_INTRA; + + if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX)) { + prefix2str(&route->prefix, buf, sizeof(buf)); + zlog_debug(" include %s", buf); + } + + ospf6_route_add(route, route_advertise); + prefix_num--; + } + if (current != end && IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX)) + zlog_debug("Trailing garbage in %s", lsa->name); + } + + op = (struct ospf6_prefix *)((caddr_t)intra_prefix_lsa + + sizeof(struct ospf6_intra_prefix_lsa)); + + prefix_num = 0; + for (route = ospf6_route_head(route_advertise); route; + route = ospf6_route_best_next(route)) { + op->prefix_length = route->prefix.prefixlen; + op->prefix_options = route->path.prefix_options; + op->prefix_metric = htons(0); + memcpy(OSPF6_PREFIX_BODY(op), &route->prefix.u.prefix6, + OSPF6_PREFIX_SPACE(op->prefix_length)); + op = OSPF6_PREFIX_NEXT(op); + prefix_num++; + } + + ospf6_route_table_delete(route_advertise); + + if (prefix_num == 0) { + if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX)) + zlog_debug( + "Quit to Advertise Intra-Prefix: no route to advertise"); + return 0; + } + + intra_prefix_lsa->prefix_num = htons(prefix_num); + + /* Fill LSA Header */ + lsa_header->age = 0; + lsa_header->type = htons(OSPF6_LSTYPE_INTRA_PREFIX); + lsa_header->id = htonl(oi->interface->ifindex); + lsa_header->adv_router = oi->area->ospf6->router_id; + lsa_header->seqnum = + ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id, + lsa_header->adv_router, oi->area->lsdb); + lsa_header->length = htons((caddr_t)op - (caddr_t)lsa_header); + + /* LSA checksum */ + ospf6_lsa_checksum(lsa_header); + + /* create LSA */ + lsa = ospf6_lsa_create(lsa_header); + + /* Originate */ + ospf6_lsa_originate_area(lsa, oi->area); + + return 0; } -void -ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa) +void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa) { - struct ospf6_area *oa; - struct ospf6_intra_prefix_lsa *intra_prefix_lsa; - struct prefix ls_prefix; - struct ospf6_route *route, *ls_entry; - int prefix_num; - struct ospf6_prefix *op; - char *start, *current, *end; - char buf[PREFIX2STR_BUFFER]; - struct interface *ifp; - int direct_connect = 0; - - if (OSPF6_LSA_IS_MAXAGE (lsa)) - return; - - if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX)) - zlog_debug ("%s found", lsa->name); - - oa = OSPF6_AREA (lsa->lsdb->data); - - intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) - OSPF6_LSA_HEADER_END (lsa->header); - if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_ROUTER)) - ospf6_linkstate_prefix (intra_prefix_lsa->ref_adv_router, - htonl (0), &ls_prefix); - else if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_NETWORK)) - ospf6_linkstate_prefix (intra_prefix_lsa->ref_adv_router, - intra_prefix_lsa->ref_id, &ls_prefix); - else - { - if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX)) - zlog_debug ("Unknown reference LS-type: %#hx", - ntohs (intra_prefix_lsa->ref_type)); - return; - } - - ls_entry = ospf6_route_lookup (&ls_prefix, oa->spf_table); - if (ls_entry == NULL) - { - if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX)) - { - ospf6_linkstate_prefix2str (&ls_prefix, buf, sizeof (buf)); - zlog_debug ("LS entry does not exist: %s", buf); - } - return; - } - - if (intra_prefix_lsa->ref_adv_router == oa->ospf6->router_id) - { - /* the intra-prefix are directly connected */ - direct_connect = 1; - } - - prefix_num = ntohs (intra_prefix_lsa->prefix_num); - start = (caddr_t) intra_prefix_lsa + - sizeof (struct ospf6_intra_prefix_lsa); - end = OSPF6_LSA_END (lsa->header); - for (current = start; current < end; current += OSPF6_PREFIX_SIZE (op)) - { - op = (struct ospf6_prefix *) current; - if (prefix_num == 0) - break; - if (end < current + OSPF6_PREFIX_SIZE (op)) - break; - - /* Appendix A.4.1.1 */ - if (CHECK_FLAG(op->prefix_options, OSPF6_PREFIX_OPTION_NU)) - { - if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX)) - { - ospf6_linkstate_prefix2str ((struct prefix *)OSPF6_PREFIX_BODY(op), - buf, sizeof (buf)); - zlog_debug ("%s: Skipping Prefix %s has NU option set", - __func__, buf); - } - continue; + struct ospf6_area *oa; + struct ospf6_intra_prefix_lsa *intra_prefix_lsa; + struct prefix ls_prefix; + struct ospf6_route *route, *ls_entry; + int prefix_num; + struct ospf6_prefix *op; + char *start, *current, *end; + char buf[PREFIX2STR_BUFFER]; + struct interface *ifp; + int direct_connect = 0; + + if (OSPF6_LSA_IS_MAXAGE(lsa)) + return; + + if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) + zlog_debug("%s found", lsa->name); + + oa = OSPF6_AREA(lsa->lsdb->data); + + intra_prefix_lsa = + (struct ospf6_intra_prefix_lsa *)OSPF6_LSA_HEADER_END( + lsa->header); + if (intra_prefix_lsa->ref_type == htons(OSPF6_LSTYPE_ROUTER)) + ospf6_linkstate_prefix(intra_prefix_lsa->ref_adv_router, + htonl(0), &ls_prefix); + else if (intra_prefix_lsa->ref_type == htons(OSPF6_LSTYPE_NETWORK)) + ospf6_linkstate_prefix(intra_prefix_lsa->ref_adv_router, + intra_prefix_lsa->ref_id, &ls_prefix); + else { + if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) + zlog_debug("Unknown reference LS-type: %#hx", + ntohs(intra_prefix_lsa->ref_type)); + return; + } + + ls_entry = ospf6_route_lookup(&ls_prefix, oa->spf_table); + if (ls_entry == NULL) { + if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) { + ospf6_linkstate_prefix2str(&ls_prefix, buf, + sizeof(buf)); + zlog_debug("LS entry does not exist: %s", buf); + } + return; + } + + if (intra_prefix_lsa->ref_adv_router == oa->ospf6->router_id) { + /* the intra-prefix are directly connected */ + direct_connect = 1; + } + + prefix_num = ntohs(intra_prefix_lsa->prefix_num); + start = (caddr_t)intra_prefix_lsa + + sizeof(struct ospf6_intra_prefix_lsa); + end = OSPF6_LSA_END(lsa->header); + for (current = start; current < end; current += OSPF6_PREFIX_SIZE(op)) { + op = (struct ospf6_prefix *)current; + if (prefix_num == 0) + break; + if (end < current + OSPF6_PREFIX_SIZE(op)) + break; + + /* Appendix A.4.1.1 */ + if (CHECK_FLAG(op->prefix_options, OSPF6_PREFIX_OPTION_NU)) { + if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) { + ospf6_linkstate_prefix2str( + (struct prefix *)OSPF6_PREFIX_BODY(op), + buf, sizeof(buf)); + zlog_debug( + "%s: Skipping Prefix %s has NU option set", + __func__, buf); + } + continue; + } + + route = ospf6_route_create(); + + memset(&route->prefix, 0, sizeof(struct prefix)); + route->prefix.family = AF_INET6; + route->prefix.prefixlen = op->prefix_length; + ospf6_prefix_in6_addr(&route->prefix.u.prefix6, op); + + route->type = OSPF6_DEST_TYPE_NETWORK; + route->path.origin.type = lsa->header->type; + route->path.origin.id = lsa->header->id; + route->path.origin.adv_router = lsa->header->adv_router; + route->path.prefix_options = op->prefix_options; + route->path.area_id = oa->area_id; + route->path.type = OSPF6_PATH_TYPE_INTRA; + route->path.metric_type = 1; + route->path.cost = + ls_entry->path.cost + ntohs(op->prefix_metric); + + if (direct_connect) { + ifp = if_lookup_prefix(&route->prefix, VRF_DEFAULT); + if (ifp) + ospf6_route_add_nexthop(route, ifp->ifindex, + NULL); + } else { + ospf6_route_copy_nexthops(route, ls_entry); + } + + if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) { + prefix2str(&route->prefix, buf, sizeof(buf)); + zlog_debug(" add %s", buf); + } + + ospf6_route_add(route, oa->route_table); + prefix_num--; } - route = ospf6_route_create (); - - memset (&route->prefix, 0, sizeof (struct prefix)); - route->prefix.family = AF_INET6; - route->prefix.prefixlen = op->prefix_length; - ospf6_prefix_in6_addr (&route->prefix.u.prefix6, op); - - route->type = OSPF6_DEST_TYPE_NETWORK; - route->path.origin.type = lsa->header->type; - route->path.origin.id = lsa->header->id; - route->path.origin.adv_router = lsa->header->adv_router; - route->path.prefix_options = op->prefix_options; - route->path.area_id = oa->area_id; - route->path.type = OSPF6_PATH_TYPE_INTRA; - route->path.metric_type = 1; - route->path.cost = ls_entry->path.cost + - ntohs (op->prefix_metric); - - if (direct_connect) - { - ifp = if_lookup_prefix(&route->prefix, VRF_DEFAULT); - if (ifp) - ospf6_route_add_nexthop (route, ifp->ifindex, NULL); - } - else - { - ospf6_route_copy_nexthops (route, ls_entry); - } - - if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX)) - { - prefix2str (&route->prefix, buf, sizeof (buf)); - zlog_debug (" add %s", buf); - } - - ospf6_route_add (route, oa->route_table); - prefix_num--; - } - - if (current != end && IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX)) - zlog_debug ("Trailing garbage ignored"); + if (current != end && IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) + zlog_debug("Trailing garbage ignored"); } -void -ospf6_intra_prefix_lsa_remove (struct ospf6_lsa *lsa) +void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa *lsa) { - struct ospf6_area *oa; - struct ospf6_intra_prefix_lsa *intra_prefix_lsa; - struct prefix prefix; - struct ospf6_route *route, *nroute; - int prefix_num; - struct ospf6_prefix *op; - char *start, *current, *end; - char buf[PREFIX2STR_BUFFER]; - - if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX)) - zlog_debug ("%s disappearing", lsa->name); - - oa = OSPF6_AREA (lsa->lsdb->data); - - intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) - OSPF6_LSA_HEADER_END (lsa->header); - - prefix_num = ntohs (intra_prefix_lsa->prefix_num); - start = (caddr_t) intra_prefix_lsa + - sizeof (struct ospf6_intra_prefix_lsa); - end = OSPF6_LSA_END (lsa->header); - for (current = start; current < end; current += OSPF6_PREFIX_SIZE (op)) - { - op = (struct ospf6_prefix *) current; - if (prefix_num == 0) - break; - if (end < current + OSPF6_PREFIX_SIZE (op)) - break; - prefix_num--; - - memset (&prefix, 0, sizeof (struct prefix)); - prefix.family = AF_INET6; - prefix.prefixlen = op->prefix_length; - ospf6_prefix_in6_addr (&prefix.u.prefix6, op); - - route = ospf6_route_lookup (&prefix, oa->route_table); - if (route == NULL) - continue; - - for (ospf6_route_lock (route); - route && ospf6_route_is_prefix (&prefix, route); - route = nroute) - { - nroute = ospf6_route_next (route); - if (route->type != OSPF6_DEST_TYPE_NETWORK) - continue; - if (route->path.area_id != oa->area_id) - continue; - if (route->path.type != OSPF6_PATH_TYPE_INTRA) - continue; - if (route->path.origin.type != lsa->header->type || - route->path.origin.id != lsa->header->id || - route->path.origin.adv_router != lsa->header->adv_router) - continue; - - if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX)) - { - prefix2str (&route->prefix, buf, sizeof (buf)); - zlog_debug ("remove %s", buf); - } - ospf6_route_remove (route, oa->route_table); - } - if (route) - ospf6_route_unlock (route); - } - - if (current != end && IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX)) - zlog_debug ("Trailing garbage ignored"); + struct ospf6_area *oa; + struct ospf6_intra_prefix_lsa *intra_prefix_lsa; + struct prefix prefix; + struct ospf6_route *route, *nroute; + int prefix_num; + struct ospf6_prefix *op; + char *start, *current, *end; + char buf[PREFIX2STR_BUFFER]; + + if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) + zlog_debug("%s disappearing", lsa->name); + + oa = OSPF6_AREA(lsa->lsdb->data); + + intra_prefix_lsa = + (struct ospf6_intra_prefix_lsa *)OSPF6_LSA_HEADER_END( + lsa->header); + + prefix_num = ntohs(intra_prefix_lsa->prefix_num); + start = (caddr_t)intra_prefix_lsa + + sizeof(struct ospf6_intra_prefix_lsa); + end = OSPF6_LSA_END(lsa->header); + for (current = start; current < end; current += OSPF6_PREFIX_SIZE(op)) { + op = (struct ospf6_prefix *)current; + if (prefix_num == 0) + break; + if (end < current + OSPF6_PREFIX_SIZE(op)) + break; + prefix_num--; + + memset(&prefix, 0, sizeof(struct prefix)); + prefix.family = AF_INET6; + prefix.prefixlen = op->prefix_length; + ospf6_prefix_in6_addr(&prefix.u.prefix6, op); + + route = ospf6_route_lookup(&prefix, oa->route_table); + if (route == NULL) + continue; + + for (ospf6_route_lock(route); + route && ospf6_route_is_prefix(&prefix, route); + route = nroute) { + nroute = ospf6_route_next(route); + if (route->type != OSPF6_DEST_TYPE_NETWORK) + continue; + if (route->path.area_id != oa->area_id) + continue; + if (route->path.type != OSPF6_PATH_TYPE_INTRA) + continue; + if (route->path.origin.type != lsa->header->type + || route->path.origin.id != lsa->header->id + || route->path.origin.adv_router + != lsa->header->adv_router) + continue; + + if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) { + prefix2str(&route->prefix, buf, sizeof(buf)); + zlog_debug("remove %s", buf); + } + ospf6_route_remove(route, oa->route_table); + } + if (route) + ospf6_route_unlock(route); + } + + if (current != end && IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) + zlog_debug("Trailing garbage ignored"); } -void -ospf6_intra_route_calculation (struct ospf6_area *oa) +void ospf6_intra_route_calculation(struct ospf6_area *oa) { - struct ospf6_route *route, *nroute; - u_int16_t type; - struct ospf6_lsa *lsa; - void (*hook_add) (struct ospf6_route *) = NULL; - void (*hook_remove) (struct ospf6_route *) = NULL; - - if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX)) - zlog_debug ("Re-examin intra-routes for area %s", oa->name); - - hook_add = oa->route_table->hook_add; - hook_remove = oa->route_table->hook_remove; - oa->route_table->hook_add = NULL; - oa->route_table->hook_remove = NULL; - - for (route = ospf6_route_head (oa->route_table); route; - route = ospf6_route_next (route)) - route->flag = OSPF6_ROUTE_REMOVE; - - type = htons (OSPF6_LSTYPE_INTRA_PREFIX); - for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) - ospf6_intra_prefix_lsa_add (lsa); - - oa->route_table->hook_add = hook_add; - oa->route_table->hook_remove = hook_remove; - - for (route = ospf6_route_head (oa->route_table); route; - route = nroute) - { - nroute = ospf6_route_next (route); - if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) && - CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD)) - { - UNSET_FLAG (route->flag, OSPF6_ROUTE_REMOVE); - UNSET_FLAG (route->flag, OSPF6_ROUTE_ADD); - } - - if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE)) - ospf6_route_remove (route, oa->route_table); - else if (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) || - CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE)) - { - if (hook_add) - (*hook_add) (route); - route->flag = 0; - } - else - { - /* Redo the summaries as things might have changed */ - ospf6_abr_originate_summary (route); - route->flag = 0; + struct ospf6_route *route, *nroute; + u_int16_t type; + struct ospf6_lsa *lsa; + void (*hook_add)(struct ospf6_route *) = NULL; + void (*hook_remove)(struct ospf6_route *) = NULL; + + if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) + zlog_debug("Re-examin intra-routes for area %s", oa->name); + + hook_add = oa->route_table->hook_add; + hook_remove = oa->route_table->hook_remove; + oa->route_table->hook_add = NULL; + oa->route_table->hook_remove = NULL; + + for (route = ospf6_route_head(oa->route_table); route; + route = ospf6_route_next(route)) + route->flag = OSPF6_ROUTE_REMOVE; + + type = htons(OSPF6_LSTYPE_INTRA_PREFIX); + for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) + ospf6_intra_prefix_lsa_add(lsa); + + oa->route_table->hook_add = hook_add; + oa->route_table->hook_remove = hook_remove; + + for (route = ospf6_route_head(oa->route_table); route; route = nroute) { + nroute = ospf6_route_next(route); + if (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE) + && CHECK_FLAG(route->flag, OSPF6_ROUTE_ADD)) { + UNSET_FLAG(route->flag, OSPF6_ROUTE_REMOVE); + UNSET_FLAG(route->flag, OSPF6_ROUTE_ADD); + } + + if (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE)) + ospf6_route_remove(route, oa->route_table); + else if (CHECK_FLAG(route->flag, OSPF6_ROUTE_ADD) + || CHECK_FLAG(route->flag, OSPF6_ROUTE_CHANGE)) { + if (hook_add) + (*hook_add)(route); + route->flag = 0; + } else { + /* Redo the summaries as things might have changed */ + ospf6_abr_originate_summary(route); + route->flag = 0; + } } - } - if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX)) - zlog_debug ("Re-examin intra-routes for area %s: Done", oa->name); + if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) + zlog_debug("Re-examin intra-routes for area %s: Done", + oa->name); } -static void -ospf6_brouter_debug_print (struct ospf6_route *brouter) +static void ospf6_brouter_debug_print(struct ospf6_route *brouter) { - u_int32_t brouter_id; - char brouter_name[16]; - char area_name[16]; - char destination[64]; - char installed[16], changed[16]; - struct timeval now, res; - char id[16], adv_router[16]; - char capa[16], options[16]; - - brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix); - inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name)); - inet_ntop (AF_INET, &brouter->path.area_id, area_name, sizeof (area_name)); - ospf6_linkstate_prefix2str (&brouter->prefix, destination, - sizeof (destination)); - - monotime(&now); - timersub (&now, &brouter->installed, &res); - timerstring (&res, installed, sizeof (installed)); - - monotime(&now); - timersub (&now, &brouter->changed, &res); - timerstring (&res, changed, sizeof (changed)); - - inet_ntop (AF_INET, &brouter->path.origin.id, id, sizeof (id)); - inet_ntop (AF_INET, &brouter->path.origin.adv_router, adv_router, - sizeof (adv_router)); - - ospf6_options_printbuf (brouter->path.options, options, sizeof (options)); - ospf6_capability_printbuf (brouter->path.router_bits, capa, sizeof (capa)); - - zlog_info ("Brouter: %s via area %s", brouter_name, area_name); - zlog_info (" memory: prev: %p this: %p next: %p parent rnode: %p", - (void *)brouter->prev, (void *)brouter, (void *)brouter->next, - (void *)brouter->rnode); - zlog_info (" type: %d prefix: %s installed: %s changed: %s", - brouter->type, destination, installed, changed); - zlog_info (" lock: %d flags: %s%s%s%s", brouter->lock, - (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_BEST) ? "B" : "-"), - (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_ADD) ? "A" : "-"), - (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"), - (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-")); - zlog_info (" path type: %s ls-origin %s id: %s adv-router %s", - OSPF6_PATH_TYPE_NAME (brouter->path.type), - ospf6_lstype_name (brouter->path.origin.type), - id, adv_router); - zlog_info (" options: %s router-bits: %s metric-type: %d metric: %d/%d", - options, capa, brouter->path.metric_type, - brouter->path.cost, brouter->path.u.cost_e2); + u_int32_t brouter_id; + char brouter_name[16]; + char area_name[16]; + char destination[64]; + char installed[16], changed[16]; + struct timeval now, res; + char id[16], adv_router[16]; + char capa[16], options[16]; + + brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix); + inet_ntop(AF_INET, &brouter_id, brouter_name, sizeof(brouter_name)); + inet_ntop(AF_INET, &brouter->path.area_id, area_name, + sizeof(area_name)); + ospf6_linkstate_prefix2str(&brouter->prefix, destination, + sizeof(destination)); + + monotime(&now); + timersub(&now, &brouter->installed, &res); + timerstring(&res, installed, sizeof(installed)); + + monotime(&now); + timersub(&now, &brouter->changed, &res); + timerstring(&res, changed, sizeof(changed)); + + inet_ntop(AF_INET, &brouter->path.origin.id, id, sizeof(id)); + inet_ntop(AF_INET, &brouter->path.origin.adv_router, adv_router, + sizeof(adv_router)); + + ospf6_options_printbuf(brouter->path.options, options, sizeof(options)); + ospf6_capability_printbuf(brouter->path.router_bits, capa, + sizeof(capa)); + + zlog_info("Brouter: %s via area %s", brouter_name, area_name); + zlog_info(" memory: prev: %p this: %p next: %p parent rnode: %p", + (void *)brouter->prev, (void *)brouter, (void *)brouter->next, + (void *)brouter->rnode); + zlog_info(" type: %d prefix: %s installed: %s changed: %s", + brouter->type, destination, installed, changed); + zlog_info(" lock: %d flags: %s%s%s%s", brouter->lock, + (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_BEST) ? "B" : "-"), + (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_ADD) ? "A" : "-"), + (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"), + (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-")); + zlog_info(" path type: %s ls-origin %s id: %s adv-router %s", + OSPF6_PATH_TYPE_NAME(brouter->path.type), + ospf6_lstype_name(brouter->path.origin.type), id, adv_router); + zlog_info(" options: %s router-bits: %s metric-type: %d metric: %d/%d", + options, capa, brouter->path.metric_type, brouter->path.cost, + brouter->path.u.cost_e2); } -void -ospf6_intra_brouter_calculation (struct ospf6_area *oa) +void ospf6_intra_brouter_calculation(struct ospf6_area *oa) { - struct ospf6_route *brouter, *nbrouter, *copy; - void (*hook_add) (struct ospf6_route *) = NULL; - void (*hook_remove) (struct ospf6_route *) = NULL; - u_int32_t brouter_id; - char brouter_name[16]; - - if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id)) - zlog_info ("border-router calculation for area %s", oa->name); - - hook_add = oa->ospf6->brouter_table->hook_add; - hook_remove = oa->ospf6->brouter_table->hook_remove; - oa->ospf6->brouter_table->hook_add = NULL; - oa->ospf6->brouter_table->hook_remove = NULL; - - /* withdraw the previous router entries for the area */ - for (brouter = ospf6_route_head (oa->ospf6->brouter_table); brouter; - brouter = ospf6_route_next (brouter)) - { - brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix); - inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name)); - if (brouter->path.area_id != oa->area_id) - continue; - SET_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE); - - if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) || - IS_OSPF6_DEBUG_ROUTE (MEMORY)) - { - zlog_info ("%p: mark as removing: area %s brouter %s", - (void *)brouter, oa->name, brouter_name); - ospf6_brouter_debug_print (brouter); - } - } - - for (brouter = ospf6_route_head (oa->spf_table); brouter; - brouter = ospf6_route_next (brouter)) - { - brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix); - inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name)); - - if (brouter->type != OSPF6_DEST_TYPE_LINKSTATE) - continue; - if (ospf6_linkstate_prefix_id (&brouter->prefix) != htonl (0)) - continue; - if (! CHECK_FLAG (brouter->path.router_bits, OSPF6_ROUTER_BIT_E) && - ! CHECK_FLAG (brouter->path.router_bits, OSPF6_ROUTER_BIT_B)) - continue; - - if (! OSPF6_OPT_ISSET (brouter->path.options, OSPF6_OPT_V6) || - ! OSPF6_OPT_ISSET (brouter->path.options, OSPF6_OPT_R)) - continue; - - copy = ospf6_route_copy (brouter); - copy->type = OSPF6_DEST_TYPE_ROUTER; - copy->path.area_id = oa->area_id; - ospf6_route_add (copy, oa->ospf6->brouter_table); - - if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) || - IS_OSPF6_DEBUG_ROUTE (MEMORY)) - { - zlog_info ("%p: transfer: area %s brouter %s", - (void *)brouter, oa->name, brouter_name); - ospf6_brouter_debug_print (brouter); - } - } - - oa->ospf6->brouter_table->hook_add = hook_add; - oa->ospf6->brouter_table->hook_remove = hook_remove; - - for (brouter = ospf6_route_head (oa->ospf6->brouter_table); brouter; - brouter = nbrouter) - { - nbrouter = ospf6_route_next (brouter); - brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix); - inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name)); - - if (brouter->path.area_id != oa->area_id) - continue; - - if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_WAS_REMOVED)) - continue; - - if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE) && - CHECK_FLAG (brouter->flag, OSPF6_ROUTE_ADD)) - { - UNSET_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE); - UNSET_FLAG (brouter->flag, OSPF6_ROUTE_ADD); - } - - if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE)) - { - if (IS_OSPF6_DEBUG_BROUTER || - IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) || - IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id)) - zlog_info ("brouter %s disappears via area %s", - brouter_name, oa->name); - ospf6_route_remove (brouter, oa->ospf6->brouter_table); - brouter = NULL; - } - else if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_ADD) || - CHECK_FLAG (brouter->flag, OSPF6_ROUTE_CHANGE)) - { - if (IS_OSPF6_DEBUG_BROUTER || - IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) || - IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id)) - zlog_info ("brouter %s appears via area %s", - brouter_name, oa->name); - - /* newly added */ - if (hook_add) - (*hook_add) (brouter); - } - else - { - if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) || - IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id)) - zlog_info ("brouter %s still exists via area %s", - brouter_name, oa->name); - /* But re-originate summaries */ - ospf6_abr_originate_summary (brouter); - } - - if (brouter) - { - UNSET_FLAG (brouter->flag, OSPF6_ROUTE_ADD); - UNSET_FLAG (brouter->flag, OSPF6_ROUTE_CHANGE); - } - } - - if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id)) - zlog_info ("border-router calculation for area %s: done", oa->name); + struct ospf6_route *brouter, *nbrouter, *copy; + void (*hook_add)(struct ospf6_route *) = NULL; + void (*hook_remove)(struct ospf6_route *) = NULL; + u_int32_t brouter_id; + char brouter_name[16]; + + if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa->area_id)) + zlog_info("border-router calculation for area %s", oa->name); + + hook_add = oa->ospf6->brouter_table->hook_add; + hook_remove = oa->ospf6->brouter_table->hook_remove; + oa->ospf6->brouter_table->hook_add = NULL; + oa->ospf6->brouter_table->hook_remove = NULL; + + /* withdraw the previous router entries for the area */ + for (brouter = ospf6_route_head(oa->ospf6->brouter_table); brouter; + brouter = ospf6_route_next(brouter)) { + brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix); + inet_ntop(AF_INET, &brouter_id, brouter_name, + sizeof(brouter_name)); + if (brouter->path.area_id != oa->area_id) + continue; + SET_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE); + + if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id) + || IS_OSPF6_DEBUG_ROUTE(MEMORY)) { + zlog_info("%p: mark as removing: area %s brouter %s", + (void *)brouter, oa->name, brouter_name); + ospf6_brouter_debug_print(brouter); + } + } + + for (brouter = ospf6_route_head(oa->spf_table); brouter; + brouter = ospf6_route_next(brouter)) { + brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix); + inet_ntop(AF_INET, &brouter_id, brouter_name, + sizeof(brouter_name)); + + if (brouter->type != OSPF6_DEST_TYPE_LINKSTATE) + continue; + if (ospf6_linkstate_prefix_id(&brouter->prefix) != htonl(0)) + continue; + if (!CHECK_FLAG(brouter->path.router_bits, OSPF6_ROUTER_BIT_E) + && !CHECK_FLAG(brouter->path.router_bits, + OSPF6_ROUTER_BIT_B)) + continue; + + if (!OSPF6_OPT_ISSET(brouter->path.options, OSPF6_OPT_V6) + || !OSPF6_OPT_ISSET(brouter->path.options, OSPF6_OPT_R)) + continue; + + copy = ospf6_route_copy(brouter); + copy->type = OSPF6_DEST_TYPE_ROUTER; + copy->path.area_id = oa->area_id; + ospf6_route_add(copy, oa->ospf6->brouter_table); + + if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id) + || IS_OSPF6_DEBUG_ROUTE(MEMORY)) { + zlog_info("%p: transfer: area %s brouter %s", + (void *)brouter, oa->name, brouter_name); + ospf6_brouter_debug_print(brouter); + } + } + + oa->ospf6->brouter_table->hook_add = hook_add; + oa->ospf6->brouter_table->hook_remove = hook_remove; + + for (brouter = ospf6_route_head(oa->ospf6->brouter_table); brouter; + brouter = nbrouter) { + nbrouter = ospf6_route_next(brouter); + brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix); + inet_ntop(AF_INET, &brouter_id, brouter_name, + sizeof(brouter_name)); + + if (brouter->path.area_id != oa->area_id) + continue; + + if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_WAS_REMOVED)) + continue; + + if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE) + && CHECK_FLAG(brouter->flag, OSPF6_ROUTE_ADD)) { + UNSET_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE); + UNSET_FLAG(brouter->flag, OSPF6_ROUTE_ADD); + } + + if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE)) { + if (IS_OSPF6_DEBUG_BROUTER + || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID( + brouter_id) + || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID( + oa->area_id)) + zlog_info("brouter %s disappears via area %s", + brouter_name, oa->name); + ospf6_route_remove(brouter, oa->ospf6->brouter_table); + brouter = NULL; + } else if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_ADD) + || CHECK_FLAG(brouter->flag, OSPF6_ROUTE_CHANGE)) { + if (IS_OSPF6_DEBUG_BROUTER + || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID( + brouter_id) + || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID( + oa->area_id)) + zlog_info("brouter %s appears via area %s", + brouter_name, oa->name); + + /* newly added */ + if (hook_add) + (*hook_add)(brouter); + } else { + if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID( + brouter_id) + || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID( + oa->area_id)) + zlog_info("brouter %s still exists via area %s", + brouter_name, oa->name); + /* But re-originate summaries */ + ospf6_abr_originate_summary(brouter); + } + + if (brouter) { + UNSET_FLAG(brouter->flag, OSPF6_ROUTE_ADD); + UNSET_FLAG(brouter->flag, OSPF6_ROUTE_CHANGE); + } + } + + if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa->area_id)) + zlog_info("border-router calculation for area %s: done", + oa->name); } -struct ospf6_lsa_handler router_handler = -{ - OSPF6_LSTYPE_ROUTER, - "Router", - "Rtr", - ospf6_router_lsa_show, - ospf6_router_lsa_get_nbr_id -}; - -struct ospf6_lsa_handler network_handler = -{ - OSPF6_LSTYPE_NETWORK, - "Network", - "Net", - ospf6_network_lsa_show, - ospf6_network_lsa_get_ar_id -}; - -struct ospf6_lsa_handler link_handler = -{ - OSPF6_LSTYPE_LINK, - "Link", - "Lnk", - ospf6_link_lsa_show, - ospf6_link_lsa_get_prefix_str -}; - -struct ospf6_lsa_handler intra_prefix_handler = -{ - OSPF6_LSTYPE_INTRA_PREFIX, - "Intra-Prefix", - "INP", - ospf6_intra_prefix_lsa_show, - ospf6_intra_prefix_lsa_get_prefix_str -}; - -void -ospf6_intra_init (void) +struct ospf6_lsa_handler router_handler = {OSPF6_LSTYPE_ROUTER, "Router", "Rtr", + ospf6_router_lsa_show, + ospf6_router_lsa_get_nbr_id}; + +struct ospf6_lsa_handler network_handler = {OSPF6_LSTYPE_NETWORK, "Network", + "Net", ospf6_network_lsa_show, + ospf6_network_lsa_get_ar_id}; + +struct ospf6_lsa_handler link_handler = {OSPF6_LSTYPE_LINK, "Link", "Lnk", + ospf6_link_lsa_show, + ospf6_link_lsa_get_prefix_str}; + +struct ospf6_lsa_handler intra_prefix_handler = { + OSPF6_LSTYPE_INTRA_PREFIX, "Intra-Prefix", "INP", + ospf6_intra_prefix_lsa_show, ospf6_intra_prefix_lsa_get_prefix_str}; + +void ospf6_intra_init(void) { - ospf6_install_lsa_handler (&router_handler); - ospf6_install_lsa_handler (&network_handler); - ospf6_install_lsa_handler (&link_handler); - ospf6_install_lsa_handler (&intra_prefix_handler); + ospf6_install_lsa_handler(&router_handler); + ospf6_install_lsa_handler(&network_handler); + ospf6_install_lsa_handler(&link_handler); + ospf6_install_lsa_handler(&intra_prefix_handler); } DEFUN (debug_ospf6_brouter, @@ -1704,8 +1649,8 @@ DEFUN (debug_ospf6_brouter, "Debug border router\n" ) { - OSPF6_DEBUG_BROUTER_ON (); - return CMD_SUCCESS; + OSPF6_DEBUG_BROUTER_ON(); + return CMD_SUCCESS; } DEFUN (no_debug_ospf6_brouter, @@ -1717,8 +1662,8 @@ DEFUN (no_debug_ospf6_brouter, "Debug border router\n" ) { - OSPF6_DEBUG_BROUTER_OFF (); - return CMD_SUCCESS; + OSPF6_DEBUG_BROUTER_OFF(); + return CMD_SUCCESS; } DEFUN (debug_ospf6_brouter_router, @@ -1731,11 +1676,11 @@ DEFUN (debug_ospf6_brouter_router, "Specify border-router's router-id\n" ) { - int idx_ipv4 = 4; - u_int32_t router_id; - inet_pton (AF_INET, argv[idx_ipv4]->arg, &router_id); - OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ON (router_id); - return CMD_SUCCESS; + int idx_ipv4 = 4; + u_int32_t router_id; + inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id); + OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ON(router_id); + return CMD_SUCCESS; } DEFUN (no_debug_ospf6_brouter_router, @@ -1748,8 +1693,8 @@ DEFUN (no_debug_ospf6_brouter_router, "Debug specific border router\n" ) { - OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF (); - return CMD_SUCCESS; + OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF(); + return CMD_SUCCESS; } DEFUN (debug_ospf6_brouter_area, @@ -1762,11 +1707,11 @@ DEFUN (debug_ospf6_brouter_area, "Specify Area-ID\n" ) { - int idx_ipv4 = 4; - u_int32_t area_id; - inet_pton (AF_INET, argv[idx_ipv4]->arg, &area_id); - OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ON (area_id); - return CMD_SUCCESS; + int idx_ipv4 = 4; + u_int32_t area_id; + inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id); + OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ON(area_id); + return CMD_SUCCESS; } DEFUN (no_debug_ospf6_brouter_area, @@ -1779,46 +1724,40 @@ DEFUN (no_debug_ospf6_brouter_area, "Debug border routers in specific Area\n" ) { - OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF (); - return CMD_SUCCESS; + OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF(); + return CMD_SUCCESS; } -int -config_write_ospf6_debug_brouter (struct vty *vty) +int config_write_ospf6_debug_brouter(struct vty *vty) { - char buf[16]; - if (IS_OSPF6_DEBUG_BROUTER) - vty_out (vty, "debug ospf6 border-routers\n"); - if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER) - { - inet_ntop (AF_INET, &conf_debug_ospf6_brouter_specific_router_id, - buf, sizeof (buf)); - vty_out (vty, "debug ospf6 border-routers router-id %s\n", buf); - } - if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA) - { - inet_ntop (AF_INET, &conf_debug_ospf6_brouter_specific_area_id, - buf, sizeof (buf)); - vty_out (vty, "debug ospf6 border-routers area-id %s\n", buf); - } - return 0; + char buf[16]; + if (IS_OSPF6_DEBUG_BROUTER) + vty_out(vty, "debug ospf6 border-routers\n"); + if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER) { + inet_ntop(AF_INET, &conf_debug_ospf6_brouter_specific_router_id, + buf, sizeof(buf)); + vty_out(vty, "debug ospf6 border-routers router-id %s\n", buf); + } + if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA) { + inet_ntop(AF_INET, &conf_debug_ospf6_brouter_specific_area_id, + buf, sizeof(buf)); + vty_out(vty, "debug ospf6 border-routers area-id %s\n", buf); + } + return 0; } -void -install_element_ospf6_debug_brouter (void) +void install_element_ospf6_debug_brouter(void) { - install_element (ENABLE_NODE, &debug_ospf6_brouter_cmd); - install_element (ENABLE_NODE, &debug_ospf6_brouter_router_cmd); - install_element (ENABLE_NODE, &debug_ospf6_brouter_area_cmd); - install_element (ENABLE_NODE, &no_debug_ospf6_brouter_cmd); - install_element (ENABLE_NODE, &no_debug_ospf6_brouter_router_cmd); - install_element (ENABLE_NODE, &no_debug_ospf6_brouter_area_cmd); - install_element (CONFIG_NODE, &debug_ospf6_brouter_cmd); - install_element (CONFIG_NODE, &debug_ospf6_brouter_router_cmd); - install_element (CONFIG_NODE, &debug_ospf6_brouter_area_cmd); - install_element (CONFIG_NODE, &no_debug_ospf6_brouter_cmd); - install_element (CONFIG_NODE, &no_debug_ospf6_brouter_router_cmd); - install_element (CONFIG_NODE, &no_debug_ospf6_brouter_area_cmd); + install_element(ENABLE_NODE, &debug_ospf6_brouter_cmd); + install_element(ENABLE_NODE, &debug_ospf6_brouter_router_cmd); + install_element(ENABLE_NODE, &debug_ospf6_brouter_area_cmd); + install_element(ENABLE_NODE, &no_debug_ospf6_brouter_cmd); + install_element(ENABLE_NODE, &no_debug_ospf6_brouter_router_cmd); + install_element(ENABLE_NODE, &no_debug_ospf6_brouter_area_cmd); + install_element(CONFIG_NODE, &debug_ospf6_brouter_cmd); + install_element(CONFIG_NODE, &debug_ospf6_brouter_router_cmd); + install_element(CONFIG_NODE, &debug_ospf6_brouter_area_cmd); + install_element(CONFIG_NODE, &no_debug_ospf6_brouter_cmd); + install_element(CONFIG_NODE, &no_debug_ospf6_brouter_router_cmd); + install_element(CONFIG_NODE, &no_debug_ospf6_brouter_area_cmd); } - - diff --git a/ospf6d/ospf6_intra.h b/ospf6d/ospf6_intra.h index 114784835..b511a9200 100644 --- a/ospf6d/ospf6_intra.h +++ b/ospf6d/ospf6_intra.h @@ -28,64 +28,65 @@ extern u_int32_t conf_debug_ospf6_brouter_specific_area_id; #define OSPF6_DEBUG_BROUTER_SUMMARY 0x01 #define OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER 0x02 #define OSPF6_DEBUG_BROUTER_SPECIFIC_AREA 0x04 -#define OSPF6_DEBUG_BROUTER_ON() \ - (conf_debug_ospf6_brouter |= OSPF6_DEBUG_BROUTER_SUMMARY) -#define OSPF6_DEBUG_BROUTER_OFF() \ - (conf_debug_ospf6_brouter &= ~OSPF6_DEBUG_BROUTER_SUMMARY) -#define IS_OSPF6_DEBUG_BROUTER \ - (conf_debug_ospf6_brouter & OSPF6_DEBUG_BROUTER_SUMMARY) - -#define OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ON(router_id) \ - do { \ - conf_debug_ospf6_brouter_specific_router_id = (router_id); \ - conf_debug_ospf6_brouter |= OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER; \ - } while (0) -#define OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF() \ - do { \ - conf_debug_ospf6_brouter_specific_router_id = 0; \ - conf_debug_ospf6_brouter &= ~OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER; \ - } while (0) -#define IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER \ - (conf_debug_ospf6_brouter & OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER) -#define IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(router_id) \ - (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER && \ - conf_debug_ospf6_brouter_specific_router_id == (router_id)) - -#define OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ON(area_id) \ - do { \ - conf_debug_ospf6_brouter_specific_area_id = (area_id); \ - conf_debug_ospf6_brouter |= OSPF6_DEBUG_BROUTER_SPECIFIC_AREA; \ - } while (0) -#define OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF() \ - do { \ - conf_debug_ospf6_brouter_specific_area_id = 0; \ - conf_debug_ospf6_brouter &= ~OSPF6_DEBUG_BROUTER_SPECIFIC_AREA; \ - } while (0) -#define IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA \ - (conf_debug_ospf6_brouter & OSPF6_DEBUG_BROUTER_SPECIFIC_AREA) -#define IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(area_id) \ - (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA && \ - conf_debug_ospf6_brouter_specific_area_id == (area_id)) +#define OSPF6_DEBUG_BROUTER_ON() \ + (conf_debug_ospf6_brouter |= OSPF6_DEBUG_BROUTER_SUMMARY) +#define OSPF6_DEBUG_BROUTER_OFF() \ + (conf_debug_ospf6_brouter &= ~OSPF6_DEBUG_BROUTER_SUMMARY) +#define IS_OSPF6_DEBUG_BROUTER \ + (conf_debug_ospf6_brouter & OSPF6_DEBUG_BROUTER_SUMMARY) + +#define OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ON(router_id) \ + do { \ + conf_debug_ospf6_brouter_specific_router_id = (router_id); \ + conf_debug_ospf6_brouter |= \ + OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER; \ + } while (0) +#define OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF() \ + do { \ + conf_debug_ospf6_brouter_specific_router_id = 0; \ + conf_debug_ospf6_brouter &= \ + ~OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER; \ + } while (0) +#define IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER \ + (conf_debug_ospf6_brouter & OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER) +#define IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(router_id) \ + (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER \ + && conf_debug_ospf6_brouter_specific_router_id == (router_id)) + +#define OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ON(area_id) \ + do { \ + conf_debug_ospf6_brouter_specific_area_id = (area_id); \ + conf_debug_ospf6_brouter |= OSPF6_DEBUG_BROUTER_SPECIFIC_AREA; \ + } while (0) +#define OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF() \ + do { \ + conf_debug_ospf6_brouter_specific_area_id = 0; \ + conf_debug_ospf6_brouter &= \ + ~OSPF6_DEBUG_BROUTER_SPECIFIC_AREA; \ + } while (0) +#define IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA \ + (conf_debug_ospf6_brouter & OSPF6_DEBUG_BROUTER_SPECIFIC_AREA) +#define IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(area_id) \ + (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA \ + && conf_debug_ospf6_brouter_specific_area_id == (area_id)) /* Router-LSA */ #define OSPF6_ROUTER_LSA_MIN_SIZE 4U -struct ospf6_router_lsa -{ - u_char bits; - u_char options[3]; - /* followed by ospf6_router_lsdesc(s) */ +struct ospf6_router_lsa { + u_char bits; + u_char options[3]; + /* followed by ospf6_router_lsdesc(s) */ }; /* Link State Description in Router-LSA */ #define OSPF6_ROUTER_LSDESC_FIX_SIZE 16U -struct ospf6_router_lsdesc -{ - u_char type; - u_char reserved; - u_int16_t metric; /* output cost */ - u_int32_t interface_id; - u_int32_t neighbor_interface_id; - u_int32_t neighbor_router_id; +struct ospf6_router_lsdesc { + u_char type; + u_char reserved; + u_int16_t metric; /* output cost */ + u_int32_t interface_id; + u_int32_t neighbor_interface_id; + u_int32_t neighbor_router_id; }; #define OSPF6_ROUTER_LSDESC_POINTTOPOINT 1 @@ -93,130 +94,134 @@ struct ospf6_router_lsdesc #define OSPF6_ROUTER_LSDESC_STUB_NETWORK 3 #define OSPF6_ROUTER_LSDESC_VIRTUAL_LINK 4 -enum stub_router_mode - { - OSPF6_NOT_STUB_ROUTER, - OSPF6_IS_STUB_ROUTER, - OSPF6_IS_STUB_ROUTER_V6, - }; - -#define ROUTER_LSDESC_IS_TYPE(t,x) \ - ((((struct ospf6_router_lsdesc *)(x))->type == \ - OSPF6_ROUTER_LSDESC_ ## t) ? 1 : 0) -#define ROUTER_LSDESC_GET_METRIC(x) \ - (ntohs (((struct ospf6_router_lsdesc *)(x))->metric)) -#define ROUTER_LSDESC_GET_IFID(x) \ - (ntohl (((struct ospf6_router_lsdesc *)(x))->interface_id)) -#define ROUTER_LSDESC_GET_NBR_IFID(x) \ - (ntohl (((struct ospf6_router_lsdesc *)(x))->neighbor_interface_id)) -#define ROUTER_LSDESC_GET_NBR_ROUTERID(x) \ - (((struct ospf6_router_lsdesc *)(x))->neighbor_router_id) +enum stub_router_mode { + OSPF6_NOT_STUB_ROUTER, + OSPF6_IS_STUB_ROUTER, + OSPF6_IS_STUB_ROUTER_V6, +}; + +#define ROUTER_LSDESC_IS_TYPE(t, x) \ + ((((struct ospf6_router_lsdesc *)(x))->type \ + == OSPF6_ROUTER_LSDESC_##t) \ + ? 1 \ + : 0) +#define ROUTER_LSDESC_GET_METRIC(x) \ + (ntohs(((struct ospf6_router_lsdesc *)(x))->metric)) +#define ROUTER_LSDESC_GET_IFID(x) \ + (ntohl(((struct ospf6_router_lsdesc *)(x))->interface_id)) +#define ROUTER_LSDESC_GET_NBR_IFID(x) \ + (ntohl(((struct ospf6_router_lsdesc *)(x))->neighbor_interface_id)) +#define ROUTER_LSDESC_GET_NBR_ROUTERID(x) \ + (((struct ospf6_router_lsdesc *)(x))->neighbor_router_id) /* Network-LSA */ #define OSPF6_NETWORK_LSA_MIN_SIZE 4U -struct ospf6_network_lsa -{ - u_char reserved; - u_char options[3]; - /* followed by ospf6_netowrk_lsd(s) */ +struct ospf6_network_lsa { + u_char reserved; + u_char options[3]; + /* followed by ospf6_netowrk_lsd(s) */ }; /* Link State Description in Router-LSA */ #define OSPF6_NETWORK_LSDESC_FIX_SIZE 4U -struct ospf6_network_lsdesc -{ - u_int32_t router_id; +struct ospf6_network_lsdesc { + u_int32_t router_id; }; -#define NETWORK_LSDESC_GET_NBR_ROUTERID(x) \ - (((struct ospf6_network_lsdesc *)(x))->router_id) +#define NETWORK_LSDESC_GET_NBR_ROUTERID(x) \ + (((struct ospf6_network_lsdesc *)(x))->router_id) /* Link-LSA */ #define OSPF6_LINK_LSA_MIN_SIZE 24U /* w/o 1st IPv6 prefix */ -struct ospf6_link_lsa -{ - u_char priority; - u_char options[3]; - struct in6_addr linklocal_addr; - u_int32_t prefix_num; - /* followed by ospf6 prefix(es) */ +struct ospf6_link_lsa { + u_char priority; + u_char options[3]; + struct in6_addr linklocal_addr; + u_int32_t prefix_num; + /* followed by ospf6 prefix(es) */ }; /* Intra-Area-Prefix-LSA */ #define OSPF6_INTRA_PREFIX_LSA_MIN_SIZE 12U /* w/o 1st IPv6 prefix */ -struct ospf6_intra_prefix_lsa -{ - u_int16_t prefix_num; - u_int16_t ref_type; - u_int32_t ref_id; - u_int32_t ref_adv_router; - /* followed by ospf6 prefix(es) */ +struct ospf6_intra_prefix_lsa { + u_int16_t prefix_num; + u_int16_t ref_type; + u_int32_t ref_id; + u_int32_t ref_adv_router; + /* followed by ospf6 prefix(es) */ }; -#define OSPF6_ROUTER_LSA_SCHEDULE(oa) \ - do { \ - if (CHECK_FLAG((oa)->flag, OSPF6_AREA_ENABLE)) \ - thread_add_event (master, ospf6_router_lsa_originate, oa, 0, &(oa)->thread_router_lsa); \ - } while (0) -#define OSPF6_NETWORK_LSA_SCHEDULE(oi) \ - do { \ - if (!CHECK_FLAG((oi)->flag, OSPF6_INTERFACE_DISABLE)) \ - thread_add_event (master, ospf6_network_lsa_originate, oi, 0, &(oi)->thread_network_lsa); \ - } while (0) -#define OSPF6_LINK_LSA_SCHEDULE(oi) \ - do { \ - if (!CHECK_FLAG((oi)->flag, OSPF6_INTERFACE_DISABLE)) \ - thread_add_event (master, ospf6_link_lsa_originate, oi, 0, &(oi)->thread_link_lsa); \ - } while (0) -#define OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oa) \ - do { \ - if (CHECK_FLAG((oa)->flag, OSPF6_AREA_ENABLE)) \ - thread_add_event (master, ospf6_intra_prefix_lsa_originate_stub, \ - oa, 0, &(oa)->thread_intra_prefix_lsa); \ - } while (0) -#define OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi) \ - do { \ - if (!CHECK_FLAG((oi)->flag, OSPF6_INTERFACE_DISABLE)) \ - thread_add_event (master, ospf6_intra_prefix_lsa_originate_transit, \ - oi, 0, &(oi)->thread_intra_prefix_lsa); \ - } while (0) - -#define OSPF6_NETWORK_LSA_EXECUTE(oi) \ - do { \ - THREAD_OFF ((oi)->thread_network_lsa); \ - thread_execute (master, ospf6_network_lsa_originate, oi, 0); \ - } while (0) -#define OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi) \ - do { \ - THREAD_OFF ((oi)->thread_intra_prefix_lsa); \ - thread_execute (master, ospf6_intra_prefix_lsa_originate_transit, oi, 0); \ - } while (0) +#define OSPF6_ROUTER_LSA_SCHEDULE(oa) \ + do { \ + if (CHECK_FLAG((oa)->flag, OSPF6_AREA_ENABLE)) \ + thread_add_event(master, ospf6_router_lsa_originate, \ + oa, 0, &(oa)->thread_router_lsa); \ + } while (0) +#define OSPF6_NETWORK_LSA_SCHEDULE(oi) \ + do { \ + if (!CHECK_FLAG((oi)->flag, OSPF6_INTERFACE_DISABLE)) \ + thread_add_event(master, ospf6_network_lsa_originate, \ + oi, 0, &(oi)->thread_network_lsa); \ + } while (0) +#define OSPF6_LINK_LSA_SCHEDULE(oi) \ + do { \ + if (!CHECK_FLAG((oi)->flag, OSPF6_INTERFACE_DISABLE)) \ + thread_add_event(master, ospf6_link_lsa_originate, oi, \ + 0, &(oi)->thread_link_lsa); \ + } while (0) +#define OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oa) \ + do { \ + if (CHECK_FLAG((oa)->flag, OSPF6_AREA_ENABLE)) \ + thread_add_event( \ + master, ospf6_intra_prefix_lsa_originate_stub, \ + oa, 0, &(oa)->thread_intra_prefix_lsa); \ + } while (0) +#define OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi) \ + do { \ + if (!CHECK_FLAG((oi)->flag, OSPF6_INTERFACE_DISABLE)) \ + thread_add_event( \ + master, \ + ospf6_intra_prefix_lsa_originate_transit, oi, \ + 0, &(oi)->thread_intra_prefix_lsa); \ + } while (0) + +#define OSPF6_NETWORK_LSA_EXECUTE(oi) \ + do { \ + THREAD_OFF((oi)->thread_network_lsa); \ + thread_execute(master, ospf6_network_lsa_originate, oi, 0); \ + } while (0) +#define OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi) \ + do { \ + THREAD_OFF((oi)->thread_intra_prefix_lsa); \ + thread_execute(master, \ + ospf6_intra_prefix_lsa_originate_transit, oi, \ + 0); \ + } while (0) /* Function Prototypes */ -extern char *ospf6_router_lsdesc_lookup (u_char type, u_int32_t interface_id, - u_int32_t neighbor_interface_id, - u_int32_t neighbor_router_id, - struct ospf6_lsa *lsa); -extern char *ospf6_network_lsdesc_lookup (u_int32_t router_id, - struct ospf6_lsa *lsa); - -extern int ospf6_router_is_stub_router (struct ospf6_lsa *lsa); -extern int ospf6_router_lsa_originate (struct thread *); -extern int ospf6_network_lsa_originate (struct thread *); -extern int ospf6_link_lsa_originate (struct thread *); -extern int ospf6_intra_prefix_lsa_originate_transit (struct thread *); -extern int ospf6_intra_prefix_lsa_originate_stub (struct thread *); -extern void ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa); -extern void ospf6_intra_prefix_lsa_remove (struct ospf6_lsa *lsa); - -extern void ospf6_intra_route_calculation (struct ospf6_area *oa); -extern void ospf6_intra_brouter_calculation (struct ospf6_area *oa); - -extern void ospf6_intra_init (void); - -extern int config_write_ospf6_debug_brouter (struct vty *vty); -extern void install_element_ospf6_debug_brouter (void); +extern char *ospf6_router_lsdesc_lookup(u_char type, u_int32_t interface_id, + u_int32_t neighbor_interface_id, + u_int32_t neighbor_router_id, + struct ospf6_lsa *lsa); +extern char *ospf6_network_lsdesc_lookup(u_int32_t router_id, + struct ospf6_lsa *lsa); + +extern int ospf6_router_is_stub_router(struct ospf6_lsa *lsa); +extern int ospf6_router_lsa_originate(struct thread *); +extern int ospf6_network_lsa_originate(struct thread *); +extern int ospf6_link_lsa_originate(struct thread *); +extern int ospf6_intra_prefix_lsa_originate_transit(struct thread *); +extern int ospf6_intra_prefix_lsa_originate_stub(struct thread *); +extern void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa); +extern void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa *lsa); + +extern void ospf6_intra_route_calculation(struct ospf6_area *oa); +extern void ospf6_intra_brouter_calculation(struct ospf6_area *oa); + +extern void ospf6_intra_init(void); + +extern int config_write_ospf6_debug_brouter(struct vty *vty); +extern void install_element_ospf6_debug_brouter(void); #endif /* OSPF6_LSA_H */ - diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c index 7817448b7..329060a16 100644 --- a/ospf6d/ospf6_lsa.c +++ b/ospf6d/ospf6_lsa.c @@ -45,769 +45,718 @@ vector ospf6_lsa_handler_vector; -static int -ospf6_unknown_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) +static int ospf6_unknown_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) { - u_char *start, *end, *current; - char byte[4]; + u_char *start, *end, *current; + char byte[4]; - start = (u_char *) lsa->header + sizeof (struct ospf6_lsa_header); - end = (u_char *) lsa->header + ntohs (lsa->header->length); + start = (u_char *)lsa->header + sizeof(struct ospf6_lsa_header); + end = (u_char *)lsa->header + ntohs(lsa->header->length); - vty_out (vty, " Unknown contents:\n"); - for (current = start; current < end; current ++) - { - if ((current - start) % 16 == 0) - vty_out (vty, "\n "); - else if ((current - start) % 4 == 0) - vty_out (vty, " "); + vty_out(vty, " Unknown contents:\n"); + for (current = start; current < end; current++) { + if ((current - start) % 16 == 0) + vty_out(vty, "\n "); + else if ((current - start) % 4 == 0) + vty_out(vty, " "); - snprintf (byte, sizeof (byte), "%02x", *current); - vty_out (vty, "%s", byte); - } + snprintf(byte, sizeof(byte), "%02x", *current); + vty_out(vty, "%s", byte); + } - vty_out (vty, "\n\n"); - return 0; + vty_out(vty, "\n\n"); + return 0; } -struct ospf6_lsa_handler unknown_handler = -{ - OSPF6_LSTYPE_UNKNOWN, - "Unknown", - "Unk", - ospf6_unknown_lsa_show, - NULL -}; +struct ospf6_lsa_handler unknown_handler = { + OSPF6_LSTYPE_UNKNOWN, "Unknown", "Unk", ospf6_unknown_lsa_show, NULL}; -void -ospf6_install_lsa_handler (struct ospf6_lsa_handler *handler) +void ospf6_install_lsa_handler(struct ospf6_lsa_handler *handler) { - /* type in handler is host byte order */ - int index = handler->type & OSPF6_LSTYPE_FCODE_MASK; - vector_set_index (ospf6_lsa_handler_vector, index, handler); + /* type in handler is host byte order */ + int index = handler->type & OSPF6_LSTYPE_FCODE_MASK; + vector_set_index(ospf6_lsa_handler_vector, index, handler); } -struct ospf6_lsa_handler * -ospf6_get_lsa_handler (u_int16_t type) +struct ospf6_lsa_handler *ospf6_get_lsa_handler(u_int16_t type) { - struct ospf6_lsa_handler *handler = NULL; - unsigned int index = ntohs (type) & OSPF6_LSTYPE_FCODE_MASK; + struct ospf6_lsa_handler *handler = NULL; + unsigned int index = ntohs(type) & OSPF6_LSTYPE_FCODE_MASK; - if (index >= vector_active (ospf6_lsa_handler_vector)) - handler = &unknown_handler; - else - handler = vector_slot (ospf6_lsa_handler_vector, index); + if (index >= vector_active(ospf6_lsa_handler_vector)) + handler = &unknown_handler; + else + handler = vector_slot(ospf6_lsa_handler_vector, index); - if (handler == NULL) - handler = &unknown_handler; + if (handler == NULL) + handler = &unknown_handler; - return handler; + return handler; } -const char * -ospf6_lstype_name (u_int16_t type) +const char *ospf6_lstype_name(u_int16_t type) { - static char buf[8]; - struct ospf6_lsa_handler *handler; + static char buf[8]; + struct ospf6_lsa_handler *handler; - handler = ospf6_get_lsa_handler (type); - if (handler && handler != &unknown_handler) - return handler->name; + handler = ospf6_get_lsa_handler(type); + if (handler && handler != &unknown_handler) + return handler->name; - snprintf (buf, sizeof (buf), "0x%04hx", ntohs (type)); - return buf; + snprintf(buf, sizeof(buf), "0x%04hx", ntohs(type)); + return buf; } -const char * -ospf6_lstype_short_name (u_int16_t type) +const char *ospf6_lstype_short_name(u_int16_t type) { - static char buf[8]; - struct ospf6_lsa_handler *handler; + static char buf[8]; + struct ospf6_lsa_handler *handler; - handler = ospf6_get_lsa_handler (type); - if (handler && handler != &unknown_handler) - return handler->short_name; + handler = ospf6_get_lsa_handler(type); + if (handler && handler != &unknown_handler) + return handler->short_name; - snprintf (buf, sizeof (buf), "0x%04hx", ntohs (type)); - return buf; + snprintf(buf, sizeof(buf), "0x%04hx", ntohs(type)); + return buf; } -u_char -ospf6_lstype_debug (u_int16_t type) +u_char ospf6_lstype_debug(u_int16_t type) { - struct ospf6_lsa_handler *handler; - handler = ospf6_get_lsa_handler (type); - return handler->debug; + struct ospf6_lsa_handler *handler; + handler = ospf6_get_lsa_handler(type); + return handler->debug; } /* RFC2328: Section 13.2 */ -int -ospf6_lsa_is_differ (struct ospf6_lsa *lsa1, - struct ospf6_lsa *lsa2) +int ospf6_lsa_is_differ(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2) { - int len; + int len; - assert (OSPF6_LSA_IS_SAME (lsa1, lsa2)); + assert(OSPF6_LSA_IS_SAME(lsa1, lsa2)); - /* XXX, Options ??? */ + /* XXX, Options ??? */ - ospf6_lsa_age_current (lsa1); - ospf6_lsa_age_current (lsa2); - if (ntohs (lsa1->header->age) == OSPF_LSA_MAXAGE && - ntohs (lsa2->header->age) != OSPF_LSA_MAXAGE) - return 1; - if (ntohs (lsa1->header->age) != OSPF_LSA_MAXAGE && - ntohs (lsa2->header->age) == OSPF_LSA_MAXAGE) - return 1; + ospf6_lsa_age_current(lsa1); + ospf6_lsa_age_current(lsa2); + if (ntohs(lsa1->header->age) == OSPF_LSA_MAXAGE + && ntohs(lsa2->header->age) != OSPF_LSA_MAXAGE) + return 1; + if (ntohs(lsa1->header->age) != OSPF_LSA_MAXAGE + && ntohs(lsa2->header->age) == OSPF_LSA_MAXAGE) + return 1; - /* compare body */ - if (ntohs (lsa1->header->length) != ntohs (lsa2->header->length)) - return 1; + /* compare body */ + if (ntohs(lsa1->header->length) != ntohs(lsa2->header->length)) + return 1; - len = ntohs (lsa1->header->length) - sizeof (struct ospf6_lsa_header); - return memcmp (lsa1->header + 1, lsa2->header + 1, len); + len = ntohs(lsa1->header->length) - sizeof(struct ospf6_lsa_header); + return memcmp(lsa1->header + 1, lsa2->header + 1, len); } -int -ospf6_lsa_is_changed (struct ospf6_lsa *lsa1, - struct ospf6_lsa *lsa2) +int ospf6_lsa_is_changed(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2) { - int length; + int length; - if (OSPF6_LSA_IS_MAXAGE (lsa1) ^ OSPF6_LSA_IS_MAXAGE (lsa2)) - return 1; - if (ntohs (lsa1->header->length) != ntohs (lsa2->header->length)) - return 1; - /* Going beyond LSA headers to compare the payload only makes sense, when both LSAs aren't header-only. */ - if (CHECK_FLAG (lsa1->flag, OSPF6_LSA_HEADERONLY) != CHECK_FLAG (lsa2->flag, OSPF6_LSA_HEADERONLY)) - { - zlog_warn ("%s: only one of two (%s, %s) LSAs compared is header-only", __func__, lsa1->name, lsa2->name); - return 1; - } - if (CHECK_FLAG (lsa1->flag, OSPF6_LSA_HEADERONLY)) - return 0; + if (OSPF6_LSA_IS_MAXAGE(lsa1) ^ OSPF6_LSA_IS_MAXAGE(lsa2)) + return 1; + if (ntohs(lsa1->header->length) != ntohs(lsa2->header->length)) + return 1; + /* Going beyond LSA headers to compare the payload only makes sense, + * when both LSAs aren't header-only. */ + if (CHECK_FLAG(lsa1->flag, OSPF6_LSA_HEADERONLY) + != CHECK_FLAG(lsa2->flag, OSPF6_LSA_HEADERONLY)) { + zlog_warn( + "%s: only one of two (%s, %s) LSAs compared is header-only", + __func__, lsa1->name, lsa2->name); + return 1; + } + if (CHECK_FLAG(lsa1->flag, OSPF6_LSA_HEADERONLY)) + return 0; - length = OSPF6_LSA_SIZE (lsa1->header) - sizeof (struct ospf6_lsa_header); - /* Once upper layer verifies LSAs received, length underrun should become a warning. */ - if (length <= 0) - return 0; + length = OSPF6_LSA_SIZE(lsa1->header) - sizeof(struct ospf6_lsa_header); + /* Once upper layer verifies LSAs received, length underrun should + * become a warning. */ + if (length <= 0) + return 0; - return memcmp (OSPF6_LSA_HEADER_END (lsa1->header), - OSPF6_LSA_HEADER_END (lsa2->header), length); + return memcmp(OSPF6_LSA_HEADER_END(lsa1->header), + OSPF6_LSA_HEADER_END(lsa2->header), length); } /* ospf6 age functions */ /* calculate birth */ -static void -ospf6_lsa_age_set (struct ospf6_lsa *lsa) +static void ospf6_lsa_age_set(struct ospf6_lsa *lsa) { - struct timeval now; + struct timeval now; - assert (lsa && lsa->header); + assert(lsa && lsa->header); - monotime(&now); + monotime(&now); - lsa->birth.tv_sec = now.tv_sec - ntohs (lsa->header->age); - lsa->birth.tv_usec = now.tv_usec; + lsa->birth.tv_sec = now.tv_sec - ntohs(lsa->header->age); + lsa->birth.tv_usec = now.tv_usec; - return; + return; } /* this function calculates current age from its birth, then update age field of LSA header. return value is current age */ -u_int16_t -ospf6_lsa_age_current (struct ospf6_lsa *lsa) +u_int16_t ospf6_lsa_age_current(struct ospf6_lsa *lsa) { - struct timeval now; - u_int32_t ulage; - u_int16_t age; + struct timeval now; + u_int32_t ulage; + u_int16_t age; - assert (lsa); - assert (lsa->header); + assert(lsa); + assert(lsa->header); - /* current time */ - monotime(&now); + /* current time */ + monotime(&now); - if (ntohs (lsa->header->age) >= OSPF_LSA_MAXAGE) - { - /* ospf6_lsa_premature_aging () sets age to MAXAGE; when using - relative time, we cannot compare against lsa birth time, so - we catch this special case here. */ - lsa->header->age = htons (OSPF_LSA_MAXAGE); - return OSPF_LSA_MAXAGE; - } - /* calculate age */ - ulage = now.tv_sec - lsa->birth.tv_sec; + if (ntohs(lsa->header->age) >= OSPF_LSA_MAXAGE) { + /* ospf6_lsa_premature_aging () sets age to MAXAGE; when using + relative time, we cannot compare against lsa birth time, so + we catch this special case here. */ + lsa->header->age = htons(OSPF_LSA_MAXAGE); + return OSPF_LSA_MAXAGE; + } + /* calculate age */ + ulage = now.tv_sec - lsa->birth.tv_sec; - /* if over MAXAGE, set to it */ - age = (ulage > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : ulage); + /* if over MAXAGE, set to it */ + age = (ulage > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : ulage); - lsa->header->age = htons (age); - return age; + lsa->header->age = htons(age); + return age; } /* update age field of LSA header with adding InfTransDelay */ -void -ospf6_lsa_age_update_to_send (struct ospf6_lsa *lsa, u_int32_t transdelay) -{ - unsigned short age; - - age = ospf6_lsa_age_current (lsa) + transdelay; - if (age > OSPF_LSA_MAXAGE) - age = OSPF_LSA_MAXAGE; - lsa->header->age = htons (age); -} - -void -ospf6_lsa_premature_aging (struct ospf6_lsa *lsa) -{ - /* log */ - if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type)) - zlog_debug ("LSA: Premature aging: %s", lsa->name); - - THREAD_OFF (lsa->expire); - THREAD_OFF (lsa->refresh); - - /* - * We clear the LSA from the neighbor retx lists now because it - * will not get deleted later. Essentially, changing the age to - * MaxAge will prevent this LSA from being matched with its - * existing entries in the retx list thereby causing those entries - * to be silently replaced with its MaxAged version, but with ever - * increasing retx count causing this LSA to remain forever and - * for the MaxAge remover thread to be called forever too. - * - * The reason the previous entry silently disappears is that when - * entry is added to a neighbor's retx list, it replaces the existing - * entry. But since the ospf6_lsdb_add() routine is generic and not aware - * of the special semantics of retx count, the retx count is not - * decremented when its replaced. Attempting to add the incr and decr - * retx count routines as the hook_add and hook_remove for the retx lists - * have a problem because the hook_remove routine is called for MaxAge - * entries (as will be the case in a traditional LSDB, unlike in this case - * where an LSDB is used as an efficient tree structure to store all kinds - * of data) that are added instead of calling the hook_add routine. - */ - - ospf6_flood_clear (lsa); - - lsa->header->age = htons (OSPF_LSA_MAXAGE); - thread_execute (master, ospf6_lsa_expire, lsa, 0); +void ospf6_lsa_age_update_to_send(struct ospf6_lsa *lsa, u_int32_t transdelay) +{ + unsigned short age; + + age = ospf6_lsa_age_current(lsa) + transdelay; + if (age > OSPF_LSA_MAXAGE) + age = OSPF_LSA_MAXAGE; + lsa->header->age = htons(age); +} + +void ospf6_lsa_premature_aging(struct ospf6_lsa *lsa) +{ + /* log */ + if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)) + zlog_debug("LSA: Premature aging: %s", lsa->name); + + THREAD_OFF(lsa->expire); + THREAD_OFF(lsa->refresh); + + /* + * We clear the LSA from the neighbor retx lists now because it + * will not get deleted later. Essentially, changing the age to + * MaxAge will prevent this LSA from being matched with its + * existing entries in the retx list thereby causing those entries + * to be silently replaced with its MaxAged version, but with ever + * increasing retx count causing this LSA to remain forever and + * for the MaxAge remover thread to be called forever too. + * + * The reason the previous entry silently disappears is that when + * entry is added to a neighbor's retx list, it replaces the existing + * entry. But since the ospf6_lsdb_add() routine is generic and not + * aware + * of the special semantics of retx count, the retx count is not + * decremented when its replaced. Attempting to add the incr and decr + * retx count routines as the hook_add and hook_remove for the retx + * lists + * have a problem because the hook_remove routine is called for MaxAge + * entries (as will be the case in a traditional LSDB, unlike in this + * case + * where an LSDB is used as an efficient tree structure to store all + * kinds + * of data) that are added instead of calling the hook_add routine. + */ + + ospf6_flood_clear(lsa); + + lsa->header->age = htons(OSPF_LSA_MAXAGE); + thread_execute(master, ospf6_lsa_expire, lsa, 0); } /* check which is more recent. if a is more recent, return -1; if the same, return 0; otherwise(b is more recent), return 1 */ -int -ospf6_lsa_compare (struct ospf6_lsa *a, struct ospf6_lsa *b) +int ospf6_lsa_compare(struct ospf6_lsa *a, struct ospf6_lsa *b) { - int32_t seqnuma, seqnumb; - u_int16_t cksuma, cksumb; - u_int16_t agea, ageb; + int32_t seqnuma, seqnumb; + u_int16_t cksuma, cksumb; + u_int16_t agea, ageb; + + assert(a && a->header); + assert(b && b->header); + assert(OSPF6_LSA_IS_SAME(a, b)); - assert (a && a->header); - assert (b && b->header); - assert (OSPF6_LSA_IS_SAME (a, b)); + seqnuma = (int32_t)ntohl(a->header->seqnum); + seqnumb = (int32_t)ntohl(b->header->seqnum); - seqnuma = (int32_t) ntohl (a->header->seqnum); - seqnumb = (int32_t) ntohl (b->header->seqnum); - - /* compare by sequence number */ - if (seqnuma > seqnumb) - return -1; - if (seqnuma < seqnumb) - return 1; - - /* Checksum */ - cksuma = ntohs (a->header->checksum); - cksumb = ntohs (b->header->checksum); - if (cksuma > cksumb) - return -1; - if (cksuma < cksumb) - return 0; - - /* Update Age */ - agea = ospf6_lsa_age_current (a); - ageb = ospf6_lsa_age_current (b); - - /* MaxAge check */ - if (agea == OSPF_LSA_MAXAGE && ageb != OSPF_LSA_MAXAGE) - return -1; - else if (agea != OSPF_LSA_MAXAGE && ageb == OSPF_LSA_MAXAGE) - return 1; - - /* Age check */ - if (agea > ageb && agea - ageb >= OSPF_LSA_MAXAGE_DIFF) - return 1; - else if (agea < ageb && ageb - agea >= OSPF_LSA_MAXAGE_DIFF) - return -1; - - /* neither recent */ - return 0; -} - -char * -ospf6_lsa_printbuf (struct ospf6_lsa *lsa, char *buf, int size) -{ - char id[16], adv_router[16]; - inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id)); - inet_ntop (AF_INET, &lsa->header->adv_router, adv_router, - sizeof (adv_router)); - snprintf (buf, size, "[%s Id:%s Adv:%s]", - ospf6_lstype_name (lsa->header->type), id, adv_router); - return buf; -} - -void -ospf6_lsa_header_print_raw (struct ospf6_lsa_header *header) -{ - char id[16], adv_router[16]; - inet_ntop (AF_INET, &header->id, id, sizeof (id)); - inet_ntop (AF_INET, &header->adv_router, adv_router, - sizeof (adv_router)); - zlog_debug (" [%s Id:%s Adv:%s]", - ospf6_lstype_name (header->type), id, adv_router); - zlog_debug (" Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d", - ntohs (header->age), (u_long) ntohl (header->seqnum), - ntohs (header->checksum), ntohs (header->length)); -} - -void -ospf6_lsa_header_print (struct ospf6_lsa *lsa) -{ - ospf6_lsa_age_current (lsa); - ospf6_lsa_header_print_raw (lsa->header); -} - -void -ospf6_lsa_show_summary_header (struct vty *vty) -{ - vty_out (vty, "%-4s %-15s%-15s%4s %8s %30s\n", - "Type", "LSId", "AdvRouter", "Age", "SeqNum", - "Payload"); -} - -void -ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa) -{ - char adv_router[16], id[16]; - int type; - struct ospf6_lsa_handler *handler; - char buf[64], tmpbuf[80]; - int cnt = 0; - - assert (lsa); - assert (lsa->header); - - inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id)); - inet_ntop (AF_INET, &lsa->header->adv_router, adv_router, - sizeof (adv_router)); - - type = ntohs(lsa->header->type); - handler = ospf6_get_lsa_handler (lsa->header->type); - if ((type == OSPF6_LSTYPE_INTER_PREFIX) || - (type == OSPF6_LSTYPE_INTER_ROUTER) || - (type == OSPF6_LSTYPE_AS_EXTERNAL)) - { - vty_out (vty, "%-4s %-15s%-15s%4hu %8lx %30s\n", - ospf6_lstype_short_name (lsa->header->type), - id, adv_router, ospf6_lsa_age_current (lsa), - (u_long) ntohl (lsa->header->seqnum), - handler->get_prefix_str(lsa, buf, sizeof(buf), 0)); - } - else if (type != OSPF6_LSTYPE_UNKNOWN) - { - sprintf (tmpbuf, "%-4s %-15s%-15s%4hu %8lx", - ospf6_lstype_short_name (lsa->header->type), - id, adv_router, ospf6_lsa_age_current (lsa), - (u_long) ntohl (lsa->header->seqnum)); - - while (handler->get_prefix_str(lsa, buf, sizeof(buf), cnt) != NULL) - { - vty_out (vty, "%s %30s\n", tmpbuf, buf); - cnt++; + /* compare by sequence number */ + if (seqnuma > seqnumb) + return -1; + if (seqnuma < seqnumb) + return 1; + + /* Checksum */ + cksuma = ntohs(a->header->checksum); + cksumb = ntohs(b->header->checksum); + if (cksuma > cksumb) + return -1; + if (cksuma < cksumb) + return 0; + + /* Update Age */ + agea = ospf6_lsa_age_current(a); + ageb = ospf6_lsa_age_current(b); + + /* MaxAge check */ + if (agea == OSPF_LSA_MAXAGE && ageb != OSPF_LSA_MAXAGE) + return -1; + else if (agea != OSPF_LSA_MAXAGE && ageb == OSPF_LSA_MAXAGE) + return 1; + + /* Age check */ + if (agea > ageb && agea - ageb >= OSPF_LSA_MAXAGE_DIFF) + return 1; + else if (agea < ageb && ageb - agea >= OSPF_LSA_MAXAGE_DIFF) + return -1; + + /* neither recent */ + return 0; +} + +char *ospf6_lsa_printbuf(struct ospf6_lsa *lsa, char *buf, int size) +{ + char id[16], adv_router[16]; + inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id)); + inet_ntop(AF_INET, &lsa->header->adv_router, adv_router, + sizeof(adv_router)); + snprintf(buf, size, "[%s Id:%s Adv:%s]", + ospf6_lstype_name(lsa->header->type), id, adv_router); + return buf; +} + +void ospf6_lsa_header_print_raw(struct ospf6_lsa_header *header) +{ + char id[16], adv_router[16]; + inet_ntop(AF_INET, &header->id, id, sizeof(id)); + inet_ntop(AF_INET, &header->adv_router, adv_router, sizeof(adv_router)); + zlog_debug(" [%s Id:%s Adv:%s]", ospf6_lstype_name(header->type), id, + adv_router); + zlog_debug(" Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d", + ntohs(header->age), (u_long)ntohl(header->seqnum), + ntohs(header->checksum), ntohs(header->length)); +} + +void ospf6_lsa_header_print(struct ospf6_lsa *lsa) +{ + ospf6_lsa_age_current(lsa); + ospf6_lsa_header_print_raw(lsa->header); +} + +void ospf6_lsa_show_summary_header(struct vty *vty) +{ + vty_out(vty, "%-4s %-15s%-15s%4s %8s %30s\n", "Type", "LSId", + "AdvRouter", "Age", "SeqNum", "Payload"); +} + +void ospf6_lsa_show_summary(struct vty *vty, struct ospf6_lsa *lsa) +{ + char adv_router[16], id[16]; + int type; + struct ospf6_lsa_handler *handler; + char buf[64], tmpbuf[80]; + int cnt = 0; + + assert(lsa); + assert(lsa->header); + + inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id)); + inet_ntop(AF_INET, &lsa->header->adv_router, adv_router, + sizeof(adv_router)); + + type = ntohs(lsa->header->type); + handler = ospf6_get_lsa_handler(lsa->header->type); + if ((type == OSPF6_LSTYPE_INTER_PREFIX) + || (type == OSPF6_LSTYPE_INTER_ROUTER) + || (type == OSPF6_LSTYPE_AS_EXTERNAL)) { + vty_out(vty, "%-4s %-15s%-15s%4hu %8lx %30s\n", + ospf6_lstype_short_name(lsa->header->type), id, + adv_router, ospf6_lsa_age_current(lsa), + (u_long)ntohl(lsa->header->seqnum), + handler->get_prefix_str(lsa, buf, sizeof(buf), 0)); + } else if (type != OSPF6_LSTYPE_UNKNOWN) { + sprintf(tmpbuf, "%-4s %-15s%-15s%4hu %8lx", + ospf6_lstype_short_name(lsa->header->type), id, + adv_router, ospf6_lsa_age_current(lsa), + (u_long)ntohl(lsa->header->seqnum)); + + while (handler->get_prefix_str(lsa, buf, sizeof(buf), cnt) + != NULL) { + vty_out(vty, "%s %30s\n", tmpbuf, buf); + cnt++; + } + } else { + vty_out(vty, "%-4s %-15s%-15s%4hu %8lx\n", + ospf6_lstype_short_name(lsa->header->type), id, + adv_router, ospf6_lsa_age_current(lsa), + (u_long)ntohl(lsa->header->seqnum)); } - } - else - { - vty_out (vty, "%-4s %-15s%-15s%4hu %8lx\n", - ospf6_lstype_short_name (lsa->header->type), - id, adv_router, ospf6_lsa_age_current (lsa), - (u_long) ntohl (lsa->header->seqnum)); - } -} - -void -ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa) -{ - u_char *start, *end, *current; - char byte[4]; - - start = (u_char *) lsa->header; - end = (u_char *) lsa->header + ntohs (lsa->header->length); - - vty_out (vty, "\n"); - vty_out (vty, "%s:\n", lsa->name); - - for (current = start; current < end; current ++) - { - if ((current - start) % 16 == 0) - vty_out (vty, "\n "); - else if ((current - start) % 4 == 0) - vty_out (vty, " "); - - snprintf (byte, sizeof (byte), "%02x", *current); - vty_out (vty, "%s", byte); - } - - vty_out (vty, "\n\n"); - return; -} - -void -ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa) -{ - char adv_router[64], id[64]; - - assert (lsa && lsa->header); - - inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id)); - inet_ntop (AF_INET, &lsa->header->adv_router, - adv_router, sizeof (adv_router)); - - vty_out (vty, "\n"); - vty_out (vty, "Age: %4hu Type: %s\n", ospf6_lsa_age_current (lsa), - ospf6_lstype_name (lsa->header->type)); - vty_out (vty, "Link State ID: %s\n", id); - vty_out (vty, "Advertising Router: %s\n", adv_router); - vty_out (vty, "LS Sequence Number: %#010lx\n", - (u_long) ntohl (lsa->header->seqnum)); - vty_out (vty, "CheckSum: %#06hx Length: %hu\n", - ntohs (lsa->header->checksum), - ntohs (lsa->header->length)); - vty_out (vty, "Flag: %x \n", lsa->flag); - vty_out (vty, "Lock: %d \n", lsa->lock); - vty_out (vty, "ReTx Count: %d\n", lsa->retrans_count); - vty_out (vty, "Threads: Expire: 0x%p, Refresh: 0x%p \n", - (void *)lsa->expire, (void *)lsa->refresh); - vty_out (vty, "\n"); - return; -} - -void -ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) -{ - char adv_router[64], id[64]; - struct ospf6_lsa_handler *handler; - struct timeval now, res; - char duration[16]; - - assert (lsa && lsa->header); - - inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id)); - inet_ntop (AF_INET, &lsa->header->adv_router, - adv_router, sizeof (adv_router)); - - monotime(&now); - timersub (&now, &lsa->installed, &res); - timerstring (&res, duration, sizeof (duration)); - - vty_out (vty, "Age: %4hu Type: %s\n", ospf6_lsa_age_current (lsa), - ospf6_lstype_name (lsa->header->type)); - vty_out (vty, "Link State ID: %s\n", id); - vty_out (vty, "Advertising Router: %s\n", adv_router); - vty_out (vty, "LS Sequence Number: %#010lx\n", - (u_long) ntohl (lsa->header->seqnum)); - vty_out (vty, "CheckSum: %#06hx Length: %hu\n", - ntohs (lsa->header->checksum), - ntohs (lsa->header->length)); - vty_out (vty, "Duration: %s\n", duration); - - handler = ospf6_get_lsa_handler (lsa->header->type); - if (handler->show == NULL) - handler = &unknown_handler; - (*handler->show) (vty, lsa); - - vty_out (vty, "\n"); +} + +void ospf6_lsa_show_dump(struct vty *vty, struct ospf6_lsa *lsa) +{ + u_char *start, *end, *current; + char byte[4]; + + start = (u_char *)lsa->header; + end = (u_char *)lsa->header + ntohs(lsa->header->length); + + vty_out(vty, "\n"); + vty_out(vty, "%s:\n", lsa->name); + + for (current = start; current < end; current++) { + if ((current - start) % 16 == 0) + vty_out(vty, "\n "); + else if ((current - start) % 4 == 0) + vty_out(vty, " "); + + snprintf(byte, sizeof(byte), "%02x", *current); + vty_out(vty, "%s", byte); + } + + vty_out(vty, "\n\n"); + return; +} + +void ospf6_lsa_show_internal(struct vty *vty, struct ospf6_lsa *lsa) +{ + char adv_router[64], id[64]; + + assert(lsa && lsa->header); + + inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id)); + inet_ntop(AF_INET, &lsa->header->adv_router, adv_router, + sizeof(adv_router)); + + vty_out(vty, "\n"); + vty_out(vty, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa), + ospf6_lstype_name(lsa->header->type)); + vty_out(vty, "Link State ID: %s\n", id); + vty_out(vty, "Advertising Router: %s\n", adv_router); + vty_out(vty, "LS Sequence Number: %#010lx\n", + (u_long)ntohl(lsa->header->seqnum)); + vty_out(vty, "CheckSum: %#06hx Length: %hu\n", + ntohs(lsa->header->checksum), ntohs(lsa->header->length)); + vty_out(vty, "Flag: %x \n", lsa->flag); + vty_out(vty, "Lock: %d \n", lsa->lock); + vty_out(vty, "ReTx Count: %d\n", lsa->retrans_count); + vty_out(vty, "Threads: Expire: 0x%p, Refresh: 0x%p \n", + (void *)lsa->expire, (void *)lsa->refresh); + vty_out(vty, "\n"); + return; +} + +void ospf6_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) +{ + char adv_router[64], id[64]; + struct ospf6_lsa_handler *handler; + struct timeval now, res; + char duration[16]; + + assert(lsa && lsa->header); + + inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id)); + inet_ntop(AF_INET, &lsa->header->adv_router, adv_router, + sizeof(adv_router)); + + monotime(&now); + timersub(&now, &lsa->installed, &res); + timerstring(&res, duration, sizeof(duration)); + + vty_out(vty, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa), + ospf6_lstype_name(lsa->header->type)); + vty_out(vty, "Link State ID: %s\n", id); + vty_out(vty, "Advertising Router: %s\n", adv_router); + vty_out(vty, "LS Sequence Number: %#010lx\n", + (u_long)ntohl(lsa->header->seqnum)); + vty_out(vty, "CheckSum: %#06hx Length: %hu\n", + ntohs(lsa->header->checksum), ntohs(lsa->header->length)); + vty_out(vty, "Duration: %s\n", duration); + + handler = ospf6_get_lsa_handler(lsa->header->type); + if (handler->show == NULL) + handler = &unknown_handler; + (*handler->show)(vty, lsa); + + vty_out(vty, "\n"); } /* OSPFv3 LSA creation/deletion function */ -struct ospf6_lsa * -ospf6_lsa_create (struct ospf6_lsa_header *header) +struct ospf6_lsa *ospf6_lsa_create(struct ospf6_lsa_header *header) { - struct ospf6_lsa *lsa = NULL; - struct ospf6_lsa_header *new_header = NULL; - u_int16_t lsa_size = 0; + struct ospf6_lsa *lsa = NULL; + struct ospf6_lsa_header *new_header = NULL; + u_int16_t lsa_size = 0; - /* size of the entire LSA */ - lsa_size = ntohs (header->length); /* XXX vulnerable */ + /* size of the entire LSA */ + lsa_size = ntohs(header->length); /* XXX vulnerable */ - /* allocate memory for this LSA */ - new_header = (struct ospf6_lsa_header *) - XMALLOC (MTYPE_OSPF6_LSA, lsa_size); + /* allocate memory for this LSA */ + new_header = + (struct ospf6_lsa_header *)XMALLOC(MTYPE_OSPF6_LSA, lsa_size); - /* copy LSA from original header */ - memcpy (new_header, header, lsa_size); + /* copy LSA from original header */ + memcpy(new_header, header, lsa_size); - /* LSA information structure */ - /* allocate memory */ - lsa = (struct ospf6_lsa *) - XCALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa)); + /* LSA information structure */ + /* allocate memory */ + lsa = (struct ospf6_lsa *)XCALLOC(MTYPE_OSPF6_LSA, + sizeof(struct ospf6_lsa)); - lsa->header = (struct ospf6_lsa_header *) new_header; + lsa->header = (struct ospf6_lsa_header *)new_header; - /* dump string */ - ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name)); + /* dump string */ + ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name)); - /* calculate birth of this lsa */ - ospf6_lsa_age_set (lsa); + /* calculate birth of this lsa */ + ospf6_lsa_age_set(lsa); - return lsa; + return lsa; } -struct ospf6_lsa * -ospf6_lsa_create_headeronly (struct ospf6_lsa_header *header) +struct ospf6_lsa *ospf6_lsa_create_headeronly(struct ospf6_lsa_header *header) { - struct ospf6_lsa *lsa = NULL; - struct ospf6_lsa_header *new_header = NULL; + struct ospf6_lsa *lsa = NULL; + struct ospf6_lsa_header *new_header = NULL; - /* allocate memory for this LSA */ - new_header = (struct ospf6_lsa_header *) - XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa_header)); + /* allocate memory for this LSA */ + new_header = (struct ospf6_lsa_header *)XMALLOC( + MTYPE_OSPF6_LSA, sizeof(struct ospf6_lsa_header)); - /* copy LSA from original header */ - memcpy (new_header, header, sizeof (struct ospf6_lsa_header)); + /* copy LSA from original header */ + memcpy(new_header, header, sizeof(struct ospf6_lsa_header)); - /* LSA information structure */ - /* allocate memory */ - lsa = (struct ospf6_lsa *) - XCALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa)); + /* LSA information structure */ + /* allocate memory */ + lsa = (struct ospf6_lsa *)XCALLOC(MTYPE_OSPF6_LSA, + sizeof(struct ospf6_lsa)); - lsa->header = (struct ospf6_lsa_header *) new_header; - SET_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY); + lsa->header = (struct ospf6_lsa_header *)new_header; + SET_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY); - /* dump string */ - ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name)); + /* dump string */ + ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name)); - /* calculate birth of this lsa */ - ospf6_lsa_age_set (lsa); + /* calculate birth of this lsa */ + ospf6_lsa_age_set(lsa); - return lsa; + return lsa; } -void -ospf6_lsa_delete (struct ospf6_lsa *lsa) +void ospf6_lsa_delete(struct ospf6_lsa *lsa) { - assert (lsa->lock == 0); + assert(lsa->lock == 0); - /* cancel threads */ - THREAD_OFF (lsa->expire); - THREAD_OFF (lsa->refresh); + /* cancel threads */ + THREAD_OFF(lsa->expire); + THREAD_OFF(lsa->refresh); - /* do free */ - XFREE (MTYPE_OSPF6_LSA, lsa->header); - XFREE (MTYPE_OSPF6_LSA, lsa); + /* do free */ + XFREE(MTYPE_OSPF6_LSA, lsa->header); + XFREE(MTYPE_OSPF6_LSA, lsa); } -struct ospf6_lsa * -ospf6_lsa_copy (struct ospf6_lsa *lsa) +struct ospf6_lsa *ospf6_lsa_copy(struct ospf6_lsa *lsa) { - struct ospf6_lsa *copy = NULL; + struct ospf6_lsa *copy = NULL; - ospf6_lsa_age_current (lsa); - if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY)) - copy = ospf6_lsa_create_headeronly (lsa->header); - else - copy = ospf6_lsa_create (lsa->header); - assert (copy->lock == 0); + ospf6_lsa_age_current(lsa); + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY)) + copy = ospf6_lsa_create_headeronly(lsa->header); + else + copy = ospf6_lsa_create(lsa->header); + assert(copy->lock == 0); - copy->birth = lsa->birth; - copy->originated = lsa->originated; - copy->received = lsa->received; - copy->installed = lsa->installed; - copy->lsdb = lsa->lsdb; - copy->rn = NULL; + copy->birth = lsa->birth; + copy->originated = lsa->originated; + copy->received = lsa->received; + copy->installed = lsa->installed; + copy->lsdb = lsa->lsdb; + copy->rn = NULL; - return copy; + return copy; } /* increment reference counter of struct ospf6_lsa */ -void -ospf6_lsa_lock (struct ospf6_lsa *lsa) +void ospf6_lsa_lock(struct ospf6_lsa *lsa) { - lsa->lock++; - return; + lsa->lock++; + return; } /* decrement reference counter of struct ospf6_lsa */ -void -ospf6_lsa_unlock (struct ospf6_lsa *lsa) +void ospf6_lsa_unlock(struct ospf6_lsa *lsa) { - /* decrement reference counter */ - assert (lsa->lock > 0); - lsa->lock--; + /* decrement reference counter */ + assert(lsa->lock > 0); + lsa->lock--; - if (lsa->lock != 0) - return; + if (lsa->lock != 0) + return; - ospf6_lsa_delete (lsa); + ospf6_lsa_delete(lsa); } /* ospf6 lsa expiry */ -int -ospf6_lsa_expire (struct thread *thread) +int ospf6_lsa_expire(struct thread *thread) { - struct ospf6_lsa *lsa; + struct ospf6_lsa *lsa; - lsa = (struct ospf6_lsa *) THREAD_ARG (thread); + lsa = (struct ospf6_lsa *)THREAD_ARG(thread); - assert (lsa && lsa->header); - assert (OSPF6_LSA_IS_MAXAGE (lsa)); - assert (! lsa->refresh); + assert(lsa && lsa->header); + assert(OSPF6_LSA_IS_MAXAGE(lsa)); + assert(!lsa->refresh); - lsa->expire = (struct thread *) NULL; + lsa->expire = (struct thread *)NULL; - if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type)) - { - zlog_debug ("LSA Expire:"); - ospf6_lsa_header_print (lsa); - } + if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)) { + zlog_debug("LSA Expire:"); + ospf6_lsa_header_print(lsa); + } - if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY)) - return 0; /* dbexchange will do something ... */ + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY)) + return 0; /* dbexchange will do something ... */ - /* reinstall lsa */ - ospf6_install_lsa (lsa); + /* reinstall lsa */ + ospf6_install_lsa(lsa); - /* reflood lsa */ - ospf6_flood (NULL, lsa); + /* reflood lsa */ + ospf6_flood(NULL, lsa); - /* schedule maxage remover */ - ospf6_maxage_remove (ospf6); + /* schedule maxage remover */ + ospf6_maxage_remove(ospf6); - return 0; + return 0; } -int -ospf6_lsa_refresh (struct thread *thread) +int ospf6_lsa_refresh(struct thread *thread) { - struct ospf6_lsa *old, *self, *new; - struct ospf6_lsdb *lsdb_self; - - old = (struct ospf6_lsa *) THREAD_ARG (thread); - assert (old && old->header); - - old->refresh = (struct thread *) NULL; + struct ospf6_lsa *old, *self, *new; + struct ospf6_lsdb *lsdb_self; - lsdb_self = ospf6_get_scoped_lsdb_self (old); - self = ospf6_lsdb_lookup (old->header->type, old->header->id, - old->header->adv_router, lsdb_self); - if (self == NULL) - { - if (IS_OSPF6_DEBUG_LSA_TYPE (old->header->type)) - zlog_debug ("Refresh: could not find self LSA, flush %s", old->name); - ospf6_lsa_premature_aging (old); - return 0; - } + old = (struct ospf6_lsa *)THREAD_ARG(thread); + assert(old && old->header); - /* Reset age, increment LS sequence number. */ - self->header->age = htons (0); - self->header->seqnum = - ospf6_new_ls_seqnum (self->header->type, self->header->id, - self->header->adv_router, old->lsdb); - ospf6_lsa_checksum (self->header); + old->refresh = (struct thread *)NULL; - new = ospf6_lsa_create (self->header); - new->lsdb = old->lsdb; - new->refresh = NULL; - thread_add_timer(master, ospf6_lsa_refresh, new, OSPF_LS_REFRESH_TIME, - &new->refresh); - - /* store it in the LSDB for self-originated LSAs */ - ospf6_lsdb_add (ospf6_lsa_copy (new), lsdb_self); + lsdb_self = ospf6_get_scoped_lsdb_self(old); + self = ospf6_lsdb_lookup(old->header->type, old->header->id, + old->header->adv_router, lsdb_self); + if (self == NULL) { + if (IS_OSPF6_DEBUG_LSA_TYPE(old->header->type)) + zlog_debug("Refresh: could not find self LSA, flush %s", + old->name); + ospf6_lsa_premature_aging(old); + return 0; + } - if (IS_OSPF6_DEBUG_LSA_TYPE (new->header->type)) - { - zlog_debug ("LSA Refresh:"); - ospf6_lsa_header_print (new); - } + /* Reset age, increment LS sequence number. */ + self->header->age = htons(0); + self->header->seqnum = + ospf6_new_ls_seqnum(self->header->type, self->header->id, + self->header->adv_router, old->lsdb); + ospf6_lsa_checksum(self->header); + + new = ospf6_lsa_create(self->header); + new->lsdb = old->lsdb; + new->refresh = NULL; + thread_add_timer(master, ospf6_lsa_refresh, new, OSPF_LS_REFRESH_TIME, + &new->refresh); + + /* store it in the LSDB for self-originated LSAs */ + ospf6_lsdb_add(ospf6_lsa_copy(new), lsdb_self); + + if (IS_OSPF6_DEBUG_LSA_TYPE(new->header->type)) { + zlog_debug("LSA Refresh:"); + ospf6_lsa_header_print(new); + } - ospf6_install_lsa (new); - ospf6_flood (NULL, new); + ospf6_install_lsa(new); + ospf6_flood(NULL, new); - return 0; + return 0; } - /* Fletcher Checksum -- Refer to RFC1008. */ /* All the offsets are zero-based. The offsets in the RFC1008 are one-based. */ -unsigned short -ospf6_lsa_checksum (struct ospf6_lsa_header *lsa_header) +unsigned short ospf6_lsa_checksum(struct ospf6_lsa_header *lsa_header) { - u_char *buffer = (u_char *) &lsa_header->type; - int type_offset = buffer - (u_char *) &lsa_header->age; /* should be 2 */ + u_char *buffer = (u_char *)&lsa_header->type; + int type_offset = buffer - (u_char *)&lsa_header->age; /* should be 2 */ - /* Skip the AGE field */ - u_int16_t len = ntohs(lsa_header->length) - type_offset; + /* Skip the AGE field */ + u_int16_t len = ntohs(lsa_header->length) - type_offset; - /* Checksum offset starts from "type" field, not the beginning of the - lsa_header struct. The offset is 14, rather than 16. */ - int checksum_offset = (u_char *) &lsa_header->checksum - buffer; + /* Checksum offset starts from "type" field, not the beginning of the + lsa_header struct. The offset is 14, rather than 16. */ + int checksum_offset = (u_char *)&lsa_header->checksum - buffer; - return (unsigned short)fletcher_checksum(buffer, len, checksum_offset); + return (unsigned short)fletcher_checksum(buffer, len, checksum_offset); } -int -ospf6_lsa_checksum_valid (struct ospf6_lsa_header *lsa_header) +int ospf6_lsa_checksum_valid(struct ospf6_lsa_header *lsa_header) { - u_char *buffer = (u_char *) &lsa_header->type; - int type_offset = buffer - (u_char *) &lsa_header->age; /* should be 2 */ + u_char *buffer = (u_char *)&lsa_header->type; + int type_offset = buffer - (u_char *)&lsa_header->age; /* should be 2 */ - /* Skip the AGE field */ - u_int16_t len = ntohs(lsa_header->length) - type_offset; + /* Skip the AGE field */ + u_int16_t len = ntohs(lsa_header->length) - type_offset; - return (fletcher_checksum(buffer, len, FLETCHER_CHECKSUM_VALIDATE) == 0); + return (fletcher_checksum(buffer, len, FLETCHER_CHECKSUM_VALIDATE) + == 0); } -void -ospf6_lsa_init (void) +void ospf6_lsa_init(void) { - ospf6_lsa_handler_vector = vector_init (0); - ospf6_install_lsa_handler (&unknown_handler); + ospf6_lsa_handler_vector = vector_init(0); + ospf6_install_lsa_handler(&unknown_handler); } -void -ospf6_lsa_terminate (void) +void ospf6_lsa_terminate(void) { - vector_free (ospf6_lsa_handler_vector); + vector_free(ospf6_lsa_handler_vector); } -static char * -ospf6_lsa_handler_name (struct ospf6_lsa_handler *h) +static char *ospf6_lsa_handler_name(struct ospf6_lsa_handler *h) { - static char buf[64]; - unsigned int i; - unsigned int size = strlen (h->name); + static char buf[64]; + unsigned int i; + unsigned int size = strlen(h->name); - if (!strcmp(h->name, "unknown") && - h->type != OSPF6_LSTYPE_UNKNOWN) - { - snprintf (buf, sizeof (buf), "%#04hx", h->type); - return buf; - } + if (!strcmp(h->name, "unknown") && h->type != OSPF6_LSTYPE_UNKNOWN) { + snprintf(buf, sizeof(buf), "%#04hx", h->type); + return buf; + } - for (i = 0; i < MIN (size, sizeof (buf)); i++) - { - if (! islower ((unsigned char)h->name[i])) - buf[i] = tolower ((unsigned char)h->name[i]); - else - buf[i] = h->name[i]; - } - buf[size] = '\0'; - return buf; + for (i = 0; i < MIN(size, sizeof(buf)); i++) { + if (!islower((unsigned char)h->name[i])) + buf[i] = tolower((unsigned char)h->name[i]); + else + buf[i] = h->name[i]; + } + buf[size] = '\0'; + return buf; } DEFUN (debug_ospf6_lsa_type, @@ -828,39 +777,38 @@ DEFUN (debug_ospf6_lsa_type, "Dump LSAs\n" "Display LSA's internal information\n") { - int idx_lsa = 3; - int idx_type = 4; - unsigned int i; - struct ospf6_lsa_handler *handler = NULL; - - for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++) - { - handler = vector_slot (ospf6_lsa_handler_vector, i); - if (handler == NULL) - continue; - if (strncmp (argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler), strlen(argv[idx_lsa]->arg)) == 0) - break; - if (! strcasecmp (argv[idx_lsa]->arg, handler->name)) - break; - handler = NULL; - } - - if (handler == NULL) - handler = &unknown_handler; - - if (argc == 5) - { - if (strmatch(argv[idx_type]->text, "originate")) - SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE); - else if (strmatch(argv[idx_type]->text, "examine")) - SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN); - else if (strmatch(argv[idx_type]->text, "flooding")) - SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD); - } - else - SET_FLAG (handler->debug, OSPF6_LSA_DEBUG); - - return CMD_SUCCESS; + int idx_lsa = 3; + int idx_type = 4; + unsigned int i; + struct ospf6_lsa_handler *handler = NULL; + + for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) { + handler = vector_slot(ospf6_lsa_handler_vector, i); + if (handler == NULL) + continue; + if (strncmp(argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler), + strlen(argv[idx_lsa]->arg)) + == 0) + break; + if (!strcasecmp(argv[idx_lsa]->arg, handler->name)) + break; + handler = NULL; + } + + if (handler == NULL) + handler = &unknown_handler; + + if (argc == 5) { + if (strmatch(argv[idx_type]->text, "originate")) + SET_FLAG(handler->debug, OSPF6_LSA_DEBUG_ORIGINATE); + else if (strmatch(argv[idx_type]->text, "examine")) + SET_FLAG(handler->debug, OSPF6_LSA_DEBUG_EXAMIN); + else if (strmatch(argv[idx_type]->text, "flooding")) + SET_FLAG(handler->debug, OSPF6_LSA_DEBUG_FLOOD); + } else + SET_FLAG(handler->debug, OSPF6_LSA_DEBUG); + + return CMD_SUCCESS; } DEFUN (no_debug_ospf6_lsa_type, @@ -882,75 +830,69 @@ DEFUN (no_debug_ospf6_lsa_type, "Dump LSAs\n" "Display LSA's internal information\n") { - int idx_lsa = 4; - int idx_type = 5; - u_int i; - struct ospf6_lsa_handler *handler = NULL; - - for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++) - { - handler = vector_slot (ospf6_lsa_handler_vector, i); - if (handler == NULL) - continue; - if (strncmp (argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler), strlen(argv[idx_lsa]->arg)) == 0) - break; - if (! strcasecmp (argv[idx_lsa]->arg, handler->name)) - break; - } - - if (handler == NULL) - return CMD_SUCCESS; - - if (argc == 6) - { - if (strmatch(argv[idx_type]->text, "originate")) - UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE); - if (strmatch(argv[idx_type]->text, "examine")) - UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN); - if (strmatch(argv[idx_type]->text, "flooding")) - UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD); - } - else - UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG); - - return CMD_SUCCESS; -} - -void -install_element_ospf6_debug_lsa (void) -{ - install_element (ENABLE_NODE, &debug_ospf6_lsa_hex_cmd); - install_element (ENABLE_NODE, &no_debug_ospf6_lsa_hex_cmd); - install_element (CONFIG_NODE, &debug_ospf6_lsa_hex_cmd); - install_element (CONFIG_NODE, &no_debug_ospf6_lsa_hex_cmd); -} - -int -config_write_ospf6_debug_lsa (struct vty *vty) -{ - u_int i; - struct ospf6_lsa_handler *handler; - - for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++) - { - handler = vector_slot (ospf6_lsa_handler_vector, i); - if (handler == NULL) - continue; - if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG)) - vty_out (vty, "debug ospf6 lsa %s\n", - ospf6_lsa_handler_name (handler)); - if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE)) - vty_out (vty, "debug ospf6 lsa %s originate\n", - ospf6_lsa_handler_name (handler)); - if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN)) - vty_out (vty, "debug ospf6 lsa %s examine\n", - ospf6_lsa_handler_name (handler)); - if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD)) - vty_out (vty, "debug ospf6 lsa %s flooding\n", - ospf6_lsa_handler_name (handler)); - } - - return 0; -} + int idx_lsa = 4; + int idx_type = 5; + u_int i; + struct ospf6_lsa_handler *handler = NULL; + + for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) { + handler = vector_slot(ospf6_lsa_handler_vector, i); + if (handler == NULL) + continue; + if (strncmp(argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler), + strlen(argv[idx_lsa]->arg)) + == 0) + break; + if (!strcasecmp(argv[idx_lsa]->arg, handler->name)) + break; + } + if (handler == NULL) + return CMD_SUCCESS; + + if (argc == 6) { + if (strmatch(argv[idx_type]->text, "originate")) + UNSET_FLAG(handler->debug, OSPF6_LSA_DEBUG_ORIGINATE); + if (strmatch(argv[idx_type]->text, "examine")) + UNSET_FLAG(handler->debug, OSPF6_LSA_DEBUG_EXAMIN); + if (strmatch(argv[idx_type]->text, "flooding")) + UNSET_FLAG(handler->debug, OSPF6_LSA_DEBUG_FLOOD); + } else + UNSET_FLAG(handler->debug, OSPF6_LSA_DEBUG); + + return CMD_SUCCESS; +} + +void install_element_ospf6_debug_lsa(void) +{ + install_element(ENABLE_NODE, &debug_ospf6_lsa_hex_cmd); + install_element(ENABLE_NODE, &no_debug_ospf6_lsa_hex_cmd); + install_element(CONFIG_NODE, &debug_ospf6_lsa_hex_cmd); + install_element(CONFIG_NODE, &no_debug_ospf6_lsa_hex_cmd); +} + +int config_write_ospf6_debug_lsa(struct vty *vty) +{ + u_int i; + struct ospf6_lsa_handler *handler; + + for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) { + handler = vector_slot(ospf6_lsa_handler_vector, i); + if (handler == NULL) + continue; + if (CHECK_FLAG(handler->debug, OSPF6_LSA_DEBUG)) + vty_out(vty, "debug ospf6 lsa %s\n", + ospf6_lsa_handler_name(handler)); + if (CHECK_FLAG(handler->debug, OSPF6_LSA_DEBUG_ORIGINATE)) + vty_out(vty, "debug ospf6 lsa %s originate\n", + ospf6_lsa_handler_name(handler)); + if (CHECK_FLAG(handler->debug, OSPF6_LSA_DEBUG_EXAMIN)) + vty_out(vty, "debug ospf6 lsa %s examine\n", + ospf6_lsa_handler_name(handler)); + if (CHECK_FLAG(handler->debug, OSPF6_LSA_DEBUG_FLOOD)) + vty_out(vty, "debug ospf6 lsa %s flooding\n", + ospf6_lsa_handler_name(handler)); + } + return 0; +} diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h index 36cf55986..ef63429fd 100644 --- a/ospf6d/ospf6_lsa.h +++ b/ospf6d/ospf6_lsa.h @@ -27,23 +27,22 @@ #define OSPF6_LSA_DEBUG_EXAMIN 0x04 #define OSPF6_LSA_DEBUG_FLOOD 0x08 -#define IS_OSPF6_DEBUG_LSA(name) \ - (ospf6_lstype_debug (htons (OSPF6_LSTYPE_ ## name)) & \ - OSPF6_LSA_DEBUG) -#define IS_OSPF6_DEBUG_ORIGINATE(name) \ - (ospf6_lstype_debug (htons (OSPF6_LSTYPE_ ## name)) & \ - OSPF6_LSA_DEBUG_ORIGINATE) -#define IS_OSPF6_DEBUG_EXAMIN(name) \ - (ospf6_lstype_debug (htons (OSPF6_LSTYPE_ ## name)) & \ - OSPF6_LSA_DEBUG_EXAMIN) -#define IS_OSPF6_DEBUG_LSA_TYPE(type) \ - (ospf6_lstype_debug (type) & OSPF6_LSA_DEBUG) -#define IS_OSPF6_DEBUG_ORIGINATE_TYPE(type) \ - (ospf6_lstype_debug (type) & OSPF6_LSA_DEBUG_ORIGINATE) -#define IS_OSPF6_DEBUG_EXAMIN_TYPE(type) \ - (ospf6_lstype_debug (type) & OSPF6_LSA_DEBUG_EXAMIN) -#define IS_OSPF6_DEBUG_FLOOD_TYPE(type) \ - (ospf6_lstype_debug (type) & OSPF6_LSA_DEBUG_FLOOD) +#define IS_OSPF6_DEBUG_LSA(name) \ + (ospf6_lstype_debug(htons(OSPF6_LSTYPE_##name)) & OSPF6_LSA_DEBUG) +#define IS_OSPF6_DEBUG_ORIGINATE(name) \ + (ospf6_lstype_debug(htons(OSPF6_LSTYPE_##name)) \ + & OSPF6_LSA_DEBUG_ORIGINATE) +#define IS_OSPF6_DEBUG_EXAMIN(name) \ + (ospf6_lstype_debug(htons(OSPF6_LSTYPE_##name)) \ + & OSPF6_LSA_DEBUG_EXAMIN) +#define IS_OSPF6_DEBUG_LSA_TYPE(type) \ + (ospf6_lstype_debug(type) & OSPF6_LSA_DEBUG) +#define IS_OSPF6_DEBUG_ORIGINATE_TYPE(type) \ + (ospf6_lstype_debug(type) & OSPF6_LSA_DEBUG_ORIGINATE) +#define IS_OSPF6_DEBUG_EXAMIN_TYPE(type) \ + (ospf6_lstype_debug(type) & OSPF6_LSA_DEBUG_EXAMIN) +#define IS_OSPF6_DEBUG_FLOOD_TYPE(type) \ + (ospf6_lstype_debug(type) & OSPF6_LSA_DEBUG_FLOOD) /* LSA definition */ @@ -74,66 +73,60 @@ #define OSPF6_SCOPE_RESERVED 0x6000 /* XXX U-bit handling should be treated here */ -#define OSPF6_LSA_SCOPE(type) \ - (ntohs (type) & OSPF6_LSTYPE_SCOPE_MASK) +#define OSPF6_LSA_SCOPE(type) (ntohs(type) & OSPF6_LSTYPE_SCOPE_MASK) /* LSA Header */ #define OSPF6_LSA_HEADER_SIZE 20U -struct ospf6_lsa_header -{ - u_int16_t age; /* LS age */ - u_int16_t type; /* LS type */ - u_int32_t id; /* Link State ID */ - u_int32_t adv_router; /* Advertising Router */ - u_int32_t seqnum; /* LS sequence number */ - u_int16_t checksum; /* LS checksum */ - u_int16_t length; /* LSA length */ +struct ospf6_lsa_header { + u_int16_t age; /* LS age */ + u_int16_t type; /* LS type */ + u_int32_t id; /* Link State ID */ + u_int32_t adv_router; /* Advertising Router */ + u_int32_t seqnum; /* LS sequence number */ + u_int16_t checksum; /* LS checksum */ + u_int16_t length; /* LSA length */ }; -#define OSPF6_LSA_HEADER_END(h) \ - ((caddr_t)(h) + sizeof (struct ospf6_lsa_header)) -#define OSPF6_LSA_SIZE(h) \ - (ntohs (((struct ospf6_lsa_header *) (h))->length)) -#define OSPF6_LSA_END(h) \ - ((caddr_t)(h) + ntohs (((struct ospf6_lsa_header *) (h))->length)) -#define OSPF6_LSA_IS_TYPE(t, L) \ - ((L)->header->type == htons (OSPF6_LSTYPE_ ## t) ? 1 : 0) -#define OSPF6_LSA_IS_SAME(L1, L2) \ - ((L1)->header->adv_router == (L2)->header->adv_router && \ - (L1)->header->id == (L2)->header->id && \ - (L1)->header->type == (L2)->header->type) -#define OSPF6_LSA_IS_MATCH(t, i, a, L) \ - ((L)->header->adv_router == (a) && (L)->header->id == (i) && \ - (L)->header->type == (t)) +#define OSPF6_LSA_HEADER_END(h) ((caddr_t)(h) + sizeof(struct ospf6_lsa_header)) +#define OSPF6_LSA_SIZE(h) (ntohs(((struct ospf6_lsa_header *)(h))->length)) +#define OSPF6_LSA_END(h) \ + ((caddr_t)(h) + ntohs(((struct ospf6_lsa_header *)(h))->length)) +#define OSPF6_LSA_IS_TYPE(t, L) \ + ((L)->header->type == htons(OSPF6_LSTYPE_##t) ? 1 : 0) +#define OSPF6_LSA_IS_SAME(L1, L2) \ + ((L1)->header->adv_router == (L2)->header->adv_router \ + && (L1)->header->id == (L2)->header->id \ + && (L1)->header->type == (L2)->header->type) +#define OSPF6_LSA_IS_MATCH(t, i, a, L) \ + ((L)->header->adv_router == (a) && (L)->header->id == (i) \ + && (L)->header->type == (t)) #define OSPF6_LSA_IS_DIFFER(L1, L2) ospf6_lsa_is_differ (L1, L2) #define OSPF6_LSA_IS_MAXAGE(L) (ospf6_lsa_age_current (L) == OSPF_LSA_MAXAGE) #define OSPF6_LSA_IS_CHANGED(L1, L2) ospf6_lsa_is_changed (L1, L2) #define OSPF6_LSA_IS_SEQWRAP(L) ((L)->header->seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER + 1)) +struct ospf6_lsa { + char name[64]; /* dump string */ -struct ospf6_lsa -{ - char name[64]; /* dump string */ + struct route_node *rn; - struct route_node *rn; + unsigned char lock; /* reference counter */ + unsigned char flag; /* special meaning (e.g. floodback) */ - unsigned char lock; /* reference counter */ - unsigned char flag; /* special meaning (e.g. floodback) */ + struct timeval birth; /* tv_sec when LS age 0 */ + struct timeval originated; /* used by MinLSInterval check */ + struct timeval received; /* used by MinLSArrival check */ + struct timeval installed; - struct timeval birth; /* tv_sec when LS age 0 */ - struct timeval originated; /* used by MinLSInterval check */ - struct timeval received; /* used by MinLSArrival check */ - struct timeval installed; + struct thread *expire; + struct thread *refresh; /* For self-originated LSA */ - struct thread *expire; - struct thread *refresh; /* For self-originated LSA */ + int retrans_count; - int retrans_count; + struct ospf6_lsdb *lsdb; - struct ospf6_lsdb *lsdb; - - /* lsa instance */ - struct ospf6_lsa_header *header; + /* lsa instance */ + struct ospf6_lsa_header *header; }; #define OSPF6_LSA_HEADERONLY 0x01 @@ -143,119 +136,114 @@ struct ospf6_lsa #define OSPF6_LSA_UNAPPROVED 0x10 #define OSPF6_LSA_SEQWRAPPED 0x20 -struct ospf6_lsa_handler -{ - u_int16_t type; /* host byte order */ - const char *name; - const char *short_name; - int (*show) (struct vty *, struct ospf6_lsa *); - char *(*get_prefix_str) (struct ospf6_lsa *, char *buf, int buflen, int pos); - u_char debug; +struct ospf6_lsa_handler { + u_int16_t type; /* host byte order */ + const char *name; + const char *short_name; + int (*show)(struct vty *, struct ospf6_lsa *); + char *(*get_prefix_str)(struct ospf6_lsa *, char *buf, int buflen, + int pos); + u_char debug; }; extern struct ospf6_lsa_handler unknown_handler; -#define OSPF6_LSA_IS_KNOWN(type) \ - (ospf6_get_lsa_handler (type) != &unknown_handler ? 1 : 0) +#define OSPF6_LSA_IS_KNOWN(type) \ + (ospf6_get_lsa_handler(type) != &unknown_handler ? 1 : 0) extern vector ospf6_lsa_handler_vector; /* Macro for LSA Origination */ /* addr is (struct prefix *) */ -#define CONTINUE_IF_ADDRESS_LINKLOCAL(debug,addr) \ - if (IN6_IS_ADDR_LINKLOCAL (&(addr)->u.prefix6)) \ - { \ - char buf[PREFIX2STR_BUFFER]; \ - prefix2str (addr, buf, sizeof (buf)); \ - if (debug) \ - zlog_debug ("Filter out Linklocal: %s", buf); \ - continue; \ - } - -#define CONTINUE_IF_ADDRESS_UNSPECIFIED(debug,addr) \ - if (IN6_IS_ADDR_UNSPECIFIED (&(addr)->u.prefix6)) \ - { \ - char buf[PREFIX2STR_BUFFER]; \ - prefix2str (addr, buf, sizeof (buf)); \ - if (debug) \ - zlog_debug ("Filter out Unspecified: %s", buf);\ - continue; \ - } - -#define CONTINUE_IF_ADDRESS_LOOPBACK(debug,addr) \ - if (IN6_IS_ADDR_LOOPBACK (&(addr)->u.prefix6)) \ - { \ - char buf[PREFIX2STR_BUFFER]; \ - prefix2str (addr, buf, sizeof (buf)); \ - if (debug) \ - zlog_debug ("Filter out Loopback: %s", buf); \ - continue; \ - } - -#define CONTINUE_IF_ADDRESS_V4COMPAT(debug,addr) \ - if (IN6_IS_ADDR_V4COMPAT (&(addr)->u.prefix6)) \ - { \ - char buf[PREFIX2STR_BUFFER]; \ - prefix2str (addr, buf, sizeof (buf)); \ - if (debug) \ - zlog_debug ("Filter out V4Compat: %s", buf); \ - continue; \ - } - -#define CONTINUE_IF_ADDRESS_V4MAPPED(debug,addr) \ - if (IN6_IS_ADDR_V4MAPPED (&(addr)->u.prefix6)) \ - { \ - char buf[PREFIX2STR_BUFFER]; \ - prefix2str (addr, buf, sizeof (buf)); \ - if (debug) \ - zlog_debug ("Filter out V4Mapped: %s", buf); \ - continue; \ - } +#define CONTINUE_IF_ADDRESS_LINKLOCAL(debug, addr) \ + if (IN6_IS_ADDR_LINKLOCAL(&(addr)->u.prefix6)) { \ + char buf[PREFIX2STR_BUFFER]; \ + prefix2str(addr, buf, sizeof(buf)); \ + if (debug) \ + zlog_debug("Filter out Linklocal: %s", buf); \ + continue; \ + } + +#define CONTINUE_IF_ADDRESS_UNSPECIFIED(debug, addr) \ + if (IN6_IS_ADDR_UNSPECIFIED(&(addr)->u.prefix6)) { \ + char buf[PREFIX2STR_BUFFER]; \ + prefix2str(addr, buf, sizeof(buf)); \ + if (debug) \ + zlog_debug("Filter out Unspecified: %s", buf); \ + continue; \ + } + +#define CONTINUE_IF_ADDRESS_LOOPBACK(debug, addr) \ + if (IN6_IS_ADDR_LOOPBACK(&(addr)->u.prefix6)) { \ + char buf[PREFIX2STR_BUFFER]; \ + prefix2str(addr, buf, sizeof(buf)); \ + if (debug) \ + zlog_debug("Filter out Loopback: %s", buf); \ + continue; \ + } + +#define CONTINUE_IF_ADDRESS_V4COMPAT(debug, addr) \ + if (IN6_IS_ADDR_V4COMPAT(&(addr)->u.prefix6)) { \ + char buf[PREFIX2STR_BUFFER]; \ + prefix2str(addr, buf, sizeof(buf)); \ + if (debug) \ + zlog_debug("Filter out V4Compat: %s", buf); \ + continue; \ + } + +#define CONTINUE_IF_ADDRESS_V4MAPPED(debug, addr) \ + if (IN6_IS_ADDR_V4MAPPED(&(addr)->u.prefix6)) { \ + char buf[PREFIX2STR_BUFFER]; \ + prefix2str(addr, buf, sizeof(buf)); \ + if (debug) \ + zlog_debug("Filter out V4Mapped: %s", buf); \ + continue; \ + } /* Function Prototypes */ -extern const char *ospf6_lstype_name (u_int16_t type); -extern const char *ospf6_lstype_short_name (u_int16_t type); -extern u_char ospf6_lstype_debug (u_int16_t type); -extern int ospf6_lsa_is_differ (struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2); -extern int ospf6_lsa_is_changed (struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2); -extern u_int16_t ospf6_lsa_age_current (struct ospf6_lsa *); -extern void ospf6_lsa_age_update_to_send (struct ospf6_lsa *, u_int32_t); -extern void ospf6_lsa_premature_aging (struct ospf6_lsa *); -extern int ospf6_lsa_compare (struct ospf6_lsa *, struct ospf6_lsa *); - -extern char *ospf6_lsa_printbuf (struct ospf6_lsa *lsa, char *buf, int size); -extern void ospf6_lsa_header_print_raw (struct ospf6_lsa_header *header); -extern void ospf6_lsa_header_print (struct ospf6_lsa *lsa); -extern void ospf6_lsa_show_summary_header (struct vty *vty); -extern void ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa); -extern void ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa); -extern void ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa); -extern void ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa); - -extern struct ospf6_lsa *ospf6_lsa_create (struct ospf6_lsa_header *header); -extern struct ospf6_lsa *ospf6_lsa_create_headeronly (struct ospf6_lsa_header *header); -extern void ospf6_lsa_delete (struct ospf6_lsa *lsa); -extern struct ospf6_lsa *ospf6_lsa_copy (struct ospf6_lsa *); - -extern void ospf6_lsa_lock (struct ospf6_lsa *); -extern void ospf6_lsa_unlock (struct ospf6_lsa *); - -extern int ospf6_lsa_expire (struct thread *); -extern int ospf6_lsa_refresh (struct thread *); - -extern unsigned short ospf6_lsa_checksum (struct ospf6_lsa_header *); -extern int ospf6_lsa_checksum_valid (struct ospf6_lsa_header *); -extern int ospf6_lsa_prohibited_duration (u_int16_t type, u_int32_t id, - u_int32_t adv_router, void *scope); - -extern void ospf6_install_lsa_handler (struct ospf6_lsa_handler *handler); -extern struct ospf6_lsa_handler *ospf6_get_lsa_handler (u_int16_t type); - -extern void ospf6_lsa_init (void); -extern void ospf6_lsa_terminate (void); - -extern int config_write_ospf6_debug_lsa (struct vty *vty); -extern void install_element_ospf6_debug_lsa (void); +extern const char *ospf6_lstype_name(u_int16_t type); +extern const char *ospf6_lstype_short_name(u_int16_t type); +extern u_char ospf6_lstype_debug(u_int16_t type); +extern int ospf6_lsa_is_differ(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2); +extern int ospf6_lsa_is_changed(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2); +extern u_int16_t ospf6_lsa_age_current(struct ospf6_lsa *); +extern void ospf6_lsa_age_update_to_send(struct ospf6_lsa *, u_int32_t); +extern void ospf6_lsa_premature_aging(struct ospf6_lsa *); +extern int ospf6_lsa_compare(struct ospf6_lsa *, struct ospf6_lsa *); + +extern char *ospf6_lsa_printbuf(struct ospf6_lsa *lsa, char *buf, int size); +extern void ospf6_lsa_header_print_raw(struct ospf6_lsa_header *header); +extern void ospf6_lsa_header_print(struct ospf6_lsa *lsa); +extern void ospf6_lsa_show_summary_header(struct vty *vty); +extern void ospf6_lsa_show_summary(struct vty *vty, struct ospf6_lsa *lsa); +extern void ospf6_lsa_show_dump(struct vty *vty, struct ospf6_lsa *lsa); +extern void ospf6_lsa_show_internal(struct vty *vty, struct ospf6_lsa *lsa); +extern void ospf6_lsa_show(struct vty *vty, struct ospf6_lsa *lsa); + +extern struct ospf6_lsa *ospf6_lsa_create(struct ospf6_lsa_header *header); +extern struct ospf6_lsa * +ospf6_lsa_create_headeronly(struct ospf6_lsa_header *header); +extern void ospf6_lsa_delete(struct ospf6_lsa *lsa); +extern struct ospf6_lsa *ospf6_lsa_copy(struct ospf6_lsa *); + +extern void ospf6_lsa_lock(struct ospf6_lsa *); +extern void ospf6_lsa_unlock(struct ospf6_lsa *); + +extern int ospf6_lsa_expire(struct thread *); +extern int ospf6_lsa_refresh(struct thread *); + +extern unsigned short ospf6_lsa_checksum(struct ospf6_lsa_header *); +extern int ospf6_lsa_checksum_valid(struct ospf6_lsa_header *); +extern int ospf6_lsa_prohibited_duration(u_int16_t type, u_int32_t id, + u_int32_t adv_router, void *scope); + +extern void ospf6_install_lsa_handler(struct ospf6_lsa_handler *handler); +extern struct ospf6_lsa_handler *ospf6_get_lsa_handler(u_int16_t type); + +extern void ospf6_lsa_init(void); +extern void ospf6_lsa_terminate(void); + +extern int config_write_ospf6_debug_lsa(struct vty *vty); +extern void install_element_ospf6_debug_lsa(void); #endif /* OSPF6_LSA_H */ - diff --git a/ospf6d/ospf6_lsdb.c b/ospf6d/ospf6_lsdb.c index ed0180065..23a33d312 100644 --- a/ospf6d/ospf6_lsdb.c +++ b/ospf6d/ospf6_lsdb.c @@ -34,454 +34,410 @@ #include "ospf6d.h" #include "bitfield.h" -struct ospf6_lsdb * -ospf6_lsdb_create (void *data) +struct ospf6_lsdb *ospf6_lsdb_create(void *data) { - struct ospf6_lsdb *lsdb; - - lsdb = XCALLOC (MTYPE_OSPF6_LSDB, sizeof (struct ospf6_lsdb)); - if (lsdb == NULL) - { - zlog_warn ("Can't malloc lsdb"); - return NULL; - } - memset (lsdb, 0, sizeof (struct ospf6_lsdb)); - - lsdb->data = data; - lsdb->table = route_table_init (); - return lsdb; + struct ospf6_lsdb *lsdb; + + lsdb = XCALLOC(MTYPE_OSPF6_LSDB, sizeof(struct ospf6_lsdb)); + if (lsdb == NULL) { + zlog_warn("Can't malloc lsdb"); + return NULL; + } + memset(lsdb, 0, sizeof(struct ospf6_lsdb)); + + lsdb->data = data; + lsdb->table = route_table_init(); + return lsdb; } -void -ospf6_lsdb_delete (struct ospf6_lsdb *lsdb) +void ospf6_lsdb_delete(struct ospf6_lsdb *lsdb) { - if (lsdb != NULL) - { - ospf6_lsdb_remove_all (lsdb); - route_table_finish (lsdb->table); - XFREE (MTYPE_OSPF6_LSDB, lsdb); - } + if (lsdb != NULL) { + ospf6_lsdb_remove_all(lsdb); + route_table_finish(lsdb->table); + XFREE(MTYPE_OSPF6_LSDB, lsdb); + } } -static void -ospf6_lsdb_set_key (struct prefix_ipv6 *key, const void *value, int len) +static void ospf6_lsdb_set_key(struct prefix_ipv6 *key, const void *value, + int len) { - assert (key->prefixlen % 8 == 0); + assert(key->prefixlen % 8 == 0); - memcpy ((caddr_t) &key->prefix + key->prefixlen / 8, - (caddr_t) value, len); - key->family = AF_INET6; - key->prefixlen += len * 8; + memcpy((caddr_t)&key->prefix + key->prefixlen / 8, (caddr_t)value, len); + key->family = AF_INET6; + key->prefixlen += len * 8; } #ifdef DEBUG -static void -_lsdb_count_assert (struct ospf6_lsdb *lsdb) +static void _lsdb_count_assert(struct ospf6_lsdb *lsdb) { - struct ospf6_lsa *debug; - unsigned int num = 0; - for (ALL_LSDB(lsdb, debug)) - num++; - - if (num == lsdb->count) - return; - - zlog_debug ("PANIC !! lsdb[%p]->count = %d, real = %d", - lsdb, lsdb->count, num); - for (ALL_LSDB(lsdb, debug)) - zlog_debug ("%p %p %s lsdb[%p]", debug->prev, debug->next, debug->name, - debug->lsdb); - zlog_debug ("DUMP END"); - - assert (num == lsdb->count); + struct ospf6_lsa *debug; + unsigned int num = 0; + for (ALL_LSDB(lsdb, debug)) + num++; + + if (num == lsdb->count) + return; + + zlog_debug("PANIC !! lsdb[%p]->count = %d, real = %d", lsdb, + lsdb->count, num); + for (ALL_LSDB(lsdb, debug)) + zlog_debug("%p %p %s lsdb[%p]", debug->prev, debug->next, + debug->name, debug->lsdb); + zlog_debug("DUMP END"); + + assert(num == lsdb->count); } #define ospf6_lsdb_count_assert(t) (_lsdb_count_assert (t)) -#else /*DEBUG*/ +#else /*DEBUG*/ #define ospf6_lsdb_count_assert(t) ((void) 0) #endif /*DEBUG*/ -void -ospf6_lsdb_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb) +void ospf6_lsdb_add(struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb) { - struct prefix_ipv6 key; - struct route_node *current; - struct ospf6_lsa *old = NULL; - - memset (&key, 0, sizeof (key)); - ospf6_lsdb_set_key (&key, &lsa->header->type, sizeof (lsa->header->type)); - ospf6_lsdb_set_key (&key, &lsa->header->adv_router, - sizeof (lsa->header->adv_router)); - ospf6_lsdb_set_key (&key, &lsa->header->id, sizeof (lsa->header->id)); - - current = route_node_get (lsdb->table, (struct prefix *) &key); - old = current->info; - current->info = lsa; - lsa->rn = current; - ospf6_lsa_lock (lsa); - - if (!old) - { - lsdb->count++; - - if (OSPF6_LSA_IS_MAXAGE (lsa)) - { - if (lsdb->hook_remove) - (*lsdb->hook_remove) (lsa); + struct prefix_ipv6 key; + struct route_node *current; + struct ospf6_lsa *old = NULL; + + memset(&key, 0, sizeof(key)); + ospf6_lsdb_set_key(&key, &lsa->header->type, sizeof(lsa->header->type)); + ospf6_lsdb_set_key(&key, &lsa->header->adv_router, + sizeof(lsa->header->adv_router)); + ospf6_lsdb_set_key(&key, &lsa->header->id, sizeof(lsa->header->id)); + + current = route_node_get(lsdb->table, (struct prefix *)&key); + old = current->info; + current->info = lsa; + lsa->rn = current; + ospf6_lsa_lock(lsa); + + if (!old) { + lsdb->count++; + + if (OSPF6_LSA_IS_MAXAGE(lsa)) { + if (lsdb->hook_remove) + (*lsdb->hook_remove)(lsa); + } else { + if (lsdb->hook_add) + (*lsdb->hook_add)(lsa); + } + } else { + if (OSPF6_LSA_IS_CHANGED(old, lsa)) { + if (OSPF6_LSA_IS_MAXAGE(lsa)) { + if (lsdb->hook_remove) { + (*lsdb->hook_remove)(old); + (*lsdb->hook_remove)(lsa); + } + } else if (OSPF6_LSA_IS_MAXAGE(old)) { + if (lsdb->hook_add) + (*lsdb->hook_add)(lsa); + } else { + if (lsdb->hook_remove) + (*lsdb->hook_remove)(old); + if (lsdb->hook_add) + (*lsdb->hook_add)(lsa); + } + } + ospf6_lsa_unlock(old); } - else - { - if (lsdb->hook_add) - (*lsdb->hook_add) (lsa); - } - } - else - { - if (OSPF6_LSA_IS_CHANGED (old, lsa)) - { - if (OSPF6_LSA_IS_MAXAGE (lsa)) - { - if (lsdb->hook_remove) - { - (*lsdb->hook_remove) (old); - (*lsdb->hook_remove) (lsa); - } - } - else if (OSPF6_LSA_IS_MAXAGE (old)) - { - if (lsdb->hook_add) - (*lsdb->hook_add) (lsa); - } - else - { - if (lsdb->hook_remove) - (*lsdb->hook_remove) (old); - if (lsdb->hook_add) - (*lsdb->hook_add) (lsa); - } - } - ospf6_lsa_unlock (old); - } - - ospf6_lsdb_count_assert (lsdb); + + ospf6_lsdb_count_assert(lsdb); } -void -ospf6_lsdb_remove (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb) +void ospf6_lsdb_remove(struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb) { - struct route_node *node; - struct prefix_ipv6 key; + struct route_node *node; + struct prefix_ipv6 key; - memset (&key, 0, sizeof (key)); - ospf6_lsdb_set_key (&key, &lsa->header->type, sizeof (lsa->header->type)); - ospf6_lsdb_set_key (&key, &lsa->header->adv_router, - sizeof (lsa->header->adv_router)); - ospf6_lsdb_set_key (&key, &lsa->header->id, sizeof (lsa->header->id)); + memset(&key, 0, sizeof(key)); + ospf6_lsdb_set_key(&key, &lsa->header->type, sizeof(lsa->header->type)); + ospf6_lsdb_set_key(&key, &lsa->header->adv_router, + sizeof(lsa->header->adv_router)); + ospf6_lsdb_set_key(&key, &lsa->header->id, sizeof(lsa->header->id)); - node = route_node_lookup (lsdb->table, (struct prefix *) &key); - assert (node && node->info == lsa); + node = route_node_lookup(lsdb->table, (struct prefix *)&key); + assert(node && node->info == lsa); - node->info = NULL; - lsdb->count--; + node->info = NULL; + lsdb->count--; - if (lsdb->hook_remove) - (*lsdb->hook_remove) (lsa); + if (lsdb->hook_remove) + (*lsdb->hook_remove)(lsa); - route_unlock_node (node); /* to free the lookup lock */ - route_unlock_node (node); /* to free the original lock */ - ospf6_lsa_unlock (lsa); + route_unlock_node(node); /* to free the lookup lock */ + route_unlock_node(node); /* to free the original lock */ + ospf6_lsa_unlock(lsa); - ospf6_lsdb_count_assert (lsdb); + ospf6_lsdb_count_assert(lsdb); } -struct ospf6_lsa * -ospf6_lsdb_lookup (u_int16_t type, u_int32_t id, u_int32_t adv_router, - struct ospf6_lsdb *lsdb) +struct ospf6_lsa *ospf6_lsdb_lookup(u_int16_t type, u_int32_t id, + u_int32_t adv_router, + struct ospf6_lsdb *lsdb) { - struct route_node *node; - struct prefix_ipv6 key; + struct route_node *node; + struct prefix_ipv6 key; - if (lsdb == NULL) - return NULL; + if (lsdb == NULL) + return NULL; - memset (&key, 0, sizeof (key)); - ospf6_lsdb_set_key (&key, &type, sizeof (type)); - ospf6_lsdb_set_key (&key, &adv_router, sizeof (adv_router)); - ospf6_lsdb_set_key (&key, &id, sizeof (id)); + memset(&key, 0, sizeof(key)); + ospf6_lsdb_set_key(&key, &type, sizeof(type)); + ospf6_lsdb_set_key(&key, &adv_router, sizeof(adv_router)); + ospf6_lsdb_set_key(&key, &id, sizeof(id)); - node = route_node_lookup (lsdb->table, (struct prefix *) &key); - if (node == NULL || node->info == NULL) - return NULL; + node = route_node_lookup(lsdb->table, (struct prefix *)&key); + if (node == NULL || node->info == NULL) + return NULL; - route_unlock_node (node); - return (struct ospf6_lsa *) node->info; + route_unlock_node(node); + return (struct ospf6_lsa *)node->info; } -struct ospf6_lsa * -ospf6_lsdb_lookup_next (u_int16_t type, u_int32_t id, u_int32_t adv_router, - struct ospf6_lsdb *lsdb) +struct ospf6_lsa *ospf6_lsdb_lookup_next(u_int16_t type, u_int32_t id, + u_int32_t adv_router, + struct ospf6_lsdb *lsdb) { - struct route_node *node; - struct prefix_ipv6 key; + struct route_node *node; + struct prefix_ipv6 key; - if (lsdb == NULL) - return NULL; + if (lsdb == NULL) + return NULL; - memset (&key, 0, sizeof (key)); - ospf6_lsdb_set_key (&key, &type, sizeof (type)); - ospf6_lsdb_set_key (&key, &adv_router, sizeof (adv_router)); - ospf6_lsdb_set_key (&key, &id, sizeof (id)); + memset(&key, 0, sizeof(key)); + ospf6_lsdb_set_key(&key, &type, sizeof(type)); + ospf6_lsdb_set_key(&key, &adv_router, sizeof(adv_router)); + ospf6_lsdb_set_key(&key, &id, sizeof(id)); - { - char buf[PREFIX2STR_BUFFER]; - prefix2str (&key, buf, sizeof (buf)); - zlog_debug ("lsdb_lookup_next: key: %s", buf); - } + { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&key, buf, sizeof(buf)); + zlog_debug("lsdb_lookup_next: key: %s", buf); + } - node = route_table_get_next (lsdb->table, &key); + node = route_table_get_next(lsdb->table, &key); - /* skip to real existing entry */ - while (node && node->info == NULL) - node = route_next (node); + /* skip to real existing entry */ + while (node && node->info == NULL) + node = route_next(node); - if (! node) - return NULL; + if (!node) + return NULL; - route_unlock_node (node); - if (! node->info) - return NULL; + route_unlock_node(node); + if (!node->info) + return NULL; - return (struct ospf6_lsa *) node->info; + return (struct ospf6_lsa *)node->info; } -const struct route_node * -ospf6_lsdb_head (struct ospf6_lsdb *lsdb, - int argmode, uint16_t type, uint32_t adv_router, - struct ospf6_lsa **lsa) +const struct route_node *ospf6_lsdb_head(struct ospf6_lsdb *lsdb, int argmode, + uint16_t type, uint32_t adv_router, + struct ospf6_lsa **lsa) { - struct route_node *node, *end; - - *lsa = NULL; - - if (argmode > 0) - { - struct prefix_ipv6 key = { .family = AF_INET6, .prefixlen = 0 }; - - ospf6_lsdb_set_key (&key, &type, sizeof (type)); - if (argmode > 1) - ospf6_lsdb_set_key (&key, &adv_router, sizeof (adv_router)); - - node = route_table_get_next (lsdb->table, &key); - if (!node || !prefix_match((struct prefix *)&key, &node->p)) - return NULL; - - for (end = node; - end && end->parent && end->parent->p.prefixlen >= key.prefixlen; - end = end->parent) - ; - } - else - { - node = route_top (lsdb->table); - end = NULL; - } - - while (node && !node->info) - node = route_next_until(node, end); - - if (!node) - return NULL; - if (!node->info) - { - route_unlock_node(node); - return NULL; - } - - *lsa = node->info; - ospf6_lsa_lock (*lsa); - - return end; + struct route_node *node, *end; + + *lsa = NULL; + + if (argmode > 0) { + struct prefix_ipv6 key = {.family = AF_INET6, .prefixlen = 0}; + + ospf6_lsdb_set_key(&key, &type, sizeof(type)); + if (argmode > 1) + ospf6_lsdb_set_key(&key, &adv_router, + sizeof(adv_router)); + + node = route_table_get_next(lsdb->table, &key); + if (!node || !prefix_match((struct prefix *)&key, &node->p)) + return NULL; + + for (end = node; end && end->parent + && end->parent->p.prefixlen >= key.prefixlen; + end = end->parent) + ; + } else { + node = route_top(lsdb->table); + end = NULL; + } + + while (node && !node->info) + node = route_next_until(node, end); + + if (!node) + return NULL; + if (!node->info) { + route_unlock_node(node); + return NULL; + } + + *lsa = node->info; + ospf6_lsa_lock(*lsa); + + return end; } -struct ospf6_lsa * -ospf6_lsdb_next (const struct route_node *iterend, - struct ospf6_lsa *lsa) +struct ospf6_lsa *ospf6_lsdb_next(const struct route_node *iterend, + struct ospf6_lsa *lsa) { - struct route_node *node = lsa->rn; + struct route_node *node = lsa->rn; - ospf6_lsa_unlock(lsa); + ospf6_lsa_unlock(lsa); - do - node = route_next_until(node, iterend); - while (node && !node->info); + do + node = route_next_until(node, iterend); + while (node && !node->info); - if (node && node->info) - { - struct ospf6_lsa *next = node->info; - ospf6_lsa_lock (next); - return next; - } + if (node && node->info) { + struct ospf6_lsa *next = node->info; + ospf6_lsa_lock(next); + return next; + } - if (node) - route_unlock_node (node); - return NULL; + if (node) + route_unlock_node(node); + return NULL; } -void -ospf6_lsdb_remove_all (struct ospf6_lsdb *lsdb) +void ospf6_lsdb_remove_all(struct ospf6_lsdb *lsdb) { - struct ospf6_lsa *lsa; + struct ospf6_lsa *lsa; - if (lsdb == NULL) - return; + if (lsdb == NULL) + return; - for (ALL_LSDB(lsdb, lsa)) - ospf6_lsdb_remove (lsa, lsdb); + for (ALL_LSDB(lsdb, lsa)) + ospf6_lsdb_remove(lsa, lsdb); } -void -ospf6_lsdb_lsa_unlock (struct ospf6_lsa *lsa) +void ospf6_lsdb_lsa_unlock(struct ospf6_lsa *lsa) { - if (lsa != NULL) - { - if (lsa->rn != NULL) - route_unlock_node (lsa->rn); - ospf6_lsa_unlock (lsa); - } + if (lsa != NULL) { + if (lsa->rn != NULL) + route_unlock_node(lsa->rn); + ospf6_lsa_unlock(lsa); + } } -int -ospf6_lsdb_maxage_remover (struct ospf6_lsdb *lsdb) +int ospf6_lsdb_maxage_remover(struct ospf6_lsdb *lsdb) { - int reschedule = 0; - struct ospf6_lsa *lsa; - - for (ALL_LSDB(lsdb, lsa)) - { - if (! OSPF6_LSA_IS_MAXAGE (lsa)) - continue; - if (lsa->retrans_count != 0) - { - reschedule = 1; - continue; + int reschedule = 0; + struct ospf6_lsa *lsa; + + for (ALL_LSDB(lsdb, lsa)) { + if (!OSPF6_LSA_IS_MAXAGE(lsa)) + continue; + if (lsa->retrans_count != 0) { + reschedule = 1; + continue; + } + if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)) + zlog_debug("Remove MaxAge %s", lsa->name); + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED)) { + UNSET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED); + /* + * lsa->header->age = 0; + */ + lsa->header->seqnum = + htonl(OSPF_MAX_SEQUENCE_NUMBER + 1); + ospf6_lsa_checksum(lsa->header); + + THREAD_OFF(lsa->refresh); + thread_execute(master, ospf6_lsa_refresh, lsa, 0); + } else { + ospf6_lsdb_remove(lsa, lsdb); + } } - if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type)) - zlog_debug ("Remove MaxAge %s", lsa->name); - if (CHECK_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED)) - { - UNSET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED); - /* - * lsa->header->age = 0; - */ - lsa->header->seqnum = htonl(OSPF_MAX_SEQUENCE_NUMBER + 1); - ospf6_lsa_checksum (lsa->header); - - THREAD_OFF(lsa->refresh); - thread_execute (master, ospf6_lsa_refresh, lsa, 0); - } else { - ospf6_lsdb_remove (lsa, lsdb); - } - } - - return (reschedule); + + return (reschedule); } -void -ospf6_lsdb_show (struct vty *vty, enum ospf_lsdb_show_level level, - u_int16_t *type, u_int32_t *id, u_int32_t *adv_router, - struct ospf6_lsdb *lsdb) +void ospf6_lsdb_show(struct vty *vty, enum ospf_lsdb_show_level level, + u_int16_t *type, u_int32_t *id, u_int32_t *adv_router, + struct ospf6_lsdb *lsdb) { - struct ospf6_lsa *lsa; - const struct route_node *end = NULL; - void (*showfunc) (struct vty *, struct ospf6_lsa *) = NULL; - - switch (level) - { - case OSPF6_LSDB_SHOW_LEVEL_DETAIL: - showfunc = ospf6_lsa_show; - break; - case OSPF6_LSDB_SHOW_LEVEL_INTERNAL: - showfunc = ospf6_lsa_show_internal; - break; - case OSPF6_LSDB_SHOW_LEVEL_DUMP: - showfunc = ospf6_lsa_show_dump; - break; - case OSPF6_LSDB_SHOW_LEVEL_NORMAL: - default: - showfunc = ospf6_lsa_show_summary; - } - - if (type && id && adv_router) - { - lsa = ospf6_lsdb_lookup (*type, *id, *adv_router, lsdb); - if (lsa) - { - if (level == OSPF6_LSDB_SHOW_LEVEL_NORMAL) - ospf6_lsa_show (vty, lsa); - else - (*showfunc) (vty, lsa); - } - return; - } - - if (level == OSPF6_LSDB_SHOW_LEVEL_NORMAL) - ospf6_lsa_show_summary_header (vty); - - end = ospf6_lsdb_head(lsdb, !!type + !!(type && adv_router), - *type, *adv_router, &lsa); - while (lsa) - { - if ((! adv_router || lsa->header->adv_router == *adv_router) && - (! id || lsa->header->id == *id)) - (*showfunc) (vty, lsa); - - lsa = ospf6_lsdb_next (end, lsa); - } + struct ospf6_lsa *lsa; + const struct route_node *end = NULL; + void (*showfunc)(struct vty *, struct ospf6_lsa *) = NULL; + + switch (level) { + case OSPF6_LSDB_SHOW_LEVEL_DETAIL: + showfunc = ospf6_lsa_show; + break; + case OSPF6_LSDB_SHOW_LEVEL_INTERNAL: + showfunc = ospf6_lsa_show_internal; + break; + case OSPF6_LSDB_SHOW_LEVEL_DUMP: + showfunc = ospf6_lsa_show_dump; + break; + case OSPF6_LSDB_SHOW_LEVEL_NORMAL: + default: + showfunc = ospf6_lsa_show_summary; + } + + if (type && id && adv_router) { + lsa = ospf6_lsdb_lookup(*type, *id, *adv_router, lsdb); + if (lsa) { + if (level == OSPF6_LSDB_SHOW_LEVEL_NORMAL) + ospf6_lsa_show(vty, lsa); + else + (*showfunc)(vty, lsa); + } + return; + } + + if (level == OSPF6_LSDB_SHOW_LEVEL_NORMAL) + ospf6_lsa_show_summary_header(vty); + + end = ospf6_lsdb_head(lsdb, !!type + !!(type && adv_router), *type, + *adv_router, &lsa); + while (lsa) { + if ((!adv_router || lsa->header->adv_router == *adv_router) + && (!id || lsa->header->id == *id)) + (*showfunc)(vty, lsa); + + lsa = ospf6_lsdb_next(end, lsa); + } } -u_int32_t -ospf6_new_ls_id (u_int16_t type, u_int32_t adv_router, - struct ospf6_lsdb *lsdb) +u_int32_t ospf6_new_ls_id(u_int16_t type, u_int32_t adv_router, + struct ospf6_lsdb *lsdb) { - struct ospf6_lsa *lsa; - u_int32_t id = 1, tmp_id; - - /* This routine is curently invoked only for Inter-Prefix LSAs for - * non-summarized routes (no area/range). - */ - for (ALL_LSDB_TYPED_ADVRTR(lsdb, type, adv_router, lsa)) - { - tmp_id = ntohl (lsa->header->id); - if (tmp_id < id) - continue; - - if (tmp_id > id) - { - ospf6_lsdb_lsa_unlock (lsa); - break; - } - id++; - } - - return ((u_int32_t) htonl (id)); + struct ospf6_lsa *lsa; + u_int32_t id = 1, tmp_id; + + /* This routine is curently invoked only for Inter-Prefix LSAs for + * non-summarized routes (no area/range). + */ + for (ALL_LSDB_TYPED_ADVRTR(lsdb, type, adv_router, lsa)) { + tmp_id = ntohl(lsa->header->id); + if (tmp_id < id) + continue; + + if (tmp_id > id) { + ospf6_lsdb_lsa_unlock(lsa); + break; + } + id++; + } + + return ((u_int32_t)htonl(id)); } /* Decide new LS sequence number to originate. note return value is network byte order */ -u_int32_t -ospf6_new_ls_seqnum (u_int16_t type, u_int32_t id, u_int32_t adv_router, - struct ospf6_lsdb *lsdb) +u_int32_t ospf6_new_ls_seqnum(u_int16_t type, u_int32_t id, + u_int32_t adv_router, struct ospf6_lsdb *lsdb) { - struct ospf6_lsa *lsa; - signed long seqnum = 0; + struct ospf6_lsa *lsa; + signed long seqnum = 0; - /* if current database copy not found, return InitialSequenceNumber */ - lsa = ospf6_lsdb_lookup (type, id, adv_router, lsdb); - if (lsa == NULL) - seqnum = OSPF_INITIAL_SEQUENCE_NUMBER; - else - seqnum = (signed long) ntohl (lsa->header->seqnum) + 1; + /* if current database copy not found, return InitialSequenceNumber */ + lsa = ospf6_lsdb_lookup(type, id, adv_router, lsdb); + if (lsa == NULL) + seqnum = OSPF_INITIAL_SEQUENCE_NUMBER; + else + seqnum = (signed long)ntohl(lsa->header->seqnum) + 1; - return ((u_int32_t) htonl (seqnum)); + return ((u_int32_t)htonl(seqnum)); } - - diff --git a/ospf6d/ospf6_lsdb.h b/ospf6d/ospf6_lsdb.h index 0eb5322b4..41e54b5d8 100644 --- a/ospf6d/ospf6_lsdb.h +++ b/ospf6d/ospf6_lsdb.h @@ -25,76 +25,72 @@ #include "table.h" #include "ospf6_route.h" -struct ospf6_lsdb -{ - void *data; /* data structure that holds this lsdb */ - struct route_table *table; - u_int32_t count; - void (*hook_add) (struct ospf6_lsa *); - void (*hook_remove) (struct ospf6_lsa *); +struct ospf6_lsdb { + void *data; /* data structure that holds this lsdb */ + struct route_table *table; + u_int32_t count; + void (*hook_add)(struct ospf6_lsa *); + void (*hook_remove)(struct ospf6_lsa *); }; /* Function Prototypes */ -extern struct ospf6_lsdb *ospf6_lsdb_create (void *data); -extern void ospf6_lsdb_delete (struct ospf6_lsdb *lsdb); +extern struct ospf6_lsdb *ospf6_lsdb_create(void *data); +extern void ospf6_lsdb_delete(struct ospf6_lsdb *lsdb); -extern struct ospf6_lsa *ospf6_lsdb_lookup (u_int16_t type, u_int32_t id, - u_int32_t adv_router, - struct ospf6_lsdb *lsdb); -extern struct ospf6_lsa *ospf6_lsdb_lookup_next (u_int16_t type, u_int32_t id, - u_int32_t adv_router, - struct ospf6_lsdb *lsdb); +extern struct ospf6_lsa *ospf6_lsdb_lookup(u_int16_t type, u_int32_t id, + u_int32_t adv_router, + struct ospf6_lsdb *lsdb); +extern struct ospf6_lsa *ospf6_lsdb_lookup_next(u_int16_t type, u_int32_t id, + u_int32_t adv_router, + struct ospf6_lsdb *lsdb); -extern void ospf6_lsdb_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb); -extern void ospf6_lsdb_remove (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb); +extern void ospf6_lsdb_add(struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb); +extern void ospf6_lsdb_remove(struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb); -extern const struct route_node *ospf6_lsdb_head ( - struct ospf6_lsdb *lsdb, - int argmode, - uint16_t type, - uint32_t adv_router, - struct ospf6_lsa **lsa); -extern struct ospf6_lsa *ospf6_lsdb_next (const struct route_node *iterend, - struct ospf6_lsa *lsa); +extern const struct route_node *ospf6_lsdb_head(struct ospf6_lsdb *lsdb, + int argmode, uint16_t type, + uint32_t adv_router, + struct ospf6_lsa **lsa); +extern struct ospf6_lsa *ospf6_lsdb_next(const struct route_node *iterend, + struct ospf6_lsa *lsa); -#define ALL_LSDB_TYPED_ADVRTR(lsdb, type, adv_router, lsa) \ - const struct route_node *iterend = \ - ospf6_lsdb_head(lsdb, 2, type, adv_router, &lsa); \ - lsa; \ +#define ALL_LSDB_TYPED_ADVRTR(lsdb, type, adv_router, lsa) \ + const struct route_node *iterend = \ + ospf6_lsdb_head(lsdb, 2, type, adv_router, &lsa); \ + lsa; \ lsa = ospf6_lsdb_next(iterend, lsa) -#define ALL_LSDB_TYPED(lsdb, type, lsa) \ - const struct route_node *iterend = \ - ospf6_lsdb_head(lsdb, 1, type, 0, &lsa); \ - lsa; \ +#define ALL_LSDB_TYPED(lsdb, type, lsa) \ + const struct route_node *iterend = \ + ospf6_lsdb_head(lsdb, 1, type, 0, &lsa); \ + lsa; \ lsa = ospf6_lsdb_next(iterend, lsa) -#define ALL_LSDB(lsdb, lsa) \ - const struct route_node *iterend = \ - ospf6_lsdb_head(lsdb, 0, 0, 0, &lsa); \ - lsa; \ +#define ALL_LSDB(lsdb, lsa) \ + const struct route_node *iterend = \ + ospf6_lsdb_head(lsdb, 0, 0, 0, &lsa); \ + lsa; \ lsa = ospf6_lsdb_next(iterend, lsa) -extern void ospf6_lsdb_remove_all (struct ospf6_lsdb *lsdb); -extern void ospf6_lsdb_lsa_unlock (struct ospf6_lsa *lsa); +extern void ospf6_lsdb_remove_all(struct ospf6_lsdb *lsdb); +extern void ospf6_lsdb_lsa_unlock(struct ospf6_lsa *lsa); enum ospf_lsdb_show_level { - OSPF6_LSDB_SHOW_LEVEL_NORMAL = 0, - OSPF6_LSDB_SHOW_LEVEL_DETAIL, - OSPF6_LSDB_SHOW_LEVEL_INTERNAL, - OSPF6_LSDB_SHOW_LEVEL_DUMP, + OSPF6_LSDB_SHOW_LEVEL_NORMAL = 0, + OSPF6_LSDB_SHOW_LEVEL_DETAIL, + OSPF6_LSDB_SHOW_LEVEL_INTERNAL, + OSPF6_LSDB_SHOW_LEVEL_DUMP, }; -extern void ospf6_lsdb_show (struct vty *vty, - enum ospf_lsdb_show_level level, u_int16_t *type, - u_int32_t *id, u_int32_t *adv_router, - struct ospf6_lsdb *lsdb); +extern void ospf6_lsdb_show(struct vty *vty, enum ospf_lsdb_show_level level, + u_int16_t *type, u_int32_t *id, + u_int32_t *adv_router, struct ospf6_lsdb *lsdb); -extern u_int32_t ospf6_new_ls_id (u_int16_t type, u_int32_t adv_router, - struct ospf6_lsdb *lsdb); -extern u_int32_t ospf6_new_ls_seqnum (u_int16_t type, u_int32_t id, - u_int32_t adv_router, - struct ospf6_lsdb *lsdb); -extern int ospf6_lsdb_maxage_remover (struct ospf6_lsdb *lsdb); +extern u_int32_t ospf6_new_ls_id(u_int16_t type, u_int32_t adv_router, + struct ospf6_lsdb *lsdb); +extern u_int32_t ospf6_new_ls_seqnum(u_int16_t type, u_int32_t id, + u_int32_t adv_router, + struct ospf6_lsdb *lsdb); +extern int ospf6_lsdb_maxage_remover(struct ospf6_lsdb *lsdb); #endif /* OSPF6_LSDB_H */ diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c index 0a4a3a28c..28bb956c4 100644 --- a/ospf6d/ospf6_main.c +++ b/ospf6d/ospf6_main.c @@ -55,187 +55,163 @@ #define OSPF6_VTY_PORT 2606 /* ospf6d privileges */ -zebra_capabilities_t _caps_p [] = -{ - ZCAP_NET_RAW, - ZCAP_BIND -}; +zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND}; -struct zebra_privs_t ospf6d_privs = -{ +struct zebra_privs_t ospf6d_privs = { #if defined(FRR_USER) - .user = FRR_USER, + .user = FRR_USER, #endif #if defined FRR_GROUP - .group = FRR_GROUP, + .group = FRR_GROUP, #endif #ifdef VTY_GROUP - .vty_group = VTY_GROUP, + .vty_group = VTY_GROUP, #endif - .caps_p = _caps_p, - .cap_num_p = 2, - .cap_num_i = 0 -}; + .caps_p = _caps_p, + .cap_num_p = 2, + .cap_num_i = 0}; /* ospf6d options, we use GNU getopt library. */ -struct option longopts[] = -{ - { 0 } -}; +struct option longopts[] = {{0}}; /* Master of threads. */ struct thread_master *master; -static void __attribute__ ((noreturn)) -ospf6_exit (int status) +static void __attribute__((noreturn)) ospf6_exit(int status) { - struct listnode *node; - struct interface *ifp; + struct listnode *node; + struct interface *ifp; - if (ospf6) - ospf6_delete (ospf6); + if (ospf6) + ospf6_delete(ospf6); - bfd_gbl_exit(); + bfd_gbl_exit(); - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - if (ifp->info != NULL) - ospf6_interface_delete(ifp->info); + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) + if (ifp->info != NULL) + ospf6_interface_delete(ifp->info); - ospf6_message_terminate (); - ospf6_asbr_terminate (); - ospf6_lsa_terminate (); + ospf6_message_terminate(); + ospf6_asbr_terminate(); + ospf6_lsa_terminate(); - vrf_terminate (); - vty_terminate (); - cmd_terminate (); + vrf_terminate(); + vty_terminate(); + cmd_terminate(); - if (zclient) - { - zclient_stop (zclient); - zclient_free (zclient); - } + if (zclient) { + zclient_stop(zclient); + zclient_free(zclient); + } - if (master) - thread_master_free (master); + if (master) + thread_master_free(master); - closezlog (); + closezlog(); - exit (status); + exit(status); } /* SIGHUP handler. */ -static void -sighup (void) +static void sighup(void) { - zlog_info ("SIGHUP received"); + zlog_info("SIGHUP received"); } /* SIGINT handler. */ -static void -sigint (void) +static void sigint(void) { - zlog_notice ("Terminating on signal SIGINT"); - ospf6_exit (0); + zlog_notice("Terminating on signal SIGINT"); + ospf6_exit(0); } /* SIGTERM handler. */ -static void -sigterm (void) +static void sigterm(void) { - zlog_notice ("Terminating on signal SIGTERM"); - ospf6_clean(); - ospf6_exit (0); + zlog_notice("Terminating on signal SIGTERM"); + ospf6_clean(); + ospf6_exit(0); } /* SIGUSR1 handler. */ -static void -sigusr1 (void) +static void sigusr1(void) { - zlog_info ("SIGUSR1 received"); - zlog_rotate(); + zlog_info("SIGUSR1 received"); + zlog_rotate(); } -struct quagga_signal_t ospf6_signals[] = -{ - { - .signal = SIGHUP, - .handler = &sighup, - }, - { - .signal = SIGINT, - .handler = &sigint, - }, - { - .signal = SIGTERM, - .handler = &sigterm, - }, - { - .signal = SIGUSR1, - .handler = &sigusr1, - }, +struct quagga_signal_t ospf6_signals[] = { + { + .signal = SIGHUP, + .handler = &sighup, + }, + { + .signal = SIGINT, + .handler = &sigint, + }, + { + .signal = SIGTERM, + .handler = &sigterm, + }, + { + .signal = SIGUSR1, + .handler = &sigusr1, + }, }; -FRR_DAEMON_INFO(ospf6d, OSPF6, - .vty_port = OSPF6_VTY_PORT, +FRR_DAEMON_INFO(ospf6d, OSPF6, .vty_port = OSPF6_VTY_PORT, - .proghelp = "Implementation of the OSPFv3 routing protocol.", + .proghelp = "Implementation of the OSPFv3 routing protocol.", - .signals = ospf6_signals, - .n_signals = array_size(ospf6_signals), + .signals = ospf6_signals, + .n_signals = array_size(ospf6_signals), - .privs = &ospf6d_privs, -) + .privs = &ospf6d_privs, ) /* Main routine of ospf6d. Treatment of argument and starting ospf finite state machine is handled here. */ -int -main (int argc, char *argv[], char *envp[]) +int main(int argc, char *argv[], char *envp[]) { - int opt; - - frr_preinit (&ospf6d_di, argc, argv); - frr_opt_add ("", longopts, ""); - - /* Command line argument treatment. */ - while (1) - { - opt = frr_getopt (argc, argv, NULL); - - if (opt == EOF) - break; - - switch (opt) - { - case 0: - break; - default: - frr_help_exit (1); - break; - } - } - - if (geteuid () != 0) - { - errno = EPERM; - perror (ospf6d_di.progname); - exit (1); - } - - /* thread master */ - master = frr_init (); - - vrf_init (NULL, NULL, NULL, NULL); - access_list_init (); - prefix_list_init (); - - /* initialize ospf6 */ - ospf6_init (); - - frr_config_fork (); - frr_run (master); - - /* Not reached. */ - ospf6_exit (0); -} + int opt; + + frr_preinit(&ospf6d_di, argc, argv); + frr_opt_add("", longopts, ""); + /* Command line argument treatment. */ + while (1) { + opt = frr_getopt(argc, argv, NULL); + if (opt == EOF) + break; + + switch (opt) { + case 0: + break; + default: + frr_help_exit(1); + break; + } + } + + if (geteuid() != 0) { + errno = EPERM; + perror(ospf6d_di.progname); + exit(1); + } + + /* thread master */ + master = frr_init(); + + vrf_init(NULL, NULL, NULL, NULL); + access_list_init(); + prefix_list_init(); + + /* initialize ospf6 */ + ospf6_init(); + + frr_config_fork(); + frr_run(master); + + /* Not reached. */ + ospf6_exit(0); +} diff --git a/ospf6d/ospf6_memory.c b/ospf6d/ospf6_memory.c index 35d03f7e4..133dc2cb3 100644 --- a/ospf6d/ospf6_memory.c +++ b/ospf6d/ospf6_memory.c @@ -26,18 +26,18 @@ #include "ospf6_memory.h" DEFINE_MGROUP(OSPF6D, "ospf6d") -DEFINE_MTYPE(OSPF6D, OSPF6_TOP, "OSPF6 top") -DEFINE_MTYPE(OSPF6D, OSPF6_AREA, "OSPF6 area") -DEFINE_MTYPE(OSPF6D, OSPF6_IF, "OSPF6 interface") -DEFINE_MTYPE(OSPF6D, OSPF6_NEIGHBOR, "OSPF6 neighbor") -DEFINE_MTYPE(OSPF6D, OSPF6_ROUTE, "OSPF6 route") -DEFINE_MTYPE(OSPF6D, OSPF6_PREFIX, "OSPF6 prefix") -DEFINE_MTYPE(OSPF6D, OSPF6_MESSAGE, "OSPF6 message") -DEFINE_MTYPE(OSPF6D, OSPF6_LSA, "OSPF6 LSA") -DEFINE_MTYPE(OSPF6D, OSPF6_LSA_SUMMARY, "OSPF6 LSA summary") -DEFINE_MTYPE(OSPF6D, OSPF6_LSDB, "OSPF6 LSA database") -DEFINE_MTYPE(OSPF6D, OSPF6_VERTEX, "OSPF6 vertex") -DEFINE_MTYPE(OSPF6D, OSPF6_SPFTREE, "OSPF6 SPF tree") -DEFINE_MTYPE(OSPF6D, OSPF6_NEXTHOP, "OSPF6 nexthop") -DEFINE_MTYPE(OSPF6D, OSPF6_EXTERNAL_INFO,"OSPF6 ext. info") -DEFINE_MTYPE(OSPF6D, OSPF6_OTHER, "OSPF6 other") +DEFINE_MTYPE(OSPF6D, OSPF6_TOP, "OSPF6 top") +DEFINE_MTYPE(OSPF6D, OSPF6_AREA, "OSPF6 area") +DEFINE_MTYPE(OSPF6D, OSPF6_IF, "OSPF6 interface") +DEFINE_MTYPE(OSPF6D, OSPF6_NEIGHBOR, "OSPF6 neighbor") +DEFINE_MTYPE(OSPF6D, OSPF6_ROUTE, "OSPF6 route") +DEFINE_MTYPE(OSPF6D, OSPF6_PREFIX, "OSPF6 prefix") +DEFINE_MTYPE(OSPF6D, OSPF6_MESSAGE, "OSPF6 message") +DEFINE_MTYPE(OSPF6D, OSPF6_LSA, "OSPF6 LSA") +DEFINE_MTYPE(OSPF6D, OSPF6_LSA_SUMMARY, "OSPF6 LSA summary") +DEFINE_MTYPE(OSPF6D, OSPF6_LSDB, "OSPF6 LSA database") +DEFINE_MTYPE(OSPF6D, OSPF6_VERTEX, "OSPF6 vertex") +DEFINE_MTYPE(OSPF6D, OSPF6_SPFTREE, "OSPF6 SPF tree") +DEFINE_MTYPE(OSPF6D, OSPF6_NEXTHOP, "OSPF6 nexthop") +DEFINE_MTYPE(OSPF6D, OSPF6_EXTERNAL_INFO, "OSPF6 ext. info") +DEFINE_MTYPE(OSPF6D, OSPF6_OTHER, "OSPF6 other") diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c index 583ba2a02..aa5f05ce1 100644 --- a/ospf6d/ospf6_message.c +++ b/ospf6d/ospf6_message.c @@ -49,897 +49,872 @@ #include unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0}; -static const struct message ospf6_message_type_str [] = -{ - { OSPF6_MESSAGE_TYPE_HELLO, "Hello" }, - { OSPF6_MESSAGE_TYPE_DBDESC, "DbDesc" }, - { OSPF6_MESSAGE_TYPE_LSREQ, "LSReq" }, - { OSPF6_MESSAGE_TYPE_LSUPDATE, "LSUpdate" }, - { OSPF6_MESSAGE_TYPE_LSACK, "LSAck" }, - { 0 } -}; +static const struct message ospf6_message_type_str[] = { + {OSPF6_MESSAGE_TYPE_HELLO, "Hello"}, + {OSPF6_MESSAGE_TYPE_DBDESC, "DbDesc"}, + {OSPF6_MESSAGE_TYPE_LSREQ, "LSReq"}, + {OSPF6_MESSAGE_TYPE_LSUPDATE, "LSUpdate"}, + {OSPF6_MESSAGE_TYPE_LSACK, "LSAck"}, + {0}}; /* Minimum (besides the standard OSPF packet header) lengths for OSPF packets of particular types, offset is the "type" field. */ -const u_int16_t ospf6_packet_minlen[OSPF6_MESSAGE_TYPE_ALL] = -{ - 0, - OSPF6_HELLO_MIN_SIZE, - OSPF6_DB_DESC_MIN_SIZE, - OSPF6_LS_REQ_MIN_SIZE, - OSPF6_LS_UPD_MIN_SIZE, - OSPF6_LS_ACK_MIN_SIZE -}; +const u_int16_t ospf6_packet_minlen[OSPF6_MESSAGE_TYPE_ALL] = { + 0, + OSPF6_HELLO_MIN_SIZE, + OSPF6_DB_DESC_MIN_SIZE, + OSPF6_LS_REQ_MIN_SIZE, + OSPF6_LS_UPD_MIN_SIZE, + OSPF6_LS_ACK_MIN_SIZE}; /* Minimum (besides the standard LSA header) lengths for LSAs of particular types, offset is the "LSA function code" portion of "LSA type" field. */ -const u_int16_t ospf6_lsa_minlen[OSPF6_LSTYPE_SIZE] = -{ - 0, - /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE, - /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE, - /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE, - /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE, - /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE, - /* 0x2006 */ 0, - /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE, - /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE, - /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE -}; +const u_int16_t ospf6_lsa_minlen[OSPF6_LSTYPE_SIZE] = { + 0, + /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE, + /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE, + /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE, + /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE, + /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE, + /* 0x2006 */ 0, + /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE, + /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE, + /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE}; /* print functions */ -static void -ospf6_header_print (struct ospf6_header *oh) +static void ospf6_header_print(struct ospf6_header *oh) { - char router_id[16], area_id[16]; - inet_ntop (AF_INET, &oh->router_id, router_id, sizeof (router_id)); - inet_ntop (AF_INET, &oh->area_id, area_id, sizeof (area_id)); - - zlog_debug (" OSPFv%d Type:%d Len:%hu Router-ID:%s", - oh->version, oh->type, ntohs (oh->length), router_id); - zlog_debug (" Area-ID:%s Cksum:%hx Instance-ID:%d", - area_id, ntohs (oh->checksum), oh->instance_id); + char router_id[16], area_id[16]; + inet_ntop(AF_INET, &oh->router_id, router_id, sizeof(router_id)); + inet_ntop(AF_INET, &oh->area_id, area_id, sizeof(area_id)); + + zlog_debug(" OSPFv%d Type:%d Len:%hu Router-ID:%s", oh->version, + oh->type, ntohs(oh->length), router_id); + zlog_debug(" Area-ID:%s Cksum:%hx Instance-ID:%d", area_id, + ntohs(oh->checksum), oh->instance_id); } -void -ospf6_hello_print (struct ospf6_header *oh) +void ospf6_hello_print(struct ospf6_header *oh) { - struct ospf6_hello *hello; - char options[16]; - char drouter[16], bdrouter[16], neighbor[16]; - char *p; - - ospf6_header_print (oh); - assert (oh->type == OSPF6_MESSAGE_TYPE_HELLO); - - hello = (struct ospf6_hello *) - ((caddr_t) oh + sizeof (struct ospf6_header)); - - inet_ntop (AF_INET, &hello->drouter, drouter, sizeof (drouter)); - inet_ntop (AF_INET, &hello->bdrouter, bdrouter, sizeof (bdrouter)); - ospf6_options_printbuf (hello->options, options, sizeof (options)); - - zlog_debug (" I/F-Id:%ld Priority:%d Option:%s", - (u_long) ntohl (hello->interface_id), hello->priority, options); - zlog_debug (" HelloInterval:%hu DeadInterval:%hu", - ntohs (hello->hello_interval), ntohs (hello->dead_interval)); - zlog_debug (" DR:%s BDR:%s", drouter, bdrouter); - - for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello)); - p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh); - p += sizeof (u_int32_t)) - { - inet_ntop (AF_INET, (void *) p, neighbor, sizeof (neighbor)); - zlog_debug (" Neighbor: %s", neighbor); - } - - assert (p == OSPF6_MESSAGE_END (oh)); + struct ospf6_hello *hello; + char options[16]; + char drouter[16], bdrouter[16], neighbor[16]; + char *p; + + ospf6_header_print(oh); + assert(oh->type == OSPF6_MESSAGE_TYPE_HELLO); + + hello = (struct ospf6_hello *)((caddr_t)oh + + sizeof(struct ospf6_header)); + + inet_ntop(AF_INET, &hello->drouter, drouter, sizeof(drouter)); + inet_ntop(AF_INET, &hello->bdrouter, bdrouter, sizeof(bdrouter)); + ospf6_options_printbuf(hello->options, options, sizeof(options)); + + zlog_debug(" I/F-Id:%ld Priority:%d Option:%s", + (u_long)ntohl(hello->interface_id), hello->priority, + options); + zlog_debug(" HelloInterval:%hu DeadInterval:%hu", + ntohs(hello->hello_interval), ntohs(hello->dead_interval)); + zlog_debug(" DR:%s BDR:%s", drouter, bdrouter); + + for (p = (char *)((caddr_t)hello + sizeof(struct ospf6_hello)); + p + sizeof(u_int32_t) <= OSPF6_MESSAGE_END(oh); + p += sizeof(u_int32_t)) { + inet_ntop(AF_INET, (void *)p, neighbor, sizeof(neighbor)); + zlog_debug(" Neighbor: %s", neighbor); + } + + assert(p == OSPF6_MESSAGE_END(oh)); } -void -ospf6_dbdesc_print (struct ospf6_header *oh) +void ospf6_dbdesc_print(struct ospf6_header *oh) { - struct ospf6_dbdesc *dbdesc; - char options[16]; - char *p; + struct ospf6_dbdesc *dbdesc; + char options[16]; + char *p; - ospf6_header_print (oh); - assert (oh->type == OSPF6_MESSAGE_TYPE_DBDESC); + ospf6_header_print(oh); + assert(oh->type == OSPF6_MESSAGE_TYPE_DBDESC); - dbdesc = (struct ospf6_dbdesc *) - ((caddr_t) oh + sizeof (struct ospf6_header)); + dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh + + sizeof(struct ospf6_header)); - ospf6_options_printbuf (dbdesc->options, options, sizeof (options)); + ospf6_options_printbuf(dbdesc->options, options, sizeof(options)); - zlog_debug (" MBZ: %#x Option: %s IfMTU: %hu", - dbdesc->reserved1, options, ntohs (dbdesc->ifmtu)); - zlog_debug (" MBZ: %#x Bits: %s%s%s SeqNum: %#lx", - dbdesc->reserved2, - (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) ? "I" : "-"), - (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) ? "M" : "-"), - (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"), - (u_long) ntohl (dbdesc->seqnum)); + zlog_debug(" MBZ: %#x Option: %s IfMTU: %hu", dbdesc->reserved1, + options, ntohs(dbdesc->ifmtu)); + zlog_debug(" MBZ: %#x Bits: %s%s%s SeqNum: %#lx", dbdesc->reserved2, + (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT) ? "I" : "-"), + (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MBIT) ? "M" : "-"), + (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"), + (u_long)ntohl(dbdesc->seqnum)); - for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc)); - p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh); - p += sizeof (struct ospf6_lsa_header)) - ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p); + for (p = (char *)((caddr_t)dbdesc + sizeof(struct ospf6_dbdesc)); + p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh); + p += sizeof(struct ospf6_lsa_header)) + ospf6_lsa_header_print_raw((struct ospf6_lsa_header *)p); - assert (p == OSPF6_MESSAGE_END (oh)); + assert(p == OSPF6_MESSAGE_END(oh)); } -void -ospf6_lsreq_print (struct ospf6_header *oh) +void ospf6_lsreq_print(struct ospf6_header *oh) { - char id[16], adv_router[16]; - char *p; - - ospf6_header_print (oh); - assert (oh->type == OSPF6_MESSAGE_TYPE_LSREQ); - - for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header)); - p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh); - p += sizeof (struct ospf6_lsreq_entry)) - { - struct ospf6_lsreq_entry *e = (struct ospf6_lsreq_entry *) p; - inet_ntop (AF_INET, &e->adv_router, adv_router, sizeof (adv_router)); - inet_ntop (AF_INET, &e->id, id, sizeof (id)); - zlog_debug (" [%s Id:%s Adv:%s]", - ospf6_lstype_name (e->type), id, adv_router); - } - - assert (p == OSPF6_MESSAGE_END (oh)); + char id[16], adv_router[16]; + char *p; + + ospf6_header_print(oh); + assert(oh->type == OSPF6_MESSAGE_TYPE_LSREQ); + + for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header)); + p + sizeof(struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END(oh); + p += sizeof(struct ospf6_lsreq_entry)) { + struct ospf6_lsreq_entry *e = (struct ospf6_lsreq_entry *)p; + inet_ntop(AF_INET, &e->adv_router, adv_router, + sizeof(adv_router)); + inet_ntop(AF_INET, &e->id, id, sizeof(id)); + zlog_debug(" [%s Id:%s Adv:%s]", ospf6_lstype_name(e->type), + id, adv_router); + } + + assert(p == OSPF6_MESSAGE_END(oh)); } -void -ospf6_lsupdate_print (struct ospf6_header *oh) +void ospf6_lsupdate_print(struct ospf6_header *oh) { - struct ospf6_lsupdate *lsupdate; - u_long num; - char *p; + struct ospf6_lsupdate *lsupdate; + u_long num; + char *p; - ospf6_header_print (oh); - assert (oh->type == OSPF6_MESSAGE_TYPE_LSUPDATE); + ospf6_header_print(oh); + assert(oh->type == OSPF6_MESSAGE_TYPE_LSUPDATE); - lsupdate = (struct ospf6_lsupdate *) - ((caddr_t) oh + sizeof (struct ospf6_header)); + lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh + + sizeof(struct ospf6_header)); - num = ntohl (lsupdate->lsa_number); - zlog_debug (" Number of LSA: %ld", num); + num = ntohl(lsupdate->lsa_number); + zlog_debug(" Number of LSA: %ld", num); - for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate)); - p < OSPF6_MESSAGE_END (oh) && - p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh); - p += OSPF6_LSA_SIZE (p)) - { - ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p); - } + for (p = (char *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate)); + p < OSPF6_MESSAGE_END(oh) + && p + OSPF6_LSA_SIZE(p) <= OSPF6_MESSAGE_END(oh); + p += OSPF6_LSA_SIZE(p)) { + ospf6_lsa_header_print_raw((struct ospf6_lsa_header *)p); + } - assert (p == OSPF6_MESSAGE_END (oh)); + assert(p == OSPF6_MESSAGE_END(oh)); } -void -ospf6_lsack_print (struct ospf6_header *oh) +void ospf6_lsack_print(struct ospf6_header *oh) { - char *p; + char *p; - ospf6_header_print (oh); - assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK); + ospf6_header_print(oh); + assert(oh->type == OSPF6_MESSAGE_TYPE_LSACK); - for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header)); - p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh); - p += sizeof (struct ospf6_lsa_header)) - ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p); + for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header)); + p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh); + p += sizeof(struct ospf6_lsa_header)) + ospf6_lsa_header_print_raw((struct ospf6_lsa_header *)p); - assert (p == OSPF6_MESSAGE_END (oh)); + assert(p == OSPF6_MESSAGE_END(oh)); } -static void -ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst, - struct ospf6_interface *oi, struct ospf6_header *oh) +static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, + struct ospf6_header *oh) { - struct ospf6_hello *hello; - struct ospf6_neighbor *on; - char *p; - int twoway = 0; - int neighborchange = 0; - int neighbor_ifindex_change = 0; - int backupseen = 0; - - hello = (struct ospf6_hello *) - ((caddr_t) oh + sizeof (struct ospf6_header)); - - /* HelloInterval check */ - if (ntohs (hello->hello_interval) != oi->hello_interval) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("HelloInterval mismatch"); - return; - } - - /* RouterDeadInterval check */ - if (ntohs (hello->dead_interval) != oi->dead_interval) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("RouterDeadInterval mismatch"); - return; - } - - /* E-bit check */ - if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E) != - OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E)) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("E-bit mismatch"); - return; - } - - /* Find neighbor, create if not exist */ - on = ospf6_neighbor_lookup (oh->router_id, oi); - if (on == NULL) - { - on = ospf6_neighbor_create (oh->router_id, oi); - on->prev_drouter = on->drouter = hello->drouter; - on->prev_bdrouter = on->bdrouter = hello->bdrouter; - on->priority = hello->priority; - } - - /* Always override neighbor's source address */ - memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr)); - - /* Neighbor ifindex check */ - if (on->ifindex != (ifindex_t)ntohl (hello->interface_id)) - { - on->ifindex = ntohl (hello->interface_id); - neighbor_ifindex_change++; - } - - /* TwoWay check */ - for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello)); - p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh); - p += sizeof (u_int32_t)) - { - u_int32_t *router_id = (u_int32_t *) p; - - if (*router_id == oi->area->ospf6->router_id) - twoway++; - } - - assert (p == OSPF6_MESSAGE_END (oh)); - - /* RouterPriority check */ - if (on->priority != hello->priority) - { - on->priority = hello->priority; - neighborchange++; - } - - /* DR check */ - if (on->drouter != hello->drouter) - { - on->prev_drouter = on->drouter; - on->drouter = hello->drouter; - if (on->prev_drouter == on->router_id || on->drouter == on->router_id) - neighborchange++; - } - - /* BDR check */ - if (on->bdrouter != hello->bdrouter) - { - on->prev_bdrouter = on->bdrouter; - on->bdrouter = hello->bdrouter; - if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id) - neighborchange++; - } - - /* BackupSeen check */ - if (oi->state == OSPF6_INTERFACE_WAITING) - { - if (hello->bdrouter == on->router_id) - backupseen++; - else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0)) - backupseen++; - } - - /* Execute neighbor events */ - thread_execute (master, hello_received, on, 0); - if (twoway) - thread_execute (master, twoway_received, on, 0); - else - thread_execute (master, oneway_received, on, 0); - - /* Schedule interface events */ - if (backupseen) - thread_add_event (master, backup_seen, oi, 0, NULL); - if (neighborchange) - thread_add_event (master, neighbor_change, oi, 0, NULL); - - if (neighbor_ifindex_change && on->state == OSPF6_NEIGHBOR_FULL) - OSPF6_ROUTER_LSA_SCHEDULE (oi->area); + struct ospf6_hello *hello; + struct ospf6_neighbor *on; + char *p; + int twoway = 0; + int neighborchange = 0; + int neighbor_ifindex_change = 0; + int backupseen = 0; + + hello = (struct ospf6_hello *)((caddr_t)oh + + sizeof(struct ospf6_header)); + + /* HelloInterval check */ + if (ntohs(hello->hello_interval) != oi->hello_interval) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("HelloInterval mismatch"); + return; + } + + /* RouterDeadInterval check */ + if (ntohs(hello->dead_interval) != oi->dead_interval) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("RouterDeadInterval mismatch"); + return; + } + + /* E-bit check */ + if (OSPF6_OPT_ISSET(hello->options, OSPF6_OPT_E) + != OSPF6_OPT_ISSET(oi->area->options, OSPF6_OPT_E)) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("E-bit mismatch"); + return; + } + + /* Find neighbor, create if not exist */ + on = ospf6_neighbor_lookup(oh->router_id, oi); + if (on == NULL) { + on = ospf6_neighbor_create(oh->router_id, oi); + on->prev_drouter = on->drouter = hello->drouter; + on->prev_bdrouter = on->bdrouter = hello->bdrouter; + on->priority = hello->priority; + } + + /* Always override neighbor's source address */ + memcpy(&on->linklocal_addr, src, sizeof(struct in6_addr)); + + /* Neighbor ifindex check */ + if (on->ifindex != (ifindex_t)ntohl(hello->interface_id)) { + on->ifindex = ntohl(hello->interface_id); + neighbor_ifindex_change++; + } + + /* TwoWay check */ + for (p = (char *)((caddr_t)hello + sizeof(struct ospf6_hello)); + p + sizeof(u_int32_t) <= OSPF6_MESSAGE_END(oh); + p += sizeof(u_int32_t)) { + u_int32_t *router_id = (u_int32_t *)p; + + if (*router_id == oi->area->ospf6->router_id) + twoway++; + } + + assert(p == OSPF6_MESSAGE_END(oh)); + + /* RouterPriority check */ + if (on->priority != hello->priority) { + on->priority = hello->priority; + neighborchange++; + } + + /* DR check */ + if (on->drouter != hello->drouter) { + on->prev_drouter = on->drouter; + on->drouter = hello->drouter; + if (on->prev_drouter == on->router_id + || on->drouter == on->router_id) + neighborchange++; + } + + /* BDR check */ + if (on->bdrouter != hello->bdrouter) { + on->prev_bdrouter = on->bdrouter; + on->bdrouter = hello->bdrouter; + if (on->prev_bdrouter == on->router_id + || on->bdrouter == on->router_id) + neighborchange++; + } + + /* BackupSeen check */ + if (oi->state == OSPF6_INTERFACE_WAITING) { + if (hello->bdrouter == on->router_id) + backupseen++; + else if (hello->drouter == on->router_id + && hello->bdrouter == htonl(0)) + backupseen++; + } + + /* Execute neighbor events */ + thread_execute(master, hello_received, on, 0); + if (twoway) + thread_execute(master, twoway_received, on, 0); + else + thread_execute(master, oneway_received, on, 0); + + /* Schedule interface events */ + if (backupseen) + thread_add_event(master, backup_seen, oi, 0, NULL); + if (neighborchange) + thread_add_event(master, neighbor_change, oi, 0, NULL); + + if (neighbor_ifindex_change && on->state == OSPF6_NEIGHBOR_FULL) + OSPF6_ROUTER_LSA_SCHEDULE(oi->area); } -static void -ospf6_dbdesc_recv_master (struct ospf6_header *oh, - struct ospf6_neighbor *on) +static void ospf6_dbdesc_recv_master(struct ospf6_header *oh, + struct ospf6_neighbor *on) { - struct ospf6_dbdesc *dbdesc; - char *p; - - dbdesc = (struct ospf6_dbdesc *) - ((caddr_t) oh + sizeof (struct ospf6_header)); - - if (on->state < OSPF6_NEIGHBOR_INIT) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Neighbor state less than Init, ignore"); - return; - } - - switch (on->state) - { - case OSPF6_NEIGHBOR_TWOWAY: - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Neighbor state is 2-Way, ignore"); - return; - - case OSPF6_NEIGHBOR_INIT: - thread_execute (master, twoway_received, on, 0); - if (on->state != OSPF6_NEIGHBOR_EXSTART) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Neighbor state is not ExStart, ignore"); - return; - } - /* else fall through to ExStart */ - /* fallthru */ - case OSPF6_NEIGHBOR_EXSTART: - /* if neighbor obeys us as our slave, schedule negotiation_done - and process LSA Headers. Otherwise, ignore this message */ - if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) && - ! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) && - ntohl (dbdesc->seqnum) == on->dbdesc_seqnum) - { - /* execute NegotiationDone */ - thread_execute (master, negotiation_done, on, 0); - - /* Record neighbor options */ - memcpy (on->options, dbdesc->options, sizeof (on->options)); - } - else - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Negotiation failed"); - return; - } - /* fall through to exchange */ - - case OSPF6_NEIGHBOR_EXCHANGE: - if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc))) - { - /* Duplicated DatabaseDescription is dropped by master */ - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Duplicated dbdesc discarded by Master, ignore"); - return; - } - - if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT)) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Master/Slave bit mismatch"); - thread_add_event (master, seqnumber_mismatch, on, 0, NULL); - return; - } - - if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT)) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Initialize bit mismatch"); - thread_add_event (master, seqnumber_mismatch, on, 0, NULL); - return; - } - - if (memcmp (on->options, dbdesc->options, sizeof (on->options))) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Option field mismatch"); - thread_add_event (master, seqnumber_mismatch, on, 0, NULL); - return; - } - - if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Sequence number mismatch (%#lx expected)", - (u_long) on->dbdesc_seqnum); - thread_add_event (master, seqnumber_mismatch, on, 0, NULL); - return; - } - break; - - case OSPF6_NEIGHBOR_LOADING: - case OSPF6_NEIGHBOR_FULL: - if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc))) - { - /* Duplicated DatabaseDescription is dropped by master */ - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Duplicated dbdesc discarded by Master, ignore"); - return; - } - - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Not duplicate dbdesc in state %s", - ospf6_neighbor_state_str[on->state]); - thread_add_event (master, seqnumber_mismatch, on, 0, NULL); - return; - - default: - assert (0); - break; - } - - /* Process LSA headers */ - for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc)); - p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh); - p += sizeof (struct ospf6_lsa_header)) - { - struct ospf6_lsa *his, *mine; - struct ospf6_lsdb *lsdb = NULL; - - his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p); - - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("%s", his->name); - - switch (OSPF6_LSA_SCOPE (his->header->type)) - { - case OSPF6_SCOPE_LINKLOCAL: - lsdb = on->ospf6_if->lsdb; - break; - case OSPF6_SCOPE_AREA: - lsdb = on->ospf6_if->area->lsdb; - break; - case OSPF6_SCOPE_AS: - lsdb = on->ospf6_if->area->ospf6->lsdb; - break; - case OSPF6_SCOPE_RESERVED: - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Ignoring LSA of reserved scope"); - ospf6_lsa_delete (his); - continue; - break; - } - - if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL && - IS_AREA_STUB (on->ospf6_if->area)) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("SeqNumMismatch (E-bit mismatch), discard"); - ospf6_lsa_delete (his); - thread_add_event (master, seqnumber_mismatch, on, 0, NULL); - return; - } - - mine = ospf6_lsdb_lookup (his->header->type, his->header->id, - his->header->adv_router, lsdb); - if (mine == NULL) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Add request (No database copy)"); - ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list); - } - else if (ospf6_lsa_compare (his, mine) < 0) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Add request (Received MoreRecent)"); - ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list); - } - else - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Discard (Existing MoreRecent)"); - } - ospf6_lsa_delete (his); - } - - assert (p == OSPF6_MESSAGE_END (oh)); - - /* Increment sequence number */ - on->dbdesc_seqnum ++; - - /* schedule send lsreq */ - if (on->request_list->count) - thread_add_event (master, ospf6_lsreq_send, on, 0, &on->thread_send_lsreq); - - THREAD_OFF (on->thread_send_dbdesc); - - /* More bit check */ - if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) && - ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT)) - thread_add_event (master, exchange_done, on, 0, NULL); - else { - on->thread_send_dbdesc = NULL; - thread_add_event(master, ospf6_dbdesc_send_newone, on, 0, - &on->thread_send_dbdesc); - } - - /* save last received dbdesc */ - memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc)); + struct ospf6_dbdesc *dbdesc; + char *p; + + dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh + + sizeof(struct ospf6_header)); + + if (on->state < OSPF6_NEIGHBOR_INIT) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Neighbor state less than Init, ignore"); + return; + } + + switch (on->state) { + case OSPF6_NEIGHBOR_TWOWAY: + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Neighbor state is 2-Way, ignore"); + return; + + case OSPF6_NEIGHBOR_INIT: + thread_execute(master, twoway_received, on, 0); + if (on->state != OSPF6_NEIGHBOR_EXSTART) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug( + "Neighbor state is not ExStart, ignore"); + return; + } + /* else fall through to ExStart */ + /* fallthru */ + case OSPF6_NEIGHBOR_EXSTART: + /* if neighbor obeys us as our slave, schedule negotiation_done + and process LSA Headers. Otherwise, ignore this message */ + if (!CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT) + && !CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT) + && ntohl(dbdesc->seqnum) == on->dbdesc_seqnum) { + /* execute NegotiationDone */ + thread_execute(master, negotiation_done, on, 0); + + /* Record neighbor options */ + memcpy(on->options, dbdesc->options, + sizeof(on->options)); + } else { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Negotiation failed"); + return; + } + /* fall through to exchange */ + + case OSPF6_NEIGHBOR_EXCHANGE: + if (!memcmp(dbdesc, &on->dbdesc_last, + sizeof(struct ospf6_dbdesc))) { + /* Duplicated DatabaseDescription is dropped by master + */ + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug( + "Duplicated dbdesc discarded by Master, ignore"); + return; + } + + if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT)) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Master/Slave bit mismatch"); + thread_add_event(master, seqnumber_mismatch, on, 0, + NULL); + return; + } + + if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT)) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Initialize bit mismatch"); + thread_add_event(master, seqnumber_mismatch, on, 0, + NULL); + return; + } + + if (memcmp(on->options, dbdesc->options, sizeof(on->options))) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Option field mismatch"); + thread_add_event(master, seqnumber_mismatch, on, 0, + NULL); + return; + } + + if (ntohl(dbdesc->seqnum) != on->dbdesc_seqnum) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug( + "Sequence number mismatch (%#lx expected)", + (u_long)on->dbdesc_seqnum); + thread_add_event(master, seqnumber_mismatch, on, 0, + NULL); + return; + } + break; + + case OSPF6_NEIGHBOR_LOADING: + case OSPF6_NEIGHBOR_FULL: + if (!memcmp(dbdesc, &on->dbdesc_last, + sizeof(struct ospf6_dbdesc))) { + /* Duplicated DatabaseDescription is dropped by master + */ + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug( + "Duplicated dbdesc discarded by Master, ignore"); + return; + } + + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Not duplicate dbdesc in state %s", + ospf6_neighbor_state_str[on->state]); + thread_add_event(master, seqnumber_mismatch, on, 0, NULL); + return; + + default: + assert(0); + break; + } + + /* Process LSA headers */ + for (p = (char *)((caddr_t)dbdesc + sizeof(struct ospf6_dbdesc)); + p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh); + p += sizeof(struct ospf6_lsa_header)) { + struct ospf6_lsa *his, *mine; + struct ospf6_lsdb *lsdb = NULL; + + his = ospf6_lsa_create_headeronly((struct ospf6_lsa_header *)p); + + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("%s", his->name); + + switch (OSPF6_LSA_SCOPE(his->header->type)) { + case OSPF6_SCOPE_LINKLOCAL: + lsdb = on->ospf6_if->lsdb; + break; + case OSPF6_SCOPE_AREA: + lsdb = on->ospf6_if->area->lsdb; + break; + case OSPF6_SCOPE_AS: + lsdb = on->ospf6_if->area->ospf6->lsdb; + break; + case OSPF6_SCOPE_RESERVED: + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Ignoring LSA of reserved scope"); + ospf6_lsa_delete(his); + continue; + break; + } + + if (ntohs(his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL + && IS_AREA_STUB(on->ospf6_if->area)) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug( + "SeqNumMismatch (E-bit mismatch), discard"); + ospf6_lsa_delete(his); + thread_add_event(master, seqnumber_mismatch, on, 0, + NULL); + return; + } + + mine = ospf6_lsdb_lookup(his->header->type, his->header->id, + his->header->adv_router, lsdb); + if (mine == NULL) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Add request (No database copy)"); + ospf6_lsdb_add(ospf6_lsa_copy(his), on->request_list); + } else if (ospf6_lsa_compare(his, mine) < 0) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Add request (Received MoreRecent)"); + ospf6_lsdb_add(ospf6_lsa_copy(his), on->request_list); + } else { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Discard (Existing MoreRecent)"); + } + ospf6_lsa_delete(his); + } + + assert(p == OSPF6_MESSAGE_END(oh)); + + /* Increment sequence number */ + on->dbdesc_seqnum++; + + /* schedule send lsreq */ + if (on->request_list->count) + thread_add_event(master, ospf6_lsreq_send, on, 0, + &on->thread_send_lsreq); + + THREAD_OFF(on->thread_send_dbdesc); + + /* More bit check */ + if (!CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MBIT) + && !CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT)) + thread_add_event(master, exchange_done, on, 0, NULL); + else { + on->thread_send_dbdesc = NULL; + thread_add_event(master, ospf6_dbdesc_send_newone, on, 0, + &on->thread_send_dbdesc); + } + + /* save last received dbdesc */ + memcpy(&on->dbdesc_last, dbdesc, sizeof(struct ospf6_dbdesc)); } -static void -ospf6_dbdesc_recv_slave (struct ospf6_header *oh, - struct ospf6_neighbor *on) +static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh, + struct ospf6_neighbor *on) { - struct ospf6_dbdesc *dbdesc; - char *p; - - dbdesc = (struct ospf6_dbdesc *) - ((caddr_t) oh + sizeof (struct ospf6_header)); - - if (on->state < OSPF6_NEIGHBOR_INIT) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Neighbor state less than Init, ignore"); - return; - } - - switch (on->state) - { - case OSPF6_NEIGHBOR_TWOWAY: - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Neighbor state is 2-Way, ignore"); - return; - - case OSPF6_NEIGHBOR_INIT: - thread_execute (master, twoway_received, on, 0); - if (on->state != OSPF6_NEIGHBOR_EXSTART) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Neighbor state is not ExStart, ignore"); - return; - } - /* else fall through to ExStart */ - /* fallthru */ - case OSPF6_NEIGHBOR_EXSTART: - /* If the neighbor is Master, act as Slave. Schedule negotiation_done - and process LSA Headers. Otherwise, ignore this message */ - if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) && - CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) && - CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) && - ntohs (oh->length) == sizeof (struct ospf6_header) + - sizeof (struct ospf6_dbdesc)) - { - /* set the master/slave bit to slave */ - UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT); - - /* set the DD sequence number to one specified by master */ - on->dbdesc_seqnum = ntohl (dbdesc->seqnum); - - /* schedule NegotiationDone */ - thread_execute (master, negotiation_done, on, 0); - - /* Record neighbor options */ - memcpy (on->options, dbdesc->options, sizeof (on->options)); - } - else - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Negotiation failed"); - return; - } - break; - - case OSPF6_NEIGHBOR_EXCHANGE: - if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc))) - { - /* Duplicated DatabaseDescription causes slave to retransmit */ - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Duplicated dbdesc causes retransmit"); - THREAD_OFF (on->thread_send_dbdesc); - on->thread_send_dbdesc = NULL; - thread_add_event(master, ospf6_dbdesc_send, on, 0, - &on->thread_send_dbdesc); - return; - } - - if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT)) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Master/Slave bit mismatch"); - thread_add_event (master, seqnumber_mismatch, on, 0, NULL); - return; - } - - if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT)) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Initialize bit mismatch"); - thread_add_event (master, seqnumber_mismatch, on, 0, NULL); - return; - } - - if (memcmp (on->options, dbdesc->options, sizeof (on->options))) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Option field mismatch"); - thread_add_event (master, seqnumber_mismatch, on, 0, NULL); - return; - } - - if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum + 1) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Sequence number mismatch (%#lx expected)", - (u_long) on->dbdesc_seqnum + 1); - thread_add_event (master, seqnumber_mismatch, on, 0, NULL); - return; - } - break; - - case OSPF6_NEIGHBOR_LOADING: - case OSPF6_NEIGHBOR_FULL: - if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc))) - { - /* Duplicated DatabaseDescription causes slave to retransmit */ - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Duplicated dbdesc causes retransmit"); - THREAD_OFF (on->thread_send_dbdesc); - thread_add_event (master, ospf6_dbdesc_send, on, 0, &on->thread_send_dbdesc); - return; - } - - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Not duplicate dbdesc in state %s", - ospf6_neighbor_state_str[on->state]); - thread_add_event (master, seqnumber_mismatch, on, 0, NULL); - return; - - default: - assert (0); - break; - } - - /* Process LSA headers */ - for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc)); - p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh); - p += sizeof (struct ospf6_lsa_header)) - { - struct ospf6_lsa *his, *mine; - struct ospf6_lsdb *lsdb = NULL; - - his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p); - - switch (OSPF6_LSA_SCOPE (his->header->type)) - { - case OSPF6_SCOPE_LINKLOCAL: - lsdb = on->ospf6_if->lsdb; - break; - case OSPF6_SCOPE_AREA: - lsdb = on->ospf6_if->area->lsdb; - break; - case OSPF6_SCOPE_AS: - lsdb = on->ospf6_if->area->ospf6->lsdb; - break; - case OSPF6_SCOPE_RESERVED: - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Ignoring LSA of reserved scope"); - ospf6_lsa_delete (his); - continue; - break; - } - - if (OSPF6_LSA_SCOPE (his->header->type) == OSPF6_SCOPE_AS && - IS_AREA_STUB (on->ospf6_if->area)) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("E-bit mismatch with LSA Headers"); - ospf6_lsa_delete (his); - thread_add_event (master, seqnumber_mismatch, on, 0, NULL); - return; - } - - mine = ospf6_lsdb_lookup (his->header->type, his->header->id, - his->header->adv_router, lsdb); - if (mine == NULL || ospf6_lsa_compare (his, mine) < 0) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Add request-list: %s", his->name); - ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list); - } - ospf6_lsa_delete (his); - } - - assert (p == OSPF6_MESSAGE_END (oh)); - - /* Set sequence number to Master's */ - on->dbdesc_seqnum = ntohl (dbdesc->seqnum); - - /* schedule send lsreq */ - if (on->request_list->count) - thread_add_event (master, ospf6_lsreq_send, on, 0, &on->thread_send_lsreq); - - THREAD_OFF (on->thread_send_dbdesc); - thread_add_event (master, ospf6_dbdesc_send_newone, on, 0, &on->thread_send_dbdesc); - - /* save last received dbdesc */ - memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc)); + struct ospf6_dbdesc *dbdesc; + char *p; + + dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh + + sizeof(struct ospf6_header)); + + if (on->state < OSPF6_NEIGHBOR_INIT) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Neighbor state less than Init, ignore"); + return; + } + + switch (on->state) { + case OSPF6_NEIGHBOR_TWOWAY: + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Neighbor state is 2-Way, ignore"); + return; + + case OSPF6_NEIGHBOR_INIT: + thread_execute(master, twoway_received, on, 0); + if (on->state != OSPF6_NEIGHBOR_EXSTART) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug( + "Neighbor state is not ExStart, ignore"); + return; + } + /* else fall through to ExStart */ + /* fallthru */ + case OSPF6_NEIGHBOR_EXSTART: + /* If the neighbor is Master, act as Slave. Schedule + negotiation_done + and process LSA Headers. Otherwise, ignore this message */ + if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT) + && CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MBIT) + && CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT) + && ntohs(oh->length) + == sizeof(struct ospf6_header) + + sizeof(struct ospf6_dbdesc)) { + /* set the master/slave bit to slave */ + UNSET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT); + + /* set the DD sequence number to one specified by master + */ + on->dbdesc_seqnum = ntohl(dbdesc->seqnum); + + /* schedule NegotiationDone */ + thread_execute(master, negotiation_done, on, 0); + + /* Record neighbor options */ + memcpy(on->options, dbdesc->options, + sizeof(on->options)); + } else { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Negotiation failed"); + return; + } + break; + + case OSPF6_NEIGHBOR_EXCHANGE: + if (!memcmp(dbdesc, &on->dbdesc_last, + sizeof(struct ospf6_dbdesc))) { + /* Duplicated DatabaseDescription causes slave to + * retransmit */ + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug( + "Duplicated dbdesc causes retransmit"); + THREAD_OFF(on->thread_send_dbdesc); + on->thread_send_dbdesc = NULL; + thread_add_event(master, ospf6_dbdesc_send, on, 0, + &on->thread_send_dbdesc); + return; + } + + if (!CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT)) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Master/Slave bit mismatch"); + thread_add_event(master, seqnumber_mismatch, on, 0, + NULL); + return; + } + + if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT)) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Initialize bit mismatch"); + thread_add_event(master, seqnumber_mismatch, on, 0, + NULL); + return; + } + + if (memcmp(on->options, dbdesc->options, sizeof(on->options))) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Option field mismatch"); + thread_add_event(master, seqnumber_mismatch, on, 0, + NULL); + return; + } + + if (ntohl(dbdesc->seqnum) != on->dbdesc_seqnum + 1) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug( + "Sequence number mismatch (%#lx expected)", + (u_long)on->dbdesc_seqnum + 1); + thread_add_event(master, seqnumber_mismatch, on, 0, + NULL); + return; + } + break; + + case OSPF6_NEIGHBOR_LOADING: + case OSPF6_NEIGHBOR_FULL: + if (!memcmp(dbdesc, &on->dbdesc_last, + sizeof(struct ospf6_dbdesc))) { + /* Duplicated DatabaseDescription causes slave to + * retransmit */ + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug( + "Duplicated dbdesc causes retransmit"); + THREAD_OFF(on->thread_send_dbdesc); + thread_add_event(master, ospf6_dbdesc_send, on, 0, + &on->thread_send_dbdesc); + return; + } + + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Not duplicate dbdesc in state %s", + ospf6_neighbor_state_str[on->state]); + thread_add_event(master, seqnumber_mismatch, on, 0, NULL); + return; + + default: + assert(0); + break; + } + + /* Process LSA headers */ + for (p = (char *)((caddr_t)dbdesc + sizeof(struct ospf6_dbdesc)); + p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh); + p += sizeof(struct ospf6_lsa_header)) { + struct ospf6_lsa *his, *mine; + struct ospf6_lsdb *lsdb = NULL; + + his = ospf6_lsa_create_headeronly((struct ospf6_lsa_header *)p); + + switch (OSPF6_LSA_SCOPE(his->header->type)) { + case OSPF6_SCOPE_LINKLOCAL: + lsdb = on->ospf6_if->lsdb; + break; + case OSPF6_SCOPE_AREA: + lsdb = on->ospf6_if->area->lsdb; + break; + case OSPF6_SCOPE_AS: + lsdb = on->ospf6_if->area->ospf6->lsdb; + break; + case OSPF6_SCOPE_RESERVED: + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Ignoring LSA of reserved scope"); + ospf6_lsa_delete(his); + continue; + break; + } + + if (OSPF6_LSA_SCOPE(his->header->type) == OSPF6_SCOPE_AS + && IS_AREA_STUB(on->ospf6_if->area)) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("E-bit mismatch with LSA Headers"); + ospf6_lsa_delete(his); + thread_add_event(master, seqnumber_mismatch, on, 0, + NULL); + return; + } + + mine = ospf6_lsdb_lookup(his->header->type, his->header->id, + his->header->adv_router, lsdb); + if (mine == NULL || ospf6_lsa_compare(his, mine) < 0) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Add request-list: %s", his->name); + ospf6_lsdb_add(ospf6_lsa_copy(his), on->request_list); + } + ospf6_lsa_delete(his); + } + + assert(p == OSPF6_MESSAGE_END(oh)); + + /* Set sequence number to Master's */ + on->dbdesc_seqnum = ntohl(dbdesc->seqnum); + + /* schedule send lsreq */ + if (on->request_list->count) + thread_add_event(master, ospf6_lsreq_send, on, 0, + &on->thread_send_lsreq); + + THREAD_OFF(on->thread_send_dbdesc); + thread_add_event(master, ospf6_dbdesc_send_newone, on, 0, + &on->thread_send_dbdesc); + + /* save last received dbdesc */ + memcpy(&on->dbdesc_last, dbdesc, sizeof(struct ospf6_dbdesc)); } -static void -ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst, - struct ospf6_interface *oi, struct ospf6_header *oh) +static void ospf6_dbdesc_recv(struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, + struct ospf6_header *oh) { - struct ospf6_neighbor *on; - struct ospf6_dbdesc *dbdesc; - - on = ospf6_neighbor_lookup (oh->router_id, oi); - if (on == NULL) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Neighbor not found, ignore"); - return; - } - - dbdesc = (struct ospf6_dbdesc *) - ((caddr_t) oh + sizeof (struct ospf6_header)); - - /* Interface MTU check */ - if (!oi->mtu_ignore && ntohs (dbdesc->ifmtu) != oi->ifmtu) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("I/F MTU mismatch"); - return; - } - - if (dbdesc->reserved1 || dbdesc->reserved2) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Non-0 reserved field in %s's DbDesc, correct", - on->name); - dbdesc->reserved1 = 0; - dbdesc->reserved2 = 0; - } - - if (ntohl (oh->router_id) < ntohl (ospf6->router_id)) - ospf6_dbdesc_recv_master (oh, on); - else if (ntohl (ospf6->router_id) < ntohl (oh->router_id)) - ospf6_dbdesc_recv_slave (oh, on); - else - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Can't decide which is master, ignore"); - } + struct ospf6_neighbor *on; + struct ospf6_dbdesc *dbdesc; + + on = ospf6_neighbor_lookup(oh->router_id, oi); + if (on == NULL) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Neighbor not found, ignore"); + return; + } + + dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh + + sizeof(struct ospf6_header)); + + /* Interface MTU check */ + if (!oi->mtu_ignore && ntohs(dbdesc->ifmtu) != oi->ifmtu) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("I/F MTU mismatch"); + return; + } + + if (dbdesc->reserved1 || dbdesc->reserved2) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug( + "Non-0 reserved field in %s's DbDesc, correct", + on->name); + dbdesc->reserved1 = 0; + dbdesc->reserved2 = 0; + } + + if (ntohl(oh->router_id) < ntohl(ospf6->router_id)) + ospf6_dbdesc_recv_master(oh, on); + else if (ntohl(ospf6->router_id) < ntohl(oh->router_id)) + ospf6_dbdesc_recv_slave(oh, on); + else { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Can't decide which is master, ignore"); + } } -static void -ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst, - struct ospf6_interface *oi, struct ospf6_header *oh) +static void ospf6_lsreq_recv(struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, + struct ospf6_header *oh) { - struct ospf6_neighbor *on; - char *p; - struct ospf6_lsreq_entry *e; - struct ospf6_lsdb *lsdb = NULL; - struct ospf6_lsa *lsa; - - on = ospf6_neighbor_lookup (oh->router_id, oi); - if (on == NULL) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Neighbor not found, ignore"); - return; - } - - if (on->state != OSPF6_NEIGHBOR_EXCHANGE && - on->state != OSPF6_NEIGHBOR_LOADING && - on->state != OSPF6_NEIGHBOR_FULL) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Neighbor state less than Exchange, ignore"); - return; - } - - /* Process each request */ - for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header)); - p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh); - p += sizeof (struct ospf6_lsreq_entry)) - { - e = (struct ospf6_lsreq_entry *) p; - - switch (OSPF6_LSA_SCOPE (e->type)) - { - case OSPF6_SCOPE_LINKLOCAL: - lsdb = on->ospf6_if->lsdb; - break; - case OSPF6_SCOPE_AREA: - lsdb = on->ospf6_if->area->lsdb; - break; - case OSPF6_SCOPE_AS: - lsdb = on->ospf6_if->area->ospf6->lsdb; - break; - default: - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Ignoring LSA of reserved scope"); - continue; - break; - } - - /* Find database copy */ - lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb); - if (lsa == NULL) - { - char id[16], adv_router[16]; - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - { - inet_ntop (AF_INET, &e->id, id, sizeof (id)); - inet_ntop (AF_INET, &e->adv_router, adv_router, - sizeof (adv_router)); - zlog_debug ("Can't find requested [%s Id:%s Adv:%s]", - ospf6_lstype_name (e->type), id, adv_router); - } - thread_add_event (master, bad_lsreq, on, 0, NULL); - return; - } - - ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list); - } - - assert (p == OSPF6_MESSAGE_END (oh)); - - /* schedule send lsupdate */ - THREAD_OFF (on->thread_send_lsupdate); - thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0, &on->thread_send_lsupdate); + struct ospf6_neighbor *on; + char *p; + struct ospf6_lsreq_entry *e; + struct ospf6_lsdb *lsdb = NULL; + struct ospf6_lsa *lsa; + + on = ospf6_neighbor_lookup(oh->router_id, oi); + if (on == NULL) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Neighbor not found, ignore"); + return; + } + + if (on->state != OSPF6_NEIGHBOR_EXCHANGE + && on->state != OSPF6_NEIGHBOR_LOADING + && on->state != OSPF6_NEIGHBOR_FULL) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Neighbor state less than Exchange, ignore"); + return; + } + + /* Process each request */ + for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header)); + p + sizeof(struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END(oh); + p += sizeof(struct ospf6_lsreq_entry)) { + e = (struct ospf6_lsreq_entry *)p; + + switch (OSPF6_LSA_SCOPE(e->type)) { + case OSPF6_SCOPE_LINKLOCAL: + lsdb = on->ospf6_if->lsdb; + break; + case OSPF6_SCOPE_AREA: + lsdb = on->ospf6_if->area->lsdb; + break; + case OSPF6_SCOPE_AS: + lsdb = on->ospf6_if->area->ospf6->lsdb; + break; + default: + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Ignoring LSA of reserved scope"); + continue; + break; + } + + /* Find database copy */ + lsa = ospf6_lsdb_lookup(e->type, e->id, e->adv_router, lsdb); + if (lsa == NULL) { + char id[16], adv_router[16]; + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) { + inet_ntop(AF_INET, &e->id, id, sizeof(id)); + inet_ntop(AF_INET, &e->adv_router, adv_router, + sizeof(adv_router)); + zlog_debug( + "Can't find requested [%s Id:%s Adv:%s]", + ospf6_lstype_name(e->type), id, + adv_router); + } + thread_add_event(master, bad_lsreq, on, 0, NULL); + return; + } + + ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->lsupdate_list); + } + + assert(p == OSPF6_MESSAGE_END(oh)); + + /* schedule send lsupdate */ + THREAD_OFF(on->thread_send_lsupdate); + thread_add_event(master, ospf6_lsupdate_send_neighbor, on, 0, + &on->thread_send_lsupdate); } /* Verify, that the specified memory area contains exactly N valid IPv6 prefixes as specified by RFC5340, A.4.1. */ -static unsigned -ospf6_prefixes_examin -( - struct ospf6_prefix *current, /* start of buffer */ - unsigned length, - const u_int32_t req_num_pfxs /* always compared with the actual number of prefixes */ -) +static unsigned ospf6_prefixes_examin( + struct ospf6_prefix *current, /* start of buffer */ + unsigned length, + const u_int32_t req_num_pfxs /* always compared with the actual number + of prefixes */ + ) { - u_char requested_pfx_bytes; - u_int32_t real_num_pfxs = 0; - - while (length) - { - if (length < OSPF6_PREFIX_MIN_SIZE) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: undersized IPv6 prefix header", __func__); - return MSG_NG; - } - /* safe to look deeper */ - if (current->prefix_length > IPV6_MAX_BITLEN) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: invalid PrefixLength (%u bits)", __func__, current->prefix_length); - return MSG_NG; - } - /* covers both fixed- and variable-sized fields */ - requested_pfx_bytes = OSPF6_PREFIX_MIN_SIZE + OSPF6_PREFIX_SPACE (current->prefix_length); - if (requested_pfx_bytes > length) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: undersized IPv6 prefix", __func__); - return MSG_NG; - } - /* next prefix */ - length -= requested_pfx_bytes; - current = (struct ospf6_prefix *) ((caddr_t) current + requested_pfx_bytes); - real_num_pfxs++; - } - if (real_num_pfxs != req_num_pfxs) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: IPv6 prefix number mismatch (%u required, %u real)", - __func__, req_num_pfxs, real_num_pfxs); - return MSG_NG; - } - return MSG_OK; + u_char requested_pfx_bytes; + u_int32_t real_num_pfxs = 0; + + while (length) { + if (length < OSPF6_PREFIX_MIN_SIZE) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV)) + zlog_debug("%s: undersized IPv6 prefix header", + __func__); + return MSG_NG; + } + /* safe to look deeper */ + if (current->prefix_length > IPV6_MAX_BITLEN) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV)) + zlog_debug("%s: invalid PrefixLength (%u bits)", + __func__, current->prefix_length); + return MSG_NG; + } + /* covers both fixed- and variable-sized fields */ + requested_pfx_bytes = + OSPF6_PREFIX_MIN_SIZE + + OSPF6_PREFIX_SPACE(current->prefix_length); + if (requested_pfx_bytes > length) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV)) + zlog_debug("%s: undersized IPv6 prefix", + __func__); + return MSG_NG; + } + /* next prefix */ + length -= requested_pfx_bytes; + current = (struct ospf6_prefix *)((caddr_t)current + + requested_pfx_bytes); + real_num_pfxs++; + } + if (real_num_pfxs != req_num_pfxs) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + zlog_debug( + "%s: IPv6 prefix number mismatch (%u required, %u real)", + __func__, req_num_pfxs, real_num_pfxs); + return MSG_NG; + } + return MSG_OK; } /* Verify an LSA to have a valid length and dispatch further (where @@ -947,1374 +922,1378 @@ ospf6_prefixes_examin is properly sized/aligned within the LSA. Note that this function gets LSA type in network byte order, uses in host byte order and passes to ospf6_lstype_name() in network byte order again. */ -static unsigned -ospf6_lsa_examin (struct ospf6_lsa_header *lsah, const u_int16_t lsalen, const u_char headeronly) +static unsigned ospf6_lsa_examin(struct ospf6_lsa_header *lsah, + const u_int16_t lsalen, + const u_char headeronly) { - struct ospf6_intra_prefix_lsa *intra_prefix_lsa; - struct ospf6_as_external_lsa *as_external_lsa; - struct ospf6_link_lsa *link_lsa; - unsigned exp_length; - u_int8_t ltindex; - u_int16_t lsatype; - - /* In case an additional minimum length constraint is defined for current - LSA type, make sure that this constraint is met. */ - lsatype = ntohs (lsah->type); - ltindex = lsatype & OSPF6_LSTYPE_FCODE_MASK; - if - ( - ltindex < OSPF6_LSTYPE_SIZE && - ospf6_lsa_minlen[ltindex] && - lsalen < ospf6_lsa_minlen[ltindex] + OSPF6_LSA_HEADER_SIZE - ) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: undersized (%u B) LSA", __func__, lsalen); - return MSG_NG; - } - switch (lsatype) - { - case OSPF6_LSTYPE_ROUTER: - /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes followed - by N>=0 interface descriptions. */ - if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_ROUTER_LSA_MIN_SIZE) % OSPF6_ROUTER_LSDESC_FIX_SIZE) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: interface description alignment error", __func__); - return MSG_NG; - } - break; - case OSPF6_LSTYPE_NETWORK: - /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes - followed by N>=0 attached router descriptions. */ - if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_NETWORK_LSA_MIN_SIZE) % OSPF6_NETWORK_LSDESC_FIX_SIZE) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: router description alignment error", __func__); - return MSG_NG; - } - break; - case OSPF6_LSTYPE_INTER_PREFIX: - /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE bytes - followed by 3-4 fields of a single IPv6 prefix. */ - if (headeronly) - break; - return ospf6_prefixes_examin - ( - (struct ospf6_prefix *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_PREFIX_LSA_MIN_SIZE), - lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTER_PREFIX_LSA_MIN_SIZE, - 1 - ); - case OSPF6_LSTYPE_INTER_ROUTER: - /* RFC5340 A.4.6, fixed-size LSA. */ - if (lsalen > OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_ROUTER_LSA_FIX_SIZE) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: oversized (%u B) LSA", __func__, lsalen); - return MSG_NG; - } - break; - case OSPF6_LSTYPE_AS_EXTERNAL: /* RFC5340 A.4.7, same as A.4.8. */ - case OSPF6_LSTYPE_TYPE_7: - /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE bytes - followed by 3-4 fields of IPv6 prefix and 3 conditional LSA fields: - 16 bytes of forwarding address, 4 bytes of external route tag, - 4 bytes of referenced link state ID. */ - if (headeronly) - break; - as_external_lsa = (struct ospf6_as_external_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE); - exp_length = OSPF6_LSA_HEADER_SIZE + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE; - /* To find out if the last optional field (Referenced Link State ID) is - assumed in this LSA, we need to access fixed fields of the IPv6 - prefix before ospf6_prefix_examin() confirms its sizing. */ - if (exp_length + OSPF6_PREFIX_MIN_SIZE > lsalen) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen); - return MSG_NG; - } - /* forwarding address */ - if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F)) - exp_length += 16; - /* external route tag */ - if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T)) - exp_length += 4; - /* referenced link state ID */ - if (as_external_lsa->prefix.u._prefix_referenced_lstype) - exp_length += 4; - /* All the fixed-size fields (mandatory and optional) must fit. I.e., - this check does not include any IPv6 prefix fields. */ - if (exp_length > lsalen) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen); - return MSG_NG; - } - /* The last call completely covers the remainder (IPv6 prefix). */ - return ospf6_prefixes_examin - ( - (struct ospf6_prefix *) ((caddr_t) as_external_lsa + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE), - lsalen - exp_length, - 1 - ); - case OSPF6_LSTYPE_LINK: - /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes followed - by N>=0 IPv6 prefix blocks (with N declared beforehand). */ - if (headeronly) - break; - link_lsa = (struct ospf6_link_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE); - return ospf6_prefixes_examin - ( - (struct ospf6_prefix *) ((caddr_t) link_lsa + OSPF6_LINK_LSA_MIN_SIZE), - lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_LINK_LSA_MIN_SIZE, - ntohl (link_lsa->prefix_num) /* 32 bits */ - ); - case OSPF6_LSTYPE_INTRA_PREFIX: - /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE bytes - followed by N>=0 IPv6 prefixes (with N declared beforehand). */ - if (headeronly) - break; - intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE); - return ospf6_prefixes_examin - ( - (struct ospf6_prefix *) ((caddr_t) intra_prefix_lsa + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE), - lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE, - ntohs (intra_prefix_lsa->prefix_num) /* 16 bits */ - ); - } - /* No additional validation is possible for unknown LSA types, which are - themselves valid in OPSFv3, hence the default decision is to accept. */ - return MSG_OK; + struct ospf6_intra_prefix_lsa *intra_prefix_lsa; + struct ospf6_as_external_lsa *as_external_lsa; + struct ospf6_link_lsa *link_lsa; + unsigned exp_length; + u_int8_t ltindex; + u_int16_t lsatype; + + /* In case an additional minimum length constraint is defined for + current + LSA type, make sure that this constraint is met. */ + lsatype = ntohs(lsah->type); + ltindex = lsatype & OSPF6_LSTYPE_FCODE_MASK; + if (ltindex < OSPF6_LSTYPE_SIZE && ospf6_lsa_minlen[ltindex] + && lsalen < ospf6_lsa_minlen[ltindex] + OSPF6_LSA_HEADER_SIZE) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + zlog_debug("%s: undersized (%u B) LSA", __func__, + lsalen); + return MSG_NG; + } + switch (lsatype) { + case OSPF6_LSTYPE_ROUTER: + /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes + followed + by N>=0 interface descriptions. */ + if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_ROUTER_LSA_MIN_SIZE) + % OSPF6_ROUTER_LSDESC_FIX_SIZE) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV)) + zlog_debug( + "%s: interface description alignment error", + __func__); + return MSG_NG; + } + break; + case OSPF6_LSTYPE_NETWORK: + /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes + followed by N>=0 attached router descriptions. */ + if ((lsalen - OSPF6_LSA_HEADER_SIZE + - OSPF6_NETWORK_LSA_MIN_SIZE) + % OSPF6_NETWORK_LSDESC_FIX_SIZE) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV)) + zlog_debug( + "%s: router description alignment error", + __func__); + return MSG_NG; + } + break; + case OSPF6_LSTYPE_INTER_PREFIX: + /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE + bytes + followed by 3-4 fields of a single IPv6 prefix. */ + if (headeronly) + break; + return ospf6_prefixes_examin( + (struct ospf6_prefix + *)((caddr_t)lsah + OSPF6_LSA_HEADER_SIZE + + OSPF6_INTER_PREFIX_LSA_MIN_SIZE), + lsalen - OSPF6_LSA_HEADER_SIZE + - OSPF6_INTER_PREFIX_LSA_MIN_SIZE, + 1); + case OSPF6_LSTYPE_INTER_ROUTER: + /* RFC5340 A.4.6, fixed-size LSA. */ + if (lsalen + > OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_ROUTER_LSA_FIX_SIZE) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV)) + zlog_debug("%s: oversized (%u B) LSA", __func__, + lsalen); + return MSG_NG; + } + break; + case OSPF6_LSTYPE_AS_EXTERNAL: /* RFC5340 A.4.7, same as A.4.8. */ + case OSPF6_LSTYPE_TYPE_7: + /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE + bytes + followed by 3-4 fields of IPv6 prefix and 3 conditional LSA + fields: + 16 bytes of forwarding address, 4 bytes of external route + tag, + 4 bytes of referenced link state ID. */ + if (headeronly) + break; + as_external_lsa = + (struct ospf6_as_external_lsa + *)((caddr_t)lsah + OSPF6_LSA_HEADER_SIZE); + exp_length = + OSPF6_LSA_HEADER_SIZE + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE; + /* To find out if the last optional field (Referenced Link State + ID) is + assumed in this LSA, we need to access fixed fields of the + IPv6 + prefix before ospf6_prefix_examin() confirms its sizing. */ + if (exp_length + OSPF6_PREFIX_MIN_SIZE > lsalen) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV)) + zlog_debug("%s: undersized (%u B) LSA header", + __func__, lsalen); + return MSG_NG; + } + /* forwarding address */ + if (CHECK_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F)) + exp_length += 16; + /* external route tag */ + if (CHECK_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T)) + exp_length += 4; + /* referenced link state ID */ + if (as_external_lsa->prefix.u._prefix_referenced_lstype) + exp_length += 4; + /* All the fixed-size fields (mandatory and optional) must fit. + I.e., + this check does not include any IPv6 prefix fields. */ + if (exp_length > lsalen) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV)) + zlog_debug("%s: undersized (%u B) LSA header", + __func__, lsalen); + return MSG_NG; + } + /* The last call completely covers the remainder (IPv6 prefix). + */ + return ospf6_prefixes_examin( + (struct ospf6_prefix + *)((caddr_t)as_external_lsa + + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE), + lsalen - exp_length, 1); + case OSPF6_LSTYPE_LINK: + /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes + followed + by N>=0 IPv6 prefix blocks (with N declared beforehand). */ + if (headeronly) + break; + link_lsa = (struct ospf6_link_lsa *)((caddr_t)lsah + + OSPF6_LSA_HEADER_SIZE); + return ospf6_prefixes_examin( + (struct ospf6_prefix *)((caddr_t)link_lsa + + OSPF6_LINK_LSA_MIN_SIZE), + lsalen - OSPF6_LSA_HEADER_SIZE + - OSPF6_LINK_LSA_MIN_SIZE, + ntohl(link_lsa->prefix_num) /* 32 bits */ + ); + case OSPF6_LSTYPE_INTRA_PREFIX: + /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE + bytes + followed by N>=0 IPv6 prefixes (with N declared beforehand). + */ + if (headeronly) + break; + intra_prefix_lsa = + (struct ospf6_intra_prefix_lsa + *)((caddr_t)lsah + OSPF6_LSA_HEADER_SIZE); + return ospf6_prefixes_examin( + (struct ospf6_prefix + *)((caddr_t)intra_prefix_lsa + + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE), + lsalen - OSPF6_LSA_HEADER_SIZE + - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE, + ntohs(intra_prefix_lsa->prefix_num) /* 16 bits */ + ); + } + /* No additional validation is possible for unknown LSA types, which are + themselves valid in OPSFv3, hence the default decision is to accept. + */ + return MSG_OK; } /* Verify if the provided input buffer is a valid sequence of LSAs. This includes verification of LSA blocks length/alignment and dispatching of deeper-level checks. */ static unsigned -ospf6_lsaseq_examin -( - struct ospf6_lsa_header *lsah, /* start of buffered data */ - size_t length, - const u_char headeronly, - /* When declared_num_lsas is not 0, compare it to the real number of LSAs - and treat the difference as an error. */ - const u_int32_t declared_num_lsas -) +ospf6_lsaseq_examin(struct ospf6_lsa_header *lsah, /* start of buffered data */ + size_t length, const u_char headeronly, + /* When declared_num_lsas is not 0, compare it to the real + number of LSAs + and treat the difference as an error. */ + const u_int32_t declared_num_lsas) { - u_int32_t counted_lsas = 0; - - while (length) - { - u_int16_t lsalen; - if (length < OSPF6_LSA_HEADER_SIZE) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: undersized (%zu B) trailing (#%u) LSA header", - __func__, length, counted_lsas); - return MSG_NG; - } - /* save on ntohs() calls here and in the LSA validator */ - lsalen = OSPF6_LSA_SIZE (lsah); - if (lsalen < OSPF6_LSA_HEADER_SIZE) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: malformed LSA header #%u, declared length is %u B", - __func__, counted_lsas, lsalen); - return MSG_NG; - } - if (headeronly) - { - /* less checks here and in ospf6_lsa_examin() */ - if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 1)) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: anomaly in header-only %s LSA #%u", __func__, - ospf6_lstype_name (lsah->type), counted_lsas); - return MSG_NG; - } - lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE); - length -= OSPF6_LSA_HEADER_SIZE; - } - else - { - /* make sure the input buffer is deep enough before further checks */ - if (lsalen > length) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B", - __func__, ospf6_lstype_name (lsah->type), counted_lsas, lsalen, length); - return MSG_NG; - } - if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 0)) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: anomaly in %s LSA #%u", __func__, - ospf6_lstype_name (lsah->type), counted_lsas); - return MSG_NG; - } - lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + lsalen); - length -= lsalen; - } - counted_lsas++; - } - - if (declared_num_lsas && counted_lsas != declared_num_lsas) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: #LSAs declared (%u) does not match actual (%u)", - __func__, declared_num_lsas, counted_lsas); - return MSG_NG; - } - return MSG_OK; + u_int32_t counted_lsas = 0; + + while (length) { + u_int16_t lsalen; + if (length < OSPF6_LSA_HEADER_SIZE) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV)) + zlog_debug( + "%s: undersized (%zu B) trailing (#%u) LSA header", + __func__, length, counted_lsas); + return MSG_NG; + } + /* save on ntohs() calls here and in the LSA validator */ + lsalen = OSPF6_LSA_SIZE(lsah); + if (lsalen < OSPF6_LSA_HEADER_SIZE) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, + RECV)) + zlog_debug( + "%s: malformed LSA header #%u, declared length is %u B", + __func__, counted_lsas, lsalen); + return MSG_NG; + } + if (headeronly) { + /* less checks here and in ospf6_lsa_examin() */ + if (MSG_OK != ospf6_lsa_examin(lsah, lsalen, 1)) { + if (IS_OSPF6_DEBUG_MESSAGE( + OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + zlog_debug( + "%s: anomaly in header-only %s LSA #%u", + __func__, + ospf6_lstype_name(lsah->type), + counted_lsas); + return MSG_NG; + } + lsah = (struct ospf6_lsa_header + *)((caddr_t)lsah + + OSPF6_LSA_HEADER_SIZE); + length -= OSPF6_LSA_HEADER_SIZE; + } else { + /* make sure the input buffer is deep enough before + * further checks */ + if (lsalen > length) { + if (IS_OSPF6_DEBUG_MESSAGE( + OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + zlog_debug( + "%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B", + __func__, + ospf6_lstype_name(lsah->type), + counted_lsas, lsalen, length); + return MSG_NG; + } + if (MSG_OK != ospf6_lsa_examin(lsah, lsalen, 0)) { + if (IS_OSPF6_DEBUG_MESSAGE( + OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + zlog_debug( + "%s: anomaly in %s LSA #%u", + __func__, + ospf6_lstype_name(lsah->type), + counted_lsas); + return MSG_NG; + } + lsah = (struct ospf6_lsa_header *)((caddr_t)lsah + + lsalen); + length -= lsalen; + } + counted_lsas++; + } + + if (declared_num_lsas && counted_lsas != declared_num_lsas) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + zlog_debug( + "%s: #LSAs declared (%u) does not match actual (%u)", + __func__, declared_num_lsas, counted_lsas); + return MSG_NG; + } + return MSG_OK; } /* Verify a complete OSPF packet for proper sizing/alignment. */ -static unsigned -ospf6_packet_examin (struct ospf6_header *oh, const unsigned bytesonwire) +static unsigned ospf6_packet_examin(struct ospf6_header *oh, + const unsigned bytesonwire) { - struct ospf6_lsupdate *lsupd; - unsigned test; - - /* length, 1st approximation */ - if (bytesonwire < OSPF6_HEADER_SIZE) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: undersized (%u B) packet", __func__, bytesonwire); - return MSG_NG; - } - /* Now it is safe to access header fields. */ - if (bytesonwire != ntohs (oh->length)) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: packet length error (%u real, %u declared)", - __func__, bytesonwire, ntohs (oh->length)); - return MSG_NG; - } - /* version check */ - if (oh->version != OSPFV3_VERSION) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: invalid (%u) protocol version", __func__, oh->version); - return MSG_NG; - } - /* length, 2nd approximation */ - if - ( - oh->type < OSPF6_MESSAGE_TYPE_ALL && - ospf6_packet_minlen[oh->type] && - bytesonwire < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type] - ) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: undersized (%u B) %s packet", __func__, - bytesonwire, lookup_msg(ospf6_message_type_str, oh->type, NULL)); - return MSG_NG; - } - /* type-specific deeper validation */ - switch (oh->type) - { - case OSPF6_MESSAGE_TYPE_HELLO: - /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes followed - by N>=0 router-IDs. */ - if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_HELLO_MIN_SIZE) % 4) - return MSG_OK; - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: alignment error in %s packet", - __func__, lookup_msg(ospf6_message_type_str, oh->type, NULL)); - return MSG_NG; - case OSPF6_MESSAGE_TYPE_DBDESC: - /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes followed - by N>=0 header-only LSAs. */ - test = ospf6_lsaseq_examin - ( - (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_DB_DESC_MIN_SIZE), - bytesonwire - OSPF6_HEADER_SIZE - OSPF6_DB_DESC_MIN_SIZE, - 1, - 0 - ); - break; - case OSPF6_MESSAGE_TYPE_LSREQ: - /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */ - if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_REQ_MIN_SIZE) % OSPF6_LSREQ_LSDESC_FIX_SIZE) - return MSG_OK; - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: alignment error in %s packet", - __func__, lookup_msg(ospf6_message_type_str, oh->type, NULL)); - return MSG_NG; - case OSPF6_MESSAGE_TYPE_LSUPDATE: - /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes followed - by N>=0 full LSAs (with N declared beforehand). */ - lsupd = (struct ospf6_lsupdate *) ((caddr_t) oh + OSPF6_HEADER_SIZE); - test = ospf6_lsaseq_examin - ( - (struct ospf6_lsa_header *) ((caddr_t) lsupd + OSPF6_LS_UPD_MIN_SIZE), - bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_UPD_MIN_SIZE, - 0, - ntohl (lsupd->lsa_number) /* 32 bits */ - ); - break; - case OSPF6_MESSAGE_TYPE_LSACK: - /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */ - test = ospf6_lsaseq_examin - ( - (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_LS_ACK_MIN_SIZE), - bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_ACK_MIN_SIZE, - 1, - 0 - ); - break; - default: - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: invalid (%u) message type", __func__, oh->type); - return MSG_NG; - } - if (test != MSG_OK && IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: anomaly in %s packet", __func__, lookup_msg(ospf6_message_type_str, oh->type, NULL)); - return test; + struct ospf6_lsupdate *lsupd; + unsigned test; + + /* length, 1st approximation */ + if (bytesonwire < OSPF6_HEADER_SIZE) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + zlog_debug("%s: undersized (%u B) packet", __func__, + bytesonwire); + return MSG_NG; + } + /* Now it is safe to access header fields. */ + if (bytesonwire != ntohs(oh->length)) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + zlog_debug( + "%s: packet length error (%u real, %u declared)", + __func__, bytesonwire, ntohs(oh->length)); + return MSG_NG; + } + /* version check */ + if (oh->version != OSPFV3_VERSION) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + zlog_debug("%s: invalid (%u) protocol version", + __func__, oh->version); + return MSG_NG; + } + /* length, 2nd approximation */ + if (oh->type < OSPF6_MESSAGE_TYPE_ALL && ospf6_packet_minlen[oh->type] + && bytesonwire + < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + zlog_debug("%s: undersized (%u B) %s packet", __func__, + bytesonwire, + lookup_msg(ospf6_message_type_str, oh->type, + NULL)); + return MSG_NG; + } + /* type-specific deeper validation */ + switch (oh->type) { + case OSPF6_MESSAGE_TYPE_HELLO: + /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes + followed + by N>=0 router-IDs. */ + if (0 + == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_HELLO_MIN_SIZE) + % 4) + return MSG_OK; + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + zlog_debug("%s: alignment error in %s packet", __func__, + lookup_msg(ospf6_message_type_str, oh->type, + NULL)); + return MSG_NG; + case OSPF6_MESSAGE_TYPE_DBDESC: + /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes + followed + by N>=0 header-only LSAs. */ + test = ospf6_lsaseq_examin( + (struct ospf6_lsa_header *)((caddr_t)oh + + OSPF6_HEADER_SIZE + + OSPF6_DB_DESC_MIN_SIZE), + bytesonwire - OSPF6_HEADER_SIZE + - OSPF6_DB_DESC_MIN_SIZE, + 1, 0); + break; + case OSPF6_MESSAGE_TYPE_LSREQ: + /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */ + if (0 + == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_REQ_MIN_SIZE) + % OSPF6_LSREQ_LSDESC_FIX_SIZE) + return MSG_OK; + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + zlog_debug("%s: alignment error in %s packet", __func__, + lookup_msg(ospf6_message_type_str, oh->type, + NULL)); + return MSG_NG; + case OSPF6_MESSAGE_TYPE_LSUPDATE: + /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes + followed + by N>=0 full LSAs (with N declared beforehand). */ + lsupd = (struct ospf6_lsupdate *)((caddr_t)oh + + OSPF6_HEADER_SIZE); + test = ospf6_lsaseq_examin( + (struct ospf6_lsa_header *)((caddr_t)lsupd + + OSPF6_LS_UPD_MIN_SIZE), + bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_UPD_MIN_SIZE, + 0, ntohl(lsupd->lsa_number) /* 32 bits */ + ); + break; + case OSPF6_MESSAGE_TYPE_LSACK: + /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */ + test = ospf6_lsaseq_examin( + (struct ospf6_lsa_header *)((caddr_t)oh + + OSPF6_HEADER_SIZE + + OSPF6_LS_ACK_MIN_SIZE), + bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_ACK_MIN_SIZE, + 1, 0); + break; + default: + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + zlog_debug("%s: invalid (%u) message type", __func__, + oh->type); + return MSG_NG; + } + if (test != MSG_OK + && IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + zlog_debug("%s: anomaly in %s packet", __func__, + lookup_msg(ospf6_message_type_str, oh->type, NULL)); + return test; } /* Verify particular fields of otherwise correct received OSPF packet to meet the requirements of RFC. */ -static int -ospf6_rxpacket_examin (struct ospf6_interface *oi, struct ospf6_header *oh, const unsigned bytesonwire) +static int ospf6_rxpacket_examin(struct ospf6_interface *oi, + struct ospf6_header *oh, + const unsigned bytesonwire) { - char buf[2][INET_ADDRSTRLEN]; - - if (MSG_OK != ospf6_packet_examin (oh, bytesonwire)) - return MSG_NG; - - /* Area-ID check */ - if (oh->area_id != oi->area->area_id) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - { - if (oh->area_id == OSPF_AREA_BACKBONE) - zlog_debug ("%s: Message may be via Virtual Link: not supported", __func__); - else - zlog_debug - ( - "%s: Area-ID mismatch (my %s, rcvd %s)", __func__, - inet_ntop (AF_INET, &oi->area->area_id, buf[0], INET_ADDRSTRLEN), - inet_ntop (AF_INET, &oh->area_id, buf[1], INET_ADDRSTRLEN) - ); - } - return MSG_NG; - } - - /* Instance-ID check */ - if (oh->instance_id != oi->instance_id) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("%s: Instance-ID mismatch (my %u, rcvd %u)", __func__, oi->instance_id, oh->instance_id); - return MSG_NG; - } - - /* Router-ID check */ - if (oh->router_id == oi->area->ospf6->router_id) - { - zlog_warn ("%s: Duplicate Router-ID (%s)", __func__, inet_ntop (AF_INET, &oh->router_id, buf[0], INET_ADDRSTRLEN)); - return MSG_NG; - } - return MSG_OK; + char buf[2][INET_ADDRSTRLEN]; + + if (MSG_OK != ospf6_packet_examin(oh, bytesonwire)) + return MSG_NG; + + /* Area-ID check */ + if (oh->area_id != oi->area->area_id) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) { + if (oh->area_id == OSPF_AREA_BACKBONE) + zlog_debug( + "%s: Message may be via Virtual Link: not supported", + __func__); + else + zlog_debug( + "%s: Area-ID mismatch (my %s, rcvd %s)", + __func__, + inet_ntop(AF_INET, &oi->area->area_id, + buf[0], INET_ADDRSTRLEN), + inet_ntop(AF_INET, &oh->area_id, buf[1], + INET_ADDRSTRLEN)); + } + return MSG_NG; + } + + /* Instance-ID check */ + if (oh->instance_id != oi->instance_id) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("%s: Instance-ID mismatch (my %u, rcvd %u)", + __func__, oi->instance_id, oh->instance_id); + return MSG_NG; + } + + /* Router-ID check */ + if (oh->router_id == oi->area->ospf6->router_id) { + zlog_warn("%s: Duplicate Router-ID (%s)", __func__, + inet_ntop(AF_INET, &oh->router_id, buf[0], + INET_ADDRSTRLEN)); + return MSG_NG; + } + return MSG_OK; } -static void -ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst, - struct ospf6_interface *oi, struct ospf6_header *oh) +static void ospf6_lsupdate_recv(struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, + struct ospf6_header *oh) { - struct ospf6_neighbor *on; - struct ospf6_lsupdate *lsupdate; - char *p; - - on = ospf6_neighbor_lookup (oh->router_id, oi); - if (on == NULL) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Neighbor not found, ignore"); - return; - } - - if (on->state != OSPF6_NEIGHBOR_EXCHANGE && - on->state != OSPF6_NEIGHBOR_LOADING && - on->state != OSPF6_NEIGHBOR_FULL) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Neighbor state less than Exchange, ignore"); - return; - } - - lsupdate = (struct ospf6_lsupdate *) - ((caddr_t) oh + sizeof (struct ospf6_header)); - - /* Process LSAs */ - for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate)); - p < OSPF6_MESSAGE_END (oh) && - p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh); - p += OSPF6_LSA_SIZE (p)) - { - ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p); - } - - assert (p == OSPF6_MESSAGE_END (oh)); + struct ospf6_neighbor *on; + struct ospf6_lsupdate *lsupdate; + char *p; + + on = ospf6_neighbor_lookup(oh->router_id, oi); + if (on == NULL) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Neighbor not found, ignore"); + return; + } + + if (on->state != OSPF6_NEIGHBOR_EXCHANGE + && on->state != OSPF6_NEIGHBOR_LOADING + && on->state != OSPF6_NEIGHBOR_FULL) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Neighbor state less than Exchange, ignore"); + return; + } + + lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh + + sizeof(struct ospf6_header)); + /* Process LSAs */ + for (p = (char *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate)); + p < OSPF6_MESSAGE_END(oh) + && p + OSPF6_LSA_SIZE(p) <= OSPF6_MESSAGE_END(oh); + p += OSPF6_LSA_SIZE(p)) { + ospf6_receive_lsa(on, (struct ospf6_lsa_header *)p); + } + + assert(p == OSPF6_MESSAGE_END(oh)); } -static void -ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst, - struct ospf6_interface *oi, struct ospf6_header *oh) +static void ospf6_lsack_recv(struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, + struct ospf6_header *oh) { - struct ospf6_neighbor *on; - char *p; - struct ospf6_lsa *his, *mine; - struct ospf6_lsdb *lsdb = NULL; - - assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK); - - on = ospf6_neighbor_lookup (oh->router_id, oi); - if (on == NULL) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Neighbor not found, ignore"); - return; - } - - if (on->state != OSPF6_NEIGHBOR_EXCHANGE && - on->state != OSPF6_NEIGHBOR_LOADING && - on->state != OSPF6_NEIGHBOR_FULL) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Neighbor state less than Exchange, ignore"); - return; - } - - for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header)); - p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh); - p += sizeof (struct ospf6_lsa_header)) - { - his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p); - - switch (OSPF6_LSA_SCOPE (his->header->type)) - { - case OSPF6_SCOPE_LINKLOCAL: - lsdb = on->ospf6_if->lsdb; - break; - case OSPF6_SCOPE_AREA: - lsdb = on->ospf6_if->area->lsdb; - break; - case OSPF6_SCOPE_AS: - lsdb = on->ospf6_if->area->ospf6->lsdb; - break; - case OSPF6_SCOPE_RESERVED: - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Ignoring LSA of reserved scope"); - ospf6_lsa_delete (his); - continue; - break; - } - - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("%s acknowledged by %s", his->name, on->name); - - /* Find database copy */ - mine = ospf6_lsdb_lookup (his->header->type, his->header->id, - his->header->adv_router, lsdb); - if (mine == NULL) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("No database copy"); - ospf6_lsa_delete (his); - continue; - } - - /* Check if the LSA is on his retrans-list */ - mine = ospf6_lsdb_lookup (his->header->type, his->header->id, - his->header->adv_router, on->retrans_list); - if (mine == NULL) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Not on %s's retrans-list", on->name); - ospf6_lsa_delete (his); - continue; - } - - if (ospf6_lsa_compare (his, mine) != 0) - { - /* Log this questionable acknowledgement, - and examine the next one. */ - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Questionable acknowledgement"); - ospf6_lsa_delete (his); - continue; - } - - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Acknowledged, remove from %s's retrans-list", - on->name); - - ospf6_decrement_retrans_count (mine); - if (OSPF6_LSA_IS_MAXAGE (mine)) - ospf6_maxage_remove (on->ospf6_if->area->ospf6); - ospf6_lsdb_remove (mine, on->retrans_list); - ospf6_lsa_delete (his); - } - - assert (p == OSPF6_MESSAGE_END (oh)); + struct ospf6_neighbor *on; + char *p; + struct ospf6_lsa *his, *mine; + struct ospf6_lsdb *lsdb = NULL; + + assert(oh->type == OSPF6_MESSAGE_TYPE_LSACK); + + on = ospf6_neighbor_lookup(oh->router_id, oi); + if (on == NULL) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Neighbor not found, ignore"); + return; + } + + if (on->state != OSPF6_NEIGHBOR_EXCHANGE + && on->state != OSPF6_NEIGHBOR_LOADING + && on->state != OSPF6_NEIGHBOR_FULL) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Neighbor state less than Exchange, ignore"); + return; + } + + for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header)); + p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh); + p += sizeof(struct ospf6_lsa_header)) { + his = ospf6_lsa_create_headeronly((struct ospf6_lsa_header *)p); + + switch (OSPF6_LSA_SCOPE(his->header->type)) { + case OSPF6_SCOPE_LINKLOCAL: + lsdb = on->ospf6_if->lsdb; + break; + case OSPF6_SCOPE_AREA: + lsdb = on->ospf6_if->area->lsdb; + break; + case OSPF6_SCOPE_AS: + lsdb = on->ospf6_if->area->ospf6->lsdb; + break; + case OSPF6_SCOPE_RESERVED: + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Ignoring LSA of reserved scope"); + ospf6_lsa_delete(his); + continue; + break; + } + + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("%s acknowledged by %s", his->name, + on->name); + + /* Find database copy */ + mine = ospf6_lsdb_lookup(his->header->type, his->header->id, + his->header->adv_router, lsdb); + if (mine == NULL) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("No database copy"); + ospf6_lsa_delete(his); + continue; + } + + /* Check if the LSA is on his retrans-list */ + mine = ospf6_lsdb_lookup(his->header->type, his->header->id, + his->header->adv_router, + on->retrans_list); + if (mine == NULL) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Not on %s's retrans-list", + on->name); + ospf6_lsa_delete(his); + continue; + } + + if (ospf6_lsa_compare(his, mine) != 0) { + /* Log this questionable acknowledgement, + and examine the next one. */ + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug("Questionable acknowledgement"); + ospf6_lsa_delete(his); + continue; + } + + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) + zlog_debug( + "Acknowledged, remove from %s's retrans-list", + on->name); + + ospf6_decrement_retrans_count(mine); + if (OSPF6_LSA_IS_MAXAGE(mine)) + ospf6_maxage_remove(on->ospf6_if->area->ospf6); + ospf6_lsdb_remove(mine, on->retrans_list); + ospf6_lsa_delete(his); + } + + assert(p == OSPF6_MESSAGE_END(oh)); } static u_char *recvbuf = NULL; static u_char *sendbuf = NULL; static unsigned int iobuflen = 0; -int -ospf6_iobuf_size (unsigned int size) +int ospf6_iobuf_size(unsigned int size) { - u_char *recvnew, *sendnew; - - if (size <= iobuflen) - return iobuflen; - - recvnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size); - sendnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size); - if (recvnew == NULL || sendnew == NULL) - { - if (recvnew) - XFREE (MTYPE_OSPF6_MESSAGE, recvnew); - if (sendnew) - XFREE (MTYPE_OSPF6_MESSAGE, sendnew); - zlog_debug ("Could not allocate I/O buffer of size %d.", size); - return iobuflen; - } - - if (recvbuf) - XFREE (MTYPE_OSPF6_MESSAGE, recvbuf); - if (sendbuf) - XFREE (MTYPE_OSPF6_MESSAGE, sendbuf); - recvbuf = recvnew; - sendbuf = sendnew; - iobuflen = size; - - return iobuflen; + u_char *recvnew, *sendnew; + + if (size <= iobuflen) + return iobuflen; + + recvnew = XMALLOC(MTYPE_OSPF6_MESSAGE, size); + sendnew = XMALLOC(MTYPE_OSPF6_MESSAGE, size); + if (recvnew == NULL || sendnew == NULL) { + if (recvnew) + XFREE(MTYPE_OSPF6_MESSAGE, recvnew); + if (sendnew) + XFREE(MTYPE_OSPF6_MESSAGE, sendnew); + zlog_debug("Could not allocate I/O buffer of size %d.", size); + return iobuflen; + } + + if (recvbuf) + XFREE(MTYPE_OSPF6_MESSAGE, recvbuf); + if (sendbuf) + XFREE(MTYPE_OSPF6_MESSAGE, sendbuf); + recvbuf = recvnew; + sendbuf = sendnew; + iobuflen = size; + + return iobuflen; } -void -ospf6_message_terminate (void) +void ospf6_message_terminate(void) { - if (recvbuf) - { - XFREE (MTYPE_OSPF6_MESSAGE, recvbuf); - recvbuf = NULL; - } - - if (sendbuf) - { - XFREE (MTYPE_OSPF6_MESSAGE, sendbuf); - sendbuf = NULL; - } - - iobuflen = 0; + if (recvbuf) { + XFREE(MTYPE_OSPF6_MESSAGE, recvbuf); + recvbuf = NULL; + } + + if (sendbuf) { + XFREE(MTYPE_OSPF6_MESSAGE, sendbuf); + sendbuf = NULL; + } + + iobuflen = 0; } -int -ospf6_receive (struct thread *thread) +int ospf6_receive(struct thread *thread) { - int sockfd; - unsigned int len; - char srcname[64], dstname[64]; - struct in6_addr src, dst; - ifindex_t ifindex; - struct iovec iovector[2]; - struct ospf6_interface *oi; - struct ospf6_header *oh; - - /* add next read thread */ - sockfd = THREAD_FD (thread); - thread_add_read (master, ospf6_receive, NULL, sockfd, NULL); - - /* initialize */ - memset (&src, 0, sizeof (src)); - memset (&dst, 0, sizeof (dst)); - ifindex = 0; - memset (recvbuf, 0, iobuflen); - iovector[0].iov_base = recvbuf; - iovector[0].iov_len = iobuflen; - iovector[1].iov_base = NULL; - iovector[1].iov_len = 0; - - /* receive message */ - len = ospf6_recvmsg (&src, &dst, &ifindex, iovector); - if (len > iobuflen) - { - zlog_err ("Excess message read"); - return 0; - } - - oi = ospf6_interface_lookup_by_ifindex (ifindex); - if (oi == NULL || oi->area == NULL || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) - { - zlog_debug ("Message received on disabled interface"); - return 0; - } - if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE)) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: Ignore message on passive interface %s", - __func__, oi->interface->name); - return 0; - } - - oh = (struct ospf6_header *) recvbuf; - if (ospf6_rxpacket_examin (oi, oh, len) != MSG_OK) - return 0; - - /* Being here means, that no sizing/alignment issues were detected in - the input packet. This renders the additional checks performed below - and also in the type-specific dispatching functions a dead code, - which can be dismissed in a cleanup-focused review round later. */ - - /* Log */ - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - { - inet_ntop (AF_INET6, &src, srcname, sizeof (srcname)); - inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname)); - zlog_debug ("%s received on %s", - lookup_msg(ospf6_message_type_str, oh->type, NULL), oi->interface->name); - zlog_debug (" src: %s", srcname); - zlog_debug (" dst: %s", dstname); - - switch (oh->type) - { - case OSPF6_MESSAGE_TYPE_HELLO: - ospf6_hello_print (oh); - break; - case OSPF6_MESSAGE_TYPE_DBDESC: - ospf6_dbdesc_print (oh); - break; - case OSPF6_MESSAGE_TYPE_LSREQ: - ospf6_lsreq_print (oh); - break; - case OSPF6_MESSAGE_TYPE_LSUPDATE: - ospf6_lsupdate_print (oh); - break; - case OSPF6_MESSAGE_TYPE_LSACK: - ospf6_lsack_print (oh); - break; - default: - assert (0); - } - } - - switch (oh->type) - { - case OSPF6_MESSAGE_TYPE_HELLO: - ospf6_hello_recv (&src, &dst, oi, oh); - break; - - case OSPF6_MESSAGE_TYPE_DBDESC: - ospf6_dbdesc_recv (&src, &dst, oi, oh); - break; - - case OSPF6_MESSAGE_TYPE_LSREQ: - ospf6_lsreq_recv (&src, &dst, oi, oh); - break; - - case OSPF6_MESSAGE_TYPE_LSUPDATE: - ospf6_lsupdate_recv (&src, &dst, oi, oh); - break; - - case OSPF6_MESSAGE_TYPE_LSACK: - ospf6_lsack_recv (&src, &dst, oi, oh); - break; - - default: - assert (0); - } - - return 0; + int sockfd; + unsigned int len; + char srcname[64], dstname[64]; + struct in6_addr src, dst; + ifindex_t ifindex; + struct iovec iovector[2]; + struct ospf6_interface *oi; + struct ospf6_header *oh; + + /* add next read thread */ + sockfd = THREAD_FD(thread); + thread_add_read(master, ospf6_receive, NULL, sockfd, NULL); + + /* initialize */ + memset(&src, 0, sizeof(src)); + memset(&dst, 0, sizeof(dst)); + ifindex = 0; + memset(recvbuf, 0, iobuflen); + iovector[0].iov_base = recvbuf; + iovector[0].iov_len = iobuflen; + iovector[1].iov_base = NULL; + iovector[1].iov_len = 0; + + /* receive message */ + len = ospf6_recvmsg(&src, &dst, &ifindex, iovector); + if (len > iobuflen) { + zlog_err("Excess message read"); + return 0; + } + + oi = ospf6_interface_lookup_by_ifindex(ifindex); + if (oi == NULL || oi->area == NULL + || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) { + zlog_debug("Message received on disabled interface"); + return 0; + } + if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE)) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + zlog_debug("%s: Ignore message on passive interface %s", + __func__, oi->interface->name); + return 0; + } + + oh = (struct ospf6_header *)recvbuf; + if (ospf6_rxpacket_examin(oi, oh, len) != MSG_OK) + return 0; + + /* Being here means, that no sizing/alignment issues were detected in + the input packet. This renders the additional checks performed below + and also in the type-specific dispatching functions a dead code, + which can be dismissed in a cleanup-focused review round later. */ + + /* Log */ + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) { + inet_ntop(AF_INET6, &src, srcname, sizeof(srcname)); + inet_ntop(AF_INET6, &dst, dstname, sizeof(dstname)); + zlog_debug("%s received on %s", + lookup_msg(ospf6_message_type_str, oh->type, NULL), + oi->interface->name); + zlog_debug(" src: %s", srcname); + zlog_debug(" dst: %s", dstname); + + switch (oh->type) { + case OSPF6_MESSAGE_TYPE_HELLO: + ospf6_hello_print(oh); + break; + case OSPF6_MESSAGE_TYPE_DBDESC: + ospf6_dbdesc_print(oh); + break; + case OSPF6_MESSAGE_TYPE_LSREQ: + ospf6_lsreq_print(oh); + break; + case OSPF6_MESSAGE_TYPE_LSUPDATE: + ospf6_lsupdate_print(oh); + break; + case OSPF6_MESSAGE_TYPE_LSACK: + ospf6_lsack_print(oh); + break; + default: + assert(0); + } + } + + switch (oh->type) { + case OSPF6_MESSAGE_TYPE_HELLO: + ospf6_hello_recv(&src, &dst, oi, oh); + break; + + case OSPF6_MESSAGE_TYPE_DBDESC: + ospf6_dbdesc_recv(&src, &dst, oi, oh); + break; + + case OSPF6_MESSAGE_TYPE_LSREQ: + ospf6_lsreq_recv(&src, &dst, oi, oh); + break; + + case OSPF6_MESSAGE_TYPE_LSUPDATE: + ospf6_lsupdate_recv(&src, &dst, oi, oh); + break; + + case OSPF6_MESSAGE_TYPE_LSACK: + ospf6_lsack_recv(&src, &dst, oi, oh); + break; + + default: + assert(0); + } + + return 0; } -static void -ospf6_send (struct in6_addr *src, struct in6_addr *dst, - struct ospf6_interface *oi, struct ospf6_header *oh) +static void ospf6_send(struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, struct ospf6_header *oh) { - unsigned int len; - char srcname[64], dstname[64]; - struct iovec iovector[2]; - - /* initialize */ - iovector[0].iov_base = (caddr_t) oh; - iovector[0].iov_len = ntohs (oh->length); - iovector[1].iov_base = NULL; - iovector[1].iov_len = 0; - - /* fill OSPF header */ - oh->version = OSPFV3_VERSION; - /* message type must be set before */ - /* message length must be set before */ - oh->router_id = oi->area->ospf6->router_id; - oh->area_id = oi->area->area_id; - /* checksum is calculated by kernel */ - oh->instance_id = oi->instance_id; - oh->reserved = 0; - - /* Log */ - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND)) - { - inet_ntop (AF_INET6, dst, dstname, sizeof (dstname)); - if (src) - inet_ntop (AF_INET6, src, srcname, sizeof (srcname)); - else - memset (srcname, 0, sizeof (srcname)); - zlog_debug ("%s send on %s", - lookup_msg(ospf6_message_type_str, oh->type, NULL), oi->interface->name); - zlog_debug (" src: %s", srcname); - zlog_debug (" dst: %s", dstname); - - switch (oh->type) - { - case OSPF6_MESSAGE_TYPE_HELLO: - ospf6_hello_print (oh); - break; - case OSPF6_MESSAGE_TYPE_DBDESC: - ospf6_dbdesc_print (oh); - break; - case OSPF6_MESSAGE_TYPE_LSREQ: - ospf6_lsreq_print (oh); - break; - case OSPF6_MESSAGE_TYPE_LSUPDATE: - ospf6_lsupdate_print (oh); - break; - case OSPF6_MESSAGE_TYPE_LSACK: - ospf6_lsack_print (oh); - break; - default: - zlog_debug ("Unknown message"); - assert (0); - break; - } - } - - /* send message */ - len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector); - if (len != ntohs (oh->length)) - zlog_err ("Could not send entire message"); + unsigned int len; + char srcname[64], dstname[64]; + struct iovec iovector[2]; + + /* initialize */ + iovector[0].iov_base = (caddr_t)oh; + iovector[0].iov_len = ntohs(oh->length); + iovector[1].iov_base = NULL; + iovector[1].iov_len = 0; + + /* fill OSPF header */ + oh->version = OSPFV3_VERSION; + /* message type must be set before */ + /* message length must be set before */ + oh->router_id = oi->area->ospf6->router_id; + oh->area_id = oi->area->area_id; + /* checksum is calculated by kernel */ + oh->instance_id = oi->instance_id; + oh->reserved = 0; + + /* Log */ + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)) { + inet_ntop(AF_INET6, dst, dstname, sizeof(dstname)); + if (src) + inet_ntop(AF_INET6, src, srcname, sizeof(srcname)); + else + memset(srcname, 0, sizeof(srcname)); + zlog_debug("%s send on %s", + lookup_msg(ospf6_message_type_str, oh->type, NULL), + oi->interface->name); + zlog_debug(" src: %s", srcname); + zlog_debug(" dst: %s", dstname); + + switch (oh->type) { + case OSPF6_MESSAGE_TYPE_HELLO: + ospf6_hello_print(oh); + break; + case OSPF6_MESSAGE_TYPE_DBDESC: + ospf6_dbdesc_print(oh); + break; + case OSPF6_MESSAGE_TYPE_LSREQ: + ospf6_lsreq_print(oh); + break; + case OSPF6_MESSAGE_TYPE_LSUPDATE: + ospf6_lsupdate_print(oh); + break; + case OSPF6_MESSAGE_TYPE_LSACK: + ospf6_lsack_print(oh); + break; + default: + zlog_debug("Unknown message"); + assert(0); + break; + } + } + + /* send message */ + len = ospf6_sendmsg(src, dst, &oi->interface->ifindex, iovector); + if (len != ntohs(oh->length)) + zlog_err("Could not send entire message"); } -static uint32_t -ospf6_packet_max(struct ospf6_interface *oi) +static uint32_t ospf6_packet_max(struct ospf6_interface *oi) { - assert (oi->ifmtu > sizeof (struct ip6_hdr)); - return oi->ifmtu - (sizeof (struct ip6_hdr)); + assert(oi->ifmtu > sizeof(struct ip6_hdr)); + return oi->ifmtu - (sizeof(struct ip6_hdr)); } -int -ospf6_hello_send (struct thread *thread) +int ospf6_hello_send(struct thread *thread) { - struct ospf6_interface *oi; - struct ospf6_header *oh; - struct ospf6_hello *hello; - u_char *p; - struct listnode *node, *nnode; - struct ospf6_neighbor *on; - - oi = (struct ospf6_interface *) THREAD_ARG (thread); - oi->thread_send_hello = (struct thread *) NULL; - - if (oi->state <= OSPF6_INTERFACE_DOWN) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND)) - zlog_debug ("Unable to send Hello on down interface %s", - oi->interface->name); - return 0; - } - - if (iobuflen == 0) - { - zlog_debug ("Unable to send Hello on interface %s iobuflen is 0", - oi->interface->name); - return 0; - } - - /* set next thread */ - thread_add_timer (master, ospf6_hello_send, oi, oi->hello_interval, &oi->thread_send_hello); - - memset (sendbuf, 0, iobuflen); - oh = (struct ospf6_header *) sendbuf; - hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header)); - - hello->interface_id = htonl (oi->interface->ifindex); - hello->priority = oi->priority; - hello->options[0] = oi->area->options[0]; - hello->options[1] = oi->area->options[1]; - hello->options[2] = oi->area->options[2]; - hello->hello_interval = htons (oi->hello_interval); - hello->dead_interval = htons (oi->dead_interval); - hello->drouter = oi->drouter; - hello->bdrouter = oi->bdrouter; - - p = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello)); - - for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) - { - if (on->state < OSPF6_NEIGHBOR_INIT) - continue; - - if (p - sendbuf + sizeof (u_int32_t) > ospf6_packet_max(oi)) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND)) - zlog_debug ("sending Hello message: exceeds I/F MTU"); - break; - } - - memcpy (p, &on->router_id, sizeof (u_int32_t)); - p += sizeof (u_int32_t); - } - - oh->type = OSPF6_MESSAGE_TYPE_HELLO; - oh->length = htons (p - sendbuf); - - ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh); - return 0; + struct ospf6_interface *oi; + struct ospf6_header *oh; + struct ospf6_hello *hello; + u_char *p; + struct listnode *node, *nnode; + struct ospf6_neighbor *on; + + oi = (struct ospf6_interface *)THREAD_ARG(thread); + oi->thread_send_hello = (struct thread *)NULL; + + if (oi->state <= OSPF6_INTERFACE_DOWN) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO, SEND)) + zlog_debug("Unable to send Hello on down interface %s", + oi->interface->name); + return 0; + } + + if (iobuflen == 0) { + zlog_debug("Unable to send Hello on interface %s iobuflen is 0", + oi->interface->name); + return 0; + } + + /* set next thread */ + thread_add_timer(master, ospf6_hello_send, oi, oi->hello_interval, + &oi->thread_send_hello); + + memset(sendbuf, 0, iobuflen); + oh = (struct ospf6_header *)sendbuf; + hello = (struct ospf6_hello *)((caddr_t)oh + + sizeof(struct ospf6_header)); + + hello->interface_id = htonl(oi->interface->ifindex); + hello->priority = oi->priority; + hello->options[0] = oi->area->options[0]; + hello->options[1] = oi->area->options[1]; + hello->options[2] = oi->area->options[2]; + hello->hello_interval = htons(oi->hello_interval); + hello->dead_interval = htons(oi->dead_interval); + hello->drouter = oi->drouter; + hello->bdrouter = oi->bdrouter; + + p = (u_char *)((caddr_t)hello + sizeof(struct ospf6_hello)); + + for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) { + if (on->state < OSPF6_NEIGHBOR_INIT) + continue; + + if (p - sendbuf + sizeof(u_int32_t) > ospf6_packet_max(oi)) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO, + SEND)) + zlog_debug( + "sending Hello message: exceeds I/F MTU"); + break; + } + + memcpy(p, &on->router_id, sizeof(u_int32_t)); + p += sizeof(u_int32_t); + } + + oh->type = OSPF6_MESSAGE_TYPE_HELLO; + oh->length = htons(p - sendbuf); + + ospf6_send(oi->linklocal_addr, &allspfrouters6, oi, oh); + return 0; } -int -ospf6_dbdesc_send (struct thread *thread) +int ospf6_dbdesc_send(struct thread *thread) { - struct ospf6_neighbor *on; - struct ospf6_header *oh; - struct ospf6_dbdesc *dbdesc; - u_char *p; - struct ospf6_lsa *lsa; - struct in6_addr *dst; - - on = (struct ospf6_neighbor *) THREAD_ARG (thread); - on->thread_send_dbdesc = (struct thread *) NULL; - - if (on->state < OSPF6_NEIGHBOR_EXSTART) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND)) - zlog_debug ("Quit to send DbDesc to neighbor %s state %s", - on->name, ospf6_neighbor_state_str[on->state]); - return 0; - } - - /* set next thread if master */ - if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT)) - thread_add_timer (master, ospf6_dbdesc_send, on, - on->ospf6_if->rxmt_interval, - &on->thread_send_dbdesc); - - memset (sendbuf, 0, iobuflen); - oh = (struct ospf6_header *) sendbuf; - dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh + - sizeof (struct ospf6_header)); - - /* if this is initial one, initialize sequence number for DbDesc */ - if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT) && - (on->dbdesc_seqnum == 0)) - { - on->dbdesc_seqnum = monotime(NULL); - } - - dbdesc->options[0] = on->ospf6_if->area->options[0]; - dbdesc->options[1] = on->ospf6_if->area->options[1]; - dbdesc->options[2] = on->ospf6_if->area->options[2]; - dbdesc->ifmtu = htons (on->ospf6_if->ifmtu); - dbdesc->bits = on->dbdesc_bits; - dbdesc->seqnum = htonl (on->dbdesc_seqnum); - - /* if this is not initial one, set LSA headers in dbdesc */ - p = (u_char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc)); - if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT)) - { - for (ALL_LSDB(on->dbdesc_list, lsa)) - { - ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay); - - /* MTU check */ - if (p - sendbuf + sizeof (struct ospf6_lsa_header) > - ospf6_packet_max(on->ospf6_if)) - { - ospf6_lsdb_lsa_unlock (lsa); - break; - } - memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header)); - p += sizeof (struct ospf6_lsa_header); - } - } - - oh->type = OSPF6_MESSAGE_TYPE_DBDESC; - oh->length = htons (p - sendbuf); - - - if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) - dst = &allspfrouters6; - else - dst = &on->linklocal_addr; - - ospf6_send (on->ospf6_if->linklocal_addr, dst, on->ospf6_if, oh); - - return 0; + struct ospf6_neighbor *on; + struct ospf6_header *oh; + struct ospf6_dbdesc *dbdesc; + u_char *p; + struct ospf6_lsa *lsa; + struct in6_addr *dst; + + on = (struct ospf6_neighbor *)THREAD_ARG(thread); + on->thread_send_dbdesc = (struct thread *)NULL; + + if (on->state < OSPF6_NEIGHBOR_EXSTART) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_DBDESC, SEND)) + zlog_debug( + "Quit to send DbDesc to neighbor %s state %s", + on->name, ospf6_neighbor_state_str[on->state]); + return 0; + } + + /* set next thread if master */ + if (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT)) + thread_add_timer(master, ospf6_dbdesc_send, on, + on->ospf6_if->rxmt_interval, + &on->thread_send_dbdesc); + + memset(sendbuf, 0, iobuflen); + oh = (struct ospf6_header *)sendbuf; + dbdesc = (struct ospf6_dbdesc *)((caddr_t)oh + + sizeof(struct ospf6_header)); + + /* if this is initial one, initialize sequence number for DbDesc */ + if (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT) + && (on->dbdesc_seqnum == 0)) { + on->dbdesc_seqnum = monotime(NULL); + } + + dbdesc->options[0] = on->ospf6_if->area->options[0]; + dbdesc->options[1] = on->ospf6_if->area->options[1]; + dbdesc->options[2] = on->ospf6_if->area->options[2]; + dbdesc->ifmtu = htons(on->ospf6_if->ifmtu); + dbdesc->bits = on->dbdesc_bits; + dbdesc->seqnum = htonl(on->dbdesc_seqnum); + + /* if this is not initial one, set LSA headers in dbdesc */ + p = (u_char *)((caddr_t)dbdesc + sizeof(struct ospf6_dbdesc)); + if (!CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT)) { + for (ALL_LSDB(on->dbdesc_list, lsa)) { + ospf6_lsa_age_update_to_send(lsa, + on->ospf6_if->transdelay); + + /* MTU check */ + if (p - sendbuf + sizeof(struct ospf6_lsa_header) + > ospf6_packet_max(on->ospf6_if)) { + ospf6_lsdb_lsa_unlock(lsa); + break; + } + memcpy(p, lsa->header, sizeof(struct ospf6_lsa_header)); + p += sizeof(struct ospf6_lsa_header); + } + } + + oh->type = OSPF6_MESSAGE_TYPE_DBDESC; + oh->length = htons(p - sendbuf); + + + if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) + dst = &allspfrouters6; + else + dst = &on->linklocal_addr; + + ospf6_send(on->ospf6_if->linklocal_addr, dst, on->ospf6_if, oh); + + return 0; } -int -ospf6_dbdesc_send_newone (struct thread *thread) +int ospf6_dbdesc_send_newone(struct thread *thread) { - struct ospf6_neighbor *on; - struct ospf6_lsa *lsa; - unsigned int size = 0; - - on = (struct ospf6_neighbor *) THREAD_ARG (thread); - ospf6_lsdb_remove_all (on->dbdesc_list); - - /* move LSAs from summary_list to dbdesc_list (within neighbor structure) - so that ospf6_send_dbdesc () can send those LSAs */ - size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc); - for (ALL_LSDB(on->summary_list, lsa)) - { - if (size + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if)) - { - ospf6_lsdb_lsa_unlock (lsa); - break; - } - - ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list); - ospf6_lsdb_remove (lsa, on->summary_list); - size += sizeof (struct ospf6_lsa_header); - } - - if (on->summary_list->count == 0) - UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT); - - /* If slave, More bit check must be done here */ - if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */ - ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) && - ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT)) - thread_add_event (master, exchange_done, on, 0, NULL); - - thread_execute (master, ospf6_dbdesc_send, on, 0); - return 0; + struct ospf6_neighbor *on; + struct ospf6_lsa *lsa; + unsigned int size = 0; + + on = (struct ospf6_neighbor *)THREAD_ARG(thread); + ospf6_lsdb_remove_all(on->dbdesc_list); + + /* move LSAs from summary_list to dbdesc_list (within neighbor + structure) + so that ospf6_send_dbdesc () can send those LSAs */ + size = sizeof(struct ospf6_lsa_header) + sizeof(struct ospf6_dbdesc); + for (ALL_LSDB(on->summary_list, lsa)) { + if (size + sizeof(struct ospf6_lsa_header) + > ospf6_packet_max(on->ospf6_if)) { + ospf6_lsdb_lsa_unlock(lsa); + break; + } + + ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->dbdesc_list); + ospf6_lsdb_remove(lsa, on->summary_list); + size += sizeof(struct ospf6_lsa_header); + } + + if (on->summary_list->count == 0) + UNSET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT); + + /* If slave, More bit check must be done here */ + if (!CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */ + !CHECK_FLAG(on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) + && !CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT)) + thread_add_event(master, exchange_done, on, 0, NULL); + + thread_execute(master, ospf6_dbdesc_send, on, 0); + return 0; } -int -ospf6_lsreq_send (struct thread *thread) +int ospf6_lsreq_send(struct thread *thread) { - struct ospf6_neighbor *on; - struct ospf6_header *oh; - struct ospf6_lsreq_entry *e; - u_char *p; - struct ospf6_lsa *lsa, *last_req; - - on = (struct ospf6_neighbor *) THREAD_ARG (thread); - on->thread_send_lsreq = (struct thread *) NULL; - - /* LSReq will be sent only in ExStart or Loading */ - if (on->state != OSPF6_NEIGHBOR_EXCHANGE && - on->state != OSPF6_NEIGHBOR_LOADING) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND)) - zlog_debug ("Quit to send LSReq to neighbor %s state %s", - on->name, ospf6_neighbor_state_str[on->state]); - return 0; - } - - /* schedule loading_done if request list is empty */ - if (on->request_list->count == 0) - { - thread_add_event (master, loading_done, on, 0, NULL); - return 0; - } - - memset (sendbuf, 0, iobuflen); - oh = (struct ospf6_header *) sendbuf; - last_req = NULL; - - /* set Request entries in lsreq */ - p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header)); - for (ALL_LSDB(on->request_list, lsa)) - { - /* MTU check */ - if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > ospf6_packet_max(on->ospf6_if)) - { - ospf6_lsdb_lsa_unlock (lsa); - break; - } - - e = (struct ospf6_lsreq_entry *) p; - e->type = lsa->header->type; - e->id = lsa->header->id; - e->adv_router = lsa->header->adv_router; - p += sizeof (struct ospf6_lsreq_entry); - last_req = lsa; - } - - if (last_req != NULL) - { - if (on->last_ls_req != NULL) - { - ospf6_lsa_unlock (on->last_ls_req); - } - ospf6_lsa_lock (last_req); - on->last_ls_req = last_req; - } - - oh->type = OSPF6_MESSAGE_TYPE_LSREQ; - oh->length = htons (p - sendbuf); - - if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) - ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6, - on->ospf6_if, oh); - else - ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, - on->ospf6_if, oh); - - /* set next thread */ - if (on->request_list->count != 0) - { - on->thread_send_lsreq = NULL; - thread_add_timer(master, ospf6_lsreq_send, on, on->ospf6_if->rxmt_interval, - &on->thread_send_lsreq); - } - - return 0; + struct ospf6_neighbor *on; + struct ospf6_header *oh; + struct ospf6_lsreq_entry *e; + u_char *p; + struct ospf6_lsa *lsa, *last_req; + + on = (struct ospf6_neighbor *)THREAD_ARG(thread); + on->thread_send_lsreq = (struct thread *)NULL; + + /* LSReq will be sent only in ExStart or Loading */ + if (on->state != OSPF6_NEIGHBOR_EXCHANGE + && on->state != OSPF6_NEIGHBOR_LOADING) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ, SEND)) + zlog_debug("Quit to send LSReq to neighbor %s state %s", + on->name, + ospf6_neighbor_state_str[on->state]); + return 0; + } + + /* schedule loading_done if request list is empty */ + if (on->request_list->count == 0) { + thread_add_event(master, loading_done, on, 0, NULL); + return 0; + } + + memset(sendbuf, 0, iobuflen); + oh = (struct ospf6_header *)sendbuf; + last_req = NULL; + + /* set Request entries in lsreq */ + p = (u_char *)((caddr_t)oh + sizeof(struct ospf6_header)); + for (ALL_LSDB(on->request_list, lsa)) { + /* MTU check */ + if (p - sendbuf + sizeof(struct ospf6_lsreq_entry) + > ospf6_packet_max(on->ospf6_if)) { + ospf6_lsdb_lsa_unlock(lsa); + break; + } + + e = (struct ospf6_lsreq_entry *)p; + e->type = lsa->header->type; + e->id = lsa->header->id; + e->adv_router = lsa->header->adv_router; + p += sizeof(struct ospf6_lsreq_entry); + last_req = lsa; + } + + if (last_req != NULL) { + if (on->last_ls_req != NULL) { + ospf6_lsa_unlock(on->last_ls_req); + } + ospf6_lsa_lock(last_req); + on->last_ls_req = last_req; + } + + oh->type = OSPF6_MESSAGE_TYPE_LSREQ; + oh->length = htons(p - sendbuf); + + if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) + ospf6_send(on->ospf6_if->linklocal_addr, &allspfrouters6, + on->ospf6_if, oh); + else + ospf6_send(on->ospf6_if->linklocal_addr, &on->linklocal_addr, + on->ospf6_if, oh); + + /* set next thread */ + if (on->request_list->count != 0) { + on->thread_send_lsreq = NULL; + thread_add_timer(master, ospf6_lsreq_send, on, + on->ospf6_if->rxmt_interval, + &on->thread_send_lsreq); + } + + return 0; } -int -ospf6_lsupdate_send_neighbor (struct thread *thread) +int ospf6_lsupdate_send_neighbor(struct thread *thread) { - struct ospf6_neighbor *on; - struct ospf6_header *oh; - struct ospf6_lsupdate *lsupdate; - u_char *p; - int lsa_cnt; - struct ospf6_lsa *lsa; - - on = (struct ospf6_neighbor *) THREAD_ARG (thread); - on->thread_send_lsupdate = (struct thread *) NULL; - - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND)) - zlog_debug ("LSUpdate to neighbor %s", on->name); - - if (on->state < OSPF6_NEIGHBOR_EXCHANGE) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND)) - zlog_debug ("Quit to send (neighbor state %s)", - ospf6_neighbor_state_str[on->state]); - return 0; - } - - memset (sendbuf, 0, iobuflen); - oh = (struct ospf6_header *) sendbuf; - lsupdate = (struct ospf6_lsupdate *) - ((caddr_t) oh + sizeof (struct ospf6_header)); - - p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate)); - lsa_cnt = 0; - - /* lsupdate_list lists those LSA which doesn't need to be - retransmitted. remove those from the list */ - for (ALL_LSDB(on->lsupdate_list, lsa)) - { - /* MTU check */ - if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header)) - > ospf6_packet_max(on->ospf6_if)) - { - ospf6_lsdb_lsa_unlock (lsa); - break; - } - - ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay); - memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header)); - p += OSPF6_LSA_SIZE (lsa->header); - lsa_cnt++; - - assert (lsa->lock == 2); - ospf6_lsdb_remove (lsa, on->lsupdate_list); - } - - if (lsa_cnt) - { - oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE; - oh->length = htons (p - sendbuf); - lsupdate->lsa_number = htonl (lsa_cnt); - - if ((on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) || - (on->ospf6_if->state == OSPF6_INTERFACE_DR) || - (on->ospf6_if->state == OSPF6_INTERFACE_BDR)) - ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6, - on->ospf6_if, oh); - else - ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, - on->ospf6_if, oh); - } - - /* The addresses used for retransmissions are different from those sent the - first time and so we need to separate them here. - */ - memset (sendbuf, 0, iobuflen); - oh = (struct ospf6_header *) sendbuf; - lsupdate = (struct ospf6_lsupdate *) - ((caddr_t) oh + sizeof (struct ospf6_header)); - p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate)); - lsa_cnt = 0; - - for (ALL_LSDB(on->retrans_list, lsa)) - { - /* MTU check */ - if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header)) - > ospf6_packet_max(on->ospf6_if)) - { - ospf6_lsdb_lsa_unlock (lsa); - break; - } - - ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay); - memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header)); - p += OSPF6_LSA_SIZE (lsa->header); - lsa_cnt++; - } - - if (lsa_cnt) - { - oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE; - oh->length = htons (p - sendbuf); - lsupdate->lsa_number = htonl (lsa_cnt); - - if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) - ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6, - on->ospf6_if, oh); - else - ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, - on->ospf6_if, oh); - } - - if (on->lsupdate_list->count != 0) { - on->thread_send_lsupdate = NULL; - thread_add_event(master, ospf6_lsupdate_send_neighbor, on, 0, - &on->thread_send_lsupdate); - } - else if (on->retrans_list->count != 0) { - on->thread_send_lsupdate = NULL; - thread_add_timer(master, ospf6_lsupdate_send_neighbor, on, on->ospf6_if->rxmt_interval, - &on->thread_send_lsupdate); - } - return 0; + struct ospf6_neighbor *on; + struct ospf6_header *oh; + struct ospf6_lsupdate *lsupdate; + u_char *p; + int lsa_cnt; + struct ospf6_lsa *lsa; + + on = (struct ospf6_neighbor *)THREAD_ARG(thread); + on->thread_send_lsupdate = (struct thread *)NULL; + + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND)) + zlog_debug("LSUpdate to neighbor %s", on->name); + + if (on->state < OSPF6_NEIGHBOR_EXCHANGE) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND)) + zlog_debug("Quit to send (neighbor state %s)", + ospf6_neighbor_state_str[on->state]); + return 0; + } + + memset(sendbuf, 0, iobuflen); + oh = (struct ospf6_header *)sendbuf; + lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh + + sizeof(struct ospf6_header)); + + p = (u_char *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate)); + lsa_cnt = 0; + + /* lsupdate_list lists those LSA which doesn't need to be + retransmitted. remove those from the list */ + for (ALL_LSDB(on->lsupdate_list, lsa)) { + /* MTU check */ + if ((p - sendbuf + (unsigned int)OSPF6_LSA_SIZE(lsa->header)) + > ospf6_packet_max(on->ospf6_if)) { + ospf6_lsdb_lsa_unlock(lsa); + break; + } + + ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay); + memcpy(p, lsa->header, OSPF6_LSA_SIZE(lsa->header)); + p += OSPF6_LSA_SIZE(lsa->header); + lsa_cnt++; + + assert(lsa->lock == 2); + ospf6_lsdb_remove(lsa, on->lsupdate_list); + } + + if (lsa_cnt) { + oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE; + oh->length = htons(p - sendbuf); + lsupdate->lsa_number = htonl(lsa_cnt); + + if ((on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) + || (on->ospf6_if->state == OSPF6_INTERFACE_DR) + || (on->ospf6_if->state == OSPF6_INTERFACE_BDR)) + ospf6_send(on->ospf6_if->linklocal_addr, + &allspfrouters6, on->ospf6_if, oh); + else + ospf6_send(on->ospf6_if->linklocal_addr, + &on->linklocal_addr, on->ospf6_if, oh); + } + + /* The addresses used for retransmissions are different from those sent + the + first time and so we need to separate them here. + */ + memset(sendbuf, 0, iobuflen); + oh = (struct ospf6_header *)sendbuf; + lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh + + sizeof(struct ospf6_header)); + p = (u_char *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate)); + lsa_cnt = 0; + + for (ALL_LSDB(on->retrans_list, lsa)) { + /* MTU check */ + if ((p - sendbuf + (unsigned int)OSPF6_LSA_SIZE(lsa->header)) + > ospf6_packet_max(on->ospf6_if)) { + ospf6_lsdb_lsa_unlock(lsa); + break; + } + + ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay); + memcpy(p, lsa->header, OSPF6_LSA_SIZE(lsa->header)); + p += OSPF6_LSA_SIZE(lsa->header); + lsa_cnt++; + } + + if (lsa_cnt) { + oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE; + oh->length = htons(p - sendbuf); + lsupdate->lsa_number = htonl(lsa_cnt); + + if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) + ospf6_send(on->ospf6_if->linklocal_addr, + &allspfrouters6, on->ospf6_if, oh); + else + ospf6_send(on->ospf6_if->linklocal_addr, + &on->linklocal_addr, on->ospf6_if, oh); + } + + if (on->lsupdate_list->count != 0) { + on->thread_send_lsupdate = NULL; + thread_add_event(master, ospf6_lsupdate_send_neighbor, on, 0, + &on->thread_send_lsupdate); + } else if (on->retrans_list->count != 0) { + on->thread_send_lsupdate = NULL; + thread_add_timer(master, ospf6_lsupdate_send_neighbor, on, + on->ospf6_if->rxmt_interval, + &on->thread_send_lsupdate); + } + return 0; } -int -ospf6_lsupdate_send_interface (struct thread *thread) +int ospf6_lsupdate_send_interface(struct thread *thread) { - struct ospf6_interface *oi; - struct ospf6_header *oh; - struct ospf6_lsupdate *lsupdate; - u_char *p; - int lsa_cnt; - struct ospf6_lsa *lsa; - - oi = (struct ospf6_interface *) THREAD_ARG (thread); - oi->thread_send_lsupdate = (struct thread *) NULL; - - if (oi->state <= OSPF6_INTERFACE_WAITING) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND)) - zlog_debug ("Quit to send LSUpdate to interface %s state %s", - oi->interface->name, ospf6_interface_state_str[oi->state]); - return 0; - } - - /* if we have nothing to send, return */ - if (oi->lsupdate_list->count == 0) - return 0; - - memset (sendbuf, 0, iobuflen); - oh = (struct ospf6_header *) sendbuf; - lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh + - sizeof (struct ospf6_header)); - - p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate)); - lsa_cnt = 0; - - for (ALL_LSDB(oi->lsupdate_list, lsa)) - { - /* MTU check */ - if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header))) - > ospf6_packet_max(oi)) - { - ospf6_lsdb_lsa_unlock (lsa); - break; - } - - ospf6_lsa_age_update_to_send (lsa, oi->transdelay); - memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header)); - p += OSPF6_LSA_SIZE (lsa->header); - lsa_cnt++; - - assert (lsa->lock == 2); - ospf6_lsdb_remove (lsa, oi->lsupdate_list); - } - - if (lsa_cnt) - { - lsupdate->lsa_number = htonl (lsa_cnt); - - oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE; - oh->length = htons (p - sendbuf); - - if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) || - (oi->state == OSPF6_INTERFACE_DR) || - (oi->state == OSPF6_INTERFACE_BDR)) - ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh); - else - ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh); - - } - - if (oi->lsupdate_list->count > 0) - { - oi->thread_send_lsupdate = NULL; - thread_add_event(master, ospf6_lsupdate_send_interface, oi, 0, - &oi->thread_send_lsupdate); - } - - return 0; + struct ospf6_interface *oi; + struct ospf6_header *oh; + struct ospf6_lsupdate *lsupdate; + u_char *p; + int lsa_cnt; + struct ospf6_lsa *lsa; + + oi = (struct ospf6_interface *)THREAD_ARG(thread); + oi->thread_send_lsupdate = (struct thread *)NULL; + + if (oi->state <= OSPF6_INTERFACE_WAITING) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND)) + zlog_debug( + "Quit to send LSUpdate to interface %s state %s", + oi->interface->name, + ospf6_interface_state_str[oi->state]); + return 0; + } + + /* if we have nothing to send, return */ + if (oi->lsupdate_list->count == 0) + return 0; + + memset(sendbuf, 0, iobuflen); + oh = (struct ospf6_header *)sendbuf; + lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh + + sizeof(struct ospf6_header)); + + p = (u_char *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate)); + lsa_cnt = 0; + + for (ALL_LSDB(oi->lsupdate_list, lsa)) { + /* MTU check */ + if ((p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE(lsa->header))) + > ospf6_packet_max(oi)) { + ospf6_lsdb_lsa_unlock(lsa); + break; + } + + ospf6_lsa_age_update_to_send(lsa, oi->transdelay); + memcpy(p, lsa->header, OSPF6_LSA_SIZE(lsa->header)); + p += OSPF6_LSA_SIZE(lsa->header); + lsa_cnt++; + + assert(lsa->lock == 2); + ospf6_lsdb_remove(lsa, oi->lsupdate_list); + } + + if (lsa_cnt) { + lsupdate->lsa_number = htonl(lsa_cnt); + + oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE; + oh->length = htons(p - sendbuf); + + if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) + || (oi->state == OSPF6_INTERFACE_DR) + || (oi->state == OSPF6_INTERFACE_BDR)) + ospf6_send(oi->linklocal_addr, &allspfrouters6, oi, oh); + else + ospf6_send(oi->linklocal_addr, &alldrouters6, oi, oh); + } + + if (oi->lsupdate_list->count > 0) { + oi->thread_send_lsupdate = NULL; + thread_add_event(master, ospf6_lsupdate_send_interface, oi, 0, + &oi->thread_send_lsupdate); + } + + return 0; } -int -ospf6_lsack_send_neighbor (struct thread *thread) +int ospf6_lsack_send_neighbor(struct thread *thread) { - struct ospf6_neighbor *on; - struct ospf6_header *oh; - u_char *p; - struct ospf6_lsa *lsa; - int lsa_cnt = 0; - - on = (struct ospf6_neighbor *) THREAD_ARG (thread); - on->thread_send_lsack = (struct thread *) NULL; - - if (on->state < OSPF6_NEIGHBOR_EXCHANGE) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND)) - zlog_debug ("Quit to send LSAck to neighbor %s state %s", - on->name, ospf6_neighbor_state_str[on->state]); - return 0; - } - - /* if we have nothing to send, return */ - if (on->lsack_list->count == 0) - return 0; - - memset (sendbuf, 0, iobuflen); - oh = (struct ospf6_header *) sendbuf; - - p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header)); - - for (ALL_LSDB(on->lsack_list, lsa)) - { - /* MTU check */ - if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if)) - { - /* if we run out of packet size/space here, - better to try again soon. */ - THREAD_OFF (on->thread_send_lsack); - thread_add_event (master, ospf6_lsack_send_neighbor, on, 0, &on->thread_send_lsack); - - ospf6_lsdb_lsa_unlock (lsa); - break; - } - - ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay); - memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header)); - p += sizeof (struct ospf6_lsa_header); - - assert (lsa->lock == 2); - ospf6_lsdb_remove (lsa, on->lsack_list); - lsa_cnt++; - } - - if (lsa_cnt) - { - oh->type = OSPF6_MESSAGE_TYPE_LSACK; - oh->length = htons (p - sendbuf); - - ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, - on->ospf6_if, oh); - } - - if (on->lsack_list->count > 0) - thread_add_event (master, ospf6_lsack_send_neighbor, on, 0, &on->thread_send_lsack); - - return 0; + struct ospf6_neighbor *on; + struct ospf6_header *oh; + u_char *p; + struct ospf6_lsa *lsa; + int lsa_cnt = 0; + + on = (struct ospf6_neighbor *)THREAD_ARG(thread); + on->thread_send_lsack = (struct thread *)NULL; + + if (on->state < OSPF6_NEIGHBOR_EXCHANGE) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK, SEND)) + zlog_debug("Quit to send LSAck to neighbor %s state %s", + on->name, + ospf6_neighbor_state_str[on->state]); + return 0; + } + + /* if we have nothing to send, return */ + if (on->lsack_list->count == 0) + return 0; + + memset(sendbuf, 0, iobuflen); + oh = (struct ospf6_header *)sendbuf; + + p = (u_char *)((caddr_t)oh + sizeof(struct ospf6_header)); + + for (ALL_LSDB(on->lsack_list, lsa)) { + /* MTU check */ + if (p - sendbuf + sizeof(struct ospf6_lsa_header) + > ospf6_packet_max(on->ospf6_if)) { + /* if we run out of packet size/space here, + better to try again soon. */ + THREAD_OFF(on->thread_send_lsack); + thread_add_event(master, ospf6_lsack_send_neighbor, on, + 0, &on->thread_send_lsack); + + ospf6_lsdb_lsa_unlock(lsa); + break; + } + + ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay); + memcpy(p, lsa->header, sizeof(struct ospf6_lsa_header)); + p += sizeof(struct ospf6_lsa_header); + + assert(lsa->lock == 2); + ospf6_lsdb_remove(lsa, on->lsack_list); + lsa_cnt++; + } + + if (lsa_cnt) { + oh->type = OSPF6_MESSAGE_TYPE_LSACK; + oh->length = htons(p - sendbuf); + + ospf6_send(on->ospf6_if->linklocal_addr, &on->linklocal_addr, + on->ospf6_if, oh); + } + + if (on->lsack_list->count > 0) + thread_add_event(master, ospf6_lsack_send_neighbor, on, 0, + &on->thread_send_lsack); + + return 0; } -int -ospf6_lsack_send_interface (struct thread *thread) +int ospf6_lsack_send_interface(struct thread *thread) { - struct ospf6_interface *oi; - struct ospf6_header *oh; - u_char *p; - struct ospf6_lsa *lsa; - int lsa_cnt = 0; - - oi = (struct ospf6_interface *) THREAD_ARG (thread); - oi->thread_send_lsack = (struct thread *) NULL; - - if (oi->state <= OSPF6_INTERFACE_WAITING) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND)) - zlog_debug ("Quit to send LSAck to interface %s state %s", - oi->interface->name, ospf6_interface_state_str[oi->state]); - return 0; - } - - /* if we have nothing to send, return */ - if (oi->lsack_list->count == 0) - return 0; - - memset (sendbuf, 0, iobuflen); - oh = (struct ospf6_header *) sendbuf; - - p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header)); - - for (ALL_LSDB(oi->lsack_list, lsa)) - { - /* MTU check */ - if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(oi)) - { - /* if we run out of packet size/space here, - better to try again soon. */ - THREAD_OFF (oi->thread_send_lsack); - thread_add_event (master, ospf6_lsack_send_interface, oi, 0, - &oi->thread_send_lsack); - - ospf6_lsdb_lsa_unlock (lsa); - break; - } - - ospf6_lsa_age_update_to_send (lsa, oi->transdelay); - memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header)); - p += sizeof (struct ospf6_lsa_header); - - assert (lsa->lock == 2); - ospf6_lsdb_remove (lsa, oi->lsack_list); - lsa_cnt++; - } - - if (lsa_cnt) - { - oh->type = OSPF6_MESSAGE_TYPE_LSACK; - oh->length = htons (p - sendbuf); - - if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) || - (oi->state == OSPF6_INTERFACE_DR) || - (oi->state == OSPF6_INTERFACE_BDR)) - ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh); - else - ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh); - } - - if (oi->lsack_list->count > 0) - thread_add_event (master, ospf6_lsack_send_interface, oi, 0, &oi->thread_send_lsack); - - return 0; + struct ospf6_interface *oi; + struct ospf6_header *oh; + u_char *p; + struct ospf6_lsa *lsa; + int lsa_cnt = 0; + + oi = (struct ospf6_interface *)THREAD_ARG(thread); + oi->thread_send_lsack = (struct thread *)NULL; + + if (oi->state <= OSPF6_INTERFACE_WAITING) { + if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK, SEND)) + zlog_debug( + "Quit to send LSAck to interface %s state %s", + oi->interface->name, + ospf6_interface_state_str[oi->state]); + return 0; + } + + /* if we have nothing to send, return */ + if (oi->lsack_list->count == 0) + return 0; + + memset(sendbuf, 0, iobuflen); + oh = (struct ospf6_header *)sendbuf; + + p = (u_char *)((caddr_t)oh + sizeof(struct ospf6_header)); + + for (ALL_LSDB(oi->lsack_list, lsa)) { + /* MTU check */ + if (p - sendbuf + sizeof(struct ospf6_lsa_header) + > ospf6_packet_max(oi)) { + /* if we run out of packet size/space here, + better to try again soon. */ + THREAD_OFF(oi->thread_send_lsack); + thread_add_event(master, ospf6_lsack_send_interface, oi, + 0, &oi->thread_send_lsack); + + ospf6_lsdb_lsa_unlock(lsa); + break; + } + + ospf6_lsa_age_update_to_send(lsa, oi->transdelay); + memcpy(p, lsa->header, sizeof(struct ospf6_lsa_header)); + p += sizeof(struct ospf6_lsa_header); + + assert(lsa->lock == 2); + ospf6_lsdb_remove(lsa, oi->lsack_list); + lsa_cnt++; + } + + if (lsa_cnt) { + oh->type = OSPF6_MESSAGE_TYPE_LSACK; + oh->length = htons(p - sendbuf); + + if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) + || (oi->state == OSPF6_INTERFACE_DR) + || (oi->state == OSPF6_INTERFACE_BDR)) + ospf6_send(oi->linklocal_addr, &allspfrouters6, oi, oh); + else + ospf6_send(oi->linklocal_addr, &alldrouters6, oi, oh); + } + + if (oi->lsack_list->count > 0) + thread_add_event(master, ospf6_lsack_send_interface, oi, 0, + &oi->thread_send_lsack); + + return 0; } @@ -2335,44 +2314,42 @@ DEFUN (debug_ospf6_message, "Debug only sending message\n" "Debug only receiving message\n") { - int idx_packet = 3; - int idx_send_recv = 4; - unsigned char level = 0; - int type = 0; - int i; - - /* check type */ - if (! strncmp (argv[idx_packet]->arg, "u", 1)) - type = OSPF6_MESSAGE_TYPE_UNKNOWN; - else if (! strncmp (argv[idx_packet]->arg, "h", 1)) - type = OSPF6_MESSAGE_TYPE_HELLO; - else if (! strncmp (argv[idx_packet]->arg, "d", 1)) - type = OSPF6_MESSAGE_TYPE_DBDESC; - else if (! strncmp (argv[idx_packet]->arg, "lsr", 3)) - type = OSPF6_MESSAGE_TYPE_LSREQ; - else if (! strncmp (argv[idx_packet]->arg, "lsu", 3)) - type = OSPF6_MESSAGE_TYPE_LSUPDATE; - else if (! strncmp (argv[idx_packet]->arg, "lsa", 3)) - type = OSPF6_MESSAGE_TYPE_LSACK; - else if (! strncmp (argv[idx_packet]->arg, "a", 1)) - type = OSPF6_MESSAGE_TYPE_ALL; - - if (argc == 4) - level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV; - else if (! strncmp (argv[idx_send_recv]->arg, "s", 1)) - level = OSPF6_DEBUG_MESSAGE_SEND; - else if (! strncmp (argv[idx_send_recv]->arg, "r", 1)) - level = OSPF6_DEBUG_MESSAGE_RECV; - - if (type == OSPF6_MESSAGE_TYPE_ALL) - { - for (i = 0; i < 6; i++) - OSPF6_DEBUG_MESSAGE_ON (i, level); - } - else - OSPF6_DEBUG_MESSAGE_ON (type, level); - - return CMD_SUCCESS; + int idx_packet = 3; + int idx_send_recv = 4; + unsigned char level = 0; + int type = 0; + int i; + + /* check type */ + if (!strncmp(argv[idx_packet]->arg, "u", 1)) + type = OSPF6_MESSAGE_TYPE_UNKNOWN; + else if (!strncmp(argv[idx_packet]->arg, "h", 1)) + type = OSPF6_MESSAGE_TYPE_HELLO; + else if (!strncmp(argv[idx_packet]->arg, "d", 1)) + type = OSPF6_MESSAGE_TYPE_DBDESC; + else if (!strncmp(argv[idx_packet]->arg, "lsr", 3)) + type = OSPF6_MESSAGE_TYPE_LSREQ; + else if (!strncmp(argv[idx_packet]->arg, "lsu", 3)) + type = OSPF6_MESSAGE_TYPE_LSUPDATE; + else if (!strncmp(argv[idx_packet]->arg, "lsa", 3)) + type = OSPF6_MESSAGE_TYPE_LSACK; + else if (!strncmp(argv[idx_packet]->arg, "a", 1)) + type = OSPF6_MESSAGE_TYPE_ALL; + + if (argc == 4) + level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV; + else if (!strncmp(argv[idx_send_recv]->arg, "s", 1)) + level = OSPF6_DEBUG_MESSAGE_SEND; + else if (!strncmp(argv[idx_send_recv]->arg, "r", 1)) + level = OSPF6_DEBUG_MESSAGE_RECV; + + if (type == OSPF6_MESSAGE_TYPE_ALL) { + for (i = 0; i < 6; i++) + OSPF6_DEBUG_MESSAGE_ON(i, level); + } else + OSPF6_DEBUG_MESSAGE_ON(type, level); + + return CMD_SUCCESS; } DEFUN (no_debug_ospf6_message, @@ -2392,110 +2369,100 @@ DEFUN (no_debug_ospf6_message, "Debug only sending message\n" "Debug only receiving message\n") { - int idx_packet = 4; - int idx_send_recv = 5; - unsigned char level = 0; - int type = 0; - int i; - - /* check type */ - if (! strncmp (argv[idx_packet]->arg, "u", 1)) - type = OSPF6_MESSAGE_TYPE_UNKNOWN; - else if (! strncmp (argv[idx_packet]->arg, "h", 1)) - type = OSPF6_MESSAGE_TYPE_HELLO; - else if (! strncmp (argv[idx_packet]->arg, "d", 1)) - type = OSPF6_MESSAGE_TYPE_DBDESC; - else if (! strncmp (argv[idx_packet]->arg, "lsr", 3)) - type = OSPF6_MESSAGE_TYPE_LSREQ; - else if (! strncmp (argv[idx_packet]->arg, "lsu", 3)) - type = OSPF6_MESSAGE_TYPE_LSUPDATE; - else if (! strncmp (argv[idx_packet]->arg, "lsa", 3)) - type = OSPF6_MESSAGE_TYPE_LSACK; - else if (! strncmp (argv[idx_packet]->arg, "a", 1)) - type = OSPF6_MESSAGE_TYPE_ALL; - - if (argc == 5) - level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV; - else if (! strncmp (argv[idx_send_recv]->arg, "s", 1)) - level = OSPF6_DEBUG_MESSAGE_SEND; - else if (! strncmp (argv[idx_send_recv]->arg, "r", 1)) - level = OSPF6_DEBUG_MESSAGE_RECV; - - if (type == OSPF6_MESSAGE_TYPE_ALL) - { - for (i = 0; i < 6; i++) - OSPF6_DEBUG_MESSAGE_OFF (i, level); - } - else - OSPF6_DEBUG_MESSAGE_OFF (type, level); - - return CMD_SUCCESS; + int idx_packet = 4; + int idx_send_recv = 5; + unsigned char level = 0; + int type = 0; + int i; + + /* check type */ + if (!strncmp(argv[idx_packet]->arg, "u", 1)) + type = OSPF6_MESSAGE_TYPE_UNKNOWN; + else if (!strncmp(argv[idx_packet]->arg, "h", 1)) + type = OSPF6_MESSAGE_TYPE_HELLO; + else if (!strncmp(argv[idx_packet]->arg, "d", 1)) + type = OSPF6_MESSAGE_TYPE_DBDESC; + else if (!strncmp(argv[idx_packet]->arg, "lsr", 3)) + type = OSPF6_MESSAGE_TYPE_LSREQ; + else if (!strncmp(argv[idx_packet]->arg, "lsu", 3)) + type = OSPF6_MESSAGE_TYPE_LSUPDATE; + else if (!strncmp(argv[idx_packet]->arg, "lsa", 3)) + type = OSPF6_MESSAGE_TYPE_LSACK; + else if (!strncmp(argv[idx_packet]->arg, "a", 1)) + type = OSPF6_MESSAGE_TYPE_ALL; + + if (argc == 5) + level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV; + else if (!strncmp(argv[idx_send_recv]->arg, "s", 1)) + level = OSPF6_DEBUG_MESSAGE_SEND; + else if (!strncmp(argv[idx_send_recv]->arg, "r", 1)) + level = OSPF6_DEBUG_MESSAGE_RECV; + + if (type == OSPF6_MESSAGE_TYPE_ALL) { + for (i = 0; i < 6; i++) + OSPF6_DEBUG_MESSAGE_OFF(i, level); + } else + OSPF6_DEBUG_MESSAGE_OFF(type, level); + + return CMD_SUCCESS; } -int -config_write_ospf6_debug_message (struct vty *vty) +int config_write_ospf6_debug_message(struct vty *vty) { - const char *type_str[] = {"unknown", "hello", "dbdesc", - "lsreq", "lsupdate", "lsack"}; - unsigned char s = 0, r = 0; - int i; - - for (i = 0; i < 6; i++) - { - if (IS_OSPF6_DEBUG_MESSAGE (i, SEND)) - s |= 1 << i; - if (IS_OSPF6_DEBUG_MESSAGE (i, RECV)) - r |= 1 << i; - } - - if (s == 0x3f && r == 0x3f) - { - vty_out (vty, "debug ospf6 message all\n"); - return 0; - } - - if (s == 0x3f && r == 0) - { - vty_out (vty, "debug ospf6 message all send\n"); - return 0; - } - else if (s == 0 && r == 0x3f) - { - vty_out (vty, "debug ospf6 message all recv\n"); - return 0; - } - - /* Unknown message is logged by default */ - if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) && - ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - vty_out (vty, "no debug ospf6 message unknown\n"); - else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND)) - vty_out (vty, "no debug ospf6 message unknown send\n"); - else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - vty_out (vty, "no debug ospf6 message unknown recv\n"); - - for (i = 1; i < 6; i++) - { - if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) && - IS_OSPF6_DEBUG_MESSAGE (i, RECV)) - vty_out (vty, "debug ospf6 message %s\n", type_str[i]); - else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND)) - vty_out (vty, "debug ospf6 message %s send\n", type_str[i]); - else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV)) - vty_out (vty, "debug ospf6 message %s recv\n", type_str[i]); - } - - return 0; + const char *type_str[] = {"unknown", "hello", "dbdesc", + "lsreq", "lsupdate", "lsack"}; + unsigned char s = 0, r = 0; + int i; + + for (i = 0; i < 6; i++) { + if (IS_OSPF6_DEBUG_MESSAGE(i, SEND)) + s |= 1 << i; + if (IS_OSPF6_DEBUG_MESSAGE(i, RECV)) + r |= 1 << i; + } + + if (s == 0x3f && r == 0x3f) { + vty_out(vty, "debug ospf6 message all\n"); + return 0; + } + + if (s == 0x3f && r == 0) { + vty_out(vty, "debug ospf6 message all send\n"); + return 0; + } else if (s == 0 && r == 0x3f) { + vty_out(vty, "debug ospf6 message all recv\n"); + return 0; + } + + /* Unknown message is logged by default */ + if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) + && !IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + vty_out(vty, "no debug ospf6 message unknown\n"); + else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, SEND)) + vty_out(vty, "no debug ospf6 message unknown send\n"); + else if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) + vty_out(vty, "no debug ospf6 message unknown recv\n"); + + for (i = 1; i < 6; i++) { + if (IS_OSPF6_DEBUG_MESSAGE(i, SEND) + && IS_OSPF6_DEBUG_MESSAGE(i, RECV)) + vty_out(vty, "debug ospf6 message %s\n", type_str[i]); + else if (IS_OSPF6_DEBUG_MESSAGE(i, SEND)) + vty_out(vty, "debug ospf6 message %s send\n", + type_str[i]); + else if (IS_OSPF6_DEBUG_MESSAGE(i, RECV)) + vty_out(vty, "debug ospf6 message %s recv\n", + type_str[i]); + } + + return 0; } -void -install_element_ospf6_debug_message (void) +void install_element_ospf6_debug_message(void) { - install_element (ENABLE_NODE, &debug_ospf6_message_cmd); - install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd); - install_element (CONFIG_NODE, &debug_ospf6_message_cmd); - install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd); + install_element(ENABLE_NODE, &debug_ospf6_message_cmd); + install_element(ENABLE_NODE, &no_debug_ospf6_message_cmd); + install_element(CONFIG_NODE, &debug_ospf6_message_cmd); + install_element(CONFIG_NODE, &no_debug_ospf6_message_cmd); } - - diff --git a/ospf6d/ospf6_message.h b/ospf6d/ospf6_message.h index b0107dfff..d867bd025 100644 --- a/ospf6d/ospf6_message.h +++ b/ospf6d/ospf6_message.h @@ -27,12 +27,12 @@ extern unsigned char conf_debug_ospf6_message[]; #define OSPF6_DEBUG_MESSAGE_SEND 0x01 #define OSPF6_DEBUG_MESSAGE_RECV 0x02 -#define OSPF6_DEBUG_MESSAGE_ON(type, level) \ - (conf_debug_ospf6_message[type] |= (level)) -#define OSPF6_DEBUG_MESSAGE_OFF(type, level) \ - (conf_debug_ospf6_message[type] &= ~(level)) -#define IS_OSPF6_DEBUG_MESSAGE(t, e) \ - (conf_debug_ospf6_message[t] & OSPF6_DEBUG_MESSAGE_ ## e) +#define OSPF6_DEBUG_MESSAGE_ON(type, level) \ + (conf_debug_ospf6_message[type] |= (level)) +#define OSPF6_DEBUG_MESSAGE_OFF(type, level) \ + (conf_debug_ospf6_message[type] &= ~(level)) +#define IS_OSPF6_DEBUG_MESSAGE(t, e) \ + (conf_debug_ospf6_message[t] & OSPF6_DEBUG_MESSAGE_##e) /* Type */ #define OSPF6_MESSAGE_TYPE_UNKNOWN 0x0 @@ -45,45 +45,42 @@ extern unsigned char conf_debug_ospf6_message[]; /* OSPFv3 packet header */ #define OSPF6_HEADER_SIZE 16U -struct ospf6_header -{ - u_char version; - u_char type; - u_int16_t length; - u_int32_t router_id; - u_int32_t area_id; - u_int16_t checksum; - u_char instance_id; - u_char reserved; +struct ospf6_header { + u_char version; + u_char type; + u_int16_t length; + u_int32_t router_id; + u_int32_t area_id; + u_int16_t checksum; + u_char instance_id; + u_char reserved; }; #define OSPF6_MESSAGE_END(H) ((caddr_t) (H) + ntohs ((H)->length)) /* Hello */ #define OSPF6_HELLO_MIN_SIZE 20U -struct ospf6_hello -{ - ifindex_t interface_id; - u_char priority; - u_char options[3]; - u_int16_t hello_interval; - u_int16_t dead_interval; - u_int32_t drouter; - u_int32_t bdrouter; - /* Followed by Router-IDs */ +struct ospf6_hello { + ifindex_t interface_id; + u_char priority; + u_char options[3]; + u_int16_t hello_interval; + u_int16_t dead_interval; + u_int32_t drouter; + u_int32_t bdrouter; + /* Followed by Router-IDs */ }; /* Database Description */ #define OSPF6_DB_DESC_MIN_SIZE 12U -struct ospf6_dbdesc -{ - u_char reserved1; - u_char options[3]; - u_int16_t ifmtu; - u_char reserved2; - u_char bits; - u_int32_t seqnum; - /* Followed by LSA Headers */ +struct ospf6_dbdesc { + u_char reserved1; + u_char options[3]; + u_int16_t ifmtu; + u_char reserved2; + u_char bits; + u_int32_t seqnum; + /* Followed by LSA Headers */ }; #define OSPF6_DBDESC_MSBIT (0x01) /* master/slave bit */ @@ -94,20 +91,18 @@ struct ospf6_dbdesc #define OSPF6_LS_REQ_MIN_SIZE 0U /* It is just a sequence of entries below */ #define OSPF6_LSREQ_LSDESC_FIX_SIZE 12U -struct ospf6_lsreq_entry -{ - u_int16_t reserved; /* Must Be Zero */ - u_int16_t type; /* LS type */ - u_int32_t id; /* Link State ID */ - u_int32_t adv_router; /* Advertising Router */ +struct ospf6_lsreq_entry { + u_int16_t reserved; /* Must Be Zero */ + u_int16_t type; /* LS type */ + u_int32_t id; /* Link State ID */ + u_int32_t adv_router; /* Advertising Router */ }; /* Link State Update */ #define OSPF6_LS_UPD_MIN_SIZE 4U -struct ospf6_lsupdate -{ - u_int32_t lsa_number; - /* Followed by LSAs */ +struct ospf6_lsupdate { + u_int32_t lsa_number; + /* Followed by LSAs */ }; /* Link State Acknowledgement */ @@ -115,27 +110,26 @@ struct ospf6_lsupdate /* It is just a sequence of LSA Headers */ /* Function definition */ -extern void ospf6_hello_print (struct ospf6_header *); -extern void ospf6_dbdesc_print (struct ospf6_header *); -extern void ospf6_lsreq_print (struct ospf6_header *); -extern void ospf6_lsupdate_print (struct ospf6_header *); -extern void ospf6_lsack_print (struct ospf6_header *); - -extern int ospf6_iobuf_size (unsigned int size); -extern void ospf6_message_terminate (void); -extern int ospf6_receive (struct thread *thread); - -extern int ospf6_hello_send (struct thread *thread); -extern int ospf6_dbdesc_send (struct thread *thread); -extern int ospf6_dbdesc_send_newone (struct thread *thread); -extern int ospf6_lsreq_send (struct thread *thread); -extern int ospf6_lsupdate_send_interface (struct thread *thread); -extern int ospf6_lsupdate_send_neighbor (struct thread *thread); -extern int ospf6_lsack_send_interface (struct thread *thread); -extern int ospf6_lsack_send_neighbor (struct thread *thread); - -extern int config_write_ospf6_debug_message (struct vty *); -extern void install_element_ospf6_debug_message (void); +extern void ospf6_hello_print(struct ospf6_header *); +extern void ospf6_dbdesc_print(struct ospf6_header *); +extern void ospf6_lsreq_print(struct ospf6_header *); +extern void ospf6_lsupdate_print(struct ospf6_header *); +extern void ospf6_lsack_print(struct ospf6_header *); + +extern int ospf6_iobuf_size(unsigned int size); +extern void ospf6_message_terminate(void); +extern int ospf6_receive(struct thread *thread); + +extern int ospf6_hello_send(struct thread *thread); +extern int ospf6_dbdesc_send(struct thread *thread); +extern int ospf6_dbdesc_send_newone(struct thread *thread); +extern int ospf6_lsreq_send(struct thread *thread); +extern int ospf6_lsupdate_send_interface(struct thread *thread); +extern int ospf6_lsupdate_send_neighbor(struct thread *thread); +extern int ospf6_lsack_send_interface(struct thread *thread); +extern int ospf6_lsack_send_neighbor(struct thread *thread); + +extern int config_write_ospf6_debug_message(struct vty *); +extern void install_element_ospf6_debug_message(void); #endif /* OSPF6_MESSAGE_H */ - diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index d0a97eea4..a21da0748 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -46,751 +46,712 @@ #include "ospf6_zebra.h" DEFINE_HOOK(ospf6_neighbor_change, - (struct ospf6_neighbor *on, int state, int next_state), - (on, state, next_state)) + (struct ospf6_neighbor * on, int state, int next_state), + (on, state, next_state)) unsigned char conf_debug_ospf6_neighbor = 0; -const char *ospf6_neighbor_state_str[] = -{ "None", "Down", "Attempt", "Init", "Twoway", "ExStart", "ExChange", - "Loading", "Full", NULL }; +const char *ospf6_neighbor_state_str[] = { + "None", "Down", "Attempt", "Init", "Twoway", + "ExStart", "ExChange", "Loading", "Full", NULL}; -int -ospf6_neighbor_cmp (void *va, void *vb) +int ospf6_neighbor_cmp(void *va, void *vb) { - struct ospf6_neighbor *ona = (struct ospf6_neighbor *) va; - struct ospf6_neighbor *onb = (struct ospf6_neighbor *) vb; - return (ntohl (ona->router_id) < ntohl (onb->router_id) ? -1 : 1); + struct ospf6_neighbor *ona = (struct ospf6_neighbor *)va; + struct ospf6_neighbor *onb = (struct ospf6_neighbor *)vb; + return (ntohl(ona->router_id) < ntohl(onb->router_id) ? -1 : 1); } -struct ospf6_neighbor * -ospf6_neighbor_lookup (u_int32_t router_id, - struct ospf6_interface *oi) +struct ospf6_neighbor *ospf6_neighbor_lookup(u_int32_t router_id, + struct ospf6_interface *oi) { - struct listnode *n; - struct ospf6_neighbor *on; - - for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, n, on)) - if (on->router_id == router_id) - return on; - - return (struct ospf6_neighbor *) NULL; + struct listnode *n; + struct ospf6_neighbor *on; + + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, n, on)) + if (on->router_id == router_id) + return on; + + return (struct ospf6_neighbor *)NULL; } /* create ospf6_neighbor */ -struct ospf6_neighbor * -ospf6_neighbor_create (u_int32_t router_id, struct ospf6_interface *oi) +struct ospf6_neighbor *ospf6_neighbor_create(u_int32_t router_id, + struct ospf6_interface *oi) { - struct ospf6_neighbor *on; - char buf[16]; - - on = (struct ospf6_neighbor *) - XMALLOC (MTYPE_OSPF6_NEIGHBOR, sizeof (struct ospf6_neighbor)); - if (on == NULL) - { - zlog_warn ("neighbor: malloc failed"); - return NULL; - } - - memset (on, 0, sizeof (struct ospf6_neighbor)); - inet_ntop (AF_INET, &router_id, buf, sizeof (buf)); - snprintf (on->name, sizeof (on->name), "%s%%%s", - buf, oi->interface->name); - on->ospf6_if = oi; - on->state = OSPF6_NEIGHBOR_DOWN; - on->state_change = 0; - monotime(&on->last_changed); - on->router_id = router_id; - - on->summary_list = ospf6_lsdb_create (on); - on->request_list = ospf6_lsdb_create (on); - on->retrans_list = ospf6_lsdb_create (on); - - on->dbdesc_list = ospf6_lsdb_create (on); - on->lsupdate_list = ospf6_lsdb_create (on); - on->lsack_list = ospf6_lsdb_create (on); - - listnode_add_sort (oi->neighbor_list, on); - - ospf6_bfd_info_nbr_create(oi, on); - return on; + struct ospf6_neighbor *on; + char buf[16]; + + on = (struct ospf6_neighbor *)XMALLOC(MTYPE_OSPF6_NEIGHBOR, + sizeof(struct ospf6_neighbor)); + if (on == NULL) { + zlog_warn("neighbor: malloc failed"); + return NULL; + } + + memset(on, 0, sizeof(struct ospf6_neighbor)); + inet_ntop(AF_INET, &router_id, buf, sizeof(buf)); + snprintf(on->name, sizeof(on->name), "%s%%%s", buf, + oi->interface->name); + on->ospf6_if = oi; + on->state = OSPF6_NEIGHBOR_DOWN; + on->state_change = 0; + monotime(&on->last_changed); + on->router_id = router_id; + + on->summary_list = ospf6_lsdb_create(on); + on->request_list = ospf6_lsdb_create(on); + on->retrans_list = ospf6_lsdb_create(on); + + on->dbdesc_list = ospf6_lsdb_create(on); + on->lsupdate_list = ospf6_lsdb_create(on); + on->lsack_list = ospf6_lsdb_create(on); + + listnode_add_sort(oi->neighbor_list, on); + + ospf6_bfd_info_nbr_create(oi, on); + return on; } -void -ospf6_neighbor_delete (struct ospf6_neighbor *on) +void ospf6_neighbor_delete(struct ospf6_neighbor *on) { - struct ospf6_lsa *lsa; + struct ospf6_lsa *lsa; - ospf6_lsdb_remove_all (on->summary_list); - ospf6_lsdb_remove_all (on->request_list); - for (ALL_LSDB(on->retrans_list, lsa)) - { - ospf6_decrement_retrans_count (lsa); - ospf6_lsdb_remove (lsa, on->retrans_list); - } + ospf6_lsdb_remove_all(on->summary_list); + ospf6_lsdb_remove_all(on->request_list); + for (ALL_LSDB(on->retrans_list, lsa)) { + ospf6_decrement_retrans_count(lsa); + ospf6_lsdb_remove(lsa, on->retrans_list); + } - ospf6_lsdb_remove_all (on->dbdesc_list); - ospf6_lsdb_remove_all (on->lsupdate_list); - ospf6_lsdb_remove_all (on->lsack_list); + ospf6_lsdb_remove_all(on->dbdesc_list); + ospf6_lsdb_remove_all(on->lsupdate_list); + ospf6_lsdb_remove_all(on->lsack_list); - ospf6_lsdb_delete (on->summary_list); - ospf6_lsdb_delete (on->request_list); - ospf6_lsdb_delete (on->retrans_list); + ospf6_lsdb_delete(on->summary_list); + ospf6_lsdb_delete(on->request_list); + ospf6_lsdb_delete(on->retrans_list); - ospf6_lsdb_delete (on->dbdesc_list); - ospf6_lsdb_delete (on->lsupdate_list); - ospf6_lsdb_delete (on->lsack_list); + ospf6_lsdb_delete(on->dbdesc_list); + ospf6_lsdb_delete(on->lsupdate_list); + ospf6_lsdb_delete(on->lsack_list); - THREAD_OFF (on->inactivity_timer); + THREAD_OFF(on->inactivity_timer); - THREAD_OFF (on->thread_send_dbdesc); - THREAD_OFF (on->thread_send_lsreq); - THREAD_OFF (on->thread_send_lsupdate); - THREAD_OFF (on->thread_send_lsack); + THREAD_OFF(on->thread_send_dbdesc); + THREAD_OFF(on->thread_send_lsreq); + THREAD_OFF(on->thread_send_lsupdate); + THREAD_OFF(on->thread_send_lsack); - ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_DEREGISTER); - XFREE (MTYPE_OSPF6_NEIGHBOR, on); + ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_DEREGISTER); + XFREE(MTYPE_OSPF6_NEIGHBOR, on); } -static void -ospf6_neighbor_state_change (u_char next_state, struct ospf6_neighbor *on, int event) +static void ospf6_neighbor_state_change(u_char next_state, + struct ospf6_neighbor *on, int event) { - u_char prev_state; - - prev_state = on->state; - on->state = next_state; - - if (prev_state == next_state) - return; - - on->state_change++; - monotime(&on->last_changed); - - /* log */ - if (IS_OSPF6_DEBUG_NEIGHBOR (STATE)) - { - zlog_debug ("Neighbor state change %s: [%s]->[%s] (%s)", on->name, - ospf6_neighbor_state_str[prev_state], - ospf6_neighbor_state_str[next_state], - ospf6_neighbor_event_string(event)); - } - - /* Optionally notify about adjacency changes */ - if (CHECK_FLAG(on->ospf6_if->area->ospf6->config_flags, - OSPF6_LOG_ADJACENCY_CHANGES) && - (CHECK_FLAG(on->ospf6_if->area->ospf6->config_flags, - OSPF6_LOG_ADJACENCY_DETAIL) || - (next_state == OSPF6_NEIGHBOR_FULL) || (next_state < prev_state))) - zlog_notice("AdjChg: Nbr %s: %s -> %s (%s)", on->name, - ospf6_neighbor_state_str[prev_state], - ospf6_neighbor_state_str[next_state], - ospf6_neighbor_event_string(event)); - - if (prev_state == OSPF6_NEIGHBOR_FULL || next_state == OSPF6_NEIGHBOR_FULL) - { - OSPF6_ROUTER_LSA_SCHEDULE (on->ospf6_if->area); - if (on->ospf6_if->state == OSPF6_INTERFACE_DR) - { - OSPF6_NETWORK_LSA_SCHEDULE (on->ospf6_if); - OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (on->ospf6_if); - } - OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (on->ospf6_if->area); - } - - if ((prev_state == OSPF6_NEIGHBOR_EXCHANGE || - prev_state == OSPF6_NEIGHBOR_LOADING) && - (next_state != OSPF6_NEIGHBOR_EXCHANGE && - next_state != OSPF6_NEIGHBOR_LOADING)) - ospf6_maxage_remove (on->ospf6_if->area->ospf6); - - hook_call(ospf6_neighbor_change, on, next_state, prev_state); - ospf6_bfd_trigger_event(on, prev_state, next_state); + u_char prev_state; + + prev_state = on->state; + on->state = next_state; + + if (prev_state == next_state) + return; + + on->state_change++; + monotime(&on->last_changed); + + /* log */ + if (IS_OSPF6_DEBUG_NEIGHBOR(STATE)) { + zlog_debug("Neighbor state change %s: [%s]->[%s] (%s)", + on->name, ospf6_neighbor_state_str[prev_state], + ospf6_neighbor_state_str[next_state], + ospf6_neighbor_event_string(event)); + } + + /* Optionally notify about adjacency changes */ + if (CHECK_FLAG(on->ospf6_if->area->ospf6->config_flags, + OSPF6_LOG_ADJACENCY_CHANGES) + && (CHECK_FLAG(on->ospf6_if->area->ospf6->config_flags, + OSPF6_LOG_ADJACENCY_DETAIL) + || (next_state == OSPF6_NEIGHBOR_FULL) + || (next_state < prev_state))) + zlog_notice("AdjChg: Nbr %s: %s -> %s (%s)", on->name, + ospf6_neighbor_state_str[prev_state], + ospf6_neighbor_state_str[next_state], + ospf6_neighbor_event_string(event)); + + if (prev_state == OSPF6_NEIGHBOR_FULL + || next_state == OSPF6_NEIGHBOR_FULL) { + OSPF6_ROUTER_LSA_SCHEDULE(on->ospf6_if->area); + if (on->ospf6_if->state == OSPF6_INTERFACE_DR) { + OSPF6_NETWORK_LSA_SCHEDULE(on->ospf6_if); + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(on->ospf6_if); + } + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(on->ospf6_if->area); + } + + if ((prev_state == OSPF6_NEIGHBOR_EXCHANGE + || prev_state == OSPF6_NEIGHBOR_LOADING) + && (next_state != OSPF6_NEIGHBOR_EXCHANGE + && next_state != OSPF6_NEIGHBOR_LOADING)) + ospf6_maxage_remove(on->ospf6_if->area->ospf6); + + hook_call(ospf6_neighbor_change, on, next_state, prev_state); + ospf6_bfd_trigger_event(on, prev_state, next_state); } /* RFC2328 section 10.4 */ -static int -need_adjacency (struct ospf6_neighbor *on) +static int need_adjacency(struct ospf6_neighbor *on) { - if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT || - on->ospf6_if->state == OSPF6_INTERFACE_DR || - on->ospf6_if->state == OSPF6_INTERFACE_BDR) - return 1; + if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT + || on->ospf6_if->state == OSPF6_INTERFACE_DR + || on->ospf6_if->state == OSPF6_INTERFACE_BDR) + return 1; - if (on->ospf6_if->drouter == on->router_id || - on->ospf6_if->bdrouter == on->router_id) - return 1; + if (on->ospf6_if->drouter == on->router_id + || on->ospf6_if->bdrouter == on->router_id) + return 1; - return 0; + return 0; } -int -hello_received (struct thread *thread) +int hello_received(struct thread *thread) { - struct ospf6_neighbor *on; + struct ospf6_neighbor *on; - on = (struct ospf6_neighbor *) THREAD_ARG (thread); - assert (on); + on = (struct ospf6_neighbor *)THREAD_ARG(thread); + assert(on); - if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) - zlog_debug ("Neighbor Event %s: *HelloReceived*", on->name); + if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) + zlog_debug("Neighbor Event %s: *HelloReceived*", on->name); - /* reset Inactivity Timer */ - THREAD_OFF (on->inactivity_timer); - on->inactivity_timer = NULL; - thread_add_timer(master, inactivity_timer, on, on->ospf6_if->dead_interval, - &on->inactivity_timer); + /* reset Inactivity Timer */ + THREAD_OFF(on->inactivity_timer); + on->inactivity_timer = NULL; + thread_add_timer(master, inactivity_timer, on, + on->ospf6_if->dead_interval, &on->inactivity_timer); - if (on->state <= OSPF6_NEIGHBOR_DOWN) - ospf6_neighbor_state_change (OSPF6_NEIGHBOR_INIT, on, - OSPF6_NEIGHBOR_EVENT_HELLO_RCVD); + if (on->state <= OSPF6_NEIGHBOR_DOWN) + ospf6_neighbor_state_change(OSPF6_NEIGHBOR_INIT, on, + OSPF6_NEIGHBOR_EVENT_HELLO_RCVD); - return 0; + return 0; } -int -twoway_received (struct thread *thread) +int twoway_received(struct thread *thread) { - struct ospf6_neighbor *on; + struct ospf6_neighbor *on; - on = (struct ospf6_neighbor *) THREAD_ARG (thread); - assert (on); + on = (struct ospf6_neighbor *)THREAD_ARG(thread); + assert(on); - if (on->state > OSPF6_NEIGHBOR_INIT) - return 0; + if (on->state > OSPF6_NEIGHBOR_INIT) + return 0; - if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) - zlog_debug ("Neighbor Event %s: *2Way-Received*", on->name); + if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) + zlog_debug("Neighbor Event %s: *2Way-Received*", on->name); - thread_add_event(master, neighbor_change, on->ospf6_if, 0, NULL); + thread_add_event(master, neighbor_change, on->ospf6_if, 0, NULL); - if (! need_adjacency (on)) - { - ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on, - OSPF6_NEIGHBOR_EVENT_TWOWAY_RCVD); - return 0; - } + if (!need_adjacency(on)) { + ospf6_neighbor_state_change(OSPF6_NEIGHBOR_TWOWAY, on, + OSPF6_NEIGHBOR_EVENT_TWOWAY_RCVD); + return 0; + } - ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on, - OSPF6_NEIGHBOR_EVENT_TWOWAY_RCVD); - SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT); - SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT); - SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT); + ospf6_neighbor_state_change(OSPF6_NEIGHBOR_EXSTART, on, + OSPF6_NEIGHBOR_EVENT_TWOWAY_RCVD); + SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT); + SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT); + SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT); - THREAD_OFF (on->thread_send_dbdesc); - on->thread_send_dbdesc = NULL; - thread_add_event(master, ospf6_dbdesc_send, on, 0, &on->thread_send_dbdesc); + THREAD_OFF(on->thread_send_dbdesc); + on->thread_send_dbdesc = NULL; + thread_add_event(master, ospf6_dbdesc_send, on, 0, + &on->thread_send_dbdesc); - return 0; + return 0; } -int -negotiation_done (struct thread *thread) +int negotiation_done(struct thread *thread) { - struct ospf6_neighbor *on; - struct ospf6_lsa *lsa; - - on = (struct ospf6_neighbor *) THREAD_ARG (thread); - assert (on); - - if (on->state != OSPF6_NEIGHBOR_EXSTART) - return 0; - - if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) - zlog_debug ("Neighbor Event %s: *NegotiationDone*", on->name); - - /* clear ls-list */ - ospf6_lsdb_remove_all (on->summary_list); - ospf6_lsdb_remove_all (on->request_list); - for (ALL_LSDB(on->retrans_list, lsa)) - { - ospf6_decrement_retrans_count (lsa); - ospf6_lsdb_remove (lsa, on->retrans_list); - } - - /* Interface scoped LSAs */ - for (ALL_LSDB(on->ospf6_if->lsdb, lsa)) - { - if (OSPF6_LSA_IS_MAXAGE (lsa)) - { - ospf6_increment_retrans_count (lsa); - ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); - } - else - ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->summary_list); - } - - /* Area scoped LSAs */ - for (ALL_LSDB(on->ospf6_if->area->lsdb, lsa)) - { - if (OSPF6_LSA_IS_MAXAGE (lsa)) - { - ospf6_increment_retrans_count (lsa); - ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); - } - else - ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->summary_list); - } - - /* AS scoped LSAs */ - for (ALL_LSDB(on->ospf6_if->area->ospf6->lsdb, lsa)) - { - if (OSPF6_LSA_IS_MAXAGE (lsa)) - { - ospf6_increment_retrans_count (lsa); - ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); - } - else - ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->summary_list); - } - - UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT); - ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXCHANGE, on, - OSPF6_NEIGHBOR_EVENT_NEGOTIATION_DONE); - - return 0; + struct ospf6_neighbor *on; + struct ospf6_lsa *lsa; + + on = (struct ospf6_neighbor *)THREAD_ARG(thread); + assert(on); + + if (on->state != OSPF6_NEIGHBOR_EXSTART) + return 0; + + if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) + zlog_debug("Neighbor Event %s: *NegotiationDone*", on->name); + + /* clear ls-list */ + ospf6_lsdb_remove_all(on->summary_list); + ospf6_lsdb_remove_all(on->request_list); + for (ALL_LSDB(on->retrans_list, lsa)) { + ospf6_decrement_retrans_count(lsa); + ospf6_lsdb_remove(lsa, on->retrans_list); + } + + /* Interface scoped LSAs */ + for (ALL_LSDB(on->ospf6_if->lsdb, lsa)) { + if (OSPF6_LSA_IS_MAXAGE(lsa)) { + ospf6_increment_retrans_count(lsa); + ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list); + } else + ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->summary_list); + } + + /* Area scoped LSAs */ + for (ALL_LSDB(on->ospf6_if->area->lsdb, lsa)) { + if (OSPF6_LSA_IS_MAXAGE(lsa)) { + ospf6_increment_retrans_count(lsa); + ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list); + } else + ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->summary_list); + } + + /* AS scoped LSAs */ + for (ALL_LSDB(on->ospf6_if->area->ospf6->lsdb, lsa)) { + if (OSPF6_LSA_IS_MAXAGE(lsa)) { + ospf6_increment_retrans_count(lsa); + ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list); + } else + ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->summary_list); + } + + UNSET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT); + ospf6_neighbor_state_change(OSPF6_NEIGHBOR_EXCHANGE, on, + OSPF6_NEIGHBOR_EVENT_NEGOTIATION_DONE); + + return 0; } -int -exchange_done (struct thread *thread) +int exchange_done(struct thread *thread) { - struct ospf6_neighbor *on; + struct ospf6_neighbor *on; - on = (struct ospf6_neighbor *) THREAD_ARG (thread); - assert (on); + on = (struct ospf6_neighbor *)THREAD_ARG(thread); + assert(on); - if (on->state != OSPF6_NEIGHBOR_EXCHANGE) - return 0; + if (on->state != OSPF6_NEIGHBOR_EXCHANGE) + return 0; - if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) - zlog_debug ("Neighbor Event %s: *ExchangeDone*", on->name); + if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) + zlog_debug("Neighbor Event %s: *ExchangeDone*", on->name); - THREAD_OFF (on->thread_send_dbdesc); - ospf6_lsdb_remove_all (on->dbdesc_list); + THREAD_OFF(on->thread_send_dbdesc); + ospf6_lsdb_remove_all(on->dbdesc_list); -/* XXX - thread_add_timer (master, ospf6_neighbor_last_dbdesc_release, on, - on->ospf6_if->dead_interval); -*/ + /* XXX + thread_add_timer (master, ospf6_neighbor_last_dbdesc_release, on, + on->ospf6_if->dead_interval); + */ - if (on->request_list->count == 0) - ospf6_neighbor_state_change (OSPF6_NEIGHBOR_FULL, on, - OSPF6_NEIGHBOR_EVENT_EXCHANGE_DONE); - else - { - ospf6_neighbor_state_change (OSPF6_NEIGHBOR_LOADING, on, - OSPF6_NEIGHBOR_EVENT_EXCHANGE_DONE); + if (on->request_list->count == 0) + ospf6_neighbor_state_change(OSPF6_NEIGHBOR_FULL, on, + OSPF6_NEIGHBOR_EVENT_EXCHANGE_DONE); + else { + ospf6_neighbor_state_change(OSPF6_NEIGHBOR_LOADING, on, + OSPF6_NEIGHBOR_EVENT_EXCHANGE_DONE); - thread_add_event(master, ospf6_lsreq_send, on, 0, - &on->thread_send_lsreq); - } + thread_add_event(master, ospf6_lsreq_send, on, 0, + &on->thread_send_lsreq); + } - return 0; + return 0; } /* Check loading state. */ -void -ospf6_check_nbr_loading (struct ospf6_neighbor *on) +void ospf6_check_nbr_loading(struct ospf6_neighbor *on) { - /* RFC2328 Section 10.9: When the neighbor responds to these requests - with the proper Link State Update packet(s), the Link state request - list is truncated and a new Link State Request packet is sent. - */ - if ((on->state == OSPF6_NEIGHBOR_LOADING) || - (on->state == OSPF6_NEIGHBOR_EXCHANGE)) - { - if (on->request_list->count == 0) - thread_add_event(master, loading_done, on, 0, NULL); - else if (on->last_ls_req == NULL) - { - if (on->thread_send_lsreq != NULL) - THREAD_OFF (on->thread_send_lsreq); - on->thread_send_lsreq = NULL; - thread_add_event(master, ospf6_lsreq_send, on, 0, - &on->thread_send_lsreq); + /* RFC2328 Section 10.9: When the neighbor responds to these requests + with the proper Link State Update packet(s), the Link state request + list is truncated and a new Link State Request packet is sent. + */ + if ((on->state == OSPF6_NEIGHBOR_LOADING) + || (on->state == OSPF6_NEIGHBOR_EXCHANGE)) { + if (on->request_list->count == 0) + thread_add_event(master, loading_done, on, 0, NULL); + else if (on->last_ls_req == NULL) { + if (on->thread_send_lsreq != NULL) + THREAD_OFF(on->thread_send_lsreq); + on->thread_send_lsreq = NULL; + thread_add_event(master, ospf6_lsreq_send, on, 0, + &on->thread_send_lsreq); + } } - } } -int -loading_done (struct thread *thread) +int loading_done(struct thread *thread) { - struct ospf6_neighbor *on; + struct ospf6_neighbor *on; - on = (struct ospf6_neighbor *) THREAD_ARG (thread); - assert (on); + on = (struct ospf6_neighbor *)THREAD_ARG(thread); + assert(on); - if (on->state != OSPF6_NEIGHBOR_LOADING) - return 0; + if (on->state != OSPF6_NEIGHBOR_LOADING) + return 0; - if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) - zlog_debug ("Neighbor Event %s: *LoadingDone*", on->name); + if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) + zlog_debug("Neighbor Event %s: *LoadingDone*", on->name); - assert (on->request_list->count == 0); + assert(on->request_list->count == 0); - ospf6_neighbor_state_change (OSPF6_NEIGHBOR_FULL, on, - OSPF6_NEIGHBOR_EVENT_LOADING_DONE); + ospf6_neighbor_state_change(OSPF6_NEIGHBOR_FULL, on, + OSPF6_NEIGHBOR_EVENT_LOADING_DONE); - return 0; + return 0; } -int -adj_ok (struct thread *thread) +int adj_ok(struct thread *thread) { - struct ospf6_neighbor *on; - struct ospf6_lsa *lsa; - - on = (struct ospf6_neighbor *) THREAD_ARG (thread); - assert (on); - - if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) - zlog_debug ("Neighbor Event %s: *AdjOK?*", on->name); - - if (on->state == OSPF6_NEIGHBOR_TWOWAY && need_adjacency (on)) - { - ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on, - OSPF6_NEIGHBOR_EVENT_ADJ_OK); - SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT); - SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT); - SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT); - - THREAD_OFF (on->thread_send_dbdesc); - on->thread_send_dbdesc = NULL; - thread_add_event(master, ospf6_dbdesc_send, on, 0, - &on->thread_send_dbdesc); - - } - else if (on->state >= OSPF6_NEIGHBOR_EXSTART && - ! need_adjacency (on)) - { - ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on, - OSPF6_NEIGHBOR_EVENT_ADJ_OK); - ospf6_lsdb_remove_all (on->summary_list); - ospf6_lsdb_remove_all (on->request_list); - for (ALL_LSDB(on->retrans_list, lsa)) - { - ospf6_decrement_retrans_count (lsa); - ospf6_lsdb_remove (lsa, on->retrans_list); - } - } - - return 0; + struct ospf6_neighbor *on; + struct ospf6_lsa *lsa; + + on = (struct ospf6_neighbor *)THREAD_ARG(thread); + assert(on); + + if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) + zlog_debug("Neighbor Event %s: *AdjOK?*", on->name); + + if (on->state == OSPF6_NEIGHBOR_TWOWAY && need_adjacency(on)) { + ospf6_neighbor_state_change(OSPF6_NEIGHBOR_EXSTART, on, + OSPF6_NEIGHBOR_EVENT_ADJ_OK); + SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT); + SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT); + SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT); + + THREAD_OFF(on->thread_send_dbdesc); + on->thread_send_dbdesc = NULL; + thread_add_event(master, ospf6_dbdesc_send, on, 0, + &on->thread_send_dbdesc); + + } else if (on->state >= OSPF6_NEIGHBOR_EXSTART && !need_adjacency(on)) { + ospf6_neighbor_state_change(OSPF6_NEIGHBOR_TWOWAY, on, + OSPF6_NEIGHBOR_EVENT_ADJ_OK); + ospf6_lsdb_remove_all(on->summary_list); + ospf6_lsdb_remove_all(on->request_list); + for (ALL_LSDB(on->retrans_list, lsa)) { + ospf6_decrement_retrans_count(lsa); + ospf6_lsdb_remove(lsa, on->retrans_list); + } + } + + return 0; } -int -seqnumber_mismatch (struct thread *thread) +int seqnumber_mismatch(struct thread *thread) { - struct ospf6_neighbor *on; - struct ospf6_lsa *lsa; + struct ospf6_neighbor *on; + struct ospf6_lsa *lsa; - on = (struct ospf6_neighbor *) THREAD_ARG (thread); - assert (on); + on = (struct ospf6_neighbor *)THREAD_ARG(thread); + assert(on); - if (on->state < OSPF6_NEIGHBOR_EXCHANGE) - return 0; + if (on->state < OSPF6_NEIGHBOR_EXCHANGE) + return 0; - if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) - zlog_debug ("Neighbor Event %s: *SeqNumberMismatch*", on->name); + if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) + zlog_debug("Neighbor Event %s: *SeqNumberMismatch*", on->name); - ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on, - OSPF6_NEIGHBOR_EVENT_SEQNUMBER_MISMATCH); - SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT); - SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT); - SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT); + ospf6_neighbor_state_change(OSPF6_NEIGHBOR_EXSTART, on, + OSPF6_NEIGHBOR_EVENT_SEQNUMBER_MISMATCH); + SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT); + SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT); + SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT); - ospf6_lsdb_remove_all (on->summary_list); - ospf6_lsdb_remove_all (on->request_list); - for (ALL_LSDB(on->retrans_list, lsa)) - { - ospf6_decrement_retrans_count (lsa); - ospf6_lsdb_remove (lsa, on->retrans_list); - } + ospf6_lsdb_remove_all(on->summary_list); + ospf6_lsdb_remove_all(on->request_list); + for (ALL_LSDB(on->retrans_list, lsa)) { + ospf6_decrement_retrans_count(lsa); + ospf6_lsdb_remove(lsa, on->retrans_list); + } - THREAD_OFF (on->thread_send_dbdesc); - on->dbdesc_seqnum++; /* Incr seqnum as per RFC2328, sec 10.3 */ + THREAD_OFF(on->thread_send_dbdesc); + on->dbdesc_seqnum++; /* Incr seqnum as per RFC2328, sec 10.3 */ - on->thread_send_dbdesc = NULL; - thread_add_event(master, ospf6_dbdesc_send, on, 0, &on->thread_send_dbdesc); + on->thread_send_dbdesc = NULL; + thread_add_event(master, ospf6_dbdesc_send, on, 0, + &on->thread_send_dbdesc); - return 0; + return 0; } -int -bad_lsreq (struct thread *thread) +int bad_lsreq(struct thread *thread) { - struct ospf6_neighbor *on; - struct ospf6_lsa *lsa; + struct ospf6_neighbor *on; + struct ospf6_lsa *lsa; - on = (struct ospf6_neighbor *) THREAD_ARG (thread); - assert (on); + on = (struct ospf6_neighbor *)THREAD_ARG(thread); + assert(on); - if (on->state < OSPF6_NEIGHBOR_EXCHANGE) - return 0; + if (on->state < OSPF6_NEIGHBOR_EXCHANGE) + return 0; - if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) - zlog_debug ("Neighbor Event %s: *BadLSReq*", on->name); + if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) + zlog_debug("Neighbor Event %s: *BadLSReq*", on->name); - ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on, - OSPF6_NEIGHBOR_EVENT_BAD_LSREQ); - SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT); - SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT); - SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT); + ospf6_neighbor_state_change(OSPF6_NEIGHBOR_EXSTART, on, + OSPF6_NEIGHBOR_EVENT_BAD_LSREQ); + SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT); + SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT); + SET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT); - ospf6_lsdb_remove_all (on->summary_list); - ospf6_lsdb_remove_all (on->request_list); - for (ALL_LSDB(on->retrans_list, lsa)) - { - ospf6_decrement_retrans_count (lsa); - ospf6_lsdb_remove (lsa, on->retrans_list); - } + ospf6_lsdb_remove_all(on->summary_list); + ospf6_lsdb_remove_all(on->request_list); + for (ALL_LSDB(on->retrans_list, lsa)) { + ospf6_decrement_retrans_count(lsa); + ospf6_lsdb_remove(lsa, on->retrans_list); + } - THREAD_OFF (on->thread_send_dbdesc); - on->dbdesc_seqnum++; /* Incr seqnum as per RFC2328, sec 10.3 */ + THREAD_OFF(on->thread_send_dbdesc); + on->dbdesc_seqnum++; /* Incr seqnum as per RFC2328, sec 10.3 */ - on->thread_send_dbdesc = NULL; - thread_add_event(master, ospf6_dbdesc_send, on, 0, &on->thread_send_dbdesc); + on->thread_send_dbdesc = NULL; + thread_add_event(master, ospf6_dbdesc_send, on, 0, + &on->thread_send_dbdesc); - return 0; + return 0; } -int -oneway_received (struct thread *thread) +int oneway_received(struct thread *thread) { - struct ospf6_neighbor *on; - struct ospf6_lsa *lsa; + struct ospf6_neighbor *on; + struct ospf6_lsa *lsa; - on = (struct ospf6_neighbor *) THREAD_ARG (thread); - assert (on); + on = (struct ospf6_neighbor *)THREAD_ARG(thread); + assert(on); - if (on->state < OSPF6_NEIGHBOR_TWOWAY) - return 0; + if (on->state < OSPF6_NEIGHBOR_TWOWAY) + return 0; - if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) - zlog_debug ("Neighbor Event %s: *1Way-Received*", on->name); + if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) + zlog_debug("Neighbor Event %s: *1Way-Received*", on->name); - ospf6_neighbor_state_change (OSPF6_NEIGHBOR_INIT, on, - OSPF6_NEIGHBOR_EVENT_ONEWAY_RCVD); - thread_add_event(master, neighbor_change, on->ospf6_if, 0, NULL); + ospf6_neighbor_state_change(OSPF6_NEIGHBOR_INIT, on, + OSPF6_NEIGHBOR_EVENT_ONEWAY_RCVD); + thread_add_event(master, neighbor_change, on->ospf6_if, 0, NULL); - ospf6_lsdb_remove_all (on->summary_list); - ospf6_lsdb_remove_all (on->request_list); - for (ALL_LSDB(on->retrans_list, lsa)) - { - ospf6_decrement_retrans_count (lsa); - ospf6_lsdb_remove (lsa, on->retrans_list); - } + ospf6_lsdb_remove_all(on->summary_list); + ospf6_lsdb_remove_all(on->request_list); + for (ALL_LSDB(on->retrans_list, lsa)) { + ospf6_decrement_retrans_count(lsa); + ospf6_lsdb_remove(lsa, on->retrans_list); + } - THREAD_OFF (on->thread_send_dbdesc); - THREAD_OFF (on->thread_send_lsreq); - THREAD_OFF (on->thread_send_lsupdate); - THREAD_OFF (on->thread_send_lsack); + THREAD_OFF(on->thread_send_dbdesc); + THREAD_OFF(on->thread_send_lsreq); + THREAD_OFF(on->thread_send_lsupdate); + THREAD_OFF(on->thread_send_lsack); - return 0; + return 0; } -int -inactivity_timer (struct thread *thread) +int inactivity_timer(struct thread *thread) { - struct ospf6_neighbor *on; + struct ospf6_neighbor *on; - on = (struct ospf6_neighbor *) THREAD_ARG (thread); - assert (on); + on = (struct ospf6_neighbor *)THREAD_ARG(thread); + assert(on); - if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) - zlog_debug ("Neighbor Event %s: *InactivityTimer*", on->name); + if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) + zlog_debug("Neighbor Event %s: *InactivityTimer*", on->name); - on->inactivity_timer = NULL; - on->drouter = on->prev_drouter = 0; - on->bdrouter = on->prev_bdrouter = 0; + on->inactivity_timer = NULL; + on->drouter = on->prev_drouter = 0; + on->bdrouter = on->prev_bdrouter = 0; - ospf6_neighbor_state_change (OSPF6_NEIGHBOR_DOWN, on, - OSPF6_NEIGHBOR_EVENT_INACTIVITY_TIMER); - thread_add_event(master, neighbor_change, on->ospf6_if, 0, NULL); + ospf6_neighbor_state_change(OSPF6_NEIGHBOR_DOWN, on, + OSPF6_NEIGHBOR_EVENT_INACTIVITY_TIMER); + thread_add_event(master, neighbor_change, on->ospf6_if, 0, NULL); - listnode_delete (on->ospf6_if->neighbor_list, on); - ospf6_neighbor_delete (on); + listnode_delete(on->ospf6_if->neighbor_list, on); + ospf6_neighbor_delete(on); - return 0; + return 0; } - /* vty functions */ /* show neighbor structure */ -static void -ospf6_neighbor_show (struct vty *vty, struct ospf6_neighbor *on) +static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on) { - char router_id[16]; - char duration[16]; - struct timeval res; - char nstate[16]; - char deadtime[16]; - long h, m, s; - - /* Router-ID (Name) */ - inet_ntop (AF_INET, &on->router_id, router_id, sizeof (router_id)); + char router_id[16]; + char duration[16]; + struct timeval res; + char nstate[16]; + char deadtime[16]; + long h, m, s; + + /* Router-ID (Name) */ + inet_ntop(AF_INET, &on->router_id, router_id, sizeof(router_id)); #ifdef HAVE_GETNAMEINFO - { - } + { + } #endif /*HAVE_GETNAMEINFO*/ - /* Dead time */ - h = m = s = 0; - if (on->inactivity_timer) - { - s = monotime_until(&on->inactivity_timer->u.sands, NULL) / 1000000LL; - h = s / 3600; - s -= h * 3600; - m = s / 60; - s -= m * 60; - } - snprintf (deadtime, sizeof (deadtime), "%02ld:%02ld:%02ld", h, m, s); - - /* Neighbor State */ - if (if_is_pointopoint (on->ospf6_if->interface)) - snprintf (nstate, sizeof (nstate), "PointToPoint"); - else - { - if (on->router_id == on->drouter) - snprintf (nstate, sizeof (nstate), "DR"); - else if (on->router_id == on->bdrouter) - snprintf (nstate, sizeof (nstate), "BDR"); - else - snprintf (nstate, sizeof (nstate), "DROther"); - } - - /* Duration */ - monotime_since(&on->last_changed, &res); - timerstring (&res, duration, sizeof (duration)); - - /* - vty_out (vty, "%-15s %3d %11s %6s/%-12s %11s %s[%s]\n", - "Neighbor ID", "Pri", "DeadTime", "State", "", "Duration", - "I/F", "State"); - */ - - vty_out (vty, "%-15s %3d %11s %8s/%-12s %11s %s[%s]\n", - router_id, on->priority, deadtime, - ospf6_neighbor_state_str[on->state], nstate, duration, - on->ospf6_if->interface->name, - ospf6_interface_state_str[on->ospf6_if->state]); + /* Dead time */ + h = m = s = 0; + if (on->inactivity_timer) { + s = monotime_until(&on->inactivity_timer->u.sands, NULL) + / 1000000LL; + h = s / 3600; + s -= h * 3600; + m = s / 60; + s -= m * 60; + } + snprintf(deadtime, sizeof(deadtime), "%02ld:%02ld:%02ld", h, m, s); + + /* Neighbor State */ + if (if_is_pointopoint(on->ospf6_if->interface)) + snprintf(nstate, sizeof(nstate), "PointToPoint"); + else { + if (on->router_id == on->drouter) + snprintf(nstate, sizeof(nstate), "DR"); + else if (on->router_id == on->bdrouter) + snprintf(nstate, sizeof(nstate), "BDR"); + else + snprintf(nstate, sizeof(nstate), "DROther"); + } + + /* Duration */ + monotime_since(&on->last_changed, &res); + timerstring(&res, duration, sizeof(duration)); + + /* + vty_out (vty, "%-15s %3d %11s %6s/%-12s %11s %s[%s]\n", + "Neighbor ID", "Pri", "DeadTime", "State", "", "Duration", + "I/F", "State"); + */ + + vty_out(vty, "%-15s %3d %11s %8s/%-12s %11s %s[%s]\n", router_id, + on->priority, deadtime, ospf6_neighbor_state_str[on->state], + nstate, duration, on->ospf6_if->interface->name, + ospf6_interface_state_str[on->ospf6_if->state]); } -static void -ospf6_neighbor_show_drchoice (struct vty *vty, struct ospf6_neighbor *on) +static void ospf6_neighbor_show_drchoice(struct vty *vty, + struct ospf6_neighbor *on) { - char router_id[16]; - char drouter[16], bdrouter[16]; - char duration[16]; - struct timeval now, res; - -/* - vty_out (vty, "%-15s %6s/%-11s %-15s %-15s %s[%s]\n", - "RouterID", "State", "Duration", "DR", "BDR", "I/F", - "State"); -*/ - - inet_ntop (AF_INET, &on->router_id, router_id, sizeof (router_id)); - inet_ntop (AF_INET, &on->drouter, drouter, sizeof (drouter)); - inet_ntop (AF_INET, &on->bdrouter, bdrouter, sizeof (bdrouter)); - - monotime(&now); - timersub (&now, &on->last_changed, &res); - timerstring (&res, duration, sizeof (duration)); - - vty_out (vty, "%-15s %8s/%-11s %-15s %-15s %s[%s]\n", - router_id, ospf6_neighbor_state_str[on->state], - duration, drouter, bdrouter, on->ospf6_if->interface->name, - ospf6_interface_state_str[on->ospf6_if->state]); + char router_id[16]; + char drouter[16], bdrouter[16]; + char duration[16]; + struct timeval now, res; + + /* + vty_out (vty, "%-15s %6s/%-11s %-15s %-15s %s[%s]\n", + "RouterID", "State", "Duration", "DR", "BDR", "I/F", + "State"); + */ + + inet_ntop(AF_INET, &on->router_id, router_id, sizeof(router_id)); + inet_ntop(AF_INET, &on->drouter, drouter, sizeof(drouter)); + inet_ntop(AF_INET, &on->bdrouter, bdrouter, sizeof(bdrouter)); + + monotime(&now); + timersub(&now, &on->last_changed, &res); + timerstring(&res, duration, sizeof(duration)); + + vty_out(vty, "%-15s %8s/%-11s %-15s %-15s %s[%s]\n", router_id, + ospf6_neighbor_state_str[on->state], duration, drouter, + bdrouter, on->ospf6_if->interface->name, + ospf6_interface_state_str[on->ospf6_if->state]); } -static void -ospf6_neighbor_show_detail (struct vty *vty, struct ospf6_neighbor *on) +static void ospf6_neighbor_show_detail(struct vty *vty, + struct ospf6_neighbor *on) { - char drouter[16], bdrouter[16]; - char linklocal_addr[64], duration[32]; - struct timeval now, res; - struct ospf6_lsa *lsa; - - inet_ntop (AF_INET6, &on->linklocal_addr, linklocal_addr, - sizeof (linklocal_addr)); - inet_ntop (AF_INET, &on->drouter, drouter, sizeof (drouter)); - inet_ntop (AF_INET, &on->bdrouter, bdrouter, sizeof (bdrouter)); - - monotime(&now); - timersub (&now, &on->last_changed, &res); - timerstring (&res, duration, sizeof (duration)); - - vty_out (vty, " Neighbor %s\n", on->name); - vty_out (vty, " Area %s via interface %s (ifindex %d)\n", - on->ospf6_if->area->name, - on->ospf6_if->interface->name, - on->ospf6_if->interface->ifindex); - vty_out (vty, " His IfIndex: %d Link-local address: %s\n", - on->ifindex, linklocal_addr); - vty_out (vty, " State %s for a duration of %s\n", - ospf6_neighbor_state_str[on->state], duration); - vty_out (vty, " His choice of DR/BDR %s/%s, Priority %d\n", - drouter, bdrouter, on->priority); - vty_out (vty, " DbDesc status: %s%s%s SeqNum: %#lx\n", - (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT) ? "Initial " : ""), - (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT) ? "More " : ""), - (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) ? - "Master" : "Slave"), (u_long) ntohl (on->dbdesc_seqnum)); - - vty_out (vty, " Summary-List: %d LSAs\n", on->summary_list->count); - for (ALL_LSDB(on->summary_list, lsa)) - vty_out (vty, " %s\n", lsa->name); - - vty_out (vty, " Request-List: %d LSAs\n", on->request_list->count); - for (ALL_LSDB(on->request_list, lsa)) - vty_out (vty, " %s\n", lsa->name); - - vty_out (vty, " Retrans-List: %d LSAs\n", on->retrans_list->count); - for (ALL_LSDB(on->retrans_list, lsa)) - vty_out (vty, " %s\n", lsa->name); - - timerclear (&res); - if (on->thread_send_dbdesc) - timersub (&on->thread_send_dbdesc->u.sands, &now, &res); - timerstring (&res, duration, sizeof (duration)); - vty_out (vty, " %d Pending LSAs for DbDesc in Time %s [thread %s]\n", - on->dbdesc_list->count, duration, - (on->thread_send_dbdesc ? "on" : "off")); - for (ALL_LSDB(on->dbdesc_list, lsa)) - vty_out (vty, " %s\n", lsa->name); - - timerclear (&res); - if (on->thread_send_lsreq) - timersub (&on->thread_send_lsreq->u.sands, &now, &res); - timerstring (&res, duration, sizeof (duration)); - vty_out (vty, " %d Pending LSAs for LSReq in Time %s [thread %s]\n", - on->request_list->count, duration, - (on->thread_send_lsreq ? "on" : "off")); - for (ALL_LSDB(on->request_list, lsa)) - vty_out (vty, " %s\n", lsa->name); - - timerclear (&res); - if (on->thread_send_lsupdate) - timersub (&on->thread_send_lsupdate->u.sands, &now, &res); - timerstring (&res, duration, sizeof (duration)); - vty_out (vty, " %d Pending LSAs for LSUpdate in Time %s [thread %s]\n", - on->lsupdate_list->count, duration, - (on->thread_send_lsupdate ? "on" : "off")); - for (ALL_LSDB(on->lsupdate_list, lsa)) - vty_out (vty, " %s\n", lsa->name); - - timerclear (&res); - if (on->thread_send_lsack) - timersub (&on->thread_send_lsack->u.sands, &now, &res); - timerstring (&res, duration, sizeof (duration)); - vty_out (vty, " %d Pending LSAs for LSAck in Time %s [thread %s]\n", - on->lsack_list->count, duration, - (on->thread_send_lsack ? "on" : "off")); - for (ALL_LSDB(on->lsack_list, lsa)) - vty_out (vty, " %s\n", lsa->name); - - ospf6_bfd_show_info(vty, on->bfd_info, 0); + char drouter[16], bdrouter[16]; + char linklocal_addr[64], duration[32]; + struct timeval now, res; + struct ospf6_lsa *lsa; + + inet_ntop(AF_INET6, &on->linklocal_addr, linklocal_addr, + sizeof(linklocal_addr)); + inet_ntop(AF_INET, &on->drouter, drouter, sizeof(drouter)); + inet_ntop(AF_INET, &on->bdrouter, bdrouter, sizeof(bdrouter)); + + monotime(&now); + timersub(&now, &on->last_changed, &res); + timerstring(&res, duration, sizeof(duration)); + + vty_out(vty, " Neighbor %s\n", on->name); + vty_out(vty, " Area %s via interface %s (ifindex %d)\n", + on->ospf6_if->area->name, on->ospf6_if->interface->name, + on->ospf6_if->interface->ifindex); + vty_out(vty, " His IfIndex: %d Link-local address: %s\n", + on->ifindex, linklocal_addr); + vty_out(vty, " State %s for a duration of %s\n", + ospf6_neighbor_state_str[on->state], duration); + vty_out(vty, " His choice of DR/BDR %s/%s, Priority %d\n", drouter, + bdrouter, on->priority); + vty_out(vty, " DbDesc status: %s%s%s SeqNum: %#lx\n", + (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT) ? "Initial " + : ""), + (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT) ? "More " : ""), + (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT) ? "Master" + : "Slave"), + (u_long)ntohl(on->dbdesc_seqnum)); + + vty_out(vty, " Summary-List: %d LSAs\n", on->summary_list->count); + for (ALL_LSDB(on->summary_list, lsa)) + vty_out(vty, " %s\n", lsa->name); + + vty_out(vty, " Request-List: %d LSAs\n", on->request_list->count); + for (ALL_LSDB(on->request_list, lsa)) + vty_out(vty, " %s\n", lsa->name); + + vty_out(vty, " Retrans-List: %d LSAs\n", on->retrans_list->count); + for (ALL_LSDB(on->retrans_list, lsa)) + vty_out(vty, " %s\n", lsa->name); + + timerclear(&res); + if (on->thread_send_dbdesc) + timersub(&on->thread_send_dbdesc->u.sands, &now, &res); + timerstring(&res, duration, sizeof(duration)); + vty_out(vty, " %d Pending LSAs for DbDesc in Time %s [thread %s]\n", + on->dbdesc_list->count, duration, + (on->thread_send_dbdesc ? "on" : "off")); + for (ALL_LSDB(on->dbdesc_list, lsa)) + vty_out(vty, " %s\n", lsa->name); + + timerclear(&res); + if (on->thread_send_lsreq) + timersub(&on->thread_send_lsreq->u.sands, &now, &res); + timerstring(&res, duration, sizeof(duration)); + vty_out(vty, " %d Pending LSAs for LSReq in Time %s [thread %s]\n", + on->request_list->count, duration, + (on->thread_send_lsreq ? "on" : "off")); + for (ALL_LSDB(on->request_list, lsa)) + vty_out(vty, " %s\n", lsa->name); + + timerclear(&res); + if (on->thread_send_lsupdate) + timersub(&on->thread_send_lsupdate->u.sands, &now, &res); + timerstring(&res, duration, sizeof(duration)); + vty_out(vty, + " %d Pending LSAs for LSUpdate in Time %s [thread %s]\n", + on->lsupdate_list->count, duration, + (on->thread_send_lsupdate ? "on" : "off")); + for (ALL_LSDB(on->lsupdate_list, lsa)) + vty_out(vty, " %s\n", lsa->name); + + timerclear(&res); + if (on->thread_send_lsack) + timersub(&on->thread_send_lsack->u.sands, &now, &res); + timerstring(&res, duration, sizeof(duration)); + vty_out(vty, " %d Pending LSAs for LSAck in Time %s [thread %s]\n", + on->lsack_list->count, duration, + (on->thread_send_lsack ? "on" : "off")); + for (ALL_LSDB(on->lsack_list, lsa)) + vty_out(vty, " %s\n", lsa->name); + + ospf6_bfd_show_info(vty, on->bfd_info, 0); } DEFUN (show_ipv6_ospf6_neighbor, @@ -803,39 +764,37 @@ DEFUN (show_ipv6_ospf6_neighbor, "Display details\n" "Display DR choices\n") { - int idx_type = 4; - struct ospf6_neighbor *on; - struct ospf6_interface *oi; - struct ospf6_area *oa; - struct listnode *i, *j, *k; - void (*showfunc) (struct vty *, struct ospf6_neighbor *); - - OSPF6_CMD_CHECK_RUNNING (); - showfunc = ospf6_neighbor_show; - - if (argc == 5) - { - if (! strncmp (argv[idx_type]->arg, "de", 2)) - showfunc = ospf6_neighbor_show_detail; - else if (! strncmp (argv[idx_type]->arg, "dr", 2)) - showfunc = ospf6_neighbor_show_drchoice; - } - - if (showfunc == ospf6_neighbor_show) - vty_out (vty, "%-15s %3s %11s %8s/%-12s %11s %s[%s]\n", - "Neighbor ID", "Pri", "DeadTime", "State", "IfState", "Duration", - "I/F", "State"); - else if (showfunc == ospf6_neighbor_show_drchoice) - vty_out (vty, "%-15s %8s/%-11s %-15s %-15s %s[%s]\n", - "RouterID", "State", "Duration", "DR", "BDR", "I/F", - "State"); - - for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, i, oa)) - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, k, on)) - (*showfunc) (vty, on); - - return CMD_SUCCESS; + int idx_type = 4; + struct ospf6_neighbor *on; + struct ospf6_interface *oi; + struct ospf6_area *oa; + struct listnode *i, *j, *k; + void (*showfunc)(struct vty *, struct ospf6_neighbor *); + + OSPF6_CMD_CHECK_RUNNING(); + showfunc = ospf6_neighbor_show; + + if (argc == 5) { + if (!strncmp(argv[idx_type]->arg, "de", 2)) + showfunc = ospf6_neighbor_show_detail; + else if (!strncmp(argv[idx_type]->arg, "dr", 2)) + showfunc = ospf6_neighbor_show_drchoice; + } + + if (showfunc == ospf6_neighbor_show) + vty_out(vty, "%-15s %3s %11s %8s/%-12s %11s %s[%s]\n", + "Neighbor ID", "Pri", "DeadTime", "State", "IfState", + "Duration", "I/F", "State"); + else if (showfunc == ospf6_neighbor_show_drchoice) + vty_out(vty, "%-15s %8s/%-11s %-15s %-15s %s[%s]\n", "RouterID", + "State", "Duration", "DR", "BDR", "I/F", "State"); + + for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on)) + (*showfunc)(vty, on); + + return CMD_SUCCESS; } @@ -849,36 +808,35 @@ DEFUN (show_ipv6_ospf6_neighbor_one, "Specify Router-ID as IPv4 address notation\n" ) { - int idx_ipv4 = 4; - struct ospf6_neighbor *on; - struct ospf6_interface *oi; - struct ospf6_area *oa; - struct listnode *i, *j, *k; - void (*showfunc) (struct vty *, struct ospf6_neighbor *); - u_int32_t router_id; - - OSPF6_CMD_CHECK_RUNNING (); - showfunc = ospf6_neighbor_show_detail; - - if ((inet_pton (AF_INET, argv[idx_ipv4]->arg, &router_id)) != 1) - { - vty_out (vty, "Router-ID is not parsable: %s\n", argv[idx_ipv4]->arg); - return CMD_SUCCESS; - } - - for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, i, oa)) - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, k, on)) - (*showfunc) (vty, on); - - return CMD_SUCCESS; + int idx_ipv4 = 4; + struct ospf6_neighbor *on; + struct ospf6_interface *oi; + struct ospf6_area *oa; + struct listnode *i, *j, *k; + void (*showfunc)(struct vty *, struct ospf6_neighbor *); + u_int32_t router_id; + + OSPF6_CMD_CHECK_RUNNING(); + showfunc = ospf6_neighbor_show_detail; + + if ((inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id)) != 1) { + vty_out(vty, "Router-ID is not parsable: %s\n", + argv[idx_ipv4]->arg); + return CMD_SUCCESS; + } + + for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on)) + (*showfunc)(vty, on); + + return CMD_SUCCESS; } -void -ospf6_neighbor_init (void) +void ospf6_neighbor_init(void) { - install_element (VIEW_NODE, &show_ipv6_ospf6_neighbor_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_neighbor_one_cmd); + install_element(VIEW_NODE, &show_ipv6_ospf6_neighbor_cmd); + install_element(VIEW_NODE, &show_ipv6_ospf6_neighbor_one_cmd); } DEFUN (debug_ospf6_neighbor, @@ -890,21 +848,19 @@ DEFUN (debug_ospf6_neighbor, "Debug OSPFv3 Neighbor State Change\n" "Debug OSPFv3 Neighbor Event\n") { - int idx_type = 3; - unsigned char level = 0; - - if (argc == 4) - { - if (! strncmp (argv[idx_type]->arg, "s", 1)) - level = OSPF6_DEBUG_NEIGHBOR_STATE; - else if (! strncmp (argv[idx_type]->arg, "e", 1)) - level = OSPF6_DEBUG_NEIGHBOR_EVENT; - } - else - level = OSPF6_DEBUG_NEIGHBOR_STATE | OSPF6_DEBUG_NEIGHBOR_EVENT; - - OSPF6_DEBUG_NEIGHBOR_ON (level); - return CMD_SUCCESS; + int idx_type = 3; + unsigned char level = 0; + + if (argc == 4) { + if (!strncmp(argv[idx_type]->arg, "s", 1)) + level = OSPF6_DEBUG_NEIGHBOR_STATE; + else if (!strncmp(argv[idx_type]->arg, "e", 1)) + level = OSPF6_DEBUG_NEIGHBOR_EVENT; + } else + level = OSPF6_DEBUG_NEIGHBOR_STATE | OSPF6_DEBUG_NEIGHBOR_EVENT; + + OSPF6_DEBUG_NEIGHBOR_ON(level); + return CMD_SUCCESS; } @@ -918,21 +874,19 @@ DEFUN (no_debug_ospf6_neighbor, "Debug OSPFv3 Neighbor State Change\n" "Debug OSPFv3 Neighbor Event\n") { - int idx_type = 4; - unsigned char level = 0; - - if (argc == 5) - { - if (! strncmp (argv[idx_type]->arg, "s", 1)) - level = OSPF6_DEBUG_NEIGHBOR_STATE; - if (! strncmp (argv[idx_type]->arg, "e", 1)) - level = OSPF6_DEBUG_NEIGHBOR_EVENT; - } - else - level = OSPF6_DEBUG_NEIGHBOR_STATE | OSPF6_DEBUG_NEIGHBOR_EVENT; - - OSPF6_DEBUG_NEIGHBOR_OFF (level); - return CMD_SUCCESS; + int idx_type = 4; + unsigned char level = 0; + + if (argc == 5) { + if (!strncmp(argv[idx_type]->arg, "s", 1)) + level = OSPF6_DEBUG_NEIGHBOR_STATE; + if (!strncmp(argv[idx_type]->arg, "e", 1)) + level = OSPF6_DEBUG_NEIGHBOR_EVENT; + } else + level = OSPF6_DEBUG_NEIGHBOR_STATE | OSPF6_DEBUG_NEIGHBOR_EVENT; + + OSPF6_DEBUG_NEIGHBOR_OFF(level); + return CMD_SUCCESS; } @@ -943,66 +897,61 @@ DEFUN (no_debug_ospf6, DEBUG_STR OSPF6_STR) { - u_int i; - struct ospf6_lsa_handler *handler = NULL; - - OSPF6_DEBUG_ABR_OFF (); - OSPF6_DEBUG_ASBR_OFF (); - OSPF6_DEBUG_BROUTER_OFF (); - OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF (); - OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF (); - OSPF6_DEBUG_FLOODING_OFF (); - OSPF6_DEBUG_INTERFACE_OFF (); - - for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++) - { - handler = vector_slot (ospf6_lsa_handler_vector, i); - - if (handler != NULL) - { - UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG); - } - } - - for (i = 0; i < 6; i++) - OSPF6_DEBUG_MESSAGE_OFF (i, OSPF6_DEBUG_NEIGHBOR_STATE | OSPF6_DEBUG_NEIGHBOR_EVENT); - - OSPF6_DEBUG_NEIGHBOR_OFF (OSPF6_DEBUG_NEIGHBOR_STATE | OSPF6_DEBUG_NEIGHBOR_EVENT); - OSPF6_DEBUG_ROUTE_OFF (OSPF6_DEBUG_ROUTE_TABLE); - OSPF6_DEBUG_ROUTE_OFF (OSPF6_DEBUG_ROUTE_INTRA); - OSPF6_DEBUG_ROUTE_OFF (OSPF6_DEBUG_ROUTE_INTER); - OSPF6_DEBUG_ROUTE_OFF (OSPF6_DEBUG_ROUTE_MEMORY); - OSPF6_DEBUG_SPF_OFF (OSPF6_DEBUG_SPF_PROCESS); - OSPF6_DEBUG_SPF_OFF (OSPF6_DEBUG_SPF_TIME); - OSPF6_DEBUG_SPF_OFF (OSPF6_DEBUG_SPF_DATABASE); - OSPF6_DEBUG_ZEBRA_OFF (OSPF6_DEBUG_ZEBRA_SEND | OSPF6_DEBUG_ZEBRA_RECV); - - return CMD_SUCCESS; + u_int i; + struct ospf6_lsa_handler *handler = NULL; + + OSPF6_DEBUG_ABR_OFF(); + OSPF6_DEBUG_ASBR_OFF(); + OSPF6_DEBUG_BROUTER_OFF(); + OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF(); + OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF(); + OSPF6_DEBUG_FLOODING_OFF(); + OSPF6_DEBUG_INTERFACE_OFF(); + + for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) { + handler = vector_slot(ospf6_lsa_handler_vector, i); + + if (handler != NULL) { + UNSET_FLAG(handler->debug, OSPF6_LSA_DEBUG); + } + } + + for (i = 0; i < 6; i++) + OSPF6_DEBUG_MESSAGE_OFF(i, + OSPF6_DEBUG_NEIGHBOR_STATE + | OSPF6_DEBUG_NEIGHBOR_EVENT); + + OSPF6_DEBUG_NEIGHBOR_OFF(OSPF6_DEBUG_NEIGHBOR_STATE + | OSPF6_DEBUG_NEIGHBOR_EVENT); + OSPF6_DEBUG_ROUTE_OFF(OSPF6_DEBUG_ROUTE_TABLE); + OSPF6_DEBUG_ROUTE_OFF(OSPF6_DEBUG_ROUTE_INTRA); + OSPF6_DEBUG_ROUTE_OFF(OSPF6_DEBUG_ROUTE_INTER); + OSPF6_DEBUG_ROUTE_OFF(OSPF6_DEBUG_ROUTE_MEMORY); + OSPF6_DEBUG_SPF_OFF(OSPF6_DEBUG_SPF_PROCESS); + OSPF6_DEBUG_SPF_OFF(OSPF6_DEBUG_SPF_TIME); + OSPF6_DEBUG_SPF_OFF(OSPF6_DEBUG_SPF_DATABASE); + OSPF6_DEBUG_ZEBRA_OFF(OSPF6_DEBUG_ZEBRA_SEND | OSPF6_DEBUG_ZEBRA_RECV); + + return CMD_SUCCESS; } -int -config_write_ospf6_debug_neighbor (struct vty *vty) +int config_write_ospf6_debug_neighbor(struct vty *vty) { - if (IS_OSPF6_DEBUG_NEIGHBOR (STATE) && - IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) - vty_out (vty, "debug ospf6 neighbor\n"); - else if (IS_OSPF6_DEBUG_NEIGHBOR (STATE)) - vty_out (vty, "debug ospf6 neighbor state\n"); - else if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) - vty_out (vty, "debug ospf6 neighbor event\n"); - return 0; + if (IS_OSPF6_DEBUG_NEIGHBOR(STATE) && IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) + vty_out(vty, "debug ospf6 neighbor\n"); + else if (IS_OSPF6_DEBUG_NEIGHBOR(STATE)) + vty_out(vty, "debug ospf6 neighbor state\n"); + else if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) + vty_out(vty, "debug ospf6 neighbor event\n"); + return 0; } -void -install_element_ospf6_debug_neighbor (void) +void install_element_ospf6_debug_neighbor(void) { - install_element (ENABLE_NODE, &debug_ospf6_neighbor_cmd); - install_element (ENABLE_NODE, &no_debug_ospf6_neighbor_cmd); - install_element (ENABLE_NODE, &no_debug_ospf6_cmd); - install_element (CONFIG_NODE, &debug_ospf6_neighbor_cmd); - install_element (CONFIG_NODE, &no_debug_ospf6_neighbor_cmd); - install_element (CONFIG_NODE, &no_debug_ospf6_cmd); + install_element(ENABLE_NODE, &debug_ospf6_neighbor_cmd); + install_element(ENABLE_NODE, &no_debug_ospf6_neighbor_cmd); + install_element(ENABLE_NODE, &no_debug_ospf6_cmd); + install_element(CONFIG_NODE, &debug_ospf6_neighbor_cmd); + install_element(CONFIG_NODE, &no_debug_ospf6_neighbor_cmd); + install_element(CONFIG_NODE, &no_debug_ospf6_cmd); } - - - diff --git a/ospf6d/ospf6_neighbor.h b/ospf6d/ospf6_neighbor.h index 3ff341933..529f586f1 100644 --- a/ospf6d/ospf6_neighbor.h +++ b/ospf6d/ospf6_neighbor.h @@ -27,79 +27,76 @@ extern unsigned char conf_debug_ospf6_neighbor; #define OSPF6_DEBUG_NEIGHBOR_STATE 0x01 #define OSPF6_DEBUG_NEIGHBOR_EVENT 0x02 -#define OSPF6_DEBUG_NEIGHBOR_ON(level) \ - (conf_debug_ospf6_neighbor |= (level)) -#define OSPF6_DEBUG_NEIGHBOR_OFF(level) \ - (conf_debug_ospf6_neighbor &= ~(level)) -#define IS_OSPF6_DEBUG_NEIGHBOR(level) \ - (conf_debug_ospf6_neighbor & OSPF6_DEBUG_NEIGHBOR_ ## level) +#define OSPF6_DEBUG_NEIGHBOR_ON(level) (conf_debug_ospf6_neighbor |= (level)) +#define OSPF6_DEBUG_NEIGHBOR_OFF(level) (conf_debug_ospf6_neighbor &= ~(level)) +#define IS_OSPF6_DEBUG_NEIGHBOR(level) \ + (conf_debug_ospf6_neighbor & OSPF6_DEBUG_NEIGHBOR_##level) /* Neighbor structure */ -struct ospf6_neighbor -{ - /* Neighbor Router ID String */ - char name[32]; +struct ospf6_neighbor { + /* Neighbor Router ID String */ + char name[32]; - /* OSPFv3 Interface this neighbor belongs to */ - struct ospf6_interface *ospf6_if; + /* OSPFv3 Interface this neighbor belongs to */ + struct ospf6_interface *ospf6_if; - /* Neighbor state */ - u_char state; + /* Neighbor state */ + u_char state; - /* timestamp of last changing state */ - u_int32_t state_change; - struct timeval last_changed; + /* timestamp of last changing state */ + u_int32_t state_change; + struct timeval last_changed; - /* Neighbor Router ID */ - u_int32_t router_id; + /* Neighbor Router ID */ + u_int32_t router_id; - /* Neighbor Interface ID */ - ifindex_t ifindex; + /* Neighbor Interface ID */ + ifindex_t ifindex; - /* Router Priority of this neighbor */ - u_char priority; + /* Router Priority of this neighbor */ + u_char priority; - u_int32_t drouter; - u_int32_t bdrouter; - u_int32_t prev_drouter; - u_int32_t prev_bdrouter; + u_int32_t drouter; + u_int32_t bdrouter; + u_int32_t prev_drouter; + u_int32_t prev_bdrouter; - /* Options field (Capability) */ - char options[3]; + /* Options field (Capability) */ + char options[3]; - /* IPaddr of I/F on our side link */ - struct in6_addr linklocal_addr; + /* IPaddr of I/F on our side link */ + struct in6_addr linklocal_addr; - /* For Database Exchange */ - u_char dbdesc_bits; - u_int32_t dbdesc_seqnum; - /* Last received Database Description packet */ - struct ospf6_dbdesc dbdesc_last; + /* For Database Exchange */ + u_char dbdesc_bits; + u_int32_t dbdesc_seqnum; + /* Last received Database Description packet */ + struct ospf6_dbdesc dbdesc_last; - /* LS-list */ - struct ospf6_lsdb *summary_list; - struct ospf6_lsdb *request_list; - struct ospf6_lsdb *retrans_list; + /* LS-list */ + struct ospf6_lsdb *summary_list; + struct ospf6_lsdb *request_list; + struct ospf6_lsdb *retrans_list; - /* LSA list for message transmission */ - struct ospf6_lsdb *dbdesc_list; - struct ospf6_lsdb *lsreq_list; - struct ospf6_lsdb *lsupdate_list; - struct ospf6_lsdb *lsack_list; + /* LSA list for message transmission */ + struct ospf6_lsdb *dbdesc_list; + struct ospf6_lsdb *lsreq_list; + struct ospf6_lsdb *lsupdate_list; + struct ospf6_lsdb *lsack_list; - struct ospf6_lsa *last_ls_req; + struct ospf6_lsa *last_ls_req; - /* Inactivity timer */ - struct thread *inactivity_timer; + /* Inactivity timer */ + struct thread *inactivity_timer; - /* Thread for sending message */ - struct thread *thread_send_dbdesc; - struct thread *thread_send_lsreq; - struct thread *thread_send_lsupdate; - struct thread *thread_send_lsack; + /* Thread for sending message */ + struct thread *thread_send_dbdesc; + struct thread *thread_send_lsreq; + struct thread *thread_send_lsupdate; + struct thread *thread_send_lsack; - /* BFD information */ - void *bfd_info; + /* BFD information */ + void *bfd_info; }; /* Neighbor state */ @@ -126,62 +123,53 @@ struct ospf6_neighbor #define OSPF6_NEIGHBOR_EVENT_INACTIVITY_TIMER 10 #define OSPF6_NEIGHBOR_EVENT_MAX_EVENT 11 -static const char *ospf6_neighbor_event_str[] = - { - "NoEvent", - "HelloReceived", - "2-WayReceived", - "NegotiationDone", - "ExchangeDone", - "LoadingDone", - "AdjOK?", - "SeqNumberMismatch", - "BadLSReq", - "1-WayReceived", - "InactivityTimer", - }; - -static inline const char *ospf6_neighbor_event_string (int event) +static const char *ospf6_neighbor_event_str[] = { + "NoEvent", "HelloReceived", "2-WayReceived", "NegotiationDone", + "ExchangeDone", "LoadingDone", "AdjOK?", "SeqNumberMismatch", + "BadLSReq", "1-WayReceived", "InactivityTimer", +}; + +static inline const char *ospf6_neighbor_event_string(int event) { - #define OSPF6_NEIGHBOR_UNKNOWN_EVENT_STRING "UnknownEvent" +#define OSPF6_NEIGHBOR_UNKNOWN_EVENT_STRING "UnknownEvent" - if (event < OSPF6_NEIGHBOR_EVENT_MAX_EVENT) - return ospf6_neighbor_event_str[event]; - return OSPF6_NEIGHBOR_UNKNOWN_EVENT_STRING; + if (event < OSPF6_NEIGHBOR_EVENT_MAX_EVENT) + return ospf6_neighbor_event_str[event]; + return OSPF6_NEIGHBOR_UNKNOWN_EVENT_STRING; } extern const char *ospf6_neighbor_state_str[]; /* Function Prototypes */ -int ospf6_neighbor_cmp (void *va, void *vb); -void ospf6_neighbor_dbex_init (struct ospf6_neighbor *on); +int ospf6_neighbor_cmp(void *va, void *vb); +void ospf6_neighbor_dbex_init(struct ospf6_neighbor *on); -struct ospf6_neighbor *ospf6_neighbor_lookup (u_int32_t, - struct ospf6_interface *); -struct ospf6_neighbor *ospf6_neighbor_create (u_int32_t, - struct ospf6_interface *); -void ospf6_neighbor_delete (struct ospf6_neighbor *); +struct ospf6_neighbor *ospf6_neighbor_lookup(u_int32_t, + struct ospf6_interface *); +struct ospf6_neighbor *ospf6_neighbor_create(u_int32_t, + struct ospf6_interface *); +void ospf6_neighbor_delete(struct ospf6_neighbor *); /* Neighbor event */ -extern int hello_received (struct thread *); -extern int twoway_received (struct thread *); -extern int negotiation_done (struct thread *); -extern int exchange_done (struct thread *); -extern int loading_done (struct thread *); -extern int adj_ok (struct thread *); -extern int seqnumber_mismatch (struct thread *); -extern int bad_lsreq (struct thread *); -extern int oneway_received (struct thread *); -extern int inactivity_timer (struct thread *); -extern void ospf6_check_nbr_loading (struct ospf6_neighbor *); - -extern void ospf6_neighbor_init (void); -extern int config_write_ospf6_debug_neighbor (struct vty *vty); -extern void install_element_ospf6_debug_neighbor (void); +extern int hello_received(struct thread *); +extern int twoway_received(struct thread *); +extern int negotiation_done(struct thread *); +extern int exchange_done(struct thread *); +extern int loading_done(struct thread *); +extern int adj_ok(struct thread *); +extern int seqnumber_mismatch(struct thread *); +extern int bad_lsreq(struct thread *); +extern int oneway_received(struct thread *); +extern int inactivity_timer(struct thread *); +extern void ospf6_check_nbr_loading(struct ospf6_neighbor *); + +extern void ospf6_neighbor_init(void); +extern int config_write_ospf6_debug_neighbor(struct vty *vty); +extern void install_element_ospf6_debug_neighbor(void); DECLARE_HOOK(ospf6_neighbor_change, - (struct ospf6_neighbor *on, int state, int next_state), - (on, state, next_state)) + (struct ospf6_neighbor * on, int state, int next_state), + (on, state, next_state)) #endif /* OSPF6_NEIGHBOR_H */ diff --git a/ospf6d/ospf6_network.c b/ospf6d/ospf6_network.c index 9e7dd06bd..4d9c25944 100644 --- a/ospf6d/ospf6_network.c +++ b/ospf6d/ospf6_network.c @@ -32,237 +32,225 @@ extern struct zebra_privs_t ospf6d_privs; -int ospf6_sock; +int ospf6_sock; struct in6_addr allspfrouters6; struct in6_addr alldrouters6; /* setsockopt MulticastLoop to off */ -static void -ospf6_reset_mcastloop (void) +static void ospf6_reset_mcastloop(void) { - u_int off = 0; - if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, - &off, sizeof (u_int)) < 0) - zlog_warn ("Network: reset IPV6_MULTICAST_LOOP failed: %s", - safe_strerror (errno)); + u_int off = 0; + if (setsockopt(ospf6_sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off, + sizeof(u_int)) + < 0) + zlog_warn("Network: reset IPV6_MULTICAST_LOOP failed: %s", + safe_strerror(errno)); } -static void -ospf6_set_pktinfo (void) +static void ospf6_set_pktinfo(void) { - setsockopt_ipv6_pktinfo (ospf6_sock, 1); + setsockopt_ipv6_pktinfo(ospf6_sock, 1); } -static void -ospf6_set_transport_class (void) +static void ospf6_set_transport_class(void) { #ifdef IPTOS_PREC_INTERNETCONTROL - setsockopt_ipv6_tclass (ospf6_sock, IPTOS_PREC_INTERNETCONTROL); + setsockopt_ipv6_tclass(ospf6_sock, IPTOS_PREC_INTERNETCONTROL); #endif } -static void -ospf6_set_checksum (void) +static void ospf6_set_checksum(void) { - int offset = 12; + int offset = 12; #ifndef DISABLE_IPV6_CHECKSUM - if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_CHECKSUM, - &offset, sizeof (offset)) < 0) - zlog_warn ("Network: set IPV6_CHECKSUM failed: %s", safe_strerror (errno)); + if (setsockopt(ospf6_sock, IPPROTO_IPV6, IPV6_CHECKSUM, &offset, + sizeof(offset)) + < 0) + zlog_warn("Network: set IPV6_CHECKSUM failed: %s", + safe_strerror(errno)); #else - zlog_warn ("Network: Don't set IPV6_CHECKSUM"); + zlog_warn("Network: Don't set IPV6_CHECKSUM"); #endif /* DISABLE_IPV6_CHECKSUM */ } /* Make ospf6d's server socket. */ -int -ospf6_serv_sock (void) +int ospf6_serv_sock(void) { - if (ospf6d_privs.change (ZPRIVS_RAISE)) - zlog_err ("ospf6_serv_sock: could not raise privs"); - - ospf6_sock = socket (AF_INET6, SOCK_RAW, IPPROTO_OSPFIGP); - if (ospf6_sock < 0) - { - zlog_warn ("Network: can't create OSPF6 socket."); - if (ospf6d_privs.change (ZPRIVS_LOWER)) - zlog_err ("ospf_sock_init: could not lower privs"); - return -1; - } - if (ospf6d_privs.change (ZPRIVS_LOWER)) - zlog_err ("ospf_sock_init: could not lower privs"); - - /* set socket options */ + if (ospf6d_privs.change(ZPRIVS_RAISE)) + zlog_err("ospf6_serv_sock: could not raise privs"); + + ospf6_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_OSPFIGP); + if (ospf6_sock < 0) { + zlog_warn("Network: can't create OSPF6 socket."); + if (ospf6d_privs.change(ZPRIVS_LOWER)) + zlog_err("ospf_sock_init: could not lower privs"); + return -1; + } + if (ospf6d_privs.change(ZPRIVS_LOWER)) + zlog_err("ospf_sock_init: could not lower privs"); + +/* set socket options */ #if 1 - sockopt_reuseaddr (ospf6_sock); + sockopt_reuseaddr(ospf6_sock); #else - ospf6_set_reuseaddr (); + ospf6_set_reuseaddr(); #endif /*1*/ - ospf6_reset_mcastloop (); - ospf6_set_pktinfo (); - ospf6_set_transport_class (); - ospf6_set_checksum (); + ospf6_reset_mcastloop(); + ospf6_set_pktinfo(); + ospf6_set_transport_class(); + ospf6_set_checksum(); - /* setup global in6_addr, allspf6 and alldr6 for later use */ - inet_pton (AF_INET6, ALLSPFROUTERS6, &allspfrouters6); - inet_pton (AF_INET6, ALLDROUTERS6, &alldrouters6); + /* setup global in6_addr, allspf6 and alldr6 for later use */ + inet_pton(AF_INET6, ALLSPFROUTERS6, &allspfrouters6); + inet_pton(AF_INET6, ALLDROUTERS6, &alldrouters6); - return 0; + return 0; } /* ospf6 set socket option */ -int -ospf6_sso (ifindex_t ifindex, struct in6_addr *group, int option) +int ospf6_sso(ifindex_t ifindex, struct in6_addr *group, int option) { - struct ipv6_mreq mreq6; - int ret; - int bufsize = (8 * 1024 * 1024); - - assert (ifindex); - mreq6.ipv6mr_interface = ifindex; - memcpy (&mreq6.ipv6mr_multiaddr, group, sizeof (struct in6_addr)); - - ret = setsockopt (ospf6_sock, IPPROTO_IPV6, option, - &mreq6, sizeof (mreq6)); - if (ret < 0) - { - zlog_err ("Network: setsockopt (%d) on ifindex %d failed: %s", - option, ifindex, safe_strerror (errno)); - return ret; - } - - setsockopt_so_sendbuf (ospf6_sock, bufsize); - setsockopt_so_recvbuf (ospf6_sock, bufsize); - - return 0; + struct ipv6_mreq mreq6; + int ret; + int bufsize = (8 * 1024 * 1024); + + assert(ifindex); + mreq6.ipv6mr_interface = ifindex; + memcpy(&mreq6.ipv6mr_multiaddr, group, sizeof(struct in6_addr)); + + ret = setsockopt(ospf6_sock, IPPROTO_IPV6, option, &mreq6, + sizeof(mreq6)); + if (ret < 0) { + zlog_err("Network: setsockopt (%d) on ifindex %d failed: %s", + option, ifindex, safe_strerror(errno)); + return ret; + } + + setsockopt_so_sendbuf(ospf6_sock, bufsize); + setsockopt_so_recvbuf(ospf6_sock, bufsize); + + return 0; } -static int -iov_count (struct iovec *iov) +static int iov_count(struct iovec *iov) { - int i; - for (i = 0; iov[i].iov_base; i++) - ; - return i; + int i; + for (i = 0; iov[i].iov_base; i++) + ; + return i; } -static int -iov_totallen (struct iovec *iov) +static int iov_totallen(struct iovec *iov) { - int i; - int totallen = 0; - for (i = 0; iov[i].iov_base; i++) - totallen += iov[i].iov_len; - return totallen; + int i; + int totallen = 0; + for (i = 0; iov[i].iov_base; i++) + totallen += iov[i].iov_len; + return totallen; } -int -ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst, - ifindex_t *ifindex, struct iovec *message) +int ospf6_sendmsg(struct in6_addr *src, struct in6_addr *dst, + ifindex_t *ifindex, struct iovec *message) { - int retval; - struct msghdr smsghdr; - struct cmsghdr *scmsgp; - union - { - struct cmsghdr hdr; - u_char buf[CMSG_SPACE (sizeof (struct in6_pktinfo))]; - } cmsgbuf; - struct in6_pktinfo *pktinfo; - struct sockaddr_in6 dst_sin6; - - assert (dst); - assert (*ifindex); - - scmsgp = (struct cmsghdr *)&cmsgbuf; - pktinfo = (struct in6_pktinfo *)(CMSG_DATA(scmsgp)); - memset (&dst_sin6, 0, sizeof (struct sockaddr_in6)); - - /* source address */ - pktinfo->ipi6_ifindex = *ifindex; - if (src) - memcpy (&pktinfo->ipi6_addr, src, sizeof (struct in6_addr)); - else - memset (&pktinfo->ipi6_addr, 0, sizeof (struct in6_addr)); - - /* destination address */ - dst_sin6.sin6_family = AF_INET6; + int retval; + struct msghdr smsghdr; + struct cmsghdr *scmsgp; + union { + struct cmsghdr hdr; + u_char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; + } cmsgbuf; + struct in6_pktinfo *pktinfo; + struct sockaddr_in6 dst_sin6; + + assert(dst); + assert(*ifindex); + + scmsgp = (struct cmsghdr *)&cmsgbuf; + pktinfo = (struct in6_pktinfo *)(CMSG_DATA(scmsgp)); + memset(&dst_sin6, 0, sizeof(struct sockaddr_in6)); + + /* source address */ + pktinfo->ipi6_ifindex = *ifindex; + if (src) + memcpy(&pktinfo->ipi6_addr, src, sizeof(struct in6_addr)); + else + memset(&pktinfo->ipi6_addr, 0, sizeof(struct in6_addr)); + + /* destination address */ + dst_sin6.sin6_family = AF_INET6; #ifdef SIN6_LEN - dst_sin6.sin6_len = sizeof (struct sockaddr_in6); + dst_sin6.sin6_len = sizeof(struct sockaddr_in6); #endif /*SIN6_LEN*/ - memcpy (&dst_sin6.sin6_addr, dst, sizeof (struct in6_addr)); - dst_sin6.sin6_scope_id = *ifindex; - - /* send control msg */ - scmsgp->cmsg_level = IPPROTO_IPV6; - scmsgp->cmsg_type = IPV6_PKTINFO; - scmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo)); - /* scmsgp = CMSG_NXTHDR (&smsghdr, scmsgp); */ - - /* send msg hdr */ - memset (&smsghdr, 0, sizeof (smsghdr)); - smsghdr.msg_iov = message; - smsghdr.msg_iovlen = iov_count (message); - smsghdr.msg_name = (caddr_t) &dst_sin6; - smsghdr.msg_namelen = sizeof (struct sockaddr_in6); - smsghdr.msg_control = (caddr_t) &cmsgbuf.buf; - smsghdr.msg_controllen = sizeof(cmsgbuf.buf); - - retval = sendmsg (ospf6_sock, &smsghdr, 0); - if (retval != iov_totallen (message)) - zlog_warn ("sendmsg failed: ifindex: %d: %s (%d)", - *ifindex, safe_strerror (errno), errno); - - return retval; + memcpy(&dst_sin6.sin6_addr, dst, sizeof(struct in6_addr)); + dst_sin6.sin6_scope_id = *ifindex; + + /* send control msg */ + scmsgp->cmsg_level = IPPROTO_IPV6; + scmsgp->cmsg_type = IPV6_PKTINFO; + scmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + /* scmsgp = CMSG_NXTHDR (&smsghdr, scmsgp); */ + + /* send msg hdr */ + memset(&smsghdr, 0, sizeof(smsghdr)); + smsghdr.msg_iov = message; + smsghdr.msg_iovlen = iov_count(message); + smsghdr.msg_name = (caddr_t)&dst_sin6; + smsghdr.msg_namelen = sizeof(struct sockaddr_in6); + smsghdr.msg_control = (caddr_t)&cmsgbuf.buf; + smsghdr.msg_controllen = sizeof(cmsgbuf.buf); + + retval = sendmsg(ospf6_sock, &smsghdr, 0); + if (retval != iov_totallen(message)) + zlog_warn("sendmsg failed: ifindex: %d: %s (%d)", *ifindex, + safe_strerror(errno), errno); + + return retval; } -int -ospf6_recvmsg (struct in6_addr *src, struct in6_addr *dst, - ifindex_t *ifindex, struct iovec *message) +int ospf6_recvmsg(struct in6_addr *src, struct in6_addr *dst, + ifindex_t *ifindex, struct iovec *message) { - int retval; - struct msghdr rmsghdr; - struct cmsghdr *rcmsgp; - u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))]; - struct in6_pktinfo *pktinfo; - struct sockaddr_in6 src_sin6; - - rcmsgp = (struct cmsghdr *)cmsgbuf; - pktinfo = (struct in6_pktinfo *)(CMSG_DATA(rcmsgp)); - memset (&src_sin6, 0, sizeof (struct sockaddr_in6)); - - /* receive control msg */ - rcmsgp->cmsg_level = IPPROTO_IPV6; - rcmsgp->cmsg_type = IPV6_PKTINFO; - rcmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo)); - /* rcmsgp = CMSG_NXTHDR (&rmsghdr, rcmsgp); */ - - /* receive msg hdr */ - memset (&rmsghdr, 0, sizeof (rmsghdr)); - rmsghdr.msg_iov = message; - rmsghdr.msg_iovlen = iov_count (message); - rmsghdr.msg_name = (caddr_t) &src_sin6; - rmsghdr.msg_namelen = sizeof (struct sockaddr_in6); - rmsghdr.msg_control = (caddr_t) cmsgbuf; - rmsghdr.msg_controllen = sizeof (cmsgbuf); - - retval = recvmsg (ospf6_sock, &rmsghdr, 0); - if (retval < 0) - zlog_warn ("recvmsg failed: %s", safe_strerror (errno)); - else if (retval == iov_totallen (message)) - zlog_warn ("recvmsg read full buffer size: %d", retval); - - /* source address */ - assert (src); - memcpy (src, &src_sin6.sin6_addr, sizeof (struct in6_addr)); - - /* destination address */ - if (ifindex) - *ifindex = pktinfo->ipi6_ifindex; - if (dst) - memcpy (dst, &pktinfo->ipi6_addr, sizeof (struct in6_addr)); - - return retval; + int retval; + struct msghdr rmsghdr; + struct cmsghdr *rcmsgp; + u_char cmsgbuf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; + struct in6_pktinfo *pktinfo; + struct sockaddr_in6 src_sin6; + + rcmsgp = (struct cmsghdr *)cmsgbuf; + pktinfo = (struct in6_pktinfo *)(CMSG_DATA(rcmsgp)); + memset(&src_sin6, 0, sizeof(struct sockaddr_in6)); + + /* receive control msg */ + rcmsgp->cmsg_level = IPPROTO_IPV6; + rcmsgp->cmsg_type = IPV6_PKTINFO; + rcmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + /* rcmsgp = CMSG_NXTHDR (&rmsghdr, rcmsgp); */ + + /* receive msg hdr */ + memset(&rmsghdr, 0, sizeof(rmsghdr)); + rmsghdr.msg_iov = message; + rmsghdr.msg_iovlen = iov_count(message); + rmsghdr.msg_name = (caddr_t)&src_sin6; + rmsghdr.msg_namelen = sizeof(struct sockaddr_in6); + rmsghdr.msg_control = (caddr_t)cmsgbuf; + rmsghdr.msg_controllen = sizeof(cmsgbuf); + + retval = recvmsg(ospf6_sock, &rmsghdr, 0); + if (retval < 0) + zlog_warn("recvmsg failed: %s", safe_strerror(errno)); + else if (retval == iov_totallen(message)) + zlog_warn("recvmsg read full buffer size: %d", retval); + + /* source address */ + assert(src); + memcpy(src, &src_sin6.sin6_addr, sizeof(struct in6_addr)); + + /* destination address */ + if (ifindex) + *ifindex = pktinfo->ipi6_ifindex; + if (dst) + memcpy(dst, &pktinfo->ipi6_addr, sizeof(struct in6_addr)); + + return retval; } - - diff --git a/ospf6d/ospf6_network.h b/ospf6d/ospf6_network.h index 690901ca0..7c7c155fb 100644 --- a/ospf6d/ospf6_network.h +++ b/ospf6d/ospf6_network.h @@ -21,19 +21,16 @@ #ifndef OSPF6_NETWORK_H #define OSPF6_NETWORK_H - - extern int ospf6_sock; extern struct in6_addr allspfrouters6; extern struct in6_addr alldrouters6; -extern int ospf6_serv_sock (void); -extern int ospf6_sso (ifindex_t ifindex, struct in6_addr *group, int option); +extern int ospf6_serv_sock(void); +extern int ospf6_sso(ifindex_t ifindex, struct in6_addr *group, int option); -extern int ospf6_sendmsg (struct in6_addr *, struct in6_addr *, - ifindex_t *, struct iovec *); -extern int ospf6_recvmsg (struct in6_addr *, struct in6_addr *, - ifindex_t *, struct iovec *); +extern int ospf6_sendmsg(struct in6_addr *, struct in6_addr *, ifindex_t *, + struct iovec *); +extern int ospf6_recvmsg(struct in6_addr *, struct in6_addr *, ifindex_t *, + struct iovec *); #endif /* OSPF6_NETWORK_H */ - diff --git a/ospf6d/ospf6_proto.c b/ospf6d/ospf6_proto.c index 1538c891c..d0ab67655 100644 --- a/ospf6d/ospf6_proto.c +++ b/ospf6d/ospf6_proto.c @@ -24,60 +24,53 @@ #include "ospf6_proto.h" -void -ospf6_prefix_apply_mask (struct ospf6_prefix *op) +void ospf6_prefix_apply_mask(struct ospf6_prefix *op) { - u_char *pnt, mask; - int index, offset; + u_char *pnt, mask; + int index, offset; - pnt = (u_char *)((caddr_t) op + sizeof (struct ospf6_prefix)); - index = op->prefix_length / 8; - offset = op->prefix_length % 8; - mask = 0xff << (8 - offset); + pnt = (u_char *)((caddr_t)op + sizeof(struct ospf6_prefix)); + index = op->prefix_length / 8; + offset = op->prefix_length % 8; + mask = 0xff << (8 - offset); - if (index > 16) - { - zlog_warn ("Prefix length too long: %d", op->prefix_length); - return; - } + if (index > 16) { + zlog_warn("Prefix length too long: %d", op->prefix_length); + return; + } - /* nonzero mask means no check for this byte because if it contains - * prefix bits it must be there for us to write */ - if (mask) - pnt[index++] &= mask; + /* nonzero mask means no check for this byte because if it contains + * prefix bits it must be there for us to write */ + if (mask) + pnt[index++] &= mask; - while (index < OSPF6_PREFIX_SPACE (op->prefix_length)) - pnt[index++] = 0; + while (index < OSPF6_PREFIX_SPACE(op->prefix_length)) + pnt[index++] = 0; } -void -ospf6_prefix_options_printbuf (u_int8_t prefix_options, char *buf, int size) +void ospf6_prefix_options_printbuf(u_int8_t prefix_options, char *buf, int size) { - snprintf (buf, size, "xxx"); + snprintf(buf, size, "xxx"); } -void -ospf6_capability_printbuf (char capability, char *buf, int size) +void ospf6_capability_printbuf(char capability, char *buf, int size) { - char w, v, e, b; - w = (capability & OSPF6_ROUTER_BIT_W ? 'W' : '-'); - v = (capability & OSPF6_ROUTER_BIT_V ? 'V' : '-'); - e = (capability & OSPF6_ROUTER_BIT_E ? 'E' : '-'); - b = (capability & OSPF6_ROUTER_BIT_B ? 'B' : '-'); - snprintf (buf, size, "----%c%c%c%c", w, v, e, b); + char w, v, e, b; + w = (capability & OSPF6_ROUTER_BIT_W ? 'W' : '-'); + v = (capability & OSPF6_ROUTER_BIT_V ? 'V' : '-'); + e = (capability & OSPF6_ROUTER_BIT_E ? 'E' : '-'); + b = (capability & OSPF6_ROUTER_BIT_B ? 'B' : '-'); + snprintf(buf, size, "----%c%c%c%c", w, v, e, b); } -void -ospf6_options_printbuf (u_char *options, char *buf, int size) +void ospf6_options_printbuf(u_char *options, char *buf, int size) { - const char *dc, *r, *n, *mc, *e, *v6; - dc = (OSPF6_OPT_ISSET (options, OSPF6_OPT_DC) ? "DC" : "--"); - r = (OSPF6_OPT_ISSET (options, OSPF6_OPT_R) ? "R" : "-" ); - n = (OSPF6_OPT_ISSET (options, OSPF6_OPT_N) ? "N" : "-" ); - mc = (OSPF6_OPT_ISSET (options, OSPF6_OPT_MC) ? "MC" : "--"); - e = (OSPF6_OPT_ISSET (options, OSPF6_OPT_E) ? "E" : "-" ); - v6 = (OSPF6_OPT_ISSET (options, OSPF6_OPT_V6) ? "V6" : "--"); - snprintf (buf, size, "%s|%s|%s|%s|%s|%s", dc, r, n, mc, e, v6); + const char *dc, *r, *n, *mc, *e, *v6; + dc = (OSPF6_OPT_ISSET(options, OSPF6_OPT_DC) ? "DC" : "--"); + r = (OSPF6_OPT_ISSET(options, OSPF6_OPT_R) ? "R" : "-"); + n = (OSPF6_OPT_ISSET(options, OSPF6_OPT_N) ? "N" : "-"); + mc = (OSPF6_OPT_ISSET(options, OSPF6_OPT_MC) ? "MC" : "--"); + e = (OSPF6_OPT_ISSET(options, OSPF6_OPT_E) ? "E" : "-"); + v6 = (OSPF6_OPT_ISSET(options, OSPF6_OPT_V6) ? "V6" : "--"); + snprintf(buf, size, "%s|%s|%s|%s|%s|%s", dc, r, n, mc, e, v6); } - - diff --git a/ospf6d/ospf6_proto.h b/ospf6d/ospf6_proto.h index e4f29aa3e..174b5a4f0 100644 --- a/ospf6d/ospf6_proto.h +++ b/ospf6d/ospf6_proto.h @@ -52,17 +52,16 @@ /* OSPF6 Prefix */ #define OSPF6_PREFIX_MIN_SIZE 4U /* .length == 0 */ -struct ospf6_prefix -{ - u_int8_t prefix_length; - u_int8_t prefix_options; - union { - u_int16_t _prefix_metric; - u_int16_t _prefix_referenced_lstype; - } u; +struct ospf6_prefix { + u_int8_t prefix_length; + u_int8_t prefix_options; + union { + u_int16_t _prefix_metric; + u_int16_t _prefix_referenced_lstype; + } u; #define prefix_metric u._prefix_metric #define prefix_refer_lstype u._prefix_referenced_lstype - /* followed by one address_prefix */ + /* followed by one address_prefix */ }; #define OSPF6_PREFIX_OPTION_NU (1 << 0) /* No Unicast */ @@ -77,24 +76,24 @@ struct ospf6_prefix #define OSPF6_PREFIX_SPACE(x) ((((x) + 31) / 32) * 4) /* size_t OSPF6_PREFIX_SIZE (struct ospf6_prefix *); */ -#define OSPF6_PREFIX_SIZE(x) \ - (OSPF6_PREFIX_SPACE ((x)->prefix_length) + sizeof (struct ospf6_prefix)) +#define OSPF6_PREFIX_SIZE(x) \ + (OSPF6_PREFIX_SPACE((x)->prefix_length) + sizeof(struct ospf6_prefix)) /* struct ospf6_prefix *OSPF6_PREFIX_NEXT (struct ospf6_prefix *); */ -#define OSPF6_PREFIX_NEXT(x) \ - ((struct ospf6_prefix *)((caddr_t)(x) + OSPF6_PREFIX_SIZE (x))) - -#define ospf6_prefix_in6_addr(in6, op) \ -do { \ - memset (in6, 0, sizeof (struct in6_addr)); \ - memcpy (in6, (caddr_t) (op) + sizeof (struct ospf6_prefix), \ - OSPF6_PREFIX_SPACE ((op)->prefix_length)); \ -} while (0) - -extern void ospf6_prefix_apply_mask (struct ospf6_prefix *op); -extern void ospf6_prefix_options_printbuf (u_int8_t prefix_options, - char *buf, int size); -extern void ospf6_capability_printbuf (char capability, char *buf, int size); -extern void ospf6_options_printbuf (u_char *options, char *buf, int size); +#define OSPF6_PREFIX_NEXT(x) \ + ((struct ospf6_prefix *)((caddr_t)(x) + OSPF6_PREFIX_SIZE(x))) + +#define ospf6_prefix_in6_addr(in6, op) \ + do { \ + memset(in6, 0, sizeof(struct in6_addr)); \ + memcpy(in6, (caddr_t)(op) + sizeof(struct ospf6_prefix), \ + OSPF6_PREFIX_SPACE((op)->prefix_length)); \ + } while (0) + +extern void ospf6_prefix_apply_mask(struct ospf6_prefix *op); +extern void ospf6_prefix_options_printbuf(u_int8_t prefix_options, char *buf, + int size); +extern void ospf6_capability_printbuf(char capability, char *buf, int size); +extern void ospf6_options_printbuf(u_char *options, char *buf, int size); #endif /* OSPF6_PROTO_H */ diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index d223651f4..5e8fd0e15 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -40,1522 +40,1409 @@ unsigned char conf_debug_ospf6_route = 0; -static char * -ospf6_route_table_name (struct ospf6_route_table *table) +static char *ospf6_route_table_name(struct ospf6_route_table *table) { - static char name[64]; - switch (table->scope_type) - { - case OSPF6_SCOPE_TYPE_GLOBAL: - { - switch (table->table_type) - { - case OSPF6_TABLE_TYPE_ROUTES: - snprintf (name, sizeof (name), "global route table"); - break; - case OSPF6_TABLE_TYPE_BORDER_ROUTERS: - snprintf (name, sizeof (name), "global brouter table"); - break; - case OSPF6_TABLE_TYPE_EXTERNAL_ROUTES: - snprintf (name, sizeof (name), "global external table"); - break; - default: - snprintf (name, sizeof (name), "global unknown table"); - break; - } - } - break; - - case OSPF6_SCOPE_TYPE_AREA: - { - struct ospf6_area *oa = (struct ospf6_area *) table->scope; - switch (table->table_type) - { - case OSPF6_TABLE_TYPE_SPF_RESULTS: - snprintf (name, sizeof (name), - "area %s spf table", oa->name); - break; - case OSPF6_TABLE_TYPE_ROUTES: - snprintf (name, sizeof (name), - "area %s route table", oa->name); - break; - case OSPF6_TABLE_TYPE_PREFIX_RANGES: - snprintf (name, sizeof (name), - "area %s range table", oa->name); - break; - case OSPF6_TABLE_TYPE_SUMMARY_PREFIXES: - snprintf (name, sizeof (name), - "area %s summary prefix table", oa->name); - break; - case OSPF6_TABLE_TYPE_SUMMARY_ROUTERS: - snprintf (name, sizeof (name), - "area %s summary router table", oa->name); - break; - default: - snprintf (name, sizeof (name), - "area %s unknown table", oa->name); - break; - } - } - break; - - case OSPF6_SCOPE_TYPE_INTERFACE: - { - struct ospf6_interface *oi = (struct ospf6_interface *) table->scope; - switch (table->table_type) - { - case OSPF6_TABLE_TYPE_CONNECTED_ROUTES: - snprintf (name, sizeof (name), "interface %s connected table", - oi->interface->name); - break; - default: - snprintf (name, sizeof (name), "interface %s unknown table", - oi->interface->name); - break; - } - } - break; - - default: - { - switch (table->table_type) - { - case OSPF6_TABLE_TYPE_SPF_RESULTS: - snprintf (name, sizeof (name), "temporary spf table"); - break; - default: - snprintf (name, sizeof (name), "temporary unknown table"); - break; - } - } - break; - } - return name; + static char name[64]; + switch (table->scope_type) { + case OSPF6_SCOPE_TYPE_GLOBAL: { + switch (table->table_type) { + case OSPF6_TABLE_TYPE_ROUTES: + snprintf(name, sizeof(name), "global route table"); + break; + case OSPF6_TABLE_TYPE_BORDER_ROUTERS: + snprintf(name, sizeof(name), "global brouter table"); + break; + case OSPF6_TABLE_TYPE_EXTERNAL_ROUTES: + snprintf(name, sizeof(name), "global external table"); + break; + default: + snprintf(name, sizeof(name), "global unknown table"); + break; + } + } break; + + case OSPF6_SCOPE_TYPE_AREA: { + struct ospf6_area *oa = (struct ospf6_area *)table->scope; + switch (table->table_type) { + case OSPF6_TABLE_TYPE_SPF_RESULTS: + snprintf(name, sizeof(name), "area %s spf table", + oa->name); + break; + case OSPF6_TABLE_TYPE_ROUTES: + snprintf(name, sizeof(name), "area %s route table", + oa->name); + break; + case OSPF6_TABLE_TYPE_PREFIX_RANGES: + snprintf(name, sizeof(name), "area %s range table", + oa->name); + break; + case OSPF6_TABLE_TYPE_SUMMARY_PREFIXES: + snprintf(name, sizeof(name), + "area %s summary prefix table", oa->name); + break; + case OSPF6_TABLE_TYPE_SUMMARY_ROUTERS: + snprintf(name, sizeof(name), + "area %s summary router table", oa->name); + break; + default: + snprintf(name, sizeof(name), "area %s unknown table", + oa->name); + break; + } + } break; + + case OSPF6_SCOPE_TYPE_INTERFACE: { + struct ospf6_interface *oi = + (struct ospf6_interface *)table->scope; + switch (table->table_type) { + case OSPF6_TABLE_TYPE_CONNECTED_ROUTES: + snprintf(name, sizeof(name), + "interface %s connected table", + oi->interface->name); + break; + default: + snprintf(name, sizeof(name), + "interface %s unknown table", + oi->interface->name); + break; + } + } break; + + default: { + switch (table->table_type) { + case OSPF6_TABLE_TYPE_SPF_RESULTS: + snprintf(name, sizeof(name), "temporary spf table"); + break; + default: + snprintf(name, sizeof(name), "temporary unknown table"); + break; + } + } break; + } + return name; } -void -ospf6_linkstate_prefix (u_int32_t adv_router, u_int32_t id, - struct prefix *prefix) +void ospf6_linkstate_prefix(u_int32_t adv_router, u_int32_t id, + struct prefix *prefix) { - memset (prefix, 0, sizeof (struct prefix)); - prefix->family = AF_INET6; - prefix->prefixlen = 64; - memcpy (&prefix->u.prefix6.s6_addr[0], &adv_router, 4); - memcpy (&prefix->u.prefix6.s6_addr[4], &id, 4); + memset(prefix, 0, sizeof(struct prefix)); + prefix->family = AF_INET6; + prefix->prefixlen = 64; + memcpy(&prefix->u.prefix6.s6_addr[0], &adv_router, 4); + memcpy(&prefix->u.prefix6.s6_addr[4], &id, 4); } -void -ospf6_linkstate_prefix2str (struct prefix *prefix, char *buf, int size) +void ospf6_linkstate_prefix2str(struct prefix *prefix, char *buf, int size) { - u_int32_t adv_router, id; - char adv_router_str[16], id_str[16]; - memcpy (&adv_router, &prefix->u.prefix6.s6_addr[0], 4); - memcpy (&id, &prefix->u.prefix6.s6_addr[4], 4); - inet_ntop (AF_INET, &adv_router, adv_router_str, sizeof (adv_router_str)); - inet_ntop (AF_INET, &id, id_str, sizeof (id_str)); - if (ntohl (id)) - snprintf (buf, size, "%s Net-ID: %s", adv_router_str, id_str); - else - snprintf (buf, size, "%s", adv_router_str); + u_int32_t adv_router, id; + char adv_router_str[16], id_str[16]; + memcpy(&adv_router, &prefix->u.prefix6.s6_addr[0], 4); + memcpy(&id, &prefix->u.prefix6.s6_addr[4], 4); + inet_ntop(AF_INET, &adv_router, adv_router_str, sizeof(adv_router_str)); + inet_ntop(AF_INET, &id, id_str, sizeof(id_str)); + if (ntohl(id)) + snprintf(buf, size, "%s Net-ID: %s", adv_router_str, id_str); + else + snprintf(buf, size, "%s", adv_router_str); } /* Global strings for logging */ -const char *ospf6_dest_type_str[OSPF6_DEST_TYPE_MAX] = -{ "Unknown", "Router", "Network", "Discard", "Linkstate", "AddressRange", }; +const char *ospf6_dest_type_str[OSPF6_DEST_TYPE_MAX] = { + "Unknown", "Router", "Network", "Discard", "Linkstate", "AddressRange", +}; -const char *ospf6_dest_type_substr[OSPF6_DEST_TYPE_MAX] = -{ "?", "R", "N", "D", "L", "A", }; +const char *ospf6_dest_type_substr[OSPF6_DEST_TYPE_MAX] = { + "?", "R", "N", "D", "L", "A", +}; -const char *ospf6_path_type_str[OSPF6_PATH_TYPE_MAX] = -{ "Unknown", "Intra-Area", "Inter-Area", "External-1", "External-2", }; +const char *ospf6_path_type_str[OSPF6_PATH_TYPE_MAX] = { + "Unknown", "Intra-Area", "Inter-Area", "External-1", "External-2", +}; -const char *ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX] = -{ "??", "IA", "IE", "E1", "E2", }; +const char *ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX] = { + "??", "IA", "IE", "E1", "E2", +}; -struct ospf6_nexthop * -ospf6_nexthop_create (void) +struct ospf6_nexthop *ospf6_nexthop_create(void) { - struct ospf6_nexthop *nh; + struct ospf6_nexthop *nh; - nh = XCALLOC (MTYPE_OSPF6_NEXTHOP, sizeof (struct ospf6_nexthop)); - return nh; + nh = XCALLOC(MTYPE_OSPF6_NEXTHOP, sizeof(struct ospf6_nexthop)); + return nh; } -void -ospf6_nexthop_delete (struct ospf6_nexthop *nh) +void ospf6_nexthop_delete(struct ospf6_nexthop *nh) { - if (nh) - XFREE (MTYPE_OSPF6_NEXTHOP, nh); + if (nh) + XFREE(MTYPE_OSPF6_NEXTHOP, nh); } -void -ospf6_free_nexthops (struct list *nh_list) +void ospf6_free_nexthops(struct list *nh_list) { - struct ospf6_nexthop *nh; - struct listnode *node, *nnode; - - if (nh_list) - { - for (ALL_LIST_ELEMENTS (nh_list, node, nnode, nh)) - ospf6_nexthop_delete (nh); - } + struct ospf6_nexthop *nh; + struct listnode *node, *nnode; + + if (nh_list) { + for (ALL_LIST_ELEMENTS(nh_list, node, nnode, nh)) + ospf6_nexthop_delete(nh); + } } -void -ospf6_clear_nexthops (struct list *nh_list) +void ospf6_clear_nexthops(struct list *nh_list) { - struct listnode *node; - struct ospf6_nexthop *nh; - - if (nh_list) - { - for (ALL_LIST_ELEMENTS_RO (nh_list, node, nh)) - ospf6_nexthop_clear (nh); - } + struct listnode *node; + struct ospf6_nexthop *nh; + + if (nh_list) { + for (ALL_LIST_ELEMENTS_RO(nh_list, node, nh)) + ospf6_nexthop_clear(nh); + } } static struct ospf6_nexthop * -ospf6_route_find_nexthop (struct list *nh_list, struct ospf6_nexthop *nh_match) +ospf6_route_find_nexthop(struct list *nh_list, struct ospf6_nexthop *nh_match) { - struct listnode *node; - struct ospf6_nexthop *nh; - - if (nh_list && nh_match) - { - for (ALL_LIST_ELEMENTS_RO (nh_list, node, nh)) - { - if (ospf6_nexthop_is_same (nh, nh_match)) - return (nh); + struct listnode *node; + struct ospf6_nexthop *nh; + + if (nh_list && nh_match) { + for (ALL_LIST_ELEMENTS_RO(nh_list, node, nh)) { + if (ospf6_nexthop_is_same(nh, nh_match)) + return (nh); + } } - } - return (NULL); + return (NULL); } -void -ospf6_copy_nexthops (struct list *dst, struct list *src) +void ospf6_copy_nexthops(struct list *dst, struct list *src) { - struct ospf6_nexthop *nh_new, *nh; - struct listnode *node; - - if (dst && src) - { - for (ALL_LIST_ELEMENTS_RO (src, node, nh)) - { - if (ospf6_nexthop_is_set (nh)) - { - nh_new = ospf6_nexthop_create (); - ospf6_nexthop_copy (nh_new, nh); - listnode_add (dst, nh_new); - } + struct ospf6_nexthop *nh_new, *nh; + struct listnode *node; + + if (dst && src) { + for (ALL_LIST_ELEMENTS_RO(src, node, nh)) { + if (ospf6_nexthop_is_set(nh)) { + nh_new = ospf6_nexthop_create(); + ospf6_nexthop_copy(nh_new, nh); + listnode_add(dst, nh_new); + } + } } - } } -void -ospf6_merge_nexthops (struct list *dst, struct list *src) +void ospf6_merge_nexthops(struct list *dst, struct list *src) { - struct listnode *node; - struct ospf6_nexthop *nh, *nh_new; - - if (src && dst) - { - for (ALL_LIST_ELEMENTS_RO (src, node, nh)) - { - if (!ospf6_route_find_nexthop (dst, nh)) - { - nh_new = ospf6_nexthop_create (); - ospf6_nexthop_copy (nh_new, nh); - listnode_add (dst, nh_new); - } + struct listnode *node; + struct ospf6_nexthop *nh, *nh_new; + + if (src && dst) { + for (ALL_LIST_ELEMENTS_RO(src, node, nh)) { + if (!ospf6_route_find_nexthop(dst, nh)) { + nh_new = ospf6_nexthop_create(); + ospf6_nexthop_copy(nh_new, nh); + listnode_add(dst, nh_new); + } + } } - } } -int -ospf6_route_cmp_nexthops (struct ospf6_route *a, struct ospf6_route *b) +int ospf6_route_cmp_nexthops(struct ospf6_route *a, struct ospf6_route *b) { - struct listnode *anode, *bnode; - struct ospf6_nexthop *anh, *bnh; - - if (a && b) - { - if (listcount(a->nh_list) == listcount(b->nh_list)) - { - for (ALL_LIST_ELEMENTS_RO (a->nh_list, anode, anh)) - { - for (ALL_LIST_ELEMENTS_RO (b->nh_list, bnode, bnh)) - if (!ospf6_nexthop_is_same (anh, bnh)) - return (1); - } - return (0); + struct listnode *anode, *bnode; + struct ospf6_nexthop *anh, *bnh; + + if (a && b) { + if (listcount(a->nh_list) == listcount(b->nh_list)) { + for (ALL_LIST_ELEMENTS_RO(a->nh_list, anode, anh)) { + for (ALL_LIST_ELEMENTS_RO(b->nh_list, bnode, + bnh)) + if (!ospf6_nexthop_is_same(anh, bnh)) + return (1); + } + return (0); + } else + return (1); } - else + /* One of the routes doesn't exist ? */ return (1); - } - /* One of the routes doesn't exist ? */ - return (1); } -int -ospf6_num_nexthops (struct list *nh_list) +int ospf6_num_nexthops(struct list *nh_list) { - return (listcount(nh_list)); + return (listcount(nh_list)); } -void -ospf6_add_nexthop (struct list *nh_list, int ifindex, - struct in6_addr *addr) +void ospf6_add_nexthop(struct list *nh_list, int ifindex, struct in6_addr *addr) { - struct ospf6_nexthop *nh; - struct ospf6_nexthop nh_match; - - if (nh_list) - { - nh_match.ifindex = ifindex; - if (addr != NULL) - memcpy (&nh_match.address, addr, sizeof (struct in6_addr)); - else - memset (&nh_match.address, 0, sizeof (struct in6_addr)); - - if (!ospf6_route_find_nexthop (nh_list, &nh_match)) - { - nh = ospf6_nexthop_create(); - ospf6_nexthop_copy (nh, &nh_match); - listnode_add (nh_list, nh); + struct ospf6_nexthop *nh; + struct ospf6_nexthop nh_match; + + if (nh_list) { + nh_match.ifindex = ifindex; + if (addr != NULL) + memcpy(&nh_match.address, addr, + sizeof(struct in6_addr)); + else + memset(&nh_match.address, 0, sizeof(struct in6_addr)); + + if (!ospf6_route_find_nexthop(nh_list, &nh_match)) { + nh = ospf6_nexthop_create(); + ospf6_nexthop_copy(nh, &nh_match); + listnode_add(nh_list, nh); + } } - } } -void -ospf6_route_zebra_copy_nexthops (struct ospf6_route *route, - ifindex_t *ifindexes, - struct in6_addr **nexthop_addr, - int entries) +void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route, + ifindex_t *ifindexes, + struct in6_addr **nexthop_addr, + int entries) { - struct ospf6_nexthop *nh; - struct listnode *node; - char buf[64]; - int i; - - if (route) - { - i = 0; - for (ALL_LIST_ELEMENTS_RO (route->nh_list, node, nh)) - { - if (IS_OSPF6_DEBUG_ZEBRA (SEND)) - { - const char *ifname; - inet_ntop (AF_INET6, &nh->address, buf, sizeof (buf)); - ifname = ifindex2ifname (nh->ifindex, VRF_DEFAULT); - zlog_debug (" nexthop: %s%%%.*s(%d)", buf, IFNAMSIZ, ifname, - nh->ifindex); - } - if (i < entries) - { - nexthop_addr[i] = &nh->address; - ifindexes[i] = nh->ifindex; - i++; - } - else - { - return; - } + struct ospf6_nexthop *nh; + struct listnode *node; + char buf[64]; + int i; + + if (route) { + i = 0; + for (ALL_LIST_ELEMENTS_RO(route->nh_list, node, nh)) { + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) { + const char *ifname; + inet_ntop(AF_INET6, &nh->address, buf, + sizeof(buf)); + ifname = ifindex2ifname(nh->ifindex, + VRF_DEFAULT); + zlog_debug(" nexthop: %s%%%.*s(%d)", buf, + IFNAMSIZ, ifname, nh->ifindex); + } + if (i < entries) { + nexthop_addr[i] = &nh->address; + ifindexes[i] = nh->ifindex; + i++; + } else { + return; + } + } } - } } -int -ospf6_route_get_first_nh_index (struct ospf6_route *route) +int ospf6_route_get_first_nh_index(struct ospf6_route *route) { - struct ospf6_nexthop *nh; + struct ospf6_nexthop *nh; - if (route) - { - if ((nh = (struct ospf6_nexthop *)listhead (route->nh_list))) - return (nh->ifindex); - } + if (route) { + if ((nh = (struct ospf6_nexthop *)listhead(route->nh_list))) + return (nh->ifindex); + } - return (-1); + return (-1); } -struct ospf6_route * -ospf6_route_create (void) +struct ospf6_route *ospf6_route_create(void) { - struct ospf6_route *route; - route = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route)); - route->nh_list = list_new(); - return route; + struct ospf6_route *route; + route = XCALLOC(MTYPE_OSPF6_ROUTE, sizeof(struct ospf6_route)); + route->nh_list = list_new(); + return route; } -void -ospf6_route_delete (struct ospf6_route *route) +void ospf6_route_delete(struct ospf6_route *route) { - if (route) - { - ospf6_free_nexthops (route->nh_list); - list_free (route->nh_list); - XFREE (MTYPE_OSPF6_ROUTE, route); - } + if (route) { + ospf6_free_nexthops(route->nh_list); + list_free(route->nh_list); + XFREE(MTYPE_OSPF6_ROUTE, route); + } } -struct ospf6_route * -ospf6_route_copy (struct ospf6_route *route) +struct ospf6_route *ospf6_route_copy(struct ospf6_route *route) { - struct ospf6_route *new; - - new = ospf6_route_create (); - new->type = route->type; - memcpy (&new->prefix, &route->prefix, sizeof (struct prefix)); - new->installed = route->installed; - new->changed = route->changed; - new->flag = route->flag; - new->route_option = route->route_option; - new->linkstate_id = route->linkstate_id; - new->path = route->path; - ospf6_copy_nexthops (new->nh_list, route->nh_list); - new->rnode = NULL; - new->prev = NULL; - new->next = NULL; - new->table = NULL; - new->lock = 0; - return new; + struct ospf6_route *new; + + new = ospf6_route_create(); + new->type = route->type; + memcpy(&new->prefix, &route->prefix, sizeof(struct prefix)); + new->installed = route->installed; + new->changed = route->changed; + new->flag = route->flag; + new->route_option = route->route_option; + new->linkstate_id = route->linkstate_id; + new->path = route->path; + ospf6_copy_nexthops(new->nh_list, route->nh_list); + new->rnode = NULL; + new->prev = NULL; + new->next = NULL; + new->table = NULL; + new->lock = 0; + return new; } -void -ospf6_route_lock (struct ospf6_route *route) +void ospf6_route_lock(struct ospf6_route *route) { - route->lock++; + route->lock++; } -void -ospf6_route_unlock (struct ospf6_route *route) +void ospf6_route_unlock(struct ospf6_route *route) { - assert (route->lock > 0); - route->lock--; - if (route->lock == 0) - { - /* Can't detach from the table until here - because ospf6_route_next () will use - the 'route->table' pointer for logging */ - route->table = NULL; - ospf6_route_delete (route); - } + assert(route->lock > 0); + route->lock--; + if (route->lock == 0) { + /* Can't detach from the table until here + because ospf6_route_next () will use + the 'route->table' pointer for logging */ + route->table = NULL; + ospf6_route_delete(route); + } } /* Route compare function. If ra is more preferred, it returns less than 0. If rb is more preferred returns greater than 0. Otherwise (neither one is preferred), returns 0 */ -int -ospf6_route_cmp (struct ospf6_route *ra, struct ospf6_route *rb) +int ospf6_route_cmp(struct ospf6_route *ra, struct ospf6_route *rb) { - assert (ospf6_route_is_same (ra, rb)); - assert (OSPF6_PATH_TYPE_NONE < ra->path.type && - ra->path.type < OSPF6_PATH_TYPE_MAX); - assert (OSPF6_PATH_TYPE_NONE < rb->path.type && - rb->path.type < OSPF6_PATH_TYPE_MAX); - - if (ra->type != rb->type) - return (ra->type - rb->type); - - if (ra->path.area_id != rb->path.area_id) - return (ntohl (ra->path.area_id) - ntohl (rb->path.area_id)); - - if (ra->path.type != rb->path.type) - return (ra->path.type - rb->path.type); - - if (ra->path.type == OSPF6_PATH_TYPE_EXTERNAL2) - { - if (ra->path.u.cost_e2 != rb->path.u.cost_e2) - return (ra->path.u.cost_e2 - rb->path.u.cost_e2); - } - else - { - if (ra->path.cost != rb->path.cost) - return (ra->path.cost - rb->path.cost); - } - - return 0; + assert(ospf6_route_is_same(ra, rb)); + assert(OSPF6_PATH_TYPE_NONE < ra->path.type + && ra->path.type < OSPF6_PATH_TYPE_MAX); + assert(OSPF6_PATH_TYPE_NONE < rb->path.type + && rb->path.type < OSPF6_PATH_TYPE_MAX); + + if (ra->type != rb->type) + return (ra->type - rb->type); + + if (ra->path.area_id != rb->path.area_id) + return (ntohl(ra->path.area_id) - ntohl(rb->path.area_id)); + + if (ra->path.type != rb->path.type) + return (ra->path.type - rb->path.type); + + if (ra->path.type == OSPF6_PATH_TYPE_EXTERNAL2) { + if (ra->path.u.cost_e2 != rb->path.u.cost_e2) + return (ra->path.u.cost_e2 - rb->path.u.cost_e2); + } else { + if (ra->path.cost != rb->path.cost) + return (ra->path.cost - rb->path.cost); + } + + return 0; } -struct ospf6_route * -ospf6_route_lookup (struct prefix *prefix, - struct ospf6_route_table *table) +struct ospf6_route *ospf6_route_lookup(struct prefix *prefix, + struct ospf6_route_table *table) { - struct route_node *node; - struct ospf6_route *route; + struct route_node *node; + struct ospf6_route *route; - node = route_node_lookup (table->table, prefix); - if (node == NULL) - return NULL; + node = route_node_lookup(table->table, prefix); + if (node == NULL) + return NULL; - route = (struct ospf6_route *) node->info; - return route; + route = (struct ospf6_route *)node->info; + return route; } struct ospf6_route * -ospf6_route_lookup_identical (struct ospf6_route *route, - struct ospf6_route_table *table) +ospf6_route_lookup_identical(struct ospf6_route *route, + struct ospf6_route_table *table) { - struct ospf6_route *target; - - for (target = ospf6_route_lookup (&route->prefix, table); - target; target = target->next) - { - if (ospf6_route_is_identical (target, route)) - return target; - } - return NULL; + struct ospf6_route *target; + + for (target = ospf6_route_lookup(&route->prefix, table); target; + target = target->next) { + if (ospf6_route_is_identical(target, route)) + return target; + } + return NULL; } struct ospf6_route * -ospf6_route_lookup_bestmatch (struct prefix *prefix, - struct ospf6_route_table *table) +ospf6_route_lookup_bestmatch(struct prefix *prefix, + struct ospf6_route_table *table) { - struct route_node *node; - struct ospf6_route *route; + struct route_node *node; + struct ospf6_route *route; - node = route_node_match (table->table, prefix); - if (node == NULL) - return NULL; - route_unlock_node (node); + node = route_node_match(table->table, prefix); + if (node == NULL) + return NULL; + route_unlock_node(node); - route = (struct ospf6_route *) node->info; - return route; + route = (struct ospf6_route *)node->info; + return route; } #ifdef DEBUG -static void -route_table_assert (struct ospf6_route_table *table) +static void route_table_assert(struct ospf6_route_table *table) { - struct ospf6_route *prev, *r, *next; - char buf[PREFIX2STR_BUFFER]; - unsigned int link_error = 0, num = 0; - - r = ospf6_route_head (table); - prev = NULL; - while (r) - { - if (r->prev != prev) - link_error++; - - next = ospf6_route_next (r); - - if (r->next != next) - link_error++; - - prev = r; - r = next; - } - - for (r = ospf6_route_head (table); r; r = ospf6_route_next (r)) - num++; - - if (link_error == 0 && num == table->count) - return; - - zlog_err ("PANIC !!"); - zlog_err ("Something has gone wrong with ospf6_route_table[%p]", table); - zlog_debug ("table count = %d, real number = %d", table->count, num); - zlog_debug ("DUMP START"); - for (r = ospf6_route_head (table); r; r = ospf6_route_next (r)) - { - prefix2str (&r->prefix, buf, sizeof (buf)); - zlog_info ("%p<-[%p]->%p : %s", r->prev, r, r->next, buf); - } - zlog_debug ("DUMP END"); - - assert (link_error == 0 && num == table->count); + struct ospf6_route *prev, *r, *next; + char buf[PREFIX2STR_BUFFER]; + unsigned int link_error = 0, num = 0; + + r = ospf6_route_head(table); + prev = NULL; + while (r) { + if (r->prev != prev) + link_error++; + + next = ospf6_route_next(r); + + if (r->next != next) + link_error++; + + prev = r; + r = next; + } + + for (r = ospf6_route_head(table); r; r = ospf6_route_next(r)) + num++; + + if (link_error == 0 && num == table->count) + return; + + zlog_err("PANIC !!"); + zlog_err("Something has gone wrong with ospf6_route_table[%p]", table); + zlog_debug("table count = %d, real number = %d", table->count, num); + zlog_debug("DUMP START"); + for (r = ospf6_route_head(table); r; r = ospf6_route_next(r)) { + prefix2str(&r->prefix, buf, sizeof(buf)); + zlog_info("%p<-[%p]->%p : %s", r->prev, r, r->next, buf); + } + zlog_debug("DUMP END"); + + assert(link_error == 0 && num == table->count); } #define ospf6_route_table_assert(t) (route_table_assert (t)) #else #define ospf6_route_table_assert(t) ((void) 0) #endif /*DEBUG*/ -struct ospf6_route * -ospf6_route_add (struct ospf6_route *route, - struct ospf6_route_table *table) +struct ospf6_route *ospf6_route_add(struct ospf6_route *route, + struct ospf6_route_table *table) { - struct route_node *node, *nextnode, *prevnode; - struct ospf6_route *current = NULL; - struct ospf6_route *prev = NULL, *old = NULL, *next = NULL; - char buf[PREFIX2STR_BUFFER]; - struct timeval now; - - assert (route->rnode == NULL); - assert (route->lock == 0); - assert (route->next == NULL); - assert (route->prev == NULL); - - if (route->type == OSPF6_DEST_TYPE_LINKSTATE) - ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf)); - else - prefix2str (&route->prefix, buf, sizeof (buf)); - - if (IS_OSPF6_DEBUG_ROUTE (MEMORY)) - zlog_debug ("%s %p: route add %p: %s", ospf6_route_table_name (table), - (void *)table, (void *)route, buf); - else if (IS_OSPF6_DEBUG_ROUTE (TABLE)) - zlog_debug ("%s: route add: %s", ospf6_route_table_name (table), buf); - - monotime(&now); - - node = route_node_get (table->table, &route->prefix); - route->rnode = node; - - /* find place to insert */ - for (current = node->info; current; current = current->next) - { - if (! ospf6_route_is_same (current, route)) - next = current; - else if (current->type != route->type) - prev = current; - else if (ospf6_route_is_same_origin (current, route)) - old = current; - else if (ospf6_route_cmp (current, route) > 0) - next = current; - else - prev = current; - - if (old || next) - break; - } - - if (old) - { - /* if route does not actually change, return unchanged */ - if (ospf6_route_is_identical (old, route)) - { - if (IS_OSPF6_DEBUG_ROUTE (MEMORY)) - zlog_debug ("%s %p: route add %p: needless update of %p", - ospf6_route_table_name (table), - (void *)table, (void *)route, (void *)old); - else if (IS_OSPF6_DEBUG_ROUTE (TABLE)) - zlog_debug ("%s: route add: needless update", - ospf6_route_table_name (table)); - - ospf6_route_delete (route); - SET_FLAG (old->flag, OSPF6_ROUTE_ADD); - ospf6_route_table_assert (table); - - return old; - } - - if (IS_OSPF6_DEBUG_ROUTE (MEMORY)) - zlog_debug ("%s %p: route add %p: update of %p", - ospf6_route_table_name (table), - (void *)table, (void *)route, (void *)old); - else if (IS_OSPF6_DEBUG_ROUTE (TABLE)) - zlog_debug ("%s: route add: update", - ospf6_route_table_name (table)); - - /* replace old one if exists */ - if (node->info == old) - { - node->info = route; - SET_FLAG (route->flag, OSPF6_ROUTE_BEST); - } - - if (old->prev) - old->prev->next = route; - route->prev = old->prev; - if (old->next) - old->next->prev = route; - route->next = old->next; - - route->installed = old->installed; - route->changed = now; - assert (route->table == NULL); - route->table = table; - - ospf6_route_unlock (old); /* will be deleted later */ - ospf6_route_lock (route); - - SET_FLAG (route->flag, OSPF6_ROUTE_CHANGE); - ospf6_route_table_assert (table); - - if (table->hook_add) - (*table->hook_add) (route); - - return route; - } - - /* insert if previous or next node found */ - if (prev || next) - { - if (IS_OSPF6_DEBUG_ROUTE (MEMORY)) - zlog_debug ("%s %p: route add %p: another path: prev %p, next %p", - ospf6_route_table_name (table), - (void *)table, (void *)route, (void *)prev, (void *)next); - else if (IS_OSPF6_DEBUG_ROUTE (TABLE)) - zlog_debug ("%s: route add: another path found", - ospf6_route_table_name (table)); - - if (prev == NULL) - prev = next->prev; - if (next == NULL) - next = prev->next; - - if (prev) - prev->next = route; - route->prev = prev; - if (next) - next->prev = route; - route->next = next; - - if (node->info == next) - { - assert (next->rnode == node); - node->info = route; - UNSET_FLAG (next->flag, OSPF6_ROUTE_BEST); - SET_FLAG (route->flag, OSPF6_ROUTE_BEST); - if (IS_OSPF6_DEBUG_ROUTE (MEMORY)) - zlog_info ("%s %p: route add %p: replacing previous best: %p", - ospf6_route_table_name (table), - (void *)table, (void *)route, (void *)next); - } - - route->installed = now; - route->changed = now; - assert (route->table == NULL); - route->table = table; - - ospf6_route_lock (route); - table->count++; - ospf6_route_table_assert (table); - - SET_FLAG (route->flag, OSPF6_ROUTE_ADD); - if (table->hook_add) - (*table->hook_add) (route); - - return route; - } - - /* Else, this is the brand new route regarding to the prefix */ - if (IS_OSPF6_DEBUG_ROUTE (MEMORY)) - zlog_debug ("%s %p: route add %p: brand new route", - ospf6_route_table_name (table), (void *)table, (void *)route); - else if (IS_OSPF6_DEBUG_ROUTE (TABLE)) - zlog_debug ("%s: route add: brand new route", - ospf6_route_table_name (table)); - - assert (node->info == NULL); - node->info = route; - SET_FLAG (route->flag, OSPF6_ROUTE_BEST); - ospf6_route_lock (route); - route->installed = now; - route->changed = now; - assert (route->table == NULL); - route->table = table; - - /* lookup real existing next route */ - nextnode = node; - route_lock_node (nextnode); - do { - nextnode = route_next (nextnode); - } while (nextnode && nextnode->info == NULL); - - /* set next link */ - if (nextnode == NULL) - route->next = NULL; - else - { - route_unlock_node (nextnode); - - next = nextnode->info; - route->next = next; - next->prev = route; - } - - /* lookup real existing prev route */ - prevnode = node; - route_lock_node (prevnode); - do { - prevnode = route_prev (prevnode); - } while (prevnode && prevnode->info == NULL); - - /* set prev link */ - if (prevnode == NULL) - route->prev = NULL; - else - { - route_unlock_node (prevnode); - - prev = prevnode->info; - while (prev->next && ospf6_route_is_same (prev, prev->next)) - prev = prev->next; - route->prev = prev; - prev->next = route; - } - - table->count++; - ospf6_route_table_assert (table); - - SET_FLAG (route->flag, OSPF6_ROUTE_ADD); - if (table->hook_add) - (*table->hook_add) (route); - - return route; -} + struct route_node *node, *nextnode, *prevnode; + struct ospf6_route *current = NULL; + struct ospf6_route *prev = NULL, *old = NULL, *next = NULL; + char buf[PREFIX2STR_BUFFER]; + struct timeval now; + + assert(route->rnode == NULL); + assert(route->lock == 0); + assert(route->next == NULL); + assert(route->prev == NULL); + + if (route->type == OSPF6_DEST_TYPE_LINKSTATE) + ospf6_linkstate_prefix2str(&route->prefix, buf, sizeof(buf)); + else + prefix2str(&route->prefix, buf, sizeof(buf)); + + if (IS_OSPF6_DEBUG_ROUTE(MEMORY)) + zlog_debug("%s %p: route add %p: %s", + ospf6_route_table_name(table), (void *)table, + (void *)route, buf); + else if (IS_OSPF6_DEBUG_ROUTE(TABLE)) + zlog_debug("%s: route add: %s", ospf6_route_table_name(table), + buf); + + monotime(&now); + + node = route_node_get(table->table, &route->prefix); + route->rnode = node; + + /* find place to insert */ + for (current = node->info; current; current = current->next) { + if (!ospf6_route_is_same(current, route)) + next = current; + else if (current->type != route->type) + prev = current; + else if (ospf6_route_is_same_origin(current, route)) + old = current; + else if (ospf6_route_cmp(current, route) > 0) + next = current; + else + prev = current; + + if (old || next) + break; + } -void -ospf6_route_remove (struct ospf6_route *route, - struct ospf6_route_table *table) -{ - struct route_node *node; - struct ospf6_route *current; - char buf[PREFIX2STR_BUFFER]; - - if (route->type == OSPF6_DEST_TYPE_LINKSTATE) - ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf)); - else - prefix2str (&route->prefix, buf, sizeof (buf)); - - if (IS_OSPF6_DEBUG_ROUTE (MEMORY)) - zlog_debug ("%s %p: route remove %p: %s", - ospf6_route_table_name (table), - (void *)table, (void *)route, buf); - else if (IS_OSPF6_DEBUG_ROUTE (TABLE)) - zlog_debug ("%s: route remove: %s", ospf6_route_table_name (table), buf); - - node = route_node_lookup (table->table, &route->prefix); - assert (node); - - /* find the route to remove, making sure that the route pointer - is from the route table. */ - current = node->info; - while (current && ospf6_route_is_same (current, route)) - { - if (current == route) - break; - current = current->next; - } - assert (current == route); - - /* adjust doubly linked list */ - if (route->prev) - route->prev->next = route->next; - if (route->next) - route->next->prev = route->prev; - - if (node->info == route) - { - if (route->next && route->next->rnode == node) - { - node->info = route->next; - SET_FLAG (route->next->flag, OSPF6_ROUTE_BEST); - } - else - node->info = NULL; /* should unlock route_node here ? */ - } - - table->count--; - ospf6_route_table_assert (table); - - SET_FLAG (route->flag, OSPF6_ROUTE_WAS_REMOVED); - - if (table->hook_remove) - (*table->hook_remove) (route); - - ospf6_route_unlock (route); + if (old) { + /* if route does not actually change, return unchanged */ + if (ospf6_route_is_identical(old, route)) { + if (IS_OSPF6_DEBUG_ROUTE(MEMORY)) + zlog_debug( + "%s %p: route add %p: needless update of %p", + ospf6_route_table_name(table), + (void *)table, (void *)route, + (void *)old); + else if (IS_OSPF6_DEBUG_ROUTE(TABLE)) + zlog_debug("%s: route add: needless update", + ospf6_route_table_name(table)); + + ospf6_route_delete(route); + SET_FLAG(old->flag, OSPF6_ROUTE_ADD); + ospf6_route_table_assert(table); + + return old; + } + + if (IS_OSPF6_DEBUG_ROUTE(MEMORY)) + zlog_debug("%s %p: route add %p: update of %p", + ospf6_route_table_name(table), (void *)table, + (void *)route, (void *)old); + else if (IS_OSPF6_DEBUG_ROUTE(TABLE)) + zlog_debug("%s: route add: update", + ospf6_route_table_name(table)); + + /* replace old one if exists */ + if (node->info == old) { + node->info = route; + SET_FLAG(route->flag, OSPF6_ROUTE_BEST); + } + + if (old->prev) + old->prev->next = route; + route->prev = old->prev; + if (old->next) + old->next->prev = route; + route->next = old->next; + + route->installed = old->installed; + route->changed = now; + assert(route->table == NULL); + route->table = table; + + ospf6_route_unlock(old); /* will be deleted later */ + ospf6_route_lock(route); + + SET_FLAG(route->flag, OSPF6_ROUTE_CHANGE); + ospf6_route_table_assert(table); + + if (table->hook_add) + (*table->hook_add)(route); + + return route; + } + + /* insert if previous or next node found */ + if (prev || next) { + if (IS_OSPF6_DEBUG_ROUTE(MEMORY)) + zlog_debug( + "%s %p: route add %p: another path: prev %p, next %p", + ospf6_route_table_name(table), (void *)table, + (void *)route, (void *)prev, (void *)next); + else if (IS_OSPF6_DEBUG_ROUTE(TABLE)) + zlog_debug("%s: route add: another path found", + ospf6_route_table_name(table)); + + if (prev == NULL) + prev = next->prev; + if (next == NULL) + next = prev->next; + + if (prev) + prev->next = route; + route->prev = prev; + if (next) + next->prev = route; + route->next = next; + + if (node->info == next) { + assert(next->rnode == node); + node->info = route; + UNSET_FLAG(next->flag, OSPF6_ROUTE_BEST); + SET_FLAG(route->flag, OSPF6_ROUTE_BEST); + if (IS_OSPF6_DEBUG_ROUTE(MEMORY)) + zlog_info( + "%s %p: route add %p: replacing previous best: %p", + ospf6_route_table_name(table), + (void *)table, (void *)route, + (void *)next); + } + + route->installed = now; + route->changed = now; + assert(route->table == NULL); + route->table = table; + + ospf6_route_lock(route); + table->count++; + ospf6_route_table_assert(table); + + SET_FLAG(route->flag, OSPF6_ROUTE_ADD); + if (table->hook_add) + (*table->hook_add)(route); + + return route; + } + + /* Else, this is the brand new route regarding to the prefix */ + if (IS_OSPF6_DEBUG_ROUTE(MEMORY)) + zlog_debug("%s %p: route add %p: brand new route", + ospf6_route_table_name(table), (void *)table, + (void *)route); + else if (IS_OSPF6_DEBUG_ROUTE(TABLE)) + zlog_debug("%s: route add: brand new route", + ospf6_route_table_name(table)); + + assert(node->info == NULL); + node->info = route; + SET_FLAG(route->flag, OSPF6_ROUTE_BEST); + ospf6_route_lock(route); + route->installed = now; + route->changed = now; + assert(route->table == NULL); + route->table = table; + + /* lookup real existing next route */ + nextnode = node; + route_lock_node(nextnode); + do { + nextnode = route_next(nextnode); + } while (nextnode && nextnode->info == NULL); + + /* set next link */ + if (nextnode == NULL) + route->next = NULL; + else { + route_unlock_node(nextnode); + + next = nextnode->info; + route->next = next; + next->prev = route; + } + + /* lookup real existing prev route */ + prevnode = node; + route_lock_node(prevnode); + do { + prevnode = route_prev(prevnode); + } while (prevnode && prevnode->info == NULL); + + /* set prev link */ + if (prevnode == NULL) + route->prev = NULL; + else { + route_unlock_node(prevnode); + + prev = prevnode->info; + while (prev->next && ospf6_route_is_same(prev, prev->next)) + prev = prev->next; + route->prev = prev; + prev->next = route; + } + + table->count++; + ospf6_route_table_assert(table); + + SET_FLAG(route->flag, OSPF6_ROUTE_ADD); + if (table->hook_add) + (*table->hook_add)(route); + + return route; } -struct ospf6_route * -ospf6_route_head (struct ospf6_route_table *table) +void ospf6_route_remove(struct ospf6_route *route, + struct ospf6_route_table *table) { - struct route_node *node; - struct ospf6_route *route; - - node = route_top (table->table); - if (node == NULL) - return NULL; + struct route_node *node; + struct ospf6_route *current; + char buf[PREFIX2STR_BUFFER]; + + if (route->type == OSPF6_DEST_TYPE_LINKSTATE) + ospf6_linkstate_prefix2str(&route->prefix, buf, sizeof(buf)); + else + prefix2str(&route->prefix, buf, sizeof(buf)); + + if (IS_OSPF6_DEBUG_ROUTE(MEMORY)) + zlog_debug("%s %p: route remove %p: %s", + ospf6_route_table_name(table), (void *)table, + (void *)route, buf); + else if (IS_OSPF6_DEBUG_ROUTE(TABLE)) + zlog_debug("%s: route remove: %s", + ospf6_route_table_name(table), buf); + + node = route_node_lookup(table->table, &route->prefix); + assert(node); + + /* find the route to remove, making sure that the route pointer + is from the route table. */ + current = node->info; + while (current && ospf6_route_is_same(current, route)) { + if (current == route) + break; + current = current->next; + } + assert(current == route); + + /* adjust doubly linked list */ + if (route->prev) + route->prev->next = route->next; + if (route->next) + route->next->prev = route->prev; + + if (node->info == route) { + if (route->next && route->next->rnode == node) { + node->info = route->next; + SET_FLAG(route->next->flag, OSPF6_ROUTE_BEST); + } else + node->info = NULL; /* should unlock route_node here ? */ + } - /* skip to the real existing entry */ - while (node && node->info == NULL) - node = route_next (node); - if (node == NULL) - return NULL; + table->count--; + ospf6_route_table_assert(table); - route_unlock_node (node); - assert (node->info); + SET_FLAG(route->flag, OSPF6_ROUTE_WAS_REMOVED); - route = (struct ospf6_route *) node->info; - assert (route->prev == NULL); - assert (route->table == table); - ospf6_route_lock (route); + if (table->hook_remove) + (*table->hook_remove)(route); - if (IS_OSPF6_DEBUG_ROUTE (MEMORY)) - zlog_info ("%s %p: route head: %p<-[%p]->%p", - ospf6_route_table_name (table), (void *)table, - (void *)route->prev, (void *)route, (void *)route->next); + ospf6_route_unlock(route); +} - return route; +struct ospf6_route *ospf6_route_head(struct ospf6_route_table *table) +{ + struct route_node *node; + struct ospf6_route *route; + + node = route_top(table->table); + if (node == NULL) + return NULL; + + /* skip to the real existing entry */ + while (node && node->info == NULL) + node = route_next(node); + if (node == NULL) + return NULL; + + route_unlock_node(node); + assert(node->info); + + route = (struct ospf6_route *)node->info; + assert(route->prev == NULL); + assert(route->table == table); + ospf6_route_lock(route); + + if (IS_OSPF6_DEBUG_ROUTE(MEMORY)) + zlog_info("%s %p: route head: %p<-[%p]->%p", + ospf6_route_table_name(table), (void *)table, + (void *)route->prev, (void *)route, + (void *)route->next); + + return route; } -struct ospf6_route * -ospf6_route_next (struct ospf6_route *route) +struct ospf6_route *ospf6_route_next(struct ospf6_route *route) { - struct ospf6_route *next = route->next; + struct ospf6_route *next = route->next; - if (IS_OSPF6_DEBUG_ROUTE (MEMORY)) - zlog_info ("%s %p: route next: %p<-[%p]->%p", - ospf6_route_table_name (route->table), (void *)route->table, - (void *)route->prev, (void *)route, (void *)route->next); + if (IS_OSPF6_DEBUG_ROUTE(MEMORY)) + zlog_info("%s %p: route next: %p<-[%p]->%p", + ospf6_route_table_name(route->table), + (void *)route->table, (void *)route->prev, + (void *)route, (void *)route->next); - ospf6_route_unlock (route); - if (next) - ospf6_route_lock (next); + ospf6_route_unlock(route); + if (next) + ospf6_route_lock(next); - return next; + return next; } -struct ospf6_route * -ospf6_route_best_next (struct ospf6_route *route) +struct ospf6_route *ospf6_route_best_next(struct ospf6_route *route) { - struct route_node *rnode; - struct ospf6_route *next; - - ospf6_route_unlock (route); - - rnode = route->rnode; - route_lock_node (rnode); - rnode = route_next (rnode); - while (rnode && rnode->info == NULL) - rnode = route_next (rnode); - if (rnode == NULL) - return NULL; - route_unlock_node (rnode); - - assert (rnode->info); - next = (struct ospf6_route *) rnode->info; - ospf6_route_lock (next); - return next; + struct route_node *rnode; + struct ospf6_route *next; + + ospf6_route_unlock(route); + + rnode = route->rnode; + route_lock_node(rnode); + rnode = route_next(rnode); + while (rnode && rnode->info == NULL) + rnode = route_next(rnode); + if (rnode == NULL) + return NULL; + route_unlock_node(rnode); + + assert(rnode->info); + next = (struct ospf6_route *)rnode->info; + ospf6_route_lock(next); + return next; } -struct ospf6_route * -ospf6_route_match_head (struct prefix *prefix, - struct ospf6_route_table *table) +struct ospf6_route *ospf6_route_match_head(struct prefix *prefix, + struct ospf6_route_table *table) { - struct route_node *node; - struct ospf6_route *route; - - /* Walk down tree. */ - node = table->table->top; - while (node && node->p.prefixlen < prefix->prefixlen && - prefix_match (&node->p, prefix)) - node = node->link[prefix_bit(&prefix->u.prefix, node->p.prefixlen)]; - - if (node) - route_lock_node (node); - while (node && node->info == NULL) - node = route_next (node); - if (node == NULL) - return NULL; - route_unlock_node (node); - - if (! prefix_match (prefix, &node->p)) - return NULL; - - route = node->info; - ospf6_route_lock (route); - return route; + struct route_node *node; + struct ospf6_route *route; + + /* Walk down tree. */ + node = table->table->top; + while (node && node->p.prefixlen < prefix->prefixlen + && prefix_match(&node->p, prefix)) + node = node->link[prefix_bit(&prefix->u.prefix, + node->p.prefixlen)]; + + if (node) + route_lock_node(node); + while (node && node->info == NULL) + node = route_next(node); + if (node == NULL) + return NULL; + route_unlock_node(node); + + if (!prefix_match(prefix, &node->p)) + return NULL; + + route = node->info; + ospf6_route_lock(route); + return route; } -struct ospf6_route * -ospf6_route_match_next (struct prefix *prefix, - struct ospf6_route *route) +struct ospf6_route *ospf6_route_match_next(struct prefix *prefix, + struct ospf6_route *route) { - struct ospf6_route *next; + struct ospf6_route *next; - next = ospf6_route_next (route); - if (next && ! prefix_match (prefix, &next->prefix)) - { - ospf6_route_unlock (next); - next = NULL; - } + next = ospf6_route_next(route); + if (next && !prefix_match(prefix, &next->prefix)) { + ospf6_route_unlock(next); + next = NULL; + } - return next; + return next; } -void -ospf6_route_remove_all (struct ospf6_route_table *table) +void ospf6_route_remove_all(struct ospf6_route_table *table) { - struct ospf6_route *route; - for (route = ospf6_route_head (table); route; - route = ospf6_route_next (route)) - ospf6_route_remove (route, table); + struct ospf6_route *route; + for (route = ospf6_route_head(table); route; + route = ospf6_route_next(route)) + ospf6_route_remove(route, table); } -struct ospf6_route_table * -ospf6_route_table_create (int s, int t) +struct ospf6_route_table *ospf6_route_table_create(int s, int t) { - struct ospf6_route_table *new; - new = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_table)); - new->table = route_table_init (); - new->scope_type = s; - new->table_type = t; - return new; + struct ospf6_route_table *new; + new = XCALLOC(MTYPE_OSPF6_ROUTE, sizeof(struct ospf6_route_table)); + new->table = route_table_init(); + new->scope_type = s; + new->table_type = t; + return new; } -void -ospf6_route_table_delete (struct ospf6_route_table *table) +void ospf6_route_table_delete(struct ospf6_route_table *table) { - ospf6_route_remove_all (table); - route_table_finish (table->table); - XFREE (MTYPE_OSPF6_ROUTE, table); + ospf6_route_remove_all(table); + route_table_finish(table->table); + XFREE(MTYPE_OSPF6_ROUTE, table); } /* VTY commands */ -void -ospf6_route_show (struct vty *vty, struct ospf6_route *route) +void ospf6_route_show(struct vty *vty, struct ospf6_route *route) { - int i; - char destination[PREFIX2STR_BUFFER], nexthop[64]; - char duration[16]; - const char *ifname; - struct timeval now, res; - struct listnode *node; - struct ospf6_nexthop *nh; - - monotime(&now); - timersub (&now, &route->changed, &res); - timerstring (&res, duration, sizeof (duration)); - - /* destination */ - if (route->type == OSPF6_DEST_TYPE_LINKSTATE) - ospf6_linkstate_prefix2str (&route->prefix, destination, - sizeof (destination)); - else if (route->type == OSPF6_DEST_TYPE_ROUTER) - inet_ntop (route->prefix.family, &route->prefix.u.prefix, - destination, sizeof (destination)); - else - prefix2str (&route->prefix, destination, sizeof (destination)); - - i = 0; - for (ALL_LIST_ELEMENTS_RO (route->nh_list, node, nh)) - { - /* nexthop */ - inet_ntop (AF_INET6, &nh->address, nexthop, - sizeof (nexthop)); - ifname = ifindex2ifname (nh->ifindex, VRF_DEFAULT); - - if (!i) - { - vty_out (vty, "%c%1s %2s %-30s %-25s %6.*s %s\n", - (ospf6_route_is_best (route) ? '*' : ' '), - OSPF6_DEST_TYPE_SUBSTR (route->type), - OSPF6_PATH_TYPE_SUBSTR (route->path.type), - destination, nexthop, IFNAMSIZ, ifname, duration); - i++; + int i; + char destination[PREFIX2STR_BUFFER], nexthop[64]; + char duration[16]; + const char *ifname; + struct timeval now, res; + struct listnode *node; + struct ospf6_nexthop *nh; + + monotime(&now); + timersub(&now, &route->changed, &res); + timerstring(&res, duration, sizeof(duration)); + + /* destination */ + if (route->type == OSPF6_DEST_TYPE_LINKSTATE) + ospf6_linkstate_prefix2str(&route->prefix, destination, + sizeof(destination)); + else if (route->type == OSPF6_DEST_TYPE_ROUTER) + inet_ntop(route->prefix.family, &route->prefix.u.prefix, + destination, sizeof(destination)); + else + prefix2str(&route->prefix, destination, sizeof(destination)); + + i = 0; + for (ALL_LIST_ELEMENTS_RO(route->nh_list, node, nh)) { + /* nexthop */ + inet_ntop(AF_INET6, &nh->address, nexthop, sizeof(nexthop)); + ifname = ifindex2ifname(nh->ifindex, VRF_DEFAULT); + + if (!i) { + vty_out(vty, "%c%1s %2s %-30s %-25s %6.*s %s\n", + (ospf6_route_is_best(route) ? '*' : ' '), + OSPF6_DEST_TYPE_SUBSTR(route->type), + OSPF6_PATH_TYPE_SUBSTR(route->path.type), + destination, nexthop, IFNAMSIZ, ifname, + duration); + i++; + } else + vty_out(vty, "%c%1s %2s %-30s %-25s %6.*s %s\n", ' ', + "", "", "", nexthop, IFNAMSIZ, ifname, ""); } - else - vty_out (vty, "%c%1s %2s %-30s %-25s %6.*s %s\n", - ' ', "", "", "", nexthop, IFNAMSIZ, ifname, ""); - } } -void -ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route) +void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route) { - const char *ifname; - char destination[PREFIX2STR_BUFFER], nexthop[64]; - char area_id[16], id[16], adv_router[16], capa[16], options[16]; - struct timeval now, res; - char duration[16]; - struct listnode *node; - struct ospf6_nexthop *nh; - - monotime(&now); - - /* destination */ - if (route->type == OSPF6_DEST_TYPE_LINKSTATE) - ospf6_linkstate_prefix2str (&route->prefix, destination, - sizeof (destination)); - else if (route->type == OSPF6_DEST_TYPE_ROUTER) - inet_ntop (route->prefix.family, &route->prefix.u.prefix, - destination, sizeof (destination)); - else - prefix2str (&route->prefix, destination, sizeof (destination)); - vty_out (vty, "Destination: %s\n", destination); - - /* destination type */ - vty_out (vty, "Destination type: %s\n", - OSPF6_DEST_TYPE_NAME (route->type)); - - /* Time */ - timersub (&now, &route->installed, &res); - timerstring (&res, duration, sizeof (duration)); - vty_out (vty, "Installed Time: %s ago\n", duration); - - timersub (&now, &route->changed, &res); - timerstring (&res, duration, sizeof (duration)); - vty_out (vty, " Changed Time: %s ago\n", duration); - - /* Debugging info */ - vty_out (vty, "Lock: %d Flags: %s%s%s%s\n", route->lock, - (CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST) ? "B" : "-"), - (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) ? "A" : "-"), - (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"), - (CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-")); - vty_out (vty, "Memory: prev: %p this: %p next: %p\n", - (void *)route->prev, (void *)route, (void *)route->next); - - /* Path section */ - - /* Area-ID */ - inet_ntop (AF_INET, &route->path.area_id, area_id, sizeof (area_id)); - vty_out (vty, "Associated Area: %s\n", area_id); - - /* Path type */ - vty_out (vty, "Path Type: %s\n", - OSPF6_PATH_TYPE_NAME (route->path.type)); - - /* LS Origin */ - inet_ntop (AF_INET, &route->path.origin.id, id, sizeof (id)); - inet_ntop (AF_INET, &route->path.origin.adv_router, adv_router, - sizeof (adv_router)); - vty_out (vty, "LS Origin: %s Id: %s Adv: %s\n", - ospf6_lstype_name (route->path.origin.type), - id, adv_router); - - /* Options */ - ospf6_options_printbuf (route->path.options, options, sizeof (options)); - vty_out (vty, "Options: %s\n", options); - - /* Router Bits */ - ospf6_capability_printbuf (route->path.router_bits, capa, sizeof (capa)); - vty_out (vty, "Router Bits: %s\n", capa); - - /* Prefix Options */ - vty_out (vty, "Prefix Options: xxx\n"); - - /* Metrics */ - vty_out (vty, "Metric Type: %d\n", route->path.metric_type); - vty_out (vty, "Metric: %d (%d)\n", - route->path.cost, route->path.u.cost_e2); - - /* Nexthops */ - vty_out (vty, "Nexthop:\n"); - for (ALL_LIST_ELEMENTS_RO (route->nh_list, node, nh)) - { - /* nexthop */ - inet_ntop (AF_INET6, &nh->address, nexthop, sizeof (nexthop)); - ifname = ifindex2ifname (nh->ifindex, VRF_DEFAULT); - vty_out (vty, " %s %.*s\n", nexthop, IFNAMSIZ, ifname); - } - vty_out (vty, "\n"); + const char *ifname; + char destination[PREFIX2STR_BUFFER], nexthop[64]; + char area_id[16], id[16], adv_router[16], capa[16], options[16]; + struct timeval now, res; + char duration[16]; + struct listnode *node; + struct ospf6_nexthop *nh; + + monotime(&now); + + /* destination */ + if (route->type == OSPF6_DEST_TYPE_LINKSTATE) + ospf6_linkstate_prefix2str(&route->prefix, destination, + sizeof(destination)); + else if (route->type == OSPF6_DEST_TYPE_ROUTER) + inet_ntop(route->prefix.family, &route->prefix.u.prefix, + destination, sizeof(destination)); + else + prefix2str(&route->prefix, destination, sizeof(destination)); + vty_out(vty, "Destination: %s\n", destination); + + /* destination type */ + vty_out(vty, "Destination type: %s\n", + OSPF6_DEST_TYPE_NAME(route->type)); + + /* Time */ + timersub(&now, &route->installed, &res); + timerstring(&res, duration, sizeof(duration)); + vty_out(vty, "Installed Time: %s ago\n", duration); + + timersub(&now, &route->changed, &res); + timerstring(&res, duration, sizeof(duration)); + vty_out(vty, " Changed Time: %s ago\n", duration); + + /* Debugging info */ + vty_out(vty, "Lock: %d Flags: %s%s%s%s\n", route->lock, + (CHECK_FLAG(route->flag, OSPF6_ROUTE_BEST) ? "B" : "-"), + (CHECK_FLAG(route->flag, OSPF6_ROUTE_ADD) ? "A" : "-"), + (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"), + (CHECK_FLAG(route->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-")); + vty_out(vty, "Memory: prev: %p this: %p next: %p\n", + (void *)route->prev, (void *)route, (void *)route->next); + + /* Path section */ + + /* Area-ID */ + inet_ntop(AF_INET, &route->path.area_id, area_id, sizeof(area_id)); + vty_out(vty, "Associated Area: %s\n", area_id); + + /* Path type */ + vty_out(vty, "Path Type: %s\n", OSPF6_PATH_TYPE_NAME(route->path.type)); + + /* LS Origin */ + inet_ntop(AF_INET, &route->path.origin.id, id, sizeof(id)); + inet_ntop(AF_INET, &route->path.origin.adv_router, adv_router, + sizeof(adv_router)); + vty_out(vty, "LS Origin: %s Id: %s Adv: %s\n", + ospf6_lstype_name(route->path.origin.type), id, adv_router); + + /* Options */ + ospf6_options_printbuf(route->path.options, options, sizeof(options)); + vty_out(vty, "Options: %s\n", options); + + /* Router Bits */ + ospf6_capability_printbuf(route->path.router_bits, capa, sizeof(capa)); + vty_out(vty, "Router Bits: %s\n", capa); + + /* Prefix Options */ + vty_out(vty, "Prefix Options: xxx\n"); + + /* Metrics */ + vty_out(vty, "Metric Type: %d\n", route->path.metric_type); + vty_out(vty, "Metric: %d (%d)\n", route->path.cost, + route->path.u.cost_e2); + + /* Nexthops */ + vty_out(vty, "Nexthop:\n"); + for (ALL_LIST_ELEMENTS_RO(route->nh_list, node, nh)) { + /* nexthop */ + inet_ntop(AF_INET6, &nh->address, nexthop, sizeof(nexthop)); + ifname = ifindex2ifname(nh->ifindex, VRF_DEFAULT); + vty_out(vty, " %s %.*s\n", nexthop, IFNAMSIZ, ifname); + } + vty_out(vty, "\n"); } -static void -ospf6_route_show_table_summary (struct vty *vty, - struct ospf6_route_table *table) +static void ospf6_route_show_table_summary(struct vty *vty, + struct ospf6_route_table *table) { - struct ospf6_route *route, *prev = NULL; - int i, pathtype[OSPF6_PATH_TYPE_MAX]; - unsigned int number = 0; - int nh_count =0 , nhinval = 0, ecmp = 0; - int alternative = 0, destination = 0; - - for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++) - pathtype[i] = 0; - - for (route = ospf6_route_head (table); route; - route = ospf6_route_next (route)) - { - if (prev == NULL || ! ospf6_route_is_same (prev, route)) - destination++; - else - alternative++; - nh_count = ospf6_num_nexthops (route->nh_list); - if (!nh_count) - nhinval++; - else if (nh_count > 1) - ecmp++; - pathtype[route->path.type]++; - number++; - - prev = route; - } - - assert (number == table->count); - - vty_out (vty, "Number of OSPFv3 routes: %d\n", number); - vty_out (vty, "Number of Destination: %d\n", destination); - vty_out (vty, "Number of Alternative routes: %d\n", alternative); - vty_out (vty, "Number of Equal Cost Multi Path: %d\n", ecmp); - for (i = OSPF6_PATH_TYPE_INTRA; i <= OSPF6_PATH_TYPE_EXTERNAL2; i++) - { - vty_out (vty, "Number of %s routes: %d\n", - OSPF6_PATH_TYPE_NAME (i), pathtype[i]); - } + struct ospf6_route *route, *prev = NULL; + int i, pathtype[OSPF6_PATH_TYPE_MAX]; + unsigned int number = 0; + int nh_count = 0, nhinval = 0, ecmp = 0; + int alternative = 0, destination = 0; + + for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++) + pathtype[i] = 0; + + for (route = ospf6_route_head(table); route; + route = ospf6_route_next(route)) { + if (prev == NULL || !ospf6_route_is_same(prev, route)) + destination++; + else + alternative++; + nh_count = ospf6_num_nexthops(route->nh_list); + if (!nh_count) + nhinval++; + else if (nh_count > 1) + ecmp++; + pathtype[route->path.type]++; + number++; + + prev = route; + } + + assert(number == table->count); + + vty_out(vty, "Number of OSPFv3 routes: %d\n", number); + vty_out(vty, "Number of Destination: %d\n", destination); + vty_out(vty, "Number of Alternative routes: %d\n", alternative); + vty_out(vty, "Number of Equal Cost Multi Path: %d\n", ecmp); + for (i = OSPF6_PATH_TYPE_INTRA; i <= OSPF6_PATH_TYPE_EXTERNAL2; i++) { + vty_out(vty, "Number of %s routes: %d\n", + OSPF6_PATH_TYPE_NAME(i), pathtype[i]); + } } -static void -ospf6_route_show_table_prefix (struct vty *vty, - struct prefix *prefix, - struct ospf6_route_table *table) +static void ospf6_route_show_table_prefix(struct vty *vty, + struct prefix *prefix, + struct ospf6_route_table *table) { - struct ospf6_route *route; - - route = ospf6_route_lookup (prefix, table); - if (route == NULL) - return; - - ospf6_route_lock (route); - while (route && ospf6_route_is_prefix (prefix, route)) - { - /* Specifying a prefix will always display details */ - ospf6_route_show_detail (vty, route); - route = ospf6_route_next (route); - } - if (route) - ospf6_route_unlock (route); + struct ospf6_route *route; + + route = ospf6_route_lookup(prefix, table); + if (route == NULL) + return; + + ospf6_route_lock(route); + while (route && ospf6_route_is_prefix(prefix, route)) { + /* Specifying a prefix will always display details */ + ospf6_route_show_detail(vty, route); + route = ospf6_route_next(route); + } + if (route) + ospf6_route_unlock(route); } -static void -ospf6_route_show_table_address (struct vty *vty, - struct prefix *prefix, - struct ospf6_route_table *table) +static void ospf6_route_show_table_address(struct vty *vty, + struct prefix *prefix, + struct ospf6_route_table *table) { - struct ospf6_route *route; - - route = ospf6_route_lookup_bestmatch (prefix, table); - if (route == NULL) - return; - - prefix = &route->prefix; - ospf6_route_lock (route); - while (route && ospf6_route_is_prefix (prefix, route)) - { - /* Specifying a prefix will always display details */ - ospf6_route_show_detail (vty, route); - route = ospf6_route_next (route); - } - if (route) - ospf6_route_unlock (route); + struct ospf6_route *route; + + route = ospf6_route_lookup_bestmatch(prefix, table); + if (route == NULL) + return; + + prefix = &route->prefix; + ospf6_route_lock(route); + while (route && ospf6_route_is_prefix(prefix, route)) { + /* Specifying a prefix will always display details */ + ospf6_route_show_detail(vty, route); + route = ospf6_route_next(route); + } + if (route) + ospf6_route_unlock(route); } -static void -ospf6_route_show_table_match (struct vty *vty, int detail, - struct prefix *prefix, - struct ospf6_route_table *table) +static void ospf6_route_show_table_match(struct vty *vty, int detail, + struct prefix *prefix, + struct ospf6_route_table *table) { - struct ospf6_route *route; - assert (prefix->family); - - route = ospf6_route_match_head (prefix, table); - while (route) - { - if (detail) - ospf6_route_show_detail (vty, route); - else - ospf6_route_show (vty, route); - route = ospf6_route_match_next (prefix, route); - } + struct ospf6_route *route; + assert(prefix->family); + + route = ospf6_route_match_head(prefix, table); + while (route) { + if (detail) + ospf6_route_show_detail(vty, route); + else + ospf6_route_show(vty, route); + route = ospf6_route_match_next(prefix, route); + } } -static void -ospf6_route_show_table_type (struct vty *vty, int detail, u_char type, - struct ospf6_route_table *table) +static void ospf6_route_show_table_type(struct vty *vty, int detail, + u_char type, + struct ospf6_route_table *table) { - struct ospf6_route *route; - - route = ospf6_route_head (table); - while (route) - { - if (route->path.type == type) - { - if (detail) - ospf6_route_show_detail (vty, route); - else - ospf6_route_show (vty, route); - } - route = ospf6_route_next (route); - } + struct ospf6_route *route; + + route = ospf6_route_head(table); + while (route) { + if (route->path.type == type) { + if (detail) + ospf6_route_show_detail(vty, route); + else + ospf6_route_show(vty, route); + } + route = ospf6_route_next(route); + } } -static void -ospf6_route_show_table (struct vty *vty, int detail, - struct ospf6_route_table *table) +static void ospf6_route_show_table(struct vty *vty, int detail, + struct ospf6_route_table *table) { - struct ospf6_route *route; - - route = ospf6_route_head (table); - while (route) - { - if (detail) - ospf6_route_show_detail (vty, route); - else - ospf6_route_show (vty, route); - route = ospf6_route_next (route); - } + struct ospf6_route *route; + + route = ospf6_route_head(table); + while (route) { + if (detail) + ospf6_route_show_detail(vty, route); + else + ospf6_route_show(vty, route); + route = ospf6_route_next(route); + } } -int -ospf6_route_table_show (struct vty *vty, int argc_start, int argc, struct cmd_token **argv, - struct ospf6_route_table *table) +int ospf6_route_table_show(struct vty *vty, int argc_start, int argc, + struct cmd_token **argv, + struct ospf6_route_table *table) { - int summary = 0; - int match = 0; - int detail = 0; - int slash = 0; - int isprefix = 0; - int i, ret; - struct prefix prefix; - u_char type = 0; - - memset (&prefix, 0, sizeof (struct prefix)); - - for (i = argc_start; i < argc; i++) - { - if (strmatch(argv[i]->text, "summary")) - { - summary++; - continue; - } - - if (strmatch(argv[i]->text, "intra-area")) - { - type = OSPF6_PATH_TYPE_INTRA; - continue; - } - - if (strmatch(argv[i]->text, "inter-area")) - { - type = OSPF6_PATH_TYPE_INTER; - continue; - } - - if (strmatch(argv[i]->text, "external-1")) - { - type = OSPF6_PATH_TYPE_EXTERNAL1; - continue; - } - - if (strmatch(argv[i]->text, "external-2")) - { - type = OSPF6_PATH_TYPE_EXTERNAL2; - continue; - } - - if (strmatch(argv[i]->text, "detail")) - { - detail++; - continue; - } - - if (strmatch(argv[i]->text, "match")) - { - match++; - continue; - } - - ret = str2prefix (argv[i]->arg, &prefix); - if (ret == 1 && prefix.family == AF_INET6) - { - isprefix++; - if (strchr (argv[i]->arg, '/')) - slash++; - continue; - } - - vty_out (vty, "Malformed argument: %s\n", argv[i]->arg); - return CMD_SUCCESS; - } - - /* Give summary of this route table */ - if (summary) - { - ospf6_route_show_table_summary (vty, table); - return CMD_SUCCESS; - } - - /* Give exact prefix-match route */ - if (isprefix && ! match) - { - /* If exact address, give best matching route */ - if (! slash) - ospf6_route_show_table_address (vty, &prefix, table); - else - ospf6_route_show_table_prefix (vty, &prefix, table); - - return CMD_SUCCESS; - } - - if (match) - ospf6_route_show_table_match (vty, detail, &prefix, table); - else if (type) - ospf6_route_show_table_type (vty, detail, type, table); - else - ospf6_route_show_table (vty, detail, table); - - return CMD_SUCCESS; + int summary = 0; + int match = 0; + int detail = 0; + int slash = 0; + int isprefix = 0; + int i, ret; + struct prefix prefix; + u_char type = 0; + + memset(&prefix, 0, sizeof(struct prefix)); + + for (i = argc_start; i < argc; i++) { + if (strmatch(argv[i]->text, "summary")) { + summary++; + continue; + } + + if (strmatch(argv[i]->text, "intra-area")) { + type = OSPF6_PATH_TYPE_INTRA; + continue; + } + + if (strmatch(argv[i]->text, "inter-area")) { + type = OSPF6_PATH_TYPE_INTER; + continue; + } + + if (strmatch(argv[i]->text, "external-1")) { + type = OSPF6_PATH_TYPE_EXTERNAL1; + continue; + } + + if (strmatch(argv[i]->text, "external-2")) { + type = OSPF6_PATH_TYPE_EXTERNAL2; + continue; + } + + if (strmatch(argv[i]->text, "detail")) { + detail++; + continue; + } + + if (strmatch(argv[i]->text, "match")) { + match++; + continue; + } + + ret = str2prefix(argv[i]->arg, &prefix); + if (ret == 1 && prefix.family == AF_INET6) { + isprefix++; + if (strchr(argv[i]->arg, '/')) + slash++; + continue; + } + + vty_out(vty, "Malformed argument: %s\n", argv[i]->arg); + return CMD_SUCCESS; + } + + /* Give summary of this route table */ + if (summary) { + ospf6_route_show_table_summary(vty, table); + return CMD_SUCCESS; + } + + /* Give exact prefix-match route */ + if (isprefix && !match) { + /* If exact address, give best matching route */ + if (!slash) + ospf6_route_show_table_address(vty, &prefix, table); + else + ospf6_route_show_table_prefix(vty, &prefix, table); + + return CMD_SUCCESS; + } + + if (match) + ospf6_route_show_table_match(vty, detail, &prefix, table); + else if (type) + ospf6_route_show_table_type(vty, detail, type, table); + else + ospf6_route_show_table(vty, detail, table); + + return CMD_SUCCESS; } -static void -ospf6_linkstate_show_header (struct vty *vty) +static void ospf6_linkstate_show_header(struct vty *vty) { - vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %s\n", - "Type", "Router-ID", "Net-ID", "Rtr-Bits", "Options", "Cost"); + vty_out(vty, "%-7s %-15s %-15s %-8s %-14s %s\n", "Type", "Router-ID", + "Net-ID", "Rtr-Bits", "Options", "Cost"); } -static void -ospf6_linkstate_show (struct vty *vty, struct ospf6_route *route) +static void ospf6_linkstate_show(struct vty *vty, struct ospf6_route *route) { - u_int32_t router, id; - char routername[16], idname[16], rbits[16], options[16]; - - router = ospf6_linkstate_prefix_adv_router (&route->prefix); - inet_ntop (AF_INET, &router, routername, sizeof (routername)); - id = ospf6_linkstate_prefix_id (&route->prefix); - inet_ntop (AF_INET, &id, idname, sizeof (idname)); - - ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits)); - ospf6_options_printbuf (route->path.options, options, sizeof (options)); - - if (ntohl (id)) - vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %lu\n", - "Network", routername, idname, rbits, options, - (unsigned long) route->path.cost); - else - vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %lu\n", - "Router", routername, idname, rbits, options, - (unsigned long) route->path.cost); + u_int32_t router, id; + char routername[16], idname[16], rbits[16], options[16]; + + router = ospf6_linkstate_prefix_adv_router(&route->prefix); + inet_ntop(AF_INET, &router, routername, sizeof(routername)); + id = ospf6_linkstate_prefix_id(&route->prefix); + inet_ntop(AF_INET, &id, idname, sizeof(idname)); + + ospf6_capability_printbuf(route->path.router_bits, rbits, + sizeof(rbits)); + ospf6_options_printbuf(route->path.options, options, sizeof(options)); + + if (ntohl(id)) + vty_out(vty, "%-7s %-15s %-15s %-8s %-14s %lu\n", "Network", + routername, idname, rbits, options, + (unsigned long)route->path.cost); + else + vty_out(vty, "%-7s %-15s %-15s %-8s %-14s %lu\n", "Router", + routername, idname, rbits, options, + (unsigned long)route->path.cost); } -static void -ospf6_linkstate_show_table_exact (struct vty *vty, - struct prefix *prefix, - struct ospf6_route_table *table) +static void ospf6_linkstate_show_table_exact(struct vty *vty, + struct prefix *prefix, + struct ospf6_route_table *table) { - struct ospf6_route *route; - - route = ospf6_route_lookup (prefix, table); - if (route == NULL) - return; - - ospf6_route_lock (route); - while (route && ospf6_route_is_prefix (prefix, route)) - { - /* Specifying a prefix will always display details */ - ospf6_route_show_detail (vty, route); - route = ospf6_route_next (route); - } - if (route) - ospf6_route_unlock (route); + struct ospf6_route *route; + + route = ospf6_route_lookup(prefix, table); + if (route == NULL) + return; + + ospf6_route_lock(route); + while (route && ospf6_route_is_prefix(prefix, route)) { + /* Specifying a prefix will always display details */ + ospf6_route_show_detail(vty, route); + route = ospf6_route_next(route); + } + if (route) + ospf6_route_unlock(route); } -static void -ospf6_linkstate_show_table (struct vty *vty, int detail, - struct ospf6_route_table *table) +static void ospf6_linkstate_show_table(struct vty *vty, int detail, + struct ospf6_route_table *table) { - struct ospf6_route *route; - - if (! detail) - ospf6_linkstate_show_header (vty); - - route = ospf6_route_head (table); - while (route) - { - if (detail) - ospf6_route_show_detail (vty, route); - else - ospf6_linkstate_show (vty, route); - route = ospf6_route_next (route); - } + struct ospf6_route *route; + + if (!detail) + ospf6_linkstate_show_header(vty); + + route = ospf6_route_head(table); + while (route) { + if (detail) + ospf6_route_show_detail(vty, route); + else + ospf6_linkstate_show(vty, route); + route = ospf6_route_next(route); + } } -int -ospf6_linkstate_table_show (struct vty *vty, int idx_ipv4, int argc, - struct cmd_token **argv, - struct ospf6_route_table *table) +int ospf6_linkstate_table_show(struct vty *vty, int idx_ipv4, int argc, + struct cmd_token **argv, + struct ospf6_route_table *table) { - int detail = 0; - int is_id = 0; - int is_router = 0; - int i, ret; - struct prefix router, id, prefix; - - memset (&router, 0, sizeof (struct prefix)); - memset (&id, 0, sizeof (struct prefix)); - memset (&prefix, 0, sizeof (struct prefix)); - - for (i = idx_ipv4; i < argc; i++) - { - if (strmatch(argv[i]->text, "detail")) - { - detail++; - continue; - } - - if (! is_router) - { - ret = str2prefix (argv[i]->arg, &router); - if (ret == 1 && router.family == AF_INET) - { - is_router++; - continue; - } - vty_out (vty, "Malformed argument: %s\n", argv[i]->arg); - return CMD_SUCCESS; - } - - if (! is_id) - { - ret = str2prefix (argv[i]->arg, &id); - if (ret == 1 && id.family == AF_INET) - { - is_id++; - continue; - } - vty_out (vty, "Malformed argument: %s\n", argv[i]->arg); - return CMD_SUCCESS; - } - - vty_out (vty, "Malformed argument: %s\n", argv[i]->arg); - return CMD_SUCCESS; - } - - if (is_router) - ospf6_linkstate_prefix (router.u.prefix4.s_addr, - id.u.prefix4.s_addr, &prefix); - - if (prefix.family) - ospf6_linkstate_show_table_exact (vty, &prefix, table); - else - ospf6_linkstate_show_table (vty, detail, table); - - return CMD_SUCCESS; + int detail = 0; + int is_id = 0; + int is_router = 0; + int i, ret; + struct prefix router, id, prefix; + + memset(&router, 0, sizeof(struct prefix)); + memset(&id, 0, sizeof(struct prefix)); + memset(&prefix, 0, sizeof(struct prefix)); + + for (i = idx_ipv4; i < argc; i++) { + if (strmatch(argv[i]->text, "detail")) { + detail++; + continue; + } + + if (!is_router) { + ret = str2prefix(argv[i]->arg, &router); + if (ret == 1 && router.family == AF_INET) { + is_router++; + continue; + } + vty_out(vty, "Malformed argument: %s\n", argv[i]->arg); + return CMD_SUCCESS; + } + + if (!is_id) { + ret = str2prefix(argv[i]->arg, &id); + if (ret == 1 && id.family == AF_INET) { + is_id++; + continue; + } + vty_out(vty, "Malformed argument: %s\n", argv[i]->arg); + return CMD_SUCCESS; + } + + vty_out(vty, "Malformed argument: %s\n", argv[i]->arg); + return CMD_SUCCESS; + } + + if (is_router) + ospf6_linkstate_prefix(router.u.prefix4.s_addr, + id.u.prefix4.s_addr, &prefix); + + if (prefix.family) + ospf6_linkstate_show_table_exact(vty, &prefix, table); + else + ospf6_linkstate_show_table(vty, detail, table); + + return CMD_SUCCESS; } -void -ospf6_brouter_show_header (struct vty *vty) +void ospf6_brouter_show_header(struct vty *vty) { - vty_out (vty, "%-15s %-8s %-14s %-10s %-15s\n", - "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area"); + vty_out(vty, "%-15s %-8s %-14s %-10s %-15s\n", "Router-ID", "Rtr-Bits", + "Options", "Path-Type", "Area"); } -void -ospf6_brouter_show (struct vty *vty, struct ospf6_route *route) +void ospf6_brouter_show(struct vty *vty, struct ospf6_route *route) { - u_int32_t adv_router; - char adv[16], rbits[16], options[16], area[16]; - - adv_router = ospf6_linkstate_prefix_adv_router (&route->prefix); - inet_ntop (AF_INET, &adv_router, adv, sizeof (adv)); - ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits)); - ospf6_options_printbuf (route->path.options, options, sizeof (options)); - inet_ntop (AF_INET, &route->path.area_id, area, sizeof (area)); - - /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s\n", - "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area"); */ - vty_out (vty, "%-15s %-8s %-14s %-10s %-15s\n", - adv, rbits, options, OSPF6_PATH_TYPE_NAME (route->path.type), - area); + u_int32_t adv_router; + char adv[16], rbits[16], options[16], area[16]; + + adv_router = ospf6_linkstate_prefix_adv_router(&route->prefix); + inet_ntop(AF_INET, &adv_router, adv, sizeof(adv)); + ospf6_capability_printbuf(route->path.router_bits, rbits, + sizeof(rbits)); + ospf6_options_printbuf(route->path.options, options, sizeof(options)); + inet_ntop(AF_INET, &route->path.area_id, area, sizeof(area)); + + /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s\n", + "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area"); */ + vty_out(vty, "%-15s %-8s %-14s %-10s %-15s\n", adv, rbits, options, + OSPF6_PATH_TYPE_NAME(route->path.type), area); } DEFUN (debug_ospf6_route, @@ -1570,19 +1457,19 @@ DEFUN (debug_ospf6_route, "Debug route memory use\n" ) { - int idx_type = 3; - unsigned char level = 0; - - if (! strncmp (argv[idx_type]->arg, "table", 5)) - level = OSPF6_DEBUG_ROUTE_TABLE; - else if (! strncmp (argv[idx_type]->arg, "intra", 5)) - level = OSPF6_DEBUG_ROUTE_INTRA; - else if (! strncmp (argv[idx_type]->arg, "inter", 5)) - level = OSPF6_DEBUG_ROUTE_INTER; - else if (! strncmp (argv[idx_type]->arg, "memor", 5)) - level = OSPF6_DEBUG_ROUTE_MEMORY; - OSPF6_DEBUG_ROUTE_ON (level); - return CMD_SUCCESS; + int idx_type = 3; + unsigned char level = 0; + + if (!strncmp(argv[idx_type]->arg, "table", 5)) + level = OSPF6_DEBUG_ROUTE_TABLE; + else if (!strncmp(argv[idx_type]->arg, "intra", 5)) + level = OSPF6_DEBUG_ROUTE_INTRA; + else if (!strncmp(argv[idx_type]->arg, "inter", 5)) + level = OSPF6_DEBUG_ROUTE_INTER; + else if (!strncmp(argv[idx_type]->arg, "memor", 5)) + level = OSPF6_DEBUG_ROUTE_MEMORY; + OSPF6_DEBUG_ROUTE_ON(level); + return CMD_SUCCESS; } DEFUN (no_debug_ospf6_route, @@ -1597,41 +1484,36 @@ DEFUN (no_debug_ospf6_route, "Debug inter-area route calculation\n" "Debug route memory use\n") { - int idx_type = 4; - unsigned char level = 0; - - if (! strncmp (argv[idx_type]->arg, "table", 5)) - level = OSPF6_DEBUG_ROUTE_TABLE; - else if (! strncmp (argv[idx_type]->arg, "intra", 5)) - level = OSPF6_DEBUG_ROUTE_INTRA; - else if (! strncmp (argv[idx_type]->arg, "inter", 5)) - level = OSPF6_DEBUG_ROUTE_INTER; - else if (! strncmp (argv[idx_type]->arg, "memor", 5)) - level = OSPF6_DEBUG_ROUTE_MEMORY; - OSPF6_DEBUG_ROUTE_OFF (level); - return CMD_SUCCESS; + int idx_type = 4; + unsigned char level = 0; + + if (!strncmp(argv[idx_type]->arg, "table", 5)) + level = OSPF6_DEBUG_ROUTE_TABLE; + else if (!strncmp(argv[idx_type]->arg, "intra", 5)) + level = OSPF6_DEBUG_ROUTE_INTRA; + else if (!strncmp(argv[idx_type]->arg, "inter", 5)) + level = OSPF6_DEBUG_ROUTE_INTER; + else if (!strncmp(argv[idx_type]->arg, "memor", 5)) + level = OSPF6_DEBUG_ROUTE_MEMORY; + OSPF6_DEBUG_ROUTE_OFF(level); + return CMD_SUCCESS; } -int -config_write_ospf6_debug_route (struct vty *vty) +int config_write_ospf6_debug_route(struct vty *vty) { - if (IS_OSPF6_DEBUG_ROUTE (TABLE)) - vty_out (vty, "debug ospf6 route table\n"); - if (IS_OSPF6_DEBUG_ROUTE (INTRA)) - vty_out (vty, "debug ospf6 route intra-area\n"); - if (IS_OSPF6_DEBUG_ROUTE (INTER)) - vty_out (vty, "debug ospf6 route inter-area\n"); - return 0; + if (IS_OSPF6_DEBUG_ROUTE(TABLE)) + vty_out(vty, "debug ospf6 route table\n"); + if (IS_OSPF6_DEBUG_ROUTE(INTRA)) + vty_out(vty, "debug ospf6 route intra-area\n"); + if (IS_OSPF6_DEBUG_ROUTE(INTER)) + vty_out(vty, "debug ospf6 route inter-area\n"); + return 0; } -void -install_element_ospf6_debug_route (void) +void install_element_ospf6_debug_route(void) { - install_element (ENABLE_NODE, &debug_ospf6_route_cmd); - install_element (ENABLE_NODE, &no_debug_ospf6_route_cmd); - install_element (CONFIG_NODE, &debug_ospf6_route_cmd); - install_element (CONFIG_NODE, &no_debug_ospf6_route_cmd); + install_element(ENABLE_NODE, &debug_ospf6_route_cmd); + install_element(ENABLE_NODE, &no_debug_ospf6_route_cmd); + install_element(CONFIG_NODE, &debug_ospf6_route_cmd); + install_element(CONFIG_NODE, &no_debug_ospf6_route_cmd); } - - - diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h index 7cf69a26e..69d275f8b 100644 --- a/ospf6d/ospf6_route.h +++ b/ospf6d/ospf6_route.h @@ -31,77 +31,70 @@ extern unsigned char conf_debug_ospf6_route; #define OSPF6_DEBUG_ROUTE_INTRA 0x02 #define OSPF6_DEBUG_ROUTE_INTER 0x04 #define OSPF6_DEBUG_ROUTE_MEMORY 0x80 -#define OSPF6_DEBUG_ROUTE_ON(level) \ - (conf_debug_ospf6_route |= (level)) -#define OSPF6_DEBUG_ROUTE_OFF(level) \ - (conf_debug_ospf6_route &= ~(level)) -#define IS_OSPF6_DEBUG_ROUTE(e) \ - (conf_debug_ospf6_route & OSPF6_DEBUG_ROUTE_ ## e) +#define OSPF6_DEBUG_ROUTE_ON(level) (conf_debug_ospf6_route |= (level)) +#define OSPF6_DEBUG_ROUTE_OFF(level) (conf_debug_ospf6_route &= ~(level)) +#define IS_OSPF6_DEBUG_ROUTE(e) (conf_debug_ospf6_route & OSPF6_DEBUG_ROUTE_##e) /* Nexthop */ -struct ospf6_nexthop -{ - /* Interface index */ - ifindex_t ifindex; +struct ospf6_nexthop { + /* Interface index */ + ifindex_t ifindex; - /* IP address, if any */ - struct in6_addr address; + /* IP address, if any */ + struct in6_addr address; }; -#define ospf6_nexthop_is_set(x) \ - ((x)->ifindex || ! IN6_IS_ADDR_UNSPECIFIED (&(x)->address)) -#define ospf6_nexthop_is_same(a,b) \ - ((a)->ifindex == (b)->ifindex && \ - IN6_ARE_ADDR_EQUAL (&(a)->address, &(b)->address)) -#define ospf6_nexthop_clear(x) \ - do { \ - (x)->ifindex = 0; \ - memset (&(x)->address, 0, sizeof (struct in6_addr)); \ - } while (0) -#define ospf6_nexthop_copy(a, b) \ - do { \ - (a)->ifindex = (b)->ifindex; \ - memcpy (&(a)->address, &(b)->address, \ - sizeof (struct in6_addr)); \ - } while (0) +#define ospf6_nexthop_is_set(x) \ + ((x)->ifindex || !IN6_IS_ADDR_UNSPECIFIED(&(x)->address)) +#define ospf6_nexthop_is_same(a, b) \ + ((a)->ifindex == (b)->ifindex \ + && IN6_ARE_ADDR_EQUAL(&(a)->address, &(b)->address)) +#define ospf6_nexthop_clear(x) \ + do { \ + (x)->ifindex = 0; \ + memset(&(x)->address, 0, sizeof(struct in6_addr)); \ + } while (0) +#define ospf6_nexthop_copy(a, b) \ + do { \ + (a)->ifindex = (b)->ifindex; \ + memcpy(&(a)->address, &(b)->address, sizeof(struct in6_addr)); \ + } while (0) /* Path */ -struct ospf6_ls_origin -{ - u_int16_t type; - u_int32_t id; - u_int32_t adv_router; +struct ospf6_ls_origin { + u_int16_t type; + u_int32_t id; + u_int32_t adv_router; }; -struct ospf6_path -{ - /* Link State Origin */ - struct ospf6_ls_origin origin; +struct ospf6_path { + /* Link State Origin */ + struct ospf6_ls_origin origin; - /* Router bits */ - u_char router_bits; + /* Router bits */ + u_char router_bits; - /* Optional Capabilities */ - u_char options[3]; + /* Optional Capabilities */ + u_char options[3]; - /* Prefix Options */ - u_char prefix_options; + /* Prefix Options */ + u_char prefix_options; - /* Associated Area */ - u_int32_t area_id; + /* Associated Area */ + u_int32_t area_id; - /* Path-type */ - u_char type; - u_char subtype; /* only used for redistribute i.e ZEBRA_ROUTE_XXX */ + /* Path-type */ + u_char type; + u_char subtype; /* only used for redistribute i.e ZEBRA_ROUTE_XXX */ - /* Cost */ - u_int8_t metric_type; - u_int32_t cost; - union { - u_int32_t cost_e2; - u_int32_t cost_config; - } u; - u_int32_t tag; + /* Cost */ + u_int8_t metric_type; + u_int32_t cost; + union { + u_int32_t cost_e2; + u_int32_t cost_config; + } u; + u_int32_t tag; }; #define OSPF6_PATH_TYPE_NONE 0 @@ -120,44 +113,43 @@ struct ospf6_path #include "table.h" #include "bitfield.h" -struct ospf6_route -{ - struct route_node *rnode; - struct ospf6_route_table *table; - struct ospf6_route *prev; - struct ospf6_route *next; +struct ospf6_route { + struct route_node *rnode; + struct ospf6_route_table *table; + struct ospf6_route *prev; + struct ospf6_route *next; - unsigned int lock; + unsigned int lock; - /* Destination Type */ - u_char type; + /* Destination Type */ + u_char type; - /* XXX: It would likely be better to use separate struct in_addr's - * for the advertising router-ID and prefix IDs, instead of stuffing them - * into one. See also XXX below. - */ - /* Destination ID */ - struct prefix prefix; + /* XXX: It would likely be better to use separate struct in_addr's + * for the advertising router-ID and prefix IDs, instead of stuffing + * them + * into one. See also XXX below. + */ + /* Destination ID */ + struct prefix prefix; - /* Time */ - struct timeval installed; - struct timeval changed; + /* Time */ + struct timeval installed; + struct timeval changed; - /* flag */ - u_char flag; + /* flag */ + u_char flag; - /* route option */ - void *route_option; + /* route option */ + void *route_option; - /* link state id for advertising */ - u_int32_t linkstate_id; + /* link state id for advertising */ + u_int32_t linkstate_id; - /* path */ - struct ospf6_path path; - - /* nexthop */ - struct list *nh_list; + /* path */ + struct ospf6_path path; + /* nexthop */ + struct list *nh_list; }; #define OSPF6_DEST_TYPE_NONE 0 @@ -177,23 +169,22 @@ struct ospf6_route #define OSPF6_ROUTE_WAS_REMOVED 0x40 #define OSPF6_ROUTE_BLACKHOLE_ADDED 0x80 -struct ospf6_route_table -{ - int scope_type; - int table_type; - void *scope; +struct ospf6_route_table { + int scope_type; + int table_type; + void *scope; - /* patricia tree */ - struct route_table *table; + /* patricia tree */ + struct route_table *table; - u_int32_t count; + u_int32_t count; - bitfield_t idspace; + bitfield_t idspace; - /* hooks */ - void (*hook_add) (struct ospf6_route *); - void (*hook_change) (struct ospf6_route *); - void (*hook_remove) (struct ospf6_route *); + /* hooks */ + void (*hook_add)(struct ospf6_route *); + void (*hook_change)(struct ospf6_route *); + void (*hook_remove)(struct ospf6_route *); }; #define OSPF6_SCOPE_TYPE_NONE 0 @@ -211,138 +202,135 @@ struct ospf6_route_table #define OSPF6_TABLE_TYPE_SUMMARY_PREFIXES 7 #define OSPF6_TABLE_TYPE_SUMMARY_ROUTERS 8 -#define OSPF6_ROUTE_TABLE_CREATE(s, t) \ - ospf6_route_table_create (OSPF6_SCOPE_TYPE_ ## s, \ - OSPF6_TABLE_TYPE_ ## t) +#define OSPF6_ROUTE_TABLE_CREATE(s, t) \ + ospf6_route_table_create(OSPF6_SCOPE_TYPE_##s, OSPF6_TABLE_TYPE_##t) extern const char *ospf6_dest_type_str[OSPF6_DEST_TYPE_MAX]; extern const char *ospf6_dest_type_substr[OSPF6_DEST_TYPE_MAX]; -#define OSPF6_DEST_TYPE_NAME(x) \ - (0 < (x) && (x) < OSPF6_DEST_TYPE_MAX ? \ - ospf6_dest_type_str[(x)] : ospf6_dest_type_str[0]) -#define OSPF6_DEST_TYPE_SUBSTR(x) \ - (0 < (x) && (x) < OSPF6_DEST_TYPE_MAX ? \ - ospf6_dest_type_substr[(x)] : ospf6_dest_type_substr[0]) +#define OSPF6_DEST_TYPE_NAME(x) \ + (0 < (x) && (x) < OSPF6_DEST_TYPE_MAX ? ospf6_dest_type_str[(x)] \ + : ospf6_dest_type_str[0]) +#define OSPF6_DEST_TYPE_SUBSTR(x) \ + (0 < (x) && (x) < OSPF6_DEST_TYPE_MAX ? ospf6_dest_type_substr[(x)] \ + : ospf6_dest_type_substr[0]) extern const char *ospf6_path_type_str[OSPF6_PATH_TYPE_MAX]; extern const char *ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX]; -#define OSPF6_PATH_TYPE_NAME(x) \ - (0 < (x) && (x) < OSPF6_PATH_TYPE_MAX ? \ - ospf6_path_type_str[(x)] : ospf6_path_type_str[0]) -#define OSPF6_PATH_TYPE_SUBSTR(x) \ - (0 < (x) && (x) < OSPF6_PATH_TYPE_MAX ? \ - ospf6_path_type_substr[(x)] : ospf6_path_type_substr[0]) +#define OSPF6_PATH_TYPE_NAME(x) \ + (0 < (x) && (x) < OSPF6_PATH_TYPE_MAX ? ospf6_path_type_str[(x)] \ + : ospf6_path_type_str[0]) +#define OSPF6_PATH_TYPE_SUBSTR(x) \ + (0 < (x) && (x) < OSPF6_PATH_TYPE_MAX ? ospf6_path_type_substr[(x)] \ + : ospf6_path_type_substr[0]) #define OSPF6_ROUTE_ADDRESS_STR "Display the route bestmatches the address\n" #define OSPF6_ROUTE_PREFIX_STR "Display the route\n" #define OSPF6_ROUTE_MATCH_STR "Display the route matches the prefix\n" -#define ospf6_route_is_prefix(p, r) \ - (memcmp (p, &(r)->prefix, sizeof (struct prefix)) == 0) -#define ospf6_route_is_same(ra, rb) \ - (prefix_same (&(ra)->prefix, &(rb)->prefix)) -#define ospf6_route_is_same_origin(ra, rb) \ - ((ra)->path.area_id == (rb)->path.area_id && \ - memcmp (&(ra)->path.origin, &(rb)->path.origin, \ - sizeof (struct ospf6_ls_origin)) == 0) -#define ospf6_route_is_identical(ra, rb) \ - ((ra)->type == (rb)->type && \ - memcmp (&(ra)->prefix, &(rb)->prefix, sizeof (struct prefix)) == 0 && \ - memcmp (&(ra)->path, &(rb)->path, sizeof (struct ospf6_path)) == 0 && \ - ospf6_route_cmp_nexthops (ra, rb) == 0) +#define ospf6_route_is_prefix(p, r) \ + (memcmp(p, &(r)->prefix, sizeof(struct prefix)) == 0) +#define ospf6_route_is_same(ra, rb) (prefix_same(&(ra)->prefix, &(rb)->prefix)) +#define ospf6_route_is_same_origin(ra, rb) \ + ((ra)->path.area_id == (rb)->path.area_id \ + && memcmp(&(ra)->path.origin, &(rb)->path.origin, \ + sizeof(struct ospf6_ls_origin)) \ + == 0) +#define ospf6_route_is_identical(ra, rb) \ + ((ra)->type == (rb)->type \ + && memcmp(&(ra)->prefix, &(rb)->prefix, sizeof(struct prefix)) == 0 \ + && memcmp(&(ra)->path, &(rb)->path, sizeof(struct ospf6_path)) == 0 \ + && ospf6_route_cmp_nexthops(ra, rb) == 0) #define ospf6_route_is_best(r) (CHECK_FLAG ((r)->flag, OSPF6_ROUTE_BEST)) -#define ospf6_linkstate_prefix_adv_router(x) \ - ((x)->u.lp.id.s_addr) -#define ospf6_linkstate_prefix_id(x) \ - ((x)->u.lp.adv_router.s_addr) +#define ospf6_linkstate_prefix_adv_router(x) ((x)->u.lp.id.s_addr) +#define ospf6_linkstate_prefix_id(x) ((x)->u.lp.adv_router.s_addr) -#define ADV_ROUTER_IN_PREFIX(x) \ - ((x)->u.lp.id.s_addr) +#define ADV_ROUTER_IN_PREFIX(x) ((x)->u.lp.id.s_addr) /* Function prototype */ -extern void ospf6_linkstate_prefix (u_int32_t adv_router, u_int32_t id, - struct prefix *prefix); -extern void ospf6_linkstate_prefix2str (struct prefix *prefix, char *buf, - int size); - -extern struct ospf6_nexthop *ospf6_nexthop_create (void); -extern void ospf6_nexthop_delete (struct ospf6_nexthop *nh); -extern void ospf6_free_nexthops (struct list *nh_list); -extern void ospf6_clear_nexthops (struct list *nh_list); -extern int ospf6_num_nexthops (struct list *nh_list); -extern void ospf6_copy_nexthops (struct list *dst, struct list *src); -extern void ospf6_merge_nexthops (struct list *dst, struct list *src); -extern void ospf6_add_nexthop (struct list *nh_list, int ifindex, - struct in6_addr *addr); -extern int ospf6_num_nexthops (struct list *nh_list); -extern int ospf6_route_cmp_nexthops (struct ospf6_route *a, - struct ospf6_route *b); -extern void ospf6_route_zebra_copy_nexthops (struct ospf6_route *route, - ifindex_t *ifindices, - struct in6_addr **addr, - int entries); -extern int ospf6_route_get_first_nh_index (struct ospf6_route *route); +extern void ospf6_linkstate_prefix(u_int32_t adv_router, u_int32_t id, + struct prefix *prefix); +extern void ospf6_linkstate_prefix2str(struct prefix *prefix, char *buf, + int size); + +extern struct ospf6_nexthop *ospf6_nexthop_create(void); +extern void ospf6_nexthop_delete(struct ospf6_nexthop *nh); +extern void ospf6_free_nexthops(struct list *nh_list); +extern void ospf6_clear_nexthops(struct list *nh_list); +extern int ospf6_num_nexthops(struct list *nh_list); +extern void ospf6_copy_nexthops(struct list *dst, struct list *src); +extern void ospf6_merge_nexthops(struct list *dst, struct list *src); +extern void ospf6_add_nexthop(struct list *nh_list, int ifindex, + struct in6_addr *addr); +extern int ospf6_num_nexthops(struct list *nh_list); +extern int ospf6_route_cmp_nexthops(struct ospf6_route *a, + struct ospf6_route *b); +extern void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route, + ifindex_t *ifindices, + struct in6_addr **addr, + int entries); +extern int ospf6_route_get_first_nh_index(struct ospf6_route *route); /* Hide abstraction of nexthop implementation in route from outsiders */ #define ospf6_route_copy_nexthops(dst, src) ospf6_copy_nexthops(dst->nh_list, src->nh_list) #define ospf6_route_merge_nexthops(dst, src) ospf6_merge_nexthops(dst->nh_list, src->nh_list) #define ospf6_route_num_nexthops(route) ospf6_num_nexthops(route->nh_list) -#define ospf6_route_add_nexthop(route, ifindex, addr) \ - ospf6_add_nexthop(route->nh_list, ifindex, addr) - -extern struct ospf6_route *ospf6_route_create (void); -extern void ospf6_route_delete (struct ospf6_route *); -extern struct ospf6_route *ospf6_route_copy (struct ospf6_route *route); -extern int ospf6_route_cmp (struct ospf6_route *ra, struct ospf6_route *rb); - -extern void ospf6_route_lock (struct ospf6_route *route); -extern void ospf6_route_unlock (struct ospf6_route *route); - -extern struct ospf6_route *ospf6_route_lookup (struct prefix *prefix, - struct ospf6_route_table *table); -extern struct ospf6_route *ospf6_route_lookup_identical (struct ospf6_route *route, - struct ospf6_route_table *table); -extern struct ospf6_route *ospf6_route_lookup_bestmatch (struct prefix *prefix, - struct ospf6_route_table *table); - -extern struct ospf6_route *ospf6_route_add (struct ospf6_route *route, - struct ospf6_route_table *table); -extern void ospf6_route_remove (struct ospf6_route *route, - struct ospf6_route_table *table); - -extern struct ospf6_route *ospf6_route_head (struct ospf6_route_table *table); -extern struct ospf6_route *ospf6_route_next (struct ospf6_route *route); -extern struct ospf6_route *ospf6_route_best_next (struct ospf6_route *route); - -extern struct ospf6_route *ospf6_route_match_head (struct prefix *prefix, - struct ospf6_route_table *table); -extern struct ospf6_route *ospf6_route_match_next (struct prefix *prefix, - struct ospf6_route *route); - -extern void ospf6_route_remove_all (struct ospf6_route_table *); -extern struct ospf6_route_table *ospf6_route_table_create (int s, int t); -extern void ospf6_route_table_delete (struct ospf6_route_table *); -extern void ospf6_route_dump (struct ospf6_route_table *table); - - -extern void ospf6_route_show (struct vty *vty, struct ospf6_route *route); -extern void ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route); - -extern int ospf6_route_table_show (struct vty *, int, int, struct cmd_token **, - struct ospf6_route_table *); -extern int ospf6_linkstate_table_show (struct vty *vty, int idx_ipv4, int argc, - struct cmd_token **argv, - struct ospf6_route_table *table); - -extern void ospf6_brouter_show_header (struct vty *vty); -extern void ospf6_brouter_show (struct vty *vty, struct ospf6_route *route); - -extern int config_write_ospf6_debug_route (struct vty *vty); -extern void install_element_ospf6_debug_route (void); -extern void ospf6_route_init (void); -extern void ospf6_clean (void); +#define ospf6_route_add_nexthop(route, ifindex, addr) \ + ospf6_add_nexthop(route->nh_list, ifindex, addr) + +extern struct ospf6_route *ospf6_route_create(void); +extern void ospf6_route_delete(struct ospf6_route *); +extern struct ospf6_route *ospf6_route_copy(struct ospf6_route *route); +extern int ospf6_route_cmp(struct ospf6_route *ra, struct ospf6_route *rb); + +extern void ospf6_route_lock(struct ospf6_route *route); +extern void ospf6_route_unlock(struct ospf6_route *route); + +extern struct ospf6_route *ospf6_route_lookup(struct prefix *prefix, + struct ospf6_route_table *table); +extern struct ospf6_route * +ospf6_route_lookup_identical(struct ospf6_route *route, + struct ospf6_route_table *table); +extern struct ospf6_route * +ospf6_route_lookup_bestmatch(struct prefix *prefix, + struct ospf6_route_table *table); + +extern struct ospf6_route *ospf6_route_add(struct ospf6_route *route, + struct ospf6_route_table *table); +extern void ospf6_route_remove(struct ospf6_route *route, + struct ospf6_route_table *table); + +extern struct ospf6_route *ospf6_route_head(struct ospf6_route_table *table); +extern struct ospf6_route *ospf6_route_next(struct ospf6_route *route); +extern struct ospf6_route *ospf6_route_best_next(struct ospf6_route *route); + +extern struct ospf6_route * +ospf6_route_match_head(struct prefix *prefix, struct ospf6_route_table *table); +extern struct ospf6_route *ospf6_route_match_next(struct prefix *prefix, + struct ospf6_route *route); + +extern void ospf6_route_remove_all(struct ospf6_route_table *); +extern struct ospf6_route_table *ospf6_route_table_create(int s, int t); +extern void ospf6_route_table_delete(struct ospf6_route_table *); +extern void ospf6_route_dump(struct ospf6_route_table *table); + + +extern void ospf6_route_show(struct vty *vty, struct ospf6_route *route); +extern void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route); + +extern int ospf6_route_table_show(struct vty *, int, int, struct cmd_token **, + struct ospf6_route_table *); +extern int ospf6_linkstate_table_show(struct vty *vty, int idx_ipv4, int argc, + struct cmd_token **argv, + struct ospf6_route_table *table); + +extern void ospf6_brouter_show_header(struct vty *vty); +extern void ospf6_brouter_show(struct vty *vty, struct ospf6_route *route); + +extern int config_write_ospf6_debug_route(struct vty *vty); +extern void install_element_ospf6_debug_route(void); +extern void ospf6_route_init(void); +extern void ospf6_clean(void); #endif /* OSPF6_ROUTE_H */ - diff --git a/ospf6d/ospf6_snmp.c b/ospf6d/ospf6_snmp.c index 29327bd38..0b399bad1 100644 --- a/ospf6d/ospf6_snmp.c +++ b/ospf6d/ospf6_snmp.c @@ -205,1007 +205,1208 @@ SNMP_LOCAL_VARIABLES /* OSPFv3-MIB instances. */ -static oid ospfv3_oid [] = { OSPFv3MIB }; -static oid ospfv3_trap_oid [] = { OSPFv3MIB, 0 }; +static oid ospfv3_oid[] = {OSPFv3MIB}; +static oid ospfv3_trap_oid[] = {OSPFv3MIB, 0}; /* Hook functions. */ -static u_char *ospfv3GeneralGroup (struct variable *, oid *, size_t *, - int, size_t *, WriteMethod **); -static u_char *ospfv3AreaEntry (struct variable *, oid *, size_t *, - int, size_t *, WriteMethod **); -static u_char *ospfv3WwLsdbEntry (struct variable *, oid *, size_t *, - int, size_t *, WriteMethod **); -static u_char *ospfv3NbrEntry (struct variable *, oid *, size_t *, - int, size_t *, WriteMethod **); -static u_char *ospfv3IfEntry (struct variable *, oid *, size_t *, - int, size_t *, WriteMethod **); - -static struct variable ospfv3_variables[] = -{ - /* OSPF general variables */ - {OSPFv3ROUTERID, UNSIGNED, RWRITE, ospfv3GeneralGroup, - 3, {1, 1, 1}}, - {OSPFv3ADMINSTAT, INTEGER, RWRITE, ospfv3GeneralGroup, - 3, {1, 1, 2}}, - {OSPFv3VERSIONNUMBER, INTEGER, RONLY, ospfv3GeneralGroup, - 3, {1, 1, 3}}, - {OSPFv3AREABDRRTRSTATUS, INTEGER, RONLY, ospfv3GeneralGroup, - 3, {1, 1, 4}}, - {OSPFv3ASBDRRTRSTATUS, INTEGER, RWRITE, ospfv3GeneralGroup, - 3, {1, 1, 5}}, - {OSPFv3ASSCOPELSACOUNT, GAUGE, RONLY, ospfv3GeneralGroup, - 3, {1, 1, 6}}, - {OSPFv3ASSCOPELSACHECKSUMSUM,UNSIGNED, RONLY, ospfv3GeneralGroup, - 3, {1, 1, 7}}, - {OSPFv3ORIGINATENEWLSAS, COUNTER, RONLY, ospfv3GeneralGroup, - 3, {1, 1, 8}}, - {OSPFv3RXNEWLSAS, COUNTER, RONLY, ospfv3GeneralGroup, - 3, {1, 1, 9}}, - {OSPFv3EXTLSACOUNT, GAUGE, RONLY, ospfv3GeneralGroup, - 3, {1, 1, 10}}, - {OSPFv3EXTAREALSDBLIMIT, INTEGER, RWRITE, ospfv3GeneralGroup, - 3, {1, 1, 11}}, - {OSPFv3EXITOVERFLOWINTERVAL, UNSIGNED, RWRITE, ospfv3GeneralGroup, - 3, {1, 1, 12}}, - {OSPFv3DEMANDEXTENSIONS, INTEGER, RWRITE, ospfv3GeneralGroup, - 3, {1, 1, 13}}, - {OSPFv3REFERENCEBANDWIDTH, UNSIGNED, RWRITE, ospfv3GeneralGroup, - 3, {1, 1, 14}}, - {OSPFv3RESTARTSUPPORT, INTEGER, RWRITE, ospfv3GeneralGroup, - 3, {1, 1, 15}}, - {OSPFv3RESTARTINTERVAL, UNSIGNED, RWRITE, ospfv3GeneralGroup, - 3, {1, 1, 16}}, - {OSPFv3RESTARTSTRICTLSACHECKING, INTEGER, RWRITE, ospfv3GeneralGroup, - 3, {1, 1, 17}}, - {OSPFv3RESTARTSTATUS, INTEGER, RONLY, ospfv3GeneralGroup, - 3, {1, 1, 18}}, - {OSPFv3RESTARTAGE, UNSIGNED, RONLY, ospfv3GeneralGroup, - 3, {1, 1, 19}}, - {OSPFv3RESTARTEXITREASON, INTEGER, RONLY, ospfv3GeneralGroup, - 3, {1, 1, 20}}, - {OSPFv3NOTIFICATIONENABLE, INTEGER, RWRITE, ospfv3GeneralGroup, - 3, {1, 1, 21}}, - {OSPFv3STUBROUTERSUPPORT, INTEGER, RONLY, ospfv3GeneralGroup, - 3, {1, 1, 22}}, - {OSPFv3STUBROUTERADVERTISEMENT, INTEGER, RWRITE, ospfv3GeneralGroup, - 3, {1, 1, 23}}, - {OSPFv3DISCONTINUITYTIME, TIMETICKS, RONLY, ospfv3GeneralGroup, - 3, {1, 1, 24}}, - {OSPFv3RESTARTTIME, TIMETICKS, RONLY, ospfv3GeneralGroup, - 3, {1, 1, 25}}, - - /* OSPFv3 Area Data Structure */ - {OSPFv3IMPORTASEXTERN, INTEGER, RWRITE, ospfv3AreaEntry, - 4, {1, 2, 1, 2}}, - {OSPFv3AREASPFRUNS, COUNTER, RONLY, ospfv3AreaEntry, - 4, {1, 2, 1, 3}}, - {OSPFv3AREABDRRTRCOUNT, GAUGE, RONLY, ospfv3AreaEntry, - 4, {1, 2, 1, 4}}, - {OSPFv3AREAASBDRRTRCOUNT, GAUGE, RONLY, ospfv3AreaEntry, - 4, {1, 2, 1, 5}}, - {OSPFv3AREASCOPELSACOUNT, GAUGE, RONLY, ospfv3AreaEntry, - 4, {1, 2, 1, 6}}, - {OSPFv3AREASCOPELSACKSUMSUM, UNSIGNED, RONLY, ospfv3AreaEntry, - 4, {1, 2, 1, 7}}, - {OSPFv3AREASUMMARY, INTEGER, RWRITE, ospfv3AreaEntry, - 4, {1, 2, 1, 8}}, - {OSPFv3AREAROWSTATUS, INTEGER, RWRITE, ospfv3AreaEntry, - 4, {1, 2, 1, 9}}, - {OSPFv3AREASTUBMETRIC, INTEGER, RWRITE, ospfv3AreaEntry, - 4, {1, 2, 1, 10}}, - {OSPFv3AREANSSATRANSLATORROLE, INTEGER, RWRITE, ospfv3AreaEntry, - 4, {1, 2, 1, 11}}, - {OSPFv3AREANSSATRANSLATORSTATE, INTEGER, RONLY, ospfv3AreaEntry, - 4, {1, 2, 1, 12}}, - {OSPFv3AREANSSATRANSLATORSTABINTERVAL, UNSIGNED, RWRITE, ospfv3AreaEntry, - 4, {1, 2, 1, 13}}, - {OSPFv3AREANSSATRANSLATOREVENTS, COUNTER, RONLY, ospfv3AreaEntry, - 4, {1, 2, 1, 14}}, - {OSPFv3AREASTUBMETRICTYPE, INTEGER, RWRITE, ospfv3AreaEntry, - 4, {1, 2, 1, 15}}, - {OSPFv3AREATEENABLED, INTEGER, RWRITE, ospfv3AreaEntry, - 4, {1, 2, 1, 16}}, - - /* OSPFv3 AS LSDB */ - {OSPFv3WWLSDBSEQUENCE | OSPFv3WWASTABLE, INTEGER, RONLY, ospfv3WwLsdbEntry, - 4, {1, 3, 1, 4}}, - {OSPFv3WWLSDBAGE | OSPFv3WWASTABLE, UNSIGNED, RONLY, ospfv3WwLsdbEntry, - 4, {1, 3, 1, 5}}, - {OSPFv3WWLSDBCHECKSUM | OSPFv3WWASTABLE, INTEGER, RONLY, ospfv3WwLsdbEntry, - 4, {1, 3, 1, 6}}, - {OSPFv3WWLSDBADVERTISEMENT | OSPFv3WWASTABLE, STRING, RONLY, ospfv3WwLsdbEntry, - 4, {1, 3, 1, 7}}, - {OSPFv3WWLSDBTYPEKNOWN | OSPFv3WWASTABLE, INTEGER, RONLY, ospfv3WwLsdbEntry, - 4, {1, 3, 1, 8}}, - - /* OSPFv3 Area LSDB */ - {OSPFv3WWLSDBSEQUENCE | OSPFv3WWAREATABLE, INTEGER, RONLY, ospfv3WwLsdbEntry, - 4, {1, 4, 1, 5}}, - {OSPFv3WWLSDBAGE | OSPFv3WWAREATABLE, UNSIGNED, RONLY, ospfv3WwLsdbEntry, - 4, {1, 4, 1, 6}}, - {OSPFv3WWLSDBCHECKSUM | OSPFv3WWAREATABLE, INTEGER, RONLY, ospfv3WwLsdbEntry, - 4, {1, 4, 1, 7}}, - {OSPFv3WWLSDBADVERTISEMENT | OSPFv3WWAREATABLE, STRING, RONLY, ospfv3WwLsdbEntry, - 4, {1, 4, 1, 8}}, - {OSPFv3WWLSDBTYPEKNOWN | OSPFv3WWAREATABLE, INTEGER, RONLY, ospfv3WwLsdbEntry, - 4, {1, 4, 1, 9}}, - - /* OSPFv3 Link LSDB */ - {OSPFv3WWLSDBSEQUENCE | OSPFv3WWLINKTABLE, INTEGER, RONLY, ospfv3WwLsdbEntry, - 4, {1, 5, 1, 6}}, - {OSPFv3WWLSDBAGE | OSPFv3WWLINKTABLE, UNSIGNED, RONLY, ospfv3WwLsdbEntry, - 4, {1, 5, 1, 7}}, - {OSPFv3WWLSDBCHECKSUM | OSPFv3WWLINKTABLE, INTEGER, RONLY, ospfv3WwLsdbEntry, - 4, {1, 5, 1, 8}}, - {OSPFv3WWLSDBADVERTISEMENT | OSPFv3WWLINKTABLE, STRING, RONLY, ospfv3WwLsdbEntry, - 4, {1, 5, 1, 9}}, - {OSPFv3WWLSDBTYPEKNOWN | OSPFv3WWLINKTABLE, INTEGER, RONLY, ospfv3WwLsdbEntry, - 4, {1, 5, 1, 10}}, - - /* OSPFv3 interfaces */ - {OSPFv3IFAREAID, UNSIGNED, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 3}}, - {OSPFv3IFTYPE, INTEGER, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 4}}, - {OSPFv3IFADMINSTATUS, INTEGER, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 5}}, - {OSPFv3IFRTRPRIORITY, INTEGER, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 6}}, - {OSPFv3IFTRANSITDELAY, UNSIGNED, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 7}}, - {OSPFv3IFRETRANSINTERVAL, UNSIGNED, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 8}}, - {OSPFv3IFHELLOINTERVAL, INTEGER, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 9}}, - {OSPFv3IFRTRDEADINTERVAL, UNSIGNED, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 10}}, - {OSPFv3IFPOLLINTERVAL, UNSIGNED, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 11}}, - {OSPFv3IFSTATE, INTEGER, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 12}}, - {OSPFv3IFDESIGNATEDROUTER, UNSIGNED, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 13}}, - {OSPFv3IFBACKUPDESIGNATEDROUTER, UNSIGNED, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 14}}, - {OSPFv3IFEVENTS, COUNTER, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 15}}, - {OSPFv3IFROWSTATUS, INTEGER, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 16}}, - {OSPFv3IFDEMAND, INTEGER, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 17}}, - {OSPFv3IFMETRICVALUE, INTEGER, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 18}}, - {OSPFv3IFLINKSCOPELSACOUNT, GAUGE, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 19}}, - {OSPFv3IFLINKLSACKSUMSUM, UNSIGNED, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 20}}, - {OSPFv3IFDEMANDNBRPROBE, INTEGER, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 21}}, - {OSPFv3IFDEMANDNBRPROBERETRANSLIMIT, UNSIGNED, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 22}}, - {OSPFv3IFDEMANDNBRPROBEINTERVAL, UNSIGNED, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 23}}, - {OSPFv3IFTEDISABLED, INTEGER, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 24}}, - {OSPFv3IFLINKLSASUPPRESSION, INTEGER, RONLY, ospfv3IfEntry, - 4, {1, 7, 1, 25}}, - - /* OSPFv3 neighbors */ - {OSPFv3NBRADDRESSTYPE, INTEGER, RONLY, ospfv3NbrEntry, - 4, {1, 9, 1, 4}}, - {OSPFv3NBRADDRESS, STRING, RONLY, ospfv3NbrEntry, - 4, {1, 9, 1, 5}}, - {OSPFv3NBROPTIONS, INTEGER, RONLY, ospfv3NbrEntry, - 4, {1, 9, 1, 6}}, - {OSPFv3NBRPRIORITY, INTEGER, RONLY, ospfv3NbrEntry, - 4, {1, 9, 1, 7}}, - {OSPFv3NBRSTATE, INTEGER, RONLY, ospfv3NbrEntry, - 4, {1, 9, 1, 8}}, - {OSPFv3NBREVENTS, COUNTER, RONLY, ospfv3NbrEntry, - 4, {1, 9, 1, 9}}, - {OSPFv3NBRLSRETRANSQLEN, GAUGE, RONLY, ospfv3NbrEntry, - 4, {1, 9, 1, 10}}, - {OSPFv3NBRHELLOSUPPRESSED, INTEGER, RONLY, ospfv3NbrEntry, - 4, {1, 9, 1, 11}}, - {OSPFv3NBRIFID, INTEGER, RONLY, ospfv3NbrEntry, - 4, {1, 9, 1, 12}}, - {OSPFv3NBRRESTARTHELPERSTATUS, INTEGER, RONLY, ospfv3NbrEntry, - 4, {1, 9, 1, 13}}, - {OSPFv3NBRRESTARTHELPERAGE, UNSIGNED, RONLY, ospfv3NbrEntry, - 4, {1, 9, 1, 14}}, - {OSPFv3NBRRESTARTHELPEREXITREASON, INTEGER, RONLY, ospfv3NbrEntry, - 4, {1, 9, 1, 15}}, +static u_char *ospfv3GeneralGroup(struct variable *, oid *, size_t *, int, + size_t *, WriteMethod **); +static u_char *ospfv3AreaEntry(struct variable *, oid *, size_t *, int, + size_t *, WriteMethod **); +static u_char *ospfv3WwLsdbEntry(struct variable *, oid *, size_t *, int, + size_t *, WriteMethod **); +static u_char *ospfv3NbrEntry(struct variable *, oid *, size_t *, int, size_t *, + WriteMethod **); +static u_char *ospfv3IfEntry(struct variable *, oid *, size_t *, int, size_t *, + WriteMethod **); + +static struct variable ospfv3_variables[] = { + /* OSPF general variables */ + {OSPFv3ROUTERID, UNSIGNED, RWRITE, ospfv3GeneralGroup, 3, {1, 1, 1}}, + {OSPFv3ADMINSTAT, INTEGER, RWRITE, ospfv3GeneralGroup, 3, {1, 1, 2}}, + {OSPFv3VERSIONNUMBER, INTEGER, RONLY, ospfv3GeneralGroup, 3, {1, 1, 3}}, + {OSPFv3AREABDRRTRSTATUS, + INTEGER, + RONLY, + ospfv3GeneralGroup, + 3, + {1, 1, 4}}, + {OSPFv3ASBDRRTRSTATUS, + INTEGER, + RWRITE, + ospfv3GeneralGroup, + 3, + {1, 1, 5}}, + {OSPFv3ASSCOPELSACOUNT, GAUGE, RONLY, ospfv3GeneralGroup, 3, {1, 1, 6}}, + {OSPFv3ASSCOPELSACHECKSUMSUM, + UNSIGNED, + RONLY, + ospfv3GeneralGroup, + 3, + {1, 1, 7}}, + {OSPFv3ORIGINATENEWLSAS, + COUNTER, + RONLY, + ospfv3GeneralGroup, + 3, + {1, 1, 8}}, + {OSPFv3RXNEWLSAS, COUNTER, RONLY, ospfv3GeneralGroup, 3, {1, 1, 9}}, + {OSPFv3EXTLSACOUNT, GAUGE, RONLY, ospfv3GeneralGroup, 3, {1, 1, 10}}, + {OSPFv3EXTAREALSDBLIMIT, + INTEGER, + RWRITE, + ospfv3GeneralGroup, + 3, + {1, 1, 11}}, + {OSPFv3EXITOVERFLOWINTERVAL, + UNSIGNED, + RWRITE, + ospfv3GeneralGroup, + 3, + {1, 1, 12}}, + {OSPFv3DEMANDEXTENSIONS, + INTEGER, + RWRITE, + ospfv3GeneralGroup, + 3, + {1, 1, 13}}, + {OSPFv3REFERENCEBANDWIDTH, + UNSIGNED, + RWRITE, + ospfv3GeneralGroup, + 3, + {1, 1, 14}}, + {OSPFv3RESTARTSUPPORT, + INTEGER, + RWRITE, + ospfv3GeneralGroup, + 3, + {1, 1, 15}}, + {OSPFv3RESTARTINTERVAL, + UNSIGNED, + RWRITE, + ospfv3GeneralGroup, + 3, + {1, 1, 16}}, + {OSPFv3RESTARTSTRICTLSACHECKING, + INTEGER, + RWRITE, + ospfv3GeneralGroup, + 3, + {1, 1, 17}}, + {OSPFv3RESTARTSTATUS, + INTEGER, + RONLY, + ospfv3GeneralGroup, + 3, + {1, 1, 18}}, + {OSPFv3RESTARTAGE, UNSIGNED, RONLY, ospfv3GeneralGroup, 3, {1, 1, 19}}, + {OSPFv3RESTARTEXITREASON, + INTEGER, + RONLY, + ospfv3GeneralGroup, + 3, + {1, 1, 20}}, + {OSPFv3NOTIFICATIONENABLE, + INTEGER, + RWRITE, + ospfv3GeneralGroup, + 3, + {1, 1, 21}}, + {OSPFv3STUBROUTERSUPPORT, + INTEGER, + RONLY, + ospfv3GeneralGroup, + 3, + {1, 1, 22}}, + {OSPFv3STUBROUTERADVERTISEMENT, + INTEGER, + RWRITE, + ospfv3GeneralGroup, + 3, + {1, 1, 23}}, + {OSPFv3DISCONTINUITYTIME, + TIMETICKS, + RONLY, + ospfv3GeneralGroup, + 3, + {1, 1, 24}}, + {OSPFv3RESTARTTIME, + TIMETICKS, + RONLY, + ospfv3GeneralGroup, + 3, + {1, 1, 25}}, + + /* OSPFv3 Area Data Structure */ + {OSPFv3IMPORTASEXTERN, + INTEGER, + RWRITE, + ospfv3AreaEntry, + 4, + {1, 2, 1, 2}}, + {OSPFv3AREASPFRUNS, COUNTER, RONLY, ospfv3AreaEntry, 4, {1, 2, 1, 3}}, + {OSPFv3AREABDRRTRCOUNT, GAUGE, RONLY, ospfv3AreaEntry, 4, {1, 2, 1, 4}}, + {OSPFv3AREAASBDRRTRCOUNT, + GAUGE, + RONLY, + ospfv3AreaEntry, + 4, + {1, 2, 1, 5}}, + {OSPFv3AREASCOPELSACOUNT, + GAUGE, + RONLY, + ospfv3AreaEntry, + 4, + {1, 2, 1, 6}}, + {OSPFv3AREASCOPELSACKSUMSUM, + UNSIGNED, + RONLY, + ospfv3AreaEntry, + 4, + {1, 2, 1, 7}}, + {OSPFv3AREASUMMARY, INTEGER, RWRITE, ospfv3AreaEntry, 4, {1, 2, 1, 8}}, + {OSPFv3AREAROWSTATUS, + INTEGER, + RWRITE, + ospfv3AreaEntry, + 4, + {1, 2, 1, 9}}, + {OSPFv3AREASTUBMETRIC, + INTEGER, + RWRITE, + ospfv3AreaEntry, + 4, + {1, 2, 1, 10}}, + {OSPFv3AREANSSATRANSLATORROLE, + INTEGER, + RWRITE, + ospfv3AreaEntry, + 4, + {1, 2, 1, 11}}, + {OSPFv3AREANSSATRANSLATORSTATE, + INTEGER, + RONLY, + ospfv3AreaEntry, + 4, + {1, 2, 1, 12}}, + {OSPFv3AREANSSATRANSLATORSTABINTERVAL, + UNSIGNED, + RWRITE, + ospfv3AreaEntry, + 4, + {1, 2, 1, 13}}, + {OSPFv3AREANSSATRANSLATOREVENTS, + COUNTER, + RONLY, + ospfv3AreaEntry, + 4, + {1, 2, 1, 14}}, + {OSPFv3AREASTUBMETRICTYPE, + INTEGER, + RWRITE, + ospfv3AreaEntry, + 4, + {1, 2, 1, 15}}, + {OSPFv3AREATEENABLED, + INTEGER, + RWRITE, + ospfv3AreaEntry, + 4, + {1, 2, 1, 16}}, + + /* OSPFv3 AS LSDB */ + {OSPFv3WWLSDBSEQUENCE | OSPFv3WWASTABLE, + INTEGER, + RONLY, + ospfv3WwLsdbEntry, + 4, + {1, 3, 1, 4}}, + {OSPFv3WWLSDBAGE | OSPFv3WWASTABLE, + UNSIGNED, + RONLY, + ospfv3WwLsdbEntry, + 4, + {1, 3, 1, 5}}, + {OSPFv3WWLSDBCHECKSUM | OSPFv3WWASTABLE, + INTEGER, + RONLY, + ospfv3WwLsdbEntry, + 4, + {1, 3, 1, 6}}, + {OSPFv3WWLSDBADVERTISEMENT | OSPFv3WWASTABLE, + STRING, + RONLY, + ospfv3WwLsdbEntry, + 4, + {1, 3, 1, 7}}, + {OSPFv3WWLSDBTYPEKNOWN | OSPFv3WWASTABLE, + INTEGER, + RONLY, + ospfv3WwLsdbEntry, + 4, + {1, 3, 1, 8}}, + + /* OSPFv3 Area LSDB */ + {OSPFv3WWLSDBSEQUENCE | OSPFv3WWAREATABLE, + INTEGER, + RONLY, + ospfv3WwLsdbEntry, + 4, + {1, 4, 1, 5}}, + {OSPFv3WWLSDBAGE | OSPFv3WWAREATABLE, + UNSIGNED, + RONLY, + ospfv3WwLsdbEntry, + 4, + {1, 4, 1, 6}}, + {OSPFv3WWLSDBCHECKSUM | OSPFv3WWAREATABLE, + INTEGER, + RONLY, + ospfv3WwLsdbEntry, + 4, + {1, 4, 1, 7}}, + {OSPFv3WWLSDBADVERTISEMENT | OSPFv3WWAREATABLE, + STRING, + RONLY, + ospfv3WwLsdbEntry, + 4, + {1, 4, 1, 8}}, + {OSPFv3WWLSDBTYPEKNOWN | OSPFv3WWAREATABLE, + INTEGER, + RONLY, + ospfv3WwLsdbEntry, + 4, + {1, 4, 1, 9}}, + + /* OSPFv3 Link LSDB */ + {OSPFv3WWLSDBSEQUENCE | OSPFv3WWLINKTABLE, + INTEGER, + RONLY, + ospfv3WwLsdbEntry, + 4, + {1, 5, 1, 6}}, + {OSPFv3WWLSDBAGE | OSPFv3WWLINKTABLE, + UNSIGNED, + RONLY, + ospfv3WwLsdbEntry, + 4, + {1, 5, 1, 7}}, + {OSPFv3WWLSDBCHECKSUM | OSPFv3WWLINKTABLE, + INTEGER, + RONLY, + ospfv3WwLsdbEntry, + 4, + {1, 5, 1, 8}}, + {OSPFv3WWLSDBADVERTISEMENT | OSPFv3WWLINKTABLE, + STRING, + RONLY, + ospfv3WwLsdbEntry, + 4, + {1, 5, 1, 9}}, + {OSPFv3WWLSDBTYPEKNOWN | OSPFv3WWLINKTABLE, + INTEGER, + RONLY, + ospfv3WwLsdbEntry, + 4, + {1, 5, 1, 10}}, + + /* OSPFv3 interfaces */ + {OSPFv3IFAREAID, UNSIGNED, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 3}}, + {OSPFv3IFTYPE, INTEGER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 4}}, + {OSPFv3IFADMINSTATUS, INTEGER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 5}}, + {OSPFv3IFRTRPRIORITY, INTEGER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 6}}, + {OSPFv3IFTRANSITDELAY, UNSIGNED, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 7}}, + {OSPFv3IFRETRANSINTERVAL, + UNSIGNED, + RONLY, + ospfv3IfEntry, + 4, + {1, 7, 1, 8}}, + {OSPFv3IFHELLOINTERVAL, INTEGER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 9}}, + {OSPFv3IFRTRDEADINTERVAL, + UNSIGNED, + RONLY, + ospfv3IfEntry, + 4, + {1, 7, 1, 10}}, + {OSPFv3IFPOLLINTERVAL, + UNSIGNED, + RONLY, + ospfv3IfEntry, + 4, + {1, 7, 1, 11}}, + {OSPFv3IFSTATE, INTEGER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 12}}, + {OSPFv3IFDESIGNATEDROUTER, + UNSIGNED, + RONLY, + ospfv3IfEntry, + 4, + {1, 7, 1, 13}}, + {OSPFv3IFBACKUPDESIGNATEDROUTER, + UNSIGNED, + RONLY, + ospfv3IfEntry, + 4, + {1, 7, 1, 14}}, + {OSPFv3IFEVENTS, COUNTER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 15}}, + {OSPFv3IFROWSTATUS, INTEGER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 16}}, + {OSPFv3IFDEMAND, INTEGER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 17}}, + {OSPFv3IFMETRICVALUE, INTEGER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 18}}, + {OSPFv3IFLINKSCOPELSACOUNT, + GAUGE, + RONLY, + ospfv3IfEntry, + 4, + {1, 7, 1, 19}}, + {OSPFv3IFLINKLSACKSUMSUM, + UNSIGNED, + RONLY, + ospfv3IfEntry, + 4, + {1, 7, 1, 20}}, + {OSPFv3IFDEMANDNBRPROBE, + INTEGER, + RONLY, + ospfv3IfEntry, + 4, + {1, 7, 1, 21}}, + {OSPFv3IFDEMANDNBRPROBERETRANSLIMIT, + UNSIGNED, + RONLY, + ospfv3IfEntry, + 4, + {1, 7, 1, 22}}, + {OSPFv3IFDEMANDNBRPROBEINTERVAL, + UNSIGNED, + RONLY, + ospfv3IfEntry, + 4, + {1, 7, 1, 23}}, + {OSPFv3IFTEDISABLED, INTEGER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 24}}, + {OSPFv3IFLINKLSASUPPRESSION, + INTEGER, + RONLY, + ospfv3IfEntry, + 4, + {1, 7, 1, 25}}, + + /* OSPFv3 neighbors */ + {OSPFv3NBRADDRESSTYPE, INTEGER, RONLY, ospfv3NbrEntry, 4, {1, 9, 1, 4}}, + {OSPFv3NBRADDRESS, STRING, RONLY, ospfv3NbrEntry, 4, {1, 9, 1, 5}}, + {OSPFv3NBROPTIONS, INTEGER, RONLY, ospfv3NbrEntry, 4, {1, 9, 1, 6}}, + {OSPFv3NBRPRIORITY, INTEGER, RONLY, ospfv3NbrEntry, 4, {1, 9, 1, 7}}, + {OSPFv3NBRSTATE, INTEGER, RONLY, ospfv3NbrEntry, 4, {1, 9, 1, 8}}, + {OSPFv3NBREVENTS, COUNTER, RONLY, ospfv3NbrEntry, 4, {1, 9, 1, 9}}, + {OSPFv3NBRLSRETRANSQLEN, + GAUGE, + RONLY, + ospfv3NbrEntry, + 4, + {1, 9, 1, 10}}, + {OSPFv3NBRHELLOSUPPRESSED, + INTEGER, + RONLY, + ospfv3NbrEntry, + 4, + {1, 9, 1, 11}}, + {OSPFv3NBRIFID, INTEGER, RONLY, ospfv3NbrEntry, 4, {1, 9, 1, 12}}, + {OSPFv3NBRRESTARTHELPERSTATUS, + INTEGER, + RONLY, + ospfv3NbrEntry, + 4, + {1, 9, 1, 13}}, + {OSPFv3NBRRESTARTHELPERAGE, + UNSIGNED, + RONLY, + ospfv3NbrEntry, + 4, + {1, 9, 1, 14}}, + {OSPFv3NBRRESTARTHELPEREXITREASON, + INTEGER, + RONLY, + ospfv3NbrEntry, + 4, + {1, 9, 1, 15}}, }; -static u_char * -ospfv3GeneralGroup (struct variable *v, oid *name, size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *ospfv3GeneralGroup(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - u_int16_t sum; - u_int32_t count; - struct ospf6_lsa *lsa = NULL; - - /* Check whether the instance identifier is valid */ - if (smux_header_generic (v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - /* Return the current value of the variable */ - switch (v->magic) - { - case OSPFv3ROUTERID: - /* Router-ID of this OSPF instance. */ - if (ospf6) - return SNMP_INTEGER (ntohl (ospf6->router_id)); - return SNMP_INTEGER (0); - case OSPFv3ADMINSTAT: - if (ospf6) - return SNMP_INTEGER (CHECK_FLAG (ospf6->flag, OSPF6_DISABLED)? - OSPF_STATUS_DISABLED:OSPF_STATUS_ENABLED); - return SNMP_INTEGER (OSPF_STATUS_DISABLED); - case OSPFv3VERSIONNUMBER: - return SNMP_INTEGER (3); - case OSPFv3AREABDRRTRSTATUS: - if (ospf6) - return SNMP_INTEGER (ospf6_is_router_abr (ospf6)?SNMP_TRUE:SNMP_FALSE); - return SNMP_INTEGER (SNMP_FALSE); - case OSPFv3ASBDRRTRSTATUS: - if (ospf6) - return SNMP_INTEGER (ospf6_asbr_is_asbr (ospf6)?SNMP_TRUE:SNMP_FALSE); - return SNMP_INTEGER (SNMP_FALSE); - case OSPFv3ASSCOPELSACOUNT: - if (ospf6) - return SNMP_INTEGER (ospf6->lsdb->count); - return SNMP_INTEGER (0); - case OSPFv3ASSCOPELSACHECKSUMSUM: - if (ospf6) - { - sum = 0; - for (ALL_LSDB(ospf6->lsdb, lsa)) - sum += ntohs (lsa->header->checksum); - return SNMP_INTEGER (sum); - } - return SNMP_INTEGER (0); - case OSPFv3ORIGINATENEWLSAS: - return SNMP_INTEGER (0); /* Don't know where to get this value... */ - case OSPFv3RXNEWLSAS: - return SNMP_INTEGER (0); /* Don't know where to get this value... */ - case OSPFv3EXTLSACOUNT: - if (ospf6) - { - count = 0; - for (ALL_LSDB_TYPED(ospf6->lsdb, htons (OSPF6_LSTYPE_AS_EXTERNAL), lsa)) - count += 1; - return SNMP_INTEGER (count); - } - return SNMP_INTEGER (0); - case OSPFv3EXTAREALSDBLIMIT: - return SNMP_INTEGER (-1); - case OSPFv3EXITOVERFLOWINTERVAL: - return SNMP_INTEGER (0); /* Not supported */ - case OSPFv3DEMANDEXTENSIONS: - return SNMP_INTEGER (0); /* Not supported */ - case OSPFv3REFERENCEBANDWIDTH: - if (ospf6) - return SNMP_INTEGER (ospf6->ref_bandwidth); - /* Otherwise, like for "not implemented". */ - /* fallthru */ - case OSPFv3RESTARTSUPPORT: - case OSPFv3RESTARTINTERVAL: - case OSPFv3RESTARTSTRICTLSACHECKING: - case OSPFv3RESTARTSTATUS: - case OSPFv3RESTARTAGE: - case OSPFv3RESTARTEXITREASON: - case OSPFv3NOTIFICATIONENABLE: - case OSPFv3STUBROUTERSUPPORT: - case OSPFv3STUBROUTERADVERTISEMENT: - case OSPFv3DISCONTINUITYTIME: - case OSPFv3RESTARTTIME: - /* TODO: Not implemented */ - return NULL; - } - return NULL; + u_int16_t sum; + u_int32_t count; + struct ospf6_lsa *lsa = NULL; + + /* Check whether the instance identifier is valid */ + if (smux_header_generic(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + /* Return the current value of the variable */ + switch (v->magic) { + case OSPFv3ROUTERID: + /* Router-ID of this OSPF instance. */ + if (ospf6) + return SNMP_INTEGER(ntohl(ospf6->router_id)); + return SNMP_INTEGER(0); + case OSPFv3ADMINSTAT: + if (ospf6) + return SNMP_INTEGER( + CHECK_FLAG(ospf6->flag, OSPF6_DISABLED) + ? OSPF_STATUS_DISABLED + : OSPF_STATUS_ENABLED); + return SNMP_INTEGER(OSPF_STATUS_DISABLED); + case OSPFv3VERSIONNUMBER: + return SNMP_INTEGER(3); + case OSPFv3AREABDRRTRSTATUS: + if (ospf6) + return SNMP_INTEGER(ospf6_is_router_abr(ospf6) + ? SNMP_TRUE + : SNMP_FALSE); + return SNMP_INTEGER(SNMP_FALSE); + case OSPFv3ASBDRRTRSTATUS: + if (ospf6) + return SNMP_INTEGER(ospf6_asbr_is_asbr(ospf6) + ? SNMP_TRUE + : SNMP_FALSE); + return SNMP_INTEGER(SNMP_FALSE); + case OSPFv3ASSCOPELSACOUNT: + if (ospf6) + return SNMP_INTEGER(ospf6->lsdb->count); + return SNMP_INTEGER(0); + case OSPFv3ASSCOPELSACHECKSUMSUM: + if (ospf6) { + sum = 0; + for (ALL_LSDB(ospf6->lsdb, lsa)) + sum += ntohs(lsa->header->checksum); + return SNMP_INTEGER(sum); + } + return SNMP_INTEGER(0); + case OSPFv3ORIGINATENEWLSAS: + return SNMP_INTEGER( + 0); /* Don't know where to get this value... */ + case OSPFv3RXNEWLSAS: + return SNMP_INTEGER( + 0); /* Don't know where to get this value... */ + case OSPFv3EXTLSACOUNT: + if (ospf6) { + count = 0; + for (ALL_LSDB_TYPED(ospf6->lsdb, + htons(OSPF6_LSTYPE_AS_EXTERNAL), + lsa)) + count += 1; + return SNMP_INTEGER(count); + } + return SNMP_INTEGER(0); + case OSPFv3EXTAREALSDBLIMIT: + return SNMP_INTEGER(-1); + case OSPFv3EXITOVERFLOWINTERVAL: + return SNMP_INTEGER(0); /* Not supported */ + case OSPFv3DEMANDEXTENSIONS: + return SNMP_INTEGER(0); /* Not supported */ + case OSPFv3REFERENCEBANDWIDTH: + if (ospf6) + return SNMP_INTEGER(ospf6->ref_bandwidth); + /* Otherwise, like for "not implemented". */ + /* fallthru */ + case OSPFv3RESTARTSUPPORT: + case OSPFv3RESTARTINTERVAL: + case OSPFv3RESTARTSTRICTLSACHECKING: + case OSPFv3RESTARTSTATUS: + case OSPFv3RESTARTAGE: + case OSPFv3RESTARTEXITREASON: + case OSPFv3NOTIFICATIONENABLE: + case OSPFv3STUBROUTERSUPPORT: + case OSPFv3STUBROUTERADVERTISEMENT: + case OSPFv3DISCONTINUITYTIME: + case OSPFv3RESTARTTIME: + /* TODO: Not implemented */ + return NULL; + } + return NULL; } -static u_char * -ospfv3AreaEntry (struct variable *v, oid *name, size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *ospfv3AreaEntry(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - struct ospf6_area *oa, *area = NULL; - struct ospf6_lsa *lsa = NULL; - u_int32_t area_id = 0; - u_int32_t count; - u_int16_t sum; - struct listnode *node; - unsigned int len; - char a[16]; - struct ospf6_route *ro; - - if (ospf6 == NULL) - return NULL; - - if (smux_header_table(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - len = *length - v->namelen; - len = (len >= 1 ? 1 : 0); - if (exact && len != 1) - return NULL; - if (len) - area_id = htonl (name[v->namelen]); - - inet_ntop (AF_INET, &area_id, a, sizeof (a)); - zlog_debug ("SNMP access by area: %s, exact=%d len=%d length=%lu", - a, exact, len, (u_long)*length); - - for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa)) - { - if (area == NULL) - { - if (len == 0) /* return first area entry */ - area = oa; - else if (exact && ntohl (oa->area_id) == ntohl (area_id)) - area = oa; - else if (ntohl (oa->area_id) > ntohl (area_id)) - area = oa; - } - } - - if (area == NULL) - return NULL; - - *length = v->namelen + 1; - name[v->namelen] = ntohl (area->area_id); - - inet_ntop (AF_INET, &area->area_id, a, sizeof (a)); - zlog_debug ("SNMP found area: %s, exact=%d len=%d length=%lu", - a, exact, len, (u_long)*length); - - switch (v->magic) - { - case OSPFv3IMPORTASEXTERN: - /* No NSSA support */ - return SNMP_INTEGER (IS_AREA_STUB(area)?2:1); - case OSPFv3AREASPFRUNS: - return SNMP_INTEGER (area->spf_calculation); - case OSPFv3AREABDRRTRCOUNT: - case OSPFv3AREAASBDRRTRCOUNT: - count = 0; - for (ro = ospf6_route_head (ospf6->brouter_table); ro; - ro = ospf6_route_next (ro)) - { - if (ntohl (ro->path.area_id) != ntohl (area->area_id)) continue; - if (v->magic == OSPFv3AREABDRRTRCOUNT && - CHECK_FLAG (ro->path.router_bits, OSPF6_ROUTER_BIT_B)) - count++; - if (v->magic == OSPFv3AREAASBDRRTRCOUNT && - CHECK_FLAG (ro->path.router_bits, OSPF6_ROUTER_BIT_E)) - count++; - } - return SNMP_INTEGER (count); - case OSPFv3AREASCOPELSACOUNT: - return SNMP_INTEGER (area->lsdb->count); - case OSPFv3AREASCOPELSACKSUMSUM: - sum = 0; - for (ALL_LSDB(area->lsdb, lsa)) - sum += ntohs (lsa->header->checksum); - return SNMP_INTEGER (sum); - case OSPFv3AREASUMMARY: - return SNMP_INTEGER (2); /* sendAreaSummary */ - case OSPFv3AREAROWSTATUS: - return SNMP_INTEGER (1); /* Active */ - case OSPFv3AREASTUBMETRIC: - case OSPFv3AREANSSATRANSLATORROLE: - case OSPFv3AREANSSATRANSLATORSTATE: - case OSPFv3AREANSSATRANSLATORSTABINTERVAL: - case OSPFv3AREANSSATRANSLATOREVENTS: - case OSPFv3AREASTUBMETRICTYPE: - case OSPFv3AREATEENABLED: - /* Not implemented. */ - return NULL; - } - return NULL; + struct ospf6_area *oa, *area = NULL; + struct ospf6_lsa *lsa = NULL; + u_int32_t area_id = 0; + u_int32_t count; + u_int16_t sum; + struct listnode *node; + unsigned int len; + char a[16]; + struct ospf6_route *ro; + + if (ospf6 == NULL) + return NULL; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + len = *length - v->namelen; + len = (len >= 1 ? 1 : 0); + if (exact && len != 1) + return NULL; + if (len) + area_id = htonl(name[v->namelen]); + + inet_ntop(AF_INET, &area_id, a, sizeof(a)); + zlog_debug("SNMP access by area: %s, exact=%d len=%d length=%lu", a, + exact, len, (u_long)*length); + + for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) { + if (area == NULL) { + if (len == 0) /* return first area entry */ + area = oa; + else if (exact && ntohl(oa->area_id) == ntohl(area_id)) + area = oa; + else if (ntohl(oa->area_id) > ntohl(area_id)) + area = oa; + } + } + + if (area == NULL) + return NULL; + + *length = v->namelen + 1; + name[v->namelen] = ntohl(area->area_id); + + inet_ntop(AF_INET, &area->area_id, a, sizeof(a)); + zlog_debug("SNMP found area: %s, exact=%d len=%d length=%lu", a, exact, + len, (u_long)*length); + + switch (v->magic) { + case OSPFv3IMPORTASEXTERN: + /* No NSSA support */ + return SNMP_INTEGER(IS_AREA_STUB(area) ? 2 : 1); + case OSPFv3AREASPFRUNS: + return SNMP_INTEGER(area->spf_calculation); + case OSPFv3AREABDRRTRCOUNT: + case OSPFv3AREAASBDRRTRCOUNT: + count = 0; + for (ro = ospf6_route_head(ospf6->brouter_table); ro; + ro = ospf6_route_next(ro)) { + if (ntohl(ro->path.area_id) != ntohl(area->area_id)) + continue; + if (v->magic == OSPFv3AREABDRRTRCOUNT + && CHECK_FLAG(ro->path.router_bits, + OSPF6_ROUTER_BIT_B)) + count++; + if (v->magic == OSPFv3AREAASBDRRTRCOUNT + && CHECK_FLAG(ro->path.router_bits, + OSPF6_ROUTER_BIT_E)) + count++; + } + return SNMP_INTEGER(count); + case OSPFv3AREASCOPELSACOUNT: + return SNMP_INTEGER(area->lsdb->count); + case OSPFv3AREASCOPELSACKSUMSUM: + sum = 0; + for (ALL_LSDB(area->lsdb, lsa)) + sum += ntohs(lsa->header->checksum); + return SNMP_INTEGER(sum); + case OSPFv3AREASUMMARY: + return SNMP_INTEGER(2); /* sendAreaSummary */ + case OSPFv3AREAROWSTATUS: + return SNMP_INTEGER(1); /* Active */ + case OSPFv3AREASTUBMETRIC: + case OSPFv3AREANSSATRANSLATORROLE: + case OSPFv3AREANSSATRANSLATORSTATE: + case OSPFv3AREANSSATRANSLATORSTABINTERVAL: + case OSPFv3AREANSSATRANSLATOREVENTS: + case OSPFv3AREASTUBMETRICTYPE: + case OSPFv3AREATEENABLED: + /* Not implemented. */ + return NULL; + } + return NULL; } -static int -if_icmp_func (struct interface *ifp1, struct interface *ifp2) +static int if_icmp_func(struct interface *ifp1, struct interface *ifp2) { - return (ifp1->ifindex - ifp2->ifindex); + return (ifp1->ifindex - ifp2->ifindex); } -static u_char * -ospfv3WwLsdbEntry (struct variable *v, oid *name, size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *ospfv3WwLsdbEntry(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - struct ospf6_lsa *lsa = NULL; - ifindex_t ifindex; - uint32_t area_id, id, instid, adv_router; - u_int16_t type; - int len; - oid *offset; - int offsetlen; - struct ospf6_area *oa = NULL; - struct listnode *node; - struct interface *iif; - struct ospf6_interface *oi = NULL; - struct list *ifslist; - - if (smux_header_table(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - instid = ifindex = area_id = type = id = adv_router = 0; - - /* Check OSPFv3 instance. */ - if (ospf6 == NULL) - return NULL; - - /* Get variable length. */ - offset = name + v->namelen; - offsetlen = *length - v->namelen; - - if (exact && (v->magic & OSPFv3WWASTABLE) && offsetlen != 3) - return NULL; - if (exact && (v->magic & OSPFv3WWAREATABLE) && offsetlen != 4) - return NULL; - if (exact && (v->magic & OSPFv3WWLINKTABLE) && offsetlen != 5) - return NULL; - - if (v->magic & OSPFv3WWLINKTABLE) - { - /* Parse ifindex */ - len = (offsetlen < 1 ? 0 : 1); - if (len) - ifindex = *offset; - offset += len; - offsetlen -= len; - - /* Parse instance ID */ - len = (offsetlen < 1 ? 0 : 1); - if (len) - instid = *offset; - offset += len; - offsetlen -= len; - } - else if (v->magic & OSPFv3WWAREATABLE) - { - /* Parse area-id */ - len = (offsetlen < 1 ? 0 : 1); - if (len) - area_id = htonl (*offset); - offset += len; - offsetlen -= len; - } - - /* Parse type */ - len = (offsetlen < 1 ? 0 : 1); - if (len) - type = htons (*offset); - offset += len; - offsetlen -= len; - - /* Parse Router-ID */ - len = (offsetlen < 1 ? 0 : 1); - if (len) - adv_router = htonl (*offset); - offset += len; - offsetlen -= len; - - /* Parse LS-ID */ - len = (offsetlen < 1 ? 0 : 1); - if (len) - id = htonl (*offset); - offset += len; - offsetlen -= len; - - if (exact) - { - if (v->magic & OSPFv3WWASTABLE) - { - lsa = ospf6_lsdb_lookup (type, id, adv_router, ospf6->lsdb); - } - else if (v->magic & OSPFv3WWAREATABLE) - { - oa = ospf6_area_lookup (area_id, ospf6); - if (!oa) return NULL; - lsa = ospf6_lsdb_lookup (type, id, adv_router, oa->lsdb); - } - else if (v->magic & OSPFv3WWLINKTABLE) - { - oi = ospf6_interface_lookup_by_ifindex (ifindex); - if (!oi || oi->instance_id != instid) return NULL; - lsa = ospf6_lsdb_lookup (type, id, adv_router, oi->lsdb); - } - } - else - { - if (v->magic & OSPFv3WWASTABLE) - { - if (ospf6->lsdb->count) - lsa = ospf6_lsdb_lookup_next (type, id, adv_router, - ospf6->lsdb); + struct ospf6_lsa *lsa = NULL; + ifindex_t ifindex; + uint32_t area_id, id, instid, adv_router; + u_int16_t type; + int len; + oid *offset; + int offsetlen; + struct ospf6_area *oa = NULL; + struct listnode *node; + struct interface *iif; + struct ospf6_interface *oi = NULL; + struct list *ifslist; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + instid = ifindex = area_id = type = id = adv_router = 0; + + /* Check OSPFv3 instance. */ + if (ospf6 == NULL) + return NULL; + + /* Get variable length. */ + offset = name + v->namelen; + offsetlen = *length - v->namelen; + + if (exact && (v->magic & OSPFv3WWASTABLE) && offsetlen != 3) + return NULL; + if (exact && (v->magic & OSPFv3WWAREATABLE) && offsetlen != 4) + return NULL; + if (exact && (v->magic & OSPFv3WWLINKTABLE) && offsetlen != 5) + return NULL; + + if (v->magic & OSPFv3WWLINKTABLE) { + /* Parse ifindex */ + len = (offsetlen < 1 ? 0 : 1); + if (len) + ifindex = *offset; + offset += len; + offsetlen -= len; + + /* Parse instance ID */ + len = (offsetlen < 1 ? 0 : 1); + if (len) + instid = *offset; + offset += len; + offsetlen -= len; + } else if (v->magic & OSPFv3WWAREATABLE) { + /* Parse area-id */ + len = (offsetlen < 1 ? 0 : 1); + if (len) + area_id = htonl(*offset); + offset += len; + offsetlen -= len; } - else if (v->magic & OSPFv3WWAREATABLE) - for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa)) - { - if (oa->area_id < area_id) - continue; - - if (oa->lsdb->count) - lsa = ospf6_lsdb_lookup_next (type, id, adv_router, - oa->lsdb); - if (lsa) break; - type = 0; - id = 0; - adv_router = 0; - } - else if (v->magic & OSPFv3WWLINKTABLE) - { - /* We build a sorted list of interfaces */ - ifslist = list_new (); - if (!ifslist) return NULL; - ifslist->cmp = (int (*)(void *, void *))if_icmp_func; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, iif)) - listnode_add_sort (ifslist, iif); - - for (ALL_LIST_ELEMENTS_RO (ifslist, node, iif)) - { - if (!iif->ifindex) continue; - oi = ospf6_interface_lookup_by_ifindex (iif->ifindex); - if (!oi) continue; - if (iif->ifindex < ifindex) continue; - if (oi->instance_id < instid) continue; - - if (oi->lsdb->count) - lsa = ospf6_lsdb_lookup_next (type, id, adv_router, - oi->lsdb); - if (lsa) break; - type = 0; - id = 0; - adv_router = 0; - oi = NULL; - } - - list_delete_all_node (ifslist); - } - } - - if (! lsa) - return NULL; - - /* Add indexes */ - if (v->magic & OSPFv3WWASTABLE) - { - *length = v->namelen + 3; - offset = name + v->namelen; - } - else if (v->magic & OSPFv3WWAREATABLE) - { - *length = v->namelen + 4; - offset = name + v->namelen; - *offset = ntohl (oa->area_id); - offset++; - } - else if (v->magic & OSPFv3WWLINKTABLE) - { - *length = v->namelen + 5; - offset = name + v->namelen; - *offset = oi->interface->ifindex; - offset++; - *offset = oi->instance_id; - offset++; - } - *offset = ntohs (lsa->header->type); - offset++; - *offset = ntohl (lsa->header->adv_router); - offset++; - *offset = ntohl (lsa->header->id); - offset++; - - /* Return the current value of the variable */ - switch (v->magic & OSPFv3WWCOLUMN) - { - case OSPFv3WWLSDBSEQUENCE: - return SNMP_INTEGER (ntohl (lsa->header->seqnum)); - break; - case OSPFv3WWLSDBAGE: - ospf6_lsa_age_current (lsa); - return SNMP_INTEGER (ntohs (lsa->header->age)); - break; - case OSPFv3WWLSDBCHECKSUM: - return SNMP_INTEGER (ntohs (lsa->header->checksum)); - break; - case OSPFv3WWLSDBADVERTISEMENT: - *var_len = ntohs (lsa->header->length); - return (u_char *) lsa->header; - break; - case OSPFv3WWLSDBTYPEKNOWN: - return SNMP_INTEGER (OSPF6_LSA_IS_KNOWN (lsa->header->type) ? - SNMP_TRUE : SNMP_FALSE); - break; - } - return NULL; + + /* Parse type */ + len = (offsetlen < 1 ? 0 : 1); + if (len) + type = htons(*offset); + offset += len; + offsetlen -= len; + + /* Parse Router-ID */ + len = (offsetlen < 1 ? 0 : 1); + if (len) + adv_router = htonl(*offset); + offset += len; + offsetlen -= len; + + /* Parse LS-ID */ + len = (offsetlen < 1 ? 0 : 1); + if (len) + id = htonl(*offset); + offset += len; + offsetlen -= len; + + if (exact) { + if (v->magic & OSPFv3WWASTABLE) { + lsa = ospf6_lsdb_lookup(type, id, adv_router, + ospf6->lsdb); + } else if (v->magic & OSPFv3WWAREATABLE) { + oa = ospf6_area_lookup(area_id, ospf6); + if (!oa) + return NULL; + lsa = ospf6_lsdb_lookup(type, id, adv_router, oa->lsdb); + } else if (v->magic & OSPFv3WWLINKTABLE) { + oi = ospf6_interface_lookup_by_ifindex(ifindex); + if (!oi || oi->instance_id != instid) + return NULL; + lsa = ospf6_lsdb_lookup(type, id, adv_router, oi->lsdb); + } + } else { + if (v->magic & OSPFv3WWASTABLE) { + if (ospf6->lsdb->count) + lsa = ospf6_lsdb_lookup_next( + type, id, adv_router, ospf6->lsdb); + } else if (v->magic & OSPFv3WWAREATABLE) + for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) { + if (oa->area_id < area_id) + continue; + + if (oa->lsdb->count) + lsa = ospf6_lsdb_lookup_next( + type, id, adv_router, oa->lsdb); + if (lsa) + break; + type = 0; + id = 0; + adv_router = 0; + } + else if (v->magic & OSPFv3WWLINKTABLE) { + /* We build a sorted list of interfaces */ + ifslist = list_new(); + if (!ifslist) + return NULL; + ifslist->cmp = (int (*)(void *, void *))if_icmp_func; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, + iif)) + listnode_add_sort(ifslist, iif); + + for (ALL_LIST_ELEMENTS_RO(ifslist, node, iif)) { + if (!iif->ifindex) + continue; + oi = ospf6_interface_lookup_by_ifindex( + iif->ifindex); + if (!oi) + continue; + if (iif->ifindex < ifindex) + continue; + if (oi->instance_id < instid) + continue; + + if (oi->lsdb->count) + lsa = ospf6_lsdb_lookup_next( + type, id, adv_router, oi->lsdb); + if (lsa) + break; + type = 0; + id = 0; + adv_router = 0; + oi = NULL; + } + + list_delete_all_node(ifslist); + } + } + + if (!lsa) + return NULL; + + /* Add indexes */ + if (v->magic & OSPFv3WWASTABLE) { + *length = v->namelen + 3; + offset = name + v->namelen; + } else if (v->magic & OSPFv3WWAREATABLE) { + *length = v->namelen + 4; + offset = name + v->namelen; + *offset = ntohl(oa->area_id); + offset++; + } else if (v->magic & OSPFv3WWLINKTABLE) { + *length = v->namelen + 5; + offset = name + v->namelen; + *offset = oi->interface->ifindex; + offset++; + *offset = oi->instance_id; + offset++; + } + *offset = ntohs(lsa->header->type); + offset++; + *offset = ntohl(lsa->header->adv_router); + offset++; + *offset = ntohl(lsa->header->id); + offset++; + + /* Return the current value of the variable */ + switch (v->magic & OSPFv3WWCOLUMN) { + case OSPFv3WWLSDBSEQUENCE: + return SNMP_INTEGER(ntohl(lsa->header->seqnum)); + break; + case OSPFv3WWLSDBAGE: + ospf6_lsa_age_current(lsa); + return SNMP_INTEGER(ntohs(lsa->header->age)); + break; + case OSPFv3WWLSDBCHECKSUM: + return SNMP_INTEGER(ntohs(lsa->header->checksum)); + break; + case OSPFv3WWLSDBADVERTISEMENT: + *var_len = ntohs(lsa->header->length); + return (u_char *)lsa->header; + break; + case OSPFv3WWLSDBTYPEKNOWN: + return SNMP_INTEGER(OSPF6_LSA_IS_KNOWN(lsa->header->type) + ? SNMP_TRUE + : SNMP_FALSE); + break; + } + return NULL; } -static u_char * -ospfv3IfEntry (struct variable *v, oid *name, size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *ospfv3IfEntry(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - ifindex_t ifindex = 0; - unsigned int instid = 0; - struct ospf6_interface *oi = NULL; - struct ospf6_lsa *lsa = NULL; - struct interface *iif; - struct listnode *i; - struct list *ifslist; - oid *offset; - int offsetlen, len; - u_int32_t sum; - - if (smux_header_table (v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - /* Check OSPFv3 instance. */ - if (ospf6 == NULL) - return NULL; - - /* Get variable length. */ - offset = name + v->namelen; - offsetlen = *length - v->namelen; - - if (exact && offsetlen != 2) - return NULL; - - /* Parse if index */ - len = (offsetlen < 1 ? 0 : 1); - if (len) - ifindex = *offset; - offset += len; - offsetlen -= len; - - /* Parse instance ID */ - len = (offsetlen < 1 ? 0 : 1); - if (len) - instid = *offset; - offset += len; - offsetlen -= len; - - if (exact) - { - oi = ospf6_interface_lookup_by_ifindex (ifindex); - if (!oi || oi->instance_id != instid) return NULL; - } - else - { - /* We build a sorted list of interfaces */ - ifslist = list_new (); - if (!ifslist) return NULL; - ifslist->cmp = (int (*)(void *, void *))if_icmp_func; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), i, iif)) - listnode_add_sort (ifslist, iif); - - for (ALL_LIST_ELEMENTS_RO (ifslist, i, iif)) - { - if (!iif->ifindex) continue; - oi = ospf6_interface_lookup_by_ifindex (iif->ifindex); - if (!oi) continue; - if (iif->ifindex > ifindex || - (iif->ifindex == ifindex && - (oi->instance_id > instid))) - break; - oi = NULL; - } - - list_delete_all_node (ifslist); - } - - if (!oi) return NULL; - - /* Add Index (IfIndex, IfInstId) */ - *length = v->namelen + 2; - offset = name + v->namelen; - *offset = oi->interface->ifindex; - offset++; - *offset = oi->instance_id; - offset++; - - /* Return the current value of the variable */ - switch (v->magic) - { - case OSPFv3IFAREAID: - if (oi->area) - return SNMP_INTEGER (ntohl (oi->area->area_id)); - break; - case OSPFv3IFTYPE: - if (if_is_broadcast (oi->interface)) - return SNMP_INTEGER (1); - else if (if_is_pointopoint (oi->interface)) - return SNMP_INTEGER (3); - else break; /* Unknown, don't put anything */ - case OSPFv3IFADMINSTATUS: - if (oi->area) - return SNMP_INTEGER (OSPF_STATUS_ENABLED); - return SNMP_INTEGER (OSPF_STATUS_DISABLED); - case OSPFv3IFRTRPRIORITY: - return SNMP_INTEGER (oi->priority); - case OSPFv3IFTRANSITDELAY: - return SNMP_INTEGER (oi->transdelay); - case OSPFv3IFRETRANSINTERVAL: - return SNMP_INTEGER (oi->rxmt_interval); - case OSPFv3IFHELLOINTERVAL: - return SNMP_INTEGER (oi->hello_interval); - case OSPFv3IFRTRDEADINTERVAL: - return SNMP_INTEGER (oi->dead_interval); - case OSPFv3IFPOLLINTERVAL: - /* No support for NBMA */ - break; - case OSPFv3IFSTATE: - return SNMP_INTEGER (oi->state); - case OSPFv3IFDESIGNATEDROUTER: - return SNMP_INTEGER (ntohl (oi->drouter)); - case OSPFv3IFBACKUPDESIGNATEDROUTER: - return SNMP_INTEGER (ntohl (oi->bdrouter)); - case OSPFv3IFEVENTS: - return SNMP_INTEGER (oi->state_change); - case OSPFv3IFROWSTATUS: - return SNMP_INTEGER (1); - case OSPFv3IFDEMAND: - return SNMP_INTEGER (SNMP_FALSE); - case OSPFv3IFMETRICVALUE: - return SNMP_INTEGER (oi->cost); - case OSPFv3IFLINKSCOPELSACOUNT: - return SNMP_INTEGER (oi->lsdb->count); - case OSPFv3IFLINKLSACKSUMSUM: - sum = 0; - for (ALL_LSDB(oi->lsdb, lsa)) - sum += ntohs (lsa->header->checksum); - return SNMP_INTEGER (sum); - case OSPFv3IFDEMANDNBRPROBE: - case OSPFv3IFDEMANDNBRPROBERETRANSLIMIT: - case OSPFv3IFDEMANDNBRPROBEINTERVAL: - case OSPFv3IFTEDISABLED: - case OSPFv3IFLINKLSASUPPRESSION: - /* Not implemented. Only works if all the last ones are not - implemented! */ - return NULL; - } - - /* Try an internal getnext. Some columns are missing in this table. */ - if (!exact && (name[*length-1] < MAX_SUBID)) - return ospfv3IfEntry(v, name, length, - exact, var_len, write_method); - return NULL; + ifindex_t ifindex = 0; + unsigned int instid = 0; + struct ospf6_interface *oi = NULL; + struct ospf6_lsa *lsa = NULL; + struct interface *iif; + struct listnode *i; + struct list *ifslist; + oid *offset; + int offsetlen, len; + u_int32_t sum; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + /* Check OSPFv3 instance. */ + if (ospf6 == NULL) + return NULL; + + /* Get variable length. */ + offset = name + v->namelen; + offsetlen = *length - v->namelen; + + if (exact && offsetlen != 2) + return NULL; + + /* Parse if index */ + len = (offsetlen < 1 ? 0 : 1); + if (len) + ifindex = *offset; + offset += len; + offsetlen -= len; + + /* Parse instance ID */ + len = (offsetlen < 1 ? 0 : 1); + if (len) + instid = *offset; + offset += len; + offsetlen -= len; + + if (exact) { + oi = ospf6_interface_lookup_by_ifindex(ifindex); + if (!oi || oi->instance_id != instid) + return NULL; + } else { + /* We build a sorted list of interfaces */ + ifslist = list_new(); + if (!ifslist) + return NULL; + ifslist->cmp = (int (*)(void *, void *))if_icmp_func; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), i, iif)) + listnode_add_sort(ifslist, iif); + + for (ALL_LIST_ELEMENTS_RO(ifslist, i, iif)) { + if (!iif->ifindex) + continue; + oi = ospf6_interface_lookup_by_ifindex(iif->ifindex); + if (!oi) + continue; + if (iif->ifindex > ifindex + || (iif->ifindex == ifindex + && (oi->instance_id > instid))) + break; + oi = NULL; + } + + list_delete_all_node(ifslist); + } + + if (!oi) + return NULL; + + /* Add Index (IfIndex, IfInstId) */ + *length = v->namelen + 2; + offset = name + v->namelen; + *offset = oi->interface->ifindex; + offset++; + *offset = oi->instance_id; + offset++; + + /* Return the current value of the variable */ + switch (v->magic) { + case OSPFv3IFAREAID: + if (oi->area) + return SNMP_INTEGER(ntohl(oi->area->area_id)); + break; + case OSPFv3IFTYPE: + if (if_is_broadcast(oi->interface)) + return SNMP_INTEGER(1); + else if (if_is_pointopoint(oi->interface)) + return SNMP_INTEGER(3); + else + break; /* Unknown, don't put anything */ + case OSPFv3IFADMINSTATUS: + if (oi->area) + return SNMP_INTEGER(OSPF_STATUS_ENABLED); + return SNMP_INTEGER(OSPF_STATUS_DISABLED); + case OSPFv3IFRTRPRIORITY: + return SNMP_INTEGER(oi->priority); + case OSPFv3IFTRANSITDELAY: + return SNMP_INTEGER(oi->transdelay); + case OSPFv3IFRETRANSINTERVAL: + return SNMP_INTEGER(oi->rxmt_interval); + case OSPFv3IFHELLOINTERVAL: + return SNMP_INTEGER(oi->hello_interval); + case OSPFv3IFRTRDEADINTERVAL: + return SNMP_INTEGER(oi->dead_interval); + case OSPFv3IFPOLLINTERVAL: + /* No support for NBMA */ + break; + case OSPFv3IFSTATE: + return SNMP_INTEGER(oi->state); + case OSPFv3IFDESIGNATEDROUTER: + return SNMP_INTEGER(ntohl(oi->drouter)); + case OSPFv3IFBACKUPDESIGNATEDROUTER: + return SNMP_INTEGER(ntohl(oi->bdrouter)); + case OSPFv3IFEVENTS: + return SNMP_INTEGER(oi->state_change); + case OSPFv3IFROWSTATUS: + return SNMP_INTEGER(1); + case OSPFv3IFDEMAND: + return SNMP_INTEGER(SNMP_FALSE); + case OSPFv3IFMETRICVALUE: + return SNMP_INTEGER(oi->cost); + case OSPFv3IFLINKSCOPELSACOUNT: + return SNMP_INTEGER(oi->lsdb->count); + case OSPFv3IFLINKLSACKSUMSUM: + sum = 0; + for (ALL_LSDB(oi->lsdb, lsa)) + sum += ntohs(lsa->header->checksum); + return SNMP_INTEGER(sum); + case OSPFv3IFDEMANDNBRPROBE: + case OSPFv3IFDEMANDNBRPROBERETRANSLIMIT: + case OSPFv3IFDEMANDNBRPROBEINTERVAL: + case OSPFv3IFTEDISABLED: + case OSPFv3IFLINKLSASUPPRESSION: + /* Not implemented. Only works if all the last ones are not + implemented! */ + return NULL; + } + + /* Try an internal getnext. Some columns are missing in this table. */ + if (!exact && (name[*length - 1] < MAX_SUBID)) + return ospfv3IfEntry(v, name, length, exact, var_len, + write_method); + return NULL; } -static u_char * -ospfv3NbrEntry (struct variable *v, oid *name, size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *ospfv3NbrEntry(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - ifindex_t ifindex = 0; - unsigned int instid, rtrid; - struct ospf6_interface *oi = NULL; - struct ospf6_neighbor *on = NULL; - struct interface *iif; - struct listnode *i, *j; - struct list *ifslist; - oid *offset; - int offsetlen, len; - - if (smux_header_table (v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - instid = rtrid = 0; - - /* Check OSPFv3 instance. */ - if (ospf6 == NULL) - return NULL; - - /* Get variable length. */ - offset = name + v->namelen; - offsetlen = *length - v->namelen; - - if (exact && offsetlen != 3) - return NULL; - - /* Parse if index */ - len = (offsetlen < 1 ? 0 : 1); - if (len) - ifindex = *offset; - offset += len; - offsetlen -= len; - - /* Parse instance ID */ - len = (offsetlen < 1 ? 0 : 1); - if (len) - instid = *offset; - offset += len; - offsetlen -= len; - - /* Parse router ID */ - len = (offsetlen < 1 ? 0 : 1); - if (len) - rtrid = htonl (*offset); - offset += len; - offsetlen -= len; - - if (exact) - { - oi = ospf6_interface_lookup_by_ifindex (ifindex); - if (!oi || oi->instance_id != instid) return NULL; - on = ospf6_neighbor_lookup (rtrid, oi); - } - else - { - /* We build a sorted list of interfaces */ - ifslist = list_new (); - if (!ifslist) return NULL; - ifslist->cmp = (int (*)(void *, void *))if_icmp_func; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), i, iif)) - listnode_add_sort (ifslist, iif); - - for (ALL_LIST_ELEMENTS_RO (ifslist, i, iif)) - { - if (!iif->ifindex) continue; - oi = ospf6_interface_lookup_by_ifindex (iif->ifindex); - if (!oi) continue; - for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on)) { - if (iif->ifindex > ifindex || - (iif->ifindex == ifindex && - (oi->instance_id > instid || - (oi->instance_id == instid && - ntohl (on->router_id) > ntohl (rtrid))))) - break; - } - if (on) break; - oi = NULL; - on = NULL; - } - - list_delete_all_node (ifslist); - } - - if (!oi || !on) return NULL; - - /* Add Index (IfIndex, IfInstId, RtrId) */ - *length = v->namelen + 3; - offset = name + v->namelen; - *offset = oi->interface->ifindex; - offset++; - *offset = oi->instance_id; - offset++; - *offset = ntohl (on->router_id); - offset++; - - /* Return the current value of the variable */ - switch (v->magic) - { - case OSPFv3NBRADDRESSTYPE: - return SNMP_INTEGER (2); /* IPv6 only */ - case OSPFv3NBRADDRESS: - *var_len = sizeof (struct in6_addr); - return (u_char *) &on->linklocal_addr; - case OSPFv3NBROPTIONS: - return SNMP_INTEGER (on->options[2]); - case OSPFv3NBRPRIORITY: - return SNMP_INTEGER (on->priority); - case OSPFv3NBRSTATE: - return SNMP_INTEGER (on->state); - case OSPFv3NBREVENTS: - return SNMP_INTEGER (on->state_change); - case OSPFv3NBRLSRETRANSQLEN: - return SNMP_INTEGER (on->retrans_list->count); - case OSPFv3NBRHELLOSUPPRESSED: - return SNMP_INTEGER (SNMP_FALSE); - case OSPFv3NBRIFID: - return SNMP_INTEGER (on->ifindex); - case OSPFv3NBRRESTARTHELPERSTATUS: - case OSPFv3NBRRESTARTHELPERAGE: - case OSPFv3NBRRESTARTHELPEREXITREASON: - /* Not implemented. Only works if all the last ones are not - implemented! */ - return NULL; - } - - return NULL; + ifindex_t ifindex = 0; + unsigned int instid, rtrid; + struct ospf6_interface *oi = NULL; + struct ospf6_neighbor *on = NULL; + struct interface *iif; + struct listnode *i, *j; + struct list *ifslist; + oid *offset; + int offsetlen, len; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + instid = rtrid = 0; + + /* Check OSPFv3 instance. */ + if (ospf6 == NULL) + return NULL; + + /* Get variable length. */ + offset = name + v->namelen; + offsetlen = *length - v->namelen; + + if (exact && offsetlen != 3) + return NULL; + + /* Parse if index */ + len = (offsetlen < 1 ? 0 : 1); + if (len) + ifindex = *offset; + offset += len; + offsetlen -= len; + + /* Parse instance ID */ + len = (offsetlen < 1 ? 0 : 1); + if (len) + instid = *offset; + offset += len; + offsetlen -= len; + + /* Parse router ID */ + len = (offsetlen < 1 ? 0 : 1); + if (len) + rtrid = htonl(*offset); + offset += len; + offsetlen -= len; + + if (exact) { + oi = ospf6_interface_lookup_by_ifindex(ifindex); + if (!oi || oi->instance_id != instid) + return NULL; + on = ospf6_neighbor_lookup(rtrid, oi); + } else { + /* We build a sorted list of interfaces */ + ifslist = list_new(); + if (!ifslist) + return NULL; + ifslist->cmp = (int (*)(void *, void *))if_icmp_func; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), i, iif)) + listnode_add_sort(ifslist, iif); + + for (ALL_LIST_ELEMENTS_RO(ifslist, i, iif)) { + if (!iif->ifindex) + continue; + oi = ospf6_interface_lookup_by_ifindex(iif->ifindex); + if (!oi) + continue; + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, j, on)) { + if (iif->ifindex > ifindex + || (iif->ifindex == ifindex + && (oi->instance_id > instid + || (oi->instance_id == instid + && ntohl(on->router_id) + > ntohl(rtrid))))) + break; + } + if (on) + break; + oi = NULL; + on = NULL; + } + + list_delete_all_node(ifslist); + } + + if (!oi || !on) + return NULL; + + /* Add Index (IfIndex, IfInstId, RtrId) */ + *length = v->namelen + 3; + offset = name + v->namelen; + *offset = oi->interface->ifindex; + offset++; + *offset = oi->instance_id; + offset++; + *offset = ntohl(on->router_id); + offset++; + + /* Return the current value of the variable */ + switch (v->magic) { + case OSPFv3NBRADDRESSTYPE: + return SNMP_INTEGER(2); /* IPv6 only */ + case OSPFv3NBRADDRESS: + *var_len = sizeof(struct in6_addr); + return (u_char *)&on->linklocal_addr; + case OSPFv3NBROPTIONS: + return SNMP_INTEGER(on->options[2]); + case OSPFv3NBRPRIORITY: + return SNMP_INTEGER(on->priority); + case OSPFv3NBRSTATE: + return SNMP_INTEGER(on->state); + case OSPFv3NBREVENTS: + return SNMP_INTEGER(on->state_change); + case OSPFv3NBRLSRETRANSQLEN: + return SNMP_INTEGER(on->retrans_list->count); + case OSPFv3NBRHELLOSUPPRESSED: + return SNMP_INTEGER(SNMP_FALSE); + case OSPFv3NBRIFID: + return SNMP_INTEGER(on->ifindex); + case OSPFv3NBRRESTARTHELPERSTATUS: + case OSPFv3NBRRESTARTHELPERAGE: + case OSPFv3NBRRESTARTHELPEREXITREASON: + /* Not implemented. Only works if all the last ones are not + implemented! */ + return NULL; + } + + return NULL; } /* OSPF Traps. */ #define NBRSTATECHANGE 2 #define IFSTATECHANGE 10 -static struct trap_object ospf6NbrTrapList[] = -{ - {-3, {1, 1, OSPFv3ROUTERID}}, - {4, {1, 9, 1, OSPFv3NBRADDRESSTYPE}}, - {4, {1, 9, 1, OSPFv3NBRADDRESS}}, - {4, {1, 9, 1, OSPFv3NBRSTATE}} -}; +static struct trap_object ospf6NbrTrapList[] = { + {-3, {1, 1, OSPFv3ROUTERID}}, + {4, {1, 9, 1, OSPFv3NBRADDRESSTYPE}}, + {4, {1, 9, 1, OSPFv3NBRADDRESS}}, + {4, {1, 9, 1, OSPFv3NBRSTATE}}}; -static struct trap_object ospf6IfTrapList[] = -{ - {-3, {1, 1, OSPFv3ROUTERID}}, - {4, {1, 7, 1, OSPFv3IFSTATE}}, - {4, {1, 7, 1, OSPFv3IFADMINSTATUS}}, - {4, {1, 7, 1, OSPFv3IFAREAID}} -}; +static struct trap_object ospf6IfTrapList[] = { + {-3, {1, 1, OSPFv3ROUTERID}}, + {4, {1, 7, 1, OSPFv3IFSTATE}}, + {4, {1, 7, 1, OSPFv3IFADMINSTATUS}}, + {4, {1, 7, 1, OSPFv3IFAREAID}}}; -static int -ospf6TrapNbrStateChange (struct ospf6_neighbor *on, - int next_state, int prev_state) +static int ospf6TrapNbrStateChange(struct ospf6_neighbor *on, int next_state, + int prev_state) { - oid index[3]; - - /* Terminal state or regression */ - if ((next_state != OSPF6_NEIGHBOR_FULL) && - (next_state != OSPF6_NEIGHBOR_TWOWAY) && - (next_state >= prev_state)) - return 0; - - index[0] = on->ospf6_if->interface->ifindex; - index[1] = on->ospf6_if->instance_id; - index[2] = ntohl (on->router_id); - - smux_trap (ospfv3_variables, sizeof ospfv3_variables / sizeof (struct variable), - ospfv3_trap_oid, sizeof ospfv3_trap_oid / sizeof (oid), - ospfv3_oid, sizeof ospfv3_oid / sizeof (oid), - index, 3, - ospf6NbrTrapList, - sizeof ospf6NbrTrapList / sizeof (struct trap_object), - NBRSTATECHANGE); - return 0; + oid index[3]; + + /* Terminal state or regression */ + if ((next_state != OSPF6_NEIGHBOR_FULL) + && (next_state != OSPF6_NEIGHBOR_TWOWAY) + && (next_state >= prev_state)) + return 0; + + index[0] = on->ospf6_if->interface->ifindex; + index[1] = on->ospf6_if->instance_id; + index[2] = ntohl(on->router_id); + + smux_trap(ospfv3_variables, + sizeof ospfv3_variables / sizeof(struct variable), + ospfv3_trap_oid, sizeof ospfv3_trap_oid / sizeof(oid), + ospfv3_oid, sizeof ospfv3_oid / sizeof(oid), index, 3, + ospf6NbrTrapList, + sizeof ospf6NbrTrapList / sizeof(struct trap_object), + NBRSTATECHANGE); + return 0; } -static int -ospf6TrapIfStateChange (struct ospf6_interface *oi, - int next_state, int prev_state) +static int ospf6TrapIfStateChange(struct ospf6_interface *oi, int next_state, + int prev_state) { - oid index[2]; - - /* Terminal state or regression */ - if ((next_state != OSPF6_INTERFACE_POINTTOPOINT) && - (next_state != OSPF6_INTERFACE_DROTHER) && - (next_state != OSPF6_INTERFACE_BDR) && - (next_state != OSPF6_INTERFACE_DR) && - (next_state >= prev_state)) - return 0; - - index[0] = oi->interface->ifindex; - index[1] = oi->instance_id; - - smux_trap (ospfv3_variables, sizeof ospfv3_variables / sizeof (struct variable), - ospfv3_trap_oid, sizeof ospfv3_trap_oid / sizeof (oid), - ospfv3_oid, sizeof ospfv3_oid / sizeof (oid), - index, 2, - ospf6IfTrapList, - sizeof ospf6IfTrapList / sizeof (struct trap_object), - IFSTATECHANGE); - return 0; + oid index[2]; + + /* Terminal state or regression */ + if ((next_state != OSPF6_INTERFACE_POINTTOPOINT) + && (next_state != OSPF6_INTERFACE_DROTHER) + && (next_state != OSPF6_INTERFACE_BDR) + && (next_state != OSPF6_INTERFACE_DR) && (next_state >= prev_state)) + return 0; + + index[0] = oi->interface->ifindex; + index[1] = oi->instance_id; + + smux_trap(ospfv3_variables, + sizeof ospfv3_variables / sizeof(struct variable), + ospfv3_trap_oid, sizeof ospfv3_trap_oid / sizeof(oid), + ospfv3_oid, sizeof ospfv3_oid / sizeof(oid), index, 2, + ospf6IfTrapList, + sizeof ospf6IfTrapList / sizeof(struct trap_object), + IFSTATECHANGE); + return 0; } /* Register OSPFv3-MIB. */ -static int -ospf6_snmp_init (struct thread_master *master) +static int ospf6_snmp_init(struct thread_master *master) { - smux_init (master); - REGISTER_MIB ("OSPFv3MIB", ospfv3_variables, variable, ospfv3_oid); - return 0; + smux_init(master); + REGISTER_MIB("OSPFv3MIB", ospfv3_variables, variable, ospfv3_oid); + return 0; } -static int -ospf6_snmp_module_init (void) +static int ospf6_snmp_module_init(void) { - hook_register(ospf6_interface_change, ospf6TrapIfStateChange); - hook_register(ospf6_neighbor_change, ospf6TrapNbrStateChange); - hook_register(frr_late_init, ospf6_snmp_init); - return 0; + hook_register(ospf6_interface_change, ospf6TrapIfStateChange); + hook_register(ospf6_neighbor_change, ospf6TrapNbrStateChange); + hook_register(frr_late_init, ospf6_snmp_init); + return 0; } -FRR_MODULE_SETUP( - .name = "ospf6d_snmp", - .version = FRR_VERSION, - .description = "ospf6d AgentX SNMP module", - .init = ospf6_snmp_module_init, -) +FRR_MODULE_SETUP(.name = "ospf6d_snmp", .version = FRR_VERSION, + .description = "ospf6d AgentX SNMP module", + .init = ospf6_snmp_module_init, ) diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c index 8d2e244c8..86f893bc6 100644 --- a/ospf6d/ospf6_spf.c +++ b/ospf6d/ospf6_spf.c @@ -45,721 +45,688 @@ unsigned char conf_debug_ospf6_spf = 0; -static void -ospf6_spf_copy_nexthops_to_route (struct ospf6_route *rt, - struct ospf6_vertex *v) +static void ospf6_spf_copy_nexthops_to_route(struct ospf6_route *rt, + struct ospf6_vertex *v) { - if (rt && v) - ospf6_copy_nexthops (rt->nh_list, v->nh_list); + if (rt && v) + ospf6_copy_nexthops(rt->nh_list, v->nh_list); } -static void -ospf6_spf_merge_nexthops_to_route (struct ospf6_route *rt, - struct ospf6_vertex *v) +static void ospf6_spf_merge_nexthops_to_route(struct ospf6_route *rt, + struct ospf6_vertex *v) { - if (rt && v) - ospf6_merge_nexthops (rt->nh_list, v->nh_list); + if (rt && v) + ospf6_merge_nexthops(rt->nh_list, v->nh_list); } -static unsigned int -ospf6_spf_get_ifindex_from_nh (struct ospf6_vertex *v) +static unsigned int ospf6_spf_get_ifindex_from_nh(struct ospf6_vertex *v) { - struct ospf6_nexthop *nh; - struct listnode *node; - - if (v) - { - node = listhead(v->nh_list); - if (node) - { - nh = listgetdata (node); - if (nh) - return (nh->ifindex); + struct ospf6_nexthop *nh; + struct listnode *node; + + if (v) { + node = listhead(v->nh_list); + if (node) { + nh = listgetdata(node); + if (nh) + return (nh->ifindex); + } } - } - return 0; + return 0; } -static int -ospf6_vertex_cmp (void *a, void *b) +static int ospf6_vertex_cmp(void *a, void *b) { - struct ospf6_vertex *va = (struct ospf6_vertex *) a; - struct ospf6_vertex *vb = (struct ospf6_vertex *) b; + struct ospf6_vertex *va = (struct ospf6_vertex *)a; + struct ospf6_vertex *vb = (struct ospf6_vertex *)b; - /* ascending order */ - if (va->cost != vb->cost) - return (va->cost - vb->cost); - return (va->hops - vb->hops); + /* ascending order */ + if (va->cost != vb->cost) + return (va->cost - vb->cost); + return (va->hops - vb->hops); } -static int -ospf6_vertex_id_cmp (void *a, void *b) +static int ospf6_vertex_id_cmp(void *a, void *b) { - struct ospf6_vertex *va = (struct ospf6_vertex *) a; - struct ospf6_vertex *vb = (struct ospf6_vertex *) b; - int ret = 0; - - ret = ntohl (ospf6_linkstate_prefix_adv_router (&va->vertex_id)) - - ntohl (ospf6_linkstate_prefix_adv_router (&vb->vertex_id)); - if (ret) - return ret; - - ret = ntohl (ospf6_linkstate_prefix_id (&va->vertex_id)) - - ntohl (ospf6_linkstate_prefix_id (&vb->vertex_id)); - return ret; + struct ospf6_vertex *va = (struct ospf6_vertex *)a; + struct ospf6_vertex *vb = (struct ospf6_vertex *)b; + int ret = 0; + + ret = ntohl(ospf6_linkstate_prefix_adv_router(&va->vertex_id)) + - ntohl(ospf6_linkstate_prefix_adv_router(&vb->vertex_id)); + if (ret) + return ret; + + ret = ntohl(ospf6_linkstate_prefix_id(&va->vertex_id)) + - ntohl(ospf6_linkstate_prefix_id(&vb->vertex_id)); + return ret; } -static struct ospf6_vertex * -ospf6_vertex_create (struct ospf6_lsa *lsa) +static struct ospf6_vertex *ospf6_vertex_create(struct ospf6_lsa *lsa) { - struct ospf6_vertex *v; + struct ospf6_vertex *v; - v = (struct ospf6_vertex *) - XMALLOC (MTYPE_OSPF6_VERTEX, sizeof (struct ospf6_vertex)); + v = (struct ospf6_vertex *)XMALLOC(MTYPE_OSPF6_VERTEX, + sizeof(struct ospf6_vertex)); - /* type */ - if (ntohs (lsa->header->type) == OSPF6_LSTYPE_ROUTER) - v->type = OSPF6_VERTEX_TYPE_ROUTER; - else if (ntohs (lsa->header->type) == OSPF6_LSTYPE_NETWORK) - v->type = OSPF6_VERTEX_TYPE_NETWORK; - else - assert (0); + /* type */ + if (ntohs(lsa->header->type) == OSPF6_LSTYPE_ROUTER) + v->type = OSPF6_VERTEX_TYPE_ROUTER; + else if (ntohs(lsa->header->type) == OSPF6_LSTYPE_NETWORK) + v->type = OSPF6_VERTEX_TYPE_NETWORK; + else + assert(0); - /* vertex_id */ - ospf6_linkstate_prefix (lsa->header->adv_router, lsa->header->id, - &v->vertex_id); + /* vertex_id */ + ospf6_linkstate_prefix(lsa->header->adv_router, lsa->header->id, + &v->vertex_id); - /* name */ - ospf6_linkstate_prefix2str (&v->vertex_id, v->name, sizeof (v->name)); + /* name */ + ospf6_linkstate_prefix2str(&v->vertex_id, v->name, sizeof(v->name)); - if (IS_OSPF6_DEBUG_SPF (PROCESS)) - zlog_debug ("%s: Creating vertex %s of type %s", __func__, v->name, - ((ntohs (lsa->header->type) == OSPF6_LSTYPE_ROUTER) ? "Router" : "N/W")); + if (IS_OSPF6_DEBUG_SPF(PROCESS)) + zlog_debug("%s: Creating vertex %s of type %s", __func__, + v->name, + ((ntohs(lsa->header->type) == OSPF6_LSTYPE_ROUTER) + ? "Router" + : "N/W")); - /* Associated LSA */ - v->lsa = lsa; + /* Associated LSA */ + v->lsa = lsa; - /* capability bits + options */ - v->capability = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header)); - v->options[0] = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header) + 1); - v->options[1] = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header) + 2); - v->options[2] = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header) + 3); + /* capability bits + options */ + v->capability = *(u_char *)(OSPF6_LSA_HEADER_END(lsa->header)); + v->options[0] = *(u_char *)(OSPF6_LSA_HEADER_END(lsa->header) + 1); + v->options[1] = *(u_char *)(OSPF6_LSA_HEADER_END(lsa->header) + 2); + v->options[2] = *(u_char *)(OSPF6_LSA_HEADER_END(lsa->header) + 3); - v->nh_list = list_new(); + v->nh_list = list_new(); - v->parent = NULL; - v->child_list = list_new (); - v->child_list->cmp = ospf6_vertex_id_cmp; + v->parent = NULL; + v->child_list = list_new(); + v->child_list->cmp = ospf6_vertex_id_cmp; - return v; + return v; } -static void -ospf6_vertex_delete (struct ospf6_vertex *v) +static void ospf6_vertex_delete(struct ospf6_vertex *v) { - list_delete(v->nh_list); - list_delete (v->child_list); - XFREE (MTYPE_OSPF6_VERTEX, v); + list_delete(v->nh_list); + list_delete(v->child_list); + XFREE(MTYPE_OSPF6_VERTEX, v); } -static struct ospf6_lsa * -ospf6_lsdesc_lsa (caddr_t lsdesc, struct ospf6_vertex *v) +static struct ospf6_lsa *ospf6_lsdesc_lsa(caddr_t lsdesc, + struct ospf6_vertex *v) { - struct ospf6_lsa *lsa; - u_int16_t type = 0; - u_int32_t id = 0, adv_router = 0; - - if (VERTEX_IS_TYPE (NETWORK, v)) - { - type = htons (OSPF6_LSTYPE_ROUTER); - id = htonl (0); - adv_router = NETWORK_LSDESC_GET_NBR_ROUTERID (lsdesc); - } - else - { - if (ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, lsdesc)) - { - type = htons (OSPF6_LSTYPE_ROUTER); - id = htonl (0); - adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc); - } - else if (ROUTER_LSDESC_IS_TYPE (TRANSIT_NETWORK, lsdesc)) - { - type = htons (OSPF6_LSTYPE_NETWORK); - id = htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc)); - adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc); - } - } - - lsa = ospf6_lsdb_lookup (type, id, adv_router, v->area->lsdb); - - if (IS_OSPF6_DEBUG_SPF (PROCESS)) - { - char ibuf[16], abuf[16]; - inet_ntop (AF_INET, &id, ibuf, sizeof (ibuf)); - inet_ntop (AF_INET, &adv_router, abuf, sizeof (abuf)); - if (lsa) - zlog_debug (" Link to: %s", lsa->name); - else - zlog_debug (" Link to: [%s Id:%s Adv:%s] No LSA", - ospf6_lstype_name (type), ibuf, abuf); - } - - return lsa; + struct ospf6_lsa *lsa; + u_int16_t type = 0; + u_int32_t id = 0, adv_router = 0; + + if (VERTEX_IS_TYPE(NETWORK, v)) { + type = htons(OSPF6_LSTYPE_ROUTER); + id = htonl(0); + adv_router = NETWORK_LSDESC_GET_NBR_ROUTERID(lsdesc); + } else { + if (ROUTER_LSDESC_IS_TYPE(POINTTOPOINT, lsdesc)) { + type = htons(OSPF6_LSTYPE_ROUTER); + id = htonl(0); + adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID(lsdesc); + } else if (ROUTER_LSDESC_IS_TYPE(TRANSIT_NETWORK, lsdesc)) { + type = htons(OSPF6_LSTYPE_NETWORK); + id = htonl(ROUTER_LSDESC_GET_NBR_IFID(lsdesc)); + adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID(lsdesc); + } + } + + lsa = ospf6_lsdb_lookup(type, id, adv_router, v->area->lsdb); + + if (IS_OSPF6_DEBUG_SPF(PROCESS)) { + char ibuf[16], abuf[16]; + inet_ntop(AF_INET, &id, ibuf, sizeof(ibuf)); + inet_ntop(AF_INET, &adv_router, abuf, sizeof(abuf)); + if (lsa) + zlog_debug(" Link to: %s", lsa->name); + else + zlog_debug(" Link to: [%s Id:%s Adv:%s] No LSA", + ospf6_lstype_name(type), ibuf, abuf); + } + + return lsa; } -static char * -ospf6_lsdesc_backlink (struct ospf6_lsa *lsa, - caddr_t lsdesc, struct ospf6_vertex *v) +static char *ospf6_lsdesc_backlink(struct ospf6_lsa *lsa, caddr_t lsdesc, + struct ospf6_vertex *v) { - caddr_t backlink, found = NULL; - int size; - - size = (OSPF6_LSA_IS_TYPE (ROUTER, lsa) ? - sizeof (struct ospf6_router_lsdesc) : - sizeof (struct ospf6_network_lsdesc)); - for (backlink = OSPF6_LSA_HEADER_END (lsa->header) + 4; - backlink + size <= OSPF6_LSA_END (lsa->header); backlink += size) - { - assert (! (OSPF6_LSA_IS_TYPE (NETWORK, lsa) && - VERTEX_IS_TYPE (NETWORK, v))); - - if (OSPF6_LSA_IS_TYPE (NETWORK, lsa) && - NETWORK_LSDESC_GET_NBR_ROUTERID (backlink) - == v->lsa->header->adv_router) - found = backlink; - else if (VERTEX_IS_TYPE (NETWORK, v) && - ROUTER_LSDESC_IS_TYPE (TRANSIT_NETWORK, backlink) && - ROUTER_LSDESC_GET_NBR_ROUTERID (backlink) - == v->lsa->header->adv_router && - ROUTER_LSDESC_GET_NBR_IFID (backlink) - == ntohl (v->lsa->header->id)) - found = backlink; - else - { - if (! ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, backlink) || - ! ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, lsdesc)) - continue; - if (ROUTER_LSDESC_GET_NBR_IFID (backlink) != - ROUTER_LSDESC_GET_IFID (lsdesc) || - ROUTER_LSDESC_GET_NBR_IFID (lsdesc) != - ROUTER_LSDESC_GET_IFID (backlink)) - continue; - if (ROUTER_LSDESC_GET_NBR_ROUTERID (backlink) != - v->lsa->header->adv_router || - ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc) != - lsa->header->adv_router) - continue; - found = backlink; - } - } - - if (IS_OSPF6_DEBUG_SPF (PROCESS)) - zlog_debug (" Backlink %s", (found ? "OK" : "FAIL")); - - return found; + caddr_t backlink, found = NULL; + int size; + + size = (OSPF6_LSA_IS_TYPE(ROUTER, lsa) + ? sizeof(struct ospf6_router_lsdesc) + : sizeof(struct ospf6_network_lsdesc)); + for (backlink = OSPF6_LSA_HEADER_END(lsa->header) + 4; + backlink + size <= OSPF6_LSA_END(lsa->header); backlink += size) { + assert(!(OSPF6_LSA_IS_TYPE(NETWORK, lsa) + && VERTEX_IS_TYPE(NETWORK, v))); + + if (OSPF6_LSA_IS_TYPE(NETWORK, lsa) + && NETWORK_LSDESC_GET_NBR_ROUTERID(backlink) + == v->lsa->header->adv_router) + found = backlink; + else if (VERTEX_IS_TYPE(NETWORK, v) + && ROUTER_LSDESC_IS_TYPE(TRANSIT_NETWORK, backlink) + && ROUTER_LSDESC_GET_NBR_ROUTERID(backlink) + == v->lsa->header->adv_router + && ROUTER_LSDESC_GET_NBR_IFID(backlink) + == ntohl(v->lsa->header->id)) + found = backlink; + else { + if (!ROUTER_LSDESC_IS_TYPE(POINTTOPOINT, backlink) + || !ROUTER_LSDESC_IS_TYPE(POINTTOPOINT, lsdesc)) + continue; + if (ROUTER_LSDESC_GET_NBR_IFID(backlink) + != ROUTER_LSDESC_GET_IFID(lsdesc) + || ROUTER_LSDESC_GET_NBR_IFID(lsdesc) + != ROUTER_LSDESC_GET_IFID(backlink)) + continue; + if (ROUTER_LSDESC_GET_NBR_ROUTERID(backlink) + != v->lsa->header->adv_router + || ROUTER_LSDESC_GET_NBR_ROUTERID(lsdesc) + != lsa->header->adv_router) + continue; + found = backlink; + } + } + + if (IS_OSPF6_DEBUG_SPF(PROCESS)) + zlog_debug(" Backlink %s", (found ? "OK" : "FAIL")); + + return found; } -static void -ospf6_nexthop_calc (struct ospf6_vertex *w, struct ospf6_vertex *v, - caddr_t lsdesc) +static void ospf6_nexthop_calc(struct ospf6_vertex *w, struct ospf6_vertex *v, + caddr_t lsdesc) { - int i; - ifindex_t ifindex; - struct ospf6_interface *oi; - u_int16_t type; - u_int32_t adv_router; - struct ospf6_lsa *lsa; - struct ospf6_link_lsa *link_lsa; - char buf[64]; - - assert (VERTEX_IS_TYPE (ROUTER, w)); - ifindex = (VERTEX_IS_TYPE (NETWORK, v) ? ospf6_spf_get_ifindex_from_nh (v) : - ROUTER_LSDESC_GET_IFID (lsdesc)); - if (ifindex == 0) - { - zlog_err ("No nexthop ifindex at vertex %s", v->name); - return; - } - - oi = ospf6_interface_lookup_by_ifindex (ifindex); - if (oi == NULL) - { - if (IS_OSPF6_DEBUG_SPF (PROCESS)) - zlog_debug ("Can't find interface in SPF: ifindex %d", ifindex); - return; - } - - type = htons (OSPF6_LSTYPE_LINK); - adv_router = (VERTEX_IS_TYPE (NETWORK, v) ? - NETWORK_LSDESC_GET_NBR_ROUTERID (lsdesc) : - ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc)); - - i = 0; - for (ALL_LSDB_TYPED_ADVRTR(oi->lsdb, type, adv_router, lsa)) - { - if (VERTEX_IS_TYPE (ROUTER, v) && - htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc)) != lsa->header->id) - continue; - - link_lsa = (struct ospf6_link_lsa *) OSPF6_LSA_HEADER_END (lsa->header); - if (IS_OSPF6_DEBUG_SPF (PROCESS)) - { - inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf)); - zlog_debug (" nexthop %s from %s", buf, lsa->name); - } - - ospf6_add_nexthop (w->nh_list, ifindex, &link_lsa->linklocal_addr); - i++; - } - - if (i == 0 && IS_OSPF6_DEBUG_SPF (PROCESS)) - zlog_debug ("No nexthop for %s found", w->name); + int i; + ifindex_t ifindex; + struct ospf6_interface *oi; + u_int16_t type; + u_int32_t adv_router; + struct ospf6_lsa *lsa; + struct ospf6_link_lsa *link_lsa; + char buf[64]; + + assert(VERTEX_IS_TYPE(ROUTER, w)); + ifindex = (VERTEX_IS_TYPE(NETWORK, v) ? ospf6_spf_get_ifindex_from_nh(v) + : ROUTER_LSDESC_GET_IFID(lsdesc)); + if (ifindex == 0) { + zlog_err("No nexthop ifindex at vertex %s", v->name); + return; + } + + oi = ospf6_interface_lookup_by_ifindex(ifindex); + if (oi == NULL) { + if (IS_OSPF6_DEBUG_SPF(PROCESS)) + zlog_debug("Can't find interface in SPF: ifindex %d", + ifindex); + return; + } + + type = htons(OSPF6_LSTYPE_LINK); + adv_router = (VERTEX_IS_TYPE(NETWORK, v) + ? NETWORK_LSDESC_GET_NBR_ROUTERID(lsdesc) + : ROUTER_LSDESC_GET_NBR_ROUTERID(lsdesc)); + + i = 0; + for (ALL_LSDB_TYPED_ADVRTR(oi->lsdb, type, adv_router, lsa)) { + if (VERTEX_IS_TYPE(ROUTER, v) + && htonl(ROUTER_LSDESC_GET_NBR_IFID(lsdesc)) + != lsa->header->id) + continue; + + link_lsa = (struct ospf6_link_lsa *)OSPF6_LSA_HEADER_END( + lsa->header); + if (IS_OSPF6_DEBUG_SPF(PROCESS)) { + inet_ntop(AF_INET6, &link_lsa->linklocal_addr, buf, + sizeof(buf)); + zlog_debug(" nexthop %s from %s", buf, lsa->name); + } + + ospf6_add_nexthop(w->nh_list, ifindex, + &link_lsa->linklocal_addr); + i++; + } + + if (i == 0 && IS_OSPF6_DEBUG_SPF(PROCESS)) + zlog_debug("No nexthop for %s found", w->name); } -static int -ospf6_spf_install (struct ospf6_vertex *v, - struct ospf6_route_table *result_table) +static int ospf6_spf_install(struct ospf6_vertex *v, + struct ospf6_route_table *result_table) { - struct ospf6_route *route, *parent_route; - struct ospf6_vertex *prev; - - if (IS_OSPF6_DEBUG_SPF (PROCESS)) - zlog_debug ("SPF install %s hops %d cost %d", - v->name, v->hops, v->cost); - - route = ospf6_route_lookup (&v->vertex_id, result_table); - if (route && route->path.cost < v->cost) - { - if (IS_OSPF6_DEBUG_SPF (PROCESS)) - zlog_debug (" already installed with lower cost (%d), ignore", - route->path.cost); - ospf6_vertex_delete (v); - return -1; - } - else if (route && route->path.cost == v->cost) - { - if (IS_OSPF6_DEBUG_SPF (PROCESS)) - zlog_debug (" another path found, merge"); - - ospf6_spf_merge_nexthops_to_route (route, v); - - prev = (struct ospf6_vertex *) route->route_option; - assert (prev->hops <= v->hops); - ospf6_vertex_delete (v); - - return -1; - } - - /* There should be no case where candidate being installed (variable - "v") is closer than the one in the SPF tree (variable "route"). - In the case something has gone wrong with the behavior of - Priority-Queue. */ - - /* the case where the route exists already is handled and returned - up to here. */ - assert (route == NULL); - - route = ospf6_route_create (); - memcpy (&route->prefix, &v->vertex_id, sizeof (struct prefix)); - route->type = OSPF6_DEST_TYPE_LINKSTATE; - route->path.type = OSPF6_PATH_TYPE_INTRA; - route->path.origin.type = v->lsa->header->type; - route->path.origin.id = v->lsa->header->id; - route->path.origin.adv_router = v->lsa->header->adv_router; - route->path.metric_type = 1; - route->path.cost = v->cost; - route->path.u.cost_e2 = v->hops; - route->path.router_bits = v->capability; - route->path.options[0] = v->options[0]; - route->path.options[1] = v->options[1]; - route->path.options[2] = v->options[2]; - - ospf6_spf_copy_nexthops_to_route (route, v); - - /* - * The SPF logic implementation does not transfer the multipathing properties - * of a parent to a child node. Thus if there was a 3-way multipath to a - * node's parent and a single hop from the parent to the child, the logic of - * creating new vertices and computing next hops prevents there from being 3 - * paths to the child node. This is primarily because the resolution of - * multipath is done in this routine, not in the main spf loop. - * - * The following logic addresses that problem by merging the parent's nexthop - * information with the child's, if the parent is not the root of the tree. - * This is based on the assumption that before a node's route is installed, - * its parent's route's nexthops have already been installed. - */ - if (v->parent && v->parent->hops) - { - parent_route = ospf6_route_lookup (&v->parent->vertex_id, result_table); - if (parent_route) - { - ospf6_route_merge_nexthops (route, parent_route); + struct ospf6_route *route, *parent_route; + struct ospf6_vertex *prev; + + if (IS_OSPF6_DEBUG_SPF(PROCESS)) + zlog_debug("SPF install %s hops %d cost %d", v->name, v->hops, + v->cost); + + route = ospf6_route_lookup(&v->vertex_id, result_table); + if (route && route->path.cost < v->cost) { + if (IS_OSPF6_DEBUG_SPF(PROCESS)) + zlog_debug( + " already installed with lower cost (%d), ignore", + route->path.cost); + ospf6_vertex_delete(v); + return -1; + } else if (route && route->path.cost == v->cost) { + if (IS_OSPF6_DEBUG_SPF(PROCESS)) + zlog_debug(" another path found, merge"); + + ospf6_spf_merge_nexthops_to_route(route, v); + + prev = (struct ospf6_vertex *)route->route_option; + assert(prev->hops <= v->hops); + ospf6_vertex_delete(v); + + return -1; } - } - if (v->parent) - listnode_add_sort (v->parent->child_list, v); - route->route_option = v; + /* There should be no case where candidate being installed (variable + "v") is closer than the one in the SPF tree (variable "route"). + In the case something has gone wrong with the behavior of + Priority-Queue. */ + + /* the case where the route exists already is handled and returned + up to here. */ + assert(route == NULL); + + route = ospf6_route_create(); + memcpy(&route->prefix, &v->vertex_id, sizeof(struct prefix)); + route->type = OSPF6_DEST_TYPE_LINKSTATE; + route->path.type = OSPF6_PATH_TYPE_INTRA; + route->path.origin.type = v->lsa->header->type; + route->path.origin.id = v->lsa->header->id; + route->path.origin.adv_router = v->lsa->header->adv_router; + route->path.metric_type = 1; + route->path.cost = v->cost; + route->path.u.cost_e2 = v->hops; + route->path.router_bits = v->capability; + route->path.options[0] = v->options[0]; + route->path.options[1] = v->options[1]; + route->path.options[2] = v->options[2]; + + ospf6_spf_copy_nexthops_to_route(route, v); + + /* + * The SPF logic implementation does not transfer the multipathing + * properties + * of a parent to a child node. Thus if there was a 3-way multipath to a + * node's parent and a single hop from the parent to the child, the + * logic of + * creating new vertices and computing next hops prevents there from + * being 3 + * paths to the child node. This is primarily because the resolution of + * multipath is done in this routine, not in the main spf loop. + * + * The following logic addresses that problem by merging the parent's + * nexthop + * information with the child's, if the parent is not the root of the + * tree. + * This is based on the assumption that before a node's route is + * installed, + * its parent's route's nexthops have already been installed. + */ + if (v->parent && v->parent->hops) { + parent_route = + ospf6_route_lookup(&v->parent->vertex_id, result_table); + if (parent_route) { + ospf6_route_merge_nexthops(route, parent_route); + } + } + + if (v->parent) + listnode_add_sort(v->parent->child_list, v); + route->route_option = v; - ospf6_route_add (route, result_table); - return 0; + ospf6_route_add(route, result_table); + return 0; } -void -ospf6_spf_table_finish (struct ospf6_route_table *result_table) +void ospf6_spf_table_finish(struct ospf6_route_table *result_table) { - struct ospf6_route *route, *nroute; - struct ospf6_vertex *v; - for (route = ospf6_route_head (result_table); route; - route = nroute) - { - nroute = ospf6_route_next (route); - v = (struct ospf6_vertex *) route->route_option; - ospf6_vertex_delete (v); - ospf6_route_remove (route, result_table); - } + struct ospf6_route *route, *nroute; + struct ospf6_vertex *v; + for (route = ospf6_route_head(result_table); route; route = nroute) { + nroute = ospf6_route_next(route); + v = (struct ospf6_vertex *)route->route_option; + ospf6_vertex_delete(v); + ospf6_route_remove(route, result_table); + } } -static const char *ospf6_spf_reason_str[] = - { - "R+", - "R-", - "N+", - "N-", - "L+", - "L-", - "R*", - "N*", - }; - -void ospf6_spf_reason_string (unsigned int reason, char *buf, int size) +static const char *ospf6_spf_reason_str[] = { + "R+", "R-", "N+", "N-", "L+", "L-", "R*", "N*", +}; + +void ospf6_spf_reason_string(unsigned int reason, char *buf, int size) { - unsigned int bit; - int len = 0; - - if (!buf) - return; - - for (bit = 0; bit < array_size(ospf6_spf_reason_str); bit++) - { - if ((reason & (1 << bit)) && (len < size)) - { - len += snprintf((buf + len), (size - len), "%s%s", - (len > 0) ? ", " : "", ospf6_spf_reason_str[bit]); + unsigned int bit; + int len = 0; + + if (!buf) + return; + + for (bit = 0; bit < array_size(ospf6_spf_reason_str); bit++) { + if ((reason & (1 << bit)) && (len < size)) { + len += snprintf((buf + len), (size - len), "%s%s", + (len > 0) ? ", " : "", + ospf6_spf_reason_str[bit]); + } } - } } /* RFC2328 16.1. Calculating the shortest-path tree for an area */ /* RFC2740 3.8.1. Calculating the shortest path tree for an area */ -void -ospf6_spf_calculation (u_int32_t router_id, - struct ospf6_route_table *result_table, - struct ospf6_area *oa) +void ospf6_spf_calculation(u_int32_t router_id, + struct ospf6_route_table *result_table, + struct ospf6_area *oa) { - struct pqueue *candidate_list; - struct ospf6_vertex *root, *v, *w; - int size; - caddr_t lsdesc; - struct ospf6_lsa *lsa; - struct in6_addr address; - - ospf6_spf_table_finish (result_table); - - /* Install the calculating router itself as the root of the SPF tree */ - /* construct root vertex */ - lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_ROUTER), htonl (0), - router_id, oa->lsdb_self); - if (lsa == NULL) - { - if (IS_OSPF6_DEBUG_SPF (PROCESS)) - zlog_debug ("%s: No router LSA for area %s\n", - __func__, oa->name); - return; - } - - /* initialize */ - candidate_list = pqueue_create (); - candidate_list->cmp = ospf6_vertex_cmp; - - root = ospf6_vertex_create (lsa); - root->area = oa; - root->cost = 0; - root->hops = 0; - inet_pton (AF_INET6, "::1", &address); - - /* Actually insert root to the candidate-list as the only candidate */ - pqueue_enqueue (root, candidate_list); - - /* Iterate until candidate-list becomes empty */ - while (candidate_list->size) - { - /* get closest candidate from priority queue */ - v = pqueue_dequeue (candidate_list); - - /* installing may result in merging or rejecting of the vertex */ - if (ospf6_spf_install (v, result_table) < 0) - continue; - - /* Skip overloaded routers */ - if ((OSPF6_LSA_IS_TYPE (ROUTER, v->lsa) && - ospf6_router_is_stub_router (v->lsa))) - continue; - - /* For each LS description in the just-added vertex V's LSA */ - size = (VERTEX_IS_TYPE (ROUTER, v) ? - sizeof (struct ospf6_router_lsdesc) : - sizeof (struct ospf6_network_lsdesc)); - for (lsdesc = OSPF6_LSA_HEADER_END (v->lsa->header) + 4; - lsdesc + size <= OSPF6_LSA_END (v->lsa->header); lsdesc += size) - { - lsa = ospf6_lsdesc_lsa (lsdesc, v); - if (lsa == NULL) - continue; - - if (OSPF6_LSA_IS_MAXAGE (lsa)) - continue; - - if (! ospf6_lsdesc_backlink (lsa, lsdesc, v)) - continue; - - w = ospf6_vertex_create (lsa); - w->area = oa; - w->parent = v; - if (VERTEX_IS_TYPE (ROUTER, v)) - { - w->cost = v->cost + ROUTER_LSDESC_GET_METRIC (lsdesc); - w->hops = v->hops + (VERTEX_IS_TYPE (NETWORK, w) ? 0 : 1); - } - else /* NETWORK */ - { - w->cost = v->cost; - w->hops = v->hops + 1; - } - - /* nexthop calculation */ - if (w->hops == 0) - ospf6_add_nexthop (w->nh_list, ROUTER_LSDESC_GET_IFID (lsdesc), NULL); - else if (w->hops == 1 && v->hops == 0) - ospf6_nexthop_calc (w, v, lsdesc); - else - { - ospf6_copy_nexthops (w->nh_list, v->nh_list); - } - - /* add new candidate to the candidate_list */ - if (IS_OSPF6_DEBUG_SPF (PROCESS)) - zlog_debug (" New candidate: %s hops %d cost %d", - w->name, w->hops, w->cost); - pqueue_enqueue (w, candidate_list); - } - } - - pqueue_delete (candidate_list); - - oa->spf_calculation++; + struct pqueue *candidate_list; + struct ospf6_vertex *root, *v, *w; + int size; + caddr_t lsdesc; + struct ospf6_lsa *lsa; + struct in6_addr address; + + ospf6_spf_table_finish(result_table); + + /* Install the calculating router itself as the root of the SPF tree */ + /* construct root vertex */ + lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_ROUTER), htonl(0), router_id, + oa->lsdb_self); + if (lsa == NULL) { + if (IS_OSPF6_DEBUG_SPF(PROCESS)) + zlog_debug("%s: No router LSA for area %s\n", __func__, + oa->name); + return; + } + + /* initialize */ + candidate_list = pqueue_create(); + candidate_list->cmp = ospf6_vertex_cmp; + + root = ospf6_vertex_create(lsa); + root->area = oa; + root->cost = 0; + root->hops = 0; + inet_pton(AF_INET6, "::1", &address); + + /* Actually insert root to the candidate-list as the only candidate */ + pqueue_enqueue(root, candidate_list); + + /* Iterate until candidate-list becomes empty */ + while (candidate_list->size) { + /* get closest candidate from priority queue */ + v = pqueue_dequeue(candidate_list); + + /* installing may result in merging or rejecting of the vertex + */ + if (ospf6_spf_install(v, result_table) < 0) + continue; + + /* Skip overloaded routers */ + if ((OSPF6_LSA_IS_TYPE(ROUTER, v->lsa) + && ospf6_router_is_stub_router(v->lsa))) + continue; + + /* For each LS description in the just-added vertex V's LSA */ + size = (VERTEX_IS_TYPE(ROUTER, v) + ? sizeof(struct ospf6_router_lsdesc) + : sizeof(struct ospf6_network_lsdesc)); + for (lsdesc = OSPF6_LSA_HEADER_END(v->lsa->header) + 4; + lsdesc + size <= OSPF6_LSA_END(v->lsa->header); + lsdesc += size) { + lsa = ospf6_lsdesc_lsa(lsdesc, v); + if (lsa == NULL) + continue; + + if (OSPF6_LSA_IS_MAXAGE(lsa)) + continue; + + if (!ospf6_lsdesc_backlink(lsa, lsdesc, v)) + continue; + + w = ospf6_vertex_create(lsa); + w->area = oa; + w->parent = v; + if (VERTEX_IS_TYPE(ROUTER, v)) { + w->cost = v->cost + + ROUTER_LSDESC_GET_METRIC(lsdesc); + w->hops = + v->hops + + (VERTEX_IS_TYPE(NETWORK, w) ? 0 : 1); + } else /* NETWORK */ + { + w->cost = v->cost; + w->hops = v->hops + 1; + } + + /* nexthop calculation */ + if (w->hops == 0) + ospf6_add_nexthop( + w->nh_list, + ROUTER_LSDESC_GET_IFID(lsdesc), NULL); + else if (w->hops == 1 && v->hops == 0) + ospf6_nexthop_calc(w, v, lsdesc); + else { + ospf6_copy_nexthops(w->nh_list, v->nh_list); + } + + /* add new candidate to the candidate_list */ + if (IS_OSPF6_DEBUG_SPF(PROCESS)) + zlog_debug( + " New candidate: %s hops %d cost %d", + w->name, w->hops, w->cost); + pqueue_enqueue(w, candidate_list); + } + } + + pqueue_delete(candidate_list); + + oa->spf_calculation++; } -static void -ospf6_spf_log_database (struct ospf6_area *oa) +static void ospf6_spf_log_database(struct ospf6_area *oa) { - char *p, *end, buffer[256]; - struct listnode *node; - struct ospf6_interface *oi; - - p = buffer; - end = buffer + sizeof (buffer); - - snprintf (p, end - p, "SPF on DB (#LSAs):"); - p = (buffer + strlen (buffer) < end ? buffer + strlen (buffer) : end); - snprintf (p, end - p, " Area %s: %d", oa->name, oa->lsdb->count); - p = (buffer + strlen (buffer) < end ? buffer + strlen (buffer) : end); - - for (ALL_LIST_ELEMENTS_RO (oa->if_list, node, oi)) - { - snprintf (p, end - p, " I/F %s: %d", - oi->interface->name, oi->lsdb->count); - p = (buffer + strlen (buffer) < end ? buffer + strlen (buffer) : end); - } - - zlog_debug ("%s", buffer); + char *p, *end, buffer[256]; + struct listnode *node; + struct ospf6_interface *oi; + + p = buffer; + end = buffer + sizeof(buffer); + + snprintf(p, end - p, "SPF on DB (#LSAs):"); + p = (buffer + strlen(buffer) < end ? buffer + strlen(buffer) : end); + snprintf(p, end - p, " Area %s: %d", oa->name, oa->lsdb->count); + p = (buffer + strlen(buffer) < end ? buffer + strlen(buffer) : end); + + for (ALL_LIST_ELEMENTS_RO(oa->if_list, node, oi)) { + snprintf(p, end - p, " I/F %s: %d", oi->interface->name, + oi->lsdb->count); + p = (buffer + strlen(buffer) < end ? buffer + strlen(buffer) + : end); + } + + zlog_debug("%s", buffer); } -static int -ospf6_spf_calculation_thread (struct thread *t) +static int ospf6_spf_calculation_thread(struct thread *t) { - struct ospf6_area *oa; - struct ospf6 *ospf6; - struct timeval start, end, runtime; - struct listnode *node; - int areas_processed = 0; - char rbuf[32]; - - ospf6 = (struct ospf6 *)THREAD_ARG (t); - ospf6->t_spf_calc = NULL; - - /* execute SPF calculation */ - monotime(&start); - - if (ospf6_is_router_abr (ospf6)) - ospf6_abr_range_reset_cost (ospf6); - - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) - { - - if (oa == ospf6->backbone) - continue; - - if (IS_OSPF6_DEBUG_SPF (PROCESS)) - zlog_debug ("SPF calculation for Area %s", oa->name); - if (IS_OSPF6_DEBUG_SPF (DATABASE)) - ospf6_spf_log_database (oa); - - ospf6_spf_calculation (ospf6->router_id, oa->spf_table, oa); - ospf6_intra_route_calculation (oa); - ospf6_intra_brouter_calculation (oa); - - areas_processed++; - } - - if (ospf6->backbone) - { - if (IS_OSPF6_DEBUG_SPF (PROCESS)) - zlog_debug ("SPF calculation for Backbone area %s", - ospf6->backbone->name); - if (IS_OSPF6_DEBUG_SPF (DATABASE)) - ospf6_spf_log_database(ospf6->backbone); - - ospf6_spf_calculation(ospf6->router_id, ospf6->backbone->spf_table, - ospf6->backbone); - ospf6_intra_route_calculation(ospf6->backbone); - ospf6_intra_brouter_calculation(ospf6->backbone); - areas_processed++; - } - - if (ospf6_is_router_abr (ospf6)) - ospf6_abr_defaults_to_stub (ospf6); - - monotime(&end); - timersub (&end, &start, &runtime); - - ospf6->ts_spf_duration = runtime; - - ospf6_spf_reason_string(ospf6->spf_reason, rbuf, sizeof(rbuf)); - - if (IS_OSPF6_DEBUG_SPF (PROCESS) || IS_OSPF6_DEBUG_SPF (TIME)) - zlog_debug ("SPF runtime: %lld sec %lld usec", - (long long)runtime.tv_sec, (long long)runtime.tv_usec); - - zlog_info("SPF processing: # Areas: %d, SPF runtime: %lld sec %lld usec, " - "Reason: %s\n", areas_processed, - (long long)runtime.tv_sec, (long long)runtime.tv_usec, - rbuf); - ospf6->last_spf_reason = ospf6->spf_reason; - ospf6_reset_spf_reason(ospf6); - return 0; + struct ospf6_area *oa; + struct ospf6 *ospf6; + struct timeval start, end, runtime; + struct listnode *node; + int areas_processed = 0; + char rbuf[32]; + + ospf6 = (struct ospf6 *)THREAD_ARG(t); + ospf6->t_spf_calc = NULL; + + /* execute SPF calculation */ + monotime(&start); + + if (ospf6_is_router_abr(ospf6)) + ospf6_abr_range_reset_cost(ospf6); + + for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) { + + if (oa == ospf6->backbone) + continue; + + if (IS_OSPF6_DEBUG_SPF(PROCESS)) + zlog_debug("SPF calculation for Area %s", oa->name); + if (IS_OSPF6_DEBUG_SPF(DATABASE)) + ospf6_spf_log_database(oa); + + ospf6_spf_calculation(ospf6->router_id, oa->spf_table, oa); + ospf6_intra_route_calculation(oa); + ospf6_intra_brouter_calculation(oa); + + areas_processed++; + } + + if (ospf6->backbone) { + if (IS_OSPF6_DEBUG_SPF(PROCESS)) + zlog_debug("SPF calculation for Backbone area %s", + ospf6->backbone->name); + if (IS_OSPF6_DEBUG_SPF(DATABASE)) + ospf6_spf_log_database(ospf6->backbone); + + ospf6_spf_calculation(ospf6->router_id, + ospf6->backbone->spf_table, + ospf6->backbone); + ospf6_intra_route_calculation(ospf6->backbone); + ospf6_intra_brouter_calculation(ospf6->backbone); + areas_processed++; + } + + if (ospf6_is_router_abr(ospf6)) + ospf6_abr_defaults_to_stub(ospf6); + + monotime(&end); + timersub(&end, &start, &runtime); + + ospf6->ts_spf_duration = runtime; + + ospf6_spf_reason_string(ospf6->spf_reason, rbuf, sizeof(rbuf)); + + if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF(TIME)) + zlog_debug("SPF runtime: %lld sec %lld usec", + (long long)runtime.tv_sec, + (long long)runtime.tv_usec); + + zlog_info( + "SPF processing: # Areas: %d, SPF runtime: %lld sec %lld usec, " + "Reason: %s\n", + areas_processed, (long long)runtime.tv_sec, + (long long)runtime.tv_usec, rbuf); + ospf6->last_spf_reason = ospf6->spf_reason; + ospf6_reset_spf_reason(ospf6); + return 0; } /* Add schedule for SPF calculation. To avoid frequenst SPF calc, we set timer for SPF calc. */ -void -ospf6_spf_schedule (struct ospf6 *ospf6, unsigned int reason) +void ospf6_spf_schedule(struct ospf6 *ospf6, unsigned int reason) { - unsigned long delay, elapsed, ht; - - ospf6_set_spf_reason(ospf6, reason); - - if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME)) - { - char rbuf[32]; - ospf6_spf_reason_string(reason, rbuf, sizeof(rbuf)); - zlog_debug ("SPF: calculation timer scheduled (reason %s)", rbuf); - } - - /* OSPF instance does not exist. */ - if (ospf6 == NULL) - return; - - /* SPF calculation timer is already scheduled. */ - if (ospf6->t_spf_calc) - { - if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME)) - zlog_debug ("SPF: calculation timer is already scheduled: %p", - (void *)ospf6->t_spf_calc); - return; - } - - elapsed = monotime_since(&ospf6->ts_spf, NULL) / 1000LL; - ht = ospf6->spf_holdtime * ospf6->spf_hold_multiplier; - - if (ht > ospf6->spf_max_holdtime) - ht = ospf6->spf_max_holdtime; - - /* Get SPF calculation delay time. */ - if (elapsed < ht) - { - /* Got an event within the hold time of last SPF. We need to - * increase the hold_multiplier, if it's not already at/past - * maximum value, and wasn't already increased.. - */ - if (ht < ospf6->spf_max_holdtime) - ospf6->spf_hold_multiplier++; - - /* always honour the SPF initial delay */ - if ( (ht - elapsed) < ospf6->spf_delay) - delay = ospf6->spf_delay; - else - delay = ht - elapsed; - } - else - { - /* Event is past required hold-time of last SPF */ - delay = ospf6->spf_delay; - ospf6->spf_hold_multiplier = 1; - } - - if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME)) - zlog_debug ("SPF: calculation timer delay = %ld", delay); - - zlog_info ("SPF: Scheduled in %ld msec", delay); - - ospf6->t_spf_calc = NULL; - thread_add_timer_msec(master, ospf6_spf_calculation_thread, ospf6, delay, - &ospf6->t_spf_calc); + unsigned long delay, elapsed, ht; + + ospf6_set_spf_reason(ospf6, reason); + + if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF(TIME)) { + char rbuf[32]; + ospf6_spf_reason_string(reason, rbuf, sizeof(rbuf)); + zlog_debug("SPF: calculation timer scheduled (reason %s)", + rbuf); + } + + /* OSPF instance does not exist. */ + if (ospf6 == NULL) + return; + + /* SPF calculation timer is already scheduled. */ + if (ospf6->t_spf_calc) { + if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF(TIME)) + zlog_debug( + "SPF: calculation timer is already scheduled: %p", + (void *)ospf6->t_spf_calc); + return; + } + + elapsed = monotime_since(&ospf6->ts_spf, NULL) / 1000LL; + ht = ospf6->spf_holdtime * ospf6->spf_hold_multiplier; + + if (ht > ospf6->spf_max_holdtime) + ht = ospf6->spf_max_holdtime; + + /* Get SPF calculation delay time. */ + if (elapsed < ht) { + /* Got an event within the hold time of last SPF. We need to + * increase the hold_multiplier, if it's not already at/past + * maximum value, and wasn't already increased.. + */ + if (ht < ospf6->spf_max_holdtime) + ospf6->spf_hold_multiplier++; + + /* always honour the SPF initial delay */ + if ((ht - elapsed) < ospf6->spf_delay) + delay = ospf6->spf_delay; + else + delay = ht - elapsed; + } else { + /* Event is past required hold-time of last SPF */ + delay = ospf6->spf_delay; + ospf6->spf_hold_multiplier = 1; + } + + if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF(TIME)) + zlog_debug("SPF: calculation timer delay = %ld", delay); + + zlog_info("SPF: Scheduled in %ld msec", delay); + + ospf6->t_spf_calc = NULL; + thread_add_timer_msec(master, ospf6_spf_calculation_thread, ospf6, + delay, &ospf6->t_spf_calc); } -void -ospf6_spf_display_subtree (struct vty *vty, const char *prefix, int rest, - struct ospf6_vertex *v) +void ospf6_spf_display_subtree(struct vty *vty, const char *prefix, int rest, + struct ospf6_vertex *v) { - struct listnode *node, *nnode; - struct ospf6_vertex *c; - char *next_prefix; - int len; - int restnum; - - /* "prefix" is the space prefix of the display line */ - vty_out (vty, "%s+-%s [%d]\n", prefix, v->name, v->cost); - - len = strlen (prefix) + 4; - next_prefix = (char *) malloc (len); - if (next_prefix == NULL) - { - vty_out (vty, "malloc failed\n"); - return; - } - snprintf (next_prefix, len, "%s%s", prefix, (rest ? "| " : " ")); - - restnum = listcount (v->child_list); - for (ALL_LIST_ELEMENTS (v->child_list, node, nnode, c)) - { - restnum--; - ospf6_spf_display_subtree (vty, next_prefix, restnum, c); - } - - free (next_prefix); + struct listnode *node, *nnode; + struct ospf6_vertex *c; + char *next_prefix; + int len; + int restnum; + + /* "prefix" is the space prefix of the display line */ + vty_out(vty, "%s+-%s [%d]\n", prefix, v->name, v->cost); + + len = strlen(prefix) + 4; + next_prefix = (char *)malloc(len); + if (next_prefix == NULL) { + vty_out(vty, "malloc failed\n"); + return; + } + snprintf(next_prefix, len, "%s%s", prefix, (rest ? "| " : " ")); + + restnum = listcount(v->child_list); + for (ALL_LIST_ELEMENTS(v->child_list, node, nnode, c)) { + restnum--; + ospf6_spf_display_subtree(vty, next_prefix, restnum, c); + } + + free(next_prefix); } DEFUN (debug_ospf6_spf_process, @@ -771,10 +738,10 @@ DEFUN (debug_ospf6_spf_process, "Debug Detailed SPF Process\n" ) { - unsigned char level = 0; - level = OSPF6_DEBUG_SPF_PROCESS; - OSPF6_DEBUG_SPF_ON (level); - return CMD_SUCCESS; + unsigned char level = 0; + level = OSPF6_DEBUG_SPF_PROCESS; + OSPF6_DEBUG_SPF_ON(level); + return CMD_SUCCESS; } DEFUN (debug_ospf6_spf_time, @@ -786,10 +753,10 @@ DEFUN (debug_ospf6_spf_time, "Measure time taken by SPF Calculation\n" ) { - unsigned char level = 0; - level = OSPF6_DEBUG_SPF_TIME; - OSPF6_DEBUG_SPF_ON (level); - return CMD_SUCCESS; + unsigned char level = 0; + level = OSPF6_DEBUG_SPF_TIME; + OSPF6_DEBUG_SPF_ON(level); + return CMD_SUCCESS; } DEFUN (debug_ospf6_spf_database, @@ -801,10 +768,10 @@ DEFUN (debug_ospf6_spf_database, "Log number of LSAs at SPF Calculation time\n" ) { - unsigned char level = 0; - level = OSPF6_DEBUG_SPF_DATABASE; - OSPF6_DEBUG_SPF_ON (level); - return CMD_SUCCESS; + unsigned char level = 0; + level = OSPF6_DEBUG_SPF_DATABASE; + OSPF6_DEBUG_SPF_ON(level); + return CMD_SUCCESS; } DEFUN (no_debug_ospf6_spf_process, @@ -817,10 +784,10 @@ DEFUN (no_debug_ospf6_spf_process, "Quit Debugging Detailed SPF Process\n" ) { - unsigned char level = 0; - level = OSPF6_DEBUG_SPF_PROCESS; - OSPF6_DEBUG_SPF_OFF (level); - return CMD_SUCCESS; + unsigned char level = 0; + level = OSPF6_DEBUG_SPF_PROCESS; + OSPF6_DEBUG_SPF_OFF(level); + return CMD_SUCCESS; } DEFUN (no_debug_ospf6_spf_time, @@ -833,10 +800,10 @@ DEFUN (no_debug_ospf6_spf_time, "Quit Measuring time taken by SPF Calculation\n" ) { - unsigned char level = 0; - level = OSPF6_DEBUG_SPF_TIME; - OSPF6_DEBUG_SPF_OFF (level); - return CMD_SUCCESS; + unsigned char level = 0; + level = OSPF6_DEBUG_SPF_TIME; + OSPF6_DEBUG_SPF_OFF(level); + return CMD_SUCCESS; } DEFUN (no_debug_ospf6_spf_database, @@ -849,24 +816,22 @@ DEFUN (no_debug_ospf6_spf_database, "Quit Logging number of LSAs at SPF Calculation time\n" ) { - unsigned char level = 0; - level = OSPF6_DEBUG_SPF_DATABASE; - OSPF6_DEBUG_SPF_OFF (level); - return CMD_SUCCESS; + unsigned char level = 0; + level = OSPF6_DEBUG_SPF_DATABASE; + OSPF6_DEBUG_SPF_OFF(level); + return CMD_SUCCESS; } -static int -ospf6_timers_spf_set (struct vty *vty, unsigned int delay, - unsigned int hold, - unsigned int max) +static int ospf6_timers_spf_set(struct vty *vty, unsigned int delay, + unsigned int hold, unsigned int max) { - VTY_DECLVAR_CONTEXT(ospf6, ospf); + VTY_DECLVAR_CONTEXT(ospf6, ospf); - ospf->spf_delay = delay; - ospf->spf_holdtime = hold; - ospf->spf_max_holdtime = max; + ospf->spf_delay = delay; + ospf->spf_holdtime = hold; + ospf->spf_max_holdtime = max; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ospf6_timers_throttle_spf, @@ -879,16 +844,16 @@ DEFUN (ospf6_timers_throttle_spf, "Initial hold time (msec) between consecutive SPF calculations\n" "Maximum hold time (msec)\n") { - int idx_number = 3; - int idx_number_2 = 4; - int idx_number_3 = 5; - unsigned int delay, hold, max; + int idx_number = 3; + int idx_number_2 = 4; + int idx_number_3 = 5; + unsigned int delay, hold, max; - delay = strtoul(argv[idx_number]->arg, NULL, 10); - hold = strtoul(argv[idx_number_2]->arg, NULL, 10); - max = strtoul(argv[idx_number_3]->arg, NULL, 10); + delay = strtoul(argv[idx_number]->arg, NULL, 10); + hold = strtoul(argv[idx_number_2]->arg, NULL, 10); + max = strtoul(argv[idx_number_3]->arg, NULL, 10); - return ospf6_timers_spf_set (vty, delay, hold, max); + return ospf6_timers_spf_set(vty, delay, hold, max); } DEFUN (no_ospf6_timers_throttle_spf, @@ -902,58 +867,52 @@ DEFUN (no_ospf6_timers_throttle_spf, "Initial hold time (msec) between consecutive SPF calculations\n" "Maximum hold time (msec)\n") { - return ospf6_timers_spf_set (vty, - OSPF_SPF_DELAY_DEFAULT, - OSPF_SPF_HOLDTIME_DEFAULT, - OSPF_SPF_MAX_HOLDTIME_DEFAULT); + return ospf6_timers_spf_set(vty, OSPF_SPF_DELAY_DEFAULT, + OSPF_SPF_HOLDTIME_DEFAULT, + OSPF_SPF_MAX_HOLDTIME_DEFAULT); } -int -config_write_ospf6_debug_spf (struct vty *vty) +int config_write_ospf6_debug_spf(struct vty *vty) { - if (IS_OSPF6_DEBUG_SPF (PROCESS)) - vty_out (vty, "debug ospf6 spf process\n"); - if (IS_OSPF6_DEBUG_SPF (TIME)) - vty_out (vty, "debug ospf6 spf time\n"); - if (IS_OSPF6_DEBUG_SPF (DATABASE)) - vty_out (vty, "debug ospf6 spf database\n"); - return 0; + if (IS_OSPF6_DEBUG_SPF(PROCESS)) + vty_out(vty, "debug ospf6 spf process\n"); + if (IS_OSPF6_DEBUG_SPF(TIME)) + vty_out(vty, "debug ospf6 spf time\n"); + if (IS_OSPF6_DEBUG_SPF(DATABASE)) + vty_out(vty, "debug ospf6 spf database\n"); + return 0; } -void -ospf6_spf_config_write (struct vty *vty) +void ospf6_spf_config_write(struct vty *vty) { - if (ospf6->spf_delay != OSPF_SPF_DELAY_DEFAULT || - ospf6->spf_holdtime != OSPF_SPF_HOLDTIME_DEFAULT || - ospf6->spf_max_holdtime != OSPF_SPF_MAX_HOLDTIME_DEFAULT) - vty_out (vty, " timers throttle spf %d %d %d\n", - ospf6->spf_delay, ospf6->spf_holdtime, - ospf6->spf_max_holdtime); - + if (ospf6->spf_delay != OSPF_SPF_DELAY_DEFAULT + || ospf6->spf_holdtime != OSPF_SPF_HOLDTIME_DEFAULT + || ospf6->spf_max_holdtime != OSPF_SPF_MAX_HOLDTIME_DEFAULT) + vty_out(vty, " timers throttle spf %d %d %d\n", + ospf6->spf_delay, ospf6->spf_holdtime, + ospf6->spf_max_holdtime); } -void -install_element_ospf6_debug_spf (void) +void install_element_ospf6_debug_spf(void) { - install_element (ENABLE_NODE, &debug_ospf6_spf_process_cmd); - install_element (ENABLE_NODE, &debug_ospf6_spf_time_cmd); - install_element (ENABLE_NODE, &debug_ospf6_spf_database_cmd); - install_element (ENABLE_NODE, &no_debug_ospf6_spf_process_cmd); - install_element (ENABLE_NODE, &no_debug_ospf6_spf_time_cmd); - install_element (ENABLE_NODE, &no_debug_ospf6_spf_database_cmd); - install_element (CONFIG_NODE, &debug_ospf6_spf_process_cmd); - install_element (CONFIG_NODE, &debug_ospf6_spf_time_cmd); - install_element (CONFIG_NODE, &debug_ospf6_spf_database_cmd); - install_element (CONFIG_NODE, &no_debug_ospf6_spf_process_cmd); - install_element (CONFIG_NODE, &no_debug_ospf6_spf_time_cmd); - install_element (CONFIG_NODE, &no_debug_ospf6_spf_database_cmd); + install_element(ENABLE_NODE, &debug_ospf6_spf_process_cmd); + install_element(ENABLE_NODE, &debug_ospf6_spf_time_cmd); + install_element(ENABLE_NODE, &debug_ospf6_spf_database_cmd); + install_element(ENABLE_NODE, &no_debug_ospf6_spf_process_cmd); + install_element(ENABLE_NODE, &no_debug_ospf6_spf_time_cmd); + install_element(ENABLE_NODE, &no_debug_ospf6_spf_database_cmd); + install_element(CONFIG_NODE, &debug_ospf6_spf_process_cmd); + install_element(CONFIG_NODE, &debug_ospf6_spf_time_cmd); + install_element(CONFIG_NODE, &debug_ospf6_spf_database_cmd); + install_element(CONFIG_NODE, &no_debug_ospf6_spf_process_cmd); + install_element(CONFIG_NODE, &no_debug_ospf6_spf_time_cmd); + install_element(CONFIG_NODE, &no_debug_ospf6_spf_database_cmd); } -void -ospf6_spf_init (void) +void ospf6_spf_init(void) { - install_element (OSPF6_NODE, &ospf6_timers_throttle_spf_cmd); - install_element (OSPF6_NODE, &no_ospf6_timers_throttle_spf_cmd); + install_element(OSPF6_NODE, &ospf6_timers_throttle_spf_cmd); + install_element(OSPF6_NODE, &no_ospf6_timers_throttle_spf_cmd); } diff --git a/ospf6d/ospf6_spf.h b/ospf6d/ospf6_spf.h index 87a86c0ac..2246e2dfc 100644 --- a/ospf6d/ospf6_spf.h +++ b/ospf6d/ospf6_spf.h @@ -28,55 +28,51 @@ extern unsigned char conf_debug_ospf6_spf; #define OSPF6_DEBUG_SPF_PROCESS 0x01 #define OSPF6_DEBUG_SPF_TIME 0x02 #define OSPF6_DEBUG_SPF_DATABASE 0x04 -#define OSPF6_DEBUG_SPF_ON(level) \ - (conf_debug_ospf6_spf |= (level)) -#define OSPF6_DEBUG_SPF_OFF(level) \ - (conf_debug_ospf6_spf &= ~(level)) -#define IS_OSPF6_DEBUG_SPF(level) \ - (conf_debug_ospf6_spf & OSPF6_DEBUG_SPF_ ## level) +#define OSPF6_DEBUG_SPF_ON(level) (conf_debug_ospf6_spf |= (level)) +#define OSPF6_DEBUG_SPF_OFF(level) (conf_debug_ospf6_spf &= ~(level)) +#define IS_OSPF6_DEBUG_SPF(level) \ + (conf_debug_ospf6_spf & OSPF6_DEBUG_SPF_##level) /* Transit Vertex */ -struct ospf6_vertex -{ - /* type of this vertex */ - u_int8_t type; +struct ospf6_vertex { + /* type of this vertex */ + u_int8_t type; - /* Vertex Identifier */ - struct prefix vertex_id; + /* Vertex Identifier */ + struct prefix vertex_id; - /* Identifier String */ - char name[128]; + /* Identifier String */ + char name[128]; - /* Associated Area */ - struct ospf6_area *area; + /* Associated Area */ + struct ospf6_area *area; - /* Associated LSA */ - struct ospf6_lsa *lsa; + /* Associated LSA */ + struct ospf6_lsa *lsa; - /* Distance from Root (i.e. Cost) */ - u_int32_t cost; + /* Distance from Root (i.e. Cost) */ + u_int32_t cost; - /* Router hops to this node */ - u_char hops; + /* Router hops to this node */ + u_char hops; - /* capability bits */ - u_char capability; + /* capability bits */ + u_char capability; - /* Optional capabilities */ - u_char options[3]; + /* Optional capabilities */ + u_char options[3]; - /* For tree display */ - struct ospf6_vertex *parent; - struct list *child_list; + /* For tree display */ + struct ospf6_vertex *parent; + struct list *child_list; - /* nexthops to this node */ - struct list *nh_list; + /* nexthops to this node */ + struct list *nh_list; }; #define OSPF6_VERTEX_TYPE_ROUTER 0x01 #define OSPF6_VERTEX_TYPE_NETWORK 0x02 -#define VERTEX_IS_TYPE(t, v) \ - ((v)->type == OSPF6_VERTEX_TYPE_ ## t ? 1 : 0) +#define VERTEX_IS_TYPE(t, v) ((v)->type == OSPF6_VERTEX_TYPE_##t ? 1 : 0) /* What triggered the SPF? */ #define OSPF6_SPF_FLAGS_ROUTER_LSA_ADDED (1 << 0) @@ -88,76 +84,69 @@ struct ospf6_vertex #define OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED (1 << 6) #define OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED (1 << 7) -static inline void -ospf6_set_spf_reason (struct ospf6* ospf, unsigned int reason) +static inline void ospf6_set_spf_reason(struct ospf6 *ospf, unsigned int reason) { - ospf->spf_reason |= reason; + ospf->spf_reason |= reason; } -static inline void -ospf6_reset_spf_reason (struct ospf6 *ospf) +static inline void ospf6_reset_spf_reason(struct ospf6 *ospf) { - ospf->spf_reason = 0; + ospf->spf_reason = 0; } -static inline unsigned int -ospf6_lsadd_to_spf_reason (struct ospf6_lsa *lsa) +static inline unsigned int ospf6_lsadd_to_spf_reason(struct ospf6_lsa *lsa) { - unsigned int reason = 0; - - switch (ntohs (lsa->header->type)) - { - case OSPF6_LSTYPE_ROUTER: - reason = OSPF6_SPF_FLAGS_ROUTER_LSA_ADDED; - break; - case OSPF6_LSTYPE_NETWORK: - reason = OSPF6_SPF_FLAGS_NETWORK_LSA_ADDED; - break; - case OSPF6_LSTYPE_LINK: - reason = OSPF6_SPF_FLAGS_LINK_LSA_ADDED; - break; - default: - break; - } - return (reason); + unsigned int reason = 0; + + switch (ntohs(lsa->header->type)) { + case OSPF6_LSTYPE_ROUTER: + reason = OSPF6_SPF_FLAGS_ROUTER_LSA_ADDED; + break; + case OSPF6_LSTYPE_NETWORK: + reason = OSPF6_SPF_FLAGS_NETWORK_LSA_ADDED; + break; + case OSPF6_LSTYPE_LINK: + reason = OSPF6_SPF_FLAGS_LINK_LSA_ADDED; + break; + default: + break; + } + return (reason); } -static inline unsigned int -ospf6_lsremove_to_spf_reason (struct ospf6_lsa *lsa) +static inline unsigned int ospf6_lsremove_to_spf_reason(struct ospf6_lsa *lsa) { - unsigned int reason = 0; - - switch (ntohs (lsa->header->type)) - { - case OSPF6_LSTYPE_ROUTER: - reason = OSPF6_SPF_FLAGS_ROUTER_LSA_REMOVED; - break; - case OSPF6_LSTYPE_NETWORK: - reason = OSPF6_SPF_FLAGS_NETWORK_LSA_REMOVED; - break; - case OSPF6_LSTYPE_LINK: - reason = OSPF6_SPF_FLAGS_LINK_LSA_REMOVED; - break; - default: - break; - } - return (reason); + unsigned int reason = 0; + + switch (ntohs(lsa->header->type)) { + case OSPF6_LSTYPE_ROUTER: + reason = OSPF6_SPF_FLAGS_ROUTER_LSA_REMOVED; + break; + case OSPF6_LSTYPE_NETWORK: + reason = OSPF6_SPF_FLAGS_NETWORK_LSA_REMOVED; + break; + case OSPF6_LSTYPE_LINK: + reason = OSPF6_SPF_FLAGS_LINK_LSA_REMOVED; + break; + default: + break; + } + return (reason); } -extern void ospf6_spf_table_finish (struct ospf6_route_table *result_table); -extern void ospf6_spf_calculation (u_int32_t router_id, - struct ospf6_route_table *result_table, - struct ospf6_area *oa); -extern void ospf6_spf_schedule (struct ospf6 *ospf, unsigned int reason); +extern void ospf6_spf_table_finish(struct ospf6_route_table *result_table); +extern void ospf6_spf_calculation(u_int32_t router_id, + struct ospf6_route_table *result_table, + struct ospf6_area *oa); +extern void ospf6_spf_schedule(struct ospf6 *ospf, unsigned int reason); -extern void ospf6_spf_display_subtree (struct vty *vty, const char *prefix, - int rest, struct ospf6_vertex *v); +extern void ospf6_spf_display_subtree(struct vty *vty, const char *prefix, + int rest, struct ospf6_vertex *v); -extern void ospf6_spf_config_write (struct vty *vty); -extern int config_write_ospf6_debug_spf (struct vty *vty); -extern void install_element_ospf6_debug_spf (void); -extern void ospf6_spf_init (void); -extern void ospf6_spf_reason_string (unsigned int reason, char *buf, int size); +extern void ospf6_spf_config_write(struct vty *vty); +extern int config_write_ospf6_debug_spf(struct vty *vty); +extern void install_element_ospf6_debug_spf(void); +extern void ospf6_spf_init(void); +extern void ospf6_spf_reason_string(unsigned int reason, char *buf, int size); #endif /* OSPF6_SPF_H */ - diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 9e0b86b7b..387690bc8 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -54,240 +54,218 @@ DEFINE_QOBJ_TYPE(ospf6) /* global ospf6d variable */ struct ospf6 *ospf6; -static void ospf6_disable (struct ospf6 *o); +static void ospf6_disable(struct ospf6 *o); -static void -ospf6_top_lsdb_hook_add (struct ospf6_lsa *lsa) +static void ospf6_top_lsdb_hook_add(struct ospf6_lsa *lsa) { - switch (ntohs (lsa->header->type)) - { - case OSPF6_LSTYPE_AS_EXTERNAL: - ospf6_asbr_lsa_add (lsa); - break; - - default: - break; - } + switch (ntohs(lsa->header->type)) { + case OSPF6_LSTYPE_AS_EXTERNAL: + ospf6_asbr_lsa_add(lsa); + break; + + default: + break; + } } -static void -ospf6_top_lsdb_hook_remove (struct ospf6_lsa *lsa) +static void ospf6_top_lsdb_hook_remove(struct ospf6_lsa *lsa) { - switch (ntohs (lsa->header->type)) - { - case OSPF6_LSTYPE_AS_EXTERNAL: - ospf6_asbr_lsa_remove (lsa); - break; - - default: - break; - } + switch (ntohs(lsa->header->type)) { + case OSPF6_LSTYPE_AS_EXTERNAL: + ospf6_asbr_lsa_remove(lsa); + break; + + default: + break; + } } -static void -ospf6_top_route_hook_add (struct ospf6_route *route) +static void ospf6_top_route_hook_add(struct ospf6_route *route) { - ospf6_abr_originate_summary (route); - ospf6_zebra_route_update_add (route); + ospf6_abr_originate_summary(route); + ospf6_zebra_route_update_add(route); } -static void -ospf6_top_route_hook_remove (struct ospf6_route *route) +static void ospf6_top_route_hook_remove(struct ospf6_route *route) { - route->flag |= OSPF6_ROUTE_REMOVE; - ospf6_abr_originate_summary (route); - ospf6_zebra_route_update_remove (route); + route->flag |= OSPF6_ROUTE_REMOVE; + ospf6_abr_originate_summary(route); + ospf6_zebra_route_update_remove(route); } -static void -ospf6_top_brouter_hook_add (struct ospf6_route *route) +static void ospf6_top_brouter_hook_add(struct ospf6_route *route) { - ospf6_abr_examin_brouter (ADV_ROUTER_IN_PREFIX (&route->prefix)); - ospf6_asbr_lsentry_add (route); - ospf6_abr_originate_summary (route); + ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix)); + ospf6_asbr_lsentry_add(route); + ospf6_abr_originate_summary(route); } -static void -ospf6_top_brouter_hook_remove (struct ospf6_route *route) +static void ospf6_top_brouter_hook_remove(struct ospf6_route *route) { - route->flag |= OSPF6_ROUTE_REMOVE; - ospf6_abr_examin_brouter (ADV_ROUTER_IN_PREFIX (&route->prefix)); - ospf6_asbr_lsentry_remove (route); - ospf6_abr_originate_summary (route); + route->flag |= OSPF6_ROUTE_REMOVE; + ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix)); + ospf6_asbr_lsentry_remove(route); + ospf6_abr_originate_summary(route); } -static struct ospf6 * -ospf6_create (void) +static struct ospf6 *ospf6_create(void) { - struct ospf6 *o; + struct ospf6 *o; - o = XCALLOC (MTYPE_OSPF6_TOP, sizeof (struct ospf6)); + o = XCALLOC(MTYPE_OSPF6_TOP, sizeof(struct ospf6)); - /* initialize */ - monotime(&o->starttime); - o->area_list = list_new (); - o->area_list->cmp = ospf6_area_cmp; - o->lsdb = ospf6_lsdb_create (o); - o->lsdb_self = ospf6_lsdb_create (o); - o->lsdb->hook_add = ospf6_top_lsdb_hook_add; - o->lsdb->hook_remove = ospf6_top_lsdb_hook_remove; + /* initialize */ + monotime(&o->starttime); + o->area_list = list_new(); + o->area_list->cmp = ospf6_area_cmp; + o->lsdb = ospf6_lsdb_create(o); + o->lsdb_self = ospf6_lsdb_create(o); + o->lsdb->hook_add = ospf6_top_lsdb_hook_add; + o->lsdb->hook_remove = ospf6_top_lsdb_hook_remove; - o->spf_delay = OSPF_SPF_DELAY_DEFAULT; - o->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT; - o->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT; - o->spf_hold_multiplier = 1; + o->spf_delay = OSPF_SPF_DELAY_DEFAULT; + o->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT; + o->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT; + o->spf_hold_multiplier = 1; - /* LSA timers value init */ - o->lsa_minarrival = OSPF_MIN_LS_ARRIVAL; + /* LSA timers value init */ + o->lsa_minarrival = OSPF_MIN_LS_ARRIVAL; - o->route_table = OSPF6_ROUTE_TABLE_CREATE (GLOBAL, ROUTES); - o->route_table->scope = o; - o->route_table->hook_add = ospf6_top_route_hook_add; - o->route_table->hook_remove = ospf6_top_route_hook_remove; + o->route_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, ROUTES); + o->route_table->scope = o; + o->route_table->hook_add = ospf6_top_route_hook_add; + o->route_table->hook_remove = ospf6_top_route_hook_remove; - o->brouter_table = OSPF6_ROUTE_TABLE_CREATE (GLOBAL, BORDER_ROUTERS); - o->brouter_table->scope = o; - o->brouter_table->hook_add = ospf6_top_brouter_hook_add; - o->brouter_table->hook_remove = ospf6_top_brouter_hook_remove; + o->brouter_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, BORDER_ROUTERS); + o->brouter_table->scope = o; + o->brouter_table->hook_add = ospf6_top_brouter_hook_add; + o->brouter_table->hook_remove = ospf6_top_brouter_hook_remove; - o->external_table = OSPF6_ROUTE_TABLE_CREATE (GLOBAL, EXTERNAL_ROUTES); - o->external_table->scope = o; + o->external_table = OSPF6_ROUTE_TABLE_CREATE(GLOBAL, EXTERNAL_ROUTES); + o->external_table->scope = o; - o->external_id_table = route_table_init (); + o->external_id_table = route_table_init(); - o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH; + o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH; - o->distance_table = route_table_init (); + o->distance_table = route_table_init(); - /* Enable "log-adjacency-changes" */ +/* Enable "log-adjacency-changes" */ #if DFLT_OSPF6_LOG_ADJACENCY_CHANGES - SET_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES); + SET_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES); #endif - QOBJ_REG (o, ospf6); + QOBJ_REG(o, ospf6); - return o; + return o; } -void -ospf6_delete (struct ospf6 *o) +void ospf6_delete(struct ospf6 *o) { - struct listnode *node, *nnode; - struct ospf6_area *oa; + struct listnode *node, *nnode; + struct ospf6_area *oa; - QOBJ_UNREG (o); - ospf6_disable (ospf6); + QOBJ_UNREG(o); + ospf6_disable(ospf6); - for (ALL_LIST_ELEMENTS (o->area_list, node, nnode, oa)) - ospf6_area_delete (oa); + for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa)) + ospf6_area_delete(oa); - list_delete (o->area_list); + list_delete(o->area_list); - ospf6_lsdb_delete (o->lsdb); - ospf6_lsdb_delete (o->lsdb_self); + ospf6_lsdb_delete(o->lsdb); + ospf6_lsdb_delete(o->lsdb_self); - ospf6_route_table_delete (o->route_table); - ospf6_route_table_delete (o->brouter_table); + ospf6_route_table_delete(o->route_table); + ospf6_route_table_delete(o->brouter_table); - ospf6_route_table_delete (o->external_table); - route_table_finish (o->external_id_table); + ospf6_route_table_delete(o->external_table); + route_table_finish(o->external_id_table); - ospf6_distance_reset (o); - route_table_finish (o->distance_table); + ospf6_distance_reset(o); + route_table_finish(o->distance_table); - XFREE (MTYPE_OSPF6_TOP, o); + XFREE(MTYPE_OSPF6_TOP, o); } -static void -ospf6_disable (struct ospf6 *o) +static void ospf6_disable(struct ospf6 *o) { - struct listnode *node, *nnode; - struct ospf6_area *oa; - - if (! CHECK_FLAG (o->flag, OSPF6_DISABLED)) - { - SET_FLAG (o->flag, OSPF6_DISABLED); - - for (ALL_LIST_ELEMENTS (o->area_list, node, nnode, oa)) - ospf6_area_disable (oa); - - /* XXX: This also changes persistent settings */ - ospf6_asbr_redistribute_reset(); - - ospf6_lsdb_remove_all (o->lsdb); - ospf6_route_remove_all (o->route_table); - ospf6_route_remove_all (o->brouter_table); - - THREAD_OFF(o->maxage_remover); - THREAD_OFF(o->t_spf_calc); - THREAD_OFF(o->t_ase_calc); - } + struct listnode *node, *nnode; + struct ospf6_area *oa; + + if (!CHECK_FLAG(o->flag, OSPF6_DISABLED)) { + SET_FLAG(o->flag, OSPF6_DISABLED); + + for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa)) + ospf6_area_disable(oa); + + /* XXX: This also changes persistent settings */ + ospf6_asbr_redistribute_reset(); + + ospf6_lsdb_remove_all(o->lsdb); + ospf6_route_remove_all(o->route_table); + ospf6_route_remove_all(o->brouter_table); + + THREAD_OFF(o->maxage_remover); + THREAD_OFF(o->t_spf_calc); + THREAD_OFF(o->t_ase_calc); + } } -static int -ospf6_maxage_remover (struct thread *thread) +static int ospf6_maxage_remover(struct thread *thread) { - struct ospf6 *o = (struct ospf6 *) THREAD_ARG (thread); - struct ospf6_area *oa; - struct ospf6_interface *oi; - struct ospf6_neighbor *on; - struct listnode *i, *j, *k; - int reschedule = 0; - - o->maxage_remover = (struct thread *) NULL; - - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - { - for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, k, on)) - { - if (on->state != OSPF6_NEIGHBOR_EXCHANGE && - on->state != OSPF6_NEIGHBOR_LOADING) - continue; - - ospf6_maxage_remove (o); - return 0; - } - } - } - - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - { - if (ospf6_lsdb_maxage_remover (oi->lsdb)) - { - reschedule = 1; - } + struct ospf6 *o = (struct ospf6 *)THREAD_ARG(thread); + struct ospf6_area *oa; + struct ospf6_interface *oi; + struct ospf6_neighbor *on; + struct listnode *i, *j, *k; + int reschedule = 0; + + o->maxage_remover = (struct thread *)NULL; + + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on)) { + if (on->state != OSPF6_NEIGHBOR_EXCHANGE + && on->state != OSPF6_NEIGHBOR_LOADING) + continue; + + ospf6_maxage_remove(o); + return 0; + } + } } - - if (ospf6_lsdb_maxage_remover (oa->lsdb)) - { - reschedule = 1; + + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + if (ospf6_lsdb_maxage_remover(oi->lsdb)) { + reschedule = 1; + } + } + + if (ospf6_lsdb_maxage_remover(oa->lsdb)) { + reschedule = 1; + } } - } - if (ospf6_lsdb_maxage_remover (o->lsdb)) - { - reschedule = 1; - } + if (ospf6_lsdb_maxage_remover(o->lsdb)) { + reschedule = 1; + } - if (reschedule) - { - ospf6_maxage_remove (o); - } + if (reschedule) { + ospf6_maxage_remove(o); + } - return 0; + return 0; } -void -ospf6_maxage_remove (struct ospf6 *o) +void ospf6_maxage_remove(struct ospf6 *o) { - if (o) - thread_add_timer(master, ospf6_maxage_remover, o, OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT, - &o->maxage_remover); + if (o) + thread_add_timer(master, ospf6_maxage_remover, o, + OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT, + &o->maxage_remover); } /* start ospf6 */ @@ -297,13 +275,13 @@ DEFUN_NOSH (router_ospf6, ROUTER_STR OSPF6_STR) { - if (ospf6 == NULL) - ospf6 = ospf6_create (); + if (ospf6 == NULL) + ospf6 = ospf6_create(); - /* set current ospf point. */ - VTY_PUSH_CONTEXT(OSPF6_NODE, ospf6); + /* set current ospf point. */ + VTY_PUSH_CONTEXT(OSPF6_NODE, ospf6); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* stop ospf6 */ @@ -314,18 +292,17 @@ DEFUN (no_router_ospf6, ROUTER_STR OSPF6_STR) { - if (ospf6 == NULL) - vty_out (vty, "OSPFv3 is not configured\n"); - else - { - ospf6_delete (ospf6); - ospf6 = NULL; - } + if (ospf6 == NULL) + vty_out(vty, "OSPFv3 is not configured\n"); + else { + ospf6_delete(ospf6); + ospf6 = NULL; + } - /* return to config node . */ - VTY_PUSH_CONTEXT_NULL(CONFIG_NODE); + /* return to config node . */ + VTY_PUSH_CONTEXT_NULL(CONFIG_NODE); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* change Router_ID commands. */ @@ -335,23 +312,23 @@ DEFUN (ospf6_router_id, "Configure OSPF Router-ID\n" V4NOTATION_STR) { - VTY_DECLVAR_CONTEXT(ospf6, o); - int idx_ipv4 = 1; - int ret; - u_int32_t router_id; - - ret = inet_pton (AF_INET, argv[idx_ipv4]->arg, &router_id); - if (ret == 0) - { - vty_out (vty, "malformed OSPF Router-ID: %s\n", argv[idx_ipv4]->arg); - return CMD_SUCCESS; - } + VTY_DECLVAR_CONTEXT(ospf6, o); + int idx_ipv4 = 1; + int ret; + u_int32_t router_id; + + ret = inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id); + if (ret == 0) { + vty_out(vty, "malformed OSPF Router-ID: %s\n", + argv[idx_ipv4]->arg); + return CMD_SUCCESS; + } - o->router_id_static = router_id; - if (o->router_id == 0) - o->router_id = router_id; + o->router_id_static = router_id; + if (o->router_id == 0) + o->router_id = router_id; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ospf6_log_adjacency_changes, @@ -359,11 +336,11 @@ DEFUN (ospf6_log_adjacency_changes, "log-adjacency-changes", "Log changes in adjacency state\n") { - VTY_DECLVAR_CONTEXT(ospf6, ospf6); + VTY_DECLVAR_CONTEXT(ospf6, ospf6); - SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES); - UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL); - return CMD_SUCCESS; + SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES); + UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL); + return CMD_SUCCESS; } DEFUN (ospf6_log_adjacency_changes_detail, @@ -372,11 +349,11 @@ DEFUN (ospf6_log_adjacency_changes_detail, "Log changes in adjacency state\n" "Log all state changes\n") { - VTY_DECLVAR_CONTEXT(ospf6, ospf6); + VTY_DECLVAR_CONTEXT(ospf6, ospf6); - SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES); - SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL); - return CMD_SUCCESS; + SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES); + SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL); + return CMD_SUCCESS; } DEFUN (no_ospf6_log_adjacency_changes, @@ -385,11 +362,11 @@ DEFUN (no_ospf6_log_adjacency_changes, NO_STR "Log changes in adjacency state\n") { - VTY_DECLVAR_CONTEXT(ospf6, ospf6); + VTY_DECLVAR_CONTEXT(ospf6, ospf6); - UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL); - UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES); - return CMD_SUCCESS; + UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL); + UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES); + return CMD_SUCCESS; } DEFUN (no_ospf6_log_adjacency_changes_detail, @@ -399,10 +376,10 @@ DEFUN (no_ospf6_log_adjacency_changes_detail, "Log changes in adjacency state\n" "Log all state changes\n") { - VTY_DECLVAR_CONTEXT(ospf6, ospf6); + VTY_DECLVAR_CONTEXT(ospf6, ospf6); - UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL); - return CMD_SUCCESS; + UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL); + return CMD_SUCCESS; } DEFUN (ospf6_timers_lsa, @@ -413,14 +390,14 @@ DEFUN (ospf6_timers_lsa, "Minimum delay in receiving new version of a LSA\n" "Delay in milliseconds\n") { - VTY_DECLVAR_CONTEXT(ospf6, ospf); - int idx_number = 3; - unsigned int minarrival; + VTY_DECLVAR_CONTEXT(ospf6, ospf); + int idx_number = 3; + unsigned int minarrival; - minarrival = strtoul(argv[idx_number]->arg, NULL, 10); - ospf->lsa_minarrival = minarrival; + minarrival = strtoul(argv[idx_number]->arg, NULL, 10); + ospf->lsa_minarrival = minarrival; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf6_timers_lsa, @@ -432,22 +409,21 @@ DEFUN (no_ospf6_timers_lsa, "Minimum delay in receiving new version of a LSA\n" "Delay in milliseconds\n") { - VTY_DECLVAR_CONTEXT(ospf6, ospf); - int idx_number = 4; - unsigned int minarrival; + VTY_DECLVAR_CONTEXT(ospf6, ospf); + int idx_number = 4; + unsigned int minarrival; - if (argc == 5) - { - minarrival = strtoul(argv[idx_number]->arg, NULL, 10); + if (argc == 5) { + minarrival = strtoul(argv[idx_number]->arg, NULL, 10); - if (ospf->lsa_minarrival != minarrival || - minarrival == OSPF_MIN_LS_ARRIVAL) - return CMD_SUCCESS; - } + if (ospf->lsa_minarrival != minarrival + || minarrival == OSPF_MIN_LS_ARRIVAL) + return CMD_SUCCESS; + } - ospf->lsa_minarrival = OSPF_MIN_LS_ARRIVAL; + ospf->lsa_minarrival = OSPF_MIN_LS_ARRIVAL; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -457,11 +433,11 @@ DEFUN (ospf6_distance, "Administrative distance\n" "OSPF6 Administrative distance\n") { - VTY_DECLVAR_CONTEXT(ospf6, o); + VTY_DECLVAR_CONTEXT(ospf6, o); - o->distance_all = atoi (argv[1]->arg); + o->distance_all = atoi(argv[1]->arg); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf6_distance, @@ -471,11 +447,11 @@ DEFUN (no_ospf6_distance, "Administrative distance\n" "OSPF6 Administrative distance\n") { - VTY_DECLVAR_CONTEXT(ospf6, o); + VTY_DECLVAR_CONTEXT(ospf6, o); - o->distance_all = 0; + o->distance_all = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ospf6_distance_ospf6, @@ -490,19 +466,19 @@ DEFUN (ospf6_distance_ospf6, "External routes\n" "Distance for external routes\n") { - VTY_DECLVAR_CONTEXT(ospf6, o); - int idx = 0; + VTY_DECLVAR_CONTEXT(ospf6, o); + int idx = 0; + + if (argv_find(argv, argc, "intra-area", &idx)) + o->distance_intra = atoi(argv[idx + 1]->arg); + idx = 0; + if (argv_find(argv, argc, "inter-area", &idx)) + o->distance_inter = atoi(argv[idx + 1]->arg); + idx = 0; + if (argv_find(argv, argc, "external", &idx)) + o->distance_external = atoi(argv[idx + 1]->arg); - if (argv_find (argv, argc, "intra-area", &idx)) - o->distance_intra = atoi(argv[idx + 1]->arg); - idx = 0; - if (argv_find (argv, argc, "inter-area", &idx)) - o->distance_inter = atoi(argv[idx + 1]->arg); - idx = 0; - if (argv_find (argv, argc, "external", &idx)) - o->distance_external = atoi(argv[idx + 1]->arg); - - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf6_distance_ospf6, @@ -518,17 +494,17 @@ DEFUN (no_ospf6_distance_ospf6, "External routes\n" "Distance for external routes\n") { - VTY_DECLVAR_CONTEXT(ospf6, o); - int idx = 0; + VTY_DECLVAR_CONTEXT(ospf6, o); + int idx = 0; - if (argv_find (argv, argc, "intra-area", &idx) || argc == 3) - idx = o->distance_intra = 0; - if (argv_find (argv, argc, "inter-area", &idx) || argc == 3) - idx = o->distance_inter = 0; - if (argv_find (argv, argc, "external", &idx) || argc == 3) - o->distance_external = 0; + if (argv_find(argv, argc, "intra-area", &idx) || argc == 3) + idx = o->distance_intra = 0; + if (argv_find(argv, argc, "inter-area", &idx) || argc == 3) + idx = o->distance_inter = 0; + if (argv_find(argv, argc, "external", &idx) || argc == 3) + o->distance_external = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } #if 0 @@ -573,56 +549,54 @@ DEFUN (ospf6_interface_area, "OSPF6 area ID in IPv4 address notation\n" ) { - VTY_DECLVAR_CONTEXT(ospf6, o); - int idx_ifname = 1; - int idx_ipv4 = 3; - struct ospf6_area *oa; - struct ospf6_interface *oi; - struct interface *ifp; - u_int32_t area_id; - - /* find/create ospf6 interface */ - ifp = if_get_by_name (argv[idx_ifname]->arg, VRF_DEFAULT); - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - oi = ospf6_interface_create (ifp); - if (oi->area) - { - vty_out (vty, "%s already attached to Area %s\n", - oi->interface->name, oi->area->name); - return CMD_SUCCESS; - } - - /* parse Area-ID */ - if (inet_pton (AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) - { - vty_out (vty, "Invalid Area-ID: %s\n", argv[idx_ipv4]->arg); - return CMD_SUCCESS; - } - - /* find/create ospf6 area */ - oa = ospf6_area_lookup (area_id, o); - if (oa == NULL) - oa = ospf6_area_create (area_id, o, OSPF6_AREA_FMT_DOTTEDQUAD); - - /* attach interface to area */ - listnode_add (oa->if_list, oi); /* sort ?? */ - oi->area = oa; - - SET_FLAG (oa->flag, OSPF6_AREA_ENABLE); - - /* ospf6 process is currently disabled, not much more to do */ - if (CHECK_FLAG (o->flag, OSPF6_DISABLED)) - return CMD_SUCCESS; - - /* start up */ - ospf6_interface_enable (oi); - - /* If the router is ABR, originate summary routes */ - if (ospf6_is_router_abr (o)) - ospf6_abr_enable_area (oa); + VTY_DECLVAR_CONTEXT(ospf6, o); + int idx_ifname = 1; + int idx_ipv4 = 3; + struct ospf6_area *oa; + struct ospf6_interface *oi; + struct interface *ifp; + u_int32_t area_id; + + /* find/create ospf6 interface */ + ifp = if_get_by_name(argv[idx_ifname]->arg, VRF_DEFAULT); + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) + oi = ospf6_interface_create(ifp); + if (oi->area) { + vty_out(vty, "%s already attached to Area %s\n", + oi->interface->name, oi->area->name); + return CMD_SUCCESS; + } - return CMD_SUCCESS; + /* parse Area-ID */ + if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) { + vty_out(vty, "Invalid Area-ID: %s\n", argv[idx_ipv4]->arg); + return CMD_SUCCESS; + } + + /* find/create ospf6 area */ + oa = ospf6_area_lookup(area_id, o); + if (oa == NULL) + oa = ospf6_area_create(area_id, o, OSPF6_AREA_FMT_DOTTEDQUAD); + + /* attach interface to area */ + listnode_add(oa->if_list, oi); /* sort ?? */ + oi->area = oa; + + SET_FLAG(oa->flag, OSPF6_AREA_ENABLE); + + /* ospf6 process is currently disabled, not much more to do */ + if (CHECK_FLAG(o->flag, OSPF6_DISABLED)) + return CMD_SUCCESS; + + /* start up */ + ospf6_interface_enable(oi); + + /* If the router is ABR, originate summary routes */ + if (ospf6_is_router_abr(o)) + ospf6_abr_enable_area(oa); + + return CMD_SUCCESS; } DEFUN (no_ospf6_interface_area, @@ -635,62 +609,56 @@ DEFUN (no_ospf6_interface_area, "OSPF6 area ID in IPv4 address notation\n" ) { - int idx_ifname = 2; - int idx_ipv4 = 4; - struct ospf6_interface *oi; - struct ospf6_area *oa; - struct interface *ifp; - u_int32_t area_id; - - ifp = if_lookup_by_name (argv[idx_ifname]->arg, VRF_DEFAULT); - if (ifp == NULL) - { - vty_out (vty, "No such interface %s\n", argv[idx_ifname]->arg); - return CMD_SUCCESS; - } - - oi = (struct ospf6_interface *) ifp->info; - if (oi == NULL) - { - vty_out (vty, "Interface %s not enabled\n", ifp->name); - return CMD_SUCCESS; - } - - /* parse Area-ID */ - if (inet_pton (AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) - { - vty_out (vty, "Invalid Area-ID: %s\n", argv[idx_ipv4]->arg); - return CMD_SUCCESS; - } - - /* Verify Area */ - if (oi->area == NULL) - { - vty_out (vty, "No such Area-ID: %s\n", argv[idx_ipv4]->arg); - return CMD_SUCCESS; - } - - if (oi->area->area_id != area_id) - { - vty_out (vty, "Wrong Area-ID: %s is attached to area %s\n", - oi->interface->name, oi->area->name); - return CMD_SUCCESS; - } - - thread_execute (master, interface_down, oi, 0); - - oa = oi->area; - listnode_delete (oi->area->if_list, oi); - oi->area = (struct ospf6_area *) NULL; - - /* Withdraw inter-area routes from this area, if necessary */ - if (oa->if_list->count == 0) - { - UNSET_FLAG (oa->flag, OSPF6_AREA_ENABLE); - ospf6_abr_disable_area (oa); - } + int idx_ifname = 2; + int idx_ipv4 = 4; + struct ospf6_interface *oi; + struct ospf6_area *oa; + struct interface *ifp; + u_int32_t area_id; + + ifp = if_lookup_by_name(argv[idx_ifname]->arg, VRF_DEFAULT); + if (ifp == NULL) { + vty_out(vty, "No such interface %s\n", argv[idx_ifname]->arg); + return CMD_SUCCESS; + } - return CMD_SUCCESS; + oi = (struct ospf6_interface *)ifp->info; + if (oi == NULL) { + vty_out(vty, "Interface %s not enabled\n", ifp->name); + return CMD_SUCCESS; + } + + /* parse Area-ID */ + if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) { + vty_out(vty, "Invalid Area-ID: %s\n", argv[idx_ipv4]->arg); + return CMD_SUCCESS; + } + + /* Verify Area */ + if (oi->area == NULL) { + vty_out(vty, "No such Area-ID: %s\n", argv[idx_ipv4]->arg); + return CMD_SUCCESS; + } + + if (oi->area->area_id != area_id) { + vty_out(vty, "Wrong Area-ID: %s is attached to area %s\n", + oi->interface->name, oi->area->name); + return CMD_SUCCESS; + } + + thread_execute(master, interface_down, oi, 0); + + oa = oi->area; + listnode_delete(oi->area->if_list, oi); + oi->area = (struct ospf6_area *)NULL; + + /* Withdraw inter-area routes from this area, if necessary */ + if (oa->if_list->count == 0) { + UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE); + ospf6_abr_disable_area(oa); + } + + return CMD_SUCCESS; } DEFUN (ospf6_stub_router_admin, @@ -699,21 +667,19 @@ DEFUN (ospf6_stub_router_admin, "Make router a stub router\n" "Administratively applied, for an indefinite period\n") { - struct listnode *node; - struct ospf6_area *oa; - - if (!CHECK_FLAG (ospf6->flag, OSPF6_STUB_ROUTER)) - { - for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa)) - { - OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_V6); - OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_R); - OSPF6_ROUTER_LSA_SCHEDULE (oa); + struct listnode *node; + struct ospf6_area *oa; + + if (!CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER)) { + for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) { + OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_V6); + OSPF6_OPT_CLEAR(oa->options, OSPF6_OPT_R); + OSPF6_ROUTER_LSA_SCHEDULE(oa); + } + SET_FLAG(ospf6->flag, OSPF6_STUB_ROUTER); } - SET_FLAG (ospf6->flag, OSPF6_STUB_ROUTER); - } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf6_stub_router_admin, @@ -723,21 +689,19 @@ DEFUN (no_ospf6_stub_router_admin, "Make router a stub router\n" "Administratively applied, for an indefinite period\n") { - struct listnode *node; - struct ospf6_area *oa; - - if (CHECK_FLAG (ospf6->flag, OSPF6_STUB_ROUTER)) - { - for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa)) - { - OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6); - OSPF6_OPT_SET (oa->options, OSPF6_OPT_R); - OSPF6_ROUTER_LSA_SCHEDULE (oa); + struct listnode *node; + struct ospf6_area *oa; + + if (CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER)) { + for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) { + OSPF6_OPT_SET(oa->options, OSPF6_OPT_V6); + OSPF6_OPT_SET(oa->options, OSPF6_OPT_R); + OSPF6_ROUTER_LSA_SCHEDULE(oa); + } + UNSET_FLAG(ospf6->flag, OSPF6_STUB_ROUTER); } - UNSET_FLAG (ospf6->flag, OSPF6_STUB_ROUTER); - } - return CMD_SUCCESS; + return CMD_SUCCESS; } #if 0 @@ -788,81 +752,75 @@ DEFUN (no_ospf6_stub_router_shutdown, } #endif -static void -ospf6_show (struct vty *vty, struct ospf6 *o) +static void ospf6_show(struct vty *vty, struct ospf6 *o) { - struct listnode *n; - struct ospf6_area *oa; - char router_id[16], duration[32]; - struct timeval now, running, result; - char buf[32], rbuf[32]; - - /* process id, router id */ - inet_ntop (AF_INET, &o->router_id, router_id, sizeof (router_id)); - vty_out (vty, " OSPFv3 Routing Process (0) with Router-ID %s\n", - router_id); - - /* running time */ - monotime(&now); - timersub (&now, &o->starttime, &running); - timerstring (&running, duration, sizeof (duration)); - vty_out (vty, " Running %s\n", duration); - - /* Redistribute configuration */ - /* XXX */ - - vty_out (vty, " LSA minimum arrival %d msecs\n",o->lsa_minarrival); - - /* Show SPF parameters */ - vty_out(vty, " Initial SPF scheduling delay %d millisec(s)\n" - " Minimum hold time between consecutive SPFs %d millsecond(s)\n" - " Maximum hold time between consecutive SPFs %d millsecond(s)\n" - " Hold time multiplier is currently %d\n", - o->spf_delay, - o->spf_holdtime, - o->spf_max_holdtime, - o->spf_hold_multiplier); - - vty_out(vty, " SPF algorithm "); - if (o->ts_spf.tv_sec || o->ts_spf.tv_usec) - { - timersub(&now, &o->ts_spf, &result); - timerstring(&result, buf, sizeof(buf)); - ospf6_spf_reason_string(o->last_spf_reason, rbuf, sizeof(rbuf)); - vty_out(vty, "last executed %s ago, reason %s\n", buf, rbuf); - vty_out (vty, " Last SPF duration %lld sec %lld usec\n", - (long long)o->ts_spf_duration.tv_sec, - (long long)o->ts_spf_duration.tv_usec); - } - else - vty_out(vty, "has not been run$\n"); - threadtimer_string(now, o->t_spf_calc, buf, sizeof(buf)); - vty_out (vty, " SPF timer %s%s\n", - (o->t_spf_calc ? "due in " : "is "), buf); - - if (CHECK_FLAG (o->flag, OSPF6_STUB_ROUTER)) - vty_out (vty, " Router Is Stub Router\n"); - - /* LSAs */ - vty_out (vty, " Number of AS scoped LSAs is %u\n", - o->lsdb->count); - - /* Areas */ - vty_out (vty, " Number of areas in this router is %u\n", - listcount (o->area_list)); - - if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) - { - if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_DETAIL)) - vty_out (vty, " All adjacency changes are logged\n"); - else - vty_out (vty, " Adjacency changes are logged\n"); - } - - vty_out (vty, "\n"); - - for (ALL_LIST_ELEMENTS_RO (o->area_list, n, oa)) - ospf6_area_show (vty, oa); + struct listnode *n; + struct ospf6_area *oa; + char router_id[16], duration[32]; + struct timeval now, running, result; + char buf[32], rbuf[32]; + + /* process id, router id */ + inet_ntop(AF_INET, &o->router_id, router_id, sizeof(router_id)); + vty_out(vty, " OSPFv3 Routing Process (0) with Router-ID %s\n", + router_id); + + /* running time */ + monotime(&now); + timersub(&now, &o->starttime, &running); + timerstring(&running, duration, sizeof(duration)); + vty_out(vty, " Running %s\n", duration); + + /* Redistribute configuration */ + /* XXX */ + + vty_out(vty, " LSA minimum arrival %d msecs\n", o->lsa_minarrival); + + /* Show SPF parameters */ + vty_out(vty, + " Initial SPF scheduling delay %d millisec(s)\n" + " Minimum hold time between consecutive SPFs %d millsecond(s)\n" + " Maximum hold time between consecutive SPFs %d millsecond(s)\n" + " Hold time multiplier is currently %d\n", + o->spf_delay, o->spf_holdtime, o->spf_max_holdtime, + o->spf_hold_multiplier); + + vty_out(vty, " SPF algorithm "); + if (o->ts_spf.tv_sec || o->ts_spf.tv_usec) { + timersub(&now, &o->ts_spf, &result); + timerstring(&result, buf, sizeof(buf)); + ospf6_spf_reason_string(o->last_spf_reason, rbuf, sizeof(rbuf)); + vty_out(vty, "last executed %s ago, reason %s\n", buf, rbuf); + vty_out(vty, " Last SPF duration %lld sec %lld usec\n", + (long long)o->ts_spf_duration.tv_sec, + (long long)o->ts_spf_duration.tv_usec); + } else + vty_out(vty, "has not been run$\n"); + threadtimer_string(now, o->t_spf_calc, buf, sizeof(buf)); + vty_out(vty, " SPF timer %s%s\n", (o->t_spf_calc ? "due in " : "is "), + buf); + + if (CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER)) + vty_out(vty, " Router Is Stub Router\n"); + + /* LSAs */ + vty_out(vty, " Number of AS scoped LSAs is %u\n", o->lsdb->count); + + /* Areas */ + vty_out(vty, " Number of areas in this router is %u\n", + listcount(o->area_list)); + + if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) { + if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_DETAIL)) + vty_out(vty, " All adjacency changes are logged\n"); + else + vty_out(vty, " Adjacency changes are logged\n"); + } + + vty_out(vty, "\n"); + + for (ALL_LIST_ELEMENTS_RO(o->area_list, n, oa)) + ospf6_area_show(vty, oa); } /* show top level structures */ @@ -873,10 +831,10 @@ DEFUN (show_ipv6_ospf6, IP6_STR OSPF6_STR) { - OSPF6_CMD_CHECK_RUNNING (); + OSPF6_CMD_CHECK_RUNNING(); - ospf6_show (vty, ospf6); - return CMD_SUCCESS; + ospf6_show(vty, ospf6); + return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_route, @@ -895,10 +853,10 @@ DEFUN (show_ipv6_ospf6_route, "Detailed information\n" "Summary of route table\n") { - OSPF6_CMD_CHECK_RUNNING (); + OSPF6_CMD_CHECK_RUNNING(); - ospf6_route_table_show (vty, 4, argc, argv, ospf6->route_table); - return CMD_SUCCESS; + ospf6_route_table_show(vty, 4, argc, argv, ospf6->route_table); + return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_route_match, @@ -912,10 +870,10 @@ DEFUN (show_ipv6_ospf6_route_match, "Display routes which match the specified route\n" "Display routes longer than the specified route\n") { - OSPF6_CMD_CHECK_RUNNING (); + OSPF6_CMD_CHECK_RUNNING(); - ospf6_route_table_show (vty, 4, argc, argv, ospf6->route_table); - return CMD_SUCCESS; + ospf6_route_table_show(vty, 4, argc, argv, ospf6->route_table); + return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_route_match_detail, @@ -930,14 +888,13 @@ DEFUN (show_ipv6_ospf6_route_match_detail, "Detailed information\n" ) { - OSPF6_CMD_CHECK_RUNNING (); + OSPF6_CMD_CHECK_RUNNING(); - ospf6_route_table_show (vty, 4, argc, argv, ospf6->route_table); - return CMD_SUCCESS; + ospf6_route_table_show(vty, 4, argc, argv, ospf6->route_table); + return CMD_SUCCESS; } - DEFUN (show_ipv6_ospf6_route_type_detail, show_ipv6_ospf6_route_type_detail_cmd, "show ipv6 ospf6 route detail", @@ -952,153 +909,143 @@ DEFUN (show_ipv6_ospf6_route_type_detail, "Detailed information\n" ) { - OSPF6_CMD_CHECK_RUNNING (); + OSPF6_CMD_CHECK_RUNNING(); - ospf6_route_table_show (vty, 4, argc, argv, ospf6->route_table); - return CMD_SUCCESS; + ospf6_route_table_show(vty, 4, argc, argv, ospf6->route_table); + return CMD_SUCCESS; } -static void -ospf6_stub_router_config_write (struct vty *vty) +static void ospf6_stub_router_config_write(struct vty *vty) { - if (CHECK_FLAG (ospf6->flag, OSPF6_STUB_ROUTER)) - { - vty_out (vty, " stub-router administrative\n"); - } - return; + if (CHECK_FLAG(ospf6->flag, OSPF6_STUB_ROUTER)) { + vty_out(vty, " stub-router administrative\n"); + } + return; } -static int -ospf6_distance_config_write (struct vty *vty) +static int ospf6_distance_config_write(struct vty *vty) { - struct route_node *rn; - struct ospf6_distance *odistance; - - if (ospf6->distance_all) - vty_out (vty, " distance %u\n", ospf6->distance_all); - - if (ospf6->distance_intra - || ospf6->distance_inter - || ospf6->distance_external) - { - vty_out (vty, " distance ospf6"); - - if (ospf6->distance_intra) - vty_out (vty, " intra-area %u", ospf6->distance_intra); - if (ospf6->distance_inter) - vty_out (vty, " inter-area %u", ospf6->distance_inter); - if (ospf6->distance_external) - vty_out (vty, " external %u", ospf6->distance_external); - - vty_out (vty, "\n"); - } - - for (rn = route_top (ospf6->distance_table); rn; rn = route_next (rn)) - if ((odistance = rn->info) != NULL) - { - char buf[PREFIX_STRLEN]; - - vty_out (vty, " distance %u %s %s\n", odistance->distance, - prefix2str (&rn->p, buf, sizeof (buf)), - odistance->access_list ? odistance->access_list : ""); - } - return 0; + struct route_node *rn; + struct ospf6_distance *odistance; + + if (ospf6->distance_all) + vty_out(vty, " distance %u\n", ospf6->distance_all); + + if (ospf6->distance_intra || ospf6->distance_inter + || ospf6->distance_external) { + vty_out(vty, " distance ospf6"); + + if (ospf6->distance_intra) + vty_out(vty, " intra-area %u", ospf6->distance_intra); + if (ospf6->distance_inter) + vty_out(vty, " inter-area %u", ospf6->distance_inter); + if (ospf6->distance_external) + vty_out(vty, " external %u", ospf6->distance_external); + + vty_out(vty, "\n"); + } + + for (rn = route_top(ospf6->distance_table); rn; rn = route_next(rn)) + if ((odistance = rn->info) != NULL) { + char buf[PREFIX_STRLEN]; + + vty_out(vty, " distance %u %s %s\n", + odistance->distance, + prefix2str(&rn->p, buf, sizeof(buf)), + odistance->access_list ? odistance->access_list + : ""); + } + return 0; } /* OSPF configuration write function. */ -static int -config_write_ospf6 (struct vty *vty) +static int config_write_ospf6(struct vty *vty) { - char router_id[16]; - struct listnode *j, *k; - struct ospf6_area *oa; - struct ospf6_interface *oi; - - /* OSPFv3 configuration. */ - if (ospf6 == NULL) - return CMD_SUCCESS; - - inet_ntop (AF_INET, &ospf6->router_id_static, router_id, sizeof (router_id)); - vty_out (vty, "router ospf6\n"); - if (ospf6->router_id_static != 0) - vty_out (vty, " router-id %s\n", router_id); - - /* log-adjacency-changes flag print. */ - if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) - { - if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL)) - vty_out (vty, " log-adjacency-changes detail\n"); - else if (!DFLT_OSPF6_LOG_ADJACENCY_CHANGES) - vty_out (vty, " log-adjacency-changes\n"); - } - else if (DFLT_OSPF6_LOG_ADJACENCY_CHANGES) - { - vty_out (vty, " no log-adjacency-changes\n"); - } - - if (ospf6->ref_bandwidth != OSPF6_REFERENCE_BANDWIDTH) - vty_out (vty, " auto-cost reference-bandwidth %d\n", ospf6->ref_bandwidth); - - /* LSA timers print. */ - if (ospf6->lsa_minarrival != OSPF_MIN_LS_ARRIVAL) - vty_out (vty, " timers lsa min-arrival %d\n",ospf6->lsa_minarrival); - - ospf6_stub_router_config_write (vty); - ospf6_redistribute_config_write (vty); - ospf6_area_config_write (vty); - ospf6_spf_config_write (vty); - ospf6_distance_config_write (vty); - - for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, j, oa)) - { - for (ALL_LIST_ELEMENTS_RO (oa->if_list, k, oi)) - vty_out (vty, " interface %s area %s\n", - oi->interface->name, oa->name); - } - vty_out (vty, "!\n"); - return 0; + char router_id[16]; + struct listnode *j, *k; + struct ospf6_area *oa; + struct ospf6_interface *oi; + + /* OSPFv3 configuration. */ + if (ospf6 == NULL) + return CMD_SUCCESS; + + inet_ntop(AF_INET, &ospf6->router_id_static, router_id, + sizeof(router_id)); + vty_out(vty, "router ospf6\n"); + if (ospf6->router_id_static != 0) + vty_out(vty, " router-id %s\n", router_id); + + /* log-adjacency-changes flag print. */ + if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES)) { + if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL)) + vty_out(vty, " log-adjacency-changes detail\n"); + else if (!DFLT_OSPF6_LOG_ADJACENCY_CHANGES) + vty_out(vty, " log-adjacency-changes\n"); + } else if (DFLT_OSPF6_LOG_ADJACENCY_CHANGES) { + vty_out(vty, " no log-adjacency-changes\n"); + } + + if (ospf6->ref_bandwidth != OSPF6_REFERENCE_BANDWIDTH) + vty_out(vty, " auto-cost reference-bandwidth %d\n", + ospf6->ref_bandwidth); + + /* LSA timers print. */ + if (ospf6->lsa_minarrival != OSPF_MIN_LS_ARRIVAL) + vty_out(vty, " timers lsa min-arrival %d\n", + ospf6->lsa_minarrival); + + ospf6_stub_router_config_write(vty); + ospf6_redistribute_config_write(vty); + ospf6_area_config_write(vty); + ospf6_spf_config_write(vty); + ospf6_distance_config_write(vty); + + for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, j, oa)) { + for (ALL_LIST_ELEMENTS_RO(oa->if_list, k, oi)) + vty_out(vty, " interface %s area %s\n", + oi->interface->name, oa->name); + } + vty_out(vty, "!\n"); + return 0; } /* OSPF6 node structure. */ -static struct cmd_node ospf6_node = -{ - OSPF6_NODE, - "%s(config-ospf6)# ", - 1 /* VTYSH */ +static struct cmd_node ospf6_node = { + OSPF6_NODE, "%s(config-ospf6)# ", 1 /* VTYSH */ }; /* Install ospf related commands. */ -void -ospf6_top_init (void) +void ospf6_top_init(void) { - /* Install ospf6 top node. */ - install_node (&ospf6_node, config_write_ospf6); - - install_element (VIEW_NODE, &show_ipv6_ospf6_cmd); - install_element (CONFIG_NODE, &router_ospf6_cmd); - install_element (CONFIG_NODE, &no_router_ospf6_cmd); - - install_element (VIEW_NODE, &show_ipv6_ospf6_route_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_route_match_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_route_match_detail_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_route_type_detail_cmd); - - install_default (OSPF6_NODE); - install_element (OSPF6_NODE, &ospf6_router_id_cmd); - install_element (OSPF6_NODE, &ospf6_log_adjacency_changes_cmd); - install_element (OSPF6_NODE, &ospf6_log_adjacency_changes_detail_cmd); - install_element (OSPF6_NODE, &no_ospf6_log_adjacency_changes_cmd); - install_element (OSPF6_NODE, &no_ospf6_log_adjacency_changes_detail_cmd); - - /* LSA timers commands */ - install_element (OSPF6_NODE, &ospf6_timers_lsa_cmd); - install_element (OSPF6_NODE, &no_ospf6_timers_lsa_cmd); - - install_element (OSPF6_NODE, &ospf6_interface_area_cmd); - install_element (OSPF6_NODE, &no_ospf6_interface_area_cmd); - install_element (OSPF6_NODE, &ospf6_stub_router_admin_cmd); - install_element (OSPF6_NODE, &no_ospf6_stub_router_admin_cmd); - /* For a later time */ + /* Install ospf6 top node. */ + install_node(&ospf6_node, config_write_ospf6); + + install_element(VIEW_NODE, &show_ipv6_ospf6_cmd); + install_element(CONFIG_NODE, &router_ospf6_cmd); + install_element(CONFIG_NODE, &no_router_ospf6_cmd); + + install_element(VIEW_NODE, &show_ipv6_ospf6_route_cmd); + install_element(VIEW_NODE, &show_ipv6_ospf6_route_match_cmd); + install_element(VIEW_NODE, &show_ipv6_ospf6_route_match_detail_cmd); + install_element(VIEW_NODE, &show_ipv6_ospf6_route_type_detail_cmd); + + install_default(OSPF6_NODE); + install_element(OSPF6_NODE, &ospf6_router_id_cmd); + install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_cmd); + install_element(OSPF6_NODE, &ospf6_log_adjacency_changes_detail_cmd); + install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_cmd); + install_element(OSPF6_NODE, &no_ospf6_log_adjacency_changes_detail_cmd); + + /* LSA timers commands */ + install_element(OSPF6_NODE, &ospf6_timers_lsa_cmd); + install_element(OSPF6_NODE, &no_ospf6_timers_lsa_cmd); + + install_element(OSPF6_NODE, &ospf6_interface_area_cmd); + install_element(OSPF6_NODE, &no_ospf6_interface_area_cmd); + install_element(OSPF6_NODE, &ospf6_stub_router_admin_cmd); + install_element(OSPF6_NODE, &no_ospf6_stub_router_admin_cmd); +/* For a later time */ #if 0 install_element (OSPF6_NODE, &ospf6_stub_router_startup_cmd); install_element (OSPF6_NODE, &no_ospf6_stub_router_startup_cmd); @@ -1106,10 +1053,10 @@ ospf6_top_init (void) install_element (OSPF6_NODE, &no_ospf6_stub_router_shutdown_cmd); #endif - install_element (OSPF6_NODE, &ospf6_distance_cmd); - install_element (OSPF6_NODE, &no_ospf6_distance_cmd); - install_element (OSPF6_NODE, &ospf6_distance_ospf6_cmd); - install_element (OSPF6_NODE, &no_ospf6_distance_ospf6_cmd); + install_element(OSPF6_NODE, &ospf6_distance_cmd); + install_element(OSPF6_NODE, &no_ospf6_distance_cmd); + install_element(OSPF6_NODE, &ospf6_distance_ospf6_cmd); + install_element(OSPF6_NODE, &no_ospf6_distance_ospf6_cmd); #if 0 install_element (OSPF6_NODE, &ospf6_distance_source_cmd); install_element (OSPF6_NODE, &no_ospf6_distance_source_cmd); diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h index 5e101520d..d8d34d0f3 100644 --- a/ospf6d/ospf6_top.h +++ b/ospf6d/ospf6_top.h @@ -25,76 +25,75 @@ #include "routemap.h" /* OSPFv3 top level data structure */ -struct ospf6 -{ - /* my router id */ - u_int32_t router_id; +struct ospf6 { + /* my router id */ + u_int32_t router_id; - /* static router id */ - u_int32_t router_id_static; + /* static router id */ + u_int32_t router_id_static; - /* start time */ - struct timeval starttime; + /* start time */ + struct timeval starttime; - /* list of areas */ - struct list *area_list; - struct ospf6_area *backbone; + /* list of areas */ + struct list *area_list; + struct ospf6_area *backbone; - /* AS scope link state database */ - struct ospf6_lsdb *lsdb; - struct ospf6_lsdb *lsdb_self; + /* AS scope link state database */ + struct ospf6_lsdb *lsdb; + struct ospf6_lsdb *lsdb_self; - struct ospf6_route_table *route_table; - struct ospf6_route_table *brouter_table; + struct ospf6_route_table *route_table; + struct ospf6_route_table *brouter_table; - struct ospf6_route_table *external_table; - struct route_table *external_id_table; - u_int32_t external_id; + struct ospf6_route_table *external_table; + struct route_table *external_id_table; + u_int32_t external_id; - /* redistribute route-map */ - struct - { - char *name; - struct route_map *map; - } rmap[ZEBRA_ROUTE_MAX]; + /* redistribute route-map */ + struct { + char *name; + struct route_map *map; + } rmap[ZEBRA_ROUTE_MAX]; - u_char flag; + u_char flag; - /* Configured flags */ - u_char config_flags; + /* Configured flags */ + u_char config_flags; #define OSPF6_LOG_ADJACENCY_CHANGES (1 << 0) #define OSPF6_LOG_ADJACENCY_DETAIL (1 << 1) - /* LSA timer parameters */ - unsigned int lsa_minarrival; /* LSA minimum arrival in milliseconds. */ + /* LSA timer parameters */ + unsigned int lsa_minarrival; /* LSA minimum arrival in milliseconds. */ - /* SPF parameters */ - unsigned int spf_delay; /* SPF delay time. */ - unsigned int spf_holdtime; /* SPF hold time. */ - unsigned int spf_max_holdtime; /* SPF maximum-holdtime */ - unsigned int spf_hold_multiplier; /* Adaptive multiplier for hold time */ - unsigned int spf_reason; /* reason bits while scheduling SPF */ + /* SPF parameters */ + unsigned int spf_delay; /* SPF delay time. */ + unsigned int spf_holdtime; /* SPF hold time. */ + unsigned int spf_max_holdtime; /* SPF maximum-holdtime */ + unsigned int + spf_hold_multiplier; /* Adaptive multiplier for hold time */ + unsigned int spf_reason; /* reason bits while scheduling SPF */ - struct timeval ts_spf; /* SPF calculation time stamp. */ - struct timeval ts_spf_duration; /* Execution time of last SPF */ - unsigned int last_spf_reason; /* Last SPF reason */ + struct timeval ts_spf; /* SPF calculation time stamp. */ + struct timeval ts_spf_duration; /* Execution time of last SPF */ + unsigned int last_spf_reason; /* Last SPF reason */ - /* Threads */ - struct thread *t_spf_calc; /* SPF calculation timer. */ - struct thread *t_ase_calc; /* ASE calculation timer. */ - struct thread *maxage_remover; + /* Threads */ + struct thread *t_spf_calc; /* SPF calculation timer. */ + struct thread *t_ase_calc; /* ASE calculation timer. */ + struct thread *maxage_remover; - u_int32_t ref_bandwidth; + u_int32_t ref_bandwidth; - /* Distance parameters */ - u_char distance_all; - u_char distance_intra; - u_char distance_inter; - u_char distance_external; + /* Distance parameters */ + u_char distance_all; + u_char distance_intra; + u_char distance_inter; + u_char distance_external; - struct route_table *distance_table; + struct route_table *distance_table; - QOBJ_FIELDS + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(ospf6) @@ -105,11 +104,9 @@ DECLARE_QOBJ_TYPE(ospf6) extern struct ospf6 *ospf6; /* prototypes */ -extern void ospf6_top_init (void); -extern void ospf6_delete (struct ospf6 *o); +extern void ospf6_top_init(void); +extern void ospf6_delete(struct ospf6 *o); -extern void ospf6_maxage_remove (struct ospf6 *o); +extern void ospf6_maxage_remove(struct ospf6 *o); #endif /* OSPF6_TOP_H */ - - diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index ddd2f3f1b..d33f41730 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -39,7 +39,7 @@ #include "ospf6_zebra.h" #include "ospf6d.h" -DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_DISTANCE, "OSPF6 distance") +DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_DISTANCE, "OSPF6 distance") unsigned char conf_debug_ospf6_zebra = 0; @@ -49,79 +49,75 @@ struct zclient *zclient = NULL; struct in_addr router_id_zebra; /* Router-id update message from zebra. */ -static int -ospf6_router_id_update_zebra (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int ospf6_router_id_update_zebra(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct prefix router_id; - struct ospf6 *o = ospf6; + struct prefix router_id; + struct ospf6 *o = ospf6; - zebra_router_id_update_read(zclient->ibuf,&router_id); - router_id_zebra = router_id.u.prefix4; + zebra_router_id_update_read(zclient->ibuf, &router_id); + router_id_zebra = router_id.u.prefix4; - if (o == NULL) - return 0; + if (o == NULL) + return 0; - if (o->router_id == 0) - o->router_id = (u_int32_t) router_id_zebra.s_addr; + if (o->router_id == 0) + o->router_id = (u_int32_t)router_id_zebra.s_addr; - return 0; + return 0; } /* redistribute function */ -void -ospf6_zebra_redistribute (int type) +void ospf6_zebra_redistribute(int type) { - if (vrf_bitmap_check (zclient->redist[AFI_IP6][type], VRF_DEFAULT)) - return; - vrf_bitmap_set (zclient->redist[AFI_IP6][type], VRF_DEFAULT); + if (vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT)) + return; + vrf_bitmap_set(zclient->redist[AFI_IP6][type], VRF_DEFAULT); - if (zclient->sock > 0) - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0, - VRF_DEFAULT); + if (zclient->sock > 0) + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, + AFI_IP6, type, 0, VRF_DEFAULT); } -void -ospf6_zebra_no_redistribute (int type) +void ospf6_zebra_no_redistribute(int type) { - if (!vrf_bitmap_check (zclient->redist[AFI_IP6][type], VRF_DEFAULT)) - return; - vrf_bitmap_unset (zclient->redist[AFI_IP6][type], VRF_DEFAULT); - if (zclient->sock > 0) - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP6, type, - 0, VRF_DEFAULT); + if (!vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT)) + return; + vrf_bitmap_unset(zclient->redist[AFI_IP6][type], VRF_DEFAULT); + if (zclient->sock > 0) + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, + AFI_IP6, type, 0, VRF_DEFAULT); } /* Inteface addition message from zebra. */ -static int -ospf6_zebra_if_add (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int ospf6_zebra_if_add(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - - ifp = zebra_interface_add_read (zclient->ibuf, vrf_id); - if (IS_OSPF6_DEBUG_ZEBRA (RECV)) - zlog_debug ("Zebra Interface add: %s index %d mtu %d", - ifp->name, ifp->ifindex, ifp->mtu6); - ospf6_interface_if_add (ifp); - return 0; + struct interface *ifp; + + ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); + if (IS_OSPF6_DEBUG_ZEBRA(RECV)) + zlog_debug("Zebra Interface add: %s index %d mtu %d", ifp->name, + ifp->ifindex, ifp->mtu6); + ospf6_interface_if_add(ifp); + return 0; } -static int -ospf6_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int ospf6_zebra_if_del(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; + struct interface *ifp; - if (!(ifp = zebra_interface_state_read (zclient->ibuf, vrf_id))) - return 0; + if (!(ifp = zebra_interface_state_read(zclient->ibuf, vrf_id))) + return 0; - if (if_is_up (ifp)) - zlog_warn ("Zebra: got delete of %s, but interface is still up", ifp->name); + if (if_is_up(ifp)) + zlog_warn("Zebra: got delete of %s, but interface is still up", + ifp->name); - if (IS_OSPF6_DEBUG_ZEBRA (RECV)) - zlog_debug ("Zebra Interface delete: %s index %d mtu %d", - ifp->name, ifp->ifindex, ifp->mtu6); + if (IS_OSPF6_DEBUG_ZEBRA(RECV)) + zlog_debug("Zebra Interface delete: %s index %d mtu %d", + ifp->name, ifp->ifindex, ifp->mtu6); #if 0 /* XXX: ospf6_interface_if_del is not the right way to handle this, @@ -130,178 +126,180 @@ ospf6_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length, ospf6_interface_if_del (ifp); #endif /*0*/ - ifp->ifindex = IFINDEX_DELETED; - return 0; + ifp->ifindex = IFINDEX_DELETED; + return 0; } -static int -ospf6_zebra_if_state_update (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int ospf6_zebra_if_state_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - - ifp = zebra_interface_state_read (zclient->ibuf, vrf_id); - if (ifp == NULL) - return 0; - - if (IS_OSPF6_DEBUG_ZEBRA (RECV)) - zlog_debug ("Zebra Interface state change: " - "%s index %d flags %llx metric %d mtu %d bandwidth %d", - ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, - ifp->metric, ifp->mtu6, ifp->bandwidth); - - ospf6_interface_state_update (ifp); - return 0; + struct interface *ifp; + + ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); + if (ifp == NULL) + return 0; + + if (IS_OSPF6_DEBUG_ZEBRA(RECV)) + zlog_debug( + "Zebra Interface state change: " + "%s index %d flags %llx metric %d mtu %d bandwidth %d", + ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, + ifp->metric, ifp->mtu6, ifp->bandwidth); + + ospf6_interface_state_update(ifp); + return 0; } -static int -ospf6_zebra_if_address_update_add (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int ospf6_zebra_if_address_update_add(int command, + struct zclient *zclient, + zebra_size_t length, + vrf_id_t vrf_id) { - struct connected *c; - char buf[128]; - - c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD, zclient->ibuf, - vrf_id); - if (c == NULL) - return 0; - - if (IS_OSPF6_DEBUG_ZEBRA (RECV)) - zlog_debug ("Zebra Interface address add: %s %5s %s/%d", - c->ifp->name, prefix_family_str (c->address), - inet_ntop (c->address->family, &c->address->u.prefix, - buf, sizeof (buf)), c->address->prefixlen); - - if (c->address->family == AF_INET6) - { - ospf6_interface_state_update (c->ifp); - ospf6_interface_connected_route_update (c->ifp); - } - return 0; + struct connected *c; + char buf[128]; + + c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, + zclient->ibuf, vrf_id); + if (c == NULL) + return 0; + + if (IS_OSPF6_DEBUG_ZEBRA(RECV)) + zlog_debug("Zebra Interface address add: %s %5s %s/%d", + c->ifp->name, prefix_family_str(c->address), + inet_ntop(c->address->family, &c->address->u.prefix, + buf, sizeof(buf)), + c->address->prefixlen); + + if (c->address->family == AF_INET6) { + ospf6_interface_state_update(c->ifp); + ospf6_interface_connected_route_update(c->ifp); + } + return 0; } -static int -ospf6_zebra_if_address_update_delete (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int ospf6_zebra_if_address_update_delete(int command, + struct zclient *zclient, + zebra_size_t length, + vrf_id_t vrf_id) { - struct connected *c; - char buf[128]; + struct connected *c; + char buf[128]; + + c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, + zclient->ibuf, vrf_id); + if (c == NULL) + return 0; + + if (IS_OSPF6_DEBUG_ZEBRA(RECV)) + zlog_debug("Zebra Interface address delete: %s %5s %s/%d", + c->ifp->name, prefix_family_str(c->address), + inet_ntop(c->address->family, &c->address->u.prefix, + buf, sizeof(buf)), + c->address->prefixlen); + + if (c->address->family == AF_INET6) { + ospf6_interface_connected_route_update(c->ifp); + ospf6_interface_state_update(c->ifp); + } - c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE, zclient->ibuf, - vrf_id); - if (c == NULL) - return 0; + connected_free(c); - if (IS_OSPF6_DEBUG_ZEBRA (RECV)) - zlog_debug ("Zebra Interface address delete: %s %5s %s/%d", - c->ifp->name, prefix_family_str (c->address), - inet_ntop (c->address->family, &c->address->u.prefix, - buf, sizeof (buf)), c->address->prefixlen); + return 0; +} - if (c->address->family == AF_INET6) - { - ospf6_interface_connected_route_update (c->ifp); - ospf6_interface_state_update (c->ifp); - } +static int ospf6_zebra_read_ipv6(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) +{ + struct stream *s; + struct zapi_ipv6 api; + unsigned long ifindex; + struct prefix p, src_p; + struct in6_addr *nexthop; + + if (ospf6 == NULL) + return 0; + + s = zclient->ibuf; + ifindex = 0; + nexthop = NULL; + memset(&api, 0, sizeof(api)); + + /* Type, flags, message. */ + api.type = stream_getc(s); + api.instance = stream_getw(s); + api.flags = stream_getl(s); + api.message = stream_getc(s); + + /* IPv6 prefix. */ + memset(&p, 0, sizeof(struct prefix)); + p.family = AF_INET6; + p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s)); + stream_get(&p.u.prefix6, s, PSIZE(p.prefixlen)); + + memset(&src_p, 0, sizeof(struct prefix)); + src_p.family = AF_INET6; + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { + src_p.prefixlen = stream_getc(s); + stream_get(&src_p.u.prefix6, s, PSIZE(src_p.prefixlen)); + } + + if (src_p.prefixlen) + /* we completely ignore srcdest routes for now. */ + return 0; + + /* Nexthop, ifindex, distance, metric. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { + api.nexthop_num = stream_getc(s); + nexthop = (struct in6_addr *)malloc(api.nexthop_num + * sizeof(struct in6_addr)); + stream_get(nexthop, s, + api.nexthop_num * sizeof(struct in6_addr)); + } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { + api.ifindex_num = stream_getc(s); + ifindex = stream_getl(s); + } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) + api.distance = stream_getc(s); + else + api.distance = 0; + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) + api.metric = stream_getl(s); + else + api.metric = 0; + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getl(s); + else + api.tag = 0; + + if (IS_OSPF6_DEBUG_ZEBRA(RECV)) { + char prefixstr[PREFIX2STR_BUFFER], nexthopstr[128]; + prefix2str((struct prefix *)&p, prefixstr, sizeof(prefixstr)); + if (nexthop) + inet_ntop(AF_INET6, nexthop, nexthopstr, + sizeof(nexthopstr)); + else + snprintf(nexthopstr, sizeof(nexthopstr), "::"); + + zlog_debug( + "Zebra Receive route %s: %s %s nexthop %s ifindex %ld tag %" ROUTE_TAG_PRI, + (command == ZEBRA_REDISTRIBUTE_IPV6_ADD ? "add" + : "delete"), + zebra_route_string(api.type), prefixstr, nexthopstr, + ifindex, api.tag); + } - connected_free (c); + if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) + ospf6_asbr_redistribute_add(api.type, ifindex, &p, + api.nexthop_num, nexthop, api.tag); + else + ospf6_asbr_redistribute_remove(api.type, ifindex, &p); - return 0; -} + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) + free(nexthop); -static int -ospf6_zebra_read_ipv6 (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) -{ - struct stream *s; - struct zapi_ipv6 api; - unsigned long ifindex; - struct prefix p, src_p; - struct in6_addr *nexthop; - - if (ospf6 == NULL) - return 0; - - s = zclient->ibuf; - ifindex = 0; - nexthop = NULL; - memset (&api, 0, sizeof (api)); - - /* Type, flags, message. */ - api.type = stream_getc (s); - api.instance = stream_getw (s); - api.flags = stream_getl (s); - api.message = stream_getc (s); - - /* IPv6 prefix. */ - memset (&p, 0, sizeof (struct prefix)); - p.family = AF_INET6; - p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc (s)); - stream_get (&p.u.prefix6, s, PSIZE (p.prefixlen)); - - memset (&src_p, 0, sizeof (struct prefix)); - src_p.family = AF_INET6; - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_SRCPFX)) - { - src_p.prefixlen = stream_getc (s); - stream_get (&src_p.u.prefix6, s, PSIZE (src_p.prefixlen)); - } - - if (src_p.prefixlen) - /* we completely ignore srcdest routes for now. */ - return 0; - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) - { - api.nexthop_num = stream_getc (s); - nexthop = (struct in6_addr *) - malloc (api.nexthop_num * sizeof (struct in6_addr)); - stream_get (nexthop, s, api.nexthop_num * sizeof (struct in6_addr)); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) - { - api.ifindex_num = stream_getc (s); - ifindex = stream_getl (s); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc (s); - else - api.distance = 0; - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl (s); - else - api.metric = 0; - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl (s); - else - api.tag = 0; - - if (IS_OSPF6_DEBUG_ZEBRA (RECV)) - { - char prefixstr[PREFIX2STR_BUFFER], nexthopstr[128]; - prefix2str ((struct prefix *)&p, prefixstr, sizeof (prefixstr)); - if (nexthop) - inet_ntop (AF_INET6, nexthop, nexthopstr, sizeof (nexthopstr)); - else - snprintf (nexthopstr, sizeof (nexthopstr), "::"); - - zlog_debug ("Zebra Receive route %s: %s %s nexthop %s ifindex %ld tag %"ROUTE_TAG_PRI, - (command == ZEBRA_REDISTRIBUTE_IPV6_ADD ? "add" : "delete"), - zebra_route_string(api.type), prefixstr, nexthopstr, ifindex, api.tag); - } - - if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) - ospf6_asbr_redistribute_add (api.type, ifindex, &p, - api.nexthop_num, nexthop, api.tag); - else - ospf6_asbr_redistribute_remove (api.type, ifindex, &p); - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) - free (nexthop); - - return 0; + return 0; } DEFUN (show_zebra, @@ -312,292 +310,270 @@ DEFUN (show_zebra, OSPF6_STR "Zebra information\n") { - int i; - if (zclient == NULL) - { - vty_out (vty, "Not connected to zebra\n"); - return CMD_SUCCESS; - } - - vty_out (vty, "Zebra Infomation\n"); - vty_out (vty, " enable: %d fail: %d\n", - zclient->enable, zclient->fail); - vty_out (vty, " redistribute default: %d\n", - vrf_bitmap_check (zclient->default_information, VRF_DEFAULT)); - vty_out (vty, " redistribute:"); - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - if (vrf_bitmap_check (zclient->redist[AFI_IP6][i], VRF_DEFAULT)) - vty_out (vty, " %s", zebra_route_string(i)); - } - vty_out (vty, "\n"); - return CMD_SUCCESS; + int i; + if (zclient == NULL) { + vty_out(vty, "Not connected to zebra\n"); + return CMD_SUCCESS; + } + + vty_out(vty, "Zebra Infomation\n"); + vty_out(vty, " enable: %d fail: %d\n", zclient->enable, zclient->fail); + vty_out(vty, " redistribute default: %d\n", + vrf_bitmap_check(zclient->default_information, VRF_DEFAULT)); + vty_out(vty, " redistribute:"); + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (vrf_bitmap_check(zclient->redist[AFI_IP6][i], VRF_DEFAULT)) + vty_out(vty, " %s", zebra_route_string(i)); + } + vty_out(vty, "\n"); + return CMD_SUCCESS; } /* Zebra configuration write function. */ -static int -config_write_ospf6_zebra (struct vty *vty) +static int config_write_ospf6_zebra(struct vty *vty) { - if (! zclient->enable) - { - vty_out (vty, "no router zebra\n"); - vty_out (vty, "!\n"); - } - else if (! vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT)) - { - vty_out (vty, "router zebra\n"); - vty_out (vty, " no redistribute ospf6\n"); - vty_out (vty, "!\n"); - } - return 0; + if (!zclient->enable) { + vty_out(vty, "no router zebra\n"); + vty_out(vty, "!\n"); + } else if (!vrf_bitmap_check( + zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], + VRF_DEFAULT)) { + vty_out(vty, "router zebra\n"); + vty_out(vty, " no redistribute ospf6\n"); + vty_out(vty, "!\n"); + } + return 0; } /* Zebra node structure. */ -static struct cmd_node zebra_node = -{ - ZEBRA_NODE, - "%s(config-zebra)# ", +static struct cmd_node zebra_node = { + ZEBRA_NODE, "%s(config-zebra)# ", }; #define ADD 0 #define REM 1 -static void -ospf6_zebra_route_update (int type, struct ospf6_route *request) +static void ospf6_zebra_route_update(int type, struct ospf6_route *request) { - struct zapi_ipv6 api; - char buf[PREFIX2STR_BUFFER]; - int nhcount; - struct in6_addr **nexthops; - ifindex_t *ifindexes; - int ret = 0; - struct prefix_ipv6 *dest; - - if (IS_OSPF6_DEBUG_ZEBRA (SEND)) - { - prefix2str (&request->prefix, buf, sizeof (buf)); - zlog_debug ("Send %s route: %s", - (type == REM ? "remove" : "add"), buf); - } - - if (zclient->sock < 0) - { - if (IS_OSPF6_DEBUG_ZEBRA (SEND)) - zlog_debug (" Not connected to Zebra"); - return; - } - - if (request->path.origin.adv_router == ospf6->router_id && - (request->path.type == OSPF6_PATH_TYPE_EXTERNAL1 || - request->path.type == OSPF6_PATH_TYPE_EXTERNAL2)) - { - if (IS_OSPF6_DEBUG_ZEBRA (SEND)) - zlog_debug (" Ignore self-originated external route"); - return; - } - - /* If removing is the best path and if there's another path, - treat this request as add the secondary path */ - if (type == REM && ospf6_route_is_best (request) && - request->next && ospf6_route_is_same (request, request->next)) - { - if (IS_OSPF6_DEBUG_ZEBRA (SEND)) - zlog_debug (" Best-path removal resulted Sencondary addition"); - type = ADD; - request = request->next; - } - - /* Only the best path will be sent to zebra. */ - if (! ospf6_route_is_best (request)) - { - /* this is not preferred best route, ignore */ - if (IS_OSPF6_DEBUG_ZEBRA (SEND)) - zlog_debug (" Ignore non-best route"); - return; - } - - nhcount = ospf6_route_num_nexthops (request); - if (nhcount == 0) - { - if (IS_OSPF6_DEBUG_ZEBRA (SEND)) - zlog_debug (" No nexthop, ignore"); - return; - } - - /* allocate memory for nexthop_list */ - nexthops = XCALLOC (MTYPE_OSPF6_OTHER, - nhcount * sizeof (struct in6_addr *)); - if (nexthops == NULL) - { - zlog_warn ("Can't send route to zebra: malloc failed"); - return; - } - - /* allocate memory for ifindex_list */ - ifindexes = XCALLOC (MTYPE_OSPF6_OTHER, - nhcount * sizeof (ifindex_t)); - if (ifindexes == NULL) - { - zlog_warn ("Can't send route to zebra: malloc failed"); - XFREE (MTYPE_OSPF6_OTHER, nexthops); - return; - } - - ospf6_route_zebra_copy_nexthops (request, ifindexes, nexthops, nhcount); - - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_OSPF6; - api.instance = 0; - api.flags = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = nhcount; - api.nexthop = nexthops; - SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); - api.ifindex_num = nhcount; - api.ifindex = ifindexes; - SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); - api.metric = (request->path.metric_type == 2 ? - request->path.u.cost_e2 : request->path.cost); - if (request->path.tag) - { - SET_FLAG (api.message, ZAPI_MESSAGE_TAG); - api.tag = request->path.tag; - } - - dest = (struct prefix_ipv6 *) &request->prefix; - - SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = ospf6_distance_apply (dest, request); - - if (type == REM) - ret = zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, dest, NULL, &api); - else - ret = zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, dest, NULL, &api); - - if (ret < 0) - zlog_err ("zapi_ipv6_route() %s failed: %s", - (type == REM ? "delete" : "add"), safe_strerror (errno)); - - XFREE (MTYPE_OSPF6_OTHER, nexthops); - XFREE (MTYPE_OSPF6_OTHER, ifindexes); - - return; + struct zapi_ipv6 api; + char buf[PREFIX2STR_BUFFER]; + int nhcount; + struct in6_addr **nexthops; + ifindex_t *ifindexes; + int ret = 0; + struct prefix_ipv6 *dest; + + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) { + prefix2str(&request->prefix, buf, sizeof(buf)); + zlog_debug("Send %s route: %s", + (type == REM ? "remove" : "add"), buf); + } + + if (zclient->sock < 0) { + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + zlog_debug(" Not connected to Zebra"); + return; + } + + if (request->path.origin.adv_router == ospf6->router_id + && (request->path.type == OSPF6_PATH_TYPE_EXTERNAL1 + || request->path.type == OSPF6_PATH_TYPE_EXTERNAL2)) { + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + zlog_debug(" Ignore self-originated external route"); + return; + } + + /* If removing is the best path and if there's another path, + treat this request as add the secondary path */ + if (type == REM && ospf6_route_is_best(request) && request->next + && ospf6_route_is_same(request, request->next)) { + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + zlog_debug( + " Best-path removal resulted Sencondary addition"); + type = ADD; + request = request->next; + } + + /* Only the best path will be sent to zebra. */ + if (!ospf6_route_is_best(request)) { + /* this is not preferred best route, ignore */ + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + zlog_debug(" Ignore non-best route"); + return; + } + + nhcount = ospf6_route_num_nexthops(request); + if (nhcount == 0) { + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + zlog_debug(" No nexthop, ignore"); + return; + } + + /* allocate memory for nexthop_list */ + nexthops = + XCALLOC(MTYPE_OSPF6_OTHER, nhcount * sizeof(struct in6_addr *)); + if (nexthops == NULL) { + zlog_warn("Can't send route to zebra: malloc failed"); + return; + } + + /* allocate memory for ifindex_list */ + ifindexes = XCALLOC(MTYPE_OSPF6_OTHER, nhcount * sizeof(ifindex_t)); + if (ifindexes == NULL) { + zlog_warn("Can't send route to zebra: malloc failed"); + XFREE(MTYPE_OSPF6_OTHER, nexthops); + return; + } + + ospf6_route_zebra_copy_nexthops(request, ifindexes, nexthops, nhcount); + + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_OSPF6; + api.instance = 0; + api.flags = 0; + api.message = 0; + api.safi = SAFI_UNICAST; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = nhcount; + api.nexthop = nexthops; + SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); + api.ifindex_num = nhcount; + api.ifindex = ifindexes; + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = (request->path.metric_type == 2 ? request->path.u.cost_e2 + : request->path.cost); + if (request->path.tag) { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = request->path.tag; + } + + dest = (struct prefix_ipv6 *)&request->prefix; + + SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = ospf6_distance_apply(dest, request); + + if (type == REM) + ret = zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, dest, + NULL, &api); + else + ret = zapi_ipv6_route(ZEBRA_IPV6_ROUTE_ADD, zclient, dest, NULL, + &api); + + if (ret < 0) + zlog_err("zapi_ipv6_route() %s failed: %s", + (type == REM ? "delete" : "add"), + safe_strerror(errno)); + + XFREE(MTYPE_OSPF6_OTHER, nexthops); + XFREE(MTYPE_OSPF6_OTHER, ifindexes); + + return; } -void -ospf6_zebra_route_update_add (struct ospf6_route *request) +void ospf6_zebra_route_update_add(struct ospf6_route *request) { - if (! vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT)) - { - ospf6->route_table->hook_add = NULL; - ospf6->route_table->hook_remove = NULL; - return; - } - ospf6_zebra_route_update (ADD, request); + if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], + VRF_DEFAULT)) { + ospf6->route_table->hook_add = NULL; + ospf6->route_table->hook_remove = NULL; + return; + } + ospf6_zebra_route_update(ADD, request); } -void -ospf6_zebra_route_update_remove (struct ospf6_route *request) +void ospf6_zebra_route_update_remove(struct ospf6_route *request) { - if (! vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT)) - { - ospf6->route_table->hook_add = NULL; - ospf6->route_table->hook_remove = NULL; - return; - } - ospf6_zebra_route_update (REM, request); + if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], + VRF_DEFAULT)) { + ospf6->route_table->hook_add = NULL; + ospf6->route_table->hook_remove = NULL; + return; + } + ospf6_zebra_route_update(REM, request); } -void -ospf6_zebra_add_discard (struct ospf6_route *request) +void ospf6_zebra_add_discard(struct ospf6_route *request) { - struct zapi_ipv6 api; - char buf[INET6_ADDRSTRLEN]; - struct prefix_ipv6 *dest; - - if (vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], - VRF_DEFAULT)) - { - if (!CHECK_FLAG (request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) - { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_OSPF6; - api.flags = ZEBRA_FLAG_BLACKHOLE; - api.instance = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.ifindex_num = 0; - - dest = (struct prefix_ipv6 *) &request->prefix; - - zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, dest, NULL, &api); - - if (IS_OSPF6_DEBUG_ZEBRA (SEND)) - zlog_debug ("Zebra: Route add discard %s/%d", - inet_ntop (AF_INET6, &dest->prefix, - buf, INET6_ADDRSTRLEN), - dest->prefixlen); - SET_FLAG (request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED); + struct zapi_ipv6 api; + char buf[INET6_ADDRSTRLEN]; + struct prefix_ipv6 *dest; + + if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], + VRF_DEFAULT)) { + if (!CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_OSPF6; + api.flags = ZEBRA_FLAG_BLACKHOLE; + api.instance = 0; + api.message = 0; + api.safi = SAFI_UNICAST; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = 0; + api.ifindex_num = 0; + + dest = (struct prefix_ipv6 *)&request->prefix; + + zapi_ipv6_route(ZEBRA_IPV6_ROUTE_ADD, zclient, dest, + NULL, &api); + + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + zlog_debug("Zebra: Route add discard %s/%d", + inet_ntop(AF_INET6, &dest->prefix, + buf, INET6_ADDRSTRLEN), + dest->prefixlen); + SET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED); + } else { + dest = (struct prefix_ipv6 *)&request->prefix; + + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + zlog_debug( + "Zebra: Blackhole route present already %s/%d", + inet_ntop(AF_INET6, &dest->prefix, buf, + INET6_ADDRSTRLEN), + dest->prefixlen); + } } - else - { - dest = (struct prefix_ipv6 *) &request->prefix; - - if (IS_OSPF6_DEBUG_ZEBRA (SEND)) - zlog_debug ("Zebra: Blackhole route present already %s/%d", - inet_ntop (AF_INET6, &dest->prefix, - buf, INET6_ADDRSTRLEN), - dest->prefixlen); - } - } } -void -ospf6_zebra_delete_discard (struct ospf6_route *request) +void ospf6_zebra_delete_discard(struct ospf6_route *request) { - struct zapi_ipv6 api; - char buf[INET6_ADDRSTRLEN]; - struct prefix_ipv6 *dest; - - if (vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], VRF_DEFAULT)) - { - if (CHECK_FLAG (request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) - { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_OSPF6; - api.flags = ZEBRA_FLAG_BLACKHOLE; - api.instance = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.ifindex_num = 0; - - dest = (struct prefix_ipv6 *) &request->prefix; - - zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, dest, NULL, &api); - - if (IS_OSPF6_DEBUG_ZEBRA (SEND)) - zlog_debug ("Zebra: Route delete discard %s/%d", - inet_ntop (AF_INET6, &dest->prefix, buf, - INET6_ADDRSTRLEN), dest->prefixlen); - UNSET_FLAG (request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED); - } - else - { - dest = (struct prefix_ipv6 *) &request->prefix; - if (IS_OSPF6_DEBUG_ZEBRA (SEND)) - zlog_debug ("Zebra: Blackhole route already deleted %s/%d", - inet_ntop (AF_INET6, &dest->prefix, buf, - INET6_ADDRSTRLEN), dest->prefixlen); + struct zapi_ipv6 api; + char buf[INET6_ADDRSTRLEN]; + struct prefix_ipv6 *dest; + + if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], + VRF_DEFAULT)) { + if (CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) { + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_OSPF6; + api.flags = ZEBRA_FLAG_BLACKHOLE; + api.instance = 0; + api.message = 0; + api.safi = SAFI_UNICAST; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = 0; + api.ifindex_num = 0; + + dest = (struct prefix_ipv6 *)&request->prefix; + + zapi_ipv6_route(ZEBRA_IPV6_ROUTE_DELETE, zclient, dest, + NULL, &api); + + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + zlog_debug("Zebra: Route delete discard %s/%d", + inet_ntop(AF_INET6, &dest->prefix, + buf, INET6_ADDRSTRLEN), + dest->prefixlen); + UNSET_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED); + } else { + dest = (struct prefix_ipv6 *)&request->prefix; + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + zlog_debug( + "Zebra: Blackhole route already deleted %s/%d", + inet_ntop(AF_INET6, &dest->prefix, buf, + INET6_ADDRSTRLEN), + dest->prefixlen); + } } - } } DEFUN (redistribute_ospf6, @@ -606,25 +582,27 @@ DEFUN (redistribute_ospf6, "Redistribute control\n" "OSPF6 route\n") { - struct ospf6_route *route; + struct ospf6_route *route; - if (vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], VRF_DEFAULT)) - return CMD_SUCCESS; + if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], + VRF_DEFAULT)) + return CMD_SUCCESS; - vrf_bitmap_set (zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], VRF_DEFAULT); + vrf_bitmap_set(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], + VRF_DEFAULT); - if (ospf6 == NULL) - return CMD_SUCCESS; + if (ospf6 == NULL) + return CMD_SUCCESS; - /* send ospf6 route to zebra route table */ - for (route = ospf6_route_head (ospf6->route_table); route; - route = ospf6_route_next (route)) - ospf6_zebra_route_update_add (route); + /* send ospf6 route to zebra route table */ + for (route = ospf6_route_head(ospf6->route_table); route; + route = ospf6_route_next(route)) + ospf6_zebra_route_update_add(route); - ospf6->route_table->hook_add = ospf6_zebra_route_update_add; - ospf6->route_table->hook_remove = ospf6_zebra_route_update_remove; + ospf6->route_table->hook_add = ospf6_zebra_route_update_add; + ospf6->route_table->hook_remove = ospf6_zebra_route_update_remove; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_redistribute_ospf6, @@ -634,212 +612,197 @@ DEFUN (no_redistribute_ospf6, "Redistribute control\n" "OSPF6 route\n") { - struct ospf6_route *route; + struct ospf6_route *route; - if (! vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], VRF_DEFAULT)) - return CMD_SUCCESS; + if (!vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], + VRF_DEFAULT)) + return CMD_SUCCESS; - vrf_bitmap_unset (zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], VRF_DEFAULT); + vrf_bitmap_unset(zclient->redist[AFI_IP6][ZEBRA_ROUTE_OSPF6], + VRF_DEFAULT); - if (ospf6 == NULL) - return CMD_SUCCESS; + if (ospf6 == NULL) + return CMD_SUCCESS; - ospf6->route_table->hook_add = NULL; - ospf6->route_table->hook_remove = NULL; + ospf6->route_table->hook_add = NULL; + ospf6->route_table->hook_remove = NULL; - /* withdraw ospf6 route from zebra route table */ - for (route = ospf6_route_head (ospf6->route_table); route; - route = ospf6_route_next (route)) - ospf6_zebra_route_update_remove (route); + /* withdraw ospf6 route from zebra route table */ + for (route = ospf6_route_head(ospf6->route_table); route; + route = ospf6_route_next(route)) + ospf6_zebra_route_update_remove(route); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static struct ospf6_distance * -ospf6_distance_new (void) +static struct ospf6_distance *ospf6_distance_new(void) { - return XCALLOC (MTYPE_OSPF6_DISTANCE, sizeof (struct ospf6_distance)); + return XCALLOC(MTYPE_OSPF6_DISTANCE, sizeof(struct ospf6_distance)); } -static void -ospf6_distance_free (struct ospf6_distance *odistance) +static void ospf6_distance_free(struct ospf6_distance *odistance) { - XFREE (MTYPE_OSPF6_DISTANCE, odistance); + XFREE(MTYPE_OSPF6_DISTANCE, odistance); } -int -ospf6_distance_set (struct vty *vty, struct ospf6 *o, - const char *distance_str, - const char *ip_str, - const char *access_list_str) +int ospf6_distance_set(struct vty *vty, struct ospf6 *o, + const char *distance_str, const char *ip_str, + const char *access_list_str) { - int ret; - struct prefix_ipv6 p; - u_char distance; - struct route_node *rn; - struct ospf6_distance *odistance; - - ret = str2prefix_ipv6 (ip_str, &p); - if (ret == 0) - { - vty_out (vty, "Malformed prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - distance = atoi (distance_str); - - /* Get OSPF6 distance node. */ - rn = route_node_get (o->distance_table, (struct prefix *) &p); - if (rn->info) - { - odistance = rn->info; - route_unlock_node (rn); - } - else - { - odistance = ospf6_distance_new (); - rn->info = odistance; - } - - /* Set distance value. */ - odistance->distance = distance; - - /* Reset access-list configuration. */ - if (odistance->access_list) - { - free (odistance->access_list); - odistance->access_list = NULL; - } - if (access_list_str) - odistance->access_list = strdup (access_list_str); - - return CMD_SUCCESS; + int ret; + struct prefix_ipv6 p; + u_char distance; + struct route_node *rn; + struct ospf6_distance *odistance; + + ret = str2prefix_ipv6(ip_str, &p); + if (ret == 0) { + vty_out(vty, "Malformed prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + distance = atoi(distance_str); + + /* Get OSPF6 distance node. */ + rn = route_node_get(o->distance_table, (struct prefix *)&p); + if (rn->info) { + odistance = rn->info; + route_unlock_node(rn); + } else { + odistance = ospf6_distance_new(); + rn->info = odistance; + } + + /* Set distance value. */ + odistance->distance = distance; + + /* Reset access-list configuration. */ + if (odistance->access_list) { + free(odistance->access_list); + odistance->access_list = NULL; + } + if (access_list_str) + odistance->access_list = strdup(access_list_str); + + return CMD_SUCCESS; } -int -ospf6_distance_unset (struct vty *vty, struct ospf6 *o, - const char *distance_str, - const char *ip_str, - const char *access_list_str) +int ospf6_distance_unset(struct vty *vty, struct ospf6 *o, + const char *distance_str, const char *ip_str, + const char *access_list_str) { - int ret; - struct prefix_ipv6 p; - struct route_node *rn; - struct ospf6_distance *odistance; - - ret = str2prefix_ipv6 (ip_str, &p); - if (ret == 0) - { - vty_out (vty, "Malformed prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - rn = route_node_lookup (o->distance_table, (struct prefix *) &p); - if (!rn) - { - vty_out (vty, "Cant't find specified prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - odistance = rn->info; - - if (odistance->access_list) - free (odistance->access_list); - ospf6_distance_free (odistance); - - rn->info = NULL; - route_unlock_node (rn); - route_unlock_node (rn); - - return CMD_SUCCESS; + int ret; + struct prefix_ipv6 p; + struct route_node *rn; + struct ospf6_distance *odistance; + + ret = str2prefix_ipv6(ip_str, &p); + if (ret == 0) { + vty_out(vty, "Malformed prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + rn = route_node_lookup(o->distance_table, (struct prefix *)&p); + if (!rn) { + vty_out(vty, "Cant't find specified prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + odistance = rn->info; + + if (odistance->access_list) + free(odistance->access_list); + ospf6_distance_free(odistance); + + rn->info = NULL; + route_unlock_node(rn); + route_unlock_node(rn); + + return CMD_SUCCESS; } -void -ospf6_distance_reset (struct ospf6 *o) +void ospf6_distance_reset(struct ospf6 *o) { - struct route_node *rn; - struct ospf6_distance *odistance; - - for (rn = route_top (o->distance_table); rn; rn = route_next (rn)) - if ((odistance = rn->info) != NULL) - { - if (odistance->access_list) - free (odistance->access_list); - ospf6_distance_free (odistance); - rn->info = NULL; - route_unlock_node (rn); - } + struct route_node *rn; + struct ospf6_distance *odistance; + + for (rn = route_top(o->distance_table); rn; rn = route_next(rn)) + if ((odistance = rn->info) != NULL) { + if (odistance->access_list) + free(odistance->access_list); + ospf6_distance_free(odistance); + rn->info = NULL; + route_unlock_node(rn); + } } -u_char -ospf6_distance_apply (struct prefix_ipv6 *p, struct ospf6_route *or) +u_char ospf6_distance_apply(struct prefix_ipv6 *p, struct ospf6_route * or) { - struct ospf6 *o; + struct ospf6 *o; - o = ospf6; - if (o == NULL) - return 0; + o = ospf6; + if (o == NULL) + return 0; - if (o->distance_intra) - if (or->path.type == OSPF6_PATH_TYPE_INTRA) - return o->distance_intra; + if (o->distance_intra) + if (or->path.type == OSPF6_PATH_TYPE_INTRA) + return o->distance_intra; - if (o->distance_inter) - if (or->path.type == OSPF6_PATH_TYPE_INTER) - return o->distance_inter; + if (o->distance_inter) + if (or->path.type == OSPF6_PATH_TYPE_INTER) + return o->distance_inter; - if (o->distance_external) - if(or->path.type == OSPF6_PATH_TYPE_EXTERNAL1 - || or->path.type == OSPF6_PATH_TYPE_EXTERNAL2) - return o->distance_external; + if (o->distance_external) + if (or->path.type == OSPF6_PATH_TYPE_EXTERNAL1 || + or->path.type == OSPF6_PATH_TYPE_EXTERNAL2) + return o->distance_external; - if (o->distance_all) - return o->distance_all; + if (o->distance_all) + return o->distance_all; - return 0; + return 0; } -static void -ospf6_zebra_connected (struct zclient *zclient) +static void ospf6_zebra_connected(struct zclient *zclient) { - /* Send the client registration */ - bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); + /* Send the client registration */ + bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); - zclient_send_reg_requests (zclient, VRF_DEFAULT); + zclient_send_reg_requests(zclient, VRF_DEFAULT); } -void -ospf6_zebra_init (struct thread_master *master) +void ospf6_zebra_init(struct thread_master *master) { - /* Allocate zebra structure. */ - zclient = zclient_new(master); - zclient_init (zclient, ZEBRA_ROUTE_OSPF6, 0); - zclient->zebra_connected = ospf6_zebra_connected; - zclient->router_id_update = ospf6_router_id_update_zebra; - zclient->interface_add = ospf6_zebra_if_add; - zclient->interface_delete = ospf6_zebra_if_del; - zclient->interface_up = ospf6_zebra_if_state_update; - zclient->interface_down = ospf6_zebra_if_state_update; - zclient->interface_address_add = ospf6_zebra_if_address_update_add; - zclient->interface_address_delete = ospf6_zebra_if_address_update_delete; - zclient->redistribute_route_ipv4_add = NULL; - zclient->redistribute_route_ipv4_del = NULL; - zclient->redistribute_route_ipv6_add = ospf6_zebra_read_ipv6; - zclient->redistribute_route_ipv6_del = ospf6_zebra_read_ipv6; - - /* redistribute connected route by default */ - /* ospf6_zebra_redistribute (ZEBRA_ROUTE_CONNECT); */ - - /* Install zebra node. */ - install_node (&zebra_node, config_write_ospf6_zebra); - - /* Install command element for zebra node. */ - install_element (VIEW_NODE, &show_ospf6_zebra_cmd); - install_default (ZEBRA_NODE); - install_element (ZEBRA_NODE, &redistribute_ospf6_cmd); - install_element (ZEBRA_NODE, &no_redistribute_ospf6_cmd); - - return; + /* Allocate zebra structure. */ + zclient = zclient_new(master); + zclient_init(zclient, ZEBRA_ROUTE_OSPF6, 0); + zclient->zebra_connected = ospf6_zebra_connected; + zclient->router_id_update = ospf6_router_id_update_zebra; + zclient->interface_add = ospf6_zebra_if_add; + zclient->interface_delete = ospf6_zebra_if_del; + zclient->interface_up = ospf6_zebra_if_state_update; + zclient->interface_down = ospf6_zebra_if_state_update; + zclient->interface_address_add = ospf6_zebra_if_address_update_add; + zclient->interface_address_delete = + ospf6_zebra_if_address_update_delete; + zclient->redistribute_route_ipv4_add = NULL; + zclient->redistribute_route_ipv4_del = NULL; + zclient->redistribute_route_ipv6_add = ospf6_zebra_read_ipv6; + zclient->redistribute_route_ipv6_del = ospf6_zebra_read_ipv6; + + /* redistribute connected route by default */ + /* ospf6_zebra_redistribute (ZEBRA_ROUTE_CONNECT); */ + + /* Install zebra node. */ + install_node(&zebra_node, config_write_ospf6_zebra); + + /* Install command element for zebra node. */ + install_element(VIEW_NODE, &show_ospf6_zebra_cmd); + install_default(ZEBRA_NODE); + install_element(ZEBRA_NODE, &redistribute_ospf6_cmd); + install_element(ZEBRA_NODE, &no_redistribute_ospf6_cmd); + + return; } /* Debug */ @@ -854,21 +817,19 @@ DEFUN (debug_ospf6_zebra_sendrecv, "Debug Receiving zebra\n" ) { - int idx_send_recv = 3; - unsigned char level = 0; - - if (argc == 4) - { - if (strmatch(argv[idx_send_recv]->text, "send")) - level = OSPF6_DEBUG_ZEBRA_SEND; - else if (strmatch(argv[idx_send_recv]->text, "recv")) - level = OSPF6_DEBUG_ZEBRA_RECV; - } - else - level = OSPF6_DEBUG_ZEBRA_SEND | OSPF6_DEBUG_ZEBRA_RECV; - - OSPF6_DEBUG_ZEBRA_ON (level); - return CMD_SUCCESS; + int idx_send_recv = 3; + unsigned char level = 0; + + if (argc == 4) { + if (strmatch(argv[idx_send_recv]->text, "send")) + level = OSPF6_DEBUG_ZEBRA_SEND; + else if (strmatch(argv[idx_send_recv]->text, "recv")) + level = OSPF6_DEBUG_ZEBRA_RECV; + } else + level = OSPF6_DEBUG_ZEBRA_SEND | OSPF6_DEBUG_ZEBRA_RECV; + + OSPF6_DEBUG_ZEBRA_ON(level); + return CMD_SUCCESS; } DEFUN (no_debug_ospf6_zebra_sendrecv, @@ -882,46 +843,39 @@ DEFUN (no_debug_ospf6_zebra_sendrecv, "Debug Receiving zebra\n" ) { - int idx_send_recv = 4; - unsigned char level = 0; - - if (argc == 5) - { - if (strmatch(argv[idx_send_recv]->text, "send")) - level = OSPF6_DEBUG_ZEBRA_SEND; - else if (strmatch(argv[idx_send_recv]->text, "recv")) - level = OSPF6_DEBUG_ZEBRA_RECV; - } - else - level = OSPF6_DEBUG_ZEBRA_SEND | OSPF6_DEBUG_ZEBRA_RECV; - - OSPF6_DEBUG_ZEBRA_OFF (level); - return CMD_SUCCESS; + int idx_send_recv = 4; + unsigned char level = 0; + + if (argc == 5) { + if (strmatch(argv[idx_send_recv]->text, "send")) + level = OSPF6_DEBUG_ZEBRA_SEND; + else if (strmatch(argv[idx_send_recv]->text, "recv")) + level = OSPF6_DEBUG_ZEBRA_RECV; + } else + level = OSPF6_DEBUG_ZEBRA_SEND | OSPF6_DEBUG_ZEBRA_RECV; + + OSPF6_DEBUG_ZEBRA_OFF(level); + return CMD_SUCCESS; } -int -config_write_ospf6_debug_zebra (struct vty *vty) +int config_write_ospf6_debug_zebra(struct vty *vty) { - if (IS_OSPF6_DEBUG_ZEBRA (SEND) && IS_OSPF6_DEBUG_ZEBRA (RECV)) - vty_out (vty, "debug ospf6 zebra\n"); - else - { - if (IS_OSPF6_DEBUG_ZEBRA (SEND)) - vty_out (vty, "debug ospf6 zebra send\n"); - if (IS_OSPF6_DEBUG_ZEBRA (RECV)) - vty_out (vty, "debug ospf6 zebra recv\n"); - } - return 0; + if (IS_OSPF6_DEBUG_ZEBRA(SEND) && IS_OSPF6_DEBUG_ZEBRA(RECV)) + vty_out(vty, "debug ospf6 zebra\n"); + else { + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + vty_out(vty, "debug ospf6 zebra send\n"); + if (IS_OSPF6_DEBUG_ZEBRA(RECV)) + vty_out(vty, "debug ospf6 zebra recv\n"); + } + return 0; } -void -install_element_ospf6_debug_zebra (void) +void install_element_ospf6_debug_zebra(void) { - install_element (ENABLE_NODE, &debug_ospf6_zebra_sendrecv_cmd); - install_element (ENABLE_NODE, &no_debug_ospf6_zebra_sendrecv_cmd); - install_element (CONFIG_NODE, &debug_ospf6_zebra_sendrecv_cmd); - install_element (CONFIG_NODE, &no_debug_ospf6_zebra_sendrecv_cmd); + install_element(ENABLE_NODE, &debug_ospf6_zebra_sendrecv_cmd); + install_element(ENABLE_NODE, &no_debug_ospf6_zebra_sendrecv_cmd); + install_element(CONFIG_NODE, &debug_ospf6_zebra_sendrecv_cmd); + install_element(CONFIG_NODE, &no_debug_ospf6_zebra_sendrecv_cmd); } - - diff --git a/ospf6d/ospf6_zebra.h b/ospf6d/ospf6_zebra.h index f7f808c86..8ab999336 100644 --- a/ospf6d/ospf6_zebra.h +++ b/ospf6d/ospf6_zebra.h @@ -27,46 +27,42 @@ extern unsigned char conf_debug_ospf6_zebra; #define OSPF6_DEBUG_ZEBRA_SEND 0x01 #define OSPF6_DEBUG_ZEBRA_RECV 0x02 -#define OSPF6_DEBUG_ZEBRA_ON(level) \ - (conf_debug_ospf6_zebra |= level) -#define OSPF6_DEBUG_ZEBRA_OFF(level) \ - (conf_debug_ospf6_zebra &= ~(level)) -#define IS_OSPF6_DEBUG_ZEBRA(e) \ - (conf_debug_ospf6_zebra & OSPF6_DEBUG_ZEBRA_ ## e) +#define OSPF6_DEBUG_ZEBRA_ON(level) (conf_debug_ospf6_zebra |= level) +#define OSPF6_DEBUG_ZEBRA_OFF(level) (conf_debug_ospf6_zebra &= ~(level)) +#define IS_OSPF6_DEBUG_ZEBRA(e) (conf_debug_ospf6_zebra & OSPF6_DEBUG_ZEBRA_##e) /* OSPF6 distance */ -struct ospf6_distance -{ - /* Distance value for the IP source prefix */ - u_char distance; +struct ospf6_distance { + /* Distance value for the IP source prefix */ + u_char distance; - /* Name of the access-list to be matched */ - char *access_list; + /* Name of the access-list to be matched */ + char *access_list; }; extern struct zclient *zclient; -extern void ospf6_zebra_route_update_add (struct ospf6_route *request); -extern void ospf6_zebra_route_update_remove (struct ospf6_route *request); +extern void ospf6_zebra_route_update_add(struct ospf6_route *request); +extern void ospf6_zebra_route_update_remove(struct ospf6_route *request); -extern void ospf6_zebra_redistribute (int); -extern void ospf6_zebra_no_redistribute (int); -#define ospf6_zebra_is_redistribute(type) \ - vrf_bitmap_check (zclient->redist[AFI_IP6][type], VRF_DEFAULT) -extern void ospf6_zebra_init (struct thread_master *); -extern void ospf6_zebra_add_discard (struct ospf6_route *request); -extern void ospf6_zebra_delete_discard (struct ospf6_route *request); +extern void ospf6_zebra_redistribute(int); +extern void ospf6_zebra_no_redistribute(int); +#define ospf6_zebra_is_redistribute(type) \ + vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT) +extern void ospf6_zebra_init(struct thread_master *); +extern void ospf6_zebra_add_discard(struct ospf6_route *request); +extern void ospf6_zebra_delete_discard(struct ospf6_route *request); struct ospf6; -extern void ospf6_distance_reset (struct ospf6 *); -extern u_char ospf6_distance_apply (struct prefix_ipv6 *, struct ospf6_route *); +extern void ospf6_distance_reset(struct ospf6 *); +extern u_char ospf6_distance_apply(struct prefix_ipv6 *, struct ospf6_route *); -extern int ospf6_distance_set (struct vty *, struct ospf6 *, const char *, - const char *, const char *); -extern int ospf6_distance_unset (struct vty *, struct ospf6 *, const char *, - const char *, const char *); +extern int ospf6_distance_set(struct vty *, struct ospf6 *, const char *, + const char *, const char *); +extern int ospf6_distance_unset(struct vty *, struct ospf6 *, const char *, + const char *, const char *); -extern int config_write_ospf6_debug_zebra (struct vty *vty); -extern void install_element_ospf6_debug_zebra (void); +extern int config_write_ospf6_debug_zebra(struct vty *vty); +extern void install_element_ospf6_debug_zebra(void); #endif /*OSPF6_ZEBRA_H*/ diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c index c4a499031..6b47fca57 100644 --- a/ospf6d/ospf6d.c +++ b/ospf6d/ospf6d.c @@ -46,31 +46,28 @@ char ospf6_daemon_version[] = OSPF6_DAEMON_VERSION; -struct route_node * -route_prev (struct route_node *node) +struct route_node *route_prev(struct route_node *node) { - struct route_node *end; - struct route_node *prev = NULL; - - end = node; - node = node->parent; - if (node) - route_lock_node (node); - while (node) - { - prev = node; - node = route_next (node); - if (node == end) - { - route_unlock_node (node); - node = NULL; - } - } - route_unlock_node (end); - if (prev) - route_lock_node (prev); - - return prev; + struct route_node *end; + struct route_node *prev = NULL; + + end = node; + node = node->parent; + if (node) + route_lock_node(node); + while (node) { + prev = node; + node = route_next(node); + if (node == end) { + route_unlock_node(node); + node = NULL; + } + } + route_unlock_node(end); + if (prev) + route_lock_node(prev); + + return prev; } @@ -83,86 +80,76 @@ DEFUN (show_version_ospf6, "Display ospf6d version\n" ) { - vty_out (vty, "Zebra OSPF6d Version: %s\n", - ospf6_daemon_version); + vty_out(vty, "Zebra OSPF6d Version: %s\n", ospf6_daemon_version); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static struct cmd_node debug_node = -{ - DEBUG_NODE, - "", - 1 /* VTYSH */ +static struct cmd_node debug_node = { + DEBUG_NODE, "", 1 /* VTYSH */ }; -static int -config_write_ospf6_debug (struct vty *vty) +static int config_write_ospf6_debug(struct vty *vty) { - config_write_ospf6_debug_message (vty); - config_write_ospf6_debug_lsa (vty); - config_write_ospf6_debug_zebra (vty); - config_write_ospf6_debug_interface (vty); - config_write_ospf6_debug_neighbor (vty); - config_write_ospf6_debug_spf (vty); - config_write_ospf6_debug_route (vty); - config_write_ospf6_debug_brouter (vty); - config_write_ospf6_debug_asbr (vty); - config_write_ospf6_debug_abr (vty); - config_write_ospf6_debug_flood (vty); - vty_out (vty, "!\n"); - return 0; + config_write_ospf6_debug_message(vty); + config_write_ospf6_debug_lsa(vty); + config_write_ospf6_debug_zebra(vty); + config_write_ospf6_debug_interface(vty); + config_write_ospf6_debug_neighbor(vty); + config_write_ospf6_debug_spf(vty); + config_write_ospf6_debug_route(vty); + config_write_ospf6_debug_brouter(vty); + config_write_ospf6_debug_asbr(vty); + config_write_ospf6_debug_abr(vty); + config_write_ospf6_debug_flood(vty); + vty_out(vty, "!\n"); + return 0; } -#define AREA_LSDB_TITLE_FORMAT \ - "\n Area Scoped Link State Database (Area %s)\n\n" -#define IF_LSDB_TITLE_FORMAT \ - "\n I/F Scoped Link State Database (I/F %s in Area %s)\n\n" -#define AS_LSDB_TITLE_FORMAT \ - "\n AS Scoped Link State Database\n\n" +#define AREA_LSDB_TITLE_FORMAT \ + "\n Area Scoped Link State Database (Area %s)\n\n" +#define IF_LSDB_TITLE_FORMAT \ + "\n I/F Scoped Link State Database (I/F %s in Area %s)\n\n" +#define AS_LSDB_TITLE_FORMAT "\n AS Scoped Link State Database\n\n" -static int -parse_show_level (int idx_level, int argc, struct cmd_token **argv) +static int parse_show_level(int idx_level, int argc, struct cmd_token **argv) { - int level = OSPF6_LSDB_SHOW_LEVEL_NORMAL; - - if (argc > idx_level) - { - if (strmatch (argv[idx_level]->text, "detail")) - level = OSPF6_LSDB_SHOW_LEVEL_DETAIL; - else if (strmatch (argv[idx_level]->text, "dump")) - level = OSPF6_LSDB_SHOW_LEVEL_DUMP; - else if (strmatch (argv[idx_level]->text, "internal")) - level = OSPF6_LSDB_SHOW_LEVEL_INTERNAL; - } - - return level; + int level = OSPF6_LSDB_SHOW_LEVEL_NORMAL; + + if (argc > idx_level) { + if (strmatch(argv[idx_level]->text, "detail")) + level = OSPF6_LSDB_SHOW_LEVEL_DETAIL; + else if (strmatch(argv[idx_level]->text, "dump")) + level = OSPF6_LSDB_SHOW_LEVEL_DUMP; + else if (strmatch(argv[idx_level]->text, "internal")) + level = OSPF6_LSDB_SHOW_LEVEL_INTERNAL; + } + + return level; } -static u_int16_t -parse_type_spec (int idx_lsa, int argc, struct cmd_token **argv) +static u_int16_t parse_type_spec(int idx_lsa, int argc, struct cmd_token **argv) { - u_int16_t type = 0; - - if (argc > idx_lsa) - { - if (strmatch (argv[idx_lsa]->text, "router")) - type = htons (OSPF6_LSTYPE_ROUTER); - else if (strmatch (argv[idx_lsa]->text, "network")) - type = htons (OSPF6_LSTYPE_NETWORK); - else if (strmatch (argv[idx_lsa]->text, "as-external")) - type = htons (OSPF6_LSTYPE_AS_EXTERNAL); - else if (strmatch (argv[idx_lsa]->text, "intra-prefix")) - type = htons (OSPF6_LSTYPE_INTRA_PREFIX); - else if (strmatch (argv[idx_lsa]->text, "inter-router")) - type = htons (OSPF6_LSTYPE_INTER_ROUTER); - else if (strmatch (argv[idx_lsa]->text, "inter-prefix")) - type = htons (OSPF6_LSTYPE_INTER_PREFIX); - else if (strmatch (argv[idx_lsa]->text, "link")) - type = htons (OSPF6_LSTYPE_LINK); - } - - return type; + u_int16_t type = 0; + + if (argc > idx_lsa) { + if (strmatch(argv[idx_lsa]->text, "router")) + type = htons(OSPF6_LSTYPE_ROUTER); + else if (strmatch(argv[idx_lsa]->text, "network")) + type = htons(OSPF6_LSTYPE_NETWORK); + else if (strmatch(argv[idx_lsa]->text, "as-external")) + type = htons(OSPF6_LSTYPE_AS_EXTERNAL); + else if (strmatch(argv[idx_lsa]->text, "intra-prefix")) + type = htons(OSPF6_LSTYPE_INTRA_PREFIX); + else if (strmatch(argv[idx_lsa]->text, "inter-router")) + type = htons(OSPF6_LSTYPE_INTER_ROUTER); + else if (strmatch(argv[idx_lsa]->text, "inter-prefix")) + type = htons(OSPF6_LSTYPE_INTER_PREFIX); + else if (strmatch(argv[idx_lsa]->text, "link")) + type = htons(OSPF6_LSTYPE_LINK); + } + + return type; } DEFUN (show_ipv6_ospf6_database, @@ -176,38 +163,35 @@ DEFUN (show_ipv6_ospf6_database, "Dump LSAs\n" "Display LSA's internal information\n") { - int idx_level = 4; - int level; - struct listnode *i, *j; - struct ospf6 *o = ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; - - OSPF6_CMD_CHECK_RUNNING (); - - level = parse_show_level (idx_level, argc, argv); - - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - vty_out (vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show (vty, level, NULL, NULL, NULL, oa->lsdb); - } - - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - { - vty_out (vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show (vty, level, NULL, NULL, NULL, oi->lsdb); - } - } - - vty_out (vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show (vty, level, NULL, NULL, NULL, o->lsdb); - - vty_out (vty, "\n"); - return CMD_SUCCESS; + int idx_level = 4; + int level; + struct listnode *i, *j; + struct ospf6 *o = ospf6; + struct ospf6_area *oa; + struct ospf6_interface *oi; + + OSPF6_CMD_CHECK_RUNNING(); + + level = parse_show_level(idx_level, argc, argv); + + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); + ospf6_lsdb_show(vty, level, NULL, NULL, NULL, oa->lsdb); + } + + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + vty_out(vty, IF_LSDB_TITLE_FORMAT, oi->interface->name, + oa->name); + ospf6_lsdb_show(vty, level, NULL, NULL, NULL, oi->lsdb); + } + } + + vty_out(vty, AS_LSDB_TITLE_FORMAT); + ospf6_lsdb_show(vty, level, NULL, NULL, NULL, o->lsdb); + + vty_out(vty, "\n"); + return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_database_type, @@ -231,54 +215,52 @@ DEFUN (show_ipv6_ospf6_database_type, "Display LSA's internal information\n" ) { - int idx_lsa = 4; - int idx_level = 5; - int level; - struct listnode *i, *j; - struct ospf6 *o = ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; - u_int16_t type = 0; - - OSPF6_CMD_CHECK_RUNNING (); - - type = parse_type_spec (idx_lsa, argc, argv); - level = parse_show_level (idx_level, argc, argv); - - switch (OSPF6_LSA_SCOPE (type)) - { - case OSPF6_SCOPE_AREA: - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - vty_out (vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show (vty, level, &type, NULL, NULL, oa->lsdb); - } - break; - - case OSPF6_SCOPE_LINKLOCAL: - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - { - vty_out (vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show (vty, level, &type, NULL, NULL, oi->lsdb); - } - } - break; - - case OSPF6_SCOPE_AS: - vty_out (vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show (vty, level, &type, NULL, NULL, o->lsdb); - break; - - default: - assert (0); - break; - } - - vty_out (vty, "\n"); - return CMD_SUCCESS; + int idx_lsa = 4; + int idx_level = 5; + int level; + struct listnode *i, *j; + struct ospf6 *o = ospf6; + struct ospf6_area *oa; + struct ospf6_interface *oi; + u_int16_t type = 0; + + OSPF6_CMD_CHECK_RUNNING(); + + type = parse_type_spec(idx_lsa, argc, argv); + level = parse_show_level(idx_level, argc, argv); + + switch (OSPF6_LSA_SCOPE(type)) { + case OSPF6_SCOPE_AREA: + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); + ospf6_lsdb_show(vty, level, &type, NULL, NULL, + oa->lsdb); + } + break; + + case OSPF6_SCOPE_LINKLOCAL: + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + vty_out(vty, IF_LSDB_TITLE_FORMAT, + oi->interface->name, oa->name); + ospf6_lsdb_show(vty, level, &type, NULL, NULL, + oi->lsdb); + } + } + break; + + case OSPF6_SCOPE_AS: + vty_out(vty, AS_LSDB_TITLE_FORMAT); + ospf6_lsdb_show(vty, level, &type, NULL, NULL, o->lsdb); + break; + + default: + assert(0); + break; + } + + vty_out(vty, "\n"); + return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_database_id, @@ -295,43 +277,40 @@ DEFUN (show_ipv6_ospf6_database_id, "Dump LSAs\n" "Display LSA's internal information\n") { - int idx_ipv4 = 5; - int idx_level = 6; - int level; - struct listnode *i, *j; - struct ospf6 *o = ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; - u_int32_t id = 0; - - OSPF6_CMD_CHECK_RUNNING (); - - if (argv[idx_ipv4]->type == IPV4_TKN) - inet_pton (AF_INET, argv[idx_ipv4]->arg, &id); - - level = parse_show_level (idx_level, argc, argv); - - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - vty_out (vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show (vty, level, NULL, &id, NULL, oa->lsdb); - } - - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - { - vty_out (vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show (vty, level, NULL, &id, NULL, oi->lsdb); - } - } - - vty_out (vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show (vty, level, NULL, &id, NULL, o->lsdb); - - vty_out (vty, "\n"); - return CMD_SUCCESS; + int idx_ipv4 = 5; + int idx_level = 6; + int level; + struct listnode *i, *j; + struct ospf6 *o = ospf6; + struct ospf6_area *oa; + struct ospf6_interface *oi; + u_int32_t id = 0; + + OSPF6_CMD_CHECK_RUNNING(); + + if (argv[idx_ipv4]->type == IPV4_TKN) + inet_pton(AF_INET, argv[idx_ipv4]->arg, &id); + + level = parse_show_level(idx_level, argc, argv); + + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); + ospf6_lsdb_show(vty, level, NULL, &id, NULL, oa->lsdb); + } + + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + vty_out(vty, IF_LSDB_TITLE_FORMAT, oi->interface->name, + oa->name); + ospf6_lsdb_show(vty, level, NULL, &id, NULL, oi->lsdb); + } + } + + vty_out(vty, AS_LSDB_TITLE_FORMAT); + ospf6_lsdb_show(vty, level, NULL, &id, NULL, o->lsdb); + + vty_out(vty, "\n"); + return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_database_router, @@ -349,40 +328,38 @@ DEFUN (show_ipv6_ospf6_database_router, "Dump LSAs\n" "Display LSA's internal information\n") { - int idx_ipv4 = 6; - int idx_level = 7; - int level; - struct listnode *i, *j; - struct ospf6 *o = ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; - u_int32_t adv_router = 0; - - OSPF6_CMD_CHECK_RUNNING (); - inet_pton (AF_INET, argv[idx_ipv4]->arg, &adv_router); - level = parse_show_level (idx_level, argc, argv); - - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - vty_out (vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show (vty, level, NULL, NULL, &adv_router, oa->lsdb); - } - - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - { - vty_out (vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show (vty, level, NULL, NULL, &adv_router, oi->lsdb); - } - } - - vty_out (vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show (vty, level, NULL, NULL, &adv_router, o->lsdb); - - vty_out (vty, "\n"); - return CMD_SUCCESS; + int idx_ipv4 = 6; + int idx_level = 7; + int level; + struct listnode *i, *j; + struct ospf6 *o = ospf6; + struct ospf6_area *oa; + struct ospf6_interface *oi; + u_int32_t adv_router = 0; + + OSPF6_CMD_CHECK_RUNNING(); + inet_pton(AF_INET, argv[idx_ipv4]->arg, &adv_router); + level = parse_show_level(idx_level, argc, argv); + + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); + ospf6_lsdb_show(vty, level, NULL, NULL, &adv_router, oa->lsdb); + } + + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + vty_out(vty, IF_LSDB_TITLE_FORMAT, oi->interface->name, + oa->name); + ospf6_lsdb_show(vty, level, NULL, NULL, &adv_router, + oi->lsdb); + } + } + + vty_out(vty, AS_LSDB_TITLE_FORMAT); + ospf6_lsdb_show(vty, level, NULL, NULL, &adv_router, o->lsdb); + + vty_out(vty, "\n"); + return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_database_type_id, @@ -408,57 +385,54 @@ DEFUN (show_ipv6_ospf6_database_type_id, "Display LSA's internal information\n" ) { - int idx_lsa = 4; - int idx_ipv4 = 6; - int idx_level = 7; - int level; - struct listnode *i, *j; - struct ospf6 *o = ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; - u_int16_t type = 0; - u_int32_t id = 0; - - OSPF6_CMD_CHECK_RUNNING (); - - type = parse_type_spec (idx_lsa, argc, argv); - inet_pton (AF_INET, argv[idx_ipv4]->arg, &id); - level = parse_show_level (idx_level, argc, argv); - - switch (OSPF6_LSA_SCOPE (type)) - { - case OSPF6_SCOPE_AREA: - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - vty_out (vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show (vty, level, &type, &id, NULL, oa->lsdb); - } - break; - - case OSPF6_SCOPE_LINKLOCAL: - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - { - vty_out (vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show (vty, level, &type, &id, NULL, oi->lsdb); - } - } - break; - - case OSPF6_SCOPE_AS: - vty_out (vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show (vty, level, &type, &id, NULL, o->lsdb); - break; - - default: - assert (0); - break; - } - - vty_out (vty, "\n"); - return CMD_SUCCESS; + int idx_lsa = 4; + int idx_ipv4 = 6; + int idx_level = 7; + int level; + struct listnode *i, *j; + struct ospf6 *o = ospf6; + struct ospf6_area *oa; + struct ospf6_interface *oi; + u_int16_t type = 0; + u_int32_t id = 0; + + OSPF6_CMD_CHECK_RUNNING(); + + type = parse_type_spec(idx_lsa, argc, argv); + inet_pton(AF_INET, argv[idx_ipv4]->arg, &id); + level = parse_show_level(idx_level, argc, argv); + + switch (OSPF6_LSA_SCOPE(type)) { + case OSPF6_SCOPE_AREA: + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); + ospf6_lsdb_show(vty, level, &type, &id, NULL, oa->lsdb); + } + break; + + case OSPF6_SCOPE_LINKLOCAL: + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + vty_out(vty, IF_LSDB_TITLE_FORMAT, + oi->interface->name, oa->name); + ospf6_lsdb_show(vty, level, &type, &id, NULL, + oi->lsdb); + } + } + break; + + case OSPF6_SCOPE_AS: + vty_out(vty, AS_LSDB_TITLE_FORMAT); + ospf6_lsdb_show(vty, level, &type, &id, NULL, o->lsdb); + break; + + default: + assert(0); + break; + } + + vty_out(vty, "\n"); + return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_database_type_router, @@ -485,57 +459,55 @@ DEFUN (show_ipv6_ospf6_database_type_router, "Display LSA's internal information\n" ) { - int idx_lsa = 4; - int idx_ipv4 = 6; - int idx_level = 7; - int level; - struct listnode *i, *j; - struct ospf6 *o = ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; - u_int16_t type = 0; - u_int32_t adv_router = 0; - - OSPF6_CMD_CHECK_RUNNING (); - - type = parse_type_spec (idx_lsa, argc, argv); - inet_pton (AF_INET, argv[idx_ipv4]->arg, &adv_router); - level = parse_show_level (idx_level, argc, argv); - - switch (OSPF6_LSA_SCOPE (type)) - { - case OSPF6_SCOPE_AREA: - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - vty_out (vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show (vty, level, &type, NULL, &adv_router, oa->lsdb); - } - break; - - case OSPF6_SCOPE_LINKLOCAL: - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - { - vty_out (vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show (vty, level, &type, NULL, &adv_router, oi->lsdb); - } - } - break; - - case OSPF6_SCOPE_AS: - vty_out (vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show (vty, level, &type, NULL, &adv_router, o->lsdb); - break; - - default: - assert (0); - break; - } - - vty_out (vty, "\n"); - return CMD_SUCCESS; + int idx_lsa = 4; + int idx_ipv4 = 6; + int idx_level = 7; + int level; + struct listnode *i, *j; + struct ospf6 *o = ospf6; + struct ospf6_area *oa; + struct ospf6_interface *oi; + u_int16_t type = 0; + u_int32_t adv_router = 0; + + OSPF6_CMD_CHECK_RUNNING(); + + type = parse_type_spec(idx_lsa, argc, argv); + inet_pton(AF_INET, argv[idx_ipv4]->arg, &adv_router); + level = parse_show_level(idx_level, argc, argv); + + switch (OSPF6_LSA_SCOPE(type)) { + case OSPF6_SCOPE_AREA: + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); + ospf6_lsdb_show(vty, level, &type, NULL, &adv_router, + oa->lsdb); + } + break; + + case OSPF6_SCOPE_LINKLOCAL: + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + vty_out(vty, IF_LSDB_TITLE_FORMAT, + oi->interface->name, oa->name); + ospf6_lsdb_show(vty, level, &type, NULL, + &adv_router, oi->lsdb); + } + } + break; + + case OSPF6_SCOPE_AS: + vty_out(vty, AS_LSDB_TITLE_FORMAT); + ospf6_lsdb_show(vty, level, &type, NULL, &adv_router, o->lsdb); + break; + + default: + assert(0); + break; + } + + vty_out(vty, "\n"); + return CMD_SUCCESS; } @@ -554,43 +526,41 @@ DEFUN (show_ipv6_ospf6_database_id_router, "Display LSA's internal information\n" ) { - int idx_ls_id = 5; - int idx_adv_rtr = 6; - int idx_level = 7; - int level; - struct listnode *i, *j; - struct ospf6 *o = ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; - u_int32_t id = 0; - u_int32_t adv_router = 0; - - OSPF6_CMD_CHECK_RUNNING (); - inet_pton (AF_INET, argv[idx_ls_id]->arg, &id); - inet_pton (AF_INET, argv[idx_adv_rtr]->arg, &adv_router); - level = parse_show_level (idx_level, argc, argv); - - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - vty_out (vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show (vty, level, NULL, &id, &adv_router, oa->lsdb); - } - - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - { - vty_out (vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show (vty, level, NULL, &id, &adv_router, oi->lsdb); - } - } - - vty_out (vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show (vty, level, NULL, &id, &adv_router, o->lsdb); - - vty_out (vty, "\n"); - return CMD_SUCCESS; + int idx_ls_id = 5; + int idx_adv_rtr = 6; + int idx_level = 7; + int level; + struct listnode *i, *j; + struct ospf6 *o = ospf6; + struct ospf6_area *oa; + struct ospf6_interface *oi; + u_int32_t id = 0; + u_int32_t adv_router = 0; + + OSPF6_CMD_CHECK_RUNNING(); + inet_pton(AF_INET, argv[idx_ls_id]->arg, &id); + inet_pton(AF_INET, argv[idx_adv_rtr]->arg, &adv_router); + level = parse_show_level(idx_level, argc, argv); + + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); + ospf6_lsdb_show(vty, level, NULL, &id, &adv_router, oa->lsdb); + } + + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + vty_out(vty, IF_LSDB_TITLE_FORMAT, oi->interface->name, + oa->name); + ospf6_lsdb_show(vty, level, NULL, &id, &adv_router, + oi->lsdb); + } + } + + vty_out(vty, AS_LSDB_TITLE_FORMAT); + ospf6_lsdb_show(vty, level, NULL, &id, &adv_router, o->lsdb); + + vty_out(vty, "\n"); + return CMD_SUCCESS; } @@ -609,43 +579,41 @@ DEFUN (show_ipv6_ospf6_database_adv_router_linkstate_id, "Dump LSAs\n" "Display LSA's internal information\n") { - int idx_adv_rtr = 5; - int idx_ls_id = 7; - int idx_level = 8; - int level; - struct listnode *i, *j; - struct ospf6 *o = ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; - u_int32_t id = 0; - u_int32_t adv_router = 0; - - OSPF6_CMD_CHECK_RUNNING (); - inet_pton (AF_INET, argv[idx_adv_rtr]->arg, &adv_router); - inet_pton (AF_INET, argv[idx_ls_id]->arg, &id); - level = parse_show_level (idx_level, argc, argv); - - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - vty_out (vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show (vty, level, NULL, &id, &adv_router, oa->lsdb); - } - - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - { - vty_out (vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show (vty, level, NULL, &id, &adv_router, oi->lsdb); - } - } - - vty_out (vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show (vty, level, NULL, &id, &adv_router, o->lsdb); - - vty_out (vty, "\n"); - return CMD_SUCCESS; + int idx_adv_rtr = 5; + int idx_ls_id = 7; + int idx_level = 8; + int level; + struct listnode *i, *j; + struct ospf6 *o = ospf6; + struct ospf6_area *oa; + struct ospf6_interface *oi; + u_int32_t id = 0; + u_int32_t adv_router = 0; + + OSPF6_CMD_CHECK_RUNNING(); + inet_pton(AF_INET, argv[idx_adv_rtr]->arg, &adv_router); + inet_pton(AF_INET, argv[idx_ls_id]->arg, &id); + level = parse_show_level(idx_level, argc, argv); + + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); + ospf6_lsdb_show(vty, level, NULL, &id, &adv_router, oa->lsdb); + } + + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + vty_out(vty, IF_LSDB_TITLE_FORMAT, oi->interface->name, + oa->name); + ospf6_lsdb_show(vty, level, NULL, &id, &adv_router, + oi->lsdb); + } + } + + vty_out(vty, AS_LSDB_TITLE_FORMAT); + ospf6_lsdb_show(vty, level, NULL, &id, &adv_router, o->lsdb); + + vty_out(vty, "\n"); + return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_database_type_id_router, @@ -669,60 +637,58 @@ DEFUN (show_ipv6_ospf6_database_type_id_router, "Dump LSAs\n" "Display LSA's internal information\n") { - int idx_lsa = 4; - int idx_ls_id = 5; - int idx_adv_rtr = 6; - int idx_level = 7; - int level; - struct listnode *i, *j; - struct ospf6 *o = ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; - u_int16_t type = 0; - u_int32_t id = 0; - u_int32_t adv_router = 0; - - OSPF6_CMD_CHECK_RUNNING (); - - type = parse_type_spec (idx_lsa, argc, argv); - inet_pton (AF_INET, argv[idx_ls_id]->arg, &id); - inet_pton (AF_INET, argv[idx_adv_rtr]->arg, &adv_router); - level = parse_show_level (idx_level, argc, argv); - - switch (OSPF6_LSA_SCOPE (type)) - { - case OSPF6_SCOPE_AREA: - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - vty_out (vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show (vty, level, &type, &id, &adv_router, oa->lsdb); - } - break; - - case OSPF6_SCOPE_LINKLOCAL: - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - { - vty_out (vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show (vty, level, &type, &id, &adv_router, oi->lsdb); - } - } - break; - - case OSPF6_SCOPE_AS: - vty_out (vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show (vty, level, &type, &id, &adv_router, o->lsdb); - break; - - default: - assert (0); - break; - } - - vty_out (vty, "\n"); - return CMD_SUCCESS; + int idx_lsa = 4; + int idx_ls_id = 5; + int idx_adv_rtr = 6; + int idx_level = 7; + int level; + struct listnode *i, *j; + struct ospf6 *o = ospf6; + struct ospf6_area *oa; + struct ospf6_interface *oi; + u_int16_t type = 0; + u_int32_t id = 0; + u_int32_t adv_router = 0; + + OSPF6_CMD_CHECK_RUNNING(); + + type = parse_type_spec(idx_lsa, argc, argv); + inet_pton(AF_INET, argv[idx_ls_id]->arg, &id); + inet_pton(AF_INET, argv[idx_adv_rtr]->arg, &adv_router); + level = parse_show_level(idx_level, argc, argv); + + switch (OSPF6_LSA_SCOPE(type)) { + case OSPF6_SCOPE_AREA: + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); + ospf6_lsdb_show(vty, level, &type, &id, &adv_router, + oa->lsdb); + } + break; + + case OSPF6_SCOPE_LINKLOCAL: + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + vty_out(vty, IF_LSDB_TITLE_FORMAT, + oi->interface->name, oa->name); + ospf6_lsdb_show(vty, level, &type, &id, + &adv_router, oi->lsdb); + } + } + break; + + case OSPF6_SCOPE_AS: + vty_out(vty, AS_LSDB_TITLE_FORMAT); + ospf6_lsdb_show(vty, level, &type, &id, &adv_router, o->lsdb); + break; + + default: + assert(0); + break; + } + + vty_out(vty, "\n"); + return CMD_SUCCESS; } @@ -749,60 +715,58 @@ DEFUN (show_ipv6_ospf6_database_type_adv_router_linkstate_id, "Dump LSAs\n" "Display LSA's internal information\n") { - int idx_lsa = 4; - int idx_adv_rtr = 6; - int idx_ls_id = 8; - int idx_level = 9; - int level; - struct listnode *i, *j; - struct ospf6 *o = ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; - u_int16_t type = 0; - u_int32_t id = 0; - u_int32_t adv_router = 0; - - OSPF6_CMD_CHECK_RUNNING (); - - type = parse_type_spec (idx_lsa, argc, argv); - inet_pton (AF_INET, argv[idx_adv_rtr]->arg, &adv_router); - inet_pton (AF_INET, argv[idx_ls_id]->arg, &id); - level = parse_show_level (idx_level, argc, argv); - - switch (OSPF6_LSA_SCOPE (type)) - { - case OSPF6_SCOPE_AREA: - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - vty_out (vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show (vty, level, &type, &id, &adv_router, oa->lsdb); - } - break; - - case OSPF6_SCOPE_LINKLOCAL: - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - { - vty_out (vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show (vty, level, &type, &id, &adv_router, oi->lsdb); - } - } - break; - - case OSPF6_SCOPE_AS: - vty_out (vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show (vty, level, &type, &id, &adv_router, o->lsdb); - break; - - default: - assert (0); - break; - } - - vty_out (vty, "\n"); - return CMD_SUCCESS; + int idx_lsa = 4; + int idx_adv_rtr = 6; + int idx_ls_id = 8; + int idx_level = 9; + int level; + struct listnode *i, *j; + struct ospf6 *o = ospf6; + struct ospf6_area *oa; + struct ospf6_interface *oi; + u_int16_t type = 0; + u_int32_t id = 0; + u_int32_t adv_router = 0; + + OSPF6_CMD_CHECK_RUNNING(); + + type = parse_type_spec(idx_lsa, argc, argv); + inet_pton(AF_INET, argv[idx_adv_rtr]->arg, &adv_router); + inet_pton(AF_INET, argv[idx_ls_id]->arg, &id); + level = parse_show_level(idx_level, argc, argv); + + switch (OSPF6_LSA_SCOPE(type)) { + case OSPF6_SCOPE_AREA: + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); + ospf6_lsdb_show(vty, level, &type, &id, &adv_router, + oa->lsdb); + } + break; + + case OSPF6_SCOPE_LINKLOCAL: + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + vty_out(vty, IF_LSDB_TITLE_FORMAT, + oi->interface->name, oa->name); + ospf6_lsdb_show(vty, level, &type, &id, + &adv_router, oi->lsdb); + } + } + break; + + case OSPF6_SCOPE_AS: + vty_out(vty, AS_LSDB_TITLE_FORMAT); + ospf6_lsdb_show(vty, level, &type, &id, &adv_router, o->lsdb); + break; + + default: + assert(0); + break; + } + + vty_out(vty, "\n"); + return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_database_self_originated, @@ -817,39 +781,37 @@ DEFUN (show_ipv6_ospf6_database_self_originated, "Dump LSAs\n" "Display LSA's internal information\n") { - int idx_level = 5; - int level; - struct listnode *i, *j; - struct ospf6 *o = ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; - u_int32_t adv_router = 0; - - OSPF6_CMD_CHECK_RUNNING (); - level = parse_show_level (idx_level, argc, argv); - adv_router = o->router_id; - - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - vty_out (vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show (vty, level, NULL, NULL, &adv_router, oa->lsdb); - } - - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - { - vty_out (vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show (vty, level, NULL, NULL, &adv_router, oi->lsdb); - } - } - - vty_out (vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show (vty, level, NULL, NULL, &adv_router, o->lsdb); - - vty_out (vty, "\n"); - return CMD_SUCCESS; + int idx_level = 5; + int level; + struct listnode *i, *j; + struct ospf6 *o = ospf6; + struct ospf6_area *oa; + struct ospf6_interface *oi; + u_int32_t adv_router = 0; + + OSPF6_CMD_CHECK_RUNNING(); + level = parse_show_level(idx_level, argc, argv); + adv_router = o->router_id; + + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); + ospf6_lsdb_show(vty, level, NULL, NULL, &adv_router, oa->lsdb); + } + + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + vty_out(vty, IF_LSDB_TITLE_FORMAT, oi->interface->name, + oa->name); + ospf6_lsdb_show(vty, level, NULL, NULL, &adv_router, + oi->lsdb); + } + } + + vty_out(vty, AS_LSDB_TITLE_FORMAT); + ospf6_lsdb_show(vty, level, NULL, NULL, &adv_router, o->lsdb); + + vty_out(vty, "\n"); + return CMD_SUCCESS; } @@ -874,57 +836,55 @@ DEFUN (show_ipv6_ospf6_database_type_self_originated, "Dump LSAs\n" "Display LSA's internal information\n") { - int idx_lsa = 4; - int idx_level = 6; - int level; - struct listnode *i, *j; - struct ospf6 *o = ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; - u_int16_t type = 0; - u_int32_t adv_router = 0; - - OSPF6_CMD_CHECK_RUNNING (); - - type = parse_type_spec (idx_lsa, argc, argv); - level = parse_show_level (idx_level, argc, argv); - - adv_router = o->router_id; - - switch (OSPF6_LSA_SCOPE (type)) - { - case OSPF6_SCOPE_AREA: - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - vty_out (vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show (vty, level, &type, NULL, &adv_router, oa->lsdb); - } - break; - - case OSPF6_SCOPE_LINKLOCAL: - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - { - vty_out (vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show (vty, level, &type, NULL, &adv_router, oi->lsdb); - } - } - break; - - case OSPF6_SCOPE_AS: - vty_out (vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show (vty, level, &type, NULL, &adv_router, o->lsdb); - break; - - default: - assert (0); - break; - } - - vty_out (vty, "\n"); - return CMD_SUCCESS; + int idx_lsa = 4; + int idx_level = 6; + int level; + struct listnode *i, *j; + struct ospf6 *o = ospf6; + struct ospf6_area *oa; + struct ospf6_interface *oi; + u_int16_t type = 0; + u_int32_t adv_router = 0; + + OSPF6_CMD_CHECK_RUNNING(); + + type = parse_type_spec(idx_lsa, argc, argv); + level = parse_show_level(idx_level, argc, argv); + + adv_router = o->router_id; + + switch (OSPF6_LSA_SCOPE(type)) { + case OSPF6_SCOPE_AREA: + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); + ospf6_lsdb_show(vty, level, &type, NULL, &adv_router, + oa->lsdb); + } + break; + + case OSPF6_SCOPE_LINKLOCAL: + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + vty_out(vty, IF_LSDB_TITLE_FORMAT, + oi->interface->name, oa->name); + ospf6_lsdb_show(vty, level, &type, NULL, + &adv_router, oi->lsdb); + } + } + break; + + case OSPF6_SCOPE_AS: + vty_out(vty, AS_LSDB_TITLE_FORMAT); + ospf6_lsdb_show(vty, level, &type, NULL, &adv_router, o->lsdb); + break; + + default: + assert(0); + break; + } + + vty_out(vty, "\n"); + return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_database_type_self_originated_linkstate_id, @@ -950,59 +910,57 @@ DEFUN (show_ipv6_ospf6_database_type_self_originated_linkstate_id, "Dump LSAs\n" "Display LSA's internal information\n") { - int idx_lsa = 4; - int idx_ls_id = 7; - int idx_level = 8; - int level; - struct listnode *i, *j; - struct ospf6 *o = ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; - u_int16_t type = 0; - u_int32_t adv_router = 0; - u_int32_t id = 0; - - OSPF6_CMD_CHECK_RUNNING (); - - type = parse_type_spec (idx_lsa, argc, argv); - inet_pton (AF_INET, argv[idx_ls_id]->arg, &id); - level = parse_show_level (idx_level, argc, argv); - adv_router = o->router_id; - - switch (OSPF6_LSA_SCOPE (type)) - { - case OSPF6_SCOPE_AREA: - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - vty_out (vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show (vty, level, &type, &id, &adv_router, oa->lsdb); - } - break; - - case OSPF6_SCOPE_LINKLOCAL: - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - { - vty_out (vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show (vty, level, &type, &id, &adv_router, oi->lsdb); - } - } - break; - - case OSPF6_SCOPE_AS: - vty_out (vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show (vty, level, &type, &id, &adv_router, o->lsdb); - break; - - default: - assert (0); - break; - } - - vty_out (vty, "\n"); - return CMD_SUCCESS; + int idx_lsa = 4; + int idx_ls_id = 7; + int idx_level = 8; + int level; + struct listnode *i, *j; + struct ospf6 *o = ospf6; + struct ospf6_area *oa; + struct ospf6_interface *oi; + u_int16_t type = 0; + u_int32_t adv_router = 0; + u_int32_t id = 0; + + OSPF6_CMD_CHECK_RUNNING(); + + type = parse_type_spec(idx_lsa, argc, argv); + inet_pton(AF_INET, argv[idx_ls_id]->arg, &id); + level = parse_show_level(idx_level, argc, argv); + adv_router = o->router_id; + + switch (OSPF6_LSA_SCOPE(type)) { + case OSPF6_SCOPE_AREA: + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); + ospf6_lsdb_show(vty, level, &type, &id, &adv_router, + oa->lsdb); + } + break; + + case OSPF6_SCOPE_LINKLOCAL: + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + vty_out(vty, IF_LSDB_TITLE_FORMAT, + oi->interface->name, oa->name); + ospf6_lsdb_show(vty, level, &type, &id, + &adv_router, oi->lsdb); + } + } + break; + + case OSPF6_SCOPE_AS: + vty_out(vty, AS_LSDB_TITLE_FORMAT); + ospf6_lsdb_show(vty, level, &type, &id, &adv_router, o->lsdb); + break; + + default: + assert(0); + break; + } + + vty_out(vty, "\n"); + return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_database_type_id_self_originated, @@ -1027,59 +985,57 @@ DEFUN (show_ipv6_ospf6_database_type_id_self_originated, "Dump LSAs\n" "Display LSA's internal information\n") { - int idx_lsa = 4; - int idx_ls_id = 5; - int idx_level = 7; - int level; - struct listnode *i, *j; - struct ospf6 *o = ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; - u_int16_t type = 0; - u_int32_t adv_router = 0; - u_int32_t id = 0; - - OSPF6_CMD_CHECK_RUNNING (); - - type = parse_type_spec (idx_lsa, argc, argv); - inet_pton (AF_INET, argv[idx_ls_id]->arg, &id); - level = parse_show_level (idx_level, argc, argv); - adv_router = o->router_id; - - switch (OSPF6_LSA_SCOPE (type)) - { - case OSPF6_SCOPE_AREA: - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - vty_out (vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show (vty, level, &type, &id, &adv_router, oa->lsdb); - } - break; - - case OSPF6_SCOPE_LINKLOCAL: - for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa)) - { - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - { - vty_out (vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show (vty, level, &type, &id, &adv_router, oi->lsdb); - } - } - break; - - case OSPF6_SCOPE_AS: - vty_out (vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show (vty, level, &type, &id, &adv_router, o->lsdb); - break; - - default: - assert (0); - break; - } - - vty_out (vty, "\n"); - return CMD_SUCCESS; + int idx_lsa = 4; + int idx_ls_id = 5; + int idx_level = 7; + int level; + struct listnode *i, *j; + struct ospf6 *o = ospf6; + struct ospf6_area *oa; + struct ospf6_interface *oi; + u_int16_t type = 0; + u_int32_t adv_router = 0; + u_int32_t id = 0; + + OSPF6_CMD_CHECK_RUNNING(); + + type = parse_type_spec(idx_lsa, argc, argv); + inet_pton(AF_INET, argv[idx_ls_id]->arg, &id); + level = parse_show_level(idx_level, argc, argv); + adv_router = o->router_id; + + switch (OSPF6_LSA_SCOPE(type)) { + case OSPF6_SCOPE_AREA: + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); + ospf6_lsdb_show(vty, level, &type, &id, &adv_router, + oa->lsdb); + } + break; + + case OSPF6_SCOPE_LINKLOCAL: + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + vty_out(vty, IF_LSDB_TITLE_FORMAT, + oi->interface->name, oa->name); + ospf6_lsdb_show(vty, level, &type, &id, + &adv_router, oi->lsdb); + } + } + break; + + case OSPF6_SCOPE_AS: + vty_out(vty, AS_LSDB_TITLE_FORMAT); + ospf6_lsdb_show(vty, level, &type, &id, &adv_router, o->lsdb); + break; + + default: + assert(0); + break; + } + + vty_out(vty, "\n"); + return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_border_routers, @@ -1092,47 +1048,42 @@ DEFUN (show_ipv6_ospf6_border_routers, "Router ID\n" "Show detailed output\n") { - int idx_ipv4 = 4; - u_int32_t adv_router; - struct ospf6_route *ro; - struct prefix prefix; - - OSPF6_CMD_CHECK_RUNNING (); - - if (argc == 5) - { - if (strmatch (argv[idx_ipv4]->text, "detail")) - { - for (ro = ospf6_route_head (ospf6->brouter_table); ro; - ro = ospf6_route_next (ro)) - ospf6_route_show_detail (vty, ro); - } - else - { - inet_pton (AF_INET, argv[idx_ipv4]->arg, &adv_router); - - ospf6_linkstate_prefix (adv_router, 0, &prefix); - ro = ospf6_route_lookup (&prefix, ospf6->brouter_table); - if (!ro) - { - vty_out (vty, "No Route found for Router ID: %s\n", argv[4]->arg); - return CMD_SUCCESS; - } - - ospf6_route_show_detail (vty, ro); - return CMD_SUCCESS; - } - } - else - { - ospf6_brouter_show_header (vty); - - for (ro = ospf6_route_head (ospf6->brouter_table); ro; - ro = ospf6_route_next (ro)) - ospf6_brouter_show (vty, ro); - } - - return CMD_SUCCESS; + int idx_ipv4 = 4; + u_int32_t adv_router; + struct ospf6_route *ro; + struct prefix prefix; + + OSPF6_CMD_CHECK_RUNNING(); + + if (argc == 5) { + if (strmatch(argv[idx_ipv4]->text, "detail")) { + for (ro = ospf6_route_head(ospf6->brouter_table); ro; + ro = ospf6_route_next(ro)) + ospf6_route_show_detail(vty, ro); + } else { + inet_pton(AF_INET, argv[idx_ipv4]->arg, &adv_router); + + ospf6_linkstate_prefix(adv_router, 0, &prefix); + ro = ospf6_route_lookup(&prefix, ospf6->brouter_table); + if (!ro) { + vty_out(vty, + "No Route found for Router ID: %s\n", + argv[4]->arg); + return CMD_SUCCESS; + } + + ospf6_route_show_detail(vty, ro); + return CMD_SUCCESS; + } + } else { + ospf6_brouter_show_header(vty); + + for (ro = ospf6_route_head(ospf6->brouter_table); ro; + ro = ospf6_route_next(ro)) + ospf6_brouter_show(vty, ro); + } + + return CMD_SUCCESS; } @@ -1149,24 +1100,23 @@ DEFUN (show_ipv6_ospf6_linkstate, "Specify Router ID as IPv4 address notation\n" "Specify Link state ID as IPv4 address notation\n") { - int idx_ipv4 = 4; - struct listnode *node; - struct ospf6_area *oa; + int idx_ipv4 = 4; + struct listnode *node; + struct ospf6_area *oa; - OSPF6_CMD_CHECK_RUNNING (); + OSPF6_CMD_CHECK_RUNNING(); - for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa)) - { - vty_out (vty, "\n SPF Result in Area %s\n\n", oa->name); - ospf6_linkstate_table_show (vty, idx_ipv4, argc, argv, oa->spf_table); - } + for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) { + vty_out(vty, "\n SPF Result in Area %s\n\n", oa->name); + ospf6_linkstate_table_show(vty, idx_ipv4, argc, argv, + oa->spf_table); + } - vty_out (vty, "\n"); - return CMD_SUCCESS; + vty_out(vty, "\n"); + return CMD_SUCCESS; } - DEFUN (show_ipv6_ospf6_linkstate_detail, show_ipv6_ospf6_linkstate_detail_cmd, "show ipv6 ospf6 linkstate detail", @@ -1176,89 +1126,96 @@ DEFUN (show_ipv6_ospf6_linkstate_detail, "Display linkstate routing table\n" "Display detailed information\n") { - int idx_detail = 4; - struct listnode *node; - struct ospf6_area *oa; + int idx_detail = 4; + struct listnode *node; + struct ospf6_area *oa; - OSPF6_CMD_CHECK_RUNNING (); + OSPF6_CMD_CHECK_RUNNING(); - for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa)) - { - vty_out (vty, "\n SPF Result in Area %s\n\n", oa->name); - ospf6_linkstate_table_show (vty, idx_detail, argc, argv, oa->spf_table); - } + for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) { + vty_out(vty, "\n SPF Result in Area %s\n\n", oa->name); + ospf6_linkstate_table_show(vty, idx_detail, argc, argv, + oa->spf_table); + } - vty_out (vty, "\n"); - return CMD_SUCCESS; + vty_out(vty, "\n"); + return CMD_SUCCESS; } /* Install ospf related commands. */ -void -ospf6_init (void) +void ospf6_init(void) { - ospf6_top_init (); - ospf6_area_init (); - ospf6_interface_init (); - ospf6_neighbor_init (); - ospf6_zebra_init(master); - - ospf6_lsa_init (); - ospf6_spf_init (); - ospf6_intra_init (); - ospf6_asbr_init (); - ospf6_abr_init (); - - ospf6_bfd_init(); - install_node (&debug_node, config_write_ospf6_debug); - - install_element_ospf6_debug_message (); - install_element_ospf6_debug_lsa (); - install_element_ospf6_debug_interface (); - install_element_ospf6_debug_neighbor (); - install_element_ospf6_debug_zebra (); - install_element_ospf6_debug_spf (); - install_element_ospf6_debug_route (); - install_element_ospf6_debug_brouter (); - install_element_ospf6_debug_asbr (); - install_element_ospf6_debug_abr (); - install_element_ospf6_debug_flood (); - - install_element_ospf6_clear_interface (); - - install_element (VIEW_NODE, &show_version_ospf6_cmd); - - install_element (VIEW_NODE, &show_ipv6_ospf6_border_routers_cmd); - - install_element (VIEW_NODE, &show_ipv6_ospf6_linkstate_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_linkstate_detail_cmd); - - install_element (VIEW_NODE, &show_ipv6_ospf6_database_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_database_id_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_database_router_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_id_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_router_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_database_adv_router_linkstate_id_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_database_id_router_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_id_router_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_adv_router_linkstate_id_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_database_self_originated_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_self_originated_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_id_self_originated_cmd); - install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_self_originated_linkstate_id_cmd); - - /* Make ospf protocol socket. */ - ospf6_serv_sock (); - thread_add_read(master, ospf6_receive, NULL, ospf6_sock, NULL); + ospf6_top_init(); + ospf6_area_init(); + ospf6_interface_init(); + ospf6_neighbor_init(); + ospf6_zebra_init(master); + + ospf6_lsa_init(); + ospf6_spf_init(); + ospf6_intra_init(); + ospf6_asbr_init(); + ospf6_abr_init(); + + ospf6_bfd_init(); + install_node(&debug_node, config_write_ospf6_debug); + + install_element_ospf6_debug_message(); + install_element_ospf6_debug_lsa(); + install_element_ospf6_debug_interface(); + install_element_ospf6_debug_neighbor(); + install_element_ospf6_debug_zebra(); + install_element_ospf6_debug_spf(); + install_element_ospf6_debug_route(); + install_element_ospf6_debug_brouter(); + install_element_ospf6_debug_asbr(); + install_element_ospf6_debug_abr(); + install_element_ospf6_debug_flood(); + + install_element_ospf6_clear_interface(); + + install_element(VIEW_NODE, &show_version_ospf6_cmd); + + install_element(VIEW_NODE, &show_ipv6_ospf6_border_routers_cmd); + + install_element(VIEW_NODE, &show_ipv6_ospf6_linkstate_cmd); + install_element(VIEW_NODE, &show_ipv6_ospf6_linkstate_detail_cmd); + + install_element(VIEW_NODE, &show_ipv6_ospf6_database_cmd); + install_element(VIEW_NODE, &show_ipv6_ospf6_database_type_cmd); + install_element(VIEW_NODE, &show_ipv6_ospf6_database_id_cmd); + install_element(VIEW_NODE, &show_ipv6_ospf6_database_router_cmd); + install_element(VIEW_NODE, &show_ipv6_ospf6_database_type_id_cmd); + install_element(VIEW_NODE, &show_ipv6_ospf6_database_type_router_cmd); + install_element(VIEW_NODE, + &show_ipv6_ospf6_database_adv_router_linkstate_id_cmd); + install_element(VIEW_NODE, &show_ipv6_ospf6_database_id_router_cmd); + install_element(VIEW_NODE, + &show_ipv6_ospf6_database_type_id_router_cmd); + install_element( + VIEW_NODE, + &show_ipv6_ospf6_database_type_adv_router_linkstate_id_cmd); + install_element(VIEW_NODE, + &show_ipv6_ospf6_database_self_originated_cmd); + install_element(VIEW_NODE, + &show_ipv6_ospf6_database_type_self_originated_cmd); + install_element(VIEW_NODE, + &show_ipv6_ospf6_database_type_id_self_originated_cmd); + install_element( + VIEW_NODE, + &show_ipv6_ospf6_database_type_self_originated_linkstate_id_cmd); + + /* Make ospf protocol socket. */ + ospf6_serv_sock(); + thread_add_read(master, ospf6_receive, NULL, ospf6_sock, NULL); } -void -ospf6_clean (void) +void ospf6_clean(void) { - if (!ospf6) - return; - if (ospf6->route_table) - ospf6_route_remove_all (ospf6->route_table); - if (ospf6->brouter_table) - ospf6_route_remove_all (ospf6->brouter_table); + if (!ospf6) + return; + if (ospf6->route_table) + ospf6_route_remove_all(ospf6->route_table); + if (ospf6->brouter_table) + ospf6_route_remove_all(ospf6->brouter_table); } diff --git a/ospf6d/ospf6d.h b/ospf6d/ospf6d.h index 2da11d0ab..1515c3ad0 100644 --- a/ospf6d/ospf6d.h +++ b/ospf6d/ospf6d.h @@ -57,31 +57,31 @@ extern struct thread_master *master; #define OSPF6_NEIGHBOR(x) ((struct ospf6_neighbor *) (x)) /* operation on timeval structure */ -#define timerstring(tv, buf, size) \ - do { \ - if ((tv)->tv_sec / 60 / 60 / 24) \ - snprintf (buf, size, "%lldd%02lld:%02lld:%02lld", \ - (tv)->tv_sec / 60LL / 60 / 24, \ - (tv)->tv_sec / 60LL / 60 % 24, \ - (tv)->tv_sec / 60LL % 60, \ - (tv)->tv_sec % 60LL); \ - else \ - snprintf (buf, size, "%02lld:%02lld:%02lld", \ - (tv)->tv_sec / 60LL / 60 % 24, \ - (tv)->tv_sec / 60LL % 60, \ - (tv)->tv_sec % 60LL); \ - } while (0) - -#define threadtimer_string(now, t, buf, size) \ - do { \ - struct timeval result; \ - if (!t) \ - snprintf(buf, size, "inactive"); \ - else { \ - timersub(&t->u.sands, &now, &result); \ - timerstring(&result, buf, size); \ - } \ -} while (0) +#define timerstring(tv, buf, size) \ + do { \ + if ((tv)->tv_sec / 60 / 60 / 24) \ + snprintf(buf, size, "%lldd%02lld:%02lld:%02lld", \ + (tv)->tv_sec / 60LL / 60 / 24, \ + (tv)->tv_sec / 60LL / 60 % 24, \ + (tv)->tv_sec / 60LL % 60, \ + (tv)->tv_sec % 60LL); \ + else \ + snprintf(buf, size, "%02lld:%02lld:%02lld", \ + (tv)->tv_sec / 60LL / 60 % 24, \ + (tv)->tv_sec / 60LL % 60, \ + (tv)->tv_sec % 60LL); \ + } while (0) + +#define threadtimer_string(now, t, buf, size) \ + do { \ + struct timeval result; \ + if (!t) \ + snprintf(buf, size, "inactive"); \ + else { \ + timersub(&t->u.sands, &now, &result); \ + timerstring(&result, buf, size); \ + } \ + } while (0) /* for commands */ #define OSPF6_AREA_STR "Area information\n" @@ -90,20 +90,17 @@ extern struct thread_master *master; #define OSPF6_ROUTER_ID_STR "Specify Router-ID\n" #define OSPF6_LS_ID_STR "Specify Link State ID\n" -#define OSPF6_CMD_CHECK_RUNNING() \ - if (ospf6 == NULL) \ - { \ - vty_out (vty, "OSPFv3 is not running\n"); \ - return CMD_SUCCESS; \ - } +#define OSPF6_CMD_CHECK_RUNNING() \ + if (ospf6 == NULL) { \ + vty_out(vty, "OSPFv3 is not running\n"); \ + return CMD_SUCCESS; \ + } /* Function Prototypes */ -extern struct route_node *route_prev (struct route_node *node); +extern struct route_node *route_prev(struct route_node *node); -extern void ospf6_debug (void); -extern void ospf6_init (void); +extern void ospf6_debug(void); +extern void ospf6_init(void); #endif /* OSPF6D_H */ - - diff --git a/ospfclient/ospf_apiclient.c b/ospfclient/ospf_apiclient.c index 3f3b5511a..bdac0e49a 100644 --- a/ospfclient/ospf_apiclient.c +++ b/ospfclient/ospf_apiclient.c @@ -66,24 +66,23 @@ DEFINE_MTYPE_STATIC(OSPFCLIENT, OSPF_APICLIENT, "OSPF-API client") * ----------------------------------------------------------- */ -void ospf_apiclient_handle_reply (struct ospf_apiclient *oclient, - struct msg *msg); -void ospf_apiclient_handle_update_notify (struct ospf_apiclient *oclient, - struct msg *msg); -void ospf_apiclient_handle_delete_notify (struct ospf_apiclient *oclient, - struct msg *msg); +void ospf_apiclient_handle_reply(struct ospf_apiclient *oclient, + struct msg *msg); +void ospf_apiclient_handle_update_notify(struct ospf_apiclient *oclient, + struct msg *msg); +void ospf_apiclient_handle_delete_notify(struct ospf_apiclient *oclient, + struct msg *msg); /* ----------------------------------------------------------- * Initialization * ----------------------------------------------------------- */ -static unsigned short -ospf_apiclient_getport (void) +static unsigned short ospf_apiclient_getport(void) { - struct servent *sp = getservbyname ("ospfapi", "tcp"); + struct servent *sp = getservbyname("ospfapi", "tcp"); - return sp ? ntohs (sp->s_port) : OSPF_API_SYNC_PORT; + return sp ? ntohs(sp->s_port) : OSPF_API_SYNC_PORT; } /* ----------------------------------------------------------- @@ -91,214 +90,208 @@ ospf_apiclient_getport (void) * ----------------------------------------------------------- */ -struct ospf_apiclient * -ospf_apiclient_connect (char *host, int syncport) +struct ospf_apiclient *ospf_apiclient_connect(char *host, int syncport) { - struct sockaddr_in myaddr_sync; - struct sockaddr_in myaddr_async; - struct sockaddr_in peeraddr; - struct hostent *hp; - struct ospf_apiclient *new; - int size = 0; - unsigned int peeraddrlen; - int async_server_sock; - int fd1, fd2; - int ret; - int on = 1; - - /* There are two connections between the client and the server. - First the client opens a connection for synchronous requests/replies - to the server. The server will accept this connection and - as a reaction open a reverse connection channel for - asynchronous messages. */ - - async_server_sock = socket (AF_INET, SOCK_STREAM, 0); - if (async_server_sock < 0) - { - fprintf (stderr, - "ospf_apiclient_connect: creating async socket failed\n"); - return NULL; - } - - /* Prepare socket for asynchronous messages */ - /* Initialize async address structure */ - memset (&myaddr_async, 0, sizeof (struct sockaddr_in)); - myaddr_async.sin_family = AF_INET; - myaddr_async.sin_addr.s_addr = htonl (INADDR_ANY); - myaddr_async.sin_port = htons (syncport+1); - size = sizeof (struct sockaddr_in); + struct sockaddr_in myaddr_sync; + struct sockaddr_in myaddr_async; + struct sockaddr_in peeraddr; + struct hostent *hp; + struct ospf_apiclient *new; + int size = 0; + unsigned int peeraddrlen; + int async_server_sock; + int fd1, fd2; + int ret; + int on = 1; + + /* There are two connections between the client and the server. + First the client opens a connection for synchronous requests/replies + to the server. The server will accept this connection and + as a reaction open a reverse connection channel for + asynchronous messages. */ + + async_server_sock = socket(AF_INET, SOCK_STREAM, 0); + if (async_server_sock < 0) { + fprintf(stderr, + "ospf_apiclient_connect: creating async socket failed\n"); + return NULL; + } + + /* Prepare socket for asynchronous messages */ + /* Initialize async address structure */ + memset(&myaddr_async, 0, sizeof(struct sockaddr_in)); + myaddr_async.sin_family = AF_INET; + myaddr_async.sin_addr.s_addr = htonl(INADDR_ANY); + myaddr_async.sin_port = htons(syncport + 1); + size = sizeof(struct sockaddr_in); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - myaddr_async.sin_len = size; + myaddr_async.sin_len = size; #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - /* This is a server socket, reuse addr and port */ - ret = setsockopt (async_server_sock, SOL_SOCKET, - SO_REUSEADDR, (void *) &on, sizeof (on)); - if (ret < 0) - { - fprintf (stderr, "ospf_apiclient_connect: SO_REUSEADDR failed\n"); - close (async_server_sock); - return NULL; - } + /* This is a server socket, reuse addr and port */ + ret = setsockopt(async_server_sock, SOL_SOCKET, SO_REUSEADDR, + (void *)&on, sizeof(on)); + if (ret < 0) { + fprintf(stderr, + "ospf_apiclient_connect: SO_REUSEADDR failed\n"); + close(async_server_sock); + return NULL; + } #ifdef SO_REUSEPORT - ret = setsockopt (async_server_sock, SOL_SOCKET, SO_REUSEPORT, - (void *) &on, sizeof (on)); - if (ret < 0) - { - fprintf (stderr, "ospf_apiclient_connect: SO_REUSEPORT failed\n"); - close (async_server_sock); - return NULL; - } + ret = setsockopt(async_server_sock, SOL_SOCKET, SO_REUSEPORT, + (void *)&on, sizeof(on)); + if (ret < 0) { + fprintf(stderr, + "ospf_apiclient_connect: SO_REUSEPORT failed\n"); + close(async_server_sock); + return NULL; + } #endif /* SO_REUSEPORT */ - /* Bind socket to address structure */ - ret = bind (async_server_sock, (struct sockaddr *) &myaddr_async, size); - if (ret < 0) - { - fprintf (stderr, "ospf_apiclient_connect: bind async socket failed\n"); - close (async_server_sock); - return NULL; - } - - /* Wait for reverse channel connection establishment from server */ - ret = listen (async_server_sock, BACKLOG); - if (ret < 0) - { - fprintf (stderr, "ospf_apiclient_connect: listen: %s\n", safe_strerror (errno)); - close (async_server_sock); - return NULL; - } - - /* Make connection for synchronous requests and connect to server */ - /* Resolve address of server */ - hp = gethostbyname (host); - if (!hp) - { - fprintf (stderr, "ospf_apiclient_connect: no such host %s\n", host); - close (async_server_sock); - return NULL; - } - - fd1 = socket (AF_INET, SOCK_STREAM, 0); - if (fd1 < 0) - { - close (async_server_sock); - fprintf (stderr, - "ospf_apiclient_connect: creating sync socket failed\n"); - return NULL; - } - - - /* Reuse addr and port */ - ret = setsockopt (fd1, SOL_SOCKET, - SO_REUSEADDR, (void *) &on, sizeof (on)); - if (ret < 0) - { - fprintf (stderr, "ospf_apiclient_connect: SO_REUSEADDR failed\n"); - close (fd1); - close (async_server_sock); - return NULL; - } + /* Bind socket to address structure */ + ret = bind(async_server_sock, (struct sockaddr *)&myaddr_async, size); + if (ret < 0) { + fprintf(stderr, + "ospf_apiclient_connect: bind async socket failed\n"); + close(async_server_sock); + return NULL; + } + + /* Wait for reverse channel connection establishment from server */ + ret = listen(async_server_sock, BACKLOG); + if (ret < 0) { + fprintf(stderr, "ospf_apiclient_connect: listen: %s\n", + safe_strerror(errno)); + close(async_server_sock); + return NULL; + } + + /* Make connection for synchronous requests and connect to server */ + /* Resolve address of server */ + hp = gethostbyname(host); + if (!hp) { + fprintf(stderr, "ospf_apiclient_connect: no such host %s\n", + host); + close(async_server_sock); + return NULL; + } + + fd1 = socket(AF_INET, SOCK_STREAM, 0); + if (fd1 < 0) { + close(async_server_sock); + fprintf(stderr, + "ospf_apiclient_connect: creating sync socket failed\n"); + return NULL; + } + + + /* Reuse addr and port */ + ret = setsockopt(fd1, SOL_SOCKET, SO_REUSEADDR, (void *)&on, + sizeof(on)); + if (ret < 0) { + fprintf(stderr, + "ospf_apiclient_connect: SO_REUSEADDR failed\n"); + close(fd1); + close(async_server_sock); + return NULL; + } #ifdef SO_REUSEPORT - ret = setsockopt (fd1, SOL_SOCKET, SO_REUSEPORT, - (void *) &on, sizeof (on)); - if (ret < 0) - { - fprintf (stderr, "ospf_apiclient_connect: SO_REUSEPORT failed\n"); - close (fd1); - close (async_server_sock); - return NULL; - } + ret = setsockopt(fd1, SOL_SOCKET, SO_REUSEPORT, (void *)&on, + sizeof(on)); + if (ret < 0) { + fprintf(stderr, + "ospf_apiclient_connect: SO_REUSEPORT failed\n"); + close(fd1); + close(async_server_sock); + return NULL; + } #endif /* SO_REUSEPORT */ - /* Bind sync socket to address structure. This is needed since we - want the sync port number on a fixed port number. The reverse - async channel will be at this port+1 */ + /* Bind sync socket to address structure. This is needed since we + want the sync port number on a fixed port number. The reverse + async channel will be at this port+1 */ - memset (&myaddr_sync, 0, sizeof (struct sockaddr_in)); - myaddr_sync.sin_family = AF_INET; - myaddr_sync.sin_port = htons (syncport); + memset(&myaddr_sync, 0, sizeof(struct sockaddr_in)); + myaddr_sync.sin_family = AF_INET; + myaddr_sync.sin_port = htons(syncport); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - myaddr_sync.sin_len = sizeof (struct sockaddr_in); + myaddr_sync.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - ret = bind (fd1, (struct sockaddr *) &myaddr_sync, size); - if (ret < 0) - { - fprintf (stderr, "ospf_apiclient_connect: bind sync socket failed\n"); - close (fd1); - close (async_server_sock); - return NULL; - } - - /* Prepare address structure for connect */ - memcpy (&myaddr_sync.sin_addr, hp->h_addr, hp->h_length); - myaddr_sync.sin_family = AF_INET; - myaddr_sync.sin_port = htons(ospf_apiclient_getport ()); + ret = bind(fd1, (struct sockaddr *)&myaddr_sync, size); + if (ret < 0) { + fprintf(stderr, + "ospf_apiclient_connect: bind sync socket failed\n"); + close(fd1); + close(async_server_sock); + return NULL; + } + + /* Prepare address structure for connect */ + memcpy(&myaddr_sync.sin_addr, hp->h_addr, hp->h_length); + myaddr_sync.sin_family = AF_INET; + myaddr_sync.sin_port = htons(ospf_apiclient_getport()); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - myaddr_sync.sin_len = sizeof (struct sockaddr_in); + myaddr_sync.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - /* Now establish synchronous channel with OSPF daemon */ - ret = connect (fd1, (struct sockaddr *) &myaddr_sync, - sizeof (struct sockaddr_in)); - if (ret < 0) - { - fprintf (stderr, "ospf_apiclient_connect: sync connect failed\n"); - close (async_server_sock); - close (fd1); - return NULL; - } - - /* Accept reverse connection */ - peeraddrlen = sizeof (struct sockaddr_in); - memset (&peeraddr, 0, peeraddrlen); - - fd2 = - accept (async_server_sock, (struct sockaddr *) &peeraddr, &peeraddrlen); - if (fd2 < 0) - { - fprintf (stderr, "ospf_apiclient_connect: accept async failed\n"); - close (async_server_sock); - close (fd1); - close (fd2); - return NULL; - } - - /* Server socket is not needed anymore since we are not accepting more - connections */ - close (async_server_sock); - - /* Create new client-side instance */ - new = XCALLOC (MTYPE_OSPF_APICLIENT, sizeof (struct ospf_apiclient)); - - /* Initialize socket descriptors for sync and async channels */ - new->fd_sync = fd1; - new->fd_async = fd2; - - return new; + /* Now establish synchronous channel with OSPF daemon */ + ret = connect(fd1, (struct sockaddr *)&myaddr_sync, + sizeof(struct sockaddr_in)); + if (ret < 0) { + fprintf(stderr, + "ospf_apiclient_connect: sync connect failed\n"); + close(async_server_sock); + close(fd1); + return NULL; + } + + /* Accept reverse connection */ + peeraddrlen = sizeof(struct sockaddr_in); + memset(&peeraddr, 0, peeraddrlen); + + fd2 = accept(async_server_sock, (struct sockaddr *)&peeraddr, + &peeraddrlen); + if (fd2 < 0) { + fprintf(stderr, + "ospf_apiclient_connect: accept async failed\n"); + close(async_server_sock); + close(fd1); + close(fd2); + return NULL; + } + + /* Server socket is not needed anymore since we are not accepting more + connections */ + close(async_server_sock); + + /* Create new client-side instance */ + new = XCALLOC(MTYPE_OSPF_APICLIENT, sizeof(struct ospf_apiclient)); + + /* Initialize socket descriptors for sync and async channels */ + new->fd_sync = fd1; + new->fd_async = fd2; + + return new; } -int -ospf_apiclient_close (struct ospf_apiclient *oclient) +int ospf_apiclient_close(struct ospf_apiclient *oclient) { - if (oclient->fd_sync >= 0) - { - close (oclient->fd_sync); - } + if (oclient->fd_sync >= 0) { + close(oclient->fd_sync); + } - if (oclient->fd_async >= 0) - { - close (oclient->fd_async); - } + if (oclient->fd_async >= 0) { + close(oclient->fd_async); + } - /* Free client structure */ - XFREE (MTYPE_OSPF_APICLIENT, oclient); - return 0; + /* Free client structure */ + XFREE(MTYPE_OSPF_APICLIENT, oclient); + return 0; } /* ----------------------------------------------------------- @@ -307,40 +300,39 @@ ospf_apiclient_close (struct ospf_apiclient *oclient) */ /* Send synchronous request, wait for reply */ -static int -ospf_apiclient_send_request (struct ospf_apiclient *oclient, struct msg *msg) +static int ospf_apiclient_send_request(struct ospf_apiclient *oclient, + struct msg *msg) { - u_int32_t reqseq; - struct msg_reply *msgreply; - int rc; + u_int32_t reqseq; + struct msg_reply *msgreply; + int rc; - /* NB: Given "msg" is freed inside this function. */ + /* NB: Given "msg" is freed inside this function. */ - /* Remember the sequence number of the request */ - reqseq = ntohl (msg->hdr.msgseq); + /* Remember the sequence number of the request */ + reqseq = ntohl(msg->hdr.msgseq); - /* Write message to OSPFd */ - rc = msg_write (oclient->fd_sync, msg); - msg_free (msg); + /* Write message to OSPFd */ + rc = msg_write(oclient->fd_sync, msg); + msg_free(msg); - if (rc < 0) - { - return -1; - } + if (rc < 0) { + return -1; + } - /* Wait for reply *//* NB: New "msg" is allocated by "msg_read()". */ - msg = msg_read (oclient->fd_sync); - if (!msg) - return -1; + /* Wait for reply */ /* NB: New "msg" is allocated by "msg_read()". */ + msg = msg_read(oclient->fd_sync); + if (!msg) + return -1; - assert (msg->hdr.msgtype == MSG_REPLY); - assert (ntohl (msg->hdr.msgseq) == reqseq); + assert(msg->hdr.msgtype == MSG_REPLY); + assert(ntohl(msg->hdr.msgseq) == reqseq); - msgreply = (struct msg_reply *) STREAM_DATA (msg->s); - rc = msgreply->errcode; - msg_free (msg); + msgreply = (struct msg_reply *)STREAM_DATA(msg->s); + rc = msgreply->errcode; + msg_free(msg); - return rc; + return rc; } @@ -349,23 +341,19 @@ ospf_apiclient_send_request (struct ospf_apiclient *oclient, struct msg *msg) * ----------------------------------------------------------- */ -static u_int32_t -ospf_apiclient_get_seqnr (void) +static u_int32_t ospf_apiclient_get_seqnr(void) { - static u_int32_t seqnr = MIN_SEQ; - u_int32_t tmp; - - tmp = seqnr; - /* Increment sequence number */ - if (seqnr < MAX_SEQ) - { - seqnr++; - } - else - { - seqnr = MIN_SEQ; - } - return tmp; + static u_int32_t seqnr = MIN_SEQ; + u_int32_t tmp; + + tmp = seqnr; + /* Increment sequence number */ + if (seqnr < MAX_SEQ) { + seqnr++; + } else { + seqnr = MIN_SEQ; + } + return tmp; } /* ----------------------------------------------------------- @@ -376,141 +364,132 @@ ospf_apiclient_get_seqnr (void) /* * Synchronous request to register opaque type. */ -int -ospf_apiclient_register_opaque_type (struct ospf_apiclient *cl, - u_char ltype, u_char otype) +int ospf_apiclient_register_opaque_type(struct ospf_apiclient *cl, u_char ltype, + u_char otype) { - struct msg *msg; - int rc; - - /* just put 1 as a sequence number. */ - msg = new_msg_register_opaque_type (ospf_apiclient_get_seqnr (), - ltype, otype); - if (!msg) - { - fprintf (stderr, "new_msg_register_opaque_type failed\n"); - return -1; - } - - rc = ospf_apiclient_send_request (cl, msg); - return rc; + struct msg *msg; + int rc; + + /* just put 1 as a sequence number. */ + msg = new_msg_register_opaque_type(ospf_apiclient_get_seqnr(), ltype, + otype); + if (!msg) { + fprintf(stderr, "new_msg_register_opaque_type failed\n"); + return -1; + } + + rc = ospf_apiclient_send_request(cl, msg); + return rc; } -/* +/* * Synchronous request to synchronize with OSPF's LSDB. * Two steps required: register_event in order to get * dynamic updates and LSDB_Sync. */ -int -ospf_apiclient_sync_lsdb (struct ospf_apiclient *oclient) +int ospf_apiclient_sync_lsdb(struct ospf_apiclient *oclient) { - struct msg *msg; - int rc; - struct lsa_filter_type filter; - - filter.typemask = 0xFFFF; /* all LSAs */ - filter.origin = ANY_ORIGIN; - filter.num_areas = 0; /* all Areas. */ - - msg = new_msg_register_event (ospf_apiclient_get_seqnr (), &filter); - if (!msg) - { - fprintf (stderr, "new_msg_register_event failed\n"); - return -1; - } - rc = ospf_apiclient_send_request (oclient, msg); - - if (rc != 0) - goto out; - - msg = new_msg_sync_lsdb (ospf_apiclient_get_seqnr (), &filter); - if (!msg) - { - fprintf (stderr, "new_msg_sync_lsdb failed\n"); - return -1; - } - rc = ospf_apiclient_send_request (oclient, msg); + struct msg *msg; + int rc; + struct lsa_filter_type filter; + + filter.typemask = 0xFFFF; /* all LSAs */ + filter.origin = ANY_ORIGIN; + filter.num_areas = 0; /* all Areas. */ + + msg = new_msg_register_event(ospf_apiclient_get_seqnr(), &filter); + if (!msg) { + fprintf(stderr, "new_msg_register_event failed\n"); + return -1; + } + rc = ospf_apiclient_send_request(oclient, msg); + + if (rc != 0) + goto out; + + msg = new_msg_sync_lsdb(ospf_apiclient_get_seqnr(), &filter); + if (!msg) { + fprintf(stderr, "new_msg_sync_lsdb failed\n"); + return -1; + } + rc = ospf_apiclient_send_request(oclient, msg); out: - return rc; + return rc; } -/* +/* * Synchronous request to originate or update an LSA. */ -int -ospf_apiclient_lsa_originate (struct ospf_apiclient *oclient, - struct in_addr ifaddr, - struct in_addr area_id, - u_char lsa_type, - u_char opaque_type, u_int32_t opaque_id, - void *opaquedata, int opaquelen) +int ospf_apiclient_lsa_originate(struct ospf_apiclient *oclient, + struct in_addr ifaddr, struct in_addr area_id, + u_char lsa_type, u_char opaque_type, + u_int32_t opaque_id, void *opaquedata, + int opaquelen) { - struct msg *msg; - int rc; - u_char buf[OSPF_MAX_LSA_SIZE]; - struct lsa_header *lsah; - u_int32_t tmp; - - - /* We can only originate opaque LSAs */ - if (!IS_OPAQUE_LSA (lsa_type)) - { - fprintf (stderr, "Cannot originate non-opaque LSA type %d\n", lsa_type); - return OSPF_API_ILLEGALLSATYPE; - } - - /* Make a new LSA from parameters */ - lsah = (struct lsa_header *) buf; - lsah->ls_age = 0; - lsah->options = 0; - lsah->type = lsa_type; - - tmp = SET_OPAQUE_LSID (opaque_type, opaque_id); - lsah->id.s_addr = htonl (tmp); - lsah->adv_router.s_addr = 0; - lsah->ls_seqnum = 0; - lsah->checksum = 0; - lsah->length = htons (sizeof (struct lsa_header) + opaquelen); - - memcpy (((u_char *) lsah) + sizeof (struct lsa_header), opaquedata, - opaquelen); - - msg = new_msg_originate_request (ospf_apiclient_get_seqnr (), - ifaddr, area_id, lsah); - if (!msg) - { - fprintf (stderr, "new_msg_originate_request failed\n"); - return OSPF_API_NOMEMORY; - } - - rc = ospf_apiclient_send_request (oclient, msg); - return rc; + struct msg *msg; + int rc; + u_char buf[OSPF_MAX_LSA_SIZE]; + struct lsa_header *lsah; + u_int32_t tmp; + + + /* We can only originate opaque LSAs */ + if (!IS_OPAQUE_LSA(lsa_type)) { + fprintf(stderr, "Cannot originate non-opaque LSA type %d\n", + lsa_type); + return OSPF_API_ILLEGALLSATYPE; + } + + /* Make a new LSA from parameters */ + lsah = (struct lsa_header *)buf; + lsah->ls_age = 0; + lsah->options = 0; + lsah->type = lsa_type; + + tmp = SET_OPAQUE_LSID(opaque_type, opaque_id); + lsah->id.s_addr = htonl(tmp); + lsah->adv_router.s_addr = 0; + lsah->ls_seqnum = 0; + lsah->checksum = 0; + lsah->length = htons(sizeof(struct lsa_header) + opaquelen); + + memcpy(((u_char *)lsah) + sizeof(struct lsa_header), opaquedata, + opaquelen); + + msg = new_msg_originate_request(ospf_apiclient_get_seqnr(), ifaddr, + area_id, lsah); + if (!msg) { + fprintf(stderr, "new_msg_originate_request failed\n"); + return OSPF_API_NOMEMORY; + } + + rc = ospf_apiclient_send_request(oclient, msg); + return rc; } -int -ospf_apiclient_lsa_delete (struct ospf_apiclient *oclient, - struct in_addr area_id, u_char lsa_type, - u_char opaque_type, u_int32_t opaque_id) +int ospf_apiclient_lsa_delete(struct ospf_apiclient *oclient, + struct in_addr area_id, u_char lsa_type, + u_char opaque_type, u_int32_t opaque_id) { - struct msg *msg; - int rc; - - /* Only opaque LSA can be deleted */ - if (!IS_OPAQUE_LSA (lsa_type)) - { - fprintf (stderr, "Cannot delete non-opaque LSA type %d\n", lsa_type); - return OSPF_API_ILLEGALLSATYPE; - } - - /* opaque_id is in host byte order and will be converted - * to network byte order by new_msg_delete_request */ - msg = new_msg_delete_request (ospf_apiclient_get_seqnr (), - area_id, lsa_type, opaque_type, opaque_id); - - rc = ospf_apiclient_send_request (oclient, msg); - return rc; + struct msg *msg; + int rc; + + /* Only opaque LSA can be deleted */ + if (!IS_OPAQUE_LSA(lsa_type)) { + fprintf(stderr, "Cannot delete non-opaque LSA type %d\n", + lsa_type); + return OSPF_API_ILLEGALLSATYPE; + } + + /* opaque_id is in host byte order and will be converted + * to network byte order by new_msg_delete_request */ + msg = new_msg_delete_request(ospf_apiclient_get_seqnr(), area_id, + lsa_type, opaque_type, opaque_id); + + rc = ospf_apiclient_send_request(oclient, msg); + return rc; } /* ----------------------------------------------------------- @@ -518,168 +497,155 @@ ospf_apiclient_lsa_delete (struct ospf_apiclient *oclient, * ----------------------------------------------------------- */ -static void -ospf_apiclient_handle_ready (struct ospf_apiclient *oclient, struct msg *msg) +static void ospf_apiclient_handle_ready(struct ospf_apiclient *oclient, + struct msg *msg) { - struct msg_ready_notify *r; - r = (struct msg_ready_notify *) STREAM_DATA (msg->s); - - /* Invoke registered callback function. */ - if (oclient->ready_notify) - { - (oclient->ready_notify) (r->lsa_type, r->opaque_type, r->addr); - } + struct msg_ready_notify *r; + r = (struct msg_ready_notify *)STREAM_DATA(msg->s); + + /* Invoke registered callback function. */ + if (oclient->ready_notify) { + (oclient->ready_notify)(r->lsa_type, r->opaque_type, r->addr); + } } -static void -ospf_apiclient_handle_new_if (struct ospf_apiclient *oclient, struct msg *msg) +static void ospf_apiclient_handle_new_if(struct ospf_apiclient *oclient, + struct msg *msg) { - struct msg_new_if *n; - n = (struct msg_new_if *) STREAM_DATA (msg->s); - - /* Invoke registered callback function. */ - if (oclient->new_if) - { - (oclient->new_if) (n->ifaddr, n->area_id); - } + struct msg_new_if *n; + n = (struct msg_new_if *)STREAM_DATA(msg->s); + + /* Invoke registered callback function. */ + if (oclient->new_if) { + (oclient->new_if)(n->ifaddr, n->area_id); + } } -static void -ospf_apiclient_handle_del_if (struct ospf_apiclient *oclient, struct msg *msg) +static void ospf_apiclient_handle_del_if(struct ospf_apiclient *oclient, + struct msg *msg) { - struct msg_del_if *d; - d = (struct msg_del_if *) STREAM_DATA (msg->s); - - /* Invoke registered callback function. */ - if (oclient->del_if) - { - (oclient->del_if) (d->ifaddr); - } + struct msg_del_if *d; + d = (struct msg_del_if *)STREAM_DATA(msg->s); + + /* Invoke registered callback function. */ + if (oclient->del_if) { + (oclient->del_if)(d->ifaddr); + } } -static void -ospf_apiclient_handle_ism_change (struct ospf_apiclient *oclient, - struct msg *msg) +static void ospf_apiclient_handle_ism_change(struct ospf_apiclient *oclient, + struct msg *msg) { - struct msg_ism_change *m; - m = (struct msg_ism_change *) STREAM_DATA (msg->s); - - /* Invoke registered callback function. */ - if (oclient->ism_change) - { - (oclient->ism_change) (m->ifaddr, m->area_id, m->status); - } + struct msg_ism_change *m; + m = (struct msg_ism_change *)STREAM_DATA(msg->s); + /* Invoke registered callback function. */ + if (oclient->ism_change) { + (oclient->ism_change)(m->ifaddr, m->area_id, m->status); + } } -static void -ospf_apiclient_handle_nsm_change (struct ospf_apiclient *oclient, - struct msg *msg) +static void ospf_apiclient_handle_nsm_change(struct ospf_apiclient *oclient, + struct msg *msg) { - struct msg_nsm_change *m; - m = (struct msg_nsm_change *) STREAM_DATA (msg->s); - - /* Invoke registered callback function. */ - if (oclient->nsm_change) - { - (oclient->nsm_change) (m->ifaddr, m->nbraddr, m->router_id, m->status); - } + struct msg_nsm_change *m; + m = (struct msg_nsm_change *)STREAM_DATA(msg->s); + + /* Invoke registered callback function. */ + if (oclient->nsm_change) { + (oclient->nsm_change)(m->ifaddr, m->nbraddr, m->router_id, + m->status); + } } -static void -ospf_apiclient_handle_lsa_update (struct ospf_apiclient *oclient, - struct msg *msg) +static void ospf_apiclient_handle_lsa_update(struct ospf_apiclient *oclient, + struct msg *msg) { - struct msg_lsa_change_notify *cn; - struct lsa_header *lsa; - int lsalen; - - cn = (struct msg_lsa_change_notify *) STREAM_DATA (msg->s); - - /* Extract LSA from message */ - lsalen = ntohs (cn->data.length); - lsa = XMALLOC (MTYPE_OSPF_APICLIENT, lsalen); - if (!lsa) - { - fprintf (stderr, "LSA update: Cannot allocate memory for LSA\n"); - return; - } - memcpy (lsa, &(cn->data), lsalen); - - /* Invoke registered update callback function */ - if (oclient->update_notify) - { - (oclient->update_notify) (cn->ifaddr, cn->area_id, - cn->is_self_originated, lsa); - } - - /* free memory allocated by ospf apiclient library */ - XFREE (MTYPE_OSPF_APICLIENT, lsa); + struct msg_lsa_change_notify *cn; + struct lsa_header *lsa; + int lsalen; + + cn = (struct msg_lsa_change_notify *)STREAM_DATA(msg->s); + + /* Extract LSA from message */ + lsalen = ntohs(cn->data.length); + lsa = XMALLOC(MTYPE_OSPF_APICLIENT, lsalen); + if (!lsa) { + fprintf(stderr, "LSA update: Cannot allocate memory for LSA\n"); + return; + } + memcpy(lsa, &(cn->data), lsalen); + + /* Invoke registered update callback function */ + if (oclient->update_notify) { + (oclient->update_notify)(cn->ifaddr, cn->area_id, + cn->is_self_originated, lsa); + } + + /* free memory allocated by ospf apiclient library */ + XFREE(MTYPE_OSPF_APICLIENT, lsa); } -static void -ospf_apiclient_handle_lsa_delete (struct ospf_apiclient *oclient, - struct msg *msg) +static void ospf_apiclient_handle_lsa_delete(struct ospf_apiclient *oclient, + struct msg *msg) { - struct msg_lsa_change_notify *cn; - struct lsa_header *lsa; - int lsalen; - - cn = (struct msg_lsa_change_notify *) STREAM_DATA (msg->s); - - /* Extract LSA from message */ - lsalen = ntohs (cn->data.length); - lsa = XMALLOC (MTYPE_OSPF_APICLIENT, lsalen); - if (!lsa) - { - fprintf (stderr, "LSA delete: Cannot allocate memory for LSA\n"); - return; - } - memcpy (lsa, &(cn->data), lsalen); - - /* Invoke registered update callback function */ - if (oclient->delete_notify) - { - (oclient->delete_notify) (cn->ifaddr, cn->area_id, - cn->is_self_originated, lsa); - } - - /* free memory allocated by ospf apiclient library */ - XFREE (MTYPE_OSPF_APICLIENT, lsa); + struct msg_lsa_change_notify *cn; + struct lsa_header *lsa; + int lsalen; + + cn = (struct msg_lsa_change_notify *)STREAM_DATA(msg->s); + + /* Extract LSA from message */ + lsalen = ntohs(cn->data.length); + lsa = XMALLOC(MTYPE_OSPF_APICLIENT, lsalen); + if (!lsa) { + fprintf(stderr, "LSA delete: Cannot allocate memory for LSA\n"); + return; + } + memcpy(lsa, &(cn->data), lsalen); + + /* Invoke registered update callback function */ + if (oclient->delete_notify) { + (oclient->delete_notify)(cn->ifaddr, cn->area_id, + cn->is_self_originated, lsa); + } + + /* free memory allocated by ospf apiclient library */ + XFREE(MTYPE_OSPF_APICLIENT, lsa); } -static void -ospf_apiclient_msghandle (struct ospf_apiclient *oclient, struct msg *msg) +static void ospf_apiclient_msghandle(struct ospf_apiclient *oclient, + struct msg *msg) { - /* Call message handler function. */ - switch (msg->hdr.msgtype) - { - case MSG_READY_NOTIFY: - ospf_apiclient_handle_ready (oclient, msg); - break; - case MSG_NEW_IF: - ospf_apiclient_handle_new_if (oclient, msg); - break; - case MSG_DEL_IF: - ospf_apiclient_handle_del_if (oclient, msg); - break; - case MSG_ISM_CHANGE: - ospf_apiclient_handle_ism_change (oclient, msg); - break; - case MSG_NSM_CHANGE: - ospf_apiclient_handle_nsm_change (oclient, msg); - break; - case MSG_LSA_UPDATE_NOTIFY: - ospf_apiclient_handle_lsa_update (oclient, msg); - break; - case MSG_LSA_DELETE_NOTIFY: - ospf_apiclient_handle_lsa_delete (oclient, msg); - break; - default: - fprintf (stderr, "ospf_apiclient_read: Unknown message type: %d\n", - msg->hdr.msgtype); - break; - } + /* Call message handler function. */ + switch (msg->hdr.msgtype) { + case MSG_READY_NOTIFY: + ospf_apiclient_handle_ready(oclient, msg); + break; + case MSG_NEW_IF: + ospf_apiclient_handle_new_if(oclient, msg); + break; + case MSG_DEL_IF: + ospf_apiclient_handle_del_if(oclient, msg); + break; + case MSG_ISM_CHANGE: + ospf_apiclient_handle_ism_change(oclient, msg); + break; + case MSG_NSM_CHANGE: + ospf_apiclient_handle_nsm_change(oclient, msg); + break; + case MSG_LSA_UPDATE_NOTIFY: + ospf_apiclient_handle_lsa_update(oclient, msg); + break; + case MSG_LSA_DELETE_NOTIFY: + ospf_apiclient_handle_lsa_delete(oclient, msg); + break; + default: + fprintf(stderr, + "ospf_apiclient_read: Unknown message type: %d\n", + msg->hdr.msgtype); + break; + } } /* ----------------------------------------------------------- @@ -687,48 +653,32 @@ ospf_apiclient_msghandle (struct ospf_apiclient *oclient, struct msg *msg) * ----------------------------------------------------------- */ -void -ospf_apiclient_register_callback (struct ospf_apiclient *oclient, - void (*ready_notify) (u_char lsa_type, - u_char opaque_type, - struct in_addr addr), - void (*new_if) (struct in_addr ifaddr, - struct in_addr area_id), - void (*del_if) (struct in_addr ifaddr), - void (*ism_change) (struct in_addr ifaddr, - struct in_addr area_id, - u_char status), - void (*nsm_change) (struct in_addr ifaddr, - struct in_addr nbraddr, - struct in_addr - router_id, - u_char status), - void (*update_notify) (struct in_addr - ifaddr, - struct in_addr - area_id, - u_char self_origin, - struct lsa_header * - lsa), - void (*delete_notify) (struct in_addr - ifaddr, - struct in_addr - area_id, - u_char self_origin, - struct lsa_header * - lsa)) +void ospf_apiclient_register_callback( + struct ospf_apiclient *oclient, + void (*ready_notify)(u_char lsa_type, u_char opaque_type, + struct in_addr addr), + void (*new_if)(struct in_addr ifaddr, struct in_addr area_id), + void (*del_if)(struct in_addr ifaddr), + void (*ism_change)(struct in_addr ifaddr, struct in_addr area_id, + u_char status), + void (*nsm_change)(struct in_addr ifaddr, struct in_addr nbraddr, + struct in_addr router_id, u_char status), + void (*update_notify)(struct in_addr ifaddr, struct in_addr area_id, + u_char self_origin, struct lsa_header *lsa), + void (*delete_notify)(struct in_addr ifaddr, struct in_addr area_id, + u_char self_origin, struct lsa_header *lsa)) { - assert (oclient); - assert (update_notify); - - /* Register callback function */ - oclient->ready_notify = ready_notify; - oclient->new_if = new_if; - oclient->del_if = del_if; - oclient->ism_change = ism_change; - oclient->nsm_change = nsm_change; - oclient->update_notify = update_notify; - oclient->delete_notify = delete_notify; + assert(oclient); + assert(update_notify); + + /* Register callback function */ + oclient->ready_notify = ready_notify; + oclient->new_if = new_if; + oclient->del_if = del_if; + oclient->ism_change = ism_change; + oclient->nsm_change = nsm_change; + oclient->update_notify = update_notify; + oclient->delete_notify = delete_notify; } /* ----------------------------------------------------------- @@ -736,25 +686,23 @@ ospf_apiclient_register_callback (struct ospf_apiclient *oclient, * ----------------------------------------------------------- */ -int -ospf_apiclient_handle_async (struct ospf_apiclient *oclient) +int ospf_apiclient_handle_async(struct ospf_apiclient *oclient) { - struct msg *msg; + struct msg *msg; - /* Get a message */ - msg = msg_read (oclient->fd_async); + /* Get a message */ + msg = msg_read(oclient->fd_async); - if (!msg) - { - /* Connection broke down */ - return -1; - } + if (!msg) { + /* Connection broke down */ + return -1; + } - /* Handle message */ - ospf_apiclient_msghandle (oclient, msg); + /* Handle message */ + ospf_apiclient_msghandle(oclient, msg); - /* Don't forget to free this message */ - msg_free (msg); + /* Don't forget to free this message */ + msg_free(msg); - return 0; + return 0; } diff --git a/ospfclient/ospf_apiclient.h b/ospfclient/ospf_apiclient.h index 5882ac349..916a2d8ed 100644 --- a/ospfclient/ospf_apiclient.h +++ b/ospfclient/ospf_apiclient.h @@ -23,28 +23,25 @@ #define _OSPF_APICLIENT_H /* Structure for the OSPF API client */ -struct ospf_apiclient -{ - - /* Sockets for sync requests and async notifications */ - int fd_sync; - int fd_async; - - /* Pointer to callback functions */ - void (*ready_notify) (u_char lsa_type, u_char opaque_type, - struct in_addr addr); - void (*new_if) (struct in_addr ifaddr, struct in_addr area_id); - void (*del_if) (struct in_addr ifaddr); - void (*ism_change) (struct in_addr ifaddr, struct in_addr area_id, - u_char status); - void (*nsm_change) (struct in_addr ifaddr, struct in_addr nbraddr, - struct in_addr router_id, u_char status); - void (*update_notify) (struct in_addr ifaddr, struct in_addr area_id, - u_char self_origin, - struct lsa_header * lsa); - void (*delete_notify) (struct in_addr ifaddr, struct in_addr area_id, - u_char self_origin, - struct lsa_header * lsa); +struct ospf_apiclient { + + /* Sockets for sync requests and async notifications */ + int fd_sync; + int fd_async; + + /* Pointer to callback functions */ + void (*ready_notify)(u_char lsa_type, u_char opaque_type, + struct in_addr addr); + void (*new_if)(struct in_addr ifaddr, struct in_addr area_id); + void (*del_if)(struct in_addr ifaddr); + void (*ism_change)(struct in_addr ifaddr, struct in_addr area_id, + u_char status); + void (*nsm_change)(struct in_addr ifaddr, struct in_addr nbraddr, + struct in_addr router_id, u_char status); + void (*update_notify)(struct in_addr ifaddr, struct in_addr area_id, + u_char self_origin, struct lsa_header *lsa); + void (*delete_notify)(struct in_addr ifaddr, struct in_addr area_id, + u_char self_origin, struct lsa_header *lsa); }; @@ -54,79 +51,53 @@ struct ospf_apiclient /* Open connection to OSPF daemon. Two ports will be allocated on client, sync channel at syncport and reverse channel at syncport+1 */ -struct ospf_apiclient *ospf_apiclient_connect (char *host, int syncport); +struct ospf_apiclient *ospf_apiclient_connect(char *host, int syncport); /* Shutdown connection to OSPF daemon. */ -int ospf_apiclient_close (struct ospf_apiclient *oclient); +int ospf_apiclient_close(struct ospf_apiclient *oclient); /* Synchronous request to register opaque type. */ -int ospf_apiclient_register_opaque_type (struct ospf_apiclient *oclient, - u_char ltype, u_char otype); +int ospf_apiclient_register_opaque_type(struct ospf_apiclient *oclient, + u_char ltype, u_char otype); /* Synchronous request to register event mask. */ -int ospf_apiclient_register_events (struct ospf_apiclient *oclient, - u_int32_t mask); +int ospf_apiclient_register_events(struct ospf_apiclient *oclient, + u_int32_t mask); /* Register callback functions.*/ -void ospf_apiclient_register_callback (struct ospf_apiclient *oclient, - void (*ready_notify) (u_char lsa_type, - u_char - opaque_type, - struct in_addr - addr), - void (*new_if) (struct in_addr ifaddr, - struct in_addr - area_id), - void (*del_if) (struct in_addr ifaddr), - void (*ism_change) (struct in_addr - ifaddr, - struct in_addr - area_id, - u_char status), - void (*nsm_change) (struct in_addr - ifaddr, - struct in_addr - nbraddr, - struct in_addr - router_id, - u_char status), - void (*update_notify) (struct in_addr - ifaddr, - struct in_addr - area_id, - u_char selforig, - struct - lsa_header * - lsa), - void (*delete_notify) (struct in_addr - ifaddr, - struct in_addr - area_id, - u_char selforig, - struct - lsa_header * - lsa)); +void ospf_apiclient_register_callback( + struct ospf_apiclient *oclient, + void (*ready_notify)(u_char lsa_type, u_char opaque_type, + struct in_addr addr), + void (*new_if)(struct in_addr ifaddr, struct in_addr area_id), + void (*del_if)(struct in_addr ifaddr), + void (*ism_change)(struct in_addr ifaddr, struct in_addr area_id, + u_char status), + void (*nsm_change)(struct in_addr ifaddr, struct in_addr nbraddr, + struct in_addr router_id, u_char status), + void (*update_notify)(struct in_addr ifaddr, struct in_addr area_id, + u_char selforig, struct lsa_header *lsa), + void (*delete_notify)(struct in_addr ifaddr, struct in_addr area_id, + u_char selforig, struct lsa_header *lsa)); /* Synchronous request to synchronize LSDB. */ -int ospf_apiclient_sync_lsdb (struct ospf_apiclient *oclient); +int ospf_apiclient_sync_lsdb(struct ospf_apiclient *oclient); /* Synchronous request to originate or update opaque LSA. */ -int -ospf_apiclient_lsa_originate(struct ospf_apiclient *oclient, - struct in_addr ifaddr, - struct in_addr area_id, - u_char lsa_type, - u_char opaque_type, u_int32_t opaque_id, - void *opaquedata, int opaquelen); +int ospf_apiclient_lsa_originate(struct ospf_apiclient *oclient, + struct in_addr ifaddr, struct in_addr area_id, + u_char lsa_type, u_char opaque_type, + u_int32_t opaque_id, void *opaquedata, + int opaquelen); /* Synchronous request to delete opaque LSA. Parameter opaque_id is in host byte order */ -int ospf_apiclient_lsa_delete (struct ospf_apiclient *oclient, - struct in_addr area_id, u_char lsa_type, - u_char opaque_type, u_int32_t opaque_id); +int ospf_apiclient_lsa_delete(struct ospf_apiclient *oclient, + struct in_addr area_id, u_char lsa_type, + u_char opaque_type, u_int32_t opaque_id); /* Fetch async message and handle it */ -int ospf_apiclient_handle_async (struct ospf_apiclient *oclient); +int ospf_apiclient_handle_async(struct ospf_apiclient *oclient); #endif /* _OSPF_APICLIENT_H */ diff --git a/ospfclient/ospfclient.c b/ospfclient/ospfclient.c index 63fcafb73..5713105f4 100644 --- a/ospfclient/ospfclient.c +++ b/ospfclient/ospfclient.c @@ -15,7 +15,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -/* +/* * Simple program to demonstrate how OSPF API can be used. This * application retrieves the LSDB from the OSPF daemon and then * originates, updates and finally deletes an application-specific @@ -41,17 +41,14 @@ #include "ospfd/ospf_api.h" #include "ospf_apiclient.h" -/* privileges struct. +/* privileges struct. * set cap_num_* and uid/gid to nothing to use NULL privs * as ospfapiclient links in libospf.a which uses privs. */ -struct zebra_privs_t ospfd_privs = -{ - .user = NULL, - .group = NULL, - .cap_num_p = 0, - .cap_num_i = 0 -}; +struct zebra_privs_t ospfd_privs = {.user = NULL, + .group = NULL, + .cap_num_p = 0, + .cap_num_i = 0}; /* The following includes are specific to this application. For example it uses threads from libfrr, however your application is @@ -73,298 +70,275 @@ struct ospf_apiclient *oclient; char **args; /* Our opaque LSAs have the following format. */ -struct my_opaque_lsa -{ - struct lsa_header hdr; /* include common LSA header */ - u_char data[4]; /* our own data format then follows here */ +struct my_opaque_lsa { + struct lsa_header hdr; /* include common LSA header */ + u_char data[4]; /* our own data format then follows here */ }; /* --------------------------------------------------------- - * Threads for asynchronous messages and LSA update/delete + * Threads for asynchronous messages and LSA update/delete * --------------------------------------------------------- */ -static int -lsa_delete (struct thread *t) +static int lsa_delete(struct thread *t) { - struct ospf_apiclient *oclient; - struct in_addr area_id; - int rc; - - oclient = THREAD_ARG (t); - - rc = inet_aton (args[6], &area_id); - if (rc <= 0) - { - printf("Address Specified: %s is invalid\n", args[6]); - return rc; - } - - printf ("Deleting LSA... "); - rc = ospf_apiclient_lsa_delete (oclient, - area_id, - atoi (args[2]), /* lsa type */ - atoi (args[3]), /* opaque type */ - atoi (args[4])); /* opaque ID */ - printf ("done, return code is = %d\n", rc); - return rc; + struct ospf_apiclient *oclient; + struct in_addr area_id; + int rc; + + oclient = THREAD_ARG(t); + + rc = inet_aton(args[6], &area_id); + if (rc <= 0) { + printf("Address Specified: %s is invalid\n", args[6]); + return rc; + } + + printf("Deleting LSA... "); + rc = ospf_apiclient_lsa_delete(oclient, area_id, + atoi(args[2]), /* lsa type */ + atoi(args[3]), /* opaque type */ + atoi(args[4])); /* opaque ID */ + printf("done, return code is = %d\n", rc); + return rc; } -static int -lsa_inject (struct thread *t) +static int lsa_inject(struct thread *t) { - struct ospf_apiclient *cl; - struct in_addr ifaddr; - struct in_addr area_id; - u_char lsa_type; - u_char opaque_type; - u_int32_t opaque_id; - void *opaquedata; - int opaquelen; - - static u_int32_t counter = 1; /* Incremented each time invoked */ - int rc; - - cl = THREAD_ARG (t); - - rc = inet_aton (args[5], &ifaddr); - if (rc <= 0) - { - printf ("Ifaddr specified %s is invalid\n", args[5]); - return rc; - } - - rc = inet_aton (args[6], &area_id); - if (rc <= 0) - { - printf( "Area ID specified %s is invalid\n", args[6]); - return rc; - } - lsa_type = atoi (args[2]); - opaque_type = atoi (args[3]); - opaque_id = atoi (args[4]); - opaquedata = &counter; - opaquelen = sizeof (u_int32_t); - - printf ("Originating/updating LSA with counter=%d... ", counter); - rc = ospf_apiclient_lsa_originate(cl, ifaddr, area_id, - lsa_type, - opaque_type, opaque_id, - opaquedata, opaquelen); - - printf ("done, return code is %d\n", rc); - - counter++; - - return 0; + struct ospf_apiclient *cl; + struct in_addr ifaddr; + struct in_addr area_id; + u_char lsa_type; + u_char opaque_type; + u_int32_t opaque_id; + void *opaquedata; + int opaquelen; + + static u_int32_t counter = 1; /* Incremented each time invoked */ + int rc; + + cl = THREAD_ARG(t); + + rc = inet_aton(args[5], &ifaddr); + if (rc <= 0) { + printf("Ifaddr specified %s is invalid\n", args[5]); + return rc; + } + + rc = inet_aton(args[6], &area_id); + if (rc <= 0) { + printf("Area ID specified %s is invalid\n", args[6]); + return rc; + } + lsa_type = atoi(args[2]); + opaque_type = atoi(args[3]); + opaque_id = atoi(args[4]); + opaquedata = &counter; + opaquelen = sizeof(u_int32_t); + + printf("Originating/updating LSA with counter=%d... ", counter); + rc = ospf_apiclient_lsa_originate(cl, ifaddr, area_id, lsa_type, + opaque_type, opaque_id, opaquedata, + opaquelen); + + printf("done, return code is %d\n", rc); + + counter++; + + return 0; } /* This thread handles asynchronous messages coming in from the OSPF API server */ -static int -lsa_read (struct thread *thread) +static int lsa_read(struct thread *thread) { - struct ospf_apiclient *oclient; - int fd; - int ret; + struct ospf_apiclient *oclient; + int fd; + int ret; - printf ("lsa_read called\n"); + printf("lsa_read called\n"); - oclient = THREAD_ARG (thread); - fd = THREAD_FD (thread); + oclient = THREAD_ARG(thread); + fd = THREAD_FD(thread); - /* Handle asynchronous message */ - ret = ospf_apiclient_handle_async (oclient); - if (ret < 0) { - printf ("Connection closed, exiting..."); - exit(0); - } + /* Handle asynchronous message */ + ret = ospf_apiclient_handle_async(oclient); + if (ret < 0) { + printf("Connection closed, exiting..."); + exit(0); + } - /* Reschedule read thread */ - thread_add_read(master, lsa_read, oclient, fd, NULL); + /* Reschedule read thread */ + thread_add_read(master, lsa_read, oclient, fd, NULL); - return 0; + return 0; } /* --------------------------------------------------------- - * Callback functions for asynchronous events + * Callback functions for asynchronous events * --------------------------------------------------------- */ -static void -lsa_update_callback (struct in_addr ifaddr, struct in_addr area_id, - u_char is_self_originated, - struct lsa_header *lsa) +static void lsa_update_callback(struct in_addr ifaddr, struct in_addr area_id, + u_char is_self_originated, + struct lsa_header *lsa) { - printf ("lsa_update_callback: "); - printf ("ifaddr: %s ", inet_ntoa (ifaddr)); - printf ("area: %s\n", inet_ntoa (area_id)); - printf ("is_self_origin: %u\n", is_self_originated); - - /* It is important to note that lsa_header does indeed include the - header and the LSA payload. To access the payload, first check - the LSA type and then typecast lsa into the corresponding type, - e.g.: - - if (lsa->type == OSPF_ROUTER_LSA) { - struct router_lsa *rl = (struct router_lsa) lsa; - ... - u_int16_t links = rl->links; - ... - } - */ - - ospf_lsa_header_dump (lsa); + printf("lsa_update_callback: "); + printf("ifaddr: %s ", inet_ntoa(ifaddr)); + printf("area: %s\n", inet_ntoa(area_id)); + printf("is_self_origin: %u\n", is_self_originated); + + /* It is important to note that lsa_header does indeed include the + header and the LSA payload. To access the payload, first check + the LSA type and then typecast lsa into the corresponding type, + e.g.: + + if (lsa->type == OSPF_ROUTER_LSA) { + struct router_lsa *rl = (struct router_lsa) lsa; + ... + u_int16_t links = rl->links; + ... + } + */ + + ospf_lsa_header_dump(lsa); } -static void -lsa_delete_callback (struct in_addr ifaddr, struct in_addr area_id, - u_char is_self_originated, - struct lsa_header *lsa) +static void lsa_delete_callback(struct in_addr ifaddr, struct in_addr area_id, + u_char is_self_originated, + struct lsa_header *lsa) { - printf ("lsa_delete_callback: "); - printf ("ifaddr: %s ", inet_ntoa (ifaddr)); - printf ("area: %s\n", inet_ntoa (area_id)); - printf ("is_self_origin: %u\n", is_self_originated); + printf("lsa_delete_callback: "); + printf("ifaddr: %s ", inet_ntoa(ifaddr)); + printf("area: %s\n", inet_ntoa(area_id)); + printf("is_self_origin: %u\n", is_self_originated); - ospf_lsa_header_dump (lsa); + ospf_lsa_header_dump(lsa); } -static void -ready_callback (u_char lsa_type, u_char opaque_type, struct in_addr addr) +static void ready_callback(u_char lsa_type, u_char opaque_type, + struct in_addr addr) { - printf ("ready_callback: lsa_type: %d opaque_type: %d addr=%s\n", - lsa_type, opaque_type, inet_ntoa (addr)); + printf("ready_callback: lsa_type: %d opaque_type: %d addr=%s\n", + lsa_type, opaque_type, inet_ntoa(addr)); - /* Schedule opaque LSA originate in 5 secs */ - thread_add_timer(master, lsa_inject, oclient, 5, NULL); + /* Schedule opaque LSA originate in 5 secs */ + thread_add_timer(master, lsa_inject, oclient, 5, NULL); - /* Schedule opaque LSA update with new value */ - thread_add_timer(master, lsa_inject, oclient, 10, NULL); + /* Schedule opaque LSA update with new value */ + thread_add_timer(master, lsa_inject, oclient, 10, NULL); - /* Schedule delete */ - thread_add_timer(master, lsa_delete, oclient, 30, NULL); + /* Schedule delete */ + thread_add_timer(master, lsa_delete, oclient, 30, NULL); } -static void -new_if_callback (struct in_addr ifaddr, struct in_addr area_id) +static void new_if_callback(struct in_addr ifaddr, struct in_addr area_id) { - printf ("new_if_callback: ifaddr: %s ", inet_ntoa (ifaddr)); - printf ("area_id: %s\n", inet_ntoa (area_id)); + printf("new_if_callback: ifaddr: %s ", inet_ntoa(ifaddr)); + printf("area_id: %s\n", inet_ntoa(area_id)); } -static void -del_if_callback (struct in_addr ifaddr) +static void del_if_callback(struct in_addr ifaddr) { - printf ("new_if_callback: ifaddr: %s\n ", inet_ntoa (ifaddr)); + printf("new_if_callback: ifaddr: %s\n ", inet_ntoa(ifaddr)); } -static void -ism_change_callback (struct in_addr ifaddr, struct in_addr area_id, - u_char state) +static void ism_change_callback(struct in_addr ifaddr, struct in_addr area_id, + u_char state) { - printf ("ism_change: ifaddr: %s ", inet_ntoa (ifaddr)); - printf ("area_id: %s\n", inet_ntoa (area_id)); - printf ("state: %d [%s]\n", state, lookup_msg(ospf_ism_state_msg, state, NULL)); + printf("ism_change: ifaddr: %s ", inet_ntoa(ifaddr)); + printf("area_id: %s\n", inet_ntoa(area_id)); + printf("state: %d [%s]\n", state, + lookup_msg(ospf_ism_state_msg, state, NULL)); } -static void -nsm_change_callback (struct in_addr ifaddr, struct in_addr nbraddr, - struct in_addr router_id, u_char state) +static void nsm_change_callback(struct in_addr ifaddr, struct in_addr nbraddr, + struct in_addr router_id, u_char state) { - printf ("nsm_change: ifaddr: %s ", inet_ntoa (ifaddr)); - printf ("nbraddr: %s\n", inet_ntoa (nbraddr)); - printf ("router_id: %s\n", inet_ntoa (router_id)); - printf ("state: %d [%s]\n", state, lookup_msg(ospf_nsm_state_msg, state, NULL)); + printf("nsm_change: ifaddr: %s ", inet_ntoa(ifaddr)); + printf("nbraddr: %s\n", inet_ntoa(nbraddr)); + printf("router_id: %s\n", inet_ntoa(router_id)); + printf("state: %d [%s]\n", state, + lookup_msg(ospf_nsm_state_msg, state, NULL)); } /* --------------------------------------------------------- - * Main program + * Main program * --------------------------------------------------------- */ static int usage(void) { - printf("Usage: ospfclient \n"); - printf("where ospfd : router where API-enabled OSPF daemon is running\n"); - printf(" lsatype : either 9, 10, or 11 depending on flooding scope\n"); - printf(" opaquetype: 0-255 (e.g., experimental applications use > 128)\n"); - printf(" opaqueid : arbitrary application instance (24 bits)\n"); - printf(" ifaddr : interface IP address (for type 9) otherwise ignored\n"); - printf(" areaid : area in IP address format (for type 10) otherwise ignored\n"); - - exit(1); + printf("Usage: ospfclient \n"); + printf("where ospfd : router where API-enabled OSPF daemon is running\n"); + printf(" lsatype : either 9, 10, or 11 depending on flooding scope\n"); + printf(" opaquetype: 0-255 (e.g., experimental applications use > 128)\n"); + printf(" opaqueid : arbitrary application instance (24 bits)\n"); + printf(" ifaddr : interface IP address (for type 9) otherwise ignored\n"); + printf(" areaid : area in IP address format (for type 10) otherwise ignored\n"); + + exit(1); } -int -main (int argc, char *argv[]) +int main(int argc, char *argv[]) { - struct thread thread; - - args = argv; - - /* ospfclient should be started with the following arguments: - * - * (1) host (2) lsa_type (3) opaque_type (4) opaque_id (5) if_addr - * (6) area_id - * - * host: name or IP of host where ospfd is running - * lsa_type: 9, 10, or 11 - * opaque_type: 0-255 (e.g., experimental applications use > 128) - * opaque_id: arbitrary application instance (24 bits) - * if_addr: interface IP address (for type 9) otherwise ignored - * area_id: area in IP address format (for type 10) otherwise ignored - */ - - if (argc != 7) - { - usage(); - } - - /* Initialization */ - zprivs_init (&ospfd_privs); - master = thread_master_create(NULL); - - /* Open connection to OSPF daemon */ - oclient = ospf_apiclient_connect (args[1], ASYNCPORT); - if (!oclient) - { - printf ("Connecting to OSPF daemon on %s failed!\n", - args[1]); - exit (1); - } - - /* Register callback functions. */ - ospf_apiclient_register_callback (oclient, - ready_callback, - new_if_callback, - del_if_callback, - ism_change_callback, - nsm_change_callback, - lsa_update_callback, - lsa_delete_callback); - - /* Register LSA type and opaque type. */ - ospf_apiclient_register_opaque_type (oclient, atoi (args[2]), - atoi (args[3])); - - /* Synchronize database with OSPF daemon. */ - ospf_apiclient_sync_lsdb (oclient); - - /* Schedule thread that handles asynchronous messages */ - thread_add_read(master, lsa_read, oclient, oclient->fd_async, NULL); - - /* Now connection is established, run loop */ - while (1) - { - thread_fetch (master, &thread); - thread_call (&thread); - } - - /* Never reached */ - return 0; + struct thread thread; + + args = argv; + + /* ospfclient should be started with the following arguments: + * + * (1) host (2) lsa_type (3) opaque_type (4) opaque_id (5) if_addr + * (6) area_id + * + * host: name or IP of host where ospfd is running + * lsa_type: 9, 10, or 11 + * opaque_type: 0-255 (e.g., experimental applications use > 128) + * opaque_id: arbitrary application instance (24 bits) + * if_addr: interface IP address (for type 9) otherwise ignored + * area_id: area in IP address format (for type 10) otherwise ignored + */ + + if (argc != 7) { + usage(); + } + + /* Initialization */ + zprivs_init(&ospfd_privs); + master = thread_master_create(NULL); + + /* Open connection to OSPF daemon */ + oclient = ospf_apiclient_connect(args[1], ASYNCPORT); + if (!oclient) { + printf("Connecting to OSPF daemon on %s failed!\n", args[1]); + exit(1); + } + + /* Register callback functions. */ + ospf_apiclient_register_callback( + oclient, ready_callback, new_if_callback, del_if_callback, + ism_change_callback, nsm_change_callback, lsa_update_callback, + lsa_delete_callback); + + /* Register LSA type and opaque type. */ + ospf_apiclient_register_opaque_type(oclient, atoi(args[2]), + atoi(args[3])); + + /* Synchronize database with OSPF daemon. */ + ospf_apiclient_sync_lsdb(oclient); + + /* Schedule thread that handles asynchronous messages */ + thread_add_read(master, lsa_read, oclient, oclient->fd_async, NULL); + + /* Now connection is established, run loop */ + while (1) { + thread_fetch(master, &thread); + thread_call(&thread); + } + + /* Never reached */ + return 0; } - diff --git a/ospfd/ospf_abr.c b/ospfd/ospf_abr.c index 06038fed7..c6d4364fa 100644 --- a/ospfd/ospf_abr.c +++ b/ospfd/ospf_abr.c @@ -50,1667 +50,1648 @@ #include "ospfd/ospf_zebra.h" #include "ospfd/ospf_dump.h" -static struct ospf_area_range * -ospf_area_range_new (struct prefix_ipv4 *p) +static struct ospf_area_range *ospf_area_range_new(struct prefix_ipv4 *p) { - struct ospf_area_range *range; + struct ospf_area_range *range; - range = XCALLOC (MTYPE_OSPF_AREA_RANGE, sizeof (struct ospf_area_range)); - range->addr = p->prefix; - range->masklen = p->prefixlen; - range->cost_config = OSPF_AREA_RANGE_COST_UNSPEC; + range = XCALLOC(MTYPE_OSPF_AREA_RANGE, sizeof(struct ospf_area_range)); + range->addr = p->prefix; + range->masklen = p->prefixlen; + range->cost_config = OSPF_AREA_RANGE_COST_UNSPEC; - return range; + return range; } -static void -ospf_area_range_free (struct ospf_area_range *range) +static void ospf_area_range_free(struct ospf_area_range *range) { - XFREE (MTYPE_OSPF_AREA_RANGE, range); + XFREE(MTYPE_OSPF_AREA_RANGE, range); } -static void -ospf_area_range_add (struct ospf_area *area, struct ospf_area_range *range) +static void ospf_area_range_add(struct ospf_area *area, + struct ospf_area_range *range) { - struct route_node *rn; - struct prefix_ipv4 p; - - p.family = AF_INET; - p.prefixlen = range->masklen; - p.prefix = range->addr; - - rn = route_node_get (area->ranges, (struct prefix *)&p); - if (rn->info) - route_unlock_node (rn); - else - rn->info = range; + struct route_node *rn; + struct prefix_ipv4 p; + + p.family = AF_INET; + p.prefixlen = range->masklen; + p.prefix = range->addr; + + rn = route_node_get(area->ranges, (struct prefix *)&p); + if (rn->info) + route_unlock_node(rn); + else + rn->info = range; } -static void -ospf_area_range_delete (struct ospf_area *area, struct route_node *rn) +static void ospf_area_range_delete(struct ospf_area *area, + struct route_node *rn) { - struct ospf_area_range *range = rn->info; + struct ospf_area_range *range = rn->info; - if (range->specifics != 0) - ospf_delete_discard_route (area->ospf->new_table, - (struct prefix_ipv4 *) &rn->p); + if (range->specifics != 0) + ospf_delete_discard_route(area->ospf->new_table, + (struct prefix_ipv4 *)&rn->p); - ospf_area_range_free (range); - rn->info = NULL; - route_unlock_node (rn); - route_unlock_node (rn); + ospf_area_range_free(range); + rn->info = NULL; + route_unlock_node(rn); + route_unlock_node(rn); } -struct ospf_area_range * -ospf_area_range_lookup (struct ospf_area *area, struct prefix_ipv4 *p) +struct ospf_area_range *ospf_area_range_lookup(struct ospf_area *area, + struct prefix_ipv4 *p) { - struct route_node *rn; - - rn = route_node_lookup (area->ranges, (struct prefix *)p); - if (rn) - { - route_unlock_node (rn); - return rn->info; - } - return NULL; + struct route_node *rn; + + rn = route_node_lookup(area->ranges, (struct prefix *)p); + if (rn) { + route_unlock_node(rn); + return rn->info; + } + return NULL; } -struct ospf_area_range * -ospf_area_range_lookup_next (struct ospf_area *area, - struct in_addr *range_net, - int first) +struct ospf_area_range *ospf_area_range_lookup_next(struct ospf_area *area, + struct in_addr *range_net, + int first) { - struct route_node *rn; - struct prefix_ipv4 p; - struct ospf_area_range *find; - - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - p.prefix = *range_net; - - if (first) - rn = route_top (area->ranges); - else - { - rn = route_node_get (area->ranges, (struct prefix *) &p); - rn = route_next (rn); - } - - for (; rn; rn = route_next (rn)) - if (rn->info) - break; - - if (rn && rn->info) - { - find = rn->info; - *range_net = rn->p.u.prefix4; - route_unlock_node (rn); - return find; - } - return NULL; + struct route_node *rn; + struct prefix_ipv4 p; + struct ospf_area_range *find; + + p.family = AF_INET; + p.prefixlen = IPV4_MAX_BITLEN; + p.prefix = *range_net; + + if (first) + rn = route_top(area->ranges); + else { + rn = route_node_get(area->ranges, (struct prefix *)&p); + rn = route_next(rn); + } + + for (; rn; rn = route_next(rn)) + if (rn->info) + break; + + if (rn && rn->info) { + find = rn->info; + *range_net = rn->p.u.prefix4; + route_unlock_node(rn); + return find; + } + return NULL; } -static struct ospf_area_range * -ospf_area_range_match (struct ospf_area *area, struct prefix_ipv4 *p) +static struct ospf_area_range *ospf_area_range_match(struct ospf_area *area, + struct prefix_ipv4 *p) { - struct route_node *node; - - node = route_node_match (area->ranges, (struct prefix *) p); - if (node) - { - route_unlock_node (node); - return node->info; - } - return NULL; + struct route_node *node; + + node = route_node_match(area->ranges, (struct prefix *)p); + if (node) { + route_unlock_node(node); + return node->info; + } + return NULL; } -struct ospf_area_range * -ospf_area_range_match_any (struct ospf *ospf, struct prefix_ipv4 *p) +struct ospf_area_range *ospf_area_range_match_any(struct ospf *ospf, + struct prefix_ipv4 *p) { - struct ospf_area_range *range; - struct ospf_area *area; - struct listnode *node; + struct ospf_area_range *range; + struct ospf_area *area; + struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - if ((range = ospf_area_range_match (area, p))) - return range; + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) + if ((range = ospf_area_range_match(area, p))) + return range; - return NULL; + return NULL; } -int -ospf_area_range_active (struct ospf_area_range *range) +int ospf_area_range_active(struct ospf_area_range *range) { - return range->specifics; + return range->specifics; } -static int -ospf_area_actively_attached (struct ospf_area *area) +static int ospf_area_actively_attached(struct ospf_area *area) { - return area->act_ints; + return area->act_ints; } -int -ospf_area_range_set (struct ospf *ospf, struct in_addr area_id, - struct prefix_ipv4 *p, int advertise) +int ospf_area_range_set(struct ospf *ospf, struct in_addr area_id, + struct prefix_ipv4 *p, int advertise) { - struct ospf_area *area; - struct ospf_area_range *range; - - area = ospf_area_get (ospf, area_id); - if (area == NULL) - return 0; - - range = ospf_area_range_lookup (area, p); - if (range != NULL) - { - if ((CHECK_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE) - && !CHECK_FLAG (advertise, OSPF_AREA_RANGE_ADVERTISE)) - || (!CHECK_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE) - && CHECK_FLAG (advertise, OSPF_AREA_RANGE_ADVERTISE))) - ospf_schedule_abr_task (ospf); - } - else - { - range = ospf_area_range_new (p); - ospf_area_range_add (area, range); - ospf_schedule_abr_task (ospf); - } - - if (CHECK_FLAG (advertise, OSPF_AREA_RANGE_ADVERTISE)) - SET_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE); - else - UNSET_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE); - - return 1; + struct ospf_area *area; + struct ospf_area_range *range; + + area = ospf_area_get(ospf, area_id); + if (area == NULL) + return 0; + + range = ospf_area_range_lookup(area, p); + if (range != NULL) { + if ((CHECK_FLAG(range->flags, OSPF_AREA_RANGE_ADVERTISE) + && !CHECK_FLAG(advertise, OSPF_AREA_RANGE_ADVERTISE)) + || (!CHECK_FLAG(range->flags, OSPF_AREA_RANGE_ADVERTISE) + && CHECK_FLAG(advertise, OSPF_AREA_RANGE_ADVERTISE))) + ospf_schedule_abr_task(ospf); + } else { + range = ospf_area_range_new(p); + ospf_area_range_add(area, range); + ospf_schedule_abr_task(ospf); + } + + if (CHECK_FLAG(advertise, OSPF_AREA_RANGE_ADVERTISE)) + SET_FLAG(range->flags, OSPF_AREA_RANGE_ADVERTISE); + else + UNSET_FLAG(range->flags, OSPF_AREA_RANGE_ADVERTISE); + + return 1; } -int -ospf_area_range_cost_set (struct ospf *ospf, struct in_addr area_id, - struct prefix_ipv4 *p, u_int32_t cost) +int ospf_area_range_cost_set(struct ospf *ospf, struct in_addr area_id, + struct prefix_ipv4 *p, u_int32_t cost) { - struct ospf_area *area; - struct ospf_area_range *range; + struct ospf_area *area; + struct ospf_area_range *range; - area = ospf_area_get (ospf, area_id); - if (area == NULL) - return 0; + area = ospf_area_get(ospf, area_id); + if (area == NULL) + return 0; - range = ospf_area_range_lookup (area, p); - if (range == NULL) - return 0; + range = ospf_area_range_lookup(area, p); + if (range == NULL) + return 0; - if (range->cost_config != cost) - { - range->cost_config = cost; - if (ospf_area_range_active (range)) - ospf_schedule_abr_task (ospf); - } + if (range->cost_config != cost) { + range->cost_config = cost; + if (ospf_area_range_active(range)) + ospf_schedule_abr_task(ospf); + } - return 1; + return 1; } -int -ospf_area_range_unset (struct ospf *ospf, struct in_addr area_id, - struct prefix_ipv4 *p) +int ospf_area_range_unset(struct ospf *ospf, struct in_addr area_id, + struct prefix_ipv4 *p) { - struct ospf_area *area; - struct route_node *rn; + struct ospf_area *area; + struct route_node *rn; - area = ospf_area_lookup_by_area_id (ospf, area_id); - if (area == NULL) - return 0; + area = ospf_area_lookup_by_area_id(ospf, area_id); + if (area == NULL) + return 0; - rn = route_node_lookup (area->ranges, (struct prefix*)p); - if (rn == NULL) - return 0; + rn = route_node_lookup(area->ranges, (struct prefix *)p); + if (rn == NULL) + return 0; - if (ospf_area_range_active (rn->info)) - ospf_schedule_abr_task (ospf); + if (ospf_area_range_active(rn->info)) + ospf_schedule_abr_task(ospf); - ospf_area_range_delete (area, rn); + ospf_area_range_delete(area, rn); - return 1; + return 1; } -int -ospf_area_range_substitute_set (struct ospf *ospf, struct in_addr area_id, - struct prefix_ipv4 *p, struct prefix_ipv4 *s) +int ospf_area_range_substitute_set(struct ospf *ospf, struct in_addr area_id, + struct prefix_ipv4 *p, struct prefix_ipv4 *s) { - struct ospf_area *area; - struct ospf_area_range *range; - - area = ospf_area_get (ospf, area_id); - range = ospf_area_range_lookup (area, p); - - if (range != NULL) - { - if (!CHECK_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE) || - !CHECK_FLAG (range->flags, OSPF_AREA_RANGE_SUBSTITUTE)) - ospf_schedule_abr_task (ospf); - } - else - { - range = ospf_area_range_new (p); - ospf_area_range_add (area, range); - ospf_schedule_abr_task (ospf); - } - - SET_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE); - SET_FLAG (range->flags, OSPF_AREA_RANGE_SUBSTITUTE); - range->subst_addr = s->prefix; - range->subst_masklen = s->prefixlen; - - return 1; + struct ospf_area *area; + struct ospf_area_range *range; + + area = ospf_area_get(ospf, area_id); + range = ospf_area_range_lookup(area, p); + + if (range != NULL) { + if (!CHECK_FLAG(range->flags, OSPF_AREA_RANGE_ADVERTISE) + || !CHECK_FLAG(range->flags, OSPF_AREA_RANGE_SUBSTITUTE)) + ospf_schedule_abr_task(ospf); + } else { + range = ospf_area_range_new(p); + ospf_area_range_add(area, range); + ospf_schedule_abr_task(ospf); + } + + SET_FLAG(range->flags, OSPF_AREA_RANGE_ADVERTISE); + SET_FLAG(range->flags, OSPF_AREA_RANGE_SUBSTITUTE); + range->subst_addr = s->prefix; + range->subst_masklen = s->prefixlen; + + return 1; } -int -ospf_area_range_substitute_unset (struct ospf *ospf, struct in_addr area_id, - struct prefix_ipv4 *p) +int ospf_area_range_substitute_unset(struct ospf *ospf, struct in_addr area_id, + struct prefix_ipv4 *p) { - struct ospf_area *area; - struct ospf_area_range *range; + struct ospf_area *area; + struct ospf_area_range *range; - area = ospf_area_lookup_by_area_id (ospf, area_id); - if (area == NULL) - return 0; + area = ospf_area_lookup_by_area_id(ospf, area_id); + if (area == NULL) + return 0; - range = ospf_area_range_lookup (area, p); - if (range == NULL) - return 0; + range = ospf_area_range_lookup(area, p); + if (range == NULL) + return 0; - if (CHECK_FLAG (range->flags, OSPF_AREA_RANGE_SUBSTITUTE)) - if (ospf_area_range_active (range)) - ospf_schedule_abr_task (ospf); + if (CHECK_FLAG(range->flags, OSPF_AREA_RANGE_SUBSTITUTE)) + if (ospf_area_range_active(range)) + ospf_schedule_abr_task(ospf); - UNSET_FLAG (range->flags, OSPF_AREA_RANGE_SUBSTITUTE); - range->subst_addr.s_addr = 0; - range->subst_masklen = 0; + UNSET_FLAG(range->flags, OSPF_AREA_RANGE_SUBSTITUTE); + range->subst_addr.s_addr = 0; + range->subst_masklen = 0; - return 1; + return 1; } -int -ospf_act_bb_connection (struct ospf *ospf) +int ospf_act_bb_connection(struct ospf *ospf) { - if (ospf->backbone == NULL) - return 0; + if (ospf->backbone == NULL) + return 0; - return ospf->backbone->full_nbrs; + return ospf->backbone->full_nbrs; } /* Determine whether this router is elected translator or not for area */ -static int -ospf_abr_nssa_am_elected (struct ospf_area *area) +static int ospf_abr_nssa_am_elected(struct ospf_area *area) { - struct route_node *rn; - struct ospf_lsa *lsa; - struct router_lsa *rlsa; - struct in_addr *best = NULL; - - LSDB_LOOP ( ROUTER_LSDB (area), rn, lsa) - { - /* sanity checks */ - if (!lsa - || (lsa->data->type != OSPF_ROUTER_LSA) - || IS_LSA_SELF (lsa)) - continue; - - rlsa = (struct router_lsa *) lsa->data; - - /* ignore non-ABR routers */ - if (!IS_ROUTER_LSA_BORDER (rlsa)) - continue; - - /* Router has Nt flag - always translate */ - if (IS_ROUTER_LSA_NT (rlsa)) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_nssa_am_elected: " - "router %s asserts Nt", - inet_ntoa (lsa->data->id) ); - return 0; - } - - if (best == NULL) - best = &lsa->data->id; - else - if (IPV4_ADDR_CMP (&best->s_addr, &lsa->data->id.s_addr) < 0) - best = &lsa->data->id; - } - - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_nssa_am_elected: best electable ABR is: %s", - (best) ? inet_ntoa (*best) : "" ); - - if (best == NULL) - return 1; - - if (IPV4_ADDR_CMP (&best->s_addr, &area->ospf->router_id.s_addr) < 0) - return 1; - else - return 0; + struct route_node *rn; + struct ospf_lsa *lsa; + struct router_lsa *rlsa; + struct in_addr *best = NULL; + + LSDB_LOOP(ROUTER_LSDB(area), rn, lsa) + { + /* sanity checks */ + if (!lsa || (lsa->data->type != OSPF_ROUTER_LSA) + || IS_LSA_SELF(lsa)) + continue; + + rlsa = (struct router_lsa *)lsa->data; + + /* ignore non-ABR routers */ + if (!IS_ROUTER_LSA_BORDER(rlsa)) + continue; + + /* Router has Nt flag - always translate */ + if (IS_ROUTER_LSA_NT(rlsa)) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_abr_nssa_am_elected: " + "router %s asserts Nt", + inet_ntoa(lsa->data->id)); + return 0; + } + + if (best == NULL) + best = &lsa->data->id; + else if (IPV4_ADDR_CMP(&best->s_addr, &lsa->data->id.s_addr) + < 0) + best = &lsa->data->id; + } + + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_abr_nssa_am_elected: best electable ABR is: %s", + (best) ? inet_ntoa(*best) : ""); + + if (best == NULL) + return 1; + + if (IPV4_ADDR_CMP(&best->s_addr, &area->ospf->router_id.s_addr) < 0) + return 1; + else + return 0; } /* Check NSSA ABR status * assumes there are nssa areas */ -static void -ospf_abr_nssa_check_status (struct ospf *ospf) +static void ospf_abr_nssa_check_status(struct ospf *ospf) { - struct ospf_area *area; - struct listnode *lnode, *nnode; - - for (ALL_LIST_ELEMENTS (ospf->areas, lnode, nnode, area)) - { - u_char old_state = area->NSSATranslatorState; - - if (area->external_routing != OSPF_AREA_NSSA) - continue; - - if (IS_DEBUG_OSPF (nssa, NSSA)) - zlog_debug ("ospf_abr_nssa_check_status: " - "checking area %s", - inet_ntoa (area->area_id)); - - if (!IS_OSPF_ABR (area->ospf)) - { - if (IS_DEBUG_OSPF (nssa, NSSA)) - zlog_debug ("ospf_abr_nssa_check_status: " - "not ABR"); - area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED; - } - else - { - switch (area->NSSATranslatorRole) - { - case OSPF_NSSA_ROLE_NEVER: - /* We never Translate Type-7 LSA. */ - /* TODO: check previous state and flush? */ - if (IS_DEBUG_OSPF (nssa, NSSA)) - zlog_debug ("ospf_abr_nssa_check_status: " - "never translate"); - area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED; - break; - - case OSPF_NSSA_ROLE_ALWAYS: - /* We always translate if we are an ABR - * TODO: originate new LSAs if state change? - * or let the nssa abr task take care of it? - */ - if (IS_DEBUG_OSPF (nssa, NSSA)) - zlog_debug ("ospf_abr_nssa_check_status: " - "translate always"); - area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_ENABLED; - break; - - case OSPF_NSSA_ROLE_CANDIDATE: - /* We are a candidate for Translation */ - if (ospf_abr_nssa_am_elected (area) > 0) - { - area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_ENABLED; - if (IS_DEBUG_OSPF (nssa, NSSA)) - zlog_debug ("ospf_abr_nssa_check_status: " - "elected translator"); - } - else - { - area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED; - if (IS_DEBUG_OSPF (nssa, NSSA)) - zlog_debug ("ospf_abr_nssa_check_status: " "not elected"); - } - break; - } - } - /* RFC3101, 3.1: - * All NSSA border routers must set the E-bit in the Type-1 router-LSAs - * of their directly attached non-stub areas, even when they are not - * translating. - */ - if (old_state != area->NSSATranslatorState) - { - if (old_state == OSPF_NSSA_TRANSLATE_DISABLED) - ospf_asbr_status_update (ospf, ++ospf->redistribute); - else if (area->NSSATranslatorState == OSPF_NSSA_TRANSLATE_DISABLED) - ospf_asbr_status_update (ospf, --ospf->redistribute); + struct ospf_area *area; + struct listnode *lnode, *nnode; + + for (ALL_LIST_ELEMENTS(ospf->areas, lnode, nnode, area)) { + u_char old_state = area->NSSATranslatorState; + + if (area->external_routing != OSPF_AREA_NSSA) + continue; + + if (IS_DEBUG_OSPF(nssa, NSSA)) + zlog_debug( + "ospf_abr_nssa_check_status: " + "checking area %s", + inet_ntoa(area->area_id)); + + if (!IS_OSPF_ABR(area->ospf)) { + if (IS_DEBUG_OSPF(nssa, NSSA)) + zlog_debug( + "ospf_abr_nssa_check_status: " + "not ABR"); + area->NSSATranslatorState = + OSPF_NSSA_TRANSLATE_DISABLED; + } else { + switch (area->NSSATranslatorRole) { + case OSPF_NSSA_ROLE_NEVER: + /* We never Translate Type-7 LSA. */ + /* TODO: check previous state and flush? */ + if (IS_DEBUG_OSPF(nssa, NSSA)) + zlog_debug( + "ospf_abr_nssa_check_status: " + "never translate"); + area->NSSATranslatorState = + OSPF_NSSA_TRANSLATE_DISABLED; + break; + + case OSPF_NSSA_ROLE_ALWAYS: + /* We always translate if we are an ABR + * TODO: originate new LSAs if state change? + * or let the nssa abr task take care of it? + */ + if (IS_DEBUG_OSPF(nssa, NSSA)) + zlog_debug( + "ospf_abr_nssa_check_status: " + "translate always"); + area->NSSATranslatorState = + OSPF_NSSA_TRANSLATE_ENABLED; + break; + + case OSPF_NSSA_ROLE_CANDIDATE: + /* We are a candidate for Translation */ + if (ospf_abr_nssa_am_elected(area) > 0) { + area->NSSATranslatorState = + OSPF_NSSA_TRANSLATE_ENABLED; + if (IS_DEBUG_OSPF(nssa, NSSA)) + zlog_debug( + "ospf_abr_nssa_check_status: " + "elected translator"); + } else { + area->NSSATranslatorState = + OSPF_NSSA_TRANSLATE_DISABLED; + if (IS_DEBUG_OSPF(nssa, NSSA)) + zlog_debug( + "ospf_abr_nssa_check_status: " + "not elected"); + } + break; + } + } + /* RFC3101, 3.1: + * All NSSA border routers must set the E-bit in the Type-1 + * router-LSAs + * of their directly attached non-stub areas, even when they are + * not + * translating. + */ + if (old_state != area->NSSATranslatorState) { + if (old_state == OSPF_NSSA_TRANSLATE_DISABLED) + ospf_asbr_status_update(ospf, + ++ospf->redistribute); + else if (area->NSSATranslatorState + == OSPF_NSSA_TRANSLATE_DISABLED) + ospf_asbr_status_update(ospf, + --ospf->redistribute); + } } - } } /* Check area border router status. */ -void -ospf_check_abr_status (struct ospf *ospf) +void ospf_check_abr_status(struct ospf *ospf) { - struct ospf_area *area; - struct listnode *node, *nnode; - int bb_configured = 0; - int bb_act_attached = 0; - int areas_configured = 0; - int areas_act_attached = 0; - u_char new_flags = ospf->flags; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_check_abr_status(): Start"); - - for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) - { - if (listcount (area->oiflist)) - { - areas_configured++; - - if (OSPF_IS_AREA_BACKBONE (area)) - bb_configured = 1; + struct ospf_area *area; + struct listnode *node, *nnode; + int bb_configured = 0; + int bb_act_attached = 0; + int areas_configured = 0; + int areas_act_attached = 0; + u_char new_flags = ospf->flags; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_check_abr_status(): Start"); + + for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { + if (listcount(area->oiflist)) { + areas_configured++; + + if (OSPF_IS_AREA_BACKBONE(area)) + bb_configured = 1; + } + + if (ospf_area_actively_attached(area)) { + areas_act_attached++; + + if (OSPF_IS_AREA_BACKBONE(area)) + bb_act_attached = 1; + } } - if (ospf_area_actively_attached (area)) - { - areas_act_attached++; - - if (OSPF_IS_AREA_BACKBONE (area)) - bb_act_attached = 1; + if (IS_DEBUG_OSPF_EVENT) { + zlog_debug("ospf_check_abr_status(): looked through areas"); + zlog_debug("ospf_check_abr_status(): bb_configured: %d", + bb_configured); + zlog_debug("ospf_check_abr_status(): bb_act_attached: %d", + bb_act_attached); + zlog_debug("ospf_check_abr_status(): areas_configured: %d", + areas_configured); + zlog_debug("ospf_check_abr_status(): areas_act_attached: %d", + areas_act_attached); + } + + switch (ospf->abr_type) { + case OSPF_ABR_SHORTCUT: + case OSPF_ABR_STAND: + if (areas_act_attached > 1) + SET_FLAG(new_flags, OSPF_FLAG_ABR); + else + UNSET_FLAG(new_flags, OSPF_FLAG_ABR); + break; + + case OSPF_ABR_IBM: + if ((areas_act_attached > 1) && bb_configured) + SET_FLAG(new_flags, OSPF_FLAG_ABR); + else + UNSET_FLAG(new_flags, OSPF_FLAG_ABR); + break; + + case OSPF_ABR_CISCO: + if ((areas_configured > 1) && bb_act_attached) + SET_FLAG(new_flags, OSPF_FLAG_ABR); + else + UNSET_FLAG(new_flags, OSPF_FLAG_ABR); + break; + default: + break; + } + + if (new_flags != ospf->flags) { + ospf_spf_calculate_schedule(ospf, SPF_FLAG_ABR_STATUS_CHANGE); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_check_abr_status(): new router flags: %x", + new_flags); + ospf->flags = new_flags; + ospf_router_lsa_update(ospf); } - } - - if (IS_DEBUG_OSPF_EVENT) - { - zlog_debug ("ospf_check_abr_status(): looked through areas"); - zlog_debug ("ospf_check_abr_status(): bb_configured: %d", bb_configured); - zlog_debug ("ospf_check_abr_status(): bb_act_attached: %d", - bb_act_attached); - zlog_debug ("ospf_check_abr_status(): areas_configured: %d", - areas_configured); - zlog_debug ("ospf_check_abr_status(): areas_act_attached: %d", - areas_act_attached); - } - - switch (ospf->abr_type) - { - case OSPF_ABR_SHORTCUT: - case OSPF_ABR_STAND: - if (areas_act_attached > 1) - SET_FLAG (new_flags, OSPF_FLAG_ABR); - else - UNSET_FLAG (new_flags, OSPF_FLAG_ABR); - break; - - case OSPF_ABR_IBM: - if ((areas_act_attached > 1) && bb_configured) - SET_FLAG (new_flags, OSPF_FLAG_ABR); - else - UNSET_FLAG (new_flags, OSPF_FLAG_ABR); - break; - - case OSPF_ABR_CISCO: - if ((areas_configured > 1) && bb_act_attached) - SET_FLAG (new_flags, OSPF_FLAG_ABR); - else - UNSET_FLAG (new_flags, OSPF_FLAG_ABR); - break; - default: - break; - } - - if (new_flags != ospf->flags) - { - ospf_spf_calculate_schedule (ospf, SPF_FLAG_ABR_STATUS_CHANGE); - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_check_abr_status(): new router flags: %x",new_flags); - ospf->flags = new_flags; - ospf_router_lsa_update (ospf); - } } -static void -ospf_abr_update_aggregate (struct ospf_area_range *range, - struct ospf_route *or, struct ospf_area *area) +static void ospf_abr_update_aggregate(struct ospf_area_range *range, + struct ospf_route * or, + struct ospf_area *area) { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_update_aggregate(): Start"); - - if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED) && - (range->cost != OSPF_STUB_MAX_METRIC_SUMMARY_COST)) - { - range->cost = OSPF_STUB_MAX_METRIC_SUMMARY_COST; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_update_aggregate(): use summary max-metric 0x%08x", - range->cost); - } - else if (range->cost_config != OSPF_AREA_RANGE_COST_UNSPEC) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_update_aggregate(): use configured cost %d", - range->cost_config); - - range->cost = range->cost_config; - } - else - { - if (range->specifics == 0) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_update_aggregate(): use or->cost %d", - or->cost); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_update_aggregate(): Start"); - range->cost = or->cost; /* 1st time get 1st cost */ - } + if (CHECK_FLAG(area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED) + && (range->cost != OSPF_STUB_MAX_METRIC_SUMMARY_COST)) { + range->cost = OSPF_STUB_MAX_METRIC_SUMMARY_COST; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_update_aggregate(): use summary max-metric 0x%08x", + range->cost); + } else if (range->cost_config != OSPF_AREA_RANGE_COST_UNSPEC) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_update_aggregate(): use configured cost %d", + range->cost_config); - if (or->cost > range->cost) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_update_aggregate(): update to %d", or->cost); + range->cost = range->cost_config; + } else { + if (range->specifics == 0) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_update_aggregate(): use or->cost %d", + or->cost); + + range->cost = or->cost; /* 1st time get 1st cost */ + } - range->cost = or->cost; - } - } + if (or->cost > range->cost) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_update_aggregate(): update to %d", + or->cost); - range->specifics++; + range->cost = or->cost; + } + } + + range->specifics++; } -static void -set_metric (struct ospf_lsa *lsa, u_int32_t metric) +static void set_metric(struct ospf_lsa *lsa, u_int32_t metric) { - struct summary_lsa *header; - u_char *mp; - metric = htonl (metric); - mp = (u_char *) &metric; - mp++; - header = (struct summary_lsa *) lsa->data; - memcpy(header->metric, mp, 3); + struct summary_lsa *header; + u_char *mp; + metric = htonl(metric); + mp = (u_char *)&metric; + mp++; + header = (struct summary_lsa *)lsa->data; + memcpy(header->metric, mp, 3); } /* ospf_abr_translate_nssa */ -static int -ospf_abr_translate_nssa (struct ospf_area *area, struct ospf_lsa *lsa) +static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa) { - /* Incoming Type-7 or later aggregated Type-7 - * - * LSA is skipped if P-bit is off. - * LSA is aggregated if within range. - * - * The Type-7 is translated, Installed/Approved as a Type-5 into - * global LSDB, then Flooded through AS - * - * Later, any Unapproved Translated Type-5's are flushed/discarded - */ - - struct ospf_lsa *old = NULL, - *new = NULL; - struct as_external_lsa *ext7; - struct prefix_ipv4 p; - - if (! CHECK_FLAG (lsa->data->options, OSPF_OPTION_NP)) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_translate_nssa(): LSA Id %s, P-bit off, NO Translation", - inet_ntoa (lsa->data->id)); - return 1; - } - - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_translate_nssa(): LSA Id %s, TRANSLATING 7 to 5", - inet_ntoa (lsa->data->id)); - - ext7 = (struct as_external_lsa *)(lsa->data); - p.prefix = lsa->data->id; - p.prefixlen = ip_masklen (ext7->mask); - - if (ext7->e[0].fwd_addr.s_addr == OSPF_DEFAULT_DESTINATION) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_translate_nssa(): LSA Id %s, " - "Forward address is 0, NO Translation", - inet_ntoa (lsa->data->id)); - return 1; - } - - /* try find existing AS-External LSA for this prefix */ - - old = ospf_external_info_find_lsa (area->ospf, &p); - - if (old) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_translate_nssa(): " - "found old translated LSA Id %s, refreshing", - inet_ntoa (old->data->id)); - - /* refresh */ - new = ospf_translated_nssa_refresh (area->ospf, lsa, old); - if (!new) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_translate_nssa(): " - "could not refresh translated LSA Id %s", - inet_ntoa (old->data->id)); - } - } - else - { - /* no existing external route for this LSA Id - * originate translated LSA - */ - - if ((new = ospf_translated_nssa_originate (area->ospf, lsa)) - == NULL) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_translate_nssa(): Could not translate " - "Type-7 for %s to Type-5", - inet_ntoa (lsa->data->id)); - return 1; - } - } - - /* Area where Aggregate testing will be inserted, just like summary - advertisements */ - /* ospf_abr_check_nssa_range (p_arg, lsa-> cost, lsa -> area); */ - - return 0; + /* Incoming Type-7 or later aggregated Type-7 + * + * LSA is skipped if P-bit is off. + * LSA is aggregated if within range. + * + * The Type-7 is translated, Installed/Approved as a Type-5 into + * global LSDB, then Flooded through AS + * + * Later, any Unapproved Translated Type-5's are flushed/discarded + */ + + struct ospf_lsa *old = NULL, *new = NULL; + struct as_external_lsa *ext7; + struct prefix_ipv4 p; + + if (!CHECK_FLAG(lsa->data->options, OSPF_OPTION_NP)) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_abr_translate_nssa(): LSA Id %s, P-bit off, NO Translation", + inet_ntoa(lsa->data->id)); + return 1; + } + + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_abr_translate_nssa(): LSA Id %s, TRANSLATING 7 to 5", + inet_ntoa(lsa->data->id)); + + ext7 = (struct as_external_lsa *)(lsa->data); + p.prefix = lsa->data->id; + p.prefixlen = ip_masklen(ext7->mask); + + if (ext7->e[0].fwd_addr.s_addr == OSPF_DEFAULT_DESTINATION) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_abr_translate_nssa(): LSA Id %s, " + "Forward address is 0, NO Translation", + inet_ntoa(lsa->data->id)); + return 1; + } + + /* try find existing AS-External LSA for this prefix */ + + old = ospf_external_info_find_lsa(area->ospf, &p); + + if (old) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_abr_translate_nssa(): " + "found old translated LSA Id %s, refreshing", + inet_ntoa(old->data->id)); + + /* refresh */ + new = ospf_translated_nssa_refresh(area->ospf, lsa, old); + if (!new) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_abr_translate_nssa(): " + "could not refresh translated LSA Id %s", + inet_ntoa(old->data->id)); + } + } else { + /* no existing external route for this LSA Id + * originate translated LSA + */ + + if ((new = ospf_translated_nssa_originate(area->ospf, lsa)) + == NULL) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_abr_translate_nssa(): Could not translate " + "Type-7 for %s to Type-5", + inet_ntoa(lsa->data->id)); + return 1; + } + } + + /* Area where Aggregate testing will be inserted, just like summary + advertisements */ + /* ospf_abr_check_nssa_range (p_arg, lsa-> cost, lsa -> area); */ + + return 0; } -static void -ospf_abr_translate_nssa_range (struct prefix_ipv4 *p, u_int32_t cost) +static void ospf_abr_translate_nssa_range(struct prefix_ipv4 *p, u_int32_t cost) { - /* The Type-7 is created from the aggregated prefix and forwarded - for lsa installation and flooding... to be added... */ + /* The Type-7 is created from the aggregated prefix and forwarded + for lsa installation and flooding... to be added... */ } -void -ospf_abr_announce_network_to_area (struct prefix_ipv4 *p, u_int32_t cost, - struct ospf_area *area) +void ospf_abr_announce_network_to_area(struct prefix_ipv4 *p, u_int32_t cost, + struct ospf_area *area) { - struct ospf_lsa *lsa, *old = NULL; - struct summary_lsa *sl = NULL; - u_int32_t full_cost; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_network_to_area(): Start"); - - if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED)) - full_cost = OSPF_STUB_MAX_METRIC_SUMMARY_COST; - else - full_cost = cost; - - old = ospf_lsa_lookup_by_prefix (area->lsdb, OSPF_SUMMARY_LSA, - (struct prefix_ipv4 *) p, - area->ospf->router_id); - if (old) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_network_to_area(): old summary found"); - - sl = (struct summary_lsa *) old->data; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_network_to_area(): " - "old metric: %d, new metric: %d", - GET_METRIC (sl->metric), cost); - - if ((GET_METRIC (sl->metric) == full_cost) && - ((old->flags & OSPF_LSA_IN_MAXAGE) == 0)) - { - /* unchanged. simply reapprove it */ - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_network_to_area(): " - "old summary approved"); - SET_FLAG (old->flags, OSPF_LSA_APPROVED); - } - else - { - /* LSA is changed, refresh it */ - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_network_to_area(): " - "refreshing summary"); - set_metric (old, full_cost); - lsa = ospf_lsa_refresh (area->ospf, old); - - if (!lsa) - { - char buf[PREFIX2STR_BUFFER]; - - prefix2str ((struct prefix *) p, buf, sizeof(buf)); - zlog_warn ("%s: Could not refresh %s to %s", - __func__, - buf, - inet_ntoa (area->area_id)); - return; - } - - SET_FLAG (lsa->flags, OSPF_LSA_APPROVED); - /* This will flood through area. */ - } - } - else - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_network_to_area(): " - "creating new summary"); - lsa = ospf_summary_lsa_originate ( (struct prefix_ipv4 *)p, full_cost, area); - /* This will flood through area. */ - - if (!lsa) - { - char buf[PREFIX2STR_BUFFER]; - - prefix2str ((struct prefix *)p, buf, sizeof(buf)); - zlog_warn ("%s: Could not originate %s to %s", - __func__, - buf, - inet_ntoa (area->area_id)); - return; + struct ospf_lsa *lsa, *old = NULL; + struct summary_lsa *sl = NULL; + u_int32_t full_cost; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_announce_network_to_area(): Start"); + + if (CHECK_FLAG(area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED)) + full_cost = OSPF_STUB_MAX_METRIC_SUMMARY_COST; + else + full_cost = cost; + + old = ospf_lsa_lookup_by_prefix(area->lsdb, OSPF_SUMMARY_LSA, + (struct prefix_ipv4 *)p, + area->ospf->router_id); + if (old) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_network_to_area(): old summary found"); + + sl = (struct summary_lsa *)old->data; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_network_to_area(): " + "old metric: %d, new metric: %d", + GET_METRIC(sl->metric), cost); + + if ((GET_METRIC(sl->metric) == full_cost) + && ((old->flags & OSPF_LSA_IN_MAXAGE) == 0)) { + /* unchanged. simply reapprove it */ + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_network_to_area(): " + "old summary approved"); + SET_FLAG(old->flags, OSPF_LSA_APPROVED); + } else { + /* LSA is changed, refresh it */ + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_network_to_area(): " + "refreshing summary"); + set_metric(old, full_cost); + lsa = ospf_lsa_refresh(area->ospf, old); + + if (!lsa) { + char buf[PREFIX2STR_BUFFER]; + + prefix2str((struct prefix *)p, buf, + sizeof(buf)); + zlog_warn("%s: Could not refresh %s to %s", + __func__, buf, + inet_ntoa(area->area_id)); + return; + } + + SET_FLAG(lsa->flags, OSPF_LSA_APPROVED); + /* This will flood through area. */ + } + } else { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_network_to_area(): " + "creating new summary"); + lsa = ospf_summary_lsa_originate((struct prefix_ipv4 *)p, + full_cost, area); + /* This will flood through area. */ + + if (!lsa) { + char buf[PREFIX2STR_BUFFER]; + + prefix2str((struct prefix *)p, buf, sizeof(buf)); + zlog_warn("%s: Could not originate %s to %s", __func__, + buf, inet_ntoa(area->area_id)); + return; + } + + SET_FLAG(lsa->flags, OSPF_LSA_APPROVED); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_network_to_area(): " + "flooding new version of summary"); } - - SET_FLAG (lsa->flags, OSPF_LSA_APPROVED); - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_network_to_area(): " - "flooding new version of summary"); - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_network_to_area(): Stop"); + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_announce_network_to_area(): Stop"); } -static int -ospf_abr_nexthops_belong_to_area (struct ospf_route *or, - struct ospf_area *area) +static int ospf_abr_nexthops_belong_to_area(struct ospf_route * or, + struct ospf_area *area) { - struct listnode *node, *nnode; - struct ospf_path *path; - struct ospf_interface *oi; + struct listnode *node, *nnode; + struct ospf_path *path; + struct ospf_interface *oi; - for (ALL_LIST_ELEMENTS_RO (or->paths, node, path)) - for (ALL_LIST_ELEMENTS_RO (area->oiflist, nnode, oi)) - if (oi->ifp && oi->ifp->ifindex == path->ifindex) - return 1; + for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) + for (ALL_LIST_ELEMENTS_RO(area->oiflist, nnode, oi)) + if (oi->ifp && oi->ifp->ifindex == path->ifindex) + return 1; - return 0; + return 0; } -static int -ospf_abr_should_accept (struct prefix_ipv4 *p, struct ospf_area *area) +static int ospf_abr_should_accept(struct prefix_ipv4 *p, struct ospf_area *area) { - if (IMPORT_NAME (area)) - { - if (IMPORT_LIST (area) == NULL) - IMPORT_LIST (area) = access_list_lookup (AFI_IP, IMPORT_NAME (area)); - - if (IMPORT_LIST (area)) - if (access_list_apply (IMPORT_LIST (area), p) == FILTER_DENY) - return 0; - } + if (IMPORT_NAME(area)) { + if (IMPORT_LIST(area) == NULL) + IMPORT_LIST(area) = + access_list_lookup(AFI_IP, IMPORT_NAME(area)); + + if (IMPORT_LIST(area)) + if (access_list_apply(IMPORT_LIST(area), p) + == FILTER_DENY) + return 0; + } - return 1; + return 1; } -static int -ospf_abr_plist_in_check (struct ospf_area *area, struct ospf_route *or, - struct prefix_ipv4 *p) +static int ospf_abr_plist_in_check(struct ospf_area *area, + struct ospf_route * or, + struct prefix_ipv4 *p) { - if (PREFIX_NAME_IN (area)) - { - if (PREFIX_LIST_IN (area) == NULL) - PREFIX_LIST_IN (area) = prefix_list_lookup (AFI_IP, - PREFIX_NAME_IN (area)); - if (PREFIX_LIST_IN (area)) - if (prefix_list_apply (PREFIX_LIST_IN (area), p) != PREFIX_PERMIT) - return 0; - } - return 1; + if (PREFIX_NAME_IN(area)) { + if (PREFIX_LIST_IN(area) == NULL) + PREFIX_LIST_IN(area) = prefix_list_lookup( + AFI_IP, PREFIX_NAME_IN(area)); + if (PREFIX_LIST_IN(area)) + if (prefix_list_apply(PREFIX_LIST_IN(area), p) + != PREFIX_PERMIT) + return 0; + } + return 1; } -static int -ospf_abr_plist_out_check (struct ospf_area *area, struct ospf_route *or, - struct prefix_ipv4 *p) +static int ospf_abr_plist_out_check(struct ospf_area *area, + struct ospf_route * or, + struct prefix_ipv4 *p) { - if (PREFIX_NAME_OUT (area)) - { - if (PREFIX_LIST_OUT (area) == NULL) - PREFIX_LIST_OUT (area) = prefix_list_lookup (AFI_IP, - PREFIX_NAME_OUT (area)); - if (PREFIX_LIST_OUT (area)) - if (prefix_list_apply (PREFIX_LIST_OUT (area), p) != PREFIX_PERMIT) - return 0; - } - return 1; + if (PREFIX_NAME_OUT(area)) { + if (PREFIX_LIST_OUT(area) == NULL) + PREFIX_LIST_OUT(area) = prefix_list_lookup( + AFI_IP, PREFIX_NAME_OUT(area)); + if (PREFIX_LIST_OUT(area)) + if (prefix_list_apply(PREFIX_LIST_OUT(area), p) + != PREFIX_PERMIT) + return 0; + } + return 1; } -static void -ospf_abr_announce_network (struct ospf *ospf, - struct prefix_ipv4 *p, struct ospf_route *or) +static void ospf_abr_announce_network(struct ospf *ospf, struct prefix_ipv4 *p, + struct ospf_route * or) { - struct ospf_area_range *range; - struct ospf_area *area, *or_area; - struct listnode *node; + struct ospf_area_range *range; + struct ospf_area *area, *or_area; + struct listnode *node; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_network(): Start"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_announce_network(): Start"); - or_area = ospf_area_lookup_by_area_id (ospf, or->u.std.area_id); - assert (or_area); + or_area = ospf_area_lookup_by_area_id(ospf, or->u.std.area_id); + assert(or_area); - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_network(): looking at area %s", - inet_ntoa (area->area_id)); + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_network(): looking at area %s", + inet_ntoa(area->area_id)); - if (IPV4_ADDR_SAME (&or->u.std.area_id, &area->area_id)) - continue; + if (IPV4_ADDR_SAME(& or->u.std.area_id, &area->area_id)) + continue; - if (ospf_abr_nexthops_belong_to_area (or, area)) - continue; + if (ospf_abr_nexthops_belong_to_area(or, area)) + continue; - if (!ospf_abr_should_accept (p, area)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_network(): " - "prefix %s/%d was denied by import-list", - inet_ntoa (p->prefix), p->prefixlen); - continue; - } + if (!ospf_abr_should_accept(p, area)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_network(): " + "prefix %s/%d was denied by import-list", + inet_ntoa(p->prefix), p->prefixlen); + continue; + } + + if (!ospf_abr_plist_in_check(area, or, p)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_network(): " + "prefix %s/%d was denied by prefix-list", + inet_ntoa(p->prefix), p->prefixlen); + continue; + } + + if (area->external_routing != OSPF_AREA_DEFAULT + && area->no_summary) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_network(): " + "area %s is stub and no_summary", + inet_ntoa(area->area_id)); + continue; + } + + if (or->path_type == OSPF_PATH_INTER_AREA) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_network(): this is " + "inter-area route to %s/%d", + inet_ntoa(p->prefix), p->prefixlen); - if (!ospf_abr_plist_in_check (area, or, p)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_network(): " - "prefix %s/%d was denied by prefix-list", - inet_ntoa (p->prefix), p->prefixlen); - continue; + if (!OSPF_IS_AREA_BACKBONE(area)) + ospf_abr_announce_network_to_area(p, or->cost, + area); + } + + if (or->path_type == OSPF_PATH_INTRA_AREA) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_network(): " + "this is intra-area route to %s/%d", + inet_ntoa(p->prefix), p->prefixlen); + if ((range = ospf_area_range_match(or_area, p)) + && !ospf_area_is_transit(area)) + ospf_abr_update_aggregate(range, or, area); + else + ospf_abr_announce_network_to_area(p, or->cost, + area); + } } +} - if (area->external_routing != OSPF_AREA_DEFAULT && area->no_summary) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_network(): " - "area %s is stub and no_summary", - inet_ntoa (area->area_id)); - continue; +static int ospf_abr_should_announce(struct ospf *ospf, struct prefix_ipv4 *p, + struct ospf_route * or) +{ + struct ospf_area *area; + + area = ospf_area_lookup_by_area_id(ospf, or->u.std.area_id); + + assert(area); + + if (EXPORT_NAME(area)) { + if (EXPORT_LIST(area) == NULL) + EXPORT_LIST(area) = + access_list_lookup(AFI_IP, EXPORT_NAME(area)); + + if (EXPORT_LIST(area)) + if (access_list_apply(EXPORT_LIST(area), p) + == FILTER_DENY) + return 0; } - if (or->path_type == OSPF_PATH_INTER_AREA) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_network(): this is " - "inter-area route to %s/%d", - inet_ntoa (p->prefix), p->prefixlen); + return 1; +} - if (!OSPF_IS_AREA_BACKBONE (area)) - ospf_abr_announce_network_to_area (p, or->cost, area); +static void ospf_abr_process_nssa_translates(struct ospf *ospf) +{ + /* Scan through all NSSA_LSDB records for all areas; + + If P-bit is on, translate all Type-7's to 5's and aggregate or + flood install as approved in Type-5 LSDB with XLATE Flag on + later, do same for all aggregates... At end, DISCARD all + remaining UNAPPROVED Type-5's (Aggregate is for future ) */ + struct listnode *node; + struct ospf_area *area; + struct route_node *rn; + struct ospf_lsa *lsa; + + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("ospf_abr_process_nssa_translates(): Start"); + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + if (!area->NSSATranslatorState) + continue; /* skip if not translator */ + + if (area->external_routing != OSPF_AREA_NSSA) + continue; /* skip if not Nssa Area */ + + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_abr_process_nssa_translates(): " + "looking at area %s", + inet_ntoa(area->area_id)); + + LSDB_LOOP(NSSA_LSDB(area), rn, lsa) + ospf_abr_translate_nssa(area, lsa); } - if (or->path_type == OSPF_PATH_INTRA_AREA) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_network(): " - "this is intra-area route to %s/%d", - inet_ntoa (p->prefix), p->prefixlen); - if ((range = ospf_area_range_match (or_area, p)) - && !ospf_area_is_transit (area)) - ospf_abr_update_aggregate (range, or, area); - else - ospf_abr_announce_network_to_area (p, or->cost, area); - } - } + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("ospf_abr_process_nssa_translates(): Stop"); } -static int -ospf_abr_should_announce (struct ospf *ospf, - struct prefix_ipv4 *p, struct ospf_route *or) +static void ospf_abr_process_network_rt(struct ospf *ospf, + struct route_table *rt) { - struct ospf_area *area; + struct ospf_area *area; + struct ospf_route * or ; + struct route_node *rn; - area = ospf_area_lookup_by_area_id (ospf, or->u.std.area_id); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_process_network_rt(): Start"); - assert (area); - - if (EXPORT_NAME (area)) - { - if (EXPORT_LIST (area) == NULL) - EXPORT_LIST (area) = access_list_lookup (AFI_IP, EXPORT_NAME (area)); + for (rn = route_top(rt); rn; rn = route_next(rn)) { + if ((or = rn->info) == NULL) + continue; - if (EXPORT_LIST (area)) - if (access_list_apply (EXPORT_LIST (area), p) == FILTER_DENY) - return 0; - } + if (!(area = ospf_area_lookup_by_area_id(ospf, + or->u.std.area_id))) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_process_network_rt(): area %s no longer exists", + inet_ntoa(or->u.std.area_id)); + continue; + } - return 1; -} + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_process_network_rt(): this is a route to %s/%d", + inet_ntoa(rn->p.u.prefix4), rn->p.prefixlen); + if (or->path_type >= OSPF_PATH_TYPE1_EXTERNAL) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_process_network_rt(): " + "this is an External router, skipping"); + continue; + } -static void -ospf_abr_process_nssa_translates (struct ospf *ospf) -{ - /* Scan through all NSSA_LSDB records for all areas; - - If P-bit is on, translate all Type-7's to 5's and aggregate or - flood install as approved in Type-5 LSDB with XLATE Flag on - later, do same for all aggregates... At end, DISCARD all - remaining UNAPPROVED Type-5's (Aggregate is for future ) */ - struct listnode *node; - struct ospf_area *area; - struct route_node *rn; - struct ospf_lsa *lsa; - - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_process_nssa_translates(): Start"); - - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - if (! area->NSSATranslatorState) - continue; /* skip if not translator */ - - if (area->external_routing != OSPF_AREA_NSSA) - continue; /* skip if not Nssa Area */ - - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_process_nssa_translates(): " - "looking at area %s", inet_ntoa (area->area_id)); - - LSDB_LOOP (NSSA_LSDB (area), rn, lsa) - ospf_abr_translate_nssa (area, lsa); - } - - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_process_nssa_translates(): Stop"); + if (or->cost >= OSPF_LS_INFINITY) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_process_network_rt():" + " this route's cost is infinity, skipping"); + continue; + } -} + if (or->type == OSPF_DESTINATION_DISCARD) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_process_network_rt():" + " this is a discard entry, skipping"); + continue; + } + + if ( + or->path_type == OSPF_PATH_INTRA_AREA + && !ospf_abr_should_announce( + ospf, (struct prefix_ipv4 *)&rn->p, + or)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_process_network_rt(): denied by export-list"); + continue; + } + + if ( + or->path_type == OSPF_PATH_INTRA_AREA + && !ospf_abr_plist_out_check( + area, or, + (struct prefix_ipv4 *)&rn->p)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_process_network_rt(): denied by prefix-list"); + continue; + } -static void -ospf_abr_process_network_rt (struct ospf *ospf, - struct route_table *rt) -{ - struct ospf_area *area; - struct ospf_route *or; - struct route_node *rn; + if ((or->path_type == OSPF_PATH_INTER_AREA) + && !OSPF_IS_AREA_ID_BACKBONE(or->u.std.area_id)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_process_network_rt():" + " this is route is not backbone one, skipping"); + continue; + } - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_process_network_rt(): Start"); - for (rn = route_top (rt); rn; rn = route_next (rn)) - { - if ((or = rn->info) == NULL) - continue; + if ((ospf->abr_type == OSPF_ABR_CISCO) + || (ospf->abr_type == OSPF_ABR_IBM)) - if (!(area = ospf_area_lookup_by_area_id (ospf, or->u.std.area_id))) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_process_network_rt(): area %s no longer exists", - inet_ntoa (or->u.std.area_id)); - continue; - } + if (!ospf_act_bb_connection(ospf) && + or->path_type != OSPF_PATH_INTRA_AREA) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_process_network_rt(): ALT ABR: " + "No BB connection, skip not intra-area routes"); + continue; + } - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_process_network_rt(): this is a route to %s/%d", - inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen); - if (or->path_type >= OSPF_PATH_TYPE1_EXTERNAL) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_process_network_rt(): " - "this is an External router, skipping"); - continue; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_process_network_rt(): announcing"); + ospf_abr_announce_network(ospf, (struct prefix_ipv4 *)&rn->p, + or); } - if (or->cost >= OSPF_LS_INFINITY) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_process_network_rt():" - " this route's cost is infinity, skipping"); - continue; - } + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_process_network_rt(): Stop"); +} - if (or->type == OSPF_DESTINATION_DISCARD) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_process_network_rt():" - " this is a discard entry, skipping"); - continue; - } +static void ospf_abr_announce_rtr_to_area(struct prefix_ipv4 *p, u_int32_t cost, + struct ospf_area *area) +{ + struct ospf_lsa *lsa, *old = NULL; + struct summary_lsa *slsa = NULL; - if (or->path_type == OSPF_PATH_INTRA_AREA && - !ospf_abr_should_announce (ospf, (struct prefix_ipv4 *) &rn->p, or)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug("ospf_abr_process_network_rt(): denied by export-list"); - continue; - } + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_announce_rtr_to_area(): Start"); - if (or->path_type == OSPF_PATH_INTRA_AREA && - !ospf_abr_plist_out_check (area, or, (struct prefix_ipv4 *) &rn->p)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug("ospf_abr_process_network_rt(): denied by prefix-list"); - continue; - } + old = ospf_lsa_lookup_by_prefix(area->lsdb, OSPF_ASBR_SUMMARY_LSA, p, + area->ospf->router_id); + if (old) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_rtr_to_area(): old summary found"); + slsa = (struct summary_lsa *)old->data; - if ((or->path_type == OSPF_PATH_INTER_AREA) && - !OSPF_IS_AREA_ID_BACKBONE (or->u.std.area_id)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_process_network_rt():" - " this is route is not backbone one, skipping"); - continue; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_network_to_area(): " + "old metric: %d, new metric: %d", + GET_METRIC(slsa->metric), cost); } + if (old && (GET_METRIC(slsa->metric) == cost) + && ((old->flags & OSPF_LSA_IN_MAXAGE) == 0)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_rtr_to_area(): old summary approved"); + SET_FLAG(old->flags, OSPF_LSA_APPROVED); + } else { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_announce_rtr_to_area(): 2.2"); + + if (old) { + set_metric(old, cost); + lsa = ospf_lsa_refresh(area->ospf, old); + } else + lsa = ospf_summary_asbr_lsa_originate(p, cost, area); + if (!lsa) { + char buf[PREFIX2STR_BUFFER]; + + prefix2str((struct prefix *)p, buf, sizeof(buf)); + zlog_warn("%s: Could not refresh/originate %s to %s", + __func__, buf, inet_ntoa(area->area_id)); + return; + } - if ((ospf->abr_type == OSPF_ABR_CISCO) || - (ospf->abr_type == OSPF_ABR_IBM)) + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_rtr_to_area(): " + "flooding new version of summary"); - if (!ospf_act_bb_connection (ospf) && - or->path_type != OSPF_PATH_INTRA_AREA) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_process_network_rt(): ALT ABR: " - "No BB connection, skip not intra-area routes"); - continue; - } + /* + zlog_info ("ospf_abr_announce_rtr_to_area(): creating new + summary"); + lsa = ospf_summary_asbr_lsa (p, cost, area, old); */ - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_process_network_rt(): announcing"); - ospf_abr_announce_network (ospf, (struct prefix_ipv4 *)&rn->p, or); - } + SET_FLAG(lsa->flags, OSPF_LSA_APPROVED); + /* ospf_flood_through_area (area, NULL, lsa);*/ + } - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_process_network_rt(): Stop"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_announce_rtr_to_area(): Stop"); } -static void -ospf_abr_announce_rtr_to_area (struct prefix_ipv4 *p, u_int32_t cost, - struct ospf_area *area) + +static void ospf_abr_announce_rtr(struct ospf *ospf, struct prefix_ipv4 *p, + struct ospf_route * or) { - struct ospf_lsa *lsa, *old = NULL; - struct summary_lsa *slsa = NULL; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_rtr_to_area(): Start"); - - old = ospf_lsa_lookup_by_prefix (area->lsdb, OSPF_ASBR_SUMMARY_LSA, - p, area->ospf->router_id); - if (old) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_rtr_to_area(): old summary found"); - slsa = (struct summary_lsa *) old->data; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_network_to_area(): " - "old metric: %d, new metric: %d", - GET_METRIC (slsa->metric), cost); - } - - if (old && (GET_METRIC (slsa->metric) == cost) && - ((old->flags & OSPF_LSA_IN_MAXAGE) == 0)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_rtr_to_area(): old summary approved"); - SET_FLAG (old->flags, OSPF_LSA_APPROVED); - } - else - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_rtr_to_area(): 2.2"); - - if (old) - { - set_metric (old, cost); - lsa = ospf_lsa_refresh (area->ospf, old); + struct listnode *node; + struct ospf_area *area; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_announce_rtr(): Start"); + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_rtr(): looking at area %s", + inet_ntoa(area->area_id)); + + if (IPV4_ADDR_SAME(& or->u.std.area_id, &area->area_id)) + continue; + + if (ospf_abr_nexthops_belong_to_area(or, area)) + continue; + + if (area->external_routing != OSPF_AREA_DEFAULT) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_rtr(): " + "area %s doesn't support external routing", + inet_ntoa(area->area_id)); + continue; + } + + if (or->path_type == OSPF_PATH_INTER_AREA) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_rtr(): " + "this is inter-area route to %s", + inet_ntoa(p->prefix)); + if (!OSPF_IS_AREA_BACKBONE(area)) + ospf_abr_announce_rtr_to_area(p, or->cost, + area); + } + + if (or->path_type == OSPF_PATH_INTRA_AREA) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_rtr(): " + "this is intra-area route to %s", + inet_ntoa(p->prefix)); + ospf_abr_announce_rtr_to_area(p, or->cost, area); + } } - else - lsa = ospf_summary_asbr_lsa_originate (p, cost, area); - if (!lsa) - { - char buf[PREFIX2STR_BUFFER]; - - prefix2str ((struct prefix *)p, buf, sizeof(buf)); - zlog_warn ("%s: Could not refresh/originate %s to %s", - __func__, - buf, - inet_ntoa (area->area_id)); - return; - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_rtr_to_area(): " - "flooding new version of summary"); - - /* - zlog_info ("ospf_abr_announce_rtr_to_area(): creating new summary"); - lsa = ospf_summary_asbr_lsa (p, cost, area, old); */ - - SET_FLAG (lsa->flags, OSPF_LSA_APPROVED); - /* ospf_flood_through_area (area, NULL, lsa);*/ - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_rtr_to_area(): Stop"); -} + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_announce_rtr(): Stop"); +} -static void -ospf_abr_announce_rtr (struct ospf *ospf, - struct prefix_ipv4 *p, struct ospf_route *or) +static void ospf_abr_process_router_rt(struct ospf *ospf, + struct route_table *rt) { - struct listnode *node; - struct ospf_area *area; + struct ospf_route * or ; + struct route_node *rn; + struct list *l; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_rtr(): Start"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_process_router_rt(): Start"); - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_rtr(): looking at area %s", - inet_ntoa (area->area_id)); + for (rn = route_top(rt); rn; rn = route_next(rn)) { + struct listnode *node, *nnode; + char flag = 0; + struct ospf_route *best = NULL; - if (IPV4_ADDR_SAME (&or->u.std.area_id, &area->area_id)) - continue; + if (rn->info == NULL) + continue; - if (ospf_abr_nexthops_belong_to_area (or, area)) - continue; + l = rn->info; - if (area->external_routing != OSPF_AREA_DEFAULT) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_rtr(): " - "area %s doesn't support external routing", - inet_ntoa(area->area_id)); - continue; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_process_router_rt(): this is a route to %s", + inet_ntoa(rn->p.u.prefix4)); + + for (ALL_LIST_ELEMENTS(l, node, nnode, or)) { + if (!ospf_area_lookup_by_area_id(ospf, + or->u.std.area_id)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_process_router_rt(): area %s no longer exists", + inet_ntoa(or->u.std.area_id)); + continue; + } + + + if (!CHECK_FLAG(or->u.std.flags, ROUTER_LSA_EXTERNAL)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_process_router_rt(): " + "This is not an ASBR, skipping"); + continue; + } + + if (!flag) { + best = ospf_find_asbr_route( + ospf, rt, (struct prefix_ipv4 *)&rn->p); + flag = 1; + } + + if (best == NULL) + continue; + + if (or != best) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_process_router_rt(): " + "This route is not the best among possible, skipping"); + continue; + } + + if ( + or->path_type == OSPF_PATH_INTER_AREA + && !OSPF_IS_AREA_ID_BACKBONE( + or->u.std.area_id)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_process_router_rt(): " + "This route is not a backbone one, skipping"); + continue; + } + + if (or->cost >= OSPF_LS_INFINITY) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_process_router_rt(): " + "This route has LS_INFINITY metric, skipping"); + continue; + } + + if (ospf->abr_type == OSPF_ABR_CISCO + || ospf->abr_type == OSPF_ABR_IBM) + if (!ospf_act_bb_connection(ospf) && + or->path_type != OSPF_PATH_INTRA_AREA) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_process_network_rt(): ALT ABR: " + "No BB connection, skip not intra-area routes"); + continue; + } + + ospf_abr_announce_rtr(ospf, + (struct prefix_ipv4 *)&rn->p, or); + } } - if (or->path_type == OSPF_PATH_INTER_AREA) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_rtr(): " - "this is inter-area route to %s", inet_ntoa (p->prefix)); - if (!OSPF_IS_AREA_BACKBONE (area)) - ospf_abr_announce_rtr_to_area (p, or->cost, area); - } + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_process_router_rt(): Stop"); +} - if (or->path_type == OSPF_PATH_INTRA_AREA) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_rtr(): " - "this is intra-area route to %s", inet_ntoa (p->prefix)); - ospf_abr_announce_rtr_to_area (p, or->cost, area); +static void +ospf_abr_unapprove_translates(struct ospf *ospf) /* For NSSA Translations */ +{ + struct ospf_lsa *lsa; + struct route_node *rn; + + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("ospf_abr_unapprove_translates(): Start"); + + /* NSSA Translator is not checked, because it may have gone away, + and we would want to flush any residuals anyway */ + + LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa) + if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) { + UNSET_FLAG(lsa->flags, OSPF_LSA_APPROVED); + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_abr_unapprove_translates(): " + "approved unset on link id %s", + inet_ntoa(lsa->data->id)); } - } - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_rtr(): Stop"); + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("ospf_abr_unapprove_translates(): Stop"); } -static void -ospf_abr_process_router_rt (struct ospf *ospf, struct route_table *rt) +static void ospf_abr_unapprove_summaries(struct ospf *ospf) { - struct ospf_route *or; - struct route_node *rn; - struct list *l; + struct listnode *node; + struct ospf_area *area; + struct route_node *rn; + struct ospf_lsa *lsa; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_process_router_rt(): Start"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_unapprove_summaries(): Start"); - for (rn = route_top (rt); rn; rn = route_next (rn)) - { - struct listnode *node, *nnode; - char flag = 0; - struct ospf_route *best = NULL; + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_unapprove_summaries(): " + "considering area %s", + inet_ntoa(area->area_id)); + LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa) + if (ospf_lsa_is_self_originated(ospf, lsa)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_unapprove_summaries(): " + "approved unset on summary link id %s", + inet_ntoa(lsa->data->id)); + UNSET_FLAG(lsa->flags, OSPF_LSA_APPROVED); + } + + LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa) + if (ospf_lsa_is_self_originated(ospf, lsa)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_unapprove_summaries(): " + "approved unset on asbr-summary link id %s", + inet_ntoa(lsa->data->id)); + UNSET_FLAG(lsa->flags, OSPF_LSA_APPROVED); + } + } - if (rn->info == NULL) - continue; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_unapprove_summaries(): Stop"); +} - l = rn->info; +static void ospf_abr_prepare_aggregates(struct ospf *ospf) +{ + struct listnode *node; + struct route_node *rn; + struct ospf_area_range *range; + struct ospf_area *area; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_prepare_aggregates(): Start"); + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + for (rn = route_top(area->ranges); rn; rn = route_next(rn)) + if ((range = rn->info) != NULL) { + range->cost = 0; + range->specifics = 0; + } + } - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_process_router_rt(): this is a route to %s", - inet_ntoa (rn->p.u.prefix4)); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_prepare_aggregates(): Stop"); +} - for (ALL_LIST_ELEMENTS (l, node, nnode, or)) - { - if (!ospf_area_lookup_by_area_id (ospf, or->u.std.area_id)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_process_router_rt(): area %s no longer exists", - inet_ntoa (or->u.std.area_id)); - continue; - } - - - if (!CHECK_FLAG (or->u.std.flags, ROUTER_LSA_EXTERNAL)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_process_router_rt(): " - "This is not an ASBR, skipping"); - continue; - } - - if (!flag) - { - best = ospf_find_asbr_route (ospf, rt, - (struct prefix_ipv4 *) &rn->p); - flag = 1; - } - - if (best == NULL) - continue; - - if (or != best) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_process_router_rt(): " - "This route is not the best among possible, skipping"); - continue; - } - - if (or->path_type == OSPF_PATH_INTER_AREA && - !OSPF_IS_AREA_ID_BACKBONE (or->u.std.area_id)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_process_router_rt(): " - "This route is not a backbone one, skipping"); - continue; - } - - if (or->cost >= OSPF_LS_INFINITY) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_process_router_rt(): " - "This route has LS_INFINITY metric, skipping"); - continue; - } - - if (ospf->abr_type == OSPF_ABR_CISCO - || ospf->abr_type == OSPF_ABR_IBM) - if (!ospf_act_bb_connection (ospf) - && or->path_type != OSPF_PATH_INTRA_AREA) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug("ospf_abr_process_network_rt(): ALT ABR: " - "No BB connection, skip not intra-area routes"); - continue; - } - - ospf_abr_announce_rtr (ospf, (struct prefix_ipv4 *) &rn->p, or); +static void ospf_abr_announce_aggregates(struct ospf *ospf) +{ + struct ospf_area *area, *ar; + struct ospf_area_range *range; + struct route_node *rn; + struct prefix p; + struct listnode *node, *n; - } + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_announce_aggregates(): Start"); - } + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_aggregates(): looking at area %s", + inet_ntoa(area->area_id)); + + for (rn = route_top(area->ranges); rn; rn = route_next(rn)) + if ((range = rn->info)) { + if (!CHECK_FLAG(range->flags, + OSPF_AREA_RANGE_ADVERTISE)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_aggregates():" + " discarding suppress-ranges"); + continue; + } + + p.family = AF_INET; + p.u.prefix4 = range->addr; + p.prefixlen = range->masklen; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_aggregates():" + " this is range: %s/%d", + inet_ntoa(p.u.prefix4), + p.prefixlen); + + if (CHECK_FLAG(range->flags, + OSPF_AREA_RANGE_SUBSTITUTE)) { + p.family = AF_INET; + p.u.prefix4 = range->subst_addr; + p.prefixlen = range->subst_masklen; + } + + if (range->specifics) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_aggregates(): active range"); + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, + n, ar)) { + if (ar == area) + continue; + + /* We do not check nexthops + here, because + intra-area routes can be + associated with + one area only */ + + /* backbone routes are not + summarized + when announced into transit + areas */ + + if (ospf_area_is_transit(ar) + && OSPF_IS_AREA_BACKBONE( + area)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_aggregates(): Skipping " + "announcement of BB aggregate into" + " a transit area"); + continue; + } + ospf_abr_announce_network_to_area( + (struct prefix_ipv4 + *)&p, + range->cost, ar); + } + } + } + } - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_process_router_rt(): Stop"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_announce_aggregates(): Stop"); } static void -ospf_abr_unapprove_translates (struct ospf *ospf) /* For NSSA Translations */ +ospf_abr_send_nssa_aggregates(struct ospf *ospf) /* temporarily turned off */ { - struct ospf_lsa *lsa; - struct route_node *rn; - - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_unapprove_translates(): Start"); - - /* NSSA Translator is not checked, because it may have gone away, - and we would want to flush any residuals anyway */ - - LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) - if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)) - { - UNSET_FLAG (lsa->flags, OSPF_LSA_APPROVED); - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_unapprove_translates(): " - "approved unset on link id %s", - inet_ntoa (lsa->data->id)); - } - - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_unapprove_translates(): Stop"); + struct listnode *node; /*, n; */ + struct ospf_area *area; /*, *ar; */ + struct route_node *rn; + struct ospf_area_range *range; + struct prefix_ipv4 p; + + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("ospf_abr_send_nssa_aggregates(): Start"); + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + if (!area->NSSATranslatorState) + continue; + + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_abr_send_nssa_aggregates(): looking at area %s", + inet_ntoa(area->area_id)); + + for (rn = route_top(area->ranges); rn; rn = route_next(rn)) { + if (rn->info == NULL) + continue; + + range = rn->info; + + if (!CHECK_FLAG(range->flags, + OSPF_AREA_RANGE_ADVERTISE)) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_abr_send_nssa_aggregates():" + " discarding suppress-ranges"); + continue; + } + + p.family = AF_INET; + p.prefix = range->addr; + p.prefixlen = range->masklen; + + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_abr_send_nssa_aggregates():" + " this is range: %s/%d", + inet_ntoa(p.prefix), p.prefixlen); + + if (CHECK_FLAG(range->flags, + OSPF_AREA_RANGE_SUBSTITUTE)) { + p.family = AF_INET; + p.prefix = range->subst_addr; + p.prefixlen = range->subst_masklen; + } + + if (range->specifics) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_abr_send_nssa_aggregates(): active range"); + + /* Fetch LSA-Type-7 from aggregate prefix, and + * then + * translate, Install (as Type-5), Approve, and + * Flood + */ + ospf_abr_translate_nssa_range(&p, range->cost); + } + } /* all area ranges*/ + } /* all areas */ + + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("ospf_abr_send_nssa_aggregates(): Stop"); } -static void -ospf_abr_unapprove_summaries (struct ospf *ospf) +static void ospf_abr_announce_stub_defaults(struct ospf *ospf) { - struct listnode *node; - struct ospf_area *area; - struct route_node *rn; - struct ospf_lsa *lsa; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_unapprove_summaries(): Start"); - - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_unapprove_summaries(): " - "considering area %s", - inet_ntoa (area->area_id)); - LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa) - if (ospf_lsa_is_self_originated (ospf, lsa)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_unapprove_summaries(): " - "approved unset on summary link id %s", - inet_ntoa (lsa->data->id)); - UNSET_FLAG (lsa->flags, OSPF_LSA_APPROVED); - } - - LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa) - if (ospf_lsa_is_self_originated (ospf, lsa)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_unapprove_summaries(): " - "approved unset on asbr-summary link id %s", - inet_ntoa (lsa->data->id)); - UNSET_FLAG (lsa->flags, OSPF_LSA_APPROVED); - } - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_unapprove_summaries(): Stop"); -} + struct listnode *node; + struct ospf_area *area; + struct prefix_ipv4 p; -static void -ospf_abr_prepare_aggregates (struct ospf *ospf) -{ - struct listnode *node; - struct route_node *rn; - struct ospf_area_range *range; - struct ospf_area *area; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_prepare_aggregates(): Start"); - - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - for (rn = route_top (area->ranges); rn; rn = route_next (rn)) - if ((range = rn->info) != NULL) - { - range->cost = 0; - range->specifics = 0; - } - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_prepare_aggregates(): Stop"); -} + if (!IS_OSPF_ABR(ospf)) + return; -static void -ospf_abr_announce_aggregates (struct ospf *ospf) -{ - struct ospf_area *area, *ar; - struct ospf_area_range *range; - struct route_node *rn; - struct prefix p; - struct listnode *node, *n; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_aggregates(): Start"); - - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_aggregates(): looking at area %s", - inet_ntoa (area->area_id)); - - for (rn = route_top (area->ranges); rn; rn = route_next (rn)) - if ((range = rn->info)) - { - if (!CHECK_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_aggregates():" - " discarding suppress-ranges"); - continue; - } - - p.family = AF_INET; - p.u.prefix4 = range->addr; - p.prefixlen = range->masklen; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_aggregates():" - " this is range: %s/%d", - inet_ntoa (p.u.prefix4), p.prefixlen); - - if (CHECK_FLAG (range->flags, OSPF_AREA_RANGE_SUBSTITUTE)) - { - p.family = AF_INET; - p.u.prefix4 = range->subst_addr; - p.prefixlen = range->subst_masklen; - } - - if (range->specifics) - { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_announce_stub_defaults(): Start"); + + p.family = AF_INET; + p.prefix.s_addr = OSPF_DEFAULT_DESTINATION; + p.prefixlen = 0; + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_aggregates(): active range"); + zlog_debug( + "ospf_abr_announce_stub_defaults(): looking at area %s", + inet_ntoa(area->area_id)); - for (ALL_LIST_ELEMENTS_RO (ospf->areas, n, ar)) - { - if (ar == area) - continue; + if ((area->external_routing != OSPF_AREA_STUB) + && (area->external_routing != OSPF_AREA_NSSA)) + continue; - /* We do not check nexthops here, because - intra-area routes can be associated with - one area only */ + if (OSPF_IS_AREA_BACKBONE(area)) + continue; /* Sanity Check */ - /* backbone routes are not summarized - when announced into transit areas */ + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_stub_defaults(): " + "announcing 0.0.0.0/0 to area %s", + inet_ntoa(area->area_id)); + ospf_abr_announce_network_to_area(&p, area->default_cost, area); + } - if (ospf_area_is_transit (ar) && - OSPF_IS_AREA_BACKBONE (area)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_aggregates(): Skipping " - "announcement of BB aggregate into" - " a transit area"); - continue; - } - ospf_abr_announce_network_to_area ((struct prefix_ipv4 *)&p, range->cost, ar); - } - } - } - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_aggregates(): Stop"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_announce_stub_defaults(): Stop"); } -static void -ospf_abr_send_nssa_aggregates (struct ospf *ospf) /* temporarily turned off */ +static int ospf_abr_remove_unapproved_translates_apply(struct ospf *ospf, + struct ospf_lsa *lsa) { - struct listnode *node; /*, n; */ - struct ospf_area *area; /*, *ar; */ - struct route_node *rn; - struct ospf_area_range *range; - struct prefix_ipv4 p; + if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT) + && !CHECK_FLAG(lsa->flags, OSPF_LSA_APPROVED)) { + zlog_info( + "ospf_abr_remove_unapproved_translates(): " + "removing unapproved translates, ID: %s", + inet_ntoa(lsa->data->id)); - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_send_nssa_aggregates(): Start"); + /* FLUSH THROUGHOUT AS */ + ospf_lsa_flush_as(ospf, lsa); - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - if (! area->NSSATranslatorState) - continue; - - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_send_nssa_aggregates(): looking at area %s", - inet_ntoa (area->area_id)); - - for (rn = route_top (area->ranges); rn; rn = route_next (rn)) - { - if (rn->info == NULL) - continue; - - range = rn->info; - - if (!CHECK_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE)) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_send_nssa_aggregates():" - " discarding suppress-ranges"); - continue; - } - - p.family = AF_INET; - p.prefix = range->addr; - p.prefixlen = range->masklen; - - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_send_nssa_aggregates():" - " this is range: %s/%d", - inet_ntoa (p.prefix), p.prefixlen); - - if (CHECK_FLAG (range->flags, OSPF_AREA_RANGE_SUBSTITUTE)) - { - p.family = AF_INET; - p.prefix = range->subst_addr; - p.prefixlen = range->subst_masklen; - } - - if (range->specifics) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_send_nssa_aggregates(): active range"); - - /* Fetch LSA-Type-7 from aggregate prefix, and then - * translate, Install (as Type-5), Approve, and Flood - */ - ospf_abr_translate_nssa_range (&p, range->cost); - } - } /* all area ranges*/ - } /* all areas */ - - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_send_nssa_aggregates(): Stop"); + /* DISCARD from LSDB */ + } + return 0; } -static void -ospf_abr_announce_stub_defaults (struct ospf *ospf) +static void ospf_abr_remove_unapproved_translates(struct ospf *ospf) { - struct listnode *node; - struct ospf_area *area; - struct prefix_ipv4 p; - - if (! IS_OSPF_ABR (ospf)) - return; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_stub_defaults(): Start"); - - p.family = AF_INET; - p.prefix.s_addr = OSPF_DEFAULT_DESTINATION; - p.prefixlen = 0; - - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_stub_defaults(): looking at area %s", - inet_ntoa (area->area_id)); - - if ( (area->external_routing != OSPF_AREA_STUB) - && (area->external_routing != OSPF_AREA_NSSA) - ) - continue; - - if (OSPF_IS_AREA_BACKBONE (area)) - continue; /* Sanity Check */ - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_stub_defaults(): " - "announcing 0.0.0.0/0 to area %s", - inet_ntoa (area->area_id)); - ospf_abr_announce_network_to_area (&p, area->default_cost, area); - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_stub_defaults(): Stop"); -} + struct route_node *rn; + struct ospf_lsa *lsa; -static int -ospf_abr_remove_unapproved_translates_apply (struct ospf *ospf, - struct ospf_lsa *lsa) -{ - if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT) - && ! CHECK_FLAG (lsa->flags, OSPF_LSA_APPROVED)) - { - zlog_info ("ospf_abr_remove_unapproved_translates(): " - "removing unapproved translates, ID: %s", - inet_ntoa (lsa->data->id)); - - /* FLUSH THROUGHOUT AS */ - ospf_lsa_flush_as (ospf, lsa); - - /* DISCARD from LSDB */ - } - return 0; -} + /* All AREA PROCESS should have APPROVED necessary LSAs */ + /* Remove any left over and not APPROVED */ + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("ospf_abr_remove_unapproved_translates(): Start"); -static void -ospf_abr_remove_unapproved_translates (struct ospf *ospf) -{ - struct route_node *rn; - struct ospf_lsa *lsa; - - /* All AREA PROCESS should have APPROVED necessary LSAs */ - /* Remove any left over and not APPROVED */ - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_remove_unapproved_translates(): Start"); - - LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) - ospf_abr_remove_unapproved_translates_apply (ospf, lsa); - - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_remove_unapproved_translates(): Stop"); + LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa) + ospf_abr_remove_unapproved_translates_apply(ospf, lsa); + + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("ospf_abr_remove_unapproved_translates(): Stop"); } -static void -ospf_abr_remove_unapproved_summaries (struct ospf *ospf) +static void ospf_abr_remove_unapproved_summaries(struct ospf *ospf) { - struct listnode *node; - struct ospf_area *area; - struct route_node *rn; - struct ospf_lsa *lsa; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_remove_unapproved_summaries(): Start"); - - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_remove_unapproved_summaries(): " - "looking at area %s", inet_ntoa (area->area_id)); - - LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa) - if (ospf_lsa_is_self_originated (ospf, lsa)) - if (!CHECK_FLAG (lsa->flags, OSPF_LSA_APPROVED)) - ospf_lsa_flush_area (lsa, area); - - LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa) - if (ospf_lsa_is_self_originated (ospf, lsa)) - if (!CHECK_FLAG (lsa->flags, OSPF_LSA_APPROVED)) - ospf_lsa_flush_area (lsa, area); - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_remove_unapproved_summaries(): Stop"); + struct listnode *node; + struct ospf_area *area; + struct route_node *rn; + struct ospf_lsa *lsa; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_remove_unapproved_summaries(): Start"); + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_remove_unapproved_summaries(): " + "looking at area %s", + inet_ntoa(area->area_id)); + + LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa) + if (ospf_lsa_is_self_originated(ospf, lsa)) + if (!CHECK_FLAG(lsa->flags, OSPF_LSA_APPROVED)) + ospf_lsa_flush_area(lsa, area); + + LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa) + if (ospf_lsa_is_self_originated(ospf, lsa)) + if (!CHECK_FLAG(lsa->flags, OSPF_LSA_APPROVED)) + ospf_lsa_flush_area(lsa, area); + } + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_remove_unapproved_summaries(): Stop"); } -static void -ospf_abr_manage_discard_routes (struct ospf *ospf) +static void ospf_abr_manage_discard_routes(struct ospf *ospf) { - struct listnode *node, *nnode; - struct route_node *rn; - struct ospf_area *area; - struct ospf_area_range *range; - - for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) - for (rn = route_top (area->ranges); rn; rn = route_next (rn)) - if ((range = rn->info) != NULL) - if (CHECK_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE)) - { - if (range->specifics) - ospf_add_discard_route (ospf->new_table, area, - (struct prefix_ipv4 *) &rn->p); - else - ospf_delete_discard_route (ospf->new_table, - (struct prefix_ipv4 *) &rn->p); - } + struct listnode *node, *nnode; + struct route_node *rn; + struct ospf_area *area; + struct ospf_area_range *range; + + for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) + for (rn = route_top(area->ranges); rn; rn = route_next(rn)) + if ((range = rn->info) != NULL) + if (CHECK_FLAG(range->flags, + OSPF_AREA_RANGE_ADVERTISE)) { + if (range->specifics) + ospf_add_discard_route( + ospf->new_table, area, + (struct prefix_ipv4 + *)&rn->p); + else + ospf_delete_discard_route( + ospf->new_table, + (struct prefix_ipv4 + *)&rn->p); + } } /* This is the function taking care about ABR NSSA, i.e. NSSA @@ -1738,145 +1719,141 @@ ospf_abr_manage_discard_routes (struct ospf *ospf) For External Calculations, any NSSA areas use the Type-7 AREA-LSDB, any ABR-non-NSSA areas use the Type-5 GLOBAL-LSDB. */ -static void -ospf_abr_nssa_task (struct ospf *ospf) /* called only if any_nssa */ +static void ospf_abr_nssa_task(struct ospf *ospf) /* called only if any_nssa */ { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("Check for NSSA-ABR Tasks():"); - - if (! IS_OSPF_ABR (ospf)) - return; - - if (! ospf->anyNSSA) - return; - - /* Each area must confirm TranslatorRole */ - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_nssa_task(): Start"); - - /* For all Global Entries flagged "local-translate", unset APPROVED */ - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_nssa_task(): unapprove translates"); - - ospf_abr_unapprove_translates (ospf); - - /* RESET all Ranges in every Area, same as summaries */ - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_nssa_task(): NSSA initialize aggregates"); - ospf_abr_prepare_aggregates (ospf); /*TURNED OFF just for now */ - - /* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or - * Aggregate as Type-7 - * Install or Approve in Type-5 Global LSDB - */ - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_nssa_task(): process translates"); - ospf_abr_process_nssa_translates (ospf); - - /* Translate/Send any "ranged" aggregates, and also 5-Install and - * Approve - * Scan Type-7's for aggregates, translate to Type-5's, - * Install/Flood/Approve - */ - if (IS_DEBUG_OSPF_NSSA) - zlog_debug("ospf_abr_nssa_task(): send NSSA aggregates"); - ospf_abr_send_nssa_aggregates (ospf); /*TURNED OFF FOR NOW */ - - /* Send any NSSA defaults as Type-5 - *if (IS_DEBUG_OSPF_NSSA) - * zlog_debug ("ospf_abr_nssa_task(): announce nssa defaults"); - *ospf_abr_announce_nssa_defaults (ospf); - * havnt a clue what above is supposed to do. - */ - - /* Flush any unapproved previous translates from Global Data Base */ - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_nssa_task(): remove unapproved translates"); - ospf_abr_remove_unapproved_translates (ospf); - - ospf_abr_manage_discard_routes (ospf); /* same as normal...discard */ - - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_abr_nssa_task(): Stop"); + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("Check for NSSA-ABR Tasks():"); + + if (!IS_OSPF_ABR(ospf)) + return; + + if (!ospf->anyNSSA) + return; + + /* Each area must confirm TranslatorRole */ + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("ospf_abr_nssa_task(): Start"); + + /* For all Global Entries flagged "local-translate", unset APPROVED */ + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("ospf_abr_nssa_task(): unapprove translates"); + + ospf_abr_unapprove_translates(ospf); + + /* RESET all Ranges in every Area, same as summaries */ + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("ospf_abr_nssa_task(): NSSA initialize aggregates"); + ospf_abr_prepare_aggregates(ospf); /*TURNED OFF just for now */ + + /* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or + * Aggregate as Type-7 + * Install or Approve in Type-5 Global LSDB + */ + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("ospf_abr_nssa_task(): process translates"); + ospf_abr_process_nssa_translates(ospf); + + /* Translate/Send any "ranged" aggregates, and also 5-Install and + * Approve + * Scan Type-7's for aggregates, translate to Type-5's, + * Install/Flood/Approve + */ + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("ospf_abr_nssa_task(): send NSSA aggregates"); + ospf_abr_send_nssa_aggregates(ospf); /*TURNED OFF FOR NOW */ + + /* Send any NSSA defaults as Type-5 + *if (IS_DEBUG_OSPF_NSSA) + * zlog_debug ("ospf_abr_nssa_task(): announce nssa defaults"); + *ospf_abr_announce_nssa_defaults (ospf); + * havnt a clue what above is supposed to do. + */ + + /* Flush any unapproved previous translates from Global Data Base */ + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_abr_nssa_task(): remove unapproved translates"); + ospf_abr_remove_unapproved_translates(ospf); + + ospf_abr_manage_discard_routes(ospf); /* same as normal...discard */ + + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("ospf_abr_nssa_task(): Stop"); } /* This is the function taking care about ABR stuff, i.e. summary-LSA origination and flooding. */ -void -ospf_abr_task (struct ospf *ospf) +void ospf_abr_task(struct ospf *ospf) { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_task(): Start"); - - if (ospf->new_table == NULL || ospf->new_rtrs == NULL) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_task(): Routing tables are not yet ready"); - return; - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_task(): unapprove summaries"); - ospf_abr_unapprove_summaries (ospf); - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_task(): prepare aggregates"); - ospf_abr_prepare_aggregates (ospf); - - if (IS_OSPF_ABR (ospf)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_task(): process network RT"); - ospf_abr_process_network_rt (ospf, ospf->new_table); - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_task(): process router RT"); - ospf_abr_process_router_rt (ospf, ospf->new_rtrs); - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_task(): announce aggregates"); - ospf_abr_announce_aggregates (ospf); - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_task(): announce stub defaults"); - ospf_abr_announce_stub_defaults (ospf); - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_task(): remove unapproved summaries"); - ospf_abr_remove_unapproved_summaries (ospf); - - ospf_abr_manage_discard_routes (ospf); - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_task(): Stop"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_task(): Start"); + + if (ospf->new_table == NULL || ospf->new_rtrs == NULL) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_task(): Routing tables are not yet ready"); + return; + } + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_task(): unapprove summaries"); + ospf_abr_unapprove_summaries(ospf); + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_task(): prepare aggregates"); + ospf_abr_prepare_aggregates(ospf); + + if (IS_OSPF_ABR(ospf)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_task(): process network RT"); + ospf_abr_process_network_rt(ospf, ospf->new_table); + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_task(): process router RT"); + ospf_abr_process_router_rt(ospf, ospf->new_rtrs); + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_task(): announce aggregates"); + ospf_abr_announce_aggregates(ospf); + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_task(): announce stub defaults"); + ospf_abr_announce_stub_defaults(ospf); + } + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_task(): remove unapproved summaries"); + ospf_abr_remove_unapproved_summaries(ospf); + + ospf_abr_manage_discard_routes(ospf); + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_abr_task(): Stop"); } -static int -ospf_abr_task_timer (struct thread *thread) +static int ospf_abr_task_timer(struct thread *thread) { - struct ospf *ospf = THREAD_ARG (thread); + struct ospf *ospf = THREAD_ARG(thread); - ospf->t_abr_task = 0; + ospf->t_abr_task = 0; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Running ABR task on timer"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Running ABR task on timer"); - ospf_check_abr_status (ospf); - ospf_abr_nssa_check_status (ospf); + ospf_check_abr_status(ospf); + ospf_abr_nssa_check_status(ospf); - ospf_abr_task (ospf); - ospf_abr_nssa_task (ospf); /* if nssa-abr, then scan Type-7 LSDB */ + ospf_abr_task(ospf); + ospf_abr_nssa_task(ospf); /* if nssa-abr, then scan Type-7 LSDB */ - return 0; + return 0; } -void -ospf_schedule_abr_task (struct ospf *ospf) +void ospf_schedule_abr_task(struct ospf *ospf) { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Scheduling ABR task"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Scheduling ABR task"); - thread_add_timer(master, ospf_abr_task_timer, ospf, OSPF_ABR_TASK_DELAY, - &ospf->t_abr_task); + thread_add_timer(master, ospf_abr_task_timer, ospf, OSPF_ABR_TASK_DELAY, + &ospf->t_abr_task); } diff --git a/ospfd/ospf_abr.h b/ospfd/ospf_abr.h index 71eb71bdc..379273213 100644 --- a/ospfd/ospf_abr.h +++ b/ospfd/ospf_abr.h @@ -28,65 +28,59 @@ #define OSPF_AREA_RANGE_SUBSTITUTE (1 << 1) /* Area range. */ -struct ospf_area_range -{ - /* Area range address. */ - struct in_addr addr; +struct ospf_area_range { + /* Area range address. */ + struct in_addr addr; - /* Area range masklen. */ - u_char masklen; + /* Area range masklen. */ + u_char masklen; - /* Flags. */ - u_char flags; + /* Flags. */ + u_char flags; - /* Number of more specific prefixes. */ - int specifics; + /* Number of more specific prefixes. */ + int specifics; - /* Addr and masklen to substitute. */ - struct in_addr subst_addr; - u_char subst_masklen; + /* Addr and masklen to substitute. */ + struct in_addr subst_addr; + u_char subst_masklen; - /* Range cost. */ - u_int32_t cost; + /* Range cost. */ + u_int32_t cost; - /* Configured range cost. */ - u_int32_t cost_config; + /* Configured range cost. */ + u_int32_t cost_config; }; /* Prototypes. */ -extern struct ospf_area_range *ospf_area_range_lookup (struct ospf_area *, - struct prefix_ipv4 *); - -extern struct ospf_area_range *ospf_some_area_range_match (struct prefix_ipv4 - *); - -extern struct ospf_area_range *ospf_area_range_lookup_next (struct ospf_area - *, - struct in_addr *, - int); - -extern int ospf_area_range_set (struct ospf *, struct in_addr, - struct prefix_ipv4 *, int); -extern int ospf_area_range_cost_set (struct ospf *, struct in_addr, - struct prefix_ipv4 *, u_int32_t); -extern int ospf_area_range_unset (struct ospf *, struct in_addr, - struct prefix_ipv4 *); -extern int ospf_area_range_substitute_set (struct ospf *, struct in_addr, - struct prefix_ipv4 *, - struct prefix_ipv4 *); -extern int ospf_area_range_substitute_unset (struct ospf *, struct in_addr, - struct prefix_ipv4 *); -extern struct ospf_area_range *ospf_area_range_match_any (struct ospf *, - struct prefix_ipv4 - *); -extern int ospf_area_range_active (struct ospf_area_range *); -extern int ospf_act_bb_connection (struct ospf *); - -extern void ospf_check_abr_status (struct ospf *); -extern void ospf_abr_task (struct ospf *); -extern void ospf_schedule_abr_task (struct ospf *); - -extern void ospf_abr_announce_network_to_area (struct prefix_ipv4 *, - u_int32_t, - struct ospf_area *); +extern struct ospf_area_range *ospf_area_range_lookup(struct ospf_area *, + struct prefix_ipv4 *); + +extern struct ospf_area_range *ospf_some_area_range_match(struct prefix_ipv4 *); + +extern struct ospf_area_range * +ospf_area_range_lookup_next(struct ospf_area *, struct in_addr *, int); + +extern int ospf_area_range_set(struct ospf *, struct in_addr, + struct prefix_ipv4 *, int); +extern int ospf_area_range_cost_set(struct ospf *, struct in_addr, + struct prefix_ipv4 *, u_int32_t); +extern int ospf_area_range_unset(struct ospf *, struct in_addr, + struct prefix_ipv4 *); +extern int ospf_area_range_substitute_set(struct ospf *, struct in_addr, + struct prefix_ipv4 *, + struct prefix_ipv4 *); +extern int ospf_area_range_substitute_unset(struct ospf *, struct in_addr, + struct prefix_ipv4 *); +extern struct ospf_area_range *ospf_area_range_match_any(struct ospf *, + struct prefix_ipv4 *); +extern int ospf_area_range_active(struct ospf_area_range *); +extern int ospf_act_bb_connection(struct ospf *); + +extern void ospf_check_abr_status(struct ospf *); +extern void ospf_abr_task(struct ospf *); +extern void ospf_schedule_abr_task(struct ospf *); + +extern void ospf_abr_announce_network_to_area(struct prefix_ipv4 *, u_int32_t, + struct ospf_area *); #endif /* _ZEBRA_OSPF_ABR_H */ diff --git a/ospfd/ospf_api.c b/ospfd/ospf_api.c index 69d61b12e..f1a743376 100644 --- a/ospfd/ospf_api.c +++ b/ospfd/ospf_api.c @@ -34,7 +34,7 @@ #include "log.h" #include "thread.h" #include "hash.h" -#include "sockunion.h" /* for inet_aton() */ +#include "sockunion.h" /* for inet_aton() */ #include "buffer.h" #include "network.h" @@ -58,31 +58,28 @@ /* For debugging only, will be removed */ -void -api_opaque_lsa_print (struct lsa_header *data) +void api_opaque_lsa_print(struct lsa_header *data) { - struct opaque_lsa - { - struct lsa_header header; - u_char mydata[]; - }; + struct opaque_lsa { + struct lsa_header header; + u_char mydata[]; + }; - struct opaque_lsa *olsa; - int opaquelen; - int i; + struct opaque_lsa *olsa; + int opaquelen; + int i; - ospf_lsa_header_dump (data); + ospf_lsa_header_dump(data); - olsa = (struct opaque_lsa *) data; + olsa = (struct opaque_lsa *)data; - opaquelen = ntohs (data->length) - OSPF_LSA_HEADER_SIZE; - zlog_debug ("apiserver_lsa_print: opaquelen=%d\n", opaquelen); + opaquelen = ntohs(data->length) - OSPF_LSA_HEADER_SIZE; + zlog_debug("apiserver_lsa_print: opaquelen=%d\n", opaquelen); - for (i = 0; i < opaquelen; i++) - { - zlog_debug ("0x%x ", olsa->mydata[i]); - } - zlog_debug ("\n"); + for (i = 0; i < opaquelen; i++) { + zlog_debug("0x%x ", olsa->mydata[i]); + } + zlog_debug("\n"); } /* ----------------------------------------------------------- @@ -90,172 +87,212 @@ api_opaque_lsa_print (struct lsa_header *data) * ----------------------------------------------------------- */ -struct msg * -msg_new (u_char msgtype, void *msgbody, u_int32_t seqnum, u_int16_t msglen) +struct msg *msg_new(u_char msgtype, void *msgbody, u_int32_t seqnum, + u_int16_t msglen) { - struct msg *new; + struct msg *new; - new = XCALLOC (MTYPE_OSPF_API_MSG, sizeof (struct msg)); + new = XCALLOC(MTYPE_OSPF_API_MSG, sizeof(struct msg)); - new->hdr.version = OSPF_API_VERSION; - new->hdr.msgtype = msgtype; - new->hdr.msglen = htons (msglen); - new->hdr.msgseq = htonl (seqnum); + new->hdr.version = OSPF_API_VERSION; + new->hdr.msgtype = msgtype; + new->hdr.msglen = htons(msglen); + new->hdr.msgseq = htonl(seqnum); - new->s = stream_new (msglen); - assert (new->s); - stream_put (new->s, msgbody, msglen); + new->s = stream_new(msglen); + assert(new->s); + stream_put(new->s, msgbody, msglen); - return new; + return new; } /* Duplicate a message by copying content. */ -struct msg * -msg_dup (struct msg *msg) +struct msg *msg_dup(struct msg *msg) { - struct msg *new; + struct msg *new; - assert (msg); + assert(msg); - new = msg_new (msg->hdr.msgtype, STREAM_DATA (msg->s), - ntohl (msg->hdr.msgseq), ntohs (msg->hdr.msglen)); - return new; + new = msg_new(msg->hdr.msgtype, STREAM_DATA(msg->s), + ntohl(msg->hdr.msgseq), ntohs(msg->hdr.msglen)); + return new; } /* XXX only for testing, will be removed */ struct nametab { - int value; - const char *name; + int value; + const char *name; }; -const char * -ospf_api_typename (int msgtype) +const char *ospf_api_typename(int msgtype) { - struct nametab NameTab[] = { - { MSG_REGISTER_OPAQUETYPE, "Register opaque-type", }, - { MSG_UNREGISTER_OPAQUETYPE, "Unregister opaque-type", }, - { MSG_REGISTER_EVENT, "Register event", }, - { MSG_SYNC_LSDB, "Sync LSDB", }, - { MSG_ORIGINATE_REQUEST, "Originate request", }, - { MSG_DELETE_REQUEST, "Delete request", }, - { MSG_REPLY, "Reply", }, - { MSG_READY_NOTIFY, "Ready notify", }, - { MSG_LSA_UPDATE_NOTIFY, "LSA update notify", }, - { MSG_LSA_DELETE_NOTIFY, "LSA delete notify", }, - { MSG_NEW_IF, "New interface", }, - { MSG_DEL_IF, "Del interface", }, - { MSG_ISM_CHANGE, "ISM change", }, - { MSG_NSM_CHANGE, "NSM change", }, - }; - - int i, n = array_size(NameTab); - const char *name = NULL; - - for (i = 0; i < n; i++) - { - if (NameTab[i].value == msgtype) - { - name = NameTab[i].name; - break; - } - } - - return name ? name : "?"; + struct nametab NameTab[] = { + { + MSG_REGISTER_OPAQUETYPE, "Register opaque-type", + }, + { + MSG_UNREGISTER_OPAQUETYPE, "Unregister opaque-type", + }, + { + MSG_REGISTER_EVENT, "Register event", + }, + { + MSG_SYNC_LSDB, "Sync LSDB", + }, + { + MSG_ORIGINATE_REQUEST, "Originate request", + }, + { + MSG_DELETE_REQUEST, "Delete request", + }, + { + MSG_REPLY, "Reply", + }, + { + MSG_READY_NOTIFY, "Ready notify", + }, + { + MSG_LSA_UPDATE_NOTIFY, "LSA update notify", + }, + { + MSG_LSA_DELETE_NOTIFY, "LSA delete notify", + }, + { + MSG_NEW_IF, "New interface", + }, + { + MSG_DEL_IF, "Del interface", + }, + { + MSG_ISM_CHANGE, "ISM change", + }, + { + MSG_NSM_CHANGE, "NSM change", + }, + }; + + int i, n = array_size(NameTab); + const char *name = NULL; + + for (i = 0; i < n; i++) { + if (NameTab[i].value == msgtype) { + name = NameTab[i].name; + break; + } + } + + return name ? name : "?"; } -const char * -ospf_api_errname (int errcode) +const char *ospf_api_errname(int errcode) { - struct nametab NameTab[] = { - { OSPF_API_OK, "OK", }, - { OSPF_API_NOSUCHINTERFACE, "No such interface", }, - { OSPF_API_NOSUCHAREA, "No such area", }, - { OSPF_API_NOSUCHLSA, "No such LSA", }, - { OSPF_API_ILLEGALLSATYPE, "Illegal LSA type", }, - { OSPF_API_OPAQUETYPEINUSE, "Opaque type in use", }, - { OSPF_API_OPAQUETYPENOTREGISTERED, "Opaque type not registered", }, - { OSPF_API_NOTREADY, "Not ready", }, - { OSPF_API_NOMEMORY, "No memory", }, - { OSPF_API_ERROR, "Other error", }, - { OSPF_API_UNDEF, "Undefined", }, - }; - - int i, n = array_size(NameTab); - const char *name = NULL; - - for (i = 0; i < n; i++) - { - if (NameTab[i].value == errcode) - { - name = NameTab[i].name; - break; - } - } - - return name ? name : "?"; + struct nametab NameTab[] = { + { + OSPF_API_OK, "OK", + }, + { + OSPF_API_NOSUCHINTERFACE, "No such interface", + }, + { + OSPF_API_NOSUCHAREA, "No such area", + }, + { + OSPF_API_NOSUCHLSA, "No such LSA", + }, + { + OSPF_API_ILLEGALLSATYPE, "Illegal LSA type", + }, + { + OSPF_API_OPAQUETYPEINUSE, "Opaque type in use", + }, + { + OSPF_API_OPAQUETYPENOTREGISTERED, + "Opaque type not registered", + }, + { + OSPF_API_NOTREADY, "Not ready", + }, + { + OSPF_API_NOMEMORY, "No memory", + }, + { + OSPF_API_ERROR, "Other error", + }, + { + OSPF_API_UNDEF, "Undefined", + }, + }; + + int i, n = array_size(NameTab); + const char *name = NULL; + + for (i = 0; i < n; i++) { + if (NameTab[i].value == errcode) { + name = NameTab[i].name; + break; + } + } + + return name ? name : "?"; } -void -msg_print (struct msg *msg) +void msg_print(struct msg *msg) { - if (!msg) - { - zlog_debug ("msg_print msg=NULL!\n"); - return; - } + if (!msg) { + zlog_debug("msg_print msg=NULL!\n"); + return; + } #ifdef ORIGINAL_CODING - zlog_debug - ("msg=%p msgtype=%d msglen=%d msgseq=%d streamdata=%p streamsize=%lu\n", - msg, msg->hdr.msgtype, ntohs (msg->hdr.msglen), ntohl (msg->hdr.msgseq), - STREAM_DATA (msg->s), STREAM_SIZE (msg->s)); + zlog_debug( + "msg=%p msgtype=%d msglen=%d msgseq=%d streamdata=%p streamsize=%lu\n", + msg, msg->hdr.msgtype, ntohs(msg->hdr.msglen), + ntohl(msg->hdr.msgseq), STREAM_DATA(msg->s), + STREAM_SIZE(msg->s)); #else /* ORIGINAL_CODING */ - /* API message common header part. */ - zlog_debug - ("API-msg [%s]: type(%d),len(%d),seq(%lu),data(%p),size(%zd)", - ospf_api_typename (msg->hdr.msgtype), msg->hdr.msgtype, - ntohs (msg->hdr.msglen), (unsigned long) ntohl (msg->hdr.msgseq), - STREAM_DATA (msg->s), STREAM_SIZE (msg->s)); - - /* API message body part. */ + /* API message common header part. */ + zlog_debug("API-msg [%s]: type(%d),len(%d),seq(%lu),data(%p),size(%zd)", + ospf_api_typename(msg->hdr.msgtype), msg->hdr.msgtype, + ntohs(msg->hdr.msglen), + (unsigned long)ntohl(msg->hdr.msgseq), STREAM_DATA(msg->s), + STREAM_SIZE(msg->s)); + +/* API message body part. */ #ifdef ndef - /* Generic Hex/Ascii dump */ - DumpBuf (STREAM_DATA (msg->s), STREAM_SIZE (msg->s)); /* Sorry, deleted! */ -#else /* ndef */ - /* Message-type dependent dump function. */ + /* Generic Hex/Ascii dump */ + DumpBuf(STREAM_DATA(msg->s), STREAM_SIZE(msg->s)); /* Sorry, deleted! */ +#else /* ndef */ +/* Message-type dependent dump function. */ #endif /* ndef */ - return; + return; #endif /* ORIGINAL_CODING */ } -void -msg_free (struct msg *msg) +void msg_free(struct msg *msg) { - if (msg->s) - stream_free (msg->s); + if (msg->s) + stream_free(msg->s); - XFREE (MTYPE_OSPF_API_MSG, msg); + XFREE(MTYPE_OSPF_API_MSG, msg); } /* Set sequence number of message */ -void -msg_set_seq (struct msg *msg, u_int32_t seqnr) +void msg_set_seq(struct msg *msg, u_int32_t seqnr) { - assert (msg); - msg->hdr.msgseq = htonl (seqnr); + assert(msg); + msg->hdr.msgseq = htonl(seqnr); } /* Get sequence number of message */ -u_int32_t -msg_get_seq (struct msg *msg) +u_int32_t msg_get_seq(struct msg *msg) { - assert (msg); - return ntohl (msg->hdr.msgseq); + assert(msg); + return ntohl(msg->hdr.msgseq); } /* ----------------------------------------------------------- @@ -263,178 +300,151 @@ msg_get_seq (struct msg *msg) * ----------------------------------------------------------- */ -struct msg_fifo * -msg_fifo_new () +struct msg_fifo *msg_fifo_new() { - return XCALLOC (MTYPE_OSPF_API_FIFO, sizeof (struct msg_fifo)); + return XCALLOC(MTYPE_OSPF_API_FIFO, sizeof(struct msg_fifo)); } /* Add new message to fifo. */ -void -msg_fifo_push (struct msg_fifo *fifo, struct msg *msg) +void msg_fifo_push(struct msg_fifo *fifo, struct msg *msg) { - if (fifo->tail) - fifo->tail->next = msg; - else - fifo->head = msg; + if (fifo->tail) + fifo->tail->next = msg; + else + fifo->head = msg; - fifo->tail = msg; - fifo->count++; + fifo->tail = msg; + fifo->count++; } /* Remove first message from fifo. */ -struct msg * -msg_fifo_pop (struct msg_fifo *fifo) +struct msg *msg_fifo_pop(struct msg_fifo *fifo) { - struct msg *msg; + struct msg *msg; - msg = fifo->head; - if (msg) - { - fifo->head = msg->next; + msg = fifo->head; + if (msg) { + fifo->head = msg->next; - if (fifo->head == NULL) - fifo->tail = NULL; + if (fifo->head == NULL) + fifo->tail = NULL; - fifo->count--; - } - return msg; + fifo->count--; + } + return msg; } /* Return first fifo entry but do not remove it. */ -struct msg * -msg_fifo_head (struct msg_fifo *fifo) +struct msg *msg_fifo_head(struct msg_fifo *fifo) { - return fifo->head; + return fifo->head; } /* Flush message fifo. */ -void -msg_fifo_flush (struct msg_fifo *fifo) +void msg_fifo_flush(struct msg_fifo *fifo) { - struct msg *op; - struct msg *next; + struct msg *op; + struct msg *next; - for (op = fifo->head; op; op = next) - { - next = op->next; - msg_free (op); - } + for (op = fifo->head; op; op = next) { + next = op->next; + msg_free(op); + } - fifo->head = fifo->tail = NULL; - fifo->count = 0; + fifo->head = fifo->tail = NULL; + fifo->count = 0; } /* Free API message fifo. */ -void -msg_fifo_free (struct msg_fifo *fifo) +void msg_fifo_free(struct msg_fifo *fifo) { - msg_fifo_flush (fifo); + msg_fifo_flush(fifo); - XFREE (MTYPE_OSPF_API_FIFO, fifo); + XFREE(MTYPE_OSPF_API_FIFO, fifo); } -struct msg * -msg_read (int fd) +struct msg *msg_read(int fd) { - struct msg *msg; - struct apimsghdr hdr; - u_char buf[OSPF_API_MAX_MSG_SIZE]; - int bodylen; - int rlen; - - /* Read message header */ - rlen = readn (fd, (u_char *) &hdr, sizeof (struct apimsghdr)); - - if (rlen < 0) - { - zlog_warn ("msg_read: readn %s", safe_strerror (errno)); - return NULL; - } - else if (rlen == 0) - { - zlog_warn ("msg_read: Connection closed by peer"); - return NULL; - } - else if (rlen != sizeof (struct apimsghdr)) - { - zlog_warn ("msg_read: Cannot read message header!"); - return NULL; - } - - /* Check version of API protocol */ - if (hdr.version != OSPF_API_VERSION) - { - zlog_warn ("msg_read: OSPF API protocol version mismatch"); - return NULL; - } - - /* Determine body length. */ - bodylen = ntohs (hdr.msglen); - if (bodylen > 0) - { - - /* Read message body */ - rlen = readn (fd, buf, bodylen); - if (rlen < 0) - { - zlog_warn ("msg_read: readn %s", safe_strerror (errno)); - return NULL; + struct msg *msg; + struct apimsghdr hdr; + u_char buf[OSPF_API_MAX_MSG_SIZE]; + int bodylen; + int rlen; + + /* Read message header */ + rlen = readn(fd, (u_char *)&hdr, sizeof(struct apimsghdr)); + + if (rlen < 0) { + zlog_warn("msg_read: readn %s", safe_strerror(errno)); + return NULL; + } else if (rlen == 0) { + zlog_warn("msg_read: Connection closed by peer"); + return NULL; + } else if (rlen != sizeof(struct apimsghdr)) { + zlog_warn("msg_read: Cannot read message header!"); + return NULL; } - else if (rlen == 0) - { - zlog_warn ("msg_read: Connection closed by peer"); - return NULL; + + /* Check version of API protocol */ + if (hdr.version != OSPF_API_VERSION) { + zlog_warn("msg_read: OSPF API protocol version mismatch"); + return NULL; } - else if (rlen != bodylen) - { - zlog_warn ("msg_read: Cannot read message body!"); - return NULL; + + /* Determine body length. */ + bodylen = ntohs(hdr.msglen); + if (bodylen > 0) { + + /* Read message body */ + rlen = readn(fd, buf, bodylen); + if (rlen < 0) { + zlog_warn("msg_read: readn %s", safe_strerror(errno)); + return NULL; + } else if (rlen == 0) { + zlog_warn("msg_read: Connection closed by peer"); + return NULL; + } else if (rlen != bodylen) { + zlog_warn("msg_read: Cannot read message body!"); + return NULL; + } } - } - /* Allocate new message */ - msg = msg_new (hdr.msgtype, buf, ntohl (hdr.msgseq), ntohs (hdr.msglen)); + /* Allocate new message */ + msg = msg_new(hdr.msgtype, buf, ntohl(hdr.msgseq), ntohs(hdr.msglen)); - return msg; + return msg; } -int -msg_write (int fd, struct msg *msg) +int msg_write(int fd, struct msg *msg) { - u_char buf[OSPF_API_MAX_MSG_SIZE]; - int l; - int wlen; - - assert (msg); - assert (msg->s); - - /* Length of message including header */ - l = sizeof (struct apimsghdr) + ntohs (msg->hdr.msglen); - - /* Make contiguous memory buffer for message */ - memcpy (buf, &msg->hdr, sizeof (struct apimsghdr)); - memcpy (buf + sizeof (struct apimsghdr), STREAM_DATA (msg->s), - ntohs (msg->hdr.msglen)); - - wlen = writen (fd, buf, l); - if (wlen < 0) - { - zlog_warn ("msg_write: writen %s", safe_strerror (errno)); - return -1; - } - else if (wlen == 0) - { - zlog_warn ("msg_write: Connection closed by peer"); - return -1; - } - else if (wlen != l) - { - zlog_warn ("msg_write: Cannot write API message"); - return -1; - } - return 0; + u_char buf[OSPF_API_MAX_MSG_SIZE]; + int l; + int wlen; + + assert(msg); + assert(msg->s); + + /* Length of message including header */ + l = sizeof(struct apimsghdr) + ntohs(msg->hdr.msglen); + + /* Make contiguous memory buffer for message */ + memcpy(buf, &msg->hdr, sizeof(struct apimsghdr)); + memcpy(buf + sizeof(struct apimsghdr), STREAM_DATA(msg->s), + ntohs(msg->hdr.msglen)); + + wlen = writen(fd, buf, l); + if (wlen < 0) { + zlog_warn("msg_write: writen %s", safe_strerror(errno)); + return -1; + } else if (wlen == 0) { + zlog_warn("msg_write: Connection closed by peer"); + return -1; + } else if (wlen != l) { + zlog_warn("msg_write: Cannot write API message"); + return -1; + } + return 0; } /* ----------------------------------------------------------- @@ -442,207 +452,201 @@ msg_write (int fd, struct msg *msg) * ----------------------------------------------------------- */ -struct msg * -new_msg_register_opaque_type (u_int32_t seqnum, u_char ltype, u_char otype) +struct msg *new_msg_register_opaque_type(u_int32_t seqnum, u_char ltype, + u_char otype) { - struct msg_register_opaque_type rmsg; + struct msg_register_opaque_type rmsg; - rmsg.lsatype = ltype; - rmsg.opaquetype = otype; - memset (&rmsg.pad, 0, sizeof (rmsg.pad)); + rmsg.lsatype = ltype; + rmsg.opaquetype = otype; + memset(&rmsg.pad, 0, sizeof(rmsg.pad)); - return msg_new (MSG_REGISTER_OPAQUETYPE, &rmsg, seqnum, - sizeof (struct msg_register_opaque_type)); + return msg_new(MSG_REGISTER_OPAQUETYPE, &rmsg, seqnum, + sizeof(struct msg_register_opaque_type)); } -struct msg * -new_msg_register_event (u_int32_t seqnum, struct lsa_filter_type *filter) +struct msg *new_msg_register_event(u_int32_t seqnum, + struct lsa_filter_type *filter) { - u_char buf[OSPF_API_MAX_MSG_SIZE]; - struct msg_register_event *emsg; - unsigned int len; - - emsg = (struct msg_register_event *) buf; - len = sizeof (struct msg_register_event) + - filter->num_areas * sizeof (struct in_addr); - emsg->filter.typemask = htons (filter->typemask); - emsg->filter.origin = filter->origin; - emsg->filter.num_areas = filter->num_areas; - if (len > sizeof (buf)) - len = sizeof(buf); - /* API broken - missing memcpy to fill data */ - return msg_new (MSG_REGISTER_EVENT, emsg, seqnum, len); + u_char buf[OSPF_API_MAX_MSG_SIZE]; + struct msg_register_event *emsg; + unsigned int len; + + emsg = (struct msg_register_event *)buf; + len = sizeof(struct msg_register_event) + + filter->num_areas * sizeof(struct in_addr); + emsg->filter.typemask = htons(filter->typemask); + emsg->filter.origin = filter->origin; + emsg->filter.num_areas = filter->num_areas; + if (len > sizeof(buf)) + len = sizeof(buf); + /* API broken - missing memcpy to fill data */ + return msg_new(MSG_REGISTER_EVENT, emsg, seqnum, len); } -struct msg * -new_msg_sync_lsdb (u_int32_t seqnum, struct lsa_filter_type *filter) +struct msg *new_msg_sync_lsdb(u_int32_t seqnum, struct lsa_filter_type *filter) { - u_char buf[OSPF_API_MAX_MSG_SIZE]; - struct msg_sync_lsdb *smsg; - unsigned int len; - - smsg = (struct msg_sync_lsdb *) buf; - len = sizeof (struct msg_sync_lsdb) + - filter->num_areas * sizeof (struct in_addr); - smsg->filter.typemask = htons (filter->typemask); - smsg->filter.origin = filter->origin; - smsg->filter.num_areas = filter->num_areas; - if (len > sizeof (buf)) - len = sizeof(buf); - /* API broken - missing memcpy to fill data */ - return msg_new (MSG_SYNC_LSDB, smsg, seqnum, len); + u_char buf[OSPF_API_MAX_MSG_SIZE]; + struct msg_sync_lsdb *smsg; + unsigned int len; + + smsg = (struct msg_sync_lsdb *)buf; + len = sizeof(struct msg_sync_lsdb) + + filter->num_areas * sizeof(struct in_addr); + smsg->filter.typemask = htons(filter->typemask); + smsg->filter.origin = filter->origin; + smsg->filter.num_areas = filter->num_areas; + if (len > sizeof(buf)) + len = sizeof(buf); + /* API broken - missing memcpy to fill data */ + return msg_new(MSG_SYNC_LSDB, smsg, seqnum, len); } -struct msg * -new_msg_originate_request (u_int32_t seqnum, - struct in_addr ifaddr, - struct in_addr area_id, struct lsa_header *data) +struct msg *new_msg_originate_request(u_int32_t seqnum, struct in_addr ifaddr, + struct in_addr area_id, + struct lsa_header *data) { - struct msg_originate_request *omsg; - unsigned int omsglen; - char buf[OSPF_API_MAX_MSG_SIZE]; - - omsg = (struct msg_originate_request *) buf; - omsg->ifaddr = ifaddr; - omsg->area_id = area_id; - - omsglen = ntohs (data->length); - if (omsglen > sizeof (buf) - offsetof (struct msg_originate_request, data)) - omsglen = sizeof (buf) - offsetof (struct msg_originate_request, data); - memcpy (&omsg->data, data, omsglen); - omsglen += sizeof (struct msg_originate_request) - sizeof (struct lsa_header); - - return msg_new (MSG_ORIGINATE_REQUEST, omsg, seqnum, omsglen); + struct msg_originate_request *omsg; + unsigned int omsglen; + char buf[OSPF_API_MAX_MSG_SIZE]; + + omsg = (struct msg_originate_request *)buf; + omsg->ifaddr = ifaddr; + omsg->area_id = area_id; + + omsglen = ntohs(data->length); + if (omsglen + > sizeof(buf) - offsetof(struct msg_originate_request, data)) + omsglen = sizeof(buf) + - offsetof(struct msg_originate_request, data); + memcpy(&omsg->data, data, omsglen); + omsglen += sizeof(struct msg_originate_request) + - sizeof(struct lsa_header); + + return msg_new(MSG_ORIGINATE_REQUEST, omsg, seqnum, omsglen); } -struct msg * -new_msg_delete_request (u_int32_t seqnum, - struct in_addr area_id, u_char lsa_type, - u_char opaque_type, u_int32_t opaque_id) +struct msg *new_msg_delete_request(u_int32_t seqnum, struct in_addr area_id, + u_char lsa_type, u_char opaque_type, + u_int32_t opaque_id) { - struct msg_delete_request dmsg; - dmsg.area_id = area_id; - dmsg.lsa_type = lsa_type; - dmsg.opaque_type = opaque_type; - dmsg.opaque_id = htonl (opaque_id); - memset (&dmsg.pad, 0, sizeof (dmsg.pad)); - - return msg_new (MSG_DELETE_REQUEST, &dmsg, seqnum, - sizeof (struct msg_delete_request)); + struct msg_delete_request dmsg; + dmsg.area_id = area_id; + dmsg.lsa_type = lsa_type; + dmsg.opaque_type = opaque_type; + dmsg.opaque_id = htonl(opaque_id); + memset(&dmsg.pad, 0, sizeof(dmsg.pad)); + + return msg_new(MSG_DELETE_REQUEST, &dmsg, seqnum, + sizeof(struct msg_delete_request)); } -struct msg * -new_msg_reply (u_int32_t seqnr, u_char rc) +struct msg *new_msg_reply(u_int32_t seqnr, u_char rc) { - struct msg *msg; - struct msg_reply rmsg; + struct msg *msg; + struct msg_reply rmsg; - /* Set return code */ - rmsg.errcode = rc; - memset (&rmsg.pad, 0, sizeof (rmsg.pad)); + /* Set return code */ + rmsg.errcode = rc; + memset(&rmsg.pad, 0, sizeof(rmsg.pad)); - msg = msg_new (MSG_REPLY, &rmsg, seqnr, sizeof (struct msg_reply)); + msg = msg_new(MSG_REPLY, &rmsg, seqnr, sizeof(struct msg_reply)); - return msg; + return msg; } -struct msg * -new_msg_ready_notify (u_int32_t seqnr, u_char lsa_type, - u_char opaque_type, struct in_addr addr) +struct msg *new_msg_ready_notify(u_int32_t seqnr, u_char lsa_type, + u_char opaque_type, struct in_addr addr) { - struct msg_ready_notify rmsg; + struct msg_ready_notify rmsg; - rmsg.lsa_type = lsa_type; - rmsg.opaque_type = opaque_type; - memset (&rmsg.pad, 0, sizeof (rmsg.pad)); - rmsg.addr = addr; + rmsg.lsa_type = lsa_type; + rmsg.opaque_type = opaque_type; + memset(&rmsg.pad, 0, sizeof(rmsg.pad)); + rmsg.addr = addr; - return msg_new (MSG_READY_NOTIFY, &rmsg, seqnr, - sizeof (struct msg_ready_notify)); + return msg_new(MSG_READY_NOTIFY, &rmsg, seqnr, + sizeof(struct msg_ready_notify)); } -struct msg * -new_msg_new_if (u_int32_t seqnr, - struct in_addr ifaddr, struct in_addr area_id) +struct msg *new_msg_new_if(u_int32_t seqnr, struct in_addr ifaddr, + struct in_addr area_id) { - struct msg_new_if nmsg; + struct msg_new_if nmsg; - nmsg.ifaddr = ifaddr; - nmsg.area_id = area_id; + nmsg.ifaddr = ifaddr; + nmsg.area_id = area_id; - return msg_new (MSG_NEW_IF, &nmsg, seqnr, sizeof (struct msg_new_if)); + return msg_new(MSG_NEW_IF, &nmsg, seqnr, sizeof(struct msg_new_if)); } -struct msg * -new_msg_del_if (u_int32_t seqnr, struct in_addr ifaddr) +struct msg *new_msg_del_if(u_int32_t seqnr, struct in_addr ifaddr) { - struct msg_del_if dmsg; + struct msg_del_if dmsg; - dmsg.ifaddr = ifaddr; + dmsg.ifaddr = ifaddr; - return msg_new (MSG_DEL_IF, &dmsg, seqnr, sizeof (struct msg_del_if)); + return msg_new(MSG_DEL_IF, &dmsg, seqnr, sizeof(struct msg_del_if)); } -struct msg * -new_msg_ism_change (u_int32_t seqnr, struct in_addr ifaddr, - struct in_addr area_id, u_char status) +struct msg *new_msg_ism_change(u_int32_t seqnr, struct in_addr ifaddr, + struct in_addr area_id, u_char status) { - struct msg_ism_change imsg; + struct msg_ism_change imsg; - imsg.ifaddr = ifaddr; - imsg.area_id = area_id; - imsg.status = status; - memset (&imsg.pad, 0, sizeof (imsg.pad)); + imsg.ifaddr = ifaddr; + imsg.area_id = area_id; + imsg.status = status; + memset(&imsg.pad, 0, sizeof(imsg.pad)); - return msg_new (MSG_ISM_CHANGE, &imsg, seqnr, - sizeof (struct msg_ism_change)); + return msg_new(MSG_ISM_CHANGE, &imsg, seqnr, + sizeof(struct msg_ism_change)); } -struct msg * -new_msg_nsm_change (u_int32_t seqnr, struct in_addr ifaddr, - struct in_addr nbraddr, - struct in_addr router_id, u_char status) +struct msg *new_msg_nsm_change(u_int32_t seqnr, struct in_addr ifaddr, + struct in_addr nbraddr, struct in_addr router_id, + u_char status) { - struct msg_nsm_change nmsg; + struct msg_nsm_change nmsg; - nmsg.ifaddr = ifaddr; - nmsg.nbraddr = nbraddr; - nmsg.router_id = router_id; - nmsg.status = status; - memset (&nmsg.pad, 0, sizeof (nmsg.pad)); + nmsg.ifaddr = ifaddr; + nmsg.nbraddr = nbraddr; + nmsg.router_id = router_id; + nmsg.status = status; + memset(&nmsg.pad, 0, sizeof(nmsg.pad)); - return msg_new (MSG_NSM_CHANGE, &nmsg, seqnr, - sizeof (struct msg_nsm_change)); + return msg_new(MSG_NSM_CHANGE, &nmsg, seqnr, + sizeof(struct msg_nsm_change)); } -struct msg * -new_msg_lsa_change_notify (u_char msgtype, - u_int32_t seqnum, - struct in_addr ifaddr, - struct in_addr area_id, - u_char is_self_originated, struct lsa_header *data) +struct msg *new_msg_lsa_change_notify(u_char msgtype, u_int32_t seqnum, + struct in_addr ifaddr, + struct in_addr area_id, + u_char is_self_originated, + struct lsa_header *data) { - u_char buf[OSPF_API_MAX_MSG_SIZE]; - struct msg_lsa_change_notify *nmsg; - unsigned int len; - - assert (data); - - nmsg = (struct msg_lsa_change_notify *) buf; - nmsg->ifaddr = ifaddr; - nmsg->area_id = area_id; - nmsg->is_self_originated = is_self_originated; - memset (&nmsg->pad, 0, sizeof (nmsg->pad)); - - len = ntohs (data->length); - if (len > sizeof (buf) - offsetof (struct msg_lsa_change_notify, data)) - len = sizeof (buf) - offsetof (struct msg_lsa_change_notify, data); - memcpy (&nmsg->data, data, len); - len += sizeof (struct msg_lsa_change_notify) - sizeof (struct lsa_header); - - return msg_new (msgtype, nmsg, seqnum, len); + u_char buf[OSPF_API_MAX_MSG_SIZE]; + struct msg_lsa_change_notify *nmsg; + unsigned int len; + + assert(data); + + nmsg = (struct msg_lsa_change_notify *)buf; + nmsg->ifaddr = ifaddr; + nmsg->area_id = area_id; + nmsg->is_self_originated = is_self_originated; + memset(&nmsg->pad, 0, sizeof(nmsg->pad)); + + len = ntohs(data->length); + if (len > sizeof(buf) - offsetof(struct msg_lsa_change_notify, data)) + len = sizeof(buf) + - offsetof(struct msg_lsa_change_notify, data); + memcpy(&nmsg->data, data, len); + len += sizeof(struct msg_lsa_change_notify) - sizeof(struct lsa_header); + + return msg_new(msgtype, nmsg, seqnum, len); } #endif /* SUPPORT_OSPF_API */ diff --git a/ospfd/ospf_api.h b/ospfd/ospf_api.h index ee18c8934..526e8228f 100644 --- a/ospfd/ospf_api.h +++ b/ospfd/ospf_api.h @@ -37,40 +37,38 @@ #define OSPF_API_SYNC_PORT 2607 /* ----------------------------------------------------------- - * Generic messages + * Generic messages * ----------------------------------------------------------- */ /* Message header structure, fields are in network byte order and aligned to four octets. */ -struct apimsghdr -{ - u_char version; /* OSPF API protocol version */ - u_char msgtype; /* Type of message */ - u_int16_t msglen; /* Length of message w/o header */ - u_int32_t msgseq; /* Sequence number */ +struct apimsghdr { + u_char version; /* OSPF API protocol version */ + u_char msgtype; /* Type of message */ + u_int16_t msglen; /* Length of message w/o header */ + u_int32_t msgseq; /* Sequence number */ }; /* Message representation with header and body */ -struct msg -{ - struct msg *next; /* to link into fifo */ +struct msg { + struct msg *next; /* to link into fifo */ - /* Message header */ - struct apimsghdr hdr; + /* Message header */ + struct apimsghdr hdr; - /* Message body */ - struct stream *s; + /* Message body */ + struct stream *s; }; /* Prototypes for generic messages. */ -extern struct msg *msg_new (u_char msgtype, void *msgbody, - u_int32_t seqnum, u_int16_t msglen); -extern struct msg *msg_dup (struct msg *msg); -extern void msg_print (struct msg *msg); /* XXX debug only */ -extern void msg_free (struct msg *msg); -struct msg *msg_read (int fd); -extern int msg_write (int fd, struct msg *msg); +extern struct msg *msg_new(u_char msgtype, void *msgbody, u_int32_t seqnum, + u_int16_t msglen); +extern struct msg *msg_dup(struct msg *msg); +extern void msg_print(struct msg *msg); /* XXX debug only */ +extern void msg_free(struct msg *msg); +struct msg *msg_read(int fd); +extern int msg_write(int fd, struct msg *msg); /* For requests, the message sequence number is between MIN_SEQ and MAX_SEQ. For notifications, the sequence number is 0. */ @@ -78,8 +76,8 @@ extern int msg_write (int fd, struct msg *msg); #define MIN_SEQ 1 #define MAX_SEQ 2147483647 -extern void msg_set_seq (struct msg *msg, u_int32_t seqnr); -extern u_int32_t msg_get_seq (struct msg *msg); +extern void msg_set_seq(struct msg *msg, u_int32_t seqnr); +extern u_int32_t msg_get_seq(struct msg *msg); /* ----------------------------------------------------------- * Message fifo queues @@ -87,21 +85,20 @@ extern u_int32_t msg_get_seq (struct msg *msg); */ /* Message queue structure. */ -struct msg_fifo -{ - unsigned long count; +struct msg_fifo { + unsigned long count; - struct msg *head; - struct msg *tail; + struct msg *head; + struct msg *tail; }; /* Prototype for message fifo queues. */ -extern struct msg_fifo *msg_fifo_new (void); -extern void msg_fifo_push (struct msg_fifo *, struct msg *msg); -extern struct msg *msg_fifo_pop (struct msg_fifo *fifo); -extern struct msg *msg_fifo_head (struct msg_fifo *fifo); -extern void msg_fifo_flush (struct msg_fifo *fifo); -extern void msg_fifo_free (struct msg_fifo *fifo); +extern struct msg_fifo *msg_fifo_new(void); +extern void msg_fifo_push(struct msg_fifo *, struct msg *msg); +extern struct msg *msg_fifo_pop(struct msg_fifo *fifo); +extern struct msg *msg_fifo_head(struct msg_fifo *fifo); +extern void msg_fifo_flush(struct msg_fifo *fifo); +extern void msg_fifo_free(struct msg_fifo *fifo); /* ----------------------------------------------------------- * Specific message type and format definitions @@ -126,18 +123,16 @@ extern void msg_fifo_free (struct msg_fifo *fifo); #define MSG_ISM_CHANGE 16 #define MSG_NSM_CHANGE 17 -struct msg_register_opaque_type -{ - u_char lsatype; - u_char opaquetype; - u_char pad[2]; /* padding */ +struct msg_register_opaque_type { + u_char lsatype; + u_char opaquetype; + u_char pad[2]; /* padding */ }; -struct msg_unregister_opaque_type -{ - u_char lsatype; - u_char opaquetype; - u_char pad[2]; /* padding */ +struct msg_unregister_opaque_type { + u_char lsatype; + u_char opaquetype; + u_char pad[2]; /* padding */ }; /* Power2 is needed to convert LSA types into bit positions, @@ -146,65 +141,58 @@ struct msg_unregister_opaque_type #ifdef ORIGINAL_CODING -static const u_int16_t - Power2[] = { 0x0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, - 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000 -}; +static const u_int16_t Power2[] = {0x0, 0x1, 0x2, 0x4, 0x8, 0x10, + 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, + 0x800, 0x1000, 0x2000, 0x4000, 0x8000}; #else -static const u_int16_t - Power2[] = { 0, (1 << 0), (1 << 1), (1 << 2), (1 << 3), (1 << 4), - (1 << 5), (1 << 6), (1 << 7), (1 << 8), (1 << 9), - (1 << 10), (1 << 11), (1 << 12), (1 << 13), (1 << 14), - (1 << 15) -}; +static const u_int16_t Power2[] = { + 0, (1 << 0), (1 << 1), (1 << 2), (1 << 3), (1 << 4), + (1 << 5), (1 << 6), (1 << 7), (1 << 8), (1 << 9), (1 << 10), + (1 << 11), (1 << 12), (1 << 13), (1 << 14), (1 << 15)}; #endif /* ORIGINAL_CODING */ -struct lsa_filter_type -{ - u_int16_t typemask; /* bitmask for selecting LSA types (1..16) */ - u_char origin; /* selects according to origin. */ +struct lsa_filter_type { + u_int16_t typemask; /* bitmask for selecting LSA types (1..16) */ + u_char origin; /* selects according to origin. */ + /* $FRR indent$ */ + /* clang-format off */ #define NON_SELF_ORIGINATED 0 #define SELF_ORIGINATED (OSPF_LSA_SELF) #define ANY_ORIGIN 2 - u_char num_areas; /* number of areas in the filter. */ - /* areas, if any, go here. */ + u_char num_areas; /* number of areas in the filter. */ + /* areas, if any, go here. */ }; -struct msg_register_event -{ - struct lsa_filter_type filter; +struct msg_register_event { + struct lsa_filter_type filter; }; -struct msg_sync_lsdb -{ - struct lsa_filter_type filter; +struct msg_sync_lsdb { + struct lsa_filter_type filter; }; -struct msg_originate_request -{ - /* Used for LSA type 9 otherwise ignored */ - struct in_addr ifaddr; +struct msg_originate_request { + /* Used for LSA type 9 otherwise ignored */ + struct in_addr ifaddr; - /* Used for LSA type 10 otherwise ignored */ - struct in_addr area_id; + /* Used for LSA type 10 otherwise ignored */ + struct in_addr area_id; - /* LSA header and LSA-specific part */ - struct lsa_header data; + /* LSA header and LSA-specific part */ + struct lsa_header data; }; -struct msg_delete_request -{ - struct in_addr area_id; /* "0.0.0.0" for AS-external opaque LSAs */ - u_char lsa_type; - u_char opaque_type; - u_char pad[2]; /* padding */ - u_int32_t opaque_id; +struct msg_delete_request { + struct in_addr area_id; /* "0.0.0.0" for AS-external opaque LSAs */ + u_char lsa_type; + u_char opaque_type; + u_char pad[2]; /* padding */ + u_int32_t opaque_id; }; -struct msg_reply -{ - signed char errcode; +struct msg_reply { + signed char errcode; #define OSPF_API_OK 0 #define OSPF_API_NOSUCHINTERFACE (-1) #define OSPF_API_NOSUCHAREA (-2) @@ -216,85 +204,76 @@ struct msg_reply #define OSPF_API_NOMEMORY (-8) #define OSPF_API_ERROR (-9) #define OSPF_API_UNDEF (-10) - u_char pad[3]; /* padding to four byte alignment */ + u_char pad[3]; /* padding to four byte alignment */ }; -/* Message to tell client application that it ospf daemon is +/* Message to tell client application that it ospf daemon is * ready to accept opaque LSAs for a given interface or area. */ -struct msg_ready_notify -{ - u_char lsa_type; - u_char opaque_type; - u_char pad[2]; /* padding */ - struct in_addr addr; /* interface address or area address */ +struct msg_ready_notify { + u_char lsa_type; + u_char opaque_type; + u_char pad[2]; /* padding */ + struct in_addr addr; /* interface address or area address */ }; /* These messages have a dynamic length depending on the embodied LSA. They are aligned to four octets. msg_lsa_change_notify is used for both LSA update and LSAs delete. */ -struct msg_lsa_change_notify -{ - /* Used for LSA type 9 otherwise ignored */ - struct in_addr ifaddr; - /* Area ID. Not valid for AS-External and Opaque11 LSAs. */ - struct in_addr area_id; - u_char is_self_originated; /* 1 if self originated. */ - u_char pad[3]; - struct lsa_header data; +struct msg_lsa_change_notify { + /* Used for LSA type 9 otherwise ignored */ + struct in_addr ifaddr; + /* Area ID. Not valid for AS-External and Opaque11 LSAs. */ + struct in_addr area_id; + u_char is_self_originated; /* 1 if self originated. */ + u_char pad[3]; + struct lsa_header data; }; -struct msg_new_if -{ - struct in_addr ifaddr; /* interface IP address */ - struct in_addr area_id; /* area this interface belongs to */ +struct msg_new_if { + struct in_addr ifaddr; /* interface IP address */ + struct in_addr area_id; /* area this interface belongs to */ }; -struct msg_del_if -{ - struct in_addr ifaddr; /* interface IP address */ +struct msg_del_if { + struct in_addr ifaddr; /* interface IP address */ }; -struct msg_ism_change -{ - struct in_addr ifaddr; /* interface IP address */ - struct in_addr area_id; /* area this interface belongs to */ - u_char status; /* interface status (up/down) */ - u_char pad[3]; /* not used */ +struct msg_ism_change { + struct in_addr ifaddr; /* interface IP address */ + struct in_addr area_id; /* area this interface belongs to */ + u_char status; /* interface status (up/down) */ + u_char pad[3]; /* not used */ }; -struct msg_nsm_change -{ - struct in_addr ifaddr; /* attached interface */ - struct in_addr nbraddr; /* Neighbor interface address */ - struct in_addr router_id; /* Router ID of neighbor */ - u_char status; /* NSM status */ - u_char pad[3]; +struct msg_nsm_change { + struct in_addr ifaddr; /* attached interface */ + struct in_addr nbraddr; /* Neighbor interface address */ + struct in_addr router_id; /* Router ID of neighbor */ + u_char status; /* NSM status */ + u_char pad[3]; }; /* We make use of a union to define a structure that covers all possible API messages. This allows us to find out how much memory needs to be reserved for the largest API message. */ -struct apimsg -{ - struct apimsghdr hdr; - union - { - struct msg_register_opaque_type register_opaque_type; - struct msg_register_event register_event; - struct msg_sync_lsdb sync_lsdb; - struct msg_originate_request originate_request; - struct msg_delete_request delete_request; - struct msg_reply reply; - struct msg_ready_notify ready_notify; - struct msg_new_if new_if; - struct msg_del_if del_if; - struct msg_ism_change ism_change; - struct msg_nsm_change nsm_change; - struct msg_lsa_change_notify lsa_change_notify; - } - u; +struct apimsg { + struct apimsghdr hdr; + union { + struct msg_register_opaque_type register_opaque_type; + struct msg_register_event register_event; + struct msg_sync_lsdb sync_lsdb; + struct msg_originate_request originate_request; + struct msg_delete_request delete_request; + struct msg_reply reply; + struct msg_ready_notify ready_notify; + struct msg_new_if new_if; + struct msg_del_if del_if; + struct msg_ism_change ism_change; + struct msg_nsm_change nsm_change; + struct msg_lsa_change_notify lsa_change_notify; + } u; }; #define OSPF_API_MAX_MSG_SIZE (sizeof(struct apimsg) + OSPF_MAX_LSA_SIZE) @@ -305,56 +284,52 @@ struct apimsg */ /* For debugging only. */ -extern void api_opaque_lsa_print (struct lsa_header *data); +extern void api_opaque_lsa_print(struct lsa_header *data); /* Messages sent by client */ -extern struct msg *new_msg_register_opaque_type (u_int32_t seqnum, - u_char ltype, u_char otype); -extern struct msg *new_msg_register_event (u_int32_t seqnum, - struct lsa_filter_type *filter); -extern struct msg *new_msg_sync_lsdb (u_int32_t seqnum, - struct lsa_filter_type *filter); -extern struct msg *new_msg_originate_request (u_int32_t seqnum, - struct in_addr ifaddr, - struct in_addr area_id, - struct lsa_header *data); -extern struct msg *new_msg_delete_request (u_int32_t seqnum, - struct in_addr area_id, - u_char lsa_type, - u_char opaque_type, - u_int32_t opaque_id); +extern struct msg *new_msg_register_opaque_type(u_int32_t seqnum, u_char ltype, + u_char otype); +extern struct msg *new_msg_register_event(u_int32_t seqnum, + struct lsa_filter_type *filter); +extern struct msg *new_msg_sync_lsdb(u_int32_t seqnum, + struct lsa_filter_type *filter); +extern struct msg *new_msg_originate_request(u_int32_t seqnum, + struct in_addr ifaddr, + struct in_addr area_id, + struct lsa_header *data); +extern struct msg *new_msg_delete_request(u_int32_t seqnum, + struct in_addr area_id, + u_char lsa_type, u_char opaque_type, + u_int32_t opaque_id); /* Messages sent by OSPF daemon */ -extern struct msg *new_msg_reply (u_int32_t seqnum, u_char rc); +extern struct msg *new_msg_reply(u_int32_t seqnum, u_char rc); -extern struct msg *new_msg_ready_notify (u_int32_t seqnr, u_char lsa_type, - u_char opaque_type, - struct in_addr addr); +extern struct msg *new_msg_ready_notify(u_int32_t seqnr, u_char lsa_type, + u_char opaque_type, + struct in_addr addr); -extern struct msg *new_msg_new_if (u_int32_t seqnr, - struct in_addr ifaddr, - struct in_addr area); +extern struct msg *new_msg_new_if(u_int32_t seqnr, struct in_addr ifaddr, + struct in_addr area); -extern struct msg *new_msg_del_if (u_int32_t seqnr, struct in_addr ifaddr); +extern struct msg *new_msg_del_if(u_int32_t seqnr, struct in_addr ifaddr); -extern struct msg *new_msg_ism_change (u_int32_t seqnr, struct in_addr ifaddr, - struct in_addr area, u_char status); +extern struct msg *new_msg_ism_change(u_int32_t seqnr, struct in_addr ifaddr, + struct in_addr area, u_char status); -extern struct msg *new_msg_nsm_change (u_int32_t seqnr, struct in_addr ifaddr, - struct in_addr nbraddr, - struct in_addr router_id, - u_char status); +extern struct msg *new_msg_nsm_change(u_int32_t seqnr, struct in_addr ifaddr, + struct in_addr nbraddr, + struct in_addr router_id, u_char status); /* msgtype is MSG_LSA_UPDATE_NOTIFY or MSG_LSA_DELETE_NOTIFY */ -extern struct msg *new_msg_lsa_change_notify (u_char msgtype, - u_int32_t seqnum, - struct in_addr ifaddr, - struct in_addr area_id, - u_char is_self_originated, - struct lsa_header *data); +extern struct msg *new_msg_lsa_change_notify(u_char msgtype, u_int32_t seqnum, + struct in_addr ifaddr, + struct in_addr area_id, + u_char is_self_originated, + struct lsa_header *data); /* string printing functions */ -extern const char *ospf_api_errname (int errcode); -extern const char *ospf_api_typename (int msgtype); +extern const char *ospf_api_errname(int errcode); +extern const char *ospf_api_typename(int msgtype); #endif /* _OSPF_API_H */ diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c index 2b72abcd7..a5f5971ac 100644 --- a/ospfd/ospf_apiserver.c +++ b/ospfd/ospf_apiserver.c @@ -34,12 +34,12 @@ #include "log.h" #include "thread.h" #include "hash.h" -#include "sockunion.h" /* for inet_aton() */ +#include "sockunion.h" /* for inet_aton() */ #include "buffer.h" #include -#include "ospfd/ospfd.h" /* for "struct thread_master" */ +#include "ospfd/ospfd.h" /* for "struct thread_master" */ #include "ospfd/ospf_interface.h" #include "ospfd/ospf_ism.h" #include "ospfd/ospf_asbr.h" @@ -76,39 +76,37 @@ struct list *apiserver_list; * ----------------------------------------------------------- */ -struct ospf_interface * -ospf_apiserver_if_lookup_by_addr (struct in_addr address) +struct ospf_interface *ospf_apiserver_if_lookup_by_addr(struct in_addr address) { - struct listnode *node, *nnode; - struct ospf_interface *oi; - struct ospf *ospf; + struct listnode *node, *nnode; + struct ospf_interface *oi; + struct ospf *ospf; - if (!(ospf = ospf_lookup ())) - return NULL; + if (!(ospf = ospf_lookup())) + return NULL; - for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) - if (oi->type != OSPF_IFTYPE_VIRTUALLINK) - if (IPV4_ADDR_SAME (&address, &oi->address->u.prefix4)) - return oi; + for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) + if (oi->type != OSPF_IFTYPE_VIRTUALLINK) + if (IPV4_ADDR_SAME(&address, &oi->address->u.prefix4)) + return oi; - return NULL; + return NULL; } -struct ospf_interface * -ospf_apiserver_if_lookup_by_ifp (struct interface *ifp) +struct ospf_interface *ospf_apiserver_if_lookup_by_ifp(struct interface *ifp) { - struct listnode *node, *nnode; - struct ospf_interface *oi; - struct ospf *ospf; + struct listnode *node, *nnode; + struct ospf_interface *oi; + struct ospf *ospf; - if (!(ospf = ospf_lookup ())) - return NULL; + if (!(ospf = ospf_lookup())) + return NULL; - for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) - if (oi->ifp == ifp) - return oi; + for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) + if (oi->ifp == ifp) + return oi; - return NULL; + return NULL; } /* ----------------------------------------------------------- @@ -116,644 +114,604 @@ ospf_apiserver_if_lookup_by_ifp (struct interface *ifp) * ----------------------------------------------------------- */ -unsigned short -ospf_apiserver_getport (void) +unsigned short ospf_apiserver_getport(void) { - struct servent *sp = getservbyname ("ospfapi", "tcp"); + struct servent *sp = getservbyname("ospfapi", "tcp"); - return sp ? ntohs (sp->s_port) : OSPF_API_SYNC_PORT; + return sp ? ntohs(sp->s_port) : OSPF_API_SYNC_PORT; } /* Initialize OSPF API module. Invoked from ospf_opaque_init() */ -int -ospf_apiserver_init (void) +int ospf_apiserver_init(void) { - int fd; - int rc = -1; - - /* Create new socket for synchronous messages. */ - fd = ospf_apiserver_serv_sock_family (ospf_apiserver_getport (), AF_INET); - - if (fd < 0) - goto out; - - /* Schedule new thread that handles accepted connections. */ - ospf_apiserver_event (OSPF_APISERVER_ACCEPT, fd, NULL); - - /* Initialize list that keeps track of all connections. */ - apiserver_list = list_new (); - - /* Register opaque-independent call back functions. These functions - are invoked on ISM, NSM changes and LSA update and LSA deletes */ - rc = - ospf_register_opaque_functab (0 /* all LSAs */, - 0 /* all opaque types */, - ospf_apiserver_new_if, - ospf_apiserver_del_if, - ospf_apiserver_ism_change, - ospf_apiserver_nsm_change, - NULL, - NULL, - NULL, - NULL, /* ospf_apiserver_show_info */ - NULL, /* originator_func */ - NULL, /* ospf_apiserver_lsa_refresher */ - ospf_apiserver_lsa_update, - ospf_apiserver_lsa_delete); - if (rc != 0) - { - zlog_warn ("ospf_apiserver_init: Failed to register opaque type [0/0]"); - } - - rc = 0; + int fd; + int rc = -1; + + /* Create new socket for synchronous messages. */ + fd = ospf_apiserver_serv_sock_family(ospf_apiserver_getport(), AF_INET); + + if (fd < 0) + goto out; + + /* Schedule new thread that handles accepted connections. */ + ospf_apiserver_event(OSPF_APISERVER_ACCEPT, fd, NULL); + + /* Initialize list that keeps track of all connections. */ + apiserver_list = list_new(); + + /* Register opaque-independent call back functions. These functions + are invoked on ISM, NSM changes and LSA update and LSA deletes */ + rc = ospf_register_opaque_functab( + 0 /* all LSAs */, 0 /* all opaque types */, + ospf_apiserver_new_if, ospf_apiserver_del_if, + ospf_apiserver_ism_change, ospf_apiserver_nsm_change, NULL, + NULL, NULL, NULL, /* ospf_apiserver_show_info */ + NULL, /* originator_func */ + NULL, /* ospf_apiserver_lsa_refresher */ + ospf_apiserver_lsa_update, ospf_apiserver_lsa_delete); + if (rc != 0) { + zlog_warn( + "ospf_apiserver_init: Failed to register opaque type [0/0]"); + } + + rc = 0; out: - return rc; + return rc; } /* Terminate OSPF API module. */ -void -ospf_apiserver_term (void) +void ospf_apiserver_term(void) { - struct ospf_apiserver *apiserv; - - /* Unregister wildcard [0/0] type */ - ospf_delete_opaque_functab (0 /* all LSAs */, - 0 /* all opaque types */); - - /* - * Free all client instances. ospf_apiserver_free removes the node - * from the list, so we examine the head of the list anew each time. - */ - while ( apiserver_list && - (apiserv = listgetdata (listhead (apiserver_list))) != NULL) - ospf_apiserver_free (apiserv); - - /* Free client list itself */ - if (apiserver_list) - list_delete (apiserver_list); - - /* Free wildcard list */ - /* XXX */ + struct ospf_apiserver *apiserv; + + /* Unregister wildcard [0/0] type */ + ospf_delete_opaque_functab(0 /* all LSAs */, 0 /* all opaque types */); + + /* + * Free all client instances. ospf_apiserver_free removes the node + * from the list, so we examine the head of the list anew each time. + */ + while (apiserver_list + && (apiserv = listgetdata(listhead(apiserver_list))) != NULL) + ospf_apiserver_free(apiserv); + + /* Free client list itself */ + if (apiserver_list) + list_delete(apiserver_list); + + /* Free wildcard list */ + /* XXX */ } -static struct ospf_apiserver * -lookup_apiserver (u_char lsa_type, u_char opaque_type) +static struct ospf_apiserver *lookup_apiserver(u_char lsa_type, + u_char opaque_type) { - struct listnode *n1, *n2; - struct registered_opaque_type *r; - struct ospf_apiserver *apiserv, *found = NULL; - - /* XXX: this approaches O(n**2) */ - for (ALL_LIST_ELEMENTS_RO (apiserver_list, n1, apiserv)) - { - for (ALL_LIST_ELEMENTS_RO (apiserv->opaque_types, n2, r)) - if (r->lsa_type == lsa_type && r->opaque_type == opaque_type) - { - found = apiserv; - goto out; - } - } + struct listnode *n1, *n2; + struct registered_opaque_type *r; + struct ospf_apiserver *apiserv, *found = NULL; + + /* XXX: this approaches O(n**2) */ + for (ALL_LIST_ELEMENTS_RO(apiserver_list, n1, apiserv)) { + for (ALL_LIST_ELEMENTS_RO(apiserv->opaque_types, n2, r)) + if (r->lsa_type == lsa_type + && r->opaque_type == opaque_type) { + found = apiserv; + goto out; + } + } out: - return found; + return found; } -static struct ospf_apiserver * -lookup_apiserver_by_lsa (struct ospf_lsa *lsa) +static struct ospf_apiserver *lookup_apiserver_by_lsa(struct ospf_lsa *lsa) { - struct lsa_header *lsah = lsa->data; - struct ospf_apiserver *found = NULL; - - if (IS_OPAQUE_LSA (lsah->type)) - { - found = lookup_apiserver (lsah->type, - GET_OPAQUE_TYPE (ntohl (lsah->id.s_addr))); - } - return found; + struct lsa_header *lsah = lsa->data; + struct ospf_apiserver *found = NULL; + + if (IS_OPAQUE_LSA(lsah->type)) { + found = lookup_apiserver( + lsah->type, GET_OPAQUE_TYPE(ntohl(lsah->id.s_addr))); + } + return found; } /* ----------------------------------------------------------- * Followings are functions to manage client connections. * ----------------------------------------------------------- */ -static int -ospf_apiserver_new_lsa_hook (struct ospf_lsa *lsa) +static int ospf_apiserver_new_lsa_hook(struct ospf_lsa *lsa) { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("API: Put LSA(%p)[%s] into reserve, total=%ld", (void *)lsa, - dump_lsa_key (lsa), lsa->lsdb->total); - return 0; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("API: Put LSA(%p)[%s] into reserve, total=%ld", + (void *)lsa, dump_lsa_key(lsa), lsa->lsdb->total); + return 0; } -static int -ospf_apiserver_del_lsa_hook (struct ospf_lsa *lsa) +static int ospf_apiserver_del_lsa_hook(struct ospf_lsa *lsa) { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("API: Get LSA(%p)[%s] from reserve, total=%ld", (void *)lsa, - dump_lsa_key (lsa), lsa->lsdb->total); - return 0; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("API: Get LSA(%p)[%s] from reserve, total=%ld", + (void *)lsa, dump_lsa_key(lsa), lsa->lsdb->total); + return 0; } /* Allocate new connection structure. */ -struct ospf_apiserver * -ospf_apiserver_new (int fd_sync, int fd_async) +struct ospf_apiserver *ospf_apiserver_new(int fd_sync, int fd_async) { - struct ospf_apiserver *new = - XMALLOC (MTYPE_OSPF_APISERVER, sizeof (struct ospf_apiserver)); + struct ospf_apiserver *new = + XMALLOC(MTYPE_OSPF_APISERVER, sizeof(struct ospf_apiserver)); - new->filter = - XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER, sizeof (struct lsa_filter_type)); + new->filter = XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER, + sizeof(struct lsa_filter_type)); - new->fd_sync = fd_sync; - new->fd_async = fd_async; + new->fd_sync = fd_sync; + new->fd_async = fd_async; - /* list of registered opaque types that application uses */ - new->opaque_types = list_new (); + /* list of registered opaque types that application uses */ + new->opaque_types = list_new(); - /* Initialize temporary strage for LSA instances to be refreshed. */ - memset (&new->reserve, 0, sizeof (struct ospf_lsdb)); - ospf_lsdb_init (&new->reserve); + /* Initialize temporary strage for LSA instances to be refreshed. */ + memset(&new->reserve, 0, sizeof(struct ospf_lsdb)); + ospf_lsdb_init(&new->reserve); - new->reserve.new_lsa_hook = ospf_apiserver_new_lsa_hook; /* debug */ - new->reserve.del_lsa_hook = ospf_apiserver_del_lsa_hook; /* debug */ + new->reserve.new_lsa_hook = ospf_apiserver_new_lsa_hook; /* debug */ + new->reserve.del_lsa_hook = ospf_apiserver_del_lsa_hook; /* debug */ - new->out_sync_fifo = msg_fifo_new (); - new->out_async_fifo = msg_fifo_new (); - new->t_sync_read = NULL; + new->out_sync_fifo = msg_fifo_new(); + new->out_async_fifo = msg_fifo_new(); + new->t_sync_read = NULL; #ifdef USE_ASYNC_READ - new->t_async_read = NULL; + new->t_async_read = NULL; #endif /* USE_ASYNC_READ */ - new->t_sync_write = NULL; - new->t_async_write = NULL; + new->t_sync_write = NULL; + new->t_async_write = NULL; - new->filter->typemask = 0; /* filter all LSAs */ - new->filter->origin = ANY_ORIGIN; - new->filter->num_areas = 0; + new->filter->typemask = 0; /* filter all LSAs */ + new->filter->origin = ANY_ORIGIN; + new->filter->num_areas = 0; - return new; + return new; } -void -ospf_apiserver_event (enum event event, int fd, - struct ospf_apiserver *apiserv) +void ospf_apiserver_event(enum event event, int fd, + struct ospf_apiserver *apiserv) { - switch (event) - { - case OSPF_APISERVER_ACCEPT: - (void) thread_add_read(master, ospf_apiserver_accept, apiserv, fd, NULL); - break; - case OSPF_APISERVER_SYNC_READ: - apiserv->t_sync_read = NULL; - thread_add_read(master, ospf_apiserver_read, apiserv, fd, - &apiserv->t_sync_read); - break; + switch (event) { + case OSPF_APISERVER_ACCEPT: + (void)thread_add_read(master, ospf_apiserver_accept, apiserv, + fd, NULL); + break; + case OSPF_APISERVER_SYNC_READ: + apiserv->t_sync_read = NULL; + thread_add_read(master, ospf_apiserver_read, apiserv, fd, + &apiserv->t_sync_read); + break; #ifdef USE_ASYNC_READ - case OSPF_APISERVER_ASYNC_READ: - apiserv->t_async_read = NULL; - thread_add_read(master, ospf_apiserver_read, apiserv, fd, - &apiserv->t_async_read); - break; + case OSPF_APISERVER_ASYNC_READ: + apiserv->t_async_read = NULL; + thread_add_read(master, ospf_apiserver_read, apiserv, fd, + &apiserv->t_async_read); + break; #endif /* USE_ASYNC_READ */ - case OSPF_APISERVER_SYNC_WRITE: - thread_add_write(master, ospf_apiserver_sync_write, apiserv, fd, - &apiserv->t_sync_write); - break; - case OSPF_APISERVER_ASYNC_WRITE: - thread_add_write(master, ospf_apiserver_async_write, apiserv, fd, - &apiserv->t_async_write); - break; - } + case OSPF_APISERVER_SYNC_WRITE: + thread_add_write(master, ospf_apiserver_sync_write, apiserv, fd, + &apiserv->t_sync_write); + break; + case OSPF_APISERVER_ASYNC_WRITE: + thread_add_write(master, ospf_apiserver_async_write, apiserv, + fd, &apiserv->t_async_write); + break; + } } /* Free instance. First unregister all opaque types used by - application, flush opaque LSAs injected by application + application, flush opaque LSAs injected by application from network and close connection. */ -void -ospf_apiserver_free (struct ospf_apiserver *apiserv) +void ospf_apiserver_free(struct ospf_apiserver *apiserv) { - struct listnode *node; + struct listnode *node; - /* Cancel read and write threads. */ - if (apiserv->t_sync_read) - { - thread_cancel (apiserv->t_sync_read); - } + /* Cancel read and write threads. */ + if (apiserv->t_sync_read) { + thread_cancel(apiserv->t_sync_read); + } #ifdef USE_ASYNC_READ - if (apiserv->t_async_read) - { - thread_cancel (apiserv->t_async_read); - } + if (apiserv->t_async_read) { + thread_cancel(apiserv->t_async_read); + } #endif /* USE_ASYNC_READ */ - if (apiserv->t_sync_write) - { - thread_cancel (apiserv->t_sync_write); - } - - if (apiserv->t_async_write) - { - thread_cancel (apiserv->t_async_write); - } + if (apiserv->t_sync_write) { + thread_cancel(apiserv->t_sync_write); + } - /* Unregister all opaque types that application registered - and flush opaque LSAs if still in LSDB. */ + if (apiserv->t_async_write) { + thread_cancel(apiserv->t_async_write); + } - while ((node = listhead (apiserv->opaque_types)) != NULL) - { - struct registered_opaque_type *regtype = listgetdata(node); + /* Unregister all opaque types that application registered + and flush opaque LSAs if still in LSDB. */ - ospf_apiserver_unregister_opaque_type (apiserv, regtype->lsa_type, - regtype->opaque_type); + while ((node = listhead(apiserv->opaque_types)) != NULL) { + struct registered_opaque_type *regtype = listgetdata(node); - } + ospf_apiserver_unregister_opaque_type( + apiserv, regtype->lsa_type, regtype->opaque_type); + } - /* Close connections to OSPFd. */ - if (apiserv->fd_sync > 0) - { - close (apiserv->fd_sync); - } + /* Close connections to OSPFd. */ + if (apiserv->fd_sync > 0) { + close(apiserv->fd_sync); + } - if (apiserv->fd_async > 0) - { - close (apiserv->fd_async); - } + if (apiserv->fd_async > 0) { + close(apiserv->fd_async); + } - /* Free fifos */ - msg_fifo_free (apiserv->out_sync_fifo); - msg_fifo_free (apiserv->out_async_fifo); + /* Free fifos */ + msg_fifo_free(apiserv->out_sync_fifo); + msg_fifo_free(apiserv->out_async_fifo); - /* Clear temporary strage for LSA instances to be refreshed. */ - ospf_lsdb_delete_all (&apiserv->reserve); - ospf_lsdb_cleanup (&apiserv->reserve); + /* Clear temporary strage for LSA instances to be refreshed. */ + ospf_lsdb_delete_all(&apiserv->reserve); + ospf_lsdb_cleanup(&apiserv->reserve); - /* Remove from the list of active clients. */ - listnode_delete (apiserver_list, apiserv); + /* Remove from the list of active clients. */ + listnode_delete(apiserver_list, apiserv); - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("API: Delete apiserv(%p), total#(%d)", - (void *)apiserv, apiserver_list->count); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("API: Delete apiserv(%p), total#(%d)", + (void *)apiserv, apiserver_list->count); - /* And free instance. */ - XFREE (MTYPE_OSPF_APISERVER, apiserv); + /* And free instance. */ + XFREE(MTYPE_OSPF_APISERVER, apiserv); } -int -ospf_apiserver_read (struct thread *thread) +int ospf_apiserver_read(struct thread *thread) { - struct ospf_apiserver *apiserv; - struct msg *msg; - int fd; - int rc = -1; - enum event event; - - apiserv = THREAD_ARG (thread); - fd = THREAD_FD (thread); - - if (fd == apiserv->fd_sync) - { - event = OSPF_APISERVER_SYNC_READ; - apiserv->t_sync_read = NULL; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("API: ospf_apiserver_read: Peer: %s/%u", - inet_ntoa (apiserv->peer_sync.sin_addr), - ntohs (apiserv->peer_sync.sin_port)); - } + struct ospf_apiserver *apiserv; + struct msg *msg; + int fd; + int rc = -1; + enum event event; + + apiserv = THREAD_ARG(thread); + fd = THREAD_FD(thread); + + if (fd == apiserv->fd_sync) { + event = OSPF_APISERVER_SYNC_READ; + apiserv->t_sync_read = NULL; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("API: ospf_apiserver_read: Peer: %s/%u", + inet_ntoa(apiserv->peer_sync.sin_addr), + ntohs(apiserv->peer_sync.sin_port)); + } #ifdef USE_ASYNC_READ - else if (fd == apiserv->fd_async) - { - event = OSPF_APISERVER_ASYNC_READ; - apiserv->t_async_read = NULL; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("API: ospf_apiserver_read: Peer: %s/%u", - inet_ntoa (apiserv->peer_async.sin_addr), - ntohs (apiserv->peer_async.sin_port)); - } + else if (fd == apiserv->fd_async) { + event = OSPF_APISERVER_ASYNC_READ; + apiserv->t_async_read = NULL; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("API: ospf_apiserver_read: Peer: %s/%u", + inet_ntoa(apiserv->peer_async.sin_addr), + ntohs(apiserv->peer_async.sin_port)); + } #endif /* USE_ASYNC_READ */ - else - { - zlog_warn ("ospf_apiserver_read: Unknown fd(%d)", fd); - ospf_apiserver_free (apiserv); - goto out; - } + else { + zlog_warn("ospf_apiserver_read: Unknown fd(%d)", fd); + ospf_apiserver_free(apiserv); + goto out; + } - /* Read message from fd. */ - msg = msg_read (fd); - if (msg == NULL) - { - zlog_warn - ("ospf_apiserver_read: read failed on fd=%d, closing connection", fd); + /* Read message from fd. */ + msg = msg_read(fd); + if (msg == NULL) { + zlog_warn( + "ospf_apiserver_read: read failed on fd=%d, closing connection", + fd); - /* Perform cleanup. */ - ospf_apiserver_free (apiserv); - goto out; - } + /* Perform cleanup. */ + ospf_apiserver_free(apiserv); + goto out; + } - if (IS_DEBUG_OSPF_EVENT) - msg_print (msg); + if (IS_DEBUG_OSPF_EVENT) + msg_print(msg); - /* Dispatch to corresponding message handler. */ - rc = ospf_apiserver_handle_msg (apiserv, msg); + /* Dispatch to corresponding message handler. */ + rc = ospf_apiserver_handle_msg(apiserv, msg); - /* Prepare for next message, add read thread. */ - ospf_apiserver_event (event, fd, apiserv); + /* Prepare for next message, add read thread. */ + ospf_apiserver_event(event, fd, apiserv); - msg_free (msg); + msg_free(msg); out: - return rc; + return rc; } -int -ospf_apiserver_sync_write (struct thread *thread) +int ospf_apiserver_sync_write(struct thread *thread) { - struct ospf_apiserver *apiserv; - struct msg *msg; - int fd; - int rc = -1; - - apiserv = THREAD_ARG (thread); - assert (apiserv); - fd = THREAD_FD (thread); - - apiserv->t_sync_write = NULL; - - /* Sanity check */ - if (fd != apiserv->fd_sync) - { - zlog_warn ("ospf_apiserver_sync_write: Unknown fd=%d", fd); - goto out; - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("API: ospf_apiserver_sync_write: Peer: %s/%u", - inet_ntoa (apiserv->peer_sync.sin_addr), - ntohs (apiserv->peer_sync.sin_port)); - - /* Check whether there is really a message in the fifo. */ - msg = msg_fifo_pop (apiserv->out_sync_fifo); - if (!msg) - { - zlog_warn ("API: ospf_apiserver_sync_write: No message in Sync-FIFO?"); - return 0; - } - - if (IS_DEBUG_OSPF_EVENT) - msg_print (msg); - - rc = msg_write (fd, msg); - - /* Once a message is dequeued, it should be freed anyway. */ - msg_free (msg); - - if (rc < 0) - { - zlog_warn - ("ospf_apiserver_sync_write: write failed on fd=%d", fd); - goto out; - } - - - /* If more messages are in sync message fifo, schedule write thread. */ - if (msg_fifo_head (apiserv->out_sync_fifo)) - { - ospf_apiserver_event (OSPF_APISERVER_SYNC_WRITE, apiserv->fd_sync, - apiserv); - } - - out: - - if (rc < 0) - { - /* Perform cleanup and disconnect with peer */ - ospf_apiserver_free (apiserv); - } - - return rc; + struct ospf_apiserver *apiserv; + struct msg *msg; + int fd; + int rc = -1; + + apiserv = THREAD_ARG(thread); + assert(apiserv); + fd = THREAD_FD(thread); + + apiserv->t_sync_write = NULL; + + /* Sanity check */ + if (fd != apiserv->fd_sync) { + zlog_warn("ospf_apiserver_sync_write: Unknown fd=%d", fd); + goto out; + } + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("API: ospf_apiserver_sync_write: Peer: %s/%u", + inet_ntoa(apiserv->peer_sync.sin_addr), + ntohs(apiserv->peer_sync.sin_port)); + + /* Check whether there is really a message in the fifo. */ + msg = msg_fifo_pop(apiserv->out_sync_fifo); + if (!msg) { + zlog_warn( + "API: ospf_apiserver_sync_write: No message in Sync-FIFO?"); + return 0; + } + + if (IS_DEBUG_OSPF_EVENT) + msg_print(msg); + + rc = msg_write(fd, msg); + + /* Once a message is dequeued, it should be freed anyway. */ + msg_free(msg); + + if (rc < 0) { + zlog_warn("ospf_apiserver_sync_write: write failed on fd=%d", + fd); + goto out; + } + + + /* If more messages are in sync message fifo, schedule write thread. */ + if (msg_fifo_head(apiserv->out_sync_fifo)) { + ospf_apiserver_event(OSPF_APISERVER_SYNC_WRITE, + apiserv->fd_sync, apiserv); + } + +out: + + if (rc < 0) { + /* Perform cleanup and disconnect with peer */ + ospf_apiserver_free(apiserv); + } + + return rc; } -int -ospf_apiserver_async_write (struct thread *thread) +int ospf_apiserver_async_write(struct thread *thread) { - struct ospf_apiserver *apiserv; - struct msg *msg; - int fd; - int rc = -1; - - apiserv = THREAD_ARG (thread); - assert (apiserv); - fd = THREAD_FD (thread); - - apiserv->t_async_write = NULL; - - /* Sanity check */ - if (fd != apiserv->fd_async) - { - zlog_warn ("ospf_apiserver_async_write: Unknown fd=%d", fd); - goto out; - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("API: ospf_apiserver_async_write: Peer: %s/%u", - inet_ntoa (apiserv->peer_async.sin_addr), - ntohs (apiserv->peer_async.sin_port)); - - /* Check whether there is really a message in the fifo. */ - msg = msg_fifo_pop (apiserv->out_async_fifo); - if (!msg) - { - zlog_warn ("API: ospf_apiserver_async_write: No message in Async-FIFO?"); - return 0; - } - - if (IS_DEBUG_OSPF_EVENT) - msg_print (msg); - - rc = msg_write (fd, msg); - - /* Once a message is dequeued, it should be freed anyway. */ - msg_free (msg); - - if (rc < 0) - { - zlog_warn - ("ospf_apiserver_async_write: write failed on fd=%d", fd); - goto out; - } - - - /* If more messages are in async message fifo, schedule write thread. */ - if (msg_fifo_head (apiserv->out_async_fifo)) - { - ospf_apiserver_event (OSPF_APISERVER_ASYNC_WRITE, apiserv->fd_async, - apiserv); - } - - out: - - if (rc < 0) - { - /* Perform cleanup and disconnect with peer */ - ospf_apiserver_free (apiserv); - } - - return rc; + struct ospf_apiserver *apiserv; + struct msg *msg; + int fd; + int rc = -1; + + apiserv = THREAD_ARG(thread); + assert(apiserv); + fd = THREAD_FD(thread); + + apiserv->t_async_write = NULL; + + /* Sanity check */ + if (fd != apiserv->fd_async) { + zlog_warn("ospf_apiserver_async_write: Unknown fd=%d", fd); + goto out; + } + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("API: ospf_apiserver_async_write: Peer: %s/%u", + inet_ntoa(apiserv->peer_async.sin_addr), + ntohs(apiserv->peer_async.sin_port)); + + /* Check whether there is really a message in the fifo. */ + msg = msg_fifo_pop(apiserv->out_async_fifo); + if (!msg) { + zlog_warn( + "API: ospf_apiserver_async_write: No message in Async-FIFO?"); + return 0; + } + + if (IS_DEBUG_OSPF_EVENT) + msg_print(msg); + + rc = msg_write(fd, msg); + + /* Once a message is dequeued, it should be freed anyway. */ + msg_free(msg); + + if (rc < 0) { + zlog_warn("ospf_apiserver_async_write: write failed on fd=%d", + fd); + goto out; + } + + + /* If more messages are in async message fifo, schedule write thread. */ + if (msg_fifo_head(apiserv->out_async_fifo)) { + ospf_apiserver_event(OSPF_APISERVER_ASYNC_WRITE, + apiserv->fd_async, apiserv); + } + +out: + + if (rc < 0) { + /* Perform cleanup and disconnect with peer */ + ospf_apiserver_free(apiserv); + } + + return rc; } -int -ospf_apiserver_serv_sock_family (unsigned short port, int family) +int ospf_apiserver_serv_sock_family(unsigned short port, int family) { - union sockunion su; - int accept_sock; - int rc; - - memset (&su, 0, sizeof (union sockunion)); - su.sa.sa_family = family; - - /* Make new socket */ - accept_sock = sockunion_stream_socket (&su); - if (accept_sock < 0) - return accept_sock; - - /* This is a server, so reuse address and port */ - sockopt_reuseaddr (accept_sock); - sockopt_reuseport (accept_sock); - - /* Bind socket to address and given port. */ - rc = sockunion_bind (accept_sock, &su, port, NULL); - if (rc < 0) - { - close (accept_sock); /* Close socket */ - return rc; - } - - /* Listen socket under queue length 3. */ - rc = listen (accept_sock, 3); - if (rc < 0) - { - zlog_warn ("ospf_apiserver_serv_sock_family: listen: %s", - safe_strerror (errno)); - close (accept_sock); /* Close socket */ - return rc; - } - return accept_sock; + union sockunion su; + int accept_sock; + int rc; + + memset(&su, 0, sizeof(union sockunion)); + su.sa.sa_family = family; + + /* Make new socket */ + accept_sock = sockunion_stream_socket(&su); + if (accept_sock < 0) + return accept_sock; + + /* This is a server, so reuse address and port */ + sockopt_reuseaddr(accept_sock); + sockopt_reuseport(accept_sock); + + /* Bind socket to address and given port. */ + rc = sockunion_bind(accept_sock, &su, port, NULL); + if (rc < 0) { + close(accept_sock); /* Close socket */ + return rc; + } + + /* Listen socket under queue length 3. */ + rc = listen(accept_sock, 3); + if (rc < 0) { + zlog_warn("ospf_apiserver_serv_sock_family: listen: %s", + safe_strerror(errno)); + close(accept_sock); /* Close socket */ + return rc; + } + return accept_sock; } /* Accept connection request from external applications. For each accepted connection allocate own connection instance. */ -int -ospf_apiserver_accept (struct thread *thread) +int ospf_apiserver_accept(struct thread *thread) { - int accept_sock; - int new_sync_sock; - int new_async_sock; - union sockunion su; - struct ospf_apiserver *apiserv; - struct sockaddr_in peer_async; - struct sockaddr_in peer_sync; - unsigned int peerlen; - int ret; - - /* THREAD_ARG (thread) is NULL */ - accept_sock = THREAD_FD (thread); - - /* Keep hearing on socket for further connections. */ - ospf_apiserver_event (OSPF_APISERVER_ACCEPT, accept_sock, NULL); - - memset (&su, 0, sizeof (union sockunion)); - /* Accept connection for synchronous messages */ - new_sync_sock = sockunion_accept (accept_sock, &su); - if (new_sync_sock < 0) - { - zlog_warn ("ospf_apiserver_accept: accept: %s", safe_strerror (errno)); - return -1; - } - - /* Get port address and port number of peer to make reverse connection. - The reverse channel uses the port number of the peer port+1. */ - - memset(&peer_sync, 0, sizeof(struct sockaddr_in)); - peerlen = sizeof (struct sockaddr_in); - - ret = getpeername (new_sync_sock, (struct sockaddr *)&peer_sync, &peerlen); - if (ret < 0) - { - zlog_warn ("ospf_apiserver_accept: getpeername: %s", safe_strerror (errno)); - close (new_sync_sock); - return -1; - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("API: ospf_apiserver_accept: New peer: %s/%u", - inet_ntoa (peer_sync.sin_addr), ntohs (peer_sync.sin_port)); - - /* Create new socket for asynchronous messages. */ - peer_async = peer_sync; - peer_async.sin_port = htons(ntohs(peer_sync.sin_port) + 1); - - /* Check if remote port number to make reverse connection is valid one. */ - if (ntohs (peer_async.sin_port) == ospf_apiserver_getport ()) - { - zlog_warn ("API: ospf_apiserver_accept: Peer(%s/%u): Invalid async port number?", - inet_ntoa (peer_async.sin_addr), ntohs (peer_async.sin_port)); - close (new_sync_sock); - return -1; - } - - new_async_sock = socket (AF_INET, SOCK_STREAM, 0); - if (new_async_sock < 0) - { - zlog_warn ("ospf_apiserver_accept: socket: %s", safe_strerror (errno)); - close (new_sync_sock); - return -1; - } - - ret = connect (new_async_sock, (struct sockaddr *) &peer_async, - sizeof (struct sockaddr_in)); - - if (ret < 0) - { - zlog_warn ("ospf_apiserver_accept: connect: %s", safe_strerror (errno)); - close (new_sync_sock); - close (new_async_sock); - return -1; - } + int accept_sock; + int new_sync_sock; + int new_async_sock; + union sockunion su; + struct ospf_apiserver *apiserv; + struct sockaddr_in peer_async; + struct sockaddr_in peer_sync; + unsigned int peerlen; + int ret; + + /* THREAD_ARG (thread) is NULL */ + accept_sock = THREAD_FD(thread); + + /* Keep hearing on socket for further connections. */ + ospf_apiserver_event(OSPF_APISERVER_ACCEPT, accept_sock, NULL); + + memset(&su, 0, sizeof(union sockunion)); + /* Accept connection for synchronous messages */ + new_sync_sock = sockunion_accept(accept_sock, &su); + if (new_sync_sock < 0) { + zlog_warn("ospf_apiserver_accept: accept: %s", + safe_strerror(errno)); + return -1; + } + + /* Get port address and port number of peer to make reverse connection. + The reverse channel uses the port number of the peer port+1. */ + + memset(&peer_sync, 0, sizeof(struct sockaddr_in)); + peerlen = sizeof(struct sockaddr_in); + + ret = getpeername(new_sync_sock, (struct sockaddr *)&peer_sync, + &peerlen); + if (ret < 0) { + zlog_warn("ospf_apiserver_accept: getpeername: %s", + safe_strerror(errno)); + close(new_sync_sock); + return -1; + } + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("API: ospf_apiserver_accept: New peer: %s/%u", + inet_ntoa(peer_sync.sin_addr), + ntohs(peer_sync.sin_port)); + + /* Create new socket for asynchronous messages. */ + peer_async = peer_sync; + peer_async.sin_port = htons(ntohs(peer_sync.sin_port) + 1); + + /* Check if remote port number to make reverse connection is valid one. + */ + if (ntohs(peer_async.sin_port) == ospf_apiserver_getport()) { + zlog_warn( + "API: ospf_apiserver_accept: Peer(%s/%u): Invalid async port number?", + inet_ntoa(peer_async.sin_addr), + ntohs(peer_async.sin_port)); + close(new_sync_sock); + return -1; + } + + new_async_sock = socket(AF_INET, SOCK_STREAM, 0); + if (new_async_sock < 0) { + zlog_warn("ospf_apiserver_accept: socket: %s", + safe_strerror(errno)); + close(new_sync_sock); + return -1; + } + + ret = connect(new_async_sock, (struct sockaddr *)&peer_async, + sizeof(struct sockaddr_in)); + + if (ret < 0) { + zlog_warn("ospf_apiserver_accept: connect: %s", + safe_strerror(errno)); + close(new_sync_sock); + close(new_async_sock); + return -1; + } #ifdef USE_ASYNC_READ -#else /* USE_ASYNC_READ */ - /* Make the asynchronous channel write-only. */ - ret = shutdown (new_async_sock, SHUT_RD); - if (ret < 0) - { - zlog_warn ("ospf_apiserver_accept: shutdown: %s", safe_strerror (errno)); - close (new_sync_sock); - close (new_async_sock); - return -1; - } +#else /* USE_ASYNC_READ */ + /* Make the asynchronous channel write-only. */ + ret = shutdown(new_async_sock, SHUT_RD); + if (ret < 0) { + zlog_warn("ospf_apiserver_accept: shutdown: %s", + safe_strerror(errno)); + close(new_sync_sock); + close(new_async_sock); + return -1; + } #endif /* USE_ASYNC_READ */ - /* Allocate new server-side connection structure */ - apiserv = ospf_apiserver_new (new_sync_sock, new_async_sock); + /* Allocate new server-side connection structure */ + apiserv = ospf_apiserver_new(new_sync_sock, new_async_sock); - /* Add to active connection list */ - listnode_add (apiserver_list, apiserv); - apiserv->peer_sync = peer_sync; - apiserv->peer_async = peer_async; + /* Add to active connection list */ + listnode_add(apiserver_list, apiserv); + apiserv->peer_sync = peer_sync; + apiserv->peer_async = peer_async; - /* And add read threads for new connection */ - ospf_apiserver_event (OSPF_APISERVER_SYNC_READ, new_sync_sock, apiserv); + /* And add read threads for new connection */ + ospf_apiserver_event(OSPF_APISERVER_SYNC_READ, new_sync_sock, apiserv); #ifdef USE_ASYNC_READ - ospf_apiserver_event (OSPF_APISERVER_ASYNC_READ, new_async_sock, apiserv); + ospf_apiserver_event(OSPF_APISERVER_ASYNC_READ, new_async_sock, + apiserv); #endif /* USE_ASYNC_READ */ - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("API: New apiserv(%p), total#(%d)", - (void *)apiserv, apiserver_list->count); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("API: New apiserv(%p), total#(%d)", (void *)apiserv, + apiserver_list->count); - return 0; + return 0; } @@ -762,71 +720,68 @@ ospf_apiserver_accept (struct thread *thread) * ----------------------------------------------------------- */ -static int -ospf_apiserver_send_msg (struct ospf_apiserver *apiserv, struct msg *msg) +static int ospf_apiserver_send_msg(struct ospf_apiserver *apiserv, + struct msg *msg) { - struct msg_fifo *fifo; - struct msg *msg2; - enum event event; - int fd; - - switch (msg->hdr.msgtype) - { - case MSG_REPLY: - fifo = apiserv->out_sync_fifo; - fd = apiserv->fd_sync; - event = OSPF_APISERVER_SYNC_WRITE; - break; - case MSG_READY_NOTIFY: - case MSG_LSA_UPDATE_NOTIFY: - case MSG_LSA_DELETE_NOTIFY: - case MSG_NEW_IF: - case MSG_DEL_IF: - case MSG_ISM_CHANGE: - case MSG_NSM_CHANGE: - fifo = apiserv->out_async_fifo; - fd = apiserv->fd_async; - event = OSPF_APISERVER_ASYNC_WRITE; - break; - default: - zlog_warn ("ospf_apiserver_send_msg: Unknown message type %d", - msg->hdr.msgtype); - return -1; - } - - /* Make a copy of the message and put in the fifo. Once the fifo - gets drained by the write thread, the message will be freed. */ - /* NB: Given "msg" is untouched in this function. */ - msg2 = msg_dup (msg); - - /* Enqueue message into corresponding fifo queue */ - msg_fifo_push (fifo, msg2); - - /* Schedule write thread */ - ospf_apiserver_event (event, fd, apiserv); - return 0; + struct msg_fifo *fifo; + struct msg *msg2; + enum event event; + int fd; + + switch (msg->hdr.msgtype) { + case MSG_REPLY: + fifo = apiserv->out_sync_fifo; + fd = apiserv->fd_sync; + event = OSPF_APISERVER_SYNC_WRITE; + break; + case MSG_READY_NOTIFY: + case MSG_LSA_UPDATE_NOTIFY: + case MSG_LSA_DELETE_NOTIFY: + case MSG_NEW_IF: + case MSG_DEL_IF: + case MSG_ISM_CHANGE: + case MSG_NSM_CHANGE: + fifo = apiserv->out_async_fifo; + fd = apiserv->fd_async; + event = OSPF_APISERVER_ASYNC_WRITE; + break; + default: + zlog_warn("ospf_apiserver_send_msg: Unknown message type %d", + msg->hdr.msgtype); + return -1; + } + + /* Make a copy of the message and put in the fifo. Once the fifo + gets drained by the write thread, the message will be freed. */ + /* NB: Given "msg" is untouched in this function. */ + msg2 = msg_dup(msg); + + /* Enqueue message into corresponding fifo queue */ + msg_fifo_push(fifo, msg2); + + /* Schedule write thread */ + ospf_apiserver_event(event, fd, apiserv); + return 0; } -int -ospf_apiserver_send_reply (struct ospf_apiserver *apiserv, u_int32_t seqnr, - u_char rc) +int ospf_apiserver_send_reply(struct ospf_apiserver *apiserv, u_int32_t seqnr, + u_char rc) { - struct msg *msg = new_msg_reply (seqnr, rc); - int ret; + struct msg *msg = new_msg_reply(seqnr, rc); + int ret; - if (!msg) - { - zlog_warn ("ospf_apiserver_send_reply: msg_new failed"); + if (!msg) { + zlog_warn("ospf_apiserver_send_reply: msg_new failed"); #ifdef NOTYET - /* Cannot allocate new message. What should we do? */ - ospf_apiserver_free (apiserv); + /* Cannot allocate new message. What should we do? */ + ospf_apiserver_free(apiserv); #endif - return -1; - } + return -1; + } - ret = ospf_apiserver_send_msg (apiserv, msg); - msg_free (msg); - return ret; + ret = ospf_apiserver_send_msg(apiserv, msg); + msg_free(msg); + return ret; } @@ -835,38 +790,36 @@ ospf_apiserver_send_reply (struct ospf_apiserver *apiserv, u_int32_t seqnr, * ----------------------------------------------------------- */ -int -ospf_apiserver_handle_msg (struct ospf_apiserver *apiserv, struct msg *msg) +int ospf_apiserver_handle_msg(struct ospf_apiserver *apiserv, struct msg *msg) { - int rc; - - /* Call corresponding message handler function. */ - switch (msg->hdr.msgtype) - { - case MSG_REGISTER_OPAQUETYPE: - rc = ospf_apiserver_handle_register_opaque_type (apiserv, msg); - break; - case MSG_UNREGISTER_OPAQUETYPE: - rc = ospf_apiserver_handle_unregister_opaque_type (apiserv, msg); - break; - case MSG_REGISTER_EVENT: - rc = ospf_apiserver_handle_register_event (apiserv, msg); - break; - case MSG_SYNC_LSDB: - rc = ospf_apiserver_handle_sync_lsdb (apiserv, msg); - break; - case MSG_ORIGINATE_REQUEST: - rc = ospf_apiserver_handle_originate_request (apiserv, msg); - break; - case MSG_DELETE_REQUEST: - rc = ospf_apiserver_handle_delete_request (apiserv, msg); - break; - default: - zlog_warn ("ospf_apiserver_handle_msg: Unknown message type: %d", - msg->hdr.msgtype); - rc = -1; - } - return rc; + int rc; + + /* Call corresponding message handler function. */ + switch (msg->hdr.msgtype) { + case MSG_REGISTER_OPAQUETYPE: + rc = ospf_apiserver_handle_register_opaque_type(apiserv, msg); + break; + case MSG_UNREGISTER_OPAQUETYPE: + rc = ospf_apiserver_handle_unregister_opaque_type(apiserv, msg); + break; + case MSG_REGISTER_EVENT: + rc = ospf_apiserver_handle_register_event(apiserv, msg); + break; + case MSG_SYNC_LSDB: + rc = ospf_apiserver_handle_sync_lsdb(apiserv, msg); + break; + case MSG_ORIGINATE_REQUEST: + rc = ospf_apiserver_handle_originate_request(apiserv, msg); + break; + case MSG_DELETE_REQUEST: + rc = ospf_apiserver_handle_delete_request(apiserv, msg); + break; + default: + zlog_warn("ospf_apiserver_handle_msg: Unknown message type: %d", + msg->hdr.msgtype); + rc = -1; + } + return rc; } @@ -875,346 +828,327 @@ ospf_apiserver_handle_msg (struct ospf_apiserver *apiserv, struct msg *msg) * ----------------------------------------------------------- */ -int -ospf_apiserver_register_opaque_type (struct ospf_apiserver *apiserv, - u_char lsa_type, u_char opaque_type) +int ospf_apiserver_register_opaque_type(struct ospf_apiserver *apiserv, + u_char lsa_type, u_char opaque_type) { - struct registered_opaque_type *regtype; - int (*originator_func) (void *arg); - int rc; - - switch (lsa_type) - { - case OSPF_OPAQUE_LINK_LSA: - originator_func = ospf_apiserver_lsa9_originator; - break; - case OSPF_OPAQUE_AREA_LSA: - originator_func = ospf_apiserver_lsa10_originator; - break; - case OSPF_OPAQUE_AS_LSA: - originator_func = ospf_apiserver_lsa11_originator; - break; - default: - zlog_warn ("ospf_apiserver_register_opaque_type: lsa_type(%d)", - lsa_type); - return OSPF_API_ILLEGALLSATYPE; - } - - - /* Register opaque function table */ - /* NB: Duplicated registration will be detected inside the function. */ - rc = - ospf_register_opaque_functab (lsa_type, opaque_type, - NULL, /* ospf_apiserver_new_if */ - NULL, /* ospf_apiserver_del_if */ - NULL, /* ospf_apiserver_ism_change */ - NULL, /* ospf_apiserver_nsm_change */ - NULL, - NULL, - NULL, - ospf_apiserver_show_info, - originator_func, - ospf_apiserver_lsa_refresher, - NULL, /* ospf_apiserver_lsa_update */ - NULL /* ospf_apiserver_lsa_delete */); - - if (rc != 0) - { - zlog_warn ("Failed to register opaque type [%d/%d]", - lsa_type, opaque_type); - return OSPF_API_OPAQUETYPEINUSE; - } - - /* Remember the opaque type that application registers so when - connection shuts down, we can flush all LSAs of this opaque - type. */ - - regtype = - XCALLOC (MTYPE_OSPF_APISERVER, sizeof (struct registered_opaque_type)); - regtype->lsa_type = lsa_type; - regtype->opaque_type = opaque_type; - - /* Add to list of registered opaque types */ - listnode_add (apiserv->opaque_types, regtype); - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("API: Add LSA-type(%d)/Opaque-type(%d) into" - " apiserv(%p), total#(%d)", - lsa_type, opaque_type, (void *)apiserv, - listcount (apiserv->opaque_types)); - - return 0; + struct registered_opaque_type *regtype; + int (*originator_func)(void *arg); + int rc; + + switch (lsa_type) { + case OSPF_OPAQUE_LINK_LSA: + originator_func = ospf_apiserver_lsa9_originator; + break; + case OSPF_OPAQUE_AREA_LSA: + originator_func = ospf_apiserver_lsa10_originator; + break; + case OSPF_OPAQUE_AS_LSA: + originator_func = ospf_apiserver_lsa11_originator; + break; + default: + zlog_warn("ospf_apiserver_register_opaque_type: lsa_type(%d)", + lsa_type); + return OSPF_API_ILLEGALLSATYPE; + } + + + /* Register opaque function table */ + /* NB: Duplicated registration will be detected inside the function. */ + rc = ospf_register_opaque_functab( + lsa_type, opaque_type, NULL, /* ospf_apiserver_new_if */ + NULL, /* ospf_apiserver_del_if */ + NULL, /* ospf_apiserver_ism_change */ + NULL, /* ospf_apiserver_nsm_change */ + NULL, NULL, NULL, ospf_apiserver_show_info, originator_func, + ospf_apiserver_lsa_refresher, + NULL, /* ospf_apiserver_lsa_update */ + NULL /* ospf_apiserver_lsa_delete */); + + if (rc != 0) { + zlog_warn("Failed to register opaque type [%d/%d]", lsa_type, + opaque_type); + return OSPF_API_OPAQUETYPEINUSE; + } + + /* Remember the opaque type that application registers so when + connection shuts down, we can flush all LSAs of this opaque + type. */ + + regtype = XCALLOC(MTYPE_OSPF_APISERVER, + sizeof(struct registered_opaque_type)); + regtype->lsa_type = lsa_type; + regtype->opaque_type = opaque_type; + + /* Add to list of registered opaque types */ + listnode_add(apiserv->opaque_types, regtype); + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "API: Add LSA-type(%d)/Opaque-type(%d) into" + " apiserv(%p), total#(%d)", + lsa_type, opaque_type, (void *)apiserv, + listcount(apiserv->opaque_types)); + + return 0; } -int -ospf_apiserver_unregister_opaque_type (struct ospf_apiserver *apiserv, - u_char lsa_type, u_char opaque_type) +int ospf_apiserver_unregister_opaque_type(struct ospf_apiserver *apiserv, + u_char lsa_type, u_char opaque_type) { - struct listnode *node, *nnode; - struct registered_opaque_type *regtype; + struct listnode *node, *nnode; + struct registered_opaque_type *regtype; - for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, regtype)) - { - /* Check if we really registered this opaque type */ - if (regtype->lsa_type == lsa_type && - regtype->opaque_type == opaque_type) - { + for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node, nnode, regtype)) { + /* Check if we really registered this opaque type */ + if (regtype->lsa_type == lsa_type + && regtype->opaque_type == opaque_type) { - /* Yes, we registered this opaque type. Flush - all existing opaque LSAs of this type */ + /* Yes, we registered this opaque type. Flush + all existing opaque LSAs of this type */ - ospf_apiserver_flush_opaque_lsa (apiserv, lsa_type, opaque_type); - ospf_delete_opaque_functab (lsa_type, opaque_type); + ospf_apiserver_flush_opaque_lsa(apiserv, lsa_type, + opaque_type); + ospf_delete_opaque_functab(lsa_type, opaque_type); - /* Remove from list of registered opaque types */ - listnode_delete (apiserv->opaque_types, regtype); + /* Remove from list of registered opaque types */ + listnode_delete(apiserv->opaque_types, regtype); - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("API: Del LSA-type(%d)/Opaque-type(%d)" - " from apiserv(%p), total#(%d)", - lsa_type, opaque_type, (void *)apiserv, - listcount (apiserv->opaque_types)); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "API: Del LSA-type(%d)/Opaque-type(%d)" + " from apiserv(%p), total#(%d)", + lsa_type, opaque_type, (void *)apiserv, + listcount(apiserv->opaque_types)); - return 0; + return 0; + } } - } - /* Opaque type is not registered */ - zlog_warn ("Failed to unregister opaque type [%d/%d]", - lsa_type, opaque_type); - return OSPF_API_OPAQUETYPENOTREGISTERED; + /* Opaque type is not registered */ + zlog_warn("Failed to unregister opaque type [%d/%d]", lsa_type, + opaque_type); + return OSPF_API_OPAQUETYPENOTREGISTERED; } -static int -apiserver_is_opaque_type_registered (struct ospf_apiserver *apiserv, - u_char lsa_type, u_char opaque_type) +static int apiserver_is_opaque_type_registered(struct ospf_apiserver *apiserv, + u_char lsa_type, + u_char opaque_type) { - struct listnode *node, *nnode; - struct registered_opaque_type *regtype; - - /* XXX: how many types are there? if few, why not just a bitmap? */ - for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, regtype)) - { - /* Check if we really registered this opaque type */ - if (regtype->lsa_type == lsa_type && - regtype->opaque_type == opaque_type) - { - /* Yes registered */ - return 1; - } - } - /* Not registered */ - return 0; + struct listnode *node, *nnode; + struct registered_opaque_type *regtype; + + /* XXX: how many types are there? if few, why not just a bitmap? */ + for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node, nnode, regtype)) { + /* Check if we really registered this opaque type */ + if (regtype->lsa_type == lsa_type + && regtype->opaque_type == opaque_type) { + /* Yes registered */ + return 1; + } + } + /* Not registered */ + return 0; } -int -ospf_apiserver_handle_register_opaque_type (struct ospf_apiserver *apiserv, - struct msg *msg) +int ospf_apiserver_handle_register_opaque_type(struct ospf_apiserver *apiserv, + struct msg *msg) { - struct msg_register_opaque_type *rmsg; - u_char lsa_type; - u_char opaque_type; - int rc = 0; - - /* Extract parameters from register opaque type message */ - rmsg = (struct msg_register_opaque_type *) STREAM_DATA (msg->s); - - lsa_type = rmsg->lsatype; - opaque_type = rmsg->opaquetype; - - rc = ospf_apiserver_register_opaque_type (apiserv, lsa_type, opaque_type); - - /* Send a reply back to client including return code */ - rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc); - if (rc < 0) - goto out; - - /* Now inform application about opaque types that are ready */ - switch (lsa_type) - { - case OSPF_OPAQUE_LINK_LSA: - ospf_apiserver_notify_ready_type9 (apiserv); - break; - case OSPF_OPAQUE_AREA_LSA: - ospf_apiserver_notify_ready_type10 (apiserv); - break; - case OSPF_OPAQUE_AS_LSA: - ospf_apiserver_notify_ready_type11 (apiserv); - break; - } + struct msg_register_opaque_type *rmsg; + u_char lsa_type; + u_char opaque_type; + int rc = 0; + + /* Extract parameters from register opaque type message */ + rmsg = (struct msg_register_opaque_type *)STREAM_DATA(msg->s); + + lsa_type = rmsg->lsatype; + opaque_type = rmsg->opaquetype; + + rc = ospf_apiserver_register_opaque_type(apiserv, lsa_type, + opaque_type); + + /* Send a reply back to client including return code */ + rc = ospf_apiserver_send_reply(apiserv, ntohl(msg->hdr.msgseq), rc); + if (rc < 0) + goto out; + + /* Now inform application about opaque types that are ready */ + switch (lsa_type) { + case OSPF_OPAQUE_LINK_LSA: + ospf_apiserver_notify_ready_type9(apiserv); + break; + case OSPF_OPAQUE_AREA_LSA: + ospf_apiserver_notify_ready_type10(apiserv); + break; + case OSPF_OPAQUE_AS_LSA: + ospf_apiserver_notify_ready_type11(apiserv); + break; + } out: - return rc; + return rc; } /* Notify specific client about all opaque types 9 that are ready. */ -void -ospf_apiserver_notify_ready_type9 (struct ospf_apiserver *apiserv) +void ospf_apiserver_notify_ready_type9(struct ospf_apiserver *apiserv) { - struct listnode *node, *nnode; - struct listnode *node2, *nnode2; - struct ospf *ospf; - struct ospf_interface *oi; - struct registered_opaque_type *r; - - ospf = ospf_lookup (); - - for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) - { - /* Check if this interface is indeed ready for type 9 */ - if (!ospf_apiserver_is_ready_type9 (oi)) - continue; - - /* Check for registered opaque type 9 types */ - /* XXX: loop-de-loop - optimise me */ - for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r)) - { - struct msg *msg; - - if (r->lsa_type == OSPF_OPAQUE_LINK_LSA) - { - - /* Yes, this opaque type is ready */ - msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA, - r->opaque_type, - oi->address->u.prefix4); - if (!msg) - { - zlog_warn ("apiserver_notify_ready_type9: msg_new failed"); + struct listnode *node, *nnode; + struct listnode *node2, *nnode2; + struct ospf *ospf; + struct ospf_interface *oi; + struct registered_opaque_type *r; + + ospf = ospf_lookup(); + + for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) { + /* Check if this interface is indeed ready for type 9 */ + if (!ospf_apiserver_is_ready_type9(oi)) + continue; + + /* Check for registered opaque type 9 types */ + /* XXX: loop-de-loop - optimise me */ + for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2, + r)) { + struct msg *msg; + + if (r->lsa_type == OSPF_OPAQUE_LINK_LSA) { + + /* Yes, this opaque type is ready */ + msg = new_msg_ready_notify( + 0, OSPF_OPAQUE_LINK_LSA, r->opaque_type, + oi->address->u.prefix4); + if (!msg) { + zlog_warn( + "apiserver_notify_ready_type9: msg_new failed"); #ifdef NOTYET - /* Cannot allocate new message. What should we do? */ - ospf_apiserver_free (apiserv); + /* Cannot allocate new message. What + * should we do? */ + ospf_apiserver_free(apiserv); #endif - goto out; + goto out; + } + ospf_apiserver_send_msg(apiserv, msg); + msg_free(msg); + } } - ospf_apiserver_send_msg (apiserv, msg); - msg_free (msg); - } } - } out: - return; + return; } /* Notify specific client about all opaque types 10 that are ready. */ -void -ospf_apiserver_notify_ready_type10 (struct ospf_apiserver *apiserv) +void ospf_apiserver_notify_ready_type10(struct ospf_apiserver *apiserv) { - struct listnode *node, *nnode; - struct listnode *node2, *nnode2; - struct ospf *ospf; - struct ospf_area *area; - - ospf = ospf_lookup (); - - for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) - { - struct registered_opaque_type *r; - - if (!ospf_apiserver_is_ready_type10 (area)) - { - continue; - } - - /* Check for registered opaque type 10 types */ - /* XXX: loop in loop - optimise me */ - for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r)) - { - struct msg *msg; - - if (r->lsa_type == OSPF_OPAQUE_AREA_LSA) - { - /* Yes, this opaque type is ready */ - msg = - new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA, - r->opaque_type, area->area_id); - if (!msg) - { - zlog_warn ("apiserver_notify_ready_type10: msg_new failed"); + struct listnode *node, *nnode; + struct listnode *node2, *nnode2; + struct ospf *ospf; + struct ospf_area *area; + + ospf = ospf_lookup(); + + for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { + struct registered_opaque_type *r; + + if (!ospf_apiserver_is_ready_type10(area)) { + continue; + } + + /* Check for registered opaque type 10 types */ + /* XXX: loop in loop - optimise me */ + for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2, + r)) { + struct msg *msg; + + if (r->lsa_type == OSPF_OPAQUE_AREA_LSA) { + /* Yes, this opaque type is ready */ + msg = new_msg_ready_notify( + 0, OSPF_OPAQUE_AREA_LSA, r->opaque_type, + area->area_id); + if (!msg) { + zlog_warn( + "apiserver_notify_ready_type10: msg_new failed"); #ifdef NOTYET - /* Cannot allocate new message. What should we do? */ - ospf_apiserver_free (apiserv); + /* Cannot allocate new message. What + * should we do? */ + ospf_apiserver_free(apiserv); #endif - goto out; + goto out; + } + ospf_apiserver_send_msg(apiserv, msg); + msg_free(msg); + } } - ospf_apiserver_send_msg (apiserv, msg); - msg_free (msg); - } } - } out: - return; + return; } /* Notify specific client about all opaque types 11 that are ready */ -void -ospf_apiserver_notify_ready_type11 (struct ospf_apiserver *apiserv) +void ospf_apiserver_notify_ready_type11(struct ospf_apiserver *apiserv) { - struct listnode *node, *nnode; - struct ospf *ospf; - struct registered_opaque_type *r; - - ospf = ospf_lookup (); - - /* Can type 11 be originated? */ - if (!ospf_apiserver_is_ready_type11 (ospf)) - goto out; - - /* Check for registered opaque type 11 types */ - for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node, nnode, r)) - { - struct msg *msg; - struct in_addr noarea_id = { .s_addr = 0L }; - - if (r->lsa_type == OSPF_OPAQUE_AS_LSA) - { - /* Yes, this opaque type is ready */ - msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA, - r->opaque_type, noarea_id); - - if (!msg) - { - zlog_warn ("apiserver_notify_ready_type11: msg_new failed"); + struct listnode *node, *nnode; + struct ospf *ospf; + struct registered_opaque_type *r; + + ospf = ospf_lookup(); + + /* Can type 11 be originated? */ + if (!ospf_apiserver_is_ready_type11(ospf)) + goto out; + + /* Check for registered opaque type 11 types */ + for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node, nnode, r)) { + struct msg *msg; + struct in_addr noarea_id = {.s_addr = 0L}; + + if (r->lsa_type == OSPF_OPAQUE_AS_LSA) { + /* Yes, this opaque type is ready */ + msg = new_msg_ready_notify(0, OSPF_OPAQUE_AS_LSA, + r->opaque_type, noarea_id); + + if (!msg) { + zlog_warn( + "apiserver_notify_ready_type11: msg_new failed"); #ifdef NOTYET - /* Cannot allocate new message. What should we do? */ - ospf_apiserver_free (apiserv); + /* Cannot allocate new message. What should we + * do? */ + ospf_apiserver_free(apiserv); #endif - goto out; - } - ospf_apiserver_send_msg (apiserv, msg); - msg_free (msg); + goto out; + } + ospf_apiserver_send_msg(apiserv, msg); + msg_free(msg); + } } - } out: - return; + return; } -int -ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver *apiserv, - struct msg *msg) +int ospf_apiserver_handle_unregister_opaque_type(struct ospf_apiserver *apiserv, + struct msg *msg) { - struct msg_unregister_opaque_type *umsg; - u_char ltype; - u_char otype; - int rc = 0; + struct msg_unregister_opaque_type *umsg; + u_char ltype; + u_char otype; + int rc = 0; - /* Extract parameters from unregister opaque type message */ - umsg = (struct msg_unregister_opaque_type *) STREAM_DATA (msg->s); + /* Extract parameters from unregister opaque type message */ + umsg = (struct msg_unregister_opaque_type *)STREAM_DATA(msg->s); - ltype = umsg->lsatype; - otype = umsg->opaquetype; + ltype = umsg->lsatype; + otype = umsg->opaquetype; - rc = ospf_apiserver_unregister_opaque_type (apiserv, ltype, otype); + rc = ospf_apiserver_unregister_opaque_type(apiserv, ltype, otype); - /* Send a reply back to client including return code */ - rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc); + /* Send a reply back to client including return code */ + rc = ospf_apiserver_send_reply(apiserv, ntohl(msg->hdr.msgseq), rc); - return rc; + return rc; } @@ -1222,38 +1156,34 @@ ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver *apiserv, * Following are functions for event (filter) registration. * ----------------------------------------------------------- */ -int -ospf_apiserver_handle_register_event (struct ospf_apiserver *apiserv, - struct msg *msg) +int ospf_apiserver_handle_register_event(struct ospf_apiserver *apiserv, + struct msg *msg) { - struct msg_register_event *rmsg; - int rc; - u_int32_t seqnum; - - rmsg = (struct msg_register_event *) STREAM_DATA (msg->s); - - /* Get request sequence number */ - seqnum = msg_get_seq (msg); - - /* Free existing filter in apiserv. */ - XFREE (MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter); - /* Alloc new space for filter. */ - - apiserv->filter = XMALLOC (MTYPE_OSPF_APISERVER_MSGFILTER, - ntohs (msg->hdr.msglen)); - if (apiserv->filter) - { - /* copy it over. */ - memcpy (apiserv->filter, &rmsg->filter, ntohs (msg->hdr.msglen)); - rc = OSPF_API_OK; - } - else - { - rc = OSPF_API_NOMEMORY; - } - /* Send a reply back to client with return code */ - rc = ospf_apiserver_send_reply (apiserv, seqnum, rc); - return rc; + struct msg_register_event *rmsg; + int rc; + u_int32_t seqnum; + + rmsg = (struct msg_register_event *)STREAM_DATA(msg->s); + + /* Get request sequence number */ + seqnum = msg_get_seq(msg); + + /* Free existing filter in apiserv. */ + XFREE(MTYPE_OSPF_APISERVER_MSGFILTER, apiserv->filter); + /* Alloc new space for filter. */ + + apiserv->filter = + XMALLOC(MTYPE_OSPF_APISERVER_MSGFILTER, ntohs(msg->hdr.msglen)); + if (apiserv->filter) { + /* copy it over. */ + memcpy(apiserv->filter, &rmsg->filter, ntohs(msg->hdr.msglen)); + rc = OSPF_API_OK; + } else { + rc = OSPF_API_NOMEMORY; + } + /* Send a reply back to client with return code */ + rc = ospf_apiserver_send_reply(apiserv, seqnum, rc); + return rc; } @@ -1262,176 +1192,161 @@ ospf_apiserver_handle_register_event (struct ospf_apiserver *apiserv, * ----------------------------------------------------------- */ -static int -apiserver_sync_callback (struct ospf_lsa *lsa, void *p_arg, int int_arg) +static int apiserver_sync_callback(struct ospf_lsa *lsa, void *p_arg, + int int_arg) { - struct ospf_apiserver *apiserv; - int seqnum; - struct msg *msg; - struct param_t - { - struct ospf_apiserver *apiserv; - struct lsa_filter_type *filter; - } - *param; - int rc = -1; - - /* Sanity check */ - assert (lsa->data); - assert (p_arg); - - param = (struct param_t *) p_arg; - apiserv = param->apiserv; - seqnum = (u_int32_t) int_arg; - - /* Check origin in filter. */ - if ((param->filter->origin == ANY_ORIGIN) || - (param->filter->origin == (lsa->flags & OSPF_LSA_SELF))) - { - - /* Default area for AS-External and Opaque11 LSAs */ - struct in_addr area_id = { .s_addr = 0L }; - - /* Default interface for non Opaque9 LSAs */ - struct in_addr ifaddr = { .s_addr = 0L }; - - if (lsa->area) - { - area_id = lsa->area->area_id; - } - if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) - { - ifaddr = lsa->oi->address->u.prefix4; - } - - msg = new_msg_lsa_change_notify (MSG_LSA_UPDATE_NOTIFY, - seqnum, - ifaddr, area_id, - lsa->flags & OSPF_LSA_SELF, lsa->data); - if (!msg) - { - zlog_warn ("apiserver_sync_callback: new_msg_update failed"); + struct ospf_apiserver *apiserv; + int seqnum; + struct msg *msg; + struct param_t { + struct ospf_apiserver *apiserv; + struct lsa_filter_type *filter; + } * param; + int rc = -1; + + /* Sanity check */ + assert(lsa->data); + assert(p_arg); + + param = (struct param_t *)p_arg; + apiserv = param->apiserv; + seqnum = (u_int32_t)int_arg; + + /* Check origin in filter. */ + if ((param->filter->origin == ANY_ORIGIN) + || (param->filter->origin == (lsa->flags & OSPF_LSA_SELF))) { + + /* Default area for AS-External and Opaque11 LSAs */ + struct in_addr area_id = {.s_addr = 0L}; + + /* Default interface for non Opaque9 LSAs */ + struct in_addr ifaddr = {.s_addr = 0L}; + + if (lsa->area) { + area_id = lsa->area->area_id; + } + if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) { + ifaddr = lsa->oi->address->u.prefix4; + } + + msg = new_msg_lsa_change_notify( + MSG_LSA_UPDATE_NOTIFY, seqnum, ifaddr, area_id, + lsa->flags & OSPF_LSA_SELF, lsa->data); + if (!msg) { + zlog_warn( + "apiserver_sync_callback: new_msg_update failed"); #ifdef NOTYET - /* Cannot allocate new message. What should we do? */ -/* ospf_apiserver_free (apiserv);*//* Do nothing here XXX */ + /* Cannot allocate new message. What should we do? */ + /* ospf_apiserver_free (apiserv);*/ /* Do nothing + here XXX + */ #endif - goto out; - } + goto out; + } - /* Send LSA */ - ospf_apiserver_send_msg (apiserv, msg); - msg_free (msg); - } - rc = 0; + /* Send LSA */ + ospf_apiserver_send_msg(apiserv, msg); + msg_free(msg); + } + rc = 0; out: - return rc; + return rc; } -int -ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver *apiserv, - struct msg *msg) +int ospf_apiserver_handle_sync_lsdb(struct ospf_apiserver *apiserv, + struct msg *msg) { - struct listnode *node, *nnode; - u_int32_t seqnum; - int rc = 0; - struct msg_sync_lsdb *smsg; - struct ospf_apiserver_param_t - { - struct ospf_apiserver *apiserv; - struct lsa_filter_type *filter; - } param; - u_int16_t mask; - struct route_node *rn; - struct ospf_lsa *lsa; - struct ospf *ospf; - struct ospf_area *area; - - ospf = ospf_lookup (); - - /* Get request sequence number */ - seqnum = msg_get_seq (msg); - /* Set sync msg. */ - smsg = (struct msg_sync_lsdb *) STREAM_DATA (msg->s); - - /* Set parameter struct. */ - param.apiserv = apiserv; - param.filter = &smsg->filter; - - /* Remember mask. */ - mask = ntohs (smsg->filter.typemask); - - /* Iterate over all areas. */ - for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) - { - int i; - u_int32_t *area_id = NULL; - - /* Compare area_id with area_ids in sync request. */ - if ((i = smsg->filter.num_areas) > 0) - { - /* Let area_id point to the list of area IDs, - * which is at the end of smsg->filter. */ - area_id = (u_int32_t *) (&smsg->filter + 1); - while (i) - { - if (*area_id == area->area_id.s_addr) - { - break; + struct listnode *node, *nnode; + u_int32_t seqnum; + int rc = 0; + struct msg_sync_lsdb *smsg; + struct ospf_apiserver_param_t { + struct ospf_apiserver *apiserv; + struct lsa_filter_type *filter; + } param; + u_int16_t mask; + struct route_node *rn; + struct ospf_lsa *lsa; + struct ospf *ospf; + struct ospf_area *area; + + ospf = ospf_lookup(); + + /* Get request sequence number */ + seqnum = msg_get_seq(msg); + /* Set sync msg. */ + smsg = (struct msg_sync_lsdb *)STREAM_DATA(msg->s); + + /* Set parameter struct. */ + param.apiserv = apiserv; + param.filter = &smsg->filter; + + /* Remember mask. */ + mask = ntohs(smsg->filter.typemask); + + /* Iterate over all areas. */ + for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { + int i; + u_int32_t *area_id = NULL; + + /* Compare area_id with area_ids in sync request. */ + if ((i = smsg->filter.num_areas) > 0) { + /* Let area_id point to the list of area IDs, + * which is at the end of smsg->filter. */ + area_id = (u_int32_t *)(&smsg->filter + 1); + while (i) { + if (*area_id == area->area_id.s_addr) { + break; + } + i--; + area_id++; + } + } else { + i = 1; + } + + /* If area was found, then i>0 here. */ + if (i) { + /* Check msg type. */ + if (mask & Power2[OSPF_ROUTER_LSA]) + LSDB_LOOP(ROUTER_LSDB(area), rn, lsa) + apiserver_sync_callback(lsa, (void *)¶m, seqnum); + if (mask & Power2[OSPF_NETWORK_LSA]) + LSDB_LOOP(NETWORK_LSDB(area), rn, lsa) + apiserver_sync_callback(lsa, (void *)¶m, seqnum); + if (mask & Power2[OSPF_SUMMARY_LSA]) + LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa) + apiserver_sync_callback(lsa, (void *)¶m, seqnum); + if (mask & Power2[OSPF_ASBR_SUMMARY_LSA]) + LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa) + apiserver_sync_callback(lsa, (void *)¶m, seqnum); + if (mask & Power2[OSPF_OPAQUE_LINK_LSA]) + LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa) + apiserver_sync_callback(lsa, (void *)¶m, seqnum); + if (mask & Power2[OSPF_OPAQUE_AREA_LSA]) + LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa) + apiserver_sync_callback(lsa, (void *)¶m, seqnum); } - i--; - area_id++; - } - } - else - { - i = 1; - } - - /* If area was found, then i>0 here. */ - if (i) - { - /* Check msg type. */ - if (mask & Power2[OSPF_ROUTER_LSA]) - LSDB_LOOP (ROUTER_LSDB (area), rn, lsa) - apiserver_sync_callback(lsa, (void *) ¶m, seqnum); - if (mask & Power2[OSPF_NETWORK_LSA]) - LSDB_LOOP (NETWORK_LSDB (area), rn, lsa) - apiserver_sync_callback(lsa, (void *) ¶m, seqnum); - if (mask & Power2[OSPF_SUMMARY_LSA]) - LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa) - apiserver_sync_callback(lsa, (void *) ¶m, seqnum); - if (mask & Power2[OSPF_ASBR_SUMMARY_LSA]) - LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa) - apiserver_sync_callback(lsa, (void *) ¶m, seqnum); - if (mask & Power2[OSPF_OPAQUE_LINK_LSA]) - LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa) - apiserver_sync_callback(lsa, (void *) ¶m, seqnum); - if (mask & Power2[OSPF_OPAQUE_AREA_LSA]) - LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) - apiserver_sync_callback(lsa, (void *) ¶m, seqnum); - } - } - - /* For AS-external LSAs */ - if (ospf->lsdb) - { - if (mask & Power2[OSPF_AS_EXTERNAL_LSA]) - LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) - apiserver_sync_callback(lsa, (void *) ¶m, seqnum); - } - - /* For AS-external opaque LSAs */ - if (ospf->lsdb) - { - if (mask & Power2[OSPF_OPAQUE_AS_LSA]) - LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa) - apiserver_sync_callback(lsa, (void *) ¶m, seqnum); - } - - /* Send a reply back to client with return code */ - rc = ospf_apiserver_send_reply (apiserv, seqnum, rc); - return rc; + } + + /* For AS-external LSAs */ + if (ospf->lsdb) { + if (mask & Power2[OSPF_AS_EXTERNAL_LSA]) + LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa) + apiserver_sync_callback(lsa, (void *)¶m, seqnum); + } + + /* For AS-external opaque LSAs */ + if (ospf->lsdb) { + if (mask & Power2[OSPF_OPAQUE_AS_LSA]) + LSDB_LOOP(OPAQUE_AS_LSDB(ospf), rn, lsa) + apiserver_sync_callback(lsa, (void *)¶m, seqnum); + } + + /* Send a reply back to client with return code */ + rc = ospf_apiserver_send_reply(apiserv, seqnum, rc); + return rc; } @@ -1447,457 +1362,435 @@ ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver *apiserv, LSAs, area parameter for type 10. Type 11 LSAs do neither need area nor interface. */ -struct ospf_lsa * -ospf_apiserver_opaque_lsa_new (struct ospf_area *area, - struct ospf_interface *oi, - struct lsa_header *protolsa) +struct ospf_lsa *ospf_apiserver_opaque_lsa_new(struct ospf_area *area, + struct ospf_interface *oi, + struct lsa_header *protolsa) { - struct stream *s; - struct lsa_header *newlsa; - struct ospf_lsa *new = NULL; - u_char options = 0x0; - u_int16_t length; - - struct ospf *ospf; - - ospf = ospf_lookup(); - assert(ospf); - - /* Create a stream for internal opaque LSA */ - if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL) - { - zlog_warn ("ospf_apiserver_opaque_lsa_new: stream_new failed"); - return NULL; - } - - newlsa = (struct lsa_header *) STREAM_DATA (s); - - /* XXX If this is a link-local LSA or an AS-external LSA, how do we - have to set options? */ - - if (area) - { - options = LSA_OPTIONS_GET (area); - options |= LSA_OPTIONS_NSSA_GET (area); - } - - options |= OSPF_OPTION_O; /* Don't forget to set option bit */ - - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - { - zlog_debug ("LSA[Type%d:%s]: Creating an Opaque-LSA instance", - protolsa->type, inet_ntoa (protolsa->id)); - } - - /* Set opaque-LSA header fields. */ - lsa_header_set (s, options, protolsa->type, protolsa->id, - ospf->router_id); - - /* Set opaque-LSA body fields. */ - stream_put (s, ((u_char *) protolsa) + sizeof (struct lsa_header), - ntohs (protolsa->length) - sizeof (struct lsa_header)); - - /* Determine length of LSA. */ - length = stream_get_endp (s); - newlsa->length = htons (length); - - /* Create OSPF LSA. */ - if ((new = ospf_lsa_new ()) == NULL) - { - zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?"); - stream_free (s); - return NULL; - } - - if ((new->data = ospf_lsa_data_new (length)) == NULL) - { - zlog_warn ("ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?"); - ospf_lsa_unlock (&new); - stream_free (s); - return NULL; - } - - new->area = area; - new->oi = oi; - - SET_FLAG (new->flags, OSPF_LSA_SELF); - memcpy (new->data, newlsa, length); - stream_free (s); - - return new; + struct stream *s; + struct lsa_header *newlsa; + struct ospf_lsa *new = NULL; + u_char options = 0x0; + u_int16_t length; + + struct ospf *ospf; + + ospf = ospf_lookup(); + assert(ospf); + + /* Create a stream for internal opaque LSA */ + if ((s = stream_new(OSPF_MAX_LSA_SIZE)) == NULL) { + zlog_warn("ospf_apiserver_opaque_lsa_new: stream_new failed"); + return NULL; + } + + newlsa = (struct lsa_header *)STREAM_DATA(s); + + /* XXX If this is a link-local LSA or an AS-external LSA, how do we + have to set options? */ + + if (area) { + options = LSA_OPTIONS_GET(area); + options |= LSA_OPTIONS_NSSA_GET(area); + } + + options |= OSPF_OPTION_O; /* Don't forget to set option bit */ + + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug("LSA[Type%d:%s]: Creating an Opaque-LSA instance", + protolsa->type, inet_ntoa(protolsa->id)); + } + + /* Set opaque-LSA header fields. */ + lsa_header_set(s, options, protolsa->type, protolsa->id, + ospf->router_id); + + /* Set opaque-LSA body fields. */ + stream_put(s, ((u_char *)protolsa) + sizeof(struct lsa_header), + ntohs(protolsa->length) - sizeof(struct lsa_header)); + + /* Determine length of LSA. */ + length = stream_get_endp(s); + newlsa->length = htons(length); + + /* Create OSPF LSA. */ + if ((new = ospf_lsa_new()) == NULL) { + zlog_warn("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?"); + stream_free(s); + return NULL; + } + + if ((new->data = ospf_lsa_data_new(length)) == NULL) { + zlog_warn( + "ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?"); + ospf_lsa_unlock(&new); + stream_free(s); + return NULL; + } + + new->area = area; + new->oi = oi; + + SET_FLAG(new->flags, OSPF_LSA_SELF); + memcpy(new->data, newlsa, length); + stream_free(s); + + return new; } -int -ospf_apiserver_is_ready_type9 (struct ospf_interface *oi) +int ospf_apiserver_is_ready_type9(struct ospf_interface *oi) { - /* Type 9 opaque LSA can be originated if there is at least one - active opaque-capable neighbor attached to the outgoing - interface. */ + /* Type 9 opaque LSA can be originated if there is at least one + active opaque-capable neighbor attached to the outgoing + interface. */ - return (ospf_nbr_count_opaque_capable (oi) > 0); + return (ospf_nbr_count_opaque_capable(oi) > 0); } -int -ospf_apiserver_is_ready_type10 (struct ospf_area *area) +int ospf_apiserver_is_ready_type10(struct ospf_area *area) { - /* Type 10 opaque LSA can be originated if there is at least one - interface belonging to the area that has an active opaque-capable - neighbor. */ - struct listnode *node, *nnode; - struct ospf_interface *oi; - - for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi)) - /* Is there an active neighbor attached to this interface? */ - if (ospf_apiserver_is_ready_type9 (oi)) - return 1; - - /* No active neighbor in area */ - return 0; + /* Type 10 opaque LSA can be originated if there is at least one + interface belonging to the area that has an active opaque-capable + neighbor. */ + struct listnode *node, *nnode; + struct ospf_interface *oi; + + for (ALL_LIST_ELEMENTS(area->oiflist, node, nnode, oi)) + /* Is there an active neighbor attached to this interface? */ + if (ospf_apiserver_is_ready_type9(oi)) + return 1; + + /* No active neighbor in area */ + return 0; } -int -ospf_apiserver_is_ready_type11 (struct ospf *ospf) +int ospf_apiserver_is_ready_type11(struct ospf *ospf) { - /* Type 11 opaque LSA can be originated if there is at least one interface - that has an active opaque-capable neighbor. */ - struct listnode *node, *nnode; - struct ospf_interface *oi; - - for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) - /* Is there an active neighbor attached to this interface? */ - if (ospf_apiserver_is_ready_type9 (oi)) - return 1; - - /* No active neighbor at all */ - return 0; + /* Type 11 opaque LSA can be originated if there is at least one + interface + that has an active opaque-capable neighbor. */ + struct listnode *node, *nnode; + struct ospf_interface *oi; + + for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) + /* Is there an active neighbor attached to this interface? */ + if (ospf_apiserver_is_ready_type9(oi)) + return 1; + + /* No active neighbor at all */ + return 0; } -int -ospf_apiserver_handle_originate_request (struct ospf_apiserver *apiserv, - struct msg *msg) +int ospf_apiserver_handle_originate_request(struct ospf_apiserver *apiserv, + struct msg *msg) { - struct msg_originate_request *omsg; - struct lsa_header *data; - struct ospf_lsa *new; - struct ospf_lsa *old; - struct ospf_area *area = NULL; - struct ospf_interface *oi = NULL; - struct ospf_lsdb *lsdb = NULL; - struct ospf *ospf; - int lsa_type, opaque_type; - int ready = 0; - int rc = 0; - - ospf = ospf_lookup(); - - /* Extract opaque LSA data from message */ - omsg = (struct msg_originate_request *) STREAM_DATA (msg->s); - data = &omsg->data; - - /* Determine interface for type9 or area for type10 LSAs. */ - switch (data->type) - { - case OSPF_OPAQUE_LINK_LSA: - oi = ospf_apiserver_if_lookup_by_addr (omsg->ifaddr); - if (!oi) - { - zlog_warn ("apiserver_originate: unknown interface %s", - inet_ntoa (omsg->ifaddr)); - rc = OSPF_API_NOSUCHINTERFACE; - goto out; - } - area = oi->area; - lsdb = area->lsdb; - break; - case OSPF_OPAQUE_AREA_LSA: - area = ospf_area_lookup_by_area_id (ospf, omsg->area_id); - if (!area) - { - zlog_warn ("apiserver_originate: unknown area %s", - inet_ntoa (omsg->area_id)); - rc = OSPF_API_NOSUCHAREA; - goto out; - } - lsdb = area->lsdb; - break; - case OSPF_OPAQUE_AS_LSA: - lsdb = ospf->lsdb; - break; - default: - /* We can only handle opaque types here */ - zlog_warn ("apiserver_originate: Cannot originate non-opaque LSA type %d", - data->type); - rc = OSPF_API_ILLEGALLSATYPE; - goto out; - } - - /* Check if we registered this opaque type */ - lsa_type = data->type; - opaque_type = GET_OPAQUE_TYPE (ntohl (data->id.s_addr)); - - if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type)) - { - zlog_warn ("apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type); - rc = OSPF_API_OPAQUETYPENOTREGISTERED; - goto out; - } - - /* Make sure that the neighbors are ready before we can originate */ - switch (data->type) - { - case OSPF_OPAQUE_LINK_LSA: - ready = ospf_apiserver_is_ready_type9 (oi); - break; - case OSPF_OPAQUE_AREA_LSA: - ready = ospf_apiserver_is_ready_type10 (area); - break; - case OSPF_OPAQUE_AS_LSA: - ready = ospf_apiserver_is_ready_type11 (ospf); - break; - default: - break; - } - - if (!ready) - { - zlog_warn ("Neighbors not ready to originate type %d", data->type); - rc = OSPF_API_NOTREADY; - goto out; - } - - /* Create OSPF's internal opaque LSA representation */ - new = ospf_apiserver_opaque_lsa_new (area, oi, data); - if (!new) - { - rc = OSPF_API_NOMEMORY; /* XXX */ - goto out; - } - - /* Determine if LSA is new or an update for an existing one. */ - old = ospf_lsdb_lookup (lsdb, new); - - if (!old) - { - /* New LSA install in LSDB. */ - rc = ospf_apiserver_originate1 (new); - } - else - { - /* - * Keep the new LSA instance in the "waiting place" until the next - * refresh timing. If several LSA update requests for the same LSID - * have issued by peer, the last one takes effect. - */ - new->lsdb = &apiserv->reserve; - ospf_lsdb_add (&apiserv->reserve, new); - - /* Kick the scheduler function. */ - ospf_opaque_lsa_refresh_schedule (old); - } + struct msg_originate_request *omsg; + struct lsa_header *data; + struct ospf_lsa *new; + struct ospf_lsa *old; + struct ospf_area *area = NULL; + struct ospf_interface *oi = NULL; + struct ospf_lsdb *lsdb = NULL; + struct ospf *ospf; + int lsa_type, opaque_type; + int ready = 0; + int rc = 0; + + ospf = ospf_lookup(); + + /* Extract opaque LSA data from message */ + omsg = (struct msg_originate_request *)STREAM_DATA(msg->s); + data = &omsg->data; + + /* Determine interface for type9 or area for type10 LSAs. */ + switch (data->type) { + case OSPF_OPAQUE_LINK_LSA: + oi = ospf_apiserver_if_lookup_by_addr(omsg->ifaddr); + if (!oi) { + zlog_warn("apiserver_originate: unknown interface %s", + inet_ntoa(omsg->ifaddr)); + rc = OSPF_API_NOSUCHINTERFACE; + goto out; + } + area = oi->area; + lsdb = area->lsdb; + break; + case OSPF_OPAQUE_AREA_LSA: + area = ospf_area_lookup_by_area_id(ospf, omsg->area_id); + if (!area) { + zlog_warn("apiserver_originate: unknown area %s", + inet_ntoa(omsg->area_id)); + rc = OSPF_API_NOSUCHAREA; + goto out; + } + lsdb = area->lsdb; + break; + case OSPF_OPAQUE_AS_LSA: + lsdb = ospf->lsdb; + break; + default: + /* We can only handle opaque types here */ + zlog_warn( + "apiserver_originate: Cannot originate non-opaque LSA type %d", + data->type); + rc = OSPF_API_ILLEGALLSATYPE; + goto out; + } + + /* Check if we registered this opaque type */ + lsa_type = data->type; + opaque_type = GET_OPAQUE_TYPE(ntohl(data->id.s_addr)); + + if (!apiserver_is_opaque_type_registered(apiserv, lsa_type, + opaque_type)) { + zlog_warn( + "apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered", + lsa_type, opaque_type); + rc = OSPF_API_OPAQUETYPENOTREGISTERED; + goto out; + } + + /* Make sure that the neighbors are ready before we can originate */ + switch (data->type) { + case OSPF_OPAQUE_LINK_LSA: + ready = ospf_apiserver_is_ready_type9(oi); + break; + case OSPF_OPAQUE_AREA_LSA: + ready = ospf_apiserver_is_ready_type10(area); + break; + case OSPF_OPAQUE_AS_LSA: + ready = ospf_apiserver_is_ready_type11(ospf); + break; + default: + break; + } + + if (!ready) { + zlog_warn("Neighbors not ready to originate type %d", + data->type); + rc = OSPF_API_NOTREADY; + goto out; + } + + /* Create OSPF's internal opaque LSA representation */ + new = ospf_apiserver_opaque_lsa_new(area, oi, data); + if (!new) { + rc = OSPF_API_NOMEMORY; /* XXX */ + goto out; + } + + /* Determine if LSA is new or an update for an existing one. */ + old = ospf_lsdb_lookup(lsdb, new); + + if (!old) { + /* New LSA install in LSDB. */ + rc = ospf_apiserver_originate1(new); + } else { + /* + * Keep the new LSA instance in the "waiting place" until the + * next + * refresh timing. If several LSA update requests for the same + * LSID + * have issued by peer, the last one takes effect. + */ + new->lsdb = &apiserv->reserve; + ospf_lsdb_add(&apiserv->reserve, new); + + /* Kick the scheduler function. */ + ospf_opaque_lsa_refresh_schedule(old); + } out: - /* Send a reply back to client with return code */ - rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc); - return rc; + /* Send a reply back to client with return code */ + rc = ospf_apiserver_send_reply(apiserv, ntohl(msg->hdr.msgseq), rc); + return rc; } /* ----------------------------------------------------------- - * Flood an LSA within its flooding scope. + * Flood an LSA within its flooding scope. * ----------------------------------------------------------- */ /* XXX We can probably use ospf_flood_through instead of this function - but then we need the neighbor parameter. If we set nbr to + but then we need the neighbor parameter. If we set nbr to NULL then ospf_flood_through crashes due to dereferencing NULL. */ -void -ospf_apiserver_flood_opaque_lsa (struct ospf_lsa *lsa) +void ospf_apiserver_flood_opaque_lsa(struct ospf_lsa *lsa) { - assert (lsa); - - switch (lsa->data->type) - { - case OSPF_OPAQUE_LINK_LSA: - /* Increment counters? XXX */ - - /* Flood LSA through local network. */ - ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa); - break; - case OSPF_OPAQUE_AREA_LSA: - /* Update LSA origination count. */ - assert (lsa->area); - lsa->area->ospf->lsa_originate_count++; - - /* Flood LSA through area. */ - ospf_flood_through_area (lsa->area, NULL /*nbr */ , lsa); - break; - case OSPF_OPAQUE_AS_LSA: - { - struct ospf *ospf; - - ospf = ospf_lookup(); - assert(ospf); - - /* Increment counters? XXX */ - - /* Flood LSA through AS. */ - ospf_flood_through_as (ospf, NULL /*nbr */ , lsa); - break; - } - } + assert(lsa); + + switch (lsa->data->type) { + case OSPF_OPAQUE_LINK_LSA: + /* Increment counters? XXX */ + + /* Flood LSA through local network. */ + ospf_flood_through_area(lsa->area, NULL /*nbr */, lsa); + break; + case OSPF_OPAQUE_AREA_LSA: + /* Update LSA origination count. */ + assert(lsa->area); + lsa->area->ospf->lsa_originate_count++; + + /* Flood LSA through area. */ + ospf_flood_through_area(lsa->area, NULL /*nbr */, lsa); + break; + case OSPF_OPAQUE_AS_LSA: { + struct ospf *ospf; + + ospf = ospf_lookup(); + assert(ospf); + + /* Increment counters? XXX */ + + /* Flood LSA through AS. */ + ospf_flood_through_as(ospf, NULL /*nbr */, lsa); + break; + } + } } -int -ospf_apiserver_originate1 (struct ospf_lsa *lsa) +int ospf_apiserver_originate1(struct ospf_lsa *lsa) { - struct ospf *ospf; + struct ospf *ospf; - ospf = ospf_lookup(); - assert(ospf); + ospf = ospf_lookup(); + assert(ospf); - /* Install this LSA into LSDB. */ - if (ospf_lsa_install (ospf, lsa->oi, lsa) == NULL) - { - zlog_warn ("ospf_apiserver_originate1: ospf_lsa_install failed"); - return -1; - } + /* Install this LSA into LSDB. */ + if (ospf_lsa_install(ospf, lsa->oi, lsa) == NULL) { + zlog_warn("ospf_apiserver_originate1: ospf_lsa_install failed"); + return -1; + } - /* Flood LSA within scope */ +/* Flood LSA within scope */ #ifdef NOTYET - /* - * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr" - * parameter, and thus it does not cause SIGSEGV error. - */ - ospf_flood_through (NULL /*nbr */ , lsa); -#else /* NOTYET */ - - ospf_apiserver_flood_opaque_lsa (lsa); + /* + * NB: Modified version of "ospf_flood_though ()" accepts NULL "inbr" + * parameter, and thus it does not cause SIGSEGV error. + */ + ospf_flood_through(NULL /*nbr */, lsa); +#else /* NOTYET */ + + ospf_apiserver_flood_opaque_lsa(lsa); #endif /* NOTYET */ - return 0; + return 0; } /* Opaque LSAs of type 9 on a specific interface can now be originated. Tell clients that registered type 9. */ -int -ospf_apiserver_lsa9_originator (void *arg) +int ospf_apiserver_lsa9_originator(void *arg) { - struct ospf_interface *oi; + struct ospf_interface *oi; - oi = (struct ospf_interface *) arg; - if (listcount (apiserver_list) > 0) { - ospf_apiserver_clients_notify_ready_type9 (oi); - } - return 0; + oi = (struct ospf_interface *)arg; + if (listcount(apiserver_list) > 0) { + ospf_apiserver_clients_notify_ready_type9(oi); + } + return 0; } -int -ospf_apiserver_lsa10_originator (void *arg) +int ospf_apiserver_lsa10_originator(void *arg) { - struct ospf_area *area; + struct ospf_area *area; - area = (struct ospf_area *) arg; - if (listcount (apiserver_list) > 0) { - ospf_apiserver_clients_notify_ready_type10 (area); - } - return 0; + area = (struct ospf_area *)arg; + if (listcount(apiserver_list) > 0) { + ospf_apiserver_clients_notify_ready_type10(area); + } + return 0; } -int -ospf_apiserver_lsa11_originator (void *arg) +int ospf_apiserver_lsa11_originator(void *arg) { - struct ospf *ospf; + struct ospf *ospf; - ospf = (struct ospf *) arg; - if (listcount (apiserver_list) > 0) { - ospf_apiserver_clients_notify_ready_type11 (ospf); - } - return 0; + ospf = (struct ospf *)arg; + if (listcount(apiserver_list) > 0) { + ospf_apiserver_clients_notify_ready_type11(ospf); + } + return 0; } /* Periodically refresh opaque LSAs so that they do not expire in other routers. */ -struct ospf_lsa * -ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa) +struct ospf_lsa *ospf_apiserver_lsa_refresher(struct ospf_lsa *lsa) { - struct ospf_apiserver *apiserv; - struct ospf_lsa *new = NULL; - struct ospf * ospf; - - ospf = ospf_lookup(); - assert(ospf); - - apiserv = lookup_apiserver_by_lsa (lsa); - if (!apiserv) - { - zlog_warn ("ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?", dump_lsa_key (lsa)); - lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */ - } - - if (IS_LSA_MAXAGE (lsa)) - { - ospf_opaque_lsa_flush_schedule (lsa); - goto out; - } - - /* Check if updated version of LSA instance has already prepared. */ - new = ospf_lsdb_lookup (&apiserv->reserve, lsa); - if (!new) - { - /* This is a periodic refresh, driven by core OSPF mechanism. */ - new = ospf_apiserver_opaque_lsa_new (lsa->area, lsa->oi, lsa->data); - if (!new) - { - zlog_warn ("ospf_apiserver_lsa_refresher: Cannot create a new LSA?"); - goto out; - } - } - else - { - /* This is a forcible refresh, requested by OSPF-API client. */ - ospf_lsdb_delete (&apiserv->reserve, new); - new->lsdb = NULL; - } - - /* Increment sequence number */ - new->data->ls_seqnum = lsa_seqnum_increment (lsa); - - /* New LSA is in same area. */ - new->area = lsa->area; - SET_FLAG (new->flags, OSPF_LSA_SELF); - - /* Install LSA into LSDB. */ - if (ospf_lsa_install (ospf, new->oi, new) == NULL) - { - zlog_warn ("ospf_apiserver_lsa_refresher: ospf_lsa_install failed"); - ospf_lsa_unlock (&new); - goto out; - } - - /* Flood updated LSA through interface, area or AS */ + struct ospf_apiserver *apiserv; + struct ospf_lsa *new = NULL; + struct ospf *ospf; + + ospf = ospf_lookup(); + assert(ospf); + + apiserv = lookup_apiserver_by_lsa(lsa); + if (!apiserv) { + zlog_warn( + "ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?", + dump_lsa_key(lsa)); + lsa->data->ls_age = + htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */ + } + + if (IS_LSA_MAXAGE(lsa)) { + ospf_opaque_lsa_flush_schedule(lsa); + goto out; + } + + /* Check if updated version of LSA instance has already prepared. */ + new = ospf_lsdb_lookup(&apiserv->reserve, lsa); + if (!new) { + /* This is a periodic refresh, driven by core OSPF mechanism. */ + new = ospf_apiserver_opaque_lsa_new(lsa->area, lsa->oi, + lsa->data); + if (!new) { + zlog_warn( + "ospf_apiserver_lsa_refresher: Cannot create a new LSA?"); + goto out; + } + } else { + /* This is a forcible refresh, requested by OSPF-API client. */ + ospf_lsdb_delete(&apiserv->reserve, new); + new->lsdb = NULL; + } + + /* Increment sequence number */ + new->data->ls_seqnum = lsa_seqnum_increment(lsa); + + /* New LSA is in same area. */ + new->area = lsa->area; + SET_FLAG(new->flags, OSPF_LSA_SELF); + + /* Install LSA into LSDB. */ + if (ospf_lsa_install(ospf, new->oi, new) == NULL) { + zlog_warn( + "ospf_apiserver_lsa_refresher: ospf_lsa_install failed"); + ospf_lsa_unlock(&new); + goto out; + } + +/* Flood updated LSA through interface, area or AS */ #ifdef NOTYET - ospf_flood_through (NULL /*nbr */ , new); + ospf_flood_through(NULL /*nbr */, new); #endif /* NOTYET */ - ospf_apiserver_flood_opaque_lsa (new); + ospf_apiserver_flood_opaque_lsa(new); - /* Debug logging. */ - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - { - zlog_debug ("LSA[Type%d:%s]: Refresh Opaque LSA", - new->data->type, inet_ntoa (new->data->id)); - ospf_lsa_header_dump (new->data); - } + /* Debug logging. */ + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug("LSA[Type%d:%s]: Refresh Opaque LSA", + new->data->type, inet_ntoa(new->data->id)); + ospf_lsa_header_dump(new->data); + } out: - return new; + return new; } @@ -1906,319 +1799,308 @@ out: * ----------------------------------------------------------- */ -int -ospf_apiserver_handle_delete_request (struct ospf_apiserver *apiserv, - struct msg *msg) +int ospf_apiserver_handle_delete_request(struct ospf_apiserver *apiserv, + struct msg *msg) { - struct msg_delete_request *dmsg; - struct ospf_lsa *old; - struct ospf_area *area = NULL; - struct in_addr id; - int lsa_type, opaque_type; - int rc = 0; - struct ospf * ospf; - - ospf = ospf_lookup(); - assert(ospf); - - /* Extract opaque LSA from message */ - dmsg = (struct msg_delete_request *) STREAM_DATA (msg->s); - - /* Lookup area for link-local and area-local opaque LSAs */ - switch (dmsg->lsa_type) - { - case OSPF_OPAQUE_LINK_LSA: - case OSPF_OPAQUE_AREA_LSA: - area = ospf_area_lookup_by_area_id (ospf, dmsg->area_id); - if (!area) - { - zlog_warn ("ospf_apiserver_lsa_delete: unknown area %s", - inet_ntoa (dmsg->area_id)); - rc = OSPF_API_NOSUCHAREA; - goto out; - } - break; - case OSPF_OPAQUE_AS_LSA: - /* AS-external opaque LSAs have no designated area */ - area = NULL; - break; - default: - zlog_warn - ("ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d", - dmsg->lsa_type); - rc = OSPF_API_ILLEGALLSATYPE; - goto out; - } - - /* Check if we registered this opaque type */ - lsa_type = dmsg->lsa_type; - opaque_type = dmsg->opaque_type; - - if (!apiserver_is_opaque_type_registered (apiserv, lsa_type, opaque_type)) - { - zlog_warn ("ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered", lsa_type, opaque_type); - rc = OSPF_API_OPAQUETYPENOTREGISTERED; - goto out; - } - - /* opaque_id is in network byte order */ - id.s_addr = htonl (SET_OPAQUE_LSID (dmsg->opaque_type, - ntohl (dmsg->opaque_id))); - - /* - * Even if the target LSA has once scheduled to flush, it remains in - * the LSDB until it is finally handled by the maxage remover thread. - * Therefore, the lookup function below may return non-NULL result. - */ - old = ospf_lsa_lookup (area, dmsg->lsa_type, id, ospf->router_id); - if (!old) - { - zlog_warn ("ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB", - dmsg->lsa_type, inet_ntoa (id)); - rc = OSPF_API_NOSUCHLSA; - goto out; - } - - /* Schedule flushing of LSA from LSDB */ - /* NB: Multiple scheduling will produce a warning message, but harmless. */ - ospf_opaque_lsa_flush_schedule (old); + struct msg_delete_request *dmsg; + struct ospf_lsa *old; + struct ospf_area *area = NULL; + struct in_addr id; + int lsa_type, opaque_type; + int rc = 0; + struct ospf *ospf; + + ospf = ospf_lookup(); + assert(ospf); + + /* Extract opaque LSA from message */ + dmsg = (struct msg_delete_request *)STREAM_DATA(msg->s); + + /* Lookup area for link-local and area-local opaque LSAs */ + switch (dmsg->lsa_type) { + case OSPF_OPAQUE_LINK_LSA: + case OSPF_OPAQUE_AREA_LSA: + area = ospf_area_lookup_by_area_id(ospf, dmsg->area_id); + if (!area) { + zlog_warn("ospf_apiserver_lsa_delete: unknown area %s", + inet_ntoa(dmsg->area_id)); + rc = OSPF_API_NOSUCHAREA; + goto out; + } + break; + case OSPF_OPAQUE_AS_LSA: + /* AS-external opaque LSAs have no designated area */ + area = NULL; + break; + default: + zlog_warn( + "ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d", + dmsg->lsa_type); + rc = OSPF_API_ILLEGALLSATYPE; + goto out; + } + + /* Check if we registered this opaque type */ + lsa_type = dmsg->lsa_type; + opaque_type = dmsg->opaque_type; + + if (!apiserver_is_opaque_type_registered(apiserv, lsa_type, + opaque_type)) { + zlog_warn( + "ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered", + lsa_type, opaque_type); + rc = OSPF_API_OPAQUETYPENOTREGISTERED; + goto out; + } + + /* opaque_id is in network byte order */ + id.s_addr = htonl( + SET_OPAQUE_LSID(dmsg->opaque_type, ntohl(dmsg->opaque_id))); + + /* + * Even if the target LSA has once scheduled to flush, it remains in + * the LSDB until it is finally handled by the maxage remover thread. + * Therefore, the lookup function below may return non-NULL result. + */ + old = ospf_lsa_lookup(area, dmsg->lsa_type, id, ospf->router_id); + if (!old) { + zlog_warn( + "ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB", + dmsg->lsa_type, inet_ntoa(id)); + rc = OSPF_API_NOSUCHLSA; + goto out; + } + + /* Schedule flushing of LSA from LSDB */ + /* NB: Multiple scheduling will produce a warning message, but harmless. + */ + ospf_opaque_lsa_flush_schedule(old); out: - /* Send reply back to client including return code */ - rc = ospf_apiserver_send_reply (apiserv, ntohl (msg->hdr.msgseq), rc); - return rc; + /* Send reply back to client including return code */ + rc = ospf_apiserver_send_reply(apiserv, ntohl(msg->hdr.msgseq), rc); + return rc; } /* Flush self-originated opaque LSA */ -static int -apiserver_flush_opaque_type_callback (struct ospf_lsa *lsa, - void *p_arg, int int_arg) +static int apiserver_flush_opaque_type_callback(struct ospf_lsa *lsa, + void *p_arg, int int_arg) { - struct param_t - { - struct ospf_apiserver *apiserv; - u_char lsa_type; - u_char opaque_type; - } - *param; - - /* Sanity check */ - assert (lsa->data); - assert (p_arg); - param = (struct param_t *) p_arg; - - /* If LSA matches type and opaque type then delete it */ - if (IS_LSA_SELF (lsa) && lsa->data->type == param->lsa_type - && GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)) == param->opaque_type) - { - ospf_opaque_lsa_flush_schedule (lsa); - } - return 0; + struct param_t { + struct ospf_apiserver *apiserv; + u_char lsa_type; + u_char opaque_type; + } * param; + + /* Sanity check */ + assert(lsa->data); + assert(p_arg); + param = (struct param_t *)p_arg; + + /* If LSA matches type and opaque type then delete it */ + if (IS_LSA_SELF(lsa) && lsa->data->type == param->lsa_type + && GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)) + == param->opaque_type) { + ospf_opaque_lsa_flush_schedule(lsa); + } + return 0; } /* Delete self-originated opaque LSAs of a given opaque type. This function is called when an application unregisters a given opaque type or a connection to an application closes and all those opaque LSAs need to be flushed the LSDB. */ -void -ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver *apiserv, - u_char lsa_type, u_char opaque_type) +void ospf_apiserver_flush_opaque_lsa(struct ospf_apiserver *apiserv, + u_char lsa_type, u_char opaque_type) { - struct param_t - { - struct ospf_apiserver *apiserv; - u_char lsa_type; - u_char opaque_type; - } param; - struct listnode *node, *nnode; - struct ospf * ospf; - struct ospf_area *area; - - ospf = ospf_lookup(); - assert(ospf); - - /* Set parameter struct. */ - param.apiserv = apiserv; - param.lsa_type = lsa_type; - param.opaque_type = opaque_type; - - switch (lsa_type) - { - struct route_node *rn; - struct ospf_lsa *lsa; - - case OSPF_OPAQUE_LINK_LSA: - for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) - LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa) - apiserver_flush_opaque_type_callback(lsa, (void *) ¶m, 0); - break; - case OSPF_OPAQUE_AREA_LSA: - for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) - LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) - apiserver_flush_opaque_type_callback(lsa, (void *) ¶m, 0); - break; - case OSPF_OPAQUE_AS_LSA: - LSDB_LOOP (OPAQUE_LINK_LSDB (ospf), rn, lsa) - apiserver_flush_opaque_type_callback(lsa, (void *) ¶m, 0); - break; - default: - break; - } - return; + struct param_t { + struct ospf_apiserver *apiserv; + u_char lsa_type; + u_char opaque_type; + } param; + struct listnode *node, *nnode; + struct ospf *ospf; + struct ospf_area *area; + + ospf = ospf_lookup(); + assert(ospf); + + /* Set parameter struct. */ + param.apiserv = apiserv; + param.lsa_type = lsa_type; + param.opaque_type = opaque_type; + + switch (lsa_type) { + struct route_node *rn; + struct ospf_lsa *lsa; + + case OSPF_OPAQUE_LINK_LSA: + for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) + LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa) + apiserver_flush_opaque_type_callback(lsa, (void *)¶m, 0); + break; + case OSPF_OPAQUE_AREA_LSA: + for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) + LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa) + apiserver_flush_opaque_type_callback(lsa, (void *)¶m, 0); + break; + case OSPF_OPAQUE_AS_LSA: + LSDB_LOOP(OPAQUE_LINK_LSDB(ospf), rn, lsa) + apiserver_flush_opaque_type_callback(lsa, (void *)¶m, 0); + break; + default: + break; + } + return; } /* ----------------------------------------------------------- - * Followings are callback functions to handle opaque types + * Followings are callback functions to handle opaque types * ----------------------------------------------------------- */ -int -ospf_apiserver_new_if (struct interface *ifp) +int ospf_apiserver_new_if(struct interface *ifp) { - struct ospf_interface *oi; - - /* For some strange reason it seems possible that we are invoked - with an interface that has no name. This seems to happen during - initialization. Return if this happens */ - - if (ifp->name[0] == '\0') { - /* interface has empty name */ - zlog_warn ("ospf_apiserver_new_if: interface has no name?"); - return 0; - } - - /* zlog_warn for debugging */ - zlog_warn ("ospf_apiserver_new_if"); - zlog_warn ("ifp name=%s status=%d index=%d", ifp->name, ifp->status, - ifp->ifindex); - - if (ifp->name[0] == '\0') { - /* interface has empty name */ - zlog_warn ("ospf_apiserver_new_if: interface has no name?"); - return 0; - } - - oi = ospf_apiserver_if_lookup_by_ifp (ifp); - - if (!oi) { - /* This interface is known to Zebra but not to OSPF daemon yet. */ - zlog_warn ("ospf_apiserver_new_if: interface %s not known to OSPFd?", - ifp->name); - return 0; - } - - assert (oi); - - /* New interface added to OSPF, tell clients about it */ - if (listcount (apiserver_list) > 0) { - ospf_apiserver_clients_notify_new_if (oi); - } - return 0; + struct ospf_interface *oi; + + /* For some strange reason it seems possible that we are invoked + with an interface that has no name. This seems to happen during + initialization. Return if this happens */ + + if (ifp->name[0] == '\0') { + /* interface has empty name */ + zlog_warn("ospf_apiserver_new_if: interface has no name?"); + return 0; + } + + /* zlog_warn for debugging */ + zlog_warn("ospf_apiserver_new_if"); + zlog_warn("ifp name=%s status=%d index=%d", ifp->name, ifp->status, + ifp->ifindex); + + if (ifp->name[0] == '\0') { + /* interface has empty name */ + zlog_warn("ospf_apiserver_new_if: interface has no name?"); + return 0; + } + + oi = ospf_apiserver_if_lookup_by_ifp(ifp); + + if (!oi) { + /* This interface is known to Zebra but not to OSPF daemon yet. + */ + zlog_warn( + "ospf_apiserver_new_if: interface %s not known to OSPFd?", + ifp->name); + return 0; + } + + assert(oi); + + /* New interface added to OSPF, tell clients about it */ + if (listcount(apiserver_list) > 0) { + ospf_apiserver_clients_notify_new_if(oi); + } + return 0; } -int -ospf_apiserver_del_if (struct interface *ifp) +int ospf_apiserver_del_if(struct interface *ifp) { - struct ospf_interface *oi; - - /* zlog_warn for debugging */ - zlog_warn ("ospf_apiserver_del_if"); - zlog_warn ("ifp name=%s status=%d index=%d\n", ifp->name, ifp->status, - ifp->ifindex); - - oi = ospf_apiserver_if_lookup_by_ifp (ifp); - - if (!oi) { - /* This interface is known to Zebra but not to OSPF daemon - anymore. No need to tell clients about it */ - return 0; - } - - /* Interface deleted, tell clients about it */ - if (listcount (apiserver_list) > 0) { - ospf_apiserver_clients_notify_del_if (oi); - } - return 0; + struct ospf_interface *oi; + + /* zlog_warn for debugging */ + zlog_warn("ospf_apiserver_del_if"); + zlog_warn("ifp name=%s status=%d index=%d\n", ifp->name, ifp->status, + ifp->ifindex); + + oi = ospf_apiserver_if_lookup_by_ifp(ifp); + + if (!oi) { + /* This interface is known to Zebra but not to OSPF daemon + anymore. No need to tell clients about it */ + return 0; + } + + /* Interface deleted, tell clients about it */ + if (listcount(apiserver_list) > 0) { + ospf_apiserver_clients_notify_del_if(oi); + } + return 0; } -void -ospf_apiserver_ism_change (struct ospf_interface *oi, int old_state) +void ospf_apiserver_ism_change(struct ospf_interface *oi, int old_state) { - /* Tell clients about interface change */ + /* Tell clients about interface change */ - /* zlog_warn for debugging */ - zlog_warn ("ospf_apiserver_ism_change"); - if (listcount (apiserver_list) > 0) { - ospf_apiserver_clients_notify_ism_change (oi); - } + /* zlog_warn for debugging */ + zlog_warn("ospf_apiserver_ism_change"); + if (listcount(apiserver_list) > 0) { + ospf_apiserver_clients_notify_ism_change(oi); + } - zlog_warn ("oi->ifp->name=%s", oi->ifp->name); - zlog_warn ("old_state=%d", old_state); - zlog_warn ("oi->state=%d", oi->state); + zlog_warn("oi->ifp->name=%s", oi->ifp->name); + zlog_warn("old_state=%d", old_state); + zlog_warn("oi->state=%d", oi->state); } -void -ospf_apiserver_nsm_change (struct ospf_neighbor *nbr, int old_status) +void ospf_apiserver_nsm_change(struct ospf_neighbor *nbr, int old_status) { - /* Neighbor status changed, tell clients about it */ - zlog_warn ("ospf_apiserver_nsm_change"); - if (listcount (apiserver_list) > 0) { - ospf_apiserver_clients_notify_nsm_change (nbr); - } + /* Neighbor status changed, tell clients about it */ + zlog_warn("ospf_apiserver_nsm_change"); + if (listcount(apiserver_list) > 0) { + ospf_apiserver_clients_notify_nsm_change(nbr); + } } -void -ospf_apiserver_show_info (struct vty *vty, struct ospf_lsa *lsa) +void ospf_apiserver_show_info(struct vty *vty, struct ospf_lsa *lsa) { - struct opaque_lsa - { - struct lsa_header header; - u_char data[1]; /* opaque data have variable length. This is start - address */ - }; - struct opaque_lsa *olsa; - int opaquelen; - - olsa = (struct opaque_lsa *) lsa->data; - - if (VALID_OPAQUE_INFO_LEN (lsa->data)) - opaquelen = ntohs (lsa->data->length) - OSPF_LSA_HEADER_SIZE; - else - opaquelen = 0; - - /* Output information about opaque LSAs */ - if (vty != NULL) - { - int i; - vty_out (vty, " Added using OSPF API: %u octets of opaque data %s\n", - opaquelen, - VALID_OPAQUE_INFO_LEN(lsa->data) ? "" : "(Invalid length?)"); - vty_out (vty, " Opaque data: "); - - for (i = 0; i < opaquelen; i++) - { - vty_out (vty, "0x%x ", olsa->data[i]); - } - vty_out (vty, "\n"); - } - else - { - int i; - zlog_debug (" Added using OSPF API: %u octets of opaque data %s", - opaquelen, - VALID_OPAQUE_INFO_LEN (lsa-> - data) ? "" : "(Invalid length?)"); - zlog_debug (" Opaque data: "); - - for (i = 0; i < opaquelen; i++) - { - zlog_debug ("0x%x ", olsa->data[i]); - } - zlog_debug ("\n"); - } - return; + struct opaque_lsa { + struct lsa_header header; + u_char data[1]; /* opaque data have variable length. This is + start + address */ + }; + struct opaque_lsa *olsa; + int opaquelen; + + olsa = (struct opaque_lsa *)lsa->data; + + if (VALID_OPAQUE_INFO_LEN(lsa->data)) + opaquelen = ntohs(lsa->data->length) - OSPF_LSA_HEADER_SIZE; + else + opaquelen = 0; + + /* Output information about opaque LSAs */ + if (vty != NULL) { + int i; + vty_out(vty, + " Added using OSPF API: %u octets of opaque data %s\n", + opaquelen, + VALID_OPAQUE_INFO_LEN(lsa->data) ? "" + : "(Invalid length?)"); + vty_out(vty, " Opaque data: "); + + for (i = 0; i < opaquelen; i++) { + vty_out(vty, "0x%x ", olsa->data[i]); + } + vty_out(vty, "\n"); + } else { + int i; + zlog_debug( + " Added using OSPF API: %u octets of opaque data %s", + opaquelen, + VALID_OPAQUE_INFO_LEN(lsa->data) ? "" + : "(Invalid length?)"); + zlog_debug(" Opaque data: "); + + for (i = 0; i < opaquelen; i++) { + zlog_debug("0x%x ", olsa->data[i]); + } + zlog_debug("\n"); + } + return; } /* ----------------------------------------------------------- @@ -2230,343 +2112,311 @@ ospf_apiserver_show_info (struct vty *vty, struct ospf_lsa *lsa) that need to be notified to all clients (such as interface changes) */ -void -ospf_apiserver_clients_notify_all (struct msg *msg) +void ospf_apiserver_clients_notify_all(struct msg *msg) { - struct listnode *node, *nnode; - struct ospf_apiserver *apiserv; + struct listnode *node, *nnode; + struct ospf_apiserver *apiserv; - /* Send message to all clients */ - for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv)) - ospf_apiserver_send_msg (apiserv, msg); + /* Send message to all clients */ + for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) + ospf_apiserver_send_msg(apiserv, msg); } /* An interface is now ready to accept opaque LSAs. Notify all clients that registered to use this opaque type */ -void -ospf_apiserver_clients_notify_ready_type9 (struct ospf_interface *oi) +void ospf_apiserver_clients_notify_ready_type9(struct ospf_interface *oi) { - struct listnode *node, *nnode; - struct msg *msg; - struct ospf_apiserver *apiserv; - - assert (oi); - if (!oi->address) - { - zlog_warn ("Interface has no address?"); - return; - } - - if (!ospf_apiserver_is_ready_type9 (oi)) - { - zlog_warn ("Interface not ready for type 9?"); - return; - } - - for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv)) - { - struct listnode *node2, *nnode2; - struct registered_opaque_type *r; - - for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r)) - { - if (r->lsa_type == OSPF_OPAQUE_LINK_LSA) - { - msg = new_msg_ready_notify (0, OSPF_OPAQUE_LINK_LSA, - r->opaque_type, - oi->address->u.prefix4); - if (!msg) - { - zlog_warn - ("ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed"); + struct listnode *node, *nnode; + struct msg *msg; + struct ospf_apiserver *apiserv; + + assert(oi); + if (!oi->address) { + zlog_warn("Interface has no address?"); + return; + } + + if (!ospf_apiserver_is_ready_type9(oi)) { + zlog_warn("Interface not ready for type 9?"); + return; + } + + for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) { + struct listnode *node2, *nnode2; + struct registered_opaque_type *r; + + for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2, + r)) { + if (r->lsa_type == OSPF_OPAQUE_LINK_LSA) { + msg = new_msg_ready_notify( + 0, OSPF_OPAQUE_LINK_LSA, r->opaque_type, + oi->address->u.prefix4); + if (!msg) { + zlog_warn( + "ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed"); #ifdef NOTYET - /* Cannot allocate new message. What should we do? */ - ospf_apiserver_free (apiserv); + /* Cannot allocate new message. What + * should we do? */ + ospf_apiserver_free(apiserv); #endif - goto out; - } + goto out; + } - ospf_apiserver_send_msg (apiserv, msg); - msg_free (msg); - } + ospf_apiserver_send_msg(apiserv, msg); + msg_free(msg); + } + } } - } out: - return; + return; } -void -ospf_apiserver_clients_notify_ready_type10 (struct ospf_area *area) +void ospf_apiserver_clients_notify_ready_type10(struct ospf_area *area) { - struct listnode *node, *nnode; - struct msg *msg; - struct ospf_apiserver *apiserv; - - assert (area); - - if (!ospf_apiserver_is_ready_type10 (area)) - { - zlog_warn ("Area not ready for type 10?"); - return; - } - - for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv)) - { - struct listnode *node2, *nnode2; - struct registered_opaque_type *r; - - for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r)) - { - if (r->lsa_type == OSPF_OPAQUE_AREA_LSA) - { - msg = new_msg_ready_notify (0, OSPF_OPAQUE_AREA_LSA, - r->opaque_type, area->area_id); - if (!msg) - { - zlog_warn - ("ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed"); + struct listnode *node, *nnode; + struct msg *msg; + struct ospf_apiserver *apiserv; + + assert(area); + + if (!ospf_apiserver_is_ready_type10(area)) { + zlog_warn("Area not ready for type 10?"); + return; + } + + for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) { + struct listnode *node2, *nnode2; + struct registered_opaque_type *r; + + for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2, + r)) { + if (r->lsa_type == OSPF_OPAQUE_AREA_LSA) { + msg = new_msg_ready_notify( + 0, OSPF_OPAQUE_AREA_LSA, r->opaque_type, + area->area_id); + if (!msg) { + zlog_warn( + "ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed"); #ifdef NOTYET - /* Cannot allocate new message. What should we do? */ - ospf_apiserver_free (apiserv); + /* Cannot allocate new message. What + * should we do? */ + ospf_apiserver_free(apiserv); #endif - goto out; - } + goto out; + } - ospf_apiserver_send_msg (apiserv, msg); - msg_free (msg); - } + ospf_apiserver_send_msg(apiserv, msg); + msg_free(msg); + } + } } - } out: - return; + return; } -void -ospf_apiserver_clients_notify_ready_type11 (struct ospf *top) +void ospf_apiserver_clients_notify_ready_type11(struct ospf *top) { - struct listnode *node, *nnode; - struct msg *msg; - struct in_addr id_null = { .s_addr = 0L }; - struct ospf_apiserver *apiserv; - - assert (top); - - if (!ospf_apiserver_is_ready_type11 (top)) - { - zlog_warn ("AS not ready for type 11?"); - return; - } - - for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv)) - { - struct listnode *node2, *nnode2; - struct registered_opaque_type *r; - - for (ALL_LIST_ELEMENTS (apiserv->opaque_types, node2, nnode2, r)) - { - if (r->lsa_type == OSPF_OPAQUE_AS_LSA) - { - msg = new_msg_ready_notify (0, OSPF_OPAQUE_AS_LSA, - r->opaque_type, id_null); - if (!msg) - { - zlog_warn - ("ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed"); + struct listnode *node, *nnode; + struct msg *msg; + struct in_addr id_null = {.s_addr = 0L}; + struct ospf_apiserver *apiserv; + + assert(top); + + if (!ospf_apiserver_is_ready_type11(top)) { + zlog_warn("AS not ready for type 11?"); + return; + } + + for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) { + struct listnode *node2, *nnode2; + struct registered_opaque_type *r; + + for (ALL_LIST_ELEMENTS(apiserv->opaque_types, node2, nnode2, + r)) { + if (r->lsa_type == OSPF_OPAQUE_AS_LSA) { + msg = new_msg_ready_notify( + 0, OSPF_OPAQUE_AS_LSA, r->opaque_type, + id_null); + if (!msg) { + zlog_warn( + "ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed"); #ifdef NOTYET - /* Cannot allocate new message. What should we do? */ - ospf_apiserver_free (apiserv); + /* Cannot allocate new message. What + * should we do? */ + ospf_apiserver_free(apiserv); #endif - goto out; - } + goto out; + } - ospf_apiserver_send_msg (apiserv, msg); - msg_free (msg); - } + ospf_apiserver_send_msg(apiserv, msg); + msg_free(msg); + } + } } - } out: - return; + return; } -void -ospf_apiserver_clients_notify_new_if (struct ospf_interface *oi) +void ospf_apiserver_clients_notify_new_if(struct ospf_interface *oi) { - struct msg *msg; - - msg = new_msg_new_if (0, oi->address->u.prefix4, oi->area->area_id); - if (msg != NULL) - { - ospf_apiserver_clients_notify_all (msg); - msg_free (msg); - } + struct msg *msg; + + msg = new_msg_new_if(0, oi->address->u.prefix4, oi->area->area_id); + if (msg != NULL) { + ospf_apiserver_clients_notify_all(msg); + msg_free(msg); + } } -void -ospf_apiserver_clients_notify_del_if (struct ospf_interface *oi) +void ospf_apiserver_clients_notify_del_if(struct ospf_interface *oi) { - struct msg *msg; - - msg = new_msg_del_if (0, oi->address->u.prefix4); - if (msg != NULL) - { - ospf_apiserver_clients_notify_all (msg); - msg_free (msg); - } + struct msg *msg; + + msg = new_msg_del_if(0, oi->address->u.prefix4); + if (msg != NULL) { + ospf_apiserver_clients_notify_all(msg); + msg_free(msg); + } } -void -ospf_apiserver_clients_notify_ism_change (struct ospf_interface *oi) +void ospf_apiserver_clients_notify_ism_change(struct ospf_interface *oi) { - struct msg *msg; - struct in_addr ifaddr = { .s_addr = 0L }; - struct in_addr area_id = { .s_addr = 0L }; - - assert (oi); - assert (oi->ifp); - - if (oi->address) - { - ifaddr = oi->address->u.prefix4; - } - if (oi->area) - { - area_id = oi->area->area_id; - } - - msg = new_msg_ism_change (0, ifaddr, area_id, oi->state); - if (!msg) - { - zlog_warn ("apiserver_clients_notify_ism_change: msg_new failed"); - return; - } - - ospf_apiserver_clients_notify_all (msg); - msg_free (msg); + struct msg *msg; + struct in_addr ifaddr = {.s_addr = 0L}; + struct in_addr area_id = {.s_addr = 0L}; + + assert(oi); + assert(oi->ifp); + + if (oi->address) { + ifaddr = oi->address->u.prefix4; + } + if (oi->area) { + area_id = oi->area->area_id; + } + + msg = new_msg_ism_change(0, ifaddr, area_id, oi->state); + if (!msg) { + zlog_warn( + "apiserver_clients_notify_ism_change: msg_new failed"); + return; + } + + ospf_apiserver_clients_notify_all(msg); + msg_free(msg); } -void -ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr) +void ospf_apiserver_clients_notify_nsm_change(struct ospf_neighbor *nbr) { - struct msg *msg; - struct in_addr ifaddr = { .s_addr = 0L }; - struct in_addr nbraddr = { .s_addr = 0L }; + struct msg *msg; + struct in_addr ifaddr = {.s_addr = 0L}; + struct in_addr nbraddr = {.s_addr = 0L}; - assert (nbr); + assert(nbr); - if (nbr->oi) - { - ifaddr = nbr->oi->address->u.prefix4; - } + if (nbr->oi) { + ifaddr = nbr->oi->address->u.prefix4; + } - nbraddr = nbr->address.u.prefix4; + nbraddr = nbr->address.u.prefix4; - msg = new_msg_nsm_change (0, ifaddr, nbraddr, nbr->router_id, nbr->state); - if (!msg) - { - zlog_warn ("apiserver_clients_notify_nsm_change: msg_new failed"); - return; - } + msg = new_msg_nsm_change(0, ifaddr, nbraddr, nbr->router_id, + nbr->state); + if (!msg) { + zlog_warn( + "apiserver_clients_notify_nsm_change: msg_new failed"); + return; + } - ospf_apiserver_clients_notify_all (msg); - msg_free (msg); + ospf_apiserver_clients_notify_all(msg); + msg_free(msg); } -static void -apiserver_clients_lsa_change_notify (u_char msgtype, struct ospf_lsa *lsa) +static void apiserver_clients_lsa_change_notify(u_char msgtype, + struct ospf_lsa *lsa) { - struct msg *msg; - struct listnode *node, *nnode; - struct ospf_apiserver *apiserv; - - /* Default area for AS-External and Opaque11 LSAs */ - struct in_addr area_id = { .s_addr = 0L }; - - /* Default interface for non Opaque9 LSAs */ - struct in_addr ifaddr = { .s_addr = 0L }; - - if (lsa->area) - { - area_id = lsa->area->area_id; - } - if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) - { - assert (lsa->oi); - ifaddr = lsa->oi->address->u.prefix4; - } - - /* Prepare message that can be sent to clients that have a matching - filter */ - msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */ - ifaddr, area_id, - lsa->flags & OSPF_LSA_SELF, lsa->data); - if (!msg) - { - zlog_warn ("apiserver_clients_lsa_change_notify: msg_new failed"); - return; - } - - /* Now send message to all clients with a matching filter */ - for (ALL_LIST_ELEMENTS (apiserver_list, node, nnode, apiserv)) - { - struct lsa_filter_type *filter; - u_int16_t mask; - u_int32_t *area; - int i; - - /* Check filter for this client. */ - filter = apiserv->filter; - - /* Check area IDs in case of non AS-E LSAs. - * If filter has areas (num_areas > 0), - * then one of the areas must match the area ID of this LSA. */ - - i = filter->num_areas; - if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA) || - (lsa->data->type == OSPF_OPAQUE_AS_LSA)) - { - i = 0; - } - - if (i > 0) - { - area = (u_int32_t *) (filter + 1); - while (i) - { - if (*area == area_id.s_addr) - { - break; + struct msg *msg; + struct listnode *node, *nnode; + struct ospf_apiserver *apiserv; + + /* Default area for AS-External and Opaque11 LSAs */ + struct in_addr area_id = {.s_addr = 0L}; + + /* Default interface for non Opaque9 LSAs */ + struct in_addr ifaddr = {.s_addr = 0L}; + + if (lsa->area) { + area_id = lsa->area->area_id; + } + if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) { + assert(lsa->oi); + ifaddr = lsa->oi->address->u.prefix4; + } + + /* Prepare message that can be sent to clients that have a matching + filter */ + msg = new_msg_lsa_change_notify(msgtype, 0L, /* no sequence number */ + ifaddr, area_id, + lsa->flags & OSPF_LSA_SELF, lsa->data); + if (!msg) { + zlog_warn( + "apiserver_clients_lsa_change_notify: msg_new failed"); + return; + } + + /* Now send message to all clients with a matching filter */ + for (ALL_LIST_ELEMENTS(apiserver_list, node, nnode, apiserv)) { + struct lsa_filter_type *filter; + u_int16_t mask; + u_int32_t *area; + int i; + + /* Check filter for this client. */ + filter = apiserv->filter; + + /* Check area IDs in case of non AS-E LSAs. + * If filter has areas (num_areas > 0), + * then one of the areas must match the area ID of this LSA. */ + + i = filter->num_areas; + if ((lsa->data->type == OSPF_AS_EXTERNAL_LSA) + || (lsa->data->type == OSPF_OPAQUE_AS_LSA)) { + i = 0; } - i--; - area++; - } - } - else - { - i = 1; - } - - if (i > 0) - { - /* Area match. Check LSA type. */ - mask = ntohs (filter->typemask); - - if (mask & Power2[lsa->data->type]) - { - /* Type also matches. Check origin. */ - if ((filter->origin == ANY_ORIGIN) || - (filter->origin == IS_LSA_SELF (lsa))) - { - ospf_apiserver_send_msg (apiserv, msg); + + if (i > 0) { + area = (u_int32_t *)(filter + 1); + while (i) { + if (*area == area_id.s_addr) { + break; + } + i--; + area++; + } + } else { + i = 1; + } + + if (i > 0) { + /* Area match. Check LSA type. */ + mask = ntohs(filter->typemask); + + if (mask & Power2[lsa->data->type]) { + /* Type also matches. Check origin. */ + if ((filter->origin == ANY_ORIGIN) + || (filter->origin == IS_LSA_SELF(lsa))) { + ospf_apiserver_send_msg(apiserv, msg); + } + } } - } } - } - /* Free message since it is not used anymore */ - msg_free (msg); + /* Free message since it is not used anymore */ + msg_free(msg); } @@ -2576,60 +2426,53 @@ apiserver_clients_lsa_change_notify (u_char msgtype, struct ospf_lsa *lsa) */ -static int -apiserver_notify_clients_lsa (u_char msgtype, struct ospf_lsa *lsa) +static int apiserver_notify_clients_lsa(u_char msgtype, struct ospf_lsa *lsa) { - struct msg *msg; - /* default area for AS-External and Opaque11 LSAs */ - struct in_addr area_id = { .s_addr = 0L }; - - /* default interface for non Opaque9 LSAs */ - struct in_addr ifaddr = { .s_addr = 0L }; - - /* Only notify this update if the LSA's age is smaller than - MAXAGE. Otherwise clients would see LSA updates with max age just - before they are deleted from the LSDB. LSA delete messages have - MAXAGE too but should not be filtered. */ - if (IS_LSA_MAXAGE(lsa) && (msgtype == MSG_LSA_UPDATE_NOTIFY)) { - return 0; - } - - if (lsa->area) - { - area_id = lsa->area->area_id; - } - if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) - { - ifaddr = lsa->oi->address->u.prefix4; - } - msg = new_msg_lsa_change_notify (msgtype, 0L, /* no sequence number */ - ifaddr, area_id, - lsa->flags & OSPF_LSA_SELF, lsa->data); - if (!msg) - { - zlog_warn ("notify_clients_lsa: msg_new failed"); - return -1; - } - /* Notify all clients that new LSA is added/updated */ - apiserver_clients_lsa_change_notify (msgtype, lsa); - - /* Clients made their own copies of msg so we can free msg here */ - msg_free (msg); - - return 0; + struct msg *msg; + /* default area for AS-External and Opaque11 LSAs */ + struct in_addr area_id = {.s_addr = 0L}; + + /* default interface for non Opaque9 LSAs */ + struct in_addr ifaddr = {.s_addr = 0L}; + + /* Only notify this update if the LSA's age is smaller than + MAXAGE. Otherwise clients would see LSA updates with max age just + before they are deleted from the LSDB. LSA delete messages have + MAXAGE too but should not be filtered. */ + if (IS_LSA_MAXAGE(lsa) && (msgtype == MSG_LSA_UPDATE_NOTIFY)) { + return 0; + } + + if (lsa->area) { + area_id = lsa->area->area_id; + } + if (lsa->data->type == OSPF_OPAQUE_LINK_LSA) { + ifaddr = lsa->oi->address->u.prefix4; + } + msg = new_msg_lsa_change_notify(msgtype, 0L, /* no sequence number */ + ifaddr, area_id, + lsa->flags & OSPF_LSA_SELF, lsa->data); + if (!msg) { + zlog_warn("notify_clients_lsa: msg_new failed"); + return -1; + } + /* Notify all clients that new LSA is added/updated */ + apiserver_clients_lsa_change_notify(msgtype, lsa); + + /* Clients made their own copies of msg so we can free msg here */ + msg_free(msg); + + return 0; } -int -ospf_apiserver_lsa_update (struct ospf_lsa *lsa) +int ospf_apiserver_lsa_update(struct ospf_lsa *lsa) { - return apiserver_notify_clients_lsa (MSG_LSA_UPDATE_NOTIFY, lsa); + return apiserver_notify_clients_lsa(MSG_LSA_UPDATE_NOTIFY, lsa); } -int -ospf_apiserver_lsa_delete (struct ospf_lsa *lsa) +int ospf_apiserver_lsa_delete(struct ospf_lsa *lsa) { - return apiserver_notify_clients_lsa (MSG_LSA_DELETE_NOTIFY, lsa); + return apiserver_notify_clients_lsa(MSG_LSA_DELETE_NOTIFY, lsa); } #endif /* SUPPORT_OSPF_API */ - diff --git a/ospfd/ospf_apiserver.h b/ospfd/ospf_apiserver.h index 2fd8e7a37..59d18bfd6 100644 --- a/ospfd/ospf_apiserver.h +++ b/ospfd/ospf_apiserver.h @@ -27,58 +27,55 @@ #define MTYPE_OSPF_APISERVER_MSGFILTER MTYPE_TMP /* List of opaque types that application registered */ -struct registered_opaque_type -{ - u_char lsa_type; - u_char opaque_type; +struct registered_opaque_type { + u_char lsa_type; + u_char opaque_type; }; /* Server instance for each accepted client connection. */ -struct ospf_apiserver -{ - /* Socket connections for synchronous commands and asynchronous - notifications */ - int fd_sync; /* synchronous requests */ - struct sockaddr_in peer_sync; - - int fd_async; /* asynchronous notifications */ - struct sockaddr_in peer_async; - - /* List of all opaque types that application registers to use. Using - a single connection with the OSPF daemon, multiple - pairs can be registered. However, each - combination can only be registered once by all applications. */ - struct list *opaque_types; /* of type registered_opaque_type */ - - /* Temporary storage for LSA instances to be refreshed. */ - struct ospf_lsdb reserve; - - /* filter for LSA update/delete notifies */ - struct lsa_filter_type *filter; - - /* Fifo buffers for outgoing messages */ - struct msg_fifo *out_sync_fifo; - struct msg_fifo *out_async_fifo; - - /* Read and write threads */ - struct thread *t_sync_read; +struct ospf_apiserver { + /* Socket connections for synchronous commands and asynchronous + notifications */ + int fd_sync; /* synchronous requests */ + struct sockaddr_in peer_sync; + + int fd_async; /* asynchronous notifications */ + struct sockaddr_in peer_async; + + /* List of all opaque types that application registers to use. Using + a single connection with the OSPF daemon, multiple + pairs can be registered. However, each + combination can only be registered once by all applications. */ + struct list *opaque_types; /* of type registered_opaque_type */ + + /* Temporary storage for LSA instances to be refreshed. */ + struct ospf_lsdb reserve; + + /* filter for LSA update/delete notifies */ + struct lsa_filter_type *filter; + + /* Fifo buffers for outgoing messages */ + struct msg_fifo *out_sync_fifo; + struct msg_fifo *out_async_fifo; + + /* Read and write threads */ + struct thread *t_sync_read; #ifdef USE_ASYNC_READ - struct thread *t_async_read; + struct thread *t_async_read; #endif /* USE_ASYNC_READ */ - struct thread *t_sync_write; - struct thread *t_async_write; + struct thread *t_sync_write; + struct thread *t_async_write; }; -enum event -{ - OSPF_APISERVER_ACCEPT, - OSPF_APISERVER_SYNC_READ, +enum event { + OSPF_APISERVER_ACCEPT, + OSPF_APISERVER_SYNC_READ, #ifdef USE_ASYNC_READ - OSPF_APISERVER_ASYNC_READ, + OSPF_APISERVER_ASYNC_READ, #endif /* USE_ASYNC_READ */ - OSPF_APISERVER_SYNC_WRITE, - OSPF_APISERVER_ASYNC_WRITE + OSPF_APISERVER_SYNC_WRITE, + OSPF_APISERVER_ASYNC_WRITE }; /* ----------------------------------------------------------- @@ -86,63 +83,67 @@ enum event * ----------------------------------------------------------- */ -extern unsigned short ospf_apiserver_getport (void); -extern int ospf_apiserver_init (void); -extern void ospf_apiserver_term (void); -extern struct ospf_apiserver *ospf_apiserver_new (int fd_sync, int fd_async); -extern void ospf_apiserver_free (struct ospf_apiserver *apiserv); -extern void ospf_apiserver_event (enum event event, int fd, - struct ospf_apiserver *apiserv); -extern int ospf_apiserver_serv_sock_family (unsigned short port, int family); -extern int ospf_apiserver_accept (struct thread *thread); -extern int ospf_apiserver_read (struct thread *thread); -extern int ospf_apiserver_sync_write (struct thread *thread); -extern int ospf_apiserver_async_write (struct thread *thread); -extern int ospf_apiserver_send_reply (struct ospf_apiserver *apiserv, - u_int32_t seqnr, u_char rc); +extern unsigned short ospf_apiserver_getport(void); +extern int ospf_apiserver_init(void); +extern void ospf_apiserver_term(void); +extern struct ospf_apiserver *ospf_apiserver_new(int fd_sync, int fd_async); +extern void ospf_apiserver_free(struct ospf_apiserver *apiserv); +extern void ospf_apiserver_event(enum event event, int fd, + struct ospf_apiserver *apiserv); +extern int ospf_apiserver_serv_sock_family(unsigned short port, int family); +extern int ospf_apiserver_accept(struct thread *thread); +extern int ospf_apiserver_read(struct thread *thread); +extern int ospf_apiserver_sync_write(struct thread *thread); +extern int ospf_apiserver_async_write(struct thread *thread); +extern int ospf_apiserver_send_reply(struct ospf_apiserver *apiserv, + u_int32_t seqnr, u_char rc); /* ----------------------------------------------------------- * Followings are message handler functions * ----------------------------------------------------------- */ -extern int ospf_apiserver_lsa9_originator (void *arg); -extern int ospf_apiserver_lsa10_originator (void *arg); -extern int ospf_apiserver_lsa11_originator (void *arg); - -extern void ospf_apiserver_clients_notify_all (struct msg *msg); - -extern void ospf_apiserver_clients_notify_ready_type9 (struct ospf_interface *oi); -extern void ospf_apiserver_clients_notify_ready_type10 (struct ospf_area *area); -extern void ospf_apiserver_clients_notify_ready_type11 (struct ospf *top); - -extern void ospf_apiserver_clients_notify_new_if (struct ospf_interface *oi); -extern void ospf_apiserver_clients_notify_del_if (struct ospf_interface *oi); -extern void ospf_apiserver_clients_notify_ism_change (struct ospf_interface *oi); -extern void ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr); - -extern int ospf_apiserver_is_ready_type9 (struct ospf_interface *oi); -extern int ospf_apiserver_is_ready_type10 (struct ospf_area *area); -extern int ospf_apiserver_is_ready_type11 (struct ospf *ospf); - -extern void ospf_apiserver_notify_ready_type9 (struct ospf_apiserver *apiserv); -extern void ospf_apiserver_notify_ready_type10 (struct ospf_apiserver *apiserv); -extern void ospf_apiserver_notify_ready_type11 (struct ospf_apiserver *apiserv); - -extern int ospf_apiserver_handle_msg (struct ospf_apiserver *apiserv, - struct msg *msg); -extern int ospf_apiserver_handle_register_opaque_type (struct ospf_apiserver - *apiserv, struct msg *msg); -extern int ospf_apiserver_handle_unregister_opaque_type (struct ospf_apiserver - *apiserv, struct msg *msg); -extern int ospf_apiserver_handle_register_event (struct ospf_apiserver *apiserv, - struct msg *msg); -extern int ospf_apiserver_handle_originate_request (struct ospf_apiserver *apiserv, - struct msg *msg); -extern int ospf_apiserver_handle_delete_request (struct ospf_apiserver *apiserv, - struct msg *msg); -extern int ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver *apiserv, +extern int ospf_apiserver_lsa9_originator(void *arg); +extern int ospf_apiserver_lsa10_originator(void *arg); +extern int ospf_apiserver_lsa11_originator(void *arg); + +extern void ospf_apiserver_clients_notify_all(struct msg *msg); + +extern void +ospf_apiserver_clients_notify_ready_type9(struct ospf_interface *oi); +extern void ospf_apiserver_clients_notify_ready_type10(struct ospf_area *area); +extern void ospf_apiserver_clients_notify_ready_type11(struct ospf *top); + +extern void ospf_apiserver_clients_notify_new_if(struct ospf_interface *oi); +extern void ospf_apiserver_clients_notify_del_if(struct ospf_interface *oi); +extern void ospf_apiserver_clients_notify_ism_change(struct ospf_interface *oi); +extern void ospf_apiserver_clients_notify_nsm_change(struct ospf_neighbor *nbr); + +extern int ospf_apiserver_is_ready_type9(struct ospf_interface *oi); +extern int ospf_apiserver_is_ready_type10(struct ospf_area *area); +extern int ospf_apiserver_is_ready_type11(struct ospf *ospf); + +extern void ospf_apiserver_notify_ready_type9(struct ospf_apiserver *apiserv); +extern void ospf_apiserver_notify_ready_type10(struct ospf_apiserver *apiserv); +extern void ospf_apiserver_notify_ready_type11(struct ospf_apiserver *apiserv); + +extern int ospf_apiserver_handle_msg(struct ospf_apiserver *apiserv, struct msg *msg); +extern int +ospf_apiserver_handle_register_opaque_type(struct ospf_apiserver *apiserv, + struct msg *msg); +extern int +ospf_apiserver_handle_unregister_opaque_type(struct ospf_apiserver *apiserv, + struct msg *msg); +extern int ospf_apiserver_handle_register_event(struct ospf_apiserver *apiserv, + struct msg *msg); +extern int +ospf_apiserver_handle_originate_request(struct ospf_apiserver *apiserv, + struct msg *msg); +extern int ospf_apiserver_handle_delete_request(struct ospf_apiserver *apiserv, + struct msg *msg); +extern int ospf_apiserver_handle_sync_lsdb(struct ospf_apiserver *apiserv, + struct msg *msg); /* ----------------------------------------------------------- @@ -150,38 +151,43 @@ extern int ospf_apiserver_handle_sync_lsdb (struct ospf_apiserver *apiserv, * ----------------------------------------------------------- */ -extern int ospf_apiserver_register_opaque_type (struct ospf_apiserver *apiserver, - u_char lsa_type, u_char opaque_type); -extern int ospf_apiserver_unregister_opaque_type (struct ospf_apiserver *apiserver, - u_char lsa_type, - u_char opaque_type); -extern struct ospf_lsa *ospf_apiserver_opaque_lsa_new (struct ospf_area *area, - struct ospf_interface *oi, - struct lsa_header *protolsa); -extern struct ospf_interface *ospf_apiserver_if_lookup_by_addr (struct in_addr - address); -extern struct ospf_interface *ospf_apiserver_if_lookup_by_ifp (struct interface - *ifp); -extern int ospf_apiserver_originate1 (struct ospf_lsa *lsa); -extern void ospf_apiserver_flood_opaque_lsa (struct ospf_lsa *lsa); +extern int ospf_apiserver_register_opaque_type(struct ospf_apiserver *apiserver, + u_char lsa_type, + u_char opaque_type); +extern int +ospf_apiserver_unregister_opaque_type(struct ospf_apiserver *apiserver, + u_char lsa_type, u_char opaque_type); +extern struct ospf_lsa * +ospf_apiserver_opaque_lsa_new(struct ospf_area *area, struct ospf_interface *oi, + struct lsa_header *protolsa); +extern struct ospf_interface * +ospf_apiserver_if_lookup_by_addr(struct in_addr address); +extern struct ospf_interface * +ospf_apiserver_if_lookup_by_ifp(struct interface *ifp); +extern int ospf_apiserver_originate1(struct ospf_lsa *lsa); +extern void ospf_apiserver_flood_opaque_lsa(struct ospf_lsa *lsa); /* ----------------------------------------------------------- - * Followings are callback functions to handle opaque types + * Followings are callback functions to handle opaque types * ----------------------------------------------------------- */ -extern int ospf_apiserver_new_if (struct interface *ifp); -extern int ospf_apiserver_del_if (struct interface *ifp); -extern void ospf_apiserver_ism_change (struct ospf_interface *oi, int old_status); -extern void ospf_apiserver_nsm_change (struct ospf_neighbor *nbr, int old_status); -extern void ospf_apiserver_config_write_router (struct vty *vty); -extern void ospf_apiserver_config_write_if (struct vty *vty, struct interface *ifp); -extern void ospf_apiserver_show_info (struct vty *vty, struct ospf_lsa *lsa); -extern int ospf_ospf_apiserver_lsa_originator (void *arg); -extern struct ospf_lsa *ospf_apiserver_lsa_refresher (struct ospf_lsa *lsa); -extern void ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver *apiserv, - u_char lsa_type, u_char opaque_type); +extern int ospf_apiserver_new_if(struct interface *ifp); +extern int ospf_apiserver_del_if(struct interface *ifp); +extern void ospf_apiserver_ism_change(struct ospf_interface *oi, + int old_status); +extern void ospf_apiserver_nsm_change(struct ospf_neighbor *nbr, + int old_status); +extern void ospf_apiserver_config_write_router(struct vty *vty); +extern void ospf_apiserver_config_write_if(struct vty *vty, + struct interface *ifp); +extern void ospf_apiserver_show_info(struct vty *vty, struct ospf_lsa *lsa); +extern int ospf_ospf_apiserver_lsa_originator(void *arg); +extern struct ospf_lsa *ospf_apiserver_lsa_refresher(struct ospf_lsa *lsa); +extern void ospf_apiserver_flush_opaque_lsa(struct ospf_apiserver *apiserv, + u_char lsa_type, + u_char opaque_type); /* ----------------------------------------------------------- * Followings are hooks when LSAs are updated or deleted @@ -191,10 +197,10 @@ extern void ospf_apiserver_flush_opaque_lsa (struct ospf_apiserver *apiserv, /* Hooks that are invoked from ospf opaque module */ -extern int ospf_apiserver_lsa_update (struct ospf_lsa *lsa); -extern int ospf_apiserver_lsa_delete (struct ospf_lsa *lsa); +extern int ospf_apiserver_lsa_update(struct ospf_lsa *lsa); +extern int ospf_apiserver_lsa_delete(struct ospf_lsa *lsa); -extern void ospf_apiserver_clients_lsa_change_notify (u_char msgtype, - struct ospf_lsa *lsa); +extern void ospf_apiserver_clients_lsa_change_notify(u_char msgtype, + struct ospf_lsa *lsa); #endif /* _OSPF_APISERVER_H */ diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c index 2ba3b5533..e3b66d597 100644 --- a/ospfd/ospf_asbr.c +++ b/ospfd/ospf_asbr.c @@ -45,280 +45,268 @@ /* Remove external route. */ -void -ospf_external_route_remove (struct ospf *ospf, struct prefix_ipv4 *p) +void ospf_external_route_remove(struct ospf *ospf, struct prefix_ipv4 *p) { - struct route_node *rn; - struct ospf_route *or; - - rn = route_node_lookup (ospf->old_external_route, (struct prefix *) p); - if (rn) - if ((or = rn->info)) - { - zlog_info ("Route[%s/%d]: external path deleted", - inet_ntoa (p->prefix), p->prefixlen); - - /* Remove route from zebra. */ - if (or->type == OSPF_DESTINATION_NETWORK) - ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, or); - - ospf_route_free (or); - rn->info = NULL; - - route_unlock_node (rn); - route_unlock_node (rn); - return; - } - - zlog_info ("Route[%s/%d]: no such external path", - inet_ntoa (p->prefix), p->prefixlen); + struct route_node *rn; + struct ospf_route * or ; + + rn = route_node_lookup(ospf->old_external_route, (struct prefix *)p); + if (rn) + if ((or = rn->info)) { + zlog_info("Route[%s/%d]: external path deleted", + inet_ntoa(p->prefix), p->prefixlen); + + /* Remove route from zebra. */ + if (or->type == OSPF_DESTINATION_NETWORK) + ospf_zebra_delete((struct prefix_ipv4 *)&rn->p, + or); + + ospf_route_free(or); + rn->info = NULL; + + route_unlock_node(rn); + route_unlock_node(rn); + return; + } + + zlog_info("Route[%s/%d]: no such external path", inet_ntoa(p->prefix), + p->prefixlen); } /* Lookup external route. */ -struct ospf_route * -ospf_external_route_lookup (struct ospf *ospf, - struct prefix_ipv4 *p) +struct ospf_route *ospf_external_route_lookup(struct ospf *ospf, + struct prefix_ipv4 *p) { - struct route_node *rn; + struct route_node *rn; - rn = route_node_lookup (ospf->old_external_route, (struct prefix *) p); - if (rn) - { - route_unlock_node (rn); - if (rn->info) - return rn->info; - } + rn = route_node_lookup(ospf->old_external_route, (struct prefix *)p); + if (rn) { + route_unlock_node(rn); + if (rn->info) + return rn->info; + } - zlog_warn ("Route[%s/%d]: lookup, no such prefix", - inet_ntoa (p->prefix), p->prefixlen); + zlog_warn("Route[%s/%d]: lookup, no such prefix", inet_ntoa(p->prefix), + p->prefixlen); - return NULL; + return NULL; } /* Add an External info for AS-external-LSA. */ -struct external_info * -ospf_external_info_new (u_char type, u_short instance) +struct external_info *ospf_external_info_new(u_char type, u_short instance) { - struct external_info *new; + struct external_info *new; - new = (struct external_info *) - XCALLOC (MTYPE_OSPF_EXTERNAL_INFO, sizeof (struct external_info)); - new->type = type; - new->instance = instance; + new = (struct external_info *)XCALLOC(MTYPE_OSPF_EXTERNAL_INFO, + sizeof(struct external_info)); + new->type = type; + new->instance = instance; - ospf_reset_route_map_set_values (&new->route_map_set); - return new; + ospf_reset_route_map_set_values(&new->route_map_set); + return new; } -static void -ospf_external_info_free (struct external_info *ei) +static void ospf_external_info_free(struct external_info *ei) { - XFREE (MTYPE_OSPF_EXTERNAL_INFO, ei); + XFREE(MTYPE_OSPF_EXTERNAL_INFO, ei); } -void -ospf_reset_route_map_set_values (struct route_map_set_values *values) +void ospf_reset_route_map_set_values(struct route_map_set_values *values) { - values->metric = -1; - values->metric_type = -1; + values->metric = -1; + values->metric_type = -1; } -int -ospf_route_map_set_compare (struct route_map_set_values *values1, - struct route_map_set_values *values2) +int ospf_route_map_set_compare(struct route_map_set_values *values1, + struct route_map_set_values *values2) { - return values1->metric == values2->metric && - values1->metric_type == values2->metric_type; + return values1->metric == values2->metric + && values1->metric_type == values2->metric_type; } /* Add an External info for AS-external-LSA. */ -struct external_info * -ospf_external_info_add (u_char type, u_short instance, struct prefix_ipv4 p, - ifindex_t ifindex, struct in_addr nexthop, - route_tag_t tag) +struct external_info *ospf_external_info_add(u_char type, u_short instance, + struct prefix_ipv4 p, + ifindex_t ifindex, + struct in_addr nexthop, + route_tag_t tag) { - struct external_info *new; - struct route_node *rn; - struct ospf_external *ext; - char inetbuf[INET6_BUFSIZ]; - - ext = ospf_external_lookup(type, instance); - if (!ext) - ext = ospf_external_add(type, instance); - - rn = route_node_get (EXTERNAL_INFO (ext), (struct prefix *) &p); - /* If old info exists, -- discard new one or overwrite with new one? */ - if (rn) - if (rn->info) - { - new = rn->info; - if ((new->ifindex == ifindex) && - (new->nexthop.s_addr == nexthop.s_addr) && (new->tag == tag)) - { - route_unlock_node(rn); - return NULL; /* NULL => no LSA to refresh */ - } - - inet_ntop(AF_INET, (void *)&nexthop.s_addr, inetbuf, INET6_BUFSIZ); - zlog_warn ("Redistribute[%s][%d]: %s/%d discarding old info with NH %s.", - ospf_redist_string(type), instance, - inet_ntoa (p.prefix), p.prefixlen, inetbuf); - XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info); - rn->info = NULL; - } - - /* Create new External info instance. */ - new = ospf_external_info_new (type, instance); - new->p = p; - new->ifindex = ifindex; - new->nexthop = nexthop; - new->tag = tag; - - /* we don't unlock rn from the get() because we're attaching the info */ - if (rn) - rn->info = new; - - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - { - inet_ntop(AF_INET, (void *)&nexthop.s_addr, inetbuf, INET6_BUFSIZ); - zlog_debug ("Redistribute[%s]: %s/%d external info created, with NH %s", - ospf_redist_string(type), - inet_ntoa (p.prefix), p.prefixlen, inetbuf); - } - return new; + struct external_info *new; + struct route_node *rn; + struct ospf_external *ext; + char inetbuf[INET6_BUFSIZ]; + + ext = ospf_external_lookup(type, instance); + if (!ext) + ext = ospf_external_add(type, instance); + + rn = route_node_get(EXTERNAL_INFO(ext), (struct prefix *)&p); + /* If old info exists, -- discard new one or overwrite with new one? */ + if (rn) + if (rn->info) { + new = rn->info; + if ((new->ifindex == ifindex) + && (new->nexthop.s_addr == nexthop.s_addr) + && (new->tag == tag)) { + route_unlock_node(rn); + return NULL; /* NULL => no LSA to refresh */ + } + + inet_ntop(AF_INET, (void *)&nexthop.s_addr, inetbuf, + INET6_BUFSIZ); + zlog_warn( + "Redistribute[%s][%d]: %s/%d discarding old info with NH %s.", + ospf_redist_string(type), instance, + inet_ntoa(p.prefix), p.prefixlen, inetbuf); + XFREE(MTYPE_OSPF_EXTERNAL_INFO, rn->info); + rn->info = NULL; + } + + /* Create new External info instance. */ + new = ospf_external_info_new(type, instance); + new->p = p; + new->ifindex = ifindex; + new->nexthop = nexthop; + new->tag = tag; + + /* we don't unlock rn from the get() because we're attaching the info */ + if (rn) + rn->info = new; + + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + inet_ntop(AF_INET, (void *)&nexthop.s_addr, inetbuf, + INET6_BUFSIZ); + zlog_debug( + "Redistribute[%s]: %s/%d external info created, with NH %s", + ospf_redist_string(type), inet_ntoa(p.prefix), + p.prefixlen, inetbuf); + } + return new; } -void -ospf_external_info_delete (u_char type, u_short instance, struct prefix_ipv4 p) +void ospf_external_info_delete(u_char type, u_short instance, + struct prefix_ipv4 p) { - struct route_node *rn; - struct ospf_external *ext; - - ext = ospf_external_lookup(type, instance); - if (!ext) - return; - - rn = route_node_lookup (EXTERNAL_INFO (ext), (struct prefix *) &p); - if (rn) - { - ospf_external_info_free (rn->info); - rn->info = NULL; - route_unlock_node (rn); - route_unlock_node (rn); - } + struct route_node *rn; + struct ospf_external *ext; + + ext = ospf_external_lookup(type, instance); + if (!ext) + return; + + rn = route_node_lookup(EXTERNAL_INFO(ext), (struct prefix *)&p); + if (rn) { + ospf_external_info_free(rn->info); + rn->info = NULL; + route_unlock_node(rn); + route_unlock_node(rn); + } } -struct external_info * -ospf_external_info_lookup (u_char type, u_short instance, struct prefix_ipv4 *p) +struct external_info *ospf_external_info_lookup(u_char type, u_short instance, + struct prefix_ipv4 *p) { - struct route_node *rn; - struct ospf_external *ext; - - ext = ospf_external_lookup(type, instance); - if (!ext) - return NULL; - - rn = route_node_lookup (EXTERNAL_INFO (ext), (struct prefix *) p); - if (rn) - { - route_unlock_node (rn); - if (rn->info) - return rn->info; - } - - return NULL; + struct route_node *rn; + struct ospf_external *ext; + + ext = ospf_external_lookup(type, instance); + if (!ext) + return NULL; + + rn = route_node_lookup(EXTERNAL_INFO(ext), (struct prefix *)p); + if (rn) { + route_unlock_node(rn); + if (rn->info) + return rn->info; + } + + return NULL; } -struct ospf_lsa * -ospf_external_info_find_lsa (struct ospf *ospf, - struct prefix_ipv4 *p) +struct ospf_lsa *ospf_external_info_find_lsa(struct ospf *ospf, + struct prefix_ipv4 *p) { - struct ospf_lsa *lsa; - struct as_external_lsa *al; - struct in_addr mask, id; + struct ospf_lsa *lsa; + struct as_external_lsa *al; + struct in_addr mask, id; - lsa = ospf_lsdb_lookup_by_id (ospf->lsdb, OSPF_AS_EXTERNAL_LSA, - p->prefix, ospf->router_id); + lsa = ospf_lsdb_lookup_by_id(ospf->lsdb, OSPF_AS_EXTERNAL_LSA, + p->prefix, ospf->router_id); - if (!lsa) - return NULL; + if (!lsa) + return NULL; - al = (struct as_external_lsa *) lsa->data; + al = (struct as_external_lsa *)lsa->data; - masklen2ip (p->prefixlen, &mask); + masklen2ip(p->prefixlen, &mask); - if (mask.s_addr != al->mask.s_addr) - { - id.s_addr = p->prefix.s_addr | (~mask.s_addr); - lsa = ospf_lsdb_lookup_by_id (ospf->lsdb, OSPF_AS_EXTERNAL_LSA, - id, ospf->router_id); - if (!lsa) - return NULL; - } + if (mask.s_addr != al->mask.s_addr) { + id.s_addr = p->prefix.s_addr | (~mask.s_addr); + lsa = ospf_lsdb_lookup_by_id(ospf->lsdb, OSPF_AS_EXTERNAL_LSA, + id, ospf->router_id); + if (!lsa) + return NULL; + } - return lsa; + return lsa; } /* Update ASBR status. */ -void -ospf_asbr_status_update (struct ospf *ospf, u_char status) +void ospf_asbr_status_update(struct ospf *ospf, u_char status) { - zlog_info ("ASBR[Status:%d]: Update", status); - - /* ASBR on. */ - if (status) - { - /* Already ASBR. */ - if (IS_OSPF_ASBR (ospf)) - { - zlog_info ("ASBR[Status:%d]: Already ASBR", status); - return; - } - SET_FLAG (ospf->flags, OSPF_FLAG_ASBR); - } - else - { - /* Already non ASBR. */ - if (! IS_OSPF_ASBR (ospf)) - { - zlog_info ("ASBR[Status:%d]: Already non ASBR", status); - return; + zlog_info("ASBR[Status:%d]: Update", status); + + /* ASBR on. */ + if (status) { + /* Already ASBR. */ + if (IS_OSPF_ASBR(ospf)) { + zlog_info("ASBR[Status:%d]: Already ASBR", status); + return; + } + SET_FLAG(ospf->flags, OSPF_FLAG_ASBR); + } else { + /* Already non ASBR. */ + if (!IS_OSPF_ASBR(ospf)) { + zlog_info("ASBR[Status:%d]: Already non ASBR", status); + return; + } + UNSET_FLAG(ospf->flags, OSPF_FLAG_ASBR); } - UNSET_FLAG (ospf->flags, OSPF_FLAG_ASBR); - } - /* Transition from/to status ASBR, schedule timer. */ - ospf_spf_calculate_schedule (ospf, SPF_FLAG_ASBR_STATUS_CHANGE); - ospf_router_lsa_update (ospf); + /* Transition from/to status ASBR, schedule timer. */ + ospf_spf_calculate_schedule(ospf, SPF_FLAG_ASBR_STATUS_CHANGE); + ospf_router_lsa_update(ospf); } -void -ospf_redistribute_withdraw (struct ospf *ospf, u_char type, u_short instance) +void ospf_redistribute_withdraw(struct ospf *ospf, u_char type, + u_short instance) { - struct route_node *rn; - struct external_info *ei; - struct ospf_external *ext; - - ext = ospf_external_lookup(type, instance); - if (!ext) - return; - - /* Delete external info for specified type. */ - if (EXTERNAL_INFO (ext)) - for (rn = route_top (EXTERNAL_INFO (ext)); rn; rn = route_next (rn)) - if ((ei = rn->info)) - if (ospf_external_info_find_lsa (ospf, &ei->p)) - { - if (is_prefix_default (&ei->p) && - ospf->default_originate != DEFAULT_ORIGINATE_NONE) - continue; - ospf_external_lsa_flush (ospf, type, &ei->p, - ei->ifindex /*, ei->nexthop */); - - ospf_external_info_free (ei); - route_unlock_node (rn); - rn->info = NULL; - } + struct route_node *rn; + struct external_info *ei; + struct ospf_external *ext; + + ext = ospf_external_lookup(type, instance); + if (!ext) + return; + + /* Delete external info for specified type. */ + if (EXTERNAL_INFO(ext)) + for (rn = route_top(EXTERNAL_INFO(ext)); rn; + rn = route_next(rn)) + if ((ei = rn->info)) + if (ospf_external_info_find_lsa(ospf, &ei->p)) { + if (is_prefix_default(&ei->p) + && ospf->default_originate + != DEFAULT_ORIGINATE_NONE) + continue; + ospf_external_lsa_flush( + ospf, type, &ei->p, + ei->ifindex /*, ei->nexthop */); + + ospf_external_info_free(ei); + route_unlock_node(rn); + rn->info = NULL; + } } diff --git a/ospfd/ospf_asbr.h b/ospfd/ospf_asbr.h index 2fd570d1b..3d7f14e7f 100644 --- a/ospfd/ospf_asbr.h +++ b/ospfd/ospf_asbr.h @@ -22,61 +22,58 @@ #ifndef _ZEBRA_OSPF_ASBR_H #define _ZEBRA_OSPF_ASBR_H -struct route_map_set_values -{ - int32_t metric; - int32_t metric_type; +struct route_map_set_values { + int32_t metric; + int32_t metric_type; }; /* Redistributed external information. */ -struct external_info -{ - /* Type of source protocol. */ - u_char type; +struct external_info { + /* Type of source protocol. */ + u_char type; - u_short instance; + u_short instance; - /* Prefix. */ - struct prefix_ipv4 p; + /* Prefix. */ + struct prefix_ipv4 p; - /* Interface index. */ - ifindex_t ifindex; + /* Interface index. */ + ifindex_t ifindex; - /* Nexthop address. */ - struct in_addr nexthop; + /* Nexthop address. */ + struct in_addr nexthop; - /* Additional Route tag. */ - route_tag_t tag; + /* Additional Route tag. */ + route_tag_t tag; - struct route_map_set_values route_map_set; + struct route_map_set_values route_map_set; #define ROUTEMAP_METRIC(E) (E)->route_map_set.metric #define ROUTEMAP_METRIC_TYPE(E) (E)->route_map_set.metric_type }; #define OSPF_ASBR_CHECK_DELAY 30 -extern void ospf_external_route_remove (struct ospf *, struct prefix_ipv4 *); -extern struct external_info *ospf_external_info_new (u_char, u_short); -extern void ospf_reset_route_map_set_values (struct route_map_set_values *); -extern int ospf_route_map_set_compare (struct route_map_set_values *, - struct route_map_set_values *); -extern struct external_info *ospf_external_info_add (u_char, u_short, - struct prefix_ipv4, - ifindex_t, - struct in_addr, - route_tag_t); -extern void ospf_external_info_delete (u_char, u_short, struct prefix_ipv4); -extern struct external_info *ospf_external_info_lookup (u_char, u_short, - struct prefix_ipv4 *); -extern struct ospf_route *ospf_external_route_lookup (struct ospf *, - struct prefix_ipv4 *); -extern void ospf_asbr_status_update (struct ospf *, u_char); +extern void ospf_external_route_remove(struct ospf *, struct prefix_ipv4 *); +extern struct external_info *ospf_external_info_new(u_char, u_short); +extern void ospf_reset_route_map_set_values(struct route_map_set_values *); +extern int ospf_route_map_set_compare(struct route_map_set_values *, + struct route_map_set_values *); +extern struct external_info *ospf_external_info_add(u_char, u_short, + struct prefix_ipv4, + ifindex_t, struct in_addr, + route_tag_t); +extern void ospf_external_info_delete(u_char, u_short, struct prefix_ipv4); +extern struct external_info *ospf_external_info_lookup(u_char, u_short, + struct prefix_ipv4 *); +extern struct ospf_route *ospf_external_route_lookup(struct ospf *, + struct prefix_ipv4 *); +extern void ospf_asbr_status_update(struct ospf *, u_char); -extern void ospf_redistribute_withdraw (struct ospf *, u_char, u_short); -extern void ospf_asbr_check (void); -extern void ospf_schedule_asbr_check (void); -extern void ospf_asbr_route_install_lsa (struct ospf_lsa *); -extern struct ospf_lsa *ospf_external_info_find_lsa (struct ospf *, - struct prefix_ipv4 *p); +extern void ospf_redistribute_withdraw(struct ospf *, u_char, u_short); +extern void ospf_asbr_check(void); +extern void ospf_schedule_asbr_check(void); +extern void ospf_asbr_route_install_lsa(struct ospf_lsa *); +extern struct ospf_lsa *ospf_external_info_find_lsa(struct ospf *, + struct prefix_ipv4 *p); #endif /* _ZEBRA_OSPF_ASBR_H */ diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c index b7cba7fd7..bf2b809dd 100644 --- a/ospfd/ospf_ase.c +++ b/ospfd/ospf_ase.c @@ -45,114 +45,115 @@ #include "ospfd/ospf_zebra.h" #include "ospfd/ospf_dump.h" -struct ospf_route * -ospf_find_asbr_route (struct ospf *ospf, - struct route_table *rtrs, struct prefix_ipv4 *asbr) +struct ospf_route *ospf_find_asbr_route(struct ospf *ospf, + struct route_table *rtrs, + struct prefix_ipv4 *asbr) { - struct route_node *rn; - struct ospf_route *or, *best = NULL; - struct listnode *node; - struct list *chosen; - - /* Sanity check. */ - if (rtrs == NULL) - return NULL; - - rn = route_node_lookup (rtrs, (struct prefix *) asbr); - if (! rn) - return NULL; - - route_unlock_node (rn); - - chosen = list_new (); - - /* First try to find intra-area non-bb paths. */ - if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE)) - for (ALL_LIST_ELEMENTS_RO ((struct list *) rn->info, node, or)) - if (or->cost < OSPF_LS_INFINITY) - if (!OSPF_IS_AREA_ID_BACKBONE (or->u.std.area_id) && - or->path_type == OSPF_PATH_INTRA_AREA) - listnode_add (chosen, or); - - /* If none is found -- look through all. */ - if (listcount (chosen) == 0) - { - list_free (chosen); - chosen = rn->info; - } + struct route_node *rn; + struct ospf_route * or, *best = NULL; + struct listnode *node; + struct list *chosen; + + /* Sanity check. */ + if (rtrs == NULL) + return NULL; + + rn = route_node_lookup(rtrs, (struct prefix *)asbr); + if (!rn) + return NULL; + + route_unlock_node(rn); + + chosen = list_new(); + + /* First try to find intra-area non-bb paths. */ + if (!CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) + for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node, or)) + if (or->cost < OSPF_LS_INFINITY) + if (!OSPF_IS_AREA_ID_BACKBONE(or->u.std.area_id) + && + or->path_type == OSPF_PATH_INTRA_AREA) + listnode_add(chosen, or); + + /* If none is found -- look through all. */ + if (listcount(chosen) == 0) { + list_free(chosen); + chosen = rn->info; + } - /* Now find the route with least cost. */ - for (ALL_LIST_ELEMENTS_RO (chosen, node, or)) - if (or->cost < OSPF_LS_INFINITY) - { - if (best == NULL) - best = or; - else if (best->cost > or->cost) - best = or; - else if (best->cost == or->cost && - IPV4_ADDR_CMP (&best->u.std.area_id, - &or->u.std.area_id) < 0) - best = or; - } - - if (chosen != rn->info) - list_delete (chosen); - - return best; + /* Now find the route with least cost. */ + for (ALL_LIST_ELEMENTS_RO(chosen, node, or)) + if (or->cost < OSPF_LS_INFINITY) { + if (best == NULL) + best = or ; + else if (best->cost > or->cost) + best = or ; + else if (best->cost == + or->cost + && IPV4_ADDR_CMP( + &best->u.std.area_id, + & or->u.std.area_id) + < 0) + best = or ; + } + + if (chosen != rn->info) + list_delete(chosen); + + return best; } -struct ospf_route * -ospf_find_asbr_route_through_area (struct route_table *rtrs, - struct prefix_ipv4 *asbr, - struct ospf_area *area) +struct ospf_route *ospf_find_asbr_route_through_area(struct route_table *rtrs, + struct prefix_ipv4 *asbr, + struct ospf_area *area) { - struct route_node *rn; + struct route_node *rn; - /* Sanity check. */ - if (rtrs == NULL) - return NULL; + /* Sanity check. */ + if (rtrs == NULL) + return NULL; - rn = route_node_lookup (rtrs, (struct prefix *) asbr); - - if (rn) - { - struct listnode *node; - struct ospf_route *or; + rn = route_node_lookup(rtrs, (struct prefix *)asbr); - route_unlock_node (rn); + if (rn) { + struct listnode *node; + struct ospf_route * or ; - for (ALL_LIST_ELEMENTS_RO ((struct list *) rn->info, node, or)) - if (IPV4_ADDR_SAME (&or->u.std.area_id, &area->area_id)) - return or; - } + route_unlock_node(rn); + + for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node, or)) + if (IPV4_ADDR_SAME(& or->u.std.area_id, &area->area_id)) + return or ; + } - return NULL; + return NULL; } -static void -ospf_ase_complete_direct_routes (struct ospf_route *ro, struct in_addr nexthop) +static void ospf_ase_complete_direct_routes(struct ospf_route *ro, + struct in_addr nexthop) { - struct listnode *node; - struct ospf_path *op; + struct listnode *node; + struct ospf_path *op; - for (ALL_LIST_ELEMENTS_RO (ro->paths, node, op)) - if (op->nexthop.s_addr == 0) - op->nexthop.s_addr = nexthop.s_addr; + for (ALL_LIST_ELEMENTS_RO(ro->paths, node, op)) + if (op->nexthop.s_addr == 0) + op->nexthop.s_addr = nexthop.s_addr; } -static int -ospf_ase_forward_address_check (struct ospf *ospf, struct in_addr fwd_addr) +static int ospf_ase_forward_address_check(struct ospf *ospf, + struct in_addr fwd_addr) { - struct listnode *ifn; - struct ospf_interface *oi; - - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, ifn, oi)) - if (if_is_operative (oi->ifp)) - if (oi->type != OSPF_IFTYPE_VIRTUALLINK) - if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &fwd_addr)) - return 0; - - return 1; + struct listnode *ifn; + struct ospf_interface *oi; + + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, ifn, oi)) + if (if_is_operative(oi->ifp)) + if (oi->type != OSPF_IFTYPE_VIRTUALLINK) + if (IPV4_ADDR_SAME(&oi->address->u.prefix4, + &fwd_addr)) + return 0; + + return 1; } #if 0 @@ -239,627 +240,608 @@ ospf_ase_calculate_asbr_route (struct ospf *ospf, #endif static struct ospf_route * -ospf_ase_calculate_new_route (struct ospf_lsa *lsa, - struct ospf_route *asbr_route, u_int32_t metric) +ospf_ase_calculate_new_route(struct ospf_lsa *lsa, + struct ospf_route *asbr_route, u_int32_t metric) { - struct as_external_lsa *al; - struct ospf_route *new; - - al = (struct as_external_lsa *) lsa->data; - - new = ospf_route_new (); - - /* Set redistributed type -- does make sense? */ - /* new->type = type; */ - new->id = al->header.id; - new->mask = al->mask; - - if (!IS_EXTERNAL_METRIC (al->e[0].tos)) - { - if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("Route[External]: type-1 created."); - new->path_type = OSPF_PATH_TYPE1_EXTERNAL; - new->cost = asbr_route->cost + metric; /* X + Y */ - } - else - { - if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("Route[External]: type-2 created."); - new->path_type = OSPF_PATH_TYPE2_EXTERNAL; - new->cost = asbr_route->cost; /* X */ - new->u.ext.type2_cost = metric; /* Y */ - } + struct as_external_lsa *al; + struct ospf_route *new; + + al = (struct as_external_lsa *)lsa->data; + + new = ospf_route_new(); + + /* Set redistributed type -- does make sense? */ + /* new->type = type; */ + new->id = al->header.id; + new->mask = al->mask; + + if (!IS_EXTERNAL_METRIC(al->e[0].tos)) { + if (IS_DEBUG_OSPF(lsa, LSA)) + zlog_debug("Route[External]: type-1 created."); + new->path_type = OSPF_PATH_TYPE1_EXTERNAL; + new->cost = asbr_route->cost + metric; /* X + Y */ + } else { + if (IS_DEBUG_OSPF(lsa, LSA)) + zlog_debug("Route[External]: type-2 created."); + new->path_type = OSPF_PATH_TYPE2_EXTERNAL; + new->cost = asbr_route->cost; /* X */ + new->u.ext.type2_cost = metric; /* Y */ + } - new->type = OSPF_DESTINATION_NETWORK; - new->u.ext.origin = lsa; - new->u.ext.tag = ntohl (al->e[0].route_tag); - new->u.ext.asbr = asbr_route; + new->type = OSPF_DESTINATION_NETWORK; + new->u.ext.origin = lsa; + new->u.ext.tag = ntohl(al->e[0].route_tag); + new->u.ext.asbr = asbr_route; - assert (new != asbr_route); + assert(new != asbr_route); - return new; + return new; } #define OSPF_ASE_CALC_INTERVAL 1 -int -ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa) +int ospf_ase_calculate_route(struct ospf *ospf, struct ospf_lsa *lsa) { - u_int32_t metric; - struct as_external_lsa *al; - struct ospf_route *asbr_route; - struct prefix_ipv4 asbr, p; - struct route_node *rn; - struct ospf_route *new, *or; - int ret; - - assert (lsa); - al = (struct as_external_lsa *) lsa->data; - - if (lsa->data->type == OSPF_AS_NSSA_LSA) - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_ase_calc(): Processing Type-7"); - - /* Stay away from any Local Translated Type-7 LSAs */ - if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_ase_calc(): Rejecting Local Xlt'd"); - return 0; - } - - if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("Route[External]: Calculate AS-external-LSA to %s/%d", - inet_ntoa (al->header.id), ip_masklen (al->mask)); - /* (1) If the cost specified by the LSA is LSInfinity, or if the - LSA's LS age is equal to MaxAge, then examine the next LSA. */ - if ((metric = GET_METRIC (al->e[0].metric)) >= OSPF_LS_INFINITY) - { - if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("Route[External]: Metric is OSPF_LS_INFINITY"); - return 0; - } - if (IS_LSA_MAXAGE (lsa)) - { - if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("Route[External]: AS-external-LSA is MAXAGE"); - return 0; - } - - /* (2) If the LSA was originated by the calculating router itself, - examine the next LSA. */ - if (IS_LSA_SELF (lsa)) - { - if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("Route[External]: AS-external-LSA is self originated"); - return 0; - } - - /* (3) Call the destination described by the LSA N. N's address is - obtained by masking the LSA's Link State ID with the - network/subnet mask contained in the body of the LSA. Look - up the routing table entries (potentially one per attached - area) for the AS boundary router (ASBR) that originated the - LSA. If no entries exist for router ASBR (i.e., ASBR is - unreachable), do nothing with this LSA and consider the next - in the list. */ - - asbr.family = AF_INET; - asbr.prefix = al->header.adv_router; - asbr.prefixlen = IPV4_MAX_BITLEN; - apply_mask_ipv4 (&asbr); - - asbr_route = ospf_find_asbr_route (ospf, ospf->new_rtrs, &asbr); - if (asbr_route == NULL) - { - if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("Route[External]: Can't find originating ASBR route"); - return 0; - } - if (!(asbr_route->u.std.flags & ROUTER_LSA_EXTERNAL)) - { - if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("Route[External]: Originating router is not an ASBR"); - return 0; - } - - /* Else, this LSA describes an AS external path to destination - N. Examine the forwarding address specified in the AS- - external-LSA. This indicates the IP address to which - packets for the destination should be forwarded. */ - - if (al->e[0].fwd_addr.s_addr == 0) - { - /* If the forwarding address is set to 0.0.0.0, packets should - be sent to the ASBR itself. Among the multiple routing table - entries for the ASBR, select the preferred entry as follows. - If RFC1583Compatibility is set to "disabled", prune the set - of routing table entries for the ASBR as described in - Section 16.4.1. In any case, among the remaining routing - table entries, select the routing table entry with the least - cost; when there are multiple least cost routing table - entries the entry whose associated area has the largest OSPF - Area ID (when considered as an unsigned 32-bit integer) is - chosen. */ - - /* asbr_route already contains the requested route */ - } - else - { - /* If the forwarding address is non-zero, look up the - forwarding address in the routing table.[24] The matching - routing table entry must specify an intra-area or inter-area - path; if no such path exists, do nothing with the LSA and - consider the next in the list. */ - if (! ospf_ase_forward_address_check (ospf, al->e[0].fwd_addr)) - { - if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("Route[External]: Forwarding address is our router " - "address"); - return 0; + u_int32_t metric; + struct as_external_lsa *al; + struct ospf_route *asbr_route; + struct prefix_ipv4 asbr, p; + struct route_node *rn; + struct ospf_route *new, * or ; + int ret; + + assert(lsa); + al = (struct as_external_lsa *)lsa->data; + + if (lsa->data->type == OSPF_AS_NSSA_LSA) + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("ospf_ase_calc(): Processing Type-7"); + + /* Stay away from any Local Translated Type-7 LSAs */ + if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("ospf_ase_calc(): Rejecting Local Xlt'd"); + return 0; } - - asbr.family = AF_INET; - asbr.prefix = al->e[0].fwd_addr; - asbr.prefixlen = IPV4_MAX_BITLEN; - rn = route_node_match (ospf->new_table, (struct prefix *) &asbr); - - if (rn == NULL || (asbr_route = rn->info) == NULL) - { - if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("Route[External]: Can't find route to forwarding " - "address"); - if (rn) - route_unlock_node (rn); - return 0; + if (IS_DEBUG_OSPF(lsa, LSA)) + zlog_debug( + "Route[External]: Calculate AS-external-LSA to %s/%d", + inet_ntoa(al->header.id), ip_masklen(al->mask)); + /* (1) If the cost specified by the LSA is LSInfinity, or if the + LSA's LS age is equal to MaxAge, then examine the next LSA. */ + if ((metric = GET_METRIC(al->e[0].metric)) >= OSPF_LS_INFINITY) { + if (IS_DEBUG_OSPF(lsa, LSA)) + zlog_debug( + "Route[External]: Metric is OSPF_LS_INFINITY"); + return 0; + } + if (IS_LSA_MAXAGE(lsa)) { + if (IS_DEBUG_OSPF(lsa, LSA)) + zlog_debug( + "Route[External]: AS-external-LSA is MAXAGE"); + return 0; } - route_unlock_node (rn); - } - - /* (4) Let X be the cost specified by the preferred routing table - entry for the ASBR/forwarding address, and Y the cost - specified in the LSA. X is in terms of the link state - metric, and Y is a type 1 or 2 external metric. */ - - - /* (5) Look up the routing table entry for the destination N. If - no entry exists for N, install the AS external path to N, - with next hop equal to the list of next hops to the - forwarding address, and advertising router equal to ASBR. - If the external metric type is 1, then the path-type is set - to type 1 external and the cost is equal to X+Y. If the - external metric type is 2, the path-type is set to type 2 - external, the link state component of the route's cost is X, - and the type 2 cost is Y. */ - new = ospf_ase_calculate_new_route (lsa, asbr_route, metric); - - /* (6) Compare the AS external path described by the LSA with the - existing paths in N's routing table entry, as follows. If - the new path is preferred, it replaces the present paths in - N's routing table entry. If the new path is of equal - preference, it is added to N's routing table entry's list of - paths. */ - - /* Set prefix. */ - p.family = AF_INET; - p.prefix = al->header.id; - p.prefixlen = ip_masklen (al->mask); - - /* if there is a Intra/Inter area route to the N - do not install external route */ - if ((rn = route_node_lookup (ospf->new_table, - (struct prefix *) &p))) - { - route_unlock_node(rn); - if (rn->info == NULL) - zlog_info ("Route[External]: rn->info NULL"); - if (new) - ospf_route_free (new); - return 0; - } - /* Find a route to the same dest */ - /* If there is no route, create new one. */ - if ((rn = route_node_lookup (ospf->new_external_route, - (struct prefix *) &p))) - route_unlock_node(rn); - - if (!rn || (or = rn->info) == NULL) - { - if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("Route[External]: Adding a new route %s/%d", - inet_ntoa (p.prefix), p.prefixlen); + /* (2) If the LSA was originated by the calculating router itself, + examine the next LSA. */ + if (IS_LSA_SELF(lsa)) { + if (IS_DEBUG_OSPF(lsa, LSA)) + zlog_debug( + "Route[External]: AS-external-LSA is self originated"); + return 0; + } - ospf_route_add (ospf->new_external_route, &p, new, asbr_route); + /* (3) Call the destination described by the LSA N. N's address is + obtained by masking the LSA's Link State ID with the + network/subnet mask contained in the body of the LSA. Look + up the routing table entries (potentially one per attached + area) for the AS boundary router (ASBR) that originated the + LSA. If no entries exist for router ASBR (i.e., ASBR is + unreachable), do nothing with this LSA and consider the next + in the list. */ + + asbr.family = AF_INET; + asbr.prefix = al->header.adv_router; + asbr.prefixlen = IPV4_MAX_BITLEN; + apply_mask_ipv4(&asbr); + + asbr_route = ospf_find_asbr_route(ospf, ospf->new_rtrs, &asbr); + if (asbr_route == NULL) { + if (IS_DEBUG_OSPF(lsa, LSA)) + zlog_debug( + "Route[External]: Can't find originating ASBR route"); + return 0; + } + if (!(asbr_route->u.std.flags & ROUTER_LSA_EXTERNAL)) { + if (IS_DEBUG_OSPF(lsa, LSA)) + zlog_debug( + "Route[External]: Originating router is not an ASBR"); + return 0; + } - if (al->e[0].fwd_addr.s_addr) - ospf_ase_complete_direct_routes (new, al->e[0].fwd_addr); - return 0; - } - else - { - /* (a) Intra-area and inter-area paths are always preferred - over AS external paths. - - (b) Type 1 external paths are always preferred over type 2 - external paths. When all paths are type 2 external - paths, the paths with the smallest advertised type 2 - metric are always preferred. */ - ret = ospf_route_cmp (ospf, new, or); - - /* (c) If the new AS external path is still indistinguishable - from the current paths in the N's routing table entry, - and RFC1583Compatibility is set to "disabled", select - the preferred paths based on the intra-AS paths to the - ASBR/forwarding addresses, as specified in Section - 16.4.1. - - (d) If the new AS external path is still indistinguishable - from the current paths in the N's routing table entry, - select the preferred path based on a least cost - comparison. Type 1 external paths are compared by - looking at the sum of the distance to the forwarding - address and the advertised type 1 metric (X+Y). Type 2 - external paths advertising equal type 2 metrics are - compared by looking at the distance to the forwarding - addresses. - */ - /* New route is better */ - if (ret < 0) - { - if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("Route[External]: New route is better"); - ospf_route_subst (rn, new, asbr_route); - if (al->e[0].fwd_addr.s_addr) - ospf_ase_complete_direct_routes (new, al->e[0].fwd_addr); - or = new; - new = NULL; + /* Else, this LSA describes an AS external path to destination + N. Examine the forwarding address specified in the AS- + external-LSA. This indicates the IP address to which + packets for the destination should be forwarded. */ + + if (al->e[0].fwd_addr.s_addr == 0) { + /* If the forwarding address is set to 0.0.0.0, packets should + be sent to the ASBR itself. Among the multiple routing table + entries for the ASBR, select the preferred entry as follows. + If RFC1583Compatibility is set to "disabled", prune the set + of routing table entries for the ASBR as described in + Section 16.4.1. In any case, among the remaining routing + table entries, select the routing table entry with the least + cost; when there are multiple least cost routing table + entries the entry whose associated area has the largest OSPF + Area ID (when considered as an unsigned 32-bit integer) is + chosen. */ + + /* asbr_route already contains the requested route */ + } else { + /* If the forwarding address is non-zero, look up the + forwarding address in the routing table.[24] The matching + routing table entry must specify an intra-area or inter-area + path; if no such path exists, do nothing with the LSA and + consider the next in the list. */ + if (!ospf_ase_forward_address_check(ospf, al->e[0].fwd_addr)) { + if (IS_DEBUG_OSPF(lsa, LSA)) + zlog_debug( + "Route[External]: Forwarding address is our router " + "address"); + return 0; + } + + asbr.family = AF_INET; + asbr.prefix = al->e[0].fwd_addr; + asbr.prefixlen = IPV4_MAX_BITLEN; + + rn = route_node_match(ospf->new_table, (struct prefix *)&asbr); + + if (rn == NULL || (asbr_route = rn->info) == NULL) { + if (IS_DEBUG_OSPF(lsa, LSA)) + zlog_debug( + "Route[External]: Can't find route to forwarding " + "address"); + if (rn) + route_unlock_node(rn); + return 0; + } + + route_unlock_node(rn); } - /* Old route is better */ - else if (ret > 0) - { - if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("Route[External]: Old route is better"); - /* do nothing */ + + /* (4) Let X be the cost specified by the preferred routing table + entry for the ASBR/forwarding address, and Y the cost + specified in the LSA. X is in terms of the link state + metric, and Y is a type 1 or 2 external metric. */ + + + /* (5) Look up the routing table entry for the destination N. If + no entry exists for N, install the AS external path to N, + with next hop equal to the list of next hops to the + forwarding address, and advertising router equal to ASBR. + If the external metric type is 1, then the path-type is set + to type 1 external and the cost is equal to X+Y. If the + external metric type is 2, the path-type is set to type 2 + external, the link state component of the route's cost is X, + and the type 2 cost is Y. */ + new = ospf_ase_calculate_new_route(lsa, asbr_route, metric); + + /* (6) Compare the AS external path described by the LSA with the + existing paths in N's routing table entry, as follows. If + the new path is preferred, it replaces the present paths in + N's routing table entry. If the new path is of equal + preference, it is added to N's routing table entry's list of + paths. */ + + /* Set prefix. */ + p.family = AF_INET; + p.prefix = al->header.id; + p.prefixlen = ip_masklen(al->mask); + + /* if there is a Intra/Inter area route to the N + do not install external route */ + if ((rn = route_node_lookup(ospf->new_table, (struct prefix *)&p))) { + route_unlock_node(rn); + if (rn->info == NULL) + zlog_info("Route[External]: rn->info NULL"); + if (new) + ospf_route_free(new); + return 0; } - /* Routes are equal */ - else - { - if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("Route[External]: Routes are equal"); - ospf_route_copy_nexthops (or, asbr_route->paths); - if (al->e[0].fwd_addr.s_addr) - ospf_ase_complete_direct_routes (or, al->e[0].fwd_addr); + /* Find a route to the same dest */ + /* If there is no route, create new one. */ + if ((rn = route_node_lookup(ospf->new_external_route, + (struct prefix *)&p))) + route_unlock_node(rn); + + if (!rn || (or = rn->info) == NULL) { + if (IS_DEBUG_OSPF(lsa, LSA)) + zlog_debug("Route[External]: Adding a new route %s/%d", + inet_ntoa(p.prefix), p.prefixlen); + + ospf_route_add(ospf->new_external_route, &p, new, asbr_route); + + if (al->e[0].fwd_addr.s_addr) + ospf_ase_complete_direct_routes(new, al->e[0].fwd_addr); + return 0; + } else { + /* (a) Intra-area and inter-area paths are always preferred + over AS external paths. + + (b) Type 1 external paths are always preferred over type 2 + external paths. When all paths are type 2 external + paths, the paths with the smallest advertised type 2 + metric are always preferred. */ + ret = ospf_route_cmp(ospf, new, or); + + /* (c) If the new AS external path is still + indistinguishable + from the current paths in the N's routing table + entry, + and RFC1583Compatibility is set to "disabled", select + the preferred paths based on the intra-AS paths to + the + ASBR/forwarding addresses, as specified in Section + 16.4.1. + + (d) If the new AS external path is still + indistinguishable + from the current paths in the N's routing table + entry, + select the preferred path based on a least cost + comparison. Type 1 external paths are compared by + looking at the sum of the distance to the forwarding + address and the advertised type 1 metric (X+Y). Type + 2 + external paths advertising equal type 2 metrics are + compared by looking at the distance to the forwarding + addresses. + */ + /* New route is better */ + if (ret < 0) { + if (IS_DEBUG_OSPF(lsa, LSA)) + zlog_debug( + "Route[External]: New route is better"); + ospf_route_subst(rn, new, asbr_route); + if (al->e[0].fwd_addr.s_addr) + ospf_ase_complete_direct_routes( + new, al->e[0].fwd_addr); + or = new; + new = NULL; + } + /* Old route is better */ + else if (ret > 0) { + if (IS_DEBUG_OSPF(lsa, LSA)) + zlog_debug( + "Route[External]: Old route is better"); + /* do nothing */ + } + /* Routes are equal */ + else { + if (IS_DEBUG_OSPF(lsa, LSA)) + zlog_debug("Route[External]: Routes are equal"); + ospf_route_copy_nexthops(or, asbr_route->paths); + if (al->e[0].fwd_addr.s_addr) + ospf_ase_complete_direct_routes( + or, al->e[0].fwd_addr); + } } - } - /* Make sure setting newly calculated ASBR route.*/ - or->u.ext.asbr = asbr_route; - if (new) - ospf_route_free (new); + /* Make sure setting newly calculated ASBR route.*/ + or->u.ext.asbr = asbr_route; + if (new) + ospf_route_free(new); - lsa->route = or; - return 0; + lsa->route = or ; + return 0; } -static int -ospf_ase_route_match_same (struct route_table *rt, struct prefix *prefix, - struct ospf_route *newor) +static int ospf_ase_route_match_same(struct route_table *rt, + struct prefix *prefix, + struct ospf_route *newor) { - struct route_node *rn; - struct ospf_route *or; - struct ospf_path *op; - struct ospf_path *newop; - struct listnode *n1; - struct listnode *n2; - - if (! rt || ! prefix) - return 0; - - rn = route_node_lookup (rt, prefix); - if (! rn) - return 0; - - route_unlock_node (rn); - - or = rn->info; - if (or->path_type != newor->path_type) - return 0; - - switch (or->path_type) - { - case OSPF_PATH_TYPE1_EXTERNAL: - if (or->cost != newor->cost) - return 0; - break; - case OSPF_PATH_TYPE2_EXTERNAL: - if ((or->cost != newor->cost) || - (or->u.ext.type2_cost != newor->u.ext.type2_cost)) - return 0; - break; - default: - assert (0); - return 0; - } - - if (or->paths->count != newor->paths->count) - return 0; - - /* Check each path. */ - for (n1 = listhead (or->paths), n2 = listhead (newor->paths); - n1 && n2; n1 = listnextnode (n1), n2 = listnextnode (n2)) - { - op = listgetdata (n1); - newop = listgetdata (n2); - - if (! IPV4_ADDR_SAME (&op->nexthop, &newop->nexthop)) - return 0; - if (op->ifindex != newop->ifindex) - return 0; - } - - if (or->u.ext.tag != newor->u.ext.tag) - return 0; - - return 1; + struct route_node *rn; + struct ospf_route * or ; + struct ospf_path *op; + struct ospf_path *newop; + struct listnode *n1; + struct listnode *n2; + + if (!rt || !prefix) + return 0; + + rn = route_node_lookup(rt, prefix); + if (!rn) + return 0; + + route_unlock_node(rn); + + or = rn->info; + if (or->path_type != newor->path_type) + return 0; + + switch (or->path_type) { + case OSPF_PATH_TYPE1_EXTERNAL: + if (or->cost != newor->cost) + return 0; + break; + case OSPF_PATH_TYPE2_EXTERNAL: + if ((or->cost != newor->cost) + || (or->u.ext.type2_cost != newor->u.ext.type2_cost)) + return 0; + break; + default: + assert(0); + return 0; + } + + if (or->paths->count != newor->paths->count) + return 0; + + /* Check each path. */ + for (n1 = listhead(or->paths), n2 = listhead(newor->paths); n1 && n2; + n1 = listnextnode(n1), n2 = listnextnode(n2)) { + op = listgetdata(n1); + newop = listgetdata(n2); + + if (!IPV4_ADDR_SAME(&op->nexthop, &newop->nexthop)) + return 0; + if (op->ifindex != newop->ifindex) + return 0; + } + + if (or->u.ext.tag != newor->u.ext.tag) + return 0; + + return 1; } -static int -ospf_ase_compare_tables (struct route_table *new_external_route, - struct route_table *old_external_route) +static int ospf_ase_compare_tables(struct route_table *new_external_route, + struct route_table *old_external_route) { - struct route_node *rn, *new_rn; - struct ospf_route *or; - - /* Remove deleted routes */ - for (rn = route_top (old_external_route); rn; rn = route_next (rn)) - if ((or = rn->info)) - { - if (! (new_rn = route_node_lookup (new_external_route, &rn->p))) - ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, or); - else - route_unlock_node (new_rn); - } - - - /* Install new routes */ - for (rn = route_top (new_external_route); rn; rn = route_next (rn)) - if ((or = rn->info) != NULL) - if (! ospf_ase_route_match_same (old_external_route, &rn->p, or)) - ospf_zebra_add ((struct prefix_ipv4 *) &rn->p, or); - - return 0; + struct route_node *rn, *new_rn; + struct ospf_route * or ; + + /* Remove deleted routes */ + for (rn = route_top(old_external_route); rn; rn = route_next(rn)) + if ((or = rn->info)) { + if (!(new_rn = route_node_lookup(new_external_route, + &rn->p))) + ospf_zebra_delete((struct prefix_ipv4 *)&rn->p, + or); + else + route_unlock_node(new_rn); + } + + + /* Install new routes */ + for (rn = route_top(new_external_route); rn; rn = route_next(rn)) + if ((or = rn->info) != NULL) + if (!ospf_ase_route_match_same(old_external_route, + &rn->p, or)) + ospf_zebra_add((struct prefix_ipv4 *)&rn->p, + or); + + return 0; } -static int -ospf_ase_calculate_timer (struct thread *t) +static int ospf_ase_calculate_timer(struct thread *t) { - struct ospf *ospf; - struct ospf_lsa *lsa; - struct route_node *rn; - struct listnode *node; - struct ospf_area *area; - struct timeval start_time, stop_time; - - ospf = THREAD_ARG (t); - ospf->t_ase_calc = NULL; - - if (ospf->ase_calc) - { - ospf->ase_calc = 0; - - monotime(&start_time); - - /* Calculate external route for each AS-external-LSA */ - LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) - ospf_ase_calculate_route (ospf, lsa); - - /* This version simple adds to the table all NSSA areas */ - if (ospf->anyNSSA) - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_ase_calculate_timer(): looking at area %s", - inet_ntoa (area->area_id)); - - if (area->external_routing == OSPF_AREA_NSSA) - LSDB_LOOP (NSSA_LSDB (area), rn, lsa) - ospf_ase_calculate_route (ospf, lsa); - } - /* kevinm: And add the NSSA routes in ospf_top */ - LSDB_LOOP (NSSA_LSDB (ospf),rn,lsa) - ospf_ase_calculate_route(ospf,lsa); - - /* Compare old and new external routing table and install the - difference info zebra/kernel */ - ospf_ase_compare_tables (ospf->new_external_route, - ospf->old_external_route); - - /* Delete old external routing table */ - ospf_route_table_free (ospf->old_external_route); - ospf->old_external_route = ospf->new_external_route; - ospf->new_external_route = route_table_init (); - - monotime(&stop_time); - - zlog_info ("SPF Processing Time(usecs): External Routes: %lld\n", - (stop_time.tv_sec - start_time.tv_sec)*1000000LL+ - (stop_time.tv_usec - start_time.tv_usec)); - } - return 0; + struct ospf *ospf; + struct ospf_lsa *lsa; + struct route_node *rn; + struct listnode *node; + struct ospf_area *area; + struct timeval start_time, stop_time; + + ospf = THREAD_ARG(t); + ospf->t_ase_calc = NULL; + + if (ospf->ase_calc) { + ospf->ase_calc = 0; + + monotime(&start_time); + + /* Calculate external route for each AS-external-LSA */ + LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa) + ospf_ase_calculate_route(ospf, lsa); + + /* This version simple adds to the table all NSSA areas */ + if (ospf->anyNSSA) + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_ase_calculate_timer(): looking at area %s", + inet_ntoa(area->area_id)); + + if (area->external_routing == OSPF_AREA_NSSA) + LSDB_LOOP(NSSA_LSDB(area), rn, lsa) + ospf_ase_calculate_route(ospf, lsa); + } + /* kevinm: And add the NSSA routes in ospf_top */ + LSDB_LOOP(NSSA_LSDB(ospf), rn, lsa) + ospf_ase_calculate_route(ospf, lsa); + + /* Compare old and new external routing table and install the + difference info zebra/kernel */ + ospf_ase_compare_tables(ospf->new_external_route, + ospf->old_external_route); + + /* Delete old external routing table */ + ospf_route_table_free(ospf->old_external_route); + ospf->old_external_route = ospf->new_external_route; + ospf->new_external_route = route_table_init(); + + monotime(&stop_time); + + zlog_info("SPF Processing Time(usecs): External Routes: %lld\n", + (stop_time.tv_sec - start_time.tv_sec) * 1000000LL + + (stop_time.tv_usec - start_time.tv_usec)); + } + return 0; } -void -ospf_ase_calculate_schedule (struct ospf *ospf) +void ospf_ase_calculate_schedule(struct ospf *ospf) { - if (ospf == NULL) - return; + if (ospf == NULL) + return; - ospf->ase_calc = 1; + ospf->ase_calc = 1; } -void -ospf_ase_calculate_timer_add (struct ospf *ospf) +void ospf_ase_calculate_timer_add(struct ospf *ospf) { - if (ospf == NULL) - return; + if (ospf == NULL) + return; - thread_add_timer(master, ospf_ase_calculate_timer, ospf, - OSPF_ASE_CALC_INTERVAL, &ospf->t_ase_calc); + thread_add_timer(master, ospf_ase_calculate_timer, ospf, + OSPF_ASE_CALC_INTERVAL, &ospf->t_ase_calc); } -void -ospf_ase_register_external_lsa (struct ospf_lsa *lsa, struct ospf *top) +void ospf_ase_register_external_lsa(struct ospf_lsa *lsa, struct ospf *top) { - struct route_node *rn; - struct prefix_ipv4 p; - struct list *lst; - struct as_external_lsa *al; - - al = (struct as_external_lsa *) lsa->data; - p.family = AF_INET; - p.prefix = lsa->data->id; - p.prefixlen = ip_masklen (al->mask); - apply_mask_ipv4 (&p); - - rn = route_node_get (top->external_lsas, (struct prefix *) &p); - if ((lst = rn->info) == NULL) - rn->info = lst = list_new(); - else - route_unlock_node (rn); - - /* We assume that if LSA is deleted from DB - is is also deleted from this RT */ - listnode_add (lst, ospf_lsa_lock (lsa)); /* external_lsas lst */ + struct route_node *rn; + struct prefix_ipv4 p; + struct list *lst; + struct as_external_lsa *al; + + al = (struct as_external_lsa *)lsa->data; + p.family = AF_INET; + p.prefix = lsa->data->id; + p.prefixlen = ip_masklen(al->mask); + apply_mask_ipv4(&p); + + rn = route_node_get(top->external_lsas, (struct prefix *)&p); + if ((lst = rn->info) == NULL) + rn->info = lst = list_new(); + else + route_unlock_node(rn); + + /* We assume that if LSA is deleted from DB + is is also deleted from this RT */ + listnode_add(lst, ospf_lsa_lock(lsa)); /* external_lsas lst */ } -void -ospf_ase_unregister_external_lsa (struct ospf_lsa *lsa, struct ospf *top) +void ospf_ase_unregister_external_lsa(struct ospf_lsa *lsa, struct ospf *top) { - struct route_node *rn; - struct prefix_ipv4 p; - struct list *lst; - struct as_external_lsa *al; - - al = (struct as_external_lsa *) lsa->data; - p.family = AF_INET; - p.prefix = lsa->data->id; - p.prefixlen = ip_masklen (al->mask); - apply_mask_ipv4 (&p); - - rn = route_node_lookup (top->external_lsas, (struct prefix *) &p); - - if (rn) { - lst = rn->info; - listnode_delete (lst, lsa); - ospf_lsa_unlock (&lsa); /* external_lsas list */ - route_unlock_node (rn); - } + struct route_node *rn; + struct prefix_ipv4 p; + struct list *lst; + struct as_external_lsa *al; + + al = (struct as_external_lsa *)lsa->data; + p.family = AF_INET; + p.prefix = lsa->data->id; + p.prefixlen = ip_masklen(al->mask); + apply_mask_ipv4(&p); + + rn = route_node_lookup(top->external_lsas, (struct prefix *)&p); + + if (rn) { + lst = rn->info; + listnode_delete(lst, lsa); + ospf_lsa_unlock(&lsa); /* external_lsas list */ + route_unlock_node(rn); + } } -void -ospf_ase_external_lsas_finish (struct route_table *rt) +void ospf_ase_external_lsas_finish(struct route_table *rt) { - struct route_node *rn; - struct ospf_lsa *lsa; - struct list *lst; - struct listnode *node, *nnode; - - for (rn = route_top (rt); rn; rn = route_next (rn)) - if ((lst = rn->info) != NULL) - { - for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa)) - ospf_lsa_unlock (&lsa); /* external_lsas lst */ - list_delete (lst); - } - - route_table_finish (rt); + struct route_node *rn; + struct ospf_lsa *lsa; + struct list *lst; + struct listnode *node, *nnode; + + for (rn = route_top(rt); rn; rn = route_next(rn)) + if ((lst = rn->info) != NULL) { + for (ALL_LIST_ELEMENTS(lst, node, nnode, lsa)) + ospf_lsa_unlock(&lsa); /* external_lsas lst */ + list_delete(lst); + } + + route_table_finish(rt); } -void -ospf_ase_incremental_update (struct ospf *ospf, struct ospf_lsa *lsa) +void ospf_ase_incremental_update(struct ospf *ospf, struct ospf_lsa *lsa) { - struct list *lsas; - struct listnode *node; - struct route_node *rn, *rn2; - struct prefix_ipv4 p; - struct route_table *tmp_old; - struct as_external_lsa *al; - - al = (struct as_external_lsa *) lsa->data; - p.family = AF_INET; - p.prefix = lsa->data->id; - p.prefixlen = ip_masklen (al->mask); - apply_mask_ipv4 (&p); - - /* if new_table is NULL, there was no spf calculation, thus - incremental update is unneeded */ - if (!ospf->new_table) - return; - - /* If there is already an intra-area or inter-area route - to the destination, no recalculation is necessary - (internal routes take precedence). */ - - rn = route_node_lookup (ospf->new_table, (struct prefix *) &p); - if (rn) - { - route_unlock_node (rn); - if (rn->info) - return; - } - - rn = route_node_lookup (ospf->external_lsas, (struct prefix *) &p); - assert (rn); - assert (rn->info); - lsas = rn->info; - route_unlock_node (rn); - - for (ALL_LIST_ELEMENTS_RO (lsas, node, lsa)) - ospf_ase_calculate_route (ospf, lsa); - - /* prepare temporary old routing table for compare */ - tmp_old = route_table_init (); - rn = route_node_lookup (ospf->old_external_route, (struct prefix *) &p); - if (rn && rn->info) - { - rn2 = route_node_get (tmp_old, (struct prefix *) &p); - rn2->info = rn->info; - route_unlock_node (rn); - } - - /* install changes to zebra */ - ospf_ase_compare_tables (ospf->new_external_route, tmp_old); + struct list *lsas; + struct listnode *node; + struct route_node *rn, *rn2; + struct prefix_ipv4 p; + struct route_table *tmp_old; + struct as_external_lsa *al; + + al = (struct as_external_lsa *)lsa->data; + p.family = AF_INET; + p.prefix = lsa->data->id; + p.prefixlen = ip_masklen(al->mask); + apply_mask_ipv4(&p); + + /* if new_table is NULL, there was no spf calculation, thus + incremental update is unneeded */ + if (!ospf->new_table) + return; + + /* If there is already an intra-area or inter-area route + to the destination, no recalculation is necessary + (internal routes take precedence). */ + + rn = route_node_lookup(ospf->new_table, (struct prefix *)&p); + if (rn) { + route_unlock_node(rn); + if (rn->info) + return; + } - /* update ospf->old_external_route table */ - if (rn && rn->info) - ospf_route_free ((struct ospf_route *) rn->info); + rn = route_node_lookup(ospf->external_lsas, (struct prefix *)&p); + assert(rn); + assert(rn->info); + lsas = rn->info; + route_unlock_node(rn); + + for (ALL_LIST_ELEMENTS_RO(lsas, node, lsa)) + ospf_ase_calculate_route(ospf, lsa); + + /* prepare temporary old routing table for compare */ + tmp_old = route_table_init(); + rn = route_node_lookup(ospf->old_external_route, (struct prefix *)&p); + if (rn && rn->info) { + rn2 = route_node_get(tmp_old, (struct prefix *)&p); + rn2->info = rn->info; + route_unlock_node(rn); + } - rn2 = route_node_lookup (ospf->new_external_route, (struct prefix *) &p); - /* if new route exists, install it to ospf->old_external_route */ - if (rn2 && rn2->info) - { - if (!rn) - rn = route_node_get (ospf->old_external_route, (struct prefix *) &p); - rn->info = rn2->info; - } - else - { - /* remove route node from ospf->old_external_route */ - if (rn) - { - rn->info = NULL; - route_unlock_node (rn); + /* install changes to zebra */ + ospf_ase_compare_tables(ospf->new_external_route, tmp_old); + + /* update ospf->old_external_route table */ + if (rn && rn->info) + ospf_route_free((struct ospf_route *)rn->info); + + rn2 = route_node_lookup(ospf->new_external_route, (struct prefix *)&p); + /* if new route exists, install it to ospf->old_external_route */ + if (rn2 && rn2->info) { + if (!rn) + rn = route_node_get(ospf->old_external_route, + (struct prefix *)&p); + rn->info = rn2->info; + } else { + /* remove route node from ospf->old_external_route */ + if (rn) { + rn->info = NULL; + route_unlock_node(rn); + } } - } - if (rn2) - { - /* rn2->info is stored in route node of ospf->old_external_route */ - rn2->info = NULL; - route_unlock_node (rn2); - route_unlock_node (rn2); - } + if (rn2) { + /* rn2->info is stored in route node of ospf->old_external_route + */ + rn2->info = NULL; + route_unlock_node(rn2); + route_unlock_node(rn2); + } - route_table_finish (tmp_old); + route_table_finish(tmp_old); } diff --git a/ospfd/ospf_ase.h b/ospfd/ospf_ase.h index d73322fca..195d658c0 100644 --- a/ospfd/ospf_ase.h +++ b/ospfd/ospf_ase.h @@ -22,25 +22,19 @@ #ifndef _ZEBRA_OSPF_ASE_H #define _ZEBRA_OSPF_ASE_H +extern struct ospf_route * +ospf_find_asbr_route(struct ospf *, struct route_table *, struct prefix_ipv4 *); +extern struct ospf_route * +ospf_find_asbr_route_through_area(struct route_table *, struct prefix_ipv4 *, + struct ospf_area *); -extern struct ospf_route *ospf_find_asbr_route (struct ospf *, - struct route_table *, - struct prefix_ipv4 *); -extern struct ospf_route *ospf_find_asbr_route_through_area (struct - route_table *, - struct - prefix_ipv4 *, - struct ospf_area - *); +extern int ospf_ase_calculate_route(struct ospf *, struct ospf_lsa *); +extern void ospf_ase_calculate_schedule(struct ospf *); +extern void ospf_ase_calculate_timer_add(struct ospf *); -extern int ospf_ase_calculate_route (struct ospf *, struct ospf_lsa *); -extern void ospf_ase_calculate_schedule (struct ospf *); -extern void ospf_ase_calculate_timer_add (struct ospf *); - -extern void ospf_ase_external_lsas_finish (struct route_table *); -extern void ospf_ase_incremental_update (struct ospf *, struct ospf_lsa *); -extern void ospf_ase_register_external_lsa (struct ospf_lsa *, struct ospf *); -extern void ospf_ase_unregister_external_lsa (struct ospf_lsa *, - struct ospf *); +extern void ospf_ase_external_lsas_finish(struct route_table *); +extern void ospf_ase_incremental_update(struct ospf *, struct ospf_lsa *); +extern void ospf_ase_register_external_lsa(struct ospf_lsa *, struct ospf *); +extern void ospf_ase_unregister_external_lsa(struct ospf_lsa *, struct ospf *); #endif /* _ZEBRA_OSPF_ASE_H */ diff --git a/ospfd/ospf_bfd.c b/ospfd/ospf_bfd.c index 1bcffea6f..6d07b4436 100644 --- a/ospfd/ospf_bfd.c +++ b/ospfd/ospf_bfd.c @@ -49,10 +49,9 @@ extern struct zclient *zclient; /* * ospf_bfd_info_free - Free BFD info structure */ -void -ospf_bfd_info_free(void **bfd_info) +void ospf_bfd_info_free(void **bfd_info) { - bfd_info_free((struct bfd_info **) bfd_info); + bfd_info_free((struct bfd_info **)bfd_info); } /* @@ -60,42 +59,40 @@ ospf_bfd_info_free(void **bfd_info) * zebra for starting/stopping the monitoring of * the neighbor rechahability. */ -static void -ospf_bfd_reg_dereg_nbr (struct ospf_neighbor *nbr, int command) +static void ospf_bfd_reg_dereg_nbr(struct ospf_neighbor *nbr, int command) { - struct ospf_interface *oi = nbr->oi; - struct interface *ifp = oi->ifp; - struct ospf_if_params *params; - struct bfd_info *bfd_info; - - /* Check if BFD is enabled */ - params = IF_DEF_PARAMS (ifp); - - /* Check if BFD is enabled */ - if (!params->bfd_info) - return; - bfd_info = (struct bfd_info *)params->bfd_info; - - if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) - zlog_debug ("%s nbr (%s) with BFD", - bfd_get_command_dbg_str(command), - inet_ntoa (nbr->src)); - - bfd_peer_sendmsg (zclient, bfd_info, AF_INET, - &nbr->src, NULL, ifp->name, 0, 0, command, 0, VRF_DEFAULT); + struct ospf_interface *oi = nbr->oi; + struct interface *ifp = oi->ifp; + struct ospf_if_params *params; + struct bfd_info *bfd_info; + + /* Check if BFD is enabled */ + params = IF_DEF_PARAMS(ifp); + + /* Check if BFD is enabled */ + if (!params->bfd_info) + return; + bfd_info = (struct bfd_info *)params->bfd_info; + + if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) + zlog_debug("%s nbr (%s) with BFD", + bfd_get_command_dbg_str(command), + inet_ntoa(nbr->src)); + + bfd_peer_sendmsg(zclient, bfd_info, AF_INET, &nbr->src, NULL, ifp->name, + 0, 0, command, 0, VRF_DEFAULT); } /* * ospf_bfd_trigger_event - Neighbor is registered/deregistered with BFD when * neighbor state is changed to/from 2way. */ -void -ospf_bfd_trigger_event(struct ospf_neighbor *nbr, int old_state, int state) +void ospf_bfd_trigger_event(struct ospf_neighbor *nbr, int old_state, int state) { - if ((old_state < NSM_TwoWay) && (state >= NSM_TwoWay)) - ospf_bfd_reg_dereg_nbr(nbr, ZEBRA_BFD_DEST_REGISTER); - else if ((old_state >= NSM_TwoWay) && (state < NSM_TwoWay)) - ospf_bfd_reg_dereg_nbr(nbr, ZEBRA_BFD_DEST_DEREGISTER); + if ((old_state < NSM_TwoWay) && (state >= NSM_TwoWay)) + ospf_bfd_reg_dereg_nbr(nbr, ZEBRA_BFD_DEST_REGISTER); + else if ((old_state >= NSM_TwoWay) && (state < NSM_TwoWay)) + ospf_bfd_reg_dereg_nbr(nbr, ZEBRA_BFD_DEST_DEREGISTER); } /* @@ -104,95 +101,91 @@ ospf_bfd_trigger_event(struct ospf_neighbor *nbr, int old_state, int state) * zebra for starting/stopping the monitoring of * the neighbor rechahability. */ -static int -ospf_bfd_reg_dereg_all_nbr (struct interface *ifp, int command) +static int ospf_bfd_reg_dereg_all_nbr(struct interface *ifp, int command) { - struct ospf_interface *oi; - struct route_table *nbrs; - struct ospf_neighbor *nbr; - struct route_node *irn; - struct route_node *nrn; - - for (irn = route_top (IF_OIFS (ifp)); irn; irn = route_next (irn)) - { - if ((oi = irn->info) == NULL) - continue; - - if ((nbrs = oi->nbrs) == NULL) - continue; - - for (nrn = route_top (nbrs); nrn; nrn = route_next (nrn)) - { - if ((nbr = nrn->info) == NULL || nbr == oi->nbr_self) - continue; - - if (command != ZEBRA_BFD_DEST_DEREGISTER) - ospf_bfd_info_nbr_create(oi, nbr); - else - bfd_info_free((struct bfd_info **)&nbr->bfd_info); - - if (nbr->state < NSM_TwoWay) - continue; - - ospf_bfd_reg_dereg_nbr(nbr, command); - } - } - - return 0; + struct ospf_interface *oi; + struct route_table *nbrs; + struct ospf_neighbor *nbr; + struct route_node *irn; + struct route_node *nrn; + + for (irn = route_top(IF_OIFS(ifp)); irn; irn = route_next(irn)) { + if ((oi = irn->info) == NULL) + continue; + + if ((nbrs = oi->nbrs) == NULL) + continue; + + for (nrn = route_top(nbrs); nrn; nrn = route_next(nrn)) { + if ((nbr = nrn->info) == NULL || nbr == oi->nbr_self) + continue; + + if (command != ZEBRA_BFD_DEST_DEREGISTER) + ospf_bfd_info_nbr_create(oi, nbr); + else + bfd_info_free( + (struct bfd_info **)&nbr->bfd_info); + + if (nbr->state < NSM_TwoWay) + continue; + + ospf_bfd_reg_dereg_nbr(nbr, command); + } + } + + return 0; } /* * ospf_bfd_nbr_replay - Replay all the neighbors that have BFD enabled * to zebra */ -static int -ospf_bfd_nbr_replay (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int ospf_bfd_nbr_replay(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct listnode *inode, *node, *onode; - struct ospf *ospf; - struct ospf_interface *oi; - struct route_table *nbrs; - struct route_node *rn; - struct ospf_neighbor *nbr; - struct ospf_if_params *params; - - if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) - { - zlog_debug("Zebra: BFD Dest replay request"); - } - - /* Send the client registration */ - bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); - - /* Replay the neighbor, if BFD is enabled in BGP */ - for (ALL_LIST_ELEMENTS (om->ospf, node, onode, ospf)) - { - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, inode, oi)) - { - if ((nbrs = oi->nbrs) == NULL) - continue; - - params = IF_DEF_PARAMS (oi->ifp); - if (!params->bfd_info) - continue; - - for (rn = route_top (nbrs); rn; rn = route_next (rn)) - { - if ((nbr = rn->info) == NULL || nbr == oi->nbr_self) - continue; - - if (nbr->state < NSM_TwoWay) - continue; - - if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) - zlog_debug ("Replaying nbr (%s) to BFD", inet_ntoa (nbr->src)); - - ospf_bfd_reg_dereg_nbr(nbr, ZEBRA_BFD_DEST_UPDATE); - } - } - } - return 0; + struct listnode *inode, *node, *onode; + struct ospf *ospf; + struct ospf_interface *oi; + struct route_table *nbrs; + struct route_node *rn; + struct ospf_neighbor *nbr; + struct ospf_if_params *params; + + if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) { + zlog_debug("Zebra: BFD Dest replay request"); + } + + /* Send the client registration */ + bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); + + /* Replay the neighbor, if BFD is enabled in BGP */ + for (ALL_LIST_ELEMENTS(om->ospf, node, onode, ospf)) { + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, inode, oi)) { + if ((nbrs = oi->nbrs) == NULL) + continue; + + params = IF_DEF_PARAMS(oi->ifp); + if (!params->bfd_info) + continue; + + for (rn = route_top(nbrs); rn; rn = route_next(rn)) { + if ((nbr = rn->info) == NULL + || nbr == oi->nbr_self) + continue; + + if (nbr->state < NSM_TwoWay) + continue; + + if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) + zlog_debug("Replaying nbr (%s) to BFD", + inet_ntoa(nbr->src)); + + ospf_bfd_reg_dereg_nbr(nbr, + ZEBRA_BFD_DEST_UPDATE); + } + } + } + return 0; } /* @@ -201,163 +194,160 @@ ospf_bfd_nbr_replay (int command, struct zclient *zclient, zebra_size_t length, * connectivity if the BFD status changed to * down. */ -static int -ospf_bfd_interface_dest_update (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int ospf_bfd_interface_dest_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - struct ospf_interface *oi; - struct ospf_if_params *params; - struct ospf_neighbor *nbr; - struct route_node *node; - struct prefix p; - int status; - int old_status; - struct bfd_info *bfd_info; - struct timeval tv; - - ifp = bfd_get_peer_info (zclient->ibuf, &p, NULL, &status, vrf_id); - - if ((ifp == NULL) || (p.family != AF_INET)) - return 0; - - if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str(&p, buf, sizeof(buf)); - zlog_debug("Zebra: interface %s bfd destination %s %s", ifp->name, buf, - bfd_get_status_str(status)); - } - - params = IF_DEF_PARAMS (ifp); - if (!params->bfd_info) - return 0; - - for (node = route_top (IF_OIFS (ifp)); node; node = route_next (node)) - { - if ((oi = node->info) == NULL) - continue; - - nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &p.u.prefix4); - if (!nbr || !nbr->bfd_info) - continue; - - bfd_info = (struct bfd_info *)nbr->bfd_info; - if (bfd_info->status == status) - continue; - - old_status = bfd_info->status; - bfd_info->status = status; - monotime(&tv); - bfd_info->last_update = tv.tv_sec; - - if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP)) - { - if (IS_DEBUG_OSPF (nsm, NSM_EVENTS)) - zlog_debug ("NSM[%s:%s]: BFD Down", - IF_NAME (nbr->oi), inet_ntoa (nbr->address.u.prefix4)); - - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_InactivityTimer); - } - } - - return 0; + struct interface *ifp; + struct ospf_interface *oi; + struct ospf_if_params *params; + struct ospf_neighbor *nbr; + struct route_node *node; + struct prefix p; + int status; + int old_status; + struct bfd_info *bfd_info; + struct timeval tv; + + ifp = bfd_get_peer_info(zclient->ibuf, &p, NULL, &status, vrf_id); + + if ((ifp == NULL) || (p.family != AF_INET)) + return 0; + + if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&p, buf, sizeof(buf)); + zlog_debug("Zebra: interface %s bfd destination %s %s", + ifp->name, buf, bfd_get_status_str(status)); + } + + params = IF_DEF_PARAMS(ifp); + if (!params->bfd_info) + return 0; + + for (node = route_top(IF_OIFS(ifp)); node; node = route_next(node)) { + if ((oi = node->info) == NULL) + continue; + + nbr = ospf_nbr_lookup_by_addr(oi->nbrs, &p.u.prefix4); + if (!nbr || !nbr->bfd_info) + continue; + + bfd_info = (struct bfd_info *)nbr->bfd_info; + if (bfd_info->status == status) + continue; + + old_status = bfd_info->status; + bfd_info->status = status; + monotime(&tv); + bfd_info->last_update = tv.tv_sec; + + if ((status == BFD_STATUS_DOWN) + && (old_status == BFD_STATUS_UP)) { + if (IS_DEBUG_OSPF(nsm, NSM_EVENTS)) + zlog_debug("NSM[%s:%s]: BFD Down", + IF_NAME(nbr->oi), + inet_ntoa(nbr->address.u.prefix4)); + + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_InactivityTimer); + } + } + + return 0; } /* * ospf_bfd_info_nbr_create - Create/update BFD information for a neighbor. */ -void -ospf_bfd_info_nbr_create (struct ospf_interface *oi, struct ospf_neighbor *nbr) +void ospf_bfd_info_nbr_create(struct ospf_interface *oi, + struct ospf_neighbor *nbr) { - struct bfd_info *oi_bfd_info; - struct bfd_info *nbr_bfd_info; - struct interface *ifp = oi->ifp; - struct ospf_if_params *params; - - /* Check if BFD is enabled */ - params = IF_DEF_PARAMS (ifp); - - /* Check if BFD is enabled */ - if (!params->bfd_info) - return; - - oi_bfd_info = (struct bfd_info *)params->bfd_info; - if (!nbr->bfd_info) - nbr->bfd_info = bfd_info_create(); - - nbr_bfd_info = (struct bfd_info *)nbr->bfd_info; - nbr_bfd_info->detect_mult = oi_bfd_info->detect_mult; - nbr_bfd_info->desired_min_tx = oi_bfd_info->desired_min_tx; - nbr_bfd_info->required_min_rx = oi_bfd_info->required_min_rx; + struct bfd_info *oi_bfd_info; + struct bfd_info *nbr_bfd_info; + struct interface *ifp = oi->ifp; + struct ospf_if_params *params; + + /* Check if BFD is enabled */ + params = IF_DEF_PARAMS(ifp); + + /* Check if BFD is enabled */ + if (!params->bfd_info) + return; + + oi_bfd_info = (struct bfd_info *)params->bfd_info; + if (!nbr->bfd_info) + nbr->bfd_info = bfd_info_create(); + + nbr_bfd_info = (struct bfd_info *)nbr->bfd_info; + nbr_bfd_info->detect_mult = oi_bfd_info->detect_mult; + nbr_bfd_info->desired_min_tx = oi_bfd_info->desired_min_tx; + nbr_bfd_info->required_min_rx = oi_bfd_info->required_min_rx; } /* * ospf_bfd_write_config - Write the interface BFD configuration. */ -void -ospf_bfd_write_config(struct vty *vty, struct ospf_if_params *params) +void ospf_bfd_write_config(struct vty *vty, struct ospf_if_params *params) { - struct bfd_info *bfd_info; + struct bfd_info *bfd_info; - if (!params->bfd_info) - return; + if (!params->bfd_info) + return; - bfd_info = (struct bfd_info *)params->bfd_info; + bfd_info = (struct bfd_info *)params->bfd_info; - if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) - vty_out (vty, " ip ospf bfd %d %d %d\n", - bfd_info->detect_mult, bfd_info->required_min_rx, - bfd_info->desired_min_tx); - else - vty_out (vty, " ip ospf bfd\n"); + if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) + vty_out(vty, " ip ospf bfd %d %d %d\n", bfd_info->detect_mult, + bfd_info->required_min_rx, bfd_info->desired_min_tx); + else + vty_out(vty, " ip ospf bfd\n"); } /* * ospf_bfd_show_info - Show BFD info structure */ -void -ospf_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj, - u_char use_json, int param_only) +void ospf_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj, + u_char use_json, int param_only) { - if (param_only) - bfd_show_param(vty, (struct bfd_info *)bfd_info, 1, 0, use_json, json_obj); - else - bfd_show_info(vty, (struct bfd_info *)bfd_info, 0, 1, use_json, json_obj); + if (param_only) + bfd_show_param(vty, (struct bfd_info *)bfd_info, 1, 0, use_json, + json_obj); + else + bfd_show_info(vty, (struct bfd_info *)bfd_info, 0, 1, use_json, + json_obj); } /* * ospf_bfd_interface_show - Show the interface BFD configuration. */ -void -ospf_bfd_interface_show(struct vty *vty, struct interface *ifp, - json_object *json_interface_sub, u_char use_json) +void ospf_bfd_interface_show(struct vty *vty, struct interface *ifp, + json_object *json_interface_sub, u_char use_json) { - struct ospf_if_params *params; + struct ospf_if_params *params; - params = IF_DEF_PARAMS (ifp); + params = IF_DEF_PARAMS(ifp); - ospf_bfd_show_info(vty, params->bfd_info, json_interface_sub, use_json, 1); + ospf_bfd_show_info(vty, params->bfd_info, json_interface_sub, use_json, + 1); } /* * ospf_bfd_if_param_set - Set the configured BFD paramter values for * interface. */ -static void -ospf_bfd_if_param_set (struct interface *ifp, u_int32_t min_rx, - u_int32_t min_tx, u_int8_t detect_mult, int defaults) +static void ospf_bfd_if_param_set(struct interface *ifp, u_int32_t min_rx, + u_int32_t min_tx, u_int8_t detect_mult, + int defaults) { - struct ospf_if_params *params; - int command = 0; + struct ospf_if_params *params; + int command = 0; - params = IF_DEF_PARAMS (ifp); + params = IF_DEF_PARAMS(ifp); - bfd_set_param((struct bfd_info **)&(params->bfd_info), min_rx, min_tx, - detect_mult, defaults, &command); - if (command) - ospf_bfd_reg_dereg_all_nbr(ifp, command); + bfd_set_param((struct bfd_info **)&(params->bfd_info), min_rx, min_tx, + detect_mult, defaults, &command); + if (command) + ospf_bfd_reg_dereg_all_nbr(ifp, command); } DEFUN (ip_ospf_bfd, @@ -367,19 +357,19 @@ DEFUN (ip_ospf_bfd, "OSPF interface commands\n" "Enables BFD support\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct ospf_if_params *params; - struct bfd_info *bfd_info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf_if_params *params; + struct bfd_info *bfd_info; - assert (ifp); - params = IF_DEF_PARAMS (ifp); - bfd_info = params->bfd_info; + assert(ifp); + params = IF_DEF_PARAMS(ifp); + bfd_info = params->bfd_info; - if (!bfd_info || ! CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) - ospf_bfd_if_param_set (ifp, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, - BFD_DEF_DETECT_MULT, 1); + if (!bfd_info || !CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) + ospf_bfd_if_param_set(ifp, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, + BFD_DEF_DETECT_MULT, 1); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_ospf_bfd_param, @@ -392,24 +382,26 @@ DEFUN (ip_ospf_bfd_param, "Required min receive interval\n" "Desired min transmit interval\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_number = 3; - int idx_number_2 = 4; - int idx_number_3 = 5; - u_int32_t rx_val; - u_int32_t tx_val; - u_int8_t dm_val; - int ret; - - assert (ifp); - - if ((ret = bfd_validate_param (vty, argv[idx_number]->arg, argv[idx_number_2]->arg, argv[idx_number_3]->arg, &dm_val, - &rx_val, &tx_val)) != CMD_SUCCESS) - return ret; - - ospf_bfd_if_param_set (ifp, rx_val, tx_val, dm_val, 0); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_number = 3; + int idx_number_2 = 4; + int idx_number_3 = 5; + u_int32_t rx_val; + u_int32_t tx_val; + u_int8_t dm_val; + int ret; + + assert(ifp); + + if ((ret = bfd_validate_param( + vty, argv[idx_number]->arg, argv[idx_number_2]->arg, + argv[idx_number_3]->arg, &dm_val, &rx_val, &tx_val)) + != CMD_SUCCESS) + return ret; + + ospf_bfd_if_param_set(ifp, rx_val, tx_val, dm_val, 0); + + return CMD_SUCCESS; } DEFUN (no_ip_ospf_bfd, @@ -423,32 +415,30 @@ DEFUN (no_ip_ospf_bfd, "Required min receive interval\n" "Desired min transmit interval\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct ospf_if_params *params; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf_if_params *params; - assert (ifp); + assert(ifp); - params = IF_DEF_PARAMS (ifp); - if (params->bfd_info) - { - ospf_bfd_reg_dereg_all_nbr(ifp, ZEBRA_BFD_DEST_DEREGISTER); - bfd_info_free(&(params->bfd_info)); - } + params = IF_DEF_PARAMS(ifp); + if (params->bfd_info) { + ospf_bfd_reg_dereg_all_nbr(ifp, ZEBRA_BFD_DEST_DEREGISTER); + bfd_info_free(&(params->bfd_info)); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } -void -ospf_bfd_init(void) +void ospf_bfd_init(void) { - bfd_gbl_init(); + bfd_gbl_init(); - /* Initialize BFD client functions */ - zclient->interface_bfd_dest_update = ospf_bfd_interface_dest_update; - zclient->bfd_dest_replay = ospf_bfd_nbr_replay; + /* Initialize BFD client functions */ + zclient->interface_bfd_dest_update = ospf_bfd_interface_dest_update; + zclient->bfd_dest_replay = ospf_bfd_nbr_replay; - /* Install BFD command */ - install_element (INTERFACE_NODE, &ip_ospf_bfd_cmd); - install_element (INTERFACE_NODE, &ip_ospf_bfd_param_cmd); - install_element (INTERFACE_NODE, &no_ip_ospf_bfd_cmd); + /* Install BFD command */ + install_element(INTERFACE_NODE, &ip_ospf_bfd_cmd); + install_element(INTERFACE_NODE, &ip_ospf_bfd_param_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_bfd_cmd); } diff --git a/ospfd/ospf_bfd.h b/ospfd/ospf_bfd.h index 75b8e11f4..c940f31eb 100644 --- a/ospfd/ospf_bfd.h +++ b/ospfd/ospf_bfd.h @@ -25,27 +25,25 @@ #include "json.h" -extern void -ospf_bfd_init(void); +extern void ospf_bfd_init(void); -extern void -ospf_bfd_write_config(struct vty *vty, struct ospf_if_params *params); +extern void ospf_bfd_write_config(struct vty *vty, + struct ospf_if_params *params); -extern void -ospf_bfd_trigger_event(struct ospf_neighbor *nbr, int old_state, int state); +extern void ospf_bfd_trigger_event(struct ospf_neighbor *nbr, int old_state, + int state); -extern void -ospf_bfd_interface_show(struct vty *vty, struct interface *ifp, - json_object *json_interface_sub, u_char use_json); +extern void ospf_bfd_interface_show(struct vty *vty, struct interface *ifp, + json_object *json_interface_sub, + u_char use_json); -extern void -ospf_bfd_info_nbr_create (struct ospf_interface *oi, struct ospf_neighbor *nbr); +extern void ospf_bfd_info_nbr_create(struct ospf_interface *oi, + struct ospf_neighbor *nbr); -extern void -ospf_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj, - u_char use_json, int param_only); +extern void ospf_bfd_show_info(struct vty *vty, void *bfd_info, + json_object *json_obj, u_char use_json, + int param_only); -extern void -ospf_bfd_info_free(void **bfd_info); +extern void ospf_bfd_info_free(void **bfd_info); #endif /* _ZEBRA_OSPF_BFD_H */ diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index f233f79c0..c0670012b 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -63,574 +63,539 @@ unsigned long term_debug_ospf_nssa = 0; unsigned long term_debug_ospf_te = 0; -const char * -ospf_redist_string(u_int route_type) +const char *ospf_redist_string(u_int route_type) { - return (route_type == ZEBRA_ROUTE_MAX) ? - "Default" : zebra_route_string(route_type); + return (route_type == ZEBRA_ROUTE_MAX) ? "Default" + : zebra_route_string(route_type); } #define OSPF_AREA_STRING_MAXLEN 16 -const char * -ospf_area_name_string (struct ospf_area *area) +const char *ospf_area_name_string(struct ospf_area *area) { - static char buf[OSPF_AREA_STRING_MAXLEN] = ""; - u_int32_t area_id; + static char buf[OSPF_AREA_STRING_MAXLEN] = ""; + u_int32_t area_id; - if (!area) - return "-"; + if (!area) + return "-"; - area_id = ntohl (area->area_id.s_addr); - snprintf (buf, OSPF_AREA_STRING_MAXLEN, "%d.%d.%d.%d", - (area_id >> 24) & 0xff, (area_id >> 16) & 0xff, - (area_id >> 8) & 0xff, area_id & 0xff); - return buf; + area_id = ntohl(area->area_id.s_addr); + snprintf(buf, OSPF_AREA_STRING_MAXLEN, "%d.%d.%d.%d", + (area_id >> 24) & 0xff, (area_id >> 16) & 0xff, + (area_id >> 8) & 0xff, area_id & 0xff); + return buf; } #define OSPF_AREA_DESC_STRING_MAXLEN 23 -const char * -ospf_area_desc_string (struct ospf_area *area) +const char *ospf_area_desc_string(struct ospf_area *area) { - static char buf[OSPF_AREA_DESC_STRING_MAXLEN] = ""; - u_char type; - - if (!area) - return "(incomplete)"; - - type = area->external_routing; - switch (type) - { - case OSPF_AREA_NSSA: - snprintf (buf, OSPF_AREA_DESC_STRING_MAXLEN, "%s [NSSA]", - ospf_area_name_string (area)); - break; - case OSPF_AREA_STUB: - snprintf (buf, OSPF_AREA_DESC_STRING_MAXLEN, "%s [Stub]", - ospf_area_name_string (area)); - break; - default: - return ospf_area_name_string (area); - } - - return buf; + static char buf[OSPF_AREA_DESC_STRING_MAXLEN] = ""; + u_char type; + + if (!area) + return "(incomplete)"; + + type = area->external_routing; + switch (type) { + case OSPF_AREA_NSSA: + snprintf(buf, OSPF_AREA_DESC_STRING_MAXLEN, "%s [NSSA]", + ospf_area_name_string(area)); + break; + case OSPF_AREA_STUB: + snprintf(buf, OSPF_AREA_DESC_STRING_MAXLEN, "%s [Stub]", + ospf_area_name_string(area)); + break; + default: + return ospf_area_name_string(area); + } + + return buf; } #define OSPF_IF_STRING_MAXLEN 40 -const char * -ospf_if_name_string (struct ospf_interface *oi) +const char *ospf_if_name_string(struct ospf_interface *oi) { - static char buf[OSPF_IF_STRING_MAXLEN] = ""; - u_int32_t ifaddr; + static char buf[OSPF_IF_STRING_MAXLEN] = ""; + u_int32_t ifaddr; - if (!oi || !oi->address) - return "inactive"; + if (!oi || !oi->address) + return "inactive"; - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - return oi->ifp->name; + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + return oi->ifp->name; - ifaddr = ntohl (oi->address->u.prefix4.s_addr); - snprintf (buf, OSPF_IF_STRING_MAXLEN, - "%s:%d.%d.%d.%d", oi->ifp->name, - (ifaddr >> 24) & 0xff, (ifaddr >> 16) & 0xff, - (ifaddr >> 8) & 0xff, ifaddr & 0xff); - return buf; + ifaddr = ntohl(oi->address->u.prefix4.s_addr); + snprintf(buf, OSPF_IF_STRING_MAXLEN, "%s:%d.%d.%d.%d", oi->ifp->name, + (ifaddr >> 24) & 0xff, (ifaddr >> 16) & 0xff, + (ifaddr >> 8) & 0xff, ifaddr & 0xff); + return buf; } -void -ospf_nbr_state_message (struct ospf_neighbor *nbr, char *buf, size_t size) +void ospf_nbr_state_message(struct ospf_neighbor *nbr, char *buf, size_t size) { - int state; - struct ospf_interface *oi = nbr->oi; + int state; + struct ospf_interface *oi = nbr->oi; - if (IPV4_ADDR_SAME (&DR (oi), &nbr->address.u.prefix4)) - state = ISM_DR; - else if (IPV4_ADDR_SAME (&BDR (oi), &nbr->address.u.prefix4)) - state = ISM_Backup; - else - state = ISM_DROther; + if (IPV4_ADDR_SAME(&DR(oi), &nbr->address.u.prefix4)) + state = ISM_DR; + else if (IPV4_ADDR_SAME(&BDR(oi), &nbr->address.u.prefix4)) + state = ISM_Backup; + else + state = ISM_DROther; - memset (buf, 0, size); + memset(buf, 0, size); - snprintf (buf, size, "%s/%s", - lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), - lookup_msg(ospf_ism_state_msg, state, NULL)); + snprintf(buf, size, "%s/%s", + lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), + lookup_msg(ospf_ism_state_msg, state, NULL)); } -const char * -ospf_timeval_dump (struct timeval *t, char *buf, size_t size) +const char *ospf_timeval_dump(struct timeval *t, char *buf, size_t size) { - /* Making formatted timer strings. */ +/* Making formatted timer strings. */ #define MINUTE_IN_SECONDS 60 #define HOUR_IN_SECONDS (60*MINUTE_IN_SECONDS) #define DAY_IN_SECONDS (24*HOUR_IN_SECONDS) #define WEEK_IN_SECONDS (7*DAY_IN_SECONDS) - unsigned long w, d, h, m, s, ms, us; - - if (!t) - return "inactive"; - - w = d = h = m = s = ms = us = 0; - memset (buf, 0, size); - - us = t->tv_usec; - if (us >= 1000) - { - ms = us / 1000; - us %= 1000; - } - - if (ms >= 1000) - { - t->tv_sec += ms / 1000; - ms %= 1000; - } - - if (t->tv_sec > WEEK_IN_SECONDS) - { - w = t->tv_sec / WEEK_IN_SECONDS; - t->tv_sec -= w * WEEK_IN_SECONDS; - } - - if (t->tv_sec > DAY_IN_SECONDS) - { - d = t->tv_sec / DAY_IN_SECONDS; - t->tv_sec -= d * DAY_IN_SECONDS; - } - - if (t->tv_sec >= HOUR_IN_SECONDS) - { - h = t->tv_sec / HOUR_IN_SECONDS; - t->tv_sec -= h * HOUR_IN_SECONDS; - } - - if (t->tv_sec >= MINUTE_IN_SECONDS) - { - m = t->tv_sec / MINUTE_IN_SECONDS; - t->tv_sec -= m * MINUTE_IN_SECONDS; - } - - if (w > 99) - snprintf (buf, size, "%ldw%1ldd", w, d); - else if (w) - snprintf (buf, size, "%ldw%1ldd%02ldh", w, d, h); - else if (d) - snprintf (buf, size, "%1ldd%02ldh%02ldm", d, h, m); - else if (h) - snprintf (buf, size, "%ldh%02ldm%02lds", h, m, (long)t->tv_sec); - else if (m) - snprintf (buf, size, "%ldm%02lds", m, (long)t->tv_sec); - else if (ms) - snprintf (buf, size, "%ld.%03lds", (long)t->tv_sec, ms); - else - snprintf (buf, size, "%ld usecs", (long)t->tv_usec); - - return buf; + unsigned long w, d, h, m, s, ms, us; + + if (!t) + return "inactive"; + + w = d = h = m = s = ms = us = 0; + memset(buf, 0, size); + + us = t->tv_usec; + if (us >= 1000) { + ms = us / 1000; + us %= 1000; + } + + if (ms >= 1000) { + t->tv_sec += ms / 1000; + ms %= 1000; + } + + if (t->tv_sec > WEEK_IN_SECONDS) { + w = t->tv_sec / WEEK_IN_SECONDS; + t->tv_sec -= w * WEEK_IN_SECONDS; + } + + if (t->tv_sec > DAY_IN_SECONDS) { + d = t->tv_sec / DAY_IN_SECONDS; + t->tv_sec -= d * DAY_IN_SECONDS; + } + + if (t->tv_sec >= HOUR_IN_SECONDS) { + h = t->tv_sec / HOUR_IN_SECONDS; + t->tv_sec -= h * HOUR_IN_SECONDS; + } + + if (t->tv_sec >= MINUTE_IN_SECONDS) { + m = t->tv_sec / MINUTE_IN_SECONDS; + t->tv_sec -= m * MINUTE_IN_SECONDS; + } + + if (w > 99) + snprintf(buf, size, "%ldw%1ldd", w, d); + else if (w) + snprintf(buf, size, "%ldw%1ldd%02ldh", w, d, h); + else if (d) + snprintf(buf, size, "%1ldd%02ldh%02ldm", d, h, m); + else if (h) + snprintf(buf, size, "%ldh%02ldm%02lds", h, m, (long)t->tv_sec); + else if (m) + snprintf(buf, size, "%ldm%02lds", m, (long)t->tv_sec); + else if (ms) + snprintf(buf, size, "%ld.%03lds", (long)t->tv_sec, ms); + else + snprintf(buf, size, "%ld usecs", (long)t->tv_usec); + + return buf; } -const char * -ospf_timer_dump (struct thread *t, char *buf, size_t size) +const char *ospf_timer_dump(struct thread *t, char *buf, size_t size) { - struct timeval result; - if (!t) - return "inactive"; + struct timeval result; + if (!t) + return "inactive"; - monotime_until (&t->u.sands, &result); - return ospf_timeval_dump (&result, buf, size); + monotime_until(&t->u.sands, &result); + return ospf_timeval_dump(&result, buf, size); } -static void -ospf_packet_hello_dump (struct stream *s, u_int16_t length) +static void ospf_packet_hello_dump(struct stream *s, u_int16_t length) { - struct ospf_hello *hello; - int i; - - hello = (struct ospf_hello *) STREAM_PNT (s); - - zlog_debug ("Hello"); - zlog_debug (" NetworkMask %s", inet_ntoa (hello->network_mask)); - zlog_debug (" HelloInterval %d", ntohs (hello->hello_interval)); - zlog_debug (" Options %d (%s)", hello->options, - ospf_options_dump (hello->options)); - zlog_debug (" RtrPriority %d", hello->priority); - zlog_debug (" RtrDeadInterval %ld", (u_long)ntohl (hello->dead_interval)); - zlog_debug (" DRouter %s", inet_ntoa (hello->d_router)); - zlog_debug (" BDRouter %s", inet_ntoa (hello->bd_router)); - - length -= OSPF_HEADER_SIZE + OSPF_HELLO_MIN_SIZE; - zlog_debug (" # Neighbors %d", length / 4); - for (i = 0; length > 0; i++, length -= sizeof (struct in_addr)) - zlog_debug (" Neighbor %s", inet_ntoa (hello->neighbors[i])); + struct ospf_hello *hello; + int i; + + hello = (struct ospf_hello *)STREAM_PNT(s); + + zlog_debug("Hello"); + zlog_debug(" NetworkMask %s", inet_ntoa(hello->network_mask)); + zlog_debug(" HelloInterval %d", ntohs(hello->hello_interval)); + zlog_debug(" Options %d (%s)", hello->options, + ospf_options_dump(hello->options)); + zlog_debug(" RtrPriority %d", hello->priority); + zlog_debug(" RtrDeadInterval %ld", + (u_long)ntohl(hello->dead_interval)); + zlog_debug(" DRouter %s", inet_ntoa(hello->d_router)); + zlog_debug(" BDRouter %s", inet_ntoa(hello->bd_router)); + + length -= OSPF_HEADER_SIZE + OSPF_HELLO_MIN_SIZE; + zlog_debug(" # Neighbors %d", length / 4); + for (i = 0; length > 0; i++, length -= sizeof(struct in_addr)) + zlog_debug(" Neighbor %s", inet_ntoa(hello->neighbors[i])); } -static char * -ospf_dd_flags_dump (u_char flags, char *buf, size_t size) +static char *ospf_dd_flags_dump(u_char flags, char *buf, size_t size) { - memset (buf, 0, size); + memset(buf, 0, size); - snprintf (buf, size, "%s|%s|%s", - (flags & OSPF_DD_FLAG_I) ? "I" : "-", - (flags & OSPF_DD_FLAG_M) ? "M" : "-", - (flags & OSPF_DD_FLAG_MS) ? "MS" : "-"); + snprintf(buf, size, "%s|%s|%s", (flags & OSPF_DD_FLAG_I) ? "I" : "-", + (flags & OSPF_DD_FLAG_M) ? "M" : "-", + (flags & OSPF_DD_FLAG_MS) ? "MS" : "-"); - return buf; + return buf; } -static char * -ospf_router_lsa_flags_dump (u_char flags, char *buf, size_t size) +static char *ospf_router_lsa_flags_dump(u_char flags, char *buf, size_t size) { - memset (buf, 0, size); + memset(buf, 0, size); - snprintf (buf, size, "%s|%s|%s", - (flags & ROUTER_LSA_VIRTUAL) ? "V" : "-", - (flags & ROUTER_LSA_EXTERNAL) ? "E" : "-", - (flags & ROUTER_LSA_BORDER) ? "B" : "-"); + snprintf(buf, size, "%s|%s|%s", + (flags & ROUTER_LSA_VIRTUAL) ? "V" : "-", + (flags & ROUTER_LSA_EXTERNAL) ? "E" : "-", + (flags & ROUTER_LSA_BORDER) ? "B" : "-"); - return buf; + return buf; } -static void -ospf_router_lsa_dump (struct stream *s, u_int16_t length) +static void ospf_router_lsa_dump(struct stream *s, u_int16_t length) { - char buf[BUFSIZ]; - struct router_lsa *rl; - int i, len; - - rl = (struct router_lsa *) STREAM_PNT (s); - - zlog_debug (" Router-LSA"); - zlog_debug (" flags %s", - ospf_router_lsa_flags_dump (rl->flags, buf, BUFSIZ)); - zlog_debug (" # links %d", ntohs (rl->links)); - - len = ntohs (rl->header.length) - OSPF_LSA_HEADER_SIZE - 4; - for (i = 0; len > 0; i++) - { - zlog_debug (" Link ID %s", inet_ntoa (rl->link[i].link_id)); - zlog_debug (" Link Data %s", inet_ntoa (rl->link[i].link_data)); - zlog_debug (" Type %d", (u_char) rl->link[i].type); - zlog_debug (" TOS %d", (u_char) rl->link[i].tos); - zlog_debug (" metric %d", ntohs (rl->link[i].metric)); - - len -= 12; - } + char buf[BUFSIZ]; + struct router_lsa *rl; + int i, len; + + rl = (struct router_lsa *)STREAM_PNT(s); + + zlog_debug(" Router-LSA"); + zlog_debug(" flags %s", + ospf_router_lsa_flags_dump(rl->flags, buf, BUFSIZ)); + zlog_debug(" # links %d", ntohs(rl->links)); + + len = ntohs(rl->header.length) - OSPF_LSA_HEADER_SIZE - 4; + for (i = 0; len > 0; i++) { + zlog_debug(" Link ID %s", inet_ntoa(rl->link[i].link_id)); + zlog_debug(" Link Data %s", + inet_ntoa(rl->link[i].link_data)); + zlog_debug(" Type %d", (u_char)rl->link[i].type); + zlog_debug(" TOS %d", (u_char)rl->link[i].tos); + zlog_debug(" metric %d", ntohs(rl->link[i].metric)); + + len -= 12; + } } -static void -ospf_network_lsa_dump (struct stream *s, u_int16_t length) +static void ospf_network_lsa_dump(struct stream *s, u_int16_t length) { - struct network_lsa *nl; - int i, cnt; - - nl = (struct network_lsa *) STREAM_PNT (s); - cnt = (ntohs (nl->header.length) - (OSPF_LSA_HEADER_SIZE + 4)) / 4; - - zlog_debug (" Network-LSA"); - /* - zlog_debug ("LSA total size %d", ntohs (nl->header.length)); - zlog_debug ("Network-LSA size %d", - ntohs (nl->header.length) - OSPF_LSA_HEADER_SIZE); - */ - zlog_debug (" Network Mask %s", inet_ntoa (nl->mask)); - zlog_debug (" # Attached Routers %d", cnt); - for (i = 0; i < cnt; i++) - zlog_debug (" Attached Router %s", inet_ntoa (nl->routers[i])); + struct network_lsa *nl; + int i, cnt; + + nl = (struct network_lsa *)STREAM_PNT(s); + cnt = (ntohs(nl->header.length) - (OSPF_LSA_HEADER_SIZE + 4)) / 4; + + zlog_debug(" Network-LSA"); + /* + zlog_debug ("LSA total size %d", ntohs (nl->header.length)); + zlog_debug ("Network-LSA size %d", + ntohs (nl->header.length) - OSPF_LSA_HEADER_SIZE); + */ + zlog_debug(" Network Mask %s", inet_ntoa(nl->mask)); + zlog_debug(" # Attached Routers %d", cnt); + for (i = 0; i < cnt; i++) + zlog_debug(" Attached Router %s", + inet_ntoa(nl->routers[i])); } -static void -ospf_summary_lsa_dump (struct stream *s, u_int16_t length) +static void ospf_summary_lsa_dump(struct stream *s, u_int16_t length) { - struct summary_lsa *sl; - int size; - int i; + struct summary_lsa *sl; + int size; + int i; - sl = (struct summary_lsa *) STREAM_PNT (s); + sl = (struct summary_lsa *)STREAM_PNT(s); - zlog_debug (" Summary-LSA"); - zlog_debug (" Network Mask %s", inet_ntoa (sl->mask)); + zlog_debug(" Summary-LSA"); + zlog_debug(" Network Mask %s", inet_ntoa(sl->mask)); - size = ntohs (sl->header.length) - OSPF_LSA_HEADER_SIZE - 4; - for (i = 0; size > 0; size -= 4, i++) - zlog_debug (" TOS=%d metric %d", sl->tos, - GET_METRIC (sl->metric)); + size = ntohs(sl->header.length) - OSPF_LSA_HEADER_SIZE - 4; + for (i = 0; size > 0; size -= 4, i++) + zlog_debug(" TOS=%d metric %d", sl->tos, + GET_METRIC(sl->metric)); } -static void -ospf_as_external_lsa_dump (struct stream *s, u_int16_t length) +static void ospf_as_external_lsa_dump(struct stream *s, u_int16_t length) { - struct as_external_lsa *al; - int size; - int i; - - al = (struct as_external_lsa *) STREAM_PNT (s); - zlog_debug (" %s", ospf_lsa_type_msg[al->header.type].str); - zlog_debug (" Network Mask %s", inet_ntoa (al->mask)); - - size = ntohs (al->header.length) - OSPF_LSA_HEADER_SIZE -4; - for (i = 0; size > 0; size -= 12, i++) - { - zlog_debug (" bit %s TOS=%d metric %d", - IS_EXTERNAL_METRIC (al->e[i].tos) ? "E" : "-", - al->e[i].tos & 0x7f, GET_METRIC (al->e[i].metric)); - zlog_debug (" Forwarding address %s", inet_ntoa (al->e[i].fwd_addr)); - zlog_debug (" External Route Tag %"ROUTE_TAG_PRI, al->e[i].route_tag); - } + struct as_external_lsa *al; + int size; + int i; + + al = (struct as_external_lsa *)STREAM_PNT(s); + zlog_debug(" %s", ospf_lsa_type_msg[al->header.type].str); + zlog_debug(" Network Mask %s", inet_ntoa(al->mask)); + + size = ntohs(al->header.length) - OSPF_LSA_HEADER_SIZE - 4; + for (i = 0; size > 0; size -= 12, i++) { + zlog_debug(" bit %s TOS=%d metric %d", + IS_EXTERNAL_METRIC(al->e[i].tos) ? "E" : "-", + al->e[i].tos & 0x7f, GET_METRIC(al->e[i].metric)); + zlog_debug(" Forwarding address %s", + inet_ntoa(al->e[i].fwd_addr)); + zlog_debug(" External Route Tag %" ROUTE_TAG_PRI, + al->e[i].route_tag); + } } -static void -ospf_lsa_header_list_dump (struct stream *s, u_int16_t length) +static void ospf_lsa_header_list_dump(struct stream *s, u_int16_t length) { - struct lsa_header *lsa; + struct lsa_header *lsa; - zlog_debug (" # LSA Headers %d", length / OSPF_LSA_HEADER_SIZE); + zlog_debug(" # LSA Headers %d", length / OSPF_LSA_HEADER_SIZE); - /* LSA Headers. */ - while (length > 0) - { - lsa = (struct lsa_header *) STREAM_PNT (s); - ospf_lsa_header_dump (lsa); + /* LSA Headers. */ + while (length > 0) { + lsa = (struct lsa_header *)STREAM_PNT(s); + ospf_lsa_header_dump(lsa); - stream_forward_getp (s, OSPF_LSA_HEADER_SIZE); - length -= OSPF_LSA_HEADER_SIZE; - } + stream_forward_getp(s, OSPF_LSA_HEADER_SIZE); + length -= OSPF_LSA_HEADER_SIZE; + } } -static void -ospf_packet_db_desc_dump (struct stream *s, u_int16_t length) +static void ospf_packet_db_desc_dump(struct stream *s, u_int16_t length) { - struct ospf_db_desc *dd; - char dd_flags[8]; + struct ospf_db_desc *dd; + char dd_flags[8]; - u_int32_t gp; + u_int32_t gp; - gp = stream_get_getp (s); - dd = (struct ospf_db_desc *) STREAM_PNT (s); + gp = stream_get_getp(s); + dd = (struct ospf_db_desc *)STREAM_PNT(s); - zlog_debug ("Database Description"); - zlog_debug (" Interface MTU %d", ntohs (dd->mtu)); - zlog_debug (" Options %d (%s)", dd->options, - ospf_options_dump (dd->options)); - zlog_debug (" Flags %d (%s)", dd->flags, - ospf_dd_flags_dump (dd->flags, dd_flags, sizeof dd_flags)); - zlog_debug (" Sequence Number 0x%08lx", (u_long)ntohl (dd->dd_seqnum)); + zlog_debug("Database Description"); + zlog_debug(" Interface MTU %d", ntohs(dd->mtu)); + zlog_debug(" Options %d (%s)", dd->options, + ospf_options_dump(dd->options)); + zlog_debug(" Flags %d (%s)", dd->flags, + ospf_dd_flags_dump(dd->flags, dd_flags, sizeof dd_flags)); + zlog_debug(" Sequence Number 0x%08lx", (u_long)ntohl(dd->dd_seqnum)); - length -= OSPF_HEADER_SIZE + OSPF_DB_DESC_MIN_SIZE; + length -= OSPF_HEADER_SIZE + OSPF_DB_DESC_MIN_SIZE; - stream_forward_getp (s, OSPF_DB_DESC_MIN_SIZE); + stream_forward_getp(s, OSPF_DB_DESC_MIN_SIZE); - ospf_lsa_header_list_dump (s, length); + ospf_lsa_header_list_dump(s, length); - stream_set_getp (s, gp); + stream_set_getp(s, gp); } -static void -ospf_packet_ls_req_dump (struct stream *s, u_int16_t length) +static void ospf_packet_ls_req_dump(struct stream *s, u_int16_t length) { - u_int32_t sp; - u_int32_t ls_type; - struct in_addr ls_id; - struct in_addr adv_router; + u_int32_t sp; + u_int32_t ls_type; + struct in_addr ls_id; + struct in_addr adv_router; - sp = stream_get_getp (s); + sp = stream_get_getp(s); - length -= OSPF_HEADER_SIZE; + length -= OSPF_HEADER_SIZE; - zlog_debug ("Link State Request"); - zlog_debug (" # Requests %d", length / 12); + zlog_debug("Link State Request"); + zlog_debug(" # Requests %d", length / 12); - for (; length > 0; length -= 12) - { - ls_type = stream_getl (s); - ls_id.s_addr = stream_get_ipv4 (s); - adv_router.s_addr = stream_get_ipv4 (s); + for (; length > 0; length -= 12) { + ls_type = stream_getl(s); + ls_id.s_addr = stream_get_ipv4(s); + adv_router.s_addr = stream_get_ipv4(s); - zlog_debug (" LS type %d", ls_type); - zlog_debug (" Link State ID %s", inet_ntoa (ls_id)); - zlog_debug (" Advertising Router %s", - inet_ntoa (adv_router)); - } + zlog_debug(" LS type %d", ls_type); + zlog_debug(" Link State ID %s", inet_ntoa(ls_id)); + zlog_debug(" Advertising Router %s", inet_ntoa(adv_router)); + } - stream_set_getp (s, sp); + stream_set_getp(s, sp); } -static void -ospf_packet_ls_upd_dump (struct stream *s, u_int16_t length) +static void ospf_packet_ls_upd_dump(struct stream *s, u_int16_t length) { - u_int32_t sp; - struct lsa_header *lsa; - int lsa_len; - u_int32_t count; - - length -= OSPF_HEADER_SIZE; - - sp = stream_get_getp (s); - - count = stream_getl (s); - length -= 4; - - zlog_debug ("Link State Update"); - zlog_debug (" # LSAs %d", count); - - while (length > 0 && count > 0) - { - if (length < OSPF_HEADER_SIZE || length % 4 != 0) - { - zlog_debug (" Remaining %d bytes; Incorrect length.", length); - break; + u_int32_t sp; + struct lsa_header *lsa; + int lsa_len; + u_int32_t count; + + length -= OSPF_HEADER_SIZE; + + sp = stream_get_getp(s); + + count = stream_getl(s); + length -= 4; + + zlog_debug("Link State Update"); + zlog_debug(" # LSAs %d", count); + + while (length > 0 && count > 0) { + if (length < OSPF_HEADER_SIZE || length % 4 != 0) { + zlog_debug(" Remaining %d bytes; Incorrect length.", + length); + break; + } + + lsa = (struct lsa_header *)STREAM_PNT(s); + lsa_len = ntohs(lsa->length); + ospf_lsa_header_dump(lsa); + + switch (lsa->type) { + case OSPF_ROUTER_LSA: + ospf_router_lsa_dump(s, length); + break; + case OSPF_NETWORK_LSA: + ospf_network_lsa_dump(s, length); + break; + case OSPF_SUMMARY_LSA: + case OSPF_ASBR_SUMMARY_LSA: + ospf_summary_lsa_dump(s, length); + break; + case OSPF_AS_EXTERNAL_LSA: + ospf_as_external_lsa_dump(s, length); + break; + case OSPF_AS_NSSA_LSA: + ospf_as_external_lsa_dump(s, length); + break; + case OSPF_OPAQUE_LINK_LSA: + case OSPF_OPAQUE_AREA_LSA: + case OSPF_OPAQUE_AS_LSA: + ospf_opaque_lsa_dump(s, length); + break; + default: + break; + } + + stream_forward_getp(s, lsa_len); + length -= lsa_len; + count--; } - lsa = (struct lsa_header *) STREAM_PNT (s); - lsa_len = ntohs (lsa->length); - ospf_lsa_header_dump (lsa); - - switch (lsa->type) - { - case OSPF_ROUTER_LSA: - ospf_router_lsa_dump (s, length); - break; - case OSPF_NETWORK_LSA: - ospf_network_lsa_dump (s, length); - break; - case OSPF_SUMMARY_LSA: - case OSPF_ASBR_SUMMARY_LSA: - ospf_summary_lsa_dump (s, length); - break; - case OSPF_AS_EXTERNAL_LSA: - ospf_as_external_lsa_dump (s, length); - break; - case OSPF_AS_NSSA_LSA: - ospf_as_external_lsa_dump (s, length); - break; - case OSPF_OPAQUE_LINK_LSA: - case OSPF_OPAQUE_AREA_LSA: - case OSPF_OPAQUE_AS_LSA: - ospf_opaque_lsa_dump (s, length); - break; - default: - break; - } - - stream_forward_getp (s, lsa_len); - length -= lsa_len; - count--; - } - - stream_set_getp (s, sp); + stream_set_getp(s, sp); } -static void -ospf_packet_ls_ack_dump (struct stream *s, u_int16_t length) +static void ospf_packet_ls_ack_dump(struct stream *s, u_int16_t length) { - u_int32_t sp; + u_int32_t sp; - length -= OSPF_HEADER_SIZE; - sp = stream_get_getp (s); + length -= OSPF_HEADER_SIZE; + sp = stream_get_getp(s); - zlog_debug ("Link State Acknowledgment"); - ospf_lsa_header_list_dump (s, length); + zlog_debug("Link State Acknowledgment"); + ospf_lsa_header_list_dump(s, length); - stream_set_getp (s, sp); + stream_set_getp(s, sp); } /* Expects header to be in host order */ -void -ospf_ip_header_dump (struct ip *iph) +void ospf_ip_header_dump(struct ip *iph) { - /* IP Header dump. */ - zlog_debug ("ip_v %d", iph->ip_v); - zlog_debug ("ip_hl %d", iph->ip_hl); - zlog_debug ("ip_tos %d", iph->ip_tos); - zlog_debug ("ip_len %d", iph->ip_len); - zlog_debug ("ip_id %u", (u_int32_t) iph->ip_id); - zlog_debug ("ip_off %u", (u_int32_t) iph->ip_off); - zlog_debug ("ip_ttl %d", iph->ip_ttl); - zlog_debug ("ip_p %d", iph->ip_p); - zlog_debug ("ip_sum 0x%x", (u_int32_t) iph->ip_sum); - zlog_debug ("ip_src %s", inet_ntoa (iph->ip_src)); - zlog_debug ("ip_dst %s", inet_ntoa (iph->ip_dst)); + /* IP Header dump. */ + zlog_debug("ip_v %d", iph->ip_v); + zlog_debug("ip_hl %d", iph->ip_hl); + zlog_debug("ip_tos %d", iph->ip_tos); + zlog_debug("ip_len %d", iph->ip_len); + zlog_debug("ip_id %u", (u_int32_t)iph->ip_id); + zlog_debug("ip_off %u", (u_int32_t)iph->ip_off); + zlog_debug("ip_ttl %d", iph->ip_ttl); + zlog_debug("ip_p %d", iph->ip_p); + zlog_debug("ip_sum 0x%x", (u_int32_t)iph->ip_sum); + zlog_debug("ip_src %s", inet_ntoa(iph->ip_src)); + zlog_debug("ip_dst %s", inet_ntoa(iph->ip_dst)); } -static void -ospf_header_dump (struct ospf_header *ospfh) +static void ospf_header_dump(struct ospf_header *ospfh) { - char buf[9]; - u_int16_t auth_type = ntohs (ospfh->auth_type); - - zlog_debug ("Header"); - zlog_debug (" Version %d", ospfh->version); - zlog_debug (" Type %d (%s)", ospfh->type, - lookup_msg(ospf_packet_type_str, ospfh->type, NULL)); - zlog_debug (" Packet Len %d", ntohs (ospfh->length)); - zlog_debug (" Router ID %s", inet_ntoa (ospfh->router_id)); - zlog_debug (" Area ID %s", inet_ntoa (ospfh->area_id)); - zlog_debug (" Checksum 0x%x", ntohs (ospfh->checksum)); - zlog_debug (" AuType %s", lookup_msg(ospf_auth_type_str, auth_type, NULL)); - - switch (auth_type) - { - case OSPF_AUTH_NULL: - break; - case OSPF_AUTH_SIMPLE: - memset (buf, 0, 9); - strncpy (buf, (char *) ospfh->u.auth_data, 8); - zlog_debug (" Simple Password %s", buf); - break; - case OSPF_AUTH_CRYPTOGRAPHIC: - zlog_debug (" Cryptographic Authentication"); - zlog_debug (" Key ID %d", ospfh->u.crypt.key_id); - zlog_debug (" Auth Data Len %d", ospfh->u.crypt.auth_data_len); - zlog_debug (" Sequence number %ld", - (u_long)ntohl (ospfh->u.crypt.crypt_seqnum)); - break; - default: - zlog_debug ("* This is not supported authentication type"); - break; - } - + char buf[9]; + u_int16_t auth_type = ntohs(ospfh->auth_type); + + zlog_debug("Header"); + zlog_debug(" Version %d", ospfh->version); + zlog_debug(" Type %d (%s)", ospfh->type, + lookup_msg(ospf_packet_type_str, ospfh->type, NULL)); + zlog_debug(" Packet Len %d", ntohs(ospfh->length)); + zlog_debug(" Router ID %s", inet_ntoa(ospfh->router_id)); + zlog_debug(" Area ID %s", inet_ntoa(ospfh->area_id)); + zlog_debug(" Checksum 0x%x", ntohs(ospfh->checksum)); + zlog_debug(" AuType %s", + lookup_msg(ospf_auth_type_str, auth_type, NULL)); + + switch (auth_type) { + case OSPF_AUTH_NULL: + break; + case OSPF_AUTH_SIMPLE: + memset(buf, 0, 9); + strncpy(buf, (char *)ospfh->u.auth_data, 8); + zlog_debug(" Simple Password %s", buf); + break; + case OSPF_AUTH_CRYPTOGRAPHIC: + zlog_debug(" Cryptographic Authentication"); + zlog_debug(" Key ID %d", ospfh->u.crypt.key_id); + zlog_debug(" Auth Data Len %d", ospfh->u.crypt.auth_data_len); + zlog_debug(" Sequence number %ld", + (u_long)ntohl(ospfh->u.crypt.crypt_seqnum)); + break; + default: + zlog_debug("* This is not supported authentication type"); + break; + } } -void -ospf_packet_dump (struct stream *s) +void ospf_packet_dump(struct stream *s) { - struct ospf_header *ospfh; - unsigned long gp; - - /* Preserve pointer. */ - gp = stream_get_getp (s); - - /* OSPF Header dump. */ - ospfh = (struct ospf_header *) STREAM_PNT (s); - - /* Until detail flag is set, return. */ - if (!(term_debug_ospf_packet[ospfh->type - 1] & OSPF_DEBUG_DETAIL)) - return; - - /* Show OSPF header detail. */ - ospf_header_dump (ospfh); - stream_forward_getp (s, OSPF_HEADER_SIZE); - - switch (ospfh->type) - { - case OSPF_MSG_HELLO: - ospf_packet_hello_dump (s, ntohs (ospfh->length)); - break; - case OSPF_MSG_DB_DESC: - ospf_packet_db_desc_dump (s, ntohs (ospfh->length)); - break; - case OSPF_MSG_LS_REQ: - ospf_packet_ls_req_dump (s, ntohs (ospfh->length)); - break; - case OSPF_MSG_LS_UPD: - ospf_packet_ls_upd_dump (s, ntohs (ospfh->length)); - break; - case OSPF_MSG_LS_ACK: - ospf_packet_ls_ack_dump (s, ntohs (ospfh->length)); - break; - default: - break; - } - - stream_set_getp (s, gp); + struct ospf_header *ospfh; + unsigned long gp; + + /* Preserve pointer. */ + gp = stream_get_getp(s); + + /* OSPF Header dump. */ + ospfh = (struct ospf_header *)STREAM_PNT(s); + + /* Until detail flag is set, return. */ + if (!(term_debug_ospf_packet[ospfh->type - 1] & OSPF_DEBUG_DETAIL)) + return; + + /* Show OSPF header detail. */ + ospf_header_dump(ospfh); + stream_forward_getp(s, OSPF_HEADER_SIZE); + + switch (ospfh->type) { + case OSPF_MSG_HELLO: + ospf_packet_hello_dump(s, ntohs(ospfh->length)); + break; + case OSPF_MSG_DB_DESC: + ospf_packet_db_desc_dump(s, ntohs(ospfh->length)); + break; + case OSPF_MSG_LS_REQ: + ospf_packet_ls_req_dump(s, ntohs(ospfh->length)); + break; + case OSPF_MSG_LS_UPD: + ospf_packet_ls_upd_dump(s, ntohs(ospfh->length)); + break; + case OSPF_MSG_LS_ACK: + ospf_packet_ls_ack_dump(s, ntohs(ospfh->length)); + break; + default: + break; + } + + stream_set_getp(s, gp); } DEFUN (debug_ospf_packet, @@ -652,61 +617,60 @@ DEFUN (debug_ospf_packet, "Detail Information\n" "Detail Information\n") { - int inst = (argv[2]->type == RANGE_TKN) ? 1 : 0; - int detail = strmatch (argv[argc - 1]->text, "detail"); - int send = strmatch (argv[argc - (1+detail)]->text, "send"); - int recv = strmatch (argv[argc - (1+detail)]->text, "recv"); - char *packet = argv[3 + inst]->text; - - if (inst) // user passed instance ID - { - if (!ospf_lookup_instance (strtoul (argv[2]->arg, NULL, 10))) - return CMD_SUCCESS; - } - - int type = 0; - int flag = 0; - int i; - - /* Check packet type. */ - if (strmatch (packet, "hello")) - type = OSPF_DEBUG_HELLO; - else if (strmatch (packet, "dd")) - type = OSPF_DEBUG_DB_DESC; - else if (strmatch (packet, "ls-request")) - type = OSPF_DEBUG_LS_REQ; - else if (strmatch (packet, "ls-update")) - type = OSPF_DEBUG_LS_UPD; - else if (strmatch (packet, "ls-ack")) - type = OSPF_DEBUG_LS_ACK; - else if (strmatch (packet, "all")) - type = OSPF_DEBUG_ALL; - - /* Cases: - * (none) = send + recv - * detail = send + recv + detail - * recv = recv - * send = send - * recv detail = recv + detail - * send detail = send + detail - */ - if (!send && !recv) - send = recv = 1; - - flag |= (send) ? OSPF_DEBUG_SEND : 0; - flag |= (recv) ? OSPF_DEBUG_RECV : 0; - flag |= (detail) ? OSPF_DEBUG_DETAIL : 0; - - for (i = 0; i < 5; i++) - if (type & (0x01 << i)) - { - if (vty->node == CONFIG_NODE) - DEBUG_PACKET_ON (i, flag); - else - TERM_DEBUG_PACKET_ON (i, flag); - } + int inst = (argv[2]->type == RANGE_TKN) ? 1 : 0; + int detail = strmatch(argv[argc - 1]->text, "detail"); + int send = strmatch(argv[argc - (1 + detail)]->text, "send"); + int recv = strmatch(argv[argc - (1 + detail)]->text, "recv"); + char *packet = argv[3 + inst]->text; - return CMD_SUCCESS; + if (inst) // user passed instance ID + { + if (!ospf_lookup_instance(strtoul(argv[2]->arg, NULL, 10))) + return CMD_SUCCESS; + } + + int type = 0; + int flag = 0; + int i; + + /* Check packet type. */ + if (strmatch(packet, "hello")) + type = OSPF_DEBUG_HELLO; + else if (strmatch(packet, "dd")) + type = OSPF_DEBUG_DB_DESC; + else if (strmatch(packet, "ls-request")) + type = OSPF_DEBUG_LS_REQ; + else if (strmatch(packet, "ls-update")) + type = OSPF_DEBUG_LS_UPD; + else if (strmatch(packet, "ls-ack")) + type = OSPF_DEBUG_LS_ACK; + else if (strmatch(packet, "all")) + type = OSPF_DEBUG_ALL; + + /* Cases: + * (none) = send + recv + * detail = send + recv + detail + * recv = recv + * send = send + * recv detail = recv + detail + * send detail = send + detail + */ + if (!send && !recv) + send = recv = 1; + + flag |= (send) ? OSPF_DEBUG_SEND : 0; + flag |= (recv) ? OSPF_DEBUG_RECV : 0; + flag |= (detail) ? OSPF_DEBUG_DETAIL : 0; + + for (i = 0; i < 5; i++) + if (type & (0x01 << i)) { + if (vty->node == CONFIG_NODE) + DEBUG_PACKET_ON(i, flag); + else + TERM_DEBUG_PACKET_ON(i, flag); + } + + return CMD_SUCCESS; } DEFUN (no_debug_ospf_packet, @@ -729,68 +693,67 @@ DEFUN (no_debug_ospf_packet, "Detail Information\n" "Detail Information\n") { - int inst = (argv[3]->type == RANGE_TKN) ? 1 : 0; - int detail = strmatch (argv[argc - 1]->text, "detail"); - int send = strmatch (argv[argc - (1+detail)]->text, "send"); - int recv = strmatch (argv[argc - (1+detail)]->text, "recv"); - char *packet = argv[4 + inst]->text; - - if (inst) // user passed instance ID - { - if (!ospf_lookup_instance (strtoul (argv[3]->arg, NULL, 10))) - return CMD_SUCCESS; - } - - int type = 0; - int flag = 0; - int i; - - /* Check packet type. */ - if (strmatch (packet, "hello")) - type = OSPF_DEBUG_HELLO; - else if (strmatch (packet, "dd")) - type = OSPF_DEBUG_DB_DESC; - else if (strmatch (packet, "ls-request")) - type = OSPF_DEBUG_LS_REQ; - else if (strmatch (packet, "ls-update")) - type = OSPF_DEBUG_LS_UPD; - else if (strmatch (packet, "ls-ack")) - type = OSPF_DEBUG_LS_ACK; - else if (strmatch (packet, "all")) - type = OSPF_DEBUG_ALL; - - /* Cases: - * (none) = send + recv - * detail = send + recv + detail - * recv = recv - * send = send - * recv detail = recv + detail - * send detail = send + detail - */ - if (!send && !recv) - send = recv = 1; - - flag |= (send) ? OSPF_DEBUG_SEND : 0; - flag |= (recv) ? OSPF_DEBUG_RECV : 0; - flag |= (detail) ? OSPF_DEBUG_DETAIL : 0; - - for (i = 0; i < 5; i++) - if (type & (0x01 << i)) - { - if (vty->node == CONFIG_NODE) - DEBUG_PACKET_OFF (i, flag); - else - TERM_DEBUG_PACKET_OFF (i, flag); - } + int inst = (argv[3]->type == RANGE_TKN) ? 1 : 0; + int detail = strmatch(argv[argc - 1]->text, "detail"); + int send = strmatch(argv[argc - (1 + detail)]->text, "send"); + int recv = strmatch(argv[argc - (1 + detail)]->text, "recv"); + char *packet = argv[4 + inst]->text; + + if (inst) // user passed instance ID + { + if (!ospf_lookup_instance(strtoul(argv[3]->arg, NULL, 10))) + return CMD_SUCCESS; + } + + int type = 0; + int flag = 0; + int i; + + /* Check packet type. */ + if (strmatch(packet, "hello")) + type = OSPF_DEBUG_HELLO; + else if (strmatch(packet, "dd")) + type = OSPF_DEBUG_DB_DESC; + else if (strmatch(packet, "ls-request")) + type = OSPF_DEBUG_LS_REQ; + else if (strmatch(packet, "ls-update")) + type = OSPF_DEBUG_LS_UPD; + else if (strmatch(packet, "ls-ack")) + type = OSPF_DEBUG_LS_ACK; + else if (strmatch(packet, "all")) + type = OSPF_DEBUG_ALL; + + /* Cases: + * (none) = send + recv + * detail = send + recv + detail + * recv = recv + * send = send + * recv detail = recv + detail + * send detail = send + detail + */ + if (!send && !recv) + send = recv = 1; + + flag |= (send) ? OSPF_DEBUG_SEND : 0; + flag |= (recv) ? OSPF_DEBUG_RECV : 0; + flag |= (detail) ? OSPF_DEBUG_DETAIL : 0; + + for (i = 0; i < 5; i++) + if (type & (0x01 << i)) { + if (vty->node == CONFIG_NODE) + DEBUG_PACKET_OFF(i, flag); + else + TERM_DEBUG_PACKET_OFF(i, flag); + } #ifdef DEBUG - /* - for (i = 0; i < 5; i++) - zlog_debug ("flag[%d] = %d", i, ospf_debug_packet[i]); - */ +/* +for (i = 0; i < 5; i++) + zlog_debug ("flag[%d] = %d", i, ospf_debug_packet[i]); +*/ #endif /* DEBUG */ - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_ospf_ism, @@ -804,46 +767,43 @@ DEFUN (debug_ospf_ism, "ISM Event Information\n" "ISM TImer Information\n") { - int inst = (argv[2]->type == RANGE_TKN); - char *dbgparam = (argc == 4 + inst) ? argv[argc - 1]->text : NULL; - - if (inst) // user passed instance ID - { - if (!ospf_lookup_instance (strtoul (argv[2]->arg, NULL, 10))) - return CMD_SUCCESS; - } - - if (vty->node == CONFIG_NODE) - { - if (!dbgparam) - DEBUG_ON (ism, ISM); - else + int inst = (argv[2]->type == RANGE_TKN); + char *dbgparam = (argc == 4 + inst) ? argv[argc - 1]->text : NULL; + + if (inst) // user passed instance ID { - if (strmatch (dbgparam, "status")) - DEBUG_ON (ism, ISM_STATUS); - else if (strmatch (dbgparam, "events")) - DEBUG_ON (ism, ISM_EVENTS); - else if (strmatch (dbgparam, "timers")) - DEBUG_ON (ism, ISM_TIMERS); + if (!ospf_lookup_instance(strtoul(argv[2]->arg, NULL, 10))) + return CMD_SUCCESS; } - return CMD_SUCCESS; - } - - /* ENABLE_NODE. */ - if (!dbgparam) - TERM_DEBUG_ON (ism, ISM); - else - { - if (strmatch (dbgparam, "status")) - TERM_DEBUG_ON (ism, ISM_STATUS); - else if (strmatch (dbgparam, "events")) - TERM_DEBUG_ON (ism, ISM_EVENTS); - else if (strmatch (dbgparam, "timers")) - TERM_DEBUG_ON (ism, ISM_TIMERS); - } - - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) { + if (!dbgparam) + DEBUG_ON(ism, ISM); + else { + if (strmatch(dbgparam, "status")) + DEBUG_ON(ism, ISM_STATUS); + else if (strmatch(dbgparam, "events")) + DEBUG_ON(ism, ISM_EVENTS); + else if (strmatch(dbgparam, "timers")) + DEBUG_ON(ism, ISM_TIMERS); + } + + return CMD_SUCCESS; + } + + /* ENABLE_NODE. */ + if (!dbgparam) + TERM_DEBUG_ON(ism, ISM); + else { + if (strmatch(dbgparam, "status")) + TERM_DEBUG_ON(ism, ISM_STATUS); + else if (strmatch(dbgparam, "events")) + TERM_DEBUG_ON(ism, ISM_EVENTS); + else if (strmatch(dbgparam, "timers")) + TERM_DEBUG_ON(ism, ISM_TIMERS); + } + + return CMD_SUCCESS; } DEFUN (no_debug_ospf_ism, @@ -858,82 +818,76 @@ DEFUN (no_debug_ospf_ism, "ISM Event Information\n" "ISM TImer Information\n") { - int inst = (argv[3]->type == RANGE_TKN); - char *dbgparam = (argc == 5 + inst) ? argv[argc - 1]->text : NULL; - - if (inst) // user passed instance ID - { - if (!ospf_lookup_instance (strtoul (argv[3]->arg, NULL, 10))) - return CMD_SUCCESS; - } - - if (vty->node == CONFIG_NODE) - { - if (!dbgparam) - DEBUG_OFF (ism, ISM); - else + int inst = (argv[3]->type == RANGE_TKN); + char *dbgparam = (argc == 5 + inst) ? argv[argc - 1]->text : NULL; + + if (inst) // user passed instance ID { - if (strmatch (dbgparam, "status")) - DEBUG_OFF (ism, ISM_STATUS); - else if (strmatch (dbgparam, "events")) - DEBUG_OFF (ism, ISM_EVENTS); - else if (strmatch (dbgparam, "timers")) - DEBUG_OFF (ism, ISM_TIMERS); + if (!ospf_lookup_instance(strtoul(argv[3]->arg, NULL, 10))) + return CMD_SUCCESS; + } + + if (vty->node == CONFIG_NODE) { + if (!dbgparam) + DEBUG_OFF(ism, ISM); + else { + if (strmatch(dbgparam, "status")) + DEBUG_OFF(ism, ISM_STATUS); + else if (strmatch(dbgparam, "events")) + DEBUG_OFF(ism, ISM_EVENTS); + else if (strmatch(dbgparam, "timers")) + DEBUG_OFF(ism, ISM_TIMERS); + } + + return CMD_SUCCESS; + } + + /* ENABLE_NODE. */ + if (!dbgparam) + TERM_DEBUG_OFF(ism, ISM); + else { + if (strmatch(dbgparam, "status")) + TERM_DEBUG_OFF(ism, ISM_STATUS); + else if (strmatch(dbgparam, "events")) + TERM_DEBUG_OFF(ism, ISM_EVENTS); + else if (strmatch(dbgparam, "timers")) + TERM_DEBUG_OFF(ism, ISM_TIMERS); } - return CMD_SUCCESS; - } - - /* ENABLE_NODE. */ - if (!dbgparam) - TERM_DEBUG_OFF (ism, ISM); - else - { - if (strmatch (dbgparam, "status")) - TERM_DEBUG_OFF (ism, ISM_STATUS); - else if (strmatch (dbgparam, "events")) - TERM_DEBUG_OFF (ism, ISM_EVENTS); - else if (strmatch (dbgparam, "timers")) - TERM_DEBUG_OFF (ism, ISM_TIMERS); - } - - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -debug_ospf_nsm_common (struct vty *vty, int arg_base, int argc, struct cmd_token **argv) +static int debug_ospf_nsm_common(struct vty *vty, int arg_base, int argc, + struct cmd_token **argv) { - if (vty->node == CONFIG_NODE) - { - if (argc == arg_base + 0) - DEBUG_ON (nsm, NSM); - else if (argc == arg_base + 1) - { - if (strmatch(argv[arg_base]->text, "status")) - DEBUG_ON (nsm, NSM_STATUS); - else if (strmatch(argv[arg_base]->text, "events")) - DEBUG_ON (nsm, NSM_EVENTS); - else if (strmatch(argv[arg_base]->text, "timers")) - DEBUG_ON (nsm, NSM_TIMERS); + if (vty->node == CONFIG_NODE) { + if (argc == arg_base + 0) + DEBUG_ON(nsm, NSM); + else if (argc == arg_base + 1) { + if (strmatch(argv[arg_base]->text, "status")) + DEBUG_ON(nsm, NSM_STATUS); + else if (strmatch(argv[arg_base]->text, "events")) + DEBUG_ON(nsm, NSM_EVENTS); + else if (strmatch(argv[arg_base]->text, "timers")) + DEBUG_ON(nsm, NSM_TIMERS); + } + + return CMD_SUCCESS; + } + + /* ENABLE_NODE. */ + if (argc == arg_base + 0) + TERM_DEBUG_ON(nsm, NSM); + else if (argc == arg_base + 1) { + if (strmatch(argv[arg_base]->text, "status")) + TERM_DEBUG_ON(nsm, NSM_STATUS); + else if (strmatch(argv[arg_base]->text, "events")) + TERM_DEBUG_ON(nsm, NSM_EVENTS); + else if (strmatch(argv[arg_base]->text, "timers")) + TERM_DEBUG_ON(nsm, NSM_TIMERS); } - return CMD_SUCCESS; - } - - /* ENABLE_NODE. */ - if (argc == arg_base + 0) - TERM_DEBUG_ON (nsm, NSM); - else if (argc == arg_base + 1) - { - if (strmatch(argv[arg_base]->text, "status")) - TERM_DEBUG_ON (nsm, NSM_STATUS); - else if (strmatch(argv[arg_base]->text, "events")) - TERM_DEBUG_ON (nsm, NSM_EVENTS); - else if (strmatch(argv[arg_base]->text, "timers")) - TERM_DEBUG_ON (nsm, NSM_TIMERS); - } - - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_ospf_nsm, @@ -946,7 +900,7 @@ DEFUN (debug_ospf_nsm, "NSM Event Information\n" "NSM Timer Information\n") { - return debug_ospf_nsm_common (vty, 3, argc, argv); + return debug_ospf_nsm_common(vty, 3, argc, argv); } DEFUN (debug_ospf_instance_nsm, @@ -960,52 +914,49 @@ DEFUN (debug_ospf_instance_nsm, "NSM Event Information\n" "NSM Timer Information\n") { - int idx_number = 2; - u_short instance = 0; + int idx_number = 2; + u_short instance = 0; - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if (!ospf_lookup_instance (instance)) - return CMD_SUCCESS; + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if (!ospf_lookup_instance(instance)) + return CMD_SUCCESS; - return debug_ospf_nsm_common (vty, 4, argc, argv); + return debug_ospf_nsm_common(vty, 4, argc, argv); } -static int -no_debug_ospf_nsm_common (struct vty *vty, int arg_base, int argc, struct cmd_token **argv) +static int no_debug_ospf_nsm_common(struct vty *vty, int arg_base, int argc, + struct cmd_token **argv) { - /* XXX qlyoung */ - if (vty->node == CONFIG_NODE) - { - if (argc == arg_base + 0) - DEBUG_OFF (nsm, NSM); - else if (argc == arg_base + 1) - { - if (strmatch(argv[arg_base]->text, "status")) - DEBUG_OFF (nsm, NSM_STATUS); - else if (strmatch(argv[arg_base]->text, "events")) - DEBUG_OFF (nsm, NSM_EVENTS); - else if (strmatch(argv[arg_base]->text, "timers")) - DEBUG_OFF (nsm, NSM_TIMERS); + /* XXX qlyoung */ + if (vty->node == CONFIG_NODE) { + if (argc == arg_base + 0) + DEBUG_OFF(nsm, NSM); + else if (argc == arg_base + 1) { + if (strmatch(argv[arg_base]->text, "status")) + DEBUG_OFF(nsm, NSM_STATUS); + else if (strmatch(argv[arg_base]->text, "events")) + DEBUG_OFF(nsm, NSM_EVENTS); + else if (strmatch(argv[arg_base]->text, "timers")) + DEBUG_OFF(nsm, NSM_TIMERS); + } + + return CMD_SUCCESS; + } + + /* ENABLE_NODE. */ + if (argc == arg_base + 0) + TERM_DEBUG_OFF(nsm, NSM); + else if (argc == arg_base + 1) { + if (strmatch(argv[arg_base]->text, "status")) + TERM_DEBUG_OFF(nsm, NSM_STATUS); + else if (strmatch(argv[arg_base]->text, "events")) + TERM_DEBUG_OFF(nsm, NSM_EVENTS); + else if (strmatch(argv[arg_base]->text, "timers")) + TERM_DEBUG_OFF(nsm, NSM_TIMERS); } - return CMD_SUCCESS; - } - - /* ENABLE_NODE. */ - if (argc == arg_base + 0) - TERM_DEBUG_OFF (nsm, NSM); - else if (argc == arg_base + 1) - { - if (strmatch(argv[arg_base]->text, "status")) - TERM_DEBUG_OFF (nsm, NSM_STATUS); - else if (strmatch(argv[arg_base]->text, "events")) - TERM_DEBUG_OFF (nsm, NSM_EVENTS); - else if (strmatch(argv[arg_base]->text, "timers")) - TERM_DEBUG_OFF (nsm, NSM_TIMERS); - } - - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_debug_ospf_nsm, @@ -1019,7 +970,7 @@ DEFUN (no_debug_ospf_nsm, "NSM Event Information\n" "NSM Timer Information\n") { - return no_debug_ospf_nsm_common(vty, 4, argc, argv); + return no_debug_ospf_nsm_common(vty, 4, argc, argv); } @@ -1035,55 +986,52 @@ DEFUN (no_debug_ospf_instance_nsm, "NSM Event Information\n" "NSM Timer Information\n") { - int idx_number = 3; - u_short instance = 0; + int idx_number = 3; + u_short instance = 0; - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if (!ospf_lookup_instance (instance)) - return CMD_SUCCESS; + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if (!ospf_lookup_instance(instance)) + return CMD_SUCCESS; - return no_debug_ospf_nsm_common(vty, 5, argc, argv); + return no_debug_ospf_nsm_common(vty, 5, argc, argv); } -static int -debug_ospf_lsa_common (struct vty *vty, int arg_base, int argc, struct cmd_token **argv) +static int debug_ospf_lsa_common(struct vty *vty, int arg_base, int argc, + struct cmd_token **argv) { - if (vty->node == CONFIG_NODE) - { - if (argc == arg_base + 0) - DEBUG_ON (lsa, LSA); - else if (argc == arg_base + 1) - { - if (strmatch(argv[arg_base]->text, "generate")) - DEBUG_ON (lsa, LSA_GENERATE); - else if (strmatch(argv[arg_base]->text, "flooding")) - DEBUG_ON (lsa, LSA_FLOODING); - else if (strmatch(argv[arg_base]->text, "install")) - DEBUG_ON (lsa, LSA_INSTALL); - else if (strmatch(argv[arg_base]->text, "refresh")) - DEBUG_ON (lsa, LSA_REFRESH); + if (vty->node == CONFIG_NODE) { + if (argc == arg_base + 0) + DEBUG_ON(lsa, LSA); + else if (argc == arg_base + 1) { + if (strmatch(argv[arg_base]->text, "generate")) + DEBUG_ON(lsa, LSA_GENERATE); + else if (strmatch(argv[arg_base]->text, "flooding")) + DEBUG_ON(lsa, LSA_FLOODING); + else if (strmatch(argv[arg_base]->text, "install")) + DEBUG_ON(lsa, LSA_INSTALL); + else if (strmatch(argv[arg_base]->text, "refresh")) + DEBUG_ON(lsa, LSA_REFRESH); + } + + return CMD_SUCCESS; } - return CMD_SUCCESS; - } - - /* ENABLE_NODE. */ - if (argc == arg_base + 0) - TERM_DEBUG_ON (lsa, LSA); - else if (argc == arg_base + 1) - { - if (strmatch(argv[arg_base]->text, "generate")) - TERM_DEBUG_ON (lsa, LSA_GENERATE); - else if (strmatch(argv[arg_base]->text, "flooding")) - TERM_DEBUG_ON (lsa, LSA_FLOODING); - else if (strmatch(argv[arg_base]->text, "install")) - TERM_DEBUG_ON (lsa, LSA_INSTALL); - else if (strmatch(argv[arg_base]->text, "refresh")) - TERM_DEBUG_ON (lsa, LSA_REFRESH); - } - - return CMD_SUCCESS; + /* ENABLE_NODE. */ + if (argc == arg_base + 0) + TERM_DEBUG_ON(lsa, LSA); + else if (argc == arg_base + 1) { + if (strmatch(argv[arg_base]->text, "generate")) + TERM_DEBUG_ON(lsa, LSA_GENERATE); + else if (strmatch(argv[arg_base]->text, "flooding")) + TERM_DEBUG_ON(lsa, LSA_FLOODING); + else if (strmatch(argv[arg_base]->text, "install")) + TERM_DEBUG_ON(lsa, LSA_INSTALL); + else if (strmatch(argv[arg_base]->text, "refresh")) + TERM_DEBUG_ON(lsa, LSA_REFRESH); + } + + return CMD_SUCCESS; } DEFUN (debug_ospf_lsa, @@ -1097,7 +1045,7 @@ DEFUN (debug_ospf_lsa, "LSA Install/Delete\n" "LSA Refresh\n") { - return debug_ospf_lsa_common(vty, 3, argc, argv); + return debug_ospf_lsa_common(vty, 3, argc, argv); } DEFUN (debug_ospf_instance_lsa, @@ -1112,55 +1060,52 @@ DEFUN (debug_ospf_instance_lsa, "LSA Install/Delete\n" "LSA Refresh\n") { - int idx_number = 2; - u_short instance = 0; + int idx_number = 2; + u_short instance = 0; - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if (!ospf_lookup_instance (instance)) - return CMD_SUCCESS; + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if (!ospf_lookup_instance(instance)) + return CMD_SUCCESS; - return debug_ospf_lsa_common(vty, 4, argc, argv); + return debug_ospf_lsa_common(vty, 4, argc, argv); } -static int -no_debug_ospf_lsa_common (struct vty *vty, int arg_base, int argc, struct cmd_token **argv) +static int no_debug_ospf_lsa_common(struct vty *vty, int arg_base, int argc, + struct cmd_token **argv) { - if (vty->node == CONFIG_NODE) - { - if (argc == arg_base + 0) - DEBUG_OFF (lsa, LSA); - else if (argc == arg_base + 1) - { - if (strmatch(argv[arg_base]->text, "generate")) - DEBUG_OFF (lsa, LSA_GENERATE); - else if (strmatch(argv[arg_base]->text, "flooding")) - DEBUG_OFF (lsa, LSA_FLOODING); - else if (strmatch(argv[arg_base]->text, "install")) - DEBUG_OFF (lsa, LSA_INSTALL); - else if (strmatch(argv[arg_base]->text, "refresh")) - DEBUG_OFF (lsa, LSA_REFRESH); + if (vty->node == CONFIG_NODE) { + if (argc == arg_base + 0) + DEBUG_OFF(lsa, LSA); + else if (argc == arg_base + 1) { + if (strmatch(argv[arg_base]->text, "generate")) + DEBUG_OFF(lsa, LSA_GENERATE); + else if (strmatch(argv[arg_base]->text, "flooding")) + DEBUG_OFF(lsa, LSA_FLOODING); + else if (strmatch(argv[arg_base]->text, "install")) + DEBUG_OFF(lsa, LSA_INSTALL); + else if (strmatch(argv[arg_base]->text, "refresh")) + DEBUG_OFF(lsa, LSA_REFRESH); + } + + return CMD_SUCCESS; + } + + /* ENABLE_NODE. */ + if (argc == arg_base + 0) + TERM_DEBUG_OFF(lsa, LSA); + else if (argc == arg_base + 1) { + if (strmatch(argv[arg_base]->text, "generate")) + TERM_DEBUG_OFF(lsa, LSA_GENERATE); + else if (strmatch(argv[arg_base]->text, "flooding")) + TERM_DEBUG_OFF(lsa, LSA_FLOODING); + else if (strmatch(argv[arg_base]->text, "install")) + TERM_DEBUG_OFF(lsa, LSA_INSTALL); + else if (strmatch(argv[arg_base]->text, "refresh")) + TERM_DEBUG_OFF(lsa, LSA_REFRESH); } - return CMD_SUCCESS; - } - - /* ENABLE_NODE. */ - if (argc == arg_base + 0) - TERM_DEBUG_OFF (lsa, LSA); - else if (argc == arg_base + 1) - { - if (strmatch(argv[arg_base]->text, "generate")) - TERM_DEBUG_OFF (lsa, LSA_GENERATE); - else if (strmatch(argv[arg_base]->text, "flooding")) - TERM_DEBUG_OFF (lsa, LSA_FLOODING); - else if (strmatch(argv[arg_base]->text, "install")) - TERM_DEBUG_OFF (lsa, LSA_INSTALL); - else if (strmatch(argv[arg_base]->text, "refresh")) - TERM_DEBUG_OFF (lsa, LSA_REFRESH); - } - - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_debug_ospf_lsa, @@ -1175,7 +1120,7 @@ DEFUN (no_debug_ospf_lsa, "LSA Install/Delete\n" "LSA Refres\n") { - return no_debug_ospf_lsa_common (vty, 4, argc, argv); + return no_debug_ospf_lsa_common(vty, 4, argc, argv); } DEFUN (no_debug_ospf_instance_lsa, @@ -1191,47 +1136,44 @@ DEFUN (no_debug_ospf_instance_lsa, "LSA Install/Delete\n" "LSA Refres\n") { - int idx_number = 3; - u_short instance = 0; + int idx_number = 3; + u_short instance = 0; - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if (!ospf_lookup_instance (instance)) - return CMD_SUCCESS; + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if (!ospf_lookup_instance(instance)) + return CMD_SUCCESS; - return no_debug_ospf_lsa_common (vty, 5, argc, argv); + return no_debug_ospf_lsa_common(vty, 5, argc, argv); } -static int -debug_ospf_zebra_common (struct vty *vty, int arg_base, int argc, struct cmd_token **argv) +static int debug_ospf_zebra_common(struct vty *vty, int arg_base, int argc, + struct cmd_token **argv) { - if (vty->node == CONFIG_NODE) - { - if (argc == arg_base + 0) - DEBUG_ON (zebra, ZEBRA); - else if (argc == arg_base + 1) - { - if (strmatch(argv[arg_base]->text, "interface")) - DEBUG_ON (zebra, ZEBRA_INTERFACE); - else if (strmatch(argv[arg_base]->text, "redistribute")) - DEBUG_ON (zebra, ZEBRA_REDISTRIBUTE); + if (vty->node == CONFIG_NODE) { + if (argc == arg_base + 0) + DEBUG_ON(zebra, ZEBRA); + else if (argc == arg_base + 1) { + if (strmatch(argv[arg_base]->text, "interface")) + DEBUG_ON(zebra, ZEBRA_INTERFACE); + else if (strmatch(argv[arg_base]->text, "redistribute")) + DEBUG_ON(zebra, ZEBRA_REDISTRIBUTE); + } + + return CMD_SUCCESS; + } + + /* ENABLE_NODE. */ + if (argc == arg_base + 0) + TERM_DEBUG_ON(zebra, ZEBRA); + else if (argc == arg_base + 1) { + if (strmatch(argv[arg_base]->text, "interface")) + TERM_DEBUG_ON(zebra, ZEBRA_INTERFACE); + else if (strmatch(argv[arg_base]->text, "redistribute")) + TERM_DEBUG_ON(zebra, ZEBRA_REDISTRIBUTE); } - return CMD_SUCCESS; - } - - /* ENABLE_NODE. */ - if (argc == arg_base + 0) - TERM_DEBUG_ON (zebra, ZEBRA); - else if (argc == arg_base + 1) - { - if (strmatch(argv[arg_base]->text, "interface")) - TERM_DEBUG_ON (zebra, ZEBRA_INTERFACE); - else if (strmatch(argv[arg_base]->text, "redistribute")) - TERM_DEBUG_ON (zebra, ZEBRA_REDISTRIBUTE); - } - - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_ospf_zebra, @@ -1243,7 +1185,7 @@ DEFUN (debug_ospf_zebra, "Zebra interface\n" "Zebra redistribute\n") { - return debug_ospf_zebra_common(vty, 3, argc, argv); + return debug_ospf_zebra_common(vty, 3, argc, argv); } DEFUN (debug_ospf_instance_zebra, @@ -1256,48 +1198,44 @@ DEFUN (debug_ospf_instance_zebra, "Zebra interface\n" "Zebra redistribute\n") { - int idx_number = 2; - u_short instance = 0; + int idx_number = 2; + u_short instance = 0; - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if (!ospf_lookup_instance (instance)) - return CMD_SUCCESS; + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if (!ospf_lookup_instance(instance)) + return CMD_SUCCESS; - return debug_ospf_zebra_common(vty, 4, argc, argv); + return debug_ospf_zebra_common(vty, 4, argc, argv); } -static int -no_debug_ospf_zebra_common(struct vty *vty, int arg_base, int argc, - struct cmd_token **argv) +static int no_debug_ospf_zebra_common(struct vty *vty, int arg_base, int argc, + struct cmd_token **argv) { - if (vty->node == CONFIG_NODE) - { - if (argc == arg_base + 0) - DEBUG_OFF (zebra, ZEBRA); - else if (argc == arg_base + 1) - { - if (strmatch(argv[arg_base]->text, "interface")) - DEBUG_OFF (zebra, ZEBRA_INTERFACE); - else if (strmatch(argv[arg_base]->text, "redistribute")) - DEBUG_OFF (zebra, ZEBRA_REDISTRIBUTE); + if (vty->node == CONFIG_NODE) { + if (argc == arg_base + 0) + DEBUG_OFF(zebra, ZEBRA); + else if (argc == arg_base + 1) { + if (strmatch(argv[arg_base]->text, "interface")) + DEBUG_OFF(zebra, ZEBRA_INTERFACE); + else if (strmatch(argv[arg_base]->text, "redistribute")) + DEBUG_OFF(zebra, ZEBRA_REDISTRIBUTE); + } + + return CMD_SUCCESS; + } + + /* ENABLE_NODE. */ + if (argc == arg_base + 0) + TERM_DEBUG_OFF(zebra, ZEBRA); + else if (argc == arg_base + 1) { + if (strmatch(argv[arg_base]->text, "interface")) + TERM_DEBUG_OFF(zebra, ZEBRA_INTERFACE); + else if (strmatch(argv[arg_base]->text, "redistribute")) + TERM_DEBUG_OFF(zebra, ZEBRA_REDISTRIBUTE); } - return CMD_SUCCESS; - } - - /* ENABLE_NODE. */ - if (argc == arg_base + 0) - TERM_DEBUG_OFF (zebra, ZEBRA); - else if (argc == arg_base + 1) - { - if (strmatch(argv[arg_base]->text, "interface")) - TERM_DEBUG_OFF (zebra, ZEBRA_INTERFACE); - else if (strmatch(argv[arg_base]->text, "redistribute")) - TERM_DEBUG_OFF (zebra, ZEBRA_REDISTRIBUTE); - } - - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_debug_ospf_zebra, @@ -1310,7 +1248,7 @@ DEFUN (no_debug_ospf_zebra, "Zebra interface\n" "Zebra redistribute\n") { - return no_debug_ospf_zebra_common(vty, 4, argc, argv); + return no_debug_ospf_zebra_common(vty, 4, argc, argv); } DEFUN (no_debug_ospf_instance_zebra, @@ -1324,18 +1262,17 @@ DEFUN (no_debug_ospf_instance_zebra, "Zebra interface\n" "Zebra redistribute\n") { - int idx_number = 3; - u_short instance = 0; + int idx_number = 3; + u_short instance = 0; - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if (!ospf_lookup_instance (instance)) - return CMD_SUCCESS; + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if (!ospf_lookup_instance(instance)) + return CMD_SUCCESS; - return no_debug_ospf_zebra_common(vty, 5, argc, argv); + return no_debug_ospf_zebra_common(vty, 5, argc, argv); } - DEFUN (debug_ospf_event, debug_ospf_event_cmd, "debug ospf event", @@ -1343,10 +1280,10 @@ DEFUN (debug_ospf_event, OSPF_STR "OSPF event information\n") { - if (vty->node == CONFIG_NODE) - CONF_DEBUG_ON (event, EVENT); - TERM_DEBUG_ON (event, EVENT); - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + CONF_DEBUG_ON(event, EVENT); + TERM_DEBUG_ON(event, EVENT); + return CMD_SUCCESS; } DEFUN (no_debug_ospf_event, @@ -1357,10 +1294,10 @@ DEFUN (no_debug_ospf_event, OSPF_STR "OSPF event information\n") { - if (vty->node == CONFIG_NODE) - CONF_DEBUG_OFF (event, EVENT); - TERM_DEBUG_OFF (event, EVENT); - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + CONF_DEBUG_OFF(event, EVENT); + TERM_DEBUG_OFF(event, EVENT); + return CMD_SUCCESS; } DEFUN (debug_ospf_instance_event, @@ -1371,17 +1308,17 @@ DEFUN (debug_ospf_instance_event, "Instance ID\n" "OSPF event information\n") { - int idx_number = 2; - u_short instance = 0; + int idx_number = 2; + u_short instance = 0; - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if (!ospf_lookup_instance (instance)) - return CMD_SUCCESS; + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if (!ospf_lookup_instance(instance)) + return CMD_SUCCESS; - if (vty->node == CONFIG_NODE) - CONF_DEBUG_ON (event, EVENT); - TERM_DEBUG_ON (event, EVENT); - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + CONF_DEBUG_ON(event, EVENT); + TERM_DEBUG_ON(event, EVENT); + return CMD_SUCCESS; } DEFUN (no_debug_ospf_instance_event, @@ -1393,17 +1330,17 @@ DEFUN (no_debug_ospf_instance_event, "Instance ID\n" "OSPF event information\n") { - int idx_number = 3; - u_short instance = 0; + int idx_number = 3; + u_short instance = 0; - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if (!ospf_lookup_instance (instance)) - return CMD_SUCCESS; + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if (!ospf_lookup_instance(instance)) + return CMD_SUCCESS; - if (vty->node == CONFIG_NODE) - CONF_DEBUG_OFF (event, EVENT); - TERM_DEBUG_OFF (event, EVENT); - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + CONF_DEBUG_OFF(event, EVENT); + TERM_DEBUG_OFF(event, EVENT); + return CMD_SUCCESS; } DEFUN (debug_ospf_nssa, @@ -1413,10 +1350,10 @@ DEFUN (debug_ospf_nssa, OSPF_STR "OSPF nssa information\n") { - if (vty->node == CONFIG_NODE) - CONF_DEBUG_ON (nssa, NSSA); - TERM_DEBUG_ON (nssa, NSSA); - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + CONF_DEBUG_ON(nssa, NSSA); + TERM_DEBUG_ON(nssa, NSSA); + return CMD_SUCCESS; } DEFUN (no_debug_ospf_nssa, @@ -1427,10 +1364,10 @@ DEFUN (no_debug_ospf_nssa, OSPF_STR "OSPF nssa information\n") { - if (vty->node == CONFIG_NODE) - CONF_DEBUG_OFF (nssa, NSSA); - TERM_DEBUG_OFF (nssa, NSSA); - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + CONF_DEBUG_OFF(nssa, NSSA); + TERM_DEBUG_OFF(nssa, NSSA); + return CMD_SUCCESS; } DEFUN (debug_ospf_instance_nssa, @@ -1441,17 +1378,17 @@ DEFUN (debug_ospf_instance_nssa, "Instance ID\n" "OSPF nssa information\n") { - int idx_number = 2; - u_short instance = 0; + int idx_number = 2; + u_short instance = 0; - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if (!ospf_lookup_instance (instance)) - return CMD_SUCCESS; + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if (!ospf_lookup_instance(instance)) + return CMD_SUCCESS; - if (vty->node == CONFIG_NODE) - CONF_DEBUG_ON (nssa, NSSA); - TERM_DEBUG_ON (nssa, NSSA); - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + CONF_DEBUG_ON(nssa, NSSA); + TERM_DEBUG_ON(nssa, NSSA); + return CMD_SUCCESS; } DEFUN (no_debug_ospf_instance_nssa, @@ -1463,17 +1400,17 @@ DEFUN (no_debug_ospf_instance_nssa, "Instance ID\n" "OSPF nssa information\n") { - int idx_number = 3; - u_short instance = 0; + int idx_number = 3; + u_short instance = 0; - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if (!ospf_lookup_instance (instance)) - return CMD_SUCCESS; + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if (!ospf_lookup_instance(instance)) + return CMD_SUCCESS; - if (vty->node == CONFIG_NODE) - CONF_DEBUG_OFF (nssa, NSSA); - TERM_DEBUG_OFF (nssa, NSSA); - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + CONF_DEBUG_OFF(nssa, NSSA); + TERM_DEBUG_OFF(nssa, NSSA); + return CMD_SUCCESS; } DEFUN (debug_ospf_te, @@ -1483,10 +1420,10 @@ DEFUN (debug_ospf_te, OSPF_STR "OSPF-TE information\n") { - if (vty->node == CONFIG_NODE) - CONF_DEBUG_ON (te, TE); - TERM_DEBUG_ON (te, TE); - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + CONF_DEBUG_ON(te, TE); + TERM_DEBUG_ON(te, TE); + return CMD_SUCCESS; } DEFUN (no_debug_ospf_te, @@ -1497,10 +1434,10 @@ DEFUN (no_debug_ospf_te, OSPF_STR "OSPF-TE information\n") { - if (vty->node == CONFIG_NODE) - CONF_DEBUG_OFF (te, TE); - TERM_DEBUG_OFF (te, TE); - return CMD_SUCCESS; + if (vty->node == CONFIG_NODE) + CONF_DEBUG_OFF(te, TE); + TERM_DEBUG_OFF(te, TE); + return CMD_SUCCESS; } DEFUN (no_debug_ospf, @@ -1510,151 +1447,154 @@ DEFUN (no_debug_ospf, DEBUG_STR OSPF_STR) { - int flag = OSPF_DEBUG_SEND | OSPF_DEBUG_RECV | OSPF_DEBUG_DETAIL; - int i; - - if (vty->node == CONFIG_NODE) - { - CONF_DEBUG_OFF (event, EVENT); - CONF_DEBUG_OFF (nssa, NSSA); - DEBUG_OFF (ism, ISM_EVENTS); - DEBUG_OFF (ism, ISM_STATUS); - DEBUG_OFF (ism, ISM_TIMERS); - DEBUG_OFF (lsa, LSA); - DEBUG_OFF (lsa, LSA_FLOODING); - DEBUG_OFF (lsa, LSA_GENERATE); - DEBUG_OFF (lsa, LSA_INSTALL); - DEBUG_OFF (lsa, LSA_REFRESH); - DEBUG_OFF (nsm, NSM); - DEBUG_OFF (nsm, NSM_EVENTS); - DEBUG_OFF (nsm, NSM_STATUS); - DEBUG_OFF (nsm, NSM_TIMERS); - DEBUG_OFF (zebra, ZEBRA); - DEBUG_OFF (zebra, ZEBRA_INTERFACE); - DEBUG_OFF (zebra, ZEBRA_REDISTRIBUTE); - - for (i = 0; i < 5; i++) - DEBUG_PACKET_OFF (i, flag); - } - - for (i = 0; i < 5; i++) - TERM_DEBUG_PACKET_OFF (i, flag); - - TERM_DEBUG_OFF (event, EVENT); - TERM_DEBUG_OFF (ism, ISM); - TERM_DEBUG_OFF (ism, ISM_EVENTS); - TERM_DEBUG_OFF (ism, ISM_STATUS); - TERM_DEBUG_OFF (ism, ISM_TIMERS); - TERM_DEBUG_OFF (lsa, LSA); - TERM_DEBUG_OFF (lsa, LSA_FLOODING); - TERM_DEBUG_OFF (lsa, LSA_GENERATE); - TERM_DEBUG_OFF (lsa, LSA_INSTALL); - TERM_DEBUG_OFF (lsa, LSA_REFRESH); - TERM_DEBUG_OFF (nsm, NSM); - TERM_DEBUG_OFF (nsm, NSM_EVENTS); - TERM_DEBUG_OFF (nsm, NSM_STATUS); - TERM_DEBUG_OFF (nsm, NSM_TIMERS); - TERM_DEBUG_OFF (nssa, NSSA); - TERM_DEBUG_OFF (zebra, ZEBRA); - TERM_DEBUG_OFF (zebra, ZEBRA_INTERFACE); - TERM_DEBUG_OFF (zebra, ZEBRA_REDISTRIBUTE); - - return CMD_SUCCESS; + int flag = OSPF_DEBUG_SEND | OSPF_DEBUG_RECV | OSPF_DEBUG_DETAIL; + int i; + + if (vty->node == CONFIG_NODE) { + CONF_DEBUG_OFF(event, EVENT); + CONF_DEBUG_OFF(nssa, NSSA); + DEBUG_OFF(ism, ISM_EVENTS); + DEBUG_OFF(ism, ISM_STATUS); + DEBUG_OFF(ism, ISM_TIMERS); + DEBUG_OFF(lsa, LSA); + DEBUG_OFF(lsa, LSA_FLOODING); + DEBUG_OFF(lsa, LSA_GENERATE); + DEBUG_OFF(lsa, LSA_INSTALL); + DEBUG_OFF(lsa, LSA_REFRESH); + DEBUG_OFF(nsm, NSM); + DEBUG_OFF(nsm, NSM_EVENTS); + DEBUG_OFF(nsm, NSM_STATUS); + DEBUG_OFF(nsm, NSM_TIMERS); + DEBUG_OFF(zebra, ZEBRA); + DEBUG_OFF(zebra, ZEBRA_INTERFACE); + DEBUG_OFF(zebra, ZEBRA_REDISTRIBUTE); + + for (i = 0; i < 5; i++) + DEBUG_PACKET_OFF(i, flag); + } + + for (i = 0; i < 5; i++) + TERM_DEBUG_PACKET_OFF(i, flag); + + TERM_DEBUG_OFF(event, EVENT); + TERM_DEBUG_OFF(ism, ISM); + TERM_DEBUG_OFF(ism, ISM_EVENTS); + TERM_DEBUG_OFF(ism, ISM_STATUS); + TERM_DEBUG_OFF(ism, ISM_TIMERS); + TERM_DEBUG_OFF(lsa, LSA); + TERM_DEBUG_OFF(lsa, LSA_FLOODING); + TERM_DEBUG_OFF(lsa, LSA_GENERATE); + TERM_DEBUG_OFF(lsa, LSA_INSTALL); + TERM_DEBUG_OFF(lsa, LSA_REFRESH); + TERM_DEBUG_OFF(nsm, NSM); + TERM_DEBUG_OFF(nsm, NSM_EVENTS); + TERM_DEBUG_OFF(nsm, NSM_STATUS); + TERM_DEBUG_OFF(nsm, NSM_TIMERS); + TERM_DEBUG_OFF(nssa, NSSA); + TERM_DEBUG_OFF(zebra, ZEBRA); + TERM_DEBUG_OFF(zebra, ZEBRA_INTERFACE); + TERM_DEBUG_OFF(zebra, ZEBRA_REDISTRIBUTE); + + return CMD_SUCCESS; } -static int -show_debugging_ospf_common (struct vty *vty, struct ospf *ospf) +static int show_debugging_ospf_common(struct vty *vty, struct ospf *ospf) { - int i; - - if (ospf->instance) - vty_out (vty, "\nOSPF Instance: %d\n\n", ospf->instance); - - vty_out (vty, "OSPF debugging status:\n"); - - /* Show debug status for events. */ - if (IS_DEBUG_OSPF(event,EVENT)) - vty_out (vty, " OSPF event debugging is on\n"); - - /* Show debug status for ISM. */ - if (IS_DEBUG_OSPF (ism, ISM) == OSPF_DEBUG_ISM) - vty_out (vty, " OSPF ISM debugging is on\n"); - else - { - if (IS_DEBUG_OSPF (ism, ISM_STATUS)) - vty_out (vty, " OSPF ISM status debugging is on\n"); - if (IS_DEBUG_OSPF (ism, ISM_EVENTS)) - vty_out (vty, " OSPF ISM event debugging is on\n"); - if (IS_DEBUG_OSPF (ism, ISM_TIMERS)) - vty_out (vty, " OSPF ISM timer debugging is on\n"); - } - - /* Show debug status for NSM. */ - if (IS_DEBUG_OSPF (nsm, NSM) == OSPF_DEBUG_NSM) - vty_out (vty, " OSPF NSM debugging is on\n"); - else - { - if (IS_DEBUG_OSPF (nsm, NSM_STATUS)) - vty_out (vty, " OSPF NSM status debugging is on\n"); - if (IS_DEBUG_OSPF (nsm, NSM_EVENTS)) - vty_out (vty, " OSPF NSM event debugging is on\n"); - if (IS_DEBUG_OSPF (nsm, NSM_TIMERS)) - vty_out (vty, " OSPF NSM timer debugging is on\n"); - } - - /* Show debug status for OSPF Packets. */ - for (i = 0; i < 5; i++) - if (IS_DEBUG_OSPF_PACKET (i, SEND) && IS_DEBUG_OSPF_PACKET (i, RECV)) - { - vty_out (vty, " OSPF packet %s%s debugging is on\n", - lookup_msg(ospf_packet_type_str, i + 1, NULL), - IS_DEBUG_OSPF_PACKET (i, DETAIL) ? " detail" : ""); - } - else - { - if (IS_DEBUG_OSPF_PACKET (i, SEND)) - vty_out (vty, " OSPF packet %s send%s debugging is on\n", - lookup_msg(ospf_packet_type_str, i + 1, NULL), - IS_DEBUG_OSPF_PACKET (i, DETAIL) ? " detail" : ""); - if (IS_DEBUG_OSPF_PACKET (i, RECV)) - vty_out (vty, " OSPF packet %s receive%s debugging is on\n", - lookup_msg(ospf_packet_type_str, i + 1, NULL), - IS_DEBUG_OSPF_PACKET (i, DETAIL) ? " detail" : ""); - } - - /* Show debug status for OSPF LSAs. */ - if (IS_DEBUG_OSPF (lsa, LSA) == OSPF_DEBUG_LSA) - vty_out (vty, " OSPF LSA debugging is on\n"); - else - { - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - vty_out (vty, " OSPF LSA generation debugging is on\n"); - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - vty_out (vty, " OSPF LSA flooding debugging is on\n"); - if (IS_DEBUG_OSPF (lsa, LSA_INSTALL)) - vty_out (vty, " OSPF LSA install debugging is on\n"); - if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) - vty_out (vty, " OSPF LSA refresh debugging is on\n"); - } - - /* Show debug status for Zebra. */ - if (IS_DEBUG_OSPF (zebra, ZEBRA) == OSPF_DEBUG_ZEBRA) - vty_out (vty, " OSPF Zebra debugging is on\n"); - else - { - if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) - vty_out (vty, " OSPF Zebra interface debugging is on\n"); - if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) - vty_out (vty, " OSPF Zebra redistribute debugging is on\n"); - } - - /* Show debug status for NSSA. */ - if (IS_DEBUG_OSPF (nssa, NSSA) == OSPF_DEBUG_NSSA) - vty_out (vty, " OSPF NSSA debugging is on\n"); - - vty_out (vty, "\n"); - - return CMD_SUCCESS; + int i; + + if (ospf->instance) + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + + vty_out(vty, "OSPF debugging status:\n"); + + /* Show debug status for events. */ + if (IS_DEBUG_OSPF(event, EVENT)) + vty_out(vty, " OSPF event debugging is on\n"); + + /* Show debug status for ISM. */ + if (IS_DEBUG_OSPF(ism, ISM) == OSPF_DEBUG_ISM) + vty_out(vty, " OSPF ISM debugging is on\n"); + else { + if (IS_DEBUG_OSPF(ism, ISM_STATUS)) + vty_out(vty, " OSPF ISM status debugging is on\n"); + if (IS_DEBUG_OSPF(ism, ISM_EVENTS)) + vty_out(vty, " OSPF ISM event debugging is on\n"); + if (IS_DEBUG_OSPF(ism, ISM_TIMERS)) + vty_out(vty, " OSPF ISM timer debugging is on\n"); + } + + /* Show debug status for NSM. */ + if (IS_DEBUG_OSPF(nsm, NSM) == OSPF_DEBUG_NSM) + vty_out(vty, " OSPF NSM debugging is on\n"); + else { + if (IS_DEBUG_OSPF(nsm, NSM_STATUS)) + vty_out(vty, " OSPF NSM status debugging is on\n"); + if (IS_DEBUG_OSPF(nsm, NSM_EVENTS)) + vty_out(vty, " OSPF NSM event debugging is on\n"); + if (IS_DEBUG_OSPF(nsm, NSM_TIMERS)) + vty_out(vty, " OSPF NSM timer debugging is on\n"); + } + + /* Show debug status for OSPF Packets. */ + for (i = 0; i < 5; i++) + if (IS_DEBUG_OSPF_PACKET(i, SEND) + && IS_DEBUG_OSPF_PACKET(i, RECV)) { + vty_out(vty, " OSPF packet %s%s debugging is on\n", + lookup_msg(ospf_packet_type_str, i + 1, NULL), + IS_DEBUG_OSPF_PACKET(i, DETAIL) ? " detail" + : ""); + } else { + if (IS_DEBUG_OSPF_PACKET(i, SEND)) + vty_out(vty, + " OSPF packet %s send%s debugging is on\n", + lookup_msg(ospf_packet_type_str, i + 1, + NULL), + IS_DEBUG_OSPF_PACKET(i, DETAIL) + ? " detail" + : ""); + if (IS_DEBUG_OSPF_PACKET(i, RECV)) + vty_out(vty, + " OSPF packet %s receive%s debugging is on\n", + lookup_msg(ospf_packet_type_str, i + 1, + NULL), + IS_DEBUG_OSPF_PACKET(i, DETAIL) + ? " detail" + : ""); + } + + /* Show debug status for OSPF LSAs. */ + if (IS_DEBUG_OSPF(lsa, LSA) == OSPF_DEBUG_LSA) + vty_out(vty, " OSPF LSA debugging is on\n"); + else { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + vty_out(vty, " OSPF LSA generation debugging is on\n"); + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + vty_out(vty, " OSPF LSA flooding debugging is on\n"); + if (IS_DEBUG_OSPF(lsa, LSA_INSTALL)) + vty_out(vty, " OSPF LSA install debugging is on\n"); + if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) + vty_out(vty, " OSPF LSA refresh debugging is on\n"); + } + + /* Show debug status for Zebra. */ + if (IS_DEBUG_OSPF(zebra, ZEBRA) == OSPF_DEBUG_ZEBRA) + vty_out(vty, " OSPF Zebra debugging is on\n"); + else { + if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) + vty_out(vty, + " OSPF Zebra interface debugging is on\n"); + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) + vty_out(vty, + " OSPF Zebra redistribute debugging is on\n"); + } + + /* Show debug status for NSSA. */ + if (IS_DEBUG_OSPF(nssa, NSSA) == OSPF_DEBUG_NSSA) + vty_out(vty, " OSPF NSSA debugging is on\n"); + + vty_out(vty, "\n"); + + return CMD_SUCCESS; } DEFUN (show_debugging_ospf, @@ -1664,12 +1604,12 @@ DEFUN (show_debugging_ospf, DEBUG_STR OSPF_STR) { - struct ospf *ospf; + struct ospf *ospf; - if ((ospf = ospf_lookup()) == NULL) - return CMD_SUCCESS; + if ((ospf = ospf_lookup()) == NULL) + return CMD_SUCCESS; - return show_debugging_ospf_common(vty, ospf); + return show_debugging_ospf_common(vty, ospf); } DEFUN (show_debugging_ospf_instance, @@ -1680,219 +1620,208 @@ DEFUN (show_debugging_ospf_instance, OSPF_STR "Instance ID\n") { - int idx_number = 3; - struct ospf *ospf; - u_short instance = 0; + int idx_number = 3; + struct ospf *ospf; + u_short instance = 0; - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if ((ospf = ospf_lookup_instance (instance)) == NULL ) - return CMD_SUCCESS; + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if ((ospf = ospf_lookup_instance(instance)) == NULL) + return CMD_SUCCESS; - return show_debugging_ospf_common(vty, ospf); + return show_debugging_ospf_common(vty, ospf); } /* Debug node. */ -static struct cmd_node debug_node = -{ - DEBUG_NODE, - "", - 1 /* VTYSH */ +static struct cmd_node debug_node = { + DEBUG_NODE, "", 1 /* VTYSH */ }; -static int -config_write_debug (struct vty *vty) +static int config_write_debug(struct vty *vty) { - int write = 0; - int i, r; - - const char *type_str[] = {"hello", "dd", "ls-request", "ls-update", "ls-ack"}; - const char *detail_str[] = {"", " send", " recv", "", " detail", - " send detail", " recv detail", " detail"}; - - struct ospf *ospf; - char str[16]; - memset (str, 0, 16); - - if ((ospf = ospf_lookup()) == NULL) - return CMD_SUCCESS; - - if (ospf->instance) - sprintf(str, " %d", ospf->instance); - - /* debug ospf ism (status|events|timers). */ - if (IS_CONF_DEBUG_OSPF (ism, ISM) == OSPF_DEBUG_ISM) - vty_out (vty, "debug ospf%s ism\n", str); - else - { - if (IS_CONF_DEBUG_OSPF (ism, ISM_STATUS)) - vty_out (vty, "debug ospf%s ism status\n", str); - if (IS_CONF_DEBUG_OSPF (ism, ISM_EVENTS)) - vty_out (vty, "debug ospf%s ism event\n", str); - if (IS_CONF_DEBUG_OSPF (ism, ISM_TIMERS)) - vty_out (vty, "debug ospf%s ism timer\n", str); - } - - /* debug ospf nsm (status|events|timers). */ - if (IS_CONF_DEBUG_OSPF (nsm, NSM) == OSPF_DEBUG_NSM) - vty_out (vty, "debug ospf%s nsm\n", str); - else - { - if (IS_CONF_DEBUG_OSPF (nsm, NSM_STATUS)) - vty_out (vty, "debug ospf%s nsm status\n", str); - if (IS_CONF_DEBUG_OSPF (nsm, NSM_EVENTS)) - vty_out (vty, "debug ospf%s nsm event\n", str); - if (IS_CONF_DEBUG_OSPF (nsm, NSM_TIMERS)) - vty_out (vty, "debug ospf%s nsm timer\n", str); - } - - /* debug ospf lsa (generate|flooding|install|refresh). */ - if (IS_CONF_DEBUG_OSPF (lsa, LSA) == OSPF_DEBUG_LSA) - vty_out (vty, "debug ospf%s lsa\n", str); - else - { - if (IS_CONF_DEBUG_OSPF (lsa, LSA_GENERATE)) - vty_out (vty, "debug ospf%s lsa generate\n", str); - if (IS_CONF_DEBUG_OSPF (lsa, LSA_FLOODING)) - vty_out (vty, "debug ospf%s lsa flooding\n", str); - if (IS_CONF_DEBUG_OSPF (lsa, LSA_INSTALL)) - vty_out (vty, "debug ospf%s lsa install\n", str); - if (IS_CONF_DEBUG_OSPF (lsa, LSA_REFRESH)) - vty_out (vty, "debug ospf%s lsa refresh\n", str); - - write = 1; - } - - /* debug ospf zebra (interface|redistribute). */ - if (IS_CONF_DEBUG_OSPF (zebra, ZEBRA) == OSPF_DEBUG_ZEBRA) - vty_out (vty, "debug ospf%s zebra\n", str); - else - { - if (IS_CONF_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) - vty_out (vty, "debug ospf%s zebra interface\n", str); - if (IS_CONF_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) - vty_out (vty, "debug ospf%s zebra redistribute\n", str); - - write = 1; - } - - /* debug ospf event. */ - if (IS_CONF_DEBUG_OSPF (event, EVENT) == OSPF_DEBUG_EVENT) - { - vty_out (vty, "debug ospf%s event\n", str); - write = 1; - } - - /* debug ospf nssa. */ - if (IS_CONF_DEBUG_OSPF (nssa, NSSA) == OSPF_DEBUG_NSSA) - { - vty_out (vty, "debug ospf%s nssa\n", str); - write = 1; - } - - /* debug ospf packet all detail. */ - r = OSPF_DEBUG_SEND_RECV|OSPF_DEBUG_DETAIL; - for (i = 0; i < 5; i++) - r &= conf_debug_ospf_packet[i] & (OSPF_DEBUG_SEND_RECV|OSPF_DEBUG_DETAIL); - if (r == (OSPF_DEBUG_SEND_RECV|OSPF_DEBUG_DETAIL)) - { - vty_out (vty, "debug ospf%s packet all detail\n", str); - return 1; - } - - /* debug ospf packet all. */ - r = OSPF_DEBUG_SEND_RECV; - for (i = 0; i < 5; i++) - r &= conf_debug_ospf_packet[i] & OSPF_DEBUG_SEND_RECV; - if (r == OSPF_DEBUG_SEND_RECV) - { - vty_out (vty, "debug ospf%s packet all\n", str); - for (i = 0; i < 5; i++) - if (conf_debug_ospf_packet[i] & OSPF_DEBUG_DETAIL) - vty_out (vty, "debug ospf%s packet %s detail\n", str, - type_str[i]); - return 1; - } - - /* debug ospf packet (hello|dd|ls-request|ls-update|ls-ack) - (send|recv) (detail). */ - for (i = 0; i < 5; i++) - { - if (conf_debug_ospf_packet[i] == 0) - continue; - - vty_out (vty, "debug ospf%s packet %s%s\n", str, - type_str[i],detail_str[conf_debug_ospf_packet[i]]); - write = 1; - } - - return write; + int write = 0; + int i, r; + + const char *type_str[] = {"hello", "dd", "ls-request", "ls-update", + "ls-ack"}; + const char *detail_str[] = { + "", " send", " recv", "", + " detail", " send detail", " recv detail", " detail"}; + + struct ospf *ospf; + char str[16]; + memset(str, 0, 16); + + if ((ospf = ospf_lookup()) == NULL) + return CMD_SUCCESS; + + if (ospf->instance) + sprintf(str, " %d", ospf->instance); + + /* debug ospf ism (status|events|timers). */ + if (IS_CONF_DEBUG_OSPF(ism, ISM) == OSPF_DEBUG_ISM) + vty_out(vty, "debug ospf%s ism\n", str); + else { + if (IS_CONF_DEBUG_OSPF(ism, ISM_STATUS)) + vty_out(vty, "debug ospf%s ism status\n", str); + if (IS_CONF_DEBUG_OSPF(ism, ISM_EVENTS)) + vty_out(vty, "debug ospf%s ism event\n", str); + if (IS_CONF_DEBUG_OSPF(ism, ISM_TIMERS)) + vty_out(vty, "debug ospf%s ism timer\n", str); + } + + /* debug ospf nsm (status|events|timers). */ + if (IS_CONF_DEBUG_OSPF(nsm, NSM) == OSPF_DEBUG_NSM) + vty_out(vty, "debug ospf%s nsm\n", str); + else { + if (IS_CONF_DEBUG_OSPF(nsm, NSM_STATUS)) + vty_out(vty, "debug ospf%s nsm status\n", str); + if (IS_CONF_DEBUG_OSPF(nsm, NSM_EVENTS)) + vty_out(vty, "debug ospf%s nsm event\n", str); + if (IS_CONF_DEBUG_OSPF(nsm, NSM_TIMERS)) + vty_out(vty, "debug ospf%s nsm timer\n", str); + } + + /* debug ospf lsa (generate|flooding|install|refresh). */ + if (IS_CONF_DEBUG_OSPF(lsa, LSA) == OSPF_DEBUG_LSA) + vty_out(vty, "debug ospf%s lsa\n", str); + else { + if (IS_CONF_DEBUG_OSPF(lsa, LSA_GENERATE)) + vty_out(vty, "debug ospf%s lsa generate\n", str); + if (IS_CONF_DEBUG_OSPF(lsa, LSA_FLOODING)) + vty_out(vty, "debug ospf%s lsa flooding\n", str); + if (IS_CONF_DEBUG_OSPF(lsa, LSA_INSTALL)) + vty_out(vty, "debug ospf%s lsa install\n", str); + if (IS_CONF_DEBUG_OSPF(lsa, LSA_REFRESH)) + vty_out(vty, "debug ospf%s lsa refresh\n", str); + + write = 1; + } + + /* debug ospf zebra (interface|redistribute). */ + if (IS_CONF_DEBUG_OSPF(zebra, ZEBRA) == OSPF_DEBUG_ZEBRA) + vty_out(vty, "debug ospf%s zebra\n", str); + else { + if (IS_CONF_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) + vty_out(vty, "debug ospf%s zebra interface\n", str); + if (IS_CONF_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) + vty_out(vty, "debug ospf%s zebra redistribute\n", str); + + write = 1; + } + + /* debug ospf event. */ + if (IS_CONF_DEBUG_OSPF(event, EVENT) == OSPF_DEBUG_EVENT) { + vty_out(vty, "debug ospf%s event\n", str); + write = 1; + } + + /* debug ospf nssa. */ + if (IS_CONF_DEBUG_OSPF(nssa, NSSA) == OSPF_DEBUG_NSSA) { + vty_out(vty, "debug ospf%s nssa\n", str); + write = 1; + } + + /* debug ospf packet all detail. */ + r = OSPF_DEBUG_SEND_RECV | OSPF_DEBUG_DETAIL; + for (i = 0; i < 5; i++) + r &= conf_debug_ospf_packet[i] + & (OSPF_DEBUG_SEND_RECV | OSPF_DEBUG_DETAIL); + if (r == (OSPF_DEBUG_SEND_RECV | OSPF_DEBUG_DETAIL)) { + vty_out(vty, "debug ospf%s packet all detail\n", str); + return 1; + } + + /* debug ospf packet all. */ + r = OSPF_DEBUG_SEND_RECV; + for (i = 0; i < 5; i++) + r &= conf_debug_ospf_packet[i] & OSPF_DEBUG_SEND_RECV; + if (r == OSPF_DEBUG_SEND_RECV) { + vty_out(vty, "debug ospf%s packet all\n", str); + for (i = 0; i < 5; i++) + if (conf_debug_ospf_packet[i] & OSPF_DEBUG_DETAIL) + vty_out(vty, "debug ospf%s packet %s detail\n", + str, type_str[i]); + return 1; + } + + /* debug ospf packet (hello|dd|ls-request|ls-update|ls-ack) + (send|recv) (detail). */ + for (i = 0; i < 5; i++) { + if (conf_debug_ospf_packet[i] == 0) + continue; + + vty_out(vty, "debug ospf%s packet %s%s\n", str, type_str[i], + detail_str[conf_debug_ospf_packet[i]]); + write = 1; + } + + return write; } /* Initialize debug commands. */ -void -debug_init () +void debug_init() { - install_node (&debug_node, config_write_debug); - - install_element (ENABLE_NODE, &show_debugging_ospf_cmd); - install_element (ENABLE_NODE, &debug_ospf_ism_cmd); - install_element (ENABLE_NODE, &debug_ospf_nsm_cmd); - install_element (ENABLE_NODE, &debug_ospf_lsa_cmd); - install_element (ENABLE_NODE, &debug_ospf_zebra_cmd); - install_element (ENABLE_NODE, &debug_ospf_event_cmd); - install_element (ENABLE_NODE, &debug_ospf_nssa_cmd); - install_element (ENABLE_NODE, &debug_ospf_te_cmd); - install_element (ENABLE_NODE, &no_debug_ospf_ism_cmd); - install_element (ENABLE_NODE, &no_debug_ospf_nsm_cmd); - install_element (ENABLE_NODE, &no_debug_ospf_lsa_cmd); - install_element (ENABLE_NODE, &no_debug_ospf_zebra_cmd); - install_element (ENABLE_NODE, &no_debug_ospf_event_cmd); - install_element (ENABLE_NODE, &no_debug_ospf_nssa_cmd); - install_element (ENABLE_NODE, &no_debug_ospf_te_cmd); - - install_element (ENABLE_NODE, &show_debugging_ospf_instance_cmd); - install_element (ENABLE_NODE, &debug_ospf_packet_cmd); - install_element (ENABLE_NODE, &no_debug_ospf_packet_cmd); - - install_element (ENABLE_NODE, &debug_ospf_instance_nsm_cmd); - install_element (ENABLE_NODE, &debug_ospf_instance_lsa_cmd); - install_element (ENABLE_NODE, &debug_ospf_instance_zebra_cmd); - install_element (ENABLE_NODE, &debug_ospf_instance_event_cmd); - install_element (ENABLE_NODE, &debug_ospf_instance_nssa_cmd); - install_element (ENABLE_NODE, &no_debug_ospf_instance_nsm_cmd); - install_element (ENABLE_NODE, &no_debug_ospf_instance_lsa_cmd); - install_element (ENABLE_NODE, &no_debug_ospf_instance_zebra_cmd); - install_element (ENABLE_NODE, &no_debug_ospf_instance_event_cmd); - install_element (ENABLE_NODE, &no_debug_ospf_instance_nssa_cmd); - install_element (ENABLE_NODE, &no_debug_ospf_cmd); - - install_element (CONFIG_NODE, &debug_ospf_packet_cmd); - install_element (CONFIG_NODE, &no_debug_ospf_packet_cmd); - install_element (CONFIG_NODE, &debug_ospf_ism_cmd); - install_element (CONFIG_NODE, &no_debug_ospf_ism_cmd); - - install_element (CONFIG_NODE, &debug_ospf_nsm_cmd); - install_element (CONFIG_NODE, &debug_ospf_lsa_cmd); - install_element (CONFIG_NODE, &debug_ospf_zebra_cmd); - install_element (CONFIG_NODE, &debug_ospf_event_cmd); - install_element (CONFIG_NODE, &debug_ospf_nssa_cmd); - install_element (CONFIG_NODE, &debug_ospf_te_cmd); - install_element (CONFIG_NODE, &no_debug_ospf_nsm_cmd); - install_element (CONFIG_NODE, &no_debug_ospf_lsa_cmd); - install_element (CONFIG_NODE, &no_debug_ospf_zebra_cmd); - install_element (CONFIG_NODE, &no_debug_ospf_event_cmd); - install_element (CONFIG_NODE, &no_debug_ospf_nssa_cmd); - install_element (CONFIG_NODE, &no_debug_ospf_te_cmd); - - install_element (CONFIG_NODE, &debug_ospf_instance_nsm_cmd); - install_element (CONFIG_NODE, &debug_ospf_instance_lsa_cmd); - install_element (CONFIG_NODE, &debug_ospf_instance_zebra_cmd); - install_element (CONFIG_NODE, &debug_ospf_instance_event_cmd); - install_element (CONFIG_NODE, &debug_ospf_instance_nssa_cmd); - install_element (CONFIG_NODE, &no_debug_ospf_instance_nsm_cmd); - install_element (CONFIG_NODE, &no_debug_ospf_instance_lsa_cmd); - install_element (CONFIG_NODE, &no_debug_ospf_instance_zebra_cmd); - install_element (CONFIG_NODE, &no_debug_ospf_instance_event_cmd); - install_element (CONFIG_NODE, &no_debug_ospf_instance_nssa_cmd); - install_element (CONFIG_NODE, &no_debug_ospf_cmd); + install_node(&debug_node, config_write_debug); + + install_element(ENABLE_NODE, &show_debugging_ospf_cmd); + install_element(ENABLE_NODE, &debug_ospf_ism_cmd); + install_element(ENABLE_NODE, &debug_ospf_nsm_cmd); + install_element(ENABLE_NODE, &debug_ospf_lsa_cmd); + install_element(ENABLE_NODE, &debug_ospf_zebra_cmd); + install_element(ENABLE_NODE, &debug_ospf_event_cmd); + install_element(ENABLE_NODE, &debug_ospf_nssa_cmd); + install_element(ENABLE_NODE, &debug_ospf_te_cmd); + install_element(ENABLE_NODE, &no_debug_ospf_ism_cmd); + install_element(ENABLE_NODE, &no_debug_ospf_nsm_cmd); + install_element(ENABLE_NODE, &no_debug_ospf_lsa_cmd); + install_element(ENABLE_NODE, &no_debug_ospf_zebra_cmd); + install_element(ENABLE_NODE, &no_debug_ospf_event_cmd); + install_element(ENABLE_NODE, &no_debug_ospf_nssa_cmd); + install_element(ENABLE_NODE, &no_debug_ospf_te_cmd); + + install_element(ENABLE_NODE, &show_debugging_ospf_instance_cmd); + install_element(ENABLE_NODE, &debug_ospf_packet_cmd); + install_element(ENABLE_NODE, &no_debug_ospf_packet_cmd); + + install_element(ENABLE_NODE, &debug_ospf_instance_nsm_cmd); + install_element(ENABLE_NODE, &debug_ospf_instance_lsa_cmd); + install_element(ENABLE_NODE, &debug_ospf_instance_zebra_cmd); + install_element(ENABLE_NODE, &debug_ospf_instance_event_cmd); + install_element(ENABLE_NODE, &debug_ospf_instance_nssa_cmd); + install_element(ENABLE_NODE, &no_debug_ospf_instance_nsm_cmd); + install_element(ENABLE_NODE, &no_debug_ospf_instance_lsa_cmd); + install_element(ENABLE_NODE, &no_debug_ospf_instance_zebra_cmd); + install_element(ENABLE_NODE, &no_debug_ospf_instance_event_cmd); + install_element(ENABLE_NODE, &no_debug_ospf_instance_nssa_cmd); + install_element(ENABLE_NODE, &no_debug_ospf_cmd); + + install_element(CONFIG_NODE, &debug_ospf_packet_cmd); + install_element(CONFIG_NODE, &no_debug_ospf_packet_cmd); + install_element(CONFIG_NODE, &debug_ospf_ism_cmd); + install_element(CONFIG_NODE, &no_debug_ospf_ism_cmd); + + install_element(CONFIG_NODE, &debug_ospf_nsm_cmd); + install_element(CONFIG_NODE, &debug_ospf_lsa_cmd); + install_element(CONFIG_NODE, &debug_ospf_zebra_cmd); + install_element(CONFIG_NODE, &debug_ospf_event_cmd); + install_element(CONFIG_NODE, &debug_ospf_nssa_cmd); + install_element(CONFIG_NODE, &debug_ospf_te_cmd); + install_element(CONFIG_NODE, &no_debug_ospf_nsm_cmd); + install_element(CONFIG_NODE, &no_debug_ospf_lsa_cmd); + install_element(CONFIG_NODE, &no_debug_ospf_zebra_cmd); + install_element(CONFIG_NODE, &no_debug_ospf_event_cmd); + install_element(CONFIG_NODE, &no_debug_ospf_nssa_cmd); + install_element(CONFIG_NODE, &no_debug_ospf_te_cmd); + + install_element(CONFIG_NODE, &debug_ospf_instance_nsm_cmd); + install_element(CONFIG_NODE, &debug_ospf_instance_lsa_cmd); + install_element(CONFIG_NODE, &debug_ospf_instance_zebra_cmd); + install_element(CONFIG_NODE, &debug_ospf_instance_event_cmd); + install_element(CONFIG_NODE, &debug_ospf_instance_nssa_cmd); + install_element(CONFIG_NODE, &no_debug_ospf_instance_nsm_cmd); + install_element(CONFIG_NODE, &no_debug_ospf_instance_lsa_cmd); + install_element(CONFIG_NODE, &no_debug_ospf_instance_zebra_cmd); + install_element(CONFIG_NODE, &no_debug_ospf_instance_event_cmd); + install_element(CONFIG_NODE, &no_debug_ospf_instance_nssa_cmd); + install_element(CONFIG_NODE, &no_debug_ospf_cmd); } diff --git a/ospfd/ospf_dump.h b/ospfd/ospf_dump.h index 94918c265..ead2f526b 100644 --- a/ospfd/ospf_dump.h +++ b/ospfd/ospf_dump.h @@ -63,50 +63,47 @@ #define CONF_DEBUG_PACKET_OFF(a, b) conf_debug_ospf_packet[a] &= ~(b) #define TERM_DEBUG_PACKET_ON(a, b) term_debug_ospf_packet[a] |= (b) #define TERM_DEBUG_PACKET_OFF(a, b) term_debug_ospf_packet[a] &= ~(b) -#define DEBUG_PACKET_ON(a, b) \ - do { \ - CONF_DEBUG_PACKET_ON(a, b); \ - TERM_DEBUG_PACKET_ON(a, b); \ - } while (0) -#define DEBUG_PACKET_OFF(a, b) \ - do { \ - CONF_DEBUG_PACKET_OFF(a, b); \ - TERM_DEBUG_PACKET_OFF(a, b); \ - } while (0) +#define DEBUG_PACKET_ON(a, b) \ + do { \ + CONF_DEBUG_PACKET_ON(a, b); \ + TERM_DEBUG_PACKET_ON(a, b); \ + } while (0) +#define DEBUG_PACKET_OFF(a, b) \ + do { \ + CONF_DEBUG_PACKET_OFF(a, b); \ + TERM_DEBUG_PACKET_OFF(a, b); \ + } while (0) #define CONF_DEBUG_ON(a, b) conf_debug_ospf_ ## a |= (OSPF_DEBUG_ ## b) #define CONF_DEBUG_OFF(a, b) conf_debug_ospf_ ## a &= ~(OSPF_DEBUG_ ## b) #define TERM_DEBUG_ON(a, b) term_debug_ospf_ ## a |= (OSPF_DEBUG_ ## b) #define TERM_DEBUG_OFF(a, b) term_debug_ospf_ ## a &= ~(OSPF_DEBUG_ ## b) -#define DEBUG_ON(a, b) \ - do { \ - CONF_DEBUG_ON(a, b); \ - TERM_DEBUG_ON(a, b); \ - } while (0) -#define DEBUG_OFF(a, b) \ - do { \ - CONF_DEBUG_OFF(a, b); \ - TERM_DEBUG_OFF(a, b); \ - } while (0) +#define DEBUG_ON(a, b) \ + do { \ + CONF_DEBUG_ON(a, b); \ + TERM_DEBUG_ON(a, b); \ + } while (0) +#define DEBUG_OFF(a, b) \ + do { \ + CONF_DEBUG_OFF(a, b); \ + TERM_DEBUG_OFF(a, b); \ + } while (0) /* Macro for checking debug option. */ -#define IS_DEBUG_OSPF_PACKET(a, b) \ - (term_debug_ospf_packet[a] & OSPF_DEBUG_ ## b) -#define IS_DEBUG_OSPF(a, b) \ - (term_debug_ospf_ ## a & OSPF_DEBUG_ ## b) +#define IS_DEBUG_OSPF_PACKET(a, b) (term_debug_ospf_packet[a] & OSPF_DEBUG_##b) +#define IS_DEBUG_OSPF(a, b) (term_debug_ospf_##a & OSPF_DEBUG_##b) #define IS_DEBUG_OSPF_EVENT IS_DEBUG_OSPF(event,EVENT) #define IS_DEBUG_OSPF_NSSA IS_DEBUG_OSPF(nssa,NSSA) #define IS_DEBUG_OSPF_TE IS_DEBUG_OSPF(te,TE) -#define IS_CONF_DEBUG_OSPF_PACKET(a, b) \ - (conf_debug_ospf_packet[a] & OSPF_DEBUG_ ## b) -#define IS_CONF_DEBUG_OSPF(a, b) \ - (conf_debug_ospf_ ## a & OSPF_DEBUG_ ## b) +#define IS_CONF_DEBUG_OSPF_PACKET(a, b) \ + (conf_debug_ospf_packet[a] & OSPF_DEBUG_##b) +#define IS_CONF_DEBUG_OSPF(a, b) (conf_debug_ospf_##a & OSPF_DEBUG_##b) #ifdef ORIGINAL_CODING -#else /* ORIGINAL_CODING */ +#else /* ORIGINAL_CODING */ struct stream; #endif /* ORIGINAL_CODING */ @@ -127,15 +124,15 @@ extern unsigned long term_debug_ospf_te; extern char *ospf_lsa_type_str[]; /* Prototypes. */ -extern const char *ospf_area_name_string (struct ospf_area *); -extern const char *ospf_area_desc_string (struct ospf_area *); -extern const char *ospf_if_name_string (struct ospf_interface *); -extern void ospf_nbr_state_message (struct ospf_neighbor *, char *, size_t); -extern const char *ospf_timer_dump (struct thread *, char *, size_t); -extern const char *ospf_timeval_dump (struct timeval *, char *, size_t); -extern void ospf_ip_header_dump (struct ip *); -extern void ospf_packet_dump (struct stream *); -extern void debug_init (void); +extern const char *ospf_area_name_string(struct ospf_area *); +extern const char *ospf_area_desc_string(struct ospf_area *); +extern const char *ospf_if_name_string(struct ospf_interface *); +extern void ospf_nbr_state_message(struct ospf_neighbor *, char *, size_t); +extern const char *ospf_timer_dump(struct thread *, char *, size_t); +extern const char *ospf_timeval_dump(struct timeval *, char *, size_t); +extern void ospf_ip_header_dump(struct ip *); +extern void ospf_packet_dump(struct stream *); +extern void debug_init(void); /* Appropriate buffer size to use with ospf_timer_dump and ospf_timeval_dump: */ #define OSPF_TIME_DUMP_SIZE 16 diff --git a/ospfd/ospf_dump_api.c b/ospfd/ospf_dump_api.c index 09f5422ef..3cfe3453a 100644 --- a/ospfd/ospf_dump_api.c +++ b/ospfd/ospf_dump_api.c @@ -30,121 +30,107 @@ #include "ospf_nsm.h" #include "ospf_ism.h" -const struct message ospf_ism_state_msg[] = -{ - { ISM_DependUpon, "DependUpon" }, - { ISM_Down, "Down" }, - { ISM_Loopback, "Loopback" }, - { ISM_Waiting, "Waiting" }, - { ISM_PointToPoint, "Point-To-Point" }, - { ISM_DROther, "DROther" }, - { ISM_Backup, "Backup" }, - { ISM_DR, "DR" }, - { 0 } -}; +const struct message ospf_ism_state_msg[] = { + {ISM_DependUpon, "DependUpon"}, + {ISM_Down, "Down"}, + {ISM_Loopback, "Loopback"}, + {ISM_Waiting, "Waiting"}, + {ISM_PointToPoint, "Point-To-Point"}, + {ISM_DROther, "DROther"}, + {ISM_Backup, "Backup"}, + {ISM_DR, "DR"}, + {0}}; -const struct message ospf_nsm_state_msg[] = -{ - { NSM_DependUpon, "DependUpon" }, - { NSM_Deleted, "Deleted" }, - { NSM_Down, "Down" }, - { NSM_Attempt, "Attempt" }, - { NSM_Init, "Init" }, - { NSM_TwoWay, "2-Way" }, - { NSM_ExStart, "ExStart" }, - { NSM_Exchange, "Exchange" }, - { NSM_Loading, "Loading" }, - { NSM_Full, "Full" }, - { 0 } -}; +const struct message ospf_nsm_state_msg[] = {{NSM_DependUpon, "DependUpon"}, + {NSM_Deleted, "Deleted"}, + {NSM_Down, "Down"}, + {NSM_Attempt, "Attempt"}, + {NSM_Init, "Init"}, + {NSM_TwoWay, "2-Way"}, + {NSM_ExStart, "ExStart"}, + {NSM_Exchange, "Exchange"}, + {NSM_Loading, "Loading"}, + {NSM_Full, "Full"}, + {0}}; -const struct message ospf_lsa_type_msg[] = -{ - { OSPF_UNKNOWN_LSA, "unknown" }, - { OSPF_ROUTER_LSA, "router-LSA" }, - { OSPF_NETWORK_LSA, "network-LSA" }, - { OSPF_SUMMARY_LSA, "summary-LSA" }, - { OSPF_ASBR_SUMMARY_LSA, "summary-LSA" }, - { OSPF_AS_EXTERNAL_LSA, "AS-external-LSA" }, - { OSPF_GROUP_MEMBER_LSA, "GROUP MEMBER LSA" }, - { OSPF_AS_NSSA_LSA, "NSSA-LSA" }, - { 8, "Type-8 LSA" }, - { OSPF_OPAQUE_LINK_LSA, "Link-Local Opaque-LSA" }, - { OSPF_OPAQUE_AREA_LSA, "Area-Local Opaque-LSA" }, - { OSPF_OPAQUE_AS_LSA, "AS-external Opaque-LSA" }, - { 0 } -}; +const struct message ospf_lsa_type_msg[] = { + {OSPF_UNKNOWN_LSA, "unknown"}, + {OSPF_ROUTER_LSA, "router-LSA"}, + {OSPF_NETWORK_LSA, "network-LSA"}, + {OSPF_SUMMARY_LSA, "summary-LSA"}, + {OSPF_ASBR_SUMMARY_LSA, "summary-LSA"}, + {OSPF_AS_EXTERNAL_LSA, "AS-external-LSA"}, + {OSPF_GROUP_MEMBER_LSA, "GROUP MEMBER LSA"}, + {OSPF_AS_NSSA_LSA, "NSSA-LSA"}, + {8, "Type-8 LSA"}, + {OSPF_OPAQUE_LINK_LSA, "Link-Local Opaque-LSA"}, + {OSPF_OPAQUE_AREA_LSA, "Area-Local Opaque-LSA"}, + {OSPF_OPAQUE_AS_LSA, "AS-external Opaque-LSA"}, + {0}}; -const struct message ospf_link_state_id_type_msg[] = -{ - { OSPF_UNKNOWN_LSA, "(unknown)" }, - { OSPF_ROUTER_LSA, "" }, - { OSPF_NETWORK_LSA, "(address of Designated Router)" }, - { OSPF_SUMMARY_LSA, "(summary Network Number)" }, - { OSPF_ASBR_SUMMARY_LSA, "(AS Boundary Router address)" }, - { OSPF_AS_EXTERNAL_LSA, "(External Network Number)" }, - { OSPF_GROUP_MEMBER_LSA, "(Group membership information)" }, - { OSPF_AS_NSSA_LSA, "(External Network Number for NSSA)" }, - { 8, "(Type-8 LSID)" }, - { OSPF_OPAQUE_LINK_LSA, "(Link-Local Opaque-Type/ID)" }, - { OSPF_OPAQUE_AREA_LSA, "(Area-Local Opaque-Type/ID)" }, - { OSPF_OPAQUE_AS_LSA, "(AS-external Opaque-Type/ID)" }, - { 0 } -}; +const struct message ospf_link_state_id_type_msg[] = { + {OSPF_UNKNOWN_LSA, "(unknown)"}, + {OSPF_ROUTER_LSA, ""}, + {OSPF_NETWORK_LSA, "(address of Designated Router)"}, + {OSPF_SUMMARY_LSA, "(summary Network Number)"}, + {OSPF_ASBR_SUMMARY_LSA, "(AS Boundary Router address)"}, + {OSPF_AS_EXTERNAL_LSA, "(External Network Number)"}, + {OSPF_GROUP_MEMBER_LSA, "(Group membership information)"}, + {OSPF_AS_NSSA_LSA, "(External Network Number for NSSA)"}, + {8, "(Type-8 LSID)"}, + {OSPF_OPAQUE_LINK_LSA, "(Link-Local Opaque-Type/ID)"}, + {OSPF_OPAQUE_AREA_LSA, "(Area-Local Opaque-Type/ID)"}, + {OSPF_OPAQUE_AS_LSA, "(AS-external Opaque-Type/ID)"}, + {0}}; -const struct message ospf_network_type_msg[] = -{ - { OSPF_IFTYPE_NONE, "NONE" }, - { OSPF_IFTYPE_POINTOPOINT, "Point-to-Point" }, - { OSPF_IFTYPE_BROADCAST, "Broadcast" }, - { OSPF_IFTYPE_NBMA, "NBMA" }, - { OSPF_IFTYPE_POINTOMULTIPOINT, "Point-to-MultiPoint" }, - { OSPF_IFTYPE_VIRTUALLINK, "Virtual-Link" }, - { 0 } -}; +const struct message ospf_network_type_msg[] = { + {OSPF_IFTYPE_NONE, "NONE"}, + {OSPF_IFTYPE_POINTOPOINT, "Point-to-Point"}, + {OSPF_IFTYPE_BROADCAST, "Broadcast"}, + {OSPF_IFTYPE_NBMA, "NBMA"}, + {OSPF_IFTYPE_POINTOMULTIPOINT, "Point-to-MultiPoint"}, + {OSPF_IFTYPE_VIRTUALLINK, "Virtual-Link"}, + {0}}; /* AuType */ -const struct message ospf_auth_type_str[] = -{ - { OSPF_AUTH_NULL, "Null" }, - { OSPF_AUTH_SIMPLE, "Simple" }, - { OSPF_AUTH_CRYPTOGRAPHIC, "Cryptographic" }, - { 0 } -}; +const struct message ospf_auth_type_str[] = { + {OSPF_AUTH_NULL, "Null"}, + {OSPF_AUTH_SIMPLE, "Simple"}, + {OSPF_AUTH_CRYPTOGRAPHIC, "Cryptographic"}, + {0}}; #define OSPF_OPTION_STR_MAXLEN 24 -char * -ospf_options_dump (u_char options) +char *ospf_options_dump(u_char options) { - static char buf[OSPF_OPTION_STR_MAXLEN]; + static char buf[OSPF_OPTION_STR_MAXLEN]; - snprintf (buf, OSPF_OPTION_STR_MAXLEN, "*|%s|%s|%s|%s|%s|%s|%s", - (options & OSPF_OPTION_O) ? "O" : "-", - (options & OSPF_OPTION_DC) ? "DC" : "-", - (options & OSPF_OPTION_EA) ? "EA" : "-", - (options & OSPF_OPTION_NP) ? "N/P" : "-", - (options & OSPF_OPTION_MC) ? "MC" : "-", - (options & OSPF_OPTION_E) ? "E" : "-", - (options & OSPF_OPTION_MT) ? "M/T" : "-"); + snprintf(buf, OSPF_OPTION_STR_MAXLEN, "*|%s|%s|%s|%s|%s|%s|%s", + (options & OSPF_OPTION_O) ? "O" : "-", + (options & OSPF_OPTION_DC) ? "DC" : "-", + (options & OSPF_OPTION_EA) ? "EA" : "-", + (options & OSPF_OPTION_NP) ? "N/P" : "-", + (options & OSPF_OPTION_MC) ? "MC" : "-", + (options & OSPF_OPTION_E) ? "E" : "-", + (options & OSPF_OPTION_MT) ? "M/T" : "-"); - return buf; + return buf; } -void -ospf_lsa_header_dump (struct lsa_header *lsah) +void ospf_lsa_header_dump(struct lsa_header *lsah) { - const char *lsah_type = lookup_msg(ospf_lsa_type_msg, lsah->type, NULL); + const char *lsah_type = lookup_msg(ospf_lsa_type_msg, lsah->type, NULL); - zlog_debug (" LSA Header"); - zlog_debug (" LS age %d", ntohs (lsah->ls_age)); - zlog_debug (" Options %d (%s)", lsah->options, - ospf_options_dump (lsah->options)); - zlog_debug (" LS type %d (%s)", lsah->type, - (lsah->type ? lsah_type : "unknown type")); - zlog_debug (" Link State ID %s", inet_ntoa (lsah->id)); - zlog_debug (" Advertising Router %s", inet_ntoa (lsah->adv_router)); - zlog_debug (" LS sequence number 0x%lx", (u_long)ntohl (lsah->ls_seqnum)); - zlog_debug (" LS checksum 0x%x", ntohs (lsah->checksum)); - zlog_debug (" length %d", ntohs (lsah->length)); + zlog_debug(" LSA Header"); + zlog_debug(" LS age %d", ntohs(lsah->ls_age)); + zlog_debug(" Options %d (%s)", lsah->options, + ospf_options_dump(lsah->options)); + zlog_debug(" LS type %d (%s)", lsah->type, + (lsah->type ? lsah_type : "unknown type")); + zlog_debug(" Link State ID %s", inet_ntoa(lsah->id)); + zlog_debug(" Advertising Router %s", inet_ntoa(lsah->adv_router)); + zlog_debug(" LS sequence number 0x%lx", + (u_long)ntohl(lsah->ls_seqnum)); + zlog_debug(" LS checksum 0x%x", ntohs(lsah->checksum)); + zlog_debug(" length %d", ntohs(lsah->length)); } diff --git a/ospfd/ospf_dump_api.h b/ospfd/ospf_dump_api.h index 836d23455..359522061 100644 --- a/ospfd/ospf_dump_api.h +++ b/ospfd/ospf_dump_api.h @@ -37,7 +37,7 @@ extern const int ospf_link_state_id_type_msg_max; extern const int ospf_network_type_msg_max; extern const size_t ospf_auth_type_str_max; -extern char *ospf_options_dump (u_char); -extern void ospf_lsa_header_dump (struct lsa_header *); +extern char *ospf_options_dump(u_char); +extern void ospf_lsa_header_dump(struct lsa_header *); #endif /* _ZEBRA_OSPF_DUMP_API_H */ diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index ba3d9e324..c775f2ea2 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -51,171 +51,177 @@ extern struct zclient *zclient; /* Do the LSA acking specified in table 19, Section 13.5, row 2 - * This get called from ospf_flood_out_interface. Declared inline + * This get called from ospf_flood_out_interface. Declared inline * for speed. */ -static void -ospf_flood_delayed_lsa_ack (struct ospf_neighbor *inbr, struct ospf_lsa *lsa) +static void ospf_flood_delayed_lsa_ack(struct ospf_neighbor *inbr, + struct ospf_lsa *lsa) { - /* LSA is more recent than database copy, but was not - flooded back out receiving interface. Delayed - acknowledgment sent. If interface is in Backup state - delayed acknowledgment sent only if advertisement - received from Designated Router, otherwise do nothing See - RFC 2328 Section 13.5 */ - - /* Whether LSA is more recent or not, and whether this is in - response to the LSA being sent out recieving interface has been - worked out previously */ - - /* Deal with router as BDR */ - if (inbr->oi->state == ISM_Backup && ! NBR_IS_DR (inbr)) - return; - - /* Schedule a delayed LSA Ack to be sent */ - listnode_add (inbr->oi->ls_ack, ospf_lsa_lock (lsa)); /* delayed LSA Ack */ + /* LSA is more recent than database copy, but was not + flooded back out receiving interface. Delayed + acknowledgment sent. If interface is in Backup state + delayed acknowledgment sent only if advertisement + received from Designated Router, otherwise do nothing See + RFC 2328 Section 13.5 */ + + /* Whether LSA is more recent or not, and whether this is in + response to the LSA being sent out recieving interface has been + worked out previously */ + + /* Deal with router as BDR */ + if (inbr->oi->state == ISM_Backup && !NBR_IS_DR(inbr)) + return; + + /* Schedule a delayed LSA Ack to be sent */ + listnode_add(inbr->oi->ls_ack, + ospf_lsa_lock(lsa)); /* delayed LSA Ack */ } /* Check LSA is related to external info. */ -struct external_info * -ospf_external_info_check (struct ospf_lsa *lsa) +struct external_info *ospf_external_info_check(struct ospf_lsa *lsa) { - struct as_external_lsa *al; - struct prefix_ipv4 p; - struct route_node *rn; - int type; - - al = (struct as_external_lsa *) lsa->data; - - p.family = AF_INET; - p.prefix = lsa->data->id; - p.prefixlen = ip_masklen (al->mask); - - for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) - { - int redist_on = 0; - - redist_on = is_prefix_default (&p) ? - vrf_bitmap_check (zclient->default_information, VRF_DEFAULT) : - (zclient->mi_redist[AFI_IP][type].enabled || - vrf_bitmap_check (zclient->redist[AFI_IP][type], VRF_DEFAULT)); - //Pending: check for MI above. - if (redist_on) - { - struct list *ext_list; - struct listnode *node; - struct ospf_external *ext; - - ext_list = om->external[type]; - if (!ext_list) - continue; - - for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) - { - rn = NULL; - if (ext->external_info) - rn = route_node_lookup (ext->external_info, - (struct prefix *) &p); - if (rn) - { - route_unlock_node (rn); - if (rn->info != NULL) - return (struct external_info *) rn->info; - } - } - } - } - - return NULL; + struct as_external_lsa *al; + struct prefix_ipv4 p; + struct route_node *rn; + int type; + + al = (struct as_external_lsa *)lsa->data; + + p.family = AF_INET; + p.prefix = lsa->data->id; + p.prefixlen = ip_masklen(al->mask); + + for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { + int redist_on = 0; + + redist_on = + is_prefix_default(&p) + ? vrf_bitmap_check(zclient->default_information, + VRF_DEFAULT) + : (zclient->mi_redist[AFI_IP][type].enabled + || vrf_bitmap_check( + zclient->redist[AFI_IP][type], + VRF_DEFAULT)); + // Pending: check for MI above. + if (redist_on) { + struct list *ext_list; + struct listnode *node; + struct ospf_external *ext; + + ext_list = om->external[type]; + if (!ext_list) + continue; + + for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) { + rn = NULL; + if (ext->external_info) + rn = route_node_lookup( + ext->external_info, + (struct prefix *)&p); + if (rn) { + route_unlock_node(rn); + if (rn->info != NULL) + return (struct external_info *) + rn->info; + } + } + } + } + + return NULL; } -static void -ospf_process_self_originated_lsa (struct ospf *ospf, - struct ospf_lsa *new, struct ospf_area *area) +static void ospf_process_self_originated_lsa(struct ospf *ospf, + struct ospf_lsa *new, + struct ospf_area *area) { - struct ospf_interface *oi; - struct external_info *ei; - struct listnode *node; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[Type%d:%s]: Process self-originated LSA seq 0x%x", - new->data->type, inet_ntoa (new->data->id), - ntohl(new->data->ls_seqnum)); - - /* If we're here, we installed a self-originated LSA that we received - from a neighbor, i.e. it's more recent. We must see whether we want - to originate it. - If yes, we should use this LSA's sequence number and reoriginate - a new instance. - if not --- we must flush this LSA from the domain. */ - switch (new->data->type) - { - case OSPF_ROUTER_LSA: - /* Originate a new instance and schedule flooding */ - if (area->router_lsa_self) - area->router_lsa_self->data->ls_seqnum = new->data->ls_seqnum; - ospf_router_lsa_update_area (area); - return; - case OSPF_NETWORK_LSA: - case OSPF_OPAQUE_LINK_LSA: - /* We must find the interface the LSA could belong to. - If the interface is no more a broadcast type or we are no more - the DR, we flush the LSA otherwise -- create the new instance and - schedule flooding. */ - - /* Look through all interfaces, not just area, since interface - could be moved from one area to another. */ - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) - /* These are sanity check. */ - if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &new->data->id)) - { - if (oi->area != area || - oi->type != OSPF_IFTYPE_BROADCAST || - !IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))) - { - ospf_schedule_lsa_flush_area (area, new); - return; - } - - if (new->data->type == OSPF_OPAQUE_LINK_LSA) - { - ospf_opaque_lsa_refresh (new); - return; - } - - if (oi->network_lsa_self) - oi->network_lsa_self->data->ls_seqnum = new->data->ls_seqnum; - /* Schedule network-LSA origination. */ - ospf_network_lsa_update (oi); - return; - } - break; - case OSPF_SUMMARY_LSA: - case OSPF_ASBR_SUMMARY_LSA: - ospf_schedule_abr_task (ospf); - break; - case OSPF_AS_EXTERNAL_LSA : - case OSPF_AS_NSSA_LSA: - if ( (new->data->type == OSPF_AS_EXTERNAL_LSA) - && CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT)) - { - ospf_translated_nssa_refresh (ospf, NULL, new); - return; - } - ei = ospf_external_info_check (new); - if (ei) - ospf_external_lsa_refresh (ospf, new, ei, LSA_REFRESH_FORCE); - else - ospf_lsa_flush_as (ospf, new); - break; - case OSPF_OPAQUE_AREA_LSA: - ospf_opaque_lsa_refresh (new); - break; - case OSPF_OPAQUE_AS_LSA: - ospf_opaque_lsa_refresh (new); /* Reconsideration may needed. *//* XXX */ - break; - default: - break; - } + struct ospf_interface *oi; + struct external_info *ei; + struct listnode *node; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[Type%d:%s]: Process self-originated LSA seq 0x%x", + new->data->type, inet_ntoa(new->data->id), + ntohl(new->data->ls_seqnum)); + + /* If we're here, we installed a self-originated LSA that we received + from a neighbor, i.e. it's more recent. We must see whether we want + to originate it. + If yes, we should use this LSA's sequence number and reoriginate + a new instance. + if not --- we must flush this LSA from the domain. */ + switch (new->data->type) { + case OSPF_ROUTER_LSA: + /* Originate a new instance and schedule flooding */ + if (area->router_lsa_self) + area->router_lsa_self->data->ls_seqnum = + new->data->ls_seqnum; + ospf_router_lsa_update_area(area); + return; + case OSPF_NETWORK_LSA: + case OSPF_OPAQUE_LINK_LSA: + /* We must find the interface the LSA could belong to. + If the interface is no more a broadcast type or we are no + more + the DR, we flush the LSA otherwise -- create the new instance + and + schedule flooding. */ + + /* Look through all interfaces, not just area, since interface + could be moved from one area to another. */ + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) + /* These are sanity check. */ + if (IPV4_ADDR_SAME(&oi->address->u.prefix4, + &new->data->id)) { + if (oi->area != area + || oi->type != OSPF_IFTYPE_BROADCAST + || !IPV4_ADDR_SAME(&oi->address->u.prefix4, + &DR(oi))) { + ospf_schedule_lsa_flush_area(area, new); + return; + } + + if (new->data->type == OSPF_OPAQUE_LINK_LSA) { + ospf_opaque_lsa_refresh(new); + return; + } + + if (oi->network_lsa_self) + oi->network_lsa_self->data->ls_seqnum = + new->data->ls_seqnum; + /* Schedule network-LSA origination. */ + ospf_network_lsa_update(oi); + return; + } + break; + case OSPF_SUMMARY_LSA: + case OSPF_ASBR_SUMMARY_LSA: + ospf_schedule_abr_task(ospf); + break; + case OSPF_AS_EXTERNAL_LSA: + case OSPF_AS_NSSA_LSA: + if ((new->data->type == OSPF_AS_EXTERNAL_LSA) + && CHECK_FLAG(new->flags, OSPF_LSA_LOCAL_XLT)) { + ospf_translated_nssa_refresh(ospf, NULL, new); + return; + } + ei = ospf_external_info_check(new); + if (ei) + ospf_external_lsa_refresh(ospf, new, ei, + LSA_REFRESH_FORCE); + else + ospf_lsa_flush_as(ospf, new); + break; + case OSPF_OPAQUE_AREA_LSA: + ospf_opaque_lsa_refresh(new); + break; + case OSPF_OPAQUE_AS_LSA: + ospf_opaque_lsa_refresh(new); + /* Reconsideration may needed. */ /* XXX */ + break; + default: + break; + } } /* OSPF LSA flooding -- RFC2328 Section 13.(5). */ @@ -228,7 +234,7 @@ ospf_process_self_originated_lsa (struct ospf *ospf, Type-7's can be received, and if a DR they will also flood the local NSSA Area as Type-7's - If a Self-Originated LSA (now an ASBR), + If a Self-Originated LSA (now an ASBR), The LSDB will be updated as Type-5's, (for continual re-fresh) If an NSSA-IR it is installed/flooded as Type-7, P-bit on. @@ -238,777 +244,757 @@ ospf_process_self_originated_lsa (struct ospf *ospf, translator, then All Type-7s (with P-bit ON) are Translated to Type-5's and flooded to all non-NSSA/STUB areas. - During ASE Calculations, + During ASE Calculations, non-ABRs calculate external routes from Type-7's ABRs calculate external routes from Type-5's and non-self Type-7s */ -int -ospf_flood (struct ospf *ospf, struct ospf_neighbor *nbr, - struct ospf_lsa *current, struct ospf_lsa *new) +int ospf_flood(struct ospf *ospf, struct ospf_neighbor *nbr, + struct ospf_lsa *current, struct ospf_lsa *new) { - struct ospf_interface *oi; - int lsa_ack_flag; - - /* Type-7 LSA's will be flooded throughout their native NSSA area, - but will also be flooded as Type-5's into ABR capable links. */ - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[Flooding]: start, NBR %s (%s), cur(%p), New-LSA[%s]", - inet_ntoa (nbr->router_id), - lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), - (void *)current, - dump_lsa_key (new)); - - oi = nbr->oi; - - /* If there is already a database copy, and if the - database copy was received via flooding and installed less - than MinLSArrival seconds ago, discard the new LSA - (without acknowledging it). */ - if (current != NULL) /* -- endo. */ - { - if (IS_LSA_SELF (current) - && (ntohs (current->data->ls_age) == 0 - && ntohl (current->data->ls_seqnum) == OSPF_INITIAL_SEQUENCE_NUMBER)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[Flooding]: Got a self-originated LSA, " - "while local one is initial instance."); - ; /* Accept this LSA for quick LSDB resynchronization. */ - } - else if (monotime_since (¤t->tv_recv, NULL) - < ospf->min_ls_arrival * 1000LL) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[Flooding]: LSA is received recently."); - return -1; - } - } - - /* Flood the new LSA out some subset of the router's interfaces. - In some cases (e.g., the state of the receiving interface is - DR and the LSA was received from a router other than the - Backup DR) the LSA will be flooded back out the receiving - interface. */ - lsa_ack_flag = ospf_flood_through (ospf, nbr, new); - - /* Remove the current database copy from all neighbors' Link state - retransmission lists. AS_EXTERNAL and AS_EXTERNAL_OPAQUE does - ^^^^^^^^^^^^^^^^^^^^^^^ - not have area ID. - All other (even NSSA's) do have area ID. */ - if (current) - { - switch (current->data->type) - { - case OSPF_AS_EXTERNAL_LSA: - case OSPF_OPAQUE_AS_LSA: - ospf_ls_retransmit_delete_nbr_as (ospf, current); - break; - default: - ospf_ls_retransmit_delete_nbr_area (nbr->oi->area, current); - break; - } - } - - /* Do some internal house keeping that is needed here */ - SET_FLAG (new->flags, OSPF_LSA_RECEIVED); - ospf_lsa_is_self_originated (ospf, new); /* Let it set the flag */ - - /* Install the new LSA in the link state database - (replacing the current database copy). This may cause the - routing table calculation to be scheduled. In addition, - timestamp the new LSA with the current time. The flooding - procedure cannot overwrite the newly installed LSA until - MinLSArrival seconds have elapsed. */ - - if (! (new = ospf_lsa_install (ospf, nbr->oi, new))) - return -1; /* unknown LSA type or any other error condition */ - - /* Acknowledge the receipt of the LSA by sending a Link State - Acknowledgment packet back out the receiving interface. */ - if (lsa_ack_flag) - ospf_flood_delayed_lsa_ack (nbr, new); - - /* If this new LSA indicates that it was originated by the - receiving router itself, the router must take special action, - either updating the LSA or in some cases flushing it from - the routing domain. */ - if (ospf_lsa_is_self_originated (ospf, new)) - ospf_process_self_originated_lsa (ospf, new, oi->area); - else - /* Update statistics value for OSPF-MIB. */ - ospf->rx_lsa_count++; - - return 0; + struct ospf_interface *oi; + int lsa_ack_flag; + + /* Type-7 LSA's will be flooded throughout their native NSSA area, + but will also be flooded as Type-5's into ABR capable links. */ + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[Flooding]: start, NBR %s (%s), cur(%p), New-LSA[%s]", + inet_ntoa(nbr->router_id), + lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), + (void *)current, dump_lsa_key(new)); + + oi = nbr->oi; + + /* If there is already a database copy, and if the + database copy was received via flooding and installed less + than MinLSArrival seconds ago, discard the new LSA + (without acknowledging it). */ + if (current != NULL) /* -- endo. */ + { + if (IS_LSA_SELF(current) + && (ntohs(current->data->ls_age) == 0 + && ntohl(current->data->ls_seqnum) + == OSPF_INITIAL_SEQUENCE_NUMBER)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[Flooding]: Got a self-originated LSA, " + "while local one is initial instance."); + ; /* Accept this LSA for quick LSDB resynchronization. + */ + } else if (monotime_since(¤t->tv_recv, NULL) + < ospf->min_ls_arrival * 1000LL) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[Flooding]: LSA is received recently."); + return -1; + } + } + + /* Flood the new LSA out some subset of the router's interfaces. + In some cases (e.g., the state of the receiving interface is + DR and the LSA was received from a router other than the + Backup DR) the LSA will be flooded back out the receiving + interface. */ + lsa_ack_flag = ospf_flood_through(ospf, nbr, new); + + /* Remove the current database copy from all neighbors' Link state + retransmission lists. AS_EXTERNAL and AS_EXTERNAL_OPAQUE does + ^^^^^^^^^^^^^^^^^^^^^^^ + not have area ID. + All other (even NSSA's) do have area ID. */ + if (current) { + switch (current->data->type) { + case OSPF_AS_EXTERNAL_LSA: + case OSPF_OPAQUE_AS_LSA: + ospf_ls_retransmit_delete_nbr_as(ospf, current); + break; + default: + ospf_ls_retransmit_delete_nbr_area(nbr->oi->area, + current); + break; + } + } + + /* Do some internal house keeping that is needed here */ + SET_FLAG(new->flags, OSPF_LSA_RECEIVED); + ospf_lsa_is_self_originated(ospf, new); /* Let it set the flag */ + + /* Install the new LSA in the link state database + (replacing the current database copy). This may cause the + routing table calculation to be scheduled. In addition, + timestamp the new LSA with the current time. The flooding + procedure cannot overwrite the newly installed LSA until + MinLSArrival seconds have elapsed. */ + + if (!(new = ospf_lsa_install(ospf, nbr->oi, new))) + return -1; /* unknown LSA type or any other error condition */ + + /* Acknowledge the receipt of the LSA by sending a Link State + Acknowledgment packet back out the receiving interface. */ + if (lsa_ack_flag) + ospf_flood_delayed_lsa_ack(nbr, new); + + /* If this new LSA indicates that it was originated by the + receiving router itself, the router must take special action, + either updating the LSA or in some cases flushing it from + the routing domain. */ + if (ospf_lsa_is_self_originated(ospf, new)) + ospf_process_self_originated_lsa(ospf, new, oi->area); + else + /* Update statistics value for OSPF-MIB. */ + ospf->rx_lsa_count++; + + return 0; } /* OSPF LSA flooding -- RFC2328 Section 13.3. */ -static int -ospf_flood_through_interface (struct ospf_interface *oi, - struct ospf_neighbor *inbr, - struct ospf_lsa *lsa) +static int ospf_flood_through_interface(struct ospf_interface *oi, + struct ospf_neighbor *inbr, + struct ospf_lsa *lsa) { - struct ospf_neighbor *onbr; - struct route_node *rn; - int retx_flag; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_flood_through_interface(): " - "considering int %s, INBR(%s), LSA[%s]", - IF_NAME (oi), inbr ? inet_ntoa (inbr->router_id) : "NULL", - dump_lsa_key (lsa)); - - if (!ospf_if_is_enable (oi)) - return 0; - - /* Remember if new LSA is aded to a retransmit list. */ - retx_flag = 0; - - /* Each of the neighbors attached to this interface are examined, - to determine whether they must receive the new LSA. The following - steps are executed for each neighbor: */ - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - { - struct ospf_lsa *ls_req; - - if (rn->info == NULL) - continue; - - onbr = rn->info; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_flood_through_interface(): considering nbr %s (%s)", - inet_ntoa (onbr->router_id), - lookup_msg(ospf_nsm_state_msg, onbr->state, NULL)); - - /* If the neighbor is in a lesser state than Exchange, it - does not participate in flooding, and the next neighbor - should be examined. */ - if (onbr->state < NSM_Exchange) - continue; - - /* If the adjacency is not yet full (neighbor state is - Exchange or Loading), examine the Link state request - list associated with this adjacency. If there is an - instance of the new LSA on the list, it indicates that - the neighboring router has an instance of the LSA - already. Compare the new LSA to the neighbor's copy: */ - if (onbr->state < NSM_Full) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_flood_through_interface(): nbr adj is not Full"); - ls_req = ospf_ls_request_lookup (onbr, lsa); - if (ls_req != NULL) - { - int ret; - - ret = ospf_lsa_more_recent (ls_req, lsa); - /* The new LSA is less recent. */ - if (ret > 0) - continue; - /* The two copies are the same instance, then delete - the LSA from the Link state request list. */ - else if (ret == 0) - { - ospf_ls_request_delete (onbr, ls_req); - ospf_check_nbr_loading (onbr); - continue; + struct ospf_neighbor *onbr; + struct route_node *rn; + int retx_flag; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_flood_through_interface(): " + "considering int %s, INBR(%s), LSA[%s]", + IF_NAME(oi), inbr ? inet_ntoa(inbr->router_id) : "NULL", + dump_lsa_key(lsa)); + + if (!ospf_if_is_enable(oi)) + return 0; + + /* Remember if new LSA is aded to a retransmit list. */ + retx_flag = 0; + + /* Each of the neighbors attached to this interface are examined, + to determine whether they must receive the new LSA. The following + steps are executed for each neighbor: */ + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) { + struct ospf_lsa *ls_req; + + if (rn->info == NULL) + continue; + + onbr = rn->info; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_flood_through_interface(): considering nbr %s (%s)", + inet_ntoa(onbr->router_id), + lookup_msg(ospf_nsm_state_msg, onbr->state, + NULL)); + + /* If the neighbor is in a lesser state than Exchange, it + does not participate in flooding, and the next neighbor + should be examined. */ + if (onbr->state < NSM_Exchange) + continue; + + /* If the adjacency is not yet full (neighbor state is + Exchange or Loading), examine the Link state request + list associated with this adjacency. If there is an + instance of the new LSA on the list, it indicates that + the neighboring router has an instance of the LSA + already. Compare the new LSA to the neighbor's copy: */ + if (onbr->state < NSM_Full) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_flood_through_interface(): nbr adj is not Full"); + ls_req = ospf_ls_request_lookup(onbr, lsa); + if (ls_req != NULL) { + int ret; + + ret = ospf_lsa_more_recent(ls_req, lsa); + /* The new LSA is less recent. */ + if (ret > 0) + continue; + /* The two copies are the same instance, then + delete + the LSA from the Link state request list. */ + else if (ret == 0) { + ospf_ls_request_delete(onbr, ls_req); + ospf_check_nbr_loading(onbr); + continue; + } + /* The new LSA is more recent. Delete the LSA + from the Link state request list. */ + else { + ospf_ls_request_delete(onbr, ls_req); + ospf_check_nbr_loading(onbr); + } + } } - /* The new LSA is more recent. Delete the LSA - from the Link state request list. */ - else - { - ospf_ls_request_delete (onbr, ls_req); - ospf_check_nbr_loading (onbr); + + if (IS_OPAQUE_LSA(lsa->data->type)) { + if (!CHECK_FLAG(onbr->options, OSPF_OPTION_O)) { + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug( + "Skip this neighbor: Not Opaque-capable."); + continue; + } } - } - } - if (IS_OPAQUE_LSA (lsa->data->type)) - { - if (! CHECK_FLAG (onbr->options, OSPF_OPTION_O)) - { - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("Skip this neighbor: Not Opaque-capable."); - continue; - } - } - - /* If the new LSA was received from this neighbor, - examine the next neighbor. */ +/* If the new LSA was received from this neighbor, + examine the next neighbor. */ #ifdef ORIGINAL_CODING - if (inbr) - if (IPV4_ADDR_SAME (&inbr->router_id, &onbr->router_id)) - continue; -#else /* ORIGINAL_CODING */ - if (inbr) - { - /* - * Triggered by LSUpd message parser "ospf_ls_upd ()". - * E.g., all LSAs handling here is received via network. - */ - if (IPV4_ADDR_SAME (&inbr->router_id, &onbr->router_id)) - { - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("Skip this neighbor: inbr == onbr"); - continue; - } - } - else - { - /* - * Triggered by MaxAge remover, so far. - * NULL "inbr" means flooding starts from this node. - */ - if (IPV4_ADDR_SAME (&lsa->data->adv_router, &onbr->router_id)) - { - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("Skip this neighbor: lsah->adv_router == onbr"); - continue; - } - } + if (inbr) + if (IPV4_ADDR_SAME(&inbr->router_id, &onbr->router_id)) + continue; +#else /* ORIGINAL_CODING */ + if (inbr) { + /* + * Triggered by LSUpd message parser "ospf_ls_upd ()". + * E.g., all LSAs handling here is received via network. + */ + if (IPV4_ADDR_SAME(&inbr->router_id, + &onbr->router_id)) { + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug( + "Skip this neighbor: inbr == onbr"); + continue; + } + } else { + /* + * Triggered by MaxAge remover, so far. + * NULL "inbr" means flooding starts from this node. + */ + if (IPV4_ADDR_SAME(&lsa->data->adv_router, + &onbr->router_id)) { + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug( + "Skip this neighbor: lsah->adv_router == onbr"); + continue; + } + } #endif /* ORIGINAL_CODING */ - /* Add the new LSA to the Link state retransmission list - for the adjacency. The LSA will be retransmitted - at intervals until an acknowledgment is seen from - the neighbor. */ - ospf_ls_retransmit_add (onbr, lsa); - retx_flag = 1; - } - - /* If in the previous step, the LSA was NOT added to any of - the Link state retransmission lists, there is no need to - flood the LSA out the interface. */ - if (retx_flag == 0) - { - return (inbr && inbr->oi == oi); - } - - /* if we've received the lsa on this interface we need to perform - additional checking */ - if (inbr && (inbr->oi == oi)) - { - /* If the new LSA was received on this interface, and it was - received from either the Designated Router or the Backup - Designated Router, chances are that all the neighbors have - received the LSA already. */ - if (NBR_IS_DR (inbr) || NBR_IS_BDR (inbr)) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_flood_through_interface(): " - "DR/BDR NOT SEND to int %s", IF_NAME (oi)); - return 1; + /* Add the new LSA to the Link state retransmission list + for the adjacency. The LSA will be retransmitted + at intervals until an acknowledgment is seen from + the neighbor. */ + ospf_ls_retransmit_add(onbr, lsa); + retx_flag = 1; } - - /* If the new LSA was received on this interface, and the - interface state is Backup, examine the next interface. The - Designated Router will do the flooding on this interface. - However, if the Designated Router fails the router will - end up retransmitting the updates. */ - - if (oi->state == ISM_Backup) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_flood_through_interface(): " - "ISM_Backup NOT SEND to int %s", IF_NAME (oi)); - return 1; + + /* If in the previous step, the LSA was NOT added to any of + the Link state retransmission lists, there is no need to + flood the LSA out the interface. */ + if (retx_flag == 0) { + return (inbr && inbr->oi == oi); + } + + /* if we've received the lsa on this interface we need to perform + additional checking */ + if (inbr && (inbr->oi == oi)) { + /* If the new LSA was received on this interface, and it was + received from either the Designated Router or the Backup + Designated Router, chances are that all the neighbors have + received the LSA already. */ + if (NBR_IS_DR(inbr) || NBR_IS_BDR(inbr)) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_flood_through_interface(): " + "DR/BDR NOT SEND to int %s", + IF_NAME(oi)); + return 1; + } + + /* If the new LSA was received on this interface, and the + interface state is Backup, examine the next interface. The + Designated Router will do the flooding on this interface. + However, if the Designated Router fails the router will + end up retransmitting the updates. */ + + if (oi->state == ISM_Backup) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_flood_through_interface(): " + "ISM_Backup NOT SEND to int %s", + IF_NAME(oi)); + return 1; + } } - } - - /* The LSA must be flooded out the interface. Send a Link State - Update packet (including the new LSA as contents) out the - interface. The LSA's LS age must be incremented by InfTransDelay - (which must be > 0) when it is copied into the outgoing Link - State Update packet (until the LS age field reaches the maximum - value of MaxAge). */ - /* XXX HASSO: Is this IS_DEBUG_OSPF_NSSA really correct? */ - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_flood_through_interface(): " - "DR/BDR sending upd to int %s", IF_NAME (oi)); - - /* RFC2328 Section 13.3 - On non-broadcast networks, separate Link State Update - packets must be sent, as unicasts, to each adjacent neighbor - (i.e., those in state Exchange or greater). The destination - IP addresses for these packets are the neighbors' IP - addresses. */ - if (oi->type == OSPF_IFTYPE_NBMA) - { - struct route_node *rn; - struct ospf_neighbor *nbr; - - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange) - ospf_ls_upd_send_lsa (nbr, lsa, OSPF_SEND_PACKET_DIRECT); - } - else - ospf_ls_upd_send_lsa (oi->nbr_self, lsa, OSPF_SEND_PACKET_INDIRECT); - - return 0; + + /* The LSA must be flooded out the interface. Send a Link State + Update packet (including the new LSA as contents) out the + interface. The LSA's LS age must be incremented by InfTransDelay + (which must be > 0) when it is copied into the outgoing Link + State Update packet (until the LS age field reaches the maximum + value of MaxAge). */ + /* XXX HASSO: Is this IS_DEBUG_OSPF_NSSA really correct? */ + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_flood_through_interface(): " + "DR/BDR sending upd to int %s", + IF_NAME(oi)); + + /* RFC2328 Section 13.3 + On non-broadcast networks, separate Link State Update + packets must be sent, as unicasts, to each adjacent neighbor + (i.e., those in state Exchange or greater). The destination + IP addresses for these packets are the neighbors' IP + addresses. */ + if (oi->type == OSPF_IFTYPE_NBMA) { + struct route_node *rn; + struct ospf_neighbor *nbr; + + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info) != NULL) + if (nbr != oi->nbr_self + && nbr->state >= NSM_Exchange) + ospf_ls_upd_send_lsa( + nbr, lsa, + OSPF_SEND_PACKET_DIRECT); + } else + ospf_ls_upd_send_lsa(oi->nbr_self, lsa, + OSPF_SEND_PACKET_INDIRECT); + + return 0; } -int -ospf_flood_through_area (struct ospf_area *area, - struct ospf_neighbor *inbr, struct ospf_lsa *lsa) +int ospf_flood_through_area(struct ospf_area *area, struct ospf_neighbor *inbr, + struct ospf_lsa *lsa) { - struct listnode *node, *nnode; - struct ospf_interface *oi; - int lsa_ack_flag = 0; - - /* All other types are specific to a single area (Area A). The - eligible interfaces are all those interfaces attaching to the - Area A. If Area A is the backbone, this includes all the virtual - links. */ - for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi)) - { - if (area->area_id.s_addr != OSPF_AREA_BACKBONE && - oi->type == OSPF_IFTYPE_VIRTUALLINK) - continue; - - if ((lsa->data->type == OSPF_OPAQUE_LINK_LSA) && (lsa->oi != oi)) - { - /* - * Link local scoped Opaque-LSA should only be flooded - * for the link on which the LSA has received. - */ - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("Type-9 Opaque-LSA: lsa->oi(%p) != oi(%p)", - (void *)lsa->oi, (void *)oi); - continue; - } - - if (ospf_flood_through_interface (oi, inbr, lsa)) - lsa_ack_flag = 1; - } - - return (lsa_ack_flag); + struct listnode *node, *nnode; + struct ospf_interface *oi; + int lsa_ack_flag = 0; + + /* All other types are specific to a single area (Area A). The + eligible interfaces are all those interfaces attaching to the + Area A. If Area A is the backbone, this includes all the virtual + links. */ + for (ALL_LIST_ELEMENTS(area->oiflist, node, nnode, oi)) { + if (area->area_id.s_addr != OSPF_AREA_BACKBONE + && oi->type == OSPF_IFTYPE_VIRTUALLINK) + continue; + + if ((lsa->data->type == OSPF_OPAQUE_LINK_LSA) + && (lsa->oi != oi)) { + /* + * Link local scoped Opaque-LSA should only be flooded + * for the link on which the LSA has received. + */ + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug( + "Type-9 Opaque-LSA: lsa->oi(%p) != oi(%p)", + (void *)lsa->oi, (void *)oi); + continue; + } + + if (ospf_flood_through_interface(oi, inbr, lsa)) + lsa_ack_flag = 1; + } + + return (lsa_ack_flag); } -int -ospf_flood_through_as (struct ospf *ospf, struct ospf_neighbor *inbr, - struct ospf_lsa *lsa) +int ospf_flood_through_as(struct ospf *ospf, struct ospf_neighbor *inbr, + struct ospf_lsa *lsa) { - struct listnode *node; - struct ospf_area *area; - int lsa_ack_flag; - - lsa_ack_flag = 0; + struct listnode *node; + struct ospf_area *area; + int lsa_ack_flag; + + lsa_ack_flag = 0; + + /* The incoming LSA is type 5 or type 7 (AS-EXTERNAL or AS-NSSA ) + + Divert the Type-5 LSA's to all non-NSSA/STUB areas + + Divert the Type-7 LSA's to all NSSA areas + + AS-external-LSAs are flooded throughout the entire AS, with the + exception of stub areas (see Section 3.6). The eligible + interfaces are all the router's interfaces, excluding virtual + links and those interfaces attaching to stub areas. */ + + if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) /* Translated from 7 */ + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("Flood/AS: NSSA TRANSLATED LSA"); + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + int continue_flag = 0; + struct listnode *if_node; + struct ospf_interface *oi; + + switch (area->external_routing) { + /* Don't send AS externals into stub areas. Various types + of support for partial stub areas can be implemented + here. NSSA's will receive Type-7's that have areas + matching the originl LSA. */ + case OSPF_AREA_NSSA: /* Sending Type 5 or 7 into NSSA area */ + /* Type-7, flood NSSA area */ + if (lsa->data->type == OSPF_AS_NSSA_LSA + && area == lsa->area) + /* We will send it. */ + continue_flag = 0; + else + continue_flag = 1; /* Skip this NSSA area for + Type-5's et al */ + break; + + case OSPF_AREA_TYPE_MAX: + case OSPF_AREA_STUB: + continue_flag = 1; /* Skip this area. */ + break; + + case OSPF_AREA_DEFAULT: + default: + /* No Type-7 into normal area */ + if (lsa->data->type == OSPF_AS_NSSA_LSA) + continue_flag = 1; /* skip Type-7 */ + else + continue_flag = 0; /* Do this area. */ + break; + } - /* The incoming LSA is type 5 or type 7 (AS-EXTERNAL or AS-NSSA ) + /* Do continue for above switch. Saves a big if then mess */ + if (continue_flag) + continue; /* main for-loop */ - Divert the Type-5 LSA's to all non-NSSA/STUB areas + /* send to every interface in this area */ - Divert the Type-7 LSA's to all NSSA areas + for (ALL_LIST_ELEMENTS_RO(area->oiflist, if_node, oi)) { + /* Skip virtual links */ + if (oi->type != OSPF_IFTYPE_VIRTUALLINK) + if (ospf_flood_through_interface(oi, inbr, + lsa)) /* lsa */ + lsa_ack_flag = 1; + } + } /* main area for-loop */ - AS-external-LSAs are flooded throughout the entire AS, with the - exception of stub areas (see Section 3.6). The eligible - interfaces are all the router's interfaces, excluding virtual - links and those interfaces attaching to stub areas. */ + return (lsa_ack_flag); +} - if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)) /* Translated from 7 */ - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("Flood/AS: NSSA TRANSLATED LSA"); +int ospf_flood_through(struct ospf *ospf, struct ospf_neighbor *inbr, + struct ospf_lsa *lsa) +{ + int lsa_ack_flag = 0; - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - int continue_flag = 0; - struct listnode *if_node; - struct ospf_interface *oi; +/* Type-7 LSA's for NSSA are flooded throughout the AS here, and + upon return are updated in the LSDB for Type-7's. Later, + re-fresh will re-send them (and also, if ABR, packet code will + translate to Type-5's) - switch (area->external_routing) - { - /* Don't send AS externals into stub areas. Various types - of support for partial stub areas can be implemented - here. NSSA's will receive Type-7's that have areas - matching the originl LSA. */ - case OSPF_AREA_NSSA: /* Sending Type 5 or 7 into NSSA area */ - /* Type-7, flood NSSA area */ - if (lsa->data->type == OSPF_AS_NSSA_LSA - && area == lsa->area) - /* We will send it. */ - continue_flag = 0; - else - continue_flag = 1; /* Skip this NSSA area for Type-5's et al */ - break; - - case OSPF_AREA_TYPE_MAX: - case OSPF_AREA_STUB: - continue_flag = 1; /* Skip this area. */ - break; - - case OSPF_AREA_DEFAULT: + As usual, Type-5 LSA's (if not DISCARDED because we are STUB or + NSSA) are flooded throughout the AS, and are updated in the + global table. */ +#ifdef ORIGINAL_CODING + switch (lsa->data->type) { + case OSPF_ROUTER_LSA: + case OSPF_NETWORK_LSA: + case OSPF_SUMMARY_LSA: + case OSPF_ASBR_SUMMARY_LSA: + case OSPF_OPAQUE_LINK_LSA: /* ospf_flood_through_interface ? */ + case OSPF_OPAQUE_AREA_LSA: + lsa_ack_flag = + ospf_flood_through_area(inbr->oi->area, inbr, lsa); + break; + case OSPF_AS_EXTERNAL_LSA: /* Type-5 */ + case OSPF_OPAQUE_AS_LSA: + lsa_ack_flag = ospf_flood_through_as(ospf, inbr, lsa); + break; + /* Type-7 Only received within NSSA, then flooded */ + case OSPF_AS_NSSA_LSA: + /* Any P-bit was installed with the Type-7. */ + lsa_ack_flag = + ospf_flood_through_area(inbr->oi->area, inbr, lsa); + + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_flood_through: LOCAL NSSA FLOOD of Type-7."); + break; default: - /* No Type-7 into normal area */ - if (lsa->data->type == OSPF_AS_NSSA_LSA) - continue_flag = 1; /* skip Type-7 */ - else - continue_flag = 0; /* Do this area. */ - break; + break; } - - /* Do continue for above switch. Saves a big if then mess */ - if (continue_flag) - continue; /* main for-loop */ - - /* send to every interface in this area */ - - for (ALL_LIST_ELEMENTS_RO (area->oiflist, if_node, oi)) - { - /* Skip virtual links */ - if (oi->type != OSPF_IFTYPE_VIRTUALLINK) - if (ospf_flood_through_interface (oi, inbr, lsa)) /* lsa */ - lsa_ack_flag = 1; +#else /* ORIGINAL_CODING */ + /* + * At the common sub-sub-function "ospf_flood_through_interface()", + * a parameter "inbr" will be used to distinguish the called context + * whether the given LSA was received from the neighbor, or the + * flooding for the LSA starts from this node (e.g. the LSA was self- + * originated, or the LSA is going to be flushed from routing domain). + * + * So, for consistency reasons, this function "ospf_flood_through()" + * should also allow the usage that the given "inbr" parameter to be + * NULL. If we do so, corresponding AREA parameter should be referred + * by "lsa->area", instead of "inbr->oi->area". + */ + switch (lsa->data->type) { + case OSPF_AS_EXTERNAL_LSA: /* Type-5 */ + case OSPF_OPAQUE_AS_LSA: + lsa_ack_flag = ospf_flood_through_as(ospf, inbr, lsa); + break; + /* Type-7 Only received within NSSA, then flooded */ + case OSPF_AS_NSSA_LSA: + /* Any P-bit was installed with the Type-7. */ + + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_flood_through: LOCAL NSSA FLOOD of Type-7."); + /* Fallthrough */ + default: + lsa_ack_flag = ospf_flood_through_area(lsa->area, inbr, lsa); + break; } - } /* main area for-loop */ - - return (lsa_ack_flag); -} - -int -ospf_flood_through (struct ospf *ospf, - struct ospf_neighbor *inbr, struct ospf_lsa *lsa) -{ - int lsa_ack_flag = 0; - - /* Type-7 LSA's for NSSA are flooded throughout the AS here, and - upon return are updated in the LSDB for Type-7's. Later, - re-fresh will re-send them (and also, if ABR, packet code will - translate to Type-5's) - - As usual, Type-5 LSA's (if not DISCARDED because we are STUB or - NSSA) are flooded throughout the AS, and are updated in the - global table. */ -#ifdef ORIGINAL_CODING - switch (lsa->data->type) - { - case OSPF_ROUTER_LSA: - case OSPF_NETWORK_LSA: - case OSPF_SUMMARY_LSA: - case OSPF_ASBR_SUMMARY_LSA: - case OSPF_OPAQUE_LINK_LSA: /* ospf_flood_through_interface ? */ - case OSPF_OPAQUE_AREA_LSA: - lsa_ack_flag = ospf_flood_through_area (inbr->oi->area, inbr, lsa); - break; - case OSPF_AS_EXTERNAL_LSA: /* Type-5 */ - case OSPF_OPAQUE_AS_LSA: - lsa_ack_flag = ospf_flood_through_as (ospf, inbr, lsa); - break; - /* Type-7 Only received within NSSA, then flooded */ - case OSPF_AS_NSSA_LSA: - /* Any P-bit was installed with the Type-7. */ - lsa_ack_flag = ospf_flood_through_area (inbr->oi->area, inbr, lsa); - - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_flood_through: LOCAL NSSA FLOOD of Type-7."); - break; - default: - break; - } -#else /* ORIGINAL_CODING */ - /* - * At the common sub-sub-function "ospf_flood_through_interface()", - * a parameter "inbr" will be used to distinguish the called context - * whether the given LSA was received from the neighbor, or the - * flooding for the LSA starts from this node (e.g. the LSA was self- - * originated, or the LSA is going to be flushed from routing domain). - * - * So, for consistency reasons, this function "ospf_flood_through()" - * should also allow the usage that the given "inbr" parameter to be - * NULL. If we do so, corresponding AREA parameter should be referred - * by "lsa->area", instead of "inbr->oi->area". - */ - switch (lsa->data->type) - { - case OSPF_AS_EXTERNAL_LSA: /* Type-5 */ - case OSPF_OPAQUE_AS_LSA: - lsa_ack_flag = ospf_flood_through_as (ospf, inbr, lsa); - break; - /* Type-7 Only received within NSSA, then flooded */ - case OSPF_AS_NSSA_LSA: - /* Any P-bit was installed with the Type-7. */ - - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_flood_through: LOCAL NSSA FLOOD of Type-7."); - /* Fallthrough */ - default: - lsa_ack_flag = ospf_flood_through_area (lsa->area, inbr, lsa); - break; - } #endif /* ORIGINAL_CODING */ - - return (lsa_ack_flag); -} + return (lsa_ack_flag); +} /* Management functions for neighbor's Link State Request list. */ -void -ospf_ls_request_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) +void ospf_ls_request_add(struct ospf_neighbor *nbr, struct ospf_lsa *lsa) { - /* - * We cannot make use of the newly introduced callback function - * "lsdb->new_lsa_hook" to replace debug output below, just because - * it seems no simple and smart way to pass neighbor information to - * the common function "ospf_lsdb_add()" -- endo. - */ - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("RqstL(%lu)++, NBR(%s), LSA[%s]", - ospf_ls_request_count (nbr), - inet_ntoa (nbr->router_id), dump_lsa_key (lsa)); - - ospf_lsdb_add (&nbr->ls_req, lsa); + /* + * We cannot make use of the newly introduced callback function + * "lsdb->new_lsa_hook" to replace debug output below, just because + * it seems no simple and smart way to pass neighbor information to + * the common function "ospf_lsdb_add()" -- endo. + */ + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug("RqstL(%lu)++, NBR(%s), LSA[%s]", + ospf_ls_request_count(nbr), + inet_ntoa(nbr->router_id), dump_lsa_key(lsa)); + + ospf_lsdb_add(&nbr->ls_req, lsa); } -unsigned long -ospf_ls_request_count (struct ospf_neighbor *nbr) +unsigned long ospf_ls_request_count(struct ospf_neighbor *nbr) { - return ospf_lsdb_count_all (&nbr->ls_req); + return ospf_lsdb_count_all(&nbr->ls_req); } -int -ospf_ls_request_isempty (struct ospf_neighbor *nbr) +int ospf_ls_request_isempty(struct ospf_neighbor *nbr) { - return ospf_lsdb_isempty (&nbr->ls_req); + return ospf_lsdb_isempty(&nbr->ls_req); } /* Remove LSA from neighbor's ls-request list. */ -void -ospf_ls_request_delete (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) +void ospf_ls_request_delete(struct ospf_neighbor *nbr, struct ospf_lsa *lsa) { - if (nbr->ls_req_last == lsa) - { - ospf_lsa_unlock (&nbr->ls_req_last); - nbr->ls_req_last = NULL; - } - - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) /* -- endo. */ - zlog_debug ("RqstL(%lu)--, NBR(%s), LSA[%s]", - ospf_ls_request_count (nbr), - inet_ntoa (nbr->router_id), dump_lsa_key (lsa)); - - ospf_lsdb_delete (&nbr->ls_req, lsa); + if (nbr->ls_req_last == lsa) { + ospf_lsa_unlock(&nbr->ls_req_last); + nbr->ls_req_last = NULL; + } + + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) /* -- endo. */ + zlog_debug("RqstL(%lu)--, NBR(%s), LSA[%s]", + ospf_ls_request_count(nbr), + inet_ntoa(nbr->router_id), dump_lsa_key(lsa)); + + ospf_lsdb_delete(&nbr->ls_req, lsa); } /* Remove all LSA from neighbor's ls-requenst list. */ -void -ospf_ls_request_delete_all (struct ospf_neighbor *nbr) +void ospf_ls_request_delete_all(struct ospf_neighbor *nbr) { - ospf_lsa_unlock (&nbr->ls_req_last); - nbr->ls_req_last = NULL; - ospf_lsdb_delete_all (&nbr->ls_req); + ospf_lsa_unlock(&nbr->ls_req_last); + nbr->ls_req_last = NULL; + ospf_lsdb_delete_all(&nbr->ls_req); } /* Lookup LSA from neighbor's ls-request list. */ -struct ospf_lsa * -ospf_ls_request_lookup (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) +struct ospf_lsa *ospf_ls_request_lookup(struct ospf_neighbor *nbr, + struct ospf_lsa *lsa) { - return ospf_lsdb_lookup (&nbr->ls_req, lsa); + return ospf_lsdb_lookup(&nbr->ls_req, lsa); } -struct ospf_lsa * -ospf_ls_request_new (struct lsa_header *lsah) +struct ospf_lsa *ospf_ls_request_new(struct lsa_header *lsah) { - struct ospf_lsa *new; + struct ospf_lsa *new; - new = ospf_lsa_new (); - new->data = ospf_lsa_data_new (OSPF_LSA_HEADER_SIZE); - memcpy (new->data, lsah, OSPF_LSA_HEADER_SIZE); + new = ospf_lsa_new(); + new->data = ospf_lsa_data_new(OSPF_LSA_HEADER_SIZE); + memcpy(new->data, lsah, OSPF_LSA_HEADER_SIZE); - return new; + return new; } /* Management functions for neighbor's ls-retransmit list. */ -unsigned long -ospf_ls_retransmit_count (struct ospf_neighbor *nbr) +unsigned long ospf_ls_retransmit_count(struct ospf_neighbor *nbr) { - return ospf_lsdb_count_all (&nbr->ls_rxmt); + return ospf_lsdb_count_all(&nbr->ls_rxmt); } -unsigned long -ospf_ls_retransmit_count_self (struct ospf_neighbor *nbr, int lsa_type) +unsigned long ospf_ls_retransmit_count_self(struct ospf_neighbor *nbr, + int lsa_type) { - return ospf_lsdb_count_self (&nbr->ls_rxmt, lsa_type); + return ospf_lsdb_count_self(&nbr->ls_rxmt, lsa_type); } -int -ospf_ls_retransmit_isempty (struct ospf_neighbor *nbr) +int ospf_ls_retransmit_isempty(struct ospf_neighbor *nbr) { - return ospf_lsdb_isempty (&nbr->ls_rxmt); + return ospf_lsdb_isempty(&nbr->ls_rxmt); } /* Add LSA to be retransmitted to neighbor's ls-retransmit list. */ -void -ospf_ls_retransmit_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) +void ospf_ls_retransmit_add(struct ospf_neighbor *nbr, struct ospf_lsa *lsa) { - struct ospf_lsa *old; + struct ospf_lsa *old; - old = ospf_ls_retransmit_lookup (nbr, lsa); + old = ospf_ls_retransmit_lookup(nbr, lsa); - if (ospf_lsa_more_recent (old, lsa) < 0) - { - if (old) - { - old->retransmit_counter--; - ospf_lsdb_delete (&nbr->ls_rxmt, old); + if (ospf_lsa_more_recent(old, lsa) < 0) { + if (old) { + old->retransmit_counter--; + ospf_lsdb_delete(&nbr->ls_rxmt, old); + } + lsa->retransmit_counter++; + /* + * We cannot make use of the newly introduced callback function + * "lsdb->new_lsa_hook" to replace debug output below, just + * because + * it seems no simple and smart way to pass neighbor information + * to + * the common function "ospf_lsdb_add()" -- endo. + */ + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug("RXmtL(%lu)++, NBR(%s), LSA[%s]", + ospf_ls_retransmit_count(nbr), + inet_ntoa(nbr->router_id), + dump_lsa_key(lsa)); + ospf_lsdb_add(&nbr->ls_rxmt, lsa); } - lsa->retransmit_counter++; - /* - * We cannot make use of the newly introduced callback function - * "lsdb->new_lsa_hook" to replace debug output below, just because - * it seems no simple and smart way to pass neighbor information to - * the common function "ospf_lsdb_add()" -- endo. - */ - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("RXmtL(%lu)++, NBR(%s), LSA[%s]", - ospf_ls_retransmit_count (nbr), - inet_ntoa (nbr->router_id), dump_lsa_key (lsa)); - ospf_lsdb_add (&nbr->ls_rxmt, lsa); - } } /* Remove LSA from neibghbor's ls-retransmit list. */ -void -ospf_ls_retransmit_delete (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) +void ospf_ls_retransmit_delete(struct ospf_neighbor *nbr, struct ospf_lsa *lsa) { - if (ospf_ls_retransmit_lookup (nbr, lsa)) - { - lsa->retransmit_counter--; - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) /* -- endo. */ - zlog_debug ("RXmtL(%lu)--, NBR(%s), LSA[%s]", - ospf_ls_retransmit_count (nbr), - inet_ntoa (nbr->router_id), dump_lsa_key (lsa)); - ospf_lsdb_delete (&nbr->ls_rxmt, lsa); - } + if (ospf_ls_retransmit_lookup(nbr, lsa)) { + lsa->retransmit_counter--; + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) /* -- endo. */ + zlog_debug("RXmtL(%lu)--, NBR(%s), LSA[%s]", + ospf_ls_retransmit_count(nbr), + inet_ntoa(nbr->router_id), + dump_lsa_key(lsa)); + ospf_lsdb_delete(&nbr->ls_rxmt, lsa); + } } /* Clear neighbor's ls-retransmit list. */ -void -ospf_ls_retransmit_clear (struct ospf_neighbor *nbr) +void ospf_ls_retransmit_clear(struct ospf_neighbor *nbr) { - struct ospf_lsdb *lsdb; - int i; + struct ospf_lsdb *lsdb; + int i; - lsdb = &nbr->ls_rxmt; + lsdb = &nbr->ls_rxmt; - for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) - { - struct route_table *table = lsdb->type[i].db; - struct route_node *rn; - struct ospf_lsa *lsa; + for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) { + struct route_table *table = lsdb->type[i].db; + struct route_node *rn; + struct ospf_lsa *lsa; - for (rn = route_top (table); rn; rn = route_next (rn)) - if ((lsa = rn->info) != NULL) - ospf_ls_retransmit_delete (nbr, lsa); - } + for (rn = route_top(table); rn; rn = route_next(rn)) + if ((lsa = rn->info) != NULL) + ospf_ls_retransmit_delete(nbr, lsa); + } - ospf_lsa_unlock (&nbr->ls_req_last); - nbr->ls_req_last = NULL; + ospf_lsa_unlock(&nbr->ls_req_last); + nbr->ls_req_last = NULL; } /* Lookup LSA from neighbor's ls-retransmit list. */ -struct ospf_lsa * -ospf_ls_retransmit_lookup (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) +struct ospf_lsa *ospf_ls_retransmit_lookup(struct ospf_neighbor *nbr, + struct ospf_lsa *lsa) { - return ospf_lsdb_lookup (&nbr->ls_rxmt, lsa); + return ospf_lsdb_lookup(&nbr->ls_rxmt, lsa); } -static void -ospf_ls_retransmit_delete_nbr_if (struct ospf_interface *oi, - struct ospf_lsa *lsa) +static void ospf_ls_retransmit_delete_nbr_if(struct ospf_interface *oi, + struct ospf_lsa *lsa) { - struct route_node *rn; - struct ospf_neighbor *nbr; - struct ospf_lsa *lsr; - - if (ospf_if_is_enable (oi)) - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - /* If LSA find in LS-retransmit list, then remove it. */ - if ((nbr = rn->info) != NULL) - { - lsr = ospf_ls_retransmit_lookup (nbr, lsa); - - /* If LSA find in ls-retransmit list, remove it. */ - if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum) - ospf_ls_retransmit_delete (nbr, lsr); - } + struct route_node *rn; + struct ospf_neighbor *nbr; + struct ospf_lsa *lsr; + + if (ospf_if_is_enable(oi)) + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) + /* If LSA find in LS-retransmit list, then remove it. */ + if ((nbr = rn->info) != NULL) { + lsr = ospf_ls_retransmit_lookup(nbr, lsa); + + /* If LSA find in ls-retransmit list, remove it. + */ + if (lsr != NULL + && lsr->data->ls_seqnum + == lsa->data->ls_seqnum) + ospf_ls_retransmit_delete(nbr, lsr); + } } -void -ospf_ls_retransmit_delete_nbr_area (struct ospf_area *area, - struct ospf_lsa *lsa) +void ospf_ls_retransmit_delete_nbr_area(struct ospf_area *area, + struct ospf_lsa *lsa) { - struct listnode *node, *nnode; - struct ospf_interface *oi; + struct listnode *node, *nnode; + struct ospf_interface *oi; - for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi)) - ospf_ls_retransmit_delete_nbr_if (oi, lsa); + for (ALL_LIST_ELEMENTS(area->oiflist, node, nnode, oi)) + ospf_ls_retransmit_delete_nbr_if(oi, lsa); } -void -ospf_ls_retransmit_delete_nbr_as (struct ospf *ospf, struct ospf_lsa *lsa) +void ospf_ls_retransmit_delete_nbr_as(struct ospf *ospf, struct ospf_lsa *lsa) { - struct listnode *node, *nnode; - struct ospf_interface *oi; + struct listnode *node, *nnode; + struct ospf_interface *oi; - for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) - ospf_ls_retransmit_delete_nbr_if (oi, lsa); + for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) + ospf_ls_retransmit_delete_nbr_if(oi, lsa); } -/* Sets ls_age to MaxAge and floods throu the area. +/* Sets ls_age to MaxAge and floods throu the area. When we implement ASE routing, there will be anothe function flushing an LSA from the whole domain. */ -void -ospf_lsa_flush_area (struct ospf_lsa *lsa, struct ospf_area *area) +void ospf_lsa_flush_area(struct ospf_lsa *lsa, struct ospf_area *area) { - /* Reset the lsa origination time such that it gives - more time for the ACK to be received and avoid - retransmissions */ - lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); - monotime(&lsa->tv_recv); - lsa->tv_orig = lsa->tv_recv; - ospf_flood_through_area (area, NULL, lsa); - ospf_lsa_maxage (area->ospf, lsa); + /* Reset the lsa origination time such that it gives + more time for the ACK to be received and avoid + retransmissions */ + lsa->data->ls_age = htons(OSPF_LSA_MAXAGE); + monotime(&lsa->tv_recv); + lsa->tv_orig = lsa->tv_recv; + ospf_flood_through_area(area, NULL, lsa); + ospf_lsa_maxage(area->ospf, lsa); } -void -ospf_lsa_flush_as (struct ospf *ospf, struct ospf_lsa *lsa) +void ospf_lsa_flush_as(struct ospf *ospf, struct ospf_lsa *lsa) { - /* Reset the lsa origination time such that it gives - more time for the ACK to be received and avoid - retransmissions */ - lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); - monotime(&lsa->tv_recv); - lsa->tv_orig = lsa->tv_recv; - ospf_flood_through_as (ospf, NULL, lsa); - ospf_lsa_maxage (ospf, lsa); + /* Reset the lsa origination time such that it gives + more time for the ACK to be received and avoid + retransmissions */ + lsa->data->ls_age = htons(OSPF_LSA_MAXAGE); + monotime(&lsa->tv_recv); + lsa->tv_orig = lsa->tv_recv; + ospf_flood_through_as(ospf, NULL, lsa); + ospf_lsa_maxage(ospf, lsa); } -void -ospf_lsa_flush (struct ospf *ospf, struct ospf_lsa *lsa) +void ospf_lsa_flush(struct ospf *ospf, struct ospf_lsa *lsa) { - lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); - - switch (lsa->data->type) - { - case OSPF_ROUTER_LSA: - case OSPF_NETWORK_LSA: - case OSPF_SUMMARY_LSA: - case OSPF_ASBR_SUMMARY_LSA: - case OSPF_AS_NSSA_LSA: - case OSPF_OPAQUE_LINK_LSA: - case OSPF_OPAQUE_AREA_LSA: - ospf_lsa_flush_area (lsa, lsa->area); - break; - case OSPF_AS_EXTERNAL_LSA: - case OSPF_OPAQUE_AS_LSA: - ospf_lsa_flush_as (ospf, lsa); - break; - default: - zlog_info ("%s: Unknown LSA type %u", __func__, lsa->data->type); - break; - } + lsa->data->ls_age = htons(OSPF_LSA_MAXAGE); + + switch (lsa->data->type) { + case OSPF_ROUTER_LSA: + case OSPF_NETWORK_LSA: + case OSPF_SUMMARY_LSA: + case OSPF_ASBR_SUMMARY_LSA: + case OSPF_AS_NSSA_LSA: + case OSPF_OPAQUE_LINK_LSA: + case OSPF_OPAQUE_AREA_LSA: + ospf_lsa_flush_area(lsa, lsa->area); + break; + case OSPF_AS_EXTERNAL_LSA: + case OSPF_OPAQUE_AS_LSA: + ospf_lsa_flush_as(ospf, lsa); + break; + default: + zlog_info("%s: Unknown LSA type %u", __func__, lsa->data->type); + break; + } } diff --git a/ospfd/ospf_flood.h b/ospfd/ospf_flood.h index b08385754..b74894567 100644 --- a/ospfd/ospf_flood.h +++ b/ospfd/ospf_flood.h @@ -22,52 +22,47 @@ #ifndef _ZEBRA_OSPF_FLOOD_H #define _ZEBRA_OSPF_FLOOD_H -extern int ospf_flood (struct ospf *, struct ospf_neighbor *, - struct ospf_lsa *, struct ospf_lsa *); -extern int ospf_flood_through (struct ospf *, struct ospf_neighbor *, - struct ospf_lsa *); -extern int ospf_flood_through_area (struct ospf_area *, - struct ospf_neighbor *, - struct ospf_lsa *); -extern int ospf_flood_through_as (struct ospf *, struct ospf_neighbor *, - struct ospf_lsa *); +extern int ospf_flood(struct ospf *, struct ospf_neighbor *, struct ospf_lsa *, + struct ospf_lsa *); +extern int ospf_flood_through(struct ospf *, struct ospf_neighbor *, + struct ospf_lsa *); +extern int ospf_flood_through_area(struct ospf_area *, struct ospf_neighbor *, + struct ospf_lsa *); +extern int ospf_flood_through_as(struct ospf *, struct ospf_neighbor *, + struct ospf_lsa *); -extern unsigned long ospf_ls_request_count (struct ospf_neighbor *); -extern int ospf_ls_request_isempty (struct ospf_neighbor *); -extern struct ospf_lsa *ospf_ls_request_new (struct lsa_header *); -extern void ospf_ls_request_free (struct ospf_lsa *); -extern void ospf_ls_request_add (struct ospf_neighbor *, struct ospf_lsa *); -extern void ospf_ls_request_delete (struct ospf_neighbor *, - struct ospf_lsa *); -extern void ospf_ls_request_delete_all (struct ospf_neighbor *); -extern struct ospf_lsa *ospf_ls_request_lookup (struct ospf_neighbor *, - struct ospf_lsa *); +extern unsigned long ospf_ls_request_count(struct ospf_neighbor *); +extern int ospf_ls_request_isempty(struct ospf_neighbor *); +extern struct ospf_lsa *ospf_ls_request_new(struct lsa_header *); +extern void ospf_ls_request_free(struct ospf_lsa *); +extern void ospf_ls_request_add(struct ospf_neighbor *, struct ospf_lsa *); +extern void ospf_ls_request_delete(struct ospf_neighbor *, struct ospf_lsa *); +extern void ospf_ls_request_delete_all(struct ospf_neighbor *); +extern struct ospf_lsa *ospf_ls_request_lookup(struct ospf_neighbor *, + struct ospf_lsa *); -extern unsigned long ospf_ls_retransmit_count (struct ospf_neighbor *); -extern unsigned long ospf_ls_retransmit_count_self (struct ospf_neighbor *, - int); -extern int ospf_ls_retransmit_isempty (struct ospf_neighbor *); -extern void ospf_ls_retransmit_add (struct ospf_neighbor *, - struct ospf_lsa *); -extern void ospf_ls_retransmit_delete (struct ospf_neighbor *, - struct ospf_lsa *); -extern void ospf_ls_retransmit_clear (struct ospf_neighbor *); -extern struct ospf_lsa *ospf_ls_retransmit_lookup (struct ospf_neighbor *, - struct ospf_lsa *); -extern void ospf_ls_retransmit_delete_nbr_area (struct ospf_area *, - struct ospf_lsa *); -extern void ospf_ls_retransmit_delete_nbr_as (struct ospf *, - struct ospf_lsa *); -extern void ospf_ls_retransmit_add_nbr_all (struct ospf_interface *, - struct ospf_lsa *); +extern unsigned long ospf_ls_retransmit_count(struct ospf_neighbor *); +extern unsigned long ospf_ls_retransmit_count_self(struct ospf_neighbor *, int); +extern int ospf_ls_retransmit_isempty(struct ospf_neighbor *); +extern void ospf_ls_retransmit_add(struct ospf_neighbor *, struct ospf_lsa *); +extern void ospf_ls_retransmit_delete(struct ospf_neighbor *, + struct ospf_lsa *); +extern void ospf_ls_retransmit_clear(struct ospf_neighbor *); +extern struct ospf_lsa *ospf_ls_retransmit_lookup(struct ospf_neighbor *, + struct ospf_lsa *); +extern void ospf_ls_retransmit_delete_nbr_area(struct ospf_area *, + struct ospf_lsa *); +extern void ospf_ls_retransmit_delete_nbr_as(struct ospf *, struct ospf_lsa *); +extern void ospf_ls_retransmit_add_nbr_all(struct ospf_interface *, + struct ospf_lsa *); -extern void ospf_flood_lsa_area (struct ospf_lsa *, struct ospf_area *); -extern void ospf_flood_lsa_as (struct ospf_lsa *); -extern void ospf_lsa_flush_area (struct ospf_lsa *, struct ospf_area *); -extern void ospf_lsa_flush_as (struct ospf *, struct ospf_lsa *); -extern void ospf_lsa_flush (struct ospf *, struct ospf_lsa *); -extern struct external_info *ospf_external_info_check (struct ospf_lsa *); +extern void ospf_flood_lsa_area(struct ospf_lsa *, struct ospf_area *); +extern void ospf_flood_lsa_as(struct ospf_lsa *); +extern void ospf_lsa_flush_area(struct ospf_lsa *, struct ospf_area *); +extern void ospf_lsa_flush_as(struct ospf *, struct ospf_lsa *); +extern void ospf_lsa_flush(struct ospf *, struct ospf_lsa *); +extern struct external_info *ospf_external_info_check(struct ospf_lsa *); -extern void ospf_lsdb_init (struct ospf_lsdb *); +extern void ospf_lsdb_init(struct ospf_lsdb *); #endif /* _ZEBRA_OSPF_FLOOD_H */ diff --git a/ospfd/ospf_ia.c b/ospfd/ospf_ia.c index ebd267ded..c65d8b874 100644 --- a/ospfd/ospf_ia.c +++ b/ospfd/ospf_ia.c @@ -45,670 +45,662 @@ #include "ospfd/ospf_ia.h" #include "ospfd/ospf_dump.h" -static struct ospf_route * -ospf_find_abr_route (struct route_table *rtrs, - struct prefix_ipv4 *abr, - struct ospf_area *area) +static struct ospf_route *ospf_find_abr_route(struct route_table *rtrs, + struct prefix_ipv4 *abr, + struct ospf_area *area) { - struct route_node *rn; - struct ospf_route *or; - struct listnode *node; + struct route_node *rn; + struct ospf_route * or ; + struct listnode *node; - if ((rn = route_node_lookup (rtrs, (struct prefix *) abr)) == NULL) - return NULL; + if ((rn = route_node_lookup(rtrs, (struct prefix *)abr)) == NULL) + return NULL; - route_unlock_node (rn); + route_unlock_node(rn); - for (ALL_LIST_ELEMENTS_RO ((struct list *) rn->info, node, or)) - if (IPV4_ADDR_SAME (&or->u.std.area_id, &area->area_id) - && (or->u.std.flags & ROUTER_LSA_BORDER)) - return or; + for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node, or)) + if (IPV4_ADDR_SAME(& or->u.std.area_id, &area->area_id) + && (or->u.std.flags & ROUTER_LSA_BORDER)) + return or ; - return NULL; + return NULL; } -static void -ospf_ia_network_route (struct ospf *ospf, struct route_table *rt, - struct prefix_ipv4 *p, struct ospf_route *new_or, - struct ospf_route *abr_or) +static void ospf_ia_network_route(struct ospf *ospf, struct route_table *rt, + struct prefix_ipv4 *p, + struct ospf_route *new_or, + struct ospf_route *abr_or) { - struct route_node *rn1; - struct ospf_route *or; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_ia_network_route(): processing summary route to %s/%d", - inet_ntoa (p->prefix), p->prefixlen); - - /* Find a route to the same dest */ - if ((rn1 = route_node_lookup (rt, (struct prefix *) p))) - { - int res; - - route_unlock_node (rn1); - - if ((or = rn1->info)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_ia_network_route(): " - "Found a route to the same network"); - /* Check the existing route. */ - if ((res = ospf_route_cmp (ospf, new_or, or)) < 0) - { - /* New route is better, so replace old one. */ - ospf_route_subst (rn1, new_or, abr_or); - } - else if (res == 0) - { - /* New and old route are equal, so next hops can be added. */ - route_lock_node (rn1); - ospf_route_copy_nexthops (or, abr_or->paths); - route_unlock_node (rn1); - - /* new route can be deleted, because existing route has been updated. */ - ospf_route_free (new_or); - } - else - { - /* New route is worse, so free it. */ - ospf_route_free (new_or); - return; - } - } /* if (or)*/ - } /*if (rn1)*/ - else - { /* no route */ - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_ia_network_route(): add new route to %s/%d", - inet_ntoa (p->prefix), p->prefixlen); - ospf_route_add (rt, p, new_or, abr_or); - } + struct route_node *rn1; + struct ospf_route * or ; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_ia_network_route(): processing summary route to %s/%d", + inet_ntoa(p->prefix), p->prefixlen); + + /* Find a route to the same dest */ + if ((rn1 = route_node_lookup(rt, (struct prefix *)p))) { + int res; + + route_unlock_node(rn1); + + if ((or = rn1->info)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_ia_network_route(): " + "Found a route to the same network"); + /* Check the existing route. */ + if ((res = ospf_route_cmp(ospf, new_or, or)) < 0) { + /* New route is better, so replace old one. */ + ospf_route_subst(rn1, new_or, abr_or); + } else if (res == 0) { + /* New and old route are equal, so next hops can + * be added. */ + route_lock_node(rn1); + ospf_route_copy_nexthops(or, abr_or->paths); + route_unlock_node(rn1); + + /* new route can be deleted, because existing + * route has been updated. */ + ospf_route_free(new_or); + } else { + /* New route is worse, so free it. */ + ospf_route_free(new_or); + return; + } + } /* if (or)*/ + } /*if (rn1)*/ + else { /* no route */ + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_ia_network_route(): add new route to %s/%d", + inet_ntoa(p->prefix), p->prefixlen); + ospf_route_add(rt, p, new_or, abr_or); + } } -static void -ospf_ia_router_route (struct ospf *ospf, struct route_table *rtrs, - struct prefix_ipv4 *p, - struct ospf_route *new_or, struct ospf_route *abr_or) +static void ospf_ia_router_route(struct ospf *ospf, struct route_table *rtrs, + struct prefix_ipv4 *p, + struct ospf_route *new_or, + struct ospf_route *abr_or) { - struct ospf_route *or = NULL; - struct route_node *rn; - int ret; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_ia_router_route(): considering %s/%d", - inet_ntoa (p->prefix), p->prefixlen); - /* Find a route to the same dest */ - rn = route_node_get (rtrs, (struct prefix *) p); - - if (rn->info == NULL) - /* This is a new route */ - rn->info = list_new (); - else - { - struct ospf_area *or_area; - or_area = ospf_area_lookup_by_area_id (ospf, new_or->u.std.area_id); - assert (or_area); - /* This is an additional route */ - route_unlock_node (rn); - or = ospf_find_asbr_route_through_area (rtrs, p, or_area); - } - - if (or) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_ia_router_route(): " - "a route to the same ABR through the same area exists"); - /* New route is better */ - if ((ret = ospf_route_cmp (ospf, new_or, or)) < 0) - { - listnode_delete (rn->info, or); - ospf_route_free (or); - /* proceed down */ + struct ospf_route * or = NULL; + struct route_node *rn; + int ret; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_ia_router_route(): considering %s/%d", + inet_ntoa(p->prefix), p->prefixlen); + /* Find a route to the same dest */ + rn = route_node_get(rtrs, (struct prefix *)p); + + if (rn->info == NULL) + /* This is a new route */ + rn->info = list_new(); + else { + struct ospf_area *or_area; + or_area = ospf_area_lookup_by_area_id(ospf, + new_or->u.std.area_id); + assert(or_area); + /* This is an additional route */ + route_unlock_node(rn); + or = ospf_find_asbr_route_through_area(rtrs, p, or_area); } - /* Routes are the same */ - else if (ret == 0) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_ia_router_route(): merging the new route"); - ospf_route_copy_nexthops (or, abr_or->paths); - ospf_route_free (new_or); - return; - } - /* New route is worse */ - else - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_ia_router_route(): skipping the new route"); - ospf_route_free (new_or); - return; + if (or) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_ia_router_route(): " + "a route to the same ABR through the same area exists"); + /* New route is better */ + if ((ret = ospf_route_cmp(ospf, new_or, or)) < 0) { + listnode_delete(rn->info, or); + ospf_route_free(or); + /* proceed down */ + } + /* Routes are the same */ + else if (ret == 0) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_ia_router_route(): merging the new route"); + + ospf_route_copy_nexthops(or, abr_or->paths); + ospf_route_free(new_or); + return; + } + /* New route is worse */ + else { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_ia_router_route(): skipping the new route"); + ospf_route_free(new_or); + return; + } } - } - ospf_route_copy_nexthops (new_or, abr_or->paths); + ospf_route_copy_nexthops(new_or, abr_or->paths); - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_ia_router_route(): adding the new route"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_ia_router_route(): adding the new route"); - listnode_add (rn->info, new_or); + listnode_add(rn->info, new_or); } -static int -process_summary_lsa (struct ospf_area *area, struct route_table *rt, - struct route_table *rtrs, struct ospf_lsa *lsa) +static int process_summary_lsa(struct ospf_area *area, struct route_table *rt, + struct route_table *rtrs, struct ospf_lsa *lsa) { - struct ospf *ospf = area->ospf; - struct ospf_area_range *range; - struct ospf_route *abr_or, *new_or; - struct summary_lsa *sl; - struct prefix_ipv4 p, abr; - u_int32_t metric; - - if (lsa == NULL) - return 0; - - sl = (struct summary_lsa *) lsa->data; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("process_summary_lsa(): LS ID: %s", inet_ntoa (sl->header.id)); - - metric = GET_METRIC (sl->metric); - - if (metric == OSPF_LS_INFINITY) - return 0; - - if (IS_LSA_MAXAGE (lsa)) - return 0; - - if (ospf_lsa_is_self_originated (area->ospf, lsa)) - return 0; - - p.family = AF_INET; - p.prefix = sl->header.id; - - if (sl->header.type == OSPF_SUMMARY_LSA) - p.prefixlen = ip_masklen (sl->mask); - else - p.prefixlen = IPV4_MAX_BITLEN; - - apply_mask_ipv4 (&p); - - if (sl->header.type == OSPF_SUMMARY_LSA && - (range = ospf_area_range_match_any (ospf, &p)) && - ospf_area_range_active (range)) - return 0; - - /* XXX: This check seems dubious to me. If an ABR has already decided - * to consider summaries received in this area, then why would one wish - * to exclude default? - */ - if (IS_OSPF_ABR(ospf) && - ospf->abr_type != OSPF_ABR_STAND && - area->external_routing != OSPF_AREA_DEFAULT && - p.prefix.s_addr == OSPF_DEFAULT_DESTINATION && - p.prefixlen == 0) - return 0; /* Ignore summary default from a stub area */ - - abr.family = AF_INET; - abr.prefix = sl->header.adv_router; - abr.prefixlen = IPV4_MAX_BITLEN; - apply_mask_ipv4 (&abr); - - abr_or = ospf_find_abr_route (rtrs, &abr, area); - - if (abr_or == NULL) - return 0; - - new_or = ospf_route_new (); - new_or->type = OSPF_DESTINATION_NETWORK; - new_or->id = sl->header.id; - new_or->mask = sl->mask; - new_or->u.std.options = sl->header.options; - new_or->u.std.origin = (struct lsa_header *) sl; - new_or->cost = abr_or->cost + metric; - new_or->u.std.area_id = area->area_id; - new_or->u.std.external_routing = area->external_routing; - new_or->path_type = OSPF_PATH_INTER_AREA; - - if (sl->header.type == OSPF_SUMMARY_LSA) - ospf_ia_network_route (ospf, rt, &p, new_or, abr_or); - else - { - new_or->type = OSPF_DESTINATION_ROUTER; - new_or->u.std.flags = ROUTER_LSA_EXTERNAL; - ospf_ia_router_route (ospf, rtrs, &p, new_or, abr_or); - } - - return 0; + struct ospf *ospf = area->ospf; + struct ospf_area_range *range; + struct ospf_route *abr_or, *new_or; + struct summary_lsa *sl; + struct prefix_ipv4 p, abr; + u_int32_t metric; + + if (lsa == NULL) + return 0; + + sl = (struct summary_lsa *)lsa->data; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("process_summary_lsa(): LS ID: %s", + inet_ntoa(sl->header.id)); + + metric = GET_METRIC(sl->metric); + + if (metric == OSPF_LS_INFINITY) + return 0; + + if (IS_LSA_MAXAGE(lsa)) + return 0; + + if (ospf_lsa_is_self_originated(area->ospf, lsa)) + return 0; + + p.family = AF_INET; + p.prefix = sl->header.id; + + if (sl->header.type == OSPF_SUMMARY_LSA) + p.prefixlen = ip_masklen(sl->mask); + else + p.prefixlen = IPV4_MAX_BITLEN; + + apply_mask_ipv4(&p); + + if (sl->header.type == OSPF_SUMMARY_LSA + && (range = ospf_area_range_match_any(ospf, &p)) + && ospf_area_range_active(range)) + return 0; + + /* XXX: This check seems dubious to me. If an ABR has already decided + * to consider summaries received in this area, then why would one wish + * to exclude default? + */ + if (IS_OSPF_ABR(ospf) && ospf->abr_type != OSPF_ABR_STAND + && area->external_routing != OSPF_AREA_DEFAULT + && p.prefix.s_addr == OSPF_DEFAULT_DESTINATION && p.prefixlen == 0) + return 0; /* Ignore summary default from a stub area */ + + abr.family = AF_INET; + abr.prefix = sl->header.adv_router; + abr.prefixlen = IPV4_MAX_BITLEN; + apply_mask_ipv4(&abr); + + abr_or = ospf_find_abr_route(rtrs, &abr, area); + + if (abr_or == NULL) + return 0; + + new_or = ospf_route_new(); + new_or->type = OSPF_DESTINATION_NETWORK; + new_or->id = sl->header.id; + new_or->mask = sl->mask; + new_or->u.std.options = sl->header.options; + new_or->u.std.origin = (struct lsa_header *)sl; + new_or->cost = abr_or->cost + metric; + new_or->u.std.area_id = area->area_id; + new_or->u.std.external_routing = area->external_routing; + new_or->path_type = OSPF_PATH_INTER_AREA; + + if (sl->header.type == OSPF_SUMMARY_LSA) + ospf_ia_network_route(ospf, rt, &p, new_or, abr_or); + else { + new_or->type = OSPF_DESTINATION_ROUTER; + new_or->u.std.flags = ROUTER_LSA_EXTERNAL; + ospf_ia_router_route(ospf, rtrs, &p, new_or, abr_or); + } + + return 0; } -static void -ospf_examine_summaries (struct ospf_area *area, - struct route_table *lsdb_rt, - struct route_table *rt, - struct route_table *rtrs) +static void ospf_examine_summaries(struct ospf_area *area, + struct route_table *lsdb_rt, + struct route_table *rt, + struct route_table *rtrs) { - struct ospf_lsa *lsa; - struct route_node *rn; + struct ospf_lsa *lsa; + struct route_node *rn; - LSDB_LOOP (lsdb_rt, rn, lsa) - process_summary_lsa (area, rt, rtrs, lsa); + LSDB_LOOP(lsdb_rt, rn, lsa) + process_summary_lsa(area, rt, rtrs, lsa); } -int -ospf_area_is_transit (struct ospf_area *area) +int ospf_area_is_transit(struct ospf_area *area) { - return (area->transit == OSPF_TRANSIT_TRUE) || - ospf_full_virtual_nbrs(area); /* Cisco forgets to set the V-bit :( */ + return (area->transit == OSPF_TRANSIT_TRUE) + || ospf_full_virtual_nbrs( + area); /* Cisco forgets to set the V-bit :( */ } -static void -ospf_update_network_route (struct ospf *ospf, - struct route_table *rt, - struct route_table *rtrs, - struct summary_lsa *lsa, - struct prefix_ipv4 *p, - struct ospf_area *area) +static void ospf_update_network_route(struct ospf *ospf, struct route_table *rt, + struct route_table *rtrs, + struct summary_lsa *lsa, + struct prefix_ipv4 *p, + struct ospf_area *area) { - struct route_node *rn; - struct ospf_route *or, *abr_or, *new_or; - struct prefix_ipv4 abr; - u_int32_t cost; - - abr.family = AF_INET; - abr.prefix =lsa->header.adv_router; - abr.prefixlen = IPV4_MAX_BITLEN; - apply_mask_ipv4 (&abr); - - abr_or = ospf_find_abr_route (rtrs, &abr, area); - - if (abr_or == NULL) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_update_network_route(): can't find a route to the ABR"); - return; - } - - cost = abr_or->cost + GET_METRIC (lsa->metric); - - rn = route_node_lookup (rt, (struct prefix *) p); - - if (! rn) - { - if (ospf->abr_type != OSPF_ABR_SHORTCUT) - return; /* Standard ABR can update only already installed - backbone paths */ - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_update_network_route(): " - "Allowing Shortcut ABR to add new route"); - new_or = ospf_route_new (); - new_or->type = OSPF_DESTINATION_NETWORK; - new_or->id = lsa->header.id; - new_or->mask = lsa->mask; - new_or->u.std.options = lsa->header.options; - new_or->u.std.origin = (struct lsa_header *) lsa; - new_or->cost = cost; - new_or->u.std.area_id = area->area_id; - new_or->u.std.external_routing = area->external_routing; - new_or->path_type = OSPF_PATH_INTER_AREA; - ospf_route_add (rt, p, new_or, abr_or); - - return; - } - else - { - route_unlock_node (rn); - if (rn->info == NULL) - return; - } - - or = rn->info; - - if (or->path_type != OSPF_PATH_INTRA_AREA && - or->path_type != OSPF_PATH_INTER_AREA) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_update_network_route(): ERR: path type is wrong"); - return; - } - - if (ospf->abr_type == OSPF_ABR_SHORTCUT) - { - if (or->path_type == OSPF_PATH_INTRA_AREA && - !OSPF_IS_AREA_ID_BACKBONE (or->u.std.area_id)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_update_network_route(): Shortcut: " - "this intra-area path is not backbone"); - return; + struct route_node *rn; + struct ospf_route * or, *abr_or, *new_or; + struct prefix_ipv4 abr; + u_int32_t cost; + + abr.family = AF_INET; + abr.prefix = lsa->header.adv_router; + abr.prefixlen = IPV4_MAX_BITLEN; + apply_mask_ipv4(&abr); + + abr_or = ospf_find_abr_route(rtrs, &abr, area); + + if (abr_or == NULL) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_update_network_route(): can't find a route to the ABR"); + return; } - } - else /* Not Shortcut ABR */ - { - if (!OSPF_IS_AREA_ID_BACKBONE (or->u.std.area_id)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_update_network_route(): " - "route is not BB-associated"); - return; /* We can update only BB routes */ + + cost = abr_or->cost + GET_METRIC(lsa->metric); + + rn = route_node_lookup(rt, (struct prefix *)p); + + if (!rn) { + if (ospf->abr_type != OSPF_ABR_SHORTCUT) + return; /* Standard ABR can update only already + installed + backbone paths */ + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_update_network_route(): " + "Allowing Shortcut ABR to add new route"); + new_or = ospf_route_new(); + new_or->type = OSPF_DESTINATION_NETWORK; + new_or->id = lsa->header.id; + new_or->mask = lsa->mask; + new_or->u.std.options = lsa->header.options; + new_or->u.std.origin = (struct lsa_header *)lsa; + new_or->cost = cost; + new_or->u.std.area_id = area->area_id; + new_or->u.std.external_routing = area->external_routing; + new_or->path_type = OSPF_PATH_INTER_AREA; + ospf_route_add(rt, p, new_or, abr_or); + + return; + } else { + route_unlock_node(rn); + if (rn->info == NULL) + return; } - } - - if (or->cost < cost) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_update_network_route(): new route is worse"); - return; - } - - if (or->cost == cost) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_update_network_route(): " - "new route is same distance, adding nexthops"); - ospf_route_copy_nexthops (or, abr_or->paths); - } - - if (or->cost > cost) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_update_network_route(): " - "new route is better, overriding nexthops"); - ospf_route_subst_nexthops (or, abr_or->paths); - or->cost = cost; - - if ((ospf->abr_type == OSPF_ABR_SHORTCUT) && - !OSPF_IS_AREA_ID_BACKBONE (or->u.std.area_id)) - { - or->path_type = OSPF_PATH_INTER_AREA; - or->u.std.area_id = area->area_id; - or->u.std.external_routing = area->external_routing; - /* Note that we can do this only in Shortcut ABR mode, - because standard ABR must leave the route type and area - unchanged - */ - } - } -} -static void -ospf_update_router_route (struct ospf *ospf, - struct route_table *rtrs, - struct summary_lsa *lsa, - struct prefix_ipv4 *p, - struct ospf_area *area) -{ - struct ospf_route *or, *abr_or, *new_or; - struct prefix_ipv4 abr; - u_int32_t cost; - - abr.family = AF_INET; - abr.prefix = lsa->header.adv_router; - abr.prefixlen = IPV4_MAX_BITLEN; - apply_mask_ipv4 (&abr); - - abr_or = ospf_find_abr_route (rtrs, &abr, area); - - if (abr_or == NULL) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_update_router_route(): can't find a route to the ABR"); - return; - } - - cost = abr_or->cost + GET_METRIC (lsa->metric); - - /* First try to find a backbone path, - because standard ABR can update only BB-associated paths */ - - if ((ospf->backbone == NULL) && - (ospf->abr_type != OSPF_ABR_SHORTCUT)) - return; /* no BB area, not Shortcut ABR, exiting */ - - /* find the backbone route, if possible */ - if ((ospf->backbone == NULL) - || !(or = ospf_find_asbr_route_through_area (rtrs, p, ospf->backbone))) - { - if (ospf->abr_type != OSPF_ABR_SHORTCUT) - - /* route to ASBR through the BB not found - the router is not Shortcut ABR, exiting */ - - return; - else - /* We're a Shortcut ABR*/ + or = rn->info; + + if (or->path_type != OSPF_PATH_INTRA_AREA && + or->path_type != OSPF_PATH_INTER_AREA) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_update_network_route(): ERR: path type is wrong"); + return; + } + + if (ospf->abr_type == OSPF_ABR_SHORTCUT) { + if ( + or->path_type == OSPF_PATH_INTRA_AREA + && !OSPF_IS_AREA_ID_BACKBONE( + or->u.std.area_id)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_update_network_route(): Shortcut: " + "this intra-area path is not backbone"); + return; + } + } else /* Not Shortcut ABR */ { - /* Let it either add a new router or update the route - through the same (non-BB) area. */ - - new_or = ospf_route_new (); - new_or->type = OSPF_DESTINATION_ROUTER; - new_or->id = lsa->header.id; - new_or->mask = lsa->mask; - new_or->u.std.options = lsa->header.options; - new_or->u.std.origin = (struct lsa_header *)lsa; - new_or->cost = cost; - new_or->u.std.area_id = area->area_id; - new_or->u.std.external_routing = area->external_routing; - new_or->path_type = OSPF_PATH_INTER_AREA; - new_or->u.std.flags = ROUTER_LSA_EXTERNAL; - ospf_ia_router_route (ospf, rtrs, p, new_or, abr_or); - - return; - } - } - - /* At this point the "or" is always bb-associated */ - - if (!(or->u.std.flags & ROUTER_LSA_EXTERNAL)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_upd_router_route(): the remote router is not an ASBR"); - return; - } - - if (or->path_type != OSPF_PATH_INTRA_AREA && - or->path_type != OSPF_PATH_INTER_AREA) - return; - - if (or->cost < cost) - return; - - else if (or->cost == cost) - ospf_route_copy_nexthops (or, abr_or->paths); - - else if (or->cost > cost) - { - ospf_route_subst_nexthops (or, abr_or->paths); - or->cost = cost; - - /* Even if the ABR runs in Shortcut mode, we can't change - the path type and area, because the "or" is always bb-associated - at this point and even Shortcut ABR can't change these attributes */ - } -} + if (!OSPF_IS_AREA_ID_BACKBONE(or->u.std.area_id)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_update_network_route(): " + "route is not BB-associated"); + return; /* We can update only BB routes */ + } + } -static int -process_transit_summary_lsa (struct ospf_area *area, struct route_table *rt, - struct route_table *rtrs, struct ospf_lsa *lsa) -{ - struct ospf *ospf = area->ospf; - struct summary_lsa *sl; - struct prefix_ipv4 p; - u_int32_t metric; - - if (lsa == NULL) - return 0; - - sl = (struct summary_lsa *) lsa->data; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("process_transit_summaries(): LS ID: %s", - inet_ntoa (lsa->data->id)); - metric = GET_METRIC (sl->metric); - - if (metric == OSPF_LS_INFINITY) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("process_transit_summaries(): metric is infinity, skip"); - return 0; - } - - if (IS_LSA_MAXAGE (lsa)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("process_transit_summaries(): This LSA is too old"); - return 0; - } - - if (ospf_lsa_is_self_originated (area->ospf, lsa)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("process_transit_summaries(): This LSA is mine, skip"); - return 0; - } - - p.family = AF_INET; - p.prefix = sl->header.id; - - if (sl->header.type == OSPF_SUMMARY_LSA) - p.prefixlen = ip_masklen (sl->mask); - else - p.prefixlen = IPV4_MAX_BITLEN; - - apply_mask_ipv4 (&p); - - if (sl->header.type == OSPF_SUMMARY_LSA) - ospf_update_network_route (ospf, rt, rtrs, sl, &p, area); - else - ospf_update_router_route (ospf, rtrs, sl, &p, area); - - return 0; -} + if (or->cost < cost) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_update_network_route(): new route is worse"); + return; + } -static void -ospf_examine_transit_summaries (struct ospf_area *area, - struct route_table *lsdb_rt, - struct route_table *rt, - struct route_table *rtrs) -{ - struct ospf_lsa *lsa; - struct route_node *rn; + if (or->cost == cost) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_update_network_route(): " + "new route is same distance, adding nexthops"); + ospf_route_copy_nexthops(or, abr_or->paths); + } - LSDB_LOOP (lsdb_rt, rn, lsa) - process_transit_summary_lsa (area, rt, rtrs, lsa); + if (or->cost > cost) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_update_network_route(): " + "new route is better, overriding nexthops"); + ospf_route_subst_nexthops(or, abr_or->paths); + or->cost = cost; + + if ((ospf->abr_type == OSPF_ABR_SHORTCUT) + && !OSPF_IS_AREA_ID_BACKBONE(or->u.std.area_id)) { + or->path_type = OSPF_PATH_INTER_AREA; + or->u.std.area_id = area->area_id; + or->u.std.external_routing = area->external_routing; + /* Note that we can do this only in Shortcut ABR mode, + because standard ABR must leave the route type and + area + unchanged + */ + } + } } -void -ospf_ia_routing (struct ospf *ospf, - struct route_table *rt, - struct route_table *rtrs) +static void ospf_update_router_route(struct ospf *ospf, + struct route_table *rtrs, + struct summary_lsa *lsa, + struct prefix_ipv4 *p, + struct ospf_area *area) { - struct ospf_area * area; + struct ospf_route * or, *abr_or, *new_or; + struct prefix_ipv4 abr; + u_int32_t cost; + + abr.family = AF_INET; + abr.prefix = lsa->header.adv_router; + abr.prefixlen = IPV4_MAX_BITLEN; + apply_mask_ipv4(&abr); + + abr_or = ospf_find_abr_route(rtrs, &abr, area); + + if (abr_or == NULL) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_update_router_route(): can't find a route to the ABR"); + return; + } - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_ia_routing():start"); + cost = abr_or->cost + GET_METRIC(lsa->metric); - if (IS_OSPF_ABR (ospf)) - { - struct listnode *node; - struct ospf_area *area; + /* First try to find a backbone path, + because standard ABR can update only BB-associated paths */ - switch (ospf->abr_type) - { - case OSPF_ABR_STAND: - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_ia_routing():Standard ABR"); + if ((ospf->backbone == NULL) && (ospf->abr_type != OSPF_ABR_SHORTCUT)) + return; /* no BB area, not Shortcut ABR, exiting */ - if ((area = ospf->backbone)) - { - struct listnode *node; + /* find the backbone route, if possible */ + if ((ospf->backbone == NULL) + || !(or = ospf_find_asbr_route_through_area(rtrs, p, + ospf->backbone))) { + if (ospf->abr_type != OSPF_ABR_SHORTCUT) - if (IS_DEBUG_OSPF_EVENT) - { - zlog_debug ("ospf_ia_routing():backbone area found"); - zlog_debug ("ospf_ia_routing():examining summaries"); - } + /* route to ASBR through the BB not found + the router is not Shortcut ABR, exiting */ - OSPF_EXAMINE_SUMMARIES_ALL (area, rt, rtrs); - - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - if (area != ospf->backbone) - if (ospf_area_is_transit (area)) - OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL (area, rt, rtrs); - } - else - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_ia_routing():backbone area NOT found"); - break; - case OSPF_ABR_IBM: - case OSPF_ABR_CISCO: - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_ia_routing():Alternative Cisco/IBM ABR"); - area = ospf->backbone; /* Find the BB */ - - /* If we have an active BB connection */ - if (area && ospf_act_bb_connection (ospf)) - { - if (IS_DEBUG_OSPF_EVENT) + return; + else + /* We're a Shortcut ABR*/ { - zlog_debug ("ospf_ia_routing(): backbone area found"); - zlog_debug ("ospf_ia_routing(): examining BB summaries"); + /* Let it either add a new router or update the route + through the same (non-BB) area. */ + + new_or = ospf_route_new(); + new_or->type = OSPF_DESTINATION_ROUTER; + new_or->id = lsa->header.id; + new_or->mask = lsa->mask; + new_or->u.std.options = lsa->header.options; + new_or->u.std.origin = (struct lsa_header *)lsa; + new_or->cost = cost; + new_or->u.std.area_id = area->area_id; + new_or->u.std.external_routing = area->external_routing; + new_or->path_type = OSPF_PATH_INTER_AREA; + new_or->u.std.flags = ROUTER_LSA_EXTERNAL; + ospf_ia_router_route(ospf, rtrs, p, new_or, abr_or); + + return; } + } - OSPF_EXAMINE_SUMMARIES_ALL (area, rt, rtrs); - - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - if (area != ospf->backbone) - if (ospf_area_is_transit (area)) - OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL (area, rt, rtrs); - } - else - { /* No active BB connection--consider all areas */ - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_ia_routing(): " - "Active BB connection not found"); - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - OSPF_EXAMINE_SUMMARIES_ALL (area, rt, rtrs); - } - break; - case OSPF_ABR_SHORTCUT: - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_ia_routing():Alternative Shortcut"); - area = ospf->backbone; /* Find the BB */ - - /* If we have an active BB connection */ - if (area && ospf_act_bb_connection (ospf)) - { - if (IS_DEBUG_OSPF_EVENT) - { - zlog_debug ("ospf_ia_routing(): backbone area found"); - zlog_debug ("ospf_ia_routing(): examining BB summaries"); + /* At this point the "or" is always bb-associated */ + + if (!(or->u.std.flags & ROUTER_LSA_EXTERNAL)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_upd_router_route(): the remote router is not an ASBR"); + return; + } + + if (or->path_type != OSPF_PATH_INTRA_AREA && + or->path_type != OSPF_PATH_INTER_AREA) + return; + + if (or->cost < cost) + return; + + else if (or->cost == cost) + ospf_route_copy_nexthops(or, abr_or->paths); + + else if (or->cost > cost) { + ospf_route_subst_nexthops(or, abr_or->paths); + or->cost = cost; + + /* Even if the ABR runs in Shortcut mode, we can't change + the path type and area, because the "or" is always + bb-associated + at this point and even Shortcut ABR can't change these + attributes */ + } +} + +static int process_transit_summary_lsa(struct ospf_area *area, + struct route_table *rt, + struct route_table *rtrs, + struct ospf_lsa *lsa) +{ + struct ospf *ospf = area->ospf; + struct summary_lsa *sl; + struct prefix_ipv4 p; + u_int32_t metric; + + if (lsa == NULL) + return 0; + + sl = (struct summary_lsa *)lsa->data; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("process_transit_summaries(): LS ID: %s", + inet_ntoa(lsa->data->id)); + metric = GET_METRIC(sl->metric); + + if (metric == OSPF_LS_INFINITY) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "process_transit_summaries(): metric is infinity, skip"); + return 0; + } + + if (IS_LSA_MAXAGE(lsa)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "process_transit_summaries(): This LSA is too old"); + return 0; + } + + if (ospf_lsa_is_self_originated(area->ospf, lsa)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "process_transit_summaries(): This LSA is mine, skip"); + return 0; + } + + p.family = AF_INET; + p.prefix = sl->header.id; + + if (sl->header.type == OSPF_SUMMARY_LSA) + p.prefixlen = ip_masklen(sl->mask); + else + p.prefixlen = IPV4_MAX_BITLEN; + + apply_mask_ipv4(&p); + + if (sl->header.type == OSPF_SUMMARY_LSA) + ospf_update_network_route(ospf, rt, rtrs, sl, &p, area); + else + ospf_update_router_route(ospf, rtrs, sl, &p, area); + + return 0; +} + +static void ospf_examine_transit_summaries(struct ospf_area *area, + struct route_table *lsdb_rt, + struct route_table *rt, + struct route_table *rtrs) +{ + struct ospf_lsa *lsa; + struct route_node *rn; + + LSDB_LOOP(lsdb_rt, rn, lsa) + process_transit_summary_lsa(area, rt, rtrs, lsa); +} + +void ospf_ia_routing(struct ospf *ospf, struct route_table *rt, + struct route_table *rtrs) +{ + struct ospf_area *area; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_ia_routing():start"); + + if (IS_OSPF_ABR(ospf)) { + struct listnode *node; + struct ospf_area *area; + + switch (ospf->abr_type) { + case OSPF_ABR_STAND: + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_ia_routing():Standard ABR"); + + if ((area = ospf->backbone)) { + struct listnode *node; + + if (IS_DEBUG_OSPF_EVENT) { + zlog_debug( + "ospf_ia_routing():backbone area found"); + zlog_debug( + "ospf_ia_routing():examining summaries"); + } + + OSPF_EXAMINE_SUMMARIES_ALL(area, rt, rtrs); + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, + area)) + if (area != ospf->backbone) + if (ospf_area_is_transit(area)) + OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL( + area, rt, rtrs); + } else if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_ia_routing():backbone area NOT found"); + break; + case OSPF_ABR_IBM: + case OSPF_ABR_CISCO: + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_ia_routing():Alternative Cisco/IBM ABR"); + area = ospf->backbone; /* Find the BB */ + + /* If we have an active BB connection */ + if (area && ospf_act_bb_connection(ospf)) { + if (IS_DEBUG_OSPF_EVENT) { + zlog_debug( + "ospf_ia_routing(): backbone area found"); + zlog_debug( + "ospf_ia_routing(): examining BB summaries"); + } + + OSPF_EXAMINE_SUMMARIES_ALL(area, rt, rtrs); + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, + area)) + if (area != ospf->backbone) + if (ospf_area_is_transit(area)) + OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL( + area, rt, rtrs); + } else { /* No active BB connection--consider all areas + */ + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_ia_routing(): " + "Active BB connection not found"); + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, + area)) + OSPF_EXAMINE_SUMMARIES_ALL(area, rt, + rtrs); + } + break; + case OSPF_ABR_SHORTCUT: + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_ia_routing():Alternative Shortcut"); + area = ospf->backbone; /* Find the BB */ + + /* If we have an active BB connection */ + if (area && ospf_act_bb_connection(ospf)) { + if (IS_DEBUG_OSPF_EVENT) { + zlog_debug( + "ospf_ia_routing(): backbone area found"); + zlog_debug( + "ospf_ia_routing(): examining BB summaries"); + } + OSPF_EXAMINE_SUMMARIES_ALL(area, rt, rtrs); + } + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) + if (area != ospf->backbone) + if (ospf_area_is_transit(area) + || ((area->shortcut_configured + != OSPF_SHORTCUT_DISABLE) + && ((ospf->backbone == NULL) + || ((area->shortcut_configured + == OSPF_SHORTCUT_ENABLE) + && area->shortcut_capability)))) + OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL( + area, rt, rtrs); + break; + default: + break; } - OSPF_EXAMINE_SUMMARIES_ALL (area, rt, rtrs); - } - - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - if (area != ospf->backbone) - if (ospf_area_is_transit (area) || - ((area->shortcut_configured != OSPF_SHORTCUT_DISABLE) && - ((ospf->backbone == NULL) || - ((area->shortcut_configured == OSPF_SHORTCUT_ENABLE) && - area->shortcut_capability)))) - OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL (area, rt, rtrs); - break; - default: - break; - } - } - else - { - struct listnode *node; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_ia_routing():not ABR, considering all areas"); - - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - OSPF_EXAMINE_SUMMARIES_ALL (area, rt, rtrs); - } + } else { + struct listnode *node; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_ia_routing():not ABR, considering all areas"); + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) + OSPF_EXAMINE_SUMMARIES_ALL(area, rt, rtrs); + } } diff --git a/ospfd/ospf_ia.h b/ospfd/ospf_ia.h index f102545f8..05ad13c06 100644 --- a/ospfd/ospf_ia.h +++ b/ospfd/ospf_ia.h @@ -23,20 +23,22 @@ #define _ZEBRA_OSPF_IA_H /* Macros. */ -#define OSPF_EXAMINE_SUMMARIES_ALL(A,N,R) \ - { \ - ospf_examine_summaries ((A), SUMMARY_LSDB ((A)), (N), (R)); \ - ospf_examine_summaries ((A), ASBR_SUMMARY_LSDB ((A)), (N), (R)); \ +#define OSPF_EXAMINE_SUMMARIES_ALL(A, N, R) \ + { \ + ospf_examine_summaries((A), SUMMARY_LSDB((A)), (N), (R)); \ + ospf_examine_summaries((A), ASBR_SUMMARY_LSDB((A)), (N), (R)); \ } -#define OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL(A,N,R) \ - { \ - ospf_examine_transit_summaries ((A), SUMMARY_LSDB ((A)), (N), (R)); \ - ospf_examine_transit_summaries ((A), ASBR_SUMMARY_LSDB ((A)), (N), (R)); \ +#define OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL(A, N, R) \ + { \ + ospf_examine_transit_summaries((A), SUMMARY_LSDB((A)), (N), \ + (R)); \ + ospf_examine_transit_summaries((A), ASBR_SUMMARY_LSDB((A)), \ + (N), (R)); \ } -extern void ospf_ia_routing (struct ospf *, struct route_table *, - struct route_table *); -extern int ospf_area_is_transit (struct ospf_area *); +extern void ospf_ia_routing(struct ospf *, struct route_table *, + struct route_table *); +extern int ospf_area_is_transit(struct ospf_area *); #endif /* _ZEBRA_OSPF_IA_H */ diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index 1e95e4312..4ea8ec26f 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -48,1180 +48,1121 @@ #include "ospfd/ospf_dump.h" DEFINE_QOBJ_TYPE(ospf_interface) -DEFINE_HOOK(ospf_vl_add, (struct ospf_vl_data *vd), (vd)) -DEFINE_HOOK(ospf_vl_delete, (struct ospf_vl_data *vd), (vd)) +DEFINE_HOOK(ospf_vl_add, (struct ospf_vl_data * vd), (vd)) +DEFINE_HOOK(ospf_vl_delete, (struct ospf_vl_data * vd), (vd)) -int -ospf_if_get_output_cost (struct ospf_interface *oi) +int ospf_if_get_output_cost(struct ospf_interface *oi) { - /* If all else fails, use default OSPF cost */ - u_int32_t cost; - u_int32_t bw, refbw; - - /* ifp speed and bw can be 0 in some platforms, use ospf default bw - if bw is configured under interface it would be used. - */ - if (!oi->ifp->bandwidth && oi->ifp->speed) - bw = oi->ifp->speed; - else - bw = oi->ifp->bandwidth ? oi->ifp->bandwidth : OSPF_DEFAULT_BANDWIDTH; - refbw = oi->ospf->ref_bandwidth; - - /* A specifed ip ospf cost overrides a calculated one. */ - if (OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (oi->ifp), output_cost_cmd) || - OSPF_IF_PARAM_CONFIGURED (oi->params, output_cost_cmd)) - cost = OSPF_IF_PARAM (oi, output_cost_cmd); - /* See if a cost can be calculated from the zebra processes - interface bandwidth field. */ - else - { - cost = (u_int32_t) ((double)refbw / (double)bw + (double)0.5); - if (cost < 1) - cost = 1; - else if (cost > 65535) - cost = 65535; - } - - return cost; + /* If all else fails, use default OSPF cost */ + u_int32_t cost; + u_int32_t bw, refbw; + + /* ifp speed and bw can be 0 in some platforms, use ospf default bw + if bw is configured under interface it would be used. + */ + if (!oi->ifp->bandwidth && oi->ifp->speed) + bw = oi->ifp->speed; + else + bw = oi->ifp->bandwidth ? oi->ifp->bandwidth + : OSPF_DEFAULT_BANDWIDTH; + refbw = oi->ospf->ref_bandwidth; + + /* A specifed ip ospf cost overrides a calculated one. */ + if (OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(oi->ifp), output_cost_cmd) + || OSPF_IF_PARAM_CONFIGURED(oi->params, output_cost_cmd)) + cost = OSPF_IF_PARAM(oi, output_cost_cmd); + /* See if a cost can be calculated from the zebra processes + interface bandwidth field. */ + else { + cost = (u_int32_t)((double)refbw / (double)bw + (double)0.5); + if (cost < 1) + cost = 1; + else if (cost > 65535) + cost = 65535; + } + + return cost; } -void -ospf_if_recalculate_output_cost (struct interface *ifp) +void ospf_if_recalculate_output_cost(struct interface *ifp) { - u_int32_t newcost; - struct route_node *rn; - - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - { - struct ospf_interface *oi; - - if ( (oi = rn->info) == NULL) - continue; - - newcost = ospf_if_get_output_cost (oi); - - /* Is actual output cost changed? */ - if (oi->output_cost != newcost) - { - oi->output_cost = newcost; - ospf_router_lsa_update_area (oi->area); + u_int32_t newcost; + struct route_node *rn; + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi; + + if ((oi = rn->info) == NULL) + continue; + + newcost = ospf_if_get_output_cost(oi); + + /* Is actual output cost changed? */ + if (oi->output_cost != newcost) { + oi->output_cost = newcost; + ospf_router_lsa_update_area(oi->area); + } } - } } -/* Simulate down/up on the interface. This is needed, for example, when +/* Simulate down/up on the interface. This is needed, for example, when the MTU changes. */ -void -ospf_if_reset(struct interface *ifp) +void ospf_if_reset(struct interface *ifp) { - struct route_node *rn; - - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - { - struct ospf_interface *oi; - - if ( (oi = rn->info) == NULL) - continue; - - ospf_if_down(oi); - ospf_if_up(oi); - } + struct route_node *rn; + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi; + + if ((oi = rn->info) == NULL) + continue; + + ospf_if_down(oi); + ospf_if_up(oi); + } } -void -ospf_if_reset_variables (struct ospf_interface *oi) +void ospf_if_reset_variables(struct ospf_interface *oi) { - /* Set default values. */ - /* don't clear this flag. oi->flag = OSPF_IF_DISABLE; */ + /* Set default values. */ + /* don't clear this flag. oi->flag = OSPF_IF_DISABLE; */ - if (oi->vl_data) - oi->type = OSPF_IFTYPE_VIRTUALLINK; - else - /* preserve network-type */ - if (oi->type != OSPF_IFTYPE_NBMA) - oi->type = OSPF_IFTYPE_BROADCAST; + if (oi->vl_data) + oi->type = OSPF_IFTYPE_VIRTUALLINK; + else + /* preserve network-type */ + if (oi->type != OSPF_IFTYPE_NBMA) + oi->type = OSPF_IFTYPE_BROADCAST; - oi->state = ISM_Down; + oi->state = ISM_Down; - oi->crypt_seqnum = 0; + oi->crypt_seqnum = 0; - /* This must be short, (less than RxmtInterval) - - RFC 2328 Section 13.5 para 3. Set to 1 second to avoid Acks being - held back for too long - MAG */ - oi->v_ls_ack = 1; + /* This must be short, (less than RxmtInterval) + - RFC 2328 Section 13.5 para 3. Set to 1 second to avoid Acks being + held back for too long - MAG */ + oi->v_ls_ack = 1; } /* lookup oi for specified prefix/ifp */ -struct ospf_interface * -ospf_if_table_lookup (struct interface *ifp, struct prefix *prefix) +struct ospf_interface *ospf_if_table_lookup(struct interface *ifp, + struct prefix *prefix) { - struct prefix p; - struct route_node *rn; - struct ospf_interface *rninfo = NULL; - - p = *prefix; - p.prefixlen = IPV4_MAX_PREFIXLEN; - - /* route_node_get implicitely locks */ - if ((rn = route_node_lookup (IF_OIFS (ifp), &p))) - { - rninfo = (struct ospf_interface *) rn->info; - route_unlock_node (rn); - } - - return rninfo; + struct prefix p; + struct route_node *rn; + struct ospf_interface *rninfo = NULL; + + p = *prefix; + p.prefixlen = IPV4_MAX_PREFIXLEN; + + /* route_node_get implicitely locks */ + if ((rn = route_node_lookup(IF_OIFS(ifp), &p))) { + rninfo = (struct ospf_interface *)rn->info; + route_unlock_node(rn); + } + + return rninfo; } -static void -ospf_add_to_if (struct interface *ifp, struct ospf_interface *oi) +static void ospf_add_to_if(struct interface *ifp, struct ospf_interface *oi) { - struct route_node *rn; - struct prefix p; - - p = *oi->address; - p.prefixlen = IPV4_MAX_PREFIXLEN; - - rn = route_node_get (IF_OIFS (ifp), &p); - /* rn->info should either be NULL or equal to this oi - * as route_node_get may return an existing node - */ - assert (!rn->info || rn->info == oi); - rn->info = oi; + struct route_node *rn; + struct prefix p; + + p = *oi->address; + p.prefixlen = IPV4_MAX_PREFIXLEN; + + rn = route_node_get(IF_OIFS(ifp), &p); + /* rn->info should either be NULL or equal to this oi + * as route_node_get may return an existing node + */ + assert(!rn->info || rn->info == oi); + rn->info = oi; } -static void -ospf_delete_from_if (struct interface *ifp, struct ospf_interface *oi) +static void ospf_delete_from_if(struct interface *ifp, + struct ospf_interface *oi) { - struct route_node *rn; - struct prefix p; - - p = *oi->address; - p.prefixlen = IPV4_MAX_PREFIXLEN; - - rn = route_node_lookup (IF_OIFS (oi->ifp), &p); - assert (rn); - assert (rn->info); - rn->info = NULL; - route_unlock_node (rn); - route_unlock_node (rn); + struct route_node *rn; + struct prefix p; + + p = *oi->address; + p.prefixlen = IPV4_MAX_PREFIXLEN; + + rn = route_node_lookup(IF_OIFS(oi->ifp), &p); + assert(rn); + assert(rn->info); + rn->info = NULL; + route_unlock_node(rn); + route_unlock_node(rn); } -struct ospf_interface * -ospf_if_new (struct ospf *ospf, struct interface *ifp, struct prefix *p) +struct ospf_interface *ospf_if_new(struct ospf *ospf, struct interface *ifp, + struct prefix *p) { - struct ospf_interface *oi; - - if ((oi = ospf_if_table_lookup (ifp, p)) == NULL) - { - oi = XCALLOC (MTYPE_OSPF_IF, sizeof (struct ospf_interface)); - memset (oi, 0, sizeof (struct ospf_interface)); - } - else - return oi; - - /* Set zebra interface pointer. */ - oi->ifp = ifp; - oi->address = p; - - ospf_add_to_if (ifp, oi); - listnode_add (ospf->oiflist, oi); - - /* Initialize neighbor list. */ - oi->nbrs = route_table_init (); - - /* Initialize static neighbor list. */ - oi->nbr_nbma = list_new (); - - /* Initialize Link State Acknowledgment list. */ - oi->ls_ack = list_new (); - oi->ls_ack_direct.ls_ack = list_new (); - - /* Set default values. */ - ospf_if_reset_variables (oi); - - /* Set pseudo neighbor to Null */ - oi->nbr_self = NULL; - - oi->ls_upd_queue = route_table_init (); - oi->t_ls_upd_event = NULL; - oi->t_ls_ack_direct = NULL; - - oi->crypt_seqnum = time (NULL); - - ospf_opaque_type9_lsa_init (oi); - - oi->ospf = ospf; - QOBJ_REG (oi, ospf_interface); - - return oi; + struct ospf_interface *oi; + + if ((oi = ospf_if_table_lookup(ifp, p)) == NULL) { + oi = XCALLOC(MTYPE_OSPF_IF, sizeof(struct ospf_interface)); + memset(oi, 0, sizeof(struct ospf_interface)); + } else + return oi; + + /* Set zebra interface pointer. */ + oi->ifp = ifp; + oi->address = p; + + ospf_add_to_if(ifp, oi); + listnode_add(ospf->oiflist, oi); + + /* Initialize neighbor list. */ + oi->nbrs = route_table_init(); + + /* Initialize static neighbor list. */ + oi->nbr_nbma = list_new(); + + /* Initialize Link State Acknowledgment list. */ + oi->ls_ack = list_new(); + oi->ls_ack_direct.ls_ack = list_new(); + + /* Set default values. */ + ospf_if_reset_variables(oi); + + /* Set pseudo neighbor to Null */ + oi->nbr_self = NULL; + + oi->ls_upd_queue = route_table_init(); + oi->t_ls_upd_event = NULL; + oi->t_ls_ack_direct = NULL; + + oi->crypt_seqnum = time(NULL); + + ospf_opaque_type9_lsa_init(oi); + + oi->ospf = ospf; + QOBJ_REG(oi, ospf_interface); + + return oi; } /* Restore an interface to its pre UP state Used from ism_interface_down only */ -void -ospf_if_cleanup (struct ospf_interface *oi) +void ospf_if_cleanup(struct ospf_interface *oi) { - struct route_node *rn; - struct listnode *node, *nnode; - struct ospf_neighbor *nbr; - struct ospf_nbr_nbma *nbr_nbma; - struct ospf_lsa *lsa; - - /* oi->nbrs and oi->nbr_nbma should be deleted on InterfaceDown event */ - /* delete all static neighbors attached to this interface */ - for (ALL_LIST_ELEMENTS (oi->nbr_nbma, node, nnode, nbr_nbma)) - { - OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll); - - if (nbr_nbma->nbr) - { - nbr_nbma->nbr->nbr_nbma = NULL; - nbr_nbma->nbr = NULL; + struct route_node *rn; + struct listnode *node, *nnode; + struct ospf_neighbor *nbr; + struct ospf_nbr_nbma *nbr_nbma; + struct ospf_lsa *lsa; + + /* oi->nbrs and oi->nbr_nbma should be deleted on InterfaceDown event */ + /* delete all static neighbors attached to this interface */ + for (ALL_LIST_ELEMENTS(oi->nbr_nbma, node, nnode, nbr_nbma)) { + OSPF_POLL_TIMER_OFF(nbr_nbma->t_poll); + + if (nbr_nbma->nbr) { + nbr_nbma->nbr->nbr_nbma = NULL; + nbr_nbma->nbr = NULL; + } + + nbr_nbma->oi = NULL; + + listnode_delete(oi->nbr_nbma, nbr_nbma); } - nbr_nbma->oi = NULL; - - listnode_delete (oi->nbr_nbma, nbr_nbma); - } - - /* send Neighbor event KillNbr to all associated neighbors. */ - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - if (nbr != oi->nbr_self) - OSPF_NSM_EVENT_EXECUTE (nbr, NSM_KillNbr); - - /* Cleanup Link State Acknowlegdment list. */ - for (ALL_LIST_ELEMENTS (oi->ls_ack, node, nnode, lsa)) - ospf_lsa_unlock (&lsa); /* oi->ls_ack */ - list_delete_all_node (oi->ls_ack); - - oi->crypt_seqnum = 0; - - /* Empty link state update queue */ - ospf_ls_upd_queue_empty (oi); - - /* Reset pseudo neighbor. */ - ospf_nbr_self_reset (oi, oi->ospf->router_id); + /* send Neighbor event KillNbr to all associated neighbors. */ + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info) != NULL) + if (nbr != oi->nbr_self) + OSPF_NSM_EVENT_EXECUTE(nbr, NSM_KillNbr); + + /* Cleanup Link State Acknowlegdment list. */ + for (ALL_LIST_ELEMENTS(oi->ls_ack, node, nnode, lsa)) + ospf_lsa_unlock(&lsa); /* oi->ls_ack */ + list_delete_all_node(oi->ls_ack); + + oi->crypt_seqnum = 0; + + /* Empty link state update queue */ + ospf_ls_upd_queue_empty(oi); + + /* Reset pseudo neighbor. */ + ospf_nbr_self_reset(oi, oi->ospf->router_id); } -void -ospf_if_free (struct ospf_interface *oi) +void ospf_if_free(struct ospf_interface *oi) { - ospf_if_down (oi); + ospf_if_down(oi); + + assert(oi->state == ISM_Down); + + ospf_opaque_type9_lsa_term(oi); + + QOBJ_UNREG(oi); + + /* Free Pseudo Neighbour */ + ospf_nbr_delete(oi->nbr_self); - assert (oi->state == ISM_Down); + route_table_finish(oi->nbrs); + route_table_finish(oi->ls_upd_queue); - ospf_opaque_type9_lsa_term (oi); + /* Free any lists that should be freed */ + list_free(oi->nbr_nbma); - QOBJ_UNREG (oi); + list_free(oi->ls_ack); + list_free(oi->ls_ack_direct.ls_ack); - /* Free Pseudo Neighbour */ - ospf_nbr_delete (oi->nbr_self); - - route_table_finish (oi->nbrs); - route_table_finish (oi->ls_upd_queue); - - /* Free any lists that should be freed */ - list_free (oi->nbr_nbma); - - list_free (oi->ls_ack); - list_free (oi->ls_ack_direct.ls_ack); - - ospf_delete_from_if (oi->ifp, oi); + ospf_delete_from_if(oi->ifp, oi); - listnode_delete (oi->ospf->oiflist, oi); - listnode_delete (oi->area->oiflist, oi); + listnode_delete(oi->ospf->oiflist, oi); + listnode_delete(oi->area->oiflist, oi); - thread_cancel_event (master, oi); + thread_cancel_event(master, oi); - memset (oi, 0, sizeof (*oi)); - XFREE (MTYPE_OSPF_IF, oi); + memset(oi, 0, sizeof(*oi)); + XFREE(MTYPE_OSPF_IF, oi); } -int -ospf_if_is_up (struct ospf_interface *oi) +int ospf_if_is_up(struct ospf_interface *oi) { - return if_is_up (oi->ifp); + return if_is_up(oi->ifp); } -struct ospf_interface * -ospf_if_exists (struct ospf_interface *oic) -{ - struct listnode *node; - struct ospf *ospf; - struct ospf_interface *oi; +struct ospf_interface *ospf_if_exists(struct ospf_interface *oic) +{ + struct listnode *node; + struct ospf *ospf; + struct ospf_interface *oi; - if ((ospf = ospf_lookup ()) == NULL) - return NULL; + if ((ospf = ospf_lookup()) == NULL) + return NULL; - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) - if (oi == oic) - return oi; + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) + if (oi == oic) + return oi; - return NULL; + return NULL; } /* Lookup OSPF interface by router LSA posistion */ -struct ospf_interface * -ospf_if_lookup_by_lsa_pos (struct ospf_area *area, int lsa_pos) +struct ospf_interface *ospf_if_lookup_by_lsa_pos(struct ospf_area *area, + int lsa_pos) { - struct listnode *node; - struct ospf_interface *oi; + struct listnode *node; + struct ospf_interface *oi; - for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi)) - { - if (lsa_pos >= oi->lsa_pos_beg && lsa_pos < oi->lsa_pos_end) - return oi; - } - return NULL; + for (ALL_LIST_ELEMENTS_RO(area->oiflist, node, oi)) { + if (lsa_pos >= oi->lsa_pos_beg && lsa_pos < oi->lsa_pos_end) + return oi; + } + return NULL; } -struct ospf_interface * -ospf_if_lookup_by_local_addr (struct ospf *ospf, - struct interface *ifp, struct in_addr address) +struct ospf_interface *ospf_if_lookup_by_local_addr(struct ospf *ospf, + struct interface *ifp, + struct in_addr address) { - struct listnode *node; - struct ospf_interface *oi; - - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) - if (oi->type != OSPF_IFTYPE_VIRTUALLINK) - { - if (ifp && oi->ifp != ifp) - continue; - - if (IPV4_ADDR_SAME (&address, &oi->address->u.prefix4)) - return oi; - } - - return NULL; + struct listnode *node; + struct ospf_interface *oi; + + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) + if (oi->type != OSPF_IFTYPE_VIRTUALLINK) { + if (ifp && oi->ifp != ifp) + continue; + + if (IPV4_ADDR_SAME(&address, &oi->address->u.prefix4)) + return oi; + } + + return NULL; } -struct ospf_interface * -ospf_if_lookup_by_prefix (struct ospf *ospf, struct prefix_ipv4 *p) +struct ospf_interface *ospf_if_lookup_by_prefix(struct ospf *ospf, + struct prefix_ipv4 *p) { - struct listnode *node; - struct ospf_interface *oi; - - /* Check each Interface. */ - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) - { - if (oi->type != OSPF_IFTYPE_VIRTUALLINK) - { - struct prefix ptmp; - - prefix_copy (&ptmp, CONNECTED_PREFIX(oi->connected)); - apply_mask (&ptmp); - if (prefix_same (&ptmp, (struct prefix *) p)) - return oi; + struct listnode *node; + struct ospf_interface *oi; + + /* Check each Interface. */ + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { + if (oi->type != OSPF_IFTYPE_VIRTUALLINK) { + struct prefix ptmp; + + prefix_copy(&ptmp, CONNECTED_PREFIX(oi->connected)); + apply_mask(&ptmp); + if (prefix_same(&ptmp, (struct prefix *)p)) + return oi; + } } - } - return NULL; + return NULL; } /* determine receiving interface by ifp and source address */ -struct ospf_interface * -ospf_if_lookup_recv_if (struct ospf *ospf, struct in_addr src, - struct interface *ifp) +struct ospf_interface *ospf_if_lookup_recv_if(struct ospf *ospf, + struct in_addr src, + struct interface *ifp) { - struct route_node *rn; - struct prefix_ipv4 addr; - struct ospf_interface *oi, *match; - - addr.family = AF_INET; - addr.prefix = src; - addr.prefixlen = IPV4_MAX_BITLEN; - - match = NULL; - - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - { - oi = rn->info; - - if (!oi) /* oi can be NULL for PtP aliases */ - continue; - - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - continue; - - if (if_is_loopback (oi->ifp)) - continue; - - if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) - match = oi; - else if (prefix_match (CONNECTED_PREFIX(oi->connected), - (struct prefix *) &addr)) - { - if ( (match == NULL) || - (match->address->prefixlen < oi->address->prefixlen) - ) - match = oi; + struct route_node *rn; + struct prefix_ipv4 addr; + struct ospf_interface *oi, *match; + + addr.family = AF_INET; + addr.prefix = src; + addr.prefixlen = IPV4_MAX_BITLEN; + + match = NULL; + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + oi = rn->info; + + if (!oi) /* oi can be NULL for PtP aliases */ + continue; + + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + continue; + + if (if_is_loopback(oi->ifp)) + continue; + + if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) + match = oi; + else if (prefix_match(CONNECTED_PREFIX(oi->connected), + (struct prefix *)&addr)) { + if ((match == NULL) || (match->address->prefixlen + < oi->address->prefixlen)) + match = oi; + } } - } - return match; + return match; } -void -ospf_if_stream_set (struct ospf_interface *oi) +void ospf_if_stream_set(struct ospf_interface *oi) { - /* set output fifo queue. */ - if (oi->obuf == NULL) - oi->obuf = ospf_fifo_new (); + /* set output fifo queue. */ + if (oi->obuf == NULL) + oi->obuf = ospf_fifo_new(); } -void -ospf_if_stream_unset (struct ospf_interface *oi) +void ospf_if_stream_unset(struct ospf_interface *oi) { - struct ospf *ospf = oi->ospf; - - if (oi->obuf) - { - ospf_fifo_free (oi->obuf); - oi->obuf = NULL; - - if (oi->on_write_q) - { - listnode_delete (ospf->oi_write_q, oi); - if (list_isempty(ospf->oi_write_q)) - OSPF_TIMER_OFF (ospf->t_write); - oi->on_write_q = 0; - } - } + struct ospf *ospf = oi->ospf; + + if (oi->obuf) { + ospf_fifo_free(oi->obuf); + oi->obuf = NULL; + + if (oi->on_write_q) { + listnode_delete(ospf->oi_write_q, oi); + if (list_isempty(ospf->oi_write_q)) + OSPF_TIMER_OFF(ospf->t_write); + oi->on_write_q = 0; + } + } } -static struct ospf_if_params * -ospf_new_if_params (void) +static struct ospf_if_params *ospf_new_if_params(void) { - struct ospf_if_params *oip; - - oip = XCALLOC (MTYPE_OSPF_IF_PARAMS, sizeof (struct ospf_if_params)); - - if (!oip) - return NULL; - - UNSET_IF_PARAM (oip, output_cost_cmd); - UNSET_IF_PARAM (oip, transmit_delay); - UNSET_IF_PARAM (oip, retransmit_interval); - UNSET_IF_PARAM (oip, passive_interface); - UNSET_IF_PARAM (oip, v_hello); - UNSET_IF_PARAM (oip, fast_hello); - UNSET_IF_PARAM (oip, v_wait); - UNSET_IF_PARAM (oip, priority); - UNSET_IF_PARAM (oip, type); - UNSET_IF_PARAM (oip, auth_simple); - UNSET_IF_PARAM (oip, auth_crypt); - UNSET_IF_PARAM (oip, auth_type); - - oip->auth_crypt = list_new (); - - oip->network_lsa_seqnum = htonl(OSPF_INITIAL_SEQUENCE_NUMBER); - - return oip; + struct ospf_if_params *oip; + + oip = XCALLOC(MTYPE_OSPF_IF_PARAMS, sizeof(struct ospf_if_params)); + + if (!oip) + return NULL; + + UNSET_IF_PARAM(oip, output_cost_cmd); + UNSET_IF_PARAM(oip, transmit_delay); + UNSET_IF_PARAM(oip, retransmit_interval); + UNSET_IF_PARAM(oip, passive_interface); + UNSET_IF_PARAM(oip, v_hello); + UNSET_IF_PARAM(oip, fast_hello); + UNSET_IF_PARAM(oip, v_wait); + UNSET_IF_PARAM(oip, priority); + UNSET_IF_PARAM(oip, type); + UNSET_IF_PARAM(oip, auth_simple); + UNSET_IF_PARAM(oip, auth_crypt); + UNSET_IF_PARAM(oip, auth_type); + + oip->auth_crypt = list_new(); + + oip->network_lsa_seqnum = htonl(OSPF_INITIAL_SEQUENCE_NUMBER); + + return oip; } -void -ospf_del_if_params (struct ospf_if_params *oip) +void ospf_del_if_params(struct ospf_if_params *oip) { - list_delete (oip->auth_crypt); - bfd_info_free(&(oip->bfd_info)); - XFREE (MTYPE_OSPF_IF_PARAMS, oip); + list_delete(oip->auth_crypt); + bfd_info_free(&(oip->bfd_info)); + XFREE(MTYPE_OSPF_IF_PARAMS, oip); } -void -ospf_free_if_params (struct interface *ifp, struct in_addr addr) +void ospf_free_if_params(struct interface *ifp, struct in_addr addr) { - struct ospf_if_params *oip; - struct prefix_ipv4 p; - struct route_node *rn; - - p.family = AF_INET; - p.prefixlen = IPV4_MAX_PREFIXLEN; - p.prefix = addr; - rn = route_node_lookup (IF_OIFS_PARAMS (ifp), (struct prefix*)&p); - if (!rn || !rn->info) - return; - - oip = rn->info; - route_unlock_node (rn); - - if (!OSPF_IF_PARAM_CONFIGURED (oip, output_cost_cmd) && - !OSPF_IF_PARAM_CONFIGURED (oip, transmit_delay) && - !OSPF_IF_PARAM_CONFIGURED (oip, retransmit_interval) && - !OSPF_IF_PARAM_CONFIGURED (oip, passive_interface) && - !OSPF_IF_PARAM_CONFIGURED (oip, v_hello) && - !OSPF_IF_PARAM_CONFIGURED (oip, fast_hello) && - !OSPF_IF_PARAM_CONFIGURED (oip, v_wait) && - !OSPF_IF_PARAM_CONFIGURED (oip, priority) && - !OSPF_IF_PARAM_CONFIGURED (oip, type) && - !OSPF_IF_PARAM_CONFIGURED (oip, auth_simple) && - !OSPF_IF_PARAM_CONFIGURED (oip, auth_type) && - listcount (oip->auth_crypt) == 0 && - ntohl (oip->network_lsa_seqnum) != OSPF_INITIAL_SEQUENCE_NUMBER) - { - ospf_del_if_params (oip); - rn->info = NULL; - route_unlock_node (rn); - } + struct ospf_if_params *oip; + struct prefix_ipv4 p; + struct route_node *rn; + + p.family = AF_INET; + p.prefixlen = IPV4_MAX_PREFIXLEN; + p.prefix = addr; + rn = route_node_lookup(IF_OIFS_PARAMS(ifp), (struct prefix *)&p); + if (!rn || !rn->info) + return; + + oip = rn->info; + route_unlock_node(rn); + + if (!OSPF_IF_PARAM_CONFIGURED(oip, output_cost_cmd) + && !OSPF_IF_PARAM_CONFIGURED(oip, transmit_delay) + && !OSPF_IF_PARAM_CONFIGURED(oip, retransmit_interval) + && !OSPF_IF_PARAM_CONFIGURED(oip, passive_interface) + && !OSPF_IF_PARAM_CONFIGURED(oip, v_hello) + && !OSPF_IF_PARAM_CONFIGURED(oip, fast_hello) + && !OSPF_IF_PARAM_CONFIGURED(oip, v_wait) + && !OSPF_IF_PARAM_CONFIGURED(oip, priority) + && !OSPF_IF_PARAM_CONFIGURED(oip, type) + && !OSPF_IF_PARAM_CONFIGURED(oip, auth_simple) + && !OSPF_IF_PARAM_CONFIGURED(oip, auth_type) + && listcount(oip->auth_crypt) == 0 + && ntohl(oip->network_lsa_seqnum) != OSPF_INITIAL_SEQUENCE_NUMBER) { + ospf_del_if_params(oip); + rn->info = NULL; + route_unlock_node(rn); + } } -struct ospf_if_params * -ospf_lookup_if_params (struct interface *ifp, struct in_addr addr) +struct ospf_if_params *ospf_lookup_if_params(struct interface *ifp, + struct in_addr addr) { - struct prefix_ipv4 p; - struct route_node *rn; - - p.family = AF_INET; - p.prefixlen = IPV4_MAX_PREFIXLEN; - p.prefix = addr; - - rn = route_node_lookup (IF_OIFS_PARAMS (ifp), (struct prefix*)&p); - - if (rn) - { - route_unlock_node (rn); - return rn->info; - } - - return NULL; + struct prefix_ipv4 p; + struct route_node *rn; + + p.family = AF_INET; + p.prefixlen = IPV4_MAX_PREFIXLEN; + p.prefix = addr; + + rn = route_node_lookup(IF_OIFS_PARAMS(ifp), (struct prefix *)&p); + + if (rn) { + route_unlock_node(rn); + return rn->info; + } + + return NULL; } -struct ospf_if_params * -ospf_get_if_params (struct interface *ifp, struct in_addr addr) +struct ospf_if_params *ospf_get_if_params(struct interface *ifp, + struct in_addr addr) { - struct prefix_ipv4 p; - struct route_node *rn; - - p.family = AF_INET; - p.prefixlen = IPV4_MAX_PREFIXLEN; - p.prefix = addr; - - rn = route_node_get (IF_OIFS_PARAMS (ifp), (struct prefix*)&p); - - if (rn->info == NULL) - rn->info = ospf_new_if_params (); - else - route_unlock_node (rn); - - return rn->info; + struct prefix_ipv4 p; + struct route_node *rn; + + p.family = AF_INET; + p.prefixlen = IPV4_MAX_PREFIXLEN; + p.prefix = addr; + + rn = route_node_get(IF_OIFS_PARAMS(ifp), (struct prefix *)&p); + + if (rn->info == NULL) + rn->info = ospf_new_if_params(); + else + route_unlock_node(rn); + + return rn->info; } -void -ospf_if_update_params (struct interface *ifp, struct in_addr addr) +void ospf_if_update_params(struct interface *ifp, struct in_addr addr) { - struct route_node *rn; - struct ospf_interface *oi; - - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - { - if ((oi = rn->info) == NULL) - continue; - - if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &addr)) - oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4); - } + struct route_node *rn; + struct ospf_interface *oi; + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + if ((oi = rn->info) == NULL) + continue; + + if (IPV4_ADDR_SAME(&oi->address->u.prefix4, &addr)) + oi->params = ospf_lookup_if_params( + ifp, oi->address->u.prefix4); + } } -int -ospf_if_new_hook (struct interface *ifp) +int ospf_if_new_hook(struct interface *ifp) { - int rc = 0; - - ifp->info = XCALLOC (MTYPE_OSPF_IF_INFO, sizeof (struct ospf_if_info)); - - IF_OIFS (ifp) = route_table_init (); - IF_OIFS_PARAMS (ifp) = route_table_init (); - - IF_DEF_PARAMS (ifp) = ospf_new_if_params (); - - SET_IF_PARAM (IF_DEF_PARAMS (ifp), transmit_delay); - IF_DEF_PARAMS (ifp)->transmit_delay = OSPF_TRANSMIT_DELAY_DEFAULT; - - SET_IF_PARAM (IF_DEF_PARAMS (ifp), retransmit_interval); - IF_DEF_PARAMS (ifp)->retransmit_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT; - - SET_IF_PARAM (IF_DEF_PARAMS (ifp), priority); - IF_DEF_PARAMS (ifp)->priority = OSPF_ROUTER_PRIORITY_DEFAULT; - - IF_DEF_PARAMS (ifp)->mtu_ignore = OSPF_MTU_IGNORE_DEFAULT; - - SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_hello); - IF_DEF_PARAMS (ifp)->v_hello = OSPF_HELLO_INTERVAL_DEFAULT; - - SET_IF_PARAM (IF_DEF_PARAMS (ifp), fast_hello); - IF_DEF_PARAMS (ifp)->fast_hello = OSPF_FAST_HELLO_DEFAULT; - - SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_wait); - IF_DEF_PARAMS (ifp)->v_wait = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT; - - SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_simple); - memset (IF_DEF_PARAMS (ifp)->auth_simple, 0, OSPF_AUTH_SIMPLE_SIZE); - - SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_type); - IF_DEF_PARAMS (ifp)->auth_type = OSPF_AUTH_NOTSET; - - rc = ospf_opaque_new_if (ifp); - return rc; + int rc = 0; + + ifp->info = XCALLOC(MTYPE_OSPF_IF_INFO, sizeof(struct ospf_if_info)); + + IF_OIFS(ifp) = route_table_init(); + IF_OIFS_PARAMS(ifp) = route_table_init(); + + IF_DEF_PARAMS(ifp) = ospf_new_if_params(); + + SET_IF_PARAM(IF_DEF_PARAMS(ifp), transmit_delay); + IF_DEF_PARAMS(ifp)->transmit_delay = OSPF_TRANSMIT_DELAY_DEFAULT; + + SET_IF_PARAM(IF_DEF_PARAMS(ifp), retransmit_interval); + IF_DEF_PARAMS(ifp)->retransmit_interval = + OSPF_RETRANSMIT_INTERVAL_DEFAULT; + + SET_IF_PARAM(IF_DEF_PARAMS(ifp), priority); + IF_DEF_PARAMS(ifp)->priority = OSPF_ROUTER_PRIORITY_DEFAULT; + + IF_DEF_PARAMS(ifp)->mtu_ignore = OSPF_MTU_IGNORE_DEFAULT; + + SET_IF_PARAM(IF_DEF_PARAMS(ifp), v_hello); + IF_DEF_PARAMS(ifp)->v_hello = OSPF_HELLO_INTERVAL_DEFAULT; + + SET_IF_PARAM(IF_DEF_PARAMS(ifp), fast_hello); + IF_DEF_PARAMS(ifp)->fast_hello = OSPF_FAST_HELLO_DEFAULT; + + SET_IF_PARAM(IF_DEF_PARAMS(ifp), v_wait); + IF_DEF_PARAMS(ifp)->v_wait = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT; + + SET_IF_PARAM(IF_DEF_PARAMS(ifp), auth_simple); + memset(IF_DEF_PARAMS(ifp)->auth_simple, 0, OSPF_AUTH_SIMPLE_SIZE); + + SET_IF_PARAM(IF_DEF_PARAMS(ifp), auth_type); + IF_DEF_PARAMS(ifp)->auth_type = OSPF_AUTH_NOTSET; + + rc = ospf_opaque_new_if(ifp); + return rc; } -static int -ospf_if_delete_hook (struct interface *ifp) +static int ospf_if_delete_hook(struct interface *ifp) { - int rc = 0; - struct route_node *rn; - rc = ospf_opaque_del_if (ifp); + int rc = 0; + struct route_node *rn; + rc = ospf_opaque_del_if(ifp); - route_table_finish (IF_OIFS (ifp)); + route_table_finish(IF_OIFS(ifp)); - for (rn = route_top (IF_OIFS_PARAMS (ifp)); rn; rn = route_next (rn)) - if (rn->info) - ospf_del_if_params (rn->info); - route_table_finish (IF_OIFS_PARAMS (ifp)); + for (rn = route_top(IF_OIFS_PARAMS(ifp)); rn; rn = route_next(rn)) + if (rn->info) + ospf_del_if_params(rn->info); + route_table_finish(IF_OIFS_PARAMS(ifp)); - ospf_del_if_params ((struct ospf_if_params *) IF_DEF_PARAMS (ifp)); - XFREE (MTYPE_OSPF_IF_INFO, ifp->info); - ifp->info = NULL; + ospf_del_if_params((struct ospf_if_params *)IF_DEF_PARAMS(ifp)); + XFREE(MTYPE_OSPF_IF_INFO, ifp->info); + ifp->info = NULL; - return rc; + return rc; } -int -ospf_if_is_enable (struct ospf_interface *oi) +int ospf_if_is_enable(struct ospf_interface *oi) { - if (!if_is_loopback (oi->ifp)) - if (if_is_up (oi->ifp)) - return 1; + if (!if_is_loopback(oi->ifp)) + if (if_is_up(oi->ifp)) + return 1; - return 0; + return 0; } -void -ospf_if_set_multicast(struct ospf_interface *oi) +void ospf_if_set_multicast(struct ospf_interface *oi) { - if ((oi->state > ISM_Loopback) && - (oi->type != OSPF_IFTYPE_LOOPBACK) && - (oi->type != OSPF_IFTYPE_VIRTUALLINK) && - (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_ACTIVE)) - { - /* The interface should belong to the OSPF-all-routers group. */ - if (!OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS) && - (ospf_if_add_allspfrouters(oi->ospf, oi->address, - oi->ifp->ifindex) >= 0)) - /* Set the flag only if the system call to join succeeded. */ - OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS); - } - else - { - /* The interface should NOT belong to the OSPF-all-routers group. */ - if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS)) - { - /* Only actually drop if this is the last reference */ - if (OI_MEMBER_COUNT(oi, MEMBER_ALLROUTERS) == 1) - ospf_if_drop_allspfrouters (oi->ospf, oi->address, - oi->ifp->ifindex); - /* Unset the flag regardless of whether the system call to leave - the group succeeded, since it's much safer to assume that - we are not a member. */ - OI_MEMBER_LEFT(oi,MEMBER_ALLROUTERS); - } - } - - if (((oi->type == OSPF_IFTYPE_BROADCAST) || - (oi->type == OSPF_IFTYPE_POINTOPOINT)) && - ((oi->state == ISM_DR) || (oi->state == ISM_Backup)) && - (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_ACTIVE)) - { - /* The interface should belong to the OSPF-designated-routers group. */ - if (!OI_MEMBER_CHECK(oi, MEMBER_DROUTERS) && - (ospf_if_add_alldrouters(oi->ospf, oi->address, - oi->ifp->ifindex) >= 0)) - /* Set the flag only if the system call to join succeeded. */ - OI_MEMBER_JOINED(oi, MEMBER_DROUTERS); - } - else - { - /* The interface should NOT belong to the OSPF-designated-routers group */ - if (OI_MEMBER_CHECK(oi, MEMBER_DROUTERS)) - { - /* drop only if last reference */ - if (OI_MEMBER_COUNT(oi, MEMBER_DROUTERS) == 1) - ospf_if_drop_alldrouters(oi->ospf, oi->address, oi->ifp->ifindex); - - /* Unset the flag regardless of whether the system call to leave - the group succeeded, since it's much safer to assume that - we are not a member. */ - OI_MEMBER_LEFT(oi, MEMBER_DROUTERS); - } - } + if ((oi->state > ISM_Loopback) && (oi->type != OSPF_IFTYPE_LOOPBACK) + && (oi->type != OSPF_IFTYPE_VIRTUALLINK) + && (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_ACTIVE)) { + /* The interface should belong to the OSPF-all-routers group. */ + if (!OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS) + && (ospf_if_add_allspfrouters(oi->ospf, oi->address, + oi->ifp->ifindex) + >= 0)) + /* Set the flag only if the system call to join + * succeeded. */ + OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS); + } else { + /* The interface should NOT belong to the OSPF-all-routers + * group. */ + if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS)) { + /* Only actually drop if this is the last reference */ + if (OI_MEMBER_COUNT(oi, MEMBER_ALLROUTERS) == 1) + ospf_if_drop_allspfrouters(oi->ospf, + oi->address, + oi->ifp->ifindex); + /* Unset the flag regardless of whether the system call + to leave + the group succeeded, since it's much safer to assume + that + we are not a member. */ + OI_MEMBER_LEFT(oi, MEMBER_ALLROUTERS); + } + } + + if (((oi->type == OSPF_IFTYPE_BROADCAST) + || (oi->type == OSPF_IFTYPE_POINTOPOINT)) + && ((oi->state == ISM_DR) || (oi->state == ISM_Backup)) + && (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_ACTIVE)) { + /* The interface should belong to the OSPF-designated-routers + * group. */ + if (!OI_MEMBER_CHECK(oi, MEMBER_DROUTERS) + && (ospf_if_add_alldrouters(oi->ospf, oi->address, + oi->ifp->ifindex) + >= 0)) + /* Set the flag only if the system call to join + * succeeded. */ + OI_MEMBER_JOINED(oi, MEMBER_DROUTERS); + } else { + /* The interface should NOT belong to the + * OSPF-designated-routers group */ + if (OI_MEMBER_CHECK(oi, MEMBER_DROUTERS)) { + /* drop only if last reference */ + if (OI_MEMBER_COUNT(oi, MEMBER_DROUTERS) == 1) + ospf_if_drop_alldrouters(oi->ospf, oi->address, + oi->ifp->ifindex); + + /* Unset the flag regardless of whether the system call + to leave + the group succeeded, since it's much safer to assume + that + we are not a member. */ + OI_MEMBER_LEFT(oi, MEMBER_DROUTERS); + } + } } -int -ospf_if_up (struct ospf_interface *oi) +int ospf_if_up(struct ospf_interface *oi) { - if (oi == NULL) - return 0; - - if (oi->type == OSPF_IFTYPE_LOOPBACK) - OSPF_ISM_EVENT_SCHEDULE (oi, ISM_LoopInd); - else - { - ospf_if_stream_set (oi); - OSPF_ISM_EVENT_SCHEDULE (oi, ISM_InterfaceUp); - } - - return 1; + if (oi == NULL) + return 0; + + if (oi->type == OSPF_IFTYPE_LOOPBACK) + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_LoopInd); + else { + ospf_if_stream_set(oi); + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_InterfaceUp); + } + + return 1; } -int -ospf_if_down (struct ospf_interface *oi) +int ospf_if_down(struct ospf_interface *oi) { - if (oi == NULL) - return 0; + if (oi == NULL) + return 0; - OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown); - /* delete position in router LSA */ - oi->lsa_pos_beg = 0; - oi->lsa_pos_end = 0; - /* Shutdown packet reception and sending */ - ospf_if_stream_unset (oi); + OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown); + /* delete position in router LSA */ + oi->lsa_pos_beg = 0; + oi->lsa_pos_end = 0; + /* Shutdown packet reception and sending */ + ospf_if_stream_unset(oi); - return 1; + return 1; } /* Virtual Link related functions. */ -struct ospf_vl_data * -ospf_vl_data_new (struct ospf_area *area, struct in_addr vl_peer) +struct ospf_vl_data *ospf_vl_data_new(struct ospf_area *area, + struct in_addr vl_peer) { - struct ospf_vl_data *vl_data; + struct ospf_vl_data *vl_data; - vl_data = XCALLOC (MTYPE_OSPF_VL_DATA, sizeof (struct ospf_vl_data)); + vl_data = XCALLOC(MTYPE_OSPF_VL_DATA, sizeof(struct ospf_vl_data)); - vl_data->vl_peer.s_addr = vl_peer.s_addr; - vl_data->vl_area_id = area->area_id; - vl_data->vl_area_id_fmt = area->area_id_fmt; + vl_data->vl_peer.s_addr = vl_peer.s_addr; + vl_data->vl_area_id = area->area_id; + vl_data->vl_area_id_fmt = area->area_id_fmt; - return vl_data; + return vl_data; } -void -ospf_vl_data_free (struct ospf_vl_data *vl_data) +void ospf_vl_data_free(struct ospf_vl_data *vl_data) { - XFREE (MTYPE_OSPF_VL_DATA, vl_data); + XFREE(MTYPE_OSPF_VL_DATA, vl_data); } u_int vlink_count = 0; -struct ospf_interface * -ospf_vl_new (struct ospf *ospf, struct ospf_vl_data *vl_data) +struct ospf_interface *ospf_vl_new(struct ospf *ospf, + struct ospf_vl_data *vl_data) { - struct ospf_interface * voi; - struct interface * vi; - char ifname[INTERFACE_NAMSIZ + 1]; - struct ospf_area *area; - struct in_addr area_id; - struct connected *co; - struct prefix_ipv4 *p; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_vl_new(): Start"); - if (vlink_count == OSPF_VL_MAX_COUNT) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_vl_new(): Alarm: " - "cannot create more than OSPF_MAX_VL_COUNT virtual links"); - return NULL; - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_vl_new(): creating pseudo zebra interface"); - - snprintf (ifname, sizeof(ifname), "VLINK%d", vlink_count); - vi = if_create (ifname, strnlen(ifname, sizeof(ifname)), VRF_DEFAULT); - /* - * if_create sets ZEBRA_INTERFACE_LINKDETECTION - * virtual links don't need this. - */ - UNSET_FLAG (vi->status, ZEBRA_INTERFACE_LINKDETECTION); - co = connected_new (); - co->ifp = vi; - listnode_add (vi->connected, co); - - p = prefix_ipv4_new (); - p->family = AF_INET; - p->prefix.s_addr = 0; - p->prefixlen = 0; - - co->address = (struct prefix *)p; - - voi = ospf_if_new (ospf, vi, co->address); - if (voi == NULL) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_vl_new(): Alarm: OSPF int structure is not created"); - return NULL; - } - voi->connected = co; - voi->vl_data = vl_data; - voi->ifp->mtu = OSPF_VL_MTU; - voi->type = OSPF_IFTYPE_VIRTUALLINK; - - vlink_count++; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_vl_new(): Created name: %s", ifname); - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_vl_new(): set if->name to %s", vi->name); - - area_id.s_addr = 0; - area = ospf_area_get (ospf, area_id); - voi->area = area; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_vl_new(): set associated area to the backbone"); - - /* Add pseudo neighbor. */ - ospf_nbr_self_reset (voi, voi->ospf->router_id); - - ospf_area_add_if (voi->area, voi); - - ospf_if_stream_set (voi); - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_vl_new(): Stop"); - return voi; + struct ospf_interface *voi; + struct interface *vi; + char ifname[INTERFACE_NAMSIZ + 1]; + struct ospf_area *area; + struct in_addr area_id; + struct connected *co; + struct prefix_ipv4 *p; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_vl_new(): Start"); + if (vlink_count == OSPF_VL_MAX_COUNT) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_vl_new(): Alarm: " + "cannot create more than OSPF_MAX_VL_COUNT virtual links"); + return NULL; + } + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_vl_new(): creating pseudo zebra interface"); + + snprintf(ifname, sizeof(ifname), "VLINK%d", vlink_count); + vi = if_create(ifname, strnlen(ifname, sizeof(ifname)), VRF_DEFAULT); + /* + * if_create sets ZEBRA_INTERFACE_LINKDETECTION + * virtual links don't need this. + */ + UNSET_FLAG(vi->status, ZEBRA_INTERFACE_LINKDETECTION); + co = connected_new(); + co->ifp = vi; + listnode_add(vi->connected, co); + + p = prefix_ipv4_new(); + p->family = AF_INET; + p->prefix.s_addr = 0; + p->prefixlen = 0; + + co->address = (struct prefix *)p; + + voi = ospf_if_new(ospf, vi, co->address); + if (voi == NULL) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_vl_new(): Alarm: OSPF int structure is not created"); + return NULL; + } + voi->connected = co; + voi->vl_data = vl_data; + voi->ifp->mtu = OSPF_VL_MTU; + voi->type = OSPF_IFTYPE_VIRTUALLINK; + + vlink_count++; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_vl_new(): Created name: %s", ifname); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_vl_new(): set if->name to %s", vi->name); + + area_id.s_addr = 0; + area = ospf_area_get(ospf, area_id); + voi->area = area; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_vl_new(): set associated area to the backbone"); + + /* Add pseudo neighbor. */ + ospf_nbr_self_reset(voi, voi->ospf->router_id); + + ospf_area_add_if(voi->area, voi); + + ospf_if_stream_set(voi); + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_vl_new(): Stop"); + return voi; } -static void -ospf_vl_if_delete (struct ospf_vl_data *vl_data) +static void ospf_vl_if_delete(struct ospf_vl_data *vl_data) { - struct interface *ifp = vl_data->vl_oi->ifp; - vl_data->vl_oi->address->u.prefix4.s_addr = 0; - vl_data->vl_oi->address->prefixlen = 0; - ospf_if_free (vl_data->vl_oi); - if_delete (ifp); - vlink_count--; + struct interface *ifp = vl_data->vl_oi->ifp; + vl_data->vl_oi->address->u.prefix4.s_addr = 0; + vl_data->vl_oi->address->prefixlen = 0; + ospf_if_free(vl_data->vl_oi); + if_delete(ifp); + vlink_count--; } /* Look up vl_data for given peer, optionally qualified to be in the * specified area. NULL area returns first found.. */ -struct ospf_vl_data * -ospf_vl_lookup (struct ospf *ospf, struct ospf_area *area, - struct in_addr vl_peer) +struct ospf_vl_data *ospf_vl_lookup(struct ospf *ospf, struct ospf_area *area, + struct in_addr vl_peer) { - struct ospf_vl_data *vl_data; - struct listnode *node; - - if (IS_DEBUG_OSPF_EVENT) - { - zlog_debug ("%s: Looking for %s", __func__, inet_ntoa (vl_peer)); - if (area) - zlog_debug ("%s: in area %s", __func__, inet_ntoa (area->area_id)); - } - - for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("%s: VL %s, peer %s", __func__, - vl_data->vl_oi->ifp->name, - inet_ntoa (vl_data->vl_peer)); - - if (area && !IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id)) - continue; - - if (IPV4_ADDR_SAME (&vl_data->vl_peer, &vl_peer)) - return vl_data; - } - - return NULL; + struct ospf_vl_data *vl_data; + struct listnode *node; + + if (IS_DEBUG_OSPF_EVENT) { + zlog_debug("%s: Looking for %s", __func__, inet_ntoa(vl_peer)); + if (area) + zlog_debug("%s: in area %s", __func__, + inet_ntoa(area->area_id)); + } + + for (ALL_LIST_ELEMENTS_RO(ospf->vlinks, node, vl_data)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: VL %s, peer %s", __func__, + vl_data->vl_oi->ifp->name, + inet_ntoa(vl_data->vl_peer)); + + if (area + && !IPV4_ADDR_SAME(&vl_data->vl_area_id, &area->area_id)) + continue; + + if (IPV4_ADDR_SAME(&vl_data->vl_peer, &vl_peer)) + return vl_data; + } + + return NULL; } -static void -ospf_vl_shutdown (struct ospf_vl_data *vl_data) +static void ospf_vl_shutdown(struct ospf_vl_data *vl_data) { - struct ospf_interface *oi; + struct ospf_interface *oi; - if ((oi = vl_data->vl_oi) == NULL) - return; + if ((oi = vl_data->vl_oi) == NULL) + return; - oi->address->u.prefix4.s_addr = 0; - oi->address->prefixlen = 0; + oi->address->u.prefix4.s_addr = 0; + oi->address->prefixlen = 0; - UNSET_FLAG (oi->ifp->flags, IFF_UP); - /* OSPF_ISM_EVENT_SCHEDULE (oi, ISM_InterfaceDown); */ - OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown); + UNSET_FLAG(oi->ifp->flags, IFF_UP); + /* OSPF_ISM_EVENT_SCHEDULE (oi, ISM_InterfaceDown); */ + OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown); } -void -ospf_vl_add (struct ospf *ospf, struct ospf_vl_data *vl_data) +void ospf_vl_add(struct ospf *ospf, struct ospf_vl_data *vl_data) { - listnode_add (ospf->vlinks, vl_data); - hook_call(ospf_vl_add, vl_data); + listnode_add(ospf->vlinks, vl_data); + hook_call(ospf_vl_add, vl_data); } -void -ospf_vl_delete (struct ospf *ospf, struct ospf_vl_data *vl_data) +void ospf_vl_delete(struct ospf *ospf, struct ospf_vl_data *vl_data) { - ospf_vl_shutdown (vl_data); - ospf_vl_if_delete (vl_data); + ospf_vl_shutdown(vl_data); + ospf_vl_if_delete(vl_data); - hook_call(ospf_vl_delete, vl_data); - listnode_delete (ospf->vlinks, vl_data); + hook_call(ospf_vl_delete, vl_data); + listnode_delete(ospf->vlinks, vl_data); - ospf_vl_data_free (vl_data); + ospf_vl_data_free(vl_data); } -static int -ospf_vl_set_params (struct ospf_vl_data *vl_data, struct vertex *v) +static int ospf_vl_set_params(struct ospf_vl_data *vl_data, struct vertex *v) { - int changed = 0; - struct ospf_interface *voi; - struct listnode *node; - struct vertex_parent *vp = NULL; - unsigned int i; - struct router_lsa *rl; - - voi = vl_data->vl_oi; - - if (voi->output_cost != v->distance) - { - - voi->output_cost = v->distance; - changed = 1; - } - - for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp)) - { - vl_data->nexthop.oi = vp->nexthop->oi; - vl_data->nexthop.router = vp->nexthop->router; - - if (!IPV4_ADDR_SAME(&voi->address->u.prefix4, - &vl_data->nexthop.oi->address->u.prefix4)) - changed = 1; - - voi->address->u.prefix4 = vl_data->nexthop.oi->address->u.prefix4; - voi->address->prefixlen = vl_data->nexthop.oi->address->prefixlen; - - break; /* We take the first interface. */ - } - - rl = (struct router_lsa *)v->lsa; - - /* use SPF determined backlink index in struct vertex - * for virtual link destination address - */ - if (vp && vp->backlink >= 0) - { - if (!IPV4_ADDR_SAME (&vl_data->peer_addr, - &rl->link[vp->backlink].link_data)) - changed = 1; - vl_data->peer_addr = rl->link[vp->backlink].link_data; - } - else - { - /* This is highly odd, there is no backlink index - * there should be due to the ospf_spf_has_link() check - * in SPF. Lets warn and try pick a link anyway. - */ - zlog_warn ("ospf_vl_set_params: No backlink for %s!", - vl_data->vl_oi->ifp->name); - for (i = 0; i < ntohs (rl->links); i++) - { - switch (rl->link[i].type) - { - case LSA_LINK_TYPE_VIRTUALLINK: - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("found back link through VL"); - /* fallthru */ - case LSA_LINK_TYPE_TRANSIT: - case LSA_LINK_TYPE_POINTOPOINT: - if (!IPV4_ADDR_SAME (&vl_data->peer_addr, - &rl->link[i].link_data)) - changed = 1; - vl_data->peer_addr = rl->link[i].link_data; - } - } - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("%s: %s peer address: %s, cost: %d,%schanged", __func__, - vl_data->vl_oi->ifp->name, - inet_ntoa(vl_data->peer_addr), - voi->output_cost, - (changed ? " " : " un")); - - return changed; + int changed = 0; + struct ospf_interface *voi; + struct listnode *node; + struct vertex_parent *vp = NULL; + unsigned int i; + struct router_lsa *rl; + + voi = vl_data->vl_oi; + + if (voi->output_cost != v->distance) { + + voi->output_cost = v->distance; + changed = 1; + } + + for (ALL_LIST_ELEMENTS_RO(v->parents, node, vp)) { + vl_data->nexthop.oi = vp->nexthop->oi; + vl_data->nexthop.router = vp->nexthop->router; + + if (!IPV4_ADDR_SAME(&voi->address->u.prefix4, + &vl_data->nexthop.oi->address->u.prefix4)) + changed = 1; + + voi->address->u.prefix4 = + vl_data->nexthop.oi->address->u.prefix4; + voi->address->prefixlen = + vl_data->nexthop.oi->address->prefixlen; + + break; /* We take the first interface. */ + } + + rl = (struct router_lsa *)v->lsa; + + /* use SPF determined backlink index in struct vertex + * for virtual link destination address + */ + if (vp && vp->backlink >= 0) { + if (!IPV4_ADDR_SAME(&vl_data->peer_addr, + &rl->link[vp->backlink].link_data)) + changed = 1; + vl_data->peer_addr = rl->link[vp->backlink].link_data; + } else { + /* This is highly odd, there is no backlink index + * there should be due to the ospf_spf_has_link() check + * in SPF. Lets warn and try pick a link anyway. + */ + zlog_warn("ospf_vl_set_params: No backlink for %s!", + vl_data->vl_oi->ifp->name); + for (i = 0; i < ntohs(rl->links); i++) { + switch (rl->link[i].type) { + case LSA_LINK_TYPE_VIRTUALLINK: + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "found back link through VL"); + /* fallthru */ + case LSA_LINK_TYPE_TRANSIT: + case LSA_LINK_TYPE_POINTOPOINT: + if (!IPV4_ADDR_SAME(&vl_data->peer_addr, + &rl->link[i].link_data)) + changed = 1; + vl_data->peer_addr = rl->link[i].link_data; + } + } + } + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: %s peer address: %s, cost: %d,%schanged", + __func__, vl_data->vl_oi->ifp->name, + inet_ntoa(vl_data->peer_addr), voi->output_cost, + (changed ? " " : " un")); + + return changed; } -void -ospf_vl_up_check (struct ospf_area *area, struct in_addr rid, - struct vertex *v) +void ospf_vl_up_check(struct ospf_area *area, struct in_addr rid, + struct vertex *v) { - struct ospf *ospf = area->ospf; - struct listnode *node; - struct ospf_vl_data *vl_data; - struct ospf_interface *oi; - - if (IS_DEBUG_OSPF_EVENT) - { - zlog_debug ("ospf_vl_up_check(): Start"); - zlog_debug ("ospf_vl_up_check(): Router ID is %s", inet_ntoa (rid)); - zlog_debug ("ospf_vl_up_check(): Area is %s", inet_ntoa (area->area_id)); - } - - for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data)) - { - if (IS_DEBUG_OSPF_EVENT) - { - zlog_debug ("%s: considering VL, %s in area %s", __func__, - vl_data->vl_oi->ifp->name, - inet_ntoa (vl_data->vl_area_id)); - zlog_debug ("%s: peer ID: %s", __func__, - inet_ntoa (vl_data->vl_peer)); + struct ospf *ospf = area->ospf; + struct listnode *node; + struct ospf_vl_data *vl_data; + struct ospf_interface *oi; + + if (IS_DEBUG_OSPF_EVENT) { + zlog_debug("ospf_vl_up_check(): Start"); + zlog_debug("ospf_vl_up_check(): Router ID is %s", + inet_ntoa(rid)); + zlog_debug("ospf_vl_up_check(): Area is %s", + inet_ntoa(area->area_id)); } - if (IPV4_ADDR_SAME (&vl_data->vl_peer, &rid) && - IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id)) - { - oi = vl_data->vl_oi; - SET_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED); - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_vl_up_check(): this VL matched"); - - if (oi->state == ISM_Down) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_vl_up_check(): VL is down, waking it up"); - SET_FLAG (oi->ifp->flags, IFF_UP); - OSPF_ISM_EVENT_EXECUTE(oi,ISM_InterfaceUp); - } - - if (ospf_vl_set_params (vl_data, v)) - { - if (IS_DEBUG_OSPF (ism, ISM_EVENTS)) - zlog_debug ("ospf_vl_up_check: VL cost change," - " scheduling router lsa refresh"); - if (ospf->backbone) - ospf_router_lsa_update_area (ospf->backbone); - else if (IS_DEBUG_OSPF (ism, ISM_EVENTS)) - zlog_debug ("ospf_vl_up_check: VL cost change, no backbone!"); - } - } - } + for (ALL_LIST_ELEMENTS_RO(ospf->vlinks, node, vl_data)) { + if (IS_DEBUG_OSPF_EVENT) { + zlog_debug("%s: considering VL, %s in area %s", + __func__, vl_data->vl_oi->ifp->name, + inet_ntoa(vl_data->vl_area_id)); + zlog_debug("%s: peer ID: %s", __func__, + inet_ntoa(vl_data->vl_peer)); + } + + if (IPV4_ADDR_SAME(&vl_data->vl_peer, &rid) + && IPV4_ADDR_SAME(&vl_data->vl_area_id, &area->area_id)) { + oi = vl_data->vl_oi; + SET_FLAG(vl_data->flags, OSPF_VL_FLAG_APPROVED); + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_vl_up_check(): this VL matched"); + + if (oi->state == ISM_Down) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_vl_up_check(): VL is down, waking it up"); + SET_FLAG(oi->ifp->flags, IFF_UP); + OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceUp); + } + + if (ospf_vl_set_params(vl_data, v)) { + if (IS_DEBUG_OSPF(ism, ISM_EVENTS)) + zlog_debug( + "ospf_vl_up_check: VL cost change," + " scheduling router lsa refresh"); + if (ospf->backbone) + ospf_router_lsa_update_area( + ospf->backbone); + else if (IS_DEBUG_OSPF(ism, ISM_EVENTS)) + zlog_debug( + "ospf_vl_up_check: VL cost change, no backbone!"); + } + } + } } -void -ospf_vl_unapprove (struct ospf *ospf) +void ospf_vl_unapprove(struct ospf *ospf) { - struct listnode *node; - struct ospf_vl_data *vl_data; + struct listnode *node; + struct ospf_vl_data *vl_data; - for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data)) - UNSET_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED); + for (ALL_LIST_ELEMENTS_RO(ospf->vlinks, node, vl_data)) + UNSET_FLAG(vl_data->flags, OSPF_VL_FLAG_APPROVED); } -void -ospf_vl_shut_unapproved (struct ospf *ospf) +void ospf_vl_shut_unapproved(struct ospf *ospf) { - struct listnode *node, *nnode; - struct ospf_vl_data *vl_data; + struct listnode *node, *nnode; + struct ospf_vl_data *vl_data; - for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data)) - if (!CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED)) - ospf_vl_shutdown (vl_data); + for (ALL_LIST_ELEMENTS(ospf->vlinks, node, nnode, vl_data)) + if (!CHECK_FLAG(vl_data->flags, OSPF_VL_FLAG_APPROVED)) + ospf_vl_shutdown(vl_data); } -int -ospf_full_virtual_nbrs (struct ospf_area *area) +int ospf_full_virtual_nbrs(struct ospf_area *area) { - if (IS_DEBUG_OSPF_EVENT) - { - zlog_debug ("counting fully adjacent virtual neighbors in area %s", - inet_ntoa (area->area_id)); - zlog_debug ("there are %d of them", area->full_vls); - } - - return area->full_vls; + if (IS_DEBUG_OSPF_EVENT) { + zlog_debug( + "counting fully adjacent virtual neighbors in area %s", + inet_ntoa(area->area_id)); + zlog_debug("there are %d of them", area->full_vls); + } + + return area->full_vls; } -int -ospf_vls_in_area (struct ospf_area *area) +int ospf_vls_in_area(struct ospf_area *area) { - struct listnode *node; - struct ospf_vl_data *vl_data; - int c = 0; + struct listnode *node; + struct ospf_vl_data *vl_data; + int c = 0; - for (ALL_LIST_ELEMENTS_RO (area->ospf->vlinks, node, vl_data)) - if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id)) - c++; + for (ALL_LIST_ELEMENTS_RO(area->ospf->vlinks, node, vl_data)) + if (IPV4_ADDR_SAME(&vl_data->vl_area_id, &area->area_id)) + c++; - return c; + return c; } -struct crypt_key * -ospf_crypt_key_new () +struct crypt_key *ospf_crypt_key_new() { - return XCALLOC (MTYPE_OSPF_CRYPT_KEY, sizeof (struct crypt_key)); + return XCALLOC(MTYPE_OSPF_CRYPT_KEY, sizeof(struct crypt_key)); } -void -ospf_crypt_key_add (struct list *crypt, struct crypt_key *ck) +void ospf_crypt_key_add(struct list *crypt, struct crypt_key *ck) { - listnode_add (crypt, ck); + listnode_add(crypt, ck); } -struct crypt_key * -ospf_crypt_key_lookup (struct list *auth_crypt, u_char key_id) +struct crypt_key *ospf_crypt_key_lookup(struct list *auth_crypt, u_char key_id) { - struct listnode *node; - struct crypt_key *ck; + struct listnode *node; + struct crypt_key *ck; - for (ALL_LIST_ELEMENTS_RO (auth_crypt, node, ck)) - if (ck->key_id == key_id) - return ck; + for (ALL_LIST_ELEMENTS_RO(auth_crypt, node, ck)) + if (ck->key_id == key_id) + return ck; - return NULL; + return NULL; } -int -ospf_crypt_key_delete (struct list *auth_crypt, u_char key_id) +int ospf_crypt_key_delete(struct list *auth_crypt, u_char key_id) { - struct listnode *node, *nnode; - struct crypt_key *ck; - - for (ALL_LIST_ELEMENTS (auth_crypt, node, nnode, ck)) - { - if (ck->key_id == key_id) - { - listnode_delete (auth_crypt, ck); - XFREE (MTYPE_OSPF_CRYPT_KEY, ck); - return 1; - } - } - - return 0; + struct listnode *node, *nnode; + struct crypt_key *ck; + + for (ALL_LIST_ELEMENTS(auth_crypt, node, nnode, ck)) { + if (ck->key_id == key_id) { + listnode_delete(auth_crypt, ck); + XFREE(MTYPE_OSPF_CRYPT_KEY, ck); + return 1; + } + } + + return 0; } -u_char -ospf_default_iftype(struct interface *ifp) +u_char ospf_default_iftype(struct interface *ifp) { - if (if_is_pointopoint (ifp)) - return OSPF_IFTYPE_POINTOPOINT; - else if (if_is_loopback (ifp)) - return OSPF_IFTYPE_LOOPBACK; - else - return OSPF_IFTYPE_BROADCAST; + if (if_is_pointopoint(ifp)) + return OSPF_IFTYPE_POINTOPOINT; + else if (if_is_loopback(ifp)) + return OSPF_IFTYPE_LOOPBACK; + else + return OSPF_IFTYPE_BROADCAST; } -void -ospf_if_init () +void ospf_if_init() { - /* Initialize Zebra interface data structure. */ - om->iflist = vrf_iflist (VRF_DEFAULT); - if_add_hook (IF_NEW_HOOK, ospf_if_new_hook); - if_add_hook (IF_DELETE_HOOK, ospf_if_delete_hook); + /* Initialize Zebra interface data structure. */ + om->iflist = vrf_iflist(VRF_DEFAULT); + if_add_hook(IF_NEW_HOOK, ospf_if_new_hook); + if_add_hook(IF_DELETE_HOOK, ospf_if_delete_hook); } diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h index afb282010..d4b495b20 100644 --- a/ospfd/ospf_interface.h +++ b/ospfd/ospf_interface.h @@ -38,87 +38,93 @@ /* Test whether an OSPF interface parameter is set, generally, given some * existing ospf interface */ -#define OSPF_IF_PARAM_IS_SET(O,P) \ - (OSPF_IF_PARAM_CONFIGURED ((O)->params, P) || \ - OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS((O)->ifp)->P)) +#define OSPF_IF_PARAM_IS_SET(O, P) \ + (OSPF_IF_PARAM_CONFIGURED((O)->params, P) \ + || OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS((O)->ifp)->P)) -#define OSPF_IF_PARAM(O, P) \ - (OSPF_IF_PARAM_CONFIGURED ((O)->params, P)?\ - (O)->params->P:IF_DEF_PARAMS((O)->ifp)->P) +#define OSPF_IF_PARAM(O, P) \ + (OSPF_IF_PARAM_CONFIGURED((O)->params, P) \ + ? (O)->params->P \ + : IF_DEF_PARAMS((O)->ifp)->P) #define DECLARE_IF_PARAM(T, P) T P; u_char P##__config:1 #define UNSET_IF_PARAM(S, P) ((S)->P##__config) = 0 #define SET_IF_PARAM(S, P) ((S)->P##__config) = 1 -struct ospf_if_params -{ - DECLARE_IF_PARAM (u_int32_t, transmit_delay); /* Interface Transmisson Delay */ - DECLARE_IF_PARAM (u_int32_t, output_cost_cmd);/* Command Interface Output Cost */ - DECLARE_IF_PARAM (u_int32_t, retransmit_interval); /* Retransmission Interval */ - DECLARE_IF_PARAM (u_char, passive_interface); /* OSPF Interface is passive: no sending or receiving (no need to join multicast groups) */ - DECLARE_IF_PARAM (u_char, priority); /* OSPF Interface priority */ - /* Enable OSPF on this interface with area if_area */ - DECLARE_IF_PARAM (struct in_addr, if_area); - DECLARE_IF_PARAM (u_char, type); /* type of interface */ +struct ospf_if_params { + DECLARE_IF_PARAM(u_int32_t, + transmit_delay); /* Interface Transmisson Delay */ + DECLARE_IF_PARAM(u_int32_t, + output_cost_cmd); /* Command Interface Output Cost */ + DECLARE_IF_PARAM(u_int32_t, + retransmit_interval); /* Retransmission Interval */ + DECLARE_IF_PARAM(u_char, passive_interface); /* OSPF Interface is + passive: no sending or + receiving (no need to + join multicast groups) + */ + DECLARE_IF_PARAM(u_char, priority); /* OSPF Interface priority */ + /* Enable OSPF on this interface with area if_area */ + DECLARE_IF_PARAM(struct in_addr, if_area); + DECLARE_IF_PARAM(u_char, type); /* type of interface */ #define OSPF_IF_ACTIVE 0 #define OSPF_IF_PASSIVE 1 -#define OSPF_IF_PASSIVE_STATUS(O) \ - (OSPF_IF_PARAM_CONFIGURED((O)->params, passive_interface) ? \ - (O)->params->passive_interface : \ - (OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS((O)->ifp), passive_interface) ? \ - IF_DEF_PARAMS((O)->ifp)->passive_interface : \ - (O)->ospf->passive_interface_default)) - - DECLARE_IF_PARAM (u_int32_t, v_hello); /* Hello Interval */ - DECLARE_IF_PARAM (u_int32_t, v_wait); /* Router Dead Interval */ - - /* MTU mismatch check (see RFC2328, chap 10.6) */ - DECLARE_IF_PARAM (u_char, mtu_ignore); - - /* Fast-Hellos */ - DECLARE_IF_PARAM (u_char, fast_hello); - - /* Authentication data. */ - u_char auth_simple[OSPF_AUTH_SIMPLE_SIZE + 1]; /* Simple password. */ - u_char auth_simple__config:1; - - DECLARE_IF_PARAM (struct list *, auth_crypt); /* List of Auth cryptographic data. */ - DECLARE_IF_PARAM (int, auth_type); /* OSPF authentication type */ - - /* Other, non-configuration state */ - u_int32_t network_lsa_seqnum; /* Network LSA seqnum */ - - /* BFD configuration */ - struct bfd_info *bfd_info; +#define OSPF_IF_PASSIVE_STATUS(O) \ + (OSPF_IF_PARAM_CONFIGURED((O)->params, passive_interface) \ + ? (O)->params->passive_interface \ + : (OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS((O)->ifp), \ + passive_interface) \ + ? IF_DEF_PARAMS((O)->ifp)->passive_interface \ + : (O)->ospf->passive_interface_default)) + + DECLARE_IF_PARAM(u_int32_t, v_hello); /* Hello Interval */ + DECLARE_IF_PARAM(u_int32_t, v_wait); /* Router Dead Interval */ + + /* MTU mismatch check (see RFC2328, chap 10.6) */ + DECLARE_IF_PARAM(u_char, mtu_ignore); + + /* Fast-Hellos */ + DECLARE_IF_PARAM(u_char, fast_hello); + + /* Authentication data. */ + u_char auth_simple[OSPF_AUTH_SIMPLE_SIZE + 1]; /* Simple password. */ + u_char auth_simple__config : 1; + + DECLARE_IF_PARAM(struct list *, + auth_crypt); /* List of Auth cryptographic data. */ + DECLARE_IF_PARAM(int, auth_type); /* OSPF authentication type */ + + /* Other, non-configuration state */ + u_int32_t network_lsa_seqnum; /* Network LSA seqnum */ + + /* BFD configuration */ + struct bfd_info *bfd_info; }; -enum -{ - MEMBER_ALLROUTERS = 0, - MEMBER_DROUTERS, - MEMBER_MAX, +enum { MEMBER_ALLROUTERS = 0, + MEMBER_DROUTERS, + MEMBER_MAX, }; -struct ospf_if_info -{ - struct ospf_if_params *def_params; - struct route_table *params; - struct route_table *oifs; - unsigned int membership_counts[MEMBER_MAX]; /* multicast group refcnts */ +struct ospf_if_info { + struct ospf_if_params *def_params; + struct route_table *params; + struct route_table *oifs; + unsigned int + membership_counts[MEMBER_MAX]; /* multicast group refcnts */ }; struct ospf_interface; -struct ospf_vl_data -{ - struct in_addr vl_peer; /* Router-ID of the peer */ - struct in_addr vl_area_id; /* Transit area */ - int vl_area_id_fmt; /* Area ID format */ - struct ospf_interface *vl_oi; /* Interface data structure */ - struct vertex_nexthop nexthop; /* Nexthop router and oi to use */ - struct in_addr peer_addr; /* Address used to reach the peer */ - u_char flags; +struct ospf_vl_data { + struct in_addr vl_peer; /* Router-ID of the peer */ + struct in_addr vl_area_id; /* Transit area */ + int vl_area_id_fmt; /* Area ID format */ + struct ospf_interface *vl_oi; /* Interface data structure */ + struct vertex_nexthop nexthop; /* Nexthop router and oi to use */ + struct in_addr peer_addr; /* Address used to reach the peer */ + u_char flags; }; @@ -127,198 +133,193 @@ struct ospf_vl_data #define OSPF_VL_FLAG_APPROVED 0x01 -struct crypt_key -{ - u_char key_id; - u_char auth_key[OSPF_AUTH_MD5_SIZE + 1]; +struct crypt_key { + u_char key_id; + u_char auth_key[OSPF_AUTH_MD5_SIZE + 1]; }; /* OSPF interface structure. */ -struct ospf_interface -{ - /* This interface's parent ospf instance. */ - struct ospf *ospf; +struct ospf_interface { + /* This interface's parent ospf instance. */ + struct ospf *ospf; - /* OSPF Area. */ - struct ospf_area *area; + /* OSPF Area. */ + struct ospf_area *area; - /* Position range in Router LSA */ - uint16_t lsa_pos_beg; /* inclusive, >= */ - uint16_t lsa_pos_end; /* exclusive, < */ + /* Position range in Router LSA */ + uint16_t lsa_pos_beg; /* inclusive, >= */ + uint16_t lsa_pos_end; /* exclusive, < */ - /* Interface data from zebra. */ - struct interface *ifp; - struct ospf_vl_data *vl_data; /* Data for Virtual Link */ - - /* Packet send buffer. */ - struct ospf_fifo *obuf; /* Output queue */ + /* Interface data from zebra. */ + struct interface *ifp; + struct ospf_vl_data *vl_data; /* Data for Virtual Link */ - /* OSPF Network Type. */ - u_char type; + /* Packet send buffer. */ + struct ospf_fifo *obuf; /* Output queue */ - /* State of Interface State Machine. */ - u_char state; + /* OSPF Network Type. */ + u_char type; - /* To which multicast groups do we currently belong? */ - u_char multicast_memberships; + /* State of Interface State Machine. */ + u_char state; + + /* To which multicast groups do we currently belong? */ + u_char multicast_memberships; #define OI_MEMBER_FLAG(M) (1 << (M)) #define OI_MEMBER_COUNT(O,M) (IF_OSPF_IF_INFO(oi->ifp)->membership_counts[(M)]) -#define OI_MEMBER_CHECK(O,M) \ - (CHECK_FLAG((O)->multicast_memberships, OI_MEMBER_FLAG(M))) -#define OI_MEMBER_JOINED(O,M) \ - do { \ - SET_FLAG ((O)->multicast_memberships, OI_MEMBER_FLAG(M)); \ - IF_OSPF_IF_INFO((O)->ifp)->membership_counts[(M)]++; \ - } while (0) -#define OI_MEMBER_LEFT(O,M) \ - do { \ - UNSET_FLAG ((O)->multicast_memberships, OI_MEMBER_FLAG(M)); \ - IF_OSPF_IF_INFO((O)->ifp)->membership_counts[(M)]--; \ - } while (0) - - struct prefix *address; /* Interface prefix */ - struct connected *connected; /* Pointer to connected */ - - /* Configured varables. */ - struct ospf_if_params *params; - - u_int32_t crypt_seqnum; /* Cryptographic Sequence Number */ - u_int32_t output_cost; /* Acutual Interface Output Cost */ - - /* Neighbor information. */ - struct route_table *nbrs; /* OSPF Neighbor List */ - struct ospf_neighbor *nbr_self; /* Neighbor Self */ +#define OI_MEMBER_CHECK(O, M) \ + (CHECK_FLAG((O)->multicast_memberships, OI_MEMBER_FLAG(M))) +#define OI_MEMBER_JOINED(O, M) \ + do { \ + SET_FLAG((O)->multicast_memberships, OI_MEMBER_FLAG(M)); \ + IF_OSPF_IF_INFO((O)->ifp)->membership_counts[(M)]++; \ + } while (0) +#define OI_MEMBER_LEFT(O, M) \ + do { \ + UNSET_FLAG((O)->multicast_memberships, OI_MEMBER_FLAG(M)); \ + IF_OSPF_IF_INFO((O)->ifp)->membership_counts[(M)]--; \ + } while (0) + + struct prefix *address; /* Interface prefix */ + struct connected *connected; /* Pointer to connected */ + + /* Configured varables. */ + struct ospf_if_params *params; + + u_int32_t crypt_seqnum; /* Cryptographic Sequence Number */ + u_int32_t output_cost; /* Acutual Interface Output Cost */ + + /* Neighbor information. */ + struct route_table *nbrs; /* OSPF Neighbor List */ + struct ospf_neighbor *nbr_self; /* Neighbor Self */ + /* $FRR indent$ */ + /* clang-format off */ #define DR(I) ((I)->nbr_self->d_router) #define BDR(I) ((I)->nbr_self->bd_router) #define OPTIONS(I) ((I)->nbr_self->options) #define PRIORITY(I) ((I)->nbr_self->priority) - /* List of configured NBMA neighbor. */ - struct list *nbr_nbma; - - /* self-originated LSAs. */ - struct ospf_lsa *network_lsa_self; /* network-LSA. */ - struct list *opaque_lsa_self; /* Type-9 Opaque-LSAs */ - - struct route_table *ls_upd_queue; - - struct list *ls_ack; /* Link State Acknowledgment list. */ - - struct - { - struct list *ls_ack; - struct in_addr dst; - } ls_ack_direct; - - /* Timer values. */ - u_int32_t v_ls_ack; /* Delayed Link State Acknowledgment */ - - /* Threads. */ - struct thread *t_hello; /* timer */ - struct thread *t_wait; /* timer */ - struct thread *t_ls_ack; /* timer */ - struct thread *t_ls_ack_direct; /* event */ - struct thread *t_ls_upd_event; /* event */ - struct thread *t_opaque_lsa_self; /* Type-9 Opaque-LSAs */ - - int on_write_q; - - /* Statistics fields. */ - u_int32_t hello_in; /* Hello message input count. */ - u_int32_t hello_out; /* Hello message output count. */ - u_int32_t db_desc_in; /* database desc. message input count. */ - u_int32_t db_desc_out; /* database desc. message output count. */ - u_int32_t ls_req_in; /* LS request message input count. */ - u_int32_t ls_req_out; /* LS request message output count. */ - u_int32_t ls_upd_in; /* LS update message input count. */ - u_int32_t ls_upd_out; /* LS update message output count. */ - u_int32_t ls_ack_in; /* LS Ack message input count. */ - u_int32_t ls_ack_out; /* LS Ack message output count. */ - u_int32_t discarded; /* discarded input count by error. */ - u_int32_t state_change; /* Number of status change. */ - - u_int32_t full_nbrs; - - QOBJ_FIELDS + /* List of configured NBMA neighbor. */ + struct list *nbr_nbma; + + /* self-originated LSAs. */ + struct ospf_lsa *network_lsa_self; /* network-LSA. */ + struct list *opaque_lsa_self; /* Type-9 Opaque-LSAs */ + + struct route_table *ls_upd_queue; + + struct list *ls_ack; /* Link State Acknowledgment list. */ + + struct { + struct list *ls_ack; + struct in_addr dst; + } ls_ack_direct; + + /* Timer values. */ + u_int32_t v_ls_ack; /* Delayed Link State Acknowledgment */ + + /* Threads. */ + struct thread *t_hello; /* timer */ + struct thread *t_wait; /* timer */ + struct thread *t_ls_ack; /* timer */ + struct thread *t_ls_ack_direct; /* event */ + struct thread *t_ls_upd_event; /* event */ + struct thread *t_opaque_lsa_self; /* Type-9 Opaque-LSAs */ + + int on_write_q; + + /* Statistics fields. */ + u_int32_t hello_in; /* Hello message input count. */ + u_int32_t hello_out; /* Hello message output count. */ + u_int32_t db_desc_in; /* database desc. message input count. */ + u_int32_t db_desc_out; /* database desc. message output count. */ + u_int32_t ls_req_in; /* LS request message input count. */ + u_int32_t ls_req_out; /* LS request message output count. */ + u_int32_t ls_upd_in; /* LS update message input count. */ + u_int32_t ls_upd_out; /* LS update message output count. */ + u_int32_t ls_ack_in; /* LS Ack message input count. */ + u_int32_t ls_ack_out; /* LS Ack message output count. */ + u_int32_t discarded; /* discarded input count by error. */ + u_int32_t state_change; /* Number of status change. */ + + u_int32_t full_nbrs; + + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(ospf_interface) /* Prototypes. */ -extern char *ospf_if_name (struct ospf_interface *); -extern struct ospf_interface *ospf_if_new (struct ospf *, struct interface *, - struct prefix *); -extern void ospf_if_cleanup (struct ospf_interface *); -extern void ospf_if_free (struct ospf_interface *); -extern int ospf_if_up (struct ospf_interface *); -extern int ospf_if_down (struct ospf_interface *); - -extern int ospf_if_is_up (struct ospf_interface *); -extern struct ospf_interface *ospf_if_exists (struct ospf_interface *); -extern struct ospf_interface *ospf_if_lookup_by_lsa_pos (struct ospf_area *, - int); -extern struct ospf_interface *ospf_if_lookup_by_local_addr (struct ospf *, - struct interface - *, - struct in_addr); -extern struct ospf_interface *ospf_if_lookup_by_prefix (struct ospf *, - struct prefix_ipv4 *); -extern struct ospf_interface *ospf_if_table_lookup (struct interface *, - struct prefix *); -extern struct ospf_interface *ospf_if_addr_local (struct in_addr); -extern struct ospf_interface *ospf_if_lookup_recv_if (struct ospf *, - struct in_addr, - struct interface *); -extern struct ospf_interface *ospf_if_is_configured (struct ospf *, - struct in_addr *); - -extern struct ospf_if_params *ospf_lookup_if_params (struct interface *, - struct in_addr); -extern struct ospf_if_params *ospf_get_if_params (struct interface *, - struct in_addr); -extern void ospf_del_if_params (struct ospf_if_params *); -extern void ospf_free_if_params (struct interface *, struct in_addr); -extern void ospf_if_update_params (struct interface *, struct in_addr); - -extern int ospf_if_new_hook (struct interface *); -extern void ospf_if_init (void); -extern void ospf_if_stream_set (struct ospf_interface *); -extern void ospf_if_stream_unset (struct ospf_interface *); -extern void ospf_if_reset_variables (struct ospf_interface *); -extern int ospf_if_is_enable (struct ospf_interface *); -extern int ospf_if_get_output_cost (struct ospf_interface *); -extern void ospf_if_recalculate_output_cost (struct interface *); +extern char *ospf_if_name(struct ospf_interface *); +extern struct ospf_interface *ospf_if_new(struct ospf *, struct interface *, + struct prefix *); +extern void ospf_if_cleanup(struct ospf_interface *); +extern void ospf_if_free(struct ospf_interface *); +extern int ospf_if_up(struct ospf_interface *); +extern int ospf_if_down(struct ospf_interface *); + +extern int ospf_if_is_up(struct ospf_interface *); +extern struct ospf_interface *ospf_if_exists(struct ospf_interface *); +extern struct ospf_interface *ospf_if_lookup_by_lsa_pos(struct ospf_area *, + int); +extern struct ospf_interface * +ospf_if_lookup_by_local_addr(struct ospf *, struct interface *, struct in_addr); +extern struct ospf_interface *ospf_if_lookup_by_prefix(struct ospf *, + struct prefix_ipv4 *); +extern struct ospf_interface *ospf_if_table_lookup(struct interface *, + struct prefix *); +extern struct ospf_interface *ospf_if_addr_local(struct in_addr); +extern struct ospf_interface * +ospf_if_lookup_recv_if(struct ospf *, struct in_addr, struct interface *); +extern struct ospf_interface *ospf_if_is_configured(struct ospf *, + struct in_addr *); + +extern struct ospf_if_params *ospf_lookup_if_params(struct interface *, + struct in_addr); +extern struct ospf_if_params *ospf_get_if_params(struct interface *, + struct in_addr); +extern void ospf_del_if_params(struct ospf_if_params *); +extern void ospf_free_if_params(struct interface *, struct in_addr); +extern void ospf_if_update_params(struct interface *, struct in_addr); + +extern int ospf_if_new_hook(struct interface *); +extern void ospf_if_init(void); +extern void ospf_if_stream_set(struct ospf_interface *); +extern void ospf_if_stream_unset(struct ospf_interface *); +extern void ospf_if_reset_variables(struct ospf_interface *); +extern int ospf_if_is_enable(struct ospf_interface *); +extern int ospf_if_get_output_cost(struct ospf_interface *); +extern void ospf_if_recalculate_output_cost(struct interface *); /* Simulate down/up on the interface. */ -extern void ospf_if_reset (struct interface *); - -extern struct ospf_interface *ospf_vl_new (struct ospf *, - struct ospf_vl_data *); -extern struct ospf_vl_data *ospf_vl_data_new (struct ospf_area *, - struct in_addr); -extern struct ospf_vl_data *ospf_vl_lookup (struct ospf *, struct ospf_area *, - struct in_addr); -extern void ospf_vl_data_free (struct ospf_vl_data *); -extern void ospf_vl_add (struct ospf *, struct ospf_vl_data *); -extern void ospf_vl_delete (struct ospf *, struct ospf_vl_data *); -extern void ospf_vl_up_check (struct ospf_area *, struct in_addr, - struct vertex *); -extern void ospf_vl_unapprove (struct ospf *); -extern void ospf_vl_shut_unapproved (struct ospf *); -extern int ospf_full_virtual_nbrs (struct ospf_area *); -extern int ospf_vls_in_area (struct ospf_area *); - -extern struct crypt_key *ospf_crypt_key_lookup (struct list *, u_char); -extern struct crypt_key *ospf_crypt_key_new (void); -extern void ospf_crypt_key_add (struct list *, struct crypt_key *); -extern int ospf_crypt_key_delete (struct list *, u_char); - -extern u_char ospf_default_iftype (struct interface *ifp); +extern void ospf_if_reset(struct interface *); + +extern struct ospf_interface *ospf_vl_new(struct ospf *, struct ospf_vl_data *); +extern struct ospf_vl_data *ospf_vl_data_new(struct ospf_area *, + struct in_addr); +extern struct ospf_vl_data *ospf_vl_lookup(struct ospf *, struct ospf_area *, + struct in_addr); +extern void ospf_vl_data_free(struct ospf_vl_data *); +extern void ospf_vl_add(struct ospf *, struct ospf_vl_data *); +extern void ospf_vl_delete(struct ospf *, struct ospf_vl_data *); +extern void ospf_vl_up_check(struct ospf_area *, struct in_addr, + struct vertex *); +extern void ospf_vl_unapprove(struct ospf *); +extern void ospf_vl_shut_unapproved(struct ospf *); +extern int ospf_full_virtual_nbrs(struct ospf_area *); +extern int ospf_vls_in_area(struct ospf_area *); + +extern struct crypt_key *ospf_crypt_key_lookup(struct list *, u_char); +extern struct crypt_key *ospf_crypt_key_new(void); +extern void ospf_crypt_key_add(struct list *, struct crypt_key *); +extern int ospf_crypt_key_delete(struct list *, u_char); + +extern u_char ospf_default_iftype(struct interface *ifp); /* Set all multicast memberships appropriately based on the type and state of the interface. */ -extern void ospf_if_set_multicast (struct ospf_interface *); +extern void ospf_if_set_multicast(struct ospf_interface *); -DECLARE_HOOK(ospf_vl_add, (struct ospf_vl_data *vd), (vd)) -DECLARE_HOOK(ospf_vl_delete, (struct ospf_vl_data *vd), (vd)) +DECLARE_HOOK(ospf_vl_add, (struct ospf_vl_data * vd), (vd)) +DECLARE_HOOK(ospf_vl_delete, (struct ospf_vl_data * vd), (vd)) #endif /* _ZEBRA_OSPF_INTERFACE_H */ diff --git a/ospfd/ospf_ism.c b/ospfd/ospf_ism.c index b536491d8..f223a870d 100644 --- a/ospfd/ospf_ism.c +++ b/ospfd/ospf_ism.c @@ -1,6 +1,6 @@ /* * OSPF version 2 Interface State Machine - * From RFC2328 [OSPF Version 2] + * From RFC2328 [OSPF Version 2] * Copyright (C) 1999, 2000 Toshiaki Takada * * This file is part of GNU Zebra. @@ -44,578 +44,560 @@ #include "ospfd/ospf_abr.h" DEFINE_HOOK(ospf_ism_change, - (struct ospf_interface *oi, int state, int oldstate), - (oi, state, oldstate)) + (struct ospf_interface * oi, int state, int oldstate), + (oi, state, oldstate)) /* elect DR and BDR. Refer to RFC2319 section 9.4 */ -static struct ospf_neighbor * -ospf_dr_election_sub (struct list *routers) +static struct ospf_neighbor *ospf_dr_election_sub(struct list *routers) { - struct listnode *node; - struct ospf_neighbor *nbr, *max = NULL; - - /* Choose highest router priority. - In case of tie, choose highest Router ID. */ - for (ALL_LIST_ELEMENTS_RO (routers, node, nbr)) - { - if (max == NULL) - max = nbr; - else - { - if (max->priority < nbr->priority) - max = nbr; - else if (max->priority == nbr->priority) - if (IPV4_ADDR_CMP (&max->router_id, &nbr->router_id) < 0) - max = nbr; + struct listnode *node; + struct ospf_neighbor *nbr, *max = NULL; + + /* Choose highest router priority. + In case of tie, choose highest Router ID. */ + for (ALL_LIST_ELEMENTS_RO(routers, node, nbr)) { + if (max == NULL) + max = nbr; + else { + if (max->priority < nbr->priority) + max = nbr; + else if (max->priority == nbr->priority) + if (IPV4_ADDR_CMP(&max->router_id, + &nbr->router_id) + < 0) + max = nbr; + } } - } - return max; + return max; } -static struct ospf_neighbor * -ospf_elect_dr (struct ospf_interface *oi, struct list *el_list) +static struct ospf_neighbor *ospf_elect_dr(struct ospf_interface *oi, + struct list *el_list) { - struct list *dr_list; - struct listnode *node; - struct ospf_neighbor *nbr, *dr = NULL, *bdr = NULL; - - dr_list = list_new (); - - /* Add neighbors to the list. */ - for (ALL_LIST_ELEMENTS_RO (el_list, node, nbr)) - { - /* neighbor declared to be DR. */ - if (NBR_IS_DR (nbr)) - listnode_add (dr_list, nbr); - - /* Preserve neighbor BDR. */ - if (IPV4_ADDR_SAME (&BDR (oi), &nbr->address.u.prefix4)) - bdr = nbr; - } - - /* Elect Designated Router. */ - if (listcount (dr_list) > 0) - dr = ospf_dr_election_sub (dr_list); - else - dr = bdr; - - /* Set DR to interface. */ - if (dr) - DR (oi) = dr->address.u.prefix4; - else - DR (oi).s_addr = 0; - - list_delete (dr_list); - - return dr; + struct list *dr_list; + struct listnode *node; + struct ospf_neighbor *nbr, *dr = NULL, *bdr = NULL; + + dr_list = list_new(); + + /* Add neighbors to the list. */ + for (ALL_LIST_ELEMENTS_RO(el_list, node, nbr)) { + /* neighbor declared to be DR. */ + if (NBR_IS_DR(nbr)) + listnode_add(dr_list, nbr); + + /* Preserve neighbor BDR. */ + if (IPV4_ADDR_SAME(&BDR(oi), &nbr->address.u.prefix4)) + bdr = nbr; + } + + /* Elect Designated Router. */ + if (listcount(dr_list) > 0) + dr = ospf_dr_election_sub(dr_list); + else + dr = bdr; + + /* Set DR to interface. */ + if (dr) + DR(oi) = dr->address.u.prefix4; + else + DR(oi).s_addr = 0; + + list_delete(dr_list); + + return dr; } -static struct ospf_neighbor * -ospf_elect_bdr (struct ospf_interface *oi, struct list *el_list) +static struct ospf_neighbor *ospf_elect_bdr(struct ospf_interface *oi, + struct list *el_list) { - struct list *bdr_list, *no_dr_list; - struct listnode *node; - struct ospf_neighbor *nbr, *bdr = NULL; - - bdr_list = list_new (); - no_dr_list = list_new (); - - /* Add neighbors to the list. */ - for (ALL_LIST_ELEMENTS_RO (el_list, node, nbr)) - { - /* neighbor declared to be DR. */ - if (NBR_IS_DR (nbr)) - continue; - - /* neighbor declared to be BDR. */ - if (NBR_IS_BDR (nbr)) - listnode_add (bdr_list, nbr); - - listnode_add (no_dr_list, nbr); - } - - /* Elect Backup Designated Router. */ - if (listcount (bdr_list) > 0) - bdr = ospf_dr_election_sub (bdr_list); - else - bdr = ospf_dr_election_sub (no_dr_list); - - /* Set BDR to interface. */ - if (bdr) - BDR (oi) = bdr->address.u.prefix4; - else - BDR (oi).s_addr = 0; - - list_delete (bdr_list); - list_delete (no_dr_list); - - return bdr; + struct list *bdr_list, *no_dr_list; + struct listnode *node; + struct ospf_neighbor *nbr, *bdr = NULL; + + bdr_list = list_new(); + no_dr_list = list_new(); + + /* Add neighbors to the list. */ + for (ALL_LIST_ELEMENTS_RO(el_list, node, nbr)) { + /* neighbor declared to be DR. */ + if (NBR_IS_DR(nbr)) + continue; + + /* neighbor declared to be BDR. */ + if (NBR_IS_BDR(nbr)) + listnode_add(bdr_list, nbr); + + listnode_add(no_dr_list, nbr); + } + + /* Elect Backup Designated Router. */ + if (listcount(bdr_list) > 0) + bdr = ospf_dr_election_sub(bdr_list); + else + bdr = ospf_dr_election_sub(no_dr_list); + + /* Set BDR to interface. */ + if (bdr) + BDR(oi) = bdr->address.u.prefix4; + else + BDR(oi).s_addr = 0; + + list_delete(bdr_list); + list_delete(no_dr_list); + + return bdr; } -static int -ospf_ism_state (struct ospf_interface *oi) +static int ospf_ism_state(struct ospf_interface *oi) { - if (IPV4_ADDR_SAME (&DR (oi), &oi->address->u.prefix4)) - return ISM_DR; - else if (IPV4_ADDR_SAME (&BDR (oi), &oi->address->u.prefix4)) - return ISM_Backup; - else - return ISM_DROther; + if (IPV4_ADDR_SAME(&DR(oi), &oi->address->u.prefix4)) + return ISM_DR; + else if (IPV4_ADDR_SAME(&BDR(oi), &oi->address->u.prefix4)) + return ISM_Backup; + else + return ISM_DROther; } -static void -ospf_dr_eligible_routers (struct route_table *nbrs, struct list *el_list) +static void ospf_dr_eligible_routers(struct route_table *nbrs, + struct list *el_list) { - struct route_node *rn; - struct ospf_neighbor *nbr; - - for (rn = route_top (nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - /* Ignore 0.0.0.0 node*/ - if (nbr->router_id.s_addr != 0) - /* Is neighbor eligible? */ - if (nbr->priority > 0) - /* Is neighbor upper 2-Way? */ - if (nbr->state >= NSM_TwoWay) - listnode_add (el_list, nbr); + struct route_node *rn; + struct ospf_neighbor *nbr; + + for (rn = route_top(nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info) != NULL) + /* Ignore 0.0.0.0 node*/ + if (nbr->router_id.s_addr != 0) + /* Is neighbor eligible? */ + if (nbr->priority > 0) + /* Is neighbor upper 2-Way? */ + if (nbr->state >= NSM_TwoWay) + listnode_add(el_list, nbr); } /* Generate AdjOK? NSM event. */ -static void -ospf_dr_change (struct ospf *ospf, struct route_table *nbrs) +static void ospf_dr_change(struct ospf *ospf, struct route_table *nbrs) { - struct route_node *rn; - struct ospf_neighbor *nbr; - - for (rn = route_top (nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - /* Ignore 0.0.0.0 node*/ - if (nbr->router_id.s_addr != 0) - /* Is neighbor upper 2-Way? */ - if (nbr->state >= NSM_TwoWay) - /* Ignore myself. */ - if (!IPV4_ADDR_SAME (&nbr->router_id, &ospf->router_id)) - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_AdjOK); + struct route_node *rn; + struct ospf_neighbor *nbr; + + for (rn = route_top(nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info) != NULL) + /* Ignore 0.0.0.0 node*/ + if (nbr->router_id.s_addr != 0) + /* Is neighbor upper 2-Way? */ + if (nbr->state >= NSM_TwoWay) + /* Ignore myself. */ + if (!IPV4_ADDR_SAME(&nbr->router_id, + &ospf->router_id)) + OSPF_NSM_EVENT_SCHEDULE( + nbr, NSM_AdjOK); } -static int -ospf_dr_election (struct ospf_interface *oi) +static int ospf_dr_election(struct ospf_interface *oi) { - struct in_addr old_dr, old_bdr; - int old_state, new_state; - struct list *el_list; + struct in_addr old_dr, old_bdr; + int old_state, new_state; + struct list *el_list; - /* backup current values. */ - old_dr = DR (oi); - old_bdr = BDR (oi); - old_state = oi->state; + /* backup current values. */ + old_dr = DR(oi); + old_bdr = BDR(oi); + old_state = oi->state; - el_list = list_new (); + el_list = list_new(); - /* List eligible routers. */ - ospf_dr_eligible_routers (oi->nbrs, el_list); + /* List eligible routers. */ + ospf_dr_eligible_routers(oi->nbrs, el_list); - /* First election of DR and BDR. */ - ospf_elect_bdr (oi, el_list); - ospf_elect_dr (oi, el_list); + /* First election of DR and BDR. */ + ospf_elect_bdr(oi, el_list); + ospf_elect_dr(oi, el_list); - new_state = ospf_ism_state (oi); + new_state = ospf_ism_state(oi); - zlog_debug ("DR-Election[1st]: Backup %s", inet_ntoa (BDR (oi))); - zlog_debug ("DR-Election[1st]: DR %s", inet_ntoa (DR (oi))); + zlog_debug("DR-Election[1st]: Backup %s", inet_ntoa(BDR(oi))); + zlog_debug("DR-Election[1st]: DR %s", inet_ntoa(DR(oi))); - if (new_state != old_state && - !(new_state == ISM_DROther && old_state < ISM_DROther)) - { - ospf_elect_bdr (oi, el_list); - ospf_elect_dr (oi, el_list); + if (new_state != old_state + && !(new_state == ISM_DROther && old_state < ISM_DROther)) { + ospf_elect_bdr(oi, el_list); + ospf_elect_dr(oi, el_list); - new_state = ospf_ism_state (oi); + new_state = ospf_ism_state(oi); - zlog_debug ("DR-Election[2nd]: Backup %s", inet_ntoa (BDR (oi))); - zlog_debug ("DR-Election[2nd]: DR %s", inet_ntoa (DR (oi))); - } + zlog_debug("DR-Election[2nd]: Backup %s", inet_ntoa(BDR(oi))); + zlog_debug("DR-Election[2nd]: DR %s", inet_ntoa(DR(oi))); + } - list_delete (el_list); + list_delete(el_list); - /* if DR or BDR changes, cause AdjOK? neighbor event. */ - if (!IPV4_ADDR_SAME (&old_dr, &DR (oi)) || - !IPV4_ADDR_SAME (&old_bdr, &BDR (oi))) - ospf_dr_change (oi->ospf, oi->nbrs); + /* if DR or BDR changes, cause AdjOK? neighbor event. */ + if (!IPV4_ADDR_SAME(&old_dr, &DR(oi)) + || !IPV4_ADDR_SAME(&old_bdr, &BDR(oi))) + ospf_dr_change(oi->ospf, oi->nbrs); - return new_state; + return new_state; } -int -ospf_hello_timer (struct thread *thread) +int ospf_hello_timer(struct thread *thread) { - struct ospf_interface *oi; + struct ospf_interface *oi; - oi = THREAD_ARG (thread); - oi->t_hello = NULL; + oi = THREAD_ARG(thread); + oi->t_hello = NULL; - if (IS_DEBUG_OSPF (ism, ISM_TIMERS)) - zlog_debug("ISM[%s]: Timer (Hello timer expire)", IF_NAME(oi)); + if (IS_DEBUG_OSPF(ism, ISM_TIMERS)) + zlog_debug("ISM[%s]: Timer (Hello timer expire)", IF_NAME(oi)); - /* Sending hello packet. */ - ospf_hello_send (oi); + /* Sending hello packet. */ + ospf_hello_send(oi); - /* Hello timer set. */ - OSPF_HELLO_TIMER_ON (oi); - - return 0; + /* Hello timer set. */ + OSPF_HELLO_TIMER_ON(oi); + + return 0; } -static int -ospf_wait_timer (struct thread *thread) +static int ospf_wait_timer(struct thread *thread) { - struct ospf_interface *oi; + struct ospf_interface *oi; - oi = THREAD_ARG (thread); - oi->t_wait = NULL; + oi = THREAD_ARG(thread); + oi->t_wait = NULL; - if (IS_DEBUG_OSPF (ism, ISM_TIMERS)) - zlog_debug("ISM[%s]: Timer (Wait timer expire)", IF_NAME(oi)); + if (IS_DEBUG_OSPF(ism, ISM_TIMERS)) + zlog_debug("ISM[%s]: Timer (Wait timer expire)", IF_NAME(oi)); - OSPF_ISM_EVENT_SCHEDULE (oi, ISM_WaitTimer); + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_WaitTimer); - return 0; + return 0; } /* Hook function called after ospf ISM event is occured. And vty's network command invoke this function after making interface structure. */ -static void -ism_timer_set (struct ospf_interface *oi) +static void ism_timer_set(struct ospf_interface *oi) { - switch (oi->state) - { - case ISM_Down: - /* First entry point of ospf interface state machine. In this state - interface parameters must be set to initial values, and timers are - reset also. */ - OSPF_ISM_TIMER_OFF (oi->t_hello); - OSPF_ISM_TIMER_OFF (oi->t_wait); - OSPF_ISM_TIMER_OFF (oi->t_ls_ack); - break; - case ISM_Loopback: - /* In this state, the interface may be looped back and will be - unavailable for regular data traffic. */ - OSPF_ISM_TIMER_OFF (oi->t_hello); - OSPF_ISM_TIMER_OFF (oi->t_wait); - OSPF_ISM_TIMER_OFF (oi->t_ls_ack); - break; - case ISM_Waiting: - /* The router is trying to determine the identity of DRouter and - BDRouter. The router begin to receive and send Hello Packets. */ - /* send first hello immediately */ - OSPF_ISM_TIMER_MSEC_ON (oi->t_hello, ospf_hello_timer, 1); - OSPF_ISM_TIMER_ON (oi->t_wait, ospf_wait_timer, - OSPF_IF_PARAM (oi, v_wait)); - OSPF_ISM_TIMER_OFF (oi->t_ls_ack); - break; - case ISM_PointToPoint: - /* The interface connects to a physical Point-to-point network or - virtual link. The router attempts to form an adjacency with - neighboring router. Hello packets are also sent. */ - /* send first hello immediately */ - OSPF_ISM_TIMER_MSEC_ON (oi->t_hello, ospf_hello_timer, 1); - OSPF_ISM_TIMER_OFF (oi->t_wait); - OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack); - break; - case ISM_DROther: - /* The network type of the interface is broadcast or NBMA network, - and the router itself is neither Designated Router nor - Backup Designated Router. */ - OSPF_HELLO_TIMER_ON (oi); - OSPF_ISM_TIMER_OFF (oi->t_wait); - OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack); - break; - case ISM_Backup: - /* The network type of the interface is broadcast os NBMA network, - and the router is Backup Designated Router. */ - OSPF_HELLO_TIMER_ON (oi); - OSPF_ISM_TIMER_OFF (oi->t_wait); - OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack); - break; - case ISM_DR: - /* The network type of the interface is broadcast or NBMA network, - and the router is Designated Router. */ - OSPF_HELLO_TIMER_ON (oi); - OSPF_ISM_TIMER_OFF (oi->t_wait); - OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack); - break; - } + switch (oi->state) { + case ISM_Down: + /* First entry point of ospf interface state machine. In this + state + interface parameters must be set to initial values, and + timers are + reset also. */ + OSPF_ISM_TIMER_OFF(oi->t_hello); + OSPF_ISM_TIMER_OFF(oi->t_wait); + OSPF_ISM_TIMER_OFF(oi->t_ls_ack); + break; + case ISM_Loopback: + /* In this state, the interface may be looped back and will be + unavailable for regular data traffic. */ + OSPF_ISM_TIMER_OFF(oi->t_hello); + OSPF_ISM_TIMER_OFF(oi->t_wait); + OSPF_ISM_TIMER_OFF(oi->t_ls_ack); + break; + case ISM_Waiting: + /* The router is trying to determine the identity of DRouter and + BDRouter. The router begin to receive and send Hello Packets. + */ + /* send first hello immediately */ + OSPF_ISM_TIMER_MSEC_ON(oi->t_hello, ospf_hello_timer, 1); + OSPF_ISM_TIMER_ON(oi->t_wait, ospf_wait_timer, + OSPF_IF_PARAM(oi, v_wait)); + OSPF_ISM_TIMER_OFF(oi->t_ls_ack); + break; + case ISM_PointToPoint: + /* The interface connects to a physical Point-to-point network + or + virtual link. The router attempts to form an adjacency with + neighboring router. Hello packets are also sent. */ + /* send first hello immediately */ + OSPF_ISM_TIMER_MSEC_ON(oi->t_hello, ospf_hello_timer, 1); + OSPF_ISM_TIMER_OFF(oi->t_wait); + OSPF_ISM_TIMER_ON(oi->t_ls_ack, ospf_ls_ack_timer, + oi->v_ls_ack); + break; + case ISM_DROther: + /* The network type of the interface is broadcast or NBMA + network, + and the router itself is neither Designated Router nor + Backup Designated Router. */ + OSPF_HELLO_TIMER_ON(oi); + OSPF_ISM_TIMER_OFF(oi->t_wait); + OSPF_ISM_TIMER_ON(oi->t_ls_ack, ospf_ls_ack_timer, + oi->v_ls_ack); + break; + case ISM_Backup: + /* The network type of the interface is broadcast os NBMA + network, + and the router is Backup Designated Router. */ + OSPF_HELLO_TIMER_ON(oi); + OSPF_ISM_TIMER_OFF(oi->t_wait); + OSPF_ISM_TIMER_ON(oi->t_ls_ack, ospf_ls_ack_timer, + oi->v_ls_ack); + break; + case ISM_DR: + /* The network type of the interface is broadcast or NBMA + network, + and the router is Designated Router. */ + OSPF_HELLO_TIMER_ON(oi); + OSPF_ISM_TIMER_OFF(oi->t_wait); + OSPF_ISM_TIMER_ON(oi->t_ls_ack, ospf_ls_ack_timer, + oi->v_ls_ack); + break; + } } -static int -ism_interface_up (struct ospf_interface *oi) +static int ism_interface_up(struct ospf_interface *oi) { - int next_state = 0; - - /* if network type is point-to-point, Point-to-MultiPoint or virtual link, - the state transitions to Point-to-Point. */ - if (oi->type == OSPF_IFTYPE_POINTOPOINT || - oi->type == OSPF_IFTYPE_POINTOMULTIPOINT || - oi->type == OSPF_IFTYPE_VIRTUALLINK) - next_state = ISM_PointToPoint; - /* Else if the router is not eligible to DR, the state transitions to - DROther. */ - else if (PRIORITY (oi) == 0) /* router is eligible? */ - next_state = ISM_DROther; - else - /* Otherwise, the state transitions to Waiting. */ - next_state = ISM_Waiting; - - if (oi->type == OSPF_IFTYPE_NBMA) - ospf_nbr_nbma_if_update (oi->ospf, oi); - - /* ospf_ism_event (t); */ - return next_state; + int next_state = 0; + + /* if network type is point-to-point, Point-to-MultiPoint or virtual + link, + the state transitions to Point-to-Point. */ + if (oi->type == OSPF_IFTYPE_POINTOPOINT + || oi->type == OSPF_IFTYPE_POINTOMULTIPOINT + || oi->type == OSPF_IFTYPE_VIRTUALLINK) + next_state = ISM_PointToPoint; + /* Else if the router is not eligible to DR, the state transitions to + DROther. */ + else if (PRIORITY(oi) == 0) /* router is eligible? */ + next_state = ISM_DROther; + else + /* Otherwise, the state transitions to Waiting. */ + next_state = ISM_Waiting; + + if (oi->type == OSPF_IFTYPE_NBMA) + ospf_nbr_nbma_if_update(oi->ospf, oi); + + /* ospf_ism_event (t); */ + return next_state; } -static int -ism_loop_ind (struct ospf_interface *oi) +static int ism_loop_ind(struct ospf_interface *oi) { - int ret = 0; + int ret = 0; - /* call ism_interface_down. */ - /* ret = ism_interface_down (oi); */ + /* call ism_interface_down. */ + /* ret = ism_interface_down (oi); */ - return ret; + return ret; } /* Interface down event handler. */ -static int -ism_interface_down (struct ospf_interface *oi) +static int ism_interface_down(struct ospf_interface *oi) { - ospf_if_cleanup (oi); - return 0; + ospf_if_cleanup(oi); + return 0; } -static int -ism_backup_seen (struct ospf_interface *oi) +static int ism_backup_seen(struct ospf_interface *oi) { - return ospf_dr_election (oi); + return ospf_dr_election(oi); } -static int -ism_wait_timer (struct ospf_interface *oi) +static int ism_wait_timer(struct ospf_interface *oi) { - return ospf_dr_election (oi); + return ospf_dr_election(oi); } -static int -ism_neighbor_change (struct ospf_interface *oi) +static int ism_neighbor_change(struct ospf_interface *oi) { - return ospf_dr_election (oi); + return ospf_dr_election(oi); } -static int -ism_ignore (struct ospf_interface *oi) +static int ism_ignore(struct ospf_interface *oi) { - if (IS_DEBUG_OSPF (ism, ISM_EVENTS)) - zlog_debug("ISM[%s]: ism_ignore called", IF_NAME(oi)); + if (IS_DEBUG_OSPF(ism, ISM_EVENTS)) + zlog_debug("ISM[%s]: ism_ignore called", IF_NAME(oi)); - return 0; + return 0; } /* Interface State Machine */ struct { - int (*func) (struct ospf_interface *); - int next_state; -} ISM [OSPF_ISM_STATE_MAX][OSPF_ISM_EVENT_MAX] = -{ - { - /* DependUpon: dummy state. */ - { ism_ignore, ISM_DependUpon }, /* NoEvent */ - { ism_ignore, ISM_DependUpon }, /* InterfaceUp */ - { ism_ignore, ISM_DependUpon }, /* WaitTimer */ - { ism_ignore, ISM_DependUpon }, /* BackupSeen */ - { ism_ignore, ISM_DependUpon }, /* NeighborChange */ - { ism_ignore, ISM_DependUpon }, /* LoopInd */ - { ism_ignore, ISM_DependUpon }, /* UnloopInd */ - { ism_ignore, ISM_DependUpon }, /* InterfaceDown */ - }, - { - /* Down:*/ - { ism_ignore, ISM_DependUpon }, /* NoEvent */ - { ism_interface_up, ISM_DependUpon }, /* InterfaceUp */ - { ism_ignore, ISM_Down }, /* WaitTimer */ - { ism_ignore, ISM_Down }, /* BackupSeen */ - { ism_ignore, ISM_Down }, /* NeighborChange */ - { ism_loop_ind, ISM_Loopback }, /* LoopInd */ - { ism_ignore, ISM_Down }, /* UnloopInd */ - { ism_interface_down, ISM_Down }, /* InterfaceDown */ - }, - { - /* Loopback: */ - { ism_ignore, ISM_DependUpon }, /* NoEvent */ - { ism_ignore, ISM_Loopback }, /* InterfaceUp */ - { ism_ignore, ISM_Loopback }, /* WaitTimer */ - { ism_ignore, ISM_Loopback }, /* BackupSeen */ - { ism_ignore, ISM_Loopback }, /* NeighborChange */ - { ism_ignore, ISM_Loopback }, /* LoopInd */ - { ism_ignore, ISM_Down }, /* UnloopInd */ - { ism_interface_down, ISM_Down }, /* InterfaceDown */ - }, - { - /* Waiting: */ - { ism_ignore, ISM_DependUpon }, /* NoEvent */ - { ism_ignore, ISM_Waiting }, /* InterfaceUp */ - { ism_wait_timer, ISM_DependUpon }, /* WaitTimer */ - { ism_backup_seen, ISM_DependUpon }, /* BackupSeen */ - { ism_ignore, ISM_Waiting }, /* NeighborChange */ - { ism_loop_ind, ISM_Loopback }, /* LoopInd */ - { ism_ignore, ISM_Waiting }, /* UnloopInd */ - { ism_interface_down, ISM_Down }, /* InterfaceDown */ - }, - { - /* Point-to-Point: */ - { ism_ignore, ISM_DependUpon }, /* NoEvent */ - { ism_ignore, ISM_PointToPoint }, /* InterfaceUp */ - { ism_ignore, ISM_PointToPoint }, /* WaitTimer */ - { ism_ignore, ISM_PointToPoint }, /* BackupSeen */ - { ism_ignore, ISM_PointToPoint }, /* NeighborChange */ - { ism_loop_ind, ISM_Loopback }, /* LoopInd */ - { ism_ignore, ISM_PointToPoint }, /* UnloopInd */ - { ism_interface_down, ISM_Down }, /* InterfaceDown */ - }, - { - /* DROther: */ - { ism_ignore, ISM_DependUpon }, /* NoEvent */ - { ism_ignore, ISM_DROther }, /* InterfaceUp */ - { ism_ignore, ISM_DROther }, /* WaitTimer */ - { ism_ignore, ISM_DROther }, /* BackupSeen */ - { ism_neighbor_change, ISM_DependUpon }, /* NeighborChange */ - { ism_loop_ind, ISM_Loopback }, /* LoopInd */ - { ism_ignore, ISM_DROther }, /* UnloopInd */ - { ism_interface_down, ISM_Down }, /* InterfaceDown */ - }, - { - /* Backup: */ - { ism_ignore, ISM_DependUpon }, /* NoEvent */ - { ism_ignore, ISM_Backup }, /* InterfaceUp */ - { ism_ignore, ISM_Backup }, /* WaitTimer */ - { ism_ignore, ISM_Backup }, /* BackupSeen */ - { ism_neighbor_change, ISM_DependUpon }, /* NeighborChange */ - { ism_loop_ind, ISM_Loopback }, /* LoopInd */ - { ism_ignore, ISM_Backup }, /* UnloopInd */ - { ism_interface_down, ISM_Down }, /* InterfaceDown */ - }, - { - /* DR: */ - { ism_ignore, ISM_DependUpon }, /* NoEvent */ - { ism_ignore, ISM_DR }, /* InterfaceUp */ - { ism_ignore, ISM_DR }, /* WaitTimer */ - { ism_ignore, ISM_DR }, /* BackupSeen */ - { ism_neighbor_change, ISM_DependUpon }, /* NeighborChange */ - { ism_loop_ind, ISM_Loopback }, /* LoopInd */ - { ism_ignore, ISM_DR }, /* UnloopInd */ - { ism_interface_down, ISM_Down }, /* InterfaceDown */ - }, -}; - -static const char *ospf_ism_event_str[] = -{ - "NoEvent", - "InterfaceUp", - "WaitTimer", - "BackupSeen", - "NeighborChange", - "LoopInd", - "UnLoopInd", - "InterfaceDown", + int (*func)(struct ospf_interface *); + int next_state; +} ISM[OSPF_ISM_STATE_MAX][OSPF_ISM_EVENT_MAX] = { + { + /* DependUpon: dummy state. */ + {ism_ignore, ISM_DependUpon}, /* NoEvent */ + {ism_ignore, ISM_DependUpon}, /* InterfaceUp */ + {ism_ignore, ISM_DependUpon}, /* WaitTimer */ + {ism_ignore, ISM_DependUpon}, /* BackupSeen */ + {ism_ignore, ISM_DependUpon}, /* NeighborChange */ + {ism_ignore, ISM_DependUpon}, /* LoopInd */ + {ism_ignore, ISM_DependUpon}, /* UnloopInd */ + {ism_ignore, ISM_DependUpon}, /* InterfaceDown */ + }, + { + /* Down:*/ + {ism_ignore, ISM_DependUpon}, /* NoEvent */ + {ism_interface_up, ISM_DependUpon}, /* InterfaceUp */ + {ism_ignore, ISM_Down}, /* WaitTimer */ + {ism_ignore, ISM_Down}, /* BackupSeen */ + {ism_ignore, ISM_Down}, /* NeighborChange */ + {ism_loop_ind, ISM_Loopback}, /* LoopInd */ + {ism_ignore, ISM_Down}, /* UnloopInd */ + {ism_interface_down, ISM_Down}, /* InterfaceDown */ + }, + { + /* Loopback: */ + {ism_ignore, ISM_DependUpon}, /* NoEvent */ + {ism_ignore, ISM_Loopback}, /* InterfaceUp */ + {ism_ignore, ISM_Loopback}, /* WaitTimer */ + {ism_ignore, ISM_Loopback}, /* BackupSeen */ + {ism_ignore, ISM_Loopback}, /* NeighborChange */ + {ism_ignore, ISM_Loopback}, /* LoopInd */ + {ism_ignore, ISM_Down}, /* UnloopInd */ + {ism_interface_down, ISM_Down}, /* InterfaceDown */ + }, + { + /* Waiting: */ + {ism_ignore, ISM_DependUpon}, /* NoEvent */ + {ism_ignore, ISM_Waiting}, /* InterfaceUp */ + {ism_wait_timer, ISM_DependUpon}, /* WaitTimer */ + {ism_backup_seen, ISM_DependUpon}, /* BackupSeen */ + {ism_ignore, ISM_Waiting}, /* NeighborChange */ + {ism_loop_ind, ISM_Loopback}, /* LoopInd */ + {ism_ignore, ISM_Waiting}, /* UnloopInd */ + {ism_interface_down, ISM_Down}, /* InterfaceDown */ + }, + { + /* Point-to-Point: */ + {ism_ignore, ISM_DependUpon}, /* NoEvent */ + {ism_ignore, ISM_PointToPoint}, /* InterfaceUp */ + {ism_ignore, ISM_PointToPoint}, /* WaitTimer */ + {ism_ignore, ISM_PointToPoint}, /* BackupSeen */ + {ism_ignore, ISM_PointToPoint}, /* NeighborChange */ + {ism_loop_ind, ISM_Loopback}, /* LoopInd */ + {ism_ignore, ISM_PointToPoint}, /* UnloopInd */ + {ism_interface_down, ISM_Down}, /* InterfaceDown */ + }, + { + /* DROther: */ + {ism_ignore, ISM_DependUpon}, /* NoEvent */ + {ism_ignore, ISM_DROther}, /* InterfaceUp */ + {ism_ignore, ISM_DROther}, /* WaitTimer */ + {ism_ignore, ISM_DROther}, /* BackupSeen */ + {ism_neighbor_change, ISM_DependUpon}, /* NeighborChange */ + {ism_loop_ind, ISM_Loopback}, /* LoopInd */ + {ism_ignore, ISM_DROther}, /* UnloopInd */ + {ism_interface_down, ISM_Down}, /* InterfaceDown */ + }, + { + /* Backup: */ + {ism_ignore, ISM_DependUpon}, /* NoEvent */ + {ism_ignore, ISM_Backup}, /* InterfaceUp */ + {ism_ignore, ISM_Backup}, /* WaitTimer */ + {ism_ignore, ISM_Backup}, /* BackupSeen */ + {ism_neighbor_change, ISM_DependUpon}, /* NeighborChange */ + {ism_loop_ind, ISM_Loopback}, /* LoopInd */ + {ism_ignore, ISM_Backup}, /* UnloopInd */ + {ism_interface_down, ISM_Down}, /* InterfaceDown */ + }, + { + /* DR: */ + {ism_ignore, ISM_DependUpon}, /* NoEvent */ + {ism_ignore, ISM_DR}, /* InterfaceUp */ + {ism_ignore, ISM_DR}, /* WaitTimer */ + {ism_ignore, ISM_DR}, /* BackupSeen */ + {ism_neighbor_change, ISM_DependUpon}, /* NeighborChange */ + {ism_loop_ind, ISM_Loopback}, /* LoopInd */ + {ism_ignore, ISM_DR}, /* UnloopInd */ + {ism_interface_down, ISM_Down}, /* InterfaceDown */ + }, +}; + +static const char *ospf_ism_event_str[] = { + "NoEvent", "InterfaceUp", "WaitTimer", "BackupSeen", + "NeighborChange", "LoopInd", "UnLoopInd", "InterfaceDown", }; -static void -ism_change_state (struct ospf_interface *oi, int state) +static void ism_change_state(struct ospf_interface *oi, int state) { - int old_state; - struct ospf_lsa *lsa; - - /* Logging change of state. */ - if (IS_DEBUG_OSPF (ism, ISM_STATUS)) - zlog_debug("ISM[%s]: State change %s -> %s", IF_NAME(oi), - lookup_msg(ospf_ism_state_msg, oi->state, NULL), - lookup_msg(ospf_ism_state_msg, state, NULL)); - - old_state = oi->state; - oi->state = state; - oi->state_change++; - - hook_call(ospf_ism_change, oi, state, old_state); - - /* Set multicast memberships appropriately for new state. */ - ospf_if_set_multicast(oi); - - if (old_state == ISM_Down || state == ISM_Down) - ospf_check_abr_status (oi->ospf); - - /* Originate router-LSA. */ - if (state == ISM_Down) - { - if (oi->area->act_ints > 0) - oi->area->act_ints--; - } - else if (old_state == ISM_Down) - oi->area->act_ints++; - - /* schedule router-LSA originate. */ - ospf_router_lsa_update_area (oi->area); - - /* Originate network-LSA. */ - if (old_state != ISM_DR && state == ISM_DR) - ospf_network_lsa_update (oi); - else if (old_state == ISM_DR && state != ISM_DR) - { - /* Free self originated network LSA. */ - lsa = oi->network_lsa_self; - if (lsa) - ospf_lsa_flush_area (lsa, oi->area); - - ospf_lsa_unlock (&oi->network_lsa_self); - oi->network_lsa_self = NULL; - } - - ospf_opaque_ism_change (oi, old_state); - - /* Check area border status. */ - ospf_check_abr_status (oi->ospf); + int old_state; + struct ospf_lsa *lsa; + + /* Logging change of state. */ + if (IS_DEBUG_OSPF(ism, ISM_STATUS)) + zlog_debug("ISM[%s]: State change %s -> %s", IF_NAME(oi), + lookup_msg(ospf_ism_state_msg, oi->state, NULL), + lookup_msg(ospf_ism_state_msg, state, NULL)); + + old_state = oi->state; + oi->state = state; + oi->state_change++; + + hook_call(ospf_ism_change, oi, state, old_state); + + /* Set multicast memberships appropriately for new state. */ + ospf_if_set_multicast(oi); + + if (old_state == ISM_Down || state == ISM_Down) + ospf_check_abr_status(oi->ospf); + + /* Originate router-LSA. */ + if (state == ISM_Down) { + if (oi->area->act_ints > 0) + oi->area->act_ints--; + } else if (old_state == ISM_Down) + oi->area->act_ints++; + + /* schedule router-LSA originate. */ + ospf_router_lsa_update_area(oi->area); + + /* Originate network-LSA. */ + if (old_state != ISM_DR && state == ISM_DR) + ospf_network_lsa_update(oi); + else if (old_state == ISM_DR && state != ISM_DR) { + /* Free self originated network LSA. */ + lsa = oi->network_lsa_self; + if (lsa) + ospf_lsa_flush_area(lsa, oi->area); + + ospf_lsa_unlock(&oi->network_lsa_self); + oi->network_lsa_self = NULL; + } + + ospf_opaque_ism_change(oi, old_state); + + /* Check area border status. */ + ospf_check_abr_status(oi->ospf); } /* Execute ISM event process. */ -int -ospf_ism_event (struct thread *thread) +int ospf_ism_event(struct thread *thread) { - int event; - int next_state; - struct ospf_interface *oi; + int event; + int next_state; + struct ospf_interface *oi; - oi = THREAD_ARG (thread); - event = THREAD_VAL (thread); + oi = THREAD_ARG(thread); + event = THREAD_VAL(thread); - /* Call function. */ - next_state = (*(ISM [oi->state][event].func))(oi); + /* Call function. */ + next_state = (*(ISM[oi->state][event].func))(oi); - if (! next_state) - next_state = ISM [oi->state][event].next_state; + if (!next_state) + next_state = ISM[oi->state][event].next_state; - if (IS_DEBUG_OSPF (ism, ISM_EVENTS)) - zlog_debug("ISM[%s]: %s (%s)", IF_NAME(oi), - lookup_msg(ospf_ism_state_msg, oi->state, NULL), - ospf_ism_event_str[event]); + if (IS_DEBUG_OSPF(ism, ISM_EVENTS)) + zlog_debug("ISM[%s]: %s (%s)", IF_NAME(oi), + lookup_msg(ospf_ism_state_msg, oi->state, NULL), + ospf_ism_event_str[event]); - /* If state is changed. */ - if (next_state != oi->state) - ism_change_state (oi, next_state); + /* If state is changed. */ + if (next_state != oi->state) + ism_change_state(oi, next_state); - /* Make sure timer is set. */ - ism_timer_set (oi); + /* Make sure timer is set. */ + ism_timer_set(oi); - return 0; + return 0; } - diff --git a/ospfd/ospf_ism.h b/ospfd/ospf_ism.h index f099fe875..5ae99ab32 100644 --- a/ospfd/ospf_ism.h +++ b/ospfd/ospf_ism.h @@ -47,62 +47,60 @@ #define ISM_InterfaceDown 7 #define OSPF_ISM_EVENT_MAX 8 -#define OSPF_ISM_WRITE_ON(O) \ - do \ - { \ - if (oi->on_write_q == 0) \ - { \ - listnode_add ((O)->oi_write_q, oi); \ - oi->on_write_q = 1; \ - } \ - thread_add_write (master, ospf_write, (O), (O)->fd, &(O)->t_write); \ - } while (0) - +#define OSPF_ISM_WRITE_ON(O) \ + do { \ + if (oi->on_write_q == 0) { \ + listnode_add((O)->oi_write_q, oi); \ + oi->on_write_q = 1; \ + } \ + thread_add_write(master, ospf_write, (O), (O)->fd, \ + &(O)->t_write); \ + } while (0) + /* Macro for OSPF ISM timer turn on. */ -#define OSPF_ISM_TIMER_ON(T,F,V) \ - thread_add_timer (master, (F), oi, (V), &(T)) +#define OSPF_ISM_TIMER_ON(T, F, V) thread_add_timer(master, (F), oi, (V), &(T)) -#define OSPF_ISM_TIMER_MSEC_ON(T,F,V) \ - thread_add_timer_msec (master, (F), oi, (V), &(T)) +#define OSPF_ISM_TIMER_MSEC_ON(T, F, V) \ + thread_add_timer_msec(master, (F), oi, (V), &(T)) /* convenience macro to set hello timer correctly, according to * whether fast-hello is set or not */ -#define OSPF_HELLO_TIMER_ON(O) \ - do { \ - if (OSPF_IF_PARAM ((O), fast_hello)) \ - OSPF_ISM_TIMER_MSEC_ON ((O)->t_hello, ospf_hello_timer, \ - 1000 / OSPF_IF_PARAM ((O), fast_hello)); \ - else \ - OSPF_ISM_TIMER_ON ((O)->t_hello, ospf_hello_timer, \ - OSPF_IF_PARAM ((O), v_hello)); \ - } while (0) +#define OSPF_HELLO_TIMER_ON(O) \ + do { \ + if (OSPF_IF_PARAM((O), fast_hello)) \ + OSPF_ISM_TIMER_MSEC_ON( \ + (O)->t_hello, ospf_hello_timer, \ + 1000 / OSPF_IF_PARAM((O), fast_hello)); \ + else \ + OSPF_ISM_TIMER_ON((O)->t_hello, ospf_hello_timer, \ + OSPF_IF_PARAM((O), v_hello)); \ + } while (0) /* Macro for OSPF ISM timer turn off. */ -#define OSPF_ISM_TIMER_OFF(X) \ - do { \ - if (X) \ - { \ - thread_cancel (X); \ - (X) = NULL; \ - } \ - } while (0) +#define OSPF_ISM_TIMER_OFF(X) \ + do { \ + if (X) { \ + thread_cancel(X); \ + (X) = NULL; \ + } \ + } while (0) /* Macro for OSPF schedule event. */ -#define OSPF_ISM_EVENT_SCHEDULE(I,E) \ - thread_add_event (master, ospf_ism_event, (I), (E), NULL) +#define OSPF_ISM_EVENT_SCHEDULE(I, E) \ + thread_add_event(master, ospf_ism_event, (I), (E), NULL) /* Macro for OSPF execute event. */ -#define OSPF_ISM_EVENT_EXECUTE(I,E) \ - thread_execute (master, ospf_ism_event, (I), (E)) +#define OSPF_ISM_EVENT_EXECUTE(I, E) \ + thread_execute(master, ospf_ism_event, (I), (E)) /* Prototypes. */ -extern int ospf_ism_event (struct thread *); -extern void ism_change_status (struct ospf_interface *, int); -extern int ospf_hello_timer (struct thread *thread); +extern int ospf_ism_event(struct thread *); +extern void ism_change_status(struct ospf_interface *, int); +extern int ospf_hello_timer(struct thread *thread); DECLARE_HOOK(ospf_ism_change, - (struct ospf_interface *oi, int state, int oldstate), - (oi, state, oldstate)) + (struct ospf_interface * oi, int state, int oldstate), + (oi, state, oldstate)) #endif /* _ZEBRA_OSPF_ISM_H */ diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 835d321bb..68adf2e10 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -31,7 +31,7 @@ #include "log.h" #include "thread.h" #include "hash.h" -#include "sockunion.h" /* for inet_aton() */ +#include "sockunion.h" /* for inet_aton() */ #include "checksum.h" #include "ospfd/ospfd.h" @@ -51,1483 +51,1442 @@ #include "ospfd/ospf_zebra.h" -u_int32_t -get_metric (u_char *metric) +u_int32_t get_metric(u_char *metric) { - u_int32_t m; - m = metric[0]; - m = (m << 8) + metric[1]; - m = (m << 8) + metric[2]; - return m; + u_int32_t m; + m = metric[0]; + m = (m << 8) + metric[1]; + m = (m << 8) + metric[2]; + return m; } -struct timeval -int2tv (int a) +struct timeval int2tv(int a) { - struct timeval ret; + struct timeval ret; - ret.tv_sec = a; - ret.tv_usec = 0; + ret.tv_sec = a; + ret.tv_usec = 0; - return ret; + return ret; } -struct timeval -msec2tv (int a) +struct timeval msec2tv(int a) { - struct timeval ret; + struct timeval ret; - ret.tv_sec = a/1000; - ret.tv_usec = (a%1000) * 1000; + ret.tv_sec = a / 1000; + ret.tv_usec = (a % 1000) * 1000; - return ret; + return ret; } -int -ospf_lsa_refresh_delay (struct ospf_lsa *lsa) +int ospf_lsa_refresh_delay(struct ospf_lsa *lsa) { - struct timeval delta; - int delay = 0; + struct timeval delta; + int delay = 0; - if (monotime_since (&lsa->tv_orig, &delta) < OSPF_MIN_LS_INTERVAL * 1000LL) - { - struct timeval minv = msec2tv (OSPF_MIN_LS_INTERVAL); - timersub (&minv, &delta, &minv); + if (monotime_since(&lsa->tv_orig, &delta) + < OSPF_MIN_LS_INTERVAL * 1000LL) { + struct timeval minv = msec2tv(OSPF_MIN_LS_INTERVAL); + timersub(&minv, &delta, &minv); - /* TBD: remove padding to full sec, return timeval instead */ - delay = minv.tv_sec + !!minv.tv_usec; + /* TBD: remove padding to full sec, return timeval instead */ + delay = minv.tv_sec + !!minv.tv_usec; - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type%d:%s]: Refresh timer delay %d seconds", - lsa->data->type, inet_ntoa (lsa->data->id), delay); + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type%d:%s]: Refresh timer delay %d seconds", + lsa->data->type, inet_ntoa(lsa->data->id), + delay); - assert (delay > 0); - } + assert(delay > 0); + } - return delay; + return delay; } -int -get_age (struct ospf_lsa *lsa) +int get_age(struct ospf_lsa *lsa) { - struct timeval rel; + struct timeval rel; - monotime_since (&lsa->tv_recv, &rel); - return ntohs (lsa->data->ls_age) + rel.tv_sec; + monotime_since(&lsa->tv_recv, &rel); + return ntohs(lsa->data->ls_age) + rel.tv_sec; } /* Fletcher Checksum -- Refer to RFC1008. */ -/* All the offsets are zero-based. The offsets in the RFC1008 are +/* All the offsets are zero-based. The offsets in the RFC1008 are one-based. */ -u_int16_t -ospf_lsa_checksum (struct lsa_header *lsa) +u_int16_t ospf_lsa_checksum(struct lsa_header *lsa) { - u_char *buffer = (u_char *) &lsa->options; - int options_offset = buffer - (u_char *) &lsa->ls_age; /* should be 2 */ + u_char *buffer = (u_char *)&lsa->options; + int options_offset = buffer - (u_char *)&lsa->ls_age; /* should be 2 */ - /* Skip the AGE field */ - u_int16_t len = ntohs(lsa->length) - options_offset; + /* Skip the AGE field */ + u_int16_t len = ntohs(lsa->length) - options_offset; - /* Checksum offset starts from "options" field, not the beginning of the - lsa_header struct. The offset is 14, rather than 16. */ - int checksum_offset = (u_char *) &lsa->checksum - buffer; + /* Checksum offset starts from "options" field, not the beginning of the + lsa_header struct. The offset is 14, rather than 16. */ + int checksum_offset = (u_char *)&lsa->checksum - buffer; - return fletcher_checksum(buffer, len, checksum_offset); + return fletcher_checksum(buffer, len, checksum_offset); } -int -ospf_lsa_checksum_valid (struct lsa_header *lsa) +int ospf_lsa_checksum_valid(struct lsa_header *lsa) { - u_char *buffer = (u_char *) &lsa->options; - int options_offset = buffer - (u_char *) &lsa->ls_age; /* should be 2 */ + u_char *buffer = (u_char *)&lsa->options; + int options_offset = buffer - (u_char *)&lsa->ls_age; /* should be 2 */ - /* Skip the AGE field */ - u_int16_t len = ntohs(lsa->length) - options_offset; + /* Skip the AGE field */ + u_int16_t len = ntohs(lsa->length) - options_offset; - return(fletcher_checksum(buffer, len, FLETCHER_CHECKSUM_VALIDATE) == 0); + return (fletcher_checksum(buffer, len, FLETCHER_CHECKSUM_VALIDATE) + == 0); } - /* Create OSPF LSA. */ -struct ospf_lsa * -ospf_lsa_new () +struct ospf_lsa *ospf_lsa_new() { - struct ospf_lsa *new; + struct ospf_lsa *new; - new = XCALLOC (MTYPE_OSPF_LSA, sizeof (struct ospf_lsa)); + new = XCALLOC(MTYPE_OSPF_LSA, sizeof(struct ospf_lsa)); - new->flags = 0; - new->lock = 1; - new->retransmit_counter = 0; - monotime(&new->tv_recv); - new->tv_orig = new->tv_recv; - new->refresh_list = -1; - - return new; + new->flags = 0; + new->lock = 1; + new->retransmit_counter = 0; + monotime(&new->tv_recv); + new->tv_orig = new->tv_recv; + new->refresh_list = -1; + + return new; } /* Duplicate OSPF LSA. */ -struct ospf_lsa * -ospf_lsa_dup (struct ospf_lsa *lsa) +struct ospf_lsa *ospf_lsa_dup(struct ospf_lsa *lsa) { - struct ospf_lsa *new; + struct ospf_lsa *new; - if (lsa == NULL) - return NULL; + if (lsa == NULL) + return NULL; - new = XCALLOC (MTYPE_OSPF_LSA, sizeof (struct ospf_lsa)); + new = XCALLOC(MTYPE_OSPF_LSA, sizeof(struct ospf_lsa)); - memcpy (new, lsa, sizeof (struct ospf_lsa)); - UNSET_FLAG (new->flags, OSPF_LSA_DISCARD); - new->lock = 1; - new->retransmit_counter = 0; - new->data = ospf_lsa_data_dup (lsa->data); + memcpy(new, lsa, sizeof(struct ospf_lsa)); + UNSET_FLAG(new->flags, OSPF_LSA_DISCARD); + new->lock = 1; + new->retransmit_counter = 0; + new->data = ospf_lsa_data_dup(lsa->data); - /* kevinm: Clear the refresh_list, otherwise there are going - to be problems when we try to remove the LSA from the - queue (which it's not a member of.) - XXX: Should we add the LSA to the refresh_list queue? */ - new->refresh_list = -1; + /* kevinm: Clear the refresh_list, otherwise there are going + to be problems when we try to remove the LSA from the + queue (which it's not a member of.) + XXX: Should we add the LSA to the refresh_list queue? */ + new->refresh_list = -1; - if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("LSA: duplicated %p (new: %p)", (void *)lsa, (void *)new); + if (IS_DEBUG_OSPF(lsa, LSA)) + zlog_debug("LSA: duplicated %p (new: %p)", (void *)lsa, + (void *)new); - return new; + return new; } /* Free OSPF LSA. */ -void -ospf_lsa_free (struct ospf_lsa *lsa) +void ospf_lsa_free(struct ospf_lsa *lsa) { - assert (lsa->lock == 0); - - if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("LSA: freed %p", (void *)lsa); + assert(lsa->lock == 0); + + if (IS_DEBUG_OSPF(lsa, LSA)) + zlog_debug("LSA: freed %p", (void *)lsa); - /* Delete LSA data. */ - if (lsa->data != NULL) - ospf_lsa_data_free (lsa->data); + /* Delete LSA data. */ + if (lsa->data != NULL) + ospf_lsa_data_free(lsa->data); - assert (lsa->refresh_list < 0); + assert(lsa->refresh_list < 0); - memset (lsa, 0, sizeof (struct ospf_lsa)); - XFREE (MTYPE_OSPF_LSA, lsa); + memset(lsa, 0, sizeof(struct ospf_lsa)); + XFREE(MTYPE_OSPF_LSA, lsa); } /* Lock LSA. */ -struct ospf_lsa * -ospf_lsa_lock (struct ospf_lsa *lsa) +struct ospf_lsa *ospf_lsa_lock(struct ospf_lsa *lsa) { - lsa->lock++; - return lsa; + lsa->lock++; + return lsa; } /* Unlock LSA. */ -void -ospf_lsa_unlock (struct ospf_lsa **lsa) +void ospf_lsa_unlock(struct ospf_lsa **lsa) { - /* This is sanity check. */ - if (!lsa || !*lsa) - return; - - (*lsa)->lock--; + /* This is sanity check. */ + if (!lsa || !*lsa) + return; - assert ((*lsa)->lock >= 0); + (*lsa)->lock--; - if ((*lsa)->lock == 0) - { - assert (CHECK_FLAG ((*lsa)->flags, OSPF_LSA_DISCARD)); - ospf_lsa_free (*lsa); - *lsa = NULL; - } + assert((*lsa)->lock >= 0); + + if ((*lsa)->lock == 0) { + assert(CHECK_FLAG((*lsa)->flags, OSPF_LSA_DISCARD)); + ospf_lsa_free(*lsa); + *lsa = NULL; + } } /* Check discard flag. */ -void -ospf_lsa_discard (struct ospf_lsa *lsa) +void ospf_lsa_discard(struct ospf_lsa *lsa) { - if (!CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD)) - { - SET_FLAG (lsa->flags, OSPF_LSA_DISCARD); - ospf_lsa_unlock (&lsa); - } + if (!CHECK_FLAG(lsa->flags, OSPF_LSA_DISCARD)) { + SET_FLAG(lsa->flags, OSPF_LSA_DISCARD); + ospf_lsa_unlock(&lsa); + } } /* Create LSA data. */ -struct lsa_header * -ospf_lsa_data_new (size_t size) +struct lsa_header *ospf_lsa_data_new(size_t size) { - return XCALLOC (MTYPE_OSPF_LSA_DATA, size); + return XCALLOC(MTYPE_OSPF_LSA_DATA, size); } /* Duplicate LSA data. */ -struct lsa_header * -ospf_lsa_data_dup (struct lsa_header *lsah) +struct lsa_header *ospf_lsa_data_dup(struct lsa_header *lsah) { - struct lsa_header *new; + struct lsa_header *new; - new = ospf_lsa_data_new (ntohs (lsah->length)); - memcpy (new, lsah, ntohs (lsah->length)); + new = ospf_lsa_data_new(ntohs(lsah->length)); + memcpy(new, lsah, ntohs(lsah->length)); - return new; + return new; } /* Free LSA data. */ -void -ospf_lsa_data_free (struct lsa_header *lsah) +void ospf_lsa_data_free(struct lsa_header *lsah) { - if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("LSA[Type%d:%s]: data freed %p", - lsah->type, inet_ntoa (lsah->id), (void *)lsah); + if (IS_DEBUG_OSPF(lsa, LSA)) + zlog_debug("LSA[Type%d:%s]: data freed %p", lsah->type, + inet_ntoa(lsah->id), (void *)lsah); - XFREE (MTYPE_OSPF_LSA_DATA, lsah); + XFREE(MTYPE_OSPF_LSA_DATA, lsah); } /* LSA general functions. */ -const char * -dump_lsa_key (struct ospf_lsa *lsa) +const char *dump_lsa_key(struct ospf_lsa *lsa) { - static char buf[] = { - "Type255,id(255.255.255.255),ar(255.255.255.255)" - }; - struct lsa_header *lsah; + static char buf[] = {"Type255,id(255.255.255.255),ar(255.255.255.255)"}; + struct lsa_header *lsah; - if (lsa != NULL && (lsah = lsa->data) != NULL) - { - char id[INET_ADDRSTRLEN], ar[INET_ADDRSTRLEN]; - strcpy (id, inet_ntoa (lsah->id)); - strcpy (ar, inet_ntoa (lsah->adv_router)); + if (lsa != NULL && (lsah = lsa->data) != NULL) { + char id[INET_ADDRSTRLEN], ar[INET_ADDRSTRLEN]; + strcpy(id, inet_ntoa(lsah->id)); + strcpy(ar, inet_ntoa(lsah->adv_router)); - sprintf (buf, "Type%d,id(%s),ar(%s)", lsah->type, id, ar); - } - else - strcpy (buf, "NULL"); + sprintf(buf, "Type%d,id(%s),ar(%s)", lsah->type, id, ar); + } else + strcpy(buf, "NULL"); - return buf; + return buf; } -u_int32_t -lsa_seqnum_increment (struct ospf_lsa *lsa) +u_int32_t lsa_seqnum_increment(struct ospf_lsa *lsa) { - u_int32_t seqnum; + u_int32_t seqnum; - seqnum = ntohl (lsa->data->ls_seqnum) + 1; + seqnum = ntohl(lsa->data->ls_seqnum) + 1; - return htonl (seqnum); + return htonl(seqnum); } -void -lsa_header_set (struct stream *s, u_char options, - u_char type, struct in_addr id, struct in_addr router_id) +void lsa_header_set(struct stream *s, u_char options, u_char type, + struct in_addr id, struct in_addr router_id) { - struct lsa_header *lsah; + struct lsa_header *lsah; - lsah = (struct lsa_header *) STREAM_DATA (s); + lsah = (struct lsa_header *)STREAM_DATA(s); - lsah->ls_age = htons (OSPF_LSA_INITIAL_AGE); - lsah->options = options; - lsah->type = type; - lsah->id = id; - lsah->adv_router = router_id; - lsah->ls_seqnum = htonl (OSPF_INITIAL_SEQUENCE_NUMBER); + lsah->ls_age = htons(OSPF_LSA_INITIAL_AGE); + lsah->options = options; + lsah->type = type; + lsah->id = id; + lsah->adv_router = router_id; + lsah->ls_seqnum = htonl(OSPF_INITIAL_SEQUENCE_NUMBER); - stream_forward_endp (s, OSPF_LSA_HEADER_SIZE); + stream_forward_endp(s, OSPF_LSA_HEADER_SIZE); } /* router-LSA related functions. */ /* Get router-LSA flags. */ -static u_char -router_lsa_flags (struct ospf_area *area) -{ - u_char flags; - - flags = area->ospf->flags; - - /* Set virtual link flag. */ - if (ospf_full_virtual_nbrs (area)) - SET_FLAG (flags, ROUTER_LSA_VIRTUAL); - else - /* Just sanity check */ - UNSET_FLAG (flags, ROUTER_LSA_VIRTUAL); - - /* Set Shortcut ABR behabiour flag. */ - UNSET_FLAG (flags, ROUTER_LSA_SHORTCUT); - if (area->ospf->abr_type == OSPF_ABR_SHORTCUT) - if (!OSPF_IS_AREA_BACKBONE (area)) - if ((area->shortcut_configured == OSPF_SHORTCUT_DEFAULT && - area->ospf->backbone == NULL) || - area->shortcut_configured == OSPF_SHORTCUT_ENABLE) - SET_FLAG (flags, ROUTER_LSA_SHORTCUT); - - /* ASBR can't exit in stub area. */ - if (area->external_routing == OSPF_AREA_STUB) - UNSET_FLAG (flags, ROUTER_LSA_EXTERNAL); - /* If ASBR set External flag */ - else if (IS_OSPF_ASBR (area->ospf)) - SET_FLAG (flags, ROUTER_LSA_EXTERNAL); - - /* Set ABR dependent flags */ - if (IS_OSPF_ABR (area->ospf)) - { - SET_FLAG (flags, ROUTER_LSA_BORDER); - /* If Area is NSSA and we are both ABR and unconditional translator, - * set Nt bit to inform other routers. - */ - if ( (area->external_routing == OSPF_AREA_NSSA) - && (area->NSSATranslatorRole == OSPF_NSSA_ROLE_ALWAYS)) - SET_FLAG (flags, ROUTER_LSA_NT); - } - return flags; +static u_char router_lsa_flags(struct ospf_area *area) +{ + u_char flags; + + flags = area->ospf->flags; + + /* Set virtual link flag. */ + if (ospf_full_virtual_nbrs(area)) + SET_FLAG(flags, ROUTER_LSA_VIRTUAL); + else + /* Just sanity check */ + UNSET_FLAG(flags, ROUTER_LSA_VIRTUAL); + + /* Set Shortcut ABR behabiour flag. */ + UNSET_FLAG(flags, ROUTER_LSA_SHORTCUT); + if (area->ospf->abr_type == OSPF_ABR_SHORTCUT) + if (!OSPF_IS_AREA_BACKBONE(area)) + if ((area->shortcut_configured == OSPF_SHORTCUT_DEFAULT + && area->ospf->backbone == NULL) + || area->shortcut_configured + == OSPF_SHORTCUT_ENABLE) + SET_FLAG(flags, ROUTER_LSA_SHORTCUT); + + /* ASBR can't exit in stub area. */ + if (area->external_routing == OSPF_AREA_STUB) + UNSET_FLAG(flags, ROUTER_LSA_EXTERNAL); + /* If ASBR set External flag */ + else if (IS_OSPF_ASBR(area->ospf)) + SET_FLAG(flags, ROUTER_LSA_EXTERNAL); + + /* Set ABR dependent flags */ + if (IS_OSPF_ABR(area->ospf)) { + SET_FLAG(flags, ROUTER_LSA_BORDER); + /* If Area is NSSA and we are both ABR and unconditional + * translator, + * set Nt bit to inform other routers. + */ + if ((area->external_routing == OSPF_AREA_NSSA) + && (area->NSSATranslatorRole == OSPF_NSSA_ROLE_ALWAYS)) + SET_FLAG(flags, ROUTER_LSA_NT); + } + return flags; } /* Lookup neighbor other than myself. And check neighbor count, Point-to-Point link must have only 1 neighbor. */ -struct ospf_neighbor * -ospf_nbr_lookup_ptop (struct ospf_interface *oi) +struct ospf_neighbor *ospf_nbr_lookup_ptop(struct ospf_interface *oi) { - struct ospf_neighbor *nbr = NULL; - struct route_node *rn; + struct ospf_neighbor *nbr = NULL; + struct route_node *rn; - /* Search neighbor, there must be one of two nbrs. */ - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) - if (nbr->state == NSM_Full) - { - route_unlock_node (rn); - break; - } + /* Search neighbor, there must be one of two nbrs. */ + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info)) + if (!IPV4_ADDR_SAME(&nbr->router_id, + &oi->ospf->router_id)) + if (nbr->state == NSM_Full) { + route_unlock_node(rn); + break; + } - /* PtoP link must have only 1 neighbor. */ - if (ospf_nbr_count (oi, 0) > 1) - zlog_warn ("Point-to-Point link has more than 1 neighobrs."); + /* PtoP link must have only 1 neighbor. */ + if (ospf_nbr_count(oi, 0) > 1) + zlog_warn("Point-to-Point link has more than 1 neighobrs."); - return nbr; + return nbr; } /* Determine cost of link, taking RFC3137 stub-router support into * consideration */ -static u_int16_t -ospf_link_cost (struct ospf_interface *oi) +static u_int16_t ospf_link_cost(struct ospf_interface *oi) { - /* RFC3137 stub router support */ - if (!CHECK_FLAG (oi->area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED)) - return oi->output_cost; - else - return OSPF_OUTPUT_COST_INFINITE; + /* RFC3137 stub router support */ + if (!CHECK_FLAG(oi->area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED)) + return oi->output_cost; + else + return OSPF_OUTPUT_COST_INFINITE; } /* Set a link information. */ -static char -link_info_set (struct stream *s, struct in_addr id, - struct in_addr data, u_char type, u_char tos, u_int16_t cost) -{ - /* LSA stream is initially allocated to OSPF_MAX_LSA_SIZE, suits - * vast majority of cases. Some rare routers with lots of links need more. - * we try accomodate those here. - */ - if (STREAM_WRITEABLE(s) < OSPF_ROUTER_LSA_LINK_SIZE) - { - size_t ret = OSPF_MAX_LSA_SIZE; - - /* Can we enlarge the stream still? */ - if (STREAM_SIZE(s) == OSPF_MAX_LSA_SIZE) - { - /* we futz the size here for simplicity, really we need to account - * for just: - * IP Header - (sizeof (struct ip)) - * OSPF Header - OSPF_HEADER_SIZE - * LSA Header - OSPF_LSA_HEADER_SIZE - * MD5 auth data, if MD5 is configured - OSPF_AUTH_MD5_SIZE. - * - * Simpler just to subtract OSPF_MAX_LSA_SIZE though. - */ - ret = stream_resize (s, OSPF_MAX_PACKET_SIZE - OSPF_MAX_LSA_SIZE); - } - - if (ret == OSPF_MAX_LSA_SIZE) - { - zlog_warn ("%s: Out of space in LSA stream, left %zd, size %zd", - __func__, STREAM_REMAIN (s), STREAM_SIZE (s)); - return 0; - } - } - - /* TOS based routing is not supported. */ - stream_put_ipv4 (s, id.s_addr); /* Link ID. */ - stream_put_ipv4 (s, data.s_addr); /* Link Data. */ - stream_putc (s, type); /* Link Type. */ - stream_putc (s, tos); /* TOS = 0. */ - stream_putw (s, cost); /* Link Cost. */ - - return 1; +static char link_info_set(struct stream *s, struct in_addr id, + struct in_addr data, u_char type, u_char tos, + u_int16_t cost) +{ + /* LSA stream is initially allocated to OSPF_MAX_LSA_SIZE, suits + * vast majority of cases. Some rare routers with lots of links need + * more. + * we try accomodate those here. + */ + if (STREAM_WRITEABLE(s) < OSPF_ROUTER_LSA_LINK_SIZE) { + size_t ret = OSPF_MAX_LSA_SIZE; + + /* Can we enlarge the stream still? */ + if (STREAM_SIZE(s) == OSPF_MAX_LSA_SIZE) { + /* we futz the size here for simplicity, really we need + * to account + * for just: + * IP Header - (sizeof (struct ip)) + * OSPF Header - OSPF_HEADER_SIZE + * LSA Header - OSPF_LSA_HEADER_SIZE + * MD5 auth data, if MD5 is configured - + * OSPF_AUTH_MD5_SIZE. + * + * Simpler just to subtract OSPF_MAX_LSA_SIZE though. + */ + ret = stream_resize( + s, OSPF_MAX_PACKET_SIZE - OSPF_MAX_LSA_SIZE); + } + + if (ret == OSPF_MAX_LSA_SIZE) { + zlog_warn( + "%s: Out of space in LSA stream, left %zd, size %zd", + __func__, STREAM_REMAIN(s), STREAM_SIZE(s)); + return 0; + } + } + + /* TOS based routing is not supported. */ + stream_put_ipv4(s, id.s_addr); /* Link ID. */ + stream_put_ipv4(s, data.s_addr); /* Link Data. */ + stream_putc(s, type); /* Link Type. */ + stream_putc(s, tos); /* TOS = 0. */ + stream_putw(s, cost); /* Link Cost. */ + + return 1; } /* Describe Point-to-Point link (Section 12.4.1.1). */ -static int -lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi) -{ - int links = 0; - struct ospf_neighbor *nbr; - struct in_addr id, mask, data; - u_int16_t cost = ospf_link_cost (oi); - - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type1]: Set link Point-to-Point"); - - if ((nbr = ospf_nbr_lookup_ptop (oi))) - if (nbr->state == NSM_Full) - { - if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) - { - /* For unnumbered point-to-point networks, the Link Data field - should specify the interface's MIB-II ifIndex value. */ - data.s_addr = htonl(oi->ifp->ifindex); - links += link_info_set (s, nbr->router_id, data, - LSA_LINK_TYPE_POINTOPOINT, 0, cost); - } - else - { - links += link_info_set (s, nbr->router_id, - oi->address->u.prefix4, - LSA_LINK_TYPE_POINTOPOINT, 0, cost); - } - } - - /* no need for a stub link for unnumbered interfaces */ - if (!CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) - { - /* Regardless of the state of the neighboring router, we must - add a Type 3 link (stub network). - N.B. Options 1 & 2 share basically the same logic. */ - masklen2ip (oi->address->prefixlen, &mask); - id.s_addr = CONNECTED_PREFIX(oi->connected)->u.prefix4.s_addr & mask.s_addr; - links += link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, - oi->output_cost); - } - - return links; +static int lsa_link_ptop_set(struct stream *s, struct ospf_interface *oi) +{ + int links = 0; + struct ospf_neighbor *nbr; + struct in_addr id, mask, data; + u_int16_t cost = ospf_link_cost(oi); + + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug("LSA[Type1]: Set link Point-to-Point"); + + if ((nbr = ospf_nbr_lookup_ptop(oi))) + if (nbr->state == NSM_Full) { + if (CHECK_FLAG(oi->connected->flags, + ZEBRA_IFA_UNNUMBERED)) { + /* For unnumbered point-to-point networks, the + Link Data field + should specify the interface's MIB-II ifIndex + value. */ + data.s_addr = htonl(oi->ifp->ifindex); + links += link_info_set( + s, nbr->router_id, data, + LSA_LINK_TYPE_POINTOPOINT, 0, cost); + } else { + links += link_info_set( + s, nbr->router_id, + oi->address->u.prefix4, + LSA_LINK_TYPE_POINTOPOINT, 0, cost); + } + } + + /* no need for a stub link for unnumbered interfaces */ + if (!CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) { + /* Regardless of the state of the neighboring router, we must + add a Type 3 link (stub network). + N.B. Options 1 & 2 share basically the same logic. */ + masklen2ip(oi->address->prefixlen, &mask); + id.s_addr = CONNECTED_PREFIX(oi->connected)->u.prefix4.s_addr + & mask.s_addr; + links += link_info_set(s, id, mask, LSA_LINK_TYPE_STUB, 0, + oi->output_cost); + } + + return links; } /* Describe Broadcast Link. */ -static int -lsa_link_broadcast_set (struct stream *s, struct ospf_interface *oi) -{ - struct ospf_neighbor *dr; - struct in_addr id, mask; - u_int16_t cost = ospf_link_cost (oi); - - /* Describe Type 3 Link. */ - if (oi->state == ISM_Waiting) - { - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type1]: Interface %s is in state Waiting. " - "Adding stub interface", oi->ifp->name); - masklen2ip (oi->address->prefixlen, &mask); - id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr; - return link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, - oi->output_cost); - } - - dr = ospf_nbr_lookup_by_addr (oi->nbrs, &DR (oi)); - /* Describe Type 2 link. */ - if (dr && (dr->state == NSM_Full || - IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))) && - ospf_nbr_count (oi, NSM_Full) > 0) - { - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type1]: Interface %s has a DR. " - "Adding transit interface", oi->ifp->name); - return link_info_set (s, DR (oi), oi->address->u.prefix4, - LSA_LINK_TYPE_TRANSIT, 0, cost); - } - /* Describe type 3 link. */ - else - { - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type1]: Interface %s has no DR. " - "Adding stub interface", oi->ifp->name); - masklen2ip (oi->address->prefixlen, &mask); - id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr; - return link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, - oi->output_cost); - } -} - -static int -lsa_link_loopback_set (struct stream *s, struct ospf_interface *oi) -{ - struct in_addr id, mask; - - /* Describe Type 3 Link. */ - if (oi->state != ISM_Loopback) - return 0; - - mask.s_addr = 0xffffffff; - id.s_addr = oi->address->u.prefix4.s_addr; - return link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, 0); +static int lsa_link_broadcast_set(struct stream *s, struct ospf_interface *oi) +{ + struct ospf_neighbor *dr; + struct in_addr id, mask; + u_int16_t cost = ospf_link_cost(oi); + + /* Describe Type 3 Link. */ + if (oi->state == ISM_Waiting) { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type1]: Interface %s is in state Waiting. " + "Adding stub interface", + oi->ifp->name); + masklen2ip(oi->address->prefixlen, &mask); + id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr; + return link_info_set(s, id, mask, LSA_LINK_TYPE_STUB, 0, + oi->output_cost); + } + + dr = ospf_nbr_lookup_by_addr(oi->nbrs, &DR(oi)); + /* Describe Type 2 link. */ + if (dr && (dr->state == NSM_Full + || IPV4_ADDR_SAME(&oi->address->u.prefix4, &DR(oi))) + && ospf_nbr_count(oi, NSM_Full) > 0) { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type1]: Interface %s has a DR. " + "Adding transit interface", + oi->ifp->name); + return link_info_set(s, DR(oi), oi->address->u.prefix4, + LSA_LINK_TYPE_TRANSIT, 0, cost); + } + /* Describe type 3 link. */ + else { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type1]: Interface %s has no DR. " + "Adding stub interface", + oi->ifp->name); + masklen2ip(oi->address->prefixlen, &mask); + id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr; + return link_info_set(s, id, mask, LSA_LINK_TYPE_STUB, 0, + oi->output_cost); + } +} + +static int lsa_link_loopback_set(struct stream *s, struct ospf_interface *oi) +{ + struct in_addr id, mask; + + /* Describe Type 3 Link. */ + if (oi->state != ISM_Loopback) + return 0; + + mask.s_addr = 0xffffffff; + id.s_addr = oi->address->u.prefix4.s_addr; + return link_info_set(s, id, mask, LSA_LINK_TYPE_STUB, 0, 0); } /* Describe Virtual Link. */ -static int -lsa_link_virtuallink_set (struct stream *s, struct ospf_interface *oi) +static int lsa_link_virtuallink_set(struct stream *s, struct ospf_interface *oi) { - struct ospf_neighbor *nbr; - u_int16_t cost = ospf_link_cost (oi); + struct ospf_neighbor *nbr; + u_int16_t cost = ospf_link_cost(oi); - if (oi->state == ISM_PointToPoint) - if ((nbr = ospf_nbr_lookup_ptop (oi))) - if (nbr->state == NSM_Full) - { - return link_info_set (s, nbr->router_id, oi->address->u.prefix4, - LSA_LINK_TYPE_VIRTUALLINK, 0, cost); - } + if (oi->state == ISM_PointToPoint) + if ((nbr = ospf_nbr_lookup_ptop(oi))) + if (nbr->state == NSM_Full) { + return link_info_set(s, nbr->router_id, + oi->address->u.prefix4, + LSA_LINK_TYPE_VIRTUALLINK, + 0, cost); + } - return 0; + return 0; } #define lsa_link_nbma_set(S,O) lsa_link_broadcast_set (S, O) -/* this function add for support point-to-multipoint ,see rfc2328 +/* this function add for support point-to-multipoint ,see rfc2328 12.4.1.4.*/ /* from "edward rrr" http://marc.theaimsgroup.com/?l=zebra&m=100739222210507&w=2 */ -static int -lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi) -{ - int links = 0; - struct route_node *rn; - struct ospf_neighbor *nbr = NULL; - struct in_addr id, mask; - u_int16_t cost = ospf_link_cost (oi); - - mask.s_addr = 0xffffffff; - id.s_addr = oi->address->u.prefix4.s_addr; - links += link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, 0); - - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("PointToMultipoint: running ptomultip_set"); - - /* Search neighbor, */ - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - /* Ignore myself. */ - if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) - if (nbr->state == NSM_Full) - - { - links += link_info_set (s, nbr->router_id, oi->address->u.prefix4, - LSA_LINK_TYPE_POINTOPOINT, 0, cost); - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("PointToMultipoint: set link to %s", - inet_ntoa(oi->address->u.prefix4)); - } - - return links; +static int lsa_link_ptomp_set(struct stream *s, struct ospf_interface *oi) +{ + int links = 0; + struct route_node *rn; + struct ospf_neighbor *nbr = NULL; + struct in_addr id, mask; + u_int16_t cost = ospf_link_cost(oi); + + mask.s_addr = 0xffffffff; + id.s_addr = oi->address->u.prefix4.s_addr; + links += link_info_set(s, id, mask, LSA_LINK_TYPE_STUB, 0, 0); + + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug("PointToMultipoint: running ptomultip_set"); + + /* Search neighbor, */ + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info) != NULL) + /* Ignore myself. */ + if (!IPV4_ADDR_SAME(&nbr->router_id, + &oi->ospf->router_id)) + if (nbr->state == NSM_Full) + + { + links += link_info_set( + s, nbr->router_id, + oi->address->u.prefix4, + LSA_LINK_TYPE_POINTOPOINT, 0, + cost); + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "PointToMultipoint: set link to %s", + inet_ntoa( + oi->address->u + .prefix4)); + } + + return links; } /* Set router-LSA link information. */ -static int -router_lsa_link_set (struct stream *s, struct ospf_area *area) -{ - struct listnode *node; - struct ospf_interface *oi; - int links = 0; - - for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi)) - { - struct interface *ifp = oi->ifp; - - /* Check interface is up, OSPF is enable. */ - if (if_is_operative (ifp)) - { - if (oi->state != ISM_Down) - { - oi->lsa_pos_beg = links; - /* Describe each link. */ - switch (oi->type) - { - case OSPF_IFTYPE_POINTOPOINT: - links += lsa_link_ptop_set (s, oi); - break; - case OSPF_IFTYPE_BROADCAST: - links += lsa_link_broadcast_set (s, oi); - break; - case OSPF_IFTYPE_NBMA: - links += lsa_link_nbma_set (s, oi); - break; - case OSPF_IFTYPE_POINTOMULTIPOINT: - links += lsa_link_ptomp_set (s, oi); - break; - case OSPF_IFTYPE_VIRTUALLINK: - links += lsa_link_virtuallink_set (s, oi); - break; - case OSPF_IFTYPE_LOOPBACK: - links += lsa_link_loopback_set (s, oi); +static int router_lsa_link_set(struct stream *s, struct ospf_area *area) +{ + struct listnode *node; + struct ospf_interface *oi; + int links = 0; + + for (ALL_LIST_ELEMENTS_RO(area->oiflist, node, oi)) { + struct interface *ifp = oi->ifp; + + /* Check interface is up, OSPF is enable. */ + if (if_is_operative(ifp)) { + if (oi->state != ISM_Down) { + oi->lsa_pos_beg = links; + /* Describe each link. */ + switch (oi->type) { + case OSPF_IFTYPE_POINTOPOINT: + links += lsa_link_ptop_set(s, oi); + break; + case OSPF_IFTYPE_BROADCAST: + links += lsa_link_broadcast_set(s, oi); + break; + case OSPF_IFTYPE_NBMA: + links += lsa_link_nbma_set(s, oi); + break; + case OSPF_IFTYPE_POINTOMULTIPOINT: + links += lsa_link_ptomp_set(s, oi); + break; + case OSPF_IFTYPE_VIRTUALLINK: + links += + lsa_link_virtuallink_set(s, oi); + break; + case OSPF_IFTYPE_LOOPBACK: + links += lsa_link_loopback_set(s, oi); + } + oi->lsa_pos_end = links; + } } - oi->lsa_pos_end = links; - } } - } - return links; + return links; } /* Set router-LSA body. */ -static void -ospf_router_lsa_body_set (struct stream *s, struct ospf_area *area) -{ - unsigned long putp; - u_int16_t cnt; - - /* Set flags. */ - stream_putc (s, router_lsa_flags (area)); - - /* Set Zero fields. */ - stream_putc (s, 0); - - /* Keep pointer to # links. */ - putp = stream_get_endp(s); - - /* Forward word */ - stream_putw(s, 0); - - /* Set all link information. */ - cnt = router_lsa_link_set (s, area); - - /* Set # of links here. */ - stream_putw_at (s, putp, cnt); -} - -static int -ospf_stub_router_timer (struct thread *t) -{ - struct ospf_area *area = THREAD_ARG (t); - - area->t_stub_router = NULL; - - SET_FLAG (area->stub_router_state, OSPF_AREA_WAS_START_STUB_ROUTED); - - /* clear stub route state and generate router-lsa refresh, don't - * clobber an administratively set stub-router state though. - */ - if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED)) - return 0; - - UNSET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED); - - ospf_router_lsa_update_area (area); - - return 0; -} - -static void -ospf_stub_router_check (struct ospf_area *area) -{ - /* area must either be administratively configured to be stub - * or startup-time stub-router must be configured and we must in a pre-stub - * state. - */ - if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED)) - { - SET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED); - return; - } - - /* not admin-stubbed, check whether startup stubbing is configured and - * whether it's not been done yet - */ - if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_WAS_START_STUB_ROUTED)) - return; - - if (area->ospf->stub_router_startup_time == OSPF_STUB_ROUTER_UNCONFIGURED) - { - /* stub-router is hence done forever for this area, even if someone - * tries configure it (take effect next restart). - */ - SET_FLAG (area->stub_router_state, OSPF_AREA_WAS_START_STUB_ROUTED); - return; - } - - /* startup stub-router configured and not yet done */ - SET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED); - - OSPF_AREA_TIMER_ON (area->t_stub_router, ospf_stub_router_timer, - area->ospf->stub_router_startup_time); -} - +static void ospf_router_lsa_body_set(struct stream *s, struct ospf_area *area) +{ + unsigned long putp; + u_int16_t cnt; + + /* Set flags. */ + stream_putc(s, router_lsa_flags(area)); + + /* Set Zero fields. */ + stream_putc(s, 0); + + /* Keep pointer to # links. */ + putp = stream_get_endp(s); + + /* Forward word */ + stream_putw(s, 0); + + /* Set all link information. */ + cnt = router_lsa_link_set(s, area); + + /* Set # of links here. */ + stream_putw_at(s, putp, cnt); +} + +static int ospf_stub_router_timer(struct thread *t) +{ + struct ospf_area *area = THREAD_ARG(t); + + area->t_stub_router = NULL; + + SET_FLAG(area->stub_router_state, OSPF_AREA_WAS_START_STUB_ROUTED); + + /* clear stub route state and generate router-lsa refresh, don't + * clobber an administratively set stub-router state though. + */ + if (CHECK_FLAG(area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED)) + return 0; + + UNSET_FLAG(area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED); + + ospf_router_lsa_update_area(area); + + return 0; +} + +static void ospf_stub_router_check(struct ospf_area *area) +{ + /* area must either be administratively configured to be stub + * or startup-time stub-router must be configured and we must in a + * pre-stub + * state. + */ + if (CHECK_FLAG(area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED)) { + SET_FLAG(area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED); + return; + } + + /* not admin-stubbed, check whether startup stubbing is configured and + * whether it's not been done yet + */ + if (CHECK_FLAG(area->stub_router_state, + OSPF_AREA_WAS_START_STUB_ROUTED)) + return; + + if (area->ospf->stub_router_startup_time + == OSPF_STUB_ROUTER_UNCONFIGURED) { + /* stub-router is hence done forever for this area, even if + * someone + * tries configure it (take effect next restart). + */ + SET_FLAG(area->stub_router_state, + OSPF_AREA_WAS_START_STUB_ROUTED); + return; + } + + /* startup stub-router configured and not yet done */ + SET_FLAG(area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED); + + OSPF_AREA_TIMER_ON(area->t_stub_router, ospf_stub_router_timer, + area->ospf->stub_router_startup_time); +} + /* Create new router-LSA. */ -static struct ospf_lsa * -ospf_router_lsa_new (struct ospf_area *area) -{ - struct ospf *ospf = area->ospf; - struct stream *s; - struct lsa_header *lsah; - struct ospf_lsa *new; - int length; - - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type1]: Create router-LSA instance"); - - /* check whether stub-router is desired, and if this is the first - * router LSA. - */ - ospf_stub_router_check (area); - - /* Create a stream for LSA. */ - s = stream_new (OSPF_MAX_LSA_SIZE); - /* Set LSA common header fields. */ - lsa_header_set (s, LSA_OPTIONS_GET (area) | LSA_OPTIONS_NSSA_GET (area), - OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id); - - /* Set router-LSA body fields. */ - ospf_router_lsa_body_set (s, area); - - /* Set length. */ - length = stream_get_endp (s); - lsah = (struct lsa_header *) STREAM_DATA (s); - lsah->length = htons (length); - - /* Now, create OSPF LSA instance. */ - if ( (new = ospf_lsa_new ()) == NULL) - { - zlog_err ("%s: Unable to create new lsa", __func__); - return NULL; - } - - new->area = area; - SET_FLAG (new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); - - /* Copy LSA data to store, discard stream. */ - new->data = ospf_lsa_data_new (length); - memcpy (new->data, lsah, length); - stream_free (s); - - return new; +static struct ospf_lsa *ospf_router_lsa_new(struct ospf_area *area) +{ + struct ospf *ospf = area->ospf; + struct stream *s; + struct lsa_header *lsah; + struct ospf_lsa *new; + int length; + + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug("LSA[Type1]: Create router-LSA instance"); + + /* check whether stub-router is desired, and if this is the first + * router LSA. + */ + ospf_stub_router_check(area); + + /* Create a stream for LSA. */ + s = stream_new(OSPF_MAX_LSA_SIZE); + /* Set LSA common header fields. */ + lsa_header_set(s, LSA_OPTIONS_GET(area) | LSA_OPTIONS_NSSA_GET(area), + OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id); + + /* Set router-LSA body fields. */ + ospf_router_lsa_body_set(s, area); + + /* Set length. */ + length = stream_get_endp(s); + lsah = (struct lsa_header *)STREAM_DATA(s); + lsah->length = htons(length); + + /* Now, create OSPF LSA instance. */ + if ((new = ospf_lsa_new()) == NULL) { + zlog_err("%s: Unable to create new lsa", __func__); + return NULL; + } + + new->area = area; + SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); + + /* Copy LSA data to store, discard stream. */ + new->data = ospf_lsa_data_new(length); + memcpy(new->data, lsah, length); + stream_free(s); + + return new; } /* Originate Router-LSA. */ -static struct ospf_lsa * -ospf_router_lsa_originate (struct ospf_area *area) +static struct ospf_lsa *ospf_router_lsa_originate(struct ospf_area *area) { - struct ospf_lsa *new; - - /* Create new router-LSA instance. */ - if ( (new = ospf_router_lsa_new (area)) == NULL) - { - zlog_err ("%s: ospf_router_lsa_new returned NULL", __func__); - return NULL; - } + struct ospf_lsa *new; - /* Sanity check. */ - if (new->data->adv_router.s_addr == 0) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[Type1]: AdvRouter is 0, discard"); - ospf_lsa_discard (new); - return NULL; - } + /* Create new router-LSA instance. */ + if ((new = ospf_router_lsa_new(area)) == NULL) { + zlog_err("%s: ospf_router_lsa_new returned NULL", __func__); + return NULL; + } + + /* Sanity check. */ + if (new->data->adv_router.s_addr == 0) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("LSA[Type1]: AdvRouter is 0, discard"); + ospf_lsa_discard(new); + return NULL; + } - /* Install LSA to LSDB. */ - new = ospf_lsa_install (area->ospf, NULL, new); + /* Install LSA to LSDB. */ + new = ospf_lsa_install(area->ospf, NULL, new); - /* Update LSA origination count. */ - area->ospf->lsa_originate_count++; + /* Update LSA origination count. */ + area->ospf->lsa_originate_count++; - /* Flooding new LSA through area. */ - ospf_flood_through_area (area, NULL, new); + /* Flooding new LSA through area. */ + ospf_flood_through_area(area, NULL, new); - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - { - zlog_debug ("LSA[Type%d:%s]: Originate router-LSA %p", - new->data->type, inet_ntoa (new->data->id), (void *)new); - ospf_lsa_header_dump (new->data); - } + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug("LSA[Type%d:%s]: Originate router-LSA %p", + new->data->type, inet_ntoa(new->data->id), + (void *)new); + ospf_lsa_header_dump(new->data); + } - return new; + return new; } /* Refresh router-LSA. */ -static struct ospf_lsa * -ospf_router_lsa_refresh (struct ospf_lsa *lsa) -{ - struct ospf_area *area = lsa->area; - struct ospf_lsa *new; - - /* Sanity check. */ - assert (lsa->data); +static struct ospf_lsa *ospf_router_lsa_refresh(struct ospf_lsa *lsa) +{ + struct ospf_area *area = lsa->area; + struct ospf_lsa *new; + + /* Sanity check. */ + assert(lsa->data); - /* Delete LSA from neighbor retransmit-list. */ - ospf_ls_retransmit_delete_nbr_area (area, lsa); + /* Delete LSA from neighbor retransmit-list. */ + ospf_ls_retransmit_delete_nbr_area(area, lsa); - /* Unregister LSA from refresh-list */ - ospf_refresher_unregister_lsa (area->ospf, lsa); - - /* Create new router-LSA instance. */ - if ( (new = ospf_router_lsa_new (area)) == NULL) - { - zlog_err ("%s: ospf_router_lsa_new returned NULL", __func__); - return NULL; - } - - new->data->ls_seqnum = lsa_seqnum_increment (lsa); + /* Unregister LSA from refresh-list */ + ospf_refresher_unregister_lsa(area->ospf, lsa); - ospf_lsa_install (area->ospf, NULL, new); + /* Create new router-LSA instance. */ + if ((new = ospf_router_lsa_new(area)) == NULL) { + zlog_err("%s: ospf_router_lsa_new returned NULL", __func__); + return NULL; + } + + new->data->ls_seqnum = lsa_seqnum_increment(lsa); - /* Flood LSA through area. */ - ospf_flood_through_area (area, NULL, new); + ospf_lsa_install(area->ospf, NULL, new); - /* Debug logging. */ - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - { - zlog_debug ("LSA[Type%d:%s]: router-LSA refresh", - new->data->type, inet_ntoa (new->data->id)); - ospf_lsa_header_dump (new->data); - } + /* Flood LSA through area. */ + ospf_flood_through_area(area, NULL, new); + + /* Debug logging. */ + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug("LSA[Type%d:%s]: router-LSA refresh", + new->data->type, inet_ntoa(new->data->id)); + ospf_lsa_header_dump(new->data); + } - return NULL; + return NULL; } -int -ospf_router_lsa_update_area (struct ospf_area *area) +int ospf_router_lsa_update_area(struct ospf_area *area) { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("[router-LSA]: (router-LSA area update)"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("[router-LSA]: (router-LSA area update)"); - /* Now refresh router-LSA. */ - if (area->router_lsa_self) - ospf_lsa_refresh (area->ospf, area->router_lsa_self); - /* Newly originate router-LSA. */ - else - ospf_router_lsa_originate (area); + /* Now refresh router-LSA. */ + if (area->router_lsa_self) + ospf_lsa_refresh(area->ospf, area->router_lsa_self); + /* Newly originate router-LSA. */ + else + ospf_router_lsa_originate(area); - return 0; + return 0; } -int -ospf_router_lsa_update (struct ospf *ospf) +int ospf_router_lsa_update(struct ospf *ospf) { - struct listnode *node, *nnode; - struct ospf_area *area; + struct listnode *node, *nnode; + struct ospf_area *area; - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("Timer[router-LSA Update]: (timer expire)"); + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug("Timer[router-LSA Update]: (timer expire)"); - for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) - { - struct ospf_lsa *lsa = area->router_lsa_self; - struct router_lsa *rl; - const char *area_str; + for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { + struct ospf_lsa *lsa = area->router_lsa_self; + struct router_lsa *rl; + const char *area_str; - /* Keep Area ID string. */ - area_str = AREA_NAME (area); + /* Keep Area ID string. */ + area_str = AREA_NAME(area); - /* If LSA not exist in this Area, originate new. */ - if (lsa == NULL) - { - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug("LSA[Type1]: Create router-LSA for Area %s", area_str); + /* If LSA not exist in this Area, originate new. */ + if (lsa == NULL) { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type1]: Create router-LSA for Area %s", + area_str); - ospf_router_lsa_originate (area); - } - /* If router-ID is changed, Link ID must change. - First flush old LSA, then originate new. */ - else if (!IPV4_ADDR_SAME (&lsa->data->id, &ospf->router_id)) - { - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug("LSA[Type%d:%s]: Refresh router-LSA for Area %s", - lsa->data->type, inet_ntoa (lsa->data->id), area_str); - ospf_refresher_unregister_lsa (ospf, lsa); - ospf_lsa_flush_area (lsa, area); - ospf_lsa_unlock (&area->router_lsa_self); - area->router_lsa_self = NULL; - - /* Refresh router-LSA, (not install) and flood through area. */ - ospf_router_lsa_update_area (area); - } - else - { - rl = (struct router_lsa *) lsa->data; - /* Refresh router-LSA, (not install) and flood through area. */ - if (rl->flags != ospf->flags) - ospf_router_lsa_update_area (area); + ospf_router_lsa_originate(area); + } + /* If router-ID is changed, Link ID must change. + First flush old LSA, then originate new. */ + else if (!IPV4_ADDR_SAME(&lsa->data->id, &ospf->router_id)) { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type%d:%s]: Refresh router-LSA for Area %s", + lsa->data->type, + inet_ntoa(lsa->data->id), area_str); + ospf_refresher_unregister_lsa(ospf, lsa); + ospf_lsa_flush_area(lsa, area); + ospf_lsa_unlock(&area->router_lsa_self); + area->router_lsa_self = NULL; + + /* Refresh router-LSA, (not install) and flood through + * area. */ + ospf_router_lsa_update_area(area); + } else { + rl = (struct router_lsa *)lsa->data; + /* Refresh router-LSA, (not install) and flood through + * area. */ + if (rl->flags != ospf->flags) + ospf_router_lsa_update_area(area); + } } - } - return 0; + return 0; } /* network-LSA related functions. */ /* Originate Network-LSA. */ -static void -ospf_network_lsa_body_set (struct stream *s, struct ospf_interface *oi) +static void ospf_network_lsa_body_set(struct stream *s, + struct ospf_interface *oi) { - struct in_addr mask; - struct route_node *rn; - struct ospf_neighbor *nbr; + struct in_addr mask; + struct route_node *rn; + struct ospf_neighbor *nbr; - masklen2ip (oi->address->prefixlen, &mask); - stream_put_ipv4 (s, mask.s_addr); + masklen2ip(oi->address->prefixlen, &mask); + stream_put_ipv4(s, mask.s_addr); - /* The network-LSA lists those routers that are fully adjacent to - the Designated Router; each fully adjacent router is identified by - its OSPF Router ID. The Designated Router includes itself in this - list. RFC2328, Section 12.4.2 */ + /* The network-LSA lists those routers that are fully adjacent to + the Designated Router; each fully adjacent router is identified by + its OSPF Router ID. The Designated Router includes itself in this + list. RFC2328, Section 12.4.2 */ - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - if (nbr->state == NSM_Full || nbr == oi->nbr_self) - stream_put_ipv4 (s, nbr->router_id.s_addr); + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info) != NULL) + if (nbr->state == NSM_Full || nbr == oi->nbr_self) + stream_put_ipv4(s, nbr->router_id.s_addr); } -static struct ospf_lsa * -ospf_network_lsa_new (struct ospf_interface *oi) -{ - struct stream *s; - struct ospf_lsa *new; - struct lsa_header *lsah; - struct ospf_if_params *oip; - int length; - - /* If there are no neighbours on this network (the net is stub), - the router does not originate network-LSA (see RFC 12.4.2) */ - if (oi->full_nbrs == 0) - return NULL; - - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type2]: Create network-LSA instance"); - - /* Create new stream for LSA. */ - s = stream_new (OSPF_MAX_LSA_SIZE); - lsah = (struct lsa_header *) STREAM_DATA (s); - - lsa_header_set (s, (OPTIONS (oi) | LSA_OPTIONS_GET (oi->area)), - OSPF_NETWORK_LSA, DR (oi), oi->ospf->router_id); - - /* Set network-LSA body fields. */ - ospf_network_lsa_body_set (s, oi); - - /* Set length. */ - length = stream_get_endp (s); - lsah->length = htons (length); - - /* Create OSPF LSA instance. */ - if ( (new = ospf_lsa_new ()) == NULL) - { - zlog_err ("%s: ospf_lsa_new returned NULL", __func__); - return NULL; - } - - new->area = oi->area; - SET_FLAG (new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); - - /* Copy LSA to store. */ - new->data = ospf_lsa_data_new (length); - memcpy (new->data, lsah, length); - stream_free (s); - - /* Remember prior network LSA sequence numbers, even if we stop - * originating one for this oi, to try avoid re-originating LSAs with a - * prior sequence number, and thus speed up adjency forming & convergence. - */ - if ((oip = ospf_lookup_if_params (oi->ifp, oi->address->u.prefix4))) - { - new->data->ls_seqnum = oip->network_lsa_seqnum; - new->data->ls_seqnum = lsa_seqnum_increment (new); - } - else - { - oip = ospf_get_if_params (oi->ifp, oi->address->u.prefix4); - ospf_if_update_params (oi->ifp, oi->address->u.prefix4); - } - oip->network_lsa_seqnum = new->data->ls_seqnum; - - return new; +static struct ospf_lsa *ospf_network_lsa_new(struct ospf_interface *oi) +{ + struct stream *s; + struct ospf_lsa *new; + struct lsa_header *lsah; + struct ospf_if_params *oip; + int length; + + /* If there are no neighbours on this network (the net is stub), + the router does not originate network-LSA (see RFC 12.4.2) */ + if (oi->full_nbrs == 0) + return NULL; + + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug("LSA[Type2]: Create network-LSA instance"); + + /* Create new stream for LSA. */ + s = stream_new(OSPF_MAX_LSA_SIZE); + lsah = (struct lsa_header *)STREAM_DATA(s); + + lsa_header_set(s, (OPTIONS(oi) | LSA_OPTIONS_GET(oi->area)), + OSPF_NETWORK_LSA, DR(oi), oi->ospf->router_id); + + /* Set network-LSA body fields. */ + ospf_network_lsa_body_set(s, oi); + + /* Set length. */ + length = stream_get_endp(s); + lsah->length = htons(length); + + /* Create OSPF LSA instance. */ + if ((new = ospf_lsa_new()) == NULL) { + zlog_err("%s: ospf_lsa_new returned NULL", __func__); + return NULL; + } + + new->area = oi->area; + SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); + + /* Copy LSA to store. */ + new->data = ospf_lsa_data_new(length); + memcpy(new->data, lsah, length); + stream_free(s); + + /* Remember prior network LSA sequence numbers, even if we stop + * originating one for this oi, to try avoid re-originating LSAs with a + * prior sequence number, and thus speed up adjency forming & + * convergence. + */ + if ((oip = ospf_lookup_if_params(oi->ifp, oi->address->u.prefix4))) { + new->data->ls_seqnum = oip->network_lsa_seqnum; + new->data->ls_seqnum = lsa_seqnum_increment(new); + } else { + oip = ospf_get_if_params(oi->ifp, oi->address->u.prefix4); + ospf_if_update_params(oi->ifp, oi->address->u.prefix4); + } + oip->network_lsa_seqnum = new->data->ls_seqnum; + + return new; } /* Originate network-LSA. */ -void -ospf_network_lsa_update (struct ospf_interface *oi) +void ospf_network_lsa_update(struct ospf_interface *oi) { - struct ospf_lsa *new; - - if (oi->network_lsa_self != NULL) - { - ospf_lsa_refresh (oi->ospf, oi->network_lsa_self); - return; - } - - /* Create new network-LSA instance. */ - new = ospf_network_lsa_new (oi); - if (new == NULL) - return; + struct ospf_lsa *new; - /* Install LSA to LSDB. */ - new = ospf_lsa_install (oi->ospf, oi, new); + if (oi->network_lsa_self != NULL) { + ospf_lsa_refresh(oi->ospf, oi->network_lsa_self); + return; + } + + /* Create new network-LSA instance. */ + new = ospf_network_lsa_new(oi); + if (new == NULL) + return; - /* Update LSA origination count. */ - oi->ospf->lsa_originate_count++; + /* Install LSA to LSDB. */ + new = ospf_lsa_install(oi->ospf, oi, new); - /* Flooding new LSA through area. */ - ospf_flood_through_area (oi->area, NULL, new); + /* Update LSA origination count. */ + oi->ospf->lsa_originate_count++; - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - { - zlog_debug ("LSA[Type%d:%s]: Originate network-LSA %p", - new->data->type, inet_ntoa (new->data->id), (void *)new); - ospf_lsa_header_dump (new->data); - } + /* Flooding new LSA through area. */ + ospf_flood_through_area(oi->area, NULL, new); + + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug("LSA[Type%d:%s]: Originate network-LSA %p", + new->data->type, inet_ntoa(new->data->id), + (void *)new); + ospf_lsa_header_dump(new->data); + } - return; + return; } -static struct ospf_lsa * -ospf_network_lsa_refresh (struct ospf_lsa *lsa) -{ - struct ospf_area *area = lsa->area; - struct ospf_lsa *new, *new2; - struct ospf_if_params *oip; - struct ospf_interface *oi; - - assert (lsa->data); - - /* Retrieve the oi for the network LSA */ - oi = ospf_if_lookup_by_local_addr (area->ospf, NULL, lsa->data->id); - if (oi == NULL) - { - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - { - zlog_debug ("LSA[Type%d:%s]: network-LSA refresh: " - "no oi found, ick, ignoring.", - lsa->data->type, inet_ntoa (lsa->data->id)); - ospf_lsa_header_dump (lsa->data); - } - return NULL; - } - /* Delete LSA from neighbor retransmit-list. */ - ospf_ls_retransmit_delete_nbr_area (area, lsa); - - /* Unregister LSA from refresh-list */ - ospf_refresher_unregister_lsa (area->ospf, lsa); - - /* Create new network-LSA instance. */ - new = ospf_network_lsa_new (oi); - if (new == NULL) - return NULL; - - oip = ospf_lookup_if_params (oi->ifp, oi->address->u.prefix4); - assert (oip != NULL); - oip->network_lsa_seqnum = new->data->ls_seqnum = lsa_seqnum_increment (lsa); - - new2 = ospf_lsa_install (area->ospf, oi, new); - - assert (new2 == new); - - /* Flood LSA through aera. */ - ospf_flood_through_area (area, NULL, new); - - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - { - zlog_debug ("LSA[Type%d:%s]: network-LSA refresh", - new->data->type, inet_ntoa (new->data->id)); - ospf_lsa_header_dump (new->data); - } - - return new; -} - -static void -stream_put_ospf_metric (struct stream *s, u_int32_t metric_value) -{ - u_int32_t metric; - char *mp; - - /* Put 0 metric. TOS metric is not supported. */ - metric = htonl (metric_value); - mp = (char *) &metric; - mp++; - stream_put (s, mp, 3); +static struct ospf_lsa *ospf_network_lsa_refresh(struct ospf_lsa *lsa) +{ + struct ospf_area *area = lsa->area; + struct ospf_lsa *new, *new2; + struct ospf_if_params *oip; + struct ospf_interface *oi; + + assert(lsa->data); + + /* Retrieve the oi for the network LSA */ + oi = ospf_if_lookup_by_local_addr(area->ospf, NULL, lsa->data->id); + if (oi == NULL) { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug( + "LSA[Type%d:%s]: network-LSA refresh: " + "no oi found, ick, ignoring.", + lsa->data->type, inet_ntoa(lsa->data->id)); + ospf_lsa_header_dump(lsa->data); + } + return NULL; + } + /* Delete LSA from neighbor retransmit-list. */ + ospf_ls_retransmit_delete_nbr_area(area, lsa); + + /* Unregister LSA from refresh-list */ + ospf_refresher_unregister_lsa(area->ospf, lsa); + + /* Create new network-LSA instance. */ + new = ospf_network_lsa_new(oi); + if (new == NULL) + return NULL; + + oip = ospf_lookup_if_params(oi->ifp, oi->address->u.prefix4); + assert(oip != NULL); + oip->network_lsa_seqnum = new->data->ls_seqnum = + lsa_seqnum_increment(lsa); + + new2 = ospf_lsa_install(area->ospf, oi, new); + + assert(new2 == new); + + /* Flood LSA through aera. */ + ospf_flood_through_area(area, NULL, new); + + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug("LSA[Type%d:%s]: network-LSA refresh", + new->data->type, inet_ntoa(new->data->id)); + ospf_lsa_header_dump(new->data); + } + + return new; +} + +static void stream_put_ospf_metric(struct stream *s, u_int32_t metric_value) +{ + u_int32_t metric; + char *mp; + + /* Put 0 metric. TOS metric is not supported. */ + metric = htonl(metric_value); + mp = (char *)&metric; + mp++; + stream_put(s, mp, 3); } /* summary-LSA related functions. */ -static void -ospf_summary_lsa_body_set (struct stream *s, struct prefix *p, - u_int32_t metric) +static void ospf_summary_lsa_body_set(struct stream *s, struct prefix *p, + u_int32_t metric) { - struct in_addr mask; + struct in_addr mask; - masklen2ip (p->prefixlen, &mask); + masklen2ip(p->prefixlen, &mask); - /* Put Network Mask. */ - stream_put_ipv4 (s, mask.s_addr); + /* Put Network Mask. */ + stream_put_ipv4(s, mask.s_addr); - /* Set # TOS. */ - stream_putc (s, (u_char) 0); + /* Set # TOS. */ + stream_putc(s, (u_char)0); - /* Set metric. */ - stream_put_ospf_metric (s, metric); + /* Set metric. */ + stream_put_ospf_metric(s, metric); } -static struct ospf_lsa * -ospf_summary_lsa_new (struct ospf_area *area, struct prefix *p, - u_int32_t metric, struct in_addr id) +static struct ospf_lsa *ospf_summary_lsa_new(struct ospf_area *area, + struct prefix *p, u_int32_t metric, + struct in_addr id) { - struct stream *s; - struct ospf_lsa *new; - struct lsa_header *lsah; - int length; + struct stream *s; + struct ospf_lsa *new; + struct lsa_header *lsah; + int length; - if (id.s_addr == 0xffffffff) - { - /* Maybe Link State ID not available. */ - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type%d]: Link ID not available, can't originate", - OSPF_SUMMARY_LSA); - return NULL; - } + if (id.s_addr == 0xffffffff) { + /* Maybe Link State ID not available. */ + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type%d]: Link ID not available, can't originate", + OSPF_SUMMARY_LSA); + return NULL; + } - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type3]: Create summary-LSA instance"); + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug("LSA[Type3]: Create summary-LSA instance"); - /* Create new stream for LSA. */ - s = stream_new (OSPF_MAX_LSA_SIZE); - lsah = (struct lsa_header *) STREAM_DATA (s); + /* Create new stream for LSA. */ + s = stream_new(OSPF_MAX_LSA_SIZE); + lsah = (struct lsa_header *)STREAM_DATA(s); - lsa_header_set (s, LSA_OPTIONS_GET (area), OSPF_SUMMARY_LSA, - id, area->ospf->router_id); + lsa_header_set(s, LSA_OPTIONS_GET(area), OSPF_SUMMARY_LSA, id, + area->ospf->router_id); - /* Set summary-LSA body fields. */ - ospf_summary_lsa_body_set (s, p, metric); + /* Set summary-LSA body fields. */ + ospf_summary_lsa_body_set(s, p, metric); - /* Set length. */ - length = stream_get_endp (s); - lsah->length = htons (length); + /* Set length. */ + length = stream_get_endp(s); + lsah->length = htons(length); - /* Create OSPF LSA instance. */ - new = ospf_lsa_new (); - new->area = area; - SET_FLAG (new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); + /* Create OSPF LSA instance. */ + new = ospf_lsa_new(); + new->area = area; + SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); - /* Copy LSA to store. */ - new->data = ospf_lsa_data_new (length); - memcpy (new->data, lsah, length); - stream_free (s); + /* Copy LSA to store. */ + new->data = ospf_lsa_data_new(length); + memcpy(new->data, lsah, length); + stream_free(s); - return new; + return new; } /* Originate Summary-LSA. */ -struct ospf_lsa * -ospf_summary_lsa_originate (struct prefix_ipv4 *p, u_int32_t metric, - struct ospf_area *area) -{ - struct ospf_lsa *new; - struct in_addr id; - - id = ospf_lsa_unique_id (area->ospf, area->lsdb, OSPF_SUMMARY_LSA, p); - - if (id.s_addr == 0xffffffff) - { - /* Maybe Link State ID not available. */ - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type%d]: Link ID not available, can't originate", - OSPF_SUMMARY_LSA); - return NULL; - } - - /* Create new summary-LSA instance. */ - if ( !(new = ospf_summary_lsa_new (area, (struct prefix *) p, metric, id))) - return NULL; - - /* Instlal LSA to LSDB. */ - new = ospf_lsa_install (area->ospf, NULL, new); - - /* Update LSA origination count. */ - area->ospf->lsa_originate_count++; - - /* Flooding new LSA through area. */ - ospf_flood_through_area (area, NULL, new); - - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - { - zlog_debug ("LSA[Type%d:%s]: Originate summary-LSA %p", - new->data->type, inet_ntoa (new->data->id), (void *)new); - ospf_lsa_header_dump (new->data); - } - - return new; -} - -static struct ospf_lsa* -ospf_summary_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa) -{ - struct ospf_lsa *new; - struct summary_lsa *sl; - struct prefix p; - - /* Sanity check. */ - assert (lsa->data); - - sl = (struct summary_lsa *)lsa->data; - p.prefixlen = ip_masklen (sl->mask); - new = ospf_summary_lsa_new (lsa->area, &p, GET_METRIC (sl->metric), - sl->header.id); - - if (!new) - return NULL; - - new->data->ls_seqnum = lsa_seqnum_increment (lsa); - - ospf_lsa_install (ospf, NULL, new); - - /* Flood LSA through AS. */ - ospf_flood_through_area (new->area, NULL, new); - - /* Debug logging. */ - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - { - zlog_debug ("LSA[Type%d:%s]: summary-LSA refresh", - new->data->type, inet_ntoa (new->data->id)); - ospf_lsa_header_dump (new->data); - } - - return new; +struct ospf_lsa *ospf_summary_lsa_originate(struct prefix_ipv4 *p, + u_int32_t metric, + struct ospf_area *area) +{ + struct ospf_lsa *new; + struct in_addr id; + + id = ospf_lsa_unique_id(area->ospf, area->lsdb, OSPF_SUMMARY_LSA, p); + + if (id.s_addr == 0xffffffff) { + /* Maybe Link State ID not available. */ + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type%d]: Link ID not available, can't originate", + OSPF_SUMMARY_LSA); + return NULL; + } + + /* Create new summary-LSA instance. */ + if (!(new = ospf_summary_lsa_new(area, (struct prefix *)p, metric, id))) + return NULL; + + /* Instlal LSA to LSDB. */ + new = ospf_lsa_install(area->ospf, NULL, new); + + /* Update LSA origination count. */ + area->ospf->lsa_originate_count++; + + /* Flooding new LSA through area. */ + ospf_flood_through_area(area, NULL, new); + + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug("LSA[Type%d:%s]: Originate summary-LSA %p", + new->data->type, inet_ntoa(new->data->id), + (void *)new); + ospf_lsa_header_dump(new->data); + } + + return new; +} + +static struct ospf_lsa *ospf_summary_lsa_refresh(struct ospf *ospf, + struct ospf_lsa *lsa) +{ + struct ospf_lsa *new; + struct summary_lsa *sl; + struct prefix p; + + /* Sanity check. */ + assert(lsa->data); + + sl = (struct summary_lsa *)lsa->data; + p.prefixlen = ip_masklen(sl->mask); + new = ospf_summary_lsa_new(lsa->area, &p, GET_METRIC(sl->metric), + sl->header.id); + + if (!new) + return NULL; + + new->data->ls_seqnum = lsa_seqnum_increment(lsa); + + ospf_lsa_install(ospf, NULL, new); + + /* Flood LSA through AS. */ + ospf_flood_through_area(new->area, NULL, new); + + /* Debug logging. */ + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug("LSA[Type%d:%s]: summary-LSA refresh", + new->data->type, inet_ntoa(new->data->id)); + ospf_lsa_header_dump(new->data); + } + + return new; } /* summary-ASBR-LSA related functions. */ -static void -ospf_summary_asbr_lsa_body_set (struct stream *s, struct prefix *p, - u_int32_t metric) +static void ospf_summary_asbr_lsa_body_set(struct stream *s, struct prefix *p, + u_int32_t metric) { - /* Put Network Mask. */ - stream_put_ipv4 (s, (u_int32_t) 0); + /* Put Network Mask. */ + stream_put_ipv4(s, (u_int32_t)0); - /* Set # TOS. */ - stream_putc (s, (u_char) 0); + /* Set # TOS. */ + stream_putc(s, (u_char)0); - /* Set metric. */ - stream_put_ospf_metric (s, metric); + /* Set metric. */ + stream_put_ospf_metric(s, metric); } -static struct ospf_lsa * -ospf_summary_asbr_lsa_new (struct ospf_area *area, struct prefix *p, - u_int32_t metric, struct in_addr id) +static struct ospf_lsa *ospf_summary_asbr_lsa_new(struct ospf_area *area, + struct prefix *p, + u_int32_t metric, + struct in_addr id) { - struct stream *s; - struct ospf_lsa *new; - struct lsa_header *lsah; - int length; + struct stream *s; + struct ospf_lsa *new; + struct lsa_header *lsah; + int length; - if (id.s_addr == 0xffffffff) - { - /* Maybe Link State ID not available. */ - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type%d]: Link ID not available, can't originate", - OSPF_ASBR_SUMMARY_LSA); - return NULL; - } + if (id.s_addr == 0xffffffff) { + /* Maybe Link State ID not available. */ + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type%d]: Link ID not available, can't originate", + OSPF_ASBR_SUMMARY_LSA); + return NULL; + } - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type3]: Create summary-LSA instance"); + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug("LSA[Type3]: Create summary-LSA instance"); - /* Create new stream for LSA. */ - s = stream_new (OSPF_MAX_LSA_SIZE); - lsah = (struct lsa_header *) STREAM_DATA (s); + /* Create new stream for LSA. */ + s = stream_new(OSPF_MAX_LSA_SIZE); + lsah = (struct lsa_header *)STREAM_DATA(s); - lsa_header_set (s, LSA_OPTIONS_GET (area), OSPF_ASBR_SUMMARY_LSA, - id, area->ospf->router_id); + lsa_header_set(s, LSA_OPTIONS_GET(area), OSPF_ASBR_SUMMARY_LSA, id, + area->ospf->router_id); - /* Set summary-LSA body fields. */ - ospf_summary_asbr_lsa_body_set (s, p, metric); + /* Set summary-LSA body fields. */ + ospf_summary_asbr_lsa_body_set(s, p, metric); - /* Set length. */ - length = stream_get_endp (s); - lsah->length = htons (length); + /* Set length. */ + length = stream_get_endp(s); + lsah->length = htons(length); - /* Create OSPF LSA instance. */ - new = ospf_lsa_new (); - new->area = area; - SET_FLAG (new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); + /* Create OSPF LSA instance. */ + new = ospf_lsa_new(); + new->area = area; + SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); - /* Copy LSA to store. */ - new->data = ospf_lsa_data_new (length); - memcpy (new->data, lsah, length); - stream_free (s); + /* Copy LSA to store. */ + new->data = ospf_lsa_data_new(length); + memcpy(new->data, lsah, length); + stream_free(s); - return new; + return new; } /* Originate summary-ASBR-LSA. */ -struct ospf_lsa * -ospf_summary_asbr_lsa_originate (struct prefix_ipv4 *p, u_int32_t metric, - struct ospf_area *area) -{ - struct ospf_lsa *new; - struct in_addr id; - - id = ospf_lsa_unique_id (area->ospf, area->lsdb, OSPF_ASBR_SUMMARY_LSA, p); - - if (id.s_addr == 0xffffffff) - { - /* Maybe Link State ID not available. */ - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type%d]: Link ID not available, can't originate", - OSPF_ASBR_SUMMARY_LSA); - return NULL; - } - - /* Create new summary-LSA instance. */ - new = ospf_summary_asbr_lsa_new (area, (struct prefix *) p, metric, id); - if (!new) - return NULL; - - /* Install LSA to LSDB. */ - new = ospf_lsa_install (area->ospf, NULL, new); - - /* Update LSA origination count. */ - area->ospf->lsa_originate_count++; - - /* Flooding new LSA through area. */ - ospf_flood_through_area (area, NULL, new); - - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - { - zlog_debug ("LSA[Type%d:%s]: Originate summary-ASBR-LSA %p", - new->data->type, inet_ntoa (new->data->id), (void *)new); - ospf_lsa_header_dump (new->data); - } - - return new; -} - -static struct ospf_lsa* -ospf_summary_asbr_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa) -{ - struct ospf_lsa *new; - struct summary_lsa *sl; - struct prefix p; - - /* Sanity check. */ - assert (lsa->data); - - sl = (struct summary_lsa *)lsa->data; - p.prefixlen = ip_masklen (sl->mask); - new = ospf_summary_asbr_lsa_new (lsa->area, &p, GET_METRIC (sl->metric), - sl->header.id); - if (!new) - return NULL; - - new->data->ls_seqnum = lsa_seqnum_increment (lsa); +struct ospf_lsa *ospf_summary_asbr_lsa_originate(struct prefix_ipv4 *p, + u_int32_t metric, + struct ospf_area *area) +{ + struct ospf_lsa *new; + struct in_addr id; + + id = ospf_lsa_unique_id(area->ospf, area->lsdb, OSPF_ASBR_SUMMARY_LSA, + p); + + if (id.s_addr == 0xffffffff) { + /* Maybe Link State ID not available. */ + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type%d]: Link ID not available, can't originate", + OSPF_ASBR_SUMMARY_LSA); + return NULL; + } + + /* Create new summary-LSA instance. */ + new = ospf_summary_asbr_lsa_new(area, (struct prefix *)p, metric, id); + if (!new) + return NULL; + + /* Install LSA to LSDB. */ + new = ospf_lsa_install(area->ospf, NULL, new); - ospf_lsa_install (ospf, NULL, new); - - /* Flood LSA through area. */ - ospf_flood_through_area (new->area, NULL, new); + /* Update LSA origination count. */ + area->ospf->lsa_originate_count++; - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - { - zlog_debug ("LSA[Type%d:%s]: summary-ASBR-LSA refresh", - new->data->type, inet_ntoa (new->data->id)); - ospf_lsa_header_dump (new->data); - } + /* Flooding new LSA through area. */ + ospf_flood_through_area(area, NULL, new); - return new; + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug("LSA[Type%d:%s]: Originate summary-ASBR-LSA %p", + new->data->type, inet_ntoa(new->data->id), + (void *)new); + ospf_lsa_header_dump(new->data); + } + + return new; +} + +static struct ospf_lsa *ospf_summary_asbr_lsa_refresh(struct ospf *ospf, + struct ospf_lsa *lsa) +{ + struct ospf_lsa *new; + struct summary_lsa *sl; + struct prefix p; + + /* Sanity check. */ + assert(lsa->data); + + sl = (struct summary_lsa *)lsa->data; + p.prefixlen = ip_masklen(sl->mask); + new = ospf_summary_asbr_lsa_new(lsa->area, &p, GET_METRIC(sl->metric), + sl->header.id); + if (!new) + return NULL; + + new->data->ls_seqnum = lsa_seqnum_increment(lsa); + + ospf_lsa_install(ospf, NULL, new); + + /* Flood LSA through area. */ + ospf_flood_through_area(new->area, NULL, new); + + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug("LSA[Type%d:%s]: summary-ASBR-LSA refresh", + new->data->type, inet_ntoa(new->data->id)); + ospf_lsa_header_dump(new->data); + } + + return new; } /* AS-external-LSA related functions. */ /* Get nexthop for AS-external-LSAs. Return nexthop if its interface is connected, else 0*/ -static struct in_addr -ospf_external_lsa_nexthop_get (struct ospf *ospf, struct in_addr nexthop) +static struct in_addr ospf_external_lsa_nexthop_get(struct ospf *ospf, + struct in_addr nexthop) { - struct in_addr fwd; - struct prefix nh; - struct listnode *node; - struct ospf_interface *oi; + struct in_addr fwd; + struct prefix nh; + struct listnode *node; + struct ospf_interface *oi; + + fwd.s_addr = 0; - fwd.s_addr = 0; + if (!nexthop.s_addr) + return fwd; - if (!nexthop.s_addr) - return fwd; + /* Check whether nexthop is covered by OSPF network. */ + nh.family = AF_INET; + nh.u.prefix4 = nexthop; + nh.prefixlen = IPV4_MAX_BITLEN; - /* Check whether nexthop is covered by OSPF network. */ - nh.family = AF_INET; - nh.u.prefix4 = nexthop; - nh.prefixlen = IPV4_MAX_BITLEN; - - /* XXX/SCALE: If there were a lot of oi's on an ifp, then it'd be - * better to make use of the per-ifp table of ois. - */ - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) - if (if_is_operative (oi->ifp)) - if (oi->address->family == AF_INET) - if (prefix_match (oi->address, &nh)) - return nexthop; + /* XXX/SCALE: If there were a lot of oi's on an ifp, then it'd be + * better to make use of the per-ifp table of ois. + */ + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) + if (if_is_operative(oi->ifp)) + if (oi->address->family == AF_INET) + if (prefix_match(oi->address, &nh)) + return nexthop; - return fwd; + return fwd; } /* NSSA-external-LSA related functions. */ /* Get 1st IP connection for Forward Addr */ -struct in_addr -ospf_get_ip_from_ifp (struct ospf_interface *oi) +struct in_addr ospf_get_ip_from_ifp(struct ospf_interface *oi) { - struct in_addr fwd; + struct in_addr fwd; - fwd.s_addr = 0; + fwd.s_addr = 0; - if (if_is_operative (oi->ifp)) - return oi->address->u.prefix4; - - return fwd; + if (if_is_operative(oi->ifp)) + return oi->address->u.prefix4; + + return fwd; } /* Get 1st IP connection for Forward Addr */ -struct in_addr -ospf_get_nssa_ip (struct ospf_area *area) -{ - struct in_addr fwd; - struct in_addr best_default; - struct listnode *node; - struct ospf_interface *oi; - - fwd.s_addr = 0; - best_default.s_addr = 0; - - for (ALL_LIST_ELEMENTS_RO (area->ospf->oiflist, node, oi)) - { - if (if_is_operative (oi->ifp)) - if (oi->area->external_routing == OSPF_AREA_NSSA) - if (oi->address && oi->address->family == AF_INET) - { - if (best_default.s_addr == 0) - best_default = oi->address->u.prefix4; - if (oi->area == area) - return oi->address->u.prefix4; - } - } - if (best_default.s_addr != 0) - return best_default; +struct in_addr ospf_get_nssa_ip(struct ospf_area *area) +{ + struct in_addr fwd; + struct in_addr best_default; + struct listnode *node; + struct ospf_interface *oi; + + fwd.s_addr = 0; + best_default.s_addr = 0; + + for (ALL_LIST_ELEMENTS_RO(area->ospf->oiflist, node, oi)) { + if (if_is_operative(oi->ifp)) + if (oi->area->external_routing == OSPF_AREA_NSSA) + if (oi->address + && oi->address->family == AF_INET) { + if (best_default.s_addr == 0) + best_default = + oi->address->u.prefix4; + if (oi->area == area) + return oi->address->u.prefix4; + } + } + if (best_default.s_addr != 0) + return best_default; - if (best_default.s_addr != 0) - return best_default; + if (best_default.s_addr != 0) + return best_default; - return fwd; + return fwd; } #define DEFAULT_DEFAULT_METRIC 20 @@ -1536,841 +1495,840 @@ ospf_get_nssa_ip (struct ospf_area *area) #define DEFAULT_METRIC_TYPE EXTERNAL_METRIC_TYPE_2 -int -metric_type (struct ospf *ospf, u_char src, u_short instance) +int metric_type(struct ospf *ospf, u_char src, u_short instance) { - struct ospf_redist *red; + struct ospf_redist *red; - red = ospf_redist_lookup(ospf, src, instance); + red = ospf_redist_lookup(ospf, src, instance); - return ((!red || red->dmetric.type < 0) ? - DEFAULT_METRIC_TYPE : red->dmetric.type); + return ((!red || red->dmetric.type < 0) ? DEFAULT_METRIC_TYPE + : red->dmetric.type); } -int -metric_value (struct ospf *ospf, u_char src, u_short instance) +int metric_value(struct ospf *ospf, u_char src, u_short instance) { - struct ospf_redist *red; + struct ospf_redist *red; - red = ospf_redist_lookup(ospf, src, instance); - if (!red || red->dmetric.value < 0) - { - if (src == DEFAULT_ROUTE) - { - if (ospf->default_originate == DEFAULT_ORIGINATE_ZEBRA) - return DEFAULT_DEFAULT_ORIGINATE_METRIC; - else - return DEFAULT_DEFAULT_ALWAYS_METRIC; + red = ospf_redist_lookup(ospf, src, instance); + if (!red || red->dmetric.value < 0) { + if (src == DEFAULT_ROUTE) { + if (ospf->default_originate == DEFAULT_ORIGINATE_ZEBRA) + return DEFAULT_DEFAULT_ORIGINATE_METRIC; + else + return DEFAULT_DEFAULT_ALWAYS_METRIC; + } else if (ospf->default_metric < 0) + return DEFAULT_DEFAULT_METRIC; + else + return ospf->default_metric; } - else if (ospf->default_metric < 0) - return DEFAULT_DEFAULT_METRIC; - else - return ospf->default_metric; - } - return red->dmetric.value; + return red->dmetric.value; } /* Set AS-external-LSA body. */ -static void -ospf_external_lsa_body_set (struct stream *s, struct external_info *ei, - struct ospf *ospf) -{ - struct prefix_ipv4 *p = &ei->p; - struct in_addr mask, fwd_addr; - u_int32_t mvalue; - int mtype; - int type; - u_short instance; - - /* Put Network Mask. */ - masklen2ip (p->prefixlen, &mask); - stream_put_ipv4 (s, mask.s_addr); - - /* If prefix is default, specify DEFAULT_ROUTE. */ - type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type; - instance = is_prefix_default (&ei->p) ? 0 : ei->instance; - - mtype = (ROUTEMAP_METRIC_TYPE (ei) != -1) ? - ROUTEMAP_METRIC_TYPE (ei) : metric_type (ospf, type, instance); - - mvalue = (ROUTEMAP_METRIC (ei) != -1) ? - ROUTEMAP_METRIC (ei) : metric_value (ospf, type, instance); - - /* Put type of external metric. */ - stream_putc (s, (mtype == EXTERNAL_METRIC_TYPE_2 ? 0x80 : 0)); - - /* Put 0 metric. TOS metric is not supported. */ - stream_put_ospf_metric (s, mvalue); - - /* Get forwarding address to nexthop if on the Connection List, else 0. */ - fwd_addr = ospf_external_lsa_nexthop_get (ospf, ei->nexthop); - - /* Put forwarding address. */ - stream_put_ipv4 (s, fwd_addr.s_addr); - - /* Put route tag */ - stream_putl (s, ei->tag); +static void ospf_external_lsa_body_set(struct stream *s, + struct external_info *ei, + struct ospf *ospf) +{ + struct prefix_ipv4 *p = &ei->p; + struct in_addr mask, fwd_addr; + u_int32_t mvalue; + int mtype; + int type; + u_short instance; + + /* Put Network Mask. */ + masklen2ip(p->prefixlen, &mask); + stream_put_ipv4(s, mask.s_addr); + + /* If prefix is default, specify DEFAULT_ROUTE. */ + type = is_prefix_default(&ei->p) ? DEFAULT_ROUTE : ei->type; + instance = is_prefix_default(&ei->p) ? 0 : ei->instance; + + mtype = (ROUTEMAP_METRIC_TYPE(ei) != -1) + ? ROUTEMAP_METRIC_TYPE(ei) + : metric_type(ospf, type, instance); + + mvalue = (ROUTEMAP_METRIC(ei) != -1) + ? ROUTEMAP_METRIC(ei) + : metric_value(ospf, type, instance); + + /* Put type of external metric. */ + stream_putc(s, (mtype == EXTERNAL_METRIC_TYPE_2 ? 0x80 : 0)); + + /* Put 0 metric. TOS metric is not supported. */ + stream_put_ospf_metric(s, mvalue); + + /* Get forwarding address to nexthop if on the Connection List, else 0. + */ + fwd_addr = ospf_external_lsa_nexthop_get(ospf, ei->nexthop); + + /* Put forwarding address. */ + stream_put_ipv4(s, fwd_addr.s_addr); + + /* Put route tag */ + stream_putl(s, ei->tag); } /* Create new external-LSA. */ -static struct ospf_lsa * -ospf_external_lsa_new (struct ospf *ospf, - struct external_info *ei, struct in_addr *old_id) -{ - struct stream *s; - struct lsa_header *lsah; - struct ospf_lsa *new; - struct in_addr id; - int length; - - if (ei == NULL) - { - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type5]: External info is NULL, can't originate"); - return NULL; - } - - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type5]: Originate AS-external-LSA instance"); - - /* If old Link State ID is specified, refresh LSA with same ID. */ - if (old_id) - id = *old_id; - /* Get Link State with unique ID. */ - else - { - id = ospf_lsa_unique_id (ospf, ospf->lsdb, OSPF_AS_EXTERNAL_LSA, &ei->p); - if (id.s_addr == 0xffffffff) - { - /* Maybe Link State ID not available. */ - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type5]: Link ID not available, can't originate"); - return NULL; - } - } - - /* Create new stream for LSA. */ - s = stream_new (OSPF_MAX_LSA_SIZE); - lsah = (struct lsa_header *) STREAM_DATA (s); - - /* Set LSA common header fields. */ - lsa_header_set (s, OSPF_OPTION_E, OSPF_AS_EXTERNAL_LSA, - id, ospf->router_id); - - /* Set AS-external-LSA body fields. */ - ospf_external_lsa_body_set (s, ei, ospf); - - /* Set length. */ - length = stream_get_endp (s); - lsah->length = htons (length); - - /* Now, create OSPF LSA instance. */ - new = ospf_lsa_new (); - new->area = NULL; - SET_FLAG (new->flags, OSPF_LSA_SELF | OSPF_LSA_APPROVED | OSPF_LSA_SELF_CHECKED); - - /* Copy LSA data to store, discard stream. */ - new->data = ospf_lsa_data_new (length); - memcpy (new->data, lsah, length); - stream_free (s); - - return new; +static struct ospf_lsa *ospf_external_lsa_new(struct ospf *ospf, + struct external_info *ei, + struct in_addr *old_id) +{ + struct stream *s; + struct lsa_header *lsah; + struct ospf_lsa *new; + struct in_addr id; + int length; + + if (ei == NULL) { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type5]: External info is NULL, can't originate"); + return NULL; + } + + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug("LSA[Type5]: Originate AS-external-LSA instance"); + + /* If old Link State ID is specified, refresh LSA with same ID. */ + if (old_id) + id = *old_id; + /* Get Link State with unique ID. */ + else { + id = ospf_lsa_unique_id(ospf, ospf->lsdb, OSPF_AS_EXTERNAL_LSA, + &ei->p); + if (id.s_addr == 0xffffffff) { + /* Maybe Link State ID not available. */ + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type5]: Link ID not available, can't originate"); + return NULL; + } + } + + /* Create new stream for LSA. */ + s = stream_new(OSPF_MAX_LSA_SIZE); + lsah = (struct lsa_header *)STREAM_DATA(s); + + /* Set LSA common header fields. */ + lsa_header_set(s, OSPF_OPTION_E, OSPF_AS_EXTERNAL_LSA, id, + ospf->router_id); + + /* Set AS-external-LSA body fields. */ + ospf_external_lsa_body_set(s, ei, ospf); + + /* Set length. */ + length = stream_get_endp(s); + lsah->length = htons(length); + + /* Now, create OSPF LSA instance. */ + new = ospf_lsa_new(); + new->area = NULL; + SET_FLAG(new->flags, + OSPF_LSA_SELF | OSPF_LSA_APPROVED | OSPF_LSA_SELF_CHECKED); + + /* Copy LSA data to store, discard stream. */ + new->data = ospf_lsa_data_new(length); + memcpy(new->data, lsah, length); + stream_free(s); + + return new; } /* As Type-7 */ -static void -ospf_install_flood_nssa (struct ospf *ospf, - struct ospf_lsa *lsa, struct external_info *ei) -{ - struct ospf_lsa *new; - struct as_external_lsa *extlsa; - struct ospf_area *area; - struct listnode *node, *nnode; - - /* LSA may be a Type-5 originated via translation of a Type-7 LSA - * which originated from an NSSA area. In which case it should not be - * flooded back to NSSA areas. - */ - if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)) - return; - - /* NSSA Originate or Refresh (If anyNSSA) - - LSA is self-originated. And just installed as Type-5. - Additionally, install as Type-7 LSDB for every attached NSSA. - - P-Bit controls which ABR performs translation to outside world; If - we are an ABR....do not set the P-bit, because we send the Type-5, - not as the ABR Translator, but as the ASBR owner within the AS! - - If we are NOT ABR, Flood through NSSA as Type-7 w/P-bit set. The - elected ABR Translator will see the P-bit, Translate, and re-flood. - - Later, ABR_TASK and P-bit will scan Type-7 LSDB and translate to - Type-5's to non-NSSA Areas. (it will also attempt a re-install) */ - - for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) - { - /* Don't install Type-7 LSA's into nonNSSA area */ - if (area->external_routing != OSPF_AREA_NSSA) - continue; - - /* make lsa duplicate, lock=1 */ - new = ospf_lsa_dup (lsa); - new->area = area; - new->data->type = OSPF_AS_NSSA_LSA; - - /* set P-bit if not ABR */ - if (! IS_OSPF_ABR (ospf)) - { - SET_FLAG(new->data->options, OSPF_OPTION_NP); - - /* set non-zero FWD ADDR - - draft-ietf-ospf-nssa-update-09.txt - - if the network between the NSSA AS boundary router and the - adjacent AS is advertised into OSPF as an internal OSPF route, - the forwarding address should be the next op address as is cu - currently done with type-5 LSAs. If the intervening network is - not adversited into OSPF as an internal OSPF route and the - type-7 LSA's P-bit is set a forwarding address should be - selected from one of the router's active OSPF inteface addresses - which belong to the NSSA. If no such addresses exist, then - no type-7 LSA's with the P-bit set should originate from this - router. */ - - /* kevinm: not updating lsa anymore, just new */ - extlsa = (struct as_external_lsa *)(new->data); - - if (extlsa->e[0].fwd_addr.s_addr == 0) - extlsa->e[0].fwd_addr = ospf_get_nssa_ip(area); /* this NSSA area in ifp */ - - if (extlsa->e[0].fwd_addr.s_addr == 0) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("LSA[Type-7]: Could not build FWD-ADDR"); - ospf_lsa_discard (new); - return; - } - } - - /* install also as Type-7 */ - ospf_lsa_install (ospf, NULL, new); /* Remove Old, Lock New = 2 */ - - /* will send each copy, lock=2+n */ - ospf_flood_through_as (ospf, NULL, new); /* all attached NSSA's, no AS/STUBs */ - } +static void ospf_install_flood_nssa(struct ospf *ospf, struct ospf_lsa *lsa, + struct external_info *ei) +{ + struct ospf_lsa *new; + struct as_external_lsa *extlsa; + struct ospf_area *area; + struct listnode *node, *nnode; + + /* LSA may be a Type-5 originated via translation of a Type-7 LSA + * which originated from an NSSA area. In which case it should not be + * flooded back to NSSA areas. + */ + if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) + return; + + /* NSSA Originate or Refresh (If anyNSSA) + + LSA is self-originated. And just installed as Type-5. + Additionally, install as Type-7 LSDB for every attached NSSA. + + P-Bit controls which ABR performs translation to outside world; If + we are an ABR....do not set the P-bit, because we send the Type-5, + not as the ABR Translator, but as the ASBR owner within the AS! + + If we are NOT ABR, Flood through NSSA as Type-7 w/P-bit set. The + elected ABR Translator will see the P-bit, Translate, and re-flood. + + Later, ABR_TASK and P-bit will scan Type-7 LSDB and translate to + Type-5's to non-NSSA Areas. (it will also attempt a re-install) */ + + for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { + /* Don't install Type-7 LSA's into nonNSSA area */ + if (area->external_routing != OSPF_AREA_NSSA) + continue; + + /* make lsa duplicate, lock=1 */ + new = ospf_lsa_dup(lsa); + new->area = area; + new->data->type = OSPF_AS_NSSA_LSA; + + /* set P-bit if not ABR */ + if (!IS_OSPF_ABR(ospf)) { + SET_FLAG(new->data->options, OSPF_OPTION_NP); + + /* set non-zero FWD ADDR + + draft-ietf-ospf-nssa-update-09.txt + + if the network between the NSSA AS boundary router and + the + adjacent AS is advertised into OSPF as an internal OSPF + route, + the forwarding address should be the next op address as + is cu + currently done with type-5 LSAs. If the intervening + network is + not adversited into OSPF as an internal OSPF route and + the + type-7 LSA's P-bit is set a forwarding address should be + selected from one of the router's active OSPF inteface + addresses + which belong to the NSSA. If no such addresses exist, + then + no type-7 LSA's with the P-bit set should originate from + this + router. */ + + /* kevinm: not updating lsa anymore, just new */ + extlsa = (struct as_external_lsa *)(new->data); + + if (extlsa->e[0].fwd_addr.s_addr == 0) + extlsa->e[0].fwd_addr = ospf_get_nssa_ip( + area); /* this NSSA area in ifp */ + + if (extlsa->e[0].fwd_addr.s_addr == 0) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "LSA[Type-7]: Could not build FWD-ADDR"); + ospf_lsa_discard(new); + return; + } + } + + /* install also as Type-7 */ + ospf_lsa_install(ospf, NULL, + new); /* Remove Old, Lock New = 2 */ + + /* will send each copy, lock=2+n */ + ospf_flood_through_as( + ospf, NULL, new); /* all attached NSSA's, no AS/STUBs */ + } } -static struct ospf_lsa * -ospf_lsa_translated_nssa_new (struct ospf *ospf, - struct ospf_lsa *type7) -{ - - struct ospf_lsa *new; - struct as_external_lsa *ext, *extnew; - struct external_info ei; - - ext = (struct as_external_lsa *)(type7->data); - - /* need external_info struct, fill in bare minimum */ - ei.p.family = AF_INET; - ei.p.prefix = type7->data->id; - ei.p.prefixlen = ip_masklen (ext->mask); - ei.type = ZEBRA_ROUTE_OSPF; - ei.nexthop = ext->header.adv_router; - ei.route_map_set.metric = -1; - ei.route_map_set.metric_type = -1; - ei.tag = 0; - - if ( (new = ospf_external_lsa_new (ospf, &ei, &type7->data->id)) == NULL) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_nssa_translate_originate(): Could not originate " - "Translated Type-5 for %s", - inet_ntoa (ei.p.prefix)); - return NULL; - } - - extnew = (struct as_external_lsa *)(new->data); - - /* copy over Type-7 data to new */ - extnew->e[0].tos = ext->e[0].tos; - extnew->e[0].route_tag = ext->e[0].route_tag; - extnew->e[0].fwd_addr.s_addr = ext->e[0].fwd_addr.s_addr; - new->data->ls_seqnum = type7->data->ls_seqnum; - - /* add translated flag, checksum and lock new lsa */ - SET_FLAG (new->flags, OSPF_LSA_LOCAL_XLT); /* Translated from 7 */ - new = ospf_lsa_lock (new); - - return new; +static struct ospf_lsa *ospf_lsa_translated_nssa_new(struct ospf *ospf, + struct ospf_lsa *type7) +{ + + struct ospf_lsa *new; + struct as_external_lsa *ext, *extnew; + struct external_info ei; + + ext = (struct as_external_lsa *)(type7->data); + + /* need external_info struct, fill in bare minimum */ + ei.p.family = AF_INET; + ei.p.prefix = type7->data->id; + ei.p.prefixlen = ip_masklen(ext->mask); + ei.type = ZEBRA_ROUTE_OSPF; + ei.nexthop = ext->header.adv_router; + ei.route_map_set.metric = -1; + ei.route_map_set.metric_type = -1; + ei.tag = 0; + + if ((new = ospf_external_lsa_new(ospf, &ei, &type7->data->id)) + == NULL) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_nssa_translate_originate(): Could not originate " + "Translated Type-5 for %s", + inet_ntoa(ei.p.prefix)); + return NULL; + } + + extnew = (struct as_external_lsa *)(new->data); + + /* copy over Type-7 data to new */ + extnew->e[0].tos = ext->e[0].tos; + extnew->e[0].route_tag = ext->e[0].route_tag; + extnew->e[0].fwd_addr.s_addr = ext->e[0].fwd_addr.s_addr; + new->data->ls_seqnum = type7->data->ls_seqnum; + + /* add translated flag, checksum and lock new lsa */ + SET_FLAG(new->flags, OSPF_LSA_LOCAL_XLT); /* Translated from 7 */ + new = ospf_lsa_lock(new); + + return new; } /* Originate Translated Type-5 for supplied Type-7 NSSA LSA */ -struct ospf_lsa * -ospf_translated_nssa_originate (struct ospf *ospf, struct ospf_lsa *type7) -{ - struct ospf_lsa *new; - struct as_external_lsa *extnew; - - /* we cant use ospf_external_lsa_originate() as we need to set - * the OSPF_LSA_LOCAL_XLT flag, must originate by hand - */ - - if ( (new = ospf_lsa_translated_nssa_new (ospf, type7)) == NULL) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_translated_nssa_originate(): Could not translate " - "Type-7, Id %s, to Type-5", - inet_ntoa (type7->data->id)); - return NULL; - } - - extnew = (struct as_external_lsa *)new; - - if (IS_DEBUG_OSPF_NSSA) - { - zlog_debug ("ospf_translated_nssa_originate(): " - "translated Type 7, installed:"); - ospf_lsa_header_dump (new->data); - zlog_debug (" Network mask: %d",ip_masklen (extnew->mask)); - zlog_debug (" Forward addr: %s", inet_ntoa (extnew->e[0].fwd_addr)); - } - - if ( (new = ospf_lsa_install (ospf, NULL, new)) == NULL) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_lsa_translated_nssa_originate(): " - "Could not install LSA " - "id %s", inet_ntoa (type7->data->id)); - return NULL; - } - - ospf->lsa_originate_count++; - ospf_flood_through_as (ospf, NULL, new); - - return new; +struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf, + struct ospf_lsa *type7) +{ + struct ospf_lsa *new; + struct as_external_lsa *extnew; + + /* we cant use ospf_external_lsa_originate() as we need to set + * the OSPF_LSA_LOCAL_XLT flag, must originate by hand + */ + + if ((new = ospf_lsa_translated_nssa_new(ospf, type7)) == NULL) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_translated_nssa_originate(): Could not translate " + "Type-7, Id %s, to Type-5", + inet_ntoa(type7->data->id)); + return NULL; + } + + extnew = (struct as_external_lsa *)new; + + if (IS_DEBUG_OSPF_NSSA) { + zlog_debug( + "ospf_translated_nssa_originate(): " + "translated Type 7, installed:"); + ospf_lsa_header_dump(new->data); + zlog_debug(" Network mask: %d", ip_masklen(extnew->mask)); + zlog_debug(" Forward addr: %s", + inet_ntoa(extnew->e[0].fwd_addr)); + } + + if ((new = ospf_lsa_install(ospf, NULL, new)) == NULL) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_lsa_translated_nssa_originate(): " + "Could not install LSA " + "id %s", + inet_ntoa(type7->data->id)); + return NULL; + } + + ospf->lsa_originate_count++; + ospf_flood_through_as(ospf, NULL, new); + + return new; } /* Refresh Translated from NSSA AS-external-LSA. */ -struct ospf_lsa * -ospf_translated_nssa_refresh (struct ospf *ospf, struct ospf_lsa *type7, - struct ospf_lsa *type5) -{ - struct ospf_lsa *new = NULL; - - /* Sanity checks. */ - assert (type7 || type5); - if (!(type7 || type5)) - return NULL; - if (type7) - assert (type7->data); - if (type5) - assert (type5->data); - assert (ospf->anyNSSA); - - /* get required data according to what has been given */ - if (type7 && type5 == NULL) - { - /* find the translated Type-5 for this Type-7 */ - struct as_external_lsa *ext = (struct as_external_lsa *)(type7->data); - struct prefix_ipv4 p = - { - .prefix = type7->data->id, - .prefixlen = ip_masklen (ext->mask), - .family = AF_INET, - }; - - type5 = ospf_external_info_find_lsa (ospf, &p); - } - else if (type5 && type7 == NULL) - { - /* find the type-7 from which supplied type-5 was translated, - * ie find first type-7 with same LSA Id. - */ - struct listnode *ln, *lnn; - struct route_node *rn; - struct ospf_lsa *lsa; - struct ospf_area *area; - - for (ALL_LIST_ELEMENTS (ospf->areas, ln, lnn, area)) - { - if (area->external_routing != OSPF_AREA_NSSA - && !type7) - continue; - - LSDB_LOOP (NSSA_LSDB(area), rn, lsa) - { - if (lsa->data->id.s_addr == type5->data->id.s_addr) - { - type7 = lsa; - break; - } - } - } - } - - /* do we have type7? */ - if (!type7) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_translated_nssa_refresh(): no Type-7 found for " - "Type-5 LSA Id %s", - inet_ntoa (type5->data->id)); - return NULL; - } - - /* do we have valid translated type5? */ - if (type5 == NULL || !CHECK_FLAG (type5->flags, OSPF_LSA_LOCAL_XLT) ) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_translated_nssa_refresh(): No translated Type-5 " - "found for Type-7 with Id %s", - inet_ntoa (type7->data->id)); - return NULL; - } - - /* Delete LSA from neighbor retransmit-list. */ - ospf_ls_retransmit_delete_nbr_as (ospf, type5); - - /* create new translated LSA */ - if ( (new = ospf_lsa_translated_nssa_new (ospf, type7)) == NULL) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_translated_nssa_refresh(): Could not translate " - "Type-7 for %s to Type-5", - inet_ntoa (type7->data->id)); - return NULL; - } - - if ( !(new = ospf_lsa_install (ospf, NULL, new)) ) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_translated_nssa_refresh(): Could not install " - "translated LSA, Id %s", - inet_ntoa (type7->data->id)); - return NULL; - } - - /* Flood LSA through area. */ - ospf_flood_through_as (ospf, NULL, new); - - return new; -} - -int -is_prefix_default (struct prefix_ipv4 *p) -{ - struct prefix_ipv4 q; - - q.family = AF_INET; - q.prefix.s_addr = 0; - q.prefixlen = 0; - - return prefix_same ((struct prefix *) p, (struct prefix *) &q); +struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf, + struct ospf_lsa *type7, + struct ospf_lsa *type5) +{ + struct ospf_lsa *new = NULL; + + /* Sanity checks. */ + assert(type7 || type5); + if (!(type7 || type5)) + return NULL; + if (type7) + assert(type7->data); + if (type5) + assert(type5->data); + assert(ospf->anyNSSA); + + /* get required data according to what has been given */ + if (type7 && type5 == NULL) { + /* find the translated Type-5 for this Type-7 */ + struct as_external_lsa *ext = + (struct as_external_lsa *)(type7->data); + struct prefix_ipv4 p = { + .prefix = type7->data->id, + .prefixlen = ip_masklen(ext->mask), + .family = AF_INET, + }; + + type5 = ospf_external_info_find_lsa(ospf, &p); + } else if (type5 && type7 == NULL) { + /* find the type-7 from which supplied type-5 was translated, + * ie find first type-7 with same LSA Id. + */ + struct listnode *ln, *lnn; + struct route_node *rn; + struct ospf_lsa *lsa; + struct ospf_area *area; + + for (ALL_LIST_ELEMENTS(ospf->areas, ln, lnn, area)) { + if (area->external_routing != OSPF_AREA_NSSA && !type7) + continue; + + LSDB_LOOP(NSSA_LSDB(area), rn, lsa) + { + if (lsa->data->id.s_addr + == type5->data->id.s_addr) { + type7 = lsa; + break; + } + } + } + } + + /* do we have type7? */ + if (!type7) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_translated_nssa_refresh(): no Type-7 found for " + "Type-5 LSA Id %s", + inet_ntoa(type5->data->id)); + return NULL; + } + + /* do we have valid translated type5? */ + if (type5 == NULL || !CHECK_FLAG(type5->flags, OSPF_LSA_LOCAL_XLT)) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_translated_nssa_refresh(): No translated Type-5 " + "found for Type-7 with Id %s", + inet_ntoa(type7->data->id)); + return NULL; + } + + /* Delete LSA from neighbor retransmit-list. */ + ospf_ls_retransmit_delete_nbr_as(ospf, type5); + + /* create new translated LSA */ + if ((new = ospf_lsa_translated_nssa_new(ospf, type7)) == NULL) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_translated_nssa_refresh(): Could not translate " + "Type-7 for %s to Type-5", + inet_ntoa(type7->data->id)); + return NULL; + } + + if (!(new = ospf_lsa_install(ospf, NULL, new))) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_translated_nssa_refresh(): Could not install " + "translated LSA, Id %s", + inet_ntoa(type7->data->id)); + return NULL; + } + + /* Flood LSA through area. */ + ospf_flood_through_as(ospf, NULL, new); + + return new; +} + +int is_prefix_default(struct prefix_ipv4 *p) +{ + struct prefix_ipv4 q; + + q.family = AF_INET; + q.prefix.s_addr = 0; + q.prefixlen = 0; + + return prefix_same((struct prefix *)p, (struct prefix *)&q); } /* Originate an AS-external-LSA, install and flood. */ -struct ospf_lsa * -ospf_external_lsa_originate (struct ospf *ospf, struct external_info *ei) -{ - struct ospf_lsa *new; - - /* Added for NSSA project.... - - External LSAs are originated in ASBRs as usual, but for NSSA systems. - there is the global Type-5 LSDB and a Type-7 LSDB installed for - every area. The Type-7's are flooded to every IR and every ABR; We - install the Type-5 LSDB so that the normal "refresh" code operates - as usual, and flag them as not used during ASE calculations. The - Type-7 LSDB is used for calculations. Each Type-7 has a Forwarding - Address of non-zero. - - If an ABR is the elected NSSA translator, following SPF and during - the ABR task it will translate all the scanned Type-7's, with P-bit - ON and not-self generated, and translate to Type-5's throughout the - non-NSSA/STUB AS. - - A difference in operation depends whether this ASBR is an ABR - or not. If not an ABR, the P-bit is ON, to indicate that any - elected NSSA-ABR can perform its translation. - - If an ABR, the P-bit is OFF; No ABR will perform translation and - this ASBR will flood the Type-5 LSA as usual. - - For the case where this ASBR is not an ABR, the ASE calculations - are based on the Type-5 LSDB; The Type-7 LSDB exists just to - demonstrate to the user that there are LSA's that belong to any - attached NSSA. - - Finally, it just so happens that when the ABR is translating every - Type-7 into Type-5, it installs it into the Type-5 LSDB as an - approved Type-5 (translated from Type-7); at the end of translation - if any Translated Type-5's remain unapproved, then they must be - flushed from the AS. - - */ - - /* Check the AS-external-LSA should be originated. */ - if (!ospf_redistribute_check (ospf, ei, NULL)) - return NULL; - - /* Create new AS-external-LSA instance. */ - if ((new = ospf_external_lsa_new (ospf, ei, NULL)) == NULL) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[Type5:%s]: Could not originate AS-external-LSA", - inet_ntoa (ei->p.prefix)); - return NULL; - } - - /* Install newly created LSA into Type-5 LSDB, lock = 1. */ - ospf_lsa_install (ospf, NULL, new); - - /* Update LSA origination count. */ - ospf->lsa_originate_count++; - - /* Flooding new LSA. only to AS (non-NSSA/STUB) */ - ospf_flood_through_as (ospf, NULL, new); - - /* If there is any attached NSSA, do special handling */ - if (ospf->anyNSSA && - /* stay away from translated LSAs! */ - !(CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT))) - ospf_install_flood_nssa (ospf, new, ei); /* Install/Flood Type-7 to all NSSAs */ - - /* Debug logging. */ - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - { - zlog_debug ("LSA[Type%d:%s]: Originate AS-external-LSA %p", - new->data->type, inet_ntoa (new->data->id), (void *)new); - ospf_lsa_header_dump (new->data); - } - - return new; +struct ospf_lsa *ospf_external_lsa_originate(struct ospf *ospf, + struct external_info *ei) +{ + struct ospf_lsa *new; + + /* Added for NSSA project.... + + External LSAs are originated in ASBRs as usual, but for NSSA + systems. + there is the global Type-5 LSDB and a Type-7 LSDB installed for + every area. The Type-7's are flooded to every IR and every ABR; We + install the Type-5 LSDB so that the normal "refresh" code operates + as usual, and flag them as not used during ASE calculations. The + Type-7 LSDB is used for calculations. Each Type-7 has a Forwarding + Address of non-zero. + + If an ABR is the elected NSSA translator, following SPF and during + the ABR task it will translate all the scanned Type-7's, with P-bit + ON and not-self generated, and translate to Type-5's throughout the + non-NSSA/STUB AS. + + A difference in operation depends whether this ASBR is an ABR + or not. If not an ABR, the P-bit is ON, to indicate that any + elected NSSA-ABR can perform its translation. + + If an ABR, the P-bit is OFF; No ABR will perform translation and + this ASBR will flood the Type-5 LSA as usual. + + For the case where this ASBR is not an ABR, the ASE calculations + are based on the Type-5 LSDB; The Type-7 LSDB exists just to + demonstrate to the user that there are LSA's that belong to any + attached NSSA. + + Finally, it just so happens that when the ABR is translating every + Type-7 into Type-5, it installs it into the Type-5 LSDB as an + approved Type-5 (translated from Type-7); at the end of translation + if any Translated Type-5's remain unapproved, then they must be + flushed from the AS. + + */ + + /* Check the AS-external-LSA should be originated. */ + if (!ospf_redistribute_check(ospf, ei, NULL)) + return NULL; + + /* Create new AS-external-LSA instance. */ + if ((new = ospf_external_lsa_new(ospf, ei, NULL)) == NULL) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[Type5:%s]: Could not originate AS-external-LSA", + inet_ntoa(ei->p.prefix)); + return NULL; + } + + /* Install newly created LSA into Type-5 LSDB, lock = 1. */ + ospf_lsa_install(ospf, NULL, new); + + /* Update LSA origination count. */ + ospf->lsa_originate_count++; + + /* Flooding new LSA. only to AS (non-NSSA/STUB) */ + ospf_flood_through_as(ospf, NULL, new); + + /* If there is any attached NSSA, do special handling */ + if (ospf->anyNSSA && + /* stay away from translated LSAs! */ + !(CHECK_FLAG(new->flags, OSPF_LSA_LOCAL_XLT))) + ospf_install_flood_nssa( + ospf, new, ei); /* Install/Flood Type-7 to all NSSAs */ + + /* Debug logging. */ + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug("LSA[Type%d:%s]: Originate AS-external-LSA %p", + new->data->type, inet_ntoa(new->data->id), + (void *)new); + ospf_lsa_header_dump(new->data); + } + + return new; } /* Originate AS-external-LSA from external info with initial flag. */ -int -ospf_external_lsa_originate_timer (struct thread *thread) -{ - struct ospf *ospf = THREAD_ARG (thread); - struct route_node *rn; - struct external_info *ei; - struct route_table *rt; - int type = THREAD_VAL (thread); - struct list *ext_list; - struct listnode *node; - struct ospf_external *ext; - - ospf->t_external_lsa = NULL; - - ext_list = om->external[type]; - if (!ext_list) - return 0; - - for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) - /* Originate As-external-LSA from all type of distribute source. */ - if ((rt = ext->external_info)) - for (rn = route_top (rt); rn; rn = route_next (rn)) - if ((ei = rn->info) != NULL) - if (!is_prefix_default ((struct prefix_ipv4 *)&ei->p)) - if (!ospf_external_lsa_originate (ospf, ei)) - zlog_warn ("LSA: AS-external-LSA was not originated."); - - return 0; -} - -static struct external_info * -ospf_default_external_info (struct ospf *ospf) -{ - int type; - struct route_node *rn; - struct prefix_ipv4 p; - - p.family = AF_INET; - p.prefix.s_addr = 0; - p.prefixlen = 0; - - /* First, lookup redistributed default route. */ - for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) - { - struct list *ext_list; - struct listnode *node; - struct ospf_external *ext; - - if (type == ZEBRA_ROUTE_OSPF) - continue; - - ext_list = om->external[type]; - if (!ext_list) - continue; - - for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) - { - rn = route_node_lookup (ext->external_info, (struct prefix *) &p); - if (rn != NULL) - { - route_unlock_node (rn); - assert (rn->info); - if (ospf_redistribute_check (ospf, rn->info, NULL)) - return rn->info; - } - } - } - - return NULL; -} - -int -ospf_default_originate_timer (struct thread *thread) -{ - struct prefix_ipv4 p; - struct in_addr nexthop; - struct external_info *ei; - struct ospf *ospf; - - ospf = THREAD_ARG (thread); - - p.family = AF_INET; - p.prefix.s_addr = 0; - p.prefixlen = 0; - - if (ospf->default_originate == DEFAULT_ORIGINATE_ALWAYS) - { - /* If there is no default route via redistribute, - then originate AS-external-LSA with nexthop 0 (self). */ - nexthop.s_addr = 0; - ospf_external_info_add (DEFAULT_ROUTE, 0, p, 0, nexthop, 0); - } - - if ((ei = ospf_default_external_info (ospf))) - ospf_external_lsa_originate (ospf, ei); - - return 0; +int ospf_external_lsa_originate_timer(struct thread *thread) +{ + struct ospf *ospf = THREAD_ARG(thread); + struct route_node *rn; + struct external_info *ei; + struct route_table *rt; + int type = THREAD_VAL(thread); + struct list *ext_list; + struct listnode *node; + struct ospf_external *ext; + + ospf->t_external_lsa = NULL; + + ext_list = om->external[type]; + if (!ext_list) + return 0; + + for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) + /* Originate As-external-LSA from all type of distribute source. + */ + if ((rt = ext->external_info)) + for (rn = route_top(rt); rn; rn = route_next(rn)) + if ((ei = rn->info) != NULL) + if (!is_prefix_default( + (struct prefix_ipv4 *)&ei + ->p)) + if (!ospf_external_lsa_originate( + ospf, ei)) + zlog_warn( + "LSA: AS-external-LSA was not originated."); + + return 0; +} + +static struct external_info *ospf_default_external_info(struct ospf *ospf) +{ + int type; + struct route_node *rn; + struct prefix_ipv4 p; + + p.family = AF_INET; + p.prefix.s_addr = 0; + p.prefixlen = 0; + + /* First, lookup redistributed default route. */ + for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { + struct list *ext_list; + struct listnode *node; + struct ospf_external *ext; + + if (type == ZEBRA_ROUTE_OSPF) + continue; + + ext_list = om->external[type]; + if (!ext_list) + continue; + + for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) { + rn = route_node_lookup(ext->external_info, + (struct prefix *)&p); + if (rn != NULL) { + route_unlock_node(rn); + assert(rn->info); + if (ospf_redistribute_check(ospf, rn->info, + NULL)) + return rn->info; + } + } + } + + return NULL; +} + +int ospf_default_originate_timer(struct thread *thread) +{ + struct prefix_ipv4 p; + struct in_addr nexthop; + struct external_info *ei; + struct ospf *ospf; + + ospf = THREAD_ARG(thread); + + p.family = AF_INET; + p.prefix.s_addr = 0; + p.prefixlen = 0; + + if (ospf->default_originate == DEFAULT_ORIGINATE_ALWAYS) { + /* If there is no default route via redistribute, + then originate AS-external-LSA with nexthop 0 (self). */ + nexthop.s_addr = 0; + ospf_external_info_add(DEFAULT_ROUTE, 0, p, 0, nexthop, 0); + } + + if ((ei = ospf_default_external_info(ospf))) + ospf_external_lsa_originate(ospf, ei); + + return 0; } /* Flush any NSSA LSAs for given prefix */ -void -ospf_nssa_lsa_flush (struct ospf *ospf, struct prefix_ipv4 *p) -{ - struct listnode *node, *nnode; - struct ospf_lsa *lsa; - struct ospf_area *area; - - for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) - { - if (area->external_routing == OSPF_AREA_NSSA) - { - if (!(lsa = ospf_lsa_lookup (area, OSPF_AS_NSSA_LSA, p->prefix, - ospf->router_id))) - { - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("LSA: There is no such AS-NSSA-LSA %s/%d in LSDB", - inet_ntoa (p->prefix), p->prefixlen); - continue; - } - ospf_ls_retransmit_delete_nbr_area (area, lsa); - if (!IS_LSA_MAXAGE (lsa)) - { - ospf_refresher_unregister_lsa (ospf, lsa); - ospf_lsa_flush_area (lsa, area); - } - } - } +void ospf_nssa_lsa_flush(struct ospf *ospf, struct prefix_ipv4 *p) +{ + struct listnode *node, *nnode; + struct ospf_lsa *lsa; + struct ospf_area *area; + + for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { + if (area->external_routing == OSPF_AREA_NSSA) { + if (!(lsa = ospf_lsa_lookup(area, OSPF_AS_NSSA_LSA, + p->prefix, + ospf->router_id))) { + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug( + "LSA: There is no such AS-NSSA-LSA %s/%d in LSDB", + inet_ntoa(p->prefix), + p->prefixlen); + continue; + } + ospf_ls_retransmit_delete_nbr_area(area, lsa); + if (!IS_LSA_MAXAGE(lsa)) { + ospf_refresher_unregister_lsa(ospf, lsa); + ospf_lsa_flush_area(lsa, area); + } + } + } } /* Flush an AS-external-LSA from LSDB and routing domain. */ -void -ospf_external_lsa_flush (struct ospf *ospf, - u_char type, struct prefix_ipv4 *p, - ifindex_t ifindex /*, struct in_addr nexthop */) -{ - struct ospf_lsa *lsa; - - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("LSA: Flushing AS-external-LSA %s/%d", - inet_ntoa (p->prefix), p->prefixlen); - - /* First lookup LSA from LSDB. */ - if (!(lsa = ospf_external_info_find_lsa (ospf, p))) - { - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("LSA: There is no such AS-external-LSA %s/%d in LSDB", - inet_ntoa (p->prefix), p->prefixlen); - return; - } - - /* If LSA is selforiginated, not a translated LSA, and there is - * NSSA area, flush Type-7 LSA's at first. - */ - if (IS_LSA_SELF(lsa) && (ospf->anyNSSA) - && !(CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))) - ospf_nssa_lsa_flush (ospf, p); - - /* Sweep LSA from Link State Retransmit List. */ - ospf_ls_retransmit_delete_nbr_as (ospf, lsa); - - /* There must be no self-originated LSA in rtrs_external. */ +void ospf_external_lsa_flush(struct ospf *ospf, u_char type, + struct prefix_ipv4 *p, + ifindex_t ifindex /*, struct in_addr nexthop */) +{ + struct ospf_lsa *lsa; + + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug("LSA: Flushing AS-external-LSA %s/%d", + inet_ntoa(p->prefix), p->prefixlen); + + /* First lookup LSA from LSDB. */ + if (!(lsa = ospf_external_info_find_lsa(ospf, p))) { + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug( + "LSA: There is no such AS-external-LSA %s/%d in LSDB", + inet_ntoa(p->prefix), p->prefixlen); + return; + } + + /* If LSA is selforiginated, not a translated LSA, and there is + * NSSA area, flush Type-7 LSA's at first. + */ + if (IS_LSA_SELF(lsa) && (ospf->anyNSSA) + && !(CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT))) + ospf_nssa_lsa_flush(ospf, p); + + /* Sweep LSA from Link State Retransmit List. */ + ospf_ls_retransmit_delete_nbr_as(ospf, lsa); + +/* There must be no self-originated LSA in rtrs_external. */ #if 0 /* Remove External route from Zebra. */ ospf_zebra_delete ((struct prefix_ipv4 *) p, &nexthop); #endif - if (!IS_LSA_MAXAGE (lsa)) - { - /* Unregister LSA from Refresh queue. */ - ospf_refresher_unregister_lsa (ospf, lsa); - - /* Flush AS-external-LSA through AS. */ - ospf_lsa_flush_as (ospf, lsa); - } - - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("ospf_external_lsa_flush(): stop"); -} - -void -ospf_external_lsa_refresh_default (struct ospf *ospf) -{ - struct prefix_ipv4 p; - struct external_info *ei; - struct ospf_lsa *lsa; - - p.family = AF_INET; - p.prefixlen = 0; - p.prefix.s_addr = 0; - - ei = ospf_default_external_info (ospf); - lsa = ospf_external_info_find_lsa (ospf, &p); - - if (ei) - { - if (lsa) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p", - (void *)lsa); - ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_FORCE); - } - else - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[Type5:0.0.0.0]: Originate AS-external-LSA"); - ospf_external_lsa_originate (ospf, ei); - } - } - else - { - if (lsa) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[Type5:0.0.0.0]: Flush AS-external-LSA"); - ospf_refresher_unregister_lsa (ospf, lsa); - ospf_lsa_flush_as (ospf, lsa); - } - } -} - -void -ospf_external_lsa_refresh_type (struct ospf *ospf, u_char type, u_short instance, - int force) -{ - struct route_node *rn; - struct external_info *ei; - struct ospf_external *ext; - - if (type != DEFAULT_ROUTE) - if ((ext = ospf_external_lookup(type, instance)) && - EXTERNAL_INFO (ext)) - /* Refresh each redistributed AS-external-LSAs. */ - for (rn = route_top (EXTERNAL_INFO (ext)); rn; rn = route_next (rn)) - if ((ei = rn->info)) - if (!is_prefix_default (&ei->p)) - { - struct ospf_lsa *lsa; - - if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p))) - ospf_external_lsa_refresh (ospf, lsa, ei, force); - else - ospf_external_lsa_originate (ospf, ei); - } + if (!IS_LSA_MAXAGE(lsa)) { + /* Unregister LSA from Refresh queue. */ + ospf_refresher_unregister_lsa(ospf, lsa); + + /* Flush AS-external-LSA through AS. */ + ospf_lsa_flush_as(ospf, lsa); + } + + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug("ospf_external_lsa_flush(): stop"); +} + +void ospf_external_lsa_refresh_default(struct ospf *ospf) +{ + struct prefix_ipv4 p; + struct external_info *ei; + struct ospf_lsa *lsa; + + p.family = AF_INET; + p.prefixlen = 0; + p.prefix.s_addr = 0; + + ei = ospf_default_external_info(ospf); + lsa = ospf_external_info_find_lsa(ospf, &p); + + if (ei) { + if (lsa) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p", + (void *)lsa); + ospf_external_lsa_refresh(ospf, lsa, ei, + LSA_REFRESH_FORCE); + } else { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[Type5:0.0.0.0]: Originate AS-external-LSA"); + ospf_external_lsa_originate(ospf, ei); + } + } else { + if (lsa) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[Type5:0.0.0.0]: Flush AS-external-LSA"); + ospf_refresher_unregister_lsa(ospf, lsa); + ospf_lsa_flush_as(ospf, lsa); + } + } +} + +void ospf_external_lsa_refresh_type(struct ospf *ospf, u_char type, + u_short instance, int force) +{ + struct route_node *rn; + struct external_info *ei; + struct ospf_external *ext; + + if (type != DEFAULT_ROUTE) + if ((ext = ospf_external_lookup(type, instance)) + && EXTERNAL_INFO(ext)) + /* Refresh each redistributed AS-external-LSAs. */ + for (rn = route_top(EXTERNAL_INFO(ext)); rn; + rn = route_next(rn)) + if ((ei = rn->info)) + if (!is_prefix_default(&ei->p)) { + struct ospf_lsa *lsa; + + if ((lsa = ospf_external_info_find_lsa( + ospf, &ei->p))) + ospf_external_lsa_refresh( + ospf, lsa, ei, + force); + else + ospf_external_lsa_originate( + ospf, ei); + } } /* Refresh AS-external-LSA. */ -struct ospf_lsa * -ospf_external_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa, - struct external_info *ei, int force) -{ - struct ospf_lsa *new; - int changed; - - /* Check the AS-external-LSA should be originated. */ - if (!ospf_redistribute_check (ospf, ei, &changed)) - { - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type%d:%s]: Could not be refreshed, " - "redist check fail", - lsa->data->type, inet_ntoa (lsa->data->id)); - ospf_external_lsa_flush (ospf, ei->type, &ei->p, - ei->ifindex /*, ei->nexthop */); - return NULL; - } - - if (!changed && !force) - { - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type%d:%s]: Not refreshed, not changed/forced", - lsa->data->type, inet_ntoa (lsa->data->id)); - return NULL; - } - - /* Delete LSA from neighbor retransmit-list. */ - ospf_ls_retransmit_delete_nbr_as (ospf, lsa); - - /* Unregister AS-external-LSA from refresh-list. */ - ospf_refresher_unregister_lsa (ospf, lsa); - - new = ospf_external_lsa_new (ospf, ei, &lsa->data->id); - - if (new == NULL) - { - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type%d:%s]: Could not be refreshed", lsa->data->type, - inet_ntoa (lsa->data->id)); - return NULL; - } - - new->data->ls_seqnum = lsa_seqnum_increment (lsa); - - ospf_lsa_install (ospf, NULL, new); /* As type-5. */ - - /* Flood LSA through AS. */ - ospf_flood_through_as (ospf, NULL, new); - - /* If any attached NSSA, install as Type-7, flood to all NSSA Areas */ - if (ospf->anyNSSA && !(CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT))) - ospf_install_flood_nssa (ospf, new, ei); /* Install/Flood per new rules */ - - /* Register self-originated LSA to refresh queue. - * Translated LSAs should not be registered, but refreshed upon - * refresh of the Type-7 - */ - if ( !CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT) ) - ospf_refresher_register_lsa (ospf, new); - - /* Debug logging. */ - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - { - zlog_debug ("LSA[Type%d:%s]: AS-external-LSA refresh", - new->data->type, inet_ntoa (new->data->id)); - ospf_lsa_header_dump (new->data); - } - - return new; +struct ospf_lsa *ospf_external_lsa_refresh(struct ospf *ospf, + struct ospf_lsa *lsa, + struct external_info *ei, int force) +{ + struct ospf_lsa *new; + int changed; + + /* Check the AS-external-LSA should be originated. */ + if (!ospf_redistribute_check(ospf, ei, &changed)) { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type%d:%s]: Could not be refreshed, " + "redist check fail", + lsa->data->type, inet_ntoa(lsa->data->id)); + ospf_external_lsa_flush(ospf, ei->type, &ei->p, + ei->ifindex /*, ei->nexthop */); + return NULL; + } + + if (!changed && !force) { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type%d:%s]: Not refreshed, not changed/forced", + lsa->data->type, inet_ntoa(lsa->data->id)); + return NULL; + } + + /* Delete LSA from neighbor retransmit-list. */ + ospf_ls_retransmit_delete_nbr_as(ospf, lsa); + + /* Unregister AS-external-LSA from refresh-list. */ + ospf_refresher_unregister_lsa(ospf, lsa); + + new = ospf_external_lsa_new(ospf, ei, &lsa->data->id); + + if (new == NULL) { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug("LSA[Type%d:%s]: Could not be refreshed", + lsa->data->type, inet_ntoa(lsa->data->id)); + return NULL; + } + + new->data->ls_seqnum = lsa_seqnum_increment(lsa); + + ospf_lsa_install(ospf, NULL, new); /* As type-5. */ + + /* Flood LSA through AS. */ + ospf_flood_through_as(ospf, NULL, new); + + /* If any attached NSSA, install as Type-7, flood to all NSSA Areas */ + if (ospf->anyNSSA && !(CHECK_FLAG(new->flags, OSPF_LSA_LOCAL_XLT))) + ospf_install_flood_nssa(ospf, new, + ei); /* Install/Flood per new rules */ + + /* Register self-originated LSA to refresh queue. + * Translated LSAs should not be registered, but refreshed upon + * refresh of the Type-7 + */ + if (!CHECK_FLAG(new->flags, OSPF_LSA_LOCAL_XLT)) + ospf_refresher_register_lsa(ospf, new); + + /* Debug logging. */ + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug("LSA[Type%d:%s]: AS-external-LSA refresh", + new->data->type, inet_ntoa(new->data->id)); + ospf_lsa_header_dump(new->data); + } + + return new; } @@ -2378,114 +2336,109 @@ ospf_external_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa, /* Install router-LSA to an area. */ static struct ospf_lsa * -ospf_router_lsa_install (struct ospf *ospf, struct ospf_lsa *new, - int rt_recalc) +ospf_router_lsa_install(struct ospf *ospf, struct ospf_lsa *new, int rt_recalc) { - struct ospf_area *area = new->area; + struct ospf_area *area = new->area; - /* RFC 2328 Section 13.2 Router-LSAs and network-LSAs - The entire routing table must be recalculated, starting with - the shortest path calculations for each area (not just the - area whose link-state database has changed). - */ + /* RFC 2328 Section 13.2 Router-LSAs and network-LSAs + The entire routing table must be recalculated, starting with + the shortest path calculations for each area (not just the + area whose link-state database has changed). + */ - if (IS_LSA_SELF (new)) - { + if (IS_LSA_SELF(new)) { - /* Only install LSA if it is originated/refreshed by us. - * If LSA was received by flooding, the RECEIVED flag is set so do - * not link the LSA */ - if (CHECK_FLAG (new->flags, OSPF_LSA_RECEIVED)) - return new; /* ignore stale LSA */ + /* Only install LSA if it is originated/refreshed by us. + * If LSA was received by flooding, the RECEIVED flag is set so + * do + * not link the LSA */ + if (CHECK_FLAG(new->flags, OSPF_LSA_RECEIVED)) + return new; /* ignore stale LSA */ - /* Set self-originated router-LSA. */ - ospf_lsa_unlock (&area->router_lsa_self); - area->router_lsa_self = ospf_lsa_lock (new); + /* Set self-originated router-LSA. */ + ospf_lsa_unlock(&area->router_lsa_self); + area->router_lsa_self = ospf_lsa_lock(new); - ospf_refresher_register_lsa (ospf, new); - } - if (rt_recalc) - ospf_spf_calculate_schedule (ospf, SPF_FLAG_ROUTER_LSA_INSTALL); - return new; + ospf_refresher_register_lsa(ospf, new); + } + if (rt_recalc) + ospf_spf_calculate_schedule(ospf, SPF_FLAG_ROUTER_LSA_INSTALL); + return new; } -#define OSPF_INTERFACE_TIMER_ON(T,F,V) \ - if (!(T)) \ - (T) = thread_add_timer (master, (F), oi, (V)) +#define OSPF_INTERFACE_TIMER_ON(T, F, V) \ + if (!(T)) \ + (T) = thread_add_timer(master, (F), oi, (V)) /* Install network-LSA to an area. */ -static struct ospf_lsa * -ospf_network_lsa_install (struct ospf *ospf, - struct ospf_interface *oi, - struct ospf_lsa *new, - int rt_recalc) -{ - - /* RFC 2328 Section 13.2 Router-LSAs and network-LSAs - The entire routing table must be recalculated, starting with - the shortest path calculations for each area (not just the - area whose link-state database has changed). - */ - if (IS_LSA_SELF (new)) - { - /* We supposed that when LSA is originated by us, we pass the int - for which it was originated. If LSA was received by flooding, - the RECEIVED flag is set, so we do not link the LSA to the int. */ - if (CHECK_FLAG (new->flags, OSPF_LSA_RECEIVED)) - return new; /* ignore stale LSA */ - - ospf_lsa_unlock (&oi->network_lsa_self); - oi->network_lsa_self = ospf_lsa_lock (new); - ospf_refresher_register_lsa (ospf, new); - } - if (rt_recalc) - ospf_spf_calculate_schedule (ospf, SPF_FLAG_NETWORK_LSA_INSTALL); - - return new; +static struct ospf_lsa *ospf_network_lsa_install(struct ospf *ospf, + struct ospf_interface *oi, + struct ospf_lsa *new, + int rt_recalc) +{ + + /* RFC 2328 Section 13.2 Router-LSAs and network-LSAs + The entire routing table must be recalculated, starting with + the shortest path calculations for each area (not just the + area whose link-state database has changed). + */ + if (IS_LSA_SELF(new)) { + /* We supposed that when LSA is originated by us, we pass the + int + for which it was originated. If LSA was received by flooding, + the RECEIVED flag is set, so we do not link the LSA to the + int. */ + if (CHECK_FLAG(new->flags, OSPF_LSA_RECEIVED)) + return new; /* ignore stale LSA */ + + ospf_lsa_unlock(&oi->network_lsa_self); + oi->network_lsa_self = ospf_lsa_lock(new); + ospf_refresher_register_lsa(ospf, new); + } + if (rt_recalc) + ospf_spf_calculate_schedule(ospf, SPF_FLAG_NETWORK_LSA_INSTALL); + + return new; } /* Install summary-LSA to an area. */ static struct ospf_lsa * -ospf_summary_lsa_install (struct ospf *ospf, struct ospf_lsa *new, - int rt_recalc) -{ - if (rt_recalc && !IS_LSA_SELF (new)) - { - /* RFC 2328 Section 13.2 Summary-LSAs - The best route to the destination described by the summary- - LSA must be recalculated (see Section 16.5). If this - destination is an AS boundary router, it may also be - necessary to re-examine all the AS-external-LSAs. - */ +ospf_summary_lsa_install(struct ospf *ospf, struct ospf_lsa *new, int rt_recalc) +{ + if (rt_recalc && !IS_LSA_SELF(new)) { +/* RFC 2328 Section 13.2 Summary-LSAs + The best route to the destination described by the summary- + LSA must be recalculated (see Section 16.5). If this + destination is an AS boundary router, it may also be + necessary to re-examine all the AS-external-LSAs. +*/ #if 0 /* This doesn't exist yet... */ ospf_summary_incremental_update(new); */ -#else /* #if 0 */ - ospf_spf_calculate_schedule (ospf, SPF_FLAG_SUMMARY_LSA_INSTALL); +#else /* #if 0 */ + ospf_spf_calculate_schedule(ospf, SPF_FLAG_SUMMARY_LSA_INSTALL); #endif /* #if 0 */ - - } + } - if (IS_LSA_SELF (new)) - ospf_refresher_register_lsa (ospf, new); + if (IS_LSA_SELF(new)) + ospf_refresher_register_lsa(ospf, new); - return new; + return new; } /* Install ASBR-summary-LSA to an area. */ -static struct ospf_lsa * -ospf_summary_asbr_lsa_install (struct ospf *ospf, struct ospf_lsa *new, - int rt_recalc) -{ - if (rt_recalc && !IS_LSA_SELF (new)) - { - /* RFC 2328 Section 13.2 Summary-LSAs - The best route to the destination described by the summary- - LSA must be recalculated (see Section 16.5). If this - destination is an AS boundary router, it may also be - necessary to re-examine all the AS-external-LSAs. - */ +static struct ospf_lsa *ospf_summary_asbr_lsa_install(struct ospf *ospf, + struct ospf_lsa *new, + int rt_recalc) +{ + if (rt_recalc && !IS_LSA_SELF(new)) { +/* RFC 2328 Section 13.2 Summary-LSAs + The best route to the destination described by the summary- + LSA must be recalculated (see Section 16.5). If this + destination is an AS boundary router, it may also be + necessary to re-examine all the AS-external-LSAs. +*/ #if 0 /* These don't exist yet... */ ospf_summary_incremental_update(new); @@ -2493,428 +2446,421 @@ ospf_summary_asbr_lsa_install (struct ospf *ospf, struct ospf_lsa *new, - RFC 2328 Section 16.5 implies it should be */ /* ospf_ase_calculate_schedule(); */ #else /* #if 0 */ - ospf_spf_calculate_schedule (ospf, SPF_FLAG_ASBR_SUMMARY_LSA_INSTALL); + ospf_spf_calculate_schedule(ospf, + SPF_FLAG_ASBR_SUMMARY_LSA_INSTALL); #endif /* #if 0 */ - } + } - /* register LSA to refresh-list. */ - if (IS_LSA_SELF (new)) - ospf_refresher_register_lsa (ospf, new); + /* register LSA to refresh-list. */ + if (IS_LSA_SELF(new)) + ospf_refresher_register_lsa(ospf, new); - return new; + return new; } /* Install AS-external-LSA. */ -static struct ospf_lsa * -ospf_external_lsa_install (struct ospf *ospf, struct ospf_lsa *new, - int rt_recalc) -{ - ospf_ase_register_external_lsa (new, ospf); - /* If LSA is not self-originated, calculate an external route. */ - if (rt_recalc) - { - /* RFC 2328 Section 13.2 AS-external-LSAs - The best route to the destination described by the AS- - external-LSA must be recalculated (see Section 16.6). - */ - - if (!IS_LSA_SELF (new)) - ospf_ase_incremental_update (ospf, new); - } - - if (new->data->type == OSPF_AS_NSSA_LSA) - { - /* There is no point to register selforiginate Type-7 LSA for - * refreshing. We rely on refreshing Type-5 LSA's - */ - if (IS_LSA_SELF (new)) - return new; - else - { - /* Try refresh type-5 translated LSA for this LSA, if one exists. - * New translations will be taken care of by the abr_task. - */ - ospf_translated_nssa_refresh (ospf, new, NULL); - } - } - - /* Register self-originated LSA to refresh queue. - * Leave Translated LSAs alone if NSSA is enabled - */ - if (IS_LSA_SELF (new) && !CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT ) ) - ospf_refresher_register_lsa (ospf, new); - - return new; -} - -void -ospf_discard_from_db (struct ospf *ospf, - struct ospf_lsdb *lsdb, struct ospf_lsa *lsa) -{ - struct ospf_lsa *old; - - if (!lsdb) - { - zlog_warn ("%s: Called with NULL lsdb!", __func__); - if (!lsa) - zlog_warn ("%s: and NULL LSA!", __func__); - else - zlog_warn ("LSA[Type%d:%s]: not associated with LSDB!", - lsa->data->type, inet_ntoa (lsa->data->id)); - return; - } - - old = ospf_lsdb_lookup (lsdb, lsa); - - if (!old) - return; - - if (old->refresh_list >= 0) - ospf_refresher_unregister_lsa (ospf, old); - - switch (old->data->type) - { - case OSPF_AS_EXTERNAL_LSA: - ospf_ase_unregister_external_lsa (old, ospf); - ospf_ls_retransmit_delete_nbr_as (ospf, old); - break; - case OSPF_OPAQUE_AS_LSA: - ospf_ls_retransmit_delete_nbr_as (ospf, old); - break; - case OSPF_AS_NSSA_LSA: - ospf_ls_retransmit_delete_nbr_area (old->area, old); - ospf_ase_unregister_external_lsa (old, ospf); - break; - default: - ospf_ls_retransmit_delete_nbr_area (old->area, old); - break; - } - - ospf_lsa_maxage_delete (ospf, old); - ospf_lsa_discard (old); -} - -struct ospf_lsa * -ospf_lsa_install (struct ospf *ospf, struct ospf_interface *oi, - struct ospf_lsa *lsa) -{ - struct ospf_lsa *new = NULL; - struct ospf_lsa *old = NULL; - struct ospf_lsdb *lsdb = NULL; - int rt_recalc; - - /* Set LSDB. */ - switch (lsa->data->type) - { - /* kevinm */ - case OSPF_AS_NSSA_LSA: - if (lsa->area) - lsdb = lsa->area->lsdb; - else - lsdb = ospf->lsdb; - break; - case OSPF_AS_EXTERNAL_LSA: - case OSPF_OPAQUE_AS_LSA: - lsdb = ospf->lsdb; - break; - default: - lsdb = lsa->area->lsdb; - break; - } - - assert (lsdb); - - /* RFC 2328 13.2. Installing LSAs in the database - - Installing a new LSA in the database, either as the result of - flooding or a newly self-originated LSA, may cause the OSPF - routing table structure to be recalculated. The contents of the - new LSA should be compared to the old instance, if present. If - there is no difference, there is no need to recalculate the - routing table. When comparing an LSA to its previous instance, - the following are all considered to be differences in contents: - - o The LSA's Options field has changed. - - o One of the LSA instances has LS age set to MaxAge, and - the other does not. - - o The length field in the LSA header has changed. - - o The body of the LSA (i.e., anything outside the 20-byte - LSA header) has changed. Note that this excludes changes - in LS Sequence Number and LS Checksum. - - */ - /* Look up old LSA and determine if any SPF calculation or incremental - update is needed */ - old = ospf_lsdb_lookup (lsdb, lsa); - - /* Do comparision and record if recalc needed. */ - rt_recalc = 0; - if ( old == NULL || ospf_lsa_different(old, lsa)) - rt_recalc = 1; - - /* - Sequence number check (Section 14.1 of rfc 2328) - "Premature aging is used when it is time for a self-originated - LSA's sequence number field to wrap. At this point, the current - LSA instance (having LS sequence number MaxSequenceNumber) must - be prematurely aged and flushed from the routing domain before a - new instance with sequence number equal to InitialSequenceNumber - can be originated. " - */ - - if (ntohl(lsa->data->ls_seqnum) - 1 == OSPF_MAX_SEQUENCE_NUMBER) - { - if (ospf_lsa_is_self_originated(ospf, lsa)) - { - lsa->data->ls_seqnum = htonl(OSPF_MAX_SEQUENCE_NUMBER); - - if (!IS_LSA_MAXAGE(lsa)) - lsa->flags |= OSPF_LSA_PREMATURE_AGE; - lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); - - if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) - { - zlog_debug ("ospf_lsa_install() Premature Aging " - "lsa 0x%p, seqnum 0x%x", - (void *)lsa, ntohl(lsa->data->ls_seqnum)); - ospf_lsa_header_dump (lsa->data); - } - } - else - { - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - { - zlog_debug ("ospf_lsa_install() got an lsa with seq 0x80000000 " - "that was not self originated. Ignoring\n"); - ospf_lsa_header_dump (lsa->data); - } - return old; - } - } - - /* discard old LSA from LSDB */ - if (old != NULL) - ospf_discard_from_db (ospf, lsdb, lsa); - - /* Calculate Checksum if self-originated?. */ - if (IS_LSA_SELF (lsa)) - ospf_lsa_checksum (lsa->data); - - /* Insert LSA to LSDB. */ - ospf_lsdb_add (lsdb, lsa); - lsa->lsdb = lsdb; - - /* Do LSA specific installation process. */ - switch (lsa->data->type) - { - case OSPF_ROUTER_LSA: - new = ospf_router_lsa_install (ospf, lsa, rt_recalc); - break; - case OSPF_NETWORK_LSA: - assert (oi); - new = ospf_network_lsa_install (ospf, oi, lsa, rt_recalc); - break; - case OSPF_SUMMARY_LSA: - new = ospf_summary_lsa_install (ospf, lsa, rt_recalc); - break; - case OSPF_ASBR_SUMMARY_LSA: - new = ospf_summary_asbr_lsa_install (ospf, lsa, rt_recalc); - break; - case OSPF_AS_EXTERNAL_LSA: - new = ospf_external_lsa_install (ospf, lsa, rt_recalc); - break; - case OSPF_OPAQUE_LINK_LSA: - if (IS_LSA_SELF (lsa)) - lsa->oi = oi; /* Specify outgoing ospf-interface for this LSA. */ - else - { - /* Incoming "oi" for this LSA has set at LSUpd reception. */ - } - /* Fallthrough */ - case OSPF_OPAQUE_AREA_LSA: - case OSPF_OPAQUE_AS_LSA: - new = ospf_opaque_lsa_install (lsa, rt_recalc); - break; - case OSPF_AS_NSSA_LSA: - new = ospf_external_lsa_install (ospf, lsa, rt_recalc); - default: /* type-6,8,9....nothing special */ - break; - } - - if (new == NULL) - return new; /* Installation failed, cannot proceed further -- endo. */ - - /* Debug logs. */ - if (IS_DEBUG_OSPF (lsa, LSA_INSTALL)) - { - char area_str[INET_ADDRSTRLEN]; - - switch (lsa->data->type) - { - case OSPF_AS_EXTERNAL_LSA: - case OSPF_OPAQUE_AS_LSA: - case OSPF_AS_NSSA_LSA: - zlog_debug ("LSA[%s]: Install %s", - dump_lsa_key (new), - lookup_msg(ospf_lsa_type_msg, new->data->type, NULL)); - break; - default: - strcpy (area_str, inet_ntoa (new->area->area_id)); - zlog_debug ("LSA[%s]: Install %s to Area %s", - dump_lsa_key (new), - lookup_msg(ospf_lsa_type_msg, new->data->type, NULL), area_str); - break; - } - } - - /* - If received LSA' ls_age is MaxAge, or lsa is being prematurely aged - (it's getting flushed out of the area), set LSA on MaxAge LSA list. - */ - if (IS_LSA_MAXAGE (new)) - { - if (IS_DEBUG_OSPF (lsa, LSA_INSTALL)) - zlog_debug ("LSA[Type%d:%s]: Install LSA 0x%p, MaxAge", - new->data->type, - inet_ntoa (new->data->id), - (void *)lsa); - ospf_lsa_maxage (ospf, lsa); - } - - return new; -} - - -int -ospf_check_nbr_status (struct ospf *ospf) -{ - struct listnode *node, *nnode; - struct ospf_interface *oi; - - for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) - { - struct route_node *rn; - struct ospf_neighbor *nbr; - - if (ospf_if_is_enable (oi)) - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - if (nbr->state == NSM_Exchange || nbr->state == NSM_Loading) - { - route_unlock_node (rn); - return 0; - } - } - - return 1; -} - - - -static int -ospf_maxage_lsa_remover (struct thread *thread) -{ - struct ospf *ospf = THREAD_ARG (thread); - struct ospf_lsa *lsa; - struct route_node *rn; - int reschedule = 0; - - ospf->t_maxage = NULL; - - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("LSA[MaxAge]: remover Start"); - - reschedule = !ospf_check_nbr_status (ospf); - - if (!reschedule) - for (rn = route_top(ospf->maxage_lsa); rn; rn = route_next(rn)) - { - if ((lsa = rn->info) == NULL) - { - continue; - } - - /* There is at least one neighbor from which we still await an ack - * for that LSA, so we are not allowed to remove it from our lsdb yet - * as per RFC 2328 section 14 para 4 a) */ - if (lsa->retransmit_counter > 0) - { - reschedule = 1; - continue; - } - - /* TODO: maybe convert this function to a work-queue */ - if (thread_should_yield (thread)) - { - OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, 0); - route_unlock_node(rn); /* route_top/route_next */ - return 0; - } - - /* Remove LSA from the LSDB */ - if (IS_LSA_SELF (lsa)) - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("LSA[Type%d:%s]: LSA 0x%lx is self-originated: ", - lsa->data->type, inet_ntoa (lsa->data->id), (u_long)lsa); - - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("LSA[Type%d:%s]: MaxAge LSA removed from list", - lsa->data->type, inet_ntoa (lsa->data->id)); - - if (CHECK_FLAG (lsa->flags, OSPF_LSA_PREMATURE_AGE)) - { - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("originating new lsa for lsa 0x%p\n", (void *)lsa); - ospf_lsa_refresh (ospf, lsa); - } - - /* Remove from lsdb. */ - if (lsa->lsdb) - { - ospf_discard_from_db (ospf, lsa->lsdb, lsa); - ospf_lsdb_delete (lsa->lsdb, lsa); - } - else - zlog_warn ("%s: LSA[Type%d:%s]: No associated LSDB!", __func__, - lsa->data->type, inet_ntoa (lsa->data->id)); - } - - /* A MaxAge LSA must be removed immediately from the router's link - state database as soon as both a) it is no longer contained on any - neighbor Link state retransmission lists and b) none of the router's - neighbors are in states Exchange or Loading. */ - if (reschedule) - OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, - ospf->maxage_delay); - - return 0; -} - -void -ospf_lsa_maxage_delete (struct ospf *ospf, struct ospf_lsa *lsa) -{ - struct route_node *rn; - struct prefix_ptr lsa_prefix; - - lsa_prefix.family = 0; - lsa_prefix.prefixlen = sizeof(lsa_prefix.prefix) * CHAR_BIT; - lsa_prefix.prefix = (uintptr_t) lsa; - - if ((rn = route_node_lookup(ospf->maxage_lsa, - (struct prefix *)&lsa_prefix))) - { - if (rn->info == lsa) - { - UNSET_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE); - ospf_lsa_unlock (&lsa); /* maxage_lsa */ - rn->info = NULL; - route_unlock_node (rn); /* unlock node because lsa is deleted */ - } - route_unlock_node (rn); /* route_node_lookup */ - } +static struct ospf_lsa *ospf_external_lsa_install(struct ospf *ospf, + struct ospf_lsa *new, + int rt_recalc) +{ + ospf_ase_register_external_lsa(new, ospf); + /* If LSA is not self-originated, calculate an external route. */ + if (rt_recalc) { + /* RFC 2328 Section 13.2 AS-external-LSAs + The best route to the destination described by the AS- + external-LSA must be recalculated (see Section 16.6). + */ + + if (!IS_LSA_SELF(new)) + ospf_ase_incremental_update(ospf, new); + } + + if (new->data->type == OSPF_AS_NSSA_LSA) { + /* There is no point to register selforiginate Type-7 LSA for + * refreshing. We rely on refreshing Type-5 LSA's + */ + if (IS_LSA_SELF(new)) + return new; + else { + /* Try refresh type-5 translated LSA for this LSA, if + * one exists. + * New translations will be taken care of by the + * abr_task. + */ + ospf_translated_nssa_refresh(ospf, new, NULL); + } + } + + /* Register self-originated LSA to refresh queue. + * Leave Translated LSAs alone if NSSA is enabled + */ + if (IS_LSA_SELF(new) && !CHECK_FLAG(new->flags, OSPF_LSA_LOCAL_XLT)) + ospf_refresher_register_lsa(ospf, new); + + return new; +} + +void ospf_discard_from_db(struct ospf *ospf, struct ospf_lsdb *lsdb, + struct ospf_lsa *lsa) +{ + struct ospf_lsa *old; + + if (!lsdb) { + zlog_warn("%s: Called with NULL lsdb!", __func__); + if (!lsa) + zlog_warn("%s: and NULL LSA!", __func__); + else + zlog_warn("LSA[Type%d:%s]: not associated with LSDB!", + lsa->data->type, inet_ntoa(lsa->data->id)); + return; + } + + old = ospf_lsdb_lookup(lsdb, lsa); + + if (!old) + return; + + if (old->refresh_list >= 0) + ospf_refresher_unregister_lsa(ospf, old); + + switch (old->data->type) { + case OSPF_AS_EXTERNAL_LSA: + ospf_ase_unregister_external_lsa(old, ospf); + ospf_ls_retransmit_delete_nbr_as(ospf, old); + break; + case OSPF_OPAQUE_AS_LSA: + ospf_ls_retransmit_delete_nbr_as(ospf, old); + break; + case OSPF_AS_NSSA_LSA: + ospf_ls_retransmit_delete_nbr_area(old->area, old); + ospf_ase_unregister_external_lsa(old, ospf); + break; + default: + ospf_ls_retransmit_delete_nbr_area(old->area, old); + break; + } + + ospf_lsa_maxage_delete(ospf, old); + ospf_lsa_discard(old); +} + +struct ospf_lsa *ospf_lsa_install(struct ospf *ospf, struct ospf_interface *oi, + struct ospf_lsa *lsa) +{ + struct ospf_lsa *new = NULL; + struct ospf_lsa *old = NULL; + struct ospf_lsdb *lsdb = NULL; + int rt_recalc; + + /* Set LSDB. */ + switch (lsa->data->type) { + /* kevinm */ + case OSPF_AS_NSSA_LSA: + if (lsa->area) + lsdb = lsa->area->lsdb; + else + lsdb = ospf->lsdb; + break; + case OSPF_AS_EXTERNAL_LSA: + case OSPF_OPAQUE_AS_LSA: + lsdb = ospf->lsdb; + break; + default: + lsdb = lsa->area->lsdb; + break; + } + + assert(lsdb); + + /* RFC 2328 13.2. Installing LSAs in the database + + Installing a new LSA in the database, either as the result of + flooding or a newly self-originated LSA, may cause the OSPF + routing table structure to be recalculated. The contents of the + new LSA should be compared to the old instance, if present. If + there is no difference, there is no need to recalculate the + routing table. When comparing an LSA to its previous instance, + the following are all considered to be differences in contents: + + o The LSA's Options field has changed. + + o One of the LSA instances has LS age set to MaxAge, and + the other does not. + + o The length field in the LSA header has changed. + + o The body of the LSA (i.e., anything outside the 20-byte + LSA header) has changed. Note that this excludes changes + in LS Sequence Number and LS Checksum. + + */ + /* Look up old LSA and determine if any SPF calculation or incremental + update is needed */ + old = ospf_lsdb_lookup(lsdb, lsa); + + /* Do comparision and record if recalc needed. */ + rt_recalc = 0; + if (old == NULL || ospf_lsa_different(old, lsa)) + rt_recalc = 1; + + /* + Sequence number check (Section 14.1 of rfc 2328) + "Premature aging is used when it is time for a self-originated + LSA's sequence number field to wrap. At this point, the current + LSA instance (having LS sequence number MaxSequenceNumber) must + be prematurely aged and flushed from the routing domain before a + new instance with sequence number equal to InitialSequenceNumber + can be originated. " + */ + + if (ntohl(lsa->data->ls_seqnum) - 1 == OSPF_MAX_SEQUENCE_NUMBER) { + if (ospf_lsa_is_self_originated(ospf, lsa)) { + lsa->data->ls_seqnum = htonl(OSPF_MAX_SEQUENCE_NUMBER); + + if (!IS_LSA_MAXAGE(lsa)) + lsa->flags |= OSPF_LSA_PREMATURE_AGE; + lsa->data->ls_age = htons(OSPF_LSA_MAXAGE); + + if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) { + zlog_debug( + "ospf_lsa_install() Premature Aging " + "lsa 0x%p, seqnum 0x%x", + (void *)lsa, + ntohl(lsa->data->ls_seqnum)); + ospf_lsa_header_dump(lsa->data); + } + } else { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug( + "ospf_lsa_install() got an lsa with seq 0x80000000 " + "that was not self originated. Ignoring\n"); + ospf_lsa_header_dump(lsa->data); + } + return old; + } + } + + /* discard old LSA from LSDB */ + if (old != NULL) + ospf_discard_from_db(ospf, lsdb, lsa); + + /* Calculate Checksum if self-originated?. */ + if (IS_LSA_SELF(lsa)) + ospf_lsa_checksum(lsa->data); + + /* Insert LSA to LSDB. */ + ospf_lsdb_add(lsdb, lsa); + lsa->lsdb = lsdb; + + /* Do LSA specific installation process. */ + switch (lsa->data->type) { + case OSPF_ROUTER_LSA: + new = ospf_router_lsa_install(ospf, lsa, rt_recalc); + break; + case OSPF_NETWORK_LSA: + assert(oi); + new = ospf_network_lsa_install(ospf, oi, lsa, rt_recalc); + break; + case OSPF_SUMMARY_LSA: + new = ospf_summary_lsa_install(ospf, lsa, rt_recalc); + break; + case OSPF_ASBR_SUMMARY_LSA: + new = ospf_summary_asbr_lsa_install(ospf, lsa, rt_recalc); + break; + case OSPF_AS_EXTERNAL_LSA: + new = ospf_external_lsa_install(ospf, lsa, rt_recalc); + break; + case OSPF_OPAQUE_LINK_LSA: + if (IS_LSA_SELF(lsa)) + lsa->oi = oi; /* Specify outgoing ospf-interface for + this LSA. */ + else { + /* Incoming "oi" for this LSA has set at LSUpd + * reception. */ + } + /* Fallthrough */ + case OSPF_OPAQUE_AREA_LSA: + case OSPF_OPAQUE_AS_LSA: + new = ospf_opaque_lsa_install(lsa, rt_recalc); + break; + case OSPF_AS_NSSA_LSA: + new = ospf_external_lsa_install(ospf, lsa, rt_recalc); + default: /* type-6,8,9....nothing special */ + break; + } + + if (new == NULL) + return new; /* Installation failed, cannot proceed further -- + endo. */ + + /* Debug logs. */ + if (IS_DEBUG_OSPF(lsa, LSA_INSTALL)) { + char area_str[INET_ADDRSTRLEN]; + + switch (lsa->data->type) { + case OSPF_AS_EXTERNAL_LSA: + case OSPF_OPAQUE_AS_LSA: + case OSPF_AS_NSSA_LSA: + zlog_debug("LSA[%s]: Install %s", dump_lsa_key(new), + lookup_msg(ospf_lsa_type_msg, + new->data->type, NULL)); + break; + default: + strcpy(area_str, inet_ntoa(new->area->area_id)); + zlog_debug("LSA[%s]: Install %s to Area %s", + dump_lsa_key(new), + lookup_msg(ospf_lsa_type_msg, + new->data->type, NULL), + area_str); + break; + } + } + + /* + If received LSA' ls_age is MaxAge, or lsa is being prematurely aged + (it's getting flushed out of the area), set LSA on MaxAge LSA list. + */ + if (IS_LSA_MAXAGE(new)) { + if (IS_DEBUG_OSPF(lsa, LSA_INSTALL)) + zlog_debug("LSA[Type%d:%s]: Install LSA 0x%p, MaxAge", + new->data->type, inet_ntoa(new->data->id), + (void *)lsa); + ospf_lsa_maxage(ospf, lsa); + } + + return new; +} + + +int ospf_check_nbr_status(struct ospf *ospf) +{ + struct listnode *node, *nnode; + struct ospf_interface *oi; + + for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) { + struct route_node *rn; + struct ospf_neighbor *nbr; + + if (ospf_if_is_enable(oi)) + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info) != NULL) + if (nbr->state == NSM_Exchange + || nbr->state == NSM_Loading) { + route_unlock_node(rn); + return 0; + } + } + + return 1; +} + + +static int ospf_maxage_lsa_remover(struct thread *thread) +{ + struct ospf *ospf = THREAD_ARG(thread); + struct ospf_lsa *lsa; + struct route_node *rn; + int reschedule = 0; + + ospf->t_maxage = NULL; + + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug("LSA[MaxAge]: remover Start"); + + reschedule = !ospf_check_nbr_status(ospf); + + if (!reschedule) + for (rn = route_top(ospf->maxage_lsa); rn; + rn = route_next(rn)) { + if ((lsa = rn->info) == NULL) { + continue; + } + + /* There is at least one neighbor from which we still + * await an ack + * for that LSA, so we are not allowed to remove it from + * our lsdb yet + * as per RFC 2328 section 14 para 4 a) */ + if (lsa->retransmit_counter > 0) { + reschedule = 1; + continue; + } + + /* TODO: maybe convert this function to a work-queue */ + if (thread_should_yield(thread)) { + OSPF_TIMER_ON(ospf->t_maxage, + ospf_maxage_lsa_remover, 0); + route_unlock_node( + rn); /* route_top/route_next */ + return 0; + } + + /* Remove LSA from the LSDB */ + if (IS_LSA_SELF(lsa)) + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug( + "LSA[Type%d:%s]: LSA 0x%lx is self-originated: ", + lsa->data->type, + inet_ntoa(lsa->data->id), + (u_long)lsa); + + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug( + "LSA[Type%d:%s]: MaxAge LSA removed from list", + lsa->data->type, + inet_ntoa(lsa->data->id)); + + if (CHECK_FLAG(lsa->flags, OSPF_LSA_PREMATURE_AGE)) { + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug( + "originating new lsa for lsa 0x%p\n", + (void *)lsa); + ospf_lsa_refresh(ospf, lsa); + } + + /* Remove from lsdb. */ + if (lsa->lsdb) { + ospf_discard_from_db(ospf, lsa->lsdb, lsa); + ospf_lsdb_delete(lsa->lsdb, lsa); + } else + zlog_warn( + "%s: LSA[Type%d:%s]: No associated LSDB!", + __func__, lsa->data->type, + inet_ntoa(lsa->data->id)); + } + + /* A MaxAge LSA must be removed immediately from the router's link + state database as soon as both a) it is no longer contained on any + neighbor Link state retransmission lists and b) none of the + router's + neighbors are in states Exchange or Loading. */ + if (reschedule) + OSPF_TIMER_ON(ospf->t_maxage, ospf_maxage_lsa_remover, + ospf->maxage_delay); + + return 0; +} + +void ospf_lsa_maxage_delete(struct ospf *ospf, struct ospf_lsa *lsa) +{ + struct route_node *rn; + struct prefix_ptr lsa_prefix; + + lsa_prefix.family = 0; + lsa_prefix.prefixlen = sizeof(lsa_prefix.prefix) * CHAR_BIT; + lsa_prefix.prefix = (uintptr_t)lsa; + + if ((rn = route_node_lookup(ospf->maxage_lsa, + (struct prefix *)&lsa_prefix))) { + if (rn->info == lsa) { + UNSET_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE); + ospf_lsa_unlock(&lsa); /* maxage_lsa */ + rn->info = NULL; + route_unlock_node( + rn); /* unlock node because lsa is deleted */ + } + route_unlock_node(rn); /* route_node_lookup */ + } } /* Add LSA onto the MaxAge list, and schedule for removal. @@ -2922,841 +2868,833 @@ ospf_lsa_maxage_delete (struct ospf *ospf, struct ospf_lsa *lsa) * care of elsewhere, see, e.g., ospf_lsa_flush* (which are callers of this * function). */ -void -ospf_lsa_maxage (struct ospf *ospf, struct ospf_lsa *lsa) -{ - struct prefix_ptr lsa_prefix; - struct route_node *rn; - - /* When we saw a MaxAge LSA flooded to us, we put it on the list - and schedule the MaxAge LSA remover. */ - if (CHECK_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE)) - { - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("LSA[Type%d:%s]: %p already exists on MaxAge LSA list", - lsa->data->type, inet_ntoa (lsa->data->id), (void *)lsa); - return; - } - - lsa_prefix.family = 0; - lsa_prefix.prefixlen = sizeof(lsa_prefix.prefix) * CHAR_BIT; - lsa_prefix.prefix = (uintptr_t) lsa; - - if ((rn = route_node_get (ospf->maxage_lsa, - (struct prefix *)&lsa_prefix)) != NULL) - { - if (rn->info != NULL) - { - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("LSA[%s]: found LSA (%p) in table for LSA %p %d", - dump_lsa_key (lsa), rn->info, (void *)lsa, - lsa_prefix.prefixlen); - route_unlock_node (rn); - } - else - { - rn->info = ospf_lsa_lock(lsa); - SET_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE); - } - } - else - { - zlog_err("Unable to allocate memory for maxage lsa\n"); - assert(0); - } - - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("LSA[%s]: MaxAge LSA remover scheduled.", dump_lsa_key (lsa)); - - OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, - ospf->maxage_delay); -} - -static int -ospf_lsa_maxage_walker_remover (struct ospf *ospf, struct ospf_lsa *lsa) -{ - /* Stay away from any Local Translated Type-7 LSAs */ - if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)) - return 0; - - if (IS_LSA_MAXAGE (lsa)) - /* Self-originated LSAs should NOT time-out instead, - they're flushed and submitted to the max_age list explicitly. */ - if (!ospf_lsa_is_self_originated (ospf, lsa)) - { - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug("LSA[%s]: is MaxAge", dump_lsa_key (lsa)); - - switch (lsa->data->type) - { - case OSPF_OPAQUE_LINK_LSA: - case OSPF_OPAQUE_AREA_LSA: - case OSPF_OPAQUE_AS_LSA: - /* - * As a general rule, whenever network topology has changed - * (due to an LSA removal in this case), routing recalculation - * should be triggered. However, this is not true for opaque - * LSAs. Even if an opaque LSA instance is going to be removed - * from the routing domain, it does not mean a change in network - * topology, and thus, routing recalculation is not needed here. - */ - break; - case OSPF_AS_EXTERNAL_LSA: - case OSPF_AS_NSSA_LSA: - ospf_ase_incremental_update (ospf, lsa); - break; - default: - ospf_spf_calculate_schedule (ospf, SPF_FLAG_MAXAGE); - break; - } - ospf_lsa_maxage (ospf, lsa); - } - - if (IS_LSA_MAXAGE (lsa) && !ospf_lsa_is_self_originated (ospf, lsa)) - if (LS_AGE (lsa) > OSPF_LSA_MAXAGE + 30) - printf ("Eek! Shouldn't happen!\n"); - - return 0; +void ospf_lsa_maxage(struct ospf *ospf, struct ospf_lsa *lsa) +{ + struct prefix_ptr lsa_prefix; + struct route_node *rn; + + /* When we saw a MaxAge LSA flooded to us, we put it on the list + and schedule the MaxAge LSA remover. */ + if (CHECK_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE)) { + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug( + "LSA[Type%d:%s]: %p already exists on MaxAge LSA list", + lsa->data->type, inet_ntoa(lsa->data->id), + (void *)lsa); + return; + } + + lsa_prefix.family = 0; + lsa_prefix.prefixlen = sizeof(lsa_prefix.prefix) * CHAR_BIT; + lsa_prefix.prefix = (uintptr_t)lsa; + + if ((rn = route_node_get(ospf->maxage_lsa, + (struct prefix *)&lsa_prefix)) + != NULL) { + if (rn->info != NULL) { + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug( + "LSA[%s]: found LSA (%p) in table for LSA %p %d", + dump_lsa_key(lsa), rn->info, + (void *)lsa, lsa_prefix.prefixlen); + route_unlock_node(rn); + } else { + rn->info = ospf_lsa_lock(lsa); + SET_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE); + } + } else { + zlog_err("Unable to allocate memory for maxage lsa\n"); + assert(0); + } + + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug("LSA[%s]: MaxAge LSA remover scheduled.", + dump_lsa_key(lsa)); + + OSPF_TIMER_ON(ospf->t_maxage, ospf_maxage_lsa_remover, + ospf->maxage_delay); +} + +static int ospf_lsa_maxage_walker_remover(struct ospf *ospf, + struct ospf_lsa *lsa) +{ + /* Stay away from any Local Translated Type-7 LSAs */ + if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) + return 0; + + if (IS_LSA_MAXAGE(lsa)) + /* Self-originated LSAs should NOT time-out instead, + they're flushed and submitted to the max_age list explicitly. + */ + if (!ospf_lsa_is_self_originated(ospf, lsa)) { + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug("LSA[%s]: is MaxAge", + dump_lsa_key(lsa)); + + switch (lsa->data->type) { + case OSPF_OPAQUE_LINK_LSA: + case OSPF_OPAQUE_AREA_LSA: + case OSPF_OPAQUE_AS_LSA: + /* + * As a general rule, whenever network topology + * has changed + * (due to an LSA removal in this case), routing + * recalculation + * should be triggered. However, this is not + * true for opaque + * LSAs. Even if an opaque LSA instance is going + * to be removed + * from the routing domain, it does not mean a + * change in network + * topology, and thus, routing recalculation is + * not needed here. + */ + break; + case OSPF_AS_EXTERNAL_LSA: + case OSPF_AS_NSSA_LSA: + ospf_ase_incremental_update(ospf, lsa); + break; + default: + ospf_spf_calculate_schedule(ospf, + SPF_FLAG_MAXAGE); + break; + } + ospf_lsa_maxage(ospf, lsa); + } + + if (IS_LSA_MAXAGE(lsa) && !ospf_lsa_is_self_originated(ospf, lsa)) + if (LS_AGE(lsa) > OSPF_LSA_MAXAGE + 30) + printf("Eek! Shouldn't happen!\n"); + + return 0; } /* Periodical check of MaxAge LSA. */ -int -ospf_lsa_maxage_walker (struct thread *thread) -{ - struct ospf *ospf = THREAD_ARG (thread); - struct route_node *rn; - struct ospf_lsa *lsa; - struct ospf_area *area; - struct listnode *node, *nnode; - - ospf->t_maxage_walker = NULL; - - for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) - { - LSDB_LOOP (ROUTER_LSDB (area), rn, lsa) - ospf_lsa_maxage_walker_remover (ospf, lsa); - LSDB_LOOP (NETWORK_LSDB (area), rn, lsa) - ospf_lsa_maxage_walker_remover (ospf, lsa); - LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa) - ospf_lsa_maxage_walker_remover (ospf, lsa); - LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa) - ospf_lsa_maxage_walker_remover (ospf, lsa); - LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) - ospf_lsa_maxage_walker_remover (ospf, lsa); - LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa) - ospf_lsa_maxage_walker_remover (ospf, lsa); - LSDB_LOOP (NSSA_LSDB (area), rn, lsa) - ospf_lsa_maxage_walker_remover (ospf, lsa); - } - - /* for AS-external-LSAs. */ - if (ospf->lsdb) - { - LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) - ospf_lsa_maxage_walker_remover (ospf, lsa); - LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa) - ospf_lsa_maxage_walker_remover (ospf, lsa); - } - - OSPF_TIMER_ON (ospf->t_maxage_walker, ospf_lsa_maxage_walker, - OSPF_LSA_MAXAGE_CHECK_INTERVAL); - return 0; -} - -struct ospf_lsa * -ospf_lsa_lookup_by_prefix (struct ospf_lsdb *lsdb, u_char type, - struct prefix_ipv4 *p, struct in_addr router_id) -{ - struct ospf_lsa *lsa; - struct in_addr mask, id; - struct lsa_header_mask - { - struct lsa_header header; - struct in_addr mask; - } *hmask; - - lsa = ospf_lsdb_lookup_by_id (lsdb, type, p->prefix, router_id); - if (lsa == NULL) - return NULL; - - masklen2ip (p->prefixlen, &mask); - - hmask = (struct lsa_header_mask *) lsa->data; - - if (mask.s_addr != hmask->mask.s_addr) - { - id.s_addr = p->prefix.s_addr | (~mask.s_addr); - lsa = ospf_lsdb_lookup_by_id (lsdb, type, id, router_id); - if (!lsa) - return NULL; - } - - return lsa; -} - -struct ospf_lsa * -ospf_lsa_lookup (struct ospf_area *area, u_int32_t type, - struct in_addr id, struct in_addr adv_router) -{ - struct ospf *ospf = ospf_lookup(); - assert(ospf); - - switch (type) - { - case OSPF_ROUTER_LSA: - case OSPF_NETWORK_LSA: - case OSPF_SUMMARY_LSA: - case OSPF_ASBR_SUMMARY_LSA: - case OSPF_AS_NSSA_LSA: - case OSPF_OPAQUE_LINK_LSA: - case OSPF_OPAQUE_AREA_LSA: - return ospf_lsdb_lookup_by_id (area->lsdb, type, id, adv_router); - case OSPF_AS_EXTERNAL_LSA: - case OSPF_OPAQUE_AS_LSA: - return ospf_lsdb_lookup_by_id (ospf->lsdb, type, id, adv_router); - default: - break; - } - - return NULL; -} - -struct ospf_lsa * -ospf_lsa_lookup_by_id (struct ospf_area *area, u_int32_t type, - struct in_addr id) -{ - struct ospf_lsa *lsa; - struct route_node *rn; - - switch (type) - { - case OSPF_ROUTER_LSA: - return ospf_lsdb_lookup_by_id (area->lsdb, type, id, id); - case OSPF_NETWORK_LSA: - for (rn = route_top (NETWORK_LSDB (area)); rn; rn = route_next (rn)) - if ((lsa = rn->info)) - if (IPV4_ADDR_SAME (&lsa->data->id, &id)) - { - route_unlock_node (rn); - return lsa; - } - break; - case OSPF_SUMMARY_LSA: - case OSPF_ASBR_SUMMARY_LSA: - /* Currently not used. */ - assert (1); - return ospf_lsdb_lookup_by_id (area->lsdb, type, id, id); - case OSPF_AS_EXTERNAL_LSA: - case OSPF_AS_NSSA_LSA: - case OSPF_OPAQUE_LINK_LSA: - case OSPF_OPAQUE_AREA_LSA: - case OSPF_OPAQUE_AS_LSA: - /* Currently not used. */ - break; - default: - break; - } - - return NULL; -} - -struct ospf_lsa * -ospf_lsa_lookup_by_header (struct ospf_area *area, struct lsa_header *lsah) -{ - struct ospf_lsa *match; - - /* - * Strictly speaking, the LSA-ID field for Opaque-LSAs (type-9/10/11) - * is redefined to have two subfields; opaque-type and opaque-id. - * However, it is harmless to treat the two sub fields together, as if - * they two were forming a unique LSA-ID. - */ - - match = ospf_lsa_lookup (area, lsah->type, lsah->id, lsah->adv_router); - - if (match == NULL) - if (IS_DEBUG_OSPF (lsa, LSA) == OSPF_DEBUG_LSA) - zlog_debug ("LSA[Type%d:%s]: Lookup by header, NO MATCH", - lsah->type, inet_ntoa (lsah->id)); - - return match; +int ospf_lsa_maxage_walker(struct thread *thread) +{ + struct ospf *ospf = THREAD_ARG(thread); + struct route_node *rn; + struct ospf_lsa *lsa; + struct ospf_area *area; + struct listnode *node, *nnode; + + ospf->t_maxage_walker = NULL; + + for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { + LSDB_LOOP(ROUTER_LSDB(area), rn, lsa) + ospf_lsa_maxage_walker_remover(ospf, lsa); + LSDB_LOOP(NETWORK_LSDB(area), rn, lsa) + ospf_lsa_maxage_walker_remover(ospf, lsa); + LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa) + ospf_lsa_maxage_walker_remover(ospf, lsa); + LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa) + ospf_lsa_maxage_walker_remover(ospf, lsa); + LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa) + ospf_lsa_maxage_walker_remover(ospf, lsa); + LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa) + ospf_lsa_maxage_walker_remover(ospf, lsa); + LSDB_LOOP(NSSA_LSDB(area), rn, lsa) + ospf_lsa_maxage_walker_remover(ospf, lsa); + } + + /* for AS-external-LSAs. */ + if (ospf->lsdb) { + LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa) + ospf_lsa_maxage_walker_remover(ospf, lsa); + LSDB_LOOP(OPAQUE_AS_LSDB(ospf), rn, lsa) + ospf_lsa_maxage_walker_remover(ospf, lsa); + } + + OSPF_TIMER_ON(ospf->t_maxage_walker, ospf_lsa_maxage_walker, + OSPF_LSA_MAXAGE_CHECK_INTERVAL); + return 0; +} + +struct ospf_lsa *ospf_lsa_lookup_by_prefix(struct ospf_lsdb *lsdb, u_char type, + struct prefix_ipv4 *p, + struct in_addr router_id) +{ + struct ospf_lsa *lsa; + struct in_addr mask, id; + struct lsa_header_mask { + struct lsa_header header; + struct in_addr mask; + } * hmask; + + lsa = ospf_lsdb_lookup_by_id(lsdb, type, p->prefix, router_id); + if (lsa == NULL) + return NULL; + + masklen2ip(p->prefixlen, &mask); + + hmask = (struct lsa_header_mask *)lsa->data; + + if (mask.s_addr != hmask->mask.s_addr) { + id.s_addr = p->prefix.s_addr | (~mask.s_addr); + lsa = ospf_lsdb_lookup_by_id(lsdb, type, id, router_id); + if (!lsa) + return NULL; + } + + return lsa; +} + +struct ospf_lsa *ospf_lsa_lookup(struct ospf_area *area, u_int32_t type, + struct in_addr id, struct in_addr adv_router) +{ + struct ospf *ospf = ospf_lookup(); + assert(ospf); + + switch (type) { + case OSPF_ROUTER_LSA: + case OSPF_NETWORK_LSA: + case OSPF_SUMMARY_LSA: + case OSPF_ASBR_SUMMARY_LSA: + case OSPF_AS_NSSA_LSA: + case OSPF_OPAQUE_LINK_LSA: + case OSPF_OPAQUE_AREA_LSA: + return ospf_lsdb_lookup_by_id(area->lsdb, type, id, adv_router); + case OSPF_AS_EXTERNAL_LSA: + case OSPF_OPAQUE_AS_LSA: + return ospf_lsdb_lookup_by_id(ospf->lsdb, type, id, adv_router); + default: + break; + } + + return NULL; +} + +struct ospf_lsa *ospf_lsa_lookup_by_id(struct ospf_area *area, u_int32_t type, + struct in_addr id) +{ + struct ospf_lsa *lsa; + struct route_node *rn; + + switch (type) { + case OSPF_ROUTER_LSA: + return ospf_lsdb_lookup_by_id(area->lsdb, type, id, id); + case OSPF_NETWORK_LSA: + for (rn = route_top(NETWORK_LSDB(area)); rn; + rn = route_next(rn)) + if ((lsa = rn->info)) + if (IPV4_ADDR_SAME(&lsa->data->id, &id)) { + route_unlock_node(rn); + return lsa; + } + break; + case OSPF_SUMMARY_LSA: + case OSPF_ASBR_SUMMARY_LSA: + /* Currently not used. */ + assert(1); + return ospf_lsdb_lookup_by_id(area->lsdb, type, id, id); + case OSPF_AS_EXTERNAL_LSA: + case OSPF_AS_NSSA_LSA: + case OSPF_OPAQUE_LINK_LSA: + case OSPF_OPAQUE_AREA_LSA: + case OSPF_OPAQUE_AS_LSA: + /* Currently not used. */ + break; + default: + break; + } + + return NULL; +} + +struct ospf_lsa *ospf_lsa_lookup_by_header(struct ospf_area *area, + struct lsa_header *lsah) +{ + struct ospf_lsa *match; + + /* + * Strictly speaking, the LSA-ID field for Opaque-LSAs (type-9/10/11) + * is redefined to have two subfields; opaque-type and opaque-id. + * However, it is harmless to treat the two sub fields together, as if + * they two were forming a unique LSA-ID. + */ + + match = ospf_lsa_lookup(area, lsah->type, lsah->id, lsah->adv_router); + + if (match == NULL) + if (IS_DEBUG_OSPF(lsa, LSA) == OSPF_DEBUG_LSA) + zlog_debug("LSA[Type%d:%s]: Lookup by header, NO MATCH", + lsah->type, inet_ntoa(lsah->id)); + + return match; } /* return +n, l1 is more recent. return -n, l2 is more recent. return 0, l1 and l2 is identical. */ -int -ospf_lsa_more_recent (struct ospf_lsa *l1, struct ospf_lsa *l2) -{ - int r; - int x, y; - - if (l1 == NULL && l2 == NULL) - return 0; - if (l1 == NULL) - return -1; - if (l2 == NULL) - return 1; - - /* compare LS sequence number. */ - x = (int) ntohl (l1->data->ls_seqnum); - y = (int) ntohl (l2->data->ls_seqnum); - if (x > y) - return 1; - if (x < y) - return -1; - - /* compare LS checksum. */ - r = ntohs (l1->data->checksum) - ntohs (l2->data->checksum); - if (r) - return r; - - /* compare LS age. */ - if (IS_LSA_MAXAGE (l1) && !IS_LSA_MAXAGE (l2)) - return 1; - else if (!IS_LSA_MAXAGE (l1) && IS_LSA_MAXAGE (l2)) - return -1; - - /* compare LS age with MaxAgeDiff. */ - if (LS_AGE (l1) - LS_AGE (l2) > OSPF_LSA_MAXAGE_DIFF) - return -1; - else if (LS_AGE (l2) - LS_AGE (l1) > OSPF_LSA_MAXAGE_DIFF) - return 1; - - /* LSAs are identical. */ - return 0; +int ospf_lsa_more_recent(struct ospf_lsa *l1, struct ospf_lsa *l2) +{ + int r; + int x, y; + + if (l1 == NULL && l2 == NULL) + return 0; + if (l1 == NULL) + return -1; + if (l2 == NULL) + return 1; + + /* compare LS sequence number. */ + x = (int)ntohl(l1->data->ls_seqnum); + y = (int)ntohl(l2->data->ls_seqnum); + if (x > y) + return 1; + if (x < y) + return -1; + + /* compare LS checksum. */ + r = ntohs(l1->data->checksum) - ntohs(l2->data->checksum); + if (r) + return r; + + /* compare LS age. */ + if (IS_LSA_MAXAGE(l1) && !IS_LSA_MAXAGE(l2)) + return 1; + else if (!IS_LSA_MAXAGE(l1) && IS_LSA_MAXAGE(l2)) + return -1; + + /* compare LS age with MaxAgeDiff. */ + if (LS_AGE(l1) - LS_AGE(l2) > OSPF_LSA_MAXAGE_DIFF) + return -1; + else if (LS_AGE(l2) - LS_AGE(l1) > OSPF_LSA_MAXAGE_DIFF) + return 1; + + /* LSAs are identical. */ + return 0; } /* If two LSAs are different, return 1, otherwise return 0. */ -int -ospf_lsa_different (struct ospf_lsa *l1, struct ospf_lsa *l2) +int ospf_lsa_different(struct ospf_lsa *l1, struct ospf_lsa *l2) { - char *p1, *p2; - assert (l1); - assert (l2); - assert (l1->data); - assert (l2->data); + char *p1, *p2; + assert(l1); + assert(l2); + assert(l1->data); + assert(l2->data); - if (l1->data->options != l2->data->options) - return 1; + if (l1->data->options != l2->data->options) + return 1; - if (IS_LSA_MAXAGE (l1) && !IS_LSA_MAXAGE (l2)) - return 1; + if (IS_LSA_MAXAGE(l1) && !IS_LSA_MAXAGE(l2)) + return 1; - if (IS_LSA_MAXAGE (l2) && !IS_LSA_MAXAGE (l1)) - return 1; + if (IS_LSA_MAXAGE(l2) && !IS_LSA_MAXAGE(l1)) + return 1; - if (l1->data->length != l2->data->length) - return 1; + if (l1->data->length != l2->data->length) + return 1; - if (l1->data->length == 0) - return 1; + if (l1->data->length == 0) + return 1; - if (CHECK_FLAG ((l1->flags ^ l2->flags), OSPF_LSA_RECEIVED)) - return 1; /* May be a stale LSA in the LSBD */ + if (CHECK_FLAG((l1->flags ^ l2->flags), OSPF_LSA_RECEIVED)) + return 1; /* May be a stale LSA in the LSBD */ - assert ( ntohs(l1->data->length) > OSPF_LSA_HEADER_SIZE); + assert(ntohs(l1->data->length) > OSPF_LSA_HEADER_SIZE); - p1 = (char *) l1->data; - p2 = (char *) l2->data; + p1 = (char *)l1->data; + p2 = (char *)l2->data; - if (memcmp (p1 + OSPF_LSA_HEADER_SIZE, p2 + OSPF_LSA_HEADER_SIZE, - ntohs( l1->data->length ) - OSPF_LSA_HEADER_SIZE) != 0) - return 1; + if (memcmp(p1 + OSPF_LSA_HEADER_SIZE, p2 + OSPF_LSA_HEADER_SIZE, + ntohs(l1->data->length) - OSPF_LSA_HEADER_SIZE) + != 0) + return 1; - return 0; + return 0; } #ifdef ORIGINAL_CODING -void -ospf_lsa_flush_self_originated (struct ospf_neighbor *nbr, - struct ospf_lsa *self, - struct ospf_lsa *new) -{ - u_int32_t seqnum; - - /* Adjust LS Sequence Number. */ - seqnum = ntohl (new->data->ls_seqnum) + 1; - self->data->ls_seqnum = htonl (seqnum); - - /* Recalculate LSA checksum. */ - ospf_lsa_checksum (self->data); - - /* Reflooding LSA. */ - /* RFC2328 Section 13.3 - On non-broadcast networks, separate Link State Update - packets must be sent, as unicasts, to each adjacent neighbor - (i.e., those in state Exchange or greater). The destination - IP addresses for these packets are the neighbors' IP - addresses. */ - if (nbr->oi->type == OSPF_IFTYPE_NBMA) - { - struct route_node *rn; - struct ospf_neighbor *onbr; - - for (rn = route_top (nbr->oi->nbrs); rn; rn = route_next (rn)) - if ((onbr = rn->info) != NULL) - if (onbr != nbr->oi->nbr_self && onbr->status >= NSM_Exchange) - ospf_ls_upd_send_lsa (onbr, self, OSPF_SEND_PACKET_DIRECT); - } - else - ospf_ls_upd_send_lsa (nbr, self, OSPF_SEND_PACKET_INDIRECT); - - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type%d:%s]: Flush self-originated LSA", - self->data->type, inet_ntoa (self->data->id)); -} -#else /* ORIGINAL_CODING */ -int -ospf_lsa_flush_schedule (struct ospf *ospf, struct ospf_lsa *lsa) -{ - if (lsa == NULL || !IS_LSA_SELF (lsa)) - return 0; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", lsa->data->type, inet_ntoa (lsa->data->id)); - - /* Force given lsa's age to MaxAge. */ - lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); - - switch (lsa->data->type) - { - /* Opaque wants to be notified of flushes */ - case OSPF_OPAQUE_LINK_LSA: - case OSPF_OPAQUE_AREA_LSA: - case OSPF_OPAQUE_AS_LSA: - ospf_opaque_lsa_refresh (lsa); - break; - default: - ospf_refresher_unregister_lsa (ospf, lsa); - ospf_lsa_flush (ospf, lsa); - break; - } - - return 0; -} - -void -ospf_flush_self_originated_lsas_now (struct ospf *ospf) -{ - struct listnode *node, *nnode; - struct listnode *node2, *nnode2; - struct ospf_area *area; - struct ospf_interface *oi; - struct ospf_lsa *lsa; - struct route_node *rn; - int need_to_flush_ase = 0; - - for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) - { - if ((lsa = area->router_lsa_self) != NULL) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", - lsa->data->type, inet_ntoa (lsa->data->id)); - - ospf_refresher_unregister_lsa (ospf, lsa); - ospf_lsa_flush_area (lsa, area); - ospf_lsa_unlock (&area->router_lsa_self); - area->router_lsa_self = NULL; - } - - for (ALL_LIST_ELEMENTS (area->oiflist, node2, nnode2, oi)) - { - if ((lsa = oi->network_lsa_self) != NULL - && oi->state == ISM_DR - && oi->full_nbrs > 0) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", - lsa->data->type, inet_ntoa (lsa->data->id)); - - ospf_refresher_unregister_lsa (ospf, oi->network_lsa_self); - ospf_lsa_flush_area (oi->network_lsa_self, area); - ospf_lsa_unlock (&oi->network_lsa_self); - oi->network_lsa_self = NULL; - } - - if (oi->type != OSPF_IFTYPE_VIRTUALLINK - && area->external_routing == OSPF_AREA_DEFAULT) - need_to_flush_ase = 1; - } - - LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa) - ospf_lsa_flush_schedule (ospf, lsa); - LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa) - ospf_lsa_flush_schedule (ospf, lsa); - LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa) - ospf_lsa_flush_schedule (ospf, lsa); - LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) - ospf_lsa_flush_schedule (ospf, lsa); - } - - if (need_to_flush_ase) - { - LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) - ospf_lsa_flush_schedule (ospf, lsa); - LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa) - ospf_lsa_flush_schedule (ospf, lsa); - } - - /* - * Make sure that the MaxAge LSA remover is executed immediately, - * without conflicting to other threads. - */ - if (ospf->t_maxage != NULL) - { - OSPF_TIMER_OFF (ospf->t_maxage); - thread_execute (master, ospf_maxage_lsa_remover, ospf, 0); - } - - return; +void ospf_lsa_flush_self_originated(struct ospf_neighbor *nbr, + struct ospf_lsa *self, struct ospf_lsa *new) +{ + u_int32_t seqnum; + + /* Adjust LS Sequence Number. */ + seqnum = ntohl(new->data->ls_seqnum) + 1; + self->data->ls_seqnum = htonl(seqnum); + + /* Recalculate LSA checksum. */ + ospf_lsa_checksum(self->data); + + /* Reflooding LSA. */ + /* RFC2328 Section 13.3 + On non-broadcast networks, separate Link State Update + packets must be sent, as unicasts, to each adjacent neighbor + (i.e., those in state Exchange or greater). The destination + IP addresses for these packets are the neighbors' IP + addresses. */ + if (nbr->oi->type == OSPF_IFTYPE_NBMA) { + struct route_node *rn; + struct ospf_neighbor *onbr; + + for (rn = route_top(nbr->oi->nbrs); rn; rn = route_next(rn)) + if ((onbr = rn->info) != NULL) + if (onbr != nbr->oi->nbr_self + && onbr->status >= NSM_Exchange) + ospf_ls_upd_send_lsa( + onbr, self, + OSPF_SEND_PACKET_DIRECT); + } else + ospf_ls_upd_send_lsa(nbr, self, OSPF_SEND_PACKET_INDIRECT); + + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug("LSA[Type%d:%s]: Flush self-originated LSA", + self->data->type, inet_ntoa(self->data->id)); +} +#else /* ORIGINAL_CODING */ +int ospf_lsa_flush_schedule(struct ospf *ospf, struct ospf_lsa *lsa) +{ + if (lsa == NULL || !IS_LSA_SELF(lsa)) + return 0; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", + lsa->data->type, inet_ntoa(lsa->data->id)); + + /* Force given lsa's age to MaxAge. */ + lsa->data->ls_age = htons(OSPF_LSA_MAXAGE); + + switch (lsa->data->type) { + /* Opaque wants to be notified of flushes */ + case OSPF_OPAQUE_LINK_LSA: + case OSPF_OPAQUE_AREA_LSA: + case OSPF_OPAQUE_AS_LSA: + ospf_opaque_lsa_refresh(lsa); + break; + default: + ospf_refresher_unregister_lsa(ospf, lsa); + ospf_lsa_flush(ospf, lsa); + break; + } + + return 0; +} + +void ospf_flush_self_originated_lsas_now(struct ospf *ospf) +{ + struct listnode *node, *nnode; + struct listnode *node2, *nnode2; + struct ospf_area *area; + struct ospf_interface *oi; + struct ospf_lsa *lsa; + struct route_node *rn; + int need_to_flush_ase = 0; + + for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { + if ((lsa = area->router_lsa_self) != NULL) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", + lsa->data->type, + inet_ntoa(lsa->data->id)); + + ospf_refresher_unregister_lsa(ospf, lsa); + ospf_lsa_flush_area(lsa, area); + ospf_lsa_unlock(&area->router_lsa_self); + area->router_lsa_self = NULL; + } + + for (ALL_LIST_ELEMENTS(area->oiflist, node2, nnode2, oi)) { + if ((lsa = oi->network_lsa_self) != NULL + && oi->state == ISM_DR && oi->full_nbrs > 0) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", + lsa->data->type, + inet_ntoa(lsa->data->id)); + + ospf_refresher_unregister_lsa( + ospf, oi->network_lsa_self); + ospf_lsa_flush_area(oi->network_lsa_self, area); + ospf_lsa_unlock(&oi->network_lsa_self); + oi->network_lsa_self = NULL; + } + + if (oi->type != OSPF_IFTYPE_VIRTUALLINK + && area->external_routing == OSPF_AREA_DEFAULT) + need_to_flush_ase = 1; + } + + LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa) + ospf_lsa_flush_schedule(ospf, lsa); + LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa) + ospf_lsa_flush_schedule(ospf, lsa); + LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa) + ospf_lsa_flush_schedule(ospf, lsa); + LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa) + ospf_lsa_flush_schedule(ospf, lsa); + } + + if (need_to_flush_ase) { + LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa) + ospf_lsa_flush_schedule(ospf, lsa); + LSDB_LOOP(OPAQUE_AS_LSDB(ospf), rn, lsa) + ospf_lsa_flush_schedule(ospf, lsa); + } + + /* + * Make sure that the MaxAge LSA remover is executed immediately, + * without conflicting to other threads. + */ + if (ospf->t_maxage != NULL) { + OSPF_TIMER_OFF(ospf->t_maxage); + thread_execute(master, ospf_maxage_lsa_remover, ospf, 0); + } + + return; } #endif /* ORIGINAL_CODING */ /* If there is self-originated LSA, then return 1, otherwise return 0. */ /* An interface-independent version of ospf_lsa_is_self_originated */ -int -ospf_lsa_is_self_originated (struct ospf *ospf, struct ospf_lsa *lsa) -{ - struct listnode *node; - struct ospf_interface *oi; - - /* This LSA is already checked. */ - if (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF_CHECKED)) - return IS_LSA_SELF (lsa); - - /* Make sure LSA is self-checked. */ - SET_FLAG (lsa->flags, OSPF_LSA_SELF_CHECKED); - - /* AdvRouter and Router ID is the same. */ - if (IPV4_ADDR_SAME (&lsa->data->adv_router, &ospf->router_id)) - SET_FLAG (lsa->flags, OSPF_LSA_SELF); - - /* LSA is router-LSA. */ - else if (lsa->data->type == OSPF_ROUTER_LSA && - IPV4_ADDR_SAME (&lsa->data->id, &ospf->router_id)) - SET_FLAG (lsa->flags, OSPF_LSA_SELF); - - /* LSA is network-LSA. Compare Link ID with all interfaces. */ - else if (lsa->data->type == OSPF_NETWORK_LSA) - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) - { - /* Ignore virtual link. */ - if (oi->type != OSPF_IFTYPE_VIRTUALLINK) - if (oi->address->family == AF_INET) - if (IPV4_ADDR_SAME (&lsa->data->id, &oi->address->u.prefix4)) - { - /* to make it easier later */ - SET_FLAG (lsa->flags, OSPF_LSA_SELF); - return IS_LSA_SELF (lsa); - } - } - - return IS_LSA_SELF (lsa); +int ospf_lsa_is_self_originated(struct ospf *ospf, struct ospf_lsa *lsa) +{ + struct listnode *node; + struct ospf_interface *oi; + + /* This LSA is already checked. */ + if (CHECK_FLAG(lsa->flags, OSPF_LSA_SELF_CHECKED)) + return IS_LSA_SELF(lsa); + + /* Make sure LSA is self-checked. */ + SET_FLAG(lsa->flags, OSPF_LSA_SELF_CHECKED); + + /* AdvRouter and Router ID is the same. */ + if (IPV4_ADDR_SAME(&lsa->data->adv_router, &ospf->router_id)) + SET_FLAG(lsa->flags, OSPF_LSA_SELF); + + /* LSA is router-LSA. */ + else if (lsa->data->type == OSPF_ROUTER_LSA + && IPV4_ADDR_SAME(&lsa->data->id, &ospf->router_id)) + SET_FLAG(lsa->flags, OSPF_LSA_SELF); + + /* LSA is network-LSA. Compare Link ID with all interfaces. */ + else if (lsa->data->type == OSPF_NETWORK_LSA) + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { + /* Ignore virtual link. */ + if (oi->type != OSPF_IFTYPE_VIRTUALLINK) + if (oi->address->family == AF_INET) + if (IPV4_ADDR_SAME( + &lsa->data->id, + &oi->address->u.prefix4)) { + /* to make it easier later */ + SET_FLAG(lsa->flags, + OSPF_LSA_SELF); + return IS_LSA_SELF(lsa); + } + } + + return IS_LSA_SELF(lsa); } /* Get unique Link State ID. */ -struct in_addr -ospf_lsa_unique_id (struct ospf *ospf, - struct ospf_lsdb *lsdb, u_char type, struct prefix_ipv4 *p) -{ - struct ospf_lsa *lsa; - struct in_addr mask, id; - - id = p->prefix; - - /* Check existence of LSA instance. */ - lsa = ospf_lsdb_lookup_by_id (lsdb, type, id, ospf->router_id); - if (lsa) - { - struct as_external_lsa *al = (struct as_external_lsa *) lsa->data; - if (ip_masklen (al->mask) == p->prefixlen) - { - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("ospf_lsa_unique_id(): " - "Can't get Link State ID for %s/%d", - inet_ntoa (p->prefix), p->prefixlen); - /* id.s_addr = 0; */ - id.s_addr = 0xffffffff; - return id; - } - /* Masklen differs, then apply wildcard mask to Link State ID. */ - else - { - masklen2ip (p->prefixlen, &mask); - - id.s_addr = p->prefix.s_addr | (~mask.s_addr); - lsa = ospf_lsdb_lookup_by_id (ospf->lsdb, type, - id, ospf->router_id); - if (lsa) - { - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("ospf_lsa_unique_id(): " - "Can't get Link State ID for %s/%d", - inet_ntoa (p->prefix), p->prefixlen); - /* id.s_addr = 0; */ - id.s_addr = 0xffffffff; - return id; - } - } - } - - return id; +struct in_addr ospf_lsa_unique_id(struct ospf *ospf, struct ospf_lsdb *lsdb, + u_char type, struct prefix_ipv4 *p) +{ + struct ospf_lsa *lsa; + struct in_addr mask, id; + + id = p->prefix; + + /* Check existence of LSA instance. */ + lsa = ospf_lsdb_lookup_by_id(lsdb, type, id, ospf->router_id); + if (lsa) { + struct as_external_lsa *al = + (struct as_external_lsa *)lsa->data; + if (ip_masklen(al->mask) == p->prefixlen) { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "ospf_lsa_unique_id(): " + "Can't get Link State ID for %s/%d", + inet_ntoa(p->prefix), p->prefixlen); + /* id.s_addr = 0; */ + id.s_addr = 0xffffffff; + return id; + } + /* Masklen differs, then apply wildcard mask to Link State ID. + */ + else { + masklen2ip(p->prefixlen, &mask); + + id.s_addr = p->prefix.s_addr | (~mask.s_addr); + lsa = ospf_lsdb_lookup_by_id(ospf->lsdb, type, id, + ospf->router_id); + if (lsa) { + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "ospf_lsa_unique_id(): " + "Can't get Link State ID for %s/%d", + inet_ntoa(p->prefix), + p->prefixlen); + /* id.s_addr = 0; */ + id.s_addr = 0xffffffff; + return id; + } + } + } + + return id; } #define LSA_ACTION_FLOOD_AREA 1 #define LSA_ACTION_FLUSH_AREA 2 -struct lsa_action -{ - u_char action; - struct ospf_area *area; - struct ospf_lsa *lsa; +struct lsa_action { + u_char action; + struct ospf_area *area; + struct ospf_lsa *lsa; }; -static int -ospf_lsa_action (struct thread *t) +static int ospf_lsa_action(struct thread *t) { - struct lsa_action *data; + struct lsa_action *data; - data = THREAD_ARG (t); + data = THREAD_ARG(t); - if (IS_DEBUG_OSPF (lsa, LSA) == OSPF_DEBUG_LSA) - zlog_debug ("LSA[Action]: Performing scheduled LSA action: %d", - data->action); + if (IS_DEBUG_OSPF(lsa, LSA) == OSPF_DEBUG_LSA) + zlog_debug("LSA[Action]: Performing scheduled LSA action: %d", + data->action); - switch (data->action) - { - case LSA_ACTION_FLOOD_AREA: - ospf_flood_through_area (data->area, NULL, data->lsa); - break; - case LSA_ACTION_FLUSH_AREA: - ospf_lsa_flush_area (data->lsa, data->area); - break; - } + switch (data->action) { + case LSA_ACTION_FLOOD_AREA: + ospf_flood_through_area(data->area, NULL, data->lsa); + break; + case LSA_ACTION_FLUSH_AREA: + ospf_lsa_flush_area(data->lsa, data->area); + break; + } - ospf_lsa_unlock (&data->lsa); /* Message */ - XFREE (MTYPE_OSPF_MESSAGE, data); - return 0; + ospf_lsa_unlock(&data->lsa); /* Message */ + XFREE(MTYPE_OSPF_MESSAGE, data); + return 0; } -void -ospf_schedule_lsa_flood_area (struct ospf_area *area, struct ospf_lsa *lsa) +void ospf_schedule_lsa_flood_area(struct ospf_area *area, struct ospf_lsa *lsa) { - struct lsa_action *data; + struct lsa_action *data; - data = XCALLOC (MTYPE_OSPF_MESSAGE, sizeof (struct lsa_action)); - data->action = LSA_ACTION_FLOOD_AREA; - data->area = area; - data->lsa = ospf_lsa_lock (lsa); /* Message / Flood area */ + data = XCALLOC(MTYPE_OSPF_MESSAGE, sizeof(struct lsa_action)); + data->action = LSA_ACTION_FLOOD_AREA; + data->area = area; + data->lsa = ospf_lsa_lock(lsa); /* Message / Flood area */ - thread_add_event(master, ospf_lsa_action, data, 0, NULL); + thread_add_event(master, ospf_lsa_action, data, 0, NULL); } -void -ospf_schedule_lsa_flush_area (struct ospf_area *area, struct ospf_lsa *lsa) +void ospf_schedule_lsa_flush_area(struct ospf_area *area, struct ospf_lsa *lsa) { - struct lsa_action *data; + struct lsa_action *data; - data = XCALLOC (MTYPE_OSPF_MESSAGE, sizeof (struct lsa_action)); - data->action = LSA_ACTION_FLUSH_AREA; - data->area = area; - data->lsa = ospf_lsa_lock (lsa); /* Message / Flush area */ + data = XCALLOC(MTYPE_OSPF_MESSAGE, sizeof(struct lsa_action)); + data->action = LSA_ACTION_FLUSH_AREA; + data->area = area; + data->lsa = ospf_lsa_lock(lsa); /* Message / Flush area */ - thread_add_event(master, ospf_lsa_action, data, 0, NULL); + thread_add_event(master, ospf_lsa_action, data, 0, NULL); } /* LSA Refreshment functions. */ -struct ospf_lsa * -ospf_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa) -{ - struct external_info *ei; - struct ospf_lsa *new = NULL; - assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF)); - assert (IS_LSA_SELF (lsa)); - assert (lsa->lock > 0); - - switch (lsa->data->type) - { - /* Router and Network LSAs are processed differently. */ - case OSPF_ROUTER_LSA: - new = ospf_router_lsa_refresh (lsa); - break; - case OSPF_NETWORK_LSA: - new = ospf_network_lsa_refresh (lsa); - break; - case OSPF_SUMMARY_LSA: - new = ospf_summary_lsa_refresh (ospf, lsa); - break; - case OSPF_ASBR_SUMMARY_LSA: - new = ospf_summary_asbr_lsa_refresh (ospf, lsa); - break; - case OSPF_AS_EXTERNAL_LSA: - /* Translated from NSSA Type-5s are refreshed when - * from refresh of Type-7 - do not refresh these directly. - */ - if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)) - break; - ei = ospf_external_info_check (lsa); - if (ei) - new = ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_FORCE); - else - ospf_lsa_flush_as (ospf, lsa); - break; - case OSPF_OPAQUE_LINK_LSA: - case OSPF_OPAQUE_AREA_LSA: - case OSPF_OPAQUE_AS_LSA: - new = ospf_opaque_lsa_refresh (lsa); - break; - default: - break; - } - return new; -} - -void -ospf_refresher_register_lsa (struct ospf *ospf, struct ospf_lsa *lsa) -{ - u_int16_t index, current_index; - - assert (lsa->lock > 0); - assert (IS_LSA_SELF (lsa)); - - if (lsa->refresh_list < 0) - { - int delay; - int min_delay = OSPF_LS_REFRESH_TIME - (2 * OSPF_LS_REFRESH_JITTER); - int max_delay = OSPF_LS_REFRESH_TIME - OSPF_LS_REFRESH_JITTER; - - /* We want to refresh the LSA within OSPF_LS_REFRESH_TIME which is - * 1800s. Use jitter so that we send the LSA sometime between 1680s - * and 1740s. - */ - delay = (random() % (max_delay - min_delay)) + min_delay; - - current_index = ospf->lsa_refresh_queue.index + (monotime(NULL) - - ospf->lsa_refresher_started)/OSPF_LSA_REFRESHER_GRANULARITY; - - index = (current_index + delay/OSPF_LSA_REFRESHER_GRANULARITY) - % (OSPF_LSA_REFRESHER_SLOTS); - - if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) - zlog_debug ("LSA[Refresh:Type%d:%s]: age %d, added to index %d", - lsa->data->type, inet_ntoa (lsa->data->id), LS_AGE (lsa), index); - - if (!ospf->lsa_refresh_queue.qs[index]) - ospf->lsa_refresh_queue.qs[index] = list_new (); - - listnode_add (ospf->lsa_refresh_queue.qs[index], - ospf_lsa_lock (lsa)); /* lsa_refresh_queue */ - lsa->refresh_list = index; - - if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) - zlog_debug ("LSA[Refresh:Type%d:%s]: ospf_refresher_register_lsa(): " - "setting refresh_list on lsa %p (slod %d)", - lsa->data->type, inet_ntoa (lsa->data->id), (void *)lsa, index); - } -} - -void -ospf_refresher_unregister_lsa (struct ospf *ospf, struct ospf_lsa *lsa) -{ - assert (lsa->lock > 0); - assert (IS_LSA_SELF (lsa)); - if (lsa->refresh_list >= 0) - { - struct list *refresh_list = ospf->lsa_refresh_queue.qs[lsa->refresh_list]; - listnode_delete (refresh_list, lsa); - if (!listcount (refresh_list)) - { - list_free (refresh_list); - ospf->lsa_refresh_queue.qs[lsa->refresh_list] = NULL; - } - ospf_lsa_unlock (&lsa); /* lsa_refresh_queue */ - lsa->refresh_list = -1; - } -} - -int -ospf_lsa_refresh_walker (struct thread *t) -{ - struct list *refresh_list; - struct listnode *node, *nnode; - struct ospf *ospf = THREAD_ARG (t); - struct ospf_lsa *lsa; - int i; - struct list *lsa_to_refresh = list_new (); - - if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) - zlog_debug ("LSA[Refresh]: ospf_lsa_refresh_walker(): start"); - - - i = ospf->lsa_refresh_queue.index; - - /* Note: if clock has jumped backwards, then time change could be negative, - so we are careful to cast the expression to unsigned before taking - modulus. */ - ospf->lsa_refresh_queue.index = - ((unsigned long)(ospf->lsa_refresh_queue.index + - (monotime(NULL) - ospf->lsa_refresher_started) - / OSPF_LSA_REFRESHER_GRANULARITY)) - % OSPF_LSA_REFRESHER_SLOTS; - - if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) - zlog_debug ("LSA[Refresh]: ospf_lsa_refresh_walker(): next index %d", - ospf->lsa_refresh_queue.index); - - for (;i != ospf->lsa_refresh_queue.index; - i = (i + 1) % OSPF_LSA_REFRESHER_SLOTS) - { - if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) - zlog_debug ("LSA[Refresh]: ospf_lsa_refresh_walker(): " - "refresh index %d", i); - - refresh_list = ospf->lsa_refresh_queue.qs [i]; - - assert (i >= 0); - - ospf->lsa_refresh_queue.qs [i] = NULL; - - if (refresh_list) - { - for (ALL_LIST_ELEMENTS (refresh_list, node, nnode, lsa)) - { - if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) - zlog_debug ("LSA[Refresh:Type%d:%s]: ospf_lsa_refresh_walker(): " - "refresh lsa %p (slot %d)", - lsa->data->type, inet_ntoa (lsa->data->id), (void *)lsa, i); - - assert (lsa->lock > 0); - list_delete_node (refresh_list, node); - lsa->refresh_list = -1; - listnode_add (lsa_to_refresh, lsa); - } - list_free (refresh_list); - } - } - - ospf->t_lsa_refresher = NULL; - thread_add_timer(master, ospf_lsa_refresh_walker, ospf, ospf->lsa_refresh_interval, - &ospf->t_lsa_refresher); - ospf->lsa_refresher_started = monotime(NULL); - - for (ALL_LIST_ELEMENTS (lsa_to_refresh, node, nnode, lsa)) - { - ospf_lsa_refresh (ospf, lsa); - assert (lsa->lock > 0); - ospf_lsa_unlock (&lsa); /* lsa_refresh_queue & temp for lsa_to_refresh*/ - } - - list_delete (lsa_to_refresh); - - if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) - zlog_debug ("LSA[Refresh]: ospf_lsa_refresh_walker(): end"); - - return 0; +struct ospf_lsa *ospf_lsa_refresh(struct ospf *ospf, struct ospf_lsa *lsa) +{ + struct external_info *ei; + struct ospf_lsa *new = NULL; + assert(CHECK_FLAG(lsa->flags, OSPF_LSA_SELF)); + assert(IS_LSA_SELF(lsa)); + assert(lsa->lock > 0); + + switch (lsa->data->type) { + /* Router and Network LSAs are processed differently. */ + case OSPF_ROUTER_LSA: + new = ospf_router_lsa_refresh(lsa); + break; + case OSPF_NETWORK_LSA: + new = ospf_network_lsa_refresh(lsa); + break; + case OSPF_SUMMARY_LSA: + new = ospf_summary_lsa_refresh(ospf, lsa); + break; + case OSPF_ASBR_SUMMARY_LSA: + new = ospf_summary_asbr_lsa_refresh(ospf, lsa); + break; + case OSPF_AS_EXTERNAL_LSA: + /* Translated from NSSA Type-5s are refreshed when + * from refresh of Type-7 - do not refresh these directly. + */ + if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) + break; + ei = ospf_external_info_check(lsa); + if (ei) + new = ospf_external_lsa_refresh(ospf, lsa, ei, + LSA_REFRESH_FORCE); + else + ospf_lsa_flush_as(ospf, lsa); + break; + case OSPF_OPAQUE_LINK_LSA: + case OSPF_OPAQUE_AREA_LSA: + case OSPF_OPAQUE_AS_LSA: + new = ospf_opaque_lsa_refresh(lsa); + break; + default: + break; + } + return new; } +void ospf_refresher_register_lsa(struct ospf *ospf, struct ospf_lsa *lsa) +{ + u_int16_t index, current_index; + + assert(lsa->lock > 0); + assert(IS_LSA_SELF(lsa)); + + if (lsa->refresh_list < 0) { + int delay; + int min_delay = + OSPF_LS_REFRESH_TIME - (2 * OSPF_LS_REFRESH_JITTER); + int max_delay = OSPF_LS_REFRESH_TIME - OSPF_LS_REFRESH_JITTER; + + /* We want to refresh the LSA within OSPF_LS_REFRESH_TIME which + * is + * 1800s. Use jitter so that we send the LSA sometime between + * 1680s + * and 1740s. + */ + delay = (random() % (max_delay - min_delay)) + min_delay; + + current_index = ospf->lsa_refresh_queue.index + + (monotime(NULL) - ospf->lsa_refresher_started) + / OSPF_LSA_REFRESHER_GRANULARITY; + + index = (current_index + delay / OSPF_LSA_REFRESHER_GRANULARITY) + % (OSPF_LSA_REFRESHER_SLOTS); + + if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) + zlog_debug( + "LSA[Refresh:Type%d:%s]: age %d, added to index %d", + lsa->data->type, inet_ntoa(lsa->data->id), + LS_AGE(lsa), index); + + if (!ospf->lsa_refresh_queue.qs[index]) + ospf->lsa_refresh_queue.qs[index] = list_new(); + + listnode_add(ospf->lsa_refresh_queue.qs[index], + ospf_lsa_lock(lsa)); /* lsa_refresh_queue */ + lsa->refresh_list = index; + + if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) + zlog_debug( + "LSA[Refresh:Type%d:%s]: ospf_refresher_register_lsa(): " + "setting refresh_list on lsa %p (slod %d)", + lsa->data->type, inet_ntoa(lsa->data->id), + (void *)lsa, index); + } +} + +void ospf_refresher_unregister_lsa(struct ospf *ospf, struct ospf_lsa *lsa) +{ + assert(lsa->lock > 0); + assert(IS_LSA_SELF(lsa)); + if (lsa->refresh_list >= 0) { + struct list *refresh_list = + ospf->lsa_refresh_queue.qs[lsa->refresh_list]; + listnode_delete(refresh_list, lsa); + if (!listcount(refresh_list)) { + list_free(refresh_list); + ospf->lsa_refresh_queue.qs[lsa->refresh_list] = NULL; + } + ospf_lsa_unlock(&lsa); /* lsa_refresh_queue */ + lsa->refresh_list = -1; + } +} + +int ospf_lsa_refresh_walker(struct thread *t) +{ + struct list *refresh_list; + struct listnode *node, *nnode; + struct ospf *ospf = THREAD_ARG(t); + struct ospf_lsa *lsa; + int i; + struct list *lsa_to_refresh = list_new(); + + if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) + zlog_debug("LSA[Refresh]: ospf_lsa_refresh_walker(): start"); + + + i = ospf->lsa_refresh_queue.index; + + /* Note: if clock has jumped backwards, then time change could be + negative, + so we are careful to cast the expression to unsigned before taking + modulus. */ + ospf->lsa_refresh_queue.index = + ((unsigned long)(ospf->lsa_refresh_queue.index + + (monotime(NULL) + - ospf->lsa_refresher_started) + / OSPF_LSA_REFRESHER_GRANULARITY)) + % OSPF_LSA_REFRESHER_SLOTS; + + if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) + zlog_debug( + "LSA[Refresh]: ospf_lsa_refresh_walker(): next index %d", + ospf->lsa_refresh_queue.index); + + for (; i != ospf->lsa_refresh_queue.index; + i = (i + 1) % OSPF_LSA_REFRESHER_SLOTS) { + if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) + zlog_debug( + "LSA[Refresh]: ospf_lsa_refresh_walker(): " + "refresh index %d", + i); + + refresh_list = ospf->lsa_refresh_queue.qs[i]; + + assert(i >= 0); + + ospf->lsa_refresh_queue.qs[i] = NULL; + + if (refresh_list) { + for (ALL_LIST_ELEMENTS(refresh_list, node, nnode, + lsa)) { + if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) + zlog_debug( + "LSA[Refresh:Type%d:%s]: ospf_lsa_refresh_walker(): " + "refresh lsa %p (slot %d)", + lsa->data->type, + inet_ntoa(lsa->data->id), + (void *)lsa, i); + + assert(lsa->lock > 0); + list_delete_node(refresh_list, node); + lsa->refresh_list = -1; + listnode_add(lsa_to_refresh, lsa); + } + list_free(refresh_list); + } + } + + ospf->t_lsa_refresher = NULL; + thread_add_timer(master, ospf_lsa_refresh_walker, ospf, + ospf->lsa_refresh_interval, &ospf->t_lsa_refresher); + ospf->lsa_refresher_started = monotime(NULL); + + for (ALL_LIST_ELEMENTS(lsa_to_refresh, node, nnode, lsa)) { + ospf_lsa_refresh(ospf, lsa); + assert(lsa->lock > 0); + ospf_lsa_unlock( + &lsa); /* lsa_refresh_queue & temp for lsa_to_refresh*/ + } + + list_delete(lsa_to_refresh); + + if (IS_DEBUG_OSPF(lsa, LSA_REFRESH)) + zlog_debug("LSA[Refresh]: ospf_lsa_refresh_walker(): end"); + + return 0; +} diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index b6f2526c9..ab8e62b6e 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -52,23 +52,21 @@ #define LSA_REFRESH_FORCE 1 /* OSPF LSA header. */ -struct lsa_header -{ - u_int16_t ls_age; - u_char options; - u_char type; - struct in_addr id; - struct in_addr adv_router; - u_int32_t ls_seqnum; - u_int16_t checksum; - u_int16_t length; +struct lsa_header { + u_int16_t ls_age; + u_char options; + u_char type; + struct in_addr id; + struct in_addr adv_router; + u_int32_t ls_seqnum; + u_int16_t checksum; + u_int16_t length; }; /* OSPF LSA. */ -struct ospf_lsa -{ - /* LSA origination flag. */ - u_char flags; +struct ospf_lsa { + /* LSA origination flag. */ + u_char flags; #define OSPF_LSA_SELF 0x01 #define OSPF_LSA_SELF_CHECKED 0x02 #define OSPF_LSA_RECEIVED 0x04 @@ -78,41 +76,41 @@ struct ospf_lsa #define OSPF_LSA_PREMATURE_AGE 0x40 #define OSPF_LSA_IN_MAXAGE 0x80 - /* LSA data. */ - struct lsa_header *data; + /* LSA data. */ + struct lsa_header *data; - /* Received time stamp. */ - struct timeval tv_recv; + /* Received time stamp. */ + struct timeval tv_recv; - /* Last time it was originated */ - struct timeval tv_orig; + /* Last time it was originated */ + struct timeval tv_orig; - /* All of reference count, also lock to remove. */ - int lock; + /* All of reference count, also lock to remove. */ + int lock; - /* Flags for the SPF calculation. */ - int stat; - #define LSA_SPF_NOT_EXPLORED -1 - #define LSA_SPF_IN_SPFTREE -2 - /* If stat >= 0, stat is LSA position in candidates heap. */ - - /* References to this LSA in neighbor retransmission lists*/ - int retransmit_counter; + /* Flags for the SPF calculation. */ + int stat; +#define LSA_SPF_NOT_EXPLORED -1 +#define LSA_SPF_IN_SPFTREE -2 + /* If stat >= 0, stat is LSA position in candidates heap. */ - /* Area the LSA belongs to, may be NULL if AS-external-LSA. */ - struct ospf_area *area; + /* References to this LSA in neighbor retransmission lists*/ + int retransmit_counter; - /* Parent LSDB. */ - struct ospf_lsdb *lsdb; + /* Area the LSA belongs to, may be NULL if AS-external-LSA. */ + struct ospf_area *area; - /* Related Route. */ - void *route; + /* Parent LSDB. */ + struct ospf_lsdb *lsdb; - /* Refreshement List or Queue */ - int refresh_list; - - /* For Type-9 Opaque-LSAs */ - struct ospf_interface *oi; + /* Related Route. */ + void *route; + + /* Refreshement List or Queue */ + int refresh_list; + + /* For Type-9 Opaque-LSAs */ + struct ospf_interface *oi; }; /* OSPF LSA Link Type. */ @@ -135,16 +133,14 @@ struct ospf_lsa #define IS_ROUTER_LSA_NT(x) ((x)->flags & ROUTER_LSA_NT) /* OSPF Router-LSA Link information. */ -struct router_lsa_link -{ - struct in_addr link_id; - struct in_addr link_data; - struct - { - u_char type; - u_char tos_count; - u_int16_t metric; - } m[1]; +struct router_lsa_link { + struct in_addr link_id; + struct in_addr link_data; + struct { + u_char type; + u_char tos_count; + u_int16_t metric; + } m[1]; }; /* OSPF Router-LSAs structure. */ @@ -156,54 +152,48 @@ struct router_lsa_link reached (RFC2328 12.4.1.3). In this case the Router-LSA initially received by the other end of the VL will have 0 link descriptor blocks, but soon will be replaced with the next revision having 1 descriptor block. */ -struct router_lsa -{ - struct lsa_header header; - u_char flags; - u_char zero; - u_int16_t links; - struct - { - struct in_addr link_id; - struct in_addr link_data; - u_char type; - u_char tos; - u_int16_t metric; - } link[1]; +struct router_lsa { + struct lsa_header header; + u_char flags; + u_char zero; + u_int16_t links; + struct { + struct in_addr link_id; + struct in_addr link_data; + u_char type; + u_char tos; + u_int16_t metric; + } link[1]; }; /* OSPF Network-LSAs structure. */ #define OSPF_NETWORK_LSA_MIN_SIZE 8U /* w/1 router-ID */ -struct network_lsa -{ - struct lsa_header header; - struct in_addr mask; - struct in_addr routers[1]; +struct network_lsa { + struct lsa_header header; + struct in_addr mask; + struct in_addr routers[1]; }; /* OSPF Summary-LSAs structure. */ #define OSPF_SUMMARY_LSA_MIN_SIZE 8U /* w/1 TOS metric block */ -struct summary_lsa -{ - struct lsa_header header; - struct in_addr mask; - u_char tos; - u_char metric[3]; +struct summary_lsa { + struct lsa_header header; + struct in_addr mask; + u_char tos; + u_char metric[3]; }; /* OSPF AS-external-LSAs structure. */ #define OSPF_AS_EXTERNAL_LSA_MIN_SIZE 16U /* w/1 TOS forwarding block */ -struct as_external_lsa -{ - struct lsa_header header; - struct in_addr mask; - struct - { - u_char tos; - u_char metric[3]; - struct in_addr fwd_addr; - u_int32_t route_tag; - } e[1]; +struct as_external_lsa { + struct lsa_header header; + struct in_addr mask; + struct { + u_char tos; + u_char metric[3]; + struct in_addr fwd_addr; + u_int32_t route_tag; + } e[1]; }; #include "ospfd/ospf_opaque.h" @@ -213,121 +203,122 @@ struct as_external_lsa #define IS_EXTERNAL_METRIC(x) ((x) & 0x80) #define GET_AGE(x) (ntohs ((x)->data->ls_age) + time (NULL) - (x)->tv_recv) -#define LS_AGE(x) (OSPF_LSA_MAXAGE < get_age(x) ? \ - OSPF_LSA_MAXAGE : get_age(x)) +#define LS_AGE(x) (OSPF_LSA_MAXAGE < get_age(x) ? OSPF_LSA_MAXAGE : get_age(x)) #define IS_LSA_SELF(L) (CHECK_FLAG ((L)->flags, OSPF_LSA_SELF)) #define IS_LSA_MAXAGE(L) (LS_AGE ((L)) == OSPF_LSA_MAXAGE) #define OSPF_LSA_UPDATE_DELAY 2 -#define OSPF_LSA_UPDATE_TIMER_ON(T,F) \ - if (!(T)) \ - (T) = thread_add_timer (master, (F), 0, 2) +#define OSPF_LSA_UPDATE_TIMER_ON(T, F) \ + if (!(T)) \ + (T) = thread_add_timer(master, (F), 0, 2) /* Prototypes. */ /* XXX: Eek, time functions, similar are in lib/thread.c */ -extern struct timeval int2tv (int); -extern struct timeval msec2tv (int); +extern struct timeval int2tv(int); +extern struct timeval msec2tv(int); -extern int get_age (struct ospf_lsa *); -extern u_int16_t ospf_lsa_checksum (struct lsa_header *); -extern int ospf_lsa_checksum_valid (struct lsa_header *); -extern int ospf_lsa_refresh_delay (struct ospf_lsa *); +extern int get_age(struct ospf_lsa *); +extern u_int16_t ospf_lsa_checksum(struct lsa_header *); +extern int ospf_lsa_checksum_valid(struct lsa_header *); +extern int ospf_lsa_refresh_delay(struct ospf_lsa *); -extern const char *dump_lsa_key (struct ospf_lsa *); -extern u_int32_t lsa_seqnum_increment (struct ospf_lsa *); -extern void lsa_header_set (struct stream *, u_char, u_char, struct in_addr, - struct in_addr); -extern struct ospf_neighbor *ospf_nbr_lookup_ptop (struct ospf_interface *); -extern int ospf_check_nbr_status (struct ospf *); +extern const char *dump_lsa_key(struct ospf_lsa *); +extern u_int32_t lsa_seqnum_increment(struct ospf_lsa *); +extern void lsa_header_set(struct stream *, u_char, u_char, struct in_addr, + struct in_addr); +extern struct ospf_neighbor *ospf_nbr_lookup_ptop(struct ospf_interface *); +extern int ospf_check_nbr_status(struct ospf *); /* Prototype for LSA primitive. */ -extern struct ospf_lsa *ospf_lsa_new (void); -extern struct ospf_lsa *ospf_lsa_dup (struct ospf_lsa *); -extern void ospf_lsa_free (struct ospf_lsa *); -extern struct ospf_lsa *ospf_lsa_lock (struct ospf_lsa *); -extern void ospf_lsa_unlock (struct ospf_lsa **); -extern void ospf_lsa_discard (struct ospf_lsa *); -extern int ospf_lsa_flush_schedule (struct ospf *, struct ospf_lsa *); -extern struct lsa_header *ospf_lsa_data_new (size_t); -extern struct lsa_header *ospf_lsa_data_dup (struct lsa_header *); -extern void ospf_lsa_data_free (struct lsa_header *); +extern struct ospf_lsa *ospf_lsa_new(void); +extern struct ospf_lsa *ospf_lsa_dup(struct ospf_lsa *); +extern void ospf_lsa_free(struct ospf_lsa *); +extern struct ospf_lsa *ospf_lsa_lock(struct ospf_lsa *); +extern void ospf_lsa_unlock(struct ospf_lsa **); +extern void ospf_lsa_discard(struct ospf_lsa *); +extern int ospf_lsa_flush_schedule(struct ospf *, struct ospf_lsa *); +extern struct lsa_header *ospf_lsa_data_new(size_t); +extern struct lsa_header *ospf_lsa_data_dup(struct lsa_header *); +extern void ospf_lsa_data_free(struct lsa_header *); /* Prototype for various LSAs */ -extern int ospf_router_lsa_update (struct ospf *); -extern int ospf_router_lsa_update_area (struct ospf_area *); - -extern void ospf_network_lsa_update (struct ospf_interface *); - -extern struct ospf_lsa *ospf_summary_lsa_originate (struct prefix_ipv4 *, u_int32_t, - struct ospf_area *); -extern struct ospf_lsa *ospf_summary_asbr_lsa_originate (struct prefix_ipv4 *, - u_int32_t, - struct ospf_area *); - -extern struct ospf_lsa *ospf_lsa_install (struct ospf *, - struct ospf_interface *, struct ospf_lsa *); - -extern void ospf_nssa_lsa_flush (struct ospf *ospf, struct prefix_ipv4 *p); -extern void ospf_external_lsa_flush (struct ospf *, u_char, struct prefix_ipv4 *, - ifindex_t /* , struct in_addr nexthop */); - -extern struct in_addr ospf_get_ip_from_ifp (struct ospf_interface *); - -extern struct ospf_lsa *ospf_external_lsa_originate (struct ospf *, struct external_info *); -extern int ospf_external_lsa_originate_timer (struct thread *); -extern int ospf_default_originate_timer (struct thread *); -extern struct ospf_lsa *ospf_lsa_lookup (struct ospf_area *, u_int32_t, - struct in_addr, struct in_addr); -extern struct ospf_lsa *ospf_lsa_lookup_by_id (struct ospf_area *, - u_int32_t, - struct in_addr); -extern struct ospf_lsa *ospf_lsa_lookup_by_header (struct ospf_area *, - struct lsa_header *); -extern int ospf_lsa_more_recent (struct ospf_lsa *, struct ospf_lsa *); -extern int ospf_lsa_different (struct ospf_lsa *, struct ospf_lsa *); -extern void ospf_flush_self_originated_lsas_now (struct ospf *); - -extern int ospf_lsa_is_self_originated (struct ospf *, struct ospf_lsa *); - -extern struct ospf_lsa *ospf_lsa_lookup_by_prefix (struct ospf_lsdb *, u_char, - struct prefix_ipv4 *, - struct in_addr); - -extern void ospf_lsa_maxage (struct ospf *, struct ospf_lsa *); -extern u_int32_t get_metric (u_char *); - -extern int ospf_lsa_maxage_walker (struct thread *); -extern struct ospf_lsa *ospf_lsa_refresh (struct ospf *, struct ospf_lsa *); - -extern void ospf_external_lsa_refresh_default (struct ospf *); - -extern void ospf_external_lsa_refresh_type (struct ospf *, u_char, u_short, int); -extern struct ospf_lsa *ospf_external_lsa_refresh (struct ospf *, - struct ospf_lsa *, - struct external_info *, - int); -extern struct in_addr ospf_lsa_unique_id (struct ospf *, struct ospf_lsdb *, u_char, - struct prefix_ipv4 *); -extern void ospf_schedule_lsa_flood_area (struct ospf_area *, struct ospf_lsa *); -extern void ospf_schedule_lsa_flush_area (struct ospf_area *, struct ospf_lsa *); - -extern void ospf_refresher_register_lsa (struct ospf *, struct ospf_lsa *); -extern void ospf_refresher_unregister_lsa (struct ospf *, struct ospf_lsa *); -extern int ospf_lsa_refresh_walker (struct thread *); - -extern void ospf_lsa_maxage_delete (struct ospf *, struct ospf_lsa *); - -extern void ospf_discard_from_db (struct ospf *, struct ospf_lsdb *, struct ospf_lsa*); -extern int is_prefix_default (struct prefix_ipv4 *); - -extern int metric_type (struct ospf *, u_char, u_short); -extern int metric_value (struct ospf *, u_char, u_short); - -extern struct in_addr ospf_get_nssa_ip (struct ospf_area *); -extern int ospf_translated_nssa_compare (struct ospf_lsa *, struct ospf_lsa *); -extern struct ospf_lsa *ospf_translated_nssa_refresh (struct ospf *, struct ospf_lsa *, - struct ospf_lsa *); -extern struct ospf_lsa *ospf_translated_nssa_originate (struct ospf *, struct ospf_lsa *); +extern int ospf_router_lsa_update(struct ospf *); +extern int ospf_router_lsa_update_area(struct ospf_area *); + +extern void ospf_network_lsa_update(struct ospf_interface *); + +extern struct ospf_lsa * +ospf_summary_lsa_originate(struct prefix_ipv4 *, u_int32_t, struct ospf_area *); +extern struct ospf_lsa *ospf_summary_asbr_lsa_originate(struct prefix_ipv4 *, + u_int32_t, + struct ospf_area *); + +extern struct ospf_lsa *ospf_lsa_install(struct ospf *, struct ospf_interface *, + struct ospf_lsa *); + +extern void ospf_nssa_lsa_flush(struct ospf *ospf, struct prefix_ipv4 *p); +extern void ospf_external_lsa_flush(struct ospf *, u_char, struct prefix_ipv4 *, + ifindex_t /* , struct in_addr nexthop */); + +extern struct in_addr ospf_get_ip_from_ifp(struct ospf_interface *); + +extern struct ospf_lsa *ospf_external_lsa_originate(struct ospf *, + struct external_info *); +extern int ospf_external_lsa_originate_timer(struct thread *); +extern int ospf_default_originate_timer(struct thread *); +extern struct ospf_lsa *ospf_lsa_lookup(struct ospf_area *, u_int32_t, + struct in_addr, struct in_addr); +extern struct ospf_lsa *ospf_lsa_lookup_by_id(struct ospf_area *, u_int32_t, + struct in_addr); +extern struct ospf_lsa *ospf_lsa_lookup_by_header(struct ospf_area *, + struct lsa_header *); +extern int ospf_lsa_more_recent(struct ospf_lsa *, struct ospf_lsa *); +extern int ospf_lsa_different(struct ospf_lsa *, struct ospf_lsa *); +extern void ospf_flush_self_originated_lsas_now(struct ospf *); + +extern int ospf_lsa_is_self_originated(struct ospf *, struct ospf_lsa *); + +extern struct ospf_lsa *ospf_lsa_lookup_by_prefix(struct ospf_lsdb *, u_char, + struct prefix_ipv4 *, + struct in_addr); + +extern void ospf_lsa_maxage(struct ospf *, struct ospf_lsa *); +extern u_int32_t get_metric(u_char *); + +extern int ospf_lsa_maxage_walker(struct thread *); +extern struct ospf_lsa *ospf_lsa_refresh(struct ospf *, struct ospf_lsa *); + +extern void ospf_external_lsa_refresh_default(struct ospf *); + +extern void ospf_external_lsa_refresh_type(struct ospf *, u_char, u_short, int); +extern struct ospf_lsa *ospf_external_lsa_refresh(struct ospf *, + struct ospf_lsa *, + struct external_info *, int); +extern struct in_addr ospf_lsa_unique_id(struct ospf *, struct ospf_lsdb *, + u_char, struct prefix_ipv4 *); +extern void ospf_schedule_lsa_flood_area(struct ospf_area *, struct ospf_lsa *); +extern void ospf_schedule_lsa_flush_area(struct ospf_area *, struct ospf_lsa *); + +extern void ospf_refresher_register_lsa(struct ospf *, struct ospf_lsa *); +extern void ospf_refresher_unregister_lsa(struct ospf *, struct ospf_lsa *); +extern int ospf_lsa_refresh_walker(struct thread *); + +extern void ospf_lsa_maxage_delete(struct ospf *, struct ospf_lsa *); + +extern void ospf_discard_from_db(struct ospf *, struct ospf_lsdb *, + struct ospf_lsa *); +extern int is_prefix_default(struct prefix_ipv4 *); + +extern int metric_type(struct ospf *, u_char, u_short); +extern int metric_value(struct ospf *, u_char, u_short); + +extern struct in_addr ospf_get_nssa_ip(struct ospf_area *); +extern int ospf_translated_nssa_compare(struct ospf_lsa *, struct ospf_lsa *); +extern struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *, + struct ospf_lsa *, + struct ospf_lsa *); +extern struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *, + struct ospf_lsa *); #endif /* _ZEBRA_OSPF_LSA_H */ diff --git a/ospfd/ospf_lsdb.c b/ospfd/ospf_lsdb.c index ac22f5bbe..a596d3286 100644 --- a/ospfd/ospf_lsdb.c +++ b/ospfd/ospf_lsdb.c @@ -31,299 +31,274 @@ #include "ospfd/ospf_lsa.h" #include "ospfd/ospf_lsdb.h" -struct ospf_lsdb * -ospf_lsdb_new () +struct ospf_lsdb *ospf_lsdb_new() { - struct ospf_lsdb *new; + struct ospf_lsdb *new; - new = XCALLOC (MTYPE_OSPF_LSDB, sizeof (struct ospf_lsdb)); - ospf_lsdb_init (new); + new = XCALLOC(MTYPE_OSPF_LSDB, sizeof(struct ospf_lsdb)); + ospf_lsdb_init(new); - return new; + return new; } -void -ospf_lsdb_init (struct ospf_lsdb *lsdb) +void ospf_lsdb_init(struct ospf_lsdb *lsdb) { - int i; - - for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) - lsdb->type[i].db = route_table_init (); + int i; + + for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) + lsdb->type[i].db = route_table_init(); } -void -ospf_lsdb_free (struct ospf_lsdb *lsdb) +void ospf_lsdb_free(struct ospf_lsdb *lsdb) { - ospf_lsdb_cleanup (lsdb); - XFREE (MTYPE_OSPF_LSDB, lsdb); + ospf_lsdb_cleanup(lsdb); + XFREE(MTYPE_OSPF_LSDB, lsdb); } -void -ospf_lsdb_cleanup (struct ospf_lsdb *lsdb) +void ospf_lsdb_cleanup(struct ospf_lsdb *lsdb) { - int i; - assert (lsdb); - assert (lsdb->total == 0); - - ospf_lsdb_delete_all (lsdb); - - for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) - route_table_finish (lsdb->type[i].db); + int i; + assert(lsdb); + assert(lsdb->total == 0); + + ospf_lsdb_delete_all(lsdb); + + for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) + route_table_finish(lsdb->type[i].db); } -void -ls_prefix_set (struct prefix_ls *lp, struct ospf_lsa *lsa) +void ls_prefix_set(struct prefix_ls *lp, struct ospf_lsa *lsa) { - if (lp && lsa && lsa->data) - { - lp->family = 0; - lp->prefixlen = 64; - lp->id = lsa->data->id; - lp->adv_router = lsa->data->adv_router; - } + if (lp && lsa && lsa->data) { + lp->family = 0; + lp->prefixlen = 64; + lp->id = lsa->data->id; + lp->adv_router = lsa->data->adv_router; + } } -static void -ospf_lsdb_delete_entry (struct ospf_lsdb *lsdb, struct route_node *rn) +static void ospf_lsdb_delete_entry(struct ospf_lsdb *lsdb, + struct route_node *rn) { - struct ospf_lsa *lsa = rn->info; - - if (!lsa) - return; - - assert (rn->table == lsdb->type[lsa->data->type].db); - - if (IS_LSA_SELF (lsa)) - lsdb->type[lsa->data->type].count_self--; - lsdb->type[lsa->data->type].count--; - lsdb->type[lsa->data->type].checksum -= ntohs(lsa->data->checksum); - lsdb->total--; - rn->info = NULL; - route_unlock_node (rn); + struct ospf_lsa *lsa = rn->info; + + if (!lsa) + return; + + assert(rn->table == lsdb->type[lsa->data->type].db); + + if (IS_LSA_SELF(lsa)) + lsdb->type[lsa->data->type].count_self--; + lsdb->type[lsa->data->type].count--; + lsdb->type[lsa->data->type].checksum -= ntohs(lsa->data->checksum); + lsdb->total--; + rn->info = NULL; + route_unlock_node(rn); #ifdef MONITOR_LSDB_CHANGE - if (lsdb->del_lsa_hook != NULL) - (* lsdb->del_lsa_hook)(lsa); -#endif /* MONITOR_LSDB_CHANGE */ - ospf_lsa_unlock (&lsa); /* lsdb */ - return; + if (lsdb->del_lsa_hook != NULL) + (*lsdb->del_lsa_hook)(lsa); +#endif /* MONITOR_LSDB_CHANGE */ + ospf_lsa_unlock(&lsa); /* lsdb */ + return; } /* Add new LSA to lsdb. */ -void -ospf_lsdb_add (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa) +void ospf_lsdb_add(struct ospf_lsdb *lsdb, struct ospf_lsa *lsa) { - struct route_table *table; - struct prefix_ls lp; - struct route_node *rn; - - table = lsdb->type[lsa->data->type].db; - ls_prefix_set (&lp, lsa); - rn = route_node_get (table, (struct prefix *)&lp); - - /* nothing to do? */ - if (rn->info && rn->info == lsa) - { - route_unlock_node (rn); - return; - } - - /* purge old entry? */ - if (rn->info) - ospf_lsdb_delete_entry (lsdb, rn); - - if (IS_LSA_SELF (lsa)) - lsdb->type[lsa->data->type].count_self++; - lsdb->type[lsa->data->type].count++; - lsdb->total++; + struct route_table *table; + struct prefix_ls lp; + struct route_node *rn; + + table = lsdb->type[lsa->data->type].db; + ls_prefix_set(&lp, lsa); + rn = route_node_get(table, (struct prefix *)&lp); + + /* nothing to do? */ + if (rn->info && rn->info == lsa) { + route_unlock_node(rn); + return; + } + + /* purge old entry? */ + if (rn->info) + ospf_lsdb_delete_entry(lsdb, rn); + + if (IS_LSA_SELF(lsa)) + lsdb->type[lsa->data->type].count_self++; + lsdb->type[lsa->data->type].count++; + lsdb->total++; #ifdef MONITOR_LSDB_CHANGE - if (lsdb->new_lsa_hook != NULL) - (* lsdb->new_lsa_hook)(lsa); + if (lsdb->new_lsa_hook != NULL) + (*lsdb->new_lsa_hook)(lsa); #endif /* MONITOR_LSDB_CHANGE */ - lsdb->type[lsa->data->type].checksum += ntohs(lsa->data->checksum); - rn->info = ospf_lsa_lock (lsa); /* lsdb */ + lsdb->type[lsa->data->type].checksum += ntohs(lsa->data->checksum); + rn->info = ospf_lsa_lock(lsa); /* lsdb */ } -void -ospf_lsdb_delete (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa) +void ospf_lsdb_delete(struct ospf_lsdb *lsdb, struct ospf_lsa *lsa) { - struct route_table *table; - struct prefix_ls lp; - struct route_node *rn; - - if (!lsdb) - { - zlog_warn ("%s: Called with NULL LSDB", __func__); - if (lsa) - zlog_warn ("LSA[Type%d:%s]: LSA %p, lsa->lsdb %p", - lsa->data->type, inet_ntoa (lsa->data->id), - (void *)lsa, (void *)lsa->lsdb); - return; - } - - if (!lsa) - { - zlog_warn ("%s: Called with NULL LSA", __func__); - return; - } - - assert (lsa->data->type < OSPF_MAX_LSA); - table = lsdb->type[lsa->data->type].db; - ls_prefix_set (&lp, lsa); - if ((rn = route_node_lookup (table, (struct prefix *) &lp))) - { - if (rn->info == lsa) - ospf_lsdb_delete_entry (lsdb, rn); - route_unlock_node (rn); /* route_node_lookup */ - } + struct route_table *table; + struct prefix_ls lp; + struct route_node *rn; + + if (!lsdb) { + zlog_warn("%s: Called with NULL LSDB", __func__); + if (lsa) + zlog_warn("LSA[Type%d:%s]: LSA %p, lsa->lsdb %p", + lsa->data->type, inet_ntoa(lsa->data->id), + (void *)lsa, (void *)lsa->lsdb); + return; + } + + if (!lsa) { + zlog_warn("%s: Called with NULL LSA", __func__); + return; + } + + assert(lsa->data->type < OSPF_MAX_LSA); + table = lsdb->type[lsa->data->type].db; + ls_prefix_set(&lp, lsa); + if ((rn = route_node_lookup(table, (struct prefix *)&lp))) { + if (rn->info == lsa) + ospf_lsdb_delete_entry(lsdb, rn); + route_unlock_node(rn); /* route_node_lookup */ + } } -void -ospf_lsdb_delete_all (struct ospf_lsdb *lsdb) +void ospf_lsdb_delete_all(struct ospf_lsdb *lsdb) { - struct route_table *table; - struct route_node *rn; - int i; - - for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) - { - table = lsdb->type[i].db; - for (rn = route_top (table); rn; rn = route_next (rn)) - if (rn->info != NULL) - ospf_lsdb_delete_entry (lsdb, rn); - } + struct route_table *table; + struct route_node *rn; + int i; + + for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) { + table = lsdb->type[i].db; + for (rn = route_top(table); rn; rn = route_next(rn)) + if (rn->info != NULL) + ospf_lsdb_delete_entry(lsdb, rn); + } } -void -ospf_lsdb_clean_stat (struct ospf_lsdb *lsdb) +void ospf_lsdb_clean_stat(struct ospf_lsdb *lsdb) { - struct route_table *table; - struct route_node *rn; - struct ospf_lsa *lsa; - int i; - - for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) - { - table = lsdb->type[i].db; - for (rn = route_top (table); rn; rn = route_next (rn)) - if ((lsa = (rn->info)) != NULL) - lsa->stat = LSA_SPF_NOT_EXPLORED; - } + struct route_table *table; + struct route_node *rn; + struct ospf_lsa *lsa; + int i; + + for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) { + table = lsdb->type[i].db; + for (rn = route_top(table); rn; rn = route_next(rn)) + if ((lsa = (rn->info)) != NULL) + lsa->stat = LSA_SPF_NOT_EXPLORED; + } } -struct ospf_lsa * -ospf_lsdb_lookup (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa) +struct ospf_lsa *ospf_lsdb_lookup(struct ospf_lsdb *lsdb, struct ospf_lsa *lsa) { - struct route_table *table; - struct prefix_ls lp; - struct route_node *rn; - struct ospf_lsa *find; - - table = lsdb->type[lsa->data->type].db; - ls_prefix_set (&lp, lsa); - rn = route_node_lookup (table, (struct prefix *) &lp); - if (rn) - { - find = rn->info; - route_unlock_node (rn); - return find; - } - return NULL; + struct route_table *table; + struct prefix_ls lp; + struct route_node *rn; + struct ospf_lsa *find; + + table = lsdb->type[lsa->data->type].db; + ls_prefix_set(&lp, lsa); + rn = route_node_lookup(table, (struct prefix *)&lp); + if (rn) { + find = rn->info; + route_unlock_node(rn); + return find; + } + return NULL; } -struct ospf_lsa * -ospf_lsdb_lookup_by_id (struct ospf_lsdb *lsdb, u_char type, - struct in_addr id, struct in_addr adv_router) +struct ospf_lsa *ospf_lsdb_lookup_by_id(struct ospf_lsdb *lsdb, u_char type, + struct in_addr id, + struct in_addr adv_router) { - struct route_table *table; - struct prefix_ls lp; - struct route_node *rn; - struct ospf_lsa *find; - - table = lsdb->type[type].db; - - memset (&lp, 0, sizeof (struct prefix_ls)); - lp.family = 0; - lp.prefixlen = 64; - lp.id = id; - lp.adv_router = adv_router; - - rn = route_node_lookup (table, (struct prefix *) &lp); - if (rn) - { - find = rn->info; - route_unlock_node (rn); - return find; - } - return NULL; + struct route_table *table; + struct prefix_ls lp; + struct route_node *rn; + struct ospf_lsa *find; + + table = lsdb->type[type].db; + + memset(&lp, 0, sizeof(struct prefix_ls)); + lp.family = 0; + lp.prefixlen = 64; + lp.id = id; + lp.adv_router = adv_router; + + rn = route_node_lookup(table, (struct prefix *)&lp); + if (rn) { + find = rn->info; + route_unlock_node(rn); + return find; + } + return NULL; } -struct ospf_lsa * -ospf_lsdb_lookup_by_id_next (struct ospf_lsdb *lsdb, u_char type, - struct in_addr id, struct in_addr adv_router, - int first) +struct ospf_lsa *ospf_lsdb_lookup_by_id_next(struct ospf_lsdb *lsdb, + u_char type, struct in_addr id, + struct in_addr adv_router, + int first) { - struct route_table *table; - struct prefix_ls lp; - struct route_node *rn; - struct ospf_lsa *find; - - table = lsdb->type[type].db; - - memset (&lp, 0, sizeof (struct prefix_ls)); - lp.family = 0; - lp.prefixlen = 64; - lp.id = id; - lp.adv_router = adv_router; - - if (first) - rn = route_top (table); - else - { - if ((rn = route_node_lookup (table, (struct prefix *) &lp)) == NULL) - return NULL; - rn = route_next (rn); - } - - for (; rn; rn = route_next (rn)) - if (rn->info) - break; - - if (rn && rn->info) - { - find = rn->info; - route_unlock_node (rn); - return find; - } - return NULL; + struct route_table *table; + struct prefix_ls lp; + struct route_node *rn; + struct ospf_lsa *find; + + table = lsdb->type[type].db; + + memset(&lp, 0, sizeof(struct prefix_ls)); + lp.family = 0; + lp.prefixlen = 64; + lp.id = id; + lp.adv_router = adv_router; + + if (first) + rn = route_top(table); + else { + if ((rn = route_node_lookup(table, (struct prefix *)&lp)) + == NULL) + return NULL; + rn = route_next(rn); + } + + for (; rn; rn = route_next(rn)) + if (rn->info) + break; + + if (rn && rn->info) { + find = rn->info; + route_unlock_node(rn); + return find; + } + return NULL; } -unsigned long -ospf_lsdb_count_all (struct ospf_lsdb *lsdb) +unsigned long ospf_lsdb_count_all(struct ospf_lsdb *lsdb) { - return lsdb->total; + return lsdb->total; } -unsigned long -ospf_lsdb_count (struct ospf_lsdb *lsdb, int type) +unsigned long ospf_lsdb_count(struct ospf_lsdb *lsdb, int type) { - return lsdb->type[type].count; + return lsdb->type[type].count; } -unsigned long -ospf_lsdb_count_self (struct ospf_lsdb *lsdb, int type) +unsigned long ospf_lsdb_count_self(struct ospf_lsdb *lsdb, int type) { - return lsdb->type[type].count_self; + return lsdb->type[type].count_self; } -unsigned int -ospf_lsdb_checksum (struct ospf_lsdb *lsdb, int type) +unsigned int ospf_lsdb_checksum(struct ospf_lsdb *lsdb, int type) { - return lsdb->type[type].checksum; + return lsdb->type[type].checksum; } -unsigned long -ospf_lsdb_isempty (struct ospf_lsdb *lsdb) +unsigned long ospf_lsdb_isempty(struct ospf_lsdb *lsdb) { - return (lsdb->total == 0); + return (lsdb->total == 0); } diff --git a/ospfd/ospf_lsdb.h b/ospfd/ospf_lsdb.h index ee31cda65..483107112 100644 --- a/ospfd/ospf_lsdb.h +++ b/ospfd/ospf_lsdb.h @@ -23,29 +23,27 @@ #define _ZEBRA_OSPF_LSDB_H /* OSPF LSDB structure. */ -struct ospf_lsdb -{ - struct - { - unsigned long count; - unsigned long count_self; - unsigned int checksum; - struct route_table *db; - } type[OSPF_MAX_LSA]; - unsigned long total; +struct ospf_lsdb { + struct { + unsigned long count; + unsigned long count_self; + unsigned int checksum; + struct route_table *db; + } type[OSPF_MAX_LSA]; + unsigned long total; #define MONITOR_LSDB_CHANGE 1 /* XXX */ #ifdef MONITOR_LSDB_CHANGE - /* Hooks for callback functions to catch every add/del event. */ - int (* new_lsa_hook)(struct ospf_lsa *); - int (* del_lsa_hook)(struct ospf_lsa *); + /* Hooks for callback functions to catch every add/del event. */ + int (*new_lsa_hook)(struct ospf_lsa *); + int (*del_lsa_hook)(struct ospf_lsa *); #endif /* MONITOR_LSDB_CHANGE */ }; /* Macros. */ -#define LSDB_LOOP(T,N,L) \ - if ((T) != NULL) \ - for ((N) = route_top ((T)); ((N)); ((N)) = route_next ((N))) \ - if (((L) = (N)->info)) +#define LSDB_LOOP(T, N, L) \ + if ((T) != NULL) \ + for ((N) = route_top((T)); ((N)); ((N)) = route_next((N))) \ + if (((L) = (N)->info)) #define ROUTER_LSDB(A) ((A)->lsdb->type[OSPF_ROUTER_LSA].db) #define NETWORK_LSDB(A) ((A)->lsdb->type[OSPF_NETWORK_LSA].db) @@ -61,26 +59,26 @@ struct ospf_lsdb #define AS_LSDB(O,T) ((O)->lsdb->type[(T)].db) /* OSPF LSDB related functions. */ -extern struct ospf_lsdb *ospf_lsdb_new (void); -extern void ospf_lsdb_init (struct ospf_lsdb *); -extern void ospf_lsdb_free (struct ospf_lsdb *); -extern void ospf_lsdb_cleanup (struct ospf_lsdb *); -extern void ls_prefix_set (struct prefix_ls *lp, struct ospf_lsa *lsa); -extern void ospf_lsdb_add (struct ospf_lsdb *, struct ospf_lsa *); -extern void ospf_lsdb_delete (struct ospf_lsdb *, struct ospf_lsa *); -extern void ospf_lsdb_delete_all (struct ospf_lsdb *); +extern struct ospf_lsdb *ospf_lsdb_new(void); +extern void ospf_lsdb_init(struct ospf_lsdb *); +extern void ospf_lsdb_free(struct ospf_lsdb *); +extern void ospf_lsdb_cleanup(struct ospf_lsdb *); +extern void ls_prefix_set(struct prefix_ls *lp, struct ospf_lsa *lsa); +extern void ospf_lsdb_add(struct ospf_lsdb *, struct ospf_lsa *); +extern void ospf_lsdb_delete(struct ospf_lsdb *, struct ospf_lsa *); +extern void ospf_lsdb_delete_all(struct ospf_lsdb *); /* Set all stats to -1 (LSA_SPF_NOT_EXPLORED). */ -extern void ospf_lsdb_clean_stat (struct ospf_lsdb *lsdb); -extern struct ospf_lsa *ospf_lsdb_lookup (struct ospf_lsdb *, struct ospf_lsa *); -extern struct ospf_lsa *ospf_lsdb_lookup_by_id (struct ospf_lsdb *, u_char, - struct in_addr, struct in_addr); -extern struct ospf_lsa *ospf_lsdb_lookup_by_id_next (struct ospf_lsdb *, u_char, - struct in_addr, struct in_addr, - int); -extern unsigned long ospf_lsdb_count_all (struct ospf_lsdb *); -extern unsigned long ospf_lsdb_count (struct ospf_lsdb *, int); -extern unsigned long ospf_lsdb_count_self (struct ospf_lsdb *, int); -extern unsigned int ospf_lsdb_checksum (struct ospf_lsdb *, int); -extern unsigned long ospf_lsdb_isempty (struct ospf_lsdb *); +extern void ospf_lsdb_clean_stat(struct ospf_lsdb *lsdb); +extern struct ospf_lsa *ospf_lsdb_lookup(struct ospf_lsdb *, struct ospf_lsa *); +extern struct ospf_lsa *ospf_lsdb_lookup_by_id(struct ospf_lsdb *, u_char, + struct in_addr, struct in_addr); +extern struct ospf_lsa *ospf_lsdb_lookup_by_id_next(struct ospf_lsdb *, u_char, + struct in_addr, + struct in_addr, int); +extern unsigned long ospf_lsdb_count_all(struct ospf_lsdb *); +extern unsigned long ospf_lsdb_count(struct ospf_lsdb *, int); +extern unsigned long ospf_lsdb_count_self(struct ospf_lsdb *, int); +extern unsigned int ospf_lsdb_checksum(struct ospf_lsdb *, int); +extern unsigned long ospf_lsdb_isempty(struct ospf_lsdb *); #endif /* _ZEBRA_OSPF_LSDB_H */ diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index 6cd6d0272..f284a04cb 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -54,34 +54,26 @@ #include "ospfd/ospf_bfd.h" /* ospfd privileges */ -zebra_capabilities_t _caps_p [] = -{ - ZCAP_NET_RAW, - ZCAP_BIND, - ZCAP_NET_ADMIN, +zebra_capabilities_t _caps_p[] = { + ZCAP_NET_RAW, ZCAP_BIND, ZCAP_NET_ADMIN, }; -struct zebra_privs_t ospfd_privs = -{ +struct zebra_privs_t ospfd_privs = { #if defined(FRR_USER) && defined(FRR_GROUP) - .user = FRR_USER, - .group = FRR_GROUP, + .user = FRR_USER, + .group = FRR_GROUP, #endif #if defined(VTY_GROUP) - .vty_group = VTY_GROUP, + .vty_group = VTY_GROUP, #endif - .caps_p = _caps_p, - .cap_num_p = array_size(_caps_p), - .cap_num_i = 0 -}; + .caps_p = _caps_p, + .cap_num_p = array_size(_caps_p), + .cap_num_i = 0}; /* OSPFd options. */ -struct option longopts[] = -{ - { "instance", required_argument, NULL, 'n'}, - { "apiserver", no_argument, NULL, 'a'}, - { 0 } -}; +struct option longopts[] = {{"instance", required_argument, NULL, 'n'}, + {"apiserver", no_argument, NULL, 'a'}, + {0}}; /* OSPFd program name */ @@ -93,152 +85,140 @@ extern int ospf_apiserver_enable; #endif /* SUPPORT_OSPF_API */ /* SIGHUP handler. */ -static void -sighup (void) +static void sighup(void) { - zlog_info("SIGHUP received"); + zlog_info("SIGHUP received"); } /* SIGINT / SIGTERM handler. */ -static void -sigint (void) +static void sigint(void) { - zlog_notice ("Terminating on signal"); - ospf_terminate (); + zlog_notice("Terminating on signal"); + ospf_terminate(); } /* SIGUSR1 handler. */ -static void -sigusr1 (void) +static void sigusr1(void) { - zlog_rotate(); + zlog_rotate(); } -struct quagga_signal_t ospf_signals[] = -{ - { - .signal = SIGHUP, - .handler = &sighup, - }, - { - .signal = SIGUSR1, - .handler = &sigusr1, - }, - { - .signal = SIGINT, - .handler = &sigint, - }, - { - .signal = SIGTERM, - .handler = &sigint, - }, +struct quagga_signal_t ospf_signals[] = { + { + .signal = SIGHUP, + .handler = &sighup, + }, + { + .signal = SIGUSR1, + .handler = &sigusr1, + }, + { + .signal = SIGINT, + .handler = &sigint, + }, + { + .signal = SIGTERM, + .handler = &sigint, + }, }; -FRR_DAEMON_INFO(ospfd, OSPF, - .vty_port = OSPF_VTY_PORT, +FRR_DAEMON_INFO(ospfd, OSPF, .vty_port = OSPF_VTY_PORT, - .proghelp = "Implementation of the OSPFv2 routing protocol.", + .proghelp = "Implementation of the OSPFv2 routing protocol.", - .signals = ospf_signals, - .n_signals = array_size(ospf_signals), + .signals = ospf_signals, .n_signals = array_size(ospf_signals), - .privs = &ospfd_privs, -) + .privs = &ospfd_privs, ) /* OSPFd main routine. */ -int -main (int argc, char **argv) +int main(int argc, char **argv) { - u_short instance = 0; + u_short instance = 0; #ifdef SUPPORT_OSPF_API - /* OSPF apiserver is disabled by default. */ - ospf_apiserver_enable = 0; + /* OSPF apiserver is disabled by default. */ + ospf_apiserver_enable = 0; #endif /* SUPPORT_OSPF_API */ - frr_preinit (&ospfd_di, argc, argv); - frr_opt_add ("n:a", longopts, - " -n, --instance Set the instance id\n" - " -a, --apiserver Enable OSPF apiserver\n"); + frr_preinit(&ospfd_di, argc, argv); + frr_opt_add("n:a", longopts, + " -n, --instance Set the instance id\n" + " -a, --apiserver Enable OSPF apiserver\n"); - while (1) - { - int opt; + while (1) { + int opt; - opt = frr_getopt (argc, argv, NULL); - - if (opt == EOF) - break; + opt = frr_getopt(argc, argv, NULL); - switch (opt) - { - case 'n': - ospfd_di.instance = instance = atoi(optarg); - if (instance < 1) - exit(0); - break; - case 0: - break; + if (opt == EOF) + break; + + switch (opt) { + case 'n': + ospfd_di.instance = instance = atoi(optarg); + if (instance < 1) + exit(0); + break; + case 0: + break; #ifdef SUPPORT_OSPF_API - case 'a': - ospf_apiserver_enable = 1; - break; + case 'a': + ospf_apiserver_enable = 1; + break; #endif /* SUPPORT_OSPF_API */ - default: - frr_help_exit (1); - break; + default: + frr_help_exit(1); + break; + } } - } - - /* Invoked by a priviledged user? -- endo. */ - if (geteuid () != 0) - { - errno = EPERM; - perror (ospfd_di.progname); - exit (1); - } - - /* OSPF master init. */ - ospf_master_init (frr_init ()); - - /* Initializations. */ - master = om->master; - - /* Library inits. */ - debug_init (); - vrf_init (NULL, NULL, NULL, NULL); - - access_list_init (); - prefix_list_init (); - - /* OSPFd inits. */ - ospf_if_init (); - ospf_zebra_init(master, instance); - - /* OSPF vty inits. */ - ospf_vty_init (); - ospf_vty_show_init (); - ospf_vty_clear_init (); - - /* OSPF BFD init */ - ospf_bfd_init(); - - ospf_route_map_init (); - ospf_opaque_init (); - - /* Need to initialize the default ospf structure, so the interface mode - commands can be duly processed if they are received before 'router ospf', - when quagga(ospfd) is restarted */ - if (!ospf_get_instance(instance)) - { - zlog_err("OSPF instance init failed: %s", strerror(errno)); - exit (1); - } - - frr_config_fork(); - frr_run (master); - - /* Not reached. */ - return (0); -} + /* Invoked by a priviledged user? -- endo. */ + if (geteuid() != 0) { + errno = EPERM; + perror(ospfd_di.progname); + exit(1); + } + + /* OSPF master init. */ + ospf_master_init(frr_init()); + + /* Initializations. */ + master = om->master; + + /* Library inits. */ + debug_init(); + vrf_init(NULL, NULL, NULL, NULL); + + access_list_init(); + prefix_list_init(); + + /* OSPFd inits. */ + ospf_if_init(); + ospf_zebra_init(master, instance); + + /* OSPF vty inits. */ + ospf_vty_init(); + ospf_vty_show_init(); + ospf_vty_clear_init(); + + /* OSPF BFD init */ + ospf_bfd_init(); + + ospf_route_map_init(); + ospf_opaque_init(); + + /* Need to initialize the default ospf structure, so the interface mode + commands can be duly processed if they are received before 'router + ospf', + when quagga(ospfd) is restarted */ + if (!ospf_get_instance(instance)) { + zlog_err("OSPF instance init failed: %s", strerror(errno)); + exit(1); + } + + frr_config_fork(); + frr_run(master); + + /* Not reached. */ + return (0); +} diff --git a/ospfd/ospf_memory.c b/ospfd/ospf_memory.c index 5639c0f60..cdc9b929f 100644 --- a/ospfd/ospf_memory.c +++ b/ospfd/ospf_memory.c @@ -26,30 +26,30 @@ #include "ospf_memory.h" DEFINE_MGROUP(OSPFD, "ospfd") -DEFINE_MTYPE(OSPFD, OSPF_TOP, "OSPF top") -DEFINE_MTYPE(OSPFD, OSPF_AREA, "OSPF area") -DEFINE_MTYPE(OSPFD, OSPF_AREA_RANGE, "OSPF area range") -DEFINE_MTYPE(OSPFD, OSPF_NETWORK, "OSPF network") +DEFINE_MTYPE(OSPFD, OSPF_TOP, "OSPF top") +DEFINE_MTYPE(OSPFD, OSPF_AREA, "OSPF area") +DEFINE_MTYPE(OSPFD, OSPF_AREA_RANGE, "OSPF area range") +DEFINE_MTYPE(OSPFD, OSPF_NETWORK, "OSPF network") DEFINE_MTYPE(OSPFD, OSPF_NEIGHBOR_STATIC, "OSPF static nbr") -DEFINE_MTYPE(OSPFD, OSPF_IF, "OSPF interface") -DEFINE_MTYPE(OSPFD, OSPF_NEIGHBOR, "OSPF neighbor") -DEFINE_MTYPE(OSPFD, OSPF_ROUTE, "OSPF route") -DEFINE_MTYPE(OSPFD, OSPF_TMP, "OSPF tmp mem") -DEFINE_MTYPE(OSPFD, OSPF_LSA, "OSPF LSA") -DEFINE_MTYPE(OSPFD, OSPF_LSA_DATA, "OSPF LSA data") -DEFINE_MTYPE(OSPFD, OSPF_LSDB, "OSPF LSDB") -DEFINE_MTYPE(OSPFD, OSPF_PACKET, "OSPF packet") -DEFINE_MTYPE(OSPFD, OSPF_FIFO, "OSPF FIFO queue") -DEFINE_MTYPE(OSPFD, OSPF_VERTEX, "OSPF vertex") -DEFINE_MTYPE(OSPFD, OSPF_VERTEX_PARENT, "OSPF vertex parent") -DEFINE_MTYPE(OSPFD, OSPF_NEXTHOP, "OSPF nexthop") -DEFINE_MTYPE(OSPFD, OSPF_PATH, "OSPF path") -DEFINE_MTYPE(OSPFD, OSPF_VL_DATA, "OSPF VL data") -DEFINE_MTYPE(OSPFD, OSPF_CRYPT_KEY, "OSPF crypt key") -DEFINE_MTYPE(OSPFD, OSPF_EXTERNAL_INFO, "OSPF ext. info") -DEFINE_MTYPE(OSPFD, OSPF_DISTANCE, "OSPF distance") -DEFINE_MTYPE(OSPFD, OSPF_IF_INFO, "OSPF if info") -DEFINE_MTYPE(OSPFD, OSPF_IF_PARAMS, "OSPF if params") -DEFINE_MTYPE(OSPFD, OSPF_MESSAGE, "OSPF message") -DEFINE_MTYPE(OSPFD, OSPF_MPLS_TE, "OSPF MPLS parameters") -DEFINE_MTYPE(OSPFD, OSPF_PCE_PARAMS, "OSPF PCE parameters") +DEFINE_MTYPE(OSPFD, OSPF_IF, "OSPF interface") +DEFINE_MTYPE(OSPFD, OSPF_NEIGHBOR, "OSPF neighbor") +DEFINE_MTYPE(OSPFD, OSPF_ROUTE, "OSPF route") +DEFINE_MTYPE(OSPFD, OSPF_TMP, "OSPF tmp mem") +DEFINE_MTYPE(OSPFD, OSPF_LSA, "OSPF LSA") +DEFINE_MTYPE(OSPFD, OSPF_LSA_DATA, "OSPF LSA data") +DEFINE_MTYPE(OSPFD, OSPF_LSDB, "OSPF LSDB") +DEFINE_MTYPE(OSPFD, OSPF_PACKET, "OSPF packet") +DEFINE_MTYPE(OSPFD, OSPF_FIFO, "OSPF FIFO queue") +DEFINE_MTYPE(OSPFD, OSPF_VERTEX, "OSPF vertex") +DEFINE_MTYPE(OSPFD, OSPF_VERTEX_PARENT, "OSPF vertex parent") +DEFINE_MTYPE(OSPFD, OSPF_NEXTHOP, "OSPF nexthop") +DEFINE_MTYPE(OSPFD, OSPF_PATH, "OSPF path") +DEFINE_MTYPE(OSPFD, OSPF_VL_DATA, "OSPF VL data") +DEFINE_MTYPE(OSPFD, OSPF_CRYPT_KEY, "OSPF crypt key") +DEFINE_MTYPE(OSPFD, OSPF_EXTERNAL_INFO, "OSPF ext. info") +DEFINE_MTYPE(OSPFD, OSPF_DISTANCE, "OSPF distance") +DEFINE_MTYPE(OSPFD, OSPF_IF_INFO, "OSPF if info") +DEFINE_MTYPE(OSPFD, OSPF_IF_PARAMS, "OSPF if params") +DEFINE_MTYPE(OSPFD, OSPF_MESSAGE, "OSPF message") +DEFINE_MTYPE(OSPFD, OSPF_MPLS_TE, "OSPF MPLS parameters") +DEFINE_MTYPE(OSPFD, OSPF_PCE_PARAMS, "OSPF PCE parameters") diff --git a/ospfd/ospf_neighbor.c b/ospfd/ospf_neighbor.c index fc86cd09f..33492cf7c 100644 --- a/ospfd/ospf_neighbor.c +++ b/ospfd/ospf_neighbor.c @@ -49,462 +49,437 @@ * for all cases except Virtual-link and PointToPoint interfaces, where * neighbours are indexed by router-ID instead. */ -static void -ospf_nbr_key (struct ospf_interface *oi, struct ospf_neighbor *nbr, - struct prefix *key) +static void ospf_nbr_key(struct ospf_interface *oi, struct ospf_neighbor *nbr, + struct prefix *key) { - key->family = AF_INET; - key->prefixlen = IPV4_MAX_BITLEN; - - /* vlinks are indexed by router-id */ - if (oi->type == OSPF_IFTYPE_VIRTUALLINK || - oi->type == OSPF_IFTYPE_POINTOPOINT) - key->u.prefix4 = nbr->router_id; - else - key->u.prefix4 = nbr->src; - return; + key->family = AF_INET; + key->prefixlen = IPV4_MAX_BITLEN; + + /* vlinks are indexed by router-id */ + if (oi->type == OSPF_IFTYPE_VIRTUALLINK + || oi->type == OSPF_IFTYPE_POINTOPOINT) + key->u.prefix4 = nbr->router_id; + else + key->u.prefix4 = nbr->src; + return; } -struct ospf_neighbor * -ospf_nbr_new (struct ospf_interface *oi) +struct ospf_neighbor *ospf_nbr_new(struct ospf_interface *oi) { - struct ospf_neighbor *nbr; + struct ospf_neighbor *nbr; - /* Allcate new neighbor. */ - nbr = XCALLOC (MTYPE_OSPF_NEIGHBOR, sizeof (struct ospf_neighbor)); + /* Allcate new neighbor. */ + nbr = XCALLOC(MTYPE_OSPF_NEIGHBOR, sizeof(struct ospf_neighbor)); - /* Relate neighbor to the interface. */ - nbr->oi = oi; + /* Relate neighbor to the interface. */ + nbr->oi = oi; - /* Set default values. */ - nbr->state = NSM_Down; + /* Set default values. */ + nbr->state = NSM_Down; - /* Set inheritance values. */ - nbr->v_inactivity = OSPF_IF_PARAM (oi, v_wait); - nbr->v_db_desc = OSPF_IF_PARAM (oi, retransmit_interval); - nbr->v_ls_req = OSPF_IF_PARAM (oi, retransmit_interval); - nbr->v_ls_upd = OSPF_IF_PARAM (oi, retransmit_interval); - nbr->priority = -1; + /* Set inheritance values. */ + nbr->v_inactivity = OSPF_IF_PARAM(oi, v_wait); + nbr->v_db_desc = OSPF_IF_PARAM(oi, retransmit_interval); + nbr->v_ls_req = OSPF_IF_PARAM(oi, retransmit_interval); + nbr->v_ls_upd = OSPF_IF_PARAM(oi, retransmit_interval); + nbr->priority = -1; - /* DD flags. */ - nbr->dd_flags = OSPF_DD_FLAG_MS|OSPF_DD_FLAG_M|OSPF_DD_FLAG_I; + /* DD flags. */ + nbr->dd_flags = OSPF_DD_FLAG_MS | OSPF_DD_FLAG_M | OSPF_DD_FLAG_I; - /* Last received and sent DD. */ - nbr->last_send = NULL; + /* Last received and sent DD. */ + nbr->last_send = NULL; - nbr->nbr_nbma = NULL; + nbr->nbr_nbma = NULL; - ospf_lsdb_init (&nbr->db_sum); - ospf_lsdb_init (&nbr->ls_rxmt); - ospf_lsdb_init (&nbr->ls_req); + ospf_lsdb_init(&nbr->db_sum); + ospf_lsdb_init(&nbr->ls_rxmt); + ospf_lsdb_init(&nbr->ls_req); - nbr->crypt_seqnum = 0; + nbr->crypt_seqnum = 0; - ospf_bfd_info_nbr_create(oi, nbr); - return nbr; + ospf_bfd_info_nbr_create(oi, nbr); + return nbr; } -void -ospf_nbr_free (struct ospf_neighbor *nbr) +void ospf_nbr_free(struct ospf_neighbor *nbr) { - /* Free DB summary list. */ - if (ospf_db_summary_count (nbr)) - ospf_db_summary_clear (nbr); - /* ospf_db_summary_delete_all (nbr); */ - - /* Free ls request list. */ - if (ospf_ls_request_count (nbr)) - ospf_ls_request_delete_all (nbr); - - /* Free retransmit list. */ - if (ospf_ls_retransmit_count (nbr)) - ospf_ls_retransmit_clear (nbr); - - /* Cleanup LSDBs. */ - ospf_lsdb_cleanup (&nbr->db_sum); - ospf_lsdb_cleanup (&nbr->ls_req); - ospf_lsdb_cleanup (&nbr->ls_rxmt); - - /* Clear last send packet. */ - if (nbr->last_send) - ospf_packet_free (nbr->last_send); - - if (nbr->nbr_nbma) - { - nbr->nbr_nbma->nbr = NULL; - nbr->nbr_nbma = NULL; - } - - /* Cancel all timers. */ - OSPF_NSM_TIMER_OFF (nbr->t_inactivity); - OSPF_NSM_TIMER_OFF (nbr->t_db_desc); - OSPF_NSM_TIMER_OFF (nbr->t_ls_req); - OSPF_NSM_TIMER_OFF (nbr->t_ls_upd); - - /* Cancel all events. *//* Thread lookup cost would be negligible. */ - thread_cancel_event (master, nbr); - - ospf_bfd_info_free(&nbr->bfd_info); - XFREE (MTYPE_OSPF_NEIGHBOR, nbr); + /* Free DB summary list. */ + if (ospf_db_summary_count(nbr)) + ospf_db_summary_clear(nbr); + /* ospf_db_summary_delete_all (nbr); */ + + /* Free ls request list. */ + if (ospf_ls_request_count(nbr)) + ospf_ls_request_delete_all(nbr); + + /* Free retransmit list. */ + if (ospf_ls_retransmit_count(nbr)) + ospf_ls_retransmit_clear(nbr); + + /* Cleanup LSDBs. */ + ospf_lsdb_cleanup(&nbr->db_sum); + ospf_lsdb_cleanup(&nbr->ls_req); + ospf_lsdb_cleanup(&nbr->ls_rxmt); + + /* Clear last send packet. */ + if (nbr->last_send) + ospf_packet_free(nbr->last_send); + + if (nbr->nbr_nbma) { + nbr->nbr_nbma->nbr = NULL; + nbr->nbr_nbma = NULL; + } + + /* Cancel all timers. */ + OSPF_NSM_TIMER_OFF(nbr->t_inactivity); + OSPF_NSM_TIMER_OFF(nbr->t_db_desc); + OSPF_NSM_TIMER_OFF(nbr->t_ls_req); + OSPF_NSM_TIMER_OFF(nbr->t_ls_upd); + + /* Cancel all events. */ /* Thread lookup cost would be negligible. */ + thread_cancel_event(master, nbr); + + ospf_bfd_info_free(&nbr->bfd_info); + XFREE(MTYPE_OSPF_NEIGHBOR, nbr); } /* Delete specified OSPF neighbor from interface. */ -void -ospf_nbr_delete (struct ospf_neighbor *nbr) +void ospf_nbr_delete(struct ospf_neighbor *nbr) { - struct ospf_interface *oi; - struct route_node *rn; - struct prefix p; - - oi = nbr->oi; - - /* get appropriate prefix 'key' */ - ospf_nbr_key (oi, nbr, &p); - - rn = route_node_lookup (oi->nbrs, &p); - if (rn) - { - /* If lookup for a NBR succeeds, the leaf route_node could - * only exist because there is (or was) a nbr there. - * If the nbr was deleted, the leaf route_node should have - * lost its last refcount too, and be deleted. - * Therefore a looked-up leaf route_node in nbrs table - * should never have NULL info. - */ - assert (rn->info); - - if (rn->info) - { - rn->info = NULL; - route_unlock_node (rn); + struct ospf_interface *oi; + struct route_node *rn; + struct prefix p; + + oi = nbr->oi; + + /* get appropriate prefix 'key' */ + ospf_nbr_key(oi, nbr, &p); + + rn = route_node_lookup(oi->nbrs, &p); + if (rn) { + /* If lookup for a NBR succeeds, the leaf route_node could + * only exist because there is (or was) a nbr there. + * If the nbr was deleted, the leaf route_node should have + * lost its last refcount too, and be deleted. + * Therefore a looked-up leaf route_node in nbrs table + * should never have NULL info. + */ + assert(rn->info); + + if (rn->info) { + rn->info = NULL; + route_unlock_node(rn); + } else + zlog_info("Can't find neighbor %s in the interface %s", + inet_ntoa(nbr->src), IF_NAME(oi)); + + route_unlock_node(rn); + } else { + /* + * This neighbor was not found, but before we move on and + * free the neighbor structre, make sure that it was not + * indexed incorrectly and ended up in the "worng" place + */ + + /* Reverse the lookup rules */ + if (oi->type == OSPF_IFTYPE_VIRTUALLINK + || oi->type == OSPF_IFTYPE_POINTOPOINT) + p.u.prefix4 = nbr->src; + else + p.u.prefix4 = nbr->router_id; + + rn = route_node_lookup(oi->nbrs, &p); + if (rn) { + /* We found the neighbor! + * Now make sure it is not the exact same neighbor + * structure that we are about to free + */ + if (nbr == rn->info) { + /* Same neighbor, drop the reference to it */ + rn->info = NULL; + route_unlock_node(rn); + } + route_unlock_node(rn); + } } - else - zlog_info ("Can't find neighbor %s in the interface %s", - inet_ntoa (nbr->src), IF_NAME (oi)); - - route_unlock_node (rn); - } - else - { - /* - * This neighbor was not found, but before we move on and - * free the neighbor structre, make sure that it was not - * indexed incorrectly and ended up in the "worng" place - */ - - /* Reverse the lookup rules */ - if (oi->type == OSPF_IFTYPE_VIRTUALLINK || - oi->type == OSPF_IFTYPE_POINTOPOINT) - p.u.prefix4 = nbr->src; - else - p.u.prefix4 = nbr->router_id; - - rn = route_node_lookup (oi->nbrs, &p); - if (rn){ - /* We found the neighbor! - * Now make sure it is not the exact same neighbor - * structure that we are about to free - */ - if (nbr == rn->info){ - /* Same neighbor, drop the reference to it */ - rn->info = NULL; - route_unlock_node (rn); - } - route_unlock_node (rn); - } - } - /* Free ospf_neighbor structure. */ - ospf_nbr_free (nbr); + /* Free ospf_neighbor structure. */ + ospf_nbr_free(nbr); } /* Check myself is in the neighbor list. */ -int -ospf_nbr_bidirectional (struct in_addr *router_id, - struct in_addr *neighbors, int size) +int ospf_nbr_bidirectional(struct in_addr *router_id, struct in_addr *neighbors, + int size) { - int i; - int max; + int i; + int max; - max = size / sizeof (struct in_addr); + max = size / sizeof(struct in_addr); - for (i = 0; i < max; i ++) - if (IPV4_ADDR_SAME (router_id, &neighbors[i])) - return 1; + for (i = 0; i < max; i++) + if (IPV4_ADDR_SAME(router_id, &neighbors[i])) + return 1; - return 0; + return 0; } /* reset nbr_self */ -void -ospf_nbr_self_reset (struct ospf_interface *oi, struct in_addr router_id) +void ospf_nbr_self_reset(struct ospf_interface *oi, struct in_addr router_id) { - if (oi->nbr_self) - ospf_nbr_delete (oi->nbr_self); + if (oi->nbr_self) + ospf_nbr_delete(oi->nbr_self); - oi->nbr_self = ospf_nbr_new (oi); - ospf_nbr_add_self (oi, router_id); + oi->nbr_self = ospf_nbr_new(oi); + ospf_nbr_add_self(oi, router_id); } /* Add self to nbr list. */ -void -ospf_nbr_add_self (struct ospf_interface *oi, struct in_addr router_id) +void ospf_nbr_add_self(struct ospf_interface *oi, struct in_addr router_id) { - struct prefix p; - struct route_node *rn; - - if (!oi->nbr_self) - oi->nbr_self = ospf_nbr_new (oi); - - /* Initial state */ - oi->nbr_self->address = *oi->address; - oi->nbr_self->priority = OSPF_IF_PARAM (oi, priority); - oi->nbr_self->router_id = router_id; - oi->nbr_self->src = oi->address->u.prefix4; - oi->nbr_self->state = NSM_TwoWay; - - switch (oi->area->external_routing) - { - case OSPF_AREA_DEFAULT: - SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E); - break; - case OSPF_AREA_STUB: - UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E); - break; - case OSPF_AREA_NSSA: - UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E); - SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP); - break; - } - - /* Add nbr_self to nbrs table */ - ospf_nbr_key (oi, oi->nbr_self, &p); - - rn = route_node_get (oi->nbrs, &p); - if (rn->info) - { - /* There is already pseudo neighbor. */ - assert (oi->nbr_self == rn->info); - route_unlock_node (rn); - } - else - rn->info = oi->nbr_self; + struct prefix p; + struct route_node *rn; + + if (!oi->nbr_self) + oi->nbr_self = ospf_nbr_new(oi); + + /* Initial state */ + oi->nbr_self->address = *oi->address; + oi->nbr_self->priority = OSPF_IF_PARAM(oi, priority); + oi->nbr_self->router_id = router_id; + oi->nbr_self->src = oi->address->u.prefix4; + oi->nbr_self->state = NSM_TwoWay; + + switch (oi->area->external_routing) { + case OSPF_AREA_DEFAULT: + SET_FLAG(oi->nbr_self->options, OSPF_OPTION_E); + break; + case OSPF_AREA_STUB: + UNSET_FLAG(oi->nbr_self->options, OSPF_OPTION_E); + break; + case OSPF_AREA_NSSA: + UNSET_FLAG(oi->nbr_self->options, OSPF_OPTION_E); + SET_FLAG(oi->nbr_self->options, OSPF_OPTION_NP); + break; + } + + /* Add nbr_self to nbrs table */ + ospf_nbr_key(oi, oi->nbr_self, &p); + + rn = route_node_get(oi->nbrs, &p); + if (rn->info) { + /* There is already pseudo neighbor. */ + assert(oi->nbr_self == rn->info); + route_unlock_node(rn); + } else + rn->info = oi->nbr_self; } /* Get neighbor count by status. Specify status = 0, get all neighbor other than myself. */ -int -ospf_nbr_count (struct ospf_interface *oi, int state) +int ospf_nbr_count(struct ospf_interface *oi, int state) { - struct ospf_neighbor *nbr; - struct route_node *rn; - int count = 0; - - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) - if (state == 0 || nbr->state == state) - count++; - - return count; + struct ospf_neighbor *nbr; + struct route_node *rn; + int count = 0; + + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info)) + if (!IPV4_ADDR_SAME(&nbr->router_id, + &oi->ospf->router_id)) + if (state == 0 || nbr->state == state) + count++; + + return count; } -int -ospf_nbr_count_opaque_capable (struct ospf_interface *oi) +int ospf_nbr_count_opaque_capable(struct ospf_interface *oi) { - struct ospf_neighbor *nbr; - struct route_node *rn; - int count = 0; - - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) - if (nbr->state == NSM_Full) - if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)) - count++; - - return count; + struct ospf_neighbor *nbr; + struct route_node *rn; + int count = 0; + + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info)) + if (!IPV4_ADDR_SAME(&nbr->router_id, + &oi->ospf->router_id)) + if (nbr->state == NSM_Full) + if (CHECK_FLAG(nbr->options, + OSPF_OPTION_O)) + count++; + + return count; } /* lookup nbr by address - use this only if you know you must * otherwise use the ospf_nbr_lookup() wrapper, which deals * with virtual link and PointToPoint neighbours */ -struct ospf_neighbor * -ospf_nbr_lookup_by_addr (struct route_table *nbrs, - struct in_addr *addr) +struct ospf_neighbor *ospf_nbr_lookup_by_addr(struct route_table *nbrs, + struct in_addr *addr) +{ + struct prefix p; + struct route_node *rn; + struct ospf_neighbor *nbr; + + p.family = AF_INET; + p.prefixlen = IPV4_MAX_BITLEN; + p.u.prefix4 = *addr; + + rn = route_node_lookup(nbrs, &p); + if (!rn) + return NULL; + + /* See comment in ospf_nbr_delete */ + assert(rn->info); + + if (rn->info == NULL) { + route_unlock_node(rn); + return NULL; + } + + nbr = (struct ospf_neighbor *)rn->info; + route_unlock_node(rn); + + return nbr; +} + +struct ospf_neighbor *ospf_nbr_lookup_by_routerid(struct route_table *nbrs, + struct in_addr *id) { - struct prefix p; - struct route_node *rn; - struct ospf_neighbor *nbr; - - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - p.u.prefix4 = *addr; - - rn = route_node_lookup (nbrs, &p); - if (! rn) - return NULL; - - /* See comment in ospf_nbr_delete */ - assert (rn->info); - - if (rn->info == NULL) - { - route_unlock_node (rn); - return NULL; - } - - nbr = (struct ospf_neighbor *) rn->info; - route_unlock_node (rn); - - return nbr; + struct route_node *rn; + struct ospf_neighbor *nbr; + + for (rn = route_top(nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info) != NULL) + if (IPV4_ADDR_SAME(&nbr->router_id, id)) { + route_unlock_node(rn); + return nbr; + } + + return NULL; } -struct ospf_neighbor * -ospf_nbr_lookup_by_routerid (struct route_table *nbrs, - struct in_addr *id) +void ospf_renegotiate_optional_capabilities(struct ospf *top) { - struct route_node *rn; - struct ospf_neighbor *nbr; - - for (rn = route_top (nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - if (IPV4_ADDR_SAME (&nbr->router_id, id)) - { - route_unlock_node(rn); - return nbr; + struct listnode *node; + struct ospf_interface *oi; + struct route_table *nbrs; + struct route_node *rn; + struct ospf_neighbor *nbr; + + /* At first, flush self-originated LSAs from routing domain. */ + ospf_flush_self_originated_lsas_now(top); + + /* Revert all neighbor status to ExStart. */ + for (ALL_LIST_ELEMENTS_RO(top->oiflist, node, oi)) { + if ((nbrs = oi->nbrs) == NULL) + continue; + + for (rn = route_top(nbrs); rn; rn = route_next(rn)) { + if ((nbr = rn->info) == NULL || nbr == oi->nbr_self) + continue; + + if (nbr->state < NSM_ExStart) + continue; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Renegotiate optional capabilities with neighbor(%s)", + inet_ntoa(nbr->router_id)); + + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_SeqNumberMismatch); + } } - return NULL; + return; } -void -ospf_renegotiate_optional_capabilities (struct ospf *top) + +struct ospf_neighbor *ospf_nbr_lookup(struct ospf_interface *oi, struct ip *iph, + struct ospf_header *ospfh) { - struct listnode *node; - struct ospf_interface *oi; - struct route_table *nbrs; - struct route_node *rn; - struct ospf_neighbor *nbr; + if (oi->type == OSPF_IFTYPE_VIRTUALLINK + || oi->type == OSPF_IFTYPE_POINTOPOINT) + return (ospf_nbr_lookup_by_routerid(oi->nbrs, + &ospfh->router_id)); + else + return (ospf_nbr_lookup_by_addr(oi->nbrs, &iph->ip_src)); +} - /* At first, flush self-originated LSAs from routing domain. */ - ospf_flush_self_originated_lsas_now (top); +static struct ospf_neighbor *ospf_nbr_add(struct ospf_interface *oi, + struct ospf_header *ospfh, + struct prefix *p) +{ + struct ospf_neighbor *nbr; - /* Revert all neighbor status to ExStart. */ - for (ALL_LIST_ELEMENTS_RO (top->oiflist, node, oi)) - { - if ((nbrs = oi->nbrs) == NULL) - continue; + nbr = ospf_nbr_new(oi); + nbr->state = NSM_Down; + nbr->src = p->u.prefix4; + memcpy(&nbr->address, p, sizeof(struct prefix)); - for (rn = route_top (nbrs); rn; rn = route_next (rn)) - { - if ((nbr = rn->info) == NULL || nbr == oi->nbr_self) - continue; + nbr->nbr_nbma = NULL; + if (oi->type == OSPF_IFTYPE_NBMA) { + struct ospf_nbr_nbma *nbr_nbma; + struct listnode *node; - if (nbr->state < NSM_ExStart) - continue; + for (ALL_LIST_ELEMENTS_RO(oi->nbr_nbma, node, nbr_nbma)) { + if (IPV4_ADDR_SAME(&nbr_nbma->addr, &nbr->src)) { + nbr_nbma->nbr = nbr; + nbr->nbr_nbma = nbr_nbma; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Renegotiate optional capabilities with neighbor(%s)", inet_ntoa (nbr->router_id)); + if (nbr_nbma->t_poll) + OSPF_POLL_TIMER_OFF(nbr_nbma->t_poll); - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch); - } - } + nbr->state_change = nbr_nbma->state_change + 1; + } + } + } - return; -} + /* New nbr, save the crypto sequence number if necessary */ + if (ntohs(ospfh->auth_type) == OSPF_AUTH_CRYPTOGRAPHIC) + nbr->crypt_seqnum = ospfh->u.crypt.crypt_seqnum; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("NSM[%s:%s]: start", IF_NAME(nbr->oi), + inet_ntoa(nbr->router_id)); -struct ospf_neighbor * -ospf_nbr_lookup (struct ospf_interface *oi, struct ip *iph, - struct ospf_header *ospfh) -{ - if (oi->type == OSPF_IFTYPE_VIRTUALLINK || - oi->type == OSPF_IFTYPE_POINTOPOINT) - return (ospf_nbr_lookup_by_routerid (oi->nbrs, &ospfh->router_id)); - else - return (ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src)); + return nbr; } -static struct ospf_neighbor * -ospf_nbr_add (struct ospf_interface *oi, struct ospf_header *ospfh, - struct prefix *p) +struct ospf_neighbor *ospf_nbr_get(struct ospf_interface *oi, + struct ospf_header *ospfh, struct ip *iph, + struct prefix *p) { - struct ospf_neighbor *nbr; - - nbr = ospf_nbr_new (oi); - nbr->state = NSM_Down; - nbr->src = p->u.prefix4; - memcpy (&nbr->address, p, sizeof (struct prefix)); - - nbr->nbr_nbma = NULL; - if (oi->type == OSPF_IFTYPE_NBMA) - { - struct ospf_nbr_nbma *nbr_nbma; - struct listnode *node; - - for (ALL_LIST_ELEMENTS_RO (oi->nbr_nbma, node, nbr_nbma)) - { - if (IPV4_ADDR_SAME(&nbr_nbma->addr, &nbr->src)) - { - nbr_nbma->nbr = nbr; - nbr->nbr_nbma = nbr_nbma; - - if (nbr_nbma->t_poll) - OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll); - - nbr->state_change = nbr_nbma->state_change + 1; - } - } - } - - /* New nbr, save the crypto sequence number if necessary */ - if (ntohs (ospfh->auth_type) == OSPF_AUTH_CRYPTOGRAPHIC) - nbr->crypt_seqnum = ospfh->u.crypt.crypt_seqnum; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("NSM[%s:%s]: start", IF_NAME (nbr->oi), - inet_ntoa (nbr->router_id)); - - return nbr; -} + struct route_node *rn; + struct prefix key; + struct ospf_neighbor *nbr; + + key.family = AF_INET; + key.prefixlen = IPV4_MAX_BITLEN; + + if (oi->type == OSPF_IFTYPE_VIRTUALLINK + || oi->type == OSPF_IFTYPE_POINTOPOINT) + key.u.prefix4 = + ospfh->router_id; /* index vlink and ptp nbrs by + router-id */ + else + key.u.prefix4 = iph->ip_src; + + rn = route_node_get(oi->nbrs, &key); + if (rn->info) { + route_unlock_node(rn); + nbr = rn->info; + + if (oi->type == OSPF_IFTYPE_NBMA && nbr->state == NSM_Attempt) { + nbr->src = iph->ip_src; + memcpy(&nbr->address, p, sizeof(struct prefix)); + } + } else { + rn->info = nbr = ospf_nbr_add(oi, ospfh, p); + } -struct ospf_neighbor * -ospf_nbr_get (struct ospf_interface *oi, struct ospf_header *ospfh, - struct ip *iph, struct prefix *p) -{ - struct route_node *rn; - struct prefix key; - struct ospf_neighbor *nbr; - - key.family = AF_INET; - key.prefixlen = IPV4_MAX_BITLEN; - - if (oi->type == OSPF_IFTYPE_VIRTUALLINK || - oi->type == OSPF_IFTYPE_POINTOPOINT) - key.u.prefix4 = ospfh->router_id;/* index vlink and ptp nbrs by router-id */ - else - key.u.prefix4 = iph->ip_src; - - rn = route_node_get (oi->nbrs, &key); - if (rn->info) - { - route_unlock_node (rn); - nbr = rn->info; - - if (oi->type == OSPF_IFTYPE_NBMA && nbr->state == NSM_Attempt) - { - nbr->src = iph->ip_src; - memcpy (&nbr->address, p, sizeof (struct prefix)); - } - } - else - { - rn->info = nbr = ospf_nbr_add (oi, ospfh, p); - } - - nbr->router_id = ospfh->router_id; - - return nbr; + nbr->router_id = ospfh->router_id; + + return nbr; } diff --git a/ospfd/ospf_neighbor.h b/ospfd/ospf_neighbor.h index 70e3832d9..b19cf5b3e 100644 --- a/ospfd/ospf_neighbor.h +++ b/ospfd/ospf_neighbor.h @@ -25,71 +25,69 @@ #include /* Neighbor Data Structure */ -struct ospf_neighbor -{ - /* This neighbor's parent ospf interface. */ - struct ospf_interface *oi; - - /* OSPF neighbor Information */ - u_char state; /* NSM status. */ - u_char dd_flags; /* DD bit flags. */ - u_int32_t dd_seqnum; /* DD Sequence Number. */ - - /* Neighbor Information from Hello. */ - struct prefix address; /* Neighbor Interface Address. */ - - struct in_addr src; /* Src address. */ - struct in_addr router_id; /* Router ID. */ - u_char options; /* Options. */ - int priority; /* Router Priority. */ - struct in_addr d_router; /* Designated Router. */ - struct in_addr bd_router; /* Backup Designated Router. */ - - /* Last sent Database Description packet. */ - struct ospf_packet *last_send; - /* Timestemp when last Database Description packet was sent */ - struct timeval last_send_ts; - - /* Last received Databse Description packet. */ - struct - { - u_char options; - u_char flags; - u_int32_t dd_seqnum; - } last_recv; - - /* LSA data. */ - struct ospf_lsdb ls_rxmt; - struct ospf_lsdb db_sum; - struct ospf_lsdb ls_req; - struct ospf_lsa *ls_req_last; - - u_int32_t crypt_seqnum; /* Cryptographic Sequence Number. */ - - /* Timer values. */ - u_int32_t v_inactivity; - u_int32_t v_db_desc; - u_int32_t v_ls_req; - u_int32_t v_ls_upd; - - /* Threads. */ - struct thread *t_inactivity; - struct thread *t_db_desc; - struct thread *t_ls_req; - struct thread *t_ls_upd; - struct thread *t_hello_reply; - - /* NBMA configured neighbour */ - struct ospf_nbr_nbma *nbr_nbma; - - /* Statistics */ - struct timeval ts_last_progress; /* last advance of NSM */ - struct timeval ts_last_regress; /* last regressive NSM change */ - const char *last_regress_str; /* Event which last regressed NSM */ - u_int32_t state_change; /* NSM state change counter */ - - /* BFD information */ - void *bfd_info; +struct ospf_neighbor { + /* This neighbor's parent ospf interface. */ + struct ospf_interface *oi; + + /* OSPF neighbor Information */ + u_char state; /* NSM status. */ + u_char dd_flags; /* DD bit flags. */ + u_int32_t dd_seqnum; /* DD Sequence Number. */ + + /* Neighbor Information from Hello. */ + struct prefix address; /* Neighbor Interface Address. */ + + struct in_addr src; /* Src address. */ + struct in_addr router_id; /* Router ID. */ + u_char options; /* Options. */ + int priority; /* Router Priority. */ + struct in_addr d_router; /* Designated Router. */ + struct in_addr bd_router; /* Backup Designated Router. */ + + /* Last sent Database Description packet. */ + struct ospf_packet *last_send; + /* Timestemp when last Database Description packet was sent */ + struct timeval last_send_ts; + + /* Last received Databse Description packet. */ + struct { + u_char options; + u_char flags; + u_int32_t dd_seqnum; + } last_recv; + + /* LSA data. */ + struct ospf_lsdb ls_rxmt; + struct ospf_lsdb db_sum; + struct ospf_lsdb ls_req; + struct ospf_lsa *ls_req_last; + + u_int32_t crypt_seqnum; /* Cryptographic Sequence Number. */ + + /* Timer values. */ + u_int32_t v_inactivity; + u_int32_t v_db_desc; + u_int32_t v_ls_req; + u_int32_t v_ls_upd; + + /* Threads. */ + struct thread *t_inactivity; + struct thread *t_db_desc; + struct thread *t_ls_req; + struct thread *t_ls_upd; + struct thread *t_hello_reply; + + /* NBMA configured neighbour */ + struct ospf_nbr_nbma *nbr_nbma; + + /* Statistics */ + struct timeval ts_last_progress; /* last advance of NSM */ + struct timeval ts_last_regress; /* last regressive NSM change */ + const char *last_regress_str; /* Event which last regressed NSM */ + u_int32_t state_change; /* NSM state change counter */ + + /* BFD information */ + void *bfd_info; }; /* Macros. */ @@ -97,25 +95,23 @@ struct ospf_neighbor #define NBR_IS_BDR(n) IPV4_ADDR_SAME (&n->address.u.prefix4, &n->bd_router) /* Prototypes. */ -extern struct ospf_neighbor *ospf_nbr_new (struct ospf_interface *); -extern void ospf_nbr_free (struct ospf_neighbor *); -extern void ospf_nbr_delete (struct ospf_neighbor *); -extern int ospf_nbr_bidirectional (struct in_addr *, struct in_addr *, int); -extern void ospf_nbr_self_reset (struct ospf_interface *, struct in_addr); -extern void ospf_nbr_add_self (struct ospf_interface *, struct in_addr); -extern int ospf_nbr_count (struct ospf_interface *, int); -extern int ospf_nbr_count_opaque_capable (struct ospf_interface *); -extern struct ospf_neighbor *ospf_nbr_get (struct ospf_interface *, - struct ospf_header *, - struct ip *, struct prefix *); -extern struct ospf_neighbor *ospf_nbr_lookup (struct ospf_interface *, - struct ip *, - struct ospf_header *); -extern struct ospf_neighbor *ospf_nbr_lookup_by_addr (struct route_table *, - struct in_addr *); -extern struct ospf_neighbor *ospf_nbr_lookup_by_routerid (struct route_table - *, - struct in_addr *); -extern void ospf_renegotiate_optional_capabilities (struct ospf *top); +extern struct ospf_neighbor *ospf_nbr_new(struct ospf_interface *); +extern void ospf_nbr_free(struct ospf_neighbor *); +extern void ospf_nbr_delete(struct ospf_neighbor *); +extern int ospf_nbr_bidirectional(struct in_addr *, struct in_addr *, int); +extern void ospf_nbr_self_reset(struct ospf_interface *, struct in_addr); +extern void ospf_nbr_add_self(struct ospf_interface *, struct in_addr); +extern int ospf_nbr_count(struct ospf_interface *, int); +extern int ospf_nbr_count_opaque_capable(struct ospf_interface *); +extern struct ospf_neighbor *ospf_nbr_get(struct ospf_interface *, + struct ospf_header *, struct ip *, + struct prefix *); +extern struct ospf_neighbor *ospf_nbr_lookup(struct ospf_interface *, + struct ip *, struct ospf_header *); +extern struct ospf_neighbor *ospf_nbr_lookup_by_addr(struct route_table *, + struct in_addr *); +extern struct ospf_neighbor *ospf_nbr_lookup_by_routerid(struct route_table *, + struct in_addr *); +extern void ospf_renegotiate_optional_capabilities(struct ospf *top); #endif /* _ZEBRA_OSPF_NEIGHBOR_H */ diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c index 0f5785966..c72c69856 100644 --- a/ospfd/ospf_network.c +++ b/ospfd/ospf_network.c @@ -42,185 +42,193 @@ extern struct zebra_privs_t ospfd_privs; #include "ospfd/ospf_packet.h" - /* Join to the OSPF ALL SPF ROUTERS multicast group. */ -int -ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p, - ifindex_t ifindex) +int ospf_if_add_allspfrouters(struct ospf *top, struct prefix *p, + ifindex_t ifindex) { - int ret; - - ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP, - p->u.prefix4, htonl (OSPF_ALLSPFROUTERS), - ifindex); - if (ret < 0) - zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " - "ifindex %u, AllSPFRouters): %s; perhaps a kernel limit " - "on # of multicast group memberships has been exceeded?", - top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); - else - zlog_debug ("interface %s [%u] join AllSPFRouters Multicast group.", - inet_ntoa (p->u.prefix4), ifindex); - - return ret; + int ret; + + ret = setsockopt_ipv4_multicast(top->fd, IP_ADD_MEMBERSHIP, + p->u.prefix4, htonl(OSPF_ALLSPFROUTERS), + ifindex); + if (ret < 0) + zlog_warn( + "can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " + "ifindex %u, AllSPFRouters): %s; perhaps a kernel limit " + "on # of multicast group memberships has been exceeded?", + top->fd, inet_ntoa(p->u.prefix4), ifindex, + safe_strerror(errno)); + else + zlog_debug( + "interface %s [%u] join AllSPFRouters Multicast group.", + inet_ntoa(p->u.prefix4), ifindex); + + return ret; } -int -ospf_if_drop_allspfrouters (struct ospf *top, struct prefix *p, - ifindex_t ifindex) +int ospf_if_drop_allspfrouters(struct ospf *top, struct prefix *p, + ifindex_t ifindex) { - int ret; - - ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP, - p->u.prefix4, htonl (OSPF_ALLSPFROUTERS), - ifindex); - if (ret < 0) - zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " - "ifindex %u, AllSPFRouters): %s", - top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); - else - zlog_debug ("interface %s [%u] leave AllSPFRouters Multicast group.", - inet_ntoa (p->u.prefix4), ifindex); - - return ret; + int ret; + + ret = setsockopt_ipv4_multicast(top->fd, IP_DROP_MEMBERSHIP, + p->u.prefix4, htonl(OSPF_ALLSPFROUTERS), + ifindex); + if (ret < 0) + zlog_warn( + "can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " + "ifindex %u, AllSPFRouters): %s", + top->fd, inet_ntoa(p->u.prefix4), ifindex, + safe_strerror(errno)); + else + zlog_debug( + "interface %s [%u] leave AllSPFRouters Multicast group.", + inet_ntoa(p->u.prefix4), ifindex); + + return ret; } /* Join to the OSPF ALL Designated ROUTERS multicast group. */ -int -ospf_if_add_alldrouters (struct ospf *top, struct prefix *p, ifindex_t ifindex) +int ospf_if_add_alldrouters(struct ospf *top, struct prefix *p, + ifindex_t ifindex) { - int ret; - - ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP, - p->u.prefix4, htonl (OSPF_ALLDROUTERS), - ifindex); - if (ret < 0) - zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " - "ifindex %u, AllDRouters): %s; perhaps a kernel limit " - "on # of multicast group memberships has been exceeded?", - top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); - else - zlog_debug ("interface %s [%u] join AllDRouters Multicast group.", - inet_ntoa (p->u.prefix4), ifindex); - - return ret; + int ret; + + ret = setsockopt_ipv4_multicast(top->fd, IP_ADD_MEMBERSHIP, + p->u.prefix4, htonl(OSPF_ALLDROUTERS), + ifindex); + if (ret < 0) + zlog_warn( + "can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " + "ifindex %u, AllDRouters): %s; perhaps a kernel limit " + "on # of multicast group memberships has been exceeded?", + top->fd, inet_ntoa(p->u.prefix4), ifindex, + safe_strerror(errno)); + else + zlog_debug( + "interface %s [%u] join AllDRouters Multicast group.", + inet_ntoa(p->u.prefix4), ifindex); + + return ret; } -int -ospf_if_drop_alldrouters (struct ospf *top, struct prefix *p, ifindex_t ifindex) +int ospf_if_drop_alldrouters(struct ospf *top, struct prefix *p, + ifindex_t ifindex) { - int ret; - - ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP, - p->u.prefix4, htonl (OSPF_ALLDROUTERS), - ifindex); - if (ret < 0) - zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " - "ifindex %u, AllDRouters): %s", - top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); - else - zlog_debug ("interface %s [%u] leave AllDRouters Multicast group.", - inet_ntoa (p->u.prefix4), ifindex); - - return ret; + int ret; + + ret = setsockopt_ipv4_multicast(top->fd, IP_DROP_MEMBERSHIP, + p->u.prefix4, htonl(OSPF_ALLDROUTERS), + ifindex); + if (ret < 0) + zlog_warn( + "can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " + "ifindex %u, AllDRouters): %s", + top->fd, inet_ntoa(p->u.prefix4), ifindex, + safe_strerror(errno)); + else + zlog_debug( + "interface %s [%u] leave AllDRouters Multicast group.", + inet_ntoa(p->u.prefix4), ifindex); + + return ret; } -int -ospf_if_ipmulticast (struct ospf *top, struct prefix *p, ifindex_t ifindex) +int ospf_if_ipmulticast(struct ospf *top, struct prefix *p, ifindex_t ifindex) { - u_char val; - int ret, len; - - /* Prevent receiving self-origined multicast packets. */ - ret = setsockopt_ipv4_multicast_loop (top->fd, 0); - if (ret < 0) - zlog_warn ("can't setsockopt IP_MULTICAST_LOOP(0) for fd %d: %s", - top->fd, safe_strerror(errno)); - - /* Explicitly set multicast ttl to 1 -- endo. */ - val = 1; - len = sizeof (val); - ret = setsockopt (top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val, len); - if (ret < 0) - zlog_warn ("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s", - top->fd, safe_strerror (errno)); - - ret = setsockopt_ipv4_multicast_if (top->fd, p->u.prefix4, ifindex); - if (ret < 0) - zlog_warn("can't setsockopt IP_MULTICAST_IF(fd %d, addr %s, " - "ifindex %u): %s", - top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); - - return ret; + u_char val; + int ret, len; + + /* Prevent receiving self-origined multicast packets. */ + ret = setsockopt_ipv4_multicast_loop(top->fd, 0); + if (ret < 0) + zlog_warn("can't setsockopt IP_MULTICAST_LOOP(0) for fd %d: %s", + top->fd, safe_strerror(errno)); + + /* Explicitly set multicast ttl to 1 -- endo. */ + val = 1; + len = sizeof(val); + ret = setsockopt(top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val, + len); + if (ret < 0) + zlog_warn("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s", + top->fd, safe_strerror(errno)); + + ret = setsockopt_ipv4_multicast_if(top->fd, p->u.prefix4, ifindex); + if (ret < 0) + zlog_warn( + "can't setsockopt IP_MULTICAST_IF(fd %d, addr %s, " + "ifindex %u): %s", + top->fd, inet_ntoa(p->u.prefix4), ifindex, + safe_strerror(errno)); + + return ret; } -int -ospf_sock_init (void) +int ospf_sock_init(void) { - int ospf_sock; - int ret, hincl = 1; - int bufsize = (8 * 1024 * 1024); - - if ( ospfd_privs.change (ZPRIVS_RAISE) ) - zlog_err ("ospf_sock_init: could not raise privs, %s", - safe_strerror (errno) ); - - ospf_sock = socket (AF_INET, SOCK_RAW, IPPROTO_OSPFIGP); - if (ospf_sock < 0) - { - int save_errno = errno; - if ( ospfd_privs.change (ZPRIVS_LOWER) ) - zlog_err ("ospf_sock_init: could not lower privs, %s", - safe_strerror (errno) ); - zlog_err ("ospf_read_sock_init: socket: %s", safe_strerror (save_errno)); - exit(1); - } - + int ospf_sock; + int ret, hincl = 1; + int bufsize = (8 * 1024 * 1024); + + if (ospfd_privs.change(ZPRIVS_RAISE)) + zlog_err("ospf_sock_init: could not raise privs, %s", + safe_strerror(errno)); + + ospf_sock = socket(AF_INET, SOCK_RAW, IPPROTO_OSPFIGP); + if (ospf_sock < 0) { + int save_errno = errno; + if (ospfd_privs.change(ZPRIVS_LOWER)) + zlog_err("ospf_sock_init: could not lower privs, %s", + safe_strerror(errno)); + zlog_err("ospf_read_sock_init: socket: %s", + safe_strerror(save_errno)); + exit(1); + } + #ifdef IP_HDRINCL - /* we will include IP header with packet */ - ret = setsockopt (ospf_sock, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof (hincl)); - if (ret < 0) - { - int save_errno = errno; - if ( ospfd_privs.change (ZPRIVS_LOWER) ) - zlog_err ("ospf_sock_init: could not lower privs, %s", - safe_strerror (errno) ); - zlog_warn ("Can't set IP_HDRINCL option for fd %d: %s", - ospf_sock, safe_strerror(save_errno)); - } -#elif defined (IPTOS_PREC_INTERNETCONTROL) + /* we will include IP header with packet */ + ret = setsockopt(ospf_sock, IPPROTO_IP, IP_HDRINCL, &hincl, + sizeof(hincl)); + if (ret < 0) { + int save_errno = errno; + if (ospfd_privs.change(ZPRIVS_LOWER)) + zlog_err("ospf_sock_init: could not lower privs, %s", + safe_strerror(errno)); + zlog_warn("Can't set IP_HDRINCL option for fd %d: %s", + ospf_sock, safe_strerror(save_errno)); + } +#elif defined(IPTOS_PREC_INTERNETCONTROL) #warning "IP_HDRINCL not available on this system" #warning "using IPTOS_PREC_INTERNETCONTROL" - ret = setsockopt_ipv4_tos(ospf_sock, IPTOS_PREC_INTERNETCONTROL); - if (ret < 0) - { - int save_errno = errno; - if ( ospfd_privs.change (ZPRIVS_LOWER) ) - zlog_err ("ospf_sock_init: could not lower privs, %s", - safe_strerror (errno) ); - zlog_warn ("can't set sockopt IP_TOS %d to socket %d: %s", - tos, ospf_sock, safe_strerror(save_errno)); - close (ospf_sock); /* Prevent sd leak. */ - return ret; - } + ret = setsockopt_ipv4_tos(ospf_sock, IPTOS_PREC_INTERNETCONTROL); + if (ret < 0) { + int save_errno = errno; + if (ospfd_privs.change(ZPRIVS_LOWER)) + zlog_err("ospf_sock_init: could not lower privs, %s", + safe_strerror(errno)); + zlog_warn("can't set sockopt IP_TOS %d to socket %d: %s", tos, + ospf_sock, safe_strerror(save_errno)); + close(ospf_sock); /* Prevent sd leak. */ + return ret; + } #else /* !IPTOS_PREC_INTERNETCONTROL */ #warning "IP_HDRINCL not available, nor is IPTOS_PREC_INTERNETCONTROL" - zlog_warn ("IP_HDRINCL option not available"); + zlog_warn("IP_HDRINCL option not available"); #endif /* IP_HDRINCL */ - ret = setsockopt_ifindex (AF_INET, ospf_sock, 1); + ret = setsockopt_ifindex(AF_INET, ospf_sock, 1); - if (ret < 0) - zlog_warn ("Can't set pktinfo option for fd %d", ospf_sock); + if (ret < 0) + zlog_warn("Can't set pktinfo option for fd %d", ospf_sock); - if (ospfd_privs.change (ZPRIVS_LOWER)) - { - zlog_err ("ospf_sock_init: could not lower privs, %s", - safe_strerror (errno) ); - } + if (ospfd_privs.change(ZPRIVS_LOWER)) { + zlog_err("ospf_sock_init: could not lower privs, %s", + safe_strerror(errno)); + } - setsockopt_so_sendbuf (ospf_sock, bufsize); - setsockopt_so_recvbuf (ospf_sock, bufsize); + setsockopt_so_sendbuf(ospf_sock, bufsize); + setsockopt_so_recvbuf(ospf_sock, bufsize); - return ospf_sock; + return ospf_sock; } diff --git a/ospfd/ospf_network.h b/ospfd/ospf_network.h index 506a41905..ed5e00315 100644 --- a/ospfd/ospf_network.h +++ b/ospfd/ospf_network.h @@ -23,15 +23,12 @@ #define _ZEBRA_OSPF_NETWORK_H /* Prototypes. */ -extern int ospf_if_add_allspfrouters (struct ospf *, struct prefix *, +extern int ospf_if_add_allspfrouters(struct ospf *, struct prefix *, ifindex_t); +extern int ospf_if_drop_allspfrouters(struct ospf *, struct prefix *, ifindex_t); -extern int ospf_if_drop_allspfrouters (struct ospf *, struct prefix *, - ifindex_t); -extern int ospf_if_add_alldrouters (struct ospf *, struct prefix *, - ifindex_t); -extern int ospf_if_drop_alldrouters (struct ospf *, struct prefix *, - ifindex_t); -extern int ospf_if_ipmulticast (struct ospf *, struct prefix *, ifindex_t); -extern int ospf_sock_init (void); +extern int ospf_if_add_alldrouters(struct ospf *, struct prefix *, ifindex_t); +extern int ospf_if_drop_alldrouters(struct ospf *, struct prefix *, ifindex_t); +extern int ospf_if_ipmulticast(struct ospf *, struct prefix *, ifindex_t); +extern int ospf_sock_init(void); #endif /* _ZEBRA_OSPF_NETWORK_H */ diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index 676069d6e..a0ff2bfcc 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -50,49 +50,47 @@ #include "ospfd/ospf_bfd.h" DEFINE_HOOK(ospf_nsm_change, - (struct ospf_neighbor *on, int state, int oldstate), - (on, state, oldstate)) + (struct ospf_neighbor * on, int state, int oldstate), + (on, state, oldstate)) -static void nsm_clear_adj (struct ospf_neighbor *); +static void nsm_clear_adj(struct ospf_neighbor *); /* OSPF NSM Timer functions. */ -static int -ospf_inactivity_timer (struct thread *thread) +static int ospf_inactivity_timer(struct thread *thread) { - struct ospf_neighbor *nbr; + struct ospf_neighbor *nbr; - nbr = THREAD_ARG (thread); - nbr->t_inactivity = NULL; + nbr = THREAD_ARG(thread); + nbr->t_inactivity = NULL; - if (IS_DEBUG_OSPF (nsm, NSM_TIMERS)) - zlog_debug("NSM[%s:%s]: Timer (Inactivity timer expire)", - IF_NAME(nbr->oi), inet_ntoa(nbr->router_id)); + if (IS_DEBUG_OSPF(nsm, NSM_TIMERS)) + zlog_debug("NSM[%s:%s]: Timer (Inactivity timer expire)", + IF_NAME(nbr->oi), inet_ntoa(nbr->router_id)); - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_InactivityTimer); + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_InactivityTimer); - return 0; + return 0; } -static int -ospf_db_desc_timer (struct thread *thread) +static int ospf_db_desc_timer(struct thread *thread) { - struct ospf_neighbor *nbr; + struct ospf_neighbor *nbr; - nbr = THREAD_ARG (thread); - nbr->t_db_desc = NULL; + nbr = THREAD_ARG(thread); + nbr->t_db_desc = NULL; - if (IS_DEBUG_OSPF (nsm, NSM_TIMERS)) - zlog_debug("NSM[%s:%s]: Timer (DD Retransmit timer expire)", - IF_NAME(nbr->oi), inet_ntoa(nbr->src)); + if (IS_DEBUG_OSPF(nsm, NSM_TIMERS)) + zlog_debug("NSM[%s:%s]: Timer (DD Retransmit timer expire)", + IF_NAME(nbr->oi), inet_ntoa(nbr->src)); - /* resent last send DD packet. */ - assert (nbr->last_send); - ospf_db_desc_resend (nbr); + /* resent last send DD packet. */ + assert(nbr->last_send); + ospf_db_desc_resend(nbr); - /* DD Retransmit timer set. */ - OSPF_NSM_TIMER_ON (nbr->t_db_desc, ospf_db_desc_timer, nbr->v_db_desc); + /* DD Retransmit timer set. */ + OSPF_NSM_TIMER_ON(nbr->t_db_desc, ospf_db_desc_timer, nbr->v_db_desc); - return 0; + return 0; } /* Hook function called after ospf NSM event is occured. @@ -104,176 +102,166 @@ ospf_db_desc_timer (struct thread *thread) * We rely on this function to properly clear timers in lower states, * particularly before deleting a neighbour. */ -static void -nsm_timer_set (struct ospf_neighbor *nbr) +static void nsm_timer_set(struct ospf_neighbor *nbr) { - switch (nbr->state) - { - case NSM_Deleted: - case NSM_Down: - OSPF_NSM_TIMER_OFF (nbr->t_inactivity); - OSPF_NSM_TIMER_OFF (nbr->t_hello_reply); - /* fallthru */ - case NSM_Attempt: - case NSM_Init: - case NSM_TwoWay: - OSPF_NSM_TIMER_OFF (nbr->t_db_desc); - OSPF_NSM_TIMER_OFF (nbr->t_ls_upd); - OSPF_NSM_TIMER_OFF (nbr->t_ls_req); - break; - case NSM_ExStart: - OSPF_NSM_TIMER_ON (nbr->t_db_desc, ospf_db_desc_timer, nbr->v_db_desc); - OSPF_NSM_TIMER_OFF (nbr->t_ls_upd); - OSPF_NSM_TIMER_OFF (nbr->t_ls_req); - break; - case NSM_Exchange: - OSPF_NSM_TIMER_ON (nbr->t_ls_upd, ospf_ls_upd_timer, nbr->v_ls_upd); - if (!IS_SET_DD_MS (nbr->dd_flags)) - OSPF_NSM_TIMER_OFF (nbr->t_db_desc); - break; - case NSM_Loading: - case NSM_Full: - default: - OSPF_NSM_TIMER_OFF (nbr->t_db_desc); - break; - } + switch (nbr->state) { + case NSM_Deleted: + case NSM_Down: + OSPF_NSM_TIMER_OFF(nbr->t_inactivity); + OSPF_NSM_TIMER_OFF(nbr->t_hello_reply); + /* fallthru */ + case NSM_Attempt: + case NSM_Init: + case NSM_TwoWay: + OSPF_NSM_TIMER_OFF(nbr->t_db_desc); + OSPF_NSM_TIMER_OFF(nbr->t_ls_upd); + OSPF_NSM_TIMER_OFF(nbr->t_ls_req); + break; + case NSM_ExStart: + OSPF_NSM_TIMER_ON(nbr->t_db_desc, ospf_db_desc_timer, + nbr->v_db_desc); + OSPF_NSM_TIMER_OFF(nbr->t_ls_upd); + OSPF_NSM_TIMER_OFF(nbr->t_ls_req); + break; + case NSM_Exchange: + OSPF_NSM_TIMER_ON(nbr->t_ls_upd, ospf_ls_upd_timer, + nbr->v_ls_upd); + if (!IS_SET_DD_MS(nbr->dd_flags)) + OSPF_NSM_TIMER_OFF(nbr->t_db_desc); + break; + case NSM_Loading: + case NSM_Full: + default: + OSPF_NSM_TIMER_OFF(nbr->t_db_desc); + break; + } } /* 10.4 of RFC2328, indicate whether an adjacency is appropriate with * the given neighbour */ -static int -nsm_should_adj (struct ospf_neighbor *nbr) +static int nsm_should_adj(struct ospf_neighbor *nbr) { - struct ospf_interface *oi = nbr->oi; - - /* These network types must always form adjacencies. */ - if (oi->type == OSPF_IFTYPE_POINTOPOINT - || oi->type == OSPF_IFTYPE_POINTOMULTIPOINT - || oi->type == OSPF_IFTYPE_VIRTUALLINK - /* Router itself is the DRouter or the BDRouter. */ - || IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi)) - || IPV4_ADDR_SAME (&oi->address->u.prefix4, &BDR (oi)) - /* Neighboring Router is the DRouter or the BDRouter. */ - || IPV4_ADDR_SAME (&nbr->address.u.prefix4, &DR (oi)) - || IPV4_ADDR_SAME (&nbr->address.u.prefix4, &BDR (oi))) - return 1; - - return 0; + struct ospf_interface *oi = nbr->oi; + + /* These network types must always form adjacencies. */ + if (oi->type == OSPF_IFTYPE_POINTOPOINT + || oi->type == OSPF_IFTYPE_POINTOMULTIPOINT + || oi->type == OSPF_IFTYPE_VIRTUALLINK + /* Router itself is the DRouter or the BDRouter. */ + || IPV4_ADDR_SAME(&oi->address->u.prefix4, &DR(oi)) + || IPV4_ADDR_SAME(&oi->address->u.prefix4, &BDR(oi)) + /* Neighboring Router is the DRouter or the BDRouter. */ + || IPV4_ADDR_SAME(&nbr->address.u.prefix4, &DR(oi)) + || IPV4_ADDR_SAME(&nbr->address.u.prefix4, &BDR(oi))) + return 1; + + return 0; } /* OSPF NSM functions. */ -static int -nsm_packet_received (struct ospf_neighbor *nbr) +static int nsm_packet_received(struct ospf_neighbor *nbr) { - /* Start or Restart Inactivity Timer. */ - OSPF_NSM_TIMER_OFF (nbr->t_inactivity); - - OSPF_NSM_TIMER_ON (nbr->t_inactivity, ospf_inactivity_timer, - nbr->v_inactivity); + /* Start or Restart Inactivity Timer. */ + OSPF_NSM_TIMER_OFF(nbr->t_inactivity); + + OSPF_NSM_TIMER_ON(nbr->t_inactivity, ospf_inactivity_timer, + nbr->v_inactivity); - if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma) - OSPF_POLL_TIMER_OFF (nbr->nbr_nbma->t_poll); + if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma) + OSPF_POLL_TIMER_OFF(nbr->nbr_nbma->t_poll); - /* Send proactive ARP requests */ - if (nbr->state < NSM_Exchange) - ospf_proactively_arp (nbr); + /* Send proactive ARP requests */ + if (nbr->state < NSM_Exchange) + ospf_proactively_arp(nbr); - return 0; + return 0; } -static int -nsm_start (struct ospf_neighbor *nbr) +static int nsm_start(struct ospf_neighbor *nbr) { - if (nbr->nbr_nbma) - OSPF_POLL_TIMER_OFF (nbr->nbr_nbma->t_poll); + if (nbr->nbr_nbma) + OSPF_POLL_TIMER_OFF(nbr->nbr_nbma->t_poll); - OSPF_NSM_TIMER_OFF (nbr->t_inactivity); - - OSPF_NSM_TIMER_ON (nbr->t_inactivity, ospf_inactivity_timer, - nbr->v_inactivity); + OSPF_NSM_TIMER_OFF(nbr->t_inactivity); - /* Send proactive ARP requests */ - ospf_proactively_arp (nbr); + OSPF_NSM_TIMER_ON(nbr->t_inactivity, ospf_inactivity_timer, + nbr->v_inactivity); - return 0; + /* Send proactive ARP requests */ + ospf_proactively_arp(nbr); + + return 0; } -static int -nsm_twoway_received (struct ospf_neighbor *nbr) +static int nsm_twoway_received(struct ospf_neighbor *nbr) { - int adj = nsm_should_adj (nbr); + int adj = nsm_should_adj(nbr); - /* Send proactive ARP requests */ - if (adj) - ospf_proactively_arp (nbr); + /* Send proactive ARP requests */ + if (adj) + ospf_proactively_arp(nbr); - return (adj ? NSM_ExStart : NSM_TwoWay); + return (adj ? NSM_ExStart : NSM_TwoWay); } -int -ospf_db_summary_count (struct ospf_neighbor *nbr) +int ospf_db_summary_count(struct ospf_neighbor *nbr) { - return ospf_lsdb_count_all (&nbr->db_sum); + return ospf_lsdb_count_all(&nbr->db_sum); } -int -ospf_db_summary_isempty (struct ospf_neighbor *nbr) +int ospf_db_summary_isempty(struct ospf_neighbor *nbr) { - return ospf_lsdb_isempty (&nbr->db_sum); + return ospf_lsdb_isempty(&nbr->db_sum); } -static int -ospf_db_summary_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) +static int ospf_db_summary_add(struct ospf_neighbor *nbr, struct ospf_lsa *lsa) { - switch (lsa->data->type) - { - case OSPF_OPAQUE_LINK_LSA: - /* Exclude type-9 LSAs that does not have the same "oi" with "nbr". */ - if (nbr->oi && ospf_if_exists (lsa->oi) != nbr->oi) - return 0; - break; - case OSPF_OPAQUE_AREA_LSA: - /* - * It is assured by the caller function "nsm_negotiation_done()" - * that every given LSA belongs to the same area with "nbr". - */ - break; - case OSPF_OPAQUE_AS_LSA: - default: - break; - } - - /* Stay away from any Local Translated Type-7 LSAs */ - if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)) - return 0; - - if (IS_LSA_MAXAGE (lsa)) - ospf_ls_retransmit_add (nbr, lsa); - else - ospf_lsdb_add (&nbr->db_sum, lsa); - - return 0; + switch (lsa->data->type) { + case OSPF_OPAQUE_LINK_LSA: + /* Exclude type-9 LSAs that does not have the same "oi" with + * "nbr". */ + if (nbr->oi && ospf_if_exists(lsa->oi) != nbr->oi) + return 0; + break; + case OSPF_OPAQUE_AREA_LSA: + /* + * It is assured by the caller function "nsm_negotiation_done()" + * that every given LSA belongs to the same area with "nbr". + */ + break; + case OSPF_OPAQUE_AS_LSA: + default: + break; + } + + /* Stay away from any Local Translated Type-7 LSAs */ + if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) + return 0; + + if (IS_LSA_MAXAGE(lsa)) + ospf_ls_retransmit_add(nbr, lsa); + else + ospf_lsdb_add(&nbr->db_sum, lsa); + + return 0; } -void -ospf_db_summary_clear (struct ospf_neighbor *nbr) +void ospf_db_summary_clear(struct ospf_neighbor *nbr) { - struct ospf_lsdb *lsdb; - int i; - - lsdb = &nbr->db_sum; - for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) - { - struct route_table *table = lsdb->type[i].db; - struct route_node *rn; - - for (rn = route_top (table); rn; rn = route_next (rn)) - if (rn->info) - ospf_lsdb_delete (&nbr->db_sum, rn->info); - } -} + struct ospf_lsdb *lsdb; + int i; + lsdb = &nbr->db_sum; + for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) { + struct route_table *table = lsdb->type[i].db; + struct route_node *rn; + + for (rn = route_top(table); rn; rn = route_next(rn)) + if (rn->info) + ospf_lsdb_delete(&nbr->db_sum, rn->info); + } +} /* The area link state database consists of the router-LSAs, @@ -282,598 +270,577 @@ ospf_db_summary_clear (struct ospf_neighbor *nbr) AS-external-LSAs are omitted from a virtual neighbor's Database summary list. AS-external-LSAs are omitted from the Database summary list if the area has been configured as a stub. */ -static int -nsm_negotiation_done (struct ospf_neighbor *nbr) +static int nsm_negotiation_done(struct ospf_neighbor *nbr) { - struct ospf_area *area = nbr->oi->area; - struct ospf_lsa *lsa; - struct route_node *rn; - - /* Send proactive ARP requests */ - ospf_proactively_arp (nbr); - - LSDB_LOOP (ROUTER_LSDB (area), rn, lsa) - ospf_db_summary_add (nbr, lsa); - LSDB_LOOP (NETWORK_LSDB (area), rn, lsa) - ospf_db_summary_add (nbr, lsa); - LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa) - ospf_db_summary_add (nbr, lsa); - LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa) - ospf_db_summary_add (nbr, lsa); - - /* Process only if the neighbor is opaque capable. */ - if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)) - { - LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa) - ospf_db_summary_add (nbr, lsa); - LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) - ospf_db_summary_add (nbr, lsa); - } - - if (CHECK_FLAG (nbr->options, OSPF_OPTION_NP)) - { - LSDB_LOOP (NSSA_LSDB (area), rn, lsa) - ospf_db_summary_add (nbr, lsa); - } - - if (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK - && area->external_routing == OSPF_AREA_DEFAULT) - LSDB_LOOP (EXTERNAL_LSDB (nbr->oi->ospf), rn, lsa) - ospf_db_summary_add (nbr, lsa); - - if (CHECK_FLAG (nbr->options, OSPF_OPTION_O) - && (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK - && area->external_routing == OSPF_AREA_DEFAULT)) - LSDB_LOOP (OPAQUE_AS_LSDB (nbr->oi->ospf), rn, lsa) - ospf_db_summary_add (nbr, lsa); - - return 0; + struct ospf_area *area = nbr->oi->area; + struct ospf_lsa *lsa; + struct route_node *rn; + + /* Send proactive ARP requests */ + ospf_proactively_arp(nbr); + + LSDB_LOOP(ROUTER_LSDB(area), rn, lsa) + ospf_db_summary_add(nbr, lsa); + LSDB_LOOP(NETWORK_LSDB(area), rn, lsa) + ospf_db_summary_add(nbr, lsa); + LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa) + ospf_db_summary_add(nbr, lsa); + LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa) + ospf_db_summary_add(nbr, lsa); + + /* Process only if the neighbor is opaque capable. */ + if (CHECK_FLAG(nbr->options, OSPF_OPTION_O)) { + LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa) + ospf_db_summary_add(nbr, lsa); + LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa) + ospf_db_summary_add(nbr, lsa); + } + + if (CHECK_FLAG(nbr->options, OSPF_OPTION_NP)) { + LSDB_LOOP(NSSA_LSDB(area), rn, lsa) + ospf_db_summary_add(nbr, lsa); + } + + if (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK + && area->external_routing == OSPF_AREA_DEFAULT) + LSDB_LOOP(EXTERNAL_LSDB(nbr->oi->ospf), rn, lsa) + ospf_db_summary_add(nbr, lsa); + + if (CHECK_FLAG(nbr->options, OSPF_OPTION_O) + && (nbr->oi->type != OSPF_IFTYPE_VIRTUALLINK + && area->external_routing == OSPF_AREA_DEFAULT)) + LSDB_LOOP(OPAQUE_AS_LSDB(nbr->oi->ospf), rn, lsa) + ospf_db_summary_add(nbr, lsa); + + return 0; } -static int -nsm_exchange_done (struct ospf_neighbor *nbr) +static int nsm_exchange_done(struct ospf_neighbor *nbr) { - if (ospf_ls_request_isempty (nbr)) - return NSM_Full; + if (ospf_ls_request_isempty(nbr)) + return NSM_Full; - /* Send Link State Request. */ - if (nbr->t_ls_req == NULL) - ospf_ls_req_send (nbr); + /* Send Link State Request. */ + if (nbr->t_ls_req == NULL) + ospf_ls_req_send(nbr); - return NSM_Loading; + return NSM_Loading; } -static int -nsm_adj_ok (struct ospf_neighbor *nbr) +static int nsm_adj_ok(struct ospf_neighbor *nbr) { - int next_state = nbr->state; - int adj = nsm_should_adj (nbr); + int next_state = nbr->state; + int adj = nsm_should_adj(nbr); - if (nbr->state == NSM_TwoWay && adj == 1) - { - next_state = NSM_ExStart; + if (nbr->state == NSM_TwoWay && adj == 1) { + next_state = NSM_ExStart; - /* Send proactive ARP requests */ - ospf_proactively_arp (nbr); - } - else if (nbr->state >= NSM_ExStart && adj == 0) - next_state = NSM_TwoWay; + /* Send proactive ARP requests */ + ospf_proactively_arp(nbr); + } else if (nbr->state >= NSM_ExStart && adj == 0) + next_state = NSM_TwoWay; - return next_state; + return next_state; } /* Clear adjacency related state for a neighbour, intended where nbr * transitions from > ExStart (i.e. a Full or forming adjacency) * to <= ExStart. */ -static void -nsm_clear_adj (struct ospf_neighbor *nbr) +static void nsm_clear_adj(struct ospf_neighbor *nbr) { - /* Clear Database Summary list. */ - if (!ospf_db_summary_isempty (nbr)) - ospf_db_summary_clear (nbr); + /* Clear Database Summary list. */ + if (!ospf_db_summary_isempty(nbr)) + ospf_db_summary_clear(nbr); - /* Clear Link State Request list. */ - if (!ospf_ls_request_isempty (nbr)) - ospf_ls_request_delete_all (nbr); + /* Clear Link State Request list. */ + if (!ospf_ls_request_isempty(nbr)) + ospf_ls_request_delete_all(nbr); - /* Clear Link State Retransmission list. */ - if (!ospf_ls_retransmit_isempty (nbr)) - ospf_ls_retransmit_clear (nbr); + /* Clear Link State Retransmission list. */ + if (!ospf_ls_retransmit_isempty(nbr)) + ospf_ls_retransmit_clear(nbr); - if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)) - UNSET_FLAG (nbr->options, OSPF_OPTION_O); + if (CHECK_FLAG(nbr->options, OSPF_OPTION_O)) + UNSET_FLAG(nbr->options, OSPF_OPTION_O); } -static int -nsm_kill_nbr (struct ospf_neighbor *nbr) +static int nsm_kill_nbr(struct ospf_neighbor *nbr) { - /* killing nbr_self is invalid */ - if (nbr == nbr->oi->nbr_self) - { - assert (nbr != nbr->oi->nbr_self); - return 0; - } - - if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma != NULL) - { - struct ospf_nbr_nbma *nbr_nbma = nbr->nbr_nbma; - - nbr_nbma->nbr = NULL; - nbr_nbma->state_change = nbr->state_change; - - nbr->nbr_nbma = NULL; - - OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer, - nbr_nbma->v_poll); - - if (IS_DEBUG_OSPF (nsm, NSM_EVENTS)) - zlog_debug ("NSM[%s:%s]: Down (PollIntervalTimer scheduled)", - IF_NAME (nbr->oi), inet_ntoa (nbr->address.u.prefix4)); - } - - return 0; + /* killing nbr_self is invalid */ + if (nbr == nbr->oi->nbr_self) { + assert(nbr != nbr->oi->nbr_self); + return 0; + } + + if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma != NULL) { + struct ospf_nbr_nbma *nbr_nbma = nbr->nbr_nbma; + + nbr_nbma->nbr = NULL; + nbr_nbma->state_change = nbr->state_change; + + nbr->nbr_nbma = NULL; + + OSPF_POLL_TIMER_ON(nbr_nbma->t_poll, ospf_poll_timer, + nbr_nbma->v_poll); + + if (IS_DEBUG_OSPF(nsm, NSM_EVENTS)) + zlog_debug( + "NSM[%s:%s]: Down (PollIntervalTimer scheduled)", + IF_NAME(nbr->oi), + inet_ntoa(nbr->address.u.prefix4)); + } + + return 0; } /* Neighbor State Machine */ struct { - int (*func) (struct ospf_neighbor *); - int next_state; -} NSM [OSPF_NSM_STATE_MAX][OSPF_NSM_EVENT_MAX] = -{ - { - /* DependUpon: dummy state. */ - { NULL, NSM_DependUpon }, /* NoEvent */ - { NULL, NSM_DependUpon }, /* PacketReceived */ - { NULL, NSM_DependUpon }, /* Start */ - { NULL, NSM_DependUpon }, /* 2-WayReceived */ - { NULL, NSM_DependUpon }, /* NegotiationDone */ - { NULL, NSM_DependUpon }, /* ExchangeDone */ - { NULL, NSM_DependUpon }, /* BadLSReq */ - { NULL, NSM_DependUpon }, /* LoadingDone */ - { NULL, NSM_DependUpon }, /* AdjOK? */ - { NULL, NSM_DependUpon }, /* SeqNumberMismatch */ - { NULL, NSM_DependUpon }, /* 1-WayReceived */ - { NULL, NSM_DependUpon }, /* KillNbr */ - { NULL, NSM_DependUpon }, /* InactivityTimer */ - { NULL, NSM_DependUpon }, /* LLDown */ - }, - { - /* Deleted: dummy state. */ - { NULL, NSM_Deleted }, /* NoEvent */ - { NULL, NSM_Deleted }, /* PacketReceived */ - { NULL, NSM_Deleted }, /* Start */ - { NULL, NSM_Deleted }, /* 2-WayReceived */ - { NULL, NSM_Deleted }, /* NegotiationDone */ - { NULL, NSM_Deleted }, /* ExchangeDone */ - { NULL, NSM_Deleted }, /* BadLSReq */ - { NULL, NSM_Deleted }, /* LoadingDone */ - { NULL, NSM_Deleted }, /* AdjOK? */ - { NULL, NSM_Deleted }, /* SeqNumberMismatch */ - { NULL, NSM_Deleted }, /* 1-WayReceived */ - { NULL, NSM_Deleted }, /* KillNbr */ - { NULL, NSM_Deleted }, /* InactivityTimer */ - { NULL, NSM_Deleted }, /* LLDown */ - }, - { - /* Down: */ - { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_packet_received, NSM_Init }, /* PacketReceived */ - { nsm_start, NSM_Attempt }, /* Start */ - { NULL, NSM_Down }, /* 2-WayReceived */ - { NULL, NSM_Down }, /* NegotiationDone */ - { NULL, NSM_Down }, /* ExchangeDone */ - { NULL, NSM_Down }, /* BadLSReq */ - { NULL, NSM_Down }, /* LoadingDone */ - { NULL, NSM_Down }, /* AdjOK? */ - { NULL, NSM_Down }, /* SeqNumberMismatch */ - { NULL, NSM_Down }, /* 1-WayReceived */ - { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */ - { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */ - { nsm_kill_nbr, NSM_Deleted }, /* LLDown */ - }, - { - /* Attempt: */ - { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_packet_received, NSM_Init }, /* PacketReceived */ - { NULL, NSM_Attempt }, /* Start */ - { NULL, NSM_Attempt }, /* 2-WayReceived */ - { NULL, NSM_Attempt }, /* NegotiationDone */ - { NULL, NSM_Attempt }, /* ExchangeDone */ - { NULL, NSM_Attempt }, /* BadLSReq */ - { NULL, NSM_Attempt }, /* LoadingDone */ - { NULL, NSM_Attempt }, /* AdjOK? */ - { NULL, NSM_Attempt }, /* SeqNumberMismatch */ - { NULL, NSM_Attempt }, /* 1-WayReceived */ - { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */ - { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */ - { nsm_kill_nbr, NSM_Deleted }, /* LLDown */ - }, - { - /* Init: */ - { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_packet_received, NSM_Init }, /* PacketReceived */ - { NULL, NSM_Init }, /* Start */ - { nsm_twoway_received, NSM_DependUpon }, /* 2-WayReceived */ - { NULL, NSM_Init }, /* NegotiationDone */ - { NULL, NSM_Init }, /* ExchangeDone */ - { NULL, NSM_Init }, /* BadLSReq */ - { NULL, NSM_Init }, /* LoadingDone */ - { NULL, NSM_Init }, /* AdjOK? */ - { NULL, NSM_Init }, /* SeqNumberMismatch */ - { NULL, NSM_Init }, /* 1-WayReceived */ - { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */ - { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */ - { nsm_kill_nbr, NSM_Deleted }, /* LLDown */ - }, - { - /* 2-Way: */ - { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_packet_received, NSM_TwoWay }, /* HelloReceived */ - { NULL, NSM_TwoWay }, /* Start */ - { NULL, NSM_TwoWay }, /* 2-WayReceived */ - { NULL, NSM_TwoWay }, /* NegotiationDone */ - { NULL, NSM_TwoWay }, /* ExchangeDone */ - { NULL, NSM_TwoWay }, /* BadLSReq */ - { NULL, NSM_TwoWay }, /* LoadingDone */ - { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */ - { NULL, NSM_TwoWay }, /* SeqNumberMismatch */ - { NULL, NSM_Init }, /* 1-WayReceived */ - { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */ - { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */ - { nsm_kill_nbr, NSM_Deleted }, /* LLDown */ - }, - { - /* ExStart: */ - { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_packet_received, NSM_ExStart }, /* PacaketReceived */ - { NULL, NSM_ExStart }, /* Start */ - { NULL, NSM_ExStart }, /* 2-WayReceived */ - { nsm_negotiation_done, NSM_Exchange }, /* NegotiationDone */ - { NULL, NSM_ExStart }, /* ExchangeDone */ - { NULL, NSM_ExStart }, /* BadLSReq */ - { NULL, NSM_ExStart }, /* LoadingDone */ - { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */ - { NULL, NSM_ExStart }, /* SeqNumberMismatch */ - { NULL, NSM_Init }, /* 1-WayReceived */ - { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */ - { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */ - { nsm_kill_nbr, NSM_Deleted }, /* LLDown */ - }, - { - /* Exchange: */ - { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_packet_received, NSM_Exchange }, /* PacketReceived */ - { NULL, NSM_Exchange }, /* Start */ - { NULL, NSM_Exchange }, /* 2-WayReceived */ - { NULL, NSM_Exchange }, /* NegotiationDone */ - { nsm_exchange_done, NSM_DependUpon }, /* ExchangeDone */ - { NULL, NSM_ExStart }, /* BadLSReq */ - { NULL, NSM_Exchange }, /* LoadingDone */ - { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */ - { NULL, NSM_ExStart }, /* SeqNumberMismatch */ - { NULL, NSM_Init }, /* 1-WayReceived */ - { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */ - { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */ - { nsm_kill_nbr, NSM_Deleted }, /* LLDown */ - }, - { - /* Loading: */ - { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_packet_received, NSM_Loading }, /* PacketReceived */ - { NULL, NSM_Loading }, /* Start */ - { NULL, NSM_Loading }, /* 2-WayReceived */ - { NULL, NSM_Loading }, /* NegotiationDone */ - { NULL, NSM_Loading }, /* ExchangeDone */ - { NULL, NSM_ExStart }, /* BadLSReq */ - { NULL, NSM_Full }, /* LoadingDone */ - { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */ - { NULL, NSM_ExStart }, /* SeqNumberMismatch */ - { NULL, NSM_Init }, /* 1-WayReceived */ - { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */ - { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */ - { nsm_kill_nbr, NSM_Deleted }, /* LLDown */ - }, - { /* Full: */ - { NULL, NSM_DependUpon }, /* NoEvent */ - { nsm_packet_received, NSM_Full }, /* PacketReceived */ - { NULL, NSM_Full }, /* Start */ - { NULL, NSM_Full }, /* 2-WayReceived */ - { NULL, NSM_Full }, /* NegotiationDone */ - { NULL, NSM_Full }, /* ExchangeDone */ - { NULL, NSM_ExStart }, /* BadLSReq */ - { NULL, NSM_Full }, /* LoadingDone */ - { nsm_adj_ok, NSM_DependUpon }, /* AdjOK? */ - { NULL, NSM_ExStart }, /* SeqNumberMismatch */ - { NULL, NSM_Init }, /* 1-WayReceived */ - { nsm_kill_nbr, NSM_Deleted }, /* KillNbr */ - { nsm_kill_nbr, NSM_Deleted }, /* InactivityTimer */ - { nsm_kill_nbr, NSM_Deleted }, /* LLDown */ - }, + int (*func)(struct ospf_neighbor *); + int next_state; +} NSM[OSPF_NSM_STATE_MAX][OSPF_NSM_EVENT_MAX] = { + { + /* DependUpon: dummy state. */ + {NULL, NSM_DependUpon}, /* NoEvent */ + {NULL, NSM_DependUpon}, /* PacketReceived */ + {NULL, NSM_DependUpon}, /* Start */ + {NULL, NSM_DependUpon}, /* 2-WayReceived */ + {NULL, NSM_DependUpon}, /* NegotiationDone */ + {NULL, NSM_DependUpon}, /* ExchangeDone */ + {NULL, NSM_DependUpon}, /* BadLSReq */ + {NULL, NSM_DependUpon}, /* LoadingDone */ + {NULL, NSM_DependUpon}, /* AdjOK? */ + {NULL, NSM_DependUpon}, /* SeqNumberMismatch */ + {NULL, NSM_DependUpon}, /* 1-WayReceived */ + {NULL, NSM_DependUpon}, /* KillNbr */ + {NULL, NSM_DependUpon}, /* InactivityTimer */ + {NULL, NSM_DependUpon}, /* LLDown */ + }, + { + /* Deleted: dummy state. */ + {NULL, NSM_Deleted}, /* NoEvent */ + {NULL, NSM_Deleted}, /* PacketReceived */ + {NULL, NSM_Deleted}, /* Start */ + {NULL, NSM_Deleted}, /* 2-WayReceived */ + {NULL, NSM_Deleted}, /* NegotiationDone */ + {NULL, NSM_Deleted}, /* ExchangeDone */ + {NULL, NSM_Deleted}, /* BadLSReq */ + {NULL, NSM_Deleted}, /* LoadingDone */ + {NULL, NSM_Deleted}, /* AdjOK? */ + {NULL, NSM_Deleted}, /* SeqNumberMismatch */ + {NULL, NSM_Deleted}, /* 1-WayReceived */ + {NULL, NSM_Deleted}, /* KillNbr */ + {NULL, NSM_Deleted}, /* InactivityTimer */ + {NULL, NSM_Deleted}, /* LLDown */ + }, + { + /* Down: */ + {NULL, NSM_DependUpon}, /* NoEvent */ + {nsm_packet_received, NSM_Init}, /* PacketReceived */ + {nsm_start, NSM_Attempt}, /* Start */ + {NULL, NSM_Down}, /* 2-WayReceived */ + {NULL, NSM_Down}, /* NegotiationDone */ + {NULL, NSM_Down}, /* ExchangeDone */ + {NULL, NSM_Down}, /* BadLSReq */ + {NULL, NSM_Down}, /* LoadingDone */ + {NULL, NSM_Down}, /* AdjOK? */ + {NULL, NSM_Down}, /* SeqNumberMismatch */ + {NULL, NSM_Down}, /* 1-WayReceived */ + {nsm_kill_nbr, NSM_Deleted}, /* KillNbr */ + {nsm_kill_nbr, NSM_Deleted}, /* InactivityTimer */ + {nsm_kill_nbr, NSM_Deleted}, /* LLDown */ + }, + { + /* Attempt: */ + {NULL, NSM_DependUpon}, /* NoEvent */ + {nsm_packet_received, NSM_Init}, /* PacketReceived */ + {NULL, NSM_Attempt}, /* Start */ + {NULL, NSM_Attempt}, /* 2-WayReceived */ + {NULL, NSM_Attempt}, /* NegotiationDone */ + {NULL, NSM_Attempt}, /* ExchangeDone */ + {NULL, NSM_Attempt}, /* BadLSReq */ + {NULL, NSM_Attempt}, /* LoadingDone */ + {NULL, NSM_Attempt}, /* AdjOK? */ + {NULL, NSM_Attempt}, /* SeqNumberMismatch */ + {NULL, NSM_Attempt}, /* 1-WayReceived */ + {nsm_kill_nbr, NSM_Deleted}, /* KillNbr */ + {nsm_kill_nbr, NSM_Deleted}, /* InactivityTimer */ + {nsm_kill_nbr, NSM_Deleted}, /* LLDown */ + }, + { + /* Init: */ + {NULL, NSM_DependUpon}, /* NoEvent */ + {nsm_packet_received, NSM_Init}, /* PacketReceived */ + {NULL, NSM_Init}, /* Start */ + {nsm_twoway_received, NSM_DependUpon}, /* 2-WayReceived */ + {NULL, NSM_Init}, /* NegotiationDone */ + {NULL, NSM_Init}, /* ExchangeDone */ + {NULL, NSM_Init}, /* BadLSReq */ + {NULL, NSM_Init}, /* LoadingDone */ + {NULL, NSM_Init}, /* AdjOK? */ + {NULL, NSM_Init}, /* SeqNumberMismatch */ + {NULL, NSM_Init}, /* 1-WayReceived */ + {nsm_kill_nbr, NSM_Deleted}, /* KillNbr */ + {nsm_kill_nbr, NSM_Deleted}, /* InactivityTimer */ + {nsm_kill_nbr, NSM_Deleted}, /* LLDown */ + }, + { + /* 2-Way: */ + {NULL, NSM_DependUpon}, /* NoEvent */ + {nsm_packet_received, NSM_TwoWay}, /* HelloReceived */ + {NULL, NSM_TwoWay}, /* Start */ + {NULL, NSM_TwoWay}, /* 2-WayReceived */ + {NULL, NSM_TwoWay}, /* NegotiationDone */ + {NULL, NSM_TwoWay}, /* ExchangeDone */ + {NULL, NSM_TwoWay}, /* BadLSReq */ + {NULL, NSM_TwoWay}, /* LoadingDone */ + {nsm_adj_ok, NSM_DependUpon}, /* AdjOK? */ + {NULL, NSM_TwoWay}, /* SeqNumberMismatch */ + {NULL, NSM_Init}, /* 1-WayReceived */ + {nsm_kill_nbr, NSM_Deleted}, /* KillNbr */ + {nsm_kill_nbr, NSM_Deleted}, /* InactivityTimer */ + {nsm_kill_nbr, NSM_Deleted}, /* LLDown */ + }, + { + /* ExStart: */ + {NULL, NSM_DependUpon}, /* NoEvent */ + {nsm_packet_received, NSM_ExStart}, /* PacaketReceived */ + {NULL, NSM_ExStart}, /* Start */ + {NULL, NSM_ExStart}, /* 2-WayReceived */ + {nsm_negotiation_done, NSM_Exchange}, /* NegotiationDone */ + {NULL, NSM_ExStart}, /* ExchangeDone */ + {NULL, NSM_ExStart}, /* BadLSReq */ + {NULL, NSM_ExStart}, /* LoadingDone */ + {nsm_adj_ok, NSM_DependUpon}, /* AdjOK? */ + {NULL, NSM_ExStart}, /* SeqNumberMismatch */ + {NULL, NSM_Init}, /* 1-WayReceived */ + {nsm_kill_nbr, NSM_Deleted}, /* KillNbr */ + {nsm_kill_nbr, NSM_Deleted}, /* InactivityTimer */ + {nsm_kill_nbr, NSM_Deleted}, /* LLDown */ + }, + { + /* Exchange: */ + {NULL, NSM_DependUpon}, /* NoEvent */ + {nsm_packet_received, NSM_Exchange}, /* PacketReceived */ + {NULL, NSM_Exchange}, /* Start */ + {NULL, NSM_Exchange}, /* 2-WayReceived */ + {NULL, NSM_Exchange}, /* NegotiationDone */ + {nsm_exchange_done, NSM_DependUpon}, /* ExchangeDone */ + {NULL, NSM_ExStart}, /* BadLSReq */ + {NULL, NSM_Exchange}, /* LoadingDone */ + {nsm_adj_ok, NSM_DependUpon}, /* AdjOK? */ + {NULL, NSM_ExStart}, /* SeqNumberMismatch */ + {NULL, NSM_Init}, /* 1-WayReceived */ + {nsm_kill_nbr, NSM_Deleted}, /* KillNbr */ + {nsm_kill_nbr, NSM_Deleted}, /* InactivityTimer */ + {nsm_kill_nbr, NSM_Deleted}, /* LLDown */ + }, + { + /* Loading: */ + {NULL, NSM_DependUpon}, /* NoEvent */ + {nsm_packet_received, NSM_Loading}, /* PacketReceived */ + {NULL, NSM_Loading}, /* Start */ + {NULL, NSM_Loading}, /* 2-WayReceived */ + {NULL, NSM_Loading}, /* NegotiationDone */ + {NULL, NSM_Loading}, /* ExchangeDone */ + {NULL, NSM_ExStart}, /* BadLSReq */ + {NULL, NSM_Full}, /* LoadingDone */ + {nsm_adj_ok, NSM_DependUpon}, /* AdjOK? */ + {NULL, NSM_ExStart}, /* SeqNumberMismatch */ + {NULL, NSM_Init}, /* 1-WayReceived */ + {nsm_kill_nbr, NSM_Deleted}, /* KillNbr */ + {nsm_kill_nbr, NSM_Deleted}, /* InactivityTimer */ + {nsm_kill_nbr, NSM_Deleted}, /* LLDown */ + }, + { + /* Full: */ + {NULL, NSM_DependUpon}, /* NoEvent */ + {nsm_packet_received, NSM_Full}, /* PacketReceived */ + {NULL, NSM_Full}, /* Start */ + {NULL, NSM_Full}, /* 2-WayReceived */ + {NULL, NSM_Full}, /* NegotiationDone */ + {NULL, NSM_Full}, /* ExchangeDone */ + {NULL, NSM_ExStart}, /* BadLSReq */ + {NULL, NSM_Full}, /* LoadingDone */ + {nsm_adj_ok, NSM_DependUpon}, /* AdjOK? */ + {NULL, NSM_ExStart}, /* SeqNumberMismatch */ + {NULL, NSM_Init}, /* 1-WayReceived */ + {nsm_kill_nbr, NSM_Deleted}, /* KillNbr */ + {nsm_kill_nbr, NSM_Deleted}, /* InactivityTimer */ + {nsm_kill_nbr, NSM_Deleted}, /* LLDown */ + }, }; -static const char *ospf_nsm_event_str[] = -{ - "NoEvent", - "PacketReceived", - "Start", - "2-WayReceived", - "NegotiationDone", - "ExchangeDone", - "BadLSReq", - "LoadingDone", - "AdjOK?", - "SeqNumberMismatch", - "1-WayReceived", - "KillNbr", - "InactivityTimer", - "LLDown", +static const char *ospf_nsm_event_str[] = { + "NoEvent", "PacketReceived", "Start", + "2-WayReceived", "NegotiationDone", "ExchangeDone", + "BadLSReq", "LoadingDone", "AdjOK?", + "SeqNumberMismatch", "1-WayReceived", "KillNbr", + "InactivityTimer", "LLDown", }; -static void -nsm_notice_state_change (struct ospf_neighbor *nbr, int next_state, int event) +static void nsm_notice_state_change(struct ospf_neighbor *nbr, int next_state, + int event) { - /* Logging change of status. */ - if (IS_DEBUG_OSPF (nsm, NSM_STATUS)) - zlog_debug ("NSM[%s:%s]: State change %s -> %s (%s)", - IF_NAME (nbr->oi), inet_ntoa (nbr->router_id), - lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), - lookup_msg(ospf_nsm_state_msg, next_state, NULL), - ospf_nsm_event_str [event]); - - /* Optionally notify about adjacency changes */ - if (CHECK_FLAG(nbr->oi->ospf->config, OSPF_LOG_ADJACENCY_CHANGES) && - (CHECK_FLAG(nbr->oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL) || - (next_state == NSM_Full) || (next_state < nbr->state))) - zlog_notice("AdjChg: Nbr %s on %s: %s -> %s (%s)", - inet_ntoa (nbr->router_id), IF_NAME (nbr->oi), - lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), - lookup_msg(ospf_nsm_state_msg, next_state, NULL), - ospf_nsm_event_str [event]); - - /* Advance in NSM */ - if (next_state > nbr->state) - monotime(&nbr->ts_last_progress); - else /* regression in NSM */ - { - monotime(&nbr->ts_last_regress); - nbr->last_regress_str = ospf_nsm_event_str [event]; - } - + /* Logging change of status. */ + if (IS_DEBUG_OSPF(nsm, NSM_STATUS)) + zlog_debug("NSM[%s:%s]: State change %s -> %s (%s)", + IF_NAME(nbr->oi), inet_ntoa(nbr->router_id), + lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), + lookup_msg(ospf_nsm_state_msg, next_state, NULL), + ospf_nsm_event_str[event]); + + /* Optionally notify about adjacency changes */ + if (CHECK_FLAG(nbr->oi->ospf->config, OSPF_LOG_ADJACENCY_CHANGES) + && (CHECK_FLAG(nbr->oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL) + || (next_state == NSM_Full) || (next_state < nbr->state))) + zlog_notice("AdjChg: Nbr %s on %s: %s -> %s (%s)", + inet_ntoa(nbr->router_id), IF_NAME(nbr->oi), + lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), + lookup_msg(ospf_nsm_state_msg, next_state, NULL), + ospf_nsm_event_str[event]); + + /* Advance in NSM */ + if (next_state > nbr->state) + monotime(&nbr->ts_last_progress); + else /* regression in NSM */ + { + monotime(&nbr->ts_last_regress); + nbr->last_regress_str = ospf_nsm_event_str[event]; + } } -static void -nsm_change_state (struct ospf_neighbor *nbr, int state) +static void nsm_change_state(struct ospf_neighbor *nbr, int state) { - struct ospf_interface *oi = nbr->oi; - struct ospf_area *vl_area = NULL; - u_char old_state; - int x; - int force = 1; - - /* Preserve old status. */ - old_state = nbr->state; - - /* Change to new status. */ - nbr->state = state; - - /* Statistics. */ - nbr->state_change++; - - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - vl_area = ospf_area_lookup_by_area_id (oi->ospf, oi->vl_data->vl_area_id); - - /* Generate NeighborChange ISM event. - * - * In response to NeighborChange, DR election is rerun. The information - * from the election process is required by the router-lsa construction. - * - * Therefore, trigger the event prior to refreshing the LSAs. */ - switch (oi->state) { - case ISM_DROther: - case ISM_Backup: - case ISM_DR: - if ((old_state < NSM_TwoWay && state >= NSM_TwoWay) || - (old_state >= NSM_TwoWay && state < NSM_TwoWay)) - OSPF_ISM_EVENT_EXECUTE (oi, ISM_NeighborChange); - break; - default: - /* ISM_PointToPoint -> ISM_Down, ISM_Loopback -> ISM_Down, etc. */ - break; - } - - /* One of the neighboring routers changes to/from the FULL state. */ - if ((old_state != NSM_Full && state == NSM_Full) || - (old_state == NSM_Full && state != NSM_Full)) - { - if (state == NSM_Full) - { - oi->full_nbrs++; - oi->area->full_nbrs++; - - ospf_check_abr_status (oi->ospf); - - if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area) - if (++vl_area->full_vls == 1) - ospf_schedule_abr_task (oi->ospf); - - /* kevinm: refresh any redistributions */ - for (x = ZEBRA_ROUTE_SYSTEM; x < ZEBRA_ROUTE_MAX; x++) - { - struct list *red_list; - struct listnode *node; - struct ospf_redist *red; - - if (x == ZEBRA_ROUTE_OSPF6) - continue; - - red_list = oi->ospf->redist[x]; - if (!red_list) - continue; - - for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) - ospf_external_lsa_refresh_type (oi->ospf, x, red->instance, force); - } - /* XXX: Clearly some thing is wrong with refresh of external LSAs - * this added to hack around defaults not refreshing after a timer - * jump. - */ - ospf_external_lsa_refresh_default (oi->ospf); + struct ospf_interface *oi = nbr->oi; + struct ospf_area *vl_area = NULL; + u_char old_state; + int x; + int force = 1; + + /* Preserve old status. */ + old_state = nbr->state; + + /* Change to new status. */ + nbr->state = state; + + /* Statistics. */ + nbr->state_change++; + + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + vl_area = ospf_area_lookup_by_area_id(oi->ospf, + oi->vl_data->vl_area_id); + + /* Generate NeighborChange ISM event. + * + * In response to NeighborChange, DR election is rerun. The information + * from the election process is required by the router-lsa construction. + * + * Therefore, trigger the event prior to refreshing the LSAs. */ + switch (oi->state) { + case ISM_DROther: + case ISM_Backup: + case ISM_DR: + if ((old_state < NSM_TwoWay && state >= NSM_TwoWay) + || (old_state >= NSM_TwoWay && state < NSM_TwoWay)) + OSPF_ISM_EVENT_EXECUTE(oi, ISM_NeighborChange); + break; + default: + /* ISM_PointToPoint -> ISM_Down, ISM_Loopback -> ISM_Down, etc. + */ + break; } - else - { - oi->full_nbrs--; - oi->area->full_nbrs--; - ospf_check_abr_status (oi->ospf); + /* One of the neighboring routers changes to/from the FULL state. */ + if ((old_state != NSM_Full && state == NSM_Full) + || (old_state == NSM_Full && state != NSM_Full)) { + if (state == NSM_Full) { + oi->full_nbrs++; + oi->area->full_nbrs++; + + ospf_check_abr_status(oi->ospf); + + if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area) + if (++vl_area->full_vls == 1) + ospf_schedule_abr_task(oi->ospf); + + /* kevinm: refresh any redistributions */ + for (x = ZEBRA_ROUTE_SYSTEM; x < ZEBRA_ROUTE_MAX; x++) { + struct list *red_list; + struct listnode *node; + struct ospf_redist *red; + + if (x == ZEBRA_ROUTE_OSPF6) + continue; + + red_list = oi->ospf->redist[x]; + if (!red_list) + continue; + + for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) + ospf_external_lsa_refresh_type( + oi->ospf, x, red->instance, + force); + } + /* XXX: Clearly some thing is wrong with refresh of + * external LSAs + * this added to hack around defaults not refreshing + * after a timer + * jump. + */ + ospf_external_lsa_refresh_default(oi->ospf); + } else { + oi->full_nbrs--; + oi->area->full_nbrs--; + + ospf_check_abr_status(oi->ospf); + + if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area) + if (vl_area->full_vls > 0) + if (--vl_area->full_vls == 0) + ospf_schedule_abr_task( + oi->ospf); + } + + zlog_info( + "nsm_change_state(%s, %s -> %s): " + "scheduling new router-LSA origination", + inet_ntoa(nbr->router_id), + lookup_msg(ospf_nsm_state_msg, old_state, NULL), + lookup_msg(ospf_nsm_state_msg, state, NULL)); + + ospf_router_lsa_update_area(oi->area); + + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) { + struct ospf_area *vl_area = ospf_area_lookup_by_area_id( + oi->ospf, oi->vl_data->vl_area_id); + + if (vl_area) + ospf_router_lsa_update_area(vl_area); + } + + /* Originate network-LSA. */ + if (oi->state == ISM_DR) { + if (oi->network_lsa_self && oi->full_nbrs == 0) { + ospf_lsa_flush_area(oi->network_lsa_self, + oi->area); + ospf_lsa_unlock(&oi->network_lsa_self); + oi->network_lsa_self = NULL; + } else + ospf_network_lsa_update(oi); + } + } - if (oi->type == OSPF_IFTYPE_VIRTUALLINK && vl_area) - if (vl_area->full_vls > 0) - if (--vl_area->full_vls == 0) - ospf_schedule_abr_task (oi->ospf); + ospf_opaque_nsm_change(nbr, old_state); + + /* State changes from > ExStart to <= ExStart should clear any Exchange + * or Full/LSA Update related lists and state. + * Potential causal events: BadLSReq, SeqNumberMismatch, AdjOK? + */ + if ((old_state > NSM_ExStart) && (state <= NSM_ExStart)) + nsm_clear_adj(nbr); + + /* Start DD exchange protocol */ + if (state == NSM_ExStart) { + if (nbr->dd_seqnum == 0) + nbr->dd_seqnum = (uint32_t)random(); + else + nbr->dd_seqnum++; + + nbr->dd_flags = + OSPF_DD_FLAG_I | OSPF_DD_FLAG_M | OSPF_DD_FLAG_MS; + ospf_db_desc_send(nbr); } - zlog_info ("nsm_change_state(%s, %s -> %s): " - "scheduling new router-LSA origination", - inet_ntoa (nbr->router_id), - lookup_msg(ospf_nsm_state_msg, old_state, NULL), - lookup_msg(ospf_nsm_state_msg, state, NULL)); + /* clear cryptographic sequence number */ + if (state == NSM_Down) + nbr->crypt_seqnum = 0; - ospf_router_lsa_update_area (oi->area); + ospf_bfd_trigger_event(nbr, old_state, state); - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - { - struct ospf_area *vl_area = - ospf_area_lookup_by_area_id (oi->ospf, oi->vl_data->vl_area_id); - - if (vl_area) - ospf_router_lsa_update_area (vl_area); - } - - /* Originate network-LSA. */ - if (oi->state == ISM_DR) - { - if (oi->network_lsa_self && oi->full_nbrs == 0) - { - ospf_lsa_flush_area (oi->network_lsa_self, oi->area); - ospf_lsa_unlock (&oi->network_lsa_self); - oi->network_lsa_self = NULL; - } - else - ospf_network_lsa_update (oi); - } - } - - ospf_opaque_nsm_change (nbr, old_state); - - /* State changes from > ExStart to <= ExStart should clear any Exchange - * or Full/LSA Update related lists and state. - * Potential causal events: BadLSReq, SeqNumberMismatch, AdjOK? - */ - if ((old_state > NSM_ExStart) && (state <= NSM_ExStart)) - nsm_clear_adj (nbr); - - /* Start DD exchange protocol */ - if (state == NSM_ExStart) - { - if (nbr->dd_seqnum == 0) - nbr->dd_seqnum = (uint32_t)random (); - else - nbr->dd_seqnum++; - - nbr->dd_flags = OSPF_DD_FLAG_I|OSPF_DD_FLAG_M|OSPF_DD_FLAG_MS; - ospf_db_desc_send (nbr); - } - - /* clear cryptographic sequence number */ - if (state == NSM_Down) - nbr->crypt_seqnum = 0; - - ospf_bfd_trigger_event(nbr, old_state, state); - - /* Preserve old status? */ + /* Preserve old status? */ } /* Execute NSM event process. */ -int -ospf_nsm_event (struct thread *thread) +int ospf_nsm_event(struct thread *thread) { - int event; - int next_state; - struct ospf_neighbor *nbr; - - nbr = THREAD_ARG (thread); - event = THREAD_VAL (thread); - - if (IS_DEBUG_OSPF (nsm, NSM_EVENTS)) - zlog_debug ("NSM[%s:%s]: %s (%s)", IF_NAME (nbr->oi), - inet_ntoa (nbr->router_id), - lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), - ospf_nsm_event_str [event]); - - next_state = NSM [nbr->state][event].next_state; - - /* Call function. */ - if (NSM [nbr->state][event].func != NULL) - { - int func_state = (*(NSM [nbr->state][event].func))(nbr); - - if (NSM [nbr->state][event].next_state == NSM_DependUpon) - next_state = func_state; - else if (func_state) - { - /* There's a mismatch between the FSM tables and what an FSM - * action/state-change function returned. State changes which - * do not have conditional/DependUpon next-states should not - * try set next_state. - */ - zlog_warn ("NSM[%s:%s]: %s (%s): " - "Warning: action tried to change next_state to %s", - IF_NAME (nbr->oi), inet_ntoa (nbr->router_id), - lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), - ospf_nsm_event_str [event], - lookup_msg(ospf_nsm_state_msg, func_state, NULL)); - } - } - - assert (next_state != NSM_DependUpon); - - /* If state is changed. */ - if (next_state != nbr->state) - { - int old_state = nbr->state; - - nsm_notice_state_change (nbr, next_state, event); - nsm_change_state (nbr, next_state); - - hook_call(ospf_nsm_change, nbr, next_state, old_state); - } - - /* Make sure timer is set. */ - nsm_timer_set (nbr); - - /* When event is NSM_KillNbr, InactivityTimer or LLDown, the neighbor - * is deleted. - * - * Rather than encode knowledge here of which events lead to NBR - * delete, we take our cue from the NSM table, via the dummy - * 'Deleted' neighbour state. - */ - if (nbr->state == NSM_Deleted) - ospf_nbr_delete (nbr); - - return 0; + int event; + int next_state; + struct ospf_neighbor *nbr; + + nbr = THREAD_ARG(thread); + event = THREAD_VAL(thread); + + if (IS_DEBUG_OSPF(nsm, NSM_EVENTS)) + zlog_debug("NSM[%s:%s]: %s (%s)", IF_NAME(nbr->oi), + inet_ntoa(nbr->router_id), + lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), + ospf_nsm_event_str[event]); + + next_state = NSM[nbr->state][event].next_state; + + /* Call function. */ + if (NSM[nbr->state][event].func != NULL) { + int func_state = (*(NSM[nbr->state][event].func))(nbr); + + if (NSM[nbr->state][event].next_state == NSM_DependUpon) + next_state = func_state; + else if (func_state) { + /* There's a mismatch between the FSM tables and what an + * FSM + * action/state-change function returned. State changes + * which + * do not have conditional/DependUpon next-states should + * not + * try set next_state. + */ + zlog_warn( + "NSM[%s:%s]: %s (%s): " + "Warning: action tried to change next_state to %s", + IF_NAME(nbr->oi), inet_ntoa(nbr->router_id), + lookup_msg(ospf_nsm_state_msg, nbr->state, + NULL), + ospf_nsm_event_str[event], + lookup_msg(ospf_nsm_state_msg, func_state, + NULL)); + } + } + + assert(next_state != NSM_DependUpon); + + /* If state is changed. */ + if (next_state != nbr->state) { + int old_state = nbr->state; + + nsm_notice_state_change(nbr, next_state, event); + nsm_change_state(nbr, next_state); + + hook_call(ospf_nsm_change, nbr, next_state, old_state); + } + + /* Make sure timer is set. */ + nsm_timer_set(nbr); + + /* When event is NSM_KillNbr, InactivityTimer or LLDown, the neighbor + * is deleted. + * + * Rather than encode knowledge here of which events lead to NBR + * delete, we take our cue from the NSM table, via the dummy + * 'Deleted' neighbour state. + */ + if (nbr->state == NSM_Deleted) + ospf_nbr_delete(nbr); + + return 0; } /* Check loading state. */ -void -ospf_check_nbr_loading (struct ospf_neighbor *nbr) +void ospf_check_nbr_loading(struct ospf_neighbor *nbr) { - if (nbr->state == NSM_Loading) - { - if (ospf_ls_request_isempty (nbr)) - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_LoadingDone); - else if (nbr->ls_req_last == NULL) - ospf_ls_req_event (nbr); - } + if (nbr->state == NSM_Loading) { + if (ospf_ls_request_isempty(nbr)) + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_LoadingDone); + else if (nbr->ls_req_last == NULL) + ospf_ls_req_event(nbr); + } } diff --git a/ospfd/ospf_nsm.h b/ospfd/ospf_nsm.h index 4f363b4e6..dcfba84d8 100644 --- a/ospfd/ospf_nsm.h +++ b/ospfd/ospf_nsm.h @@ -59,33 +59,31 @@ #define OSPF_NSM_TIMER_ON(T,F,V) thread_add_timer (master, (F), nbr, (V), &(T)) /* Macro for OSPF NSM timer turn off. */ -#define OSPF_NSM_TIMER_OFF(X) \ - do { \ - if (X) \ - { \ - thread_cancel (X); \ - (X) = NULL; \ - } \ - } while (0) +#define OSPF_NSM_TIMER_OFF(X) \ + do { \ + if (X) { \ + thread_cancel(X); \ + (X) = NULL; \ + } \ + } while (0) /* Macro for OSPF NSM schedule event. */ -#define OSPF_NSM_EVENT_SCHEDULE(N,E) \ - thread_add_event (master, ospf_nsm_event, (N), (E), NULL) +#define OSPF_NSM_EVENT_SCHEDULE(N, E) \ + thread_add_event(master, ospf_nsm_event, (N), (E), NULL) /* Macro for OSPF NSM execute event. */ -#define OSPF_NSM_EVENT_EXECUTE(N,E) \ - thread_execute (master, ospf_nsm_event, (N), (E)) +#define OSPF_NSM_EVENT_EXECUTE(N, E) \ + thread_execute(master, ospf_nsm_event, (N), (E)) /* Prototypes. */ -extern int ospf_nsm_event (struct thread *); -extern void ospf_check_nbr_loading (struct ospf_neighbor *); -extern int ospf_db_summary_isempty (struct ospf_neighbor *); -extern int ospf_db_summary_count (struct ospf_neighbor *); -extern void ospf_db_summary_clear (struct ospf_neighbor *); +extern int ospf_nsm_event(struct thread *); +extern void ospf_check_nbr_loading(struct ospf_neighbor *); +extern int ospf_db_summary_isempty(struct ospf_neighbor *); +extern int ospf_db_summary_count(struct ospf_neighbor *); +extern void ospf_db_summary_clear(struct ospf_neighbor *); DECLARE_HOOK(ospf_nsm_change, - (struct ospf_neighbor *on, int state, int oldstate), - (on, state, oldstate)) + (struct ospf_neighbor * on, int state, int oldstate), + (on, state, oldstate)) #endif /* _ZEBRA_OSPF_NSM_H */ - diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index f3db6afd1..a2c40923b 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -33,7 +33,7 @@ #include "log.h" #include "thread.h" #include "hash.h" -#include "sockunion.h" /* for inet_aton() */ +#include "sockunion.h" /* for inet_aton() */ #include "ospfd/ospfd.h" #include "ospfd/ospf_interface.h" @@ -51,9 +51,9 @@ #include "ospfd/ospf_ase.h" #include "ospfd/ospf_zebra.h" -DEFINE_MTYPE_STATIC(OSPFD, OSPF_OPAQUE_FUNCTAB, "OSPF opaque function table") +DEFINE_MTYPE_STATIC(OSPFD, OSPF_OPAQUE_FUNCTAB, "OSPF opaque function table") DEFINE_MTYPE_STATIC(OSPFD, OPAQUE_INFO_PER_TYPE, "OSPF opaque per-type info") -DEFINE_MTYPE_STATIC(OSPFD, OPAQUE_INFO_PER_ID, "OSPF opaque per-ID info") +DEFINE_MTYPE_STATIC(OSPFD, OPAQUE_INFO_PER_ID, "OSPF opaque per-ID info") /*------------------------------------------------------------------------* * Followings are initialize/terminate functions for Opaque-LSAs handling. @@ -63,181 +63,169 @@ DEFINE_MTYPE_STATIC(OSPFD, OPAQUE_INFO_PER_ID, "OSPF opaque per-ID info") #include "ospfd/ospf_ri.h" #ifdef SUPPORT_OSPF_API -int ospf_apiserver_init (void); -void ospf_apiserver_term (void); +int ospf_apiserver_init(void); +void ospf_apiserver_term(void); /* Init apiserver? It's disabled by default. */ int ospf_apiserver_enable; #endif /* SUPPORT_OSPF_API */ -static void ospf_opaque_register_vty (void); -static void ospf_opaque_funclist_init (void); -static void ospf_opaque_funclist_term (void); -static void free_opaque_info_per_type (void *val); -static void free_opaque_info_per_id (void *val); -static int ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa); -static int ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa); +static void ospf_opaque_register_vty(void); +static void ospf_opaque_funclist_init(void); +static void ospf_opaque_funclist_term(void); +static void free_opaque_info_per_type(void *val); +static void free_opaque_info_per_id(void *val); +static int ospf_opaque_lsa_install_hook(struct ospf_lsa *lsa); +static int ospf_opaque_lsa_delete_hook(struct ospf_lsa *lsa); -void -ospf_opaque_init (void) +void ospf_opaque_init(void) { - ospf_opaque_register_vty (); - ospf_opaque_funclist_init (); + ospf_opaque_register_vty(); + ospf_opaque_funclist_init(); - if (ospf_mpls_te_init () != 0) - exit (1); + if (ospf_mpls_te_init() != 0) + exit(1); - if (ospf_router_info_init () != 0) - exit (1); + if (ospf_router_info_init() != 0) + exit(1); #ifdef SUPPORT_OSPF_API - if ((ospf_apiserver_enable) && (ospf_apiserver_init () != 0)) - exit (1); + if ((ospf_apiserver_enable) && (ospf_apiserver_init() != 0)) + exit(1); #endif /* SUPPORT_OSPF_API */ - return; + return; } -void -ospf_opaque_term (void) +void ospf_opaque_term(void) { - ospf_mpls_te_term (); + ospf_mpls_te_term(); - ospf_router_info_term (); + ospf_router_info_term(); #ifdef SUPPORT_OSPF_API - ospf_apiserver_term (); + ospf_apiserver_term(); #endif /* SUPPORT_OSPF_API */ - ospf_opaque_funclist_term (); - return; + ospf_opaque_funclist_term(); + return; } -int -ospf_opaque_type9_lsa_init (struct ospf_interface *oi) +int ospf_opaque_type9_lsa_init(struct ospf_interface *oi) { - if (oi->opaque_lsa_self != NULL) - list_delete (oi->opaque_lsa_self); + if (oi->opaque_lsa_self != NULL) + list_delete(oi->opaque_lsa_self); - oi->opaque_lsa_self = list_new (); - oi->opaque_lsa_self->del = free_opaque_info_per_type; - oi->t_opaque_lsa_self = NULL; - return 0; + oi->opaque_lsa_self = list_new(); + oi->opaque_lsa_self->del = free_opaque_info_per_type; + oi->t_opaque_lsa_self = NULL; + return 0; } -void -ospf_opaque_type9_lsa_term (struct ospf_interface *oi) +void ospf_opaque_type9_lsa_term(struct ospf_interface *oi) { - OSPF_TIMER_OFF (oi->t_opaque_lsa_self); - if (oi->opaque_lsa_self != NULL) - list_delete (oi->opaque_lsa_self); - oi->opaque_lsa_self = NULL; - return; + OSPF_TIMER_OFF(oi->t_opaque_lsa_self); + if (oi->opaque_lsa_self != NULL) + list_delete(oi->opaque_lsa_self); + oi->opaque_lsa_self = NULL; + return; } -int -ospf_opaque_type10_lsa_init (struct ospf_area *area) +int ospf_opaque_type10_lsa_init(struct ospf_area *area) { - if (area->opaque_lsa_self != NULL) - list_delete (area->opaque_lsa_self); + if (area->opaque_lsa_self != NULL) + list_delete(area->opaque_lsa_self); - area->opaque_lsa_self = list_new (); - area->opaque_lsa_self->del = free_opaque_info_per_type; - area->t_opaque_lsa_self = NULL; + area->opaque_lsa_self = list_new(); + area->opaque_lsa_self->del = free_opaque_info_per_type; + area->t_opaque_lsa_self = NULL; #ifdef MONITOR_LSDB_CHANGE - area->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook; - area->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook; + area->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook; + area->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook; #endif /* MONITOR_LSDB_CHANGE */ - return 0; + return 0; } -void -ospf_opaque_type10_lsa_term (struct ospf_area *area) +void ospf_opaque_type10_lsa_term(struct ospf_area *area) { #ifdef MONITOR_LSDB_CHANGE - area->lsdb->new_lsa_hook = - area->lsdb->del_lsa_hook = NULL; + area->lsdb->new_lsa_hook = area->lsdb->del_lsa_hook = NULL; #endif /* MONITOR_LSDB_CHANGE */ - OSPF_TIMER_OFF (area->t_opaque_lsa_self); - if (area->opaque_lsa_self != NULL) - list_delete (area->opaque_lsa_self); - area->opaque_lsa_self = NULL; - return; + OSPF_TIMER_OFF(area->t_opaque_lsa_self); + if (area->opaque_lsa_self != NULL) + list_delete(area->opaque_lsa_self); + area->opaque_lsa_self = NULL; + return; } -int -ospf_opaque_type11_lsa_init (struct ospf *top) +int ospf_opaque_type11_lsa_init(struct ospf *top) { - if (top->opaque_lsa_self != NULL) - list_delete (top->opaque_lsa_self); + if (top->opaque_lsa_self != NULL) + list_delete(top->opaque_lsa_self); - top->opaque_lsa_self = list_new (); - top->opaque_lsa_self->del = free_opaque_info_per_type; - top->t_opaque_lsa_self = NULL; + top->opaque_lsa_self = list_new(); + top->opaque_lsa_self->del = free_opaque_info_per_type; + top->t_opaque_lsa_self = NULL; #ifdef MONITOR_LSDB_CHANGE - top->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook; - top->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook; + top->lsdb->new_lsa_hook = ospf_opaque_lsa_install_hook; + top->lsdb->del_lsa_hook = ospf_opaque_lsa_delete_hook; #endif /* MONITOR_LSDB_CHANGE */ - return 0; + return 0; } -void -ospf_opaque_type11_lsa_term (struct ospf *top) +void ospf_opaque_type11_lsa_term(struct ospf *top) { #ifdef MONITOR_LSDB_CHANGE - top->lsdb->new_lsa_hook = - top->lsdb->del_lsa_hook = NULL; + top->lsdb->new_lsa_hook = top->lsdb->del_lsa_hook = NULL; #endif /* MONITOR_LSDB_CHANGE */ - OSPF_TIMER_OFF (top->t_opaque_lsa_self); - if (top->opaque_lsa_self != NULL) - list_delete (top->opaque_lsa_self); - top->opaque_lsa_self = NULL; - return; -} - -static const char * -ospf_opaque_type_name (u_char opaque_type) -{ - const char *name = "Unknown"; - - switch (opaque_type) - { - case OPAQUE_TYPE_WILDCARD: /* This is a special assignment! */ - name = "Wildcard"; - break; - case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA: - name = "Traffic Engineering LSA"; - break; - case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC: - name = "Sycamore optical topology description"; - break; - case OPAQUE_TYPE_GRACE_LSA: - name = "Grace-LSA"; - break; - case OPAQUE_TYPE_INTER_AS_LSA: - name = "Inter-AS TE-v2 LSA"; - break; - case OPAQUE_TYPE_ROUTER_INFORMATION_LSA: - name = "Router Information LSA"; - break; - default: - if (OPAQUE_TYPE_RANGE_UNASSIGNED (opaque_type)) - name = "Unassigned"; - else - { - u_int32_t bigger_range = opaque_type; - /* - * Get around type-limits warning: comparison is always true due to limited range of data type - */ - if (OPAQUE_TYPE_RANGE_RESERVED (bigger_range)) - name = "Private/Experimental"; - } - break; - } - return name; + OSPF_TIMER_OFF(top->t_opaque_lsa_self); + if (top->opaque_lsa_self != NULL) + list_delete(top->opaque_lsa_self); + top->opaque_lsa_self = NULL; + return; +} + +static const char *ospf_opaque_type_name(u_char opaque_type) +{ + const char *name = "Unknown"; + + switch (opaque_type) { + case OPAQUE_TYPE_WILDCARD: /* This is a special assignment! */ + name = "Wildcard"; + break; + case OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA: + name = "Traffic Engineering LSA"; + break; + case OPAQUE_TYPE_SYCAMORE_OPTICAL_TOPOLOGY_DESC: + name = "Sycamore optical topology description"; + break; + case OPAQUE_TYPE_GRACE_LSA: + name = "Grace-LSA"; + break; + case OPAQUE_TYPE_INTER_AS_LSA: + name = "Inter-AS TE-v2 LSA"; + break; + case OPAQUE_TYPE_ROUTER_INFORMATION_LSA: + name = "Router Information LSA"; + break; + default: + if (OPAQUE_TYPE_RANGE_UNASSIGNED(opaque_type)) + name = "Unassigned"; + else { + u_int32_t bigger_range = opaque_type; + /* + * Get around type-limits warning: comparison is always + * true due to limited range of data type + */ + if (OPAQUE_TYPE_RANGE_RESERVED(bigger_range)) + name = "Private/Experimental"; + } + break; + } + return name; } /*------------------------------------------------------------------------* @@ -246,23 +234,22 @@ ospf_opaque_type_name (u_char opaque_type) struct opaque_info_per_type; /* Forward declaration. */ -struct ospf_opaque_functab -{ - u_char opaque_type; - struct opaque_info_per_type *oipt; - - int (* new_if_hook)(struct interface *ifp); - int (* del_if_hook)(struct interface *ifp); - void (* ism_change_hook)(struct ospf_interface *oi, int old_status); - void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status); - void (* config_write_router)(struct vty *vty); - void (* config_write_if )(struct vty *vty, struct interface *ifp); - void (* config_write_debug )(struct vty *vty); - void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa); - int (* lsa_originator)(void *arg); - struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa); - int (* new_lsa_hook)(struct ospf_lsa *lsa); - int (* del_lsa_hook)(struct ospf_lsa *lsa); +struct ospf_opaque_functab { + u_char opaque_type; + struct opaque_info_per_type *oipt; + + int (*new_if_hook)(struct interface *ifp); + int (*del_if_hook)(struct interface *ifp); + void (*ism_change_hook)(struct ospf_interface *oi, int old_status); + void (*nsm_change_hook)(struct ospf_neighbor *nbr, int old_status); + void (*config_write_router)(struct vty *vty); + void (*config_write_if)(struct vty *vty, struct interface *ifp); + void (*config_write_debug)(struct vty *vty); + void (*show_opaque_info)(struct vty *vty, struct ospf_lsa *lsa); + int (*lsa_originator)(void *arg); + struct ospf_lsa *(*lsa_refresher)(struct ospf_lsa *lsa); + int (*new_lsa_hook)(struct ospf_lsa *lsa); + int (*del_lsa_hook)(struct ospf_lsa *lsa); }; /* Handle LSA-9/10/11 altogether. */ @@ -271,203 +258,195 @@ static struct list *ospf_opaque_type9_funclist; static struct list *ospf_opaque_type10_funclist; static struct list *ospf_opaque_type11_funclist; -static void -ospf_opaque_del_functab (void *val) +static void ospf_opaque_del_functab(void *val) { - XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, val); - return; + XFREE(MTYPE_OSPF_OPAQUE_FUNCTAB, val); + return; } -static void -ospf_opaque_funclist_init (void) +static void ospf_opaque_funclist_init(void) { - struct list *funclist; + struct list *funclist; - funclist = ospf_opaque_wildcard_funclist = list_new (); - funclist->del = ospf_opaque_del_functab; + funclist = ospf_opaque_wildcard_funclist = list_new(); + funclist->del = ospf_opaque_del_functab; - funclist = ospf_opaque_type9_funclist = list_new (); - funclist->del = ospf_opaque_del_functab; + funclist = ospf_opaque_type9_funclist = list_new(); + funclist->del = ospf_opaque_del_functab; - funclist = ospf_opaque_type10_funclist = list_new (); - funclist->del = ospf_opaque_del_functab; + funclist = ospf_opaque_type10_funclist = list_new(); + funclist->del = ospf_opaque_del_functab; - funclist = ospf_opaque_type11_funclist = list_new (); - funclist->del = ospf_opaque_del_functab; - return; + funclist = ospf_opaque_type11_funclist = list_new(); + funclist->del = ospf_opaque_del_functab; + return; } -static void -ospf_opaque_funclist_term (void) +static void ospf_opaque_funclist_term(void) { - struct list *funclist; + struct list *funclist; - funclist = ospf_opaque_wildcard_funclist; - list_delete (funclist); + funclist = ospf_opaque_wildcard_funclist; + list_delete(funclist); - funclist = ospf_opaque_type9_funclist; - list_delete (funclist); + funclist = ospf_opaque_type9_funclist; + list_delete(funclist); - funclist = ospf_opaque_type10_funclist; - list_delete (funclist); + funclist = ospf_opaque_type10_funclist; + list_delete(funclist); - funclist = ospf_opaque_type11_funclist; - list_delete (funclist); - return; + funclist = ospf_opaque_type11_funclist; + list_delete(funclist); + return; } -static struct list * -ospf_get_opaque_funclist (u_char lsa_type) +static struct list *ospf_get_opaque_funclist(u_char lsa_type) { - struct list *funclist = NULL; + struct list *funclist = NULL; - switch (lsa_type) - { - case OPAQUE_TYPE_WILDCARD: - /* XXX - * This is an ugly trick to handle type-9/10/11 LSA altogether. - * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor - * an officially assigned opaque-type. - * Though it is possible that the value might be officially used - * in the future, we use it internally as a special label, for now. - */ - funclist = ospf_opaque_wildcard_funclist; - break; - case OSPF_OPAQUE_LINK_LSA: - funclist = ospf_opaque_type9_funclist; - break; - case OSPF_OPAQUE_AREA_LSA: - funclist = ospf_opaque_type10_funclist; - break; - case OSPF_OPAQUE_AS_LSA: - funclist = ospf_opaque_type11_funclist; - break; - default: - zlog_warn ("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", lsa_type); - break; - } - return funclist; + switch (lsa_type) { + case OPAQUE_TYPE_WILDCARD: + /* XXX + * This is an ugly trick to handle type-9/10/11 LSA altogether. + * Yes, "OPAQUE_TYPE_WILDCARD (value 0)" is not an LSA-type, nor + * an officially assigned opaque-type. + * Though it is possible that the value might be officially used + * in the future, we use it internally as a special label, for + * now. + */ + funclist = ospf_opaque_wildcard_funclist; + break; + case OSPF_OPAQUE_LINK_LSA: + funclist = ospf_opaque_type9_funclist; + break; + case OSPF_OPAQUE_AREA_LSA: + funclist = ospf_opaque_type10_funclist; + break; + case OSPF_OPAQUE_AS_LSA: + funclist = ospf_opaque_type11_funclist; + break; + default: + zlog_warn("ospf_get_opaque_funclist: Unexpected LSA-type(%u)", + lsa_type); + break; + } + return funclist; } /* XXX: such a huge argument list can /not/ be healthy... */ -int -ospf_register_opaque_functab ( - u_char lsa_type, - u_char opaque_type, - int (* new_if_hook)(struct interface *ifp), - int (* del_if_hook)(struct interface *ifp), - void (* ism_change_hook)(struct ospf_interface *oi, int old_status), - void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status), - void (* config_write_router)(struct vty *vty), - void (* config_write_if )(struct vty *vty, struct interface *ifp), - void (* config_write_debug )(struct vty *vty), - void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa), - int (* lsa_originator)(void *arg), - struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa), - int (* new_lsa_hook)(struct ospf_lsa *lsa), - int (* del_lsa_hook)(struct ospf_lsa *lsa)) -{ - struct list *funclist; - struct ospf_opaque_functab *new; - int rc = -1; - - if ((funclist = ospf_get_opaque_funclist (lsa_type)) == NULL) - { - zlog_warn ("ospf_register_opaque_functab: Cannot get funclist" - " for Type-%u LSAs?", - lsa_type); - goto out; - } - else - { - struct listnode *node, *nnode; - struct ospf_opaque_functab *functab; - - for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab)) - if (functab->opaque_type == opaque_type) - { - zlog_warn ("ospf_register_opaque_functab: Duplicated entry?:" - " lsa_type(%u), opaque_type(%u)", - lsa_type, opaque_type); - goto out; - } - } - - if ((new = XCALLOC (MTYPE_OSPF_OPAQUE_FUNCTAB, - sizeof (struct ospf_opaque_functab))) == NULL) - { - zlog_warn ("ospf_register_opaque_functab: XMALLOC: %s", - safe_strerror (errno)); - goto out; - } - - new->opaque_type = opaque_type; - new->oipt = NULL; - new->new_if_hook = new_if_hook; - new->del_if_hook = del_if_hook; - new->ism_change_hook = ism_change_hook; - new->nsm_change_hook = nsm_change_hook; - new->config_write_router = config_write_router; - new->config_write_if = config_write_if; - new->config_write_debug = config_write_debug; - new->show_opaque_info = show_opaque_info; - new->lsa_originator = lsa_originator; - new->lsa_refresher = lsa_refresher; - new->new_lsa_hook = new_lsa_hook; - new->del_lsa_hook = del_lsa_hook; - - listnode_add (funclist, new); - rc = 0; +int ospf_register_opaque_functab( + u_char lsa_type, u_char opaque_type, + int (*new_if_hook)(struct interface *ifp), + int (*del_if_hook)(struct interface *ifp), + void (*ism_change_hook)(struct ospf_interface *oi, int old_status), + void (*nsm_change_hook)(struct ospf_neighbor *nbr, int old_status), + void (*config_write_router)(struct vty *vty), + void (*config_write_if)(struct vty *vty, struct interface *ifp), + void (*config_write_debug)(struct vty *vty), + void (*show_opaque_info)(struct vty *vty, struct ospf_lsa *lsa), + int (*lsa_originator)(void *arg), + struct ospf_lsa *(*lsa_refresher)(struct ospf_lsa *lsa), + int (*new_lsa_hook)(struct ospf_lsa *lsa), + int (*del_lsa_hook)(struct ospf_lsa *lsa)) +{ + struct list *funclist; + struct ospf_opaque_functab *new; + int rc = -1; + + if ((funclist = ospf_get_opaque_funclist(lsa_type)) == NULL) { + zlog_warn( + "ospf_register_opaque_functab: Cannot get funclist" + " for Type-%u LSAs?", + lsa_type); + goto out; + } else { + struct listnode *node, *nnode; + struct ospf_opaque_functab *functab; + + for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab)) + if (functab->opaque_type == opaque_type) { + zlog_warn( + "ospf_register_opaque_functab: Duplicated entry?:" + " lsa_type(%u), opaque_type(%u)", + lsa_type, opaque_type); + goto out; + } + } + + if ((new = XCALLOC(MTYPE_OSPF_OPAQUE_FUNCTAB, + sizeof(struct ospf_opaque_functab))) + == NULL) { + zlog_warn("ospf_register_opaque_functab: XMALLOC: %s", + safe_strerror(errno)); + goto out; + } + + new->opaque_type = opaque_type; + new->oipt = NULL; + new->new_if_hook = new_if_hook; + new->del_if_hook = del_if_hook; + new->ism_change_hook = ism_change_hook; + new->nsm_change_hook = nsm_change_hook; + new->config_write_router = config_write_router; + new->config_write_if = config_write_if; + new->config_write_debug = config_write_debug; + new->show_opaque_info = show_opaque_info; + new->lsa_originator = lsa_originator; + new->lsa_refresher = lsa_refresher; + new->new_lsa_hook = new_lsa_hook; + new->del_lsa_hook = del_lsa_hook; + + listnode_add(funclist, new); + rc = 0; out: - return rc; + return rc; } -void -ospf_delete_opaque_functab (u_char lsa_type, u_char opaque_type) +void ospf_delete_opaque_functab(u_char lsa_type, u_char opaque_type) { - struct list *funclist; - struct listnode *node, *nnode; - struct ospf_opaque_functab *functab; + struct list *funclist; + struct listnode *node, *nnode; + struct ospf_opaque_functab *functab; - if ((funclist = ospf_get_opaque_funclist (lsa_type)) != NULL) - for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab)) - { - if (functab->opaque_type == opaque_type) - { - /* Cleanup internal control information, if it still remains. */ - if (functab->oipt != NULL) - free_opaque_info_per_type (functab->oipt); + if ((funclist = ospf_get_opaque_funclist(lsa_type)) != NULL) + for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab)) { + if (functab->opaque_type == opaque_type) { + /* Cleanup internal control information, if it + * still remains. */ + if (functab->oipt != NULL) + free_opaque_info_per_type( + functab->oipt); - /* Dequeue listnode entry from the list. */ - listnode_delete (funclist, functab); + /* Dequeue listnode entry from the list. */ + listnode_delete(funclist, functab); - /* Avoid misjudgement in the next lookup. */ - if (listcount (funclist) == 0) - funclist->head = funclist->tail = NULL; + /* Avoid misjudgement in the next lookup. */ + if (listcount(funclist) == 0) + funclist->head = funclist->tail = NULL; - XFREE (MTYPE_OSPF_OPAQUE_FUNCTAB, functab); - break; - } - } + XFREE(MTYPE_OSPF_OPAQUE_FUNCTAB, functab); + break; + } + } - return; + return; } static struct ospf_opaque_functab * -ospf_opaque_functab_lookup (struct ospf_lsa *lsa) +ospf_opaque_functab_lookup(struct ospf_lsa *lsa) { - struct list *funclist; - struct listnode *node; - struct ospf_opaque_functab *functab; - u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)); + struct list *funclist; + struct listnode *node; + struct ospf_opaque_functab *functab; + u_char key = GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)); - if ((funclist = ospf_get_opaque_funclist (lsa->data->type)) != NULL) - for (ALL_LIST_ELEMENTS_RO (funclist, node, functab)) - if (functab->opaque_type == key) - return functab; + if ((funclist = ospf_get_opaque_funclist(lsa->data->type)) != NULL) + for (ALL_LIST_ELEMENTS_RO(funclist, node, functab)) + if (functab->opaque_type == key) + return functab; - return NULL; + return NULL; } /*------------------------------------------------------------------------* @@ -479,283 +458,286 @@ ospf_opaque_functab_lookup (struct ospf_lsa *lsa) * Single Opaque-Type may have multiple instances; each of them will be * identified by their opaque-id. */ -struct opaque_info_per_type -{ - u_char lsa_type; - u_char opaque_type; - - enum { PROC_NORMAL, PROC_SUSPEND } status; - - /* - * Thread for (re-)origination scheduling for this opaque-type. - * - * Initial origination of Opaque-LSAs is controlled by generic - * Opaque-LSA handling module so that same opaque-type entries are - * called all at once when certain conditions are met. - * However, there might be cases that some Opaque-LSA clients need - * to (re-)originate their own Opaque-LSAs out-of-sync with others. - * This thread is prepared for that specific purpose. - */ - struct thread *t_opaque_lsa_self; - - /* - * Backpointer to an "owner" which is LSA-type dependent. - * type-9: struct ospf_interface - * type-10: struct ospf_area - * type-11: struct ospf - */ - void *owner; - - /* Collection of callback functions for this opaque-type. */ - struct ospf_opaque_functab *functab; - - /* List of Opaque-LSA control informations per opaque-id. */ - struct list *id_list; +struct opaque_info_per_type { + u_char lsa_type; + u_char opaque_type; + + enum { PROC_NORMAL, PROC_SUSPEND } status; + + /* + * Thread for (re-)origination scheduling for this opaque-type. + * + * Initial origination of Opaque-LSAs is controlled by generic + * Opaque-LSA handling module so that same opaque-type entries are + * called all at once when certain conditions are met. + * However, there might be cases that some Opaque-LSA clients need + * to (re-)originate their own Opaque-LSAs out-of-sync with others. + * This thread is prepared for that specific purpose. + */ + struct thread *t_opaque_lsa_self; + + /* + * Backpointer to an "owner" which is LSA-type dependent. + * type-9: struct ospf_interface + * type-10: struct ospf_area + * type-11: struct ospf + */ + void *owner; + + /* Collection of callback functions for this opaque-type. */ + struct ospf_opaque_functab *functab; + + /* List of Opaque-LSA control informations per opaque-id. */ + struct list *id_list; }; /* Opaque-LSA control information per opaque-id. */ -struct opaque_info_per_id -{ - u_int32_t opaque_id; +struct opaque_info_per_id { + u_int32_t opaque_id; - /* Thread for refresh/flush scheduling for this opaque-type/id. */ - struct thread *t_opaque_lsa_self; + /* Thread for refresh/flush scheduling for this opaque-type/id. */ + struct thread *t_opaque_lsa_self; - /* Backpointer to Opaque-LSA control information per opaque-type. */ - struct opaque_info_per_type *opqctl_type; + /* Backpointer to Opaque-LSA control information per opaque-type. */ + struct opaque_info_per_type *opqctl_type; - /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */ - struct ospf_lsa *lsa; + /* Here comes an actual Opaque-LSA entry for this opaque-type/id. */ + struct ospf_lsa *lsa; }; -static struct opaque_info_per_type *register_opaque_info_per_type (struct ospf_opaque_functab *functab, struct ospf_lsa *new); -static struct opaque_info_per_type *lookup_opaque_info_by_type (struct ospf_lsa *lsa); -static struct opaque_info_per_id *register_opaque_info_per_id (struct opaque_info_per_type *oipt, struct ospf_lsa *new); -static struct opaque_info_per_id *lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, struct ospf_lsa *lsa); -static struct opaque_info_per_id *register_opaque_lsa (struct ospf_lsa *new); +static struct opaque_info_per_type * +register_opaque_info_per_type(struct ospf_opaque_functab *functab, + struct ospf_lsa *new); +static struct opaque_info_per_type * +lookup_opaque_info_by_type(struct ospf_lsa *lsa); +static struct opaque_info_per_id * +register_opaque_info_per_id(struct opaque_info_per_type *oipt, + struct ospf_lsa *new); +static struct opaque_info_per_id * +lookup_opaque_info_by_id(struct opaque_info_per_type *oipt, + struct ospf_lsa *lsa); +static struct opaque_info_per_id *register_opaque_lsa(struct ospf_lsa *new); static struct opaque_info_per_type * -register_opaque_info_per_type (struct ospf_opaque_functab *functab, - struct ospf_lsa *new) -{ - struct ospf *top; - struct opaque_info_per_type *oipt; - - if ((oipt = XCALLOC (MTYPE_OPAQUE_INFO_PER_TYPE, - sizeof (struct opaque_info_per_type))) == NULL) - { - zlog_warn ("register_opaque_info_per_type: XMALLOC: %s", safe_strerror (errno)); - goto out; - } - - switch (new->data->type) - { - case OSPF_OPAQUE_LINK_LSA: - oipt->owner = new->oi; - listnode_add (new->oi->opaque_lsa_self, oipt); - break; - case OSPF_OPAQUE_AREA_LSA: - oipt->owner = new->area; - listnode_add (new->area->opaque_lsa_self, oipt); - break; - case OSPF_OPAQUE_AS_LSA: - top = ospf_lookup (); - if (new->area != NULL && (top = new->area->ospf) == NULL) - { - free_opaque_info_per_type ((void *) oipt); - oipt = NULL; - goto out; /* This case may not exist. */ - } - oipt->owner = top; - listnode_add (top->opaque_lsa_self, oipt); - break; - default: - zlog_warn ("register_opaque_info_per_type: Unexpected LSA-type(%u)", new->data->type); - free_opaque_info_per_type ((void *) oipt); - oipt = NULL; - goto out; /* This case may not exist. */ - } - - oipt->lsa_type = new->data->type; - oipt->opaque_type = GET_OPAQUE_TYPE (ntohl (new->data->id.s_addr)); - oipt->status = PROC_NORMAL; - oipt->t_opaque_lsa_self = NULL; - oipt->functab = functab; - functab->oipt = oipt; - oipt->id_list = list_new (); - oipt->id_list->del = free_opaque_info_per_id; +register_opaque_info_per_type(struct ospf_opaque_functab *functab, + struct ospf_lsa *new) +{ + struct ospf *top; + struct opaque_info_per_type *oipt; + + if ((oipt = XCALLOC(MTYPE_OPAQUE_INFO_PER_TYPE, + sizeof(struct opaque_info_per_type))) + == NULL) { + zlog_warn("register_opaque_info_per_type: XMALLOC: %s", + safe_strerror(errno)); + goto out; + } + + switch (new->data->type) { + case OSPF_OPAQUE_LINK_LSA: + oipt->owner = new->oi; + listnode_add(new->oi->opaque_lsa_self, oipt); + break; + case OSPF_OPAQUE_AREA_LSA: + oipt->owner = new->area; + listnode_add(new->area->opaque_lsa_self, oipt); + break; + case OSPF_OPAQUE_AS_LSA: + top = ospf_lookup(); + if (new->area != NULL && (top = new->area->ospf) == NULL) { + free_opaque_info_per_type((void *)oipt); + oipt = NULL; + goto out; /* This case may not exist. */ + } + oipt->owner = top; + listnode_add(top->opaque_lsa_self, oipt); + break; + default: + zlog_warn( + "register_opaque_info_per_type: Unexpected LSA-type(%u)", + new->data->type); + free_opaque_info_per_type((void *)oipt); + oipt = NULL; + goto out; /* This case may not exist. */ + } + + oipt->lsa_type = new->data->type; + oipt->opaque_type = GET_OPAQUE_TYPE(ntohl(new->data->id.s_addr)); + oipt->status = PROC_NORMAL; + oipt->t_opaque_lsa_self = NULL; + oipt->functab = functab; + functab->oipt = oipt; + oipt->id_list = list_new(); + oipt->id_list->del = free_opaque_info_per_id; out: - return oipt; -} - -static void -free_opaque_info_per_type (void *val) -{ - struct opaque_info_per_type *oipt = (struct opaque_info_per_type *) val; - struct opaque_info_per_id *oipi; - struct ospf_lsa *lsa; - struct listnode *node, *nnode; - - /* Control information per opaque-id may still exist. */ - for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi)) - { - if ((lsa = oipi->lsa) == NULL) - continue; - if (IS_LSA_MAXAGE (lsa)) - continue; - ospf_opaque_lsa_flush_schedule (lsa); - } - - /* Remove "oipt" from its owner's self-originated LSA list. */ - switch (oipt->lsa_type) - { - case OSPF_OPAQUE_LINK_LSA: - { - struct ospf_interface *oi = (struct ospf_interface *)(oipt->owner); - listnode_delete (oi->opaque_lsa_self, oipt); - break; - } - case OSPF_OPAQUE_AREA_LSA: - { - struct ospf_area *area = (struct ospf_area *)(oipt->owner); - listnode_delete (area->opaque_lsa_self, oipt); - break; - } - case OSPF_OPAQUE_AS_LSA: - { - struct ospf *top = (struct ospf *)(oipt->owner); - listnode_delete (top->opaque_lsa_self, oipt); - break; - } - default: - zlog_warn ("free_opaque_info_per_type: Unexpected LSA-type(%u)", oipt->lsa_type); - break; /* This case may not exist. */ - } - - OSPF_TIMER_OFF (oipt->t_opaque_lsa_self); - list_delete (oipt->id_list); - XFREE (MTYPE_OPAQUE_INFO_PER_TYPE, oipt); - return; + return oipt; +} + +static void free_opaque_info_per_type(void *val) +{ + struct opaque_info_per_type *oipt = (struct opaque_info_per_type *)val; + struct opaque_info_per_id *oipi; + struct ospf_lsa *lsa; + struct listnode *node, *nnode; + + /* Control information per opaque-id may still exist. */ + for (ALL_LIST_ELEMENTS(oipt->id_list, node, nnode, oipi)) { + if ((lsa = oipi->lsa) == NULL) + continue; + if (IS_LSA_MAXAGE(lsa)) + continue; + ospf_opaque_lsa_flush_schedule(lsa); + } + + /* Remove "oipt" from its owner's self-originated LSA list. */ + switch (oipt->lsa_type) { + case OSPF_OPAQUE_LINK_LSA: { + struct ospf_interface *oi = + (struct ospf_interface *)(oipt->owner); + listnode_delete(oi->opaque_lsa_self, oipt); + break; + } + case OSPF_OPAQUE_AREA_LSA: { + struct ospf_area *area = (struct ospf_area *)(oipt->owner); + listnode_delete(area->opaque_lsa_self, oipt); + break; + } + case OSPF_OPAQUE_AS_LSA: { + struct ospf *top = (struct ospf *)(oipt->owner); + listnode_delete(top->opaque_lsa_self, oipt); + break; + } + default: + zlog_warn("free_opaque_info_per_type: Unexpected LSA-type(%u)", + oipt->lsa_type); + break; /* This case may not exist. */ + } + + OSPF_TIMER_OFF(oipt->t_opaque_lsa_self); + list_delete(oipt->id_list); + XFREE(MTYPE_OPAQUE_INFO_PER_TYPE, oipt); + return; } static struct opaque_info_per_type * -lookup_opaque_info_by_type (struct ospf_lsa *lsa) -{ - struct ospf *top; - struct ospf_area *area; - struct ospf_interface *oi; - struct list *listtop = NULL; - struct listnode *node, *nnode; - struct opaque_info_per_type *oipt = NULL; - u_char key = GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)); - - switch (lsa->data->type) - { - case OSPF_OPAQUE_LINK_LSA: - if ((oi = lsa->oi) != NULL) - listtop = oi->opaque_lsa_self; - else - zlog_warn ("Type-9 Opaque-LSA: Reference to OI is missing?"); - break; - case OSPF_OPAQUE_AREA_LSA: - if ((area = lsa->area) != NULL) - listtop = area->opaque_lsa_self; - else - zlog_warn ("Type-10 Opaque-LSA: Reference to AREA is missing?"); - break; - case OSPF_OPAQUE_AS_LSA: - top = ospf_lookup (); - if ((area = lsa->area) != NULL && (top = area->ospf) == NULL) - { - zlog_warn ("Type-11 Opaque-LSA: Reference to OSPF is missing?"); - break; /* Unlikely to happen. */ - } - listtop = top->opaque_lsa_self; - break; - default: - zlog_warn ("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", lsa->data->type); - break; - } - - if (listtop != NULL) - for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt)) - if (oipt->opaque_type == key) - return oipt; - - return NULL; +lookup_opaque_info_by_type(struct ospf_lsa *lsa) +{ + struct ospf *top; + struct ospf_area *area; + struct ospf_interface *oi; + struct list *listtop = NULL; + struct listnode *node, *nnode; + struct opaque_info_per_type *oipt = NULL; + u_char key = GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)); + + switch (lsa->data->type) { + case OSPF_OPAQUE_LINK_LSA: + if ((oi = lsa->oi) != NULL) + listtop = oi->opaque_lsa_self; + else + zlog_warn( + "Type-9 Opaque-LSA: Reference to OI is missing?"); + break; + case OSPF_OPAQUE_AREA_LSA: + if ((area = lsa->area) != NULL) + listtop = area->opaque_lsa_self; + else + zlog_warn( + "Type-10 Opaque-LSA: Reference to AREA is missing?"); + break; + case OSPF_OPAQUE_AS_LSA: + top = ospf_lookup(); + if ((area = lsa->area) != NULL && (top = area->ospf) == NULL) { + zlog_warn( + "Type-11 Opaque-LSA: Reference to OSPF is missing?"); + break; /* Unlikely to happen. */ + } + listtop = top->opaque_lsa_self; + break; + default: + zlog_warn("lookup_opaque_info_by_type: Unexpected LSA-type(%u)", + lsa->data->type); + break; + } + + if (listtop != NULL) + for (ALL_LIST_ELEMENTS(listtop, node, nnode, oipt)) + if (oipt->opaque_type == key) + return oipt; + + return NULL; } static struct opaque_info_per_id * -register_opaque_info_per_id (struct opaque_info_per_type *oipt, - struct ospf_lsa *new) +register_opaque_info_per_id(struct opaque_info_per_type *oipt, + struct ospf_lsa *new) { - struct opaque_info_per_id *oipi; + struct opaque_info_per_id *oipi; - if ((oipi = XCALLOC (MTYPE_OPAQUE_INFO_PER_ID, - sizeof (struct opaque_info_per_id))) == NULL) - { - zlog_warn ("register_opaque_info_per_id: XMALLOC: %s", safe_strerror (errno)); - goto out; - } - oipi->opaque_id = GET_OPAQUE_ID (ntohl (new->data->id.s_addr)); - oipi->t_opaque_lsa_self = NULL; - oipi->opqctl_type = oipt; - oipi->lsa = ospf_lsa_lock (new); + if ((oipi = XCALLOC(MTYPE_OPAQUE_INFO_PER_ID, + sizeof(struct opaque_info_per_id))) + == NULL) { + zlog_warn("register_opaque_info_per_id: XMALLOC: %s", + safe_strerror(errno)); + goto out; + } + oipi->opaque_id = GET_OPAQUE_ID(ntohl(new->data->id.s_addr)); + oipi->t_opaque_lsa_self = NULL; + oipi->opqctl_type = oipt; + oipi->lsa = ospf_lsa_lock(new); - listnode_add (oipt->id_list, oipi); + listnode_add(oipt->id_list, oipi); out: - return oipi; + return oipi; } -static void -free_opaque_info_per_id (void *val) +static void free_opaque_info_per_id(void *val) { - struct opaque_info_per_id *oipi = (struct opaque_info_per_id *) val; + struct opaque_info_per_id *oipi = (struct opaque_info_per_id *)val; - OSPF_TIMER_OFF (oipi->t_opaque_lsa_self); - if (oipi->lsa != NULL) - ospf_lsa_unlock (&oipi->lsa); - XFREE (MTYPE_OPAQUE_INFO_PER_ID, oipi); - return; + OSPF_TIMER_OFF(oipi->t_opaque_lsa_self); + if (oipi->lsa != NULL) + ospf_lsa_unlock(&oipi->lsa); + XFREE(MTYPE_OPAQUE_INFO_PER_ID, oipi); + return; } static struct opaque_info_per_id * -lookup_opaque_info_by_id (struct opaque_info_per_type *oipt, - struct ospf_lsa *lsa) +lookup_opaque_info_by_id(struct opaque_info_per_type *oipt, + struct ospf_lsa *lsa) { - struct listnode *node, *nnode; - struct opaque_info_per_id *oipi; - u_int32_t key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)); + struct listnode *node, *nnode; + struct opaque_info_per_id *oipi; + u_int32_t key = GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)); - for (ALL_LIST_ELEMENTS (oipt->id_list, node, nnode, oipi)) - if (oipi->opaque_id == key) - return oipi; + for (ALL_LIST_ELEMENTS(oipt->id_list, node, nnode, oipi)) + if (oipi->opaque_id == key) + return oipi; - return NULL; + return NULL; } -static struct opaque_info_per_id * -register_opaque_lsa (struct ospf_lsa *new) +static struct opaque_info_per_id *register_opaque_lsa(struct ospf_lsa *new) { - struct ospf_opaque_functab *functab; - struct opaque_info_per_type *oipt; - struct opaque_info_per_id *oipi = NULL; + struct ospf_opaque_functab *functab; + struct opaque_info_per_type *oipt; + struct opaque_info_per_id *oipi = NULL; - if ((functab = ospf_opaque_functab_lookup (new)) == NULL) - goto out; + if ((functab = ospf_opaque_functab_lookup(new)) == NULL) + goto out; - if ((oipt = lookup_opaque_info_by_type (new)) == NULL - && (oipt = register_opaque_info_per_type (functab, new)) == NULL) - goto out; + if ((oipt = lookup_opaque_info_by_type(new)) == NULL + && (oipt = register_opaque_info_per_type(functab, new)) == NULL) + goto out; - if ((oipi = register_opaque_info_per_id (oipt, new)) == NULL) - goto out; + if ((oipi = register_opaque_info_per_id(oipt, new)) == NULL) + goto out; out: - return oipi; + return oipi; } /*------------------------------------------------------------------------* @@ -768,18 +750,17 @@ DEFUN (capability_opaque, "Enable specific OSPF feature\n" "Opaque LSA\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); + VTY_DECLVAR_CONTEXT(ospf, ospf); - /* Turn on the "master switch" of opaque-lsa capability. */ - if (!CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Opaque capability: OFF -> ON"); + /* Turn on the "master switch" of opaque-lsa capability. */ + if (!CHECK_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Opaque capability: OFF -> ON"); - SET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE); - ospf_renegotiate_optional_capabilities (ospf); - } - return CMD_SUCCESS; + SET_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE); + ospf_renegotiate_optional_capabilities(ospf); + } + return CMD_SUCCESS; } DEFUN (ospf_opaque, @@ -788,7 +769,7 @@ DEFUN (ospf_opaque, "OSPF specific commands\n" "Enable the Opaque-LSA capability (rfc2370)\n") { - return capability_opaque (self, vty, argc, argv); + return capability_opaque(self, vty, argc, argv); } DEFUN (no_capability_opaque, @@ -798,18 +779,17 @@ DEFUN (no_capability_opaque, "Enable specific OSPF feature\n" "Opaque LSA\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); + VTY_DECLVAR_CONTEXT(ospf, ospf); - /* Turn off the "master switch" of opaque-lsa capability. */ - if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Opaque capability: ON -> OFF"); + /* Turn off the "master switch" of opaque-lsa capability. */ + if (CHECK_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Opaque capability: ON -> OFF"); - UNSET_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE); - ospf_renegotiate_optional_capabilities (ospf); - } - return CMD_SUCCESS; + UNSET_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE); + ospf_renegotiate_optional_capabilities(ospf); + } + return CMD_SUCCESS; } DEFUN (no_ospf_opaque, @@ -819,833 +799,825 @@ DEFUN (no_ospf_opaque, "OSPF specific commands\n" "Enable the Opaque-LSA capability (rfc2370)\n") { - return no_capability_opaque (self, vty, argc, argv); + return no_capability_opaque(self, vty, argc, argv); } -static void -ospf_opaque_register_vty (void) +static void ospf_opaque_register_vty(void) { - install_element (OSPF_NODE, &capability_opaque_cmd); - install_element (OSPF_NODE, &no_capability_opaque_cmd); - install_element (OSPF_NODE, &ospf_opaque_cmd); - install_element (OSPF_NODE, &no_ospf_opaque_cmd); - return; + install_element(OSPF_NODE, &capability_opaque_cmd); + install_element(OSPF_NODE, &no_capability_opaque_cmd); + install_element(OSPF_NODE, &ospf_opaque_cmd); + install_element(OSPF_NODE, &no_ospf_opaque_cmd); + return; } /*------------------------------------------------------------------------* * Followings are collection of user-registered function callers. *------------------------------------------------------------------------*/ -static int -opaque_lsa_new_if_callback (struct list *funclist, struct interface *ifp) +static int opaque_lsa_new_if_callback(struct list *funclist, + struct interface *ifp) { - struct listnode *node, *nnode; - struct ospf_opaque_functab *functab; - int rc = -1; + struct listnode *node, *nnode; + struct ospf_opaque_functab *functab; + int rc = -1; - for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab)) - if (functab->new_if_hook != NULL) - if ((* functab->new_if_hook)(ifp) != 0) - goto out; - rc = 0; + for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab)) + if (functab->new_if_hook != NULL) + if ((*functab->new_if_hook)(ifp) != 0) + goto out; + rc = 0; out: - return rc; + return rc; } -static int -opaque_lsa_del_if_callback (struct list *funclist, struct interface *ifp) +static int opaque_lsa_del_if_callback(struct list *funclist, + struct interface *ifp) { - struct listnode *node, *nnode; - struct ospf_opaque_functab *functab; - int rc = -1; + struct listnode *node, *nnode; + struct ospf_opaque_functab *functab; + int rc = -1; - for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab)) - if (functab->del_if_hook != NULL) - if ((* functab->del_if_hook)(ifp) != 0) - goto out; - rc = 0; + for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab)) + if (functab->del_if_hook != NULL) + if ((*functab->del_if_hook)(ifp) != 0) + goto out; + rc = 0; out: - return rc; + return rc; } -static void -opaque_lsa_ism_change_callback (struct list *funclist, - struct ospf_interface *oi, int old_status) +static void opaque_lsa_ism_change_callback(struct list *funclist, + struct ospf_interface *oi, + int old_status) { - struct listnode *node, *nnode; - struct ospf_opaque_functab *functab; + struct listnode *node, *nnode; + struct ospf_opaque_functab *functab; - for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab)) - if (functab->ism_change_hook != NULL) - (* functab->ism_change_hook)(oi, old_status); + for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab)) + if (functab->ism_change_hook != NULL) + (*functab->ism_change_hook)(oi, old_status); - return; + return; } -static void -opaque_lsa_nsm_change_callback (struct list *funclist, - struct ospf_neighbor *nbr, int old_status) +static void opaque_lsa_nsm_change_callback(struct list *funclist, + struct ospf_neighbor *nbr, + int old_status) { - struct listnode *node, *nnode; - struct ospf_opaque_functab *functab; + struct listnode *node, *nnode; + struct ospf_opaque_functab *functab; - for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab)) - if (functab->nsm_change_hook != NULL) - (* functab->nsm_change_hook)(nbr, old_status); - return; + for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab)) + if (functab->nsm_change_hook != NULL) + (*functab->nsm_change_hook)(nbr, old_status); + return; } -static void -opaque_lsa_config_write_router_callback (struct list *funclist, - struct vty *vty) +static void opaque_lsa_config_write_router_callback(struct list *funclist, + struct vty *vty) { - struct listnode *node, *nnode; - struct ospf_opaque_functab *functab; + struct listnode *node, *nnode; + struct ospf_opaque_functab *functab; - for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab)) - if (functab->config_write_router != NULL) - (* functab->config_write_router)(vty); - return; + for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab)) + if (functab->config_write_router != NULL) + (*functab->config_write_router)(vty); + return; } -static void -opaque_lsa_config_write_if_callback (struct list *funclist, - struct vty *vty, struct interface *ifp) +static void opaque_lsa_config_write_if_callback(struct list *funclist, + struct vty *vty, + struct interface *ifp) { - struct listnode *node, *nnode; - struct ospf_opaque_functab *functab; + struct listnode *node, *nnode; + struct ospf_opaque_functab *functab; - for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab)) - if (functab->config_write_if != NULL) - (* functab->config_write_if)(vty, ifp); - return; + for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab)) + if (functab->config_write_if != NULL) + (*functab->config_write_if)(vty, ifp); + return; } -static void -opaque_lsa_config_write_debug_callback (struct list *funclist, struct vty *vty) +static void opaque_lsa_config_write_debug_callback(struct list *funclist, + struct vty *vty) { - struct listnode *node, *nnode; - struct ospf_opaque_functab *functab; + struct listnode *node, *nnode; + struct ospf_opaque_functab *functab; - for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab)) - if (functab->config_write_debug != NULL) - (* functab->config_write_debug)(vty); - return; + for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab)) + if (functab->config_write_debug != NULL) + (*functab->config_write_debug)(vty); + return; } -static int -opaque_lsa_originate_callback (struct list *funclist, void *lsa_type_dependent) +static int opaque_lsa_originate_callback(struct list *funclist, + void *lsa_type_dependent) { - struct listnode *node, *nnode; - struct ospf_opaque_functab *functab; - int rc = -1; + struct listnode *node, *nnode; + struct ospf_opaque_functab *functab; + int rc = -1; - for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab)) - if (functab->lsa_originator != NULL) - if ((* functab->lsa_originator)(lsa_type_dependent) != 0) - goto out; - rc = 0; + for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab)) + if (functab->lsa_originator != NULL) + if ((*functab->lsa_originator)(lsa_type_dependent) != 0) + goto out; + rc = 0; out: - return rc; + return rc; } -static int -new_lsa_callback (struct list *funclist, struct ospf_lsa *lsa) +static int new_lsa_callback(struct list *funclist, struct ospf_lsa *lsa) { - struct listnode *node, *nnode; - struct ospf_opaque_functab *functab; - int rc = -1; + struct listnode *node, *nnode; + struct ospf_opaque_functab *functab; + int rc = -1; - /* This function handles ALL types of LSAs, not only opaque ones. */ - for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab)) - if (functab->new_lsa_hook != NULL) - if ((* functab->new_lsa_hook)(lsa) != 0) - goto out; - rc = 0; + /* This function handles ALL types of LSAs, not only opaque ones. */ + for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab)) + if (functab->new_lsa_hook != NULL) + if ((*functab->new_lsa_hook)(lsa) != 0) + goto out; + rc = 0; out: - return rc; + return rc; } -static int -del_lsa_callback (struct list *funclist, struct ospf_lsa *lsa) +static int del_lsa_callback(struct list *funclist, struct ospf_lsa *lsa) { - struct listnode *node, *nnode; - struct ospf_opaque_functab *functab; - int rc = -1; + struct listnode *node, *nnode; + struct ospf_opaque_functab *functab; + int rc = -1; - /* This function handles ALL types of LSAs, not only opaque ones. */ - for (ALL_LIST_ELEMENTS (funclist, node, nnode, functab)) - if (functab->del_lsa_hook != NULL) - if ((* functab->del_lsa_hook)(lsa) != 0) - goto out; - rc = 0; + /* This function handles ALL types of LSAs, not only opaque ones. */ + for (ALL_LIST_ELEMENTS(funclist, node, nnode, functab)) + if (functab->del_lsa_hook != NULL) + if ((*functab->del_lsa_hook)(lsa) != 0) + goto out; + rc = 0; out: - return rc; + return rc; } /*------------------------------------------------------------------------* * Followings are glue functions to call Opaque-LSA specific processing. *------------------------------------------------------------------------*/ -int -ospf_opaque_new_if (struct interface *ifp) +int ospf_opaque_new_if(struct interface *ifp) { - struct list *funclist; - int rc = -1; + struct list *funclist; + int rc = -1; - funclist = ospf_opaque_wildcard_funclist; - if (opaque_lsa_new_if_callback (funclist, ifp) != 0) - goto out; + funclist = ospf_opaque_wildcard_funclist; + if (opaque_lsa_new_if_callback(funclist, ifp) != 0) + goto out; - funclist = ospf_opaque_type9_funclist; - if (opaque_lsa_new_if_callback (funclist, ifp) != 0) - goto out; + funclist = ospf_opaque_type9_funclist; + if (opaque_lsa_new_if_callback(funclist, ifp) != 0) + goto out; - funclist = ospf_opaque_type10_funclist; - if (opaque_lsa_new_if_callback (funclist, ifp) != 0) - goto out; + funclist = ospf_opaque_type10_funclist; + if (opaque_lsa_new_if_callback(funclist, ifp) != 0) + goto out; - funclist = ospf_opaque_type11_funclist; - if (opaque_lsa_new_if_callback (funclist, ifp) != 0) - goto out; + funclist = ospf_opaque_type11_funclist; + if (opaque_lsa_new_if_callback(funclist, ifp) != 0) + goto out; - rc = 0; + rc = 0; out: - return rc; + return rc; } -int -ospf_opaque_del_if (struct interface *ifp) +int ospf_opaque_del_if(struct interface *ifp) { - struct list *funclist; - int rc = -1; + struct list *funclist; + int rc = -1; - funclist = ospf_opaque_wildcard_funclist; - if (opaque_lsa_del_if_callback (funclist, ifp) != 0) - goto out; + funclist = ospf_opaque_wildcard_funclist; + if (opaque_lsa_del_if_callback(funclist, ifp) != 0) + goto out; - funclist = ospf_opaque_type9_funclist; - if (opaque_lsa_del_if_callback (funclist, ifp) != 0) - goto out; + funclist = ospf_opaque_type9_funclist; + if (opaque_lsa_del_if_callback(funclist, ifp) != 0) + goto out; - funclist = ospf_opaque_type10_funclist; - if (opaque_lsa_del_if_callback (funclist, ifp) != 0) - goto out; + funclist = ospf_opaque_type10_funclist; + if (opaque_lsa_del_if_callback(funclist, ifp) != 0) + goto out; - funclist = ospf_opaque_type11_funclist; - if (opaque_lsa_del_if_callback (funclist, ifp) != 0) - goto out; + funclist = ospf_opaque_type11_funclist; + if (opaque_lsa_del_if_callback(funclist, ifp) != 0) + goto out; - rc = 0; + rc = 0; out: - return rc; + return rc; } -void -ospf_opaque_ism_change (struct ospf_interface *oi, int old_status) +void ospf_opaque_ism_change(struct ospf_interface *oi, int old_status) { - struct list *funclist; + struct list *funclist; - funclist = ospf_opaque_wildcard_funclist; - opaque_lsa_ism_change_callback (funclist, oi, old_status); + funclist = ospf_opaque_wildcard_funclist; + opaque_lsa_ism_change_callback(funclist, oi, old_status); - funclist = ospf_opaque_type9_funclist; - opaque_lsa_ism_change_callback (funclist, oi, old_status); + funclist = ospf_opaque_type9_funclist; + opaque_lsa_ism_change_callback(funclist, oi, old_status); - funclist = ospf_opaque_type10_funclist; - opaque_lsa_ism_change_callback (funclist, oi, old_status); + funclist = ospf_opaque_type10_funclist; + opaque_lsa_ism_change_callback(funclist, oi, old_status); - funclist = ospf_opaque_type11_funclist; - opaque_lsa_ism_change_callback (funclist, oi, old_status); + funclist = ospf_opaque_type11_funclist; + opaque_lsa_ism_change_callback(funclist, oi, old_status); - return; + return; } -void -ospf_opaque_nsm_change (struct ospf_neighbor *nbr, int old_state) +void ospf_opaque_nsm_change(struct ospf_neighbor *nbr, int old_state) { - struct ospf *top; - struct list *funclist; + struct ospf *top; + struct list *funclist; - if ((top = oi_to_top (nbr->oi)) == NULL) - goto out; + if ((top = oi_to_top(nbr->oi)) == NULL) + goto out; - if (old_state != NSM_Full && nbr->state == NSM_Full) - { - if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)) - { - if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Opaque-LSA: Now get operational!"); + if (old_state != NSM_Full && nbr->state == NSM_Full) { + if (CHECK_FLAG(nbr->options, OSPF_OPTION_O)) { + if (!CHECK_FLAG(top->opaque, + OPAQUE_OPERATION_READY_BIT)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Opaque-LSA: Now get operational!"); - SET_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT); - } + SET_FLAG(top->opaque, + OPAQUE_OPERATION_READY_BIT); + } - ospf_opaque_lsa_originate_schedule (nbr->oi, NULL); - } - } - else - if (old_state == NSM_Full && nbr->state != NSM_Full) - { + ospf_opaque_lsa_originate_schedule(nbr->oi, NULL); + } + } else if (old_state == NSM_Full && nbr->state != NSM_Full) { #ifdef NOTYET - /* - * If no more opaque-capable full-state neighbor remains in the - * flooding scope which corresponds to Opaque-LSA type, periodic - * LS flooding should be stopped. - */ +/* + * If no more opaque-capable full-state neighbor remains in the + * flooding scope which corresponds to Opaque-LSA type, periodic + * LS flooding should be stopped. + */ #endif /* NOTYET */ - ; - } + ; + } - funclist = ospf_opaque_wildcard_funclist; - opaque_lsa_nsm_change_callback (funclist, nbr, old_state); + funclist = ospf_opaque_wildcard_funclist; + opaque_lsa_nsm_change_callback(funclist, nbr, old_state); - funclist = ospf_opaque_type9_funclist; - opaque_lsa_nsm_change_callback (funclist, nbr, old_state); + funclist = ospf_opaque_type9_funclist; + opaque_lsa_nsm_change_callback(funclist, nbr, old_state); - funclist = ospf_opaque_type10_funclist; - opaque_lsa_nsm_change_callback (funclist, nbr, old_state); + funclist = ospf_opaque_type10_funclist; + opaque_lsa_nsm_change_callback(funclist, nbr, old_state); - funclist = ospf_opaque_type11_funclist; - opaque_lsa_nsm_change_callback (funclist, nbr, old_state); + funclist = ospf_opaque_type11_funclist; + opaque_lsa_nsm_change_callback(funclist, nbr, old_state); out: - return; + return; } -void -ospf_opaque_config_write_router (struct vty *vty, struct ospf *ospf) +void ospf_opaque_config_write_router(struct vty *vty, struct ospf *ospf) { - struct list *funclist; + struct list *funclist; - if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE)) - vty_out (vty, " capability opaque\n"); + if (CHECK_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE)) + vty_out(vty, " capability opaque\n"); - funclist = ospf_opaque_wildcard_funclist; - opaque_lsa_config_write_router_callback (funclist, vty); + funclist = ospf_opaque_wildcard_funclist; + opaque_lsa_config_write_router_callback(funclist, vty); - funclist = ospf_opaque_type9_funclist; - opaque_lsa_config_write_router_callback (funclist, vty); + funclist = ospf_opaque_type9_funclist; + opaque_lsa_config_write_router_callback(funclist, vty); - funclist = ospf_opaque_type10_funclist; - opaque_lsa_config_write_router_callback (funclist, vty); + funclist = ospf_opaque_type10_funclist; + opaque_lsa_config_write_router_callback(funclist, vty); - funclist = ospf_opaque_type11_funclist; - opaque_lsa_config_write_router_callback (funclist, vty); + funclist = ospf_opaque_type11_funclist; + opaque_lsa_config_write_router_callback(funclist, vty); - return; + return; } -void -ospf_opaque_config_write_if (struct vty *vty, struct interface *ifp) +void ospf_opaque_config_write_if(struct vty *vty, struct interface *ifp) { - struct list *funclist; + struct list *funclist; - funclist = ospf_opaque_wildcard_funclist; - opaque_lsa_config_write_if_callback (funclist, vty, ifp); + funclist = ospf_opaque_wildcard_funclist; + opaque_lsa_config_write_if_callback(funclist, vty, ifp); - funclist = ospf_opaque_type9_funclist; - opaque_lsa_config_write_if_callback (funclist, vty, ifp); + funclist = ospf_opaque_type9_funclist; + opaque_lsa_config_write_if_callback(funclist, vty, ifp); - funclist = ospf_opaque_type10_funclist; - opaque_lsa_config_write_if_callback (funclist, vty, ifp); + funclist = ospf_opaque_type10_funclist; + opaque_lsa_config_write_if_callback(funclist, vty, ifp); - funclist = ospf_opaque_type11_funclist; - opaque_lsa_config_write_if_callback (funclist, vty, ifp); + funclist = ospf_opaque_type11_funclist; + opaque_lsa_config_write_if_callback(funclist, vty, ifp); - return; + return; } -void -ospf_opaque_config_write_debug (struct vty *vty) +void ospf_opaque_config_write_debug(struct vty *vty) { - struct list *funclist; + struct list *funclist; - funclist = ospf_opaque_wildcard_funclist; - opaque_lsa_config_write_debug_callback (funclist, vty); + funclist = ospf_opaque_wildcard_funclist; + opaque_lsa_config_write_debug_callback(funclist, vty); - funclist = ospf_opaque_type9_funclist; - opaque_lsa_config_write_debug_callback (funclist, vty); + funclist = ospf_opaque_type9_funclist; + opaque_lsa_config_write_debug_callback(funclist, vty); - funclist = ospf_opaque_type10_funclist; - opaque_lsa_config_write_debug_callback (funclist, vty); + funclist = ospf_opaque_type10_funclist; + opaque_lsa_config_write_debug_callback(funclist, vty); - funclist = ospf_opaque_type11_funclist; - opaque_lsa_config_write_debug_callback (funclist, vty); + funclist = ospf_opaque_type11_funclist; + opaque_lsa_config_write_debug_callback(funclist, vty); - return; + return; } -void -show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa) +void show_opaque_info_detail(struct vty *vty, struct ospf_lsa *lsa) { - struct lsa_header *lsah = (struct lsa_header *) lsa->data; - u_int32_t lsid = ntohl (lsah->id.s_addr); - u_char opaque_type = GET_OPAQUE_TYPE (lsid); - u_int32_t opaque_id = GET_OPAQUE_ID (lsid); - struct ospf_opaque_functab *functab; + struct lsa_header *lsah = (struct lsa_header *)lsa->data; + u_int32_t lsid = ntohl(lsah->id.s_addr); + u_char opaque_type = GET_OPAQUE_TYPE(lsid); + u_int32_t opaque_id = GET_OPAQUE_ID(lsid); + struct ospf_opaque_functab *functab; - /* Switch output functionality by vty address. */ - if (vty != NULL) - { - vty_out (vty, " Opaque-Type %u (%s)\n", opaque_type, - ospf_opaque_type_name(opaque_type)); - vty_out (vty, " Opaque-ID 0x%x\n", opaque_id); + /* Switch output functionality by vty address. */ + if (vty != NULL) { + vty_out(vty, " Opaque-Type %u (%s)\n", opaque_type, + ospf_opaque_type_name(opaque_type)); + vty_out(vty, " Opaque-ID 0x%x\n", opaque_id); - vty_out (vty, " Opaque-Info: %u octets of data%s\n", - ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE, - VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)"); - } - else - { - zlog_debug (" Opaque-Type %u (%s)", opaque_type, - ospf_opaque_type_name (opaque_type)); - zlog_debug (" Opaque-ID 0x%x", opaque_id); + vty_out(vty, " Opaque-Info: %u octets of data%s\n", + ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE, + VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)"); + } else { + zlog_debug(" Opaque-Type %u (%s)", opaque_type, + ospf_opaque_type_name(opaque_type)); + zlog_debug(" Opaque-ID 0x%x", opaque_id); - zlog_debug (" Opaque-Info: %u octets of data%s", - ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE, - VALID_OPAQUE_INFO_LEN(lsah) ? "" : "(Invalid length?)"); - } + zlog_debug(" Opaque-Info: %u octets of data%s", + ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE, + VALID_OPAQUE_INFO_LEN(lsah) ? "" + : "(Invalid length?)"); + } - /* Call individual output functions. */ - if ((functab = ospf_opaque_functab_lookup (lsa)) != NULL) - if (functab->show_opaque_info != NULL) - (* functab->show_opaque_info)(vty, lsa); + /* Call individual output functions. */ + if ((functab = ospf_opaque_functab_lookup(lsa)) != NULL) + if (functab->show_opaque_info != NULL) + (*functab->show_opaque_info)(vty, lsa); - return; + return; } -void -ospf_opaque_lsa_dump (struct stream *s, u_int16_t length) +void ospf_opaque_lsa_dump(struct stream *s, u_int16_t length) { - struct ospf_lsa lsa; + struct ospf_lsa lsa; - lsa.data = (struct lsa_header *) STREAM_PNT (s); - show_opaque_info_detail (NULL, &lsa); - return; + lsa.data = (struct lsa_header *)STREAM_PNT(s); + show_opaque_info_detail(NULL, &lsa); + return; } -static int -ospf_opaque_lsa_install_hook (struct ospf_lsa *lsa) +static int ospf_opaque_lsa_install_hook(struct ospf_lsa *lsa) { - struct list *funclist; - int rc = -1; + struct list *funclist; + int rc = -1; - /* - * Some Opaque-LSA user may want to monitor every LSA installation - * into the LSDB, regardless with target LSA type. - */ - funclist = ospf_opaque_wildcard_funclist; - if (new_lsa_callback (funclist, lsa) != 0) - goto out; + /* + * Some Opaque-LSA user may want to monitor every LSA installation + * into the LSDB, regardless with target LSA type. + */ + funclist = ospf_opaque_wildcard_funclist; + if (new_lsa_callback(funclist, lsa) != 0) + goto out; - funclist = ospf_opaque_type9_funclist; - if (new_lsa_callback (funclist, lsa) != 0) - goto out; + funclist = ospf_opaque_type9_funclist; + if (new_lsa_callback(funclist, lsa) != 0) + goto out; - funclist = ospf_opaque_type10_funclist; - if (new_lsa_callback (funclist, lsa) != 0) - goto out; + funclist = ospf_opaque_type10_funclist; + if (new_lsa_callback(funclist, lsa) != 0) + goto out; - funclist = ospf_opaque_type11_funclist; - if (new_lsa_callback (funclist, lsa) != 0) - goto out; + funclist = ospf_opaque_type11_funclist; + if (new_lsa_callback(funclist, lsa) != 0) + goto out; - rc = 0; + rc = 0; out: - return rc; + return rc; } -static int -ospf_opaque_lsa_delete_hook (struct ospf_lsa *lsa) +static int ospf_opaque_lsa_delete_hook(struct ospf_lsa *lsa) { - struct list *funclist; - int rc = -1; + struct list *funclist; + int rc = -1; - /* - * Some Opaque-LSA user may want to monitor every LSA deletion - * from the LSDB, regardless with target LSA type. - */ - funclist = ospf_opaque_wildcard_funclist; - if (del_lsa_callback (funclist, lsa) != 0) - goto out; + /* + * Some Opaque-LSA user may want to monitor every LSA deletion + * from the LSDB, regardless with target LSA type. + */ + funclist = ospf_opaque_wildcard_funclist; + if (del_lsa_callback(funclist, lsa) != 0) + goto out; - funclist = ospf_opaque_type9_funclist; - if (del_lsa_callback (funclist, lsa) != 0) - goto out; + funclist = ospf_opaque_type9_funclist; + if (del_lsa_callback(funclist, lsa) != 0) + goto out; - funclist = ospf_opaque_type10_funclist; - if (del_lsa_callback (funclist, lsa) != 0) - goto out; + funclist = ospf_opaque_type10_funclist; + if (del_lsa_callback(funclist, lsa) != 0) + goto out; - funclist = ospf_opaque_type11_funclist; - if (del_lsa_callback (funclist, lsa) != 0) - goto out; + funclist = ospf_opaque_type11_funclist; + if (del_lsa_callback(funclist, lsa) != 0) + goto out; - rc = 0; + rc = 0; out: - return rc; + return rc; } /*------------------------------------------------------------------------* * Followings are Opaque-LSA origination/refresh management functions. *------------------------------------------------------------------------*/ -static int ospf_opaque_type9_lsa_originate (struct thread *t); -static int ospf_opaque_type10_lsa_originate (struct thread *t); -static int ospf_opaque_type11_lsa_originate (struct thread *t); -static void ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg); - -void -ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0) -{ - struct ospf *top; - struct ospf_area *area; - struct listnode *node, *nnode; - struct opaque_info_per_type *oipt; - int delay = 0; - - if ((top = oi_to_top (oi)) == NULL || (area = oi->area) == NULL) - { - zlog_warn ("ospf_opaque_lsa_originate_schedule: Invalid argument?"); - goto out; - } - - /* It may not a right time to schedule origination now. */ - if (! CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_opaque_lsa_originate_schedule: Not operational."); - goto out; /* This is not an error. */ - } - - if (delay0 != NULL) - delay = *delay0; - - /* - * There might be some entries that have been waiting for triggering - * of per opaque-type re-origination get resumed. - */ - ospf_opaque_lsa_reoriginate_resume ( oi->opaque_lsa_self, (void *) oi); - ospf_opaque_lsa_reoriginate_resume (area->opaque_lsa_self, (void *) area); - ospf_opaque_lsa_reoriginate_resume ( top->opaque_lsa_self, (void *) top); - - /* - * Now, schedule origination of all Opaque-LSAs per opaque-type. - */ - if (! list_isempty (ospf_opaque_type9_funclist) - && list_isempty (oi->opaque_lsa_self) - && oi->t_opaque_lsa_self == NULL) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Schedule Type-9 Opaque-LSA origination in %d ms later.", delay); - oi->t_opaque_lsa_self = NULL; - thread_add_timer_msec(master, ospf_opaque_type9_lsa_originate, oi, delay, - &oi->t_opaque_lsa_self); - delay += top->min_ls_interval; - } - - if (! list_isempty (ospf_opaque_type10_funclist) - && list_isempty (area->opaque_lsa_self) - && area->t_opaque_lsa_self == NULL) - { - /* - * One AREA may contain multiple OIs, but above 2nd and 3rd - * conditions prevent from scheduling the originate function - * again and again. - */ - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Schedule Type-10 Opaque-LSA origination in %d ms later.", delay); - area->t_opaque_lsa_self = NULL; - thread_add_timer_msec(master, ospf_opaque_type10_lsa_originate, area, delay, - &area->t_opaque_lsa_self); - delay += top->min_ls_interval; - } - - if (! list_isempty (ospf_opaque_type11_funclist) - && list_isempty (top->opaque_lsa_self) - && top->t_opaque_lsa_self == NULL) - { - /* - * One OSPF may contain multiple AREAs, but above 2nd and 3rd - * conditions prevent from scheduling the originate function - * again and again. - */ - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Schedule Type-11 Opaque-LSA origination in %d ms later.", delay); - top->t_opaque_lsa_self = NULL; - thread_add_timer_msec(master, ospf_opaque_type11_lsa_originate, top, delay, - &top->t_opaque_lsa_self); - delay += top->min_ls_interval; - } - - /* - * Following section treats a special situation that this node's - * opaque capability has changed as "ON -> OFF -> ON". - */ - if (! list_isempty (ospf_opaque_type9_funclist) - && ! list_isempty (oi->opaque_lsa_self)) - { - for (ALL_LIST_ELEMENTS (oi->opaque_lsa_self, node, nnode, oipt)) - { - /* - * removed the test for - * (! list_isempty (oipt->id_list)) * Handler is already active. * - * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list) - * not being empty. - */ - if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */ - || oipt->status == PROC_SUSPEND) /* Cannot originate now. */ - continue; - - ospf_opaque_lsa_reoriginate_schedule ((void *) oi, - OSPF_OPAQUE_LINK_LSA, oipt->opaque_type); - } - } - - if (! list_isempty (ospf_opaque_type10_funclist) - && ! list_isempty (area->opaque_lsa_self)) - { - for (ALL_LIST_ELEMENTS (area->opaque_lsa_self, node, nnode, oipt)) - { - /* - * removed the test for - * (! list_isempty (oipt->id_list)) * Handler is already active. * - * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list) - * not being empty. - */ - if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */ - || oipt->status == PROC_SUSPEND) /* Cannot originate now. */ - continue; - - ospf_opaque_lsa_reoriginate_schedule ((void *) area, - OSPF_OPAQUE_AREA_LSA, oipt->opaque_type); - } - } - - if (! list_isempty (ospf_opaque_type11_funclist) - && ! list_isempty (top->opaque_lsa_self)) - { - for (ALL_LIST_ELEMENTS (top->opaque_lsa_self, node, nnode, oipt)) - { - /* - * removed the test for - * (! list_isempty (oipt->id_list)) * Handler is already active. * - * because opaque cababilities ON -> OFF -> ON result in list_isempty (oipt->id_list) - * not being empty. - */ - if (oipt->t_opaque_lsa_self != NULL /* Waiting for a thread call. */ - || oipt->status == PROC_SUSPEND) /* Cannot originate now. */ - continue; - - ospf_opaque_lsa_reoriginate_schedule ((void *) top, - OSPF_OPAQUE_AS_LSA, oipt->opaque_type); - } - } - - if (delay0 != NULL) - *delay0 = delay; +static int ospf_opaque_type9_lsa_originate(struct thread *t); +static int ospf_opaque_type10_lsa_originate(struct thread *t); +static int ospf_opaque_type11_lsa_originate(struct thread *t); +static void ospf_opaque_lsa_reoriginate_resume(struct list *listtop, void *arg); + +void ospf_opaque_lsa_originate_schedule(struct ospf_interface *oi, int *delay0) +{ + struct ospf *top; + struct ospf_area *area; + struct listnode *node, *nnode; + struct opaque_info_per_type *oipt; + int delay = 0; + + if ((top = oi_to_top(oi)) == NULL || (area = oi->area) == NULL) { + zlog_warn( + "ospf_opaque_lsa_originate_schedule: Invalid argument?"); + goto out; + } + + /* It may not a right time to schedule origination now. */ + if (!CHECK_FLAG(top->opaque, OPAQUE_OPERATION_READY_BIT)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_opaque_lsa_originate_schedule: Not operational."); + goto out; /* This is not an error. */ + } + + if (delay0 != NULL) + delay = *delay0; + + /* + * There might be some entries that have been waiting for triggering + * of per opaque-type re-origination get resumed. + */ + ospf_opaque_lsa_reoriginate_resume(oi->opaque_lsa_self, (void *)oi); + ospf_opaque_lsa_reoriginate_resume(area->opaque_lsa_self, (void *)area); + ospf_opaque_lsa_reoriginate_resume(top->opaque_lsa_self, (void *)top); + + /* + * Now, schedule origination of all Opaque-LSAs per opaque-type. + */ + if (!list_isempty(ospf_opaque_type9_funclist) + && list_isempty(oi->opaque_lsa_self) + && oi->t_opaque_lsa_self == NULL) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Schedule Type-9 Opaque-LSA origination in %d ms later.", + delay); + oi->t_opaque_lsa_self = NULL; + thread_add_timer_msec(master, ospf_opaque_type9_lsa_originate, + oi, delay, &oi->t_opaque_lsa_self); + delay += top->min_ls_interval; + } + + if (!list_isempty(ospf_opaque_type10_funclist) + && list_isempty(area->opaque_lsa_self) + && area->t_opaque_lsa_self == NULL) { + /* + * One AREA may contain multiple OIs, but above 2nd and 3rd + * conditions prevent from scheduling the originate function + * again and again. + */ + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Schedule Type-10 Opaque-LSA origination in %d ms later.", + delay); + area->t_opaque_lsa_self = NULL; + thread_add_timer_msec(master, ospf_opaque_type10_lsa_originate, + area, delay, &area->t_opaque_lsa_self); + delay += top->min_ls_interval; + } + + if (!list_isempty(ospf_opaque_type11_funclist) + && list_isempty(top->opaque_lsa_self) + && top->t_opaque_lsa_self == NULL) { + /* + * One OSPF may contain multiple AREAs, but above 2nd and 3rd + * conditions prevent from scheduling the originate function + * again and again. + */ + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Schedule Type-11 Opaque-LSA origination in %d ms later.", + delay); + top->t_opaque_lsa_self = NULL; + thread_add_timer_msec(master, ospf_opaque_type11_lsa_originate, + top, delay, &top->t_opaque_lsa_self); + delay += top->min_ls_interval; + } + + /* + * Following section treats a special situation that this node's + * opaque capability has changed as "ON -> OFF -> ON". + */ + if (!list_isempty(ospf_opaque_type9_funclist) + && !list_isempty(oi->opaque_lsa_self)) { + for (ALL_LIST_ELEMENTS(oi->opaque_lsa_self, node, nnode, + oipt)) { + /* + * removed the test for + * (! list_isempty (oipt->id_list)) * Handler is + * already active. * + * because opaque cababilities ON -> OFF -> ON result in + * list_isempty (oipt->id_list) + * not being empty. + */ + if ( + oipt->t_opaque_lsa_self + != NULL /* Waiting for a thread call. */ + || oipt->status == PROC_SUSPEND) /* Cannot + originate + now. */ + continue; + + ospf_opaque_lsa_reoriginate_schedule( + (void *)oi, OSPF_OPAQUE_LINK_LSA, + oipt->opaque_type); + } + } + + if (!list_isempty(ospf_opaque_type10_funclist) + && !list_isempty(area->opaque_lsa_self)) { + for (ALL_LIST_ELEMENTS(area->opaque_lsa_self, node, nnode, + oipt)) { + /* + * removed the test for + * (! list_isempty (oipt->id_list)) * Handler is + * already active. * + * because opaque cababilities ON -> OFF -> ON result in + * list_isempty (oipt->id_list) + * not being empty. + */ + if ( + oipt->t_opaque_lsa_self + != NULL /* Waiting for a thread call. */ + || oipt->status == PROC_SUSPEND) /* Cannot + originate + now. */ + continue; + + ospf_opaque_lsa_reoriginate_schedule( + (void *)area, OSPF_OPAQUE_AREA_LSA, + oipt->opaque_type); + } + } + + if (!list_isempty(ospf_opaque_type11_funclist) + && !list_isempty(top->opaque_lsa_self)) { + for (ALL_LIST_ELEMENTS(top->opaque_lsa_self, node, nnode, + oipt)) { + /* + * removed the test for + * (! list_isempty (oipt->id_list)) * Handler is + * already active. * + * because opaque cababilities ON -> OFF -> ON result in + * list_isempty (oipt->id_list) + * not being empty. + */ + if ( + oipt->t_opaque_lsa_self + != NULL /* Waiting for a thread call. */ + || oipt->status == PROC_SUSPEND) /* Cannot + originate + now. */ + continue; + + ospf_opaque_lsa_reoriginate_schedule((void *)top, + OSPF_OPAQUE_AS_LSA, + oipt->opaque_type); + } + } + + if (delay0 != NULL) + *delay0 = delay; out: - return; + return; } -static int -ospf_opaque_type9_lsa_originate (struct thread *t) +static int ospf_opaque_type9_lsa_originate(struct thread *t) { - struct ospf_interface *oi; - int rc; + struct ospf_interface *oi; + int rc; - oi = THREAD_ARG (t); - oi->t_opaque_lsa_self = NULL; + oi = THREAD_ARG(t); + oi->t_opaque_lsa_self = NULL; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s", - IF_NAME (oi)); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Timer[Type9-LSA]: Originate Opaque-LSAs for OI %s", + IF_NAME(oi)); - rc = opaque_lsa_originate_callback (ospf_opaque_type9_funclist, oi); + rc = opaque_lsa_originate_callback(ospf_opaque_type9_funclist, oi); - return rc; + return rc; } -static int -ospf_opaque_type10_lsa_originate (struct thread *t) +static int ospf_opaque_type10_lsa_originate(struct thread *t) { - struct ospf_area *area; - int rc; + struct ospf_area *area; + int rc; - area = THREAD_ARG (t); - area->t_opaque_lsa_self = NULL; + area = THREAD_ARG(t); + area->t_opaque_lsa_self = NULL; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s", - inet_ntoa (area->area_id)); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Timer[Type10-LSA]: Originate Opaque-LSAs for Area %s", + inet_ntoa(area->area_id)); - rc = opaque_lsa_originate_callback (ospf_opaque_type10_funclist, area); + rc = opaque_lsa_originate_callback(ospf_opaque_type10_funclist, area); - return rc; + return rc; } -static int -ospf_opaque_type11_lsa_originate (struct thread *t) +static int ospf_opaque_type11_lsa_originate(struct thread *t) { - struct ospf *top; - int rc; + struct ospf *top; + int rc; - top = THREAD_ARG (t); - top->t_opaque_lsa_self = NULL; + top = THREAD_ARG(t); + top->t_opaque_lsa_self = NULL; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Timer[Type11-LSA]: Originate AS-External Opaque-LSAs"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Timer[Type11-LSA]: Originate AS-External Opaque-LSAs"); - rc = opaque_lsa_originate_callback (ospf_opaque_type11_funclist, top); + rc = opaque_lsa_originate_callback(ospf_opaque_type11_funclist, top); - return rc; + return rc; } -static void -ospf_opaque_lsa_reoriginate_resume (struct list *listtop, void *arg) +static void ospf_opaque_lsa_reoriginate_resume(struct list *listtop, void *arg) { - struct listnode *node, *nnode; - struct opaque_info_per_type *oipt; - struct ospf_opaque_functab *functab; + struct listnode *node, *nnode; + struct opaque_info_per_type *oipt; + struct ospf_opaque_functab *functab; - if (listtop == NULL) - goto out; + if (listtop == NULL) + goto out; - /* - * Pickup oipt entries those which in SUSPEND status, and give - * them a chance to start re-origination now. - */ - for (ALL_LIST_ELEMENTS (listtop, node, nnode, oipt)) - { - if (oipt->status != PROC_SUSPEND) - continue; + /* + * Pickup oipt entries those which in SUSPEND status, and give + * them a chance to start re-origination now. + */ + for (ALL_LIST_ELEMENTS(listtop, node, nnode, oipt)) { + if (oipt->status != PROC_SUSPEND) + continue; - oipt->status = PROC_NORMAL; + oipt->status = PROC_NORMAL; - if ((functab = oipt->functab) == NULL - || functab->lsa_originator == NULL) - continue; + if ((functab = oipt->functab) == NULL + || functab->lsa_originator == NULL) + continue; - if ((* functab->lsa_originator)(arg) != 0) - { - zlog_warn ("ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", oipt->opaque_type); - continue; - } - } + if ((*functab->lsa_originator)(arg) != 0) { + zlog_warn( + "ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)", + oipt->opaque_type); + continue; + } + } out: - return; -} - -struct ospf_lsa * -ospf_opaque_lsa_install (struct ospf_lsa *lsa, int rt_recalc) -{ - struct ospf_lsa *new = NULL; - struct opaque_info_per_type *oipt; - struct opaque_info_per_id *oipi; - struct ospf *top; - - /* Don't take "rt_recalc" into consideration for now. *//* XXX */ - - if (! IS_LSA_SELF (lsa)) - { - new = lsa; /* Don't touch this LSA. */ - goto out; - } - - if (IS_DEBUG_OSPF (lsa, LSA_INSTALL)) - zlog_debug ("Install Type-%u Opaque-LSA: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr))); - - /* Replace the existing lsa with the new one. */ - if ((oipt = lookup_opaque_info_by_type (lsa)) != NULL - && (oipi = lookup_opaque_info_by_id (oipt, lsa)) != NULL) - { - ospf_lsa_unlock (&oipi->lsa); - oipi->lsa = ospf_lsa_lock (lsa); - } - /* Register the new lsa entry and get its control info. */ - else - if ((oipi = register_opaque_lsa (lsa)) == NULL) - { - zlog_warn ("ospf_opaque_lsa_install: register_opaque_lsa() ?"); - goto out; - } - - /* - * Make use of a common mechanism (ospf_lsa_refresh_walker) - * for periodic refresh of self-originated Opaque-LSAs. - */ - switch (lsa->data->type) - { - case OSPF_OPAQUE_LINK_LSA: - if ((top = oi_to_top (lsa->oi)) == NULL) - { - /* Above conditions must have passed. */ - zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?"); - goto out; - } - break; - case OSPF_OPAQUE_AREA_LSA: - if (lsa->area == NULL || (top = lsa->area->ospf) == NULL) - { - /* Above conditions must have passed. */ - zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?"); - goto out; - } - break; - case OSPF_OPAQUE_AS_LSA: - top = ospf_lookup (); - if (lsa->area != NULL && (top = lsa->area->ospf) == NULL) - { - /* Above conditions must have passed. */ - zlog_warn ("ospf_opaque_lsa_install: Sonmething wrong?"); - goto out; - } - break; - default: - zlog_warn ("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", lsa->data->type); - goto out; - } - - ospf_refresher_register_lsa (top, lsa); - new = lsa; + return; +} + +struct ospf_lsa *ospf_opaque_lsa_install(struct ospf_lsa *lsa, int rt_recalc) +{ + struct ospf_lsa *new = NULL; + struct opaque_info_per_type *oipt; + struct opaque_info_per_id *oipi; + struct ospf *top; + + /* Don't take "rt_recalc" into consideration for now. */ /* XXX */ + + if (!IS_LSA_SELF(lsa)) { + new = lsa; /* Don't touch this LSA. */ + goto out; + } + + if (IS_DEBUG_OSPF(lsa, LSA_INSTALL)) + zlog_debug( + "Install Type-%u Opaque-LSA: [opaque-type=%u, opaque-id=%x]", + lsa->data->type, + GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)), + GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr))); + + /* Replace the existing lsa with the new one. */ + if ((oipt = lookup_opaque_info_by_type(lsa)) != NULL + && (oipi = lookup_opaque_info_by_id(oipt, lsa)) != NULL) { + ospf_lsa_unlock(&oipi->lsa); + oipi->lsa = ospf_lsa_lock(lsa); + } + /* Register the new lsa entry and get its control info. */ + else if ((oipi = register_opaque_lsa(lsa)) == NULL) { + zlog_warn("ospf_opaque_lsa_install: register_opaque_lsa() ?"); + goto out; + } + + /* + * Make use of a common mechanism (ospf_lsa_refresh_walker) + * for periodic refresh of self-originated Opaque-LSAs. + */ + switch (lsa->data->type) { + case OSPF_OPAQUE_LINK_LSA: + if ((top = oi_to_top(lsa->oi)) == NULL) { + /* Above conditions must have passed. */ + zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?"); + goto out; + } + break; + case OSPF_OPAQUE_AREA_LSA: + if (lsa->area == NULL || (top = lsa->area->ospf) == NULL) { + /* Above conditions must have passed. */ + zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?"); + goto out; + } + break; + case OSPF_OPAQUE_AS_LSA: + top = ospf_lookup(); + if (lsa->area != NULL && (top = lsa->area->ospf) == NULL) { + /* Above conditions must have passed. */ + zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?"); + goto out; + } + break; + default: + zlog_warn("ospf_opaque_lsa_install: Unexpected LSA-type(%u)", + lsa->data->type); + goto out; + } + + ospf_refresher_register_lsa(top, lsa); + new = lsa; out: - return new; + return new; } -struct ospf_lsa * -ospf_opaque_lsa_refresh (struct ospf_lsa *lsa) +struct ospf_lsa *ospf_opaque_lsa_refresh(struct ospf_lsa *lsa) { - struct ospf *ospf; - struct ospf_opaque_functab *functab; - struct ospf_lsa *new = NULL; - - ospf = ospf_lookup (); + struct ospf *ospf; + struct ospf_opaque_functab *functab; + struct ospf_lsa *new = NULL; + + ospf = ospf_lookup(); - if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL - || functab->lsa_refresher == NULL) - { - /* - * Though this LSA seems to have originated on this node, the - * handling module for this "lsa-type and opaque-type" was - * already deleted sometime ago. - * Anyway, this node still has a responsibility to flush this - * LSA from the routing domain. - */ - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[Type%d:%s]: Flush stray Opaque-LSA", lsa->data->type, inet_ntoa (lsa->data->id)); + if ((functab = ospf_opaque_functab_lookup(lsa)) == NULL + || functab->lsa_refresher == NULL) { + /* + * Though this LSA seems to have originated on this node, the + * handling module for this "lsa-type and opaque-type" was + * already deleted sometime ago. + * Anyway, this node still has a responsibility to flush this + * LSA from the routing domain. + */ + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("LSA[Type%d:%s]: Flush stray Opaque-LSA", + lsa->data->type, inet_ntoa(lsa->data->id)); - lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); - ospf_lsa_flush (ospf, lsa); - } - else - new = (* functab->lsa_refresher)(lsa); + lsa->data->ls_age = htons(OSPF_LSA_MAXAGE); + ospf_lsa_flush(ospf, lsa); + } else + new = (*functab->lsa_refresher)(lsa); - return new; + return new; } /*------------------------------------------------------------------------* @@ -1655,521 +1627,536 @@ ospf_opaque_lsa_refresh (struct ospf_lsa *lsa) #define OSPF_OPAQUE_TIMER_ON(T,F,L,V) thread_add_timer_msec (master, (F), (L), (V), &(T)) -static struct ospf_lsa *pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, u_char lsa_type, u_char opaque_type); -static int ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t); -static int ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t); -static int ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t); -static int ospf_opaque_lsa_refresh_timer (struct thread *t); - -void -ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent, - u_char lsa_type, u_char opaque_type) -{ - struct ospf *top; - struct ospf_area dummy, *area = NULL; - struct ospf_interface *oi = NULL; - - struct ospf_lsa *lsa; - struct opaque_info_per_type *oipt; - int (*func) (struct thread * t) = NULL; - int delay; - - switch (lsa_type) - { - case OSPF_OPAQUE_LINK_LSA: - if ((oi = (struct ospf_interface *) lsa_type_dependent) == NULL) - { - zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:" - " Type-9 Opaque-LSA: Invalid parameter?"); - goto out; - } - if ((top = oi_to_top (oi)) == NULL) - { - zlog_warn ("ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?", - IF_NAME (oi)); - goto out; - } - if (!list_isempty (ospf_opaque_type9_funclist) - && list_isempty (oi->opaque_lsa_self) - && oi->t_opaque_lsa_self != NULL) - { - zlog_warn ("Type-9 Opaque-LSA (opaque_type=%u):" - " Common origination for OI(%s) has already started", - opaque_type, IF_NAME (oi)); - goto out; - } - func = ospf_opaque_type9_lsa_reoriginate_timer; - break; - case OSPF_OPAQUE_AREA_LSA: - if ((area = (struct ospf_area *) lsa_type_dependent) == NULL) - { - zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:" - " Type-10 Opaque-LSA: Invalid parameter?"); - goto out; - } - if ((top = area->ospf) == NULL) - { - zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:" - " AREA(%s) -> TOP?", inet_ntoa (area->area_id)); - goto out; - } - if (!list_isempty (ospf_opaque_type10_funclist) - && list_isempty (area->opaque_lsa_self) - && area->t_opaque_lsa_self != NULL) - { - zlog_warn ("Type-10 Opaque-LSA (opaque_type=%u):" - " Common origination for AREA(%s) has already started", - opaque_type, inet_ntoa (area->area_id)); - goto out; - } - func = ospf_opaque_type10_lsa_reoriginate_timer; - break; - case OSPF_OPAQUE_AS_LSA: - if ((top = (struct ospf *) lsa_type_dependent) == NULL) - { - zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:" - " Type-11 Opaque-LSA: Invalid parameter?"); - goto out; - } - if (!list_isempty (ospf_opaque_type11_funclist) - && list_isempty (top->opaque_lsa_self) - && top->t_opaque_lsa_self != NULL) - { - zlog_warn ("Type-11 Opaque-LSA (opaque_type=%u):" - " Common origination has already started", opaque_type); - goto out; - } - - /* Fake "area" to pass "ospf" to a lookup function later. */ - dummy.ospf = top; - area = &dummy; - - func = ospf_opaque_type11_lsa_reoriginate_timer; - break; - default: - zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:" - " Unexpected LSA-type(%u)", - lsa_type); - goto out; - } - - /* It may not a right time to schedule reorigination now. */ - if (!CHECK_FLAG (top->opaque, OPAQUE_OPERATION_READY_BIT)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Not operational."); - goto out; /* This is not an error. */ - } - - /* Generate a dummy lsa to be passed for a lookup function. */ - lsa = pseudo_lsa (oi, area, lsa_type, opaque_type); - - if ((oipt = lookup_opaque_info_by_type (lsa)) == NULL) - { - struct ospf_opaque_functab *functab; - if ((functab = ospf_opaque_functab_lookup (lsa)) == NULL) - { - zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:" - " No associated function?: lsa_type(%u)," - " opaque_type(%u)", - lsa_type, opaque_type); - goto out; - } - if ((oipt = register_opaque_info_per_type (functab, lsa)) == NULL) - { - zlog_warn ("ospf_opaque_lsa_reoriginate_schedule:" - " Cannot get a control info?: lsa_type(%u)," - " opaque_type(%u)", - lsa_type, opaque_type); - goto out; - } - } - - if (oipt->t_opaque_lsa_self != NULL) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Type-%u Opaque-LSA has already scheduled to" - " RE-ORIGINATE: [opaque-type=%u]", - lsa_type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr))); - goto out; - } - - /* - * Different from initial origination time, in which various conditions - * (opaque capability, neighbor status etc) are assured by caller of - * the originating function "ospf_opaque_lsa_originate_schedule ()", - * it is highly possible that these conditions might not be satisfied - * at the time of re-origination function is to be called. - */ - delay = top->min_ls_interval; /* XXX */ - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d" - " ms later: [opaque-type=%u]", - lsa_type, delay, - GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr))); - - OSPF_OPAQUE_TIMER_ON (oipt->t_opaque_lsa_self, func, oipt, delay * 1000); +static struct ospf_lsa *pseudo_lsa(struct ospf_interface *oi, + struct ospf_area *area, u_char lsa_type, + u_char opaque_type); +static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread *t); +static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread *t); +static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread *t); +static int ospf_opaque_lsa_refresh_timer(struct thread *t); + +void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent, + u_char lsa_type, u_char opaque_type) +{ + struct ospf *top; + struct ospf_area dummy, *area = NULL; + struct ospf_interface *oi = NULL; + + struct ospf_lsa *lsa; + struct opaque_info_per_type *oipt; + int (*func)(struct thread * t) = NULL; + int delay; + + switch (lsa_type) { + case OSPF_OPAQUE_LINK_LSA: + if ((oi = (struct ospf_interface *)lsa_type_dependent) + == NULL) { + zlog_warn( + "ospf_opaque_lsa_reoriginate_schedule:" + " Type-9 Opaque-LSA: Invalid parameter?"); + goto out; + } + if ((top = oi_to_top(oi)) == NULL) { + zlog_warn( + "ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?", + IF_NAME(oi)); + goto out; + } + if (!list_isempty(ospf_opaque_type9_funclist) + && list_isempty(oi->opaque_lsa_self) + && oi->t_opaque_lsa_self != NULL) { + zlog_warn( + "Type-9 Opaque-LSA (opaque_type=%u):" + " Common origination for OI(%s) has already started", + opaque_type, IF_NAME(oi)); + goto out; + } + func = ospf_opaque_type9_lsa_reoriginate_timer; + break; + case OSPF_OPAQUE_AREA_LSA: + if ((area = (struct ospf_area *)lsa_type_dependent) == NULL) { + zlog_warn( + "ospf_opaque_lsa_reoriginate_schedule:" + " Type-10 Opaque-LSA: Invalid parameter?"); + goto out; + } + if ((top = area->ospf) == NULL) { + zlog_warn( + "ospf_opaque_lsa_reoriginate_schedule:" + " AREA(%s) -> TOP?", + inet_ntoa(area->area_id)); + goto out; + } + if (!list_isempty(ospf_opaque_type10_funclist) + && list_isempty(area->opaque_lsa_self) + && area->t_opaque_lsa_self != NULL) { + zlog_warn( + "Type-10 Opaque-LSA (opaque_type=%u):" + " Common origination for AREA(%s) has already started", + opaque_type, inet_ntoa(area->area_id)); + goto out; + } + func = ospf_opaque_type10_lsa_reoriginate_timer; + break; + case OSPF_OPAQUE_AS_LSA: + if ((top = (struct ospf *)lsa_type_dependent) == NULL) { + zlog_warn( + "ospf_opaque_lsa_reoriginate_schedule:" + " Type-11 Opaque-LSA: Invalid parameter?"); + goto out; + } + if (!list_isempty(ospf_opaque_type11_funclist) + && list_isempty(top->opaque_lsa_self) + && top->t_opaque_lsa_self != NULL) { + zlog_warn( + "Type-11 Opaque-LSA (opaque_type=%u):" + " Common origination has already started", + opaque_type); + goto out; + } + + /* Fake "area" to pass "ospf" to a lookup function later. */ + dummy.ospf = top; + area = &dummy; + + func = ospf_opaque_type11_lsa_reoriginate_timer; + break; + default: + zlog_warn( + "ospf_opaque_lsa_reoriginate_schedule:" + " Unexpected LSA-type(%u)", + lsa_type); + goto out; + } + + /* It may not a right time to schedule reorigination now. */ + if (!CHECK_FLAG(top->opaque, OPAQUE_OPERATION_READY_BIT)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_opaque_lsa_reoriginate_schedule: Not operational."); + goto out; /* This is not an error. */ + } + + /* Generate a dummy lsa to be passed for a lookup function. */ + lsa = pseudo_lsa(oi, area, lsa_type, opaque_type); + + if ((oipt = lookup_opaque_info_by_type(lsa)) == NULL) { + struct ospf_opaque_functab *functab; + if ((functab = ospf_opaque_functab_lookup(lsa)) == NULL) { + zlog_warn( + "ospf_opaque_lsa_reoriginate_schedule:" + " No associated function?: lsa_type(%u)," + " opaque_type(%u)", + lsa_type, opaque_type); + goto out; + } + if ((oipt = register_opaque_info_per_type(functab, lsa)) + == NULL) { + zlog_warn( + "ospf_opaque_lsa_reoriginate_schedule:" + " Cannot get a control info?: lsa_type(%u)," + " opaque_type(%u)", + lsa_type, opaque_type); + goto out; + } + } + + if (oipt->t_opaque_lsa_self != NULL) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Type-%u Opaque-LSA has already scheduled to" + " RE-ORIGINATE: [opaque-type=%u]", + lsa_type, + GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr))); + goto out; + } + + /* + * Different from initial origination time, in which various conditions + * (opaque capability, neighbor status etc) are assured by caller of + * the originating function "ospf_opaque_lsa_originate_schedule ()", + * it is highly possible that these conditions might not be satisfied + * at the time of re-origination function is to be called. + */ + delay = top->min_ls_interval; /* XXX */ + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Schedule Type-%u Opaque-LSA to RE-ORIGINATE in %d" + " ms later: [opaque-type=%u]", + lsa_type, delay, + GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr))); + + OSPF_OPAQUE_TIMER_ON(oipt->t_opaque_lsa_self, func, oipt, delay * 1000); out: - return; -} - -static struct ospf_lsa * -pseudo_lsa (struct ospf_interface *oi, struct ospf_area *area, - u_char lsa_type, u_char opaque_type) -{ - static struct ospf_lsa lsa = { 0 }; - static struct lsa_header lsah = { 0 }; - u_int32_t tmp; - - lsa.oi = oi; - lsa.area = area; - lsa.data = &lsah; - - lsah.type = lsa_type; - tmp = SET_OPAQUE_LSID (opaque_type, 0); /* Opaque-ID is unused here. */ - lsah.id.s_addr = htonl (tmp); - - return &lsa; -} - -static int -ospf_opaque_type9_lsa_reoriginate_timer (struct thread *t) -{ - struct opaque_info_per_type *oipt; - struct ospf_opaque_functab *functab; - struct ospf *top; - struct ospf_interface *oi; - int rc = -1; - - oipt = THREAD_ARG (t); - oipt->t_opaque_lsa_self = NULL; - - if ((functab = oipt->functab) == NULL - || functab->lsa_originator == NULL) - { - zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: No associated function?"); - goto out; - } - - oi = (struct ospf_interface *) oipt->owner; - if ((top = oi_to_top (oi)) == NULL) - { - zlog_warn ("ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?"); - goto out; - } - - if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE) - || ! ospf_if_is_enable (oi) - || ospf_nbr_count_opaque_capable (oi) == 0) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type); - - oipt->status = PROC_SUSPEND; - rc = 0; - goto out; - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", oipt->opaque_type, IF_NAME (oi)); - - rc = (* functab->lsa_originator)(oi); + return; +} + +static struct ospf_lsa *pseudo_lsa(struct ospf_interface *oi, + struct ospf_area *area, u_char lsa_type, + u_char opaque_type) +{ + static struct ospf_lsa lsa = {0}; + static struct lsa_header lsah = {0}; + u_int32_t tmp; + + lsa.oi = oi; + lsa.area = area; + lsa.data = &lsah; + + lsah.type = lsa_type; + tmp = SET_OPAQUE_LSID(opaque_type, 0); /* Opaque-ID is unused here. */ + lsah.id.s_addr = htonl(tmp); + + return &lsa; +} + +static int ospf_opaque_type9_lsa_reoriginate_timer(struct thread *t) +{ + struct opaque_info_per_type *oipt; + struct ospf_opaque_functab *functab; + struct ospf *top; + struct ospf_interface *oi; + int rc = -1; + + oipt = THREAD_ARG(t); + oipt->t_opaque_lsa_self = NULL; + + if ((functab = oipt->functab) == NULL + || functab->lsa_originator == NULL) { + zlog_warn( + "ospf_opaque_type9_lsa_reoriginate_timer: No associated function?"); + goto out; + } + + oi = (struct ospf_interface *)oipt->owner; + if ((top = oi_to_top(oi)) == NULL) { + zlog_warn( + "ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?"); + goto out; + } + + if (!CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE) + || !ospf_if_is_enable(oi) + || ospf_nbr_count_opaque_capable(oi) == 0) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Suspend re-origination of Type-9 Opaque-LSAs (opaque-type=%u) for a while...", + oipt->opaque_type); + + oipt->status = PROC_SUSPEND; + rc = 0; + goto out; + } + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Timer[Type9-LSA]: Re-originate Opaque-LSAs (opaque-type=%u) for OI (%s)", + oipt->opaque_type, IF_NAME(oi)); + + rc = (*functab->lsa_originator)(oi); out: - return rc; -} - -static int -ospf_opaque_type10_lsa_reoriginate_timer (struct thread *t) -{ - struct opaque_info_per_type *oipt; - struct ospf_opaque_functab *functab; - struct listnode *node, *nnode; - struct ospf *top; - struct ospf_area *area; - struct ospf_interface *oi; - int n, rc = -1; - - oipt = THREAD_ARG (t); - oipt->t_opaque_lsa_self = NULL; - - if ((functab = oipt->functab) == NULL - || functab->lsa_originator == NULL) - { - zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: No associated function?"); - goto out; - } - - area = (struct ospf_area *) oipt->owner; - if (area == NULL || (top = area->ospf) == NULL) - { - zlog_warn ("ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?"); - goto out; - } - - /* There must be at least one "opaque-capable, full-state" neighbor. */ - n = 0; - for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi)) - { - if ((n = ospf_nbr_count_opaque_capable (oi)) > 0) - break; - } - - if (n == 0 || ! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Suspend re-origination of Type-10 Opaque-LSAs" - " (opaque-type=%u) for a while...", - oipt->opaque_type); - - oipt->status = PROC_SUSPEND; - rc = 0; - goto out; - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Timer[Type10-LSA]: Re-originate Opaque-LSAs" - " (opaque-type=%u) for Area %s", - oipt->opaque_type, inet_ntoa (area->area_id)); - - rc = (* functab->lsa_originator)(area); + return rc; +} + +static int ospf_opaque_type10_lsa_reoriginate_timer(struct thread *t) +{ + struct opaque_info_per_type *oipt; + struct ospf_opaque_functab *functab; + struct listnode *node, *nnode; + struct ospf *top; + struct ospf_area *area; + struct ospf_interface *oi; + int n, rc = -1; + + oipt = THREAD_ARG(t); + oipt->t_opaque_lsa_self = NULL; + + if ((functab = oipt->functab) == NULL + || functab->lsa_originator == NULL) { + zlog_warn( + "ospf_opaque_type10_lsa_reoriginate_timer: No associated function?"); + goto out; + } + + area = (struct ospf_area *)oipt->owner; + if (area == NULL || (top = area->ospf) == NULL) { + zlog_warn( + "ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?"); + goto out; + } + + /* There must be at least one "opaque-capable, full-state" neighbor. */ + n = 0; + for (ALL_LIST_ELEMENTS(area->oiflist, node, nnode, oi)) { + if ((n = ospf_nbr_count_opaque_capable(oi)) > 0) + break; + } + + if (n == 0 || !CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Suspend re-origination of Type-10 Opaque-LSAs" + " (opaque-type=%u) for a while...", + oipt->opaque_type); + + oipt->status = PROC_SUSPEND; + rc = 0; + goto out; + } + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Timer[Type10-LSA]: Re-originate Opaque-LSAs" + " (opaque-type=%u) for Area %s", + oipt->opaque_type, inet_ntoa(area->area_id)); + + rc = (*functab->lsa_originator)(area); out: - return rc; -} - -static int -ospf_opaque_type11_lsa_reoriginate_timer (struct thread *t) -{ - struct opaque_info_per_type *oipt; - struct ospf_opaque_functab *functab; - struct ospf *top; - int rc = -1; - - oipt = THREAD_ARG (t); - oipt->t_opaque_lsa_self = NULL; - - if ((functab = oipt->functab) == NULL - || functab->lsa_originator == NULL) - { - zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer:" - " No associated function?"); - goto out; - } - - if ((top = (struct ospf *) oipt->owner) == NULL) - { - zlog_warn ("ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?"); - goto out; - } - - if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", oipt->opaque_type); - - oipt->status = PROC_SUSPEND; - rc = 0; - goto out; - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", oipt->opaque_type); - - rc = (* functab->lsa_originator)(top); + return rc; +} + +static int ospf_opaque_type11_lsa_reoriginate_timer(struct thread *t) +{ + struct opaque_info_per_type *oipt; + struct ospf_opaque_functab *functab; + struct ospf *top; + int rc = -1; + + oipt = THREAD_ARG(t); + oipt->t_opaque_lsa_self = NULL; + + if ((functab = oipt->functab) == NULL + || functab->lsa_originator == NULL) { + zlog_warn( + "ospf_opaque_type11_lsa_reoriginate_timer:" + " No associated function?"); + goto out; + } + + if ((top = (struct ospf *)oipt->owner) == NULL) { + zlog_warn( + "ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?"); + goto out; + } + + if (!CHECK_FLAG(top->config, OSPF_OPAQUE_CAPABLE)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Suspend re-origination of Type-11 Opaque-LSAs (opaque-type=%u) for a while...", + oipt->opaque_type); + + oipt->status = PROC_SUSPEND; + rc = 0; + goto out; + } + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Timer[Type11-LSA]: Re-originate Opaque-LSAs (opaque-type=%u).", + oipt->opaque_type); + + rc = (*functab->lsa_originator)(top); out: - return rc; -} - -void -ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa0) -{ - struct opaque_info_per_type *oipt; - struct opaque_info_per_id *oipi; - struct ospf_lsa *lsa; - struct ospf *top; - int delay; - - if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL - || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL) - { - zlog_warn ("ospf_opaque_lsa_refresh_schedule: Invalid parameter?"); - goto out; - } - - /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */ - if ((lsa = oipi->lsa) == NULL) - { - zlog_warn ("ospf_opaque_lsa_refresh_schedule: Something wrong?"); - goto out; - } - - if (oipi->t_opaque_lsa_self != NULL) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr))); - goto out; - } - - /* Delete this lsa from neighbor retransmit-list. */ - switch (lsa->data->type) - { - case OSPF_OPAQUE_LINK_LSA: - case OSPF_OPAQUE_AREA_LSA: - ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa); - break; - case OSPF_OPAQUE_AS_LSA: - top = ospf_lookup (); - if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL)) - top = lsa0->area->ospf; - ospf_ls_retransmit_delete_nbr_as (top, lsa); - break; - default: - zlog_warn ("ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", lsa->data->type); - goto out; - } - - delay = ospf_lsa_refresh_delay (lsa); - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]", lsa->data->type, delay, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr))); - - OSPF_OPAQUE_TIMER_ON (oipi->t_opaque_lsa_self, - ospf_opaque_lsa_refresh_timer, oipi, delay * 1000); + return rc; +} + +void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa *lsa0) +{ + struct opaque_info_per_type *oipt; + struct opaque_info_per_id *oipi; + struct ospf_lsa *lsa; + struct ospf *top; + int delay; + + if ((oipt = lookup_opaque_info_by_type(lsa0)) == NULL + || (oipi = lookup_opaque_info_by_id(oipt, lsa0)) == NULL) { + zlog_warn( + "ospf_opaque_lsa_refresh_schedule: Invalid parameter?"); + goto out; + } + + /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */ + if ((lsa = oipi->lsa) == NULL) { + zlog_warn("ospf_opaque_lsa_refresh_schedule: Something wrong?"); + goto out; + } + + if (oipi->t_opaque_lsa_self != NULL) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Type-%u Opaque-LSA has already scheduled to REFRESH: [opaque-type=%u, opaque-id=%x]", + lsa->data->type, + GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)), + GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr))); + goto out; + } + + /* Delete this lsa from neighbor retransmit-list. */ + switch (lsa->data->type) { + case OSPF_OPAQUE_LINK_LSA: + case OSPF_OPAQUE_AREA_LSA: + ospf_ls_retransmit_delete_nbr_area(lsa->area, lsa); + break; + case OSPF_OPAQUE_AS_LSA: + top = ospf_lookup(); + if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL)) + top = lsa0->area->ospf; + ospf_ls_retransmit_delete_nbr_as(top, lsa); + break; + default: + zlog_warn( + "ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)", + lsa->data->type); + goto out; + } + + delay = ospf_lsa_refresh_delay(lsa); + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Schedule Type-%u Opaque-LSA to REFRESH in %d sec later: [opaque-type=%u, opaque-id=%x]", + lsa->data->type, delay, + GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)), + GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr))); + + OSPF_OPAQUE_TIMER_ON(oipi->t_opaque_lsa_self, + ospf_opaque_lsa_refresh_timer, oipi, delay * 1000); out: - return; + return; } -static int -ospf_opaque_lsa_refresh_timer (struct thread *t) +static int ospf_opaque_lsa_refresh_timer(struct thread *t) { - struct opaque_info_per_id *oipi; - struct ospf_opaque_functab *functab; - struct ospf_lsa *lsa; + struct opaque_info_per_id *oipi; + struct ospf_opaque_functab *functab; + struct ospf_lsa *lsa; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Timer[Opaque-LSA]: (Opaque-LSA Refresh expire)"); - oipi = THREAD_ARG (t); - oipi->t_opaque_lsa_self = NULL; + oipi = THREAD_ARG(t); + oipi->t_opaque_lsa_self = NULL; - if ((lsa = oipi->lsa) != NULL) - if ((functab = oipi->opqctl_type->functab) != NULL) - if (functab->lsa_refresher != NULL) - (* functab->lsa_refresher)(lsa); + if ((lsa = oipi->lsa) != NULL) + if ((functab = oipi->opqctl_type->functab) != NULL) + if (functab->lsa_refresher != NULL) + (*functab->lsa_refresher)(lsa); - return 0; + return 0; } -void -ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa0) +void ospf_opaque_lsa_flush_schedule(struct ospf_lsa *lsa0) { - struct opaque_info_per_type *oipt; - struct opaque_info_per_id *oipi; - struct ospf_lsa *lsa; - struct ospf *top; + struct opaque_info_per_type *oipt; + struct opaque_info_per_id *oipi; + struct ospf_lsa *lsa; + struct ospf *top; - top = ospf_lookup (); + top = ospf_lookup(); - if ((oipt = lookup_opaque_info_by_type (lsa0)) == NULL - || (oipi = lookup_opaque_info_by_id (oipt, lsa0)) == NULL) - { - zlog_warn ("ospf_opaque_lsa_flush_schedule: Invalid parameter?"); - goto out; - } + if ((oipt = lookup_opaque_info_by_type(lsa0)) == NULL + || (oipi = lookup_opaque_info_by_id(oipt, lsa0)) == NULL) { + zlog_warn("ospf_opaque_lsa_flush_schedule: Invalid parameter?"); + goto out; + } - /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */ - if ((lsa = oipi->lsa) == NULL) - { - zlog_warn ("ospf_opaque_lsa_flush_schedule: Something wrong?"); - goto out; - } + /* Given "lsa0" and current "oipi->lsa" may different, but harmless. */ + if ((lsa = oipi->lsa) == NULL) { + zlog_warn("ospf_opaque_lsa_flush_schedule: Something wrong?"); + goto out; + } - /* Delete this lsa from neighbor retransmit-list. */ - switch (lsa->data->type) - { - case OSPF_OPAQUE_LINK_LSA: - case OSPF_OPAQUE_AREA_LSA: - ospf_ls_retransmit_delete_nbr_area (lsa->area, lsa); - break; - case OSPF_OPAQUE_AS_LSA: - if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL)) - top = lsa0->area->ospf; - ospf_ls_retransmit_delete_nbr_as (top, lsa); - break; - default: - zlog_warn ("ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", lsa->data->type); - goto out; - } + /* Delete this lsa from neighbor retransmit-list. */ + switch (lsa->data->type) { + case OSPF_OPAQUE_LINK_LSA: + case OSPF_OPAQUE_AREA_LSA: + ospf_ls_retransmit_delete_nbr_area(lsa->area, lsa); + break; + case OSPF_OPAQUE_AS_LSA: + if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL)) + top = lsa0->area->ospf; + ospf_ls_retransmit_delete_nbr_as(top, lsa); + break; + default: + zlog_warn( + "ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)", + lsa->data->type); + goto out; + } - /* Dequeue listnode entry from the list. */ - listnode_delete (oipt->id_list, oipi); + /* Dequeue listnode entry from the list. */ + listnode_delete(oipt->id_list, oipi); - /* Avoid misjudgement in the next lookup. */ - if (listcount (oipt->id_list) == 0) - oipt->id_list->head = oipt->id_list->tail = NULL; + /* Avoid misjudgement in the next lookup. */ + if (listcount(oipt->id_list) == 0) + oipt->id_list->head = oipt->id_list->tail = NULL; - /* Disassociate internal control information with the given lsa. */ - free_opaque_info_per_id ((void *) oipi); + /* Disassociate internal control information with the given lsa. */ + free_opaque_info_per_id((void *)oipi); - /* Force given lsa's age to MaxAge. */ - lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); + /* Force given lsa's age to MaxAge. */ + lsa->data->ls_age = htons(OSPF_LSA_MAXAGE); - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]", lsa->data->type, GET_OPAQUE_TYPE (ntohl (lsa->data->id.s_addr)), GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr))); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Schedule Type-%u Opaque-LSA to FLUSH: [opaque-type=%u, opaque-id=%x]", + lsa->data->type, + GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr)), + GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr))); - /* This lsa will be flushed and removed eventually. */ - ospf_lsa_flush (top, lsa); + /* This lsa will be flushed and removed eventually. */ + ospf_lsa_flush(top, lsa); out: - return; -} - -void -ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr, - struct ospf_lsa *lsa) -{ - struct ospf *top; - - if ((top = oi_to_top (nbr->oi)) == NULL) - return; - - /* - * Since these LSA entries are not yet installed into corresponding - * LSDB, just flush them without calling ospf_ls_maxage() afterward. - */ - lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); - switch (lsa->data->type) - { - case OSPF_OPAQUE_LINK_LSA: - ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa); - break; - case OSPF_OPAQUE_AREA_LSA: - ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa); - break; - case OSPF_OPAQUE_AS_LSA: - ospf_flood_through_as (top, NULL/*inbr*/, lsa); - break; - default: - zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type); - return; - } - ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */ + return; +} + +void ospf_opaque_self_originated_lsa_received(struct ospf_neighbor *nbr, + struct ospf_lsa *lsa) +{ + struct ospf *top; + + if ((top = oi_to_top(nbr->oi)) == NULL) + return; + + /* + * Since these LSA entries are not yet installed into corresponding + * LSDB, just flush them without calling ospf_ls_maxage() afterward. + */ + lsa->data->ls_age = htons(OSPF_LSA_MAXAGE); + switch (lsa->data->type) { + case OSPF_OPAQUE_LINK_LSA: + ospf_flood_through_area(nbr->oi->area, NULL /*inbr*/, lsa); + break; + case OSPF_OPAQUE_AREA_LSA: + ospf_flood_through_area(nbr->oi->area, NULL /*inbr*/, lsa); + break; + case OSPF_OPAQUE_AS_LSA: + ospf_flood_through_as(top, NULL /*inbr*/, lsa); + break; + default: + zlog_warn( + "ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", + lsa->data->type); + return; + } + ospf_lsa_discard(lsa); /* List "lsas" will be deleted by caller. */ } /*------------------------------------------------------------------------* * Followings are util functions; probably be used by Opaque-LSAs only... *------------------------------------------------------------------------*/ -struct ospf * -oi_to_top (struct ospf_interface *oi) +struct ospf *oi_to_top(struct ospf_interface *oi) { - struct ospf *top = NULL; - struct ospf_area *area; + struct ospf *top = NULL; + struct ospf_area *area; - if (oi == NULL || (area = oi->area) == NULL || (top = area->ospf) == NULL) - zlog_warn ("Broken relationship for \"OI -> AREA -> OSPF\"?"); + if (oi == NULL || (area = oi->area) == NULL + || (top = area->ospf) == NULL) + zlog_warn("Broken relationship for \"OI -> AREA -> OSPF\"?"); - return top; + return top; } - diff --git a/ospfd/ospf_opaque.h b/ospfd/ospf_opaque.h index 69cbb0766..8bad51e65 100644 --- a/ospfd/ospf_opaque.h +++ b/ospfd/ospf_opaque.h @@ -25,10 +25,9 @@ #include "vty.h" -#define IS_OPAQUE_LSA(type) \ - ((type) == OSPF_OPAQUE_LINK_LSA || \ - (type) == OSPF_OPAQUE_AREA_LSA || \ - (type) == OSPF_OPAQUE_AS_LSA) +#define IS_OPAQUE_LSA(type) \ + ((type) == OSPF_OPAQUE_LINK_LSA || (type) == OSPF_OPAQUE_AREA_LSA \ + || (type) == OSPF_OPAQUE_AS_LSA) /* * Opaque LSA's link state ID is redefined as follows. @@ -42,15 +41,12 @@ #define LSID_OPAQUE_TYPE_MASK 0xff000000 /* 8 bits */ #define LSID_OPAQUE_ID_MASK 0x00ffffff /* 24 bits */ -#define GET_OPAQUE_TYPE(lsid) \ - (((u_int32_t)(lsid) & LSID_OPAQUE_TYPE_MASK) >> 24) +#define GET_OPAQUE_TYPE(lsid) (((u_int32_t)(lsid)&LSID_OPAQUE_TYPE_MASK) >> 24) -#define GET_OPAQUE_ID(lsid) \ - ((u_int32_t)(lsid) & LSID_OPAQUE_ID_MASK) +#define GET_OPAQUE_ID(lsid) ((u_int32_t)(lsid)&LSID_OPAQUE_ID_MASK) -#define SET_OPAQUE_LSID(type, id) \ - ((((type) << 24) & LSID_OPAQUE_TYPE_MASK) \ - | ((id) & LSID_OPAQUE_ID_MASK)) +#define SET_OPAQUE_LSID(type, id) \ + ((((type) << 24) & LSID_OPAQUE_TYPE_MASK) | ((id)&LSID_OPAQUE_ID_MASK)) /* * Opaque LSA types will be assigned by IANA. @@ -72,74 +68,66 @@ /* Ugly hack to make use of an unallocated value for wildcard matching! */ #define OPAQUE_TYPE_WILDCARD 0 -#define OPAQUE_TYPE_RANGE_UNASSIGNED(type) \ - ( OPAQUE_TYPE_MAX <= (type) && (type) <= 127) +#define OPAQUE_TYPE_RANGE_UNASSIGNED(type) \ + (OPAQUE_TYPE_MAX <= (type) && (type) <= 127) -#define OPAQUE_TYPE_RANGE_RESERVED(type) \ - (127 < (type) && (type) <= 255) +#define OPAQUE_TYPE_RANGE_RESERVED(type) (127 < (type) && (type) <= 255) -#define VALID_OPAQUE_INFO_LEN(lsahdr) \ - ((ntohs((lsahdr)->length) >= sizeof (struct lsa_header)) && \ - ((ntohs((lsahdr)->length) % sizeof (u_int32_t)) == 0)) +#define VALID_OPAQUE_INFO_LEN(lsahdr) \ + ((ntohs((lsahdr)->length) >= sizeof(struct lsa_header)) \ + && ((ntohs((lsahdr)->length) % sizeof(u_int32_t)) == 0)) /* Prototypes. */ -extern void ospf_opaque_init (void); -extern void ospf_opaque_term (void); -extern int ospf_opaque_type9_lsa_init (struct ospf_interface *oi); -extern void ospf_opaque_type9_lsa_term (struct ospf_interface *oi); -extern int ospf_opaque_type10_lsa_init (struct ospf_area *area); -extern void ospf_opaque_type10_lsa_term (struct ospf_area *area); -extern int ospf_opaque_type11_lsa_init (struct ospf *ospf); -extern void ospf_opaque_type11_lsa_term (struct ospf *ospf); - -extern int -ospf_register_opaque_functab ( - u_char lsa_type, - u_char opaque_type, - int (* new_if_hook)(struct interface *ifp), - int (* del_if_hook)(struct interface *ifp), - void (* ism_change_hook)(struct ospf_interface *oi, int old_status), - void (* nsm_change_hook)(struct ospf_neighbor *nbr, int old_status), - void (* config_write_router)(struct vty *vty), - void (* config_write_if )(struct vty *vty, struct interface *ifp), - void (* config_write_debug )(struct vty *vty), - void (* show_opaque_info )(struct vty *vty, struct ospf_lsa *lsa), - int (* lsa_originator)(void *arg), - struct ospf_lsa *(* lsa_refresher )(struct ospf_lsa *lsa), - int (* new_lsa_hook)(struct ospf_lsa *lsa), - int (* del_lsa_hook)(struct ospf_lsa *lsa) -); -extern void ospf_delete_opaque_functab (u_char lsa_type, u_char opaque_type); - -extern int ospf_opaque_new_if (struct interface *ifp); -extern int ospf_opaque_del_if (struct interface *ifp); -extern void ospf_opaque_ism_change (struct ospf_interface *oi, - int old_status); -extern void ospf_opaque_nsm_change (struct ospf_neighbor *nbr, - int old_status); -extern void ospf_opaque_config_write_router (struct vty *vty, struct ospf *); -extern void ospf_opaque_config_write_if (struct vty *vty, - struct interface *ifp); -extern void ospf_opaque_config_write_debug (struct vty *vty); -extern void show_opaque_info_detail (struct vty *vty, struct ospf_lsa *lsa); -extern void ospf_opaque_lsa_dump (struct stream *s, u_int16_t length); - -extern void ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, - int *init_delay); -extern struct ospf_lsa *ospf_opaque_lsa_install (struct ospf_lsa *, - int rt_recalc); -extern struct ospf_lsa *ospf_opaque_lsa_refresh (struct ospf_lsa *lsa); - -extern void ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent, - u_char lsa_type, - u_char opaque_type); -extern void ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa); -extern void ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa); - -extern void ospf_opaque_self_originated_lsa_received (struct ospf_neighbor - *nbr, - struct ospf_lsa *lsa); -extern struct ospf *oi_to_top (struct ospf_interface *oi); +extern void ospf_opaque_init(void); +extern void ospf_opaque_term(void); +extern int ospf_opaque_type9_lsa_init(struct ospf_interface *oi); +extern void ospf_opaque_type9_lsa_term(struct ospf_interface *oi); +extern int ospf_opaque_type10_lsa_init(struct ospf_area *area); +extern void ospf_opaque_type10_lsa_term(struct ospf_area *area); +extern int ospf_opaque_type11_lsa_init(struct ospf *ospf); +extern void ospf_opaque_type11_lsa_term(struct ospf *ospf); + +extern int ospf_register_opaque_functab( + u_char lsa_type, u_char opaque_type, + int (*new_if_hook)(struct interface *ifp), + int (*del_if_hook)(struct interface *ifp), + void (*ism_change_hook)(struct ospf_interface *oi, int old_status), + void (*nsm_change_hook)(struct ospf_neighbor *nbr, int old_status), + void (*config_write_router)(struct vty *vty), + void (*config_write_if)(struct vty *vty, struct interface *ifp), + void (*config_write_debug)(struct vty *vty), + void (*show_opaque_info)(struct vty *vty, struct ospf_lsa *lsa), + int (*lsa_originator)(void *arg), + struct ospf_lsa *(*lsa_refresher)(struct ospf_lsa *lsa), + int (*new_lsa_hook)(struct ospf_lsa *lsa), + int (*del_lsa_hook)(struct ospf_lsa *lsa)); +extern void ospf_delete_opaque_functab(u_char lsa_type, u_char opaque_type); + +extern int ospf_opaque_new_if(struct interface *ifp); +extern int ospf_opaque_del_if(struct interface *ifp); +extern void ospf_opaque_ism_change(struct ospf_interface *oi, int old_status); +extern void ospf_opaque_nsm_change(struct ospf_neighbor *nbr, int old_status); +extern void ospf_opaque_config_write_router(struct vty *vty, struct ospf *); +extern void ospf_opaque_config_write_if(struct vty *vty, struct interface *ifp); +extern void ospf_opaque_config_write_debug(struct vty *vty); +extern void show_opaque_info_detail(struct vty *vty, struct ospf_lsa *lsa); +extern void ospf_opaque_lsa_dump(struct stream *s, u_int16_t length); + +extern void ospf_opaque_lsa_originate_schedule(struct ospf_interface *oi, + int *init_delay); +extern struct ospf_lsa *ospf_opaque_lsa_install(struct ospf_lsa *, + int rt_recalc); +extern struct ospf_lsa *ospf_opaque_lsa_refresh(struct ospf_lsa *lsa); + +extern void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent, + u_char lsa_type, + u_char opaque_type); +extern void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa *lsa); +extern void ospf_opaque_lsa_flush_schedule(struct ospf_lsa *lsa); + +extern void ospf_opaque_self_originated_lsa_received(struct ospf_neighbor *nbr, + struct ospf_lsa *lsa); +extern struct ospf *oi_to_top(struct ospf_interface *oi); #endif /* _ZEBRA_OSPF_OPAQUE_H */ diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 951304c4d..ac2406ec2 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -71,3588 +71,3675 @@ #endif /* Packet Type String. */ -const struct message ospf_packet_type_str[] = -{ - { OSPF_MSG_HELLO, "Hello" }, - { OSPF_MSG_DB_DESC, "Database Description" }, - { OSPF_MSG_LS_REQ, "Link State Request" }, - { OSPF_MSG_LS_UPD, "Link State Update" }, - { OSPF_MSG_LS_ACK, "Link State Acknowledgment" }, - { 0 } -}; +const struct message ospf_packet_type_str[] = { + {OSPF_MSG_HELLO, "Hello"}, + {OSPF_MSG_DB_DESC, "Database Description"}, + {OSPF_MSG_LS_REQ, "Link State Request"}, + {OSPF_MSG_LS_UPD, "Link State Update"}, + {OSPF_MSG_LS_ACK, "Link State Acknowledgment"}, + {0}}; /* Minimum (besides OSPF_HEADER_SIZE) lengths for OSPF packets of particular types, offset is the "type" field of a packet. */ -static const u_int16_t ospf_packet_minlen[] = -{ - 0, - OSPF_HELLO_MIN_SIZE, - OSPF_DB_DESC_MIN_SIZE, - OSPF_LS_REQ_MIN_SIZE, - OSPF_LS_UPD_MIN_SIZE, - OSPF_LS_ACK_MIN_SIZE, +static const u_int16_t ospf_packet_minlen[] = { + 0, + OSPF_HELLO_MIN_SIZE, + OSPF_DB_DESC_MIN_SIZE, + OSPF_LS_REQ_MIN_SIZE, + OSPF_LS_UPD_MIN_SIZE, + OSPF_LS_ACK_MIN_SIZE, }; /* Minimum (besides OSPF_LSA_HEADER_SIZE) lengths for LSAs of particular types, offset is the "LSA type" field. */ -static const u_int16_t ospf_lsa_minlen[] = -{ - 0, - OSPF_ROUTER_LSA_MIN_SIZE, - OSPF_NETWORK_LSA_MIN_SIZE, - OSPF_SUMMARY_LSA_MIN_SIZE, - OSPF_SUMMARY_LSA_MIN_SIZE, - OSPF_AS_EXTERNAL_LSA_MIN_SIZE, - 0, - OSPF_AS_EXTERNAL_LSA_MIN_SIZE, - 0, - 0, - 0, - 0, +static const u_int16_t ospf_lsa_minlen[] = { + 0, + OSPF_ROUTER_LSA_MIN_SIZE, + OSPF_NETWORK_LSA_MIN_SIZE, + OSPF_SUMMARY_LSA_MIN_SIZE, + OSPF_SUMMARY_LSA_MIN_SIZE, + OSPF_AS_EXTERNAL_LSA_MIN_SIZE, + 0, + OSPF_AS_EXTERNAL_LSA_MIN_SIZE, + 0, + 0, + 0, + 0, }; /* for ospf_check_auth() */ -static int ospf_check_sum (struct ospf_header *); +static int ospf_check_sum(struct ospf_header *); /* OSPF authentication checking function */ -static int -ospf_auth_type (struct ospf_interface *oi) +static int ospf_auth_type(struct ospf_interface *oi) { - int auth_type; + int auth_type; - if (OSPF_IF_PARAM (oi, auth_type) == OSPF_AUTH_NOTSET) - auth_type = oi->area->auth_type; - else - auth_type = OSPF_IF_PARAM (oi, auth_type); + if (OSPF_IF_PARAM(oi, auth_type) == OSPF_AUTH_NOTSET) + auth_type = oi->area->auth_type; + else + auth_type = OSPF_IF_PARAM(oi, auth_type); - /* Handle case where MD5 key list is not configured aka Cisco */ - if (auth_type == OSPF_AUTH_CRYPTOGRAPHIC && - list_isempty (OSPF_IF_PARAM (oi, auth_crypt))) - return OSPF_AUTH_NULL; - - return auth_type; + /* Handle case where MD5 key list is not configured aka Cisco */ + if (auth_type == OSPF_AUTH_CRYPTOGRAPHIC + && list_isempty(OSPF_IF_PARAM(oi, auth_crypt))) + return OSPF_AUTH_NULL; + return auth_type; } -struct ospf_packet * -ospf_packet_new (size_t size) +struct ospf_packet *ospf_packet_new(size_t size) { - struct ospf_packet *new; + struct ospf_packet *new; - new = XCALLOC (MTYPE_OSPF_PACKET, sizeof (struct ospf_packet)); - new->s = stream_new (size); + new = XCALLOC(MTYPE_OSPF_PACKET, sizeof(struct ospf_packet)); + new->s = stream_new(size); - return new; + return new; } -void -ospf_packet_free (struct ospf_packet *op) +void ospf_packet_free(struct ospf_packet *op) { - if (op->s) - stream_free (op->s); + if (op->s) + stream_free(op->s); - XFREE (MTYPE_OSPF_PACKET, op); + XFREE(MTYPE_OSPF_PACKET, op); - op = NULL; + op = NULL; } -struct ospf_fifo * -ospf_fifo_new () +struct ospf_fifo *ospf_fifo_new() { - struct ospf_fifo *new; + struct ospf_fifo *new; - new = XCALLOC (MTYPE_OSPF_FIFO, sizeof (struct ospf_fifo)); - return new; + new = XCALLOC(MTYPE_OSPF_FIFO, sizeof(struct ospf_fifo)); + return new; } /* Add new packet to fifo. */ -void -ospf_fifo_push (struct ospf_fifo *fifo, struct ospf_packet *op) +void ospf_fifo_push(struct ospf_fifo *fifo, struct ospf_packet *op) { - if (fifo->tail) - fifo->tail->next = op; - else - fifo->head = op; + if (fifo->tail) + fifo->tail->next = op; + else + fifo->head = op; - fifo->tail = op; + fifo->tail = op; - fifo->count++; + fifo->count++; } /* Add new packet to head of fifo. */ -static void -ospf_fifo_push_head (struct ospf_fifo *fifo, struct ospf_packet *op) +static void ospf_fifo_push_head(struct ospf_fifo *fifo, struct ospf_packet *op) { - op->next = fifo->head; - - if (fifo->tail == NULL) - fifo->tail = op; - - fifo->head = op; - - fifo->count++; + op->next = fifo->head; + + if (fifo->tail == NULL) + fifo->tail = op; + + fifo->head = op; + + fifo->count++; } /* Delete first packet from fifo. */ -struct ospf_packet * -ospf_fifo_pop (struct ospf_fifo *fifo) +struct ospf_packet *ospf_fifo_pop(struct ospf_fifo *fifo) { - struct ospf_packet *op; + struct ospf_packet *op; - op = fifo->head; + op = fifo->head; - if (op) - { - fifo->head = op->next; + if (op) { + fifo->head = op->next; - if (fifo->head == NULL) - fifo->tail = NULL; + if (fifo->head == NULL) + fifo->tail = NULL; - fifo->count--; - } + fifo->count--; + } - return op; + return op; } /* Return first fifo entry. */ -struct ospf_packet * -ospf_fifo_head (struct ospf_fifo *fifo) +struct ospf_packet *ospf_fifo_head(struct ospf_fifo *fifo) { - return fifo->head; + return fifo->head; } /* Flush ospf packet fifo. */ -void -ospf_fifo_flush (struct ospf_fifo *fifo) +void ospf_fifo_flush(struct ospf_fifo *fifo) { - struct ospf_packet *op; - struct ospf_packet *next; + struct ospf_packet *op; + struct ospf_packet *next; - for (op = fifo->head; op; op = next) - { - next = op->next; - ospf_packet_free (op); - } - fifo->head = fifo->tail = NULL; - fifo->count = 0; + for (op = fifo->head; op; op = next) { + next = op->next; + ospf_packet_free(op); + } + fifo->head = fifo->tail = NULL; + fifo->count = 0; } /* Free ospf packet fifo. */ -void -ospf_fifo_free (struct ospf_fifo *fifo) +void ospf_fifo_free(struct ospf_fifo *fifo) { - ospf_fifo_flush (fifo); + ospf_fifo_flush(fifo); - XFREE (MTYPE_OSPF_FIFO, fifo); + XFREE(MTYPE_OSPF_FIFO, fifo); } -void -ospf_packet_add (struct ospf_interface *oi, struct ospf_packet *op) +void ospf_packet_add(struct ospf_interface *oi, struct ospf_packet *op) { - if (!oi->obuf) - { - zlog_err("ospf_packet_add(interface %s in state %d [%s], packet type %s, " - "destination %s) called with NULL obuf, ignoring " - "(please report this bug)!\n", - IF_NAME(oi), oi->state, lookup_msg(ospf_ism_state_msg, oi->state, NULL), - lookup_msg(ospf_packet_type_str, stream_getc_from(op->s, 1), NULL), - inet_ntoa (op->dst)); - return; - } + if (!oi->obuf) { + zlog_err( + "ospf_packet_add(interface %s in state %d [%s], packet type %s, " + "destination %s) called with NULL obuf, ignoring " + "(please report this bug)!\n", + IF_NAME(oi), oi->state, + lookup_msg(ospf_ism_state_msg, oi->state, NULL), + lookup_msg(ospf_packet_type_str, + stream_getc_from(op->s, 1), NULL), + inet_ntoa(op->dst)); + return; + } - /* Add packet to end of queue. */ - ospf_fifo_push (oi->obuf, op); + /* Add packet to end of queue. */ + ospf_fifo_push(oi->obuf, op); - /* Debug of packet fifo*/ - /* ospf_fifo_debug (oi->obuf); */ + /* Debug of packet fifo*/ + /* ospf_fifo_debug (oi->obuf); */ } -static void -ospf_packet_add_top (struct ospf_interface *oi, struct ospf_packet *op) +static void ospf_packet_add_top(struct ospf_interface *oi, + struct ospf_packet *op) { - if (!oi->obuf) - { - zlog_err("ospf_packet_add(interface %s in state %d [%s], packet type %s, " - "destination %s) called with NULL obuf, ignoring " - "(please report this bug)!\n", - IF_NAME(oi), oi->state, lookup_msg(ospf_ism_state_msg, oi->state, NULL), - lookup_msg(ospf_packet_type_str, stream_getc_from(op->s, 1), NULL), - inet_ntoa (op->dst)); - return; - } + if (!oi->obuf) { + zlog_err( + "ospf_packet_add(interface %s in state %d [%s], packet type %s, " + "destination %s) called with NULL obuf, ignoring " + "(please report this bug)!\n", + IF_NAME(oi), oi->state, + lookup_msg(ospf_ism_state_msg, oi->state, NULL), + lookup_msg(ospf_packet_type_str, + stream_getc_from(op->s, 1), NULL), + inet_ntoa(op->dst)); + return; + } - /* Add packet to head of queue. */ - ospf_fifo_push_head (oi->obuf, op); + /* Add packet to head of queue. */ + ospf_fifo_push_head(oi->obuf, op); - /* Debug of packet fifo*/ - /* ospf_fifo_debug (oi->obuf); */ + /* Debug of packet fifo*/ + /* ospf_fifo_debug (oi->obuf); */ } -void -ospf_packet_delete (struct ospf_interface *oi) +void ospf_packet_delete(struct ospf_interface *oi) { - struct ospf_packet *op; - - op = ospf_fifo_pop (oi->obuf); + struct ospf_packet *op; + + op = ospf_fifo_pop(oi->obuf); - if (op) - ospf_packet_free (op); + if (op) + ospf_packet_free(op); } -struct ospf_packet * -ospf_packet_dup (struct ospf_packet *op) +struct ospf_packet *ospf_packet_dup(struct ospf_packet *op) { - struct ospf_packet *new; + struct ospf_packet *new; - if (stream_get_endp(op->s) != op->length) - /* XXX size_t */ - zlog_warn ("ospf_packet_dup stream %lu ospf_packet %u size mismatch", - (u_long)STREAM_SIZE(op->s), op->length); + if (stream_get_endp(op->s) != op->length) + /* XXX size_t */ + zlog_warn( + "ospf_packet_dup stream %lu ospf_packet %u size mismatch", + (u_long)STREAM_SIZE(op->s), op->length); - /* Reserve space for MD5 authentication that may be added later. */ - new = ospf_packet_new (stream_get_endp(op->s) + OSPF_AUTH_MD5_SIZE); - stream_copy (new->s, op->s); + /* Reserve space for MD5 authentication that may be added later. */ + new = ospf_packet_new(stream_get_endp(op->s) + OSPF_AUTH_MD5_SIZE); + stream_copy(new->s, op->s); - new->dst = op->dst; - new->length = op->length; + new->dst = op->dst; + new->length = op->length; - return new; + return new; } /* XXX inline */ -static unsigned int -ospf_packet_authspace (struct ospf_interface *oi) +static unsigned int ospf_packet_authspace(struct ospf_interface *oi) { - int auth = 0; + int auth = 0; - if ( ospf_auth_type (oi) == OSPF_AUTH_CRYPTOGRAPHIC) - auth = OSPF_AUTH_MD5_SIZE; + if (ospf_auth_type(oi) == OSPF_AUTH_CRYPTOGRAPHIC) + auth = OSPF_AUTH_MD5_SIZE; - return auth; + return auth; } -static unsigned int -ospf_packet_max (struct ospf_interface *oi) +static unsigned int ospf_packet_max(struct ospf_interface *oi) { - int max; + int max; - max = oi->ifp->mtu - ospf_packet_authspace(oi); + max = oi->ifp->mtu - ospf_packet_authspace(oi); - max -= (OSPF_HEADER_SIZE + sizeof (struct ip)); + max -= (OSPF_HEADER_SIZE + sizeof(struct ip)); - return max; + return max; } -static int -ospf_check_md5_digest (struct ospf_interface *oi, struct ospf_header *ospfh) +static int ospf_check_md5_digest(struct ospf_interface *oi, + struct ospf_header *ospfh) { - MD5_CTX ctx; - unsigned char digest[OSPF_AUTH_MD5_SIZE]; - struct crypt_key *ck; - struct ospf_neighbor *nbr; - u_int16_t length = ntohs (ospfh->length); - - /* Get secret key. */ - ck = ospf_crypt_key_lookup (OSPF_IF_PARAM (oi, auth_crypt), - ospfh->u.crypt.key_id); - if (ck == NULL) - { - zlog_warn ("interface %s: ospf_check_md5 no key %d", - IF_NAME (oi), ospfh->u.crypt.key_id); - return 0; - } + MD5_CTX ctx; + unsigned char digest[OSPF_AUTH_MD5_SIZE]; + struct crypt_key *ck; + struct ospf_neighbor *nbr; + u_int16_t length = ntohs(ospfh->length); + + /* Get secret key. */ + ck = ospf_crypt_key_lookup(OSPF_IF_PARAM(oi, auth_crypt), + ospfh->u.crypt.key_id); + if (ck == NULL) { + zlog_warn("interface %s: ospf_check_md5 no key %d", IF_NAME(oi), + ospfh->u.crypt.key_id); + return 0; + } - /* check crypto seqnum. */ - nbr = ospf_nbr_lookup_by_routerid (oi->nbrs, &ospfh->router_id); + /* check crypto seqnum. */ + nbr = ospf_nbr_lookup_by_routerid(oi->nbrs, &ospfh->router_id); - if (nbr && ntohl(nbr->crypt_seqnum) > ntohl(ospfh->u.crypt.crypt_seqnum)) - { - zlog_warn ("interface %s: ospf_check_md5 bad sequence %d (expect %d)", - IF_NAME (oi), - ntohl(ospfh->u.crypt.crypt_seqnum), - ntohl(nbr->crypt_seqnum)); - return 0; - } - - /* Generate a digest for the ospf packet - their digest + our digest. */ - memset(&ctx, 0, sizeof(ctx)); - MD5Init(&ctx); - MD5Update(&ctx, ospfh, length); - MD5Update(&ctx, ck->auth_key, OSPF_AUTH_MD5_SIZE); - MD5Final(digest, &ctx); + if (nbr + && ntohl(nbr->crypt_seqnum) > ntohl(ospfh->u.crypt.crypt_seqnum)) { + zlog_warn( + "interface %s: ospf_check_md5 bad sequence %d (expect %d)", + IF_NAME(oi), ntohl(ospfh->u.crypt.crypt_seqnum), + ntohl(nbr->crypt_seqnum)); + return 0; + } - /* compare the two */ - if (memcmp ((caddr_t)ospfh + length, digest, OSPF_AUTH_MD5_SIZE)) - { - zlog_warn ("interface %s: ospf_check_md5 checksum mismatch", - IF_NAME (oi)); - return 0; - } + /* Generate a digest for the ospf packet - their digest + our digest. */ + memset(&ctx, 0, sizeof(ctx)); + MD5Init(&ctx); + MD5Update(&ctx, ospfh, length); + MD5Update(&ctx, ck->auth_key, OSPF_AUTH_MD5_SIZE); + MD5Final(digest, &ctx); + + /* compare the two */ + if (memcmp((caddr_t)ospfh + length, digest, OSPF_AUTH_MD5_SIZE)) { + zlog_warn("interface %s: ospf_check_md5 checksum mismatch", + IF_NAME(oi)); + return 0; + } - /* save neighbor's crypt_seqnum */ - if (nbr) - nbr->crypt_seqnum = ospfh->u.crypt.crypt_seqnum; - return 1; + /* save neighbor's crypt_seqnum */ + if (nbr) + nbr->crypt_seqnum = ospfh->u.crypt.crypt_seqnum; + return 1; } /* This function is called from ospf_write(), it will detect the authentication scheme and if it is MD5, it will change the sequence and update the MD5 digest. */ -static int -ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op) -{ - struct ospf_header *ospfh; - unsigned char digest[OSPF_AUTH_MD5_SIZE] = {0}; - MD5_CTX ctx; - void *ibuf; - u_int32_t t; - struct crypt_key *ck; - const u_int8_t *auth_key; - - ibuf = STREAM_DATA (op->s); - ospfh = (struct ospf_header *) ibuf; - - if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC) - return 0; - - /* We do this here so when we dup a packet, we don't have to - waste CPU rewriting other headers. - - Note that quagga_time /deliberately/ is not used here */ - t = (time(NULL) & 0xFFFFFFFF); - if (t > oi->crypt_seqnum) - oi->crypt_seqnum = t; - else - oi->crypt_seqnum++; - - ospfh->u.crypt.crypt_seqnum = htonl (oi->crypt_seqnum); - - /* Get MD5 Authentication key from auth_key list. */ - if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt))) - auth_key = (const u_int8_t *) digest; - else - { - ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt))); - auth_key = ck->auth_key; - } +static int ospf_make_md5_digest(struct ospf_interface *oi, + struct ospf_packet *op) +{ + struct ospf_header *ospfh; + unsigned char digest[OSPF_AUTH_MD5_SIZE] = {0}; + MD5_CTX ctx; + void *ibuf; + u_int32_t t; + struct crypt_key *ck; + const u_int8_t *auth_key; + + ibuf = STREAM_DATA(op->s); + ospfh = (struct ospf_header *)ibuf; + + if (ntohs(ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC) + return 0; + + /* We do this here so when we dup a packet, we don't have to + waste CPU rewriting other headers. + + Note that quagga_time /deliberately/ is not used here */ + t = (time(NULL) & 0xFFFFFFFF); + if (t > oi->crypt_seqnum) + oi->crypt_seqnum = t; + else + oi->crypt_seqnum++; + + ospfh->u.crypt.crypt_seqnum = htonl(oi->crypt_seqnum); + + /* Get MD5 Authentication key from auth_key list. */ + if (list_isempty(OSPF_IF_PARAM(oi, auth_crypt))) + auth_key = (const u_int8_t *)digest; + else { + ck = listgetdata(listtail(OSPF_IF_PARAM(oi, auth_crypt))); + auth_key = ck->auth_key; + } - /* Generate a digest for the entire packet + our secret key. */ - memset(&ctx, 0, sizeof(ctx)); - MD5Init(&ctx); - MD5Update(&ctx, ibuf, ntohs (ospfh->length)); - MD5Update(&ctx, auth_key, OSPF_AUTH_MD5_SIZE); - MD5Final(digest, &ctx); + /* Generate a digest for the entire packet + our secret key. */ + memset(&ctx, 0, sizeof(ctx)); + MD5Init(&ctx); + MD5Update(&ctx, ibuf, ntohs(ospfh->length)); + MD5Update(&ctx, auth_key, OSPF_AUTH_MD5_SIZE); + MD5Final(digest, &ctx); - /* Append md5 digest to the end of the stream. */ - stream_put (op->s, digest, OSPF_AUTH_MD5_SIZE); + /* Append md5 digest to the end of the stream. */ + stream_put(op->s, digest, OSPF_AUTH_MD5_SIZE); - /* We do *NOT* increment the OSPF header length. */ - op->length = ntohs (ospfh->length) + OSPF_AUTH_MD5_SIZE; + /* We do *NOT* increment the OSPF header length. */ + op->length = ntohs(ospfh->length) + OSPF_AUTH_MD5_SIZE; - if (stream_get_endp(op->s) != op->length) - /* XXX size_t */ - zlog_warn("ospf_make_md5_digest: length mismatch stream %lu ospf_packet %u", - (u_long)stream_get_endp(op->s), op->length); + if (stream_get_endp(op->s) != op->length) + /* XXX size_t */ + zlog_warn( + "ospf_make_md5_digest: length mismatch stream %lu ospf_packet %u", + (u_long)stream_get_endp(op->s), op->length); - return OSPF_AUTH_MD5_SIZE; + return OSPF_AUTH_MD5_SIZE; } -static int -ospf_ls_req_timer (struct thread *thread) +static int ospf_ls_req_timer(struct thread *thread) { - struct ospf_neighbor *nbr; + struct ospf_neighbor *nbr; - nbr = THREAD_ARG (thread); - nbr->t_ls_req = NULL; + nbr = THREAD_ARG(thread); + nbr->t_ls_req = NULL; - /* Send Link State Request. */ - if (ospf_ls_request_count (nbr)) - ospf_ls_req_send (nbr); + /* Send Link State Request. */ + if (ospf_ls_request_count(nbr)) + ospf_ls_req_send(nbr); - /* Set Link State Request retransmission timer. */ - OSPF_NSM_TIMER_ON (nbr->t_ls_req, ospf_ls_req_timer, nbr->v_ls_req); + /* Set Link State Request retransmission timer. */ + OSPF_NSM_TIMER_ON(nbr->t_ls_req, ospf_ls_req_timer, nbr->v_ls_req); - return 0; + return 0; } -void -ospf_ls_req_event (struct ospf_neighbor *nbr) +void ospf_ls_req_event(struct ospf_neighbor *nbr) { - if (nbr->t_ls_req) - { - thread_cancel (nbr->t_ls_req); - nbr->t_ls_req = NULL; - } - nbr->t_ls_req = NULL; - thread_add_event(master, ospf_ls_req_timer, nbr, 0, &nbr->t_ls_req); + if (nbr->t_ls_req) { + thread_cancel(nbr->t_ls_req); + nbr->t_ls_req = NULL; + } + nbr->t_ls_req = NULL; + thread_add_event(master, ospf_ls_req_timer, nbr, 0, &nbr->t_ls_req); } /* Cyclic timer function. Fist registered in ospf_nbr_new () in ospf_neighbor.c */ -int -ospf_ls_upd_timer (struct thread *thread) -{ - struct ospf_neighbor *nbr; - - nbr = THREAD_ARG (thread); - nbr->t_ls_upd = NULL; - - /* Send Link State Update. */ - if (ospf_ls_retransmit_count (nbr) > 0) - { - struct list *update; - struct ospf_lsdb *lsdb; - int i; - int retransmit_interval; - - retransmit_interval = OSPF_IF_PARAM (nbr->oi, retransmit_interval); - - lsdb = &nbr->ls_rxmt; - update = list_new (); +int ospf_ls_upd_timer(struct thread *thread) +{ + struct ospf_neighbor *nbr; + + nbr = THREAD_ARG(thread); + nbr->t_ls_upd = NULL; + + /* Send Link State Update. */ + if (ospf_ls_retransmit_count(nbr) > 0) { + struct list *update; + struct ospf_lsdb *lsdb; + int i; + int retransmit_interval; + + retransmit_interval = + OSPF_IF_PARAM(nbr->oi, retransmit_interval); + + lsdb = &nbr->ls_rxmt; + update = list_new(); + + for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) { + struct route_table *table = lsdb->type[i].db; + struct route_node *rn; + + for (rn = route_top(table); rn; rn = route_next(rn)) { + struct ospf_lsa *lsa; + + if ((lsa = rn->info) != NULL) { + /* Don't retransmit an LSA if we + received it within + the last RxmtInterval seconds - this + is to allow the + neighbour a chance to acknowledge the + LSA as it may + have ben just received before the + retransmit timer + fired. This is a small tweak to what + is in the RFC, + but it will cut out out a lot of + retransmit traffic + - MAG */ + if (monotime_since(&lsa->tv_recv, NULL) + >= retransmit_interval * 1000000LL) + listnode_add(update, rn->info); + } + } + } - for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) - { - struct route_table *table = lsdb->type[i].db; - struct route_node *rn; - - for (rn = route_top (table); rn; rn = route_next (rn)) - { - struct ospf_lsa *lsa; - - if ((lsa = rn->info) != NULL) - { - /* Don't retransmit an LSA if we received it within - the last RxmtInterval seconds - this is to allow the - neighbour a chance to acknowledge the LSA as it may - have ben just received before the retransmit timer - fired. This is a small tweak to what is in the RFC, - but it will cut out out a lot of retransmit traffic - - MAG */ - if (monotime_since (&lsa->tv_recv, NULL) - >= retransmit_interval * 1000000LL) - listnode_add (update, rn->info); - } - } + if (listcount(update) > 0) + ospf_ls_upd_send(nbr, update, OSPF_SEND_PACKET_DIRECT); + list_delete(update); } - if (listcount (update) > 0) - ospf_ls_upd_send (nbr, update, OSPF_SEND_PACKET_DIRECT); - list_delete (update); - } + /* Set LS Update retransmission timer. */ + OSPF_NSM_TIMER_ON(nbr->t_ls_upd, ospf_ls_upd_timer, nbr->v_ls_upd); - /* Set LS Update retransmission timer. */ - OSPF_NSM_TIMER_ON (nbr->t_ls_upd, ospf_ls_upd_timer, nbr->v_ls_upd); - - return 0; + return 0; } -int -ospf_ls_ack_timer (struct thread *thread) +int ospf_ls_ack_timer(struct thread *thread) { - struct ospf_interface *oi; + struct ospf_interface *oi; - oi = THREAD_ARG (thread); - oi->t_ls_ack = NULL; + oi = THREAD_ARG(thread); + oi->t_ls_ack = NULL; - /* Send Link State Acknowledgment. */ - if (listcount (oi->ls_ack) > 0) - ospf_ls_ack_send_delayed (oi); + /* Send Link State Acknowledgment. */ + if (listcount(oi->ls_ack) > 0) + ospf_ls_ack_send_delayed(oi); - /* Set LS Ack timer. */ - OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack); + /* Set LS Ack timer. */ + OSPF_ISM_TIMER_ON(oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack); - return 0; + return 0; } #ifdef WANT_OSPF_WRITE_FRAGMENT -static void -ospf_write_frags (int fd, struct ospf_packet *op, struct ip *iph, - struct msghdr *msg, unsigned int maxdatasize, - unsigned int mtu, int flags, u_char type) +static void ospf_write_frags(int fd, struct ospf_packet *op, struct ip *iph, + struct msghdr *msg, unsigned int maxdatasize, + unsigned int mtu, int flags, u_char type) { #define OSPF_WRITE_FRAG_SHIFT 3 - u_int16_t offset; - struct iovec *iovp; - int ret; - - assert ( op->length == stream_get_endp(op->s) ); - assert (msg->msg_iovlen == 2); - - /* we can but try. - * - * SunOS, BSD and BSD derived kernels likely will clear ip_id, as - * well as the IP_MF flag, making this all quite pointless. - * - * However, for a system on which IP_MF is left alone, and ip_id left - * alone or else which sets same ip_id for each fragment this might - * work, eg linux. - * - * XXX-TODO: It would be much nicer to have the kernel's use their - * existing fragmentation support to do this for us. Bugs/RFEs need to - * be raised against the various kernels. - */ - - /* set More Frag */ - iph->ip_off |= IP_MF; - - /* ip frag offset is expressed in units of 8byte words */ - offset = maxdatasize >> OSPF_WRITE_FRAG_SHIFT; - - iovp = &msg->msg_iov[1]; - - while ( (stream_get_endp(op->s) - stream_get_getp (op->s)) - > maxdatasize ) - { - /* data length of this frag is to next offset value */ - iovp->iov_len = offset << OSPF_WRITE_FRAG_SHIFT; - iph->ip_len = iovp->iov_len + sizeof (struct ip); - assert (iph->ip_len <= mtu); - - sockopt_iphdrincl_swab_htosys (iph); - - ret = sendmsg (fd, msg, flags); - - sockopt_iphdrincl_swab_systoh (iph); - - if (ret < 0) - zlog_warn ("*** ospf_write_frags: sendmsg failed to %s," - " id %d, off %d, len %d, mtu %u failed with %s", - inet_ntoa (iph->ip_dst), - iph->ip_id, - iph->ip_off, - iph->ip_len, - mtu, - safe_strerror (errno)); - - if (IS_DEBUG_OSPF_PACKET (type - 1, SEND)) - { - zlog_debug ("ospf_write_frags: sent id %d, off %d, len %d to %s\n", - iph->ip_id, iph->ip_off, iph->ip_len, - inet_ntoa (iph->ip_dst)); - if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL)) - { - zlog_debug ("-----------------IP Header Dump----------------------"); - ospf_ip_header_dump (iph); - zlog_debug ("-----------------------------------------------------"); - } - } - - iph->ip_off += offset; - stream_forward_getp (op->s, iovp->iov_len); - iovp->iov_base = STREAM_PNT (op->s); - } - - /* setup for final fragment */ - iovp->iov_len = stream_get_endp(op->s) - stream_get_getp (op->s); - iph->ip_len = iovp->iov_len + sizeof (struct ip); - iph->ip_off &= (~IP_MF); + u_int16_t offset; + struct iovec *iovp; + int ret; + + assert(op->length == stream_get_endp(op->s)); + assert(msg->msg_iovlen == 2); + + /* we can but try. + * + * SunOS, BSD and BSD derived kernels likely will clear ip_id, as + * well as the IP_MF flag, making this all quite pointless. + * + * However, for a system on which IP_MF is left alone, and ip_id left + * alone or else which sets same ip_id for each fragment this might + * work, eg linux. + * + * XXX-TODO: It would be much nicer to have the kernel's use their + * existing fragmentation support to do this for us. Bugs/RFEs need to + * be raised against the various kernels. + */ + + /* set More Frag */ + iph->ip_off |= IP_MF; + + /* ip frag offset is expressed in units of 8byte words */ + offset = maxdatasize >> OSPF_WRITE_FRAG_SHIFT; + + iovp = &msg->msg_iov[1]; + + while ((stream_get_endp(op->s) - stream_get_getp(op->s)) + > maxdatasize) { + /* data length of this frag is to next offset value */ + iovp->iov_len = offset << OSPF_WRITE_FRAG_SHIFT; + iph->ip_len = iovp->iov_len + sizeof(struct ip); + assert(iph->ip_len <= mtu); + + sockopt_iphdrincl_swab_htosys(iph); + + ret = sendmsg(fd, msg, flags); + + sockopt_iphdrincl_swab_systoh(iph); + + if (ret < 0) + zlog_warn( + "*** ospf_write_frags: sendmsg failed to %s," + " id %d, off %d, len %d, mtu %u failed with %s", + inet_ntoa(iph->ip_dst), iph->ip_id, iph->ip_off, + iph->ip_len, mtu, safe_strerror(errno)); + + if (IS_DEBUG_OSPF_PACKET(type - 1, SEND)) { + zlog_debug( + "ospf_write_frags: sent id %d, off %d, len %d to %s\n", + iph->ip_id, iph->ip_off, iph->ip_len, + inet_ntoa(iph->ip_dst)); + if (IS_DEBUG_OSPF_PACKET(type - 1, DETAIL)) { + zlog_debug( + "-----------------IP Header Dump----------------------"); + ospf_ip_header_dump(iph); + zlog_debug( + "-----------------------------------------------------"); + } + } + + iph->ip_off += offset; + stream_forward_getp(op->s, iovp->iov_len); + iovp->iov_base = STREAM_PNT(op->s); + } + + /* setup for final fragment */ + iovp->iov_len = stream_get_endp(op->s) - stream_get_getp(op->s); + iph->ip_len = iovp->iov_len + sizeof(struct ip); + iph->ip_off &= (~IP_MF); } #endif /* WANT_OSPF_WRITE_FRAGMENT */ -static int -ospf_write (struct thread *thread) -{ - struct ospf *ospf = THREAD_ARG (thread); - struct ospf_interface *oi; - struct ospf_interface *last_serviced_oi = NULL; - struct ospf_packet *op; - struct sockaddr_in sa_dst; - struct ip iph; - struct msghdr msg; - struct iovec iov[2]; - u_char type; - int ret; - int flags = 0; - struct listnode *node; +static int ospf_write(struct thread *thread) +{ + struct ospf *ospf = THREAD_ARG(thread); + struct ospf_interface *oi; + struct ospf_interface *last_serviced_oi = NULL; + struct ospf_packet *op; + struct sockaddr_in sa_dst; + struct ip iph; + struct msghdr msg; + struct iovec iov[2]; + u_char type; + int ret; + int flags = 0; + struct listnode *node; #ifdef WANT_OSPF_WRITE_FRAGMENT - static u_int16_t ipid = 0; - u_int16_t maxdatasize; + static u_int16_t ipid = 0; + u_int16_t maxdatasize; #endif /* WANT_OSPF_WRITE_FRAGMENT */ + /* $FRR indent$ */ + /* clang-format off */ #define OSPF_WRITE_IPHL_SHIFT 2 - int pkt_count = 0; - - ospf->t_write = NULL; + int pkt_count = 0; + + ospf->t_write = NULL; - node = listhead (ospf->oi_write_q); - assert (node); - oi = listgetdata (node); - assert (oi); + node = listhead(ospf->oi_write_q); + assert(node); + oi = listgetdata(node); + assert(oi); #ifdef WANT_OSPF_WRITE_FRAGMENT - /* seed ipid static with low order bits of time */ - if (ipid == 0) - ipid = (time(NULL) & 0xffff); + /* seed ipid static with low order bits of time */ + if (ipid == 0) + ipid = (time(NULL) & 0xffff); #endif /* WANT_OSPF_WRITE_FRAGMENT */ - while ((pkt_count < ospf->write_oi_count) && oi && (last_serviced_oi != oi)) - { - /* If there is only packet in the queue, the oi is removed from - write-q, so fix up the last interface that was serviced */ - if (last_serviced_oi == NULL) { - last_serviced_oi = oi; - } - pkt_count++; + while ((pkt_count < ospf->write_oi_count) && oi + && (last_serviced_oi != oi)) { + /* If there is only packet in the queue, the oi is removed from + write-q, so fix up the last interface that was serviced */ + if (last_serviced_oi == NULL) { + last_serviced_oi = oi; + } + pkt_count++; #ifdef WANT_OSPF_WRITE_FRAGMENT - /* convenience - max OSPF data per packet */ - maxdatasize = oi->ifp->mtu - sizeof (struct ip); + /* convenience - max OSPF data per packet */ + maxdatasize = oi->ifp->mtu - sizeof(struct ip); #endif /* WANT_OSPF_WRITE_FRAGMENT */ - /* Get one packet from queue. */ - op = ospf_fifo_head (oi->obuf); - assert (op); - assert (op->length >= OSPF_HEADER_SIZE); - - if (op->dst.s_addr == htonl (OSPF_ALLSPFROUTERS) - || op->dst.s_addr == htonl (OSPF_ALLDROUTERS)) - ospf_if_ipmulticast (ospf, oi->address, oi->ifp->ifindex); - - /* Rewrite the md5 signature & update the seq */ - ospf_make_md5_digest (oi, op); - - /* Retrieve OSPF packet type. */ - stream_set_getp (op->s, 1); - type = stream_getc (op->s); - - /* reset get pointer */ - stream_set_getp (op->s, 0); - - memset (&iph, 0, sizeof (struct ip)); - memset (&sa_dst, 0, sizeof (sa_dst)); - - sa_dst.sin_family = AF_INET; + /* Get one packet from queue. */ + op = ospf_fifo_head(oi->obuf); + assert(op); + assert(op->length >= OSPF_HEADER_SIZE); + + if (op->dst.s_addr == htonl(OSPF_ALLSPFROUTERS) + || op->dst.s_addr == htonl(OSPF_ALLDROUTERS)) + ospf_if_ipmulticast(ospf, oi->address, + oi->ifp->ifindex); + + /* Rewrite the md5 signature & update the seq */ + ospf_make_md5_digest(oi, op); + + /* Retrieve OSPF packet type. */ + stream_set_getp(op->s, 1); + type = stream_getc(op->s); + + /* reset get pointer */ + stream_set_getp(op->s, 0); + + memset(&iph, 0, sizeof(struct ip)); + memset(&sa_dst, 0, sizeof(sa_dst)); + + sa_dst.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sa_dst.sin_len = sizeof(sa_dst); + sa_dst.sin_len = sizeof(sa_dst); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - sa_dst.sin_addr = op->dst; - sa_dst.sin_port = htons (0); - - /* Set DONTROUTE flag if dst is unicast. */ - if (oi->type != OSPF_IFTYPE_VIRTUALLINK) - if (!IN_MULTICAST (htonl (op->dst.s_addr))) - flags = MSG_DONTROUTE; - - iph.ip_hl = sizeof (struct ip) >> OSPF_WRITE_IPHL_SHIFT; - /* it'd be very strange for header to not be 4byte-word aligned but.. */ - if ( sizeof (struct ip) - > (unsigned int)(iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) ) - iph.ip_hl++; /* we presume sizeof struct ip cant overflow ip_hl.. */ - - iph.ip_v = IPVERSION; - iph.ip_tos = IPTOS_PREC_INTERNETCONTROL; - iph.ip_len = (iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) + op->length; + sa_dst.sin_addr = op->dst; + sa_dst.sin_port = htons(0); + + /* Set DONTROUTE flag if dst is unicast. */ + if (oi->type != OSPF_IFTYPE_VIRTUALLINK) + if (!IN_MULTICAST(htonl(op->dst.s_addr))) + flags = MSG_DONTROUTE; + + iph.ip_hl = sizeof(struct ip) >> OSPF_WRITE_IPHL_SHIFT; + /* it'd be very strange for header to not be 4byte-word aligned + * but.. */ + if (sizeof(struct ip) + > (unsigned int)(iph.ip_hl << OSPF_WRITE_IPHL_SHIFT)) + iph.ip_hl++; /* we presume sizeof struct ip cant + overflow ip_hl.. */ + + iph.ip_v = IPVERSION; + iph.ip_tos = IPTOS_PREC_INTERNETCONTROL; + iph.ip_len = (iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) + op->length; #if defined(__DragonFly__) - /* - * DragonFly's raw socket expects ip_len/ip_off in network byte order. - */ - iph.ip_len = htons(iph.ip_len); + /* + * DragonFly's raw socket expects ip_len/ip_off in network byte + * order. + */ + iph.ip_len = htons(iph.ip_len); #endif #ifdef WANT_OSPF_WRITE_FRAGMENT - /* XXX-MT: not thread-safe at all.. - * XXX: this presumes this is only programme sending OSPF packets - * otherwise, no guarantee ipid will be unique - */ - iph.ip_id = ++ipid; + /* XXX-MT: not thread-safe at all.. + * XXX: this presumes this is only programme sending OSPF + * packets + * otherwise, no guarantee ipid will be unique + */ + iph.ip_id = ++ipid; #endif /* WANT_OSPF_WRITE_FRAGMENT */ - iph.ip_off = 0; - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - iph.ip_ttl = OSPF_VL_IP_TTL; - else - iph.ip_ttl = OSPF_IP_TTL; - iph.ip_p = IPPROTO_OSPFIGP; - iph.ip_sum = 0; - iph.ip_src.s_addr = oi->address->u.prefix4.s_addr; - iph.ip_dst.s_addr = op->dst.s_addr; - - memset (&msg, 0, sizeof (msg)); - msg.msg_name = (caddr_t) &sa_dst; - msg.msg_namelen = sizeof (sa_dst); - msg.msg_iov = iov; - msg.msg_iovlen = 2; - iov[0].iov_base = (char*)&iph; - iov[0].iov_len = iph.ip_hl << OSPF_WRITE_IPHL_SHIFT; - iov[1].iov_base = STREAM_PNT (op->s); - iov[1].iov_len = op->length; - - /* Sadly we can not rely on kernels to fragment packets because of either - * IP_HDRINCL and/or multicast destination being set. - */ + iph.ip_off = 0; + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + iph.ip_ttl = OSPF_VL_IP_TTL; + else + iph.ip_ttl = OSPF_IP_TTL; + iph.ip_p = IPPROTO_OSPFIGP; + iph.ip_sum = 0; + iph.ip_src.s_addr = oi->address->u.prefix4.s_addr; + iph.ip_dst.s_addr = op->dst.s_addr; + + memset(&msg, 0, sizeof(msg)); + msg.msg_name = (caddr_t)&sa_dst; + msg.msg_namelen = sizeof(sa_dst); + msg.msg_iov = iov; + msg.msg_iovlen = 2; + iov[0].iov_base = (char *)&iph; + iov[0].iov_len = iph.ip_hl << OSPF_WRITE_IPHL_SHIFT; + iov[1].iov_base = STREAM_PNT(op->s); + iov[1].iov_len = op->length; + +/* Sadly we can not rely on kernels to fragment packets because of either + * IP_HDRINCL and/or multicast destination being set. + */ #ifdef WANT_OSPF_WRITE_FRAGMENT - if ( op->length > maxdatasize ) - ospf_write_frags (ospf->fd, op, &iph, &msg, maxdatasize, - oi->ifp->mtu, flags, type); + if (op->length > maxdatasize) + ospf_write_frags(ospf->fd, op, &iph, &msg, maxdatasize, + oi->ifp->mtu, flags, type); #endif /* WANT_OSPF_WRITE_FRAGMENT */ - /* send final fragment (could be first) */ - sockopt_iphdrincl_swab_htosys (&iph); - ret = sendmsg (ospf->fd, &msg, flags); - sockopt_iphdrincl_swab_systoh (&iph); - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_write to %s, " - "id %d, off %d, len %d, interface %s, mtu %u:", - inet_ntoa (iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len, - oi->ifp->name, oi->ifp->mtu); - - if (ret < 0) - zlog_warn ("*** sendmsg in ospf_write failed to %s, " - "id %d, off %d, len %d, interface %s, mtu %u: %s", - inet_ntoa (iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len, - oi->ifp->name, oi->ifp->mtu, safe_strerror (errno)); - - /* Show debug sending packet. */ - if (IS_DEBUG_OSPF_PACKET (type - 1, SEND)) - { - if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL)) - { - zlog_debug ("-----------------------------------------------------"); - ospf_ip_header_dump (&iph); - stream_set_getp (op->s, 0); - ospf_packet_dump (op->s); - } - - zlog_debug ("%s sent to [%s] via [%s].", - lookup_msg(ospf_packet_type_str, type, NULL), - inet_ntoa (op->dst), - IF_NAME (oi)); - - if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL)) - zlog_debug ("-----------------------------------------------------"); - } - - /* Now delete packet from queue. */ - ospf_packet_delete (oi); - - /* Move this interface to the tail of write_q to - serve everyone in a round robin fashion */ - list_delete_node (ospf->oi_write_q, node); - if (ospf_fifo_head (oi->obuf) == NULL) - { - oi->on_write_q = 0; - last_serviced_oi = NULL; - oi = NULL; - } - else - { - listnode_add (ospf->oi_write_q, oi); - } - - /* Setup to service from the head of the queue again */ - if (!list_isempty (ospf->oi_write_q)) - { - node = listhead (ospf->oi_write_q); - assert (node); - oi = listgetdata (node); - assert (oi); + /* send final fragment (could be first) */ + sockopt_iphdrincl_swab_htosys(&iph); + ret = sendmsg(ospf->fd, &msg, flags); + sockopt_iphdrincl_swab_systoh(&iph); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_write to %s, " + "id %d, off %d, len %d, interface %s, mtu %u:", + inet_ntoa(iph.ip_dst), iph.ip_id, iph.ip_off, + iph.ip_len, oi->ifp->name, oi->ifp->mtu); + + if (ret < 0) + zlog_warn( + "*** sendmsg in ospf_write failed to %s, " + "id %d, off %d, len %d, interface %s, mtu %u: %s", + inet_ntoa(iph.ip_dst), iph.ip_id, iph.ip_off, + iph.ip_len, oi->ifp->name, oi->ifp->mtu, + safe_strerror(errno)); + + /* Show debug sending packet. */ + if (IS_DEBUG_OSPF_PACKET(type - 1, SEND)) { + if (IS_DEBUG_OSPF_PACKET(type - 1, DETAIL)) { + zlog_debug( + "-----------------------------------------------------"); + ospf_ip_header_dump(&iph); + stream_set_getp(op->s, 0); + ospf_packet_dump(op->s); + } + + zlog_debug("%s sent to [%s] via [%s].", + lookup_msg(ospf_packet_type_str, type, NULL), + inet_ntoa(op->dst), IF_NAME(oi)); + + if (IS_DEBUG_OSPF_PACKET(type - 1, DETAIL)) + zlog_debug( + "-----------------------------------------------------"); + } + + /* Now delete packet from queue. */ + ospf_packet_delete(oi); + + /* Move this interface to the tail of write_q to + serve everyone in a round robin fashion */ + list_delete_node(ospf->oi_write_q, node); + if (ospf_fifo_head(oi->obuf) == NULL) { + oi->on_write_q = 0; + last_serviced_oi = NULL; + oi = NULL; + } else { + listnode_add(ospf->oi_write_q, oi); } + + /* Setup to service from the head of the queue again */ + if (!list_isempty(ospf->oi_write_q)) { + node = listhead(ospf->oi_write_q); + assert(node); + oi = listgetdata(node); + assert(oi); + } + } + + /* If packets still remain in queue, call write thread. */ + if (!list_isempty(ospf->oi_write_q)) { + ospf->t_write = NULL; + thread_add_write(master, ospf_write, ospf, ospf->fd, + &ospf->t_write); } - - /* If packets still remain in queue, call write thread. */ - if (!list_isempty (ospf->oi_write_q)) { - ospf->t_write = NULL; - thread_add_write(master, ospf_write, ospf, ospf->fd, &ospf->t_write); - } - return 0; + return 0; } /* OSPF Hello message read -- RFC2328 Section 10.5. */ -static void -ospf_hello (struct ip *iph, struct ospf_header *ospfh, - struct stream * s, struct ospf_interface *oi, int size) -{ - struct ospf_hello *hello; - struct ospf_neighbor *nbr; - int old_state; - struct prefix p; - - /* increment statistics. */ - oi->hello_in++; - - hello = (struct ospf_hello *) STREAM_PNT (s); - - /* If Hello is myself, silently discard. */ - if (IPV4_ADDR_SAME (&ospfh->router_id, &oi->ospf->router_id)) - { - if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) - { - zlog_debug ("ospf_header[%s/%s]: selforiginated, " - "dropping.", - lookup_msg(ospf_packet_type_str, ospfh->type, NULL), - inet_ntoa (iph->ip_src)); - } - return; - } - - /* get neighbor prefix. */ - p.family = AF_INET; - p.prefixlen = ip_masklen (hello->network_mask); - p.u.prefix4 = iph->ip_src; - - /* Compare network mask. */ - /* Checking is ignored for Point-to-Point and Virtual link. */ - if (oi->type != OSPF_IFTYPE_POINTOPOINT - && oi->type != OSPF_IFTYPE_VIRTUALLINK) - if (oi->address->prefixlen != p.prefixlen) - { - zlog_warn ("Packet %s [Hello:RECV]: NetworkMask mismatch on %s (configured prefix length is %d, but hello packet indicates %d).", - inet_ntoa(ospfh->router_id), IF_NAME(oi), - (int)oi->address->prefixlen, (int)p.prefixlen); - return; - } - - /* Compare Router Dead Interval. */ - if (OSPF_IF_PARAM (oi, v_wait) != ntohl (hello->dead_interval)) - { - zlog_warn ("Packet %s [Hello:RECV]: RouterDeadInterval mismatch " - "(expected %u, but received %u).", - inet_ntoa(ospfh->router_id), - OSPF_IF_PARAM(oi, v_wait), ntohl(hello->dead_interval)); - return; - } - - /* Compare Hello Interval - ignored if fast-hellos are set. */ - if (OSPF_IF_PARAM (oi, fast_hello) == 0) - { - if (OSPF_IF_PARAM (oi, v_hello) != ntohs (hello->hello_interval)) - { - zlog_warn ("Packet %s [Hello:RECV]: HelloInterval mismatch " - "(expected %u, but received %u).", - inet_ntoa(ospfh->router_id), - OSPF_IF_PARAM(oi, v_hello), ntohs(hello->hello_interval)); - return; - } - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Packet %s [Hello:RECV]: Options %s", - inet_ntoa (ospfh->router_id), - ospf_options_dump (hello->options)); - - /* Compare options. */ +static void ospf_hello(struct ip *iph, struct ospf_header *ospfh, + struct stream *s, struct ospf_interface *oi, int size) +{ + struct ospf_hello *hello; + struct ospf_neighbor *nbr; + int old_state; + struct prefix p; + + /* increment statistics. */ + oi->hello_in++; + + hello = (struct ospf_hello *)STREAM_PNT(s); + + /* If Hello is myself, silently discard. */ + if (IPV4_ADDR_SAME(&ospfh->router_id, &oi->ospf->router_id)) { + if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) { + zlog_debug( + "ospf_header[%s/%s]: selforiginated, " + "dropping.", + lookup_msg(ospf_packet_type_str, ospfh->type, + NULL), + inet_ntoa(iph->ip_src)); + } + return; + } + + /* get neighbor prefix. */ + p.family = AF_INET; + p.prefixlen = ip_masklen(hello->network_mask); + p.u.prefix4 = iph->ip_src; + + /* Compare network mask. */ + /* Checking is ignored for Point-to-Point and Virtual link. */ + if (oi->type != OSPF_IFTYPE_POINTOPOINT + && oi->type != OSPF_IFTYPE_VIRTUALLINK) + if (oi->address->prefixlen != p.prefixlen) { + zlog_warn( + "Packet %s [Hello:RECV]: NetworkMask mismatch on %s (configured prefix length is %d, but hello packet indicates %d).", + inet_ntoa(ospfh->router_id), IF_NAME(oi), + (int)oi->address->prefixlen, (int)p.prefixlen); + return; + } + + /* Compare Router Dead Interval. */ + if (OSPF_IF_PARAM(oi, v_wait) != ntohl(hello->dead_interval)) { + zlog_warn( + "Packet %s [Hello:RECV]: RouterDeadInterval mismatch " + "(expected %u, but received %u).", + inet_ntoa(ospfh->router_id), OSPF_IF_PARAM(oi, v_wait), + ntohl(hello->dead_interval)); + return; + } + + /* Compare Hello Interval - ignored if fast-hellos are set. */ + if (OSPF_IF_PARAM(oi, fast_hello) == 0) { + if (OSPF_IF_PARAM(oi, v_hello) + != ntohs(hello->hello_interval)) { + zlog_warn( + "Packet %s [Hello:RECV]: HelloInterval mismatch " + "(expected %u, but received %u).", + inet_ntoa(ospfh->router_id), + OSPF_IF_PARAM(oi, v_hello), + ntohs(hello->hello_interval)); + return; + } + } + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Packet %s [Hello:RECV]: Options %s", + inet_ntoa(ospfh->router_id), + ospf_options_dump(hello->options)); + +/* Compare options. */ #define REJECT_IF_TBIT_ON 1 /* XXX */ #ifdef REJECT_IF_TBIT_ON - if (CHECK_FLAG (hello->options, OSPF_OPTION_MT)) - { - /* - * This router does not support non-zero TOS. - * Drop this Hello packet not to establish neighbor relationship. - */ - zlog_warn ("Packet %s [Hello:RECV]: T-bit on, drop it.", - inet_ntoa (ospfh->router_id)); - return; - } + if (CHECK_FLAG(hello->options, OSPF_OPTION_MT)) { + /* + * This router does not support non-zero TOS. + * Drop this Hello packet not to establish neighbor + * relationship. + */ + zlog_warn("Packet %s [Hello:RECV]: T-bit on, drop it.", + inet_ntoa(ospfh->router_id)); + return; + } #endif /* REJECT_IF_TBIT_ON */ - if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE) - && CHECK_FLAG (hello->options, OSPF_OPTION_O)) - { - /* - * This router does know the correct usage of O-bit - * the bit should be set in DD packet only. - */ - zlog_warn ("Packet %s [Hello:RECV]: O-bit abuse?", - inet_ntoa (ospfh->router_id)); + if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE) + && CHECK_FLAG(hello->options, OSPF_OPTION_O)) { + /* + * This router does know the correct usage of O-bit + * the bit should be set in DD packet only. + */ + zlog_warn("Packet %s [Hello:RECV]: O-bit abuse?", + inet_ntoa(ospfh->router_id)); #ifdef STRICT_OBIT_USAGE_CHECK - return; /* Reject this packet. */ -#else /* STRICT_OBIT_USAGE_CHECK */ - UNSET_FLAG (hello->options, OSPF_OPTION_O); /* Ignore O-bit. */ -#endif /* STRICT_OBIT_USAGE_CHECK */ - } + return; /* Reject this packet. */ +#else /* STRICT_OBIT_USAGE_CHECK */ + UNSET_FLAG(hello->options, OSPF_OPTION_O); /* Ignore O-bit. */ +#endif /* STRICT_OBIT_USAGE_CHECK */ + } - /* new for NSSA is to ensure that NP is on and E is off */ + /* new for NSSA is to ensure that NP is on and E is off */ + + if (oi->area->external_routing == OSPF_AREA_NSSA) { + if (!(CHECK_FLAG(OPTIONS(oi), OSPF_OPTION_NP) + && CHECK_FLAG(hello->options, OSPF_OPTION_NP) + && !CHECK_FLAG(OPTIONS(oi), OSPF_OPTION_E) + && !CHECK_FLAG(hello->options, OSPF_OPTION_E))) { + zlog_warn( + "NSSA-Packet-%s[Hello:RECV]: my options: %x, his options %x", + inet_ntoa(ospfh->router_id), OPTIONS(oi), + hello->options); + return; + } + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("NSSA-Hello:RECV:Packet from %s:", + inet_ntoa(ospfh->router_id)); + } else + /* The setting of the E-bit found in the Hello Packet's Options + field must match this area's ExternalRoutingCapability A + mismatch causes processing to stop and the packet to be + dropped. The setting of the rest of the bits in the Hello + Packet's Options field should be ignored. */ + if (CHECK_FLAG(OPTIONS(oi), OSPF_OPTION_E) + != CHECK_FLAG(hello->options, OSPF_OPTION_E)) { + zlog_warn( + "Packet %s [Hello:RECV]: my options: %x, his options %x", + inet_ntoa(ospfh->router_id), OPTIONS(oi), + hello->options); + return; + } - if (oi->area->external_routing == OSPF_AREA_NSSA) - { - if (! (CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_NP) - && CHECK_FLAG (hello->options, OSPF_OPTION_NP) - && ! CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_E) - && ! CHECK_FLAG (hello->options, OSPF_OPTION_E))) - { - zlog_warn ("NSSA-Packet-%s[Hello:RECV]: my options: %x, his options %x", inet_ntoa (ospfh->router_id), OPTIONS (oi), hello->options); - return; - } - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("NSSA-Hello:RECV:Packet from %s:", inet_ntoa(ospfh->router_id)); - } - else - /* The setting of the E-bit found in the Hello Packet's Options - field must match this area's ExternalRoutingCapability A - mismatch causes processing to stop and the packet to be - dropped. The setting of the rest of the bits in the Hello - Packet's Options field should be ignored. */ - if (CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_E) != - CHECK_FLAG (hello->options, OSPF_OPTION_E)) - { - zlog_warn ("Packet %s [Hello:RECV]: my options: %x, his options %x", - inet_ntoa(ospfh->router_id), OPTIONS (oi), hello->options); - return; - } - - /* get neighbour struct */ - nbr = ospf_nbr_get (oi, ospfh, iph, &p); - - /* neighbour must be valid, ospf_nbr_get creates if none existed */ - assert (nbr); - - old_state = nbr->state; - - /* Add event to thread. */ - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived); - - /* RFC2328 Section 9.5.1 - If the router is not eligible to become Designated Router, - (snip) It must also send an Hello Packet in reply to an - Hello Packet received from any eligible neighbor (other than - the current Designated Router and Backup Designated Router). */ - if (oi->type == OSPF_IFTYPE_NBMA) - if (PRIORITY(oi) == 0 && hello->priority > 0 - && IPV4_ADDR_CMP(&DR(oi), &iph->ip_src) - && IPV4_ADDR_CMP(&BDR(oi), &iph->ip_src)) - OSPF_NSM_TIMER_ON (nbr->t_hello_reply, ospf_hello_reply_timer, - OSPF_HELLO_REPLY_DELAY); - - /* on NBMA network type, it happens to receive bidirectional Hello packet - without advance 1-Way Received event. - To avoid incorrect DR-seletion, raise 1-Way Received event.*/ - if (oi->type == OSPF_IFTYPE_NBMA && - (old_state == NSM_Down || old_state == NSM_Attempt)) - { - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived); - nbr->priority = hello->priority; - nbr->d_router = hello->d_router; - nbr->bd_router = hello->bd_router; - return; - } - - if (ospf_nbr_bidirectional (&oi->ospf->router_id, hello->neighbors, - size - OSPF_HELLO_MIN_SIZE)) - { - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_TwoWayReceived); - nbr->options |= hello->options; - } - else - { - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived); - /* Set neighbor information. */ - nbr->priority = hello->priority; - nbr->d_router = hello->d_router; - nbr->bd_router = hello->bd_router; - return; - } - - /* If neighbor itself declares DR and no BDR exists, - cause event BackupSeen */ - if (IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router)) - if (hello->bd_router.s_addr == 0 && oi->state == ISM_Waiting) - OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen); - - /* neighbor itself declares BDR. */ - if (oi->state == ISM_Waiting && - IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router)) - OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen); - - /* had not previously. */ - if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router) && - IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->d_router)) || - (IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->d_router) && - IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->d_router))) - OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange); - - /* had not previously. */ - if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router) && - IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->bd_router)) || - (IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->bd_router) && - IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->bd_router))) - OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange); - - /* Neighbor priority check. */ - if (nbr->priority >= 0 && nbr->priority != hello->priority) - OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange); - - /* Set neighbor information. */ - nbr->priority = hello->priority; - nbr->d_router = hello->d_router; - nbr->bd_router = hello->bd_router; + /* get neighbour struct */ + nbr = ospf_nbr_get(oi, ospfh, iph, &p); + + /* neighbour must be valid, ospf_nbr_get creates if none existed */ + assert(nbr); + + old_state = nbr->state; + + /* Add event to thread. */ + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_PacketReceived); + + /* RFC2328 Section 9.5.1 + If the router is not eligible to become Designated Router, + (snip) It must also send an Hello Packet in reply to an + Hello Packet received from any eligible neighbor (other than + the current Designated Router and Backup Designated Router). */ + if (oi->type == OSPF_IFTYPE_NBMA) + if (PRIORITY(oi) == 0 && hello->priority > 0 + && IPV4_ADDR_CMP(&DR(oi), &iph->ip_src) + && IPV4_ADDR_CMP(&BDR(oi), &iph->ip_src)) + OSPF_NSM_TIMER_ON(nbr->t_hello_reply, + ospf_hello_reply_timer, + OSPF_HELLO_REPLY_DELAY); + + /* on NBMA network type, it happens to receive bidirectional Hello + packet + without advance 1-Way Received event. + To avoid incorrect DR-seletion, raise 1-Way Received event.*/ + if (oi->type == OSPF_IFTYPE_NBMA + && (old_state == NSM_Down || old_state == NSM_Attempt)) { + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_OneWayReceived); + nbr->priority = hello->priority; + nbr->d_router = hello->d_router; + nbr->bd_router = hello->bd_router; + return; + } + + if (ospf_nbr_bidirectional(&oi->ospf->router_id, hello->neighbors, + size - OSPF_HELLO_MIN_SIZE)) { + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_TwoWayReceived); + nbr->options |= hello->options; + } else { + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_OneWayReceived); + /* Set neighbor information. */ + nbr->priority = hello->priority; + nbr->d_router = hello->d_router; + nbr->bd_router = hello->bd_router; + return; + } + + /* If neighbor itself declares DR and no BDR exists, + cause event BackupSeen */ + if (IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->d_router)) + if (hello->bd_router.s_addr == 0 && oi->state == ISM_Waiting) + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_BackupSeen); + + /* neighbor itself declares BDR. */ + if (oi->state == ISM_Waiting + && IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->bd_router)) + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_BackupSeen); + + /* had not previously. */ + if ((IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->d_router) + && IPV4_ADDR_CMP(&nbr->address.u.prefix4, &nbr->d_router)) + || (IPV4_ADDR_CMP(&nbr->address.u.prefix4, &hello->d_router) + && IPV4_ADDR_SAME(&nbr->address.u.prefix4, &nbr->d_router))) + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange); + + /* had not previously. */ + if ((IPV4_ADDR_SAME(&nbr->address.u.prefix4, &hello->bd_router) + && IPV4_ADDR_CMP(&nbr->address.u.prefix4, &nbr->bd_router)) + || (IPV4_ADDR_CMP(&nbr->address.u.prefix4, &hello->bd_router) + && IPV4_ADDR_SAME(&nbr->address.u.prefix4, &nbr->bd_router))) + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange); + + /* Neighbor priority check. */ + if (nbr->priority >= 0 && nbr->priority != hello->priority) + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange); + + /* Set neighbor information. */ + nbr->priority = hello->priority; + nbr->d_router = hello->d_router; + nbr->bd_router = hello->bd_router; } /* Save DD flags/options/Seqnum received. */ -static void -ospf_db_desc_save_current (struct ospf_neighbor *nbr, - struct ospf_db_desc *dd) +static void ospf_db_desc_save_current(struct ospf_neighbor *nbr, + struct ospf_db_desc *dd) { - nbr->last_recv.flags = dd->flags; - nbr->last_recv.options = dd->options; - nbr->last_recv.dd_seqnum = ntohl (dd->dd_seqnum); + nbr->last_recv.flags = dd->flags; + nbr->last_recv.options = dd->options; + nbr->last_recv.dd_seqnum = ntohl(dd->dd_seqnum); } /* Process rest of DD packet. */ -static void -ospf_db_desc_proc (struct stream *s, struct ospf_interface *oi, - struct ospf_neighbor *nbr, struct ospf_db_desc *dd, - u_int16_t size) -{ - struct ospf_lsa *new, *find; - struct lsa_header *lsah; - - stream_forward_getp (s, OSPF_DB_DESC_MIN_SIZE); - for (size -= OSPF_DB_DESC_MIN_SIZE; - size >= OSPF_LSA_HEADER_SIZE; size -= OSPF_LSA_HEADER_SIZE) - { - lsah = (struct lsa_header *) STREAM_PNT (s); - stream_forward_getp (s, OSPF_LSA_HEADER_SIZE); - - /* Unknown LS type. */ - if (lsah->type < OSPF_MIN_LSA || lsah->type >= OSPF_MAX_LSA) - { - zlog_warn ("Packet [DD:RECV]: Unknown LS type %d.", lsah->type); - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch); - return; - } - - if (IS_OPAQUE_LSA (lsah->type) - && ! CHECK_FLAG (nbr->options, OSPF_OPTION_O)) - { - zlog_warn ("LSA[Type%d:%s]: Opaque capability mismatch?", lsah->type, inet_ntoa (lsah->id)); - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch); - return; - } - - switch (lsah->type) - { - case OSPF_AS_EXTERNAL_LSA: - case OSPF_OPAQUE_AS_LSA: - /* Check for stub area. Reject if AS-External from stub but - allow if from NSSA. */ - if (oi->area->external_routing == OSPF_AREA_STUB) - { - zlog_warn ("Packet [DD:RECV]: LSA[Type%d:%s] from %s area.", - lsah->type, inet_ntoa (lsah->id), - (oi->area->external_routing == OSPF_AREA_STUB) ?\ - "STUB" : "NSSA"); - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch); - return; - } - break; - default: - break; - } - - /* Create LS-request object. */ - new = ospf_ls_request_new (lsah); - - /* Lookup received LSA, then add LS request list. */ - find = ospf_lsa_lookup_by_header (oi->area, lsah); - - /* ospf_lsa_more_recent is fine with NULL pointers */ - switch (ospf_lsa_more_recent (find, new)) - { - case -1: - /* Neighbour has a more recent LSA, we must request it */ - ospf_ls_request_add (nbr, new); - /* fallthru */ - case 0: - /* If we have a copy of this LSA, it's either less recent - * and we're requesting it from neighbour (the case above), or - * it's as recent and we both have same copy (this case). - * - * In neither of these two cases is there any point in - * describing our copy of the LSA to the neighbour in a - * DB-Summary packet, if we're still intending to do so. - * - * See: draft-ogier-ospf-dbex-opt-00.txt, describing the - * backward compatible optimisation to OSPF DB Exchange / - * DB Description process implemented here. - */ - if (find) - ospf_lsdb_delete (&nbr->db_sum, find); - ospf_lsa_discard (new); - break; - default: - /* We have the more recent copy, nothing specific to do: - * - no need to request neighbours stale copy - * - must leave DB summary list copy alone - */ - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Packet [DD:RECV]: LSA received Type %d, " - "ID %s is not recent.", lsah->type, inet_ntoa (lsah->id)); - ospf_lsa_discard (new); - } - } - - /* Master */ - if (IS_SET_DD_MS (nbr->dd_flags)) - { - nbr->dd_seqnum++; - - /* Both sides have no More, then we're done with Exchange */ - if (!IS_SET_DD_M (dd->flags) && !IS_SET_DD_M (nbr->dd_flags)) - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone); - else - ospf_db_desc_send (nbr); - } - /* Slave */ - else - { - nbr->dd_seqnum = ntohl (dd->dd_seqnum); - - /* Send DD packet in reply. - * - * Must be done to acknowledge the Master's DD, regardless of - * whether we have more LSAs ourselves to describe. - * - * This function will clear the 'More' bit, if after this DD - * we have no more LSAs to describe to the master.. - */ - ospf_db_desc_send (nbr); - - /* Slave can raise ExchangeDone now, if master is also done */ - if (!IS_SET_DD_M (dd->flags) && !IS_SET_DD_M (nbr->dd_flags)) - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone); - } - - /* Save received neighbor values from DD. */ - ospf_db_desc_save_current (nbr, dd); - - if (!nbr->t_ls_req) - ospf_ls_req_send (nbr); -} - -static int -ospf_db_desc_is_dup (struct ospf_db_desc *dd, struct ospf_neighbor *nbr) -{ - /* Is DD duplicated? */ - if (dd->options == nbr->last_recv.options && - dd->flags == nbr->last_recv.flags && - dd->dd_seqnum == htonl (nbr->last_recv.dd_seqnum)) - return 1; - - return 0; +static void ospf_db_desc_proc(struct stream *s, struct ospf_interface *oi, + struct ospf_neighbor *nbr, + struct ospf_db_desc *dd, u_int16_t size) +{ + struct ospf_lsa *new, *find; + struct lsa_header *lsah; + + stream_forward_getp(s, OSPF_DB_DESC_MIN_SIZE); + for (size -= OSPF_DB_DESC_MIN_SIZE; size >= OSPF_LSA_HEADER_SIZE; + size -= OSPF_LSA_HEADER_SIZE) { + lsah = (struct lsa_header *)STREAM_PNT(s); + stream_forward_getp(s, OSPF_LSA_HEADER_SIZE); + + /* Unknown LS type. */ + if (lsah->type < OSPF_MIN_LSA || lsah->type >= OSPF_MAX_LSA) { + zlog_warn("Packet [DD:RECV]: Unknown LS type %d.", + lsah->type); + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_SeqNumberMismatch); + return; + } + + if (IS_OPAQUE_LSA(lsah->type) + && !CHECK_FLAG(nbr->options, OSPF_OPTION_O)) { + zlog_warn("LSA[Type%d:%s]: Opaque capability mismatch?", + lsah->type, inet_ntoa(lsah->id)); + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_SeqNumberMismatch); + return; + } + + switch (lsah->type) { + case OSPF_AS_EXTERNAL_LSA: + case OSPF_OPAQUE_AS_LSA: + /* Check for stub area. Reject if AS-External from stub + but + allow if from NSSA. */ + if (oi->area->external_routing == OSPF_AREA_STUB) { + zlog_warn( + "Packet [DD:RECV]: LSA[Type%d:%s] from %s area.", + lsah->type, inet_ntoa(lsah->id), + (oi->area->external_routing + == OSPF_AREA_STUB) + ? "STUB" + : "NSSA"); + OSPF_NSM_EVENT_SCHEDULE(nbr, + NSM_SeqNumberMismatch); + return; + } + break; + default: + break; + } + + /* Create LS-request object. */ + new = ospf_ls_request_new(lsah); + + /* Lookup received LSA, then add LS request list. */ + find = ospf_lsa_lookup_by_header(oi->area, lsah); + + /* ospf_lsa_more_recent is fine with NULL pointers */ + switch (ospf_lsa_more_recent(find, new)) { + case -1: + /* Neighbour has a more recent LSA, we must request it + */ + ospf_ls_request_add(nbr, new); + /* fallthru */ + case 0: + /* If we have a copy of this LSA, it's either less + * recent + * and we're requesting it from neighbour (the case + * above), or + * it's as recent and we both have same copy (this + * case). + * + * In neither of these two cases is there any point in + * describing our copy of the LSA to the neighbour in a + * DB-Summary packet, if we're still intending to do so. + * + * See: draft-ogier-ospf-dbex-opt-00.txt, describing the + * backward compatible optimisation to OSPF DB Exchange + * / + * DB Description process implemented here. + */ + if (find) + ospf_lsdb_delete(&nbr->db_sum, find); + ospf_lsa_discard(new); + break; + default: + /* We have the more recent copy, nothing specific to do: + * - no need to request neighbours stale copy + * - must leave DB summary list copy alone + */ + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Packet [DD:RECV]: LSA received Type %d, " + "ID %s is not recent.", + lsah->type, inet_ntoa(lsah->id)); + ospf_lsa_discard(new); + } + } + + /* Master */ + if (IS_SET_DD_MS(nbr->dd_flags)) { + nbr->dd_seqnum++; + + /* Both sides have no More, then we're done with Exchange */ + if (!IS_SET_DD_M(dd->flags) && !IS_SET_DD_M(nbr->dd_flags)) + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_ExchangeDone); + else + ospf_db_desc_send(nbr); + } + /* Slave */ + else { + nbr->dd_seqnum = ntohl(dd->dd_seqnum); + + /* Send DD packet in reply. + * + * Must be done to acknowledge the Master's DD, regardless of + * whether we have more LSAs ourselves to describe. + * + * This function will clear the 'More' bit, if after this DD + * we have no more LSAs to describe to the master.. + */ + ospf_db_desc_send(nbr); + + /* Slave can raise ExchangeDone now, if master is also done */ + if (!IS_SET_DD_M(dd->flags) && !IS_SET_DD_M(nbr->dd_flags)) + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_ExchangeDone); + } + + /* Save received neighbor values from DD. */ + ospf_db_desc_save_current(nbr, dd); + + if (!nbr->t_ls_req) + ospf_ls_req_send(nbr); +} + +static int ospf_db_desc_is_dup(struct ospf_db_desc *dd, + struct ospf_neighbor *nbr) +{ + /* Is DD duplicated? */ + if (dd->options == nbr->last_recv.options + && dd->flags == nbr->last_recv.flags + && dd->dd_seqnum == htonl(nbr->last_recv.dd_seqnum)) + return 1; + + return 0; } /* OSPF Database Description message read -- RFC2328 Section 10.6. */ -static void -ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, - struct stream *s, struct ospf_interface *oi, u_int16_t size) -{ - struct ospf_db_desc *dd; - struct ospf_neighbor *nbr; - - /* Increment statistics. */ - oi->db_desc_in++; - - dd = (struct ospf_db_desc *) STREAM_PNT (s); - - nbr = ospf_nbr_lookup (oi, iph, ospfh); - if (nbr == NULL) - { - zlog_warn ("Packet[DD]: Unknown Neighbor %s", - inet_ntoa (ospfh->router_id)); - return; - } - - /* Check MTU. */ - if ((OSPF_IF_PARAM (oi, mtu_ignore) == 0) && - (ntohs (dd->mtu) > oi->ifp->mtu)) - { - zlog_warn ("Packet[DD]: Neighbor %s MTU %u is larger than [%s]'s MTU %u", - inet_ntoa (nbr->router_id), ntohs (dd->mtu), - IF_NAME (oi), oi->ifp->mtu); - return; - } - - /* - * XXX HACK by Hasso Tepper. Setting N/P bit in NSSA area DD packets is not - * required. In fact at least JunOS sends DD packets with P bit clear. - * Until proper solution is developped, this hack should help. - * - * Update: According to the RFCs, N bit is specified /only/ for Hello - * options, unfortunately its use in DD options is not specified. Hence some - * implementations follow E-bit semantics and set it in DD options, and some - * treat it as unspecified and hence follow the directive "default for - * options is clear", ie unset. - * - * Reset the flag, as ospfd follows E-bit semantics. - */ - if ( (oi->area->external_routing == OSPF_AREA_NSSA) - && (CHECK_FLAG (nbr->options, OSPF_OPTION_NP)) - && (!CHECK_FLAG (dd->options, OSPF_OPTION_NP)) ) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Packet[DD]: Neighbour %s: Has NSSA capability, sends with N bit clear in DD options", - inet_ntoa (nbr->router_id) ); - SET_FLAG (dd->options, OSPF_OPTION_NP); - } +static void ospf_db_desc(struct ip *iph, struct ospf_header *ospfh, + struct stream *s, struct ospf_interface *oi, + u_int16_t size) +{ + struct ospf_db_desc *dd; + struct ospf_neighbor *nbr; -#ifdef REJECT_IF_TBIT_ON - if (CHECK_FLAG (dd->options, OSPF_OPTION_MT)) - { - /* - * In Hello protocol, optional capability must have checked - * to prevent this T-bit enabled router be my neighbor. - */ - zlog_warn ("Packet[DD]: Neighbor %s: T-bit on?", inet_ntoa (nbr->router_id)); - return; - } -#endif /* REJECT_IF_TBIT_ON */ + /* Increment statistics. */ + oi->db_desc_in++; - if (CHECK_FLAG (dd->options, OSPF_OPTION_O) - && !CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE)) - { - /* - * This node is not configured to handle O-bit, for now. - * Clear it to ignore unsupported capability proposed by neighbor. - */ - UNSET_FLAG (dd->options, OSPF_OPTION_O); - } - - /* Add event to thread. */ - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived); - - /* Process DD packet by neighbor status. */ - switch (nbr->state) - { - case NSM_Down: - case NSM_Attempt: - case NSM_TwoWay: - zlog_warn ("Packet[DD]: Neighbor %s state is %s, packet discarded.", - inet_ntoa(nbr->router_id), - lookup_msg(ospf_nsm_state_msg, nbr->state, NULL)); - break; - case NSM_Init: - OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived); - /* If the new state is ExStart, the processing of the current - packet should then continue in this new state by falling - through to case ExStart below. */ - if (nbr->state != NSM_ExStart) - break; - /* fallthru */ - case NSM_ExStart: - /* Initial DBD */ - if ((IS_SET_DD_ALL (dd->flags) == OSPF_DD_FLAG_ALL) && - (size == OSPF_DB_DESC_MIN_SIZE)) - { - if (IPV4_ADDR_CMP (&nbr->router_id, &oi->ospf->router_id) > 0) - { - /* We're Slave---obey */ - zlog_info ("Packet[DD]: Neighbor %s Negotiation done (Slave).", - inet_ntoa(nbr->router_id)); - nbr->dd_seqnum = ntohl (dd->dd_seqnum); - - /* Reset I/MS */ - UNSET_FLAG (nbr->dd_flags, (OSPF_DD_FLAG_MS|OSPF_DD_FLAG_I)); - } - else - { - /* We're Master, ignore the initial DBD from Slave */ - zlog_info ("Packet[DD]: Neighbor %s: Initial DBD from Slave, " - "ignoring.", inet_ntoa(nbr->router_id)); - break; - } - } - /* Ack from the Slave */ - else if (!IS_SET_DD_MS (dd->flags) && !IS_SET_DD_I (dd->flags) && - ntohl (dd->dd_seqnum) == nbr->dd_seqnum && - IPV4_ADDR_CMP (&nbr->router_id, &oi->ospf->router_id) < 0) - { - zlog_info ("Packet[DD]: Neighbor %s Negotiation done (Master).", - inet_ntoa(nbr->router_id)); - /* Reset I, leaving MS */ - UNSET_FLAG (nbr->dd_flags, OSPF_DD_FLAG_I); + dd = (struct ospf_db_desc *)STREAM_PNT(s); + + nbr = ospf_nbr_lookup(oi, iph, ospfh); + if (nbr == NULL) { + zlog_warn("Packet[DD]: Unknown Neighbor %s", + inet_ntoa(ospfh->router_id)); + return; } - else - { - zlog_warn ("Packet[DD]: Neighbor %s Negotiation fails.", - inet_ntoa(nbr->router_id)); - break; - } - - /* This is where the real Options are saved */ - nbr->options = dd->options; - - if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Neighbor[%s] is %sOpaque-capable.", - inet_ntoa (nbr->router_id), - CHECK_FLAG (nbr->options, OSPF_OPTION_O) ? "" : "NOT "); - - if (! CHECK_FLAG (nbr->options, OSPF_OPTION_O) - && IPV4_ADDR_SAME (&DR (oi), &nbr->address.u.prefix4)) - { - zlog_warn ("DR-neighbor[%s] is NOT opaque-capable; " - "Opaque-LSAs cannot be reliably advertised " - "in this network.", - inet_ntoa (nbr->router_id)); - /* This situation is undesirable, but not a real error. */ - } - } - - OSPF_NSM_EVENT_EXECUTE (nbr, NSM_NegotiationDone); - - /* continue processing rest of packet. */ - ospf_db_desc_proc (s, oi, nbr, dd, size); - break; - case NSM_Exchange: - if (ospf_db_desc_is_dup (dd, nbr)) - { - if (IS_SET_DD_MS (nbr->dd_flags)) - /* Master: discard duplicated DD packet. */ - zlog_info ("Packet[DD] (Master): Neighbor %s packet duplicated.", - inet_ntoa (nbr->router_id)); - else - /* Slave: cause to retransmit the last Database Description. */ - { - zlog_info ("Packet[DD] [Slave]: Neighbor %s packet duplicated.", - inet_ntoa (nbr->router_id)); - ospf_db_desc_resend (nbr); - } - break; - } - - /* Otherwise DD packet should be checked. */ - /* Check Master/Slave bit mismatch */ - if (IS_SET_DD_MS (dd->flags) != IS_SET_DD_MS (nbr->last_recv.flags)) - { - zlog_warn ("Packet[DD]: Neighbor %s MS-bit mismatch.", - inet_ntoa(nbr->router_id)); - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch); - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Packet[DD]: dd->flags=%d, nbr->dd_flags=%d", - dd->flags, nbr->dd_flags); - break; + + /* Check MTU. */ + if ((OSPF_IF_PARAM(oi, mtu_ignore) == 0) + && (ntohs(dd->mtu) > oi->ifp->mtu)) { + zlog_warn( + "Packet[DD]: Neighbor %s MTU %u is larger than [%s]'s MTU %u", + inet_ntoa(nbr->router_id), ntohs(dd->mtu), IF_NAME(oi), + oi->ifp->mtu); + return; } - /* Check initialize bit is set. */ - if (IS_SET_DD_I (dd->flags)) - { - zlog_info ("Packet[DD]: Neighbor %s I-bit set.", - inet_ntoa(nbr->router_id)); - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch); - break; + /* + * XXX HACK by Hasso Tepper. Setting N/P bit in NSSA area DD packets is + * not + * required. In fact at least JunOS sends DD packets with P bit clear. + * Until proper solution is developped, this hack should help. + * + * Update: According to the RFCs, N bit is specified /only/ for Hello + * options, unfortunately its use in DD options is not specified. Hence + * some + * implementations follow E-bit semantics and set it in DD options, and + * some + * treat it as unspecified and hence follow the directive "default for + * options is clear", ie unset. + * + * Reset the flag, as ospfd follows E-bit semantics. + */ + if ((oi->area->external_routing == OSPF_AREA_NSSA) + && (CHECK_FLAG(nbr->options, OSPF_OPTION_NP)) + && (!CHECK_FLAG(dd->options, OSPF_OPTION_NP))) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Packet[DD]: Neighbour %s: Has NSSA capability, sends with N bit clear in DD options", + inet_ntoa(nbr->router_id)); + SET_FLAG(dd->options, OSPF_OPTION_NP); } - /* Check DD Options. */ - if (dd->options != nbr->options) - { +#ifdef REJECT_IF_TBIT_ON + if (CHECK_FLAG(dd->options, OSPF_OPTION_MT)) { + /* + * In Hello protocol, optional capability must have checked + * to prevent this T-bit enabled router be my neighbor. + */ + zlog_warn("Packet[DD]: Neighbor %s: T-bit on?", + inet_ntoa(nbr->router_id)); + return; + } +#endif /* REJECT_IF_TBIT_ON */ + + if (CHECK_FLAG(dd->options, OSPF_OPTION_O) + && !CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE)) { + /* + * This node is not configured to handle O-bit, for now. + * Clear it to ignore unsupported capability proposed by + * neighbor. + */ + UNSET_FLAG(dd->options, OSPF_OPTION_O); + } + + /* Add event to thread. */ + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_PacketReceived); + + /* Process DD packet by neighbor status. */ + switch (nbr->state) { + case NSM_Down: + case NSM_Attempt: + case NSM_TwoWay: + zlog_warn( + "Packet[DD]: Neighbor %s state is %s, packet discarded.", + inet_ntoa(nbr->router_id), + lookup_msg(ospf_nsm_state_msg, nbr->state, NULL)); + break; + case NSM_Init: + OSPF_NSM_EVENT_EXECUTE(nbr, NSM_TwoWayReceived); + /* If the new state is ExStart, the processing of the current + packet should then continue in this new state by falling + through to case ExStart below. */ + if (nbr->state != NSM_ExStart) + break; + /* fallthru */ + case NSM_ExStart: + /* Initial DBD */ + if ((IS_SET_DD_ALL(dd->flags) == OSPF_DD_FLAG_ALL) + && (size == OSPF_DB_DESC_MIN_SIZE)) { + if (IPV4_ADDR_CMP(&nbr->router_id, &oi->ospf->router_id) + > 0) { + /* We're Slave---obey */ + zlog_info( + "Packet[DD]: Neighbor %s Negotiation done (Slave).", + inet_ntoa(nbr->router_id)); + nbr->dd_seqnum = ntohl(dd->dd_seqnum); + + /* Reset I/MS */ + UNSET_FLAG(nbr->dd_flags, + (OSPF_DD_FLAG_MS | OSPF_DD_FLAG_I)); + } else { + /* We're Master, ignore the initial DBD from + * Slave */ + zlog_info( + "Packet[DD]: Neighbor %s: Initial DBD from Slave, " + "ignoring.", + inet_ntoa(nbr->router_id)); + break; + } + } + /* Ack from the Slave */ + else if (!IS_SET_DD_MS(dd->flags) && !IS_SET_DD_I(dd->flags) + && ntohl(dd->dd_seqnum) == nbr->dd_seqnum + && IPV4_ADDR_CMP(&nbr->router_id, &oi->ospf->router_id) + < 0) { + zlog_info( + "Packet[DD]: Neighbor %s Negotiation done (Master).", + inet_ntoa(nbr->router_id)); + /* Reset I, leaving MS */ + UNSET_FLAG(nbr->dd_flags, OSPF_DD_FLAG_I); + } else { + zlog_warn("Packet[DD]: Neighbor %s Negotiation fails.", + inet_ntoa(nbr->router_id)); + break; + } + + /* This is where the real Options are saved */ + nbr->options = dd->options; + + if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Neighbor[%s] is %sOpaque-capable.", + inet_ntoa(nbr->router_id), + CHECK_FLAG(nbr->options, OSPF_OPTION_O) + ? "" + : "NOT "); + + if (!CHECK_FLAG(nbr->options, OSPF_OPTION_O) + && IPV4_ADDR_SAME(&DR(oi), + &nbr->address.u.prefix4)) { + zlog_warn( + "DR-neighbor[%s] is NOT opaque-capable; " + "Opaque-LSAs cannot be reliably advertised " + "in this network.", + inet_ntoa(nbr->router_id)); + /* This situation is undesirable, but not a real + * error. */ + } + } + + OSPF_NSM_EVENT_EXECUTE(nbr, NSM_NegotiationDone); + + /* continue processing rest of packet. */ + ospf_db_desc_proc(s, oi, nbr, dd, size); + break; + case NSM_Exchange: + if (ospf_db_desc_is_dup(dd, nbr)) { + if (IS_SET_DD_MS(nbr->dd_flags)) + /* Master: discard duplicated DD packet. */ + zlog_info( + "Packet[DD] (Master): Neighbor %s packet duplicated.", + inet_ntoa(nbr->router_id)); + else + /* Slave: cause to retransmit the last Database + Description. */ + { + zlog_info( + "Packet[DD] [Slave]: Neighbor %s packet duplicated.", + inet_ntoa(nbr->router_id)); + ospf_db_desc_resend(nbr); + } + break; + } + + /* Otherwise DD packet should be checked. */ + /* Check Master/Slave bit mismatch */ + if (IS_SET_DD_MS(dd->flags) + != IS_SET_DD_MS(nbr->last_recv.flags)) { + zlog_warn("Packet[DD]: Neighbor %s MS-bit mismatch.", + inet_ntoa(nbr->router_id)); + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_SeqNumberMismatch); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Packet[DD]: dd->flags=%d, nbr->dd_flags=%d", + dd->flags, nbr->dd_flags); + break; + } + + /* Check initialize bit is set. */ + if (IS_SET_DD_I(dd->flags)) { + zlog_info("Packet[DD]: Neighbor %s I-bit set.", + inet_ntoa(nbr->router_id)); + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_SeqNumberMismatch); + break; + } + + /* Check DD Options. */ + if (dd->options != nbr->options) { #ifdef ORIGINAL_CODING - /* Save the new options for debugging */ - nbr->options = dd->options; + /* Save the new options for debugging */ + nbr->options = dd->options; #endif /* ORIGINAL_CODING */ - zlog_warn ("Packet[DD]: Neighbor %s options mismatch.", - inet_ntoa(nbr->router_id)); - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch); - break; - } + zlog_warn("Packet[DD]: Neighbor %s options mismatch.", + inet_ntoa(nbr->router_id)); + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_SeqNumberMismatch); + break; + } - /* Check DD sequence number. */ - if ((IS_SET_DD_MS (nbr->dd_flags) && - ntohl (dd->dd_seqnum) != nbr->dd_seqnum) || - (!IS_SET_DD_MS (nbr->dd_flags) && - ntohl (dd->dd_seqnum) != nbr->dd_seqnum + 1)) - { - zlog_warn ("Packet[DD]: Neighbor %s sequence number mismatch.", - inet_ntoa(nbr->router_id)); - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch); - break; - } - - /* Continue processing rest of packet. */ - ospf_db_desc_proc (s, oi, nbr, dd, size); - break; - case NSM_Loading: - case NSM_Full: - if (ospf_db_desc_is_dup (dd, nbr)) - { - if (IS_SET_DD_MS (nbr->dd_flags)) - { - /* Master should discard duplicate DD packet. */ - zlog_info ("Packet[DD]: Neighbor %s duplicated, " - "packet discarded.", - inet_ntoa(nbr->router_id)); - break; - } - else - { - if (monotime_since (&nbr->last_send_ts, NULL) - < nbr->v_inactivity * 1000000LL) - { - /* In states Loading and Full the slave must resend - its last Database Description packet in response to - duplicate Database Description packets received - from the master. For this reason the slave must - wait RouterDeadInterval seconds before freeing the - last Database Description packet. Reception of a - Database Description packet from the master after - this interval will generate a SeqNumberMismatch - neighbor event. RFC2328 Section 10.8 */ - ospf_db_desc_resend (nbr); - break; + /* Check DD sequence number. */ + if ((IS_SET_DD_MS(nbr->dd_flags) + && ntohl(dd->dd_seqnum) != nbr->dd_seqnum) + || (!IS_SET_DD_MS(nbr->dd_flags) + && ntohl(dd->dd_seqnum) != nbr->dd_seqnum + 1)) { + zlog_warn( + "Packet[DD]: Neighbor %s sequence number mismatch.", + inet_ntoa(nbr->router_id)); + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_SeqNumberMismatch); + break; + } + + /* Continue processing rest of packet. */ + ospf_db_desc_proc(s, oi, nbr, dd, size); + break; + case NSM_Loading: + case NSM_Full: + if (ospf_db_desc_is_dup(dd, nbr)) { + if (IS_SET_DD_MS(nbr->dd_flags)) { + /* Master should discard duplicate DD packet. */ + zlog_info( + "Packet[DD]: Neighbor %s duplicated, " + "packet discarded.", + inet_ntoa(nbr->router_id)); + break; + } else { + if (monotime_since(&nbr->last_send_ts, NULL) + < nbr->v_inactivity * 1000000LL) { + /* In states Loading and Full the slave + must resend + its last Database Description packet + in response to + duplicate Database Description + packets received + from the master. For this reason the + slave must + wait RouterDeadInterval seconds + before freeing the + last Database Description packet. + Reception of a + Database Description packet from the + master after + this interval will generate a + SeqNumberMismatch + neighbor event. RFC2328 Section 10.8 + */ + ospf_db_desc_resend(nbr); + break; + } + } } - } - } - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch); - break; - default: - zlog_warn ("Packet[DD]: Neighbor %s NSM illegal status %u.", - inet_ntoa(nbr->router_id), nbr->state); - break; - } + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_SeqNumberMismatch); + break; + default: + zlog_warn("Packet[DD]: Neighbor %s NSM illegal status %u.", + inet_ntoa(nbr->router_id), nbr->state); + break; + } } #define OSPF_LSA_KEY_SIZE 12 /* type(4) + id(4) + ar(4) */ /* OSPF Link State Request Read -- RFC2328 Section 10.7. */ -static void -ospf_ls_req (struct ip *iph, struct ospf_header *ospfh, - struct stream *s, struct ospf_interface *oi, u_int16_t size) -{ - struct ospf_neighbor *nbr; - u_int32_t ls_type; - struct in_addr ls_id; - struct in_addr adv_router; - struct ospf_lsa *find; - struct list *ls_upd; - unsigned int length; - - /* Increment statistics. */ - oi->ls_req_in++; - - nbr = ospf_nbr_lookup (oi, iph, ospfh); - if (nbr == NULL) - { - zlog_warn ("Link State Request: Unknown Neighbor %s.", - inet_ntoa (ospfh->router_id)); - return; - } - - /* Add event to thread. */ - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived); - - /* Neighbor State should be Exchange or later. */ - if (nbr->state != NSM_Exchange && - nbr->state != NSM_Loading && - nbr->state != NSM_Full) - { - zlog_warn ("Link State Request received from %s: " - "Neighbor state is %s, packet discarded.", - inet_ntoa (ospfh->router_id), - lookup_msg(ospf_nsm_state_msg, nbr->state, NULL)); - return; - } - - /* Send Link State Update for ALL requested LSAs. */ - ls_upd = list_new (); - length = OSPF_HEADER_SIZE + OSPF_LS_UPD_MIN_SIZE; - - while (size >= OSPF_LSA_KEY_SIZE) - { - /* Get one slice of Link State Request. */ - ls_type = stream_getl (s); - ls_id.s_addr = stream_get_ipv4 (s); - adv_router.s_addr = stream_get_ipv4 (s); - - /* Verify LSA type. */ - if (ls_type < OSPF_MIN_LSA || ls_type >= OSPF_MAX_LSA) - { - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq); - list_delete (ls_upd); - return; +static void ospf_ls_req(struct ip *iph, struct ospf_header *ospfh, + struct stream *s, struct ospf_interface *oi, + u_int16_t size) +{ + struct ospf_neighbor *nbr; + u_int32_t ls_type; + struct in_addr ls_id; + struct in_addr adv_router; + struct ospf_lsa *find; + struct list *ls_upd; + unsigned int length; + + /* Increment statistics. */ + oi->ls_req_in++; + + nbr = ospf_nbr_lookup(oi, iph, ospfh); + if (nbr == NULL) { + zlog_warn("Link State Request: Unknown Neighbor %s.", + inet_ntoa(ospfh->router_id)); + return; } - /* Search proper LSA in LSDB. */ - find = ospf_lsa_lookup (oi->area, ls_type, ls_id, adv_router); - if (find == NULL) - { - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq); - list_delete (ls_upd); - return; + /* Add event to thread. */ + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_PacketReceived); + + /* Neighbor State should be Exchange or later. */ + if (nbr->state != NSM_Exchange && nbr->state != NSM_Loading + && nbr->state != NSM_Full) { + zlog_warn( + "Link State Request received from %s: " + "Neighbor state is %s, packet discarded.", + inet_ntoa(ospfh->router_id), + lookup_msg(ospf_nsm_state_msg, nbr->state, NULL)); + return; } - /* Packet overflows MTU size, send immediately. */ - if (length + ntohs (find->data->length) > ospf_packet_max (oi)) - { - if (oi->type == OSPF_IFTYPE_NBMA) - ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_DIRECT); - else - ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_INDIRECT); + /* Send Link State Update for ALL requested LSAs. */ + ls_upd = list_new(); + length = OSPF_HEADER_SIZE + OSPF_LS_UPD_MIN_SIZE; + + while (size >= OSPF_LSA_KEY_SIZE) { + /* Get one slice of Link State Request. */ + ls_type = stream_getl(s); + ls_id.s_addr = stream_get_ipv4(s); + adv_router.s_addr = stream_get_ipv4(s); + + /* Verify LSA type. */ + if (ls_type < OSPF_MIN_LSA || ls_type >= OSPF_MAX_LSA) { + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_BadLSReq); + list_delete(ls_upd); + return; + } - /* Only remove list contents. Keep ls_upd. */ - list_delete_all_node (ls_upd); + /* Search proper LSA in LSDB. */ + find = ospf_lsa_lookup(oi->area, ls_type, ls_id, adv_router); + if (find == NULL) { + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_BadLSReq); + list_delete(ls_upd); + return; + } - length = OSPF_HEADER_SIZE + OSPF_LS_UPD_MIN_SIZE; - } + /* Packet overflows MTU size, send immediately. */ + if (length + ntohs(find->data->length) > ospf_packet_max(oi)) { + if (oi->type == OSPF_IFTYPE_NBMA) + ospf_ls_upd_send(nbr, ls_upd, + OSPF_SEND_PACKET_DIRECT); + else + ospf_ls_upd_send(nbr, ls_upd, + OSPF_SEND_PACKET_INDIRECT); + + /* Only remove list contents. Keep ls_upd. */ + list_delete_all_node(ls_upd); - /* Append LSA to update list. */ - listnode_add (ls_upd, find); - length += ntohs (find->data->length); + length = OSPF_HEADER_SIZE + OSPF_LS_UPD_MIN_SIZE; + } + + /* Append LSA to update list. */ + listnode_add(ls_upd, find); + length += ntohs(find->data->length); - size -= OSPF_LSA_KEY_SIZE; - } + size -= OSPF_LSA_KEY_SIZE; + } - /* Send rest of Link State Update. */ - if (listcount (ls_upd) > 0) - { - if (oi->type == OSPF_IFTYPE_NBMA) - ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_DIRECT); - else - ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_INDIRECT); + /* Send rest of Link State Update. */ + if (listcount(ls_upd) > 0) { + if (oi->type == OSPF_IFTYPE_NBMA) + ospf_ls_upd_send(nbr, ls_upd, OSPF_SEND_PACKET_DIRECT); + else + ospf_ls_upd_send(nbr, ls_upd, + OSPF_SEND_PACKET_INDIRECT); - list_delete (ls_upd); - } - else - list_free (ls_upd); + list_delete(ls_upd); + } else + list_free(ls_upd); } /* Get the list of LSAs from Link State Update packet. And process some validation -- RFC2328 Section 13. (1)-(2). */ -static struct list * -ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s, - struct ospf_interface *oi, size_t size) -{ - u_int16_t count, sum; - u_int32_t length; - struct lsa_header *lsah; - struct ospf_lsa *lsa; - struct list *lsas; +static struct list *ospf_ls_upd_list_lsa(struct ospf_neighbor *nbr, + struct stream *s, + struct ospf_interface *oi, size_t size) +{ + u_int16_t count, sum; + u_int32_t length; + struct lsa_header *lsah; + struct ospf_lsa *lsa; + struct list *lsas; + + lsas = list_new(); + + count = stream_getl(s); + size -= OSPF_LS_UPD_MIN_SIZE; /* # LSAs */ + + for (; size >= OSPF_LSA_HEADER_SIZE && count > 0; + size -= length, stream_forward_getp(s, length), count--) { + lsah = (struct lsa_header *)STREAM_PNT(s); + length = ntohs(lsah->length); + + if (length > size) { + zlog_warn( + "Link State Update: LSA length exceeds packet size."); + break; + } - lsas = list_new (); + /* Validate the LSA's LS checksum. */ + sum = lsah->checksum; + if (!ospf_lsa_checksum_valid(lsah)) { + /* (bug #685) more details in a one-line message make it + * possible + * to identify problem source on the one hand and to + * have a better + * chance to compress repeated messages in syslog on the + * other */ + zlog_warn( + "Link State Update: LSA checksum error %x/%x, ID=%s from: nbr %s, router ID %s, adv router %s", + sum, lsah->checksum, inet_ntoa(lsah->id), + inet_ntoa(nbr->src), inet_ntoa(nbr->router_id), + inet_ntoa(lsah->adv_router)); + continue; + } - count = stream_getl (s); - size -= OSPF_LS_UPD_MIN_SIZE; /* # LSAs */ + /* Examine the LSA's LS type. */ + if (lsah->type < OSPF_MIN_LSA || lsah->type >= OSPF_MAX_LSA) { + zlog_warn("Link State Update: Unknown LS type %d", + lsah->type); + continue; + } - for (; size >= OSPF_LSA_HEADER_SIZE && count > 0; - size -= length, stream_forward_getp (s, length), count--) - { - lsah = (struct lsa_header *) STREAM_PNT (s); - length = ntohs (lsah->length); + /* + * What if the received LSA's age is greater than MaxAge? + * Treat it as a MaxAge case -- endo. + */ + if (ntohs(lsah->ls_age) > OSPF_LSA_MAXAGE) + lsah->ls_age = htons(OSPF_LSA_MAXAGE); - if (length > size) - { - zlog_warn ("Link State Update: LSA length exceeds packet size."); - break; - } + if (CHECK_FLAG(nbr->options, OSPF_OPTION_O)) { +#ifdef STRICT_OBIT_USAGE_CHECK + if ((IS_OPAQUE_LSA(lsah->type) + && !CHECK_FLAG(lsah->options, OSPF_OPTION_O)) + || (!IS_OPAQUE_LSA(lsah->type) + && CHECK_FLAG(lsah->options, OSPF_OPTION_O))) { + /* + * This neighbor must know the exact usage of + * O-bit; + * the bit will be set in Type-9,10,11 LSAs + * only. + */ + zlog_warn("LSA[Type%d:%s]: O-bit abuse?", + lsah->type, inet_ntoa(lsah->id)); + continue; + } +#endif /* STRICT_OBIT_USAGE_CHECK */ - /* Validate the LSA's LS checksum. */ - sum = lsah->checksum; - if (! ospf_lsa_checksum_valid (lsah)) - { - /* (bug #685) more details in a one-line message make it possible - * to identify problem source on the one hand and to have a better - * chance to compress repeated messages in syslog on the other */ - zlog_warn ("Link State Update: LSA checksum error %x/%x, ID=%s from: nbr %s, router ID %s, adv router %s", - sum, lsah->checksum, inet_ntoa (lsah->id), - inet_ntoa (nbr->src), inet_ntoa (nbr->router_id), - inet_ntoa (lsah->adv_router)); - continue; - } - - /* Examine the LSA's LS type. */ - if (lsah->type < OSPF_MIN_LSA || lsah->type >= OSPF_MAX_LSA) - { - zlog_warn ("Link State Update: Unknown LS type %d", lsah->type); - continue; - } + /* Do not take in AS External Opaque-LSAs if we are a + * stub. */ + if (lsah->type == OSPF_OPAQUE_AS_LSA + && nbr->oi->area->external_routing + != OSPF_AREA_DEFAULT) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[Type%d:%s]: We are a stub, don't take this LSA.", + lsah->type, + inet_ntoa(lsah->id)); + continue; + } + } else if (IS_OPAQUE_LSA(lsah->type)) { + zlog_warn("LSA[Type%d:%s]: Opaque capability mismatch?", + lsah->type, inet_ntoa(lsah->id)); + continue; + } - /* - * What if the received LSA's age is greater than MaxAge? - * Treat it as a MaxAge case -- endo. - */ - if (ntohs (lsah->ls_age) > OSPF_LSA_MAXAGE) - lsah->ls_age = htons (OSPF_LSA_MAXAGE); + /* Create OSPF LSA instance. */ + lsa = ospf_lsa_new(); + + /* We may wish to put some error checking if type NSSA comes in + and area not in NSSA mode */ + switch (lsah->type) { + case OSPF_AS_EXTERNAL_LSA: + case OSPF_OPAQUE_AS_LSA: + lsa->area = NULL; + break; + case OSPF_OPAQUE_LINK_LSA: + lsa->oi = oi; /* Remember incoming interface for + flooding control. */ + /* Fallthrough */ + default: + lsa->area = oi->area; + break; + } - if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)) - { -#ifdef STRICT_OBIT_USAGE_CHECK - if ((IS_OPAQUE_LSA(lsah->type) && - ! CHECK_FLAG (lsah->options, OSPF_OPTION_O)) - || (! IS_OPAQUE_LSA(lsah->type) && - CHECK_FLAG (lsah->options, OSPF_OPTION_O))) - { - /* - * This neighbor must know the exact usage of O-bit; - * the bit will be set in Type-9,10,11 LSAs only. - */ - zlog_warn ("LSA[Type%d:%s]: O-bit abuse?", lsah->type, inet_ntoa (lsah->id)); - continue; - } -#endif /* STRICT_OBIT_USAGE_CHECK */ + lsa->data = ospf_lsa_data_new(length); + memcpy(lsa->data, lsah, length); + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[Type%d:%s]: %p new LSA created with Link State Update", + lsa->data->type, inet_ntoa(lsa->data->id), + (void *)lsa); + listnode_add(lsas, lsa); + } - /* Do not take in AS External Opaque-LSAs if we are a stub. */ - if (lsah->type == OSPF_OPAQUE_AS_LSA - && nbr->oi->area->external_routing != OSPF_AREA_DEFAULT) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[Type%d:%s]: We are a stub, don't take this LSA.", lsah->type, inet_ntoa (lsah->id)); - continue; - } - } - else if (IS_OPAQUE_LSA(lsah->type)) - { - zlog_warn ("LSA[Type%d:%s]: Opaque capability mismatch?", lsah->type, inet_ntoa (lsah->id)); - continue; - } - - /* Create OSPF LSA instance. */ - lsa = ospf_lsa_new (); - - /* We may wish to put some error checking if type NSSA comes in - and area not in NSSA mode */ - switch (lsah->type) - { - case OSPF_AS_EXTERNAL_LSA: - case OSPF_OPAQUE_AS_LSA: - lsa->area = NULL; - break; - case OSPF_OPAQUE_LINK_LSA: - lsa->oi = oi; /* Remember incoming interface for flooding control. */ - /* Fallthrough */ - default: - lsa->area = oi->area; - break; - } - - lsa->data = ospf_lsa_data_new (length); - memcpy (lsa->data, lsah, length); - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug("LSA[Type%d:%s]: %p new LSA created with Link State Update", - lsa->data->type, inet_ntoa (lsa->data->id), (void *)lsa); - listnode_add (lsas, lsa); - } - - return lsas; + return lsas; } /* Cleanup Update list. */ -static void -ospf_upd_list_clean (struct list *lsas) +static void ospf_upd_list_clean(struct list *lsas) { - struct listnode *node, *nnode; - struct ospf_lsa *lsa; + struct listnode *node, *nnode; + struct ospf_lsa *lsa; - for (ALL_LIST_ELEMENTS (lsas, node, nnode, lsa)) - ospf_lsa_discard (lsa); + for (ALL_LIST_ELEMENTS(lsas, node, nnode, lsa)) + ospf_lsa_discard(lsa); - list_delete (lsas); + list_delete(lsas); } /* OSPF Link State Update message read -- RFC2328 Section 13. */ -static void -ospf_ls_upd (struct ospf *ospf, struct ip *iph, struct ospf_header *ospfh, - struct stream *s, struct ospf_interface *oi, u_int16_t size) -{ - struct ospf_neighbor *nbr; - struct list *lsas; - struct listnode *node, *nnode; - struct ospf_lsa *lsa = NULL; - /* unsigned long ls_req_found = 0; */ - - /* Dis-assemble the stream, update each entry, re-encapsulate for flooding */ - - /* Increment statistics. */ - oi->ls_upd_in++; - - /* Check neighbor. */ - nbr = ospf_nbr_lookup (oi, iph, ospfh); - if (nbr == NULL) - { - zlog_warn ("Link State Update: Unknown Neighbor %s on int: %s", - inet_ntoa (ospfh->router_id), IF_NAME (oi)); - return; - } - - /* Add event to thread. */ - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived); - - /* Check neighbor state. */ - if (nbr->state < NSM_Exchange) - { - if (IS_DEBUG_OSPF (nsm, NSM_EVENTS)) - zlog_debug ("Link State Update: " - "Neighbor[%s] state %s is less than Exchange", - inet_ntoa (ospfh->router_id), - lookup_msg(ospf_nsm_state_msg, nbr->state, NULL)); - return; - } - - /* Get list of LSAs from Link State Update packet. - Also perorms Stages - * 1 (validate LSA checksum) and 2 (check for LSA consistent type) - * of section 13. - */ - lsas = ospf_ls_upd_list_lsa (nbr, s, oi, size); - -#define DISCARD_LSA(L,N) {\ - if (IS_DEBUG_OSPF_EVENT) \ - zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point %d: lsa %p" \ - " Type-%d", N, (void *)lsa, (int) lsa->data->type); \ - ospf_lsa_discard (L); \ - continue; } - - /* Process each LSA received in the one packet. - * - * Numbers in parentheses, e.g. (1), (2), etc., and the corresponding - * text below are from the steps in RFC 2328, Section 13. - */ - for (ALL_LIST_ELEMENTS (lsas, node, nnode, lsa)) - { - struct ospf_lsa *ls_ret, *current; - int ret = 1; - - if (IS_DEBUG_OSPF_NSSA) - { - char buf1[INET_ADDRSTRLEN]; - char buf2[INET_ADDRSTRLEN]; - char buf3[INET_ADDRSTRLEN]; - - zlog_debug("LSA Type-%d from %s, ID: %s, ADV: %s", - lsa->data->type, - inet_ntop (AF_INET, &ospfh->router_id, - buf1, INET_ADDRSTRLEN), - inet_ntop (AF_INET, &lsa->data->id, - buf2, INET_ADDRSTRLEN), - inet_ntop (AF_INET, &lsa->data->adv_router, - buf3, INET_ADDRSTRLEN)); - } - - listnode_delete (lsas, lsa); /* We don't need it in list anymore */ - - /* (1) Validate Checksum - Done above by ospf_ls_upd_list_lsa() */ - - /* (2) LSA Type - Done above by ospf_ls_upd_list_lsa() */ - - /* (3) Do not take in AS External LSAs if we are a stub or NSSA. */ - - /* Do not take in AS NSSA if this neighbor and we are not NSSA */ - - /* Do take in Type-7's if we are an NSSA */ - - /* If we are also an ABR, later translate them to a Type-5 packet */ - - /* Later, an NSSA Re-fresh can Re-fresh Type-7's and an ABR will - translate them to a separate Type-5 packet. */ - - if (lsa->data->type == OSPF_AS_EXTERNAL_LSA) - /* Reject from STUB or NSSA */ - if (nbr->oi->area->external_routing != OSPF_AREA_DEFAULT) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug("Incoming External LSA Discarded: We are NSSA/STUB Area"); - DISCARD_LSA (lsa, 1); - } - - if (lsa->data->type == OSPF_AS_NSSA_LSA) - if (nbr->oi->area->external_routing != OSPF_AREA_NSSA) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug("Incoming NSSA LSA Discarded: Not NSSA Area"); - DISCARD_LSA (lsa,2); - } - - /* VU229804: Router-LSA Adv-ID must be equal to LS-ID */ - if (lsa->data->type == OSPF_ROUTER_LSA) - if (!IPV4_ADDR_SAME(&lsa->data->id, &lsa->data->adv_router)) - { - char buf1[INET_ADDRSTRLEN]; - char buf2[INET_ADDRSTRLEN]; - char buf3[INET_ADDRSTRLEN]; - - zlog_err("Incoming Router-LSA from %s with " - "Adv-ID[%s] != LS-ID[%s]", - inet_ntop (AF_INET, &ospfh->router_id, - buf1, INET_ADDRSTRLEN), - inet_ntop (AF_INET, &lsa->data->id, - buf2, INET_ADDRSTRLEN), - inet_ntop (AF_INET, &lsa->data->adv_router, - buf3, INET_ADDRSTRLEN)); - zlog_err("OSPF domain compromised by attack or corruption. " - "Verify correct operation of -ALL- OSPF routers."); - DISCARD_LSA (lsa, 0); - } - - /* Find the LSA in the current database. */ - - current = ospf_lsa_lookup_by_header (oi->area, lsa->data); - - /* (4) If the LSA's LS age is equal to MaxAge, and there is currently - no instance of the LSA in the router's link state database, - and none of router's neighbors are in states Exchange or Loading, - then take the following actions: */ - - if (IS_LSA_MAXAGE (lsa) && !current && - ospf_check_nbr_status(oi->ospf)) - { - /* (4a) Response Link State Acknowledgment. */ - ospf_ls_ack_send (nbr, lsa); - - /* (4b) Discard LSA. */ - if (IS_DEBUG_OSPF (lsa, LSA)) - { - zlog_debug ("Link State Update[%s]: LS age is equal to MaxAge.", - dump_lsa_key(lsa)); - } - DISCARD_LSA (lsa, 3); - } - - if (IS_OPAQUE_LSA (lsa->data->type) - && IPV4_ADDR_SAME (&lsa->data->adv_router, &oi->ospf->router_id)) - { - /* - * Even if initial flushing seems to be completed, there might - * be a case that self-originated LSA with MaxAge still remain - * in the routing domain. - * Just send an LSAck message to cease retransmission. - */ - if (IS_LSA_MAXAGE (lsa)) - { - zlog_warn ("LSA[%s]: Boomerang effect?", dump_lsa_key (lsa)); - ospf_ls_ack_send (nbr, lsa); - ospf_lsa_discard (lsa); - - if (current != NULL && ! IS_LSA_MAXAGE (current)) - ospf_opaque_lsa_refresh_schedule (current); - continue; - } - - /* - * If an instance of self-originated Opaque-LSA is not found - * in the LSDB, there are some possible cases here. - * - * 1) This node lost opaque-capability after restart. - * 2) Else, a part of opaque-type is no more supported. - * 3) Else, a part of opaque-id is no more supported. - * - * Anyway, it is still this node's responsibility to flush it. - * Otherwise, the LSA instance remains in the routing domain - * until its age reaches to MaxAge. - */ - /* XXX: We should deal with this for *ALL* LSAs, not just opaque */ - if (current == NULL) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[%s]: Previously originated Opaque-LSA," - "not found in the LSDB.", dump_lsa_key (lsa)); - - SET_FLAG (lsa->flags, OSPF_LSA_SELF); - - ospf_opaque_self_originated_lsa_received (nbr, lsa); - ospf_ls_ack_send (nbr, lsa); - - continue; - } - } - - /* It might be happen that received LSA is self-originated network LSA, but - * router ID is changed. So, we should check if LSA is a network-LSA whose - * Link State ID is one of the router's own IP interface addresses but whose - * Advertising Router is not equal to the router's own Router ID - * According to RFC 2328 12.4.2 and 13.4 this LSA should be flushed. - */ - - if(lsa->data->type == OSPF_NETWORK_LSA) - { - struct listnode *oinode, *oinnode; - struct ospf_interface *out_if; - int Flag = 0; - - for (ALL_LIST_ELEMENTS (oi->ospf->oiflist, oinode, oinnode, out_if)) - { - if(out_if == NULL) - break; - - if((IPV4_ADDR_SAME(&out_if->address->u.prefix4, &lsa->data->id)) && - (!(IPV4_ADDR_SAME(&oi->ospf->router_id, &lsa->data->adv_router)))) - { - if(out_if->network_lsa_self) - { - ospf_lsa_flush_area(lsa,out_if->area); - if(IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point 9: lsa %p Type-%d", - (void *)lsa, (int) lsa->data->type); - ospf_lsa_discard (lsa); - Flag = 1; - } - break; - } - } - if(Flag) - continue; - } - - /* (5) Find the instance of this LSA that is currently contained - in the router's link state database. If there is no - database copy, or the received LSA is more recent than - the database copy the following steps must be performed. - (The sub steps from RFC 2328 section 13 step (5) will be performed in - ospf_flood() ) */ - - if (current == NULL || - (ret = ospf_lsa_more_recent (current, lsa)) < 0) - { - /* Actual flooding procedure. */ - if (ospf_flood (oi->ospf, nbr, current, lsa) < 0) /* Trap NSSA later. */ - DISCARD_LSA (lsa, 4); - continue; +static void ospf_ls_upd(struct ospf *ospf, struct ip *iph, + struct ospf_header *ospfh, struct stream *s, + struct ospf_interface *oi, u_int16_t size) +{ + struct ospf_neighbor *nbr; + struct list *lsas; + struct listnode *node, *nnode; + struct ospf_lsa *lsa = NULL; + /* unsigned long ls_req_found = 0; */ + + /* Dis-assemble the stream, update each entry, re-encapsulate for + * flooding */ + + /* Increment statistics. */ + oi->ls_upd_in++; + + /* Check neighbor. */ + nbr = ospf_nbr_lookup(oi, iph, ospfh); + if (nbr == NULL) { + zlog_warn("Link State Update: Unknown Neighbor %s on int: %s", + inet_ntoa(ospfh->router_id), IF_NAME(oi)); + return; } - /* (6) Else, If there is an instance of the LSA on the sending - neighbor's Link state request list, an error has occurred in - the Database Exchange process. In this case, restart the - Database Exchange process by generating the neighbor event - BadLSReq for the sending neighbor and stop processing the - Link State Update packet. */ - - if (ospf_ls_request_lookup (nbr, lsa)) - { - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq); - zlog_warn("LSA[%s] instance exists on Link state request list", - dump_lsa_key(lsa)); + /* Add event to thread. */ + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_PacketReceived); + + /* Check neighbor state. */ + if (nbr->state < NSM_Exchange) { + if (IS_DEBUG_OSPF(nsm, NSM_EVENTS)) + zlog_debug( + "Link State Update: " + "Neighbor[%s] state %s is less than Exchange", + inet_ntoa(ospfh->router_id), + lookup_msg(ospf_nsm_state_msg, nbr->state, + NULL)); + return; + } - /* Clean list of LSAs. */ - ospf_upd_list_clean (lsas); - /* this lsa is not on lsas list already. */ - ospf_lsa_discard (lsa); - return; + /* Get list of LSAs from Link State Update packet. - Also perorms Stages + * 1 (validate LSA checksum) and 2 (check for LSA consistent type) + * of section 13. + */ + lsas = ospf_ls_upd_list_lsa(nbr, s, oi, size); + +#define DISCARD_LSA(L, N) \ + { \ + if (IS_DEBUG_OSPF_EVENT) \ + zlog_debug( \ + "ospf_lsa_discard() in ospf_ls_upd() point %d: lsa %p" \ + " Type-%d", \ + N, (void *)lsa, (int)lsa->data->type); \ + ospf_lsa_discard(L); \ + continue; \ } - /* If the received LSA is the same instance as the database copy - (i.e., neither one is more recent) the following two steps - should be performed: */ + /* Process each LSA received in the one packet. + * + * Numbers in parentheses, e.g. (1), (2), etc., and the corresponding + * text below are from the steps in RFC 2328, Section 13. + */ + for (ALL_LIST_ELEMENTS(lsas, node, nnode, lsa)) { + struct ospf_lsa *ls_ret, *current; + int ret = 1; + + if (IS_DEBUG_OSPF_NSSA) { + char buf1[INET_ADDRSTRLEN]; + char buf2[INET_ADDRSTRLEN]; + char buf3[INET_ADDRSTRLEN]; + + zlog_debug("LSA Type-%d from %s, ID: %s, ADV: %s", + lsa->data->type, + inet_ntop(AF_INET, &ospfh->router_id, buf1, + INET_ADDRSTRLEN), + inet_ntop(AF_INET, &lsa->data->id, buf2, + INET_ADDRSTRLEN), + inet_ntop(AF_INET, &lsa->data->adv_router, + buf3, INET_ADDRSTRLEN)); + } - if (ret == 0) - { - /* If the LSA is listed in the Link state retransmission list - for the receiving adjacency, the router itself is expecting - an acknowledgment for this LSA. The router should treat the - received LSA as an acknowledgment by removing the LSA from - the Link state retransmission list. This is termed an - "implied acknowledgment". */ - - ls_ret = ospf_ls_retransmit_lookup (nbr, lsa); - - if (ls_ret != NULL) - { - ospf_ls_retransmit_delete (nbr, ls_ret); - - /* Delayed acknowledgment sent if advertisement received - from Designated Router, otherwise do nothing. */ - if (oi->state == ISM_Backup) - if (NBR_IS_DR (nbr)) - listnode_add (oi->ls_ack, ospf_lsa_lock (lsa)); - - DISCARD_LSA (lsa, 5); - } - else - /* Acknowledge the receipt of the LSA by sending a - Link State Acknowledgment packet back out the receiving - interface. */ - { - ospf_ls_ack_send (nbr, lsa); - DISCARD_LSA (lsa, 6); - } - } - - /* The database copy is more recent. If the database copy - has LS age equal to MaxAge and LS sequence number equal to - MaxSequenceNumber, simply discard the received LSA without - acknowledging it. (In this case, the LSA's LS sequence number is - wrapping, and the MaxSequenceNumber LSA must be completely - flushed before any new LSA instance can be introduced). */ - - else if (ret > 0) /* Database copy is more recent */ - { - if (IS_LSA_MAXAGE (current) && - current->data->ls_seqnum == htonl (OSPF_MAX_SEQUENCE_NUMBER)) - { - DISCARD_LSA (lsa, 7); - } - /* Otherwise, as long as the database copy has not been sent in a - Link State Update within the last MinLSArrival seconds, send the - database copy back to the sending neighbor, encapsulated within - a Link State Update Packet. The Link State Update Packet should - be sent directly to the neighbor. In so doing, do not put the - database copy of the LSA on the neighbor's link state - retransmission list, and do not acknowledge the received (less - recent) LSA instance. */ - else - { - if (monotime_since (¤t->tv_orig, NULL) - >= ospf->min_ls_arrival * 1000LL) - /* Trap NSSA type later.*/ - ospf_ls_upd_send_lsa (nbr, current, OSPF_SEND_PACKET_DIRECT); - DISCARD_LSA (lsa, 8); - } - } - } + listnode_delete(lsas, + lsa); /* We don't need it in list anymore */ + + /* (1) Validate Checksum - Done above by ospf_ls_upd_list_lsa() + */ + + /* (2) LSA Type - Done above by ospf_ls_upd_list_lsa() */ + + /* (3) Do not take in AS External LSAs if we are a stub or NSSA. + */ + + /* Do not take in AS NSSA if this neighbor and we are not NSSA + */ + + /* Do take in Type-7's if we are an NSSA */ + + /* If we are also an ABR, later translate them to a Type-5 + * packet */ + + /* Later, an NSSA Re-fresh can Re-fresh Type-7's and an ABR will + translate them to a separate Type-5 packet. */ + + if (lsa->data->type == OSPF_AS_EXTERNAL_LSA) + /* Reject from STUB or NSSA */ + if (nbr->oi->area->external_routing + != OSPF_AREA_DEFAULT) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "Incoming External LSA Discarded: We are NSSA/STUB Area"); + DISCARD_LSA(lsa, 1); + } + + if (lsa->data->type == OSPF_AS_NSSA_LSA) + if (nbr->oi->area->external_routing != OSPF_AREA_NSSA) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "Incoming NSSA LSA Discarded: Not NSSA Area"); + DISCARD_LSA(lsa, 2); + } + + /* VU229804: Router-LSA Adv-ID must be equal to LS-ID */ + if (lsa->data->type == OSPF_ROUTER_LSA) + if (!IPV4_ADDR_SAME(&lsa->data->id, + &lsa->data->adv_router)) { + char buf1[INET_ADDRSTRLEN]; + char buf2[INET_ADDRSTRLEN]; + char buf3[INET_ADDRSTRLEN]; + + zlog_err( + "Incoming Router-LSA from %s with " + "Adv-ID[%s] != LS-ID[%s]", + inet_ntop(AF_INET, &ospfh->router_id, + buf1, INET_ADDRSTRLEN), + inet_ntop(AF_INET, &lsa->data->id, buf2, + INET_ADDRSTRLEN), + inet_ntop(AF_INET, + &lsa->data->adv_router, buf3, + INET_ADDRSTRLEN)); + zlog_err( + "OSPF domain compromised by attack or corruption. " + "Verify correct operation of -ALL- OSPF routers."); + DISCARD_LSA(lsa, 0); + } + + /* Find the LSA in the current database. */ + + current = ospf_lsa_lookup_by_header(oi->area, lsa->data); + + /* (4) If the LSA's LS age is equal to MaxAge, and there is + currently + no instance of the LSA in the router's link state database, + and none of router's neighbors are in states Exchange or + Loading, + then take the following actions: */ + + if (IS_LSA_MAXAGE(lsa) && !current + && ospf_check_nbr_status(oi->ospf)) { + /* (4a) Response Link State Acknowledgment. */ + ospf_ls_ack_send(nbr, lsa); + + /* (4b) Discard LSA. */ + if (IS_DEBUG_OSPF(lsa, LSA)) { + zlog_debug( + "Link State Update[%s]: LS age is equal to MaxAge.", + dump_lsa_key(lsa)); + } + DISCARD_LSA(lsa, 3); + } + + if (IS_OPAQUE_LSA(lsa->data->type) + && IPV4_ADDR_SAME(&lsa->data->adv_router, + &oi->ospf->router_id)) { + /* + * Even if initial flushing seems to be completed, there + * might + * be a case that self-originated LSA with MaxAge still + * remain + * in the routing domain. + * Just send an LSAck message to cease retransmission. + */ + if (IS_LSA_MAXAGE(lsa)) { + zlog_warn("LSA[%s]: Boomerang effect?", + dump_lsa_key(lsa)); + ospf_ls_ack_send(nbr, lsa); + ospf_lsa_discard(lsa); + + if (current != NULL && !IS_LSA_MAXAGE(current)) + ospf_opaque_lsa_refresh_schedule( + current); + continue; + } + + /* + * If an instance of self-originated Opaque-LSA is not + * found + * in the LSDB, there are some possible cases here. + * + * 1) This node lost opaque-capability after restart. + * 2) Else, a part of opaque-type is no more supported. + * 3) Else, a part of opaque-id is no more supported. + * + * Anyway, it is still this node's responsibility to + * flush it. + * Otherwise, the LSA instance remains in the routing + * domain + * until its age reaches to MaxAge. + */ + /* XXX: We should deal with this for *ALL* LSAs, not + * just opaque */ + if (current == NULL) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[%s]: Previously originated Opaque-LSA," + "not found in the LSDB.", + dump_lsa_key(lsa)); + + SET_FLAG(lsa->flags, OSPF_LSA_SELF); + + ospf_opaque_self_originated_lsa_received(nbr, + lsa); + ospf_ls_ack_send(nbr, lsa); + + continue; + } + } + + /* It might be happen that received LSA is self-originated + * network LSA, but + * router ID is changed. So, we should check if LSA is a + * network-LSA whose + * Link State ID is one of the router's own IP interface + * addresses but whose + * Advertising Router is not equal to the router's own Router ID + * According to RFC 2328 12.4.2 and 13.4 this LSA should be + * flushed. + */ + + if (lsa->data->type == OSPF_NETWORK_LSA) { + struct listnode *oinode, *oinnode; + struct ospf_interface *out_if; + int Flag = 0; + + for (ALL_LIST_ELEMENTS(oi->ospf->oiflist, oinode, + oinnode, out_if)) { + if (out_if == NULL) + break; + + if ((IPV4_ADDR_SAME(&out_if->address->u.prefix4, + &lsa->data->id)) + && (!(IPV4_ADDR_SAME( + &oi->ospf->router_id, + &lsa->data->adv_router)))) { + if (out_if->network_lsa_self) { + ospf_lsa_flush_area( + lsa, out_if->area); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_lsa_discard() in ospf_ls_upd() point 9: lsa %p Type-%d", + (void *)lsa, + (int)lsa->data + ->type); + ospf_lsa_discard(lsa); + Flag = 1; + } + break; + } + } + if (Flag) + continue; + } + + /* (5) Find the instance of this LSA that is currently contained + in the router's link state database. If there is no + database copy, or the received LSA is more recent than + the database copy the following steps must be performed. + (The sub steps from RFC 2328 section 13 step (5) will be + performed in + ospf_flood() ) */ + + if (current == NULL + || (ret = ospf_lsa_more_recent(current, lsa)) < 0) { + /* Actual flooding procedure. */ + if (ospf_flood(oi->ospf, nbr, current, lsa) + < 0) /* Trap NSSA later. */ + DISCARD_LSA(lsa, 4); + continue; + } + + /* (6) Else, If there is an instance of the LSA on the sending + neighbor's Link state request list, an error has occurred in + the Database Exchange process. In this case, restart the + Database Exchange process by generating the neighbor event + BadLSReq for the sending neighbor and stop processing the + Link State Update packet. */ + + if (ospf_ls_request_lookup(nbr, lsa)) { + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_BadLSReq); + zlog_warn( + "LSA[%s] instance exists on Link state request list", + dump_lsa_key(lsa)); + + /* Clean list of LSAs. */ + ospf_upd_list_clean(lsas); + /* this lsa is not on lsas list already. */ + ospf_lsa_discard(lsa); + return; + } + + /* If the received LSA is the same instance as the database copy + (i.e., neither one is more recent) the following two steps + should be performed: */ + + if (ret == 0) { + /* If the LSA is listed in the Link state retransmission + list + for the receiving adjacency, the router itself is + expecting + an acknowledgment for this LSA. The router should + treat the + received LSA as an acknowledgment by removing the LSA + from + the Link state retransmission list. This is termed + an + "implied acknowledgment". */ + + ls_ret = ospf_ls_retransmit_lookup(nbr, lsa); + + if (ls_ret != NULL) { + ospf_ls_retransmit_delete(nbr, ls_ret); + + /* Delayed acknowledgment sent if advertisement + received + from Designated Router, otherwise do nothing. + */ + if (oi->state == ISM_Backup) + if (NBR_IS_DR(nbr)) + listnode_add( + oi->ls_ack, + ospf_lsa_lock(lsa)); + + DISCARD_LSA(lsa, 5); + } else + /* Acknowledge the receipt of the LSA by sending a + Link State Acknowledgment packet back out the + receiving + interface. */ + { + ospf_ls_ack_send(nbr, lsa); + DISCARD_LSA(lsa, 6); + } + } + + /* The database copy is more recent. If the database copy + has LS age equal to MaxAge and LS sequence number equal to + MaxSequenceNumber, simply discard the received LSA without + acknowledging it. (In this case, the LSA's LS sequence number + is + wrapping, and the MaxSequenceNumber LSA must be completely + flushed before any new LSA instance can be introduced). */ + + else if (ret > 0) /* Database copy is more recent */ + { + if (IS_LSA_MAXAGE(current) + && current->data->ls_seqnum + == htonl(OSPF_MAX_SEQUENCE_NUMBER)) { + DISCARD_LSA(lsa, 7); + } + /* Otherwise, as long as the database copy has not been + sent in a + Link State Update within the last MinLSArrival + seconds, send the + database copy back to the sending neighbor, + encapsulated within + a Link State Update Packet. The Link State Update + Packet should + be sent directly to the neighbor. In so doing, do not + put the + database copy of the LSA on the neighbor's link state + retransmission list, and do not acknowledge the + received (less + recent) LSA instance. */ + else { + if (monotime_since(¤t->tv_orig, NULL) + >= ospf->min_ls_arrival * 1000LL) + /* Trap NSSA type later.*/ + ospf_ls_upd_send_lsa( + nbr, current, + OSPF_SEND_PACKET_DIRECT); + DISCARD_LSA(lsa, 8); + } + } + } #undef DISCARD_LSA - assert (listcount (lsas) == 0); - list_delete (lsas); + assert(listcount(lsas) == 0); + list_delete(lsas); } /* OSPF Link State Acknowledgment message read -- RFC2328 Section 13.7. */ -static void -ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh, - struct stream *s, struct ospf_interface *oi, u_int16_t size) -{ - struct ospf_neighbor *nbr; - - /* increment statistics. */ - oi->ls_ack_in++; - - nbr = ospf_nbr_lookup (oi, iph, ospfh); - if (nbr == NULL) - { - zlog_warn ("Link State Acknowledgment: Unknown Neighbor %s.", - inet_ntoa (ospfh->router_id)); - return; - } - - /* Add event to thread. */ - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived); - - if (nbr->state < NSM_Exchange) - { - if (IS_DEBUG_OSPF (nsm, NSM_EVENTS)) - zlog_debug ("Link State Acknowledgment: " - "Neighbor[%s] state %s is less than Exchange", - inet_ntoa (ospfh->router_id), - lookup_msg(ospf_nsm_state_msg, nbr->state, NULL)); - return; - } - - while (size >= OSPF_LSA_HEADER_SIZE) - { - struct ospf_lsa *lsa, *lsr; - - lsa = ospf_lsa_new (); - lsa->data = (struct lsa_header *) STREAM_PNT (s); - - /* lsah = (struct lsa_header *) STREAM_PNT (s); */ - size -= OSPF_LSA_HEADER_SIZE; - stream_forward_getp (s, OSPF_LSA_HEADER_SIZE); - - if (lsa->data->type < OSPF_MIN_LSA || lsa->data->type >= OSPF_MAX_LSA) +static void ospf_ls_ack(struct ip *iph, struct ospf_header *ospfh, + struct stream *s, struct ospf_interface *oi, + u_int16_t size) +{ + struct ospf_neighbor *nbr; + + /* increment statistics. */ + oi->ls_ack_in++; + + nbr = ospf_nbr_lookup(oi, iph, ospfh); + if (nbr == NULL) { + zlog_warn("Link State Acknowledgment: Unknown Neighbor %s.", + inet_ntoa(ospfh->router_id)); + return; + } + + /* Add event to thread. */ + OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_PacketReceived); + + if (nbr->state < NSM_Exchange) { + if (IS_DEBUG_OSPF(nsm, NSM_EVENTS)) + zlog_debug( + "Link State Acknowledgment: " + "Neighbor[%s] state %s is less than Exchange", + inet_ntoa(ospfh->router_id), + lookup_msg(ospf_nsm_state_msg, nbr->state, + NULL)); + return; + } + + while (size >= OSPF_LSA_HEADER_SIZE) { + struct ospf_lsa *lsa, *lsr; + + lsa = ospf_lsa_new(); + lsa->data = (struct lsa_header *)STREAM_PNT(s); + + /* lsah = (struct lsa_header *) STREAM_PNT (s); */ + size -= OSPF_LSA_HEADER_SIZE; + stream_forward_getp(s, OSPF_LSA_HEADER_SIZE); + + if (lsa->data->type < OSPF_MIN_LSA + || lsa->data->type >= OSPF_MAX_LSA) { + lsa->data = NULL; + ospf_lsa_discard(lsa); + continue; + } + + lsr = ospf_ls_retransmit_lookup(nbr, lsa); + + if (lsr != NULL && ospf_lsa_more_recent(lsr, lsa) == 0) + ospf_ls_retransmit_delete(nbr, lsr); + + lsa->data = NULL; + ospf_lsa_discard(lsa); + } + + return; +} + +static struct stream *ospf_recv_packet(int fd, struct interface **ifp, + struct stream *ibuf) +{ + int ret; + struct ip *iph; + u_int16_t ip_len; + ifindex_t ifindex = 0; + struct iovec iov; + /* Header and data both require alignment. */ + char buff[CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())]; + struct msghdr msgh; + + memset(&msgh, 0, sizeof(struct msghdr)); + msgh.msg_iov = &iov; + msgh.msg_iovlen = 1; + msgh.msg_control = (caddr_t)buff; + msgh.msg_controllen = sizeof(buff); + + ret = stream_recvmsg(ibuf, fd, &msgh, 0, OSPF_MAX_PACKET_SIZE + 1); + if (ret < 0) { + zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno)); + return NULL; + } + if ((unsigned int)ret < sizeof(iph)) /* ret must be > 0 now */ { - lsa->data = NULL; - ospf_lsa_discard (lsa); - continue; - } - - lsr = ospf_ls_retransmit_lookup (nbr, lsa); - - if (lsr != NULL && ospf_lsa_more_recent (lsr, lsa) == 0) - ospf_ls_retransmit_delete (nbr, lsr); - - lsa->data = NULL; - ospf_lsa_discard (lsa); - } - - return; -} - -static struct stream * -ospf_recv_packet (int fd, struct interface **ifp, struct stream *ibuf) -{ - int ret; - struct ip *iph; - u_int16_t ip_len; - ifindex_t ifindex = 0; - struct iovec iov; - /* Header and data both require alignment. */ - char buff [CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())]; - struct msghdr msgh; - - memset (&msgh, 0, sizeof (struct msghdr)); - msgh.msg_iov = &iov; - msgh.msg_iovlen = 1; - msgh.msg_control = (caddr_t) buff; - msgh.msg_controllen = sizeof (buff); - - ret = stream_recvmsg (ibuf, fd, &msgh, 0, OSPF_MAX_PACKET_SIZE+1); - if (ret < 0) - { - zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno)); - return NULL; - } - if ((unsigned int)ret < sizeof(iph)) /* ret must be > 0 now */ - { - zlog_warn("ospf_recv_packet: discarding runt packet of length %d " - "(ip header size is %u)", - ret, (u_int)sizeof(iph)); - return NULL; - } - - /* Note that there should not be alignment problems with this assignment - because this is at the beginning of the stream data buffer. */ - iph = (struct ip *) STREAM_DATA(ibuf); - sockopt_iphdrincl_swab_systoh (iph); - - ip_len = iph->ip_len; - + zlog_warn( + "ospf_recv_packet: discarding runt packet of length %d " + "(ip header size is %u)", + ret, (u_int)sizeof(iph)); + return NULL; + } + + /* Note that there should not be alignment problems with this assignment + because this is at the beginning of the stream data buffer. */ + iph = (struct ip *)STREAM_DATA(ibuf); + sockopt_iphdrincl_swab_systoh(iph); + + ip_len = iph->ip_len; + #if !defined(GNU_LINUX) && (OpenBSD < 200311) && (__FreeBSD_version < 1000000) - /* - * Kernel network code touches incoming IP header parameters, - * before protocol specific processing. - * - * 1) Convert byteorder to host representation. - * --> ip_len, ip_id, ip_off - * - * 2) Adjust ip_len to strip IP header size! - * --> If user process receives entire IP packet via RAW - * socket, it must consider adding IP header size to - * the "ip_len" field of "ip" structure. - * - * For more details, see . - */ - ip_len = ip_len + (iph->ip_hl << 2); + /* + * Kernel network code touches incoming IP header parameters, + * before protocol specific processing. + * + * 1) Convert byteorder to host representation. + * --> ip_len, ip_id, ip_off + * + * 2) Adjust ip_len to strip IP header size! + * --> If user process receives entire IP packet via RAW + * socket, it must consider adding IP header size to + * the "ip_len" field of "ip" structure. + * + * For more details, see . + */ + ip_len = ip_len + (iph->ip_hl << 2); #endif - + #if defined(__DragonFly__) - /* - * in DragonFly's raw socket, ip_len/ip_off are read - * in network byte order. - * As OpenBSD < 200311 adjust ip_len to strip IP header size! - */ - ip_len = ntohs(iph->ip_len) + (iph->ip_hl << 2); + /* + * in DragonFly's raw socket, ip_len/ip_off are read + * in network byte order. + * As OpenBSD < 200311 adjust ip_len to strip IP header size! + */ + ip_len = ntohs(iph->ip_len) + (iph->ip_hl << 2); #endif - ifindex = getsockopt_ifindex (AF_INET, &msgh); - - *ifp = if_lookup_by_index (ifindex, VRF_DEFAULT); + ifindex = getsockopt_ifindex(AF_INET, &msgh); + + *ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); + + if (ret != ip_len) { + zlog_warn( + "ospf_recv_packet read length mismatch: ip_len is %d, " + "but recvmsg returned %d", + ip_len, ret); + return NULL; + } - if (ret != ip_len) - { - zlog_warn ("ospf_recv_packet read length mismatch: ip_len is %d, " - "but recvmsg returned %d", ip_len, ret); - return NULL; - } - - return ibuf; + return ibuf; } static struct ospf_interface * -ospf_associate_packet_vl (struct ospf *ospf, struct interface *ifp, - struct ip *iph, struct ospf_header *ospfh) -{ - struct ospf_interface *rcv_oi; - struct ospf_vl_data *vl_data; - struct ospf_area *vl_area; - struct listnode *node; - - if (IN_MULTICAST (ntohl (iph->ip_dst.s_addr)) || - !OSPF_IS_AREA_BACKBONE (ospfh)) - return NULL; - - /* look for local OSPF interface matching the destination - * to determine Area ID. We presume therefore the destination address - * is unique, or at least (for "unnumbered" links), not used in other - * areas - */ - if ((rcv_oi = ospf_if_lookup_by_local_addr (ospf, NULL, - iph->ip_dst)) == NULL) - return NULL; - - for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data)) - { - vl_area = ospf_area_lookup_by_area_id (ospf, vl_data->vl_area_id); - if (!vl_area) - continue; - - if (OSPF_AREA_SAME (&vl_area, &rcv_oi->area) && - IPV4_ADDR_SAME (&vl_data->vl_peer, &ospfh->router_id)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("associating packet with %s", - IF_NAME (vl_data->vl_oi)); - if (! CHECK_FLAG (vl_data->vl_oi->ifp->flags, IFF_UP)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("This VL is not up yet, sorry"); - return NULL; - } - - return vl_data->vl_oi; +ospf_associate_packet_vl(struct ospf *ospf, struct interface *ifp, + struct ip *iph, struct ospf_header *ospfh) +{ + struct ospf_interface *rcv_oi; + struct ospf_vl_data *vl_data; + struct ospf_area *vl_area; + struct listnode *node; + + if (IN_MULTICAST(ntohl(iph->ip_dst.s_addr)) + || !OSPF_IS_AREA_BACKBONE(ospfh)) + return NULL; + + /* look for local OSPF interface matching the destination + * to determine Area ID. We presume therefore the destination address + * is unique, or at least (for "unnumbered" links), not used in other + * areas + */ + if ((rcv_oi = ospf_if_lookup_by_local_addr(ospf, NULL, iph->ip_dst)) + == NULL) + return NULL; + + for (ALL_LIST_ELEMENTS_RO(ospf->vlinks, node, vl_data)) { + vl_area = + ospf_area_lookup_by_area_id(ospf, vl_data->vl_area_id); + if (!vl_area) + continue; + + if (OSPF_AREA_SAME(&vl_area, &rcv_oi->area) + && IPV4_ADDR_SAME(&vl_data->vl_peer, &ospfh->router_id)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("associating packet with %s", + IF_NAME(vl_data->vl_oi)); + if (!CHECK_FLAG(vl_data->vl_oi->ifp->flags, IFF_UP)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "This VL is not up yet, sorry"); + return NULL; + } + + return vl_data->vl_oi; + } } - } - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("couldn't find any VL to associate the packet with"); - - return NULL; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("couldn't find any VL to associate the packet with"); + + return NULL; } -static int -ospf_check_area_id (struct ospf_interface *oi, struct ospf_header *ospfh) +static int ospf_check_area_id(struct ospf_interface *oi, + struct ospf_header *ospfh) { - /* Check match the Area ID of the receiving interface. */ - if (OSPF_AREA_SAME (&oi->area, &ospfh)) - return 1; + /* Check match the Area ID of the receiving interface. */ + if (OSPF_AREA_SAME(&oi->area, &ospfh)) + return 1; - return 0; + return 0; } /* Unbound socket will accept any Raw IP packets if proto is matched. To prevent it, compare src IP address and i/f address with masking i/f network mask. */ -static int -ospf_check_network_mask (struct ospf_interface *oi, struct in_addr ip_src) +static int ospf_check_network_mask(struct ospf_interface *oi, + struct in_addr ip_src) { - struct in_addr mask, me, him; + struct in_addr mask, me, him; - if (oi->type == OSPF_IFTYPE_POINTOPOINT || - oi->type == OSPF_IFTYPE_VIRTUALLINK) - return 1; + if (oi->type == OSPF_IFTYPE_POINTOPOINT + || oi->type == OSPF_IFTYPE_VIRTUALLINK) + return 1; - masklen2ip (oi->address->prefixlen, &mask); + masklen2ip(oi->address->prefixlen, &mask); - me.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr; - him.s_addr = ip_src.s_addr & mask.s_addr; + me.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr; + him.s_addr = ip_src.s_addr & mask.s_addr; - if (IPV4_ADDR_SAME (&me, &him)) - return 1; + if (IPV4_ADDR_SAME(&me, &him)) + return 1; - return 0; + return 0; } /* Return 1, if the packet is properly authenticated and checksummed, 0 otherwise. In particular, check that AuType header field is valid and matches the locally configured AuType, and that D.5 requirements are met. */ -static int -ospf_check_auth (struct ospf_interface *oi, struct ospf_header *ospfh) -{ - struct crypt_key *ck; - u_int16_t iface_auth_type; - u_int16_t pkt_auth_type = ntohs (ospfh->auth_type); - - switch (pkt_auth_type) - { - case OSPF_AUTH_NULL: /* RFC2328 D.5.1 */ - if (OSPF_AUTH_NULL != (iface_auth_type = ospf_auth_type (oi))) - { - if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) - zlog_warn ("interface %s: auth-type mismatch, local %s, rcvd Null", - IF_NAME (oi), lookup_msg(ospf_auth_type_str, iface_auth_type, NULL)); - return 0; - } - if (! ospf_check_sum (ospfh)) - { - if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) - zlog_warn ("interface %s: Null auth OK, but checksum error, Router-ID %s", - IF_NAME (oi), inet_ntoa (ospfh->router_id)); - return 0; - } - return 1; - case OSPF_AUTH_SIMPLE: /* RFC2328 D.5.2 */ - if (OSPF_AUTH_SIMPLE != (iface_auth_type = ospf_auth_type (oi))) - { - if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) - zlog_warn ("interface %s: auth-type mismatch, local %s, rcvd Simple", - IF_NAME (oi), lookup_msg(ospf_auth_type_str, iface_auth_type, NULL)); - return 0; - } - if (memcmp (OSPF_IF_PARAM (oi, auth_simple), ospfh->u.auth_data, OSPF_AUTH_SIMPLE_SIZE)) - { - if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) - zlog_warn ("interface %s: Simple auth failed", IF_NAME (oi)); - return 0; - } - if (! ospf_check_sum (ospfh)) - { - if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) - zlog_warn ("interface %s: Simple auth OK, checksum error, Router-ID %s", - IF_NAME (oi), inet_ntoa (ospfh->router_id)); - return 0; - } - return 1; - case OSPF_AUTH_CRYPTOGRAPHIC: /* RFC2328 D.5.3 */ - if (OSPF_AUTH_CRYPTOGRAPHIC != (iface_auth_type = ospf_auth_type (oi))) - { - if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) - zlog_warn ("interface %s: auth-type mismatch, local %s, rcvd Cryptographic", - IF_NAME (oi), lookup_msg(ospf_auth_type_str, iface_auth_type, NULL)); - return 0; - } - if (ospfh->checksum) - { - if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) - zlog_warn ("interface %s: OSPF header checksum is not 0", IF_NAME (oi)); - return 0; - } - /* only MD5 crypto method can pass ospf_packet_examin() */ - if - ( - NULL == (ck = listgetdata (listtail(OSPF_IF_PARAM (oi,auth_crypt)))) || - ospfh->u.crypt.key_id != ck->key_id || - /* Condition above uses the last key ID on the list, which is - different from what ospf_crypt_key_lookup() does. A bug? */ - ! ospf_check_md5_digest (oi, ospfh) - ) - { - if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) - zlog_warn ("interface %s: MD5 auth failed", IF_NAME (oi)); - return 0; - } - return 1; - default: - if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) - zlog_warn ("interface %s: invalid packet auth-type (%02x)", - IF_NAME (oi), pkt_auth_type); - return 0; - } -} - -static int -ospf_check_sum (struct ospf_header *ospfh) -{ - u_int32_t ret; - u_int16_t sum; - - /* clear auth_data for checksum. */ - memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE); - - /* keep checksum and clear. */ - sum = ospfh->checksum; - memset (&ospfh->checksum, 0, sizeof (u_int16_t)); - - /* calculate checksum. */ - ret = in_cksum (ospfh, ntohs (ospfh->length)); - - if (ret != sum) - { - zlog_info ("ospf_check_sum(): checksum mismatch, my %X, his %X", - ret, sum); - return 0; - } - - return 1; +static int ospf_check_auth(struct ospf_interface *oi, struct ospf_header *ospfh) +{ + struct crypt_key *ck; + u_int16_t iface_auth_type; + u_int16_t pkt_auth_type = ntohs(ospfh->auth_type); + + switch (pkt_auth_type) { + case OSPF_AUTH_NULL: /* RFC2328 D.5.1 */ + if (OSPF_AUTH_NULL != (iface_auth_type = ospf_auth_type(oi))) { + if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) + zlog_warn( + "interface %s: auth-type mismatch, local %s, rcvd Null", + IF_NAME(oi), + lookup_msg(ospf_auth_type_str, + iface_auth_type, NULL)); + return 0; + } + if (!ospf_check_sum(ospfh)) { + if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) + zlog_warn( + "interface %s: Null auth OK, but checksum error, Router-ID %s", + IF_NAME(oi), + inet_ntoa(ospfh->router_id)); + return 0; + } + return 1; + case OSPF_AUTH_SIMPLE: /* RFC2328 D.5.2 */ + if (OSPF_AUTH_SIMPLE + != (iface_auth_type = ospf_auth_type(oi))) { + if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) + zlog_warn( + "interface %s: auth-type mismatch, local %s, rcvd Simple", + IF_NAME(oi), + lookup_msg(ospf_auth_type_str, + iface_auth_type, NULL)); + return 0; + } + if (memcmp(OSPF_IF_PARAM(oi, auth_simple), ospfh->u.auth_data, + OSPF_AUTH_SIMPLE_SIZE)) { + if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) + zlog_warn("interface %s: Simple auth failed", + IF_NAME(oi)); + return 0; + } + if (!ospf_check_sum(ospfh)) { + if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) + zlog_warn( + "interface %s: Simple auth OK, checksum error, Router-ID %s", + IF_NAME(oi), + inet_ntoa(ospfh->router_id)); + return 0; + } + return 1; + case OSPF_AUTH_CRYPTOGRAPHIC: /* RFC2328 D.5.3 */ + if (OSPF_AUTH_CRYPTOGRAPHIC + != (iface_auth_type = ospf_auth_type(oi))) { + if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) + zlog_warn( + "interface %s: auth-type mismatch, local %s, rcvd Cryptographic", + IF_NAME(oi), + lookup_msg(ospf_auth_type_str, + iface_auth_type, NULL)); + return 0; + } + if (ospfh->checksum) { + if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) + zlog_warn( + "interface %s: OSPF header checksum is not 0", + IF_NAME(oi)); + return 0; + } + /* only MD5 crypto method can pass ospf_packet_examin() */ + if ( + NULL == (ck = listgetdata(listtail( + OSPF_IF_PARAM(oi, auth_crypt)))) + || ospfh->u.crypt.key_id != ck->key_id || + /* Condition above uses the last key ID on the list, + which is + different from what ospf_crypt_key_lookup() does. A + bug? */ + !ospf_check_md5_digest(oi, ospfh)) { + if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) + zlog_warn("interface %s: MD5 auth failed", + IF_NAME(oi)); + return 0; + } + return 1; + default: + if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) + zlog_warn( + "interface %s: invalid packet auth-type (%02x)", + IF_NAME(oi), pkt_auth_type); + return 0; + } +} + +static int ospf_check_sum(struct ospf_header *ospfh) +{ + u_int32_t ret; + u_int16_t sum; + + /* clear auth_data for checksum. */ + memset(ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE); + + /* keep checksum and clear. */ + sum = ospfh->checksum; + memset(&ospfh->checksum, 0, sizeof(u_int16_t)); + + /* calculate checksum. */ + ret = in_cksum(ospfh, ntohs(ospfh->length)); + + if (ret != sum) { + zlog_info("ospf_check_sum(): checksum mismatch, my %X, his %X", + ret, sum); + return 0; + } + + return 1; } /* Verify, that given link/TOS records are properly sized/aligned and match Router-LSA "# links" and "# TOS" fields as specified in RFC2328 A.4.2. */ -static unsigned -ospf_router_lsa_links_examin -( - struct router_lsa_link * link, - u_int16_t linkbytes, - const u_int16_t num_links -) -{ - unsigned counted_links = 0, thislinklen; - - while (linkbytes) - { - thislinklen = OSPF_ROUTER_LSA_LINK_SIZE + 4 * link->m[0].tos_count; - if (thislinklen > linkbytes) - { - if (IS_DEBUG_OSPF_PACKET (0, RECV)) - zlog_debug ("%s: length error in link block #%u", __func__, counted_links); - return MSG_NG; - } - link = (struct router_lsa_link *)((caddr_t) link + thislinklen); - linkbytes -= thislinklen; - counted_links++; - } - if (counted_links != num_links) - { - if (IS_DEBUG_OSPF_PACKET (0, RECV)) - zlog_debug ("%s: %u link blocks declared, %u present", - __func__, num_links, counted_links); - return MSG_NG; - } - return MSG_OK; +static unsigned ospf_router_lsa_links_examin(struct router_lsa_link *link, + u_int16_t linkbytes, + const u_int16_t num_links) +{ + unsigned counted_links = 0, thislinklen; + + while (linkbytes) { + thislinklen = + OSPF_ROUTER_LSA_LINK_SIZE + 4 * link->m[0].tos_count; + if (thislinklen > linkbytes) { + if (IS_DEBUG_OSPF_PACKET(0, RECV)) + zlog_debug("%s: length error in link block #%u", + __func__, counted_links); + return MSG_NG; + } + link = (struct router_lsa_link *)((caddr_t)link + thislinklen); + linkbytes -= thislinklen; + counted_links++; + } + if (counted_links != num_links) { + if (IS_DEBUG_OSPF_PACKET(0, RECV)) + zlog_debug("%s: %u link blocks declared, %u present", + __func__, num_links, counted_links); + return MSG_NG; + } + return MSG_OK; } /* Verify, that the given LSA is properly sized/aligned (including type-specific minimum length constraint). */ -static unsigned -ospf_lsa_examin (struct lsa_header * lsah, const u_int16_t lsalen, const u_char headeronly) -{ - unsigned ret; - struct router_lsa * rlsa; - if - ( - lsah->type < OSPF_MAX_LSA && - ospf_lsa_minlen[lsah->type] && - lsalen < OSPF_LSA_HEADER_SIZE + ospf_lsa_minlen[lsah->type] - ) - { - if (IS_DEBUG_OSPF_PACKET (0, RECV)) - zlog_debug ("%s: undersized (%u B) %s", - __func__, lsalen, lookup_msg(ospf_lsa_type_msg, lsah->type, NULL)); - return MSG_NG; - } - switch (lsah->type) - { - case OSPF_ROUTER_LSA: - /* RFC2328 A.4.2, LSA header + 4 bytes followed by N>=1 (12+)-byte link blocks */ - if (headeronly) - { - ret = (lsalen - OSPF_LSA_HEADER_SIZE - OSPF_ROUTER_LSA_MIN_SIZE) % 4 ? MSG_NG : MSG_OK; - break; - } - rlsa = (struct router_lsa *) lsah; - ret = ospf_router_lsa_links_examin - ( - (struct router_lsa_link *) rlsa->link, - lsalen - OSPF_LSA_HEADER_SIZE - 4, /* skip: basic header, "flags", 0, "# links" */ - ntohs (rlsa->links) /* 16 bits */ - ); - break; - case OSPF_AS_EXTERNAL_LSA: - /* RFC2328 A.4.5, LSA header + 4 bytes followed by N>=1 12-bytes long blocks */ - case OSPF_AS_NSSA_LSA: - /* RFC3101 C, idem */ - ret = (lsalen - OSPF_LSA_HEADER_SIZE - OSPF_AS_EXTERNAL_LSA_MIN_SIZE) % 12 ? MSG_NG : MSG_OK; - break; - /* Following LSA types are considered OK length-wise as soon as their minimum - * length constraint is met and length of the whole LSA is a multiple of 4 - * (basic LSA header size is already a multiple of 4). */ - case OSPF_NETWORK_LSA: - /* RFC2328 A.4.3, LSA header + 4 bytes followed by N>=1 router-IDs */ - case OSPF_SUMMARY_LSA: - case OSPF_ASBR_SUMMARY_LSA: - /* RFC2328 A.4.4, LSA header + 4 bytes followed by N>=1 4-bytes TOS blocks */ - case OSPF_OPAQUE_LINK_LSA: - case OSPF_OPAQUE_AREA_LSA: - case OSPF_OPAQUE_AS_LSA: - /* RFC5250 A.2, "some number of octets (of application-specific - * data) padded to 32-bit alignment." This is considered equivalent - * to 4-byte alignment of all other LSA types, see OSPF-ALIGNMENT.txt - * file for the detailed analysis of this passage. */ - ret = lsalen % 4 ? MSG_NG : MSG_OK; - break; - default: - if (IS_DEBUG_OSPF_PACKET (0, RECV)) - zlog_debug ("%s: unsupported LSA type 0x%02x", __func__, lsah->type); - return MSG_NG; - } - if (ret != MSG_OK && IS_DEBUG_OSPF_PACKET (0, RECV)) - zlog_debug ("%s: alignment error in %s", - __func__, lookup_msg(ospf_lsa_type_msg, lsah->type, NULL)); - return ret; +static unsigned ospf_lsa_examin(struct lsa_header *lsah, const u_int16_t lsalen, + const u_char headeronly) +{ + unsigned ret; + struct router_lsa *rlsa; + if (lsah->type < OSPF_MAX_LSA && ospf_lsa_minlen[lsah->type] + && lsalen < OSPF_LSA_HEADER_SIZE + ospf_lsa_minlen[lsah->type]) { + if (IS_DEBUG_OSPF_PACKET(0, RECV)) + zlog_debug("%s: undersized (%u B) %s", __func__, lsalen, + lookup_msg(ospf_lsa_type_msg, lsah->type, + NULL)); + return MSG_NG; + } + switch (lsah->type) { + case OSPF_ROUTER_LSA: + /* RFC2328 A.4.2, LSA header + 4 bytes followed by N>=1 + * (12+)-byte link blocks */ + if (headeronly) { + ret = (lsalen - OSPF_LSA_HEADER_SIZE + - OSPF_ROUTER_LSA_MIN_SIZE) + % 4 + ? MSG_NG + : MSG_OK; + break; + } + rlsa = (struct router_lsa *)lsah; + ret = ospf_router_lsa_links_examin( + (struct router_lsa_link *)rlsa->link, + lsalen - OSPF_LSA_HEADER_SIZE - 4, /* skip: basic + header, "flags", + 0, "# links" */ + ntohs(rlsa->links) /* 16 bits */ + ); + break; + case OSPF_AS_EXTERNAL_LSA: + /* RFC2328 A.4.5, LSA header + 4 bytes followed by N>=1 12-bytes long + * blocks */ + case OSPF_AS_NSSA_LSA: + /* RFC3101 C, idem */ + ret = (lsalen - OSPF_LSA_HEADER_SIZE + - OSPF_AS_EXTERNAL_LSA_MIN_SIZE) + % 12 + ? MSG_NG + : MSG_OK; + break; + /* Following LSA types are considered OK length-wise as soon as their + * minimum + * length constraint is met and length of the whole LSA is a multiple of + * 4 + * (basic LSA header size is already a multiple of 4). */ + case OSPF_NETWORK_LSA: + /* RFC2328 A.4.3, LSA header + 4 bytes followed by N>=1 router-IDs */ + case OSPF_SUMMARY_LSA: + case OSPF_ASBR_SUMMARY_LSA: + /* RFC2328 A.4.4, LSA header + 4 bytes followed by N>=1 4-bytes TOS + * blocks */ + case OSPF_OPAQUE_LINK_LSA: + case OSPF_OPAQUE_AREA_LSA: + case OSPF_OPAQUE_AS_LSA: + /* RFC5250 A.2, "some number of octets (of application-specific + * data) padded to 32-bit alignment." This is considered + * equivalent + * to 4-byte alignment of all other LSA types, see + * OSPF-ALIGNMENT.txt + * file for the detailed analysis of this passage. */ + ret = lsalen % 4 ? MSG_NG : MSG_OK; + break; + default: + if (IS_DEBUG_OSPF_PACKET(0, RECV)) + zlog_debug("%s: unsupported LSA type 0x%02x", __func__, + lsah->type); + return MSG_NG; + } + if (ret != MSG_OK && IS_DEBUG_OSPF_PACKET(0, RECV)) + zlog_debug("%s: alignment error in %s", __func__, + lookup_msg(ospf_lsa_type_msg, lsah->type, NULL)); + return ret; } /* Verify if the provided input buffer is a valid sequence of LSAs. This includes verification of LSA blocks length/alignment and dispatching of deeper-level checks. */ static unsigned -ospf_lsaseq_examin -( - struct lsa_header *lsah, /* start of buffered data */ - size_t length, - const u_char headeronly, - /* When declared_num_lsas is not 0, compare it to the real number of LSAs - and treat the difference as an error. */ - const u_int32_t declared_num_lsas -) -{ - u_int32_t counted_lsas = 0; - - while (length) - { - u_int16_t lsalen; - if (length < OSPF_LSA_HEADER_SIZE) - { - if (IS_DEBUG_OSPF_PACKET (0, RECV)) - zlog_debug ("%s: undersized (%zu B) trailing (#%u) LSA header", - __func__, length, counted_lsas); - return MSG_NG; - } - /* save on ntohs() calls here and in the LSA validator */ - lsalen = ntohs (lsah->length); - if (lsalen < OSPF_LSA_HEADER_SIZE) - { - if (IS_DEBUG_OSPF_PACKET (0, RECV)) - zlog_debug ("%s: malformed LSA header #%u, declared length is %u B", - __func__, counted_lsas, lsalen); - return MSG_NG; - } - if (headeronly) - { - /* less checks here and in ospf_lsa_examin() */ - if (MSG_OK != ospf_lsa_examin (lsah, lsalen, 1)) - { - if (IS_DEBUG_OSPF_PACKET (0, RECV)) - zlog_debug ("%s: malformed header-only LSA #%u", __func__, counted_lsas); - return MSG_NG; - } - lsah = (struct lsa_header *) ((caddr_t) lsah + OSPF_LSA_HEADER_SIZE); - length -= OSPF_LSA_HEADER_SIZE; - } - else - { - /* make sure the input buffer is deep enough before further checks */ - if (lsalen > length) - { - if (IS_DEBUG_OSPF_PACKET (0, RECV)) - zlog_debug ("%s: anomaly in LSA #%u: declared length is %u B, buffered length is %zu B", - __func__, counted_lsas, lsalen, length); - return MSG_NG; - } - if (MSG_OK != ospf_lsa_examin (lsah, lsalen, 0)) - { - if (IS_DEBUG_OSPF_PACKET (0, RECV)) - zlog_debug ("%s: malformed LSA #%u", __func__, counted_lsas); - return MSG_NG; - } - lsah = (struct lsa_header *) ((caddr_t) lsah + lsalen); - length -= lsalen; - } - counted_lsas++; - } - - if (declared_num_lsas && counted_lsas != declared_num_lsas) - { - if (IS_DEBUG_OSPF_PACKET (0, RECV)) - zlog_debug ("%s: #LSAs declared (%u) does not match actual (%u)", - __func__, declared_num_lsas, counted_lsas); - return MSG_NG; - } - return MSG_OK; +ospf_lsaseq_examin(struct lsa_header *lsah, /* start of buffered data */ + size_t length, const u_char headeronly, + /* When declared_num_lsas is not 0, compare it to the real + number of LSAs + and treat the difference as an error. */ + const u_int32_t declared_num_lsas) +{ + u_int32_t counted_lsas = 0; + + while (length) { + u_int16_t lsalen; + if (length < OSPF_LSA_HEADER_SIZE) { + if (IS_DEBUG_OSPF_PACKET(0, RECV)) + zlog_debug( + "%s: undersized (%zu B) trailing (#%u) LSA header", + __func__, length, counted_lsas); + return MSG_NG; + } + /* save on ntohs() calls here and in the LSA validator */ + lsalen = ntohs(lsah->length); + if (lsalen < OSPF_LSA_HEADER_SIZE) { + if (IS_DEBUG_OSPF_PACKET(0, RECV)) + zlog_debug( + "%s: malformed LSA header #%u, declared length is %u B", + __func__, counted_lsas, lsalen); + return MSG_NG; + } + if (headeronly) { + /* less checks here and in ospf_lsa_examin() */ + if (MSG_OK != ospf_lsa_examin(lsah, lsalen, 1)) { + if (IS_DEBUG_OSPF_PACKET(0, RECV)) + zlog_debug( + "%s: malformed header-only LSA #%u", + __func__, counted_lsas); + return MSG_NG; + } + lsah = (struct lsa_header *)((caddr_t)lsah + + OSPF_LSA_HEADER_SIZE); + length -= OSPF_LSA_HEADER_SIZE; + } else { + /* make sure the input buffer is deep enough before + * further checks */ + if (lsalen > length) { + if (IS_DEBUG_OSPF_PACKET(0, RECV)) + zlog_debug( + "%s: anomaly in LSA #%u: declared length is %u B, buffered length is %zu B", + __func__, counted_lsas, lsalen, + length); + return MSG_NG; + } + if (MSG_OK != ospf_lsa_examin(lsah, lsalen, 0)) { + if (IS_DEBUG_OSPF_PACKET(0, RECV)) + zlog_debug("%s: malformed LSA #%u", + __func__, counted_lsas); + return MSG_NG; + } + lsah = (struct lsa_header *)((caddr_t)lsah + lsalen); + length -= lsalen; + } + counted_lsas++; + } + + if (declared_num_lsas && counted_lsas != declared_num_lsas) { + if (IS_DEBUG_OSPF_PACKET(0, RECV)) + zlog_debug( + "%s: #LSAs declared (%u) does not match actual (%u)", + __func__, declared_num_lsas, counted_lsas); + return MSG_NG; + } + return MSG_OK; } /* Verify a complete OSPF packet for proper sizing/alignment. */ -static unsigned -ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire) -{ - u_int16_t bytesdeclared, bytesauth; - unsigned ret; - struct ospf_ls_update * lsupd; - - /* Length, 1st approximation. */ - if (bytesonwire < OSPF_HEADER_SIZE) - { - if (IS_DEBUG_OSPF_PACKET (0, RECV)) - zlog_debug ("%s: undersized (%u B) packet", __func__, bytesonwire); - return MSG_NG; - } - /* Now it is safe to access header fields. Performing length check, allow - * for possible extra bytes of crypto auth/padding, which are not counted - * in the OSPF header "length" field. */ - if (oh->version != OSPF_VERSION) - { - if (IS_DEBUG_OSPF_PACKET (0, RECV)) - zlog_debug ("%s: invalid (%u) protocol version", __func__, oh->version); - return MSG_NG; - } - bytesdeclared = ntohs (oh->length); - if (ntohs (oh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC) - bytesauth = 0; - else - { - if (oh->u.crypt.auth_data_len != OSPF_AUTH_MD5_SIZE) - { - if (IS_DEBUG_OSPF_PACKET (0, RECV)) - zlog_debug ("%s: unsupported crypto auth length (%u B)", - __func__, oh->u.crypt.auth_data_len); - return MSG_NG; - } - bytesauth = OSPF_AUTH_MD5_SIZE; - } - if (bytesdeclared + bytesauth > bytesonwire) - { - if (IS_DEBUG_OSPF_PACKET (0, RECV)) - zlog_debug ("%s: packet length error (%u real, %u+%u declared)", - __func__, bytesonwire, bytesdeclared, bytesauth); - return MSG_NG; - } - /* Length, 2nd approximation. The type-specific constraint is checked - against declared length, not amount of bytes on wire. */ - if - ( - oh->type >= OSPF_MSG_HELLO && - oh->type <= OSPF_MSG_LS_ACK && - bytesdeclared < OSPF_HEADER_SIZE + ospf_packet_minlen[oh->type] - ) - { - if (IS_DEBUG_OSPF_PACKET (0, RECV)) - zlog_debug ("%s: undersized (%u B) %s packet", __func__, - bytesdeclared, lookup_msg(ospf_packet_type_str, oh->type, NULL)); - return MSG_NG; - } - switch (oh->type) - { - case OSPF_MSG_HELLO: - /* RFC2328 A.3.2, packet header + OSPF_HELLO_MIN_SIZE bytes followed - by N>=0 router-IDs. */ - ret = (bytesdeclared - OSPF_HEADER_SIZE - OSPF_HELLO_MIN_SIZE) % 4 ? MSG_NG : MSG_OK; - break; - case OSPF_MSG_DB_DESC: - /* RFC2328 A.3.3, packet header + OSPF_DB_DESC_MIN_SIZE bytes followed - by N>=0 header-only LSAs. */ - ret = ospf_lsaseq_examin - ( - (struct lsa_header *) ((caddr_t) oh + OSPF_HEADER_SIZE + OSPF_DB_DESC_MIN_SIZE), - bytesdeclared - OSPF_HEADER_SIZE - OSPF_DB_DESC_MIN_SIZE, - 1, /* header-only LSAs */ - 0 - ); - break; - case OSPF_MSG_LS_REQ: - /* RFC2328 A.3.4, packet header followed by N>=0 12-bytes request blocks. */ - ret = (bytesdeclared - OSPF_HEADER_SIZE - OSPF_LS_REQ_MIN_SIZE) % - OSPF_LSA_KEY_SIZE ? MSG_NG : MSG_OK; - break; - case OSPF_MSG_LS_UPD: - /* RFC2328 A.3.5, packet header + OSPF_LS_UPD_MIN_SIZE bytes followed - by N>=0 full LSAs (with N declared beforehand). */ - lsupd = (struct ospf_ls_update *) ((caddr_t) oh + OSPF_HEADER_SIZE); - ret = ospf_lsaseq_examin - ( - (struct lsa_header *) ((caddr_t) lsupd + OSPF_LS_UPD_MIN_SIZE), - bytesdeclared - OSPF_HEADER_SIZE - OSPF_LS_UPD_MIN_SIZE, - 0, /* full LSAs */ - ntohl (lsupd->num_lsas) /* 32 bits */ - ); - break; - case OSPF_MSG_LS_ACK: - /* RFC2328 A.3.6, packet header followed by N>=0 header-only LSAs. */ - ret = ospf_lsaseq_examin - ( - (struct lsa_header *) ((caddr_t) oh + OSPF_HEADER_SIZE + OSPF_LS_ACK_MIN_SIZE), - bytesdeclared - OSPF_HEADER_SIZE - OSPF_LS_ACK_MIN_SIZE, - 1, /* header-only LSAs */ - 0 - ); - break; - default: - if (IS_DEBUG_OSPF_PACKET (0, RECV)) - zlog_debug ("%s: invalid packet type 0x%02x", __func__, oh->type); - return MSG_NG; - } - if (ret != MSG_OK && IS_DEBUG_OSPF_PACKET (0, RECV)) - zlog_debug ("%s: malformed %s packet", __func__, lookup_msg(ospf_packet_type_str, oh->type, NULL)); - return ret; +static unsigned ospf_packet_examin(struct ospf_header *oh, + const unsigned bytesonwire) +{ + u_int16_t bytesdeclared, bytesauth; + unsigned ret; + struct ospf_ls_update *lsupd; + + /* Length, 1st approximation. */ + if (bytesonwire < OSPF_HEADER_SIZE) { + if (IS_DEBUG_OSPF_PACKET(0, RECV)) + zlog_debug("%s: undersized (%u B) packet", __func__, + bytesonwire); + return MSG_NG; + } + /* Now it is safe to access header fields. Performing length check, + * allow + * for possible extra bytes of crypto auth/padding, which are not + * counted + * in the OSPF header "length" field. */ + if (oh->version != OSPF_VERSION) { + if (IS_DEBUG_OSPF_PACKET(0, RECV)) + zlog_debug("%s: invalid (%u) protocol version", + __func__, oh->version); + return MSG_NG; + } + bytesdeclared = ntohs(oh->length); + if (ntohs(oh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC) + bytesauth = 0; + else { + if (oh->u.crypt.auth_data_len != OSPF_AUTH_MD5_SIZE) { + if (IS_DEBUG_OSPF_PACKET(0, RECV)) + zlog_debug( + "%s: unsupported crypto auth length (%u B)", + __func__, oh->u.crypt.auth_data_len); + return MSG_NG; + } + bytesauth = OSPF_AUTH_MD5_SIZE; + } + if (bytesdeclared + bytesauth > bytesonwire) { + if (IS_DEBUG_OSPF_PACKET(0, RECV)) + zlog_debug( + "%s: packet length error (%u real, %u+%u declared)", + __func__, bytesonwire, bytesdeclared, + bytesauth); + return MSG_NG; + } + /* Length, 2nd approximation. The type-specific constraint is checked + against declared length, not amount of bytes on wire. */ + if (oh->type >= OSPF_MSG_HELLO && oh->type <= OSPF_MSG_LS_ACK + && bytesdeclared + < OSPF_HEADER_SIZE + ospf_packet_minlen[oh->type]) { + if (IS_DEBUG_OSPF_PACKET(0, RECV)) + zlog_debug("%s: undersized (%u B) %s packet", __func__, + bytesdeclared, + lookup_msg(ospf_packet_type_str, oh->type, + NULL)); + return MSG_NG; + } + switch (oh->type) { + case OSPF_MSG_HELLO: + /* RFC2328 A.3.2, packet header + OSPF_HELLO_MIN_SIZE bytes + followed + by N>=0 router-IDs. */ + ret = (bytesdeclared - OSPF_HEADER_SIZE - OSPF_HELLO_MIN_SIZE) + % 4 + ? MSG_NG + : MSG_OK; + break; + case OSPF_MSG_DB_DESC: + /* RFC2328 A.3.3, packet header + OSPF_DB_DESC_MIN_SIZE bytes + followed + by N>=0 header-only LSAs. */ + ret = ospf_lsaseq_examin( + (struct lsa_header *)((caddr_t)oh + OSPF_HEADER_SIZE + + OSPF_DB_DESC_MIN_SIZE), + bytesdeclared - OSPF_HEADER_SIZE + - OSPF_DB_DESC_MIN_SIZE, + 1, /* header-only LSAs */ + 0); + break; + case OSPF_MSG_LS_REQ: + /* RFC2328 A.3.4, packet header followed by N>=0 12-bytes + * request blocks. */ + ret = (bytesdeclared - OSPF_HEADER_SIZE - OSPF_LS_REQ_MIN_SIZE) + % OSPF_LSA_KEY_SIZE + ? MSG_NG + : MSG_OK; + break; + case OSPF_MSG_LS_UPD: + /* RFC2328 A.3.5, packet header + OSPF_LS_UPD_MIN_SIZE bytes + followed + by N>=0 full LSAs (with N declared beforehand). */ + lsupd = (struct ospf_ls_update *)((caddr_t)oh + + OSPF_HEADER_SIZE); + ret = ospf_lsaseq_examin( + (struct lsa_header *)((caddr_t)lsupd + + OSPF_LS_UPD_MIN_SIZE), + bytesdeclared - OSPF_HEADER_SIZE - OSPF_LS_UPD_MIN_SIZE, + 0, /* full LSAs */ + ntohl(lsupd->num_lsas) /* 32 bits */ + ); + break; + case OSPF_MSG_LS_ACK: + /* RFC2328 A.3.6, packet header followed by N>=0 header-only + * LSAs. */ + ret = ospf_lsaseq_examin( + (struct lsa_header *)((caddr_t)oh + OSPF_HEADER_SIZE + + OSPF_LS_ACK_MIN_SIZE), + bytesdeclared - OSPF_HEADER_SIZE - OSPF_LS_ACK_MIN_SIZE, + 1, /* header-only LSAs */ + 0); + break; + default: + if (IS_DEBUG_OSPF_PACKET(0, RECV)) + zlog_debug("%s: invalid packet type 0x%02x", __func__, + oh->type); + return MSG_NG; + } + if (ret != MSG_OK && IS_DEBUG_OSPF_PACKET(0, RECV)) + zlog_debug("%s: malformed %s packet", __func__, + lookup_msg(ospf_packet_type_str, oh->type, NULL)); + return ret; } /* OSPF Header verification. */ -static int -ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi, - struct ip *iph, struct ospf_header *ospfh) -{ - /* Check Area ID. */ - if (!ospf_check_area_id (oi, ospfh)) - { - zlog_warn ("interface %s: ospf_read invalid Area ID %s.", - IF_NAME (oi), inet_ntoa (ospfh->area_id)); - return -1; - } +static int ospf_verify_header(struct stream *ibuf, struct ospf_interface *oi, + struct ip *iph, struct ospf_header *ospfh) +{ + /* Check Area ID. */ + if (!ospf_check_area_id(oi, ospfh)) { + zlog_warn("interface %s: ospf_read invalid Area ID %s.", + IF_NAME(oi), inet_ntoa(ospfh->area_id)); + return -1; + } - /* Check network mask, Silently discarded. */ - if (! ospf_check_network_mask (oi, iph->ip_src)) - { - zlog_warn ("interface %s: ospf_read network address is not same [%s]", - IF_NAME (oi), inet_ntoa (iph->ip_src)); - return -1; - } + /* Check network mask, Silently discarded. */ + if (!ospf_check_network_mask(oi, iph->ip_src)) { + zlog_warn( + "interface %s: ospf_read network address is not same [%s]", + IF_NAME(oi), inet_ntoa(iph->ip_src)); + return -1; + } - /* Check authentication. The function handles logging actions, where required. */ - if (! ospf_check_auth (oi, ospfh)) - return -1; + /* Check authentication. The function handles logging actions, where + * required. */ + if (!ospf_check_auth(oi, ospfh)) + return -1; - return 0; + return 0; } /* Starting point of packet process function. */ -int -ospf_read (struct thread *thread) -{ - int ret; - struct stream *ibuf; - struct ospf *ospf; - struct ospf_interface *oi; - struct ip *iph; - struct ospf_header *ospfh; - u_int16_t length; - struct interface *ifp; - struct connected *c; - - /* first of all get interface pointer. */ - ospf = THREAD_ARG (thread); - - /* prepare for next packet. */ - ospf->t_read = NULL; - thread_add_read(master, ospf_read, ospf, ospf->fd, &ospf->t_read); - - stream_reset(ospf->ibuf); - if (!(ibuf = ospf_recv_packet (ospf->fd, &ifp, ospf->ibuf))) - return -1; - /* This raw packet is known to be at least as big as its IP header. */ - - /* Note that there should not be alignment problems with this assignment - because this is at the beginning of the stream data buffer. */ - iph = (struct ip *) STREAM_DATA (ibuf); - /* Note that sockopt_iphdrincl_swab_systoh was called in ospf_recv_packet. */ - - if (ifp == NULL) - { - /* Handle cases where the platform does not support retrieving the ifindex, - and also platforms (such as Solaris 8) that claim to support ifindex - retrieval but do not. */ - c = if_lookup_address ((void *)&iph->ip_src, AF_INET, VRF_DEFAULT); - if (c) - ifp = c->ifp; - if (ifp == NULL) +int ospf_read(struct thread *thread) +{ + int ret; + struct stream *ibuf; + struct ospf *ospf; + struct ospf_interface *oi; + struct ip *iph; + struct ospf_header *ospfh; + u_int16_t length; + struct interface *ifp; + struct connected *c; + + /* first of all get interface pointer. */ + ospf = THREAD_ARG(thread); + + /* prepare for next packet. */ + ospf->t_read = NULL; + thread_add_read(master, ospf_read, ospf, ospf->fd, &ospf->t_read); + + stream_reset(ospf->ibuf); + if (!(ibuf = ospf_recv_packet(ospf->fd, &ifp, ospf->ibuf))) + return -1; + /* This raw packet is known to be at least as big as its IP header. */ + + /* Note that there should not be alignment problems with this assignment + because this is at the beginning of the stream data buffer. */ + iph = (struct ip *)STREAM_DATA(ibuf); + /* Note that sockopt_iphdrincl_swab_systoh was called in + * ospf_recv_packet. */ + + if (ifp == NULL) { + /* Handle cases where the platform does not support retrieving + the ifindex, + and also platforms (such as Solaris 8) that claim to support + ifindex + retrieval but do not. */ + c = if_lookup_address((void *)&iph->ip_src, AF_INET, + VRF_DEFAULT); + if (c) + ifp = c->ifp; + if (ifp == NULL) + return 0; + } + + /* IP Header dump. */ + if (IS_DEBUG_OSPF_PACKET(0, RECV)) + ospf_ip_header_dump(iph); + + /* Self-originated packet should be discarded silently. */ + if (ospf_if_lookup_by_local_addr(ospf, NULL, iph->ip_src)) { + if (IS_DEBUG_OSPF_PACKET(0, RECV)) { + zlog_debug( + "ospf_read[%s]: Dropping self-originated packet", + inet_ntoa(iph->ip_src)); + } + return 0; + } + + /* Advance from IP header to OSPF header (iph->ip_hl has been verified + by ospf_recv_packet() to be correct). */ + stream_forward_getp(ibuf, iph->ip_hl * 4); + + ospfh = (struct ospf_header *)STREAM_PNT(ibuf); + if (MSG_OK + != ospf_packet_examin( + ospfh, stream_get_endp(ibuf) - stream_get_getp(ibuf))) + return -1; + /* Now it is safe to access all fields of OSPF packet header. */ + + /* associate packet with ospf interface */ + oi = ospf_if_lookup_recv_if(ospf, iph->ip_src, ifp); + + /* ospf_verify_header() relies on a valid "oi" and thus can be called + only + after the passive/backbone/other checks below are passed. These + checks + in turn access the fields of unverified "ospfh" structure for their + own + purposes and must remain very accurate in doing this. */ + + /* If incoming interface is passive one, ignore it. */ + if (oi && OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_PASSIVE) { + char buf[3][INET_ADDRSTRLEN]; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ignoring packet from router %s sent to %s, " + "received on a passive interface, %s", + inet_ntop(AF_INET, &ospfh->router_id, buf[0], + sizeof(buf[0])), + inet_ntop(AF_INET, &iph->ip_dst, buf[1], + sizeof(buf[1])), + inet_ntop(AF_INET, &oi->address->u.prefix4, + buf[2], sizeof(buf[2]))); + + if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS)) { + /* Try to fix multicast membership. + * Some OS:es may have problems in this area, + * make sure it is removed. + */ + OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS); + ospf_if_set_multicast(oi); + } + return 0; + } + + + /* if no local ospf_interface, + * or header area is backbone but ospf_interface is not + * check for VLINK interface + */ + if ((oi == NULL) || (OSPF_IS_AREA_ID_BACKBONE(ospfh->area_id) + && !OSPF_IS_AREA_ID_BACKBONE(oi->area->area_id))) { + if ((oi = ospf_associate_packet_vl(ospf, ifp, iph, ospfh)) + == NULL) { + if (!ospf->instance && IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Packet from [%s] received on link %s" + " but no ospf_interface", + inet_ntoa(iph->ip_src), ifp->name); + return 0; + } + } + + /* else it must be a local ospf interface, check it was received on + * correct link + */ + else if (oi->ifp != ifp) { + if (IS_DEBUG_OSPF_EVENT) + zlog_warn("Packet from [%s] received on wrong link %s", + inet_ntoa(iph->ip_src), ifp->name); + return 0; + } else if (oi->state == ISM_Down) { + char buf[2][INET_ADDRSTRLEN]; + zlog_warn( + "Ignoring packet from %s to %s received on interface that is " + "down [%s]; interface flags are %s", + inet_ntop(AF_INET, &iph->ip_src, buf[0], + sizeof(buf[0])), + inet_ntop(AF_INET, &iph->ip_dst, buf[1], + sizeof(buf[1])), + ifp->name, if_flag_dump(ifp->flags)); + /* Fix multicast memberships? */ + if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS)) + OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS); + else if (iph->ip_dst.s_addr == htonl(OSPF_ALLDROUTERS)) + OI_MEMBER_JOINED(oi, MEMBER_DROUTERS); + if (oi->multicast_memberships) + ospf_if_set_multicast(oi); + return 0; + } + + /* + * If the received packet is destined for AllDRouters, the packet + * should be accepted only if the received ospf interface state is + * either DR or Backup -- endo. + */ + if (iph->ip_dst.s_addr == htonl(OSPF_ALLDROUTERS) + && (oi->state != ISM_DR && oi->state != ISM_Backup)) { + zlog_warn( + "Dropping packet for AllDRouters from [%s] via [%s] (ISM: %s)", + inet_ntoa(iph->ip_src), IF_NAME(oi), + lookup_msg(ospf_ism_state_msg, oi->state, NULL)); + /* Try to fix multicast membership. */ + SET_FLAG(oi->multicast_memberships, MEMBER_DROUTERS); + ospf_if_set_multicast(oi); + return 0; + } + + /* Verify more OSPF header fields. */ + ret = ospf_verify_header(ibuf, oi, iph, ospfh); + if (ret < 0) { + if (IS_DEBUG_OSPF_PACKET(0, RECV)) + zlog_debug( + "ospf_read[%s]: Header check failed, " + "dropping.", + inet_ntoa(iph->ip_src)); + return ret; + } + + /* Show debug receiving packet. */ + if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, RECV)) { + if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, DETAIL)) { + zlog_debug( + "-----------------------------------------------------"); + ospf_packet_dump(ibuf); + } + + zlog_debug("%s received from [%s] via [%s]", + lookup_msg(ospf_packet_type_str, ospfh->type, NULL), + inet_ntoa(ospfh->router_id), IF_NAME(oi)); + zlog_debug(" src [%s],", inet_ntoa(iph->ip_src)); + zlog_debug(" dst [%s]", inet_ntoa(iph->ip_dst)); + + if (IS_DEBUG_OSPF_PACKET(ospfh->type - 1, DETAIL)) + zlog_debug( + "-----------------------------------------------------"); + } + + stream_forward_getp(ibuf, OSPF_HEADER_SIZE); + + /* Adjust size to message length. */ + length = ntohs(ospfh->length) - OSPF_HEADER_SIZE; + + /* Read rest of the packet and call each sort of packet routine. */ + switch (ospfh->type) { + case OSPF_MSG_HELLO: + ospf_hello(iph, ospfh, ibuf, oi, length); + break; + case OSPF_MSG_DB_DESC: + ospf_db_desc(iph, ospfh, ibuf, oi, length); + break; + case OSPF_MSG_LS_REQ: + ospf_ls_req(iph, ospfh, ibuf, oi, length); + break; + case OSPF_MSG_LS_UPD: + ospf_ls_upd(ospf, iph, ospfh, ibuf, oi, length); + break; + case OSPF_MSG_LS_ACK: + ospf_ls_ack(iph, ospfh, ibuf, oi, length); + break; + default: + zlog_warn("interface %s: OSPF packet header type %d is illegal", + IF_NAME(oi), ospfh->type); + break; + } + return 0; - } - - /* IP Header dump. */ - if (IS_DEBUG_OSPF_PACKET(0, RECV)) - ospf_ip_header_dump (iph); - - /* Self-originated packet should be discarded silently. */ - if (ospf_if_lookup_by_local_addr (ospf, NULL, iph->ip_src)) - { - if (IS_DEBUG_OSPF_PACKET (0, RECV)) - { - zlog_debug ("ospf_read[%s]: Dropping self-originated packet", - inet_ntoa (iph->ip_src)); - } - return 0; - } - - /* Advance from IP header to OSPF header (iph->ip_hl has been verified - by ospf_recv_packet() to be correct). */ - stream_forward_getp (ibuf, iph->ip_hl * 4); - - ospfh = (struct ospf_header *) STREAM_PNT (ibuf); - if (MSG_OK != ospf_packet_examin (ospfh, stream_get_endp (ibuf) - stream_get_getp (ibuf))) - return -1; - /* Now it is safe to access all fields of OSPF packet header. */ - - /* associate packet with ospf interface */ - oi = ospf_if_lookup_recv_if (ospf, iph->ip_src, ifp); - - /* ospf_verify_header() relies on a valid "oi" and thus can be called only - after the passive/backbone/other checks below are passed. These checks - in turn access the fields of unverified "ospfh" structure for their own - purposes and must remain very accurate in doing this. */ - - /* If incoming interface is passive one, ignore it. */ - if (oi && OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE) - { - char buf[3][INET_ADDRSTRLEN]; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ignoring packet from router %s sent to %s, " - "received on a passive interface, %s", - inet_ntop(AF_INET, &ospfh->router_id, buf[0], sizeof(buf[0])), - inet_ntop(AF_INET, &iph->ip_dst, buf[1], sizeof(buf[1])), - inet_ntop(AF_INET, &oi->address->u.prefix4, - buf[2], sizeof(buf[2]))); - - if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS)) - { - /* Try to fix multicast membership. - * Some OS:es may have problems in this area, - * make sure it is removed. - */ - OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS); - ospf_if_set_multicast(oi); - } - return 0; - } - - - /* if no local ospf_interface, - * or header area is backbone but ospf_interface is not - * check for VLINK interface - */ - if ( (oi == NULL) || - (OSPF_IS_AREA_ID_BACKBONE(ospfh->area_id) - && !OSPF_IS_AREA_ID_BACKBONE(oi->area->area_id)) - ) - { - if ((oi = ospf_associate_packet_vl (ospf, ifp, iph, ospfh)) == NULL) - { - if (!ospf->instance && IS_DEBUG_OSPF_EVENT) - zlog_debug ("Packet from [%s] received on link %s" - " but no ospf_interface", - inet_ntoa (iph->ip_src), ifp->name); - return 0; - } - } - - /* else it must be a local ospf interface, check it was received on - * correct link - */ - else if (oi->ifp != ifp) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_warn ("Packet from [%s] received on wrong link %s", - inet_ntoa (iph->ip_src), ifp->name); - return 0; - } - else if (oi->state == ISM_Down) - { - char buf[2][INET_ADDRSTRLEN]; - zlog_warn ("Ignoring packet from %s to %s received on interface that is " - "down [%s]; interface flags are %s", - inet_ntop(AF_INET, &iph->ip_src, buf[0], sizeof(buf[0])), - inet_ntop(AF_INET, &iph->ip_dst, buf[1], sizeof(buf[1])), - ifp->name, if_flag_dump(ifp->flags)); - /* Fix multicast memberships? */ - if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS)) - OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS); - else if (iph->ip_dst.s_addr == htonl(OSPF_ALLDROUTERS)) - OI_MEMBER_JOINED(oi, MEMBER_DROUTERS); - if (oi->multicast_memberships) - ospf_if_set_multicast(oi); - return 0; - } - - /* - * If the received packet is destined for AllDRouters, the packet - * should be accepted only if the received ospf interface state is - * either DR or Backup -- endo. - */ - if (iph->ip_dst.s_addr == htonl (OSPF_ALLDROUTERS) - && (oi->state != ISM_DR && oi->state != ISM_Backup)) - { - zlog_warn ("Dropping packet for AllDRouters from [%s] via [%s] (ISM: %s)", - inet_ntoa (iph->ip_src), IF_NAME (oi), - lookup_msg(ospf_ism_state_msg, oi->state, NULL)); - /* Try to fix multicast membership. */ - SET_FLAG(oi->multicast_memberships, MEMBER_DROUTERS); - ospf_if_set_multicast(oi); - return 0; - } - - /* Verify more OSPF header fields. */ - ret = ospf_verify_header (ibuf, oi, iph, ospfh); - if (ret < 0) - { - if (IS_DEBUG_OSPF_PACKET (0, RECV)) - zlog_debug ("ospf_read[%s]: Header check failed, " - "dropping.", - inet_ntoa (iph->ip_src)); - return ret; - } - - /* Show debug receiving packet. */ - if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) - { - if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL)) - { - zlog_debug ("-----------------------------------------------------"); - ospf_packet_dump (ibuf); - } - - zlog_debug ("%s received from [%s] via [%s]", - lookup_msg(ospf_packet_type_str, ospfh->type, NULL), - inet_ntoa (ospfh->router_id), IF_NAME (oi)); - zlog_debug (" src [%s],", inet_ntoa (iph->ip_src)); - zlog_debug (" dst [%s]", inet_ntoa (iph->ip_dst)); - - if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL)) - zlog_debug ("-----------------------------------------------------"); - } - - stream_forward_getp (ibuf, OSPF_HEADER_SIZE); - - /* Adjust size to message length. */ - length = ntohs (ospfh->length) - OSPF_HEADER_SIZE; - - /* Read rest of the packet and call each sort of packet routine. */ - switch (ospfh->type) - { - case OSPF_MSG_HELLO: - ospf_hello (iph, ospfh, ibuf, oi, length); - break; - case OSPF_MSG_DB_DESC: - ospf_db_desc (iph, ospfh, ibuf, oi, length); - break; - case OSPF_MSG_LS_REQ: - ospf_ls_req (iph, ospfh, ibuf, oi, length); - break; - case OSPF_MSG_LS_UPD: - ospf_ls_upd (ospf, iph, ospfh, ibuf, oi, length); - break; - case OSPF_MSG_LS_ACK: - ospf_ls_ack (iph, ospfh, ibuf, oi, length); - break; - default: - zlog_warn("interface %s: OSPF packet header type %d is illegal", - IF_NAME(oi), ospfh->type); - break; - } - - return 0; } /* Make OSPF header. */ -static void -ospf_make_header (int type, struct ospf_interface *oi, struct stream *s) +static void ospf_make_header(int type, struct ospf_interface *oi, + struct stream *s) { - struct ospf_header *ospfh; + struct ospf_header *ospfh; - ospfh = (struct ospf_header *) STREAM_DATA (s); + ospfh = (struct ospf_header *)STREAM_DATA(s); - ospfh->version = (u_char) OSPF_VERSION; - ospfh->type = (u_char) type; + ospfh->version = (u_char)OSPF_VERSION; + ospfh->type = (u_char)type; - ospfh->router_id = oi->ospf->router_id; + ospfh->router_id = oi->ospf->router_id; - ospfh->checksum = 0; - ospfh->area_id = oi->area->area_id; - ospfh->auth_type = htons (ospf_auth_type (oi)); + ospfh->checksum = 0; + ospfh->area_id = oi->area->area_id; + ospfh->auth_type = htons(ospf_auth_type(oi)); - memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE); + memset(ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE); - stream_forward_endp (s, OSPF_HEADER_SIZE); + stream_forward_endp(s, OSPF_HEADER_SIZE); } /* Make Authentication Data. */ -static int -ospf_make_auth (struct ospf_interface *oi, struct ospf_header *ospfh) -{ - struct crypt_key *ck; - - switch (ospf_auth_type (oi)) - { - case OSPF_AUTH_NULL: - /* memset (ospfh->u.auth_data, 0, sizeof (ospfh->u.auth_data)); */ - break; - case OSPF_AUTH_SIMPLE: - memcpy (ospfh->u.auth_data, OSPF_IF_PARAM (oi, auth_simple), - OSPF_AUTH_SIMPLE_SIZE); - break; - case OSPF_AUTH_CRYPTOGRAPHIC: - /* If key is not set, then set 0. */ - if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt))) - { - ospfh->u.crypt.zero = 0; - ospfh->u.crypt.key_id = 0; - ospfh->u.crypt.auth_data_len = OSPF_AUTH_MD5_SIZE; - } - else - { - ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt))); - ospfh->u.crypt.zero = 0; - ospfh->u.crypt.key_id = ck->key_id; - ospfh->u.crypt.auth_data_len = OSPF_AUTH_MD5_SIZE; +static int ospf_make_auth(struct ospf_interface *oi, struct ospf_header *ospfh) +{ + struct crypt_key *ck; + + switch (ospf_auth_type(oi)) { + case OSPF_AUTH_NULL: + /* memset (ospfh->u.auth_data, 0, sizeof (ospfh->u.auth_data)); + */ + break; + case OSPF_AUTH_SIMPLE: + memcpy(ospfh->u.auth_data, OSPF_IF_PARAM(oi, auth_simple), + OSPF_AUTH_SIMPLE_SIZE); + break; + case OSPF_AUTH_CRYPTOGRAPHIC: + /* If key is not set, then set 0. */ + if (list_isempty(OSPF_IF_PARAM(oi, auth_crypt))) { + ospfh->u.crypt.zero = 0; + ospfh->u.crypt.key_id = 0; + ospfh->u.crypt.auth_data_len = OSPF_AUTH_MD5_SIZE; + } else { + ck = listgetdata( + listtail(OSPF_IF_PARAM(oi, auth_crypt))); + ospfh->u.crypt.zero = 0; + ospfh->u.crypt.key_id = ck->key_id; + ospfh->u.crypt.auth_data_len = OSPF_AUTH_MD5_SIZE; + } + /* note: the seq is done in ospf_make_md5_digest() */ + break; + default: + /* memset (ospfh->u.auth_data, 0, sizeof (ospfh->u.auth_data)); + */ + break; } - /* note: the seq is done in ospf_make_md5_digest() */ - break; - default: - /* memset (ospfh->u.auth_data, 0, sizeof (ospfh->u.auth_data)); */ - break; - } - return 0; + return 0; } /* Fill rest of OSPF header. */ -static void -ospf_fill_header (struct ospf_interface *oi, - struct stream *s, u_int16_t length) -{ - struct ospf_header *ospfh; - - ospfh = (struct ospf_header *) STREAM_DATA (s); - - /* Fill length. */ - ospfh->length = htons (length); - - /* Calculate checksum. */ - if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC) - ospfh->checksum = in_cksum (ospfh, length); - else - ospfh->checksum = 0; - - /* Add Authentication Data. */ - ospf_make_auth (oi, ospfh); -} - -static int -ospf_make_hello (struct ospf_interface *oi, struct stream *s) -{ - struct ospf_neighbor *nbr; - struct route_node *rn; - u_int16_t length = OSPF_HELLO_MIN_SIZE; - struct in_addr mask; - unsigned long p; - int flag = 0; - - /* Set netmask of interface. */ - if (!(CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED) && - oi->type == OSPF_IFTYPE_POINTOPOINT) && - oi->type != OSPF_IFTYPE_VIRTUALLINK) - masklen2ip (oi->address->prefixlen, &mask); - else - memset ((char *) &mask, 0, sizeof (struct in_addr)); - stream_put_ipv4 (s, mask.s_addr); - - /* Set Hello Interval. */ - if (OSPF_IF_PARAM (oi, fast_hello) == 0) - stream_putw (s, OSPF_IF_PARAM (oi, v_hello)); - else - stream_putw (s, 0); /* hello-interval of 0 for fast-hellos */ - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("make_hello: options: %x, int: %s", - OPTIONS(oi), IF_NAME (oi)); - - /* Set Options. */ - stream_putc (s, OPTIONS (oi)); - - /* Set Router Priority. */ - stream_putc (s, PRIORITY (oi)); - - /* Set Router Dead Interval. */ - stream_putl (s, OSPF_IF_PARAM (oi, v_wait)); - - /* Set Designated Router. */ - stream_put_ipv4 (s, DR (oi).s_addr); - - p = stream_get_endp (s); - - /* Set Backup Designated Router. */ - stream_put_ipv4 (s, BDR (oi).s_addr); - - /* Add neighbor seen. */ - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - if (nbr->router_id.s_addr != 0) /* Ignore 0.0.0.0 node. */ - if (nbr->state != NSM_Attempt) /* Ignore Down neighbor. */ - if (nbr->state != NSM_Down) /* This is myself for DR election. */ - if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) - { - /* Check neighbor is sane? */ - if (nbr->d_router.s_addr != 0 - && IPV4_ADDR_SAME (&nbr->d_router, &oi->address->u.prefix4) - && IPV4_ADDR_SAME (&nbr->bd_router, &oi->address->u.prefix4)) - flag = 1; - - stream_put_ipv4 (s, nbr->router_id.s_addr); - length += 4; - } - - /* Let neighbor generate BackupSeen. */ - if (flag == 1) - stream_putl_at (s, p, 0); /* ipv4 address, normally */ - - return length; -} - -static int -ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr, - struct stream *s) -{ - struct ospf_lsa *lsa; - u_int16_t length = OSPF_DB_DESC_MIN_SIZE; - u_char options; - unsigned long pp; - int i; - struct ospf_lsdb *lsdb; - - /* Set Interface MTU. */ - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - stream_putw (s, 0); - else - stream_putw (s, oi->ifp->mtu); - - /* Set Options. */ - options = OPTIONS (oi); - if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE)) - SET_FLAG (options, OSPF_OPTION_O); - stream_putc (s, options); - - /* DD flags */ - pp = stream_get_endp (s); - stream_putc (s, nbr->dd_flags); - - /* Set DD Sequence Number. */ - stream_putl (s, nbr->dd_seqnum); - - /* shortcut unneeded walk of (empty) summary LSDBs */ - if (ospf_db_summary_isempty (nbr)) - goto empty; - - /* Describe LSA Header from Database Summary List. */ - lsdb = &nbr->db_sum; - - for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) - { - struct route_table *table = lsdb->type[i].db; - struct route_node *rn; - - for (rn = route_top (table); rn; rn = route_next (rn)) - if ((lsa = rn->info) != NULL) - { - if (IS_OPAQUE_LSA (lsa->data->type) - && (! CHECK_FLAG (options, OSPF_OPTION_O))) - { - /* Suppress advertising opaque-informations. */ - /* Remove LSA from DB summary list. */ - ospf_lsdb_delete (lsdb, lsa); - continue; - } - - if (!CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD)) - { - struct lsa_header *lsah; - u_int16_t ls_age; - - /* DD packet overflows interface MTU. */ - if (length + OSPF_LSA_HEADER_SIZE > ospf_packet_max (oi)) - break; - - /* Keep pointer to LS age. */ - lsah = (struct lsa_header *) (STREAM_DATA (s) + - stream_get_endp (s)); - - /* Proceed stream pointer. */ - stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE); - length += OSPF_LSA_HEADER_SIZE; - - /* Set LS age. */ - ls_age = LS_AGE (lsa); - lsah->ls_age = htons (ls_age); - - } - - /* Remove LSA from DB summary list. */ - ospf_lsdb_delete (lsdb, lsa); - } - } - - /* Update 'More' bit */ - if (ospf_db_summary_isempty (nbr)) - { -empty: - if (nbr->state >= NSM_Exchange) - { - UNSET_FLAG (nbr->dd_flags, OSPF_DD_FLAG_M); - /* Rewrite DD flags */ - stream_putc_at (s, pp, nbr->dd_flags); - } - else - { - assert (IS_SET_DD_M(nbr->dd_flags)); - } - } - return length; -} - -static int -ospf_make_ls_req_func (struct stream *s, u_int16_t *length, - unsigned long delta, struct ospf_neighbor *nbr, - struct ospf_lsa *lsa) -{ - struct ospf_interface *oi; - - oi = nbr->oi; - - /* LS Request packet overflows interface MTU. */ - if (*length + delta > ospf_packet_max(oi)) - return 0; - - stream_putl (s, lsa->data->type); - stream_put_ipv4 (s, lsa->data->id.s_addr); - stream_put_ipv4 (s, lsa->data->adv_router.s_addr); - - ospf_lsa_unlock (&nbr->ls_req_last); - nbr->ls_req_last = ospf_lsa_lock (lsa); - - *length += 12; - return 1; -} - -static int -ospf_make_ls_req (struct ospf_neighbor *nbr, struct stream *s) -{ - struct ospf_lsa *lsa; - u_int16_t length = OSPF_LS_REQ_MIN_SIZE; - unsigned long delta = stream_get_endp(s)+12; - struct route_table *table; - struct route_node *rn; - int i; - struct ospf_lsdb *lsdb; - - lsdb = &nbr->ls_req; - - for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) - { - table = lsdb->type[i].db; - for (rn = route_top (table); rn; rn = route_next (rn)) - if ((lsa = (rn->info)) != NULL) - if (ospf_make_ls_req_func (s, &length, delta, nbr, lsa) == 0) - { - route_unlock_node (rn); - break; - } - } - return length; -} - -static int -ls_age_increment (struct ospf_lsa *lsa, int delay) -{ - int age; - - age = IS_LSA_MAXAGE (lsa) ? OSPF_LSA_MAXAGE : LS_AGE (lsa) + delay; - - return (age > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : age); -} - -static int -ospf_make_ls_upd (struct ospf_interface *oi, struct list *update, struct stream *s) -{ - struct ospf_lsa *lsa; - struct listnode *node; - u_int16_t length = 0; - unsigned int size_noauth; - unsigned long delta = stream_get_endp (s); - unsigned long pp; - int count = 0; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_make_ls_upd: Start"); - - pp = stream_get_endp (s); - stream_forward_endp (s, OSPF_LS_UPD_MIN_SIZE); - length += OSPF_LS_UPD_MIN_SIZE; +static void ospf_fill_header(struct ospf_interface *oi, struct stream *s, + u_int16_t length) +{ + struct ospf_header *ospfh; + + ospfh = (struct ospf_header *)STREAM_DATA(s); + + /* Fill length. */ + ospfh->length = htons(length); + + /* Calculate checksum. */ + if (ntohs(ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC) + ospfh->checksum = in_cksum(ospfh, length); + else + ospfh->checksum = 0; + + /* Add Authentication Data. */ + ospf_make_auth(oi, ospfh); +} + +static int ospf_make_hello(struct ospf_interface *oi, struct stream *s) +{ + struct ospf_neighbor *nbr; + struct route_node *rn; + u_int16_t length = OSPF_HELLO_MIN_SIZE; + struct in_addr mask; + unsigned long p; + int flag = 0; + + /* Set netmask of interface. */ + if (!(CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED) + && oi->type == OSPF_IFTYPE_POINTOPOINT) + && oi->type != OSPF_IFTYPE_VIRTUALLINK) + masklen2ip(oi->address->prefixlen, &mask); + else + memset((char *)&mask, 0, sizeof(struct in_addr)); + stream_put_ipv4(s, mask.s_addr); + + /* Set Hello Interval. */ + if (OSPF_IF_PARAM(oi, fast_hello) == 0) + stream_putw(s, OSPF_IF_PARAM(oi, v_hello)); + else + stream_putw(s, 0); /* hello-interval of 0 for fast-hellos */ + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("make_hello: options: %x, int: %s", OPTIONS(oi), + IF_NAME(oi)); + + /* Set Options. */ + stream_putc(s, OPTIONS(oi)); + + /* Set Router Priority. */ + stream_putc(s, PRIORITY(oi)); + + /* Set Router Dead Interval. */ + stream_putl(s, OSPF_IF_PARAM(oi, v_wait)); + + /* Set Designated Router. */ + stream_put_ipv4(s, DR(oi).s_addr); + + p = stream_get_endp(s); + + /* Set Backup Designated Router. */ + stream_put_ipv4(s, BDR(oi).s_addr); + + /* Add neighbor seen. */ + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info)) + if (nbr->router_id.s_addr + != 0) /* Ignore 0.0.0.0 node. */ + if (nbr->state + != NSM_Attempt) /* Ignore Down neighbor. */ + if (nbr->state + != NSM_Down) /* This is myself for + DR election. */ + if (!IPV4_ADDR_SAME( + &nbr->router_id, + &oi->ospf->router_id)) { + /* Check neighbor is + * sane? */ + if (nbr->d_router.s_addr + != 0 + && IPV4_ADDR_SAME( + &nbr->d_router, + &oi->address + ->u + .prefix4) + && IPV4_ADDR_SAME( + &nbr->bd_router, + &oi->address + ->u + .prefix4)) + flag = 1; + + stream_put_ipv4( + s, + nbr->router_id + .s_addr); + length += 4; + } + + /* Let neighbor generate BackupSeen. */ + if (flag == 1) + stream_putl_at(s, p, 0); /* ipv4 address, normally */ + + return length; +} + +static int ospf_make_db_desc(struct ospf_interface *oi, + struct ospf_neighbor *nbr, struct stream *s) +{ + struct ospf_lsa *lsa; + u_int16_t length = OSPF_DB_DESC_MIN_SIZE; + u_char options; + unsigned long pp; + int i; + struct ospf_lsdb *lsdb; + + /* Set Interface MTU. */ + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + stream_putw(s, 0); + else + stream_putw(s, oi->ifp->mtu); + + /* Set Options. */ + options = OPTIONS(oi); + if (CHECK_FLAG(oi->ospf->config, OSPF_OPAQUE_CAPABLE)) + SET_FLAG(options, OSPF_OPTION_O); + stream_putc(s, options); + + /* DD flags */ + pp = stream_get_endp(s); + stream_putc(s, nbr->dd_flags); + + /* Set DD Sequence Number. */ + stream_putl(s, nbr->dd_seqnum); + + /* shortcut unneeded walk of (empty) summary LSDBs */ + if (ospf_db_summary_isempty(nbr)) + goto empty; + + /* Describe LSA Header from Database Summary List. */ + lsdb = &nbr->db_sum; + + for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) { + struct route_table *table = lsdb->type[i].db; + struct route_node *rn; + + for (rn = route_top(table); rn; rn = route_next(rn)) + if ((lsa = rn->info) != NULL) { + if (IS_OPAQUE_LSA(lsa->data->type) + && (!CHECK_FLAG(options, OSPF_OPTION_O))) { + /* Suppress advertising + * opaque-informations. */ + /* Remove LSA from DB summary list. */ + ospf_lsdb_delete(lsdb, lsa); + continue; + } + + if (!CHECK_FLAG(lsa->flags, OSPF_LSA_DISCARD)) { + struct lsa_header *lsah; + u_int16_t ls_age; + + /* DD packet overflows interface MTU. */ + if (length + OSPF_LSA_HEADER_SIZE + > ospf_packet_max(oi)) + break; + + /* Keep pointer to LS age. */ + lsah = (struct lsa_header + *)(STREAM_DATA(s) + + stream_get_endp( + s)); + + /* Proceed stream pointer. */ + stream_put(s, lsa->data, + OSPF_LSA_HEADER_SIZE); + length += OSPF_LSA_HEADER_SIZE; + + /* Set LS age. */ + ls_age = LS_AGE(lsa); + lsah->ls_age = htons(ls_age); + } + + /* Remove LSA from DB summary list. */ + ospf_lsdb_delete(lsdb, lsa); + } + } - /* Calculate amount of packet usable for data. */ - size_noauth = stream_get_size(s) - ospf_packet_authspace(oi); + /* Update 'More' bit */ + if (ospf_db_summary_isempty(nbr)) { + empty: + if (nbr->state >= NSM_Exchange) { + UNSET_FLAG(nbr->dd_flags, OSPF_DD_FLAG_M); + /* Rewrite DD flags */ + stream_putc_at(s, pp, nbr->dd_flags); + } else { + assert(IS_SET_DD_M(nbr->dd_flags)); + } + } + return length; +} - while ((node = listhead (update)) != NULL) - { - struct lsa_header *lsah; - u_int16_t ls_age; +static int ospf_make_ls_req_func(struct stream *s, u_int16_t *length, + unsigned long delta, struct ospf_neighbor *nbr, + struct ospf_lsa *lsa) +{ + struct ospf_interface *oi; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_make_ls_upd: List Iteration %d", count); + oi = nbr->oi; - lsa = listgetdata (node); + /* LS Request packet overflows interface MTU. */ + if (*length + delta > ospf_packet_max(oi)) + return 0; - assert (lsa->data); + stream_putl(s, lsa->data->type); + stream_put_ipv4(s, lsa->data->id.s_addr); + stream_put_ipv4(s, lsa->data->adv_router.s_addr); - /* Will it fit? */ - if (length + delta + ntohs (lsa->data->length) > size_noauth) - break; + ospf_lsa_unlock(&nbr->ls_req_last); + nbr->ls_req_last = ospf_lsa_lock(lsa); - /* Keep pointer to LS age. */ - lsah = (struct lsa_header *) (STREAM_DATA (s) + stream_get_endp (s)); + *length += 12; + return 1; +} - /* Put LSA to Link State Request. */ - stream_put (s, lsa->data, ntohs (lsa->data->length)); +static int ospf_make_ls_req(struct ospf_neighbor *nbr, struct stream *s) +{ + struct ospf_lsa *lsa; + u_int16_t length = OSPF_LS_REQ_MIN_SIZE; + unsigned long delta = stream_get_endp(s) + 12; + struct route_table *table; + struct route_node *rn; + int i; + struct ospf_lsdb *lsdb; - /* Set LS age. */ - /* each hop must increment an lsa_age by transmit_delay - of OSPF interface */ - ls_age = ls_age_increment (lsa, OSPF_IF_PARAM (oi, transmit_delay)); - lsah->ls_age = htons (ls_age); + lsdb = &nbr->ls_req; - length += ntohs (lsa->data->length); - count++; + for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) { + table = lsdb->type[i].db; + for (rn = route_top(table); rn; rn = route_next(rn)) + if ((lsa = (rn->info)) != NULL) + if (ospf_make_ls_req_func(s, &length, delta, + nbr, lsa) + == 0) { + route_unlock_node(rn); + break; + } + } + return length; +} - list_delete_node (update, node); - ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */ - } +static int ls_age_increment(struct ospf_lsa *lsa, int delay) +{ + int age; - /* Now set #LSAs. */ - stream_putl_at (s, pp, count); + age = IS_LSA_MAXAGE(lsa) ? OSPF_LSA_MAXAGE : LS_AGE(lsa) + delay; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_make_ls_upd: Stop"); - return length; + return (age > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : age); } -static int -ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s) +static int ospf_make_ls_upd(struct ospf_interface *oi, struct list *update, + struct stream *s) { - struct listnode *node, *nnode; - u_int16_t length = OSPF_LS_ACK_MIN_SIZE; - unsigned long delta = stream_get_endp(s) + 24; - struct ospf_lsa *lsa; + struct ospf_lsa *lsa; + struct listnode *node; + u_int16_t length = 0; + unsigned int size_noauth; + unsigned long delta = stream_get_endp(s); + unsigned long pp; + int count = 0; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_make_ls_upd: Start"); + + pp = stream_get_endp(s); + stream_forward_endp(s, OSPF_LS_UPD_MIN_SIZE); + length += OSPF_LS_UPD_MIN_SIZE; + + /* Calculate amount of packet usable for data. */ + size_noauth = stream_get_size(s) - ospf_packet_authspace(oi); + + while ((node = listhead(update)) != NULL) { + struct lsa_header *lsah; + u_int16_t ls_age; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_make_ls_upd: List Iteration %d", + count); + + lsa = listgetdata(node); + + assert(lsa->data); + + /* Will it fit? */ + if (length + delta + ntohs(lsa->data->length) > size_noauth) + break; + + /* Keep pointer to LS age. */ + lsah = (struct lsa_header *)(STREAM_DATA(s) + + stream_get_endp(s)); + + /* Put LSA to Link State Request. */ + stream_put(s, lsa->data, ntohs(lsa->data->length)); - for (ALL_LIST_ELEMENTS (ack, node, nnode, lsa)) - { - assert (lsa); - - if (length + delta > ospf_packet_max (oi)) - break; - - stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE); - length += OSPF_LSA_HEADER_SIZE; - - listnode_delete (ack, lsa); - ospf_lsa_unlock (&lsa); /* oi->ls_ack_direct.ls_ack */ - } - - return length; + /* Set LS age. */ + /* each hop must increment an lsa_age by transmit_delay + of OSPF interface */ + ls_age = ls_age_increment(lsa, + OSPF_IF_PARAM(oi, transmit_delay)); + lsah->ls_age = htons(ls_age); + + length += ntohs(lsa->data->length); + count++; + + list_delete_node(update, node); + ospf_lsa_unlock(&lsa); /* oi->ls_upd_queue */ + } + + /* Now set #LSAs. */ + stream_putl_at(s, pp, count); + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_make_ls_upd: Stop"); + return length; } -static void -ospf_hello_send_sub (struct ospf_interface *oi, in_addr_t addr) +static int ospf_make_ls_ack(struct ospf_interface *oi, struct list *ack, + struct stream *s) { - struct ospf_packet *op; - u_int16_t length = OSPF_HEADER_SIZE; + struct listnode *node, *nnode; + u_int16_t length = OSPF_LS_ACK_MIN_SIZE; + unsigned long delta = stream_get_endp(s) + 24; + struct ospf_lsa *lsa; - op = ospf_packet_new (oi->ifp->mtu); + for (ALL_LIST_ELEMENTS(ack, node, nnode, lsa)) { + assert(lsa); - /* Prepare OSPF common header. */ - ospf_make_header (OSPF_MSG_HELLO, oi, op->s); + if (length + delta > ospf_packet_max(oi)) + break; - /* Prepare OSPF Hello body. */ - length += ospf_make_hello (oi, op->s); + stream_put(s, lsa->data, OSPF_LSA_HEADER_SIZE); + length += OSPF_LSA_HEADER_SIZE; + + listnode_delete(ack, lsa); + ospf_lsa_unlock(&lsa); /* oi->ls_ack_direct.ls_ack */ + } + + return length; +} + +static void ospf_hello_send_sub(struct ospf_interface *oi, in_addr_t addr) +{ + struct ospf_packet *op; + u_int16_t length = OSPF_HEADER_SIZE; - /* Fill OSPF header. */ - ospf_fill_header (oi, op->s, length); + op = ospf_packet_new(oi->ifp->mtu); - /* Set packet length. */ - op->length = length; + /* Prepare OSPF common header. */ + ospf_make_header(OSPF_MSG_HELLO, oi, op->s); - op->dst.s_addr = addr; + /* Prepare OSPF Hello body. */ + length += ospf_make_hello(oi, op->s); - /* Add packet to the top of the interface output queue, so that they - * can't get delayed by things like long queues of LS Update packets - */ - ospf_packet_add_top (oi, op); + /* Fill OSPF header. */ + ospf_fill_header(oi, op->s, length); - /* Hook thread to write packet. */ - OSPF_ISM_WRITE_ON (oi->ospf); + /* Set packet length. */ + op->length = length; + + op->dst.s_addr = addr; + + /* Add packet to the top of the interface output queue, so that they + * can't get delayed by things like long queues of LS Update packets + */ + ospf_packet_add_top(oi, op); + + /* Hook thread to write packet. */ + OSPF_ISM_WRITE_ON(oi->ospf); } -static void -ospf_poll_send (struct ospf_nbr_nbma *nbr_nbma) +static void ospf_poll_send(struct ospf_nbr_nbma *nbr_nbma) { - struct ospf_interface *oi; + struct ospf_interface *oi; - oi = nbr_nbma->oi; - assert(oi); + oi = nbr_nbma->oi; + assert(oi); - /* If this is passive interface, do not send OSPF Hello. */ - if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE) - return; + /* If this is passive interface, do not send OSPF Hello. */ + if (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_PASSIVE) + return; - if (oi->type != OSPF_IFTYPE_NBMA) - return; + if (oi->type != OSPF_IFTYPE_NBMA) + return; - if (nbr_nbma->nbr != NULL && nbr_nbma->nbr->state != NSM_Down) - return; + if (nbr_nbma->nbr != NULL && nbr_nbma->nbr->state != NSM_Down) + return; - if (PRIORITY(oi) == 0) - return; + if (PRIORITY(oi) == 0) + return; - if (nbr_nbma->priority == 0 - && oi->state != ISM_DR && oi->state != ISM_Backup) - return; + if (nbr_nbma->priority == 0 && oi->state != ISM_DR + && oi->state != ISM_Backup) + return; - ospf_hello_send_sub (oi, nbr_nbma->addr.s_addr); + ospf_hello_send_sub(oi, nbr_nbma->addr.s_addr); } -int -ospf_poll_timer (struct thread *thread) +int ospf_poll_timer(struct thread *thread) { - struct ospf_nbr_nbma *nbr_nbma; + struct ospf_nbr_nbma *nbr_nbma; - nbr_nbma = THREAD_ARG (thread); - nbr_nbma->t_poll = NULL; + nbr_nbma = THREAD_ARG(thread); + nbr_nbma->t_poll = NULL; - if (IS_DEBUG_OSPF (nsm, NSM_TIMERS)) - zlog_debug("NSM[%s:%s]: Timer (Poll timer expire)", IF_NAME(nbr_nbma->oi), - inet_ntoa(nbr_nbma->addr)); + if (IS_DEBUG_OSPF(nsm, NSM_TIMERS)) + zlog_debug("NSM[%s:%s]: Timer (Poll timer expire)", + IF_NAME(nbr_nbma->oi), inet_ntoa(nbr_nbma->addr)); - ospf_poll_send (nbr_nbma); + ospf_poll_send(nbr_nbma); - if (nbr_nbma->v_poll > 0) - OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer, - nbr_nbma->v_poll); + if (nbr_nbma->v_poll > 0) + OSPF_POLL_TIMER_ON(nbr_nbma->t_poll, ospf_poll_timer, + nbr_nbma->v_poll); - return 0; + return 0; } -int -ospf_hello_reply_timer (struct thread *thread) +int ospf_hello_reply_timer(struct thread *thread) { - struct ospf_neighbor *nbr; + struct ospf_neighbor *nbr; - nbr = THREAD_ARG (thread); - nbr->t_hello_reply = NULL; + nbr = THREAD_ARG(thread); + nbr->t_hello_reply = NULL; - assert (nbr->oi); + assert(nbr->oi); - if (IS_DEBUG_OSPF (nsm, NSM_TIMERS)) - zlog_debug("NSM[%s:%s]: Timer (hello-reply timer expire)", - IF_NAME(nbr->oi), inet_ntoa(nbr->router_id)); + if (IS_DEBUG_OSPF(nsm, NSM_TIMERS)) + zlog_debug("NSM[%s:%s]: Timer (hello-reply timer expire)", + IF_NAME(nbr->oi), inet_ntoa(nbr->router_id)); - ospf_hello_send_sub (nbr->oi, nbr->address.u.prefix4.s_addr); + ospf_hello_send_sub(nbr->oi, nbr->address.u.prefix4.s_addr); - return 0; + return 0; } /* Send OSPF Hello. */ -void -ospf_hello_send (struct ospf_interface *oi) -{ - /* If this is passive interface, do not send OSPF Hello. */ - if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE) - return; - - if (oi->type == OSPF_IFTYPE_NBMA) - { - struct ospf_neighbor *nbr; - struct route_node *rn; - - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - if (nbr != oi->nbr_self) - if (nbr->state != NSM_Down) - { - /* RFC 2328 Section 9.5.1 - If the router is not eligible to become Designated Router, - it must periodically send Hello Packets to both the - Designated Router and the Backup Designated Router (if they - exist). */ - if (PRIORITY(oi) == 0 && - IPV4_ADDR_CMP(&DR(oi), &nbr->address.u.prefix4) && - IPV4_ADDR_CMP(&BDR(oi), &nbr->address.u.prefix4)) - continue; - - /* If the router is eligible to become Designated Router, it - must periodically send Hello Packets to all neighbors that - are also eligible. In addition, if the router is itself the - Designated Router or Backup Designated Router, it must also - send periodic Hello Packets to all other neighbors. */ - - if (nbr->priority == 0 && oi->state == ISM_DROther) - continue; - /* if oi->state == Waiting, send hello to all neighbors */ - ospf_hello_send_sub (oi, nbr->address.u.prefix4.s_addr); - } - } - else - { - /* Decide destination address. */ - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - ospf_hello_send_sub (oi, oi->vl_data->peer_addr.s_addr); - else - ospf_hello_send_sub (oi, htonl (OSPF_ALLSPFROUTERS)); - } +void ospf_hello_send(struct ospf_interface *oi) +{ + /* If this is passive interface, do not send OSPF Hello. */ + if (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_PASSIVE) + return; + + if (oi->type == OSPF_IFTYPE_NBMA) { + struct ospf_neighbor *nbr; + struct route_node *rn; + + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info)) + if (nbr != oi->nbr_self) + if (nbr->state != NSM_Down) { + /* RFC 2328 Section 9.5.1 + If the router is not + eligible to become Designated + Router, + it must periodically send + Hello Packets to both the + Designated Router and the + Backup Designated Router (if + they + exist). */ + if (PRIORITY(oi) == 0 + && IPV4_ADDR_CMP( + &DR(oi), + &nbr->address.u + .prefix4) + && IPV4_ADDR_CMP( + &BDR(oi), + &nbr->address.u + .prefix4)) + continue; + + /* If the router is eligible to + become Designated Router, it + must periodically send Hello + Packets to all neighbors that + are also eligible. In + addition, if the router is + itself the + Designated Router or Backup + Designated Router, it must + also + send periodic Hello Packets + to all other neighbors. */ + + if (nbr->priority == 0 + && oi->state == ISM_DROther) + continue; + /* if oi->state == Waiting, send + * hello to all neighbors */ + ospf_hello_send_sub( + oi, + nbr->address.u.prefix4 + .s_addr); + } + } else { + /* Decide destination address. */ + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + ospf_hello_send_sub(oi, oi->vl_data->peer_addr.s_addr); + else + ospf_hello_send_sub(oi, htonl(OSPF_ALLSPFROUTERS)); + } } /* Send OSPF Database Description. */ -void -ospf_db_desc_send (struct ospf_neighbor *nbr) +void ospf_db_desc_send(struct ospf_neighbor *nbr) { - struct ospf_interface *oi; - struct ospf_packet *op; - u_int16_t length = OSPF_HEADER_SIZE; + struct ospf_interface *oi; + struct ospf_packet *op; + u_int16_t length = OSPF_HEADER_SIZE; - oi = nbr->oi; - op = ospf_packet_new (oi->ifp->mtu); + oi = nbr->oi; + op = ospf_packet_new(oi->ifp->mtu); - /* Prepare OSPF common header. */ - ospf_make_header (OSPF_MSG_DB_DESC, oi, op->s); + /* Prepare OSPF common header. */ + ospf_make_header(OSPF_MSG_DB_DESC, oi, op->s); - /* Prepare OSPF Database Description body. */ - length += ospf_make_db_desc (oi, nbr, op->s); + /* Prepare OSPF Database Description body. */ + length += ospf_make_db_desc(oi, nbr, op->s); - /* Fill OSPF header. */ - ospf_fill_header (oi, op->s, length); + /* Fill OSPF header. */ + ospf_fill_header(oi, op->s, length); - /* Set packet length. */ - op->length = length; + /* Set packet length. */ + op->length = length; - /* Decide destination address. */ - if (oi->type == OSPF_IFTYPE_POINTOPOINT) - op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS); - else - op->dst = nbr->address.u.prefix4; + /* Decide destination address. */ + if (oi->type == OSPF_IFTYPE_POINTOPOINT) + op->dst.s_addr = htonl(OSPF_ALLSPFROUTERS); + else + op->dst = nbr->address.u.prefix4; - /* Add packet to the interface output queue. */ - ospf_packet_add (oi, op); + /* Add packet to the interface output queue. */ + ospf_packet_add(oi, op); - /* Hook thread to write packet. */ - OSPF_ISM_WRITE_ON (oi->ospf); + /* Hook thread to write packet. */ + OSPF_ISM_WRITE_ON(oi->ospf); - /* Remove old DD packet, then copy new one and keep in neighbor structure. */ - if (nbr->last_send) - ospf_packet_free (nbr->last_send); - nbr->last_send = ospf_packet_dup (op); - monotime(&nbr->last_send_ts); + /* Remove old DD packet, then copy new one and keep in neighbor + * structure. */ + if (nbr->last_send) + ospf_packet_free(nbr->last_send); + nbr->last_send = ospf_packet_dup(op); + monotime(&nbr->last_send_ts); } /* Re-send Database Description. */ -void -ospf_db_desc_resend (struct ospf_neighbor *nbr) +void ospf_db_desc_resend(struct ospf_neighbor *nbr) { - struct ospf_interface *oi; + struct ospf_interface *oi; - oi = nbr->oi; + oi = nbr->oi; - /* Add packet to the interface output queue. */ - ospf_packet_add (oi, ospf_packet_dup (nbr->last_send)); + /* Add packet to the interface output queue. */ + ospf_packet_add(oi, ospf_packet_dup(nbr->last_send)); - /* Hook thread to write packet. */ - OSPF_ISM_WRITE_ON (oi->ospf); + /* Hook thread to write packet. */ + OSPF_ISM_WRITE_ON(oi->ospf); } /* Send Link State Request. */ -void -ospf_ls_req_send (struct ospf_neighbor *nbr) +void ospf_ls_req_send(struct ospf_neighbor *nbr) { - struct ospf_interface *oi; - struct ospf_packet *op; - u_int16_t length = OSPF_HEADER_SIZE; + struct ospf_interface *oi; + struct ospf_packet *op; + u_int16_t length = OSPF_HEADER_SIZE; - oi = nbr->oi; - op = ospf_packet_new (oi->ifp->mtu); + oi = nbr->oi; + op = ospf_packet_new(oi->ifp->mtu); - /* Prepare OSPF common header. */ - ospf_make_header (OSPF_MSG_LS_REQ, oi, op->s); + /* Prepare OSPF common header. */ + ospf_make_header(OSPF_MSG_LS_REQ, oi, op->s); - /* Prepare OSPF Link State Request body. */ - length += ospf_make_ls_req (nbr, op->s); - if (length == OSPF_HEADER_SIZE) - { - ospf_packet_free (op); - return; - } + /* Prepare OSPF Link State Request body. */ + length += ospf_make_ls_req(nbr, op->s); + if (length == OSPF_HEADER_SIZE) { + ospf_packet_free(op); + return; + } - /* Fill OSPF header. */ - ospf_fill_header (oi, op->s, length); + /* Fill OSPF header. */ + ospf_fill_header(oi, op->s, length); - /* Set packet length. */ - op->length = length; + /* Set packet length. */ + op->length = length; - /* Decide destination address. */ - if (oi->type == OSPF_IFTYPE_POINTOPOINT) - op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS); - else - op->dst = nbr->address.u.prefix4; + /* Decide destination address. */ + if (oi->type == OSPF_IFTYPE_POINTOPOINT) + op->dst.s_addr = htonl(OSPF_ALLSPFROUTERS); + else + op->dst = nbr->address.u.prefix4; - /* Add packet to the interface output queue. */ - ospf_packet_add (oi, op); + /* Add packet to the interface output queue. */ + ospf_packet_add(oi, op); - /* Hook thread to write packet. */ - OSPF_ISM_WRITE_ON (oi->ospf); + /* Hook thread to write packet. */ + OSPF_ISM_WRITE_ON(oi->ospf); - /* Add Link State Request Retransmission Timer. */ - OSPF_NSM_TIMER_ON (nbr->t_ls_req, ospf_ls_req_timer, nbr->v_ls_req); + /* Add Link State Request Retransmission Timer. */ + OSPF_NSM_TIMER_ON(nbr->t_ls_req, ospf_ls_req_timer, nbr->v_ls_req); } /* Send Link State Update with an LSA. */ -void -ospf_ls_upd_send_lsa (struct ospf_neighbor *nbr, struct ospf_lsa *lsa, - int flag) +void ospf_ls_upd_send_lsa(struct ospf_neighbor *nbr, struct ospf_lsa *lsa, + int flag) { - struct list *update; + struct list *update; - update = list_new (); + update = list_new(); - listnode_add (update, lsa); - ospf_ls_upd_send (nbr, update, flag); + listnode_add(update, lsa); + ospf_ls_upd_send(nbr, update, flag); - list_delete (update); + list_delete(update); } /* Determine size for packet. Must be at least big enough to accomodate next @@ -3662,309 +3749,310 @@ ospf_ls_upd_send_lsa (struct ospf_neighbor *nbr, struct ospf_lsa *lsa, * NULL if we can not allocate, eg because LSA is bigger than imposed limit * on packet sizes (in which case offending LSA is deleted from update list) */ -static struct ospf_packet * -ospf_ls_upd_packet_new (struct list *update, struct ospf_interface *oi) -{ - struct ospf_lsa *lsa; - struct listnode *ln; - size_t size; - static char warned = 0; - - lsa = listgetdata((ln = listhead (update))); - assert (lsa->data); - - if ((OSPF_LS_UPD_MIN_SIZE + ntohs (lsa->data->length)) - > ospf_packet_max (oi)) - { - if (!warned) - { - zlog_warn ("ospf_ls_upd_packet_new: oversized LSA encountered!" - "will need to fragment. Not optimal. Try divide up" - " your network with areas. Use 'debug ospf packet send'" - " to see details, or look at 'show ip ospf database ..'"); - warned = 1; - } - - if (IS_DEBUG_OSPF_PACKET (0, SEND)) - zlog_debug ("ospf_ls_upd_packet_new: oversized LSA id:%s," - " %d bytes originated by %s, will be fragmented!", - inet_ntoa (lsa->data->id), - ntohs (lsa->data->length), - inet_ntoa (lsa->data->adv_router)); - - /* - * Allocate just enough to fit this LSA only, to avoid including other - * LSAs in fragmented LSA Updates. - */ - size = ntohs (lsa->data->length) + (oi->ifp->mtu - ospf_packet_max (oi)) - + OSPF_LS_UPD_MIN_SIZE; - } - else - size = oi->ifp->mtu; - - if (size > OSPF_MAX_PACKET_SIZE) - { - zlog_warn ("ospf_ls_upd_packet_new: oversized LSA id:%s too big," - " %d bytes, packet size %ld, dropping it completely." - " OSPF routing is broken!", - inet_ntoa (lsa->data->id), ntohs (lsa->data->length), - (long int) size); - list_delete_node (update, ln); - return NULL; - } - - /* IP header is built up separately by ospf_write(). This means, that we must - * reduce the "affordable" size just calculated by length of an IP header. - * This makes sure, that even if we manage to fill the payload with LSA data - * completely, the final packet (our data plus IP header) still fits into - * outgoing interface MTU. This correction isn't really meaningful for an - * oversized LSA, but for consistency the correction is done for both cases. - * - * P.S. OSPF_MAX_PACKET_SIZE above already includes IP header size - */ - return ospf_packet_new (size - sizeof (struct ip)); -} - -static void -ospf_ls_upd_queue_send (struct ospf_interface *oi, struct list *update, - struct in_addr addr) -{ - struct ospf_packet *op; - u_int16_t length = OSPF_HEADER_SIZE; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("listcount = %d, [%s]dst %s", listcount (update), IF_NAME(oi), - inet_ntoa(addr)); - - op = ospf_ls_upd_packet_new (update, oi); - - /* Prepare OSPF common header. */ - ospf_make_header (OSPF_MSG_LS_UPD, oi, op->s); - - /* Prepare OSPF Link State Update body. - * Includes Type-7 translation. - */ - length += ospf_make_ls_upd (oi, update, op->s); - - /* Fill OSPF header. */ - ospf_fill_header (oi, op->s, length); - - /* Set packet length. */ - op->length = length; - - /* Decide destination address. */ - if (oi->type == OSPF_IFTYPE_POINTOPOINT) - op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS); - else - op->dst.s_addr = addr.s_addr; - - /* Add packet to the interface output queue. */ - ospf_packet_add (oi, op); - - /* Hook thread to write packet. */ - OSPF_ISM_WRITE_ON (oi->ospf); -} - -static int -ospf_ls_upd_send_queue_event (struct thread *thread) -{ - struct ospf_interface *oi = THREAD_ARG(thread); - struct route_node *rn; - struct route_node *rnext; - struct list *update; - char again = 0; - - oi->t_ls_upd_event = NULL; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_ls_upd_send_queue start"); - - for (rn = route_top (oi->ls_upd_queue); rn; rn = rnext) - { - rnext = route_next (rn); - - if (rn->info == NULL) - continue; - - update = (struct list *)rn->info; - - ospf_ls_upd_queue_send (oi, update, rn->p.u.prefix4); - - /* list might not be empty. */ - if (listcount(update) == 0) - { - list_delete (rn->info); - rn->info = NULL; - route_unlock_node (rn); - } - else - again = 1; - } - - if (again != 0) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_ls_upd_send_queue: update lists not cleared," - " %d nodes to try again, raising new event", again); - oi->t_ls_upd_event = NULL; - thread_add_event(master, ospf_ls_upd_send_queue_event, oi, 0, - &oi->t_ls_upd_event); - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_ls_upd_send_queue stop"); - - return 0; -} - -void -ospf_ls_upd_send (struct ospf_neighbor *nbr, struct list *update, int flag) -{ - struct ospf_interface *oi; - struct ospf_lsa *lsa; - struct prefix_ipv4 p; - struct route_node *rn; - struct listnode *node; - - oi = nbr->oi; - - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - - /* Decide destination address. */ - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - p.prefix = oi->vl_data->peer_addr; - else if (oi->type == OSPF_IFTYPE_POINTOPOINT) - p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS); - else if (flag == OSPF_SEND_PACKET_DIRECT) - p.prefix = nbr->address.u.prefix4; - else if (oi->state == ISM_DR || oi->state == ISM_Backup) - p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS); - else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) - p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS); - else - p.prefix.s_addr = htonl (OSPF_ALLDROUTERS); - - if (oi->type == OSPF_IFTYPE_NBMA) - { - if (flag == OSPF_SEND_PACKET_INDIRECT) - zlog_warn ("* LS-Update is directly sent on NBMA network."); - if (IPV4_ADDR_SAME(&oi->address->u.prefix4, &p.prefix.s_addr)) - zlog_warn ("* LS-Update is sent to myself."); - } - - rn = route_node_get (oi->ls_upd_queue, (struct prefix *) &p); - - if (rn->info == NULL) - rn->info = list_new (); - else - route_unlock_node (rn); - - for (ALL_LIST_ELEMENTS_RO (update, node, lsa)) - listnode_add (rn->info, ospf_lsa_lock (lsa)); /* oi->ls_upd_queue */ - - thread_add_event(master, ospf_ls_upd_send_queue_event, oi, 0, - &oi->t_ls_upd_event); -} - -static void -ospf_ls_ack_send_list (struct ospf_interface *oi, struct list *ack, - struct in_addr dst) -{ - struct ospf_packet *op; - u_int16_t length = OSPF_HEADER_SIZE; - - op = ospf_packet_new (oi->ifp->mtu); - - /* Prepare OSPF common header. */ - ospf_make_header (OSPF_MSG_LS_ACK, oi, op->s); - - /* Prepare OSPF Link State Acknowledgment body. */ - length += ospf_make_ls_ack (oi, ack, op->s); - - /* Fill OSPF header. */ - ospf_fill_header (oi, op->s, length); - - /* Set packet length. */ - op->length = length; - - /* Decide destination address. */ - if (oi->type == OSPF_IFTYPE_POINTOPOINT) - op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS); - else - op->dst.s_addr = dst.s_addr; - - /* Add packet to the interface output queue. */ - ospf_packet_add (oi, op); +static struct ospf_packet *ospf_ls_upd_packet_new(struct list *update, + struct ospf_interface *oi) +{ + struct ospf_lsa *lsa; + struct listnode *ln; + size_t size; + static char warned = 0; + + lsa = listgetdata((ln = listhead(update))); + assert(lsa->data); + + if ((OSPF_LS_UPD_MIN_SIZE + ntohs(lsa->data->length)) + > ospf_packet_max(oi)) { + if (!warned) { + zlog_warn( + "ospf_ls_upd_packet_new: oversized LSA encountered!" + "will need to fragment. Not optimal. Try divide up" + " your network with areas. Use 'debug ospf packet send'" + " to see details, or look at 'show ip ospf database ..'"); + warned = 1; + } + + if (IS_DEBUG_OSPF_PACKET(0, SEND)) + zlog_debug( + "ospf_ls_upd_packet_new: oversized LSA id:%s," + " %d bytes originated by %s, will be fragmented!", + inet_ntoa(lsa->data->id), + ntohs(lsa->data->length), + inet_ntoa(lsa->data->adv_router)); + + /* + * Allocate just enough to fit this LSA only, to avoid including + * other + * LSAs in fragmented LSA Updates. + */ + size = ntohs(lsa->data->length) + + (oi->ifp->mtu - ospf_packet_max(oi)) + + OSPF_LS_UPD_MIN_SIZE; + } else + size = oi->ifp->mtu; + + if (size > OSPF_MAX_PACKET_SIZE) { + zlog_warn( + "ospf_ls_upd_packet_new: oversized LSA id:%s too big," + " %d bytes, packet size %ld, dropping it completely." + " OSPF routing is broken!", + inet_ntoa(lsa->data->id), ntohs(lsa->data->length), + (long int)size); + list_delete_node(update, ln); + return NULL; + } - /* Hook thread to write packet. */ - OSPF_ISM_WRITE_ON (oi->ospf); + /* IP header is built up separately by ospf_write(). This means, that we + * must + * reduce the "affordable" size just calculated by length of an IP + * header. + * This makes sure, that even if we manage to fill the payload with LSA + * data + * completely, the final packet (our data plus IP header) still fits + * into + * outgoing interface MTU. This correction isn't really meaningful for + * an + * oversized LSA, but for consistency the correction is done for both + * cases. + * + * P.S. OSPF_MAX_PACKET_SIZE above already includes IP header size + */ + return ospf_packet_new(size - sizeof(struct ip)); } -static int -ospf_ls_ack_send_event (struct thread *thread) +static void ospf_ls_upd_queue_send(struct ospf_interface *oi, + struct list *update, struct in_addr addr) { - struct ospf_interface *oi = THREAD_ARG (thread); + struct ospf_packet *op; + u_int16_t length = OSPF_HEADER_SIZE; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("listcount = %d, [%s]dst %s", listcount(update), + IF_NAME(oi), inet_ntoa(addr)); + + op = ospf_ls_upd_packet_new(update, oi); - oi->t_ls_ack_direct = NULL; - - while (listcount (oi->ls_ack_direct.ls_ack)) - ospf_ls_ack_send_list (oi, oi->ls_ack_direct.ls_ack, - oi->ls_ack_direct.dst); + /* Prepare OSPF common header. */ + ospf_make_header(OSPF_MSG_LS_UPD, oi, op->s); - return 0; + /* Prepare OSPF Link State Update body. + * Includes Type-7 translation. + */ + length += ospf_make_ls_upd(oi, update, op->s); + + /* Fill OSPF header. */ + ospf_fill_header(oi, op->s, length); + + /* Set packet length. */ + op->length = length; + + /* Decide destination address. */ + if (oi->type == OSPF_IFTYPE_POINTOPOINT) + op->dst.s_addr = htonl(OSPF_ALLSPFROUTERS); + else + op->dst.s_addr = addr.s_addr; + + /* Add packet to the interface output queue. */ + ospf_packet_add(oi, op); + + /* Hook thread to write packet. */ + OSPF_ISM_WRITE_ON(oi->ospf); +} + +static int ospf_ls_upd_send_queue_event(struct thread *thread) +{ + struct ospf_interface *oi = THREAD_ARG(thread); + struct route_node *rn; + struct route_node *rnext; + struct list *update; + char again = 0; + + oi->t_ls_upd_event = NULL; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_ls_upd_send_queue start"); + + for (rn = route_top(oi->ls_upd_queue); rn; rn = rnext) { + rnext = route_next(rn); + + if (rn->info == NULL) + continue; + + update = (struct list *)rn->info; + + ospf_ls_upd_queue_send(oi, update, rn->p.u.prefix4); + + /* list might not be empty. */ + if (listcount(update) == 0) { + list_delete(rn->info); + rn->info = NULL; + route_unlock_node(rn); + } else + again = 1; + } + + if (again != 0) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_ls_upd_send_queue: update lists not cleared," + " %d nodes to try again, raising new event", + again); + oi->t_ls_upd_event = NULL; + thread_add_event(master, ospf_ls_upd_send_queue_event, oi, 0, + &oi->t_ls_upd_event); + } + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_ls_upd_send_queue stop"); + + return 0; +} + +void ospf_ls_upd_send(struct ospf_neighbor *nbr, struct list *update, int flag) +{ + struct ospf_interface *oi; + struct ospf_lsa *lsa; + struct prefix_ipv4 p; + struct route_node *rn; + struct listnode *node; + + oi = nbr->oi; + + p.family = AF_INET; + p.prefixlen = IPV4_MAX_BITLEN; + + /* Decide destination address. */ + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + p.prefix = oi->vl_data->peer_addr; + else if (oi->type == OSPF_IFTYPE_POINTOPOINT) + p.prefix.s_addr = htonl(OSPF_ALLSPFROUTERS); + else if (flag == OSPF_SEND_PACKET_DIRECT) + p.prefix = nbr->address.u.prefix4; + else if (oi->state == ISM_DR || oi->state == ISM_Backup) + p.prefix.s_addr = htonl(OSPF_ALLSPFROUTERS); + else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) + p.prefix.s_addr = htonl(OSPF_ALLSPFROUTERS); + else + p.prefix.s_addr = htonl(OSPF_ALLDROUTERS); + + if (oi->type == OSPF_IFTYPE_NBMA) { + if (flag == OSPF_SEND_PACKET_INDIRECT) + zlog_warn( + "* LS-Update is directly sent on NBMA network."); + if (IPV4_ADDR_SAME(&oi->address->u.prefix4, &p.prefix.s_addr)) + zlog_warn("* LS-Update is sent to myself."); + } + + rn = route_node_get(oi->ls_upd_queue, (struct prefix *)&p); + + if (rn->info == NULL) + rn->info = list_new(); + else + route_unlock_node(rn); + + for (ALL_LIST_ELEMENTS_RO(update, node, lsa)) + listnode_add(rn->info, + ospf_lsa_lock(lsa)); /* oi->ls_upd_queue */ + + thread_add_event(master, ospf_ls_upd_send_queue_event, oi, 0, + &oi->t_ls_upd_event); } -void -ospf_ls_ack_send (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) +static void ospf_ls_ack_send_list(struct ospf_interface *oi, struct list *ack, + struct in_addr dst) { - struct ospf_interface *oi = nbr->oi; + struct ospf_packet *op; + u_int16_t length = OSPF_HEADER_SIZE; + + op = ospf_packet_new(oi->ifp->mtu); + + /* Prepare OSPF common header. */ + ospf_make_header(OSPF_MSG_LS_ACK, oi, op->s); + + /* Prepare OSPF Link State Acknowledgment body. */ + length += ospf_make_ls_ack(oi, ack, op->s); + + /* Fill OSPF header. */ + ospf_fill_header(oi, op->s, length); - if (listcount (oi->ls_ack_direct.ls_ack) == 0) - oi->ls_ack_direct.dst = nbr->address.u.prefix4; - - listnode_add (oi->ls_ack_direct.ls_ack, ospf_lsa_lock (lsa)); - - thread_add_event(master, ospf_ls_ack_send_event, oi, 0, - &oi->t_ls_ack_direct); + /* Set packet length. */ + op->length = length; + + /* Decide destination address. */ + if (oi->type == OSPF_IFTYPE_POINTOPOINT) + op->dst.s_addr = htonl(OSPF_ALLSPFROUTERS); + else + op->dst.s_addr = dst.s_addr; + + /* Add packet to the interface output queue. */ + ospf_packet_add(oi, op); + + /* Hook thread to write packet. */ + OSPF_ISM_WRITE_ON(oi->ospf); +} + +static int ospf_ls_ack_send_event(struct thread *thread) +{ + struct ospf_interface *oi = THREAD_ARG(thread); + + oi->t_ls_ack_direct = NULL; + + while (listcount(oi->ls_ack_direct.ls_ack)) + ospf_ls_ack_send_list(oi, oi->ls_ack_direct.ls_ack, + oi->ls_ack_direct.dst); + + return 0; +} + +void ospf_ls_ack_send(struct ospf_neighbor *nbr, struct ospf_lsa *lsa) +{ + struct ospf_interface *oi = nbr->oi; + + if (listcount(oi->ls_ack_direct.ls_ack) == 0) + oi->ls_ack_direct.dst = nbr->address.u.prefix4; + + listnode_add(oi->ls_ack_direct.ls_ack, ospf_lsa_lock(lsa)); + + thread_add_event(master, ospf_ls_ack_send_event, oi, 0, + &oi->t_ls_ack_direct); } /* Send Link State Acknowledgment delayed. */ -void -ospf_ls_ack_send_delayed (struct ospf_interface *oi) -{ - struct in_addr dst; - - /* Decide destination address. */ - /* RFC2328 Section 13.5 On non-broadcast - networks, delayed Link State Acknowledgment packets must be - unicast separately over each adjacency (i.e., neighbor whose - state is >= Exchange). */ - if (oi->type == OSPF_IFTYPE_NBMA) - { - struct ospf_neighbor *nbr; - struct route_node *rn; - - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange) - while (listcount (oi->ls_ack)) - ospf_ls_ack_send_list (oi, oi->ls_ack, nbr->address.u.prefix4); - return; - } - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - dst.s_addr = oi->vl_data->peer_addr.s_addr; - else if (oi->state == ISM_DR || oi->state == ISM_Backup) - dst.s_addr = htonl (OSPF_ALLSPFROUTERS); - else if (oi->type == OSPF_IFTYPE_POINTOPOINT) - dst.s_addr = htonl (OSPF_ALLSPFROUTERS); - else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) - dst.s_addr = htonl (OSPF_ALLSPFROUTERS); - else - dst.s_addr = htonl (OSPF_ALLDROUTERS); - - while (listcount (oi->ls_ack)) - ospf_ls_ack_send_list (oi, oi->ls_ack, dst); +void ospf_ls_ack_send_delayed(struct ospf_interface *oi) +{ + struct in_addr dst; + + /* Decide destination address. */ + /* RFC2328 Section 13.5 On non-broadcast + networks, delayed Link State Acknowledgment packets must be + unicast separately over each adjacency (i.e., neighbor whose + state is >= Exchange). */ + if (oi->type == OSPF_IFTYPE_NBMA) { + struct ospf_neighbor *nbr; + struct route_node *rn; + + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info) != NULL) + if (nbr != oi->nbr_self + && nbr->state >= NSM_Exchange) + while (listcount(oi->ls_ack)) + ospf_ls_ack_send_list( + oi, oi->ls_ack, + nbr->address.u.prefix4); + return; + } + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + dst.s_addr = oi->vl_data->peer_addr.s_addr; + else if (oi->state == ISM_DR || oi->state == ISM_Backup) + dst.s_addr = htonl(OSPF_ALLSPFROUTERS); + else if (oi->type == OSPF_IFTYPE_POINTOPOINT) + dst.s_addr = htonl(OSPF_ALLSPFROUTERS); + else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) + dst.s_addr = htonl(OSPF_ALLSPFROUTERS); + else + dst.s_addr = htonl(OSPF_ALLDROUTERS); + + while (listcount(oi->ls_ack)) + ospf_ls_ack_send_list(oi, oi->ls_ack, dst); } /* @@ -3978,23 +4066,22 @@ ospf_ls_ack_send_delayed (struct ospf_interface *oi) * can be avoided if the MAC was known apriori. */ #define OSPF_PING_NBR_STR_MAX (8 + 40 + 20) -void -ospf_proactively_arp (struct ospf_neighbor *nbr) -{ - char ping_nbr[OSPF_PING_NBR_STR_MAX]; - char *str_ptr; - int ret; - - if (!nbr || !nbr->oi || !nbr->oi->ifp) - return; - - str_ptr = strcpy (ping_nbr, "ping -c 1 -I "); - str_ptr = strcat (str_ptr, nbr->oi->ifp->name); - str_ptr = strcat (str_ptr, " "); - str_ptr = strcat (str_ptr, inet_ntoa (nbr->address.u.prefix4)); - str_ptr = strcat (str_ptr, " > /dev/null 2>&1 &"); - ret = system (ping_nbr); - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Executed %s %s", ping_nbr, - ((ret == 0) ? "successfully" : "but failed")); +void ospf_proactively_arp(struct ospf_neighbor *nbr) +{ + char ping_nbr[OSPF_PING_NBR_STR_MAX]; + char *str_ptr; + int ret; + + if (!nbr || !nbr->oi || !nbr->oi->ifp) + return; + + str_ptr = strcpy(ping_nbr, "ping -c 1 -I "); + str_ptr = strcat(str_ptr, nbr->oi->ifp->name); + str_ptr = strcat(str_ptr, " "); + str_ptr = strcat(str_ptr, inet_ntoa(nbr->address.u.prefix4)); + str_ptr = strcat(str_ptr, " > /dev/null 2>&1 &"); + ret = system(ping_nbr); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Executed %s %s", ping_nbr, + ((ret == 0) ? "successfully" : "but failed")); } diff --git a/ospfd/ospf_packet.h b/ospfd/ospf_packet.h index ebc5d892d..a3617c7bd 100644 --- a/ospfd/ospf_packet.h +++ b/ospfd/ospf_packet.h @@ -49,80 +49,73 @@ #define MSG_OK 0 #define MSG_NG 1 -struct ospf_packet -{ - struct ospf_packet *next; +struct ospf_packet { + struct ospf_packet *next; - /* Pointer to data stream. */ - struct stream *s; + /* Pointer to data stream. */ + struct stream *s; - /* IP destination address. */ - struct in_addr dst; + /* IP destination address. */ + struct in_addr dst; - /* OSPF packet length. */ - u_int16_t length; + /* OSPF packet length. */ + u_int16_t length; }; /* OSPF packet queue structure. */ -struct ospf_fifo -{ - unsigned long count; +struct ospf_fifo { + unsigned long count; - struct ospf_packet *head; - struct ospf_packet *tail; + struct ospf_packet *head; + struct ospf_packet *tail; }; /* OSPF packet header structure. */ -struct ospf_header -{ - u_char version; /* OSPF Version. */ - u_char type; /* Packet Type. */ - u_int16_t length; /* Packet Length. */ - struct in_addr router_id; /* Router ID. */ - struct in_addr area_id; /* Area ID. */ - u_int16_t checksum; /* Check Sum. */ - u_int16_t auth_type; /* Authentication Type. */ - /* Authentication Data. */ - union - { - /* Simple Authentication. */ - u_char auth_data [OSPF_AUTH_SIMPLE_SIZE]; - /* Cryptographic Authentication. */ - struct - { - u_int16_t zero; /* Should be 0. */ - u_char key_id; /* Key ID. */ - u_char auth_data_len; /* Auth Data Length. */ - u_int32_t crypt_seqnum; /* Cryptographic Sequence Number. */ - } crypt; - } u; +struct ospf_header { + u_char version; /* OSPF Version. */ + u_char type; /* Packet Type. */ + u_int16_t length; /* Packet Length. */ + struct in_addr router_id; /* Router ID. */ + struct in_addr area_id; /* Area ID. */ + u_int16_t checksum; /* Check Sum. */ + u_int16_t auth_type; /* Authentication Type. */ + /* Authentication Data. */ + union { + /* Simple Authentication. */ + u_char auth_data[OSPF_AUTH_SIMPLE_SIZE]; + /* Cryptographic Authentication. */ + struct { + u_int16_t zero; /* Should be 0. */ + u_char key_id; /* Key ID. */ + u_char auth_data_len; /* Auth Data Length. */ + u_int32_t crypt_seqnum; /* Cryptographic Sequence + Number. */ + } crypt; + } u; }; /* OSPF Hello body format. */ -struct ospf_hello -{ - struct in_addr network_mask; - u_int16_t hello_interval; - u_char options; - u_char priority; - u_int32_t dead_interval; - struct in_addr d_router; - struct in_addr bd_router; - struct in_addr neighbors[1]; +struct ospf_hello { + struct in_addr network_mask; + u_int16_t hello_interval; + u_char options; + u_char priority; + u_int32_t dead_interval; + struct in_addr d_router; + struct in_addr bd_router; + struct in_addr neighbors[1]; }; /* OSPF Database Description body format. */ -struct ospf_db_desc -{ - u_int16_t mtu; - u_char options; - u_char flags; - u_int32_t dd_seqnum; +struct ospf_db_desc { + u_int16_t mtu; + u_char options; + u_char flags; + u_int32_t dd_seqnum; }; -struct ospf_ls_update -{ - u_int32_t num_lsas; +struct ospf_ls_update { + u_int32_t num_lsas; }; /* Macros. */ @@ -138,41 +131,41 @@ struct ospf_ls_update #define IS_SET_DD_ALL(X) ((X) & OSPF_DD_FLAG_ALL) /* Prototypes. */ -extern void ospf_output_forward (struct stream *, int); -extern struct ospf_packet *ospf_packet_new (size_t); -extern void ospf_packet_free (struct ospf_packet *); -extern struct ospf_fifo *ospf_fifo_new (void); -extern void ospf_fifo_push (struct ospf_fifo *, struct ospf_packet *); -extern struct ospf_packet *ospf_fifo_pop (struct ospf_fifo *); -extern struct ospf_packet *ospf_fifo_head (struct ospf_fifo *); -extern void ospf_fifo_flush (struct ospf_fifo *); -extern void ospf_fifo_free (struct ospf_fifo *); -extern void ospf_packet_add (struct ospf_interface *, struct ospf_packet *); -extern void ospf_packet_delete (struct ospf_interface *); -extern struct stream *ospf_stream_dup (struct stream *); -extern struct ospf_packet *ospf_packet_dup (struct ospf_packet *); - -extern int ospf_read (struct thread *); -extern void ospf_hello_send (struct ospf_interface *); -extern void ospf_db_desc_send (struct ospf_neighbor *); -extern void ospf_db_desc_resend (struct ospf_neighbor *); -extern void ospf_ls_req_send (struct ospf_neighbor *); -extern void ospf_ls_upd_send_lsa (struct ospf_neighbor *, struct ospf_lsa *, - int); -extern void ospf_ls_upd_send (struct ospf_neighbor *, struct list *, int); -extern void ospf_ls_ack_send (struct ospf_neighbor *, struct ospf_lsa *); -extern void ospf_ls_ack_send_delayed (struct ospf_interface *); -extern void ospf_ls_retransmit (struct ospf_interface *, struct ospf_lsa *); -extern void ospf_ls_req_event (struct ospf_neighbor *); - -extern int ospf_ls_upd_timer (struct thread *); -extern int ospf_ls_ack_timer (struct thread *); -extern int ospf_poll_timer (struct thread *); -extern int ospf_hello_reply_timer (struct thread *); +extern void ospf_output_forward(struct stream *, int); +extern struct ospf_packet *ospf_packet_new(size_t); +extern void ospf_packet_free(struct ospf_packet *); +extern struct ospf_fifo *ospf_fifo_new(void); +extern void ospf_fifo_push(struct ospf_fifo *, struct ospf_packet *); +extern struct ospf_packet *ospf_fifo_pop(struct ospf_fifo *); +extern struct ospf_packet *ospf_fifo_head(struct ospf_fifo *); +extern void ospf_fifo_flush(struct ospf_fifo *); +extern void ospf_fifo_free(struct ospf_fifo *); +extern void ospf_packet_add(struct ospf_interface *, struct ospf_packet *); +extern void ospf_packet_delete(struct ospf_interface *); +extern struct stream *ospf_stream_dup(struct stream *); +extern struct ospf_packet *ospf_packet_dup(struct ospf_packet *); + +extern int ospf_read(struct thread *); +extern void ospf_hello_send(struct ospf_interface *); +extern void ospf_db_desc_send(struct ospf_neighbor *); +extern void ospf_db_desc_resend(struct ospf_neighbor *); +extern void ospf_ls_req_send(struct ospf_neighbor *); +extern void ospf_ls_upd_send_lsa(struct ospf_neighbor *, struct ospf_lsa *, + int); +extern void ospf_ls_upd_send(struct ospf_neighbor *, struct list *, int); +extern void ospf_ls_ack_send(struct ospf_neighbor *, struct ospf_lsa *); +extern void ospf_ls_ack_send_delayed(struct ospf_interface *); +extern void ospf_ls_retransmit(struct ospf_interface *, struct ospf_lsa *); +extern void ospf_ls_req_event(struct ospf_neighbor *); + +extern int ospf_ls_upd_timer(struct thread *); +extern int ospf_ls_ack_timer(struct thread *); +extern int ospf_poll_timer(struct thread *); +extern int ospf_hello_reply_timer(struct thread *); extern const struct message ospf_packet_type_str[]; extern const size_t ospf_packet_type_str_max; -extern void ospf_proactively_arp (struct ospf_neighbor *); +extern void ospf_proactively_arp(struct ospf_neighbor *); #endif /* _ZEBRA_OSPF_PACKET_H */ diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c index 0f1ef35e4..26d2ed7d1 100644 --- a/ospfd/ospf_ri.c +++ b/ospfd/ospf_ri.c @@ -38,7 +38,7 @@ #include "log.h" #include "thread.h" #include "hash.h" -#include "sockunion.h" /* for inet_aton() */ +#include "sockunion.h" /* for inet_aton() */ #include "ospfd/ospfd.h" #include "ospfd/ospf_interface.h" @@ -58,41 +58,39 @@ #include "ospfd/ospf_ri.h" #include "ospfd/ospf_te.h" -struct ospf_pce_info -{ +struct ospf_pce_info { - /* Store Router Information PCE TLV and SubTLV in network byte order. */ - struct ri_tlv_pce pce_header; - struct ri_pce_subtlv_address pce_address; - struct ri_pce_subtlv_path_scope pce_scope; - struct list *pce_domain; - struct list *pce_neighbor; - struct ri_pce_subtlv_cap_flag pce_cap_flag; + /* Store Router Information PCE TLV and SubTLV in network byte order. */ + struct ri_tlv_pce pce_header; + struct ri_pce_subtlv_address pce_address; + struct ri_pce_subtlv_path_scope pce_scope; + struct list *pce_domain; + struct list *pce_neighbor; + struct ri_pce_subtlv_cap_flag pce_cap_flag; }; /* Following structure are internal use only. */ -struct ospf_router_info -{ - status_t status; +struct ospf_router_info { + status_t status; - u_int8_t registered; - u_int8_t scope; + u_int8_t registered; + u_int8_t scope; - /* Flags to manage this router information. */ +/* Flags to manage this router information. */ #define RIFLG_LOOKUP_DONE 0x1 #define RIFLG_LSA_ENGAGED 0x2 #define RIFLG_LSA_FORCED_REFRESH 0x4 - u_int32_t flags; + u_int32_t flags; - /* area pointer if flooding is Type 10 Null if flooding is AS scope */ - struct ospf_area *area; - struct in_addr area_id; + /* area pointer if flooding is Type 10 Null if flooding is AS scope */ + struct ospf_area *area; + struct in_addr area_id; - /* Store Router Information Capabilities LSA */ - struct ri_tlv_router_cap router_cap; + /* Store Router Information Capabilities LSA */ + struct ri_tlv_router_cap router_cap; - /* Store PCE capability LSA */ - struct ospf_pce_info pce_info; + /* Store PCE capability LSA */ + struct ospf_pce_info pce_info; }; /* @@ -102,1058 +100,1005 @@ struct ospf_router_info static struct ospf_router_info OspfRI; /*------------------------------------------------------------------------------* - * Followings are initialize/terminate functions for Router Information handling. + * Followings are initialize/terminate functions for Router Information + *handling. *------------------------------------------------------------------------------*/ -static void ospf_router_info_ism_change (struct ospf_interface *oi, - int old_status); -static void ospf_router_info_nsm_change (struct ospf_neighbor *nbr, - int old_status); -static void ospf_router_info_config_write_router (struct vty *vty); -static void ospf_router_info_show_info (struct vty *vty, - struct ospf_lsa *lsa); -static int ospf_router_info_lsa_originate (void *arg); -static struct ospf_lsa *ospf_router_info_lsa_refresh (struct ospf_lsa *lsa); -static void ospf_router_info_lsa_schedule (opcode_t opcode); -static void ospf_router_info_register_vty (void); -static void del_pce_info (void *val); - -int -ospf_router_info_init (void) +static void ospf_router_info_ism_change(struct ospf_interface *oi, + int old_status); +static void ospf_router_info_nsm_change(struct ospf_neighbor *nbr, + int old_status); +static void ospf_router_info_config_write_router(struct vty *vty); +static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa); +static int ospf_router_info_lsa_originate(void *arg); +static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa); +static void ospf_router_info_lsa_schedule(opcode_t opcode); +static void ospf_router_info_register_vty(void); +static void del_pce_info(void *val); + +int ospf_router_info_init(void) { - memset (&OspfRI, 0, sizeof (struct ospf_router_info)); - OspfRI.status = disabled; - OspfRI.registered = 0; - OspfRI.scope = OSPF_OPAQUE_AS_LSA; - OspfRI.flags = 0; + memset(&OspfRI, 0, sizeof(struct ospf_router_info)); + OspfRI.status = disabled; + OspfRI.registered = 0; + OspfRI.scope = OSPF_OPAQUE_AS_LSA; + OspfRI.flags = 0; - /* Initialize pce domain and neighbor list */ - OspfRI.pce_info.pce_domain = list_new (); - OspfRI.pce_info.pce_domain->del = del_pce_info; - OspfRI.pce_info.pce_neighbor = list_new (); - OspfRI.pce_info.pce_neighbor->del = del_pce_info; + /* Initialize pce domain and neighbor list */ + OspfRI.pce_info.pce_domain = list_new(); + OspfRI.pce_info.pce_domain->del = del_pce_info; + OspfRI.pce_info.pce_neighbor = list_new(); + OspfRI.pce_info.pce_neighbor->del = del_pce_info; - ospf_router_info_register_vty (); + ospf_router_info_register_vty(); - return 0; + return 0; } -static int -ospf_router_info_register (u_int8_t scope) +static int ospf_router_info_register(u_int8_t scope) { - int rc = 0; - - if (OspfRI.registered) - return 0; - - zlog_info ("Register Router Information with scope %s(%d)", - scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", scope); - rc = ospf_register_opaque_functab (scope, - OPAQUE_TYPE_ROUTER_INFORMATION_LSA, - NULL, /* new interface */ - NULL, /* del interface */ - ospf_router_info_ism_change, - ospf_router_info_nsm_change, - ospf_router_info_config_write_router, - NULL, /* Config. write interface */ - NULL, /* Config. write debug */ - ospf_router_info_show_info, - ospf_router_info_lsa_originate, - ospf_router_info_lsa_refresh, - NULL, /* new_lsa_hook */ - NULL); /* del_lsa_hook */ - - if (rc != 0) - { - zlog_warn ("ospf_router_info_init: Failed to register functions"); - return rc; - } - - OspfRI.registered = 1; - OspfRI.scope = scope; - return 0; + int rc = 0; + + if (OspfRI.registered) + return 0; + + zlog_info("Register Router Information with scope %s(%d)", + scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", scope); + rc = ospf_register_opaque_functab( + scope, OPAQUE_TYPE_ROUTER_INFORMATION_LSA, + NULL, /* new interface */ + NULL, /* del interface */ + ospf_router_info_ism_change, ospf_router_info_nsm_change, + ospf_router_info_config_write_router, + NULL, /* Config. write interface */ + NULL, /* Config. write debug */ + ospf_router_info_show_info, ospf_router_info_lsa_originate, + ospf_router_info_lsa_refresh, NULL, /* new_lsa_hook */ + NULL); /* del_lsa_hook */ + + if (rc != 0) { + zlog_warn( + "ospf_router_info_init: Failed to register functions"); + return rc; + } + + OspfRI.registered = 1; + OspfRI.scope = scope; + return 0; } -static int -ospf_router_info_unregister () +static int ospf_router_info_unregister() { - if ((OspfRI.scope != OSPF_OPAQUE_AS_LSA) - && (OspfRI.scope != OSPF_OPAQUE_AREA_LSA)) - { - zlog_warn ("Unable to unregister Router Info functions: Wrong scope!"); - return -1; - } - - ospf_delete_opaque_functab (OspfRI.scope, - OPAQUE_TYPE_ROUTER_INFORMATION_LSA); + if ((OspfRI.scope != OSPF_OPAQUE_AS_LSA) + && (OspfRI.scope != OSPF_OPAQUE_AREA_LSA)) { + zlog_warn( + "Unable to unregister Router Info functions: Wrong scope!"); + return -1; + } - OspfRI.registered = 0; - return 0; + ospf_delete_opaque_functab(OspfRI.scope, + OPAQUE_TYPE_ROUTER_INFORMATION_LSA); + OspfRI.registered = 0; + return 0; } -void -ospf_router_info_term (void) +void ospf_router_info_term(void) { - list_delete (OspfRI.pce_info.pce_domain); - list_delete (OspfRI.pce_info.pce_neighbor); + list_delete(OspfRI.pce_info.pce_domain); + list_delete(OspfRI.pce_info.pce_neighbor); - OspfRI.pce_info.pce_domain = NULL; - OspfRI.pce_info.pce_neighbor = NULL; - OspfRI.status = disabled; + OspfRI.pce_info.pce_domain = NULL; + OspfRI.pce_info.pce_neighbor = NULL; + OspfRI.status = disabled; - ospf_router_info_unregister (); + ospf_router_info_unregister(); - return; + return; } -static void -del_pce_info (void *val) +static void del_pce_info(void *val) { - XFREE (MTYPE_OSPF_PCE_PARAMS, val); - return; + XFREE(MTYPE_OSPF_PCE_PARAMS, val); + return; } /*------------------------------------------------------------------------* - * Followings are control functions for ROUTER INFORMATION parameters management. + * Followings are control functions for ROUTER INFORMATION parameters + *management. *------------------------------------------------------------------------*/ -static void -set_router_info_capabilities (struct ri_tlv_router_cap *ric, u_int32_t cap) +static void set_router_info_capabilities(struct ri_tlv_router_cap *ric, + u_int32_t cap) { - ric->header.type = htons (RI_TLV_CAPABILITIES); - ric->header.length = htons (RI_TLV_LENGTH); - ric->value = htonl (cap); - return; + ric->header.type = htons(RI_TLV_CAPABILITIES); + ric->header.length = htons(RI_TLV_LENGTH); + ric->value = htonl(cap); + return; } -static int -set_pce_header (struct ospf_pce_info *pce) +static int set_pce_header(struct ospf_pce_info *pce) { - u_int16_t length = 0; - struct listnode *node; - struct ri_pce_subtlv_domain *domain; - struct ri_pce_subtlv_neighbor *neighbor; - - /* PCE Address */ - if (ntohs (pce->pce_address.header.type) != 0) - length += RI_TLV_SIZE (&pce->pce_address.header); - - /* PCE Path Scope */ - if (ntohs (pce->pce_scope.header.type) != 0) - length += RI_TLV_SIZE (&pce->pce_scope.header); - - /* PCE Domain */ - for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain)) - { - if (ntohs (domain->header.type) != 0) - length += RI_TLV_SIZE (&domain->header); - } - - /* PCE Neighbor */ - for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor)) - { - if (ntohs (neighbor->header.type) != 0) - length += RI_TLV_SIZE (&neighbor->header); - } - - /* PCE Capabilities */ - if (ntohs (pce->pce_cap_flag.header.type) != 0) - length += RI_TLV_SIZE (&pce->pce_cap_flag.header); - - if (length != 0) - { - pce->pce_header.header.type = htons (RI_TLV_PCE); - pce->pce_header.header.length = htons (length); - } - else - { - pce->pce_header.header.type = 0; - pce->pce_header.header.length = 0; - } - - return length; + u_int16_t length = 0; + struct listnode *node; + struct ri_pce_subtlv_domain *domain; + struct ri_pce_subtlv_neighbor *neighbor; + + /* PCE Address */ + if (ntohs(pce->pce_address.header.type) != 0) + length += RI_TLV_SIZE(&pce->pce_address.header); + + /* PCE Path Scope */ + if (ntohs(pce->pce_scope.header.type) != 0) + length += RI_TLV_SIZE(&pce->pce_scope.header); + + /* PCE Domain */ + for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) { + if (ntohs(domain->header.type) != 0) + length += RI_TLV_SIZE(&domain->header); + } + + /* PCE Neighbor */ + for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) { + if (ntohs(neighbor->header.type) != 0) + length += RI_TLV_SIZE(&neighbor->header); + } + + /* PCE Capabilities */ + if (ntohs(pce->pce_cap_flag.header.type) != 0) + length += RI_TLV_SIZE(&pce->pce_cap_flag.header); + + if (length != 0) { + pce->pce_header.header.type = htons(RI_TLV_PCE); + pce->pce_header.header.length = htons(length); + } else { + pce->pce_header.header.type = 0; + pce->pce_header.header.length = 0; + } + + return length; } -static void -set_pce_address (struct in_addr ipv4, struct ospf_pce_info *pce) +static void set_pce_address(struct in_addr ipv4, struct ospf_pce_info *pce) { - /* Enable PCE Info */ - pce->pce_header.header.type = htons (RI_TLV_PCE); - /* Set PCE Address */ - pce->pce_address.header.type = htons (RI_PCE_SUBTLV_ADDRESS); - pce->pce_address.header.length = htons (PCE_ADDRESS_LENGTH_IPV4); - pce->pce_address.address.type = htons (PCE_ADDRESS_TYPE_IPV4); - pce->pce_address.address.value = ipv4; + /* Enable PCE Info */ + pce->pce_header.header.type = htons(RI_TLV_PCE); + /* Set PCE Address */ + pce->pce_address.header.type = htons(RI_PCE_SUBTLV_ADDRESS); + pce->pce_address.header.length = htons(PCE_ADDRESS_LENGTH_IPV4); + pce->pce_address.address.type = htons(PCE_ADDRESS_TYPE_IPV4); + pce->pce_address.address.value = ipv4; - return; + return; } -static void -set_pce_path_scope (u_int32_t scope, struct ospf_pce_info *pce) +static void set_pce_path_scope(u_int32_t scope, struct ospf_pce_info *pce) { - /* Enable PCE Info */ - pce->pce_header.header.type = htons (RI_TLV_PCE); - /* Set PCE Scope */ - pce->pce_scope.header.type = htons (RI_PCE_SUBTLV_PATH_SCOPE); - pce->pce_scope.header.length = htons (RI_TLV_LENGTH); - pce->pce_scope.value = htonl (scope); + /* Enable PCE Info */ + pce->pce_header.header.type = htons(RI_TLV_PCE); + /* Set PCE Scope */ + pce->pce_scope.header.type = htons(RI_PCE_SUBTLV_PATH_SCOPE); + pce->pce_scope.header.length = htons(RI_TLV_LENGTH); + pce->pce_scope.value = htonl(scope); - return; + return; } -static void -set_pce_domain (u_int16_t type, u_int32_t domain, struct ospf_pce_info *pce) +static void set_pce_domain(u_int16_t type, u_int32_t domain, + struct ospf_pce_info *pce) { - struct ri_pce_subtlv_domain *new; + struct ri_pce_subtlv_domain *new; - /* Enable PCE Info */ - pce->pce_header.header.type = htons (RI_TLV_PCE); + /* Enable PCE Info */ + pce->pce_header.header.type = htons(RI_TLV_PCE); - /* Create new domain info */ - new = - XCALLOC (MTYPE_OSPF_PCE_PARAMS, - sizeof (struct ri_pce_subtlv_domain)); + /* Create new domain info */ + new = XCALLOC(MTYPE_OSPF_PCE_PARAMS, + sizeof(struct ri_pce_subtlv_domain)); - new->header.type = htons (RI_PCE_SUBTLV_DOMAIN); - new->header.length = htons (PCE_ADDRESS_LENGTH_IPV4); - new->type = htons (type); - new->value = htonl (domain); + new->header.type = htons(RI_PCE_SUBTLV_DOMAIN); + new->header.length = htons(PCE_ADDRESS_LENGTH_IPV4); + new->type = htons(type); + new->value = htonl(domain); - /* Add new domain to the list */ - listnode_add (pce->pce_domain, new); + /* Add new domain to the list */ + listnode_add(pce->pce_domain, new); - return; + return; } -static void -unset_pce_domain (u_int16_t type, u_int32_t domain, struct ospf_pce_info *pce) +static void unset_pce_domain(u_int16_t type, u_int32_t domain, + struct ospf_pce_info *pce) { - struct listnode *node; - struct ri_pce_subtlv_domain *old = NULL; - int found = 0; - - /* Search the corresponding node */ - for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, old)) - { - if ((old->type == htons (type)) && (old->value == htonl (domain))) - { - found = 1; - break; - } - } - - /* if found remove it */ - if (found) - { - listnode_delete (pce->pce_domain, old); - - /* Avoid misjudgement in the next lookup. */ - if (listcount (pce->pce_domain) == 0) - pce->pce_domain->head = pce->pce_domain->tail = NULL; - - /* Finally free the old domain */ - XFREE (MTYPE_OSPF_PCE_PARAMS, old); - } + struct listnode *node; + struct ri_pce_subtlv_domain *old = NULL; + int found = 0; + + /* Search the corresponding node */ + for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, old)) { + if ((old->type == htons(type)) + && (old->value == htonl(domain))) { + found = 1; + break; + } + } + + /* if found remove it */ + if (found) { + listnode_delete(pce->pce_domain, old); + + /* Avoid misjudgement in the next lookup. */ + if (listcount(pce->pce_domain) == 0) + pce->pce_domain->head = pce->pce_domain->tail = NULL; + + /* Finally free the old domain */ + XFREE(MTYPE_OSPF_PCE_PARAMS, old); + } } -static void -set_pce_neighbor (u_int16_t type, u_int32_t domain, struct ospf_pce_info *pce) +static void set_pce_neighbor(u_int16_t type, u_int32_t domain, + struct ospf_pce_info *pce) { - struct ri_pce_subtlv_neighbor *new; + struct ri_pce_subtlv_neighbor *new; - /* Enable PCE Info */ - pce->pce_header.header.type = htons (RI_TLV_PCE); + /* Enable PCE Info */ + pce->pce_header.header.type = htons(RI_TLV_PCE); - /* Create new neighbor info */ - new = - XCALLOC (MTYPE_OSPF_PCE_PARAMS, - sizeof (struct ri_pce_subtlv_neighbor)); + /* Create new neighbor info */ + new = XCALLOC(MTYPE_OSPF_PCE_PARAMS, + sizeof(struct ri_pce_subtlv_neighbor)); - new->header.type = htons (RI_PCE_SUBTLV_NEIGHBOR); - new->header.length = htons (PCE_ADDRESS_LENGTH_IPV4); - new->type = htons (type); - new->value = htonl (domain); + new->header.type = htons(RI_PCE_SUBTLV_NEIGHBOR); + new->header.length = htons(PCE_ADDRESS_LENGTH_IPV4); + new->type = htons(type); + new->value = htonl(domain); - /* Add new domain to the list */ - listnode_add (pce->pce_neighbor, new); + /* Add new domain to the list */ + listnode_add(pce->pce_neighbor, new); - return; + return; } -static void -unset_pce_neighbor (u_int16_t type, u_int32_t domain, - struct ospf_pce_info *pce) +static void unset_pce_neighbor(u_int16_t type, u_int32_t domain, + struct ospf_pce_info *pce) { - struct listnode *node; - struct ri_pce_subtlv_neighbor *old = NULL; - int found = 0; - - /* Search the corresponding node */ - for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, old)) - { - if ((old->type == htons (type)) && (old->value == htonl (domain))) - { - found = 1; - break; - } - } - - /* if found remove it */ - if (found) - { - listnode_delete (pce->pce_neighbor, old); - - /* Avoid misjudgement in the next lookup. */ - if (listcount (pce->pce_neighbor) == 0) - pce->pce_neighbor->head = pce->pce_neighbor->tail = NULL; - - /* Finally free the old domain */ - XFREE (MTYPE_OSPF_PCE_PARAMS, old); - } + struct listnode *node; + struct ri_pce_subtlv_neighbor *old = NULL; + int found = 0; + + /* Search the corresponding node */ + for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, old)) { + if ((old->type == htons(type)) + && (old->value == htonl(domain))) { + found = 1; + break; + } + } + + /* if found remove it */ + if (found) { + listnode_delete(pce->pce_neighbor, old); + + /* Avoid misjudgement in the next lookup. */ + if (listcount(pce->pce_neighbor) == 0) + pce->pce_neighbor->head = pce->pce_neighbor->tail = + NULL; + + /* Finally free the old domain */ + XFREE(MTYPE_OSPF_PCE_PARAMS, old); + } } -static void -set_pce_cap_flag (u_int32_t cap, struct ospf_pce_info *pce) +static void set_pce_cap_flag(u_int32_t cap, struct ospf_pce_info *pce) { - /* Enable PCE Info */ - pce->pce_header.header.type = htons (RI_TLV_PCE); - /* Set PCE Capabilities flag */ - pce->pce_cap_flag.header.type = htons (RI_PCE_SUBTLV_CAP_FLAG); - pce->pce_cap_flag.header.length = htons (RI_TLV_LENGTH); - pce->pce_cap_flag.value = htonl (cap); + /* Enable PCE Info */ + pce->pce_header.header.type = htons(RI_TLV_PCE); + /* Set PCE Capabilities flag */ + pce->pce_cap_flag.header.type = htons(RI_PCE_SUBTLV_CAP_FLAG); + pce->pce_cap_flag.header.length = htons(RI_TLV_LENGTH); + pce->pce_cap_flag.value = htonl(cap); - return; + return; } -static void -unset_param (struct ri_tlv_header *tlv) +static void unset_param(struct ri_tlv_header *tlv) { - tlv->type = 0; - /* Fill the Value to 0 */ - memset ((tlv + RI_TLV_HDR_SIZE), 0, RI_TLV_BODY_SIZE (tlv)); - tlv->length = 0; + tlv->type = 0; + /* Fill the Value to 0 */ + memset((tlv + RI_TLV_HDR_SIZE), 0, RI_TLV_BODY_SIZE(tlv)); + tlv->length = 0; - return; + return; } -static void -initialize_params (struct ospf_router_info *ori) +static void initialize_params(struct ospf_router_info *ori) { - u_int32_t cap; - struct ospf *top; - - /* - * Initialize default Router Information Capabilities. - */ - cap = 0; - cap = cap | RI_TE_SUPPORT; - - set_router_info_capabilities (&ori->router_cap, cap); - - /* If Area address is not null and exist, retrieve corresponding structure */ - top = ospf_lookup (); - zlog_info ("RI-> Initialize Router Info for %s scope within area %s", - OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", - inet_ntoa (OspfRI.area_id)); - - /* Try to get the Area context at this step. Do it latter if not available */ - if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL)) - OspfRI.area = ospf_area_lookup_by_area_id (top, OspfRI.area_id); - - /* - * Initialize default PCE Information values - */ - /* PCE address == OSPF Router ID */ - set_pce_address (top->router_id, &ori->pce_info); - - /* PCE scope */ - cap = 7; /* Set L, R and Rd bits to one = intra & inter-area path computation */ - set_pce_path_scope (cap, &ori->pce_info); - - /* PCE Capabilities */ - cap = - PCE_CAP_BIDIRECTIONAL | PCE_CAP_DIVERSE_PATH | PCE_CAP_OBJECTIVES | - PCE_CAP_ADDITIVE | PCE_CAP_MULTIPLE_REQ; - set_pce_cap_flag (cap, &ori->pce_info); - - /* Finally compute PCE header */ - set_pce_header (&ori->pce_info); - - return; + u_int32_t cap; + struct ospf *top; + + /* + * Initialize default Router Information Capabilities. + */ + cap = 0; + cap = cap | RI_TE_SUPPORT; + + set_router_info_capabilities(&ori->router_cap, cap); + + /* If Area address is not null and exist, retrieve corresponding + * structure */ + top = ospf_lookup(); + zlog_info("RI-> Initialize Router Info for %s scope within area %s", + OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", + inet_ntoa(OspfRI.area_id)); + + /* Try to get the Area context at this step. Do it latter if not + * available */ + if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL)) + OspfRI.area = ospf_area_lookup_by_area_id(top, OspfRI.area_id); + + /* + * Initialize default PCE Information values + */ + /* PCE address == OSPF Router ID */ + set_pce_address(top->router_id, &ori->pce_info); + + /* PCE scope */ + cap = 7; /* Set L, R and Rd bits to one = intra & inter-area path + computation */ + set_pce_path_scope(cap, &ori->pce_info); + + /* PCE Capabilities */ + cap = PCE_CAP_BIDIRECTIONAL | PCE_CAP_DIVERSE_PATH | PCE_CAP_OBJECTIVES + | PCE_CAP_ADDITIVE | PCE_CAP_MULTIPLE_REQ; + set_pce_cap_flag(cap, &ori->pce_info); + + /* Finally compute PCE header */ + set_pce_header(&ori->pce_info); + + return; } -static int -is_mandated_params_set (struct ospf_router_info ori) +static int is_mandated_params_set(struct ospf_router_info ori) { - int rc = 0; + int rc = 0; - if (ntohs (ori.router_cap.header.type) == 0) - goto out; + if (ntohs(ori.router_cap.header.type) == 0) + goto out; - if ((ntohs (ori.pce_info.pce_header.header.type) == RI_TLV_PCE) - && (ntohs (ori.pce_info.pce_address.header.type) == 0) - && (ntohs (ori.pce_info.pce_cap_flag.header.type) == 0)) - goto out; + if ((ntohs(ori.pce_info.pce_header.header.type) == RI_TLV_PCE) + && (ntohs(ori.pce_info.pce_address.header.type) == 0) + && (ntohs(ori.pce_info.pce_cap_flag.header.type) == 0)) + goto out; - rc = 1; + rc = 1; out: - return rc; + return rc; } /*------------------------------------------------------------------------* * Followings are callback functions against generic Opaque-LSAs handling. *------------------------------------------------------------------------*/ -static void -ospf_router_info_ism_change (struct ospf_interface *oi, int old_state) +static void ospf_router_info_ism_change(struct ospf_interface *oi, + int old_state) { - /* So far, nothing to do here. */ - return; - + /* So far, nothing to do here. */ + return; } -static void -ospf_router_info_nsm_change (struct ospf_neighbor *nbr, int old_state) +static void ospf_router_info_nsm_change(struct ospf_neighbor *nbr, + int old_state) { - /* So far, nothing to do here. */ - return; + /* So far, nothing to do here. */ + return; } /*------------------------------------------------------------------------* * Followings are OSPF protocol processing functions for ROUTER INFORMATION *------------------------------------------------------------------------*/ -static void -build_tlv_header (struct stream *s, struct ri_tlv_header *tlvh) +static void build_tlv_header(struct stream *s, struct ri_tlv_header *tlvh) { - stream_put (s, tlvh, sizeof (struct ri_tlv_header)); - return; + stream_put(s, tlvh, sizeof(struct ri_tlv_header)); + return; } -static void -build_tlv (struct stream *s, struct ri_tlv_header *tlvh) +static void build_tlv(struct stream *s, struct ri_tlv_header *tlvh) { - if (ntohs (tlvh->type) != 0) - { - build_tlv_header (s, tlvh); - stream_put (s, tlvh + 1, RI_TLV_BODY_SIZE (tlvh)); - } - return; + if (ntohs(tlvh->type) != 0) { + build_tlv_header(s, tlvh); + stream_put(s, tlvh + 1, RI_TLV_BODY_SIZE(tlvh)); + } + return; } -static void -ospf_router_info_lsa_body_set (struct stream *s) +static void ospf_router_info_lsa_body_set(struct stream *s) { - struct listnode *node; - struct ri_pce_subtlv_domain *domain; - struct ri_pce_subtlv_neighbor *neighbor; + struct listnode *node; + struct ri_pce_subtlv_domain *domain; + struct ri_pce_subtlv_neighbor *neighbor; - /* Build Router Information TLV */ - build_tlv (s, &OspfRI.router_cap.header); + /* Build Router Information TLV */ + build_tlv(s, &OspfRI.router_cap.header); - /* Add RI PCE TLV if it is set */ - /* Compute PCE Info header first */ - if ((set_pce_header (&OspfRI.pce_info)) != 0) - { + /* Add RI PCE TLV if it is set */ + /* Compute PCE Info header first */ + if ((set_pce_header(&OspfRI.pce_info)) != 0) { - /* Build PCE TLV */ - build_tlv_header (s, &OspfRI.pce_info.pce_header.header); + /* Build PCE TLV */ + build_tlv_header(s, &OspfRI.pce_info.pce_header.header); - /* Build PCE address sub-tlv */ - build_tlv (s, &OspfRI.pce_info.pce_address.header); + /* Build PCE address sub-tlv */ + build_tlv(s, &OspfRI.pce_info.pce_address.header); - /* Build PCE path scope sub-tlv */ - build_tlv (s, &OspfRI.pce_info.pce_scope.header); + /* Build PCE path scope sub-tlv */ + build_tlv(s, &OspfRI.pce_info.pce_scope.header); - /* Build PCE domain sub-tlv */ - for (ALL_LIST_ELEMENTS_RO (OspfRI.pce_info.pce_domain, node, domain)) - build_tlv (s, &domain->header); + /* Build PCE domain sub-tlv */ + for (ALL_LIST_ELEMENTS_RO(OspfRI.pce_info.pce_domain, node, + domain)) + build_tlv(s, &domain->header); - /* Build PCE neighbor sub-tlv */ - for (ALL_LIST_ELEMENTS_RO - (OspfRI.pce_info.pce_neighbor, node, neighbor)) - build_tlv (s, &neighbor->header); + /* Build PCE neighbor sub-tlv */ + for (ALL_LIST_ELEMENTS_RO(OspfRI.pce_info.pce_neighbor, node, + neighbor)) + build_tlv(s, &neighbor->header); - /* Build PCE cap flag sub-tlv */ - build_tlv (s, &OspfRI.pce_info.pce_cap_flag.header); - } + /* Build PCE cap flag sub-tlv */ + build_tlv(s, &OspfRI.pce_info.pce_cap_flag.header); + } - return; + return; } /* Create new opaque-LSA. */ -static struct ospf_lsa * -ospf_router_info_lsa_new () +static struct ospf_lsa *ospf_router_info_lsa_new() { - struct ospf *top; - struct stream *s; - struct lsa_header *lsah; - struct ospf_lsa *new = NULL; - u_char options, lsa_type; - struct in_addr lsa_id; - u_int32_t tmp; - u_int16_t length; - - /* Create a stream for LSA. */ - if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL) - { - zlog_warn ("ospf_router_info_lsa_new: stream_new() ?"); - goto out; - } - lsah = (struct lsa_header *) STREAM_DATA (s); - - options = OSPF_OPTION_E; /* Enable AS external as we flood RI with Opaque Type 11 */ - options |= OSPF_OPTION_O; /* Don't forget this :-) */ - - lsa_type = OspfRI.scope; - /* LSA ID == 0 for Router Information see RFC 4970 */ - tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0); - lsa_id.s_addr = htonl (tmp); - - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug - ("LSA[Type%d:%s]: Create an Opaque-LSA/ROUTER INFORMATION instance", - lsa_type, inet_ntoa (lsa_id)); - - top = ospf_lookup (); - - /* Set opaque-LSA header fields. */ - lsa_header_set (s, options, lsa_type, lsa_id, top->router_id); - - /* Set opaque-LSA body fields. */ - ospf_router_info_lsa_body_set (s); - - /* Set length. */ - length = stream_get_endp (s); - lsah->length = htons (length); - - /* Now, create an OSPF LSA instance. */ - if ((new = ospf_lsa_new ()) == NULL) - { - zlog_warn ("ospf_router_info_lsa_new: ospf_lsa_new() ?"); - stream_free (s); - goto out; - } - if ((new->data = ospf_lsa_data_new (length)) == NULL) - { - zlog_warn ("ospf_router_info_lsa_new: ospf_lsa_data_new() ?"); - ospf_lsa_unlock (&new); - new = NULL; - stream_free (s); - goto out; - } - - new->area = OspfRI.area; /* Area must be null if the Opaque type is AS scope, fulfill otherwise */ - - SET_FLAG (new->flags, OSPF_LSA_SELF); - memcpy (new->data, lsah, length); - stream_free (s); - -out:return new; + struct ospf *top; + struct stream *s; + struct lsa_header *lsah; + struct ospf_lsa *new = NULL; + u_char options, lsa_type; + struct in_addr lsa_id; + u_int32_t tmp; + u_int16_t length; + + /* Create a stream for LSA. */ + if ((s = stream_new(OSPF_MAX_LSA_SIZE)) == NULL) { + zlog_warn("ospf_router_info_lsa_new: stream_new() ?"); + goto out; + } + lsah = (struct lsa_header *)STREAM_DATA(s); + + options = OSPF_OPTION_E; /* Enable AS external as we flood RI with + Opaque Type 11 */ + options |= OSPF_OPTION_O; /* Don't forget this :-) */ + + lsa_type = OspfRI.scope; + /* LSA ID == 0 for Router Information see RFC 4970 */ + tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0); + lsa_id.s_addr = htonl(tmp); + + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type%d:%s]: Create an Opaque-LSA/ROUTER INFORMATION instance", + lsa_type, inet_ntoa(lsa_id)); + + top = ospf_lookup(); + + /* Set opaque-LSA header fields. */ + lsa_header_set(s, options, lsa_type, lsa_id, top->router_id); + + /* Set opaque-LSA body fields. */ + ospf_router_info_lsa_body_set(s); + + /* Set length. */ + length = stream_get_endp(s); + lsah->length = htons(length); + + /* Now, create an OSPF LSA instance. */ + if ((new = ospf_lsa_new()) == NULL) { + zlog_warn("ospf_router_info_lsa_new: ospf_lsa_new() ?"); + stream_free(s); + goto out; + } + if ((new->data = ospf_lsa_data_new(length)) == NULL) { + zlog_warn("ospf_router_info_lsa_new: ospf_lsa_data_new() ?"); + ospf_lsa_unlock(&new); + new = NULL; + stream_free(s); + goto out; + } + + new->area = OspfRI.area; /* Area must be null if the Opaque type is AS + scope, fulfill otherwise */ + + SET_FLAG(new->flags, OSPF_LSA_SELF); + memcpy(new->data, lsah, length); + stream_free(s); + +out: + return new; } -static int -ospf_router_info_lsa_originate1 (void *arg) +static int ospf_router_info_lsa_originate1(void *arg) { - struct ospf_lsa *new; - struct ospf *top; - struct ospf_area *area; - int rc = -1; - - /* First check if the area is known if flooding scope is Area */ - if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) - { - area = (struct ospf_area *) arg; - if (area->area_id.s_addr != OspfRI.area_id.s_addr) - { - zlog_debug - ("RI -> This is not the Router Information Area. Stop processing"); - goto out; - } - OspfRI.area = area; - } - - /* Create new Opaque-LSA/ROUTER INFORMATION instance. */ - if ((new = ospf_router_info_lsa_new ()) == NULL) - { - zlog_warn - ("ospf_router_info_lsa_originate1: ospf_router_info_lsa_new() ?"); - goto out; - } - - /* Get ospf info */ - top = ospf_lookup (); - - /* Install this LSA into LSDB. */ - if (ospf_lsa_install (top, NULL /*oi */ , new) == NULL) - { - zlog_warn ("ospf_router_info_lsa_originate1: ospf_lsa_install() ?"); - ospf_lsa_unlock (&new); - goto out; - } - - /* Now this Router Info parameter entry has associated LSA. */ - SET_FLAG (OspfRI.flags, RIFLG_LSA_ENGAGED); - - /* Update new LSA origination count. */ - top->lsa_originate_count++; - - /* Flood new LSA through AS. */ - if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) - ospf_flood_through_as (top, NULL /*nbr */ , new); - else - ospf_flood_through_area (OspfRI.area, NULL /*nbr */ , new); - - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - { - zlog_debug ("LSA[Type%d:%s]: Originate Opaque-LSA/ROUTER INFORMATION", - new->data->type, inet_ntoa (new->data->id)); - ospf_lsa_header_dump (new->data); - } - - rc = 0; -out:return rc; + struct ospf_lsa *new; + struct ospf *top; + struct ospf_area *area; + int rc = -1; + + /* First check if the area is known if flooding scope is Area */ + if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) { + area = (struct ospf_area *)arg; + if (area->area_id.s_addr != OspfRI.area_id.s_addr) { + zlog_debug( + "RI -> This is not the Router Information Area. Stop processing"); + goto out; + } + OspfRI.area = area; + } + + /* Create new Opaque-LSA/ROUTER INFORMATION instance. */ + if ((new = ospf_router_info_lsa_new()) == NULL) { + zlog_warn( + "ospf_router_info_lsa_originate1: ospf_router_info_lsa_new() ?"); + goto out; + } + + /* Get ospf info */ + top = ospf_lookup(); + + /* Install this LSA into LSDB. */ + if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) { + zlog_warn( + "ospf_router_info_lsa_originate1: ospf_lsa_install() ?"); + ospf_lsa_unlock(&new); + goto out; + } + + /* Now this Router Info parameter entry has associated LSA. */ + SET_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED); + + /* Update new LSA origination count. */ + top->lsa_originate_count++; + + /* Flood new LSA through AS. */ + if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) + ospf_flood_through_as(top, NULL /*nbr */, new); + else + ospf_flood_through_area(OspfRI.area, NULL /*nbr */, new); + + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug( + "LSA[Type%d:%s]: Originate Opaque-LSA/ROUTER INFORMATION", + new->data->type, inet_ntoa(new->data->id)); + ospf_lsa_header_dump(new->data); + } + + rc = 0; +out: + return rc; } -static int -ospf_router_info_lsa_originate (void *arg) +static int ospf_router_info_lsa_originate(void *arg) { - int rc = -1; - - if (OspfRI.status == disabled) - { - zlog_info - ("ospf_router_info_lsa_originate: ROUTER INFORMATION is disabled now."); - rc = 0; /* This is not an error case. */ - goto out; - } - - /* Check if Router Information LSA is already engaged */ - if (OspfRI.flags & RIFLG_LSA_ENGAGED) - { - if (OspfRI.flags & RIFLG_LSA_FORCED_REFRESH) - { - OspfRI.flags &= ~RIFLG_LSA_FORCED_REFRESH; - ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); - } - } - else - { - if (!is_mandated_params_set (OspfRI)) - zlog_warn - ("ospf_router_info_lsa_originate: lacks mandated ROUTER INFORMATION parameters"); - - /* Ok, let's try to originate an LSA */ - if (ospf_router_info_lsa_originate1 (arg) != 0) - goto out; - } - - rc = 0; -out:return rc; + int rc = -1; + + if (OspfRI.status == disabled) { + zlog_info( + "ospf_router_info_lsa_originate: ROUTER INFORMATION is disabled now."); + rc = 0; /* This is not an error case. */ + goto out; + } + + /* Check if Router Information LSA is already engaged */ + if (OspfRI.flags & RIFLG_LSA_ENGAGED) { + if (OspfRI.flags & RIFLG_LSA_FORCED_REFRESH) { + OspfRI.flags &= ~RIFLG_LSA_FORCED_REFRESH; + ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); + } + } else { + if (!is_mandated_params_set(OspfRI)) + zlog_warn( + "ospf_router_info_lsa_originate: lacks mandated ROUTER INFORMATION parameters"); + + /* Ok, let's try to originate an LSA */ + if (ospf_router_info_lsa_originate1(arg) != 0) + goto out; + } + + rc = 0; +out: + return rc; } -static struct ospf_lsa * -ospf_router_info_lsa_refresh (struct ospf_lsa *lsa) +static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa) { - struct ospf_lsa *new = NULL; - struct ospf *top; - - if (OspfRI.status == disabled) - { - /* - * This LSA must have flushed before due to ROUTER INFORMATION status change. - * It seems a slip among routers in the routing domain. - */ - zlog_info - ("ospf_router_info_lsa_refresh: ROUTER INFORMATION is disabled now."); - lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */ - } - - /* Verify that the Router Information ID is supported */ - if (GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)) != 0) - { - zlog_warn - ("ospf_router_info_lsa_refresh: Unsupported Router Information ID"); - goto out; - } - - /* If the lsa's age reached to MaxAge, start flushing procedure. */ - if (IS_LSA_MAXAGE (lsa)) - { - OspfRI.flags &= ~RIFLG_LSA_ENGAGED; - ospf_opaque_lsa_flush_schedule (lsa); - goto out; - } - - /* Create new Opaque-LSA/ROUTER INFORMATION instance. */ - if ((new = ospf_router_info_lsa_new ()) == NULL) - { - zlog_warn - ("ospf_router_info_lsa_refresh: ospf_router_info_lsa_new() ?"); - goto out; - } - new->data->ls_seqnum = lsa_seqnum_increment (lsa); - - /* Install this LSA into LSDB. */ - /* Given "lsa" will be freed in the next function. */ - top = ospf_lookup (); - if (ospf_lsa_install (top, NULL /*oi */ , new) == NULL) - { - zlog_warn ("ospf_router_info_lsa_refresh: ospf_lsa_install() ?"); - ospf_lsa_unlock (&new); - goto out; - } - - /* Flood updated LSA through AS or AREA depending of OspfRI.scope. */ - if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) - ospf_flood_through_as (top, NULL /*nbr */ , new); - else - ospf_flood_through_area (OspfRI.area, NULL /*nbr */ , new); - - /* Debug logging. */ - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - { - zlog_debug ("LSA[Type%d:%s]: Refresh Opaque-LSA/ROUTER INFORMATION", - new->data->type, inet_ntoa (new->data->id)); - ospf_lsa_header_dump (new->data); - } - -out:return new; + struct ospf_lsa *new = NULL; + struct ospf *top; + + if (OspfRI.status == disabled) { + /* + * This LSA must have flushed before due to ROUTER INFORMATION + * status change. + * It seems a slip among routers in the routing domain. + */ + zlog_info( + "ospf_router_info_lsa_refresh: ROUTER INFORMATION is disabled now."); + lsa->data->ls_age = + htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */ + } + + /* Verify that the Router Information ID is supported */ + if (GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)) != 0) { + zlog_warn( + "ospf_router_info_lsa_refresh: Unsupported Router Information ID"); + goto out; + } + + /* If the lsa's age reached to MaxAge, start flushing procedure. */ + if (IS_LSA_MAXAGE(lsa)) { + OspfRI.flags &= ~RIFLG_LSA_ENGAGED; + ospf_opaque_lsa_flush_schedule(lsa); + goto out; + } + + /* Create new Opaque-LSA/ROUTER INFORMATION instance. */ + if ((new = ospf_router_info_lsa_new()) == NULL) { + zlog_warn( + "ospf_router_info_lsa_refresh: ospf_router_info_lsa_new() ?"); + goto out; + } + new->data->ls_seqnum = lsa_seqnum_increment(lsa); + + /* Install this LSA into LSDB. */ + /* Given "lsa" will be freed in the next function. */ + top = ospf_lookup(); + if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) { + zlog_warn("ospf_router_info_lsa_refresh: ospf_lsa_install() ?"); + ospf_lsa_unlock(&new); + goto out; + } + + /* Flood updated LSA through AS or AREA depending of OspfRI.scope. */ + if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) + ospf_flood_through_as(top, NULL /*nbr */, new); + else + ospf_flood_through_area(OspfRI.area, NULL /*nbr */, new); + + /* Debug logging. */ + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug( + "LSA[Type%d:%s]: Refresh Opaque-LSA/ROUTER INFORMATION", + new->data->type, inet_ntoa(new->data->id)); + ospf_lsa_header_dump(new->data); + } + +out: + return new; } -static void -ospf_router_info_lsa_schedule (opcode_t opcode) +static void ospf_router_info_lsa_schedule(opcode_t opcode) { - struct ospf_lsa lsa; - struct lsa_header lsah; - struct ospf *top; - u_int32_t tmp; - - memset (&lsa, 0, sizeof (lsa)); - memset (&lsah, 0, sizeof (lsah)); - - zlog_debug ("RI-> LSA schedule %s%s%s", - opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "", - opcode == REFRESH_THIS_LSA ? "Refresh" : "", - opcode == FLUSH_THIS_LSA ? "Flush" : ""); - - top = ospf_lookup (); - if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL)) - { - zlog_warn - ("ospf_router_info_lsa_schedule(): Router Info is Area scope flooding but area is not set"); - OspfRI.area = ospf_area_lookup_by_area_id (top, OspfRI.area_id); - } - lsa.area = OspfRI.area; - lsa.data = &lsah; - lsah.type = OspfRI.scope; - - /* LSA ID is set to 0 for the Router Information. See RFC 4970 */ - tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0); - lsah.id.s_addr = htonl (tmp); - - switch (opcode) - { - case REORIGINATE_THIS_LSA: - if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) - ospf_opaque_lsa_reoriginate_schedule ((void *) OspfRI.area, - OSPF_OPAQUE_AREA_LSA, - OPAQUE_TYPE_ROUTER_INFORMATION_LSA); - else - ospf_opaque_lsa_reoriginate_schedule ((void *) top, - OSPF_OPAQUE_AS_LSA, - OPAQUE_TYPE_ROUTER_INFORMATION_LSA); - break; - case REFRESH_THIS_LSA: - ospf_opaque_lsa_refresh_schedule (&lsa); - break; - case FLUSH_THIS_LSA: - OspfRI.flags &= ~RIFLG_LSA_ENGAGED; - ospf_opaque_lsa_flush_schedule (&lsa); - break; - default: - zlog_warn ("ospf_router_info_lsa_schedule: Unknown opcode (%u)", - opcode); - break; - } - - return; + struct ospf_lsa lsa; + struct lsa_header lsah; + struct ospf *top; + u_int32_t tmp; + + memset(&lsa, 0, sizeof(lsa)); + memset(&lsah, 0, sizeof(lsah)); + + zlog_debug("RI-> LSA schedule %s%s%s", + opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "", + opcode == REFRESH_THIS_LSA ? "Refresh" : "", + opcode == FLUSH_THIS_LSA ? "Flush" : ""); + + top = ospf_lookup(); + if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL)) { + zlog_warn( + "ospf_router_info_lsa_schedule(): Router Info is Area scope flooding but area is not set"); + OspfRI.area = ospf_area_lookup_by_area_id(top, OspfRI.area_id); + } + lsa.area = OspfRI.area; + lsa.data = &lsah; + lsah.type = OspfRI.scope; + + /* LSA ID is set to 0 for the Router Information. See RFC 4970 */ + tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0); + lsah.id.s_addr = htonl(tmp); + + switch (opcode) { + case REORIGINATE_THIS_LSA: + if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) + ospf_opaque_lsa_reoriginate_schedule( + (void *)OspfRI.area, OSPF_OPAQUE_AREA_LSA, + OPAQUE_TYPE_ROUTER_INFORMATION_LSA); + else + ospf_opaque_lsa_reoriginate_schedule( + (void *)top, OSPF_OPAQUE_AS_LSA, + OPAQUE_TYPE_ROUTER_INFORMATION_LSA); + break; + case REFRESH_THIS_LSA: + ospf_opaque_lsa_refresh_schedule(&lsa); + break; + case FLUSH_THIS_LSA: + OspfRI.flags &= ~RIFLG_LSA_ENGAGED; + ospf_opaque_lsa_flush_schedule(&lsa); + break; + default: + zlog_warn("ospf_router_info_lsa_schedule: Unknown opcode (%u)", + opcode); + break; + } + + return; } /*------------------------------------------------------------------------* * Followings are vty session control functions. *------------------------------------------------------------------------*/ -static u_int16_t -show_vty_router_cap (struct vty *vty, struct ri_tlv_header *tlvh) +static u_int16_t show_vty_router_cap(struct vty *vty, + struct ri_tlv_header *tlvh) { - struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *) tlvh; + struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *)tlvh; - if (vty != NULL) - vty_out (vty, " Router Capabilities: 0x%x\n",ntohl(top->value)); - else - zlog_debug (" Router Capabilities: 0x%x", ntohl (top->value)); + if (vty != NULL) + vty_out(vty, " Router Capabilities: 0x%x\n", + ntohl(top->value)); + else + zlog_debug(" Router Capabilities: 0x%x", ntohl(top->value)); - return RI_TLV_SIZE (tlvh); + return RI_TLV_SIZE(tlvh); } -static u_int16_t -show_vty_pce_subtlv_address (struct vty *vty, struct ri_tlv_header *tlvh) +static u_int16_t show_vty_pce_subtlv_address(struct vty *vty, + struct ri_tlv_header *tlvh) { - struct ri_pce_subtlv_address *top = (struct ri_pce_subtlv_address *) tlvh; - - if (ntohs (top->address.type) == PCE_ADDRESS_TYPE_IPV4) - { - if (vty != NULL) - vty_out (vty, " PCE Address: %s\n",inet_ntoa(top->address.value)); - else - zlog_debug (" PCE Address: %s", inet_ntoa (top->address.value)); - } - else - { - /* TODO: Add support to IPv6 with inet_ntop() */ - if (vty != NULL) - vty_out (vty, " PCE Address: 0x%x\n", - ntohl(top->address.value.s_addr)); - else - zlog_debug (" PCE Address: 0x%x", - ntohl (top->address.value.s_addr)); - } - - return RI_TLV_SIZE (tlvh); + struct ri_pce_subtlv_address *top = + (struct ri_pce_subtlv_address *)tlvh; + + if (ntohs(top->address.type) == PCE_ADDRESS_TYPE_IPV4) { + if (vty != NULL) + vty_out(vty, " PCE Address: %s\n", + inet_ntoa(top->address.value)); + else + zlog_debug(" PCE Address: %s", + inet_ntoa(top->address.value)); + } else { + /* TODO: Add support to IPv6 with inet_ntop() */ + if (vty != NULL) + vty_out(vty, " PCE Address: 0x%x\n", + ntohl(top->address.value.s_addr)); + else + zlog_debug(" PCE Address: 0x%x", + ntohl(top->address.value.s_addr)); + } + + return RI_TLV_SIZE(tlvh); } -static u_int16_t -show_vty_pce_subtlv_path_scope (struct vty *vty, struct ri_tlv_header *tlvh) +static u_int16_t show_vty_pce_subtlv_path_scope(struct vty *vty, + struct ri_tlv_header *tlvh) { - struct ri_pce_subtlv_path_scope *top = - (struct ri_pce_subtlv_path_scope *) tlvh; + struct ri_pce_subtlv_path_scope *top = + (struct ri_pce_subtlv_path_scope *)tlvh; - if (vty != NULL) - vty_out (vty, " PCE Path Scope: 0x%x\n",ntohl(top->value)); - else - zlog_debug (" PCE Path Scope: 0x%x", ntohl (top->value)); + if (vty != NULL) + vty_out(vty, " PCE Path Scope: 0x%x\n", ntohl(top->value)); + else + zlog_debug(" PCE Path Scope: 0x%x", ntohl(top->value)); - return RI_TLV_SIZE (tlvh); + return RI_TLV_SIZE(tlvh); } -static u_int16_t -show_vty_pce_subtlv_domain (struct vty *vty, struct ri_tlv_header *tlvh) +static u_int16_t show_vty_pce_subtlv_domain(struct vty *vty, + struct ri_tlv_header *tlvh) { - struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *) tlvh; - struct in_addr tmp; - - if (ntohs (top->type) == PCE_DOMAIN_TYPE_AREA) - { - tmp.s_addr = top->value; - if (vty != NULL) - vty_out (vty, " PCE domain Area: %s\n",inet_ntoa(tmp)); - else - zlog_debug (" PCE domain Area: %s", inet_ntoa (tmp)); - } - else - { - if (vty != NULL) - vty_out (vty, " PCE domain AS: %d\n",ntohl(top->value)); - else - zlog_debug (" PCE domain AS: %d", ntohl (top->value)); - } - return RI_TLV_SIZE (tlvh); + struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *)tlvh; + struct in_addr tmp; + + if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) { + tmp.s_addr = top->value; + if (vty != NULL) + vty_out(vty, " PCE domain Area: %s\n", inet_ntoa(tmp)); + else + zlog_debug(" PCE domain Area: %s", inet_ntoa(tmp)); + } else { + if (vty != NULL) + vty_out(vty, " PCE domain AS: %d\n", + ntohl(top->value)); + else + zlog_debug(" PCE domain AS: %d", ntohl(top->value)); + } + return RI_TLV_SIZE(tlvh); } -static u_int16_t -show_vty_pce_subtlv_neighbor (struct vty *vty, struct ri_tlv_header *tlvh) +static u_int16_t show_vty_pce_subtlv_neighbor(struct vty *vty, + struct ri_tlv_header *tlvh) { - struct ri_pce_subtlv_neighbor *top = (struct ri_pce_subtlv_neighbor *) tlvh; - struct in_addr tmp; - - if (ntohs (top->type) == PCE_DOMAIN_TYPE_AREA) - { - tmp.s_addr = top->value; - if (vty != NULL) - vty_out (vty, " PCE neighbor Area: %s\n",inet_ntoa(tmp)); - else - zlog_debug (" PCE neighbor Area: %s", inet_ntoa (tmp)); - } - else - { - if (vty != NULL) - vty_out (vty, " PCE neighbor AS: %d\n",ntohl(top->value)); - else - zlog_debug (" PCE neighbor AS: %d", ntohl (top->value)); - } - return RI_TLV_SIZE (tlvh); + struct ri_pce_subtlv_neighbor *top = + (struct ri_pce_subtlv_neighbor *)tlvh; + struct in_addr tmp; + + if (ntohs(top->type) == PCE_DOMAIN_TYPE_AREA) { + tmp.s_addr = top->value; + if (vty != NULL) + vty_out(vty, " PCE neighbor Area: %s\n", + inet_ntoa(tmp)); + else + zlog_debug(" PCE neighbor Area: %s", inet_ntoa(tmp)); + } else { + if (vty != NULL) + vty_out(vty, " PCE neighbor AS: %d\n", + ntohl(top->value)); + else + zlog_debug(" PCE neighbor AS: %d", + ntohl(top->value)); + } + return RI_TLV_SIZE(tlvh); } -static u_int16_t -show_vty_pce_subtlv_cap_flag (struct vty *vty, struct ri_tlv_header *tlvh) +static u_int16_t show_vty_pce_subtlv_cap_flag(struct vty *vty, + struct ri_tlv_header *tlvh) { - struct ri_pce_subtlv_cap_flag *top = (struct ri_pce_subtlv_cap_flag *) tlvh; + struct ri_pce_subtlv_cap_flag *top = + (struct ri_pce_subtlv_cap_flag *)tlvh; - if (vty != NULL) - vty_out (vty, " PCE Capabilities Flag: 0x%x\n",ntohl(top->value)); - else - zlog_debug (" PCE Capabilities Flag: 0x%x", ntohl (top->value)); + if (vty != NULL) + vty_out(vty, " PCE Capabilities Flag: 0x%x\n", + ntohl(top->value)); + else + zlog_debug(" PCE Capabilities Flag: 0x%x", + ntohl(top->value)); - return RI_TLV_SIZE (tlvh); + return RI_TLV_SIZE(tlvh); } -static u_int16_t -show_vty_unknown_tlv (struct vty *vty, struct ri_tlv_header *tlvh) +static u_int16_t show_vty_unknown_tlv(struct vty *vty, + struct ri_tlv_header *tlvh) { - if (vty != NULL) - vty_out (vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n", - ntohs (tlvh->type), ntohs(tlvh->length)); - else - zlog_debug (" Unknown TLV: [type(0x%x), length(0x%x)]", - ntohs (tlvh->type), ntohs (tlvh->length)); - - return RI_TLV_SIZE (tlvh); + if (vty != NULL) + vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n", + ntohs(tlvh->type), ntohs(tlvh->length)); + else + zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]", + ntohs(tlvh->type), ntohs(tlvh->length)); + + return RI_TLV_SIZE(tlvh); } -static u_int16_t -show_vty_pce_info (struct vty *vty, struct ri_tlv_header *ri, uint32_t total) +static u_int16_t show_vty_pce_info(struct vty *vty, struct ri_tlv_header *ri, + uint32_t total) { - struct ri_tlv_header *tlvh; - u_int16_t sum = 0; - - for (tlvh = ri; sum < total; tlvh = RI_TLV_HDR_NEXT (tlvh)) - { - switch (ntohs (tlvh->type)) - { - case RI_PCE_SUBTLV_ADDRESS: - sum += show_vty_pce_subtlv_address (vty, tlvh); - break; - case RI_PCE_SUBTLV_PATH_SCOPE: - sum += show_vty_pce_subtlv_path_scope (vty, tlvh); - break; - case RI_PCE_SUBTLV_DOMAIN: - sum += show_vty_pce_subtlv_domain (vty, tlvh); - break; - case RI_PCE_SUBTLV_NEIGHBOR: - sum += show_vty_pce_subtlv_neighbor (vty, tlvh); - break; - case RI_PCE_SUBTLV_CAP_FLAG: - sum += show_vty_pce_subtlv_cap_flag (vty, tlvh); - break; - default: - sum += show_vty_unknown_tlv (vty, tlvh); - break; - } - } - return sum; + struct ri_tlv_header *tlvh; + u_int16_t sum = 0; + + for (tlvh = ri; sum < total; tlvh = RI_TLV_HDR_NEXT(tlvh)) { + switch (ntohs(tlvh->type)) { + case RI_PCE_SUBTLV_ADDRESS: + sum += show_vty_pce_subtlv_address(vty, tlvh); + break; + case RI_PCE_SUBTLV_PATH_SCOPE: + sum += show_vty_pce_subtlv_path_scope(vty, tlvh); + break; + case RI_PCE_SUBTLV_DOMAIN: + sum += show_vty_pce_subtlv_domain(vty, tlvh); + break; + case RI_PCE_SUBTLV_NEIGHBOR: + sum += show_vty_pce_subtlv_neighbor(vty, tlvh); + break; + case RI_PCE_SUBTLV_CAP_FLAG: + sum += show_vty_pce_subtlv_cap_flag(vty, tlvh); + break; + default: + sum += show_vty_unknown_tlv(vty, tlvh); + break; + } + } + return sum; } -static void -ospf_router_info_show_info (struct vty *vty, struct ospf_lsa *lsa) +static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa) { - struct lsa_header *lsah = (struct lsa_header *) lsa->data; - struct ri_tlv_header *tlvh; - u_int16_t length = 0, sum = 0; - - /* Initialize TLV browsing */ - length = ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE; - - for (tlvh = RI_TLV_HDR_TOP (lsah); sum < length; - tlvh = RI_TLV_HDR_NEXT (tlvh)) - { - switch (ntohs (tlvh->type)) - { - case RI_TLV_CAPABILITIES: - sum += show_vty_router_cap (vty, tlvh); - break; - case RI_TLV_PCE: - tlvh++; - sum += RI_TLV_HDR_SIZE; - sum += show_vty_pce_info (vty, tlvh, length - sum); - break; - default: - sum += show_vty_unknown_tlv (vty, tlvh); - break; - } - } - - return; + struct lsa_header *lsah = (struct lsa_header *)lsa->data; + struct ri_tlv_header *tlvh; + u_int16_t length = 0, sum = 0; + + /* Initialize TLV browsing */ + length = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE; + + for (tlvh = RI_TLV_HDR_TOP(lsah); sum < length; + tlvh = RI_TLV_HDR_NEXT(tlvh)) { + switch (ntohs(tlvh->type)) { + case RI_TLV_CAPABILITIES: + sum += show_vty_router_cap(vty, tlvh); + break; + case RI_TLV_PCE: + tlvh++; + sum += RI_TLV_HDR_SIZE; + sum += show_vty_pce_info(vty, tlvh, length - sum); + break; + default: + sum += show_vty_unknown_tlv(vty, tlvh); + break; + } + } + + return; } -static void -ospf_router_info_config_write_router (struct vty *vty) +static void ospf_router_info_config_write_router(struct vty *vty) { - struct ospf_pce_info *pce = &OspfRI.pce_info; - struct listnode *node; - struct ri_pce_subtlv_domain *domain; - struct ri_pce_subtlv_neighbor *neighbor; - struct in_addr tmp; - - if (OspfRI.status == enabled) - { - if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) - vty_out (vty, " router-info as\n"); - else - vty_out (vty, " router-info area %s\n",inet_ntoa(OspfRI.area_id)); - - if (pce->pce_address.header.type != 0) - vty_out (vty, " pce address %s\n", - inet_ntoa(pce->pce_address.address.value)); - - if (pce->pce_cap_flag.header.type != 0) - vty_out (vty, " pce flag 0x%x\n",ntohl(pce->pce_cap_flag.value)); - - for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain)) - { - if (domain->header.type != 0) - { - if (domain->type == PCE_DOMAIN_TYPE_AREA) - { - tmp.s_addr = domain->value; - vty_out (vty, " pce domain area %s\n",inet_ntoa(tmp)); - } - else - { - vty_out (vty, " pce domain as %d\n",ntohl(domain->value)); - } - } - } - - for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor)) - { - if (neighbor->header.type != 0) - { - if (neighbor->type == PCE_DOMAIN_TYPE_AREA) - { - tmp.s_addr = neighbor->value; - vty_out (vty, " pce neighbor area %s\n",inet_ntoa(tmp)); - } - else - { - vty_out (vty, " pce neighbor as %d\n", - ntohl(neighbor->value)); - } - } - } - - if (pce->pce_scope.header.type != 0) - vty_out (vty, " pce scope 0x%x\n", - ntohl(OspfRI.pce_info.pce_scope.value)); - } - return; + struct ospf_pce_info *pce = &OspfRI.pce_info; + struct listnode *node; + struct ri_pce_subtlv_domain *domain; + struct ri_pce_subtlv_neighbor *neighbor; + struct in_addr tmp; + + if (OspfRI.status == enabled) { + if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) + vty_out(vty, " router-info as\n"); + else + vty_out(vty, " router-info area %s\n", + inet_ntoa(OspfRI.area_id)); + + if (pce->pce_address.header.type != 0) + vty_out(vty, " pce address %s\n", + inet_ntoa(pce->pce_address.address.value)); + + if (pce->pce_cap_flag.header.type != 0) + vty_out(vty, " pce flag 0x%x\n", + ntohl(pce->pce_cap_flag.value)); + + for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) { + if (domain->header.type != 0) { + if (domain->type == PCE_DOMAIN_TYPE_AREA) { + tmp.s_addr = domain->value; + vty_out(vty, " pce domain area %s\n", + inet_ntoa(tmp)); + } else { + vty_out(vty, " pce domain as %d\n", + ntohl(domain->value)); + } + } + } + + for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) { + if (neighbor->header.type != 0) { + if (neighbor->type == PCE_DOMAIN_TYPE_AREA) { + tmp.s_addr = neighbor->value; + vty_out(vty, " pce neighbor area %s\n", + inet_ntoa(tmp)); + } else { + vty_out(vty, " pce neighbor as %d\n", + ntohl(neighbor->value)); + } + } + } + + if (pce->pce_scope.header.type != 0) + vty_out(vty, " pce scope 0x%x\n", + ntohl(OspfRI.pce_info.pce_scope.value)); + } + return; } /*------------------------------------------------------------------------* @@ -1168,61 +1113,58 @@ DEFUN (router_info, "Enable the Router Information functionality with Area flooding scope\n" "OSPF area ID in IP format") { - int idx_ipv4 = 2; - char *area = (argc == 3) ? argv[idx_ipv4]->arg : NULL; - - u_int8_t scope; - - if (OspfRI.status == enabled) - return CMD_SUCCESS; - - /* Check and get Area value if present */ - if (area) - { - if (!inet_aton (area, &OspfRI.area_id)) - { - vty_out (vty, "%% specified Area ID %s is invalid\n", - area); - return CMD_WARNING_CONFIG_FAILED; - } - scope = OSPF_OPAQUE_AREA_LSA; - } - else - { - OspfRI.area_id.s_addr = 0; - scope = OSPF_OPAQUE_AS_LSA; - } - - /* First start to register Router Information callbacks */ - if ((ospf_router_info_register (scope)) != 0) - { - zlog_warn ("Enable to register Router Information callbacks. Abort!"); - return CMD_WARNING_CONFIG_FAILED; - } - - OspfRI.status = enabled; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("RI-> Router Information (%s flooding): OFF -> ON", - OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS"); - - /* - * Following code is intended to handle two cases; - * - * 1) Router Information was disabled at startup time, but now become enabled. - * 2) Router Information was once enabled then disabled, and now enabled again. - */ - - initialize_params (&OspfRI); - - /* Refresh RI LSA if already engaged */ - if (OspfRI.flags & RIFLG_LSA_ENGAGED) - { - zlog_debug ("RI-> Initial origination following configuration"); - ospf_router_info_lsa_schedule (REORIGINATE_THIS_LSA); - } - return CMD_SUCCESS; - + int idx_ipv4 = 2; + char *area = (argc == 3) ? argv[idx_ipv4]->arg : NULL; + + u_int8_t scope; + + if (OspfRI.status == enabled) + return CMD_SUCCESS; + + /* Check and get Area value if present */ + if (area) { + if (!inet_aton(area, &OspfRI.area_id)) { + vty_out(vty, "%% specified Area ID %s is invalid\n", + area); + return CMD_WARNING_CONFIG_FAILED; + } + scope = OSPF_OPAQUE_AREA_LSA; + } else { + OspfRI.area_id.s_addr = 0; + scope = OSPF_OPAQUE_AS_LSA; + } + + /* First start to register Router Information callbacks */ + if ((ospf_router_info_register(scope)) != 0) { + zlog_warn( + "Enable to register Router Information callbacks. Abort!"); + return CMD_WARNING_CONFIG_FAILED; + } + + OspfRI.status = enabled; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("RI-> Router Information (%s flooding): OFF -> ON", + OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" + : "AS"); + + /* + * Following code is intended to handle two cases; + * + * 1) Router Information was disabled at startup time, but now become + * enabled. + * 2) Router Information was once enabled then disabled, and now enabled + * again. + */ + + initialize_params(&OspfRI); + + /* Refresh RI LSA if already engaged */ + if (OspfRI.flags & RIFLG_LSA_ENGAGED) { + zlog_debug("RI-> Initial origination following configuration"); + ospf_router_info_lsa_schedule(REORIGINATE_THIS_LSA); + } + return CMD_SUCCESS; } @@ -1233,33 +1175,32 @@ DEFUN (no_router_info, "Disable the Router Information functionality\n") { - if (OspfRI.status == disabled) - return CMD_SUCCESS; + if (OspfRI.status == disabled) + return CMD_SUCCESS; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("RI-> Router Information: ON -> OFF"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("RI-> Router Information: ON -> OFF"); - if (OspfRI.flags & RIFLG_LSA_ENGAGED) - ospf_router_info_lsa_schedule (FLUSH_THIS_LSA); + if (OspfRI.flags & RIFLG_LSA_ENGAGED) + ospf_router_info_lsa_schedule(FLUSH_THIS_LSA); - /* Unregister the callbacks */ - ospf_router_info_unregister (); + /* Unregister the callbacks */ + ospf_router_info_unregister(); - OspfRI.status = disabled; + OspfRI.status = disabled; - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -ospf_ri_enabled (struct vty *vty) +static int ospf_ri_enabled(struct vty *vty) { - if (OspfRI.status == enabled) - return 1; + if (OspfRI.status == enabled) + return 1; - if (vty) - vty_out (vty, "%% OSPF RI is not turned on\n"); + if (vty) + vty_out(vty, "%% OSPF RI is not turned on\n"); - return 0; + return 0; } DEFUN (pce_address, @@ -1269,31 +1210,30 @@ DEFUN (pce_address, "Stable IP address of the PCE\n" "PCE address in IPv4 address format\n") { - int idx_ipv4 = 2; - struct in_addr value; - struct ospf_pce_info *pi = &OspfRI.pce_info; + int idx_ipv4 = 2; + struct in_addr value; + struct ospf_pce_info *pi = &OspfRI.pce_info; - if (!ospf_ri_enabled (vty)) - return CMD_WARNING_CONFIG_FAILED; + if (!ospf_ri_enabled(vty)) + return CMD_WARNING_CONFIG_FAILED; - if (!inet_aton (argv[idx_ipv4]->arg, &value)) - { - vty_out (vty, "Please specify PCE Address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!inet_aton(argv[idx_ipv4]->arg, &value)) { + vty_out(vty, "Please specify PCE Address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (ntohs (pi->pce_address.header.type) == 0 - || ntohl (pi->pce_address.address.value.s_addr) != ntohl (value.s_addr)) - { + if (ntohs(pi->pce_address.header.type) == 0 + || ntohl(pi->pce_address.address.value.s_addr) + != ntohl(value.s_addr)) { - set_pce_address (value, pi); + set_pce_address(value, pi); - /* Refresh RI LSA if already engaged */ - if (OspfRI.flags & RIFLG_LSA_ENGAGED) - ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); - } + /* Refresh RI LSA if already engaged */ + if (OspfRI.flags & RIFLG_LSA_ENGAGED) + ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_pce_address, @@ -1305,13 +1245,13 @@ DEFUN (no_pce_address, "PCE address in IPv4 address format\n") { - unset_param (&OspfRI.pce_info.pce_address.header); + unset_param(&OspfRI.pce_info.pce_address.header); - /* Refresh RI LSA if already engaged */ - if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) - ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (pce_path_scope, @@ -1321,29 +1261,29 @@ DEFUN (pce_path_scope, "Path scope visibilities of the PCE for path computation\n" "32-bit Hexadecimal value\n") { - int idx_bitpattern = 2; - uint32_t scope; - struct ospf_pce_info *pi = &OspfRI.pce_info; + int idx_bitpattern = 2; + uint32_t scope; + struct ospf_pce_info *pi = &OspfRI.pce_info; - if (!ospf_ri_enabled (vty)) - return CMD_WARNING_CONFIG_FAILED; + if (!ospf_ri_enabled(vty)) + return CMD_WARNING_CONFIG_FAILED; - if (sscanf (argv[idx_bitpattern]->arg, "0x%x", &scope) != 1) - { - vty_out (vty, "pce_path_scope: fscanf: %s\n",safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + if (sscanf(argv[idx_bitpattern]->arg, "0x%x", &scope) != 1) { + vty_out(vty, "pce_path_scope: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - if (ntohl (pi->pce_scope.header.type) == 0 || scope != pi->pce_scope.value) - { - set_pce_path_scope (scope, pi); + if (ntohl(pi->pce_scope.header.type) == 0 + || scope != pi->pce_scope.value) { + set_pce_path_scope(scope, pi); - /* Refresh RI LSA if already engaged */ - if (OspfRI.flags & RIFLG_LSA_ENGAGED) - ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); - } + /* Refresh RI LSA if already engaged */ + if (OspfRI.flags & RIFLG_LSA_ENGAGED) + ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_pce_path_scope, @@ -1355,13 +1295,13 @@ DEFUN (no_pce_path_scope, "32-bit Hexadecimal value\n") { - unset_param (&OspfRI.pce_info.pce_address.header); + unset_param(&OspfRI.pce_info.pce_address.header); - /* Refresh RI LSA if already engaged */ - if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) - ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (pce_domain, @@ -1372,37 +1312,35 @@ DEFUN (pce_domain, "AS number where the PCE as visibilities for path computation\n" "AS number in decimal <0-65535>\n") { - int idx_number = 3; + int idx_number = 3; - uint32_t as; - struct ospf_pce_info *pce = &OspfRI.pce_info; - struct listnode *node; - struct ri_pce_subtlv_domain *domain; + uint32_t as; + struct ospf_pce_info *pce = &OspfRI.pce_info; + struct listnode *node; + struct ri_pce_subtlv_domain *domain; - if (!ospf_ri_enabled (vty)) - return CMD_WARNING_CONFIG_FAILED; + if (!ospf_ri_enabled(vty)) + return CMD_WARNING_CONFIG_FAILED; - if (sscanf (argv[idx_number]->arg, "%d", &as) != 1) - { - vty_out (vty, "pce_domain: fscanf: %s\n",safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + if (sscanf(argv[idx_number]->arg, "%d", &as) != 1) { + vty_out(vty, "pce_domain: fscanf: %s\n", safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - /* Check if the domain is not already in the domain list */ - for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain)) - { - if (ntohl (domain->header.type) == 0 && as == domain->value) - return CMD_SUCCESS; - } + /* Check if the domain is not already in the domain list */ + for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) { + if (ntohl(domain->header.type) == 0 && as == domain->value) + return CMD_SUCCESS; + } - /* Create new domain if not found */ - set_pce_domain (PCE_DOMAIN_TYPE_AS, as, pce); + /* Create new domain if not found */ + set_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce); - /* Refresh RI LSA if already engaged */ - if (OspfRI.flags & RIFLG_LSA_ENGAGED) - ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + /* Refresh RI LSA if already engaged */ + if (OspfRI.flags & RIFLG_LSA_ENGAGED) + ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_pce_domain, @@ -1414,25 +1352,25 @@ DEFUN (no_pce_domain, "AS number where the PCE as visibilities for path computation\n" "AS number in decimal <0-65535>\n") { - int idx_number = 4; + int idx_number = 4; - uint32_t as; - struct ospf_pce_info *pce = &OspfRI.pce_info; + uint32_t as; + struct ospf_pce_info *pce = &OspfRI.pce_info; - if (sscanf (argv[idx_number]->arg, "%d", &as) != 1) - { - vty_out (vty, "no_pce_domain: fscanf: %s\n",safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + if (sscanf(argv[idx_number]->arg, "%d", &as) != 1) { + vty_out(vty, "no_pce_domain: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - /* Unset corresponding PCE domain */ - unset_pce_domain (PCE_DOMAIN_TYPE_AS, as, pce); + /* Unset corresponding PCE domain */ + unset_pce_domain(PCE_DOMAIN_TYPE_AS, as, pce); - /* Refresh RI LSA if already engaged */ - if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) - ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (pce_neigbhor, @@ -1443,37 +1381,36 @@ DEFUN (pce_neigbhor, "AS number of PCE neighbors\n" "AS number in decimal <0-65535>\n") { - int idx_number = 3; + int idx_number = 3; - uint32_t as; - struct ospf_pce_info *pce = &OspfRI.pce_info; - struct listnode *node; - struct ri_pce_subtlv_neighbor *neighbor; + uint32_t as; + struct ospf_pce_info *pce = &OspfRI.pce_info; + struct listnode *node; + struct ri_pce_subtlv_neighbor *neighbor; - if (!ospf_ri_enabled (vty)) - return CMD_WARNING_CONFIG_FAILED; + if (!ospf_ri_enabled(vty)) + return CMD_WARNING_CONFIG_FAILED; - if (sscanf (argv[idx_number]->arg, "%d", &as) != 1) - { - vty_out (vty, "pce_neighbor: fscanf: %s\n",safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + if (sscanf(argv[idx_number]->arg, "%d", &as) != 1) { + vty_out(vty, "pce_neighbor: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - /* Check if the domain is not already in the domain list */ - for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor)) - { - if (ntohl (neighbor->header.type) == 0 && as == neighbor->value) - return CMD_SUCCESS; - } + /* Check if the domain is not already in the domain list */ + for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) { + if (ntohl(neighbor->header.type) == 0 && as == neighbor->value) + return CMD_SUCCESS; + } - /* Create new domain if not found */ - set_pce_neighbor (PCE_DOMAIN_TYPE_AS, as, pce); + /* Create new domain if not found */ + set_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce); - /* Refresh RI LSA if already engaged */ - if (OspfRI.flags & RIFLG_LSA_ENGAGED) - ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + /* Refresh RI LSA if already engaged */ + if (OspfRI.flags & RIFLG_LSA_ENGAGED) + ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_pce_neighbor, @@ -1485,25 +1422,25 @@ DEFUN (no_pce_neighbor, "AS number of PCE neighbor\n" "AS number in decimal <0-65535>\n") { - int idx_number = 4; + int idx_number = 4; - uint32_t as; - struct ospf_pce_info *pce = &OspfRI.pce_info; + uint32_t as; + struct ospf_pce_info *pce = &OspfRI.pce_info; - if (sscanf (argv[idx_number]->arg, "%d", &as) != 1) - { - vty_out (vty, "no_pce_neighbor: fscanf: %s\n",safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + if (sscanf(argv[idx_number]->arg, "%d", &as) != 1) { + vty_out(vty, "no_pce_neighbor: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - /* Unset corresponding PCE domain */ - unset_pce_neighbor (PCE_DOMAIN_TYPE_AS, as, pce); + /* Unset corresponding PCE domain */ + unset_pce_neighbor(PCE_DOMAIN_TYPE_AS, as, pce); - /* Refresh RI LSA if already engaged */ - if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) - ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (pce_cap_flag, @@ -1513,31 +1450,30 @@ DEFUN (pce_cap_flag, "Capabilities of the PCE for path computation\n" "32-bit Hexadecimal value\n") { - int idx_bitpattern = 2; + int idx_bitpattern = 2; - uint32_t cap; - struct ospf_pce_info *pce = &OspfRI.pce_info; + uint32_t cap; + struct ospf_pce_info *pce = &OspfRI.pce_info; - if (!ospf_ri_enabled (vty)) - return CMD_WARNING_CONFIG_FAILED; + if (!ospf_ri_enabled(vty)) + return CMD_WARNING_CONFIG_FAILED; - if (sscanf (argv[idx_bitpattern]->arg, "0x%x", &cap) != 1) - { - vty_out (vty, "pce_cap_flag: fscanf: %s\n",safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + if (sscanf(argv[idx_bitpattern]->arg, "0x%x", &cap) != 1) { + vty_out(vty, "pce_cap_flag: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - if (ntohl (pce->pce_cap_flag.header.type) == 0 - || cap != pce->pce_cap_flag.value) - { - set_pce_cap_flag (cap, pce); + if (ntohl(pce->pce_cap_flag.header.type) == 0 + || cap != pce->pce_cap_flag.value) { + set_pce_cap_flag(cap, pce); - /* Refresh RI LSA if already engaged */ - if (OspfRI.flags & RIFLG_LSA_ENGAGED) - ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); - } + /* Refresh RI LSA if already engaged */ + if (OspfRI.flags & RIFLG_LSA_ENGAGED) + ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_pce_cap_flag, @@ -1548,13 +1484,13 @@ DEFUN (no_pce_cap_flag, "Disable PCE capabilities\n") { - unset_param (&OspfRI.pce_info.pce_cap_flag.header); + unset_param(&OspfRI.pce_info.pce_cap_flag.header); - /* Refresh RI LSA if already engaged */ - if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) - ospf_router_info_lsa_schedule (REFRESH_THIS_LSA); + /* Refresh RI LSA if already engaged */ + if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED)) + ospf_router_info_lsa_schedule(REFRESH_THIS_LSA); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_ospf_router_info, @@ -1566,17 +1502,15 @@ DEFUN (show_ip_ospf_router_info, "Router Information\n") { - if (OspfRI.status == enabled) - { - vty_out (vty, "--- Router Information parameters ---\n"); - show_vty_router_cap (vty, &OspfRI.router_cap.header); - } - else - { - if (vty != NULL) - vty_out (vty, " Router Information is disabled on this router\n"); - } - return CMD_SUCCESS; + if (OspfRI.status == enabled) { + vty_out(vty, "--- Router Information parameters ---\n"); + show_vty_router_cap(vty, &OspfRI.router_cap.header); + } else { + if (vty != NULL) + vty_out(vty, + " Router Information is disabled on this router\n"); + } + return CMD_SUCCESS; } DEFUN (show_ip_opsf_router_info_pce, @@ -1589,64 +1523,64 @@ DEFUN (show_ip_opsf_router_info_pce, "PCE information\n") { - struct ospf_pce_info *pce = &OspfRI.pce_info; - struct listnode *node; - struct ri_pce_subtlv_domain *domain; - struct ri_pce_subtlv_neighbor *neighbor; + struct ospf_pce_info *pce = &OspfRI.pce_info; + struct listnode *node; + struct ri_pce_subtlv_domain *domain; + struct ri_pce_subtlv_neighbor *neighbor; - if (OspfRI.status == enabled) - { - vty_out (vty, "--- PCE parameters ---\n"); + if (OspfRI.status == enabled) { + vty_out(vty, "--- PCE parameters ---\n"); - if (pce->pce_address.header.type != 0) - show_vty_pce_subtlv_address (vty, &pce->pce_address.header); + if (pce->pce_address.header.type != 0) + show_vty_pce_subtlv_address(vty, + &pce->pce_address.header); - if (pce->pce_scope.header.type != 0) - show_vty_pce_subtlv_path_scope (vty, &pce->pce_scope.header); + if (pce->pce_scope.header.type != 0) + show_vty_pce_subtlv_path_scope(vty, + &pce->pce_scope.header); - for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain)) - { - if (domain->header.type != 0) - show_vty_pce_subtlv_domain (vty, &domain->header); - } + for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) { + if (domain->header.type != 0) + show_vty_pce_subtlv_domain(vty, + &domain->header); + } - for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor)) - { - if (neighbor->header.type != 0) - show_vty_pce_subtlv_neighbor (vty, &neighbor->header); - } + for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) { + if (neighbor->header.type != 0) + show_vty_pce_subtlv_neighbor(vty, + &neighbor->header); + } - if (pce->pce_cap_flag.header.type != 0) - show_vty_pce_subtlv_cap_flag (vty, &pce->pce_cap_flag.header); + if (pce->pce_cap_flag.header.type != 0) + show_vty_pce_subtlv_cap_flag(vty, + &pce->pce_cap_flag.header); - } - else - { - vty_out (vty," Router Information is disabled on this router\n"); - } + } else { + vty_out(vty, + " Router Information is disabled on this router\n"); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Install new CLI commands */ -static void -ospf_router_info_register_vty (void) +static void ospf_router_info_register_vty(void) { - install_element (VIEW_NODE, &show_ip_ospf_router_info_cmd); - install_element (VIEW_NODE, &show_ip_ospf_router_info_pce_cmd); - - install_element (OSPF_NODE, &router_info_area_cmd); - install_element (OSPF_NODE, &no_router_info_cmd); - install_element (OSPF_NODE, &pce_address_cmd); - install_element (OSPF_NODE, &no_pce_address_cmd); - install_element (OSPF_NODE, &pce_path_scope_cmd); - install_element (OSPF_NODE, &no_pce_path_scope_cmd); - install_element (OSPF_NODE, &pce_domain_cmd); - install_element (OSPF_NODE, &no_pce_domain_cmd); - install_element (OSPF_NODE, &pce_neighbor_cmd); - install_element (OSPF_NODE, &no_pce_neighbor_cmd); - install_element (OSPF_NODE, &pce_cap_flag_cmd); - install_element (OSPF_NODE, &no_pce_cap_flag_cmd); - - return; + install_element(VIEW_NODE, &show_ip_ospf_router_info_cmd); + install_element(VIEW_NODE, &show_ip_ospf_router_info_pce_cmd); + + install_element(OSPF_NODE, &router_info_area_cmd); + install_element(OSPF_NODE, &no_router_info_cmd); + install_element(OSPF_NODE, &pce_address_cmd); + install_element(OSPF_NODE, &no_pce_address_cmd); + install_element(OSPF_NODE, &pce_path_scope_cmd); + install_element(OSPF_NODE, &no_pce_path_scope_cmd); + install_element(OSPF_NODE, &pce_domain_cmd); + install_element(OSPF_NODE, &no_pce_domain_cmd); + install_element(OSPF_NODE, &pce_neighbor_cmd); + install_element(OSPF_NODE, &no_pce_neighbor_cmd); + install_element(OSPF_NODE, &pce_cap_flag_cmd); + install_element(OSPF_NODE, &no_pce_cap_flag_cmd); + + return; } diff --git a/ospfd/ospf_ri.h b/ospfd/ospf_ri.h index c9ed3c56a..50221b25c 100644 --- a/ospfd/ospf_ri.h +++ b/ospfd/ospf_ri.h @@ -58,7 +58,8 @@ * | LS checksum | Length | V * +--------+--------+--------+--------+ --- * | Type | Length | A - * +--------+--------+--------+--------+ | TLV part for Router Information; Values might be + * +--------+--------+--------+--------+ | TLV part for Router Information; + * Values might be * | Values ... | V structured as a set of sub-TLVs. * +--------+--------+--------+--------+ --- */ @@ -67,10 +68,9 @@ * Following section defines TLV (tag, length, value) structures, * used for Router Information. */ -struct ri_tlv_header -{ - u_int16_t type; /* RI_TLV_XXX (see below) */ - u_int16_t length; /* Value portion only, in byte */ +struct ri_tlv_header { + u_int16_t type; /* RI_TLV_XXX (see below) */ + u_int16_t length; /* Value portion only, in byte */ }; #define RI_TLV_HDR_SIZE (sizeof (struct ri_tlv_header)) @@ -90,10 +90,9 @@ struct ri_tlv_header /* RFC4970: Router Information Capabilities TLV */ /* Mandatory */ #define RI_TLV_CAPABILITIES 1 -struct ri_tlv_router_cap -{ - struct ri_tlv_header header; /* Value length is 4 bytes. */ - u_int32_t value; +struct ri_tlv_router_cap { + struct ri_tlv_header header; /* Value length is 4 bytes. */ + u_int32_t value; }; #define RI_GRACE_RESTART 0x01 @@ -109,35 +108,37 @@ struct ri_tlv_router_cap /* RI PCE TLV */ #define RI_TLV_PCE 6 -struct ri_tlv_pce -{ - struct ri_tlv_header header; -/* A set of PCE-sub-TLVs will follow. */ +struct ri_tlv_pce { + struct ri_tlv_header header; + /* A set of PCE-sub-TLVs will follow. */ }; /* PCE Address Sub-TLV */ /* Mandatory */ #define RI_PCE_SUBTLV_ADDRESS 1 -struct ri_pce_subtlv_address -{ - struct ri_tlv_header header; /* Type = 1; Length is 8 (IPv4) or 20 (IPv6) bytes. */ +struct ri_pce_subtlv_address { + struct ri_tlv_header + header; /* Type = 1; Length is 8 (IPv4) or 20 (IPv6) bytes. */ + /* $FRR indent$ */ + /* clang-format off */ #define PCE_ADDRESS_LENGTH_IPV4 8 #define PCE_ADDRESS_LENGTH_IPV6 20 - struct - { - u_int16_t type; /* Address type: 1 = IPv4, 2 = IPv6 */ + struct { + u_int16_t type; /* Address type: 1 = IPv4, 2 = IPv6 */ + /* $FRR indent$ */ + /* clang-format off */ #define PCE_ADDRESS_TYPE_IPV4 1 #define PCE_ADDRESS_TYPE_IPV6 2 - u_int16_t reserved; - struct in_addr value; /* PCE address */ - } address; + u_int16_t reserved; + struct in_addr value; /* PCE address */ + } address; }; /* PCE Path-Scope Sub-TLV */ /* Mandatory */ #define RI_PCE_SUBTLV_PATH_SCOPE 2 -struct ri_pce_subtlv_path_scope -{ - struct ri_tlv_header header; /* Type = 2; Length = 4 bytes. */ - u_int32_t value; /* L, R, Rd, S, Sd, Y, PrefL, PrefR, PrefS and PrefY bits see RFC5088 page 9 */ +struct ri_pce_subtlv_path_scope { + struct ri_tlv_header header; /* Type = 2; Length = 4 bytes. */ + u_int32_t value; /* L, R, Rd, S, Sd, Y, PrefL, PrefR, PrefS and PrefY + bits see RFC5088 page 9 */ }; /* PCE Domain Sub-TLV */ /* Optional */ @@ -146,22 +147,20 @@ struct ri_pce_subtlv_path_scope #define PCE_DOMAIN_TYPE_AREA 1 #define PCE_DOMAIN_TYPE_AS 2 -struct ri_pce_subtlv_domain -{ - struct ri_tlv_header header; /* Type = 3; Length = 8 bytes. */ - u_int16_t type; /* Domain type: 1 = OSPF Area ID, 2 = AS Number */ - u_int16_t reserved; - u_int32_t value; +struct ri_pce_subtlv_domain { + struct ri_tlv_header header; /* Type = 3; Length = 8 bytes. */ + u_int16_t type; /* Domain type: 1 = OSPF Area ID, 2 = AS Number */ + u_int16_t reserved; + u_int32_t value; }; /* PCE Neighbor Sub-TLV */ /* Mandatory if R or S bit is set */ #define RI_PCE_SUBTLV_NEIGHBOR 4 -struct ri_pce_subtlv_neighbor -{ - struct ri_tlv_header header; /* Type = 4; Length = 8 bytes. */ - u_int16_t type; /* Domain type: 1 = OSPF Area ID, 2 = AS Number */ - u_int16_t reserved; - u_int32_t value; +struct ri_pce_subtlv_neighbor { + struct ri_tlv_header header; /* Type = 4; Length = 8 bytes. */ + u_int16_t type; /* Domain type: 1 = OSPF Area ID, 2 = AS Number */ + u_int16_t reserved; + u_int32_t value; }; /* PCE Capabilities Flags Sub-TLV */ /* Optional */ @@ -177,14 +176,13 @@ struct ri_pce_subtlv_neighbor #define PCE_CAP_PRIORIZATION 0x0080 #define PCE_CAP_MULTIPLE_REQ 0x0100 -struct ri_pce_subtlv_cap_flag -{ - struct ri_tlv_header header; /* Type = 5; Length = n x 4 bytes. */ - u_int32_t value; +struct ri_pce_subtlv_cap_flag { + struct ri_tlv_header header; /* Type = 5; Length = n x 4 bytes. */ + u_int32_t value; }; /* Prototypes. */ -extern int ospf_router_info_init (void); -extern void ospf_router_info_term (void); +extern int ospf_router_info_init(void); +extern void ospf_router_info_term(void); #endif /* _ZEBRA_OSPF_ROUTER_INFO_H */ diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c index fcd5f18a7..9c4dca2e2 100644 --- a/ospfd/ospf_route.c +++ b/ospfd/ospf_route.c @@ -39,1012 +39,979 @@ #include "ospfd/ospf_zebra.h" #include "ospfd/ospf_dump.h" -struct ospf_route * -ospf_route_new () +struct ospf_route *ospf_route_new() { - struct ospf_route *new; + struct ospf_route *new; - new = XCALLOC (MTYPE_OSPF_ROUTE, sizeof (struct ospf_route)); + new = XCALLOC(MTYPE_OSPF_ROUTE, sizeof(struct ospf_route)); - new->paths = list_new (); - new->paths->del = (void (*) (void *))ospf_path_free; + new->paths = list_new(); + new->paths->del = (void (*)(void *))ospf_path_free; - return new; + return new; } -void -ospf_route_free (struct ospf_route *or) +void ospf_route_free(struct ospf_route * or) { - if (or->paths) - list_delete (or->paths); + if (or->paths) + list_delete(or->paths); - XFREE (MTYPE_OSPF_ROUTE, or); + XFREE(MTYPE_OSPF_ROUTE, or); } -struct ospf_path * -ospf_path_new () +struct ospf_path *ospf_path_new() { - struct ospf_path *new; + struct ospf_path *new; - new = XCALLOC (MTYPE_OSPF_PATH, sizeof (struct ospf_path)); + new = XCALLOC(MTYPE_OSPF_PATH, sizeof(struct ospf_path)); - return new; + return new; } -static struct ospf_path * -ospf_path_dup (struct ospf_path *path) +static struct ospf_path *ospf_path_dup(struct ospf_path *path) { - struct ospf_path *new; + struct ospf_path *new; - new = ospf_path_new (); - memcpy (new, path, sizeof (struct ospf_path)); + new = ospf_path_new(); + memcpy(new, path, sizeof(struct ospf_path)); - return new; + return new; } -void -ospf_path_free (struct ospf_path *op) +void ospf_path_free(struct ospf_path *op) { - XFREE (MTYPE_OSPF_PATH, op); + XFREE(MTYPE_OSPF_PATH, op); } -void -ospf_route_delete (struct route_table *rt) +void ospf_route_delete(struct route_table *rt) { - struct route_node *rn; - struct ospf_route *or; - - for (rn = route_top (rt); rn; rn = route_next (rn)) - if ((or = rn->info) != NULL) - { - if (or->type == OSPF_DESTINATION_NETWORK) - ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, - or); - else if (or->type == OSPF_DESTINATION_DISCARD) - ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p); - } + struct route_node *rn; + struct ospf_route * or ; + + for (rn = route_top(rt); rn; rn = route_next(rn)) + if ((or = rn->info) != NULL) { + if (or->type == OSPF_DESTINATION_NETWORK) + ospf_zebra_delete((struct prefix_ipv4 *)&rn->p, + or); + else if (or->type == OSPF_DESTINATION_DISCARD) + ospf_zebra_delete_discard( + (struct prefix_ipv4 *)&rn->p); + } } -void -ospf_route_table_free (struct route_table *rt) +void ospf_route_table_free(struct route_table *rt) { - struct route_node *rn; - struct ospf_route *or; + struct route_node *rn; + struct ospf_route * or ; - for (rn = route_top (rt); rn; rn = route_next (rn)) - if ((or = rn->info) != NULL) - { - ospf_route_free (or); + for (rn = route_top(rt); rn; rn = route_next(rn)) + if ((or = rn->info) != NULL) { + ospf_route_free(or); - rn->info = NULL; - route_unlock_node (rn); - } + rn->info = NULL; + route_unlock_node(rn); + } - route_table_finish (rt); + route_table_finish(rt); } /* If a prefix exists in the new routing table, then return 1, otherwise return 0. Since the ZEBRA-RIB does an implicit withdraw, it is not necessary to send a delete, an add later will act like an implicit delete. */ -static int -ospf_route_exist_new_table (struct route_table *rt, struct prefix_ipv4 *prefix) +static int ospf_route_exist_new_table(struct route_table *rt, + struct prefix_ipv4 *prefix) { - struct route_node *rn; + struct route_node *rn; - assert (rt); - assert (prefix); + assert(rt); + assert(prefix); - rn = route_node_lookup (rt, (struct prefix *) prefix); - if (!rn) { - return 0; - } - route_unlock_node (rn); + rn = route_node_lookup(rt, (struct prefix *)prefix); + if (!rn) { + return 0; + } + route_unlock_node(rn); - if (!rn->info) { - return 0; - } + if (!rn->info) { + return 0; + } - return 1; + return 1; } /* If a prefix and a nexthop match any route in the routing table, then return 1, otherwise return 0. */ -int -ospf_route_match_same (struct route_table *rt, struct prefix_ipv4 *prefix, - struct ospf_route *newor) +int ospf_route_match_same(struct route_table *rt, struct prefix_ipv4 *prefix, + struct ospf_route *newor) { - struct route_node *rn; - struct ospf_route *or; - struct ospf_path *op; - struct ospf_path *newop; - struct listnode *n1; - struct listnode *n2; - - if (! rt || ! prefix) - return 0; - - rn = route_node_lookup (rt, (struct prefix *) prefix); - if (! rn || ! rn->info) - return 0; - - route_unlock_node (rn); - - or = rn->info; - if (or->type == newor->type && or->cost == newor->cost) - { - if (or->type == OSPF_DESTINATION_NETWORK) - { - if (or->paths->count != newor->paths->count) - return 0; - - /* Check each path. */ - for (n1 = listhead (or->paths), n2 = listhead (newor->paths); - n1 && n2; n1 = listnextnode (n1), n2 = listnextnode (n2)) - { - op = listgetdata (n1); - newop = listgetdata (n2); - - if (! IPV4_ADDR_SAME (&op->nexthop, &newop->nexthop)) - return 0; - if (op->ifindex != newop->ifindex) - return 0; - } - return 1; - } - else if (prefix_same (&rn->p, (struct prefix *) prefix)) - return 1; - } - return 0; + struct route_node *rn; + struct ospf_route * or ; + struct ospf_path *op; + struct ospf_path *newop; + struct listnode *n1; + struct listnode *n2; + + if (!rt || !prefix) + return 0; + + rn = route_node_lookup(rt, (struct prefix *)prefix); + if (!rn || !rn->info) + return 0; + + route_unlock_node(rn); + + or = rn->info; + if (or->type == newor->type && or->cost == newor->cost) { + if (or->type == OSPF_DESTINATION_NETWORK) { + if (or->paths->count != newor->paths->count) + return 0; + + /* Check each path. */ + for (n1 = listhead(or->paths), + n2 = listhead(newor->paths); + n1 && n2; + n1 = listnextnode(n1), n2 = listnextnode(n2)) { + op = listgetdata(n1); + newop = listgetdata(n2); + + if (!IPV4_ADDR_SAME(&op->nexthop, + &newop->nexthop)) + return 0; + if (op->ifindex != newop->ifindex) + return 0; + } + return 1; + } else if (prefix_same(&rn->p, (struct prefix *)prefix)) + return 1; + } + return 0; } /* delete routes generated from AS-External routes if there is a inter/intra * area route */ -static void -ospf_route_delete_same_ext(struct route_table *external_routes, - struct route_table *routes) +static void ospf_route_delete_same_ext(struct route_table *external_routes, + struct route_table *routes) { - struct route_node *rn, - *ext_rn; - - if ( (external_routes == NULL) || (routes == NULL) ) - return; - - /* Remove deleted routes */ - for ( rn = route_top (routes); rn; rn = route_next (rn) ) - { - if (rn && rn->info) - { - struct prefix_ipv4 *p = (struct prefix_ipv4 *)(&rn->p); - if ( (ext_rn = route_node_lookup (external_routes, (struct prefix *)p)) ) - { - if (ext_rn->info) - { - ospf_zebra_delete (p, ext_rn->info); - ospf_route_free( ext_rn->info); - ext_rn->info = NULL; - } - route_unlock_node (ext_rn); - } - } - } + struct route_node *rn, *ext_rn; + + if ((external_routes == NULL) || (routes == NULL)) + return; + + /* Remove deleted routes */ + for (rn = route_top(routes); rn; rn = route_next(rn)) { + if (rn && rn->info) { + struct prefix_ipv4 *p = (struct prefix_ipv4 *)(&rn->p); + if ((ext_rn = route_node_lookup(external_routes, + (struct prefix *)p))) { + if (ext_rn->info) { + ospf_zebra_delete(p, ext_rn->info); + ospf_route_free(ext_rn->info); + ext_rn->info = NULL; + } + route_unlock_node(ext_rn); + } + } + } } /* rt: Old, cmprt: New */ -static void -ospf_route_delete_uniq (struct route_table *rt, struct route_table *cmprt) +static void ospf_route_delete_uniq(struct route_table *rt, + struct route_table *cmprt) { - struct route_node *rn; - struct ospf_route *or; - - for (rn = route_top (rt); rn; rn = route_next (rn)) - if ((or = rn->info) != NULL) - if (or->path_type == OSPF_PATH_INTRA_AREA || - or->path_type == OSPF_PATH_INTER_AREA) - { - if (or->type == OSPF_DESTINATION_NETWORK) - { - if (! ospf_route_exist_new_table (cmprt, - (struct prefix_ipv4 *) &rn->p)) - ospf_zebra_delete ((struct prefix_ipv4 *) &rn->p, or); - } - else if (or->type == OSPF_DESTINATION_DISCARD) - if (! ospf_route_exist_new_table (cmprt, - (struct prefix_ipv4 *) &rn->p)) - ospf_zebra_delete_discard ((struct prefix_ipv4 *) &rn->p); - } + struct route_node *rn; + struct ospf_route * or ; + + for (rn = route_top(rt); rn; rn = route_next(rn)) + if ((or = rn->info) != NULL) + if (or->path_type == OSPF_PATH_INTRA_AREA || + or->path_type == OSPF_PATH_INTER_AREA) { + if (or->type == OSPF_DESTINATION_NETWORK) { + if (!ospf_route_exist_new_table( + cmprt, + (struct prefix_ipv4 *)&rn + ->p)) + ospf_zebra_delete( + (struct prefix_ipv4 + *)&rn->p, + or); + } else if (or->type == OSPF_DESTINATION_DISCARD) + if (!ospf_route_exist_new_table( + cmprt, + (struct prefix_ipv4 *)&rn + ->p)) + ospf_zebra_delete_discard( + (struct prefix_ipv4 + *)&rn->p); + } } /* Install routes to table. */ -void -ospf_route_install (struct ospf *ospf, struct route_table *rt) +void ospf_route_install(struct ospf *ospf, struct route_table *rt) { - struct route_node *rn; - struct ospf_route *or; - - /* rt contains new routing table, new_table contains an old one. - updating pointers */ - if (ospf->old_table) - ospf_route_table_free (ospf->old_table); - - ospf->old_table = ospf->new_table; - ospf->new_table = rt; - - /* Delete old routes. */ - if (ospf->old_table) - ospf_route_delete_uniq (ospf->old_table, rt); - if (ospf->old_external_route) - ospf_route_delete_same_ext (ospf->old_external_route, rt); - - /* Install new routes. */ - for (rn = route_top (rt); rn; rn = route_next (rn)) - if ((or = rn->info) != NULL) - { - if (or->type == OSPF_DESTINATION_NETWORK) - { - if (! ospf_route_match_same (ospf->old_table, - (struct prefix_ipv4 *)&rn->p, or)) - ospf_zebra_add ((struct prefix_ipv4 *) &rn->p, or); - } - else if (or->type == OSPF_DESTINATION_DISCARD) - if (! ospf_route_match_same (ospf->old_table, - (struct prefix_ipv4 *) &rn->p, or)) - ospf_zebra_add_discard ((struct prefix_ipv4 *) &rn->p); - } + struct route_node *rn; + struct ospf_route * or ; + + /* rt contains new routing table, new_table contains an old one. + updating pointers */ + if (ospf->old_table) + ospf_route_table_free(ospf->old_table); + + ospf->old_table = ospf->new_table; + ospf->new_table = rt; + + /* Delete old routes. */ + if (ospf->old_table) + ospf_route_delete_uniq(ospf->old_table, rt); + if (ospf->old_external_route) + ospf_route_delete_same_ext(ospf->old_external_route, rt); + + /* Install new routes. */ + for (rn = route_top(rt); rn; rn = route_next(rn)) + if ((or = rn->info) != NULL) { + if (or->type == OSPF_DESTINATION_NETWORK) { + if (!ospf_route_match_same( + ospf->old_table, + (struct prefix_ipv4 *)&rn->p, or)) + ospf_zebra_add( + (struct prefix_ipv4 *)&rn->p, + or); + } else if (or->type == OSPF_DESTINATION_DISCARD) + if (!ospf_route_match_same( + ospf->old_table, + (struct prefix_ipv4 *)&rn->p, or)) + ospf_zebra_add_discard( + (struct prefix_ipv4 *)&rn->p); + } } /* RFC2328 16.1. (4). For "router". */ -void -ospf_intra_add_router (struct route_table *rt, struct vertex *v, - struct ospf_area *area) +void ospf_intra_add_router(struct route_table *rt, struct vertex *v, + struct ospf_area *area) { - struct route_node *rn; - struct ospf_route *or; - struct prefix_ipv4 p; - struct router_lsa *lsa; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_intra_add_router: Start"); - - lsa = (struct router_lsa *) v->lsa; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_intra_add_router: LS ID: %s", - inet_ntoa (lsa->header.id)); - - if (!OSPF_IS_AREA_BACKBONE(area)) - ospf_vl_up_check (area, lsa->header.id, v); - - if (!CHECK_FLAG (lsa->flags, ROUTER_LSA_SHORTCUT)) - area->shortcut_capability = 0; - - /* If the newly added vertex is an area border router or AS boundary - router, a routing table entry is added whose destination type is - "router". */ - if (! IS_ROUTER_LSA_BORDER (lsa) && ! IS_ROUTER_LSA_EXTERNAL (lsa)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_intra_add_router: " - "this router is neither ASBR nor ABR, skipping it"); - return; - } - - /* Update ABR and ASBR count in this area. */ - if (IS_ROUTER_LSA_BORDER (lsa)) - area->abr_count++; - if (IS_ROUTER_LSA_EXTERNAL (lsa)) - area->asbr_count++; - - /* The Options field found in the associated router-LSA is copied - into the routing table entry's Optional capabilities field. Call - the newly added vertex Router X. */ - or = ospf_route_new (); - - or->id = v->id; - or->u.std.area_id = area->area_id; - or->u.std.external_routing = area->external_routing; - or->path_type = OSPF_PATH_INTRA_AREA; - or->cost = v->distance; - or->type = OSPF_DESTINATION_ROUTER; - or->u.std.origin = (struct lsa_header *) lsa; - or->u.std.options = lsa->header.options; - or->u.std.flags = lsa->flags; - - /* If Router X is the endpoint of one of the calculating router's - virtual links, and the virtual link uses Area A as Transit area: - the virtual link is declared up, the IP address of the virtual - interface is set to the IP address of the outgoing interface - calculated above for Router X, and the virtual neighbor's IP - address is set to Router X's interface address (contained in - Router X's router-LSA) that points back to the root of the - shortest- path tree; equivalently, this is the interface that - points back to Router X's parent vertex on the shortest-path tree - (similar to the calculation in Section 16.1.1). */ - - p.family = AF_INET; - p.prefix = v->id; - p.prefixlen = IPV4_MAX_BITLEN; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_intra_add_router: talking about %s/%d", - inet_ntoa (p.prefix), p.prefixlen); - - rn = route_node_get (rt, (struct prefix *) &p); - - /* Note that we keep all routes to ABRs and ASBRs, not only the best */ - if (rn->info == NULL) - rn->info = list_new (); - else - route_unlock_node (rn); - - ospf_route_copy_nexthops_from_vertex (or, v); - - listnode_add (rn->info, or); - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_intra_add_router: Stop"); + struct route_node *rn; + struct ospf_route * or ; + struct prefix_ipv4 p; + struct router_lsa *lsa; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_intra_add_router: Start"); + + lsa = (struct router_lsa *)v->lsa; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_intra_add_router: LS ID: %s", + inet_ntoa(lsa->header.id)); + + if (!OSPF_IS_AREA_BACKBONE(area)) + ospf_vl_up_check(area, lsa->header.id, v); + + if (!CHECK_FLAG(lsa->flags, ROUTER_LSA_SHORTCUT)) + area->shortcut_capability = 0; + + /* If the newly added vertex is an area border router or AS boundary + router, a routing table entry is added whose destination type is + "router". */ + if (!IS_ROUTER_LSA_BORDER(lsa) && !IS_ROUTER_LSA_EXTERNAL(lsa)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_intra_add_router: " + "this router is neither ASBR nor ABR, skipping it"); + return; + } + + /* Update ABR and ASBR count in this area. */ + if (IS_ROUTER_LSA_BORDER(lsa)) + area->abr_count++; + if (IS_ROUTER_LSA_EXTERNAL(lsa)) + area->asbr_count++; + + /* The Options field found in the associated router-LSA is copied + into the routing table entry's Optional capabilities field. Call + the newly added vertex Router X. */ + or = ospf_route_new(); + + or->id = v->id; + or->u.std.area_id = area->area_id; + or->u.std.external_routing = area->external_routing; + or->path_type = OSPF_PATH_INTRA_AREA; + or->cost = v->distance; + or->type = OSPF_DESTINATION_ROUTER; + or->u.std.origin = (struct lsa_header *)lsa; + or->u.std.options = lsa->header.options; + or->u.std.flags = lsa->flags; + + /* If Router X is the endpoint of one of the calculating router's + virtual links, and the virtual link uses Area A as Transit area: + the virtual link is declared up, the IP address of the virtual + interface is set to the IP address of the outgoing interface + calculated above for Router X, and the virtual neighbor's IP + address is set to Router X's interface address (contained in + Router X's router-LSA) that points back to the root of the + shortest- path tree; equivalently, this is the interface that + points back to Router X's parent vertex on the shortest-path tree + (similar to the calculation in Section 16.1.1). */ + + p.family = AF_INET; + p.prefix = v->id; + p.prefixlen = IPV4_MAX_BITLEN; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_intra_add_router: talking about %s/%d", + inet_ntoa(p.prefix), p.prefixlen); + + rn = route_node_get(rt, (struct prefix *)&p); + + /* Note that we keep all routes to ABRs and ASBRs, not only the best */ + if (rn->info == NULL) + rn->info = list_new(); + else + route_unlock_node(rn); + + ospf_route_copy_nexthops_from_vertex(or, v); + + listnode_add(rn->info, or); + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_intra_add_router: Stop"); } /* RFC2328 16.1. (4). For transit network. */ -void -ospf_intra_add_transit (struct route_table *rt, struct vertex *v, - struct ospf_area *area) +void ospf_intra_add_transit(struct route_table *rt, struct vertex *v, + struct ospf_area *area) { - struct route_node *rn; - struct ospf_route *or; - struct prefix_ipv4 p; - struct network_lsa *lsa; - - lsa = (struct network_lsa*) v->lsa; - - /* If the newly added vertex is a transit network, the routing table - entry for the network is located. The entry's Destination ID is - the IP network number, which can be obtained by masking the - Vertex ID (Link State ID) with its associated subnet mask (found - in the body of the associated network-LSA). */ - p.family = AF_INET; - p.prefix = v->id; - p.prefixlen = ip_masklen (lsa->mask); - apply_mask_ipv4 (&p); - - rn = route_node_get (rt, (struct prefix *) &p); - - /* If the routing table entry already exists (i.e., there is already - an intra-area route to the destination installed in the routing - table), multiple vertices have mapped to the same IP network. - For example, this can occur when a new Designated Router is being - established. In this case, the current routing table entry - should be overwritten if and only if the newly found path is just - as short and the current routing table entry's Link State Origin - has a smaller Link State ID than the newly added vertex' LSA. */ - if (rn->info) - { - struct ospf_route *cur_or; - - route_unlock_node (rn); - cur_or = rn->info; - - if (v->distance > cur_or->cost || - IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) > 0) - return; - - ospf_route_free (rn->info); - } - - or = ospf_route_new (); - - or->id = v->id; - or->u.std.area_id = area->area_id; - or->u.std.external_routing = area->external_routing; - or->path_type = OSPF_PATH_INTRA_AREA; - or->cost = v->distance; - or->type = OSPF_DESTINATION_NETWORK; - or->u.std.origin = (struct lsa_header *) lsa; - - ospf_route_copy_nexthops_from_vertex (or, v); - - rn->info = or; + struct route_node *rn; + struct ospf_route * or ; + struct prefix_ipv4 p; + struct network_lsa *lsa; + + lsa = (struct network_lsa *)v->lsa; + + /* If the newly added vertex is a transit network, the routing table + entry for the network is located. The entry's Destination ID is + the IP network number, which can be obtained by masking the + Vertex ID (Link State ID) with its associated subnet mask (found + in the body of the associated network-LSA). */ + p.family = AF_INET; + p.prefix = v->id; + p.prefixlen = ip_masklen(lsa->mask); + apply_mask_ipv4(&p); + + rn = route_node_get(rt, (struct prefix *)&p); + + /* If the routing table entry already exists (i.e., there is already + an intra-area route to the destination installed in the routing + table), multiple vertices have mapped to the same IP network. + For example, this can occur when a new Designated Router is being + established. In this case, the current routing table entry + should be overwritten if and only if the newly found path is just + as short and the current routing table entry's Link State Origin + has a smaller Link State ID than the newly added vertex' LSA. */ + if (rn->info) { + struct ospf_route *cur_or; + + route_unlock_node(rn); + cur_or = rn->info; + + if (v->distance > cur_or->cost + || IPV4_ADDR_CMP(&cur_or->u.std.origin->id, &lsa->header.id) + > 0) + return; + + ospf_route_free(rn->info); + } + + or = ospf_route_new(); + + or->id = v->id; + or->u.std.area_id = area->area_id; + or->u.std.external_routing = area->external_routing; + or->path_type = OSPF_PATH_INTRA_AREA; + or->cost = v->distance; + or->type = OSPF_DESTINATION_NETWORK; + or->u.std.origin = (struct lsa_header *)lsa; + + ospf_route_copy_nexthops_from_vertex(or, v); + + rn->info = or ; } /* RFC2328 16.1. second stage. */ -void -ospf_intra_add_stub (struct route_table *rt, struct router_lsa_link *link, - struct vertex *v, struct ospf_area *area, - int parent_is_root, int lsa_pos) +void ospf_intra_add_stub(struct route_table *rt, struct router_lsa_link *link, + struct vertex *v, struct ospf_area *area, + int parent_is_root, int lsa_pos) { - u_int32_t cost; - struct route_node *rn; - struct ospf_route *or; - struct prefix_ipv4 p; - struct router_lsa *lsa; - struct ospf_interface *oi; - struct ospf_path *path; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_intra_add_stub(): Start"); - - lsa = (struct router_lsa *) v->lsa; - - p.family = AF_INET; - p.prefix = link->link_id; - p.prefixlen = ip_masklen (link->link_data); - apply_mask_ipv4 (&p); - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_intra_add_stub(): processing route to %s/%d", - inet_ntoa (p.prefix), p.prefixlen); - - /* (1) Calculate the distance D of stub network from the root. D is - equal to the distance from the root to the router vertex - (calculated in stage 1), plus the stub network link's advertised - cost. */ - cost = v->distance + ntohs (link->m[0].metric); - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_intra_add_stub(): calculated cost is %d + %d = %d", - v->distance, ntohs(link->m[0].metric), cost); - - /* PtP links with /32 masks adds host routes to remote, directly - * connected hosts, see RFC 2328, 12.4.1.1, Option 1. - * Such routes can just be ignored for the sake of tidyness. - */ - if (parent_is_root && link->link_data.s_addr == 0xffffffff && - ospf_if_lookup_by_local_addr (area->ospf, NULL, link->link_id)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("%s: ignoring host route %s/32 to self.", - __func__, inet_ntoa (link->link_id)); - return; - } - - rn = route_node_get (rt, (struct prefix *) &p); - - /* Lookup current routing table. */ - if (rn->info) - { - struct ospf_route *cur_or; - - route_unlock_node (rn); - - cur_or = rn->info; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_intra_add_stub(): " - "another route to the same prefix found with cost %u", - cur_or->cost); - - /* Compare this distance to the current best cost to the stub - network. This is done by looking up the stub network's - current routing table entry. If the calculated distance D is - larger, go on to examine the next stub network link in the - LSA. */ - if (cost > cur_or->cost) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_intra_add_stub(): old route is better, exit"); - return; + u_int32_t cost; + struct route_node *rn; + struct ospf_route * or ; + struct prefix_ipv4 p; + struct router_lsa *lsa; + struct ospf_interface *oi; + struct ospf_path *path; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_intra_add_stub(): Start"); + + lsa = (struct router_lsa *)v->lsa; + + p.family = AF_INET; + p.prefix = link->link_id; + p.prefixlen = ip_masklen(link->link_data); + apply_mask_ipv4(&p); + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_intra_add_stub(): processing route to %s/%d", + inet_ntoa(p.prefix), p.prefixlen); + + /* (1) Calculate the distance D of stub network from the root. D is + equal to the distance from the root to the router vertex + (calculated in stage 1), plus the stub network link's advertised + cost. */ + cost = v->distance + ntohs(link->m[0].metric); + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_intra_add_stub(): calculated cost is %d + %d = %d", + v->distance, ntohs(link->m[0].metric), cost); + + /* PtP links with /32 masks adds host routes to remote, directly + * connected hosts, see RFC 2328, 12.4.1.1, Option 1. + * Such routes can just be ignored for the sake of tidyness. + */ + if (parent_is_root && link->link_data.s_addr == 0xffffffff + && ospf_if_lookup_by_local_addr(area->ospf, NULL, link->link_id)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: ignoring host route %s/32 to self.", + __func__, inet_ntoa(link->link_id)); + return; } - /* (2) If this step is reached, the stub network's routing table - entry must be updated. Calculate the set of next hops that - would result from using the stub network link. This - calculation is shown in Section 16.1.1; input to this - calculation is the destination (the stub network) and the - parent vertex (the router vertex). If the distance D is the - same as the current routing table cost, simply add this set - of next hops to the routing table entry's list of next hops. - In this case, the routing table already has a Link State - Origin. If this Link State Origin is a router-LSA whose Link - State ID is smaller than V's Router ID, reset the Link State - Origin to V's router-LSA. */ - - if (cost == cur_or->cost) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_intra_add_stub(): routes are equal, merge"); + rn = route_node_get(rt, (struct prefix *)&p); - ospf_route_copy_nexthops_from_vertex (cur_or, v); + /* Lookup current routing table. */ + if (rn->info) { + struct ospf_route *cur_or; - if (IPV4_ADDR_CMP (&cur_or->u.std.origin->id, &lsa->header.id) < 0) - cur_or->u.std.origin = (struct lsa_header *) lsa; - return; - } + route_unlock_node(rn); - /* Otherwise D is smaller than the routing table cost. - Overwrite the current routing table entry by setting the - routing table entry's cost to D, and by setting the entry's - list of next hops to the newly calculated set. Set the - routing table entry's Link State Origin to V's router-LSA. - Then go on to examine the next stub network link. */ + cur_or = rn->info; - if (cost < cur_or->cost) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_intra_add_stub(): new route is better, set it"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_intra_add_stub(): " + "another route to the same prefix found with cost %u", + cur_or->cost); + + /* Compare this distance to the current best cost to the stub + network. This is done by looking up the stub network's + current routing table entry. If the calculated distance D is + larger, go on to examine the next stub network link in the + LSA. */ + if (cost > cur_or->cost) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_intra_add_stub(): old route is better, exit"); + return; + } - cur_or->cost = cost; + /* (2) If this step is reached, the stub network's routing table + entry must be updated. Calculate the set of next hops that + would result from using the stub network link. This + calculation is shown in Section 16.1.1; input to this + calculation is the destination (the stub network) and the + parent vertex (the router vertex). If the distance D is the + same as the current routing table cost, simply add this set + of next hops to the routing table entry's list of next hops. + In this case, the routing table already has a Link State + Origin. If this Link State Origin is a router-LSA whose Link + State ID is smaller than V's Router ID, reset the Link State + Origin to V's router-LSA. */ + + if (cost == cur_or->cost) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_intra_add_stub(): routes are equal, merge"); + + ospf_route_copy_nexthops_from_vertex(cur_or, v); + + if (IPV4_ADDR_CMP(&cur_or->u.std.origin->id, + &lsa->header.id) + < 0) + cur_or->u.std.origin = (struct lsa_header *)lsa; + return; + } - list_delete_all_node (cur_or->paths); + /* Otherwise D is smaller than the routing table cost. + Overwrite the current routing table entry by setting the + routing table entry's cost to D, and by setting the entry's + list of next hops to the newly calculated set. Set the + routing table entry's Link State Origin to V's router-LSA. + Then go on to examine the next stub network link. */ - ospf_route_copy_nexthops_from_vertex (cur_or, v); + if (cost < cur_or->cost) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_intra_add_stub(): new route is better, set it"); - cur_or->u.std.origin = (struct lsa_header *) lsa; - return; - } - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_intra_add_stub(): installing new route"); - - or = ospf_route_new (); - - or->id = v->id; - or->u.std.area_id = area->area_id; - or->u.std.external_routing = area->external_routing; - or->path_type = OSPF_PATH_INTRA_AREA; - or->cost = cost; - or->type = OSPF_DESTINATION_NETWORK; - or->u.std.origin = (struct lsa_header *) lsa; - - /* Nexthop is depend on connection type. */ - if (v != area->spf) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_intra_add_stub(): this network is on remote router"); - ospf_route_copy_nexthops_from_vertex (or, v); - } - else - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_intra_add_stub(): this network is on this router"); - - if ((oi = ospf_if_lookup_by_lsa_pos (area, lsa_pos))) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_intra_add_stub(): the interface is %s", - IF_NAME (oi)); - - path = ospf_path_new (); - path->nexthop.s_addr = 0; - path->ifindex = oi->ifp->ifindex; - if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) - path->unnumbered = 1; - listnode_add (or->paths, path); + cur_or->cost = cost; + + list_delete_all_node(cur_or->paths); + + ospf_route_copy_nexthops_from_vertex(cur_or, v); + + cur_or->u.std.origin = (struct lsa_header *)lsa; + return; + } } - else - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_intra_add_stub(): where's the interface ?"); + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_intra_add_stub(): installing new route"); + + or = ospf_route_new(); + + or->id = v->id; + or->u.std.area_id = area->area_id; + or->u.std.external_routing = area->external_routing; + or->path_type = OSPF_PATH_INTRA_AREA; + or->cost = cost; + or->type = OSPF_DESTINATION_NETWORK; + or->u.std.origin = (struct lsa_header *)lsa; + + /* Nexthop is depend on connection type. */ + if (v != area->spf) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_intra_add_stub(): this network is on remote router"); + ospf_route_copy_nexthops_from_vertex(or, v); + } else { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_intra_add_stub(): this network is on this router"); + + if ((oi = ospf_if_lookup_by_lsa_pos(area, lsa_pos))) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_intra_add_stub(): the interface is %s", + IF_NAME(oi)); + + path = ospf_path_new(); + path->nexthop.s_addr = 0; + path->ifindex = oi->ifp->ifindex; + if (CHECK_FLAG(oi->connected->flags, + ZEBRA_IFA_UNNUMBERED)) + path->unnumbered = 1; + listnode_add(or->paths, path); + } else { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_intra_add_stub(): where's the interface ?"); + } } - } - rn->info = or; + rn->info = or ; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug("ospf_intra_add_stub(): Stop"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_intra_add_stub(): Stop"); } -const char *ospf_path_type_str[] = -{ - "unknown-type", - "intra-area", - "inter-area", - "type1-external", - "type2-external" -}; - -void -ospf_route_table_dump (struct route_table *rt) +const char *ospf_path_type_str[] = {"unknown-type", "intra-area", "inter-area", + "type1-external", "type2-external"}; + +void ospf_route_table_dump(struct route_table *rt) { - struct route_node *rn; - struct ospf_route *or; - char buf1[BUFSIZ]; - char buf2[BUFSIZ]; - struct listnode *pnode; - struct ospf_path *path; + struct route_node *rn; + struct ospf_route * or ; + char buf1[BUFSIZ]; + char buf2[BUFSIZ]; + struct listnode *pnode; + struct ospf_path *path; #if 0 zlog_debug ("Type Dest Area Path Type Cost Next Adv."); zlog_debug (" Hop(s) Router(s)"); #endif /* 0 */ - zlog_debug ("========== OSPF routing table =========="); - for (rn = route_top (rt); rn; rn = route_next (rn)) - if ((or = rn->info) != NULL) - { - if (or->type == OSPF_DESTINATION_NETWORK) - { - zlog_debug ("N %s/%d\t%s\t%s\t%d", - inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ), - rn->p.prefixlen, - inet_ntop (AF_INET, &or->u.std.area_id, buf2, - BUFSIZ), - ospf_path_type_str[or->path_type], - or->cost); - for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path)) - zlog_debug (" -> %s", inet_ntoa (path->nexthop)); - } - else - zlog_debug ("R %s\t%s\t%s\t%d", - inet_ntop (AF_INET, &rn->p.u.prefix4, buf1, BUFSIZ), - inet_ntop (AF_INET, &or->u.std.area_id, buf2, - BUFSIZ), - ospf_path_type_str[or->path_type], - or->cost); - } - zlog_debug ("========================================"); + zlog_debug("========== OSPF routing table =========="); + for (rn = route_top(rt); rn; rn = route_next(rn)) + if ((or = rn->info) != NULL) { + if (or->type == OSPF_DESTINATION_NETWORK) { + zlog_debug("N %s/%d\t%s\t%s\t%d", + inet_ntop(AF_INET, &rn->p.u.prefix4, + buf1, BUFSIZ), + rn->p.prefixlen, + inet_ntop(AF_INET, + & or->u.std.area_id, buf2, + BUFSIZ), + ospf_path_type_str[or->path_type], + or->cost); + for (ALL_LIST_ELEMENTS_RO(or->paths, pnode, + path)) + zlog_debug(" -> %s", + inet_ntoa(path->nexthop)); + } else + zlog_debug("R %s\t%s\t%s\t%d", + inet_ntop(AF_INET, &rn->p.u.prefix4, + buf1, BUFSIZ), + inet_ntop(AF_INET, + & or->u.std.area_id, buf2, + BUFSIZ), + ospf_path_type_str[or->path_type], + or->cost); + } + zlog_debug("========================================"); } /* This is 16.4.1 implementation. o Intra-area paths using non-backbone areas are always the most preferred. o The other paths, intra-area backbone paths and inter-area paths, are of equal preference. */ -static int -ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1, - struct ospf_route *r2) +static int ospf_asbr_route_cmp(struct ospf *ospf, struct ospf_route *r1, + struct ospf_route *r2) { - u_char r1_type, r2_type; + u_char r1_type, r2_type; - r1_type = r1->path_type; - r2_type = r2->path_type; + r1_type = r1->path_type; + r2_type = r2->path_type; - /* r1/r2 itself is backbone, and it's Inter-area path. */ - if (OSPF_IS_AREA_ID_BACKBONE (r1->u.std.area_id)) - r1_type = OSPF_PATH_INTER_AREA; - if (OSPF_IS_AREA_ID_BACKBONE (r2->u.std.area_id)) - r2_type = OSPF_PATH_INTER_AREA; + /* r1/r2 itself is backbone, and it's Inter-area path. */ + if (OSPF_IS_AREA_ID_BACKBONE(r1->u.std.area_id)) + r1_type = OSPF_PATH_INTER_AREA; + if (OSPF_IS_AREA_ID_BACKBONE(r2->u.std.area_id)) + r2_type = OSPF_PATH_INTER_AREA; - return (r1_type - r2_type); + return (r1_type - r2_type); } /* Compare two routes. ret < 0 -- r1 is better. ret == 0 -- r1 and r2 are the same. ret > 0 -- r2 is better. */ -int -ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1, - struct ospf_route *r2) +int ospf_route_cmp(struct ospf *ospf, struct ospf_route *r1, + struct ospf_route *r2) { - int ret = 0; - - /* Path types of r1 and r2 are not the same. */ - if ((ret = (r1->path_type - r2->path_type))) - return ret; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Route[Compare]: Path types are the same."); - /* Path types are the same, compare any cost. */ - switch (r1->path_type) - { - case OSPF_PATH_INTRA_AREA: - case OSPF_PATH_INTER_AREA: - break; - case OSPF_PATH_TYPE1_EXTERNAL: - if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE)) - { - ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr); - if (ret != 0) - return ret; - } - break; - case OSPF_PATH_TYPE2_EXTERNAL: - if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost))) - return ret; - - if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE)) - { - ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr); - if (ret != 0) - return ret; + int ret = 0; + + /* Path types of r1 and r2 are not the same. */ + if ((ret = (r1->path_type - r2->path_type))) + return ret; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Route[Compare]: Path types are the same."); + /* Path types are the same, compare any cost. */ + switch (r1->path_type) { + case OSPF_PATH_INTRA_AREA: + case OSPF_PATH_INTER_AREA: + break; + case OSPF_PATH_TYPE1_EXTERNAL: + if (!CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) { + ret = ospf_asbr_route_cmp(ospf, r1->u.ext.asbr, + r2->u.ext.asbr); + if (ret != 0) + return ret; + } + break; + case OSPF_PATH_TYPE2_EXTERNAL: + if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost))) + return ret; + + if (!CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) { + ret = ospf_asbr_route_cmp(ospf, r1->u.ext.asbr, + r2->u.ext.asbr); + if (ret != 0) + return ret; + } + break; } - break; - } - /* Anyway, compare the costs. */ - return (r1->cost - r2->cost); + /* Anyway, compare the costs. */ + return (r1->cost - r2->cost); } -static int -ospf_path_exist (struct list *plist, struct in_addr nexthop, - struct ospf_interface *oi) +static int ospf_path_exist(struct list *plist, struct in_addr nexthop, + struct ospf_interface *oi) { - struct listnode *node, *nnode; - struct ospf_path *path; + struct listnode *node, *nnode; + struct ospf_path *path; - for (ALL_LIST_ELEMENTS (plist, node, nnode, path)) - if (IPV4_ADDR_SAME (&path->nexthop, &nexthop) && - path->ifindex == oi->ifp->ifindex) - return 1; + for (ALL_LIST_ELEMENTS(plist, node, nnode, path)) + if (IPV4_ADDR_SAME(&path->nexthop, &nexthop) + && path->ifindex == oi->ifp->ifindex) + return 1; - return 0; + return 0; } -void -ospf_route_copy_nexthops_from_vertex (struct ospf_route *to, - struct vertex *v) +void ospf_route_copy_nexthops_from_vertex(struct ospf_route *to, + struct vertex *v) { - struct listnode *node; - struct ospf_path *path; - struct vertex_nexthop *nexthop; - struct vertex_parent *vp; - - assert (to->paths); - - for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp)) - { - nexthop = vp->nexthop; - - if (nexthop->oi != NULL) - { - if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi)) - { - path = ospf_path_new (); - path->nexthop = nexthop->router; - path->ifindex = nexthop->oi->ifp->ifindex; - if (CHECK_FLAG(nexthop->oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) - path->unnumbered = 1; - listnode_add (to->paths, path); - } + struct listnode *node; + struct ospf_path *path; + struct vertex_nexthop *nexthop; + struct vertex_parent *vp; + + assert(to->paths); + + for (ALL_LIST_ELEMENTS_RO(v->parents, node, vp)) { + nexthop = vp->nexthop; + + if (nexthop->oi != NULL) { + if (!ospf_path_exist(to->paths, nexthop->router, + nexthop->oi)) { + path = ospf_path_new(); + path->nexthop = nexthop->router; + path->ifindex = nexthop->oi->ifp->ifindex; + if (CHECK_FLAG(nexthop->oi->connected->flags, + ZEBRA_IFA_UNNUMBERED)) + path->unnumbered = 1; + listnode_add(to->paths, path); + } + } } - } } -struct ospf_path * -ospf_path_lookup (struct list *plist, struct ospf_path *path) +struct ospf_path *ospf_path_lookup(struct list *plist, struct ospf_path *path) { - struct listnode *node; - struct ospf_path *op; - - for (ALL_LIST_ELEMENTS_RO (plist, node, op)) - { - if (!IPV4_ADDR_SAME (&op->nexthop, &path->nexthop)) - continue; - if (!IPV4_ADDR_SAME (&op->adv_router, &path->adv_router)) - continue; - if (op->ifindex != path->ifindex) - continue; - return op; - } - return NULL; + struct listnode *node; + struct ospf_path *op; + + for (ALL_LIST_ELEMENTS_RO(plist, node, op)) { + if (!IPV4_ADDR_SAME(&op->nexthop, &path->nexthop)) + continue; + if (!IPV4_ADDR_SAME(&op->adv_router, &path->adv_router)) + continue; + if (op->ifindex != path->ifindex) + continue; + return op; + } + return NULL; } -void -ospf_route_copy_nexthops (struct ospf_route *to, struct list *from) +void ospf_route_copy_nexthops(struct ospf_route *to, struct list *from) { - struct listnode *node, *nnode; - struct ospf_path *path; + struct listnode *node, *nnode; + struct ospf_path *path; - assert (to->paths); + assert(to->paths); - for (ALL_LIST_ELEMENTS (from, node, nnode, path)) - /* The same routes are just discarded. */ - if (!ospf_path_lookup (to->paths, path)) - listnode_add (to->paths, ospf_path_dup (path)); + for (ALL_LIST_ELEMENTS(from, node, nnode, path)) + /* The same routes are just discarded. */ + if (!ospf_path_lookup(to->paths, path)) + listnode_add(to->paths, ospf_path_dup(path)); } -void -ospf_route_subst_nexthops (struct ospf_route *to, struct list *from) +void ospf_route_subst_nexthops(struct ospf_route *to, struct list *from) { - list_delete_all_node (to->paths); - ospf_route_copy_nexthops (to, from); + list_delete_all_node(to->paths); + ospf_route_copy_nexthops(to, from); } -void -ospf_route_subst (struct route_node *rn, struct ospf_route *new_or, - struct ospf_route *over) +void ospf_route_subst(struct route_node *rn, struct ospf_route *new_or, + struct ospf_route *over) { - route_lock_node (rn); - ospf_route_free (rn->info); + route_lock_node(rn); + ospf_route_free(rn->info); - ospf_route_copy_nexthops (new_or, over->paths); - rn->info = new_or; - route_unlock_node (rn); + ospf_route_copy_nexthops(new_or, over->paths); + rn->info = new_or; + route_unlock_node(rn); } -void -ospf_route_add (struct route_table *rt, struct prefix_ipv4 *p, - struct ospf_route *new_or, struct ospf_route *over) +void ospf_route_add(struct route_table *rt, struct prefix_ipv4 *p, + struct ospf_route *new_or, struct ospf_route *over) { - struct route_node *rn; + struct route_node *rn; - rn = route_node_get (rt, (struct prefix *) p); + rn = route_node_get(rt, (struct prefix *)p); - ospf_route_copy_nexthops (new_or, over->paths); + ospf_route_copy_nexthops(new_or, over->paths); + + if (rn->info) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_route_add(): something's wrong !"); + route_unlock_node(rn); + return; + } - if (rn->info) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_route_add(): something's wrong !"); - route_unlock_node (rn); - return; - } + rn->info = new_or; +} - rn->info = new_or; +void ospf_prune_unreachable_networks(struct route_table *rt) +{ + struct route_node *rn, *next; + struct ospf_route * or ; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Pruning unreachable networks"); + + for (rn = route_top(rt); rn; rn = next) { + next = route_next(rn); + if (rn->info != NULL) { + or = rn->info; + if (listcount(or->paths) == 0) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Pruning route to %s/%d", + inet_ntoa(rn->p.u.prefix4), + rn->p.prefixlen); + + ospf_route_free(or); + rn->info = NULL; + route_unlock_node(rn); + } + } + } } -void -ospf_prune_unreachable_networks (struct route_table *rt) +void ospf_prune_unreachable_routers(struct route_table *rtrs) { - struct route_node *rn, *next; - struct ospf_route *or; + struct route_node *rn, *next; + struct ospf_route * or ; + struct listnode *node, *nnode; + struct list *paths; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Pruning unreachable routers"); + + for (rn = route_top(rtrs); rn; rn = next) { + next = route_next(rn); + if ((paths = rn->info) == NULL) + continue; + + for (ALL_LIST_ELEMENTS(paths, node, nnode, or)) { + if (listcount(or->paths) == 0) { + if (IS_DEBUG_OSPF_EVENT) { + zlog_debug("Pruning route to rtr %s", + inet_ntoa(rn->p.u.prefix4)); + zlog_debug( + " via area %s", + inet_ntoa(or->u.std.area_id)); + } + + listnode_delete(paths, or); + ospf_route_free(or); + } + } - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Pruning unreachable networks"); + if (listcount(paths) == 0) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Pruning router node %s", + inet_ntoa(rn->p.u.prefix4)); - for (rn = route_top (rt); rn; rn = next) - { - next = route_next (rn); - if (rn->info != NULL) - { - or = rn->info; - if (listcount (or->paths) == 0) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Pruning route to %s/%d", - inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen); - - ospf_route_free (or); - rn->info = NULL; - route_unlock_node (rn); - } + list_delete(paths); + rn->info = NULL; + route_unlock_node(rn); + } } - } } -void -ospf_prune_unreachable_routers (struct route_table *rtrs) +int ospf_add_discard_route(struct route_table *rt, struct ospf_area *area, + struct prefix_ipv4 *p) { - struct route_node *rn, *next; - struct ospf_route *or; - struct listnode *node, *nnode; - struct list *paths; + struct route_node *rn; + struct ospf_route * or, *new_or; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Pruning unreachable routers"); + rn = route_node_get(rt, (struct prefix *)p); - for (rn = route_top (rtrs); rn; rn = next) - { - next = route_next (rn); - if ((paths = rn->info) == NULL) - continue; + if (rn == NULL) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_add_discard_route(): router installation error"); + return 0; + } - for (ALL_LIST_ELEMENTS (paths, node, nnode, or)) + if (rn->info) /* If the route to the same destination is found */ { - if (listcount (or->paths) == 0) - { - if (IS_DEBUG_OSPF_EVENT) - { - zlog_debug ("Pruning route to rtr %s", - inet_ntoa (rn->p.u.prefix4)); - zlog_debug (" via area %s", - inet_ntoa (or->u.std.area_id)); - } + route_unlock_node(rn); - listnode_delete (paths, or); - ospf_route_free (or); - } - } + or = rn->info; - if (listcount (paths) == 0) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Pruning router node %s", inet_ntoa (rn->p.u.prefix4)); + if (or->path_type == OSPF_PATH_INTRA_AREA) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_add_discard_route(): " + "an intra-area route exists"); + return 0; + } - list_delete (paths); - rn->info = NULL; - route_unlock_node (rn); - } - } -} + if (or->type == OSPF_DESTINATION_DISCARD) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_add_discard_route(): " + "discard entry already installed"); + return 0; + } -int -ospf_add_discard_route (struct route_table *rt, struct ospf_area *area, - struct prefix_ipv4 *p) -{ - struct route_node *rn; - struct ospf_route *or, *new_or; + ospf_route_free(rn->info); + } - rn = route_node_get (rt, (struct prefix *) p); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_add_discard_route(): " + "adding %s/%d", + inet_ntoa(p->prefix), p->prefixlen); - if (rn == NULL) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_add_discard_route(): router installation error"); - return 0; - } + new_or = ospf_route_new(); + new_or->type = OSPF_DESTINATION_DISCARD; + new_or->id.s_addr = 0; + new_or->cost = 0; + new_or->u.std.area_id = area->area_id; + new_or->u.std.external_routing = area->external_routing; + new_or->path_type = OSPF_PATH_INTER_AREA; + rn->info = new_or; - if (rn->info) /* If the route to the same destination is found */ - { - route_unlock_node (rn); + ospf_zebra_add_discard(p); - or = rn->info; + return 1; +} - if (or->path_type == OSPF_PATH_INTRA_AREA) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_add_discard_route(): " - "an intra-area route exists"); - return 0; +void ospf_delete_discard_route(struct route_table *rt, struct prefix_ipv4 *p) +{ + struct route_node *rn; + struct ospf_route * or ; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_delete_discard_route(): " + "deleting %s/%d", + inet_ntoa(p->prefix), p->prefixlen); + + rn = route_node_lookup(rt, (struct prefix *)p); + + if (rn == NULL) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_delete_discard_route(): no route found"); + return; } - if (or->type == OSPF_DESTINATION_DISCARD) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_add_discard_route(): " - "discard entry already installed"); - return 0; + or = rn->info; + + if (or->path_type == OSPF_PATH_INTRA_AREA) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_delete_discard_route(): " + "an intra-area route exists"); + return; } - ospf_route_free (rn->info); - } + if (or->type != OSPF_DESTINATION_DISCARD) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_delete_discard_route(): " + "not a discard entry"); + return; + } - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_add_discard_route(): " - "adding %s/%d", inet_ntoa (p->prefix), p->prefixlen); + /* free the route entry and the route node */ + ospf_route_free(rn->info); - new_or = ospf_route_new (); - new_or->type = OSPF_DESTINATION_DISCARD; - new_or->id.s_addr = 0; - new_or->cost = 0; - new_or->u.std.area_id = area->area_id; - new_or->u.std.external_routing = area->external_routing; - new_or->path_type = OSPF_PATH_INTER_AREA; - rn->info = new_or; + rn->info = NULL; + route_unlock_node(rn); + route_unlock_node(rn); - ospf_zebra_add_discard (p); + /* remove the discard entry from the rib */ + ospf_zebra_delete_discard(p); - return 1; -} - -void -ospf_delete_discard_route (struct route_table *rt, struct prefix_ipv4 *p) -{ - struct route_node *rn; - struct ospf_route *or; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_delete_discard_route(): " - "deleting %s/%d", inet_ntoa (p->prefix), p->prefixlen); - - rn = route_node_lookup (rt, (struct prefix*)p); - - if (rn == NULL) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug("ospf_delete_discard_route(): no route found"); - return; - } - - or = rn->info; - - if (or->path_type == OSPF_PATH_INTRA_AREA) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_delete_discard_route(): " - "an intra-area route exists"); - return; - } - - if (or->type != OSPF_DESTINATION_DISCARD) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_delete_discard_route(): " - "not a discard entry"); - return; - } - - /* free the route entry and the route node */ - ospf_route_free (rn->info); - - rn->info = NULL; - route_unlock_node (rn); - route_unlock_node (rn); - - /* remove the discard entry from the rib */ - ospf_zebra_delete_discard(p); - - return; + return; } - diff --git a/ospfd/ospf_route.h b/ospfd/ospf_route.h index 16c6b0000..199937984 100644 --- a/ospfd/ospf_route.h +++ b/ospfd/ospf_route.h @@ -34,12 +34,11 @@ #define OSPF_PATH_MAX 5 /* OSPF Path. */ -struct ospf_path -{ - struct in_addr nexthop; - struct in_addr adv_router; - ifindex_t ifindex; - unsigned char unnumbered; +struct ospf_path { + struct in_addr nexthop; + struct in_addr adv_router; + ifindex_t ifindex; + unsigned char unnumbered; }; /* Below is the structure linked to every @@ -54,107 +53,103 @@ struct ospf_path nr->info is a (struct ospf_router_route *) for OSPF_DESTINATION_ROUTER */ -struct route_standard -{ - /* Link Sate Origin. */ - struct lsa_header *origin; +struct route_standard { + /* Link Sate Origin. */ + struct lsa_header *origin; - /* Associated Area. */ - struct in_addr area_id; /* The area the route belongs to */ + /* Associated Area. */ + struct in_addr area_id; /* The area the route belongs to */ - /* Area Type */ - int external_routing; + /* Area Type */ + int external_routing; - /* Optional Capability. */ - u_char options; /* Get from LSA header. */ + /* Optional Capability. */ + u_char options; /* Get from LSA header. */ - /* */ - u_char flags; /* From router-LSA */ + /* */ + u_char flags; /* From router-LSA */ }; -struct route_external -{ - /* Link State Origin. */ - struct ospf_lsa *origin; +struct route_external { + /* Link State Origin. */ + struct ospf_lsa *origin; - /* Link State Cost Type2. */ - u_int32_t type2_cost; + /* Link State Cost Type2. */ + u_int32_t type2_cost; - /* Tag value. */ - u_int32_t tag; + /* Tag value. */ + u_int32_t tag; - /* ASBR route. */ - struct ospf_route *asbr; + /* ASBR route. */ + struct ospf_route *asbr; }; -struct ospf_route -{ - /* Destination Type. */ - u_char type; +struct ospf_route { + /* Destination Type. */ + u_char type; - /* Destination ID. */ /* i.e. Link State ID. */ - struct in_addr id; + /* Destination ID. */ /* i.e. Link State ID. */ + struct in_addr id; - /* Address Mask. */ - struct in_addr mask; /* Only valid for networks. */ + /* Address Mask. */ + struct in_addr mask; /* Only valid for networks. */ - /* Path Type. */ - u_char path_type; + /* Path Type. */ + u_char path_type; - /* List of Paths. */ - struct list *paths; + /* List of Paths. */ + struct list *paths; - /* Link State Cost. */ - u_int32_t cost; /* i.e. metric. */ + /* Link State Cost. */ + u_int32_t cost; /* i.e. metric. */ - /* Route specific info. */ - union - { - struct route_standard std; - struct route_external ext; - } u; + /* Route specific info. */ + union { + struct route_standard std; + struct route_external ext; + } u; }; -extern struct ospf_path *ospf_path_new (void); -extern void ospf_path_free (struct ospf_path *); -extern struct ospf_path *ospf_path_lookup (struct list *, struct ospf_path *); -extern struct ospf_route *ospf_route_new (void); -extern void ospf_route_free (struct ospf_route *); -extern void ospf_route_delete (struct route_table *); -extern void ospf_route_table_free (struct route_table *); +extern struct ospf_path *ospf_path_new(void); +extern void ospf_path_free(struct ospf_path *); +extern struct ospf_path *ospf_path_lookup(struct list *, struct ospf_path *); +extern struct ospf_route *ospf_route_new(void); +extern void ospf_route_free(struct ospf_route *); +extern void ospf_route_delete(struct route_table *); +extern void ospf_route_table_free(struct route_table *); -extern void ospf_route_install (struct ospf *, struct route_table *); -extern void ospf_route_table_dump (struct route_table *); +extern void ospf_route_install(struct ospf *, struct route_table *); +extern void ospf_route_table_dump(struct route_table *); -extern void ospf_intra_add_router (struct route_table *, struct vertex *, +extern void ospf_intra_add_router(struct route_table *, struct vertex *, + struct ospf_area *); + +extern void ospf_intra_add_transit(struct route_table *, struct vertex *, struct ospf_area *); -extern void ospf_intra_add_transit (struct route_table *, struct vertex *, - struct ospf_area *); - -extern void ospf_intra_add_stub (struct route_table *, - struct router_lsa_link *, struct vertex *, - struct ospf_area *, - int parent_is_root, int); - -extern int ospf_route_cmp (struct ospf *, struct ospf_route *, - struct ospf_route *); -extern void ospf_route_copy_nexthops (struct ospf_route *, struct list *); -extern void ospf_route_copy_nexthops_from_vertex (struct ospf_route *, - struct vertex *); - -extern void ospf_route_subst (struct route_node *, struct ospf_route *, - struct ospf_route *); -extern void ospf_route_add (struct route_table *, struct prefix_ipv4 *, - struct ospf_route *, struct ospf_route *); - -extern void ospf_route_subst_nexthops (struct ospf_route *, struct list *); -extern void ospf_prune_unreachable_networks (struct route_table *); -extern void ospf_prune_unreachable_routers (struct route_table *); -extern int ospf_add_discard_route (struct route_table *, struct ospf_area *, - struct prefix_ipv4 *); -extern void ospf_delete_discard_route (struct route_table *, struct prefix_ipv4 *); -extern int ospf_route_match_same (struct route_table *, struct prefix_ipv4 *, - struct ospf_route *); +extern void ospf_intra_add_stub(struct route_table *, struct router_lsa_link *, + struct vertex *, struct ospf_area *, + int parent_is_root, int); + +extern int ospf_route_cmp(struct ospf *, struct ospf_route *, + struct ospf_route *); +extern void ospf_route_copy_nexthops(struct ospf_route *, struct list *); +extern void ospf_route_copy_nexthops_from_vertex(struct ospf_route *, + struct vertex *); + +extern void ospf_route_subst(struct route_node *, struct ospf_route *, + struct ospf_route *); +extern void ospf_route_add(struct route_table *, struct prefix_ipv4 *, + struct ospf_route *, struct ospf_route *); + +extern void ospf_route_subst_nexthops(struct ospf_route *, struct list *); +extern void ospf_prune_unreachable_networks(struct route_table *); +extern void ospf_prune_unreachable_routers(struct route_table *); +extern int ospf_add_discard_route(struct route_table *, struct ospf_area *, + struct prefix_ipv4 *); +extern void ospf_delete_discard_route(struct route_table *, + struct prefix_ipv4 *); +extern int ospf_route_match_same(struct route_table *, struct prefix_ipv4 *, + struct ospf_route *); #endif /* _ZEBRA_OSPF_ROUTE_H */ diff --git a/ospfd/ospf_routemap.c b/ospfd/ospf_routemap.c index 7032cbe1e..547e1e8f5 100644 --- a/ospfd/ospf_routemap.c +++ b/ospfd/ospf_routemap.c @@ -41,488 +41,432 @@ #include "ospfd/ospf_zebra.h" /* Hook function for updating route_map assignment. */ -static void -ospf_route_map_update (const char *name) -{ - struct ospf *ospf; - int type; - - /* If OSPF instatnce does not exist, return right now. */ - ospf = ospf_lookup (); - if (ospf == NULL) - return; - - /* Update route-map */ - for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) - { - struct list *red_list; - struct listnode *node; - struct ospf_redist *red; - - red_list = ospf->redist[type]; - if (!red_list) - continue; - - for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) - { - if (ROUTEMAP_NAME (red) - && strcmp (ROUTEMAP_NAME (red), name) == 0) - { - /* Keep old route-map. */ - struct route_map *old = ROUTEMAP (red); - - /* Update route-map. */ - ROUTEMAP (red) = - route_map_lookup_by_name (ROUTEMAP_NAME (red)); - - /* No update for this distribute type. */ - if (old == NULL && ROUTEMAP (red) == NULL) - continue; - - ospf_distribute_list_update (ospf, type, red->instance); - } - } - } +static void ospf_route_map_update(const char *name) +{ + struct ospf *ospf; + int type; + + /* If OSPF instatnce does not exist, return right now. */ + ospf = ospf_lookup(); + if (ospf == NULL) + return; + + /* Update route-map */ + for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { + struct list *red_list; + struct listnode *node; + struct ospf_redist *red; + + red_list = ospf->redist[type]; + if (!red_list) + continue; + + for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { + if (ROUTEMAP_NAME(red) + && strcmp(ROUTEMAP_NAME(red), name) == 0) { + /* Keep old route-map. */ + struct route_map *old = ROUTEMAP(red); + + /* Update route-map. */ + ROUTEMAP(red) = route_map_lookup_by_name( + ROUTEMAP_NAME(red)); + + /* No update for this distribute type. */ + if (old == NULL && ROUTEMAP(red) == NULL) + continue; + + ospf_distribute_list_update(ospf, type, + red->instance); + } + } + } } -static void -ospf_route_map_event (route_map_event_t event, const char *name) +static void ospf_route_map_event(route_map_event_t event, const char *name) { - struct ospf *ospf; - int type; - - /* If OSPF instatnce does not exist, return right now. */ - ospf = ospf_lookup (); - if (ospf == NULL) - return; - - for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) - { - struct list *red_list; - struct listnode *node; - struct ospf_redist *red; - - red_list = ospf->redist[type]; - if (!red_list) - continue; - - for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) - { - if (ROUTEMAP_NAME (red) && ROUTEMAP (red) - && !strcmp (ROUTEMAP_NAME (red), name)) - { - ospf_distribute_list_update (ospf, type, red->instance); - } - } - } + struct ospf *ospf; + int type; + + /* If OSPF instatnce does not exist, return right now. */ + ospf = ospf_lookup(); + if (ospf == NULL) + return; + + for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { + struct list *red_list; + struct listnode *node; + struct ospf_redist *red; + + red_list = ospf->redist[type]; + if (!red_list) + continue; + + for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { + if (ROUTEMAP_NAME(red) && ROUTEMAP(red) + && !strcmp(ROUTEMAP_NAME(red), name)) { + ospf_distribute_list_update(ospf, type, + red->instance); + } + } + } } /* `match ip netxthop ' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_ip_nexthop (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct access_list *alist; - struct external_info *ei = object; - struct prefix_ipv4 p; - - if (type == RMAP_OSPF) - { - p.family = AF_INET; - p.prefix = ei->nexthop; - p.prefixlen = IPV4_MAX_BITLEN; - - alist = access_list_lookup (AFI_IP, (char *) rule); - if (alist == NULL) - return RMAP_NOMATCH; - - return (access_list_apply (alist, &p) == FILTER_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; +static route_map_result_t route_match_ip_nexthop(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct access_list *alist; + struct external_info *ei = object; + struct prefix_ipv4 p; + + if (type == RMAP_OSPF) { + p.family = AF_INET; + p.prefix = ei->nexthop; + p.prefixlen = IPV4_MAX_BITLEN; + + alist = access_list_lookup(AFI_IP, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; + + return (access_list_apply(alist, &p) == FILTER_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } + return RMAP_NOMATCH; } /* Route map `ip next-hop' match statement. `arg' should be access-list name. */ -static void * -route_match_ip_nexthop_compile (const char *arg) +static void *route_match_ip_nexthop_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `ip address' value. */ -static void -route_match_ip_nexthop_free (void *rule) +static void route_match_ip_nexthop_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for metric matching. */ -struct route_map_rule_cmd route_match_ip_nexthop_cmd = -{ - "ip next-hop", - route_match_ip_nexthop, - route_match_ip_nexthop_compile, - route_match_ip_nexthop_free -}; +struct route_map_rule_cmd route_match_ip_nexthop_cmd = { + "ip next-hop", route_match_ip_nexthop, route_match_ip_nexthop_compile, + route_match_ip_nexthop_free}; /* `match ip next-hop prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - struct prefix_list *plist; - struct external_info *ei = object; - struct prefix_ipv4 p; - - if (type == RMAP_OSPF) - { - p.family = AF_INET; - p.prefix = ei->nexthop; - p.prefixlen = IPV4_MAX_BITLEN; - - plist = prefix_list_lookup (AFI_IP, (char *) rule); - if (plist == NULL) - return RMAP_NOMATCH; - - return (prefix_list_apply (plist, &p) == PREFIX_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; + struct prefix_list *plist; + struct external_info *ei = object; + struct prefix_ipv4 p; + + if (type == RMAP_OSPF) { + p.family = AF_INET; + p.prefix = ei->nexthop; + p.prefixlen = IPV4_MAX_BITLEN; + + plist = prefix_list_lookup(AFI_IP, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; + + return (prefix_list_apply(plist, &p) == PREFIX_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } + return RMAP_NOMATCH; } -static void * -route_match_ip_next_hop_prefix_list_compile (const char *arg) +static void *route_match_ip_next_hop_prefix_list_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ip_next_hop_prefix_list_free (void *rule) +static void route_match_ip_next_hop_prefix_list_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = -{ - "ip next-hop prefix-list", - route_match_ip_next_hop_prefix_list, - route_match_ip_next_hop_prefix_list_compile, - route_match_ip_next_hop_prefix_list_free -}; +struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = { + "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list, + route_match_ip_next_hop_prefix_list_compile, + route_match_ip_next_hop_prefix_list_free}; /* `match ip address IP_ACCESS_LIST' */ /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t -route_match_ip_address (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct access_list *alist; - /* struct prefix_ipv4 match; */ - - if (type == RMAP_OSPF) - { - alist = access_list_lookup (AFI_IP, (char *) rule); - if (alist == NULL) - return RMAP_NOMATCH; - - return (access_list_apply (alist, prefix) == FILTER_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; +static route_map_result_t route_match_ip_address(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct access_list *alist; + /* struct prefix_ipv4 match; */ + + if (type == RMAP_OSPF) { + alist = access_list_lookup(AFI_IP, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; + + return (access_list_apply(alist, prefix) == FILTER_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } + return RMAP_NOMATCH; } /* Route map `ip address' match statement. `arg' should be access-list name. */ -static void * -route_match_ip_address_compile (const char *arg) +static void *route_match_ip_address_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `ip address' value. */ -static void -route_match_ip_address_free (void *rule) +static void route_match_ip_address_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip address matching. */ -struct route_map_rule_cmd route_match_ip_address_cmd = -{ - "ip address", - route_match_ip_address, - route_match_ip_address_compile, - route_match_ip_address_free -}; +struct route_map_rule_cmd route_match_ip_address_cmd = { + "ip address", route_match_ip_address, route_match_ip_address_compile, + route_match_ip_address_free}; /* `match ip address prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_address_prefix_list (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - struct prefix_list *plist; - - if (type == RMAP_OSPF) - { - plist = prefix_list_lookup (AFI_IP, (char *) rule); - if (plist == NULL) - return RMAP_NOMATCH; - - return (prefix_list_apply (plist, prefix) == PREFIX_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; + struct prefix_list *plist; + + if (type == RMAP_OSPF) { + plist = prefix_list_lookup(AFI_IP, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; + + return (prefix_list_apply(plist, prefix) == PREFIX_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } + return RMAP_NOMATCH; } -static void * -route_match_ip_address_prefix_list_compile (const char *arg) +static void *route_match_ip_address_prefix_list_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ip_address_prefix_list_free (void *rule) +static void route_match_ip_address_prefix_list_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = -{ - "ip address prefix-list", - route_match_ip_address_prefix_list, - route_match_ip_address_prefix_list_compile, - route_match_ip_address_prefix_list_free -}; +struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { + "ip address prefix-list", route_match_ip_address_prefix_list, + route_match_ip_address_prefix_list_compile, + route_match_ip_address_prefix_list_free}; /* `match interface IFNAME' */ /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t -route_match_interface (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_interface(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct interface *ifp; - struct external_info *ei; + struct interface *ifp; + struct external_info *ei; - if (type == RMAP_OSPF) - { - ei = object; - ifp = if_lookup_by_name ((char *)rule, VRF_DEFAULT); + if (type == RMAP_OSPF) { + ei = object; + ifp = if_lookup_by_name((char *)rule, VRF_DEFAULT); - if (ifp == NULL || ifp->ifindex != ei->ifindex) - return RMAP_NOMATCH; + if (ifp == NULL || ifp->ifindex != ei->ifindex) + return RMAP_NOMATCH; - return RMAP_MATCH; - } - return RMAP_NOMATCH; + return RMAP_MATCH; + } + return RMAP_NOMATCH; } /* Route map `interface' match statement. `arg' should be interface name. */ -static void * -route_match_interface_compile (const char *arg) +static void *route_match_interface_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `interface' value. */ -static void -route_match_interface_free (void *rule) +static void route_match_interface_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip address matching. */ -struct route_map_rule_cmd route_match_interface_cmd = -{ - "interface", - route_match_interface, - route_match_interface_compile, - route_match_interface_free -}; +struct route_map_rule_cmd route_match_interface_cmd = { + "interface", route_match_interface, route_match_interface_compile, + route_match_interface_free}; /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_tag (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_tag(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - route_tag_t *tag; - struct external_info *ei; + route_tag_t *tag; + struct external_info *ei; - if (type == RMAP_OSPF) - { - tag = rule; - ei = object; + if (type == RMAP_OSPF) { + tag = rule; + ei = object; - return ((ei->tag == *tag)? RMAP_MATCH : RMAP_NOMATCH); - } + return ((ei->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH); + } - return RMAP_NOMATCH; + return RMAP_NOMATCH; } /* Route map commands for tag matching. */ -static struct route_map_rule_cmd route_match_tag_cmd = -{ - "tag", - route_match_tag, - route_map_rule_tag_compile, - route_map_rule_tag_free, +static struct route_map_rule_cmd route_match_tag_cmd = { + "tag", route_match_tag, route_map_rule_tag_compile, + route_map_rule_tag_free, }; /* `set metric METRIC' */ /* Set metric to attribute. */ -static route_map_result_t -route_set_metric (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, + route_map_object_t type, + void *object) { - u_int32_t *metric; - struct external_info *ei; - - if (type == RMAP_OSPF) - { - /* Fetch routemap's rule information. */ - metric = rule; - ei = object; - - /* Set metric out value. */ - ei->route_map_set.metric = *metric; - } - return RMAP_OKAY; + u_int32_t *metric; + struct external_info *ei; + + if (type == RMAP_OSPF) { + /* Fetch routemap's rule information. */ + metric = rule; + ei = object; + + /* Set metric out value. */ + ei->route_map_set.metric = *metric; + } + return RMAP_OKAY; } /* set metric compilation. */ -static void * -route_set_metric_compile (const char *arg) -{ - u_int32_t *metric; - - /* OSPF doesn't support the +/- in - set metric <+/-metric> check - Ignore the +/- component */ - if (! all_digit (arg)) - { - if ((arg[0] == '+' || arg[0] == '-') && all_digit (arg+1)) - { - zlog_warn ("OSPF does not support 'set metric +/-'"); - arg++; +static void *route_set_metric_compile(const char *arg) +{ + u_int32_t *metric; + + /* OSPF doesn't support the +/- in + set metric <+/-metric> check + Ignore the +/- component */ + if (!all_digit(arg)) { + if ((arg[0] == '+' || arg[0] == '-') && all_digit(arg + 1)) { + zlog_warn("OSPF does not support 'set metric +/-'"); + arg++; + } else { + if (strmatch(arg, "+rtt") || strmatch(arg, "-rtt")) + zlog_warn( + "OSPF does not support 'set metric +rtt / -rtt'"); + return NULL; + } } - else - { - if (strmatch (arg, "+rtt") || strmatch (arg, "-rtt")) - zlog_warn ("OSPF does not support 'set metric +rtt / -rtt'"); - return NULL; - } - } - metric = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); - *metric = strtoul (arg, NULL, 10); - - return metric; + metric = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t)); + *metric = strtoul(arg, NULL, 10); + + return metric; } /* Free route map's compiled `set metric' value. */ -static void -route_set_metric_free (void *rule) +static void route_set_metric_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Set metric rule structure. */ -struct route_map_rule_cmd route_set_metric_cmd = -{ - "metric", - route_set_metric, - route_set_metric_compile, - route_set_metric_free, +struct route_map_rule_cmd route_set_metric_cmd = { + "metric", route_set_metric, route_set_metric_compile, + route_set_metric_free, }; /* `set metric-type TYPE' */ /* Set metric-type to attribute. */ -static route_map_result_t -route_set_metric_type (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_metric_type(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - u_int32_t *metric_type; - struct external_info *ei; - - if (type == RMAP_OSPF) - { - /* Fetch routemap's rule information. */ - metric_type = rule; - ei = object; - - /* Set metric out value. */ - ei->route_map_set.metric_type = *metric_type; - } - return RMAP_OKAY; + u_int32_t *metric_type; + struct external_info *ei; + + if (type == RMAP_OSPF) { + /* Fetch routemap's rule information. */ + metric_type = rule; + ei = object; + + /* Set metric out value. */ + ei->route_map_set.metric_type = *metric_type; + } + return RMAP_OKAY; } /* set metric-type compilation. */ -static void * -route_set_metric_type_compile (const char *arg) +static void *route_set_metric_type_compile(const char *arg) { - u_int32_t *metric_type; + u_int32_t *metric_type; - metric_type = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); - if (strcmp (arg, "type-1") == 0) - *metric_type = EXTERNAL_METRIC_TYPE_1; - else if (strcmp (arg, "type-2") == 0) - *metric_type = EXTERNAL_METRIC_TYPE_2; + metric_type = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t)); + if (strcmp(arg, "type-1") == 0) + *metric_type = EXTERNAL_METRIC_TYPE_1; + else if (strcmp(arg, "type-2") == 0) + *metric_type = EXTERNAL_METRIC_TYPE_2; - if (*metric_type == EXTERNAL_METRIC_TYPE_1 || - *metric_type == EXTERNAL_METRIC_TYPE_2) - return metric_type; + if (*metric_type == EXTERNAL_METRIC_TYPE_1 + || *metric_type == EXTERNAL_METRIC_TYPE_2) + return metric_type; - XFREE (MTYPE_ROUTE_MAP_COMPILED, metric_type); - return NULL; + XFREE(MTYPE_ROUTE_MAP_COMPILED, metric_type); + return NULL; } /* Free route map's compiled `set metric-type' value. */ -static void -route_set_metric_type_free (void *rule) +static void route_set_metric_type_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Set metric rule structure. */ -struct route_map_rule_cmd route_set_metric_type_cmd = -{ - "metric-type", - route_set_metric_type, - route_set_metric_type_compile, - route_set_metric_type_free, +struct route_map_rule_cmd route_set_metric_type_cmd = { + "metric-type", route_set_metric_type, route_set_metric_type_compile, + route_set_metric_type_free, }; -static route_map_result_t -route_set_tag (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_tag(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - route_tag_t *tag; - struct external_info *ei; + route_tag_t *tag; + struct external_info *ei; - if (type == RMAP_OSPF) - { - tag = rule; - ei = object; + if (type == RMAP_OSPF) { + tag = rule; + ei = object; - /* Set tag value */ - ei->tag=*tag; - } + /* Set tag value */ + ei->tag = *tag; + } - return RMAP_OKAY; + return RMAP_OKAY; } /* Route map commands for tag set. */ -static struct route_map_rule_cmd route_set_tag_cmd = -{ - "tag", - route_set_tag, - route_map_rule_tag_compile, - route_map_rule_tag_free, +static struct route_map_rule_cmd route_set_tag_cmd = { + "tag", route_set_tag, route_map_rule_tag_compile, + route_map_rule_tag_free, }; DEFUN (set_metric_type, @@ -533,9 +477,9 @@ DEFUN (set_metric_type, "OSPF[6] external type 1 metric\n" "OSPF[6] external type 2 metric\n") { - char *ext = argv[2]->text; - return generic_set_add (vty, VTY_GET_CONTEXT(route_map_index), - "metric-type", ext); + char *ext = argv[2]->text; + return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), + "metric-type", ext); } DEFUN (no_set_metric_type, @@ -547,59 +491,58 @@ DEFUN (no_set_metric_type, "OSPF[6] external type 1 metric\n" "OSPF[6] external type 2 metric\n") { - char *ext = (argc == 4) ? argv[3]->text : NULL; - return generic_set_delete (vty, VTY_GET_CONTEXT(route_map_index), - "metric-type", ext); + char *ext = (argc == 4) ? argv[3]->text : NULL; + return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index), + "metric-type", ext); } /* Route-map init */ -void -ospf_route_map_init (void) +void ospf_route_map_init(void) { - route_map_init (); + route_map_init(); + + route_map_add_hook(ospf_route_map_update); + route_map_delete_hook(ospf_route_map_update); + route_map_event_hook(ospf_route_map_event); - route_map_add_hook (ospf_route_map_update); - route_map_delete_hook (ospf_route_map_update); - route_map_event_hook (ospf_route_map_event); + route_map_set_metric_hook(generic_set_add); + route_map_no_set_metric_hook(generic_set_delete); - route_map_set_metric_hook (generic_set_add); - route_map_no_set_metric_hook (generic_set_delete); + route_map_match_ip_next_hop_hook(generic_match_add); + route_map_no_match_ip_next_hop_hook(generic_match_delete); - route_map_match_ip_next_hop_hook (generic_match_add); - route_map_no_match_ip_next_hop_hook (generic_match_delete); + route_map_match_interface_hook(generic_match_add); + route_map_no_match_interface_hook(generic_match_delete); - route_map_match_interface_hook (generic_match_add); - route_map_no_match_interface_hook (generic_match_delete); + route_map_match_ip_address_hook(generic_match_add); + route_map_no_match_ip_address_hook(generic_match_delete); - route_map_match_ip_address_hook (generic_match_add); - route_map_no_match_ip_address_hook (generic_match_delete); + route_map_match_ip_address_prefix_list_hook(generic_match_add); + route_map_no_match_ip_address_prefix_list_hook(generic_match_delete); - route_map_match_ip_address_prefix_list_hook (generic_match_add); - route_map_no_match_ip_address_prefix_list_hook (generic_match_delete); + route_map_match_ip_next_hop_prefix_list_hook(generic_match_add); + route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete); - route_map_match_ip_next_hop_prefix_list_hook (generic_match_add); - route_map_no_match_ip_next_hop_prefix_list_hook (generic_match_delete); + route_map_match_tag_hook(generic_match_add); + route_map_no_match_tag_hook(generic_match_delete); - route_map_match_tag_hook (generic_match_add); - route_map_no_match_tag_hook (generic_match_delete); + route_map_set_metric_hook(generic_set_add); + route_map_no_set_metric_hook(generic_set_delete); - route_map_set_metric_hook (generic_set_add); - route_map_no_set_metric_hook (generic_set_delete); + route_map_set_tag_hook(generic_set_add); + route_map_no_set_tag_hook(generic_set_delete); - route_map_set_tag_hook (generic_set_add); - route_map_no_set_tag_hook (generic_set_delete); - - route_map_install_match (&route_match_ip_nexthop_cmd); - route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd); - route_map_install_match (&route_match_ip_address_cmd); - route_map_install_match (&route_match_ip_address_prefix_list_cmd); - route_map_install_match (&route_match_interface_cmd); - route_map_install_match (&route_match_tag_cmd); + route_map_install_match(&route_match_ip_nexthop_cmd); + route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd); + route_map_install_match(&route_match_ip_address_cmd); + route_map_install_match(&route_match_ip_address_prefix_list_cmd); + route_map_install_match(&route_match_interface_cmd); + route_map_install_match(&route_match_tag_cmd); - route_map_install_set (&route_set_metric_cmd); - route_map_install_set (&route_set_metric_type_cmd); - route_map_install_set (&route_set_tag_cmd); + route_map_install_set(&route_set_metric_cmd); + route_map_install_set(&route_set_metric_type_cmd); + route_map_install_set(&route_set_tag_cmd); - install_element (RMAP_NODE, &set_metric_type_cmd); - install_element (RMAP_NODE, &no_set_metric_type_cmd); + install_element(RMAP_NODE, &set_metric_type_cmd); + install_element(RMAP_NODE, &no_set_metric_type_cmd); } diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c index b491d43ce..6a352380b 100644 --- a/ospfd/ospf_snmp.c +++ b/ospfd/ospf_snmp.c @@ -206,2418 +206,2352 @@ #define STRING ASN_OCTET_STR /* Because DR/DROther values are exhanged wrt RFC */ -#define ISM_SNMP(x) (((x) == ISM_DROther) ? ISM_DR : \ - ((x) == ISM_DR) ? ISM_DROther : (x)) +#define ISM_SNMP(x) \ + (((x) == ISM_DROther) ? ISM_DR : ((x) == ISM_DR) ? ISM_DROther : (x)) /* Declare static local variables for convenience. */ SNMP_LOCAL_VARIABLES /* OSPF-MIB instances. */ -static oid ospf_oid [] = { OSPF2MIB }; -static oid ospf_trap_oid [] = { OSPF2MIB, 16, 2 }; /* Not reverse mappable! */ +static oid ospf_oid[] = {OSPF2MIB}; +static oid ospf_trap_oid[] = {OSPF2MIB, 16, 2}; /* Not reverse mappable! */ /* IP address 0.0.0.0. */ -static struct in_addr ospf_empty_addr = { .s_addr = 0 }; +static struct in_addr ospf_empty_addr = {.s_addr = 0}; /* Hook functions. */ -static u_char *ospfGeneralGroup (struct variable *, oid *, size_t *, - int, size_t *, WriteMethod **); -static u_char *ospfAreaEntry (struct variable *, oid *, size_t *, int, - size_t *, WriteMethod **); -static u_char *ospfStubAreaEntry (struct variable *, oid *, size_t *, - int, size_t *, WriteMethod **); -static u_char *ospfLsdbEntry (struct variable *, oid *, size_t *, int, - size_t *, WriteMethod **); -static u_char *ospfAreaRangeEntry (struct variable *, oid *, size_t *, int, - size_t *, WriteMethod **); -static u_char *ospfHostEntry (struct variable *, oid *, size_t *, int, - size_t *, WriteMethod **); -static u_char *ospfIfEntry (struct variable *, oid *, size_t *, int, - size_t *, WriteMethod **); -static u_char *ospfIfMetricEntry (struct variable *, oid *, size_t *, int, - size_t *, WriteMethod **); -static u_char *ospfVirtIfEntry (struct variable *, oid *, size_t *, int, +static u_char *ospfGeneralGroup(struct variable *, oid *, size_t *, int, size_t *, WriteMethod **); -static u_char *ospfNbrEntry (struct variable *, oid *, size_t *, int, - size_t *, WriteMethod **); -static u_char *ospfVirtNbrEntry (struct variable *, oid *, size_t *, int, +static u_char *ospfAreaEntry(struct variable *, oid *, size_t *, int, size_t *, + WriteMethod **); +static u_char *ospfStubAreaEntry(struct variable *, oid *, size_t *, int, size_t *, WriteMethod **); -static u_char *ospfExtLsdbEntry (struct variable *, oid *, size_t *, int, +static u_char *ospfLsdbEntry(struct variable *, oid *, size_t *, int, size_t *, + WriteMethod **); +static u_char *ospfAreaRangeEntry(struct variable *, oid *, size_t *, int, + size_t *, WriteMethod **); +static u_char *ospfHostEntry(struct variable *, oid *, size_t *, int, size_t *, + WriteMethod **); +static u_char *ospfIfEntry(struct variable *, oid *, size_t *, int, size_t *, + WriteMethod **); +static u_char *ospfIfMetricEntry(struct variable *, oid *, size_t *, int, size_t *, WriteMethod **); -static u_char *ospfAreaAggregateEntry (struct variable *, oid *, size_t *, - int, size_t *, WriteMethod **); - -static struct variable ospf_variables[] = -{ - /* OSPF general variables */ - {OSPFROUTERID, IPADDRESS, RWRITE, ospfGeneralGroup, - 2, {1, 1}}, - {OSPFADMINSTAT, INTEGER, RWRITE, ospfGeneralGroup, - 2, {1, 2}}, - {OSPFVERSIONNUMBER, INTEGER, RONLY, ospfGeneralGroup, - 2, {1, 3}}, - {OSPFAREABDRRTRSTATUS, INTEGER, RONLY, ospfGeneralGroup, - 2, {1, 4}}, - {OSPFASBDRRTRSTATUS, INTEGER, RWRITE, ospfGeneralGroup, - 2, {1, 5}}, - {OSPFEXTERNLSACOUNT, GAUGE, RONLY, ospfGeneralGroup, - 2, {1, 6}}, - {OSPFEXTERNLSACKSUMSUM, INTEGER, RONLY, ospfGeneralGroup, - 2, {1, 7}}, - {OSPFTOSSUPPORT, INTEGER, RWRITE, ospfGeneralGroup, - 2, {1, 8}}, - {OSPFORIGINATENEWLSAS, COUNTER, RONLY, ospfGeneralGroup, - 2, {1, 9}}, - {OSPFRXNEWLSAS, COUNTER, RONLY, ospfGeneralGroup, - 2, {1, 10}}, - {OSPFEXTLSDBLIMIT, INTEGER, RWRITE, ospfGeneralGroup, - 2, {1, 11}}, - {OSPFMULTICASTEXTENSIONS, INTEGER, RWRITE, ospfGeneralGroup, - 2, {1, 12}}, - {OSPFEXITOVERFLOWINTERVAL, INTEGER, RWRITE, ospfGeneralGroup, - 2, {1, 13}}, - {OSPFDEMANDEXTENSIONS, INTEGER, RWRITE, ospfGeneralGroup, - 2, {1, 14}}, - - /* OSPF area data structure. */ - {OSPFAREAID, IPADDRESS, RONLY, ospfAreaEntry, - 3, {2, 1, 1}}, - {OSPFAUTHTYPE, INTEGER, RWRITE, ospfAreaEntry, - 3, {2, 1, 2}}, - {OSPFIMPORTASEXTERN, INTEGER, RWRITE, ospfAreaEntry, - 3, {2, 1, 3}}, - {OSPFSPFRUNS, COUNTER, RONLY, ospfAreaEntry, - 3, {2, 1, 4}}, - {OSPFAREABDRRTRCOUNT, GAUGE, RONLY, ospfAreaEntry, - 3, {2, 1, 5}}, - {OSPFASBDRRTRCOUNT, GAUGE, RONLY, ospfAreaEntry, - 3, {2, 1, 6}}, - {OSPFAREALSACOUNT, GAUGE, RONLY, ospfAreaEntry, - 3, {2, 1, 7}}, - {OSPFAREALSACKSUMSUM, INTEGER, RONLY, ospfAreaEntry, - 3, {2, 1, 8}}, - {OSPFAREASUMMARY, INTEGER, RWRITE, ospfAreaEntry, - 3, {2, 1, 9}}, - {OSPFAREASTATUS, INTEGER, RWRITE, ospfAreaEntry, - 3, {2, 1, 10}}, - - /* OSPF stub area information. */ - {OSPFSTUBAREAID, IPADDRESS, RONLY, ospfStubAreaEntry, - 3, {3, 1, 1}}, - {OSPFSTUBTOS, INTEGER, RONLY, ospfStubAreaEntry, - 3, {3, 1, 2}}, - {OSPFSTUBMETRIC, INTEGER, RWRITE, ospfStubAreaEntry, - 3, {3, 1, 3}}, - {OSPFSTUBSTATUS, INTEGER, RWRITE, ospfStubAreaEntry, - 3, {3, 1, 4}}, - {OSPFSTUBMETRICTYPE, INTEGER, RWRITE, ospfStubAreaEntry, - 3, {3, 1, 5}}, - - /* OSPF link state database. */ - {OSPFLSDBAREAID, IPADDRESS, RONLY, ospfLsdbEntry, - 3, {4, 1, 1}}, - {OSPFLSDBTYPE, INTEGER, RONLY, ospfLsdbEntry, - 3, {4, 1, 2}}, - {OSPFLSDBLSID, IPADDRESS, RONLY, ospfLsdbEntry, - 3, {4, 1, 3}}, - {OSPFLSDBROUTERID, IPADDRESS, RONLY, ospfLsdbEntry, - 3, {4, 1, 4}}, - {OSPFLSDBSEQUENCE, INTEGER, RONLY, ospfLsdbEntry, - 3, {4, 1, 5}}, - {OSPFLSDBAGE, INTEGER, RONLY, ospfLsdbEntry, - 3, {4, 1, 6}}, - {OSPFLSDBCHECKSUM, INTEGER, RONLY, ospfLsdbEntry, - 3, {4, 1, 7}}, - {OSPFLSDBADVERTISEMENT, STRING, RONLY, ospfLsdbEntry, - 3, {4, 1, 8}}, - - /* Area range table. */ - {OSPFAREARANGEAREAID, IPADDRESS, RONLY, ospfAreaRangeEntry, - 3, {5, 1, 1}}, - {OSPFAREARANGENET, IPADDRESS, RONLY, ospfAreaRangeEntry, - 3, {5, 1, 2}}, - {OSPFAREARANGEMASK, IPADDRESS, RWRITE, ospfAreaRangeEntry, - 3, {5, 1, 3}}, - {OSPFAREARANGESTATUS, INTEGER, RWRITE, ospfAreaRangeEntry, - 3, {5, 1, 4}}, - {OSPFAREARANGEEFFECT, INTEGER, RWRITE, ospfAreaRangeEntry, - 3, {5, 1, 5}}, - - /* OSPF host table. */ - {OSPFHOSTIPADDRESS, IPADDRESS, RONLY, ospfHostEntry, - 3, {6, 1, 1}}, - {OSPFHOSTTOS, INTEGER, RONLY, ospfHostEntry, - 3, {6, 1, 2}}, - {OSPFHOSTMETRIC, INTEGER, RWRITE, ospfHostEntry, - 3, {6, 1, 3}}, - {OSPFHOSTSTATUS, INTEGER, RWRITE, ospfHostEntry, - 3, {6, 1, 4}}, - {OSPFHOSTAREAID, IPADDRESS, RONLY, ospfHostEntry, - 3, {6, 1, 5}}, - - /* OSPF interface table. */ - {OSPFIFIPADDRESS, IPADDRESS, RONLY, ospfIfEntry, - 3, {7, 1, 1}}, - {OSPFADDRESSLESSIF, INTEGER, RONLY, ospfIfEntry, - 3, {7, 1, 2}}, - {OSPFIFAREAID, IPADDRESS, RWRITE, ospfIfEntry, - 3, {7, 1, 3}}, - {OSPFIFTYPE, INTEGER, RWRITE, ospfIfEntry, - 3, {7, 1, 4}}, - {OSPFIFADMINSTAT, INTEGER, RWRITE, ospfIfEntry, - 3, {7, 1, 5}}, - {OSPFIFRTRPRIORITY, INTEGER, RWRITE, ospfIfEntry, - 3, {7, 1, 6}}, - {OSPFIFTRANSITDELAY, INTEGER, RWRITE, ospfIfEntry, - 3, {7, 1, 7}}, - {OSPFIFRETRANSINTERVAL, INTEGER, RWRITE, ospfIfEntry, - 3, {7, 1, 8}}, - {OSPFIFHELLOINTERVAL, INTEGER, RWRITE, ospfIfEntry, - 3, {7, 1, 9}}, - {OSPFIFRTRDEADINTERVAL, INTEGER, RWRITE, ospfIfEntry, - 3, {7, 1, 10}}, - {OSPFIFPOLLINTERVAL, INTEGER, RWRITE, ospfIfEntry, - 3, {7, 1, 11}}, - {OSPFIFSTATE, INTEGER, RONLY, ospfIfEntry, - 3, {7, 1, 12}}, - {OSPFIFDESIGNATEDROUTER, IPADDRESS, RONLY, ospfIfEntry, - 3, {7, 1, 13}}, - {OSPFIFBACKUPDESIGNATEDROUTER, IPADDRESS, RONLY, ospfIfEntry, - 3, {7, 1, 14}}, - {OSPFIFEVENTS, COUNTER, RONLY, ospfIfEntry, - 3, {7, 1, 15}}, - {OSPFIFAUTHKEY, STRING, RWRITE, ospfIfEntry, - 3, {7, 1, 16}}, - {OSPFIFSTATUS, INTEGER, RWRITE, ospfIfEntry, - 3, {7, 1, 17}}, - {OSPFIFMULTICASTFORWARDING, INTEGER, RWRITE, ospfIfEntry, - 3, {7, 1, 18}}, - {OSPFIFDEMAND, INTEGER, RWRITE, ospfIfEntry, - 3, {7, 1, 19}}, - {OSPFIFAUTHTYPE, INTEGER, RWRITE, ospfIfEntry, - 3, {7, 1, 20}}, - - /* OSPF interface metric table. */ - {OSPFIFMETRICIPADDRESS, IPADDRESS, RONLY, ospfIfMetricEntry, - 3, {8, 1, 1}}, - {OSPFIFMETRICADDRESSLESSIF, INTEGER, RONLY, ospfIfMetricEntry, - 3, {8, 1, 2}}, - {OSPFIFMETRICTOS, INTEGER, RONLY, ospfIfMetricEntry, - 3, {8, 1, 3}}, - {OSPFIFMETRICVALUE, INTEGER, RWRITE, ospfIfMetricEntry, - 3, {8, 1, 4}}, - {OSPFIFMETRICSTATUS, INTEGER, RWRITE, ospfIfMetricEntry, - 3, {8, 1, 5}}, - - /* OSPF virtual interface table. */ - {OSPFVIRTIFAREAID, IPADDRESS, RONLY, ospfVirtIfEntry, - 3, {9, 1, 1}}, - {OSPFVIRTIFNEIGHBOR, IPADDRESS, RONLY, ospfVirtIfEntry, - 3, {9, 1, 2}}, - {OSPFVIRTIFTRANSITDELAY, INTEGER, RWRITE, ospfVirtIfEntry, - 3, {9, 1, 3}}, - {OSPFVIRTIFRETRANSINTERVAL, INTEGER, RWRITE, ospfVirtIfEntry, - 3, {9, 1, 4}}, - {OSPFVIRTIFHELLOINTERVAL, INTEGER, RWRITE, ospfVirtIfEntry, - 3, {9, 1, 5}}, - {OSPFVIRTIFRTRDEADINTERVAL, INTEGER, RWRITE, ospfVirtIfEntry, - 3, {9, 1, 6}}, - {OSPFVIRTIFSTATE, INTEGER, RONLY, ospfVirtIfEntry, - 3, {9, 1, 7}}, - {OSPFVIRTIFEVENTS, COUNTER, RONLY, ospfVirtIfEntry, - 3, {9, 1, 8}}, - {OSPFVIRTIFAUTHKEY, STRING, RWRITE, ospfVirtIfEntry, - 3, {9, 1, 9}}, - {OSPFVIRTIFSTATUS, INTEGER, RWRITE, ospfVirtIfEntry, - 3, {9, 1, 10}}, - {OSPFVIRTIFAUTHTYPE, INTEGER, RWRITE, ospfVirtIfEntry, - 3, {9, 1, 11}}, - - /* OSPF neighbor table. */ - {OSPFNBRIPADDR, IPADDRESS, RONLY, ospfNbrEntry, - 3, {10, 1, 1}}, - {OSPFNBRADDRESSLESSINDEX, INTEGER, RONLY, ospfNbrEntry, - 3, {10, 1, 2}}, - {OSPFNBRRTRID, IPADDRESS, RONLY, ospfNbrEntry, - 3, {10, 1, 3}}, - {OSPFNBROPTIONS, INTEGER, RONLY, ospfNbrEntry, - 3, {10, 1, 4}}, - {OSPFNBRPRIORITY, INTEGER, RWRITE, ospfNbrEntry, - 3, {10, 1, 5}}, - {OSPFNBRSTATE, INTEGER, RONLY, ospfNbrEntry, - 3, {10, 1, 6}}, - {OSPFNBREVENTS, COUNTER, RONLY, ospfNbrEntry, - 3, {10, 1, 7}}, - {OSPFNBRLSRETRANSQLEN, GAUGE, RONLY, ospfNbrEntry, - 3, {10, 1, 8}}, - {OSPFNBMANBRSTATUS, INTEGER, RWRITE, ospfNbrEntry, - 3, {10, 1, 9}}, - {OSPFNBMANBRPERMANENCE, INTEGER, RONLY, ospfNbrEntry, - 3, {10, 1, 10}}, - {OSPFNBRHELLOSUPPRESSED, INTEGER, RONLY, ospfNbrEntry, - 3, {10, 1, 11}}, - - /* OSPF virtual neighbor table. */ - {OSPFVIRTNBRAREA, IPADDRESS, RONLY, ospfVirtNbrEntry, - 3, {11, 1, 1}}, - {OSPFVIRTNBRRTRID, IPADDRESS, RONLY, ospfVirtNbrEntry, - 3, {11, 1, 2}}, - {OSPFVIRTNBRIPADDR, IPADDRESS, RONLY, ospfVirtNbrEntry, - 3, {11, 1, 3}}, - {OSPFVIRTNBROPTIONS, INTEGER, RONLY, ospfVirtNbrEntry, - 3, {11, 1, 4}}, - {OSPFVIRTNBRSTATE, INTEGER, RONLY, ospfVirtNbrEntry, - 3, {11, 1, 5}}, - {OSPFVIRTNBREVENTS, COUNTER, RONLY, ospfVirtNbrEntry, - 3, {11, 1, 6}}, - {OSPFVIRTNBRLSRETRANSQLEN, INTEGER, RONLY, ospfVirtNbrEntry, - 3, {11, 1, 7}}, - {OSPFVIRTNBRHELLOSUPPRESSED, INTEGER, RONLY, ospfVirtNbrEntry, - 3, {11, 1, 8}}, - - /* OSPF link state database, external. */ - {OSPFEXTLSDBTYPE, INTEGER, RONLY, ospfExtLsdbEntry, - 3, {12, 1, 1}}, - {OSPFEXTLSDBLSID, IPADDRESS, RONLY, ospfExtLsdbEntry, - 3, {12, 1, 2}}, - {OSPFEXTLSDBROUTERID, IPADDRESS, RONLY, ospfExtLsdbEntry, - 3, {12, 1, 3}}, - {OSPFEXTLSDBSEQUENCE, INTEGER, RONLY, ospfExtLsdbEntry, - 3, {12, 1, 4}}, - {OSPFEXTLSDBAGE, INTEGER, RONLY, ospfExtLsdbEntry, - 3, {12, 1, 5}}, - {OSPFEXTLSDBCHECKSUM, INTEGER, RONLY, ospfExtLsdbEntry, - 3, {12, 1, 6}}, - {OSPFEXTLSDBADVERTISEMENT, STRING, RONLY, ospfExtLsdbEntry, - 3, {12, 1, 7}}, - - /* OSPF area aggregate table. */ - {OSPFAREAAGGREGATEAREAID, IPADDRESS, RONLY, ospfAreaAggregateEntry, - 3, {14, 1, 1}}, - {OSPFAREAAGGREGATELSDBTYPE, INTEGER, RONLY, ospfAreaAggregateEntry, - 3, {14, 1, 2}}, - {OSPFAREAAGGREGATENET, IPADDRESS, RONLY, ospfAreaAggregateEntry, - 3, {14, 1, 3}}, - {OSPFAREAAGGREGATEMASK, IPADDRESS, RONLY, ospfAreaAggregateEntry, - 3, {14, 1, 4}}, - {OSPFAREAAGGREGATESTATUS, INTEGER, RWRITE, ospfAreaAggregateEntry, - 3, {14, 1, 5}}, - {OSPFAREAAGGREGATEEFFECT, INTEGER, RWRITE, ospfAreaAggregateEntry, - 3, {14, 1, 6}} -}; +static u_char *ospfVirtIfEntry(struct variable *, oid *, size_t *, int, + size_t *, WriteMethod **); +static u_char *ospfNbrEntry(struct variable *, oid *, size_t *, int, size_t *, + WriteMethod **); +static u_char *ospfVirtNbrEntry(struct variable *, oid *, size_t *, int, + size_t *, WriteMethod **); +static u_char *ospfExtLsdbEntry(struct variable *, oid *, size_t *, int, + size_t *, WriteMethod **); +static u_char *ospfAreaAggregateEntry(struct variable *, oid *, size_t *, int, + size_t *, WriteMethod **); + +static struct variable ospf_variables[] = { + /* OSPF general variables */ + {OSPFROUTERID, IPADDRESS, RWRITE, ospfGeneralGroup, 2, {1, 1}}, + {OSPFADMINSTAT, INTEGER, RWRITE, ospfGeneralGroup, 2, {1, 2}}, + {OSPFVERSIONNUMBER, INTEGER, RONLY, ospfGeneralGroup, 2, {1, 3}}, + {OSPFAREABDRRTRSTATUS, INTEGER, RONLY, ospfGeneralGroup, 2, {1, 4}}, + {OSPFASBDRRTRSTATUS, INTEGER, RWRITE, ospfGeneralGroup, 2, {1, 5}}, + {OSPFEXTERNLSACOUNT, GAUGE, RONLY, ospfGeneralGroup, 2, {1, 6}}, + {OSPFEXTERNLSACKSUMSUM, INTEGER, RONLY, ospfGeneralGroup, 2, {1, 7}}, + {OSPFTOSSUPPORT, INTEGER, RWRITE, ospfGeneralGroup, 2, {1, 8}}, + {OSPFORIGINATENEWLSAS, COUNTER, RONLY, ospfGeneralGroup, 2, {1, 9}}, + {OSPFRXNEWLSAS, COUNTER, RONLY, ospfGeneralGroup, 2, {1, 10}}, + {OSPFEXTLSDBLIMIT, INTEGER, RWRITE, ospfGeneralGroup, 2, {1, 11}}, + {OSPFMULTICASTEXTENSIONS, + INTEGER, + RWRITE, + ospfGeneralGroup, + 2, + {1, 12}}, + {OSPFEXITOVERFLOWINTERVAL, + INTEGER, + RWRITE, + ospfGeneralGroup, + 2, + {1, 13}}, + {OSPFDEMANDEXTENSIONS, INTEGER, RWRITE, ospfGeneralGroup, 2, {1, 14}}, + + /* OSPF area data structure. */ + {OSPFAREAID, IPADDRESS, RONLY, ospfAreaEntry, 3, {2, 1, 1}}, + {OSPFAUTHTYPE, INTEGER, RWRITE, ospfAreaEntry, 3, {2, 1, 2}}, + {OSPFIMPORTASEXTERN, INTEGER, RWRITE, ospfAreaEntry, 3, {2, 1, 3}}, + {OSPFSPFRUNS, COUNTER, RONLY, ospfAreaEntry, 3, {2, 1, 4}}, + {OSPFAREABDRRTRCOUNT, GAUGE, RONLY, ospfAreaEntry, 3, {2, 1, 5}}, + {OSPFASBDRRTRCOUNT, GAUGE, RONLY, ospfAreaEntry, 3, {2, 1, 6}}, + {OSPFAREALSACOUNT, GAUGE, RONLY, ospfAreaEntry, 3, {2, 1, 7}}, + {OSPFAREALSACKSUMSUM, INTEGER, RONLY, ospfAreaEntry, 3, {2, 1, 8}}, + {OSPFAREASUMMARY, INTEGER, RWRITE, ospfAreaEntry, 3, {2, 1, 9}}, + {OSPFAREASTATUS, INTEGER, RWRITE, ospfAreaEntry, 3, {2, 1, 10}}, + + /* OSPF stub area information. */ + {OSPFSTUBAREAID, IPADDRESS, RONLY, ospfStubAreaEntry, 3, {3, 1, 1}}, + {OSPFSTUBTOS, INTEGER, RONLY, ospfStubAreaEntry, 3, {3, 1, 2}}, + {OSPFSTUBMETRIC, INTEGER, RWRITE, ospfStubAreaEntry, 3, {3, 1, 3}}, + {OSPFSTUBSTATUS, INTEGER, RWRITE, ospfStubAreaEntry, 3, {3, 1, 4}}, + {OSPFSTUBMETRICTYPE, INTEGER, RWRITE, ospfStubAreaEntry, 3, {3, 1, 5}}, + + /* OSPF link state database. */ + {OSPFLSDBAREAID, IPADDRESS, RONLY, ospfLsdbEntry, 3, {4, 1, 1}}, + {OSPFLSDBTYPE, INTEGER, RONLY, ospfLsdbEntry, 3, {4, 1, 2}}, + {OSPFLSDBLSID, IPADDRESS, RONLY, ospfLsdbEntry, 3, {4, 1, 3}}, + {OSPFLSDBROUTERID, IPADDRESS, RONLY, ospfLsdbEntry, 3, {4, 1, 4}}, + {OSPFLSDBSEQUENCE, INTEGER, RONLY, ospfLsdbEntry, 3, {4, 1, 5}}, + {OSPFLSDBAGE, INTEGER, RONLY, ospfLsdbEntry, 3, {4, 1, 6}}, + {OSPFLSDBCHECKSUM, INTEGER, RONLY, ospfLsdbEntry, 3, {4, 1, 7}}, + {OSPFLSDBADVERTISEMENT, STRING, RONLY, ospfLsdbEntry, 3, {4, 1, 8}}, + + /* Area range table. */ + {OSPFAREARANGEAREAID, + IPADDRESS, + RONLY, + ospfAreaRangeEntry, + 3, + {5, 1, 1}}, + {OSPFAREARANGENET, IPADDRESS, RONLY, ospfAreaRangeEntry, 3, {5, 1, 2}}, + {OSPFAREARANGEMASK, + IPADDRESS, + RWRITE, + ospfAreaRangeEntry, + 3, + {5, 1, 3}}, + {OSPFAREARANGESTATUS, + INTEGER, + RWRITE, + ospfAreaRangeEntry, + 3, + {5, 1, 4}}, + {OSPFAREARANGEEFFECT, + INTEGER, + RWRITE, + ospfAreaRangeEntry, + 3, + {5, 1, 5}}, + + /* OSPF host table. */ + {OSPFHOSTIPADDRESS, IPADDRESS, RONLY, ospfHostEntry, 3, {6, 1, 1}}, + {OSPFHOSTTOS, INTEGER, RONLY, ospfHostEntry, 3, {6, 1, 2}}, + {OSPFHOSTMETRIC, INTEGER, RWRITE, ospfHostEntry, 3, {6, 1, 3}}, + {OSPFHOSTSTATUS, INTEGER, RWRITE, ospfHostEntry, 3, {6, 1, 4}}, + {OSPFHOSTAREAID, IPADDRESS, RONLY, ospfHostEntry, 3, {6, 1, 5}}, + + /* OSPF interface table. */ + {OSPFIFIPADDRESS, IPADDRESS, RONLY, ospfIfEntry, 3, {7, 1, 1}}, + {OSPFADDRESSLESSIF, INTEGER, RONLY, ospfIfEntry, 3, {7, 1, 2}}, + {OSPFIFAREAID, IPADDRESS, RWRITE, ospfIfEntry, 3, {7, 1, 3}}, + {OSPFIFTYPE, INTEGER, RWRITE, ospfIfEntry, 3, {7, 1, 4}}, + {OSPFIFADMINSTAT, INTEGER, RWRITE, ospfIfEntry, 3, {7, 1, 5}}, + {OSPFIFRTRPRIORITY, INTEGER, RWRITE, ospfIfEntry, 3, {7, 1, 6}}, + {OSPFIFTRANSITDELAY, INTEGER, RWRITE, ospfIfEntry, 3, {7, 1, 7}}, + {OSPFIFRETRANSINTERVAL, INTEGER, RWRITE, ospfIfEntry, 3, {7, 1, 8}}, + {OSPFIFHELLOINTERVAL, INTEGER, RWRITE, ospfIfEntry, 3, {7, 1, 9}}, + {OSPFIFRTRDEADINTERVAL, INTEGER, RWRITE, ospfIfEntry, 3, {7, 1, 10}}, + {OSPFIFPOLLINTERVAL, INTEGER, RWRITE, ospfIfEntry, 3, {7, 1, 11}}, + {OSPFIFSTATE, INTEGER, RONLY, ospfIfEntry, 3, {7, 1, 12}}, + {OSPFIFDESIGNATEDROUTER, IPADDRESS, RONLY, ospfIfEntry, 3, {7, 1, 13}}, + {OSPFIFBACKUPDESIGNATEDROUTER, + IPADDRESS, + RONLY, + ospfIfEntry, + 3, + {7, 1, 14}}, + {OSPFIFEVENTS, COUNTER, RONLY, ospfIfEntry, 3, {7, 1, 15}}, + {OSPFIFAUTHKEY, STRING, RWRITE, ospfIfEntry, 3, {7, 1, 16}}, + {OSPFIFSTATUS, INTEGER, RWRITE, ospfIfEntry, 3, {7, 1, 17}}, + {OSPFIFMULTICASTFORWARDING, + INTEGER, + RWRITE, + ospfIfEntry, + 3, + {7, 1, 18}}, + {OSPFIFDEMAND, INTEGER, RWRITE, ospfIfEntry, 3, {7, 1, 19}}, + {OSPFIFAUTHTYPE, INTEGER, RWRITE, ospfIfEntry, 3, {7, 1, 20}}, + + /* OSPF interface metric table. */ + {OSPFIFMETRICIPADDRESS, + IPADDRESS, + RONLY, + ospfIfMetricEntry, + 3, + {8, 1, 1}}, + {OSPFIFMETRICADDRESSLESSIF, + INTEGER, + RONLY, + ospfIfMetricEntry, + 3, + {8, 1, 2}}, + {OSPFIFMETRICTOS, INTEGER, RONLY, ospfIfMetricEntry, 3, {8, 1, 3}}, + {OSPFIFMETRICVALUE, INTEGER, RWRITE, ospfIfMetricEntry, 3, {8, 1, 4}}, + {OSPFIFMETRICSTATUS, INTEGER, RWRITE, ospfIfMetricEntry, 3, {8, 1, 5}}, + + /* OSPF virtual interface table. */ + {OSPFVIRTIFAREAID, IPADDRESS, RONLY, ospfVirtIfEntry, 3, {9, 1, 1}}, + {OSPFVIRTIFNEIGHBOR, IPADDRESS, RONLY, ospfVirtIfEntry, 3, {9, 1, 2}}, + {OSPFVIRTIFTRANSITDELAY, + INTEGER, + RWRITE, + ospfVirtIfEntry, + 3, + {9, 1, 3}}, + {OSPFVIRTIFRETRANSINTERVAL, + INTEGER, + RWRITE, + ospfVirtIfEntry, + 3, + {9, 1, 4}}, + {OSPFVIRTIFHELLOINTERVAL, + INTEGER, + RWRITE, + ospfVirtIfEntry, + 3, + {9, 1, 5}}, + {OSPFVIRTIFRTRDEADINTERVAL, + INTEGER, + RWRITE, + ospfVirtIfEntry, + 3, + {9, 1, 6}}, + {OSPFVIRTIFSTATE, INTEGER, RONLY, ospfVirtIfEntry, 3, {9, 1, 7}}, + {OSPFVIRTIFEVENTS, COUNTER, RONLY, ospfVirtIfEntry, 3, {9, 1, 8}}, + {OSPFVIRTIFAUTHKEY, STRING, RWRITE, ospfVirtIfEntry, 3, {9, 1, 9}}, + {OSPFVIRTIFSTATUS, INTEGER, RWRITE, ospfVirtIfEntry, 3, {9, 1, 10}}, + {OSPFVIRTIFAUTHTYPE, INTEGER, RWRITE, ospfVirtIfEntry, 3, {9, 1, 11}}, + + /* OSPF neighbor table. */ + {OSPFNBRIPADDR, IPADDRESS, RONLY, ospfNbrEntry, 3, {10, 1, 1}}, + {OSPFNBRADDRESSLESSINDEX, INTEGER, RONLY, ospfNbrEntry, 3, {10, 1, 2}}, + {OSPFNBRRTRID, IPADDRESS, RONLY, ospfNbrEntry, 3, {10, 1, 3}}, + {OSPFNBROPTIONS, INTEGER, RONLY, ospfNbrEntry, 3, {10, 1, 4}}, + {OSPFNBRPRIORITY, INTEGER, RWRITE, ospfNbrEntry, 3, {10, 1, 5}}, + {OSPFNBRSTATE, INTEGER, RONLY, ospfNbrEntry, 3, {10, 1, 6}}, + {OSPFNBREVENTS, COUNTER, RONLY, ospfNbrEntry, 3, {10, 1, 7}}, + {OSPFNBRLSRETRANSQLEN, GAUGE, RONLY, ospfNbrEntry, 3, {10, 1, 8}}, + {OSPFNBMANBRSTATUS, INTEGER, RWRITE, ospfNbrEntry, 3, {10, 1, 9}}, + {OSPFNBMANBRPERMANENCE, INTEGER, RONLY, ospfNbrEntry, 3, {10, 1, 10}}, + {OSPFNBRHELLOSUPPRESSED, INTEGER, RONLY, ospfNbrEntry, 3, {10, 1, 11}}, + + /* OSPF virtual neighbor table. */ + {OSPFVIRTNBRAREA, IPADDRESS, RONLY, ospfVirtNbrEntry, 3, {11, 1, 1}}, + {OSPFVIRTNBRRTRID, IPADDRESS, RONLY, ospfVirtNbrEntry, 3, {11, 1, 2}}, + {OSPFVIRTNBRIPADDR, IPADDRESS, RONLY, ospfVirtNbrEntry, 3, {11, 1, 3}}, + {OSPFVIRTNBROPTIONS, INTEGER, RONLY, ospfVirtNbrEntry, 3, {11, 1, 4}}, + {OSPFVIRTNBRSTATE, INTEGER, RONLY, ospfVirtNbrEntry, 3, {11, 1, 5}}, + {OSPFVIRTNBREVENTS, COUNTER, RONLY, ospfVirtNbrEntry, 3, {11, 1, 6}}, + {OSPFVIRTNBRLSRETRANSQLEN, + INTEGER, + RONLY, + ospfVirtNbrEntry, + 3, + {11, 1, 7}}, + {OSPFVIRTNBRHELLOSUPPRESSED, + INTEGER, + RONLY, + ospfVirtNbrEntry, + 3, + {11, 1, 8}}, + + /* OSPF link state database, external. */ + {OSPFEXTLSDBTYPE, INTEGER, RONLY, ospfExtLsdbEntry, 3, {12, 1, 1}}, + {OSPFEXTLSDBLSID, IPADDRESS, RONLY, ospfExtLsdbEntry, 3, {12, 1, 2}}, + {OSPFEXTLSDBROUTERID, + IPADDRESS, + RONLY, + ospfExtLsdbEntry, + 3, + {12, 1, 3}}, + {OSPFEXTLSDBSEQUENCE, INTEGER, RONLY, ospfExtLsdbEntry, 3, {12, 1, 4}}, + {OSPFEXTLSDBAGE, INTEGER, RONLY, ospfExtLsdbEntry, 3, {12, 1, 5}}, + {OSPFEXTLSDBCHECKSUM, INTEGER, RONLY, ospfExtLsdbEntry, 3, {12, 1, 6}}, + {OSPFEXTLSDBADVERTISEMENT, + STRING, + RONLY, + ospfExtLsdbEntry, + 3, + {12, 1, 7}}, + + /* OSPF area aggregate table. */ + {OSPFAREAAGGREGATEAREAID, + IPADDRESS, + RONLY, + ospfAreaAggregateEntry, + 3, + {14, 1, 1}}, + {OSPFAREAAGGREGATELSDBTYPE, + INTEGER, + RONLY, + ospfAreaAggregateEntry, + 3, + {14, 1, 2}}, + {OSPFAREAAGGREGATENET, + IPADDRESS, + RONLY, + ospfAreaAggregateEntry, + 3, + {14, 1, 3}}, + {OSPFAREAAGGREGATEMASK, + IPADDRESS, + RONLY, + ospfAreaAggregateEntry, + 3, + {14, 1, 4}}, + {OSPFAREAAGGREGATESTATUS, + INTEGER, + RWRITE, + ospfAreaAggregateEntry, + 3, + {14, 1, 5}}, + {OSPFAREAAGGREGATEEFFECT, + INTEGER, + RWRITE, + ospfAreaAggregateEntry, + 3, + {14, 1, 6}}}; /* The administrative status of OSPF. When OSPF is enbled on at least one interface return 1. */ -static int -ospf_admin_stat (struct ospf *ospf) +static int ospf_admin_stat(struct ospf *ospf) { - struct listnode *node; - struct ospf_interface *oi; + struct listnode *node; + struct ospf_interface *oi; - if (ospf == NULL) - return 0; + if (ospf == NULL) + return 0; - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) - if (oi && oi->address) - return 1; + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) + if (oi && oi->address) + return 1; - return 0; + return 0; } -static u_char * -ospfGeneralGroup (struct variable *v, oid *name, size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *ospfGeneralGroup(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - struct ospf *ospf; - - ospf = ospf_lookup (); - - /* Check whether the instance identifier is valid */ - if (smux_header_generic (v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - /* Return the current value of the variable */ - switch (v->magic) - { - case OSPFROUTERID: /* 1 */ - /* Router-ID of this OSPF instance. */ - if (ospf) - return SNMP_IPADDRESS (ospf->router_id); - else - return SNMP_IPADDRESS (ospf_empty_addr); - break; - case OSPFADMINSTAT: /* 2 */ - /* The administrative status of OSPF in the router. */ - if (ospf_admin_stat (ospf)) - return SNMP_INTEGER (OSPF_STATUS_ENABLED); - else - return SNMP_INTEGER (OSPF_STATUS_DISABLED); - break; - case OSPFVERSIONNUMBER: /* 3 */ - /* OSPF version 2. */ - return SNMP_INTEGER (OSPF_VERSION); - break; - case OSPFAREABDRRTRSTATUS: /* 4 */ - /* Area Border router status. */ - if (ospf && CHECK_FLAG (ospf->flags, OSPF_FLAG_ABR)) - return SNMP_INTEGER (SNMP_TRUE); - else - return SNMP_INTEGER (SNMP_FALSE); - break; - case OSPFASBDRRTRSTATUS: /* 5 */ - /* AS Border router status. */ - if (ospf && CHECK_FLAG (ospf->flags, OSPF_FLAG_ASBR)) - return SNMP_INTEGER (SNMP_TRUE); - else - return SNMP_INTEGER (SNMP_FALSE); - break; - case OSPFEXTERNLSACOUNT: /* 6 */ - /* External LSA counts. */ - if (ospf) - return SNMP_INTEGER (ospf_lsdb_count_all (ospf->lsdb)); - else - return SNMP_INTEGER (0); - break; - case OSPFEXTERNLSACKSUMSUM: /* 7 */ - /* External LSA checksum. */ - return SNMP_INTEGER (0); - break; - case OSPFTOSSUPPORT: /* 8 */ - /* TOS is not supported. */ - return SNMP_INTEGER (SNMP_FALSE); - break; - case OSPFORIGINATENEWLSAS: /* 9 */ - /* The number of new link-state advertisements. */ - if (ospf) - return SNMP_INTEGER (ospf->lsa_originate_count); - else - return SNMP_INTEGER (0); - break; - case OSPFRXNEWLSAS: /* 10 */ - /* The number of link-state advertisements received determined - to be new instantiations. */ - if (ospf) - return SNMP_INTEGER (ospf->rx_lsa_count); - else - return SNMP_INTEGER (0); - break; - case OSPFEXTLSDBLIMIT: /* 11 */ - /* There is no limit for the number of non-default - AS-external-LSAs. */ - return SNMP_INTEGER (-1); - break; - case OSPFMULTICASTEXTENSIONS: /* 12 */ - /* Multicast Extensions to OSPF is not supported. */ - return SNMP_INTEGER (0); - break; - case OSPFEXITOVERFLOWINTERVAL: /* 13 */ - /* Overflow is not supported. */ - return SNMP_INTEGER (0); - break; - case OSPFDEMANDEXTENSIONS: /* 14 */ - /* Demand routing is not supported. */ - return SNMP_INTEGER (SNMP_FALSE); - break; - default: - return NULL; - } - return NULL; + struct ospf *ospf; + + ospf = ospf_lookup(); + + /* Check whether the instance identifier is valid */ + if (smux_header_generic(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + /* Return the current value of the variable */ + switch (v->magic) { + case OSPFROUTERID: /* 1 */ + /* Router-ID of this OSPF instance. */ + if (ospf) + return SNMP_IPADDRESS(ospf->router_id); + else + return SNMP_IPADDRESS(ospf_empty_addr); + break; + case OSPFADMINSTAT: /* 2 */ + /* The administrative status of OSPF in the router. */ + if (ospf_admin_stat(ospf)) + return SNMP_INTEGER(OSPF_STATUS_ENABLED); + else + return SNMP_INTEGER(OSPF_STATUS_DISABLED); + break; + case OSPFVERSIONNUMBER: /* 3 */ + /* OSPF version 2. */ + return SNMP_INTEGER(OSPF_VERSION); + break; + case OSPFAREABDRRTRSTATUS: /* 4 */ + /* Area Border router status. */ + if (ospf && CHECK_FLAG(ospf->flags, OSPF_FLAG_ABR)) + return SNMP_INTEGER(SNMP_TRUE); + else + return SNMP_INTEGER(SNMP_FALSE); + break; + case OSPFASBDRRTRSTATUS: /* 5 */ + /* AS Border router status. */ + if (ospf && CHECK_FLAG(ospf->flags, OSPF_FLAG_ASBR)) + return SNMP_INTEGER(SNMP_TRUE); + else + return SNMP_INTEGER(SNMP_FALSE); + break; + case OSPFEXTERNLSACOUNT: /* 6 */ + /* External LSA counts. */ + if (ospf) + return SNMP_INTEGER(ospf_lsdb_count_all(ospf->lsdb)); + else + return SNMP_INTEGER(0); + break; + case OSPFEXTERNLSACKSUMSUM: /* 7 */ + /* External LSA checksum. */ + return SNMP_INTEGER(0); + break; + case OSPFTOSSUPPORT: /* 8 */ + /* TOS is not supported. */ + return SNMP_INTEGER(SNMP_FALSE); + break; + case OSPFORIGINATENEWLSAS: /* 9 */ + /* The number of new link-state advertisements. */ + if (ospf) + return SNMP_INTEGER(ospf->lsa_originate_count); + else + return SNMP_INTEGER(0); + break; + case OSPFRXNEWLSAS: /* 10 */ + /* The number of link-state advertisements received determined + to be new instantiations. */ + if (ospf) + return SNMP_INTEGER(ospf->rx_lsa_count); + else + return SNMP_INTEGER(0); + break; + case OSPFEXTLSDBLIMIT: /* 11 */ + /* There is no limit for the number of non-default + AS-external-LSAs. */ + return SNMP_INTEGER(-1); + break; + case OSPFMULTICASTEXTENSIONS: /* 12 */ + /* Multicast Extensions to OSPF is not supported. */ + return SNMP_INTEGER(0); + break; + case OSPFEXITOVERFLOWINTERVAL: /* 13 */ + /* Overflow is not supported. */ + return SNMP_INTEGER(0); + break; + case OSPFDEMANDEXTENSIONS: /* 14 */ + /* Demand routing is not supported. */ + return SNMP_INTEGER(SNMP_FALSE); + break; + default: + return NULL; + } + return NULL; } static struct ospf_area * -ospf_area_lookup_next (struct ospf *ospf, struct in_addr *area_id, int first) +ospf_area_lookup_next(struct ospf *ospf, struct in_addr *area_id, int first) { - struct ospf_area *area; - struct listnode *node; - - if (ospf == NULL) - return NULL; - - if (first) - { - node = listhead (ospf->areas); - if (node) - { - area = listgetdata (node); - *area_id = area->area_id; - return area; + struct ospf_area *area; + struct listnode *node; + + if (ospf == NULL) + return NULL; + + if (first) { + node = listhead(ospf->areas); + if (node) { + area = listgetdata(node); + *area_id = area->area_id; + return area; + } + return NULL; } - return NULL; - } - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - if (ntohl (area->area_id.s_addr) > ntohl (area_id->s_addr)) - { - *area_id = area->area_id; - return area; + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + if (ntohl(area->area_id.s_addr) > ntohl(area_id->s_addr)) { + *area_id = area->area_id; + return area; + } } - } - return NULL; + return NULL; } -static struct ospf_area * -ospfAreaLookup (struct variable *v, oid name[], size_t *length, - struct in_addr *addr, int exact) +static struct ospf_area *ospfAreaLookup(struct variable *v, oid name[], + size_t *length, struct in_addr *addr, + int exact) { - struct ospf *ospf; - struct ospf_area *area; - int len; - - ospf = ospf_lookup (); - if (ospf == NULL) - return NULL; - - if (exact) - { - /* Length is insufficient to lookup OSPF area. */ - if (*length - v->namelen != sizeof (struct in_addr)) - return NULL; + struct ospf *ospf; + struct ospf_area *area; + int len; - oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr); + ospf = ospf_lookup(); + if (ospf == NULL) + return NULL; - area = ospf_area_lookup_by_area_id (ospf, *addr); + if (exact) { + /* Length is insufficient to lookup OSPF area. */ + if (*length - v->namelen != sizeof(struct in_addr)) + return NULL; - return area; - } - else - { - len = *length - v->namelen; - if (len > 4) - len = 4; - - oid2in_addr (name + v->namelen, len, addr); + oid2in_addr(name + v->namelen, sizeof(struct in_addr), addr); - area = ospf_area_lookup_next (ospf, addr, len == 0 ? 1 : 0); + area = ospf_area_lookup_by_area_id(ospf, *addr); - if (area == NULL) - return NULL; - - oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr)); - *length = sizeof (struct in_addr) + v->namelen; + return area; + } else { + len = *length - v->namelen; + if (len > 4) + len = 4; - return area; - } - return NULL; -} + oid2in_addr(name + v->namelen, len, addr); -static u_char * -ospfAreaEntry (struct variable *v, oid *name, size_t *length, int exact, - size_t *var_len, WriteMethod **write_method) -{ - struct ospf_area *area; - struct in_addr addr; - - if (smux_header_table(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - memset (&addr, 0, sizeof (struct in_addr)); - - area = ospfAreaLookup (v, name, length, &addr, exact); - if (! area) - return NULL; - - /* Return the current value of the variable */ - switch (v->magic) - { - case OSPFAREAID: /* 1 */ - return SNMP_IPADDRESS (area->area_id); - break; - case OSPFAUTHTYPE: /* 2 */ - return SNMP_INTEGER (area->auth_type); - break; - case OSPFIMPORTASEXTERN: /* 3 */ - return SNMP_INTEGER (area->external_routing + 1); - break; - case OSPFSPFRUNS: /* 4 */ - return SNMP_INTEGER (area->spf_calculation); - break; - case OSPFAREABDRRTRCOUNT: /* 5 */ - return SNMP_INTEGER (area->abr_count); - break; - case OSPFASBDRRTRCOUNT: /* 6 */ - return SNMP_INTEGER (area->asbr_count); - break; - case OSPFAREALSACOUNT: /* 7 */ - return SNMP_INTEGER (area->lsdb->total); - break; - case OSPFAREALSACKSUMSUM: /* 8 */ - return SNMP_INTEGER (0); - break; - case OSPFAREASUMMARY: /* 9 */ -#define OSPF_noAreaSummary 1 -#define OSPF_sendAreaSummary 2 - if (area->no_summary) - return SNMP_INTEGER (OSPF_noAreaSummary); - else - return SNMP_INTEGER (OSPF_sendAreaSummary); - break; - case OSPFAREASTATUS: /* 10 */ - return SNMP_INTEGER (SNMP_VALID); - break; - default: - return NULL; - break; - } - return NULL; -} + area = ospf_area_lookup_next(ospf, addr, len == 0 ? 1 : 0); -static struct ospf_area * -ospf_stub_area_lookup_next (struct in_addr *area_id, int first) -{ - struct ospf_area *area; - struct listnode *node; - struct ospf *ospf; + if (area == NULL) + return NULL; - ospf = ospf_lookup (); - if (ospf == NULL) - return NULL; + oid_copy_addr(name + v->namelen, addr, sizeof(struct in_addr)); + *length = sizeof(struct in_addr) + v->namelen; - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - if (area->external_routing == OSPF_AREA_STUB) - { - if (first) - { - *area_id = area->area_id; - return area; - } - else if (ntohl (area->area_id.s_addr) > ntohl (area_id->s_addr)) - { - *area_id = area->area_id; - return area; - } + return area; } - } - return NULL; + return NULL; } -static struct ospf_area * -ospfStubAreaLookup (struct variable *v, oid name[], size_t *length, - struct in_addr *addr, int exact) +static u_char *ospfAreaEntry(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - struct ospf *ospf; - struct ospf_area *area; - int len; - - ospf = ospf_lookup (); - if (ospf == NULL) - return NULL; - - /* Exact lookup. */ - if (exact) - { - /* ospfStubAreaID + ospfStubTOS. */ - if (*length != v->namelen + sizeof (struct in_addr) + 1) - return NULL; - - /* Check ospfStubTOS is zero. */ - if (name[*length - 1] != 0) - return NULL; - - oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr); - - area = ospf_area_lookup_by_area_id (ospf, *addr); - - if (area->external_routing == OSPF_AREA_STUB) - return area; - else - return NULL; - } - else - { - len = *length - v->namelen; - if (len > 4) - len = 4; - - oid2in_addr (name + v->namelen, len, addr); - - area = ospf_stub_area_lookup_next (addr, len == 0 ? 1 : 0); - - if (area == NULL) + struct ospf_area *area; + struct in_addr addr; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + memset(&addr, 0, sizeof(struct in_addr)); + + area = ospfAreaLookup(v, name, length, &addr, exact); + if (!area) + return NULL; + + /* Return the current value of the variable */ + switch (v->magic) { + case OSPFAREAID: /* 1 */ + return SNMP_IPADDRESS(area->area_id); + break; + case OSPFAUTHTYPE: /* 2 */ + return SNMP_INTEGER(area->auth_type); + break; + case OSPFIMPORTASEXTERN: /* 3 */ + return SNMP_INTEGER(area->external_routing + 1); + break; + case OSPFSPFRUNS: /* 4 */ + return SNMP_INTEGER(area->spf_calculation); + break; + case OSPFAREABDRRTRCOUNT: /* 5 */ + return SNMP_INTEGER(area->abr_count); + break; + case OSPFASBDRRTRCOUNT: /* 6 */ + return SNMP_INTEGER(area->asbr_count); + break; + case OSPFAREALSACOUNT: /* 7 */ + return SNMP_INTEGER(area->lsdb->total); + break; + case OSPFAREALSACKSUMSUM: /* 8 */ + return SNMP_INTEGER(0); + break; + case OSPFAREASUMMARY: /* 9 */ + /* $FRR indent$ */ + /* clang-format off */ +#define OSPF_noAreaSummary 1 +#define OSPF_sendAreaSummary 2 + if (area->no_summary) + return SNMP_INTEGER(OSPF_noAreaSummary); + else + return SNMP_INTEGER(OSPF_sendAreaSummary); + break; + case OSPFAREASTATUS: /* 10 */ + return SNMP_INTEGER(SNMP_VALID); + break; + default: + return NULL; + break; + } return NULL; - - oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr)); - /* Set TOS 0. */ - name[v->namelen + sizeof (struct in_addr)] = 0; - *length = v->namelen + sizeof (struct in_addr) + 1; - - return area; - } - return NULL; } -static u_char * -ospfStubAreaEntry (struct variable *v, oid *name, size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static struct ospf_area *ospf_stub_area_lookup_next(struct in_addr *area_id, + int first) { - struct ospf_area *area; - struct in_addr addr; - - if (smux_header_table(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - memset (&addr, 0, sizeof (struct in_addr)); - - area = ospfStubAreaLookup (v, name, length, &addr, exact); - if (! area) - return NULL; - - /* Return the current value of the variable */ - switch (v->magic) - { - case OSPFSTUBAREAID: /* 1 */ - /* OSPF stub area id. */ - return SNMP_IPADDRESS (area->area_id); - break; - case OSPFSTUBTOS: /* 2 */ - /* TOS value is not supported. */ - return SNMP_INTEGER (0); - break; - case OSPFSTUBMETRIC: /* 3 */ - /* Default cost to stub area. */ - return SNMP_INTEGER (area->default_cost); - break; - case OSPFSTUBSTATUS: /* 4 */ - /* Status of the stub area. */ - return SNMP_INTEGER (SNMP_VALID); - break; - case OSPFSTUBMETRICTYPE: /* 5 */ - /* OSPF Metric type. */ -#define OSPF_ospfMetric 1 -#define OSPF_comparableCost 2 -#define OSPF_nonComparable 3 - return SNMP_INTEGER (OSPF_ospfMetric); - break; - default: - return NULL; - break; - } - return NULL; + struct ospf_area *area; + struct listnode *node; + struct ospf *ospf; + + ospf = ospf_lookup(); + if (ospf == NULL) + return NULL; + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + if (area->external_routing == OSPF_AREA_STUB) { + if (first) { + *area_id = area->area_id; + return area; + } else if (ntohl(area->area_id.s_addr) + > ntohl(area_id->s_addr)) { + *area_id = area->area_id; + return area; + } + } + } + return NULL; } -static struct ospf_lsa * -lsdb_lookup_next (struct ospf_area *area, u_char *type, int type_next, - struct in_addr *ls_id, int ls_id_next, - struct in_addr *router_id, int router_id_next) +static struct ospf_area *ospfStubAreaLookup(struct variable *v, oid name[], + size_t *length, + struct in_addr *addr, int exact) { - struct ospf_lsa *lsa; - int i; - - if (type_next) - i = OSPF_MIN_LSA; - else - i = *type; - - /* Sanity check, if LSA type unknwon - merley skip any LSA */ - if ((i < OSPF_MIN_LSA) || (i >= OSPF_MAX_LSA)) - { - zlog_debug("Strange request with LSA type %d\n", i); - return NULL; - } - - for (; i < OSPF_MAX_LSA; i++) - { - *type = i; - - lsa = ospf_lsdb_lookup_by_id_next (area->lsdb, *type, *ls_id, *router_id, - ls_id_next); - if (lsa) - return lsa; - - ls_id_next = 1; - } - return NULL; -} + struct ospf *ospf; + struct ospf_area *area; + int len; -static struct ospf_lsa * -ospfLsdbLookup (struct variable *v, oid *name, size_t *length, - struct in_addr *area_id, u_char *type, - struct in_addr *ls_id, struct in_addr *router_id, int exact) -{ - struct ospf *ospf; - struct ospf_area *area; - struct ospf_lsa *lsa; - int len; - int type_next; - int ls_id_next; - int router_id_next; - oid *offset; - int offsetlen; - - ospf = ospf_lookup (); - -#define OSPF_LSDB_ENTRY_OFFSET \ - (IN_ADDR_SIZE + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE) - - if (exact) - { - /* Area ID + Type + LS ID + Router ID. */ - if (*length - v->namelen != OSPF_LSDB_ENTRY_OFFSET) - return NULL; - - /* Set OID offset for Area ID. */ - offset = name + v->namelen; - - /* Lookup area first. */ - oid2in_addr (offset, IN_ADDR_SIZE, area_id); - area = ospf_area_lookup_by_area_id (ospf, *area_id); - if (! area) - return NULL; - offset += IN_ADDR_SIZE; + ospf = ospf_lookup(); + if (ospf == NULL) + return NULL; - /* Type. */ - *type = *offset; - offset++; + /* Exact lookup. */ + if (exact) { + /* ospfStubAreaID + ospfStubTOS. */ + if (*length != v->namelen + sizeof(struct in_addr) + 1) + return NULL; - /* LS ID. */ - oid2in_addr (offset, IN_ADDR_SIZE, ls_id); - offset += IN_ADDR_SIZE; + /* Check ospfStubTOS is zero. */ + if (name[*length - 1] != 0) + return NULL; - /* Router ID. */ - oid2in_addr (offset, IN_ADDR_SIZE, router_id); + oid2in_addr(name + v->namelen, sizeof(struct in_addr), addr); - /* Lookup LSDB. */ - return ospf_lsdb_lookup_by_id (area->lsdb, *type, *ls_id, *router_id); - } - else - { - /* Get variable length. */ - offset = name + v->namelen; - offsetlen = *length - v->namelen; - len = offsetlen; + area = ospf_area_lookup_by_area_id(ospf, *addr); - if (len > (int)IN_ADDR_SIZE) - len = IN_ADDR_SIZE; + if (area->external_routing == OSPF_AREA_STUB) + return area; + else + return NULL; + } else { + len = *length - v->namelen; + if (len > 4) + len = 4; - oid2in_addr (offset, len, area_id); + oid2in_addr(name + v->namelen, len, addr); - /* First we search area. */ - if (len == IN_ADDR_SIZE) - area = ospf_area_lookup_by_area_id (ospf, *area_id); - else - area = ospf_area_lookup_next (ospf, area_id, 1); + area = ospf_stub_area_lookup_next(addr, len == 0 ? 1 : 0); - if (area == NULL) - return NULL; + if (area == NULL) + return NULL; - do - { - /* Next we lookup type. */ - offset += len; - offsetlen -= len; - len = offsetlen; - - if (len <= 0) - type_next = 1; - else - { - len = 1; - type_next = 0; - *type = *offset; - } - - /* LS ID. */ - offset++; - offsetlen--; - len = offsetlen; - - if (len <= 0) - ls_id_next = 1; - else - { - ls_id_next = 0; - if (len > (int)IN_ADDR_SIZE) - len = IN_ADDR_SIZE; - - oid2in_addr (offset, len, ls_id); - } - - /* Router ID. */ - offset += IN_ADDR_SIZE; - offsetlen -= IN_ADDR_SIZE; - len = offsetlen; - - if (len <= 0) - router_id_next = 1; - else - { - router_id_next = 0; - if (len > (int)IN_ADDR_SIZE) - len = IN_ADDR_SIZE; - - oid2in_addr (offset, len, router_id); - } - - lsa = lsdb_lookup_next (area, type, type_next, ls_id, ls_id_next, - router_id, router_id_next); - - if (lsa) - { - /* Fill in length. */ - *length = v->namelen + OSPF_LSDB_ENTRY_OFFSET; - - /* Fill in value. */ - offset = name + v->namelen; - oid_copy_addr (offset, area_id, IN_ADDR_SIZE); - offset += IN_ADDR_SIZE; - *offset = lsa->data->type; - offset++; - oid_copy_addr (offset, &lsa->data->id, IN_ADDR_SIZE); - offset += IN_ADDR_SIZE; - oid_copy_addr (offset, &lsa->data->adv_router, IN_ADDR_SIZE); - - return lsa; - } + oid_copy_addr(name + v->namelen, addr, sizeof(struct in_addr)); + /* Set TOS 0. */ + name[v->namelen + sizeof(struct in_addr)] = 0; + *length = v->namelen + sizeof(struct in_addr) + 1; + + return area; } - while ((area = ospf_area_lookup_next (ospf, area_id, 0)) != NULL); - } - return NULL; + return NULL; } -static u_char * -ospfLsdbEntry (struct variable *v, oid *name, size_t *length, int exact, - size_t *var_len, WriteMethod **write_method) +static u_char *ospfStubAreaEntry(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - struct ospf_lsa *lsa; - struct lsa_header *lsah; - struct in_addr area_id; - u_char type; - struct in_addr ls_id; - struct in_addr router_id; - struct ospf *ospf; - - if (smux_header_table(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - /* INDEX { ospfLsdbAreaId, ospfLsdbType, - ospfLsdbLsid, ospfLsdbRouterId } */ - - memset (&area_id, 0, sizeof (struct in_addr)); - type = 0; - memset (&ls_id, 0, sizeof (struct in_addr)); - memset (&router_id, 0, sizeof (struct in_addr)); - - /* Check OSPF instance. */ - ospf = ospf_lookup (); - if (ospf == NULL) - return NULL; - - lsa = ospfLsdbLookup (v, name, length, &area_id, &type, &ls_id, &router_id, - exact); - if (! lsa) - return NULL; - - lsah = lsa->data; - - /* Return the current value of the variable */ - switch (v->magic) - { - case OSPFLSDBAREAID: /* 1 */ - return SNMP_IPADDRESS (lsa->area->area_id); - break; - case OSPFLSDBTYPE: /* 2 */ - return SNMP_INTEGER (lsah->type); - break; - case OSPFLSDBLSID: /* 3 */ - return SNMP_IPADDRESS (lsah->id); - break; - case OSPFLSDBROUTERID: /* 4 */ - return SNMP_IPADDRESS (lsah->adv_router); - break; - case OSPFLSDBSEQUENCE: /* 5 */ - return SNMP_INTEGER (lsah->ls_seqnum); - break; - case OSPFLSDBAGE: /* 6 */ - return SNMP_INTEGER (lsah->ls_age); - break; - case OSPFLSDBCHECKSUM: /* 7 */ - return SNMP_INTEGER (lsah->checksum); - break; - case OSPFLSDBADVERTISEMENT: /* 8 */ - *var_len = ntohs (lsah->length); - return (u_char *) lsah; - break; - default: - return NULL; - break; - } - return NULL; + struct ospf_area *area; + struct in_addr addr; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + memset(&addr, 0, sizeof(struct in_addr)); + + area = ospfStubAreaLookup(v, name, length, &addr, exact); + if (!area) + return NULL; + + /* Return the current value of the variable */ + switch (v->magic) { + case OSPFSTUBAREAID: /* 1 */ + /* OSPF stub area id. */ + return SNMP_IPADDRESS(area->area_id); + break; + case OSPFSTUBTOS: /* 2 */ + /* TOS value is not supported. */ + return SNMP_INTEGER(0); + break; + case OSPFSTUBMETRIC: /* 3 */ + /* Default cost to stub area. */ + return SNMP_INTEGER(area->default_cost); + break; + case OSPFSTUBSTATUS: /* 4 */ + /* Status of the stub area. */ + return SNMP_INTEGER(SNMP_VALID); + break; + case OSPFSTUBMETRICTYPE: /* 5 */ +/* OSPF Metric type. */ +#define OSPF_ospfMetric 1 +#define OSPF_comparableCost 2 +#define OSPF_nonComparable 3 + return SNMP_INTEGER(OSPF_ospfMetric); + break; + default: + return NULL; + break; + } + return NULL; } -static struct ospf_area_range * -ospfAreaRangeLookup (struct variable *v, oid *name, size_t *length, - struct in_addr *area_id, struct in_addr *range_net, - int exact) +static struct ospf_lsa *lsdb_lookup_next(struct ospf_area *area, u_char *type, + int type_next, struct in_addr *ls_id, + int ls_id_next, + struct in_addr *router_id, + int router_id_next) { - oid *offset; - int offsetlen; - int len; - struct ospf *ospf; - struct ospf_area *area; - struct ospf_area_range *range; - struct prefix_ipv4 p; - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - - ospf = ospf_lookup (); - - if (exact) - { - /* Area ID + Range Network. */ - if (v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE != *length) - return NULL; + struct ospf_lsa *lsa; + int i; + + if (type_next) + i = OSPF_MIN_LSA; + else + i = *type; + + /* Sanity check, if LSA type unknwon + merley skip any LSA */ + if ((i < OSPF_MIN_LSA) || (i >= OSPF_MAX_LSA)) { + zlog_debug("Strange request with LSA type %d\n", i); + return NULL; + } - /* Set OID offset for Area ID. */ - offset = name + v->namelen; + for (; i < OSPF_MAX_LSA; i++) { + *type = i; - /* Lookup area first. */ - oid2in_addr (offset, IN_ADDR_SIZE, area_id); + lsa = ospf_lsdb_lookup_by_id_next(area->lsdb, *type, *ls_id, + *router_id, ls_id_next); + if (lsa) + return lsa; - area = ospf_area_lookup_by_area_id (ospf, *area_id); - if (! area) + ls_id_next = 1; + } return NULL; +} - offset += IN_ADDR_SIZE; - - /* Lookup area range. */ - oid2in_addr (offset, IN_ADDR_SIZE, range_net); - p.prefix = *range_net; - - return ospf_area_range_lookup (area, &p); - } - else - { - /* Set OID offset for Area ID. */ - offset = name + v->namelen; - offsetlen = *length - v->namelen; - - len = offsetlen; - if (len > (int)IN_ADDR_SIZE) - len = IN_ADDR_SIZE; - - oid2in_addr (offset, len, area_id); - - /* First we search area. */ - if (len == IN_ADDR_SIZE) - area = ospf_area_lookup_by_area_id (ospf,*area_id); - else - area = ospf_area_lookup_next (ospf, area_id, len == 0 ? 1 : 0); - - if (area == NULL) +static struct ospf_lsa *ospfLsdbLookup(struct variable *v, oid *name, + size_t *length, struct in_addr *area_id, + u_char *type, struct in_addr *ls_id, + struct in_addr *router_id, int exact) +{ + struct ospf *ospf; + struct ospf_area *area; + struct ospf_lsa *lsa; + int len; + int type_next; + int ls_id_next; + int router_id_next; + oid *offset; + int offsetlen; + + ospf = ospf_lookup(); + +#define OSPF_LSDB_ENTRY_OFFSET (IN_ADDR_SIZE + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE) + + if (exact) { + /* Area ID + Type + LS ID + Router ID. */ + if (*length - v->namelen != OSPF_LSDB_ENTRY_OFFSET) + return NULL; + + /* Set OID offset for Area ID. */ + offset = name + v->namelen; + + /* Lookup area first. */ + oid2in_addr(offset, IN_ADDR_SIZE, area_id); + area = ospf_area_lookup_by_area_id(ospf, *area_id); + if (!area) + return NULL; + offset += IN_ADDR_SIZE; + + /* Type. */ + *type = *offset; + offset++; + + /* LS ID. */ + oid2in_addr(offset, IN_ADDR_SIZE, ls_id); + offset += IN_ADDR_SIZE; + + /* Router ID. */ + oid2in_addr(offset, IN_ADDR_SIZE, router_id); + + /* Lookup LSDB. */ + return ospf_lsdb_lookup_by_id(area->lsdb, *type, *ls_id, + *router_id); + } else { + /* Get variable length. */ + offset = name + v->namelen; + offsetlen = *length - v->namelen; + len = offsetlen; + + if (len > (int)IN_ADDR_SIZE) + len = IN_ADDR_SIZE; + + oid2in_addr(offset, len, area_id); + + /* First we search area. */ + if (len == IN_ADDR_SIZE) + area = ospf_area_lookup_by_area_id(ospf, *area_id); + else + area = ospf_area_lookup_next(ospf, area_id, 1); + + if (area == NULL) + return NULL; + + do { + /* Next we lookup type. */ + offset += len; + offsetlen -= len; + len = offsetlen; + + if (len <= 0) + type_next = 1; + else { + len = 1; + type_next = 0; + *type = *offset; + } + + /* LS ID. */ + offset++; + offsetlen--; + len = offsetlen; + + if (len <= 0) + ls_id_next = 1; + else { + ls_id_next = 0; + if (len > (int)IN_ADDR_SIZE) + len = IN_ADDR_SIZE; + + oid2in_addr(offset, len, ls_id); + } + + /* Router ID. */ + offset += IN_ADDR_SIZE; + offsetlen -= IN_ADDR_SIZE; + len = offsetlen; + + if (len <= 0) + router_id_next = 1; + else { + router_id_next = 0; + if (len > (int)IN_ADDR_SIZE) + len = IN_ADDR_SIZE; + + oid2in_addr(offset, len, router_id); + } + + lsa = lsdb_lookup_next(area, type, type_next, ls_id, + ls_id_next, router_id, + router_id_next); + + if (lsa) { + /* Fill in length. */ + *length = v->namelen + OSPF_LSDB_ENTRY_OFFSET; + + /* Fill in value. */ + offset = name + v->namelen; + oid_copy_addr(offset, area_id, IN_ADDR_SIZE); + offset += IN_ADDR_SIZE; + *offset = lsa->data->type; + offset++; + oid_copy_addr(offset, &lsa->data->id, + IN_ADDR_SIZE); + offset += IN_ADDR_SIZE; + oid_copy_addr(offset, &lsa->data->adv_router, + IN_ADDR_SIZE); + + return lsa; + } + } while ((area = ospf_area_lookup_next(ospf, area_id, 0)) + != NULL); + } return NULL; +} - do - { - offset += IN_ADDR_SIZE; - offsetlen -= IN_ADDR_SIZE; - len = offsetlen; - - if (len < 0) - len = 0; - if (len > (int)IN_ADDR_SIZE) - len = IN_ADDR_SIZE; - - oid2in_addr (offset, len, range_net); - - range = ospf_area_range_lookup_next (area, range_net, - len == 0 ? 1 : 0); - - if (range) - { - /* Fill in length. */ - *length = v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE; - - /* Fill in value. */ - offset = name + v->namelen; - oid_copy_addr (offset, area_id, IN_ADDR_SIZE); - offset += IN_ADDR_SIZE; - oid_copy_addr (offset, range_net, IN_ADDR_SIZE); +static u_char *ospfLsdbEntry(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) +{ + struct ospf_lsa *lsa; + struct lsa_header *lsah; + struct in_addr area_id; + u_char type; + struct in_addr ls_id; + struct in_addr router_id; + struct ospf *ospf; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + /* INDEX { ospfLsdbAreaId, ospfLsdbType, + ospfLsdbLsid, ospfLsdbRouterId } */ + + memset(&area_id, 0, sizeof(struct in_addr)); + type = 0; + memset(&ls_id, 0, sizeof(struct in_addr)); + memset(&router_id, 0, sizeof(struct in_addr)); + + /* Check OSPF instance. */ + ospf = ospf_lookup(); + if (ospf == NULL) + return NULL; + + lsa = ospfLsdbLookup(v, name, length, &area_id, &type, &ls_id, + &router_id, exact); + if (!lsa) + return NULL; + + lsah = lsa->data; + + /* Return the current value of the variable */ + switch (v->magic) { + case OSPFLSDBAREAID: /* 1 */ + return SNMP_IPADDRESS(lsa->area->area_id); + break; + case OSPFLSDBTYPE: /* 2 */ + return SNMP_INTEGER(lsah->type); + break; + case OSPFLSDBLSID: /* 3 */ + return SNMP_IPADDRESS(lsah->id); + break; + case OSPFLSDBROUTERID: /* 4 */ + return SNMP_IPADDRESS(lsah->adv_router); + break; + case OSPFLSDBSEQUENCE: /* 5 */ + return SNMP_INTEGER(lsah->ls_seqnum); + break; + case OSPFLSDBAGE: /* 6 */ + return SNMP_INTEGER(lsah->ls_age); + break; + case OSPFLSDBCHECKSUM: /* 7 */ + return SNMP_INTEGER(lsah->checksum); + break; + case OSPFLSDBADVERTISEMENT: /* 8 */ + *var_len = ntohs(lsah->length); + return (u_char *)lsah; + break; + default: + return NULL; + break; + } + return NULL; +} - return range; - } +static struct ospf_area_range *ospfAreaRangeLookup(struct variable *v, + oid *name, size_t *length, + struct in_addr *area_id, + struct in_addr *range_net, + int exact) +{ + oid *offset; + int offsetlen; + int len; + struct ospf *ospf; + struct ospf_area *area; + struct ospf_area_range *range; + struct prefix_ipv4 p; + p.family = AF_INET; + p.prefixlen = IPV4_MAX_BITLEN; + + ospf = ospf_lookup(); + + if (exact) { + /* Area ID + Range Network. */ + if (v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE != *length) + return NULL; + + /* Set OID offset for Area ID. */ + offset = name + v->namelen; + + /* Lookup area first. */ + oid2in_addr(offset, IN_ADDR_SIZE, area_id); + + area = ospf_area_lookup_by_area_id(ospf, *area_id); + if (!area) + return NULL; + + offset += IN_ADDR_SIZE; + + /* Lookup area range. */ + oid2in_addr(offset, IN_ADDR_SIZE, range_net); + p.prefix = *range_net; + + return ospf_area_range_lookup(area, &p); + } else { + /* Set OID offset for Area ID. */ + offset = name + v->namelen; + offsetlen = *length - v->namelen; + + len = offsetlen; + if (len > (int)IN_ADDR_SIZE) + len = IN_ADDR_SIZE; + + oid2in_addr(offset, len, area_id); + + /* First we search area. */ + if (len == IN_ADDR_SIZE) + area = ospf_area_lookup_by_area_id(ospf, *area_id); + else + area = ospf_area_lookup_next(ospf, area_id, + len == 0 ? 1 : 0); + + if (area == NULL) + return NULL; + + do { + offset += IN_ADDR_SIZE; + offsetlen -= IN_ADDR_SIZE; + len = offsetlen; + + if (len < 0) + len = 0; + if (len > (int)IN_ADDR_SIZE) + len = IN_ADDR_SIZE; + + oid2in_addr(offset, len, range_net); + + range = ospf_area_range_lookup_next(area, range_net, + len == 0 ? 1 : 0); + + if (range) { + /* Fill in length. */ + *length = v->namelen + IN_ADDR_SIZE + + IN_ADDR_SIZE; + + /* Fill in value. */ + offset = name + v->namelen; + oid_copy_addr(offset, area_id, IN_ADDR_SIZE); + offset += IN_ADDR_SIZE; + oid_copy_addr(offset, range_net, IN_ADDR_SIZE); + + return range; + } + } while ((area = ospf_area_lookup_next(ospf, area_id, 0)) + != NULL); } - while ((area = ospf_area_lookup_next (ospf, area_id, 0)) != NULL); - } - return NULL; + return NULL; } -static u_char * -ospfAreaRangeEntry (struct variable *v, oid *name, size_t *length, int exact, - size_t *var_len, WriteMethod **write_method) +static u_char *ospfAreaRangeEntry(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - struct ospf_area_range *range; - struct in_addr area_id; - struct in_addr range_net; - struct in_addr mask; - struct ospf *ospf; - - if (smux_header_table(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - /* Check OSPF instance. */ - ospf = ospf_lookup (); - if (ospf == NULL) - return NULL; - - memset (&area_id, 0, IN_ADDR_SIZE); - memset (&range_net, 0, IN_ADDR_SIZE); - - range = ospfAreaRangeLookup (v, name, length, &area_id, &range_net, exact); - if (! range) - return NULL; - - /* Convert prefixlen to network mask format. */ - masklen2ip (range->subst_masklen, &mask); - - /* Return the current value of the variable */ - switch (v->magic) - { - case OSPFAREARANGEAREAID: /* 1 */ - return SNMP_IPADDRESS (area_id); - break; - case OSPFAREARANGENET: /* 2 */ - return SNMP_IPADDRESS (range_net); - break; - case OSPFAREARANGEMASK: /* 3 */ - return SNMP_IPADDRESS (mask); - break; - case OSPFAREARANGESTATUS: /* 4 */ - return SNMP_INTEGER (SNMP_VALID); - break; - case OSPFAREARANGEEFFECT: /* 5 */ + struct ospf_area_range *range; + struct in_addr area_id; + struct in_addr range_net; + struct in_addr mask; + struct ospf *ospf; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + /* Check OSPF instance. */ + ospf = ospf_lookup(); + if (ospf == NULL) + return NULL; + + memset(&area_id, 0, IN_ADDR_SIZE); + memset(&range_net, 0, IN_ADDR_SIZE); + + range = ospfAreaRangeLookup(v, name, length, &area_id, &range_net, + exact); + if (!range) + return NULL; + + /* Convert prefixlen to network mask format. */ + masklen2ip(range->subst_masklen, &mask); + + /* Return the current value of the variable */ + switch (v->magic) { + case OSPFAREARANGEAREAID: /* 1 */ + return SNMP_IPADDRESS(area_id); + break; + case OSPFAREARANGENET: /* 2 */ + return SNMP_IPADDRESS(range_net); + break; + case OSPFAREARANGEMASK: /* 3 */ + return SNMP_IPADDRESS(mask); + break; + case OSPFAREARANGESTATUS: /* 4 */ + return SNMP_INTEGER(SNMP_VALID); + break; + case OSPFAREARANGEEFFECT: /* 5 */ + /* $FRR indent$ */ + /* clang-format off */ #define OSPF_advertiseMatching 1 #define OSPF_doNotAdvertiseMatching 2 - return SNMP_INTEGER (OSPF_advertiseMatching); - break; - default: - return NULL; - break; - } - return NULL; + return SNMP_INTEGER(OSPF_advertiseMatching); + break; + default: + return NULL; + break; + } + return NULL; } -static struct ospf_nbr_nbma * -ospfHostLookup (struct variable *v, oid *name, size_t *length, - struct in_addr *addr, int exact) +static struct ospf_nbr_nbma *ospfHostLookup(struct variable *v, oid *name, + size_t *length, + struct in_addr *addr, int exact) { - int len; - struct ospf_nbr_nbma *nbr_nbma; - struct ospf *ospf; - - ospf = ospf_lookup (); - if (ospf == NULL) - return NULL; - - if (exact) - { - /* INDEX { ospfHostIpAddress, ospfHostTOS } */ - if (*length != v->namelen + IN_ADDR_SIZE + 1) - return NULL; + int len; + struct ospf_nbr_nbma *nbr_nbma; + struct ospf *ospf; - /* Check ospfHostTOS. */ - if (name[*length - 1] != 0) - return NULL; + ospf = ospf_lookup(); + if (ospf == NULL) + return NULL; - oid2in_addr (name + v->namelen, IN_ADDR_SIZE, addr); + if (exact) { + /* INDEX { ospfHostIpAddress, ospfHostTOS } */ + if (*length != v->namelen + IN_ADDR_SIZE + 1) + return NULL; - nbr_nbma = ospf_nbr_nbma_lookup (ospf, *addr); + /* Check ospfHostTOS. */ + if (name[*length - 1] != 0) + return NULL; - return nbr_nbma; - } - else - { - len = *length - v->namelen; - if (len > 4) - len = 4; - - oid2in_addr (name + v->namelen, len, addr); + oid2in_addr(name + v->namelen, IN_ADDR_SIZE, addr); - nbr_nbma = ospf_nbr_nbma_lookup_next (ospf, addr, len == 0 ? 1 : 0); + nbr_nbma = ospf_nbr_nbma_lookup(ospf, *addr); - if (nbr_nbma == NULL) - return NULL; + return nbr_nbma; + } else { + len = *length - v->namelen; + if (len > 4) + len = 4; + + oid2in_addr(name + v->namelen, len, addr); + + nbr_nbma = + ospf_nbr_nbma_lookup_next(ospf, addr, len == 0 ? 1 : 0); - oid_copy_addr (name + v->namelen, addr, IN_ADDR_SIZE); + if (nbr_nbma == NULL) + return NULL; - /* Set TOS 0. */ - name[v->namelen + IN_ADDR_SIZE] = 0; + oid_copy_addr(name + v->namelen, addr, IN_ADDR_SIZE); - *length = v->namelen + IN_ADDR_SIZE + 1; + /* Set TOS 0. */ + name[v->namelen + IN_ADDR_SIZE] = 0; - return nbr_nbma; - } - return NULL; + *length = v->namelen + IN_ADDR_SIZE + 1; + + return nbr_nbma; + } + return NULL; } -static u_char * -ospfHostEntry (struct variable *v, oid *name, size_t *length, int exact, - size_t *var_len, WriteMethod **write_method) +static u_char *ospfHostEntry(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - struct ospf_nbr_nbma *nbr_nbma; - struct ospf_interface *oi; - struct in_addr addr; - struct ospf *ospf; - - if (smux_header_table(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - /* Check OSPF instance. */ - ospf = ospf_lookup (); - if (ospf == NULL) - return NULL; - - memset (&addr, 0, sizeof (struct in_addr)); - - nbr_nbma = ospfHostLookup (v, name, length, &addr, exact); - if (nbr_nbma == NULL) - return NULL; - - oi = nbr_nbma->oi; - - /* Return the current value of the variable */ - switch (v->magic) - { - case OSPFHOSTIPADDRESS: /* 1 */ - return SNMP_IPADDRESS (nbr_nbma->addr); - break; - case OSPFHOSTTOS: /* 2 */ - return SNMP_INTEGER (0); - break; - case OSPFHOSTMETRIC: /* 3 */ - if (oi) - return SNMP_INTEGER (oi->output_cost); - else - return SNMP_INTEGER (1); - break; - case OSPFHOSTSTATUS: /* 4 */ - return SNMP_INTEGER (SNMP_VALID); - break; - case OSPFHOSTAREAID: /* 5 */ - if (oi && oi->area) - return SNMP_IPADDRESS (oi->area->area_id); - else - return SNMP_IPADDRESS (ospf_empty_addr); - break; - default: - return NULL; - break; - } - return NULL; + struct ospf_nbr_nbma *nbr_nbma; + struct ospf_interface *oi; + struct in_addr addr; + struct ospf *ospf; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + /* Check OSPF instance. */ + ospf = ospf_lookup(); + if (ospf == NULL) + return NULL; + + memset(&addr, 0, sizeof(struct in_addr)); + + nbr_nbma = ospfHostLookup(v, name, length, &addr, exact); + if (nbr_nbma == NULL) + return NULL; + + oi = nbr_nbma->oi; + + /* Return the current value of the variable */ + switch (v->magic) { + case OSPFHOSTIPADDRESS: /* 1 */ + return SNMP_IPADDRESS(nbr_nbma->addr); + break; + case OSPFHOSTTOS: /* 2 */ + return SNMP_INTEGER(0); + break; + case OSPFHOSTMETRIC: /* 3 */ + if (oi) + return SNMP_INTEGER(oi->output_cost); + else + return SNMP_INTEGER(1); + break; + case OSPFHOSTSTATUS: /* 4 */ + return SNMP_INTEGER(SNMP_VALID); + break; + case OSPFHOSTAREAID: /* 5 */ + if (oi && oi->area) + return SNMP_IPADDRESS(oi->area->area_id); + else + return SNMP_IPADDRESS(ospf_empty_addr); + break; + default: + return NULL; + break; + } + return NULL; } static struct list *ospf_snmp_iflist; -struct ospf_snmp_if -{ - struct in_addr addr; - ifindex_t ifindex; - struct interface *ifp; +struct ospf_snmp_if { + struct in_addr addr; + ifindex_t ifindex; + struct interface *ifp; }; -static struct ospf_snmp_if * -ospf_snmp_if_new (void) +static struct ospf_snmp_if *ospf_snmp_if_new(void) { - return XCALLOC (MTYPE_TMP, sizeof (struct ospf_snmp_if)); + return XCALLOC(MTYPE_TMP, sizeof(struct ospf_snmp_if)); } -static void -ospf_snmp_if_free (struct ospf_snmp_if *osif) +static void ospf_snmp_if_free(struct ospf_snmp_if *osif) { - XFREE (MTYPE_TMP, osif); + XFREE(MTYPE_TMP, osif); } -static int -ospf_snmp_if_delete (struct interface *ifp) +static int ospf_snmp_if_delete(struct interface *ifp) { - struct listnode *node, *nnode; - struct ospf_snmp_if *osif; - - for (ALL_LIST_ELEMENTS (ospf_snmp_iflist, node, nnode, osif)) - { - if (osif->ifp == ifp) - { - list_delete_node (ospf_snmp_iflist, node); - ospf_snmp_if_free (osif); - break; + struct listnode *node, *nnode; + struct ospf_snmp_if *osif; + + for (ALL_LIST_ELEMENTS(ospf_snmp_iflist, node, nnode, osif)) { + if (osif->ifp == ifp) { + list_delete_node(ospf_snmp_iflist, node); + ospf_snmp_if_free(osif); + break; + } } - } - return 0; + return 0; } -static int -ospf_snmp_if_update (struct interface *ifp) +static int ospf_snmp_if_update(struct interface *ifp) { - struct listnode *node; - struct listnode *pn; - struct connected *ifc; - struct prefix *p; - struct ospf_snmp_if *osif; - struct in_addr *addr; - ifindex_t ifindex; - - ospf_snmp_if_delete (ifp); - - p = NULL; - addr = NULL; - ifindex = 0; - - /* Lookup first IPv4 address entry. */ - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc)) - { - p = CONNECTED_ID(ifc); - - if (p->family == AF_INET) - { - addr = &p->u.prefix4; - break; + struct listnode *node; + struct listnode *pn; + struct connected *ifc; + struct prefix *p; + struct ospf_snmp_if *osif; + struct in_addr *addr; + ifindex_t ifindex; + + ospf_snmp_if_delete(ifp); + + p = NULL; + addr = NULL; + ifindex = 0; + + /* Lookup first IPv4 address entry. */ + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { + p = CONNECTED_ID(ifc); + + if (p->family == AF_INET) { + addr = &p->u.prefix4; + break; + } } - } - if (! addr) - ifindex = ifp->ifindex; - - /* Add interface to the list. */ - pn = NULL; - for (ALL_LIST_ELEMENTS_RO (ospf_snmp_iflist, node, osif)) - { - if (addr) - { - /* Usual interfaces --> Sort them based on interface IPv4 addresses */ - if (ntohl (osif->addr.s_addr) > ntohl (addr->s_addr)) - break; + if (!addr) + ifindex = ifp->ifindex; + + /* Add interface to the list. */ + pn = NULL; + for (ALL_LIST_ELEMENTS_RO(ospf_snmp_iflist, node, osif)) { + if (addr) { + /* Usual interfaces --> Sort them based on interface + * IPv4 addresses */ + if (ntohl(osif->addr.s_addr) > ntohl(addr->s_addr)) + break; + } else { + /* Unnumbered interfaces --> Sort them based on + * interface indexes */ + if (osif->addr.s_addr != 0 || osif->ifindex > ifindex) + break; + } + pn = node; } - else + + osif = ospf_snmp_if_new(); + if (addr) /* Usual interface */ { - /* Unnumbered interfaces --> Sort them based on interface indexes */ - if (osif->addr.s_addr != 0 || osif->ifindex > ifindex) - break; - } - pn = node; - } - - osif = ospf_snmp_if_new (); - if (addr) /* Usual interface */ - { - osif->addr = *addr; - - /* This field is used for storing ospfAddressLessIf OID value, - * conform to RFC1850 OSPF-MIB specification, it must be 0 for - * usual interface */ - osif->ifindex = 0; - } - else /* Unnumbered interface */ - osif->ifindex = ifindex; - osif->ifp = ifp; - - listnode_add_after (ospf_snmp_iflist, pn, osif); - return 0; + osif->addr = *addr; + + /* This field is used for storing ospfAddressLessIf OID value, + * conform to RFC1850 OSPF-MIB specification, it must be 0 for + * usual interface */ + osif->ifindex = 0; + } else /* Unnumbered interface */ + osif->ifindex = ifindex; + osif->ifp = ifp; + + listnode_add_after(ospf_snmp_iflist, pn, osif); + return 0; } -static int -ospf_snmp_is_if_have_addr (struct interface *ifp) +static int ospf_snmp_is_if_have_addr(struct interface *ifp) { - struct listnode *nn; - struct connected *ifc; - - /* Is this interface having any connected IPv4 address ? */ - for (ALL_LIST_ELEMENTS_RO (ifp->connected, nn, ifc)) - { - if (CONNECTED_PREFIX(ifc)->family == AF_INET) - return 1; - } - - return 0; + struct listnode *nn; + struct connected *ifc; + + /* Is this interface having any connected IPv4 address ? */ + for (ALL_LIST_ELEMENTS_RO(ifp->connected, nn, ifc)) { + if (CONNECTED_PREFIX(ifc)->family == AF_INET) + return 1; + } + + return 0; } -static struct ospf_interface * -ospf_snmp_if_lookup (struct in_addr *ifaddr, ifindex_t *ifindex) +static struct ospf_interface *ospf_snmp_if_lookup(struct in_addr *ifaddr, + ifindex_t *ifindex) { - struct listnode *node; - struct ospf_snmp_if *osif; - struct ospf_interface *oi = NULL; - struct ospf *ospf = ospf_lookup (); - - for (ALL_LIST_ELEMENTS_RO (ospf_snmp_iflist, node, osif)) - { - if (ifaddr->s_addr) - { - if (IPV4_ADDR_SAME (&osif->addr, ifaddr)) - oi = ospf_if_lookup_by_local_addr (ospf, osif->ifp, *ifaddr); - } - else - { - if (osif->ifindex == *ifindex) - oi = ospf_if_lookup_by_local_addr (ospf, osif->ifp, *ifaddr); - } - } - return oi; + struct listnode *node; + struct ospf_snmp_if *osif; + struct ospf_interface *oi = NULL; + struct ospf *ospf = ospf_lookup(); + + for (ALL_LIST_ELEMENTS_RO(ospf_snmp_iflist, node, osif)) { + if (ifaddr->s_addr) { + if (IPV4_ADDR_SAME(&osif->addr, ifaddr)) + oi = ospf_if_lookup_by_local_addr( + ospf, osif->ifp, *ifaddr); + } else { + if (osif->ifindex == *ifindex) + oi = ospf_if_lookup_by_local_addr( + ospf, osif->ifp, *ifaddr); + } + } + return oi; } -static struct ospf_interface * -ospf_snmp_if_lookup_next (struct in_addr *ifaddr, ifindex_t *ifindex, - int ifaddr_next, ifindex_t ifindex_next) +static struct ospf_interface *ospf_snmp_if_lookup_next(struct in_addr *ifaddr, + ifindex_t *ifindex, + int ifaddr_next, + ifindex_t ifindex_next) { - struct ospf_snmp_if *osif; - struct listnode *nn; - struct ospf *ospf = ospf_lookup (); - struct ospf_interface *oi = NULL; - - if (ospf == NULL) - return NULL; - - /* No instance is specified --> Return the first OSPF interface */ - if (ifaddr_next) - { - for (ALL_LIST_ELEMENTS_RO (ospf_snmp_iflist, nn, osif)) - { - osif = listgetdata (nn); - *ifaddr = osif->addr; - *ifindex = osif->ifindex; - /* Because no instance is specified, we don't care about the kind of - * interface (usual or unnumbered), just returning the first valid - * OSPF interface */ - oi = ospf_if_lookup_by_local_addr (ospf, osif->ifp, *ifaddr); - if (oi) - return (oi); + struct ospf_snmp_if *osif; + struct listnode *nn; + struct ospf *ospf = ospf_lookup(); + struct ospf_interface *oi = NULL; + + if (ospf == NULL) + return NULL; + + /* No instance is specified --> Return the first OSPF interface */ + if (ifaddr_next) { + for (ALL_LIST_ELEMENTS_RO(ospf_snmp_iflist, nn, osif)) { + osif = listgetdata(nn); + *ifaddr = osif->addr; + *ifindex = osif->ifindex; + /* Because no instance is specified, we don't care about + * the kind of + * interface (usual or unnumbered), just returning the + * first valid + * OSPF interface */ + oi = ospf_if_lookup_by_local_addr(ospf, osif->ifp, + *ifaddr); + if (oi) + return (oi); + } + return NULL; } - return NULL; - } - - /* An instance is specified --> Return the next OSPF interface */ - for (ALL_LIST_ELEMENTS_RO (ospf_snmp_iflist, nn, osif)) - { - /* Usual interface */ - if (ifaddr->s_addr) - { - /* The interface must have valid AF_INET connected address */ - /* it must have lager IPv4 address value than the lookup entry */ - if ((ospf_snmp_is_if_have_addr(osif->ifp)) && - (ntohl (osif->addr.s_addr) > ntohl (ifaddr->s_addr))) - { - *ifaddr = osif->addr; - *ifindex = osif->ifindex; - - /* and it must be an OSPF interface */ - oi = ospf_if_lookup_by_local_addr (ospf, osif->ifp, *ifaddr); - if (oi) - return oi; - } + + /* An instance is specified --> Return the next OSPF interface */ + for (ALL_LIST_ELEMENTS_RO(ospf_snmp_iflist, nn, osif)) { + /* Usual interface */ + if (ifaddr->s_addr) { + /* The interface must have valid AF_INET connected + * address */ + /* it must have lager IPv4 address value than the lookup + * entry */ + if ((ospf_snmp_is_if_have_addr(osif->ifp)) + && (ntohl(osif->addr.s_addr) + > ntohl(ifaddr->s_addr))) { + *ifaddr = osif->addr; + *ifindex = osif->ifindex; + + /* and it must be an OSPF interface */ + oi = ospf_if_lookup_by_local_addr( + ospf, osif->ifp, *ifaddr); + if (oi) + return oi; + } + } + /* Unnumbered interface */ + else + /* The interface must NOT have valid AF_INET connected + address */ + /* it must have lager interface index than the lookup + entry */ + if ((!ospf_snmp_is_if_have_addr(osif->ifp)) + && (osif->ifindex > *ifindex)) { + *ifaddr = osif->addr; + *ifindex = osif->ifindex; + + /* and it must be an OSPF interface */ + oi = ospf_if_lookup_by_local_addr(ospf, osif->ifp, + *ifaddr); + if (oi) + return oi; + } } - /* Unnumbered interface */ - else - /* The interface must NOT have valid AF_INET connected address */ - /* it must have lager interface index than the lookup entry */ - if ((!ospf_snmp_is_if_have_addr(osif->ifp)) && - (osif->ifindex > *ifindex)) - { - *ifaddr = osif->addr; - *ifindex = osif->ifindex; - - /* and it must be an OSPF interface */ - oi = ospf_if_lookup_by_local_addr (ospf, osif->ifp, *ifaddr); - if (oi) - return oi; - } - } - return NULL; + return NULL; } -static int -ospf_snmp_iftype (struct interface *ifp) +static int ospf_snmp_iftype(struct interface *ifp) { #define ospf_snmp_iftype_broadcast 1 #define ospf_snmp_iftype_nbma 2 #define ospf_snmp_iftype_pointToPoint 3 #define ospf_snmp_iftype_pointToMultipoint 5 - if (if_is_broadcast (ifp)) - return ospf_snmp_iftype_broadcast; - if (if_is_pointopoint (ifp)) - return ospf_snmp_iftype_pointToPoint; - return ospf_snmp_iftype_broadcast; + if (if_is_broadcast(ifp)) + return ospf_snmp_iftype_broadcast; + if (if_is_pointopoint(ifp)) + return ospf_snmp_iftype_pointToPoint; + return ospf_snmp_iftype_broadcast; } -static struct ospf_interface * -ospfIfLookup (struct variable *v, oid *name, size_t *length, - struct in_addr *ifaddr, ifindex_t *ifindex, int exact) +static struct ospf_interface *ospfIfLookup(struct variable *v, oid *name, + size_t *length, + struct in_addr *ifaddr, + ifindex_t *ifindex, int exact) { - unsigned int len; - int ifaddr_next = 0; - ifindex_t ifindex_next = 0; - struct ospf_interface *oi; - oid *offset; - - if (exact) - { - if (*length != v->namelen + IN_ADDR_SIZE + 1) - return NULL; - - oid2in_addr (name + v->namelen, IN_ADDR_SIZE, ifaddr); - *ifindex = name[v->namelen + IN_ADDR_SIZE]; - - return ospf_snmp_if_lookup (ifaddr, ifindex); - } - else - { - len = *length - v->namelen; - if (len >= IN_ADDR_SIZE) - len = IN_ADDR_SIZE; - if (len <= 0) - ifaddr_next = 1; - - oid2in_addr (name + v->namelen, len, ifaddr); - - len = *length - v->namelen - IN_ADDR_SIZE; - if (len >= 1) - len = 1; - else - ifindex_next = 1; - - if (len == 1) - *ifindex = name[v->namelen + IN_ADDR_SIZE]; - - oi = ospf_snmp_if_lookup_next (ifaddr, ifindex, ifaddr_next, - ifindex_next); - if (oi) - { - *length = v->namelen + IN_ADDR_SIZE + 1; - offset = name + v->namelen; - oid_copy_addr (offset, ifaddr, IN_ADDR_SIZE); - offset += IN_ADDR_SIZE; - *offset = *ifindex; - return oi; + unsigned int len; + int ifaddr_next = 0; + ifindex_t ifindex_next = 0; + struct ospf_interface *oi; + oid *offset; + + if (exact) { + if (*length != v->namelen + IN_ADDR_SIZE + 1) + return NULL; + + oid2in_addr(name + v->namelen, IN_ADDR_SIZE, ifaddr); + *ifindex = name[v->namelen + IN_ADDR_SIZE]; + + return ospf_snmp_if_lookup(ifaddr, ifindex); + } else { + len = *length - v->namelen; + if (len >= IN_ADDR_SIZE) + len = IN_ADDR_SIZE; + if (len <= 0) + ifaddr_next = 1; + + oid2in_addr(name + v->namelen, len, ifaddr); + + len = *length - v->namelen - IN_ADDR_SIZE; + if (len >= 1) + len = 1; + else + ifindex_next = 1; + + if (len == 1) + *ifindex = name[v->namelen + IN_ADDR_SIZE]; + + oi = ospf_snmp_if_lookup_next(ifaddr, ifindex, ifaddr_next, + ifindex_next); + if (oi) { + *length = v->namelen + IN_ADDR_SIZE + 1; + offset = name + v->namelen; + oid_copy_addr(offset, ifaddr, IN_ADDR_SIZE); + offset += IN_ADDR_SIZE; + *offset = *ifindex; + return oi; + } } - } - return NULL; + return NULL; } -static u_char * -ospfIfEntry (struct variable *v, oid *name, size_t *length, int exact, - size_t *var_len, WriteMethod **write_method) +static u_char *ospfIfEntry(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - ifindex_t ifindex; - struct in_addr ifaddr; - struct ospf_interface *oi; - struct ospf *ospf; - - if (smux_header_table(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - ifindex = 0; - memset (&ifaddr, 0, sizeof (struct in_addr)); - - /* Check OSPF instance. */ - ospf = ospf_lookup (); - if (ospf == NULL) - return NULL; - - oi = ospfIfLookup (v, name, length, &ifaddr, &ifindex, exact); - if (oi == NULL) - return NULL; - - /* Return the current value of the variable */ - switch (v->magic) - { - case OSPFIFIPADDRESS: /* 1 */ - return SNMP_IPADDRESS (ifaddr); - break; - case OSPFADDRESSLESSIF: /* 2 */ - return SNMP_INTEGER (ifindex); - break; - case OSPFIFAREAID: /* 3 */ - if (oi->area) - return SNMP_IPADDRESS (oi->area->area_id); - else - return SNMP_IPADDRESS (ospf_empty_addr); - break; - case OSPFIFTYPE: /* 4 */ - return SNMP_INTEGER (ospf_snmp_iftype (oi->ifp)); - break; - case OSPFIFADMINSTAT: /* 5 */ - if (oi) - return SNMP_INTEGER (OSPF_STATUS_ENABLED); - else - return SNMP_INTEGER (OSPF_STATUS_DISABLED); - break; - case OSPFIFRTRPRIORITY: /* 6 */ - return SNMP_INTEGER (PRIORITY (oi)); - break; - case OSPFIFTRANSITDELAY: /* 7 */ - return SNMP_INTEGER (OSPF_IF_PARAM (oi, transmit_delay)); - break; - case OSPFIFRETRANSINTERVAL: /* 8 */ - return SNMP_INTEGER (OSPF_IF_PARAM (oi, retransmit_interval)); - break; - case OSPFIFHELLOINTERVAL: /* 9 */ - return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_hello)); - break; - case OSPFIFRTRDEADINTERVAL: /* 10 */ - return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_wait)); - break; - case OSPFIFPOLLINTERVAL: /* 11 */ - return SNMP_INTEGER (OSPF_POLL_INTERVAL_DEFAULT); - break; - case OSPFIFSTATE: /* 12 */ - return SNMP_INTEGER (ISM_SNMP(oi->state)); - break; - case OSPFIFDESIGNATEDROUTER: /* 13 */ - return SNMP_IPADDRESS (DR (oi)); - break; - case OSPFIFBACKUPDESIGNATEDROUTER: /* 14 */ - return SNMP_IPADDRESS (BDR (oi)); - break; - case OSPFIFEVENTS: /* 15 */ - return SNMP_INTEGER (oi->state_change); - break; - case OSPFIFAUTHKEY: /* 16 */ - *var_len = 0; - return (u_char *) OSPF_IF_PARAM (oi, auth_simple); - break; - case OSPFIFSTATUS: /* 17 */ - return SNMP_INTEGER (SNMP_VALID); - break; - case OSPFIFMULTICASTFORWARDING: /* 18 */ + ifindex_t ifindex; + struct in_addr ifaddr; + struct ospf_interface *oi; + struct ospf *ospf; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + ifindex = 0; + memset(&ifaddr, 0, sizeof(struct in_addr)); + + /* Check OSPF instance. */ + ospf = ospf_lookup(); + if (ospf == NULL) + return NULL; + + oi = ospfIfLookup(v, name, length, &ifaddr, &ifindex, exact); + if (oi == NULL) + return NULL; + + /* Return the current value of the variable */ + switch (v->magic) { + case OSPFIFIPADDRESS: /* 1 */ + return SNMP_IPADDRESS(ifaddr); + break; + case OSPFADDRESSLESSIF: /* 2 */ + return SNMP_INTEGER(ifindex); + break; + case OSPFIFAREAID: /* 3 */ + if (oi->area) + return SNMP_IPADDRESS(oi->area->area_id); + else + return SNMP_IPADDRESS(ospf_empty_addr); + break; + case OSPFIFTYPE: /* 4 */ + return SNMP_INTEGER(ospf_snmp_iftype(oi->ifp)); + break; + case OSPFIFADMINSTAT: /* 5 */ + if (oi) + return SNMP_INTEGER(OSPF_STATUS_ENABLED); + else + return SNMP_INTEGER(OSPF_STATUS_DISABLED); + break; + case OSPFIFRTRPRIORITY: /* 6 */ + return SNMP_INTEGER(PRIORITY(oi)); + break; + case OSPFIFTRANSITDELAY: /* 7 */ + return SNMP_INTEGER(OSPF_IF_PARAM(oi, transmit_delay)); + break; + case OSPFIFRETRANSINTERVAL: /* 8 */ + return SNMP_INTEGER(OSPF_IF_PARAM(oi, retransmit_interval)); + break; + case OSPFIFHELLOINTERVAL: /* 9 */ + return SNMP_INTEGER(OSPF_IF_PARAM(oi, v_hello)); + break; + case OSPFIFRTRDEADINTERVAL: /* 10 */ + return SNMP_INTEGER(OSPF_IF_PARAM(oi, v_wait)); + break; + case OSPFIFPOLLINTERVAL: /* 11 */ + return SNMP_INTEGER(OSPF_POLL_INTERVAL_DEFAULT); + break; + case OSPFIFSTATE: /* 12 */ + return SNMP_INTEGER(ISM_SNMP(oi->state)); + break; + case OSPFIFDESIGNATEDROUTER: /* 13 */ + return SNMP_IPADDRESS(DR(oi)); + break; + case OSPFIFBACKUPDESIGNATEDROUTER: /* 14 */ + return SNMP_IPADDRESS(BDR(oi)); + break; + case OSPFIFEVENTS: /* 15 */ + return SNMP_INTEGER(oi->state_change); + break; + case OSPFIFAUTHKEY: /* 16 */ + *var_len = 0; + return (u_char *)OSPF_IF_PARAM(oi, auth_simple); + break; + case OSPFIFSTATUS: /* 17 */ + return SNMP_INTEGER(SNMP_VALID); + break; + case OSPFIFMULTICASTFORWARDING: /* 18 */ + /* $FRR indent$ */ + /* clang-format off */ #define ospf_snmp_multiforward_blocked 1 #define ospf_snmp_multiforward_multicast 2 #define ospf_snmp_multiforward_unicast 3 - return SNMP_INTEGER (ospf_snmp_multiforward_blocked); - break; - case OSPFIFDEMAND: /* 19 */ - return SNMP_INTEGER (SNMP_FALSE); - break; - case OSPFIFAUTHTYPE: /* 20 */ - if (oi->area) - return SNMP_INTEGER (oi->area->auth_type); - else - return SNMP_INTEGER (0); - break; - default: - return NULL; - break; - } - return NULL; + return SNMP_INTEGER(ospf_snmp_multiforward_blocked); + break; + case OSPFIFDEMAND: /* 19 */ + return SNMP_INTEGER(SNMP_FALSE); + break; + case OSPFIFAUTHTYPE: /* 20 */ + if (oi->area) + return SNMP_INTEGER(oi->area->auth_type); + else + return SNMP_INTEGER(0); + break; + default: + return NULL; + break; + } + return NULL; } #define OSPF_SNMP_METRIC_VALUE 1 -static struct ospf_interface * -ospfIfMetricLookup (struct variable *v, oid *name, size_t *length, - struct in_addr *ifaddr, ifindex_t *ifindex, int exact) +static struct ospf_interface *ospfIfMetricLookup(struct variable *v, oid *name, + size_t *length, + struct in_addr *ifaddr, + ifindex_t *ifindex, int exact) { - unsigned int len; - int ifaddr_next = 0; - ifindex_t ifindex_next = 0; - struct ospf_interface *oi; - oid *offset; - int metric; - - if (exact) - { - if (*length != v->namelen + IN_ADDR_SIZE + 1 + 1) - return NULL; - - oid2in_addr (name + v->namelen, IN_ADDR_SIZE, ifaddr); - *ifindex = name[v->namelen + IN_ADDR_SIZE]; - metric = name[v->namelen + IN_ADDR_SIZE + 1]; - - if (metric != OSPF_SNMP_METRIC_VALUE) - return NULL; - - return ospf_snmp_if_lookup (ifaddr, ifindex); - } - else - { - len = *length - v->namelen; - if (len >= IN_ADDR_SIZE) - len = IN_ADDR_SIZE; - else - ifaddr_next = 1; - - oid2in_addr (name + v->namelen, len, ifaddr); - - len = *length - v->namelen - IN_ADDR_SIZE; - if (len >= 1) - len = 1; - else - ifindex_next = 1; - - if (len == 1) - *ifindex = name[v->namelen + IN_ADDR_SIZE]; - - oi = ospf_snmp_if_lookup_next (ifaddr, ifindex, ifaddr_next, - ifindex_next); - if (oi) - { - *length = v->namelen + IN_ADDR_SIZE + 1 + 1; - offset = name + v->namelen; - oid_copy_addr (offset, ifaddr, IN_ADDR_SIZE); - offset += IN_ADDR_SIZE; - *offset = *ifindex; - offset++; - *offset = OSPF_SNMP_METRIC_VALUE; - return oi; + unsigned int len; + int ifaddr_next = 0; + ifindex_t ifindex_next = 0; + struct ospf_interface *oi; + oid *offset; + int metric; + + if (exact) { + if (*length != v->namelen + IN_ADDR_SIZE + 1 + 1) + return NULL; + + oid2in_addr(name + v->namelen, IN_ADDR_SIZE, ifaddr); + *ifindex = name[v->namelen + IN_ADDR_SIZE]; + metric = name[v->namelen + IN_ADDR_SIZE + 1]; + + if (metric != OSPF_SNMP_METRIC_VALUE) + return NULL; + + return ospf_snmp_if_lookup(ifaddr, ifindex); + } else { + len = *length - v->namelen; + if (len >= IN_ADDR_SIZE) + len = IN_ADDR_SIZE; + else + ifaddr_next = 1; + + oid2in_addr(name + v->namelen, len, ifaddr); + + len = *length - v->namelen - IN_ADDR_SIZE; + if (len >= 1) + len = 1; + else + ifindex_next = 1; + + if (len == 1) + *ifindex = name[v->namelen + IN_ADDR_SIZE]; + + oi = ospf_snmp_if_lookup_next(ifaddr, ifindex, ifaddr_next, + ifindex_next); + if (oi) { + *length = v->namelen + IN_ADDR_SIZE + 1 + 1; + offset = name + v->namelen; + oid_copy_addr(offset, ifaddr, IN_ADDR_SIZE); + offset += IN_ADDR_SIZE; + *offset = *ifindex; + offset++; + *offset = OSPF_SNMP_METRIC_VALUE; + return oi; + } } - } - return NULL; + return NULL; } -static u_char * -ospfIfMetricEntry (struct variable *v, oid *name, size_t *length, int exact, - size_t *var_len, WriteMethod **write_method) +static u_char *ospfIfMetricEntry(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - /* Currently we support metric 1 only. */ - ifindex_t ifindex; - struct in_addr ifaddr; - struct ospf_interface *oi; - struct ospf *ospf; - - if (smux_header_table(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - ifindex = 0; - memset (&ifaddr, 0, sizeof (struct in_addr)); - - /* Check OSPF instance. */ - ospf = ospf_lookup (); - if (ospf == NULL) - return NULL; - - oi = ospfIfMetricLookup (v, name, length, &ifaddr, &ifindex, exact); - if (oi == NULL) - return NULL; - - /* Return the current value of the variable */ - switch (v->magic) - { - case OSPFIFMETRICIPADDRESS: - return SNMP_IPADDRESS (ifaddr); - break; - case OSPFIFMETRICADDRESSLESSIF: - return SNMP_INTEGER (ifindex); - break; - case OSPFIFMETRICTOS: - return SNMP_INTEGER (0); - break; - case OSPFIFMETRICVALUE: - return SNMP_INTEGER (OSPF_SNMP_METRIC_VALUE); - break; - case OSPFIFMETRICSTATUS: - return SNMP_INTEGER (1); - break; - default: - return NULL; - break; - } - return NULL; + /* Currently we support metric 1 only. */ + ifindex_t ifindex; + struct in_addr ifaddr; + struct ospf_interface *oi; + struct ospf *ospf; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + ifindex = 0; + memset(&ifaddr, 0, sizeof(struct in_addr)); + + /* Check OSPF instance. */ + ospf = ospf_lookup(); + if (ospf == NULL) + return NULL; + + oi = ospfIfMetricLookup(v, name, length, &ifaddr, &ifindex, exact); + if (oi == NULL) + return NULL; + + /* Return the current value of the variable */ + switch (v->magic) { + case OSPFIFMETRICIPADDRESS: + return SNMP_IPADDRESS(ifaddr); + break; + case OSPFIFMETRICADDRESSLESSIF: + return SNMP_INTEGER(ifindex); + break; + case OSPFIFMETRICTOS: + return SNMP_INTEGER(0); + break; + case OSPFIFMETRICVALUE: + return SNMP_INTEGER(OSPF_SNMP_METRIC_VALUE); + break; + case OSPFIFMETRICSTATUS: + return SNMP_INTEGER(1); + break; + default: + return NULL; + break; + } + return NULL; } static struct route_table *ospf_snmp_vl_table; -static int -ospf_snmp_vl_add (struct ospf_vl_data *vl_data) +static int ospf_snmp_vl_add(struct ospf_vl_data *vl_data) { - struct prefix_ls lp; - struct route_node *rn; + struct prefix_ls lp; + struct route_node *rn; - memset (&lp, 0, sizeof (struct prefix_ls)); - lp.family = 0; - lp.prefixlen = 64; - lp.id = vl_data->vl_area_id; - lp.adv_router = vl_data->vl_peer; + memset(&lp, 0, sizeof(struct prefix_ls)); + lp.family = 0; + lp.prefixlen = 64; + lp.id = vl_data->vl_area_id; + lp.adv_router = vl_data->vl_peer; - rn = route_node_get (ospf_snmp_vl_table, (struct prefix *) &lp); - if (rn->info) - route_unlock_node (rn); + rn = route_node_get(ospf_snmp_vl_table, (struct prefix *)&lp); + if (rn->info) + route_unlock_node(rn); - rn->info = vl_data; - return 0; + rn->info = vl_data; + return 0; } -static int -ospf_snmp_vl_delete (struct ospf_vl_data *vl_data) +static int ospf_snmp_vl_delete(struct ospf_vl_data *vl_data) { - struct prefix_ls lp; - struct route_node *rn; - - memset (&lp, 0, sizeof (struct prefix_ls)); - lp.family = 0; - lp.prefixlen = 64; - lp.id = vl_data->vl_area_id; - lp.adv_router = vl_data->vl_peer; - - rn = route_node_lookup (ospf_snmp_vl_table, (struct prefix *) &lp); - if (! rn) - return 0; - rn->info = NULL; - route_unlock_node (rn); - route_unlock_node (rn); - return 0; + struct prefix_ls lp; + struct route_node *rn; + + memset(&lp, 0, sizeof(struct prefix_ls)); + lp.family = 0; + lp.prefixlen = 64; + lp.id = vl_data->vl_area_id; + lp.adv_router = vl_data->vl_peer; + + rn = route_node_lookup(ospf_snmp_vl_table, (struct prefix *)&lp); + if (!rn) + return 0; + rn->info = NULL; + route_unlock_node(rn); + route_unlock_node(rn); + return 0; } -static struct ospf_vl_data * -ospf_snmp_vl_lookup (struct in_addr *area_id, struct in_addr *neighbor) +static struct ospf_vl_data *ospf_snmp_vl_lookup(struct in_addr *area_id, + struct in_addr *neighbor) { - struct prefix_ls lp; - struct route_node *rn; - struct ospf_vl_data *vl_data; - - memset (&lp, 0, sizeof (struct prefix_ls)); - lp.family = 0; - lp.prefixlen = 64; - lp.id = *area_id; - lp.adv_router = *neighbor; - - rn = route_node_lookup (ospf_snmp_vl_table, (struct prefix *) &lp); - if (rn) - { - vl_data = rn->info; - route_unlock_node (rn); - return vl_data; - } - return NULL; + struct prefix_ls lp; + struct route_node *rn; + struct ospf_vl_data *vl_data; + + memset(&lp, 0, sizeof(struct prefix_ls)); + lp.family = 0; + lp.prefixlen = 64; + lp.id = *area_id; + lp.adv_router = *neighbor; + + rn = route_node_lookup(ospf_snmp_vl_table, (struct prefix *)&lp); + if (rn) { + vl_data = rn->info; + route_unlock_node(rn); + return vl_data; + } + return NULL; } -static struct ospf_vl_data * -ospf_snmp_vl_lookup_next (struct in_addr *area_id, struct in_addr *neighbor, - int first) +static struct ospf_vl_data *ospf_snmp_vl_lookup_next(struct in_addr *area_id, + struct in_addr *neighbor, + int first) { - struct prefix_ls lp; - struct route_node *rn; - struct ospf_vl_data *vl_data; - - memset (&lp, 0, sizeof (struct prefix_ls)); - lp.family = 0; - lp.prefixlen = 64; - lp.id = *area_id; - lp.adv_router = *neighbor; - - if (first) - rn = route_top (ospf_snmp_vl_table); - else - { - rn = route_node_get (ospf_snmp_vl_table, (struct prefix *) &lp); - rn = route_next (rn); - } - - for (; rn; rn = route_next (rn)) - if (rn->info) - break; - - if (rn && rn->info) - { - vl_data = rn->info; - *area_id = vl_data->vl_area_id; - *neighbor = vl_data->vl_peer; - route_unlock_node (rn); - return vl_data; - } - return NULL; -} + struct prefix_ls lp; + struct route_node *rn; + struct ospf_vl_data *vl_data; + + memset(&lp, 0, sizeof(struct prefix_ls)); + lp.family = 0; + lp.prefixlen = 64; + lp.id = *area_id; + lp.adv_router = *neighbor; + + if (first) + rn = route_top(ospf_snmp_vl_table); + else { + rn = route_node_get(ospf_snmp_vl_table, (struct prefix *)&lp); + rn = route_next(rn); + } -static struct ospf_vl_data * -ospfVirtIfLookup (struct variable *v, oid *name, size_t *length, - struct in_addr *area_id, struct in_addr *neighbor, int exact) -{ - int first; - unsigned int len; - struct ospf_vl_data *vl_data; + for (; rn; rn = route_next(rn)) + if (rn->info) + break; - if (exact) - { - if (*length != v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE) + if (rn && rn->info) { + vl_data = rn->info; + *area_id = vl_data->vl_area_id; + *neighbor = vl_data->vl_peer; + route_unlock_node(rn); + return vl_data; + } return NULL; +} - oid2in_addr (name + v->namelen, IN_ADDR_SIZE, area_id); - oid2in_addr (name + v->namelen + IN_ADDR_SIZE, IN_ADDR_SIZE, neighbor); - - return ospf_snmp_vl_lookup (area_id, neighbor); - } - else - { - first = 0; - - len = *length - v->namelen; - if (len <= 0) - first = 1; - if (len > IN_ADDR_SIZE) - len = IN_ADDR_SIZE; - oid2in_addr (name + v->namelen, len, area_id); - - len = *length - v->namelen - IN_ADDR_SIZE; - if (len > IN_ADDR_SIZE) - len = IN_ADDR_SIZE; - oid2in_addr (name + v->namelen + IN_ADDR_SIZE, len, neighbor); - - vl_data = ospf_snmp_vl_lookup_next (area_id, neighbor, first); - - if (vl_data) - { - *length = v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE; - oid_copy_addr (name + v->namelen, area_id, IN_ADDR_SIZE); - oid_copy_addr (name + v->namelen + IN_ADDR_SIZE, neighbor, - IN_ADDR_SIZE); - return vl_data; +static struct ospf_vl_data * +ospfVirtIfLookup(struct variable *v, oid *name, size_t *length, + struct in_addr *area_id, struct in_addr *neighbor, int exact) +{ + int first; + unsigned int len; + struct ospf_vl_data *vl_data; + + if (exact) { + if (*length != v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE) + return NULL; + + oid2in_addr(name + v->namelen, IN_ADDR_SIZE, area_id); + oid2in_addr(name + v->namelen + IN_ADDR_SIZE, IN_ADDR_SIZE, + neighbor); + + return ospf_snmp_vl_lookup(area_id, neighbor); + } else { + first = 0; + + len = *length - v->namelen; + if (len <= 0) + first = 1; + if (len > IN_ADDR_SIZE) + len = IN_ADDR_SIZE; + oid2in_addr(name + v->namelen, len, area_id); + + len = *length - v->namelen - IN_ADDR_SIZE; + if (len > IN_ADDR_SIZE) + len = IN_ADDR_SIZE; + oid2in_addr(name + v->namelen + IN_ADDR_SIZE, len, neighbor); + + vl_data = ospf_snmp_vl_lookup_next(area_id, neighbor, first); + + if (vl_data) { + *length = v->namelen + IN_ADDR_SIZE + IN_ADDR_SIZE; + oid_copy_addr(name + v->namelen, area_id, IN_ADDR_SIZE); + oid_copy_addr(name + v->namelen + IN_ADDR_SIZE, + neighbor, IN_ADDR_SIZE); + return vl_data; + } } - } - return NULL; + return NULL; } -static u_char * -ospfVirtIfEntry (struct variable *v, oid *name, size_t *length, int exact, - size_t *var_len, WriteMethod **write_method) +static u_char *ospfVirtIfEntry(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - struct ospf_vl_data *vl_data; - struct ospf_interface *oi; - struct in_addr area_id; - struct in_addr neighbor; - - if (smux_header_table(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - memset (&area_id, 0, sizeof (struct in_addr)); - memset (&neighbor, 0, sizeof (struct in_addr)); - - vl_data = ospfVirtIfLookup (v, name, length, &area_id, &neighbor, exact); - if (! vl_data) - return NULL; - oi = vl_data->vl_oi; - if (! oi) - return NULL; - - /* Return the current value of the variable */ - switch (v->magic) - { - case OSPFVIRTIFAREAID: - return SNMP_IPADDRESS (area_id); - break; - case OSPFVIRTIFNEIGHBOR: - return SNMP_IPADDRESS (neighbor); - break; - case OSPFVIRTIFTRANSITDELAY: - return SNMP_INTEGER (OSPF_IF_PARAM (oi, transmit_delay)); - break; - case OSPFVIRTIFRETRANSINTERVAL: - return SNMP_INTEGER (OSPF_IF_PARAM (oi, retransmit_interval)); - break; - case OSPFVIRTIFHELLOINTERVAL: - return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_hello)); - break; - case OSPFVIRTIFRTRDEADINTERVAL: - return SNMP_INTEGER (OSPF_IF_PARAM (oi, v_wait)); - break; - case OSPFVIRTIFSTATE: - return SNMP_INTEGER (oi->state); - break; - case OSPFVIRTIFEVENTS: - return SNMP_INTEGER (oi->state_change); - break; - case OSPFVIRTIFAUTHKEY: - *var_len = 0; - return (u_char *) OSPF_IF_PARAM (oi, auth_simple); - break; - case OSPFVIRTIFSTATUS: - return SNMP_INTEGER (SNMP_VALID); - break; - case OSPFVIRTIFAUTHTYPE: - if (oi->area) - return SNMP_INTEGER (oi->area->auth_type); - else - return SNMP_INTEGER (0); - break; - default: - return NULL; - break; - } - return NULL; + struct ospf_vl_data *vl_data; + struct ospf_interface *oi; + struct in_addr area_id; + struct in_addr neighbor; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + memset(&area_id, 0, sizeof(struct in_addr)); + memset(&neighbor, 0, sizeof(struct in_addr)); + + vl_data = ospfVirtIfLookup(v, name, length, &area_id, &neighbor, exact); + if (!vl_data) + return NULL; + oi = vl_data->vl_oi; + if (!oi) + return NULL; + + /* Return the current value of the variable */ + switch (v->magic) { + case OSPFVIRTIFAREAID: + return SNMP_IPADDRESS(area_id); + break; + case OSPFVIRTIFNEIGHBOR: + return SNMP_IPADDRESS(neighbor); + break; + case OSPFVIRTIFTRANSITDELAY: + return SNMP_INTEGER(OSPF_IF_PARAM(oi, transmit_delay)); + break; + case OSPFVIRTIFRETRANSINTERVAL: + return SNMP_INTEGER(OSPF_IF_PARAM(oi, retransmit_interval)); + break; + case OSPFVIRTIFHELLOINTERVAL: + return SNMP_INTEGER(OSPF_IF_PARAM(oi, v_hello)); + break; + case OSPFVIRTIFRTRDEADINTERVAL: + return SNMP_INTEGER(OSPF_IF_PARAM(oi, v_wait)); + break; + case OSPFVIRTIFSTATE: + return SNMP_INTEGER(oi->state); + break; + case OSPFVIRTIFEVENTS: + return SNMP_INTEGER(oi->state_change); + break; + case OSPFVIRTIFAUTHKEY: + *var_len = 0; + return (u_char *)OSPF_IF_PARAM(oi, auth_simple); + break; + case OSPFVIRTIFSTATUS: + return SNMP_INTEGER(SNMP_VALID); + break; + case OSPFVIRTIFAUTHTYPE: + if (oi->area) + return SNMP_INTEGER(oi->area->auth_type); + else + return SNMP_INTEGER(0); + break; + default: + return NULL; + break; + } + return NULL; } -static struct ospf_neighbor * -ospf_snmp_nbr_lookup (struct ospf *ospf, struct in_addr *nbr_addr, - ifindex_t *ifindex) +static struct ospf_neighbor *ospf_snmp_nbr_lookup(struct ospf *ospf, + struct in_addr *nbr_addr, + ifindex_t *ifindex) { - struct listnode *node, *nnode; - struct ospf_interface *oi; - struct ospf_neighbor *nbr; - struct route_node *rn; - - for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) - { - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL - && nbr != oi->nbr_self -/* If EXACT match is needed, provide ALL entry found - && nbr->state != NSM_Down - */ - && nbr->src.s_addr != 0) - { - if (IPV4_ADDR_SAME (&nbr->src, nbr_addr)) - { - route_unlock_node (rn); - return nbr; - } - } - } - return NULL; + struct listnode *node, *nnode; + struct ospf_interface *oi; + struct ospf_neighbor *nbr; + struct route_node *rn; + + for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) { + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info) != NULL && nbr != oi->nbr_self + /* If EXACT match is needed, provide ALL entry found + && nbr->state != NSM_Down + */ + && nbr->src.s_addr != 0) { + if (IPV4_ADDR_SAME(&nbr->src, nbr_addr)) { + route_unlock_node(rn); + return nbr; + } + } + } + return NULL; } -static struct ospf_neighbor * -ospf_snmp_nbr_lookup_next (struct in_addr *nbr_addr, ifindex_t *ifindex, - int first) +static struct ospf_neighbor *ospf_snmp_nbr_lookup_next(struct in_addr *nbr_addr, + ifindex_t *ifindex, + int first) { - struct listnode *nn; - struct ospf_interface *oi; - struct ospf_neighbor *nbr; - struct route_node *rn; - struct ospf_neighbor *min = NULL; - struct ospf *ospf = ospf; - - ospf = ospf_lookup (); - - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, nn, oi)) - { - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL - && nbr != oi->nbr_self - && nbr->state != NSM_Down - && nbr->src.s_addr != 0) - { - if (first) - { - if (! min) - min = nbr; - else if (ntohl (nbr->src.s_addr) < ntohl (min->src.s_addr)) - min = nbr; - } - else if (ntohl (nbr->src.s_addr) > ntohl (nbr_addr->s_addr)) - { - if (! min) - min = nbr; - else if (ntohl (nbr->src.s_addr) < ntohl (min->src.s_addr)) - min = nbr; - } - } - } - if (min) - { - *nbr_addr = min->src; - *ifindex = 0; - return min; - } - return NULL; + struct listnode *nn; + struct ospf_interface *oi; + struct ospf_neighbor *nbr; + struct route_node *rn; + struct ospf_neighbor *min = NULL; + struct ospf *ospf = ospf; + + ospf = ospf_lookup(); + + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, nn, oi)) { + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info) != NULL && nbr != oi->nbr_self + && nbr->state != NSM_Down && nbr->src.s_addr != 0) { + if (first) { + if (!min) + min = nbr; + else if (ntohl(nbr->src.s_addr) + < ntohl(min->src.s_addr)) + min = nbr; + } else if (ntohl(nbr->src.s_addr) + > ntohl(nbr_addr->s_addr)) { + if (!min) + min = nbr; + else if (ntohl(nbr->src.s_addr) + < ntohl(min->src.s_addr)) + min = nbr; + } + } + } + if (min) { + *nbr_addr = min->src; + *ifindex = 0; + return min; + } + return NULL; } -static struct ospf_neighbor * -ospfNbrLookup (struct variable *v, oid *name, size_t *length, - struct in_addr *nbr_addr, ifindex_t *ifindex, int exact) +static struct ospf_neighbor *ospfNbrLookup(struct variable *v, oid *name, + size_t *length, + struct in_addr *nbr_addr, + ifindex_t *ifindex, int exact) { - unsigned int len; - int first; - struct ospf_neighbor *nbr; - struct ospf *ospf; + unsigned int len; + int first; + struct ospf_neighbor *nbr; + struct ospf *ospf; - ospf = ospf_lookup (); + ospf = ospf_lookup(); - if (! ospf) - return NULL; + if (!ospf) + return NULL; - if (exact) - { - if (*length != v->namelen + IN_ADDR_SIZE + 1) - return NULL; + if (exact) { + if (*length != v->namelen + IN_ADDR_SIZE + 1) + return NULL; - oid2in_addr (name + v->namelen, IN_ADDR_SIZE, nbr_addr); - *ifindex = name[v->namelen + IN_ADDR_SIZE]; + oid2in_addr(name + v->namelen, IN_ADDR_SIZE, nbr_addr); + *ifindex = name[v->namelen + IN_ADDR_SIZE]; - return ospf_snmp_nbr_lookup (ospf, nbr_addr, ifindex); - } - else - { - first = 0; - len = *length - v->namelen; + return ospf_snmp_nbr_lookup(ospf, nbr_addr, ifindex); + } else { + first = 0; + len = *length - v->namelen; - if (len <= 0) - first = 1; + if (len <= 0) + first = 1; - if (len > IN_ADDR_SIZE) - len = IN_ADDR_SIZE; + if (len > IN_ADDR_SIZE) + len = IN_ADDR_SIZE; - oid2in_addr (name + v->namelen, len, nbr_addr); + oid2in_addr(name + v->namelen, len, nbr_addr); - len = *length - v->namelen - IN_ADDR_SIZE; - if (len >= 1) - *ifindex = name[v->namelen + IN_ADDR_SIZE]; - - nbr = ospf_snmp_nbr_lookup_next (nbr_addr, ifindex, first); + len = *length - v->namelen - IN_ADDR_SIZE; + if (len >= 1) + *ifindex = name[v->namelen + IN_ADDR_SIZE]; - if (nbr) - { - *length = v->namelen + IN_ADDR_SIZE + 1; - oid_copy_addr (name + v->namelen, nbr_addr, IN_ADDR_SIZE); - name[v->namelen + IN_ADDR_SIZE] = *ifindex; - return nbr; + nbr = ospf_snmp_nbr_lookup_next(nbr_addr, ifindex, first); + + if (nbr) { + *length = v->namelen + IN_ADDR_SIZE + 1; + oid_copy_addr(name + v->namelen, nbr_addr, + IN_ADDR_SIZE); + name[v->namelen + IN_ADDR_SIZE] = *ifindex; + return nbr; + } } - } - return NULL; + return NULL; } /* map internal quagga neighbor states to official MIB values: ospfNbrState OBJECT-TYPE - SYNTAX INTEGER { - down (1), - attempt (2), - init (3), - twoWay (4), - exchangeStart (5), - exchange (6), - loading (7), - full (8) - } + SYNTAX INTEGER { + down (1), + attempt (2), + init (3), + twoWay (4), + exchangeStart (5), + exchange (6), + loading (7), + full (8) + } */ -static int32_t -ospf_snmp_neighbor_state(u_char nst) +static int32_t ospf_snmp_neighbor_state(u_char nst) { - switch (nst) - { - case NSM_Attempt: - return 2; - case NSM_Init: - return 3; - case NSM_TwoWay: - return 4; - case NSM_ExStart: - return 5; - case NSM_Exchange: - return 6; - case NSM_Loading: - return 7; - case NSM_Full: - return 8; - default: - return 1; /* down */ - } + switch (nst) { + case NSM_Attempt: + return 2; + case NSM_Init: + return 3; + case NSM_TwoWay: + return 4; + case NSM_ExStart: + return 5; + case NSM_Exchange: + return 6; + case NSM_Loading: + return 7; + case NSM_Full: + return 8; + default: + return 1; /* down */ + } } -static u_char * -ospfNbrEntry (struct variable *v, oid *name, size_t *length, int exact, - size_t *var_len, WriteMethod **write_method) +static u_char *ospfNbrEntry(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - struct in_addr nbr_addr; - ifindex_t ifindex; - struct ospf_neighbor *nbr; - struct ospf_interface *oi; - - if (smux_header_table(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - memset (&nbr_addr, 0, sizeof (struct in_addr)); - ifindex = 0; - - nbr = ospfNbrLookup (v, name, length, &nbr_addr, &ifindex, exact); - if (! nbr) - return NULL; - oi = nbr->oi; - if (! oi) - return NULL; - - /* Return the current value of the variable */ - switch (v->magic) - { - case OSPFNBRIPADDR: - return SNMP_IPADDRESS (nbr_addr); - break; - case OSPFNBRADDRESSLESSINDEX: - return SNMP_INTEGER (ifindex); - break; - case OSPFNBRRTRID: - return SNMP_IPADDRESS (nbr->router_id); - break; - case OSPFNBROPTIONS: - return SNMP_INTEGER (oi->nbr_self->options); - break; - case OSPFNBRPRIORITY: - return SNMP_INTEGER (nbr->priority); - break; - case OSPFNBRSTATE: - return SNMP_INTEGER (ospf_snmp_neighbor_state(nbr->state)); - break; - case OSPFNBREVENTS: - return SNMP_INTEGER (nbr->state_change); - break; - case OSPFNBRLSRETRANSQLEN: - return SNMP_INTEGER (ospf_ls_retransmit_count (nbr)); - break; - case OSPFNBMANBRSTATUS: - return SNMP_INTEGER (SNMP_VALID); - break; - case OSPFNBMANBRPERMANENCE: - return SNMP_INTEGER (2); - break; - case OSPFNBRHELLOSUPPRESSED: - return SNMP_INTEGER (SNMP_FALSE); - break; - default: - return NULL; - break; - } - return NULL; + struct in_addr nbr_addr; + ifindex_t ifindex; + struct ospf_neighbor *nbr; + struct ospf_interface *oi; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + memset(&nbr_addr, 0, sizeof(struct in_addr)); + ifindex = 0; + + nbr = ospfNbrLookup(v, name, length, &nbr_addr, &ifindex, exact); + if (!nbr) + return NULL; + oi = nbr->oi; + if (!oi) + return NULL; + + /* Return the current value of the variable */ + switch (v->magic) { + case OSPFNBRIPADDR: + return SNMP_IPADDRESS(nbr_addr); + break; + case OSPFNBRADDRESSLESSINDEX: + return SNMP_INTEGER(ifindex); + break; + case OSPFNBRRTRID: + return SNMP_IPADDRESS(nbr->router_id); + break; + case OSPFNBROPTIONS: + return SNMP_INTEGER(oi->nbr_self->options); + break; + case OSPFNBRPRIORITY: + return SNMP_INTEGER(nbr->priority); + break; + case OSPFNBRSTATE: + return SNMP_INTEGER(ospf_snmp_neighbor_state(nbr->state)); + break; + case OSPFNBREVENTS: + return SNMP_INTEGER(nbr->state_change); + break; + case OSPFNBRLSRETRANSQLEN: + return SNMP_INTEGER(ospf_ls_retransmit_count(nbr)); + break; + case OSPFNBMANBRSTATUS: + return SNMP_INTEGER(SNMP_VALID); + break; + case OSPFNBMANBRPERMANENCE: + return SNMP_INTEGER(2); + break; + case OSPFNBRHELLOSUPPRESSED: + return SNMP_INTEGER(SNMP_FALSE); + break; + default: + return NULL; + break; + } + return NULL; } -static u_char * -ospfVirtNbrEntry (struct variable *v, oid *name, size_t *length, int exact, - size_t *var_len, WriteMethod **write_method) +static u_char *ospfVirtNbrEntry(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - struct ospf_vl_data *vl_data; - struct in_addr area_id; - struct in_addr neighbor; - struct ospf *ospf; - - if (smux_header_table(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - memset (&area_id, 0, sizeof (struct in_addr)); - memset (&neighbor, 0, sizeof (struct in_addr)); - - /* Check OSPF instance. */ - ospf = ospf_lookup (); - if (ospf == NULL) - return NULL; - - vl_data = ospfVirtIfLookup (v, name, length, &area_id, &neighbor, exact); - if (! vl_data) - return NULL; - - /* Return the current value of the variable */ - switch (v->magic) - { - case OSPFVIRTNBRAREA: - return (u_char *) NULL; - break; - case OSPFVIRTNBRRTRID: - return (u_char *) NULL; - break; - case OSPFVIRTNBRIPADDR: - return (u_char *) NULL; - break; - case OSPFVIRTNBROPTIONS: - return (u_char *) NULL; - break; - case OSPFVIRTNBRSTATE: - return (u_char *) NULL; - break; - case OSPFVIRTNBREVENTS: - return (u_char *) NULL; - break; - case OSPFVIRTNBRLSRETRANSQLEN: - return (u_char *) NULL; - break; - case OSPFVIRTNBRHELLOSUPPRESSED: - return (u_char *) NULL; - break; - default: - return NULL; - break; - } - return NULL; + struct ospf_vl_data *vl_data; + struct in_addr area_id; + struct in_addr neighbor; + struct ospf *ospf; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + memset(&area_id, 0, sizeof(struct in_addr)); + memset(&neighbor, 0, sizeof(struct in_addr)); + + /* Check OSPF instance. */ + ospf = ospf_lookup(); + if (ospf == NULL) + return NULL; + + vl_data = ospfVirtIfLookup(v, name, length, &area_id, &neighbor, exact); + if (!vl_data) + return NULL; + + /* Return the current value of the variable */ + switch (v->magic) { + case OSPFVIRTNBRAREA: + return (u_char *)NULL; + break; + case OSPFVIRTNBRRTRID: + return (u_char *)NULL; + break; + case OSPFVIRTNBRIPADDR: + return (u_char *)NULL; + break; + case OSPFVIRTNBROPTIONS: + return (u_char *)NULL; + break; + case OSPFVIRTNBRSTATE: + return (u_char *)NULL; + break; + case OSPFVIRTNBREVENTS: + return (u_char *)NULL; + break; + case OSPFVIRTNBRLSRETRANSQLEN: + return (u_char *)NULL; + break; + case OSPFVIRTNBRHELLOSUPPRESSED: + return (u_char *)NULL; + break; + default: + return NULL; + break; + } + return NULL; } -static struct ospf_lsa * -ospfExtLsdbLookup (struct variable *v, oid *name, size_t *length, u_char *type, - struct in_addr *ls_id, struct in_addr *router_id, int exact) +static struct ospf_lsa *ospfExtLsdbLookup(struct variable *v, oid *name, + size_t *length, u_char *type, + struct in_addr *ls_id, + struct in_addr *router_id, int exact) { - int first; - oid *offset; - int offsetlen; - u_char lsa_type; - unsigned int len; - struct ospf_lsa *lsa; - struct ospf *ospf; - - ospf = ospf_lookup (); - if (exact) - { - if (*length != v->namelen + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE) - return NULL; - - offset = name + v->namelen; - - /* Make it sure given value match to type. */ - lsa_type = *offset; - offset++; - - if (lsa_type != *type) - return NULL; - - /* LS ID. */ - oid2in_addr (offset, IN_ADDR_SIZE, ls_id); - offset += IN_ADDR_SIZE; - - /* Router ID. */ - oid2in_addr (offset, IN_ADDR_SIZE, router_id); - - return ospf_lsdb_lookup_by_id (ospf->lsdb, *type, *ls_id, *router_id); - } - else - { - /* Get variable length. */ - first = 0; - offset = name + v->namelen; - offsetlen = *length - v->namelen; - - /* LSA type value. */ - lsa_type = *offset; - offset++; - offsetlen--; - - if (offsetlen <= 0 || lsa_type < OSPF_AS_EXTERNAL_LSA) - first = 1; - - /* LS ID. */ - len = offsetlen; - if (len > IN_ADDR_SIZE) - len = IN_ADDR_SIZE; - - oid2in_addr (offset, len, ls_id); - - offset += IN_ADDR_SIZE; - offsetlen -= IN_ADDR_SIZE; - - /* Router ID. */ - len = offsetlen; - if (len > IN_ADDR_SIZE) - len = IN_ADDR_SIZE; - - oid2in_addr (offset, len, router_id); - - lsa = ospf_lsdb_lookup_by_id_next (ospf->lsdb, *type, *ls_id, - *router_id, first); - - if (lsa) - { - /* Fill in length. */ - *length = v->namelen + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE; - - /* Fill in value. */ - offset = name + v->namelen; - - *offset = OSPF_AS_EXTERNAL_LSA; - offset++; - oid_copy_addr (offset, &lsa->data->id, IN_ADDR_SIZE); - offset += IN_ADDR_SIZE; - oid_copy_addr (offset, &lsa->data->adv_router, IN_ADDR_SIZE); - - return lsa; + int first; + oid *offset; + int offsetlen; + u_char lsa_type; + unsigned int len; + struct ospf_lsa *lsa; + struct ospf *ospf; + + ospf = ospf_lookup(); + if (exact) { + if (*length != v->namelen + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE) + return NULL; + + offset = name + v->namelen; + + /* Make it sure given value match to type. */ + lsa_type = *offset; + offset++; + + if (lsa_type != *type) + return NULL; + + /* LS ID. */ + oid2in_addr(offset, IN_ADDR_SIZE, ls_id); + offset += IN_ADDR_SIZE; + + /* Router ID. */ + oid2in_addr(offset, IN_ADDR_SIZE, router_id); + + return ospf_lsdb_lookup_by_id(ospf->lsdb, *type, *ls_id, + *router_id); + } else { + /* Get variable length. */ + first = 0; + offset = name + v->namelen; + offsetlen = *length - v->namelen; + + /* LSA type value. */ + lsa_type = *offset; + offset++; + offsetlen--; + + if (offsetlen <= 0 || lsa_type < OSPF_AS_EXTERNAL_LSA) + first = 1; + + /* LS ID. */ + len = offsetlen; + if (len > IN_ADDR_SIZE) + len = IN_ADDR_SIZE; + + oid2in_addr(offset, len, ls_id); + + offset += IN_ADDR_SIZE; + offsetlen -= IN_ADDR_SIZE; + + /* Router ID. */ + len = offsetlen; + if (len > IN_ADDR_SIZE) + len = IN_ADDR_SIZE; + + oid2in_addr(offset, len, router_id); + + lsa = ospf_lsdb_lookup_by_id_next(ospf->lsdb, *type, *ls_id, + *router_id, first); + + if (lsa) { + /* Fill in length. */ + *length = v->namelen + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE; + + /* Fill in value. */ + offset = name + v->namelen; + + *offset = OSPF_AS_EXTERNAL_LSA; + offset++; + oid_copy_addr(offset, &lsa->data->id, IN_ADDR_SIZE); + offset += IN_ADDR_SIZE; + oid_copy_addr(offset, &lsa->data->adv_router, + IN_ADDR_SIZE); + + return lsa; + } } - } - return NULL; + return NULL; } -static u_char * -ospfExtLsdbEntry (struct variable *v, oid *name, size_t *length, int exact, - size_t *var_len, WriteMethod **write_method) +static u_char *ospfExtLsdbEntry(struct variable *v, oid *name, size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - struct ospf_lsa *lsa; - struct lsa_header *lsah; - u_char type; - struct in_addr ls_id; - struct in_addr router_id; - struct ospf *ospf; - - if (smux_header_table(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - type = OSPF_AS_EXTERNAL_LSA; - memset (&ls_id, 0, sizeof (struct in_addr)); - memset (&router_id, 0, sizeof (struct in_addr)); - - /* Check OSPF instance. */ - ospf = ospf_lookup (); - if (ospf == NULL) - return NULL; - - lsa = ospfExtLsdbLookup (v, name, length, &type, &ls_id, &router_id, exact); - if (! lsa) - return NULL; - - lsah = lsa->data; - - /* Return the current value of the variable */ - switch (v->magic) - { - case OSPFEXTLSDBTYPE: - return SNMP_INTEGER (OSPF_AS_EXTERNAL_LSA); - break; - case OSPFEXTLSDBLSID: - return SNMP_IPADDRESS (lsah->id); - break; - case OSPFEXTLSDBROUTERID: - return SNMP_IPADDRESS (lsah->adv_router); - break; - case OSPFEXTLSDBSEQUENCE: - return SNMP_INTEGER (lsah->ls_seqnum); - break; - case OSPFEXTLSDBAGE: - return SNMP_INTEGER (lsah->ls_age); - break; - case OSPFEXTLSDBCHECKSUM: - return SNMP_INTEGER (lsah->checksum); - break; - case OSPFEXTLSDBADVERTISEMENT: - *var_len = ntohs (lsah->length); - return (u_char *) lsah; - break; - default: - return NULL; - break; - } - return NULL; + struct ospf_lsa *lsa; + struct lsa_header *lsah; + u_char type; + struct in_addr ls_id; + struct in_addr router_id; + struct ospf *ospf; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + type = OSPF_AS_EXTERNAL_LSA; + memset(&ls_id, 0, sizeof(struct in_addr)); + memset(&router_id, 0, sizeof(struct in_addr)); + + /* Check OSPF instance. */ + ospf = ospf_lookup(); + if (ospf == NULL) + return NULL; + + lsa = ospfExtLsdbLookup(v, name, length, &type, &ls_id, &router_id, + exact); + if (!lsa) + return NULL; + + lsah = lsa->data; + + /* Return the current value of the variable */ + switch (v->magic) { + case OSPFEXTLSDBTYPE: + return SNMP_INTEGER(OSPF_AS_EXTERNAL_LSA); + break; + case OSPFEXTLSDBLSID: + return SNMP_IPADDRESS(lsah->id); + break; + case OSPFEXTLSDBROUTERID: + return SNMP_IPADDRESS(lsah->adv_router); + break; + case OSPFEXTLSDBSEQUENCE: + return SNMP_INTEGER(lsah->ls_seqnum); + break; + case OSPFEXTLSDBAGE: + return SNMP_INTEGER(lsah->ls_age); + break; + case OSPFEXTLSDBCHECKSUM: + return SNMP_INTEGER(lsah->checksum); + break; + case OSPFEXTLSDBADVERTISEMENT: + *var_len = ntohs(lsah->length); + return (u_char *)lsah; + break; + default: + return NULL; + break; + } + return NULL; } -static u_char * -ospfAreaAggregateEntry (struct variable *v, oid *name, size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *ospfAreaAggregateEntry(struct variable *v, oid *name, + size_t *length, int exact, + size_t *var_len, + WriteMethod **write_method) { - if (smux_header_table(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - /* Return the current value of the variable */ - switch (v->magic) - { - case OSPFAREAAGGREGATEAREAID: - return (u_char *) NULL; - break; - case OSPFAREAAGGREGATELSDBTYPE: - return (u_char *) NULL; - break; - case OSPFAREAAGGREGATENET: - return (u_char *) NULL; - break; - case OSPFAREAAGGREGATEMASK: - return (u_char *) NULL; - break; - case OSPFAREAAGGREGATESTATUS: - return (u_char *) NULL; - break; - case OSPFAREAAGGREGATEEFFECT: - return (u_char *) NULL; - break; - default: - return NULL; - break; - } - return NULL; + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + /* Return the current value of the variable */ + switch (v->magic) { + case OSPFAREAAGGREGATEAREAID: + return (u_char *)NULL; + break; + case OSPFAREAAGGREGATELSDBTYPE: + return (u_char *)NULL; + break; + case OSPFAREAAGGREGATENET: + return (u_char *)NULL; + break; + case OSPFAREAAGGREGATEMASK: + return (u_char *)NULL; + break; + case OSPFAREAAGGREGATESTATUS: + return (u_char *)NULL; + break; + case OSPFAREAAGGREGATEEFFECT: + return (u_char *)NULL; + break; + default: + return NULL; + break; + } + return NULL; } /* OSPF Traps. */ @@ -2626,188 +2560,165 @@ ospfAreaAggregateEntry (struct variable *v, oid *name, size_t *length, #define NBRSTATECHANGE 2 #define VIRTNBRSTATECHANGE 3 -static struct trap_object ospfNbrTrapList[] = -{ - {-2, {1, OSPFROUTERID}}, - {3, {10, 1, OSPFNBRIPADDR}}, - {3, {10, 1, OSPFNBRRTRID}}, - {3, {10, 1, OSPFNBRSTATE}} -}; +static struct trap_object ospfNbrTrapList[] = {{-2, {1, OSPFROUTERID}}, + {3, {10, 1, OSPFNBRIPADDR}}, + {3, {10, 1, OSPFNBRRTRID}}, + {3, {10, 1, OSPFNBRSTATE}}}; -static struct trap_object ospfVirtNbrTrapList[] = -{ - {-2, {1, 1}}, - {3, {11, 1, OSPFVIRTNBRAREA}}, - {3, {11, 1, OSPFVIRTNBRRTRID}}, - {3, {11, 1, OSPFVIRTNBRSTATE}} -}; +static struct trap_object ospfVirtNbrTrapList[] = { + {-2, {1, 1}}, + {3, {11, 1, OSPFVIRTNBRAREA}}, + {3, {11, 1, OSPFVIRTNBRRTRID}}, + {3, {11, 1, OSPFVIRTNBRSTATE}}}; -static struct trap_object ospfIfTrapList[] = -{ - {-2, {1, OSPFROUTERID}}, - {3, {7, 1, OSPFIFIPADDRESS}}, - {3, {7, 1, OSPFADDRESSLESSIF}}, - {3, {7, 1, OSPFIFSTATE}} -}; +static struct trap_object ospfIfTrapList[] = {{-2, {1, OSPFROUTERID}}, + {3, {7, 1, OSPFIFIPADDRESS}}, + {3, {7, 1, OSPFADDRESSLESSIF}}, + {3, {7, 1, OSPFIFSTATE}}}; -static struct trap_object ospfVirtIfTrapList[] = -{ - {-2, {1, OSPFROUTERID}}, - {3, {9, 1, OSPFVIRTIFAREAID}}, - {3, {9, 1, OSPFVIRTIFNEIGHBOR}}, - {3, {9, 1, OSPFVIRTIFSTATE}} -}; +static struct trap_object ospfVirtIfTrapList[] = { + {-2, {1, OSPFROUTERID}}, + {3, {9, 1, OSPFVIRTIFAREAID}}, + {3, {9, 1, OSPFVIRTIFNEIGHBOR}}, + {3, {9, 1, OSPFVIRTIFSTATE}}}; -static void -ospfTrapNbrStateChange (struct ospf_neighbor *on) +static void ospfTrapNbrStateChange(struct ospf_neighbor *on) { - oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)]; - char msgbuf[16]; - - ospf_nbr_state_message(on, msgbuf, sizeof(msgbuf)); - zlog_info("ospfTrapNbrStateChange trap sent: %s now %s", - inet_ntoa(on->address.u.prefix4), msgbuf); - - oid_copy_addr (index, &(on->address.u.prefix4), IN_ADDR_SIZE); - index[IN_ADDR_SIZE] = 0; - - smux_trap (ospf_variables, sizeof ospf_variables / sizeof (struct variable), - ospf_trap_oid, sizeof ospf_trap_oid / sizeof (oid), - ospf_oid, sizeof ospf_oid / sizeof (oid), - index, IN_ADDR_SIZE + 1, - ospfNbrTrapList, - sizeof ospfNbrTrapList / sizeof (struct trap_object), - NBRSTATECHANGE); + oid index[sizeof(oid) * (IN_ADDR_SIZE + 1)]; + char msgbuf[16]; + + ospf_nbr_state_message(on, msgbuf, sizeof(msgbuf)); + zlog_info("ospfTrapNbrStateChange trap sent: %s now %s", + inet_ntoa(on->address.u.prefix4), msgbuf); + + oid_copy_addr(index, &(on->address.u.prefix4), IN_ADDR_SIZE); + index[IN_ADDR_SIZE] = 0; + + smux_trap(ospf_variables, + sizeof ospf_variables / sizeof(struct variable), + ospf_trap_oid, sizeof ospf_trap_oid / sizeof(oid), ospf_oid, + sizeof ospf_oid / sizeof(oid), index, IN_ADDR_SIZE + 1, + ospfNbrTrapList, + sizeof ospfNbrTrapList / sizeof(struct trap_object), + NBRSTATECHANGE); } -static void -ospfTrapVirtNbrStateChange (struct ospf_neighbor *on) +static void ospfTrapVirtNbrStateChange(struct ospf_neighbor *on) { - oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)]; - - zlog_info("ospfTrapVirtNbrStateChange trap sent"); - - oid_copy_addr (index, &(on->address.u.prefix4), IN_ADDR_SIZE); - index[IN_ADDR_SIZE] = 0; - - smux_trap (ospf_variables, sizeof ospf_variables / sizeof (struct variable), - ospf_trap_oid, sizeof ospf_trap_oid / sizeof (oid), - ospf_oid, sizeof ospf_oid / sizeof (oid), - index, IN_ADDR_SIZE + 1, - ospfVirtNbrTrapList, - sizeof ospfVirtNbrTrapList / sizeof (struct trap_object), - VIRTNBRSTATECHANGE); + oid index[sizeof(oid) * (IN_ADDR_SIZE + 1)]; + + zlog_info("ospfTrapVirtNbrStateChange trap sent"); + + oid_copy_addr(index, &(on->address.u.prefix4), IN_ADDR_SIZE); + index[IN_ADDR_SIZE] = 0; + + smux_trap(ospf_variables, + sizeof ospf_variables / sizeof(struct variable), + ospf_trap_oid, sizeof ospf_trap_oid / sizeof(oid), ospf_oid, + sizeof ospf_oid / sizeof(oid), index, IN_ADDR_SIZE + 1, + ospfVirtNbrTrapList, + sizeof ospfVirtNbrTrapList / sizeof(struct trap_object), + VIRTNBRSTATECHANGE); } -static int -ospf_snmp_nsm_change (struct ospf_neighbor *nbr, - int next_state, int old_state) +static int ospf_snmp_nsm_change(struct ospf_neighbor *nbr, int next_state, + int old_state) { - /* Terminal state or regression */ - if ((next_state == NSM_Full) - || (next_state == NSM_TwoWay) - || (next_state < old_state)) - { - /* ospfVirtNbrStateChange */ - if (nbr->oi->type == OSPF_IFTYPE_VIRTUALLINK) - ospfTrapVirtNbrStateChange(nbr); - /* ospfNbrStateChange trap */ - else - /* To/From FULL, only managed by DR */ - if (((next_state != NSM_Full) && (nbr->state != NSM_Full)) - || (nbr->oi->state == ISM_DR)) - ospfTrapNbrStateChange(nbr); - } - return 0; + /* Terminal state or regression */ + if ((next_state == NSM_Full) || (next_state == NSM_TwoWay) + || (next_state < old_state)) { + /* ospfVirtNbrStateChange */ + if (nbr->oi->type == OSPF_IFTYPE_VIRTUALLINK) + ospfTrapVirtNbrStateChange(nbr); + /* ospfNbrStateChange trap */ + else + /* To/From FULL, only managed by DR */ + if (((next_state != NSM_Full) + && (nbr->state != NSM_Full)) + || (nbr->oi->state == ISM_DR)) + ospfTrapNbrStateChange(nbr); + } + return 0; } -static void -ospfTrapIfStateChange (struct ospf_interface *oi) +static void ospfTrapIfStateChange(struct ospf_interface *oi) { - oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)]; - - zlog_info("ospfTrapIfStateChange trap sent: %s now %s", - inet_ntoa(oi->address->u.prefix4), - lookup_msg(ospf_ism_state_msg, oi->state, NULL)); - - oid_copy_addr (index, &(oi->address->u.prefix4), IN_ADDR_SIZE); - index[IN_ADDR_SIZE] = 0; - - smux_trap (ospf_variables, sizeof ospf_variables / sizeof (struct variable), - ospf_trap_oid, sizeof ospf_trap_oid / sizeof (oid), - ospf_oid, sizeof ospf_oid / sizeof (oid), - index, IN_ADDR_SIZE + 1, - ospfIfTrapList, - sizeof ospfIfTrapList / sizeof (struct trap_object), - IFSTATECHANGE); + oid index[sizeof(oid) * (IN_ADDR_SIZE + 1)]; + + zlog_info("ospfTrapIfStateChange trap sent: %s now %s", + inet_ntoa(oi->address->u.prefix4), + lookup_msg(ospf_ism_state_msg, oi->state, NULL)); + + oid_copy_addr(index, &(oi->address->u.prefix4), IN_ADDR_SIZE); + index[IN_ADDR_SIZE] = 0; + + smux_trap(ospf_variables, + sizeof ospf_variables / sizeof(struct variable), + ospf_trap_oid, sizeof ospf_trap_oid / sizeof(oid), ospf_oid, + sizeof ospf_oid / sizeof(oid), index, IN_ADDR_SIZE + 1, + ospfIfTrapList, + sizeof ospfIfTrapList / sizeof(struct trap_object), + IFSTATECHANGE); } -static void -ospfTrapVirtIfStateChange (struct ospf_interface *oi) +static void ospfTrapVirtIfStateChange(struct ospf_interface *oi) { - oid index[sizeof (oid) * (IN_ADDR_SIZE + 1)]; - - zlog_info("ospfTrapVirtIfStateChange trap sent"); - - oid_copy_addr (index, &(oi->address->u.prefix4), IN_ADDR_SIZE); - index[IN_ADDR_SIZE] = 0; - - smux_trap (ospf_variables, sizeof ospf_variables / sizeof (struct variable), - ospf_trap_oid, sizeof ospf_trap_oid / sizeof (oid), - ospf_oid, sizeof ospf_oid / sizeof (oid), - index, IN_ADDR_SIZE + 1, - ospfVirtIfTrapList, - sizeof ospfVirtIfTrapList / sizeof (struct trap_object), - VIRTIFSTATECHANGE); + oid index[sizeof(oid) * (IN_ADDR_SIZE + 1)]; + + zlog_info("ospfTrapVirtIfStateChange trap sent"); + + oid_copy_addr(index, &(oi->address->u.prefix4), IN_ADDR_SIZE); + index[IN_ADDR_SIZE] = 0; + + smux_trap(ospf_variables, + sizeof ospf_variables / sizeof(struct variable), + ospf_trap_oid, sizeof ospf_trap_oid / sizeof(oid), ospf_oid, + sizeof ospf_oid / sizeof(oid), index, IN_ADDR_SIZE + 1, + ospfVirtIfTrapList, + sizeof ospfVirtIfTrapList / sizeof(struct trap_object), + VIRTIFSTATECHANGE); } -static int -ospf_snmp_ism_change (struct ospf_interface *oi, - int state, int old_state) +static int ospf_snmp_ism_change(struct ospf_interface *oi, int state, + int old_state) { - /* Terminal state or regression */ - if ((state == ISM_DR) || (state == ISM_Backup) || (state == ISM_DROther) || - (state == ISM_PointToPoint) || (state < old_state)) - { - /* ospfVirtIfStateChange */ - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - ospfTrapVirtIfStateChange (oi); - /* ospfIfStateChange */ - else - ospfTrapIfStateChange (oi); - } - return 0; + /* Terminal state or regression */ + if ((state == ISM_DR) || (state == ISM_Backup) || (state == ISM_DROther) + || (state == ISM_PointToPoint) || (state < old_state)) { + /* ospfVirtIfStateChange */ + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + ospfTrapVirtIfStateChange(oi); + /* ospfIfStateChange */ + else + ospfTrapIfStateChange(oi); + } + return 0; } /* Register OSPF2-MIB. */ -static int -ospf_snmp_init (struct thread_master *tm) +static int ospf_snmp_init(struct thread_master *tm) { - ospf_snmp_iflist = list_new (); - ospf_snmp_vl_table = route_table_init (); - smux_init (tm); - REGISTER_MIB("mibII/ospf", ospf_variables, variable, ospf_oid); - return 0; + ospf_snmp_iflist = list_new(); + ospf_snmp_vl_table = route_table_init(); + smux_init(tm); + REGISTER_MIB("mibII/ospf", ospf_variables, variable, ospf_oid); + return 0; } -static int -ospf_snmp_module_init (void) +static int ospf_snmp_module_init(void) { - hook_register(ospf_if_update, ospf_snmp_if_update); - hook_register(ospf_if_delete, ospf_snmp_if_delete); - hook_register(ospf_vl_add, ospf_snmp_vl_add); - hook_register(ospf_vl_delete, ospf_snmp_vl_delete); - hook_register(ospf_ism_change, ospf_snmp_ism_change); - hook_register(ospf_nsm_change, ospf_snmp_nsm_change); - - hook_register(frr_late_init, ospf_snmp_init); - return 0; + hook_register(ospf_if_update, ospf_snmp_if_update); + hook_register(ospf_if_delete, ospf_snmp_if_delete); + hook_register(ospf_vl_add, ospf_snmp_vl_add); + hook_register(ospf_vl_delete, ospf_snmp_vl_delete); + hook_register(ospf_ism_change, ospf_snmp_ism_change); + hook_register(ospf_nsm_change, ospf_snmp_nsm_change); + + hook_register(frr_late_init, ospf_snmp_init); + return 0; } -FRR_MODULE_SETUP( - .name = "ospfd_snmp", - .version = FRR_VERSION, - .description = "ospfd AgentX SNMP module", - .init = ospf_snmp_module_init, -) +FRR_MODULE_SETUP(.name = "ospfd_snmp", .version = FRR_VERSION, + .description = "ospfd AgentX SNMP module", + .init = ospf_snmp_module_init, ) diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c index 173c4e91d..c520a3126 100644 --- a/ospfd/ospf_spf.c +++ b/ospfd/ospf_spf.c @@ -29,7 +29,7 @@ #include "if.h" #include "table.h" #include "log.h" -#include "sockunion.h" /* for inet_ntop () */ +#include "sockunion.h" /* for inet_ntop () */ #include "pqueue.h" #include "ospfd/ospfd.h" @@ -51,326 +51,304 @@ static unsigned int spf_reason_flags = 0; -static void -ospf_clear_spf_reason_flags (void) +static void ospf_clear_spf_reason_flags(void) { - spf_reason_flags = 0; + spf_reason_flags = 0; } -static void -ospf_spf_set_reason (ospf_spf_reason_t reason) +static void ospf_spf_set_reason(ospf_spf_reason_t reason) { - spf_reason_flags |= 1 << reason; + spf_reason_flags |= 1 << reason; } -static void ospf_vertex_free (void *); +static void ospf_vertex_free(void *); /* List of allocated vertices, to simplify cleanup of SPF. * Not thread-safe obviously. If it ever needs to be, it'd have to be * dynamically allocated at begin of ospf_spf_calculate */ -static struct list vertex_list = { .del = ospf_vertex_free }; +static struct list vertex_list = {.del = ospf_vertex_free}; /* Heap related functions, for the managment of the candidates, to * be used with pqueue. */ -static int -cmp (void * node1 , void * node2) +static int cmp(void *node1, void *node2) { - struct vertex * v1 = (struct vertex *) node1; - struct vertex * v2 = (struct vertex *) node2; - if (v1 != NULL && v2 != NULL ) - { - /* network vertices must be chosen before router vertices of same - * cost in order to find all shortest paths - */ - if ( ((v1->distance - v2->distance) == 0) - && (v1->type != v2->type)) - { - switch (v1->type) - { - case OSPF_VERTEX_NETWORK: - return -1; - case OSPF_VERTEX_ROUTER: - return 1; - } - } - else - return (v1->distance - v2->distance); - } - return 0; + struct vertex *v1 = (struct vertex *)node1; + struct vertex *v2 = (struct vertex *)node2; + if (v1 != NULL && v2 != NULL) { + /* network vertices must be chosen before router vertices of + * same + * cost in order to find all shortest paths + */ + if (((v1->distance - v2->distance) == 0) + && (v1->type != v2->type)) { + switch (v1->type) { + case OSPF_VERTEX_NETWORK: + return -1; + case OSPF_VERTEX_ROUTER: + return 1; + } + } else + return (v1->distance - v2->distance); + } + return 0; } -static void -update_stat (void *node , int position) +static void update_stat(void *node, int position) { - struct vertex *v = node; + struct vertex *v = node; - /* Set the status of the vertex, when its position changes. */ - *(v->stat) = position; + /* Set the status of the vertex, when its position changes. */ + *(v->stat) = position; } -static struct vertex_nexthop * -vertex_nexthop_new (void) +static struct vertex_nexthop *vertex_nexthop_new(void) { - return XCALLOC (MTYPE_OSPF_NEXTHOP, sizeof (struct vertex_nexthop)); + return XCALLOC(MTYPE_OSPF_NEXTHOP, sizeof(struct vertex_nexthop)); } -static void -vertex_nexthop_free (struct vertex_nexthop *nh) +static void vertex_nexthop_free(struct vertex_nexthop *nh) { - XFREE (MTYPE_OSPF_NEXTHOP, nh); + XFREE(MTYPE_OSPF_NEXTHOP, nh); } /* Free the canonical nexthop objects for an area, ie the nexthop objects * attached to the first-hop router vertices, and any intervening network * vertices. */ -static void -ospf_canonical_nexthops_free (struct vertex *root) +static void ospf_canonical_nexthops_free(struct vertex *root) { - struct listnode *node, *nnode; - struct vertex *child; - - for (ALL_LIST_ELEMENTS (root->children, node, nnode, child)) - { - struct listnode *n2, *nn2; - struct vertex_parent *vp; - - /* router vertices through an attached network each - * have a distinct (canonical / not inherited) nexthop - * which must be freed. - * - * A network vertex can only have router vertices as its - * children, so only one level of recursion is possible. - */ - if (child->type == OSPF_VERTEX_NETWORK) - ospf_canonical_nexthops_free (child); - - /* Free child nexthops pointing back to this root vertex */ - for (ALL_LIST_ELEMENTS (child->parents, n2, nn2, vp)) - if (vp->parent == root && vp->nexthop) - vertex_nexthop_free (vp->nexthop); - } -} + struct listnode *node, *nnode; + struct vertex *child; + + for (ALL_LIST_ELEMENTS(root->children, node, nnode, child)) { + struct listnode *n2, *nn2; + struct vertex_parent *vp; + + /* router vertices through an attached network each + * have a distinct (canonical / not inherited) nexthop + * which must be freed. + * + * A network vertex can only have router vertices as its + * children, so only one level of recursion is possible. + */ + if (child->type == OSPF_VERTEX_NETWORK) + ospf_canonical_nexthops_free(child); + + /* Free child nexthops pointing back to this root vertex */ + for (ALL_LIST_ELEMENTS(child->parents, n2, nn2, vp)) + if (vp->parent == root && vp->nexthop) + vertex_nexthop_free(vp->nexthop); + } +} /* TODO: Parent list should be excised, in favour of maintaining only * vertex_nexthop, with refcounts. */ -static struct vertex_parent * -vertex_parent_new (struct vertex *v, int backlink, struct vertex_nexthop *hop) +static struct vertex_parent *vertex_parent_new(struct vertex *v, int backlink, + struct vertex_nexthop *hop) { - struct vertex_parent *new; - - new = XMALLOC (MTYPE_OSPF_VERTEX_PARENT, sizeof (struct vertex_parent)); - - if (new == NULL) - return NULL; - - new->parent = v; - new->backlink = backlink; - new->nexthop = hop; - return new; + struct vertex_parent *new; + + new = XMALLOC(MTYPE_OSPF_VERTEX_PARENT, sizeof(struct vertex_parent)); + + if (new == NULL) + return NULL; + + new->parent = v; + new->backlink = backlink; + new->nexthop = hop; + return new; } -static void -vertex_parent_free (void *p) +static void vertex_parent_free(void *p) { - XFREE (MTYPE_OSPF_VERTEX_PARENT, p); + XFREE(MTYPE_OSPF_VERTEX_PARENT, p); } -static struct vertex * -ospf_vertex_new (struct ospf_lsa *lsa) +static struct vertex *ospf_vertex_new(struct ospf_lsa *lsa) { - struct vertex *new; - - new = XCALLOC (MTYPE_OSPF_VERTEX, sizeof (struct vertex)); - - new->flags = 0; - new->stat = &(lsa->stat); - new->type = lsa->data->type; - new->id = lsa->data->id; - new->lsa = lsa->data; - new->children = list_new (); - new->parents = list_new (); - new->parents->del = vertex_parent_free; - - listnode_add (&vertex_list, new); - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("%s: Created %s vertex %s", __func__, - new->type == OSPF_VERTEX_ROUTER ? "Router" : "Network", - inet_ntoa (new->lsa->id)); - return new; + struct vertex *new; + + new = XCALLOC(MTYPE_OSPF_VERTEX, sizeof(struct vertex)); + + new->flags = 0; + new->stat = &(lsa->stat); + new->type = lsa->data->type; + new->id = lsa->data->id; + new->lsa = lsa->data; + new->children = list_new(); + new->parents = list_new(); + new->parents->del = vertex_parent_free; + + listnode_add(&vertex_list, new); + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: Created %s vertex %s", __func__, + new->type == OSPF_VERTEX_ROUTER ? "Router" + : "Network", + inet_ntoa(new->lsa->id)); + return new; } -static void -ospf_vertex_free (void *data) +static void ospf_vertex_free(void *data) { - struct vertex *v = data; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("%s: Free %s vertex %s", __func__, - v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network", - inet_ntoa (v->lsa->id)); - - /* There should be no parents potentially holding references to this vertex - * Children however may still be there, but presumably referenced by other - * vertices - */ - //assert (listcount (v->parents) == 0); - - if (v->children) - list_delete (v->children); - v->children = NULL; - - if (v->parents) - list_delete (v->parents); - v->parents = NULL; - - v->lsa = NULL; - - XFREE (MTYPE_OSPF_VERTEX, v); + struct vertex *v = data; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: Free %s vertex %s", __func__, + v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network", + inet_ntoa(v->lsa->id)); + + /* There should be no parents potentially holding references to this + * vertex + * Children however may still be there, but presumably referenced by + * other + * vertices + */ + // assert (listcount (v->parents) == 0); + + if (v->children) + list_delete(v->children); + v->children = NULL; + + if (v->parents) + list_delete(v->parents); + v->parents = NULL; + + v->lsa = NULL; + + XFREE(MTYPE_OSPF_VERTEX, v); } -static void -ospf_vertex_dump(const char *msg, struct vertex *v, - int print_parents, int print_children) +static void ospf_vertex_dump(const char *msg, struct vertex *v, + int print_parents, int print_children) { - if ( ! IS_DEBUG_OSPF_EVENT) - return; - - zlog_debug("%s %s vertex %s distance %u flags %u", - msg, - v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network", - inet_ntoa(v->lsa->id), - v->distance, - (unsigned int)v->flags); - - if (print_parents) - { - struct listnode *node; - struct vertex_parent *vp; - - for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp)) - { - char buf1[BUFSIZ]; - - if (vp) - { - zlog_debug ("parent %s backlink %d nexthop %s interface %s", - inet_ntoa(vp->parent->lsa->id), vp->backlink, - inet_ntop(AF_INET, &vp->nexthop->router, buf1, BUFSIZ), - vp->nexthop->oi ? IF_NAME(vp->nexthop->oi) : "NULL"); - } + if (!IS_DEBUG_OSPF_EVENT) + return; + + zlog_debug("%s %s vertex %s distance %u flags %u", msg, + v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network", + inet_ntoa(v->lsa->id), v->distance, (unsigned int)v->flags); + + if (print_parents) { + struct listnode *node; + struct vertex_parent *vp; + + for (ALL_LIST_ELEMENTS_RO(v->parents, node, vp)) { + char buf1[BUFSIZ]; + + if (vp) { + zlog_debug( + "parent %s backlink %d nexthop %s interface %s", + inet_ntoa(vp->parent->lsa->id), + vp->backlink, + inet_ntop(AF_INET, &vp->nexthop->router, + buf1, BUFSIZ), + vp->nexthop->oi + ? IF_NAME(vp->nexthop->oi) + : "NULL"); + } + } + } + + if (print_children) { + struct listnode *cnode; + struct vertex *cv; + + for (ALL_LIST_ELEMENTS_RO(v->children, cnode, cv)) + ospf_vertex_dump(" child:", cv, 0, 0); } - } - - if (print_children) - { - struct listnode *cnode; - struct vertex *cv; - - for (ALL_LIST_ELEMENTS_RO (v->children, cnode, cv)) - ospf_vertex_dump(" child:", cv, 0, 0); - } } /* Add a vertex to the list of children in each of its parents. */ -static void -ospf_vertex_add_parent (struct vertex *v) +static void ospf_vertex_add_parent(struct vertex *v) { - struct vertex_parent *vp; - struct listnode *node; - - assert (v && v->parents); - - for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp)) - { - assert (vp->parent && vp->parent->children); - - /* No need to add two links from the same parent. */ - if (listnode_lookup (vp->parent->children, v) == NULL) - listnode_add (vp->parent->children, v); - } + struct vertex_parent *vp; + struct listnode *node; + + assert(v && v->parents); + + for (ALL_LIST_ELEMENTS_RO(v->parents, node, vp)) { + assert(vp->parent && vp->parent->children); + + /* No need to add two links from the same parent. */ + if (listnode_lookup(vp->parent->children, v) == NULL) + listnode_add(vp->parent->children, v); + } } -static void -ospf_spf_init (struct ospf_area *area) +static void ospf_spf_init(struct ospf_area *area) { - struct vertex *v; - - /* Create root node. */ - v = ospf_vertex_new (area->router_lsa_self); - - area->spf = v; - - /* Reset ABR and ASBR router counts. */ - area->abr_count = 0; - area->asbr_count = 0; + struct vertex *v; + + /* Create root node. */ + v = ospf_vertex_new(area->router_lsa_self); + + area->spf = v; + + /* Reset ABR and ASBR router counts. */ + area->abr_count = 0; + area->asbr_count = 0; } /* return index of link back to V from W, or -1 if no link found */ -static int -ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v) +static int ospf_lsa_has_link(struct lsa_header *w, struct lsa_header *v) { - unsigned int i, length; - struct router_lsa *rl; - struct network_lsa *nl; - - /* In case of W is Network LSA. */ - if (w->type == OSPF_NETWORK_LSA) - { - if (v->type == OSPF_NETWORK_LSA) - return -1; - - nl = (struct network_lsa *) w; - length = (ntohs (w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4; - - for (i = 0; i < length; i++) - if (IPV4_ADDR_SAME (&nl->routers[i], &v->id)) - return i; - return -1; - } - - /* In case of W is Router LSA. */ - if (w->type == OSPF_ROUTER_LSA) - { - rl = (struct router_lsa *) w; - - length = ntohs (w->length); - - for (i = 0; - i < ntohs (rl->links) && length >= sizeof (struct router_lsa); - i++, length -= 12) - { - switch (rl->link[i].type) - { - case LSA_LINK_TYPE_POINTOPOINT: - case LSA_LINK_TYPE_VIRTUALLINK: - /* Router LSA ID. */ - if (v->type == OSPF_ROUTER_LSA && - IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id)) - { - return i; - } - break; - case LSA_LINK_TYPE_TRANSIT: - /* Network LSA ID. */ - if (v->type == OSPF_NETWORK_LSA && - IPV4_ADDR_SAME (&rl->link[i].link_id, &v->id)) - { - return i; - } - break; - case LSA_LINK_TYPE_STUB: - /* Stub can't lead anywhere, carry on */ - continue; - default: - break; - } - } - } - return -1; + unsigned int i, length; + struct router_lsa *rl; + struct network_lsa *nl; + + /* In case of W is Network LSA. */ + if (w->type == OSPF_NETWORK_LSA) { + if (v->type == OSPF_NETWORK_LSA) + return -1; + + nl = (struct network_lsa *)w; + length = (ntohs(w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4; + + for (i = 0; i < length; i++) + if (IPV4_ADDR_SAME(&nl->routers[i], &v->id)) + return i; + return -1; + } + + /* In case of W is Router LSA. */ + if (w->type == OSPF_ROUTER_LSA) { + rl = (struct router_lsa *)w; + + length = ntohs(w->length); + + for (i = 0; i < ntohs(rl->links) + && length >= sizeof(struct router_lsa); + i++, length -= 12) { + switch (rl->link[i].type) { + case LSA_LINK_TYPE_POINTOPOINT: + case LSA_LINK_TYPE_VIRTUALLINK: + /* Router LSA ID. */ + if (v->type == OSPF_ROUTER_LSA + && IPV4_ADDR_SAME(&rl->link[i].link_id, + &v->id)) { + return i; + } + break; + case LSA_LINK_TYPE_TRANSIT: + /* Network LSA ID. */ + if (v->type == OSPF_NETWORK_LSA + && IPV4_ADDR_SAME(&rl->link[i].link_id, + &v->id)) { + return i; + } + break; + case LSA_LINK_TYPE_STUB: + /* Stub can't lead anywhere, carry on */ + continue; + default: + break; + } + } + } + return -1; } /* Find the next link after prev_link from v to w. If prev_link is @@ -378,119 +356,117 @@ ospf_lsa_has_link (struct lsa_header *w, struct lsa_header *v) * these link types will never be returned. */ static struct router_lsa_link * -ospf_get_next_link (struct vertex *v, struct vertex *w, - struct router_lsa_link *prev_link) +ospf_get_next_link(struct vertex *v, struct vertex *w, + struct router_lsa_link *prev_link) { - u_char *p; - u_char *lim; - u_char lsa_type = LSA_LINK_TYPE_TRANSIT; - struct router_lsa_link *l; - - if (w->type == OSPF_VERTEX_ROUTER) - lsa_type = LSA_LINK_TYPE_POINTOPOINT; - - if (prev_link == NULL) - p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4; - else - { - p = (u_char *) prev_link; - p += (OSPF_ROUTER_LSA_LINK_SIZE + - (prev_link->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE)); - } + u_char *p; + u_char *lim; + u_char lsa_type = LSA_LINK_TYPE_TRANSIT; + struct router_lsa_link *l; + + if (w->type == OSPF_VERTEX_ROUTER) + lsa_type = LSA_LINK_TYPE_POINTOPOINT; + + if (prev_link == NULL) + p = ((u_char *)v->lsa) + OSPF_LSA_HEADER_SIZE + 4; + else { + p = (u_char *)prev_link; + p += (OSPF_ROUTER_LSA_LINK_SIZE + + (prev_link->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE)); + } - lim = ((u_char *) v->lsa) + ntohs (v->lsa->length); + lim = ((u_char *)v->lsa) + ntohs(v->lsa->length); - while (p < lim) - { - l = (struct router_lsa_link *) p; + while (p < lim) { + l = (struct router_lsa_link *)p; - p += (OSPF_ROUTER_LSA_LINK_SIZE + (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE)); + p += (OSPF_ROUTER_LSA_LINK_SIZE + + (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE)); - if (l->m[0].type != lsa_type) - continue; + if (l->m[0].type != lsa_type) + continue; - if (IPV4_ADDR_SAME (&l->link_id, &w->id)) - return l; - } + if (IPV4_ADDR_SAME(&l->link_id, &w->id)) + return l; + } - return NULL; + return NULL; } -static void -ospf_spf_flush_parents (struct vertex *w) +static void ospf_spf_flush_parents(struct vertex *w) { - struct vertex_parent *vp; - struct listnode *ln, *nn; - - /* delete the existing nexthops */ - for (ALL_LIST_ELEMENTS (w->parents, ln, nn, vp)) - { - list_delete_node (w->parents, ln); - vertex_parent_free (vp); - } + struct vertex_parent *vp; + struct listnode *ln, *nn; + + /* delete the existing nexthops */ + for (ALL_LIST_ELEMENTS(w->parents, ln, nn, vp)) { + list_delete_node(w->parents, ln); + vertex_parent_free(vp); + } } -/* +/* * Consider supplied next-hop for inclusion to the supplied list of - * equal-cost next-hops, adjust list as neccessary. + * equal-cost next-hops, adjust list as neccessary. */ -static void -ospf_spf_add_parent (struct vertex *v, struct vertex *w, - struct vertex_nexthop *newhop, - unsigned int distance) +static void ospf_spf_add_parent(struct vertex *v, struct vertex *w, + struct vertex_nexthop *newhop, + unsigned int distance) { - struct vertex_parent *vp, *wp; - struct listnode *node; - - /* we must have a newhop, and a distance */ - assert (v && w && newhop); - assert (distance); - - /* IFF w has already been assigned a distance, then we shouldn't get here - * unless callers have determined V(l)->W is shortest / equal-shortest - * path (0 is a special case distance (no distance yet assigned)). - */ - if (w->distance) - assert (distance <= w->distance); - else - w->distance = distance; - - if (IS_DEBUG_OSPF_EVENT) - { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug ("%s: Adding %s as parent of %s", - __func__, - inet_ntop(AF_INET, &v->lsa->id, buf[0], sizeof(buf[0])), - inet_ntop(AF_INET, &w->lsa->id, buf[1], sizeof(buf[1]))); - } - - /* Adding parent for a new, better path: flush existing parents from W. */ - if (distance < w->distance) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("%s: distance %d better than %d, flushing existing parents", - __func__, distance, w->distance); - ospf_spf_flush_parents (w); - w->distance = distance; - } - - /* new parent is <= existing parents, add it to parent list (if nexthop - * not on parent list) - */ - for (ALL_LIST_ELEMENTS_RO(w->parents, node, wp)) - { - if (memcmp(newhop, wp->nexthop, sizeof(*newhop)) == 0) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("%s: ... nexthop already on parent list, skipping add", __func__); - return; - } - } + struct vertex_parent *vp, *wp; + struct listnode *node; + + /* we must have a newhop, and a distance */ + assert(v && w && newhop); + assert(distance); + + /* IFF w has already been assigned a distance, then we shouldn't get + * here + * unless callers have determined V(l)->W is shortest / equal-shortest + * path (0 is a special case distance (no distance yet assigned)). + */ + if (w->distance) + assert(distance <= w->distance); + else + w->distance = distance; + + if (IS_DEBUG_OSPF_EVENT) { + char buf[2][INET_ADDRSTRLEN]; + zlog_debug( + "%s: Adding %s as parent of %s", __func__, + inet_ntop(AF_INET, &v->lsa->id, buf[0], sizeof(buf[0])), + inet_ntop(AF_INET, &w->lsa->id, buf[1], + sizeof(buf[1]))); + } + + /* Adding parent for a new, better path: flush existing parents from W. + */ + if (distance < w->distance) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "%s: distance %d better than %d, flushing existing parents", + __func__, distance, w->distance); + ospf_spf_flush_parents(w); + w->distance = distance; + } + + /* new parent is <= existing parents, add it to parent list (if nexthop + * not on parent list) + */ + for (ALL_LIST_ELEMENTS_RO(w->parents, node, wp)) { + if (memcmp(newhop, wp->nexthop, sizeof(*newhop)) == 0) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "%s: ... nexthop already on parent list, skipping add", + __func__); + return; + } + } - vp = vertex_parent_new (v, ospf_lsa_has_link (w->lsa, v->lsa), newhop); - listnode_add (w->parents, vp); + vp = vertex_parent_new(v, ospf_lsa_has_link(w->lsa, v->lsa), newhop); + listnode_add(w->parents, vp); - return; + return; } /* 16.1.1. Calculate nexthop from root through V (parent) to @@ -504,256 +480,298 @@ ospf_spf_add_parent (struct vertex *v, struct vertex *w, * this function returns. This function will update the W vertex with the * provided distance as appropriate. */ -static unsigned int -ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v, - struct vertex *w, struct router_lsa_link *l, - unsigned int distance, int lsa_pos) +static unsigned int ospf_nexthop_calculation(struct ospf_area *area, + struct vertex *v, struct vertex *w, + struct router_lsa_link *l, + unsigned int distance, int lsa_pos) { - struct listnode *node, *nnode; - struct vertex_nexthop *nh; - struct vertex_parent *vp; - struct ospf_interface *oi = NULL; - unsigned int added = 0; - char buf1[BUFSIZ]; - char buf2[BUFSIZ]; - - if (IS_DEBUG_OSPF_EVENT) - { - zlog_debug ("ospf_nexthop_calculation(): Start"); - ospf_vertex_dump("V (parent):", v, 1, 1); - ospf_vertex_dump("W (dest) :", w, 1, 1); - zlog_debug ("V->W distance: %d", distance); - } - - if (v == area->spf) - { - /* 16.1.1 para 4. In the first case, the parent vertex (V) is the - root (the calculating router itself). This means that the - destination is either a directly connected network or directly - connected router. The outgoing interface in this case is simply - the OSPF interface connecting to the destination network/router. - */ - - /* we *must* be supplied with the link data */ - assert (l != NULL); - oi = ospf_if_lookup_by_lsa_pos (area, lsa_pos); - if (!oi) - { - zlog_debug("%s: OI not found in LSA: lsa_pos:%d link_id:%s link_data:%s", - __func__, lsa_pos, - inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ), - inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ)); - return 0; - } - - if (IS_DEBUG_OSPF_EVENT) - { - zlog_debug("%s: considering link:%s " - "type:%d link_id:%s link_data:%s", - __func__, oi->ifp->name, l->m[0].type, - inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ), - inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ)); + struct listnode *node, *nnode; + struct vertex_nexthop *nh; + struct vertex_parent *vp; + struct ospf_interface *oi = NULL; + unsigned int added = 0; + char buf1[BUFSIZ]; + char buf2[BUFSIZ]; + + if (IS_DEBUG_OSPF_EVENT) { + zlog_debug("ospf_nexthop_calculation(): Start"); + ospf_vertex_dump("V (parent):", v, 1, 1); + ospf_vertex_dump("W (dest) :", w, 1, 1); + zlog_debug("V->W distance: %d", distance); } - if (w->type == OSPF_VERTEX_ROUTER) - { - /* l is a link from v to w - * l2 will be link from w to v - */ - struct router_lsa_link *l2 = NULL; - - if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT) - { - struct in_addr nexthop = { .s_addr = 0 }; - - /* If the destination is a router which connects to - the calculating router via a Point-to-MultiPoint - network, the destination's next hop IP address(es) - can be determined by examining the destination's - router-LSA: each link pointing back to the - calculating router and having a Link Data field - belonging to the Point-to-MultiPoint network - provides an IP address of the next hop router. - - At this point l is a link from V to W, and V is the - root ("us"). If it is a point-to-multipoint interface, - then look through the links in the opposite direction (W to V). - If any of them have an address that lands within the - subnet declared by the PtMP link, then that link - is a constituent of the PtMP link, and its address is - a nexthop address for V. - */ - if (oi->type == OSPF_IFTYPE_POINTOPOINT) - { - /* Having nexthop = 0 is tempting, but NOT acceptable. - It breaks AS-External routes with a forwarding address, - since ospf_ase_complete_direct_routes() will mistakenly - assume we've reached the last hop and should place the - forwarding address as nexthop. - Also, users may configure multi-access links in p2p mode, - so we need the IP to ARP the nexthop. - */ - struct ospf_neighbor *nbr_w; - - nbr_w = ospf_nbr_lookup_by_routerid (oi->nbrs, &l->link_id); - if (nbr_w != NULL) - { - added = 1; - nexthop = nbr_w->src; - } + if (v == area->spf) { + /* 16.1.1 para 4. In the first case, the parent vertex (V) is + the + root (the calculating router itself). This means that the + destination is either a directly connected network or + directly + connected router. The outgoing interface in this case is + simply + the OSPF interface connecting to the destination + network/router. + */ + + /* we *must* be supplied with the link data */ + assert(l != NULL); + oi = ospf_if_lookup_by_lsa_pos(area, lsa_pos); + if (!oi) { + zlog_debug( + "%s: OI not found in LSA: lsa_pos:%d link_id:%s link_data:%s", + __func__, lsa_pos, + inet_ntop(AF_INET, &l->link_id, buf1, BUFSIZ), + inet_ntop(AF_INET, &l->link_data, buf2, + BUFSIZ)); + return 0; } - else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) - { - struct prefix_ipv4 la; - - la.family = AF_INET; - la.prefixlen = oi->address->prefixlen; - /* V links to W on PtMP interface - - find the interface address on W */ - while ((l2 = ospf_get_next_link (w, v, l2))) - { - la.prefix = l2->link_data; + if (IS_DEBUG_OSPF_EVENT) { + zlog_debug( + "%s: considering link:%s " + "type:%d link_id:%s link_data:%s", + __func__, oi->ifp->name, l->m[0].type, + inet_ntop(AF_INET, &l->link_id, buf1, BUFSIZ), + inet_ntop(AF_INET, &l->link_data, buf2, + BUFSIZ)); + } - if (prefix_cmp ((struct prefix *) &la, - oi->address) != 0) - continue; - /* link_data is on our PtMP network */ - added = 1; - nexthop = l2->link_data; - break; - } + if (w->type == OSPF_VERTEX_ROUTER) { + /* l is a link from v to w + * l2 will be link from w to v + */ + struct router_lsa_link *l2 = NULL; + + if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT) { + struct in_addr nexthop = {.s_addr = 0}; + + /* If the destination is a router which connects + to + the calculating router via a + Point-to-MultiPoint + network, the destination's next hop IP + address(es) + can be determined by examining the + destination's + router-LSA: each link pointing back to the + calculating router and having a Link Data + field + belonging to the Point-to-MultiPoint network + provides an IP address of the next hop + router. + + At this point l is a link from V to W, and V + is the + root ("us"). If it is a point-to-multipoint + interface, + then look through the links in the opposite + direction (W to V). + If any of them have an address that lands + within the + subnet declared by the PtMP link, then that + link + is a constituent of the PtMP link, and its + address is + a nexthop address for V. + */ + if (oi->type == OSPF_IFTYPE_POINTOPOINT) { + /* Having nexthop = 0 is tempting, but + NOT acceptable. + It breaks AS-External routes with a + forwarding address, + since + ospf_ase_complete_direct_routes() + will mistakenly + assume we've reached the last hop and + should place the + forwarding address as nexthop. + Also, users may configure + multi-access links in p2p mode, + so we need the IP to ARP the nexthop. + */ + struct ospf_neighbor *nbr_w; + + nbr_w = ospf_nbr_lookup_by_routerid( + oi->nbrs, &l->link_id); + if (nbr_w != NULL) { + added = 1; + nexthop = nbr_w->src; + } + } else if (oi->type + == OSPF_IFTYPE_POINTOMULTIPOINT) { + struct prefix_ipv4 la; + + la.family = AF_INET; + la.prefixlen = oi->address->prefixlen; + + /* V links to W on PtMP interface + - find the interface address on W */ + while ((l2 = ospf_get_next_link(w, v, + l2))) { + la.prefix = l2->link_data; + + if (prefix_cmp((struct prefix + *)&la, + oi->address) + != 0) + continue; + /* link_data is on our PtMP + * network */ + added = 1; + nexthop = l2->link_data; + break; + } + } + + if (added) { + /* found all necessary info to build + * nexthop */ + nh = vertex_nexthop_new(); + nh->oi = oi; + nh->router = nexthop; + ospf_spf_add_parent(v, w, nh, distance); + return 1; + } else + zlog_info( + "%s: could not determine nexthop for link %s", + __func__, oi->ifp->name); + } /* end point-to-point link from V to W */ + else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK) { + struct ospf_vl_data *vl_data; + + /* VLink implementation limitations: + * a) vl_data can only reference one nexthop, so + * no ECMP + * to backbone through VLinks. Though + * transit-area + * summaries may be considered, and those can + * be ECMP. + * b) We can only use /one/ VLink, even if + * multiple ones + * exist this router through multiple + * transit-areas. + */ + vl_data = ospf_vl_lookup(area->ospf, NULL, + l->link_id); + + if (vl_data + && CHECK_FLAG(vl_data->flags, + OSPF_VL_FLAG_APPROVED)) { + nh = vertex_nexthop_new(); + nh->oi = vl_data->nexthop.oi; + nh->router = vl_data->nexthop.router; + ospf_spf_add_parent(v, w, nh, distance); + return 1; + } else + zlog_info( + "ospf_nexthop_calculation(): " + "vl_data for VL link not found"); + } /* end virtual-link from V to W */ + return 0; + } /* end W is a Router vertex */ + else { + assert(w->type == OSPF_VERTEX_NETWORK); + + nh = vertex_nexthop_new(); + nh->oi = oi; + nh->router.s_addr = 0; /* Nexthop not required */ + ospf_spf_add_parent(v, w, nh, distance); + return 1; + } + } /* end V is the root */ + /* Check if W's parent is a network connected to root. */ + else if (v->type == OSPF_VERTEX_NETWORK) { + /* See if any of V's parents are the root. */ + for (ALL_LIST_ELEMENTS(v->parents, node, nnode, vp)) { + if (vp->parent == area->spf) /* connects to root? */ + { + /* 16.1.1 para 5. ...the parent vertex is a + * network that + * directly connects the calculating router to + * the destination + * router. The list of next hops is then + * determined by + * examining the destination's router-LSA... + */ + + assert(w->type == OSPF_VERTEX_ROUTER); + while ((l = ospf_get_next_link(w, v, l))) { + /* ...For each link in the router-LSA + * that points back to the + * parent network, the link's Link Data + * field provides the IP + * address of a next hop router. The + * outgoing interface to + * use can then be derived from the next + * hop IP address (or + * it can be inherited from the parent + * network). + */ + nh = vertex_nexthop_new(); + nh->oi = vp->nexthop->oi; + nh->router = l->link_data; + added = 1; + ospf_spf_add_parent(v, w, nh, distance); + } + /* Note lack of return is deliberate. See next + * comment. */ + } } + /* NB: This code is non-trivial. + * + * E.g. it is not enough to know that V connects to the root. It + * is + * also important that the while above, looping through all + * links from + * W->V found at least one link, so that we know there is + * bi-directional connectivity between V and W (which need not + * be the + * case, e.g. when OSPF has not yet converged fully). + * Otherwise, if + * we /always/ return here, without having checked that + * root->V->-W + * actually resulted in a valid nexthop being created, then we + * we will + * prevent SPF from finding/using higher cost paths. + * + * It is important, if root->V->W has not been added, that we + * continue + * through to the intervening-router nexthop code below. So as + * to + * ensure other paths to V may be used. This avoids unnecessary + * blackholes while OSPF is convergening. + * + * I.e. we may have arrived at this function, examining V -> W, + * via + * workable paths other than root -> V, and it's important to + * avoid + * getting "confused" by non-working root->V->W path - it's + * important + * to *not* lose the working non-root paths, just because of a + * non-viable root->V->W. + * + * See also bug #330 (required reading!), and: + * + * http://blogs.oracle.com/paulj/entry/the_difference_a_line_makes + */ + if (added) + return added; + } - if (added) - { - /* found all necessary info to build nexthop */ - nh = vertex_nexthop_new (); - nh->oi = oi; - nh->router = nexthop; - ospf_spf_add_parent (v, w, nh, distance); - return 1; - } - else - zlog_info("%s: could not determine nexthop for link %s", - __func__, oi->ifp->name); - } /* end point-to-point link from V to W */ - else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK) - { - struct ospf_vl_data *vl_data; - - /* VLink implementation limitations: - * a) vl_data can only reference one nexthop, so no ECMP - * to backbone through VLinks. Though transit-area - * summaries may be considered, and those can be ECMP. - * b) We can only use /one/ VLink, even if multiple ones - * exist this router through multiple transit-areas. - */ - vl_data = ospf_vl_lookup (area->ospf, NULL, l->link_id); - - if (vl_data - && CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED)) - { - nh = vertex_nexthop_new (); - nh->oi = vl_data->nexthop.oi; - nh->router = vl_data->nexthop.router; - ospf_spf_add_parent (v, w, nh, distance); - return 1; - } - else - zlog_info("ospf_nexthop_calculation(): " - "vl_data for VL link not found"); - } /* end virtual-link from V to W */ - return 0; - } /* end W is a Router vertex */ - else - { - assert(w->type == OSPF_VERTEX_NETWORK); + /* 16.1.1 para 4. If there is at least one intervening router in the + * current shortest path between the destination and the root, the + * destination simply inherits the set of next hops from the + * parent. + */ + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: Intervening routers, adding parent(s)", + __func__); + + for (ALL_LIST_ELEMENTS(v->parents, node, nnode, vp)) { + added = 1; + ospf_spf_add_parent(v, w, vp->nexthop, distance); + } - nh = vertex_nexthop_new (); - nh->oi = oi; - nh->router.s_addr = 0; /* Nexthop not required */ - ospf_spf_add_parent (v, w, nh, distance); - return 1; - } - } /* end V is the root */ - /* Check if W's parent is a network connected to root. */ - else if (v->type == OSPF_VERTEX_NETWORK) - { - /* See if any of V's parents are the root. */ - for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp)) - { - if (vp->parent == area->spf) /* connects to root? */ - { - /* 16.1.1 para 5. ...the parent vertex is a network that - * directly connects the calculating router to the destination - * router. The list of next hops is then determined by - * examining the destination's router-LSA... - */ - - assert(w->type == OSPF_VERTEX_ROUTER); - while ((l = ospf_get_next_link (w, v, l))) - { - /* ...For each link in the router-LSA that points back to the - * parent network, the link's Link Data field provides the IP - * address of a next hop router. The outgoing interface to - * use can then be derived from the next hop IP address (or - * it can be inherited from the parent network). - */ - nh = vertex_nexthop_new (); - nh->oi = vp->nexthop->oi; - nh->router = l->link_data; - added = 1; - ospf_spf_add_parent (v, w, nh, distance); - } - /* Note lack of return is deliberate. See next comment. */ - } - } - /* NB: This code is non-trivial. - * - * E.g. it is not enough to know that V connects to the root. It is - * also important that the while above, looping through all links from - * W->V found at least one link, so that we know there is - * bi-directional connectivity between V and W (which need not be the - * case, e.g. when OSPF has not yet converged fully). Otherwise, if - * we /always/ return here, without having checked that root->V->-W - * actually resulted in a valid nexthop being created, then we we will - * prevent SPF from finding/using higher cost paths. - * - * It is important, if root->V->W has not been added, that we continue - * through to the intervening-router nexthop code below. So as to - * ensure other paths to V may be used. This avoids unnecessary - * blackholes while OSPF is convergening. - * - * I.e. we may have arrived at this function, examining V -> W, via - * workable paths other than root -> V, and it's important to avoid - * getting "confused" by non-working root->V->W path - it's important - * to *not* lose the working non-root paths, just because of a - * non-viable root->V->W. - * - * See also bug #330 (required reading!), and: - * - * http://blogs.oracle.com/paulj/entry/the_difference_a_line_makes - */ - if (added) - return added; - } - - /* 16.1.1 para 4. If there is at least one intervening router in the - * current shortest path between the destination and the root, the - * destination simply inherits the set of next hops from the - * parent. - */ - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("%s: Intervening routers, adding parent(s)", __func__); - - for (ALL_LIST_ELEMENTS (v->parents, node, nnode, vp)) - { - added = 1; - ospf_spf_add_parent (v, w, vp->nexthop, distance); - } - - return added; + return added; } /* RFC2328 Section 16.1 (2). @@ -761,329 +779,319 @@ ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v, * of candidates with any vertices not already on the list. If a lower-cost * path is found to a vertex already on the candidate list, store the new cost. */ -static void -ospf_spf_next (struct vertex *v, struct ospf_area *area, - struct pqueue * candidate) +static void ospf_spf_next(struct vertex *v, struct ospf_area *area, + struct pqueue *candidate) { - struct ospf_lsa *w_lsa = NULL; - u_char *p; - u_char *lim; - struct router_lsa_link *l = NULL; - struct in_addr *r; - int type = 0, lsa_pos=-1, lsa_pos_next=0; - - /* If this is a router-LSA, and bit V of the router-LSA (see Section - A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */ - if (v->type == OSPF_VERTEX_ROUTER) - { - if (IS_ROUTER_LSA_VIRTUAL ((struct router_lsa *) v->lsa)) - area->transit = OSPF_TRANSIT_TRUE; - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("%s: Next vertex of %s vertex %s", - __func__, - v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network", - inet_ntoa(v->lsa->id)); - - p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4; - lim = ((u_char *) v->lsa) + ntohs (v->lsa->length); - - while (p < lim) - { - struct vertex *w; - unsigned int distance; - - /* In case of V is Router-LSA. */ - if (v->lsa->type == OSPF_ROUTER_LSA) - { - l = (struct router_lsa_link *) p; - - lsa_pos = lsa_pos_next; /* LSA link position */ - lsa_pos_next++; - p += (OSPF_ROUTER_LSA_LINK_SIZE + - (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE)); - - /* (a) If this is a link to a stub network, examine the next - link in V's LSA. Links to stub networks will be - considered in the second stage of the shortest path - calculation. */ - if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB) - continue; - - /* (b) Otherwise, W is a transit vertex (router or transit - network). Look up the vertex W's LSA (router-LSA or - network-LSA) in Area A's link state database. */ - switch (type) - { - case LSA_LINK_TYPE_POINTOPOINT: - case LSA_LINK_TYPE_VIRTUALLINK: - if (type == LSA_LINK_TYPE_VIRTUALLINK) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("looking up LSA through VL: %s", - inet_ntoa (l->link_id)); - } + struct ospf_lsa *w_lsa = NULL; + u_char *p; + u_char *lim; + struct router_lsa_link *l = NULL; + struct in_addr *r; + int type = 0, lsa_pos = -1, lsa_pos_next = 0; + + /* If this is a router-LSA, and bit V of the router-LSA (see Section + A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */ + if (v->type == OSPF_VERTEX_ROUTER) { + if (IS_ROUTER_LSA_VIRTUAL((struct router_lsa *)v->lsa)) + area->transit = OSPF_TRANSIT_TRUE; + } - w_lsa = ospf_lsa_lookup (area, OSPF_ROUTER_LSA, l->link_id, - l->link_id); - if (w_lsa) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("found Router LSA %s", inet_ntoa (l->link_id)); - } - break; - case LSA_LINK_TYPE_TRANSIT: - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Looking up Network LSA, ID: %s", - inet_ntoa (l->link_id)); - w_lsa = ospf_lsa_lookup_by_id (area, OSPF_NETWORK_LSA, - l->link_id); - if (w_lsa) - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("found the LSA"); - break; - default: - zlog_warn ("Invalid LSA link type %d", type); - continue; - } - } - else - { - /* In case of V is Network-LSA. */ - r = (struct in_addr *) p; - p += sizeof (struct in_addr); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: Next vertex of %s vertex %s", __func__, + v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network", + inet_ntoa(v->lsa->id)); + + p = ((u_char *)v->lsa) + OSPF_LSA_HEADER_SIZE + 4; + lim = ((u_char *)v->lsa) + ntohs(v->lsa->length); + + while (p < lim) { + struct vertex *w; + unsigned int distance; + + /* In case of V is Router-LSA. */ + if (v->lsa->type == OSPF_ROUTER_LSA) { + l = (struct router_lsa_link *)p; + + lsa_pos = lsa_pos_next; /* LSA link position */ + lsa_pos_next++; + p += (OSPF_ROUTER_LSA_LINK_SIZE + + (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE)); + + /* (a) If this is a link to a stub network, examine the + next + link in V's LSA. Links to stub networks will be + considered in the second stage of the shortest path + calculation. */ + if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB) + continue; + + /* (b) Otherwise, W is a transit vertex (router or + transit + network). Look up the vertex W's LSA (router-LSA or + network-LSA) in Area A's link state database. */ + switch (type) { + case LSA_LINK_TYPE_POINTOPOINT: + case LSA_LINK_TYPE_VIRTUALLINK: + if (type == LSA_LINK_TYPE_VIRTUALLINK) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "looking up LSA through VL: %s", + inet_ntoa(l->link_id)); + } + + w_lsa = ospf_lsa_lookup(area, OSPF_ROUTER_LSA, + l->link_id, l->link_id); + if (w_lsa) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "found Router LSA %s", + inet_ntoa(l->link_id)); + } + break; + case LSA_LINK_TYPE_TRANSIT: + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Looking up Network LSA, ID: %s", + inet_ntoa(l->link_id)); + w_lsa = ospf_lsa_lookup_by_id( + area, OSPF_NETWORK_LSA, l->link_id); + if (w_lsa) + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("found the LSA"); + break; + default: + zlog_warn("Invalid LSA link type %d", type); + continue; + } + } else { + /* In case of V is Network-LSA. */ + r = (struct in_addr *)p; + p += sizeof(struct in_addr); + + /* Lookup the vertex W's LSA. */ + w_lsa = ospf_lsa_lookup_by_id(area, OSPF_ROUTER_LSA, + *r); + if (w_lsa) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("found Router LSA %s", + inet_ntoa(w_lsa->data->id)); + } + } - /* Lookup the vertex W's LSA. */ - w_lsa = ospf_lsa_lookup_by_id (area, OSPF_ROUTER_LSA, *r); - if (w_lsa) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("found Router LSA %s", inet_ntoa (w_lsa->data->id)); - } - } + /* (b cont.) If the LSA does not exist, or its LS age is equal + to MaxAge, or it does not have a link back to vertex V, + examine the next link in V's LSA.[23] */ + if (w_lsa == NULL) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("No LSA found"); + continue; + } - /* (b cont.) If the LSA does not exist, or its LS age is equal - to MaxAge, or it does not have a link back to vertex V, - examine the next link in V's LSA.[23] */ - if (w_lsa == NULL) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("No LSA found"); - continue; - } + if (IS_LSA_MAXAGE(w_lsa)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("LSA is MaxAge"); + continue; + } - if (IS_LSA_MAXAGE (w_lsa)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA is MaxAge"); - continue; - } + if (ospf_lsa_has_link(w_lsa->data, v->lsa) < 0) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("The LSA doesn't have a link back"); + continue; + } - if (ospf_lsa_has_link (w_lsa->data, v->lsa) < 0 ) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("The LSA doesn't have a link back"); - continue; - } + /* (c) If vertex W is already on the shortest-path tree, examine + the next link in the LSA. */ + if (w_lsa->stat == LSA_SPF_IN_SPFTREE) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("The LSA is already in SPF"); + continue; + } - /* (c) If vertex W is already on the shortest-path tree, examine - the next link in the LSA. */ - if (w_lsa->stat == LSA_SPF_IN_SPFTREE) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("The LSA is already in SPF"); - continue; - } + /* (d) Calculate the link state cost D of the resulting path + from the root to vertex W. D is equal to the sum of the link + state cost of the (already calculated) shortest path to + vertex V and the advertised cost of the link between vertices + V and W. If D is: */ + + /* calculate link cost D. */ + if (v->lsa->type == OSPF_ROUTER_LSA) + distance = v->distance + ntohs(l->m[0].metric); + else /* v is not a Router-LSA */ + distance = v->distance; + + /* Is there already vertex W in candidate list? */ + if (w_lsa->stat == LSA_SPF_NOT_EXPLORED) { + /* prepare vertex W. */ + w = ospf_vertex_new(w_lsa); + + /* Calculate nexthop to W. */ + if (ospf_nexthop_calculation(area, v, w, l, distance, + lsa_pos)) + pqueue_enqueue(w, candidate); + else if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Nexthop Calc failed"); + } else if (w_lsa->stat >= 0) { + /* Get the vertex from candidates. */ + w = candidate->array[w_lsa->stat]; + + /* if D is greater than. */ + if (w->distance < distance) { + continue; + } + /* equal to. */ + else if (w->distance == distance) { + /* Found an equal-cost path to W. + * Calculate nexthop of to W from V. */ + ospf_nexthop_calculation(area, v, w, l, + distance, lsa_pos); + } + /* less than. */ + else { + /* Found a lower-cost path to W. + * nexthop_calculation is conditional, if it + * finds + * valid nexthop it will call spf_add_parents, + * which + * will flush the old parents + */ + if (ospf_nexthop_calculation(area, v, w, l, + distance, lsa_pos)) + /* Decrease the key of the node in the + * heap. + * trickle-sort it up towards root, just + * in case this + * node should now be the new root due + * the cost change. + * (next pqueu_{de,en}queue will fully + * re-heap the queue). + */ + trickle_up(w_lsa->stat, candidate); + } + } /* end W is already on the candidate list */ + } /* end loop over the links in V's LSA */ +} - /* (d) Calculate the link state cost D of the resulting path - from the root to vertex W. D is equal to the sum of the link - state cost of the (already calculated) shortest path to - vertex V and the advertised cost of the link between vertices - V and W. If D is: */ - - /* calculate link cost D. */ - if (v->lsa->type == OSPF_ROUTER_LSA) - distance = v->distance + ntohs (l->m[0].metric); - else /* v is not a Router-LSA */ - distance = v->distance; - - /* Is there already vertex W in candidate list? */ - if (w_lsa->stat == LSA_SPF_NOT_EXPLORED) - { - /* prepare vertex W. */ - w = ospf_vertex_new (w_lsa); - - /* Calculate nexthop to W. */ - if (ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos)) - pqueue_enqueue (w, candidate); - else if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Nexthop Calc failed"); +static void ospf_spf_dump(struct vertex *v, int i) +{ + struct listnode *cnode; + struct listnode *nnode; + struct vertex_parent *parent; + + if (v->type == OSPF_VERTEX_ROUTER) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("SPF Result: %d [R] %s", i, + inet_ntoa(v->lsa->id)); + } else { + struct network_lsa *lsa = (struct network_lsa *)v->lsa; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("SPF Result: %d [N] %s/%d", i, + inet_ntoa(v->lsa->id), + ip_masklen(lsa->mask)); } - else if (w_lsa->stat >= 0) - { - /* Get the vertex from candidates. */ - w = candidate->array[w_lsa->stat]; - /* if D is greater than. */ - if (w->distance < distance) - { - continue; - } - /* equal to. */ - else if (w->distance == distance) - { - /* Found an equal-cost path to W. - * Calculate nexthop of to W from V. */ - ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos); - } - /* less than. */ - else - { - /* Found a lower-cost path to W. - * nexthop_calculation is conditional, if it finds - * valid nexthop it will call spf_add_parents, which - * will flush the old parents - */ - if (ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos)) - /* Decrease the key of the node in the heap. - * trickle-sort it up towards root, just in case this - * node should now be the new root due the cost change. - * (next pqueu_{de,en}queue will fully re-heap the queue). - */ - trickle_up (w_lsa->stat, candidate); - } - } /* end W is already on the candidate list */ - } /* end loop over the links in V's LSA */ -} + if (IS_DEBUG_OSPF_EVENT) + for (ALL_LIST_ELEMENTS_RO(v->parents, nnode, parent)) { + zlog_debug(" nexthop %p %s %s", (void *)parent->nexthop, + inet_ntoa(parent->nexthop->router), + parent->nexthop->oi + ? IF_NAME(parent->nexthop->oi) + : "NULL"); + } -static void -ospf_spf_dump (struct vertex *v, int i) -{ - struct listnode *cnode; - struct listnode *nnode; - struct vertex_parent *parent; - - if (v->type == OSPF_VERTEX_ROUTER) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("SPF Result: %d [R] %s", i, inet_ntoa (v->lsa->id)); - } - else - { - struct network_lsa *lsa = (struct network_lsa *) v->lsa; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("SPF Result: %d [N] %s/%d", i, inet_ntoa (v->lsa->id), - ip_masklen (lsa->mask)); - } + i++; - if (IS_DEBUG_OSPF_EVENT) - for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent)) - { - zlog_debug (" nexthop %p %s %s", - (void *)parent->nexthop, - inet_ntoa (parent->nexthop->router), - parent->nexthop->oi ? IF_NAME(parent->nexthop->oi) - : "NULL"); - } - - i++; - - for (ALL_LIST_ELEMENTS_RO (v->children, cnode, v)) - ospf_spf_dump (v, i); + for (ALL_LIST_ELEMENTS_RO(v->children, cnode, v)) + ospf_spf_dump(v, i); } /* Second stage of SPF calculation. */ -static void -ospf_spf_process_stubs (struct ospf_area *area, struct vertex *v, - struct route_table *rt, - int parent_is_root) +static void ospf_spf_process_stubs(struct ospf_area *area, struct vertex *v, + struct route_table *rt, int parent_is_root) { - struct listnode *cnode, *cnnode; - struct vertex *child; + struct listnode *cnode, *cnnode; + struct vertex *child; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_process_stub():processing stubs for area %s", + inet_ntoa(area->area_id)); + if (v->type == OSPF_VERTEX_ROUTER) { + u_char *p; + u_char *lim; + struct router_lsa_link *l; + struct router_lsa *rlsa; + int lsa_pos = 0; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_process_stubs():processing router LSA, id: %s", + inet_ntoa(v->lsa->id)); + rlsa = (struct router_lsa *)v->lsa; + + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_process_stubs(): we have %d links to process", + ntohs(rlsa->links)); + p = ((u_char *)v->lsa) + OSPF_LSA_HEADER_SIZE + 4; + lim = ((u_char *)v->lsa) + ntohs(v->lsa->length); + + while (p < lim) { + l = (struct router_lsa_link *)p; + + p += (OSPF_ROUTER_LSA_LINK_SIZE + + (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE)); + + if (l->m[0].type == LSA_LINK_TYPE_STUB) + ospf_intra_add_stub(rt, l, v, area, + parent_is_root, lsa_pos); + lsa_pos++; + } + } - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_process_stub():processing stubs for area %s", - inet_ntoa (area->area_id)); - if (v->type == OSPF_VERTEX_ROUTER) - { - u_char *p; - u_char *lim; - struct router_lsa_link *l; - struct router_lsa *rlsa; - int lsa_pos = 0; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_process_stubs():processing router LSA, id: %s", - inet_ntoa (v->lsa->id)); - rlsa = (struct router_lsa *) v->lsa; - - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_process_stubs(): we have %d links to process", - ntohs (rlsa->links)); - p = ((u_char *) v->lsa) + OSPF_LSA_HEADER_SIZE + 4; - lim = ((u_char *) v->lsa) + ntohs (v->lsa->length); - - while (p < lim) - { - l = (struct router_lsa_link *) p; + ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, + 1); - p += (OSPF_ROUTER_LSA_LINK_SIZE + - (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE)); + for (ALL_LIST_ELEMENTS(v->children, cnode, cnnode, child)) { + if (CHECK_FLAG(child->flags, OSPF_VERTEX_PROCESSED)) + continue; - if (l->m[0].type == LSA_LINK_TYPE_STUB) - ospf_intra_add_stub (rt, l, v, area, parent_is_root, lsa_pos); - lsa_pos++; - } - } - - ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1, 1); - - for (ALL_LIST_ELEMENTS (v->children, cnode, cnnode, child)) - { - if (CHECK_FLAG (child->flags, OSPF_VERTEX_PROCESSED)) - continue; - - /* the first level of routers connected to the root - * should have 'parent_is_root' set, including those - * connected via a network vertex. - */ - if (area->spf == v) - parent_is_root = 1; - else if (v->type == OSPF_VERTEX_ROUTER) - parent_is_root = 0; - - ospf_spf_process_stubs (area, child, rt, parent_is_root); - - SET_FLAG (child->flags, OSPF_VERTEX_PROCESSED); - } + /* the first level of routers connected to the root + * should have 'parent_is_root' set, including those + * connected via a network vertex. + */ + if (area->spf == v) + parent_is_root = 1; + else if (v->type == OSPF_VERTEX_ROUTER) + parent_is_root = 0; + + ospf_spf_process_stubs(area, child, rt, parent_is_root); + + SET_FLAG(child->flags, OSPF_VERTEX_PROCESSED); + } } -void -ospf_rtrs_free (struct route_table *rtrs) +void ospf_rtrs_free(struct route_table *rtrs) { - struct route_node *rn; - struct list *or_list; - struct ospf_route *or; - struct listnode *node, *nnode; + struct route_node *rn; + struct list *or_list; + struct ospf_route * or ; + struct listnode *node, *nnode; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Route: Router Routing Table free"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Route: Router Routing Table free"); - for (rn = route_top (rtrs); rn; rn = route_next (rn)) - if ((or_list = rn->info) != NULL) - { - for (ALL_LIST_ELEMENTS (or_list, node, nnode, or)) - ospf_route_free (or); + for (rn = route_top(rtrs); rn; rn = route_next(rn)) + if ((or_list = rn->info) != NULL) { + for (ALL_LIST_ELEMENTS(or_list, node, nnode, or)) + ospf_route_free(or); - list_delete (or_list); + list_delete(or_list); - /* Unlock the node. */ - rn->info = NULL; - route_unlock_node (rn); - } - route_table_finish (rtrs); + /* Unlock the node. */ + rn->info = NULL; + route_unlock_node(rn); + } + route_table_finish(rtrs); } #if 0 @@ -1149,318 +1157,309 @@ ospf_rtrs_print (struct route_table *rtrs) #endif /* Calculating the shortest-path tree for an area. */ -static void -ospf_spf_calculate (struct ospf_area *area, struct route_table *new_table, - struct route_table *new_rtrs) +static void ospf_spf_calculate(struct ospf_area *area, + struct route_table *new_table, + struct route_table *new_rtrs) { - struct pqueue *candidate; - struct vertex *v; - - if (IS_DEBUG_OSPF_EVENT) - { - zlog_debug ("ospf_spf_calculate: Start"); - zlog_debug ("ospf_spf_calculate: running Dijkstra for area %s", - inet_ntoa (area->area_id)); - } - - /* Check router-lsa-self. If self-router-lsa is not yet allocated, - return this area's calculation. */ - if (!area->router_lsa_self) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_spf_calculate: " - "Skip area %s's calculation due to empty router_lsa_self", - inet_ntoa (area->area_id)); - return; - } - - /* RFC2328 16.1. (1). */ - /* Initialize the algorithm's data structures. */ - - /* This function scans all the LSA database and set the stat field to - * LSA_SPF_NOT_EXPLORED. */ - ospf_lsdb_clean_stat (area->lsdb); - /* Create a new heap for the candidates. */ - candidate = pqueue_create(); - candidate->cmp = cmp; - candidate->update = update_stat; - - /* Initialize the shortest-path tree to only the root (which is the - router doing the calculation). */ - ospf_spf_init (area); - v = area->spf; - /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the - * spanning tree. */ - *(v->stat) = LSA_SPF_IN_SPFTREE; - - /* Set Area A's TransitCapability to FALSE. */ - area->transit = OSPF_TRANSIT_FALSE; - area->shortcut_capability = 1; - - for (;;) - { - /* RFC2328 16.1. (2). */ - ospf_spf_next (v, area, candidate); - - /* RFC2328 16.1. (3). */ - /* If at this step the candidate list is empty, the shortest- - path tree (of transit vertices) has been completely built and - this stage of the procedure terminates. */ - if (candidate->size == 0) - break; - - /* Otherwise, choose the vertex belonging to the candidate list - that is closest to the root, and add it to the shortest-path - tree (removing it from the candidate list in the - process). */ - /* Extract from the candidates the node with the lower key. */ - v = (struct vertex *) pqueue_dequeue (candidate); - /* Update stat field in vertex. */ - *(v->stat) = LSA_SPF_IN_SPFTREE; - - ospf_vertex_add_parent (v); - - /* RFC2328 16.1. (4). */ - if (v->type == OSPF_VERTEX_ROUTER) - ospf_intra_add_router (new_rtrs, v, area); - else - ospf_intra_add_transit (new_table, v, area); - - /* RFC2328 16.1. (5). */ - /* Iterate the algorithm by returning to Step 2. */ - - } /* end loop until no more candidate vertices */ + struct pqueue *candidate; + struct vertex *v; - if (IS_DEBUG_OSPF_EVENT) - { - ospf_spf_dump (area->spf, 0); - ospf_route_table_dump (new_table); - } + if (IS_DEBUG_OSPF_EVENT) { + zlog_debug("ospf_spf_calculate: Start"); + zlog_debug("ospf_spf_calculate: running Dijkstra for area %s", + inet_ntoa(area->area_id)); + } - /* Second stage of SPF calculation procedure's */ - ospf_spf_process_stubs (area, area->spf, new_table, 0); + /* Check router-lsa-self. If self-router-lsa is not yet allocated, + return this area's calculation. */ + if (!area->router_lsa_self) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_spf_calculate: " + "Skip area %s's calculation due to empty router_lsa_self", + inet_ntoa(area->area_id)); + return; + } - /* Free candidate queue. */ - pqueue_delete (candidate); + /* RFC2328 16.1. (1). */ + /* Initialize the algorithm's data structures. */ + + /* This function scans all the LSA database and set the stat field to + * LSA_SPF_NOT_EXPLORED. */ + ospf_lsdb_clean_stat(area->lsdb); + /* Create a new heap for the candidates. */ + candidate = pqueue_create(); + candidate->cmp = cmp; + candidate->update = update_stat; + + /* Initialize the shortest-path tree to only the root (which is the + router doing the calculation). */ + ospf_spf_init(area); + v = area->spf; + /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of + * the + * spanning tree. */ + *(v->stat) = LSA_SPF_IN_SPFTREE; + + /* Set Area A's TransitCapability to FALSE. */ + area->transit = OSPF_TRANSIT_FALSE; + area->shortcut_capability = 1; + + for (;;) { + /* RFC2328 16.1. (2). */ + ospf_spf_next(v, area, candidate); + + /* RFC2328 16.1. (3). */ + /* If at this step the candidate list is empty, the shortest- + path tree (of transit vertices) has been completely built and + this stage of the procedure terminates. */ + if (candidate->size == 0) + break; + + /* Otherwise, choose the vertex belonging to the candidate list + that is closest to the root, and add it to the shortest-path + tree (removing it from the candidate list in the + process). */ + /* Extract from the candidates the node with the lower key. */ + v = (struct vertex *)pqueue_dequeue(candidate); + /* Update stat field in vertex. */ + *(v->stat) = LSA_SPF_IN_SPFTREE; + + ospf_vertex_add_parent(v); + + /* RFC2328 16.1. (4). */ + if (v->type == OSPF_VERTEX_ROUTER) + ospf_intra_add_router(new_rtrs, v, area); + else + ospf_intra_add_transit(new_table, v, area); + + /* RFC2328 16.1. (5). */ + /* Iterate the algorithm by returning to Step 2. */ + + } /* end loop until no more candidate vertices */ + + if (IS_DEBUG_OSPF_EVENT) { + ospf_spf_dump(area->spf, 0); + ospf_route_table_dump(new_table); + } - ospf_vertex_dump (__func__, area->spf, 0, 1); - /* Free nexthop information, canonical versions of which are attached - * the first level of router vertices attached to the root vertex, see - * ospf_nexthop_calculation. - */ - ospf_canonical_nexthops_free (area->spf); + /* Second stage of SPF calculation procedure's */ + ospf_spf_process_stubs(area, area->spf, new_table, 0); - /* Increment SPF Calculation Counter. */ - area->spf_calculation++; + /* Free candidate queue. */ + pqueue_delete(candidate); - monotime(&area->ospf->ts_spf); - area->ts_spf = area->ospf->ts_spf; + ospf_vertex_dump(__func__, area->spf, 0, 1); + /* Free nexthop information, canonical versions of which are attached + * the first level of router vertices attached to the root vertex, see + * ospf_nexthop_calculation. + */ + ospf_canonical_nexthops_free(area->spf); - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_spf_calculate: Stop. %zd vertices", - mtype_stats_alloc(MTYPE_OSPF_VERTEX)); + /* Increment SPF Calculation Counter. */ + area->spf_calculation++; + + monotime(&area->ospf->ts_spf); + area->ts_spf = area->ospf->ts_spf; - /* Free SPF vertices, but not the list. List has ospf_vertex_free - * as deconstructor. - */ - list_delete_all_node (&vertex_list); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("ospf_spf_calculate: Stop. %zd vertices", + mtype_stats_alloc(MTYPE_OSPF_VERTEX)); + + /* Free SPF vertices, but not the list. List has ospf_vertex_free + * as deconstructor. + */ + list_delete_all_node(&vertex_list); } /* Timer for SPF calculation. */ -static int -ospf_spf_calculate_timer (struct thread *thread) +static int ospf_spf_calculate_timer(struct thread *thread) { - struct ospf *ospf = THREAD_ARG (thread); - struct route_table *new_table, *new_rtrs; - struct ospf_area *area; - struct listnode *node, *nnode; - struct timeval start_time, spf_start_time; - int areas_processed = 0; - unsigned long ia_time, prune_time, rt_time; - unsigned long abr_time, total_spf_time, spf_time; - char rbuf[32]; /* reason_buf */ - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("SPF: Timer (SPF calculation expire)"); - - ospf->t_spf_calc = NULL; - - monotime(&spf_start_time); - /* Allocate new table tree. */ - new_table = route_table_init (); - new_rtrs = route_table_init (); - - ospf_vl_unapprove (ospf); - - /* Calculate SPF for each area. */ - for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) - { - /* Do backbone last, so as to first discover intra-area paths - * for any back-bone virtual-links - */ - if (ospf->backbone && ospf->backbone == area) - continue; - - ospf_spf_calculate (area, new_table, new_rtrs); - areas_processed++; - } - - /* SPF for backbone, if required */ - if (ospf->backbone) - { - ospf_spf_calculate (ospf->backbone, new_table, new_rtrs); - areas_processed++; - } - - spf_time = monotime_since(&spf_start_time, NULL); - - ospf_vl_shut_unapproved (ospf); - - monotime(&start_time); - ospf_ia_routing (ospf, new_table, new_rtrs); - ia_time = monotime_since(&start_time, NULL); - - monotime(&start_time); - ospf_prune_unreachable_networks (new_table); - ospf_prune_unreachable_routers (new_rtrs); - prune_time = monotime_since(&start_time, NULL); - - /* AS-external-LSA calculation should not be performed here. */ - - /* If new Router Route is installed, - then schedule re-calculate External routes. */ - if (1) - ospf_ase_calculate_schedule (ospf); - - ospf_ase_calculate_timer_add (ospf); - - /* Update routing table. */ - monotime(&start_time); - ospf_route_install (ospf, new_table); - rt_time = monotime_since(&start_time, NULL); - - /* Update ABR/ASBR routing table */ - if (ospf->old_rtrs) - { - /* old_rtrs's node holds linked list of ospf_route. --kunihiro. */ - /* ospf_route_delete (ospf->old_rtrs); */ - ospf_rtrs_free (ospf->old_rtrs); - } - - ospf->old_rtrs = ospf->new_rtrs; - ospf->new_rtrs = new_rtrs; - - monotime(&start_time); - if (IS_OSPF_ABR (ospf)) - ospf_abr_task (ospf); - abr_time = monotime_since(&start_time, NULL); - - total_spf_time = monotime_since(&spf_start_time, &ospf->ts_spf_duration); - - rbuf[0] = '\0'; - if (spf_reason_flags) - { - if (spf_reason_flags & SPF_FLAG_ROUTER_LSA_INSTALL) - strncat (rbuf, "R, ", sizeof(rbuf) - strlen(rbuf) - 1); - if (spf_reason_flags & SPF_FLAG_NETWORK_LSA_INSTALL) - strncat (rbuf, "N, ", sizeof(rbuf) - strlen(rbuf) - 1); - if (spf_reason_flags & SPF_FLAG_SUMMARY_LSA_INSTALL) - strncat (rbuf, "S, ", sizeof(rbuf) - strlen(rbuf) - 1); - if (spf_reason_flags & SPF_FLAG_ASBR_SUMMARY_LSA_INSTALL) - strncat (rbuf, "AS, ", sizeof(rbuf) - strlen(rbuf) - 1); - if (spf_reason_flags & SPF_FLAG_ABR_STATUS_CHANGE) - strncat (rbuf, "ABR, ", sizeof(rbuf) - strlen(rbuf) - 1); - if (spf_reason_flags & SPF_FLAG_ASBR_STATUS_CHANGE) - strncat (rbuf, "ASBR, ", sizeof(rbuf) - strlen(rbuf) - 1); - if (spf_reason_flags & SPF_FLAG_MAXAGE) - strncat (rbuf, "M, ", sizeof(rbuf) - strlen(rbuf) - 1); - - size_t rbuflen = strlen(rbuf); - if (rbuflen >= 2) - rbuf[rbuflen - 2] = '\0'; /* skip the last ", " */ - else - rbuf[0] = '\0'; - } + struct ospf *ospf = THREAD_ARG(thread); + struct route_table *new_table, *new_rtrs; + struct ospf_area *area; + struct listnode *node, *nnode; + struct timeval start_time, spf_start_time; + int areas_processed = 0; + unsigned long ia_time, prune_time, rt_time; + unsigned long abr_time, total_spf_time, spf_time; + char rbuf[32]; /* reason_buf */ + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("SPF: Timer (SPF calculation expire)"); + + ospf->t_spf_calc = NULL; + + monotime(&spf_start_time); + /* Allocate new table tree. */ + new_table = route_table_init(); + new_rtrs = route_table_init(); + + ospf_vl_unapprove(ospf); + + /* Calculate SPF for each area. */ + for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { + /* Do backbone last, so as to first discover intra-area paths + * for any back-bone virtual-links + */ + if (ospf->backbone && ospf->backbone == area) + continue; - if (IS_DEBUG_OSPF_EVENT) - { - zlog_info ("SPF Processing Time(usecs): %ld", total_spf_time); - zlog_info ("\t SPF Time: %ld", spf_time); - zlog_info ("\t InterArea: %ld", ia_time); - zlog_info ("\t Prune: %ld", prune_time); - zlog_info ("\tRouteInstall: %ld", rt_time); - if (IS_OSPF_ABR (ospf)) - zlog_info ("\t ABR: %ld (%d areas)", - abr_time, areas_processed); - zlog_info ("Reason(s) for SPF: %s", rbuf); - } - - ospf_clear_spf_reason_flags (); - - return 0; + ospf_spf_calculate(area, new_table, new_rtrs); + areas_processed++; + } + + /* SPF for backbone, if required */ + if (ospf->backbone) { + ospf_spf_calculate(ospf->backbone, new_table, new_rtrs); + areas_processed++; + } + + spf_time = monotime_since(&spf_start_time, NULL); + + ospf_vl_shut_unapproved(ospf); + + monotime(&start_time); + ospf_ia_routing(ospf, new_table, new_rtrs); + ia_time = monotime_since(&start_time, NULL); + + monotime(&start_time); + ospf_prune_unreachable_networks(new_table); + ospf_prune_unreachable_routers(new_rtrs); + prune_time = monotime_since(&start_time, NULL); + + /* AS-external-LSA calculation should not be performed here. */ + + /* If new Router Route is installed, + then schedule re-calculate External routes. */ + if (1) + ospf_ase_calculate_schedule(ospf); + + ospf_ase_calculate_timer_add(ospf); + + /* Update routing table. */ + monotime(&start_time); + ospf_route_install(ospf, new_table); + rt_time = monotime_since(&start_time, NULL); + + /* Update ABR/ASBR routing table */ + if (ospf->old_rtrs) { + /* old_rtrs's node holds linked list of ospf_route. --kunihiro. + */ + /* ospf_route_delete (ospf->old_rtrs); */ + ospf_rtrs_free(ospf->old_rtrs); + } + + ospf->old_rtrs = ospf->new_rtrs; + ospf->new_rtrs = new_rtrs; + + monotime(&start_time); + if (IS_OSPF_ABR(ospf)) + ospf_abr_task(ospf); + abr_time = monotime_since(&start_time, NULL); + + total_spf_time = + monotime_since(&spf_start_time, &ospf->ts_spf_duration); + + rbuf[0] = '\0'; + if (spf_reason_flags) { + if (spf_reason_flags & SPF_FLAG_ROUTER_LSA_INSTALL) + strncat(rbuf, "R, ", sizeof(rbuf) - strlen(rbuf) - 1); + if (spf_reason_flags & SPF_FLAG_NETWORK_LSA_INSTALL) + strncat(rbuf, "N, ", sizeof(rbuf) - strlen(rbuf) - 1); + if (spf_reason_flags & SPF_FLAG_SUMMARY_LSA_INSTALL) + strncat(rbuf, "S, ", sizeof(rbuf) - strlen(rbuf) - 1); + if (spf_reason_flags & SPF_FLAG_ASBR_SUMMARY_LSA_INSTALL) + strncat(rbuf, "AS, ", sizeof(rbuf) - strlen(rbuf) - 1); + if (spf_reason_flags & SPF_FLAG_ABR_STATUS_CHANGE) + strncat(rbuf, "ABR, ", sizeof(rbuf) - strlen(rbuf) - 1); + if (spf_reason_flags & SPF_FLAG_ASBR_STATUS_CHANGE) + strncat(rbuf, "ASBR, ", + sizeof(rbuf) - strlen(rbuf) - 1); + if (spf_reason_flags & SPF_FLAG_MAXAGE) + strncat(rbuf, "M, ", sizeof(rbuf) - strlen(rbuf) - 1); + + size_t rbuflen = strlen(rbuf); + if (rbuflen >= 2) + rbuf[rbuflen - 2] = '\0'; /* skip the last ", " */ + else + rbuf[0] = '\0'; + } + + if (IS_DEBUG_OSPF_EVENT) { + zlog_info("SPF Processing Time(usecs): %ld", total_spf_time); + zlog_info("\t SPF Time: %ld", spf_time); + zlog_info("\t InterArea: %ld", ia_time); + zlog_info("\t Prune: %ld", prune_time); + zlog_info("\tRouteInstall: %ld", rt_time); + if (IS_OSPF_ABR(ospf)) + zlog_info("\t ABR: %ld (%d areas)", abr_time, + areas_processed); + zlog_info("Reason(s) for SPF: %s", rbuf); + } + + ospf_clear_spf_reason_flags(); + + return 0; } /* Add schedule for SPF calculation. To avoid frequenst SPF calc, we set timer for SPF calc. */ -void -ospf_spf_calculate_schedule (struct ospf *ospf, ospf_spf_reason_t reason) +void ospf_spf_calculate_schedule(struct ospf *ospf, ospf_spf_reason_t reason) { - unsigned long delay, elapsed, ht; + unsigned long delay, elapsed, ht; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("SPF: calculation timer scheduled"); - - /* OSPF instance does not exist. */ - if (ospf == NULL) - return; - - ospf_spf_set_reason (reason); - - /* SPF calculation timer is already scheduled. */ - if (ospf->t_spf_calc) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("SPF: calculation timer is already scheduled: %p", - (void *)ospf->t_spf_calc); - return; - } - - elapsed = monotime_since (&ospf->ts_spf, NULL) / 1000; - - ht = ospf->spf_holdtime * ospf->spf_hold_multiplier; - - if (ht > ospf->spf_max_holdtime) - ht = ospf->spf_max_holdtime; - - /* Get SPF calculation delay time. */ - if (elapsed < ht) - { - /* Got an event within the hold time of last SPF. We need to - * increase the hold_multiplier, if it's not already at/past - * maximum value, and wasn't already increased.. - */ - if (ht < ospf->spf_max_holdtime) - ospf->spf_hold_multiplier++; - - /* always honour the SPF initial delay */ - if ( (ht - elapsed) < ospf->spf_delay) - delay = ospf->spf_delay; - else - delay = ht - elapsed; - } - else - { - /* Event is past required hold-time of last SPF */ - delay = ospf->spf_delay; - ospf->spf_hold_multiplier = 1; - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("SPF: calculation timer delay = %ld", delay); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("SPF: calculation timer scheduled"); + + /* OSPF instance does not exist. */ + if (ospf == NULL) + return; + + ospf_spf_set_reason(reason); + + /* SPF calculation timer is already scheduled. */ + if (ospf->t_spf_calc) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "SPF: calculation timer is already scheduled: %p", + (void *)ospf->t_spf_calc); + return; + } + + elapsed = monotime_since(&ospf->ts_spf, NULL) / 1000; + + ht = ospf->spf_holdtime * ospf->spf_hold_multiplier; + + if (ht > ospf->spf_max_holdtime) + ht = ospf->spf_max_holdtime; + + /* Get SPF calculation delay time. */ + if (elapsed < ht) { + /* Got an event within the hold time of last SPF. We need to + * increase the hold_multiplier, if it's not already at/past + * maximum value, and wasn't already increased.. + */ + if (ht < ospf->spf_max_holdtime) + ospf->spf_hold_multiplier++; + + /* always honour the SPF initial delay */ + if ((ht - elapsed) < ospf->spf_delay) + delay = ospf->spf_delay; + else + delay = ht - elapsed; + } else { + /* Event is past required hold-time of last SPF */ + delay = ospf->spf_delay; + ospf->spf_hold_multiplier = 1; + } + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("SPF: calculation timer delay = %ld", delay); - zlog_info ("SPF: Scheduled in %ld msec", delay); + zlog_info("SPF: Scheduled in %ld msec", delay); - ospf->t_spf_calc = NULL; - thread_add_timer_msec(master, ospf_spf_calculate_timer, ospf, delay, - &ospf->t_spf_calc); + ospf->t_spf_calc = NULL; + thread_add_timer_msec(master, ospf_spf_calculate_timer, ospf, delay, + &ospf->t_spf_calc); } diff --git a/ospfd/ospf_spf.h b/ospfd/ospf_spf.h index 349f461c9..e23f5941f 100644 --- a/ospfd/ospf_spf.h +++ b/ospfd/ospf_spf.h @@ -32,46 +32,44 @@ /* The "root" is the node running the SPF calculation */ /* A router or network in an area */ -struct vertex -{ - u_char flags; - u_char type; /* copied from LSA header */ - struct in_addr id; /* copied from LSA header */ - struct lsa_header *lsa; /* Router or Network LSA */ - int *stat; /* Link to LSA status. */ - u_int32_t distance; /* from root to this vertex */ - struct list *parents; /* list of parents in SPF tree */ - struct list *children; /* list of children in SPF tree*/ +struct vertex { + u_char flags; + u_char type; /* copied from LSA header */ + struct in_addr id; /* copied from LSA header */ + struct lsa_header *lsa; /* Router or Network LSA */ + int *stat; /* Link to LSA status. */ + u_int32_t distance; /* from root to this vertex */ + struct list *parents; /* list of parents in SPF tree */ + struct list *children; /* list of children in SPF tree*/ }; /* A nexthop taken on the root node to get to this (parent) vertex */ -struct vertex_nexthop -{ - struct ospf_interface *oi; /* output intf on root node */ - struct in_addr router; /* router address to send to */ +struct vertex_nexthop { + struct ospf_interface *oi; /* output intf on root node */ + struct in_addr router; /* router address to send to */ }; -struct vertex_parent -{ - struct vertex_nexthop *nexthop; /* link to nexthop info for this parent */ - struct vertex *parent; /* parent vertex */ - int backlink; /* index back to parent for router-lsa's */ +struct vertex_parent { + struct vertex_nexthop + *nexthop; /* link to nexthop info for this parent */ + struct vertex *parent; /* parent vertex */ + int backlink; /* index back to parent for router-lsa's */ }; /* What triggered the SPF ? */ typedef enum { - SPF_FLAG_ROUTER_LSA_INSTALL = 1, - SPF_FLAG_NETWORK_LSA_INSTALL, - SPF_FLAG_SUMMARY_LSA_INSTALL, - SPF_FLAG_ASBR_SUMMARY_LSA_INSTALL, - SPF_FLAG_MAXAGE, - SPF_FLAG_ABR_STATUS_CHANGE, - SPF_FLAG_ASBR_STATUS_CHANGE, - SPF_FLAG_CONFIG_CHANGE, + SPF_FLAG_ROUTER_LSA_INSTALL = 1, + SPF_FLAG_NETWORK_LSA_INSTALL, + SPF_FLAG_SUMMARY_LSA_INSTALL, + SPF_FLAG_ASBR_SUMMARY_LSA_INSTALL, + SPF_FLAG_MAXAGE, + SPF_FLAG_ABR_STATUS_CHANGE, + SPF_FLAG_ASBR_STATUS_CHANGE, + SPF_FLAG_CONFIG_CHANGE, } ospf_spf_reason_t; -extern void ospf_spf_calculate_schedule (struct ospf *, ospf_spf_reason_t); -extern void ospf_rtrs_free (struct route_table *); +extern void ospf_spf_calculate_schedule(struct ospf *, ospf_spf_reason_t); +extern void ospf_rtrs_free(struct route_table *); /* void ospf_spf_calculate_timer_add (); */ #endif /* _QUAGGA_OSPF_SPF_H */ diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index c34d97ff2..4ca6578ea 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -41,7 +41,7 @@ #include "log.h" #include "thread.h" #include "hash.h" -#include "sockunion.h" /* for inet_aton() */ +#include "sockunion.h" /* for inet_aton() */ #include "network.h" #include "ospfd/ospfd.h" @@ -68,1596 +68,1566 @@ */ struct ospf_mpls_te OspfMplsTE; -const char *mode2text[] = { "Disable", "AS", "Area", "Emulate" }; +const char *mode2text[] = {"Disable", "AS", "Area", "Emulate"}; -enum oifstate -{ - OI_ANY, OI_DOWN, OI_UP -}; +enum oifstate { OI_ANY, OI_DOWN, OI_UP }; /*------------------------------------------------------------------------* * Followings are initialize/terminate functions for MPLS-TE handling. *------------------------------------------------------------------------*/ -static int ospf_mpls_te_new_if (struct interface *ifp); -static int ospf_mpls_te_del_if (struct interface *ifp); -static void ospf_mpls_te_ism_change (struct ospf_interface *oi, - int old_status); -static void ospf_mpls_te_nsm_change (struct ospf_neighbor *nbr, int old_status); -static void ospf_mpls_te_config_write_router (struct vty *vty); -static void ospf_mpls_te_show_info (struct vty *vty, struct ospf_lsa *lsa); -static int ospf_mpls_te_lsa_originate_area (void *arg); -static int ospf_mpls_te_lsa_originate_as (void *arg); -static struct ospf_lsa *ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa); - -static void del_mpls_te_link (void *val); -static void ospf_mpls_te_register_vty (void); - -int -ospf_mpls_te_init (void) -{ - int rc; - - rc = ospf_register_opaque_functab ( - OSPF_OPAQUE_AREA_LSA, - OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, - ospf_mpls_te_new_if, - ospf_mpls_te_del_if, - ospf_mpls_te_ism_change, - ospf_mpls_te_nsm_change, +static int ospf_mpls_te_new_if(struct interface *ifp); +static int ospf_mpls_te_del_if(struct interface *ifp); +static void ospf_mpls_te_ism_change(struct ospf_interface *oi, int old_status); +static void ospf_mpls_te_nsm_change(struct ospf_neighbor *nbr, int old_status); +static void ospf_mpls_te_config_write_router(struct vty *vty); +static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa); +static int ospf_mpls_te_lsa_originate_area(void *arg); +static int ospf_mpls_te_lsa_originate_as(void *arg); +static struct ospf_lsa *ospf_mpls_te_lsa_refresh(struct ospf_lsa *lsa); + +static void del_mpls_te_link(void *val); +static void ospf_mpls_te_register_vty(void); + +int ospf_mpls_te_init(void) +{ + int rc; + + rc = ospf_register_opaque_functab( + OSPF_OPAQUE_AREA_LSA, OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, + ospf_mpls_te_new_if, ospf_mpls_te_del_if, + ospf_mpls_te_ism_change, ospf_mpls_te_nsm_change, ospf_mpls_te_config_write_router, - NULL,/*ospf_mpls_te_config_write_if */ - NULL,/* ospf_mpls_te_config_write_debug */ - ospf_mpls_te_show_info, - ospf_mpls_te_lsa_originate_area, - ospf_mpls_te_lsa_refresh, - NULL,/* ospf_mpls_te_new_lsa_hook */ + NULL, /*ospf_mpls_te_config_write_if */ + NULL, /* ospf_mpls_te_config_write_debug */ + ospf_mpls_te_show_info, ospf_mpls_te_lsa_originate_area, + ospf_mpls_te_lsa_refresh, NULL, /* ospf_mpls_te_new_lsa_hook */ NULL /* ospf_mpls_te_del_lsa_hook */); - if (rc != 0) - { - zlog_warn ("ospf_mpls_te_init: Failed to register Traffic Engineering functions"); - goto out; - } + if (rc != 0) { + zlog_warn( + "ospf_mpls_te_init: Failed to register Traffic Engineering functions"); + goto out; + } - memset (&OspfMplsTE, 0, sizeof (struct ospf_mpls_te)); - OspfMplsTE.status = disabled; - OspfMplsTE.inter_as = Disable; - OspfMplsTE.iflist = list_new (); - OspfMplsTE.iflist->del = del_mpls_te_link; + memset(&OspfMplsTE, 0, sizeof(struct ospf_mpls_te)); + OspfMplsTE.status = disabled; + OspfMplsTE.inter_as = Disable; + OspfMplsTE.iflist = list_new(); + OspfMplsTE.iflist->del = del_mpls_te_link; - ospf_mpls_te_register_vty (); + ospf_mpls_te_register_vty(); out: - return rc; + return rc; } /* Additional register for RFC5392 support */ -static int -ospf_mpls_te_register (enum inter_as_mode mode) +static int ospf_mpls_te_register(enum inter_as_mode mode) { - int rc; - u_int8_t scope; + int rc; + u_int8_t scope; - if (OspfMplsTE.inter_as != Disable) - return 0; + if (OspfMplsTE.inter_as != Disable) + return 0; - if (mode == AS) - scope = OSPF_OPAQUE_AS_LSA; - else - scope = OSPF_OPAQUE_AREA_LSA; + if (mode == AS) + scope = OSPF_OPAQUE_AS_LSA; + else + scope = OSPF_OPAQUE_AREA_LSA; - rc = ospf_register_opaque_functab (scope, - OPAQUE_TYPE_INTER_AS_LSA, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - ospf_mpls_te_show_info, - ospf_mpls_te_lsa_originate_as, - ospf_mpls_te_lsa_refresh, NULL, NULL); + rc = ospf_register_opaque_functab(scope, OPAQUE_TYPE_INTER_AS_LSA, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + ospf_mpls_te_show_info, + ospf_mpls_te_lsa_originate_as, + ospf_mpls_te_lsa_refresh, NULL, NULL); - if (rc != 0) - { - zlog_warn ("ospf_router_info_init: Failed to register Inter-AS functions"); - return rc; - } + if (rc != 0) { + zlog_warn( + "ospf_router_info_init: Failed to register Inter-AS functions"); + return rc; + } - return 0; + return 0; } -static int -ospf_mpls_te_unregister () +static int ospf_mpls_te_unregister() { - u_int8_t scope; - - if (OspfMplsTE.inter_as == Disable) - return 0; + u_int8_t scope; - if (OspfMplsTE.inter_as == AS) - scope = OSPF_OPAQUE_AS_LSA; - else - scope = OSPF_OPAQUE_AREA_LSA; + if (OspfMplsTE.inter_as == Disable) + return 0; - ospf_delete_opaque_functab (scope, OPAQUE_TYPE_INTER_AS_LSA); + if (OspfMplsTE.inter_as == AS) + scope = OSPF_OPAQUE_AS_LSA; + else + scope = OSPF_OPAQUE_AREA_LSA; - return 0; + ospf_delete_opaque_functab(scope, OPAQUE_TYPE_INTER_AS_LSA); + return 0; } -void -ospf_mpls_te_term (void) +void ospf_mpls_te_term(void) { - list_delete (OspfMplsTE.iflist); - OspfMplsTE.iflist = NULL; + list_delete(OspfMplsTE.iflist); + OspfMplsTE.iflist = NULL; - ospf_delete_opaque_functab (OSPF_OPAQUE_AREA_LSA, - OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA); - OspfMplsTE.status = disabled; + ospf_delete_opaque_functab(OSPF_OPAQUE_AREA_LSA, + OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA); + OspfMplsTE.status = disabled; - ospf_mpls_te_unregister (); - OspfMplsTE.inter_as = Disable; + ospf_mpls_te_unregister(); + OspfMplsTE.inter_as = Disable; - return; + return; } /*------------------------------------------------------------------------* * Followings are control functions for MPLS-TE parameters management. *------------------------------------------------------------------------*/ -static void -del_mpls_te_link (void *val) +static void del_mpls_te_link(void *val) { - XFREE (MTYPE_OSPF_MPLS_TE, val); - return; + XFREE(MTYPE_OSPF_MPLS_TE, val); + return; } -u_int32_t -get_mpls_te_instance_value (void) +u_int32_t get_mpls_te_instance_value(void) { - static u_int32_t seqno = 0; + static u_int32_t seqno = 0; - if (seqno < MAX_LEGAL_TE_INSTANCE_NUM ) - seqno += 1; - else - seqno = 1; /* Avoid zero. */ + if (seqno < MAX_LEGAL_TE_INSTANCE_NUM) + seqno += 1; + else + seqno = 1; /* Avoid zero. */ - return seqno; + return seqno; } -static struct ospf_interface * -lookup_oi_by_ifp (struct interface *ifp, - struct ospf_area *area, enum oifstate oifstate) +static struct ospf_interface *lookup_oi_by_ifp(struct interface *ifp, + struct ospf_area *area, + enum oifstate oifstate) { - struct ospf_interface *oi = NULL; - struct route_node *rn; + struct ospf_interface *oi = NULL; + struct route_node *rn; - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - { - if ((oi = rn->info) == NULL) - continue; + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + if ((oi = rn->info) == NULL) + continue; - switch (oifstate) - { - case OI_ANY: - break; - case OI_DOWN: - if (ospf_if_is_enable (oi)) - continue; - break; - case OI_UP: - if (! ospf_if_is_enable (oi)) - continue; - break; - default: - zlog_warn ("lookup_oi_by_ifp: Unknown oifstate: %x", oifstate); - goto out; - } + switch (oifstate) { + case OI_ANY: + break; + case OI_DOWN: + if (ospf_if_is_enable(oi)) + continue; + break; + case OI_UP: + if (!ospf_if_is_enable(oi)) + continue; + break; + default: + zlog_warn("lookup_oi_by_ifp: Unknown oifstate: %x", + oifstate); + goto out; + } - if (area == NULL || oi->area == area) - return oi; - } + if (area == NULL || oi->area == area) + return oi; + } out: - return NULL; + return NULL; } -static struct mpls_te_link * -lookup_linkparams_by_ifp (struct interface *ifp) +static struct mpls_te_link *lookup_linkparams_by_ifp(struct interface *ifp) { - struct listnode *node, *nnode; - struct mpls_te_link *lp; + struct listnode *node, *nnode; + struct mpls_te_link *lp; - for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp)) - if (lp->ifp == ifp) - return lp; + for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) + if (lp->ifp == ifp) + return lp; - return NULL; + return NULL; } -static struct mpls_te_link * -lookup_linkparams_by_instance (struct ospf_lsa *lsa) +static struct mpls_te_link *lookup_linkparams_by_instance(struct ospf_lsa *lsa) { - struct listnode *node; - struct mpls_te_link *lp; - unsigned int key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)); + struct listnode *node; + struct mpls_te_link *lp; + unsigned int key = GET_OPAQUE_ID(ntohl(lsa->data->id.s_addr)); - for (ALL_LIST_ELEMENTS_RO (OspfMplsTE.iflist, node, lp)) - if (lp->instance == key) - return lp; + for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node, lp)) + if (lp->instance == key) + return lp; - zlog_warn ("lookup_linkparams_by_instance: Entry not found: key(%x)", key); - return NULL; + zlog_warn("lookup_linkparams_by_instance: Entry not found: key(%x)", + key); + return NULL; } -static void -ospf_mpls_te_foreach_area (void (*func) - (struct mpls_te_link * lp, opcode_t sched_opcode), - opcode_t sched_opcode) +static void ospf_mpls_te_foreach_area(void (*func)(struct mpls_te_link *lp, + opcode_t sched_opcode), + opcode_t sched_opcode) { - struct listnode *node, *nnode; - struct listnode *node2; - struct mpls_te_link *lp; - struct ospf_area *area; + struct listnode *node, *nnode; + struct listnode *node2; + struct mpls_te_link *lp; + struct ospf_area *area; - for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp)) - { - /* Skip Inter-AS TEv2 Links */ - if (IS_INTER_AS (lp->type)) - continue; - if ((area = lp->area) == NULL) - continue; - if CHECK_FLAG (lp->flags, LPFLG_LOOKUP_DONE) continue; + for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) { + /* Skip Inter-AS TEv2 Links */ + if (IS_INTER_AS(lp->type)) + continue; + if ((area = lp->area) == NULL) + continue; + if + CHECK_FLAG(lp->flags, LPFLG_LOOKUP_DONE) continue; - if (func != NULL) - (* func)(lp, sched_opcode); + if (func != NULL) + (*func)(lp, sched_opcode); - for (node2 = listnextnode (node); node2; node2 = listnextnode (node2)) - if ((lp = listgetdata (node2)) != NULL) - if (lp->area != NULL) - if (IPV4_ADDR_SAME (&lp->area->area_id, &area->area_id)) - SET_FLAG (lp->flags, LPFLG_LOOKUP_DONE); - } + for (node2 = listnextnode(node); node2; + node2 = listnextnode(node2)) + if ((lp = listgetdata(node2)) != NULL) + if (lp->area != NULL) + if (IPV4_ADDR_SAME(&lp->area->area_id, + &area->area_id)) + SET_FLAG(lp->flags, + LPFLG_LOOKUP_DONE); + } - for (ALL_LIST_ELEMENTS_RO (OspfMplsTE.iflist, node, lp)) - if (lp->area != NULL) - UNSET_FLAG (lp->flags, LPFLG_LOOKUP_DONE); + for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node, lp)) + if (lp->area != NULL) + UNSET_FLAG(lp->flags, LPFLG_LOOKUP_DONE); - return; + return; } -static void -set_mpls_te_router_addr (struct in_addr ipv4) +static void set_mpls_te_router_addr(struct in_addr ipv4) { - OspfMplsTE.router_addr.header.type = htons (TE_TLV_ROUTER_ADDR); - OspfMplsTE.router_addr.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); - OspfMplsTE.router_addr.value = ipv4; - return; + OspfMplsTE.router_addr.header.type = htons(TE_TLV_ROUTER_ADDR); + OspfMplsTE.router_addr.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE); + OspfMplsTE.router_addr.value = ipv4; + return; } -static void -set_linkparams_link_header (struct mpls_te_link *lp) +static void set_linkparams_link_header(struct mpls_te_link *lp) { - u_int16_t length = 0; + u_int16_t length = 0; - /* TE_LINK_SUBTLV_LINK_TYPE */ - if (ntohs (lp->link_type.header.type) != 0) - length += TLV_SIZE (&lp->link_type.header); + /* TE_LINK_SUBTLV_LINK_TYPE */ + if (ntohs(lp->link_type.header.type) != 0) + length += TLV_SIZE(&lp->link_type.header); - /* TE_LINK_SUBTLV_LINK_ID */ - if (ntohs (lp->link_id.header.type) != 0) - length += TLV_SIZE (&lp->link_id.header); + /* TE_LINK_SUBTLV_LINK_ID */ + if (ntohs(lp->link_id.header.type) != 0) + length += TLV_SIZE(&lp->link_id.header); - /* TE_LINK_SUBTLV_LCLIF_IPADDR */ - if (lp->lclif_ipaddr.header.type != 0) - length += TLV_SIZE (&lp->lclif_ipaddr.header); + /* TE_LINK_SUBTLV_LCLIF_IPADDR */ + if (lp->lclif_ipaddr.header.type != 0) + length += TLV_SIZE(&lp->lclif_ipaddr.header); - /* TE_LINK_SUBTLV_RMTIF_IPADDR */ - if (lp->rmtif_ipaddr.header.type != 0) - length += TLV_SIZE (&lp->rmtif_ipaddr.header); + /* TE_LINK_SUBTLV_RMTIF_IPADDR */ + if (lp->rmtif_ipaddr.header.type != 0) + length += TLV_SIZE(&lp->rmtif_ipaddr.header); - /* TE_LINK_SUBTLV_TE_METRIC */ - if (ntohs (lp->te_metric.header.type) != 0) - length += TLV_SIZE (&lp->te_metric.header); + /* TE_LINK_SUBTLV_TE_METRIC */ + if (ntohs(lp->te_metric.header.type) != 0) + length += TLV_SIZE(&lp->te_metric.header); - /* TE_LINK_SUBTLV_MAX_BW */ - if (ntohs (lp->max_bw.header.type) != 0) - length += TLV_SIZE (&lp->max_bw.header); + /* TE_LINK_SUBTLV_MAX_BW */ + if (ntohs(lp->max_bw.header.type) != 0) + length += TLV_SIZE(&lp->max_bw.header); - /* TE_LINK_SUBTLV_MAX_RSV_BW */ - if (ntohs (lp->max_rsv_bw.header.type) != 0) - length += TLV_SIZE (&lp->max_rsv_bw.header); + /* TE_LINK_SUBTLV_MAX_RSV_BW */ + if (ntohs(lp->max_rsv_bw.header.type) != 0) + length += TLV_SIZE(&lp->max_rsv_bw.header); - /* TE_LINK_SUBTLV_UNRSV_BW */ - if (ntohs (lp->unrsv_bw.header.type) != 0) - length += TLV_SIZE (&lp->unrsv_bw.header); + /* TE_LINK_SUBTLV_UNRSV_BW */ + if (ntohs(lp->unrsv_bw.header.type) != 0) + length += TLV_SIZE(&lp->unrsv_bw.header); - /* TE_LINK_SUBTLV_RSC_CLSCLR */ - if (ntohs (lp->rsc_clsclr.header.type) != 0) - length += TLV_SIZE (&lp->rsc_clsclr.header); - - /* TE_LINK_SUBTLV_LLRI */ - if (ntohs (lp->llri.header.type) != 0) - length += TLV_SIZE (&lp->llri.header); - - /* TE_LINK_SUBTLV_RIP */ - if (ntohs (lp->rip.header.type) != 0) - length += TLV_SIZE (&lp->rip.header); - - /* TE_LINK_SUBTLV_RAS */ - if (ntohs (lp->ras.header.type) != 0) - length += TLV_SIZE (&lp->ras.header); - - /* TE_LINK_SUBTLV_LRRID */ - if (ntohs (lp->lrrid.header.type) != 0) - length += TLV_SIZE (&lp->lrrid.header); - - /* TE_LINK_SUBTLV_AV_DELAY */ - if (ntohs (lp->av_delay.header.type) != 0) - length += TLV_SIZE (&lp->av_delay.header); - - /* TE_LINK_SUBTLV_MM_DELAY */ - if (ntohs (lp->mm_delay.header.type) != 0) - length += TLV_SIZE (&lp->mm_delay.header); - - /* TE_LINK_SUBTLV_DELAY_VAR */ - if (ntohs (lp->delay_var.header.type) != 0) - length += TLV_SIZE (&lp->delay_var.header); - - /* TE_LINK_SUBTLV_PKT_LOSS */ - if (ntohs (lp->pkt_loss.header.type) != 0) - length += TLV_SIZE (&lp->pkt_loss.header); - - /* TE_LINK_SUBTLV_RES_BW */ - if (ntohs (lp->res_bw.header.type) != 0) - length += TLV_SIZE (&lp->res_bw.header); - - /* TE_LINK_SUBTLV_AVA_BW */ - if (ntohs (lp->ava_bw.header.type) != 0) - length += TLV_SIZE (&lp->ava_bw.header); - - /* TE_LINK_SUBTLV_USE_BW */ - if (ntohs (lp->use_bw.header.type) != 0) - length += TLV_SIZE (&lp->use_bw.header); - - lp->link_header.header.type = htons (TE_TLV_LINK); - lp->link_header.header.length = htons (length); + /* TE_LINK_SUBTLV_RSC_CLSCLR */ + if (ntohs(lp->rsc_clsclr.header.type) != 0) + length += TLV_SIZE(&lp->rsc_clsclr.header); + + /* TE_LINK_SUBTLV_LLRI */ + if (ntohs(lp->llri.header.type) != 0) + length += TLV_SIZE(&lp->llri.header); + + /* TE_LINK_SUBTLV_RIP */ + if (ntohs(lp->rip.header.type) != 0) + length += TLV_SIZE(&lp->rip.header); + + /* TE_LINK_SUBTLV_RAS */ + if (ntohs(lp->ras.header.type) != 0) + length += TLV_SIZE(&lp->ras.header); + + /* TE_LINK_SUBTLV_LRRID */ + if (ntohs(lp->lrrid.header.type) != 0) + length += TLV_SIZE(&lp->lrrid.header); + + /* TE_LINK_SUBTLV_AV_DELAY */ + if (ntohs(lp->av_delay.header.type) != 0) + length += TLV_SIZE(&lp->av_delay.header); + + /* TE_LINK_SUBTLV_MM_DELAY */ + if (ntohs(lp->mm_delay.header.type) != 0) + length += TLV_SIZE(&lp->mm_delay.header); + + /* TE_LINK_SUBTLV_DELAY_VAR */ + if (ntohs(lp->delay_var.header.type) != 0) + length += TLV_SIZE(&lp->delay_var.header); + + /* TE_LINK_SUBTLV_PKT_LOSS */ + if (ntohs(lp->pkt_loss.header.type) != 0) + length += TLV_SIZE(&lp->pkt_loss.header); + + /* TE_LINK_SUBTLV_RES_BW */ + if (ntohs(lp->res_bw.header.type) != 0) + length += TLV_SIZE(&lp->res_bw.header); + + /* TE_LINK_SUBTLV_AVA_BW */ + if (ntohs(lp->ava_bw.header.type) != 0) + length += TLV_SIZE(&lp->ava_bw.header); + + /* TE_LINK_SUBTLV_USE_BW */ + if (ntohs(lp->use_bw.header.type) != 0) + length += TLV_SIZE(&lp->use_bw.header); - return; + lp->link_header.header.type = htons(TE_TLV_LINK); + lp->link_header.header.length = htons(length); + + return; } - -static void -set_linkparams_link_type (struct ospf_interface *oi, struct mpls_te_link *lp) -{ - lp->link_type.header.type = htons (TE_LINK_SUBTLV_LINK_TYPE); - lp->link_type.header.length = htons (TE_LINK_SUBTLV_TYPE_SIZE); - - switch (oi->type) - { - case OSPF_IFTYPE_POINTOPOINT: - lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_PTP; - break; - case OSPF_IFTYPE_BROADCAST: - case OSPF_IFTYPE_NBMA: - lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_MA; - break; - default: - /* Not supported yet. *//* XXX */ - lp->link_type.header.type = htons (0); - break; - } - return; + +static void set_linkparams_link_type(struct ospf_interface *oi, + struct mpls_te_link *lp) +{ + lp->link_type.header.type = htons(TE_LINK_SUBTLV_LINK_TYPE); + lp->link_type.header.length = htons(TE_LINK_SUBTLV_TYPE_SIZE); + + switch (oi->type) { + case OSPF_IFTYPE_POINTOPOINT: + lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_PTP; + break; + case OSPF_IFTYPE_BROADCAST: + case OSPF_IFTYPE_NBMA: + lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_MA; + break; + default: + /* Not supported yet. */ /* XXX */ + lp->link_type.header.type = htons(0); + break; + } + return; } - -static void -set_linkparams_link_id (struct ospf_interface *oi, struct mpls_te_link *lp) + +static void set_linkparams_link_id(struct ospf_interface *oi, + struct mpls_te_link *lp) { - struct ospf_neighbor *nbr; - int done = 0; - - lp->link_id.header.type = htons (TE_LINK_SUBTLV_LINK_ID); - lp->link_id.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); + struct ospf_neighbor *nbr; + int done = 0; - /* - * The Link ID is identical to the contents of the Link ID field - * in the Router LSA for these link types. - */ - switch (oi->type) - { - case OSPF_IFTYPE_POINTOPOINT: - /* Take the router ID of the neighbor. */ - if ((nbr = ospf_nbr_lookup_ptop (oi)) && nbr->state == NSM_Full) - { - lp->link_id.value = nbr->router_id; - done = 1; - } - break; - case OSPF_IFTYPE_BROADCAST: - case OSPF_IFTYPE_NBMA: - /* Take the interface address of the designated router. */ - if ((nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &DR (oi))) == NULL) - break; + lp->link_id.header.type = htons(TE_LINK_SUBTLV_LINK_ID); + lp->link_id.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE); - if (nbr->state == NSM_Full - || (IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi)) - && ospf_nbr_count (oi, NSM_Full) > 0)) - { - lp->link_id.value = DR (oi); - done = 1; - } - break; - default: - /* Not supported yet. *//* XXX */ - lp->link_id.header.type = htons (0); - break; - } + /* + * The Link ID is identical to the contents of the Link ID field + * in the Router LSA for these link types. + */ + switch (oi->type) { + case OSPF_IFTYPE_POINTOPOINT: + /* Take the router ID of the neighbor. */ + if ((nbr = ospf_nbr_lookup_ptop(oi)) + && nbr->state == NSM_Full) { + lp->link_id.value = nbr->router_id; + done = 1; + } + break; + case OSPF_IFTYPE_BROADCAST: + case OSPF_IFTYPE_NBMA: + /* Take the interface address of the designated router. */ + if ((nbr = ospf_nbr_lookup_by_addr(oi->nbrs, &DR(oi))) == NULL) + break; - if (! done) - { - struct in_addr mask; - masklen2ip (oi->address->prefixlen, &mask); - lp->link_id.value.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr; - } - return; + if (nbr->state == NSM_Full + || (IPV4_ADDR_SAME(&oi->address->u.prefix4, &DR(oi)) + && ospf_nbr_count(oi, NSM_Full) > 0)) { + lp->link_id.value = DR(oi); + done = 1; + } + break; + default: + /* Not supported yet. */ /* XXX */ + lp->link_id.header.type = htons(0); + break; + } + + if (!done) { + struct in_addr mask; + masklen2ip(oi->address->prefixlen, &mask); + lp->link_id.value.s_addr = + oi->address->u.prefix4.s_addr & mask.s_addr; + } + return; } -static void -set_linkparams_lclif_ipaddr (struct mpls_te_link *lp, struct in_addr lclif) +static void set_linkparams_lclif_ipaddr(struct mpls_te_link *lp, + struct in_addr lclif) { - lp->lclif_ipaddr.header.type = htons (TE_LINK_SUBTLV_LCLIF_IPADDR); - lp->lclif_ipaddr.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); - lp->lclif_ipaddr.value[0] = lclif; - return; + lp->lclif_ipaddr.header.type = htons(TE_LINK_SUBTLV_LCLIF_IPADDR); + lp->lclif_ipaddr.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE); + lp->lclif_ipaddr.value[0] = lclif; + return; } -static void -set_linkparams_rmtif_ipaddr (struct mpls_te_link *lp, struct in_addr rmtif) +static void set_linkparams_rmtif_ipaddr(struct mpls_te_link *lp, + struct in_addr rmtif) { - lp->rmtif_ipaddr.header.type = htons (TE_LINK_SUBTLV_RMTIF_IPADDR); - lp->rmtif_ipaddr.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); - lp->rmtif_ipaddr.value[0] = rmtif; - return; + lp->rmtif_ipaddr.header.type = htons(TE_LINK_SUBTLV_RMTIF_IPADDR); + lp->rmtif_ipaddr.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE); + lp->rmtif_ipaddr.value[0] = rmtif; + return; } -static void -set_linkparams_te_metric (struct mpls_te_link *lp, u_int32_t te_metric) +static void set_linkparams_te_metric(struct mpls_te_link *lp, + u_int32_t te_metric) { - lp->te_metric.header.type = htons (TE_LINK_SUBTLV_TE_METRIC); - lp->te_metric.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); - lp->te_metric.value = htonl (te_metric); - return; + lp->te_metric.header.type = htons(TE_LINK_SUBTLV_TE_METRIC); + lp->te_metric.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE); + lp->te_metric.value = htonl(te_metric); + return; } -static void -set_linkparams_max_bw (struct mpls_te_link *lp, float fp) +static void set_linkparams_max_bw(struct mpls_te_link *lp, float fp) { - lp->max_bw.header.type = htons (TE_LINK_SUBTLV_MAX_BW); - lp->max_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); - lp->max_bw.value = htonf (fp); - return; + lp->max_bw.header.type = htons(TE_LINK_SUBTLV_MAX_BW); + lp->max_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE); + lp->max_bw.value = htonf(fp); + return; } -static void -set_linkparams_max_rsv_bw (struct mpls_te_link *lp, float fp) +static void set_linkparams_max_rsv_bw(struct mpls_te_link *lp, float fp) { - lp->max_rsv_bw.header.type = htons (TE_LINK_SUBTLV_MAX_RSV_BW); - lp->max_rsv_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); - lp->max_rsv_bw.value = htonf (fp); - return; + lp->max_rsv_bw.header.type = htons(TE_LINK_SUBTLV_MAX_RSV_BW); + lp->max_rsv_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE); + lp->max_rsv_bw.value = htonf(fp); + return; } -static void -set_linkparams_unrsv_bw (struct mpls_te_link *lp, int priority, float fp) +static void set_linkparams_unrsv_bw(struct mpls_te_link *lp, int priority, + float fp) { - /* Note that TLV-length field is the size of array. */ - lp->unrsv_bw.header.type = htons (TE_LINK_SUBTLV_UNRSV_BW); - lp->unrsv_bw.header.length = htons (TE_LINK_SUBTLV_UNRSV_SIZE); - lp->unrsv_bw.value [priority] = htonf (fp); - return; + /* Note that TLV-length field is the size of array. */ + lp->unrsv_bw.header.type = htons(TE_LINK_SUBTLV_UNRSV_BW); + lp->unrsv_bw.header.length = htons(TE_LINK_SUBTLV_UNRSV_SIZE); + lp->unrsv_bw.value[priority] = htonf(fp); + return; } -static void -set_linkparams_rsc_clsclr (struct mpls_te_link *lp, u_int32_t classcolor) +static void set_linkparams_rsc_clsclr(struct mpls_te_link *lp, + u_int32_t classcolor) { - lp->rsc_clsclr.header.type = htons (TE_LINK_SUBTLV_RSC_CLSCLR); - lp->rsc_clsclr.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); - lp->rsc_clsclr.value = htonl (classcolor); - return; + lp->rsc_clsclr.header.type = htons(TE_LINK_SUBTLV_RSC_CLSCLR); + lp->rsc_clsclr.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE); + lp->rsc_clsclr.value = htonl(classcolor); + return; } -static void -set_linkparams_inter_as (struct mpls_te_link *lp, struct in_addr addr, - u_int32_t as) +static void set_linkparams_inter_as(struct mpls_te_link *lp, + struct in_addr addr, u_int32_t as) { - /* Set the Remote ASBR IP address and then the associated AS number */ - lp->rip.header.type = htons (TE_LINK_SUBTLV_RIP); - lp->rip.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); - lp->rip.value = addr; + /* Set the Remote ASBR IP address and then the associated AS number */ + lp->rip.header.type = htons(TE_LINK_SUBTLV_RIP); + lp->rip.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE); + lp->rip.value = addr; - lp->ras.header.type = htons (TE_LINK_SUBTLV_RAS); - lp->ras.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); - lp->ras.value = htonl (as); + lp->ras.header.type = htons(TE_LINK_SUBTLV_RAS); + lp->ras.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE); + lp->ras.value = htonl(as); } -static void -unset_linkparams_inter_as (struct mpls_te_link *lp) +static void unset_linkparams_inter_as(struct mpls_te_link *lp) { - /* Reset the Remote ASBR IP address and then the associated AS number */ - lp->rip.header.type = htons (0); - lp->rip.header.length = htons (0); - lp->rip.value.s_addr = htonl (0); + /* Reset the Remote ASBR IP address and then the associated AS number */ + lp->rip.header.type = htons(0); + lp->rip.header.length = htons(0); + lp->rip.value.s_addr = htonl(0); - lp->ras.header.type = htons (0); - lp->ras.header.length = htons (0); - lp->ras.value = htonl (0); + lp->ras.header.type = htons(0); + lp->ras.header.length = htons(0); + lp->ras.value = htonl(0); } -void -set_linkparams_llri (struct mpls_te_link *lp, u_int32_t local, - u_int32_t remote) +void set_linkparams_llri(struct mpls_te_link *lp, u_int32_t local, + u_int32_t remote) { - lp->llri.header.type = htons (TE_LINK_SUBTLV_LLRI); - lp->llri.header.length = htons (TE_LINK_SUBTLV_LLRI_SIZE); - lp->llri.local = htonl (local); - lp->llri.remote = htonl (remote); + lp->llri.header.type = htons(TE_LINK_SUBTLV_LLRI); + lp->llri.header.length = htons(TE_LINK_SUBTLV_LLRI_SIZE); + lp->llri.local = htonl(local); + lp->llri.remote = htonl(remote); } -void -set_linkparams_lrrid (struct mpls_te_link *lp, struct in_addr local, - struct in_addr remote) +void set_linkparams_lrrid(struct mpls_te_link *lp, struct in_addr local, + struct in_addr remote) { - lp->lrrid.header.type = htons (TE_LINK_SUBTLV_LRRID); - lp->lrrid.header.length = htons (TE_LINK_SUBTLV_LRRID_SIZE); - lp->lrrid.local.s_addr = local.s_addr; - lp->lrrid.remote.s_addr = remote.s_addr; + lp->lrrid.header.type = htons(TE_LINK_SUBTLV_LRRID); + lp->lrrid.header.length = htons(TE_LINK_SUBTLV_LRRID_SIZE); + lp->lrrid.local.s_addr = local.s_addr; + lp->lrrid.remote.s_addr = remote.s_addr; } -static void -set_linkparams_av_delay (struct mpls_te_link *lp, u_int32_t delay, u_char anormal) +static void set_linkparams_av_delay(struct mpls_te_link *lp, u_int32_t delay, + u_char anormal) { - u_int32_t tmp; - /* Note that TLV-length field is the size of array. */ - lp->av_delay.header.type = htons (TE_LINK_SUBTLV_AV_DELAY); - lp->av_delay.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); - tmp = delay & TE_EXT_MASK; - if (anormal) - tmp |= TE_EXT_ANORMAL; - lp->av_delay.value = htonl (tmp); - return; + u_int32_t tmp; + /* Note that TLV-length field is the size of array. */ + lp->av_delay.header.type = htons(TE_LINK_SUBTLV_AV_DELAY); + lp->av_delay.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE); + tmp = delay & TE_EXT_MASK; + if (anormal) + tmp |= TE_EXT_ANORMAL; + lp->av_delay.value = htonl(tmp); + return; } -static void -set_linkparams_mm_delay (struct mpls_te_link *lp, u_int32_t low, u_int32_t high, u_char anormal) +static void set_linkparams_mm_delay(struct mpls_te_link *lp, u_int32_t low, + u_int32_t high, u_char anormal) { - u_int32_t tmp; - /* Note that TLV-length field is the size of array. */ - lp->mm_delay.header.type = htons (TE_LINK_SUBTLV_MM_DELAY); - lp->mm_delay.header.length = htons (TE_LINK_SUBTLV_MM_DELAY_SIZE); - tmp = low & TE_EXT_MASK; - if (anormal) - tmp |= TE_EXT_ANORMAL; - lp->mm_delay.low = htonl (tmp); - lp->mm_delay.high = htonl (high); - return; + u_int32_t tmp; + /* Note that TLV-length field is the size of array. */ + lp->mm_delay.header.type = htons(TE_LINK_SUBTLV_MM_DELAY); + lp->mm_delay.header.length = htons(TE_LINK_SUBTLV_MM_DELAY_SIZE); + tmp = low & TE_EXT_MASK; + if (anormal) + tmp |= TE_EXT_ANORMAL; + lp->mm_delay.low = htonl(tmp); + lp->mm_delay.high = htonl(high); + return; } -static void -set_linkparams_delay_var (struct mpls_te_link *lp, u_int32_t jitter) +static void set_linkparams_delay_var(struct mpls_te_link *lp, u_int32_t jitter) { - /* Note that TLV-length field is the size of array. */ - lp->delay_var.header.type = htons (TE_LINK_SUBTLV_DELAY_VAR); - lp->delay_var.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); - lp->delay_var.value = htonl (jitter & TE_EXT_MASK); - return; + /* Note that TLV-length field is the size of array. */ + lp->delay_var.header.type = htons(TE_LINK_SUBTLV_DELAY_VAR); + lp->delay_var.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE); + lp->delay_var.value = htonl(jitter & TE_EXT_MASK); + return; } -static void -set_linkparams_pkt_loss (struct mpls_te_link *lp, u_int32_t loss, u_char anormal) +static void set_linkparams_pkt_loss(struct mpls_te_link *lp, u_int32_t loss, + u_char anormal) { - u_int32_t tmp; - /* Note that TLV-length field is the size of array. */ - lp->pkt_loss.header.type = htons (TE_LINK_SUBTLV_PKT_LOSS); - lp->pkt_loss.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); - tmp = loss & TE_EXT_MASK; - if (anormal) - tmp |= TE_EXT_ANORMAL; - lp->pkt_loss.value = htonl (tmp); - return; + u_int32_t tmp; + /* Note that TLV-length field is the size of array. */ + lp->pkt_loss.header.type = htons(TE_LINK_SUBTLV_PKT_LOSS); + lp->pkt_loss.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE); + tmp = loss & TE_EXT_MASK; + if (anormal) + tmp |= TE_EXT_ANORMAL; + lp->pkt_loss.value = htonl(tmp); + return; } -static void -set_linkparams_res_bw (struct mpls_te_link *lp, float fp) +static void set_linkparams_res_bw(struct mpls_te_link *lp, float fp) { - /* Note that TLV-length field is the size of array. */ - lp->res_bw.header.type = htons (TE_LINK_SUBTLV_RES_BW); - lp->res_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); - lp->res_bw.value = htonf (fp); - return; + /* Note that TLV-length field is the size of array. */ + lp->res_bw.header.type = htons(TE_LINK_SUBTLV_RES_BW); + lp->res_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE); + lp->res_bw.value = htonf(fp); + return; } -static void -set_linkparams_ava_bw (struct mpls_te_link *lp, float fp) +static void set_linkparams_ava_bw(struct mpls_te_link *lp, float fp) { - /* Note that TLV-length field is the size of array. */ - lp->ava_bw.header.type = htons (TE_LINK_SUBTLV_AVA_BW); - lp->ava_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); - lp->ava_bw.value = htonf (fp); - return; + /* Note that TLV-length field is the size of array. */ + lp->ava_bw.header.type = htons(TE_LINK_SUBTLV_AVA_BW); + lp->ava_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE); + lp->ava_bw.value = htonf(fp); + return; } -static void -set_linkparams_use_bw (struct mpls_te_link *lp, float fp) +static void set_linkparams_use_bw(struct mpls_te_link *lp, float fp) { - /* Note that TLV-length field is the size of array. */ - lp->use_bw.header.type = htons (TE_LINK_SUBTLV_USE_BW); - lp->use_bw.header.length = htons (TE_LINK_SUBTLV_DEF_SIZE); - lp->use_bw.value = htonf (fp); - return; + /* Note that TLV-length field is the size of array. */ + lp->use_bw.header.type = htons(TE_LINK_SUBTLV_USE_BW); + lp->use_bw.header.length = htons(TE_LINK_SUBTLV_DEF_SIZE); + lp->use_bw.value = htonf(fp); + return; } /* Update TE parameters from Interface */ -static void -update_linkparams(struct mpls_te_link *lp) -{ - int i; - struct interface *ifp; - - /* Get the Interface structure */ - if ((ifp = lp->ifp) == NULL) - { - if (IS_DEBUG_OSPF_TE) - zlog_debug("OSPF MPLS-TE: Abort update TE parameters: no interface associated to Link Parameters"); - return; - } - if (!HAS_LINK_PARAMS(ifp)) - { - if (IS_DEBUG_OSPF_TE) - zlog_debug("OSPF MPLS-TE: Abort update TE parameters: no Link Parameters for interface"); - return; - } - - /* RFC3630 metrics */ - if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP)) - set_linkparams_rsc_clsclr (lp, ifp->link_params->admin_grp); - else - TLV_TYPE(lp->rsc_clsclr) = 0; - - if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW)) - set_linkparams_max_bw (lp, ifp->link_params->max_bw); - else - TLV_TYPE(lp->max_bw) = 0; - - if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW)) - set_linkparams_max_rsv_bw (lp, ifp->link_params->max_rsv_bw); - else - TLV_TYPE(lp->max_rsv_bw) = 0; - - if (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW)) - for (i = 0; i < MAX_CLASS_TYPE; i++) - set_linkparams_unrsv_bw (lp, i, ifp->link_params->unrsv_bw[i]); - else - TLV_TYPE(lp->unrsv_bw) = 0; - - if (IS_PARAM_SET(ifp->link_params, LP_TE_METRIC)) - set_linkparams_te_metric(lp, ifp->link_params->te_metric); - else - TLV_TYPE(lp->te_metric) = 0; - - /* TE metric Extensions */ - if (IS_PARAM_SET(ifp->link_params, LP_DELAY)) - set_linkparams_av_delay(lp, ifp->link_params->av_delay, 0); - else - TLV_TYPE(lp->av_delay) = 0; - - if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY)) - set_linkparams_mm_delay(lp, ifp->link_params->min_delay, ifp->link_params->max_delay, 0); - else - TLV_TYPE(lp->mm_delay) = 0; - - if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR)) - set_linkparams_delay_var(lp, ifp->link_params->delay_var); - else - TLV_TYPE(lp->delay_var) = 0; - - if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS)) - set_linkparams_pkt_loss(lp, ifp->link_params->pkt_loss, 0); - else - TLV_TYPE(lp->pkt_loss) = 0; - - if (IS_PARAM_SET(ifp->link_params, LP_RES_BW)) - set_linkparams_res_bw(lp, ifp->link_params->res_bw); - else - TLV_TYPE(lp->res_bw) = 0; - - if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW)) - set_linkparams_ava_bw(lp, ifp->link_params->ava_bw); - else - TLV_TYPE(lp->ava_bw) = 0; - - if (IS_PARAM_SET(ifp->link_params, LP_USE_BW)) - set_linkparams_use_bw(lp, ifp->link_params->use_bw); - else - TLV_TYPE(lp->use_bw) = 0; - - /* RFC5392 */ - if (IS_PARAM_SET(ifp->link_params, LP_RMT_AS)) - { - /* Flush LSA if it engaged and was previously a STD_TE one */ - if (IS_STD_TE(lp->type) && CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)) - { - if (IS_DEBUG_OSPF_TE) - zlog_debug("OSPF MPLS-TE Update IF: Switch from Standard LSA to INTER-AS for %s[%d/%d]", - ifp->name, lp->flags, lp->type); - - ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA); - /* Then, switch it to INTER-AS */ - if (OspfMplsTE.inter_as == AS) - lp->flags = INTER_AS | FLOOD_AS; - else - { - lp->flags = INTER_AS | FLOOD_AREA; - lp->area = ospf_area_lookup_by_area_id (ospf_lookup(), OspfMplsTE.interas_areaid); - } - } - set_linkparams_inter_as(lp, ifp->link_params->rmt_ip, ifp->link_params->rmt_as); - } - else - { - if (IS_DEBUG_OSPF_TE) - zlog_debug("OSPF MPLS-TE Update IF: Switch from INTER-AS LSA to Standard for %s[%d/%d]", - ifp->name, lp->flags, lp->type); - - /* reset inter-as TE params */ - /* Flush LSA if it engaged and was previously an INTER_AS one */ - if (IS_INTER_AS(lp->type) && CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)) - { - ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA); - /* Then, switch it to Standard TE */ - lp->flags = STD_TE | FLOOD_AREA; - } - unset_linkparams_inter_as (lp); - } -} - -static void -initialize_linkparams (struct mpls_te_link *lp) -{ - struct interface *ifp = lp->ifp; - struct ospf_interface *oi; - - if (IS_DEBUG_OSPF_TE) - zlog_debug("MPLS-TE(initialize_linkparams) Initialize Link Parameters for interface %s", - ifp->name); - - if ((oi = lookup_oi_by_ifp (ifp, NULL, OI_ANY)) == NULL) - { - if (IS_DEBUG_OSPF_TE) - zlog_warn("MPLS-TE(initialize_linkparams) Could not find corresponding OSPF Interface for %s", - ifp->name); - return; - } - - /* - * Try to set initial values those can be derived from - * zebra-interface information. - */ - set_linkparams_link_type (oi, lp); - - /* Set local IP addr */ - set_linkparams_lclif_ipaddr (lp, oi->address->u.prefix4); - - /* Set Remote IP addr if Point to Point Interface */ - if (oi->type == LINK_TYPE_SUBTLV_VALUE_PTP) - { - struct prefix *pref = CONNECTED_PREFIX(oi->connected); - if (pref != NULL) - set_linkparams_rmtif_ipaddr(lp, pref->u.prefix4); - } - - /* Keep Area information in combination with link parameters. */ - lp->area = oi->area; - - return; -} - -static int -is_mandated_params_set (struct mpls_te_link *lp) -{ - int rc = 0; - - if (ntohs (OspfMplsTE.router_addr.header.type) == 0) - { - zlog_warn ("MPLS-TE(is_mandated_params_set) Missing Router Address"); - goto out; - } - - if (ntohs (lp->link_type.header.type) == 0) - { - zlog_warn ("MPLS-TE(is_mandated_params_set) Missing Link Type"); - goto out; - } - - if (!IS_INTER_AS (lp->type) && (ntohs (lp->link_id.header.type) == 0)) - { - zlog_warn ("MPLS-TE(is_mandated_params_set) Missing Link ID"); - goto out; - } - - rc = 1; +static void update_linkparams(struct mpls_te_link *lp) +{ + int i; + struct interface *ifp; + + /* Get the Interface structure */ + if ((ifp = lp->ifp) == NULL) { + if (IS_DEBUG_OSPF_TE) + zlog_debug( + "OSPF MPLS-TE: Abort update TE parameters: no interface associated to Link Parameters"); + return; + } + if (!HAS_LINK_PARAMS(ifp)) { + if (IS_DEBUG_OSPF_TE) + zlog_debug( + "OSPF MPLS-TE: Abort update TE parameters: no Link Parameters for interface"); + return; + } + + /* RFC3630 metrics */ + if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP)) + set_linkparams_rsc_clsclr(lp, ifp->link_params->admin_grp); + else + TLV_TYPE(lp->rsc_clsclr) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW)) + set_linkparams_max_bw(lp, ifp->link_params->max_bw); + else + TLV_TYPE(lp->max_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW)) + set_linkparams_max_rsv_bw(lp, ifp->link_params->max_rsv_bw); + else + TLV_TYPE(lp->max_rsv_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW)) + for (i = 0; i < MAX_CLASS_TYPE; i++) + set_linkparams_unrsv_bw(lp, i, + ifp->link_params->unrsv_bw[i]); + else + TLV_TYPE(lp->unrsv_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_TE_METRIC)) + set_linkparams_te_metric(lp, ifp->link_params->te_metric); + else + TLV_TYPE(lp->te_metric) = 0; + + /* TE metric Extensions */ + if (IS_PARAM_SET(ifp->link_params, LP_DELAY)) + set_linkparams_av_delay(lp, ifp->link_params->av_delay, 0); + else + TLV_TYPE(lp->av_delay) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY)) + set_linkparams_mm_delay(lp, ifp->link_params->min_delay, + ifp->link_params->max_delay, 0); + else + TLV_TYPE(lp->mm_delay) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR)) + set_linkparams_delay_var(lp, ifp->link_params->delay_var); + else + TLV_TYPE(lp->delay_var) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS)) + set_linkparams_pkt_loss(lp, ifp->link_params->pkt_loss, 0); + else + TLV_TYPE(lp->pkt_loss) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_RES_BW)) + set_linkparams_res_bw(lp, ifp->link_params->res_bw); + else + TLV_TYPE(lp->res_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW)) + set_linkparams_ava_bw(lp, ifp->link_params->ava_bw); + else + TLV_TYPE(lp->ava_bw) = 0; + + if (IS_PARAM_SET(ifp->link_params, LP_USE_BW)) + set_linkparams_use_bw(lp, ifp->link_params->use_bw); + else + TLV_TYPE(lp->use_bw) = 0; + + /* RFC5392 */ + if (IS_PARAM_SET(ifp->link_params, LP_RMT_AS)) { + /* Flush LSA if it engaged and was previously a STD_TE one */ + if (IS_STD_TE(lp->type) + && CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) { + if (IS_DEBUG_OSPF_TE) + zlog_debug( + "OSPF MPLS-TE Update IF: Switch from Standard LSA to INTER-AS for %s[%d/%d]", + ifp->name, lp->flags, lp->type); + + ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA); + /* Then, switch it to INTER-AS */ + if (OspfMplsTE.inter_as == AS) + lp->flags = INTER_AS | FLOOD_AS; + else { + lp->flags = INTER_AS | FLOOD_AREA; + lp->area = ospf_area_lookup_by_area_id( + ospf_lookup(), + OspfMplsTE.interas_areaid); + } + } + set_linkparams_inter_as(lp, ifp->link_params->rmt_ip, + ifp->link_params->rmt_as); + } else { + if (IS_DEBUG_OSPF_TE) + zlog_debug( + "OSPF MPLS-TE Update IF: Switch from INTER-AS LSA to Standard for %s[%d/%d]", + ifp->name, lp->flags, lp->type); + + /* reset inter-as TE params */ + /* Flush LSA if it engaged and was previously an INTER_AS one */ + if (IS_INTER_AS(lp->type) + && CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) { + ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA); + /* Then, switch it to Standard TE */ + lp->flags = STD_TE | FLOOD_AREA; + } + unset_linkparams_inter_as(lp); + } +} + +static void initialize_linkparams(struct mpls_te_link *lp) +{ + struct interface *ifp = lp->ifp; + struct ospf_interface *oi; + + if (IS_DEBUG_OSPF_TE) + zlog_debug( + "MPLS-TE(initialize_linkparams) Initialize Link Parameters for interface %s", + ifp->name); + + if ((oi = lookup_oi_by_ifp(ifp, NULL, OI_ANY)) == NULL) { + if (IS_DEBUG_OSPF_TE) + zlog_warn( + "MPLS-TE(initialize_linkparams) Could not find corresponding OSPF Interface for %s", + ifp->name); + return; + } + + /* + * Try to set initial values those can be derived from + * zebra-interface information. + */ + set_linkparams_link_type(oi, lp); + + /* Set local IP addr */ + set_linkparams_lclif_ipaddr(lp, oi->address->u.prefix4); + + /* Set Remote IP addr if Point to Point Interface */ + if (oi->type == LINK_TYPE_SUBTLV_VALUE_PTP) { + struct prefix *pref = CONNECTED_PREFIX(oi->connected); + if (pref != NULL) + set_linkparams_rmtif_ipaddr(lp, pref->u.prefix4); + } + + /* Keep Area information in combination with link parameters. */ + lp->area = oi->area; + + return; +} + +static int is_mandated_params_set(struct mpls_te_link *lp) +{ + int rc = 0; + + if (ntohs(OspfMplsTE.router_addr.header.type) == 0) { + zlog_warn( + "MPLS-TE(is_mandated_params_set) Missing Router Address"); + goto out; + } + + if (ntohs(lp->link_type.header.type) == 0) { + zlog_warn("MPLS-TE(is_mandated_params_set) Missing Link Type"); + goto out; + } + + if (!IS_INTER_AS(lp->type) && (ntohs(lp->link_id.header.type) == 0)) { + zlog_warn("MPLS-TE(is_mandated_params_set) Missing Link ID"); + goto out; + } + + rc = 1; out: - return rc; + return rc; } /*------------------------------------------------------------------------* * Followings are callback functions against generic Opaque-LSAs handling. *------------------------------------------------------------------------*/ -static int -ospf_mpls_te_new_if (struct interface *ifp) +static int ospf_mpls_te_new_if(struct interface *ifp) { - struct mpls_te_link *new; - int rc = -1; + struct mpls_te_link *new; + int rc = -1; - if (IS_DEBUG_OSPF_TE) - zlog_debug ("MPLS-TE(ospf_mpls_te_new_if) Add new %s interface %s to MPLS-TE list", - ifp->link_params ? "Active" : "Inactive", ifp->name); + if (IS_DEBUG_OSPF_TE) + zlog_debug( + "MPLS-TE(ospf_mpls_te_new_if) Add new %s interface %s to MPLS-TE list", + ifp->link_params ? "Active" : "Inactive", ifp->name); - if (lookup_linkparams_by_ifp (ifp) != NULL) - { - zlog_warn ("ospf_mpls_te_new_if: ifp(%p) already in use?", (void *)ifp); - rc = 0; /* Do nothing here. */ - goto out; - } + if (lookup_linkparams_by_ifp(ifp) != NULL) { + zlog_warn("ospf_mpls_te_new_if: ifp(%p) already in use?", + (void *)ifp); + rc = 0; /* Do nothing here. */ + goto out; + } - new = XCALLOC (MTYPE_OSPF_MPLS_TE, sizeof (struct mpls_te_link)); - if (new == NULL) - { - zlog_warn ("ospf_mpls_te_new_if: XMALLOC: %s", safe_strerror (errno)); - goto out; - } + new = XCALLOC(MTYPE_OSPF_MPLS_TE, sizeof(struct mpls_te_link)); + if (new == NULL) { + zlog_warn("ospf_mpls_te_new_if: XMALLOC: %s", + safe_strerror(errno)); + goto out; + } - new->instance = get_mpls_te_instance_value (); - new->ifp = ifp; - /* By default TE-Link is RFC3630 compatible flooding in Area and not active */ - /* This default behavior will be adapted with call to ospf_mpls_te_update_if() */ - new->type = STD_TE | FLOOD_AREA; - new->flags = LPFLG_LSA_INACTIVE; + new->instance = get_mpls_te_instance_value(); + new->ifp = ifp; + /* By default TE-Link is RFC3630 compatible flooding in Area and not + * active */ + /* This default behavior will be adapted with call to + * ospf_mpls_te_update_if() */ + new->type = STD_TE | FLOOD_AREA; + new->flags = LPFLG_LSA_INACTIVE; - /* Initialize Link Parameters from Interface */ - initialize_linkparams(new); + /* Initialize Link Parameters from Interface */ + initialize_linkparams(new); - /* Set TE Parameters from Interface */ - update_linkparams(new); + /* Set TE Parameters from Interface */ + update_linkparams(new); - /* Add Link Parameters structure to the list */ - listnode_add (OspfMplsTE.iflist, new); + /* Add Link Parameters structure to the list */ + listnode_add(OspfMplsTE.iflist, new); - if (IS_DEBUG_OSPF_TE) - zlog_debug("OSPF MPLS-TE New IF: Add new LP context for %s[%d/%d]", - ifp->name, new->flags, new->type); + if (IS_DEBUG_OSPF_TE) + zlog_debug( + "OSPF MPLS-TE New IF: Add new LP context for %s[%d/%d]", + ifp->name, new->flags, new->type); - /* Schedule Opaque-LSA refresh. *//* XXX */ + /* Schedule Opaque-LSA refresh. */ /* XXX */ - rc = 0; + rc = 0; out: - return rc; + return rc; } -static int -ospf_mpls_te_del_if (struct interface *ifp) +static int ospf_mpls_te_del_if(struct interface *ifp) { - struct mpls_te_link *lp; - int rc = -1; + struct mpls_te_link *lp; + int rc = -1; - if ((lp = lookup_linkparams_by_ifp (ifp)) != NULL) - { - struct list *iflist = OspfMplsTE.iflist; + if ((lp = lookup_linkparams_by_ifp(ifp)) != NULL) { + struct list *iflist = OspfMplsTE.iflist; - /* Dequeue listnode entry from the list. */ - listnode_delete (iflist, lp); + /* Dequeue listnode entry from the list. */ + listnode_delete(iflist, lp); - /* Avoid misjudgement in the next lookup. */ - if (listcount (iflist) == 0) - iflist->head = iflist->tail = NULL; + /* Avoid misjudgement in the next lookup. */ + if (listcount(iflist) == 0) + iflist->head = iflist->tail = NULL; - XFREE (MTYPE_OSPF_MPLS_TE, lp); - } + XFREE(MTYPE_OSPF_MPLS_TE, lp); + } - /* Schedule Opaque-LSA refresh. *//* XXX */ + /* Schedule Opaque-LSA refresh. */ /* XXX */ - rc = 0; -/*out:*/ - return rc; + rc = 0; + /*out:*/ + return rc; } /* Main initialization / update function of the MPLS TE Link context */ /* Call when interface TE Link parameters are modified */ -void -ospf_mpls_te_update_if (struct interface *ifp) -{ - struct mpls_te_link *lp; - - if (IS_DEBUG_OSPF_TE) - zlog_debug ("OSPF MPLS-TE: Update LSA parameters for interface %s [%s]", - ifp->name, HAS_LINK_PARAMS(ifp) ? "ON" : "OFF"); - - /* Get Link context from interface */ - if ((lp = lookup_linkparams_by_ifp(ifp)) == NULL) - { - if (IS_DEBUG_OSPF_TE) - zlog_warn ("OSPF MPLS-TE Update: Did not find Link Parameters context for interface %s", ifp->name); - return; - } - - /* Fulfill MPLS-TE Link TLV from Interface TE Link parameters */ - if (HAS_LINK_PARAMS(ifp)) - { - SET_FLAG (lp->flags, LPFLG_LSA_ACTIVE); - - /* Update TE parameters */ - update_linkparams(lp); - - /* Finally Re-Originate or Refresh Opaque LSA if MPLS_TE is enabled */ - if (OspfMplsTE.status == enabled) - if (lp->area != NULL) - { - if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED) - ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA); - else - ospf_mpls_te_lsa_schedule (lp, REORIGINATE_THIS_LSA); - } - } - else - { - /* If MPLS TE is disable on this interface, flush LSA if it is already engaged */ - if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED) - ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA); - else - /* Reset Activity flag */ - lp->flags = LPFLG_LSA_INACTIVE; - } - - return; -} - -static void -ospf_mpls_te_ism_change (struct ospf_interface *oi, int old_state) -{ - struct te_link_subtlv_link_type old_type; - struct te_link_subtlv_link_id old_id; - struct mpls_te_link *lp; - - if ((lp = lookup_linkparams_by_ifp (oi->ifp)) == NULL) - { - zlog_warn ("ospf_mpls_te_ism_change: Cannot get linkparams from OI(%s)?", IF_NAME (oi)); - goto out; - } - - if (oi->area == NULL || oi->area->ospf == NULL) - { - zlog_warn ("ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?", IF_NAME (oi)); - goto out; - } +void ospf_mpls_te_update_if(struct interface *ifp) +{ + struct mpls_te_link *lp; + + if (IS_DEBUG_OSPF_TE) + zlog_debug( + "OSPF MPLS-TE: Update LSA parameters for interface %s [%s]", + ifp->name, HAS_LINK_PARAMS(ifp) ? "ON" : "OFF"); + + /* Get Link context from interface */ + if ((lp = lookup_linkparams_by_ifp(ifp)) == NULL) { + if (IS_DEBUG_OSPF_TE) + zlog_warn( + "OSPF MPLS-TE Update: Did not find Link Parameters context for interface %s", + ifp->name); + return; + } + + /* Fulfill MPLS-TE Link TLV from Interface TE Link parameters */ + if (HAS_LINK_PARAMS(ifp)) { + SET_FLAG(lp->flags, LPFLG_LSA_ACTIVE); + + /* Update TE parameters */ + update_linkparams(lp); + + /* Finally Re-Originate or Refresh Opaque LSA if MPLS_TE is + * enabled */ + if (OspfMplsTE.status == enabled) + if (lp->area != NULL) { + if + CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED) + ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA); + else ospf_mpls_te_lsa_schedule( + lp, REORIGINATE_THIS_LSA); + } + } else { + /* If MPLS TE is disable on this interface, flush LSA if it is + * already engaged */ + if + CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED) + ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA); + else + /* Reset Activity flag */ + lp->flags = LPFLG_LSA_INACTIVE; + } + + return; +} + +static void ospf_mpls_te_ism_change(struct ospf_interface *oi, int old_state) +{ + struct te_link_subtlv_link_type old_type; + struct te_link_subtlv_link_id old_id; + struct mpls_te_link *lp; + + if ((lp = lookup_linkparams_by_ifp(oi->ifp)) == NULL) { + zlog_warn( + "ospf_mpls_te_ism_change: Cannot get linkparams from OI(%s)?", + IF_NAME(oi)); + goto out; + } + + if (oi->area == NULL || oi->area->ospf == NULL) { + zlog_warn( + "ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?", + IF_NAME(oi)); + goto out; + } #ifdef notyet - if ((lp->area != NULL - && ! IPV4_ADDR_SAME (&lp->area->area_id, &oi->area->area_id)) - || (lp->area != NULL && oi->area == NULL)) - { - /* How should we consider this case? */ - zlog_warn ("MPLS-TE: Area for OI(%s) has changed to [%s], flush previous LSAs", - IF_NAME (oi), oi->area ? inet_ntoa (oi->area->area_id) : "N/A"); - ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA); - } + if ((lp->area != NULL + && !IPV4_ADDR_SAME(&lp->area->area_id, &oi->area->area_id)) + || (lp->area != NULL && oi->area == NULL)) { + /* How should we consider this case? */ + zlog_warn( + "MPLS-TE: Area for OI(%s) has changed to [%s], flush previous LSAs", + IF_NAME(oi), + oi->area ? inet_ntoa(oi->area->area_id) : "N/A"); + ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA); + } #endif - /* Keep Area information in combination with linkparams. */ - lp->area = oi->area; - - /* Keep interface MPLS-TE status */ - lp->flags = HAS_LINK_PARAMS(oi->ifp); - - switch (oi->state) - { - case ISM_PointToPoint: - case ISM_DROther: - case ISM_Backup: - case ISM_DR: - old_type = lp->link_type; - old_id = lp->link_id; - - /* Set Link type, Link ID, Local and Remote IP addr */ - set_linkparams_link_type (oi, lp); - set_linkparams_link_id (oi, lp); - set_linkparams_lclif_ipaddr (lp, oi->address->u.prefix4); - - if (oi->type == LINK_TYPE_SUBTLV_VALUE_PTP) - { - struct prefix *pref = CONNECTED_PREFIX(oi->connected); - if (pref != NULL) - set_linkparams_rmtif_ipaddr(lp, pref->u.prefix4); - } - - /* Update TE parameters */ - update_linkparams(lp); - - /* Try to Schedule LSA */ - if ((ntohs (old_type.header.type) != ntohs (lp->link_type.header.type) - || old_type.link_type.value != lp->link_type.link_type.value) - || (ntohs (old_id.header.type) != ntohs (lp->link_id.header.type) - || ntohl (old_id.value.s_addr) != - ntohl (lp->link_id.value.s_addr))) - { - if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED) - ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA); - else - ospf_mpls_te_lsa_schedule (lp, REORIGINATE_THIS_LSA); - - } - break; - default: - lp->link_type.header.type = htons (0); - lp->link_id.header.type = htons (0); - - if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED) - ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA); - break; - } + /* Keep Area information in combination with linkparams. */ + lp->area = oi->area; + + /* Keep interface MPLS-TE status */ + lp->flags = HAS_LINK_PARAMS(oi->ifp); + + switch (oi->state) { + case ISM_PointToPoint: + case ISM_DROther: + case ISM_Backup: + case ISM_DR: + old_type = lp->link_type; + old_id = lp->link_id; + + /* Set Link type, Link ID, Local and Remote IP addr */ + set_linkparams_link_type(oi, lp); + set_linkparams_link_id(oi, lp); + set_linkparams_lclif_ipaddr(lp, oi->address->u.prefix4); + + if (oi->type == LINK_TYPE_SUBTLV_VALUE_PTP) { + struct prefix *pref = CONNECTED_PREFIX(oi->connected); + if (pref != NULL) + set_linkparams_rmtif_ipaddr(lp, + pref->u.prefix4); + } + + /* Update TE parameters */ + update_linkparams(lp); + + /* Try to Schedule LSA */ + if ((ntohs(old_type.header.type) + != ntohs(lp->link_type.header.type) + || old_type.link_type.value + != lp->link_type.link_type.value) + || (ntohs(old_id.header.type) + != ntohs(lp->link_id.header.type) + || ntohl(old_id.value.s_addr) + != ntohl(lp->link_id.value.s_addr))) { + if + CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED) + ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA); + else ospf_mpls_te_lsa_schedule(lp, + REORIGINATE_THIS_LSA); + } + break; + default: + lp->link_type.header.type = htons(0); + lp->link_id.header.type = htons(0); + + if + CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED) + ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA); + break; + } out: - return; - + return; } -static void -ospf_mpls_te_nsm_change (struct ospf_neighbor *nbr, int old_state) +static void ospf_mpls_te_nsm_change(struct ospf_neighbor *nbr, int old_state) { - /* Nothing to do here */ - return; + /* Nothing to do here */ + return; } /*------------------------------------------------------------------------* * Followings are OSPF protocol processing functions for MPLS-TE. *------------------------------------------------------------------------*/ -static void -build_tlv_header (struct stream *s, struct te_tlv_header *tlvh) -{ - stream_put (s, tlvh, sizeof (struct te_tlv_header)); - return; -} - -static void -build_router_tlv (struct stream *s) -{ - struct te_tlv_header *tlvh = &OspfMplsTE.router_addr.header; - if (ntohs (tlvh->type) != 0) - { - build_tlv_header (s, tlvh); - stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); - } - return; -} - -static void -build_link_subtlv (struct stream *s, struct te_tlv_header *tlvh) - { - - if ((tlvh != NULL) && (ntohs (tlvh->type) != 0)) - { - build_tlv_header (s, tlvh); - stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); - } - return; -} - -static void -build_link_tlv (struct stream *s, struct mpls_te_link *lp) -{ - set_linkparams_link_header (lp); - build_tlv_header (s, &lp->link_header.header); - - build_link_subtlv (s, &lp->link_type.header); - build_link_subtlv (s, &lp->link_id.header); - build_link_subtlv (s, &lp->lclif_ipaddr.header); - build_link_subtlv (s, &lp->rmtif_ipaddr.header); - build_link_subtlv (s, &lp->te_metric.header); - build_link_subtlv (s, &lp->max_bw.header); - build_link_subtlv (s, &lp->max_rsv_bw.header); - build_link_subtlv (s, &lp->unrsv_bw.header); - build_link_subtlv (s, &lp->rsc_clsclr.header); - build_link_subtlv (s, &lp->lrrid.header); - build_link_subtlv (s, &lp->llri.header); - build_link_subtlv (s, &lp->rip.header); - build_link_subtlv (s, &lp->ras.header); - build_link_subtlv (s, &lp->av_delay.header); - build_link_subtlv (s, &lp->mm_delay.header); - build_link_subtlv (s, &lp->delay_var.header); - build_link_subtlv (s, &lp->pkt_loss.header); - build_link_subtlv (s, &lp->res_bw.header); - build_link_subtlv (s, &lp->ava_bw.header); - build_link_subtlv (s, &lp->use_bw.header); - - return; -} - -static void -ospf_mpls_te_lsa_body_set (struct stream *s, struct mpls_te_link *lp) -{ - /* - * The router address TLV is type 1, and ... - * It must appear in exactly one - * Traffic Engineering LSA originated by a router. - */ - build_router_tlv (s); - - /* - * Only one Link TLV shall be carried in each LSA, allowing for fine - * granularity changes in topology. - */ - build_link_tlv (s, lp); - return; +static void build_tlv_header(struct stream *s, struct te_tlv_header *tlvh) +{ + stream_put(s, tlvh, sizeof(struct te_tlv_header)); + return; +} + +static void build_router_tlv(struct stream *s) +{ + struct te_tlv_header *tlvh = &OspfMplsTE.router_addr.header; + if (ntohs(tlvh->type) != 0) { + build_tlv_header(s, tlvh); + stream_put(s, tlvh + 1, TLV_BODY_SIZE(tlvh)); + } + return; +} + +static void build_link_subtlv(struct stream *s, struct te_tlv_header *tlvh) +{ + + if ((tlvh != NULL) && (ntohs(tlvh->type) != 0)) { + build_tlv_header(s, tlvh); + stream_put(s, tlvh + 1, TLV_BODY_SIZE(tlvh)); + } + return; +} + +static void build_link_tlv(struct stream *s, struct mpls_te_link *lp) +{ + set_linkparams_link_header(lp); + build_tlv_header(s, &lp->link_header.header); + + build_link_subtlv(s, &lp->link_type.header); + build_link_subtlv(s, &lp->link_id.header); + build_link_subtlv(s, &lp->lclif_ipaddr.header); + build_link_subtlv(s, &lp->rmtif_ipaddr.header); + build_link_subtlv(s, &lp->te_metric.header); + build_link_subtlv(s, &lp->max_bw.header); + build_link_subtlv(s, &lp->max_rsv_bw.header); + build_link_subtlv(s, &lp->unrsv_bw.header); + build_link_subtlv(s, &lp->rsc_clsclr.header); + build_link_subtlv(s, &lp->lrrid.header); + build_link_subtlv(s, &lp->llri.header); + build_link_subtlv(s, &lp->rip.header); + build_link_subtlv(s, &lp->ras.header); + build_link_subtlv(s, &lp->av_delay.header); + build_link_subtlv(s, &lp->mm_delay.header); + build_link_subtlv(s, &lp->delay_var.header); + build_link_subtlv(s, &lp->pkt_loss.header); + build_link_subtlv(s, &lp->res_bw.header); + build_link_subtlv(s, &lp->ava_bw.header); + build_link_subtlv(s, &lp->use_bw.header); + + return; +} + +static void ospf_mpls_te_lsa_body_set(struct stream *s, struct mpls_te_link *lp) +{ + /* + * The router address TLV is type 1, and ... + * It must appear in exactly one + * Traffic Engineering LSA originated by a router. + */ + build_router_tlv(s); + + /* + * Only one Link TLV shall be carried in each LSA, allowing for fine + * granularity changes in topology. + */ + build_link_tlv(s, lp); + return; } /* Create new opaque-LSA. */ -static struct ospf_lsa * -ospf_mpls_te_lsa_new (struct ospf_area *area, struct mpls_te_link *lp) -{ - struct stream *s; - struct lsa_header *lsah; - struct ospf_lsa *new = NULL; - u_char options, lsa_type = 0; - struct in_addr lsa_id; - u_int32_t tmp; - u_int16_t length; - - /* Create a stream for LSA. */ - if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL) - { - zlog_warn ("ospf_mpls_te_lsa_new: stream_new() ?"); - goto out; - } - lsah = (struct lsa_header *) STREAM_DATA (s); - - options = OSPF_OPTION_O; /* Don't forget this :-) */ - - /* Set opaque-LSA header fields depending of the type of RFC */ - if (IS_INTER_AS (lp->type)) - { - if IS_FLOOD_AS (lp->type) - { - options |= OSPF_OPTION_E; /* Enable AS external as we flood Inter-AS with Opaque Type 11 */ - lsa_type = OSPF_OPAQUE_AS_LSA; - } - else - { - options |= LSA_OPTIONS_GET (area); /* Get area default option */ - options |= LSA_OPTIONS_NSSA_GET (area); - lsa_type = OSPF_OPAQUE_AREA_LSA; - } - tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_INTER_AS_LSA, lp->instance); - lsa_id.s_addr = htonl (tmp); - - struct ospf *top = ospf_lookup (); - - lsa_header_set (s, options, lsa_type, lsa_id, top->router_id); - } - else - { - options |= LSA_OPTIONS_GET (area); /* Get area default option */ - options |= LSA_OPTIONS_NSSA_GET (area); - lsa_type = OSPF_OPAQUE_AREA_LSA; - tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, lp->instance); - lsa_id.s_addr = htonl (tmp); - lsa_header_set (s, options, lsa_type, lsa_id, area->ospf->router_id); - } - - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("LSA[Type%d:%s]: Create an Opaque-LSA/MPLS-TE instance", - lsa_type, inet_ntoa (lsa_id)); - - /* Set opaque-LSA body fields. */ - ospf_mpls_te_lsa_body_set (s, lp); - - /* Set length. */ - length = stream_get_endp (s); - lsah->length = htons (length); - - /* Now, create an OSPF LSA instance. */ - if ((new = ospf_lsa_new ()) == NULL) - { - zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_new() ?"); - stream_free (s); - goto out; - } - if ((new->data = ospf_lsa_data_new (length)) == NULL) - { - zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_data_new() ?"); - ospf_lsa_unlock (&new); - new = NULL; - stream_free (s); - goto out; - } - - new->area = area; - SET_FLAG (new->flags, OSPF_LSA_SELF); - memcpy (new->data, lsah, length); - stream_free (s); +static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf_area *area, + struct mpls_te_link *lp) +{ + struct stream *s; + struct lsa_header *lsah; + struct ospf_lsa *new = NULL; + u_char options, lsa_type = 0; + struct in_addr lsa_id; + u_int32_t tmp; + u_int16_t length; + + /* Create a stream for LSA. */ + if ((s = stream_new(OSPF_MAX_LSA_SIZE)) == NULL) { + zlog_warn("ospf_mpls_te_lsa_new: stream_new() ?"); + goto out; + } + lsah = (struct lsa_header *)STREAM_DATA(s); + + options = OSPF_OPTION_O; /* Don't forget this :-) */ + + /* Set opaque-LSA header fields depending of the type of RFC */ + if (IS_INTER_AS(lp->type)) { + if + IS_FLOOD_AS(lp->type) + { + options |= OSPF_OPTION_E; /* Enable AS external + as we flood + Inter-AS with + Opaque Type 11 */ + lsa_type = OSPF_OPAQUE_AS_LSA; + } + else { + options |= LSA_OPTIONS_GET( + area); /* Get area default option */ + options |= LSA_OPTIONS_NSSA_GET(area); + lsa_type = OSPF_OPAQUE_AREA_LSA; + } + tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_INTER_AS_LSA, lp->instance); + lsa_id.s_addr = htonl(tmp); + + struct ospf *top = ospf_lookup(); + + lsa_header_set(s, options, lsa_type, lsa_id, top->router_id); + } else { + options |= LSA_OPTIONS_GET(area); /* Get area default option */ + options |= LSA_OPTIONS_NSSA_GET(area); + lsa_type = OSPF_OPAQUE_AREA_LSA; + tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, + lp->instance); + lsa_id.s_addr = htonl(tmp); + lsa_header_set(s, options, lsa_type, lsa_id, + area->ospf->router_id); + } + + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) + zlog_debug( + "LSA[Type%d:%s]: Create an Opaque-LSA/MPLS-TE instance", + lsa_type, inet_ntoa(lsa_id)); + + /* Set opaque-LSA body fields. */ + ospf_mpls_te_lsa_body_set(s, lp); + + /* Set length. */ + length = stream_get_endp(s); + lsah->length = htons(length); + + /* Now, create an OSPF LSA instance. */ + if ((new = ospf_lsa_new()) == NULL) { + zlog_warn("ospf_mpls_te_lsa_new: ospf_lsa_new() ?"); + stream_free(s); + goto out; + } + if ((new->data = ospf_lsa_data_new(length)) == NULL) { + zlog_warn("ospf_mpls_te_lsa_new: ospf_lsa_data_new() ?"); + ospf_lsa_unlock(&new); + new = NULL; + stream_free(s); + goto out; + } + + new->area = area; + SET_FLAG(new->flags, OSPF_LSA_SELF); + memcpy(new->data, lsah, length); + stream_free(s); out: - return new; -} - -static int -ospf_mpls_te_lsa_originate1 (struct ospf_area *area, struct mpls_te_link *lp) -{ - struct ospf_lsa *new; - int rc = -1; - - /* Create new Opaque-LSA/MPLS-TE instance. */ - if ((new = ospf_mpls_te_lsa_new (area, lp)) == NULL) - { - zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_mpls_te_lsa_new() ?"); - goto out; - } - - /* Install this LSA into LSDB. */ - if (ospf_lsa_install (area->ospf, NULL/*oi*/, new) == NULL) - { - zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_lsa_install() ?"); - ospf_lsa_unlock (&new); - goto out; - } - - /* Now this link-parameter entry has associated LSA. */ - SET_FLAG (lp->flags, LPFLG_LSA_ENGAGED); - /* Update new LSA origination count. */ - area->ospf->lsa_originate_count++; - - /* Flood new LSA through area. */ - ospf_flood_through_area (area, NULL/*nbr*/, new); - - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - { - char area_id[INET_ADDRSTRLEN]; - strcpy (area_id, inet_ntoa (area->area_id)); - zlog_debug ("LSA[Type%d:%s]: Originate Opaque-LSA/MPLS-TE: Area(%s), Link(%s)", - new->data->type, inet_ntoa (new->data->id), area_id, lp->ifp->name); - ospf_lsa_header_dump (new->data); - } - - rc = 0; + return new; +} + +static int ospf_mpls_te_lsa_originate1(struct ospf_area *area, + struct mpls_te_link *lp) +{ + struct ospf_lsa *new; + int rc = -1; + + /* Create new Opaque-LSA/MPLS-TE instance. */ + if ((new = ospf_mpls_te_lsa_new(area, lp)) == NULL) { + zlog_warn( + "ospf_mpls_te_lsa_originate1: ospf_mpls_te_lsa_new() ?"); + goto out; + } + + /* Install this LSA into LSDB. */ + if (ospf_lsa_install(area->ospf, NULL /*oi*/, new) == NULL) { + zlog_warn("ospf_mpls_te_lsa_originate1: ospf_lsa_install() ?"); + ospf_lsa_unlock(&new); + goto out; + } + + /* Now this link-parameter entry has associated LSA. */ + SET_FLAG(lp->flags, LPFLG_LSA_ENGAGED); + /* Update new LSA origination count. */ + area->ospf->lsa_originate_count++; + + /* Flood new LSA through area. */ + ospf_flood_through_area(area, NULL /*nbr*/, new); + + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + char area_id[INET_ADDRSTRLEN]; + strcpy(area_id, inet_ntoa(area->area_id)); + zlog_debug( + "LSA[Type%d:%s]: Originate Opaque-LSA/MPLS-TE: Area(%s), Link(%s)", + new->data->type, inet_ntoa(new->data->id), area_id, + lp->ifp->name); + ospf_lsa_header_dump(new->data); + } + + rc = 0; out: - return rc; -} - -static int -ospf_mpls_te_lsa_originate_area (void *arg) -{ - struct ospf_area *area = (struct ospf_area *) arg; - struct listnode *node, *nnode; - struct mpls_te_link *lp; - int rc = -1; - - if (OspfMplsTE.status == disabled) - { - zlog_info ("ospf_mpls_te_lsa_originate_area: MPLS-TE is disabled now."); - rc = 0; /* This is not an error case. */ - goto out; - } - - for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp)) - { - /* Process only enabled LSA with area scope flooding */ - if (!CHECK_FLAG (lp->flags, LPFLG_LSA_ACTIVE) || IS_FLOOD_AS (lp->type)) - continue; - - if (lp->area == NULL) - continue; - - if (! IPV4_ADDR_SAME (&lp->area->area_id, &area->area_id)) - continue; - - if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED) - { - if CHECK_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH) - { - UNSET_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH); - zlog_warn ("OSPF MPLS-TE (ospf_mpls_te_lsa_originate_area): Refresh instead of Originate"); - ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA); - } - continue; - } - if (! is_mandated_params_set (lp)) - { - zlog_warn ("ospf_mpls_te_lsa_originate_area: Link(%s) lacks some mandated MPLS-TE parameters.", - lp->ifp ? lp->ifp->name : "?"); - continue; - } - - /* Ok, let's try to originate an LSA for this area and Link. */ - if (IS_DEBUG_OSPF_TE) - zlog_debug ("MPLS-TE(ospf_mpls_te_lsa_originate_area) Let's finally reoriginate the LSA %d through the Area %s for Link %s", - lp->instance, inet_ntoa (area->area_id), lp->ifp ? lp->ifp->name : "?"); - if (ospf_mpls_te_lsa_originate1 (area, lp) != 0) - goto out; - } - - rc = 0; + return rc; +} + +static int ospf_mpls_te_lsa_originate_area(void *arg) +{ + struct ospf_area *area = (struct ospf_area *)arg; + struct listnode *node, *nnode; + struct mpls_te_link *lp; + int rc = -1; + + if (OspfMplsTE.status == disabled) { + zlog_info( + "ospf_mpls_te_lsa_originate_area: MPLS-TE is disabled now."); + rc = 0; /* This is not an error case. */ + goto out; + } + + for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) { + /* Process only enabled LSA with area scope flooding */ + if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE) + || IS_FLOOD_AS(lp->type)) + continue; + + if (lp->area == NULL) + continue; + + if (!IPV4_ADDR_SAME(&lp->area->area_id, &area->area_id)) + continue; + + if + CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED) + { + if + CHECK_FLAG(lp->flags, + LPFLG_LSA_FORCED_REFRESH) + { + UNSET_FLAG( + lp->flags, + LPFLG_LSA_FORCED_REFRESH); + zlog_warn( + "OSPF MPLS-TE (ospf_mpls_te_lsa_originate_area): Refresh instead of Originate"); + ospf_mpls_te_lsa_schedule( + lp, REFRESH_THIS_LSA); + } + continue; + } + if (!is_mandated_params_set(lp)) { + zlog_warn( + "ospf_mpls_te_lsa_originate_area: Link(%s) lacks some mandated MPLS-TE parameters.", + lp->ifp ? lp->ifp->name : "?"); + continue; + } + + /* Ok, let's try to originate an LSA for this area and Link. */ + if (IS_DEBUG_OSPF_TE) + zlog_debug( + "MPLS-TE(ospf_mpls_te_lsa_originate_area) Let's finally reoriginate the LSA %d through the Area %s for Link %s", + lp->instance, inet_ntoa(area->area_id), + lp->ifp ? lp->ifp->name : "?"); + if (ospf_mpls_te_lsa_originate1(area, lp) != 0) + goto out; + } + + rc = 0; out: - return rc; -} - -static int -ospf_mpls_te_lsa_originate2 (struct ospf *top, struct mpls_te_link *lp) -{ - struct ospf_lsa *new; - int rc = -1; - - /* Create new Opaque-LSA/Inter-AS instance. */ - if ((new = ospf_mpls_te_lsa_new (NULL, lp)) == NULL) - { - zlog_warn ("ospf_mpls_te_lsa_originate2: ospf_router_info_lsa_new() ?"); - goto out; - } - - /* Install this LSA into LSDB. */ - if (ospf_lsa_install (top, NULL /*oi */ , new) == NULL) - { - zlog_warn ("ospf_mpls_te_lsa_originate2: ospf_lsa_install() ?"); - ospf_lsa_unlock (&new); - goto out; - } - - /* Now this Router Info parameter entry has associated LSA. */ - SET_FLAG (lp->flags, LPFLG_LSA_ENGAGED); - /* Update new LSA origination count. */ - top->lsa_originate_count++; - - /* Flood new LSA through AS. */ - ospf_flood_through_as (top, NULL /*nbr */ , new); - - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - { - zlog_debug ("LSA[Type%d:%s]: Originate Opaque-LSA/MPLS-TE Inter-AS", - new->data->type, inet_ntoa (new->data->id)); - ospf_lsa_header_dump (new->data); - } - - rc = 0; -out:return rc; -} - -static int -ospf_mpls_te_lsa_originate_as (void *arg) -{ - struct ospf *top; - struct ospf_area *area; - struct listnode *node, *nnode; - struct mpls_te_link *lp; - int rc = -1; - - if ((OspfMplsTE.status == disabled) || (OspfMplsTE.inter_as == Disable)) - { - zlog_info - ("ospf_mpls_te_lsa_originate_as: MPLS-TE Inter-AS is disabled for now."); - rc = 0; /* This is not an error case. */ - goto out; - } - - for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp)) - { - /* Process only enabled INTER_AS Links or Pseudo-Links */ - if (!CHECK_FLAG (lp->flags, LPFLG_LSA_ACTIVE) || !IS_INTER_AS (lp->type)) - continue; - - if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED) - { - if CHECK_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH) - { - UNSET_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH); - ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA); - } - continue; - } - if (!is_mandated_params_set (lp)) - { - zlog_warn ("ospf_mpls_te_lsa_originate_as: Link(%s) lacks some mandated MPLS-TE parameters.", - lp->ifp ? lp->ifp->name : "?"); - continue; - } - - /* Ok, let's try to originate an LSA for this AS and Link. */ - if (IS_DEBUG_OSPF_TE) - zlog_debug ("MPLS-TE(ospf_mpls_te_lsa_originate_as) Let's finally re-originate the Inter-AS LSA %d through the %s for Link %s", - lp->instance, IS_FLOOD_AS (lp->type) ? "AS" : "Area", lp->ifp ? lp->ifp->name : "Unknown"); - - if (IS_FLOOD_AS (lp->type)) - { - top = (struct ospf *) arg; - ospf_mpls_te_lsa_originate2 (top, lp); - } - else - { - area = (struct ospf_area *) arg; - ospf_mpls_te_lsa_originate1 (area, lp); - } - } - - rc = 0; -out:return rc; -} - -static struct ospf_lsa * -ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa) -{ - struct mpls_te_link *lp; - struct ospf_area *area = lsa->area; - struct ospf *top; - struct ospf_lsa *new = NULL; - - if (OspfMplsTE.status == disabled) - { - /* - * This LSA must have flushed before due to MPLS-TE status change. - * It seems a slip among routers in the routing domain. - */ - zlog_info ("ospf_mpls_te_lsa_refresh: MPLS-TE is disabled now."); - lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */ - } - - /* At first, resolve lsa/lp relationship. */ - if ((lp = lookup_linkparams_by_instance (lsa)) == NULL) - { - zlog_warn ("ospf_mpls_te_lsa_refresh: Invalid parameter?"); - lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */ - } - - /* Check if lp was not disable in the interval */ - if (!CHECK_FLAG (lp->flags, LPFLG_LSA_ACTIVE)) - { - zlog_warn ("ospf_mpls_te_lsa_refresh: lp was disabled: Flush it!"); - lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */ - } - - /* If the lsa's age reached to MaxAge, start flushing procedure. */ - if (IS_LSA_MAXAGE (lsa)) - { - if (lp) - UNSET_FLAG (lp->flags, LPFLG_LSA_ENGAGED); - ospf_opaque_lsa_flush_schedule (lsa); - goto out; - } - - /* Create new Opaque-LSA/MPLS-TE instance. */ - if ((new = ospf_mpls_te_lsa_new (area, lp)) == NULL) - { - zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_mpls_te_lsa_new() ?"); - goto out; - } - new->data->ls_seqnum = lsa_seqnum_increment (lsa); - - /* Install this LSA into LSDB. */ - /* Given "lsa" will be freed in the next function. */ - /* As area could be NULL i.e. when using OPAQUE_LSA_AS, we prefer to use ospf_lookup() to get ospf instance */ - if (area) - top = area->ospf; - else - top = ospf_lookup (); - - if (ospf_lsa_install (top, NULL /*oi */ , new) == NULL) - { - zlog_warn ("ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?"); - ospf_lsa_unlock (&new); - goto out; - } - - /* Flood updated LSA through AS or Area depending of the RFC of the link */ - if (IS_FLOOD_AS (lp->type)) - ospf_flood_through_as (top, NULL, new); - else - ospf_flood_through_area (area, NULL/*nbr*/, new); - - /* Debug logging. */ - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - { - zlog_debug ("LSA[Type%d:%s]: Refresh Opaque-LSA/MPLS-TE", - new->data->type, inet_ntoa (new->data->id)); - ospf_lsa_header_dump (new->data); - } + return rc; +} +static int ospf_mpls_te_lsa_originate2(struct ospf *top, + struct mpls_te_link *lp) +{ + struct ospf_lsa *new; + int rc = -1; + + /* Create new Opaque-LSA/Inter-AS instance. */ + if ((new = ospf_mpls_te_lsa_new(NULL, lp)) == NULL) { + zlog_warn( + "ospf_mpls_te_lsa_originate2: ospf_router_info_lsa_new() ?"); + goto out; + } + + /* Install this LSA into LSDB. */ + if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) { + zlog_warn("ospf_mpls_te_lsa_originate2: ospf_lsa_install() ?"); + ospf_lsa_unlock(&new); + goto out; + } + + /* Now this Router Info parameter entry has associated LSA. */ + SET_FLAG(lp->flags, LPFLG_LSA_ENGAGED); + /* Update new LSA origination count. */ + top->lsa_originate_count++; + + /* Flood new LSA through AS. */ + ospf_flood_through_as(top, NULL /*nbr */, new); + + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug( + "LSA[Type%d:%s]: Originate Opaque-LSA/MPLS-TE Inter-AS", + new->data->type, inet_ntoa(new->data->id)); + ospf_lsa_header_dump(new->data); + } + + rc = 0; +out: + return rc; +} + +static int ospf_mpls_te_lsa_originate_as(void *arg) +{ + struct ospf *top; + struct ospf_area *area; + struct listnode *node, *nnode; + struct mpls_te_link *lp; + int rc = -1; + + if ((OspfMplsTE.status == disabled) + || (OspfMplsTE.inter_as == Disable)) { + zlog_info( + "ospf_mpls_te_lsa_originate_as: MPLS-TE Inter-AS is disabled for now."); + rc = 0; /* This is not an error case. */ + goto out; + } + + for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) { + /* Process only enabled INTER_AS Links or Pseudo-Links */ + if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE) + || !IS_INTER_AS(lp->type)) + continue; + + if + CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED) + { + if + CHECK_FLAG(lp->flags, + LPFLG_LSA_FORCED_REFRESH) + { + UNSET_FLAG( + lp->flags, + LPFLG_LSA_FORCED_REFRESH); + ospf_mpls_te_lsa_schedule( + lp, REFRESH_THIS_LSA); + } + continue; + } + if (!is_mandated_params_set(lp)) { + zlog_warn( + "ospf_mpls_te_lsa_originate_as: Link(%s) lacks some mandated MPLS-TE parameters.", + lp->ifp ? lp->ifp->name : "?"); + continue; + } + + /* Ok, let's try to originate an LSA for this AS and Link. */ + if (IS_DEBUG_OSPF_TE) + zlog_debug( + "MPLS-TE(ospf_mpls_te_lsa_originate_as) Let's finally re-originate the Inter-AS LSA %d through the %s for Link %s", + lp->instance, + IS_FLOOD_AS(lp->type) ? "AS" : "Area", + lp->ifp ? lp->ifp->name : "Unknown"); + + if (IS_FLOOD_AS(lp->type)) { + top = (struct ospf *)arg; + ospf_mpls_te_lsa_originate2(top, lp); + } else { + area = (struct ospf_area *)arg; + ospf_mpls_te_lsa_originate1(area, lp); + } + } + + rc = 0; out: - return new; -} - -void -ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp, opcode_t opcode) -{ - struct ospf_lsa lsa; - struct lsa_header lsah; - struct ospf *top; - u_int32_t tmp; - - memset (&lsa, 0, sizeof (lsa)); - memset (&lsah, 0, sizeof (lsah)); - top = ospf_lookup (); - - /* Check if the pseudo link is ready to flood */ - if (!(CHECK_FLAG (lp->flags, LPFLG_LSA_ACTIVE)) - || !(IS_FLOOD_AREA (lp->type) || IS_FLOOD_AS (lp->type))) { - return; - } - - lsa.area = lp->area; - lsa.data = &lsah; - if (IS_FLOOD_AS (lp->type)) - { - lsah.type = OSPF_OPAQUE_AS_LSA; - tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_INTER_AS_LSA, lp->instance); - lsah.id.s_addr = htonl (tmp); - } - else - { - lsah.type = OSPF_OPAQUE_AREA_LSA; - if (IS_INTER_AS (lp->type)) - { - /* Set the area context if not know */ - if (lp->area == NULL) - lp->area = ospf_area_lookup_by_area_id (top, OspfMplsTE.interas_areaid); - /* Unable to set the area context. Abort! */ - if (lp->area == NULL) - { - zlog_warn ("MPLS-TE(ospf_mpls_te_lsa_schedule) Area context is null. Abort !"); - return; - } - tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_INTER_AS_LSA, lp->instance); - } - else - tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, lp->instance); - lsah.id.s_addr = htonl (tmp); - } - - switch (opcode) - { - case REORIGINATE_THIS_LSA: - if (IS_FLOOD_AS (lp->type)) - { - ospf_opaque_lsa_reoriginate_schedule ((void *) top, OSPF_OPAQUE_AS_LSA, - OPAQUE_TYPE_INTER_AS_LSA); - break; - } - - if (IS_FLOOD_AREA (lp->type)) - { - if (IS_INTER_AS (lp->type)) - ospf_opaque_lsa_reoriginate_schedule ((void *) lp->area, OSPF_OPAQUE_AREA_LSA, - OPAQUE_TYPE_INTER_AS_LSA); - else - ospf_opaque_lsa_reoriginate_schedule ((void *) lp->area, OSPF_OPAQUE_AREA_LSA, - OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA); - break; - } - break; - case REFRESH_THIS_LSA: - ospf_opaque_lsa_refresh_schedule (&lsa); - break; - case FLUSH_THIS_LSA: - /* Reset Activity flag */ - lp->flags = LPFLG_LSA_INACTIVE; - ospf_opaque_lsa_flush_schedule (&lsa); - break; - default: - zlog_warn ("ospf_mpls_te_lsa_schedule: Unknown opcode (%u)", opcode); - break; - } - - return; + return rc; +} + +static struct ospf_lsa *ospf_mpls_te_lsa_refresh(struct ospf_lsa *lsa) +{ + struct mpls_te_link *lp; + struct ospf_area *area = lsa->area; + struct ospf *top; + struct ospf_lsa *new = NULL; + + if (OspfMplsTE.status == disabled) { + /* + * This LSA must have flushed before due to MPLS-TE status + * change. + * It seems a slip among routers in the routing domain. + */ + zlog_info("ospf_mpls_te_lsa_refresh: MPLS-TE is disabled now."); + lsa->data->ls_age = + htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */ + } + + /* At first, resolve lsa/lp relationship. */ + if ((lp = lookup_linkparams_by_instance(lsa)) == NULL) { + zlog_warn("ospf_mpls_te_lsa_refresh: Invalid parameter?"); + lsa->data->ls_age = + htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */ + } + + /* Check if lp was not disable in the interval */ + if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE)) { + zlog_warn( + "ospf_mpls_te_lsa_refresh: lp was disabled: Flush it!"); + lsa->data->ls_age = + htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */ + } + + /* If the lsa's age reached to MaxAge, start flushing procedure. */ + if (IS_LSA_MAXAGE(lsa)) { + if (lp) + UNSET_FLAG(lp->flags, LPFLG_LSA_ENGAGED); + ospf_opaque_lsa_flush_schedule(lsa); + goto out; + } + + /* Create new Opaque-LSA/MPLS-TE instance. */ + if ((new = ospf_mpls_te_lsa_new(area, lp)) == NULL) { + zlog_warn("ospf_mpls_te_lsa_refresh: ospf_mpls_te_lsa_new() ?"); + goto out; + } + new->data->ls_seqnum = lsa_seqnum_increment(lsa); + + /* Install this LSA into LSDB. */ + /* Given "lsa" will be freed in the next function. */ + /* As area could be NULL i.e. when using OPAQUE_LSA_AS, we prefer to use + * ospf_lookup() to get ospf instance */ + if (area) + top = area->ospf; + else + top = ospf_lookup(); + + if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) { + zlog_warn("ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?"); + ospf_lsa_unlock(&new); + goto out; + } + + /* Flood updated LSA through AS or Area depending of the RFC of the link + */ + if (IS_FLOOD_AS(lp->type)) + ospf_flood_through_as(top, NULL, new); + else + ospf_flood_through_area(area, NULL /*nbr*/, new); + + /* Debug logging. */ + if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) { + zlog_debug("LSA[Type%d:%s]: Refresh Opaque-LSA/MPLS-TE", + new->data->type, inet_ntoa(new->data->id)); + ospf_lsa_header_dump(new->data); + } + +out: + return new; +} + +void ospf_mpls_te_lsa_schedule(struct mpls_te_link *lp, opcode_t opcode) +{ + struct ospf_lsa lsa; + struct lsa_header lsah; + struct ospf *top; + u_int32_t tmp; + + memset(&lsa, 0, sizeof(lsa)); + memset(&lsah, 0, sizeof(lsah)); + top = ospf_lookup(); + + /* Check if the pseudo link is ready to flood */ + if (!(CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE)) + || !(IS_FLOOD_AREA(lp->type) || IS_FLOOD_AS(lp->type))) { + return; + } + + lsa.area = lp->area; + lsa.data = &lsah; + if (IS_FLOOD_AS(lp->type)) { + lsah.type = OSPF_OPAQUE_AS_LSA; + tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_INTER_AS_LSA, lp->instance); + lsah.id.s_addr = htonl(tmp); + } else { + lsah.type = OSPF_OPAQUE_AREA_LSA; + if (IS_INTER_AS(lp->type)) { + /* Set the area context if not know */ + if (lp->area == NULL) + lp->area = ospf_area_lookup_by_area_id( + top, OspfMplsTE.interas_areaid); + /* Unable to set the area context. Abort! */ + if (lp->area == NULL) { + zlog_warn( + "MPLS-TE(ospf_mpls_te_lsa_schedule) Area context is null. Abort !"); + return; + } + tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_INTER_AS_LSA, + lp->instance); + } else + tmp = SET_OPAQUE_LSID( + OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, + lp->instance); + lsah.id.s_addr = htonl(tmp); + } + + switch (opcode) { + case REORIGINATE_THIS_LSA: + if (IS_FLOOD_AS(lp->type)) { + ospf_opaque_lsa_reoriginate_schedule( + (void *)top, OSPF_OPAQUE_AS_LSA, + OPAQUE_TYPE_INTER_AS_LSA); + break; + } + + if (IS_FLOOD_AREA(lp->type)) { + if (IS_INTER_AS(lp->type)) + ospf_opaque_lsa_reoriginate_schedule( + (void *)lp->area, OSPF_OPAQUE_AREA_LSA, + OPAQUE_TYPE_INTER_AS_LSA); + else + ospf_opaque_lsa_reoriginate_schedule( + (void *)lp->area, OSPF_OPAQUE_AREA_LSA, + OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA); + break; + } + break; + case REFRESH_THIS_LSA: + ospf_opaque_lsa_refresh_schedule(&lsa); + break; + case FLUSH_THIS_LSA: + /* Reset Activity flag */ + lp->flags = LPFLG_LSA_INACTIVE; + ospf_opaque_lsa_flush_schedule(&lsa); + break; + default: + zlog_warn("ospf_mpls_te_lsa_schedule: Unknown opcode (%u)", + opcode); + break; + } + + return; } @@ -1665,583 +1635,594 @@ ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp, opcode_t opcode) * Followings are vty session control functions. *------------------------------------------------------------------------*/ -static u_int16_t -show_vty_router_addr (struct vty *vty, struct te_tlv_header *tlvh) +static u_int16_t show_vty_router_addr(struct vty *vty, + struct te_tlv_header *tlvh) { - struct te_tlv_router_addr *top = (struct te_tlv_router_addr *) tlvh; + struct te_tlv_router_addr *top = (struct te_tlv_router_addr *)tlvh; - if (vty != NULL) - vty_out (vty, " Router-Address: %s\n",inet_ntoa(top->value)); - else - zlog_debug (" Router-Address: %s", inet_ntoa (top->value)); + if (vty != NULL) + vty_out(vty, " Router-Address: %s\n", inet_ntoa(top->value)); + else + zlog_debug(" Router-Address: %s", inet_ntoa(top->value)); - return TLV_SIZE (tlvh); + return TLV_SIZE(tlvh); } -static u_int16_t -show_vty_link_header (struct vty *vty, struct te_tlv_header *tlvh) +static u_int16_t show_vty_link_header(struct vty *vty, + struct te_tlv_header *tlvh) { - struct te_tlv_link *top = (struct te_tlv_link *) tlvh; + struct te_tlv_link *top = (struct te_tlv_link *)tlvh; - if (vty != NULL) - vty_out (vty, " Link: %u octets of data\n",ntohs(top->header.length)); - else - zlog_debug (" Link: %u octets of data", ntohs (top->header.length)); + if (vty != NULL) + vty_out(vty, " Link: %u octets of data\n", + ntohs(top->header.length)); + else + zlog_debug(" Link: %u octets of data", + ntohs(top->header.length)); - return TLV_HDR_SIZE; /* Here is special, not "TLV_SIZE". */ + return TLV_HDR_SIZE; /* Here is special, not "TLV_SIZE". */ } -static u_int16_t -show_vty_link_subtlv_link_type (struct vty *vty, struct te_tlv_header *tlvh) +static u_int16_t show_vty_link_subtlv_link_type(struct vty *vty, + struct te_tlv_header *tlvh) { - struct te_link_subtlv_link_type *top; - const char *cp = "Unknown"; + struct te_link_subtlv_link_type *top; + const char *cp = "Unknown"; - top = (struct te_link_subtlv_link_type *) tlvh; - switch (top->link_type.value) - { - case LINK_TYPE_SUBTLV_VALUE_PTP: - cp = "Point-to-point"; - break; - case LINK_TYPE_SUBTLV_VALUE_MA: - cp = "Multiaccess"; - break; - default: - break; - } + top = (struct te_link_subtlv_link_type *)tlvh; + switch (top->link_type.value) { + case LINK_TYPE_SUBTLV_VALUE_PTP: + cp = "Point-to-point"; + break; + case LINK_TYPE_SUBTLV_VALUE_MA: + cp = "Multiaccess"; + break; + default: + break; + } - if (vty != NULL) - vty_out (vty, " Link-Type: %s (%u)\n", cp,top->link_type.value); - else - zlog_debug (" Link-Type: %s (%u)", cp, top->link_type.value); + if (vty != NULL) + vty_out(vty, " Link-Type: %s (%u)\n", cp, + top->link_type.value); + else + zlog_debug(" Link-Type: %s (%u)", cp, top->link_type.value); - return TLV_SIZE (tlvh); + return TLV_SIZE(tlvh); } -static u_int16_t -show_vty_link_subtlv_link_id (struct vty *vty, struct te_tlv_header *tlvh) +static u_int16_t show_vty_link_subtlv_link_id(struct vty *vty, + struct te_tlv_header *tlvh) { - struct te_link_subtlv_link_id *top; + struct te_link_subtlv_link_id *top; - top = (struct te_link_subtlv_link_id *) tlvh; - if (vty != NULL) - vty_out (vty, " Link-ID: %s\n", inet_ntoa(top->value)); - else - zlog_debug (" Link-ID: %s", inet_ntoa (top->value)); + top = (struct te_link_subtlv_link_id *)tlvh; + if (vty != NULL) + vty_out(vty, " Link-ID: %s\n", inet_ntoa(top->value)); + else + zlog_debug(" Link-ID: %s", inet_ntoa(top->value)); - return TLV_SIZE (tlvh); + return TLV_SIZE(tlvh); } -static u_int16_t -show_vty_link_subtlv_lclif_ipaddr (struct vty *vty, - struct te_tlv_header *tlvh) +static u_int16_t show_vty_link_subtlv_lclif_ipaddr(struct vty *vty, + struct te_tlv_header *tlvh) { - struct te_link_subtlv_lclif_ipaddr *top; - int i, n; + struct te_link_subtlv_lclif_ipaddr *top; + int i, n; - top = (struct te_link_subtlv_lclif_ipaddr *) tlvh; - n = ntohs (tlvh->length) / sizeof (top->value[0]); + top = (struct te_link_subtlv_lclif_ipaddr *)tlvh; + n = ntohs(tlvh->length) / sizeof(top->value[0]); - if (vty != NULL) - vty_out (vty, " Local Interface IP Address(es): %d\n", n); - else - zlog_debug (" Local Interface IP Address(es): %d", n); + if (vty != NULL) + vty_out(vty, " Local Interface IP Address(es): %d\n", n); + else + zlog_debug(" Local Interface IP Address(es): %d", n); - for (i = 0; i < n; i++) - { - if (vty != NULL) - vty_out (vty, " #%d: %s\n", i,inet_ntoa(top->value[i])); - else - zlog_debug (" #%d: %s", i, inet_ntoa (top->value[i])); - } - return TLV_SIZE (tlvh); + for (i = 0; i < n; i++) { + if (vty != NULL) + vty_out(vty, " #%d: %s\n", i, + inet_ntoa(top->value[i])); + else + zlog_debug(" #%d: %s", i, + inet_ntoa(top->value[i])); + } + return TLV_SIZE(tlvh); } -static u_int16_t -show_vty_link_subtlv_rmtif_ipaddr (struct vty *vty, - struct te_tlv_header *tlvh) +static u_int16_t show_vty_link_subtlv_rmtif_ipaddr(struct vty *vty, + struct te_tlv_header *tlvh) { - struct te_link_subtlv_rmtif_ipaddr *top; - int i, n; + struct te_link_subtlv_rmtif_ipaddr *top; + int i, n; - top = (struct te_link_subtlv_rmtif_ipaddr *) tlvh; - n = ntohs (tlvh->length) / sizeof (top->value[0]); - if (vty != NULL) - vty_out (vty, " Remote Interface IP Address(es): %d\n", n); - else - zlog_debug (" Remote Interface IP Address(es): %d", n); + top = (struct te_link_subtlv_rmtif_ipaddr *)tlvh; + n = ntohs(tlvh->length) / sizeof(top->value[0]); + if (vty != NULL) + vty_out(vty, " Remote Interface IP Address(es): %d\n", n); + else + zlog_debug(" Remote Interface IP Address(es): %d", n); - for (i = 0; i < n; i++) - { - if (vty != NULL) - vty_out (vty, " #%d: %s\n", i,inet_ntoa(top->value[i])); - else - zlog_debug (" #%d: %s", i, inet_ntoa (top->value[i])); - } - return TLV_SIZE (tlvh); + for (i = 0; i < n; i++) { + if (vty != NULL) + vty_out(vty, " #%d: %s\n", i, + inet_ntoa(top->value[i])); + else + zlog_debug(" #%d: %s", i, + inet_ntoa(top->value[i])); + } + return TLV_SIZE(tlvh); } -static u_int16_t -show_vty_link_subtlv_te_metric (struct vty *vty, struct te_tlv_header *tlvh) +static u_int16_t show_vty_link_subtlv_te_metric(struct vty *vty, + struct te_tlv_header *tlvh) { - struct te_link_subtlv_te_metric *top; + struct te_link_subtlv_te_metric *top; - top = (struct te_link_subtlv_te_metric *) tlvh; - if (vty != NULL) - vty_out (vty, " Traffic Engineering Metric: %u\n", - (u_int32_t)ntohl(top->value)); - else - zlog_debug (" Traffic Engineering Metric: %u", - (u_int32_t) ntohl (top->value)); + top = (struct te_link_subtlv_te_metric *)tlvh; + if (vty != NULL) + vty_out(vty, " Traffic Engineering Metric: %u\n", + (u_int32_t)ntohl(top->value)); + else + zlog_debug(" Traffic Engineering Metric: %u", + (u_int32_t)ntohl(top->value)); - return TLV_SIZE (tlvh); + return TLV_SIZE(tlvh); } -static u_int16_t -show_vty_link_subtlv_max_bw (struct vty *vty, struct te_tlv_header *tlvh) +static u_int16_t show_vty_link_subtlv_max_bw(struct vty *vty, + struct te_tlv_header *tlvh) { - struct te_link_subtlv_max_bw *top; - float fval; + struct te_link_subtlv_max_bw *top; + float fval; - top = (struct te_link_subtlv_max_bw *) tlvh; - fval = ntohf (top->value); + top = (struct te_link_subtlv_max_bw *)tlvh; + fval = ntohf(top->value); - if (vty != NULL) - vty_out (vty, " Maximum Bandwidth: %g (Bytes/sec)\n", fval); - else - zlog_debug (" Maximum Bandwidth: %g (Bytes/sec)", fval); + if (vty != NULL) + vty_out(vty, " Maximum Bandwidth: %g (Bytes/sec)\n", fval); + else + zlog_debug(" Maximum Bandwidth: %g (Bytes/sec)", fval); - return TLV_SIZE (tlvh); + return TLV_SIZE(tlvh); } -static u_int16_t -show_vty_link_subtlv_max_rsv_bw (struct vty *vty, struct te_tlv_header *tlvh) +static u_int16_t show_vty_link_subtlv_max_rsv_bw(struct vty *vty, + struct te_tlv_header *tlvh) { - struct te_link_subtlv_max_rsv_bw *top; - float fval; + struct te_link_subtlv_max_rsv_bw *top; + float fval; - top = (struct te_link_subtlv_max_rsv_bw *) tlvh; - fval = ntohf (top->value); + top = (struct te_link_subtlv_max_rsv_bw *)tlvh; + fval = ntohf(top->value); - if (vty != NULL) - vty_out (vty, " Maximum Reservable Bandwidth: %g (Bytes/sec)\n",fval); - else - zlog_debug (" Maximum Reservable Bandwidth: %g (Bytes/sec)", fval); + if (vty != NULL) + vty_out(vty, " Maximum Reservable Bandwidth: %g (Bytes/sec)\n", + fval); + else + zlog_debug(" Maximum Reservable Bandwidth: %g (Bytes/sec)", + fval); - return TLV_SIZE (tlvh); + return TLV_SIZE(tlvh); } -static u_int16_t -show_vty_link_subtlv_unrsv_bw (struct vty *vty, struct te_tlv_header *tlvh) +static u_int16_t show_vty_link_subtlv_unrsv_bw(struct vty *vty, + struct te_tlv_header *tlvh) { - struct te_link_subtlv_unrsv_bw *top; - float fval1, fval2; - int i; + struct te_link_subtlv_unrsv_bw *top; + float fval1, fval2; + int i; - top = (struct te_link_subtlv_unrsv_bw *) tlvh; - if (vty != NULL) - vty_out (vty, " Unreserved Bandwidth per Class Type in Byte/s:\n"); - else - zlog_debug (" Unreserved Bandwidth per Class Type in Byte/s:"); - for (i = 0; i < MAX_CLASS_TYPE; i+=2) - { - fval1 = ntohf (top->value[i]); - fval2 = ntohf (top->value[i+1]); + top = (struct te_link_subtlv_unrsv_bw *)tlvh; + if (vty != NULL) + vty_out(vty, + " Unreserved Bandwidth per Class Type in Byte/s:\n"); + else + zlog_debug( + " Unreserved Bandwidth per Class Type in Byte/s:"); + for (i = 0; i < MAX_CLASS_TYPE; i += 2) { + fval1 = ntohf(top->value[i]); + fval2 = ntohf(top->value[i + 1]); - if (vty != NULL) - vty_out (vty, " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n", - i, fval1, i+1, fval2); - else - zlog_debug (" [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)", - i, fval1, i+1, fval2); - } + if (vty != NULL) + vty_out(vty, + " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n", + i, fval1, i + 1, fval2); + else + zlog_debug( + " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)", + i, fval1, i + 1, fval2); + } - return TLV_SIZE (tlvh); + return TLV_SIZE(tlvh); } -static u_int16_t -show_vty_link_subtlv_rsc_clsclr (struct vty *vty, struct te_tlv_header *tlvh) +static u_int16_t show_vty_link_subtlv_rsc_clsclr(struct vty *vty, + struct te_tlv_header *tlvh) { - struct te_link_subtlv_rsc_clsclr *top; + struct te_link_subtlv_rsc_clsclr *top; - top = (struct te_link_subtlv_rsc_clsclr *) tlvh; - if (vty != NULL) - vty_out (vty, " Resource class/color: 0x%x\n", - (u_int32_t)ntohl(top->value)); - else - zlog_debug (" Resource Class/Color: 0x%x", - (u_int32_t) ntohl (top->value)); + top = (struct te_link_subtlv_rsc_clsclr *)tlvh; + if (vty != NULL) + vty_out(vty, " Resource class/color: 0x%x\n", + (u_int32_t)ntohl(top->value)); + else + zlog_debug(" Resource Class/Color: 0x%x", + (u_int32_t)ntohl(top->value)); - return TLV_SIZE (tlvh); + return TLV_SIZE(tlvh); } -static u_int16_t -show_vty_link_subtlv_lrrid (struct vty *vty, struct te_tlv_header *tlvh) +static u_int16_t show_vty_link_subtlv_lrrid(struct vty *vty, + struct te_tlv_header *tlvh) { - struct te_link_subtlv_lrrid *top; + struct te_link_subtlv_lrrid *top; - top = (struct te_link_subtlv_lrrid *) tlvh; + top = (struct te_link_subtlv_lrrid *)tlvh; - if (vty != NULL) - { - vty_out (vty, " Local TE Router ID: %s\n",inet_ntoa(top->local)); - vty_out (vty, " Remote TE Router ID: %s\n",inet_ntoa(top->remote)); - } - else - { - zlog_debug (" Local TE Router ID: %s", inet_ntoa (top->local)); - zlog_debug (" Remote TE Router ID: %s", inet_ntoa (top->remote)); - } + if (vty != NULL) { + vty_out(vty, " Local TE Router ID: %s\n", + inet_ntoa(top->local)); + vty_out(vty, " Remote TE Router ID: %s\n", + inet_ntoa(top->remote)); + } else { + zlog_debug(" Local TE Router ID: %s", + inet_ntoa(top->local)); + zlog_debug(" Remote TE Router ID: %s", + inet_ntoa(top->remote)); + } - return TLV_SIZE (tlvh); + return TLV_SIZE(tlvh); } -static u_int16_t -show_vty_link_subtlv_llri (struct vty *vty, struct te_tlv_header *tlvh) +static u_int16_t show_vty_link_subtlv_llri(struct vty *vty, + struct te_tlv_header *tlvh) { - struct te_link_subtlv_llri *top; + struct te_link_subtlv_llri *top; - top = (struct te_link_subtlv_llri *) tlvh; + top = (struct te_link_subtlv_llri *)tlvh; - if (vty != NULL) - { - vty_out (vty, " Link Local ID: %d\n",(u_int32_t)ntohl(top->local)); - vty_out (vty, " Link Remote ID: %d\n",(u_int32_t)ntohl(top->remote)); - } - else - { - zlog_debug (" Link Local ID: %d", (u_int32_t) ntohl (top->local)); - zlog_debug (" Link Remote ID: %d", (u_int32_t) ntohl (top->remote)); - } + if (vty != NULL) { + vty_out(vty, " Link Local ID: %d\n", + (u_int32_t)ntohl(top->local)); + vty_out(vty, " Link Remote ID: %d\n", + (u_int32_t)ntohl(top->remote)); + } else { + zlog_debug(" Link Local ID: %d", + (u_int32_t)ntohl(top->local)); + zlog_debug(" Link Remote ID: %d", + (u_int32_t)ntohl(top->remote)); + } - return TLV_SIZE (tlvh); + return TLV_SIZE(tlvh); } -static u_int16_t -show_vty_link_subtlv_rip (struct vty *vty, struct te_tlv_header *tlvh) +static u_int16_t show_vty_link_subtlv_rip(struct vty *vty, + struct te_tlv_header *tlvh) { - struct te_link_subtlv_rip *top; + struct te_link_subtlv_rip *top; - top = (struct te_link_subtlv_rip *) tlvh; + top = (struct te_link_subtlv_rip *)tlvh; - if (vty != NULL) - vty_out (vty, " Inter-AS TE Remote ASBR IP address: %s\n", - inet_ntoa(top->value)); - else - zlog_debug (" Inter-AS TE Remote ASBR IP address: %s", - inet_ntoa (top->value)); + if (vty != NULL) + vty_out(vty, " Inter-AS TE Remote ASBR IP address: %s\n", + inet_ntoa(top->value)); + else + zlog_debug(" Inter-AS TE Remote ASBR IP address: %s", + inet_ntoa(top->value)); - return TLV_SIZE (tlvh); + return TLV_SIZE(tlvh); } -static u_int16_t -show_vty_link_subtlv_ras (struct vty *vty, struct te_tlv_header *tlvh) +static u_int16_t show_vty_link_subtlv_ras(struct vty *vty, + struct te_tlv_header *tlvh) { - struct te_link_subtlv_ras *top; + struct te_link_subtlv_ras *top; - top = (struct te_link_subtlv_ras *) tlvh; + top = (struct te_link_subtlv_ras *)tlvh; - if (vty != NULL) - vty_out (vty, " Inter-AS TE Remote AS number: %u\n",ntohl(top->value)); - else - zlog_debug (" Inter-AS TE Remote AS number: %u", ntohl (top->value)); + if (vty != NULL) + vty_out(vty, " Inter-AS TE Remote AS number: %u\n", + ntohl(top->value)); + else + zlog_debug(" Inter-AS TE Remote AS number: %u", + ntohl(top->value)); - return TLV_SIZE (tlvh); + return TLV_SIZE(tlvh); } -static u_int16_t -show_vty_link_subtlv_av_delay (struct vty *vty, struct te_tlv_header *tlvh) +static u_int16_t show_vty_link_subtlv_av_delay(struct vty *vty, + struct te_tlv_header *tlvh) { - struct te_link_subtlv_av_delay *top; - u_int32_t delay; - u_int32_t anomalous; + struct te_link_subtlv_av_delay *top; + u_int32_t delay; + u_int32_t anomalous; - top = (struct te_link_subtlv_av_delay *) tlvh; - delay = (u_int32_t) ntohl (top->value) & TE_EXT_MASK; - anomalous = (u_int32_t) ntohl (top->value) & TE_EXT_ANORMAL; + top = (struct te_link_subtlv_av_delay *)tlvh; + delay = (u_int32_t)ntohl(top->value) & TE_EXT_MASK; + anomalous = (u_int32_t)ntohl(top->value) & TE_EXT_ANORMAL; - if (vty != NULL) - vty_out (vty, " %s Average Link Delay: %d (micro-sec)\n", - anomalous ? "Anomalous" : "Normal", delay); - else - zlog_debug (" %s Average Link Delay: %d (micro-sec)", - anomalous ? "Anomalous" : "Normal", delay); + if (vty != NULL) + vty_out(vty, " %s Average Link Delay: %d (micro-sec)\n", + anomalous ? "Anomalous" : "Normal", delay); + else + zlog_debug(" %s Average Link Delay: %d (micro-sec)", + anomalous ? "Anomalous" : "Normal", delay); - return TLV_SIZE (tlvh); + return TLV_SIZE(tlvh); } -static u_int16_t -show_vty_link_subtlv_mm_delay (struct vty *vty, struct te_tlv_header *tlvh) +static u_int16_t show_vty_link_subtlv_mm_delay(struct vty *vty, + struct te_tlv_header *tlvh) { - struct te_link_subtlv_mm_delay *top; - u_int32_t low, high; - u_int32_t anomalous; + struct te_link_subtlv_mm_delay *top; + u_int32_t low, high; + u_int32_t anomalous; - top = (struct te_link_subtlv_mm_delay *) tlvh; - low = (u_int32_t) ntohl (top->low) & TE_EXT_MASK; - anomalous = (u_int32_t) ntohl (top->low) & TE_EXT_ANORMAL; - high = (u_int32_t) ntohl (top->high); + top = (struct te_link_subtlv_mm_delay *)tlvh; + low = (u_int32_t)ntohl(top->low) & TE_EXT_MASK; + anomalous = (u_int32_t)ntohl(top->low) & TE_EXT_ANORMAL; + high = (u_int32_t)ntohl(top->high); - if (vty != NULL) - vty_out (vty, " %s Min/Max Link Delay: %d/%d (micro-sec)\n", - anomalous ? "Anomalous" : "Normal", low, high); - else - zlog_debug (" %s Min/Max Link Delay: %d/%d (micro-sec)", - anomalous ? "Anomalous" : "Normal", low, high); + if (vty != NULL) + vty_out(vty, " %s Min/Max Link Delay: %d/%d (micro-sec)\n", + anomalous ? "Anomalous" : "Normal", low, high); + else + zlog_debug(" %s Min/Max Link Delay: %d/%d (micro-sec)", + anomalous ? "Anomalous" : "Normal", low, high); - return TLV_SIZE (tlvh); + return TLV_SIZE(tlvh); } -static u_int16_t -show_vty_link_subtlv_delay_var (struct vty *vty, struct te_tlv_header *tlvh) +static u_int16_t show_vty_link_subtlv_delay_var(struct vty *vty, + struct te_tlv_header *tlvh) { - struct te_link_subtlv_delay_var *top; - u_int32_t jitter; + struct te_link_subtlv_delay_var *top; + u_int32_t jitter; - top = (struct te_link_subtlv_delay_var *) tlvh; - jitter = (u_int32_t) ntohl (top->value) & TE_EXT_MASK; + top = (struct te_link_subtlv_delay_var *)tlvh; + jitter = (u_int32_t)ntohl(top->value) & TE_EXT_MASK; - if (vty != NULL) - vty_out (vty, " Delay Variation: %d (micro-sec)\n", jitter); - else - zlog_debug (" Delay Variation: %d (micro-sec)", jitter); + if (vty != NULL) + vty_out(vty, " Delay Variation: %d (micro-sec)\n", jitter); + else + zlog_debug(" Delay Variation: %d (micro-sec)", jitter); - return TLV_SIZE (tlvh); + return TLV_SIZE(tlvh); } -static u_int16_t -show_vty_link_subtlv_pkt_loss (struct vty *vty, struct te_tlv_header *tlvh) +static u_int16_t show_vty_link_subtlv_pkt_loss(struct vty *vty, + struct te_tlv_header *tlvh) { - struct te_link_subtlv_pkt_loss *top; - u_int32_t loss; - u_int32_t anomalous; - float fval; + struct te_link_subtlv_pkt_loss *top; + u_int32_t loss; + u_int32_t anomalous; + float fval; - top = (struct te_link_subtlv_pkt_loss *) tlvh; - loss = (u_int32_t) ntohl (top->value) & TE_EXT_MASK; - fval = (float) (loss * LOSS_PRECISION); - anomalous = (u_int32_t) ntohl (top->value) & TE_EXT_ANORMAL; + top = (struct te_link_subtlv_pkt_loss *)tlvh; + loss = (u_int32_t)ntohl(top->value) & TE_EXT_MASK; + fval = (float)(loss * LOSS_PRECISION); + anomalous = (u_int32_t)ntohl(top->value) & TE_EXT_ANORMAL; - if (vty != NULL) - vty_out (vty, " %s Link Loss: %g (%%)\n", anomalous ? "Anomalous" : "Normal", - fval); - else - zlog_debug (" %s Link Loss: %g (%%)", anomalous ? "Anomalous" : "Normal", - fval); + if (vty != NULL) + vty_out(vty, " %s Link Loss: %g (%%)\n", + anomalous ? "Anomalous" : "Normal", fval); + else + zlog_debug(" %s Link Loss: %g (%%)", + anomalous ? "Anomalous" : "Normal", fval); - return TLV_SIZE (tlvh); + return TLV_SIZE(tlvh); } -static u_int16_t -show_vty_link_subtlv_res_bw (struct vty *vty, struct te_tlv_header *tlvh) +static u_int16_t show_vty_link_subtlv_res_bw(struct vty *vty, + struct te_tlv_header *tlvh) { - struct te_link_subtlv_res_bw *top; - float fval; - - top = (struct te_link_subtlv_res_bw *) tlvh; - fval = ntohf (top->value); + struct te_link_subtlv_res_bw *top; + float fval; - if (vty != NULL) - vty_out (vty, " Unidirectional Residual Bandwidth: %g (Bytes/sec)\n", - fval); - else - zlog_debug (" Unidirectional Residual Bandwidth: %g (Bytes/sec)", - fval); + top = (struct te_link_subtlv_res_bw *)tlvh; + fval = ntohf(top->value); - return TLV_SIZE (tlvh); -} - -static u_int16_t -show_vty_link_subtlv_ava_bw (struct vty *vty, struct te_tlv_header *tlvh) -{ - struct te_link_subtlv_ava_bw *top; - float fval; - - top = (struct te_link_subtlv_ava_bw *) tlvh; - fval = ntohf (top->value); - - if (vty != NULL) - vty_out (vty, " Unidirectional Available Bandwidth: %g (Bytes/sec)\n", - fval); - else - zlog_debug (" Unidirectional Available Bandwidth: %g (Bytes/sec)", - fval); - - return TLV_SIZE (tlvh); -} - -static u_int16_t -show_vty_link_subtlv_use_bw (struct vty *vty, struct te_tlv_header *tlvh) -{ - struct te_link_subtlv_use_bw *top; - float fval; - - top = (struct te_link_subtlv_use_bw *) tlvh; - fval = ntohf (top->value); - - if (vty != NULL) - vty_out (vty, " Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n", - fval); - else - zlog_debug (" Unidirectional Utilized Bandwidth: %g (Bytes/sec)", - fval); - - return TLV_SIZE (tlvh); -} - -static u_int16_t -show_vty_unknown_tlv (struct vty *vty, struct te_tlv_header *tlvh) -{ - if (vty != NULL) - vty_out (vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n", - ntohs (tlvh->type), ntohs(tlvh->length)); - else - zlog_debug (" Unknown TLV: [type(0x%x), length(0x%x)]", - ntohs (tlvh->type), ntohs (tlvh->length)); - - return TLV_SIZE (tlvh); -} - -static u_int16_t -ospf_mpls_te_show_link_subtlv (struct vty *vty, struct te_tlv_header *tlvh0, - u_int16_t subtotal, u_int16_t total) -{ - struct te_tlv_header *tlvh, *next; - u_int16_t sum = subtotal; - - for (tlvh = tlvh0; sum < total; tlvh = (next ? next : TLV_HDR_NEXT (tlvh))) - { - next = NULL; - switch (ntohs (tlvh->type)) - { - case TE_LINK_SUBTLV_LINK_TYPE: - sum += show_vty_link_subtlv_link_type (vty, tlvh); - break; - case TE_LINK_SUBTLV_LINK_ID: - sum += show_vty_link_subtlv_link_id (vty, tlvh); - break; - case TE_LINK_SUBTLV_LCLIF_IPADDR: - sum += show_vty_link_subtlv_lclif_ipaddr (vty, tlvh); - break; - case TE_LINK_SUBTLV_RMTIF_IPADDR: - sum += show_vty_link_subtlv_rmtif_ipaddr (vty, tlvh); - break; - case TE_LINK_SUBTLV_TE_METRIC: - sum += show_vty_link_subtlv_te_metric (vty, tlvh); - break; - case TE_LINK_SUBTLV_MAX_BW: - sum += show_vty_link_subtlv_max_bw (vty, tlvh); - break; - case TE_LINK_SUBTLV_MAX_RSV_BW: - sum += show_vty_link_subtlv_max_rsv_bw (vty, tlvh); - break; - case TE_LINK_SUBTLV_UNRSV_BW: - sum += show_vty_link_subtlv_unrsv_bw (vty, tlvh); - break; - case TE_LINK_SUBTLV_RSC_CLSCLR: - sum += show_vty_link_subtlv_rsc_clsclr (vty, tlvh); - break; - case TE_LINK_SUBTLV_LRRID: - sum += show_vty_link_subtlv_lrrid (vty, tlvh); - break; - case TE_LINK_SUBTLV_LLRI: - sum += show_vty_link_subtlv_llri (vty, tlvh); - break; - case TE_LINK_SUBTLV_RIP: - sum += show_vty_link_subtlv_rip (vty, tlvh); - break; - case TE_LINK_SUBTLV_RAS: - sum += show_vty_link_subtlv_ras (vty, tlvh); - break; - case TE_LINK_SUBTLV_AV_DELAY: - sum += show_vty_link_subtlv_av_delay (vty, tlvh); - break; - case TE_LINK_SUBTLV_MM_DELAY: - sum += show_vty_link_subtlv_mm_delay (vty, tlvh); - break; - case TE_LINK_SUBTLV_DELAY_VAR: - sum += show_vty_link_subtlv_delay_var (vty, tlvh); - break; - case TE_LINK_SUBTLV_PKT_LOSS: - sum += show_vty_link_subtlv_pkt_loss (vty, tlvh); - break; - case TE_LINK_SUBTLV_RES_BW: - sum += show_vty_link_subtlv_res_bw (vty, tlvh); - break; - case TE_LINK_SUBTLV_AVA_BW: - sum += show_vty_link_subtlv_ava_bw (vty, tlvh); - break; - case TE_LINK_SUBTLV_USE_BW: - sum += show_vty_link_subtlv_use_bw (vty, tlvh); - break; - default: - sum += show_vty_unknown_tlv (vty, tlvh); - break; - } - } - return sum; -} - -static void -ospf_mpls_te_show_info (struct vty *vty, struct ospf_lsa *lsa) -{ - struct lsa_header *lsah = (struct lsa_header *) lsa->data; - struct te_tlv_header *tlvh, *next; - u_int16_t sum, total; - u_int16_t (* subfunc)(struct vty *vty, struct te_tlv_header *tlvh, - u_int16_t subtotal, u_int16_t total) = NULL; - - sum = 0; - total = ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE; - - for (tlvh = TLV_HDR_TOP (lsah); sum < total; - tlvh = (next ? next : TLV_HDR_NEXT (tlvh))) - { - if (subfunc != NULL) - { - sum = (* subfunc)(vty, tlvh, sum, total); - next = (struct te_tlv_header *)((char *) tlvh + sum); - subfunc = NULL; - continue; - } - - next = NULL; - switch (ntohs (tlvh->type)) - { - case TE_TLV_ROUTER_ADDR: - sum += show_vty_router_addr (vty, tlvh); - break; - case TE_TLV_LINK: - sum += show_vty_link_header (vty, tlvh); - subfunc = ospf_mpls_te_show_link_subtlv; - next = tlvh + 1; - break; - default: - sum += show_vty_unknown_tlv (vty, tlvh); - break; - } - } - return; -} - -static void -ospf_mpls_te_config_write_router (struct vty *vty) -{ - - if (OspfMplsTE.status == enabled) - { - vty_out (vty, " mpls-te on\n"); - vty_out (vty, " mpls-te router-address %s\n", - inet_ntoa(OspfMplsTE.router_addr.value)); - } - - if (OspfMplsTE.inter_as == AS) - vty_out (vty, " mpls-te inter-as as\n"); - if (OspfMplsTE.inter_as == Area) - vty_out (vty, " mpls-te inter-as area %s \n", - inet_ntoa(OspfMplsTE.interas_areaid)); - - return; + if (vty != NULL) + vty_out(vty, + " Unidirectional Residual Bandwidth: %g (Bytes/sec)\n", + fval); + else + zlog_debug( + " Unidirectional Residual Bandwidth: %g (Bytes/sec)", + fval); + + return TLV_SIZE(tlvh); +} + +static u_int16_t show_vty_link_subtlv_ava_bw(struct vty *vty, + struct te_tlv_header *tlvh) +{ + struct te_link_subtlv_ava_bw *top; + float fval; + + top = (struct te_link_subtlv_ava_bw *)tlvh; + fval = ntohf(top->value); + + if (vty != NULL) + vty_out(vty, + " Unidirectional Available Bandwidth: %g (Bytes/sec)\n", + fval); + else + zlog_debug( + " Unidirectional Available Bandwidth: %g (Bytes/sec)", + fval); + + return TLV_SIZE(tlvh); +} + +static u_int16_t show_vty_link_subtlv_use_bw(struct vty *vty, + struct te_tlv_header *tlvh) +{ + struct te_link_subtlv_use_bw *top; + float fval; + + top = (struct te_link_subtlv_use_bw *)tlvh; + fval = ntohf(top->value); + + if (vty != NULL) + vty_out(vty, + " Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n", + fval); + else + zlog_debug( + " Unidirectional Utilized Bandwidth: %g (Bytes/sec)", + fval); + + return TLV_SIZE(tlvh); +} + +static u_int16_t show_vty_unknown_tlv(struct vty *vty, + struct te_tlv_header *tlvh) +{ + if (vty != NULL) + vty_out(vty, " Unknown TLV: [type(0x%x), length(0x%x)]\n", + ntohs(tlvh->type), ntohs(tlvh->length)); + else + zlog_debug(" Unknown TLV: [type(0x%x), length(0x%x)]", + ntohs(tlvh->type), ntohs(tlvh->length)); + + return TLV_SIZE(tlvh); +} + +static u_int16_t ospf_mpls_te_show_link_subtlv(struct vty *vty, + struct te_tlv_header *tlvh0, + u_int16_t subtotal, + u_int16_t total) +{ + struct te_tlv_header *tlvh, *next; + u_int16_t sum = subtotal; + + for (tlvh = tlvh0; sum < total; + tlvh = (next ? next : TLV_HDR_NEXT(tlvh))) { + next = NULL; + switch (ntohs(tlvh->type)) { + case TE_LINK_SUBTLV_LINK_TYPE: + sum += show_vty_link_subtlv_link_type(vty, tlvh); + break; + case TE_LINK_SUBTLV_LINK_ID: + sum += show_vty_link_subtlv_link_id(vty, tlvh); + break; + case TE_LINK_SUBTLV_LCLIF_IPADDR: + sum += show_vty_link_subtlv_lclif_ipaddr(vty, tlvh); + break; + case TE_LINK_SUBTLV_RMTIF_IPADDR: + sum += show_vty_link_subtlv_rmtif_ipaddr(vty, tlvh); + break; + case TE_LINK_SUBTLV_TE_METRIC: + sum += show_vty_link_subtlv_te_metric(vty, tlvh); + break; + case TE_LINK_SUBTLV_MAX_BW: + sum += show_vty_link_subtlv_max_bw(vty, tlvh); + break; + case TE_LINK_SUBTLV_MAX_RSV_BW: + sum += show_vty_link_subtlv_max_rsv_bw(vty, tlvh); + break; + case TE_LINK_SUBTLV_UNRSV_BW: + sum += show_vty_link_subtlv_unrsv_bw(vty, tlvh); + break; + case TE_LINK_SUBTLV_RSC_CLSCLR: + sum += show_vty_link_subtlv_rsc_clsclr(vty, tlvh); + break; + case TE_LINK_SUBTLV_LRRID: + sum += show_vty_link_subtlv_lrrid(vty, tlvh); + break; + case TE_LINK_SUBTLV_LLRI: + sum += show_vty_link_subtlv_llri(vty, tlvh); + break; + case TE_LINK_SUBTLV_RIP: + sum += show_vty_link_subtlv_rip(vty, tlvh); + break; + case TE_LINK_SUBTLV_RAS: + sum += show_vty_link_subtlv_ras(vty, tlvh); + break; + case TE_LINK_SUBTLV_AV_DELAY: + sum += show_vty_link_subtlv_av_delay(vty, tlvh); + break; + case TE_LINK_SUBTLV_MM_DELAY: + sum += show_vty_link_subtlv_mm_delay(vty, tlvh); + break; + case TE_LINK_SUBTLV_DELAY_VAR: + sum += show_vty_link_subtlv_delay_var(vty, tlvh); + break; + case TE_LINK_SUBTLV_PKT_LOSS: + sum += show_vty_link_subtlv_pkt_loss(vty, tlvh); + break; + case TE_LINK_SUBTLV_RES_BW: + sum += show_vty_link_subtlv_res_bw(vty, tlvh); + break; + case TE_LINK_SUBTLV_AVA_BW: + sum += show_vty_link_subtlv_ava_bw(vty, tlvh); + break; + case TE_LINK_SUBTLV_USE_BW: + sum += show_vty_link_subtlv_use_bw(vty, tlvh); + break; + default: + sum += show_vty_unknown_tlv(vty, tlvh); + break; + } + } + return sum; +} + +static void ospf_mpls_te_show_info(struct vty *vty, struct ospf_lsa *lsa) +{ + struct lsa_header *lsah = (struct lsa_header *)lsa->data; + struct te_tlv_header *tlvh, *next; + u_int16_t sum, total; + u_int16_t (*subfunc)(struct vty * vty, struct te_tlv_header * tlvh, + u_int16_t subtotal, u_int16_t total) = NULL; + + sum = 0; + total = ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE; + + for (tlvh = TLV_HDR_TOP(lsah); sum < total; + tlvh = (next ? next : TLV_HDR_NEXT(tlvh))) { + if (subfunc != NULL) { + sum = (*subfunc)(vty, tlvh, sum, total); + next = (struct te_tlv_header *)((char *)tlvh + sum); + subfunc = NULL; + continue; + } + + next = NULL; + switch (ntohs(tlvh->type)) { + case TE_TLV_ROUTER_ADDR: + sum += show_vty_router_addr(vty, tlvh); + break; + case TE_TLV_LINK: + sum += show_vty_link_header(vty, tlvh); + subfunc = ospf_mpls_te_show_link_subtlv; + next = tlvh + 1; + break; + default: + sum += show_vty_unknown_tlv(vty, tlvh); + break; + } + } + return; +} + +static void ospf_mpls_te_config_write_router(struct vty *vty) +{ + + if (OspfMplsTE.status == enabled) { + vty_out(vty, " mpls-te on\n"); + vty_out(vty, " mpls-te router-address %s\n", + inet_ntoa(OspfMplsTE.router_addr.value)); + } + + if (OspfMplsTE.inter_as == AS) + vty_out(vty, " mpls-te inter-as as\n"); + if (OspfMplsTE.inter_as == Area) + vty_out(vty, " mpls-te inter-as area %s \n", + inet_ntoa(OspfMplsTE.interas_areaid)); + + return; } /*------------------------------------------------------------------------* @@ -2254,34 +2235,33 @@ DEFUN (ospf_mpls_te_on, MPLS_TE_STR "Enable the MPLS-TE functionality\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - struct listnode *node; - struct mpls_te_link *lp; + VTY_DECLVAR_CONTEXT(ospf, ospf); + struct listnode *node; + struct mpls_te_link *lp; - if (OspfMplsTE.status == enabled) - return CMD_SUCCESS; + if (OspfMplsTE.status == enabled) + return CMD_SUCCESS; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("MPLS-TE: OFF -> ON"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("MPLS-TE: OFF -> ON"); - OspfMplsTE.status = enabled; + OspfMplsTE.status = enabled; - /* Reoriginate RFC3630 & RFC6827 Links */ - ospf_mpls_te_foreach_area (ospf_mpls_te_lsa_schedule, REORIGINATE_THIS_LSA); + /* Reoriginate RFC3630 & RFC6827 Links */ + ospf_mpls_te_foreach_area(ospf_mpls_te_lsa_schedule, + REORIGINATE_THIS_LSA); - /* Reoriginate LSA if INTER-AS is always on */ - if (OspfMplsTE.inter_as != Disable) - { - for (ALL_LIST_ELEMENTS_RO (OspfMplsTE.iflist, node, lp)) - { - if (IS_INTER_AS (lp->type)) - { - ospf_mpls_te_lsa_schedule (lp, REORIGINATE_THIS_LSA); - } - } - } + /* Reoriginate LSA if INTER-AS is always on */ + if (OspfMplsTE.inter_as != Disable) { + for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node, lp)) { + if (IS_INTER_AS(lp->type)) { + ospf_mpls_te_lsa_schedule(lp, + REORIGINATE_THIS_LSA); + } + } + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf_mpls_te, @@ -2291,23 +2271,24 @@ DEFUN (no_ospf_mpls_te, MPLS_TE_STR "Disable the MPLS-TE functionality\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - struct listnode *node, *nnode; - struct mpls_te_link *lp; + VTY_DECLVAR_CONTEXT(ospf, ospf); + struct listnode *node, *nnode; + struct mpls_te_link *lp; - if (OspfMplsTE.status == disabled) - return CMD_SUCCESS; + if (OspfMplsTE.status == disabled) + return CMD_SUCCESS; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("MPLS-TE: ON -> OFF"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("MPLS-TE: ON -> OFF"); - OspfMplsTE.status = disabled; + OspfMplsTE.status = disabled; - for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp)) - if CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED) - ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA); + for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) + if + CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED) + ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -2318,127 +2299,118 @@ DEFUN (ospf_mpls_te_router_addr, "Stable IP address of the advertising router\n" "MPLS-TE router address in IPv4 address format\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4 = 2; - struct te_tlv_router_addr *ra = &OspfMplsTE.router_addr; - struct in_addr value; - - if (! inet_aton (argv[idx_ipv4]->arg, &value)) - { - vty_out (vty, "Please specify Router-Addr by A.B.C.D\n"); - return CMD_WARNING; - } - - if (ntohs (ra->header.type) == 0 - || ntohl (ra->value.s_addr) != ntohl (value.s_addr)) - { - struct listnode *node, *nnode; - struct mpls_te_link *lp; - int need_to_reoriginate = 0; - - set_mpls_te_router_addr (value); - - if (OspfMplsTE.status == disabled) - goto out; - - for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp)) - { - if ((lp->area == NULL) || IS_FLOOD_AS (lp->type)) - continue; - - if (!CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)) - { - need_to_reoriginate = 1; - break; - } - } - - for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp)) - { - if ((lp->area == NULL) || IS_FLOOD_AS (lp->type)) - continue; - - if (need_to_reoriginate) - SET_FLAG (lp->flags, LPFLG_LSA_FORCED_REFRESH); - else - ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA); - } - - if (need_to_reoriginate) - ospf_mpls_te_foreach_area (ospf_mpls_te_lsa_schedule, REORIGINATE_THIS_LSA); - } + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4 = 2; + struct te_tlv_router_addr *ra = &OspfMplsTE.router_addr; + struct in_addr value; + + if (!inet_aton(argv[idx_ipv4]->arg, &value)) { + vty_out(vty, "Please specify Router-Addr by A.B.C.D\n"); + return CMD_WARNING; + } + + if (ntohs(ra->header.type) == 0 + || ntohl(ra->value.s_addr) != ntohl(value.s_addr)) { + struct listnode *node, *nnode; + struct mpls_te_link *lp; + int need_to_reoriginate = 0; + + set_mpls_te_router_addr(value); + + if (OspfMplsTE.status == disabled) + goto out; + + for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) { + if ((lp->area == NULL) || IS_FLOOD_AS(lp->type)) + continue; + + if (!CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) { + need_to_reoriginate = 1; + break; + } + } + + for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) { + if ((lp->area == NULL) || IS_FLOOD_AS(lp->type)) + continue; + + if (need_to_reoriginate) + SET_FLAG(lp->flags, LPFLG_LSA_FORCED_REFRESH); + else + ospf_mpls_te_lsa_schedule(lp, REFRESH_THIS_LSA); + } + + if (need_to_reoriginate) + ospf_mpls_te_foreach_area(ospf_mpls_te_lsa_schedule, + REORIGINATE_THIS_LSA); + } out: - return CMD_SUCCESS; -} - -static int -set_inter_as_mode (struct vty *vty, const char *mode_name, - const char *area_id) -{ - enum inter_as_mode mode; - struct listnode *node; - struct mpls_te_link *lp; - int format; - - if (OspfMplsTE.status == enabled) - { - - /* Read and Check inter_as mode */ - if (strcmp (mode_name, "as") == 0) - mode = AS; - else if (strcmp (mode_name, "area") == 0) - { - mode = Area; - VTY_GET_OSPF_AREA_ID (OspfMplsTE.interas_areaid, format, area_id); - } - else - { - vty_out (vty,"Unknown mode. Please choose between as or area\n"); - return CMD_WARNING; - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("MPLS-TE: Inter-AS enable with %s flooding support", - mode2text[mode]); - - /* Register new callbacks regarding the flooding scope (AS or Area) */ - if (ospf_mpls_te_register (mode) < 0) - { - vty_out (vty, - "Internal error: Unable to register Inter-AS functions\n"); - return CMD_WARNING; - } - - /* Enable mode and re-originate LSA if needed */ - if ((OspfMplsTE.inter_as == Disable) && (mode != OspfMplsTE.inter_as)) - { - OspfMplsTE.inter_as = mode; - /* Re-originate all InterAS-TEv2 LSA */ - for (ALL_LIST_ELEMENTS_RO (OspfMplsTE.iflist, node, lp)) - { - if (IS_INTER_AS (lp->type)) - { - if (mode == AS) - lp->type |= FLOOD_AS; - else - lp->type |= FLOOD_AREA; - ospf_mpls_te_lsa_schedule (lp, REORIGINATE_THIS_LSA); - } - } - } - else - { - vty_out (vty, "Please change Inter-AS support to disable first before going to mode %s\n", - mode2text[mode]); - return CMD_WARNING; - } - } - else - { - vty_out (vty, "mpls-te has not been turned on\n"); - return CMD_WARNING; - } - return CMD_SUCCESS; + return CMD_SUCCESS; +} + +static int set_inter_as_mode(struct vty *vty, const char *mode_name, + const char *area_id) +{ + enum inter_as_mode mode; + struct listnode *node; + struct mpls_te_link *lp; + int format; + + if (OspfMplsTE.status == enabled) { + + /* Read and Check inter_as mode */ + if (strcmp(mode_name, "as") == 0) + mode = AS; + else if (strcmp(mode_name, "area") == 0) { + mode = Area; + VTY_GET_OSPF_AREA_ID(OspfMplsTE.interas_areaid, format, + area_id); + } else { + vty_out(vty, + "Unknown mode. Please choose between as or area\n"); + return CMD_WARNING; + } + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "MPLS-TE: Inter-AS enable with %s flooding support", + mode2text[mode]); + + /* Register new callbacks regarding the flooding scope (AS or + * Area) */ + if (ospf_mpls_te_register(mode) < 0) { + vty_out(vty, + "Internal error: Unable to register Inter-AS functions\n"); + return CMD_WARNING; + } + + /* Enable mode and re-originate LSA if needed */ + if ((OspfMplsTE.inter_as == Disable) + && (mode != OspfMplsTE.inter_as)) { + OspfMplsTE.inter_as = mode; + /* Re-originate all InterAS-TEv2 LSA */ + for (ALL_LIST_ELEMENTS_RO(OspfMplsTE.iflist, node, + lp)) { + if (IS_INTER_AS(lp->type)) { + if (mode == AS) + lp->type |= FLOOD_AS; + else + lp->type |= FLOOD_AREA; + ospf_mpls_te_lsa_schedule( + lp, REORIGINATE_THIS_LSA); + } + } + } else { + vty_out(vty, + "Please change Inter-AS support to disable first before going to mode %s\n", + mode2text[mode]); + return CMD_WARNING; + } + } else { + vty_out(vty, "mpls-te has not been turned on\n"); + return CMD_WARNING; + } + return CMD_SUCCESS; } @@ -2449,7 +2421,7 @@ DEFUN (ospf_mpls_te_inter_as_as, "Configure MPLS-TE Inter-AS support\n" "AS native mode self originate INTER_AS LSA with Type 11 (as flooding scope)\n") { - return set_inter_as_mode (vty, "as", ""); + return set_inter_as_mode(vty, "as", ""); } DEFUN (ospf_mpls_te_inter_as_area, @@ -2461,8 +2433,8 @@ DEFUN (ospf_mpls_te_inter_as_area, "OSPF area ID in IP format\n" "OSPF area ID as decimal value\n") { - int idx_ipv4_number = 3; - return set_inter_as_mode (vty, "area", argv[idx_ipv4_number]->arg); + int idx_ipv4_number = 3; + return set_inter_as_mode(vty, "area", argv[idx_ipv4_number]->arg); } DEFUN (no_ospf_mpls_te_inter_as, @@ -2473,25 +2445,26 @@ DEFUN (no_ospf_mpls_te_inter_as, "Disable MPLS-TE Inter-AS support\n") { - struct listnode *node, *nnode; - struct mpls_te_link *lp; + struct listnode *node, *nnode; + struct mpls_te_link *lp; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("MPLS-TE: Inter-AS support OFF"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("MPLS-TE: Inter-AS support OFF"); - if ((OspfMplsTE.status == enabled) && (OspfMplsTE.inter_as != Disable)) - { - OspfMplsTE.inter_as = Disable; - /* Flush all Inter-AS LSA */ - for (ALL_LIST_ELEMENTS (OspfMplsTE.iflist, node, nnode, lp)) - if (IS_INTER_AS (lp->type) && CHECK_FLAG (lp->flags, LPFLG_LSA_ENGAGED)) - ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA); - } + if ((OspfMplsTE.status == enabled) + && (OspfMplsTE.inter_as != Disable)) { + OspfMplsTE.inter_as = Disable; + /* Flush all Inter-AS LSA */ + for (ALL_LIST_ELEMENTS(OspfMplsTE.iflist, node, nnode, lp)) + if (IS_INTER_AS(lp->type) + && CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) + ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA); + } - /* Deregister the Callbacks for Inter-AS suport */ - ospf_mpls_te_unregister (); + /* Deregister the Callbacks for Inter-AS suport */ + ospf_mpls_te_unregister(); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_ospf_mpls_te_router, @@ -2503,97 +2476,100 @@ DEFUN (show_ip_ospf_mpls_te_router, "MPLS-TE information\n" "MPLS-TE Router parameters\n") { - if (OspfMplsTE.status == enabled) - { - vty_out (vty, "--- MPLS-TE router parameters ---\n"); - - if (ntohs (OspfMplsTE.router_addr.header.type) != 0) - show_vty_router_addr (vty, &OspfMplsTE.router_addr.header); - else if (vty != NULL) - vty_out (vty, " N/A\n"); - } - return CMD_SUCCESS; -} - -static void -show_mpls_te_link_sub (struct vty *vty, struct interface *ifp) -{ - struct mpls_te_link *lp; - - if ((OspfMplsTE.status == enabled) - && HAS_LINK_PARAMS(ifp) - && !if_is_loopback (ifp) - && if_is_up (ifp) - && ((lp = lookup_linkparams_by_ifp (ifp)) != NULL)) - { - /* Continue only if interface is not passive or support Inter-AS TEv2 */ - if (!(ospf_oi_count (ifp) > 0)) - { - if (IS_INTER_AS (lp->type)) - { - vty_out (vty, "-- Inter-AS TEv2 link parameters for %s --\n", - ifp->name); - } - else - { - /* MPLS-TE is not activate on this interface */ - /* or this interface is passive and Inter-AS TEv2 is not activate */ - vty_out (vty, " %s: MPLS-TE is disabled on this interface\n", - ifp->name); - return; - } - } - else - { - vty_out (vty, "-- MPLS-TE link parameters for %s --\n", - ifp->name); - } - - if (TLV_TYPE(lp->link_type) != 0) - show_vty_link_subtlv_link_type (vty, &lp->link_type.header); - if (TLV_TYPE(lp->link_id) != 0) - show_vty_link_subtlv_link_id (vty, &lp->link_id.header); - if (TLV_TYPE(lp->lclif_ipaddr) != 0) - show_vty_link_subtlv_lclif_ipaddr (vty, &lp->lclif_ipaddr.header); - if (TLV_TYPE(lp->rmtif_ipaddr) != 0) - show_vty_link_subtlv_rmtif_ipaddr (vty, &lp->rmtif_ipaddr.header); - if (TLV_TYPE(lp->rip) != 0) - show_vty_link_subtlv_rip (vty, &lp->rip.header); - if (TLV_TYPE(lp->ras) != 0) - show_vty_link_subtlv_ras (vty, &lp->ras.header); - if (TLV_TYPE(lp->te_metric) != 0) - show_vty_link_subtlv_te_metric (vty, &lp->te_metric.header); - if (TLV_TYPE(lp->max_bw) != 0) - show_vty_link_subtlv_max_bw (vty, &lp->max_bw.header); - if (TLV_TYPE(lp->max_rsv_bw) != 0) - show_vty_link_subtlv_max_rsv_bw (vty, &lp->max_rsv_bw.header); - if (TLV_TYPE(lp->unrsv_bw) != 0) - show_vty_link_subtlv_unrsv_bw (vty, &lp->unrsv_bw.header); - if (TLV_TYPE(lp->rsc_clsclr) != 0) - show_vty_link_subtlv_rsc_clsclr (vty, &lp->rsc_clsclr.header); - if (TLV_TYPE(lp->av_delay) != 0) - show_vty_link_subtlv_av_delay (vty, &lp->av_delay.header); - if (TLV_TYPE(lp->mm_delay) != 0) - show_vty_link_subtlv_mm_delay (vty, &lp->mm_delay.header); - if (TLV_TYPE(lp->delay_var) != 0) - show_vty_link_subtlv_delay_var (vty, &lp->delay_var.header); - if (TLV_TYPE(lp->pkt_loss) != 0) - show_vty_link_subtlv_pkt_loss (vty, &lp->pkt_loss.header); - if (TLV_TYPE(lp->res_bw) != 0) - show_vty_link_subtlv_res_bw (vty, &lp->res_bw.header); - if (TLV_TYPE(lp->ava_bw) != 0) - show_vty_link_subtlv_ava_bw (vty, &lp->ava_bw.header); - if (TLV_TYPE(lp->use_bw) != 0) - show_vty_link_subtlv_use_bw (vty, &lp->use_bw.header); - vty_out (vty, "---------------\n\n"); - } - else - { - vty_out (vty, " %s: MPLS-TE is disabled on this interface\n", - ifp->name); - } - - return; + if (OspfMplsTE.status == enabled) { + vty_out(vty, "--- MPLS-TE router parameters ---\n"); + + if (ntohs(OspfMplsTE.router_addr.header.type) != 0) + show_vty_router_addr(vty, + &OspfMplsTE.router_addr.header); + else if (vty != NULL) + vty_out(vty, " N/A\n"); + } + return CMD_SUCCESS; +} + +static void show_mpls_te_link_sub(struct vty *vty, struct interface *ifp) +{ + struct mpls_te_link *lp; + + if ((OspfMplsTE.status == enabled) && HAS_LINK_PARAMS(ifp) + && !if_is_loopback(ifp) && if_is_up(ifp) + && ((lp = lookup_linkparams_by_ifp(ifp)) != NULL)) { + /* Continue only if interface is not passive or support Inter-AS + * TEv2 */ + if (!(ospf_oi_count(ifp) > 0)) { + if (IS_INTER_AS(lp->type)) { + vty_out(vty, + "-- Inter-AS TEv2 link parameters for %s --\n", + ifp->name); + } else { + /* MPLS-TE is not activate on this interface */ + /* or this interface is passive and Inter-AS + * TEv2 is not activate */ + vty_out(vty, + " %s: MPLS-TE is disabled on this interface\n", + ifp->name); + return; + } + } else { + vty_out(vty, "-- MPLS-TE link parameters for %s --\n", + ifp->name); + } + + if (TLV_TYPE(lp->link_type) != 0) + show_vty_link_subtlv_link_type(vty, + &lp->link_type.header); + if (TLV_TYPE(lp->link_id) != 0) + show_vty_link_subtlv_link_id(vty, &lp->link_id.header); + if (TLV_TYPE(lp->lclif_ipaddr) != 0) + show_vty_link_subtlv_lclif_ipaddr( + vty, &lp->lclif_ipaddr.header); + if (TLV_TYPE(lp->rmtif_ipaddr) != 0) + show_vty_link_subtlv_rmtif_ipaddr( + vty, &lp->rmtif_ipaddr.header); + if (TLV_TYPE(lp->rip) != 0) + show_vty_link_subtlv_rip(vty, &lp->rip.header); + if (TLV_TYPE(lp->ras) != 0) + show_vty_link_subtlv_ras(vty, &lp->ras.header); + if (TLV_TYPE(lp->te_metric) != 0) + show_vty_link_subtlv_te_metric(vty, + &lp->te_metric.header); + if (TLV_TYPE(lp->max_bw) != 0) + show_vty_link_subtlv_max_bw(vty, &lp->max_bw.header); + if (TLV_TYPE(lp->max_rsv_bw) != 0) + show_vty_link_subtlv_max_rsv_bw(vty, + &lp->max_rsv_bw.header); + if (TLV_TYPE(lp->unrsv_bw) != 0) + show_vty_link_subtlv_unrsv_bw(vty, + &lp->unrsv_bw.header); + if (TLV_TYPE(lp->rsc_clsclr) != 0) + show_vty_link_subtlv_rsc_clsclr(vty, + &lp->rsc_clsclr.header); + if (TLV_TYPE(lp->av_delay) != 0) + show_vty_link_subtlv_av_delay(vty, + &lp->av_delay.header); + if (TLV_TYPE(lp->mm_delay) != 0) + show_vty_link_subtlv_mm_delay(vty, + &lp->mm_delay.header); + if (TLV_TYPE(lp->delay_var) != 0) + show_vty_link_subtlv_delay_var(vty, + &lp->delay_var.header); + if (TLV_TYPE(lp->pkt_loss) != 0) + show_vty_link_subtlv_pkt_loss(vty, + &lp->pkt_loss.header); + if (TLV_TYPE(lp->res_bw) != 0) + show_vty_link_subtlv_res_bw(vty, &lp->res_bw.header); + if (TLV_TYPE(lp->ava_bw) != 0) + show_vty_link_subtlv_ava_bw(vty, &lp->ava_bw.header); + if (TLV_TYPE(lp->use_bw) != 0) + show_vty_link_subtlv_use_bw(vty, &lp->use_bw.header); + vty_out(vty, "---------------\n\n"); + } else { + vty_out(vty, " %s: MPLS-TE is disabled on this interface\n", + ifp->name); + } + + return; } DEFUN (show_ip_ospf_mpls_te_link, @@ -2606,40 +2582,40 @@ DEFUN (show_ip_ospf_mpls_te_link, "Interface information\n" "Interface name\n") { - int idx_interface = 5; - struct interface *ifp; - struct listnode *node, *nnode; - - /* Show All Interfaces. */ - if (argc == 5) - { - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp)) - show_mpls_te_link_sub (vty, ifp); - } - /* Interface name is specified. */ - else - { - if ((ifp = if_lookup_by_name (argv[idx_interface]->arg, VRF_DEFAULT)) == NULL) - vty_out (vty, "No such interface name\n"); - else - show_mpls_te_link_sub (vty, ifp); - } - - return CMD_SUCCESS; -} - -static void -ospf_mpls_te_register_vty (void) -{ - install_element (VIEW_NODE, &show_ip_ospf_mpls_te_router_cmd); - install_element (VIEW_NODE, &show_ip_ospf_mpls_te_link_cmd); - - install_element (OSPF_NODE, &ospf_mpls_te_on_cmd); - install_element (OSPF_NODE, &no_ospf_mpls_te_cmd); - install_element (OSPF_NODE, &ospf_mpls_te_router_addr_cmd); - install_element (OSPF_NODE, &ospf_mpls_te_inter_as_cmd); - install_element (OSPF_NODE, &ospf_mpls_te_inter_as_area_cmd); - install_element (OSPF_NODE, &no_ospf_mpls_te_inter_as_cmd); - - return; + int idx_interface = 5; + struct interface *ifp; + struct listnode *node, *nnode; + + /* Show All Interfaces. */ + if (argc == 5) { + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), node, nnode, + ifp)) + show_mpls_te_link_sub(vty, ifp); + } + /* Interface name is specified. */ + else { + if ((ifp = if_lookup_by_name(argv[idx_interface]->arg, + VRF_DEFAULT)) + == NULL) + vty_out(vty, "No such interface name\n"); + else + show_mpls_te_link_sub(vty, ifp); + } + + return CMD_SUCCESS; +} + +static void ospf_mpls_te_register_vty(void) +{ + install_element(VIEW_NODE, &show_ip_ospf_mpls_te_router_cmd); + install_element(VIEW_NODE, &show_ip_ospf_mpls_te_link_cmd); + + install_element(OSPF_NODE, &ospf_mpls_te_on_cmd); + install_element(OSPF_NODE, &no_ospf_mpls_te_cmd); + install_element(OSPF_NODE, &ospf_mpls_te_router_addr_cmd); + install_element(OSPF_NODE, &ospf_mpls_te_inter_as_cmd); + install_element(OSPF_NODE, &ospf_mpls_te_inter_as_area_cmd); + install_element(OSPF_NODE, &no_ospf_mpls_te_inter_as_cmd); + + return; } diff --git a/ospfd/ospf_te.h b/ospfd/ospf_te.h index 885180bc1..4ee9139a3 100644 --- a/ospfd/ospf_te.h +++ b/ospfd/ospf_te.h @@ -98,52 +98,45 @@ * Following section defines TLV (tag, length, value) structures, * used for Traffic Engineering. */ -struct te_tlv_header -{ - u_int16_t type; /* TE_TLV_XXX (see below) */ - u_int16_t length; /* Value portion only, in octets */ +struct te_tlv_header { + u_int16_t type; /* TE_TLV_XXX (see below) */ + u_int16_t length; /* Value portion only, in octets */ }; -#define TLV_HDR_SIZE \ - (sizeof (struct te_tlv_header)) +#define TLV_HDR_SIZE (sizeof(struct te_tlv_header)) -#define TLV_BODY_SIZE(tlvh) \ - (ROUNDUP (ntohs ((tlvh)->length), sizeof (u_int32_t))) +#define TLV_BODY_SIZE(tlvh) (ROUNDUP(ntohs((tlvh)->length), sizeof(u_int32_t))) -#define TLV_SIZE(tlvh) \ - (TLV_HDR_SIZE + TLV_BODY_SIZE(tlvh)) +#define TLV_SIZE(tlvh) (TLV_HDR_SIZE + TLV_BODY_SIZE(tlvh)) -#define TLV_HDR_TOP(lsah) \ +#define TLV_HDR_TOP(lsah) \ (struct te_tlv_header *)((char *)(lsah) + OSPF_LSA_HEADER_SIZE) -#define TLV_HDR_NEXT(tlvh) \ +#define TLV_HDR_NEXT(tlvh) \ (struct te_tlv_header *)((char *)(tlvh) + TLV_SIZE(tlvh)) -#define TLV_HDR_SUBTLV(tlvh) \ +#define TLV_HDR_SUBTLV(tlvh) \ (struct te_tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE) #define TLV_TYPE(tlvh) tlvh.header.type #define TLV_LEN(tlvh) tlvh.header.length #define TLV_HDR(tlvh) tlvh.header - /* * Following section defines TLV body parts. */ /* Router Address TLV */ /* Mandatory */ #define TE_TLV_ROUTER_ADDR 1 -struct te_tlv_router_addr -{ - struct te_tlv_header header; /* Value length is 4 octets. */ - struct in_addr value; +struct te_tlv_router_addr { + struct te_tlv_header header; /* Value length is 4 octets. */ + struct in_addr value; }; /* Link TLV */ #define TE_TLV_LINK 2 -struct te_tlv_link -{ - struct te_tlv_header header; - /* A set of link-sub-TLVs will follow. */ +struct te_tlv_link { + struct te_tlv_header header; + /* A set of link-sub-TLVs will follow. */ }; #define TE_LINK_SUBTLV_DEF_SIZE 4 @@ -151,105 +144,94 @@ struct te_tlv_link /* Link Type Sub-TLV */ /* Mandatory */ #define TE_LINK_SUBTLV_LINK_TYPE 1 #define TE_LINK_SUBTLV_TYPE_SIZE 1 -struct te_link_subtlv_link_type -{ - struct te_tlv_header header; /* Value length is 1 octet. */ - struct - { +struct te_link_subtlv_link_type { + struct te_tlv_header header; /* Value length is 1 octet. */ + struct { #define LINK_TYPE_SUBTLV_VALUE_PTP 1 #define LINK_TYPE_SUBTLV_VALUE_MA 2 - u_char value; - u_char padding[3]; - } link_type; + u_char value; + u_char padding[3]; + } link_type; }; /* Link Sub-TLV: Link ID */ /* Mandatory */ #define TE_LINK_SUBTLV_LINK_ID 2 -struct te_link_subtlv_link_id -{ - struct te_tlv_header header; /* Value length is 4 octets. */ - struct in_addr value; /* Same as router-lsa's link-id. */ +struct te_link_subtlv_link_id { + struct te_tlv_header header; /* Value length is 4 octets. */ + struct in_addr value; /* Same as router-lsa's link-id. */ }; /* Link Sub-TLV: Local Interface IP Address */ /* Optional */ #define TE_LINK_SUBTLV_LCLIF_IPADDR 3 -struct te_link_subtlv_lclif_ipaddr -{ - struct te_tlv_header header; /* Value length is 4 x N octets. */ - struct in_addr value[1]; /* Local IP address(es). */ +struct te_link_subtlv_lclif_ipaddr { + struct te_tlv_header header; /* Value length is 4 x N octets. */ + struct in_addr value[1]; /* Local IP address(es). */ }; /* Link Sub-TLV: Remote Interface IP Address */ /* Optional */ #define TE_LINK_SUBTLV_RMTIF_IPADDR 4 -struct te_link_subtlv_rmtif_ipaddr -{ - struct te_tlv_header header; /* Value length is 4 x N octets. */ - struct in_addr value[1]; /* Neighbor's IP address(es). */ +struct te_link_subtlv_rmtif_ipaddr { + struct te_tlv_header header; /* Value length is 4 x N octets. */ + struct in_addr value[1]; /* Neighbor's IP address(es). */ }; /* Link Sub-TLV: Traffic Engineering Metric */ /* Optional */ #define TE_LINK_SUBTLV_TE_METRIC 5 -struct te_link_subtlv_te_metric -{ - struct te_tlv_header header; /* Value length is 4 octets. */ - u_int32_t value; /* Link metric for TE purpose. */ +struct te_link_subtlv_te_metric { + struct te_tlv_header header; /* Value length is 4 octets. */ + u_int32_t value; /* Link metric for TE purpose. */ }; /* Link Sub-TLV: Maximum Bandwidth */ /* Optional */ #define TE_LINK_SUBTLV_MAX_BW 6 -struct te_link_subtlv_max_bw -{ - struct te_tlv_header header; /* Value length is 4 octets. */ - float value; /* bytes/sec */ +struct te_link_subtlv_max_bw { + struct te_tlv_header header; /* Value length is 4 octets. */ + float value; /* bytes/sec */ }; /* Link Sub-TLV: Maximum Reservable Bandwidth */ /* Optional */ #define TE_LINK_SUBTLV_MAX_RSV_BW 7 -struct te_link_subtlv_max_rsv_bw -{ - struct te_tlv_header header; /* Value length is 4 octets. */ - float value; /* bytes/sec */ +struct te_link_subtlv_max_rsv_bw { + struct te_tlv_header header; /* Value length is 4 octets. */ + float value; /* bytes/sec */ }; /* Link Sub-TLV: Unreserved Bandwidth */ /* Optional */ #define TE_LINK_SUBTLV_UNRSV_BW 8 #define TE_LINK_SUBTLV_UNRSV_SIZE 32 -struct te_link_subtlv_unrsv_bw -{ - struct te_tlv_header header; /* Value length is 32 octets. */ - float value[MAX_CLASS_TYPE]; /* One for each priority level. */ +struct te_link_subtlv_unrsv_bw { + struct te_tlv_header header; /* Value length is 32 octets. */ + float value[MAX_CLASS_TYPE]; /* One for each priority level. */ }; /* Link Sub-TLV: Resource Class/Color */ /* Optional */ #define TE_LINK_SUBTLV_RSC_CLSCLR 9 -struct te_link_subtlv_rsc_clsclr -{ - struct te_tlv_header header; /* Value length is 4 octets. */ - u_int32_t value; /* Admin. group membership. */ +struct te_link_subtlv_rsc_clsclr { + struct te_tlv_header header; /* Value length is 4 octets. */ + u_int32_t value; /* Admin. group membership. */ }; /* For RFC6827 */ /* Local and Remote TE Router ID */ #define TE_LINK_SUBTLV_LRRID 10 #define TE_LINK_SUBTLV_LRRID_SIZE 8 -struct te_link_subtlv_lrrid -{ - struct te_tlv_header header; /* Value length is 8 octets. */ - struct in_addr local; /* Local TE Router Identifier */ - struct in_addr remote; /* Remote TE Router Identifier */ +struct te_link_subtlv_lrrid { + struct te_tlv_header header; /* Value length is 8 octets. */ + struct in_addr local; /* Local TE Router Identifier */ + struct in_addr remote; /* Remote TE Router Identifier */ }; /* RFC4203: Link Local/Remote Identifiers */ #define TE_LINK_SUBTLV_LLRI 11 #define TE_LINK_SUBTLV_LLRI_SIZE 8 -struct te_link_subtlv_llri -{ - struct te_tlv_header header; /* Value length is 8 octets. */ - u_int32_t local; /* Link Local Identifier */ - u_int32_t remote; /* Link Remote Identifier */ +struct te_link_subtlv_llri { + struct te_tlv_header header; /* Value length is 8 octets. */ + u_int32_t local; /* Link Local Identifier */ + u_int32_t remote; /* Link Remote Identifier */ }; -/* Inter-RA Export Upward sub-TLV (12) and Inter-RA Export Downward sub-TLV (13) (RFC6827bis) are not yet supported */ +/* Inter-RA Export Upward sub-TLV (12) and Inter-RA Export Downward sub-TLV (13) + * (RFC6827bis) are not yet supported */ /* SUBTLV 14-16 (RFC4203) are not yet supported */ /* Bandwidth Constraints sub-TLV (17) (RFC4124) is not yet supported */ /* SUBLV 18-20 are for OSPFv3 TE (RFC5329). see ospf6d */ @@ -257,18 +239,16 @@ struct te_link_subtlv_llri /* For RFC 5392 */ /* Remote AS Number sub-TLV */ #define TE_LINK_SUBTLV_RAS 21 -struct te_link_subtlv_ras -{ - struct te_tlv_header header; /* Value length is 4 octets. */ - u_int32_t value; /* Remote AS number */ +struct te_link_subtlv_ras { + struct te_tlv_header header; /* Value length is 4 octets. */ + u_int32_t value; /* Remote AS number */ }; /* IPv4 Remote ASBR ID Sub-TLV */ #define TE_LINK_SUBTLV_RIP 22 -struct te_link_subtlv_rip -{ - struct te_tlv_header header; /* Value length is 4 octets. */ - struct in_addr value; /* Remote ASBR IP address */ +struct te_link_subtlv_rip { + struct te_tlv_header header; /* Value length is 4 octets. */ + struct in_addr value; /* Remote ASBR IP address */ }; /* SUBTLV 24 is IPv6 Remote ASBR ID (RFC5392). see ospf6d */ @@ -280,63 +260,64 @@ struct te_link_subtlv_rip /* RFC7471 */ /* Link Sub-TLV: Average Link Delay */ /* Optional */ #define TE_LINK_SUBTLV_AV_DELAY 27 -struct te_link_subtlv_av_delay -{ - struct te_tlv_header header; /* Value length is 4 bytes. */ - u_int32_t value; /* delay in micro-seconds only 24 bits => 0 ... 16777215 - with Anomalous Bit as Upper most bit */ +struct te_link_subtlv_av_delay { + struct te_tlv_header header; /* Value length is 4 bytes. */ + u_int32_t + value; /* delay in micro-seconds only 24 bits => 0 ... 16777215 + with Anomalous Bit as Upper most bit */ }; /* Link Sub-TLV: Low/High Link Delay */ #define TE_LINK_SUBTLV_MM_DELAY 28 #define TE_LINK_SUBTLV_MM_DELAY_SIZE 8 -struct te_link_subtlv_mm_delay -{ - struct te_tlv_header header; /* Value length is 8 bytes. */ - u_int32_t low; /* low delay in micro-seconds only 24 bits => 0 ... 16777215 - with Anomalous Bit (A) as Upper most bit */ - u_int32_t high; /* high delay in micro-seconds only 24 bits => 0 ... 16777215 */ +struct te_link_subtlv_mm_delay { + struct te_tlv_header header; /* Value length is 8 bytes. */ + u_int32_t low; /* low delay in micro-seconds only 24 bits => 0 ... + 16777215 + with Anomalous Bit (A) as Upper most bit */ + u_int32_t high; /* high delay in micro-seconds only 24 bits => 0 ... + 16777215 */ }; /* Link Sub-TLV: Link Delay Variation i.e. Jitter */ #define TE_LINK_SUBTLV_DELAY_VAR 29 -struct te_link_subtlv_delay_var -{ - struct te_tlv_header header; /* Value length is 4 bytes. */ - u_int32_t value; /* interval in micro-seconds only 24 bits => 0 ... 16777215 */ +struct te_link_subtlv_delay_var { + struct te_tlv_header header; /* Value length is 4 bytes. */ + u_int32_t value; /* interval in micro-seconds only 24 bits => 0 ... + 16777215 */ }; /* Link Sub-TLV: Routine Unidirectional Link Packet Loss */ #define TE_LINK_SUBTLV_PKT_LOSS 30 -struct te_link_subtlv_pkt_loss -{ - struct te_tlv_header header; /* Value length is 4 bytes. */ - u_int32_t value; /* in percentage of total traffic only 24 bits (2^24 - 2) - with Anomalous Bit as Upper most bit */ +struct te_link_subtlv_pkt_loss { + struct te_tlv_header header; /* Value length is 4 bytes. */ + u_int32_t + value; /* in percentage of total traffic only 24 bits (2^24 - 2) + with Anomalous Bit as Upper most bit */ }; /* Link Sub-TLV: Unidirectional Residual Bandwidth */ /* Optional */ #define TE_LINK_SUBTLV_RES_BW 31 -struct te_link_subtlv_res_bw -{ - struct te_tlv_header header; /* Value length is 4 bytes. */ - float value; /* bandwidth in IEEE floating point format with units in bytes per second */ +struct te_link_subtlv_res_bw { + struct te_tlv_header header; /* Value length is 4 bytes. */ + float value; /* bandwidth in IEEE floating point format with units in + bytes per second */ }; /* Link Sub-TLV: Unidirectional Available Bandwidth */ /* Optional */ #define TE_LINK_SUBTLV_AVA_BW 32 -struct te_link_subtlv_ava_bw -{ - struct te_tlv_header header; /* Value length is 4 octets. */ - float value; /* bandwidth in IEEE floating point format with units in bytes per second */ +struct te_link_subtlv_ava_bw { + struct te_tlv_header header; /* Value length is 4 octets. */ + float value; /* bandwidth in IEEE floating point format with units in + bytes per second */ }; /* Link Sub-TLV: Unidirectional Utilized Bandwidth */ /* Optional */ #define TE_LINK_SUBTLV_USE_BW 33 -struct te_link_subtlv_use_bw -{ - struct te_tlv_header header; /* Value length is 4 octets. */ - float value; /* bandwidth in IEEE floating point format with units in bytes per second */ +struct te_link_subtlv_use_bw { + struct te_tlv_header header; /* Value length is 4 octets. */ + float value; /* bandwidth in IEEE floating point format with units in + bytes per second */ }; #define TE_LINK_SUBTLV_MAX 34 /* Last SUBTLV + 1 */ @@ -345,121 +326,121 @@ struct te_link_subtlv_use_bw #define MPLS_TE_MINIMUM_BANDWIDTH 1.0 /* Reasonable? *//* XXX */ /* Following declaration concerns the MPLS-TE and LINk-TE management */ -typedef enum _opcode_t -{ REORIGINATE_THIS_LSA, REFRESH_THIS_LSA, FLUSH_THIS_LSA } opcode_t; +typedef enum _opcode_t { + REORIGINATE_THIS_LSA, + REFRESH_THIS_LSA, + FLUSH_THIS_LSA +} opcode_t; -typedef enum _status_t -{ disabled, enabled } status_t; +typedef enum _status_t { disabled, enabled } status_t; /* Mode for Inter-AS Opaque-LSA */ enum inter_as_mode { Disable, AS, Area }; -struct te_link_subtlv -{ - struct te_tlv_header header; - union - { - u_int32_t link_type; - struct in_addr link_id; - struct in_addr lclif; - struct in_addr rmtif; - u_int32_t te_metric; - float max_bw; - float max_rsv_bw; - float unrsv[8]; - u_int32_t rsc_clsclr; - u_int32_t llri[2]; - u_int32_t ras; - struct in_addr rip; - struct in_addr lrrid[2]; - u_int32_t av_delay; - u_int32_t mm_delay; - u_int32_t delay_var; - u_int32_t pkt_loss; - float res_bw; - float ava_bw; - float use_bw; - } value; +struct te_link_subtlv { + struct te_tlv_header header; + union { + u_int32_t link_type; + struct in_addr link_id; + struct in_addr lclif; + struct in_addr rmtif; + u_int32_t te_metric; + float max_bw; + float max_rsv_bw; + float unrsv[8]; + u_int32_t rsc_clsclr; + u_int32_t llri[2]; + u_int32_t ras; + struct in_addr rip; + struct in_addr lrrid[2]; + u_int32_t av_delay; + u_int32_t mm_delay; + u_int32_t delay_var; + u_int32_t pkt_loss; + float res_bw; + float ava_bw; + float use_bw; + } value; }; /* Following structure are internal use only. */ -struct ospf_mpls_te -{ - /* Status of MPLS-TE: enable or disbale */ - status_t status; +struct ospf_mpls_te { + /* Status of MPLS-TE: enable or disbale */ + status_t status; - /* RFC5392 */ - enum inter_as_mode inter_as; - struct in_addr interas_areaid; + /* RFC5392 */ + enum inter_as_mode inter_as; + struct in_addr interas_areaid; - /* List elements are zebra-interfaces (ifp), not ospf-interfaces (oi). */ - struct list *iflist; + /* List elements are zebra-interfaces (ifp), not ospf-interfaces (oi). + */ + struct list *iflist; - /* Store Router-TLV in network byte order. */ - struct te_tlv_router_addr router_addr; + /* Store Router-TLV in network byte order. */ + struct te_tlv_router_addr router_addr; }; -struct mpls_te_link -{ - /* - * According to MPLS-TE (draft) specification, 24-bit Opaque-ID field - * is subdivided into 8-bit "unused" field and 16-bit "instance" field. - * In this implementation, each Link-TLV has its own instance. - */ - u_int32_t instance; - - /* Reference pointer to a Zebra-interface. */ - struct interface *ifp; - - /* Area info in which this MPLS-TE link belongs to. */ - struct ospf_area *area; - - /* Flags to manage this link parameters. */ - u_int32_t flags; - - /* Type of MPLS-TE link: RFC3630, RFC5392, RFC5392 emulated, RFC6827 */ - u_int8_t type; - - /* Store Link-TLV in network byte order. */ - /* RFC3630 & RFC6827 / RFC 6827 */ - struct te_tlv_link link_header; - struct te_link_subtlv_link_type link_type; - struct te_link_subtlv_link_id link_id; - struct te_link_subtlv_lclif_ipaddr lclif_ipaddr; - struct te_link_subtlv_rmtif_ipaddr rmtif_ipaddr; - struct te_link_subtlv_te_metric te_metric; - struct te_link_subtlv_max_bw max_bw; - struct te_link_subtlv_max_rsv_bw max_rsv_bw; - struct te_link_subtlv_unrsv_bw unrsv_bw; - struct te_link_subtlv_rsc_clsclr rsc_clsclr; - /* RFC4203 */ - struct te_link_subtlv_llri llri; - /* RFC5392 */ - struct te_link_subtlv_ras ras; - struct te_link_subtlv_rip rip; - /* RFC6827 */ - struct te_link_subtlv_lrrid lrrid; - /* RFC7471 */ - struct te_link_subtlv_av_delay av_delay; - struct te_link_subtlv_mm_delay mm_delay; - struct te_link_subtlv_delay_var delay_var; - struct te_link_subtlv_pkt_loss pkt_loss; - struct te_link_subtlv_res_bw res_bw; - struct te_link_subtlv_ava_bw ava_bw; - struct te_link_subtlv_use_bw use_bw; - - struct in_addr adv_router; - struct in_addr id; +struct mpls_te_link { + /* + * According to MPLS-TE (draft) specification, 24-bit Opaque-ID field + * is subdivided into 8-bit "unused" field and 16-bit "instance" field. + * In this implementation, each Link-TLV has its own instance. + */ + u_int32_t instance; + + /* Reference pointer to a Zebra-interface. */ + struct interface *ifp; + + /* Area info in which this MPLS-TE link belongs to. */ + struct ospf_area *area; + + /* Flags to manage this link parameters. */ + u_int32_t flags; + + /* Type of MPLS-TE link: RFC3630, RFC5392, RFC5392 emulated, RFC6827 */ + u_int8_t type; + + /* Store Link-TLV in network byte order. */ + /* RFC3630 & RFC6827 / RFC 6827 */ + struct te_tlv_link link_header; + struct te_link_subtlv_link_type link_type; + struct te_link_subtlv_link_id link_id; + struct te_link_subtlv_lclif_ipaddr lclif_ipaddr; + struct te_link_subtlv_rmtif_ipaddr rmtif_ipaddr; + struct te_link_subtlv_te_metric te_metric; + struct te_link_subtlv_max_bw max_bw; + struct te_link_subtlv_max_rsv_bw max_rsv_bw; + struct te_link_subtlv_unrsv_bw unrsv_bw; + struct te_link_subtlv_rsc_clsclr rsc_clsclr; + /* RFC4203 */ + struct te_link_subtlv_llri llri; + /* RFC5392 */ + struct te_link_subtlv_ras ras; + struct te_link_subtlv_rip rip; + /* RFC6827 */ + struct te_link_subtlv_lrrid lrrid; + /* RFC7471 */ + struct te_link_subtlv_av_delay av_delay; + struct te_link_subtlv_mm_delay mm_delay; + struct te_link_subtlv_delay_var delay_var; + struct te_link_subtlv_pkt_loss pkt_loss; + struct te_link_subtlv_res_bw res_bw; + struct te_link_subtlv_ava_bw ava_bw; + struct te_link_subtlv_use_bw use_bw; + + struct in_addr adv_router; + struct in_addr id; }; /* Prototypes. */ -extern int ospf_mpls_te_init (void); -extern void ospf_mpls_te_term (void); -extern struct ospf_mpls_te *get_ospf_mpls_te (void); -extern void ospf_mpls_te_update_if (struct interface *); -extern void ospf_mpls_te_lsa_schedule (struct mpls_te_link *, opcode_t); -extern u_int32_t get_mpls_te_instance_value (void); -extern void set_linkparams_llri (struct mpls_te_link *, u_int32_t, u_int32_t); -extern void set_linkparams_lrrid (struct mpls_te_link *, struct in_addr, struct in_addr); +extern int ospf_mpls_te_init(void); +extern void ospf_mpls_te_term(void); +extern struct ospf_mpls_te *get_ospf_mpls_te(void); +extern void ospf_mpls_te_update_if(struct interface *); +extern void ospf_mpls_te_lsa_schedule(struct mpls_te_link *, opcode_t); +extern u_int32_t get_mpls_te_instance_value(void); +extern void set_linkparams_llri(struct mpls_te_link *, u_int32_t, u_int32_t); +extern void set_linkparams_lrrid(struct mpls_te_link *, struct in_addr, + struct in_addr); #endif /* _ZEBRA_OSPF_MPLS_TE_H */ diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index f6387b759..55d6c27e8 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -53,88 +53,77 @@ #include "ospfd/ospf_dump.h" #include "ospfd/ospf_bfd.h" -static const char *ospf_network_type_str[] = -{ - "Null", - "POINTOPOINT", - "BROADCAST", - "NBMA", - "POINTOMULTIPOINT", - "VIRTUALLINK", - "LOOPBACK" -}; +static const char *ospf_network_type_str[] = { + "Null", "POINTOPOINT", "BROADCAST", "NBMA", "POINTOMULTIPOINT", + "VIRTUALLINK", "LOOPBACK"}; /* Utility functions. */ -int -str2area_id (const char *str, struct in_addr *area_id, int *area_id_fmt) +int str2area_id(const char *str, struct in_addr *area_id, int *area_id_fmt) { - char *ep; + char *ep; - area_id->s_addr = htonl (strtoul (str, &ep, 10)); - if (*ep && !inet_aton (str, area_id)) - return -1; + area_id->s_addr = htonl(strtoul(str, &ep, 10)); + if (*ep && !inet_aton(str, area_id)) + return -1; - *area_id_fmt = *ep ? OSPF_AREA_ID_FMT_DOTTEDQUAD : OSPF_AREA_ID_FMT_DECIMAL; + *area_id_fmt = + *ep ? OSPF_AREA_ID_FMT_DOTTEDQUAD : OSPF_AREA_ID_FMT_DECIMAL; - return 0; + return 0; } -void -area_id2str (char *buf, int length, struct in_addr *area_id, int area_id_fmt) +void area_id2str(char *buf, int length, struct in_addr *area_id, + int area_id_fmt) { - memset (buf, 0, length); + memset(buf, 0, length); - if (area_id_fmt == OSPF_AREA_ID_FMT_DOTTEDQUAD) - strncpy (buf, inet_ntoa (*area_id), length); - else - sprintf (buf, "%lu", (unsigned long) ntohl (area_id->s_addr)); + if (area_id_fmt == OSPF_AREA_ID_FMT_DOTTEDQUAD) + strncpy(buf, inet_ntoa(*area_id), length); + else + sprintf(buf, "%lu", (unsigned long)ntohl(area_id->s_addr)); } -static int -str2metric (const char *str, int *metric) +static int str2metric(const char *str, int *metric) { - /* Sanity check. */ - if (str == NULL) - return 0; + /* Sanity check. */ + if (str == NULL) + return 0; - *metric = strtol (str, NULL, 10); - if (*metric < 0 && *metric > 16777214) - { - /* vty_out (vty, "OSPF metric value is invalid\n"); */ - return 0; - } + *metric = strtol(str, NULL, 10); + if (*metric < 0 && *metric > 16777214) { + /* vty_out (vty, "OSPF metric value is invalid\n"); */ + return 0; + } - return 1; + return 1; } -static int -str2metric_type (const char *str, int *metric_type) +static int str2metric_type(const char *str, int *metric_type) { - /* Sanity check. */ - if (str == NULL) - return 0; + /* Sanity check. */ + if (str == NULL) + return 0; - if (strncmp (str, "1", 1) == 0) - *metric_type = EXTERNAL_METRIC_TYPE_1; - else if (strncmp (str, "2", 1) == 0) - *metric_type = EXTERNAL_METRIC_TYPE_2; - else - return 0; + if (strncmp(str, "1", 1) == 0) + *metric_type = EXTERNAL_METRIC_TYPE_1; + else if (strncmp(str, "2", 1) == 0) + *metric_type = EXTERNAL_METRIC_TYPE_2; + else + return 0; - return 1; + return 1; } -int -ospf_oi_count (struct interface *ifp) +int ospf_oi_count(struct interface *ifp) { - struct route_node *rn; - int i = 0; + struct route_node *rn; + int i = 0; - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - if (rn->info) - i++; + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) + if (rn->info) + i++; - return i; + return i; } DEFUN_NOSH (router_ospf, @@ -144,33 +133,32 @@ DEFUN_NOSH (router_ospf, "Start OSPF configuration\n" "Instance ID\n") { - struct ospf *ospf; - u_short instance = 0; + struct ospf *ospf; + u_short instance = 0; - ospf = ospf_lookup(); - if (!ospf) - { - vty_out (vty, "There isn't active ospf instance \n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (argc > 2) - instance = strtoul (argv[2]->arg, NULL, 10); - - /* The following logic to set the vty qobj index is in place to be able - to ignore the commands which dont belong to this instance. */ - if (ospf->instance != instance) - VTY_PUSH_CONTEXT_NULL(OSPF_NODE); - else - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Config command 'router ospf %d' received", instance); - ospf->oi_running = 1; - VTY_PUSH_CONTEXT(OSPF_NODE, ospf); - ospf_router_id_update (ospf); - } - - return CMD_SUCCESS; + ospf = ospf_lookup(); + if (!ospf) { + vty_out(vty, "There isn't active ospf instance \n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (argc > 2) + instance = strtoul(argv[2]->arg, NULL, 10); + + /* The following logic to set the vty qobj index is in place to be able + to ignore the commands which dont belong to this instance. */ + if (ospf->instance != instance) + VTY_PUSH_CONTEXT_NULL(OSPF_NODE); + else { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Config command 'router ospf %d' received", + instance); + ospf->oi_running = 1; + VTY_PUSH_CONTEXT(OSPF_NODE, ospf); + ospf_router_id_update(ospf); + } + + return CMD_SUCCESS; } DEFUN (no_router_ospf, @@ -181,18 +169,18 @@ DEFUN (no_router_ospf, "Start OSPF configuration\n" "Instance ID\n") { - struct ospf *ospf; - u_short instance = 0; + struct ospf *ospf; + u_short instance = 0; - if (argc > 3) - instance = strtoul(argv[3]->arg, NULL, 10); + if (argc > 3) + instance = strtoul(argv[3]->arg, NULL, 10); - if ((ospf = ospf_lookup_instance (instance)) == NULL) - return CMD_SUCCESS; + if ((ospf = ospf_lookup_instance(instance)) == NULL) + return CMD_SUCCESS; - ospf_finish (ospf); + ospf_finish(ospf); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -203,33 +191,32 @@ DEFUN (ospf_router_id, "router-id for the OSPF process\n" "OSPF router-id in IP address format\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4 = 2; - struct listnode *node; - struct ospf_area *area; - struct in_addr router_id; - int ret; - - ret = inet_aton (argv[idx_ipv4]->arg, &router_id); - if (!ret) - { - vty_out (vty, "Please specify Router ID by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ospf->router_id_static = router_id; - - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - if (area->full_nbrs) - { - vty_out (vty, "For this router-id change to take effect," - " save config and restart ospfd\n"); - return CMD_SUCCESS; - } - - ospf_router_id_update (ospf); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4 = 2; + struct listnode *node; + struct ospf_area *area; + struct in_addr router_id; + int ret; + + ret = inet_aton(argv[idx_ipv4]->arg, &router_id); + if (!ret) { + vty_out(vty, "Please specify Router ID by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ospf->router_id_static = router_id; + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) + if (area->full_nbrs) { + vty_out(vty, + "For this router-id change to take effect," + " save config and restart ospfd\n"); + return CMD_SUCCESS; + } + + ospf_router_id_update(ospf); + + return CMD_SUCCESS; } DEFUN_HIDDEN (ospf_router_id_old, @@ -238,33 +225,32 @@ DEFUN_HIDDEN (ospf_router_id_old, "router-id for the OSPF process\n" "OSPF router-id in IP address format\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4 = 1; - struct listnode *node; - struct ospf_area *area; - struct in_addr router_id; - int ret; - - ret = inet_aton (argv[idx_ipv4]->arg, &router_id); - if (!ret) - { - vty_out (vty, "Please specify Router ID by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ospf->router_id_static = router_id; - - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - if (area->full_nbrs) - { - vty_out (vty, "For this router-id change to take effect," - " save config and restart ospfd\n"); - return CMD_SUCCESS; - } - - ospf_router_id_update (ospf); + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4 = 1; + struct listnode *node; + struct ospf_area *area; + struct in_addr router_id; + int ret; + + ret = inet_aton(argv[idx_ipv4]->arg, &router_id); + if (!ret) { + vty_out(vty, "Please specify Router ID by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + ospf->router_id_static = router_id; + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) + if (area->full_nbrs) { + vty_out(vty, + "For this router-id change to take effect," + " save config and restart ospfd\n"); + return CMD_SUCCESS; + } + + ospf_router_id_update(ospf); + + return CMD_SUCCESS; } DEFUN (no_ospf_router_id, @@ -275,87 +261,85 @@ DEFUN (no_ospf_router_id, "router-id for the OSPF process\n" "OSPF router-id in IP address format\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - struct listnode *node; - struct ospf_area *area; + VTY_DECLVAR_CONTEXT(ospf, ospf); + struct listnode *node; + struct ospf_area *area; - ospf->router_id_static.s_addr = 0; + ospf->router_id_static.s_addr = 0; - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - if (area->full_nbrs) - { - vty_out (vty, "For this router-id change to take effect," - " save config and restart ospfd\n"); - return CMD_SUCCESS; - } + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) + if (area->full_nbrs) { + vty_out(vty, + "For this router-id change to take effect," + " save config and restart ospfd\n"); + return CMD_SUCCESS; + } - ospf_router_id_update (ospf); + ospf_router_id_update(ospf); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static void -ospf_passive_interface_default (struct ospf *ospf, u_char newval) -{ - struct listnode *ln; - struct interface *ifp; - struct ospf_interface *oi; - - ospf->passive_interface_default = newval; - - for (ALL_LIST_ELEMENTS_RO (om->iflist, ln, ifp)) - { - if (ifp && - OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), passive_interface)) - UNSET_IF_PARAM (IF_DEF_PARAMS (ifp), passive_interface); - } - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, ln, oi)) - { - if (OSPF_IF_PARAM_CONFIGURED (oi->params, passive_interface)) - UNSET_IF_PARAM (oi->params, passive_interface); - /* update multicast memberships */ - ospf_if_set_multicast(oi); - } -} - -static void -ospf_passive_interface_update_addr (struct ospf *ospf, struct interface *ifp, - struct ospf_if_params *params, u_char value, - struct in_addr addr) -{ - u_char dflt; - - params->passive_interface = value; - if (params != IF_DEF_PARAMS (ifp)) - { - if (OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), passive_interface)) - dflt = IF_DEF_PARAMS (ifp)->passive_interface; - else - dflt = ospf->passive_interface_default; - - if (value != dflt) - SET_IF_PARAM (params, passive_interface); - else - UNSET_IF_PARAM (params, passive_interface); - - ospf_free_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } -} - -static void -ospf_passive_interface_update (struct ospf *ospf, struct interface *ifp, - struct ospf_if_params *params, u_char value) -{ - params->passive_interface = value; - if (params == IF_DEF_PARAMS (ifp)) - { - if (value != ospf->passive_interface_default) - SET_IF_PARAM (params, passive_interface); - else - UNSET_IF_PARAM (params, passive_interface); - } +static void ospf_passive_interface_default(struct ospf *ospf, u_char newval) +{ + struct listnode *ln; + struct interface *ifp; + struct ospf_interface *oi; + + ospf->passive_interface_default = newval; + + for (ALL_LIST_ELEMENTS_RO(om->iflist, ln, ifp)) { + if (ifp && OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(ifp), + passive_interface)) + UNSET_IF_PARAM(IF_DEF_PARAMS(ifp), passive_interface); + } + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, ln, oi)) { + if (OSPF_IF_PARAM_CONFIGURED(oi->params, passive_interface)) + UNSET_IF_PARAM(oi->params, passive_interface); + /* update multicast memberships */ + ospf_if_set_multicast(oi); + } +} + +static void ospf_passive_interface_update_addr(struct ospf *ospf, + struct interface *ifp, + struct ospf_if_params *params, + u_char value, + struct in_addr addr) +{ + u_char dflt; + + params->passive_interface = value; + if (params != IF_DEF_PARAMS(ifp)) { + if (OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(ifp), + passive_interface)) + dflt = IF_DEF_PARAMS(ifp)->passive_interface; + else + dflt = ospf->passive_interface_default; + + if (value != dflt) + SET_IF_PARAM(params, passive_interface); + else + UNSET_IF_PARAM(params, passive_interface); + + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } +} + +static void ospf_passive_interface_update(struct ospf *ospf, + struct interface *ifp, + struct ospf_if_params *params, + u_char value) +{ + params->passive_interface = value; + if (params == IF_DEF_PARAMS(ifp)) { + if (value != ospf->passive_interface_default) + SET_IF_PARAM(params, passive_interface); + else + UNSET_IF_PARAM(params, passive_interface); + } } DEFUN (ospf_passive_interface, @@ -366,64 +350,62 @@ DEFUN (ospf_passive_interface, "IPv4 address\n" "Suppress routing updates on interfaces by default\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4 = 2; - struct interface *ifp; - struct in_addr addr = { .s_addr = INADDR_ANY }; - int ret; - struct ospf_if_params *params; - struct route_node *rn; - - if (strmatch(argv[1]->text, "default")) - { - ospf_passive_interface_default (ospf, OSPF_IF_PASSIVE); - return CMD_SUCCESS; - } - - ifp = if_get_by_name (argv[1]->arg, VRF_DEFAULT); - - params = IF_DEF_PARAMS (ifp); - - if (argc == 3) - { - ret = inet_aton(argv[idx_ipv4]->arg, &addr); - if (!ret) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - params = ospf_get_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - ospf_passive_interface_update_addr (ospf, ifp, params, - OSPF_IF_PASSIVE, addr); - } - - ospf_passive_interface_update (ospf, ifp, params, OSPF_IF_PASSIVE); - - /* XXX We should call ospf_if_set_multicast on exactly those - * interfaces for which the passive property changed. It is too much - * work to determine this set, so we do this for every interface. - * This is safe and reasonable because ospf_if_set_multicast uses a - * record of joined groups to avoid systems calls if the desired - * memberships match the current memership. - */ - - for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next (rn)) - { - struct ospf_interface *oi = rn->info; - - if (oi && (OSPF_IF_PARAM(oi, passive_interface) == OSPF_IF_PASSIVE)) - ospf_if_set_multicast(oi); - } - /* - * XXX It is not clear what state transitions the interface needs to - * undergo when going from active to passive. Fixing this will - * require precise identification of interfaces having such a - * transition. - */ - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4 = 2; + struct interface *ifp; + struct in_addr addr = {.s_addr = INADDR_ANY}; + int ret; + struct ospf_if_params *params; + struct route_node *rn; + + if (strmatch(argv[1]->text, "default")) { + ospf_passive_interface_default(ospf, OSPF_IF_PASSIVE); + return CMD_SUCCESS; + } + + ifp = if_get_by_name(argv[1]->arg, VRF_DEFAULT); + + params = IF_DEF_PARAMS(ifp); + + if (argc == 3) { + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + ospf_passive_interface_update_addr(ospf, ifp, params, + OSPF_IF_PASSIVE, addr); + } + + ospf_passive_interface_update(ospf, ifp, params, OSPF_IF_PASSIVE); + + /* XXX We should call ospf_if_set_multicast on exactly those + * interfaces for which the passive property changed. It is too much + * work to determine this set, so we do this for every interface. + * This is safe and reasonable because ospf_if_set_multicast uses a + * record of joined groups to avoid systems calls if the desired + * memberships match the current memership. + */ + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi = rn->info; + + if (oi && (OSPF_IF_PARAM(oi, passive_interface) + == OSPF_IF_PASSIVE)) + ospf_if_set_multicast(oi); + } + /* + * XXX It is not clear what state transitions the interface needs to + * undergo when going from active to passive. Fixing this will + * require precise identification of interfaces having such a + * transition. + */ + + return CMD_SUCCESS; } DEFUN (no_ospf_passive_interface, @@ -435,61 +417,58 @@ DEFUN (no_ospf_passive_interface, "IPv4 address\n" "Allow routing updates on interfaces by default\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4 = 3; - struct interface *ifp; - struct in_addr addr = { .s_addr = INADDR_ANY }; - struct ospf_if_params *params; - int ret; - struct route_node *rn; - - if (strmatch(argv[2]->text, "default")) - { - ospf_passive_interface_default (ospf, OSPF_IF_ACTIVE); - return CMD_SUCCESS; - } - - ifp = if_get_by_name (argv[2]->arg, VRF_DEFAULT); - - params = IF_DEF_PARAMS (ifp); - - if (argc == 4) - { - ret = inet_aton(argv[idx_ipv4]->arg, &addr); - if (!ret) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4 = 3; + struct interface *ifp; + struct in_addr addr = {.s_addr = INADDR_ANY}; + struct ospf_if_params *params; + int ret; + struct route_node *rn; + + if (strmatch(argv[2]->text, "default")) { + ospf_passive_interface_default(ospf, OSPF_IF_ACTIVE); + return CMD_SUCCESS; } - params = ospf_lookup_if_params (ifp, addr); - if (params == NULL) - return CMD_SUCCESS; - ospf_passive_interface_update_addr (ospf, ifp, params, OSPF_IF_ACTIVE, - addr); - } - ospf_passive_interface_update (ospf, ifp, params, OSPF_IF_ACTIVE); - - /* XXX We should call ospf_if_set_multicast on exactly those - * interfaces for which the passive property changed. It is too much - * work to determine this set, so we do this for every interface. - * This is safe and reasonable because ospf_if_set_multicast uses a - * record of joined groups to avoid systems calls if the desired - * memberships match the current memership. - */ - for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next (rn)) - { - struct ospf_interface *oi = rn->info; - - if (oi && (OSPF_IF_PARAM(oi, passive_interface) == OSPF_IF_ACTIVE)) - ospf_if_set_multicast(oi); - } + ifp = if_get_by_name(argv[2]->arg, VRF_DEFAULT); - return CMD_SUCCESS; + params = IF_DEF_PARAMS(ifp); + + if (argc == 4) { + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) + return CMD_SUCCESS; + ospf_passive_interface_update_addr(ospf, ifp, params, + OSPF_IF_ACTIVE, addr); + } + ospf_passive_interface_update(ospf, ifp, params, OSPF_IF_ACTIVE); + + /* XXX We should call ospf_if_set_multicast on exactly those + * interfaces for which the passive property changed. It is too much + * work to determine this set, so we do this for every interface. + * This is safe and reasonable because ospf_if_set_multicast uses a + * record of joined groups to avoid systems calls if the desired + * memberships match the current memership. + */ + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi = rn->info; + + if (oi + && (OSPF_IF_PARAM(oi, passive_interface) == OSPF_IF_ACTIVE)) + ospf_if_set_multicast(oi); + } + + return CMD_SUCCESS; } - DEFUN (ospf_network_area, ospf_network_area_cmd, "network A.B.C.D/M area ", @@ -499,37 +478,36 @@ DEFUN (ospf_network_area, "OSPF area ID in IP address format\n" "OSPF area ID as a decimal value\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_prefixlen = 1; - int idx_ipv4_number = 3; - struct prefix_ipv4 p; - struct in_addr area_id; - int ret, format; - - if (ospf->instance) - { - vty_out (vty, "The network command is not supported in multi-instance ospf\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (ospf->if_ospf_cli_count > 0) - { - vty_out (vty, "Please remove all ip ospf area x.x.x.x commands first.\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Get network prefix and Area ID. */ - str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); - VTY_GET_OSPF_AREA_ID (area_id, format, argv[idx_ipv4_number]->arg); - - ret = ospf_network_set (ospf, &p, area_id, format); - if (ret == 0) - { - vty_out (vty, "There is already same network statement.\n"); - return CMD_WARNING_CONFIG_FAILED; - } + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_prefixlen = 1; + int idx_ipv4_number = 3; + struct prefix_ipv4 p; + struct in_addr area_id; + int ret, format; + + if (ospf->instance) { + vty_out(vty, + "The network command is not supported in multi-instance ospf\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + if (ospf->if_ospf_cli_count > 0) { + vty_out(vty, + "Please remove all ip ospf area x.x.x.x commands first.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Get network prefix and Area ID. */ + str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + + ret = ospf_network_set(ospf, &p, area_id, format); + if (ret == 0) { + vty_out(vty, "There is already same network statement.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } DEFUN (no_ospf_network_area, @@ -542,31 +520,31 @@ DEFUN (no_ospf_network_area, "OSPF area ID in IP address format\n" "OSPF area ID as a decimal value\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_prefixlen = 2; - int idx_ipv4_number = 4; - struct prefix_ipv4 p; - struct in_addr area_id; - int ret, format; - - if (ospf->instance) - { - vty_out (vty, "The network command is not supported in multi-instance ospf\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Get network prefix and Area ID. */ - str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); - VTY_GET_OSPF_AREA_ID (area_id, format, argv[idx_ipv4_number]->arg); - - ret = ospf_network_unset (ospf, &p, area_id); - if (ret == 0) - { - vty_out (vty, "Can't find specified network area configuration.\n"); - return CMD_WARNING_CONFIG_FAILED; - } + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_prefixlen = 2; + int idx_ipv4_number = 4; + struct prefix_ipv4 p; + struct in_addr area_id; + int ret, format; + + if (ospf->instance) { + vty_out(vty, + "The network command is not supported in multi-instance ospf\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + /* Get network prefix and Area ID. */ + str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + + ret = ospf_network_unset(ospf, &p, area_id); + if (ret == 0) { + vty_out(vty, + "Can't find specified network area configuration.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } DEFUN (ospf_area_range, @@ -581,26 +559,25 @@ DEFUN (ospf_area_range, "User specified metric for this range\n" "Advertised metric for this range\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 1; - int idx_ipv4_prefixlen = 3; - int idx_cost = 6; - struct prefix_ipv4 p; - struct in_addr area_id; - int format; - u_int32_t cost; - - VTY_GET_OSPF_AREA_ID (area_id, format, argv[idx_ipv4_number]->arg); - str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); - - ospf_area_range_set (ospf, area_id, &p, OSPF_AREA_RANGE_ADVERTISE); - if (argc > 5) - { - cost = strtoul(argv[idx_cost]->arg, NULL, 10); - ospf_area_range_cost_set (ospf, area_id, &p, cost); - } + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + int idx_ipv4_prefixlen = 3; + int idx_cost = 6; + struct prefix_ipv4 p; + struct in_addr area_id; + int format; + u_int32_t cost; + + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + + ospf_area_range_set(ospf, area_id, &p, OSPF_AREA_RANGE_ADVERTISE); + if (argc > 5) { + cost = strtoul(argv[idx_cost]->arg, NULL, 10); + ospf_area_range_cost_set(ospf, area_id, &p, cost); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ospf_area_range_cost, @@ -614,25 +591,26 @@ DEFUN (ospf_area_range_cost, "User specified metric for this range\n" "Advertised metric for this range\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 1; - int idx_ipv4_prefixlen = 3; - int idx_cost = 5; - struct prefix_ipv4 p; - struct in_addr area_id; - int format; - u_int32_t cost; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + int idx_ipv4_prefixlen = 3; + int idx_cost = 5; + struct prefix_ipv4 p; + struct in_addr area_id; + int format; + u_int32_t cost; - VTY_GET_OSPF_AREA_ID (area_id, format, argv[idx_ipv4_number]->arg); - str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); - ospf_area_range_set (ospf, area_id, &p, OSPF_AREA_RANGE_ADVERTISE); - ospf_area_display_format_set (ospf, ospf_area_get (ospf, area_id), format); + ospf_area_range_set(ospf, area_id, &p, OSPF_AREA_RANGE_ADVERTISE); + ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id), + format); - cost = strtoul(argv[idx_cost]->arg, NULL, 10); - ospf_area_range_cost_set (ospf, area_id, &p, cost); + cost = strtoul(argv[idx_cost]->arg, NULL, 10); + ospf_area_range_cost_set(ospf, area_id, &p, cost); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ospf_area_range_not_advertise, @@ -645,20 +623,21 @@ DEFUN (ospf_area_range_not_advertise, "Area range prefix\n" "DoNotAdvertise this range\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 1; - int idx_ipv4_prefixlen = 3; - struct prefix_ipv4 p; - struct in_addr area_id; - int format; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + int idx_ipv4_prefixlen = 3; + struct prefix_ipv4 p; + struct in_addr area_id; + int format; - VTY_GET_OSPF_AREA_ID (area_id, format, argv[idx_ipv4_number]->arg); - str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); - ospf_area_range_set (ospf, area_id, &p, 0); - ospf_area_display_format_set (ospf, ospf_area_get (ospf, area_id), format); + ospf_area_range_set(ospf, area_id, &p, 0); + ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id), + format); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf_area_range, @@ -677,19 +656,19 @@ DEFUN (no_ospf_area_range, "Advertised metric for this range\n" "DoNotAdvertise this range\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 2; - int idx_ipv4_prefixlen = 4; - struct prefix_ipv4 p; - struct in_addr area_id; - int format; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + int idx_ipv4_prefixlen = 4; + struct prefix_ipv4 p; + struct in_addr area_id; + int format; - VTY_GET_OSPF_AREA_ID (area_id, format, argv[idx_ipv4_number]->arg); - str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); - ospf_area_range_unset (ospf, area_id, &p); + ospf_area_range_unset(ospf, area_id, &p); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ospf_area_range_substitute, @@ -703,22 +682,23 @@ DEFUN (ospf_area_range_substitute, "Announce area range as another prefix\n" "Network prefix to be announced instead of range\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 1; - int idx_ipv4_prefixlen = 3; - int idx_ipv4_prefixlen_2 = 5; - struct prefix_ipv4 p, s; - struct in_addr area_id; - int format; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + int idx_ipv4_prefixlen = 3; + int idx_ipv4_prefixlen_2 = 5; + struct prefix_ipv4 p, s; + struct in_addr area_id; + int format; - VTY_GET_OSPF_AREA_ID (area_id, format, argv[idx_ipv4_number]->arg); - str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); - str2prefix_ipv4(argv[idx_ipv4_prefixlen_2]->arg, &s); + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + str2prefix_ipv4(argv[idx_ipv4_prefixlen_2]->arg, &s); - ospf_area_range_substitute_set (ospf, area_id, &p, &s); - ospf_area_display_format_set (ospf, ospf_area_get (ospf, area_id), format); + ospf_area_range_substitute_set(ospf, area_id, &p, &s); + ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id), + format); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf_area_range_substitute, @@ -733,21 +713,21 @@ DEFUN (no_ospf_area_range_substitute, "Announce area range as another prefix\n" "Network prefix to be announced instead of range\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 2; - int idx_ipv4_prefixlen = 4; - int idx_ipv4_prefixlen_2 = 6; - struct prefix_ipv4 p, s; - struct in_addr area_id; - int format; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + int idx_ipv4_prefixlen = 4; + int idx_ipv4_prefixlen_2 = 6; + struct prefix_ipv4 p, s; + struct in_addr area_id; + int format; - VTY_GET_OSPF_AREA_ID (area_id, format, argv[idx_ipv4_number]->arg); - str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); - str2prefix_ipv4(argv[idx_ipv4_prefixlen_2]->arg, &s); + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + str2prefix_ipv4(argv[idx_ipv4_prefixlen_2]->arg, &s); - ospf_area_range_substitute_unset (ospf, area_id, &p); + ospf_area_range_substitute_unset(ospf, area_id, &p); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -762,243 +742,232 @@ DEFUN (no_ospf_area_range_substitute, bacckend handler. This is to drastically reduce the verbeage required to coe up with a reasonably compatible Cisco VLink command - - Matthew Grant + - Matthew Grant Wed, 21 Feb 2001 15:13:52 +1300 */ -/* Configuration data for virtual links - */ +/* Configuration data for virtual links + */ struct ospf_vl_config_data { - struct vty *vty; /* vty stuff */ - struct in_addr area_id; /* area ID from command line */ - int area_id_fmt; /* command line area ID format */ - struct in_addr vl_peer; /* command line vl_peer */ - int auth_type; /* Authehntication type, if given */ - char *auth_key; /* simple password if present */ - int crypto_key_id; /* Cryptographic key ID */ - char *md5_key; /* MD5 authentication key */ - int hello_interval; /* Obvious what these are... */ - int retransmit_interval; - int transmit_delay; - int dead_interval; + struct vty *vty; /* vty stuff */ + struct in_addr area_id; /* area ID from command line */ + int area_id_fmt; /* command line area ID format */ + struct in_addr vl_peer; /* command line vl_peer */ + int auth_type; /* Authehntication type, if given */ + char *auth_key; /* simple password if present */ + int crypto_key_id; /* Cryptographic key ID */ + char *md5_key; /* MD5 authentication key */ + int hello_interval; /* Obvious what these are... */ + int retransmit_interval; + int transmit_delay; + int dead_interval; }; -static void -ospf_vl_config_data_init (struct ospf_vl_config_data *vl_config, - struct vty *vty) +static void ospf_vl_config_data_init(struct ospf_vl_config_data *vl_config, + struct vty *vty) { - memset (vl_config, 0, sizeof (struct ospf_vl_config_data)); - vl_config->auth_type = OSPF_AUTH_CMD_NOTSEEN; - vl_config->vty = vty; + memset(vl_config, 0, sizeof(struct ospf_vl_config_data)); + vl_config->auth_type = OSPF_AUTH_CMD_NOTSEEN; + vl_config->vty = vty; } static struct ospf_vl_data * -ospf_find_vl_data (struct ospf *ospf, struct ospf_vl_config_data *vl_config) -{ - struct ospf_area *area; - struct ospf_vl_data *vl_data; - struct vty *vty; - struct in_addr area_id; - - vty = vl_config->vty; - area_id = vl_config->area_id; - - if (area_id.s_addr == OSPF_AREA_BACKBONE) - { - vty_out (vty, - "Configuring VLs over the backbone is not allowed\n"); - return NULL; - } - area = ospf_area_get (ospf, area_id); - ospf_area_display_format_set (ospf, area, vl_config->area_id_fmt); - - if (area->external_routing != OSPF_AREA_DEFAULT) - { - if (vl_config->area_id_fmt == OSPF_AREA_ID_FMT_DOTTEDQUAD) - vty_out (vty, "Area %s is %s\n", - inet_ntoa (area_id), - area->external_routing == OSPF_AREA_NSSA?"nssa":"stub"); - else - vty_out (vty, "Area %ld is %s\n", - (u_long)ntohl (area_id.s_addr), - area->external_routing == OSPF_AREA_NSSA?"nssa":"stub"); - return NULL; - } - - if ((vl_data = ospf_vl_lookup (ospf, area, vl_config->vl_peer)) == NULL) - { - vl_data = ospf_vl_data_new (area, vl_config->vl_peer); - if (vl_data->vl_oi == NULL) - { - vl_data->vl_oi = ospf_vl_new (ospf, vl_data); - ospf_vl_add (ospf, vl_data); - ospf_spf_calculate_schedule (ospf, SPF_FLAG_CONFIG_CHANGE); +ospf_find_vl_data(struct ospf *ospf, struct ospf_vl_config_data *vl_config) +{ + struct ospf_area *area; + struct ospf_vl_data *vl_data; + struct vty *vty; + struct in_addr area_id; + + vty = vl_config->vty; + area_id = vl_config->area_id; + + if (area_id.s_addr == OSPF_AREA_BACKBONE) { + vty_out(vty, + "Configuring VLs over the backbone is not allowed\n"); + return NULL; + } + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, vl_config->area_id_fmt); + + if (area->external_routing != OSPF_AREA_DEFAULT) { + if (vl_config->area_id_fmt == OSPF_AREA_ID_FMT_DOTTEDQUAD) + vty_out(vty, "Area %s is %s\n", inet_ntoa(area_id), + area->external_routing == OSPF_AREA_NSSA + ? "nssa" + : "stub"); + else + vty_out(vty, "Area %ld is %s\n", + (u_long)ntohl(area_id.s_addr), + area->external_routing == OSPF_AREA_NSSA + ? "nssa" + : "stub"); + return NULL; + } + + if ((vl_data = ospf_vl_lookup(ospf, area, vl_config->vl_peer)) + == NULL) { + vl_data = ospf_vl_data_new(area, vl_config->vl_peer); + if (vl_data->vl_oi == NULL) { + vl_data->vl_oi = ospf_vl_new(ospf, vl_data); + ospf_vl_add(ospf, vl_data); + ospf_spf_calculate_schedule(ospf, + SPF_FLAG_CONFIG_CHANGE); + } } - } - return vl_data; + return vl_data; } -static int -ospf_vl_set_security (struct ospf_vl_data *vl_data, - struct ospf_vl_config_data *vl_config) -{ - struct crypt_key *ck; - struct vty *vty; - struct interface *ifp = vl_data->vl_oi->ifp; - - vty = vl_config->vty; - - if (vl_config->auth_type != OSPF_AUTH_CMD_NOTSEEN) - { - SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_type); - IF_DEF_PARAMS (ifp)->auth_type = vl_config->auth_type; - } - - if (vl_config->auth_key) - { - memset(IF_DEF_PARAMS (ifp)->auth_simple, 0, OSPF_AUTH_SIMPLE_SIZE+1); - strncpy ((char *) IF_DEF_PARAMS (ifp)->auth_simple, vl_config->auth_key, - OSPF_AUTH_SIMPLE_SIZE); - } - else if (vl_config->md5_key) - { - if (ospf_crypt_key_lookup (IF_DEF_PARAMS (ifp)->auth_crypt, vl_config->crypto_key_id) - != NULL) - { - vty_out (vty, "OSPF: Key %d already exists\n", - vl_config->crypto_key_id); - return CMD_WARNING_CONFIG_FAILED; - } - ck = ospf_crypt_key_new (); - ck->key_id = vl_config->crypto_key_id; - memset(ck->auth_key, 0, OSPF_AUTH_MD5_SIZE+1); - strncpy ((char *) ck->auth_key, vl_config->md5_key, OSPF_AUTH_MD5_SIZE); - - ospf_crypt_key_add (IF_DEF_PARAMS (ifp)->auth_crypt, ck); - } - else if (vl_config->crypto_key_id != 0) - { - /* Delete a key */ - - if (ospf_crypt_key_lookup (IF_DEF_PARAMS (ifp)->auth_crypt, - vl_config->crypto_key_id) == NULL) - { - vty_out (vty, "OSPF: Key %d does not exist\n", - vl_config->crypto_key_id); - return CMD_WARNING_CONFIG_FAILED; +static int ospf_vl_set_security(struct ospf_vl_data *vl_data, + struct ospf_vl_config_data *vl_config) +{ + struct crypt_key *ck; + struct vty *vty; + struct interface *ifp = vl_data->vl_oi->ifp; + + vty = vl_config->vty; + + if (vl_config->auth_type != OSPF_AUTH_CMD_NOTSEEN) { + SET_IF_PARAM(IF_DEF_PARAMS(ifp), auth_type); + IF_DEF_PARAMS(ifp)->auth_type = vl_config->auth_type; } - - ospf_crypt_key_delete (IF_DEF_PARAMS (ifp)->auth_crypt, vl_config->crypto_key_id); - } - - return CMD_SUCCESS; + if (vl_config->auth_key) { + memset(IF_DEF_PARAMS(ifp)->auth_simple, 0, + OSPF_AUTH_SIMPLE_SIZE + 1); + strncpy((char *)IF_DEF_PARAMS(ifp)->auth_simple, + vl_config->auth_key, OSPF_AUTH_SIMPLE_SIZE); + } else if (vl_config->md5_key) { + if (ospf_crypt_key_lookup(IF_DEF_PARAMS(ifp)->auth_crypt, + vl_config->crypto_key_id) + != NULL) { + vty_out(vty, "OSPF: Key %d already exists\n", + vl_config->crypto_key_id); + return CMD_WARNING_CONFIG_FAILED; + } + ck = ospf_crypt_key_new(); + ck->key_id = vl_config->crypto_key_id; + memset(ck->auth_key, 0, OSPF_AUTH_MD5_SIZE + 1); + strncpy((char *)ck->auth_key, vl_config->md5_key, + OSPF_AUTH_MD5_SIZE); + + ospf_crypt_key_add(IF_DEF_PARAMS(ifp)->auth_crypt, ck); + } else if (vl_config->crypto_key_id != 0) { + /* Delete a key */ + + if (ospf_crypt_key_lookup(IF_DEF_PARAMS(ifp)->auth_crypt, + vl_config->crypto_key_id) + == NULL) { + vty_out(vty, "OSPF: Key %d does not exist\n", + vl_config->crypto_key_id); + return CMD_WARNING_CONFIG_FAILED; + } + + ospf_crypt_key_delete(IF_DEF_PARAMS(ifp)->auth_crypt, + vl_config->crypto_key_id); + } + + return CMD_SUCCESS; } -static int -ospf_vl_set_timers (struct ospf_vl_data *vl_data, - struct ospf_vl_config_data *vl_config) -{ - struct interface *ifp = vl_data->vl_oi->ifp; - /* Virtual Link data initialised to defaults, so only set - if a value given */ - if (vl_config->hello_interval) - { - SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_hello); - IF_DEF_PARAMS (ifp)->v_hello = vl_config->hello_interval; - } - - if (vl_config->dead_interval) - { - SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_wait); - IF_DEF_PARAMS (ifp)->v_wait = vl_config->dead_interval; - } - - if (vl_config->retransmit_interval) - { - SET_IF_PARAM (IF_DEF_PARAMS (ifp), retransmit_interval); - IF_DEF_PARAMS (ifp)->retransmit_interval = vl_config->retransmit_interval; - } - - if (vl_config->transmit_delay) - { - SET_IF_PARAM (IF_DEF_PARAMS (ifp), transmit_delay); - IF_DEF_PARAMS (ifp)->transmit_delay = vl_config->transmit_delay; - } - - return CMD_SUCCESS; +static int ospf_vl_set_timers(struct ospf_vl_data *vl_data, + struct ospf_vl_config_data *vl_config) +{ + struct interface *ifp = vl_data->vl_oi->ifp; + /* Virtual Link data initialised to defaults, so only set + if a value given */ + if (vl_config->hello_interval) { + SET_IF_PARAM(IF_DEF_PARAMS(ifp), v_hello); + IF_DEF_PARAMS(ifp)->v_hello = vl_config->hello_interval; + } + + if (vl_config->dead_interval) { + SET_IF_PARAM(IF_DEF_PARAMS(ifp), v_wait); + IF_DEF_PARAMS(ifp)->v_wait = vl_config->dead_interval; + } + + if (vl_config->retransmit_interval) { + SET_IF_PARAM(IF_DEF_PARAMS(ifp), retransmit_interval); + IF_DEF_PARAMS(ifp)->retransmit_interval = + vl_config->retransmit_interval; + } + + if (vl_config->transmit_delay) { + SET_IF_PARAM(IF_DEF_PARAMS(ifp), transmit_delay); + IF_DEF_PARAMS(ifp)->transmit_delay = vl_config->transmit_delay; + } + + return CMD_SUCCESS; } /* The business end of all of the above */ -static int -ospf_vl_set (struct ospf *ospf, struct ospf_vl_config_data *vl_config) -{ - struct ospf_vl_data *vl_data; - int ret; - - vl_data = ospf_find_vl_data (ospf, vl_config); - if (!vl_data) - return CMD_WARNING_CONFIG_FAILED; - - /* Process this one first as it can have a fatal result, which can - only logically occur if the virtual link exists already - Thus a command error does not result in a change to the - running configuration such as unexpectedly altered timer - values etc.*/ - ret = ospf_vl_set_security (vl_data, vl_config); - if (ret != CMD_SUCCESS) - return ret; - - /* Set any time based parameters, these area already range checked */ - - ret = ospf_vl_set_timers (vl_data, vl_config); - if (ret != CMD_SUCCESS) - return ret; +static int ospf_vl_set(struct ospf *ospf, struct ospf_vl_config_data *vl_config) +{ + struct ospf_vl_data *vl_data; + int ret; - return CMD_SUCCESS; + vl_data = ospf_find_vl_data(ospf, vl_config); + if (!vl_data) + return CMD_WARNING_CONFIG_FAILED; + + /* Process this one first as it can have a fatal result, which can + only logically occur if the virtual link exists already + Thus a command error does not result in a change to the + running configuration such as unexpectedly altered timer + values etc.*/ + ret = ospf_vl_set_security(vl_data, vl_config); + if (ret != CMD_SUCCESS) + return ret; + + /* Set any time based parameters, these area already range checked */ + + ret = ospf_vl_set_timers(vl_data, vl_config); + if (ret != CMD_SUCCESS) + return ret; + return CMD_SUCCESS; } /* This stuff exists to make specifying all the alias commands A LOT simpler */ -#define VLINK_HELPSTR_IPADDR \ - "OSPF area parameters\n" \ - "OSPF area ID in IP address format\n" \ - "OSPF area ID as a decimal value\n" \ - "Configure a virtual link\n" \ - "Router ID of the remote ABR\n" - -#define VLINK_HELPSTR_AUTHTYPE_SIMPLE \ - "Enable authentication on this virtual link\n" \ - "dummy string \n" - -#define VLINK_HELPSTR_AUTHTYPE_ALL \ - VLINK_HELPSTR_AUTHTYPE_SIMPLE \ - "Use null authentication\n" \ - "Use message-digest authentication\n" - -#define VLINK_HELPSTR_TIME_PARAM \ - "Time between HELLO packets\n" \ - "Seconds\n" \ - "Time between retransmitting lost link state advertisements\n" \ - "Seconds\n" \ - "Link state transmit delay\n" \ - "Seconds\n" \ - "Interval time after which a neighbor is declared down\n" \ - "Seconds\n" \ - -#define VLINK_HELPSTR_AUTH_SIMPLE \ - "Authentication password (key)\n" \ - "The OSPF password (key)" - -#define VLINK_HELPSTR_AUTH_MD5 \ - "Message digest authentication password (key)\n" \ - "dummy string \n" \ - "Key ID\n" \ - "Use MD5 algorithm\n" \ - "The OSPF password (key)" +#define VLINK_HELPSTR_IPADDR \ + "OSPF area parameters\n" \ + "OSPF area ID in IP address format\n" \ + "OSPF area ID as a decimal value\n" \ + "Configure a virtual link\n" \ + "Router ID of the remote ABR\n" + +#define VLINK_HELPSTR_AUTHTYPE_SIMPLE \ + "Enable authentication on this virtual link\n" \ + "dummy string \n" + +#define VLINK_HELPSTR_AUTHTYPE_ALL \ + VLINK_HELPSTR_AUTHTYPE_SIMPLE \ + "Use null authentication\n" \ + "Use message-digest authentication\n" + +#define VLINK_HELPSTR_TIME_PARAM \ + "Time between HELLO packets\n" \ + "Seconds\n" \ + "Time between retransmitting lost link state advertisements\n" \ + "Seconds\n" \ + "Link state transmit delay\n" \ + "Seconds\n" \ + "Interval time after which a neighbor is declared down\n" \ + "Seconds\n" + +#define VLINK_HELPSTR_AUTH_SIMPLE \ + "Authentication password (key)\n" \ + "The OSPF password (key)" + +#define VLINK_HELPSTR_AUTH_MD5 \ + "Message digest authentication password (key)\n" \ + "dummy string \n" \ + "Key ID\n" \ + "Use MD5 algorithm\n" \ + "The OSPF password (key)" DEFUN (ospf_area_vlink, ospf_area_vlink_cmd, @@ -1012,111 +981,115 @@ DEFUN (ospf_area_vlink, "Use MD5 algorithm\n" \ "The OSPF password (key)") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 1; - int idx_ipv4 = 3; - struct ospf_vl_config_data vl_config; - char auth_key[OSPF_AUTH_SIMPLE_SIZE+1]; - char md5_key[OSPF_AUTH_MD5_SIZE+1]; - int i; - int ret; - - ospf_vl_config_data_init(&vl_config, vty); - - /* Read off first 2 parameters and check them */ - ret = str2area_id (argv[idx_ipv4_number]->arg, &vl_config.area_id, - &vl_config.area_id_fmt); - if (ret < 0) - { - vty_out (vty, "OSPF area ID is invalid\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ret = inet_aton (argv[idx_ipv4]->arg, &vl_config.vl_peer); - if (! ret) - { - vty_out (vty, "Please specify valid Router ID as a.b.c.d\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (argc <=4) - { - /* Thats all folks! - BUGS B. strikes again!!!*/ - - return ospf_vl_set (ospf, &vl_config); - } - - /* Deal with other parameters */ - for (i=5; i < argc; i++) - { - - /* vty_out (vty, "argv[%d]->arg - %s\n", i, argv[i]->text); */ - - switch (argv[i]->arg[0]) - { + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + int idx_ipv4 = 3; + struct ospf_vl_config_data vl_config; + char auth_key[OSPF_AUTH_SIMPLE_SIZE + 1]; + char md5_key[OSPF_AUTH_MD5_SIZE + 1]; + int i; + int ret; + + ospf_vl_config_data_init(&vl_config, vty); + + /* Read off first 2 parameters and check them */ + ret = str2area_id(argv[idx_ipv4_number]->arg, &vl_config.area_id, + &vl_config.area_id_fmt); + if (ret < 0) { + vty_out(vty, "OSPF area ID is invalid\n"); + return CMD_WARNING_CONFIG_FAILED; + } - case 'a': - if (i >5 || strncmp (argv[i]->arg, "authentication-", 15) == 0) - { - /* authentication-key - this option can occur anywhere on - command line. At start of command line - must check for authentication option. */ - memset (auth_key, 0, OSPF_AUTH_SIMPLE_SIZE + 1); - strncpy (auth_key, argv[i+1]->text, OSPF_AUTH_SIMPLE_SIZE); - vl_config.auth_key = auth_key; - i++; - } - else if (strncmp (argv[i]->arg, "authentication", 14) == 0) - { - /* authentication - this option can only occur at start - of command line */ - vl_config.auth_type = OSPF_AUTH_SIMPLE; - if ((i+1) < argc) - { - if (strncmp (argv[i+1]->arg, "n", 1) == 0) - { - /* "authentication null" */ - vl_config.auth_type = OSPF_AUTH_NULL; - i++; - } - else if (strncmp (argv[i+1]->arg, "m", 1) == 0 - && !strmatch(argv[i + 1]->text, "message-digest-")) - { - /* "authentication message-digest" */ - vl_config.auth_type = OSPF_AUTH_CRYPTOGRAPHIC; - i++; - } - } - } - break; - - case 'm': - /* message-digest-key */ - i++; - if (i < argc) - { - vl_config.crypto_key_id = strtol (argv[i]->arg, NULL, 10); - if (vl_config.crypto_key_id < 0) - return CMD_WARNING_CONFIG_FAILED; - i++; - if (i < argc) - { - memset(md5_key, 0, OSPF_AUTH_MD5_SIZE+1); - strncpy (md5_key, argv[i]->arg, OSPF_AUTH_MD5_SIZE); - vl_config.md5_key = md5_key; - } - } - else - vl_config.md5_key = NULL; - break; + ret = inet_aton(argv[idx_ipv4]->arg, &vl_config.vl_peer); + if (!ret) { + vty_out(vty, "Please specify valid Router ID as a.b.c.d\n"); + return CMD_WARNING_CONFIG_FAILED; } - } + if (argc <= 4) { + /* Thats all folks! - BUGS B. strikes again!!!*/ - /* Action configuration */ + return ospf_vl_set(ospf, &vl_config); + } + + /* Deal with other parameters */ + for (i = 5; i < argc; i++) { + + /* vty_out (vty, "argv[%d]->arg - %s\n", i, argv[i]->text); */ + + switch (argv[i]->arg[0]) { + + case 'a': + if (i > 5 + || strncmp(argv[i]->arg, "authentication-", 15) + == 0) { + /* authentication-key - this option can occur + anywhere on + command line. At start + of command line + must check for + authentication option. */ + memset(auth_key, 0, OSPF_AUTH_SIMPLE_SIZE + 1); + strncpy(auth_key, argv[i + 1]->text, + OSPF_AUTH_SIMPLE_SIZE); + vl_config.auth_key = auth_key; + i++; + } else if (strncmp(argv[i]->arg, "authentication", 14) + == 0) { + /* authentication - this option can only occur + at start + of command line */ + vl_config.auth_type = OSPF_AUTH_SIMPLE; + if ((i + 1) < argc) { + if (strncmp(argv[i + 1]->arg, "n", 1) + == 0) { + /* "authentication null" */ + vl_config.auth_type = + OSPF_AUTH_NULL; + i++; + } else if ( + strncmp(argv[i + 1]->arg, "m", + 1) + == 0 + && !strmatch( + argv[i + 1]->text, + "message-digest-")) { + /* "authentication + * message-digest" */ + vl_config.auth_type = + OSPF_AUTH_CRYPTOGRAPHIC; + i++; + } + } + } + break; + + case 'm': + /* message-digest-key */ + i++; + if (i < argc) { + vl_config.crypto_key_id = + strtol(argv[i]->arg, NULL, 10); + if (vl_config.crypto_key_id < 0) + return CMD_WARNING_CONFIG_FAILED; + i++; + if (i < argc) { + memset(md5_key, 0, + OSPF_AUTH_MD5_SIZE + 1); + strncpy(md5_key, argv[i]->arg, + OSPF_AUTH_MD5_SIZE); + vl_config.md5_key = md5_key; + } + } else + vl_config.md5_key = NULL; + break; + } + } - return ospf_vl_set (ospf, &vl_config); + /* Action configuration */ + + return ospf_vl_set(ospf, &vl_config); } DEFUN (no_ospf_area_vlink, @@ -1132,100 +1105,97 @@ DEFUN (no_ospf_area_vlink, "Use MD5 algorithm\n" \ "The OSPF password (key)") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 2; - int idx_ipv4 = 4; - struct ospf_area *area; - struct ospf_vl_config_data vl_config; - struct ospf_vl_data *vl_data = NULL; - char auth_key[OSPF_AUTH_SIMPLE_SIZE+1]; - int i; - int ret, format; - - ospf_vl_config_data_init(&vl_config, vty); - - ret = str2area_id (argv[idx_ipv4_number]->arg, &vl_config.area_id, &format); - if (ret < 0) - { - vty_out (vty, "OSPF area ID is invalid\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - area = ospf_area_lookup_by_area_id (ospf, vl_config.area_id); - if (!area) - { - vty_out (vty, "Area does not exist\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ret = inet_aton (argv[idx_ipv4]->arg, &vl_config.vl_peer); - if (! ret) - { - vty_out (vty, "Please specify valid Router ID as a.b.c.d\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (argc <=5) - { - /* Basic VLink no command */ - /* Thats all folks! - BUGS B. strikes again!!!*/ - if ((vl_data = ospf_vl_lookup (ospf, area, vl_config.vl_peer))) - ospf_vl_delete (ospf, vl_data); - - ospf_area_check_free (ospf, vl_config.area_id); - - return CMD_SUCCESS; - } - - /* If we are down here, we are reseting parameters */ - - /* Deal with other parameters */ - for (i=6; i < argc; i++) - { - /* vty_out (vty, "argv[%d] - %s\n", i, argv[i]); */ - - switch (argv[i]->arg[0]) - { + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + int idx_ipv4 = 4; + struct ospf_area *area; + struct ospf_vl_config_data vl_config; + struct ospf_vl_data *vl_data = NULL; + char auth_key[OSPF_AUTH_SIMPLE_SIZE + 1]; + int i; + int ret, format; + + ospf_vl_config_data_init(&vl_config, vty); + + ret = str2area_id(argv[idx_ipv4_number]->arg, &vl_config.area_id, + &format); + if (ret < 0) { + vty_out(vty, "OSPF area ID is invalid\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + area = ospf_area_lookup_by_area_id(ospf, vl_config.area_id); + if (!area) { + vty_out(vty, "Area does not exist\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = inet_aton(argv[idx_ipv4]->arg, &vl_config.vl_peer); + if (!ret) { + vty_out(vty, "Please specify valid Router ID as a.b.c.d\n"); + return CMD_WARNING_CONFIG_FAILED; + } - case 'a': - if (i > 2 || strncmp (argv[i]->text, "authentication-", 15) == 0) - { - /* authentication-key - this option can occur anywhere on - command line. At start of command line - must check for authentication option. */ - memset (auth_key, 0, OSPF_AUTH_SIMPLE_SIZE + 1); - vl_config.auth_key = auth_key; - } - else if (strncmp (argv[i]->text, "authentication", 14) == 0) - { - /* authentication - this option can only occur at start - of command line */ - vl_config.auth_type = OSPF_AUTH_NOTSET; - } - break; - - case 'm': - /* message-digest-key */ - /* Delete one key */ - i++; - if (i < argc) - { - vl_config.crypto_key_id = strtol (argv[i]->arg, NULL, 10); - if (vl_config.crypto_key_id < 0) - return CMD_WARNING_CONFIG_FAILED; - vl_config.md5_key = NULL; - } - else - return CMD_WARNING_CONFIG_FAILED; - break; - - } - } - - - /* Action configuration */ - - return ospf_vl_set (ospf, &vl_config); + if (argc <= 5) { + /* Basic VLink no command */ + /* Thats all folks! - BUGS B. strikes again!!!*/ + if ((vl_data = ospf_vl_lookup(ospf, area, vl_config.vl_peer))) + ospf_vl_delete(ospf, vl_data); + + ospf_area_check_free(ospf, vl_config.area_id); + + return CMD_SUCCESS; + } + + /* If we are down here, we are reseting parameters */ + + /* Deal with other parameters */ + for (i = 6; i < argc; i++) { + /* vty_out (vty, "argv[%d] - %s\n", i, argv[i]); */ + + switch (argv[i]->arg[0]) { + + case 'a': + if (i > 2 + || strncmp(argv[i]->text, "authentication-", 15) + == 0) { + /* authentication-key - this option can occur + anywhere on + command line. At start + of command line + must check for + authentication option. */ + memset(auth_key, 0, OSPF_AUTH_SIMPLE_SIZE + 1); + vl_config.auth_key = auth_key; + } else if (strncmp(argv[i]->text, "authentication", 14) + == 0) { + /* authentication - this option can only occur + at start + of command line */ + vl_config.auth_type = OSPF_AUTH_NOTSET; + } + break; + + case 'm': + /* message-digest-key */ + /* Delete one key */ + i++; + if (i < argc) { + vl_config.crypto_key_id = + strtol(argv[i]->arg, NULL, 10); + if (vl_config.crypto_key_id < 0) + return CMD_WARNING_CONFIG_FAILED; + vl_config.md5_key = NULL; + } else + return CMD_WARNING_CONFIG_FAILED; + break; + } + } + + + /* Action configuration */ + + return ospf_vl_set(ospf, &vl_config); } DEFUN (ospf_area_vlink_intervals, @@ -1234,43 +1204,44 @@ DEFUN (ospf_area_vlink_intervals, VLINK_HELPSTR_IPADDR VLINK_HELPSTR_TIME_PARAM) { - VTY_DECLVAR_CONTEXT(ospf, ospf); - struct ospf_vl_config_data vl_config; - int ret = 0; - - ospf_vl_config_data_init(&vl_config, vty); - - char *area_id = argv[1]->arg; - char *router_id = argv[3]->arg; - - ret = str2area_id (area_id, &vl_config.area_id, &vl_config.area_id_fmt); - if (ret < 0) - { - vty_out (vty, "OSPF area ID is invalid\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ret = inet_aton (router_id, &vl_config.vl_peer); - if (! ret) - { - vty_out (vty, "Please specify valid Router ID as a.b.c.d\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - for (int idx = 4; idx < argc; idx++) - { - if (strmatch (argv[idx]->text, "hello-interval")) - vl_config.hello_interval = strtol(argv[++idx]->arg, NULL, 10); - else if (strmatch (argv[idx]->text, "retransmit-interval")) - vl_config.retransmit_interval = strtol(argv[++idx]->arg, NULL, 10); - else if (strmatch (argv[idx]->text, "transmit-delay")) - vl_config.transmit_delay = strtol(argv[++idx]->arg, NULL, 10); - else if (strmatch (argv[idx]->text, "dead-interval")) - vl_config.dead_interval = strtol(argv[++idx]->arg, NULL, 10); - } - - /* Action configuration */ - return ospf_vl_set (ospf, &vl_config); + VTY_DECLVAR_CONTEXT(ospf, ospf); + struct ospf_vl_config_data vl_config; + int ret = 0; + + ospf_vl_config_data_init(&vl_config, vty); + + char *area_id = argv[1]->arg; + char *router_id = argv[3]->arg; + + ret = str2area_id(area_id, &vl_config.area_id, &vl_config.area_id_fmt); + if (ret < 0) { + vty_out(vty, "OSPF area ID is invalid\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = inet_aton(router_id, &vl_config.vl_peer); + if (!ret) { + vty_out(vty, "Please specify valid Router ID as a.b.c.d\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + for (int idx = 4; idx < argc; idx++) { + if (strmatch(argv[idx]->text, "hello-interval")) + vl_config.hello_interval = + strtol(argv[++idx]->arg, NULL, 10); + else if (strmatch(argv[idx]->text, "retransmit-interval")) + vl_config.retransmit_interval = + strtol(argv[++idx]->arg, NULL, 10); + else if (strmatch(argv[idx]->text, "transmit-delay")) + vl_config.transmit_delay = + strtol(argv[++idx]->arg, NULL, 10); + else if (strmatch(argv[idx]->text, "dead-interval")) + vl_config.dead_interval = + strtol(argv[++idx]->arg, NULL, 10); + } + + /* Action configuration */ + return ospf_vl_set(ospf, &vl_config); } DEFUN (no_ospf_area_vlink_intervals, @@ -1280,43 +1251,42 @@ DEFUN (no_ospf_area_vlink_intervals, VLINK_HELPSTR_IPADDR VLINK_HELPSTR_TIME_PARAM) { - VTY_DECLVAR_CONTEXT(ospf, ospf); - struct ospf_vl_config_data vl_config; - int ret = 0; - - ospf_vl_config_data_init(&vl_config, vty); - - char *area_id = argv[2]->arg; - char *router_id = argv[4]->arg; - - ret = str2area_id (area_id, &vl_config.area_id, &vl_config.area_id_fmt); - if (ret < 0) - { - vty_out (vty, "OSPF area ID is invalid\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ret = inet_aton (router_id, &vl_config.vl_peer); - if (! ret) - { - vty_out (vty, "Please specify valid Router ID as a.b.c.d\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - for (int idx = 5; idx < argc; idx++) - { - if (strmatch (argv[idx]->text, "hello-interval")) - vl_config.hello_interval = OSPF_HELLO_INTERVAL_DEFAULT; - else if (strmatch (argv[idx]->text, "retransmit-interval")) - vl_config.retransmit_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT; - else if (strmatch (argv[idx]->text, "transmit-delay")) - vl_config.transmit_delay = OSPF_TRANSMIT_DELAY_DEFAULT; - else if (strmatch (argv[idx]->text, "dead-interval")) - vl_config.dead_interval = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT; - } - - /* Action configuration */ - return ospf_vl_set (ospf, &vl_config); + VTY_DECLVAR_CONTEXT(ospf, ospf); + struct ospf_vl_config_data vl_config; + int ret = 0; + + ospf_vl_config_data_init(&vl_config, vty); + + char *area_id = argv[2]->arg; + char *router_id = argv[4]->arg; + + ret = str2area_id(area_id, &vl_config.area_id, &vl_config.area_id_fmt); + if (ret < 0) { + vty_out(vty, "OSPF area ID is invalid\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = inet_aton(router_id, &vl_config.vl_peer); + if (!ret) { + vty_out(vty, "Please specify valid Router ID as a.b.c.d\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + for (int idx = 5; idx < argc; idx++) { + if (strmatch(argv[idx]->text, "hello-interval")) + vl_config.hello_interval = OSPF_HELLO_INTERVAL_DEFAULT; + else if (strmatch(argv[idx]->text, "retransmit-interval")) + vl_config.retransmit_interval = + OSPF_RETRANSMIT_INTERVAL_DEFAULT; + else if (strmatch(argv[idx]->text, "transmit-delay")) + vl_config.transmit_delay = OSPF_TRANSMIT_DELAY_DEFAULT; + else if (strmatch(argv[idx]->text, "dead-interval")) + vl_config.dead_interval = + OSPF_ROUTER_DEAD_INTERVAL_DEFAULT; + } + + /* Action configuration */ + return ospf_vl_set(ospf, &vl_config); } DEFUN (ospf_area_shortcut, @@ -1330,35 +1300,37 @@ DEFUN (ospf_area_shortcut, "Enable shortcutting through the area\n" "Disable shortcutting through the area\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 1; - int idx_enable_disable = 3; - struct ospf_area *area; - struct in_addr area_id; - int mode; - int format; - - VTY_GET_OSPF_AREA_ID_NO_BB ("shortcut", area_id, format, argv[idx_ipv4_number]->arg); - - area = ospf_area_get (ospf, area_id); - ospf_area_display_format_set (ospf, area, format); - - if (strncmp (argv[idx_enable_disable]->arg, "de", 2) == 0) - mode = OSPF_SHORTCUT_DEFAULT; - else if (strncmp (argv[idx_enable_disable]->arg, "di", 2) == 0) - mode = OSPF_SHORTCUT_DISABLE; - else if (strncmp (argv[idx_enable_disable]->arg, "e", 1) == 0) - mode = OSPF_SHORTCUT_ENABLE; - else - return CMD_WARNING_CONFIG_FAILED; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + int idx_enable_disable = 3; + struct ospf_area *area; + struct in_addr area_id; + int mode; + int format; + + VTY_GET_OSPF_AREA_ID_NO_BB("shortcut", area_id, format, + argv[idx_ipv4_number]->arg); + + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + + if (strncmp(argv[idx_enable_disable]->arg, "de", 2) == 0) + mode = OSPF_SHORTCUT_DEFAULT; + else if (strncmp(argv[idx_enable_disable]->arg, "di", 2) == 0) + mode = OSPF_SHORTCUT_DISABLE; + else if (strncmp(argv[idx_enable_disable]->arg, "e", 1) == 0) + mode = OSPF_SHORTCUT_ENABLE; + else + return CMD_WARNING_CONFIG_FAILED; - ospf_area_shortcut_set (ospf, area, mode); + ospf_area_shortcut_set(ospf, area, mode); - if (ospf->abr_type != OSPF_ABR_SHORTCUT) - vty_out (vty, "Shortcut area setting will take effect " - "only when the router is configured as Shortcut ABR\n"); + if (ospf->abr_type != OSPF_ABR_SHORTCUT) + vty_out(vty, + "Shortcut area setting will take effect " + "only when the router is configured as Shortcut ABR\n"); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf_area_shortcut, @@ -1372,21 +1344,22 @@ DEFUN (no_ospf_area_shortcut, "Deconfigure enabled shortcutting through the area\n" "Deconfigure disabled shortcutting through the area\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 2; - struct ospf_area *area; - struct in_addr area_id; - int format; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + struct ospf_area *area; + struct in_addr area_id; + int format; - VTY_GET_OSPF_AREA_ID_NO_BB ("shortcut", area_id, format, argv[idx_ipv4_number]->arg); + VTY_GET_OSPF_AREA_ID_NO_BB("shortcut", area_id, format, + argv[idx_ipv4_number]->arg); - area = ospf_area_lookup_by_area_id (ospf, area_id); - if (!area) - return CMD_SUCCESS; + area = ospf_area_lookup_by_area_id(ospf, area_id); + if (!area) + return CMD_SUCCESS; - ospf_area_shortcut_unset (ospf, area); + ospf_area_shortcut_unset(ospf, area); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1398,24 +1371,26 @@ DEFUN (ospf_area_stub, "OSPF area ID as a decimal value\n" "Configure OSPF area as stub\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 1; - struct in_addr area_id; - int ret, format; - - VTY_GET_OSPF_AREA_ID_NO_BB ("stub", area_id, format, argv[idx_ipv4_number]->arg); - - ret = ospf_area_stub_set (ospf, area_id); - ospf_area_display_format_set (ospf, ospf_area_get (ospf, area_id), format); - if (ret == 0) - { - vty_out (vty, "First deconfigure all virtual link through this area\n"); - return CMD_WARNING_CONFIG_FAILED; - } + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + struct in_addr area_id; + int ret, format; + + VTY_GET_OSPF_AREA_ID_NO_BB("stub", area_id, format, + argv[idx_ipv4_number]->arg); + + ret = ospf_area_stub_set(ospf, area_id); + ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id), + format); + if (ret == 0) { + vty_out(vty, + "First deconfigure all virtual link through this area\n"); + return CMD_WARNING_CONFIG_FAILED; + } - ospf_area_no_summary_unset (ospf, area_id); + ospf_area_no_summary_unset(ospf, area_id); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ospf_area_stub_no_summary, @@ -1427,24 +1402,26 @@ DEFUN (ospf_area_stub_no_summary, "Configure OSPF area as stub\n" "Do not inject inter-area routes into stub\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 1; - struct in_addr area_id; - int ret, format; - - VTY_GET_OSPF_AREA_ID_NO_BB ("stub", area_id, format, argv[idx_ipv4_number]->arg); - - ret = ospf_area_stub_set (ospf, area_id); - ospf_area_display_format_set (ospf, ospf_area_get (ospf, area_id), format); - if (ret == 0) - { - vty_out (vty, "%% Area cannot be stub as it contains a virtual link\n"); - return CMD_WARNING_CONFIG_FAILED; - } + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + struct in_addr area_id; + int ret, format; + + VTY_GET_OSPF_AREA_ID_NO_BB("stub", area_id, format, + argv[idx_ipv4_number]->arg); + + ret = ospf_area_stub_set(ospf, area_id); + ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id), + format); + if (ret == 0) { + vty_out(vty, + "%% Area cannot be stub as it contains a virtual link\n"); + return CMD_WARNING_CONFIG_FAILED; + } - ospf_area_no_summary_set (ospf, area_id); + ospf_area_no_summary_set(ospf, area_id); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf_area_stub, @@ -1456,17 +1433,18 @@ DEFUN (no_ospf_area_stub, "OSPF area ID as a decimal value\n" "Configure OSPF area as stub\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 2; - struct in_addr area_id; - int format; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + struct in_addr area_id; + int format; - VTY_GET_OSPF_AREA_ID_NO_BB ("stub", area_id, format, argv[idx_ipv4_number]->arg); + VTY_GET_OSPF_AREA_ID_NO_BB("stub", area_id, format, + argv[idx_ipv4_number]->arg); - ospf_area_stub_unset (ospf, area_id); - ospf_area_no_summary_unset (ospf, area_id); + ospf_area_stub_unset(ospf, area_id); + ospf_area_no_summary_unset(ospf, area_id); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf_area_stub_no_summary, @@ -1479,61 +1457,59 @@ DEFUN (no_ospf_area_stub_no_summary, "Configure OSPF area as stub\n" "Do not inject inter-area routes into area\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 2; - struct in_addr area_id; - int format; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + struct in_addr area_id; + int format; - VTY_GET_OSPF_AREA_ID_NO_BB ("stub", area_id, format, argv[idx_ipv4_number]->arg); - ospf_area_no_summary_unset (ospf, area_id); + VTY_GET_OSPF_AREA_ID_NO_BB("stub", area_id, format, + argv[idx_ipv4_number]->arg); + ospf_area_no_summary_unset(ospf, area_id); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -ospf_area_nssa_cmd_handler (struct vty *vty, int argc, struct cmd_token **argv, - int nosum) +static int ospf_area_nssa_cmd_handler(struct vty *vty, int argc, + struct cmd_token **argv, int nosum) { - VTY_DECLVAR_CONTEXT(ospf, ospf); - struct in_addr area_id; - int ret, format; - - VTY_GET_OSPF_AREA_ID_NO_BB ("NSSA", area_id, format, argv[1]->arg); - - ret = ospf_area_nssa_set (ospf, area_id); - ospf_area_display_format_set (ospf, ospf_area_get (ospf, area_id), format); - if (ret == 0) - { - vty_out (vty, "%% Area cannot be nssa as it contains a virtual link\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (argc > 3) - { - if (strncmp (argv[3]->text, "translate-c", 11) == 0) - ospf_area_nssa_translator_role_set (ospf, area_id, - OSPF_NSSA_ROLE_CANDIDATE); - else if (strncmp (argv[3]->text, "translate-n", 11) == 0) - ospf_area_nssa_translator_role_set (ospf, area_id, - OSPF_NSSA_ROLE_NEVER); - else if (strncmp (argv[3]->text, "translate-a", 11) == 0) - ospf_area_nssa_translator_role_set (ospf, area_id, - OSPF_NSSA_ROLE_ALWAYS); - } - else - { - ospf_area_nssa_translator_role_set (ospf, area_id, - OSPF_NSSA_ROLE_CANDIDATE); - } - - if (nosum) - ospf_area_no_summary_set (ospf, area_id); - else - ospf_area_no_summary_unset (ospf, area_id); - - ospf_schedule_abr_task (ospf); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(ospf, ospf); + struct in_addr area_id; + int ret, format; + + VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format, argv[1]->arg); + + ret = ospf_area_nssa_set(ospf, area_id); + ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id), + format); + if (ret == 0) { + vty_out(vty, + "%% Area cannot be nssa as it contains a virtual link\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (argc > 3) { + if (strncmp(argv[3]->text, "translate-c", 11) == 0) + ospf_area_nssa_translator_role_set( + ospf, area_id, OSPF_NSSA_ROLE_CANDIDATE); + else if (strncmp(argv[3]->text, "translate-n", 11) == 0) + ospf_area_nssa_translator_role_set( + ospf, area_id, OSPF_NSSA_ROLE_NEVER); + else if (strncmp(argv[3]->text, "translate-a", 11) == 0) + ospf_area_nssa_translator_role_set( + ospf, area_id, OSPF_NSSA_ROLE_ALWAYS); + } else { + ospf_area_nssa_translator_role_set(ospf, area_id, + OSPF_NSSA_ROLE_CANDIDATE); + } + + if (nosum) + ospf_area_no_summary_set(ospf, area_id); + else + ospf_area_no_summary_unset(ospf, area_id); + + ospf_schedule_abr_task(ospf); + + return CMD_SUCCESS; } DEFUN (ospf_area_nssa_translate_no_summary, @@ -1548,7 +1524,7 @@ DEFUN (ospf_area_nssa_translate_no_summary, "Configure NSSA-ABR to always translate\n" "Do not inject inter-area routes into nssa\n") { - return ospf_area_nssa_cmd_handler (vty, argc, argv, 1); + return ospf_area_nssa_cmd_handler(vty, argc, argv, 1); } DEFUN (ospf_area_nssa_translate, @@ -1562,7 +1538,7 @@ DEFUN (ospf_area_nssa_translate, "Configure NSSA-ABR to never translate\n" "Configure NSSA-ABR to always translate\n") { - return ospf_area_nssa_cmd_handler (vty, argc, argv, 0); + return ospf_area_nssa_cmd_handler(vty, argc, argv, 0); } DEFUN (ospf_area_nssa, @@ -1573,7 +1549,7 @@ DEFUN (ospf_area_nssa, "OSPF area ID as a decimal value\n" "Configure OSPF area as nssa\n") { - return ospf_area_nssa_cmd_handler (vty, argc, argv, 0); + return ospf_area_nssa_cmd_handler(vty, argc, argv, 0); } DEFUN (ospf_area_nssa_no_summary, @@ -1585,7 +1561,7 @@ DEFUN (ospf_area_nssa_no_summary, "Configure OSPF area as nssa\n" "Do not inject inter-area routes into nssa\n") { - return ospf_area_nssa_cmd_handler (vty, argc, argv, 1); + return ospf_area_nssa_cmd_handler(vty, argc, argv, 1); } DEFUN (no_ospf_area_nssa, @@ -1601,19 +1577,20 @@ DEFUN (no_ospf_area_nssa, "Configure NSSA-ABR to always translate\n" "Do not inject inter-area routes into nssa\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 2; - struct in_addr area_id; - int format; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + struct in_addr area_id; + int format; - VTY_GET_OSPF_AREA_ID_NO_BB ("NSSA", area_id, format, argv[idx_ipv4_number]->arg); + VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format, + argv[idx_ipv4_number]->arg); - ospf_area_nssa_unset (ospf, area_id); - ospf_area_no_summary_unset (ospf, area_id); + ospf_area_nssa_unset(ospf, area_id); + ospf_area_no_summary_unset(ospf, area_id); - ospf_schedule_abr_task (ospf); + ospf_schedule_abr_task(ospf); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1626,39 +1603,40 @@ DEFUN (ospf_area_default_cost, "Set the summary-default cost of a NSSA or stub area\n" "Stub's advertised default summary cost\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 1; - int idx_number = 3; - struct ospf_area *area; - struct in_addr area_id; - u_int32_t cost; - int format; - struct prefix_ipv4 p; - - VTY_GET_OSPF_AREA_ID_NO_BB ("default-cost", area_id, format, argv[idx_ipv4_number]->arg); - cost = strtoul(argv[idx_number]->arg, NULL, 10); - - area = ospf_area_get (ospf, area_id); - ospf_area_display_format_set (ospf, area, format); - - if (area->external_routing == OSPF_AREA_DEFAULT) - { - vty_out (vty, "The area is neither stub, nor NSSA\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - area->default_cost = cost; - - p.family = AF_INET; - p.prefix.s_addr = OSPF_DEFAULT_DESTINATION; - p.prefixlen = 0; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_stub_defaults(): " - "announcing 0.0.0.0/0 to area %s", - inet_ntoa (area->area_id)); - ospf_abr_announce_network_to_area (&p, area->default_cost, area); + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + int idx_number = 3; + struct ospf_area *area; + struct in_addr area_id; + u_int32_t cost; + int format; + struct prefix_ipv4 p; + + VTY_GET_OSPF_AREA_ID_NO_BB("default-cost", area_id, format, + argv[idx_ipv4_number]->arg); + cost = strtoul(argv[idx_number]->arg, NULL, 10); + + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + + if (area->external_routing == OSPF_AREA_DEFAULT) { + vty_out(vty, "The area is neither stub, nor NSSA\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + area->default_cost = cost; + + p.family = AF_INET; + p.prefix.s_addr = OSPF_DEFAULT_DESTINATION; + p.prefixlen = 0; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_stub_defaults(): " + "announcing 0.0.0.0/0 to area %s", + inet_ntoa(area->area_id)); + ospf_abr_announce_network_to_area(&p, area->default_cost, area); + + return CMD_SUCCESS; } DEFUN (no_ospf_area_default_cost, @@ -1671,40 +1649,41 @@ DEFUN (no_ospf_area_default_cost, "Set the summary-default cost of a NSSA or stub area\n" "Stub's advertised default summary cost\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 2; - struct ospf_area *area; - struct in_addr area_id; - int format; - struct prefix_ipv4 p; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + struct ospf_area *area; + struct in_addr area_id; + int format; + struct prefix_ipv4 p; - VTY_GET_OSPF_AREA_ID_NO_BB ("default-cost", area_id, format, argv[idx_ipv4_number]->arg); + VTY_GET_OSPF_AREA_ID_NO_BB("default-cost", area_id, format, + argv[idx_ipv4_number]->arg); - area = ospf_area_lookup_by_area_id (ospf, area_id); - if (area == NULL) - return CMD_SUCCESS; + area = ospf_area_lookup_by_area_id(ospf, area_id); + if (area == NULL) + return CMD_SUCCESS; - if (area->external_routing == OSPF_AREA_DEFAULT) - { - vty_out (vty, "The area is neither stub, nor NSSA\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (area->external_routing == OSPF_AREA_DEFAULT) { + vty_out(vty, "The area is neither stub, nor NSSA\n"); + return CMD_WARNING_CONFIG_FAILED; + } - area->default_cost = 1; + area->default_cost = 1; - p.family = AF_INET; - p.prefix.s_addr = OSPF_DEFAULT_DESTINATION; - p.prefixlen = 0; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_abr_announce_stub_defaults(): " - "announcing 0.0.0.0/0 to area %s", - inet_ntoa (area->area_id)); - ospf_abr_announce_network_to_area (&p, area->default_cost, area); + p.family = AF_INET; + p.prefix.s_addr = OSPF_DEFAULT_DESTINATION; + p.prefixlen = 0; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_stub_defaults(): " + "announcing 0.0.0.0/0 to area %s", + inet_ntoa(area->area_id)); + ospf_abr_announce_network_to_area(&p, area->default_cost, area); - ospf_area_check_free (ospf, area_id); + ospf_area_check_free(ospf, area_id); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ospf_area_export_list, @@ -1716,19 +1695,19 @@ DEFUN (ospf_area_export_list, "Set the filter for networks announced to other areas\n" "Name of the access-list\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 1; - struct ospf_area *area; - struct in_addr area_id; - int format; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + struct ospf_area *area; + struct in_addr area_id; + int format; - VTY_GET_OSPF_AREA_ID (area_id, format, argv[idx_ipv4_number]->arg); + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); - area = ospf_area_get (ospf, area_id); - ospf_area_display_format_set (ospf, area, format); - ospf_area_export_list_set (ospf, area, argv[3]->arg); + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + ospf_area_export_list_set(ospf, area, argv[3]->arg); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf_area_export_list, @@ -1741,21 +1720,21 @@ DEFUN (no_ospf_area_export_list, "Unset the filter for networks announced to other areas\n" "Name of the access-list\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 2; - struct ospf_area *area; - struct in_addr area_id; - int format; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + struct ospf_area *area; + struct in_addr area_id; + int format; - VTY_GET_OSPF_AREA_ID (area_id, format, argv[idx_ipv4_number]->arg); + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); - area = ospf_area_lookup_by_area_id (ospf, area_id); - if (area == NULL) - return CMD_SUCCESS; + area = ospf_area_lookup_by_area_id(ospf, area_id); + if (area == NULL) + return CMD_SUCCESS; - ospf_area_export_list_unset (ospf, area); + ospf_area_export_list_unset(ospf, area); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1768,19 +1747,19 @@ DEFUN (ospf_area_import_list, "Set the filter for networks from other areas announced to the specified one\n" "Name of the access-list\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 1; - struct ospf_area *area; - struct in_addr area_id; - int format; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + struct ospf_area *area; + struct in_addr area_id; + int format; - VTY_GET_OSPF_AREA_ID (area_id, format, argv[idx_ipv4_number]->arg); + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); - area = ospf_area_get (ospf, area_id); - ospf_area_display_format_set (ospf, area, format); - ospf_area_import_list_set (ospf, area, argv[3]->arg); + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + ospf_area_import_list_set(ospf, area, argv[3]->arg); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf_area_import_list, @@ -1793,21 +1772,21 @@ DEFUN (no_ospf_area_import_list, "Unset the filter for networks announced to other areas\n" "Name of the access-list\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 2; - struct ospf_area *area; - struct in_addr area_id; - int format; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + struct ospf_area *area; + struct in_addr area_id; + int format; - VTY_GET_OSPF_AREA_ID (area_id, format, argv[idx_ipv4_number]->arg); + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); - area = ospf_area_lookup_by_area_id (ospf, area_id); - if (area == NULL) - return CMD_SUCCESS; + area = ospf_area_lookup_by_area_id(ospf, area_id); + if (area == NULL) + return CMD_SUCCESS; - ospf_area_import_list_unset (ospf, area); + ospf_area_import_list_unset(ospf, area); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ospf_area_filter_list, @@ -1822,40 +1801,37 @@ DEFUN (ospf_area_filter_list, "Filter networks sent to this area\n" "Filter networks sent from this area\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 1; - int idx_word = 4; - int idx_in_out = 5; - struct ospf_area *area; - struct in_addr area_id; - struct prefix_list *plist; - int format; - - VTY_GET_OSPF_AREA_ID (area_id, format, argv[idx_ipv4_number]->arg); - - area = ospf_area_get (ospf, area_id); - ospf_area_display_format_set (ospf, area, format); - plist = prefix_list_lookup (AFI_IP, argv[idx_word]->arg); - if (strncmp (argv[idx_in_out]->arg, "in", 2) == 0) - { - PREFIX_LIST_IN (area) = plist; - if (PREFIX_NAME_IN (area)) - free (PREFIX_NAME_IN (area)); - - PREFIX_NAME_IN (area) = strdup (argv[idx_word]->arg); - ospf_schedule_abr_task (ospf); - } - else - { - PREFIX_LIST_OUT (area) = plist; - if (PREFIX_NAME_OUT (area)) - free (PREFIX_NAME_OUT (area)); - - PREFIX_NAME_OUT (area) = strdup (argv[idx_word]->arg); - ospf_schedule_abr_task (ospf); - } + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + int idx_word = 4; + int idx_in_out = 5; + struct ospf_area *area; + struct in_addr area_id; + struct prefix_list *plist; + int format; + + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + plist = prefix_list_lookup(AFI_IP, argv[idx_word]->arg); + if (strncmp(argv[idx_in_out]->arg, "in", 2) == 0) { + PREFIX_LIST_IN(area) = plist; + if (PREFIX_NAME_IN(area)) + free(PREFIX_NAME_IN(area)); + + PREFIX_NAME_IN(area) = strdup(argv[idx_word]->arg); + ospf_schedule_abr_task(ospf); + } else { + PREFIX_LIST_OUT(area) = plist; + if (PREFIX_NAME_OUT(area)) + free(PREFIX_NAME_OUT(area)); + + PREFIX_NAME_OUT(area) = strdup(argv[idx_word]->arg); + ospf_schedule_abr_task(ospf); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf_area_filter_list, @@ -1871,49 +1847,48 @@ DEFUN (no_ospf_area_filter_list, "Filter networks sent to this area\n" "Filter networks sent from this area\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 2; - int idx_word = 5; - int idx_in_out = 6; - struct ospf_area *area; - struct in_addr area_id; - int format; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + int idx_word = 5; + int idx_in_out = 6; + struct ospf_area *area; + struct in_addr area_id; + int format; - VTY_GET_OSPF_AREA_ID (area_id, format, argv[idx_ipv4_number]->arg); + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); - if ((area = ospf_area_lookup_by_area_id (ospf, area_id)) == NULL) - return CMD_SUCCESS; - - if (strncmp (argv[idx_in_out]->arg, "in", 2) == 0) - { - if (PREFIX_NAME_IN (area)) - if (strcmp (PREFIX_NAME_IN (area), argv[idx_word]->arg) != 0) - return CMD_SUCCESS; + if ((area = ospf_area_lookup_by_area_id(ospf, area_id)) == NULL) + return CMD_SUCCESS; - PREFIX_LIST_IN (area) = NULL; - if (PREFIX_NAME_IN (area)) - free (PREFIX_NAME_IN (area)); + if (strncmp(argv[idx_in_out]->arg, "in", 2) == 0) { + if (PREFIX_NAME_IN(area)) + if (strcmp(PREFIX_NAME_IN(area), argv[idx_word]->arg) + != 0) + return CMD_SUCCESS; - PREFIX_NAME_IN (area) = NULL; + PREFIX_LIST_IN(area) = NULL; + if (PREFIX_NAME_IN(area)) + free(PREFIX_NAME_IN(area)); - ospf_schedule_abr_task (ospf); - } - else - { - if (PREFIX_NAME_OUT (area)) - if (strcmp (PREFIX_NAME_OUT (area), argv[idx_word]->arg) != 0) - return CMD_SUCCESS; + PREFIX_NAME_IN(area) = NULL; - PREFIX_LIST_OUT (area) = NULL; - if (PREFIX_NAME_OUT (area)) - free (PREFIX_NAME_OUT (area)); + ospf_schedule_abr_task(ospf); + } else { + if (PREFIX_NAME_OUT(area)) + if (strcmp(PREFIX_NAME_OUT(area), argv[idx_word]->arg) + != 0) + return CMD_SUCCESS; - PREFIX_NAME_OUT (area) = NULL; + PREFIX_LIST_OUT(area) = NULL; + if (PREFIX_NAME_OUT(area)) + free(PREFIX_NAME_OUT(area)); - ospf_schedule_abr_task (ospf); - } + PREFIX_NAME_OUT(area) = NULL; - return CMD_SUCCESS; + ospf_schedule_abr_task(ospf); + } + + return CMD_SUCCESS; } @@ -1926,19 +1901,19 @@ DEFUN (ospf_area_authentication_message_digest, "Enable authentication\n" "Use message-digest authentication\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 1; - struct ospf_area *area; - struct in_addr area_id; - int format; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + struct ospf_area *area; + struct in_addr area_id; + int format; - VTY_GET_OSPF_AREA_ID (area_id, format, argv[idx_ipv4_number]->arg); + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); - area = ospf_area_get (ospf, area_id); - ospf_area_display_format_set (ospf, area, format); - area->auth_type = OSPF_AUTH_CRYPTOGRAPHIC; + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + area->auth_type = OSPF_AUTH_CRYPTOGRAPHIC; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ospf_area_authentication, @@ -1949,19 +1924,19 @@ DEFUN (ospf_area_authentication, "OSPF area ID as a decimal value\n" "Enable authentication\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 1; - struct ospf_area *area; - struct in_addr area_id; - int format; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + struct ospf_area *area; + struct in_addr area_id; + int format; - VTY_GET_OSPF_AREA_ID (area_id, format, argv[idx_ipv4_number]->arg); + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); - area = ospf_area_get (ospf, area_id); - ospf_area_display_format_set (ospf, area, format); - area->auth_type = OSPF_AUTH_SIMPLE; + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + area->auth_type = OSPF_AUTH_SIMPLE; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf_area_authentication, @@ -1973,23 +1948,23 @@ DEFUN (no_ospf_area_authentication, "OSPF area ID as a decimal value\n" "Enable authentication\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4_number = 2; - struct ospf_area *area; - struct in_addr area_id; - int format; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + struct ospf_area *area; + struct in_addr area_id; + int format; - VTY_GET_OSPF_AREA_ID (area_id, format, argv[idx_ipv4_number]->arg); + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); - area = ospf_area_lookup_by_area_id (ospf, area_id); - if (area == NULL) - return CMD_SUCCESS; + area = ospf_area_lookup_by_area_id(ospf, area_id); + if (area == NULL) + return CMD_SUCCESS; - area->auth_type = OSPF_AUTH_NULL; + area->auth_type = OSPF_AUTH_NULL; - ospf_area_check_free (ospf, area_id); - - return CMD_SUCCESS; + ospf_area_check_free(ospf, area_id); + + return CMD_SUCCESS; } @@ -2003,29 +1978,28 @@ DEFUN (ospf_abr_type, "Shortcut ABR\n" "Standard behavior (RFC2328)\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_vendor = 2; - u_char abr_type = OSPF_ABR_UNKNOWN; - - if (strncmp (argv[idx_vendor]->arg, "c", 1) == 0) - abr_type = OSPF_ABR_CISCO; - else if (strncmp (argv[idx_vendor]->arg, "i", 1) == 0) - abr_type = OSPF_ABR_IBM; - else if (strncmp (argv[idx_vendor]->arg, "sh", 2) == 0) - abr_type = OSPF_ABR_SHORTCUT; - else if (strncmp (argv[idx_vendor]->arg, "st", 2) == 0) - abr_type = OSPF_ABR_STAND; - else - return CMD_WARNING_CONFIG_FAILED; - - /* If ABR type value is changed, schedule ABR task. */ - if (ospf->abr_type != abr_type) - { - ospf->abr_type = abr_type; - ospf_schedule_abr_task (ospf); - } + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_vendor = 2; + u_char abr_type = OSPF_ABR_UNKNOWN; + + if (strncmp(argv[idx_vendor]->arg, "c", 1) == 0) + abr_type = OSPF_ABR_CISCO; + else if (strncmp(argv[idx_vendor]->arg, "i", 1) == 0) + abr_type = OSPF_ABR_IBM; + else if (strncmp(argv[idx_vendor]->arg, "sh", 2) == 0) + abr_type = OSPF_ABR_SHORTCUT; + else if (strncmp(argv[idx_vendor]->arg, "st", 2) == 0) + abr_type = OSPF_ABR_STAND; + else + return CMD_WARNING_CONFIG_FAILED; - return CMD_SUCCESS; + /* If ABR type value is changed, schedule ABR task. */ + if (ospf->abr_type != abr_type) { + ospf->abr_type = abr_type; + ospf_schedule_abr_task(ospf); + } + + return CMD_SUCCESS; } DEFUN (no_ospf_abr_type, @@ -2039,29 +2013,28 @@ DEFUN (no_ospf_abr_type, "Shortcut ABR\n" "Standard ABR\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_vendor = 3; - u_char abr_type = OSPF_ABR_UNKNOWN; - - if (strncmp (argv[idx_vendor]->arg, "c", 1) == 0) - abr_type = OSPF_ABR_CISCO; - else if (strncmp (argv[idx_vendor]->arg, "i", 1) == 0) - abr_type = OSPF_ABR_IBM; - else if (strncmp (argv[idx_vendor]->arg, "sh", 2) == 0) - abr_type = OSPF_ABR_SHORTCUT; - else if (strncmp (argv[idx_vendor]->arg, "st", 2) == 0) - abr_type = OSPF_ABR_STAND; - else - return CMD_WARNING_CONFIG_FAILED; - - /* If ABR type value is changed, schedule ABR task. */ - if (ospf->abr_type == abr_type) - { - ospf->abr_type = OSPF_ABR_DEFAULT; - ospf_schedule_abr_task (ospf); - } + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_vendor = 3; + u_char abr_type = OSPF_ABR_UNKNOWN; + + if (strncmp(argv[idx_vendor]->arg, "c", 1) == 0) + abr_type = OSPF_ABR_CISCO; + else if (strncmp(argv[idx_vendor]->arg, "i", 1) == 0) + abr_type = OSPF_ABR_IBM; + else if (strncmp(argv[idx_vendor]->arg, "sh", 2) == 0) + abr_type = OSPF_ABR_SHORTCUT; + else if (strncmp(argv[idx_vendor]->arg, "st", 2) == 0) + abr_type = OSPF_ABR_STAND; + else + return CMD_WARNING_CONFIG_FAILED; - return CMD_SUCCESS; + /* If ABR type value is changed, schedule ABR task. */ + if (ospf->abr_type == abr_type) { + ospf->abr_type = OSPF_ABR_DEFAULT; + ospf_schedule_abr_task(ospf); + } + + return CMD_SUCCESS; } DEFUN (ospf_log_adjacency_changes, @@ -2069,11 +2042,11 @@ DEFUN (ospf_log_adjacency_changes, "log-adjacency-changes", "Log changes in adjacency state\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); + VTY_DECLVAR_CONTEXT(ospf, ospf); - SET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES); - UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL); - return CMD_SUCCESS; + SET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES); + UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL); + return CMD_SUCCESS; } DEFUN (ospf_log_adjacency_changes_detail, @@ -2082,11 +2055,11 @@ DEFUN (ospf_log_adjacency_changes_detail, "Log changes in adjacency state\n" "Log all state changes\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); + VTY_DECLVAR_CONTEXT(ospf, ospf); - SET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES); - SET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL); - return CMD_SUCCESS; + SET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES); + SET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL); + return CMD_SUCCESS; } DEFUN (no_ospf_log_adjacency_changes, @@ -2095,11 +2068,11 @@ DEFUN (no_ospf_log_adjacency_changes, NO_STR "Log changes in adjacency state\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); + VTY_DECLVAR_CONTEXT(ospf, ospf); - UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL); - UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES); - return CMD_SUCCESS; + UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL); + UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES); + return CMD_SUCCESS; } DEFUN (no_ospf_log_adjacency_changes_detail, @@ -2109,10 +2082,10 @@ DEFUN (no_ospf_log_adjacency_changes_detail, "Log changes in adjacency state\n" "Log all state changes\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); + VTY_DECLVAR_CONTEXT(ospf, ospf); - UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL); - return CMD_SUCCESS; + UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL); + return CMD_SUCCESS; } DEFUN (ospf_compatible_rfc1583, @@ -2121,14 +2094,13 @@ DEFUN (ospf_compatible_rfc1583, "OSPF compatibility list\n" "compatible with RFC 1583\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); + VTY_DECLVAR_CONTEXT(ospf, ospf); - if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE)) - { - SET_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE); - ospf_spf_calculate_schedule (ospf, SPF_FLAG_CONFIG_CHANGE); - } - return CMD_SUCCESS; + if (!CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) { + SET_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE); + ospf_spf_calculate_schedule(ospf, SPF_FLAG_CONFIG_CHANGE); + } + return CMD_SUCCESS; } DEFUN (no_ospf_compatible_rfc1583, @@ -2138,41 +2110,35 @@ DEFUN (no_ospf_compatible_rfc1583, "OSPF compatibility list\n" "compatible with RFC 1583\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); + VTY_DECLVAR_CONTEXT(ospf, ospf); - if (CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE)) - { - UNSET_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE); - ospf_spf_calculate_schedule (ospf, SPF_FLAG_CONFIG_CHANGE); - } - return CMD_SUCCESS; + if (CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) { + UNSET_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE); + ospf_spf_calculate_schedule(ospf, SPF_FLAG_CONFIG_CHANGE); + } + return CMD_SUCCESS; } -ALIAS (ospf_compatible_rfc1583, - ospf_rfc1583_flag_cmd, - "ospf rfc1583compatibility", - "OSPF specific commands\n" - "Enable the RFC1583Compatibility flag\n") +ALIAS(ospf_compatible_rfc1583, ospf_rfc1583_flag_cmd, + "ospf rfc1583compatibility", + "OSPF specific commands\n" + "Enable the RFC1583Compatibility flag\n") -ALIAS (no_ospf_compatible_rfc1583, - no_ospf_rfc1583_flag_cmd, - "no ospf rfc1583compatibility", - NO_STR - "OSPF specific commands\n" - "Disable the RFC1583Compatibility flag\n") +ALIAS(no_ospf_compatible_rfc1583, no_ospf_rfc1583_flag_cmd, + "no ospf rfc1583compatibility", NO_STR + "OSPF specific commands\n" + "Disable the RFC1583Compatibility flag\n") -static int -ospf_timers_spf_set (struct vty *vty, unsigned int delay, - unsigned int hold, - unsigned int max) +static int ospf_timers_spf_set(struct vty *vty, unsigned int delay, + unsigned int hold, unsigned int max) { - VTY_DECLVAR_CONTEXT(ospf, ospf); + VTY_DECLVAR_CONTEXT(ospf, ospf); - ospf->spf_delay = delay; - ospf->spf_holdtime = hold; - ospf->spf_max_holdtime = max; - - return CMD_SUCCESS; + ospf->spf_delay = delay; + ospf->spf_holdtime = hold; + ospf->spf_max_holdtime = max; + + return CMD_SUCCESS; } DEFUN (ospf_timers_min_ls_interval, @@ -2184,21 +2150,20 @@ DEFUN (ospf_timers_min_ls_interval, "All LSA types\n" "Delay (msec) between sending LSAs\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_number = 4; - unsigned int interval; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_number = 4; + unsigned int interval; - if (argc < 5) - { - vty_out (vty, "Insufficient arguments\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (argc < 5) { + vty_out(vty, "Insufficient arguments\n"); + return CMD_WARNING_CONFIG_FAILED; + } - interval = strtoul(argv[idx_number]->arg, NULL, 10); + interval = strtoul(argv[idx_number]->arg, NULL, 10); - ospf->min_ls_interval = interval; + ospf->min_ls_interval = interval; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf_timers_min_ls_interval, @@ -2211,10 +2176,10 @@ DEFUN (no_ospf_timers_min_ls_interval, "All LSA types\n" "Delay (msec) between sending LSAs\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - ospf->min_ls_interval = OSPF_MIN_LS_INTERVAL; + VTY_DECLVAR_CONTEXT(ospf, ospf); + ospf->min_ls_interval = OSPF_MIN_LS_INTERVAL; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -2226,21 +2191,20 @@ DEFUN (ospf_timers_min_ls_arrival, "OSPF minimum arrival interval delay\n" "Delay (msec) between accepted LSAs\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_number = 3; - unsigned int arrival; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_number = 3; + unsigned int arrival; - if (argc < 4) - { - vty_out (vty, "Insufficient arguments\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (argc < 4) { + vty_out(vty, "Insufficient arguments\n"); + return CMD_WARNING_CONFIG_FAILED; + } - arrival = strtoul(argv[idx_number]->arg, NULL, 10); + arrival = strtoul(argv[idx_number]->arg, NULL, 10); - ospf->min_ls_arrival = arrival; + ospf->min_ls_arrival = arrival; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf_timers_min_ls_arrival, @@ -2252,11 +2216,11 @@ DEFUN (no_ospf_timers_min_ls_arrival, "OSPF minimum arrival interval delay\n" "Delay (msec) between accepted LSAs\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); + VTY_DECLVAR_CONTEXT(ospf, ospf); - ospf->min_ls_arrival = OSPF_MIN_LS_ARRIVAL; + ospf->min_ls_arrival = OSPF_MIN_LS_ARRIVAL; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -2270,22 +2234,21 @@ DEFUN (ospf_timers_throttle_spf, "Initial hold time (msec) between consecutive SPF calculations\n" "Maximum hold time (msec)\n") { - int idx_number = 3; - int idx_number_2 = 4; - int idx_number_3 = 5; - unsigned int delay, hold, max; - - if (argc < 6) - { - vty_out (vty, "Insufficient arguments\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - delay = strtoul(argv[idx_number]->arg, NULL, 10); - hold = strtoul(argv[idx_number_2]->arg, NULL, 10); - max = strtoul(argv[idx_number_3]->arg, NULL, 10); - - return ospf_timers_spf_set (vty, delay, hold, max); + int idx_number = 3; + int idx_number_2 = 4; + int idx_number_3 = 5; + unsigned int delay, hold, max; + + if (argc < 6) { + vty_out(vty, "Insufficient arguments\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + delay = strtoul(argv[idx_number]->arg, NULL, 10); + hold = strtoul(argv[idx_number_2]->arg, NULL, 10); + max = strtoul(argv[idx_number_3]->arg, NULL, 10); + + return ospf_timers_spf_set(vty, delay, hold, max); } DEFUN (no_ospf_timers_throttle_spf, @@ -2299,10 +2262,9 @@ DEFUN (no_ospf_timers_throttle_spf, "Initial hold time (msec) between consecutive SPF calculations\n" "Maximum hold time (msec)\n") { - return ospf_timers_spf_set (vty, - OSPF_SPF_DELAY_DEFAULT, - OSPF_SPF_HOLDTIME_DEFAULT, - OSPF_SPF_MAX_HOLDTIME_DEFAULT); + return ospf_timers_spf_set(vty, OSPF_SPF_DELAY_DEFAULT, + OSPF_SPF_HOLDTIME_DEFAULT, + OSPF_SPF_MAX_HOLDTIME_DEFAULT); } @@ -2314,21 +2276,20 @@ DEFUN (ospf_timers_lsa, "Minimum delay in receiving new version of a LSA\n" "Delay in milliseconds\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_number = 3; - unsigned int minarrival; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_number = 3; + unsigned int minarrival; - if (argc < 4) - { - vty_out (vty, "Insufficient number of arguments\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (argc < 4) { + vty_out(vty, "Insufficient number of arguments\n"); + return CMD_WARNING_CONFIG_FAILED; + } - minarrival = strtoul(argv[idx_number]->arg, NULL, 10); + minarrival = strtoul(argv[idx_number]->arg, NULL, 10); - ospf->min_ls_arrival = minarrival; + ospf->min_ls_arrival = minarrival; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf_timers_lsa, @@ -2340,21 +2301,20 @@ DEFUN (no_ospf_timers_lsa, "Minimum delay in receiving new version of a LSA\n" "Delay in milliseconds\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - unsigned int minarrival; + VTY_DECLVAR_CONTEXT(ospf, ospf); + unsigned int minarrival; - if (argc > 4) - { - minarrival = strtoul(argv[4]->arg, NULL, 10); + if (argc > 4) { + minarrival = strtoul(argv[4]->arg, NULL, 10); - if (ospf->min_ls_arrival != minarrival || - minarrival == OSPF_MIN_LS_ARRIVAL) - return CMD_SUCCESS; - } + if (ospf->min_ls_arrival != minarrival + || minarrival == OSPF_MIN_LS_ARRIVAL) + return CMD_SUCCESS; + } - ospf->min_ls_arrival = OSPF_MIN_LS_ARRIVAL; + ospf->min_ls_arrival = OSPF_MIN_LS_ARRIVAL; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ospf_neighbor, @@ -2367,31 +2327,31 @@ DEFUN (ospf_neighbor, "Dead Neighbor Polling interval\n" "Seconds\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4 = 1; - int idx_pri = 3; - int idx_poll = 5; - struct in_addr nbr_addr; - unsigned int priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT; - unsigned int interval = OSPF_POLL_INTERVAL_DEFAULT; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4 = 1; + int idx_pri = 3; + int idx_poll = 5; + struct in_addr nbr_addr; + unsigned int priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT; + unsigned int interval = OSPF_POLL_INTERVAL_DEFAULT; - inet_aton(argv[idx_ipv4]->arg, &nbr_addr); + inet_aton(argv[idx_ipv4]->arg, &nbr_addr); - if (argc > 2) - priority = strtoul(argv[idx_pri]->arg, NULL, 10); + if (argc > 2) + priority = strtoul(argv[idx_pri]->arg, NULL, 10); - if (argc > 4) - interval = strtoul(argv[idx_poll]->arg, NULL, 10); + if (argc > 4) + interval = strtoul(argv[idx_poll]->arg, NULL, 10); - ospf_nbr_nbma_set (ospf, nbr_addr); + ospf_nbr_nbma_set(ospf, nbr_addr); - if (argc > 2) - ospf_nbr_nbma_priority_set (ospf, nbr_addr, priority); + if (argc > 2) + ospf_nbr_nbma_priority_set(ospf, nbr_addr, priority); - if (argc > 4) - ospf_nbr_nbma_poll_interval_set (ospf, nbr_addr, interval); + if (argc > 4) + ospf_nbr_nbma_poll_interval_set(ospf, nbr_addr, interval); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ospf_neighbor_poll_interval, @@ -2404,28 +2364,28 @@ DEFUN (ospf_neighbor_poll_interval, "OSPF priority of non-broadcast neighbor\n" "Priority\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4 = 1; - int idx_poll = 3; - int idx_pri = 5; - struct in_addr nbr_addr; - unsigned int priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT; - unsigned int interval = OSPF_POLL_INTERVAL_DEFAULT; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4 = 1; + int idx_poll = 3; + int idx_pri = 5; + struct in_addr nbr_addr; + unsigned int priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT; + unsigned int interval = OSPF_POLL_INTERVAL_DEFAULT; - inet_aton(argv[idx_ipv4]->arg, &nbr_addr); + inet_aton(argv[idx_ipv4]->arg, &nbr_addr); - interval = strtoul(argv[idx_poll]->arg, NULL, 10); + interval = strtoul(argv[idx_poll]->arg, NULL, 10); - if (argc > 4) - priority = strtoul(argv[idx_pri]->arg, NULL, 10); + if (argc > 4) + priority = strtoul(argv[idx_pri]->arg, NULL, 10); - ospf_nbr_nbma_set (ospf, nbr_addr); - ospf_nbr_nbma_poll_interval_set (ospf, nbr_addr, interval); + ospf_nbr_nbma_set(ospf, nbr_addr); + ospf_nbr_nbma_poll_interval_set(ospf, nbr_addr, interval); - if (argc > 4) - ospf_nbr_nbma_priority_set (ospf, nbr_addr, priority); + if (argc > 4) + ospf_nbr_nbma_priority_set(ospf, nbr_addr, priority); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf_neighbor, @@ -2439,15 +2399,15 @@ DEFUN (no_ospf_neighbor, "Dead Neighbor Polling interval\n" "Seconds\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4 = 2; - struct in_addr nbr_addr; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4 = 2; + struct in_addr nbr_addr; - inet_aton(argv[idx_ipv4]->arg, &nbr_addr); + inet_aton(argv[idx_ipv4]->arg, &nbr_addr); - (void)ospf_nbr_nbma_unset (ospf, nbr_addr); + (void)ospf_nbr_nbma_unset(ospf, nbr_addr); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf_neighbor_poll, @@ -2461,15 +2421,15 @@ DEFUN (no_ospf_neighbor_poll, "Neighbor Priority\n" "Priority\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ipv4 = 2; - struct in_addr nbr_addr; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ipv4 = 2; + struct in_addr nbr_addr; - inet_aton(argv[idx_ipv4]->arg, &nbr_addr); + inet_aton(argv[idx_ipv4]->arg, &nbr_addr); - (void)ospf_nbr_nbma_unset (ospf, nbr_addr); + (void)ospf_nbr_nbma_unset(ospf, nbr_addr); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ospf_refresh_timer, @@ -2479,16 +2439,17 @@ DEFUN (ospf_refresh_timer, "Set refresh timer\n" "Timer value in seconds\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_number = 2; - unsigned int interval; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_number = 2; + unsigned int interval; - interval = strtoul(argv[idx_number]->arg, NULL, 10); - interval = (interval / OSPF_LSA_REFRESHER_GRANULARITY) * OSPF_LSA_REFRESHER_GRANULARITY; + interval = strtoul(argv[idx_number]->arg, NULL, 10); + interval = (interval / OSPF_LSA_REFRESHER_GRANULARITY) + * OSPF_LSA_REFRESHER_GRANULARITY; - ospf_timers_refresh_set (ospf, interval); + ospf_timers_refresh_set(ospf, interval); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf_refresh_timer, @@ -2499,22 +2460,21 @@ DEFUN (no_ospf_refresh_timer, "Unset refresh timer\n" "Timer value in seconds\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_number = 3; - unsigned int interval; - - if (argc == 1) - { - interval = strtoul(argv[idx_number]->arg, NULL, 10); - - if (ospf->lsa_refresh_interval != interval || - interval == OSPF_LSA_REFRESH_INTERVAL_DEFAULT) - return CMD_SUCCESS; - } + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_number = 3; + unsigned int interval; - ospf_timers_refresh_unset (ospf); + if (argc == 1) { + interval = strtoul(argv[idx_number]->arg, NULL, 10); - return CMD_SUCCESS; + if (ospf->lsa_refresh_interval != interval + || interval == OSPF_LSA_REFRESH_INTERVAL_DEFAULT) + return CMD_SUCCESS; + } + + ospf_timers_refresh_unset(ospf); + + return CMD_SUCCESS; } @@ -2525,28 +2485,27 @@ DEFUN (ospf_auto_cost_reference_bandwidth, "Use reference bandwidth method to assign OSPF cost\n" "The reference bandwidth in terms of Mbits per second\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_number = 2; - u_int32_t refbw; - struct listnode *node; - struct interface *ifp; - - refbw = strtol (argv[idx_number]->arg, NULL, 10); - if (refbw < 1 || refbw > 4294967) - { - vty_out (vty, "reference-bandwidth value is invalid\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* If reference bandwidth is changed. */ - if ((refbw) == ospf->ref_bandwidth) - return CMD_SUCCESS; - - ospf->ref_bandwidth = refbw; - for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp)) - ospf_if_recalculate_output_cost (ifp); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_number = 2; + u_int32_t refbw; + struct listnode *node; + struct interface *ifp; + + refbw = strtol(argv[idx_number]->arg, NULL, 10); + if (refbw < 1 || refbw > 4294967) { + vty_out(vty, "reference-bandwidth value is invalid\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* If reference bandwidth is changed. */ + if ((refbw) == ospf->ref_bandwidth) + return CMD_SUCCESS; + + ospf->ref_bandwidth = refbw; + for (ALL_LIST_ELEMENTS_RO(om->iflist, node, ifp)) + ospf_if_recalculate_output_cost(ifp); + + return CMD_SUCCESS; } DEFUN (no_ospf_auto_cost_reference_bandwidth, @@ -2557,21 +2516,22 @@ DEFUN (no_ospf_auto_cost_reference_bandwidth, "Use reference bandwidth method to assign OSPF cost\n" "The reference bandwidth in terms of Mbits per second\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - struct listnode *node, *nnode; - struct interface *ifp; + VTY_DECLVAR_CONTEXT(ospf, ospf); + struct listnode *node, *nnode; + struct interface *ifp; - if (ospf->ref_bandwidth == OSPF_DEFAULT_REF_BANDWIDTH) - return CMD_SUCCESS; - - ospf->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH; - vty_out (vty, "%% OSPF: Reference bandwidth is changed.\n"); - vty_out (vty, " Please ensure reference bandwidth is consistent across all routers\n"); - - for (ALL_LIST_ELEMENTS (om->iflist, node, nnode, ifp)) - ospf_if_recalculate_output_cost (ifp); - - return CMD_SUCCESS; + if (ospf->ref_bandwidth == OSPF_DEFAULT_REF_BANDWIDTH) + return CMD_SUCCESS; + + ospf->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH; + vty_out(vty, "%% OSPF: Reference bandwidth is changed.\n"); + vty_out(vty, + " Please ensure reference bandwidth is consistent across all routers\n"); + + for (ALL_LIST_ELEMENTS(om->iflist, node, nnode, ifp)) + ospf_if_recalculate_output_cost(ifp); + + return CMD_SUCCESS; } DEFUN (ospf_write_multiplier, @@ -2581,31 +2541,28 @@ DEFUN (ospf_write_multiplier, "Write multiplier\n" "Maximum number of interface serviced per write\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_number; - u_int32_t write_oi_count; - - if (argc == 3) - idx_number = 2; - else - idx_number = 1; - - write_oi_count = strtol (argv[idx_number]->arg, NULL, 10); - if (write_oi_count < 1 || write_oi_count > 100) - { - vty_out (vty, "write-multiplier value is invalid\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ospf->write_oi_count = write_oi_count; - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_number; + u_int32_t write_oi_count; + + if (argc == 3) + idx_number = 2; + else + idx_number = 1; + + write_oi_count = strtol(argv[idx_number]->arg, NULL, 10); + if (write_oi_count < 1 || write_oi_count > 100) { + vty_out(vty, "write-multiplier value is invalid\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ospf->write_oi_count = write_oi_count; + return CMD_SUCCESS; } -ALIAS (ospf_write_multiplier, - write_multiplier_cmd, - "write-multiplier (1-100)", - "Write multiplier\n" - "Maximum number of interface serviced per write\n") +ALIAS(ospf_write_multiplier, write_multiplier_cmd, "write-multiplier (1-100)", + "Write multiplier\n" + "Maximum number of interface serviced per write\n") DEFUN (no_ospf_write_multiplier, no_ospf_write_multiplier_cmd, @@ -2615,564 +2572,618 @@ DEFUN (no_ospf_write_multiplier, "Write multiplier\n" "Maximum number of interface serviced per write\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); + VTY_DECLVAR_CONTEXT(ospf, ospf); - ospf->write_oi_count = OSPF_WRITE_INTERFACE_COUNT_DEFAULT; - return CMD_SUCCESS; + ospf->write_oi_count = OSPF_WRITE_INTERFACE_COUNT_DEFAULT; + return CMD_SUCCESS; } -ALIAS (no_ospf_write_multiplier, - no_write_multiplier_cmd, - "no write-multiplier (1-100)", - NO_STR - "Write multiplier\n" - "Maximum number of interface serviced per write\n") +ALIAS(no_ospf_write_multiplier, no_write_multiplier_cmd, + "no write-multiplier (1-100)", NO_STR + "Write multiplier\n" + "Maximum number of interface serviced per write\n") + +const char *ospf_abr_type_descr_str[] = {"Unknown", "Standard (RFC2328)", + "Alternative IBM", "Alternative Cisco", + "Alternative Shortcut"}; + +const char *ospf_shortcut_mode_descr_str[] = {"Default", "Enabled", "Disabled"}; + +static void show_ip_ospf_area(struct vty *vty, struct ospf_area *area, + json_object *json_areas, u_char use_json) +{ + json_object *json_area = NULL; + + if (use_json) + json_area = json_object_new_object(); + + /* Show Area ID. */ + if (!use_json) + vty_out(vty, " Area ID: %s", inet_ntoa(area->area_id)); + + /* Show Area type/mode. */ + if (OSPF_IS_AREA_BACKBONE(area)) { + if (use_json) + json_object_boolean_true_add(json_area, "backbone"); + else + vty_out(vty, " (Backbone)\n"); + } else { + if (use_json) { + if (area->external_routing == OSPF_AREA_STUB) { + if (area->no_summary) + json_object_boolean_true_add( + json_area, "stubNoSummary"); + if (area->shortcut_configured) + json_object_boolean_true_add( + json_area, "stubShortcut"); + } else if (area->external_routing == OSPF_AREA_NSSA) { + if (area->no_summary) + json_object_boolean_true_add( + json_area, "nssaNoSummary"); + if (area->shortcut_configured) + json_object_boolean_true_add( + json_area, "nssaShortcut"); + } -const char *ospf_abr_type_descr_str[] = -{ - "Unknown", - "Standard (RFC2328)", - "Alternative IBM", - "Alternative Cisco", - "Alternative Shortcut" -}; + json_object_string_add( + json_area, "shortcuttingMode", + ospf_shortcut_mode_descr_str + [area->shortcut_configured]); + if (area->shortcut_capability) + json_object_boolean_true_add(json_area, + "sBitConcensus"); + } else { + if (area->external_routing == OSPF_AREA_STUB) + vty_out(vty, " (Stub%s%s)", + area->no_summary ? ", no summary" : "", + area->shortcut_configured ? "; " : ""); + else if (area->external_routing == OSPF_AREA_NSSA) + vty_out(vty, " (NSSA%s%s)", + area->no_summary ? ", no summary" : "", + area->shortcut_configured ? "; " : ""); + + vty_out(vty, "\n"); + vty_out(vty, " Shortcutting mode: %s", + ospf_shortcut_mode_descr_str + [area->shortcut_configured]); + vty_out(vty, ", S-bit consensus: %s\n", + area->shortcut_capability ? "ok" : "no"); + } + } -const char *ospf_shortcut_mode_descr_str[] = -{ - "Default", - "Enabled", - "Disabled" -}; + /* Show number of interfaces */ + if (use_json) { + json_object_int_add(json_area, "areaIfTotalCounter", + listcount(area->oiflist)); + json_object_int_add(json_area, "areaIfActiveCounter", + area->act_ints); + } else + vty_out(vty, + " Number of interfaces in this area: Total: %d, " + "Active: %d\n", + listcount(area->oiflist), area->act_ints); + + if (area->external_routing == OSPF_AREA_NSSA) { + if (use_json) { + json_object_boolean_true_add(json_area, "nssa"); + if (!IS_OSPF_ABR(area->ospf)) + json_object_boolean_false_add(json_area, "abr"); + else if (area->NSSATranslatorState) { + json_object_boolean_true_add(json_area, "abr"); + if (area->NSSATranslatorRole + == OSPF_NSSA_ROLE_CANDIDATE) + json_object_boolean_true_add( + json_area, + "nssaTranslatorElected"); + else if (area->NSSATranslatorRole + == OSPF_NSSA_ROLE_ALWAYS) + json_object_boolean_true_add( + json_area, + "nssaTranslatorAlways"); + } else { + json_object_boolean_true_add(json_area, "abr"); + if (area->NSSATranslatorRole + == OSPF_NSSA_ROLE_CANDIDATE) + json_object_boolean_false_add( + json_area, + "nssaTranslatorElected"); + else + json_object_boolean_true_add( + json_area, + "nssaTranslatorNever"); + } + } else { + vty_out(vty, + " It is an NSSA configuration. \n Elected NSSA/ABR performs type-7/type-5 LSA translation. \n"); + if (!IS_OSPF_ABR(area->ospf)) + vty_out(vty, + " It is not ABR, therefore not Translator. \n"); + else if (area->NSSATranslatorState) { + vty_out(vty, " We are an ABR and "); + if (area->NSSATranslatorRole + == OSPF_NSSA_ROLE_CANDIDATE) + vty_out(vty, + "the NSSA Elected Translator. \n"); + else if (area->NSSATranslatorRole + == OSPF_NSSA_ROLE_ALWAYS) + vty_out(vty, + "always an NSSA Translator. \n"); + } else { + vty_out(vty, " We are an ABR, but "); + if (area->NSSATranslatorRole + == OSPF_NSSA_ROLE_CANDIDATE) + vty_out(vty, + "not the NSSA Elected Translator. \n"); + else + vty_out(vty, + "never an NSSA Translator. \n"); + } + } + } + + /* Stub-router state for this area */ + if (CHECK_FLAG(area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED)) { + char timebuf[OSPF_TIME_DUMP_SIZE]; + + if (use_json) { + json_object_boolean_true_add( + json_area, "originStubMaxDistRouterLsa"); + if (CHECK_FLAG(area->stub_router_state, + OSPF_AREA_ADMIN_STUB_ROUTED)) + json_object_boolean_true_add( + json_area, "indefiniteActiveAdmin"); + if (area->t_stub_router) { + long time_store; + time_store = + monotime_until( + &area->t_stub_router->u.sands, + NULL) + / 1000LL; + json_object_int_add( + json_area, + "activeStartupRemainderMsecs", + time_store); + } + } else { + vty_out(vty, + " Originating stub / maximum-distance Router-LSA\n"); + if (CHECK_FLAG(area->stub_router_state, + OSPF_AREA_ADMIN_STUB_ROUTED)) + vty_out(vty, + " Administratively activated (indefinitely)\n"); + if (area->t_stub_router) + vty_out(vty, + " Active from startup, %s remaining\n", + ospf_timer_dump(area->t_stub_router, + timebuf, + sizeof(timebuf))); + } + } + + if (use_json) { + /* Show number of fully adjacent neighbors. */ + json_object_int_add(json_area, "nbrFullAdjacentCounter", + area->full_nbrs); + + /* Show authentication type. */ + if (area->auth_type == OSPF_AUTH_NULL) + json_object_string_add(json_area, "authentication", + "authenticationNone"); + else if (area->auth_type == OSPF_AUTH_SIMPLE) + json_object_string_add(json_area, "authentication", + "authenticationSimplePassword"); + else if (area->auth_type == OSPF_AUTH_CRYPTOGRAPHIC) + json_object_string_add(json_area, "authentication", + "authenticationMessageDigest"); + + if (!OSPF_IS_AREA_BACKBONE(area)) + json_object_int_add(json_area, + "virtualAdjacenciesPassingCounter", + area->full_vls); + + /* Show SPF calculation times. */ + json_object_int_add(json_area, "spfExecutedCounter", + area->spf_calculation); + json_object_int_add(json_area, "lsaNumber", area->lsdb->total); + json_object_int_add( + json_area, "lsaRouterNumber", + ospf_lsdb_count(area->lsdb, OSPF_ROUTER_LSA)); + json_object_int_add( + json_area, "lsaRouterChecksum", + ospf_lsdb_checksum(area->lsdb, OSPF_ROUTER_LSA)); + json_object_int_add( + json_area, "lsaNetworkNumber", + ospf_lsdb_count(area->lsdb, OSPF_NETWORK_LSA)); + json_object_int_add( + json_area, "lsaNetworkChecksum", + ospf_lsdb_checksum(area->lsdb, OSPF_NETWORK_LSA)); + json_object_int_add( + json_area, "lsaSummaryNumber", + ospf_lsdb_count(area->lsdb, OSPF_SUMMARY_LSA)); + json_object_int_add( + json_area, "lsaSummaryChecksum", + ospf_lsdb_checksum(area->lsdb, OSPF_SUMMARY_LSA)); + json_object_int_add( + json_area, "lsaAsbrNumber", + ospf_lsdb_count(area->lsdb, OSPF_ASBR_SUMMARY_LSA)); + json_object_int_add( + json_area, "lsaAsbrChecksum", + ospf_lsdb_checksum(area->lsdb, OSPF_ASBR_SUMMARY_LSA)); + json_object_int_add( + json_area, "lsaNssaNumber", + ospf_lsdb_count(area->lsdb, OSPF_AS_NSSA_LSA)); + json_object_int_add( + json_area, "lsaNssaChecksum", + ospf_lsdb_checksum(area->lsdb, OSPF_AS_NSSA_LSA)); + } else { + /* Show number of fully adjacent neighbors. */ + vty_out(vty, + " Number of fully adjacent neighbors in this area:" + " %d\n", + area->full_nbrs); + + /* Show authentication type. */ + vty_out(vty, " Area has "); + if (area->auth_type == OSPF_AUTH_NULL) + vty_out(vty, "no authentication\n"); + else if (area->auth_type == OSPF_AUTH_SIMPLE) + vty_out(vty, "simple password authentication\n"); + else if (area->auth_type == OSPF_AUTH_CRYPTOGRAPHIC) + vty_out(vty, "message digest authentication\n"); + + if (!OSPF_IS_AREA_BACKBONE(area)) + vty_out(vty, + " Number of full virtual adjacencies going through" + " this area: %d\n", + area->full_vls); + + /* Show SPF calculation times. */ + vty_out(vty, " SPF algorithm executed %d times\n", + area->spf_calculation); + + /* Show number of LSA. */ + vty_out(vty, " Number of LSA %ld\n", area->lsdb->total); + vty_out(vty, + " Number of router LSA %ld. Checksum Sum 0x%08x\n", + ospf_lsdb_count(area->lsdb, OSPF_ROUTER_LSA), + ospf_lsdb_checksum(area->lsdb, OSPF_ROUTER_LSA)); + vty_out(vty, + " Number of network LSA %ld. Checksum Sum 0x%08x\n", + ospf_lsdb_count(area->lsdb, OSPF_NETWORK_LSA), + ospf_lsdb_checksum(area->lsdb, OSPF_NETWORK_LSA)); + vty_out(vty, + " Number of summary LSA %ld. Checksum Sum 0x%08x\n", + ospf_lsdb_count(area->lsdb, OSPF_SUMMARY_LSA), + ospf_lsdb_checksum(area->lsdb, OSPF_SUMMARY_LSA)); + vty_out(vty, + " Number of ASBR summary LSA %ld. Checksum Sum 0x%08x\n", + ospf_lsdb_count(area->lsdb, OSPF_ASBR_SUMMARY_LSA), + ospf_lsdb_checksum(area->lsdb, OSPF_ASBR_SUMMARY_LSA)); + vty_out(vty, " Number of NSSA LSA %ld. Checksum Sum 0x%08x\n", + ospf_lsdb_count(area->lsdb, OSPF_AS_NSSA_LSA), + ospf_lsdb_checksum(area->lsdb, OSPF_AS_NSSA_LSA)); + } + + if (use_json) { + json_object_int_add( + json_area, "lsaOpaqueLinkNumber", + ospf_lsdb_count(area->lsdb, OSPF_OPAQUE_LINK_LSA)); + json_object_int_add( + json_area, "lsaOpaqueLinkChecksum", + ospf_lsdb_checksum(area->lsdb, OSPF_OPAQUE_LINK_LSA)); + json_object_int_add( + json_area, "lsaOpaqueAreaNumber", + ospf_lsdb_count(area->lsdb, OSPF_OPAQUE_AREA_LSA)); + json_object_int_add( + json_area, "lsaOpaqueAreaChecksum", + ospf_lsdb_checksum(area->lsdb, OSPF_OPAQUE_AREA_LSA)); + } else { + vty_out(vty, + " Number of opaque link LSA %ld. Checksum Sum 0x%08x\n", + ospf_lsdb_count(area->lsdb, OSPF_OPAQUE_LINK_LSA), + ospf_lsdb_checksum(area->lsdb, OSPF_OPAQUE_LINK_LSA)); + vty_out(vty, + " Number of opaque area LSA %ld. Checksum Sum 0x%08x\n", + ospf_lsdb_count(area->lsdb, OSPF_OPAQUE_AREA_LSA), + ospf_lsdb_checksum(area->lsdb, OSPF_OPAQUE_AREA_LSA)); + } -static void -show_ip_ospf_area (struct vty *vty, struct ospf_area *area, json_object *json_areas, u_char use_json) -{ - json_object *json_area = NULL; - - if (use_json) - json_area = json_object_new_object(); - - /* Show Area ID. */ - if (!use_json) - vty_out (vty, " Area ID: %s", inet_ntoa (area->area_id)); - - /* Show Area type/mode. */ - if (OSPF_IS_AREA_BACKBONE (area)) - { - if (use_json) - json_object_boolean_true_add(json_area, "backbone"); - else - vty_out (vty, " (Backbone)\n"); - } - else - { - if (use_json) - { - if (area->external_routing == OSPF_AREA_STUB) - { - if (area->no_summary) - json_object_boolean_true_add(json_area, "stubNoSummary"); - if (area->shortcut_configured) - json_object_boolean_true_add(json_area, "stubShortcut"); - } - else if (area->external_routing == OSPF_AREA_NSSA) - { - if (area->no_summary) - json_object_boolean_true_add(json_area, "nssaNoSummary"); - if (area->shortcut_configured) - json_object_boolean_true_add(json_area, "nssaShortcut"); - } - - json_object_string_add(json_area,"shortcuttingMode", - ospf_shortcut_mode_descr_str[area->shortcut_configured]); - if (area->shortcut_capability) - json_object_boolean_true_add(json_area,"sBitConcensus"); - } - else - { - if (area->external_routing == OSPF_AREA_STUB) - vty_out (vty, " (Stub%s%s)", - area->no_summary ? ", no summary" : "", - area->shortcut_configured ? "; " : ""); - else if (area->external_routing == OSPF_AREA_NSSA) - vty_out (vty, " (NSSA%s%s)", - area->no_summary ? ", no summary" : "", - area->shortcut_configured ? "; " : ""); - - vty_out (vty, "\n"); - vty_out (vty, " Shortcutting mode: %s", - ospf_shortcut_mode_descr_str[area->shortcut_configured]); - vty_out (vty, ", S-bit consensus: %s\n", - area->shortcut_capability ? "ok" : "no"); - } - } - - /* Show number of interfaces */ - if (use_json) - { - json_object_int_add(json_area, "areaIfTotalCounter", listcount (area->oiflist)); - json_object_int_add(json_area, "areaIfActiveCounter", area->act_ints); - } - else - vty_out (vty, " Number of interfaces in this area: Total: %d, " - "Active: %d\n", listcount (area->oiflist), - area->act_ints); - - if (area->external_routing == OSPF_AREA_NSSA) - { - if (use_json) - { - json_object_boolean_true_add(json_area, "nssa"); - if (! IS_OSPF_ABR (area->ospf)) - json_object_boolean_false_add(json_area, "abr"); - else if (area->NSSATranslatorState) - { - json_object_boolean_true_add(json_area, "abr"); - if (area->NSSATranslatorRole == OSPF_NSSA_ROLE_CANDIDATE) - json_object_boolean_true_add(json_area, "nssaTranslatorElected"); - else if (area->NSSATranslatorRole == OSPF_NSSA_ROLE_ALWAYS) - json_object_boolean_true_add(json_area, "nssaTranslatorAlways"); - } - else - { - json_object_boolean_true_add(json_area, "abr"); - if (area->NSSATranslatorRole == OSPF_NSSA_ROLE_CANDIDATE) - json_object_boolean_false_add(json_area, "nssaTranslatorElected"); - else - json_object_boolean_true_add(json_area, "nssaTranslatorNever"); - } - } - else - { - vty_out (vty, " It is an NSSA configuration. \n Elected NSSA/ABR performs type-7/type-5 LSA translation. \n"); - if (! IS_OSPF_ABR (area->ospf)) - vty_out (vty, " It is not ABR, therefore not Translator. \n"); - else if (area->NSSATranslatorState) - { - vty_out (vty, " We are an ABR and "); - if (area->NSSATranslatorRole == OSPF_NSSA_ROLE_CANDIDATE) - vty_out (vty, "the NSSA Elected Translator. \n"); - else if (area->NSSATranslatorRole == OSPF_NSSA_ROLE_ALWAYS) - vty_out (vty, "always an NSSA Translator. \n"); - } - else - { - vty_out (vty, " We are an ABR, but "); - if (area->NSSATranslatorRole == OSPF_NSSA_ROLE_CANDIDATE) - vty_out (vty, "not the NSSA Elected Translator. \n"); - else - vty_out (vty, "never an NSSA Translator. \n"); - } - } - } - - /* Stub-router state for this area */ - if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED)) - { - char timebuf[OSPF_TIME_DUMP_SIZE]; - - if (use_json) - { - json_object_boolean_true_add(json_area, "originStubMaxDistRouterLsa"); - if (CHECK_FLAG(area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED)) - json_object_boolean_true_add(json_area, "indefiniteActiveAdmin"); - if (area->t_stub_router) - { - long time_store; - time_store = monotime_until(&area->t_stub_router->u.sands, NULL) / 1000LL; - json_object_int_add(json_area, "activeStartupRemainderMsecs", time_store); - } - } - else - { - vty_out (vty, " Originating stub / maximum-distance Router-LSA\n"); - if (CHECK_FLAG(area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED)) - vty_out (vty, " Administratively activated (indefinitely)\n"); - if (area->t_stub_router) - vty_out (vty, " Active from startup, %s remaining\n", - ospf_timer_dump (area->t_stub_router, timebuf, - sizeof(timebuf))); - } - } - - if (use_json) - { - /* Show number of fully adjacent neighbors. */ - json_object_int_add(json_area, "nbrFullAdjacentCounter", area->full_nbrs); - - /* Show authentication type. */ - if (area->auth_type == OSPF_AUTH_NULL) - json_object_string_add(json_area, "authentication", "authenticationNone"); - else if (area->auth_type == OSPF_AUTH_SIMPLE) - json_object_string_add(json_area, "authentication", "authenticationSimplePassword"); - else if (area->auth_type == OSPF_AUTH_CRYPTOGRAPHIC) - json_object_string_add(json_area, "authentication", "authenticationMessageDigest"); - - if (!OSPF_IS_AREA_BACKBONE (area)) - json_object_int_add(json_area, "virtualAdjacenciesPassingCounter", area->full_vls); - - /* Show SPF calculation times. */ - json_object_int_add(json_area, "spfExecutedCounter", area->spf_calculation); - json_object_int_add(json_area, "lsaNumber", area->lsdb->total); - json_object_int_add(json_area, "lsaRouterNumber", ospf_lsdb_count (area->lsdb, OSPF_ROUTER_LSA)); - json_object_int_add(json_area, "lsaRouterChecksum", ospf_lsdb_checksum (area->lsdb, OSPF_ROUTER_LSA)); - json_object_int_add(json_area, "lsaNetworkNumber", ospf_lsdb_count (area->lsdb, OSPF_NETWORK_LSA)); - json_object_int_add(json_area, "lsaNetworkChecksum", ospf_lsdb_checksum (area->lsdb, OSPF_NETWORK_LSA)); - json_object_int_add(json_area, "lsaSummaryNumber", ospf_lsdb_count (area->lsdb, OSPF_SUMMARY_LSA)); - json_object_int_add(json_area, "lsaSummaryChecksum", ospf_lsdb_checksum (area->lsdb, OSPF_SUMMARY_LSA)); - json_object_int_add(json_area, "lsaAsbrNumber", ospf_lsdb_count (area->lsdb, OSPF_ASBR_SUMMARY_LSA)); - json_object_int_add(json_area, "lsaAsbrChecksum", ospf_lsdb_checksum (area->lsdb, OSPF_ASBR_SUMMARY_LSA)); - json_object_int_add(json_area, "lsaNssaNumber", ospf_lsdb_count (area->lsdb, OSPF_AS_NSSA_LSA)); - json_object_int_add(json_area, "lsaNssaChecksum", ospf_lsdb_checksum (area->lsdb, OSPF_AS_NSSA_LSA)); - } - else - { - /* Show number of fully adjacent neighbors. */ - vty_out (vty, " Number of fully adjacent neighbors in this area:" - " %d\n", area->full_nbrs); - - /* Show authentication type. */ - vty_out (vty, " Area has "); - if (area->auth_type == OSPF_AUTH_NULL) - vty_out (vty, "no authentication\n"); - else if (area->auth_type == OSPF_AUTH_SIMPLE) - vty_out (vty, "simple password authentication\n"); - else if (area->auth_type == OSPF_AUTH_CRYPTOGRAPHIC) - vty_out (vty, "message digest authentication\n"); - - if (!OSPF_IS_AREA_BACKBONE (area)) - vty_out (vty, " Number of full virtual adjacencies going through" - " this area: %d\n", area->full_vls); - - /* Show SPF calculation times. */ - vty_out (vty, " SPF algorithm executed %d times\n", - area->spf_calculation); - - /* Show number of LSA. */ - vty_out (vty, " Number of LSA %ld\n", area->lsdb->total); - vty_out (vty, " Number of router LSA %ld. Checksum Sum 0x%08x\n", - ospf_lsdb_count (area->lsdb, OSPF_ROUTER_LSA), - ospf_lsdb_checksum (area->lsdb, OSPF_ROUTER_LSA)); - vty_out (vty, " Number of network LSA %ld. Checksum Sum 0x%08x\n", - ospf_lsdb_count (area->lsdb, OSPF_NETWORK_LSA), - ospf_lsdb_checksum (area->lsdb, OSPF_NETWORK_LSA)); - vty_out (vty, " Number of summary LSA %ld. Checksum Sum 0x%08x\n", - ospf_lsdb_count (area->lsdb, OSPF_SUMMARY_LSA), - ospf_lsdb_checksum (area->lsdb, OSPF_SUMMARY_LSA)); - vty_out (vty, " Number of ASBR summary LSA %ld. Checksum Sum 0x%08x\n", - ospf_lsdb_count (area->lsdb, OSPF_ASBR_SUMMARY_LSA), - ospf_lsdb_checksum (area->lsdb, OSPF_ASBR_SUMMARY_LSA)); - vty_out (vty, " Number of NSSA LSA %ld. Checksum Sum 0x%08x\n", - ospf_lsdb_count (area->lsdb, OSPF_AS_NSSA_LSA), - ospf_lsdb_checksum (area->lsdb, OSPF_AS_NSSA_LSA)); - } - - if (use_json) - { - json_object_int_add(json_area, "lsaOpaqueLinkNumber", ospf_lsdb_count (area->lsdb, OSPF_OPAQUE_LINK_LSA)); - json_object_int_add(json_area, "lsaOpaqueLinkChecksum", ospf_lsdb_checksum (area->lsdb, OSPF_OPAQUE_LINK_LSA)); - json_object_int_add(json_area, "lsaOpaqueAreaNumber", ospf_lsdb_count (area->lsdb, OSPF_OPAQUE_AREA_LSA)); - json_object_int_add(json_area, "lsaOpaqueAreaChecksum", ospf_lsdb_checksum (area->lsdb, OSPF_OPAQUE_AREA_LSA)); - } - else - { - vty_out (vty, " Number of opaque link LSA %ld. Checksum Sum 0x%08x\n", - ospf_lsdb_count (area->lsdb, OSPF_OPAQUE_LINK_LSA), - ospf_lsdb_checksum (area->lsdb, OSPF_OPAQUE_LINK_LSA)); - vty_out (vty, " Number of opaque area LSA %ld. Checksum Sum 0x%08x\n", - ospf_lsdb_count (area->lsdb, OSPF_OPAQUE_AREA_LSA), - ospf_lsdb_checksum (area->lsdb, OSPF_OPAQUE_AREA_LSA)); - } - - if (use_json) - json_object_object_add(json_areas, inet_ntoa (area->area_id), json_area); - else - vty_out (vty, "\n"); + if (use_json) + json_object_object_add(json_areas, inet_ntoa(area->area_id), + json_area); + else + vty_out(vty, "\n"); } -static int -show_ip_ospf_common (struct vty *vty, struct ospf *ospf, u_char use_json) -{ - struct listnode *node, *nnode; - struct ospf_area * area; - struct timeval result; - char timebuf[OSPF_TIME_DUMP_SIZE]; - json_object *json = NULL; - json_object *json_areas = NULL; - - if (use_json) - { - json = json_object_new_object(); - json_areas = json_object_new_object(); - } - - if (ospf->instance) - { - if (use_json) - { - json_object_int_add(json, "ospfInstance", ospf->instance); - } - else - { - vty_out (vty, "\nOSPF Instance: %d\n\n", ospf->instance); - } - } - - /* Show Router ID. */ - if (use_json) - { - json_object_string_add(json, "routerId", inet_ntoa (ospf->router_id)); - } - else - { - vty_out (vty, " OSPF Routing Process, Router ID: %s\n", - inet_ntoa (ospf->router_id)); - } - - /* Graceful shutdown */ - if (ospf->t_deferred_shutdown) - { - if (use_json) - { - long time_store; - time_store = monotime_until(&ospf->t_deferred_shutdown->u.sands, NULL) / 1000LL; - json_object_int_add(json, "deferredShutdownMsecs", time_store); - } - else - { - vty_out (vty, " Deferred shutdown in progress, %s remaining\n", - ospf_timer_dump (ospf->t_deferred_shutdown, - timebuf, sizeof (timebuf))); - } - } - - /* Show capability. */ - if (use_json) - { - json_object_boolean_true_add(json, "tosRoutesOnly"); - json_object_boolean_true_add(json, "rfc2328Conform"); - if (CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE)) - { - json_object_boolean_true_add(json, "rfc1583Compatibility"); - } - } - else - { - vty_out (vty, " Supports only single TOS (TOS0) routes\n"); - vty_out (vty, " This implementation conforms to RFC2328\n"); - vty_out (vty, " RFC1583Compatibility flag is %s\n", - CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE) ? - "enabled" : "disabled"); - } - - if (use_json) - { - if (CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE)) - { - json_object_boolean_true_add(json, "opaqueCapable"); - } - } - else - { - vty_out (vty, " OpaqueCapability flag is %s\n", - CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE) ? "enabled" : "disabled"); - } - - /* Show stub-router configuration */ - if (ospf->stub_router_startup_time != OSPF_STUB_ROUTER_UNCONFIGURED - || ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED) - { - if (use_json) - { - json_object_boolean_true_add(json, "stubAdvertisement"); - if (ospf->stub_router_startup_time != OSPF_STUB_ROUTER_UNCONFIGURED) - json_object_int_add(json,"postStartEnabledMsecs", ospf->stub_router_startup_time / 1000); - if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED) - json_object_int_add(json,"preShutdownEnabledMsecs", ospf->stub_router_shutdown_time / 1000); - } - else - { - vty_out (vty, " Stub router advertisement is configured\n"); - if (ospf->stub_router_startup_time != OSPF_STUB_ROUTER_UNCONFIGURED) - vty_out (vty, " Enabled for %us after start-up\n", - ospf->stub_router_startup_time); - if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED) - vty_out (vty, " Enabled for %us prior to full shutdown\n", - ospf->stub_router_shutdown_time); - } - } - - /* Show SPF timers. */ - if (use_json) - { - json_object_int_add(json, "spfScheduleDelayMsecs", ospf->spf_delay); - json_object_int_add(json, "holdtimeMinMsecs", ospf->spf_holdtime); - json_object_int_add(json, "holdtimeMaxMsecs", ospf->spf_max_holdtime); - json_object_int_add(json, "holdtimeMultplier", ospf->spf_hold_multiplier); - } - else - { - vty_out (vty, " Initial SPF scheduling delay %d millisec(s)\n" - " Minimum hold time between consecutive SPFs %d millisec(s)\n" - " Maximum hold time between consecutive SPFs %d millisec(s)\n" - " Hold time multiplier is currently %d\n", - ospf->spf_delay, - ospf->spf_holdtime, - ospf->spf_max_holdtime, - ospf->spf_hold_multiplier); - } - - if (use_json) - { - if (ospf->ts_spf.tv_sec || ospf->ts_spf.tv_usec) - { - long time_store = 0; - - time_store = monotime_since(&ospf->ts_spf, NULL) / 1000LL; - json_object_int_add(json, "spfLastExecutedMsecs", time_store); - - time_store = (1000 * ospf->ts_spf_duration.tv_sec) + (ospf->ts_spf_duration.tv_usec / 1000); - json_object_int_add(json, "spfLastDurationMsecs", time_store); - } - else - json_object_boolean_true_add(json, "spfHasNotRun"); - } - else - { - vty_out (vty, " SPF algorithm "); - if (ospf->ts_spf.tv_sec || ospf->ts_spf.tv_usec) - { - monotime_since(&ospf->ts_spf, &result); - vty_out (vty, "last executed %s ago\n", - ospf_timeval_dump (&result, timebuf, sizeof (timebuf))); - vty_out (vty, " Last SPF duration %s\n", - ospf_timeval_dump (&ospf->ts_spf_duration, timebuf, sizeof (timebuf))); - } - else - vty_out (vty, "has not been run\n"); - } - - if (use_json) - { - if (ospf->t_spf_calc) - { - long time_store; - time_store = monotime_until(&ospf->t_spf_calc->u.sands, NULL) / 1000LL; - json_object_int_add(json, "spfTimerDueInMsecs", time_store); - } - - json_object_int_add(json, "lsaMinIntervalMsecs", ospf->min_ls_interval); - json_object_int_add(json, "lsaMinArrivalMsecs", ospf->min_ls_arrival); - /* Show write multiplier values */ - json_object_int_add(json, "writeMultiplier", ospf->write_oi_count); - /* Show refresh parameters. */ - json_object_int_add(json, "refreshTimerMsecs", ospf->lsa_refresh_interval * 1000); - } - else - { - vty_out (vty, " SPF timer %s%s\n", - (ospf->t_spf_calc ? "due in " : "is "), - ospf_timer_dump (ospf->t_spf_calc, timebuf, sizeof (timebuf))); - - vty_out (vty, " LSA minimum interval %d msecs\n", - ospf->min_ls_interval); - vty_out (vty, " LSA minimum arrival %d msecs\n", - ospf->min_ls_arrival); - - /* Show write multiplier values */ - vty_out (vty, " Write Multiplier set to %d \n", - ospf->write_oi_count); - - /* Show refresh parameters. */ - vty_out (vty, " Refresh timer %d secs\n", - ospf->lsa_refresh_interval); - } - - /* Show ABR/ASBR flags. */ - if (CHECK_FLAG (ospf->flags, OSPF_FLAG_ABR)) - { - if (use_json) - json_object_string_add(json, "abrType", ospf_abr_type_descr_str[ospf->abr_type]); - else - vty_out (vty, " This router is an ABR, ABR type is: %s\n", - ospf_abr_type_descr_str[ospf->abr_type]); - } - if (CHECK_FLAG (ospf->flags, OSPF_FLAG_ASBR)) - { - if (use_json) - json_object_string_add(json, "asbrRouter", "injectingExternalRoutingInformation"); - else - vty_out (vty, " This router is an ASBR " - "(injecting external routing information)\n"); - } - - /* Show Number of AS-external-LSAs. */ - if (use_json) - { - json_object_int_add(json, "lsaExternalCounter", - ospf_lsdb_count (ospf->lsdb, OSPF_AS_EXTERNAL_LSA)); - json_object_int_add(json, "lsaExternalChecksum", - ospf_lsdb_checksum (ospf->lsdb, OSPF_AS_EXTERNAL_LSA)); - } - else - { - vty_out (vty, " Number of external LSA %ld. Checksum Sum 0x%08x\n", - ospf_lsdb_count (ospf->lsdb, OSPF_AS_EXTERNAL_LSA), - ospf_lsdb_checksum (ospf->lsdb, OSPF_AS_EXTERNAL_LSA)); - } - - if (use_json) - { - json_object_int_add(json, "lsaAsopaqueCounter", - ospf_lsdb_count (ospf->lsdb, OSPF_OPAQUE_AS_LSA)); - json_object_int_add(json, "lsaAsOpaqueChecksum", - ospf_lsdb_checksum (ospf->lsdb, OSPF_OPAQUE_AS_LSA)); - } - else - { - vty_out (vty, " Number of opaque AS LSA %ld. Checksum Sum 0x%08x\n", - ospf_lsdb_count (ospf->lsdb, OSPF_OPAQUE_AS_LSA), - ospf_lsdb_checksum (ospf->lsdb, OSPF_OPAQUE_AS_LSA)); - } - - /* Show number of areas attached. */ - if (use_json) - json_object_int_add(json, "attachedAreaCounter", listcount (ospf->areas)); - else - vty_out (vty, " Number of areas attached to this router: %d\n", - listcount (ospf->areas)); - - if (CHECK_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES)) - { - if (CHECK_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) - { - if (use_json) - json_object_boolean_true_add(json, "adjacencyChangesLoggedAll"); - else - vty_out(vty, " All adjacency changes are logged\n"); - } - else - { - if (use_json) - json_object_boolean_true_add(json, "adjacencyChangesLogged"); - else - vty_out(vty, " Adjacency changes are logged\n"); - } - } - /* Show each area status. */ - for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) - show_ip_ospf_area (vty, area, json_areas, use_json); - - if (use_json) - { - json_object_object_add(json, "areas", json_areas); - vty_out (vty, "%s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - vty_out (vty, "\n"); +static int show_ip_ospf_common(struct vty *vty, struct ospf *ospf, + u_char use_json) +{ + struct listnode *node, *nnode; + struct ospf_area *area; + struct timeval result; + char timebuf[OSPF_TIME_DUMP_SIZE]; + json_object *json = NULL; + json_object *json_areas = NULL; - return CMD_SUCCESS; + if (use_json) { + json = json_object_new_object(); + json_areas = json_object_new_object(); + } + + if (ospf->instance) { + if (use_json) { + json_object_int_add(json, "ospfInstance", + ospf->instance); + } else { + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + } + + /* Show Router ID. */ + if (use_json) { + json_object_string_add(json, "routerId", + inet_ntoa(ospf->router_id)); + } else { + vty_out(vty, " OSPF Routing Process, Router ID: %s\n", + inet_ntoa(ospf->router_id)); + } + + /* Graceful shutdown */ + if (ospf->t_deferred_shutdown) { + if (use_json) { + long time_store; + time_store = + monotime_until( + &ospf->t_deferred_shutdown->u.sands, + NULL) + / 1000LL; + json_object_int_add(json, "deferredShutdownMsecs", + time_store); + } else { + vty_out(vty, + " Deferred shutdown in progress, %s remaining\n", + ospf_timer_dump(ospf->t_deferred_shutdown, + timebuf, sizeof(timebuf))); + } + } + + /* Show capability. */ + if (use_json) { + json_object_boolean_true_add(json, "tosRoutesOnly"); + json_object_boolean_true_add(json, "rfc2328Conform"); + if (CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) { + json_object_boolean_true_add(json, + "rfc1583Compatibility"); + } + } else { + vty_out(vty, " Supports only single TOS (TOS0) routes\n"); + vty_out(vty, " This implementation conforms to RFC2328\n"); + vty_out(vty, " RFC1583Compatibility flag is %s\n", + CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE) + ? "enabled" + : "disabled"); + } + + if (use_json) { + if (CHECK_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE)) { + json_object_boolean_true_add(json, "opaqueCapable"); + } + } else { + vty_out(vty, " OpaqueCapability flag is %s\n", + CHECK_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE) + ? "enabled" + : "disabled"); + } + + /* Show stub-router configuration */ + if (ospf->stub_router_startup_time != OSPF_STUB_ROUTER_UNCONFIGURED + || ospf->stub_router_shutdown_time + != OSPF_STUB_ROUTER_UNCONFIGURED) { + if (use_json) { + json_object_boolean_true_add(json, "stubAdvertisement"); + if (ospf->stub_router_startup_time + != OSPF_STUB_ROUTER_UNCONFIGURED) + json_object_int_add( + json, "postStartEnabledMsecs", + ospf->stub_router_startup_time / 1000); + if (ospf->stub_router_shutdown_time + != OSPF_STUB_ROUTER_UNCONFIGURED) + json_object_int_add( + json, "preShutdownEnabledMsecs", + ospf->stub_router_shutdown_time / 1000); + } else { + vty_out(vty, + " Stub router advertisement is configured\n"); + if (ospf->stub_router_startup_time + != OSPF_STUB_ROUTER_UNCONFIGURED) + vty_out(vty, + " Enabled for %us after start-up\n", + ospf->stub_router_startup_time); + if (ospf->stub_router_shutdown_time + != OSPF_STUB_ROUTER_UNCONFIGURED) + vty_out(vty, + " Enabled for %us prior to full shutdown\n", + ospf->stub_router_shutdown_time); + } + } + + /* Show SPF timers. */ + if (use_json) { + json_object_int_add(json, "spfScheduleDelayMsecs", + ospf->spf_delay); + json_object_int_add(json, "holdtimeMinMsecs", + ospf->spf_holdtime); + json_object_int_add(json, "holdtimeMaxMsecs", + ospf->spf_max_holdtime); + json_object_int_add(json, "holdtimeMultplier", + ospf->spf_hold_multiplier); + } else { + vty_out(vty, + " Initial SPF scheduling delay %d millisec(s)\n" + " Minimum hold time between consecutive SPFs %d millisec(s)\n" + " Maximum hold time between consecutive SPFs %d millisec(s)\n" + " Hold time multiplier is currently %d\n", + ospf->spf_delay, ospf->spf_holdtime, + ospf->spf_max_holdtime, ospf->spf_hold_multiplier); + } + + if (use_json) { + if (ospf->ts_spf.tv_sec || ospf->ts_spf.tv_usec) { + long time_store = 0; + + time_store = + monotime_since(&ospf->ts_spf, NULL) / 1000LL; + json_object_int_add(json, "spfLastExecutedMsecs", + time_store); + + time_store = (1000 * ospf->ts_spf_duration.tv_sec) + + (ospf->ts_spf_duration.tv_usec / 1000); + json_object_int_add(json, "spfLastDurationMsecs", + time_store); + } else + json_object_boolean_true_add(json, "spfHasNotRun"); + } else { + vty_out(vty, " SPF algorithm "); + if (ospf->ts_spf.tv_sec || ospf->ts_spf.tv_usec) { + monotime_since(&ospf->ts_spf, &result); + vty_out(vty, "last executed %s ago\n", + ospf_timeval_dump(&result, timebuf, + sizeof(timebuf))); + vty_out(vty, " Last SPF duration %s\n", + ospf_timeval_dump(&ospf->ts_spf_duration, + timebuf, sizeof(timebuf))); + } else + vty_out(vty, "has not been run\n"); + } + + if (use_json) { + if (ospf->t_spf_calc) { + long time_store; + time_store = + monotime_until(&ospf->t_spf_calc->u.sands, NULL) + / 1000LL; + json_object_int_add(json, "spfTimerDueInMsecs", + time_store); + } + + json_object_int_add(json, "lsaMinIntervalMsecs", + ospf->min_ls_interval); + json_object_int_add(json, "lsaMinArrivalMsecs", + ospf->min_ls_arrival); + /* Show write multiplier values */ + json_object_int_add(json, "writeMultiplier", + ospf->write_oi_count); + /* Show refresh parameters. */ + json_object_int_add(json, "refreshTimerMsecs", + ospf->lsa_refresh_interval * 1000); + } else { + vty_out(vty, " SPF timer %s%s\n", + (ospf->t_spf_calc ? "due in " : "is "), + ospf_timer_dump(ospf->t_spf_calc, timebuf, + sizeof(timebuf))); + + vty_out(vty, " LSA minimum interval %d msecs\n", + ospf->min_ls_interval); + vty_out(vty, " LSA minimum arrival %d msecs\n", + ospf->min_ls_arrival); + + /* Show write multiplier values */ + vty_out(vty, " Write Multiplier set to %d \n", + ospf->write_oi_count); + + /* Show refresh parameters. */ + vty_out(vty, " Refresh timer %d secs\n", + ospf->lsa_refresh_interval); + } + + /* Show ABR/ASBR flags. */ + if (CHECK_FLAG(ospf->flags, OSPF_FLAG_ABR)) { + if (use_json) + json_object_string_add( + json, "abrType", + ospf_abr_type_descr_str[ospf->abr_type]); + else + vty_out(vty, + " This router is an ABR, ABR type is: %s\n", + ospf_abr_type_descr_str[ospf->abr_type]); + } + if (CHECK_FLAG(ospf->flags, OSPF_FLAG_ASBR)) { + if (use_json) + json_object_string_add( + json, "asbrRouter", + "injectingExternalRoutingInformation"); + else + vty_out(vty, + " This router is an ASBR " + "(injecting external routing information)\n"); + } + + /* Show Number of AS-external-LSAs. */ + if (use_json) { + json_object_int_add( + json, "lsaExternalCounter", + ospf_lsdb_count(ospf->lsdb, OSPF_AS_EXTERNAL_LSA)); + json_object_int_add( + json, "lsaExternalChecksum", + ospf_lsdb_checksum(ospf->lsdb, OSPF_AS_EXTERNAL_LSA)); + } else { + vty_out(vty, + " Number of external LSA %ld. Checksum Sum 0x%08x\n", + ospf_lsdb_count(ospf->lsdb, OSPF_AS_EXTERNAL_LSA), + ospf_lsdb_checksum(ospf->lsdb, OSPF_AS_EXTERNAL_LSA)); + } + + if (use_json) { + json_object_int_add( + json, "lsaAsopaqueCounter", + ospf_lsdb_count(ospf->lsdb, OSPF_OPAQUE_AS_LSA)); + json_object_int_add( + json, "lsaAsOpaqueChecksum", + ospf_lsdb_checksum(ospf->lsdb, OSPF_OPAQUE_AS_LSA)); + } else { + vty_out(vty, + " Number of opaque AS LSA %ld. Checksum Sum 0x%08x\n", + ospf_lsdb_count(ospf->lsdb, OSPF_OPAQUE_AS_LSA), + ospf_lsdb_checksum(ospf->lsdb, OSPF_OPAQUE_AS_LSA)); + } + + /* Show number of areas attached. */ + if (use_json) + json_object_int_add(json, "attachedAreaCounter", + listcount(ospf->areas)); + else + vty_out(vty, " Number of areas attached to this router: %d\n", + listcount(ospf->areas)); + + if (CHECK_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES)) { + if (CHECK_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) { + if (use_json) + json_object_boolean_true_add( + json, "adjacencyChangesLoggedAll"); + else + vty_out(vty, + " All adjacency changes are logged\n"); + } else { + if (use_json) + json_object_boolean_true_add( + json, "adjacencyChangesLogged"); + else + vty_out(vty, " Adjacency changes are logged\n"); + } + } + /* Show each area status. */ + for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) + show_ip_ospf_area(vty, area, json_areas, use_json); + + if (use_json) { + json_object_object_add(json, "areas", json_areas); + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else + vty_out(vty, "\n"); + + return CMD_SUCCESS; } DEFUN (show_ip_ospf, @@ -3183,13 +3194,13 @@ DEFUN (show_ip_ospf, "OSPF information\n" JSON_STR) { - struct ospf *ospf; - u_char uj = use_json(argc, argv); + struct ospf *ospf; + u_char uj = use_json(argc, argv); - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) + return CMD_SUCCESS; - return (show_ip_ospf_common(vty, ospf, uj)); + return (show_ip_ospf_common(vty, ospf, uj)); } DEFUN (show_ip_ospf_instance, @@ -3201,360 +3212,407 @@ DEFUN (show_ip_ospf_instance, "Instance ID\n" JSON_STR) { - int idx_number = 3; - struct ospf *ospf; - u_short instance = 0; - u_char uj = use_json(argc, argv); + int idx_number = 3; + struct ospf *ospf; + u_short instance = 0; + u_char uj = use_json(argc, argv); + + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if ((ospf = ospf_lookup_instance(instance)) == NULL + || !ospf->oi_running) + return CMD_SUCCESS; + + return (show_ip_ospf_common(vty, ospf, uj)); +} + +static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf, + struct interface *ifp, + json_object *json_interface_sub, + u_char use_json) +{ + int is_up; + struct ospf_neighbor *nbr; + struct route_node *rn; + uint32_t bandwidth = ifp->bandwidth ? ifp->bandwidth : ifp->speed; + + /* Is interface up? */ + if (use_json) { + is_up = if_is_operative(ifp); + if (is_up) + json_object_boolean_true_add(json_interface_sub, + "ifUp"); + else + json_object_boolean_false_add(json_interface_sub, + "ifDown"); + + json_object_int_add(json_interface_sub, "ifIndex", + ifp->ifindex); + json_object_int_add(json_interface_sub, "mtuBytes", ifp->mtu); + json_object_int_add(json_interface_sub, "bandwidthMbit", + bandwidth); + json_object_string_add(json_interface_sub, "ifFlags", + if_flag_dump(ifp->flags)); + } else { + vty_out(vty, "%s is %s\n", ifp->name, + ((is_up = if_is_operative(ifp)) ? "up" : "down")); + vty_out(vty, " ifindex %u, MTU %u bytes, BW %u Mbit %s\n", + ifp->ifindex, ifp->mtu, bandwidth, + if_flag_dump(ifp->flags)); + } - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if ((ospf = ospf_lookup_instance (instance)) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + /* Is interface OSPF enabled? */ + if (use_json) { + if (ospf_oi_count(ifp) == 0) { + json_object_boolean_false_add(json_interface_sub, + "ospfEnabled"); + return; + } else if (!is_up) { + json_object_boolean_false_add(json_interface_sub, + "ospfRunning"); + return; + } else + json_object_boolean_true_add(json_interface_sub, + "ospfEnabled"); + } else { + if (ospf_oi_count(ifp) == 0) { + vty_out(vty, " OSPF not enabled on this interface\n"); + return; + } else if (!is_up) { + vty_out(vty, + " OSPF is enabled, but not running on this interface\n"); + return; + } + } + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi = rn->info; + + if (oi == NULL) + continue; + + if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) { + if (use_json) + json_object_boolean_true_add(json_interface_sub, + "ifUnnumbered"); + else + vty_out(vty, " This interface is UNNUMBERED,"); + } else { + /* Show OSPF interface information. */ + if (use_json) { + json_object_string_add( + json_interface_sub, "ipAddress", + inet_ntoa(oi->address->u.prefix4)); + json_object_int_add(json_interface_sub, + "ipAddressPrefixlen", + oi->address->prefixlen); + } else + vty_out(vty, " Internet Address %s/%d,", + inet_ntoa(oi->address->u.prefix4), + oi->address->prefixlen); + + if (oi->connected->destination + || oi->type == OSPF_IFTYPE_VIRTUALLINK) { + struct in_addr *dest; + const char *dstr; + + if (CONNECTED_PEER(oi->connected) + || oi->type == OSPF_IFTYPE_VIRTUALLINK) + dstr = "Peer"; + else + dstr = "Broadcast"; + + /* For Vlinks, showing the peer address is + * probably more + * * * * * informative than the local + * interface that is being used + * * * * */ + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + dest = &oi->vl_data->peer_addr; + else + dest = &oi->connected->destination->u + .prefix4; + + if (use_json) { + json_object_string_add( + json_interface_sub, + "ospfIfType", dstr); + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + json_object_string_add( + json_interface_sub, + "vlinkPeer", + inet_ntoa(*dest)); + else + json_object_string_add( + json_interface_sub, + "localIfUsed", + inet_ntoa(*dest)); + } else + vty_out(vty, " %s %s,", dstr, + inet_ntoa(*dest)); + } + } + if (use_json) { + json_object_string_add(json_interface_sub, "area", + ospf_area_desc_string(oi->area)); + if (OSPF_IF_PARAM(oi, mtu_ignore)) + json_object_boolean_true_add( + json_interface_sub, + "mtuMismatchDetect"); + json_object_string_add(json_interface_sub, "routerId", + inet_ntoa(ospf->router_id)); + json_object_string_add(json_interface_sub, + "networkType", + ospf_network_type_str[oi->type]); + json_object_int_add(json_interface_sub, "cost", + oi->output_cost); + json_object_int_add( + json_interface_sub, "transmitDelayMsecs", + 1000 / OSPF_IF_PARAM(oi, transmit_delay)); + json_object_string_add(json_interface_sub, "state", + lookup_msg(ospf_ism_state_msg, + oi->state, NULL)); + json_object_int_add(json_interface_sub, "priority", + PRIORITY(oi)); + } else { + vty_out(vty, " Area %s\n", + ospf_area_desc_string(oi->area)); + + vty_out(vty, " MTU mismatch detection: %s\n", + OSPF_IF_PARAM(oi, mtu_ignore) ? "disabled" + : "enabled"); + + vty_out(vty, + " Router ID %s, Network Type %s, Cost: %d\n", + inet_ntoa(ospf->router_id), + ospf_network_type_str[oi->type], + oi->output_cost); + + vty_out(vty, + " Transmit Delay is %d sec, State %s, Priority %d\n", + OSPF_IF_PARAM(oi, transmit_delay), + lookup_msg(ospf_ism_state_msg, oi->state, NULL), + PRIORITY(oi)); + } + + /* Show DR information. */ + if (DR(oi).s_addr == 0) { + if (!use_json) + vty_out(vty, + " No backup designated router on this network\n"); + } else { + nbr = ospf_nbr_lookup_by_addr(oi->nbrs, &BDR(oi)); + if (nbr == NULL) { + if (!use_json) + vty_out(vty, + " No backup designated router on this network\n"); + } else { + if (use_json) { + json_object_string_add( + json_interface_sub, "bdrId", + inet_ntoa(nbr->router_id)); + json_object_string_add( + json_interface_sub, + "bdrAddress", + inet_ntoa(nbr->address.u + .prefix4)); + } else { + vty_out(vty, + " Backup Designated Router (ID) %s,", + inet_ntoa(nbr->router_id)); + vty_out(vty, " Interface Address %s\n", + inet_ntoa(nbr->address.u + .prefix4)); + } + } + } + + /* Next network-LSA sequence number we'll use, if we're elected + * DR */ + if (oi->params + && ntohl(oi->params->network_lsa_seqnum) + != OSPF_INITIAL_SEQUENCE_NUMBER) { + if (use_json) + json_object_int_add( + json_interface_sub, + "networkLsaSequence", + ntohl(oi->params->network_lsa_seqnum)); + else + vty_out(vty, + " Saved Network-LSA sequence number 0x%x\n", + ntohl(oi->params->network_lsa_seqnum)); + } + + if (use_json) { + if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS) + || OI_MEMBER_CHECK(oi, MEMBER_DROUTERS)) { + if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS)) + json_object_boolean_true_add( + json_interface_sub, + "mcastMemberOspfAllRouters"); + if (OI_MEMBER_CHECK(oi, MEMBER_DROUTERS)) + json_object_boolean_true_add( + json_interface_sub, + "mcastMemberOspfDesignatedRouters"); + } + } else { + vty_out(vty, " Multicast group memberships:"); + if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS) + || OI_MEMBER_CHECK(oi, MEMBER_DROUTERS)) { + if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS)) + vty_out(vty, " OSPFAllRouters"); + if (OI_MEMBER_CHECK(oi, MEMBER_DROUTERS)) + vty_out(vty, " OSPFDesignatedRouters"); + } else + vty_out(vty, " "); + vty_out(vty, "\n"); + } + + if (use_json) { + if (OSPF_IF_PARAM(oi, fast_hello) == 0) + json_object_int_add( + json_interface_sub, "timerMsecs", + 1000 / OSPF_IF_PARAM(oi, v_hello)); + else + json_object_int_add( + json_interface_sub, "timerMsecs", + 1000 / OSPF_IF_PARAM(oi, fast_hello)); + json_object_int_add(json_interface_sub, + "timerDeadMsecs", + 1000 / OSPF_IF_PARAM(oi, v_wait)); + json_object_int_add(json_interface_sub, + "timerWaitMsecs", + 1000 / OSPF_IF_PARAM(oi, v_wait)); + json_object_int_add( + json_interface_sub, "timerRetransmit", + 1000 / OSPF_IF_PARAM(oi, retransmit_interval)); + } else { + vty_out(vty, " Timer intervals configured,"); + vty_out(vty, " Hello "); + if (OSPF_IF_PARAM(oi, fast_hello) == 0) + vty_out(vty, "%ds,", + OSPF_IF_PARAM(oi, v_hello)); + else + vty_out(vty, "%dms,", + 1000 / OSPF_IF_PARAM(oi, fast_hello)); + vty_out(vty, " Dead %ds, Wait %ds, Retransmit %d\n", + OSPF_IF_PARAM(oi, v_wait), + OSPF_IF_PARAM(oi, v_wait), + OSPF_IF_PARAM(oi, retransmit_interval)); + } + + if (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_ACTIVE) { + char timebuf[OSPF_TIME_DUMP_SIZE]; + if (use_json) { + long time_store = 0; + if (oi->t_hello) + time_store = + monotime_until( + &oi->t_hello->u.sands, + NULL) + / 1000LL; + json_object_int_add(json_interface_sub, + "timerHelloInMsecs", + time_store); + } else + vty_out(vty, " Hello due in %s\n", + ospf_timer_dump(oi->t_hello, timebuf, + sizeof(timebuf))); + } else /* passive-interface is set */ + { + if (use_json) + json_object_boolean_true_add( + json_interface_sub, + "timerPassiveIface"); + else + vty_out(vty, + " No Hellos (Passive interface)\n"); + } - return (show_ip_ospf_common(vty, ospf, uj)); -} - -static void -show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf, struct interface *ifp, - json_object *json_interface_sub, u_char use_json) -{ - int is_up; - struct ospf_neighbor *nbr; - struct route_node *rn; - uint32_t bandwidth = ifp->bandwidth ? ifp->bandwidth : ifp->speed; - - /* Is interface up? */ - if (use_json) - { - is_up = if_is_operative(ifp); - if (is_up) - json_object_boolean_true_add(json_interface_sub, "ifUp"); - else - json_object_boolean_false_add(json_interface_sub, "ifDown"); - - json_object_int_add(json_interface_sub, "ifIndex", ifp->ifindex); - json_object_int_add(json_interface_sub, "mtuBytes", ifp->mtu); - json_object_int_add(json_interface_sub, "bandwidthMbit", bandwidth); - json_object_string_add(json_interface_sub, "ifFlags", if_flag_dump(ifp->flags)); - } - else - { - vty_out (vty, "%s is %s\n", ifp->name, - ((is_up = if_is_operative(ifp)) ? "up" : "down")); - vty_out (vty, " ifindex %u, MTU %u bytes, BW %u Mbit %s\n", - ifp->ifindex, ifp->mtu, bandwidth, if_flag_dump(ifp->flags)); - } - - /* Is interface OSPF enabled? */ - if (use_json) - { - if (ospf_oi_count(ifp) == 0) - { - json_object_boolean_false_add(json_interface_sub, "ospfEnabled"); - return; - } - else if (!is_up) - { - json_object_boolean_false_add(json_interface_sub, "ospfRunning"); - return; - } - else - json_object_boolean_true_add(json_interface_sub, "ospfEnabled"); - } - else - { - if (ospf_oi_count(ifp) == 0) - { - vty_out (vty, " OSPF not enabled on this interface\n"); - return; - } - else if (!is_up) - { - vty_out (vty, " OSPF is enabled, but not running on this interface\n"); - return; - } - } - - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - { - struct ospf_interface *oi = rn->info; - - if (oi == NULL) - continue; - - if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) - { - if (use_json) - json_object_boolean_true_add(json_interface_sub, "ifUnnumbered"); - else - vty_out (vty, " This interface is UNNUMBERED,"); - } - else - { - /* Show OSPF interface information. */ - if (use_json) - { - json_object_string_add(json_interface_sub, "ipAddress", inet_ntoa (oi->address->u.prefix4)); - json_object_int_add(json_interface_sub, "ipAddressPrefixlen", oi->address->prefixlen); - } - else - vty_out (vty, " Internet Address %s/%d,", - inet_ntoa (oi->address->u.prefix4), oi->address->prefixlen); - - if (oi->connected->destination || oi->type == OSPF_IFTYPE_VIRTUALLINK) - { - struct in_addr *dest; - const char *dstr; - - if (CONNECTED_PEER(oi->connected) - || oi->type == OSPF_IFTYPE_VIRTUALLINK) - dstr = "Peer"; - else - dstr = "Broadcast"; - - /* For Vlinks, showing the peer address is probably more - * * * * * informative than the local interface that is being used - * * * * */ - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - dest = &oi->vl_data->peer_addr; - else - dest = &oi->connected->destination->u.prefix4; - - if (use_json) - { - json_object_string_add(json_interface_sub, "ospfIfType", dstr); - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - json_object_string_add(json_interface_sub, "vlinkPeer", inet_ntoa (*dest)); - else - json_object_string_add(json_interface_sub, "localIfUsed", inet_ntoa (*dest)); - } - else - vty_out (vty, " %s %s,", dstr, inet_ntoa (*dest)); - } - } - if (use_json) - { - json_object_string_add(json_interface_sub, "area", ospf_area_desc_string (oi->area)); - if (OSPF_IF_PARAM(oi, mtu_ignore)) - json_object_boolean_true_add(json_interface_sub, "mtuMismatchDetect"); - json_object_string_add(json_interface_sub, "routerId", inet_ntoa (ospf->router_id)); - json_object_string_add(json_interface_sub, "networkType", ospf_network_type_str[oi->type]); - json_object_int_add(json_interface_sub, "cost", oi->output_cost); - json_object_int_add(json_interface_sub, "transmitDelayMsecs", 1000 / OSPF_IF_PARAM (oi,transmit_delay)); - json_object_string_add(json_interface_sub, "state", lookup_msg(ospf_ism_state_msg, oi->state, NULL)); - json_object_int_add(json_interface_sub, "priority", PRIORITY (oi)); - } - else - { - vty_out (vty, " Area %s\n", ospf_area_desc_string (oi->area)); - - vty_out (vty, " MTU mismatch detection: %s\n", - OSPF_IF_PARAM(oi, mtu_ignore) ? "disabled" : "enabled"); - - vty_out (vty, " Router ID %s, Network Type %s, Cost: %d\n", - inet_ntoa (ospf->router_id), ospf_network_type_str[oi->type], - oi->output_cost); - - vty_out (vty, " Transmit Delay is %d sec, State %s, Priority %d\n", - OSPF_IF_PARAM (oi,transmit_delay), lookup_msg(ospf_ism_state_msg, oi->state, NULL), - PRIORITY (oi)); - } - - /* Show DR information. */ - if (DR (oi).s_addr == 0) - { - if (!use_json) - vty_out (vty, " No backup designated router on this network\n"); - } - else - { - nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &BDR (oi)); - if (nbr == NULL) - { - if (!use_json) - vty_out (vty, " No backup designated router on this network\n"); - } - else - { - if (use_json) - { - json_object_string_add(json_interface_sub, "bdrId", inet_ntoa (nbr->router_id)); - json_object_string_add(json_interface_sub, "bdrAddress", inet_ntoa (nbr->address.u.prefix4)); - } - else - { - vty_out (vty, " Backup Designated Router (ID) %s,", - inet_ntoa (nbr->router_id)); - vty_out (vty, " Interface Address %s\n", - inet_ntoa (nbr->address.u.prefix4)); - } - } - } - - /* Next network-LSA sequence number we'll use, if we're elected DR */ - if (oi->params && ntohl (oi->params->network_lsa_seqnum) != OSPF_INITIAL_SEQUENCE_NUMBER) - { - if (use_json) - json_object_int_add(json_interface_sub, "networkLsaSequence", ntohl (oi->params->network_lsa_seqnum)); - else - vty_out (vty, " Saved Network-LSA sequence number 0x%x\n", - ntohl (oi->params->network_lsa_seqnum)); - } - - if (use_json) - { - if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS) - || OI_MEMBER_CHECK(oi, MEMBER_DROUTERS)) - { - if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS)) - json_object_boolean_true_add(json_interface_sub, "mcastMemberOspfAllRouters"); - if (OI_MEMBER_CHECK(oi, MEMBER_DROUTERS)) - json_object_boolean_true_add(json_interface_sub, "mcastMemberOspfDesignatedRouters"); - } - } - else - { - vty_out (vty, " Multicast group memberships:"); - if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS) - || OI_MEMBER_CHECK(oi, MEMBER_DROUTERS)) - { - if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS)) - vty_out (vty, " OSPFAllRouters"); - if (OI_MEMBER_CHECK(oi, MEMBER_DROUTERS)) - vty_out (vty, " OSPFDesignatedRouters"); - } - else - vty_out (vty, " "); - vty_out (vty, "\n"); - } - - if (use_json) - { - if (OSPF_IF_PARAM (oi, fast_hello) == 0) - json_object_int_add(json_interface_sub, "timerMsecs", 1000 /OSPF_IF_PARAM (oi, v_hello)); - else - json_object_int_add(json_interface_sub, "timerMsecs", 1000 / OSPF_IF_PARAM (oi, fast_hello)); - json_object_int_add(json_interface_sub, "timerDeadMsecs", 1000 / OSPF_IF_PARAM (oi, v_wait)); - json_object_int_add(json_interface_sub, "timerWaitMsecs", 1000 / OSPF_IF_PARAM (oi, v_wait)); - json_object_int_add(json_interface_sub, "timerRetransmit", 1000 / OSPF_IF_PARAM (oi, retransmit_interval)); - } - else - { - vty_out (vty, " Timer intervals configured,"); - vty_out (vty, " Hello "); - if (OSPF_IF_PARAM (oi, fast_hello) == 0) - vty_out (vty, "%ds,", OSPF_IF_PARAM (oi, v_hello)); - else - vty_out (vty, "%dms,", 1000 / OSPF_IF_PARAM (oi, fast_hello)); - vty_out (vty, " Dead %ds, Wait %ds, Retransmit %d\n", - OSPF_IF_PARAM (oi, v_wait), - OSPF_IF_PARAM (oi, v_wait), - OSPF_IF_PARAM (oi, retransmit_interval)); - } - - if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_ACTIVE) - { - char timebuf[OSPF_TIME_DUMP_SIZE]; - if (use_json) - { - long time_store = 0; - if (oi->t_hello) - time_store = monotime_until(&oi->t_hello->u.sands, NULL) / 1000LL; - json_object_int_add(json_interface_sub, "timerHelloInMsecs", time_store); - } - else - vty_out (vty, " Hello due in %s\n", - ospf_timer_dump (oi->t_hello, timebuf, sizeof(timebuf))); - } - else /* passive-interface is set */ - { - if (use_json) - json_object_boolean_true_add(json_interface_sub, "timerPassiveIface"); - else - vty_out (vty, " No Hellos (Passive interface)\n"); - } - - if (use_json) - { - json_object_int_add(json_interface_sub, "nbrCount", ospf_nbr_count (oi, 0)); - json_object_int_add(json_interface_sub, "nbrAdjacentCount", ospf_nbr_count (oi, NSM_Full)); - } - else - vty_out (vty, " Neighbor Count is %d, Adjacent neighbor count is %d\n", - ospf_nbr_count (oi, 0), ospf_nbr_count (oi, NSM_Full)); - ospf_bfd_interface_show(vty, ifp, json_interface_sub, use_json); - } + if (use_json) { + json_object_int_add(json_interface_sub, "nbrCount", + ospf_nbr_count(oi, 0)); + json_object_int_add(json_interface_sub, + "nbrAdjacentCount", + ospf_nbr_count(oi, NSM_Full)); + } else + vty_out(vty, + " Neighbor Count is %d, Adjacent neighbor count is %d\n", + ospf_nbr_count(oi, 0), + ospf_nbr_count(oi, NSM_Full)); + ospf_bfd_interface_show(vty, ifp, json_interface_sub, use_json); + } } -static int -show_ip_ospf_interface_common (struct vty *vty, struct ospf *ospf, int argc, - struct cmd_token **argv, int iface_argv, u_char use_json) -{ - struct interface *ifp; - struct listnode *node; - json_object *json = NULL; - json_object *json_interface_sub = NULL; - - if (use_json) - { - json = json_object_new_object(); - } - - if (ospf->instance) - { - if (use_json) - json_object_int_add(json, "ospfInstance", ospf->instance); - else - vty_out (vty, "\nOSPF Instance: %d\n\n", ospf->instance); - } - - if (argc == iface_argv) - { - /* Show All Interfaces.*/ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - if (ospf_oi_count(ifp)) - { - if (use_json) - json_interface_sub = json_object_new_object(); - - show_ip_ospf_interface_sub (vty, ospf, ifp, json_interface_sub, use_json); - - if (use_json) - json_object_object_add (json, ifp->name, json_interface_sub); - } - } - } - else - { - /* Interface name is specified. */ - if ((ifp = if_lookup_by_name (argv[iface_argv]->arg, VRF_DEFAULT)) == NULL) - { - if (use_json) - json_object_boolean_true_add(json, "noSuchIface"); - else - vty_out (vty, "No such interface name\n"); - } - else - { - if (use_json) - json_interface_sub = json_object_new_object(); - - show_ip_ospf_interface_sub (vty, ospf, ifp, json_interface_sub, use_json); - - if (use_json) - json_object_object_add(json, ifp->name, json_interface_sub); - } - } - - if (use_json) - { - vty_out (vty, "%s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - vty_out (vty, "\n"); +static int show_ip_ospf_interface_common(struct vty *vty, struct ospf *ospf, + int argc, struct cmd_token **argv, + int iface_argv, u_char use_json) +{ + struct interface *ifp; + struct listnode *node; + json_object *json = NULL; + json_object *json_interface_sub = NULL; - return CMD_SUCCESS; + if (use_json) { + json = json_object_new_object(); + } + + if (ospf->instance) { + if (use_json) + json_object_int_add(json, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + + if (argc == iface_argv) { + /* Show All Interfaces.*/ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + if (ospf_oi_count(ifp)) { + if (use_json) + json_interface_sub = + json_object_new_object(); + + show_ip_ospf_interface_sub(vty, ospf, ifp, + json_interface_sub, + use_json); + + if (use_json) + json_object_object_add( + json, ifp->name, + json_interface_sub); + } + } + } else { + /* Interface name is specified. */ + if ((ifp = if_lookup_by_name(argv[iface_argv]->arg, + VRF_DEFAULT)) + == NULL) { + if (use_json) + json_object_boolean_true_add(json, + "noSuchIface"); + else + vty_out(vty, "No such interface name\n"); + } else { + if (use_json) + json_interface_sub = json_object_new_object(); + + show_ip_ospf_interface_sub( + vty, ospf, ifp, json_interface_sub, use_json); + + if (use_json) + json_object_object_add(json, ifp->name, + json_interface_sub); + } + } + + if (use_json) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else + vty_out(vty, "\n"); + + return CMD_SUCCESS; } DEFUN (show_ip_ospf_interface, @@ -3567,16 +3625,16 @@ DEFUN (show_ip_ospf_interface, "Interface name\n" JSON_STR) { - struct ospf *ospf; - u_char uj = use_json(argc, argv); + struct ospf *ospf; + u_char uj = use_json(argc, argv); - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) + return CMD_SUCCESS; - if (uj) - argc--; + if (uj) + argc--; - return show_ip_ospf_interface_common(vty, ospf, argc, argv, 4, uj); + return show_ip_ospf_interface_common(vty, ospf, argc, argv, 4, uj); } DEFUN (show_ip_ospf_instance_interface, @@ -3590,129 +3648,182 @@ DEFUN (show_ip_ospf_instance_interface, "Interface name\n" JSON_STR) { - int idx_number = 3; - struct ospf *ospf; - u_short instance = 0; - u_char uj = use_json(argc, argv); + int idx_number = 3; + struct ospf *ospf; + u_short instance = 0; + u_char uj = use_json(argc, argv); + + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if ((ospf = ospf_lookup_instance(instance)) == NULL + || !ospf->oi_running) + return CMD_SUCCESS; + + if (uj) + argc--; + + return show_ip_ospf_interface_common(vty, ospf, argc, argv, 5, uj); +} + +static void show_ip_ospf_neighbour_header(struct vty *vty) +{ + vty_out(vty, "\n%-15s %3s %-15s %9s %-15s %-20s %5s %5s %5s\n", + "Neighbor ID", "Pri", "State", "Dead Time", "Address", + "Interface", "RXmtL", "RqstL", "DBsmL"); +} + +static void show_ip_ospf_neighbor_sub(struct vty *vty, + struct ospf_interface *oi, + json_object *json, u_char use_json) +{ + struct route_node *rn; + struct ospf_neighbor *nbr; + char msgbuf[16]; + char timebuf[OSPF_TIME_DUMP_SIZE]; + json_object *json_neighbor = NULL; + + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) { + if ((nbr = rn->info)) { + /* Do not show myself. */ + if (nbr != oi->nbr_self) { + /* Down state is not shown. */ + if (nbr->state != NSM_Down) { + if (use_json) { + json_neighbor = + json_object_new_object(); + ospf_nbr_state_message( + nbr, msgbuf, 16); + + long time_store; + + time_store = + monotime_until( + &nbr->t_inactivity + ->u + .sands, + NULL) + / 1000LL; + + json_object_int_add( + json_neighbor, + "priority", + nbr->priority); + json_object_string_add( + json_neighbor, "state", + msgbuf); + json_object_int_add( + json_neighbor, + "deadTimeMsecs", + time_store); + json_object_string_add( + json_neighbor, + "address", + inet_ntoa(nbr->src)); + json_object_string_add( + json_neighbor, + "ifaceName", + IF_NAME(oi)); + json_object_int_add( + json_neighbor, + "retransmitCounter", + ospf_ls_retransmit_count( + nbr)); + json_object_int_add( + json_neighbor, + "requestCounter", + ospf_ls_request_count( + nbr)); + json_object_int_add( + json_neighbor, + "dbSummaryCounter", + ospf_db_summary_count( + nbr)); + if (nbr->state == NSM_Attempt + && nbr->router_id.s_addr + == 0) + json_object_object_add( + json, + "neighbor", + json_neighbor); + else + json_object_object_add( + json, + inet_ntoa( + nbr->router_id), + json_neighbor); + } else { + ospf_nbr_state_message( + nbr, msgbuf, 16); + + if (nbr->state == NSM_Attempt + && nbr->router_id.s_addr + == 0) + vty_out(vty, + "%-15s %3d %-15s ", + "-", + nbr->priority, + msgbuf); + else + vty_out(vty, + "%-15s %3d %-15s ", + inet_ntoa( + nbr->router_id), + nbr->priority, + msgbuf); + + vty_out(vty, "%9s ", + ospf_timer_dump( + nbr->t_inactivity, + timebuf, + sizeof(timebuf))); + vty_out(vty, "%-15s ", + inet_ntoa(nbr->src)); + vty_out(vty, + "%-20s %5ld %5ld %5d\n", + IF_NAME(oi), + ospf_ls_retransmit_count( + nbr), + ospf_ls_request_count( + nbr), + ospf_db_summary_count( + nbr)); + } + } + } + } + } +} + +static int show_ip_ospf_neighbor_common(struct vty *vty, struct ospf *ospf, + u_char use_json) +{ + struct ospf_interface *oi; + struct listnode *node; + json_object *json = NULL; - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if ((ospf = ospf_lookup_instance (instance)) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + if (use_json) + json = json_object_new_object(); + else + show_ip_ospf_neighbour_header(vty); + + if (ospf->instance) { + if (use_json) + json_object_int_add(json, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } - if (uj) - argc--; - - return show_ip_ospf_interface_common(vty, ospf, argc, argv, 5, uj); -} - -static void -show_ip_ospf_neighbour_header (struct vty *vty) -{ - vty_out (vty, "\n%-15s %3s %-15s %9s %-15s %-20s %5s %5s %5s\n", - "Neighbor ID", "Pri", "State", "Dead Time", - "Address", "Interface", "RXmtL", "RqstL", "DBsmL"); -} - -static void -show_ip_ospf_neighbor_sub (struct vty *vty, struct ospf_interface *oi, json_object *json, u_char use_json) -{ - struct route_node *rn; - struct ospf_neighbor *nbr; - char msgbuf[16]; - char timebuf[OSPF_TIME_DUMP_SIZE]; - json_object *json_neighbor = NULL; - - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - { - if ((nbr = rn->info)) - { - /* Do not show myself. */ - if (nbr != oi->nbr_self) - { - /* Down state is not shown. */ - if (nbr->state != NSM_Down) - { - if (use_json) - { - json_neighbor = json_object_new_object(); - ospf_nbr_state_message (nbr, msgbuf, 16); - - long time_store; - - time_store = monotime_until(&nbr->t_inactivity->u.sands, NULL) / 1000LL; - - json_object_int_add (json_neighbor, "priority", nbr->priority); - json_object_string_add (json_neighbor, "state", msgbuf); - json_object_int_add (json_neighbor, "deadTimeMsecs", time_store); - json_object_string_add (json_neighbor, "address", inet_ntoa (nbr->src)); - json_object_string_add (json_neighbor, "ifaceName", IF_NAME (oi)); - json_object_int_add (json_neighbor, "retransmitCounter", ospf_ls_retransmit_count (nbr)); - json_object_int_add (json_neighbor, "requestCounter", ospf_ls_request_count (nbr)); - json_object_int_add (json_neighbor, "dbSummaryCounter", ospf_db_summary_count (nbr)); - if (nbr->state == NSM_Attempt && nbr->router_id.s_addr == 0) - json_object_object_add(json, "neighbor", json_neighbor); - else - json_object_object_add(json, inet_ntoa (nbr->router_id), json_neighbor); - } - else - { - ospf_nbr_state_message (nbr, msgbuf, 16); - - if (nbr->state == NSM_Attempt && nbr->router_id.s_addr == 0) - vty_out (vty, "%-15s %3d %-15s ", - "-", nbr->priority, - msgbuf); - else - vty_out (vty, "%-15s %3d %-15s ", - inet_ntoa (nbr->router_id), nbr->priority, - msgbuf); - - vty_out (vty, "%9s ", - ospf_timer_dump (nbr->t_inactivity, timebuf, - sizeof(timebuf))); - vty_out (vty, "%-15s ", inet_ntoa (nbr->src)); - vty_out (vty, "%-20s %5ld %5ld %5d\n", - IF_NAME (oi), ospf_ls_retransmit_count (nbr), - ospf_ls_request_count (nbr), ospf_db_summary_count (nbr)); - } - } - } - } - } -} + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) + show_ip_ospf_neighbor_sub(vty, oi, json, use_json); -static int -show_ip_ospf_neighbor_common (struct vty *vty, struct ospf *ospf, u_char use_json) -{ - struct ospf_interface *oi; - struct listnode *node; - json_object *json = NULL; - - if (use_json) - json = json_object_new_object(); - else - show_ip_ospf_neighbour_header (vty); - - if (ospf->instance) - { - if (use_json) - json_object_int_add(json, "ospfInstance", ospf->instance); - else - vty_out (vty, "\nOSPF Instance: %d\n\n", ospf->instance); - } - - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) - show_ip_ospf_neighbor_sub (vty, oi, json, use_json); - - if (use_json) - { - vty_out (vty, "%s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - vty_out (vty, "\n"); + if (use_json) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else + vty_out(vty, "\n"); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_ospf_neighbor, @@ -3724,13 +3835,13 @@ DEFUN (show_ip_ospf_neighbor, "Neighbor list\n" JSON_STR) { - struct ospf *ospf; - u_char uj = use_json(argc, argv); + struct ospf *ospf; + u_char uj = use_json(argc, argv); - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) + return CMD_SUCCESS; - return show_ip_ospf_neighbor_common(vty, ospf, uj); + return show_ip_ospf_neighbor_common(vty, ospf, uj); } @@ -3744,86 +3855,95 @@ DEFUN (show_ip_ospf_instance_neighbor, "Neighbor list\n" JSON_STR) { - int idx_number = 3; - struct ospf *ospf; - u_short instance = 0; - u_char uj = use_json(argc, argv); + int idx_number = 3; + struct ospf *ospf; + u_short instance = 0; + u_char uj = use_json(argc, argv); - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if ((ospf = ospf_lookup_instance(instance)) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if ((ospf = ospf_lookup_instance(instance)) == NULL + || !ospf->oi_running) + return CMD_SUCCESS; - return show_ip_ospf_neighbor_common(vty, ospf, uj); + return show_ip_ospf_neighbor_common(vty, ospf, uj); } -static int -show_ip_ospf_neighbor_all_common (struct vty *vty, struct ospf *ospf, u_char use_json) -{ - struct listnode *node; - struct ospf_interface *oi; - json_object *json = NULL; - json_object *json_neighbor_sub = NULL; - - if (use_json) - { - json = json_object_new_object(); - json_neighbor_sub = json_object_new_object(); - } - else - show_ip_ospf_neighbour_header (vty); - - if (ospf->instance) - { - if (use_json) - json_object_int_add(json, "ospfInstance", ospf->instance); - else - vty_out (vty, "\nOSPF Instance: %d\n\n", ospf->instance); - } - - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) - { - struct listnode *nbr_node; - struct ospf_nbr_nbma *nbr_nbma; - - show_ip_ospf_neighbor_sub (vty, oi, json, use_json); - - /* print Down neighbor status */ - for (ALL_LIST_ELEMENTS_RO (oi->nbr_nbma, nbr_node, nbr_nbma)) - { - if (nbr_nbma->nbr == NULL - || nbr_nbma->nbr->state == NSM_Down) - { - if (use_json) - { - json_object_int_add (json_neighbor_sub, "nbrNbmaPriority", nbr_nbma->priority); - json_object_boolean_true_add (json_neighbor_sub, "nbrNbmaDown"); - json_object_string_add (json_neighbor_sub, "nbrNbmaIfaceName", IF_NAME (oi)); - json_object_int_add (json_neighbor_sub, "nbrNbmaRetransmitCounter", 0); - json_object_int_add (json_neighbor_sub, "nbrNbmaRequestCounter", 0); - json_object_int_add (json_neighbor_sub, "nbrNbmaDbSummaryCounter", 0); - json_object_object_add(json, inet_ntoa (nbr_nbma->addr), json_neighbor_sub); - } - else - { - vty_out (vty, "%-15s %3d %-15s %9s ", - "-", nbr_nbma->priority, "Down", "-"); - vty_out (vty, "%-15s %-20s %5d %5d %5d\n", - inet_ntoa (nbr_nbma->addr), IF_NAME (oi), - 0, 0, 0); - } - } - } - } - - if (use_json) - { - vty_out (vty, "%s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - vty_out (vty, "\n"); +static int show_ip_ospf_neighbor_all_common(struct vty *vty, struct ospf *ospf, + u_char use_json) +{ + struct listnode *node; + struct ospf_interface *oi; + json_object *json = NULL; + json_object *json_neighbor_sub = NULL; - return CMD_SUCCESS; + if (use_json) { + json = json_object_new_object(); + json_neighbor_sub = json_object_new_object(); + } else + show_ip_ospf_neighbour_header(vty); + + if (ospf->instance) { + if (use_json) + json_object_int_add(json, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { + struct listnode *nbr_node; + struct ospf_nbr_nbma *nbr_nbma; + + show_ip_ospf_neighbor_sub(vty, oi, json, use_json); + + /* print Down neighbor status */ + for (ALL_LIST_ELEMENTS_RO(oi->nbr_nbma, nbr_node, nbr_nbma)) { + if (nbr_nbma->nbr == NULL + || nbr_nbma->nbr->state == NSM_Down) { + if (use_json) { + json_object_int_add(json_neighbor_sub, + "nbrNbmaPriority", + nbr_nbma->priority); + json_object_boolean_true_add( + json_neighbor_sub, + "nbrNbmaDown"); + json_object_string_add( + json_neighbor_sub, + "nbrNbmaIfaceName", + IF_NAME(oi)); + json_object_int_add( + json_neighbor_sub, + "nbrNbmaRetransmitCounter", 0); + json_object_int_add( + json_neighbor_sub, + "nbrNbmaRequestCounter", 0); + json_object_int_add( + json_neighbor_sub, + "nbrNbmaDbSummaryCounter", 0); + json_object_object_add( + json, inet_ntoa(nbr_nbma->addr), + json_neighbor_sub); + } else { + vty_out(vty, "%-15s %3d %-15s %9s ", + "-", nbr_nbma->priority, "Down", + "-"); + vty_out(vty, + "%-15s %-20s %5d %5d %5d\n", + inet_ntoa(nbr_nbma->addr), + IF_NAME(oi), 0, 0, 0); + } + } + } + } + + if (use_json) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else + vty_out(vty, "\n"); + + return CMD_SUCCESS; } DEFUN (show_ip_ospf_neighbor_all, @@ -3836,13 +3956,13 @@ DEFUN (show_ip_ospf_neighbor_all, "include down status neighbor\n" JSON_STR) { - struct ospf *ospf; - u_char uj = use_json(argc, argv); + struct ospf *ospf; + u_char uj = use_json(argc, argv); - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) + return CMD_SUCCESS; - return show_ip_ospf_neighbor_all_common(vty, ospf, uj); + return show_ip_ospf_neighbor_all_common(vty, ospf, uj); } DEFUN (show_ip_ospf_instance_neighbor_all, @@ -3856,68 +3976,67 @@ DEFUN (show_ip_ospf_instance_neighbor_all, "include down status neighbor\n" JSON_STR) { - int idx_number = 3; - struct ospf *ospf; - u_short instance = 0; - u_char uj = use_json(argc, argv); + int idx_number = 3; + struct ospf *ospf; + u_short instance = 0; + u_char uj = use_json(argc, argv); - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if ((ospf = ospf_lookup_instance(instance)) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if ((ospf = ospf_lookup_instance(instance)) == NULL + || !ospf->oi_running) + return CMD_SUCCESS; - return show_ip_ospf_neighbor_all_common(vty, ospf, uj); + return show_ip_ospf_neighbor_all_common(vty, ospf, uj); } -static int -show_ip_ospf_neighbor_int_common (struct vty *vty, struct ospf *ospf, int arg_base, - struct cmd_token **argv, u_char use_json) -{ - struct interface *ifp; - struct route_node *rn; - json_object *json = NULL; - - if (use_json) - json = json_object_new_object(); - else - show_ip_ospf_neighbour_header (vty); - - if (ospf->instance) - { - if (use_json) - json_object_int_add(json, "ospfInstance", ospf->instance); - else - vty_out (vty, "\nOSPF Instance: %d\n\n", ospf->instance); - } - - ifp = if_lookup_by_name (argv[arg_base]->arg, VRF_DEFAULT); - if (!ifp) - { - if (use_json) - json_object_boolean_true_add(json, "noSuchIface"); - else - vty_out (vty, "No such interface.\n"); - return CMD_WARNING; - } - - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - { - struct ospf_interface *oi = rn->info; - - if (oi == NULL) - continue; - - show_ip_ospf_neighbor_sub (vty, oi, json, use_json); - } - - if (use_json) - { - vty_out (vty, "%s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - vty_out (vty, "\n"); +static int show_ip_ospf_neighbor_int_common(struct vty *vty, struct ospf *ospf, + int arg_base, + struct cmd_token **argv, + u_char use_json) +{ + struct interface *ifp; + struct route_node *rn; + json_object *json = NULL; - return CMD_SUCCESS; + if (use_json) + json = json_object_new_object(); + else + show_ip_ospf_neighbour_header(vty); + + if (ospf->instance) { + if (use_json) + json_object_int_add(json, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + + ifp = if_lookup_by_name(argv[arg_base]->arg, VRF_DEFAULT); + if (!ifp) { + if (use_json) + json_object_boolean_true_add(json, "noSuchIface"); + else + vty_out(vty, "No such interface.\n"); + return CMD_WARNING; + } + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi = rn->info; + + if (oi == NULL) + continue; + + show_ip_ospf_neighbor_sub(vty, oi, json, use_json); + } + + if (use_json) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else + vty_out(vty, "\n"); + + return CMD_SUCCESS; } DEFUN (show_ip_ospf_neighbor_int, @@ -3930,13 +4049,13 @@ DEFUN (show_ip_ospf_neighbor_int, "Interface name\n" JSON_STR) { - struct ospf *ospf; - u_char uj = use_json(argc, argv); + struct ospf *ospf; + u_char uj = use_json(argc, argv); - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) + return CMD_SUCCESS; - return show_ip_ospf_neighbor_int_common(vty, ospf, 0, argv, uj); + return show_ip_ospf_neighbor_int_common(vty, ospf, 0, argv, uj); } DEFUN (show_ip_ospf_instance_neighbor_int, @@ -3950,340 +4069,357 @@ DEFUN (show_ip_ospf_instance_neighbor_int, "Interface name\n" JSON_STR) { - int idx_number = 3; - struct ospf *ospf; - u_short instance = 0; - u_char uj = use_json(argc, argv); + int idx_number = 3; + struct ospf *ospf; + u_short instance = 0; + u_char uj = use_json(argc, argv); - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if ((ospf = ospf_lookup_instance(instance)) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if ((ospf = ospf_lookup_instance(instance)) == NULL + || !ospf->oi_running) + return CMD_SUCCESS; - return show_ip_ospf_neighbor_int_common(vty, ospf, 1, argv, uj); -} - -static void -show_ip_ospf_nbr_nbma_detail_sub (struct vty *vty, struct ospf_interface *oi, struct ospf_nbr_nbma *nbr_nbma, - u_char use_json, json_object *json) -{ - char timebuf[OSPF_TIME_DUMP_SIZE]; - json_object *json_sub = NULL; - - if (use_json) - json_sub = json_object_new_object(); - else /* Show neighbor ID. */ - vty_out (vty, " Neighbor %s,", "-"); - - /* Show interface address. */ - if (use_json) - json_object_string_add(json_sub, "ifaceAddress", inet_ntoa (nbr_nbma->addr)); - else - vty_out (vty, " interface address %s\n", - inet_ntoa (nbr_nbma->addr)); - - /* Show Area ID. */ - if (use_json) - { - json_object_string_add(json_sub, "areaId", ospf_area_desc_string (oi->area)); - json_object_string_add(json_sub, "iface", IF_NAME (oi)); - } - else - vty_out (vty, " In the area %s via interface %s\n", - ospf_area_desc_string (oi->area), IF_NAME (oi)); - - /* Show neighbor priority and state. */ - if (use_json) - { - json_object_int_add(json_sub, "nbrPriority", nbr_nbma->priority); - json_object_string_add(json_sub, "nbrState", "down"); - } - else - vty_out (vty, " Neighbor priority is %d, State is %s,", - nbr_nbma->priority, "Down"); - - /* Show state changes. */ - if (use_json) - json_object_int_add(json_sub, "stateChangeCounter", nbr_nbma->state_change); - else - vty_out (vty, " %d state changes\n", nbr_nbma->state_change); - - /* Show PollInterval */ - if (use_json) - json_object_int_add(json_sub, "pollInterval", nbr_nbma->v_poll); - else - vty_out (vty, " Poll interval %d\n", nbr_nbma->v_poll); - - /* Show poll-interval timer. */ - if (use_json) - { - long time_store; - time_store = monotime_until(&nbr_nbma->t_poll->u.sands, NULL) / 1000LL; - json_object_int_add(json_sub, "pollIntervalTimerDueMsec", time_store); - } - else - vty_out (vty, " Poll timer due in %s\n", - ospf_timer_dump (nbr_nbma->t_poll, timebuf, sizeof(timebuf))); - - /* Show poll-interval timer thread. */ - if (use_json) - { - if (nbr_nbma->t_poll != NULL) - json_object_string_add(json_sub, "pollIntervalTimerThread", "on"); - } - else - vty_out (vty, " Thread Poll Timer %s\n", - nbr_nbma->t_poll != NULL ? "on" : "off"); - - if (use_json) - json_object_object_add(json, "noNbrId", json_sub); -} - -static void -show_ip_ospf_neighbor_detail_sub (struct vty *vty, struct ospf_interface *oi, - struct ospf_neighbor *nbr, u_char use_json, json_object *json) -{ - char timebuf[OSPF_TIME_DUMP_SIZE]; - json_object *json_sub = NULL; - - if (use_json) - json_sub = json_object_new_object(); - else - { - /* Show neighbor ID. */ - if (nbr->state == NSM_Attempt && nbr->router_id.s_addr == 0) - vty_out (vty, " Neighbor %s,", "-"); - else - vty_out (vty, " Neighbor %s,", inet_ntoa (nbr->router_id)); - } - - /* Show interface address. */ - if (use_json) - json_object_string_add(json_sub, "ifaceAddress", inet_ntoa (nbr->address.u.prefix4)); - else - vty_out (vty, " interface address %s\n", - inet_ntoa (nbr->address.u.prefix4)); - - /* Show Area ID. */ - if (use_json) - { - json_object_string_add(json_sub, "areaId", ospf_area_desc_string (oi->area)); - json_object_string_add(json_sub, "ifaceName", oi->ifp->name); - } - else - vty_out (vty, " In the area %s via interface %s\n", - ospf_area_desc_string (oi->area), oi->ifp->name); - - /* Show neighbor priority and state. */ - if (use_json) - { - json_object_int_add(json_sub, "nbrPriority", nbr->priority); - json_object_string_add(json_sub, "nbrState", lookup_msg(ospf_nsm_state_msg, nbr->state, NULL)); - } - else - vty_out (vty, " Neighbor priority is %d, State is %s,", - nbr->priority, lookup_msg(ospf_nsm_state_msg, nbr->state, NULL)); - - /* Show state changes. */ - if (use_json) - json_object_int_add(json_sub, "stateChangeCounter", nbr->state_change); - else - vty_out (vty, " %d state changes\n", nbr->state_change); - - if (nbr->ts_last_progress.tv_sec || nbr->ts_last_progress.tv_usec) - { - struct timeval res; - long time_store; - - time_store = monotime_since(&nbr->ts_last_progress, &res) / 1000LL; - if (use_json) - { - json_object_int_add(json_sub, "lastPrgrsvChangeMsec", time_store); - } - else - { - vty_out (vty, " Most recent state change statistics:\n"); - vty_out (vty, " Progressive change %s ago\n", - ospf_timeval_dump (&res, timebuf, sizeof(timebuf))); - } - } - - if (nbr->ts_last_regress.tv_sec || nbr->ts_last_regress.tv_usec) - { - struct timeval res; - long time_store; - - time_store = monotime_since(&nbr->ts_last_regress, &res) / 1000LL; - if (use_json) - { - json_object_int_add(json_sub, "lastRegressiveChangeMsec", time_store); - if (nbr->last_regress_str) - json_object_string_add(json_sub, "lastRegressiveChangeReason", nbr->last_regress_str); - } - else - { - vty_out (vty, " Regressive change %s ago, due to %s\n", - ospf_timeval_dump (&res, timebuf, sizeof(timebuf)), - (nbr->last_regress_str ? nbr->last_regress_str : "??")); - } - } - - /* Show Designated Rotuer ID. */ - if (use_json) - json_object_string_add(json_sub, "routerDesignatedId", inet_ntoa (nbr->d_router)); - else - vty_out (vty, " DR is %s,", inet_ntoa (nbr->d_router)); - - /* Show Backup Designated Rotuer ID. */ - if (use_json) - json_object_string_add(json_sub, "routerDesignatedBackupId", inet_ntoa (nbr->bd_router)); - else - vty_out (vty, " BDR is %s\n", inet_ntoa (nbr->bd_router)); - - /* Show options. */ - if (use_json) - { - json_object_int_add(json_sub, "optionsCounter", nbr->options); - json_object_string_add(json_sub, "optionsList", ospf_options_dump (nbr->options)); - } - else - vty_out (vty, " Options %d %s\n", nbr->options, - ospf_options_dump (nbr->options)); - - /* Show Router Dead interval timer. */ - if (use_json) - { - if (nbr->t_inactivity) - { - long time_store; - time_store = monotime_until(&nbr->t_inactivity->u.sands, NULL) / 1000LL; - json_object_int_add(json_sub, "routerDeadIntervalTimerDueMsec", time_store); - } - else - json_object_int_add(json_sub, "routerDeadIntervalTimerDueMsec", -1); - } - else - vty_out (vty, " Dead timer due in %s\n", - ospf_timer_dump (nbr->t_inactivity, timebuf, sizeof (timebuf))); - - /* Show Database Summary list. */ - if (use_json) - json_object_int_add(json_sub, "databaseSummaryListCounter", ospf_db_summary_count (nbr)); - else - vty_out (vty, " Database Summary List %d\n", - ospf_db_summary_count (nbr)); - - /* Show Link State Request list. */ - if (use_json) - json_object_int_add(json_sub, "linkStateRequestListCounter", ospf_ls_request_count (nbr)); - else - vty_out (vty, " Link State Request List %ld\n", - ospf_ls_request_count (nbr)); - - /* Show Link State Retransmission list. */ - if (use_json) - json_object_int_add(json_sub, "linkStateRetransmissionListCounter", ospf_ls_retransmit_count (nbr)); - else - vty_out (vty, " Link State Retransmission List %ld\n", - ospf_ls_retransmit_count (nbr)); - - /* Show inactivity timer thread. */ - if (use_json) - { - if (nbr->t_inactivity != NULL) - json_object_string_add(json_sub, "threadInactivityTimer", "on"); - } - else - vty_out (vty, " Thread Inactivity Timer %s\n", - nbr->t_inactivity != NULL ? "on" : "off"); - - /* Show Database Description retransmission thread. */ - if (use_json) - { - if (nbr->t_db_desc != NULL) - json_object_string_add(json_sub, "threadDatabaseDescriptionRetransmission", "on"); - } - else - vty_out (vty, " Thread Database Description Retransmision %s\n", - nbr->t_db_desc != NULL ? "on" : "off"); - - /* Show Link State Request Retransmission thread. */ - if (use_json) - { - if (nbr->t_ls_req != NULL) - json_object_string_add(json_sub, "threadLinkStateRequestRetransmission", "on"); - } - else - vty_out (vty, " Thread Link State Request Retransmission %s\n", - nbr->t_ls_req != NULL ? "on" : "off"); - - /* Show Link State Update Retransmission thread. */ - if (use_json) - { - if (nbr->t_ls_upd != NULL) - json_object_string_add(json_sub, "threadLinkStateUpdateRetransmission", "on"); - } - else - vty_out (vty, " Thread Link State Update Retransmission %s\n\n", - nbr->t_ls_upd != NULL ? "on" : "off"); - - if (use_json) - { - if (nbr->state == NSM_Attempt && nbr->router_id.s_addr == 0) - json_object_object_add(json, "noNbrId", json_sub); - else - json_object_object_add(json, inet_ntoa (nbr->router_id), json_sub); - } - - ospf_bfd_show_info(vty, nbr->bfd_info, json, use_json, 0); + return show_ip_ospf_neighbor_int_common(vty, ospf, 1, argv, uj); } -static int -show_ip_ospf_neighbor_id_common (struct vty *vty, struct ospf *ospf, - int arg_base, struct cmd_token **argv, u_char use_json) -{ - struct listnode *node; - struct ospf_neighbor *nbr; - struct ospf_interface *oi; - struct in_addr router_id; - int ret; - json_object *json = NULL; - - if (use_json) - json = json_object_new_object(); - - if (ospf->instance) - { - if (use_json) - json_object_int_add(json, "ospfInstance", ospf->instance); - else - vty_out (vty, "\nOSPF Instance: %d\n\n", ospf->instance); - } - - ret = inet_aton (argv[arg_base]->arg, &router_id); - if (!ret) - { - if (!use_json) - vty_out (vty, "Please specify Neighbor ID by A.B.C.D\n"); - return CMD_WARNING; - } - - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) - { - if ((nbr = ospf_nbr_lookup_by_routerid (oi->nbrs, &router_id))) - { - show_ip_ospf_neighbor_detail_sub (vty, oi, nbr, use_json, json); - } - } - - if (use_json) - { - vty_out (vty, "%s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - vty_out (vty, "\n"); +static void show_ip_ospf_nbr_nbma_detail_sub(struct vty *vty, + struct ospf_interface *oi, + struct ospf_nbr_nbma *nbr_nbma, + u_char use_json, json_object *json) +{ + char timebuf[OSPF_TIME_DUMP_SIZE]; + json_object *json_sub = NULL; - return CMD_SUCCESS; + if (use_json) + json_sub = json_object_new_object(); + else /* Show neighbor ID. */ + vty_out(vty, " Neighbor %s,", "-"); + + /* Show interface address. */ + if (use_json) + json_object_string_add(json_sub, "ifaceAddress", + inet_ntoa(nbr_nbma->addr)); + else + vty_out(vty, " interface address %s\n", + inet_ntoa(nbr_nbma->addr)); + + /* Show Area ID. */ + if (use_json) { + json_object_string_add(json_sub, "areaId", + ospf_area_desc_string(oi->area)); + json_object_string_add(json_sub, "iface", IF_NAME(oi)); + } else + vty_out(vty, " In the area %s via interface %s\n", + ospf_area_desc_string(oi->area), IF_NAME(oi)); + + /* Show neighbor priority and state. */ + if (use_json) { + json_object_int_add(json_sub, "nbrPriority", + nbr_nbma->priority); + json_object_string_add(json_sub, "nbrState", "down"); + } else + vty_out(vty, " Neighbor priority is %d, State is %s,", + nbr_nbma->priority, "Down"); + + /* Show state changes. */ + if (use_json) + json_object_int_add(json_sub, "stateChangeCounter", + nbr_nbma->state_change); + else + vty_out(vty, " %d state changes\n", nbr_nbma->state_change); + + /* Show PollInterval */ + if (use_json) + json_object_int_add(json_sub, "pollInterval", nbr_nbma->v_poll); + else + vty_out(vty, " Poll interval %d\n", nbr_nbma->v_poll); + + /* Show poll-interval timer. */ + if (use_json) { + long time_store; + time_store = monotime_until(&nbr_nbma->t_poll->u.sands, NULL) + / 1000LL; + json_object_int_add(json_sub, "pollIntervalTimerDueMsec", + time_store); + } else + vty_out(vty, " Poll timer due in %s\n", + ospf_timer_dump(nbr_nbma->t_poll, timebuf, + sizeof(timebuf))); + + /* Show poll-interval timer thread. */ + if (use_json) { + if (nbr_nbma->t_poll != NULL) + json_object_string_add(json_sub, + "pollIntervalTimerThread", "on"); + } else + vty_out(vty, " Thread Poll Timer %s\n", + nbr_nbma->t_poll != NULL ? "on" : "off"); + + if (use_json) + json_object_object_add(json, "noNbrId", json_sub); +} + +static void show_ip_ospf_neighbor_detail_sub(struct vty *vty, + struct ospf_interface *oi, + struct ospf_neighbor *nbr, + u_char use_json, json_object *json) +{ + char timebuf[OSPF_TIME_DUMP_SIZE]; + json_object *json_sub = NULL; + + if (use_json) + json_sub = json_object_new_object(); + else { + /* Show neighbor ID. */ + if (nbr->state == NSM_Attempt && nbr->router_id.s_addr == 0) + vty_out(vty, " Neighbor %s,", "-"); + else + vty_out(vty, " Neighbor %s,", + inet_ntoa(nbr->router_id)); + } + + /* Show interface address. */ + if (use_json) + json_object_string_add(json_sub, "ifaceAddress", + inet_ntoa(nbr->address.u.prefix4)); + else + vty_out(vty, " interface address %s\n", + inet_ntoa(nbr->address.u.prefix4)); + + /* Show Area ID. */ + if (use_json) { + json_object_string_add(json_sub, "areaId", + ospf_area_desc_string(oi->area)); + json_object_string_add(json_sub, "ifaceName", oi->ifp->name); + } else + vty_out(vty, " In the area %s via interface %s\n", + ospf_area_desc_string(oi->area), oi->ifp->name); + + /* Show neighbor priority and state. */ + if (use_json) { + json_object_int_add(json_sub, "nbrPriority", nbr->priority); + json_object_string_add( + json_sub, "nbrState", + lookup_msg(ospf_nsm_state_msg, nbr->state, NULL)); + } else + vty_out(vty, " Neighbor priority is %d, State is %s,", + nbr->priority, + lookup_msg(ospf_nsm_state_msg, nbr->state, NULL)); + + /* Show state changes. */ + if (use_json) + json_object_int_add(json_sub, "stateChangeCounter", + nbr->state_change); + else + vty_out(vty, " %d state changes\n", nbr->state_change); + + if (nbr->ts_last_progress.tv_sec || nbr->ts_last_progress.tv_usec) { + struct timeval res; + long time_store; + + time_store = + monotime_since(&nbr->ts_last_progress, &res) / 1000LL; + if (use_json) { + json_object_int_add(json_sub, "lastPrgrsvChangeMsec", + time_store); + } else { + vty_out(vty, + " Most recent state change statistics:\n"); + vty_out(vty, " Progressive change %s ago\n", + ospf_timeval_dump(&res, timebuf, + sizeof(timebuf))); + } + } + + if (nbr->ts_last_regress.tv_sec || nbr->ts_last_regress.tv_usec) { + struct timeval res; + long time_store; + + time_store = + monotime_since(&nbr->ts_last_regress, &res) / 1000LL; + if (use_json) { + json_object_int_add(json_sub, + "lastRegressiveChangeMsec", + time_store); + if (nbr->last_regress_str) + json_object_string_add( + json_sub, "lastRegressiveChangeReason", + nbr->last_regress_str); + } else { + vty_out(vty, + " Regressive change %s ago, due to %s\n", + ospf_timeval_dump(&res, timebuf, + sizeof(timebuf)), + (nbr->last_regress_str ? nbr->last_regress_str + : "??")); + } + } + + /* Show Designated Rotuer ID. */ + if (use_json) + json_object_string_add(json_sub, "routerDesignatedId", + inet_ntoa(nbr->d_router)); + else + vty_out(vty, " DR is %s,", inet_ntoa(nbr->d_router)); + + /* Show Backup Designated Rotuer ID. */ + if (use_json) + json_object_string_add(json_sub, "routerDesignatedBackupId", + inet_ntoa(nbr->bd_router)); + else + vty_out(vty, " BDR is %s\n", inet_ntoa(nbr->bd_router)); + + /* Show options. */ + if (use_json) { + json_object_int_add(json_sub, "optionsCounter", nbr->options); + json_object_string_add(json_sub, "optionsList", + ospf_options_dump(nbr->options)); + } else + vty_out(vty, " Options %d %s\n", nbr->options, + ospf_options_dump(nbr->options)); + + /* Show Router Dead interval timer. */ + if (use_json) { + if (nbr->t_inactivity) { + long time_store; + time_store = monotime_until(&nbr->t_inactivity->u.sands, + NULL) + / 1000LL; + json_object_int_add(json_sub, + "routerDeadIntervalTimerDueMsec", + time_store); + } else + json_object_int_add( + json_sub, "routerDeadIntervalTimerDueMsec", -1); + } else + vty_out(vty, " Dead timer due in %s\n", + ospf_timer_dump(nbr->t_inactivity, timebuf, + sizeof(timebuf))); + + /* Show Database Summary list. */ + if (use_json) + json_object_int_add(json_sub, "databaseSummaryListCounter", + ospf_db_summary_count(nbr)); + else + vty_out(vty, " Database Summary List %d\n", + ospf_db_summary_count(nbr)); + + /* Show Link State Request list. */ + if (use_json) + json_object_int_add(json_sub, "linkStateRequestListCounter", + ospf_ls_request_count(nbr)); + else + vty_out(vty, " Link State Request List %ld\n", + ospf_ls_request_count(nbr)); + + /* Show Link State Retransmission list. */ + if (use_json) + json_object_int_add(json_sub, + "linkStateRetransmissionListCounter", + ospf_ls_retransmit_count(nbr)); + else + vty_out(vty, " Link State Retransmission List %ld\n", + ospf_ls_retransmit_count(nbr)); + + /* Show inactivity timer thread. */ + if (use_json) { + if (nbr->t_inactivity != NULL) + json_object_string_add(json_sub, + "threadInactivityTimer", "on"); + } else + vty_out(vty, " Thread Inactivity Timer %s\n", + nbr->t_inactivity != NULL ? "on" : "off"); + + /* Show Database Description retransmission thread. */ + if (use_json) { + if (nbr->t_db_desc != NULL) + json_object_string_add( + json_sub, + "threadDatabaseDescriptionRetransmission", + "on"); + } else + vty_out(vty, + " Thread Database Description Retransmision %s\n", + nbr->t_db_desc != NULL ? "on" : "off"); + + /* Show Link State Request Retransmission thread. */ + if (use_json) { + if (nbr->t_ls_req != NULL) + json_object_string_add( + json_sub, + "threadLinkStateRequestRetransmission", "on"); + } else + vty_out(vty, + " Thread Link State Request Retransmission %s\n", + nbr->t_ls_req != NULL ? "on" : "off"); + + /* Show Link State Update Retransmission thread. */ + if (use_json) { + if (nbr->t_ls_upd != NULL) + json_object_string_add( + json_sub, "threadLinkStateUpdateRetransmission", + "on"); + } else + vty_out(vty, + " Thread Link State Update Retransmission %s\n\n", + nbr->t_ls_upd != NULL ? "on" : "off"); + + if (use_json) { + if (nbr->state == NSM_Attempt && nbr->router_id.s_addr == 0) + json_object_object_add(json, "noNbrId", json_sub); + else + json_object_object_add(json, inet_ntoa(nbr->router_id), + json_sub); + } + + ospf_bfd_show_info(vty, nbr->bfd_info, json, use_json, 0); +} + +static int show_ip_ospf_neighbor_id_common(struct vty *vty, struct ospf *ospf, + int arg_base, + struct cmd_token **argv, + u_char use_json) +{ + struct listnode *node; + struct ospf_neighbor *nbr; + struct ospf_interface *oi; + struct in_addr router_id; + int ret; + json_object *json = NULL; + + if (use_json) + json = json_object_new_object(); + + if (ospf->instance) { + if (use_json) + json_object_int_add(json, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + + ret = inet_aton(argv[arg_base]->arg, &router_id); + if (!ret) { + if (!use_json) + vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n"); + return CMD_WARNING; + } + + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { + if ((nbr = ospf_nbr_lookup_by_routerid(oi->nbrs, &router_id))) { + show_ip_ospf_neighbor_detail_sub(vty, oi, nbr, use_json, + json); + } + } + + if (use_json) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else + vty_out(vty, "\n"); + + return CMD_SUCCESS; } DEFUN (show_ip_ospf_neighbor_id, @@ -4296,13 +4432,13 @@ DEFUN (show_ip_ospf_neighbor_id, "Neighbor ID\n" JSON_STR) { - struct ospf *ospf; - u_char uj = use_json(argc, argv); + struct ospf *ospf; + u_char uj = use_json(argc, argv); - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) + return CMD_SUCCESS; - return show_ip_ospf_neighbor_id_common(vty, ospf, 0, argv, uj); + return show_ip_ospf_neighbor_id_common(vty, ospf, 0, argv, uj); } DEFUN (show_ip_ospf_instance_neighbor_id, @@ -4316,65 +4452,63 @@ DEFUN (show_ip_ospf_instance_neighbor_id, "Neighbor ID\n" JSON_STR) { - int idx_number = 3; - struct ospf *ospf; - u_short instance = 0; - u_char uj = use_json(argc, argv); + int idx_number = 3; + struct ospf *ospf; + u_short instance = 0; + u_char uj = use_json(argc, argv); - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if ((ospf = ospf_lookup_instance(instance)) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if ((ospf = ospf_lookup_instance(instance)) == NULL + || !ospf->oi_running) + return CMD_SUCCESS; - return show_ip_ospf_neighbor_id_common(vty, ospf, 1, argv, uj); + return show_ip_ospf_neighbor_id_common(vty, ospf, 1, argv, uj); } -static int -show_ip_ospf_neighbor_detail_common (struct vty *vty, struct ospf *ospf, u_char use_json) -{ - struct ospf_interface *oi; - struct listnode *node; - json_object *json = NULL; - - if (use_json) - json = json_object_new_object(); - - if (ospf->instance) - { - if (use_json) - json_object_int_add(json, "ospfInstance", ospf->instance); - else - vty_out (vty, "\nOSPF Instance: %d\n\n", ospf->instance); - } - - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) - { - struct route_node *rn; - struct ospf_neighbor *nbr; - - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - { - if ((nbr = rn->info)) - { - if (nbr != oi->nbr_self) - { - if (nbr->state != NSM_Down) - { - show_ip_ospf_neighbor_detail_sub (vty, oi, nbr, use_json, json); - } - } - } - } - } - - if (use_json) - { - vty_out (vty, "%s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - vty_out (vty, "\n"); +static int show_ip_ospf_neighbor_detail_common(struct vty *vty, + struct ospf *ospf, + u_char use_json) +{ + struct ospf_interface *oi; + struct listnode *node; + json_object *json = NULL; - return CMD_SUCCESS; + if (use_json) + json = json_object_new_object(); + + if (ospf->instance) { + if (use_json) + json_object_int_add(json, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { + struct route_node *rn; + struct ospf_neighbor *nbr; + + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) { + if ((nbr = rn->info)) { + if (nbr != oi->nbr_self) { + if (nbr->state != NSM_Down) { + show_ip_ospf_neighbor_detail_sub( + vty, oi, nbr, use_json, + json); + } + } + } + } + } + + if (use_json) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else + vty_out(vty, "\n"); + + return CMD_SUCCESS; } DEFUN (show_ip_ospf_neighbor_detail, @@ -4387,13 +4521,13 @@ DEFUN (show_ip_ospf_neighbor_detail, "detail of all neighbors\n" JSON_STR) { - struct ospf *ospf; - u_char uj = use_json(argc, argv); + struct ospf *ospf; + u_char uj = use_json(argc, argv); - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) + return CMD_SUCCESS; - return show_ip_ospf_neighbor_detail_common(vty, ospf, uj); + return show_ip_ospf_neighbor_detail_common(vty, ospf, uj); } DEFUN (show_ip_ospf_instance_neighbor_detail, @@ -4407,71 +4541,73 @@ DEFUN (show_ip_ospf_instance_neighbor_detail, "detail of all neighbors\n" JSON_STR) { - int idx_number = 3; - struct ospf *ospf; - u_short instance = 0; - u_char uj = use_json(argc, argv); + int idx_number = 3; + struct ospf *ospf; + u_short instance = 0; + u_char uj = use_json(argc, argv); - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if ((ospf = ospf_lookup_instance (instance)) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if ((ospf = ospf_lookup_instance(instance)) == NULL + || !ospf->oi_running) + return CMD_SUCCESS; - return show_ip_ospf_neighbor_detail_common(vty, ospf, uj); + return show_ip_ospf_neighbor_detail_common(vty, ospf, uj); } -static int -show_ip_ospf_neighbor_detail_all_common (struct vty *vty, struct ospf *ospf, u_char use_json) -{ - struct listnode *node; - struct ospf_interface *oi; - json_object *json = NULL; - - if (use_json) - json = json_object_new_object(); - - if (ospf->instance) - { - if (use_json) - json_object_int_add(json, "ospfInstance", ospf->instance); - else - vty_out (vty, "\nOSPF Instance: %d\n\n", ospf->instance); - } - - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) - { - struct route_node *rn; - struct ospf_neighbor *nbr; - struct ospf_nbr_nbma *nbr_nbma; - - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - if (nbr != oi->nbr_self) - if (nbr->state != NSM_Down) - show_ip_ospf_neighbor_detail_sub (vty, oi, rn->info, use_json, json); - - if (oi->type == OSPF_IFTYPE_NBMA) - { - struct listnode *nd; - - for (ALL_LIST_ELEMENTS_RO (oi->nbr_nbma, nd, nbr_nbma)) - { - if (nbr_nbma->nbr == NULL || nbr_nbma->nbr->state == NSM_Down) - show_ip_ospf_nbr_nbma_detail_sub (vty, oi, nbr_nbma, use_json, json); - } - } - } - - if (use_json) - { - vty_out (vty, "%s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - { - vty_out (vty, "\n"); - } +static int show_ip_ospf_neighbor_detail_all_common(struct vty *vty, + struct ospf *ospf, + u_char use_json) +{ + struct listnode *node; + struct ospf_interface *oi; + json_object *json = NULL; - return CMD_SUCCESS; + if (use_json) + json = json_object_new_object(); + + if (ospf->instance) { + if (use_json) + json_object_int_add(json, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { + struct route_node *rn; + struct ospf_neighbor *nbr; + struct ospf_nbr_nbma *nbr_nbma; + + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info)) + if (nbr != oi->nbr_self) + if (nbr->state != NSM_Down) + show_ip_ospf_neighbor_detail_sub( + vty, oi, rn->info, + use_json, json); + + if (oi->type == OSPF_IFTYPE_NBMA) { + struct listnode *nd; + + for (ALL_LIST_ELEMENTS_RO(oi->nbr_nbma, nd, nbr_nbma)) { + if (nbr_nbma->nbr == NULL + || nbr_nbma->nbr->state == NSM_Down) + show_ip_ospf_nbr_nbma_detail_sub( + vty, oi, nbr_nbma, use_json, + json); + } + } + } + + if (use_json) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else { + vty_out(vty, "\n"); + } + + return CMD_SUCCESS; } DEFUN (show_ip_ospf_neighbor_detail_all, @@ -4485,13 +4621,13 @@ DEFUN (show_ip_ospf_neighbor_detail_all, "include down status neighbor\n" JSON_STR) { - struct ospf *ospf; - u_char uj = use_json(argc, argv); + struct ospf *ospf; + u_char uj = use_json(argc, argv); - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) + return CMD_SUCCESS; - return show_ip_ospf_neighbor_detail_all_common(vty, ospf, uj); + return show_ip_ospf_neighbor_detail_all_common(vty, ospf, uj); } DEFUN (show_ip_ospf_instance_neighbor_detail_all, @@ -4506,74 +4642,73 @@ DEFUN (show_ip_ospf_instance_neighbor_detail_all, "include down status neighbor\n" JSON_STR) { - int idx_number = 3; - struct ospf *ospf; - u_short instance = 0; - u_char uj = use_json(argc, argv); + int idx_number = 3; + struct ospf *ospf; + u_short instance = 0; + u_char uj = use_json(argc, argv); - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if ((ospf = ospf_lookup_instance(instance)) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if ((ospf = ospf_lookup_instance(instance)) == NULL + || !ospf->oi_running) + return CMD_SUCCESS; - return show_ip_ospf_neighbor_detail_all_common(vty, ospf, uj); + return show_ip_ospf_neighbor_detail_all_common(vty, ospf, uj); } -static int -show_ip_ospf_neighbor_int_detail_common (struct vty *vty, struct ospf *ospf, - int arg_base, struct cmd_token **argv, u_char use_json) -{ - struct ospf_interface *oi; - struct interface *ifp; - struct route_node *rn, *nrn; - struct ospf_neighbor *nbr; - json_object *json = NULL; - - if (use_json) - json = json_object_new_object(); - - if (ospf->instance) - { - if (use_json) - json_object_int_add(json, "ospfInstance", ospf->instance); - else - vty_out (vty, "\nOSPF Instance: %d\n\n", ospf->instance); - } - - ifp = if_lookup_by_name (argv[arg_base]->arg, VRF_DEFAULT); - if (!ifp) - { - if (!use_json) - vty_out (vty, "No such interface.\n"); - return CMD_WARNING; - } - - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - { - if ((oi = rn->info)) - { - for (nrn = route_top (oi->nbrs); nrn; nrn = route_next (nrn)) - { - if ((nbr = nrn->info)) - { - if (nbr != oi->nbr_self) - { - if (nbr->state != NSM_Down) - show_ip_ospf_neighbor_detail_sub (vty, oi, nbr, use_json, json); - } - } - } - } - } - - if (use_json) - { - vty_out (vty, "%s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - vty_out (vty, "\n"); +static int show_ip_ospf_neighbor_int_detail_common(struct vty *vty, + struct ospf *ospf, + int arg_base, + struct cmd_token **argv, + u_char use_json) +{ + struct ospf_interface *oi; + struct interface *ifp; + struct route_node *rn, *nrn; + struct ospf_neighbor *nbr; + json_object *json = NULL; - return CMD_SUCCESS; + if (use_json) + json = json_object_new_object(); + + if (ospf->instance) { + if (use_json) + json_object_int_add(json, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + + ifp = if_lookup_by_name(argv[arg_base]->arg, VRF_DEFAULT); + if (!ifp) { + if (!use_json) + vty_out(vty, "No such interface.\n"); + return CMD_WARNING; + } + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + if ((oi = rn->info)) { + for (nrn = route_top(oi->nbrs); nrn; + nrn = route_next(nrn)) { + if ((nbr = nrn->info)) { + if (nbr != oi->nbr_self) { + if (nbr->state != NSM_Down) + show_ip_ospf_neighbor_detail_sub( + vty, oi, nbr, + use_json, json); + } + } + } + } + } + + if (use_json) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else + vty_out(vty, "\n"); + + return CMD_SUCCESS; } DEFUN (show_ip_ospf_neighbor_int_detail, @@ -4587,13 +4722,13 @@ DEFUN (show_ip_ospf_neighbor_int_detail, "detail of all neighbors\n" JSON_STR) { - struct ospf *ospf; - u_char uj = use_json(argc, argv); + struct ospf *ospf; + u_char uj = use_json(argc, argv); - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) + return CMD_SUCCESS; - return show_ip_ospf_neighbor_int_detail_common(vty, ospf, 0, argv, uj); + return show_ip_ospf_neighbor_int_detail_common(vty, ospf, 0, argv, uj); } DEFUN (show_ip_ospf_instance_neighbor_int_detail, @@ -4608,311 +4743,293 @@ DEFUN (show_ip_ospf_instance_neighbor_int_detail, "detail of all neighbors\n" JSON_STR) { - int idx_number = 3; - struct ospf *ospf; - u_short instance = 0; - u_char uj = use_json(argc, argv); + int idx_number = 3; + struct ospf *ospf; + u_short instance = 0; + u_char uj = use_json(argc, argv); - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if ((ospf = ospf_lookup_instance(instance)) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if ((ospf = ospf_lookup_instance(instance)) == NULL + || !ospf->oi_running) + return CMD_SUCCESS; - return show_ip_ospf_neighbor_int_detail_common(vty, ospf, 1, argv, uj); + return show_ip_ospf_neighbor_int_detail_common(vty, ospf, 1, argv, uj); } /* Show functions */ -static int -show_lsa_summary (struct vty *vty, struct ospf_lsa *lsa, int self) -{ - struct router_lsa *rl; - struct summary_lsa *sl; - struct as_external_lsa *asel; - struct prefix_ipv4 p; - - if (lsa != NULL) - /* If self option is set, check LSA self flag. */ - if (self == 0 || IS_LSA_SELF (lsa)) - { - /* LSA common part show. */ - vty_out (vty, "%-15s ", inet_ntoa (lsa->data->id)); - vty_out (vty, "%-15s %4d 0x%08lx 0x%04x", - inet_ntoa (lsa->data->adv_router), LS_AGE (lsa), - (u_long)ntohl (lsa->data->ls_seqnum), ntohs (lsa->data->checksum)); - /* LSA specific part show. */ - switch (lsa->data->type) - { - case OSPF_ROUTER_LSA: - rl = (struct router_lsa *) lsa->data; - vty_out (vty, " %-d", ntohs (rl->links)); - break; - case OSPF_SUMMARY_LSA: - sl = (struct summary_lsa *) lsa->data; - - p.family = AF_INET; - p.prefix = sl->header.id; - p.prefixlen = ip_masklen (sl->mask); - apply_mask_ipv4 (&p); - - vty_out (vty, " %s/%d", inet_ntoa (p.prefix), p.prefixlen); - break; - case OSPF_AS_EXTERNAL_LSA: - case OSPF_AS_NSSA_LSA: - asel = (struct as_external_lsa *) lsa->data; - - p.family = AF_INET; - p.prefix = asel->header.id; - p.prefixlen = ip_masklen (asel->mask); - apply_mask_ipv4 (&p); - - vty_out (vty, " %s %s/%d [0x%lx]", - IS_EXTERNAL_METRIC (asel->e[0].tos) ? "E2" : "E1", - inet_ntoa (p.prefix), p.prefixlen, - (u_long)ntohl (asel->e[0].route_tag)); - break; - case OSPF_NETWORK_LSA: - case OSPF_ASBR_SUMMARY_LSA: - case OSPF_OPAQUE_LINK_LSA: - case OSPF_OPAQUE_AREA_LSA: - case OSPF_OPAQUE_AS_LSA: - default: - break; - } - vty_out (vty, "\n"); - } - - return 0; -} +static int show_lsa_summary(struct vty *vty, struct ospf_lsa *lsa, int self) +{ + struct router_lsa *rl; + struct summary_lsa *sl; + struct as_external_lsa *asel; + struct prefix_ipv4 p; + + if (lsa != NULL) + /* If self option is set, check LSA self flag. */ + if (self == 0 || IS_LSA_SELF(lsa)) { + /* LSA common part show. */ + vty_out(vty, "%-15s ", inet_ntoa(lsa->data->id)); + vty_out(vty, "%-15s %4d 0x%08lx 0x%04x", + inet_ntoa(lsa->data->adv_router), LS_AGE(lsa), + (u_long)ntohl(lsa->data->ls_seqnum), + ntohs(lsa->data->checksum)); + /* LSA specific part show. */ + switch (lsa->data->type) { + case OSPF_ROUTER_LSA: + rl = (struct router_lsa *)lsa->data; + vty_out(vty, " %-d", ntohs(rl->links)); + break; + case OSPF_SUMMARY_LSA: + sl = (struct summary_lsa *)lsa->data; + + p.family = AF_INET; + p.prefix = sl->header.id; + p.prefixlen = ip_masklen(sl->mask); + apply_mask_ipv4(&p); + + vty_out(vty, " %s/%d", inet_ntoa(p.prefix), + p.prefixlen); + break; + case OSPF_AS_EXTERNAL_LSA: + case OSPF_AS_NSSA_LSA: + asel = (struct as_external_lsa *)lsa->data; + + p.family = AF_INET; + p.prefix = asel->header.id; + p.prefixlen = ip_masklen(asel->mask); + apply_mask_ipv4(&p); + + vty_out(vty, " %s %s/%d [0x%lx]", + IS_EXTERNAL_METRIC(asel->e[0].tos) + ? "E2" + : "E1", + inet_ntoa(p.prefix), p.prefixlen, + (u_long)ntohl(asel->e[0].route_tag)); + break; + case OSPF_NETWORK_LSA: + case OSPF_ASBR_SUMMARY_LSA: + case OSPF_OPAQUE_LINK_LSA: + case OSPF_OPAQUE_AREA_LSA: + case OSPF_OPAQUE_AS_LSA: + default: + break; + } + vty_out(vty, "\n"); + } -static const char *show_database_desc[] = -{ - "unknown", - "Router Link States", - "Net Link States", - "Summary Link States", - "ASBR-Summary Link States", - "AS External Link States", - "Group Membership LSA", - "NSSA-external Link States", - "Type-8 LSA", - "Link-Local Opaque-LSA", - "Area-Local Opaque-LSA", - "AS-external Opaque-LSA", + return 0; +} + +static const char *show_database_desc[] = { + "unknown", + "Router Link States", + "Net Link States", + "Summary Link States", + "ASBR-Summary Link States", + "AS External Link States", + "Group Membership LSA", + "NSSA-external Link States", + "Type-8 LSA", + "Link-Local Opaque-LSA", + "Area-Local Opaque-LSA", + "AS-external Opaque-LSA", }; -static const char *show_database_header[] = -{ - "", - "Link ID ADV Router Age Seq# CkSum Link count", - "Link ID ADV Router Age Seq# CkSum", - "Link ID ADV Router Age Seq# CkSum Route", - "Link ID ADV Router Age Seq# CkSum", - "Link ID ADV Router Age Seq# CkSum Route", - " --- header for Group Member ----", - "Link ID ADV Router Age Seq# CkSum Route", - " --- type-8 ---", - "Opaque-Type/Id ADV Router Age Seq# CkSum", - "Opaque-Type/Id ADV Router Age Seq# CkSum", - "Opaque-Type/Id ADV Router Age Seq# CkSum", +static const char *show_database_header[] = { + "", + "Link ID ADV Router Age Seq# CkSum Link count", + "Link ID ADV Router Age Seq# CkSum", + "Link ID ADV Router Age Seq# CkSum Route", + "Link ID ADV Router Age Seq# CkSum", + "Link ID ADV Router Age Seq# CkSum Route", + " --- header for Group Member ----", + "Link ID ADV Router Age Seq# CkSum Route", + " --- type-8 ---", + "Opaque-Type/Id ADV Router Age Seq# CkSum", + "Opaque-Type/Id ADV Router Age Seq# CkSum", + "Opaque-Type/Id ADV Router Age Seq# CkSum", }; -static void -show_ip_ospf_database_header (struct vty *vty, struct ospf_lsa *lsa) -{ - struct router_lsa *rlsa = (struct router_lsa*) lsa->data; - - vty_out (vty, " LS age: %d\n", LS_AGE (lsa)); - vty_out (vty, " Options: 0x%-2x : %s\n", lsa->data->options, - ospf_options_dump(lsa->data->options)); - vty_out (vty, " LS Flags: 0x%-2x %s\n", - lsa->flags, - ((lsa->flags & OSPF_LSA_LOCAL_XLT) ? - "(Translated from Type-7)" : "")); - - if (lsa->data->type == OSPF_ROUTER_LSA) - { - vty_out (vty, " Flags: 0x%x" , rlsa->flags); - - if (rlsa->flags) - vty_out (vty, " :%s%s%s%s", - IS_ROUTER_LSA_BORDER (rlsa) ? " ABR" : "", - IS_ROUTER_LSA_EXTERNAL (rlsa) ? " ASBR" : "", - IS_ROUTER_LSA_VIRTUAL (rlsa) ? " VL-endpoint" : "", - IS_ROUTER_LSA_SHORTCUT (rlsa) ? " Shortcut" : ""); - - vty_out (vty, "\n"); - } - vty_out (vty, " LS Type: %s\n", - lookup_msg(ospf_lsa_type_msg, lsa->data->type, NULL)); - vty_out (vty, " Link State ID: %s %s\n", inet_ntoa (lsa->data->id), - lookup_msg(ospf_link_state_id_type_msg, lsa->data->type, NULL)); - vty_out (vty, " Advertising Router: %s\n", inet_ntoa (lsa->data->adv_router)); - vty_out (vty, " LS Seq Number: %08lx\n", (u_long)ntohl (lsa->data->ls_seqnum)); - vty_out (vty, " Checksum: 0x%04x\n", ntohs (lsa->data->checksum)); - vty_out (vty, " Length: %d\n\n", ntohs (lsa->data->length)); -} - -const char *link_type_desc[] = -{ - "(null)", - "another Router (point-to-point)", - "a Transit Network", - "Stub Network", - "a Virtual Link", +static void show_ip_ospf_database_header(struct vty *vty, struct ospf_lsa *lsa) +{ + struct router_lsa *rlsa = (struct router_lsa *)lsa->data; + + vty_out(vty, " LS age: %d\n", LS_AGE(lsa)); + vty_out(vty, " Options: 0x%-2x : %s\n", lsa->data->options, + ospf_options_dump(lsa->data->options)); + vty_out(vty, " LS Flags: 0x%-2x %s\n", lsa->flags, + ((lsa->flags & OSPF_LSA_LOCAL_XLT) ? "(Translated from Type-7)" + : "")); + + if (lsa->data->type == OSPF_ROUTER_LSA) { + vty_out(vty, " Flags: 0x%x", rlsa->flags); + + if (rlsa->flags) + vty_out(vty, " :%s%s%s%s", + IS_ROUTER_LSA_BORDER(rlsa) ? " ABR" : "", + IS_ROUTER_LSA_EXTERNAL(rlsa) ? " ASBR" : "", + IS_ROUTER_LSA_VIRTUAL(rlsa) ? " VL-endpoint" + : "", + IS_ROUTER_LSA_SHORTCUT(rlsa) ? " Shortcut" + : ""); + + vty_out(vty, "\n"); + } + vty_out(vty, " LS Type: %s\n", + lookup_msg(ospf_lsa_type_msg, lsa->data->type, NULL)); + vty_out(vty, " Link State ID: %s %s\n", inet_ntoa(lsa->data->id), + lookup_msg(ospf_link_state_id_type_msg, lsa->data->type, NULL)); + vty_out(vty, " Advertising Router: %s\n", + inet_ntoa(lsa->data->adv_router)); + vty_out(vty, " LS Seq Number: %08lx\n", + (u_long)ntohl(lsa->data->ls_seqnum)); + vty_out(vty, " Checksum: 0x%04x\n", ntohs(lsa->data->checksum)); + vty_out(vty, " Length: %d\n\n", ntohs(lsa->data->length)); +} + +const char *link_type_desc[] = { + "(null)", + "another Router (point-to-point)", + "a Transit Network", + "Stub Network", + "a Virtual Link", }; -const char *link_id_desc[] = -{ - "(null)", - "Neighboring Router ID", - "Designated Router address", - "Net", - "Neighboring Router ID", +const char *link_id_desc[] = { + "(null)", "Neighboring Router ID", "Designated Router address", + "Net", "Neighboring Router ID", }; -const char *link_data_desc[] = -{ - "(null)", - "Router Interface address", - "Router Interface address", - "Network Mask", - "Router Interface address", +const char *link_data_desc[] = { + "(null)", "Router Interface address", "Router Interface address", + "Network Mask", "Router Interface address", }; /* Show router-LSA each Link information. */ -static void -show_ip_ospf_database_router_links (struct vty *vty, - struct router_lsa *rl) -{ - int len, type; - unsigned int i; - - len = ntohs (rl->header.length) - 4; - for (i = 0; i < ntohs (rl->links) && len > 0; len -= 12, i++) - { - type = rl->link[i].type; - - vty_out (vty, " Link connected to: %s\n", - link_type_desc[type]); - vty_out (vty, " (Link ID) %s: %s\n", link_id_desc[type], - inet_ntoa (rl->link[i].link_id)); - vty_out (vty, " (Link Data) %s: %s\n", link_data_desc[type], - inet_ntoa (rl->link[i].link_data)); - vty_out (vty, " Number of TOS metrics: 0\n"); - vty_out (vty, " TOS 0 Metric: %d\n", - ntohs (rl->link[i].metric)); - vty_out (vty, "\n"); - } +static void show_ip_ospf_database_router_links(struct vty *vty, + struct router_lsa *rl) +{ + int len, type; + unsigned int i; + + len = ntohs(rl->header.length) - 4; + for (i = 0; i < ntohs(rl->links) && len > 0; len -= 12, i++) { + type = rl->link[i].type; + + vty_out(vty, " Link connected to: %s\n", + link_type_desc[type]); + vty_out(vty, " (Link ID) %s: %s\n", link_id_desc[type], + inet_ntoa(rl->link[i].link_id)); + vty_out(vty, " (Link Data) %s: %s\n", link_data_desc[type], + inet_ntoa(rl->link[i].link_data)); + vty_out(vty, " Number of TOS metrics: 0\n"); + vty_out(vty, " TOS 0 Metric: %d\n", + ntohs(rl->link[i].metric)); + vty_out(vty, "\n"); + } } /* Show router-LSA detail information. */ -static int -show_router_lsa_detail (struct vty *vty, struct ospf_lsa *lsa) +static int show_router_lsa_detail(struct vty *vty, struct ospf_lsa *lsa) { - if (lsa != NULL) - { - struct router_lsa *rl = (struct router_lsa *) lsa->data; + if (lsa != NULL) { + struct router_lsa *rl = (struct router_lsa *)lsa->data; - show_ip_ospf_database_header (vty, lsa); - - vty_out (vty, " Number of Links: %d\n\n", ntohs (rl->links)); + show_ip_ospf_database_header(vty, lsa); - show_ip_ospf_database_router_links (vty, rl); - vty_out (vty, "\n"); - } + vty_out(vty, " Number of Links: %d\n\n", ntohs(rl->links)); - return 0; + show_ip_ospf_database_router_links(vty, rl); + vty_out(vty, "\n"); + } + + return 0; } /* Show network-LSA detail information. */ -static int -show_network_lsa_detail (struct vty *vty, struct ospf_lsa *lsa) +static int show_network_lsa_detail(struct vty *vty, struct ospf_lsa *lsa) { - int length, i; + int length, i; - if (lsa != NULL) - { - struct network_lsa *nl = (struct network_lsa *) lsa->data; + if (lsa != NULL) { + struct network_lsa *nl = (struct network_lsa *)lsa->data; - show_ip_ospf_database_header (vty, lsa); + show_ip_ospf_database_header(vty, lsa); - vty_out (vty, " Network Mask: /%d\n", - ip_masklen (nl->mask)); + vty_out(vty, " Network Mask: /%d\n", ip_masklen(nl->mask)); - length = ntohs (lsa->data->length) - OSPF_LSA_HEADER_SIZE - 4; + length = ntohs(lsa->data->length) - OSPF_LSA_HEADER_SIZE - 4; - for (i = 0; length > 0; i++, length -= 4) - vty_out (vty, " Attached Router: %s\n", - inet_ntoa (nl->routers[i])); + for (i = 0; length > 0; i++, length -= 4) + vty_out(vty, " Attached Router: %s\n", + inet_ntoa(nl->routers[i])); - vty_out (vty, "\n"); - } + vty_out(vty, "\n"); + } - return 0; + return 0; } /* Show summary-LSA detail information. */ -static int -show_summary_lsa_detail (struct vty *vty, struct ospf_lsa *lsa) +static int show_summary_lsa_detail(struct vty *vty, struct ospf_lsa *lsa) { - if (lsa != NULL) - { - struct summary_lsa *sl = (struct summary_lsa *) lsa->data; + if (lsa != NULL) { + struct summary_lsa *sl = (struct summary_lsa *)lsa->data; - show_ip_ospf_database_header (vty, lsa); + show_ip_ospf_database_header(vty, lsa); - vty_out (vty, " Network Mask: /%d\n", ip_masklen (sl->mask)); - vty_out (vty, " TOS: 0 Metric: %d\n", GET_METRIC (sl->metric)); - vty_out (vty, "\n"); - } + vty_out(vty, " Network Mask: /%d\n", ip_masklen(sl->mask)); + vty_out(vty, " TOS: 0 Metric: %d\n", + GET_METRIC(sl->metric)); + vty_out(vty, "\n"); + } - return 0; + return 0; } /* Show summary-ASBR-LSA detail information. */ -static int -show_summary_asbr_lsa_detail (struct vty *vty, struct ospf_lsa *lsa) +static int show_summary_asbr_lsa_detail(struct vty *vty, struct ospf_lsa *lsa) { - if (lsa != NULL) - { - struct summary_lsa *sl = (struct summary_lsa *) lsa->data; + if (lsa != NULL) { + struct summary_lsa *sl = (struct summary_lsa *)lsa->data; - show_ip_ospf_database_header (vty, lsa); + show_ip_ospf_database_header(vty, lsa); - vty_out (vty, " Network Mask: /%d\n", - ip_masklen (sl->mask)); - vty_out (vty, " TOS: 0 Metric: %d\n", GET_METRIC (sl->metric)); - vty_out (vty, "\n"); - } + vty_out(vty, " Network Mask: /%d\n", ip_masklen(sl->mask)); + vty_out(vty, " TOS: 0 Metric: %d\n", + GET_METRIC(sl->metric)); + vty_out(vty, "\n"); + } - return 0; + return 0; } /* Show AS-external-LSA detail information. */ -static int -show_as_external_lsa_detail (struct vty *vty, struct ospf_lsa *lsa) -{ - if (lsa != NULL) - { - struct as_external_lsa *al = (struct as_external_lsa *) lsa->data; - - show_ip_ospf_database_header (vty, lsa); - - vty_out (vty, " Network Mask: /%d\n", - ip_masklen (al->mask)); - vty_out (vty, " Metric Type: %s\n", - IS_EXTERNAL_METRIC (al->e[0].tos) ? - "2 (Larger than any link state path)" : "1"); - vty_out (vty, " TOS: 0\n"); - vty_out (vty, " Metric: %d\n", - GET_METRIC (al->e[0].metric)); - vty_out (vty, " Forward Address: %s\n", - inet_ntoa (al->e[0].fwd_addr)); - - vty_out (vty, " External Route Tag: %"ROUTE_TAG_PRI"\n\n", - (route_tag_t)ntohl (al->e[0].route_tag)); - } +static int show_as_external_lsa_detail(struct vty *vty, struct ospf_lsa *lsa) +{ + if (lsa != NULL) { + struct as_external_lsa *al = + (struct as_external_lsa *)lsa->data; + + show_ip_ospf_database_header(vty, lsa); + + vty_out(vty, " Network Mask: /%d\n", ip_masklen(al->mask)); + vty_out(vty, " Metric Type: %s\n", + IS_EXTERNAL_METRIC(al->e[0].tos) + ? "2 (Larger than any link state path)" + : "1"); + vty_out(vty, " TOS: 0\n"); + vty_out(vty, " Metric: %d\n", + GET_METRIC(al->e[0].metric)); + vty_out(vty, " Forward Address: %s\n", + inet_ntoa(al->e[0].fwd_addr)); + + vty_out(vty, + " External Route Tag: %" ROUTE_TAG_PRI "\n\n", + (route_tag_t)ntohl(al->e[0].route_tag)); + } - return 0; + return 0; } #if 0 static int @@ -4940,273 +5057,253 @@ show_as_external_lsa_stdvty (struct ospf_lsa *lsa) } #endif /* Show AS-NSSA-LSA detail information. */ -static int -show_as_nssa_lsa_detail (struct vty *vty, struct ospf_lsa *lsa) -{ - if (lsa != NULL) - { - struct as_external_lsa *al = (struct as_external_lsa *) lsa->data; - - show_ip_ospf_database_header (vty, lsa); - - vty_out (vty, " Network Mask: /%d\n", - ip_masklen (al->mask)); - vty_out (vty, " Metric Type: %s\n", - IS_EXTERNAL_METRIC (al->e[0].tos) ? - "2 (Larger than any link state path)" : "1"); - vty_out (vty, " TOS: 0\n"); - vty_out (vty, " Metric: %d\n", - GET_METRIC (al->e[0].metric)); - vty_out (vty, " NSSA: Forward Address: %s\n", - inet_ntoa (al->e[0].fwd_addr)); - - vty_out (vty, " External Route Tag: %"ROUTE_TAG_PRI"\n\n", - (route_tag_t)ntohl (al->e[0].route_tag)); - } +static int show_as_nssa_lsa_detail(struct vty *vty, struct ospf_lsa *lsa) +{ + if (lsa != NULL) { + struct as_external_lsa *al = + (struct as_external_lsa *)lsa->data; + + show_ip_ospf_database_header(vty, lsa); + + vty_out(vty, " Network Mask: /%d\n", ip_masklen(al->mask)); + vty_out(vty, " Metric Type: %s\n", + IS_EXTERNAL_METRIC(al->e[0].tos) + ? "2 (Larger than any link state path)" + : "1"); + vty_out(vty, " TOS: 0\n"); + vty_out(vty, " Metric: %d\n", + GET_METRIC(al->e[0].metric)); + vty_out(vty, " NSSA: Forward Address: %s\n", + inet_ntoa(al->e[0].fwd_addr)); + + vty_out(vty, + " External Route Tag: %" ROUTE_TAG_PRI "\n\n", + (route_tag_t)ntohl(al->e[0].route_tag)); + } - return 0; + return 0; } -static int -show_func_dummy (struct vty *vty, struct ospf_lsa *lsa) +static int show_func_dummy(struct vty *vty, struct ospf_lsa *lsa) { - return 0; + return 0; } -static int -show_opaque_lsa_detail (struct vty *vty, struct ospf_lsa *lsa) +static int show_opaque_lsa_detail(struct vty *vty, struct ospf_lsa *lsa) { - if (lsa != NULL) - { - show_ip_ospf_database_header (vty, lsa); - show_opaque_info_detail (vty, lsa); + if (lsa != NULL) { + show_ip_ospf_database_header(vty, lsa); + show_opaque_info_detail(vty, lsa); - vty_out (vty, "\n"); - } - return 0; + vty_out(vty, "\n"); + } + return 0; +} + +int (*show_function[])(struct vty *, struct ospf_lsa *) = { + NULL, + show_router_lsa_detail, + show_network_lsa_detail, + show_summary_lsa_detail, + show_summary_asbr_lsa_detail, + show_as_external_lsa_detail, + show_func_dummy, + show_as_nssa_lsa_detail, /* almost same as external */ + NULL, /* type-8 */ + show_opaque_lsa_detail, + show_opaque_lsa_detail, + show_opaque_lsa_detail, +}; + +static void show_lsa_prefix_set(struct vty *vty, struct prefix_ls *lp, + struct in_addr *id, struct in_addr *adv_router) +{ + memset(lp, 0, sizeof(struct prefix_ls)); + lp->family = 0; + if (id == NULL) + lp->prefixlen = 0; + else if (adv_router == NULL) { + lp->prefixlen = 32; + lp->id = *id; + } else { + lp->prefixlen = 64; + lp->id = *id; + lp->adv_router = *adv_router; + } } -int (*show_function[])(struct vty *, struct ospf_lsa *) = -{ - NULL, - show_router_lsa_detail, - show_network_lsa_detail, - show_summary_lsa_detail, - show_summary_asbr_lsa_detail, - show_as_external_lsa_detail, - show_func_dummy, - show_as_nssa_lsa_detail, /* almost same as external */ - NULL, /* type-8 */ - show_opaque_lsa_detail, - show_opaque_lsa_detail, - show_opaque_lsa_detail, -}; +static void show_lsa_detail_proc(struct vty *vty, struct route_table *rt, + struct in_addr *id, struct in_addr *adv_router) +{ + struct prefix_ls lp; + struct route_node *rn, *start; + struct ospf_lsa *lsa; -static void -show_lsa_prefix_set (struct vty *vty, struct prefix_ls *lp, struct in_addr *id, - struct in_addr *adv_router) -{ - memset (lp, 0, sizeof (struct prefix_ls)); - lp->family = 0; - if (id == NULL) - lp->prefixlen = 0; - else if (adv_router == NULL) - { - lp->prefixlen = 32; - lp->id = *id; - } - else - { - lp->prefixlen = 64; - lp->id = *id; - lp->adv_router = *adv_router; - } -} - -static void -show_lsa_detail_proc (struct vty *vty, struct route_table *rt, - struct in_addr *id, struct in_addr *adv_router) -{ - struct prefix_ls lp; - struct route_node *rn, *start; - struct ospf_lsa *lsa; - - show_lsa_prefix_set (vty, &lp, id, adv_router); - start = route_node_get (rt, (struct prefix *) &lp); - if (start) - { - route_lock_node (start); - for (rn = start; rn; rn = route_next_until (rn, start)) - if ((lsa = rn->info)) - { - if (show_function[lsa->data->type] != NULL) - show_function[lsa->data->type] (vty, lsa); - } - route_unlock_node (start); - } + show_lsa_prefix_set(vty, &lp, id, adv_router); + start = route_node_get(rt, (struct prefix *)&lp); + if (start) { + route_lock_node(start); + for (rn = start; rn; rn = route_next_until(rn, start)) + if ((lsa = rn->info)) { + if (show_function[lsa->data->type] != NULL) + show_function[lsa->data->type](vty, + lsa); + } + route_unlock_node(start); + } } /* Show detail LSA information -- if id is NULL then show all LSAs. */ -static void -show_lsa_detail (struct vty *vty, struct ospf *ospf, int type, - struct in_addr *id, struct in_addr *adv_router) -{ - struct listnode *node; - struct ospf_area *area; - - switch (type) - { - case OSPF_AS_EXTERNAL_LSA: - case OSPF_OPAQUE_AS_LSA: - vty_out (vty, " %s \n\n", - show_database_desc[type]); - show_lsa_detail_proc (vty, AS_LSDB (ospf, type), id, adv_router); - break; - default: - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - vty_out (vty, "\n %s (Area %s)\n\n", show_database_desc[type], - ospf_area_desc_string (area)); - show_lsa_detail_proc (vty, AREA_LSDB (area, type), id, adv_router); - } - break; - } -} - -static void -show_lsa_detail_adv_router_proc (struct vty *vty, struct route_table *rt, - struct in_addr *adv_router) -{ - struct route_node *rn; - struct ospf_lsa *lsa; - - for (rn = route_top (rt); rn; rn = route_next (rn)) - if ((lsa = rn->info)) - if (IPV4_ADDR_SAME (adv_router, &lsa->data->adv_router)) - { - if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)) - continue; - if (show_function[lsa->data->type] != NULL) - show_function[lsa->data->type] (vty, lsa); +static void show_lsa_detail(struct vty *vty, struct ospf *ospf, int type, + struct in_addr *id, struct in_addr *adv_router) +{ + struct listnode *node; + struct ospf_area *area; + + switch (type) { + case OSPF_AS_EXTERNAL_LSA: + case OSPF_OPAQUE_AS_LSA: + vty_out(vty, " %s \n\n", + show_database_desc[type]); + show_lsa_detail_proc(vty, AS_LSDB(ospf, type), id, adv_router); + break; + default: + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + vty_out(vty, "\n %s (Area %s)\n\n", + show_database_desc[type], + ospf_area_desc_string(area)); + show_lsa_detail_proc(vty, AREA_LSDB(area, type), id, + adv_router); + } + break; } } +static void show_lsa_detail_adv_router_proc(struct vty *vty, + struct route_table *rt, + struct in_addr *adv_router) +{ + struct route_node *rn; + struct ospf_lsa *lsa; + + for (rn = route_top(rt); rn; rn = route_next(rn)) + if ((lsa = rn->info)) + if (IPV4_ADDR_SAME(adv_router, + &lsa->data->adv_router)) { + if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) + continue; + if (show_function[lsa->data->type] != NULL) + show_function[lsa->data->type](vty, + lsa); + } +} + /* Show detail LSA information. */ -static void -show_lsa_detail_adv_router (struct vty *vty, struct ospf *ospf, int type, - struct in_addr *adv_router) -{ - struct listnode *node; - struct ospf_area *area; - - switch (type) - { - case OSPF_AS_EXTERNAL_LSA: - case OSPF_OPAQUE_AS_LSA: - vty_out (vty, " %s \n\n", - show_database_desc[type]); - show_lsa_detail_adv_router_proc (vty, AS_LSDB (ospf, type), - adv_router); - break; - default: - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - vty_out (vty, "\n %s (Area %s)\n\n", show_database_desc[type], - ospf_area_desc_string (area)); - show_lsa_detail_adv_router_proc (vty, AREA_LSDB (area, type), - adv_router); - } - break; - } -} - -static void -show_ip_ospf_database_summary (struct vty *vty, struct ospf *ospf, int self) -{ - struct ospf_lsa *lsa; - struct route_node *rn; - struct ospf_area *area; - struct listnode *node; - int type; - - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - for (type = OSPF_MIN_LSA; type < OSPF_MAX_LSA; type++) - { - switch (type) - { - case OSPF_AS_EXTERNAL_LSA: - case OSPF_OPAQUE_AS_LSA: - continue; - default: - break; - } - if (ospf_lsdb_count_self (area->lsdb, type) > 0 || - (!self && ospf_lsdb_count (area->lsdb, type) > 0)) - { - vty_out (vty, " %s (Area %s)\n\n", - show_database_desc[type], - ospf_area_desc_string (area)); - vty_out (vty, "%s\n", show_database_header[type]); - - LSDB_LOOP (AREA_LSDB (area, type), rn, lsa) - show_lsa_summary (vty, lsa, self); - - vty_out (vty, "\n"); - } - } - } - - for (type = OSPF_MIN_LSA; type < OSPF_MAX_LSA; type++) - { - switch (type) - { - case OSPF_AS_EXTERNAL_LSA: - case OSPF_OPAQUE_AS_LSA: - break; - default: - continue; - } - if (ospf_lsdb_count_self (ospf->lsdb, type) || - (!self && ospf_lsdb_count (ospf->lsdb, type))) - { - vty_out (vty, " %s\n\n", - show_database_desc[type]); - vty_out (vty, "%s\n", show_database_header[type]); - - LSDB_LOOP (AS_LSDB (ospf, type), rn, lsa) - show_lsa_summary (vty, lsa, self); - - vty_out (vty, "\n"); - } - } - - vty_out (vty, "\n"); -} - -static void -show_ip_ospf_database_maxage (struct vty *vty, struct ospf *ospf) -{ - struct route_node *rn; - - vty_out (vty, "\n MaxAge Link States:\n\n"); - - for (rn = route_top (ospf->maxage_lsa); rn; rn = route_next (rn)) - { - struct ospf_lsa *lsa; - - if ((lsa = rn->info) != NULL) - { - vty_out (vty, "Link type: %d\n", lsa->data->type); - vty_out (vty, "Link State ID: %s\n", - inet_ntoa (lsa->data->id)); - vty_out (vty, "Advertising Router: %s\n", - inet_ntoa (lsa->data->adv_router)); - vty_out (vty, "LSA lock count: %d\n", lsa->lock); - vty_out (vty, "\n"); +static void show_lsa_detail_adv_router(struct vty *vty, struct ospf *ospf, + int type, struct in_addr *adv_router) +{ + struct listnode *node; + struct ospf_area *area; + + switch (type) { + case OSPF_AS_EXTERNAL_LSA: + case OSPF_OPAQUE_AS_LSA: + vty_out(vty, " %s \n\n", + show_database_desc[type]); + show_lsa_detail_adv_router_proc(vty, AS_LSDB(ospf, type), + adv_router); + break; + default: + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + vty_out(vty, "\n %s (Area %s)\n\n", + show_database_desc[type], + ospf_area_desc_string(area)); + show_lsa_detail_adv_router_proc( + vty, AREA_LSDB(area, type), adv_router); + } + break; + } +} + +static void show_ip_ospf_database_summary(struct vty *vty, struct ospf *ospf, + int self) +{ + struct ospf_lsa *lsa; + struct route_node *rn; + struct ospf_area *area; + struct listnode *node; + int type; + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + for (type = OSPF_MIN_LSA; type < OSPF_MAX_LSA; type++) { + switch (type) { + case OSPF_AS_EXTERNAL_LSA: + case OSPF_OPAQUE_AS_LSA: + continue; + default: + break; + } + if (ospf_lsdb_count_self(area->lsdb, type) > 0 + || (!self + && ospf_lsdb_count(area->lsdb, type) > 0)) { + vty_out(vty, " %s (Area %s)\n\n", + show_database_desc[type], + ospf_area_desc_string(area)); + vty_out(vty, "%s\n", + show_database_header[type]); + + LSDB_LOOP(AREA_LSDB(area, type), rn, lsa) + show_lsa_summary(vty, lsa, self); + + vty_out(vty, "\n"); + } + } + } + + for (type = OSPF_MIN_LSA; type < OSPF_MAX_LSA; type++) { + switch (type) { + case OSPF_AS_EXTERNAL_LSA: + case OSPF_OPAQUE_AS_LSA: + break; + default: + continue; + } + if (ospf_lsdb_count_self(ospf->lsdb, type) + || (!self && ospf_lsdb_count(ospf->lsdb, type))) { + vty_out(vty, " %s\n\n", + show_database_desc[type]); + vty_out(vty, "%s\n", show_database_header[type]); + + LSDB_LOOP(AS_LSDB(ospf, type), rn, lsa) + show_lsa_summary(vty, lsa, self); + + vty_out(vty, "\n"); + } + } + + vty_out(vty, "\n"); +} + +static void show_ip_ospf_database_maxage(struct vty *vty, struct ospf *ospf) +{ + struct route_node *rn; + + vty_out(vty, "\n MaxAge Link States:\n\n"); + + for (rn = route_top(ospf->maxage_lsa); rn; rn = route_next(rn)) { + struct ospf_lsa *lsa; + + if ((lsa = rn->info) != NULL) { + vty_out(vty, "Link type: %d\n", lsa->data->type); + vty_out(vty, "Link State ID: %s\n", + inet_ntoa(lsa->data->id)); + vty_out(vty, "Advertising Router: %s\n", + inet_ntoa(lsa->data->adv_router)); + vty_out(vty, "LSA lock count: %d\n", lsa->lock); + vty_out(vty, "\n"); + } } - } } #define OSPF_LSA_TYPE_NSSA_DESC "NSSA external link state\n" @@ -5217,98 +5314,89 @@ show_ip_ospf_database_maxage (struct vty *vty, struct ospf *ospf) #define OSPF_LSA_TYPE_OPAQUE_AS_DESC "Link AS Opaque-LSA\n" #define OSPF_LSA_TYPE_OPAQUE_CMD_STR "|opaque-link|opaque-area|opaque-as" -#define OSPF_LSA_TYPES_DESC \ - "ASBR summary link states\n" \ - "External link states\n" \ - "Network link states\n" \ - "Router link states\n" \ - "Network summary link states\n" \ - OSPF_LSA_TYPE_NSSA_DESC \ - OSPF_LSA_TYPE_OPAQUE_LINK_DESC \ - OSPF_LSA_TYPE_OPAQUE_AREA_DESC \ - OSPF_LSA_TYPE_OPAQUE_AS_DESC +#define OSPF_LSA_TYPES_DESC \ + "ASBR summary link states\n" \ + "External link states\n" \ + "Network link states\n" \ + "Router link states\n" \ + "Network summary link states\n" OSPF_LSA_TYPE_NSSA_DESC \ + OSPF_LSA_TYPE_OPAQUE_LINK_DESC OSPF_LSA_TYPE_OPAQUE_AREA_DESC \ + OSPF_LSA_TYPE_OPAQUE_AS_DESC + +static int show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf, + int arg_base, int argc, + struct cmd_token **argv) +{ + int idx_type = 4; + int type, ret; + struct in_addr id, adv_router; + + if (ospf->instance) + vty_out(vty, "\nOSPF Instance: %d\n", ospf->instance); + + vty_out(vty, "\n OSPF Router with ID (%s)\n\n", + inet_ntoa(ospf->router_id)); + + /* Show all LSA. */ + if (argc == arg_base + 4) { + show_ip_ospf_database_summary(vty, ospf, 0); + return CMD_SUCCESS; + } -static int -show_ip_ospf_database_common (struct vty *vty, struct ospf *ospf, - int arg_base, int argc, struct cmd_token **argv) -{ - int idx_type = 4; - int type, ret; - struct in_addr id, adv_router; - - if (ospf->instance) - vty_out (vty, "\nOSPF Instance: %d\n", ospf->instance); - - vty_out (vty, "\n OSPF Router with ID (%s)\n\n", - inet_ntoa (ospf->router_id)); - - /* Show all LSA. */ - if (argc == arg_base + 4) - { - show_ip_ospf_database_summary (vty, ospf, 0); - return CMD_SUCCESS; - } - - /* Set database type to show. */ - if (strncmp (argv[arg_base + idx_type]->text, "r", 1) == 0) - type = OSPF_ROUTER_LSA; - else if (strncmp (argv[arg_base + idx_type]->text, "ne", 2) == 0) - type = OSPF_NETWORK_LSA; - else if (strncmp (argv[arg_base + idx_type]->text, "ns", 2) == 0) - type = OSPF_AS_NSSA_LSA; - else if (strncmp (argv[arg_base + idx_type]->text, "su", 2) == 0) - type = OSPF_SUMMARY_LSA; - else if (strncmp (argv[arg_base + idx_type]->text, "a", 1) == 0) - type = OSPF_ASBR_SUMMARY_LSA; - else if (strncmp (argv[arg_base + idx_type]->text, "e", 1) == 0) - type = OSPF_AS_EXTERNAL_LSA; - else if (strncmp (argv[arg_base + idx_type]->text, "se", 2) == 0) - { - show_ip_ospf_database_summary (vty, ospf, 1); - return CMD_SUCCESS; - } - else if (strncmp (argv[arg_base + idx_type]->text, "m", 1) == 0) - { - show_ip_ospf_database_maxage (vty, ospf); - return CMD_SUCCESS; - } - else if (strncmp (argv[arg_base + idx_type]->text, "opaque-l", 8) == 0) - type = OSPF_OPAQUE_LINK_LSA; - else if (strncmp (argv[arg_base + idx_type]->text, "opaque-ar", 9) == 0) - type = OSPF_OPAQUE_AREA_LSA; - else if (strncmp (argv[arg_base + idx_type]->text, "opaque-as", 9) == 0) - type = OSPF_OPAQUE_AS_LSA; - else - return CMD_WARNING; - - /* `show ip ospf database LSA'. */ - if (argc == arg_base + 5) - show_lsa_detail (vty, ospf, type, NULL, NULL); - else if (argc >= arg_base + 6) - { - ret = inet_aton (argv[arg_base + 5]->arg, &id); - if (!ret) - return CMD_WARNING; - - /* `show ip ospf database LSA ID'. */ - if (argc == arg_base + 6) - show_lsa_detail (vty, ospf, type, &id, NULL); - /* `show ip ospf database LSA ID adv-router ADV_ROUTER'. */ - else if (argc == arg_base + 7) - { - if (strncmp (argv[arg_base + 6]->text, "s", 1) == 0) - adv_router = ospf->router_id; - else - { - ret = inet_aton (argv[arg_base + 7]->arg, &adv_router); - if (!ret) + /* Set database type to show. */ + if (strncmp(argv[arg_base + idx_type]->text, "r", 1) == 0) + type = OSPF_ROUTER_LSA; + else if (strncmp(argv[arg_base + idx_type]->text, "ne", 2) == 0) + type = OSPF_NETWORK_LSA; + else if (strncmp(argv[arg_base + idx_type]->text, "ns", 2) == 0) + type = OSPF_AS_NSSA_LSA; + else if (strncmp(argv[arg_base + idx_type]->text, "su", 2) == 0) + type = OSPF_SUMMARY_LSA; + else if (strncmp(argv[arg_base + idx_type]->text, "a", 1) == 0) + type = OSPF_ASBR_SUMMARY_LSA; + else if (strncmp(argv[arg_base + idx_type]->text, "e", 1) == 0) + type = OSPF_AS_EXTERNAL_LSA; + else if (strncmp(argv[arg_base + idx_type]->text, "se", 2) == 0) { + show_ip_ospf_database_summary(vty, ospf, 1); + return CMD_SUCCESS; + } else if (strncmp(argv[arg_base + idx_type]->text, "m", 1) == 0) { + show_ip_ospf_database_maxage(vty, ospf); + return CMD_SUCCESS; + } else if (strncmp(argv[arg_base + idx_type]->text, "opaque-l", 8) == 0) + type = OSPF_OPAQUE_LINK_LSA; + else if (strncmp(argv[arg_base + idx_type]->text, "opaque-ar", 9) == 0) + type = OSPF_OPAQUE_AREA_LSA; + else if (strncmp(argv[arg_base + idx_type]->text, "opaque-as", 9) == 0) + type = OSPF_OPAQUE_AS_LSA; + else return CMD_WARNING; - } - show_lsa_detail (vty, ospf, type, &id, &adv_router); + + /* `show ip ospf database LSA'. */ + if (argc == arg_base + 5) + show_lsa_detail(vty, ospf, type, NULL, NULL); + else if (argc >= arg_base + 6) { + ret = inet_aton(argv[arg_base + 5]->arg, &id); + if (!ret) + return CMD_WARNING; + + /* `show ip ospf database LSA ID'. */ + if (argc == arg_base + 6) + show_lsa_detail(vty, ospf, type, &id, NULL); + /* `show ip ospf database LSA ID adv-router ADV_ROUTER'. */ + else if (argc == arg_base + 7) { + if (strncmp(argv[arg_base + 6]->text, "s", 1) == 0) + adv_router = ospf->router_id; + else { + ret = inet_aton(argv[arg_base + 7]->arg, + &adv_router); + if (!ret) + return CMD_WARNING; + } + show_lsa_detail(vty, ospf, type, &id, &adv_router); + } } - } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_ospf_database_max, @@ -5321,12 +5409,12 @@ DEFUN (show_ip_ospf_database_max, "LSAs in MaxAge list\n" "Self-originated link states\n") { - struct ospf *ospf; + struct ospf *ospf; - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) + return CMD_SUCCESS; - return (show_ip_ospf_database_common(vty, ospf, 0, argc, argv)); + return (show_ip_ospf_database_common(vty, ospf, 0, argc, argv)); } DEFUN (show_ip_ospf_instance_database, @@ -5343,23 +5431,22 @@ DEFUN (show_ip_ospf_instance_database, "Advertising Router link states\n" "Advertising Router (as an IP address)\n") { - struct ospf *ospf; - u_short instance = 0; + struct ospf *ospf; + u_short instance = 0; - int idx = 0; - if (argv_find (argv, argc, "(1-65535)", &idx)) - { - instance = strtoul(argv[idx]->arg, NULL, 10); - ospf = ospf_lookup_instance (instance); - } - else { - ospf = ospf_lookup(); - } + int idx = 0; + if (argv_find(argv, argc, "(1-65535)", &idx)) { + instance = strtoul(argv[idx]->arg, NULL, 10); + ospf = ospf_lookup_instance(instance); + } else { + ospf = ospf_lookup(); + } - if (!ospf || !ospf->oi_running) - return CMD_SUCCESS; + if (!ospf || !ospf->oi_running) + return CMD_SUCCESS; - return (show_ip_ospf_database_common(vty, ospf, idx ? 1 : 0, argc, argv)); + return (show_ip_ospf_database_common(vty, ospf, idx ? 1 : 0, argc, + argv)); } DEFUN (show_ip_ospf_instance_database_max, @@ -5373,68 +5460,69 @@ DEFUN (show_ip_ospf_instance_database_max, "LSAs in MaxAge list\n" "Self-originated link states\n") { - int idx_number = 3; - struct ospf *ospf; - u_short instance = 0; - - instance = strtoul(argv[idx_number]->arg, NULL, 10); - - if ((ospf = ospf_lookup_instance (instance)) == NULL || !ospf->oi_running) - return CMD_SUCCESS; - - return (show_ip_ospf_database_common(vty, ospf, 1, argc, argv)); -} + int idx_number = 3; + struct ospf *ospf; + u_short instance = 0; + + instance = strtoul(argv[idx_number]->arg, NULL, 10); + + if ((ospf = ospf_lookup_instance(instance)) == NULL + || !ospf->oi_running) + return CMD_SUCCESS; + + return (show_ip_ospf_database_common(vty, ospf, 1, argc, argv)); +} + + +static int show_ip_ospf_database_type_adv_router_common(struct vty *vty, + struct ospf *ospf, + int arg_base, int argc, + struct cmd_token **argv) +{ + int idx_type = 4; + int type, ret; + struct in_addr adv_router; + + if (ospf->instance) + vty_out(vty, "\nOSPF Instance: %d\n", ospf->instance); + + vty_out(vty, "\n OSPF Router with ID (%s)\n\n", + inet_ntoa(ospf->router_id)); + + /* Set database type to show. */ + if (strncmp(argv[arg_base + idx_type]->text, "r", 1) == 0) + type = OSPF_ROUTER_LSA; + else if (strncmp(argv[arg_base + idx_type]->text, "ne", 2) == 0) + type = OSPF_NETWORK_LSA; + else if (strncmp(argv[arg_base + idx_type]->text, "ns", 2) == 0) + type = OSPF_AS_NSSA_LSA; + else if (strncmp(argv[arg_base + idx_type]->text, "s", 1) == 0) + type = OSPF_SUMMARY_LSA; + else if (strncmp(argv[arg_base + idx_type]->text, "a", 1) == 0) + type = OSPF_ASBR_SUMMARY_LSA; + else if (strncmp(argv[arg_base + idx_type]->text, "e", 1) == 0) + type = OSPF_AS_EXTERNAL_LSA; + else if (strncmp(argv[arg_base + idx_type]->text, "opaque-l", 8) == 0) + type = OSPF_OPAQUE_LINK_LSA; + else if (strncmp(argv[arg_base + idx_type]->text, "opaque-ar", 9) == 0) + type = OSPF_OPAQUE_AREA_LSA; + else if (strncmp(argv[arg_base + idx_type]->text, "opaque-as", 9) == 0) + type = OSPF_OPAQUE_AS_LSA; + else + return CMD_WARNING; + /* `show ip ospf database LSA adv-router ADV_ROUTER'. */ + if (strncmp(argv[arg_base + 5]->text, "s", 1) == 0) + adv_router = ospf->router_id; + else { + ret = inet_aton(argv[arg_base + 6]->arg, &adv_router); + if (!ret) + return CMD_WARNING; + } -static int -show_ip_ospf_database_type_adv_router_common (struct vty *vty, struct ospf *ospf, - int arg_base, int argc, struct cmd_token **argv) -{ - int idx_type = 4; - int type, ret; - struct in_addr adv_router; - - if (ospf->instance) - vty_out (vty, "\nOSPF Instance: %d\n", ospf->instance); - - vty_out (vty, "\n OSPF Router with ID (%s)\n\n", - inet_ntoa (ospf->router_id)); - - /* Set database type to show. */ - if (strncmp (argv[arg_base + idx_type]->text, "r", 1) == 0) - type = OSPF_ROUTER_LSA; - else if (strncmp (argv[arg_base + idx_type]->text, "ne", 2) == 0) - type = OSPF_NETWORK_LSA; - else if (strncmp (argv[arg_base + idx_type]->text, "ns", 2) == 0) - type = OSPF_AS_NSSA_LSA; - else if (strncmp (argv[arg_base + idx_type]->text, "s", 1) == 0) - type = OSPF_SUMMARY_LSA; - else if (strncmp (argv[arg_base + idx_type]->text, "a", 1) == 0) - type = OSPF_ASBR_SUMMARY_LSA; - else if (strncmp (argv[arg_base + idx_type]->text, "e", 1) == 0) - type = OSPF_AS_EXTERNAL_LSA; - else if (strncmp (argv[arg_base + idx_type]->text, "opaque-l", 8) == 0) - type = OSPF_OPAQUE_LINK_LSA; - else if (strncmp (argv[arg_base + idx_type]->text, "opaque-ar", 9) == 0) - type = OSPF_OPAQUE_AREA_LSA; - else if (strncmp (argv[arg_base + idx_type]->text, "opaque-as", 9) == 0) - type = OSPF_OPAQUE_AS_LSA; - else - return CMD_WARNING; - - /* `show ip ospf database LSA adv-router ADV_ROUTER'. */ - if (strncmp (argv[arg_base + 5]->text, "s", 1) == 0) - adv_router = ospf->router_id; - else - { - ret = inet_aton (argv[arg_base + 6]->arg, &adv_router); - if (!ret) - return CMD_WARNING; - } - - show_lsa_detail_adv_router (vty, ospf, type, &adv_router); + show_lsa_detail_adv_router(vty, ospf, type, &adv_router); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_ospf_instance_database_type_adv_router, @@ -5450,22 +5538,21 @@ DEFUN (show_ip_ospf_instance_database_type_adv_router, "Advertising Router (as an IP address)\n" "Self-originated link states\n") { - struct ospf *ospf; - u_short instance = 0; - int idx = 0; + struct ospf *ospf; + u_short instance = 0; + int idx = 0; - if (argv_find(argv, argc, "(1-65535)", &idx)) - { - instance = strtoul(argv[idx]->arg, NULL, 10); - ospf = ospf_lookup_instance(instance); - } - else - ospf = ospf_lookup(); + if (argv_find(argv, argc, "(1-65535)", &idx)) { + instance = strtoul(argv[idx]->arg, NULL, 10); + ospf = ospf_lookup_instance(instance); + } else + ospf = ospf_lookup(); - if (!ospf || !ospf->oi_running) - return CMD_SUCCESS; + if (!ospf || !ospf->oi_running) + return CMD_SUCCESS; - return (show_ip_ospf_database_type_adv_router_common(vty, ospf, idx ? 1 : 0, argc, argv)); + return (show_ip_ospf_database_type_adv_router_common( + vty, ospf, idx ? 1 : 0, argc, argv)); } DEFUN (ip_ospf_authentication_args, @@ -5478,46 +5565,43 @@ DEFUN (ip_ospf_authentication_args, "Use message-digest authentication\n" "Address of interface\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_encryption = 3; - int idx_ipv4 = 4; - struct in_addr addr; - int ret; - struct ospf_if_params *params; - - params = IF_DEF_PARAMS (ifp); - - if (argc == 5) - { - ret = inet_aton(argv[idx_ipv4]->arg, &addr); - if (!ret) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_encryption = 3; + int idx_ipv4 = 4; + struct in_addr addr; + int ret; + struct ospf_if_params *params; + + params = IF_DEF_PARAMS(ifp); + + if (argc == 5) { + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - params = ospf_get_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } - /* Handle null authentication */ - if ( argv[idx_encryption]->arg[0] == 'n' ) - { - SET_IF_PARAM (params, auth_type); - params->auth_type = OSPF_AUTH_NULL; - return CMD_SUCCESS; - } + /* Handle null authentication */ + if (argv[idx_encryption]->arg[0] == 'n') { + SET_IF_PARAM(params, auth_type); + params->auth_type = OSPF_AUTH_NULL; + return CMD_SUCCESS; + } - /* Handle message-digest authentication */ - if ( argv[idx_encryption]->arg[0] == 'm' ) - { - SET_IF_PARAM (params, auth_type); - params->auth_type = OSPF_AUTH_CRYPTOGRAPHIC; - return CMD_SUCCESS; - } + /* Handle message-digest authentication */ + if (argv[idx_encryption]->arg[0] == 'm') { + SET_IF_PARAM(params, auth_type); + params->auth_type = OSPF_AUTH_CRYPTOGRAPHIC; + return CMD_SUCCESS; + } - vty_out (vty, "You shouldn't get here!\n"); - return CMD_WARNING_CONFIG_FAILED; + vty_out(vty, "You shouldn't get here!\n"); + return CMD_WARNING_CONFIG_FAILED; } DEFUN (ip_ospf_authentication, @@ -5528,31 +5612,30 @@ DEFUN (ip_ospf_authentication, "Enable authentication on this interface\n" "Address of interface") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_ipv4 = 3; - struct in_addr addr; - int ret; - struct ospf_if_params *params; - - params = IF_DEF_PARAMS (ifp); - - if (argc == 4) - { - ret = inet_aton(argv[idx_ipv4]->arg, &addr); - if (!ret) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_ipv4 = 3; + struct in_addr addr; + int ret; + struct ospf_if_params *params; + + params = IF_DEF_PARAMS(ifp); + + if (argc == 4) { + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); } - params = ospf_get_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } - - SET_IF_PARAM (params, auth_type); - params->auth_type = OSPF_AUTH_SIMPLE; + SET_IF_PARAM(params, auth_type); + params->auth_type = OSPF_AUTH_SIMPLE; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_ospf_authentication_args, @@ -5566,86 +5649,75 @@ DEFUN (no_ip_ospf_authentication_args, "Use message-digest authentication\n" "Address of interface") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_encryption = 4; - int idx_ipv4 = 5; - struct in_addr addr; - int ret; - struct ospf_if_params *params; - struct route_node *rn; - int auth_type; - - params = IF_DEF_PARAMS (ifp); - - if (argc == 6) - { - ret = inet_aton(argv[idx_ipv4]->arg, &addr); - if (!ret) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_encryption = 4; + int idx_ipv4 = 5; + struct in_addr addr; + int ret; + struct ospf_if_params *params; + struct route_node *rn; + int auth_type; + + params = IF_DEF_PARAMS(ifp); + + if (argc == 6) { + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - params = ospf_lookup_if_params (ifp, addr); - if (params == NULL) - { - vty_out (vty, "Ip Address specified is unknown\n"); - return CMD_WARNING_CONFIG_FAILED; - } - params->auth_type = OSPF_AUTH_NOTSET; - UNSET_IF_PARAM (params, auth_type); - if (params != IF_DEF_PARAMS (ifp)) - { - ospf_free_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } - } - else - { - if ( argv[idx_encryption]->arg[0] == 'n' ) - { - auth_type = OSPF_AUTH_NULL; - } - else if ( argv[idx_encryption]->arg[0] == 'm' ) - { - auth_type = OSPF_AUTH_CRYPTOGRAPHIC; - } - else - { - vty_out (vty, "Unexpected input encountered\n"); - return CMD_WARNING_CONFIG_FAILED; - } - /* - * Here we have a case where the user has entered - * 'no ip ospf authentication (null | message_digest )' - * we need to find if we have any ip addresses underneath it that - * correspond to the associated type. - */ - if (params->auth_type == auth_type) - { - params->auth_type = OSPF_AUTH_NOTSET; - UNSET_IF_PARAM (params, auth_type); - } - - for (rn = route_top (IF_OIFS_PARAMS (ifp)); rn; rn = route_next (rn)) - { - if ((params = rn->info)) - { - if (params->auth_type == auth_type) - { - params->auth_type = OSPF_AUTH_NOTSET; - UNSET_IF_PARAM (params, auth_type); - if (params != IF_DEF_PARAMS (ifp)) - { - ospf_free_if_params (ifp, rn->p.u.prefix4); - ospf_if_update_params(ifp, rn->p.u.prefix4); - } + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) { + vty_out(vty, "Ip Address specified is unknown\n"); + return CMD_WARNING_CONFIG_FAILED; + } + params->auth_type = OSPF_AUTH_NOTSET; + UNSET_IF_PARAM(params, auth_type); + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + } else { + if (argv[idx_encryption]->arg[0] == 'n') { + auth_type = OSPF_AUTH_NULL; + } else if (argv[idx_encryption]->arg[0] == 'm') { + auth_type = OSPF_AUTH_CRYPTOGRAPHIC; + } else { + vty_out(vty, "Unexpected input encountered\n"); + return CMD_WARNING_CONFIG_FAILED; + } + /* + * Here we have a case where the user has entered + * 'no ip ospf authentication (null | message_digest )' + * we need to find if we have any ip addresses underneath it + * that + * correspond to the associated type. + */ + if (params->auth_type == auth_type) { + params->auth_type = OSPF_AUTH_NOTSET; + UNSET_IF_PARAM(params, auth_type); + } + + for (rn = route_top(IF_OIFS_PARAMS(ifp)); rn; + rn = route_next(rn)) { + if ((params = rn->info)) { + if (params->auth_type == auth_type) { + params->auth_type = OSPF_AUTH_NOTSET; + UNSET_IF_PARAM(params, auth_type); + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params( + ifp, rn->p.u.prefix4); + ospf_if_update_params( + ifp, rn->p.u.prefix4); + } + } + } } - } } - } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_ospf_authentication, @@ -5657,76 +5729,71 @@ DEFUN (no_ip_ospf_authentication, "Enable authentication on this interface\n" "Address of interface") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_ipv4 = 4; - struct in_addr addr; - int ret; - struct ospf_if_params *params; - struct route_node *rn; - - params = IF_DEF_PARAMS (ifp); - - if (argc == 5) - { - ret = inet_aton(argv[idx_ipv4]->arg, &addr); - if (!ret) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_ipv4 = 4; + struct in_addr addr; + int ret; + struct ospf_if_params *params; + struct route_node *rn; + + params = IF_DEF_PARAMS(ifp); + + if (argc == 5) { + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - params = ospf_lookup_if_params (ifp, addr); - if (params == NULL) - { - vty_out (vty, "Ip Address specified is unknown\n"); - return CMD_WARNING_CONFIG_FAILED; - } + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) { + vty_out(vty, "Ip Address specified is unknown\n"); + return CMD_WARNING_CONFIG_FAILED; + } - params->auth_type = OSPF_AUTH_NOTSET; - UNSET_IF_PARAM (params, auth_type); - if (params != IF_DEF_PARAMS (ifp)) - { - ospf_free_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } - } - else - { - /* - * When a user enters 'no ip ospf authentication' - * We should remove all authentication types from - * the interface. - */ - if ((params->auth_type == OSPF_AUTH_NULL) || - (params->auth_type == OSPF_AUTH_CRYPTOGRAPHIC) || - (params->auth_type == OSPF_AUTH_SIMPLE)) - { - params->auth_type = OSPF_AUTH_NOTSET; - UNSET_IF_PARAM (params, auth_type); - } - - for (rn = route_top (IF_OIFS_PARAMS (ifp)); rn; rn = route_next (rn)) - { - if ((params = rn->info)) - { + params->auth_type = OSPF_AUTH_NOTSET; + UNSET_IF_PARAM(params, auth_type); + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + } else { + /* + * When a user enters 'no ip ospf authentication' + * We should remove all authentication types from + * the interface. + */ + if ((params->auth_type == OSPF_AUTH_NULL) + || (params->auth_type == OSPF_AUTH_CRYPTOGRAPHIC) + || (params->auth_type == OSPF_AUTH_SIMPLE)) { + params->auth_type = OSPF_AUTH_NOTSET; + UNSET_IF_PARAM(params, auth_type); + } - if ((params->auth_type == OSPF_AUTH_NULL) || - (params->auth_type == OSPF_AUTH_CRYPTOGRAPHIC) || - (params->auth_type == OSPF_AUTH_SIMPLE)) - { - params->auth_type = OSPF_AUTH_NOTSET; - UNSET_IF_PARAM (params, auth_type); - if (params != IF_DEF_PARAMS (ifp)) - { - ospf_free_if_params (ifp, rn->p.u.prefix4); - ospf_if_update_params(ifp, rn->p.u.prefix4); - } + for (rn = route_top(IF_OIFS_PARAMS(ifp)); rn; + rn = route_next(rn)) { + if ((params = rn->info)) { + + if ((params->auth_type == OSPF_AUTH_NULL) + || (params->auth_type + == OSPF_AUTH_CRYPTOGRAPHIC) + || (params->auth_type + == OSPF_AUTH_SIMPLE)) { + params->auth_type = OSPF_AUTH_NOTSET; + UNSET_IF_PARAM(params, auth_type); + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params( + ifp, rn->p.u.prefix4); + ospf_if_update_params( + ifp, rn->p.u.prefix4); + } + } + } } - } } - } - - return CMD_SUCCESS; + + return CMD_SUCCESS; } @@ -5739,30 +5806,30 @@ DEFUN (ip_ospf_authentication_key, "The OSPF password (key)\n" "Address of interface") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx = 0; - struct in_addr addr; - struct ospf_if_params *params; - - params = IF_DEF_PARAMS (ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + struct in_addr addr; + struct ospf_if_params *params; - if (argv_find (argv, argc, "A.B.C.D", &idx)) - { - if (!inet_aton(argv[idx]->arg, &addr)) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } + params = IF_DEF_PARAMS(ifp); + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - params = ospf_get_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } - memset (params->auth_simple, 0, OSPF_AUTH_SIMPLE_SIZE + 1); - strncpy ((char *) params->auth_simple, argv[3]->arg, OSPF_AUTH_SIMPLE_SIZE); - SET_IF_PARAM (params, auth_simple); + memset(params->auth_simple, 0, OSPF_AUTH_SIMPLE_SIZE + 1); + strncpy((char *)params->auth_simple, argv[3]->arg, + OSPF_AUTH_SIMPLE_SIZE); + SET_IF_PARAM(params, auth_simple); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_HIDDEN (ospf_authentication_key, @@ -5773,7 +5840,7 @@ DEFUN_HIDDEN (ospf_authentication_key, "The OSPF password (key)\n" "Address of interface\n") { - return ip_ospf_authentication_key (self, vty, argc, argv); + return ip_ospf_authentication_key(self, vty, argc, argv); } DEFUN (no_ip_ospf_authentication_key, @@ -5785,35 +5852,33 @@ DEFUN (no_ip_ospf_authentication_key, "Authentication password (key)\n" "The OSPF password (key)") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx = 0; - struct in_addr addr; - struct ospf_if_params *params; - params = IF_DEF_PARAMS (ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + struct in_addr addr; + struct ospf_if_params *params; + params = IF_DEF_PARAMS(ifp); + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (argv_find (argv, argc, "A.B.C.D", &idx)) - { - if (!inet_aton(argv[idx]->arg, &addr)) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) + return CMD_SUCCESS; } - params = ospf_lookup_if_params (ifp, addr); - if (params == NULL) - return CMD_SUCCESS; - } - - memset (params->auth_simple, 0, OSPF_AUTH_SIMPLE_SIZE); - UNSET_IF_PARAM (params, auth_simple); + memset(params->auth_simple, 0, OSPF_AUTH_SIMPLE_SIZE); + UNSET_IF_PARAM(params, auth_simple); - if (params != IF_DEF_PARAMS (ifp)) - { - ospf_free_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_HIDDEN (no_ospf_authentication_key, @@ -5824,7 +5889,7 @@ DEFUN_HIDDEN (no_ospf_authentication_key, "Authentication password (key)\n" "The OSPF password (key)") { - return no_ip_ospf_authentication_key (self, vty, argc, argv); + return no_ip_ospf_authentication_key(self, vty, argc, argv); } DEFUN (ip_ospf_message_digest_key, @@ -5838,48 +5903,46 @@ DEFUN (ip_ospf_message_digest_key, "The OSPF password (key)\n" "Address of interface\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct crypt_key *ck; - u_char key_id; - struct in_addr addr; - struct ospf_if_params *params; - - params = IF_DEF_PARAMS (ifp); - int idx = 0; - - argv_find (argv, argc, "(1-255)", &idx); - char *keyid = argv[idx]->arg; - argv_find (argv, argc, "KEY", &idx); - char *cryptkey = argv[idx]->arg; - - if (argv_find (argv, argc, "A.B.C.D", &idx)) - { - if (!inet_aton(argv[idx]->arg, &addr)) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct crypt_key *ck; + u_char key_id; + struct in_addr addr; + struct ospf_if_params *params; + + params = IF_DEF_PARAMS(ifp); + int idx = 0; + + argv_find(argv, argc, "(1-255)", &idx); + char *keyid = argv[idx]->arg; + argv_find(argv, argc, "KEY", &idx); + char *cryptkey = argv[idx]->arg; + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); } - params = ospf_get_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } + key_id = strtol(keyid, NULL, 10); + if (ospf_crypt_key_lookup(params->auth_crypt, key_id) != NULL) { + vty_out(vty, "OSPF: Key %d already exists\n", key_id); + return CMD_WARNING_CONFIG_FAILED; + } - key_id = strtol (keyid, NULL, 10); - if (ospf_crypt_key_lookup (params->auth_crypt, key_id) != NULL) - { - vty_out (vty, "OSPF: Key %d already exists\n", key_id); - return CMD_WARNING_CONFIG_FAILED; - } + ck = ospf_crypt_key_new(); + ck->key_id = (u_char)key_id; + memset(ck->auth_key, 0, OSPF_AUTH_MD5_SIZE + 1); + strncpy((char *)ck->auth_key, cryptkey, OSPF_AUTH_MD5_SIZE); - ck = ospf_crypt_key_new (); - ck->key_id = (u_char) key_id; - memset (ck->auth_key, 0, OSPF_AUTH_MD5_SIZE+1); - strncpy ((char *) ck->auth_key, cryptkey, OSPF_AUTH_MD5_SIZE); + ospf_crypt_key_add(params->auth_crypt, ck); + SET_IF_PARAM(params, auth_crypt); - ospf_crypt_key_add (params->auth_crypt, ck); - SET_IF_PARAM (params, auth_crypt); - - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_HIDDEN (ospf_message_digest_key, @@ -5892,7 +5955,7 @@ DEFUN_HIDDEN (ospf_message_digest_key, "The OSPF password (key)\n" "Address of interface\n") { - return ip_ospf_message_digest_key (self, vty, argc, argv); + return ip_ospf_message_digest_key(self, vty, argc, argv); } DEFUN (no_ip_ospf_message_digest_key, @@ -5907,47 +5970,44 @@ DEFUN (no_ip_ospf_message_digest_key, "The OSPF password (key)\n" "Address of interface\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx = 0; - struct crypt_key *ck; - int key_id; - struct in_addr addr; - struct ospf_if_params *params; - params = IF_DEF_PARAMS (ifp); - - argv_find (argv, argc, "(1-255)", &idx); - char *keyid = argv[idx]->arg; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + struct crypt_key *ck; + int key_id; + struct in_addr addr; + struct ospf_if_params *params; + params = IF_DEF_PARAMS(ifp); + + argv_find(argv, argc, "(1-255)", &idx); + char *keyid = argv[idx]->arg; + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (argv_find (argv, argc, "A.B.C.D", &idx)) - { - if (!inet_aton(argv[idx]->arg, &addr)) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) + return CMD_SUCCESS; } - params = ospf_lookup_if_params (ifp, addr); - if (params == NULL) - return CMD_SUCCESS; - } - - key_id = strtol (keyid, NULL, 10); - ck = ospf_crypt_key_lookup (params->auth_crypt, key_id); - if (ck == NULL) - { - vty_out (vty, "OSPF: Key %d does not exist\n", key_id); - return CMD_WARNING_CONFIG_FAILED; - } + key_id = strtol(keyid, NULL, 10); + ck = ospf_crypt_key_lookup(params->auth_crypt, key_id); + if (ck == NULL) { + vty_out(vty, "OSPF: Key %d does not exist\n", key_id); + return CMD_WARNING_CONFIG_FAILED; + } - ospf_crypt_key_delete (params->auth_crypt, key_id); + ospf_crypt_key_delete(params->auth_crypt, key_id); - if (params != IF_DEF_PARAMS (ifp)) - { - ospf_free_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_HIDDEN (no_ospf_message_digest_key, @@ -5959,7 +6019,7 @@ DEFUN_HIDDEN (no_ospf_message_digest_key, "Key ID\n" "Address of interface") { - return no_ip_ospf_message_digest_key (self, vty, argc, argv); + return no_ip_ospf_message_digest_key(self, vty, argc, argv); } DEFUN (ip_ospf_cost, @@ -5971,38 +6031,38 @@ DEFUN (ip_ospf_cost, "Cost\n" "Address of interface\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx = 0; - u_int32_t cost; - struct in_addr addr; - struct ospf_if_params *params; - params = IF_DEF_PARAMS (ifp); - - // get arguments - char *coststr = NULL, *ifaddr = NULL; - coststr = argv_find (argv, argc, "(1-65535)", &idx) ? argv[idx]->arg : NULL; - ifaddr = argv_find (argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL; - - cost = strtol (coststr, NULL, 10); + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + u_int32_t cost; + struct in_addr addr; + struct ospf_if_params *params; + params = IF_DEF_PARAMS(ifp); + + // get arguments + char *coststr = NULL, *ifaddr = NULL; + coststr = argv_find(argv, argc, "(1-65535)", &idx) ? argv[idx]->arg + : NULL; + ifaddr = argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL; + + cost = strtol(coststr, NULL, 10); + + if (ifaddr) { + if (!inet_aton(ifaddr, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (ifaddr) - { - if(!inet_aton(ifaddr, &addr)) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); } - params = ospf_get_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } - - SET_IF_PARAM (params, output_cost_cmd); - params->output_cost_cmd = cost; + SET_IF_PARAM(params, output_cost_cmd); + params->output_cost_cmd = cost; - ospf_if_recalculate_output_cost (ifp); + ospf_if_recalculate_output_cost(ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_HIDDEN (ospf_cost, @@ -6013,7 +6073,7 @@ DEFUN_HIDDEN (ospf_cost, "Cost\n" "Address of interface\n") { - return ip_ospf_cost (self, vty, argc, argv); + return ip_ospf_cost(self, vty, argc, argv); } DEFUN (no_ip_ospf_cost, @@ -6024,45 +6084,43 @@ DEFUN (no_ip_ospf_cost, "Interface cost\n" "Address of interface") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx = 0; - struct in_addr addr; - struct ospf_if_params *params; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + struct in_addr addr; + struct ospf_if_params *params; - params = IF_DEF_PARAMS (ifp); + params = IF_DEF_PARAMS(ifp); - // get arguments - char *ifaddr = NULL; - ifaddr = argv_find (argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL; + // get arguments + char *ifaddr = NULL; + ifaddr = argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL; - /* According to the semantics we are mimicking "no ip ospf cost N" is - * always treated as "no ip ospf cost" regardless of the actual value - * of N already configured for the interface. Thus ignore cost. */ + /* According to the semantics we are mimicking "no ip ospf cost N" is + * always treated as "no ip ospf cost" regardless of the actual value + * of N already configured for the interface. Thus ignore cost. */ - if (ifaddr) - { - if (!inet_aton(ifaddr, &addr)) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (ifaddr) { + if (!inet_aton(ifaddr, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - params = ospf_lookup_if_params (ifp, addr); - if (params == NULL) - return CMD_SUCCESS; - } + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) + return CMD_SUCCESS; + } - UNSET_IF_PARAM (params, output_cost_cmd); + UNSET_IF_PARAM(params, output_cost_cmd); - if (params != IF_DEF_PARAMS (ifp)) - { - ospf_free_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } - ospf_if_recalculate_output_cost (ifp); + ospf_if_recalculate_output_cost(ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_HIDDEN (no_ospf_cost, @@ -6074,98 +6132,86 @@ DEFUN_HIDDEN (no_ospf_cost, "Cost\n" "Address of interface\n") { - return no_ip_ospf_cost (self, vty, argc, argv); + return no_ip_ospf_cost(self, vty, argc, argv); } -static void -ospf_nbr_timer_update (struct ospf_interface *oi) +static void ospf_nbr_timer_update(struct ospf_interface *oi) { - struct route_node *rn; - struct ospf_neighbor *nbr; + struct route_node *rn; + struct ospf_neighbor *nbr; - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - { - nbr->v_inactivity = OSPF_IF_PARAM (oi, v_wait); - nbr->v_db_desc = OSPF_IF_PARAM (oi, retransmit_interval); - nbr->v_ls_req = OSPF_IF_PARAM (oi, retransmit_interval); - nbr->v_ls_upd = OSPF_IF_PARAM (oi, retransmit_interval); - } + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info)) { + nbr->v_inactivity = OSPF_IF_PARAM(oi, v_wait); + nbr->v_db_desc = OSPF_IF_PARAM(oi, retransmit_interval); + nbr->v_ls_req = OSPF_IF_PARAM(oi, retransmit_interval); + nbr->v_ls_upd = OSPF_IF_PARAM(oi, retransmit_interval); + } } -static int -ospf_vty_dead_interval_set (struct vty *vty, const char *interval_str, - const char *nbr_str, - const char *fast_hello_str) -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - u_int32_t seconds; - u_char hellomult; - struct in_addr addr; - int ret; - struct ospf_if_params *params; - struct ospf_interface *oi; - struct route_node *rn; - - params = IF_DEF_PARAMS (ifp); - - if (nbr_str) - { - ret = inet_aton(nbr_str, &addr); - if (!ret) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - params = ospf_get_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } - - if (interval_str) - { - seconds = strtoul(interval_str, NULL, 10); - - /* reset fast_hello too, just to be sure */ - UNSET_IF_PARAM (params, fast_hello); - params->fast_hello = OSPF_FAST_HELLO_DEFAULT; - } - else if (fast_hello_str) - { - hellomult = strtoul(fast_hello_str, NULL, 10); - /* 1s dead-interval with sub-second hellos desired */ - seconds = OSPF_ROUTER_DEAD_INTERVAL_MINIMAL; - SET_IF_PARAM (params, fast_hello); - params->fast_hello = hellomult; - } - else - { - vty_out (vty, "Please specify dead-interval or hello-multiplier\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - SET_IF_PARAM (params, v_wait); - params->v_wait = seconds; - - /* Update timer values in neighbor structure. */ - if (nbr_str) - { - struct ospf *ospf; - if ((ospf = ospf_lookup())) - { - oi = ospf_if_lookup_by_local_addr (ospf, ifp, addr); - if (oi) - ospf_nbr_timer_update (oi); - } - } - else - { - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - if ((oi = rn->info)) - ospf_nbr_timer_update (oi); - } +static int ospf_vty_dead_interval_set(struct vty *vty, const char *interval_str, + const char *nbr_str, + const char *fast_hello_str) +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + u_int32_t seconds; + u_char hellomult; + struct in_addr addr; + int ret; + struct ospf_if_params *params; + struct ospf_interface *oi; + struct route_node *rn; - return CMD_SUCCESS; + params = IF_DEF_PARAMS(ifp); + + if (nbr_str) { + ret = inet_aton(nbr_str, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + + if (interval_str) { + seconds = strtoul(interval_str, NULL, 10); + + /* reset fast_hello too, just to be sure */ + UNSET_IF_PARAM(params, fast_hello); + params->fast_hello = OSPF_FAST_HELLO_DEFAULT; + } else if (fast_hello_str) { + hellomult = strtoul(fast_hello_str, NULL, 10); + /* 1s dead-interval with sub-second hellos desired */ + seconds = OSPF_ROUTER_DEAD_INTERVAL_MINIMAL; + SET_IF_PARAM(params, fast_hello); + params->fast_hello = hellomult; + } else { + vty_out(vty, + "Please specify dead-interval or hello-multiplier\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + SET_IF_PARAM(params, v_wait); + params->v_wait = seconds; + + /* Update timer values in neighbor structure. */ + if (nbr_str) { + struct ospf *ospf; + if ((ospf = ospf_lookup())) { + oi = ospf_if_lookup_by_local_addr(ospf, ifp, addr); + if (oi) + ospf_nbr_timer_update(oi); + } + } else { + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) + if ((oi = rn->info)) + ospf_nbr_timer_update(oi); + } + + return CMD_SUCCESS; } DEFUN (ip_ospf_dead_interval, @@ -6177,10 +6223,13 @@ DEFUN (ip_ospf_dead_interval, "Seconds\n" "Address of interface\n") { - int idx = 0; - char *interval = argv_find (argv, argc, "(1-65535)", &idx) ? argv[idx]->arg : NULL; - char *ifaddr = argv_find (argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL; - return ospf_vty_dead_interval_set (vty, interval, ifaddr, NULL); + int idx = 0; + char *interval = argv_find(argv, argc, "(1-65535)", &idx) + ? argv[idx]->arg + : NULL; + char *ifaddr = + argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL; + return ospf_vty_dead_interval_set(vty, interval, ifaddr, NULL); } @@ -6192,7 +6241,7 @@ DEFUN_HIDDEN (ospf_dead_interval, "Seconds\n" "Address of interface\n") { - return ip_ospf_dead_interval (self, vty, argc, argv); + return ip_ospf_dead_interval(self, vty, argc, argv); } DEFUN (ip_ospf_dead_interval_minimal, @@ -6206,12 +6255,14 @@ DEFUN (ip_ospf_dead_interval_minimal, "Number of Hellos to send each second\n" "Address of interface\n") { - int idx_number = 5; - int idx_ipv4 = 6; - if (argc == 7) - return ospf_vty_dead_interval_set (vty, NULL, argv[idx_ipv4]->arg, argv[idx_number]->arg); - else - return ospf_vty_dead_interval_set (vty, NULL, NULL, argv[idx_number]->arg); + int idx_number = 5; + int idx_ipv4 = 6; + if (argc == 7) + return ospf_vty_dead_interval_set( + vty, NULL, argv[idx_ipv4]->arg, argv[idx_number]->arg); + else + return ospf_vty_dead_interval_set(vty, NULL, NULL, + argv[idx_number]->arg); } DEFUN (no_ip_ospf_dead_interval, @@ -6224,62 +6275,56 @@ DEFUN (no_ip_ospf_dead_interval, "Seconds\n" "Address of interface") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_ipv4 = argc - 1; - struct in_addr addr = { .s_addr = 0L}; - int ret; - struct ospf_if_params *params; - struct ospf_interface *oi; - struct route_node *rn; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_ipv4 = argc - 1; + struct in_addr addr = {.s_addr = 0L}; + int ret; + struct ospf_if_params *params; + struct ospf_interface *oi; + struct route_node *rn; + + params = IF_DEF_PARAMS(ifp); + + if (argv[idx_ipv4]->type == IPV4_TKN) { + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - params = IF_DEF_PARAMS (ifp); + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) + return CMD_SUCCESS; + } - if (argv[idx_ipv4]->type == IPV4_TKN) - { - ret = inet_aton(argv[idx_ipv4]->arg, &addr); - if (!ret) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; + UNSET_IF_PARAM(params, v_wait); + params->v_wait = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT; + + UNSET_IF_PARAM(params, fast_hello); + params->fast_hello = OSPF_FAST_HELLO_DEFAULT; + + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); } - params = ospf_lookup_if_params (ifp, addr); - if (params == NULL) - return CMD_SUCCESS; - } - - UNSET_IF_PARAM (params, v_wait); - params->v_wait = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT; - - UNSET_IF_PARAM (params, fast_hello); - params->fast_hello = OSPF_FAST_HELLO_DEFAULT; - - if (params != IF_DEF_PARAMS (ifp)) - { - ospf_free_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } - - /* Update timer values in neighbor structure. */ - if (argc == 1) - { - struct ospf *ospf; - - if ((ospf = ospf_lookup())) - { - oi = ospf_if_lookup_by_local_addr (ospf, ifp, addr); - if (oi) - ospf_nbr_timer_update (oi); - } - } - else - { - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - if ((oi = rn->info)) - ospf_nbr_timer_update (oi); - } + /* Update timer values in neighbor structure. */ + if (argc == 1) { + struct ospf *ospf; - return CMD_SUCCESS; + if ((ospf = ospf_lookup())) { + oi = ospf_if_lookup_by_local_addr(ospf, ifp, addr); + if (oi) + ospf_nbr_timer_update(oi); + } + } else { + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) + if ((oi = rn->info)) + ospf_nbr_timer_update(oi); + } + + return CMD_SUCCESS; } DEFUN_HIDDEN (no_ospf_dead_interval, @@ -6291,7 +6336,7 @@ DEFUN_HIDDEN (no_ospf_dead_interval, "Seconds\n" "Address of interface") { - return no_ip_ospf_dead_interval (self, vty, argc, argv); + return no_ip_ospf_dead_interval(self, vty, argc, argv); } DEFUN (ip_ospf_hello_interval, @@ -6303,32 +6348,31 @@ DEFUN (ip_ospf_hello_interval, "Seconds\n" "Address of interface\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx = 0; - struct in_addr addr; - struct ospf_if_params *params; - params = IF_DEF_PARAMS (ifp); - u_int32_t seconds = 0; - - argv_find (argv, argc, "(1-65535)", &idx); - seconds = strtol (argv[idx]->arg, NULL, 10); - - if (argv_find (argv, argc, "A.B.C.D", &idx)) - { - if(!inet_aton(argv[idx]->arg, &addr)) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + struct in_addr addr; + struct ospf_if_params *params; + params = IF_DEF_PARAMS(ifp); + u_int32_t seconds = 0; + + argv_find(argv, argc, "(1-65535)", &idx); + seconds = strtol(argv[idx]->arg, NULL, 10); + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - params = ospf_get_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } - SET_IF_PARAM (params, v_hello); - params->v_hello = seconds; + SET_IF_PARAM(params, v_hello); + params->v_hello = seconds; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_HIDDEN (ospf_hello_interval, @@ -6339,7 +6383,7 @@ DEFUN_HIDDEN (ospf_hello_interval, "Seconds\n" "Address of interface\n") { - return ip_ospf_hello_interval (self, vty, argc, argv); + return ip_ospf_hello_interval(self, vty, argc, argv); } DEFUN (no_ip_ospf_hello_interval, @@ -6352,36 +6396,34 @@ DEFUN (no_ip_ospf_hello_interval, "Seconds\n" "Address of interface\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx = 0; - struct in_addr addr; - struct ospf_if_params *params; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + struct in_addr addr; + struct ospf_if_params *params; - params = IF_DEF_PARAMS (ifp); + params = IF_DEF_PARAMS(ifp); - if (argv_find (argv, argc, "A.B.C.D", &idx)) - { - if(!inet_aton(argv[idx]->arg, &addr)) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - params = ospf_lookup_if_params (ifp, addr); - if (params == NULL) - return CMD_SUCCESS; - } + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) + return CMD_SUCCESS; + } - UNSET_IF_PARAM (params, v_hello); - params->v_hello = OSPF_HELLO_INTERVAL_DEFAULT; + UNSET_IF_PARAM(params, v_hello); + params->v_hello = OSPF_HELLO_INTERVAL_DEFAULT; - if (params != IF_DEF_PARAMS (ifp)) - { - ospf_free_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_HIDDEN (no_ospf_hello_interval, @@ -6393,7 +6435,7 @@ DEFUN_HIDDEN (no_ospf_hello_interval, "Seconds\n" "Address of interface\n") { - return no_ip_ospf_hello_interval (self, vty, argc, argv); + return no_ip_ospf_hello_interval(self, vty, argc, argv); } DEFUN (ip_ospf_network, @@ -6407,48 +6449,46 @@ DEFUN (ip_ospf_network, "Specify OSPF point-to-multipoint network\n" "Specify OSPF point-to-point network\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx = 0; - int old_type = IF_DEF_PARAMS (ifp)->type; - struct route_node *rn; - - if (old_type == OSPF_IFTYPE_LOOPBACK) - { - vty_out (vty, "This is a loopback interface. Can't set network type.\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (argv_find (argv, argc, "broadcast", &idx)) - IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_BROADCAST; - else if (argv_find (argv, argc, "non-broadcast", &idx)) - IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_NBMA; - else if (argv_find (argv, argc, "point-to-multipoint", &idx)) - IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_POINTOMULTIPOINT; - else if (argv_find (argv, argc, "point-to-point", &idx)) - IF_DEF_PARAMS (ifp)->type = OSPF_IFTYPE_POINTOPOINT; - - if (IF_DEF_PARAMS (ifp)->type == old_type) - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + int old_type = IF_DEF_PARAMS(ifp)->type; + struct route_node *rn; - SET_IF_PARAM (IF_DEF_PARAMS (ifp), type); + if (old_type == OSPF_IFTYPE_LOOPBACK) { + vty_out(vty, + "This is a loopback interface. Can't set network type.\n"); + return CMD_WARNING_CONFIG_FAILED; + } - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - { - struct ospf_interface *oi = rn->info; + if (argv_find(argv, argc, "broadcast", &idx)) + IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_BROADCAST; + else if (argv_find(argv, argc, "non-broadcast", &idx)) + IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_NBMA; + else if (argv_find(argv, argc, "point-to-multipoint", &idx)) + IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_POINTOMULTIPOINT; + else if (argv_find(argv, argc, "point-to-point", &idx)) + IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_POINTOPOINT; - if (!oi) - continue; - - oi->type = IF_DEF_PARAMS (ifp)->type; - - if (oi->state > ISM_Down) - { - OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown); - OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceUp); + if (IF_DEF_PARAMS(ifp)->type == old_type) + return CMD_SUCCESS; + + SET_IF_PARAM(IF_DEF_PARAMS(ifp), type); + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi = rn->info; + + if (!oi) + continue; + + oi->type = IF_DEF_PARAMS(ifp)->type; + + if (oi->state > ISM_Down) { + OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown); + OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceUp); + } } - } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_HIDDEN (ospf_network, @@ -6461,7 +6501,7 @@ DEFUN_HIDDEN (ospf_network, "Specify OSPF point-to-multipoint network\n" "Specify OSPF point-to-point network\n") { - return ip_ospf_network (self, vty, argc, argv); + return ip_ospf_network(self, vty, argc, argv); } DEFUN (no_ip_ospf_network, @@ -6476,32 +6516,30 @@ DEFUN (no_ip_ospf_network, "Specify OSPF point-to-multipoint network\n" "Specify OSPF point-to-point network\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int old_type = IF_DEF_PARAMS (ifp)->type; - struct route_node *rn; + VTY_DECLVAR_CONTEXT(interface, ifp); + int old_type = IF_DEF_PARAMS(ifp)->type; + struct route_node *rn; - IF_DEF_PARAMS (ifp)->type = ospf_default_iftype(ifp); + IF_DEF_PARAMS(ifp)->type = ospf_default_iftype(ifp); - if (IF_DEF_PARAMS (ifp)->type == old_type) - return CMD_SUCCESS; + if (IF_DEF_PARAMS(ifp)->type == old_type) + return CMD_SUCCESS; - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - { - struct ospf_interface *oi = rn->info; + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi = rn->info; - if (!oi) - continue; + if (!oi) + continue; - oi->type = IF_DEF_PARAMS (ifp)->type; + oi->type = IF_DEF_PARAMS(ifp)->type; - if (oi->state > ISM_Down) - { - OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown); - OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceUp); + if (oi->state > ISM_Down) { + OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown); + OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceUp); + } } - } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_HIDDEN (no_ospf_network, @@ -6515,7 +6553,7 @@ DEFUN_HIDDEN (no_ospf_network, "Specify OSPF point-to-multipoint network\n" "Specify OSPF point-to-point network\n") { - return no_ip_ospf_network (self, vty, argc, argv); + return no_ip_ospf_network(self, vty, argc, argv); } DEFUN (ip_ospf_priority, @@ -6527,47 +6565,44 @@ DEFUN (ip_ospf_priority, "Priority\n" "Address of interface") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx = 0; - long priority; - struct route_node *rn; - struct in_addr addr; - struct ospf_if_params *params; - params = IF_DEF_PARAMS (ifp); - - argv_find (argv, argc, "(0-255)", &idx); - priority = strtol (argv[idx]->arg, NULL, 10); + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + long priority; + struct route_node *rn; + struct in_addr addr; + struct ospf_if_params *params; + params = IF_DEF_PARAMS(ifp); + + argv_find(argv, argc, "(0-255)", &idx); + priority = strtol(argv[idx]->arg, NULL, 10); + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (argv_find (argv, argc, "A.B.C.D", &idx)) - { - if (!inet_aton(argv[idx]->arg, &addr)) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); } - params = ospf_get_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } + SET_IF_PARAM(params, priority); + params->priority = priority; - SET_IF_PARAM (params, priority); - params->priority = priority; + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi = rn->info; - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - { - struct ospf_interface *oi = rn->info; + if (!oi) + continue; - if (!oi) - continue; - - if (PRIORITY (oi) != OSPF_IF_PARAM (oi, priority)) - { - PRIORITY (oi) = OSPF_IF_PARAM (oi, priority); - OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange); + if (PRIORITY(oi) != OSPF_IF_PARAM(oi, priority)) { + PRIORITY(oi) = OSPF_IF_PARAM(oi, priority); + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange); + } } - } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_HIDDEN (ospf_priority, @@ -6578,7 +6613,7 @@ DEFUN_HIDDEN (ospf_priority, "Priority\n" "Address of interface") { - return ip_ospf_priority (self, vty, argc, argv); + return ip_ospf_priority(self, vty, argc, argv); } DEFUN (no_ip_ospf_priority, @@ -6591,51 +6626,47 @@ DEFUN (no_ip_ospf_priority, "Priority\n" "Address of interface") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx = 0; - struct route_node *rn; - struct in_addr addr; - struct ospf_if_params *params; - - params = IF_DEF_PARAMS (ifp); - - if (argv_find (argv, argc, "A.B.C.D", &idx)) - { - if (!inet_aton(argv[idx]->arg, &addr)) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + struct route_node *rn; + struct in_addr addr; + struct ospf_if_params *params; + + params = IF_DEF_PARAMS(ifp); + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) + return CMD_SUCCESS; } - params = ospf_lookup_if_params (ifp, addr); - if (params == NULL) - return CMD_SUCCESS; - } - - UNSET_IF_PARAM (params, priority); - params->priority = OSPF_ROUTER_PRIORITY_DEFAULT; - - if (params != IF_DEF_PARAMS (ifp)) - { - ospf_free_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } - - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - { - struct ospf_interface *oi = rn->info; - - if (!oi) - continue; - - if (PRIORITY (oi) != OSPF_IF_PARAM (oi, priority)) - { - PRIORITY (oi) = OSPF_IF_PARAM (oi, priority); - OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange); + UNSET_IF_PARAM(params, priority); + params->priority = OSPF_ROUTER_PRIORITY_DEFAULT; + + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); } - } - - return CMD_SUCCESS; + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi = rn->info; + + if (!oi) + continue; + + if (PRIORITY(oi) != OSPF_IF_PARAM(oi, priority)) { + PRIORITY(oi) = OSPF_IF_PARAM(oi, priority); + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange); + } + } + + return CMD_SUCCESS; } DEFUN_HIDDEN (no_ospf_priority, @@ -6647,7 +6678,7 @@ DEFUN_HIDDEN (no_ospf_priority, "Priority\n" "Address of interface") { - return no_ip_ospf_priority (self, vty, argc, argv); + return no_ip_ospf_priority(self, vty, argc, argv); } DEFUN (ip_ospf_retransmit_interval, @@ -6659,32 +6690,31 @@ DEFUN (ip_ospf_retransmit_interval, "Seconds\n" "Address of interface") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx = 0; - u_int32_t seconds; - struct in_addr addr; - struct ospf_if_params *params; - params = IF_DEF_PARAMS (ifp); - - argv_find (argv, argc, "(3-65535)", &idx); - seconds = strtol (argv[idx]->arg, NULL, 10); + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + u_int32_t seconds; + struct in_addr addr; + struct ospf_if_params *params; + params = IF_DEF_PARAMS(ifp); + + argv_find(argv, argc, "(3-65535)", &idx); + seconds = strtol(argv[idx]->arg, NULL, 10); + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (argv_find (argv, argc, "A.B.C.D", &idx)) - { - if (!inet_aton(argv[idx]->arg, &addr)) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); } - params = ospf_get_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } + SET_IF_PARAM(params, retransmit_interval); + params->retransmit_interval = seconds; - SET_IF_PARAM (params, retransmit_interval); - params->retransmit_interval = seconds; - - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_HIDDEN (ospf_retransmit_interval, @@ -6695,7 +6725,7 @@ DEFUN_HIDDEN (ospf_retransmit_interval, "Seconds\n" "Address of interface") { - return ip_ospf_retransmit_interval (self, vty, argc, argv); + return ip_ospf_retransmit_interval(self, vty, argc, argv); } DEFUN (no_ip_ospf_retransmit_interval, @@ -6708,36 +6738,34 @@ DEFUN (no_ip_ospf_retransmit_interval, "Seconds\n" "Address of interface\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx = 0; - struct in_addr addr; - struct ospf_if_params *params; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + struct in_addr addr; + struct ospf_if_params *params; - params = IF_DEF_PARAMS (ifp); + params = IF_DEF_PARAMS(ifp); - if (argv_find (argv, argc, "A.B.C.D", &idx)) - { - if (!inet_aton(argv[idx]->arg, &addr)) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - params = ospf_lookup_if_params (ifp, addr); - if (params == NULL) - return CMD_SUCCESS; - } + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) + return CMD_SUCCESS; + } - UNSET_IF_PARAM (params, retransmit_interval); - params->retransmit_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT; + UNSET_IF_PARAM(params, retransmit_interval); + params->retransmit_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT; - if (params != IF_DEF_PARAMS (ifp)) - { - ospf_free_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_HIDDEN (no_ospf_retransmit_interval, @@ -6749,7 +6777,7 @@ DEFUN_HIDDEN (no_ospf_retransmit_interval, "Seconds\n" "Address of interface\n") { - return no_ip_ospf_retransmit_interval (self, vty, argc, argv); + return no_ip_ospf_retransmit_interval(self, vty, argc, argv); } DEFUN (ip_ospf_transmit_delay, @@ -6761,32 +6789,31 @@ DEFUN (ip_ospf_transmit_delay, "Seconds\n" "Address of interface") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx = 0; - u_int32_t seconds; - struct in_addr addr; - struct ospf_if_params *params; - - params = IF_DEF_PARAMS (ifp); - argv_find (argv, argc, "(1-65535)", &idx); - seconds = strtol (argv[idx]->arg, NULL, 10); + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + u_int32_t seconds; + struct in_addr addr; + struct ospf_if_params *params; + + params = IF_DEF_PARAMS(ifp); + argv_find(argv, argc, "(1-65535)", &idx); + seconds = strtol(argv[idx]->arg, NULL, 10); + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (argv_find (argv, argc, "A.B.C.D", &idx)) - { - if (!inet_aton(argv[idx]->arg, &addr)) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); } - params = ospf_get_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } + SET_IF_PARAM(params, transmit_delay); + params->transmit_delay = seconds; - SET_IF_PARAM (params, transmit_delay); - params->transmit_delay = seconds; - - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_HIDDEN (ospf_transmit_delay, @@ -6797,7 +6824,7 @@ DEFUN_HIDDEN (ospf_transmit_delay, "Seconds\n" "Address of interface") { - return ip_ospf_transmit_delay (self, vty, argc, argv); + return ip_ospf_transmit_delay(self, vty, argc, argv); } DEFUN (no_ip_ospf_transmit_delay, @@ -6809,36 +6836,34 @@ DEFUN (no_ip_ospf_transmit_delay, "Link state transmit delay\n" "Address of interface") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx = 0; - struct in_addr addr; - struct ospf_if_params *params; - - params = IF_DEF_PARAMS (ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + struct in_addr addr; + struct ospf_if_params *params; - if (argv_find (argv, argc, "A.B.C.D", &idx)) - { - if (!inet_aton(argv[idx]->arg, &addr)) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } + params = IF_DEF_PARAMS(ifp); - params = ospf_lookup_if_params (ifp, addr); - if (params == NULL) - return CMD_SUCCESS; - } + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - UNSET_IF_PARAM (params, transmit_delay); - params->transmit_delay = OSPF_TRANSMIT_DELAY_DEFAULT; + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) + return CMD_SUCCESS; + } - if (params != IF_DEF_PARAMS (ifp)) - { - ospf_free_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } + UNSET_IF_PARAM(params, transmit_delay); + params->transmit_delay = OSPF_TRANSMIT_DELAY_DEFAULT; - return CMD_SUCCESS; + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + + return CMD_SUCCESS; } @@ -6849,7 +6874,7 @@ DEFUN_HIDDEN (no_ospf_transmit_delay, "OSPF interface commands\n" "Link state transmit delay\n") { - return no_ip_ospf_transmit_delay (self, vty, argc, argv); + return no_ip_ospf_transmit_delay(self, vty, argc, argv); } DEFUN (ip_ospf_area, @@ -6863,87 +6888,81 @@ DEFUN (ip_ospf_area, "OSPF area ID as a decimal value\n" "Address of interface\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx = 0; - int format, ret; - struct in_addr area_id; - struct in_addr addr; - struct ospf_if_params *params; - struct route_node *rn; - struct ospf *ospf; - u_short instance = 0; - char *areaid; - - if (argv_find (argv, argc, "(1-65535)", &idx)) - instance = strtol (argv[idx]->arg, NULL, 10); - - argv_find (argv, argc, "area", &idx); - areaid = argv[idx + 1]->arg; - - ospf = ospf_lookup_instance (instance); - if (ospf == NULL) - { - params = IF_DEF_PARAMS (ifp); - if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) - { - UNSET_IF_PARAM (params, if_area); - ospf_interface_area_unset (ifp); - ospf = ospf_lookup(); - ospf->if_ospf_cli_count--; - } - return CMD_SUCCESS; - } - - ret = str2area_id (areaid, &area_id, &format); - if (ret < 0) - { - vty_out (vty, "Please specify area by A.B.C.D|<0-4294967295>\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (memcmp (ifp->name, "VLINK", 5) == 0) - { - vty_out (vty, "Cannot enable OSPF on a virtual link.\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - params = IF_DEF_PARAMS (ifp); - if (OSPF_IF_PARAM_CONFIGURED(params, if_area) && !IPV4_ADDR_SAME(¶ms->if_area, &area_id)) - { - vty_out (vty, - "Must remove previous area config before changing ospf area \n"); - return CMD_WARNING_CONFIG_FAILED; - } - - // Check if we have an address arg and proccess it - if (argc == idx + 3) { - inet_aton(argv[idx+2]->arg, &addr); - // update/create address-level params - params = ospf_get_if_params ((ifp), (addr)); - if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) - { - vty_out (vty, - "Must remove previous area/address config before changing ospf area"); - return CMD_WARNING_CONFIG_FAILED; - } - ospf_if_update_params ((ifp), (addr)); - } - - for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) - { - if (rn->info != NULL) - { - vty_out (vty, "Please remove all network commands first.\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - /* enable ospf on this interface with area_id */ - SET_IF_PARAM (params, if_area); - params->if_area = area_id; - ospf_interface_area_set (ifp); - ospf->if_ospf_cli_count++; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + int format, ret; + struct in_addr area_id; + struct in_addr addr; + struct ospf_if_params *params; + struct route_node *rn; + struct ospf *ospf; + u_short instance = 0; + char *areaid; + + if (argv_find(argv, argc, "(1-65535)", &idx)) + instance = strtol(argv[idx]->arg, NULL, 10); + + argv_find(argv, argc, "area", &idx); + areaid = argv[idx + 1]->arg; + + ospf = ospf_lookup_instance(instance); + if (ospf == NULL) { + params = IF_DEF_PARAMS(ifp); + if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) { + UNSET_IF_PARAM(params, if_area); + ospf_interface_area_unset(ifp); + ospf = ospf_lookup(); + ospf->if_ospf_cli_count--; + } + return CMD_SUCCESS; + } - return CMD_SUCCESS; + ret = str2area_id(areaid, &area_id, &format); + if (ret < 0) { + vty_out(vty, "Please specify area by A.B.C.D|<0-4294967295>\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (memcmp(ifp->name, "VLINK", 5) == 0) { + vty_out(vty, "Cannot enable OSPF on a virtual link.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = IF_DEF_PARAMS(ifp); + if (OSPF_IF_PARAM_CONFIGURED(params, if_area) + && !IPV4_ADDR_SAME(¶ms->if_area, &area_id)) { + vty_out(vty, + "Must remove previous area config before changing ospf area \n"); + return CMD_WARNING_CONFIG_FAILED; + } + + // Check if we have an address arg and proccess it + if (argc == idx + 3) { + inet_aton(argv[idx + 2]->arg, &addr); + // update/create address-level params + params = ospf_get_if_params((ifp), (addr)); + if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) { + vty_out(vty, + "Must remove previous area/address config before changing ospf area"); + return CMD_WARNING_CONFIG_FAILED; + } + ospf_if_update_params((ifp), (addr)); + } + + for (rn = route_top(ospf->networks); rn; rn = route_next(rn)) { + if (rn->info != NULL) { + vty_out(vty, + "Please remove all network commands first.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + /* enable ospf on this interface with area_id */ + SET_IF_PARAM(params, if_area); + params->if_area = area_id; + ospf_interface_area_set(ifp); + ospf->if_ospf_cli_count++; + + return CMD_SUCCESS; } DEFUN (no_ip_ospf_area, @@ -6958,47 +6977,45 @@ DEFUN (no_ip_ospf_area, "OSPF area ID as a decimal value\n" "Address of interface\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx = 0; - struct ospf *ospf; - struct ospf_if_params *params; - u_short instance = 0; - struct in_addr addr; - - if (argv_find (argv, argc, "(1-65535)", &idx)) - instance = strtol (argv[idx]->arg, NULL, 10); - - if ((ospf = ospf_lookup_instance (instance)) == NULL) - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + struct ospf *ospf; + struct ospf_if_params *params; + u_short instance = 0; + struct in_addr addr; + + if (argv_find(argv, argc, "(1-65535)", &idx)) + instance = strtol(argv[idx]->arg, NULL, 10); + + if ((ospf = ospf_lookup_instance(instance)) == NULL) + return CMD_SUCCESS; + + argv_find(argv, argc, "area", &idx); + + // Check if we have an address arg and proccess it + if (argc == idx + 3) { + inet_aton(argv[idx + 2]->arg, &addr); + params = ospf_lookup_if_params(ifp, addr); + if ((params) == NULL) + return CMD_SUCCESS; + } else + params = IF_DEF_PARAMS(ifp); + + if (!OSPF_IF_PARAM_CONFIGURED(params, if_area)) { + vty_out(vty, + "Can't find specified interface area configuration.\n"); + return CMD_WARNING_CONFIG_FAILED; + } - argv_find (argv, argc, "area", &idx); - - // Check if we have an address arg and proccess it - if (argc == idx + 3) { - inet_aton(argv[idx+2]->arg, &addr); - params = ospf_lookup_if_params (ifp, addr); - if ((params) == NULL) - return CMD_SUCCESS; - } - else - params = IF_DEF_PARAMS (ifp); - - if (!OSPF_IF_PARAM_CONFIGURED(params, if_area)) - { - vty_out (vty, "Can't find specified interface area configuration.\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - UNSET_IF_PARAM (params, if_area); - if (params != IF_DEF_PARAMS ((ifp))) - { - ospf_free_if_params ((ifp), (addr)); - ospf_if_update_params ((ifp), (addr)); - } - - ospf_interface_area_unset (ifp); - ospf->if_ospf_cli_count--; - return CMD_SUCCESS; + UNSET_IF_PARAM(params, if_area); + if (params != IF_DEF_PARAMS((ifp))) { + ospf_free_if_params((ifp), (addr)); + ospf_if_update_params((ifp), (addr)); + } + + ospf_interface_area_unset(ifp); + ospf->if_ospf_cli_count--; + return CMD_SUCCESS; } DEFUN (ospf_redistribute_source, @@ -7013,42 +7030,41 @@ DEFUN (ospf_redistribute_source, "Route map reference\n" "Pointer to route-map entries\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_protocol = 1; - int source; - int type = -1; - int metric = -1; - struct ospf_redist *red; - int idx = 0; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_protocol = 1; + int source; + int type = -1; + int metric = -1; + struct ospf_redist *red; + int idx = 0; - if (!ospf) - return CMD_SUCCESS; + if (!ospf) + return CMD_SUCCESS; + + /* Get distribute source. */ + source = proto_redistnum(AFI_IP, argv[idx_protocol]->text); + if (source < 0) + return CMD_WARNING_CONFIG_FAILED; + + red = ospf_redist_add(ospf, source, 0); + + /* Get metric value. */ + if (argv_find(argv, argc, "(0-16777214)", &idx)) { + if (!str2metric(argv[idx]->arg, &metric)) + return CMD_WARNING_CONFIG_FAILED; + } + /* Get metric type. */ + else if (argv_find(argv, argc, "(1-2)", &idx)) { + if (!str2metric_type(argv[idx]->arg, &type)) + return CMD_WARNING_CONFIG_FAILED; + } + /* Get route-map */ + else if (argv_find(argv, argc, "WORD", &idx)) { + ospf_routemap_set(red, argv[idx]->arg); + } else + ospf_routemap_unset(red); - /* Get distribute source. */ - source = proto_redistnum(AFI_IP, argv[idx_protocol]->text); - if (source < 0) - return CMD_WARNING_CONFIG_FAILED; - - red = ospf_redist_add(ospf, source, 0); - - /* Get metric value. */ - if (argv_find (argv, argc, "(0-16777214)", &idx)) { - if (!str2metric (argv[idx]->arg, &metric)) - return CMD_WARNING_CONFIG_FAILED; - } - /* Get metric type. */ - else if (argv_find (argv, argc, "(1-2)", &idx)) { - if (!str2metric_type (argv[idx]->arg, &type)) - return CMD_WARNING_CONFIG_FAILED; - } - /* Get route-map */ - else if (argv_find (argv, argc, "WORD", &idx)) { - ospf_routemap_set (red, argv[idx]->arg); - } - else - ospf_routemap_unset (red); - - return ospf_redistribute_set (ospf, source, 0, type, metric); + return ospf_redistribute_set(ospf, source, 0, type, metric); } DEFUN (no_ospf_redistribute_source, @@ -7064,21 +7080,21 @@ DEFUN (no_ospf_redistribute_source, "Route map reference\n" "Pointer to route-map entries\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_protocol = 2; - int source; - struct ospf_redist *red; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_protocol = 2; + int source; + struct ospf_redist *red; - source = proto_redistnum(AFI_IP, argv[idx_protocol]->text); - if (source < 0) - return CMD_WARNING_CONFIG_FAILED; + source = proto_redistnum(AFI_IP, argv[idx_protocol]->text); + if (source < 0) + return CMD_WARNING_CONFIG_FAILED; - red = ospf_redist_lookup(ospf, source, 0); - if (!red) - return CMD_SUCCESS; + red = ospf_redist_lookup(ospf, source, 0); + if (!red) + return CMD_SUCCESS; - ospf_routemap_unset (red); - return ospf_redistribute_unset (ospf, source, 0); + ospf_routemap_unset(red); + return ospf_redistribute_unset(ospf, source, 0); } DEFUN (ospf_redistribute_instance_source, @@ -7095,58 +7111,57 @@ DEFUN (ospf_redistribute_instance_source, "Route map reference\n" "Pointer to route-map entries\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ospf_table = 1; - int idx_number = 2; - int idx = 3; - int source; - int type = -1; - int metric = -1; - u_short instance; - struct ospf_redist *red; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ospf_table = 1; + int idx_number = 2; + int idx = 3; + int source; + int type = -1; + int metric = -1; + u_short instance; + struct ospf_redist *red; - if (!ospf) - return CMD_SUCCESS; + if (!ospf) + return CMD_SUCCESS; - source = proto_redistnum (AFI_IP, argv[idx_ospf_table]->text); + source = proto_redistnum(AFI_IP, argv[idx_ospf_table]->text); - instance = strtoul(argv[idx_number]->arg, NULL, 10); + instance = strtoul(argv[idx_number]->arg, NULL, 10); - if (!ospf) - return CMD_SUCCESS; + if (!ospf) + return CMD_SUCCESS; - if ((source == ZEBRA_ROUTE_OSPF) && !ospf->instance) - { - vty_out (vty, "Instance redistribution in non-instanced OSPF not allowed\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if ((source == ZEBRA_ROUTE_OSPF) && !ospf->instance) { + vty_out(vty, + "Instance redistribution in non-instanced OSPF not allowed\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if ((source == ZEBRA_ROUTE_OSPF) && (ospf->instance == instance)) - { - vty_out (vty, "Same instance OSPF redistribution not allowed\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if ((source == ZEBRA_ROUTE_OSPF) && (ospf->instance == instance)) { + vty_out(vty, "Same instance OSPF redistribution not allowed\n"); + return CMD_WARNING_CONFIG_FAILED; + } - /* Get metric value. */ - if (argv_find (argv, argc, "metric", &idx)) - if (!str2metric (argv[idx+1]->arg, &metric)) - return CMD_WARNING_CONFIG_FAILED; + /* Get metric value. */ + if (argv_find(argv, argc, "metric", &idx)) + if (!str2metric(argv[idx + 1]->arg, &metric)) + return CMD_WARNING_CONFIG_FAILED; - idx = 3; - /* Get metric type. */ - if (argv_find (argv, argc, "metric-type", &idx)) - if (!str2metric_type (argv[idx+1]->arg, &type)) - return CMD_WARNING_CONFIG_FAILED; + idx = 3; + /* Get metric type. */ + if (argv_find(argv, argc, "metric-type", &idx)) + if (!str2metric_type(argv[idx + 1]->arg, &type)) + return CMD_WARNING_CONFIG_FAILED; - red = ospf_redist_add(ospf, source, instance); + red = ospf_redist_add(ospf, source, instance); - idx = 3; - if (argv_find (argv, argc, "route-map", &idx)) - ospf_routemap_set (red, argv[idx+1]->arg); - else - ospf_routemap_unset (red); + idx = 3; + if (argv_find(argv, argc, "route-map", &idx)) + ospf_routemap_set(red, argv[idx + 1]->arg); + else + ospf_routemap_unset(red); - return ospf_redistribute_set (ospf, source, instance, type, metric); + return ospf_redistribute_set(ospf, source, instance, type, metric); } DEFUN (no_ospf_redistribute_instance_source, @@ -7164,38 +7179,37 @@ DEFUN (no_ospf_redistribute_instance_source, "Route map reference\n" "Pointer to route-map entries\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_ospf_table = 2; - int idx_number = 3; - u_int instance; - struct ospf_redist *red; - int source; - - if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) - source = ZEBRA_ROUTE_OSPF; - else - source = ZEBRA_ROUTE_TABLE; - - instance = strtoul(argv[idx_number]->arg, NULL, 10); - - if ((source == ZEBRA_ROUTE_OSPF) && !ospf->instance) - { - vty_out (vty, "Instance redistribution in non-instanced OSPF not allowed\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if ((source == ZEBRA_ROUTE_OSPF) && (ospf->instance == instance)) - { - vty_out (vty, "Same instance OSPF redistribution not allowed\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - red = ospf_redist_lookup(ospf, source, instance); - if (!red) - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_ospf_table = 2; + int idx_number = 3; + u_int instance; + struct ospf_redist *red; + int source; + + if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) + source = ZEBRA_ROUTE_OSPF; + else + source = ZEBRA_ROUTE_TABLE; + + instance = strtoul(argv[idx_number]->arg, NULL, 10); - ospf_routemap_unset (red); - return ospf_redistribute_unset (ospf, source, instance); + if ((source == ZEBRA_ROUTE_OSPF) && !ospf->instance) { + vty_out(vty, + "Instance redistribution in non-instanced OSPF not allowed\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if ((source == ZEBRA_ROUTE_OSPF) && (ospf->instance == instance)) { + vty_out(vty, "Same instance OSPF redistribution not allowed\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + red = ospf_redist_lookup(ospf, source, instance); + if (!red) + return CMD_SUCCESS; + + ospf_routemap_unset(red); + return ospf_redistribute_unset(ospf, source, instance); } DEFUN (ospf_distribute_list_out, @@ -7206,18 +7220,18 @@ DEFUN (ospf_distribute_list_out, OUT_STR FRR_REDIST_HELP_STR_OSPFD) { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_word = 1; - int source; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_word = 1; + int source; - char *proto = argv[argc - 1]->text; + char *proto = argv[argc - 1]->text; - /* Get distribute source. */ - source = proto_redistnum(AFI_IP, proto); - if (source < 0) - return CMD_WARNING_CONFIG_FAILED; + /* Get distribute source. */ + source = proto_redistnum(AFI_IP, proto); + if (source < 0) + return CMD_WARNING_CONFIG_FAILED; - return ospf_distribute_list_out_set (ospf, source, argv[idx_word]->arg); + return ospf_distribute_list_out_set(ospf, source, argv[idx_word]->arg); } DEFUN (no_ospf_distribute_list_out, @@ -7229,16 +7243,17 @@ DEFUN (no_ospf_distribute_list_out, OUT_STR FRR_REDIST_HELP_STR_OSPFD) { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_word = 2; - int source; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_word = 2; + int source; - char *proto = argv[argc - 1]->text; - source = proto_redistnum(AFI_IP, proto); - if (source < 0) - return CMD_WARNING_CONFIG_FAILED; + char *proto = argv[argc - 1]->text; + source = proto_redistnum(AFI_IP, proto); + if (source < 0) + return CMD_WARNING_CONFIG_FAILED; - return ospf_distribute_list_out_unset (ospf, source, argv[idx_word]->arg); + return ospf_distribute_list_out_unset(ospf, source, + argv[idx_word]->arg); } /* Default information originate. */ @@ -7255,36 +7270,36 @@ DEFUN (ospf_default_information_originate, "Route map reference\n" "Pointer to route-map entries\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int default_originate = DEFAULT_ORIGINATE_ZEBRA; - int type = -1; - int metric = -1; - struct ospf_redist *red; - int idx = 0; - - red = ospf_redist_add(ospf, DEFAULT_ROUTE, 0); - - /* Check whether "always" was specified */ - if (argv_find (argv, argc, "always", &idx)) - default_originate = DEFAULT_ORIGINATE_ALWAYS; - /* Get metric value */ - else if (argv_find (argv, argc, "(0-16777214)", &idx)) { - if (!str2metric (argv[idx]->arg, &metric)) - return CMD_WARNING_CONFIG_FAILED; - } - /* Get metric type. */ - else if (argv_find (argv, argc, "(1-2)", &idx)) { - if (!str2metric_type (argv[idx]->arg, &type)) - return CMD_WARNING_CONFIG_FAILED; - } - /* Get route-map */ - else if (argv_find (argv, argc, "WORD", &idx)) - ospf_routemap_set (red, argv[idx]->arg); - else - ospf_routemap_unset (red); - - return ospf_redistribute_default_set (ospf, default_originate, - type, metric); + VTY_DECLVAR_CONTEXT(ospf, ospf); + int default_originate = DEFAULT_ORIGINATE_ZEBRA; + int type = -1; + int metric = -1; + struct ospf_redist *red; + int idx = 0; + + red = ospf_redist_add(ospf, DEFAULT_ROUTE, 0); + + /* Check whether "always" was specified */ + if (argv_find(argv, argc, "always", &idx)) + default_originate = DEFAULT_ORIGINATE_ALWAYS; + /* Get metric value */ + else if (argv_find(argv, argc, "(0-16777214)", &idx)) { + if (!str2metric(argv[idx]->arg, &metric)) + return CMD_WARNING_CONFIG_FAILED; + } + /* Get metric type. */ + else if (argv_find(argv, argc, "(1-2)", &idx)) { + if (!str2metric_type(argv[idx]->arg, &type)) + return CMD_WARNING_CONFIG_FAILED; + } + /* Get route-map */ + else if (argv_find(argv, argc, "WORD", &idx)) + ospf_routemap_set(red, argv[idx]->arg); + else + ospf_routemap_unset(red); + + return ospf_redistribute_default_set(ospf, default_originate, type, + metric); } DEFUN (no_ospf_default_information_originate, @@ -7301,29 +7316,29 @@ DEFUN (no_ospf_default_information_originate, "Route map reference\n" "Pointer to route-map entries\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - struct prefix_ipv4 p; - struct ospf_external *ext; - struct ospf_redist *red; + VTY_DECLVAR_CONTEXT(ospf, ospf); + struct prefix_ipv4 p; + struct ospf_external *ext; + struct ospf_redist *red; - p.family = AF_INET; - p.prefix.s_addr = 0; - p.prefixlen = 0; + p.family = AF_INET; + p.prefix.s_addr = 0; + p.prefixlen = 0; - ospf_external_lsa_flush (ospf, DEFAULT_ROUTE, &p, 0); + ospf_external_lsa_flush(ospf, DEFAULT_ROUTE, &p, 0); - if ((ext = ospf_external_lookup(DEFAULT_ROUTE, 0)) && - EXTERNAL_INFO (ext)) { - ospf_external_info_delete (DEFAULT_ROUTE, 0, p); - ospf_external_del (DEFAULT_ROUTE, 0); - } + if ((ext = ospf_external_lookup(DEFAULT_ROUTE, 0)) + && EXTERNAL_INFO(ext)) { + ospf_external_info_delete(DEFAULT_ROUTE, 0, p); + ospf_external_del(DEFAULT_ROUTE, 0); + } - red = ospf_redist_lookup(ospf, DEFAULT_ROUTE, 0); - if (!red) - return CMD_SUCCESS; + red = ospf_redist_lookup(ospf, DEFAULT_ROUTE, 0); + if (!red) + return CMD_SUCCESS; - ospf_routemap_unset (red); - return ospf_redistribute_default_unset (ospf); + ospf_routemap_unset(red); + return ospf_redistribute_default_unset(ospf); } DEFUN (ospf_default_metric, @@ -7332,16 +7347,16 @@ DEFUN (ospf_default_metric, "Set metric of redistributed routes\n" "Default metric\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_number = 1; - int metric = -1; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_number = 1; + int metric = -1; - if (!str2metric (argv[idx_number]->arg, &metric)) - return CMD_WARNING_CONFIG_FAILED; + if (!str2metric(argv[idx_number]->arg, &metric)) + return CMD_WARNING_CONFIG_FAILED; - ospf->default_metric = metric; + ospf->default_metric = metric; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf_default_metric, @@ -7351,11 +7366,11 @@ DEFUN (no_ospf_default_metric, "Set metric of redistributed routes\n" "Default metric\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); + VTY_DECLVAR_CONTEXT(ospf, ospf); - ospf->default_metric = -1; + ospf->default_metric = -1; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -7365,12 +7380,12 @@ DEFUN (ospf_distance, "Administrative distance\n" "OSPF Administrative distance\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_number = 1; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_number = 1; - ospf->distance_all = atoi (argv[idx_number]->arg); + ospf->distance_all = atoi(argv[idx_number]->arg); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf_distance, @@ -7380,11 +7395,11 @@ DEFUN (no_ospf_distance, "Administrative distance\n" "OSPF Administrative distance\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); + VTY_DECLVAR_CONTEXT(ospf, ospf); - ospf->distance_all = 0; + ospf->distance_all = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ospf_distance_ospf, @@ -7400,20 +7415,20 @@ DEFUN (no_ospf_distance_ospf, "External routes\n" "Distance for external routes\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx = 0; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx = 0; - if (!ospf) - return CMD_SUCCESS; + if (!ospf) + return CMD_SUCCESS; - if (argv_find (argv, argc, "intra-area", &idx) || argc == 3) - idx = ospf->distance_intra = 0; - if (argv_find (argv, argc, "inter-area", &idx) || argc == 3) - idx = ospf->distance_inter = 0; - if (argv_find (argv, argc, "external", &idx) || argc == 3) - ospf->distance_external = 0; + if (argv_find(argv, argc, "intra-area", &idx) || argc == 3) + idx = ospf->distance_intra = 0; + if (argv_find(argv, argc, "inter-area", &idx) || argc == 3) + idx = ospf->distance_inter = 0; + if (argv_find(argv, argc, "external", &idx) || argc == 3) + ospf->distance_external = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ospf_distance_ospf, @@ -7428,19 +7443,19 @@ DEFUN (ospf_distance_ospf, "External routes\n" "Distance for external routes\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx = 0; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx = 0; - if (argv_find (argv, argc, "intra-area", &idx)) - ospf->distance_intra = atoi(argv[idx + 1]->arg); - idx = 0; - if (argv_find (argv, argc, "inter-area", &idx)) - ospf->distance_inter = atoi(argv[idx + 1]->arg); - idx = 0; - if (argv_find (argv, argc, "external", &idx)) - ospf->distance_external = atoi(argv[idx + 1]->arg); + if (argv_find(argv, argc, "intra-area", &idx)) + ospf->distance_intra = atoi(argv[idx + 1]->arg); + idx = 0; + if (argv_find(argv, argc, "inter-area", &idx)) + ospf->distance_inter = atoi(argv[idx + 1]->arg); + idx = 0; + if (argv_find(argv, argc, "external", &idx)) + ospf->distance_external = atoi(argv[idx + 1]->arg); - return CMD_SUCCESS; + return CMD_SUCCESS; } #if 0 @@ -7535,38 +7550,35 @@ DEFUN (ip_ospf_mtu_ignore, "Disable MTU mismatch detection on this interface\n" "Address of interface") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_ipv4 = 3; - struct in_addr addr; - int ret; - - struct ospf_if_params *params; - params = IF_DEF_PARAMS (ifp); - - if (argc == 4) - { - ret = inet_aton(argv[idx_ipv4]->arg, &addr); - if (!ret) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } - params = ospf_get_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } - params->mtu_ignore = 1; - if (params->mtu_ignore != OSPF_MTU_IGNORE_DEFAULT) - SET_IF_PARAM (params, mtu_ignore); - else - { - UNSET_IF_PARAM (params, mtu_ignore); - if (params != IF_DEF_PARAMS (ifp)) - { - ospf_free_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } - } - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_ipv4 = 3; + struct in_addr addr; + int ret; + + struct ospf_if_params *params; + params = IF_DEF_PARAMS(ifp); + + if (argc == 4) { + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + params->mtu_ignore = 1; + if (params->mtu_ignore != OSPF_MTU_IGNORE_DEFAULT) + SET_IF_PARAM(params, mtu_ignore); + else { + UNSET_IF_PARAM(params, mtu_ignore); + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + } + return CMD_SUCCESS; } DEFUN (no_ip_ospf_mtu_ignore, @@ -7577,38 +7589,35 @@ DEFUN (no_ip_ospf_mtu_ignore, "Disable MTU mismatch detection on this interface\n" "Address of interface") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_ipv4 = 4; - struct in_addr addr; - int ret; - - struct ospf_if_params *params; - params = IF_DEF_PARAMS (ifp); - - if (argc == 5) - { - ret = inet_aton(argv[idx_ipv4]->arg, &addr); - if (!ret) - { - vty_out (vty, "Please specify interface address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } - params = ospf_get_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } - params->mtu_ignore = 0; - if (params->mtu_ignore != OSPF_MTU_IGNORE_DEFAULT) - SET_IF_PARAM (params, mtu_ignore); - else - { - UNSET_IF_PARAM (params, mtu_ignore); - if (params != IF_DEF_PARAMS (ifp)) - { - ospf_free_if_params (ifp, addr); - ospf_if_update_params (ifp, addr); - } - } - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_ipv4 = 4; + struct in_addr addr; + int ret; + + struct ospf_if_params *params; + params = IF_DEF_PARAMS(ifp); + + if (argc == 5) { + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + params->mtu_ignore = 0; + if (params->mtu_ignore != OSPF_MTU_IGNORE_DEFAULT) + SET_IF_PARAM(params, mtu_ignore); + else { + UNSET_IF_PARAM(params, mtu_ignore); + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + } + return CMD_SUCCESS; } @@ -7619,22 +7628,22 @@ DEFUN (ospf_max_metric_router_lsa_admin, "Advertise own Router-LSA with infinite distance (stub router)\n" "Administratively applied, for an indefinite period\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - struct listnode *ln; - struct ospf_area *area; + VTY_DECLVAR_CONTEXT(ospf, ospf); + struct listnode *ln; + struct ospf_area *area; - for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area)) - { - SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED); - - if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED)) - ospf_router_lsa_update_area (area); - } + for (ALL_LIST_ELEMENTS_RO(ospf->areas, ln, area)) { + SET_FLAG(area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED); - /* Allows for areas configured later to get the property */ - ospf->stub_router_admin_set = OSPF_STUB_ROUTER_ADMINISTRATIVE_SET; + if (!CHECK_FLAG(area->stub_router_state, + OSPF_AREA_IS_STUB_ROUTED)) + ospf_router_lsa_update_area(area); + } - return CMD_SUCCESS; + /* Allows for areas configured later to get the property */ + ospf->stub_router_admin_set = OSPF_STUB_ROUTER_ADMINISTRATIVE_SET; + + return CMD_SUCCESS; } DEFUN (no_ospf_max_metric_router_lsa_admin, @@ -7645,24 +7654,25 @@ DEFUN (no_ospf_max_metric_router_lsa_admin, "Advertise own Router-LSA with infinite distance (stub router)\n" "Administratively applied, for an indefinite period\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - struct listnode *ln; - struct ospf_area *area; - - for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area)) - { - UNSET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED); - - /* Don't trample on the start-up stub timer */ - if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED) - && !area->t_stub_router) - { - UNSET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED); - ospf_router_lsa_update_area (area); - } - } - ospf->stub_router_admin_set = OSPF_STUB_ROUTER_ADMINISTRATIVE_UNSET; - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(ospf, ospf); + struct listnode *ln; + struct ospf_area *area; + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, ln, area)) { + UNSET_FLAG(area->stub_router_state, + OSPF_AREA_ADMIN_STUB_ROUTED); + + /* Don't trample on the start-up stub timer */ + if (CHECK_FLAG(area->stub_router_state, + OSPF_AREA_IS_STUB_ROUTED) + && !area->t_stub_router) { + UNSET_FLAG(area->stub_router_state, + OSPF_AREA_IS_STUB_ROUTED); + ospf_router_lsa_update_area(area); + } + } + ospf->stub_router_admin_set = OSPF_STUB_ROUTER_ADMINISTRATIVE_UNSET; + return CMD_SUCCESS; } DEFUN (ospf_max_metric_router_lsa_startup, @@ -7673,21 +7683,20 @@ DEFUN (ospf_max_metric_router_lsa_startup, "Automatically advertise stub Router-LSA on startup of OSPF\n" "Time (seconds) to advertise self as stub-router\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_number = 3; - unsigned int seconds; - - if (argc != 1) - { - vty_out (vty, "%% Must supply stub-router period"); - return CMD_WARNING_CONFIG_FAILED; - } - - seconds = strtoul(argv[idx_number]->arg, NULL, 10); - - ospf->stub_router_startup_time = seconds; - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_number = 3; + unsigned int seconds; + + if (argc != 1) { + vty_out(vty, "%% Must supply stub-router period"); + return CMD_WARNING_CONFIG_FAILED; + } + + seconds = strtoul(argv[idx_number]->arg, NULL, 10); + + ospf->stub_router_startup_time = seconds; + + return CMD_SUCCESS; } DEFUN (no_ospf_max_metric_router_lsa_startup, @@ -7699,25 +7708,26 @@ DEFUN (no_ospf_max_metric_router_lsa_startup, "Automatically advertise stub Router-LSA on startup of OSPF\n" "Time (seconds) to advertise self as stub-router\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - struct listnode *ln; - struct ospf_area *area; - - ospf->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED; - - for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area)) - { - SET_FLAG (area->stub_router_state, OSPF_AREA_WAS_START_STUB_ROUTED); - OSPF_TIMER_OFF (area->t_stub_router); - - /* Don't trample on admin stub routed */ - if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED)) - { - UNSET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED); - ospf_router_lsa_update_area (area); - } - } - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(ospf, ospf); + struct listnode *ln; + struct ospf_area *area; + + ospf->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED; + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, ln, area)) { + SET_FLAG(area->stub_router_state, + OSPF_AREA_WAS_START_STUB_ROUTED); + OSPF_TIMER_OFF(area->t_stub_router); + + /* Don't trample on admin stub routed */ + if (!CHECK_FLAG(area->stub_router_state, + OSPF_AREA_ADMIN_STUB_ROUTED)) { + UNSET_FLAG(area->stub_router_state, + OSPF_AREA_IS_STUB_ROUTED); + ospf_router_lsa_update_area(area); + } + } + return CMD_SUCCESS; } @@ -7729,21 +7739,20 @@ DEFUN (ospf_max_metric_router_lsa_shutdown, "Advertise stub-router prior to full shutdown of OSPF\n" "Time (seconds) to wait till full shutdown\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); - int idx_number = 3; - unsigned int seconds; - - if (argc != 1) - { - vty_out (vty, "%% Must supply stub-router shutdown period"); - return CMD_WARNING_CONFIG_FAILED; - } - - seconds = strtoul(argv[idx_number]->arg, NULL, 10); - - ospf->stub_router_shutdown_time = seconds; - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(ospf, ospf); + int idx_number = 3; + unsigned int seconds; + + if (argc != 1) { + vty_out(vty, "%% Must supply stub-router shutdown period"); + return CMD_WARNING_CONFIG_FAILED; + } + + seconds = strtoul(argv[idx_number]->arg, NULL, 10); + + ospf->stub_router_shutdown_time = seconds; + + return CMD_SUCCESS; } DEFUN (no_ospf_max_metric_router_lsa_shutdown, @@ -7755,203 +7764,236 @@ DEFUN (no_ospf_max_metric_router_lsa_shutdown, "Advertise stub-router prior to full shutdown of OSPF\n" "Time (seconds) to wait till full shutdown\n") { - VTY_DECLVAR_CONTEXT(ospf, ospf); + VTY_DECLVAR_CONTEXT(ospf, ospf); - ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED; - - return CMD_SUCCESS; + ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED; + + return CMD_SUCCESS; } -static void -config_write_stub_router (struct vty *vty, struct ospf *ospf) -{ - struct listnode *ln; - struct ospf_area *area; - - if (ospf->stub_router_startup_time != OSPF_STUB_ROUTER_UNCONFIGURED) - vty_out (vty, " max-metric router-lsa on-startup %u\n", - ospf->stub_router_startup_time); - if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED) - vty_out (vty, " max-metric router-lsa on-shutdown %u\n", - ospf->stub_router_shutdown_time); - for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area)) - { - if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED)) - { - vty_out (vty, " max-metric router-lsa administrative\n"); - break; - } - } - return; -} - -static void -show_ip_ospf_route_network (struct vty *vty, struct route_table *rt) -{ - struct route_node *rn; - struct ospf_route *or; - struct listnode *pnode, *pnnode; - struct ospf_path *path; - - vty_out (vty, "============ OSPF network routing table ============\n"); - - for (rn = route_top (rt); rn; rn = route_next (rn)) - if ((or = rn->info) != NULL) - { - char buf1[19]; - snprintf (buf1, 19, "%s/%d", - inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen); - - switch (or->path_type) - { - case OSPF_PATH_INTER_AREA: - if (or->type == OSPF_DESTINATION_NETWORK) - vty_out (vty, "N IA %-18s [%d] area: %s\n", buf1, or->cost, - inet_ntoa (or->u.std.area_id)); - else if (or->type == OSPF_DESTINATION_DISCARD) - vty_out (vty, "D IA %-18s Discard entry\n", buf1); - break; - case OSPF_PATH_INTRA_AREA: - vty_out (vty, "N %-18s [%d] area: %s\n", buf1, or->cost, - inet_ntoa (or->u.std.area_id)); - break; - default: - break; - } - - if (or->type == OSPF_DESTINATION_NETWORK) - for (ALL_LIST_ELEMENTS (or->paths, pnode, pnnode, path)) - { - if (if_lookup_by_index(path->ifindex, VRF_DEFAULT)) - { - if (path->nexthop.s_addr == 0) - vty_out (vty, "%24s directly attached to %s\n", - "", ifindex2ifname (path->ifindex, VRF_DEFAULT)); - else - vty_out (vty, "%24s via %s, %s\n", "", - inet_ntoa (path->nexthop), - ifindex2ifname (path->ifindex, VRF_DEFAULT)); - } - } - } - vty_out (vty, "\n"); -} - -static void -show_ip_ospf_route_router (struct vty *vty, struct route_table *rtrs) -{ - struct route_node *rn; - struct ospf_route *or; - struct listnode *pnode; - struct listnode *node; - struct ospf_path *path; - - vty_out (vty, "============ OSPF router routing table =============\n"); - for (rn = route_top (rtrs); rn; rn = route_next (rn)) - if (rn->info) - { - int flag = 0; - - vty_out (vty, "R %-15s ", inet_ntoa (rn->p.u.prefix4)); - - for (ALL_LIST_ELEMENTS_RO ((struct list *)rn->info, node, or)) - { - if (flag++) - vty_out (vty, "%24s", ""); - - /* Show path. */ - vty_out (vty, "%s [%d] area: %s", - (or->path_type == OSPF_PATH_INTER_AREA ? "IA" : " "), - or->cost, inet_ntoa (or->u.std.area_id)); - /* Show flags. */ - vty_out (vty, "%s%s\n", - (or->u.std.flags & ROUTER_LSA_BORDER ? ", ABR" : ""), - (or->u.std.flags & ROUTER_LSA_EXTERNAL ? ", ASBR" : "")); - - for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path)) - { - if (if_lookup_by_index(path->ifindex, VRF_DEFAULT)) - { - if (path->nexthop.s_addr == 0) - vty_out (vty, "%24s directly attached to %s\n", - "", ifindex2ifname (path->ifindex, VRF_DEFAULT)); - else - vty_out (vty, "%24s via %s, %s\n", "", - inet_ntoa (path->nexthop), - ifindex2ifname (path->ifindex, VRF_DEFAULT)); +static void config_write_stub_router(struct vty *vty, struct ospf *ospf) +{ + struct listnode *ln; + struct ospf_area *area; + + if (ospf->stub_router_startup_time != OSPF_STUB_ROUTER_UNCONFIGURED) + vty_out(vty, " max-metric router-lsa on-startup %u\n", + ospf->stub_router_startup_time); + if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED) + vty_out(vty, " max-metric router-lsa on-shutdown %u\n", + ospf->stub_router_shutdown_time); + for (ALL_LIST_ELEMENTS_RO(ospf->areas, ln, area)) { + if (CHECK_FLAG(area->stub_router_state, + OSPF_AREA_ADMIN_STUB_ROUTED)) { + vty_out(vty, " max-metric router-lsa administrative\n"); + break; + } + } + return; +} + +static void show_ip_ospf_route_network(struct vty *vty, struct route_table *rt) +{ + struct route_node *rn; + struct ospf_route * or ; + struct listnode *pnode, *pnnode; + struct ospf_path *path; + + vty_out(vty, "============ OSPF network routing table ============\n"); + + for (rn = route_top(rt); rn; rn = route_next(rn)) + if ((or = rn->info) != NULL) { + char buf1[19]; + snprintf(buf1, 19, "%s/%d", inet_ntoa(rn->p.u.prefix4), + rn->p.prefixlen); + + switch (or->path_type) { + case OSPF_PATH_INTER_AREA: + if (or->type == OSPF_DESTINATION_NETWORK) + vty_out(vty, + "N IA %-18s [%d] area: %s\n", + buf1, or->cost, + inet_ntoa(or->u.std.area_id)); + else if (or->type == OSPF_DESTINATION_DISCARD) + vty_out(vty, + "D IA %-18s Discard entry\n", + buf1); + break; + case OSPF_PATH_INTRA_AREA: + vty_out(vty, "N %-18s [%d] area: %s\n", + buf1, or->cost, + inet_ntoa(or->u.std.area_id)); + break; + default: + break; + } + + if (or->type == OSPF_DESTINATION_NETWORK) + for (ALL_LIST_ELEMENTS(or->paths, pnode, pnnode, + path)) { + if (if_lookup_by_index(path->ifindex, + VRF_DEFAULT)) { + if (path->nexthop.s_addr == 0) + vty_out(vty, + "%24s directly attached to %s\n", + "", + ifindex2ifname( + path->ifindex, + VRF_DEFAULT)); + else + vty_out(vty, + "%24s via %s, %s\n", + "", + inet_ntoa( + path->nexthop), + ifindex2ifname( + path->ifindex, + VRF_DEFAULT)); + } + } + } + vty_out(vty, "\n"); +} + +static void show_ip_ospf_route_router(struct vty *vty, struct route_table *rtrs) +{ + struct route_node *rn; + struct ospf_route * or ; + struct listnode *pnode; + struct listnode *node; + struct ospf_path *path; + + vty_out(vty, "============ OSPF router routing table =============\n"); + for (rn = route_top(rtrs); rn; rn = route_next(rn)) + if (rn->info) { + int flag = 0; + + vty_out(vty, "R %-15s ", + inet_ntoa(rn->p.u.prefix4)); + + for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node, + or)) { + if (flag++) + vty_out(vty, "%24s", ""); + + /* Show path. */ + vty_out(vty, "%s [%d] area: %s", + (or->path_type == OSPF_PATH_INTER_AREA + ? "IA" + : " "), + or->cost, inet_ntoa(or->u.std.area_id)); + /* Show flags. */ + vty_out(vty, "%s%s\n", + (or->u.std.flags & ROUTER_LSA_BORDER + ? ", ABR" + : ""), + (or->u.std.flags & ROUTER_LSA_EXTERNAL + ? ", ASBR" + : "")); + + for (ALL_LIST_ELEMENTS_RO(or->paths, pnode, + path)) { + if (if_lookup_by_index(path->ifindex, + VRF_DEFAULT)) { + if (path->nexthop.s_addr == 0) + vty_out(vty, + "%24s directly attached to %s\n", + "", + ifindex2ifname( + path->ifindex, + VRF_DEFAULT)); + else + vty_out(vty, + "%24s via %s, %s\n", + "", + inet_ntoa( + path->nexthop), + ifindex2ifname( + path->ifindex, + VRF_DEFAULT)); + } + } + } + } + vty_out(vty, "\n"); +} + +static void show_ip_ospf_route_external(struct vty *vty, struct route_table *rt) +{ + struct route_node *rn; + struct ospf_route *er; + struct listnode *pnode, *pnnode; + struct ospf_path *path; + + vty_out(vty, "============ OSPF external routing table ===========\n"); + for (rn = route_top(rt); rn; rn = route_next(rn)) + if ((er = rn->info) != NULL) { + char buf1[19]; + snprintf(buf1, 19, "%s/%d", inet_ntoa(rn->p.u.prefix4), + rn->p.prefixlen); + + switch (er->path_type) { + case OSPF_PATH_TYPE1_EXTERNAL: + vty_out(vty, + "N E1 %-18s [%d] tag: %" ROUTE_TAG_PRI + "\n", + buf1, er->cost, er->u.ext.tag); + break; + case OSPF_PATH_TYPE2_EXTERNAL: + vty_out(vty, + "N E2 %-18s [%d/%d] tag: %" ROUTE_TAG_PRI + "\n", + buf1, er->cost, er->u.ext.type2_cost, + er->u.ext.tag); + break; + } + + for (ALL_LIST_ELEMENTS(er->paths, pnode, pnnode, + path)) { + if (if_lookup_by_index(path->ifindex, + VRF_DEFAULT)) { + if (path->nexthop.s_addr == 0) + vty_out(vty, + "%24s directly attached to %s\n", + "", + ifindex2ifname( + path->ifindex, + VRF_DEFAULT)); + else + vty_out(vty, + "%24s via %s, %s\n", + "", + inet_ntoa( + path->nexthop), + ifindex2ifname( + path->ifindex, + VRF_DEFAULT)); + } } - } - } - } - vty_out (vty, "\n"); -} - -static void -show_ip_ospf_route_external (struct vty *vty, struct route_table *rt) -{ - struct route_node *rn; - struct ospf_route *er; - struct listnode *pnode, *pnnode; - struct ospf_path *path; - - vty_out (vty, "============ OSPF external routing table ===========\n"); - for (rn = route_top (rt); rn; rn = route_next (rn)) - if ((er = rn->info) != NULL) - { - char buf1[19]; - snprintf (buf1, 19, "%s/%d", - inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen); - - switch (er->path_type) - { - case OSPF_PATH_TYPE1_EXTERNAL: - vty_out (vty, "N E1 %-18s [%d] tag: %"ROUTE_TAG_PRI"\n", buf1, - er->cost, er->u.ext.tag); - break; - case OSPF_PATH_TYPE2_EXTERNAL: - vty_out (vty, "N E2 %-18s [%d/%d] tag: %"ROUTE_TAG_PRI"\n", buf1, er->cost, - er->u.ext.type2_cost, er->u.ext.tag); - break; - } - - for (ALL_LIST_ELEMENTS (er->paths, pnode, pnnode, path)) - { - if (if_lookup_by_index(path->ifindex, VRF_DEFAULT)) - { - if (path->nexthop.s_addr == 0) - vty_out (vty, "%24s directly attached to %s\n", - "", ifindex2ifname (path->ifindex, VRF_DEFAULT)); - else - vty_out (vty, "%24s via %s, %s\n", "", - inet_ntoa (path->nexthop), - ifindex2ifname (path->ifindex, VRF_DEFAULT)); - } - } - } - vty_out (vty, "\n"); + } + vty_out(vty, "\n"); } -static int -show_ip_ospf_border_routers_common (struct vty *vty, struct ospf *ospf) +static int show_ip_ospf_border_routers_common(struct vty *vty, + struct ospf *ospf) { - if (ospf->instance) - vty_out (vty, "\nOSPF Instance: %d\n\n", ospf->instance); + if (ospf->instance) + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); - if (ospf->new_table == NULL) - { - vty_out (vty, "No OSPF routing information exist\n"); - return CMD_SUCCESS; - } + if (ospf->new_table == NULL) { + vty_out(vty, "No OSPF routing information exist\n"); + return CMD_SUCCESS; + } - /* Show Network routes. - show_ip_ospf_route_network (vty, ospf->new_table); */ + /* Show Network routes. + show_ip_ospf_route_network (vty, ospf->new_table); */ - /* Show Router routes. */ - show_ip_ospf_route_router (vty, ospf->new_rtrs); + /* Show Router routes. */ + show_ip_ospf_route_router(vty, ospf->new_rtrs); - vty_out (vty, "\n"); + vty_out(vty, "\n"); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_ospf_border_routers, @@ -7962,12 +8004,12 @@ DEFUN (show_ip_ospf_border_routers, "OSPF information\n" "Show all the ABR's and ASBR's\n") { - struct ospf *ospf; + struct ospf *ospf; - if ((ospf = ospf_lookup ()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) + return CMD_SUCCESS; - return show_ip_ospf_border_routers_common(vty, ospf); + return show_ip_ospf_border_routers_common(vty, ospf); } DEFUN (show_ip_ospf_instance_border_routers, @@ -7979,41 +8021,40 @@ DEFUN (show_ip_ospf_instance_border_routers, "Instance ID\n" "Show all the ABR's and ASBR's\n") { - int idx_number = 3; - struct ospf *ospf; - u_short instance = 0; + int idx_number = 3; + struct ospf *ospf; + u_short instance = 0; - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if ((ospf = ospf_lookup_instance (instance)) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if ((ospf = ospf_lookup_instance(instance)) == NULL + || !ospf->oi_running) + return CMD_SUCCESS; - return show_ip_ospf_border_routers_common(vty, ospf); + return show_ip_ospf_border_routers_common(vty, ospf); } -static int -show_ip_ospf_route_common (struct vty *vty, struct ospf *ospf) +static int show_ip_ospf_route_common(struct vty *vty, struct ospf *ospf) { - if (ospf->instance) - vty_out (vty, "\nOSPF Instance: %d\n\n", ospf->instance); + if (ospf->instance) + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); - if (ospf->new_table == NULL) - { - vty_out (vty, "No OSPF routing information exist\n"); - return CMD_SUCCESS; - } + if (ospf->new_table == NULL) { + vty_out(vty, "No OSPF routing information exist\n"); + return CMD_SUCCESS; + } - /* Show Network routes. */ - show_ip_ospf_route_network (vty, ospf->new_table); + /* Show Network routes. */ + show_ip_ospf_route_network(vty, ospf->new_table); - /* Show Router routes. */ - show_ip_ospf_route_router (vty, ospf->new_rtrs); + /* Show Router routes. */ + show_ip_ospf_route_router(vty, ospf->new_rtrs); - /* Show AS External routes. */ - show_ip_ospf_route_external (vty, ospf->old_external_route); + /* Show AS External routes. */ + show_ip_ospf_route_external(vty, ospf->old_external_route); - vty_out (vty, "\n"); + vty_out(vty, "\n"); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_ospf_route, @@ -8024,12 +8065,12 @@ DEFUN (show_ip_ospf_route, "OSPF information\n" "OSPF routing table\n") { - struct ospf *ospf; + struct ospf *ospf; - if ((ospf = ospf_lookup ()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) + return CMD_SUCCESS; - return show_ip_ospf_route_common(vty, ospf); + return show_ip_ospf_route_common(vty, ospf); } DEFUN (show_ip_ospf_instance_route, @@ -8041,907 +8082,902 @@ DEFUN (show_ip_ospf_instance_route, "Instance ID\n" "OSPF routing table\n") { - int idx_number = 3; - struct ospf *ospf; - u_short instance = 0; + int idx_number = 3; + struct ospf *ospf; + u_short instance = 0; - instance = strtoul(argv[idx_number]->arg, NULL, 10); - if ((ospf = ospf_lookup_instance (instance)) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if ((ospf = ospf_lookup_instance(instance)) == NULL + || !ospf->oi_running) + return CMD_SUCCESS; - return show_ip_ospf_route_common(vty, ospf); + return show_ip_ospf_route_common(vty, ospf); } -const char *ospf_abr_type_str[] = -{ - "unknown", - "standard", - "ibm", - "cisco", - "shortcut" -}; +const char *ospf_abr_type_str[] = {"unknown", "standard", "ibm", "cisco", + "shortcut"}; -const char *ospf_shortcut_mode_str[] = -{ - "default", - "enable", - "disable" -}; +const char *ospf_shortcut_mode_str[] = {"default", "enable", "disable"}; -const char *ospf_int_type_str[] = -{ - "unknown", /* should never be used. */ - "point-to-point", - "broadcast", - "non-broadcast", - "point-to-multipoint", - "virtual-link", /* should never be used. */ - "loopback" -}; +const char *ospf_int_type_str[] = {"unknown", /* should never be used. */ + "point-to-point", "broadcast", + "non-broadcast", "point-to-multipoint", + "virtual-link", /* should never be used. */ + "loopback"}; /* Configuration write function for ospfd. */ -static int -config_write_interface (struct vty *vty) -{ - struct listnode *n1, *n2; - struct interface *ifp; - struct crypt_key *ck; - int write = 0; - struct route_node *rn = NULL; - struct ospf_if_params *params; - struct ospf *ospf = ospf_lookup(); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), n1, ifp)) - { - if (memcmp (ifp->name, "VLINK", 5) == 0) - continue; - - if (ifp->ifindex == IFINDEX_DELETED) - continue; - - vty_out (vty, "!\n"); - vty_out (vty, "interface %s\n", ifp->name); - if (ifp->desc) - vty_out (vty, " description %s\n", ifp->desc); - - write++; - - params = IF_DEF_PARAMS (ifp); - - do { - /* Interface Network print. */ - if (OSPF_IF_PARAM_CONFIGURED (params, type) && - params->type != OSPF_IFTYPE_LOOPBACK) - { - if (params->type != ospf_default_iftype(ifp)) - { - vty_out (vty, " ip ospf network %s", - ospf_int_type_str[params->type]); - if (params != IF_DEF_PARAMS (ifp)) - vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4)); - vty_out (vty, "\n"); - } - } - - /* OSPF interface authentication print */ - if (OSPF_IF_PARAM_CONFIGURED (params, auth_type) && - params->auth_type != OSPF_AUTH_NOTSET) - { - const char *auth_str; - - /* Translation tables are not that much help here due to syntax - of the simple option */ - switch (params->auth_type) - { - - case OSPF_AUTH_NULL: - auth_str = " null"; - break; - - case OSPF_AUTH_SIMPLE: - auth_str = ""; - break; - - case OSPF_AUTH_CRYPTOGRAPHIC: - auth_str = " message-digest"; - break; - - default: - auth_str = ""; - break; - } - - vty_out (vty, " ip ospf authentication%s", auth_str); - if (params != IF_DEF_PARAMS (ifp)) - vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4)); - vty_out (vty, "\n"); - } - - /* Simple Authentication Password print. */ - if (OSPF_IF_PARAM_CONFIGURED (params, auth_simple) && - params->auth_simple[0] != '\0') - { - vty_out (vty, " ip ospf authentication-key %s", - params->auth_simple); - if (params != IF_DEF_PARAMS (ifp)) - vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4)); - vty_out (vty, "\n"); - } - - /* Cryptographic Authentication Key print. */ - for (ALL_LIST_ELEMENTS_RO (params->auth_crypt, n2, ck)) - { - vty_out (vty, " ip ospf message-digest-key %d md5 %s", - ck->key_id, ck->auth_key); - if (params != IF_DEF_PARAMS (ifp)) - vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4)); - vty_out (vty, "\n"); - } - - /* Interface Output Cost print. */ - if (OSPF_IF_PARAM_CONFIGURED (params, output_cost_cmd)) - { - vty_out (vty, " ip ospf cost %u", params->output_cost_cmd); - if (params != IF_DEF_PARAMS (ifp)) - vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4)); - vty_out (vty, "\n"); - } - - /* Hello Interval print. */ - if (OSPF_IF_PARAM_CONFIGURED (params, v_hello) && - params->v_hello != OSPF_HELLO_INTERVAL_DEFAULT) - { - vty_out (vty, " ip ospf hello-interval %u", params->v_hello); - if (params != IF_DEF_PARAMS (ifp)) - vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4)); - vty_out (vty, "\n"); - } - - - /* Router Dead Interval print. */ - if (OSPF_IF_PARAM_CONFIGURED (params, v_wait) && - params->v_wait != OSPF_ROUTER_DEAD_INTERVAL_DEFAULT) - { - vty_out (vty, " ip ospf dead-interval "); - - /* fast hello ? */ - if (OSPF_IF_PARAM_CONFIGURED (params, fast_hello)) - vty_out (vty, "minimal hello-multiplier %d", - params->fast_hello); - else - vty_out (vty, "%u", params->v_wait); - - if (params != IF_DEF_PARAMS (ifp)) - vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4)); - vty_out (vty, "\n"); - } - - /* Router Priority print. */ - if (OSPF_IF_PARAM_CONFIGURED (params, priority) && - params->priority != OSPF_ROUTER_PRIORITY_DEFAULT) - { - vty_out (vty, " ip ospf priority %u", params->priority); - if (params != IF_DEF_PARAMS (ifp)) - vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4)); - vty_out (vty, "\n"); - } - - /* Retransmit Interval print. */ - if (OSPF_IF_PARAM_CONFIGURED (params, retransmit_interval) && - params->retransmit_interval != OSPF_RETRANSMIT_INTERVAL_DEFAULT) - { - vty_out (vty, " ip ospf retransmit-interval %u", - params->retransmit_interval); - if (params != IF_DEF_PARAMS (ifp)) - vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4)); - vty_out (vty, "\n"); - } - - /* Transmit Delay print. */ - if (OSPF_IF_PARAM_CONFIGURED (params, transmit_delay) && - params->transmit_delay != OSPF_TRANSMIT_DELAY_DEFAULT) - { - vty_out (vty, " ip ospf transmit-delay %u", params->transmit_delay); - if (params != IF_DEF_PARAMS (ifp)) - vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4)); - vty_out (vty, "\n"); - } - - /* Area print. */ - if (OSPF_IF_PARAM_CONFIGURED (params, if_area)) - { - if (ospf->instance) - vty_out (vty, " ip ospf %d", ospf->instance); - else - vty_out (vty, " ip ospf"); - - vty_out (vty, " area %s", inet_ntoa (params->if_area)); - if (params != IF_DEF_PARAMS (ifp)) - vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4)); - vty_out (vty, "\n"); - } - - /* bfd print. */ - ospf_bfd_write_config(vty, params); - - /* MTU ignore print. */ - if (OSPF_IF_PARAM_CONFIGURED (params, mtu_ignore) && - params->mtu_ignore != OSPF_MTU_IGNORE_DEFAULT) - { - if (params->mtu_ignore == 0) - vty_out (vty, " no ip ospf mtu-ignore"); - else - vty_out (vty, " ip ospf mtu-ignore"); - if (params != IF_DEF_PARAMS (ifp)) - vty_out (vty, " %s", inet_ntoa (rn->p.u.prefix4)); - vty_out (vty, "\n"); - } - - - while (1) - { - if (rn == NULL) - rn = route_top (IF_OIFS_PARAMS (ifp)); - else - rn = route_next (rn); - - if (rn == NULL) - break; - params = rn->info; - if (params != NULL) - break; - } - } while (rn); - - ospf_opaque_config_write_if (vty, ifp); - } - - return write; +static int config_write_interface(struct vty *vty) +{ + struct listnode *n1, *n2; + struct interface *ifp; + struct crypt_key *ck; + int write = 0; + struct route_node *rn = NULL; + struct ospf_if_params *params; + struct ospf *ospf = ospf_lookup(); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), n1, ifp)) { + if (memcmp(ifp->name, "VLINK", 5) == 0) + continue; + + if (ifp->ifindex == IFINDEX_DELETED) + continue; + + vty_out(vty, "!\n"); + vty_out(vty, "interface %s\n", ifp->name); + if (ifp->desc) + vty_out(vty, " description %s\n", ifp->desc); + + write++; + + params = IF_DEF_PARAMS(ifp); + + do { + /* Interface Network print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, type) + && params->type != OSPF_IFTYPE_LOOPBACK) { + if (params->type != ospf_default_iftype(ifp)) { + vty_out(vty, " ip ospf network %s", + ospf_int_type_str + [params->type]); + if (params != IF_DEF_PARAMS(ifp)) + vty_out(vty, " %s", + inet_ntoa( + rn->p.u.prefix4)); + vty_out(vty, "\n"); + } + } + + /* OSPF interface authentication print */ + if (OSPF_IF_PARAM_CONFIGURED(params, auth_type) + && params->auth_type != OSPF_AUTH_NOTSET) { + const char *auth_str; + + /* Translation tables are not that much help + here due to syntax + of the simple option */ + switch (params->auth_type) { + + case OSPF_AUTH_NULL: + auth_str = " null"; + break; + + case OSPF_AUTH_SIMPLE: + auth_str = ""; + break; + + case OSPF_AUTH_CRYPTOGRAPHIC: + auth_str = " message-digest"; + break; + + default: + auth_str = ""; + break; + } + + vty_out(vty, " ip ospf authentication%s", + auth_str); + if (params != IF_DEF_PARAMS(ifp)) + vty_out(vty, " %s", + inet_ntoa(rn->p.u.prefix4)); + vty_out(vty, "\n"); + } + + /* Simple Authentication Password print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, auth_simple) + && params->auth_simple[0] != '\0') { + vty_out(vty, " ip ospf authentication-key %s", + params->auth_simple); + if (params != IF_DEF_PARAMS(ifp)) + vty_out(vty, " %s", + inet_ntoa(rn->p.u.prefix4)); + vty_out(vty, "\n"); + } + + /* Cryptographic Authentication Key print. */ + for (ALL_LIST_ELEMENTS_RO(params->auth_crypt, n2, ck)) { + vty_out(vty, + " ip ospf message-digest-key %d md5 %s", + ck->key_id, ck->auth_key); + if (params != IF_DEF_PARAMS(ifp)) + vty_out(vty, " %s", + inet_ntoa(rn->p.u.prefix4)); + vty_out(vty, "\n"); + } + + /* Interface Output Cost print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, output_cost_cmd)) { + vty_out(vty, " ip ospf cost %u", + params->output_cost_cmd); + if (params != IF_DEF_PARAMS(ifp)) + vty_out(vty, " %s", + inet_ntoa(rn->p.u.prefix4)); + vty_out(vty, "\n"); + } + + /* Hello Interval print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, v_hello) + && params->v_hello != OSPF_HELLO_INTERVAL_DEFAULT) { + vty_out(vty, " ip ospf hello-interval %u", + params->v_hello); + if (params != IF_DEF_PARAMS(ifp)) + vty_out(vty, " %s", + inet_ntoa(rn->p.u.prefix4)); + vty_out(vty, "\n"); + } + + + /* Router Dead Interval print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, v_wait) + && params->v_wait + != OSPF_ROUTER_DEAD_INTERVAL_DEFAULT) { + vty_out(vty, " ip ospf dead-interval "); + + /* fast hello ? */ + if (OSPF_IF_PARAM_CONFIGURED(params, + fast_hello)) + vty_out(vty, + "minimal hello-multiplier %d", + params->fast_hello); + else + vty_out(vty, "%u", params->v_wait); + + if (params != IF_DEF_PARAMS(ifp)) + vty_out(vty, " %s", + inet_ntoa(rn->p.u.prefix4)); + vty_out(vty, "\n"); + } + + /* Router Priority print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, priority) + && params->priority + != OSPF_ROUTER_PRIORITY_DEFAULT) { + vty_out(vty, " ip ospf priority %u", + params->priority); + if (params != IF_DEF_PARAMS(ifp)) + vty_out(vty, " %s", + inet_ntoa(rn->p.u.prefix4)); + vty_out(vty, "\n"); + } + + /* Retransmit Interval print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, + retransmit_interval) + && params->retransmit_interval + != OSPF_RETRANSMIT_INTERVAL_DEFAULT) { + vty_out(vty, " ip ospf retransmit-interval %u", + params->retransmit_interval); + if (params != IF_DEF_PARAMS(ifp)) + vty_out(vty, " %s", + inet_ntoa(rn->p.u.prefix4)); + vty_out(vty, "\n"); + } + + /* Transmit Delay print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, transmit_delay) + && params->transmit_delay + != OSPF_TRANSMIT_DELAY_DEFAULT) { + vty_out(vty, " ip ospf transmit-delay %u", + params->transmit_delay); + if (params != IF_DEF_PARAMS(ifp)) + vty_out(vty, " %s", + inet_ntoa(rn->p.u.prefix4)); + vty_out(vty, "\n"); + } + + /* Area print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) { + if (ospf->instance) + vty_out(vty, " ip ospf %d", + ospf->instance); + else + vty_out(vty, " ip ospf"); + + vty_out(vty, " area %s", + inet_ntoa(params->if_area)); + if (params != IF_DEF_PARAMS(ifp)) + vty_out(vty, " %s", + inet_ntoa(rn->p.u.prefix4)); + vty_out(vty, "\n"); + } + + /* bfd print. */ + ospf_bfd_write_config(vty, params); + + /* MTU ignore print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, mtu_ignore) + && params->mtu_ignore != OSPF_MTU_IGNORE_DEFAULT) { + if (params->mtu_ignore == 0) + vty_out(vty, " no ip ospf mtu-ignore"); + else + vty_out(vty, " ip ospf mtu-ignore"); + if (params != IF_DEF_PARAMS(ifp)) + vty_out(vty, " %s", + inet_ntoa(rn->p.u.prefix4)); + vty_out(vty, "\n"); + } + + + while (1) { + if (rn == NULL) + rn = route_top(IF_OIFS_PARAMS(ifp)); + else + rn = route_next(rn); + + if (rn == NULL) + break; + params = rn->info; + if (params != NULL) + break; + } + } while (rn); + + ospf_opaque_config_write_if(vty, ifp); + } + + return write; } -static int -config_write_network_area (struct vty *vty, struct ospf *ospf) +static int config_write_network_area(struct vty *vty, struct ospf *ospf) { - struct route_node *rn; - u_char buf[INET_ADDRSTRLEN]; + struct route_node *rn; + u_char buf[INET_ADDRSTRLEN]; - /* `network area' print. */ - for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) - if (rn->info) - { - struct ospf_network *n = rn->info; + /* `network area' print. */ + for (rn = route_top(ospf->networks); rn; rn = route_next(rn)) + if (rn->info) { + struct ospf_network *n = rn->info; - memset (buf, 0, INET_ADDRSTRLEN); + memset(buf, 0, INET_ADDRSTRLEN); - /* Create Area ID string by specified Area ID format. */ - if (n->area_id_fmt == OSPF_AREA_ID_FMT_DOTTEDQUAD) - strncpy ((char *) buf, inet_ntoa (n->area_id), INET_ADDRSTRLEN); - else - sprintf ((char *) buf, "%lu", - (unsigned long int) ntohl (n->area_id.s_addr)); + /* Create Area ID string by specified Area ID format. */ + if (n->area_id_fmt == OSPF_AREA_ID_FMT_DOTTEDQUAD) + strncpy((char *)buf, inet_ntoa(n->area_id), + INET_ADDRSTRLEN); + else + sprintf((char *)buf, "%lu", + (unsigned long int)ntohl( + n->area_id.s_addr)); - /* Network print. */ - vty_out (vty, " network %s/%d area %s\n", - inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen, - buf); - } + /* Network print. */ + vty_out(vty, " network %s/%d area %s\n", + inet_ntoa(rn->p.u.prefix4), rn->p.prefixlen, + buf); + } - return 0; + return 0; } -static int -config_write_ospf_area (struct vty *vty, struct ospf *ospf) +static int config_write_ospf_area(struct vty *vty, struct ospf *ospf) { - struct listnode *node; - struct ospf_area *area; - u_char buf[INET_ADDRSTRLEN]; + struct listnode *node; + struct ospf_area *area; + u_char buf[INET_ADDRSTRLEN]; - /* Area configuration print. */ - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - struct route_node *rn1; + /* Area configuration print. */ + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + struct route_node *rn1; - area_id2str ((char *) buf, INET_ADDRSTRLEN, &area->area_id, - area->area_id_fmt); + area_id2str((char *)buf, INET_ADDRSTRLEN, &area->area_id, + area->area_id_fmt); - if (area->auth_type != OSPF_AUTH_NULL) - { - if (area->auth_type == OSPF_AUTH_SIMPLE) - vty_out (vty, " area %s authentication\n", buf); - else - vty_out (vty, " area %s authentication message-digest\n", - buf); - } + if (area->auth_type != OSPF_AUTH_NULL) { + if (area->auth_type == OSPF_AUTH_SIMPLE) + vty_out(vty, " area %s authentication\n", buf); + else + vty_out(vty, + " area %s authentication message-digest\n", + buf); + } - if (area->shortcut_configured != OSPF_SHORTCUT_DEFAULT) - vty_out (vty, " area %s shortcut %s\n", buf, - ospf_shortcut_mode_str[area->shortcut_configured]); + if (area->shortcut_configured != OSPF_SHORTCUT_DEFAULT) + vty_out(vty, " area %s shortcut %s\n", buf, + ospf_shortcut_mode_str + [area->shortcut_configured]); + + if ((area->external_routing == OSPF_AREA_STUB) + || (area->external_routing == OSPF_AREA_NSSA)) { + if (area->external_routing == OSPF_AREA_STUB) + vty_out(vty, " area %s stub", buf); + else if (area->external_routing == OSPF_AREA_NSSA) { + vty_out(vty, " area %s nssa", buf); + switch (area->NSSATranslatorRole) { + case OSPF_NSSA_ROLE_NEVER: + vty_out(vty, " translate-never"); + break; + case OSPF_NSSA_ROLE_ALWAYS: + vty_out(vty, " translate-always"); + break; + case OSPF_NSSA_ROLE_CANDIDATE: + default: + vty_out(vty, " translate-candidate"); + } + } - if ((area->external_routing == OSPF_AREA_STUB) - || (area->external_routing == OSPF_AREA_NSSA) - ) - { - if (area->external_routing == OSPF_AREA_STUB) - vty_out (vty, " area %s stub", buf); - else if (area->external_routing == OSPF_AREA_NSSA) - { - vty_out (vty, " area %s nssa", buf); - switch (area->NSSATranslatorRole) - { - case OSPF_NSSA_ROLE_NEVER: - vty_out (vty, " translate-never"); - break; - case OSPF_NSSA_ROLE_ALWAYS: - vty_out (vty, " translate-always"); - break; - case OSPF_NSSA_ROLE_CANDIDATE: - default: - vty_out (vty, " translate-candidate"); - } - } - - if (area->no_summary) - vty_out (vty, " no-summary"); - - vty_out (vty, "\n"); - - if (area->default_cost != 1) - vty_out (vty, " area %s default-cost %d\n", buf, - area->default_cost); - } - - for (rn1 = route_top (area->ranges); rn1; rn1 = route_next (rn1)) - if (rn1->info) - { - struct ospf_area_range *range = rn1->info; - - vty_out (vty, " area %s range %s/%d", buf, - inet_ntoa (rn1->p.u.prefix4), rn1->p.prefixlen); - - if (range->cost_config != OSPF_AREA_RANGE_COST_UNSPEC) - vty_out (vty, " cost %d", range->cost_config); - - if (!CHECK_FLAG (range->flags, OSPF_AREA_RANGE_ADVERTISE)) - vty_out (vty, " not-advertise"); - - if (CHECK_FLAG (range->flags, OSPF_AREA_RANGE_SUBSTITUTE)) - vty_out (vty, " substitute %s/%d", - inet_ntoa (range->subst_addr), range->subst_masklen); - - vty_out (vty, "\n"); - } - - if (EXPORT_NAME (area)) - vty_out (vty, " area %s export-list %s\n", buf, - EXPORT_NAME (area)); - - if (IMPORT_NAME (area)) - vty_out (vty, " area %s import-list %s\n", buf, - IMPORT_NAME (area)); - - if (PREFIX_NAME_IN (area)) - vty_out (vty, " area %s filter-list prefix %s in\n", buf, - PREFIX_NAME_IN (area)); - - if (PREFIX_NAME_OUT (area)) - vty_out (vty, " area %s filter-list prefix %s out\n", buf, - PREFIX_NAME_OUT (area)); - } + if (area->no_summary) + vty_out(vty, " no-summary"); - return 0; -} + vty_out(vty, "\n"); -static int -config_write_ospf_nbr_nbma (struct vty *vty, struct ospf *ospf) -{ - struct ospf_nbr_nbma *nbr_nbma; - struct route_node *rn; + if (area->default_cost != 1) + vty_out(vty, " area %s default-cost %d\n", buf, + area->default_cost); + } - /* Static Neighbor configuration print. */ - for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn)) - if ((nbr_nbma = rn->info)) - { - vty_out (vty, " neighbor %s", inet_ntoa (nbr_nbma->addr)); + for (rn1 = route_top(area->ranges); rn1; rn1 = route_next(rn1)) + if (rn1->info) { + struct ospf_area_range *range = rn1->info; - if (nbr_nbma->priority != OSPF_NEIGHBOR_PRIORITY_DEFAULT) - vty_out (vty, " priority %d", nbr_nbma->priority); + vty_out(vty, " area %s range %s/%d", buf, + inet_ntoa(rn1->p.u.prefix4), + rn1->p.prefixlen); - if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT) - vty_out (vty, " poll-interval %d", nbr_nbma->v_poll); + if (range->cost_config + != OSPF_AREA_RANGE_COST_UNSPEC) + vty_out(vty, " cost %d", + range->cost_config); - vty_out (vty, "\n"); - } + if (!CHECK_FLAG(range->flags, + OSPF_AREA_RANGE_ADVERTISE)) + vty_out(vty, " not-advertise"); - return 0; + if (CHECK_FLAG(range->flags, + OSPF_AREA_RANGE_SUBSTITUTE)) + vty_out(vty, " substitute %s/%d", + inet_ntoa(range->subst_addr), + range->subst_masklen); + + vty_out(vty, "\n"); + } + + if (EXPORT_NAME(area)) + vty_out(vty, " area %s export-list %s\n", buf, + EXPORT_NAME(area)); + + if (IMPORT_NAME(area)) + vty_out(vty, " area %s import-list %s\n", buf, + IMPORT_NAME(area)); + + if (PREFIX_NAME_IN(area)) + vty_out(vty, " area %s filter-list prefix %s in\n", buf, + PREFIX_NAME_IN(area)); + + if (PREFIX_NAME_OUT(area)) + vty_out(vty, " area %s filter-list prefix %s out\n", + buf, PREFIX_NAME_OUT(area)); + } + + return 0; } -static int -config_write_virtual_link (struct vty *vty, struct ospf *ospf) +static int config_write_ospf_nbr_nbma(struct vty *vty, struct ospf *ospf) { - struct listnode *node; - struct ospf_vl_data *vl_data; - char buf[INET_ADDRSTRLEN]; + struct ospf_nbr_nbma *nbr_nbma; + struct route_node *rn; - /* Virtual-Link print */ - for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data)) - { - struct listnode *n2; - struct crypt_key *ck; - struct ospf_interface *oi; + /* Static Neighbor configuration print. */ + for (rn = route_top(ospf->nbr_nbma); rn; rn = route_next(rn)) + if ((nbr_nbma = rn->info)) { + vty_out(vty, " neighbor %s", inet_ntoa(nbr_nbma->addr)); - if (vl_data != NULL) - { - memset (buf, 0, INET_ADDRSTRLEN); - - area_id2str (buf, sizeof(buf), &vl_data->vl_area_id, vl_data->vl_area_id_fmt); - oi = vl_data->vl_oi; - - /* timers */ - if (OSPF_IF_PARAM (oi, v_hello) != OSPF_HELLO_INTERVAL_DEFAULT || - OSPF_IF_PARAM (oi, v_wait) != OSPF_ROUTER_DEAD_INTERVAL_DEFAULT || - OSPF_IF_PARAM (oi, retransmit_interval) != OSPF_RETRANSMIT_INTERVAL_DEFAULT || - OSPF_IF_PARAM (oi, transmit_delay) != OSPF_TRANSMIT_DELAY_DEFAULT) - vty_out (vty, " area %s virtual-link %s hello-interval %d retransmit-interval %d transmit-delay %d dead-interval %d\n", - buf, - inet_ntoa (vl_data->vl_peer), - OSPF_IF_PARAM (oi, v_hello), - OSPF_IF_PARAM (oi, retransmit_interval), - OSPF_IF_PARAM (oi, transmit_delay), - OSPF_IF_PARAM (oi, v_wait)); - else - vty_out (vty, " area %s virtual-link %s\n", buf, - inet_ntoa (vl_data->vl_peer)); - /* Auth key */ - if (IF_DEF_PARAMS (vl_data->vl_oi->ifp)->auth_simple[0] != '\0') - vty_out (vty, " area %s virtual-link %s authentication-key %s\n", - buf, - inet_ntoa (vl_data->vl_peer), - IF_DEF_PARAMS (vl_data->vl_oi->ifp)->auth_simple); - /* md5 keys */ - for (ALL_LIST_ELEMENTS_RO (IF_DEF_PARAMS (vl_data->vl_oi->ifp)->auth_crypt, - n2, ck)) - vty_out (vty, " area %s virtual-link %s" - " message-digest-key %d md5 %s\n", - buf, - inet_ntoa (vl_data->vl_peer), - ck->key_id, ck->auth_key); - - } - } + if (nbr_nbma->priority + != OSPF_NEIGHBOR_PRIORITY_DEFAULT) + vty_out(vty, " priority %d", + nbr_nbma->priority); - return 0; + if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT) + vty_out(vty, " poll-interval %d", + nbr_nbma->v_poll); + + vty_out(vty, "\n"); + } + + return 0; +} + +static int config_write_virtual_link(struct vty *vty, struct ospf *ospf) +{ + struct listnode *node; + struct ospf_vl_data *vl_data; + char buf[INET_ADDRSTRLEN]; + + /* Virtual-Link print */ + for (ALL_LIST_ELEMENTS_RO(ospf->vlinks, node, vl_data)) { + struct listnode *n2; + struct crypt_key *ck; + struct ospf_interface *oi; + + if (vl_data != NULL) { + memset(buf, 0, INET_ADDRSTRLEN); + + area_id2str(buf, sizeof(buf), &vl_data->vl_area_id, + vl_data->vl_area_id_fmt); + oi = vl_data->vl_oi; + + /* timers */ + if (OSPF_IF_PARAM(oi, v_hello) + != OSPF_HELLO_INTERVAL_DEFAULT + || OSPF_IF_PARAM(oi, v_wait) + != OSPF_ROUTER_DEAD_INTERVAL_DEFAULT + || OSPF_IF_PARAM(oi, retransmit_interval) + != OSPF_RETRANSMIT_INTERVAL_DEFAULT + || OSPF_IF_PARAM(oi, transmit_delay) + != OSPF_TRANSMIT_DELAY_DEFAULT) + vty_out(vty, + " area %s virtual-link %s hello-interval %d retransmit-interval %d transmit-delay %d dead-interval %d\n", + buf, inet_ntoa(vl_data->vl_peer), + OSPF_IF_PARAM(oi, v_hello), + OSPF_IF_PARAM(oi, retransmit_interval), + OSPF_IF_PARAM(oi, transmit_delay), + OSPF_IF_PARAM(oi, v_wait)); + else + vty_out(vty, " area %s virtual-link %s\n", buf, + inet_ntoa(vl_data->vl_peer)); + /* Auth key */ + if (IF_DEF_PARAMS(vl_data->vl_oi->ifp)->auth_simple[0] + != '\0') + vty_out(vty, + " area %s virtual-link %s authentication-key %s\n", + buf, inet_ntoa(vl_data->vl_peer), + IF_DEF_PARAMS(vl_data->vl_oi->ifp) + ->auth_simple); + /* md5 keys */ + for (ALL_LIST_ELEMENTS_RO( + IF_DEF_PARAMS(vl_data->vl_oi->ifp) + ->auth_crypt, + n2, ck)) + vty_out(vty, + " area %s virtual-link %s" + " message-digest-key %d md5 %s\n", + buf, inet_ntoa(vl_data->vl_peer), + ck->key_id, ck->auth_key); + } + } + + return 0; } -static int -config_write_ospf_redistribute (struct vty *vty, struct ospf *ospf) +static int config_write_ospf_redistribute(struct vty *vty, struct ospf *ospf) { - int type; + int type; - /* redistribute print. */ - for (type = 0; type < ZEBRA_ROUTE_MAX; type++) - { - struct list *red_list; - struct listnode *node; - struct ospf_redist *red; + /* redistribute print. */ + for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { + struct list *red_list; + struct listnode *node; + struct ospf_redist *red; - red_list = ospf->redist[type]; - if (!red_list) - continue; + red_list = ospf->redist[type]; + if (!red_list) + continue; - for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) - { - vty_out (vty, " redistribute %s", zebra_route_string(type)); - if (red->instance) - vty_out (vty, " %d", red->instance); + for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { + vty_out(vty, " redistribute %s", + zebra_route_string(type)); + if (red->instance) + vty_out(vty, " %d", red->instance); - if (red->dmetric.value >= 0) - vty_out (vty, " metric %d", red->dmetric.value); + if (red->dmetric.value >= 0) + vty_out(vty, " metric %d", red->dmetric.value); - if (red->dmetric.type == EXTERNAL_METRIC_TYPE_1) - vty_out (vty, " metric-type 1"); + if (red->dmetric.type == EXTERNAL_METRIC_TYPE_1) + vty_out(vty, " metric-type 1"); - if (ROUTEMAP_NAME (red)) - vty_out (vty, " route-map %s", ROUTEMAP_NAME (red)); + if (ROUTEMAP_NAME(red)) + vty_out(vty, " route-map %s", + ROUTEMAP_NAME(red)); - vty_out (vty, "\n"); - } - } + vty_out(vty, "\n"); + } + } - return 0; + return 0; } -static int -config_write_ospf_default_metric (struct vty *vty, struct ospf *ospf) +static int config_write_ospf_default_metric(struct vty *vty, struct ospf *ospf) { - if (ospf->default_metric != -1) - vty_out (vty, " default-metric %d\n", ospf->default_metric); - return 0; + if (ospf->default_metric != -1) + vty_out(vty, " default-metric %d\n", ospf->default_metric); + return 0; } -static int -config_write_ospf_distribute (struct vty *vty, struct ospf *ospf) -{ - int type; - struct ospf_redist *red; - - if (ospf) - { - /* distribute-list print. */ - for (type = 0; type < ZEBRA_ROUTE_MAX; type++) - if (DISTRIBUTE_NAME (ospf, type)) - vty_out (vty, " distribute-list %s out %s\n", - DISTRIBUTE_NAME (ospf, type), - zebra_route_string(type)); - - /* default-information print. */ - if (ospf->default_originate != DEFAULT_ORIGINATE_NONE) - { - vty_out (vty, " default-information originate"); - if (ospf->default_originate == DEFAULT_ORIGINATE_ALWAYS) - vty_out (vty, " always"); +static int config_write_ospf_distribute(struct vty *vty, struct ospf *ospf) +{ + int type; + struct ospf_redist *red; - red = ospf_redist_lookup(ospf, DEFAULT_ROUTE, 0); - if (red) - { - if (red->dmetric.value >= 0) - vty_out (vty, " metric %d", - red->dmetric.value); - if (red->dmetric.type == EXTERNAL_METRIC_TYPE_1) - vty_out (vty, " metric-type 1"); + if (ospf) { + /* distribute-list print. */ + for (type = 0; type < ZEBRA_ROUTE_MAX; type++) + if (DISTRIBUTE_NAME(ospf, type)) + vty_out(vty, " distribute-list %s out %s\n", + DISTRIBUTE_NAME(ospf, type), + zebra_route_string(type)); - if (ROUTEMAP_NAME (red)) - vty_out (vty, " route-map %s", - ROUTEMAP_NAME (red)); - } - - vty_out (vty, "\n"); - } + /* default-information print. */ + if (ospf->default_originate != DEFAULT_ORIGINATE_NONE) { + vty_out(vty, " default-information originate"); + if (ospf->default_originate == DEFAULT_ORIGINATE_ALWAYS) + vty_out(vty, " always"); - } + red = ospf_redist_lookup(ospf, DEFAULT_ROUTE, 0); + if (red) { + if (red->dmetric.value >= 0) + vty_out(vty, " metric %d", + red->dmetric.value); + if (red->dmetric.type == EXTERNAL_METRIC_TYPE_1) + vty_out(vty, " metric-type 1"); - return 0; + if (ROUTEMAP_NAME(red)) + vty_out(vty, " route-map %s", + ROUTEMAP_NAME(red)); + } + + vty_out(vty, "\n"); + } + } + + return 0; } -static int -config_write_ospf_distance (struct vty *vty, struct ospf *ospf) -{ - struct route_node *rn; - struct ospf_distance *odistance; - - if (ospf->distance_all) - vty_out (vty, " distance %d\n", ospf->distance_all); - - if (ospf->distance_intra - || ospf->distance_inter - || ospf->distance_external) - { - vty_out (vty, " distance ospf"); - - if (ospf->distance_intra) - vty_out (vty, " intra-area %d", ospf->distance_intra); - if (ospf->distance_inter) - vty_out (vty, " inter-area %d", ospf->distance_inter); - if (ospf->distance_external) - vty_out (vty, " external %d", ospf->distance_external); - - vty_out (vty, "\n"); - } - - for (rn = route_top (ospf->distance_table); rn; rn = route_next (rn)) - if ((odistance = rn->info) != NULL) - { - vty_out (vty, " distance %d %s/%d %s\n", odistance->distance, - inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen, - odistance->access_list ? odistance->access_list : ""); - } - return 0; +static int config_write_ospf_distance(struct vty *vty, struct ospf *ospf) +{ + struct route_node *rn; + struct ospf_distance *odistance; + + if (ospf->distance_all) + vty_out(vty, " distance %d\n", ospf->distance_all); + + if (ospf->distance_intra || ospf->distance_inter + || ospf->distance_external) { + vty_out(vty, " distance ospf"); + + if (ospf->distance_intra) + vty_out(vty, " intra-area %d", ospf->distance_intra); + if (ospf->distance_inter) + vty_out(vty, " inter-area %d", ospf->distance_inter); + if (ospf->distance_external) + vty_out(vty, " external %d", ospf->distance_external); + + vty_out(vty, "\n"); + } + + for (rn = route_top(ospf->distance_table); rn; rn = route_next(rn)) + if ((odistance = rn->info) != NULL) { + vty_out(vty, " distance %d %s/%d %s\n", + odistance->distance, inet_ntoa(rn->p.u.prefix4), + rn->p.prefixlen, + odistance->access_list ? odistance->access_list + : ""); + } + return 0; } /* OSPF configuration write function. */ -static int -ospf_config_write (struct vty *vty) -{ - struct ospf *ospf; - struct interface *ifp; - struct ospf_interface *oi; - struct listnode *node; - int write = 0; - - ospf = ospf_lookup (); - if (ospf != NULL && ospf->oi_running) - { - /* `router ospf' print. */ - if (ospf->instance) - vty_out (vty, "router ospf %d\n", ospf->instance); - else - vty_out (vty, "router ospf\n"); - - write++; - - if (!ospf->networks) - return write; - - /* Router ID print. */ - if (ospf->router_id_static.s_addr != 0) - vty_out (vty, " ospf router-id %s\n", - inet_ntoa (ospf->router_id_static)); - - /* ABR type print. */ - if (ospf->abr_type != OSPF_ABR_DEFAULT) - vty_out (vty, " ospf abr-type %s\n", - ospf_abr_type_str[ospf->abr_type]); - - /* log-adjacency-changes flag print. */ - if (CHECK_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES)) - { - if (CHECK_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) - vty_out(vty, " log-adjacency-changes detail\n"); - else if (!DFLT_OSPF_LOG_ADJACENCY_CHANGES) - vty_out(vty, " log-adjacency-changes\n"); - } - else if (DFLT_OSPF_LOG_ADJACENCY_CHANGES) - { - vty_out(vty, " no log-adjacency-changes\n"); - } - - /* RFC1583 compatibility flag print -- Compatible with CISCO 12.1. */ - if (CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE)) - vty_out (vty, " compatible rfc1583\n"); - - /* auto-cost reference-bandwidth configuration. */ - if (ospf->ref_bandwidth != OSPF_DEFAULT_REF_BANDWIDTH) - { - vty_out (vty, "! Important: ensure reference bandwidth " - "is consistent across all routers\n"); - vty_out (vty, " auto-cost reference-bandwidth %d\n", - ospf->ref_bandwidth); - } - - /* SPF timers print. */ - if (ospf->spf_delay != OSPF_SPF_DELAY_DEFAULT || - ospf->spf_holdtime != OSPF_SPF_HOLDTIME_DEFAULT || - ospf->spf_max_holdtime != OSPF_SPF_MAX_HOLDTIME_DEFAULT) - vty_out (vty, " timers throttle spf %d %d %d\n", - ospf->spf_delay, ospf->spf_holdtime, - ospf->spf_max_holdtime); - - /* LSA timers print. */ - if (ospf->min_ls_interval != OSPF_MIN_LS_INTERVAL) - vty_out (vty, " timers throttle lsa all %d\n", - ospf->min_ls_interval); - if (ospf->min_ls_arrival != OSPF_MIN_LS_ARRIVAL) - vty_out (vty, " timers lsa min-arrival %d\n", - ospf->min_ls_arrival); - - /* Write multiplier print. */ - if (ospf->write_oi_count != OSPF_WRITE_INTERFACE_COUNT_DEFAULT) - vty_out (vty, " ospf write-multiplier %d\n", - ospf->write_oi_count); - - /* Max-metric router-lsa print */ - config_write_stub_router (vty, ospf); - - /* SPF refresh parameters print. */ - if (ospf->lsa_refresh_interval != OSPF_LSA_REFRESH_INTERVAL_DEFAULT) - vty_out (vty, " refresh timer %d\n", - ospf->lsa_refresh_interval); - - /* Redistribute information print. */ - config_write_ospf_redistribute (vty, ospf); - - /* passive-interface print. */ - if (ospf->passive_interface_default == OSPF_IF_PASSIVE) - vty_out (vty, " passive-interface default\n"); - - for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp)) - if (OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), passive_interface) - && IF_DEF_PARAMS (ifp)->passive_interface != - ospf->passive_interface_default) - { - vty_out (vty, " %spassive-interface %s\n", - IF_DEF_PARAMS (ifp)->passive_interface ? "" : "no ", - ifp->name); - } - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) - { - if (!OSPF_IF_PARAM_CONFIGURED (oi->params, passive_interface)) - continue; - if (OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (oi->ifp), - passive_interface)) - { - if (oi->params->passive_interface == IF_DEF_PARAMS (oi->ifp)->passive_interface) - continue; - } - else if (oi->params->passive_interface == ospf->passive_interface_default) - continue; - - vty_out (vty, " %spassive-interface %s %s\n", - oi->params->passive_interface ? "" : "no ", - oi->ifp->name, - inet_ntoa (oi->address->u.prefix4)); - } - - /* Network area print. */ - config_write_network_area (vty, ospf); - - /* Area config print. */ - config_write_ospf_area (vty, ospf); - - /* static neighbor print. */ - config_write_ospf_nbr_nbma (vty, ospf); - - /* Virtual-Link print. */ - config_write_virtual_link (vty, ospf); - - /* Default metric configuration. */ - config_write_ospf_default_metric (vty, ospf); - - /* Distribute-list and default-information print. */ - config_write_ospf_distribute (vty, ospf); - - /* Distance configuration. */ - config_write_ospf_distance (vty, ospf); - - ospf_opaque_config_write_router (vty, ospf); - } - - return write; -} - -void -ospf_vty_show_init (void) -{ - /* "show ip ospf" commands. */ - install_element (VIEW_NODE, &show_ip_ospf_cmd); - - install_element (VIEW_NODE, &show_ip_ospf_instance_cmd); - - /* "show ip ospf database" commands. */ - install_element (VIEW_NODE, &show_ip_ospf_database_max_cmd); - - install_element (VIEW_NODE, &show_ip_ospf_instance_database_type_adv_router_cmd); - install_element (VIEW_NODE, &show_ip_ospf_instance_database_cmd); - install_element (VIEW_NODE, &show_ip_ospf_instance_database_max_cmd); - - /* "show ip ospf interface" commands. */ - install_element (VIEW_NODE, &show_ip_ospf_interface_cmd); - - install_element (VIEW_NODE, &show_ip_ospf_instance_interface_cmd); - - /* "show ip ospf neighbor" commands. */ - install_element (VIEW_NODE, &show_ip_ospf_neighbor_int_detail_cmd); - install_element (VIEW_NODE, &show_ip_ospf_neighbor_int_cmd); - install_element (VIEW_NODE, &show_ip_ospf_neighbor_id_cmd); - install_element (VIEW_NODE, &show_ip_ospf_neighbor_detail_all_cmd); - install_element (VIEW_NODE, &show_ip_ospf_neighbor_detail_cmd); - install_element (VIEW_NODE, &show_ip_ospf_neighbor_cmd); - install_element (VIEW_NODE, &show_ip_ospf_neighbor_all_cmd); - - install_element (VIEW_NODE, &show_ip_ospf_instance_neighbor_int_detail_cmd); - install_element (VIEW_NODE, &show_ip_ospf_instance_neighbor_int_cmd); - install_element (VIEW_NODE, &show_ip_ospf_instance_neighbor_id_cmd); - install_element (VIEW_NODE, &show_ip_ospf_instance_neighbor_detail_all_cmd); - install_element (VIEW_NODE, &show_ip_ospf_instance_neighbor_detail_cmd); - install_element (VIEW_NODE, &show_ip_ospf_instance_neighbor_cmd); - install_element (VIEW_NODE, &show_ip_ospf_instance_neighbor_all_cmd); - - /* "show ip ospf route" commands. */ - install_element (VIEW_NODE, &show_ip_ospf_route_cmd); - install_element (VIEW_NODE, &show_ip_ospf_border_routers_cmd); - - install_element (VIEW_NODE, &show_ip_ospf_instance_route_cmd); - install_element (VIEW_NODE, &show_ip_ospf_instance_border_routers_cmd); +static int ospf_config_write(struct vty *vty) +{ + struct ospf *ospf; + struct interface *ifp; + struct ospf_interface *oi; + struct listnode *node; + int write = 0; + + ospf = ospf_lookup(); + if (ospf != NULL && ospf->oi_running) { + /* `router ospf' print. */ + if (ospf->instance) + vty_out(vty, "router ospf %d\n", ospf->instance); + else + vty_out(vty, "router ospf\n"); + + write++; + + if (!ospf->networks) + return write; + + /* Router ID print. */ + if (ospf->router_id_static.s_addr != 0) + vty_out(vty, " ospf router-id %s\n", + inet_ntoa(ospf->router_id_static)); + + /* ABR type print. */ + if (ospf->abr_type != OSPF_ABR_DEFAULT) + vty_out(vty, " ospf abr-type %s\n", + ospf_abr_type_str[ospf->abr_type]); + + /* log-adjacency-changes flag print. */ + if (CHECK_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES)) { + if (CHECK_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) + vty_out(vty, " log-adjacency-changes detail\n"); + else if (!DFLT_OSPF_LOG_ADJACENCY_CHANGES) + vty_out(vty, " log-adjacency-changes\n"); + } else if (DFLT_OSPF_LOG_ADJACENCY_CHANGES) { + vty_out(vty, " no log-adjacency-changes\n"); + } + + /* RFC1583 compatibility flag print -- Compatible with CISCO + * 12.1. */ + if (CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) + vty_out(vty, " compatible rfc1583\n"); + + /* auto-cost reference-bandwidth configuration. */ + if (ospf->ref_bandwidth != OSPF_DEFAULT_REF_BANDWIDTH) { + vty_out(vty, + "! Important: ensure reference bandwidth " + "is consistent across all routers\n"); + vty_out(vty, " auto-cost reference-bandwidth %d\n", + ospf->ref_bandwidth); + } + + /* SPF timers print. */ + if (ospf->spf_delay != OSPF_SPF_DELAY_DEFAULT + || ospf->spf_holdtime != OSPF_SPF_HOLDTIME_DEFAULT + || ospf->spf_max_holdtime != OSPF_SPF_MAX_HOLDTIME_DEFAULT) + vty_out(vty, " timers throttle spf %d %d %d\n", + ospf->spf_delay, ospf->spf_holdtime, + ospf->spf_max_holdtime); + + /* LSA timers print. */ + if (ospf->min_ls_interval != OSPF_MIN_LS_INTERVAL) + vty_out(vty, " timers throttle lsa all %d\n", + ospf->min_ls_interval); + if (ospf->min_ls_arrival != OSPF_MIN_LS_ARRIVAL) + vty_out(vty, " timers lsa min-arrival %d\n", + ospf->min_ls_arrival); + + /* Write multiplier print. */ + if (ospf->write_oi_count != OSPF_WRITE_INTERFACE_COUNT_DEFAULT) + vty_out(vty, " ospf write-multiplier %d\n", + ospf->write_oi_count); + + /* Max-metric router-lsa print */ + config_write_stub_router(vty, ospf); + + /* SPF refresh parameters print. */ + if (ospf->lsa_refresh_interval + != OSPF_LSA_REFRESH_INTERVAL_DEFAULT) + vty_out(vty, " refresh timer %d\n", + ospf->lsa_refresh_interval); + + /* Redistribute information print. */ + config_write_ospf_redistribute(vty, ospf); + + /* passive-interface print. */ + if (ospf->passive_interface_default == OSPF_IF_PASSIVE) + vty_out(vty, " passive-interface default\n"); + + for (ALL_LIST_ELEMENTS_RO(om->iflist, node, ifp)) + if (OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(ifp), + passive_interface) + && IF_DEF_PARAMS(ifp)->passive_interface + != ospf->passive_interface_default) { + vty_out(vty, " %spassive-interface %s\n", + IF_DEF_PARAMS(ifp)->passive_interface + ? "" + : "no ", + ifp->name); + } + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { + if (!OSPF_IF_PARAM_CONFIGURED(oi->params, + passive_interface)) + continue; + if (OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(oi->ifp), + passive_interface)) { + if (oi->params->passive_interface + == IF_DEF_PARAMS(oi->ifp) + ->passive_interface) + continue; + } else if (oi->params->passive_interface + == ospf->passive_interface_default) + continue; + + vty_out(vty, " %spassive-interface %s %s\n", + oi->params->passive_interface ? "" : "no ", + oi->ifp->name, + inet_ntoa(oi->address->u.prefix4)); + } + + /* Network area print. */ + config_write_network_area(vty, ospf); + + /* Area config print. */ + config_write_ospf_area(vty, ospf); + + /* static neighbor print. */ + config_write_ospf_nbr_nbma(vty, ospf); + + /* Virtual-Link print. */ + config_write_virtual_link(vty, ospf); + + /* Default metric configuration. */ + config_write_ospf_default_metric(vty, ospf); + + /* Distribute-list and default-information print. */ + config_write_ospf_distribute(vty, ospf); + + /* Distance configuration. */ + config_write_ospf_distance(vty, ospf); + + ospf_opaque_config_write_router(vty, ospf); + } + + return write; +} + +void ospf_vty_show_init(void) +{ + /* "show ip ospf" commands. */ + install_element(VIEW_NODE, &show_ip_ospf_cmd); + + install_element(VIEW_NODE, &show_ip_ospf_instance_cmd); + + /* "show ip ospf database" commands. */ + install_element(VIEW_NODE, &show_ip_ospf_database_max_cmd); + + install_element(VIEW_NODE, + &show_ip_ospf_instance_database_type_adv_router_cmd); + install_element(VIEW_NODE, &show_ip_ospf_instance_database_cmd); + install_element(VIEW_NODE, &show_ip_ospf_instance_database_max_cmd); + + /* "show ip ospf interface" commands. */ + install_element(VIEW_NODE, &show_ip_ospf_interface_cmd); + + install_element(VIEW_NODE, &show_ip_ospf_instance_interface_cmd); + + /* "show ip ospf neighbor" commands. */ + install_element(VIEW_NODE, &show_ip_ospf_neighbor_int_detail_cmd); + install_element(VIEW_NODE, &show_ip_ospf_neighbor_int_cmd); + install_element(VIEW_NODE, &show_ip_ospf_neighbor_id_cmd); + install_element(VIEW_NODE, &show_ip_ospf_neighbor_detail_all_cmd); + install_element(VIEW_NODE, &show_ip_ospf_neighbor_detail_cmd); + install_element(VIEW_NODE, &show_ip_ospf_neighbor_cmd); + install_element(VIEW_NODE, &show_ip_ospf_neighbor_all_cmd); + + install_element(VIEW_NODE, + &show_ip_ospf_instance_neighbor_int_detail_cmd); + install_element(VIEW_NODE, &show_ip_ospf_instance_neighbor_int_cmd); + install_element(VIEW_NODE, &show_ip_ospf_instance_neighbor_id_cmd); + install_element(VIEW_NODE, + &show_ip_ospf_instance_neighbor_detail_all_cmd); + install_element(VIEW_NODE, &show_ip_ospf_instance_neighbor_detail_cmd); + install_element(VIEW_NODE, &show_ip_ospf_instance_neighbor_cmd); + install_element(VIEW_NODE, &show_ip_ospf_instance_neighbor_all_cmd); + + /* "show ip ospf route" commands. */ + install_element(VIEW_NODE, &show_ip_ospf_route_cmd); + install_element(VIEW_NODE, &show_ip_ospf_border_routers_cmd); + + install_element(VIEW_NODE, &show_ip_ospf_instance_route_cmd); + install_element(VIEW_NODE, &show_ip_ospf_instance_border_routers_cmd); } /* ospfd's interface node. */ -static struct cmd_node interface_node = -{ - INTERFACE_NODE, - "%s(config-if)# ", - 1 -}; +static struct cmd_node interface_node = {INTERFACE_NODE, "%s(config-if)# ", 1}; /* Initialization of OSPF interface. */ -static void -ospf_vty_if_init (void) -{ - /* Install interface node. */ - install_node (&interface_node, config_write_interface); - if_cmd_init (); - - /* "ip ospf authentication" commands. */ - install_element (INTERFACE_NODE, &ip_ospf_authentication_args_addr_cmd); - install_element (INTERFACE_NODE, &ip_ospf_authentication_addr_cmd); - install_element (INTERFACE_NODE, &no_ip_ospf_authentication_args_addr_cmd); - install_element (INTERFACE_NODE, &no_ip_ospf_authentication_addr_cmd); - install_element (INTERFACE_NODE, &ip_ospf_authentication_key_addr_cmd); - install_element (INTERFACE_NODE, &no_ip_ospf_authentication_key_authkey_addr_cmd); - install_element (INTERFACE_NODE, &no_ospf_authentication_key_authkey_addr_cmd); - - /* "ip ospf message-digest-key" commands. */ - install_element (INTERFACE_NODE, &ip_ospf_message_digest_key_cmd); - install_element (INTERFACE_NODE, &no_ip_ospf_message_digest_key_cmd); - - /* "ip ospf cost" commands. */ - install_element (INTERFACE_NODE, &ip_ospf_cost_cmd); - install_element (INTERFACE_NODE, &no_ip_ospf_cost_cmd); - - /* "ip ospf mtu-ignore" commands. */ - install_element (INTERFACE_NODE, &ip_ospf_mtu_ignore_addr_cmd); - install_element (INTERFACE_NODE, &no_ip_ospf_mtu_ignore_addr_cmd); - - /* "ip ospf dead-interval" commands. */ - install_element (INTERFACE_NODE, &ip_ospf_dead_interval_cmd); - install_element (INTERFACE_NODE, &ip_ospf_dead_interval_minimal_addr_cmd); - install_element (INTERFACE_NODE, &no_ip_ospf_dead_interval_cmd); - - /* "ip ospf hello-interval" commands. */ - install_element (INTERFACE_NODE, &ip_ospf_hello_interval_cmd); - install_element (INTERFACE_NODE, &no_ip_ospf_hello_interval_cmd); - - /* "ip ospf network" commands. */ - install_element (INTERFACE_NODE, &ip_ospf_network_cmd); - install_element (INTERFACE_NODE, &no_ip_ospf_network_cmd); - - /* "ip ospf priority" commands. */ - install_element (INTERFACE_NODE, &ip_ospf_priority_cmd); - install_element (INTERFACE_NODE, &no_ip_ospf_priority_cmd); - - /* "ip ospf retransmit-interval" commands. */ - install_element (INTERFACE_NODE, &ip_ospf_retransmit_interval_addr_cmd); - install_element (INTERFACE_NODE, &no_ip_ospf_retransmit_interval_addr_cmd); - - /* "ip ospf transmit-delay" commands. */ - install_element (INTERFACE_NODE, &ip_ospf_transmit_delay_addr_cmd); - install_element (INTERFACE_NODE, &no_ip_ospf_transmit_delay_addr_cmd); - - /* "ip ospf area" commands. */ - install_element (INTERFACE_NODE, &ip_ospf_area_cmd); - install_element (INTERFACE_NODE, &no_ip_ospf_area_cmd); - - /* These commands are compatibitliy for previous version. */ - install_element (INTERFACE_NODE, &ospf_authentication_key_cmd); - install_element (INTERFACE_NODE, &ospf_message_digest_key_cmd); - install_element (INTERFACE_NODE, &no_ospf_message_digest_key_cmd); - install_element (INTERFACE_NODE, &ospf_dead_interval_cmd); - install_element (INTERFACE_NODE, &no_ospf_dead_interval_cmd); - install_element (INTERFACE_NODE, &ospf_hello_interval_cmd); - install_element (INTERFACE_NODE, &no_ospf_hello_interval_cmd); - install_element (INTERFACE_NODE, &ospf_cost_cmd); - install_element (INTERFACE_NODE, &no_ospf_cost_cmd); - install_element (INTERFACE_NODE, &ospf_network_cmd); - install_element (INTERFACE_NODE, &no_ospf_network_cmd); - install_element (INTERFACE_NODE, &ospf_priority_cmd); - install_element (INTERFACE_NODE, &no_ospf_priority_cmd); - install_element (INTERFACE_NODE, &ospf_retransmit_interval_cmd); - install_element (INTERFACE_NODE, &no_ospf_retransmit_interval_cmd); - install_element (INTERFACE_NODE, &ospf_transmit_delay_cmd); - install_element (INTERFACE_NODE, &no_ospf_transmit_delay_cmd); -} - -static void -ospf_vty_zebra_init (void) -{ - install_element (OSPF_NODE, &ospf_redistribute_source_cmd); - install_element (OSPF_NODE, &no_ospf_redistribute_source_cmd); - install_element (OSPF_NODE, &ospf_redistribute_instance_source_cmd); - install_element (OSPF_NODE, &no_ospf_redistribute_instance_source_cmd); - - install_element (OSPF_NODE, &ospf_distribute_list_out_cmd); - install_element (OSPF_NODE, &no_ospf_distribute_list_out_cmd); - - install_element (OSPF_NODE, &ospf_default_information_originate_cmd); - install_element (OSPF_NODE, &no_ospf_default_information_originate_cmd); - - install_element (OSPF_NODE, &ospf_default_metric_cmd); - install_element (OSPF_NODE, &no_ospf_default_metric_cmd); - - install_element (OSPF_NODE, &ospf_distance_cmd); - install_element (OSPF_NODE, &no_ospf_distance_cmd); - install_element (OSPF_NODE, &no_ospf_distance_ospf_cmd); - install_element (OSPF_NODE, &ospf_distance_ospf_cmd); +static void ospf_vty_if_init(void) +{ + /* Install interface node. */ + install_node(&interface_node, config_write_interface); + if_cmd_init(); + + /* "ip ospf authentication" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_authentication_args_addr_cmd); + install_element(INTERFACE_NODE, &ip_ospf_authentication_addr_cmd); + install_element(INTERFACE_NODE, + &no_ip_ospf_authentication_args_addr_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_authentication_addr_cmd); + install_element(INTERFACE_NODE, &ip_ospf_authentication_key_addr_cmd); + install_element(INTERFACE_NODE, + &no_ip_ospf_authentication_key_authkey_addr_cmd); + install_element(INTERFACE_NODE, + &no_ospf_authentication_key_authkey_addr_cmd); + + /* "ip ospf message-digest-key" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_message_digest_key_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_message_digest_key_cmd); + + /* "ip ospf cost" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_cost_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_cost_cmd); + + /* "ip ospf mtu-ignore" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_mtu_ignore_addr_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_mtu_ignore_addr_cmd); + + /* "ip ospf dead-interval" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_dead_interval_cmd); + install_element(INTERFACE_NODE, + &ip_ospf_dead_interval_minimal_addr_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_dead_interval_cmd); + + /* "ip ospf hello-interval" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_hello_interval_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_hello_interval_cmd); + + /* "ip ospf network" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_network_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_network_cmd); + + /* "ip ospf priority" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_priority_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_priority_cmd); + + /* "ip ospf retransmit-interval" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_retransmit_interval_addr_cmd); + install_element(INTERFACE_NODE, + &no_ip_ospf_retransmit_interval_addr_cmd); + + /* "ip ospf transmit-delay" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_transmit_delay_addr_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_transmit_delay_addr_cmd); + + /* "ip ospf area" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_area_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_area_cmd); + + /* These commands are compatibitliy for previous version. */ + install_element(INTERFACE_NODE, &ospf_authentication_key_cmd); + install_element(INTERFACE_NODE, &ospf_message_digest_key_cmd); + install_element(INTERFACE_NODE, &no_ospf_message_digest_key_cmd); + install_element(INTERFACE_NODE, &ospf_dead_interval_cmd); + install_element(INTERFACE_NODE, &no_ospf_dead_interval_cmd); + install_element(INTERFACE_NODE, &ospf_hello_interval_cmd); + install_element(INTERFACE_NODE, &no_ospf_hello_interval_cmd); + install_element(INTERFACE_NODE, &ospf_cost_cmd); + install_element(INTERFACE_NODE, &no_ospf_cost_cmd); + install_element(INTERFACE_NODE, &ospf_network_cmd); + install_element(INTERFACE_NODE, &no_ospf_network_cmd); + install_element(INTERFACE_NODE, &ospf_priority_cmd); + install_element(INTERFACE_NODE, &no_ospf_priority_cmd); + install_element(INTERFACE_NODE, &ospf_retransmit_interval_cmd); + install_element(INTERFACE_NODE, &no_ospf_retransmit_interval_cmd); + install_element(INTERFACE_NODE, &ospf_transmit_delay_cmd); + install_element(INTERFACE_NODE, &no_ospf_transmit_delay_cmd); +} + +static void ospf_vty_zebra_init(void) +{ + install_element(OSPF_NODE, &ospf_redistribute_source_cmd); + install_element(OSPF_NODE, &no_ospf_redistribute_source_cmd); + install_element(OSPF_NODE, &ospf_redistribute_instance_source_cmd); + install_element(OSPF_NODE, &no_ospf_redistribute_instance_source_cmd); + + install_element(OSPF_NODE, &ospf_distribute_list_out_cmd); + install_element(OSPF_NODE, &no_ospf_distribute_list_out_cmd); + + install_element(OSPF_NODE, &ospf_default_information_originate_cmd); + install_element(OSPF_NODE, &no_ospf_default_information_originate_cmd); + + install_element(OSPF_NODE, &ospf_default_metric_cmd); + install_element(OSPF_NODE, &no_ospf_default_metric_cmd); + + install_element(OSPF_NODE, &ospf_distance_cmd); + install_element(OSPF_NODE, &no_ospf_distance_cmd); + install_element(OSPF_NODE, &no_ospf_distance_ospf_cmd); + install_element(OSPF_NODE, &ospf_distance_ospf_cmd); #if 0 install_element (OSPF_NODE, &ospf_distance_source_cmd); install_element (OSPF_NODE, &no_ospf_distance_source_cmd); @@ -8950,22 +8986,17 @@ ospf_vty_zebra_init (void) #endif /* 0 */ } -static struct cmd_node ospf_node = -{ - OSPF_NODE, - "%s(config-router)# ", - 1 -}; +static struct cmd_node ospf_node = {OSPF_NODE, "%s(config-router)# ", 1}; -static void -ospf_interface_clear (struct interface *ifp) +static void ospf_interface_clear(struct interface *ifp) { - if (!if_is_operative (ifp)) return; + if (!if_is_operative(ifp)) + return; - if (IS_DEBUG_OSPF (ism, ISM_EVENTS)) - zlog_debug("ISM[%s]: clear by reset", ifp->name); + if (IS_DEBUG_OSPF(ism, ISM_EVENTS)) + zlog_debug("ISM[%s]: clear by reset", ifp->name); - ospf_if_reset(ifp); + ospf_if_reset(ifp); } DEFUN (clear_ip_ospf_interface, @@ -8977,175 +9008,167 @@ DEFUN (clear_ip_ospf_interface, "Interface information\n" "Interface name\n") { - int idx_ifname = 4; - struct interface *ifp; - struct listnode *node; - - if (argc == 4) /* Clear all the ospfv2 interfaces. */ - { - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - ospf_interface_clear(ifp); - } - else /* Interface name is specified. */ - { - if ((ifp = if_lookup_by_name (argv[idx_ifname]->arg, VRF_DEFAULT)) == NULL) - vty_out (vty, "No such interface name\n"); - else - ospf_interface_clear(ifp); - } + int idx_ifname = 4; + struct interface *ifp; + struct listnode *node; - return CMD_SUCCESS; + if (argc == 4) /* Clear all the ospfv2 interfaces. */ + { + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) + ospf_interface_clear(ifp); + } else /* Interface name is specified. */ + { + if ((ifp = if_lookup_by_name(argv[idx_ifname]->arg, + VRF_DEFAULT)) + == NULL) + vty_out(vty, "No such interface name\n"); + else + ospf_interface_clear(ifp); + } + + return CMD_SUCCESS; } -void -ospf_vty_clear_init (void) +void ospf_vty_clear_init(void) { - install_element (ENABLE_NODE, &clear_ip_ospf_interface_cmd); + install_element(ENABLE_NODE, &clear_ip_ospf_interface_cmd); } /* Install OSPF related vty commands. */ -void -ospf_vty_init (void) -{ - /* Install ospf top node. */ - install_node (&ospf_node, ospf_config_write); - - /* "router ospf" commands. */ - install_element (CONFIG_NODE, &router_ospf_cmd); - install_element (CONFIG_NODE, &no_router_ospf_cmd); - - - install_default (OSPF_NODE); - - /* "ospf router-id" commands. */ - install_element (OSPF_NODE, &ospf_router_id_cmd); - install_element (OSPF_NODE, &ospf_router_id_old_cmd); - install_element (OSPF_NODE, &no_ospf_router_id_cmd); - - /* "passive-interface" commands. */ - install_element (OSPF_NODE, &ospf_passive_interface_addr_cmd); - install_element (OSPF_NODE, &no_ospf_passive_interface_addr_cmd); - - /* "ospf abr-type" commands. */ - install_element (OSPF_NODE, &ospf_abr_type_cmd); - install_element (OSPF_NODE, &no_ospf_abr_type_cmd); - - /* "ospf log-adjacency-changes" commands. */ - install_element (OSPF_NODE, &ospf_log_adjacency_changes_cmd); - install_element (OSPF_NODE, &ospf_log_adjacency_changes_detail_cmd); - install_element (OSPF_NODE, &no_ospf_log_adjacency_changes_cmd); - install_element (OSPF_NODE, &no_ospf_log_adjacency_changes_detail_cmd); - - /* "ospf rfc1583-compatible" commands. */ - install_element (OSPF_NODE, &ospf_compatible_rfc1583_cmd); - install_element (OSPF_NODE, &no_ospf_compatible_rfc1583_cmd); - install_element (OSPF_NODE, &ospf_rfc1583_flag_cmd); - install_element (OSPF_NODE, &no_ospf_rfc1583_flag_cmd); - - /* "network area" commands. */ - install_element (OSPF_NODE, &ospf_network_area_cmd); - install_element (OSPF_NODE, &no_ospf_network_area_cmd); - - /* "area authentication" commands. */ - install_element (OSPF_NODE, &ospf_area_authentication_message_digest_cmd); - install_element (OSPF_NODE, &ospf_area_authentication_cmd); - install_element (OSPF_NODE, &no_ospf_area_authentication_cmd); - - /* "area range" commands. */ - install_element (OSPF_NODE, &ospf_area_range_cmd); - install_element (OSPF_NODE, &ospf_area_range_cost_cmd); - install_element (OSPF_NODE, &ospf_area_range_not_advertise_cmd); - install_element (OSPF_NODE, &no_ospf_area_range_cmd); - install_element (OSPF_NODE, &ospf_area_range_substitute_cmd); - install_element (OSPF_NODE, &no_ospf_area_range_substitute_cmd); - - /* "area virtual-link" commands. */ - install_element (OSPF_NODE, &ospf_area_vlink_cmd); - install_element (OSPF_NODE, &ospf_area_vlink_intervals_cmd); - install_element (OSPF_NODE, &no_ospf_area_vlink_cmd); - install_element (OSPF_NODE, &no_ospf_area_vlink_intervals_cmd); - - - - - - - - - - - /* "area stub" commands. */ - install_element (OSPF_NODE, &ospf_area_stub_no_summary_cmd); - install_element (OSPF_NODE, &ospf_area_stub_cmd); - install_element (OSPF_NODE, &no_ospf_area_stub_no_summary_cmd); - install_element (OSPF_NODE, &no_ospf_area_stub_cmd); - - /* "area nssa" commands. */ - install_element (OSPF_NODE, &ospf_area_nssa_cmd); - install_element (OSPF_NODE, &ospf_area_nssa_translate_no_summary_cmd); - install_element (OSPF_NODE, &ospf_area_nssa_translate_cmd); - install_element (OSPF_NODE, &ospf_area_nssa_no_summary_cmd); - install_element (OSPF_NODE, &no_ospf_area_nssa_cmd); - - install_element (OSPF_NODE, &ospf_area_default_cost_cmd); - install_element (OSPF_NODE, &no_ospf_area_default_cost_cmd); - - install_element (OSPF_NODE, &ospf_area_shortcut_cmd); - install_element (OSPF_NODE, &no_ospf_area_shortcut_cmd); - - install_element (OSPF_NODE, &ospf_area_export_list_cmd); - install_element (OSPF_NODE, &no_ospf_area_export_list_cmd); - - install_element (OSPF_NODE, &ospf_area_filter_list_cmd); - install_element (OSPF_NODE, &no_ospf_area_filter_list_cmd); - - install_element (OSPF_NODE, &ospf_area_import_list_cmd); - install_element (OSPF_NODE, &no_ospf_area_import_list_cmd); - - /* SPF timer commands */ - install_element (OSPF_NODE, &ospf_timers_throttle_spf_cmd); - install_element (OSPF_NODE, &no_ospf_timers_throttle_spf_cmd); - - /* LSA timers commands */ - install_element (OSPF_NODE, &ospf_timers_min_ls_interval_cmd); - install_element (OSPF_NODE, &no_ospf_timers_min_ls_interval_cmd); - install_element (OSPF_NODE, &ospf_timers_min_ls_arrival_cmd); - install_element (OSPF_NODE, &no_ospf_timers_min_ls_arrival_cmd); - install_element (OSPF_NODE, &ospf_timers_lsa_cmd); - install_element (OSPF_NODE, &no_ospf_timers_lsa_cmd); - - /* refresh timer commands */ - install_element (OSPF_NODE, &ospf_refresh_timer_cmd); - install_element (OSPF_NODE, &no_ospf_refresh_timer_val_cmd); - - /* max-metric commands */ - install_element (OSPF_NODE, &ospf_max_metric_router_lsa_admin_cmd); - install_element (OSPF_NODE, &no_ospf_max_metric_router_lsa_admin_cmd); - install_element (OSPF_NODE, &ospf_max_metric_router_lsa_startup_cmd); - install_element (OSPF_NODE, &no_ospf_max_metric_router_lsa_startup_cmd); - install_element (OSPF_NODE, &ospf_max_metric_router_lsa_shutdown_cmd); - install_element (OSPF_NODE, &no_ospf_max_metric_router_lsa_shutdown_cmd); - - /* reference bandwidth commands */ - install_element (OSPF_NODE, &ospf_auto_cost_reference_bandwidth_cmd); - install_element (OSPF_NODE, &no_ospf_auto_cost_reference_bandwidth_cmd); - - /* "neighbor" commands. */ - install_element (OSPF_NODE, &ospf_neighbor_cmd); - install_element (OSPF_NODE, &ospf_neighbor_poll_interval_cmd); - install_element (OSPF_NODE, &no_ospf_neighbor_cmd); - install_element (OSPF_NODE, &no_ospf_neighbor_poll_cmd); - - /* write multiplier commands */ - install_element (OSPF_NODE, &ospf_write_multiplier_cmd); - install_element (OSPF_NODE, &write_multiplier_cmd); - install_element (OSPF_NODE, &no_ospf_write_multiplier_cmd); - install_element (OSPF_NODE, &no_write_multiplier_cmd); - - /* Init interface related vty commands. */ - ospf_vty_if_init (); - - /* Init zebra related vty commands. */ - ospf_vty_zebra_init (); +void ospf_vty_init(void) +{ + /* Install ospf top node. */ + install_node(&ospf_node, ospf_config_write); + + /* "router ospf" commands. */ + install_element(CONFIG_NODE, &router_ospf_cmd); + install_element(CONFIG_NODE, &no_router_ospf_cmd); + + + install_default(OSPF_NODE); + + /* "ospf router-id" commands. */ + install_element(OSPF_NODE, &ospf_router_id_cmd); + install_element(OSPF_NODE, &ospf_router_id_old_cmd); + install_element(OSPF_NODE, &no_ospf_router_id_cmd); + + /* "passive-interface" commands. */ + install_element(OSPF_NODE, &ospf_passive_interface_addr_cmd); + install_element(OSPF_NODE, &no_ospf_passive_interface_addr_cmd); + + /* "ospf abr-type" commands. */ + install_element(OSPF_NODE, &ospf_abr_type_cmd); + install_element(OSPF_NODE, &no_ospf_abr_type_cmd); + + /* "ospf log-adjacency-changes" commands. */ + install_element(OSPF_NODE, &ospf_log_adjacency_changes_cmd); + install_element(OSPF_NODE, &ospf_log_adjacency_changes_detail_cmd); + install_element(OSPF_NODE, &no_ospf_log_adjacency_changes_cmd); + install_element(OSPF_NODE, &no_ospf_log_adjacency_changes_detail_cmd); + + /* "ospf rfc1583-compatible" commands. */ + install_element(OSPF_NODE, &ospf_compatible_rfc1583_cmd); + install_element(OSPF_NODE, &no_ospf_compatible_rfc1583_cmd); + install_element(OSPF_NODE, &ospf_rfc1583_flag_cmd); + install_element(OSPF_NODE, &no_ospf_rfc1583_flag_cmd); + + /* "network area" commands. */ + install_element(OSPF_NODE, &ospf_network_area_cmd); + install_element(OSPF_NODE, &no_ospf_network_area_cmd); + + /* "area authentication" commands. */ + install_element(OSPF_NODE, + &ospf_area_authentication_message_digest_cmd); + install_element(OSPF_NODE, &ospf_area_authentication_cmd); + install_element(OSPF_NODE, &no_ospf_area_authentication_cmd); + + /* "area range" commands. */ + install_element(OSPF_NODE, &ospf_area_range_cmd); + install_element(OSPF_NODE, &ospf_area_range_cost_cmd); + install_element(OSPF_NODE, &ospf_area_range_not_advertise_cmd); + install_element(OSPF_NODE, &no_ospf_area_range_cmd); + install_element(OSPF_NODE, &ospf_area_range_substitute_cmd); + install_element(OSPF_NODE, &no_ospf_area_range_substitute_cmd); + + /* "area virtual-link" commands. */ + install_element(OSPF_NODE, &ospf_area_vlink_cmd); + install_element(OSPF_NODE, &ospf_area_vlink_intervals_cmd); + install_element(OSPF_NODE, &no_ospf_area_vlink_cmd); + install_element(OSPF_NODE, &no_ospf_area_vlink_intervals_cmd); + + + /* "area stub" commands. */ + install_element(OSPF_NODE, &ospf_area_stub_no_summary_cmd); + install_element(OSPF_NODE, &ospf_area_stub_cmd); + install_element(OSPF_NODE, &no_ospf_area_stub_no_summary_cmd); + install_element(OSPF_NODE, &no_ospf_area_stub_cmd); + + /* "area nssa" commands. */ + install_element(OSPF_NODE, &ospf_area_nssa_cmd); + install_element(OSPF_NODE, &ospf_area_nssa_translate_no_summary_cmd); + install_element(OSPF_NODE, &ospf_area_nssa_translate_cmd); + install_element(OSPF_NODE, &ospf_area_nssa_no_summary_cmd); + install_element(OSPF_NODE, &no_ospf_area_nssa_cmd); + + install_element(OSPF_NODE, &ospf_area_default_cost_cmd); + install_element(OSPF_NODE, &no_ospf_area_default_cost_cmd); + + install_element(OSPF_NODE, &ospf_area_shortcut_cmd); + install_element(OSPF_NODE, &no_ospf_area_shortcut_cmd); + + install_element(OSPF_NODE, &ospf_area_export_list_cmd); + install_element(OSPF_NODE, &no_ospf_area_export_list_cmd); + + install_element(OSPF_NODE, &ospf_area_filter_list_cmd); + install_element(OSPF_NODE, &no_ospf_area_filter_list_cmd); + + install_element(OSPF_NODE, &ospf_area_import_list_cmd); + install_element(OSPF_NODE, &no_ospf_area_import_list_cmd); + + /* SPF timer commands */ + install_element(OSPF_NODE, &ospf_timers_throttle_spf_cmd); + install_element(OSPF_NODE, &no_ospf_timers_throttle_spf_cmd); + + /* LSA timers commands */ + install_element(OSPF_NODE, &ospf_timers_min_ls_interval_cmd); + install_element(OSPF_NODE, &no_ospf_timers_min_ls_interval_cmd); + install_element(OSPF_NODE, &ospf_timers_min_ls_arrival_cmd); + install_element(OSPF_NODE, &no_ospf_timers_min_ls_arrival_cmd); + install_element(OSPF_NODE, &ospf_timers_lsa_cmd); + install_element(OSPF_NODE, &no_ospf_timers_lsa_cmd); + + /* refresh timer commands */ + install_element(OSPF_NODE, &ospf_refresh_timer_cmd); + install_element(OSPF_NODE, &no_ospf_refresh_timer_val_cmd); + + /* max-metric commands */ + install_element(OSPF_NODE, &ospf_max_metric_router_lsa_admin_cmd); + install_element(OSPF_NODE, &no_ospf_max_metric_router_lsa_admin_cmd); + install_element(OSPF_NODE, &ospf_max_metric_router_lsa_startup_cmd); + install_element(OSPF_NODE, &no_ospf_max_metric_router_lsa_startup_cmd); + install_element(OSPF_NODE, &ospf_max_metric_router_lsa_shutdown_cmd); + install_element(OSPF_NODE, &no_ospf_max_metric_router_lsa_shutdown_cmd); + + /* reference bandwidth commands */ + install_element(OSPF_NODE, &ospf_auto_cost_reference_bandwidth_cmd); + install_element(OSPF_NODE, &no_ospf_auto_cost_reference_bandwidth_cmd); + + /* "neighbor" commands. */ + install_element(OSPF_NODE, &ospf_neighbor_cmd); + install_element(OSPF_NODE, &ospf_neighbor_poll_interval_cmd); + install_element(OSPF_NODE, &no_ospf_neighbor_cmd); + install_element(OSPF_NODE, &no_ospf_neighbor_poll_cmd); + + /* write multiplier commands */ + install_element(OSPF_NODE, &ospf_write_multiplier_cmd); + install_element(OSPF_NODE, &write_multiplier_cmd); + install_element(OSPF_NODE, &no_ospf_write_multiplier_cmd); + install_element(OSPF_NODE, &no_write_multiplier_cmd); + + /* Init interface related vty commands. */ + ospf_vty_if_init(); + + /* Init zebra related vty commands. */ + ospf_vty_zebra_init(); } diff --git a/ospfd/ospf_vty.h b/ospfd/ospf_vty.h index ba7b24ed9..9fd0c3ed4 100644 --- a/ospfd/ospf_vty.h +++ b/ospfd/ospf_vty.h @@ -22,38 +22,36 @@ #define _QUAGGA_OSPF_VTY_H /* Macros. */ -#define VTY_GET_OSPF_AREA_ID(V,F,STR) \ -{ \ - int retv; \ - retv = str2area_id ((STR), &(V), &(F)); \ - if (retv < 0) \ - { \ - vty_out (vty, "%% Invalid OSPF area ID\n"); \ - return CMD_WARNING; \ - } \ -} +#define VTY_GET_OSPF_AREA_ID(V, F, STR) \ + { \ + int retv; \ + retv = str2area_id((STR), &(V), &(F)); \ + if (retv < 0) { \ + vty_out(vty, "%% Invalid OSPF area ID\n"); \ + return CMD_WARNING; \ + } \ + } -#define VTY_GET_OSPF_AREA_ID_NO_BB(NAME,V,F,STR) \ -{ \ - int retv; \ - retv = str2area_id ((STR), &(V), &(F)); \ - if (retv < 0) \ - { \ - vty_out (vty, "%% Invalid OSPF area ID\n"); \ - return CMD_WARNING; \ - } \ - if (OSPF_IS_AREA_ID_BACKBONE ((V))) \ - { \ - vty_out (vty, "%% You can't configure %s to backbone\n", \ - NAME); \ - } \ -} +#define VTY_GET_OSPF_AREA_ID_NO_BB(NAME, V, F, STR) \ + { \ + int retv; \ + retv = str2area_id((STR), &(V), &(F)); \ + if (retv < 0) { \ + vty_out(vty, "%% Invalid OSPF area ID\n"); \ + return CMD_WARNING; \ + } \ + if (OSPF_IS_AREA_ID_BACKBONE((V))) { \ + vty_out(vty, \ + "%% You can't configure %s to backbone\n", \ + NAME); \ + } \ + } /* Prototypes. */ -extern void ospf_vty_init (void); -extern void ospf_vty_show_init (void); -extern void ospf_vty_clear_init (void); -extern int str2area_id (const char *, struct in_addr *, int *); -extern void area_id2str (char *, int, struct in_addr *, int); +extern void ospf_vty_init(void); +extern void ospf_vty_show_init(void); +extern void ospf_vty_clear_init(void); +extern int str2area_id(const char *, struct in_addr *, int *); +extern void area_id2str(char *, int, struct in_addr *, int); #endif /* _QUAGGA_OSPF_VTY_H */ diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index e262bd8aa..c6b0955da 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -51,8 +51,8 @@ #include "ospfd/ospf_zebra.h" #include "ospfd/ospf_te.h" -DEFINE_HOOK(ospf_if_update, (struct interface *ifp), (ifp)) -DEFINE_HOOK(ospf_if_delete, (struct interface *ifp), (ifp)) +DEFINE_HOOK(ospf_if_update, (struct interface * ifp), (ifp)) +DEFINE_HOOK(ospf_if_delete, (struct interface * ifp), (ifp)) /* Zebra structure to hold current status. */ struct zclient *zclient = NULL; @@ -62,1536 +62,1479 @@ extern struct thread_master *master; struct in_addr router_id_zebra; /* Router-id update message from zebra. */ -static int -ospf_router_id_update_zebra (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int ospf_router_id_update_zebra(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct ospf *ospf; - struct prefix router_id; - zebra_router_id_update_read(zclient->ibuf,&router_id); - - if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str(&router_id, buf, sizeof(buf)); - zlog_debug("Zebra rcvd: router id update %s", buf); - } - - router_id_zebra = router_id.u.prefix4; - - ospf = ospf_lookup (); - - if (ospf != NULL) - ospf_router_id_update (ospf); - - return 0; + struct ospf *ospf; + struct prefix router_id; + zebra_router_id_update_read(zclient->ibuf, &router_id); + + if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&router_id, buf, sizeof(buf)); + zlog_debug("Zebra rcvd: router id update %s", buf); + } + + router_id_zebra = router_id.u.prefix4; + + ospf = ospf_lookup(); + + if (ospf != NULL) + ospf_router_id_update(ospf); + + return 0; } /* Inteface addition message from zebra. */ -static int -ospf_interface_add (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int ospf_interface_add(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; + struct interface *ifp; - ifp = zebra_interface_add_read (zclient->ibuf, vrf_id); + ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); - if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) - zlog_debug ("Zebra: interface add %s[%u] index %d flags %llx metric %d mtu %d", - ifp->name, ifp->vrf_id, ifp->ifindex, (unsigned long long)ifp->flags, - ifp->metric, ifp->mtu); + if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) + zlog_debug( + "Zebra: interface add %s[%u] index %d flags %llx metric %d mtu %d", + ifp->name, ifp->vrf_id, ifp->ifindex, + (unsigned long long)ifp->flags, ifp->metric, ifp->mtu); - assert (ifp->info); + assert(ifp->info); - if (!OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), type)) - { - SET_IF_PARAM (IF_DEF_PARAMS (ifp), type); - IF_DEF_PARAMS (ifp)->type = ospf_default_iftype(ifp); - } + if (!OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(ifp), type)) { + SET_IF_PARAM(IF_DEF_PARAMS(ifp), type); + IF_DEF_PARAMS(ifp)->type = ospf_default_iftype(ifp); + } - ospf_if_update (NULL, ifp); + ospf_if_update(NULL, ifp); - hook_call(ospf_if_update, ifp); + hook_call(ospf_if_update, ifp); - return 0; + return 0; } -static int -ospf_interface_delete (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int ospf_interface_delete(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - struct stream *s; - struct route_node *rn; + struct interface *ifp; + struct stream *s; + struct route_node *rn; - s = zclient->ibuf; - /* zebra_interface_state_read() updates interface structure in iflist */ - ifp = zebra_interface_state_read (s, vrf_id); + s = zclient->ibuf; + /* zebra_interface_state_read() updates interface structure in iflist */ + ifp = zebra_interface_state_read(s, vrf_id); - if (ifp == NULL) - return 0; + if (ifp == NULL) + return 0; - if (if_is_up (ifp)) - zlog_warn ("Zebra: got delete of %s, but interface is still up", - ifp->name); + if (if_is_up(ifp)) + zlog_warn("Zebra: got delete of %s, but interface is still up", + ifp->name); - if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) - zlog_debug - ("Zebra: interface delete %s[%u] index %d flags %llx metric %d mtu %d", - ifp->name, ifp->vrf_id, ifp->ifindex, (unsigned long long)ifp->flags, ifp->metric, ifp->mtu); + if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) + zlog_debug( + "Zebra: interface delete %s[%u] index %d flags %llx metric %d mtu %d", + ifp->name, ifp->vrf_id, ifp->ifindex, + (unsigned long long)ifp->flags, ifp->metric, ifp->mtu); - hook_call(ospf_if_delete, ifp); + hook_call(ospf_if_delete, ifp); - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - if (rn->info) - ospf_if_free ((struct ospf_interface *) rn->info); + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) + if (rn->info) + ospf_if_free((struct ospf_interface *)rn->info); - ifp->ifindex = IFINDEX_DELETED; - return 0; + ifp->ifindex = IFINDEX_DELETED; + return 0; } -static struct interface * -zebra_interface_if_lookup (struct stream *s, vrf_id_t vrf_id) +static struct interface *zebra_interface_if_lookup(struct stream *s, + vrf_id_t vrf_id) { - char ifname_tmp[INTERFACE_NAMSIZ]; + char ifname_tmp[INTERFACE_NAMSIZ]; - /* Read interface name. */ - stream_get (ifname_tmp, s, INTERFACE_NAMSIZ); + /* Read interface name. */ + stream_get(ifname_tmp, s, INTERFACE_NAMSIZ); - /* And look it up. */ - return if_lookup_by_name_len(ifname_tmp, - strnlen(ifname_tmp, INTERFACE_NAMSIZ), - VRF_DEFAULT); + /* And look it up. */ + return if_lookup_by_name_len( + ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ), VRF_DEFAULT); } -static int -ospf_interface_state_up (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int ospf_interface_state_up(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - struct ospf_interface *oi; - struct route_node *rn; - - ifp = zebra_interface_if_lookup (zclient->ibuf, vrf_id); - - if (ifp == NULL) - return 0; - - /* Interface is already up. */ - if (if_is_operative (ifp)) - { - /* Temporarily keep ifp values. */ - struct interface if_tmp; - memcpy (&if_tmp, ifp, sizeof (struct interface)); - - zebra_interface_if_set_value (zclient->ibuf, ifp); - - if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) - zlog_debug ("Zebra: Interface[%s] state update speed %u -> %u, bw %d -> %d", - ifp->name, if_tmp.speed, ifp->speed, if_tmp.bandwidth, ifp->bandwidth); - - ospf_if_recalculate_output_cost (ifp); - - if (if_tmp.mtu != ifp->mtu) - { - if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) - zlog_debug ("Zebra: Interface[%s] MTU change %u -> %u.", - ifp->name, if_tmp.mtu, ifp->mtu); - - /* Must reset the interface (simulate down/up) when MTU changes. */ - ospf_if_reset(ifp); + struct interface *ifp; + struct ospf_interface *oi; + struct route_node *rn; + + ifp = zebra_interface_if_lookup(zclient->ibuf, vrf_id); + + if (ifp == NULL) + return 0; + + /* Interface is already up. */ + if (if_is_operative(ifp)) { + /* Temporarily keep ifp values. */ + struct interface if_tmp; + memcpy(&if_tmp, ifp, sizeof(struct interface)); + + zebra_interface_if_set_value(zclient->ibuf, ifp); + + if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) + zlog_debug( + "Zebra: Interface[%s] state update speed %u -> %u, bw %d -> %d", + ifp->name, if_tmp.speed, ifp->speed, + if_tmp.bandwidth, ifp->bandwidth); + + ospf_if_recalculate_output_cost(ifp); + + if (if_tmp.mtu != ifp->mtu) { + if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) + zlog_debug( + "Zebra: Interface[%s] MTU change %u -> %u.", + ifp->name, if_tmp.mtu, ifp->mtu); + + /* Must reset the interface (simulate down/up) when MTU + * changes. */ + ospf_if_reset(ifp); + } + return 0; } - return 0; - } - zebra_interface_if_set_value (zclient->ibuf, ifp); + zebra_interface_if_set_value(zclient->ibuf, ifp); - if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) - zlog_debug ("Zebra: Interface[%s] state change to up.", ifp->name); + if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) + zlog_debug("Zebra: Interface[%s] state change to up.", + ifp->name); - for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) - { - if ((oi = rn->info) == NULL) - continue; + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + if ((oi = rn->info) == NULL) + continue; - ospf_if_up (oi); - } + ospf_if_up(oi); + } - return 0; + return 0; } -static int -ospf_interface_state_down (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int ospf_interface_state_down(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - struct ospf_interface *oi; - struct route_node *node; + struct interface *ifp; + struct ospf_interface *oi; + struct route_node *node; - ifp = zebra_interface_state_read (zclient->ibuf, vrf_id); + ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); - if (ifp == NULL) - return 0; + if (ifp == NULL) + return 0; - if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) - zlog_debug ("Zebra: Interface[%s] state change to down.", ifp->name); + if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) + zlog_debug("Zebra: Interface[%s] state change to down.", + ifp->name); - for (node = route_top (IF_OIFS (ifp)); node; node = route_next (node)) - { - if ((oi = node->info) == NULL) - continue; - ospf_if_down (oi); - } + for (node = route_top(IF_OIFS(ifp)); node; node = route_next(node)) { + if ((oi = node->info) == NULL) + continue; + ospf_if_down(oi); + } - return 0; + return 0; } -static int -ospf_interface_address_add (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int ospf_interface_address_add(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct connected *c; + struct connected *c; - c = zebra_interface_address_read (command, zclient->ibuf, vrf_id); + c = zebra_interface_address_read(command, zclient->ibuf, vrf_id); - if (c == NULL) - return 0; + if (c == NULL) + return 0; - if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str(c->address, buf, sizeof(buf)); - zlog_debug("Zebra: interface %s address add %s", c->ifp->name, buf); - } + if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(c->address, buf, sizeof(buf)); + zlog_debug("Zebra: interface %s address add %s", c->ifp->name, + buf); + } - ospf_if_update (NULL, c->ifp); + ospf_if_update(NULL, c->ifp); - hook_call(ospf_if_update, c->ifp); + hook_call(ospf_if_update, c->ifp); - return 0; + return 0; } -static int -ospf_interface_address_delete (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int ospf_interface_address_delete(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct connected *c; - struct interface *ifp; - struct ospf_interface *oi; - struct route_node *rn; - struct prefix p; - - c = zebra_interface_address_read (command, zclient->ibuf, vrf_id); - - if (c == NULL) - return 0; - - if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str(c->address, buf, sizeof(buf)); - zlog_debug("Zebra: interface %s address delete %s", c->ifp->name, buf); - } + struct connected *c; + struct interface *ifp; + struct ospf_interface *oi; + struct route_node *rn; + struct prefix p; + + c = zebra_interface_address_read(command, zclient->ibuf, vrf_id); + + if (c == NULL) + return 0; + + if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(c->address, buf, sizeof(buf)); + zlog_debug("Zebra: interface %s address delete %s", + c->ifp->name, buf); + } - ifp = c->ifp; - p = *c->address; - p.prefixlen = IPV4_MAX_PREFIXLEN; + ifp = c->ifp; + p = *c->address; + p.prefixlen = IPV4_MAX_PREFIXLEN; - rn = route_node_lookup (IF_OIFS (ifp), &p); - if (!rn) - { - connected_free (c); - return 0; - } + rn = route_node_lookup(IF_OIFS(ifp), &p); + if (!rn) { + connected_free(c); + return 0; + } - assert (rn->info); - oi = rn->info; - route_unlock_node (rn); + assert(rn->info); + oi = rn->info; + route_unlock_node(rn); - /* Call interface hook functions to clean up */ - ospf_if_free (oi); + /* Call interface hook functions to clean up */ + ospf_if_free(oi); - hook_call(ospf_if_update, c->ifp); + hook_call(ospf_if_update, c->ifp); - connected_free (c); + connected_free(c); - return 0; + return 0; } -static int -ospf_interface_link_params (int command, struct zclient *zclient, - zebra_size_t length) +static int ospf_interface_link_params(int command, struct zclient *zclient, + zebra_size_t length) { - struct interface *ifp; + struct interface *ifp; - ifp = zebra_interface_link_params_read (zclient->ibuf); + ifp = zebra_interface_link_params_read(zclient->ibuf); - if (ifp == NULL) - return 0; + if (ifp == NULL) + return 0; - /* Update TE TLV */ - ospf_mpls_te_update_if (ifp); + /* Update TE TLV */ + ospf_mpls_te_update_if(ifp); - return 0; + return 0; } -void -ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or) +void ospf_zebra_add(struct prefix_ipv4 *p, struct ospf_route * or) { - u_char message; - u_char distance; - u_int32_t flags; - int psize; - struct stream *s; - struct ospf_path *path; - struct listnode *node; - struct ospf *ospf = ospf_lookup (); - - if ((ospf->instance && - redist_check_instance(&zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], ospf->instance)) - || - vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], VRF_DEFAULT)) - { - message = 0; - flags = 0; - - /* OSPF pass nexthop and metric */ - SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG (message, ZAPI_MESSAGE_METRIC); - - /* Distance value. */ - distance = ospf_distance_apply (p, or); - if (distance) - SET_FLAG (message, ZAPI_MESSAGE_DISTANCE); - - /* Check if path type is ASE */ - if (((or->path_type == OSPF_PATH_TYPE1_EXTERNAL) || - (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)) && - (or->u.ext.tag > 0) && (or->u.ext.tag <= ROUTE_TAG_MAX)) - SET_FLAG (message, ZAPI_MESSAGE_TAG); - - /* Make packet. */ - s = zclient->obuf; - stream_reset (s); - - /* Put command, type, flags, message. */ - zclient_create_header (s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT); - stream_putc (s, ZEBRA_ROUTE_OSPF); - stream_putw (s, ospf->instance); - stream_putl (s, flags); - stream_putc (s, message); - stream_putw (s, SAFI_UNICAST); - - /* Put prefix information. */ - psize = PSIZE (p->prefixlen); - stream_putc (s, p->prefixlen); - stream_write (s, (u_char *) & p->prefix, psize); - - /* Nexthop count. */ - stream_putc (s, or->paths->count); - - /* Nexthop, ifindex, distance and metric information. */ - for (ALL_LIST_ELEMENTS_RO (or->paths, node, path)) - { + u_char message; + u_char distance; + u_int32_t flags; + int psize; + struct stream *s; + struct ospf_path *path; + struct listnode *node; + struct ospf *ospf = ospf_lookup(); + + if ((ospf->instance + && redist_check_instance( + &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], + ospf->instance)) + || vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], + VRF_DEFAULT)) { + message = 0; + flags = 0; + + /* OSPF pass nexthop and metric */ + SET_FLAG(message, ZAPI_MESSAGE_NEXTHOP); + SET_FLAG(message, ZAPI_MESSAGE_METRIC); + + /* Distance value. */ + distance = ospf_distance_apply(p, or); + if (distance) + SET_FLAG(message, ZAPI_MESSAGE_DISTANCE); + + /* Check if path type is ASE */ + if (((or->path_type == OSPF_PATH_TYPE1_EXTERNAL) + || (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)) + && (or->u.ext.tag > 0) && (or->u.ext.tag <= ROUTE_TAG_MAX)) + SET_FLAG(message, ZAPI_MESSAGE_TAG); + + /* Make packet. */ + s = zclient->obuf; + stream_reset(s); + + /* Put command, type, flags, message. */ + zclient_create_header(s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT); + stream_putc(s, ZEBRA_ROUTE_OSPF); + stream_putw(s, ospf->instance); + stream_putl(s, flags); + stream_putc(s, message); + stream_putw(s, SAFI_UNICAST); + + /* Put prefix information. */ + psize = PSIZE(p->prefixlen); + stream_putc(s, p->prefixlen); + stream_write(s, (u_char *)&p->prefix, psize); + + /* Nexthop count. */ + stream_putc(s, or->paths->count); + + /* Nexthop, ifindex, distance and metric information. */ + for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) { #ifdef HAVE_NETLINK - if (path->unnumbered || - (path->nexthop.s_addr != INADDR_ANY && - path->ifindex != 0)) - { - stream_putc (s, NEXTHOP_TYPE_IPV4_IFINDEX); - stream_put_in_addr (s, &path->nexthop); - stream_putl (s, path->ifindex); - } - else if (path->nexthop.s_addr != INADDR_ANY) - { - stream_putc (s, NEXTHOP_TYPE_IPV4); - stream_put_in_addr (s, &path->nexthop); - } - else - { - stream_putc (s, NEXTHOP_TYPE_IFINDEX); - if (path->ifindex) - stream_putl (s, path->ifindex); - else - stream_putl (s, 0); - } + if (path->unnumbered + || (path->nexthop.s_addr != INADDR_ANY + && path->ifindex != 0)) { + stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX); + stream_put_in_addr(s, &path->nexthop); + stream_putl(s, path->ifindex); + } else if (path->nexthop.s_addr != INADDR_ANY) { + stream_putc(s, NEXTHOP_TYPE_IPV4); + stream_put_in_addr(s, &path->nexthop); + } else { + stream_putc(s, NEXTHOP_TYPE_IFINDEX); + if (path->ifindex) + stream_putl(s, path->ifindex); + else + stream_putl(s, 0); + } #else /* HAVE_NETLINK */ - if (path->nexthop.s_addr != INADDR_ANY && - path->ifindex != 0) - { - stream_putc (s, NEXTHOP_TYPE_IPV4_IFINDEX); - stream_put_in_addr (s, &path->nexthop); - stream_putl (s, path->ifindex); - } - else if (path->nexthop.s_addr != INADDR_ANY) - { - stream_putc (s, NEXTHOP_TYPE_IPV4); - stream_put_in_addr (s, &path->nexthop); - } - else - { - stream_putc (s, NEXTHOP_TYPE_IFINDEX); - if (path->ifindex) - stream_putl (s, path->ifindex); - else - stream_putl (s, 0); - } + if (path->nexthop.s_addr != INADDR_ANY + && path->ifindex != 0) { + stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX); + stream_put_in_addr(s, &path->nexthop); + stream_putl(s, path->ifindex); + } else if (path->nexthop.s_addr != INADDR_ANY) { + stream_putc(s, NEXTHOP_TYPE_IPV4); + stream_put_in_addr(s, &path->nexthop); + } else { + stream_putc(s, NEXTHOP_TYPE_IFINDEX); + if (path->ifindex) + stream_putl(s, path->ifindex); + else + stream_putl(s, 0); + } #endif /* HAVE_NETLINK */ - if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) - { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra: Route add %s/%d nexthop %s, ifindex=%d", - inet_ntop(AF_INET, &p->prefix, - buf[0], sizeof(buf[0])), - p->prefixlen, - inet_ntop(AF_INET, &path->nexthop, - buf[1], sizeof(buf[1])), - path->ifindex); - } - } - - if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) - stream_putc (s, distance); - if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) - { - if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL) - stream_putl (s, or->cost + or->u.ext.type2_cost); - else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL) - stream_putl (s, or->u.ext.type2_cost); - else - stream_putl (s, or->cost); - } - - if (CHECK_FLAG (message, ZAPI_MESSAGE_TAG)) - stream_putl (s, or->u.ext.tag); - - stream_putw_at (s, 0, stream_get_endp (s)); - - zclient_send_message(zclient); - } + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) { + char buf[2][INET_ADDRSTRLEN]; + zlog_debug( + "Zebra: Route add %s/%d nexthop %s, ifindex=%d", + inet_ntop(AF_INET, &p->prefix, buf[0], + sizeof(buf[0])), + p->prefixlen, + inet_ntop(AF_INET, &path->nexthop, + buf[1], sizeof(buf[1])), + path->ifindex); + } + } + + if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) + stream_putc(s, distance); + if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) { + if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL) + stream_putl(s, or->cost + or->u.ext.type2_cost); + else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL) + stream_putl(s, or->u.ext.type2_cost); + else + stream_putl(s, or->cost); + } + + if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG)) + stream_putl(s, or->u.ext.tag); + + stream_putw_at(s, 0, stream_get_endp(s)); + + zclient_send_message(zclient); + } } -void -ospf_zebra_delete (struct prefix_ipv4 *p, struct ospf_route *or) +void ospf_zebra_delete(struct prefix_ipv4 *p, struct ospf_route * or) { - u_char message; - u_char distance; - u_int32_t flags; - int psize; - struct stream *s; - struct ospf_path *path; - struct listnode *node; - struct ospf *ospf = ospf_lookup (); - - if ((ospf->instance && - redist_check_instance(&zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], ospf->instance)) - || - vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], VRF_DEFAULT)) - { - message = 0; - flags = 0; - /* Distance value. */ - distance = ospf_distance_apply (p, or); - /* Make packet. */ - s = zclient->obuf; - stream_reset (s); - - /* Put command, type, flags, message. */ - zclient_create_header (s, ZEBRA_IPV4_ROUTE_DELETE, VRF_DEFAULT); - stream_putc (s, ZEBRA_ROUTE_OSPF); - stream_putw (s, ospf->instance); - stream_putl (s, flags); - stream_putc (s, message); - stream_putw (s, SAFI_UNICAST); - - /* Put prefix information. */ - psize = PSIZE (p->prefixlen); - stream_putc (s, p->prefixlen); - stream_write (s, (u_char *) & p->prefix, psize); - - /* Nexthop count. */ - stream_putc (s, or->paths->count); - - /* Nexthop, ifindex, distance and metric information. */ - for (ALL_LIST_ELEMENTS_RO (or->paths, node, path)) - { - if (path->nexthop.s_addr != INADDR_ANY && - path->ifindex != 0) - { - stream_putc (s, NEXTHOP_TYPE_IPV4_IFINDEX); - stream_put_in_addr (s, &path->nexthop); - stream_putl (s, path->ifindex); - } - else if (path->nexthop.s_addr != INADDR_ANY) - { - stream_putc (s, NEXTHOP_TYPE_IPV4); - stream_put_in_addr (s, &path->nexthop); - } - else - { - stream_putc (s, NEXTHOP_TYPE_IFINDEX); - stream_putl (s, path->ifindex); - } - - if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) - { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra: Route delete %s/%d nexthop %s", - inet_ntop(AF_INET, &p->prefix, - buf[0], sizeof(buf[0])), - p->prefixlen, - inet_ntop(AF_INET, &path->nexthop, - buf[1], sizeof(buf[1]))); - } - } - - if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE)) - stream_putc (s, distance); - if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) - { - if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL) - stream_putl (s, or->cost + or->u.ext.type2_cost); - else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL) - stream_putl (s, or->u.ext.type2_cost); - else - stream_putl (s, or->cost); + u_char message; + u_char distance; + u_int32_t flags; + int psize; + struct stream *s; + struct ospf_path *path; + struct listnode *node; + struct ospf *ospf = ospf_lookup(); + + if ((ospf->instance + && redist_check_instance( + &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], + ospf->instance)) + || vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], + VRF_DEFAULT)) { + message = 0; + flags = 0; + /* Distance value. */ + distance = ospf_distance_apply(p, or); + /* Make packet. */ + s = zclient->obuf; + stream_reset(s); + + /* Put command, type, flags, message. */ + zclient_create_header(s, ZEBRA_IPV4_ROUTE_DELETE, VRF_DEFAULT); + stream_putc(s, ZEBRA_ROUTE_OSPF); + stream_putw(s, ospf->instance); + stream_putl(s, flags); + stream_putc(s, message); + stream_putw(s, SAFI_UNICAST); + + /* Put prefix information. */ + psize = PSIZE(p->prefixlen); + stream_putc(s, p->prefixlen); + stream_write(s, (u_char *)&p->prefix, psize); + + /* Nexthop count. */ + stream_putc(s, or->paths->count); + + /* Nexthop, ifindex, distance and metric information. */ + for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) { + if (path->nexthop.s_addr != INADDR_ANY + && path->ifindex != 0) { + stream_putc(s, NEXTHOP_TYPE_IPV4_IFINDEX); + stream_put_in_addr(s, &path->nexthop); + stream_putl(s, path->ifindex); + } else if (path->nexthop.s_addr != INADDR_ANY) { + stream_putc(s, NEXTHOP_TYPE_IPV4); + stream_put_in_addr(s, &path->nexthop); + } else { + stream_putc(s, NEXTHOP_TYPE_IFINDEX); + stream_putl(s, path->ifindex); + } + + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) { + char buf[2][INET_ADDRSTRLEN]; + zlog_debug( + "Zebra: Route delete %s/%d nexthop %s", + inet_ntop(AF_INET, &p->prefix, buf[0], + sizeof(buf[0])), + p->prefixlen, + inet_ntop(AF_INET, &path->nexthop, + buf[1], sizeof(buf[1]))); + } + } + + if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) + stream_putc(s, distance); + if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) { + if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL) + stream_putl(s, or->cost + or->u.ext.type2_cost); + else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL) + stream_putl(s, or->u.ext.type2_cost); + else + stream_putl(s, or->cost); + } + + stream_putw_at(s, 0, stream_get_endp(s)); + + zclient_send_message(zclient); } - - stream_putw_at (s, 0, stream_get_endp (s)); - - zclient_send_message(zclient); - } } -void -ospf_zebra_add_discard (struct prefix_ipv4 *p) +void ospf_zebra_add_discard(struct prefix_ipv4 *p) { - struct zapi_ipv4 api; - struct ospf *ospf = ospf_lookup (); - - if ((ospf->instance && - redist_check_instance(&zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], ospf->instance)) - || - vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], VRF_DEFAULT)) - { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_OSPF; - api.instance = ospf->instance; - api.flags = ZEBRA_FLAG_BLACKHOLE; - api.message = 0; - api.safi = SAFI_UNICAST; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.ifindex_num = 0; - api.tag = 0; - - zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api); - - if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) - zlog_debug ("Zebra: Route add discard %s/%d", - inet_ntoa (p->prefix), p->prefixlen); - } + struct zapi_ipv4 api; + struct ospf *ospf = ospf_lookup(); + + if ((ospf->instance + && redist_check_instance( + &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], + ospf->instance)) + || vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], + VRF_DEFAULT)) { + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_OSPF; + api.instance = ospf->instance; + api.flags = ZEBRA_FLAG_BLACKHOLE; + api.message = 0; + api.safi = SAFI_UNICAST; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = 0; + api.ifindex_num = 0; + api.tag = 0; + + zapi_ipv4_route(ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api); + + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) + zlog_debug("Zebra: Route add discard %s/%d", + inet_ntoa(p->prefix), p->prefixlen); + } } -void -ospf_zebra_delete_discard (struct prefix_ipv4 *p) +void ospf_zebra_delete_discard(struct prefix_ipv4 *p) { - struct zapi_ipv4 api; - struct ospf *ospf = ospf_lookup (); - - if ((ospf->instance && - redist_check_instance(&zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], ospf->instance)) - || - vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], VRF_DEFAULT)) - { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_OSPF; - api.instance = ospf->instance; - api.flags = ZEBRA_FLAG_BLACKHOLE; - api.message = 0; - api.safi = SAFI_UNICAST; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 0; - api.ifindex_num = 0; - api.tag = 0; - - zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api); - - if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) - zlog_debug ("Zebra: Route delete discard %s/%d", - inet_ntoa (p->prefix), p->prefixlen); - - } + struct zapi_ipv4 api; + struct ospf *ospf = ospf_lookup(); + + if ((ospf->instance + && redist_check_instance( + &zclient->mi_redist[AFI_IP][ZEBRA_ROUTE_OSPF], + ospf->instance)) + || vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_OSPF], + VRF_DEFAULT)) { + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_OSPF; + api.instance = ospf->instance; + api.flags = ZEBRA_FLAG_BLACKHOLE; + api.message = 0; + api.safi = SAFI_UNICAST; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = 0; + api.ifindex_num = 0; + api.tag = 0; + + zapi_ipv4_route(ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api); + + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) + zlog_debug("Zebra: Route delete discard %s/%d", + inet_ntoa(p->prefix), p->prefixlen); + } } -struct ospf_external * -ospf_external_lookup (u_char type, u_short instance) +struct ospf_external *ospf_external_lookup(u_char type, u_short instance) { - struct list *ext_list; - struct listnode *node; - struct ospf_external *ext; + struct list *ext_list; + struct listnode *node; + struct ospf_external *ext; - ext_list = om->external[type]; - if (!ext_list) - return(NULL); + ext_list = om->external[type]; + if (!ext_list) + return (NULL); - for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) - if (ext->instance == instance) - return ext; + for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) + if (ext->instance == instance) + return ext; - return NULL; + return NULL; } -struct ospf_external * -ospf_external_add (u_char type, u_short instance) +struct ospf_external *ospf_external_add(u_char type, u_short instance) { - struct list *ext_list; - struct ospf_external *ext; + struct list *ext_list; + struct ospf_external *ext; - ext = ospf_external_lookup(type, instance); - if (ext) - return ext; + ext = ospf_external_lookup(type, instance); + if (ext) + return ext; - if (!om->external[type]) - om->external[type] = list_new(); + if (!om->external[type]) + om->external[type] = list_new(); - ext_list = om->external[type]; - ext = (struct ospf_external *)calloc (1, sizeof(struct ospf_external)); - ext->instance = instance; - EXTERNAL_INFO (ext) = route_table_init (); + ext_list = om->external[type]; + ext = (struct ospf_external *)calloc(1, sizeof(struct ospf_external)); + ext->instance = instance; + EXTERNAL_INFO(ext) = route_table_init(); - listnode_add(ext_list, ext); + listnode_add(ext_list, ext); - return ext; + return ext; } -void -ospf_external_del (u_char type, u_short instance) +void ospf_external_del(u_char type, u_short instance) { - struct ospf_external *ext; - - ext = ospf_external_lookup(type, instance); - - if (ext) - { - if (EXTERNAL_INFO (ext)) - route_table_finish(EXTERNAL_INFO (ext)); - - listnode_delete(om->external[type], ext); - if (!om->external[type]->count) - { - list_free(om->external[type]); - om->external[type] = NULL; - } - } + struct ospf_external *ext; + + ext = ospf_external_lookup(type, instance); + + if (ext) { + if (EXTERNAL_INFO(ext)) + route_table_finish(EXTERNAL_INFO(ext)); + + listnode_delete(om->external[type], ext); + if (!om->external[type]->count) { + list_free(om->external[type]); + om->external[type] = NULL; + } + } } -struct ospf_redist * -ospf_redist_lookup (struct ospf *ospf, u_char type, u_short instance) +struct ospf_redist *ospf_redist_lookup(struct ospf *ospf, u_char type, + u_short instance) { - struct list *red_list; - struct listnode *node; - struct ospf_redist *red; + struct list *red_list; + struct listnode *node; + struct ospf_redist *red; - red_list = ospf->redist[type]; - if (!red_list) - return(NULL); + red_list = ospf->redist[type]; + if (!red_list) + return (NULL); - for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) - if (red->instance == instance) - return red; + for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) + if (red->instance == instance) + return red; - return NULL; + return NULL; } -struct ospf_redist * -ospf_redist_add (struct ospf *ospf, u_char type, u_short instance) +struct ospf_redist *ospf_redist_add(struct ospf *ospf, u_char type, + u_short instance) { - struct list *red_list; - struct ospf_redist *red; + struct list *red_list; + struct ospf_redist *red; - red = ospf_redist_lookup(ospf, type, instance); - if (red) - return red; + red = ospf_redist_lookup(ospf, type, instance); + if (red) + return red; - if (!ospf->redist[type]) - ospf->redist[type] = list_new(); + if (!ospf->redist[type]) + ospf->redist[type] = list_new(); - red_list = ospf->redist[type]; - red = (struct ospf_redist *)calloc (1, sizeof(struct ospf_redist)); - red->instance = instance; - red->dmetric.type = -1; - red->dmetric.value = -1; + red_list = ospf->redist[type]; + red = (struct ospf_redist *)calloc(1, sizeof(struct ospf_redist)); + red->instance = instance; + red->dmetric.type = -1; + red->dmetric.value = -1; - listnode_add(red_list, red); + listnode_add(red_list, red); - return red; + return red; } -void -ospf_redist_del (struct ospf *ospf, u_char type, u_short instance) +void ospf_redist_del(struct ospf *ospf, u_char type, u_short instance) { - struct ospf_redist *red; - - red = ospf_redist_lookup(ospf, type, instance); - - if (red) - { - listnode_delete(ospf->redist[type], red); - if (!ospf->redist[type]->count) - { - list_free(ospf->redist[type]); - ospf->redist[type] = NULL; - } - } + struct ospf_redist *red; + + red = ospf_redist_lookup(ospf, type, instance); + + if (red) { + listnode_delete(ospf->redist[type], red); + if (!ospf->redist[type]->count) { + list_free(ospf->redist[type]); + ospf->redist[type] = NULL; + } + } } -int -ospf_is_type_redistributed (int type, u_short instance) +int ospf_is_type_redistributed(int type, u_short instance) { - return (DEFAULT_ROUTE_TYPE (type) ? - vrf_bitmap_check (zclient->default_information, VRF_DEFAULT) : - ((instance && redist_check_instance(&zclient->mi_redist[AFI_IP][type], instance)) - || (!instance && vrf_bitmap_check (zclient->redist[AFI_IP][type], VRF_DEFAULT)))); + return (DEFAULT_ROUTE_TYPE(type) + ? vrf_bitmap_check(zclient->default_information, + VRF_DEFAULT) + : ((instance + && redist_check_instance( + &zclient->mi_redist[AFI_IP][type], + instance)) + || (!instance + && vrf_bitmap_check( + zclient->redist[AFI_IP][type], + VRF_DEFAULT)))); } -int -ospf_redistribute_set (struct ospf *ospf, int type, u_short instance, int mtype, - int mvalue) +int ospf_redistribute_set(struct ospf *ospf, int type, u_short instance, + int mtype, int mvalue) { - int force = 0; - struct ospf_redist *red; - - red = ospf_redist_lookup(ospf, type, instance); - if (ospf_is_type_redistributed (type, instance)) - { - if (mtype != red->dmetric.type) - { - red->dmetric.type = mtype; - force = LSA_REFRESH_FORCE; - } - if (mvalue != red->dmetric.value) - { - red->dmetric.value = mvalue; - force = LSA_REFRESH_FORCE; - } - - ospf_external_lsa_refresh_type (ospf, type, instance, force); - - if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) - zlog_debug ("Redistribute[%s][%d]: Refresh Type[%d], Metric[%d]", - ospf_redist_string(type), instance, - metric_type (ospf, type, instance), - metric_value (ospf, type, instance)); - - return CMD_SUCCESS; - } - - red->dmetric.type = mtype; - red->dmetric.value = mvalue; - - ospf_external_add(type, instance); - - zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type, - instance, VRF_DEFAULT); - - if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) - zlog_debug ("Redistribute[%s][%d]: Start Type[%d], Metric[%d]", - ospf_redist_string(type), instance, - metric_type (ospf, type, instance), metric_value (ospf, type, instance)); - - ospf_asbr_status_update (ospf, ++ospf->redistribute); - - return CMD_SUCCESS; + int force = 0; + struct ospf_redist *red; + + red = ospf_redist_lookup(ospf, type, instance); + if (ospf_is_type_redistributed(type, instance)) { + if (mtype != red->dmetric.type) { + red->dmetric.type = mtype; + force = LSA_REFRESH_FORCE; + } + if (mvalue != red->dmetric.value) { + red->dmetric.value = mvalue; + force = LSA_REFRESH_FORCE; + } + + ospf_external_lsa_refresh_type(ospf, type, instance, force); + + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) + zlog_debug( + "Redistribute[%s][%d]: Refresh Type[%d], Metric[%d]", + ospf_redist_string(type), instance, + metric_type(ospf, type, instance), + metric_value(ospf, type, instance)); + + return CMD_SUCCESS; + } + + red->dmetric.type = mtype; + red->dmetric.value = mvalue; + + ospf_external_add(type, instance); + + zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type, + instance, VRF_DEFAULT); + + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) + zlog_debug("Redistribute[%s][%d]: Start Type[%d], Metric[%d]", + ospf_redist_string(type), instance, + metric_type(ospf, type, instance), + metric_value(ospf, type, instance)); + + ospf_asbr_status_update(ospf, ++ospf->redistribute); + + return CMD_SUCCESS; } -int -ospf_redistribute_unset (struct ospf *ospf, int type, u_short instance) +int ospf_redistribute_unset(struct ospf *ospf, int type, u_short instance) { - if (type == zclient->redist_default && instance == zclient->instance) - return CMD_SUCCESS; + if (type == zclient->redist_default && instance == zclient->instance) + return CMD_SUCCESS; - if (!ospf_is_type_redistributed (type, instance)) - return CMD_SUCCESS; + if (!ospf_is_type_redistributed(type, instance)) + return CMD_SUCCESS; - zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, type, - instance, VRF_DEFAULT); + zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, type, + instance, VRF_DEFAULT); - if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) - zlog_debug ("Redistribute[%s][%d]: Stop", - ospf_redist_string(type), instance); + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) + zlog_debug("Redistribute[%s][%d]: Stop", + ospf_redist_string(type), instance); - ospf_redist_del (ospf, type, instance); + ospf_redist_del(ospf, type, instance); - /* Remove the routes from OSPF table. */ - ospf_redistribute_withdraw (ospf, type, instance); + /* Remove the routes from OSPF table. */ + ospf_redistribute_withdraw(ospf, type, instance); - ospf_external_del(type, instance); + ospf_external_del(type, instance); - ospf_asbr_status_update (ospf, --ospf->redistribute); + ospf_asbr_status_update(ospf, --ospf->redistribute); - return CMD_SUCCESS; + return CMD_SUCCESS; } -int -ospf_redistribute_default_set (struct ospf *ospf, int originate, - int mtype, int mvalue) +int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype, + int mvalue) { - struct ospf_redist *red; + struct ospf_redist *red; - ospf->default_originate = originate; + ospf->default_originate = originate; - red = ospf_redist_add(ospf, DEFAULT_ROUTE, 0); - red->dmetric.type = mtype; - red->dmetric.value = mvalue; + red = ospf_redist_add(ospf, DEFAULT_ROUTE, 0); + red->dmetric.type = mtype; + red->dmetric.value = mvalue; - ospf_external_add(DEFAULT_ROUTE, 0); + ospf_external_add(DEFAULT_ROUTE, 0); - if (ospf_is_type_redistributed (DEFAULT_ROUTE, 0)) - { - /* if ospf->default_originate changes value, is calling - ospf_external_lsa_refresh_default sufficient to implement - the change? */ - ospf_external_lsa_refresh_default (ospf); + if (ospf_is_type_redistributed(DEFAULT_ROUTE, 0)) { + /* if ospf->default_originate changes value, is calling + ospf_external_lsa_refresh_default sufficient to implement + the change? */ + ospf_external_lsa_refresh_default(ospf); - if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) - zlog_debug ("Redistribute[%s]: Refresh Type[%d], Metric[%d]", - ospf_redist_string(DEFAULT_ROUTE), - metric_type (ospf, DEFAULT_ROUTE, 0), - metric_value (ospf, DEFAULT_ROUTE, 0)); - return CMD_SUCCESS; - } + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) + zlog_debug( + "Redistribute[%s]: Refresh Type[%d], Metric[%d]", + ospf_redist_string(DEFAULT_ROUTE), + metric_type(ospf, DEFAULT_ROUTE, 0), + metric_value(ospf, DEFAULT_ROUTE, 0)); + return CMD_SUCCESS; + } - zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, - VRF_DEFAULT); + zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, + VRF_DEFAULT); - if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) - zlog_debug ("Redistribute[DEFAULT]: Start Type[%d], Metric[%d]", - metric_type (ospf, DEFAULT_ROUTE, 0), - metric_value (ospf, DEFAULT_ROUTE, 0)); + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) + zlog_debug("Redistribute[DEFAULT]: Start Type[%d], Metric[%d]", + metric_type(ospf, DEFAULT_ROUTE, 0), + metric_value(ospf, DEFAULT_ROUTE, 0)); - if (ospf->router_id.s_addr == 0) - ospf->external_origin |= (1 << DEFAULT_ROUTE); - else - thread_add_timer(master, ospf_default_originate_timer, ospf, 1, NULL); + if (ospf->router_id.s_addr == 0) + ospf->external_origin |= (1 << DEFAULT_ROUTE); + else + thread_add_timer(master, ospf_default_originate_timer, ospf, 1, + NULL); - ospf_asbr_status_update (ospf, ++ospf->redistribute); + ospf_asbr_status_update(ospf, ++ospf->redistribute); - return CMD_SUCCESS; + return CMD_SUCCESS; } -int -ospf_redistribute_default_unset (struct ospf *ospf) +int ospf_redistribute_default_unset(struct ospf *ospf) { - if (!ospf_is_type_redistributed (DEFAULT_ROUTE, 0)) - return CMD_SUCCESS; + if (!ospf_is_type_redistributed(DEFAULT_ROUTE, 0)) + return CMD_SUCCESS; - ospf->default_originate = DEFAULT_ORIGINATE_NONE; - ospf_redist_del(ospf, DEFAULT_ROUTE, 0); + ospf->default_originate = DEFAULT_ORIGINATE_NONE; + ospf_redist_del(ospf, DEFAULT_ROUTE, 0); - zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient, - VRF_DEFAULT); + zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient, + VRF_DEFAULT); - if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) - zlog_debug ("Redistribute[DEFAULT]: Stop"); + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) + zlog_debug("Redistribute[DEFAULT]: Stop"); - //Pending: how does the external_info cleanup work in this case? + // Pending: how does the external_info cleanup work in this case? - ospf_asbr_status_update (ospf, --ospf->redistribute); + ospf_asbr_status_update(ospf, --ospf->redistribute); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -ospf_external_lsa_originate_check (struct ospf *ospf, - struct external_info *ei) +static int ospf_external_lsa_originate_check(struct ospf *ospf, + struct external_info *ei) { - /* If prefix is multicast, then do not originate LSA. */ - if (IN_MULTICAST (htonl (ei->p.prefix.s_addr))) - { - zlog_info ("LSA[Type5:%s]: Not originate AS-external-LSA, " - "Prefix belongs multicast", inet_ntoa (ei->p.prefix)); - return 0; - } - - /* Take care of default-originate. */ - if (is_prefix_default (&ei->p)) - if (ospf->default_originate == DEFAULT_ORIGINATE_NONE) - { - zlog_info ("LSA[Type5:0.0.0.0]: Not originate AS-external-LSA " - "for default"); - return 0; - } - - return 1; + /* If prefix is multicast, then do not originate LSA. */ + if (IN_MULTICAST(htonl(ei->p.prefix.s_addr))) { + zlog_info( + "LSA[Type5:%s]: Not originate AS-external-LSA, " + "Prefix belongs multicast", + inet_ntoa(ei->p.prefix)); + return 0; + } + + /* Take care of default-originate. */ + if (is_prefix_default(&ei->p)) + if (ospf->default_originate == DEFAULT_ORIGINATE_NONE) { + zlog_info( + "LSA[Type5:0.0.0.0]: Not originate AS-external-LSA " + "for default"); + return 0; + } + + return 1; } /* If connected prefix is OSPF enable interface, then do not announce. */ -int -ospf_distribute_check_connected (struct ospf *ospf, struct external_info *ei) +int ospf_distribute_check_connected(struct ospf *ospf, struct external_info *ei) { - struct listnode *node; - struct ospf_interface *oi; + struct listnode *node; + struct ospf_interface *oi; - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) - if (prefix_match (oi->address, (struct prefix *) &ei->p)) - return 0; - return 1; + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) + if (prefix_match(oi->address, (struct prefix *)&ei->p)) + return 0; + return 1; } /* return 1 if external LSA must be originated, 0 otherwise */ -int -ospf_redistribute_check (struct ospf *ospf, - struct external_info *ei, int *changed) +int ospf_redistribute_check(struct ospf *ospf, struct external_info *ei, + int *changed) { - struct route_map_set_values save_values; - struct prefix_ipv4 *p = &ei->p; - struct ospf_redist *red; - u_char type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type; - u_short instance = is_prefix_default (&ei->p) ? 0 : ei->instance; - - if (changed) - *changed = 0; - - if (!ospf_external_lsa_originate_check (ospf, ei)) - return 0; - - /* Take care connected route. */ - if (type == ZEBRA_ROUTE_CONNECT && - !ospf_distribute_check_connected (ospf, ei)) - return 0; - - if (!DEFAULT_ROUTE_TYPE (type) && DISTRIBUTE_NAME (ospf, type)) - /* distirbute-list exists, but access-list may not? */ - if (DISTRIBUTE_LIST (ospf, type)) - if (access_list_apply (DISTRIBUTE_LIST (ospf, type), p) == FILTER_DENY) - { - if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) - zlog_debug ("Redistribute[%s]: %s/%d filtered by ditribute-list.", - ospf_redist_string(type), - inet_ntoa (p->prefix), p->prefixlen); - return 0; - } - - save_values = ei->route_map_set; - ospf_reset_route_map_set_values (&ei->route_map_set); - - /* apply route-map if needed */ - red = ospf_redist_lookup (ospf, type, instance); - if (red && ROUTEMAP_NAME(red)) - { - int ret; - - ret = route_map_apply (ROUTEMAP (red), (struct prefix *) p, - RMAP_OSPF, ei); - - if (ret == RMAP_DENYMATCH) - { - ei->route_map_set = save_values; - if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) - zlog_debug ("Redistribute[%s]: %s/%d filtered by route-map.", - ospf_redist_string(type), - inet_ntoa (p->prefix), p->prefixlen); - return 0; - } - - /* check if 'route-map set' changed something */ - if (changed) - *changed = !ospf_route_map_set_compare (&ei->route_map_set, - &save_values); - } - - return 1; + struct route_map_set_values save_values; + struct prefix_ipv4 *p = &ei->p; + struct ospf_redist *red; + u_char type = is_prefix_default(&ei->p) ? DEFAULT_ROUTE : ei->type; + u_short instance = is_prefix_default(&ei->p) ? 0 : ei->instance; + + if (changed) + *changed = 0; + + if (!ospf_external_lsa_originate_check(ospf, ei)) + return 0; + + /* Take care connected route. */ + if (type == ZEBRA_ROUTE_CONNECT + && !ospf_distribute_check_connected(ospf, ei)) + return 0; + + if (!DEFAULT_ROUTE_TYPE(type) && DISTRIBUTE_NAME(ospf, type)) + /* distirbute-list exists, but access-list may not? */ + if (DISTRIBUTE_LIST(ospf, type)) + if (access_list_apply(DISTRIBUTE_LIST(ospf, type), p) + == FILTER_DENY) { + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) + zlog_debug( + "Redistribute[%s]: %s/%d filtered by ditribute-list.", + ospf_redist_string(type), + inet_ntoa(p->prefix), + p->prefixlen); + return 0; + } + + save_values = ei->route_map_set; + ospf_reset_route_map_set_values(&ei->route_map_set); + + /* apply route-map if needed */ + red = ospf_redist_lookup(ospf, type, instance); + if (red && ROUTEMAP_NAME(red)) { + int ret; + + ret = route_map_apply(ROUTEMAP(red), (struct prefix *)p, + RMAP_OSPF, ei); + + if (ret == RMAP_DENYMATCH) { + ei->route_map_set = save_values; + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) + zlog_debug( + "Redistribute[%s]: %s/%d filtered by route-map.", + ospf_redist_string(type), + inet_ntoa(p->prefix), p->prefixlen); + return 0; + } + + /* check if 'route-map set' changed something */ + if (changed) + *changed = !ospf_route_map_set_compare( + &ei->route_map_set, &save_values); + } + + return 1; } /* OSPF route-map set for redistribution */ -void -ospf_routemap_set (struct ospf_redist *red, const char *name) +void ospf_routemap_set(struct ospf_redist *red, const char *name) { - if (ROUTEMAP_NAME (red)) - free (ROUTEMAP_NAME (red)); + if (ROUTEMAP_NAME(red)) + free(ROUTEMAP_NAME(red)); - ROUTEMAP_NAME (red) = strdup (name); - ROUTEMAP (red) = route_map_lookup_by_name (name); + ROUTEMAP_NAME(red) = strdup(name); + ROUTEMAP(red) = route_map_lookup_by_name(name); } -void -ospf_routemap_unset (struct ospf_redist *red) +void ospf_routemap_unset(struct ospf_redist *red) { - if (ROUTEMAP_NAME (red)) - free (ROUTEMAP_NAME (red)); + if (ROUTEMAP_NAME(red)) + free(ROUTEMAP_NAME(red)); - ROUTEMAP_NAME (red) = NULL; - ROUTEMAP (red) = NULL; + ROUTEMAP_NAME(red) = NULL; + ROUTEMAP(red) = NULL; } /* Zebra route add and delete treatment. */ -static int -ospf_zebra_read_ipv4 (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int ospf_zebra_read_ipv4(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv4 api; - unsigned long ifindex; - struct in_addr nexthop; - struct prefix_ipv4 p; - struct external_info *ei; - struct ospf *ospf; - int i; - - s = zclient->ibuf; - ifindex = 0; - nexthop.s_addr = 0; - - /* Type, flags, message. */ - api.type = stream_getc (s); - api.instance = stream_getw (s); - api.flags = stream_getl (s); - api.message = stream_getc (s); - - /* IPv4 prefix. */ - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc (s)); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); - - if (IPV4_NET127(ntohl(p.prefix.s_addr))) - return 0; - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) - { - api.nexthop_num = stream_getc (s); - nexthop.s_addr = stream_get_ipv4 (s); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) - { - api.ifindex_num = stream_getc (s); - /* XXX assert(api.ifindex_num == 1); */ - ifindex = stream_getl (s); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc (s); - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl (s); - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl (s); - else - api.tag = 0; - - ospf = ospf_lookup (); - if (ospf == NULL) - return 0; - - if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) - { - /* XXX|HACK|TODO|FIXME: - * Maybe we should ignore reject/blackhole routes? Testing shows that - * there is no problems though and this is only way to "summarize" - * routes in ASBR at the moment. Maybe we need just a better generalised - * solution for these types? - * - * if ( CHECK_FLAG (api.flags, ZEBRA_FLAG_BLACKHOLE) - * || CHECK_FLAG (api.flags, ZEBRA_FLAG_REJECT)) - * return 0; - */ - - /* Protocol tag overwrites all other tag value send by zebra */ - if (ospf->dtag[api.type] > 0) - api.tag = ospf->dtag[api.type]; - - /* - * Given zebra sends update for a prefix via ADD message, it should - * be considered as an implicit DEL for that prefix with other source - * types. - */ - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (i != api.type) - ospf_external_info_delete(i, api.instance, p); - - ei = ospf_external_info_add (api.type, api.instance, p, ifindex, - nexthop, api.tag); - if (ei == NULL) + struct stream *s; + struct zapi_ipv4 api; + unsigned long ifindex; + struct in_addr nexthop; + struct prefix_ipv4 p; + struct external_info *ei; + struct ospf *ospf; + int i; + + s = zclient->ibuf; + ifindex = 0; + nexthop.s_addr = 0; + + /* Type, flags, message. */ + api.type = stream_getc(s); + api.instance = stream_getw(s); + api.flags = stream_getl(s); + api.message = stream_getc(s); + + /* IPv4 prefix. */ + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); + stream_get(&p.prefix, s, PSIZE(p.prefixlen)); + + if (IPV4_NET127(ntohl(p.prefix.s_addr))) + return 0; + + /* Nexthop, ifindex, distance, metric. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { + api.nexthop_num = stream_getc(s); + nexthop.s_addr = stream_get_ipv4(s); + } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { + api.ifindex_num = stream_getc(s); + /* XXX assert(api.ifindex_num == 1); */ + ifindex = stream_getl(s); + } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) + api.distance = stream_getc(s); + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) + api.metric = stream_getl(s); + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getl(s); + else + api.tag = 0; + + ospf = ospf_lookup(); + if (ospf == NULL) + return 0; + + if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) { + /* XXX|HACK|TODO|FIXME: + * Maybe we should ignore reject/blackhole routes? Testing shows + * that + * there is no problems though and this is only way to + * "summarize" + * routes in ASBR at the moment. Maybe we need just a better + * generalised + * solution for these types? + * + * if ( CHECK_FLAG (api.flags, ZEBRA_FLAG_BLACKHOLE) + * || CHECK_FLAG (api.flags, ZEBRA_FLAG_REJECT)) + * return 0; + */ + + /* Protocol tag overwrites all other tag value send by zebra */ + if (ospf->dtag[api.type] > 0) + api.tag = ospf->dtag[api.type]; + + /* + * Given zebra sends update for a prefix via ADD message, it + * should + * be considered as an implicit DEL for that prefix with other + * source + * types. + */ + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (i != api.type) + ospf_external_info_delete(i, api.instance, p); + + ei = ospf_external_info_add(api.type, api.instance, p, ifindex, + nexthop, api.tag); + if (ei == NULL) { + /* Nothing has changed, so nothing to do; return */ + return 0; + } + if (ospf->router_id.s_addr == 0) + /* Set flags to generate AS-external-LSA originate event + for each redistributed protocols later. */ + ospf->external_origin |= (1 << api.type); + else { + if (ei) { + if (is_prefix_default(&p)) + ospf_external_lsa_refresh_default(ospf); + else { + struct ospf_lsa *current; + + current = ospf_external_info_find_lsa( + ospf, &ei->p); + if (!current) + ospf_external_lsa_originate( + ospf, ei); + else { + if (IS_DEBUG_OSPF( + zebra, + ZEBRA_REDISTRIBUTE)) + zlog_debug( + "ospf_zebra_read_ipv4() : %s refreshing LSA", + inet_ntoa( + p.prefix)); + ospf_external_lsa_refresh( + ospf, current, ei, + LSA_REFRESH_FORCE); + } + } + } + } + } else /* if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) */ { - /* Nothing has changed, so nothing to do; return */ - return 0; + ospf_external_info_delete(api.type, api.instance, p); + if (is_prefix_default(&p)) + ospf_external_lsa_refresh_default(ospf); + else + ospf_external_lsa_flush(ospf, api.type, &p, + ifindex /*, nexthop */); } - if (ospf->router_id.s_addr == 0) - /* Set flags to generate AS-external-LSA originate event - for each redistributed protocols later. */ - ospf->external_origin |= (1 << api.type); - else - { - if (ei) - { - if (is_prefix_default (&p)) - ospf_external_lsa_refresh_default (ospf); - else - { - struct ospf_lsa *current; - - current = ospf_external_info_find_lsa (ospf, &ei->p); - if (!current) - ospf_external_lsa_originate (ospf, ei); - else - { - if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) - zlog_debug ("ospf_zebra_read_ipv4() : %s refreshing LSA", - inet_ntoa (p.prefix)); - ospf_external_lsa_refresh (ospf, current, - ei, LSA_REFRESH_FORCE); - } - } - } - } - } - else /* if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) */ - { - ospf_external_info_delete (api.type, api.instance, p); - if (is_prefix_default (&p)) - ospf_external_lsa_refresh_default (ospf); - else - ospf_external_lsa_flush (ospf, api.type, &p, ifindex /*, nexthop */); - } - - return 0; + + return 0; } -int -ospf_distribute_list_out_set (struct ospf *ospf, int type, const char *name) +int ospf_distribute_list_out_set(struct ospf *ospf, int type, const char *name) { - /* Lookup access-list for distribute-list. */ - DISTRIBUTE_LIST (ospf, type) = access_list_lookup (AFI_IP, name); + /* Lookup access-list for distribute-list. */ + DISTRIBUTE_LIST(ospf, type) = access_list_lookup(AFI_IP, name); - /* Clear previous distribute-name. */ - if (DISTRIBUTE_NAME (ospf, type)) - free (DISTRIBUTE_NAME (ospf, type)); + /* Clear previous distribute-name. */ + if (DISTRIBUTE_NAME(ospf, type)) + free(DISTRIBUTE_NAME(ospf, type)); - /* Set distribute-name. */ - DISTRIBUTE_NAME (ospf, type) = strdup (name); + /* Set distribute-name. */ + DISTRIBUTE_NAME(ospf, type) = strdup(name); - /* If access-list have been set, schedule update timer. */ - if (DISTRIBUTE_LIST (ospf, type)) - ospf_distribute_list_update (ospf, type, 0); + /* If access-list have been set, schedule update timer. */ + if (DISTRIBUTE_LIST(ospf, type)) + ospf_distribute_list_update(ospf, type, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } -int -ospf_distribute_list_out_unset (struct ospf *ospf, int type, const char *name) +int ospf_distribute_list_out_unset(struct ospf *ospf, int type, + const char *name) { - /* Schedule update timer. */ - if (DISTRIBUTE_LIST (ospf, type)) - ospf_distribute_list_update (ospf, type, 0); + /* Schedule update timer. */ + if (DISTRIBUTE_LIST(ospf, type)) + ospf_distribute_list_update(ospf, type, 0); - /* Unset distribute-list. */ - DISTRIBUTE_LIST (ospf, type) = NULL; + /* Unset distribute-list. */ + DISTRIBUTE_LIST(ospf, type) = NULL; - /* Clear distribute-name. */ - if (DISTRIBUTE_NAME (ospf, type)) - free (DISTRIBUTE_NAME (ospf, type)); + /* Clear distribute-name. */ + if (DISTRIBUTE_NAME(ospf, type)) + free(DISTRIBUTE_NAME(ospf, type)); - DISTRIBUTE_NAME (ospf, type) = NULL; + DISTRIBUTE_NAME(ospf, type) = NULL; - return CMD_SUCCESS; + return CMD_SUCCESS; } /* distribute-list update timer. */ -static int -ospf_distribute_list_update_timer (struct thread *thread) +static int ospf_distribute_list_update_timer(struct thread *thread) { - struct route_node *rn; - struct external_info *ei; - struct route_table *rt; - struct ospf_lsa *lsa; - int type, default_refresh = 0; - struct ospf *ospf; - - ospf = ospf_lookup (); - if (ospf == NULL) - return 0; - - ospf->t_distribute_update = NULL; - - zlog_info ("Zebra[Redistribute]: distribute-list update timer fired!"); - - /* foreach all external info. */ - for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) - { - struct list *ext_list; - struct listnode *node; - struct ospf_external *ext; - - ext_list = om->external[type]; - if (!ext_list) - continue; - - for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) - { - rt = ext->external_info; - if (!rt) - continue; - for (rn = route_top (rt); rn; rn = route_next (rn)) - if ((ei = rn->info) != NULL) - { - if (is_prefix_default (&ei->p)) - default_refresh = 1; - else if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p))) - ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_IF_CHANGED); - else - ospf_external_lsa_originate (ospf, ei); - } - } - } - if (default_refresh) - ospf_external_lsa_refresh_default (ospf); - return 0; + struct route_node *rn; + struct external_info *ei; + struct route_table *rt; + struct ospf_lsa *lsa; + int type, default_refresh = 0; + struct ospf *ospf; + + ospf = ospf_lookup(); + if (ospf == NULL) + return 0; + + ospf->t_distribute_update = NULL; + + zlog_info("Zebra[Redistribute]: distribute-list update timer fired!"); + + /* foreach all external info. */ + for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { + struct list *ext_list; + struct listnode *node; + struct ospf_external *ext; + + ext_list = om->external[type]; + if (!ext_list) + continue; + + for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) { + rt = ext->external_info; + if (!rt) + continue; + for (rn = route_top(rt); rn; rn = route_next(rn)) + if ((ei = rn->info) != NULL) { + if (is_prefix_default(&ei->p)) + default_refresh = 1; + else if ( + (lsa = ospf_external_info_find_lsa( + ospf, &ei->p))) + ospf_external_lsa_refresh( + ospf, lsa, ei, + LSA_REFRESH_IF_CHANGED); + else + ospf_external_lsa_originate( + ospf, ei); + } + } + } + if (default_refresh) + ospf_external_lsa_refresh_default(ospf); + return 0; } /* Update distribute-list and set timer to apply access-list. */ -void -ospf_distribute_list_update (struct ospf *ospf, uintptr_t type, - u_short instance) +void ospf_distribute_list_update(struct ospf *ospf, uintptr_t type, + u_short instance) { - struct route_table *rt; - struct ospf_external *ext; - - /* External info does not exist. */ - ext = ospf_external_lookup(type, instance); - if (!ext || !(rt = EXTERNAL_INFO (ext))) - return; - - /* If exists previously invoked thread, then let it continue. */ - if (ospf->t_distribute_update) - return; - - /* Set timer. */ - ospf->t_distribute_update = NULL; - thread_add_timer_msec(master, ospf_distribute_list_update_timer, (void *)type, ospf->min_ls_interval, - &ospf->t_distribute_update); + struct route_table *rt; + struct ospf_external *ext; + + /* External info does not exist. */ + ext = ospf_external_lookup(type, instance); + if (!ext || !(rt = EXTERNAL_INFO(ext))) + return; + + /* If exists previously invoked thread, then let it continue. */ + if (ospf->t_distribute_update) + return; + + /* Set timer. */ + ospf->t_distribute_update = NULL; + thread_add_timer_msec(master, ospf_distribute_list_update_timer, + (void *)type, ospf->min_ls_interval, + &ospf->t_distribute_update); } /* If access-list is updated, apply some check. */ -static void -ospf_filter_update (struct access_list *access) +static void ospf_filter_update(struct access_list *access) { - struct ospf *ospf; - int type; - int abr_inv = 0; - struct ospf_area *area; - struct listnode *node; - - /* If OSPF instance does not exist, return right now. */ - ospf = ospf_lookup (); - if (ospf == NULL) - return; - - /* Update distribute-list, and apply filter. */ - for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) - { - struct list *red_list; - struct listnode *node; - struct ospf_redist *red; - - red_list = ospf->redist[type]; - if (red_list) - for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) - { - if (ROUTEMAP (red)) - { - /* if route-map is not NULL it may be using this access list */ - ospf_distribute_list_update (ospf, type, red->instance); - } - } - - /* There is place for route-map for default-information (ZEBRA_ROUTE_MAX), - * but no distribute list. */ - if (type == ZEBRA_ROUTE_MAX) - break; - - if (DISTRIBUTE_NAME (ospf, type)) - { - /* Keep old access-list for distribute-list. */ - struct access_list *old = DISTRIBUTE_LIST (ospf, type); - - /* Update access-list for distribute-list. */ - DISTRIBUTE_LIST (ospf, type) = - access_list_lookup (AFI_IP, DISTRIBUTE_NAME (ospf, type)); - - /* No update for this distribute type. */ - if (old == NULL && DISTRIBUTE_LIST (ospf, type) == NULL) - continue; - - /* Schedule distribute-list update timer. */ - if (DISTRIBUTE_LIST (ospf, type) == NULL || - strcmp (DISTRIBUTE_NAME (ospf, type), access->name) == 0) - ospf_distribute_list_update (ospf, type, 0); - } - } - - /* Update Area access-list. */ - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - if (EXPORT_NAME (area)) - { - EXPORT_LIST (area) = NULL; - abr_inv++; - } - - if (IMPORT_NAME (area)) - { - IMPORT_LIST (area) = NULL; - abr_inv++; - } - } - - /* Schedule ABR tasks -- this will be changed -- takada. */ - if (IS_OSPF_ABR (ospf) && abr_inv) - ospf_schedule_abr_task (ospf); + struct ospf *ospf; + int type; + int abr_inv = 0; + struct ospf_area *area; + struct listnode *node; + + /* If OSPF instance does not exist, return right now. */ + ospf = ospf_lookup(); + if (ospf == NULL) + return; + + /* Update distribute-list, and apply filter. */ + for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { + struct list *red_list; + struct listnode *node; + struct ospf_redist *red; + + red_list = ospf->redist[type]; + if (red_list) + for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { + if (ROUTEMAP(red)) { + /* if route-map is not NULL it may be + * using this access list */ + ospf_distribute_list_update( + ospf, type, red->instance); + } + } + + /* There is place for route-map for default-information + * (ZEBRA_ROUTE_MAX), + * but no distribute list. */ + if (type == ZEBRA_ROUTE_MAX) + break; + + if (DISTRIBUTE_NAME(ospf, type)) { + /* Keep old access-list for distribute-list. */ + struct access_list *old = DISTRIBUTE_LIST(ospf, type); + + /* Update access-list for distribute-list. */ + DISTRIBUTE_LIST(ospf, type) = access_list_lookup( + AFI_IP, DISTRIBUTE_NAME(ospf, type)); + + /* No update for this distribute type. */ + if (old == NULL && DISTRIBUTE_LIST(ospf, type) == NULL) + continue; + + /* Schedule distribute-list update timer. */ + if (DISTRIBUTE_LIST(ospf, type) == NULL + || strcmp(DISTRIBUTE_NAME(ospf, type), access->name) + == 0) + ospf_distribute_list_update(ospf, type, 0); + } + } + + /* Update Area access-list. */ + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + if (EXPORT_NAME(area)) { + EXPORT_LIST(area) = NULL; + abr_inv++; + } + + if (IMPORT_NAME(area)) { + IMPORT_LIST(area) = NULL; + abr_inv++; + } + } + + /* Schedule ABR tasks -- this will be changed -- takada. */ + if (IS_OSPF_ABR(ospf) && abr_inv) + ospf_schedule_abr_task(ospf); } /* If prefix-list is updated, do some updates. */ -void -ospf_prefix_list_update (struct prefix_list *plist) +void ospf_prefix_list_update(struct prefix_list *plist) { - struct ospf *ospf; - int type; - int abr_inv = 0; - struct ospf_area *area; - struct listnode *node; - - /* If OSPF instatnce does not exist, return right now. */ - ospf = ospf_lookup (); - if (ospf == NULL) - return; - - /* Update all route-maps which are used as redistribution filters. - * They might use prefix-list. - */ - for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) - { - struct list *red_list; - struct listnode *node; - struct ospf_redist *red; - - red_list = ospf->redist[type]; - if (red_list) - for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) - { - if (ROUTEMAP (red)) - { - /* if route-map is not NULL it may be using this prefix list */ - ospf_distribute_list_update (ospf, type, red->instance); - } - } - } - - /* Update area filter-lists. */ - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - /* Update filter-list in. */ - if (PREFIX_NAME_IN (area)) - if (strcmp (PREFIX_NAME_IN (area), prefix_list_name (plist)) == 0) - { - PREFIX_LIST_IN (area) = - prefix_list_lookup (AFI_IP, PREFIX_NAME_IN (area)); - abr_inv++; - } - - /* Update filter-list out. */ - if (PREFIX_NAME_OUT (area)) - if (strcmp (PREFIX_NAME_OUT (area), prefix_list_name (plist)) == 0) - { - PREFIX_LIST_IN (area) = - prefix_list_lookup (AFI_IP, PREFIX_NAME_OUT (area)); - abr_inv++; - } - } - - /* Schedule ABR task. */ - if (IS_OSPF_ABR (ospf) && abr_inv) - ospf_schedule_abr_task (ospf); + struct ospf *ospf; + int type; + int abr_inv = 0; + struct ospf_area *area; + struct listnode *node; + + /* If OSPF instatnce does not exist, return right now. */ + ospf = ospf_lookup(); + if (ospf == NULL) + return; + + /* Update all route-maps which are used as redistribution filters. + * They might use prefix-list. + */ + for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { + struct list *red_list; + struct listnode *node; + struct ospf_redist *red; + + red_list = ospf->redist[type]; + if (red_list) + for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { + if (ROUTEMAP(red)) { + /* if route-map is not NULL it may be + * using this prefix list */ + ospf_distribute_list_update( + ospf, type, red->instance); + } + } + } + + /* Update area filter-lists. */ + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + /* Update filter-list in. */ + if (PREFIX_NAME_IN(area)) + if (strcmp(PREFIX_NAME_IN(area), + prefix_list_name(plist)) + == 0) { + PREFIX_LIST_IN(area) = prefix_list_lookup( + AFI_IP, PREFIX_NAME_IN(area)); + abr_inv++; + } + + /* Update filter-list out. */ + if (PREFIX_NAME_OUT(area)) + if (strcmp(PREFIX_NAME_OUT(area), + prefix_list_name(plist)) + == 0) { + PREFIX_LIST_IN(area) = prefix_list_lookup( + AFI_IP, PREFIX_NAME_OUT(area)); + abr_inv++; + } + } + + /* Schedule ABR task. */ + if (IS_OSPF_ABR(ospf) && abr_inv) + ospf_schedule_abr_task(ospf); } -static struct ospf_distance * -ospf_distance_new (void) +static struct ospf_distance *ospf_distance_new(void) { - return XCALLOC (MTYPE_OSPF_DISTANCE, sizeof (struct ospf_distance)); + return XCALLOC(MTYPE_OSPF_DISTANCE, sizeof(struct ospf_distance)); } -static void -ospf_distance_free (struct ospf_distance *odistance) +static void ospf_distance_free(struct ospf_distance *odistance) { - XFREE (MTYPE_OSPF_DISTANCE, odistance); + XFREE(MTYPE_OSPF_DISTANCE, odistance); } -int -ospf_distance_set (struct vty *vty, struct ospf *ospf, - const char *distance_str, - const char *ip_str, - const char *access_list_str) +int ospf_distance_set(struct vty *vty, struct ospf *ospf, + const char *distance_str, const char *ip_str, + const char *access_list_str) { - int ret; - struct prefix_ipv4 p; - u_char distance; - struct route_node *rn; - struct ospf_distance *odistance; - - ret = str2prefix_ipv4 (ip_str, &p); - if (ret == 0) - { - vty_out (vty, "Malformed prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - distance = atoi (distance_str); - - /* Get OSPF distance node. */ - rn = route_node_get (ospf->distance_table, (struct prefix *) &p); - if (rn->info) - { - odistance = rn->info; - route_unlock_node (rn); - } - else - { - odistance = ospf_distance_new (); - rn->info = odistance; - } - - /* Set distance value. */ - odistance->distance = distance; - - /* Reset access-list configuration. */ - if (odistance->access_list) - { - free (odistance->access_list); - odistance->access_list = NULL; - } - if (access_list_str) - odistance->access_list = strdup (access_list_str); - - return CMD_SUCCESS; + int ret; + struct prefix_ipv4 p; + u_char distance; + struct route_node *rn; + struct ospf_distance *odistance; + + ret = str2prefix_ipv4(ip_str, &p); + if (ret == 0) { + vty_out(vty, "Malformed prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + distance = atoi(distance_str); + + /* Get OSPF distance node. */ + rn = route_node_get(ospf->distance_table, (struct prefix *)&p); + if (rn->info) { + odistance = rn->info; + route_unlock_node(rn); + } else { + odistance = ospf_distance_new(); + rn->info = odistance; + } + + /* Set distance value. */ + odistance->distance = distance; + + /* Reset access-list configuration. */ + if (odistance->access_list) { + free(odistance->access_list); + odistance->access_list = NULL; + } + if (access_list_str) + odistance->access_list = strdup(access_list_str); + + return CMD_SUCCESS; } -int -ospf_distance_unset (struct vty *vty, struct ospf *ospf, - const char *distance_str, - const char *ip_str, char - const *access_list_str) +int ospf_distance_unset(struct vty *vty, struct ospf *ospf, + const char *distance_str, const char *ip_str, + char const *access_list_str) { - int ret; - struct prefix_ipv4 p; - struct route_node *rn; - struct ospf_distance *odistance; - - ret = str2prefix_ipv4 (ip_str, &p); - if (ret == 0) - { - vty_out (vty, "Malformed prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - rn = route_node_lookup (ospf->distance_table, (struct prefix *) &p); - if (!rn) - { - vty_out (vty, "Can't find specified prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - odistance = rn->info; - - if (odistance->access_list) - free (odistance->access_list); - ospf_distance_free (odistance); - - rn->info = NULL; - route_unlock_node (rn); - route_unlock_node (rn); - - return CMD_SUCCESS; + int ret; + struct prefix_ipv4 p; + struct route_node *rn; + struct ospf_distance *odistance; + + ret = str2prefix_ipv4(ip_str, &p); + if (ret == 0) { + vty_out(vty, "Malformed prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + rn = route_node_lookup(ospf->distance_table, (struct prefix *)&p); + if (!rn) { + vty_out(vty, "Can't find specified prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + odistance = rn->info; + + if (odistance->access_list) + free(odistance->access_list); + ospf_distance_free(odistance); + + rn->info = NULL; + route_unlock_node(rn); + route_unlock_node(rn); + + return CMD_SUCCESS; } -void -ospf_distance_reset (struct ospf *ospf) +void ospf_distance_reset(struct ospf *ospf) { - struct route_node *rn; - struct ospf_distance *odistance; - - for (rn = route_top (ospf->distance_table); rn; rn = route_next (rn)) - if ((odistance = rn->info) != NULL) - { - if (odistance->access_list) - free (odistance->access_list); - ospf_distance_free (odistance); - rn->info = NULL; - route_unlock_node (rn); - } + struct route_node *rn; + struct ospf_distance *odistance; + + for (rn = route_top(ospf->distance_table); rn; rn = route_next(rn)) + if ((odistance = rn->info) != NULL) { + if (odistance->access_list) + free(odistance->access_list); + ospf_distance_free(odistance); + rn->info = NULL; + route_unlock_node(rn); + } } -u_char -ospf_distance_apply (struct prefix_ipv4 *p, struct ospf_route *or) +u_char ospf_distance_apply(struct prefix_ipv4 *p, struct ospf_route * or) { - struct ospf *ospf; + struct ospf *ospf; - ospf = ospf_lookup (); - if (ospf == NULL) - return 0; + ospf = ospf_lookup(); + if (ospf == NULL) + return 0; - if (ospf->distance_intra) - if (or->path_type == OSPF_PATH_INTRA_AREA) - return ospf->distance_intra; + if (ospf->distance_intra) + if (or->path_type == OSPF_PATH_INTRA_AREA) + return ospf->distance_intra; - if (ospf->distance_inter) - if (or->path_type == OSPF_PATH_INTER_AREA) - return ospf->distance_inter; + if (ospf->distance_inter) + if (or->path_type == OSPF_PATH_INTER_AREA) + return ospf->distance_inter; - if (ospf->distance_external) - if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL - || or->path_type == OSPF_PATH_TYPE2_EXTERNAL) - return ospf->distance_external; + if (ospf->distance_external) + if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL || + or->path_type == OSPF_PATH_TYPE2_EXTERNAL) + return ospf->distance_external; - if (ospf->distance_all) - return ospf->distance_all; + if (ospf->distance_all) + return ospf->distance_all; - return 0; + return 0; } -static void -ospf_zebra_connected (struct zclient *zclient) +static void ospf_zebra_connected(struct zclient *zclient) { - /* Send the client registration */ - bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); + /* Send the client registration */ + bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); - zclient_send_reg_requests (zclient, VRF_DEFAULT); + zclient_send_reg_requests(zclient, VRF_DEFAULT); } -void -ospf_zebra_init (struct thread_master *master, u_short instance) +void ospf_zebra_init(struct thread_master *master, u_short instance) { - /* Allocate zebra structure. */ - zclient = zclient_new(master); - zclient_init (zclient, ZEBRA_ROUTE_OSPF, instance); - zclient->zebra_connected = ospf_zebra_connected; - zclient->router_id_update = ospf_router_id_update_zebra; - zclient->interface_add = ospf_interface_add; - zclient->interface_delete = ospf_interface_delete; - zclient->interface_up = ospf_interface_state_up; - zclient->interface_down = ospf_interface_state_down; - zclient->interface_address_add = ospf_interface_address_add; - zclient->interface_address_delete = ospf_interface_address_delete; - zclient->interface_link_params = ospf_interface_link_params; - - zclient->redistribute_route_ipv4_add = ospf_zebra_read_ipv4; - zclient->redistribute_route_ipv4_del = ospf_zebra_read_ipv4; - - access_list_add_hook (ospf_filter_update); - access_list_delete_hook (ospf_filter_update); - prefix_list_add_hook (ospf_prefix_list_update); - prefix_list_delete_hook (ospf_prefix_list_update); + /* Allocate zebra structure. */ + zclient = zclient_new(master); + zclient_init(zclient, ZEBRA_ROUTE_OSPF, instance); + zclient->zebra_connected = ospf_zebra_connected; + zclient->router_id_update = ospf_router_id_update_zebra; + zclient->interface_add = ospf_interface_add; + zclient->interface_delete = ospf_interface_delete; + zclient->interface_up = ospf_interface_state_up; + zclient->interface_down = ospf_interface_state_down; + zclient->interface_address_add = ospf_interface_address_add; + zclient->interface_address_delete = ospf_interface_address_delete; + zclient->interface_link_params = ospf_interface_link_params; + + zclient->redistribute_route_ipv4_add = ospf_zebra_read_ipv4; + zclient->redistribute_route_ipv4_del = ospf_zebra_read_ipv4; + + access_list_add_hook(ospf_filter_update); + access_list_delete_hook(ospf_filter_update); + prefix_list_add_hook(ospf_prefix_list_update); + prefix_list_delete_hook(ospf_prefix_list_update); } diff --git a/ospfd/ospf_zebra.h b/ospfd/ospf_zebra.h index c0b99a95a..6fa9e33dd 100644 --- a/ospfd/ospf_zebra.h +++ b/ospfd/ospf_zebra.h @@ -32,55 +32,53 @@ #define DEFAULT_ROUTE_TYPE(T) ((T) == DEFAULT_ROUTE) /* OSPF distance. */ -struct ospf_distance -{ - /* Distance value for the IP source prefix. */ - u_char distance; +struct ospf_distance { + /* Distance value for the IP source prefix. */ + u_char distance; - /* Name of the access-list to be matched. */ - char *access_list; + /* Name of the access-list to be matched. */ + char *access_list; }; /* Prototypes */ -extern void ospf_zebra_add (struct prefix_ipv4 *, struct ospf_route *); -extern void ospf_zebra_delete (struct prefix_ipv4 *, struct ospf_route *); +extern void ospf_zebra_add(struct prefix_ipv4 *, struct ospf_route *); +extern void ospf_zebra_delete(struct prefix_ipv4 *, struct ospf_route *); -extern void ospf_zebra_add_discard (struct prefix_ipv4 *); -extern void ospf_zebra_delete_discard (struct prefix_ipv4 *); +extern void ospf_zebra_add_discard(struct prefix_ipv4 *); +extern void ospf_zebra_delete_discard(struct prefix_ipv4 *); -extern int ospf_redistribute_check (struct ospf *, struct external_info *, - int *); -extern int ospf_distribute_check_connected (struct ospf *, - struct external_info *); -extern void ospf_distribute_list_update (struct ospf *, uintptr_t, u_short); +extern int ospf_redistribute_check(struct ospf *, struct external_info *, + int *); +extern int ospf_distribute_check_connected(struct ospf *, + struct external_info *); +extern void ospf_distribute_list_update(struct ospf *, uintptr_t, u_short); -extern int ospf_is_type_redistributed (int, u_short); -extern void ospf_distance_reset (struct ospf *); -extern u_char ospf_distance_apply (struct prefix_ipv4 *, struct ospf_route *); -extern struct ospf_external *ospf_external_lookup (u_char, u_short); -extern struct ospf_external *ospf_external_add (u_char, u_short); -extern void ospf_external_del (u_char, u_short); -extern struct ospf_redist *ospf_redist_lookup (struct ospf *, u_char, u_short); -extern struct ospf_redist *ospf_redist_add (struct ospf *, u_char, u_short); -extern void ospf_redist_del (struct ospf *, u_char, u_short); +extern int ospf_is_type_redistributed(int, u_short); +extern void ospf_distance_reset(struct ospf *); +extern u_char ospf_distance_apply(struct prefix_ipv4 *, struct ospf_route *); +extern struct ospf_external *ospf_external_lookup(u_char, u_short); +extern struct ospf_external *ospf_external_add(u_char, u_short); +extern void ospf_external_del(u_char, u_short); +extern struct ospf_redist *ospf_redist_lookup(struct ospf *, u_char, u_short); +extern struct ospf_redist *ospf_redist_add(struct ospf *, u_char, u_short); +extern void ospf_redist_del(struct ospf *, u_char, u_short); -extern int ospf_redistribute_set (struct ospf *, int, u_short, int, int); -extern int ospf_redistribute_unset (struct ospf *, int, u_short); -extern int ospf_redistribute_default_set (struct ospf *, int, int, int); -extern int ospf_redistribute_default_unset (struct ospf *); -extern int ospf_distribute_list_out_set (struct ospf *, int, const char *); -extern int ospf_distribute_list_out_unset (struct ospf *, int, const char *); -extern void ospf_routemap_set (struct ospf_redist *, const char *); -extern void ospf_routemap_unset (struct ospf_redist *); -extern int ospf_distance_set (struct vty *, struct ospf *, const char *, - const char *, const char *); -extern int ospf_distance_unset (struct vty *, struct ospf *, const char *, - const char *, const char *); +extern int ospf_redistribute_set(struct ospf *, int, u_short, int, int); +extern int ospf_redistribute_unset(struct ospf *, int, u_short); +extern int ospf_redistribute_default_set(struct ospf *, int, int, int); +extern int ospf_redistribute_default_unset(struct ospf *); +extern int ospf_distribute_list_out_set(struct ospf *, int, const char *); +extern int ospf_distribute_list_out_unset(struct ospf *, int, const char *); +extern void ospf_routemap_set(struct ospf_redist *, const char *); +extern void ospf_routemap_unset(struct ospf_redist *); +extern int ospf_distance_set(struct vty *, struct ospf *, const char *, + const char *, const char *); +extern int ospf_distance_unset(struct vty *, struct ospf *, const char *, + const char *, const char *); extern void ospf_zebra_init(struct thread_master *, u_short); -DECLARE_HOOK(ospf_if_update, (struct interface *ifp), (ifp)) -DECLARE_HOOK(ospf_if_delete, (struct interface *ifp), (ifp)) +DECLARE_HOOK(ospf_if_update, (struct interface * ifp), (ifp)) +DECLARE_HOOK(ospf_if_delete, (struct interface * ifp), (ifp)) #endif /* _ZEBRA_OSPF_ZEBRA_H */ - diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 9af9f7f31..cee2244dd 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -30,7 +30,7 @@ #include "memory.h" #include "stream.h" #include "log.h" -#include "sockunion.h" /* for inet_aton () */ +#include "sockunion.h" /* for inet_aton () */ #include "zclient.h" #include "plist.h" #include "sockopt.h" @@ -68,331 +68,328 @@ extern struct zclient *zclient; extern struct in_addr router_id_zebra; -static void ospf_remove_vls_through_area (struct ospf *, struct ospf_area *); -static void ospf_network_free (struct ospf *, struct ospf_network *); -static void ospf_area_free (struct ospf_area *); -static void ospf_network_run (struct prefix *, struct ospf_area *); -static void ospf_network_run_interface (struct ospf *, struct interface *, - struct prefix *, struct ospf_area *); -static void ospf_network_run_subnet (struct ospf *, struct connected *, - struct prefix *, struct ospf_area *); -static int ospf_network_match_iface (const struct connected *, - const struct prefix *); -static void ospf_finish_final (struct ospf *); +static void ospf_remove_vls_through_area(struct ospf *, struct ospf_area *); +static void ospf_network_free(struct ospf *, struct ospf_network *); +static void ospf_area_free(struct ospf_area *); +static void ospf_network_run(struct prefix *, struct ospf_area *); +static void ospf_network_run_interface(struct ospf *, struct interface *, + struct prefix *, struct ospf_area *); +static void ospf_network_run_subnet(struct ospf *, struct connected *, + struct prefix *, struct ospf_area *); +static int ospf_network_match_iface(const struct connected *, + const struct prefix *); +static void ospf_finish_final(struct ospf *); #define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1 -void -ospf_router_id_update (struct ospf *ospf) +void ospf_router_id_update(struct ospf *ospf) { - struct in_addr router_id, router_id_old; - struct ospf_interface *oi; - struct interface *ifp; - struct listnode *node; - int type; - - if (!ospf->oi_running) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Router ospf not configured -- Router-ID update postponed"); - return; - } - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Router-ID[OLD:%s]: Update", inet_ntoa (ospf->router_id)); - - router_id_old = ospf->router_id; - - /* Select the router ID based on these priorities: - 1. Statically assigned router ID is always the first choice. - 2. If there is no statically assigned router ID, then try to stick - with the most recent value, since changing router ID's is very - disruptive. - 3. Last choice: just go with whatever the zebra daemon recommends. - */ - if (ospf->router_id_static.s_addr != 0) - router_id = ospf->router_id_static; - else if (ospf->router_id.s_addr != 0) - router_id = ospf->router_id; - else - router_id = router_id_zebra; - - - if (!IPV4_ADDR_SAME (&router_id_old, &router_id)) - { + struct in_addr router_id, router_id_old; + struct ospf_interface *oi; + struct interface *ifp; + struct listnode *node; + int type; - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) - { - /* Some nbrs are identified by router_id, these needs - * to be rebuilt. Possible optimization would be to do - * oi->nbr_self->router_id = router_id for - * !(virtual | ptop) links - */ - ospf_nbr_self_reset (oi, router_id); + if (!ospf->oi_running) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Router ospf not configured -- Router-ID update postponed"); + return; } - /* If AS-external-LSA is queued, then flush those LSAs. */ - if (router_id_old.s_addr == 0 && ospf->external_origin) - { - /* Originate each redistributed external route. */ - for (type = 0; type < ZEBRA_ROUTE_MAX; type++) - if (ospf->external_origin & (1 << type)) - thread_add_event(master, ospf_external_lsa_originate_timer, - ospf, type, NULL); - /* Originate Deafult. */ - if (ospf->external_origin & (1 << ZEBRA_ROUTE_MAX)) - thread_add_event(master, ospf_default_originate_timer, ospf, 0, - NULL); - - ospf->external_origin = 0; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Router-ID[OLD:%s]: Update", + inet_ntoa(ospf->router_id)); + + router_id_old = ospf->router_id; + + /* Select the router ID based on these priorities: + 1. Statically assigned router ID is always the first choice. + 2. If there is no statically assigned router ID, then try to stick + with the most recent value, since changing router ID's is very + disruptive. + 3. Last choice: just go with whatever the zebra daemon recommends. + */ + if (ospf->router_id_static.s_addr != 0) + router_id = ospf->router_id_static; + else if (ospf->router_id.s_addr != 0) + router_id = ospf->router_id; + else + router_id = router_id_zebra; + + + if (!IPV4_ADDR_SAME(&router_id_old, &router_id)) { + + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { + /* Some nbrs are identified by router_id, these needs + * to be rebuilt. Possible optimization would be to do + * oi->nbr_self->router_id = router_id for + * !(virtual | ptop) links + */ + ospf_nbr_self_reset(oi, router_id); + } + + /* If AS-external-LSA is queued, then flush those LSAs. */ + if (router_id_old.s_addr == 0 && ospf->external_origin) { + /* Originate each redistributed external route. */ + for (type = 0; type < ZEBRA_ROUTE_MAX; type++) + if (ospf->external_origin & (1 << type)) + thread_add_event( + master, + ospf_external_lsa_originate_timer, + ospf, type, NULL); + /* Originate Deafult. */ + if (ospf->external_origin & (1 << ZEBRA_ROUTE_MAX)) + thread_add_event(master, + ospf_default_originate_timer, + ospf, 0, NULL); + + ospf->external_origin = 0; + } + + /* Flush (inline) all external LSAs based on the OSPF_LSA_SELF + * flag */ + if (ospf->lsdb) { + struct route_node *rn; + struct ospf_lsa *lsa; + + LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa) + if (IS_LSA_SELF(lsa)) + ospf_lsa_flush_schedule(ospf, lsa); + } + + ospf->router_id = router_id; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Router-ID[NEW:%s]: Update", + inet_ntoa(ospf->router_id)); + + /* Flush (inline) all external LSAs which now match the new + router-id, + need to adjust the OSPF_LSA_SELF flag, so the flush doesnt + hit + asserts in ospf_refresher_unregister_lsa(). This step is + needed + because the current quagga code does look-up for + self-originated LSAs + based on the self router-id alone but expects OSPF_LSA_SELF + to be + properly set */ + if (ospf->lsdb) { + struct route_node *rn; + struct ospf_lsa *lsa; + + LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa) + { + /* AdvRouter and Router ID is the same. */ + if (IPV4_ADDR_SAME(&lsa->data->adv_router, + &ospf->router_id)) { + SET_FLAG(lsa->flags, + OSPF_LSA_SELF_CHECKED); + SET_FLAG(lsa->flags, OSPF_LSA_SELF); + ospf_lsa_flush_schedule(ospf, lsa); + } + } + } + + /* Originate each redistributed external route. */ + for (type = 0; type < ZEBRA_ROUTE_MAX; type++) + thread_add_event(master, + ospf_external_lsa_originate_timer, + ospf, type, NULL); + thread_add_event(master, ospf_default_originate_timer, ospf, 0, + NULL); + + /* update router-lsa's for each area */ + ospf_router_lsa_update(ospf); + + /* update ospf_interface's */ + for (ALL_LIST_ELEMENTS_RO(om->iflist, node, ifp)) + ospf_if_update(ospf, ifp); } - - /* Flush (inline) all external LSAs based on the OSPF_LSA_SELF flag */ - if (ospf->lsdb) - { - struct route_node *rn; - struct ospf_lsa *lsa; - - LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) - if (IS_LSA_SELF(lsa)) - ospf_lsa_flush_schedule(ospf, lsa); - } - - ospf->router_id = router_id; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Router-ID[NEW:%s]: Update", inet_ntoa (ospf->router_id)); - - /* Flush (inline) all external LSAs which now match the new router-id, - need to adjust the OSPF_LSA_SELF flag, so the flush doesnt hit - asserts in ospf_refresher_unregister_lsa(). This step is needed - because the current quagga code does look-up for self-originated LSAs - based on the self router-id alone but expects OSPF_LSA_SELF to be - properly set */ - if (ospf->lsdb) - { - struct route_node *rn; - struct ospf_lsa *lsa; - - LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) - { - /* AdvRouter and Router ID is the same. */ - if (IPV4_ADDR_SAME (&lsa->data->adv_router, &ospf->router_id)) - { - SET_FLAG (lsa->flags, OSPF_LSA_SELF_CHECKED); - SET_FLAG (lsa->flags, OSPF_LSA_SELF); - ospf_lsa_flush_schedule(ospf, lsa); - } - } - } - - /* Originate each redistributed external route. */ - for (type = 0; type < ZEBRA_ROUTE_MAX; type++) - thread_add_event(master, ospf_external_lsa_originate_timer, ospf, - type, NULL); - thread_add_event(master, ospf_default_originate_timer, ospf, 0, NULL); - - /* update router-lsa's for each area */ - ospf_router_lsa_update (ospf); - - /* update ospf_interface's */ - for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp)) - ospf_if_update (ospf, ifp); - } } /* For OSPF area sort by area id. */ -static int -ospf_area_id_cmp (struct ospf_area *a1, struct ospf_area *a2) +static int ospf_area_id_cmp(struct ospf_area *a1, struct ospf_area *a2) { - if (ntohl (a1->area_id.s_addr) > ntohl (a2->area_id.s_addr)) - return 1; - if (ntohl (a1->area_id.s_addr) < ntohl (a2->area_id.s_addr)) - return -1; - return 0; + if (ntohl(a1->area_id.s_addr) > ntohl(a2->area_id.s_addr)) + return 1; + if (ntohl(a1->area_id.s_addr) < ntohl(a2->area_id.s_addr)) + return -1; + return 0; } /* Allocate new ospf structure. */ -static struct ospf * -ospf_new (u_short instance) +static struct ospf *ospf_new(u_short instance) { - int i; + int i; - struct ospf *new = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf)); + struct ospf *new = XCALLOC(MTYPE_OSPF_TOP, sizeof(struct ospf)); - new->instance = instance; - new->router_id.s_addr = htonl (0); - new->router_id_static.s_addr = htonl (0); + new->instance = instance; + new->router_id.s_addr = htonl(0); + new->router_id_static.s_addr = htonl(0); - new->abr_type = OSPF_ABR_DEFAULT; - new->oiflist = list_new (); - new->vlinks = list_new (); - new->areas = list_new (); - new->areas->cmp = (int (*)(void *, void *)) ospf_area_id_cmp; - new->networks = route_table_init (); - new->nbr_nbma = route_table_init (); + new->abr_type = OSPF_ABR_DEFAULT; + new->oiflist = list_new(); + new->vlinks = list_new(); + new->areas = list_new(); + new->areas->cmp = (int (*)(void *, void *))ospf_area_id_cmp; + new->networks = route_table_init(); + new->nbr_nbma = route_table_init(); - new->lsdb = ospf_lsdb_new (); + new->lsdb = ospf_lsdb_new(); - new->default_originate = DEFAULT_ORIGINATE_NONE; + new->default_originate = DEFAULT_ORIGINATE_NONE; - new->passive_interface_default = OSPF_IF_ACTIVE; - - new->new_external_route = route_table_init (); - new->old_external_route = route_table_init (); - new->external_lsas = route_table_init (); - - new->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED; - new->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED; - new->stub_router_admin_set = OSPF_STUB_ROUTER_ADMINISTRATIVE_UNSET; + new->passive_interface_default = OSPF_IF_ACTIVE; - /* Distribute parameter init. */ - for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) - { - new->dtag[i] = 0; - } - new->default_metric = -1; - new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH; - - /* LSA timers */ - new->min_ls_interval = OSPF_MIN_LS_INTERVAL; - new->min_ls_arrival = OSPF_MIN_LS_ARRIVAL; - - /* SPF timer value init. */ - new->spf_delay = OSPF_SPF_DELAY_DEFAULT; - new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT; - new->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT; - new->spf_hold_multiplier = 1; - - /* MaxAge init. */ - new->maxage_delay = OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT; - new->maxage_lsa = route_table_init(); - new->t_maxage_walker = NULL; - thread_add_timer(master, ospf_lsa_maxage_walker, new, OSPF_LSA_MAXAGE_CHECK_INTERVAL, - &new->t_maxage_walker); - - /* Distance table init. */ - new->distance_table = route_table_init (); - - new->lsa_refresh_queue.index = 0; - new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT; - new->t_lsa_refresher = NULL; - thread_add_timer(master, ospf_lsa_refresh_walker, new, new->lsa_refresh_interval, - &new->t_lsa_refresher); - new->lsa_refresher_started = monotime(NULL); - - if ((new->fd = ospf_sock_init()) < 0) - { - zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open " - "a socket"); - exit(1); - } - if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL) - { - zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf", - OSPF_MAX_PACKET_SIZE+1); - exit(1); - } - new->t_read = NULL; - thread_add_read(master, ospf_read, new, new->fd, &new->t_read); - new->oi_write_q = list_new (); - new->write_oi_count = OSPF_WRITE_INTERFACE_COUNT_DEFAULT; - - /* Enable "log-adjacency-changes" */ + new->new_external_route = route_table_init(); + new->old_external_route = route_table_init(); + new->external_lsas = route_table_init(); + + new->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED; + new->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED; + new->stub_router_admin_set = OSPF_STUB_ROUTER_ADMINISTRATIVE_UNSET; + + /* Distribute parameter init. */ + for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) { + new->dtag[i] = 0; + } + new->default_metric = -1; + new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH; + + /* LSA timers */ + new->min_ls_interval = OSPF_MIN_LS_INTERVAL; + new->min_ls_arrival = OSPF_MIN_LS_ARRIVAL; + + /* SPF timer value init. */ + new->spf_delay = OSPF_SPF_DELAY_DEFAULT; + new->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT; + new->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT; + new->spf_hold_multiplier = 1; + + /* MaxAge init. */ + new->maxage_delay = OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT; + new->maxage_lsa = route_table_init(); + new->t_maxage_walker = NULL; + thread_add_timer(master, ospf_lsa_maxage_walker, new, + OSPF_LSA_MAXAGE_CHECK_INTERVAL, &new->t_maxage_walker); + + /* Distance table init. */ + new->distance_table = route_table_init(); + + new->lsa_refresh_queue.index = 0; + new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT; + new->t_lsa_refresher = NULL; + thread_add_timer(master, ospf_lsa_refresh_walker, new, + new->lsa_refresh_interval, &new->t_lsa_refresher); + new->lsa_refresher_started = monotime(NULL); + + if ((new->fd = ospf_sock_init()) < 0) { + zlog_err( + "ospf_new: fatal error: ospf_sock_init was unable to open " + "a socket"); + exit(1); + } + if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE + 1)) == NULL) { + zlog_err( + "ospf_new: fatal error: stream_new(%u) failed allocating ibuf", + OSPF_MAX_PACKET_SIZE + 1); + exit(1); + } + new->t_read = NULL; + thread_add_read(master, ospf_read, new, new->fd, &new->t_read); + new->oi_write_q = list_new(); + new->write_oi_count = OSPF_WRITE_INTERFACE_COUNT_DEFAULT; + +/* Enable "log-adjacency-changes" */ #if DFLT_OSPF_LOG_ADJACENCY_CHANGES - SET_FLAG(new->config, OSPF_LOG_ADJACENCY_CHANGES); + SET_FLAG(new->config, OSPF_LOG_ADJACENCY_CHANGES); #endif - QOBJ_REG (new, ospf); + QOBJ_REG(new, ospf); - return new; + return new; } -struct ospf * -ospf_lookup () +struct ospf *ospf_lookup() { - if (listcount (om->ospf) == 0) - return NULL; + if (listcount(om->ospf) == 0) + return NULL; - return listgetdata ((struct listnode *)listhead (om->ospf)); + return listgetdata((struct listnode *)listhead(om->ospf)); } -struct ospf * -ospf_lookup_instance (u_short instance) +struct ospf *ospf_lookup_instance(u_short instance) { - struct ospf *ospf; - struct listnode *node, *nnode; + struct ospf *ospf; + struct listnode *node, *nnode; - if (listcount (om->ospf) == 0) - return NULL; + if (listcount(om->ospf) == 0) + return NULL; - for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf)) - if ((ospf->instance == 0 && instance == 0) - || (ospf->instance && instance && ospf->instance == instance)) - return ospf; + for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf)) + if ((ospf->instance == 0 && instance == 0) + || (ospf->instance && instance + && ospf->instance == instance)) + return ospf; - return NULL; + return NULL; } -static int -ospf_is_ready (struct ospf *ospf) +static int ospf_is_ready(struct ospf *ospf) { - /* OSPF must be on and Router-ID must be configured. */ - if (!ospf || ospf->router_id.s_addr == 0) - return 0; - - return 1; + /* OSPF must be on and Router-ID must be configured. */ + if (!ospf || ospf->router_id.s_addr == 0) + return 0; + + return 1; } -static void -ospf_add (struct ospf *ospf) +static void ospf_add(struct ospf *ospf) { - listnode_add (om->ospf, ospf); + listnode_add(om->ospf, ospf); } -static void -ospf_delete (struct ospf *ospf) +static void ospf_delete(struct ospf *ospf) { - listnode_delete (om->ospf, ospf); + listnode_delete(om->ospf, ospf); } -struct ospf * -ospf_get () +struct ospf *ospf_get() { - struct ospf *ospf; + struct ospf *ospf; - ospf = ospf_lookup (); - if (ospf == NULL) - { - ospf = ospf_new (0); - ospf_add (ospf); + ospf = ospf_lookup(); + if (ospf == NULL) { + ospf = ospf_new(0); + ospf_add(ospf); - if (ospf->router_id_static.s_addr == 0) - ospf_router_id_update (ospf); + if (ospf->router_id_static.s_addr == 0) + ospf_router_id_update(ospf); - ospf_opaque_type11_lsa_init (ospf); - } + ospf_opaque_type11_lsa_init(ospf); + } - return ospf; + return ospf; } -struct ospf * -ospf_get_instance (u_short instance) +struct ospf *ospf_get_instance(u_short instance) { - struct ospf *ospf; + struct ospf *ospf; - ospf = ospf_lookup_instance (instance); - if (ospf == NULL) - { - ospf = ospf_new (instance); - ospf_add (ospf); + ospf = ospf_lookup_instance(instance); + if (ospf == NULL) { + ospf = ospf_new(instance); + ospf_add(ospf); - if (ospf->router_id_static.s_addr == 0) - ospf_router_id_update (ospf); + if (ospf->router_id_static.s_addr == 0) + ospf_router_id_update(ospf); - ospf_opaque_type11_lsa_init (ospf); - } + ospf_opaque_type11_lsa_init(ospf); + } - return ospf; + return ospf; } /* Handle the second half of deferred shutdown. This is called either @@ -403,633 +400,592 @@ ospf_get_instance (u_short instance) * to complete shutdown of this ospf instance. Possibly exit if the * whole process is being shutdown and this was the last OSPF instance. */ -static void -ospf_deferred_shutdown_finish (struct ospf *ospf) -{ - ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED; - OSPF_TIMER_OFF (ospf->t_deferred_shutdown); - - ospf_finish_final (ospf); - - /* *ospf is now invalid */ - - /* ospfd being shut-down? If so, was this the last ospf instance? */ - if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN) - && (listcount (om->ospf) == 0)) - { - exit (0); - } +static void ospf_deferred_shutdown_finish(struct ospf *ospf) +{ + ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED; + OSPF_TIMER_OFF(ospf->t_deferred_shutdown); + + ospf_finish_final(ospf); + + /* *ospf is now invalid */ - return; + /* ospfd being shut-down? If so, was this the last ospf instance? */ + if (CHECK_FLAG(om->options, OSPF_MASTER_SHUTDOWN) + && (listcount(om->ospf) == 0)) { + exit(0); + } + + return; } /* Timer thread for G-R */ -static int -ospf_deferred_shutdown_timer (struct thread *t) +static int ospf_deferred_shutdown_timer(struct thread *t) { - struct ospf *ospf = THREAD_ARG(t); - - ospf_deferred_shutdown_finish (ospf); - - return 0; + struct ospf *ospf = THREAD_ARG(t); + + ospf_deferred_shutdown_finish(ospf); + + return 0; } /* Check whether deferred-shutdown must be scheduled, otherwise call * down directly into second-half of instance shutdown. */ -static void -ospf_deferred_shutdown_check (struct ospf *ospf) -{ - unsigned long timeout; - struct listnode *ln; - struct ospf_area *area; - - /* deferred shutdown already running? */ - if (ospf->t_deferred_shutdown) - return; - - /* Should we try push out max-metric LSAs? */ - if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED) - { - for (ALL_LIST_ELEMENTS_RO (ospf->areas, ln, area)) - { - SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED); - - if (!CHECK_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED)) - ospf_router_lsa_update_area (area); - } - timeout = ospf->stub_router_shutdown_time; - } - else - { - /* No timer needed */ - ospf_deferred_shutdown_finish (ospf); - return; - } - - OSPF_TIMER_ON (ospf->t_deferred_shutdown, ospf_deferred_shutdown_timer, - timeout); - return; +static void ospf_deferred_shutdown_check(struct ospf *ospf) +{ + unsigned long timeout; + struct listnode *ln; + struct ospf_area *area; + + /* deferred shutdown already running? */ + if (ospf->t_deferred_shutdown) + return; + + /* Should we try push out max-metric LSAs? */ + if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED) { + for (ALL_LIST_ELEMENTS_RO(ospf->areas, ln, area)) { + SET_FLAG(area->stub_router_state, + OSPF_AREA_ADMIN_STUB_ROUTED); + + if (!CHECK_FLAG(area->stub_router_state, + OSPF_AREA_IS_STUB_ROUTED)) + ospf_router_lsa_update_area(area); + } + timeout = ospf->stub_router_shutdown_time; + } else { + /* No timer needed */ + ospf_deferred_shutdown_finish(ospf); + return; + } + + OSPF_TIMER_ON(ospf->t_deferred_shutdown, ospf_deferred_shutdown_timer, + timeout); + return; } /* Shut down the entire process */ -void -ospf_terminate (void) -{ - struct ospf *ospf; - struct listnode *node, *nnode; - - /* shutdown already in progress */ - if (CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)) - return; - - SET_FLAG (om->options, OSPF_MASTER_SHUTDOWN); - - /* exit immediately if OSPF not actually running */ - if (listcount(om->ospf) == 0) - exit(0); - - bfd_gbl_exit(); - for (ALL_LIST_ELEMENTS (om->ospf, node, nnode, ospf)) - ospf_finish (ospf); - - /* Deliberately go back up, hopefully to thread scheduler, as - * One or more ospf_finish()'s may have deferred shutdown to a timer - * thread - */ - zclient_stop (zclient); - zclient_free (zclient); -} - -void -ospf_finish (struct ospf *ospf) -{ - /* let deferred shutdown decide */ - ospf_deferred_shutdown_check (ospf); - - /* if ospf_deferred_shutdown returns, then ospf_finish_final is - * deferred to expiry of G-S timer thread. Return back up, hopefully - * to thread scheduler. - */ - return; +void ospf_terminate(void) +{ + struct ospf *ospf; + struct listnode *node, *nnode; + + /* shutdown already in progress */ + if (CHECK_FLAG(om->options, OSPF_MASTER_SHUTDOWN)) + return; + + SET_FLAG(om->options, OSPF_MASTER_SHUTDOWN); + + /* exit immediately if OSPF not actually running */ + if (listcount(om->ospf) == 0) + exit(0); + + bfd_gbl_exit(); + for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf)) + ospf_finish(ospf); + + /* Deliberately go back up, hopefully to thread scheduler, as + * One or more ospf_finish()'s may have deferred shutdown to a timer + * thread + */ + zclient_stop(zclient); + zclient_free(zclient); +} + +void ospf_finish(struct ospf *ospf) +{ + /* let deferred shutdown decide */ + ospf_deferred_shutdown_check(ospf); + + /* if ospf_deferred_shutdown returns, then ospf_finish_final is + * deferred to expiry of G-S timer thread. Return back up, hopefully + * to thread scheduler. + */ + return; } /* Final cleanup of ospf instance */ -static void -ospf_finish_final (struct ospf *ospf) +static void ospf_finish_final(struct ospf *ospf) { - struct route_node *rn; - struct ospf_nbr_nbma *nbr_nbma; - struct ospf_lsa *lsa; - struct interface *ifp; - struct ospf_interface *oi; - struct ospf_area *area; - struct ospf_vl_data *vl_data; - struct listnode *node, *nnode; - int i; - u_short instance = 0; - - QOBJ_UNREG (ospf); - - ospf_opaque_type11_lsa_term (ospf); - - /* be nice if this worked, but it doesn't */ - /*ospf_flush_self_originated_lsas_now (ospf);*/ - - /* Unregister redistribution */ - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - struct list *red_list; - struct ospf_redist *red; + struct route_node *rn; + struct ospf_nbr_nbma *nbr_nbma; + struct ospf_lsa *lsa; + struct interface *ifp; + struct ospf_interface *oi; + struct ospf_area *area; + struct ospf_vl_data *vl_data; + struct listnode *node, *nnode; + int i; + u_short instance = 0; - red_list = ospf->redist[i]; - if (!red_list) - continue; + QOBJ_UNREG(ospf); - for (ALL_LIST_ELEMENTS(red_list, node, nnode, red)) - ospf_redistribute_unset (ospf, i, red->instance); - } - ospf_redistribute_default_unset (ospf); - - for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) - ospf_remove_vls_through_area (ospf, area); - - for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data)) - ospf_vl_delete (ospf, vl_data); - - list_delete (ospf->vlinks); - - /* Remove any ospf interface config params */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - struct ospf_if_params *params; + ospf_opaque_type11_lsa_term(ospf); - params = IF_DEF_PARAMS (ifp); - if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) - UNSET_IF_PARAM (params, if_area); - } + /* be nice if this worked, but it doesn't */ + /*ospf_flush_self_originated_lsas_now (ospf);*/ - /* Reset interface. */ - for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) - ospf_if_free (oi); + /* Unregister redistribution */ + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + struct list *red_list; + struct ospf_redist *red; - /* Clear static neighbors */ - for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn)) - if ((nbr_nbma = rn->info)) - { - OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll); + red_list = ospf->redist[i]; + if (!red_list) + continue; - if (nbr_nbma->nbr) - { - nbr_nbma->nbr->nbr_nbma = NULL; - nbr_nbma->nbr = NULL; - } + for (ALL_LIST_ELEMENTS(red_list, node, nnode, red)) + ospf_redistribute_unset(ospf, i, red->instance); + } + ospf_redistribute_default_unset(ospf); - if (nbr_nbma->oi) - { - listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma); - nbr_nbma->oi = NULL; - } + for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) + ospf_remove_vls_through_area(ospf, area); - XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma); - } + for (ALL_LIST_ELEMENTS(ospf->vlinks, node, nnode, vl_data)) + ospf_vl_delete(ospf, vl_data); - route_table_finish (ospf->nbr_nbma); + list_delete(ospf->vlinks); - /* Clear networks and Areas. */ - for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) - { - struct ospf_network *network; + /* Remove any ospf interface config params */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + struct ospf_if_params *params; - if ((network = rn->info) != NULL) - { - ospf_network_free (ospf, network); - rn->info = NULL; - route_unlock_node (rn); + params = IF_DEF_PARAMS(ifp); + if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) + UNSET_IF_PARAM(params, if_area); } - } - for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area)) - { - listnode_delete (ospf->areas, area); - ospf_area_free (area); - } + /* Reset interface. */ + for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) + ospf_if_free(oi); - /* Cancel all timers. */ - OSPF_TIMER_OFF (ospf->t_external_lsa); - OSPF_TIMER_OFF (ospf->t_spf_calc); - OSPF_TIMER_OFF (ospf->t_ase_calc); - OSPF_TIMER_OFF (ospf->t_maxage); - OSPF_TIMER_OFF (ospf->t_maxage_walker); - OSPF_TIMER_OFF (ospf->t_abr_task); - OSPF_TIMER_OFF (ospf->t_asbr_check); - OSPF_TIMER_OFF (ospf->t_distribute_update); - OSPF_TIMER_OFF (ospf->t_lsa_refresher); - OSPF_TIMER_OFF (ospf->t_read); - OSPF_TIMER_OFF (ospf->t_write); - OSPF_TIMER_OFF (ospf->t_opaque_lsa_self); - - close (ospf->fd); - stream_free(ospf->ibuf); - - LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa) - ospf_discard_from_db (ospf, ospf->lsdb, lsa); - LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa) - ospf_discard_from_db (ospf, ospf->lsdb, lsa); - - ospf_lsdb_delete_all (ospf->lsdb); - ospf_lsdb_free (ospf->lsdb); - - for (rn = route_top (ospf->maxage_lsa); rn; rn = route_next (rn)) - { - struct ospf_lsa *lsa; + /* Clear static neighbors */ + for (rn = route_top(ospf->nbr_nbma); rn; rn = route_next(rn)) + if ((nbr_nbma = rn->info)) { + OSPF_POLL_TIMER_OFF(nbr_nbma->t_poll); - if ((lsa = rn->info) != NULL) - { - ospf_lsa_unlock (&lsa); - rn->info = NULL; + if (nbr_nbma->nbr) { + nbr_nbma->nbr->nbr_nbma = NULL; + nbr_nbma->nbr = NULL; + } + + if (nbr_nbma->oi) { + listnode_delete(nbr_nbma->oi->nbr_nbma, + nbr_nbma); + nbr_nbma->oi = NULL; + } + + XFREE(MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma); + } + + route_table_finish(ospf->nbr_nbma); + + /* Clear networks and Areas. */ + for (rn = route_top(ospf->networks); rn; rn = route_next(rn)) { + struct ospf_network *network; + + if ((network = rn->info) != NULL) { + ospf_network_free(ospf, network); + rn->info = NULL; + route_unlock_node(rn); + } } - route_unlock_node (rn); - } - route_table_finish (ospf->maxage_lsa); - if (ospf->old_table) - ospf_route_table_free (ospf->old_table); - if (ospf->new_table) - { - ospf_route_delete (ospf->new_table); - ospf_route_table_free (ospf->new_table); - } - if (ospf->old_rtrs) - ospf_rtrs_free (ospf->old_rtrs); - if (ospf->new_rtrs) - ospf_rtrs_free (ospf->new_rtrs); - if (ospf->new_external_route) - { - ospf_route_delete (ospf->new_external_route); - ospf_route_table_free (ospf->new_external_route); - } - if (ospf->old_external_route) - { - ospf_route_delete (ospf->old_external_route); - ospf_route_table_free (ospf->old_external_route); - } - if (ospf->external_lsas) - { - ospf_ase_external_lsas_finish (ospf->external_lsas); - } + for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { + listnode_delete(ospf->areas, area); + ospf_area_free(area); + } - list_delete (ospf->areas); - - for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++) - { - struct list *ext_list; - struct listnode *node; - struct ospf_external *ext; - - ext_list = om->external[i]; - if (!ext_list) - continue; - - for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) - { - if (ext->external_info) - for (rn = route_top (ext->external_info); rn; rn = route_next (rn)) - { - if (rn->info == NULL) - continue; - - XFREE (MTYPE_OSPF_EXTERNAL_INFO, rn->info); - rn->info = NULL; - route_unlock_node (rn); - } - } - } + /* Cancel all timers. */ + OSPF_TIMER_OFF(ospf->t_external_lsa); + OSPF_TIMER_OFF(ospf->t_spf_calc); + OSPF_TIMER_OFF(ospf->t_ase_calc); + OSPF_TIMER_OFF(ospf->t_maxage); + OSPF_TIMER_OFF(ospf->t_maxage_walker); + OSPF_TIMER_OFF(ospf->t_abr_task); + OSPF_TIMER_OFF(ospf->t_asbr_check); + OSPF_TIMER_OFF(ospf->t_distribute_update); + OSPF_TIMER_OFF(ospf->t_lsa_refresher); + OSPF_TIMER_OFF(ospf->t_read); + OSPF_TIMER_OFF(ospf->t_write); + OSPF_TIMER_OFF(ospf->t_opaque_lsa_self); + + close(ospf->fd); + stream_free(ospf->ibuf); + + LSDB_LOOP(OPAQUE_AS_LSDB(ospf), rn, lsa) + ospf_discard_from_db(ospf, ospf->lsdb, lsa); + LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa) + ospf_discard_from_db(ospf, ospf->lsdb, lsa); + + ospf_lsdb_delete_all(ospf->lsdb); + ospf_lsdb_free(ospf->lsdb); + + for (rn = route_top(ospf->maxage_lsa); rn; rn = route_next(rn)) { + struct ospf_lsa *lsa; + + if ((lsa = rn->info) != NULL) { + ospf_lsa_unlock(&lsa); + rn->info = NULL; + } + route_unlock_node(rn); + } + route_table_finish(ospf->maxage_lsa); + + if (ospf->old_table) + ospf_route_table_free(ospf->old_table); + if (ospf->new_table) { + ospf_route_delete(ospf->new_table); + ospf_route_table_free(ospf->new_table); + } + if (ospf->old_rtrs) + ospf_rtrs_free(ospf->old_rtrs); + if (ospf->new_rtrs) + ospf_rtrs_free(ospf->new_rtrs); + if (ospf->new_external_route) { + ospf_route_delete(ospf->new_external_route); + ospf_route_table_free(ospf->new_external_route); + } + if (ospf->old_external_route) { + ospf_route_delete(ospf->old_external_route); + ospf_route_table_free(ospf->old_external_route); + } + if (ospf->external_lsas) { + ospf_ase_external_lsas_finish(ospf->external_lsas); + } - ospf_distance_reset (ospf); - route_table_finish (ospf->distance_table); + list_delete(ospf->areas); + + for (i = ZEBRA_ROUTE_SYSTEM; i <= ZEBRA_ROUTE_MAX; i++) { + struct list *ext_list; + struct listnode *node; + struct ospf_external *ext; + + ext_list = om->external[i]; + if (!ext_list) + continue; + + for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) { + if (ext->external_info) + for (rn = route_top(ext->external_info); rn; + rn = route_next(rn)) { + if (rn->info == NULL) + continue; + + XFREE(MTYPE_OSPF_EXTERNAL_INFO, + rn->info); + rn->info = NULL; + route_unlock_node(rn); + } + } + } - if (!CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)) - instance = ospf->instance; + ospf_distance_reset(ospf); + route_table_finish(ospf->distance_table); - ospf_delete (ospf); + if (!CHECK_FLAG(om->options, OSPF_MASTER_SHUTDOWN)) + instance = ospf->instance; - XFREE (MTYPE_OSPF_TOP, ospf); + ospf_delete(ospf); - if (!CHECK_FLAG (om->options, OSPF_MASTER_SHUTDOWN)) - ospf_get_instance(instance); + XFREE(MTYPE_OSPF_TOP, ospf); + if (!CHECK_FLAG(om->options, OSPF_MASTER_SHUTDOWN)) + ospf_get_instance(instance); } /* allocate new OSPF Area object */ -static struct ospf_area * -ospf_area_new (struct ospf *ospf, struct in_addr area_id) +static struct ospf_area *ospf_area_new(struct ospf *ospf, + struct in_addr area_id) { - struct ospf_area *new; + struct ospf_area *new; - /* Allocate new config_network. */ - new = XCALLOC (MTYPE_OSPF_AREA, sizeof (struct ospf_area)); + /* Allocate new config_network. */ + new = XCALLOC(MTYPE_OSPF_AREA, sizeof(struct ospf_area)); - new->ospf = ospf; + new->ospf = ospf; - new->area_id = area_id; - new->area_id_fmt = OSPF_AREA_ID_FMT_DOTTEDQUAD; + new->area_id = area_id; + new->area_id_fmt = OSPF_AREA_ID_FMT_DOTTEDQUAD; - new->external_routing = OSPF_AREA_DEFAULT; - new->default_cost = 1; - new->auth_type = OSPF_AUTH_NULL; - - /* New LSDB init. */ - new->lsdb = ospf_lsdb_new (); + new->external_routing = OSPF_AREA_DEFAULT; + new->default_cost = 1; + new->auth_type = OSPF_AUTH_NULL; - /* Self-originated LSAs initialize. */ - new->router_lsa_self = NULL; + /* New LSDB init. */ + new->lsdb = ospf_lsdb_new(); - ospf_opaque_type10_lsa_init (new); + /* Self-originated LSAs initialize. */ + new->router_lsa_self = NULL; - new->oiflist = list_new (); - new->ranges = route_table_init (); + ospf_opaque_type10_lsa_init(new); - if (area_id.s_addr == OSPF_AREA_BACKBONE) - ospf->backbone = new; + new->oiflist = list_new(); + new->ranges = route_table_init(); - return new; + if (area_id.s_addr == OSPF_AREA_BACKBONE) + ospf->backbone = new; + + return new; } -static void -ospf_area_free (struct ospf_area *area) +static void ospf_area_free(struct ospf_area *area) { - struct route_node *rn; - struct ospf_lsa *lsa; + struct route_node *rn; + struct ospf_lsa *lsa; + + /* Free LSDBs. */ + LSDB_LOOP(ROUTER_LSDB(area), rn, lsa) + ospf_discard_from_db(area->ospf, area->lsdb, lsa); + LSDB_LOOP(NETWORK_LSDB(area), rn, lsa) + ospf_discard_from_db(area->ospf, area->lsdb, lsa); + LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa) + ospf_discard_from_db(area->ospf, area->lsdb, lsa); + LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa) + ospf_discard_from_db(area->ospf, area->lsdb, lsa); - /* Free LSDBs. */ - LSDB_LOOP (ROUTER_LSDB (area), rn, lsa) - ospf_discard_from_db (area->ospf, area->lsdb, lsa); - LSDB_LOOP (NETWORK_LSDB (area), rn, lsa) - ospf_discard_from_db (area->ospf, area->lsdb, lsa); - LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa) - ospf_discard_from_db (area->ospf, area->lsdb, lsa); - LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa) - ospf_discard_from_db (area->ospf, area->lsdb, lsa); + LSDB_LOOP(NSSA_LSDB(area), rn, lsa) + ospf_discard_from_db(area->ospf, area->lsdb, lsa); + LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa) + ospf_discard_from_db(area->ospf, area->lsdb, lsa); + LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa) + ospf_discard_from_db(area->ospf, area->lsdb, lsa); - LSDB_LOOP (NSSA_LSDB (area), rn, lsa) - ospf_discard_from_db (area->ospf, area->lsdb, lsa); - LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa) - ospf_discard_from_db (area->ospf, area->lsdb, lsa); - LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa) - ospf_discard_from_db (area->ospf, area->lsdb, lsa); + ospf_lsdb_delete_all(area->lsdb); + ospf_lsdb_free(area->lsdb); - ospf_lsdb_delete_all (area->lsdb); - ospf_lsdb_free (area->lsdb); + ospf_lsa_unlock(&area->router_lsa_self); - ospf_lsa_unlock (&area->router_lsa_self); - - route_table_finish (area->ranges); - list_delete (area->oiflist); + route_table_finish(area->ranges); + list_delete(area->oiflist); - if (EXPORT_NAME (area)) - free (EXPORT_NAME (area)); + if (EXPORT_NAME(area)) + free(EXPORT_NAME(area)); - if (IMPORT_NAME (area)) - free (IMPORT_NAME (area)); + if (IMPORT_NAME(area)) + free(IMPORT_NAME(area)); - /* Cancel timer. */ - OSPF_TIMER_OFF (area->t_stub_router); - OSPF_TIMER_OFF (area->t_opaque_lsa_self); - - if (OSPF_IS_AREA_BACKBONE (area)) - area->ospf->backbone = NULL; + /* Cancel timer. */ + OSPF_TIMER_OFF(area->t_stub_router); + OSPF_TIMER_OFF(area->t_opaque_lsa_self); - XFREE (MTYPE_OSPF_AREA, area); + if (OSPF_IS_AREA_BACKBONE(area)) + area->ospf->backbone = NULL; + + XFREE(MTYPE_OSPF_AREA, area); } -void -ospf_area_check_free (struct ospf *ospf, struct in_addr area_id) +void ospf_area_check_free(struct ospf *ospf, struct in_addr area_id) { - struct ospf_area *area; + struct ospf_area *area; - area = ospf_area_lookup_by_area_id (ospf, area_id); - if (area && - listcount (area->oiflist) == 0 && - area->ranges->top == NULL && - area->shortcut_configured == OSPF_SHORTCUT_DEFAULT && - area->external_routing == OSPF_AREA_DEFAULT && - area->no_summary == 0 && - area->default_cost == 1 && - EXPORT_NAME (area) == NULL && - IMPORT_NAME (area) == NULL && - area->auth_type == OSPF_AUTH_NULL) - { - listnode_delete (ospf->areas, area); - ospf_area_free (area); - } + area = ospf_area_lookup_by_area_id(ospf, area_id); + if (area && listcount(area->oiflist) == 0 && area->ranges->top == NULL + && area->shortcut_configured == OSPF_SHORTCUT_DEFAULT + && area->external_routing == OSPF_AREA_DEFAULT + && area->no_summary == 0 && area->default_cost == 1 + && EXPORT_NAME(area) == NULL && IMPORT_NAME(area) == NULL + && area->auth_type == OSPF_AUTH_NULL) { + listnode_delete(ospf->areas, area); + ospf_area_free(area); + } } -struct ospf_area * -ospf_area_get (struct ospf *ospf, struct in_addr area_id) +struct ospf_area *ospf_area_get(struct ospf *ospf, struct in_addr area_id) { - struct ospf_area *area; - - area = ospf_area_lookup_by_area_id (ospf, area_id); - if (!area) - { - area = ospf_area_new (ospf, area_id); - listnode_add_sort (ospf->areas, area); - ospf_check_abr_status (ospf); - if (ospf->stub_router_admin_set == OSPF_STUB_ROUTER_ADMINISTRATIVE_SET) - { - SET_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED); - } - } + struct ospf_area *area; + + area = ospf_area_lookup_by_area_id(ospf, area_id); + if (!area) { + area = ospf_area_new(ospf, area_id); + listnode_add_sort(ospf->areas, area); + ospf_check_abr_status(ospf); + if (ospf->stub_router_admin_set + == OSPF_STUB_ROUTER_ADMINISTRATIVE_SET) { + SET_FLAG(area->stub_router_state, + OSPF_AREA_ADMIN_STUB_ROUTED); + } + } - return area; + return area; } -struct ospf_area * -ospf_area_lookup_by_area_id (struct ospf *ospf, struct in_addr area_id) +struct ospf_area *ospf_area_lookup_by_area_id(struct ospf *ospf, + struct in_addr area_id) { - struct ospf_area *area; - struct listnode *node; + struct ospf_area *area; + struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - if (IPV4_ADDR_SAME (&area->area_id, &area_id)) - return area; + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) + if (IPV4_ADDR_SAME(&area->area_id, &area_id)) + return area; - return NULL; + return NULL; } -void -ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi) +void ospf_area_add_if(struct ospf_area *area, struct ospf_interface *oi) { - listnode_add (area->oiflist, oi); + listnode_add(area->oiflist, oi); } -void -ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi) +void ospf_area_del_if(struct ospf_area *area, struct ospf_interface *oi) { - listnode_delete (area->oiflist, oi); + listnode_delete(area->oiflist, oi); } - -static void -add_ospf_interface (struct connected *co, struct ospf_area *area) +static void add_ospf_interface(struct connected *co, struct ospf_area *area) { - struct ospf_interface *oi; - - oi = ospf_if_new (area->ospf, co->ifp, co->address); - oi->connected = co; + struct ospf_interface *oi; - oi->area = area; + oi = ospf_if_new(area->ospf, co->ifp, co->address); + oi->connected = co; - oi->params = ospf_lookup_if_params (co->ifp, oi->address->u.prefix4); - oi->output_cost = ospf_if_get_output_cost (oi); + oi->area = area; - /* Relate ospf interface to ospf instance. */ - oi->ospf = area->ospf; + oi->params = ospf_lookup_if_params(co->ifp, oi->address->u.prefix4); + oi->output_cost = ospf_if_get_output_cost(oi); - /* update network type as interface flag */ - /* If network type is specified previously, - skip network type setting. */ - oi->type = IF_DEF_PARAMS (co->ifp)->type; + /* Relate ospf interface to ospf instance. */ + oi->ospf = area->ospf; - /* Add pseudo neighbor. */ - ospf_nbr_self_reset (oi, oi->ospf->router_id); + /* update network type as interface flag */ + /* If network type is specified previously, + skip network type setting. */ + oi->type = IF_DEF_PARAMS(co->ifp)->type; - ospf_area_add_if (oi->area, oi); + /* Add pseudo neighbor. */ + ospf_nbr_self_reset(oi, oi->ospf->router_id); - /* - * if router_id is not configured, dont bring up - * interfaces. - * ospf_router_id_update() will call ospf_if_update - * whenever r-id is configured instead. - */ - if ((area->ospf->router_id.s_addr != 0) - && if_is_operative (co->ifp)) - ospf_if_up (oi); + ospf_area_add_if(oi->area, oi); + /* + * if router_id is not configured, dont bring up + * interfaces. + * ospf_router_id_update() will call ospf_if_update + * whenever r-id is configured instead. + */ + if ((area->ospf->router_id.s_addr != 0) && if_is_operative(co->ifp)) + ospf_if_up(oi); } static void update_redistributed(struct ospf *ospf, int add_to_ospf) { - struct route_node *rn; - struct external_info *ei; - struct ospf_external *ext; - - if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT, 0)) - if ((ext = ospf_external_lookup(ZEBRA_ROUTE_CONNECT, 0)) && - EXTERNAL_INFO (ext)) - { - for (rn = route_top (EXTERNAL_INFO (ext)); - rn; rn = route_next (rn)) - { - if ((ei = rn->info) != NULL) - { - if (add_to_ospf) - { - if (ospf_external_info_find_lsa (ospf, &ei->p)) - if (!ospf_distribute_check_connected (ospf, ei)) - ospf_external_lsa_flush (ospf, ei->type, &ei->p, - ei->ifindex /*, ei->nexthop */); - } - else - { - if (!ospf_external_info_find_lsa (ospf, &ei->p)) - if (ospf_distribute_check_connected (ospf, ei)) - ospf_external_lsa_originate (ospf, ei); - } - } - } - } + struct route_node *rn; + struct external_info *ei; + struct ospf_external *ext; + + if (ospf_is_type_redistributed(ZEBRA_ROUTE_CONNECT, 0)) + if ((ext = ospf_external_lookup(ZEBRA_ROUTE_CONNECT, 0)) + && EXTERNAL_INFO(ext)) { + for (rn = route_top(EXTERNAL_INFO(ext)); rn; + rn = route_next(rn)) { + if ((ei = rn->info) != NULL) { + if (add_to_ospf) { + if (ospf_external_info_find_lsa( + ospf, &ei->p)) + if (!ospf_distribute_check_connected( + ospf, ei)) + ospf_external_lsa_flush( + ospf, + ei->type, + &ei->p, + ei->ifindex /*, ei->nexthop */); + } else { + if (!ospf_external_info_find_lsa( + ospf, &ei->p)) + if (ospf_distribute_check_connected( + ospf, ei)) + ospf_external_lsa_originate( + ospf, + ei); + } + } + } + } } /* Config network statement related functions. */ -static struct ospf_network * -ospf_network_new (struct in_addr area_id) +static struct ospf_network *ospf_network_new(struct in_addr area_id) { - struct ospf_network *new; - new = XCALLOC (MTYPE_OSPF_NETWORK, sizeof (struct ospf_network)); + struct ospf_network *new; + new = XCALLOC(MTYPE_OSPF_NETWORK, sizeof(struct ospf_network)); - new->area_id = area_id; - new->area_id_fmt = OSPF_AREA_ID_FMT_DOTTEDQUAD; - - return new; + new->area_id = area_id; + new->area_id_fmt = OSPF_AREA_ID_FMT_DOTTEDQUAD; + + return new; } -static void -ospf_network_free (struct ospf *ospf, struct ospf_network *network) +static void ospf_network_free(struct ospf *ospf, struct ospf_network *network) { - ospf_area_check_free (ospf, network->area_id); - ospf_schedule_abr_task (ospf); - XFREE (MTYPE_OSPF_NETWORK, network); + ospf_area_check_free(ospf, network->area_id); + ospf_schedule_abr_task(ospf); + XFREE(MTYPE_OSPF_NETWORK, network); } -int -ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p, - struct in_addr area_id, int df) +int ospf_network_set(struct ospf *ospf, struct prefix_ipv4 *p, + struct in_addr area_id, int df) { - struct ospf_network *network; - struct ospf_area *area; - struct route_node *rn; + struct ospf_network *network; + struct ospf_area *area; + struct route_node *rn; - rn = route_node_get (ospf->networks, (struct prefix *)p); - if (rn->info) - { - /* There is already same network statement. */ - route_unlock_node (rn); - return 0; - } + rn = route_node_get(ospf->networks, (struct prefix *)p); + if (rn->info) { + /* There is already same network statement. */ + route_unlock_node(rn); + return 0; + } - rn->info = network = ospf_network_new (area_id); - network->area_id_fmt = df; - area = ospf_area_get (ospf, area_id); - ospf_area_display_format_set (ospf, area, df); + rn->info = network = ospf_network_new(area_id); + network->area_id_fmt = df; + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, df); - /* Run network config now. */ - ospf_network_run ((struct prefix *)p, area); + /* Run network config now. */ + ospf_network_run((struct prefix *)p, area); - /* Update connected redistribute. */ - update_redistributed(ospf, 1); /* interfaces possibly added */ + /* Update connected redistribute. */ + update_redistributed(ospf, 1); /* interfaces possibly added */ - ospf_area_check_free (ospf, area_id); + ospf_area_check_free(ospf, area_id); - return 1; + return 1; } -int -ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p, - struct in_addr area_id) +int ospf_network_unset(struct ospf *ospf, struct prefix_ipv4 *p, + struct in_addr area_id) { - struct route_node *rn; - struct ospf_network *network; - struct listnode *node, *nnode; - struct ospf_interface *oi; + struct route_node *rn; + struct ospf_network *network; + struct listnode *node, *nnode; + struct ospf_interface *oi; - rn = route_node_lookup (ospf->networks, (struct prefix *)p); - if (rn == NULL) - return 0; + rn = route_node_lookup(ospf->networks, (struct prefix *)p); + if (rn == NULL) + return 0; - network = rn->info; - route_unlock_node (rn); - if (!IPV4_ADDR_SAME (&area_id, &network->area_id)) - return 0; + network = rn->info; + route_unlock_node(rn); + if (!IPV4_ADDR_SAME(&area_id, &network->area_id)) + return 0; - ospf_network_free (ospf, rn->info); - rn->info = NULL; - route_unlock_node (rn); /* initial reference */ + ospf_network_free(ospf, rn->info); + rn->info = NULL; + route_unlock_node(rn); /* initial reference */ - /* Find interfaces that not configured already. */ - for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) - { - ospf_network_run_subnet (ospf, oi->connected, NULL, NULL); - } - - /* Update connected redistribute. */ - update_redistributed(ospf, 0); /* interfaces possibly removed */ - ospf_area_check_free (ospf, area_id); + /* Find interfaces that not configured already. */ + for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) { + ospf_network_run_subnet(ospf, oi->connected, NULL, NULL); + } - return 1; + /* Update connected redistribute. */ + update_redistributed(ospf, 0); /* interfaces possibly removed */ + ospf_area_check_free(ospf, area_id); + + return 1; } /* Ensure there's an OSPF instance, as "ip ospf area" enabled OSPF means @@ -1037,69 +993,67 @@ ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p, * * Otherwise, doesn't do anything different to ospf_if_update for now */ -void -ospf_interface_area_set (struct interface *ifp) +void ospf_interface_area_set(struct interface *ifp) { - struct ospf *ospf = ospf_get(); - - ospf_if_update (ospf, ifp); - /* if_update does a update_redistributed */ - - return; + struct ospf *ospf = ospf_get(); + + ospf_if_update(ospf, ifp); + /* if_update does a update_redistributed */ + + return; } -void -ospf_interface_area_unset (struct interface *ifp) +void ospf_interface_area_unset(struct interface *ifp) { - struct route_node *rn_oi; - struct ospf *ospf; + struct route_node *rn_oi; + struct ospf *ospf; - ospf = ospf_lookup (); - if (!ospf) - return; /* Ospf not ready yet */ + ospf = ospf_lookup(); + if (!ospf) + return; /* Ospf not ready yet */ - /* Find interfaces that may need to be removed. */ - for (rn_oi = route_top (IF_OIFS (ifp)); rn_oi; rn_oi = route_next (rn_oi)) - { - struct ospf_interface *oi; - - if ( (oi = rn_oi->info) == NULL) - continue; - - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - continue; - - ospf_network_run_subnet (ospf, oi->connected, NULL, NULL); - } + /* Find interfaces that may need to be removed. */ + for (rn_oi = route_top(IF_OIFS(ifp)); rn_oi; + rn_oi = route_next(rn_oi)) { + struct ospf_interface *oi; + + if ((oi = rn_oi->info) == NULL) + continue; + + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + continue; + + ospf_network_run_subnet(ospf, oi->connected, NULL, NULL); + } - /* Update connected redistribute. */ - update_redistributed(ospf, 0); /* interfaces possibly removed */ + /* Update connected redistribute. */ + update_redistributed(ospf, 0); /* interfaces possibly removed */ } /* Check whether interface matches given network * returns: 1, true. 0, false */ -static int -ospf_network_match_iface(const struct connected *co, const struct prefix *net) +static int ospf_network_match_iface(const struct connected *co, + const struct prefix *net) { - /* new approach: more elegant and conceptually clean */ - return prefix_match_network_statement(net, CONNECTED_PREFIX(co)); + /* new approach: more elegant and conceptually clean */ + return prefix_match_network_statement(net, CONNECTED_PREFIX(co)); } -static void -ospf_update_interface_area (struct connected *co, struct ospf_area *area) +static void ospf_update_interface_area(struct connected *co, + struct ospf_area *area) { - struct ospf_interface *oi = ospf_if_table_lookup (co->ifp, co->address); - - /* nothing to be done case */ - if (oi && oi->area == area){ - return; - } - - if (oi) - ospf_if_free (oi); - - add_ospf_interface (co, area); + struct ospf_interface *oi = ospf_if_table_lookup(co->ifp, co->address); + + /* nothing to be done case */ + if (oi && oi->area == area) { + return; + } + + if (oi) + ospf_if_free(oi); + + add_ospf_interface(co, area); } /* Run OSPF for the given subnet, taking into account the following @@ -1111,399 +1065,379 @@ ospf_update_interface_area (struct connected *co, struct ospf_area *area) * - If no specific network prefix/area is supplied, whether there's * a matching network configured. */ -static void -ospf_network_run_subnet (struct ospf *ospf, struct connected *co, - struct prefix *p, struct ospf_area *given_area) -{ - struct ospf_interface *oi; - struct ospf_if_params *params; - struct ospf_area *area = NULL; - struct route_node *rn; - int configed = 0; - - if (CHECK_FLAG(co->flags, ZEBRA_IFA_SECONDARY)) - return; - - if (co->address->family != AF_INET) - return; - - /* Try determine the appropriate area for this interface + address - * Start by checking interface config - */ - params = ospf_lookup_if_params (co->ifp, co->address->u.prefix4); - if ( params && OSPF_IF_PARAM_CONFIGURED(params, if_area)) - area = ospf_area_get (ospf, params->if_area); - else{ - params = IF_DEF_PARAMS (co->ifp); - if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) - area = ospf_area_get (ospf, params->if_area); - } +static void ospf_network_run_subnet(struct ospf *ospf, struct connected *co, + struct prefix *p, + struct ospf_area *given_area) +{ + struct ospf_interface *oi; + struct ospf_if_params *params; + struct ospf_area *area = NULL; + struct route_node *rn; + int configed = 0; + + if (CHECK_FLAG(co->flags, ZEBRA_IFA_SECONDARY)) + return; + + if (co->address->family != AF_INET) + return; + + /* Try determine the appropriate area for this interface + address + * Start by checking interface config + */ + params = ospf_lookup_if_params(co->ifp, co->address->u.prefix4); + if (params && OSPF_IF_PARAM_CONFIGURED(params, if_area)) + area = ospf_area_get(ospf, params->if_area); + else { + params = IF_DEF_PARAMS(co->ifp); + if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) + area = ospf_area_get(ospf, params->if_area); + } - /* If we've found an interface and/or addr specific area, then we're - * done - */ - if (area) - { - ospf_update_interface_area (co, area); - return; - } - - /* Otherwise, only remaining possibility is a matching network statement */ - if (p) - { - assert (given_area != NULL); - - /* Which either was supplied as a parameter.. (e.g. cause a new - * network/area was just added).. - */ - if (p->family == co->address->family - && ospf_network_match_iface (co, p)) - ospf_update_interface_area (co, given_area); - - return; - } - - /* Else we have to search the existing network/area config to see - * if any match.. - */ - for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) - if (rn->info != NULL - && ospf_network_match_iface (co, &rn->p)) - { - struct ospf_network *network = (struct ospf_network *) rn->info; - area = ospf_area_get (ospf, network->area_id); - ospf_update_interface_area (co, area); - configed = 1; - } - - /* If the subnet isn't in any area, deconfigure */ - if (!configed && (oi = ospf_if_table_lookup (co->ifp, co->address))) - ospf_if_free (oi); -} - -static void -ospf_network_run_interface (struct ospf *ospf, struct interface *ifp, - struct prefix *p, - struct ospf_area *given_area) -{ - struct listnode *cnode; - struct connected *co; - - if (memcmp (ifp->name, "VLINK", 5) == 0) - return; - - /* Network prefix without area is nonsensical */ - if (p) - assert (given_area != NULL); - - /* if interface prefix is match specified prefix, - then create socket and join multicast group. */ - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co)) - ospf_network_run_subnet (ospf, co, p, given_area); -} - -static void -ospf_network_run (struct prefix *p, struct ospf_area *area) -{ - struct interface *ifp; - struct listnode *node; + /* If we've found an interface and/or addr specific area, then we're + * done + */ + if (area) { + ospf_update_interface_area(co, area); + return; + } - /* Schedule Router ID Update. */ - if (area->ospf->router_id.s_addr == 0) - ospf_router_id_update (area->ospf); - - /* Get target interface. */ - for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp)) - ospf_network_run_interface (area->ospf, ifp, p, area); -} - -void -ospf_ls_upd_queue_empty (struct ospf_interface *oi) -{ - struct route_node *rn; - struct listnode *node, *nnode; - struct list *lst; - struct ospf_lsa *lsa; - - /* empty ls update queue */ - for (rn = route_top (oi->ls_upd_queue); rn; - rn = route_next (rn)) - if ((lst = (struct list *) rn->info)) - { - for (ALL_LIST_ELEMENTS (lst, node, nnode, lsa)) - ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */ - list_free (lst); - rn->info = NULL; - } - - /* remove update event */ - if (oi->t_ls_upd_event) - { - thread_cancel (oi->t_ls_upd_event); - oi->t_ls_upd_event = NULL; - } + /* Otherwise, only remaining possibility is a matching network statement + */ + if (p) { + assert(given_area != NULL); + + /* Which either was supplied as a parameter.. (e.g. cause a new + * network/area was just added).. + */ + if (p->family == co->address->family + && ospf_network_match_iface(co, p)) + ospf_update_interface_area(co, given_area); + + return; + } + + /* Else we have to search the existing network/area config to see + * if any match.. + */ + for (rn = route_top(ospf->networks); rn; rn = route_next(rn)) + if (rn->info != NULL && ospf_network_match_iface(co, &rn->p)) { + struct ospf_network *network = + (struct ospf_network *)rn->info; + area = ospf_area_get(ospf, network->area_id); + ospf_update_interface_area(co, area); + configed = 1; + } + + /* If the subnet isn't in any area, deconfigure */ + if (!configed && (oi = ospf_if_table_lookup(co->ifp, co->address))) + ospf_if_free(oi); } -void -ospf_if_update (struct ospf *ospf, struct interface *ifp) +static void ospf_network_run_interface(struct ospf *ospf, struct interface *ifp, + struct prefix *p, + struct ospf_area *given_area) { - if (!ospf) - ospf = ospf_lookup (); + struct listnode *cnode; + struct connected *co; + + if (memcmp(ifp->name, "VLINK", 5) == 0) + return; - /* OSPF must be ready. */ - if (!ospf_is_ready (ospf)) - return; - - ospf_network_run_interface (ospf, ifp, NULL, NULL); - - /* Update connected redistribute. */ - update_redistributed(ospf, 1); + /* Network prefix without area is nonsensical */ + if (p) + assert(given_area != NULL); + + /* if interface prefix is match specified prefix, + then create socket and join multicast group. */ + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, co)) + ospf_network_run_subnet(ospf, co, p, given_area); } -void -ospf_remove_vls_through_area (struct ospf *ospf, struct ospf_area *area) +static void ospf_network_run(struct prefix *p, struct ospf_area *area) { - struct listnode *node, *nnode; - struct ospf_vl_data *vl_data; + struct interface *ifp; + struct listnode *node; + + /* Schedule Router ID Update. */ + if (area->ospf->router_id.s_addr == 0) + ospf_router_id_update(area->ospf); - for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data)) - if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id)) - ospf_vl_delete (ospf, vl_data); + /* Get target interface. */ + for (ALL_LIST_ELEMENTS_RO(om->iflist, node, ifp)) + ospf_network_run_interface(area->ospf, ifp, p, area); } +void ospf_ls_upd_queue_empty(struct ospf_interface *oi) +{ + struct route_node *rn; + struct listnode *node, *nnode; + struct list *lst; + struct ospf_lsa *lsa; + + /* empty ls update queue */ + for (rn = route_top(oi->ls_upd_queue); rn; rn = route_next(rn)) + if ((lst = (struct list *)rn->info)) { + for (ALL_LIST_ELEMENTS(lst, node, nnode, lsa)) + ospf_lsa_unlock(&lsa); /* oi->ls_upd_queue */ + list_free(lst); + rn->info = NULL; + } + + /* remove update event */ + if (oi->t_ls_upd_event) { + thread_cancel(oi->t_ls_upd_event); + oi->t_ls_upd_event = NULL; + } +} -static const struct message ospf_area_type_msg[] = +void ospf_if_update(struct ospf *ospf, struct interface *ifp) { - { OSPF_AREA_DEFAULT, "Default" }, - { OSPF_AREA_STUB, "Stub" }, - { OSPF_AREA_NSSA, "NSSA" }, - { 0 } -}; + if (!ospf) + ospf = ospf_lookup(); + + /* OSPF must be ready. */ + if (!ospf_is_ready(ospf)) + return; + + ospf_network_run_interface(ospf, ifp, NULL, NULL); + + /* Update connected redistribute. */ + update_redistributed(ospf, 1); +} -static void -ospf_area_type_set (struct ospf_area *area, int type) +void ospf_remove_vls_through_area(struct ospf *ospf, struct ospf_area *area) { - struct listnode *node; - struct ospf_interface *oi; + struct listnode *node, *nnode; + struct ospf_vl_data *vl_data; - if (area->external_routing == type) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Area[%s]: Types are the same, ignored.", - inet_ntoa (area->area_id)); - return; - } + for (ALL_LIST_ELEMENTS(ospf->vlinks, node, nnode, vl_data)) + if (IPV4_ADDR_SAME(&vl_data->vl_area_id, &area->area_id)) + ospf_vl_delete(ospf, vl_data); +} - area->external_routing = type; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Area[%s]: Configured as %s", inet_ntoa (area->area_id), - lookup_msg(ospf_area_type_msg, type, NULL)); +static const struct message ospf_area_type_msg[] = { + {OSPF_AREA_DEFAULT, "Default"}, + {OSPF_AREA_STUB, "Stub"}, + {OSPF_AREA_NSSA, "NSSA"}, + {0}}; - switch (area->external_routing) - { - case OSPF_AREA_DEFAULT: - for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi)) - if (oi->nbr_self != NULL) - { - UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP); - SET_FLAG (oi->nbr_self->options, OSPF_OPTION_E); - } - break; - case OSPF_AREA_STUB: - for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi)) - if (oi->nbr_self != NULL) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("setting options on %s accordingly", IF_NAME (oi)); - UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP); - UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E); - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("options set on %s: %x", - IF_NAME (oi), OPTIONS (oi)); - } - break; - case OSPF_AREA_NSSA: - for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi)) - if (oi->nbr_self != NULL) - { - zlog_debug ("setting nssa options on %s accordingly", IF_NAME (oi)); - UNSET_FLAG (oi->nbr_self->options, OSPF_OPTION_E); - SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP); - zlog_debug ("options set on %s: %x", IF_NAME (oi), OPTIONS (oi)); - } - break; - default: - break; - } +static void ospf_area_type_set(struct ospf_area *area, int type) +{ + struct listnode *node; + struct ospf_interface *oi; + + if (area->external_routing == type) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Area[%s]: Types are the same, ignored.", + inet_ntoa(area->area_id)); + return; + } - ospf_router_lsa_update_area (area); - ospf_schedule_abr_task (area->ospf); + area->external_routing = type; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Area[%s]: Configured as %s", + inet_ntoa(area->area_id), + lookup_msg(ospf_area_type_msg, type, NULL)); + + switch (area->external_routing) { + case OSPF_AREA_DEFAULT: + for (ALL_LIST_ELEMENTS_RO(area->oiflist, node, oi)) + if (oi->nbr_self != NULL) { + UNSET_FLAG(oi->nbr_self->options, + OSPF_OPTION_NP); + SET_FLAG(oi->nbr_self->options, OSPF_OPTION_E); + } + break; + case OSPF_AREA_STUB: + for (ALL_LIST_ELEMENTS_RO(area->oiflist, node, oi)) + if (oi->nbr_self != NULL) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "setting options on %s accordingly", + IF_NAME(oi)); + UNSET_FLAG(oi->nbr_self->options, + OSPF_OPTION_NP); + UNSET_FLAG(oi->nbr_self->options, + OSPF_OPTION_E); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("options set on %s: %x", + IF_NAME(oi), OPTIONS(oi)); + } + break; + case OSPF_AREA_NSSA: + for (ALL_LIST_ELEMENTS_RO(area->oiflist, node, oi)) + if (oi->nbr_self != NULL) { + zlog_debug( + "setting nssa options on %s accordingly", + IF_NAME(oi)); + UNSET_FLAG(oi->nbr_self->options, + OSPF_OPTION_E); + SET_FLAG(oi->nbr_self->options, OSPF_OPTION_NP); + zlog_debug("options set on %s: %x", IF_NAME(oi), + OPTIONS(oi)); + } + break; + default: + break; + } + + ospf_router_lsa_update_area(area); + ospf_schedule_abr_task(area->ospf); } -int -ospf_area_shortcut_set (struct ospf *ospf, struct ospf_area *area, int mode) +int ospf_area_shortcut_set(struct ospf *ospf, struct ospf_area *area, int mode) { - if (area->shortcut_configured == mode) - return 0; + if (area->shortcut_configured == mode) + return 0; - area->shortcut_configured = mode; - ospf_router_lsa_update_area (area); - ospf_schedule_abr_task (ospf); + area->shortcut_configured = mode; + ospf_router_lsa_update_area(area); + ospf_schedule_abr_task(ospf); - ospf_area_check_free (ospf, area->area_id); + ospf_area_check_free(ospf, area->area_id); - return 1; + return 1; } -int -ospf_area_shortcut_unset (struct ospf *ospf, struct ospf_area *area) +int ospf_area_shortcut_unset(struct ospf *ospf, struct ospf_area *area) { - area->shortcut_configured = OSPF_SHORTCUT_DEFAULT; - ospf_router_lsa_update_area (area); - ospf_area_check_free (ospf, area->area_id); - ospf_schedule_abr_task (ospf); + area->shortcut_configured = OSPF_SHORTCUT_DEFAULT; + ospf_router_lsa_update_area(area); + ospf_area_check_free(ospf, area->area_id); + ospf_schedule_abr_task(ospf); - return 1; + return 1; } -static int -ospf_area_vlink_count (struct ospf *ospf, struct ospf_area *area) +static int ospf_area_vlink_count(struct ospf *ospf, struct ospf_area *area) { - struct ospf_vl_data *vl; - struct listnode *node; - int count = 0; + struct ospf_vl_data *vl; + struct listnode *node; + int count = 0; - for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl)) - if (IPV4_ADDR_SAME (&vl->vl_area_id, &area->area_id)) - count++; + for (ALL_LIST_ELEMENTS_RO(ospf->vlinks, node, vl)) + if (IPV4_ADDR_SAME(&vl->vl_area_id, &area->area_id)) + count++; - return count; + return count; } -int -ospf_area_display_format_set (struct ospf *ospf, struct ospf_area *area, int df) +int ospf_area_display_format_set(struct ospf *ospf, struct ospf_area *area, + int df) { - area->area_id_fmt = df; + area->area_id_fmt = df; - return 1; + return 1; } -int -ospf_area_stub_set (struct ospf *ospf, struct in_addr area_id) +int ospf_area_stub_set(struct ospf *ospf, struct in_addr area_id) { - struct ospf_area *area; + struct ospf_area *area; - area = ospf_area_get (ospf, area_id); - if (ospf_area_vlink_count (ospf, area)) - return 0; + area = ospf_area_get(ospf, area_id); + if (ospf_area_vlink_count(ospf, area)) + return 0; - if (area->external_routing != OSPF_AREA_STUB) - ospf_area_type_set (area, OSPF_AREA_STUB); + if (area->external_routing != OSPF_AREA_STUB) + ospf_area_type_set(area, OSPF_AREA_STUB); - return 1; + return 1; } -int -ospf_area_stub_unset (struct ospf *ospf, struct in_addr area_id) +int ospf_area_stub_unset(struct ospf *ospf, struct in_addr area_id) { - struct ospf_area *area; + struct ospf_area *area; - area = ospf_area_lookup_by_area_id (ospf, area_id); - if (area == NULL) - return 1; + area = ospf_area_lookup_by_area_id(ospf, area_id); + if (area == NULL) + return 1; - if (area->external_routing == OSPF_AREA_STUB) - ospf_area_type_set (area, OSPF_AREA_DEFAULT); + if (area->external_routing == OSPF_AREA_STUB) + ospf_area_type_set(area, OSPF_AREA_DEFAULT); - ospf_area_check_free (ospf, area_id); + ospf_area_check_free(ospf, area_id); - return 1; + return 1; } -int -ospf_area_no_summary_set (struct ospf *ospf, struct in_addr area_id) +int ospf_area_no_summary_set(struct ospf *ospf, struct in_addr area_id) { - struct ospf_area *area; + struct ospf_area *area; - area = ospf_area_get (ospf, area_id); - area->no_summary = 1; + area = ospf_area_get(ospf, area_id); + area->no_summary = 1; - return 1; + return 1; } -int -ospf_area_no_summary_unset (struct ospf *ospf, struct in_addr area_id) +int ospf_area_no_summary_unset(struct ospf *ospf, struct in_addr area_id) { - struct ospf_area *area; + struct ospf_area *area; - area = ospf_area_lookup_by_area_id (ospf, area_id); - if (area == NULL) - return 0; + area = ospf_area_lookup_by_area_id(ospf, area_id); + if (area == NULL) + return 0; - area->no_summary = 0; - ospf_area_check_free (ospf, area_id); + area->no_summary = 0; + ospf_area_check_free(ospf, area_id); - return 1; + return 1; } -int -ospf_area_nssa_set (struct ospf *ospf, struct in_addr area_id) +int ospf_area_nssa_set(struct ospf *ospf, struct in_addr area_id) { - struct ospf_area *area; + struct ospf_area *area; - area = ospf_area_get (ospf, area_id); - if (ospf_area_vlink_count (ospf, area)) - return 0; + area = ospf_area_get(ospf, area_id); + if (ospf_area_vlink_count(ospf, area)) + return 0; - if (area->external_routing != OSPF_AREA_NSSA) - { - ospf_area_type_set (area, OSPF_AREA_NSSA); - ospf->anyNSSA++; - } + if (area->external_routing != OSPF_AREA_NSSA) { + ospf_area_type_set(area, OSPF_AREA_NSSA); + ospf->anyNSSA++; + } - /* set NSSA area defaults */ - area->no_summary = 0; - area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE; - area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED; - area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT; + /* set NSSA area defaults */ + area->no_summary = 0; + area->NSSATranslatorRole = OSPF_NSSA_ROLE_CANDIDATE; + area->NSSATranslatorState = OSPF_NSSA_TRANSLATE_DISABLED; + area->NSSATranslatorStabilityInterval = OSPF_NSSA_TRANS_STABLE_DEFAULT; - return 1; + return 1; } -int -ospf_area_nssa_unset (struct ospf *ospf, struct in_addr area_id) +int ospf_area_nssa_unset(struct ospf *ospf, struct in_addr area_id) { - struct ospf_area *area; + struct ospf_area *area; - area = ospf_area_lookup_by_area_id (ospf, area_id); - if (area == NULL) - return 0; + area = ospf_area_lookup_by_area_id(ospf, area_id); + if (area == NULL) + return 0; - if (area->external_routing == OSPF_AREA_NSSA) - { - ospf->anyNSSA--; - ospf_area_type_set (area, OSPF_AREA_DEFAULT); - } + if (area->external_routing == OSPF_AREA_NSSA) { + ospf->anyNSSA--; + ospf_area_type_set(area, OSPF_AREA_DEFAULT); + } - ospf_area_check_free (ospf, area_id); + ospf_area_check_free(ospf, area_id); - return 1; + return 1; } -int -ospf_area_nssa_translator_role_set (struct ospf *ospf, struct in_addr area_id, - int role) +int ospf_area_nssa_translator_role_set(struct ospf *ospf, + struct in_addr area_id, int role) { - struct ospf_area *area; + struct ospf_area *area; - area = ospf_area_lookup_by_area_id (ospf, area_id); - if (area == NULL) - return 0; + area = ospf_area_lookup_by_area_id(ospf, area_id); + if (area == NULL) + return 0; - area->NSSATranslatorRole = role; + area->NSSATranslatorRole = role; - return 1; + return 1; } #if 0 @@ -1526,276 +1460,258 @@ ospf_area_nssa_translator_role_unset (struct ospf *ospf, } #endif -int -ospf_area_export_list_set (struct ospf *ospf, - struct ospf_area *area, const char *list_name) +int ospf_area_export_list_set(struct ospf *ospf, struct ospf_area *area, + const char *list_name) { - struct access_list *list; - list = access_list_lookup (AFI_IP, list_name); + struct access_list *list; + list = access_list_lookup(AFI_IP, list_name); - EXPORT_LIST (area) = list; + EXPORT_LIST(area) = list; - if (EXPORT_NAME (area)) - free (EXPORT_NAME (area)); + if (EXPORT_NAME(area)) + free(EXPORT_NAME(area)); - EXPORT_NAME (area) = strdup (list_name); - ospf_schedule_abr_task (ospf); + EXPORT_NAME(area) = strdup(list_name); + ospf_schedule_abr_task(ospf); - return 1; + return 1; } -int -ospf_area_export_list_unset (struct ospf *ospf, struct ospf_area * area) +int ospf_area_export_list_unset(struct ospf *ospf, struct ospf_area *area) { - EXPORT_LIST (area) = 0; + EXPORT_LIST(area) = 0; - if (EXPORT_NAME (area)) - free (EXPORT_NAME (area)); + if (EXPORT_NAME(area)) + free(EXPORT_NAME(area)); - EXPORT_NAME (area) = NULL; + EXPORT_NAME(area) = NULL; - ospf_area_check_free (ospf, area->area_id); - - ospf_schedule_abr_task (ospf); + ospf_area_check_free(ospf, area->area_id); - return 1; + ospf_schedule_abr_task(ospf); + + return 1; } -int -ospf_area_import_list_set (struct ospf *ospf, struct ospf_area *area, - const char *name) +int ospf_area_import_list_set(struct ospf *ospf, struct ospf_area *area, + const char *name) { - struct access_list *list; - list = access_list_lookup (AFI_IP, name); + struct access_list *list; + list = access_list_lookup(AFI_IP, name); - IMPORT_LIST (area) = list; + IMPORT_LIST(area) = list; - if (IMPORT_NAME (area)) - free (IMPORT_NAME (area)); + if (IMPORT_NAME(area)) + free(IMPORT_NAME(area)); - IMPORT_NAME (area) = strdup (name); - ospf_schedule_abr_task (ospf); + IMPORT_NAME(area) = strdup(name); + ospf_schedule_abr_task(ospf); - return 1; + return 1; } -int -ospf_area_import_list_unset (struct ospf *ospf, struct ospf_area * area) +int ospf_area_import_list_unset(struct ospf *ospf, struct ospf_area *area) { - IMPORT_LIST (area) = 0; + IMPORT_LIST(area) = 0; - if (IMPORT_NAME (area)) - free (IMPORT_NAME (area)); + if (IMPORT_NAME(area)) + free(IMPORT_NAME(area)); - IMPORT_NAME (area) = NULL; - ospf_area_check_free (ospf, area->area_id); + IMPORT_NAME(area) = NULL; + ospf_area_check_free(ospf, area->area_id); - ospf_schedule_abr_task (ospf); + ospf_schedule_abr_task(ospf); - return 1; + return 1; } -int -ospf_timers_refresh_set (struct ospf *ospf, int interval) +int ospf_timers_refresh_set(struct ospf *ospf, int interval) { - int time_left; + int time_left; - if (ospf->lsa_refresh_interval == interval) - return 1; + if (ospf->lsa_refresh_interval == interval) + return 1; - time_left = ospf->lsa_refresh_interval - - (monotime(NULL) - ospf->lsa_refresher_started); - - if (time_left > interval) - { - OSPF_TIMER_OFF (ospf->t_lsa_refresher); - thread_add_timer(master, ospf_lsa_refresh_walker, ospf, interval, - &ospf->t_lsa_refresher); - } - ospf->lsa_refresh_interval = interval; + time_left = ospf->lsa_refresh_interval + - (monotime(NULL) - ospf->lsa_refresher_started); - return 1; + if (time_left > interval) { + OSPF_TIMER_OFF(ospf->t_lsa_refresher); + thread_add_timer(master, ospf_lsa_refresh_walker, ospf, + interval, &ospf->t_lsa_refresher); + } + ospf->lsa_refresh_interval = interval; + + return 1; } -int -ospf_timers_refresh_unset (struct ospf *ospf) +int ospf_timers_refresh_unset(struct ospf *ospf) { - int time_left; + int time_left; - time_left = ospf->lsa_refresh_interval - - (monotime(NULL) - ospf->lsa_refresher_started); + time_left = ospf->lsa_refresh_interval + - (monotime(NULL) - ospf->lsa_refresher_started); - if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT) - { - OSPF_TIMER_OFF (ospf->t_lsa_refresher); - ospf->t_lsa_refresher = NULL; - thread_add_timer(master, ospf_lsa_refresh_walker, ospf, OSPF_LSA_REFRESH_INTERVAL_DEFAULT, - &ospf->t_lsa_refresher); - } + if (time_left > OSPF_LSA_REFRESH_INTERVAL_DEFAULT) { + OSPF_TIMER_OFF(ospf->t_lsa_refresher); + ospf->t_lsa_refresher = NULL; + thread_add_timer(master, ospf_lsa_refresh_walker, ospf, + OSPF_LSA_REFRESH_INTERVAL_DEFAULT, + &ospf->t_lsa_refresher); + } - ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT; + ospf->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT; - return 1; + return 1; } -static struct ospf_nbr_nbma * -ospf_nbr_nbma_new (void) +static struct ospf_nbr_nbma *ospf_nbr_nbma_new(void) { - struct ospf_nbr_nbma *nbr_nbma; + struct ospf_nbr_nbma *nbr_nbma; - nbr_nbma = XCALLOC (MTYPE_OSPF_NEIGHBOR_STATIC, - sizeof (struct ospf_nbr_nbma)); + nbr_nbma = XCALLOC(MTYPE_OSPF_NEIGHBOR_STATIC, + sizeof(struct ospf_nbr_nbma)); - nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT; - nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT; + nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT; + nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT; - return nbr_nbma; + return nbr_nbma; } -static void -ospf_nbr_nbma_free (struct ospf_nbr_nbma *nbr_nbma) +static void ospf_nbr_nbma_free(struct ospf_nbr_nbma *nbr_nbma) { - XFREE (MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma); + XFREE(MTYPE_OSPF_NEIGHBOR_STATIC, nbr_nbma); } -static void -ospf_nbr_nbma_delete (struct ospf *ospf, struct ospf_nbr_nbma *nbr_nbma) +static void ospf_nbr_nbma_delete(struct ospf *ospf, + struct ospf_nbr_nbma *nbr_nbma) { - struct route_node *rn; - struct prefix_ipv4 p; + struct route_node *rn; + struct prefix_ipv4 p; - p.family = AF_INET; - p.prefix = nbr_nbma->addr; - p.prefixlen = IPV4_MAX_BITLEN; + p.family = AF_INET; + p.prefix = nbr_nbma->addr; + p.prefixlen = IPV4_MAX_BITLEN; - rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p); - if (rn) - { - ospf_nbr_nbma_free (rn->info); - rn->info = NULL; - route_unlock_node (rn); - route_unlock_node (rn); - } + rn = route_node_lookup(ospf->nbr_nbma, (struct prefix *)&p); + if (rn) { + ospf_nbr_nbma_free(rn->info); + rn->info = NULL; + route_unlock_node(rn); + route_unlock_node(rn); + } } -static void -ospf_nbr_nbma_down (struct ospf_nbr_nbma *nbr_nbma) +static void ospf_nbr_nbma_down(struct ospf_nbr_nbma *nbr_nbma) { - OSPF_TIMER_OFF (nbr_nbma->t_poll); + OSPF_TIMER_OFF(nbr_nbma->t_poll); - if (nbr_nbma->nbr) - { - nbr_nbma->nbr->nbr_nbma = NULL; - OSPF_NSM_EVENT_EXECUTE (nbr_nbma->nbr, NSM_KillNbr); - } + if (nbr_nbma->nbr) { + nbr_nbma->nbr->nbr_nbma = NULL; + OSPF_NSM_EVENT_EXECUTE(nbr_nbma->nbr, NSM_KillNbr); + } - if (nbr_nbma->oi) - listnode_delete (nbr_nbma->oi->nbr_nbma, nbr_nbma); + if (nbr_nbma->oi) + listnode_delete(nbr_nbma->oi->nbr_nbma, nbr_nbma); } -static void -ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma, - struct ospf_interface *oi) +static void ospf_nbr_nbma_add(struct ospf_nbr_nbma *nbr_nbma, + struct ospf_interface *oi) { - struct ospf_neighbor *nbr; - struct route_node *rn; - struct prefix p; + struct ospf_neighbor *nbr; + struct route_node *rn; + struct prefix p; - if (oi->type != OSPF_IFTYPE_NBMA) - return; + if (oi->type != OSPF_IFTYPE_NBMA) + return; - if (nbr_nbma->nbr != NULL) - return; + if (nbr_nbma->nbr != NULL) + return; - if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr)) - return; - - nbr_nbma->oi = oi; - listnode_add (oi->nbr_nbma, nbr_nbma); + if (IPV4_ADDR_SAME(&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr)) + return; - /* Get neighbor information from table. */ - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - p.u.prefix4 = nbr_nbma->addr; + nbr_nbma->oi = oi; + listnode_add(oi->nbr_nbma, nbr_nbma); - rn = route_node_get (oi->nbrs, (struct prefix *)&p); - if (rn->info) - { - nbr = rn->info; - nbr->nbr_nbma = nbr_nbma; - nbr_nbma->nbr = nbr; + /* Get neighbor information from table. */ + p.family = AF_INET; + p.prefixlen = IPV4_MAX_BITLEN; + p.u.prefix4 = nbr_nbma->addr; - route_unlock_node (rn); - } - else - { - nbr = rn->info = ospf_nbr_new (oi); - nbr->state = NSM_Down; - nbr->src = nbr_nbma->addr; - nbr->nbr_nbma = nbr_nbma; - nbr->priority = nbr_nbma->priority; - nbr->address = p; + rn = route_node_get(oi->nbrs, (struct prefix *)&p); + if (rn->info) { + nbr = rn->info; + nbr->nbr_nbma = nbr_nbma; + nbr_nbma->nbr = nbr; - nbr_nbma->nbr = nbr; + route_unlock_node(rn); + } else { + nbr = rn->info = ospf_nbr_new(oi); + nbr->state = NSM_Down; + nbr->src = nbr_nbma->addr; + nbr->nbr_nbma = nbr_nbma; + nbr->priority = nbr_nbma->priority; + nbr->address = p; - OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start); - } + nbr_nbma->nbr = nbr; + + OSPF_NSM_EVENT_EXECUTE(nbr, NSM_Start); + } } -void -ospf_nbr_nbma_if_update (struct ospf *ospf, struct ospf_interface *oi) +void ospf_nbr_nbma_if_update(struct ospf *ospf, struct ospf_interface *oi) { - struct ospf_nbr_nbma *nbr_nbma; - struct route_node *rn; - struct prefix_ipv4 p; + struct ospf_nbr_nbma *nbr_nbma; + struct route_node *rn; + struct prefix_ipv4 p; - if (oi->type != OSPF_IFTYPE_NBMA) - return; + if (oi->type != OSPF_IFTYPE_NBMA) + return; - for (rn = route_top (ospf->nbr_nbma); rn; rn = route_next (rn)) - if ((nbr_nbma = rn->info)) - if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL) - { - p.family = AF_INET; - p.prefix = nbr_nbma->addr; - p.prefixlen = IPV4_MAX_BITLEN; + for (rn = route_top(ospf->nbr_nbma); rn; rn = route_next(rn)) + if ((nbr_nbma = rn->info)) + if (nbr_nbma->oi == NULL && nbr_nbma->nbr == NULL) { + p.family = AF_INET; + p.prefix = nbr_nbma->addr; + p.prefixlen = IPV4_MAX_BITLEN; - if (prefix_match (oi->address, (struct prefix *)&p)) - ospf_nbr_nbma_add (nbr_nbma, oi); - } + if (prefix_match(oi->address, + (struct prefix *)&p)) + ospf_nbr_nbma_add(nbr_nbma, oi); + } } -struct ospf_nbr_nbma * -ospf_nbr_nbma_lookup (struct ospf *ospf, struct in_addr nbr_addr) +struct ospf_nbr_nbma *ospf_nbr_nbma_lookup(struct ospf *ospf, + struct in_addr nbr_addr) { - struct route_node *rn; - struct prefix_ipv4 p; + struct route_node *rn; + struct prefix_ipv4 p; - p.family = AF_INET; - p.prefix = nbr_addr; - p.prefixlen = IPV4_MAX_BITLEN; + p.family = AF_INET; + p.prefix = nbr_addr; + p.prefixlen = IPV4_MAX_BITLEN; - rn = route_node_lookup (ospf->nbr_nbma, (struct prefix *)&p); - if (rn) - { - route_unlock_node (rn); - return rn->info; - } - return NULL; + rn = route_node_lookup(ospf->nbr_nbma, (struct prefix *)&p); + if (rn) { + route_unlock_node(rn); + return rn->info; + } + return NULL; } -struct ospf_nbr_nbma * -ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first) +struct ospf_nbr_nbma *ospf_nbr_nbma_lookup_next(struct ospf *ospf, + struct in_addr *addr, int first) { #if 0 struct ospf_nbr_nbma *nbr_nbma; struct listnode *node; #endif - if (ospf == NULL) - return NULL; + if (ospf == NULL) + return NULL; #if 0 for (ALL_LIST_ELEMENTS_RO (ospf->nbr_nbma, node, nbr_nbma)) @@ -1812,138 +1728,127 @@ ospf_nbr_nbma_lookup_next (struct ospf *ospf, struct in_addr *addr, int first) } } #endif - return NULL; + return NULL; } -int -ospf_nbr_nbma_set (struct ospf *ospf, struct in_addr nbr_addr) +int ospf_nbr_nbma_set(struct ospf *ospf, struct in_addr nbr_addr) { - struct ospf_nbr_nbma *nbr_nbma; - struct ospf_interface *oi; - struct prefix_ipv4 p; - struct route_node *rn; - struct listnode *node; + struct ospf_nbr_nbma *nbr_nbma; + struct ospf_interface *oi; + struct prefix_ipv4 p; + struct route_node *rn; + struct listnode *node; - nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr); - if (nbr_nbma) - return 0; + nbr_nbma = ospf_nbr_nbma_lookup(ospf, nbr_addr); + if (nbr_nbma) + return 0; - nbr_nbma = ospf_nbr_nbma_new (); - nbr_nbma->addr = nbr_addr; + nbr_nbma = ospf_nbr_nbma_new(); + nbr_nbma->addr = nbr_addr; - p.family = AF_INET; - p.prefix = nbr_addr; - p.prefixlen = IPV4_MAX_BITLEN; + p.family = AF_INET; + p.prefix = nbr_addr; + p.prefixlen = IPV4_MAX_BITLEN; - rn = route_node_get (ospf->nbr_nbma, (struct prefix *)&p); - if (rn->info) - route_unlock_node (rn); - rn->info = nbr_nbma; + rn = route_node_get(ospf->nbr_nbma, (struct prefix *)&p); + if (rn->info) + route_unlock_node(rn); + rn->info = nbr_nbma; - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) - { - if (oi->type == OSPF_IFTYPE_NBMA) - if (prefix_match (oi->address, (struct prefix *)&p)) - { - ospf_nbr_nbma_add (nbr_nbma, oi); - break; - } - } + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { + if (oi->type == OSPF_IFTYPE_NBMA) + if (prefix_match(oi->address, (struct prefix *)&p)) { + ospf_nbr_nbma_add(nbr_nbma, oi); + break; + } + } - return 1; + return 1; } -int -ospf_nbr_nbma_unset (struct ospf *ospf, struct in_addr nbr_addr) +int ospf_nbr_nbma_unset(struct ospf *ospf, struct in_addr nbr_addr) { - struct ospf_nbr_nbma *nbr_nbma; + struct ospf_nbr_nbma *nbr_nbma; - nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr); - if (nbr_nbma == NULL) - return 0; + nbr_nbma = ospf_nbr_nbma_lookup(ospf, nbr_addr); + if (nbr_nbma == NULL) + return 0; - ospf_nbr_nbma_down (nbr_nbma); - ospf_nbr_nbma_delete (ospf, nbr_nbma); + ospf_nbr_nbma_down(nbr_nbma); + ospf_nbr_nbma_delete(ospf, nbr_nbma); - return 1; + return 1; } -int -ospf_nbr_nbma_priority_set (struct ospf *ospf, struct in_addr nbr_addr, - u_char priority) +int ospf_nbr_nbma_priority_set(struct ospf *ospf, struct in_addr nbr_addr, + u_char priority) { - struct ospf_nbr_nbma *nbr_nbma; + struct ospf_nbr_nbma *nbr_nbma; - nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr); - if (nbr_nbma == NULL) - return 0; + nbr_nbma = ospf_nbr_nbma_lookup(ospf, nbr_addr); + if (nbr_nbma == NULL) + return 0; - if (nbr_nbma->priority != priority) - nbr_nbma->priority = priority; + if (nbr_nbma->priority != priority) + nbr_nbma->priority = priority; - return 1; + return 1; } -int -ospf_nbr_nbma_priority_unset (struct ospf *ospf, struct in_addr nbr_addr) +int ospf_nbr_nbma_priority_unset(struct ospf *ospf, struct in_addr nbr_addr) { - struct ospf_nbr_nbma *nbr_nbma; + struct ospf_nbr_nbma *nbr_nbma; - nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr); - if (nbr_nbma == NULL) - return 0; + nbr_nbma = ospf_nbr_nbma_lookup(ospf, nbr_addr); + if (nbr_nbma == NULL) + return 0; - if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT) - nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT; + if (nbr_nbma != OSPF_NEIGHBOR_PRIORITY_DEFAULT) + nbr_nbma->priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT; - return 1; + return 1; } -int -ospf_nbr_nbma_poll_interval_set (struct ospf *ospf, struct in_addr nbr_addr, - unsigned int interval) +int ospf_nbr_nbma_poll_interval_set(struct ospf *ospf, struct in_addr nbr_addr, + unsigned int interval) { - struct ospf_nbr_nbma *nbr_nbma; + struct ospf_nbr_nbma *nbr_nbma; - nbr_nbma = ospf_nbr_nbma_lookup (ospf, nbr_addr); - if (nbr_nbma == NULL) - return 0; + nbr_nbma = ospf_nbr_nbma_lookup(ospf, nbr_addr); + if (nbr_nbma == NULL) + return 0; - if (nbr_nbma->v_poll != interval) - { - nbr_nbma->v_poll = interval; - if (nbr_nbma->oi && ospf_if_is_up (nbr_nbma->oi)) - { - OSPF_TIMER_OFF (nbr_nbma->t_poll); - OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer, - nbr_nbma->v_poll); + if (nbr_nbma->v_poll != interval) { + nbr_nbma->v_poll = interval; + if (nbr_nbma->oi && ospf_if_is_up(nbr_nbma->oi)) { + OSPF_TIMER_OFF(nbr_nbma->t_poll); + OSPF_POLL_TIMER_ON(nbr_nbma->t_poll, ospf_poll_timer, + nbr_nbma->v_poll); + } } - } - return 1; + return 1; } -int -ospf_nbr_nbma_poll_interval_unset (struct ospf *ospf, struct in_addr addr) +int ospf_nbr_nbma_poll_interval_unset(struct ospf *ospf, struct in_addr addr) { - struct ospf_nbr_nbma *nbr_nbma; + struct ospf_nbr_nbma *nbr_nbma; - nbr_nbma = ospf_nbr_nbma_lookup (ospf, addr); - if (nbr_nbma == NULL) - return 0; + nbr_nbma = ospf_nbr_nbma_lookup(ospf, addr); + if (nbr_nbma == NULL) + return 0; - if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT) - nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT; + if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT) + nbr_nbma->v_poll = OSPF_POLL_INTERVAL_DEFAULT; - return 1; + return 1; } -void -ospf_master_init (struct thread_master *master) +void ospf_master_init(struct thread_master *master) { - memset (&ospf_master, 0, sizeof (struct ospf_master)); + memset(&ospf_master, 0, sizeof(struct ospf_master)); - om = &ospf_master; - om->ospf = list_new (); - om->master = master; + om = &ospf_master; + om->ospf = list_new(); + om->master = master; } diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index b93f13728..4142f1a3e 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -49,14 +49,13 @@ #define OSPF_ALLSPFROUTERS 0xe0000005 /* 224.0.0.5 */ #define OSPF_ALLDROUTERS 0xe0000006 /* 224.0.0.6 */ - /* OSPF Authentication Type. */ #define OSPF_AUTH_NULL 0 #define OSPF_AUTH_SIMPLE 1 #define OSPF_AUTH_CRYPTOGRAPHIC 2 /* For Interface authentication setting default */ #define OSPF_AUTH_NOTSET -1 -/* For the consumption and sanity of the command handler */ +/* For the consumption and sanity of the command handler */ /* DO NIOT REMOVE!!! Need to detect whether a value has been given or not in VLink command handlers */ #define OSPF_AUTH_CMD_NOTSEEN -2 @@ -80,75 +79,70 @@ #define OSPF_LS_REFRESH_SHIFT (60 * 15) #define OSPF_LS_REFRESH_JITTER 60 -struct ospf_external -{ - u_short instance; - struct route_table *external_info; +struct ospf_external { + u_short instance; + struct route_table *external_info; }; /* OSPF master for system wide configuration and variables. */ -struct ospf_master -{ - /* OSPF instance. */ - struct list *ospf; +struct ospf_master { + /* OSPF instance. */ + struct list *ospf; - /* OSPF thread master. */ - struct thread_master *master; + /* OSPF thread master. */ + struct thread_master *master; - /* Zebra interface list. */ - struct list *iflist; + /* Zebra interface list. */ + struct list *iflist; - /* Redistributed external information. */ - struct list *external[ZEBRA_ROUTE_MAX + 1]; + /* Redistributed external information. */ + struct list *external[ZEBRA_ROUTE_MAX + 1]; #define EXTERNAL_INFO(E) (E->external_info) - /* Various OSPF global configuration. */ - u_char options; + /* Various OSPF global configuration. */ + u_char options; #define OSPF_MASTER_SHUTDOWN (1 << 0) /* deferred-shutdown */ }; -struct ospf_redist -{ - u_short instance; - - /* Redistribute metric info. */ - struct - { - int type; /* External metric type (E1 or E2). */ - int value; /* Value for static metric (24-bit). - -1 means metric value is not set. */ - } dmetric; - - /* For redistribute route map. */ - struct - { - char *name; - struct route_map *map; - } route_map; /* +1 is for default-information */ +struct ospf_redist { + u_short instance; + + /* Redistribute metric info. */ + struct { + int type; /* External metric type (E1 or E2). */ + int value; /* Value for static metric (24-bit). + -1 means metric value is not set. */ + } dmetric; + + /* For redistribute route map. */ + struct { + char *name; + struct route_map *map; + } route_map; /* +1 is for default-information */ #define ROUTEMAP_NAME(R) (R->route_map.name) #define ROUTEMAP(R) (R->route_map.map) }; /* OSPF instance structure. */ -struct ospf -{ - /* OSPF's running state based on the '[no] router ospf []' config. */ - u_char oi_running; +struct ospf { + /* OSPF's running state based on the '[no] router ospf []' + * config. */ + u_char oi_running; - /* OSPF instance ID */ - u_short instance; + /* OSPF instance ID */ + u_short instance; - /* OSPF Router ID. */ - struct in_addr router_id; /* Configured automatically. */ - struct in_addr router_id_static; /* Configured manually. */ + /* OSPF Router ID. */ + struct in_addr router_id; /* Configured automatically. */ + struct in_addr router_id_static; /* Configured manually. */ - /* ABR/ASBR internal flags. */ - u_char flags; + /* ABR/ASBR internal flags. */ + u_char flags; #define OSPF_FLAG_ABR 0x0001 #define OSPF_FLAG_ASBR 0x0002 - /* ABR type. */ - u_char abr_type; + /* ABR type. */ + u_char abr_type; #define OSPF_ABR_UNKNOWN 0 #define OSPF_ABR_STAND 1 #define OSPF_ABR_IBM 2 @@ -156,311 +150,320 @@ struct ospf #define OSPF_ABR_SHORTCUT 4 #define OSPF_ABR_DEFAULT OSPF_ABR_CISCO - /* NSSA ABR */ - u_char anyNSSA; /* Bump for every NSSA attached. */ + /* NSSA ABR */ + u_char anyNSSA; /* Bump for every NSSA attached. */ - /* Configured variables. */ - u_char config; + /* Configured variables. */ + u_char config; #define OSPF_RFC1583_COMPATIBLE (1 << 0) #define OSPF_OPAQUE_CAPABLE (1 << 2) #define OSPF_LOG_ADJACENCY_CHANGES (1 << 3) #define OSPF_LOG_ADJACENCY_DETAIL (1 << 4) - /* Opaque-LSA administrative flags. */ - u_char opaque; + /* Opaque-LSA administrative flags. */ + u_char opaque; #define OPAQUE_OPERATION_READY_BIT (1 << 0) - /* RFC3137 stub router. Configured time to stay stub / max-metric */ - unsigned int stub_router_startup_time; /* seconds */ - unsigned int stub_router_shutdown_time; /* seconds */ + /* RFC3137 stub router. Configured time to stay stub / max-metric */ + unsigned int stub_router_startup_time; /* seconds */ + unsigned int stub_router_shutdown_time; /* seconds */ + /* $FRR indent$ */ + /* clang-format off */ #define OSPF_STUB_ROUTER_UNCONFIGURED 0 - u_char stub_router_admin_set; + u_char stub_router_admin_set; #define OSPF_STUB_ROUTER_ADMINISTRATIVE_SET 1 #define OSPF_STUB_ROUTER_ADMINISTRATIVE_UNSET 0 #define OSPF_STUB_MAX_METRIC_SUMMARY_COST 0x00ff0000 - /* LSA timers */ - unsigned int min_ls_interval; /* minimum delay between LSAs (in msec) */ - unsigned int min_ls_arrival; /* minimum interarrival time between LSAs (in msec) */ - - /* SPF parameters */ - unsigned int spf_delay; /* SPF delay time. */ - unsigned int spf_holdtime; /* SPF hold time. */ - unsigned int spf_max_holdtime; /* SPF maximum-holdtime */ - unsigned int spf_hold_multiplier; /* Adaptive multiplier for hold time */ - - int default_originate; /* Default information originate. */ + /* LSA timers */ + unsigned int min_ls_interval; /* minimum delay between LSAs (in msec) */ + unsigned int min_ls_arrival; /* minimum interarrival time between LSAs + (in msec) */ + + /* SPF parameters */ + unsigned int spf_delay; /* SPF delay time. */ + unsigned int spf_holdtime; /* SPF hold time. */ + unsigned int spf_max_holdtime; /* SPF maximum-holdtime */ + unsigned int + spf_hold_multiplier; /* Adaptive multiplier for hold time */ + + int default_originate; /* Default information originate. */ + /* $FRR indent$ */ + /* clang-format off */ #define DEFAULT_ORIGINATE_NONE 0 #define DEFAULT_ORIGINATE_ZEBRA 1 #define DEFAULT_ORIGINATE_ALWAYS 2 - u_int32_t ref_bandwidth; /* Reference Bandwidth (Kbps). */ - struct route_table *networks; /* OSPF config networks. */ - struct list *vlinks; /* Configured Virtual-Links. */ - struct list *areas; /* OSPF areas. */ - struct route_table *nbr_nbma; - struct ospf_area *backbone; /* Pointer to the Backbone Area. */ - - struct list *oiflist; /* ospf interfaces */ - u_char passive_interface_default; /* passive-interface default */ - - /* LSDB of AS-external-LSAs. */ - struct ospf_lsdb *lsdb; - - /* Flags. */ - int external_origin; /* AS-external-LSA origin flag. */ - int ase_calc; /* ASE calculation flag. */ - - struct list *opaque_lsa_self; /* Type-11 Opaque-LSAs */ - - /* Routing tables. */ - struct route_table *old_table; /* Old routing table. */ - struct route_table *new_table; /* Current routing table. */ - - struct route_table *old_rtrs; /* Old ABR/ASBR RT. */ - struct route_table *new_rtrs; /* New ABR/ASBR RT. */ - - struct route_table *new_external_route; /* New External Route. */ - struct route_table *old_external_route; /* Old External Route. */ - - struct route_table *external_lsas; /* Database of external LSAs, - prefix is LSA's adv. network*/ - - /* Time stamps */ - struct timeval ts_spf; /* SPF calculation time stamp. */ - struct timeval ts_spf_duration; /* Execution time of last SPF */ - - struct route_table *maxage_lsa; /* List of MaxAge LSA for deletion. */ - int redistribute; /* Num of redistributed protocols. */ - - /* Threads. */ - struct thread *t_abr_task; /* ABR task timer. */ - struct thread *t_asbr_check; /* ASBR check timer. */ - struct thread *t_distribute_update; /* Distirbute list update timer. */ - struct thread *t_spf_calc; /* SPF calculation timer. */ - struct thread *t_ase_calc; /* ASE calculation timer. */ - struct thread *t_external_lsa; /* AS-external-LSA origin timer. */ - struct thread *t_opaque_lsa_self; /* Type-11 Opaque-LSAs origin event. */ - - unsigned int maxage_delay; /* Delay on Maxage remover timer, sec */ - struct thread *t_maxage; /* MaxAge LSA remover timer. */ - struct thread *t_maxage_walker; /* MaxAge LSA checking timer. */ - - struct thread *t_deferred_shutdown; /* deferred/stub-router shutdown timer*/ - - struct thread *t_write; + u_int32_t ref_bandwidth; /* Reference Bandwidth (Kbps). */ + struct route_table *networks; /* OSPF config networks. */ + struct list *vlinks; /* Configured Virtual-Links. */ + struct list *areas; /* OSPF areas. */ + struct route_table *nbr_nbma; + struct ospf_area *backbone; /* Pointer to the Backbone Area. */ + + struct list *oiflist; /* ospf interfaces */ + u_char passive_interface_default; /* passive-interface default */ + + /* LSDB of AS-external-LSAs. */ + struct ospf_lsdb *lsdb; + + /* Flags. */ + int external_origin; /* AS-external-LSA origin flag. */ + int ase_calc; /* ASE calculation flag. */ + + struct list *opaque_lsa_self; /* Type-11 Opaque-LSAs */ + + /* Routing tables. */ + struct route_table *old_table; /* Old routing table. */ + struct route_table *new_table; /* Current routing table. */ + + struct route_table *old_rtrs; /* Old ABR/ASBR RT. */ + struct route_table *new_rtrs; /* New ABR/ASBR RT. */ + + struct route_table *new_external_route; /* New External Route. */ + struct route_table *old_external_route; /* Old External Route. */ + + struct route_table *external_lsas; /* Database of external LSAs, + prefix is LSA's adv. network*/ + + /* Time stamps */ + struct timeval ts_spf; /* SPF calculation time stamp. */ + struct timeval ts_spf_duration; /* Execution time of last SPF */ + + struct route_table *maxage_lsa; /* List of MaxAge LSA for deletion. */ + int redistribute; /* Num of redistributed protocols. */ + + /* Threads. */ + struct thread *t_abr_task; /* ABR task timer. */ + struct thread *t_asbr_check; /* ASBR check timer. */ + struct thread *t_distribute_update; /* Distirbute list update timer. */ + struct thread *t_spf_calc; /* SPF calculation timer. */ + struct thread *t_ase_calc; /* ASE calculation timer. */ + struct thread *t_external_lsa; /* AS-external-LSA origin timer. */ + struct thread + *t_opaque_lsa_self; /* Type-11 Opaque-LSAs origin event. */ + + unsigned int maxage_delay; /* Delay on Maxage remover timer, sec */ + struct thread *t_maxage; /* MaxAge LSA remover timer. */ + struct thread *t_maxage_walker; /* MaxAge LSA checking timer. */ + + struct thread + *t_deferred_shutdown; /* deferred/stub-router shutdown timer*/ + + struct thread *t_write; #define OSPF_WRITE_INTERFACE_COUNT_DEFAULT 20 - int write_oi_count; /* Num of packets sent per thread invocation */ - struct thread *t_read; - int fd; - struct stream *ibuf; - struct list *oi_write_q; - - /* Distribute lists out of other route sources. */ - struct - { - char *name; - struct access_list *list; - } dlist[ZEBRA_ROUTE_MAX]; + int write_oi_count; /* Num of packets sent per thread invocation */ + struct thread *t_read; + int fd; + struct stream *ibuf; + struct list *oi_write_q; + + /* Distribute lists out of other route sources. */ + struct { + char *name; + struct access_list *list; + } dlist[ZEBRA_ROUTE_MAX]; #define DISTRIBUTE_NAME(O,T) (O)->dlist[T].name #define DISTRIBUTE_LIST(O,T) (O)->dlist[T].list - /* OSPF redistribute configuration */ - struct list *redist[ZEBRA_ROUTE_MAX + 1]; + /* OSPF redistribute configuration */ + struct list *redist[ZEBRA_ROUTE_MAX + 1]; - /* Redistribute tag info. */ - route_tag_t dtag[ZEBRA_ROUTE_MAX + 1]; //Pending: cant configure as of now + /* Redistribute tag info. */ + route_tag_t + dtag[ZEBRA_ROUTE_MAX + 1]; // Pending: cant configure as of now - int default_metric; /* Default metric for redistribute. */ + int default_metric; /* Default metric for redistribute. */ #define OSPF_LSA_REFRESHER_GRANULARITY 10 -#define OSPF_LSA_REFRESHER_SLOTS ((OSPF_LS_REFRESH_TIME + \ - OSPF_LS_REFRESH_SHIFT)/OSPF_LSA_REFRESHER_GRANULARITY + 1) - struct - { - u_int16_t index; - struct list *qs[OSPF_LSA_REFRESHER_SLOTS]; - } lsa_refresh_queue; - - struct thread *t_lsa_refresher; - time_t lsa_refresher_started; +#define OSPF_LSA_REFRESHER_SLOTS \ + ((OSPF_LS_REFRESH_TIME + OSPF_LS_REFRESH_SHIFT) \ + / OSPF_LSA_REFRESHER_GRANULARITY \ + + 1) + struct { + u_int16_t index; + struct list *qs[OSPF_LSA_REFRESHER_SLOTS]; + } lsa_refresh_queue; + + struct thread *t_lsa_refresher; + time_t lsa_refresher_started; #define OSPF_LSA_REFRESH_INTERVAL_DEFAULT 10 - u_int16_t lsa_refresh_interval; - - /* Distance parameter. */ - u_char distance_all; - u_char distance_intra; - u_char distance_inter; - u_char distance_external; - - /* Statistics for LSA origination. */ - u_int32_t lsa_originate_count; - - /* Statistics for LSA used for new instantiation. */ - u_int32_t rx_lsa_count; - - /* Counter of "ip ospf area x.x.x.x" */ - u_int32_t if_ospf_cli_count; - - struct route_table *distance_table; - - QOBJ_FIELDS + u_int16_t lsa_refresh_interval; + + /* Distance parameter. */ + u_char distance_all; + u_char distance_intra; + u_char distance_inter; + u_char distance_external; + + /* Statistics for LSA origination. */ + u_int32_t lsa_originate_count; + + /* Statistics for LSA used for new instantiation. */ + u_int32_t rx_lsa_count; + + /* Counter of "ip ospf area x.x.x.x" */ + u_int32_t if_ospf_cli_count; + + struct route_table *distance_table; + + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(ospf) /* OSPF area structure. */ -struct ospf_area -{ - /* OSPF instance. */ - struct ospf *ospf; +struct ospf_area { + /* OSPF instance. */ + struct ospf *ospf; - /* Zebra interface list belonging to the area. */ - struct list *oiflist; + /* Zebra interface list belonging to the area. */ + struct list *oiflist; - /* Area ID. */ - struct in_addr area_id; + /* Area ID. */ + struct in_addr area_id; - /* Area ID format. */ - int area_id_fmt; + /* Area ID format. */ + int area_id_fmt; #define OSPF_AREA_ID_FMT_DOTTEDQUAD 1 #define OSPF_AREA_ID_FMT_DECIMAL 2 - /* Address range. */ - struct list *address_range; + /* Address range. */ + struct list *address_range; - /* Configured variables. */ - int external_routing; /* ExternalRoutingCapability. */ - int no_summary; /* Don't inject summaries into stub.*/ - int shortcut_configured; /* Area configured as shortcut. */ + /* Configured variables. */ + int external_routing; /* ExternalRoutingCapability. */ + int no_summary; /* Don't inject summaries into stub.*/ + int shortcut_configured; /* Area configured as shortcut. */ + /* $FRR indent$ */ + /* clang-format off */ #define OSPF_SHORTCUT_DEFAULT 0 #define OSPF_SHORTCUT_ENABLE 1 #define OSPF_SHORTCUT_DISABLE 2 - int shortcut_capability; /* Other ABRs agree on S-bit */ - u_int32_t default_cost; /* StubDefaultCost. */ - int auth_type; /* Authentication type. */ - + int shortcut_capability; /* Other ABRs agree on S-bit */ + u_int32_t default_cost; /* StubDefaultCost. */ + int auth_type; /* Authentication type. */ - u_char NSSATranslatorRole; /* NSSA configured role */ + + u_char NSSATranslatorRole; /* NSSA configured role */ + /* $FRR indent$ */ + /* clang-format off */ #define OSPF_NSSA_ROLE_NEVER 0 #define OSPF_NSSA_ROLE_CANDIDATE 1 #define OSPF_NSSA_ROLE_ALWAYS 2 - u_char NSSATranslatorState; /* NSSA operational role */ + u_char NSSATranslatorState; /* NSSA operational role */ + /* $FRR indent$ */ + /* clang-format off */ #define OSPF_NSSA_TRANSLATE_DISABLED 0 #define OSPF_NSSA_TRANSLATE_ENABLED 1 - int NSSATranslatorStabilityInterval; - - u_char transit; /* TransitCapability. */ + int NSSATranslatorStabilityInterval; + + u_char transit; /* TransitCapability. */ + /* $FRR indent$ */ + /* clang-format off */ #define OSPF_TRANSIT_FALSE 0 #define OSPF_TRANSIT_TRUE 1 - struct route_table *ranges; /* Configured Area Ranges. */ - - /* RFC3137 stub router state flags for area */ - u_char stub_router_state; + struct route_table *ranges; /* Configured Area Ranges. */ + + /* RFC3137 stub router state flags for area */ + u_char stub_router_state; #define OSPF_AREA_ADMIN_STUB_ROUTED (1 << 0) /* admin stub-router set */ #define OSPF_AREA_IS_STUB_ROUTED (1 << 1) /* stub-router active */ #define OSPF_AREA_WAS_START_STUB_ROUTED (1 << 2) /* startup SR was done */ - - /* Area related LSDBs[Type1-4]. */ - struct ospf_lsdb *lsdb; - - /* Self-originated LSAs. */ - struct ospf_lsa *router_lsa_self; - struct list *opaque_lsa_self; /* Type-10 Opaque-LSAs */ - - /* Area announce list. */ - struct - { - char *name; - struct access_list *list; - } _export; + /* Area related LSDBs[Type1-4]. */ + struct ospf_lsdb *lsdb; + + /* Self-originated LSAs. */ + struct ospf_lsa *router_lsa_self; + struct list *opaque_lsa_self; /* Type-10 Opaque-LSAs */ + + /* Area announce list. */ + struct { + char *name; + struct access_list *list; + } _export; #define EXPORT_NAME(A) (A)->_export.name #define EXPORT_LIST(A) (A)->_export.list - /* Area acceptance list. */ - struct - { - char *name; - struct access_list *list; - } import; + /* Area acceptance list. */ + struct { + char *name; + struct access_list *list; + } import; #define IMPORT_NAME(A) (A)->import.name #define IMPORT_LIST(A) (A)->import.list - /* Type 3 LSA Area prefix-list. */ - struct - { - char *name; - struct prefix_list *list; - } plist_in; + /* Type 3 LSA Area prefix-list. */ + struct { + char *name; + struct prefix_list *list; + } plist_in; #define PREFIX_LIST_IN(A) (A)->plist_in.list #define PREFIX_NAME_IN(A) (A)->plist_in.name - struct - { - char *name; - struct prefix_list *list; - } plist_out; + struct { + char *name; + struct prefix_list *list; + } plist_out; #define PREFIX_LIST_OUT(A) (A)->plist_out.list #define PREFIX_NAME_OUT(A) (A)->plist_out.name - /* Shortest Path Tree. */ - struct vertex *spf; + /* Shortest Path Tree. */ + struct vertex *spf; - /* Threads. */ - struct thread *t_stub_router; /* Stub-router timer */ - struct thread *t_opaque_lsa_self; /* Type-10 Opaque-LSAs origin. */ + /* Threads. */ + struct thread *t_stub_router; /* Stub-router timer */ + struct thread *t_opaque_lsa_self; /* Type-10 Opaque-LSAs origin. */ - /* Statistics field. */ - u_int32_t spf_calculation; /* SPF Calculation Count. */ + /* Statistics field. */ + u_int32_t spf_calculation; /* SPF Calculation Count. */ - /* Time stamps. */ - struct timeval ts_spf; /* SPF calculation time stamp. */ + /* Time stamps. */ + struct timeval ts_spf; /* SPF calculation time stamp. */ - /* Router count. */ - u_int32_t abr_count; /* ABR router in this area. */ - u_int32_t asbr_count; /* ASBR router in this area. */ + /* Router count. */ + u_int32_t abr_count; /* ABR router in this area. */ + u_int32_t asbr_count; /* ASBR router in this area. */ - /* Counters. */ - u_int32_t act_ints; /* Active interfaces. */ - u_int32_t full_nbrs; /* Fully adjacent neighbors. */ - u_int32_t full_vls; /* Fully adjacent virtual neighbors. */ + /* Counters. */ + u_int32_t act_ints; /* Active interfaces. */ + u_int32_t full_nbrs; /* Fully adjacent neighbors. */ + u_int32_t full_vls; /* Fully adjacent virtual neighbors. */ }; /* OSPF config network structure. */ -struct ospf_network -{ - /* Area ID. */ - struct in_addr area_id; - int area_id_fmt; +struct ospf_network { + /* Area ID. */ + struct in_addr area_id; + int area_id_fmt; }; /* OSPF NBMA neighbor structure. */ -struct ospf_nbr_nbma -{ - /* Neighbor IP address. */ - struct in_addr addr; +struct ospf_nbr_nbma { + /* Neighbor IP address. */ + struct in_addr addr; - /* OSPF interface. */ - struct ospf_interface *oi; + /* OSPF interface. */ + struct ospf_interface *oi; - /* OSPF neighbor structure. */ - struct ospf_neighbor *nbr; + /* OSPF neighbor structure. */ + struct ospf_neighbor *nbr; - /* Neighbor priority. */ - u_char priority; + /* Neighbor priority. */ + u_char priority; - /* Poll timer value. */ - u_int32_t v_poll; + /* Poll timer value. */ + u_int32_t v_poll; - /* Poll timer thread. */ - struct thread *t_poll; + /* Poll timer thread. */ + struct thread *t_poll; - /* State change. */ - u_int32_t state_change; + /* State change. */ + u_int32_t state_change; }; /* Macro. */ -#define OSPF_AREA_SAME(X,Y) \ - (memcmp ((X->area_id), (Y->area_id), IPV4_MAX_BYTELEN) == 0) +#define OSPF_AREA_SAME(X, Y) \ + (memcmp((X->area_id), (Y->area_id), IPV4_MAX_BYTELEN) == 0) #define IS_OSPF_ABR(O) ((O)->flags & OSPF_FLAG_ABR) #define IS_OSPF_ASBR(O) ((O)->flags & OSPF_FLAG_ASBR) @@ -470,27 +473,26 @@ struct ospf_nbr_nbma #ifdef roundup # define ROUNDUP(val, gran) roundup(val, gran) -#else /* roundup */ +#else /* roundup */ # define ROUNDUP(val, gran) (((val) - 1 | (gran) - 1) + 1) #endif /* roundup */ -#define LSA_OPTIONS_GET(area) \ - (((area)->external_routing == OSPF_AREA_DEFAULT) ? OSPF_OPTION_E : 0) -#define LSA_OPTIONS_NSSA_GET(area) \ - (((area)->external_routing == OSPF_AREA_NSSA) ? OSPF_OPTION_NP : 0) +#define LSA_OPTIONS_GET(area) \ + (((area)->external_routing == OSPF_AREA_DEFAULT) ? OSPF_OPTION_E : 0) +#define LSA_OPTIONS_NSSA_GET(area) \ + (((area)->external_routing == OSPF_AREA_NSSA) ? OSPF_OPTION_NP : 0) #define OSPF_TIMER_ON(T,F,V) thread_add_timer (master,(F),ospf,(V),&(T)) #define OSPF_AREA_TIMER_ON(T,F,V) thread_add_timer (master, (F), area, (V), &(T)) #define OSPF_POLL_TIMER_ON(T,F,V) thread_add_timer (master, (F), nbr_nbma, (V), &(T)) #define OSPF_POLL_TIMER_OFF(X) OSPF_TIMER_OFF((X)) -#define OSPF_TIMER_OFF(X) \ - do { \ - if (X) \ - { \ - thread_cancel (X); \ - (X) = NULL; \ - } \ - } while (0) +#define OSPF_TIMER_OFF(X) \ + do { \ + if (X) { \ + thread_cancel(X); \ + (X) = NULL; \ + } \ + } while (0) /* Extern variables. */ extern struct ospf_master *om; @@ -501,68 +503,67 @@ extern int ospf_zlog; /* Prototypes. */ extern const char *ospf_redist_string(u_int route_type); -extern struct ospf *ospf_lookup (void); -extern struct ospf *ospf_lookup_instance (u_short); -extern struct ospf *ospf_get (void); -extern struct ospf *ospf_get_instance (u_short); -extern void ospf_finish (struct ospf *); -extern void ospf_router_id_update (struct ospf *ospf); -extern int ospf_network_set (struct ospf *, struct prefix_ipv4 *, - struct in_addr, int); -extern int ospf_network_unset (struct ospf *, struct prefix_ipv4 *, - struct in_addr); -extern int ospf_area_display_format_set (struct ospf *, struct ospf_area *area, - int df); -extern int ospf_area_stub_set (struct ospf *, struct in_addr); -extern int ospf_area_stub_unset (struct ospf *, struct in_addr); -extern int ospf_area_no_summary_set (struct ospf *, struct in_addr); -extern int ospf_area_no_summary_unset (struct ospf *, struct in_addr); -extern int ospf_area_nssa_set (struct ospf *, struct in_addr); -extern int ospf_area_nssa_unset (struct ospf *, struct in_addr); -extern int ospf_area_nssa_translator_role_set (struct ospf *, struct in_addr, - int); -extern int ospf_area_export_list_set (struct ospf *, struct ospf_area *, - const char *); -extern int ospf_area_export_list_unset (struct ospf *, struct ospf_area *); -extern int ospf_area_import_list_set (struct ospf *, struct ospf_area *, - const char *); -extern int ospf_area_import_list_unset (struct ospf *, struct ospf_area *); -extern int ospf_area_shortcut_set (struct ospf *, struct ospf_area *, int); -extern int ospf_area_shortcut_unset (struct ospf *, struct ospf_area *); -extern int ospf_timers_refresh_set (struct ospf *, int); -extern int ospf_timers_refresh_unset (struct ospf *); -extern int ospf_nbr_nbma_set (struct ospf *, struct in_addr); -extern int ospf_nbr_nbma_unset (struct ospf *, struct in_addr); -extern int ospf_nbr_nbma_priority_set (struct ospf *, struct in_addr, u_char); -extern int ospf_nbr_nbma_priority_unset (struct ospf *, struct in_addr); -extern int ospf_nbr_nbma_poll_interval_set (struct ospf *, struct in_addr, - unsigned int); -extern int ospf_nbr_nbma_poll_interval_unset (struct ospf *, struct in_addr); -extern void ospf_prefix_list_update (struct prefix_list *); -extern void ospf_init (void); -extern void ospf_if_update (struct ospf *, struct interface *); -extern void ospf_ls_upd_queue_empty (struct ospf_interface *); -extern void ospf_terminate (void); -extern void ospf_nbr_nbma_if_update (struct ospf *, struct ospf_interface *); -extern struct ospf_nbr_nbma *ospf_nbr_nbma_lookup (struct ospf *, - struct in_addr); -extern struct ospf_nbr_nbma *ospf_nbr_nbma_lookup_next (struct ospf *, - struct in_addr *, - int); -extern int ospf_oi_count (struct interface *); - -extern struct ospf_area *ospf_area_get (struct ospf *, struct in_addr); -extern void ospf_area_check_free (struct ospf *, struct in_addr); -extern struct ospf_area *ospf_area_lookup_by_area_id (struct ospf *, - struct in_addr); -extern void ospf_area_add_if (struct ospf_area *, struct ospf_interface *); -extern void ospf_area_del_if (struct ospf_area *, struct ospf_interface *); - -extern void ospf_interface_area_set (struct interface *); -extern void ospf_interface_area_unset (struct interface *); - -extern void ospf_route_map_init (void); - -extern void ospf_master_init (struct thread_master *master); +extern struct ospf *ospf_lookup(void); +extern struct ospf *ospf_lookup_instance(u_short); +extern struct ospf *ospf_get(void); +extern struct ospf *ospf_get_instance(u_short); +extern void ospf_finish(struct ospf *); +extern void ospf_router_id_update(struct ospf *ospf); +extern int ospf_network_set(struct ospf *, struct prefix_ipv4 *, struct in_addr, + int); +extern int ospf_network_unset(struct ospf *, struct prefix_ipv4 *, + struct in_addr); +extern int ospf_area_display_format_set(struct ospf *, struct ospf_area *area, + int df); +extern int ospf_area_stub_set(struct ospf *, struct in_addr); +extern int ospf_area_stub_unset(struct ospf *, struct in_addr); +extern int ospf_area_no_summary_set(struct ospf *, struct in_addr); +extern int ospf_area_no_summary_unset(struct ospf *, struct in_addr); +extern int ospf_area_nssa_set(struct ospf *, struct in_addr); +extern int ospf_area_nssa_unset(struct ospf *, struct in_addr); +extern int ospf_area_nssa_translator_role_set(struct ospf *, struct in_addr, + int); +extern int ospf_area_export_list_set(struct ospf *, struct ospf_area *, + const char *); +extern int ospf_area_export_list_unset(struct ospf *, struct ospf_area *); +extern int ospf_area_import_list_set(struct ospf *, struct ospf_area *, + const char *); +extern int ospf_area_import_list_unset(struct ospf *, struct ospf_area *); +extern int ospf_area_shortcut_set(struct ospf *, struct ospf_area *, int); +extern int ospf_area_shortcut_unset(struct ospf *, struct ospf_area *); +extern int ospf_timers_refresh_set(struct ospf *, int); +extern int ospf_timers_refresh_unset(struct ospf *); +extern int ospf_nbr_nbma_set(struct ospf *, struct in_addr); +extern int ospf_nbr_nbma_unset(struct ospf *, struct in_addr); +extern int ospf_nbr_nbma_priority_set(struct ospf *, struct in_addr, u_char); +extern int ospf_nbr_nbma_priority_unset(struct ospf *, struct in_addr); +extern int ospf_nbr_nbma_poll_interval_set(struct ospf *, struct in_addr, + unsigned int); +extern int ospf_nbr_nbma_poll_interval_unset(struct ospf *, struct in_addr); +extern void ospf_prefix_list_update(struct prefix_list *); +extern void ospf_init(void); +extern void ospf_if_update(struct ospf *, struct interface *); +extern void ospf_ls_upd_queue_empty(struct ospf_interface *); +extern void ospf_terminate(void); +extern void ospf_nbr_nbma_if_update(struct ospf *, struct ospf_interface *); +extern struct ospf_nbr_nbma *ospf_nbr_nbma_lookup(struct ospf *, + struct in_addr); +extern struct ospf_nbr_nbma *ospf_nbr_nbma_lookup_next(struct ospf *, + struct in_addr *, int); +extern int ospf_oi_count(struct interface *); + +extern struct ospf_area *ospf_area_get(struct ospf *, struct in_addr); +extern void ospf_area_check_free(struct ospf *, struct in_addr); +extern struct ospf_area *ospf_area_lookup_by_area_id(struct ospf *, + struct in_addr); +extern void ospf_area_add_if(struct ospf_area *, struct ospf_interface *); +extern void ospf_area_del_if(struct ospf_area *, struct ospf_interface *); + +extern void ospf_interface_area_set(struct interface *); +extern void ospf_interface_area_unset(struct interface *); + +extern void ospf_route_map_init(void); + +extern void ospf_master_init(struct thread_master *master); #endif /* _ZEBRA_OSPFD_H */ diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c index 37515cee5..f68c252a3 100644 --- a/pimd/pim_assert.c +++ b/pimd/pim_assert.c @@ -42,283 +42,280 @@ static void assert_action_a2(struct pim_ifchannel *ch, static void assert_action_a6(struct pim_ifchannel *ch, struct pim_assert_metric winner_metric); -void pim_ifassert_winner_set(struct pim_ifchannel *ch, - enum pim_ifassert_state new_state, - struct in_addr winner, - struct pim_assert_metric winner_metric) +void pim_ifassert_winner_set(struct pim_ifchannel *ch, + enum pim_ifassert_state new_state, + struct in_addr winner, + struct pim_assert_metric winner_metric) { - int winner_changed = (ch->ifassert_winner.s_addr != winner.s_addr); - int metric_changed = !pim_assert_metric_match(&ch->ifassert_winner_metric, - &winner_metric); - - if (PIM_DEBUG_PIM_EVENTS) { - if (ch->ifassert_state != new_state) { - zlog_debug("%s: (S,G)=%s assert state changed from %s to %s on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, - pim_ifchannel_ifassert_name(ch->ifassert_state), - pim_ifchannel_ifassert_name(new_state), - ch->interface->name); - } - - if (winner_changed) { - char was_str[INET_ADDRSTRLEN]; - char winner_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", ch->ifassert_winner, was_str, sizeof(was_str)); - pim_inet4_dump("", winner, winner_str, sizeof(winner_str)); - zlog_debug("%s: (S,G)=%s assert winner changed from %s to %s on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, - was_str, winner_str, ch->interface->name); - } - } /* PIM_DEBUG_PIM_EVENTS */ - - ch->ifassert_state = new_state; - ch->ifassert_winner = winner; - ch->ifassert_winner_metric = winner_metric; - ch->ifassert_creation = pim_time_monotonic_sec(); - - if (winner_changed || metric_changed) { - pim_upstream_update_join_desired(ch->upstream); - pim_ifchannel_update_could_assert(ch); - pim_ifchannel_update_assert_tracking_desired(ch); - } + int winner_changed = (ch->ifassert_winner.s_addr != winner.s_addr); + int metric_changed = !pim_assert_metric_match( + &ch->ifassert_winner_metric, &winner_metric); + + if (PIM_DEBUG_PIM_EVENTS) { + if (ch->ifassert_state != new_state) { + zlog_debug( + "%s: (S,G)=%s assert state changed from %s to %s on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, + pim_ifchannel_ifassert_name(ch->ifassert_state), + pim_ifchannel_ifassert_name(new_state), + ch->interface->name); + } + + if (winner_changed) { + char was_str[INET_ADDRSTRLEN]; + char winner_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", ch->ifassert_winner, was_str, + sizeof(was_str)); + pim_inet4_dump("", winner, winner_str, + sizeof(winner_str)); + zlog_debug( + "%s: (S,G)=%s assert winner changed from %s to %s on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, was_str, + winner_str, ch->interface->name); + } + } /* PIM_DEBUG_PIM_EVENTS */ + + ch->ifassert_state = new_state; + ch->ifassert_winner = winner; + ch->ifassert_winner_metric = winner_metric; + ch->ifassert_creation = pim_time_monotonic_sec(); + + if (winner_changed || metric_changed) { + pim_upstream_update_join_desired(ch->upstream); + pim_ifchannel_update_could_assert(ch); + pim_ifchannel_update_assert_tracking_desired(ch); + } } -static void on_trace(const char *label, - struct interface *ifp, struct in_addr src) +static void on_trace(const char *label, struct interface *ifp, + struct in_addr src) { - if (PIM_DEBUG_PIM_TRACE) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src, src_str, sizeof(src_str)); - zlog_debug("%s: from %s on %s", - label, src_str, ifp->name); - } + if (PIM_DEBUG_PIM_TRACE) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src, src_str, sizeof(src_str)); + zlog_debug("%s: from %s on %s", label, src_str, ifp->name); + } } static int preferred_assert(const struct pim_ifchannel *ch, const struct pim_assert_metric *recv_metric) { - return pim_assert_metric_better(recv_metric, - &ch->ifassert_winner_metric); + return pim_assert_metric_better(recv_metric, + &ch->ifassert_winner_metric); } static int acceptable_assert(const struct pim_assert_metric *my_metric, const struct pim_assert_metric *recv_metric) { - return pim_assert_metric_better(recv_metric, - my_metric); + return pim_assert_metric_better(recv_metric, my_metric); } static int inferior_assert(const struct pim_assert_metric *my_metric, const struct pim_assert_metric *recv_metric) { - return pim_assert_metric_better(my_metric, - recv_metric); + return pim_assert_metric_better(my_metric, recv_metric); } static int cancel_assert(const struct pim_assert_metric *recv_metric) { - return (recv_metric->metric_preference == PIM_ASSERT_METRIC_PREFERENCE_MAX) - && - (recv_metric->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX); + return (recv_metric->metric_preference + == PIM_ASSERT_METRIC_PREFERENCE_MAX) + && (recv_metric->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX); } -static void if_could_assert_do_a1(const char *caller, - struct pim_ifchannel *ch) +static void if_could_assert_do_a1(const char *caller, struct pim_ifchannel *ch) { - if (PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { - if (assert_action_a1(ch)) { - zlog_warn("%s: %s: (S,G)=%s assert_action_a1 failure on interface %s", - __PRETTY_FUNCTION__, caller, - ch->sg_str, ch->interface->name); - /* log warning only */ - } - } + if (PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { + if (assert_action_a1(ch)) { + zlog_warn( + "%s: %s: (S,G)=%s assert_action_a1 failure on interface %s", + __PRETTY_FUNCTION__, caller, ch->sg_str, + ch->interface->name); + /* log warning only */ + } + } } -static int dispatch_assert(struct interface *ifp, - struct in_addr source_addr, +static int dispatch_assert(struct interface *ifp, struct in_addr source_addr, struct in_addr group_addr, struct pim_assert_metric recv_metric) { - struct pim_ifchannel *ch; - struct prefix_sg sg; - - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = source_addr; - sg.grp = group_addr; - ch = pim_ifchannel_add(ifp, &sg, 0); - if (!ch) { - zlog_warn("%s: (S,G)=%s failure creating channel on interface %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), ifp->name); - return -1; - } - - switch (ch->ifassert_state) { - case PIM_IFASSERT_NOINFO: - if (recv_metric.rpt_bit_flag) { - /* RPT bit set */ - if_could_assert_do_a1(__PRETTY_FUNCTION__, ch); - } - else { - /* RPT bit clear */ - if (inferior_assert(&ch->ifassert_my_metric, &recv_metric)) { - if_could_assert_do_a1(__PRETTY_FUNCTION__, ch); - } - else if (acceptable_assert(&ch->ifassert_my_metric, &recv_metric)) { - if (PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags)) { - assert_action_a6(ch, recv_metric); - } - } - } - break; - case PIM_IFASSERT_I_AM_WINNER: - if (preferred_assert(ch, &recv_metric)) { - assert_action_a2(ch, recv_metric); - } - else { - if (inferior_assert(&ch->ifassert_my_metric, &recv_metric)) { - assert_action_a3(ch); - } - } - break; - case PIM_IFASSERT_I_AM_LOSER: - if (recv_metric.ip_address.s_addr == ch->ifassert_winner.s_addr) { - /* Assert from current winner */ - - if (cancel_assert(&recv_metric)) { - assert_action_a5(ch); - } - else { - if (inferior_assert(&ch->ifassert_my_metric, &recv_metric)) { - assert_action_a5(ch); - } - else if (acceptable_assert(&ch->ifassert_my_metric, &recv_metric)) { - if (!recv_metric.rpt_bit_flag) { - assert_action_a2(ch, recv_metric); - } - } - } - } - else if (preferred_assert(ch, &recv_metric)) { - assert_action_a2(ch, recv_metric); - } - break; - default: - { - zlog_warn("%s: (S,G)=%s invalid assert state %d on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ch->ifassert_state, ifp->name); - } - return -2; - } - - return 0; + struct pim_ifchannel *ch; + struct prefix_sg sg; + + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = source_addr; + sg.grp = group_addr; + ch = pim_ifchannel_add(ifp, &sg, 0); + if (!ch) { + zlog_warn( + "%s: (S,G)=%s failure creating channel on interface %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), ifp->name); + return -1; + } + + switch (ch->ifassert_state) { + case PIM_IFASSERT_NOINFO: + if (recv_metric.rpt_bit_flag) { + /* RPT bit set */ + if_could_assert_do_a1(__PRETTY_FUNCTION__, ch); + } else { + /* RPT bit clear */ + if (inferior_assert(&ch->ifassert_my_metric, + &recv_metric)) { + if_could_assert_do_a1(__PRETTY_FUNCTION__, ch); + } else if (acceptable_assert(&ch->ifassert_my_metric, + &recv_metric)) { + if (PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED( + ch->flags)) { + assert_action_a6(ch, recv_metric); + } + } + } + break; + case PIM_IFASSERT_I_AM_WINNER: + if (preferred_assert(ch, &recv_metric)) { + assert_action_a2(ch, recv_metric); + } else { + if (inferior_assert(&ch->ifassert_my_metric, + &recv_metric)) { + assert_action_a3(ch); + } + } + break; + case PIM_IFASSERT_I_AM_LOSER: + if (recv_metric.ip_address.s_addr + == ch->ifassert_winner.s_addr) { + /* Assert from current winner */ + + if (cancel_assert(&recv_metric)) { + assert_action_a5(ch); + } else { + if (inferior_assert(&ch->ifassert_my_metric, + &recv_metric)) { + assert_action_a5(ch); + } else if (acceptable_assert( + &ch->ifassert_my_metric, + &recv_metric)) { + if (!recv_metric.rpt_bit_flag) { + assert_action_a2(ch, + recv_metric); + } + } + } + } else if (preferred_assert(ch, &recv_metric)) { + assert_action_a2(ch, recv_metric); + } + break; + default: { + zlog_warn( + "%s: (S,G)=%s invalid assert state %d on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ch->ifassert_state, + ifp->name); + } + return -2; + } + + return 0; } -int pim_assert_recv(struct interface *ifp, - struct pim_neighbor *neigh, - struct in_addr src_addr, - uint8_t *buf, int buf_size) +int pim_assert_recv(struct interface *ifp, struct pim_neighbor *neigh, + struct in_addr src_addr, uint8_t *buf, int buf_size) { - struct prefix_sg sg; - struct prefix msg_source_addr; - struct pim_assert_metric msg_metric; - int offset; - uint8_t *curr; - int curr_size; - struct pim_interface *pim_ifp = NULL; - - on_trace(__PRETTY_FUNCTION__, ifp, src_addr); - - curr = buf; - curr_size = buf_size; - - /* - Parse assert group addr - */ - memset (&sg, 0, sizeof (struct prefix_sg)); - offset = pim_parse_addr_group (&sg, curr, curr_size); - if (offset < 1) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: pim_parse_addr_group() failure: from %s on %s", - __PRETTY_FUNCTION__, - src_str, ifp->name); - return -1; - } - curr += offset; - curr_size -= offset; - - /* - Parse assert source addr - */ - offset = pim_parse_addr_ucast (&msg_source_addr, curr, curr_size); - if (offset < 1) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s", - __PRETTY_FUNCTION__, - src_str, ifp->name); - return -2; - } - curr += offset; - curr_size -= offset; - - if (curr_size != 8) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: preference/metric size is not 8: size=%d from %s on interface %s", - __PRETTY_FUNCTION__, - curr_size, - src_str, ifp->name); - return -3; - } - - /* - Parse assert metric preference - */ - - msg_metric.metric_preference = pim_read_uint32_host(curr); - - msg_metric.rpt_bit_flag = msg_metric.metric_preference & 0x80000000; /* save highest bit */ - msg_metric.metric_preference &= ~0x80000000; /* clear highest bit */ - - curr += 4; - - /* - Parse assert route metric - */ - - msg_metric.route_metric = pim_read_uint32_host(curr); - - if (PIM_DEBUG_PIM_TRACE) { - char neigh_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, neigh_str, sizeof(neigh_str)); - pim_inet4_dump("", msg_source_addr.u.prefix4, source_str, sizeof(source_str)); - pim_inet4_dump("", sg.grp, group_str, sizeof(group_str)); - zlog_debug("%s: from %s on %s: (S,G)=(%s,%s) pref=%u metric=%u rpt_bit=%u", - __PRETTY_FUNCTION__, neigh_str, ifp->name, - source_str, group_str, - msg_metric.metric_preference, - msg_metric.route_metric, - PIM_FORCE_BOOLEAN(msg_metric.rpt_bit_flag)); - } - - msg_metric.ip_address = src_addr; - - pim_ifp = ifp->info; - zassert(pim_ifp); - ++pim_ifp->pim_ifstat_assert_recv; - - return dispatch_assert(ifp, - msg_source_addr.u.prefix4, - sg.grp, - msg_metric); + struct prefix_sg sg; + struct prefix msg_source_addr; + struct pim_assert_metric msg_metric; + int offset; + uint8_t *curr; + int curr_size; + struct pim_interface *pim_ifp = NULL; + + on_trace(__PRETTY_FUNCTION__, ifp, src_addr); + + curr = buf; + curr_size = buf_size; + + /* + Parse assert group addr + */ + memset(&sg, 0, sizeof(struct prefix_sg)); + offset = pim_parse_addr_group(&sg, curr, curr_size); + if (offset < 1) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); + zlog_warn("%s: pim_parse_addr_group() failure: from %s on %s", + __PRETTY_FUNCTION__, src_str, ifp->name); + return -1; + } + curr += offset; + curr_size -= offset; + + /* + Parse assert source addr + */ + offset = pim_parse_addr_ucast(&msg_source_addr, curr, curr_size); + if (offset < 1) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); + zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s", + __PRETTY_FUNCTION__, src_str, ifp->name); + return -2; + } + curr += offset; + curr_size -= offset; + + if (curr_size != 8) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); + zlog_warn( + "%s: preference/metric size is not 8: size=%d from %s on interface %s", + __PRETTY_FUNCTION__, curr_size, src_str, ifp->name); + return -3; + } + + /* + Parse assert metric preference + */ + + msg_metric.metric_preference = pim_read_uint32_host(curr); + + msg_metric.rpt_bit_flag = msg_metric.metric_preference + & 0x80000000; /* save highest bit */ + msg_metric.metric_preference &= ~0x80000000; /* clear highest bit */ + + curr += 4; + + /* + Parse assert route metric + */ + + msg_metric.route_metric = pim_read_uint32_host(curr); + + if (PIM_DEBUG_PIM_TRACE) { + char neigh_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, neigh_str, + sizeof(neigh_str)); + pim_inet4_dump("", msg_source_addr.u.prefix4, source_str, + sizeof(source_str)); + pim_inet4_dump("", sg.grp, group_str, sizeof(group_str)); + zlog_debug( + "%s: from %s on %s: (S,G)=(%s,%s) pref=%u metric=%u rpt_bit=%u", + __PRETTY_FUNCTION__, neigh_str, ifp->name, source_str, + group_str, msg_metric.metric_preference, + msg_metric.route_metric, + PIM_FORCE_BOOLEAN(msg_metric.rpt_bit_flag)); + } + + msg_metric.ip_address = src_addr; + + pim_ifp = ifp->info; + zassert(pim_ifp); + ++pim_ifp->pim_ifstat_assert_recv; + + return dispatch_assert(ifp, msg_source_addr.u.prefix4, sg.grp, + msg_metric); } /* @@ -335,167 +332,164 @@ int pim_assert_recv(struct interface *ifp, int pim_assert_metric_better(const struct pim_assert_metric *m1, const struct pim_assert_metric *m2) { - if (m1->rpt_bit_flag < m2->rpt_bit_flag) - return 1; - if (m1->rpt_bit_flag > m2->rpt_bit_flag) - return 0; - - if (m1->metric_preference < m2->metric_preference) - return 1; - if (m1->metric_preference > m2->metric_preference) - return 0; - - if (m1->route_metric < m2->route_metric) - return 1; - if (m1->route_metric > m2->route_metric) - return 0; - - return ntohl(m1->ip_address.s_addr) > ntohl(m2->ip_address.s_addr); + if (m1->rpt_bit_flag < m2->rpt_bit_flag) + return 1; + if (m1->rpt_bit_flag > m2->rpt_bit_flag) + return 0; + + if (m1->metric_preference < m2->metric_preference) + return 1; + if (m1->metric_preference > m2->metric_preference) + return 0; + + if (m1->route_metric < m2->route_metric) + return 1; + if (m1->route_metric > m2->route_metric) + return 0; + + return ntohl(m1->ip_address.s_addr) > ntohl(m2->ip_address.s_addr); } int pim_assert_metric_match(const struct pim_assert_metric *m1, const struct pim_assert_metric *m2) { - if (m1->rpt_bit_flag != m2->rpt_bit_flag) - return 0; - if (m1->metric_preference != m2->metric_preference) - return 0; - if (m1->route_metric != m2->route_metric) - return 0; - - return m1->ip_address.s_addr == m2->ip_address.s_addr; + if (m1->rpt_bit_flag != m2->rpt_bit_flag) + return 0; + if (m1->metric_preference != m2->metric_preference) + return 0; + if (m1->route_metric != m2->route_metric) + return 0; + + return m1->ip_address.s_addr == m2->ip_address.s_addr; } -int pim_assert_build_msg(uint8_t *pim_msg, int buf_size, - struct interface *ifp, - struct in_addr group_addr, - struct in_addr source_addr, - uint32_t metric_preference, - uint32_t route_metric, +int pim_assert_build_msg(uint8_t *pim_msg, int buf_size, struct interface *ifp, + struct in_addr group_addr, struct in_addr source_addr, + uint32_t metric_preference, uint32_t route_metric, uint32_t rpt_bit_flag) { - uint8_t *buf_pastend = pim_msg + buf_size; - uint8_t *pim_msg_curr; - int pim_msg_size; - int remain; - - pim_msg_curr = pim_msg + PIM_MSG_HEADER_LEN; /* skip room for pim header */ - - /* Encode group */ - remain = buf_pastend - pim_msg_curr; - pim_msg_curr = pim_msg_addr_encode_ipv4_group(pim_msg_curr, group_addr); - if (!pim_msg_curr) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - zlog_warn("%s: failure encoding group address %s: space left=%d", - __PRETTY_FUNCTION__, group_str, remain); - return -1; - } - - /* Encode source */ - remain = buf_pastend - pim_msg_curr; - pim_msg_curr = pim_msg_addr_encode_ipv4_ucast(pim_msg_curr, source_addr); - if (!pim_msg_curr) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: failure encoding source address %s: space left=%d", - __PRETTY_FUNCTION__, source_str, remain); - return -2; - } - - /* Metric preference */ - pim_write_uint32(pim_msg_curr, rpt_bit_flag ? - metric_preference | 0x80000000 : - metric_preference); - pim_msg_curr += 4; - - /* Route metric */ - pim_write_uint32(pim_msg_curr, route_metric); - pim_msg_curr += 4; - - /* - Add PIM header - */ - pim_msg_size = pim_msg_curr - pim_msg; - pim_msg_build_header(pim_msg, pim_msg_size, - PIM_MSG_TYPE_ASSERT); - - return pim_msg_size; + uint8_t *buf_pastend = pim_msg + buf_size; + uint8_t *pim_msg_curr; + int pim_msg_size; + int remain; + + pim_msg_curr = + pim_msg + PIM_MSG_HEADER_LEN; /* skip room for pim header */ + + /* Encode group */ + remain = buf_pastend - pim_msg_curr; + pim_msg_curr = pim_msg_addr_encode_ipv4_group(pim_msg_curr, group_addr); + if (!pim_msg_curr) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group_addr, group_str, + sizeof(group_str)); + zlog_warn( + "%s: failure encoding group address %s: space left=%d", + __PRETTY_FUNCTION__, group_str, remain); + return -1; + } + + /* Encode source */ + remain = buf_pastend - pim_msg_curr; + pim_msg_curr = + pim_msg_addr_encode_ipv4_ucast(pim_msg_curr, source_addr); + if (!pim_msg_curr) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: failure encoding source address %s: space left=%d", + __PRETTY_FUNCTION__, source_str, remain); + return -2; + } + + /* Metric preference */ + pim_write_uint32(pim_msg_curr, + rpt_bit_flag ? metric_preference | 0x80000000 + : metric_preference); + pim_msg_curr += 4; + + /* Route metric */ + pim_write_uint32(pim_msg_curr, route_metric); + pim_msg_curr += 4; + + /* + Add PIM header + */ + pim_msg_size = pim_msg_curr - pim_msg; + pim_msg_build_header(pim_msg, pim_msg_size, PIM_MSG_TYPE_ASSERT); + + return pim_msg_size; } static int pim_assert_do(struct pim_ifchannel *ch, struct pim_assert_metric metric) { - struct interface *ifp; - struct pim_interface *pim_ifp; - uint8_t pim_msg[1000]; - int pim_msg_size; - - ifp = ch->interface; - if (!ifp) - { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug("%s: channel%s has no associated interface!", - __PRETTY_FUNCTION__, ch->sg_str); - return -1; - } - pim_ifp = ifp->info; - if (!pim_ifp) { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug("%s: channel %s pim not enabled on interface: %s", - __PRETTY_FUNCTION__, ch->sg_str, ifp->name); - return -1; - } - - pim_msg_size = pim_assert_build_msg(pim_msg, sizeof(pim_msg), ifp, - ch->sg.grp, ch->sg.src, - metric.metric_preference, - metric.route_metric, - metric.rpt_bit_flag); - if (pim_msg_size < 1) { - zlog_warn("%s: failure building PIM assert message: msg_size=%d", - __PRETTY_FUNCTION__, pim_msg_size); - return -2; - } - - /* - RFC 4601: 4.3.1. Sending Hello Messages - - Thus, if a router needs to send a Join/Prune or Assert message on - an interface on which it has not yet sent a Hello message with the - currently configured IP address, then it MUST immediately send the - relevant Hello message without waiting for the Hello Timer to - expire, followed by the Join/Prune or Assert message. - */ - pim_hello_require(ifp); - - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: to %s: (S,G)=%s pref=%u metric=%u rpt_bit=%u", - __PRETTY_FUNCTION__, - ifp->name, ch->sg_str, - metric.metric_preference, - metric.route_metric, - PIM_FORCE_BOOLEAN(metric.rpt_bit_flag)); - } - ++pim_ifp->pim_ifstat_assert_send; - - if (pim_msg_send(pim_ifp->pim_sock_fd, - pim_ifp->primary_address, - qpim_all_pim_routers_addr, - pim_msg, - pim_msg_size, - ifp->name)) { - zlog_warn("%s: could not send PIM message on interface %s", - __PRETTY_FUNCTION__, ifp->name); - return -3; - } - - return 0; + struct interface *ifp; + struct pim_interface *pim_ifp; + uint8_t pim_msg[1000]; + int pim_msg_size; + + ifp = ch->interface; + if (!ifp) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: channel%s has no associated interface!", + __PRETTY_FUNCTION__, ch->sg_str); + return -1; + } + pim_ifp = ifp->info; + if (!pim_ifp) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug( + "%s: channel %s pim not enabled on interface: %s", + __PRETTY_FUNCTION__, ch->sg_str, ifp->name); + return -1; + } + + pim_msg_size = + pim_assert_build_msg(pim_msg, sizeof(pim_msg), ifp, ch->sg.grp, + ch->sg.src, metric.metric_preference, + metric.route_metric, metric.rpt_bit_flag); + if (pim_msg_size < 1) { + zlog_warn( + "%s: failure building PIM assert message: msg_size=%d", + __PRETTY_FUNCTION__, pim_msg_size); + return -2; + } + + /* + RFC 4601: 4.3.1. Sending Hello Messages + + Thus, if a router needs to send a Join/Prune or Assert message on + an interface on which it has not yet sent a Hello message with the + currently configured IP address, then it MUST immediately send the + relevant Hello message without waiting for the Hello Timer to + expire, followed by the Join/Prune or Assert message. + */ + pim_hello_require(ifp); + + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: to %s: (S,G)=%s pref=%u metric=%u rpt_bit=%u", + __PRETTY_FUNCTION__, ifp->name, ch->sg_str, + metric.metric_preference, metric.route_metric, + PIM_FORCE_BOOLEAN(metric.rpt_bit_flag)); + } + ++pim_ifp->pim_ifstat_assert_send; + + if (pim_msg_send(pim_ifp->pim_sock_fd, pim_ifp->primary_address, + qpim_all_pim_routers_addr, pim_msg, pim_msg_size, + ifp->name)) { + zlog_warn("%s: could not send PIM message on interface %s", + __PRETTY_FUNCTION__, ifp->name); + return -3; + } + + return 0; } int pim_assert_send(struct pim_ifchannel *ch) { - return pim_assert_do(ch, ch->ifassert_my_metric); + return pim_assert_do(ch, ch->ifassert_my_metric); } /* @@ -506,82 +500,82 @@ int pim_assert_send(struct pim_ifchannel *ch) */ static int pim_assert_cancel(struct pim_ifchannel *ch) { - struct pim_assert_metric metric; + struct pim_assert_metric metric; - metric.rpt_bit_flag = 0; - metric.metric_preference = PIM_ASSERT_METRIC_PREFERENCE_MAX; - metric.route_metric = PIM_ASSERT_ROUTE_METRIC_MAX; - metric.ip_address = ch->sg.src; + metric.rpt_bit_flag = 0; + metric.metric_preference = PIM_ASSERT_METRIC_PREFERENCE_MAX; + metric.route_metric = PIM_ASSERT_ROUTE_METRIC_MAX; + metric.ip_address = ch->sg.src; - return pim_assert_do(ch, metric); + return pim_assert_do(ch, metric); } static int on_assert_timer(struct thread *t) { - struct pim_ifchannel *ch; - struct interface *ifp; - - ch = THREAD_ARG(t); - - ifp = ch->interface; - - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: (S,G)=%s timer expired on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ifp->name); - } - - ch->t_ifassert_timer = NULL; - - switch (ch->ifassert_state) { - case PIM_IFASSERT_I_AM_WINNER: - assert_action_a3(ch); - break; - case PIM_IFASSERT_I_AM_LOSER: - assert_action_a5(ch); - break; - default: - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_warn("%s: (S,G)=%s invalid assert state %d on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ch->ifassert_state, ifp->name); - } - } - - return 0; + struct pim_ifchannel *ch; + struct interface *ifp; + + ch = THREAD_ARG(t); + + ifp = ch->interface; + + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: (S,G)=%s timer expired on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ifp->name); + } + + ch->t_ifassert_timer = NULL; + + switch (ch->ifassert_state) { + case PIM_IFASSERT_I_AM_WINNER: + assert_action_a3(ch); + break; + case PIM_IFASSERT_I_AM_LOSER: + assert_action_a5(ch); + break; + default: { + if (PIM_DEBUG_PIM_EVENTS) + zlog_warn( + "%s: (S,G)=%s invalid assert state %d on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, + ch->ifassert_state, ifp->name); + } + } + + return 0; } static void assert_timer_off(struct pim_ifchannel *ch) { - if (PIM_DEBUG_PIM_TRACE) { - if (ch->t_ifassert_timer) { - zlog_debug("%s: (S,G)=%s cancelling timer on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ch->interface->name); - } - } - THREAD_OFF(ch->t_ifassert_timer); + if (PIM_DEBUG_PIM_TRACE) { + if (ch->t_ifassert_timer) { + zlog_debug( + "%s: (S,G)=%s cancelling timer on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, + ch->interface->name); + } + } + THREAD_OFF(ch->t_ifassert_timer); } -static void pim_assert_timer_set(struct pim_ifchannel *ch, - int interval) +static void pim_assert_timer_set(struct pim_ifchannel *ch, int interval) { - assert_timer_off(ch); + assert_timer_off(ch); - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: (S,G)=%s starting %u sec timer on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, interval, ch->interface->name); - } + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: (S,G)=%s starting %u sec timer on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, interval, + ch->interface->name); + } - thread_add_timer(master, on_assert_timer, ch, interval, - &ch->t_ifassert_timer); + thread_add_timer(master, on_assert_timer, ch, interval, + &ch->t_ifassert_timer); } static void pim_assert_timer_reset(struct pim_ifchannel *ch) { - pim_assert_timer_set(ch, PIM_ASSERT_TIME - PIM_ASSERT_OVERRIDE_INTERVAL); + pim_assert_timer_set(ch, + PIM_ASSERT_TIME - PIM_ASSERT_OVERRIDE_INTERVAL); } /* @@ -596,38 +590,37 @@ static void pim_assert_timer_reset(struct pim_ifchannel *ch) */ int assert_action_a1(struct pim_ifchannel *ch) { - struct interface *ifp = ch->interface; - struct pim_interface *pim_ifp; - - pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: (S,G)=%s multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ifp->name); - return -1; /* must return since pim_ifp is used below */ - } - - /* Switch to I_AM_WINNER before performing action_a3 below */ - pim_ifassert_winner_set(ch, PIM_IFASSERT_I_AM_WINNER, - pim_ifp->primary_address, - pim_macro_spt_assert_metric(&ch->upstream->rpf, - pim_ifp->primary_address)); - - if (assert_action_a3(ch)) { - zlog_warn("%s: (S,G)=%s assert_action_a3 failure on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ifp->name); - /* warning only */ - } - - if (ch->ifassert_state != PIM_IFASSERT_I_AM_WINNER) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_warn("%s: channel%s not in expected PIM_IFASSERT_I_AM_WINNER state", - __PRETTY_FUNCTION__, ch->sg_str); - } - - return 0; + struct interface *ifp = ch->interface; + struct pim_interface *pim_ifp; + + pim_ifp = ifp->info; + if (!pim_ifp) { + zlog_warn("%s: (S,G)=%s multicast not enabled on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ifp->name); + return -1; /* must return since pim_ifp is used below */ + } + + /* Switch to I_AM_WINNER before performing action_a3 below */ + pim_ifassert_winner_set( + ch, PIM_IFASSERT_I_AM_WINNER, pim_ifp->primary_address, + pim_macro_spt_assert_metric(&ch->upstream->rpf, + pim_ifp->primary_address)); + + if (assert_action_a3(ch)) { + zlog_warn( + "%s: (S,G)=%s assert_action_a3 failure on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ifp->name); + /* warning only */ + } + + if (ch->ifassert_state != PIM_IFASSERT_I_AM_WINNER) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_warn( + "%s: channel%s not in expected PIM_IFASSERT_I_AM_WINNER state", + __PRETTY_FUNCTION__, ch->sg_str); + } + + return 0; } /* @@ -636,24 +629,23 @@ int assert_action_a1(struct pim_ifchannel *ch) (S,G) Assert State machine Actions A2: Store new assert winner as AssertWinner(S,G,I) and assert - winner metric as AssertWinnerMetric(S,G,I). - Set Assert Timer to Assert_Time. + winner metric as AssertWinnerMetric(S,G,I). + Set Assert Timer to Assert_Time. */ static void assert_action_a2(struct pim_ifchannel *ch, struct pim_assert_metric winner_metric) { - pim_ifassert_winner_set(ch, PIM_IFASSERT_I_AM_LOSER, - winner_metric.ip_address, - winner_metric); - - pim_assert_timer_set(ch, PIM_ASSERT_TIME); - - if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_warn("%s: channel%s not in expected PIM_IFASSERT_I_AM_LOSER state", - __PRETTY_FUNCTION__, ch->sg_str); - } + pim_ifassert_winner_set(ch, PIM_IFASSERT_I_AM_LOSER, + winner_metric.ip_address, winner_metric); + + pim_assert_timer_set(ch, PIM_ASSERT_TIME); + + if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_warn( + "%s: channel%s not in expected PIM_IFASSERT_I_AM_LOSER state", + __PRETTY_FUNCTION__, ch->sg_str); + } } /* @@ -666,24 +658,23 @@ static void assert_action_a2(struct pim_ifchannel *ch, */ static int assert_action_a3(struct pim_ifchannel *ch) { - if (ch->ifassert_state != PIM_IFASSERT_I_AM_WINNER) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_warn("%s: channel%s expected to be in PIM_IFASSERT_I_AM_WINNER state", - __PRETTY_FUNCTION__, ch->sg_str); - return -1; - } - - pim_assert_timer_reset(ch); - - if (pim_assert_send(ch)) { - zlog_warn("%s: (S,G)=%s failure sending assert on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ch->interface->name); - return -1; - } - - return 0; + if (ch->ifassert_state != PIM_IFASSERT_I_AM_WINNER) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_warn( + "%s: channel%s expected to be in PIM_IFASSERT_I_AM_WINNER state", + __PRETTY_FUNCTION__, ch->sg_str); + return -1; + } + + pim_assert_timer_reset(ch); + + if (pim_assert_send(ch)) { + zlog_warn("%s: (S,G)=%s failure sending assert on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name); + return -1; + } + + return 0; } /* @@ -692,27 +683,26 @@ static int assert_action_a3(struct pim_ifchannel *ch) (S,G) Assert State machine Actions A4: Send AssertCancel(S,G). - Delete assert info (AssertWinner(S,G,I) and - AssertWinnerMetric(S,G,I) will then return their default - values). + Delete assert info (AssertWinner(S,G,I) and + AssertWinnerMetric(S,G,I) will then return their default + values). */ void assert_action_a4(struct pim_ifchannel *ch) { - if (pim_assert_cancel(ch)) { - zlog_warn("%s: failure sending AssertCancel%s on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ch->interface->name); - /* log warning only */ - } - - assert_action_a5(ch); - - if (ch->ifassert_state != PIM_IFASSERT_NOINFO) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_warn("%s: channel%s not in PIM_IFASSERT_NOINFO state as expected", - __PRETTY_FUNCTION__, ch->sg_str); - } + if (pim_assert_cancel(ch)) { + zlog_warn("%s: failure sending AssertCancel%s on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name); + /* log warning only */ + } + + assert_action_a5(ch); + + if (ch->ifassert_state != PIM_IFASSERT_NOINFO) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_warn( + "%s: channel%s not in PIM_IFASSERT_NOINFO state as expected", + __PRETTY_FUNCTION__, ch->sg_str); + } } /* @@ -725,13 +715,13 @@ void assert_action_a4(struct pim_ifchannel *ch) */ void assert_action_a5(struct pim_ifchannel *ch) { - reset_ifassert_state(ch); - if (ch->ifassert_state != PIM_IFASSERT_NOINFO) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_warn("%s: channel%s not in PIM_IFSSERT_NOINFO state as expected", - __PRETTY_FUNCTION__, ch->sg_str); - } + reset_ifassert_state(ch); + if (ch->ifassert_state != PIM_IFASSERT_NOINFO) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_warn( + "%s: channel%s not in PIM_IFSSERT_NOINFO state as expected", + __PRETTY_FUNCTION__, ch->sg_str); + } } /* @@ -740,29 +730,28 @@ void assert_action_a5(struct pim_ifchannel *ch) (S,G) Assert State machine Actions A6: Store new assert winner as AssertWinner(S,G,I) and assert - winner metric as AssertWinnerMetric(S,G,I). - Set Assert Timer to Assert_Time. - If (I is RPF_interface(S)) AND (UpstreamJPState(S,G) == true) - set SPTbit(S,G) to TRUE. + winner metric as AssertWinnerMetric(S,G,I). + Set Assert Timer to Assert_Time. + If (I is RPF_interface(S)) AND (UpstreamJPState(S,G) == true) + set SPTbit(S,G) to TRUE. */ static void assert_action_a6(struct pim_ifchannel *ch, struct pim_assert_metric winner_metric) { - assert_action_a2(ch, winner_metric); - - /* - If (I is RPF_interface(S)) AND (UpstreamJPState(S,G) == true) set - SPTbit(S,G) to TRUE. - */ - if (ch->upstream->rpf.source_nexthop.interface == ch->interface) - if (ch->upstream->join_state == PIM_UPSTREAM_JOINED) - ch->upstream->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; - - if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) - { - if(PIM_DEBUG_PIM_EVENTS) - zlog_warn("%s: channel%s not in PIM_IFASSERT_I_AM_LOSER state as expected", - __PRETTY_FUNCTION__, ch->sg_str); - } + assert_action_a2(ch, winner_metric); + + /* + If (I is RPF_interface(S)) AND (UpstreamJPState(S,G) == true) set + SPTbit(S,G) to TRUE. + */ + if (ch->upstream->rpf.source_nexthop.interface == ch->interface) + if (ch->upstream->join_state == PIM_UPSTREAM_JOINED) + ch->upstream->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + + if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_warn( + "%s: channel%s not in PIM_IFASSERT_I_AM_LOSER state as expected", + __PRETTY_FUNCTION__, ch->sg_str); + } } - diff --git a/pimd/pim_assert.h b/pimd/pim_assert.h index b2fc11523..63fda3fe3 100644 --- a/pimd/pim_assert.h +++ b/pimd/pim_assert.h @@ -40,27 +40,22 @@ #define PIM_ASSERT_METRIC_PREFERENCE_MAX (0xFFFFFFFF) #define PIM_ASSERT_ROUTE_METRIC_MAX (0xFFFFFFFF) -void pim_ifassert_winner_set(struct pim_ifchannel *ch, - enum pim_ifassert_state new_state, - struct in_addr winner, - struct pim_assert_metric winner_metric); +void pim_ifassert_winner_set(struct pim_ifchannel *ch, + enum pim_ifassert_state new_state, + struct in_addr winner, + struct pim_assert_metric winner_metric); -int pim_assert_recv(struct interface *ifp, - struct pim_neighbor *neigh, - struct in_addr src_addr, - uint8_t *buf, int buf_size); +int pim_assert_recv(struct interface *ifp, struct pim_neighbor *neigh, + struct in_addr src_addr, uint8_t *buf, int buf_size); int pim_assert_metric_better(const struct pim_assert_metric *m1, const struct pim_assert_metric *m2); int pim_assert_metric_match(const struct pim_assert_metric *m1, const struct pim_assert_metric *m2); -int pim_assert_build_msg(uint8_t *pim_msg, int buf_size, - struct interface *ifp, - struct in_addr group_addr, - struct in_addr source_addr, - uint32_t metric_preference, - uint32_t route_metric, +int pim_assert_build_msg(uint8_t *pim_msg, int buf_size, struct interface *ifp, + struct in_addr group_addr, struct in_addr source_addr, + uint32_t metric_preference, uint32_t route_metric, uint32_t rpt_bit_flag); int pim_assert_send(struct pim_ifchannel *ch); diff --git a/pimd/pim_bfd.c b/pimd/pim_bfd.c index af8a8e2c5..e4c50a18b 100644 --- a/pimd/pim_bfd.c +++ b/pimd/pim_bfd.c @@ -38,101 +38,94 @@ /* * pim_bfd_write_config - Write the interface BFD configuration. */ -void -pim_bfd_write_config (struct vty *vty, struct interface *ifp) +void pim_bfd_write_config(struct vty *vty, struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; - struct bfd_info *bfd_info = NULL; - - if (!pim_ifp) - return; - - bfd_info = (struct bfd_info *) pim_ifp->bfd_info; - if (!bfd_info) - return; - - if (CHECK_FLAG (bfd_info->flags, BFD_FLAG_PARAM_CFG)) - vty_out (vty, " ip pim bfd %d %d %d\n", - bfd_info->detect_mult, bfd_info->required_min_rx, - bfd_info->desired_min_tx); - else - vty_out (vty, " ip pim bfd\n"); + struct pim_interface *pim_ifp = ifp->info; + struct bfd_info *bfd_info = NULL; + + if (!pim_ifp) + return; + + bfd_info = (struct bfd_info *)pim_ifp->bfd_info; + if (!bfd_info) + return; + + if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) + vty_out(vty, " ip pim bfd %d %d %d\n", bfd_info->detect_mult, + bfd_info->required_min_rx, bfd_info->desired_min_tx); + else + vty_out(vty, " ip pim bfd\n"); } /* * pim_bfd_show_info - Show BFD info structure */ -void -pim_bfd_show_info (struct vty *vty, void *bfd_info, json_object * json_obj, - u_char use_json, int param_only) +void pim_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj, + u_char use_json, int param_only) { - if (param_only) - bfd_show_param (vty, (struct bfd_info *) bfd_info, 1, 0, use_json, - json_obj); - else - bfd_show_info (vty, (struct bfd_info *) bfd_info, 0, 1, use_json, - json_obj); + if (param_only) + bfd_show_param(vty, (struct bfd_info *)bfd_info, 1, 0, use_json, + json_obj); + else + bfd_show_info(vty, (struct bfd_info *)bfd_info, 0, 1, use_json, + json_obj); } /* * pim_bfd_info_nbr_create - Create/update BFD information for a neighbor. */ -void -pim_bfd_info_nbr_create (struct pim_interface *pim_ifp, - struct pim_neighbor *neigh) +void pim_bfd_info_nbr_create(struct pim_interface *pim_ifp, + struct pim_neighbor *neigh) { - struct bfd_info *nbr_bfd_info = NULL; + struct bfd_info *nbr_bfd_info = NULL; - /* Check if Pim Interface BFD is enabled */ - if (!pim_ifp || !pim_ifp->bfd_info) - return; + /* Check if Pim Interface BFD is enabled */ + if (!pim_ifp || !pim_ifp->bfd_info) + return; - if (!neigh->bfd_info) - neigh->bfd_info = bfd_info_create (); + if (!neigh->bfd_info) + neigh->bfd_info = bfd_info_create(); - if (!neigh->bfd_info) - return; + if (!neigh->bfd_info) + return; - nbr_bfd_info = (struct bfd_info *) neigh->bfd_info; - nbr_bfd_info->detect_mult = pim_ifp->bfd_info->detect_mult; - nbr_bfd_info->desired_min_tx = pim_ifp->bfd_info->desired_min_tx; - nbr_bfd_info->required_min_rx = pim_ifp->bfd_info->required_min_rx; + nbr_bfd_info = (struct bfd_info *)neigh->bfd_info; + nbr_bfd_info->detect_mult = pim_ifp->bfd_info->detect_mult; + nbr_bfd_info->desired_min_tx = pim_ifp->bfd_info->desired_min_tx; + nbr_bfd_info->required_min_rx = pim_ifp->bfd_info->required_min_rx; } /* * pim_bfd_info_free - Free BFD info structure */ -void -pim_bfd_info_free (void **bfd_info) +void pim_bfd_info_free(void **bfd_info) { - bfd_info_free ((struct bfd_info **) bfd_info); + bfd_info_free((struct bfd_info **)bfd_info); } -static void -pim_bfd_reg_dereg_nbr (struct pim_neighbor *nbr, int command) +static void pim_bfd_reg_dereg_nbr(struct pim_neighbor *nbr, int command) { - struct pim_interface *pim_ifp = NULL; - struct bfd_info *bfd_info = NULL; - struct zclient *zclient = NULL; - - zclient = pim_zebra_zclient_get (); - - if (!nbr) - return; - pim_ifp = nbr->interface->info; - bfd_info = (struct bfd_info *) pim_ifp->bfd_info; - if (!bfd_info) - return; - if (PIM_DEBUG_PIM_TRACE) - { - char str[INET_ADDRSTRLEN]; - pim_inet4_dump ("", nbr->source_addr, str, sizeof (str)); - zlog_debug ("%s Nbr %s %s with BFD", __PRETTY_FUNCTION__, str, - bfd_get_command_dbg_str (command)); - } - bfd_peer_sendmsg (zclient, bfd_info, AF_INET, - &nbr->source_addr, NULL, nbr->interface->name, - 0, 0, command, 0, VRF_DEFAULT); + struct pim_interface *pim_ifp = NULL; + struct bfd_info *bfd_info = NULL; + struct zclient *zclient = NULL; + + zclient = pim_zebra_zclient_get(); + + if (!nbr) + return; + pim_ifp = nbr->interface->info; + bfd_info = (struct bfd_info *)pim_ifp->bfd_info; + if (!bfd_info) + return; + if (PIM_DEBUG_PIM_TRACE) { + char str[INET_ADDRSTRLEN]; + pim_inet4_dump("", nbr->source_addr, str, + sizeof(str)); + zlog_debug("%s Nbr %s %s with BFD", __PRETTY_FUNCTION__, str, + bfd_get_command_dbg_str(command)); + } + bfd_peer_sendmsg(zclient, bfd_info, AF_INET, &nbr->source_addr, NULL, + nbr->interface->name, 0, 0, command, 0, VRF_DEFAULT); } /* @@ -141,75 +134,68 @@ pim_bfd_reg_dereg_nbr (struct pim_neighbor *nbr, int command) * zebra for starting/stopping the monitoring of * the neighbor rechahability. */ -int -pim_bfd_reg_dereg_all_nbr (struct interface *ifp, int command) +int pim_bfd_reg_dereg_all_nbr(struct interface *ifp, int command) { - struct pim_interface *pim_ifp = NULL; - struct listnode *node = NULL; - struct pim_neighbor *neigh = NULL; - - pim_ifp = ifp->info; - if (!pim_ifp) - return -1; - if (!pim_ifp->bfd_info) - return -1; - - for (ALL_LIST_ELEMENTS_RO (pim_ifp->pim_neighbor_list, node, neigh)) - { - if (command != ZEBRA_BFD_DEST_DEREGISTER) - pim_bfd_info_nbr_create (pim_ifp, neigh); - else - bfd_info_free ((struct bfd_info **) &neigh->bfd_info); - - pim_bfd_reg_dereg_nbr (neigh, command); - } - - return 0; + struct pim_interface *pim_ifp = NULL; + struct listnode *node = NULL; + struct pim_neighbor *neigh = NULL; + + pim_ifp = ifp->info; + if (!pim_ifp) + return -1; + if (!pim_ifp->bfd_info) + return -1; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { + if (command != ZEBRA_BFD_DEST_DEREGISTER) + pim_bfd_info_nbr_create(pim_ifp, neigh); + else + bfd_info_free((struct bfd_info **)&neigh->bfd_info); + + pim_bfd_reg_dereg_nbr(neigh, command); + } + + return 0; } /* * pim_bfd_trigger_event - Neighbor is registered/deregistered with BFD when * neighbor state is changed to/from 2way. */ -void -pim_bfd_trigger_event (struct pim_interface *pim_ifp, struct pim_neighbor *nbr, uint8_t nbr_up) +void pim_bfd_trigger_event(struct pim_interface *pim_ifp, + struct pim_neighbor *nbr, uint8_t nbr_up) { - if (nbr_up) - { - pim_bfd_info_nbr_create (pim_ifp, nbr); - pim_bfd_reg_dereg_nbr (nbr, ZEBRA_BFD_DEST_REGISTER); - } - else - { - pim_bfd_info_free ((void *)&nbr->bfd_info); - pim_bfd_reg_dereg_nbr (nbr, ZEBRA_BFD_DEST_DEREGISTER); - } + if (nbr_up) { + pim_bfd_info_nbr_create(pim_ifp, nbr); + pim_bfd_reg_dereg_nbr(nbr, ZEBRA_BFD_DEST_REGISTER); + } else { + pim_bfd_info_free((void *)&nbr->bfd_info); + pim_bfd_reg_dereg_nbr(nbr, ZEBRA_BFD_DEST_DEREGISTER); + } } /* * pim_bfd_if_param_set - Set the configured BFD paramter values for * interface. */ -void -pim_bfd_if_param_set (struct interface *ifp, u_int32_t min_rx, - u_int32_t min_tx, u_int8_t detect_mult, int defaults) +void pim_bfd_if_param_set(struct interface *ifp, u_int32_t min_rx, + u_int32_t min_tx, u_int8_t detect_mult, int defaults) { - struct pim_interface *pim_ifp = ifp->info; - int command = 0; - - if (!pim_ifp) - return; - bfd_set_param ((struct bfd_info **) &(pim_ifp->bfd_info), min_rx, min_tx, - detect_mult, defaults, &command); - - if (pim_ifp->bfd_info) - { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s: interface %s has bfd_info", __PRETTY_FUNCTION__, - ifp->name); - } - if (command) - pim_bfd_reg_dereg_all_nbr (ifp, command); + struct pim_interface *pim_ifp = ifp->info; + int command = 0; + + if (!pim_ifp) + return; + bfd_set_param((struct bfd_info **)&(pim_ifp->bfd_info), min_rx, min_tx, + detect_mult, defaults, &command); + + if (pim_ifp->bfd_info) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: interface %s has bfd_info", + __PRETTY_FUNCTION__, ifp->name); + } + if (command) + pim_bfd_reg_dereg_all_nbr(ifp, command); } @@ -219,145 +205,133 @@ pim_bfd_if_param_set (struct interface *ifp, u_int32_t min_rx, * connectivity if the BFD status changed to * down. */ -static int -pim_bfd_interface_dest_update (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int pim_bfd_interface_dest_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp = NULL; - struct pim_interface *pim_ifp = NULL; - struct prefix p; - int status; - char msg[100]; - int old_status; - struct bfd_info *bfd_info = NULL; - struct timeval tv; - struct listnode *neigh_node = NULL; - struct listnode *neigh_nextnode = NULL; - struct pim_neighbor *neigh = NULL; - - ifp = bfd_get_peer_info (zclient->ibuf, &p, NULL, &status, vrf_id); - - if ((ifp == NULL) || (p.family != AF_INET)) - return 0; - - pim_ifp = ifp->info; - if (!pim_ifp) - return 0; - - if (!pim_ifp->bfd_info) - { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s: pim interface %s BFD is disabled ", __PRETTY_FUNCTION__, - ifp->name); - return 0; - } - - if (PIM_DEBUG_PIM_TRACE) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str (&p, buf, sizeof (buf)); - zlog_debug ("%s: interface %s bfd destination %s %s", - __PRETTY_FUNCTION__, ifp->name, buf, - bfd_get_status_str (status)); - } - - for (ALL_LIST_ELEMENTS (pim_ifp->pim_neighbor_list, neigh_node, - neigh_nextnode, neigh)) - { - /* Check neigh address matches with BFD address */ - if (neigh->source_addr.s_addr != p.u.prefix4.s_addr) - continue; - - bfd_info = (struct bfd_info *) neigh->bfd_info; - if (bfd_info->status == status) - { - if (PIM_DEBUG_PIM_TRACE) - { - char str[INET_ADDRSTRLEN]; - pim_inet4_dump ("", neigh->source_addr, str, - sizeof (str)); - zlog_debug ("%s: bfd status is same for nbr %s", - __PRETTY_FUNCTION__, str); - } - continue; - } - old_status = bfd_info->status; - bfd_info->status = status; - monotime(&tv); - bfd_info->last_update = tv.tv_sec; - - if (PIM_DEBUG_PIM_TRACE) - { - zlog_debug ("%s: status %s old_status %s", __PRETTY_FUNCTION__, - bfd_get_status_str (status), - bfd_get_status_str (old_status)); - } - if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP)) - { - snprintf (msg, sizeof (msg), "BFD Session Expired"); - pim_neighbor_delete (ifp, neigh, msg); - } - } - return 0; + struct interface *ifp = NULL; + struct pim_interface *pim_ifp = NULL; + struct prefix p; + int status; + char msg[100]; + int old_status; + struct bfd_info *bfd_info = NULL; + struct timeval tv; + struct listnode *neigh_node = NULL; + struct listnode *neigh_nextnode = NULL; + struct pim_neighbor *neigh = NULL; + + ifp = bfd_get_peer_info(zclient->ibuf, &p, NULL, &status, vrf_id); + + if ((ifp == NULL) || (p.family != AF_INET)) + return 0; + + pim_ifp = ifp->info; + if (!pim_ifp) + return 0; + + if (!pim_ifp->bfd_info) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: pim interface %s BFD is disabled ", + __PRETTY_FUNCTION__, ifp->name); + return 0; + } + + if (PIM_DEBUG_PIM_TRACE) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&p, buf, sizeof(buf)); + zlog_debug("%s: interface %s bfd destination %s %s", + __PRETTY_FUNCTION__, ifp->name, buf, + bfd_get_status_str(status)); + } + + for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list, neigh_node, + neigh_nextnode, neigh)) { + /* Check neigh address matches with BFD address */ + if (neigh->source_addr.s_addr != p.u.prefix4.s_addr) + continue; + + bfd_info = (struct bfd_info *)neigh->bfd_info; + if (bfd_info->status == status) { + if (PIM_DEBUG_PIM_TRACE) { + char str[INET_ADDRSTRLEN]; + pim_inet4_dump("", neigh->source_addr, + str, sizeof(str)); + zlog_debug("%s: bfd status is same for nbr %s", + __PRETTY_FUNCTION__, str); + } + continue; + } + old_status = bfd_info->status; + bfd_info->status = status; + monotime(&tv); + bfd_info->last_update = tv.tv_sec; + + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: status %s old_status %s", + __PRETTY_FUNCTION__, + bfd_get_status_str(status), + bfd_get_status_str(old_status)); + } + if ((status == BFD_STATUS_DOWN) + && (old_status == BFD_STATUS_UP)) { + snprintf(msg, sizeof(msg), "BFD Session Expired"); + pim_neighbor_delete(ifp, neigh, msg); + } + } + return 0; } /* * pim_bfd_nbr_replay - Replay all the neighbors that have BFD enabled * to zebra */ -static int -pim_bfd_nbr_replay (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int pim_bfd_nbr_replay(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp = NULL; - struct pim_interface *pim_ifp = NULL; - struct pim_neighbor *neigh = NULL; - struct listnode *node; - struct listnode *neigh_node; - struct listnode *neigh_nextnode; - - /* Send the client registration */ - bfd_client_sendmsg (zclient, ZEBRA_BFD_CLIENT_REGISTER); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (pim_ifp->pim_sock_fd < 0) - continue; - - for (ALL_LIST_ELEMENTS (pim_ifp->pim_neighbor_list, neigh_node, - neigh_nextnode, neigh)) - { - if (!neigh->bfd_info) - continue; - if (PIM_DEBUG_PIM_TRACE) - { - char str[INET_ADDRSTRLEN]; - pim_inet4_dump ("", neigh->source_addr, str, - sizeof (str)); - zlog_debug ("%s: Replaying Pim Neigh %s to BFD", - __PRETTY_FUNCTION__, str); - } - pim_bfd_reg_dereg_nbr (neigh, ZEBRA_BFD_DEST_UPDATE); - - } - } - return 0; + struct interface *ifp = NULL; + struct pim_interface *pim_ifp = NULL; + struct pim_neighbor *neigh = NULL; + struct listnode *node; + struct listnode *neigh_node; + struct listnode *neigh_nextnode; + + /* Send the client registration */ + bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (pim_ifp->pim_sock_fd < 0) + continue; + + for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list, neigh_node, + neigh_nextnode, neigh)) { + if (!neigh->bfd_info) + continue; + if (PIM_DEBUG_PIM_TRACE) { + char str[INET_ADDRSTRLEN]; + pim_inet4_dump("", neigh->source_addr, + str, sizeof(str)); + zlog_debug("%s: Replaying Pim Neigh %s to BFD", + __PRETTY_FUNCTION__, str); + } + pim_bfd_reg_dereg_nbr(neigh, ZEBRA_BFD_DEST_UPDATE); + } + } + return 0; } -void -pim_bfd_init (void) +void pim_bfd_init(void) { - struct zclient *zclient = NULL; + struct zclient *zclient = NULL; - zclient = pim_zebra_zclient_get (); + zclient = pim_zebra_zclient_get(); - bfd_gbl_init (); + bfd_gbl_init(); - zclient->interface_bfd_dest_update = pim_bfd_interface_dest_update; - zclient->bfd_dest_replay = pim_bfd_nbr_replay; + zclient->interface_bfd_dest_update = pim_bfd_interface_dest_update; + zclient->bfd_dest_replay = pim_bfd_nbr_replay; } diff --git a/pimd/pim_bfd.h b/pimd/pim_bfd.h index 23f286b86..316d3c1e2 100644 --- a/pimd/pim_bfd.h +++ b/pimd/pim_bfd.h @@ -25,18 +25,16 @@ #include "if.h" -void pim_bfd_init (void); -void pim_bfd_write_config (struct vty *vty, struct interface *ifp); -void -pim_bfd_show_info (struct vty *vty, void *bfd_info, json_object * json_obj, - u_char use_json, int param_only); -void -pim_bfd_if_param_set (struct interface *ifp, u_int32_t min_rx, - u_int32_t min_tx, u_int8_t detect_mult, int defaults); -int pim_bfd_reg_dereg_all_nbr (struct interface *ifp, int command); -void -pim_bfd_trigger_event (struct pim_interface *pim_ifp, struct pim_neighbor *nbr, uint8_t nbr_up); -void -pim_bfd_info_nbr_create (struct pim_interface *pim_ifp, struct pim_neighbor *neigh); +void pim_bfd_init(void); +void pim_bfd_write_config(struct vty *vty, struct interface *ifp); +void pim_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj, + u_char use_json, int param_only); +void pim_bfd_if_param_set(struct interface *ifp, u_int32_t min_rx, + u_int32_t min_tx, u_int8_t detect_mult, int defaults); +int pim_bfd_reg_dereg_all_nbr(struct interface *ifp, int command); +void pim_bfd_trigger_event(struct pim_interface *pim_ifp, + struct pim_neighbor *nbr, uint8_t nbr_up); +void pim_bfd_info_nbr_create(struct pim_interface *pim_ifp, + struct pim_neighbor *neigh); void pim_bfd_info_free(void **bfd_info); #endif /* _PIM_BFD_H */ diff --git a/pimd/pim_br.c b/pimd/pim_br.c index 19a0293c4..f297b0591 100644 --- a/pimd/pim_br.c +++ b/pimd/pim_br.c @@ -29,83 +29,80 @@ #include "linklist.h" struct pim_br { - struct prefix_sg sg; - struct in_addr pmbr; + struct prefix_sg sg; + struct in_addr pmbr; }; -struct in_addr pim_br_unknown = { .s_addr = 0 }; +struct in_addr pim_br_unknown = {.s_addr = 0}; static struct list *pim_br_list = NULL; -struct in_addr -pim_br_get_pmbr (struct prefix_sg *sg) +struct in_addr pim_br_get_pmbr(struct prefix_sg *sg) { - struct listnode *node; - struct pim_br *pim_br; + struct listnode *node; + struct pim_br *pim_br; - for (ALL_LIST_ELEMENTS_RO (pim_br_list, node, pim_br)) { - if (sg->src.s_addr == pim_br->sg.src.s_addr && - sg->grp.s_addr == pim_br->sg.grp.s_addr) - return pim_br->pmbr; - } + for (ALL_LIST_ELEMENTS_RO(pim_br_list, node, pim_br)) { + if (sg->src.s_addr == pim_br->sg.src.s_addr + && sg->grp.s_addr == pim_br->sg.grp.s_addr) + return pim_br->pmbr; + } - return pim_br_unknown; + return pim_br_unknown; } -void -pim_br_set_pmbr (struct prefix_sg *sg, struct in_addr br) +void pim_br_set_pmbr(struct prefix_sg *sg, struct in_addr br) { - struct listnode *node, *next; - struct pim_br *pim_br; + struct listnode *node, *next; + struct pim_br *pim_br; - for (ALL_LIST_ELEMENTS (pim_br_list, node, next, pim_br)) { - if (sg->src.s_addr == pim_br->sg.src.s_addr && - sg->grp.s_addr == pim_br->sg.grp.s_addr) - break; - } + for (ALL_LIST_ELEMENTS(pim_br_list, node, next, pim_br)) { + if (sg->src.s_addr == pim_br->sg.src.s_addr + && sg->grp.s_addr == pim_br->sg.grp.s_addr) + break; + } - if (!pim_br) { - pim_br = XCALLOC(MTYPE_PIM_BR, sizeof (*pim_br)); - if (!pim_br) { - zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_br)); - return; - } + if (!pim_br) { + pim_br = XCALLOC(MTYPE_PIM_BR, sizeof(*pim_br)); + if (!pim_br) { + zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_br)); + return; + } - pim_br->sg = *sg; + pim_br->sg = *sg; - listnode_add(pim_br_list, pim_br); - } + listnode_add(pim_br_list, pim_br); + } - pim_br->pmbr = br; + pim_br->pmbr = br; } /* * Remove the (S,G) from the stored values */ -void -pim_br_clear_pmbr (struct prefix_sg *sg) +void pim_br_clear_pmbr(struct prefix_sg *sg) { - struct listnode *node, *next; - struct pim_br *pim_br; + struct listnode *node, *next; + struct pim_br *pim_br; - for (ALL_LIST_ELEMENTS (pim_br_list, node, next, pim_br)) { - if (sg->src.s_addr == pim_br->sg.src.s_addr && - sg->grp.s_addr == pim_br->sg.grp.s_addr) - break; - } + for (ALL_LIST_ELEMENTS(pim_br_list, node, next, pim_br)) { + if (sg->src.s_addr == pim_br->sg.src.s_addr + && sg->grp.s_addr == pim_br->sg.grp.s_addr) + break; + } - if (!pim_br) - return; + if (!pim_br) + return; - listnode_delete (pim_br_list, pim_br); + listnode_delete(pim_br_list, pim_br); } -void pim_br_init (void) +void pim_br_init(void) { - pim_br_list = list_new(); - if (!pim_br_list) { - zlog_err("%s: Failure to create pim_br_list", - __PRETTY_FUNCTION__); - return; - } + pim_br_list = list_new(); + if (!pim_br_list) { + zlog_err("%s: Failure to create pim_br_list", + __PRETTY_FUNCTION__); + return; + } } diff --git a/pimd/pim_br.h b/pimd/pim_br.h index 345dd011e..836ff5ee8 100644 --- a/pimd/pim_br.h +++ b/pimd/pim_br.h @@ -20,12 +20,12 @@ #ifndef PIM_BR_H #define PIM_BR_H -struct in_addr pim_br_get_pmbr (struct prefix_sg *sg); +struct in_addr pim_br_get_pmbr(struct prefix_sg *sg); -void pim_br_set_pmbr (struct prefix_sg *sg, struct in_addr value); -void pim_br_clear_pmbr (struct prefix_sg *sg); +void pim_br_set_pmbr(struct prefix_sg *sg, struct in_addr value); +void pim_br_clear_pmbr(struct prefix_sg *sg); -void pim_br_init (void); +void pim_br_init(void); extern struct in_addr pim_br_unknown; diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 88c43104c..1c9fe40c2 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -61,37 +61,28 @@ #include "bfd.h" static struct cmd_node pim_global_node = { - PIM_NODE, - "", - 1 /* vtysh ? yes */ + PIM_NODE, "", 1 /* vtysh ? yes */ }; static struct cmd_node interface_node = { - INTERFACE_NODE, - "%s(config-if)# ", - 1 /* vtysh ? yes */ + INTERFACE_NODE, "%s(config-if)# ", 1 /* vtysh ? yes */ }; -static struct cmd_node debug_node = -{ - DEBUG_NODE, - "", - 1 -}; +static struct cmd_node debug_node = {DEBUG_NODE, "", 1}; static void pim_if_membership_clear(struct interface *ifp) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - pim_ifp = ifp->info; - zassert(pim_ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - if (PIM_IF_TEST_PIM(pim_ifp->options) && - PIM_IF_TEST_IGMP(pim_ifp->options)) { - return; - } + if (PIM_IF_TEST_PIM(pim_ifp->options) + && PIM_IF_TEST_IGMP(pim_ifp->options)) { + return; + } - pim_ifchannel_membership_clear(ifp); + pim_ifchannel_membership_clear(ifp); } /* @@ -105,2492 +96,2953 @@ static void pim_if_membership_clear(struct interface *ifp) */ static void pim_if_membership_refresh(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *sock_node; - struct igmp_sock *igmp; + struct pim_interface *pim_ifp; + struct listnode *sock_node; + struct igmp_sock *igmp; - pim_ifp = ifp->info; - zassert(pim_ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - if (!PIM_IF_TEST_PIM(pim_ifp->options)) - return; - if (!PIM_IF_TEST_IGMP(pim_ifp->options)) - return; + if (!PIM_IF_TEST_PIM(pim_ifp->options)) + return; + if (!PIM_IF_TEST_IGMP(pim_ifp->options)) + return; - /* - First clear off membership from all PIM (S,G) entries on the - interface - */ + /* + First clear off membership from all PIM (S,G) entries on the + interface + */ - pim_ifchannel_membership_clear(ifp); + pim_ifchannel_membership_clear(ifp); - /* - Then restore PIM (S,G) membership from all IGMPv3 (S,G) entries on - the interface - */ + /* + Then restore PIM (S,G) membership from all IGMPv3 (S,G) entries on + the interface + */ - /* scan igmp sockets */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - struct listnode *grpnode; - struct igmp_group *grp; - - /* scan igmp groups */ - for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) { - struct listnode *srcnode; - struct igmp_source *src; - - /* scan group sources */ - for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) { + /* scan igmp sockets */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { + struct listnode *grpnode; + struct igmp_group *grp; - if (IGMP_SOURCE_TEST_FORWARDING(src->source_flags)) { - struct prefix_sg sg; + /* scan igmp groups */ + for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, + grp)) { + struct listnode *srcnode; + struct igmp_source *src; - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = src->source_addr; - sg.grp = grp->group_addr; - pim_ifchannel_local_membership_add(ifp, &sg); - } - - } /* scan group sources */ - } /* scan igmp groups */ - } /* scan igmp sockets */ + /* scan group sources */ + for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, + srcnode, src)) { + + if (IGMP_SOURCE_TEST_FORWARDING( + src->source_flags)) { + struct prefix_sg sg; + + memset(&sg, 0, + sizeof(struct prefix_sg)); + sg.src = src->source_addr; + sg.grp = grp->group_addr; + pim_ifchannel_local_membership_add(ifp, + &sg); + } - /* - Finally delete every PIM (S,G) entry lacking all state info - */ + } /* scan group sources */ + } /* scan igmp groups */ + } /* scan igmp sockets */ - pim_ifchannel_delete_on_noinfo(ifp); + /* + Finally delete every PIM (S,G) entry lacking all state info + */ + pim_ifchannel_delete_on_noinfo(ifp); } static void pim_show_assert(struct vty *vty) { - struct pim_interface *pim_ifp; - struct pim_ifchannel *ch; - struct listnode *ch_node; - struct in_addr ifaddr; - time_t now; - - now = pim_time_monotonic_sec(); - - vty_out (vty, - "Interface Address Source Group State Winner Uptime Timer\n"); - - for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; - char winner_str[INET_ADDRSTRLEN]; - char uptime[10]; - char timer[10]; - - pim_ifp = ch->interface->info; - - if (!pim_ifp) - continue; - - ifaddr = pim_ifp->primary_address; - - pim_inet4_dump("", ch->sg.src, - ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->sg.grp, - ch_grp_str, sizeof(ch_grp_str)); - pim_inet4_dump("", ch->ifassert_winner, - winner_str, sizeof(winner_str)); - - pim_time_uptime(uptime, sizeof(uptime), now - ch->ifassert_creation); - pim_time_timer_to_mmss(timer, sizeof(timer), - ch->t_ifassert_timer); - - vty_out (vty, "%-9s %-15s %-15s %-15s %-6s %-15s %-8s %-5s\n", - ch->interface->name, - inet_ntoa(ifaddr), - ch_src_str, - ch_grp_str, - pim_ifchannel_ifassert_name(ch->ifassert_state), - winner_str, - uptime, - timer); - } /* scan interface channels */ + struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; + struct listnode *ch_node; + struct in_addr ifaddr; + time_t now; + + now = pim_time_monotonic_sec(); + + vty_out(vty, + "Interface Address Source Group State Winner Uptime Timer\n"); + + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; + char winner_str[INET_ADDRSTRLEN]; + char uptime[10]; + char timer[10]; + + pim_ifp = ch->interface->info; + + if (!pim_ifp) + continue; + + ifaddr = pim_ifp->primary_address; + + pim_inet4_dump("", ch->sg.src, ch_src_str, + sizeof(ch_src_str)); + pim_inet4_dump("", ch->sg.grp, ch_grp_str, + sizeof(ch_grp_str)); + pim_inet4_dump("", ch->ifassert_winner, winner_str, + sizeof(winner_str)); + + pim_time_uptime(uptime, sizeof(uptime), + now - ch->ifassert_creation); + pim_time_timer_to_mmss(timer, sizeof(timer), + ch->t_ifassert_timer); + + vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %-15s %-8s %-5s\n", + ch->interface->name, inet_ntoa(ifaddr), ch_src_str, + ch_grp_str, + pim_ifchannel_ifassert_name(ch->ifassert_state), + winner_str, uptime, timer); + } /* scan interface channels */ } static void pim_show_assert_internal(struct vty *vty) { - struct pim_interface *pim_ifp; - struct listnode *ch_node; - struct pim_ifchannel *ch; - struct in_addr ifaddr; - - vty_out (vty, - "CA: CouldAssert\n" - "ECA: Evaluate CouldAssert\n" - "ATD: AssertTrackingDesired\n" - "eATD: Evaluate AssertTrackingDesired\n\n"); - - vty_out (vty, - "Interface Address Source Group CA eCA ATD eATD\n"); - - for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { - pim_ifp = ch->interface->info; - - if (!pim_ifp) - continue; - - ifaddr = pim_ifp->primary_address; - - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; - - pim_inet4_dump("", ch->sg.src, - ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->sg.grp, - ch_grp_str, sizeof(ch_grp_str)); - vty_out (vty, "%-9s %-15s %-15s %-15s %-3s %-3s %-3s %-4s\n", - ch->interface->name, - inet_ntoa(ifaddr), - ch_src_str, - ch_grp_str, - PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags) ? "yes" : "no", - pim_macro_ch_could_assert_eval(ch) ? "yes" : "no", - PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags) ? "yes" : "no", - pim_macro_assert_tracking_desired_eval(ch) ? "yes" : "no"); - } /* scan interface channels */ + struct pim_interface *pim_ifp; + struct listnode *ch_node; + struct pim_ifchannel *ch; + struct in_addr ifaddr; + + vty_out(vty, + "CA: CouldAssert\n" + "ECA: Evaluate CouldAssert\n" + "ATD: AssertTrackingDesired\n" + "eATD: Evaluate AssertTrackingDesired\n\n"); + + vty_out(vty, + "Interface Address Source Group CA eCA ATD eATD\n"); + + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { + pim_ifp = ch->interface->info; + + if (!pim_ifp) + continue; + + ifaddr = pim_ifp->primary_address; + + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; + + pim_inet4_dump("", ch->sg.src, ch_src_str, + sizeof(ch_src_str)); + pim_inet4_dump("", ch->sg.grp, ch_grp_str, + sizeof(ch_grp_str)); + vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-3s %-3s %-4s\n", + ch->interface->name, inet_ntoa(ifaddr), ch_src_str, + ch_grp_str, + PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags) ? "yes" : "no", + pim_macro_ch_could_assert_eval(ch) ? "yes" : "no", + PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags) + ? "yes" + : "no", + pim_macro_assert_tracking_desired_eval(ch) ? "yes" + : "no"); + } /* scan interface channels */ } static void pim_show_assert_metric(struct vty *vty) { - struct pim_interface *pim_ifp; - struct listnode *ch_node; - struct pim_ifchannel *ch; - struct in_addr ifaddr; + struct pim_interface *pim_ifp; + struct listnode *ch_node; + struct pim_ifchannel *ch; + struct in_addr ifaddr; - vty_out (vty, - "Interface Address Source Group RPT Pref Metric Address \n"); + vty_out(vty, + "Interface Address Source Group RPT Pref Metric Address \n"); - for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { - pim_ifp = ch->interface->info; + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { + pim_ifp = ch->interface->info; - if (!pim_ifp) - continue; + if (!pim_ifp) + continue; - ifaddr = pim_ifp->primary_address; + ifaddr = pim_ifp->primary_address; - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; - char addr_str[INET_ADDRSTRLEN]; - struct pim_assert_metric am; + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; + char addr_str[INET_ADDRSTRLEN]; + struct pim_assert_metric am; - am = pim_macro_spt_assert_metric(&ch->upstream->rpf, pim_ifp->primary_address); + am = pim_macro_spt_assert_metric(&ch->upstream->rpf, + pim_ifp->primary_address); - pim_inet4_dump("", ch->sg.src, - ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->sg.grp, - ch_grp_str, sizeof(ch_grp_str)); - pim_inet4_dump("", am.ip_address, - addr_str, sizeof(addr_str)); + pim_inet4_dump("", ch->sg.src, ch_src_str, + sizeof(ch_src_str)); + pim_inet4_dump("", ch->sg.grp, ch_grp_str, + sizeof(ch_grp_str)); + pim_inet4_dump("", am.ip_address, addr_str, + sizeof(addr_str)); - vty_out (vty, "%-9s %-15s %-15s %-15s %-3s %4u %6u %-15s\n", - ch->interface->name, - inet_ntoa(ifaddr), - ch_src_str, - ch_grp_str, - am.rpt_bit_flag ? "yes" : "no", - am.metric_preference, - am.route_metric, - addr_str); - } /* scan interface channels */ + vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %4u %6u %-15s\n", + ch->interface->name, inet_ntoa(ifaddr), ch_src_str, + ch_grp_str, am.rpt_bit_flag ? "yes" : "no", + am.metric_preference, am.route_metric, addr_str); + } /* scan interface channels */ } static void pim_show_assert_winner_metric(struct vty *vty) { - struct pim_interface *pim_ifp; - struct listnode *ch_node; - struct pim_ifchannel *ch; - struct in_addr ifaddr; - - vty_out (vty, - "Interface Address Source Group RPT Pref Metric Address \n"); + struct pim_interface *pim_ifp; + struct listnode *ch_node; + struct pim_ifchannel *ch; + struct in_addr ifaddr; + + vty_out(vty, + "Interface Address Source Group RPT Pref Metric Address \n"); + + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { + pim_ifp = ch->interface->info; - for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { - pim_ifp = ch->interface->info; - - if (!pim_ifp) - continue; + if (!pim_ifp) + continue; - ifaddr = pim_ifp->primary_address; + ifaddr = pim_ifp->primary_address; - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; - char addr_str[INET_ADDRSTRLEN]; - struct pim_assert_metric *am; - char pref_str[5]; - char metr_str[7]; + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; + char addr_str[INET_ADDRSTRLEN]; + struct pim_assert_metric *am; + char pref_str[5]; + char metr_str[7]; - am = &ch->ifassert_winner_metric; + am = &ch->ifassert_winner_metric; - pim_inet4_dump("", ch->sg.src, - ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->sg.grp, - ch_grp_str, sizeof(ch_grp_str)); - pim_inet4_dump("", am->ip_address, - addr_str, sizeof(addr_str)); + pim_inet4_dump("", ch->sg.src, ch_src_str, + sizeof(ch_src_str)); + pim_inet4_dump("", ch->sg.grp, ch_grp_str, + sizeof(ch_grp_str)); + pim_inet4_dump("", am->ip_address, addr_str, + sizeof(addr_str)); - if (am->metric_preference == PIM_ASSERT_METRIC_PREFERENCE_MAX) - snprintf(pref_str, sizeof(pref_str), "INFI"); - else - snprintf(pref_str, sizeof(pref_str), "%4u", am->metric_preference); + if (am->metric_preference == PIM_ASSERT_METRIC_PREFERENCE_MAX) + snprintf(pref_str, sizeof(pref_str), "INFI"); + else + snprintf(pref_str, sizeof(pref_str), "%4u", + am->metric_preference); - if (am->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX) - snprintf(metr_str, sizeof(metr_str), "INFI"); - else - snprintf(metr_str, sizeof(metr_str), "%6u", am->route_metric); + if (am->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX) + snprintf(metr_str, sizeof(metr_str), "INFI"); + else + snprintf(metr_str, sizeof(metr_str), "%6u", + am->route_metric); - vty_out (vty, "%-9s %-15s %-15s %-15s %-3s %-4s %-6s %-15s\n", - ch->interface->name, - inet_ntoa(ifaddr), - ch_src_str, - ch_grp_str, - am->rpt_bit_flag ? "yes" : "no", - pref_str, - metr_str, - addr_str); - } /* scan interface channels */ + vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-4s %-6s %-15s\n", + ch->interface->name, inet_ntoa(ifaddr), ch_src_str, + ch_grp_str, am->rpt_bit_flag ? "yes" : "no", pref_str, + metr_str, addr_str); + } /* scan interface channels */ } -static void json_object_pim_ifp_add(struct json_object *json, struct interface *ifp) +static void json_object_pim_ifp_add(struct json_object *json, + struct interface *ifp) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - pim_ifp = ifp->info; - json_object_string_add(json, "name", ifp->name); - json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down"); - json_object_string_add(json, "address", inet_ntoa(pim_ifp->primary_address)); - json_object_int_add(json, "index", ifp->ifindex); + pim_ifp = ifp->info; + json_object_string_add(json, "name", ifp->name); + json_object_string_add(json, "state", if_is_up(ifp) ? "up" : "down"); + json_object_string_add(json, "address", + inet_ntoa(pim_ifp->primary_address)); + json_object_int_add(json, "index", ifp->ifindex); - if (if_is_multicast(ifp)) - json_object_boolean_true_add(json, "flagMulticast"); + if (if_is_multicast(ifp)) + json_object_boolean_true_add(json, "flagMulticast"); - if (if_is_broadcast(ifp)) - json_object_boolean_true_add(json, "flagBroadcast"); + if (if_is_broadcast(ifp)) + json_object_boolean_true_add(json, "flagBroadcast"); - if (ifp->flags & IFF_ALLMULTI) - json_object_boolean_true_add(json, "flagAllMulticast"); + if (ifp->flags & IFF_ALLMULTI) + json_object_boolean_true_add(json, "flagAllMulticast"); - if (ifp->flags & IFF_PROMISC) - json_object_boolean_true_add(json, "flagPromiscuous"); + if (ifp->flags & IFF_PROMISC) + json_object_boolean_true_add(json, "flagPromiscuous"); - if (PIM_IF_IS_DELETED(ifp)) - json_object_boolean_true_add(json, "flagDeleted"); + if (PIM_IF_IS_DELETED(ifp)) + json_object_boolean_true_add(json, "flagDeleted"); - if (pim_if_lan_delay_enabled(ifp)) - json_object_boolean_true_add(json, "lanDelayEnabled"); + if (pim_if_lan_delay_enabled(ifp)) + json_object_boolean_true_add(json, "lanDelayEnabled"); } static void pim_show_membership(struct vty *vty, u_char uj) { - struct pim_interface *pim_ifp; - struct listnode *ch_node; - struct pim_ifchannel *ch; - enum json_type type; - json_object *json = NULL; - json_object *json_iface = NULL; - json_object *json_row = NULL; - json_object *json_tmp = NULL; - - json = json_object_new_object(); - - for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { - - pim_ifp = ch->interface->info; - - if (!pim_ifp) - continue; - - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; - - pim_inet4_dump("", ch->sg.src, - ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->sg.grp, - ch_grp_str, sizeof(ch_grp_str)); - - json_object_object_get_ex(json, ch->interface->name, &json_iface); - - if (!json_iface) { - json_iface = json_object_new_object(); - json_object_pim_ifp_add(json_iface, ch->interface); - json_object_object_add(json, ch->interface->name, json_iface); - } - - json_row = json_object_new_object(); - json_object_string_add(json_row, "source", ch_src_str); - json_object_string_add(json_row, "group", ch_grp_str); - json_object_string_add(json_row, "localMembership", - ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO ? "NOINFO" : "INCLUDE"); - json_object_object_add(json_iface, ch_grp_str, json_row); - } /* scan interface channels */ - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - } else { - vty_out (vty, - "Interface Address Source Group Membership\n"); - - /* - * Example of the json data we are traversing - * - * { - * "swp3":{ - * "name":"swp3", - * "state":"up", - * "address":"10.1.20.1", - * "index":5, - * "flagMulticast":true, - * "flagBroadcast":true, - * "lanDelayEnabled":true, - * "226.10.10.10":{ - * "source":"*", - * "group":"226.10.10.10", - * "localMembership":"INCLUDE" - * } - * } - * } - */ - - /* foreach interface */ - json_object_object_foreach(json, key, val) { - - /* Find all of the keys where the val is an object. In the example - * above the only one is 226.10.10.10 - */ - json_object_object_foreach(val, if_field_key, if_field_val) { - type = json_object_get_type(if_field_val); - - if (type == json_type_object) { - vty_out(vty, "%-9s ", key); - - json_object_object_get_ex(val, "address", &json_tmp); - vty_out(vty, "%-15s ", json_object_get_string(json_tmp)); - - json_object_object_get_ex(if_field_val, "source", &json_tmp); - vty_out(vty, "%-15s ", json_object_get_string(json_tmp)); - - /* Group */ - vty_out(vty, "%-15s ", if_field_key); - - json_object_object_get_ex(if_field_val, "localMembership", &json_tmp); - vty_out (vty, "%-10s\n", json_object_get_string(json_tmp)); - } - } - } - } - - json_object_free(json); -} - -static void pim_print_ifp_flags(struct vty *vty, struct interface *ifp, int mloop) -{ - vty_out (vty, "Flags\n"); - vty_out (vty, "-----\n"); - vty_out (vty, "All Multicast : %s\n", - (ifp->flags & IFF_ALLMULTI) ? "yes" : "no"); - vty_out (vty, "Broadcast : %s\n", - if_is_broadcast(ifp) ? "yes" : "no"); - vty_out (vty, "Deleted : %s\n", - PIM_IF_IS_DELETED(ifp) ? "yes" : "no"); - vty_out (vty, "Interface Index : %d\n", ifp->ifindex); - vty_out (vty, "Multicast : %s\n", - if_is_multicast(ifp) ? "yes" : "no"); - vty_out (vty, "Multicast Loop : %d\n", mloop); - vty_out (vty, "Promiscuous : %s\n", - (ifp->flags & IFF_PROMISC) ? "yes" : "no"); - vty_out (vty, "\n"); - vty_out (vty, "\n"); + struct pim_interface *pim_ifp; + struct listnode *ch_node; + struct pim_ifchannel *ch; + enum json_type type; + json_object *json = NULL; + json_object *json_iface = NULL; + json_object *json_row = NULL; + json_object *json_tmp = NULL; + + json = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { + + pim_ifp = ch->interface->info; + + if (!pim_ifp) + continue; + + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; + + pim_inet4_dump("", ch->sg.src, ch_src_str, + sizeof(ch_src_str)); + pim_inet4_dump("", ch->sg.grp, ch_grp_str, + sizeof(ch_grp_str)); + + json_object_object_get_ex(json, ch->interface->name, + &json_iface); + + if (!json_iface) { + json_iface = json_object_new_object(); + json_object_pim_ifp_add(json_iface, ch->interface); + json_object_object_add(json, ch->interface->name, + json_iface); + } + + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", ch_src_str); + json_object_string_add(json_row, "group", ch_grp_str); + json_object_string_add( + json_row, "localMembership", + ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO + ? "NOINFO" + : "INCLUDE"); + json_object_object_add(json_iface, ch_grp_str, json_row); + } /* scan interface channels */ + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + } else { + vty_out(vty, + "Interface Address Source Group Membership\n"); + + /* + * Example of the json data we are traversing + * + * { + * "swp3":{ + * "name":"swp3", + * "state":"up", + * "address":"10.1.20.1", + * "index":5, + * "flagMulticast":true, + * "flagBroadcast":true, + * "lanDelayEnabled":true, + * "226.10.10.10":{ + * "source":"*", + * "group":"226.10.10.10", + * "localMembership":"INCLUDE" + * } + * } + * } + */ + + /* foreach interface */ + json_object_object_foreach(json, key, val) + { + + /* Find all of the keys where the val is an object. In + * the example + * above the only one is 226.10.10.10 + */ + json_object_object_foreach(val, if_field_key, + if_field_val) + { + type = json_object_get_type(if_field_val); + + if (type == json_type_object) { + vty_out(vty, "%-9s ", key); + + json_object_object_get_ex( + val, "address", &json_tmp); + vty_out(vty, "%-15s ", + json_object_get_string( + json_tmp)); + + json_object_object_get_ex(if_field_val, + "source", + &json_tmp); + vty_out(vty, "%-15s ", + json_object_get_string( + json_tmp)); + + /* Group */ + vty_out(vty, "%-15s ", if_field_key); + + json_object_object_get_ex( + if_field_val, "localMembership", + &json_tmp); + vty_out(vty, "%-10s\n", + json_object_get_string( + json_tmp)); + } + } + } + } + + json_object_free(json); +} + +static void pim_print_ifp_flags(struct vty *vty, struct interface *ifp, + int mloop) +{ + vty_out(vty, "Flags\n"); + vty_out(vty, "-----\n"); + vty_out(vty, "All Multicast : %s\n", + (ifp->flags & IFF_ALLMULTI) ? "yes" : "no"); + vty_out(vty, "Broadcast : %s\n", + if_is_broadcast(ifp) ? "yes" : "no"); + vty_out(vty, "Deleted : %s\n", + PIM_IF_IS_DELETED(ifp) ? "yes" : "no"); + vty_out(vty, "Interface Index : %d\n", ifp->ifindex); + vty_out(vty, "Multicast : %s\n", + if_is_multicast(ifp) ? "yes" : "no"); + vty_out(vty, "Multicast Loop : %d\n", mloop); + vty_out(vty, "Promiscuous : %s\n", + (ifp->flags & IFF_PROMISC) ? "yes" : "no"); + vty_out(vty, "\n"); + vty_out(vty, "\n"); } static void igmp_show_interfaces(struct vty *vty, u_char uj) { - struct listnode *node; - struct interface *ifp; - time_t now; - json_object *json = NULL; - json_object *json_row = NULL; - - now = pim_time_monotonic_sec(); - - if (uj) - json = json_object_new_object(); - else - vty_out (vty, - "Interface State Address V Querier Query Timer Uptime\n"); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - struct pim_interface *pim_ifp; - struct listnode *sock_node; - struct igmp_sock *igmp; - - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - char uptime[10]; - char query_hhmmss[10]; - - pim_time_uptime(uptime, sizeof(uptime), now - igmp->sock_creation); - pim_time_timer_to_hhmmss(query_hhmmss, sizeof(query_hhmmss), igmp->t_igmp_query_timer); - - if (uj) { - json_row = json_object_new_object(); - json_object_pim_ifp_add(json_row, ifp); - json_object_string_add(json_row, "upTime", uptime); - json_object_int_add(json_row, "version", pim_ifp->igmp_version); - - if (igmp->t_igmp_query_timer) { - json_object_boolean_true_add(json_row, "querier"); - json_object_string_add(json_row, "queryTimer", query_hhmmss); - } - - json_object_object_add(json, ifp->name, json_row); - - } else { - vty_out (vty, "%-9s %5s %15s %d %7s %11s %8s\n", - ifp->name, - if_is_up(ifp) ? "up" : "down", - inet_ntoa(igmp->ifaddr), - pim_ifp->igmp_version, - igmp->t_igmp_query_timer ? "local" : "other", - query_hhmmss, - uptime); - } - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } -} - -static void igmp_show_interfaces_single(struct vty *vty, const char *ifname, u_char uj) -{ - struct igmp_sock *igmp; - struct interface *ifp; - struct listnode *node; - struct listnode *sock_node; - struct pim_interface *pim_ifp; - char uptime[10]; - char query_hhmmss[10]; - char other_hhmmss[10]; - int found_ifname = 0; - int sqi; - int mloop; - long gmi_msec; /* Group Membership Interval */ - long lmqt_msec; - long ohpi_msec; - long oqpi_msec; /* Other Querier Present Interval */ - long qri_msec; - time_t now; - - json_object *json = NULL; - json_object *json_row = NULL; - - if (uj) - json = json_object_new_object(); - - now = pim_time_monotonic_sec(); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name)) - continue; - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - found_ifname = 1; - pim_time_uptime(uptime, sizeof(uptime), now - igmp->sock_creation); - pim_time_timer_to_hhmmss(query_hhmmss, sizeof(query_hhmmss), igmp->t_igmp_query_timer); - pim_time_timer_to_hhmmss(other_hhmmss, sizeof(other_hhmmss), igmp->t_other_querier_timer); - - gmi_msec = PIM_IGMP_GMI_MSEC(igmp->querier_robustness_variable, - igmp->querier_query_interval, - pim_ifp->igmp_query_max_response_time_dsec); - - sqi = PIM_IGMP_SQI(pim_ifp->igmp_default_query_interval); - - oqpi_msec = PIM_IGMP_OQPI_MSEC(igmp->querier_robustness_variable, - igmp->querier_query_interval, - pim_ifp->igmp_query_max_response_time_dsec); - - lmqt_msec = PIM_IGMP_LMQT_MSEC(pim_ifp->igmp_query_max_response_time_dsec, - igmp->querier_robustness_variable); - - ohpi_msec = PIM_IGMP_OHPI_DSEC(igmp->querier_robustness_variable, - igmp->querier_query_interval, - pim_ifp->igmp_query_max_response_time_dsec) * 100; - - qri_msec = pim_ifp->igmp_query_max_response_time_dsec * 100; - mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd); - - if (uj) { - json_row = json_object_new_object(); - json_object_pim_ifp_add(json_row, ifp); - json_object_string_add(json_row, "upTime", uptime); - json_object_string_add(json_row, "querier", igmp->t_igmp_query_timer ? "local" : "other"); - json_object_int_add(json_row, "queryStartCount", igmp->startup_query_count); - json_object_string_add(json_row, "queryQueryTimer", query_hhmmss); - json_object_string_add(json_row, "queryOtherTimer", other_hhmmss); - json_object_int_add(json_row, "version", pim_ifp->igmp_version); - json_object_int_add(json_row, "timerGroupMembershipIntervalMsec", gmi_msec); - json_object_int_add(json_row, "timerLastMemberQueryMsec", lmqt_msec); - json_object_int_add(json_row, "timerOlderHostPresentIntervalMsec", ohpi_msec); - json_object_int_add(json_row, "timerOtherQuerierPresentIntervalMsec", oqpi_msec); - json_object_int_add(json_row, "timerQueryInterval", igmp->querier_query_interval); - json_object_int_add(json_row, "timerQueryResponseIntervalMsec", qri_msec); - json_object_int_add(json_row, "timerRobustnessVariable", igmp->querier_robustness_variable); - json_object_int_add(json_row, "timerStartupQueryInterval", sqi); - - json_object_object_add(json, ifp->name, json_row); - - } else { - vty_out (vty, "Interface : %s\n", ifp->name); - vty_out (vty, "State : %s\n", if_is_up(ifp) ? "up" : "down"); - vty_out (vty, "Address : %s\n", - inet_ntoa(pim_ifp->primary_address)); - vty_out (vty, "Uptime : %s\n", uptime); - vty_out (vty, "Version : %d\n", pim_ifp->igmp_version); - vty_out (vty, "\n"); - vty_out (vty, "\n"); - - vty_out (vty, "Querier\n"); - vty_out (vty, "-------\n"); - vty_out (vty, "Querier : %s\n", - igmp->t_igmp_query_timer ? "local" : "other"); - vty_out (vty, "Start Count : %d\n", igmp->startup_query_count); - vty_out (vty, "Query Timer : %s\n", query_hhmmss); - vty_out (vty, "Other Timer : %s\n", other_hhmmss); - vty_out (vty, "\n"); - vty_out (vty, "\n"); - - vty_out (vty, "Timers\n"); - vty_out (vty, "------\n"); - vty_out (vty, "Group Membership Interval : %lis\n", - gmi_msec / 1000); - vty_out (vty, "Last Member Query Time : %lis\n", - lmqt_msec / 1000); - vty_out (vty, "Older Host Present Interval : %lis\n", - ohpi_msec / 1000); - vty_out (vty, "Other Querier Present Interval : %lis\n", - oqpi_msec / 1000); - vty_out (vty, "Query Interval : %ds\n", - igmp->querier_query_interval); - vty_out (vty, "Query Response Interval : %lis\n", - qri_msec / 1000); - vty_out (vty, "Robustness Variable : %d\n", - igmp->querier_robustness_variable); - vty_out (vty, "Startup Query Interval : %ds\n", sqi); - vty_out (vty, "\n"); - vty_out (vty, "\n"); - - pim_print_ifp_flags(vty, ifp, mloop); - } - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } else { - if (!found_ifname) - vty_out (vty, "%% No such interface\n"); - } + struct listnode *node; + struct interface *ifp; + time_t now; + json_object *json = NULL; + json_object *json_row = NULL; + + now = pim_time_monotonic_sec(); + + if (uj) + json = json_object_new_object(); + else + vty_out(vty, + "Interface State Address V Querier Query Timer Uptime\n"); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + struct pim_interface *pim_ifp; + struct listnode *sock_node; + struct igmp_sock *igmp; + + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, + igmp)) { + char uptime[10]; + char query_hhmmss[10]; + + pim_time_uptime(uptime, sizeof(uptime), + now - igmp->sock_creation); + pim_time_timer_to_hhmmss(query_hhmmss, + sizeof(query_hhmmss), + igmp->t_igmp_query_timer); + + if (uj) { + json_row = json_object_new_object(); + json_object_pim_ifp_add(json_row, ifp); + json_object_string_add(json_row, "upTime", + uptime); + json_object_int_add(json_row, "version", + pim_ifp->igmp_version); + + if (igmp->t_igmp_query_timer) { + json_object_boolean_true_add(json_row, + "querier"); + json_object_string_add(json_row, + "queryTimer", + query_hhmmss); + } + + json_object_object_add(json, ifp->name, + json_row); + + } else { + vty_out(vty, + "%-9s %5s %15s %d %7s %11s %8s\n", + ifp->name, + if_is_up(ifp) ? "up" : "down", + inet_ntoa(igmp->ifaddr), + pim_ifp->igmp_version, + igmp->t_igmp_query_timer ? "local" + : "other", + query_hhmmss, uptime); + } + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } +} + +static void igmp_show_interfaces_single(struct vty *vty, const char *ifname, + u_char uj) +{ + struct igmp_sock *igmp; + struct interface *ifp; + struct listnode *node; + struct listnode *sock_node; + struct pim_interface *pim_ifp; + char uptime[10]; + char query_hhmmss[10]; + char other_hhmmss[10]; + int found_ifname = 0; + int sqi; + int mloop; + long gmi_msec; /* Group Membership Interval */ + long lmqt_msec; + long ohpi_msec; + long oqpi_msec; /* Other Querier Present Interval */ + long qri_msec; + time_t now; + + json_object *json = NULL; + json_object *json_row = NULL; + + if (uj) + json = json_object_new_object(); + + now = pim_time_monotonic_sec(); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name)) + continue; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, + igmp)) { + found_ifname = 1; + pim_time_uptime(uptime, sizeof(uptime), + now - igmp->sock_creation); + pim_time_timer_to_hhmmss(query_hhmmss, + sizeof(query_hhmmss), + igmp->t_igmp_query_timer); + pim_time_timer_to_hhmmss(other_hhmmss, + sizeof(other_hhmmss), + igmp->t_other_querier_timer); + + gmi_msec = PIM_IGMP_GMI_MSEC( + igmp->querier_robustness_variable, + igmp->querier_query_interval, + pim_ifp->igmp_query_max_response_time_dsec); + + sqi = PIM_IGMP_SQI( + pim_ifp->igmp_default_query_interval); + + oqpi_msec = PIM_IGMP_OQPI_MSEC( + igmp->querier_robustness_variable, + igmp->querier_query_interval, + pim_ifp->igmp_query_max_response_time_dsec); + + lmqt_msec = PIM_IGMP_LMQT_MSEC( + pim_ifp->igmp_query_max_response_time_dsec, + igmp->querier_robustness_variable); + + ohpi_msec = + PIM_IGMP_OHPI_DSEC( + igmp->querier_robustness_variable, + igmp->querier_query_interval, + pim_ifp->igmp_query_max_response_time_dsec) + * 100; + + qri_msec = pim_ifp->igmp_query_max_response_time_dsec + * 100; + mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd); + + if (uj) { + json_row = json_object_new_object(); + json_object_pim_ifp_add(json_row, ifp); + json_object_string_add(json_row, "upTime", + uptime); + json_object_string_add(json_row, "querier", + igmp->t_igmp_query_timer + ? "local" + : "other"); + json_object_int_add(json_row, "queryStartCount", + igmp->startup_query_count); + json_object_string_add(json_row, + "queryQueryTimer", + query_hhmmss); + json_object_string_add(json_row, + "queryOtherTimer", + other_hhmmss); + json_object_int_add(json_row, "version", + pim_ifp->igmp_version); + json_object_int_add( + json_row, + "timerGroupMembershipIntervalMsec", + gmi_msec); + json_object_int_add(json_row, + "timerLastMemberQueryMsec", + lmqt_msec); + json_object_int_add( + json_row, + "timerOlderHostPresentIntervalMsec", + ohpi_msec); + json_object_int_add( + json_row, + "timerOtherQuerierPresentIntervalMsec", + oqpi_msec); + json_object_int_add( + json_row, "timerQueryInterval", + igmp->querier_query_interval); + json_object_int_add( + json_row, + "timerQueryResponseIntervalMsec", + qri_msec); + json_object_int_add( + json_row, "timerRobustnessVariable", + igmp->querier_robustness_variable); + json_object_int_add(json_row, + "timerStartupQueryInterval", + sqi); + + json_object_object_add(json, ifp->name, + json_row); + + } else { + vty_out(vty, "Interface : %s\n", ifp->name); + vty_out(vty, "State : %s\n", + if_is_up(ifp) ? "up" : "down"); + vty_out(vty, "Address : %s\n", + inet_ntoa(pim_ifp->primary_address)); + vty_out(vty, "Uptime : %s\n", uptime); + vty_out(vty, "Version : %d\n", + pim_ifp->igmp_version); + vty_out(vty, "\n"); + vty_out(vty, "\n"); + + vty_out(vty, "Querier\n"); + vty_out(vty, "-------\n"); + vty_out(vty, "Querier : %s\n", + igmp->t_igmp_query_timer ? "local" + : "other"); + vty_out(vty, "Start Count : %d\n", + igmp->startup_query_count); + vty_out(vty, "Query Timer : %s\n", + query_hhmmss); + vty_out(vty, "Other Timer : %s\n", + other_hhmmss); + vty_out(vty, "\n"); + vty_out(vty, "\n"); + + vty_out(vty, "Timers\n"); + vty_out(vty, "------\n"); + vty_out(vty, + "Group Membership Interval : %lis\n", + gmi_msec / 1000); + vty_out(vty, + "Last Member Query Time : %lis\n", + lmqt_msec / 1000); + vty_out(vty, + "Older Host Present Interval : %lis\n", + ohpi_msec / 1000); + vty_out(vty, + "Other Querier Present Interval : %lis\n", + oqpi_msec / 1000); + vty_out(vty, + "Query Interval : %ds\n", + igmp->querier_query_interval); + vty_out(vty, + "Query Response Interval : %lis\n", + qri_msec / 1000); + vty_out(vty, + "Robustness Variable : %d\n", + igmp->querier_robustness_variable); + vty_out(vty, + "Startup Query Interval : %ds\n", + sqi); + vty_out(vty, "\n"); + vty_out(vty, "\n"); + + pim_print_ifp_flags(vty, ifp, mloop); + } + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else { + if (!found_ifname) + vty_out(vty, "%% No such interface\n"); + } } static void igmp_show_interface_join(struct vty *vty) { - struct listnode *node; - struct interface *ifp; - time_t now; - - now = pim_time_monotonic_sec(); - - vty_out (vty, - "Interface Address Source Group Socket Uptime \n"); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - struct pim_interface *pim_ifp; - struct listnode *join_node; - struct igmp_join *ij; - struct in_addr pri_addr; - char pri_addr_str[INET_ADDRSTRLEN]; - - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (!pim_ifp->igmp_join_list) - continue; - - pri_addr = pim_find_primary_addr(ifp); - pim_inet4_dump("", pri_addr, pri_addr_str, sizeof(pri_addr_str)); - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_join_list, join_node, ij)) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - char uptime[10]; - - pim_time_uptime(uptime, sizeof(uptime), now - ij->sock_creation); - pim_inet4_dump("", ij->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", ij->source_addr, source_str, sizeof(source_str)); - - vty_out (vty, "%-9s %-15s %-15s %-15s %6d %8s\n", - ifp->name, - pri_addr_str, - source_str, - group_str, - ij->sock_fd, - uptime); - } /* for (pim_ifp->igmp_join_list) */ - - } /* for (iflist) */ - -} - -static void pim_show_interfaces_single(struct vty *vty, const char *ifname, u_char uj) -{ - struct in_addr ifaddr; - struct interface *ifp; - struct listnode *neighnode; - struct listnode*node; - struct listnode *upnode; - struct pim_interface *pim_ifp; - struct pim_neighbor *neigh; - struct pim_upstream *up; - time_t now; - char dr_str[INET_ADDRSTRLEN]; - char dr_uptime[10]; - char expire[10]; - char grp_str[INET_ADDRSTRLEN]; - char hello_period[10]; - char hello_timer[10]; - char neigh_src_str[INET_ADDRSTRLEN]; - char src_str[INET_ADDRSTRLEN]; - char stat_uptime[10]; - char uptime[10]; - int mloop; - int found_ifname = 0; - int print_header; - json_object *json = NULL; - json_object *json_row = NULL; - json_object *json_pim_neighbor = NULL; - json_object *json_pim_neighbors = NULL; - json_object *json_group = NULL; - json_object *json_group_source = NULL; - json_object *json_fhr_sources = NULL; - struct pim_secondary_addr *sec_addr; - struct listnode *sec_node; - - now = pim_time_monotonic_sec(); - - if (uj) - json = json_object_new_object(); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (pim_ifp->pim_sock_fd < 0) - continue; - - if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name)) - continue; - - found_ifname = 1; - ifaddr = pim_ifp->primary_address; - pim_inet4_dump("", pim_ifp->pim_dr_addr, dr_str, sizeof(dr_str)); - pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), now, pim_ifp->pim_dr_election_last); - pim_time_timer_to_hhmmss(hello_timer, sizeof(hello_timer), pim_ifp->t_pim_hello_timer); - pim_time_mmss(hello_period, sizeof(hello_period), pim_ifp->pim_hello_period); - pim_time_uptime(stat_uptime, sizeof(stat_uptime), now - pim_ifp->pim_ifstat_start); - mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd); - - if (uj) { - char pbuf[PREFIX2STR_BUFFER]; - json_row = json_object_new_object(); - json_object_pim_ifp_add(json_row, ifp); - - if (pim_ifp->update_source.s_addr != INADDR_ANY) { - json_object_string_add(json_row, "useSource", inet_ntoa(pim_ifp->update_source)); - } - if (pim_ifp->sec_addr_list) { - json_object *sec_list = NULL; - - sec_list = json_object_new_array(); - for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) { - json_object_array_add(sec_list, - json_object_new_string(prefix2str(&sec_addr->addr, - pbuf, - sizeof(pbuf)))); - } - json_object_object_add(json_row, "secondaryAddressList", sec_list); - } - - // PIM neighbors - if (pim_ifp->pim_neighbor_list->count) { - json_pim_neighbors = json_object_new_object(); - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { - json_pim_neighbor = json_object_new_object(); - pim_inet4_dump("", neigh->source_addr, neigh_src_str, sizeof(neigh_src_str)); - pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation); - pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer); - - json_object_string_add(json_pim_neighbor, "address", neigh_src_str); - json_object_string_add(json_pim_neighbor, "upTime", uptime); - json_object_string_add(json_pim_neighbor, "holdtime", expire); - - json_object_object_add(json_pim_neighbors, neigh_src_str, json_pim_neighbor); - } - - json_object_object_add(json_row, "neighbors", json_pim_neighbors); - } - - json_object_string_add(json_row, "drAddress", dr_str); - json_object_int_add(json_row, "drPriority", pim_ifp->pim_dr_priority); - json_object_string_add(json_row, "drUptime", dr_uptime); - json_object_int_add(json_row, "drElections", pim_ifp->pim_dr_election_count); - json_object_int_add(json_row, "drChanges", pim_ifp->pim_dr_election_changes); - - // FHR - for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { - if (ifp == up->rpf.source_nexthop.interface) { - if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) { - if (!json_fhr_sources) { - json_fhr_sources = json_object_new_object(); - } - - pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); - pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); - - /* Does this group live in json_fhr_sources? If not create it. */ - json_object_object_get_ex(json_fhr_sources, grp_str, &json_group); - - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json_fhr_sources, grp_str, json_group); - } - - json_group_source = json_object_new_object(); - json_object_string_add(json_group_source, "source", src_str); - json_object_string_add(json_group_source, "group", grp_str); - json_object_string_add(json_group_source, "upTime", uptime); - json_object_object_add(json_group, src_str, json_group_source); - } - } - } - - if (json_fhr_sources) { - json_object_object_add(json_row, "firstHopRouter", json_fhr_sources); - } - - json_object_int_add(json_row, "helloPeriod", pim_ifp->pim_hello_period); - json_object_string_add(json_row, "helloTimer", hello_timer); - json_object_string_add(json_row, "helloStatStart", stat_uptime); - json_object_int_add(json_row, "helloReceived", pim_ifp->pim_ifstat_hello_recv); - json_object_int_add(json_row, "helloReceivedFailed", pim_ifp->pim_ifstat_hello_recvfail); - json_object_int_add(json_row, "helloSend", pim_ifp->pim_ifstat_hello_sent); - json_object_int_add(json_row, "hellosendFailed", pim_ifp->pim_ifstat_hello_sendfail); - json_object_int_add(json_row, "helloGenerationId", pim_ifp->pim_generation_id); - json_object_int_add(json_row, "flagMulticastLoop", mloop); - - json_object_int_add(json_row, "effectivePropagationDelay", pim_if_effective_propagation_delay_msec(ifp)); - json_object_int_add(json_row, "effectiveOverrideInterval", pim_if_effective_override_interval_msec(ifp)); - json_object_int_add(json_row, "joinPruneOverrideInterval", pim_if_jp_override_interval_msec(ifp)); - - json_object_int_add(json_row, "propagationDelay", pim_ifp->pim_propagation_delay_msec); - json_object_int_add(json_row, "propagationDelayHighest", pim_ifp->pim_neighbors_highest_propagation_delay_msec); - json_object_int_add(json_row, "overrideInterval", pim_ifp->pim_override_interval_msec); - json_object_int_add(json_row, "overrideIntervalHighest", pim_ifp->pim_neighbors_highest_override_interval_msec); - json_object_object_add(json, ifp->name, json_row); - - } else { - vty_out (vty, "Interface : %s\n", ifp->name); - vty_out (vty, "State : %s\n", if_is_up(ifp) ? "up" : "down"); - if (pim_ifp->update_source.s_addr != INADDR_ANY) { - vty_out (vty, "Use Source : %s\n", inet_ntoa(pim_ifp->update_source)); - } - if (pim_ifp->sec_addr_list) { - char pbuf[PREFIX2STR_BUFFER]; - vty_out (vty, "Address : %s (primary)\n", - inet_ntoa(ifaddr)); - for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, sec_node, sec_addr)) { - vty_out (vty, " %s\n", - prefix2str(&sec_addr->addr, pbuf, sizeof(pbuf))); - } - } else { - vty_out (vty, "Address : %s\n", inet_ntoa(ifaddr)); - } - vty_out (vty, "\n"); - - // PIM neighbors - print_header = 1; - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { - - if (print_header) { - vty_out (vty, "PIM Neighbors\n"); - vty_out (vty, "-------------\n"); - print_header = 0; - } - - pim_inet4_dump("", neigh->source_addr, neigh_src_str, sizeof(neigh_src_str)); - pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation); - pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer); - vty_out (vty, "%-15s : up for %s, holdtime expires in %s\n", neigh_src_str, uptime, - expire); - } - - if (!print_header) { - vty_out (vty, "\n"); - vty_out (vty, "\n"); - } - - vty_out (vty, "Designated Router\n"); - vty_out (vty, "-----------------\n"); - vty_out (vty, "Address : %s\n", dr_str); - vty_out (vty, "Priority : %d\n", pim_ifp->pim_dr_priority); - vty_out (vty, "Uptime : %s\n", dr_uptime); - vty_out (vty, "Elections : %d\n", pim_ifp->pim_dr_election_count); - vty_out (vty, "Changes : %d\n", pim_ifp->pim_dr_election_changes); - vty_out (vty, "\n"); - vty_out (vty, "\n"); - - // FHR - print_header = 1; - for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { - if (strcmp(ifp->name, up->rpf.source_nexthop.interface->name) == 0) { - if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) { - - if (print_header) { - vty_out (vty, "FHR - First Hop Router\n"); - vty_out (vty, "----------------------\n"); - print_header = 0; - } - - pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); - pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); - vty_out (vty, "%s : %s is a source, uptime is %s\n", grp_str, src_str, - uptime); - } - } - } - - if (!print_header) { - vty_out (vty, "\n"); - vty_out (vty, "\n"); - } - - vty_out (vty, "Hellos\n"); - vty_out (vty, "------\n"); - vty_out (vty, "Period : %d\n", pim_ifp->pim_hello_period); - vty_out (vty, "Timer : %s\n", hello_timer); - vty_out (vty, "StatStart : %s\n", stat_uptime); - vty_out (vty, "Receive : %d\n", pim_ifp->pim_ifstat_hello_recv); - vty_out (vty, "Receive Failed : %d\n", - pim_ifp->pim_ifstat_hello_recvfail); - vty_out (vty, "Send : %d\n", pim_ifp->pim_ifstat_hello_sent); - vty_out (vty, "Send Failed : %d\n", - pim_ifp->pim_ifstat_hello_sendfail); - vty_out (vty, "Generation ID : %08x\n", pim_ifp->pim_generation_id); - vty_out (vty, "\n"); - vty_out (vty, "\n"); - - pim_print_ifp_flags(vty, ifp, mloop); - - vty_out (vty, "Join Prune Interval\n"); - vty_out (vty, "-------------------\n"); - vty_out (vty, "LAN Delay : %s\n", - pim_if_lan_delay_enabled(ifp) ? "yes" : "no"); - vty_out (vty, "Effective Propagation Delay : %d msec\n", - pim_if_effective_propagation_delay_msec(ifp)); - vty_out (vty, "Effective Override Interval : %d msec\n", - pim_if_effective_override_interval_msec(ifp)); - vty_out (vty, "Join Prune Override Interval : %d msec\n", - pim_if_jp_override_interval_msec(ifp)); - vty_out (vty, "\n"); - vty_out (vty, "\n"); - - vty_out (vty, "LAN Prune Delay\n"); - vty_out (vty, "---------------\n"); - vty_out (vty, "Propagation Delay : %d msec\n", - pim_ifp->pim_propagation_delay_msec); - vty_out (vty, "Propagation Delay (Highest) : %d msec\n", - pim_ifp->pim_neighbors_highest_propagation_delay_msec); - vty_out (vty, "Override Interval : %d msec\n", - pim_ifp->pim_override_interval_msec); - vty_out (vty, "Override Interval (Highest) : %d msec\n", - pim_ifp->pim_neighbors_highest_override_interval_msec); - vty_out (vty, "\n"); - vty_out (vty, "\n"); - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } else { - if (!found_ifname) - vty_out (vty, "%% No such interface\n"); - } + struct listnode *node; + struct interface *ifp; + time_t now; + + now = pim_time_monotonic_sec(); + + vty_out(vty, + "Interface Address Source Group Socket Uptime \n"); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + struct pim_interface *pim_ifp; + struct listnode *join_node; + struct igmp_join *ij; + struct in_addr pri_addr; + char pri_addr_str[INET_ADDRSTRLEN]; + + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (!pim_ifp->igmp_join_list) + continue; + + pri_addr = pim_find_primary_addr(ifp); + pim_inet4_dump("", pri_addr, pri_addr_str, + sizeof(pri_addr_str)); + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_join_list, join_node, + ij)) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + char uptime[10]; + + pim_time_uptime(uptime, sizeof(uptime), + now - ij->sock_creation); + pim_inet4_dump("", ij->group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("", ij->source_addr, source_str, + sizeof(source_str)); + + vty_out(vty, "%-9s %-15s %-15s %-15s %6d %8s\n", + ifp->name, pri_addr_str, source_str, group_str, + ij->sock_fd, uptime); + } /* for (pim_ifp->igmp_join_list) */ + + } /* for (iflist) */ +} + +static void pim_show_interfaces_single(struct vty *vty, const char *ifname, + u_char uj) +{ + struct in_addr ifaddr; + struct interface *ifp; + struct listnode *neighnode; + struct listnode *node; + struct listnode *upnode; + struct pim_interface *pim_ifp; + struct pim_neighbor *neigh; + struct pim_upstream *up; + time_t now; + char dr_str[INET_ADDRSTRLEN]; + char dr_uptime[10]; + char expire[10]; + char grp_str[INET_ADDRSTRLEN]; + char hello_period[10]; + char hello_timer[10]; + char neigh_src_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; + char stat_uptime[10]; + char uptime[10]; + int mloop; + int found_ifname = 0; + int print_header; + json_object *json = NULL; + json_object *json_row = NULL; + json_object *json_pim_neighbor = NULL; + json_object *json_pim_neighbors = NULL; + json_object *json_group = NULL; + json_object *json_group_source = NULL; + json_object *json_fhr_sources = NULL; + struct pim_secondary_addr *sec_addr; + struct listnode *sec_node; + + now = pim_time_monotonic_sec(); + + if (uj) + json = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (pim_ifp->pim_sock_fd < 0) + continue; + + if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name)) + continue; + + found_ifname = 1; + ifaddr = pim_ifp->primary_address; + pim_inet4_dump("", pim_ifp->pim_dr_addr, dr_str, + sizeof(dr_str)); + pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime), now, + pim_ifp->pim_dr_election_last); + pim_time_timer_to_hhmmss(hello_timer, sizeof(hello_timer), + pim_ifp->t_pim_hello_timer); + pim_time_mmss(hello_period, sizeof(hello_period), + pim_ifp->pim_hello_period); + pim_time_uptime(stat_uptime, sizeof(stat_uptime), + now - pim_ifp->pim_ifstat_start); + mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd); + + if (uj) { + char pbuf[PREFIX2STR_BUFFER]; + json_row = json_object_new_object(); + json_object_pim_ifp_add(json_row, ifp); + + if (pim_ifp->update_source.s_addr != INADDR_ANY) { + json_object_string_add( + json_row, "useSource", + inet_ntoa(pim_ifp->update_source)); + } + if (pim_ifp->sec_addr_list) { + json_object *sec_list = NULL; + + sec_list = json_object_new_array(); + for (ALL_LIST_ELEMENTS_RO( + pim_ifp->sec_addr_list, sec_node, + sec_addr)) { + json_object_array_add( + sec_list, + json_object_new_string( + prefix2str( + &sec_addr->addr, + pbuf, + sizeof(pbuf)))); + } + json_object_object_add(json_row, + "secondaryAddressList", + sec_list); + } + + // PIM neighbors + if (pim_ifp->pim_neighbor_list->count) { + json_pim_neighbors = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO( + pim_ifp->pim_neighbor_list, + neighnode, neigh)) { + json_pim_neighbor = + json_object_new_object(); + pim_inet4_dump("", + neigh->source_addr, + neigh_src_str, + sizeof(neigh_src_str)); + pim_time_uptime(uptime, sizeof(uptime), + now - neigh->creation); + pim_time_timer_to_hhmmss( + expire, sizeof(expire), + neigh->t_expire_timer); + + json_object_string_add( + json_pim_neighbor, "address", + neigh_src_str); + json_object_string_add( + json_pim_neighbor, "upTime", + uptime); + json_object_string_add( + json_pim_neighbor, "holdtime", + expire); + + json_object_object_add( + json_pim_neighbors, + neigh_src_str, + json_pim_neighbor); + } + + json_object_object_add(json_row, "neighbors", + json_pim_neighbors); + } + + json_object_string_add(json_row, "drAddress", dr_str); + json_object_int_add(json_row, "drPriority", + pim_ifp->pim_dr_priority); + json_object_string_add(json_row, "drUptime", dr_uptime); + json_object_int_add(json_row, "drElections", + pim_ifp->pim_dr_election_count); + json_object_int_add(json_row, "drChanges", + pim_ifp->pim_dr_election_changes); + + // FHR + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, + up)) { + if (ifp == up->rpf.source_nexthop.interface) { + if (up->flags + & PIM_UPSTREAM_FLAG_MASK_FHR) { + if (!json_fhr_sources) { + json_fhr_sources = + json_object_new_object(); + } + + pim_inet4_dump("", + up->sg.src, + src_str, + sizeof(src_str)); + pim_inet4_dump("", + up->sg.grp, + grp_str, + sizeof(grp_str)); + pim_time_uptime( + uptime, sizeof(uptime), + now - up->state_transition); + + /* Does this group live in + * json_fhr_sources? If not + * create it. */ + json_object_object_get_ex( + json_fhr_sources, + grp_str, &json_group); + + if (!json_group) { + json_group = + json_object_new_object(); + json_object_object_add( + json_fhr_sources, + grp_str, + json_group); + } + + json_group_source = + json_object_new_object(); + json_object_string_add( + json_group_source, + "source", src_str); + json_object_string_add( + json_group_source, + "group", grp_str); + json_object_string_add( + json_group_source, + "upTime", uptime); + json_object_object_add( + json_group, src_str, + json_group_source); + } + } + } + + if (json_fhr_sources) { + json_object_object_add(json_row, + "firstHopRouter", + json_fhr_sources); + } + + json_object_int_add(json_row, "helloPeriod", + pim_ifp->pim_hello_period); + json_object_string_add(json_row, "helloTimer", + hello_timer); + json_object_string_add(json_row, "helloStatStart", + stat_uptime); + json_object_int_add(json_row, "helloReceived", + pim_ifp->pim_ifstat_hello_recv); + json_object_int_add(json_row, "helloReceivedFailed", + pim_ifp->pim_ifstat_hello_recvfail); + json_object_int_add(json_row, "helloSend", + pim_ifp->pim_ifstat_hello_sent); + json_object_int_add(json_row, "hellosendFailed", + pim_ifp->pim_ifstat_hello_sendfail); + json_object_int_add(json_row, "helloGenerationId", + pim_ifp->pim_generation_id); + json_object_int_add(json_row, "flagMulticastLoop", + mloop); + + json_object_int_add( + json_row, "effectivePropagationDelay", + pim_if_effective_propagation_delay_msec(ifp)); + json_object_int_add( + json_row, "effectiveOverrideInterval", + pim_if_effective_override_interval_msec(ifp)); + json_object_int_add( + json_row, "joinPruneOverrideInterval", + pim_if_jp_override_interval_msec(ifp)); + + json_object_int_add( + json_row, "propagationDelay", + pim_ifp->pim_propagation_delay_msec); + json_object_int_add( + json_row, "propagationDelayHighest", + pim_ifp->pim_neighbors_highest_propagation_delay_msec); + json_object_int_add( + json_row, "overrideInterval", + pim_ifp->pim_override_interval_msec); + json_object_int_add( + json_row, "overrideIntervalHighest", + pim_ifp->pim_neighbors_highest_override_interval_msec); + json_object_object_add(json, ifp->name, json_row); + + } else { + vty_out(vty, "Interface : %s\n", ifp->name); + vty_out(vty, "State : %s\n", + if_is_up(ifp) ? "up" : "down"); + if (pim_ifp->update_source.s_addr != INADDR_ANY) { + vty_out(vty, "Use Source : %s\n", + inet_ntoa(pim_ifp->update_source)); + } + if (pim_ifp->sec_addr_list) { + char pbuf[PREFIX2STR_BUFFER]; + vty_out(vty, "Address : %s (primary)\n", + inet_ntoa(ifaddr)); + for (ALL_LIST_ELEMENTS_RO( + pim_ifp->sec_addr_list, sec_node, + sec_addr)) { + vty_out(vty, " %s\n", + prefix2str(&sec_addr->addr, + pbuf, sizeof(pbuf))); + } + } else { + vty_out(vty, "Address : %s\n", + inet_ntoa(ifaddr)); + } + vty_out(vty, "\n"); + + // PIM neighbors + print_header = 1; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, + neighnode, neigh)) { + + if (print_header) { + vty_out(vty, "PIM Neighbors\n"); + vty_out(vty, "-------------\n"); + print_header = 0; + } + + pim_inet4_dump("", neigh->source_addr, + neigh_src_str, + sizeof(neigh_src_str)); + pim_time_uptime(uptime, sizeof(uptime), + now - neigh->creation); + pim_time_timer_to_hhmmss(expire, sizeof(expire), + neigh->t_expire_timer); + vty_out(vty, + "%-15s : up for %s, holdtime expires in %s\n", + neigh_src_str, uptime, expire); + } + + if (!print_header) { + vty_out(vty, "\n"); + vty_out(vty, "\n"); + } + + vty_out(vty, "Designated Router\n"); + vty_out(vty, "-----------------\n"); + vty_out(vty, "Address : %s\n", dr_str); + vty_out(vty, "Priority : %d\n", + pim_ifp->pim_dr_priority); + vty_out(vty, "Uptime : %s\n", dr_uptime); + vty_out(vty, "Elections : %d\n", + pim_ifp->pim_dr_election_count); + vty_out(vty, "Changes : %d\n", + pim_ifp->pim_dr_election_changes); + vty_out(vty, "\n"); + vty_out(vty, "\n"); + + // FHR + print_header = 1; + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, + up)) { + if (strcmp(ifp->name, + up->rpf.source_nexthop + .interface->name) + == 0) { + if (up->flags + & PIM_UPSTREAM_FLAG_MASK_FHR) { + + if (print_header) { + vty_out(vty, + "FHR - First Hop Router\n"); + vty_out(vty, + "----------------------\n"); + print_header = 0; + } + + pim_inet4_dump("", + up->sg.src, + src_str, + sizeof(src_str)); + pim_inet4_dump("", + up->sg.grp, + grp_str, + sizeof(grp_str)); + pim_time_uptime( + uptime, sizeof(uptime), + now - up->state_transition); + vty_out(vty, + "%s : %s is a source, uptime is %s\n", + grp_str, src_str, + uptime); + } + } + } + + if (!print_header) { + vty_out(vty, "\n"); + vty_out(vty, "\n"); + } + + vty_out(vty, "Hellos\n"); + vty_out(vty, "------\n"); + vty_out(vty, "Period : %d\n", + pim_ifp->pim_hello_period); + vty_out(vty, "Timer : %s\n", hello_timer); + vty_out(vty, "StatStart : %s\n", stat_uptime); + vty_out(vty, "Receive : %d\n", + pim_ifp->pim_ifstat_hello_recv); + vty_out(vty, "Receive Failed : %d\n", + pim_ifp->pim_ifstat_hello_recvfail); + vty_out(vty, "Send : %d\n", + pim_ifp->pim_ifstat_hello_sent); + vty_out(vty, "Send Failed : %d\n", + pim_ifp->pim_ifstat_hello_sendfail); + vty_out(vty, "Generation ID : %08x\n", + pim_ifp->pim_generation_id); + vty_out(vty, "\n"); + vty_out(vty, "\n"); + + pim_print_ifp_flags(vty, ifp, mloop); + + vty_out(vty, "Join Prune Interval\n"); + vty_out(vty, "-------------------\n"); + vty_out(vty, "LAN Delay : %s\n", + pim_if_lan_delay_enabled(ifp) ? "yes" : "no"); + vty_out(vty, "Effective Propagation Delay : %d msec\n", + pim_if_effective_propagation_delay_msec(ifp)); + vty_out(vty, "Effective Override Interval : %d msec\n", + pim_if_effective_override_interval_msec(ifp)); + vty_out(vty, "Join Prune Override Interval : %d msec\n", + pim_if_jp_override_interval_msec(ifp)); + vty_out(vty, "\n"); + vty_out(vty, "\n"); + + vty_out(vty, "LAN Prune Delay\n"); + vty_out(vty, "---------------\n"); + vty_out(vty, "Propagation Delay : %d msec\n", + pim_ifp->pim_propagation_delay_msec); + vty_out(vty, "Propagation Delay (Highest) : %d msec\n", + pim_ifp->pim_neighbors_highest_propagation_delay_msec); + vty_out(vty, "Override Interval : %d msec\n", + pim_ifp->pim_override_interval_msec); + vty_out(vty, "Override Interval (Highest) : %d msec\n", + pim_ifp->pim_neighbors_highest_override_interval_msec); + vty_out(vty, "\n"); + vty_out(vty, "\n"); + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else { + if (!found_ifname) + vty_out(vty, "%% No such interface\n"); + } } static void pim_show_interfaces(struct vty *vty, u_char uj) { - struct interface *ifp; - struct listnode *node; - struct listnode *upnode; - struct pim_interface *pim_ifp; - struct pim_upstream *up; - int fhr = 0; - int pim_nbrs = 0; - int pim_ifchannels = 0; - json_object *json = NULL; - json_object *json_row = NULL; - json_object *json_tmp; - - json = json_object_new_object(); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (pim_ifp->pim_sock_fd < 0) - continue; - - pim_nbrs = pim_ifp->pim_neighbor_list->count; - pim_ifchannels = pim_ifp->pim_ifchannel_list->count; - fhr = 0; - - for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) - if (ifp == up->rpf.source_nexthop.interface) - if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) - fhr++; - - json_row = json_object_new_object(); - json_object_pim_ifp_add(json_row, ifp); - json_object_int_add(json_row, "pimNeighbors", pim_nbrs); - json_object_int_add(json_row, "pimIfChannels", pim_ifchannels); - json_object_int_add(json_row, "firstHopRouter", fhr); - json_object_string_add(json_row, "pimDesignatedRouter", inet_ntoa(pim_ifp->pim_dr_addr)); - - if (pim_ifp->pim_dr_addr.s_addr == pim_ifp->primary_address.s_addr) - json_object_boolean_true_add(json_row, "pimDesignatedRouterLocal"); - - json_object_object_add(json, ifp->name, json_row); - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - } else { - vty_out (vty, - "Interface State Address PIM Nbrs PIM DR FHR IfChannels\n"); - - json_object_object_foreach(json, key, val) { - vty_out(vty, "%-9s ", key); - - json_object_object_get_ex(val, "state", &json_tmp); - vty_out(vty, "%5s ", json_object_get_string(json_tmp)); - - json_object_object_get_ex(val, "address", &json_tmp); - vty_out(vty, "%15s ", json_object_get_string(json_tmp)); - - json_object_object_get_ex(val, "pimNeighbors", &json_tmp); - vty_out(vty, "%8d ", json_object_get_int(json_tmp)); - - if (json_object_object_get_ex(val, "pimDesignatedRouterLocal", &json_tmp)) { - vty_out(vty, "%15s ", "local"); - } else { - json_object_object_get_ex(val, "pimDesignatedRouter", &json_tmp); - vty_out(vty, "%15s ", json_object_get_string(json_tmp)); - } - - json_object_object_get_ex(val, "firstHopRouter", &json_tmp); - vty_out(vty, "%3d ", json_object_get_int(json_tmp)); - - json_object_object_get_ex(val, "pimIfChannels", &json_tmp); - vty_out (vty, "%9d\n", json_object_get_int(json_tmp)); - } - } - - json_object_free(json); -} - -static void pim_show_interface_traffic (struct vty *vty, u_char uj) -{ - struct interface *ifp = NULL; - struct pim_interface *pim_ifp = NULL; - struct listnode *node = NULL; - json_object *json = NULL; - json_object *json_row = NULL; - - if (uj) - json = json_object_new_object (); - else - { - vty_out (vty, "\n"); - vty_out (vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n", "Interface", - " HELLO", " JOIN", " PRUNE", " REGISTER", - " REGISTER-STOP", " ASSERT"); - vty_out (vty, - "%-10s%-18s%-17s%-17s%-17s%-17s%-17s\n", - "", " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx", - " Rx/Tx", " Rx/Tx"); - vty_out (vty, - "---------------------------------------------------------------------------------------------------------------\n"); - } - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (pim_ifp->pim_sock_fd < 0) - continue; - if (uj) - { - json_row = json_object_new_object (); - json_object_pim_ifp_add (json_row, ifp); - json_object_int_add (json_row, "helloRx", pim_ifp->pim_ifstat_hello_recv); - json_object_int_add (json_row, "helloTx", pim_ifp->pim_ifstat_hello_sent); - json_object_int_add (json_row, "joinRx", pim_ifp->pim_ifstat_join_recv); - json_object_int_add (json_row, "joinTx", pim_ifp->pim_ifstat_join_send); - json_object_int_add (json_row, "registerRx", pim_ifp->pim_ifstat_reg_recv); - json_object_int_add (json_row, "registerTx", pim_ifp->pim_ifstat_reg_recv); - json_object_int_add (json_row, "registerStopRx", pim_ifp->pim_ifstat_reg_stop_recv); - json_object_int_add (json_row, "registerStopTx", pim_ifp->pim_ifstat_reg_stop_send); - json_object_int_add (json_row, "assertRx", pim_ifp->pim_ifstat_assert_recv); - json_object_int_add (json_row, "assertTx", pim_ifp->pim_ifstat_assert_send); - - json_object_object_add (json, ifp->name, json_row); - } - else - { - vty_out (vty, - "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n", - ifp->name, pim_ifp->pim_ifstat_hello_recv, - pim_ifp->pim_ifstat_hello_sent, pim_ifp->pim_ifstat_join_recv, - pim_ifp->pim_ifstat_join_send, pim_ifp->pim_ifstat_prune_recv, - pim_ifp->pim_ifstat_prune_send, pim_ifp->pim_ifstat_reg_recv, - pim_ifp->pim_ifstat_reg_send, - pim_ifp->pim_ifstat_reg_stop_recv, - pim_ifp->pim_ifstat_reg_stop_send, - pim_ifp->pim_ifstat_assert_recv, - pim_ifp->pim_ifstat_assert_send); - } - } - if (uj) - { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free (json); - } -} - -static void pim_show_interface_traffic_single (struct vty *vty, const char *ifname, u_char uj) -{ - struct interface *ifp = NULL; - struct pim_interface *pim_ifp = NULL; - struct listnode *node = NULL; - json_object *json = NULL; - json_object *json_row = NULL; - uint8_t found_ifname = 0; - - if (uj) - json = json_object_new_object (); - else - { - vty_out (vty, "\n"); - vty_out (vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n", "Interface", - " HELLO", " JOIN", " PRUNE", " REGISTER", - " REGISTER-STOP", " ASSERT"); - vty_out (vty, - "%-10s%-18s%-17s%-17s%-17s%-17s%-17s\n", - "", " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx", - " Rx/Tx", " Rx/Tx"); - vty_out (vty, - "---------------------------------------------------------------------------------------------------------------\n"); - } - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - if (strcmp (ifname, ifp->name)) - continue; - - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (pim_ifp->pim_sock_fd < 0) - continue; - - found_ifname = 1; - if (uj) - { - json_row = json_object_new_object (); - json_object_pim_ifp_add (json_row, ifp); - json_object_int_add (json_row, "helloRx", pim_ifp->pim_ifstat_hello_recv); - json_object_int_add (json_row, "helloTx", pim_ifp->pim_ifstat_hello_sent); - json_object_int_add (json_row, "joinRx", pim_ifp->pim_ifstat_join_recv); - json_object_int_add (json_row, "joinTx", pim_ifp->pim_ifstat_join_send); - json_object_int_add (json_row, "registerRx", pim_ifp->pim_ifstat_reg_recv); - json_object_int_add (json_row, "registerTx", pim_ifp->pim_ifstat_reg_recv); - json_object_int_add (json_row, "registerStopRx", pim_ifp->pim_ifstat_reg_stop_recv); - json_object_int_add (json_row, "registerStopTx", pim_ifp->pim_ifstat_reg_stop_send); - json_object_int_add (json_row, "assertRx", pim_ifp->pim_ifstat_assert_recv); - json_object_int_add (json_row, "assertTx", pim_ifp->pim_ifstat_assert_send); - - json_object_object_add (json, ifp->name, json_row); - } - else - { - vty_out (vty, - "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n", - ifp->name, pim_ifp->pim_ifstat_hello_recv, - pim_ifp->pim_ifstat_hello_sent, pim_ifp->pim_ifstat_join_recv, - pim_ifp->pim_ifstat_join_send, pim_ifp->pim_ifstat_prune_recv, - pim_ifp->pim_ifstat_prune_send, pim_ifp->pim_ifstat_reg_recv, - pim_ifp->pim_ifstat_reg_send, - pim_ifp->pim_ifstat_reg_stop_recv, - pim_ifp->pim_ifstat_reg_stop_send, - pim_ifp->pim_ifstat_assert_recv, - pim_ifp->pim_ifstat_assert_send); - } - } - if (uj) - { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free (json); - } - else - { - if (!found_ifname) - vty_out (vty, "%% No such interface\n"); - } + struct interface *ifp; + struct listnode *node; + struct listnode *upnode; + struct pim_interface *pim_ifp; + struct pim_upstream *up; + int fhr = 0; + int pim_nbrs = 0; + int pim_ifchannels = 0; + json_object *json = NULL; + json_object *json_row = NULL; + json_object *json_tmp; + + json = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (pim_ifp->pim_sock_fd < 0) + continue; + + pim_nbrs = pim_ifp->pim_neighbor_list->count; + pim_ifchannels = pim_ifp->pim_ifchannel_list->count; + fhr = 0; + + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) + if (ifp == up->rpf.source_nexthop.interface) + if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) + fhr++; + + json_row = json_object_new_object(); + json_object_pim_ifp_add(json_row, ifp); + json_object_int_add(json_row, "pimNeighbors", pim_nbrs); + json_object_int_add(json_row, "pimIfChannels", pim_ifchannels); + json_object_int_add(json_row, "firstHopRouter", fhr); + json_object_string_add(json_row, "pimDesignatedRouter", + inet_ntoa(pim_ifp->pim_dr_addr)); + + if (pim_ifp->pim_dr_addr.s_addr + == pim_ifp->primary_address.s_addr) + json_object_boolean_true_add( + json_row, "pimDesignatedRouterLocal"); + + json_object_object_add(json, ifp->name, json_row); + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + } else { + vty_out(vty, + "Interface State Address PIM Nbrs PIM DR FHR IfChannels\n"); + + json_object_object_foreach(json, key, val) + { + vty_out(vty, "%-9s ", key); + + json_object_object_get_ex(val, "state", &json_tmp); + vty_out(vty, "%5s ", json_object_get_string(json_tmp)); + + json_object_object_get_ex(val, "address", &json_tmp); + vty_out(vty, "%15s ", + json_object_get_string(json_tmp)); + + json_object_object_get_ex(val, "pimNeighbors", + &json_tmp); + vty_out(vty, "%8d ", json_object_get_int(json_tmp)); + + if (json_object_object_get_ex( + val, "pimDesignatedRouterLocal", + &json_tmp)) { + vty_out(vty, "%15s ", "local"); + } else { + json_object_object_get_ex( + val, "pimDesignatedRouter", &json_tmp); + vty_out(vty, "%15s ", + json_object_get_string(json_tmp)); + } + + json_object_object_get_ex(val, "firstHopRouter", + &json_tmp); + vty_out(vty, "%3d ", json_object_get_int(json_tmp)); + + json_object_object_get_ex(val, "pimIfChannels", + &json_tmp); + vty_out(vty, "%9d\n", json_object_get_int(json_tmp)); + } + } + + json_object_free(json); +} + +static void pim_show_interface_traffic(struct vty *vty, u_char uj) +{ + struct interface *ifp = NULL; + struct pim_interface *pim_ifp = NULL; + struct listnode *node = NULL; + json_object *json = NULL; + json_object *json_row = NULL; + + if (uj) + json = json_object_new_object(); + else { + vty_out(vty, "\n"); + vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n", + "Interface", " HELLO", " JOIN", " PRUNE", + " REGISTER", " REGISTER-STOP", " ASSERT"); + vty_out(vty, "%-10s%-18s%-17s%-17s%-17s%-17s%-17s\n", "", + " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx", + " Rx/Tx", " Rx/Tx"); + vty_out(vty, + "---------------------------------------------------------------------------------------------------------------\n"); + } + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (pim_ifp->pim_sock_fd < 0) + continue; + if (uj) { + json_row = json_object_new_object(); + json_object_pim_ifp_add(json_row, ifp); + json_object_int_add(json_row, "helloRx", + pim_ifp->pim_ifstat_hello_recv); + json_object_int_add(json_row, "helloTx", + pim_ifp->pim_ifstat_hello_sent); + json_object_int_add(json_row, "joinRx", + pim_ifp->pim_ifstat_join_recv); + json_object_int_add(json_row, "joinTx", + pim_ifp->pim_ifstat_join_send); + json_object_int_add(json_row, "registerRx", + pim_ifp->pim_ifstat_reg_recv); + json_object_int_add(json_row, "registerTx", + pim_ifp->pim_ifstat_reg_recv); + json_object_int_add(json_row, "registerStopRx", + pim_ifp->pim_ifstat_reg_stop_recv); + json_object_int_add(json_row, "registerStopTx", + pim_ifp->pim_ifstat_reg_stop_send); + json_object_int_add(json_row, "assertRx", + pim_ifp->pim_ifstat_assert_recv); + json_object_int_add(json_row, "assertTx", + pim_ifp->pim_ifstat_assert_send); + + json_object_object_add(json, ifp->name, json_row); + } else { + vty_out(vty, + "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n", + ifp->name, pim_ifp->pim_ifstat_hello_recv, + pim_ifp->pim_ifstat_hello_sent, + pim_ifp->pim_ifstat_join_recv, + pim_ifp->pim_ifstat_join_send, + pim_ifp->pim_ifstat_prune_recv, + pim_ifp->pim_ifstat_prune_send, + pim_ifp->pim_ifstat_reg_recv, + pim_ifp->pim_ifstat_reg_send, + pim_ifp->pim_ifstat_reg_stop_recv, + pim_ifp->pim_ifstat_reg_stop_send, + pim_ifp->pim_ifstat_assert_recv, + pim_ifp->pim_ifstat_assert_send); + } + } + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } +} + +static void pim_show_interface_traffic_single(struct vty *vty, + const char *ifname, u_char uj) +{ + struct interface *ifp = NULL; + struct pim_interface *pim_ifp = NULL; + struct listnode *node = NULL; + json_object *json = NULL; + json_object *json_row = NULL; + uint8_t found_ifname = 0; + + if (uj) + json = json_object_new_object(); + else { + vty_out(vty, "\n"); + vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n", + "Interface", " HELLO", " JOIN", " PRUNE", + " REGISTER", " REGISTER-STOP", " ASSERT"); + vty_out(vty, "%-10s%-18s%-17s%-17s%-17s%-17s%-17s\n", "", + " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx", + " Rx/Tx", " Rx/Tx"); + vty_out(vty, + "---------------------------------------------------------------------------------------------------------------\n"); + } + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + if (strcmp(ifname, ifp->name)) + continue; + + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (pim_ifp->pim_sock_fd < 0) + continue; + + found_ifname = 1; + if (uj) { + json_row = json_object_new_object(); + json_object_pim_ifp_add(json_row, ifp); + json_object_int_add(json_row, "helloRx", + pim_ifp->pim_ifstat_hello_recv); + json_object_int_add(json_row, "helloTx", + pim_ifp->pim_ifstat_hello_sent); + json_object_int_add(json_row, "joinRx", + pim_ifp->pim_ifstat_join_recv); + json_object_int_add(json_row, "joinTx", + pim_ifp->pim_ifstat_join_send); + json_object_int_add(json_row, "registerRx", + pim_ifp->pim_ifstat_reg_recv); + json_object_int_add(json_row, "registerTx", + pim_ifp->pim_ifstat_reg_recv); + json_object_int_add(json_row, "registerStopRx", + pim_ifp->pim_ifstat_reg_stop_recv); + json_object_int_add(json_row, "registerStopTx", + pim_ifp->pim_ifstat_reg_stop_send); + json_object_int_add(json_row, "assertRx", + pim_ifp->pim_ifstat_assert_recv); + json_object_int_add(json_row, "assertTx", + pim_ifp->pim_ifstat_assert_send); + + json_object_object_add(json, ifp->name, json_row); + } else { + vty_out(vty, + "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u \n", + ifp->name, pim_ifp->pim_ifstat_hello_recv, + pim_ifp->pim_ifstat_hello_sent, + pim_ifp->pim_ifstat_join_recv, + pim_ifp->pim_ifstat_join_send, + pim_ifp->pim_ifstat_prune_recv, + pim_ifp->pim_ifstat_prune_send, + pim_ifp->pim_ifstat_reg_recv, + pim_ifp->pim_ifstat_reg_send, + pim_ifp->pim_ifstat_reg_stop_recv, + pim_ifp->pim_ifstat_reg_stop_send, + pim_ifp->pim_ifstat_assert_recv, + pim_ifp->pim_ifstat_assert_send); + } + } + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else { + if (!found_ifname) + vty_out(vty, "%% No such interface\n"); + } } static void pim_show_join(struct vty *vty, u_char uj) { - struct pim_interface *pim_ifp; - struct in_addr ifaddr; - struct listnode *ch_node; - struct pim_ifchannel *ch; - time_t now; - json_object *json = NULL; - json_object *json_iface = NULL; - json_object *json_row = NULL; - json_object *json_grp = NULL; - - now = pim_time_monotonic_sec(); - - if (uj) - json = json_object_new_object(); - else - vty_out (vty, - "Interface Address Source Group State Uptime Expire Prune\n"); - - for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { - - pim_ifp = ch->interface->info; - - if (!pim_ifp) - continue; - - ifaddr = pim_ifp->primary_address; - - char ch_src_str[INET_ADDRSTRLEN]; - char ch_grp_str[INET_ADDRSTRLEN]; - char uptime[10]; - char expire[10]; - char prune[10]; - - pim_inet4_dump("", ch->sg.src, - ch_src_str, sizeof(ch_src_str)); - pim_inet4_dump("", ch->sg.grp, - ch_grp_str, sizeof(ch_grp_str)); - - pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation); - pim_time_timer_to_mmss(expire, sizeof(expire), - ch->t_ifjoin_expiry_timer); - pim_time_timer_to_mmss(prune, sizeof(prune), - ch->t_ifjoin_prune_pending_timer); - - if (uj) { - json_object_object_get_ex(json, ch->interface->name, &json_iface); - - if (!json_iface) { - json_iface = json_object_new_object(); - json_object_pim_ifp_add(json_iface, ch->interface); - json_object_object_add(json, ch->interface->name, json_iface); - } - - json_row = json_object_new_object(); - json_object_string_add(json_row, "source", ch_src_str); - json_object_string_add(json_row, "group", ch_grp_str); - json_object_string_add(json_row, "upTime", uptime); - json_object_string_add(json_row, "expire", expire); - json_object_string_add(json_row, "prune", prune); - json_object_string_add(json_row, "channelJoinName", - pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags)); - if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) - json_object_int_add(json_row, "SGRpt", 1); - - json_object_object_get_ex(json_iface, ch_grp_str, &json_grp); - if (!json_grp) - { - json_grp = json_object_new_object(); - json_object_object_add(json_grp, ch_src_str, json_row); - json_object_object_add(json_iface, ch_grp_str, json_grp); - } - else - json_object_object_add(json_grp, ch_src_str, json_row); - } else { - vty_out (vty, "%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s\n", - ch->interface->name, - inet_ntoa(ifaddr), - ch_src_str, - ch_grp_str, - pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags), - uptime, - expire, - prune); - } - } /* scan interface channels */ - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } -} - -static void pim_show_neighbors_single(struct vty *vty, const char *neighbor, u_char uj) -{ - struct listnode *node; - struct listnode *neighnode; - struct interface *ifp; - struct pim_interface *pim_ifp; - struct pim_neighbor *neigh; - time_t now; - int found_neighbor = 0; - int option_address_list; - int option_dr_priority; - int option_generation_id; - int option_holdtime; - int option_lan_prune_delay; - int option_t_bit; - char uptime[10]; - char expire[10]; - char neigh_src_str[INET_ADDRSTRLEN]; - - json_object *json = NULL; - json_object *json_ifp = NULL; - json_object *json_row = NULL; - - now = pim_time_monotonic_sec(); - - if (uj) - json = json_object_new_object(); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (pim_ifp->pim_sock_fd < 0) - continue; - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { - pim_inet4_dump("", neigh->source_addr, - neigh_src_str, sizeof(neigh_src_str)); - - /* - * The user can specify either the interface name or the PIM neighbor IP. - * If this pim_ifp matches neither then skip. - */ - if (strcmp(neighbor, "detail") && - strcmp(neighbor, ifp->name) && - strcmp(neighbor, neigh_src_str)) - continue; - - found_neighbor = 1; - pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation); - pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer); - - option_address_list = 0; - option_dr_priority = 0; - option_generation_id = 0; - option_holdtime = 0; - option_lan_prune_delay = 0; - option_t_bit = 0; - - if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_ADDRESS_LIST)) - option_address_list = 1; - - if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_DR_PRIORITY)) - option_dr_priority = 1; - - if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_GENERATION_ID)) - option_generation_id = 1; - - if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_HOLDTIME)) - option_holdtime = 1; - - if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY)) - option_lan_prune_delay = 1; - - if (PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION)) - option_t_bit = 1; - - if (uj) { - - /* Does this ifp live in json? If not create it. */ - json_object_object_get_ex(json, ifp->name, &json_ifp); - - if (!json_ifp) { - json_ifp = json_object_new_object(); - json_object_pim_ifp_add(json_ifp, ifp); - json_object_object_add(json, ifp->name, json_ifp); - } - - json_row = json_object_new_object(); - json_object_string_add(json_row, "interface", ifp->name); - json_object_string_add(json_row, "address", neigh_src_str); - json_object_string_add(json_row, "upTime", uptime); - json_object_string_add(json_row, "holdtime", expire); - json_object_int_add(json_row, "drPriority", neigh->dr_priority); - json_object_int_add(json_row, "generationId", neigh->generation_id); - - if (option_address_list) - json_object_boolean_true_add(json_row, "helloOptionAddressList"); - - if (option_dr_priority) - json_object_boolean_true_add(json_row, "helloOptionDrPriority"); - - if (option_generation_id) - json_object_boolean_true_add(json_row, "helloOptionGenerationId"); - - if (option_holdtime) - json_object_boolean_true_add(json_row, "helloOptionHoldtime"); - - if (option_lan_prune_delay) - json_object_boolean_true_add(json_row, "helloOptionLanPruneDelay"); - - if (option_t_bit) - json_object_boolean_true_add(json_row, "helloOptionTBit"); - - json_object_object_add(json_ifp, neigh_src_str, json_row); - - } else { - vty_out (vty, "Interface : %s\n", ifp->name); - vty_out (vty, "Neighbor : %s\n", neigh_src_str); - vty_out (vty, " Uptime : %s\n", uptime); - vty_out (vty, " Holdtime : %s\n", expire); - vty_out (vty, " DR Priority : %d\n", - neigh->dr_priority); - vty_out (vty, " Generation ID : %08x\n", - neigh->generation_id); - vty_out (vty, " Override Interval (msec) : %d\n", - neigh->override_interval_msec); - vty_out (vty, " Propagation Delay (msec) : %d\n", - neigh->propagation_delay_msec); - vty_out (vty, " Hello Option - Address List : %s\n", - option_address_list ? "yes" : "no"); - vty_out (vty, " Hello Option - DR Priority : %s\n", - option_dr_priority ? "yes" : "no"); - vty_out (vty, " Hello Option - Generation ID : %s\n", - option_generation_id ? "yes" : "no"); - vty_out (vty, " Hello Option - Holdtime : %s\n", - option_holdtime ? "yes" : "no"); - vty_out (vty, " Hello Option - LAN Prune Delay : %s\n", - option_lan_prune_delay ? "yes" : "no"); - vty_out (vty, " Hello Option - T-bit : %s\n", - option_t_bit ? "yes" : "no"); - pim_bfd_show_info (vty, neigh->bfd_info, json_ifp, uj, 0); - vty_out (vty, "\n"); - } - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } else { - { - if (!found_neighbor) - vty_out (vty, "%% No such interface or neighbor\n"); - } - } -} - -static void -pim_show_state(struct vty *vty, const char *src_or_group, const char *group, u_char uj) -{ - struct channel_oil *c_oil; - struct listnode *node; - json_object *json = NULL; - json_object *json_group = NULL; - json_object *json_ifp_in = NULL; - json_object *json_ifp_out = NULL; - json_object *json_source = NULL; - time_t now; - int first_oif; - now = pim_time_monotonic_sec(); - - if (uj) { - json = json_object_new_object(); - } else { - vty_out(vty, "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G)"); - vty_out (vty, "\nInstalled Source Group IIF OIL\n"); - } - - for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { - char grp_str[INET_ADDRSTRLEN]; - char src_str[INET_ADDRSTRLEN]; - char in_ifname[INTERFACE_NAMSIZ+1]; - char out_ifname[INTERFACE_NAMSIZ+1]; - int oif_vif_index; - struct interface *ifp_in; - first_oif = 1; - - pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, grp_str, sizeof(grp_str)); - pim_inet4_dump("", c_oil->oil.mfcc_origin, src_str, sizeof(src_str)); - ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); - - if (ifp_in) - strcpy(in_ifname, ifp_in->name); - else - strcpy(in_ifname, ""); - - if (src_or_group) - { - if (strcmp(src_or_group, src_str) && strcmp(src_or_group, grp_str)) - continue; - - if (group && strcmp(group, grp_str)) - continue; - } - - if (uj) { - - /* Find the group, create it if it doesn't exist */ - json_object_object_get_ex(json, grp_str, &json_group); - - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json, grp_str, json_group); - } - - /* Find the source nested under the group, create it if it doesn't exist */ - json_object_object_get_ex(json_group, src_str, &json_source); - - if (!json_source) { - json_source = json_object_new_object(); - json_object_object_add(json_group, src_str, json_source); - } - - /* Find the inbound interface nested under the source, create it if it doesn't exist */ - json_object_object_get_ex(json_source, in_ifname, &json_ifp_in); - - if (!json_ifp_in) { - json_ifp_in = json_object_new_object(); - json_object_object_add(json_source, in_ifname, json_ifp_in); - json_object_int_add (json_source, "Installed", c_oil->installed); - json_object_int_add (json_source, "RefCount", c_oil->oil_ref_count); - json_object_int_add (json_source, "OilListSize", c_oil->oil_size); - json_object_int_add (json_source, "OilRescan", c_oil->oil_inherited_rescan); - json_object_int_add (json_source, "LastUsed", c_oil->cc.lastused); - json_object_int_add (json_source, "PacketCount", c_oil->cc.pktcnt); - json_object_int_add (json_source, "ByteCount", c_oil->cc.bytecnt); - json_object_int_add (json_source, "WrongInterface", c_oil->cc.wrong_if); - } - } else { - vty_out(vty, "%-9d %-15s %-15s %-7s ", - c_oil->installed, - src_str, - grp_str, - ifp_in->name); - } - - for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) { - struct interface *ifp_out; - char oif_uptime[10]; - int ttl; - - ttl = c_oil->oil.mfcc_ttls[oif_vif_index]; - if (ttl < 1) - continue; - - ifp_out = pim_if_find_by_vif_index(oif_vif_index); - pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - c_oil->oif_creation[oif_vif_index]); - - if (ifp_out) - strcpy(out_ifname, ifp_out->name); - else - strcpy(out_ifname, ""); - - if (uj) { - json_ifp_out = json_object_new_object(); - json_object_string_add(json_ifp_out, "source", src_str); - json_object_string_add(json_ifp_out, "group", grp_str); - json_object_string_add(json_ifp_out, "inboundInterface", in_ifname); - json_object_string_add(json_ifp_out, "outboundInterface", out_ifname); - json_object_int_add(json_ifp_out, "installed", c_oil->installed); - - json_object_object_add(json_ifp_in, out_ifname, json_ifp_out); - } else { - if (first_oif) - { - first_oif = 0; - vty_out(vty, "%s(%c%c%c%c)", out_ifname, - (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) ? 'I' : ' ', - (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) ? 'J' : ' ', - (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) ? 'S' : ' ', - (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) ? '*' : ' '); - } - else - vty_out(vty, ", %s(%c%c%c%c)", out_ifname, - (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) ? 'I' : ' ', - (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) ? 'J' : ' ', - (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) ? 'S' : ' ', - (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) ? '*' : ' ' ); - } - } - - if (!uj) - vty_out (vty, "\n"); - } - - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } else { - vty_out (vty, "\n"); - } + struct pim_interface *pim_ifp; + struct in_addr ifaddr; + struct listnode *ch_node; + struct pim_ifchannel *ch; + time_t now; + json_object *json = NULL; + json_object *json_iface = NULL; + json_object *json_row = NULL; + json_object *json_grp = NULL; + + now = pim_time_monotonic_sec(); + + if (uj) + json = json_object_new_object(); + else + vty_out(vty, + "Interface Address Source Group State Uptime Expire Prune\n"); + + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, ch_node, ch)) { + + pim_ifp = ch->interface->info; + + if (!pim_ifp) + continue; + + ifaddr = pim_ifp->primary_address; + + char ch_src_str[INET_ADDRSTRLEN]; + char ch_grp_str[INET_ADDRSTRLEN]; + char uptime[10]; + char expire[10]; + char prune[10]; + + pim_inet4_dump("", ch->sg.src, ch_src_str, + sizeof(ch_src_str)); + pim_inet4_dump("", ch->sg.grp, ch_grp_str, + sizeof(ch_grp_str)); + + pim_time_uptime_begin(uptime, sizeof(uptime), now, + ch->ifjoin_creation); + pim_time_timer_to_mmss(expire, sizeof(expire), + ch->t_ifjoin_expiry_timer); + pim_time_timer_to_mmss(prune, sizeof(prune), + ch->t_ifjoin_prune_pending_timer); + + if (uj) { + json_object_object_get_ex(json, ch->interface->name, + &json_iface); + + if (!json_iface) { + json_iface = json_object_new_object(); + json_object_pim_ifp_add(json_iface, + ch->interface); + json_object_object_add( + json, ch->interface->name, json_iface); + } + + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", ch_src_str); + json_object_string_add(json_row, "group", ch_grp_str); + json_object_string_add(json_row, "upTime", uptime); + json_object_string_add(json_row, "expire", expire); + json_object_string_add(json_row, "prune", prune); + json_object_string_add( + json_row, "channelJoinName", + pim_ifchannel_ifjoin_name(ch->ifjoin_state, + ch->flags)); + if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) + json_object_int_add(json_row, "SGRpt", 1); + + json_object_object_get_ex(json_iface, ch_grp_str, + &json_grp); + if (!json_grp) { + json_grp = json_object_new_object(); + json_object_object_add(json_grp, ch_src_str, + json_row); + json_object_object_add(json_iface, ch_grp_str, + json_grp); + } else + json_object_object_add(json_grp, ch_src_str, + json_row); + } else { + vty_out(vty, + "%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s\n", + ch->interface->name, inet_ntoa(ifaddr), + ch_src_str, ch_grp_str, + pim_ifchannel_ifjoin_name(ch->ifjoin_state, + ch->flags), + uptime, expire, prune); + } + } /* scan interface channels */ + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } +} + +static void pim_show_neighbors_single(struct vty *vty, const char *neighbor, + u_char uj) +{ + struct listnode *node; + struct listnode *neighnode; + struct interface *ifp; + struct pim_interface *pim_ifp; + struct pim_neighbor *neigh; + time_t now; + int found_neighbor = 0; + int option_address_list; + int option_dr_priority; + int option_generation_id; + int option_holdtime; + int option_lan_prune_delay; + int option_t_bit; + char uptime[10]; + char expire[10]; + char neigh_src_str[INET_ADDRSTRLEN]; + + json_object *json = NULL; + json_object *json_ifp = NULL; + json_object *json_row = NULL; + + now = pim_time_monotonic_sec(); + + if (uj) + json = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (pim_ifp->pim_sock_fd < 0) + continue; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, + neigh)) { + pim_inet4_dump("", neigh->source_addr, + neigh_src_str, sizeof(neigh_src_str)); + + /* + * The user can specify either the interface name or the + * PIM neighbor IP. + * If this pim_ifp matches neither then skip. + */ + if (strcmp(neighbor, "detail") + && strcmp(neighbor, ifp->name) + && strcmp(neighbor, neigh_src_str)) + continue; + + found_neighbor = 1; + pim_time_uptime(uptime, sizeof(uptime), + now - neigh->creation); + pim_time_timer_to_hhmmss(expire, sizeof(expire), + neigh->t_expire_timer); + + option_address_list = 0; + option_dr_priority = 0; + option_generation_id = 0; + option_holdtime = 0; + option_lan_prune_delay = 0; + option_t_bit = 0; + + if (PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_ADDRESS_LIST)) + option_address_list = 1; + + if (PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_DR_PRIORITY)) + option_dr_priority = 1; + + if (PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_GENERATION_ID)) + option_generation_id = 1; + + if (PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_HOLDTIME)) + option_holdtime = 1; + + if (PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_LAN_PRUNE_DELAY)) + option_lan_prune_delay = 1; + + if (PIM_OPTION_IS_SET( + neigh->hello_options, + PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION)) + option_t_bit = 1; + + if (uj) { + + /* Does this ifp live in json? If not create + * it. */ + json_object_object_get_ex(json, ifp->name, + &json_ifp); + + if (!json_ifp) { + json_ifp = json_object_new_object(); + json_object_pim_ifp_add(json_ifp, ifp); + json_object_object_add(json, ifp->name, + json_ifp); + } + + json_row = json_object_new_object(); + json_object_string_add(json_row, "interface", + ifp->name); + json_object_string_add(json_row, "address", + neigh_src_str); + json_object_string_add(json_row, "upTime", + uptime); + json_object_string_add(json_row, "holdtime", + expire); + json_object_int_add(json_row, "drPriority", + neigh->dr_priority); + json_object_int_add(json_row, "generationId", + neigh->generation_id); + + if (option_address_list) + json_object_boolean_true_add( + json_row, + "helloOptionAddressList"); + + if (option_dr_priority) + json_object_boolean_true_add( + json_row, + "helloOptionDrPriority"); + + if (option_generation_id) + json_object_boolean_true_add( + json_row, + "helloOptionGenerationId"); + + if (option_holdtime) + json_object_boolean_true_add( + json_row, + "helloOptionHoldtime"); + + if (option_lan_prune_delay) + json_object_boolean_true_add( + json_row, + "helloOptionLanPruneDelay"); + + if (option_t_bit) + json_object_boolean_true_add( + json_row, "helloOptionTBit"); + + json_object_object_add(json_ifp, neigh_src_str, + json_row); + + } else { + vty_out(vty, "Interface : %s\n", ifp->name); + vty_out(vty, "Neighbor : %s\n", neigh_src_str); + vty_out(vty, + " Uptime : %s\n", + uptime); + vty_out(vty, + " Holdtime : %s\n", + expire); + vty_out(vty, + " DR Priority : %d\n", + neigh->dr_priority); + vty_out(vty, + " Generation ID : %08x\n", + neigh->generation_id); + vty_out(vty, + " Override Interval (msec) : %d\n", + neigh->override_interval_msec); + vty_out(vty, + " Propagation Delay (msec) : %d\n", + neigh->propagation_delay_msec); + vty_out(vty, + " Hello Option - Address List : %s\n", + option_address_list ? "yes" : "no"); + vty_out(vty, + " Hello Option - DR Priority : %s\n", + option_dr_priority ? "yes" : "no"); + vty_out(vty, + " Hello Option - Generation ID : %s\n", + option_generation_id ? "yes" : "no"); + vty_out(vty, + " Hello Option - Holdtime : %s\n", + option_holdtime ? "yes" : "no"); + vty_out(vty, + " Hello Option - LAN Prune Delay : %s\n", + option_lan_prune_delay ? "yes" : "no"); + vty_out(vty, + " Hello Option - T-bit : %s\n", + option_t_bit ? "yes" : "no"); + pim_bfd_show_info(vty, neigh->bfd_info, + json_ifp, uj, 0); + vty_out(vty, "\n"); + } + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else { + { + if (!found_neighbor) + vty_out(vty, + "%% No such interface or neighbor\n"); + } + } +} + +static void pim_show_state(struct vty *vty, const char *src_or_group, + const char *group, u_char uj) +{ + struct channel_oil *c_oil; + struct listnode *node; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_ifp_in = NULL; + json_object *json_ifp_out = NULL; + json_object *json_source = NULL; + time_t now; + int first_oif; + now = pim_time_monotonic_sec(); + + if (uj) { + json = json_object_new_object(); + } else { + vty_out(vty, + "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G)"); + vty_out(vty, + "\nInstalled Source Group IIF OIL\n"); + } + + for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { + char grp_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; + char in_ifname[INTERFACE_NAMSIZ + 1]; + char out_ifname[INTERFACE_NAMSIZ + 1]; + int oif_vif_index; + struct interface *ifp_in; + first_oif = 1; + + pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, grp_str, + sizeof(grp_str)); + pim_inet4_dump("", c_oil->oil.mfcc_origin, src_str, + sizeof(src_str)); + ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); + + if (ifp_in) + strcpy(in_ifname, ifp_in->name); + else + strcpy(in_ifname, ""); + + if (src_or_group) { + if (strcmp(src_or_group, src_str) + && strcmp(src_or_group, grp_str)) + continue; + + if (group && strcmp(group, grp_str)) + continue; + } + + if (uj) { + + /* Find the group, create it if it doesn't exist */ + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, + json_group); + } + + /* Find the source nested under the group, create it if + * it doesn't exist */ + json_object_object_get_ex(json_group, src_str, + &json_source); + + if (!json_source) { + json_source = json_object_new_object(); + json_object_object_add(json_group, src_str, + json_source); + } + + /* Find the inbound interface nested under the source, + * create it if it doesn't exist */ + json_object_object_get_ex(json_source, in_ifname, + &json_ifp_in); + + if (!json_ifp_in) { + json_ifp_in = json_object_new_object(); + json_object_object_add(json_source, in_ifname, + json_ifp_in); + json_object_int_add(json_source, "Installed", + c_oil->installed); + json_object_int_add(json_source, "RefCount", + c_oil->oil_ref_count); + json_object_int_add(json_source, "OilListSize", + c_oil->oil_size); + json_object_int_add( + json_source, "OilRescan", + c_oil->oil_inherited_rescan); + json_object_int_add(json_source, "LastUsed", + c_oil->cc.lastused); + json_object_int_add(json_source, "PacketCount", + c_oil->cc.pktcnt); + json_object_int_add(json_source, "ByteCount", + c_oil->cc.bytecnt); + json_object_int_add(json_source, + "WrongInterface", + c_oil->cc.wrong_if); + } + } else { + vty_out(vty, "%-9d %-15s %-15s %-7s ", + c_oil->installed, src_str, grp_str, + ifp_in->name); + } + + for (oif_vif_index = 0; oif_vif_index < MAXVIFS; + ++oif_vif_index) { + struct interface *ifp_out; + char oif_uptime[10]; + int ttl; + + ttl = c_oil->oil.mfcc_ttls[oif_vif_index]; + if (ttl < 1) + continue; + + ifp_out = pim_if_find_by_vif_index(oif_vif_index); + pim_time_uptime( + oif_uptime, sizeof(oif_uptime), + now - c_oil->oif_creation[oif_vif_index]); + + if (ifp_out) + strcpy(out_ifname, ifp_out->name); + else + strcpy(out_ifname, ""); + + if (uj) { + json_ifp_out = json_object_new_object(); + json_object_string_add(json_ifp_out, "source", + src_str); + json_object_string_add(json_ifp_out, "group", + grp_str); + json_object_string_add(json_ifp_out, + "inboundInterface", + in_ifname); + json_object_string_add(json_ifp_out, + "outboundInterface", + out_ifname); + json_object_int_add(json_ifp_out, "installed", + c_oil->installed); + + json_object_object_add(json_ifp_in, out_ifname, + json_ifp_out); + } else { + if (first_oif) { + first_oif = 0; + vty_out(vty, "%s(%c%c%c%c)", out_ifname, + (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_IGMP) + ? 'I' + : ' ', + (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_PIM) + ? 'J' + : ' ', + (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_SOURCE) + ? 'S' + : ' ', + (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_STAR) + ? '*' + : ' '); + } else + vty_out(vty, ", %s(%c%c%c%c)", + out_ifname, + (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_IGMP) + ? 'I' + : ' ', + (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_PIM) + ? 'J' + : ' ', + (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_SOURCE) + ? 'S' + : ' ', + (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_STAR) + ? '*' + : ' '); + } + } + + if (!uj) + vty_out(vty, "\n"); + } + + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else { + vty_out(vty, "\n"); + } } static void pim_show_neighbors(struct vty *vty, u_char uj) { - struct listnode *node; - struct listnode *neighnode; - struct interface *ifp; - struct pim_interface *pim_ifp; - struct pim_neighbor *neigh; - time_t now; - char uptime[10]; - char expire[10]; - char neigh_src_str[INET_ADDRSTRLEN]; - json_object *json = NULL; - json_object *json_ifp_rows = NULL; - json_object *json_row = NULL; - - now = pim_time_monotonic_sec(); - - if (uj) { - json = json_object_new_object(); - } else { - vty_out (vty, "Interface Neighbor Uptime Holdtime DR Pri\n"); - } - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - if (pim_ifp->pim_sock_fd < 0) - continue; - - if (uj) - json_ifp_rows = json_object_new_object(); - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { - pim_inet4_dump("", neigh->source_addr, - neigh_src_str, sizeof(neigh_src_str)); - pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation); - pim_time_timer_to_hhmmss(expire, sizeof(expire), neigh->t_expire_timer); - - if (uj) { - json_row = json_object_new_object(); - json_object_string_add(json_row, "interface", ifp->name); - json_object_string_add(json_row, "neighbor", neigh_src_str); - json_object_string_add(json_row, "upTime", uptime); - json_object_string_add(json_row, "holdTime", expire); - json_object_int_add(json_row, "holdTimeMax", neigh->holdtime); - json_object_int_add(json_row, "drPriority", neigh->dr_priority); - json_object_object_add(json_ifp_rows, neigh_src_str, json_row); - - } else { - vty_out (vty, "%-9s %15s %8s %8s %6d\n", - ifp->name, - neigh_src_str, - uptime, - expire, - neigh->dr_priority); - } - } - - if (uj) { - json_object_object_add(json, ifp->name, json_ifp_rows); - json_ifp_rows = NULL; - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + struct listnode *node; + struct listnode *neighnode; + struct interface *ifp; + struct pim_interface *pim_ifp; + struct pim_neighbor *neigh; + time_t now; + char uptime[10]; + char expire[10]; + char neigh_src_str[INET_ADDRSTRLEN]; + json_object *json = NULL; + json_object *json_ifp_rows = NULL; + json_object *json_row = NULL; + + now = pim_time_monotonic_sec(); + + if (uj) { + json = json_object_new_object(); + } else { + vty_out(vty, + "Interface Neighbor Uptime Holdtime DR Pri\n"); + } + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + if (pim_ifp->pim_sock_fd < 0) + continue; + + if (uj) + json_ifp_rows = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, + neigh)) { + pim_inet4_dump("", neigh->source_addr, + neigh_src_str, sizeof(neigh_src_str)); + pim_time_uptime(uptime, sizeof(uptime), + now - neigh->creation); + pim_time_timer_to_hhmmss(expire, sizeof(expire), + neigh->t_expire_timer); + + if (uj) { + json_row = json_object_new_object(); + json_object_string_add(json_row, "interface", + ifp->name); + json_object_string_add(json_row, "neighbor", + neigh_src_str); + json_object_string_add(json_row, "upTime", + uptime); + json_object_string_add(json_row, "holdTime", + expire); + json_object_int_add(json_row, "holdTimeMax", + neigh->holdtime); + json_object_int_add(json_row, "drPriority", + neigh->dr_priority); + json_object_object_add(json_ifp_rows, + neigh_src_str, json_row); + + } else { + vty_out(vty, "%-9s %15s %8s %8s %6d\n", + ifp->name, neigh_src_str, uptime, + expire, neigh->dr_priority); + } + } + + if (uj) { + json_object_object_add(json, ifp->name, json_ifp_rows); + json_ifp_rows = NULL; + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } static void pim_show_neighbors_secondary(struct vty *vty) { - struct listnode *node; - struct interface *ifp; + struct listnode *node; + struct interface *ifp; - vty_out (vty, - "Interface Address Neighbor Secondary \n"); + vty_out(vty, + "Interface Address Neighbor Secondary \n"); - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - struct pim_interface *pim_ifp; - struct in_addr ifaddr; - struct listnode *neighnode; - struct pim_neighbor *neigh; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + struct pim_interface *pim_ifp; + struct in_addr ifaddr; + struct listnode *neighnode; + struct pim_neighbor *neigh; - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; + pim_ifp = ifp->info; - if (pim_ifp->pim_sock_fd < 0) - continue; + if (!pim_ifp) + continue; - ifaddr = pim_ifp->primary_address; + if (pim_ifp->pim_sock_fd < 0) + continue; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { - char neigh_src_str[INET_ADDRSTRLEN]; - struct listnode *prefix_node; - struct prefix *p; + ifaddr = pim_ifp->primary_address; - if (!neigh->prefix_list) - continue; + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, + neigh)) { + char neigh_src_str[INET_ADDRSTRLEN]; + struct listnode *prefix_node; + struct prefix *p; - pim_inet4_dump("", neigh->source_addr, - neigh_src_str, sizeof(neigh_src_str)); + if (!neigh->prefix_list) + continue; - for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, prefix_node, p)) { - char neigh_sec_str[PREFIX2STR_BUFFER]; + pim_inet4_dump("", neigh->source_addr, + neigh_src_str, sizeof(neigh_src_str)); - prefix2str(p, neigh_sec_str, sizeof(neigh_sec_str)); + for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, + prefix_node, p)) { + char neigh_sec_str[PREFIX2STR_BUFFER]; - vty_out (vty, "%-9s %-15s %-15s %-15s\n", - ifp->name, - inet_ntoa(ifaddr), - neigh_src_str, - neigh_sec_str); - } - } - } + prefix2str(p, neigh_sec_str, + sizeof(neigh_sec_str)); + + vty_out(vty, "%-9s %-15s %-15s %-15s\n", + ifp->name, inet_ntoa(ifaddr), + neigh_src_str, neigh_sec_str); + } + } + } } -static void -json_object_pim_upstream_add (json_object *json, struct pim_upstream *up) +static void json_object_pim_upstream_add(json_object *json, + struct pim_upstream *up) { - if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED) - json_object_boolean_true_add(json, "drJoinDesired"); - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED) - json_object_boolean_true_add(json, "drJoinDesiredUpdated"); + if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED) + json_object_boolean_true_add(json, "drJoinDesired"); - if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) - json_object_boolean_true_add(json, "firstHopRouter"); + if (up->flags & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED) + json_object_boolean_true_add(json, "drJoinDesiredUpdated"); - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) - json_object_boolean_true_add(json, "sourceIgmp"); + if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) + json_object_boolean_true_add(json, "firstHopRouter"); - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_PIM) - json_object_boolean_true_add(json, "sourcePim"); + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) + json_object_boolean_true_add(json, "sourceIgmp"); - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM) - json_object_boolean_true_add(json, "sourceStream"); + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_PIM) + json_object_boolean_true_add(json, "sourcePim"); - /* XXX: need to print ths flag in the plain text display as well */ - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP) - json_object_boolean_true_add(json, "sourceMsdp"); -} + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM) + json_object_boolean_true_add(json, "sourceStream"); -static const char * -pim_upstream_state2brief_str (enum pim_upstream_state join_state, char *state_str) -{ - switch (join_state) - { - case PIM_UPSTREAM_NOTJOINED: - strcpy (state_str, "NotJ"); - break; - case PIM_UPSTREAM_JOINED: - strcpy (state_str, "J"); - break; - default: - strcpy (state_str, "Unk"); - } - return state_str; + /* XXX: need to print ths flag in the plain text display as well */ + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP) + json_object_boolean_true_add(json, "sourceMsdp"); } static const char * -pim_reg_state2brief_str (enum pim_reg_state reg_state, char *state_str) -{ - switch (reg_state) - { - case PIM_REG_NOINFO: - strcpy (state_str, "RegNI"); - break; - case PIM_REG_JOIN: - strcpy (state_str, "RegJ"); - break; - case PIM_REG_JOIN_PENDING: - case PIM_REG_PRUNE: - strcpy (state_str, "RegP"); - break; - default: - strcpy (state_str, "Unk"); - } - return state_str; +pim_upstream_state2brief_str(enum pim_upstream_state join_state, + char *state_str) +{ + switch (join_state) { + case PIM_UPSTREAM_NOTJOINED: + strcpy(state_str, "NotJ"); + break; + case PIM_UPSTREAM_JOINED: + strcpy(state_str, "J"); + break; + default: + strcpy(state_str, "Unk"); + } + return state_str; +} + +static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state, + char *state_str) +{ + switch (reg_state) { + case PIM_REG_NOINFO: + strcpy(state_str, "RegNI"); + break; + case PIM_REG_JOIN: + strcpy(state_str, "RegJ"); + break; + case PIM_REG_JOIN_PENDING: + case PIM_REG_PRUNE: + strcpy(state_str, "RegP"); + break; + default: + strcpy(state_str, "Unk"); + } + return state_str; } static void pim_show_upstream(struct vty *vty, u_char uj) { - struct listnode *upnode; - struct pim_upstream *up; - time_t now; - json_object *json = NULL; - json_object *json_group = NULL; - json_object *json_row = NULL; - - now = pim_time_monotonic_sec(); - - if (uj) - json = json_object_new_object(); - else - vty_out (vty, - "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt\n"); - - for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - char uptime[10]; - char join_timer[10]; - char rs_timer[10]; - char ka_timer[10]; - char msdp_reg_timer[10]; - char state_str[PIM_REG_STATE_STR_LEN]; - - pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); - pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition); - pim_time_timer_to_hhmmss (join_timer, sizeof(join_timer), up->t_join_timer); - - /* - * If we have a J/P timer for the neighbor display that - */ - if (!up->t_join_timer) - { - struct pim_neighbor *nbr; - - nbr = pim_neighbor_find (up->rpf.source_nexthop.interface, - up->rpf.rpf_addr.u.prefix4); - if (nbr) - pim_time_timer_to_hhmmss (join_timer, sizeof(join_timer), nbr->jp_timer); - } - - pim_time_timer_to_hhmmss (rs_timer, sizeof (rs_timer), up->t_rs_timer); - pim_time_timer_to_hhmmss (ka_timer, sizeof (ka_timer), up->t_ka_timer); - pim_time_timer_to_hhmmss (msdp_reg_timer, sizeof (msdp_reg_timer), up->t_msdp_reg_timer); - - pim_upstream_state2brief_str (up->join_state, state_str); - if (up->reg_state != PIM_REG_NOINFO) { - char tmp_str[PIM_REG_STATE_STR_LEN]; - - sprintf (state_str + strlen (state_str), ",%s", - pim_reg_state2brief_str (up->reg_state, tmp_str)); - } - - if (uj) { - json_object_object_get_ex(json, grp_str, &json_group); - - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json, grp_str, json_group); - } - - json_row = json_object_new_object(); - json_object_pim_upstream_add(json_row, up); - json_object_string_add(json_row, "inboundInterface", up->rpf.source_nexthop.interface->name); - json_object_string_add(json_row, "source", src_str); - json_object_string_add(json_row, "group", grp_str); - json_object_string_add(json_row, "state", state_str); - json_object_string_add(json_row, "joinState", pim_upstream_state2str (up->join_state)); - json_object_string_add(json_row, "regState", pim_reg_state2str (up->reg_state, state_str)); - json_object_string_add(json_row, "upTime", uptime); - json_object_string_add(json_row, "joinTimer", join_timer); - json_object_string_add(json_row, "resetTimer", rs_timer); - json_object_string_add(json_row, "keepaliveTimer", ka_timer); - json_object_string_add(json_row, "msdpRegTimer", msdp_reg_timer); - json_object_int_add(json_row, "refCount", up->ref_count); - json_object_int_add(json_row, "sptBit", up->sptbit); - json_object_object_add(json_group, src_str, json_row); - } else { - vty_out (vty, "%-10s%-15s %-15s %-11s %-8s %-9s %-9s %-9s %6d\n", - up->rpf.source_nexthop.interface->name, - src_str, - grp_str, - state_str, - uptime, - join_timer, - rs_timer, - ka_timer, - up->ref_count); - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + struct listnode *upnode; + struct pim_upstream *up; + time_t now; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_row = NULL; + + now = pim_time_monotonic_sec(); + + if (uj) + json = json_object_new_object(); + else + vty_out(vty, + "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt\n"); + + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + char uptime[10]; + char join_timer[10]; + char rs_timer[10]; + char ka_timer[10]; + char msdp_reg_timer[10]; + char state_str[PIM_REG_STATE_STR_LEN]; + + pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); + pim_time_uptime(uptime, sizeof(uptime), + now - up->state_transition); + pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer), + up->t_join_timer); + + /* + * If we have a J/P timer for the neighbor display that + */ + if (!up->t_join_timer) { + struct pim_neighbor *nbr; + + nbr = pim_neighbor_find( + up->rpf.source_nexthop.interface, + up->rpf.rpf_addr.u.prefix4); + if (nbr) + pim_time_timer_to_hhmmss(join_timer, + sizeof(join_timer), + nbr->jp_timer); + } + + pim_time_timer_to_hhmmss(rs_timer, sizeof(rs_timer), + up->t_rs_timer); + pim_time_timer_to_hhmmss(ka_timer, sizeof(ka_timer), + up->t_ka_timer); + pim_time_timer_to_hhmmss(msdp_reg_timer, sizeof(msdp_reg_timer), + up->t_msdp_reg_timer); + + pim_upstream_state2brief_str(up->join_state, state_str); + if (up->reg_state != PIM_REG_NOINFO) { + char tmp_str[PIM_REG_STATE_STR_LEN]; + + sprintf(state_str + strlen(state_str), ",%s", + pim_reg_state2brief_str(up->reg_state, + tmp_str)); + } + + if (uj) { + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, + json_group); + } + + json_row = json_object_new_object(); + json_object_pim_upstream_add(json_row, up); + json_object_string_add( + json_row, "inboundInterface", + up->rpf.source_nexthop.interface->name); + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + json_object_string_add(json_row, "state", state_str); + json_object_string_add( + json_row, "joinState", + pim_upstream_state2str(up->join_state)); + json_object_string_add( + json_row, "regState", + pim_reg_state2str(up->reg_state, state_str)); + json_object_string_add(json_row, "upTime", uptime); + json_object_string_add(json_row, "joinTimer", + join_timer); + json_object_string_add(json_row, "resetTimer", + rs_timer); + json_object_string_add(json_row, "keepaliveTimer", + ka_timer); + json_object_string_add(json_row, "msdpRegTimer", + msdp_reg_timer); + json_object_int_add(json_row, "refCount", + up->ref_count); + json_object_int_add(json_row, "sptBit", up->sptbit); + json_object_object_add(json_group, src_str, json_row); + } else { + vty_out(vty, + "%-10s%-15s %-15s %-11s %-8s %-9s %-9s %-9s %6d\n", + up->rpf.source_nexthop.interface->name, src_str, + grp_str, state_str, uptime, join_timer, + rs_timer, ka_timer, up->ref_count); + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } static void pim_show_join_desired(struct vty *vty, u_char uj) { - struct listnode *chnode; - struct pim_interface *pim_ifp; - struct pim_ifchannel *ch; - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - json_object *json = NULL; - json_object *json_group = NULL; - json_object *json_row = NULL; - - if (uj) - json = json_object_new_object(); - else - vty_out (vty, - "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD\n"); - - /* scan per-interface (S,G) state */ - for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, chnode, ch)) { - /* scan all interfaces */ - pim_ifp = ch->interface->info; - if (!pim_ifp) - continue; - - struct pim_upstream *up = ch->upstream; - - pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); - - if (uj) { - json_object_object_get_ex(json, grp_str, &json_group); - - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json, grp_str, json_group); - } - - json_row = json_object_new_object(); - json_object_pim_upstream_add(json_row, up); - json_object_string_add(json_row, "interface", ch->interface->name); - json_object_string_add(json_row, "source", src_str); - json_object_string_add(json_row, "group", grp_str); - - if (pim_macro_ch_lost_assert(ch)) - json_object_boolean_true_add(json_row, "lostAssert"); - - if (pim_macro_chisin_joins(ch)) - json_object_boolean_true_add(json_row, "joins"); - - if (pim_macro_chisin_pim_include(ch)) - json_object_boolean_true_add(json_row, "pimInclude"); - - if (pim_upstream_evaluate_join_desired(up)) - json_object_boolean_true_add(json_row, "evaluateJoinDesired"); - - json_object_object_add(json_group, src_str, json_row); - - } else { - vty_out (vty, "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s\n", - ch->interface->name, - src_str, - grp_str, - pim_macro_ch_lost_assert(ch) ? "yes" : "no", - pim_macro_chisin_joins(ch) ? "yes" : "no", - pim_macro_chisin_pim_include(ch) ? "yes" : "no", - PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags) ? "yes" : "no", - pim_upstream_evaluate_join_desired(up) ? "yes" : "no"); - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + struct listnode *chnode; + struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_row = NULL; + + if (uj) + json = json_object_new_object(); + else + vty_out(vty, + "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD\n"); + + /* scan per-interface (S,G) state */ + for (ALL_LIST_ELEMENTS_RO(pim_ifchannel_list, chnode, ch)) { + /* scan all interfaces */ + pim_ifp = ch->interface->info; + if (!pim_ifp) + continue; + + struct pim_upstream *up = ch->upstream; + + pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); + + if (uj) { + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, + json_group); + } + + json_row = json_object_new_object(); + json_object_pim_upstream_add(json_row, up); + json_object_string_add(json_row, "interface", + ch->interface->name); + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + + if (pim_macro_ch_lost_assert(ch)) + json_object_boolean_true_add(json_row, + "lostAssert"); + + if (pim_macro_chisin_joins(ch)) + json_object_boolean_true_add(json_row, "joins"); + + if (pim_macro_chisin_pim_include(ch)) + json_object_boolean_true_add(json_row, + "pimInclude"); + + if (pim_upstream_evaluate_join_desired(up)) + json_object_boolean_true_add( + json_row, "evaluateJoinDesired"); + + json_object_object_add(json_group, src_str, json_row); + + } else { + vty_out(vty, + "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s\n", + ch->interface->name, src_str, grp_str, + pim_macro_ch_lost_assert(ch) ? "yes" : "no", + pim_macro_chisin_joins(ch) ? "yes" : "no", + pim_macro_chisin_pim_include(ch) ? "yes" : "no", + PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED( + up->flags) + ? "yes" + : "no", + pim_upstream_evaluate_join_desired(up) ? "yes" + : "no"); + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } static void pim_show_upstream_rpf(struct vty *vty, u_char uj) { - struct listnode *upnode; - struct pim_upstream *up; - json_object *json = NULL; - json_object *json_group = NULL; - json_object *json_row = NULL; - - if (uj) - json = json_object_new_object(); - else - vty_out (vty, - "Source Group RpfIface RibNextHop RpfAddress \n"); - - for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - char rpf_nexthop_str[PREFIX_STRLEN]; - char rpf_addr_str[PREFIX_STRLEN]; - struct pim_rpf *rpf; - const char *rpf_ifname; - - rpf = &up->rpf; - - pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); - pim_addr_dump("", &rpf->source_nexthop.mrib_nexthop_addr, rpf_nexthop_str, sizeof(rpf_nexthop_str)); - pim_addr_dump("", &rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); - - rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : ""; - - if (uj) { - json_object_object_get_ex(json, grp_str, &json_group); - - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json, grp_str, json_group); - } - - json_row = json_object_new_object(); - json_object_pim_upstream_add(json_row, up); - json_object_string_add(json_row, "source", src_str); - json_object_string_add(json_row, "group", grp_str); - json_object_string_add(json_row, "rpfInterface", rpf_ifname); - json_object_string_add(json_row, "ribNexthop", rpf_nexthop_str); - json_object_string_add(json_row, "rpfAddress", rpf_addr_str); - json_object_object_add(json_group, src_str, json_row); - } else { - vty_out (vty, "%-15s %-15s %-8s %-15s %-15s\n", - src_str, - grp_str, - rpf_ifname, - rpf_nexthop_str, - rpf_addr_str); - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } -} - -static void show_rpf_refresh_stats(struct vty *vty, time_t now, json_object *json) -{ - char refresh_uptime[10]; - - pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now, qpim_rpf_cache_refresh_last); - - if (json) { - json_object_int_add(json, "rpfCacheRefreshDelayMsecs", qpim_rpf_cache_refresh_delay_msec); - json_object_int_add(json, "rpfCacheRefreshTimer", pim_time_timer_remain_msec(qpim_rpf_cache_refresher)); - json_object_int_add(json, "rpfCacheRefreshRequests", qpim_rpf_cache_refresh_requests); - json_object_int_add(json, "rpfCacheRefreshEvents", qpim_rpf_cache_refresh_events); - json_object_string_add(json, "rpfCacheRefreshLast", refresh_uptime); - json_object_int_add(json, "nexthopLookups", qpim_nexthop_lookups); - json_object_int_add(json, "nexthopLookupsAvoided", nexthop_lookups_avoided); - } else { - vty_out (vty, - "RPF Cache Refresh Delay: %ld msecs\n" - "RPF Cache Refresh Timer: %ld msecs\n" - "RPF Cache Refresh Requests: %lld\n" - "RPF Cache Refresh Events: %lld\n" - "RPF Cache Refresh Last: %s\n" - "Nexthop Lookups: %lld\n" - "Nexthop Lookups Avoided: %lld\n", - qpim_rpf_cache_refresh_delay_msec, - pim_time_timer_remain_msec(qpim_rpf_cache_refresher), - (long long)qpim_rpf_cache_refresh_requests, - (long long)qpim_rpf_cache_refresh_events, - refresh_uptime, - (long long) qpim_nexthop_lookups, - (long long)nexthop_lookups_avoided); - } + struct listnode *upnode; + struct pim_upstream *up; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_row = NULL; + + if (uj) + json = json_object_new_object(); + else + vty_out(vty, + "Source Group RpfIface RibNextHop RpfAddress \n"); + + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + char rpf_nexthop_str[PREFIX_STRLEN]; + char rpf_addr_str[PREFIX_STRLEN]; + struct pim_rpf *rpf; + const char *rpf_ifname; + + rpf = &up->rpf; + + pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); + pim_addr_dump("", + &rpf->source_nexthop.mrib_nexthop_addr, + rpf_nexthop_str, sizeof(rpf_nexthop_str)); + pim_addr_dump("", &rpf->rpf_addr, rpf_addr_str, + sizeof(rpf_addr_str)); + + rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : ""; + + if (uj) { + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, + json_group); + } + + json_row = json_object_new_object(); + json_object_pim_upstream_add(json_row, up); + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + json_object_string_add(json_row, "rpfInterface", + rpf_ifname); + json_object_string_add(json_row, "ribNexthop", + rpf_nexthop_str); + json_object_string_add(json_row, "rpfAddress", + rpf_addr_str); + json_object_object_add(json_group, src_str, json_row); + } else { + vty_out(vty, "%-15s %-15s %-8s %-15s %-15s\n", src_str, + grp_str, rpf_ifname, rpf_nexthop_str, + rpf_addr_str); + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } +} + +static void show_rpf_refresh_stats(struct vty *vty, time_t now, + json_object *json) +{ + char refresh_uptime[10]; + + pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now, + qpim_rpf_cache_refresh_last); + + if (json) { + json_object_int_add(json, "rpfCacheRefreshDelayMsecs", + qpim_rpf_cache_refresh_delay_msec); + json_object_int_add( + json, "rpfCacheRefreshTimer", + pim_time_timer_remain_msec(qpim_rpf_cache_refresher)); + json_object_int_add(json, "rpfCacheRefreshRequests", + qpim_rpf_cache_refresh_requests); + json_object_int_add(json, "rpfCacheRefreshEvents", + qpim_rpf_cache_refresh_events); + json_object_string_add(json, "rpfCacheRefreshLast", + refresh_uptime); + json_object_int_add(json, "nexthopLookups", + qpim_nexthop_lookups); + json_object_int_add(json, "nexthopLookupsAvoided", + nexthop_lookups_avoided); + } else { + vty_out(vty, + "RPF Cache Refresh Delay: %ld msecs\n" + "RPF Cache Refresh Timer: %ld msecs\n" + "RPF Cache Refresh Requests: %lld\n" + "RPF Cache Refresh Events: %lld\n" + "RPF Cache Refresh Last: %s\n" + "Nexthop Lookups: %lld\n" + "Nexthop Lookups Avoided: %lld\n", + qpim_rpf_cache_refresh_delay_msec, + pim_time_timer_remain_msec(qpim_rpf_cache_refresher), + (long long)qpim_rpf_cache_refresh_requests, + (long long)qpim_rpf_cache_refresh_events, + refresh_uptime, (long long)qpim_nexthop_lookups, + (long long)nexthop_lookups_avoided); + } } static void show_scan_oil_stats(struct vty *vty, time_t now) { - char uptime_scan_oil[10]; - char uptime_mroute_add[10]; - char uptime_mroute_del[10]; + char uptime_scan_oil[10]; + char uptime_mroute_add[10]; + char uptime_mroute_del[10]; - pim_time_uptime_begin(uptime_scan_oil, sizeof(uptime_scan_oil), now, qpim_scan_oil_last); - pim_time_uptime_begin(uptime_mroute_add, sizeof(uptime_mroute_add), now, qpim_mroute_add_last); - pim_time_uptime_begin(uptime_mroute_del, sizeof(uptime_mroute_del), now, qpim_mroute_del_last); + pim_time_uptime_begin(uptime_scan_oil, sizeof(uptime_scan_oil), now, + qpim_scan_oil_last); + pim_time_uptime_begin(uptime_mroute_add, sizeof(uptime_mroute_add), now, + qpim_mroute_add_last); + pim_time_uptime_begin(uptime_mroute_del, sizeof(uptime_mroute_del), now, + qpim_mroute_del_last); - vty_out (vty, - "Scan OIL - Last: %s Events: %lld\n" - "MFC Add - Last: %s Events: %lld\n" - "MFC Del - Last: %s Events: %lld\n", - uptime_scan_oil, (long long) qpim_scan_oil_events, - uptime_mroute_add, (long long) qpim_mroute_add_events, - uptime_mroute_del, (long long)qpim_mroute_del_events); + vty_out(vty, + "Scan OIL - Last: %s Events: %lld\n" + "MFC Add - Last: %s Events: %lld\n" + "MFC Del - Last: %s Events: %lld\n", + uptime_scan_oil, (long long)qpim_scan_oil_events, + uptime_mroute_add, (long long)qpim_mroute_add_events, + uptime_mroute_del, (long long)qpim_mroute_del_events); } static void pim_show_rpf(struct vty *vty, u_char uj) { - struct listnode *up_node; - struct pim_upstream *up; - time_t now = pim_time_monotonic_sec(); - json_object *json = NULL; - json_object *json_group = NULL; - json_object *json_row = NULL; - - if (uj) { - json = json_object_new_object(); - show_rpf_refresh_stats(vty, now, json); - } else { - show_rpf_refresh_stats(vty, now, json); - vty_out (vty, "\n"); - vty_out (vty, - "Source Group RpfIface RpfAddress RibNextHop Metric Pref\n"); - } - - for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, up_node, up)) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - char rpf_addr_str[PREFIX_STRLEN]; - char rib_nexthop_str[PREFIX_STRLEN]; - const char *rpf_ifname; - struct pim_rpf *rpf = &up->rpf; - - pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); - pim_addr_dump("", &rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); - pim_addr_dump("", &rpf->source_nexthop.mrib_nexthop_addr, rib_nexthop_str, sizeof(rib_nexthop_str)); - - rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : ""; - - if (uj) { - json_object_object_get_ex(json, grp_str, &json_group); - - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json, grp_str, json_group); - } - - json_row = json_object_new_object(); - json_object_string_add(json_row, "source", src_str); - json_object_string_add(json_row, "group", grp_str); - json_object_string_add(json_row, "rpfInterface", rpf_ifname); - json_object_string_add(json_row, "rpfAddress", rpf_addr_str); - json_object_string_add(json_row, "ribNexthop", rib_nexthop_str); - json_object_int_add(json_row, "routeMetric", rpf->source_nexthop.mrib_route_metric); - json_object_int_add(json_row, "routePreference", rpf->source_nexthop.mrib_metric_preference); - json_object_object_add(json_group, src_str, json_row); - - } else { - vty_out (vty, "%-15s %-15s %-8s %-15s %-15s %6d %4d\n", - src_str, - grp_str, - rpf_ifname, - rpf_addr_str, - rib_nexthop_str, - rpf->source_nexthop.mrib_route_metric, - rpf->source_nexthop.mrib_metric_preference); - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } -} - -static int -pim_print_pnc_cache_walkcb (struct hash_backet *backet, void *arg) -{ - struct pim_nexthop_cache *pnc = backet->data; - struct vty *vty = arg; - struct nexthop *nh_node = NULL; - ifindex_t first_ifindex; - struct interface *ifp = NULL; - - if (!pnc) - return CMD_SUCCESS; - - for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) - { - first_ifindex = nh_node->ifindex; - ifp = if_lookup_by_index (first_ifindex, VRF_DEFAULT); - - vty_out (vty, "%-15s ", inet_ntoa (pnc->rpf.rpf_addr.u.prefix4)); - vty_out (vty, "%-14s ", ifp ? ifp->name : "NULL"); - vty_out (vty, "%s ", inet_ntoa (nh_node->gate.ipv4)); - vty_out (vty, "\n"); - } - return CMD_SUCCESS; -} - -static void -pim_show_nexthop (struct vty *vty) -{ - - if (pimg && !pimg->rpf_hash) - { - vty_out (vty, "no nexthop cache \n"); - return; - } - - vty_out (vty, "Number of registered addresses: %lu \n", - pimg->rpf_hash->count); - vty_out (vty, "Address Interface Nexthop\n"); - vty_out (vty, "-------------------------------------------\n"); - - hash_walk (pimg->rpf_hash, pim_print_pnc_cache_walkcb, vty); + struct listnode *up_node; + struct pim_upstream *up; + time_t now = pim_time_monotonic_sec(); + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_row = NULL; + + if (uj) { + json = json_object_new_object(); + show_rpf_refresh_stats(vty, now, json); + } else { + show_rpf_refresh_stats(vty, now, json); + vty_out(vty, "\n"); + vty_out(vty, + "Source Group RpfIface RpfAddress RibNextHop Metric Pref\n"); + } + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, up_node, up)) { + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + char rpf_addr_str[PREFIX_STRLEN]; + char rib_nexthop_str[PREFIX_STRLEN]; + const char *rpf_ifname; + struct pim_rpf *rpf = &up->rpf; + + pim_inet4_dump("", up->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", up->sg.grp, grp_str, sizeof(grp_str)); + pim_addr_dump("", &rpf->rpf_addr, rpf_addr_str, + sizeof(rpf_addr_str)); + pim_addr_dump("", + &rpf->source_nexthop.mrib_nexthop_addr, + rib_nexthop_str, sizeof(rib_nexthop_str)); + + rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : ""; + + if (uj) { + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, + json_group); + } + + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + json_object_string_add(json_row, "rpfInterface", + rpf_ifname); + json_object_string_add(json_row, "rpfAddress", + rpf_addr_str); + json_object_string_add(json_row, "ribNexthop", + rib_nexthop_str); + json_object_int_add( + json_row, "routeMetric", + rpf->source_nexthop.mrib_route_metric); + json_object_int_add( + json_row, "routePreference", + rpf->source_nexthop.mrib_metric_preference); + json_object_object_add(json_group, src_str, json_row); + + } else { + vty_out(vty, "%-15s %-15s %-8s %-15s %-15s %6d %4d\n", + src_str, grp_str, rpf_ifname, rpf_addr_str, + rib_nexthop_str, + rpf->source_nexthop.mrib_route_metric, + rpf->source_nexthop.mrib_metric_preference); + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } -static void igmp_show_groups(struct vty *vty, u_char uj) +static int pim_print_pnc_cache_walkcb(struct hash_backet *backet, void *arg) { - struct listnode *ifnode; - struct interface *ifp; - time_t now; - json_object *json = NULL; - json_object *json_iface = NULL; - json_object *json_row = NULL; - - now = pim_time_monotonic_sec(); - - if (uj) - json = json_object_new_object(); - else - vty_out (vty, - "Interface Address Group Mode Timer Srcs V Uptime \n"); - - /* scan interfaces */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { - struct pim_interface *pim_ifp = ifp->info; - struct listnode *sock_node; - struct igmp_sock *igmp; - - if (!pim_ifp) - continue; - - /* scan igmp sockets */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - char ifaddr_str[INET_ADDRSTRLEN]; - struct listnode *grpnode; - struct igmp_group *grp; - - pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - - /* scan igmp groups */ - for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) { - char group_str[INET_ADDRSTRLEN]; - char hhmmss[10]; - char uptime[10]; + struct pim_nexthop_cache *pnc = backet->data; + struct vty *vty = arg; + struct nexthop *nh_node = NULL; + ifindex_t first_ifindex; + struct interface *ifp = NULL; + + if (!pnc) + return CMD_SUCCESS; + + for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) { + first_ifindex = nh_node->ifindex; + ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); + + vty_out(vty, "%-15s ", inet_ntoa(pnc->rpf.rpf_addr.u.prefix4)); + vty_out(vty, "%-14s ", ifp ? ifp->name : "NULL"); + vty_out(vty, "%s ", inet_ntoa(nh_node->gate.ipv4)); + vty_out(vty, "\n"); + } + return CMD_SUCCESS; +} + +static void pim_show_nexthop(struct vty *vty) +{ + + if (pimg && !pimg->rpf_hash) { + vty_out(vty, "no nexthop cache \n"); + return; + } + + vty_out(vty, "Number of registered addresses: %lu \n", + pimg->rpf_hash->count); + vty_out(vty, "Address Interface Nexthop\n"); + vty_out(vty, "-------------------------------------------\n"); - pim_inet4_dump("", grp->group_addr, group_str, sizeof(group_str)); - pim_time_timer_to_hhmmss(hhmmss, sizeof(hhmmss), grp->t_group_timer); - pim_time_uptime(uptime, sizeof(uptime), now - grp->group_creation); - - if (uj) { - json_object_object_get_ex(json, ifp->name, &json_iface); - - if (!json_iface) { - json_iface = json_object_new_object(); - json_object_pim_ifp_add(json_iface, ifp); - json_object_object_add(json, ifp->name, json_iface); - } - - json_row = json_object_new_object(); - json_object_string_add(json_row, "source", ifaddr_str); - json_object_string_add(json_row, "group", group_str); - - if (grp->igmp_version == 3) - json_object_string_add(json_row, "mode", grp->group_filtermode_isexcl ? "EXCLUDE" : "INCLUDE"); - - json_object_string_add(json_row, "timer", hhmmss); - json_object_int_add(json_row, "sourcesCount", grp->group_source_list ? listcount(grp->group_source_list) : 0); - json_object_int_add(json_row, "version", grp->igmp_version); - json_object_string_add(json_row, "uptime", uptime); - json_object_object_add(json_iface, group_str, json_row); - - } else { - vty_out (vty, "%-9s %-15s %-15s %4s %8s %4d %d %8s\n", - ifp->name, - ifaddr_str, - group_str, - grp->igmp_version == 3 ? (grp->group_filtermode_isexcl ? "EXCL" : "INCL") : "----", - hhmmss, - grp->group_source_list ? listcount(grp->group_source_list) : 0, - grp->igmp_version, - uptime); - } - } /* scan igmp groups */ - } /* scan igmp sockets */ - } /* scan interfaces */ - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + hash_walk(pimg->rpf_hash, pim_print_pnc_cache_walkcb, vty); +} + +static void igmp_show_groups(struct vty *vty, u_char uj) +{ + struct listnode *ifnode; + struct interface *ifp; + time_t now; + json_object *json = NULL; + json_object *json_iface = NULL; + json_object *json_row = NULL; + + now = pim_time_monotonic_sec(); + + if (uj) + json = json_object_new_object(); + else + vty_out(vty, + "Interface Address Group Mode Timer Srcs V Uptime \n"); + + /* scan interfaces */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { + struct pim_interface *pim_ifp = ifp->info; + struct listnode *sock_node; + struct igmp_sock *igmp; + + if (!pim_ifp) + continue; + + /* scan igmp sockets */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, + igmp)) { + char ifaddr_str[INET_ADDRSTRLEN]; + struct listnode *grpnode; + struct igmp_group *grp; + + pim_inet4_dump("", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + + /* scan igmp groups */ + for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, + grpnode, grp)) { + char group_str[INET_ADDRSTRLEN]; + char hhmmss[10]; + char uptime[10]; + + pim_inet4_dump("", grp->group_addr, + group_str, sizeof(group_str)); + pim_time_timer_to_hhmmss(hhmmss, sizeof(hhmmss), + grp->t_group_timer); + pim_time_uptime(uptime, sizeof(uptime), + now - grp->group_creation); + + if (uj) { + json_object_object_get_ex( + json, ifp->name, &json_iface); + + if (!json_iface) { + json_iface = + json_object_new_object(); + json_object_pim_ifp_add( + json_iface, ifp); + json_object_object_add( + json, ifp->name, + json_iface); + } + + json_row = json_object_new_object(); + json_object_string_add( + json_row, "source", ifaddr_str); + json_object_string_add( + json_row, "group", group_str); + + if (grp->igmp_version == 3) + json_object_string_add( + json_row, "mode", + grp->group_filtermode_isexcl + ? "EXCLUDE" + : "INCLUDE"); + + json_object_string_add(json_row, + "timer", hhmmss); + json_object_int_add( + json_row, "sourcesCount", + grp->group_source_list + ? listcount( + grp->group_source_list) + : 0); + json_object_int_add(json_row, "version", + grp->igmp_version); + json_object_string_add( + json_row, "uptime", uptime); + json_object_object_add(json_iface, + group_str, + json_row); + + } else { + vty_out(vty, + "%-9s %-15s %-15s %4s %8s %4d %d %8s\n", + ifp->name, ifaddr_str, + group_str, + grp->igmp_version == 3 + ? (grp->group_filtermode_isexcl + ? "EXCL" + : "INCL") + : "----", + hhmmss, + grp->group_source_list + ? listcount( + grp->group_source_list) + : 0, + grp->igmp_version, uptime); + } + } /* scan igmp groups */ + } /* scan igmp sockets */ + } /* scan interfaces */ + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } static void igmp_show_group_retransmission(struct vty *vty) { - struct listnode *ifnode; - struct interface *ifp; - - vty_out (vty, - "Interface Address Group RetTimer Counter RetSrcs\n"); - - /* scan interfaces */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { - struct pim_interface *pim_ifp = ifp->info; - struct listnode *sock_node; - struct igmp_sock *igmp; - - if (!pim_ifp) - continue; - - /* scan igmp sockets */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - char ifaddr_str[INET_ADDRSTRLEN]; - struct listnode *grpnode; - struct igmp_group *grp; - - pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - - /* scan igmp groups */ - for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) { - char group_str[INET_ADDRSTRLEN]; - char grp_retr_mmss[10]; - struct listnode *src_node; - struct igmp_source *src; - int grp_retr_sources = 0; - - pim_inet4_dump("", grp->group_addr, group_str, sizeof(group_str)); - pim_time_timer_to_mmss(grp_retr_mmss, sizeof(grp_retr_mmss), grp->t_group_query_retransmit_timer); - - - /* count group sources with retransmission state */ - for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, src_node, src)) { - if (src->source_query_retransmit_count > 0) { - ++grp_retr_sources; - } - } - - vty_out (vty, "%-9s %-15s %-15s %-8s %7d %7d\n", - ifp->name, - ifaddr_str, - group_str, - grp_retr_mmss, - grp->group_specific_query_retransmit_count, - grp_retr_sources); - - } /* scan igmp groups */ - } /* scan igmp sockets */ - } /* scan interfaces */ + struct listnode *ifnode; + struct interface *ifp; + + vty_out(vty, + "Interface Address Group RetTimer Counter RetSrcs\n"); + + /* scan interfaces */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { + struct pim_interface *pim_ifp = ifp->info; + struct listnode *sock_node; + struct igmp_sock *igmp; + + if (!pim_ifp) + continue; + + /* scan igmp sockets */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, + igmp)) { + char ifaddr_str[INET_ADDRSTRLEN]; + struct listnode *grpnode; + struct igmp_group *grp; + + pim_inet4_dump("", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + + /* scan igmp groups */ + for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, + grpnode, grp)) { + char group_str[INET_ADDRSTRLEN]; + char grp_retr_mmss[10]; + struct listnode *src_node; + struct igmp_source *src; + int grp_retr_sources = 0; + + pim_inet4_dump("", grp->group_addr, + group_str, sizeof(group_str)); + pim_time_timer_to_mmss( + grp_retr_mmss, sizeof(grp_retr_mmss), + grp->t_group_query_retransmit_timer); + + + /* count group sources with retransmission state + */ + for (ALL_LIST_ELEMENTS_RO( + grp->group_source_list, src_node, + src)) { + if (src->source_query_retransmit_count + > 0) { + ++grp_retr_sources; + } + } + + vty_out(vty, "%-9s %-15s %-15s %-8s %7d %7d\n", + ifp->name, ifaddr_str, group_str, + grp_retr_mmss, + grp->group_specific_query_retransmit_count, + grp_retr_sources); + + } /* scan igmp groups */ + } /* scan igmp sockets */ + } /* scan interfaces */ } static void igmp_show_sources(struct vty *vty) { - struct listnode *ifnode; - struct interface *ifp; - time_t now; - - now = pim_time_monotonic_sec(); - - vty_out (vty, - "Interface Address Group Source Timer Fwd Uptime \n"); - - /* scan interfaces */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { - struct pim_interface *pim_ifp = ifp->info; - struct listnode *sock_node; - struct igmp_sock *igmp; - - if (!pim_ifp) - continue; - - /* scan igmp sockets */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - char ifaddr_str[INET_ADDRSTRLEN]; - struct listnode *grpnode; - struct igmp_group *grp; - - pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - - /* scan igmp groups */ - for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) { - char group_str[INET_ADDRSTRLEN]; - struct listnode *srcnode; - struct igmp_source *src; - - pim_inet4_dump("", grp->group_addr, group_str, sizeof(group_str)); - - /* scan group sources */ - for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) { - char source_str[INET_ADDRSTRLEN]; - char mmss[10]; - char uptime[10]; - - pim_inet4_dump("", src->source_addr, source_str, sizeof(source_str)); - - pim_time_timer_to_mmss(mmss, sizeof(mmss), src->t_source_timer); - - pim_time_uptime(uptime, sizeof(uptime), now - src->source_creation); - - vty_out (vty, "%-9s %-15s %-15s %-15s %5s %3s %8s\n", - ifp->name, - ifaddr_str, - group_str, - source_str, - mmss, - IGMP_SOURCE_TEST_FORWARDING(src->source_flags) ? "Y" : "N", - uptime); - - } /* scan group sources */ - } /* scan igmp groups */ - } /* scan igmp sockets */ - } /* scan interfaces */ + struct listnode *ifnode; + struct interface *ifp; + time_t now; + + now = pim_time_monotonic_sec(); + + vty_out(vty, + "Interface Address Group Source Timer Fwd Uptime \n"); + + /* scan interfaces */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { + struct pim_interface *pim_ifp = ifp->info; + struct listnode *sock_node; + struct igmp_sock *igmp; + + if (!pim_ifp) + continue; + + /* scan igmp sockets */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, + igmp)) { + char ifaddr_str[INET_ADDRSTRLEN]; + struct listnode *grpnode; + struct igmp_group *grp; + + pim_inet4_dump("", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + + /* scan igmp groups */ + for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, + grpnode, grp)) { + char group_str[INET_ADDRSTRLEN]; + struct listnode *srcnode; + struct igmp_source *src; + + pim_inet4_dump("", grp->group_addr, + group_str, sizeof(group_str)); + + /* scan group sources */ + for (ALL_LIST_ELEMENTS_RO( + grp->group_source_list, srcnode, + src)) { + char source_str[INET_ADDRSTRLEN]; + char mmss[10]; + char uptime[10]; + + pim_inet4_dump( + "", src->source_addr, + source_str, sizeof(source_str)); + + pim_time_timer_to_mmss( + mmss, sizeof(mmss), + src->t_source_timer); + + pim_time_uptime( + uptime, sizeof(uptime), + now - src->source_creation); + + vty_out(vty, + "%-9s %-15s %-15s %-15s %5s %3s %8s\n", + ifp->name, ifaddr_str, + group_str, source_str, mmss, + IGMP_SOURCE_TEST_FORWARDING( + src->source_flags) + ? "Y" + : "N", + uptime); + + } /* scan group sources */ + } /* scan igmp groups */ + } /* scan igmp sockets */ + } /* scan interfaces */ } static void igmp_show_source_retransmission(struct vty *vty) { - struct listnode *ifnode; - struct interface *ifp; - - vty_out (vty, - "Interface Address Group Source Counter\n"); - - /* scan interfaces */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { - struct pim_interface *pim_ifp = ifp->info; - struct listnode *sock_node; - struct igmp_sock *igmp; - - if (!pim_ifp) - continue; - - /* scan igmp sockets */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - char ifaddr_str[INET_ADDRSTRLEN]; - struct listnode *grpnode; - struct igmp_group *grp; - - pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - - /* scan igmp groups */ - for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) { - char group_str[INET_ADDRSTRLEN]; - struct listnode *srcnode; - struct igmp_source *src; - - pim_inet4_dump("", grp->group_addr, group_str, sizeof(group_str)); - - /* scan group sources */ - for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) { - char source_str[INET_ADDRSTRLEN]; - - pim_inet4_dump("", src->source_addr, source_str, sizeof(source_str)); - - vty_out (vty, "%-9s %-15s %-15s %-15s %7d\n", - ifp->name, - ifaddr_str, - group_str, - source_str, - src->source_query_retransmit_count); - - } /* scan group sources */ - } /* scan igmp groups */ - } /* scan igmp sockets */ - } /* scan interfaces */ + struct listnode *ifnode; + struct interface *ifp; + + vty_out(vty, + "Interface Address Group Source Counter\n"); + + /* scan interfaces */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { + struct pim_interface *pim_ifp = ifp->info; + struct listnode *sock_node; + struct igmp_sock *igmp; + + if (!pim_ifp) + continue; + + /* scan igmp sockets */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, + igmp)) { + char ifaddr_str[INET_ADDRSTRLEN]; + struct listnode *grpnode; + struct igmp_group *grp; + + pim_inet4_dump("", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + + /* scan igmp groups */ + for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, + grpnode, grp)) { + char group_str[INET_ADDRSTRLEN]; + struct listnode *srcnode; + struct igmp_source *src; + + pim_inet4_dump("", grp->group_addr, + group_str, sizeof(group_str)); + + /* scan group sources */ + for (ALL_LIST_ELEMENTS_RO( + grp->group_source_list, srcnode, + src)) { + char source_str[INET_ADDRSTRLEN]; + + pim_inet4_dump( + "", src->source_addr, + source_str, sizeof(source_str)); + + vty_out(vty, + "%-9s %-15s %-15s %-15s %7d\n", + ifp->name, ifaddr_str, + group_str, source_str, + src->source_query_retransmit_count); + + } /* scan group sources */ + } /* scan igmp groups */ + } /* scan igmp sockets */ + } /* scan interfaces */ } static void clear_igmp_interfaces() { - struct listnode *ifnode; - struct listnode *ifnextnode; - struct interface *ifp; + struct listnode *ifnode; + struct listnode *ifnextnode; + struct interface *ifp; - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { - pim_if_addr_del_all_igmp(ifp); - } + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode, + ifp)) { + pim_if_addr_del_all_igmp(ifp); + } - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { - pim_if_addr_add_all(ifp); - } + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode, + ifp)) { + pim_if_addr_add_all(ifp); + } } static void clear_pim_interfaces() { - struct listnode *ifnode; - struct listnode *ifnextnode; - struct interface *ifp; + struct listnode *ifnode; + struct listnode *ifnextnode; + struct interface *ifp; - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { - if (ifp->info) { - pim_neighbor_delete_all(ifp, "interface cleared"); - } - } + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode, + ifp)) { + if (ifp->info) { + pim_neighbor_delete_all(ifp, "interface cleared"); + } + } } static void clear_interfaces() { - clear_igmp_interfaces(); - clear_pim_interfaces(); + clear_igmp_interfaces(); + clear_pim_interfaces(); } DEFUN (clear_ip_interfaces, @@ -2600,9 +3052,9 @@ DEFUN (clear_ip_interfaces, IP_STR "Reset interfaces\n") { - clear_interfaces(); + clear_interfaces(); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (clear_ip_igmp_interfaces, @@ -2613,47 +3065,51 @@ DEFUN (clear_ip_igmp_interfaces, CLEAR_IP_IGMP_STR "Reset IGMP interfaces\n") { - clear_igmp_interfaces(); + clear_igmp_interfaces(); - return CMD_SUCCESS; + return CMD_SUCCESS; } static void mroute_add_all() { - struct listnode *node; - struct channel_oil *c_oil; - - for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { - if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) { - /* just log warning */ - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - zlog_warn("%s %s: (S,G)=(%s,%s) failure writing MFC", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str); - } - } + struct listnode *node; + struct channel_oil *c_oil; + + for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { + if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) { + /* just log warning */ + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", c_oil->oil.mfcc_origin, + source_str, sizeof(source_str)); + pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + zlog_warn("%s %s: (S,G)=(%s,%s) failure writing MFC", + __FILE__, __PRETTY_FUNCTION__, source_str, + group_str); + } + } } static void mroute_del_all() { - struct listnode *node; - struct channel_oil *c_oil; - - for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { - if (pim_mroute_del(c_oil, __PRETTY_FUNCTION__)) { - /* just log warning */ - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - zlog_warn("%s %s: (S,G)=(%s,%s) failure clearing MFC", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str); - } - } + struct listnode *node; + struct channel_oil *c_oil; + + for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { + if (pim_mroute_del(c_oil, __PRETTY_FUNCTION__)) { + /* just log warning */ + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", c_oil->oil.mfcc_origin, + source_str, sizeof(source_str)); + pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + zlog_warn("%s %s: (S,G)=(%s,%s) failure clearing MFC", + __FILE__, __PRETTY_FUNCTION__, source_str, + group_str); + } + } } DEFUN (clear_ip_mroute, @@ -2663,10 +3119,10 @@ DEFUN (clear_ip_mroute, IP_STR "Reset multicast routes\n") { - mroute_del_all(); - mroute_add_all(); + mroute_del_all(); + mroute_add_all(); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (clear_ip_pim_interfaces, @@ -2677,9 +3133,9 @@ DEFUN (clear_ip_pim_interfaces, CLEAR_IP_PIM_STR "Reset PIM interfaces\n") { - clear_pim_interfaces(); + clear_pim_interfaces(); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (clear_ip_pim_interface_traffic, @@ -2691,34 +3147,33 @@ DEFUN (clear_ip_pim_interface_traffic, "Reset PIM interfaces\n" "Reset Protocol Packet counters\n") { - struct listnode *ifnode = NULL; - struct listnode *ifnextnode = NULL; - struct interface *ifp = NULL; - struct pim_interface *pim_ifp = NULL; - - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) - { - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - pim_ifp->pim_ifstat_hello_recv = 0; - pim_ifp->pim_ifstat_hello_sent = 0; - pim_ifp->pim_ifstat_join_recv = 0; - pim_ifp->pim_ifstat_join_send = 0; - pim_ifp->pim_ifstat_prune_recv = 0; - pim_ifp->pim_ifstat_prune_send = 0; - pim_ifp->pim_ifstat_reg_recv = 0; - pim_ifp->pim_ifstat_reg_send = 0; - pim_ifp->pim_ifstat_reg_stop_recv = 0; - pim_ifp->pim_ifstat_reg_stop_send = 0; - pim_ifp->pim_ifstat_assert_recv = 0; - pim_ifp->pim_ifstat_assert_send = 0; - - } + struct listnode *ifnode = NULL; + struct listnode *ifnextnode = NULL; + struct interface *ifp = NULL; + struct pim_interface *pim_ifp = NULL; + + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode, + ifp)) { + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + pim_ifp->pim_ifstat_hello_recv = 0; + pim_ifp->pim_ifstat_hello_sent = 0; + pim_ifp->pim_ifstat_join_recv = 0; + pim_ifp->pim_ifstat_join_send = 0; + pim_ifp->pim_ifstat_prune_recv = 0; + pim_ifp->pim_ifstat_prune_send = 0; + pim_ifp->pim_ifstat_reg_recv = 0; + pim_ifp->pim_ifstat_reg_send = 0; + pim_ifp->pim_ifstat_reg_stop_recv = 0; + pim_ifp->pim_ifstat_reg_stop_send = 0; + pim_ifp->pim_ifstat_assert_recv = 0; + pim_ifp->pim_ifstat_assert_send = 0; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (clear_ip_pim_oil, @@ -2729,9 +3184,9 @@ DEFUN (clear_ip_pim_oil, CLEAR_IP_PIM_STR "Rescan PIM OIL (output interface list)\n") { - pim_scan_oil(); + pim_scan_oil(); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_igmp_interface, @@ -2745,16 +3200,16 @@ DEFUN (show_ip_igmp_interface, "interface name\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - int idx = 0; + u_char uj = use_json(argc, argv); + int idx = 0; - if (argv_find(argv, argc, "detail", &idx) || - argv_find(argv, argc, "WORD", &idx)) - igmp_show_interfaces_single(vty, argv[idx]->arg, uj); - else - igmp_show_interfaces(vty, uj); + if (argv_find(argv, argc, "detail", &idx) + || argv_find(argv, argc, "WORD", &idx)) + igmp_show_interfaces_single(vty, argv[idx]->arg, uj); + else + igmp_show_interfaces(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_igmp_join, @@ -2765,9 +3220,9 @@ DEFUN (show_ip_igmp_join, IGMP_STR "IGMP static join information\n") { - igmp_show_interface_join(vty); + igmp_show_interface_join(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_igmp_groups, @@ -2779,10 +3234,10 @@ DEFUN (show_ip_igmp_groups, IGMP_GROUP_STR "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - igmp_show_groups(vty, uj); + u_char uj = use_json(argc, argv); + igmp_show_groups(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_igmp_groups_retransmissions, @@ -2794,9 +3249,9 @@ DEFUN (show_ip_igmp_groups_retransmissions, IGMP_GROUP_STR "IGMP group retransmissions\n") { - igmp_show_group_retransmission(vty); + igmp_show_group_retransmission(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_igmp_sources, @@ -2807,9 +3262,9 @@ DEFUN (show_ip_igmp_sources, IGMP_STR IGMP_SOURCE_STR) { - igmp_show_sources(vty); + igmp_show_sources(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_igmp_sources_retransmissions, @@ -2821,9 +3276,9 @@ DEFUN (show_ip_igmp_sources_retransmissions, IGMP_SOURCE_STR "IGMP source retransmissions\n") { - igmp_show_source_retransmission(vty); + igmp_show_source_retransmission(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_assert, @@ -2834,9 +3289,9 @@ DEFUN (show_ip_pim_assert, PIM_STR "PIM interface assert\n") { - pim_show_assert(vty); + pim_show_assert(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_assert_internal, @@ -2847,9 +3302,9 @@ DEFUN (show_ip_pim_assert_internal, PIM_STR "PIM interface internal assert state\n") { - pim_show_assert_internal(vty); + pim_show_assert_internal(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_assert_metric, @@ -2860,9 +3315,9 @@ DEFUN (show_ip_pim_assert_metric, PIM_STR "PIM interface assert metric\n") { - pim_show_assert_metric(vty); + pim_show_assert_metric(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_assert_winner_metric, @@ -2873,9 +3328,9 @@ DEFUN (show_ip_pim_assert_winner_metric, PIM_STR "PIM interface assert winner metric\n") { - pim_show_assert_winner_metric(vty); + pim_show_assert_winner_metric(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_interface, @@ -2889,17 +3344,17 @@ DEFUN (show_ip_pim_interface, "interface name\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - int idx = 0; + u_char uj = use_json(argc, argv); + int idx = 0; - if (argv_find(argv, argc, "WORD", &idx) || - argv_find(argv, argc, "detail", &idx)) - pim_show_interfaces_single(vty, argv[idx]->arg, uj); + if (argv_find(argv, argc, "WORD", &idx) + || argv_find(argv, argc, "detail", &idx)) + pim_show_interfaces_single(vty, argv[idx]->arg, uj); - else - pim_show_interfaces(vty, uj); + else + pim_show_interfaces(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_join, @@ -2911,10 +3366,10 @@ DEFUN (show_ip_pim_join, "PIM interface join information\n" JSON_STR) { - u_char uj = use_json(argc, argv); - pim_show_join(vty, uj); + u_char uj = use_json(argc, argv); + pim_show_join(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_local_membership, @@ -2926,10 +3381,10 @@ DEFUN (show_ip_pim_local_membership, "PIM interface local-membership\n" JSON_STR) { - u_char uj = use_json(argc, argv); - pim_show_membership(vty, uj); + u_char uj = use_json(argc, argv); + pim_show_membership(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_neighbor, @@ -2943,16 +3398,16 @@ DEFUN (show_ip_pim_neighbor, "Name of interface or neighbor\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - int idx = 0; + u_char uj = use_json(argc, argv); + int idx = 0; - if (argv_find(argv, argc, "detail", &idx) || - argv_find(argv, argc, "WORD", &idx)) - pim_show_neighbors_single(vty, argv[idx]->arg, uj); - else - pim_show_neighbors(vty, uj); + if (argv_find(argv, argc, "detail", &idx) + || argv_find(argv, argc, "WORD", &idx)) + pim_show_neighbors_single(vty, argv[idx]->arg, uj); + else + pim_show_neighbors(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_secondary, @@ -2963,9 +3418,9 @@ DEFUN (show_ip_pim_secondary, PIM_STR "PIM neighbor addresses\n") { - pim_show_neighbors_secondary(vty); + pim_show_neighbors_secondary(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_state, @@ -2979,23 +3434,21 @@ DEFUN (show_ip_pim_state, "Multicast address\n" "JavaScript Object Notation\n") { - const char *src_or_group = NULL; - const char *group = NULL; - u_char uj = use_json(argc, argv); - if (uj) - argc--; + const char *src_or_group = NULL; + const char *group = NULL; + u_char uj = use_json(argc, argv); + if (uj) + argc--; - if (argc == 6) - { - src_or_group = argv[4]->arg; - group = argv[5]->arg; - } - else if (argc == 5) - src_or_group = argv[4]->arg; + if (argc == 6) { + src_or_group = argv[4]->arg; + group = argv[5]->arg; + } else if (argc == 5) + src_or_group = argv[4]->arg; - pim_show_state(vty, src_or_group, group, uj); + pim_show_state(vty, src_or_group, group, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_upstream, @@ -3007,10 +3460,10 @@ DEFUN (show_ip_pim_upstream, "PIM upstream information\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - pim_show_upstream(vty, uj); + u_char uj = use_json(argc, argv); + pim_show_upstream(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_upstream_join_desired, @@ -3022,10 +3475,10 @@ DEFUN (show_ip_pim_upstream_join_desired, "PIM upstream join-desired\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - pim_show_join_desired(vty, uj); + u_char uj = use_json(argc, argv); + pim_show_join_desired(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_upstream_rpf, @@ -3037,10 +3490,10 @@ DEFUN (show_ip_pim_upstream_rpf, "PIM upstream source rpf\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - pim_show_upstream_rpf(vty, uj); + u_char uj = use_json(argc, argv); + pim_show_upstream_rpf(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_rp, @@ -3052,10 +3505,10 @@ DEFUN (show_ip_pim_rp, "PIM RP information\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - pim_rp_show_information (vty, uj); + u_char uj = use_json(argc, argv); + pim_rp_show_information(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_rpf, @@ -3067,10 +3520,10 @@ DEFUN (show_ip_pim_rpf, "PIM cached source rpf information\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - pim_show_rpf(vty, uj); + u_char uj = use_json(argc, argv); + pim_show_rpf(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_nexthop, @@ -3081,9 +3534,9 @@ DEFUN (show_ip_pim_nexthop, PIM_STR "PIM cached nexthop rpf information\n") { - pim_show_nexthop (vty); + pim_show_nexthop(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_pim_nexthop_lookup, @@ -3096,75 +3549,70 @@ DEFUN (show_ip_pim_nexthop_lookup, "Source/RP address\n" "Multicast Group address\n") { - struct pim_nexthop_cache pnc; - struct prefix nht_p; - int result = 0; - struct in_addr src_addr, grp_addr; - struct in_addr vif_source; - const char *addr_str, *addr_str1; - struct prefix grp; - struct pim_nexthop nexthop; - char nexthop_addr_str[PREFIX_STRLEN]; - char grp_str[PREFIX_STRLEN]; - - addr_str = argv[4]->arg; - result = inet_pton (AF_INET, addr_str, &src_addr); - if (result <= 0) - { - vty_out (vty, "Bad unicast address %s: errno=%d: %s\n", - addr_str, errno, safe_strerror(errno)); - return CMD_WARNING; - } - - if (pim_is_group_224_4 (src_addr)) - { - vty_out (vty, "Invalid argument. Expected Valid Source Address.\n"); - return CMD_WARNING; - } - - addr_str1 = argv[5]->arg; - result = inet_pton (AF_INET, addr_str1, &grp_addr); - if (result <= 0) - { - vty_out (vty, "Bad unicast address %s: errno=%d: %s\n", - addr_str, errno, safe_strerror(errno)); - return CMD_WARNING; - } - - if (!pim_is_group_224_4 (grp_addr)) - { - vty_out (vty, - "Invalid argument. Expected Valid Multicast Group Address.\n"); - return CMD_WARNING; - } - - if (!pim_rp_set_upstream_addr (&vif_source, src_addr, grp_addr)) - return CMD_SUCCESS; - - memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = vif_source; - grp.family = AF_INET; - grp.prefixlen = IPV4_MAX_BITLEN; - grp.u.prefix4 = grp_addr; - memset (&nexthop, 0, sizeof (nexthop)); - - if ((pim_find_or_track_nexthop (&nht_p, NULL, NULL, &pnc)) == 1) - { - //Compute PIM RPF using Cached nexthop - pim_ecmp_nexthop_search (&pnc, &nexthop, &nht_p, &grp, 0); - } - else - pim_ecmp_nexthop_lookup (&nexthop, vif_source, &nht_p, &grp, 0); - - pim_addr_dump ("", &grp, grp_str, sizeof (grp_str)); - pim_addr_dump ("", &nexthop.mrib_nexthop_addr, - nexthop_addr_str, sizeof (nexthop_addr_str)); - vty_out (vty, "Group %s --- Nexthop %s Interface %s \n", grp_str, - nexthop_addr_str, nexthop.interface->name); - - return CMD_SUCCESS; + struct pim_nexthop_cache pnc; + struct prefix nht_p; + int result = 0; + struct in_addr src_addr, grp_addr; + struct in_addr vif_source; + const char *addr_str, *addr_str1; + struct prefix grp; + struct pim_nexthop nexthop; + char nexthop_addr_str[PREFIX_STRLEN]; + char grp_str[PREFIX_STRLEN]; + + addr_str = argv[4]->arg; + result = inet_pton(AF_INET, addr_str, &src_addr); + if (result <= 0) { + vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str, + errno, safe_strerror(errno)); + return CMD_WARNING; + } + + if (pim_is_group_224_4(src_addr)) { + vty_out(vty, + "Invalid argument. Expected Valid Source Address.\n"); + return CMD_WARNING; + } + + addr_str1 = argv[5]->arg; + result = inet_pton(AF_INET, addr_str1, &grp_addr); + if (result <= 0) { + vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str, + errno, safe_strerror(errno)); + return CMD_WARNING; + } + + if (!pim_is_group_224_4(grp_addr)) { + vty_out(vty, + "Invalid argument. Expected Valid Multicast Group Address.\n"); + return CMD_WARNING; + } + + if (!pim_rp_set_upstream_addr(&vif_source, src_addr, grp_addr)) + return CMD_SUCCESS; + + memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = vif_source; + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = grp_addr; + memset(&nexthop, 0, sizeof(nexthop)); + + if ((pim_find_or_track_nexthop(&nht_p, NULL, NULL, &pnc)) == 1) { + // Compute PIM RPF using Cached nexthop + pim_ecmp_nexthop_search(&pnc, &nexthop, &nht_p, &grp, 0); + } else + pim_ecmp_nexthop_lookup(&nexthop, vif_source, &nht_p, &grp, 0); + + pim_addr_dump("", &grp, grp_str, sizeof(grp_str)); + pim_addr_dump("", &nexthop.mrib_nexthop_addr, + nexthop_addr_str, sizeof(nexthop_addr_str)); + vty_out(vty, "Group %s --- Nexthop %s Interface %s \n", grp_str, + nexthop_addr_str, nexthop.interface->name); + + return CMD_SUCCESS; } DEFUN (show_ip_pim_interface_traffic, @@ -3178,61 +3626,56 @@ DEFUN (show_ip_pim_interface_traffic, "Interface name\n" "JavaScript Object Notation\n") { - u_char uj = use_json (argc, argv); - int idx = 0; + u_char uj = use_json(argc, argv); + int idx = 0; - if (argv_find(argv, argc, "WORD", &idx)) - pim_show_interface_traffic_single (vty, argv[idx]->arg, uj); - else - pim_show_interface_traffic (vty, uj); + if (argv_find(argv, argc, "WORD", &idx)) + pim_show_interface_traffic_single(vty, argv[idx]->arg, uj); + else + pim_show_interface_traffic(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } static void show_multicast_interfaces(struct vty *vty) { - struct listnode *node; - struct interface *ifp; - - vty_out (vty, "\n"); - - vty_out (vty, - "Interface Address ifi Vif PktsIn PktsOut BytesIn BytesOut\n"); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - struct pim_interface *pim_ifp; - struct in_addr ifaddr; - struct sioc_vif_req vreq; - - pim_ifp = ifp->info; - - if (!pim_ifp) - continue; - - memset(&vreq, 0, sizeof(vreq)); - vreq.vifi = pim_ifp->mroute_vif_index; - - if (ioctl(qpim_mroute_socket_fd, SIOCGETVIFCNT, &vreq)) { - zlog_warn("ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s\n", - (unsigned long)SIOCGETVIFCNT, - ifp->name, - pim_ifp->mroute_vif_index, - errno, - safe_strerror(errno)); - } - - ifaddr = pim_ifp->primary_address; - - vty_out (vty, "%-9s %-15s %3d %3d %7lu %7lu %10lu %10lu\n", - ifp->name, - inet_ntoa(ifaddr), - ifp->ifindex, - pim_ifp->mroute_vif_index, - (unsigned long) vreq.icount, - (unsigned long) vreq.ocount, - (unsigned long) vreq.ibytes, - (unsigned long)vreq.obytes); - } + struct listnode *node; + struct interface *ifp; + + vty_out(vty, "\n"); + + vty_out(vty, + "Interface Address ifi Vif PktsIn PktsOut BytesIn BytesOut\n"); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + struct pim_interface *pim_ifp; + struct in_addr ifaddr; + struct sioc_vif_req vreq; + + pim_ifp = ifp->info; + + if (!pim_ifp) + continue; + + memset(&vreq, 0, sizeof(vreq)); + vreq.vifi = pim_ifp->mroute_vif_index; + + if (ioctl(qpim_mroute_socket_fd, SIOCGETVIFCNT, &vreq)) { + zlog_warn( + "ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s\n", + (unsigned long)SIOCGETVIFCNT, ifp->name, + pim_ifp->mroute_vif_index, errno, + safe_strerror(errno)); + } + + ifaddr = pim_ifp->primary_address; + + vty_out(vty, "%-9s %-15s %3d %3d %7lu %7lu %10lu %10lu\n", + ifp->name, inet_ntoa(ifaddr), ifp->ifindex, + pim_ifp->mroute_vif_index, (unsigned long)vreq.icount, + (unsigned long)vreq.ocount, (unsigned long)vreq.ibytes, + (unsigned long)vreq.obytes); + } } DEFUN (show_ip_multicast, @@ -3242,327 +3685,364 @@ DEFUN (show_ip_multicast, IP_STR "Multicast global information\n") { - time_t now = pim_time_monotonic_sec(); + time_t now = pim_time_monotonic_sec(); - char uptime[10]; + char uptime[10]; + + vty_out(vty, "Mroute socket descriptor: %d\n", qpim_mroute_socket_fd); - vty_out (vty, "Mroute socket descriptor: %d\n", - qpim_mroute_socket_fd); + pim_time_uptime(uptime, sizeof(uptime), + now - qpim_mroute_socket_creation); + vty_out(vty, "Mroute socket uptime: %s\n", uptime); - pim_time_uptime(uptime, sizeof(uptime), now - qpim_mroute_socket_creation); - vty_out (vty, "Mroute socket uptime: %s\n", - uptime); + vty_out(vty, "\n"); - vty_out (vty, "\n"); + pim_zebra_zclient_update(vty); + pim_zlookup_show_ip_multicast(vty); - pim_zebra_zclient_update (vty); - pim_zlookup_show_ip_multicast (vty); + vty_out(vty, "\n"); + vty_out(vty, "Maximum highest VifIndex: %d\n", PIM_MAX_USABLE_VIFS); - vty_out (vty, "\n"); - vty_out (vty, "Maximum highest VifIndex: %d\n", - PIM_MAX_USABLE_VIFS); + vty_out(vty, "\n"); + vty_out(vty, "Upstream Join Timer: %d secs\n", qpim_t_periodic); + vty_out(vty, "Join/Prune Holdtime: %d secs\n", PIM_JP_HOLDTIME); + vty_out(vty, "PIM ECMP: %s\n", qpim_ecmp_enable ? "Enable" : "Disable"); + vty_out(vty, "PIM ECMP Rebalance: %s\n", + qpim_ecmp_rebalance_enable ? "Enable" : "Disable"); - vty_out (vty, "\n"); - vty_out (vty, "Upstream Join Timer: %d secs\n", - qpim_t_periodic); - vty_out (vty, "Join/Prune Holdtime: %d secs\n", - PIM_JP_HOLDTIME); - vty_out (vty, "PIM ECMP: %s\n", - qpim_ecmp_enable ? "Enable" : "Disable"); - vty_out (vty, "PIM ECMP Rebalance: %s\n", - qpim_ecmp_rebalance_enable ? "Enable" : "Disable"); + vty_out(vty, "\n"); - vty_out (vty, "\n"); + show_rpf_refresh_stats(vty, now, NULL); - show_rpf_refresh_stats(vty, now, NULL); + vty_out(vty, "\n"); - vty_out (vty, "\n"); + show_scan_oil_stats(vty, now); - show_scan_oil_stats(vty, now); + show_multicast_interfaces(vty); - show_multicast_interfaces(vty); - - return CMD_SUCCESS; + return CMD_SUCCESS; } static void show_mroute(struct vty *vty, u_char uj) { - struct listnode *node; - struct channel_oil *c_oil; - struct static_route *s_route; - time_t now; - json_object *json = NULL; - json_object *json_group = NULL; - json_object *json_source = NULL; - json_object *json_oil = NULL; - json_object *json_ifp_out = NULL; - int found_oif = 0; - int first = 1; - char grp_str[INET_ADDRSTRLEN]; - char src_str[INET_ADDRSTRLEN]; - char in_ifname[INTERFACE_NAMSIZ+1]; - char out_ifname[INTERFACE_NAMSIZ+1]; - int oif_vif_index; - struct interface *ifp_in; - char proto[100]; - - if (uj) { - json = json_object_new_object(); - } else { - vty_out (vty, - "Source Group Proto Input Output TTL Uptime\n"); - } - - now = pim_time_monotonic_sec(); - - /* print list of PIM and IGMP routes */ - for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { - found_oif = 0; - first = 1; - if (!c_oil->installed && !uj) - continue; - - pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, grp_str, sizeof(grp_str)); - pim_inet4_dump("", c_oil->oil.mfcc_origin, src_str, sizeof(src_str)); - ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); - - if (ifp_in) - strcpy(in_ifname, ifp_in->name); - else - strcpy(in_ifname, ""); - - if (uj) { - - /* Find the group, create it if it doesn't exist */ - json_object_object_get_ex(json, grp_str, &json_group); - - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json, grp_str, json_group); - } - - /* Find the source nested under the group, create it if it doesn't exist */ - json_object_object_get_ex(json_group, src_str, &json_source); - - if (!json_source) { - json_source = json_object_new_object(); - json_object_object_add(json_group, src_str, json_source); - } - - /* Find the inbound interface nested under the source, create it if it doesn't exist */ - json_object_int_add(json_source, "installed", c_oil->installed); - json_object_int_add(json_source, "refCount", c_oil->oil_ref_count); - json_object_int_add(json_source, "oilSize", c_oil->oil_size); - json_object_int_add(json_source, "OilInheritedRescan", c_oil->oil_inherited_rescan); - json_object_string_add(json_source, "iif", in_ifname); - json_oil = NULL; - } - - for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) { - struct interface *ifp_out; - char oif_uptime[10]; - int ttl; - - ttl = c_oil->oil.mfcc_ttls[oif_vif_index]; - if (ttl < 1) - continue; - - ifp_out = pim_if_find_by_vif_index(oif_vif_index); - pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - c_oil->oif_creation[oif_vif_index]); - found_oif = 1; - - if (ifp_out) - strcpy(out_ifname, ifp_out->name); - else - strcpy(out_ifname, ""); - - if (uj) { - json_ifp_out = json_object_new_object(); - json_object_string_add(json_ifp_out, "source", src_str); - json_object_string_add(json_ifp_out, "group", grp_str); - - if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) - json_object_boolean_true_add(json_ifp_out, "protocolPim"); - - if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) - json_object_boolean_true_add(json_ifp_out, "protocolIgmp"); - - if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) - json_object_boolean_true_add(json_ifp_out, "protocolSource"); - - if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) - json_object_boolean_true_add(json_ifp_out, "protocolInherited"); - - json_object_string_add(json_ifp_out, "inboundInterface", in_ifname); - json_object_int_add(json_ifp_out, "iVifI", c_oil->oil.mfcc_parent); - json_object_string_add(json_ifp_out, "outboundInterface", out_ifname); - json_object_int_add(json_ifp_out, "oVifI", oif_vif_index); - json_object_int_add(json_ifp_out, "ttl", ttl); - json_object_string_add(json_ifp_out, "upTime", oif_uptime); - if (!json_oil) { - json_oil = json_object_new_object(); - json_object_object_add(json_source, "oil", json_oil); - } - json_object_object_add(json_oil, out_ifname, json_ifp_out); - } else { - if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) { - strcpy(proto, "PIM"); - } - - if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) { - strcpy(proto, "IGMP"); - } - - if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_SOURCE) { - strcpy(proto, "SRC"); - } - - if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_STAR) { - strcpy(proto, "STAR"); - } - - vty_out (vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n", - src_str, - grp_str, - proto, - in_ifname, - out_ifname, - ttl, - oif_uptime); - - if (first) - { - src_str[0] = '\0'; - grp_str[0] = '\0'; - in_ifname[0] = '\0'; - first = 0; - } - } - } - - if (!uj && !found_oif) { - vty_out (vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n", - src_str, - grp_str, - "none", - in_ifname, - "none", - 0, - "--:--:--"); - } - } - - /* Print list of static routes */ - for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { - first = 1; - - if (!s_route->c_oil.installed) - continue; - - pim_inet4_dump("", s_route->group, grp_str, sizeof(grp_str)); - pim_inet4_dump("", s_route->source, src_str, sizeof(src_str)); - ifp_in = pim_if_find_by_vif_index(s_route->iif); - found_oif = 0; - - if (ifp_in) - strcpy(in_ifname, ifp_in->name); - else - strcpy(in_ifname, ""); - - if (uj) { - - /* Find the group, create it if it doesn't exist */ - json_object_object_get_ex(json, grp_str, &json_group); - - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json, grp_str, json_group); - } - - /* Find the source nested under the group, create it if it doesn't exist */ - json_object_object_get_ex(json_group, src_str, &json_source); - - if (!json_source) { - json_source = json_object_new_object(); - json_object_object_add(json_group, src_str, json_source); - } - - json_object_string_add(json_source, "iif", in_ifname); - json_oil = NULL; - } else { - strcpy(proto, "STATIC"); - } - - for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) { - struct interface *ifp_out; - char oif_uptime[10]; - int ttl; - - ttl = s_route->oif_ttls[oif_vif_index]; - if (ttl < 1) - continue; - - ifp_out = pim_if_find_by_vif_index(oif_vif_index); - pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - s_route->c_oil.oif_creation[oif_vif_index]); - found_oif = 1; - - if (ifp_out) - strcpy(out_ifname, ifp_out->name); - else - strcpy(out_ifname, ""); - - if (uj) { - json_ifp_out = json_object_new_object(); - json_object_string_add(json_ifp_out, "source", src_str); - json_object_string_add(json_ifp_out, "group", grp_str); - json_object_boolean_true_add(json_ifp_out, "protocolStatic"); - json_object_string_add(json_ifp_out, "inboundInterface", in_ifname); - json_object_int_add(json_ifp_out, "iVifI", s_route->c_oil.oil.mfcc_parent); - json_object_string_add(json_ifp_out, "outboundInterface", out_ifname); - json_object_int_add(json_ifp_out, "oVifI", oif_vif_index); - json_object_int_add(json_ifp_out, "ttl", ttl); - json_object_string_add(json_ifp_out, "upTime", oif_uptime); - if (!json_oil) { - json_oil = json_object_new_object(); - json_object_object_add(json_source, "oil", json_oil); - } - json_object_object_add(json_oil, out_ifname, json_ifp_out); - } else { - vty_out (vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n", - src_str, - grp_str, - proto, - in_ifname, - out_ifname, - ttl, - oif_uptime); - if (first) - { - src_str[0] = '\0'; - grp_str[0] = '\0'; - in_ifname[0] = '\0'; - first = 0; - } - } - } - - if (!uj && !found_oif) { - vty_out (vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n", - src_str, - grp_str, - proto, - in_ifname, - "none", - 0, - "--:--:--"); - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + struct listnode *node; + struct channel_oil *c_oil; + struct static_route *s_route; + time_t now; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_source = NULL; + json_object *json_oil = NULL; + json_object *json_ifp_out = NULL; + int found_oif = 0; + int first = 1; + char grp_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; + char in_ifname[INTERFACE_NAMSIZ + 1]; + char out_ifname[INTERFACE_NAMSIZ + 1]; + int oif_vif_index; + struct interface *ifp_in; + char proto[100]; + + if (uj) { + json = json_object_new_object(); + } else { + vty_out(vty, + "Source Group Proto Input Output TTL Uptime\n"); + } + + now = pim_time_monotonic_sec(); + + /* print list of PIM and IGMP routes */ + for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { + found_oif = 0; + first = 1; + if (!c_oil->installed && !uj) + continue; + + pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, grp_str, + sizeof(grp_str)); + pim_inet4_dump("", c_oil->oil.mfcc_origin, src_str, + sizeof(src_str)); + ifp_in = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); + + if (ifp_in) + strcpy(in_ifname, ifp_in->name); + else + strcpy(in_ifname, ""); + + if (uj) { + + /* Find the group, create it if it doesn't exist */ + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, + json_group); + } + + /* Find the source nested under the group, create it if + * it doesn't exist */ + json_object_object_get_ex(json_group, src_str, + &json_source); + + if (!json_source) { + json_source = json_object_new_object(); + json_object_object_add(json_group, src_str, + json_source); + } + + /* Find the inbound interface nested under the source, + * create it if it doesn't exist */ + json_object_int_add(json_source, "installed", + c_oil->installed); + json_object_int_add(json_source, "refCount", + c_oil->oil_ref_count); + json_object_int_add(json_source, "oilSize", + c_oil->oil_size); + json_object_int_add(json_source, "OilInheritedRescan", + c_oil->oil_inherited_rescan); + json_object_string_add(json_source, "iif", in_ifname); + json_oil = NULL; + } + + for (oif_vif_index = 0; oif_vif_index < MAXVIFS; + ++oif_vif_index) { + struct interface *ifp_out; + char oif_uptime[10]; + int ttl; + + ttl = c_oil->oil.mfcc_ttls[oif_vif_index]; + if (ttl < 1) + continue; + + ifp_out = pim_if_find_by_vif_index(oif_vif_index); + pim_time_uptime( + oif_uptime, sizeof(oif_uptime), + now - c_oil->oif_creation[oif_vif_index]); + found_oif = 1; + + if (ifp_out) + strcpy(out_ifname, ifp_out->name); + else + strcpy(out_ifname, ""); + + if (uj) { + json_ifp_out = json_object_new_object(); + json_object_string_add(json_ifp_out, "source", + src_str); + json_object_string_add(json_ifp_out, "group", + grp_str); + + if (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_PIM) + json_object_boolean_true_add( + json_ifp_out, "protocolPim"); + + if (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_IGMP) + json_object_boolean_true_add( + json_ifp_out, "protocolIgmp"); + + if (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_SOURCE) + json_object_boolean_true_add( + json_ifp_out, "protocolSource"); + + if (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_STAR) + json_object_boolean_true_add( + json_ifp_out, + "protocolInherited"); + + json_object_string_add(json_ifp_out, + "inboundInterface", + in_ifname); + json_object_int_add(json_ifp_out, "iVifI", + c_oil->oil.mfcc_parent); + json_object_string_add(json_ifp_out, + "outboundInterface", + out_ifname); + json_object_int_add(json_ifp_out, "oVifI", + oif_vif_index); + json_object_int_add(json_ifp_out, "ttl", ttl); + json_object_string_add(json_ifp_out, "upTime", + oif_uptime); + if (!json_oil) { + json_oil = json_object_new_object(); + json_object_object_add(json_source, + "oil", json_oil); + } + json_object_object_add(json_oil, out_ifname, + json_ifp_out); + } else { + if (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_PIM) { + strcpy(proto, "PIM"); + } + + if (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_IGMP) { + strcpy(proto, "IGMP"); + } + + if (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_SOURCE) { + strcpy(proto, "SRC"); + } + + if (c_oil->oif_flags[oif_vif_index] + & PIM_OIF_FLAG_PROTO_STAR) { + strcpy(proto, "STAR"); + } + + vty_out(vty, + "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n", + src_str, grp_str, proto, in_ifname, + out_ifname, ttl, oif_uptime); + + if (first) { + src_str[0] = '\0'; + grp_str[0] = '\0'; + in_ifname[0] = '\0'; + first = 0; + } + } + } + + if (!uj && !found_oif) { + vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n", + src_str, grp_str, "none", in_ifname, "none", 0, + "--:--:--"); + } + } + + /* Print list of static routes */ + for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { + first = 1; + + if (!s_route->c_oil.installed) + continue; + + pim_inet4_dump("", s_route->group, grp_str, + sizeof(grp_str)); + pim_inet4_dump("", s_route->source, src_str, + sizeof(src_str)); + ifp_in = pim_if_find_by_vif_index(s_route->iif); + found_oif = 0; + + if (ifp_in) + strcpy(in_ifname, ifp_in->name); + else + strcpy(in_ifname, ""); + + if (uj) { + + /* Find the group, create it if it doesn't exist */ + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, + json_group); + } + + /* Find the source nested under the group, create it if + * it doesn't exist */ + json_object_object_get_ex(json_group, src_str, + &json_source); + + if (!json_source) { + json_source = json_object_new_object(); + json_object_object_add(json_group, src_str, + json_source); + } + + json_object_string_add(json_source, "iif", in_ifname); + json_oil = NULL; + } else { + strcpy(proto, "STATIC"); + } + + for (oif_vif_index = 0; oif_vif_index < MAXVIFS; + ++oif_vif_index) { + struct interface *ifp_out; + char oif_uptime[10]; + int ttl; + + ttl = s_route->oif_ttls[oif_vif_index]; + if (ttl < 1) + continue; + + ifp_out = pim_if_find_by_vif_index(oif_vif_index); + pim_time_uptime( + oif_uptime, sizeof(oif_uptime), + now + - s_route->c_oil + .oif_creation[oif_vif_index]); + found_oif = 1; + + if (ifp_out) + strcpy(out_ifname, ifp_out->name); + else + strcpy(out_ifname, ""); + + if (uj) { + json_ifp_out = json_object_new_object(); + json_object_string_add(json_ifp_out, "source", + src_str); + json_object_string_add(json_ifp_out, "group", + grp_str); + json_object_boolean_true_add(json_ifp_out, + "protocolStatic"); + json_object_string_add(json_ifp_out, + "inboundInterface", + in_ifname); + json_object_int_add( + json_ifp_out, "iVifI", + s_route->c_oil.oil.mfcc_parent); + json_object_string_add(json_ifp_out, + "outboundInterface", + out_ifname); + json_object_int_add(json_ifp_out, "oVifI", + oif_vif_index); + json_object_int_add(json_ifp_out, "ttl", ttl); + json_object_string_add(json_ifp_out, "upTime", + oif_uptime); + if (!json_oil) { + json_oil = json_object_new_object(); + json_object_object_add(json_source, + "oil", json_oil); + } + json_object_object_add(json_oil, out_ifname, + json_ifp_out); + } else { + vty_out(vty, + "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n", + src_str, grp_str, proto, in_ifname, + out_ifname, ttl, oif_uptime); + if (first) { + src_str[0] = '\0'; + grp_str[0] = '\0'; + in_ifname[0] = '\0'; + first = 0; + } + } + } + + if (!uj && !found_oif) { + vty_out(vty, "%-15s %-15s %-6s %-10s %-10s %-3d %8s\n", + src_str, grp_str, proto, in_ifname, "none", 0, + "--:--:--"); + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } DEFUN (show_ip_mroute, @@ -3573,65 +4053,63 @@ DEFUN (show_ip_mroute, MROUTE_STR JSON_STR) { - u_char uj = use_json(argc, argv); - show_mroute(vty, uj); - return CMD_SUCCESS; + u_char uj = use_json(argc, argv); + show_mroute(vty, uj); + return CMD_SUCCESS; } static void show_mroute_count(struct vty *vty) { - struct listnode *node; - struct channel_oil *c_oil; - struct static_route *s_route; + struct listnode *node; + struct channel_oil *c_oil; + struct static_route *s_route; - vty_out (vty, "\n"); - - vty_out (vty, - "Source Group LastUsed Packets Bytes WrongIf \n"); + vty_out(vty, "\n"); - /* Print PIM and IGMP route counts */ - for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; + vty_out(vty, + "Source Group LastUsed Packets Bytes WrongIf \n"); - if (!c_oil->installed) - continue; + /* Print PIM and IGMP route counts */ + for (ALL_LIST_ELEMENTS_RO(pim_channel_oil_list, node, c_oil)) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; - pim_mroute_update_counters (c_oil); + if (!c_oil->installed) + continue; - pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); + pim_mroute_update_counters(c_oil); - vty_out (vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld\n", - source_str, - group_str, - c_oil->cc.lastused/100, - c_oil->cc.pktcnt, - c_oil->cc.bytecnt, - c_oil->cc.wrong_if); - } + pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, + sizeof(group_str)); + pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, + sizeof(source_str)); - /* Print static route counts */ - for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; + vty_out(vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld\n", + source_str, group_str, c_oil->cc.lastused / 100, + c_oil->cc.pktcnt, c_oil->cc.bytecnt, + c_oil->cc.wrong_if); + } + + /* Print static route counts */ + for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; - if (!s_route->c_oil.installed) - continue; + if (!s_route->c_oil.installed) + continue; - pim_mroute_update_counters (&s_route->c_oil); + pim_mroute_update_counters(&s_route->c_oil); - pim_inet4_dump("", s_route->c_oil.oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("", s_route->c_oil.oil.mfcc_origin, source_str, sizeof(source_str)); + pim_inet4_dump("", s_route->c_oil.oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("", s_route->c_oil.oil.mfcc_origin, + source_str, sizeof(source_str)); - vty_out (vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld\n", - source_str, - group_str, - s_route->c_oil.cc.lastused, - s_route->c_oil.cc.pktcnt, - s_route->c_oil.cc.bytecnt, - s_route->c_oil.cc.wrong_if); - } + vty_out(vty, "%-15s %-15s %-8llu %-7ld %-10ld %-7ld\n", + source_str, group_str, s_route->c_oil.cc.lastused, + s_route->c_oil.cc.pktcnt, s_route->c_oil.cc.bytecnt, + s_route->c_oil.cc.wrong_if); + } } DEFUN (show_ip_mroute_count, @@ -3642,8 +4120,8 @@ DEFUN (show_ip_mroute_count, MROUTE_STR "Route and packet count data\n") { - show_mroute_count(vty); - return CMD_SUCCESS; + show_mroute_count(vty); + return CMD_SUCCESS; } DEFUN (show_ip_rib, @@ -3654,83 +4132,82 @@ DEFUN (show_ip_rib, RIB_STR "Unicast address\n") { - int idx_ipv4 = 3; - struct in_addr addr; - const char *addr_str; - struct pim_nexthop nexthop; - char nexthop_addr_str[PREFIX_STRLEN]; - int result; - - memset (&nexthop, 0, sizeof (nexthop)); - addr_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, addr_str, &addr); - if (result <= 0) { - vty_out (vty, "Bad unicast address %s: errno=%d: %s\n", - addr_str, errno, safe_strerror(errno)); - return CMD_WARNING; - } + int idx_ipv4 = 3; + struct in_addr addr; + const char *addr_str; + struct pim_nexthop nexthop; + char nexthop_addr_str[PREFIX_STRLEN]; + int result; + + memset(&nexthop, 0, sizeof(nexthop)); + addr_str = argv[idx_ipv4]->arg; + result = inet_pton(AF_INET, addr_str, &addr); + if (result <= 0) { + vty_out(vty, "Bad unicast address %s: errno=%d: %s\n", addr_str, + errno, safe_strerror(errno)); + return CMD_WARNING; + } - if (pim_nexthop_lookup(&nexthop, addr, 0)) { - vty_out (vty, "Failure querying RIB nexthop for unicast address %s\n", - addr_str); - return CMD_WARNING; - } + if (pim_nexthop_lookup(&nexthop, addr, 0)) { + vty_out(vty, + "Failure querying RIB nexthop for unicast address %s\n", + addr_str); + return CMD_WARNING; + } - vty_out (vty, - "Address NextHop Interface Metric Preference\n"); + vty_out(vty, + "Address NextHop Interface Metric Preference\n"); - pim_addr_dump("", &nexthop.mrib_nexthop_addr, - nexthop_addr_str, sizeof(nexthop_addr_str)); + pim_addr_dump("", &nexthop.mrib_nexthop_addr, + nexthop_addr_str, sizeof(nexthop_addr_str)); - vty_out (vty, "%-15s %-15s %-9s %6d %10d\n", - addr_str, - nexthop_addr_str, - nexthop.interface ? nexthop.interface->name : "", - nexthop.mrib_route_metric, - nexthop.mrib_metric_preference); + vty_out(vty, "%-15s %-15s %-9s %6d %10d\n", addr_str, nexthop_addr_str, + nexthop.interface ? nexthop.interface->name : "", + nexthop.mrib_route_metric, nexthop.mrib_metric_preference); - return CMD_SUCCESS; + return CMD_SUCCESS; } static void show_ssmpingd(struct vty *vty) { - struct listnode *node; - struct ssmpingd_sock *ss; - time_t now; + struct listnode *node; + struct ssmpingd_sock *ss; + time_t now; - vty_out (vty, - "Source Socket Address Port Uptime Requests\n"); + vty_out(vty, + "Source Socket Address Port Uptime Requests\n"); - if (!qpim_ssmpingd_list) - return; + if (!qpim_ssmpingd_list) + return; - now = pim_time_monotonic_sec(); + now = pim_time_monotonic_sec(); - for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) { - char source_str[INET_ADDRSTRLEN]; - char ss_uptime[10]; - struct sockaddr_in bind_addr; - socklen_t len = sizeof(bind_addr); - char bind_addr_str[INET_ADDRSTRLEN]; + for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) { + char source_str[INET_ADDRSTRLEN]; + char ss_uptime[10]; + struct sockaddr_in bind_addr; + socklen_t len = sizeof(bind_addr); + char bind_addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", ss->source_addr, source_str, sizeof(source_str)); + pim_inet4_dump("", ss->source_addr, source_str, + sizeof(source_str)); - if (pim_socket_getsockname(ss->sock_fd, (struct sockaddr *) &bind_addr, &len)) { - vty_out (vty, "%% Failure reading socket name for ssmpingd source %s on fd=%d\n", - source_str, ss->sock_fd); - } + if (pim_socket_getsockname( + ss->sock_fd, (struct sockaddr *)&bind_addr, &len)) { + vty_out(vty, + "%% Failure reading socket name for ssmpingd source %s on fd=%d\n", + source_str, ss->sock_fd); + } - pim_inet4_dump("", bind_addr.sin_addr, bind_addr_str, sizeof(bind_addr_str)); - pim_time_uptime(ss_uptime, sizeof(ss_uptime), now - ss->creation); + pim_inet4_dump("", bind_addr.sin_addr, bind_addr_str, + sizeof(bind_addr_str)); + pim_time_uptime(ss_uptime, sizeof(ss_uptime), + now - ss->creation); - vty_out (vty, "%-15s %6d %-15s %5d %8s %8lld\n", - source_str, - ss->sock_fd, - bind_addr_str, - ntohs(bind_addr.sin_port), - ss_uptime, - (long long)ss->requests); - } + vty_out(vty, "%-15s %6d %-15s %5d %8s %8lld\n", source_str, + ss->sock_fd, bind_addr_str, ntohs(bind_addr.sin_port), + ss_uptime, (long long)ss->requests); + } } DEFUN (show_ip_ssmpingd, @@ -3740,89 +4217,82 @@ DEFUN (show_ip_ssmpingd, IP_STR SHOW_SSMPINGD_STR) { - show_ssmpingd(vty); - return CMD_SUCCESS; + show_ssmpingd(vty); + return CMD_SUCCESS; } -static int -pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group, const char *plist) +static int pim_rp_cmd_worker(struct vty *vty, const char *rp, const char *group, + const char *plist) { - int result; + int result; - result = pim_rp_new (rp, group, plist); + result = pim_rp_new(rp, group, plist); - if (result == PIM_MALLOC_FAIL) - { - vty_out (vty, "%% Out of memory\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (result == PIM_MALLOC_FAIL) { + vty_out(vty, "%% Out of memory\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (result == PIM_GROUP_BAD_ADDRESS) - { - vty_out (vty, "%% Bad group address specified: %s\n", group); - return CMD_WARNING_CONFIG_FAILED; - } + if (result == PIM_GROUP_BAD_ADDRESS) { + vty_out(vty, "%% Bad group address specified: %s\n", group); + return CMD_WARNING_CONFIG_FAILED; + } - if (result == PIM_RP_BAD_ADDRESS) - { - vty_out (vty, "%% Bad RP address specified: %s\n", rp); - return CMD_WARNING_CONFIG_FAILED; - } + if (result == PIM_RP_BAD_ADDRESS) { + vty_out(vty, "%% Bad RP address specified: %s\n", rp); + return CMD_WARNING_CONFIG_FAILED; + } - if (result == PIM_RP_NO_PATH) - { - vty_out (vty, "%% No Path to RP address specified: %s\n", rp); - return CMD_WARNING_CONFIG_FAILED; - } + if (result == PIM_RP_NO_PATH) { + vty_out(vty, "%% No Path to RP address specified: %s\n", rp); + return CMD_WARNING_CONFIG_FAILED; + } - if (result == PIM_GROUP_OVERLAP) - { - vty_out (vty, "%% Group range specified cannot overlap\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (result == PIM_GROUP_OVERLAP) { + vty_out(vty, "%% Group range specified cannot overlap\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (result == PIM_GROUP_PFXLIST_OVERLAP) - { - vty_out (vty, - "%% This group is already covered by a RP prefix-list\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (result == PIM_GROUP_PFXLIST_OVERLAP) { + vty_out(vty, + "%% This group is already covered by a RP prefix-list\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (result == PIM_RP_PFXLIST_IN_USE) - { - vty_out (vty, - "%% The same prefix-list cannot be applied to multiple RPs\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (result == PIM_RP_PFXLIST_IN_USE) { + vty_out(vty, + "%% The same prefix-list cannot be applied to multiple RPs\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -pim_cmd_spt_switchover (enum pim_spt_switchover spt, const char *plist) +static int pim_cmd_spt_switchover(enum pim_spt_switchover spt, + const char *plist) { - pimg->spt.switchover = spt; + pimg->spt.switchover = spt; - switch (pimg->spt.switchover) - { - case PIM_SPT_IMMEDIATE: - if (pimg->spt.plist) - XFREE (MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist); + switch (pimg->spt.switchover) { + case PIM_SPT_IMMEDIATE: + if (pimg->spt.plist) + XFREE(MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist); - pim_upstream_add_lhr_star_pimreg (); - break; - case PIM_SPT_INFINITY: - pim_upstream_remove_lhr_star_pimreg (plist); + pim_upstream_add_lhr_star_pimreg(); + break; + case PIM_SPT_INFINITY: + pim_upstream_remove_lhr_star_pimreg(plist); - if (pimg->spt.plist) - XFREE (MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist); + if (pimg->spt.plist) + XFREE(MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist); - if (plist) - pimg->spt.plist = XSTRDUP (MTYPE_PIM_SPT_PLIST_NAME, plist); - break; - } + if (plist) + pimg->spt.plist = + XSTRDUP(MTYPE_PIM_SPT_PLIST_NAME, plist); + break; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_pim_spt_switchover_infinity, @@ -3833,7 +4303,7 @@ DEFUN (ip_pim_spt_switchover_infinity, "SPT-Switchover\n" "Never switch to SPT Tree\n") { - return pim_cmd_spt_switchover (PIM_SPT_INFINITY, NULL); + return pim_cmd_spt_switchover(PIM_SPT_INFINITY, NULL); } DEFUN (ip_pim_spt_switchover_infinity_plist, @@ -3846,7 +4316,7 @@ DEFUN (ip_pim_spt_switchover_infinity_plist, "Prefix-List to control which groups to switch\n" "Prefix-List name\n") { - return pim_cmd_spt_switchover (PIM_SPT_INFINITY, argv[5]->arg); + return pim_cmd_spt_switchover(PIM_SPT_INFINITY, argv[5]->arg); } DEFUN (no_ip_pim_spt_switchover_infinity, @@ -3858,7 +4328,7 @@ DEFUN (no_ip_pim_spt_switchover_infinity, "SPT_Switchover\n" "Never switch to SPT Tree\n") { - return pim_cmd_spt_switchover (PIM_SPT_IMMEDIATE, NULL); + return pim_cmd_spt_switchover(PIM_SPT_IMMEDIATE, NULL); } DEFUN (no_ip_pim_spt_switchover_infinity_plist, @@ -3872,7 +4342,7 @@ DEFUN (no_ip_pim_spt_switchover_infinity_plist, "Prefix-List to control which groups to switch\n" "Prefix-List name\n") { - return pim_cmd_spt_switchover (PIM_SPT_IMMEDIATE, NULL); + return pim_cmd_spt_switchover(PIM_SPT_IMMEDIATE, NULL); } DEFUN (ip_pim_joinprune_time, @@ -3883,8 +4353,8 @@ DEFUN (ip_pim_joinprune_time, "Join Prune Send Interval\n" "Seconds\n") { - qpim_t_periodic = atoi(argv[3]->arg); - return CMD_SUCCESS; + qpim_t_periodic = atoi(argv[3]->arg); + return CMD_SUCCESS; } DEFUN (no_ip_pim_joinprune_time, @@ -3896,8 +4366,8 @@ DEFUN (no_ip_pim_joinprune_time, "Join Prune Send Interval\n" "Seconds\n") { - qpim_t_periodic = PIM_DEFAULT_T_PERIODIC; - return CMD_SUCCESS; + qpim_t_periodic = PIM_DEFAULT_T_PERIODIC; + return CMD_SUCCESS; } DEFUN (ip_pim_register_suppress, @@ -3908,8 +4378,8 @@ DEFUN (ip_pim_register_suppress, "Register Suppress Timer\n" "Seconds\n") { - qpim_register_suppress_time = atoi (argv[3]->arg); - return CMD_SUCCESS; + qpim_register_suppress_time = atoi(argv[3]->arg); + return CMD_SUCCESS; } DEFUN (no_ip_pim_register_suppress, @@ -3921,8 +4391,8 @@ DEFUN (no_ip_pim_register_suppress, "Register Suppress Timer\n" "Seconds\n") { - qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT; - return CMD_SUCCESS; + qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT; + return CMD_SUCCESS; } DEFUN (ip_pim_keep_alive, @@ -3933,8 +4403,8 @@ DEFUN (ip_pim_keep_alive, "Keep alive Timer\n" "Seconds\n") { - qpim_keep_alive_time = atoi (argv[3]->arg); - return CMD_SUCCESS; + qpim_keep_alive_time = atoi(argv[3]->arg); + return CMD_SUCCESS; } DEFUN (no_ip_pim_keep_alive, @@ -3946,8 +4416,8 @@ DEFUN (no_ip_pim_keep_alive, "Keep alive Timer\n" "Seconds\n") { - qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD; - return CMD_SUCCESS; + qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD; + return CMD_SUCCESS; } DEFUN (ip_pim_packets, @@ -3958,8 +4428,8 @@ DEFUN (ip_pim_packets, "packets to process at one time per fd\n" "Number of packets\n") { - qpim_packet_process = atoi (argv[3]->arg); - return CMD_SUCCESS; + qpim_packet_process = atoi(argv[3]->arg); + return CMD_SUCCESS; } DEFUN (no_ip_pim_packets, @@ -3971,8 +4441,8 @@ DEFUN (no_ip_pim_packets, "packets to process at one time per fd\n" "Number of packets\n") { - qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS; - return CMD_SUCCESS; + qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS; + return CMD_SUCCESS; } DEFUN (ip_pim_v6_secondary, @@ -3982,9 +4452,9 @@ DEFUN (ip_pim_v6_secondary, "pim multicast routing\n" "Send v6 secondary addresses\n") { - pimg->send_v6_secondary = 1; + pimg->send_v6_secondary = 1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_pim_v6_secondary, @@ -3995,9 +4465,9 @@ DEFUN (no_ip_pim_v6_secondary, "pim multicast routing\n" "Send v6 secondary addresses\n") { - pimg->send_v6_secondary = 0; + pimg->send_v6_secondary = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_pim_rp, @@ -4009,13 +4479,13 @@ DEFUN (ip_pim_rp, "ip address of RP\n" "Group Address range to cover\n") { - int idx_ipv4 = 3; - - if (argc == (idx_ipv4 + 1)) - return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, NULL, NULL); - else - return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL); + int idx_ipv4 = 3; + if (argc == (idx_ipv4 + 1)) + return pim_rp_cmd_worker(vty, argv[idx_ipv4]->arg, NULL, NULL); + else + return pim_rp_cmd_worker(vty, argv[idx_ipv4]->arg, + argv[idx_ipv4 + 1]->arg, NULL); } DEFUN (ip_pim_rp_prefix_list, @@ -4028,34 +4498,30 @@ DEFUN (ip_pim_rp_prefix_list, "group prefix-list filter\n" "Name of a prefix-list\n") { - return pim_rp_cmd_worker (vty, argv[3]->arg, NULL, argv[5]->arg); + return pim_rp_cmd_worker(vty, argv[3]->arg, NULL, argv[5]->arg); } -static int -pim_no_rp_cmd_worker (struct vty *vty, const char *rp, const char *group, - const char *plist) +static int pim_no_rp_cmd_worker(struct vty *vty, const char *rp, + const char *group, const char *plist) { - int result = pim_rp_del (rp, group, plist); + int result = pim_rp_del(rp, group, plist); - if (result == PIM_GROUP_BAD_ADDRESS) - { - vty_out (vty, "%% Bad group address specified: %s\n", group); - return CMD_WARNING_CONFIG_FAILED; - } + if (result == PIM_GROUP_BAD_ADDRESS) { + vty_out(vty, "%% Bad group address specified: %s\n", group); + return CMD_WARNING_CONFIG_FAILED; + } - if (result == PIM_RP_BAD_ADDRESS) - { - vty_out (vty, "%% Bad RP address specified: %s\n", rp); - return CMD_WARNING_CONFIG_FAILED; - } + if (result == PIM_RP_BAD_ADDRESS) { + vty_out(vty, "%% Bad RP address specified: %s\n", rp); + return CMD_WARNING_CONFIG_FAILED; + } - if (result == PIM_RP_NOT_FOUND) - { - vty_out (vty, "%% Unable to find specified RP\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (result == PIM_RP_NOT_FOUND) { + vty_out(vty, "%% Unable to find specified RP\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_pim_rp, @@ -4068,12 +4534,14 @@ DEFUN (no_ip_pim_rp, "ip address of RP\n" "Group Address range to cover\n") { - int idx_ipv4 = 4, idx_group = 0; + int idx_ipv4 = 4, idx_group = 0; - if (argv_find (argv, argc, "A.B.C.D/M", &idx_group)) - return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_group]->arg, NULL); - else - return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, NULL, NULL); + if (argv_find(argv, argc, "A.B.C.D/M", &idx_group)) + return pim_no_rp_cmd_worker(vty, argv[idx_ipv4]->arg, + argv[idx_group]->arg, NULL); + else + return pim_no_rp_cmd_worker(vty, argv[idx_ipv4]->arg, NULL, + NULL); } DEFUN (no_ip_pim_rp_prefix_list, @@ -4087,30 +4555,28 @@ DEFUN (no_ip_pim_rp_prefix_list, "group prefix-list filter\n" "Name of a prefix-list\n") { - return pim_no_rp_cmd_worker (vty, argv[4]->arg, NULL, argv[6]->arg); + return pim_no_rp_cmd_worker(vty, argv[4]->arg, NULL, argv[6]->arg); } -static int -pim_ssm_cmd_worker (struct vty *vty, const char *plist) +static int pim_ssm_cmd_worker(struct vty *vty, const char *plist) { - int result = pim_ssm_range_set (VRF_DEFAULT, plist); + int result = pim_ssm_range_set(VRF_DEFAULT, plist); - if (result == PIM_SSM_ERR_NONE) - return CMD_SUCCESS; + if (result == PIM_SSM_ERR_NONE) + return CMD_SUCCESS; - switch (result) - { - case PIM_SSM_ERR_NO_VRF: - vty_out (vty, "%% VRF doesn't exist\n"); - break; - case PIM_SSM_ERR_DUP: - vty_out (vty, "%% duplicate config\n"); - break; - default: - vty_out (vty, "%% ssm range config failed\n"); - } + switch (result) { + case PIM_SSM_ERR_NO_VRF: + vty_out(vty, "%% VRF doesn't exist\n"); + break; + case PIM_SSM_ERR_DUP: + vty_out(vty, "%% duplicate config\n"); + break; + default: + vty_out(vty, "%% ssm range config failed\n"); + } - return CMD_WARNING_CONFIG_FAILED; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (ip_pim_ssm_prefix_list, @@ -4122,7 +4588,7 @@ DEFUN (ip_pim_ssm_prefix_list, "group range prefix-list filter\n" "Name of a prefix-list\n") { - return pim_ssm_cmd_worker (vty, argv[0]->arg); + return pim_ssm_cmd_worker(vty, argv[0]->arg); } DEFUN (no_ip_pim_ssm_prefix_list, @@ -4134,7 +4600,7 @@ DEFUN (no_ip_pim_ssm_prefix_list, "Source Specific Multicast\n" "group range prefix-list filter\n") { - return pim_ssm_cmd_worker (vty, NULL); + return pim_ssm_cmd_worker(vty, NULL); } DEFUN (no_ip_pim_ssm_prefix_list_name, @@ -4147,34 +4613,31 @@ DEFUN (no_ip_pim_ssm_prefix_list_name, "group range prefix-list filter\n" "Name of a prefix-list\n") { - struct pim_ssm *ssm = pimg->ssm_info; + struct pim_ssm *ssm = pimg->ssm_info; - if (ssm->plist_name && !strcmp(ssm->plist_name, argv[0]->arg)) - return pim_ssm_cmd_worker (vty, NULL); + if (ssm->plist_name && !strcmp(ssm->plist_name, argv[0]->arg)) + return pim_ssm_cmd_worker(vty, NULL); - vty_out (vty, "%% pim ssm prefix-list %s doesn't exist\n", - argv[0]->arg); + vty_out(vty, "%% pim ssm prefix-list %s doesn't exist\n", argv[0]->arg); - return CMD_WARNING_CONFIG_FAILED; + return CMD_WARNING_CONFIG_FAILED; } -static void -ip_pim_ssm_show_group_range(struct vty *vty, u_char uj) +static void ip_pim_ssm_show_group_range(struct vty *vty, u_char uj) { - struct pim_ssm *ssm = pimg->ssm_info; - const char *range_str = ssm->plist_name?ssm->plist_name:PIM_SSM_STANDARD_RANGE; + struct pim_ssm *ssm = pimg->ssm_info; + const char *range_str = + ssm->plist_name ? ssm->plist_name : PIM_SSM_STANDARD_RANGE; - if (uj) - { - json_object *json; - json = json_object_new_object(); - json_object_string_add(json, "ssmGroups", range_str); - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - vty_out (vty, "SSM group range : %s\n", range_str); + if (uj) { + json_object *json; + json = json_object_new_object(); + json_object_string_add(json, "ssmGroups", range_str); + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else + vty_out(vty, "SSM group range : %s\n", range_str); } DEFUN (show_ip_pim_ssm_range, @@ -4186,41 +4649,38 @@ DEFUN (show_ip_pim_ssm_range, "PIM group type\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - ip_pim_ssm_show_group_range(vty, uj); + u_char uj = use_json(argc, argv); + ip_pim_ssm_show_group_range(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static void -ip_pim_ssm_show_group_type(struct vty *vty, u_char uj, const char *group) +static void ip_pim_ssm_show_group_type(struct vty *vty, u_char uj, + const char *group) { - struct in_addr group_addr; - const char *type_str; - int result; + struct in_addr group_addr; + const char *type_str; + int result; - result = inet_pton(AF_INET, group, &group_addr); - if (result <= 0) - type_str = "invalid"; - else - { - if (pim_is_group_224_4 (group_addr)) - type_str = pim_is_grp_ssm (group_addr)?"SSM":"ASM"; - else - type_str = "not-multicast"; - } + result = inet_pton(AF_INET, group, &group_addr); + if (result <= 0) + type_str = "invalid"; + else { + if (pim_is_group_224_4(group_addr)) + type_str = pim_is_grp_ssm(group_addr) ? "SSM" : "ASM"; + else + type_str = "not-multicast"; + } - if (uj) - { - json_object *json; - json = json_object_new_object(); - json_object_string_add(json, "groupType", type_str); - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - vty_out (vty, "Group type : %s\n", type_str); + if (uj) { + json_object *json; + json = json_object_new_object(); + json_object_string_add(json, "groupType", type_str); + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else + vty_out(vty, "Group type : %s\n", type_str); } DEFUN (show_ip_pim_group_type, @@ -4233,10 +4693,10 @@ DEFUN (show_ip_pim_group_type, "group address\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - ip_pim_ssm_show_group_type(vty, uj, argv[0]->arg); + u_char uj = use_json(argc, argv); + ip_pim_ssm_show_group_type(vty, uj, argv[0]->arg); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_HIDDEN (ip_multicast_routing, @@ -4245,7 +4705,7 @@ DEFUN_HIDDEN (ip_multicast_routing, IP_STR "Enable IP multicast forwarding\n") { - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_HIDDEN (no_ip_multicast_routing, @@ -4255,9 +4715,9 @@ DEFUN_HIDDEN (no_ip_multicast_routing, IP_STR "Enable IP multicast forwarding\n") { - vty_out (vty, - "Command is Disabled and will be removed in a future version\n"); - return CMD_SUCCESS; + vty_out(vty, + "Command is Disabled and will be removed in a future version\n"); + return CMD_SUCCESS; } DEFUN (ip_ssmpingd, @@ -4267,26 +4727,26 @@ DEFUN (ip_ssmpingd, CONF_SSMPINGD_STR "Source address\n") { - int idx_ipv4 = 2; - int result; - struct in_addr source_addr; - const char *source_str = (argc == 3) ? argv[idx_ipv4]->arg : "0.0.0.0"; + int idx_ipv4 = 2; + int result; + struct in_addr source_addr; + const char *source_str = (argc == 3) ? argv[idx_ipv4]->arg : "0.0.0.0"; - result = inet_pton(AF_INET, source_str, &source_addr); - if (result <= 0) { - vty_out (vty, "%% Bad source address %s: errno=%d: %s\n", - source_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + result = inet_pton(AF_INET, source_str, &source_addr); + if (result <= 0) { + vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", + source_str, errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - result = pim_ssmpingd_start(source_addr); - if (result) { - vty_out (vty, "%% Failure starting ssmpingd for source %s: %d\n", - source_str, result); - return CMD_WARNING_CONFIG_FAILED; - } + result = pim_ssmpingd_start(source_addr); + if (result) { + vty_out(vty, "%% Failure starting ssmpingd for source %s: %d\n", + source_str, result); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_ssmpingd, @@ -4297,26 +4757,26 @@ DEFUN (no_ip_ssmpingd, CONF_SSMPINGD_STR "Source address\n") { - int idx_ipv4 = 3; - int result; - struct in_addr source_addr; - const char *source_str = (argc == 4) ? argv[idx_ipv4]->arg : "0.0.0.0"; + int idx_ipv4 = 3; + int result; + struct in_addr source_addr; + const char *source_str = (argc == 4) ? argv[idx_ipv4]->arg : "0.0.0.0"; - result = inet_pton(AF_INET, source_str, &source_addr); - if (result <= 0) { - vty_out (vty, "%% Bad source address %s: errno=%d: %s\n", - source_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + result = inet_pton(AF_INET, source_str, &source_addr); + if (result <= 0) { + vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", + source_str, errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - result = pim_ssmpingd_stop(source_addr); - if (result) { - vty_out (vty, "%% Failure stopping ssmpingd for source %s: %d\n", - source_str, result); - return CMD_WARNING_CONFIG_FAILED; - } + result = pim_ssmpingd_stop(source_addr); + if (result) { + vty_out(vty, "%% Failure stopping ssmpingd for source %s: %d\n", + source_str, result); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_pim_ecmp, @@ -4326,9 +4786,9 @@ DEFUN (ip_pim_ecmp, "pim multicast routing\n" "Enable PIM ECMP \n") { - qpim_ecmp_enable = 1; + qpim_ecmp_enable = 1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_pim_ecmp, @@ -4339,9 +4799,9 @@ DEFUN (no_ip_pim_ecmp, "pim multicast routing\n" "Disable PIM ECMP \n") { - qpim_ecmp_enable = 0; + qpim_ecmp_enable = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_pim_ecmp_rebalance, @@ -4352,10 +4812,10 @@ DEFUN (ip_pim_ecmp_rebalance, "Enable PIM ECMP \n" "Enable PIM ECMP Rebalance\n") { - qpim_ecmp_enable = 1; - qpim_ecmp_rebalance_enable = 1; + qpim_ecmp_enable = 1; + qpim_ecmp_rebalance_enable = 1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_pim_ecmp_rebalance, @@ -4367,48 +4827,41 @@ DEFUN (no_ip_pim_ecmp_rebalance, "Disable PIM ECMP \n" "Disable PIM ECMP Rebalance\n") { - qpim_ecmp_rebalance_enable = 0; + qpim_ecmp_rebalance_enable = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -pim_cmd_igmp_start (struct vty *vty, struct interface *ifp) +static int pim_cmd_igmp_start(struct vty *vty, struct interface *ifp) { - struct pim_interface *pim_ifp; - uint8_t need_startup = 0; + struct pim_interface *pim_ifp; + uint8_t need_startup = 0; - pim_ifp = ifp->info; + pim_ifp = ifp->info; - if (!pim_ifp) - { - pim_ifp = pim_if_new(ifp, 1 /* igmp=true */, 0 /* pim=false */); - if (!pim_ifp) - { - vty_out (vty, "Could not enable IGMP on interface %s\n", - ifp->name); - return CMD_WARNING_CONFIG_FAILED; - } - need_startup = 1; - } - else - { - if (!PIM_IF_TEST_IGMP(pim_ifp->options)) - { - PIM_IF_DO_IGMP(pim_ifp->options); - need_startup = 1; - } - } + if (!pim_ifp) { + pim_ifp = pim_if_new(ifp, 1 /* igmp=true */, 0 /* pim=false */); + if (!pim_ifp) { + vty_out(vty, "Could not enable IGMP on interface %s\n", + ifp->name); + return CMD_WARNING_CONFIG_FAILED; + } + need_startup = 1; + } else { + if (!PIM_IF_TEST_IGMP(pim_ifp->options)) { + PIM_IF_DO_IGMP(pim_ifp->options); + need_startup = 1; + } + } - /* 'ip igmp' executed multiple times, with need_startup - avoid multiple if add all and membership refresh */ - if (need_startup) - { - pim_if_addr_add_all(ifp); - pim_if_membership_refresh(ifp); - } + /* 'ip igmp' executed multiple times, with need_startup + avoid multiple if add all and membership refresh */ + if (need_startup) { + pim_if_addr_add_all(ifp); + pim_if_membership_refresh(ifp); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (interface_ip_igmp, @@ -4417,9 +4870,9 @@ DEFUN (interface_ip_igmp, IP_STR IFACE_IGMP_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - return pim_cmd_igmp_start(vty, ifp); + return pim_cmd_igmp_start(vty, ifp); } DEFUN (interface_no_ip_igmp, @@ -4429,23 +4882,23 @@ DEFUN (interface_no_ip_igmp, IP_STR IFACE_IGMP_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) - return CMD_SUCCESS; + if (!pim_ifp) + return CMD_SUCCESS; - PIM_IF_DONT_IGMP(pim_ifp->options); + PIM_IF_DONT_IGMP(pim_ifp->options); - pim_if_membership_clear(ifp); + pim_if_membership_clear(ifp); - pim_if_addr_del_all_igmp(ifp); + pim_if_addr_del_all_igmp(ifp); - if (!PIM_IF_TEST_PIM(pim_ifp->options)) { - pim_if_delete(ifp); - } + if (!PIM_IF_TEST_PIM(pim_ifp->options)) { + pim_if_delete(ifp); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (interface_ip_igmp_join, @@ -4457,41 +4910,42 @@ DEFUN (interface_ip_igmp_join, "Multicast group address\n" "Source address\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_ipv4 = 3; - int idx_ipv4_2 = 4; - const char *group_str; - const char *source_str; - struct in_addr group_addr; - struct in_addr source_addr; - int result; - - /* Group address */ - group_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, group_str, &group_addr); - if (result <= 0) { - vty_out (vty, "Bad group address %s: errno=%d: %s\n", - group_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Source address */ - source_str = argv[idx_ipv4_2]->arg; - result = inet_pton(AF_INET, source_str, &source_addr); - if (result <= 0) { - vty_out (vty, "Bad source address %s: errno=%d: %s\n", - source_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - result = pim_if_igmp_join_add(ifp, group_addr, source_addr); - if (result) { - vty_out (vty, "%% Failure joining IGMP group %s source %s on interface %s: %d\n", - group_str, source_str, ifp->name, result); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_ipv4 = 3; + int idx_ipv4_2 = 4; + const char *group_str; + const char *source_str; + struct in_addr group_addr; + struct in_addr source_addr; + int result; + + /* Group address */ + group_str = argv[idx_ipv4]->arg; + result = inet_pton(AF_INET, group_str, &group_addr); + if (result <= 0) { + vty_out(vty, "Bad group address %s: errno=%d: %s\n", group_str, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Source address */ + source_str = argv[idx_ipv4_2]->arg; + result = inet_pton(AF_INET, source_str, &source_addr); + if (result <= 0) { + vty_out(vty, "Bad source address %s: errno=%d: %s\n", + source_str, errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + result = pim_if_igmp_join_add(ifp, group_addr, source_addr); + if (result) { + vty_out(vty, + "%% Failure joining IGMP group %s source %s on interface %s: %d\n", + group_str, source_str, ifp->name, result); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } DEFUN (interface_no_ip_igmp_join, @@ -4504,41 +4958,42 @@ DEFUN (interface_no_ip_igmp_join, "Multicast group address\n" "Source address\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_ipv4 = 4; - int idx_ipv4_2 = 5; - const char *group_str; - const char *source_str; - struct in_addr group_addr; - struct in_addr source_addr; - int result; - - /* Group address */ - group_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, group_str, &group_addr); - if (result <= 0) { - vty_out (vty, "Bad group address %s: errno=%d: %s\n", - group_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Source address */ - source_str = argv[idx_ipv4_2]->arg; - result = inet_pton(AF_INET, source_str, &source_addr); - if (result <= 0) { - vty_out (vty, "Bad source address %s: errno=%d: %s\n", - source_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - result = pim_if_igmp_join_del(ifp, group_addr, source_addr); - if (result) { - vty_out (vty, "%% Failure leaving IGMP group %s source %s on interface %s: %d\n", - group_str, source_str, ifp->name, result); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_ipv4 = 4; + int idx_ipv4_2 = 5; + const char *group_str; + const char *source_str; + struct in_addr group_addr; + struct in_addr source_addr; + int result; + + /* Group address */ + group_str = argv[idx_ipv4]->arg; + result = inet_pton(AF_INET, group_str, &group_addr); + if (result <= 0) { + vty_out(vty, "Bad group address %s: errno=%d: %s\n", group_str, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Source address */ + source_str = argv[idx_ipv4_2]->arg; + result = inet_pton(AF_INET, source_str, &source_addr); + if (result <= 0) { + vty_out(vty, "Bad source address %s: errno=%d: %s\n", + source_str, errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + result = pim_if_igmp_join_del(ifp, group_addr, source_addr); + if (result) { + vty_out(vty, + "%% Failure leaving IGMP group %s source %s on interface %s: %d\n", + group_str, source_str, ifp->name, result); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } /* @@ -4548,125 +5003,127 @@ DEFUN (interface_no_ip_igmp_join, */ static void igmp_sock_query_interval_reconfig(struct igmp_sock *igmp) { - struct interface *ifp; - struct pim_interface *pim_ifp; + struct interface *ifp; + struct pim_interface *pim_ifp; - zassert(igmp); + zassert(igmp); - /* other querier present? */ + /* other querier present? */ - if (igmp->t_other_querier_timer) - return; + if (igmp->t_other_querier_timer) + return; - /* this is the querier */ + /* this is the querier */ - zassert(igmp->interface); - zassert(igmp->interface->info); + zassert(igmp->interface); + zassert(igmp->interface->info); - ifp = igmp->interface; - pim_ifp = ifp->info; + ifp = igmp->interface; + pim_ifp = ifp->info; - if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - zlog_debug("%s: Querier %s on %s reconfig query_interval=%d", - __PRETTY_FUNCTION__, - ifaddr_str, - ifp->name, - pim_ifp->igmp_default_query_interval); - } + if (PIM_DEBUG_IGMP_TRACE) { + char ifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + zlog_debug("%s: Querier %s on %s reconfig query_interval=%d", + __PRETTY_FUNCTION__, ifaddr_str, ifp->name, + pim_ifp->igmp_default_query_interval); + } - /* - igmp_startup_mode_on() will reset QQI: + /* + igmp_startup_mode_on() will reset QQI: - igmp->querier_query_interval = pim_ifp->igmp_default_query_interval; - */ - igmp_startup_mode_on(igmp); + igmp->querier_query_interval = pim_ifp->igmp_default_query_interval; + */ + igmp_startup_mode_on(igmp); } static void igmp_sock_query_reschedule(struct igmp_sock *igmp) { - if (igmp->t_igmp_query_timer) { - /* other querier present */ - zassert(igmp->t_igmp_query_timer); - zassert(!igmp->t_other_querier_timer); + if (igmp->t_igmp_query_timer) { + /* other querier present */ + zassert(igmp->t_igmp_query_timer); + zassert(!igmp->t_other_querier_timer); - pim_igmp_general_query_off(igmp); - pim_igmp_general_query_on(igmp); + pim_igmp_general_query_off(igmp); + pim_igmp_general_query_on(igmp); - zassert(igmp->t_igmp_query_timer); - zassert(!igmp->t_other_querier_timer); - } - else { - /* this is the querier */ + zassert(igmp->t_igmp_query_timer); + zassert(!igmp->t_other_querier_timer); + } else { + /* this is the querier */ - zassert(!igmp->t_igmp_query_timer); - zassert(igmp->t_other_querier_timer); + zassert(!igmp->t_igmp_query_timer); + zassert(igmp->t_other_querier_timer); - pim_igmp_other_querier_timer_off(igmp); - pim_igmp_other_querier_timer_on(igmp); + pim_igmp_other_querier_timer_off(igmp); + pim_igmp_other_querier_timer_on(igmp); - zassert(!igmp->t_igmp_query_timer); - zassert(igmp->t_other_querier_timer); - } + zassert(!igmp->t_igmp_query_timer); + zassert(igmp->t_other_querier_timer); + } } static void change_query_interval(struct pim_interface *pim_ifp, int query_interval) { - struct listnode *sock_node; - struct igmp_sock *igmp; + struct listnode *sock_node; + struct igmp_sock *igmp; - pim_ifp->igmp_default_query_interval = query_interval; + pim_ifp->igmp_default_query_interval = query_interval; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - igmp_sock_query_interval_reconfig(igmp); - igmp_sock_query_reschedule(igmp); - } + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { + igmp_sock_query_interval_reconfig(igmp); + igmp_sock_query_reschedule(igmp); + } } static void change_query_max_response_time(struct pim_interface *pim_ifp, int query_max_response_time_dsec) { - struct listnode *sock_node; - struct igmp_sock *igmp; - - pim_ifp->igmp_query_max_response_time_dsec = query_max_response_time_dsec; - - /* - Below we modify socket/group/source timers in order to quickly - reflect the change. Otherwise, those timers would eventually catch - up. - */ - - /* scan all sockets */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { - struct listnode *grp_node; - struct igmp_group *grp; - - /* reschedule socket general query */ - igmp_sock_query_reschedule(igmp); - - /* scan socket groups */ - for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grp_node, grp)) { - struct listnode *src_node; - struct igmp_source *src; - - /* reset group timers for groups in EXCLUDE mode */ - if (grp->group_filtermode_isexcl) { - igmp_group_reset_gmi(grp); - } - - /* scan group sources */ - for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, src_node, src)) { - - /* reset source timers for sources with running timers */ - if (src->t_source_timer) { - igmp_source_reset_gmi(igmp, grp, src); + struct listnode *sock_node; + struct igmp_sock *igmp; + + pim_ifp->igmp_query_max_response_time_dsec = + query_max_response_time_dsec; + + /* + Below we modify socket/group/source timers in order to quickly + reflect the change. Otherwise, those timers would eventually catch + up. + */ + + /* scan all sockets */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) { + struct listnode *grp_node; + struct igmp_group *grp; + + /* reschedule socket general query */ + igmp_sock_query_reschedule(igmp); + + /* scan socket groups */ + for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grp_node, + grp)) { + struct listnode *src_node; + struct igmp_source *src; + + /* reset group timers for groups in EXCLUDE mode */ + if (grp->group_filtermode_isexcl) { + igmp_group_reset_gmi(grp); + } + + /* scan group sources */ + for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, + src_node, src)) { + + /* reset source timers for sources with running + * timers */ + if (src->t_source_timer) { + igmp_source_reset_gmi(igmp, grp, src); + } + } + } } - } - } - } } #define IGMP_QUERY_INTERVAL_MIN (1) @@ -4680,49 +5137,50 @@ DEFUN (interface_ip_igmp_query_interval, IFACE_IGMP_QUERY_INTERVAL_STR "Query interval in seconds\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; - int query_interval; - int query_interval_dsec; - int ret; - - if (!pim_ifp) { - ret = pim_cmd_igmp_start(vty, ifp); - if (ret != CMD_SUCCESS) - return ret; - pim_ifp = ifp->info; - } - - query_interval = atoi(argv[3]->arg); - query_interval_dsec = 10 * query_interval; - - /* - It seems we don't need to check bounds since command.c does it - already, but we verify them anyway for extra safety. - */ - if (query_interval < IGMP_QUERY_INTERVAL_MIN) { - vty_out (vty, "General query interval %d lower than minimum %d\n", - query_interval, - IGMP_QUERY_INTERVAL_MIN); - return CMD_WARNING_CONFIG_FAILED; - } - if (query_interval > IGMP_QUERY_INTERVAL_MAX) { - vty_out (vty, "General query interval %d higher than maximum %d\n", - query_interval, - IGMP_QUERY_INTERVAL_MAX); - return CMD_WARNING_CONFIG_FAILED; - } - - if (query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) { - vty_out (vty, - "Can't set general query interval %d dsec <= query max response time %d dsec.\n", - query_interval_dsec,pim_ifp->igmp_query_max_response_time_dsec); - return CMD_WARNING_CONFIG_FAILED; - } - - change_query_interval(pim_ifp, query_interval); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; + int query_interval; + int query_interval_dsec; + int ret; + + if (!pim_ifp) { + ret = pim_cmd_igmp_start(vty, ifp); + if (ret != CMD_SUCCESS) + return ret; + pim_ifp = ifp->info; + } + + query_interval = atoi(argv[3]->arg); + query_interval_dsec = 10 * query_interval; + + /* + It seems we don't need to check bounds since command.c does it + already, but we verify them anyway for extra safety. + */ + if (query_interval < IGMP_QUERY_INTERVAL_MIN) { + vty_out(vty, + "General query interval %d lower than minimum %d\n", + query_interval, IGMP_QUERY_INTERVAL_MIN); + return CMD_WARNING_CONFIG_FAILED; + } + if (query_interval > IGMP_QUERY_INTERVAL_MAX) { + vty_out(vty, + "General query interval %d higher than maximum %d\n", + query_interval, IGMP_QUERY_INTERVAL_MAX); + return CMD_WARNING_CONFIG_FAILED; + } + + if (query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) { + vty_out(vty, + "Can't set general query interval %d dsec <= query max response time %d dsec.\n", + query_interval_dsec, + pim_ifp->igmp_query_max_response_time_dsec); + return CMD_WARNING_CONFIG_FAILED; + } + + change_query_interval(pim_ifp, query_interval); + + return CMD_SUCCESS; } DEFUN (interface_no_ip_igmp_query_interval, @@ -4733,26 +5191,27 @@ DEFUN (interface_no_ip_igmp_query_interval, IFACE_IGMP_STR IFACE_IGMP_QUERY_INTERVAL_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; - int default_query_interval_dsec; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; + int default_query_interval_dsec; - if (!pim_ifp) - return CMD_SUCCESS; + if (!pim_ifp) + return CMD_SUCCESS; - default_query_interval_dsec = IGMP_GENERAL_QUERY_INTERVAL * 10; + default_query_interval_dsec = IGMP_GENERAL_QUERY_INTERVAL * 10; - if (default_query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) { - vty_out (vty, - "Can't set default general query interval %d dsec <= query max response time %d dsec.\n", - default_query_interval_dsec, - pim_ifp->igmp_query_max_response_time_dsec); - return CMD_WARNING_CONFIG_FAILED; - } + if (default_query_interval_dsec + <= pim_ifp->igmp_query_max_response_time_dsec) { + vty_out(vty, + "Can't set default general query interval %d dsec <= query max response time %d dsec.\n", + default_query_interval_dsec, + pim_ifp->igmp_query_max_response_time_dsec); + return CMD_WARNING_CONFIG_FAILED; + } - change_query_interval(pim_ifp, IGMP_GENERAL_QUERY_INTERVAL); + change_query_interval(pim_ifp, IGMP_GENERAL_QUERY_INTERVAL); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (interface_ip_igmp_version, @@ -4763,37 +5222,36 @@ DEFUN (interface_ip_igmp_version, "IGMP version\n" "IGMP version number\n") { - VTY_DECLVAR_CONTEXT(interface,ifp); - struct pim_interface *pim_ifp = ifp->info; - int igmp_version, old_version = 0; - int ret; - - if (!pim_ifp) - { - ret = pim_cmd_igmp_start(vty, ifp); - if (ret != CMD_SUCCESS) - return ret; - pim_ifp = ifp->info; - } - - igmp_version = atoi(argv[3]->arg); - old_version = pim_ifp->igmp_version; - pim_ifp->igmp_version = igmp_version; - - //Check if IGMP is Enabled otherwise, enable on interface - if (!PIM_IF_TEST_IGMP (pim_ifp->options)) - { - PIM_IF_DO_IGMP(pim_ifp->options); - pim_if_addr_add_all(ifp); - pim_if_membership_refresh(ifp); - old_version = igmp_version; //avoid refreshing membership again. - } - /* Current and new version is different refresh existing - membership. Going from 3 -> 2 or 2 -> 3. */ - if (old_version != igmp_version) - pim_if_membership_refresh(ifp); - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; + int igmp_version, old_version = 0; + int ret; + + if (!pim_ifp) { + ret = pim_cmd_igmp_start(vty, ifp); + if (ret != CMD_SUCCESS) + return ret; + pim_ifp = ifp->info; + } + + igmp_version = atoi(argv[3]->arg); + old_version = pim_ifp->igmp_version; + pim_ifp->igmp_version = igmp_version; + + // Check if IGMP is Enabled otherwise, enable on interface + if (!PIM_IF_TEST_IGMP(pim_ifp->options)) { + PIM_IF_DO_IGMP(pim_ifp->options); + pim_if_addr_add_all(ifp); + pim_if_membership_refresh(ifp); + old_version = igmp_version; // avoid refreshing membership + // again. + } + /* Current and new version is different refresh existing + membership. Going from 3 -> 2 or 2 -> 3. */ + if (old_version != igmp_version) + pim_if_membership_refresh(ifp); + + return CMD_SUCCESS; } DEFUN (interface_no_ip_igmp_version, @@ -4805,15 +5263,15 @@ DEFUN (interface_no_ip_igmp_version, "IGMP version\n" "IGMP version number\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) - return CMD_SUCCESS; + if (!pim_ifp) + return CMD_SUCCESS; - pim_ifp->igmp_version = IGMP_DEFAULT_VERSION; + pim_ifp->igmp_version = IGMP_DEFAULT_VERSION; - return CMD_SUCCESS; + return CMD_SUCCESS; } #define IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC (10) @@ -4827,30 +5285,32 @@ DEFUN (interface_ip_igmp_query_max_response_time, IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR "Query response value in deci-seconds\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; - int query_max_response_time; - int ret; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; + int query_max_response_time; + int ret; - if (!pim_ifp) { - ret = pim_cmd_igmp_start(vty, ifp); - if (ret != CMD_SUCCESS) - return ret; - pim_ifp = ifp->info; - } + if (!pim_ifp) { + ret = pim_cmd_igmp_start(vty, ifp); + if (ret != CMD_SUCCESS) + return ret; + pim_ifp = ifp->info; + } - query_max_response_time = atoi(argv[3]->arg); + query_max_response_time = atoi(argv[3]->arg); - if (query_max_response_time >= pim_ifp->igmp_default_query_interval * 10) { - vty_out (vty, - "Can't set query max response time %d sec >= general query interval %d sec\n", - query_max_response_time,pim_ifp->igmp_default_query_interval); - return CMD_WARNING_CONFIG_FAILED; - } + if (query_max_response_time + >= pim_ifp->igmp_default_query_interval * 10) { + vty_out(vty, + "Can't set query max response time %d sec >= general query interval %d sec\n", + query_max_response_time, + pim_ifp->igmp_default_query_interval); + return CMD_WARNING_CONFIG_FAILED; + } - change_query_max_response_time(pim_ifp, query_max_response_time); + change_query_max_response_time(pim_ifp, query_max_response_time); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (interface_no_ip_igmp_query_max_response_time, @@ -4862,15 +5322,16 @@ DEFUN (interface_no_ip_igmp_query_max_response_time, IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR "Time for response in deci-seconds\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) - return CMD_SUCCESS; + if (!pim_ifp) + return CMD_SUCCESS; - change_query_max_response_time(pim_ifp, IGMP_QUERY_MAX_RESPONSE_TIME_DSEC); + change_query_max_response_time(pim_ifp, + IGMP_QUERY_MAX_RESPONSE_TIME_DSEC); - return CMD_SUCCESS; + return CMD_SUCCESS; } #define IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC (10) @@ -4884,33 +5345,34 @@ DEFUN_HIDDEN (interface_ip_igmp_query_max_response_time_dsec, IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR "Query response value in deciseconds\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; - int query_max_response_time_dsec; - int default_query_interval_dsec; - int ret; - - if (!pim_ifp) { - ret = pim_cmd_igmp_start(vty, ifp); - if (ret != CMD_SUCCESS) - return ret; - pim_ifp = ifp->info; - } + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; + int query_max_response_time_dsec; + int default_query_interval_dsec; + int ret; + + if (!pim_ifp) { + ret = pim_cmd_igmp_start(vty, ifp); + if (ret != CMD_SUCCESS) + return ret; + pim_ifp = ifp->info; + } - query_max_response_time_dsec = atoi(argv[4]->arg); + query_max_response_time_dsec = atoi(argv[4]->arg); - default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval; + default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval; - if (query_max_response_time_dsec >= default_query_interval_dsec) { - vty_out (vty, - "Can't set query max response time %d dsec >= general query interval %d dsec\n", - query_max_response_time_dsec,default_query_interval_dsec); - return CMD_WARNING_CONFIG_FAILED; - } + if (query_max_response_time_dsec >= default_query_interval_dsec) { + vty_out(vty, + "Can't set query max response time %d dsec >= general query interval %d dsec\n", + query_max_response_time_dsec, + default_query_interval_dsec); + return CMD_WARNING_CONFIG_FAILED; + } - change_query_max_response_time(pim_ifp, query_max_response_time_dsec); + change_query_max_response_time(pim_ifp, query_max_response_time_dsec); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_HIDDEN (interface_no_ip_igmp_query_max_response_time_dsec, @@ -4921,15 +5383,16 @@ DEFUN_HIDDEN (interface_no_ip_igmp_query_max_response_time_dsec, IFACE_IGMP_STR IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) - return CMD_SUCCESS; + if (!pim_ifp) + return CMD_SUCCESS; - change_query_max_response_time(pim_ifp, IGMP_QUERY_MAX_RESPONSE_TIME_DSEC); + change_query_max_response_time(pim_ifp, + IGMP_QUERY_MAX_RESPONSE_TIME_DSEC); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (interface_ip_pim_drprio, @@ -4940,26 +5403,26 @@ DEFUN (interface_ip_pim_drprio, "Set the Designated Router Election Priority\n" "Value of the new DR Priority\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_number = 3; - struct pim_interface *pim_ifp = ifp->info; - uint32_t old_dr_prio; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_number = 3; + struct pim_interface *pim_ifp = ifp->info; + uint32_t old_dr_prio; - if (!pim_ifp) { - vty_out (vty, "Please enable PIM on interface, first\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!pim_ifp) { + vty_out(vty, "Please enable PIM on interface, first\n"); + return CMD_WARNING_CONFIG_FAILED; + } - old_dr_prio = pim_ifp->pim_dr_priority; + old_dr_prio = pim_ifp->pim_dr_priority; - pim_ifp->pim_dr_priority = strtol(argv[idx_number]->arg, NULL, 10); + pim_ifp->pim_dr_priority = strtol(argv[idx_number]->arg, NULL, 10); - if (old_dr_prio != pim_ifp->pim_dr_priority) { - if (pim_if_dr_election(ifp)) - pim_hello_restart_now(ifp); - } + if (old_dr_prio != pim_ifp->pim_dr_priority) { + if (pim_if_dr_election(ifp)) + pim_hello_restart_now(ifp); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (interface_no_ip_pim_drprio, @@ -4971,41 +5434,39 @@ DEFUN (interface_no_ip_pim_drprio, "Revert the Designated Router Priority to default\n" "Old Value of the Priority\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) { - vty_out (vty, "Pim not enabled on this interface\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!pim_ifp) { + vty_out(vty, "Pim not enabled on this interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (pim_ifp->pim_dr_priority != PIM_DEFAULT_DR_PRIORITY) { - pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY; - if (pim_if_dr_election(ifp)) - pim_hello_restart_now(ifp); - } + if (pim_ifp->pim_dr_priority != PIM_DEFAULT_DR_PRIORITY) { + pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY; + if (pim_if_dr_election(ifp)) + pim_hello_restart_now(ifp); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -pim_cmd_interface_add (struct interface *ifp) +static int pim_cmd_interface_add(struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) { - pim_ifp = pim_if_new(ifp, 0 /* igmp=false */, 1 /* pim=true */); - if (!pim_ifp) { - return 0; - } - } - else { - PIM_IF_DO_PIM(pim_ifp->options); - } + if (!pim_ifp) { + pim_ifp = pim_if_new(ifp, 0 /* igmp=false */, 1 /* pim=true */); + if (!pim_ifp) { + return 0; + } + } else { + PIM_IF_DO_PIM(pim_ifp->options); + } - pim_if_addr_add_all(ifp); - pim_if_membership_refresh(ifp); - return 1; + pim_if_addr_add_all(ifp); + pim_if_membership_refresh(ifp); + return 1; } DEFUN_HIDDEN (interface_ip_pim_ssm, @@ -5015,16 +5476,17 @@ DEFUN_HIDDEN (interface_ip_pim_ssm, PIM_STR IFACE_PIM_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - if (!pim_cmd_interface_add(ifp)) { - vty_out (vty, "Could not enable PIM SM on interface\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!pim_cmd_interface_add(ifp)) { + vty_out(vty, "Could not enable PIM SM on interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } - vty_out(vty, "WARN: Enabled PIM SM on interface; configure PIM SSM " - "range if needed\n"); - return CMD_SUCCESS; + vty_out(vty, + "WARN: Enabled PIM SM on interface; configure PIM SSM " + "range if needed\n"); + return CMD_SUCCESS; } DEFUN (interface_ip_pim_sm, @@ -5034,41 +5496,40 @@ DEFUN (interface_ip_pim_sm, PIM_STR IFACE_PIM_SM_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); - if (!pim_cmd_interface_add(ifp)) { - vty_out (vty, "Could not enable PIM SM on interface\n"); - return CMD_WARNING_CONFIG_FAILED; - } + VTY_DECLVAR_CONTEXT(interface, ifp); + if (!pim_cmd_interface_add(ifp)) { + vty_out(vty, "Could not enable PIM SM on interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } - pim_if_create_pimreg(); + pim_if_create_pimreg(); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -pim_cmd_interface_delete (struct interface *ifp) +static int pim_cmd_interface_delete(struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) - return 1; + if (!pim_ifp) + return 1; - PIM_IF_DONT_PIM(pim_ifp->options); + PIM_IF_DONT_PIM(pim_ifp->options); - pim_if_membership_clear(ifp); + pim_if_membership_clear(ifp); - /* - pim_sock_delete() removes all neighbors from - pim_ifp->pim_neighbor_list. - */ - pim_sock_delete(ifp, "pim unconfigured on interface"); + /* + pim_sock_delete() removes all neighbors from + pim_ifp->pim_neighbor_list. + */ + pim_sock_delete(ifp, "pim unconfigured on interface"); - if (!PIM_IF_TEST_IGMP(pim_ifp->options)) { - pim_if_addr_del_all(ifp); - pim_if_delete(ifp); - } + if (!PIM_IF_TEST_IGMP(pim_ifp->options)) { + pim_if_addr_del_all(ifp); + pim_if_delete(ifp); + } - return 1; + return 1; } DEFUN_HIDDEN (interface_no_ip_pim_ssm, @@ -5079,13 +5540,13 @@ DEFUN_HIDDEN (interface_no_ip_pim_ssm, PIM_STR IFACE_PIM_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); - if (!pim_cmd_interface_delete(ifp)) { - vty_out (vty, "Unable to delete interface information\n"); - return CMD_WARNING_CONFIG_FAILED; - } + VTY_DECLVAR_CONTEXT(interface, ifp); + if (!pim_cmd_interface_delete(ifp)) { + vty_out(vty, "Unable to delete interface information\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (interface_no_ip_pim_sm, @@ -5096,13 +5557,13 @@ DEFUN (interface_no_ip_pim_sm, PIM_STR IFACE_PIM_SM_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); - if (!pim_cmd_interface_delete(ifp)) { - vty_out (vty, "Unable to delete interface information\n"); - return CMD_WARNING_CONFIG_FAILED; - } + VTY_DECLVAR_CONTEXT(interface, ifp); + if (!pim_cmd_interface_delete(ifp)) { + vty_out(vty, "Unable to delete interface information\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (interface_ip_mroute, @@ -5113,40 +5574,39 @@ DEFUN (interface_ip_mroute, "Outgoing interface name\n" "Group address\n") { - VTY_DECLVAR_CONTEXT(interface, iif); - int idx_interface = 2; - int idx_ipv4 = 3; - struct interface *oif; - const char *oifname; - const char *grp_str; - struct in_addr grp_addr; - struct in_addr src_addr; - int result; - - oifname = argv[idx_interface]->arg; - oif = if_lookup_by_name(oifname, VRF_DEFAULT); - if (!oif) { - vty_out (vty, "No such interface name %s\n", - oifname); - return CMD_WARNING_CONFIG_FAILED; - } - - grp_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, grp_str, &grp_addr); - if (result <= 0) { - vty_out (vty, "Bad group address %s: errno=%d: %s\n", - grp_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - src_addr.s_addr = INADDR_ANY; - - if (pim_static_add(iif, oif, grp_addr, src_addr)) { - vty_out (vty, "Failed to add route\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, iif); + int idx_interface = 2; + int idx_ipv4 = 3; + struct interface *oif; + const char *oifname; + const char *grp_str; + struct in_addr grp_addr; + struct in_addr src_addr; + int result; + + oifname = argv[idx_interface]->arg; + oif = if_lookup_by_name(oifname, VRF_DEFAULT); + if (!oif) { + vty_out(vty, "No such interface name %s\n", oifname); + return CMD_WARNING_CONFIG_FAILED; + } + + grp_str = argv[idx_ipv4]->arg; + result = inet_pton(AF_INET, grp_str, &grp_addr); + if (result <= 0) { + vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + src_addr.s_addr = INADDR_ANY; + + if (pim_static_add(iif, oif, grp_addr, src_addr)) { + vty_out(vty, "Failed to add route\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } DEFUN (interface_ip_mroute_source, @@ -5158,48 +5618,47 @@ DEFUN (interface_ip_mroute_source, "Group address\n" "Source address\n") { - VTY_DECLVAR_CONTEXT(interface, iif); - int idx_interface = 2; - int idx_ipv4 = 3; - int idx_ipv4_2 = 4; - struct interface *oif; - const char *oifname; - const char *grp_str; - struct in_addr grp_addr; - const char *src_str; - struct in_addr src_addr; - int result; - - oifname = argv[idx_interface]->arg; - oif = if_lookup_by_name(oifname, VRF_DEFAULT); - if (!oif) { - vty_out (vty, "No such interface name %s\n", - oifname); - return CMD_WARNING_CONFIG_FAILED; - } - - grp_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, grp_str, &grp_addr); - if (result <= 0) { - vty_out (vty, "Bad group address %s: errno=%d: %s\n", - grp_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - src_str = argv[idx_ipv4_2]->arg; - result = inet_pton(AF_INET, src_str, &src_addr); - if (result <= 0) { - vty_out (vty, "Bad source address %s: errno=%d: %s\n", - src_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - if (pim_static_add(iif, oif, grp_addr, src_addr)) { - vty_out (vty, "Failed to add route\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, iif); + int idx_interface = 2; + int idx_ipv4 = 3; + int idx_ipv4_2 = 4; + struct interface *oif; + const char *oifname; + const char *grp_str; + struct in_addr grp_addr; + const char *src_str; + struct in_addr src_addr; + int result; + + oifname = argv[idx_interface]->arg; + oif = if_lookup_by_name(oifname, VRF_DEFAULT); + if (!oif) { + vty_out(vty, "No such interface name %s\n", oifname); + return CMD_WARNING_CONFIG_FAILED; + } + + grp_str = argv[idx_ipv4]->arg; + result = inet_pton(AF_INET, grp_str, &grp_addr); + if (result <= 0) { + vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + src_str = argv[idx_ipv4_2]->arg; + result = inet_pton(AF_INET, src_str, &src_addr); + if (result <= 0) { + vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + if (pim_static_add(iif, oif, grp_addr, src_addr)) { + vty_out(vty, "Failed to add route\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } DEFUN (interface_no_ip_mroute, @@ -5211,40 +5670,39 @@ DEFUN (interface_no_ip_mroute, "Outgoing interface name\n" "Group Address\n") { - VTY_DECLVAR_CONTEXT(interface, iif); - int idx_interface = 3; - int idx_ipv4 = 4; - struct interface *oif; - const char *oifname; - const char *grp_str; - struct in_addr grp_addr; - struct in_addr src_addr; - int result; - - oifname = argv[idx_interface]->arg; - oif = if_lookup_by_name(oifname, VRF_DEFAULT); - if (!oif) { - vty_out (vty, "No such interface name %s\n", - oifname); - return CMD_WARNING_CONFIG_FAILED; - } - - grp_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, grp_str, &grp_addr); - if (result <= 0) { - vty_out (vty, "Bad group address %s: errno=%d: %s\n", - grp_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - src_addr.s_addr = INADDR_ANY; - - if (pim_static_del(iif, oif, grp_addr, src_addr)) { - vty_out (vty, "Failed to remove route\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, iif); + int idx_interface = 3; + int idx_ipv4 = 4; + struct interface *oif; + const char *oifname; + const char *grp_str; + struct in_addr grp_addr; + struct in_addr src_addr; + int result; + + oifname = argv[idx_interface]->arg; + oif = if_lookup_by_name(oifname, VRF_DEFAULT); + if (!oif) { + vty_out(vty, "No such interface name %s\n", oifname); + return CMD_WARNING_CONFIG_FAILED; + } + + grp_str = argv[idx_ipv4]->arg; + result = inet_pton(AF_INET, grp_str, &grp_addr); + if (result <= 0) { + vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + src_addr.s_addr = INADDR_ANY; + + if (pim_static_del(iif, oif, grp_addr, src_addr)) { + vty_out(vty, "Failed to remove route\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } DEFUN (interface_no_ip_mroute_source, @@ -5257,48 +5715,47 @@ DEFUN (interface_no_ip_mroute_source, "Group Address\n" "Source Address\n") { - VTY_DECLVAR_CONTEXT(interface, iif); - int idx_interface = 3; - int idx_ipv4 = 4; - int idx_ipv4_2 = 5; - struct interface *oif; - const char *oifname; - const char *grp_str; - struct in_addr grp_addr; - const char *src_str; - struct in_addr src_addr; - int result; - - oifname = argv[idx_interface]->arg; - oif = if_lookup_by_name(oifname, VRF_DEFAULT); - if (!oif) { - vty_out (vty, "No such interface name %s\n", - oifname); - return CMD_WARNING_CONFIG_FAILED; - } - - grp_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, grp_str, &grp_addr); - if (result <= 0) { - vty_out (vty, "Bad group address %s: errno=%d: %s\n", - grp_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - src_str = argv[idx_ipv4_2]->arg; - result = inet_pton(AF_INET, src_str, &src_addr); - if (result <= 0) { - vty_out (vty, "Bad source address %s: errno=%d: %s\n", - src_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - if (pim_static_del(iif, oif, grp_addr, src_addr)) { - vty_out (vty, "Failed to remove route\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, iif); + int idx_interface = 3; + int idx_ipv4 = 4; + int idx_ipv4_2 = 5; + struct interface *oif; + const char *oifname; + const char *grp_str; + struct in_addr grp_addr; + const char *src_str; + struct in_addr src_addr; + int result; + + oifname = argv[idx_interface]->arg; + oif = if_lookup_by_name(oifname, VRF_DEFAULT); + if (!oif) { + vty_out(vty, "No such interface name %s\n", oifname); + return CMD_WARNING_CONFIG_FAILED; + } + + grp_str = argv[idx_ipv4]->arg; + result = inet_pton(AF_INET, grp_str, &grp_addr); + if (result <= 0) { + vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + src_str = argv[idx_ipv4_2]->arg; + result = inet_pton(AF_INET, src_str, &src_addr); + if (result <= 0) { + vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + if (pim_static_del(iif, oif, grp_addr, src_addr)) { + vty_out(vty, "Failed to remove route\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } DEFUN (interface_ip_pim_hello, @@ -5310,31 +5767,29 @@ DEFUN (interface_ip_pim_hello, IFACE_PIM_HELLO_TIME_STR IFACE_PIM_HELLO_HOLD_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_time = 3; - int idx_hold = 4; - struct pim_interface *pim_ifp = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_time = 3; + int idx_hold = 4; + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) - { - if (!pim_cmd_interface_add(ifp)) - { - vty_out (vty, "Could not enable PIM SM on interface\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } + if (!pim_ifp) { + if (!pim_cmd_interface_add(ifp)) { + vty_out(vty, "Could not enable PIM SM on interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } - pim_ifp = ifp->info; - pim_ifp->pim_hello_period = strtol(argv[idx_time]->arg, NULL, 10); + pim_ifp = ifp->info; + pim_ifp->pim_hello_period = strtol(argv[idx_time]->arg, NULL, 10); - if (argc == idx_hold + 1) - pim_ifp->pim_default_holdtime = strtol(argv[idx_hold]->arg, NULL, 10); + if (argc == idx_hold + 1) + pim_ifp->pim_default_holdtime = + strtol(argv[idx_hold]->arg, NULL, 10); - return CMD_SUCCESS; + return CMD_SUCCESS; } - DEFUN (interface_no_ip_pim_hello, interface_no_ip_pim_hello_cmd, "no ip pim hello [(1-180) (1-180)]", @@ -5345,18 +5800,18 @@ DEFUN (interface_no_ip_pim_hello, IFACE_PIM_HELLO_TIME_STR IFACE_PIM_HELLO_HOLD_STR) { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) { - vty_out (vty, "Pim not enabled on this interface\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!pim_ifp) { + vty_out(vty, "Pim not enabled on this interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } - pim_ifp->pim_hello_period = PIM_DEFAULT_HELLO_PERIOD; - pim_ifp->pim_default_holdtime = -1; + pim_ifp->pim_hello_period = PIM_DEFAULT_HELLO_PERIOD; + pim_ifp->pim_default_holdtime = -1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_igmp, @@ -5365,10 +5820,10 @@ DEFUN (debug_igmp, DEBUG_STR DEBUG_IGMP_STR) { - PIM_DO_DEBUG_IGMP_EVENTS; - PIM_DO_DEBUG_IGMP_PACKETS; - PIM_DO_DEBUG_IGMP_TRACE; - return CMD_SUCCESS; + PIM_DO_DEBUG_IGMP_EVENTS; + PIM_DO_DEBUG_IGMP_PACKETS; + PIM_DO_DEBUG_IGMP_TRACE; + return CMD_SUCCESS; } DEFUN (no_debug_igmp, @@ -5378,10 +5833,10 @@ DEFUN (no_debug_igmp, DEBUG_STR DEBUG_IGMP_STR) { - PIM_DONT_DEBUG_IGMP_EVENTS; - PIM_DONT_DEBUG_IGMP_PACKETS; - PIM_DONT_DEBUG_IGMP_TRACE; - return CMD_SUCCESS; + PIM_DONT_DEBUG_IGMP_EVENTS; + PIM_DONT_DEBUG_IGMP_PACKETS; + PIM_DONT_DEBUG_IGMP_TRACE; + return CMD_SUCCESS; } @@ -5392,8 +5847,8 @@ DEFUN (debug_igmp_events, DEBUG_IGMP_STR DEBUG_IGMP_EVENTS_STR) { - PIM_DO_DEBUG_IGMP_EVENTS; - return CMD_SUCCESS; + PIM_DO_DEBUG_IGMP_EVENTS; + return CMD_SUCCESS; } DEFUN (no_debug_igmp_events, @@ -5404,8 +5859,8 @@ DEFUN (no_debug_igmp_events, DEBUG_IGMP_STR DEBUG_IGMP_EVENTS_STR) { - PIM_DONT_DEBUG_IGMP_EVENTS; - return CMD_SUCCESS; + PIM_DONT_DEBUG_IGMP_EVENTS; + return CMD_SUCCESS; } @@ -5416,8 +5871,8 @@ DEFUN (debug_igmp_packets, DEBUG_IGMP_STR DEBUG_IGMP_PACKETS_STR) { - PIM_DO_DEBUG_IGMP_PACKETS; - return CMD_SUCCESS; + PIM_DO_DEBUG_IGMP_PACKETS; + return CMD_SUCCESS; } DEFUN (no_debug_igmp_packets, @@ -5428,8 +5883,8 @@ DEFUN (no_debug_igmp_packets, DEBUG_IGMP_STR DEBUG_IGMP_PACKETS_STR) { - PIM_DONT_DEBUG_IGMP_PACKETS; - return CMD_SUCCESS; + PIM_DONT_DEBUG_IGMP_PACKETS; + return CMD_SUCCESS; } @@ -5440,8 +5895,8 @@ DEFUN (debug_igmp_trace, DEBUG_IGMP_STR DEBUG_IGMP_TRACE_STR) { - PIM_DO_DEBUG_IGMP_TRACE; - return CMD_SUCCESS; + PIM_DO_DEBUG_IGMP_TRACE; + return CMD_SUCCESS; } DEFUN (no_debug_igmp_trace, @@ -5452,8 +5907,8 @@ DEFUN (no_debug_igmp_trace, DEBUG_IGMP_STR DEBUG_IGMP_TRACE_STR) { - PIM_DONT_DEBUG_IGMP_TRACE; - return CMD_SUCCESS; + PIM_DONT_DEBUG_IGMP_TRACE; + return CMD_SUCCESS; } @@ -5463,8 +5918,8 @@ DEFUN (debug_mroute, DEBUG_STR DEBUG_MROUTE_STR) { - PIM_DO_DEBUG_MROUTE; - return CMD_SUCCESS; + PIM_DO_DEBUG_MROUTE; + return CMD_SUCCESS; } DEFUN (debug_mroute_detail, @@ -5474,8 +5929,8 @@ DEFUN (debug_mroute_detail, DEBUG_MROUTE_STR "detailed\n") { - PIM_DO_DEBUG_MROUTE_DETAIL; - return CMD_SUCCESS; + PIM_DO_DEBUG_MROUTE_DETAIL; + return CMD_SUCCESS; } DEFUN (no_debug_mroute, @@ -5485,8 +5940,8 @@ DEFUN (no_debug_mroute, DEBUG_STR DEBUG_MROUTE_STR) { - PIM_DONT_DEBUG_MROUTE; - return CMD_SUCCESS; + PIM_DONT_DEBUG_MROUTE; + return CMD_SUCCESS; } DEFUN (no_debug_mroute_detail, @@ -5497,8 +5952,8 @@ DEFUN (no_debug_mroute_detail, DEBUG_MROUTE_STR "detailed\n") { - PIM_DONT_DEBUG_MROUTE_DETAIL; - return CMD_SUCCESS; + PIM_DONT_DEBUG_MROUTE_DETAIL; + return CMD_SUCCESS; } DEFUN (debug_static, @@ -5507,8 +5962,8 @@ DEFUN (debug_static, DEBUG_STR DEBUG_STATIC_STR) { - PIM_DO_DEBUG_STATIC; - return CMD_SUCCESS; + PIM_DO_DEBUG_STATIC; + return CMD_SUCCESS; } DEFUN (no_debug_static, @@ -5518,8 +5973,8 @@ DEFUN (no_debug_static, DEBUG_STR DEBUG_STATIC_STR) { - PIM_DONT_DEBUG_STATIC; - return CMD_SUCCESS; + PIM_DONT_DEBUG_STATIC; + return CMD_SUCCESS; } @@ -5529,12 +5984,12 @@ DEFUN (debug_pim, DEBUG_STR DEBUG_PIM_STR) { - PIM_DO_DEBUG_PIM_EVENTS; - PIM_DO_DEBUG_PIM_PACKETS; - PIM_DO_DEBUG_PIM_TRACE; - PIM_DO_DEBUG_MSDP_EVENTS; - PIM_DO_DEBUG_MSDP_PACKETS; - return CMD_SUCCESS; + PIM_DO_DEBUG_PIM_EVENTS; + PIM_DO_DEBUG_PIM_PACKETS; + PIM_DO_DEBUG_PIM_TRACE; + PIM_DO_DEBUG_MSDP_EVENTS; + PIM_DO_DEBUG_MSDP_PACKETS; + return CMD_SUCCESS; } DEFUN (no_debug_pim, @@ -5544,16 +5999,16 @@ DEFUN (no_debug_pim, DEBUG_STR DEBUG_PIM_STR) { - PIM_DONT_DEBUG_PIM_EVENTS; - PIM_DONT_DEBUG_PIM_PACKETS; - PIM_DONT_DEBUG_PIM_TRACE; - PIM_DONT_DEBUG_MSDP_EVENTS; - PIM_DONT_DEBUG_MSDP_PACKETS; + PIM_DONT_DEBUG_PIM_EVENTS; + PIM_DONT_DEBUG_PIM_PACKETS; + PIM_DONT_DEBUG_PIM_TRACE; + PIM_DONT_DEBUG_MSDP_EVENTS; + PIM_DONT_DEBUG_MSDP_PACKETS; - PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND; - PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV; + PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND; + PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -5564,8 +6019,8 @@ DEFUN (debug_pim_events, DEBUG_PIM_STR DEBUG_PIM_EVENTS_STR) { - PIM_DO_DEBUG_PIM_EVENTS; - return CMD_SUCCESS; + PIM_DO_DEBUG_PIM_EVENTS; + return CMD_SUCCESS; } DEFUN (no_debug_pim_events, @@ -5576,8 +6031,8 @@ DEFUN (no_debug_pim_events, DEBUG_PIM_STR DEBUG_PIM_EVENTS_STR) { - PIM_DONT_DEBUG_PIM_EVENTS; - return CMD_SUCCESS; + PIM_DONT_DEBUG_PIM_EVENTS; + return CMD_SUCCESS; } DEFUN (debug_pim_packets, @@ -5590,28 +6045,21 @@ DEFUN (debug_pim_packets, DEBUG_PIM_J_P_PACKETS_STR DEBUG_PIM_PIM_REG_PACKETS_STR) { - int idx = 0; - if (argv_find (argv, argc, "hello", &idx)) - { - PIM_DO_DEBUG_PIM_HELLO; - vty_out (vty, "PIM Hello debugging is on\n"); - } - else if (argv_find (argv, argc ,"joins", &idx)) - { - PIM_DO_DEBUG_PIM_J_P; - vty_out (vty, "PIM Join/Prune debugging is on\n"); - } - else if (argv_find (argv, argc, "register", &idx)) - { - PIM_DO_DEBUG_PIM_REG; - vty_out (vty, "PIM Register debugging is on\n"); - } - else - { - PIM_DO_DEBUG_PIM_PACKETS; - vty_out (vty, "PIM Packet debugging is on \n"); - } - return CMD_SUCCESS; + int idx = 0; + if (argv_find(argv, argc, "hello", &idx)) { + PIM_DO_DEBUG_PIM_HELLO; + vty_out(vty, "PIM Hello debugging is on\n"); + } else if (argv_find(argv, argc, "joins", &idx)) { + PIM_DO_DEBUG_PIM_J_P; + vty_out(vty, "PIM Join/Prune debugging is on\n"); + } else if (argv_find(argv, argc, "register", &idx)) { + PIM_DO_DEBUG_PIM_REG; + vty_out(vty, "PIM Register debugging is on\n"); + } else { + PIM_DO_DEBUG_PIM_PACKETS; + vty_out(vty, "PIM Packet debugging is on \n"); + } + return CMD_SUCCESS; } DEFUN (no_debug_pim_packets, @@ -5625,26 +6073,20 @@ DEFUN (no_debug_pim_packets, DEBUG_PIM_J_P_PACKETS_STR DEBUG_PIM_PIM_REG_PACKETS_STR) { - int idx = 0; - if (argv_find (argv, argc,"hello",&idx)) - { - PIM_DONT_DEBUG_PIM_HELLO; - vty_out (vty, "PIM Hello debugging is off \n"); - } - else if (argv_find (argv, argc, "joins", &idx)) - { - PIM_DONT_DEBUG_PIM_J_P; - vty_out (vty, "PIM Join/Prune debugging is off \n"); - } - else if (argv_find (argv, argc, "register", &idx)) - { - PIM_DONT_DEBUG_PIM_REG; - vty_out (vty, "PIM Register debugging is off\n"); - } - else - PIM_DONT_DEBUG_PIM_PACKETS; - - return CMD_SUCCESS; + int idx = 0; + if (argv_find(argv, argc, "hello", &idx)) { + PIM_DONT_DEBUG_PIM_HELLO; + vty_out(vty, "PIM Hello debugging is off \n"); + } else if (argv_find(argv, argc, "joins", &idx)) { + PIM_DONT_DEBUG_PIM_J_P; + vty_out(vty, "PIM Join/Prune debugging is off \n"); + } else if (argv_find(argv, argc, "register", &idx)) { + PIM_DONT_DEBUG_PIM_REG; + vty_out(vty, "PIM Register debugging is off\n"); + } else + PIM_DONT_DEBUG_PIM_PACKETS; + + return CMD_SUCCESS; } @@ -5656,8 +6098,8 @@ DEFUN (debug_pim_packetdump_send, DEBUG_PIM_PACKETDUMP_STR DEBUG_PIM_PACKETDUMP_SEND_STR) { - PIM_DO_DEBUG_PIM_PACKETDUMP_SEND; - return CMD_SUCCESS; + PIM_DO_DEBUG_PIM_PACKETDUMP_SEND; + return CMD_SUCCESS; } DEFUN (no_debug_pim_packetdump_send, @@ -5669,8 +6111,8 @@ DEFUN (no_debug_pim_packetdump_send, DEBUG_PIM_PACKETDUMP_STR DEBUG_PIM_PACKETDUMP_SEND_STR) { - PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND; - return CMD_SUCCESS; + PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND; + return CMD_SUCCESS; } @@ -5682,8 +6124,8 @@ DEFUN (debug_pim_packetdump_recv, DEBUG_PIM_PACKETDUMP_STR DEBUG_PIM_PACKETDUMP_RECV_STR) { - PIM_DO_DEBUG_PIM_PACKETDUMP_RECV; - return CMD_SUCCESS; + PIM_DO_DEBUG_PIM_PACKETDUMP_RECV; + return CMD_SUCCESS; } DEFUN (no_debug_pim_packetdump_recv, @@ -5695,8 +6137,8 @@ DEFUN (no_debug_pim_packetdump_recv, DEBUG_PIM_PACKETDUMP_STR DEBUG_PIM_PACKETDUMP_RECV_STR) { - PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV; - return CMD_SUCCESS; + PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV; + return CMD_SUCCESS; } @@ -5707,8 +6149,8 @@ DEFUN (debug_pim_trace, DEBUG_PIM_STR DEBUG_PIM_TRACE_STR) { - PIM_DO_DEBUG_PIM_TRACE; - return CMD_SUCCESS; + PIM_DO_DEBUG_PIM_TRACE; + return CMD_SUCCESS; } DEFUN (no_debug_pim_trace, @@ -5719,8 +6161,8 @@ DEFUN (no_debug_pim_trace, DEBUG_PIM_STR DEBUG_PIM_TRACE_STR) { - PIM_DONT_DEBUG_PIM_TRACE; - return CMD_SUCCESS; + PIM_DONT_DEBUG_PIM_TRACE; + return CMD_SUCCESS; } @@ -5730,8 +6172,8 @@ DEFUN (debug_ssmpingd, DEBUG_STR DEBUG_SSMPINGD_STR) { - PIM_DO_DEBUG_SSMPINGD; - return CMD_SUCCESS; + PIM_DO_DEBUG_SSMPINGD; + return CMD_SUCCESS; } DEFUN (no_debug_ssmpingd, @@ -5741,8 +6183,8 @@ DEFUN (no_debug_ssmpingd, DEBUG_STR DEBUG_SSMPINGD_STR) { - PIM_DONT_DEBUG_SSMPINGD; - return CMD_SUCCESS; + PIM_DONT_DEBUG_SSMPINGD; + return CMD_SUCCESS; } @@ -5753,8 +6195,8 @@ DEFUN (debug_pim_zebra, DEBUG_PIM_STR DEBUG_PIM_ZEBRA_STR) { - PIM_DO_DEBUG_ZEBRA; - return CMD_SUCCESS; + PIM_DO_DEBUG_ZEBRA; + return CMD_SUCCESS; } DEFUN (no_debug_pim_zebra, @@ -5765,8 +6207,8 @@ DEFUN (no_debug_pim_zebra, DEBUG_PIM_STR DEBUG_PIM_ZEBRA_STR) { - PIM_DONT_DEBUG_ZEBRA; - return CMD_SUCCESS; + PIM_DONT_DEBUG_ZEBRA; + return CMD_SUCCESS; } @@ -5776,9 +6218,9 @@ DEFUN (debug_msdp, DEBUG_STR DEBUG_MSDP_STR) { - PIM_DO_DEBUG_MSDP_EVENTS; - PIM_DO_DEBUG_MSDP_PACKETS; - return CMD_SUCCESS; + PIM_DO_DEBUG_MSDP_EVENTS; + PIM_DO_DEBUG_MSDP_PACKETS; + return CMD_SUCCESS; } DEFUN (no_debug_msdp, @@ -5788,16 +6230,13 @@ DEFUN (no_debug_msdp, DEBUG_STR DEBUG_MSDP_STR) { - PIM_DONT_DEBUG_MSDP_EVENTS; - PIM_DONT_DEBUG_MSDP_PACKETS; - return CMD_SUCCESS; + PIM_DONT_DEBUG_MSDP_EVENTS; + PIM_DONT_DEBUG_MSDP_PACKETS; + return CMD_SUCCESS; } -ALIAS (no_debug_msdp, - undebug_msdp_cmd, - "undebug msdp", - UNDEBUG_STR - DEBUG_MSDP_STR) +ALIAS(no_debug_msdp, undebug_msdp_cmd, "undebug msdp", + UNDEBUG_STR DEBUG_MSDP_STR) DEFUN (debug_msdp_events, debug_msdp_events_cmd, @@ -5806,8 +6245,8 @@ DEFUN (debug_msdp_events, DEBUG_MSDP_STR DEBUG_MSDP_EVENTS_STR) { - PIM_DO_DEBUG_MSDP_EVENTS; - return CMD_SUCCESS; + PIM_DO_DEBUG_MSDP_EVENTS; + return CMD_SUCCESS; } DEFUN (no_debug_msdp_events, @@ -5818,16 +6257,12 @@ DEFUN (no_debug_msdp_events, DEBUG_MSDP_STR DEBUG_MSDP_EVENTS_STR) { - PIM_DONT_DEBUG_MSDP_EVENTS; - return CMD_SUCCESS; + PIM_DONT_DEBUG_MSDP_EVENTS; + return CMD_SUCCESS; } -ALIAS (no_debug_msdp_events, - undebug_msdp_events_cmd, - "undebug msdp events", - UNDEBUG_STR - DEBUG_MSDP_STR - DEBUG_MSDP_EVENTS_STR) +ALIAS(no_debug_msdp_events, undebug_msdp_events_cmd, "undebug msdp events", + UNDEBUG_STR DEBUG_MSDP_STR DEBUG_MSDP_EVENTS_STR) DEFUN (debug_msdp_packets, debug_msdp_packets_cmd, @@ -5836,8 +6271,8 @@ DEFUN (debug_msdp_packets, DEBUG_MSDP_STR DEBUG_MSDP_PACKETS_STR) { - PIM_DO_DEBUG_MSDP_PACKETS; - return CMD_SUCCESS; + PIM_DO_DEBUG_MSDP_PACKETS; + return CMD_SUCCESS; } DEFUN (no_debug_msdp_packets, @@ -5848,16 +6283,12 @@ DEFUN (no_debug_msdp_packets, DEBUG_MSDP_STR DEBUG_MSDP_PACKETS_STR) { - PIM_DONT_DEBUG_MSDP_PACKETS; - return CMD_SUCCESS; + PIM_DONT_DEBUG_MSDP_PACKETS; + return CMD_SUCCESS; } -ALIAS (no_debug_msdp_packets, - undebug_msdp_packets_cmd, - "undebug msdp packets", - UNDEBUG_STR - DEBUG_MSDP_STR - DEBUG_MSDP_PACKETS_STR) +ALIAS(no_debug_msdp_packets, undebug_msdp_packets_cmd, "undebug msdp packets", + UNDEBUG_STR DEBUG_MSDP_STR DEBUG_MSDP_PACKETS_STR) DEFUN (show_debugging_pim, show_debugging_pim_cmd, @@ -5866,39 +6297,38 @@ DEFUN (show_debugging_pim, DEBUG_STR PIM_STR) { - pim_debug_config_write(vty); - return CMD_SUCCESS; + pim_debug_config_write(vty); + return CMD_SUCCESS; } -static int -interface_pim_use_src_cmd_worker(struct vty *vty, const char *source) +static int interface_pim_use_src_cmd_worker(struct vty *vty, const char *source) { - int result; - struct in_addr source_addr; - VTY_DECLVAR_CONTEXT(interface, ifp); + int result; + struct in_addr source_addr; + VTY_DECLVAR_CONTEXT(interface, ifp); - result = inet_pton(AF_INET, source, &source_addr); - if (result <= 0) { - vty_out (vty, "%% Bad source address %s: errno=%d: %s\n", - source, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + result = inet_pton(AF_INET, source, &source_addr); + if (result <= 0) { + vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", source, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - result = pim_update_source_set(ifp, source_addr); - switch (result) { - case PIM_SUCCESS: - break; - case PIM_IFACE_NOT_FOUND: - vty_out (vty, "Pim not enabled on this interface\n"); - break; - case PIM_UPDATE_SOURCE_DUP: - vty_out (vty, "%% Source already set to %s\n", source); - break; - default: - vty_out (vty, "%% Source set failed\n"); - } + result = pim_update_source_set(ifp, source_addr); + switch (result) { + case PIM_SUCCESS: + break; + case PIM_IFACE_NOT_FOUND: + vty_out(vty, "Pim not enabled on this interface\n"); + break; + case PIM_UPDATE_SOURCE_DUP: + vty_out(vty, "%% Source already set to %s\n", source); + break; + default: + vty_out(vty, "%% Source set failed\n"); + } - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; } DEFUN (interface_pim_use_source, @@ -5909,7 +6339,7 @@ DEFUN (interface_pim_use_source, "Configure primary IP address\n" "source ip address\n") { - return interface_pim_use_src_cmd_worker (vty, argv[3]->arg); + return interface_pim_use_src_cmd_worker(vty, argv[3]->arg); } DEFUN (interface_no_pim_use_source, @@ -5920,7 +6350,7 @@ DEFUN (interface_no_pim_use_source, "pim multicast routing\n" "Delete source IP address\n") { - return interface_pim_use_src_cmd_worker (vty, "0.0.0.0"); + return interface_pim_use_src_cmd_worker(vty, "0.0.0.0"); } DEFUN (ip_pim_bfd, @@ -5930,19 +6360,19 @@ DEFUN (ip_pim_bfd, PIM_STR "Enables BFD support\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; - struct bfd_info *bfd_info = NULL; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; + struct bfd_info *bfd_info = NULL; - if (!pim_ifp) - return CMD_SUCCESS; - bfd_info = pim_ifp->bfd_info; + if (!pim_ifp) + return CMD_SUCCESS; + bfd_info = pim_ifp->bfd_info; - if (!bfd_info || !CHECK_FLAG (bfd_info->flags, BFD_FLAG_PARAM_CFG)) - pim_bfd_if_param_set (ifp, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, - BFD_DEF_DETECT_MULT, 1); + if (!bfd_info || !CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) + pim_bfd_if_param_set(ifp, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, + BFD_DEF_DETECT_MULT, 1); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_pim_bfd, @@ -5953,19 +6383,18 @@ DEFUN (no_ip_pim_bfd, PIM_STR "Disables BFD support\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct pim_interface *pim_ifp = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) - return CMD_SUCCESS; + if (!pim_ifp) + return CMD_SUCCESS; - if (pim_ifp->bfd_info) - { - pim_bfd_reg_dereg_all_nbr (ifp, ZEBRA_BFD_DEST_DEREGISTER); - bfd_info_free (&(pim_ifp->bfd_info)); - } + if (pim_ifp->bfd_info) { + pim_bfd_reg_dereg_all_nbr(ifp, ZEBRA_BFD_DEST_DEREGISTER); + bfd_info_free(&(pim_ifp->bfd_info)); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_pim_bfd_param, @@ -5978,77 +6407,74 @@ DEFUN (ip_pim_bfd_param, "Required min receive interval\n" "Desired min transmit interval\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_number = 3; - int idx_number_2 = 4; - int idx_number_3 = 5; - u_int32_t rx_val; - u_int32_t tx_val; - u_int8_t dm_val; - int ret; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_number = 3; + int idx_number_2 = 4; + int idx_number_3 = 5; + u_int32_t rx_val; + u_int32_t tx_val; + u_int8_t dm_val; + int ret; - if ((ret = bfd_validate_param (vty, argv[idx_number]->arg, - argv[idx_number_2]->arg, - argv[idx_number_3]->arg, - &dm_val, &rx_val, &tx_val)) != CMD_SUCCESS) - return ret; + if ((ret = bfd_validate_param( + vty, argv[idx_number]->arg, argv[idx_number_2]->arg, + argv[idx_number_3]->arg, &dm_val, &rx_val, &tx_val)) + != CMD_SUCCESS) + return ret; - pim_bfd_if_param_set (ifp, rx_val, tx_val, dm_val, 0); + pim_bfd_if_param_set(ifp, rx_val, tx_val, dm_val, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } -ALIAS (no_ip_pim_bfd, - no_ip_pim_bfd_param_cmd, - "no ip pim bfd (2-255) (50-60000) (50-60000)", - NO_STR - IP_STR - PIM_STR - "Enables BFD support\n" - "Detect Multiplier\n" - "Required min receive interval\n" - "Desired min transmit interval\n") +ALIAS(no_ip_pim_bfd, no_ip_pim_bfd_param_cmd, + "no ip pim bfd (2-255) (50-60000) (50-60000)", NO_STR IP_STR PIM_STR + "Enables BFD support\n" + "Detect Multiplier\n" + "Required min receive interval\n" + "Desired min transmit interval\n") + +static int ip_msdp_peer_cmd_worker(struct vty *vty, const char *peer, + const char *local) +{ + enum pim_msdp_err result; + struct in_addr peer_addr; + struct in_addr local_addr; + + result = inet_pton(AF_INET, peer, &peer_addr); + if (result <= 0) { + vty_out(vty, "%% Bad peer address %s: errno=%d: %s\n", peer, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + result = inet_pton(AF_INET, local, &local_addr); + if (result <= 0) { + vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", local, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } -static int -ip_msdp_peer_cmd_worker (struct vty *vty, const char *peer, const char *local) -{ - enum pim_msdp_err result; - struct in_addr peer_addr; - struct in_addr local_addr; - - result = inet_pton(AF_INET, peer, &peer_addr); - if (result <= 0) { - vty_out (vty, "%% Bad peer address %s: errno=%d: %s\n", - peer, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - result = inet_pton(AF_INET, local, &local_addr); - if (result <= 0) { - vty_out (vty, "%% Bad source address %s: errno=%d: %s\n", - local, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - result = pim_msdp_peer_add(peer_addr, local_addr, "default", NULL/* mp_p */); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_OOM: - vty_out (vty, "%% Out of memory\n"); - break; - case PIM_MSDP_ERR_PEER_EXISTS: - vty_out (vty, "%% Peer exists\n"); - break; - case PIM_MSDP_ERR_MAX_MESH_GROUPS: - vty_out (vty, "%% Only one mesh-group allowed currently\n"); - break; - default: - vty_out (vty, "%% peer add failed\n"); - } - - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + result = pim_msdp_peer_add(peer_addr, local_addr, "default", + NULL /* mp_p */); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_OOM: + vty_out(vty, "%% Out of memory\n"); + break; + case PIM_MSDP_ERR_PEER_EXISTS: + vty_out(vty, "%% Peer exists\n"); + break; + case PIM_MSDP_ERR_MAX_MESH_GROUPS: + vty_out(vty, "%% Only one mesh-group allowed currently\n"); + break; + default: + vty_out(vty, "%% peer add failed\n"); + } + + return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; } DEFUN_HIDDEN (ip_msdp_peer, @@ -6061,34 +6487,33 @@ DEFUN_HIDDEN (ip_msdp_peer, "Source address for TCP connection\n" "local ip address\n") { - return ip_msdp_peer_cmd_worker (vty, argv[3]->arg, argv[5]->arg); + return ip_msdp_peer_cmd_worker(vty, argv[3]->arg, argv[5]->arg); } -static int -ip_no_msdp_peer_cmd_worker (struct vty *vty, const char *peer) +static int ip_no_msdp_peer_cmd_worker(struct vty *vty, const char *peer) { - enum pim_msdp_err result; - struct in_addr peer_addr; + enum pim_msdp_err result; + struct in_addr peer_addr; - result = inet_pton(AF_INET, peer, &peer_addr); - if (result <= 0) { - vty_out (vty, "%% Bad peer address %s: errno=%d: %s\n", - peer, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + result = inet_pton(AF_INET, peer, &peer_addr); + if (result <= 0) { + vty_out(vty, "%% Bad peer address %s: errno=%d: %s\n", peer, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - result = pim_msdp_peer_del(peer_addr); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_NO_PEER: - vty_out (vty, "%% Peer does not exist\n"); - break; - default: - vty_out (vty, "%% peer del failed\n"); - } + result = pim_msdp_peer_del(peer_addr); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_NO_PEER: + vty_out(vty, "%% Peer does not exist\n"); + break; + default: + vty_out(vty, "%% peer del failed\n"); + } - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; } DEFUN_HIDDEN (no_ip_msdp_peer, @@ -6100,40 +6525,40 @@ DEFUN_HIDDEN (no_ip_msdp_peer, "Delete MSDP peer\n" "peer ip address\n") { - return ip_no_msdp_peer_cmd_worker (vty, argv[4]->arg); + return ip_no_msdp_peer_cmd_worker(vty, argv[4]->arg); } -static int -ip_msdp_mesh_group_member_cmd_worker(struct vty *vty, const char *mg, const char *mbr) +static int ip_msdp_mesh_group_member_cmd_worker(struct vty *vty, const char *mg, + const char *mbr) { - enum pim_msdp_err result; - struct in_addr mbr_ip; + enum pim_msdp_err result; + struct in_addr mbr_ip; - result = inet_pton(AF_INET, mbr, &mbr_ip); - if (result <= 0) { - vty_out (vty, "%% Bad member address %s: errno=%d: %s\n", - mbr, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + result = inet_pton(AF_INET, mbr, &mbr_ip); + if (result <= 0) { + vty_out(vty, "%% Bad member address %s: errno=%d: %s\n", mbr, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - result = pim_msdp_mg_mbr_add(mg, mbr_ip); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_OOM: - vty_out (vty, "%% Out of memory\n"); - break; - case PIM_MSDP_ERR_MG_MBR_EXISTS: - vty_out (vty, "%% mesh-group member exists\n"); - break; - case PIM_MSDP_ERR_MAX_MESH_GROUPS: - vty_out (vty, "%% Only one mesh-group allowed currently\n"); - break; - default: - vty_out (vty, "%% member add failed\n"); - } + result = pim_msdp_mg_mbr_add(mg, mbr_ip); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_OOM: + vty_out(vty, "%% Out of memory\n"); + break; + case PIM_MSDP_ERR_MG_MBR_EXISTS: + vty_out(vty, "%% mesh-group member exists\n"); + break; + case PIM_MSDP_ERR_MAX_MESH_GROUPS: + vty_out(vty, "%% Only one mesh-group allowed currently\n"); + break; + default: + vty_out(vty, "%% member add failed\n"); + } - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; } DEFUN (ip_msdp_mesh_group_member, @@ -6146,37 +6571,39 @@ DEFUN (ip_msdp_mesh_group_member, "mesh group member\n" "peer ip address\n") { - return ip_msdp_mesh_group_member_cmd_worker(vty, argv[3]->arg, argv[5]->arg); + return ip_msdp_mesh_group_member_cmd_worker(vty, argv[3]->arg, + argv[5]->arg); } -static int -ip_no_msdp_mesh_group_member_cmd_worker(struct vty *vty, const char *mg, const char *mbr) +static int ip_no_msdp_mesh_group_member_cmd_worker(struct vty *vty, + const char *mg, + const char *mbr) { - enum pim_msdp_err result; - struct in_addr mbr_ip; + enum pim_msdp_err result; + struct in_addr mbr_ip; - result = inet_pton(AF_INET, mbr, &mbr_ip); - if (result <= 0) { - vty_out (vty, "%% Bad member address %s: errno=%d: %s\n", - mbr, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + result = inet_pton(AF_INET, mbr, &mbr_ip); + if (result <= 0) { + vty_out(vty, "%% Bad member address %s: errno=%d: %s\n", mbr, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - result = pim_msdp_mg_mbr_del(mg, mbr_ip); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_NO_MG: - vty_out (vty, "%% mesh-group does not exist\n"); - break; - case PIM_MSDP_ERR_NO_MG_MBR: - vty_out (vty, "%% mesh-group member does not exist\n"); - break; - default: - vty_out (vty, "%% mesh-group member del failed\n"); - } + result = pim_msdp_mg_mbr_del(mg, mbr_ip); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_NO_MG: + vty_out(vty, "%% mesh-group does not exist\n"); + break; + case PIM_MSDP_ERR_NO_MG_MBR: + vty_out(vty, "%% mesh-group member does not exist\n"); + break; + default: + vty_out(vty, "%% mesh-group member del failed\n"); + } - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; } DEFUN (no_ip_msdp_mesh_group_member, no_ip_msdp_mesh_group_member_cmd, @@ -6189,37 +6616,38 @@ DEFUN (no_ip_msdp_mesh_group_member, "mesh group member\n" "peer ip address\n") { - return ip_no_msdp_mesh_group_member_cmd_worker(vty, argv[4]->arg, argv[6]->arg); + return ip_no_msdp_mesh_group_member_cmd_worker(vty, argv[4]->arg, + argv[6]->arg); } -static int -ip_msdp_mesh_group_source_cmd_worker(struct vty *vty, const char *mg, const char *src) +static int ip_msdp_mesh_group_source_cmd_worker(struct vty *vty, const char *mg, + const char *src) { - enum pim_msdp_err result; - struct in_addr src_ip; + enum pim_msdp_err result; + struct in_addr src_ip; - result = inet_pton(AF_INET, src, &src_ip); - if (result <= 0) { - vty_out (vty, "%% Bad source address %s: errno=%d: %s\n", - src, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + result = inet_pton(AF_INET, src, &src_ip); + if (result <= 0) { + vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", src, + errno, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - result = pim_msdp_mg_src_add(mg, src_ip); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_OOM: - vty_out (vty, "%% Out of memory\n"); - break; - case PIM_MSDP_ERR_MAX_MESH_GROUPS: - vty_out (vty, "%% Only one mesh-group allowed currently\n"); - break; - default: - vty_out (vty, "%% source add failed\n"); - } + result = pim_msdp_mg_src_add(mg, src_ip); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_OOM: + vty_out(vty, "%% Out of memory\n"); + break; + case PIM_MSDP_ERR_MAX_MESH_GROUPS: + vty_out(vty, "%% Only one mesh-group allowed currently\n"); + break; + default: + vty_out(vty, "%% source add failed\n"); + } - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; } @@ -6233,45 +6661,45 @@ DEFUN (ip_msdp_mesh_group_source, "mesh group local address\n" "source ip address for the TCP connection\n") { - return ip_msdp_mesh_group_source_cmd_worker(vty, argv[3]->arg, argv[5]->arg); + return ip_msdp_mesh_group_source_cmd_worker(vty, argv[3]->arg, + argv[5]->arg); } -static int -ip_no_msdp_mesh_group_source_cmd_worker(struct vty *vty, const char *mg) +static int ip_no_msdp_mesh_group_source_cmd_worker(struct vty *vty, + const char *mg) { - enum pim_msdp_err result; + enum pim_msdp_err result; - result = pim_msdp_mg_src_del(mg); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_NO_MG: - vty_out (vty, "%% mesh-group does not exist\n"); - break; - default: - vty_out (vty, "%% mesh-group source del failed\n"); - } + result = pim_msdp_mg_src_del(mg); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_NO_MG: + vty_out(vty, "%% mesh-group does not exist\n"); + break; + default: + vty_out(vty, "%% mesh-group source del failed\n"); + } - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; } -static int -ip_no_msdp_mesh_group_cmd_worker(struct vty *vty, const char *mg) +static int ip_no_msdp_mesh_group_cmd_worker(struct vty *vty, const char *mg) { - enum pim_msdp_err result; + enum pim_msdp_err result; - result = pim_msdp_mg_del(mg); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_NO_MG: - vty_out (vty, "%% mesh-group does not exist\n"); - break; - default: - vty_out (vty, "%% mesh-group source del failed\n"); - } + result = pim_msdp_mg_del(mg); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_NO_MG: + vty_out(vty, "%% mesh-group does not exist\n"); + break; + default: + vty_out(vty, "%% mesh-group source del failed\n"); + } - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; } DEFUN (no_ip_msdp_mesh_group_source, @@ -6285,86 +6713,87 @@ DEFUN (no_ip_msdp_mesh_group_source, "mesh group source\n" "mesh group local address\n") { - if (argc == 7) - return ip_no_msdp_mesh_group_cmd_worker(vty, argv[6]->arg); - else - return ip_no_msdp_mesh_group_source_cmd_worker(vty, argv[4]->arg); -} - -static void -print_empty_json_obj(struct vty *vty) -{ - json_object *json; - json = json_object_new_object(); - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); -} - -static void -ip_msdp_show_mesh_group(struct vty *vty, u_char uj) -{ - struct listnode *mbrnode; - struct pim_msdp_mg_mbr *mbr; - struct pim_msdp_mg *mg = msdp->mg; - char mbr_str[INET_ADDRSTRLEN]; - char src_str[INET_ADDRSTRLEN]; - char state_str[PIM_MSDP_STATE_STRLEN]; - enum pim_msdp_peer_state state; - json_object *json = NULL; - json_object *json_mg_row = NULL; - json_object *json_members = NULL; - json_object *json_row = NULL; - - if (!mg) { - if (uj) - print_empty_json_obj(vty); - return; - } - - pim_inet4_dump("", mg->src_ip, src_str, sizeof(src_str)); - if (uj) { - json = json_object_new_object(); - /* currently there is only one mesh group but we should still make - * it a dict with mg-name as key */ - json_mg_row = json_object_new_object(); - json_object_string_add(json_mg_row, "name", mg->mesh_group_name); - json_object_string_add(json_mg_row, "source", src_str); - } else { - vty_out (vty, "Mesh group : %s\n", mg->mesh_group_name); - vty_out (vty, " Source : %s\n", src_str); - vty_out (vty, " Member State\n"); - } - - for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) { - pim_inet4_dump("", mbr->mbr_ip, mbr_str, sizeof(mbr_str)); - if (mbr->mp) { - state = mbr->mp->state; - } else { - state = PIM_MSDP_DISABLED; - } - pim_msdp_state_dump(state, state_str, sizeof(state_str)); - if (uj) { - json_row = json_object_new_object(); - json_object_string_add(json_row, "member", mbr_str); - json_object_string_add(json_row, "state", state_str); - if (!json_members) { - json_members = json_object_new_object(); - json_object_object_add(json_mg_row, "members", json_members); - } - json_object_object_add(json_members, mbr_str, json_row); - } else { - vty_out (vty, " %-15s %11s\n", - mbr_str, state_str); - } - } - - if (uj) { - json_object_object_add(json, mg->mesh_group_name, json_mg_row); - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + if (argc == 7) + return ip_no_msdp_mesh_group_cmd_worker(vty, argv[6]->arg); + else + return ip_no_msdp_mesh_group_source_cmd_worker(vty, + argv[4]->arg); +} + +static void print_empty_json_obj(struct vty *vty) +{ + json_object *json; + json = json_object_new_object(); + vty_out(vty, "%s\n", + json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); +} + +static void ip_msdp_show_mesh_group(struct vty *vty, u_char uj) +{ + struct listnode *mbrnode; + struct pim_msdp_mg_mbr *mbr; + struct pim_msdp_mg *mg = msdp->mg; + char mbr_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; + char state_str[PIM_MSDP_STATE_STRLEN]; + enum pim_msdp_peer_state state; + json_object *json = NULL; + json_object *json_mg_row = NULL; + json_object *json_members = NULL; + json_object *json_row = NULL; + + if (!mg) { + if (uj) + print_empty_json_obj(vty); + return; + } + + pim_inet4_dump("", mg->src_ip, src_str, sizeof(src_str)); + if (uj) { + json = json_object_new_object(); + /* currently there is only one mesh group but we should still + * make + * it a dict with mg-name as key */ + json_mg_row = json_object_new_object(); + json_object_string_add(json_mg_row, "name", + mg->mesh_group_name); + json_object_string_add(json_mg_row, "source", src_str); + } else { + vty_out(vty, "Mesh group : %s\n", mg->mesh_group_name); + vty_out(vty, " Source : %s\n", src_str); + vty_out(vty, " Member State\n"); + } + + for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) { + pim_inet4_dump("", mbr->mbr_ip, mbr_str, sizeof(mbr_str)); + if (mbr->mp) { + state = mbr->mp->state; + } else { + state = PIM_MSDP_DISABLED; + } + pim_msdp_state_dump(state, state_str, sizeof(state_str)); + if (uj) { + json_row = json_object_new_object(); + json_object_string_add(json_row, "member", mbr_str); + json_object_string_add(json_row, "state", state_str); + if (!json_members) { + json_members = json_object_new_object(); + json_object_object_add(json_mg_row, "members", + json_members); + } + json_object_object_add(json_members, mbr_str, json_row); + } else { + vty_out(vty, " %-15s %11s\n", mbr_str, state_str); + } + } + + if (uj) { + json_object_object_add(json, mg->mesh_group_name, json_mg_row); + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } DEFUN (show_ip_msdp_mesh_group, @@ -6376,151 +6805,168 @@ DEFUN (show_ip_msdp_mesh_group, "MSDP mesh-group information\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - ip_msdp_show_mesh_group(vty, uj); - - return CMD_SUCCESS; -} - -static void -ip_msdp_show_peers(struct vty *vty, u_char uj) -{ - struct listnode *mpnode; - struct pim_msdp_peer *mp; - char peer_str[INET_ADDRSTRLEN]; - char local_str[INET_ADDRSTRLEN]; - char state_str[PIM_MSDP_STATE_STRLEN]; - char timebuf[PIM_MSDP_UPTIME_STRLEN]; - int64_t now; - json_object *json = NULL; - json_object *json_row = NULL; - - - if (uj) { - json = json_object_new_object(); - } else { - vty_out (vty, - "Peer Local State Uptime SaCnt\n"); - } - - for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { - if (mp->state == PIM_MSDP_ESTABLISHED) { - now = pim_time_monotonic_sec(); - pim_time_uptime(timebuf, sizeof(timebuf), now - mp->uptime); - } else { - strcpy(timebuf, "-"); - } - pim_inet4_dump("", mp->peer, peer_str, sizeof(peer_str)); - pim_inet4_dump("", mp->local, local_str, sizeof(local_str)); - pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); - if (uj) { - json_row = json_object_new_object(); - json_object_string_add(json_row, "peer", peer_str); - json_object_string_add(json_row, "local", local_str); - json_object_string_add(json_row, "state", state_str); - json_object_string_add(json_row, "upTime", timebuf); - json_object_int_add(json_row, "saCount", mp->sa_cnt); - json_object_object_add(json, peer_str, json_row); - } else { - vty_out (vty, "%-15s %15s %11s %8s %6d\n", - peer_str, local_str, state_str, - timebuf, mp->sa_cnt); - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } -} - -static void -ip_msdp_show_peers_detail(struct vty *vty, const char *peer, u_char uj) -{ - struct listnode *mpnode; - struct pim_msdp_peer *mp; - char peer_str[INET_ADDRSTRLEN]; - char local_str[INET_ADDRSTRLEN]; - char state_str[PIM_MSDP_STATE_STRLEN]; - char timebuf[PIM_MSDP_UPTIME_STRLEN]; - char katimer[PIM_MSDP_TIMER_STRLEN]; - char crtimer[PIM_MSDP_TIMER_STRLEN]; - char holdtimer[PIM_MSDP_TIMER_STRLEN]; - int64_t now; - json_object *json = NULL; - json_object *json_row = NULL; - - if (uj) { - json = json_object_new_object(); - } - - for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { - pim_inet4_dump("", mp->peer, peer_str, sizeof(peer_str)); - if (strcmp(peer, "detail") && - strcmp(peer, peer_str)) - continue; - - if (mp->state == PIM_MSDP_ESTABLISHED) { - now = pim_time_monotonic_sec(); - pim_time_uptime(timebuf, sizeof(timebuf), now - mp->uptime); - } else { - strcpy(timebuf, "-"); - } - pim_inet4_dump("", mp->local, local_str, sizeof(local_str)); - pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); - pim_time_timer_to_hhmmss(katimer, sizeof(katimer), mp->ka_timer); - pim_time_timer_to_hhmmss(crtimer, sizeof(crtimer), mp->cr_timer); - pim_time_timer_to_hhmmss(holdtimer, sizeof(holdtimer), mp->hold_timer); - - if (uj) { - json_row = json_object_new_object(); - json_object_string_add(json_row, "peer", peer_str); - json_object_string_add(json_row, "local", local_str); - json_object_string_add(json_row, "meshGroupName", mp->mesh_group_name); - json_object_string_add(json_row, "state", state_str); - json_object_string_add(json_row, "upTime", timebuf); - json_object_string_add(json_row, "keepAliveTimer", katimer); - json_object_string_add(json_row, "connRetryTimer", crtimer); - json_object_string_add(json_row, "holdTimer", holdtimer); - json_object_string_add(json_row, "lastReset", mp->last_reset); - json_object_int_add(json_row, "connAttempts", mp->conn_attempts); - json_object_int_add(json_row, "establishedChanges", mp->est_flaps); - json_object_int_add(json_row, "saCount", mp->sa_cnt); - json_object_int_add(json_row, "kaSent", mp->ka_tx_cnt); - json_object_int_add(json_row, "kaRcvd", mp->ka_rx_cnt); - json_object_int_add(json_row, "saSent", mp->sa_tx_cnt); - json_object_int_add(json_row, "saRcvd", mp->sa_rx_cnt); - json_object_object_add(json, peer_str, json_row); - } else { - vty_out (vty, "Peer : %s\n", peer_str); - vty_out (vty, " Local : %s\n", local_str); - vty_out (vty, " Mesh Group : %s\n", mp->mesh_group_name); - vty_out (vty, " State : %s\n", state_str); - vty_out (vty, " Uptime : %s\n", timebuf); - - vty_out (vty, " Keepalive Timer : %s\n", katimer); - vty_out (vty, " Conn Retry Timer : %s\n", crtimer); - vty_out (vty, " Hold Timer : %s\n", holdtimer); - vty_out (vty, " Last Reset : %s\n", mp->last_reset); - vty_out (vty, " Conn Attempts : %d\n", mp->conn_attempts); - vty_out (vty, " Established Changes : %d\n", mp->est_flaps); - vty_out (vty, " SA Count : %d\n", mp->sa_cnt); - vty_out (vty, " Statistics :\n"); - vty_out (vty, " Sent Rcvd\n"); - vty_out (vty, " Keepalives : %10d %10d\n", - mp->ka_tx_cnt, mp->ka_rx_cnt); - vty_out (vty, " SAs : %10d %10d\n", - mp->sa_tx_cnt, mp->sa_rx_cnt); - vty_out (vty, "\n"); - } - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + u_char uj = use_json(argc, argv); + ip_msdp_show_mesh_group(vty, uj); + + return CMD_SUCCESS; +} + +static void ip_msdp_show_peers(struct vty *vty, u_char uj) +{ + struct listnode *mpnode; + struct pim_msdp_peer *mp; + char peer_str[INET_ADDRSTRLEN]; + char local_str[INET_ADDRSTRLEN]; + char state_str[PIM_MSDP_STATE_STRLEN]; + char timebuf[PIM_MSDP_UPTIME_STRLEN]; + int64_t now; + json_object *json = NULL; + json_object *json_row = NULL; + + + if (uj) { + json = json_object_new_object(); + } else { + vty_out(vty, + "Peer Local State Uptime SaCnt\n"); + } + + for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { + if (mp->state == PIM_MSDP_ESTABLISHED) { + now = pim_time_monotonic_sec(); + pim_time_uptime(timebuf, sizeof(timebuf), + now - mp->uptime); + } else { + strcpy(timebuf, "-"); + } + pim_inet4_dump("", mp->peer, peer_str, sizeof(peer_str)); + pim_inet4_dump("", mp->local, local_str, + sizeof(local_str)); + pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); + if (uj) { + json_row = json_object_new_object(); + json_object_string_add(json_row, "peer", peer_str); + json_object_string_add(json_row, "local", local_str); + json_object_string_add(json_row, "state", state_str); + json_object_string_add(json_row, "upTime", timebuf); + json_object_int_add(json_row, "saCount", mp->sa_cnt); + json_object_object_add(json, peer_str, json_row); + } else { + vty_out(vty, "%-15s %15s %11s %8s %6d\n", peer_str, + local_str, state_str, timebuf, mp->sa_cnt); + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } +} + +static void ip_msdp_show_peers_detail(struct vty *vty, const char *peer, + u_char uj) +{ + struct listnode *mpnode; + struct pim_msdp_peer *mp; + char peer_str[INET_ADDRSTRLEN]; + char local_str[INET_ADDRSTRLEN]; + char state_str[PIM_MSDP_STATE_STRLEN]; + char timebuf[PIM_MSDP_UPTIME_STRLEN]; + char katimer[PIM_MSDP_TIMER_STRLEN]; + char crtimer[PIM_MSDP_TIMER_STRLEN]; + char holdtimer[PIM_MSDP_TIMER_STRLEN]; + int64_t now; + json_object *json = NULL; + json_object *json_row = NULL; + + if (uj) { + json = json_object_new_object(); + } + + for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { + pim_inet4_dump("", mp->peer, peer_str, sizeof(peer_str)); + if (strcmp(peer, "detail") && strcmp(peer, peer_str)) + continue; + + if (mp->state == PIM_MSDP_ESTABLISHED) { + now = pim_time_monotonic_sec(); + pim_time_uptime(timebuf, sizeof(timebuf), + now - mp->uptime); + } else { + strcpy(timebuf, "-"); + } + pim_inet4_dump("", mp->local, local_str, + sizeof(local_str)); + pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); + pim_time_timer_to_hhmmss(katimer, sizeof(katimer), + mp->ka_timer); + pim_time_timer_to_hhmmss(crtimer, sizeof(crtimer), + mp->cr_timer); + pim_time_timer_to_hhmmss(holdtimer, sizeof(holdtimer), + mp->hold_timer); + + if (uj) { + json_row = json_object_new_object(); + json_object_string_add(json_row, "peer", peer_str); + json_object_string_add(json_row, "local", local_str); + json_object_string_add(json_row, "meshGroupName", + mp->mesh_group_name); + json_object_string_add(json_row, "state", state_str); + json_object_string_add(json_row, "upTime", timebuf); + json_object_string_add(json_row, "keepAliveTimer", + katimer); + json_object_string_add(json_row, "connRetryTimer", + crtimer); + json_object_string_add(json_row, "holdTimer", + holdtimer); + json_object_string_add(json_row, "lastReset", + mp->last_reset); + json_object_int_add(json_row, "connAttempts", + mp->conn_attempts); + json_object_int_add(json_row, "establishedChanges", + mp->est_flaps); + json_object_int_add(json_row, "saCount", mp->sa_cnt); + json_object_int_add(json_row, "kaSent", mp->ka_tx_cnt); + json_object_int_add(json_row, "kaRcvd", mp->ka_rx_cnt); + json_object_int_add(json_row, "saSent", mp->sa_tx_cnt); + json_object_int_add(json_row, "saRcvd", mp->sa_rx_cnt); + json_object_object_add(json, peer_str, json_row); + } else { + vty_out(vty, "Peer : %s\n", peer_str); + vty_out(vty, " Local : %s\n", local_str); + vty_out(vty, " Mesh Group : %s\n", + mp->mesh_group_name); + vty_out(vty, " State : %s\n", state_str); + vty_out(vty, " Uptime : %s\n", timebuf); + + vty_out(vty, " Keepalive Timer : %s\n", katimer); + vty_out(vty, " Conn Retry Timer : %s\n", crtimer); + vty_out(vty, " Hold Timer : %s\n", holdtimer); + vty_out(vty, " Last Reset : %s\n", + mp->last_reset); + vty_out(vty, " Conn Attempts : %d\n", + mp->conn_attempts); + vty_out(vty, " Established Changes : %d\n", + mp->est_flaps); + vty_out(vty, " SA Count : %d\n", + mp->sa_cnt); + vty_out(vty, " Statistics :\n"); + vty_out(vty, + " Sent Rcvd\n"); + vty_out(vty, " Keepalives : %10d %10d\n", + mp->ka_tx_cnt, mp->ka_rx_cnt); + vty_out(vty, " SAs : %10d %10d\n", + mp->sa_tx_cnt, mp->sa_rx_cnt); + vty_out(vty, "\n"); + } + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } DEFUN (show_ip_msdp_peer_detail, @@ -6534,181 +6980,183 @@ DEFUN (show_ip_msdp_peer_detail, "peer ip address\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - if (uj) - argc--; - - if (argc > 4) - ip_msdp_show_peers_detail(vty, argv[4]->arg, uj); - else - ip_msdp_show_peers(vty, uj); - - return CMD_SUCCESS; -} - -static void -ip_msdp_show_sa(struct vty *vty, u_char uj) -{ - struct listnode *sanode; - struct pim_msdp_sa *sa; - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - char rp_str[INET_ADDRSTRLEN]; - char timebuf[PIM_MSDP_UPTIME_STRLEN]; - char spt_str[8]; - char local_str[8]; - int64_t now; - json_object *json = NULL; - json_object *json_group = NULL; - json_object *json_row = NULL; - - if (uj) { - json = json_object_new_object(); - } else { - vty_out (vty, - "Source Group RP Local SPT Uptime\n"); - } - - for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { - now = pim_time_monotonic_sec(); - pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime); - pim_inet4_dump("", sa->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", sa->sg.grp, grp_str, sizeof(grp_str)); - if (sa->flags & PIM_MSDP_SAF_PEER) { - pim_inet4_dump("", sa->rp, rp_str, sizeof(rp_str)); - if (sa->up) { - strcpy(spt_str, "yes"); - } else { - strcpy(spt_str, "no"); - } - } else { - strcpy(rp_str, "-"); - strcpy(spt_str, "-"); - } - if (sa->flags & PIM_MSDP_SAF_LOCAL) { - strcpy(local_str, "yes"); - } else { - strcpy(local_str, "no"); - } - if (uj) { - json_object_object_get_ex(json, grp_str, &json_group); - - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json, grp_str, json_group); - } - - json_row = json_object_new_object(); - json_object_string_add(json_row, "source", src_str); - json_object_string_add(json_row, "group", grp_str); - json_object_string_add(json_row, "rp", rp_str); - json_object_string_add(json_row, "local", local_str); - json_object_string_add(json_row, "sptSetup", spt_str); - json_object_string_add(json_row, "upTime", timebuf); - json_object_object_add(json_group, src_str, json_row); - } else { - vty_out (vty, "%-15s %15s %15s %5c %3c %8s\n", - src_str, grp_str, rp_str, local_str[0], spt_str[0], timebuf); - } - } - - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } -} - -static void -ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa, const char *src_str, - const char *grp_str, struct vty *vty, - u_char uj, json_object *json) -{ - char rp_str[INET_ADDRSTRLEN]; - char peer_str[INET_ADDRSTRLEN]; - char timebuf[PIM_MSDP_UPTIME_STRLEN]; - char spt_str[8]; - char local_str[8]; - char statetimer[PIM_MSDP_TIMER_STRLEN]; - int64_t now; - json_object *json_group = NULL; - json_object *json_row = NULL; - - now = pim_time_monotonic_sec(); - pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime); - if (sa->flags & PIM_MSDP_SAF_PEER) { - pim_inet4_dump("", sa->rp, rp_str, sizeof(rp_str)); - pim_inet4_dump("", sa->peer, peer_str, sizeof(peer_str)); - if (sa->up) { - strcpy(spt_str, "yes"); - } else { - strcpy(spt_str, "no"); - } - } else { - strcpy(rp_str, "-"); - strcpy(peer_str, "-"); - strcpy(spt_str, "-"); - } - if (sa->flags & PIM_MSDP_SAF_LOCAL) { - strcpy(local_str, "yes"); - } else { - strcpy(local_str, "no"); - } - pim_time_timer_to_hhmmss(statetimer, sizeof(statetimer), sa->sa_state_timer); - if (uj) { - json_object_object_get_ex(json, grp_str, &json_group); - - if (!json_group) { - json_group = json_object_new_object(); - json_object_object_add(json, grp_str, json_group); - } - - json_row = json_object_new_object(); - json_object_string_add(json_row, "source", src_str); - json_object_string_add(json_row, "group", grp_str); - json_object_string_add(json_row, "rp", rp_str); - json_object_string_add(json_row, "local", local_str); - json_object_string_add(json_row, "sptSetup", spt_str); - json_object_string_add(json_row, "upTime", timebuf); - json_object_string_add(json_row, "stateTimer", statetimer); - json_object_object_add(json_group, src_str, json_row); - } else { - vty_out (vty, "SA : %s\n", sa->sg_str); - vty_out (vty, " RP : %s\n", rp_str); - vty_out (vty, " Peer : %s\n", peer_str); - vty_out (vty, " Local : %s\n", local_str); - vty_out (vty, " SPT Setup : %s\n", spt_str); - vty_out (vty, " Uptime : %s\n", timebuf); - vty_out (vty, " State Timer : %s\n", statetimer); - vty_out (vty, "\n"); - } -} - -static void -ip_msdp_show_sa_detail(struct vty *vty, u_char uj) -{ - struct listnode *sanode; - struct pim_msdp_sa *sa; - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - json_object *json = NULL; - - if (uj) { - json = json_object_new_object(); - } - - for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { - pim_inet4_dump("", sa->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", sa->sg.grp, grp_str, sizeof(grp_str)); - ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj, json); - } - - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + u_char uj = use_json(argc, argv); + if (uj) + argc--; + + if (argc > 4) + ip_msdp_show_peers_detail(vty, argv[4]->arg, uj); + else + ip_msdp_show_peers(vty, uj); + + return CMD_SUCCESS; +} + +static void ip_msdp_show_sa(struct vty *vty, u_char uj) +{ + struct listnode *sanode; + struct pim_msdp_sa *sa; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + char rp_str[INET_ADDRSTRLEN]; + char timebuf[PIM_MSDP_UPTIME_STRLEN]; + char spt_str[8]; + char local_str[8]; + int64_t now; + json_object *json = NULL; + json_object *json_group = NULL; + json_object *json_row = NULL; + + if (uj) { + json = json_object_new_object(); + } else { + vty_out(vty, + "Source Group RP Local SPT Uptime\n"); + } + + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + now = pim_time_monotonic_sec(); + pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime); + pim_inet4_dump("", sa->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", sa->sg.grp, grp_str, sizeof(grp_str)); + if (sa->flags & PIM_MSDP_SAF_PEER) { + pim_inet4_dump("", sa->rp, rp_str, sizeof(rp_str)); + if (sa->up) { + strcpy(spt_str, "yes"); + } else { + strcpy(spt_str, "no"); + } + } else { + strcpy(rp_str, "-"); + strcpy(spt_str, "-"); + } + if (sa->flags & PIM_MSDP_SAF_LOCAL) { + strcpy(local_str, "yes"); + } else { + strcpy(local_str, "no"); + } + if (uj) { + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, + json_group); + } + + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + json_object_string_add(json_row, "rp", rp_str); + json_object_string_add(json_row, "local", local_str); + json_object_string_add(json_row, "sptSetup", spt_str); + json_object_string_add(json_row, "upTime", timebuf); + json_object_object_add(json_group, src_str, json_row); + } else { + vty_out(vty, "%-15s %15s %15s %5c %3c %8s\n", + src_str, grp_str, rp_str, local_str[0], + spt_str[0], timebuf); + } + } + + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } +} + +static void ip_msdp_show_sa_entry_detail(struct pim_msdp_sa *sa, + const char *src_str, + const char *grp_str, struct vty *vty, + u_char uj, json_object *json) +{ + char rp_str[INET_ADDRSTRLEN]; + char peer_str[INET_ADDRSTRLEN]; + char timebuf[PIM_MSDP_UPTIME_STRLEN]; + char spt_str[8]; + char local_str[8]; + char statetimer[PIM_MSDP_TIMER_STRLEN]; + int64_t now; + json_object *json_group = NULL; + json_object *json_row = NULL; + + now = pim_time_monotonic_sec(); + pim_time_uptime(timebuf, sizeof(timebuf), now - sa->uptime); + if (sa->flags & PIM_MSDP_SAF_PEER) { + pim_inet4_dump("", sa->rp, rp_str, sizeof(rp_str)); + pim_inet4_dump("", sa->peer, peer_str, sizeof(peer_str)); + if (sa->up) { + strcpy(spt_str, "yes"); + } else { + strcpy(spt_str, "no"); + } + } else { + strcpy(rp_str, "-"); + strcpy(peer_str, "-"); + strcpy(spt_str, "-"); + } + if (sa->flags & PIM_MSDP_SAF_LOCAL) { + strcpy(local_str, "yes"); + } else { + strcpy(local_str, "no"); + } + pim_time_timer_to_hhmmss(statetimer, sizeof(statetimer), + sa->sa_state_timer); + if (uj) { + json_object_object_get_ex(json, grp_str, &json_group); + + if (!json_group) { + json_group = json_object_new_object(); + json_object_object_add(json, grp_str, json_group); + } + + json_row = json_object_new_object(); + json_object_string_add(json_row, "source", src_str); + json_object_string_add(json_row, "group", grp_str); + json_object_string_add(json_row, "rp", rp_str); + json_object_string_add(json_row, "local", local_str); + json_object_string_add(json_row, "sptSetup", spt_str); + json_object_string_add(json_row, "upTime", timebuf); + json_object_string_add(json_row, "stateTimer", statetimer); + json_object_object_add(json_group, src_str, json_row); + } else { + vty_out(vty, "SA : %s\n", sa->sg_str); + vty_out(vty, " RP : %s\n", rp_str); + vty_out(vty, " Peer : %s\n", peer_str); + vty_out(vty, " Local : %s\n", local_str); + vty_out(vty, " SPT Setup : %s\n", spt_str); + vty_out(vty, " Uptime : %s\n", timebuf); + vty_out(vty, " State Timer : %s\n", statetimer); + vty_out(vty, "\n"); + } +} + +static void ip_msdp_show_sa_detail(struct vty *vty, u_char uj) +{ + struct listnode *sanode; + struct pim_msdp_sa *sa; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + json_object *json = NULL; + + if (uj) { + json = json_object_new_object(); + } + + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + pim_inet4_dump("", sa->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", sa->sg.grp, grp_str, sizeof(grp_str)); + ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj, + json); + } + + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } DEFUN (show_ip_msdp_sa_detail, @@ -6721,66 +7169,67 @@ DEFUN (show_ip_msdp_sa_detail, "Detailed output\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); - ip_msdp_show_sa_detail(vty, uj); + u_char uj = use_json(argc, argv); + ip_msdp_show_sa_detail(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static void -ip_msdp_show_sa_addr(struct vty *vty, const char *addr, u_char uj) +static void ip_msdp_show_sa_addr(struct vty *vty, const char *addr, u_char uj) { - struct listnode *sanode; - struct pim_msdp_sa *sa; - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - json_object *json = NULL; + struct listnode *sanode; + struct pim_msdp_sa *sa; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + json_object *json = NULL; - if (uj) { - json = json_object_new_object(); - } + if (uj) { + json = json_object_new_object(); + } - for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { - pim_inet4_dump("", sa->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", sa->sg.grp, grp_str, sizeof(grp_str)); - if (!strcmp(addr, src_str) || !strcmp(addr, grp_str)) { - ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj, json); - } - } + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + pim_inet4_dump("", sa->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", sa->sg.grp, grp_str, sizeof(grp_str)); + if (!strcmp(addr, src_str) || !strcmp(addr, grp_str)) { + ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, + uj, json); + } + } - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } -static void -ip_msdp_show_sa_sg(struct vty *vty, const char *src, const char *grp, u_char uj) +static void ip_msdp_show_sa_sg(struct vty *vty, const char *src, + const char *grp, u_char uj) { - struct listnode *sanode; - struct pim_msdp_sa *sa; - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - json_object *json = NULL; + struct listnode *sanode; + struct pim_msdp_sa *sa; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + json_object *json = NULL; - if (uj) { - json = json_object_new_object(); - } + if (uj) { + json = json_object_new_object(); + } - for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { - pim_inet4_dump("", sa->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", sa->sg.grp, grp_str, sizeof(grp_str)); - if (!strcmp(src, src_str) && !strcmp(grp, grp_str)) { - ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, uj, json); - } - } + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + pim_inet4_dump("", sa->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", sa->sg.grp, grp_str, sizeof(grp_str)); + if (!strcmp(src, src_str) && !strcmp(grp, grp_str)) { + ip_msdp_show_sa_entry_detail(sa, src_str, grp_str, vty, + uj, json); + } + } - if (uj) { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + if (uj) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } DEFUN (show_ip_msdp_sa_sg, @@ -6794,218 +7243,227 @@ DEFUN (show_ip_msdp_sa_sg, "group ip\n" "JavaScript Object Notation\n") { - u_char uj = use_json(argc, argv); + u_char uj = use_json(argc, argv); - int idx = 0; - char *src_ip = argv_find (argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg : NULL; - char *grp_ip = idx < argc && argv_find (argv, argc, "A.B.C.D", &idx) ? - argv[idx]->arg : NULL; + int idx = 0; + char *src_ip = argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx++]->arg + : NULL; + char *grp_ip = idx < argc && argv_find(argv, argc, "A.B.C.D", &idx) + ? argv[idx]->arg + : NULL; - if (src_ip && grp_ip) - ip_msdp_show_sa_sg(vty, src_ip, grp_ip, uj); - else if (src_ip) - ip_msdp_show_sa_addr(vty, src_ip, uj); - else - ip_msdp_show_sa(vty, uj); + if (src_ip && grp_ip) + ip_msdp_show_sa_sg(vty, src_ip, grp_ip, uj); + else if (src_ip) + ip_msdp_show_sa_addr(vty, src_ip, uj); + else + ip_msdp_show_sa(vty, uj); - return CMD_SUCCESS; + return CMD_SUCCESS; } void pim_cmd_init() { - install_node (&pim_global_node, pim_global_config_write); /* PIM_NODE */ - install_node (&interface_node, pim_interface_config_write); /* INTERFACE_NODE */ - if_cmd_init (); - - install_node (&debug_node, pim_debug_config_write); - - install_element (CONFIG_NODE, &ip_multicast_routing_cmd); - install_element (CONFIG_NODE, &no_ip_multicast_routing_cmd); - install_element (CONFIG_NODE, &ip_pim_rp_cmd); - install_element (CONFIG_NODE, &no_ip_pim_rp_cmd); - install_element (CONFIG_NODE, &ip_pim_rp_prefix_list_cmd); - install_element (CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd); - install_element (CONFIG_NODE, &no_ip_pim_ssm_prefix_list_cmd); - install_element (CONFIG_NODE, &no_ip_pim_ssm_prefix_list_name_cmd); - install_element (CONFIG_NODE, &ip_pim_ssm_prefix_list_cmd); - install_element (CONFIG_NODE, &ip_pim_register_suppress_cmd); - install_element (CONFIG_NODE, &no_ip_pim_register_suppress_cmd); - install_element (CONFIG_NODE, &ip_pim_spt_switchover_infinity_cmd); - install_element (CONFIG_NODE, &ip_pim_spt_switchover_infinity_plist_cmd); - install_element (CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_cmd); - install_element (CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_plist_cmd); - install_element (CONFIG_NODE, &ip_pim_joinprune_time_cmd); - install_element (CONFIG_NODE, &no_ip_pim_joinprune_time_cmd); - install_element (CONFIG_NODE, &ip_pim_keep_alive_cmd); - install_element (CONFIG_NODE, &no_ip_pim_keep_alive_cmd); - install_element (CONFIG_NODE, &ip_pim_packets_cmd); - install_element (CONFIG_NODE, &no_ip_pim_packets_cmd); - install_element (CONFIG_NODE, &ip_pim_v6_secondary_cmd); - install_element (CONFIG_NODE, &no_ip_pim_v6_secondary_cmd); - install_element (CONFIG_NODE, &ip_ssmpingd_cmd); - install_element (CONFIG_NODE, &no_ip_ssmpingd_cmd); - install_element (CONFIG_NODE, &ip_msdp_peer_cmd); - install_element (CONFIG_NODE, &no_ip_msdp_peer_cmd); - install_element (CONFIG_NODE, &ip_pim_ecmp_cmd); - install_element (CONFIG_NODE, &no_ip_pim_ecmp_cmd); - install_element (CONFIG_NODE, &ip_pim_ecmp_rebalance_cmd); - install_element (CONFIG_NODE, &no_ip_pim_ecmp_rebalance_cmd); - - install_element (INTERFACE_NODE, &interface_ip_igmp_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_igmp_cmd); - install_element (INTERFACE_NODE, &interface_ip_igmp_join_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_igmp_join_cmd); - install_element (INTERFACE_NODE, &interface_ip_igmp_version_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_igmp_version_cmd); - install_element (INTERFACE_NODE, &interface_ip_igmp_query_interval_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_igmp_query_interval_cmd); - install_element (INTERFACE_NODE, &interface_ip_igmp_query_max_response_time_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_igmp_query_max_response_time_cmd); - install_element (INTERFACE_NODE, &interface_ip_igmp_query_max_response_time_dsec_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_igmp_query_max_response_time_dsec_cmd); - install_element (INTERFACE_NODE, &interface_ip_pim_ssm_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_pim_ssm_cmd); - install_element (INTERFACE_NODE, &interface_ip_pim_sm_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_pim_sm_cmd); - install_element (INTERFACE_NODE, &interface_ip_pim_drprio_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_pim_drprio_cmd); - install_element (INTERFACE_NODE, &interface_ip_pim_hello_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_pim_hello_cmd); - - // Static mroutes NEB - install_element (INTERFACE_NODE, &interface_ip_mroute_cmd); - install_element (INTERFACE_NODE, &interface_ip_mroute_source_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_mroute_cmd); - install_element (INTERFACE_NODE, &interface_no_ip_mroute_source_cmd); - - install_element (VIEW_NODE, &show_ip_igmp_interface_cmd); - install_element (VIEW_NODE, &show_ip_igmp_join_cmd); - install_element (VIEW_NODE, &show_ip_igmp_groups_cmd); - install_element (VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd); - install_element (VIEW_NODE, &show_ip_igmp_sources_cmd); - install_element (VIEW_NODE, &show_ip_igmp_sources_retransmissions_cmd); - install_element (VIEW_NODE, &show_ip_pim_assert_cmd); - install_element (VIEW_NODE, &show_ip_pim_assert_internal_cmd); - install_element (VIEW_NODE, &show_ip_pim_assert_metric_cmd); - install_element (VIEW_NODE, &show_ip_pim_assert_winner_metric_cmd); - install_element (VIEW_NODE, &show_ip_pim_interface_traffic_cmd); - install_element (VIEW_NODE, &show_ip_pim_interface_cmd); - install_element (VIEW_NODE, &show_ip_pim_join_cmd); - install_element (VIEW_NODE, &show_ip_pim_local_membership_cmd); - install_element (VIEW_NODE, &show_ip_pim_neighbor_cmd); - install_element (VIEW_NODE, &show_ip_pim_rpf_cmd); - install_element (VIEW_NODE, &show_ip_pim_secondary_cmd); - install_element (VIEW_NODE, &show_ip_pim_state_cmd); - install_element (VIEW_NODE, &show_ip_pim_upstream_cmd); - install_element (VIEW_NODE, &show_ip_pim_upstream_join_desired_cmd); - install_element (VIEW_NODE, &show_ip_pim_upstream_rpf_cmd); - install_element (VIEW_NODE, &show_ip_pim_rp_cmd); - install_element (VIEW_NODE, &show_ip_multicast_cmd); - install_element (VIEW_NODE, &show_ip_mroute_cmd); - install_element (VIEW_NODE, &show_ip_mroute_count_cmd); - install_element (VIEW_NODE, &show_ip_rib_cmd); - install_element (VIEW_NODE, &show_ip_ssmpingd_cmd); - install_element (VIEW_NODE, &show_debugging_pim_cmd); - install_element (VIEW_NODE, &show_ip_pim_nexthop_cmd); - install_element (VIEW_NODE, &show_ip_pim_nexthop_lookup_cmd); - - install_element (ENABLE_NODE, &clear_ip_interfaces_cmd); - install_element (ENABLE_NODE, &clear_ip_igmp_interfaces_cmd); - install_element (ENABLE_NODE, &clear_ip_mroute_cmd); - install_element (ENABLE_NODE, &clear_ip_pim_interfaces_cmd); - install_element (ENABLE_NODE, &clear_ip_pim_interface_traffic_cmd); - install_element (ENABLE_NODE, &clear_ip_pim_oil_cmd); - - install_element (ENABLE_NODE, &debug_igmp_cmd); - install_element (ENABLE_NODE, &no_debug_igmp_cmd); - install_element (ENABLE_NODE, &debug_igmp_events_cmd); - install_element (ENABLE_NODE, &no_debug_igmp_events_cmd); - install_element (ENABLE_NODE, &debug_igmp_packets_cmd); - install_element (ENABLE_NODE, &no_debug_igmp_packets_cmd); - install_element (ENABLE_NODE, &debug_igmp_trace_cmd); - install_element (ENABLE_NODE, &no_debug_igmp_trace_cmd); - install_element (ENABLE_NODE, &debug_mroute_cmd); - install_element (ENABLE_NODE, &debug_mroute_detail_cmd); - install_element (ENABLE_NODE, &no_debug_mroute_cmd); - install_element (ENABLE_NODE, &no_debug_mroute_detail_cmd); - install_element (ENABLE_NODE, &debug_static_cmd); - install_element (ENABLE_NODE, &no_debug_static_cmd); - install_element (ENABLE_NODE, &debug_pim_cmd); - install_element (ENABLE_NODE, &no_debug_pim_cmd); - install_element (ENABLE_NODE, &debug_pim_events_cmd); - install_element (ENABLE_NODE, &no_debug_pim_events_cmd); - install_element (ENABLE_NODE, &debug_pim_packets_cmd); - install_element (ENABLE_NODE, &no_debug_pim_packets_cmd); - install_element (ENABLE_NODE, &debug_pim_packetdump_send_cmd); - install_element (ENABLE_NODE, &no_debug_pim_packetdump_send_cmd); - install_element (ENABLE_NODE, &debug_pim_packetdump_recv_cmd); - install_element (ENABLE_NODE, &no_debug_pim_packetdump_recv_cmd); - install_element (ENABLE_NODE, &debug_pim_trace_cmd); - install_element (ENABLE_NODE, &no_debug_pim_trace_cmd); - install_element (ENABLE_NODE, &debug_ssmpingd_cmd); - install_element (ENABLE_NODE, &no_debug_ssmpingd_cmd); - install_element (ENABLE_NODE, &debug_pim_zebra_cmd); - install_element (ENABLE_NODE, &no_debug_pim_zebra_cmd); - install_element (ENABLE_NODE, &debug_msdp_cmd); - install_element (ENABLE_NODE, &no_debug_msdp_cmd); - install_element (ENABLE_NODE, &undebug_msdp_cmd); - install_element (ENABLE_NODE, &debug_msdp_events_cmd); - install_element (ENABLE_NODE, &no_debug_msdp_events_cmd); - install_element (ENABLE_NODE, &undebug_msdp_events_cmd); - install_element (ENABLE_NODE, &debug_msdp_packets_cmd); - install_element (ENABLE_NODE, &no_debug_msdp_packets_cmd); - install_element (ENABLE_NODE, &undebug_msdp_packets_cmd); - - install_element (CONFIG_NODE, &debug_igmp_cmd); - install_element (CONFIG_NODE, &no_debug_igmp_cmd); - install_element (CONFIG_NODE, &debug_igmp_events_cmd); - install_element (CONFIG_NODE, &no_debug_igmp_events_cmd); - install_element (CONFIG_NODE, &debug_igmp_packets_cmd); - install_element (CONFIG_NODE, &no_debug_igmp_packets_cmd); - install_element (CONFIG_NODE, &debug_igmp_trace_cmd); - install_element (CONFIG_NODE, &no_debug_igmp_trace_cmd); - install_element (CONFIG_NODE, &debug_mroute_cmd); - install_element (CONFIG_NODE, &debug_mroute_detail_cmd); - install_element (CONFIG_NODE, &no_debug_mroute_cmd); - install_element (CONFIG_NODE, &no_debug_mroute_detail_cmd); - install_element (CONFIG_NODE, &debug_static_cmd); - install_element (CONFIG_NODE, &no_debug_static_cmd); - install_element (CONFIG_NODE, &debug_pim_cmd); - install_element (CONFIG_NODE, &no_debug_pim_cmd); - install_element (CONFIG_NODE, &debug_pim_events_cmd); - install_element (CONFIG_NODE, &no_debug_pim_events_cmd); - install_element (CONFIG_NODE, &debug_pim_packets_cmd); - install_element (CONFIG_NODE, &no_debug_pim_packets_cmd); - install_element (CONFIG_NODE, &debug_pim_trace_cmd); - install_element (CONFIG_NODE, &no_debug_pim_trace_cmd); - install_element (CONFIG_NODE, &debug_ssmpingd_cmd); - install_element (CONFIG_NODE, &no_debug_ssmpingd_cmd); - install_element (CONFIG_NODE, &debug_pim_zebra_cmd); - install_element (CONFIG_NODE, &no_debug_pim_zebra_cmd); - install_element (CONFIG_NODE, &debug_msdp_cmd); - install_element (CONFIG_NODE, &no_debug_msdp_cmd); - install_element (CONFIG_NODE, &undebug_msdp_cmd); - install_element (CONFIG_NODE, &debug_msdp_events_cmd); - install_element (CONFIG_NODE, &no_debug_msdp_events_cmd); - install_element (CONFIG_NODE, &undebug_msdp_events_cmd); - install_element (CONFIG_NODE, &debug_msdp_packets_cmd); - install_element (CONFIG_NODE, &no_debug_msdp_packets_cmd); - install_element (CONFIG_NODE, &undebug_msdp_packets_cmd); - install_element (CONFIG_NODE, &ip_msdp_mesh_group_member_cmd); - install_element (CONFIG_NODE, &no_ip_msdp_mesh_group_member_cmd); - install_element (CONFIG_NODE, &ip_msdp_mesh_group_source_cmd); - install_element (CONFIG_NODE, &no_ip_msdp_mesh_group_source_cmd); - install_element (VIEW_NODE, &show_ip_msdp_peer_detail_cmd); - install_element (VIEW_NODE, &show_ip_msdp_sa_detail_cmd); - install_element (VIEW_NODE, &show_ip_msdp_sa_sg_cmd); - install_element (VIEW_NODE, &show_ip_msdp_mesh_group_cmd); - install_element (VIEW_NODE, &show_ip_pim_ssm_range_cmd); - install_element (VIEW_NODE, &show_ip_pim_group_type_cmd); - install_element (INTERFACE_NODE, &interface_pim_use_source_cmd); - install_element (INTERFACE_NODE, &interface_no_pim_use_source_cmd); - /* Install BFD command */ - install_element (INTERFACE_NODE, &ip_pim_bfd_cmd); - install_element (INTERFACE_NODE, &ip_pim_bfd_param_cmd); - install_element (INTERFACE_NODE, &no_ip_pim_bfd_cmd); - install_element (INTERFACE_NODE, &no_ip_pim_bfd_param_cmd); + install_node(&pim_global_node, pim_global_config_write); /* PIM_NODE */ + install_node(&interface_node, + pim_interface_config_write); /* INTERFACE_NODE */ + if_cmd_init(); + + install_node(&debug_node, pim_debug_config_write); + + install_element(CONFIG_NODE, &ip_multicast_routing_cmd); + install_element(CONFIG_NODE, &no_ip_multicast_routing_cmd); + install_element(CONFIG_NODE, &ip_pim_rp_cmd); + install_element(CONFIG_NODE, &no_ip_pim_rp_cmd); + install_element(CONFIG_NODE, &ip_pim_rp_prefix_list_cmd); + install_element(CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd); + install_element(CONFIG_NODE, &no_ip_pim_ssm_prefix_list_cmd); + install_element(CONFIG_NODE, &no_ip_pim_ssm_prefix_list_name_cmd); + install_element(CONFIG_NODE, &ip_pim_ssm_prefix_list_cmd); + install_element(CONFIG_NODE, &ip_pim_register_suppress_cmd); + install_element(CONFIG_NODE, &no_ip_pim_register_suppress_cmd); + install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_cmd); + install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_plist_cmd); + install_element(CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_cmd); + install_element(CONFIG_NODE, + &no_ip_pim_spt_switchover_infinity_plist_cmd); + install_element(CONFIG_NODE, &ip_pim_joinprune_time_cmd); + install_element(CONFIG_NODE, &no_ip_pim_joinprune_time_cmd); + install_element(CONFIG_NODE, &ip_pim_keep_alive_cmd); + install_element(CONFIG_NODE, &no_ip_pim_keep_alive_cmd); + install_element(CONFIG_NODE, &ip_pim_packets_cmd); + install_element(CONFIG_NODE, &no_ip_pim_packets_cmd); + install_element(CONFIG_NODE, &ip_pim_v6_secondary_cmd); + install_element(CONFIG_NODE, &no_ip_pim_v6_secondary_cmd); + install_element(CONFIG_NODE, &ip_ssmpingd_cmd); + install_element(CONFIG_NODE, &no_ip_ssmpingd_cmd); + install_element(CONFIG_NODE, &ip_msdp_peer_cmd); + install_element(CONFIG_NODE, &no_ip_msdp_peer_cmd); + install_element(CONFIG_NODE, &ip_pim_ecmp_cmd); + install_element(CONFIG_NODE, &no_ip_pim_ecmp_cmd); + install_element(CONFIG_NODE, &ip_pim_ecmp_rebalance_cmd); + install_element(CONFIG_NODE, &no_ip_pim_ecmp_rebalance_cmd); + + install_element(INTERFACE_NODE, &interface_ip_igmp_cmd); + install_element(INTERFACE_NODE, &interface_no_ip_igmp_cmd); + install_element(INTERFACE_NODE, &interface_ip_igmp_join_cmd); + install_element(INTERFACE_NODE, &interface_no_ip_igmp_join_cmd); + install_element(INTERFACE_NODE, &interface_ip_igmp_version_cmd); + install_element(INTERFACE_NODE, &interface_no_ip_igmp_version_cmd); + install_element(INTERFACE_NODE, &interface_ip_igmp_query_interval_cmd); + install_element(INTERFACE_NODE, + &interface_no_ip_igmp_query_interval_cmd); + install_element(INTERFACE_NODE, + &interface_ip_igmp_query_max_response_time_cmd); + install_element(INTERFACE_NODE, + &interface_no_ip_igmp_query_max_response_time_cmd); + install_element(INTERFACE_NODE, + &interface_ip_igmp_query_max_response_time_dsec_cmd); + install_element(INTERFACE_NODE, + &interface_no_ip_igmp_query_max_response_time_dsec_cmd); + install_element(INTERFACE_NODE, &interface_ip_pim_ssm_cmd); + install_element(INTERFACE_NODE, &interface_no_ip_pim_ssm_cmd); + install_element(INTERFACE_NODE, &interface_ip_pim_sm_cmd); + install_element(INTERFACE_NODE, &interface_no_ip_pim_sm_cmd); + install_element(INTERFACE_NODE, &interface_ip_pim_drprio_cmd); + install_element(INTERFACE_NODE, &interface_no_ip_pim_drprio_cmd); + install_element(INTERFACE_NODE, &interface_ip_pim_hello_cmd); + install_element(INTERFACE_NODE, &interface_no_ip_pim_hello_cmd); + + // Static mroutes NEB + install_element(INTERFACE_NODE, &interface_ip_mroute_cmd); + install_element(INTERFACE_NODE, &interface_ip_mroute_source_cmd); + install_element(INTERFACE_NODE, &interface_no_ip_mroute_cmd); + install_element(INTERFACE_NODE, &interface_no_ip_mroute_source_cmd); + + install_element(VIEW_NODE, &show_ip_igmp_interface_cmd); + install_element(VIEW_NODE, &show_ip_igmp_join_cmd); + install_element(VIEW_NODE, &show_ip_igmp_groups_cmd); + install_element(VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd); + install_element(VIEW_NODE, &show_ip_igmp_sources_cmd); + install_element(VIEW_NODE, &show_ip_igmp_sources_retransmissions_cmd); + install_element(VIEW_NODE, &show_ip_pim_assert_cmd); + install_element(VIEW_NODE, &show_ip_pim_assert_internal_cmd); + install_element(VIEW_NODE, &show_ip_pim_assert_metric_cmd); + install_element(VIEW_NODE, &show_ip_pim_assert_winner_metric_cmd); + install_element(VIEW_NODE, &show_ip_pim_interface_traffic_cmd); + install_element(VIEW_NODE, &show_ip_pim_interface_cmd); + install_element(VIEW_NODE, &show_ip_pim_join_cmd); + install_element(VIEW_NODE, &show_ip_pim_local_membership_cmd); + install_element(VIEW_NODE, &show_ip_pim_neighbor_cmd); + install_element(VIEW_NODE, &show_ip_pim_rpf_cmd); + install_element(VIEW_NODE, &show_ip_pim_secondary_cmd); + install_element(VIEW_NODE, &show_ip_pim_state_cmd); + install_element(VIEW_NODE, &show_ip_pim_upstream_cmd); + install_element(VIEW_NODE, &show_ip_pim_upstream_join_desired_cmd); + install_element(VIEW_NODE, &show_ip_pim_upstream_rpf_cmd); + install_element(VIEW_NODE, &show_ip_pim_rp_cmd); + install_element(VIEW_NODE, &show_ip_multicast_cmd); + install_element(VIEW_NODE, &show_ip_mroute_cmd); + install_element(VIEW_NODE, &show_ip_mroute_count_cmd); + install_element(VIEW_NODE, &show_ip_rib_cmd); + install_element(VIEW_NODE, &show_ip_ssmpingd_cmd); + install_element(VIEW_NODE, &show_debugging_pim_cmd); + install_element(VIEW_NODE, &show_ip_pim_nexthop_cmd); + install_element(VIEW_NODE, &show_ip_pim_nexthop_lookup_cmd); + + install_element(ENABLE_NODE, &clear_ip_interfaces_cmd); + install_element(ENABLE_NODE, &clear_ip_igmp_interfaces_cmd); + install_element(ENABLE_NODE, &clear_ip_mroute_cmd); + install_element(ENABLE_NODE, &clear_ip_pim_interfaces_cmd); + install_element(ENABLE_NODE, &clear_ip_pim_interface_traffic_cmd); + install_element(ENABLE_NODE, &clear_ip_pim_oil_cmd); + + install_element(ENABLE_NODE, &debug_igmp_cmd); + install_element(ENABLE_NODE, &no_debug_igmp_cmd); + install_element(ENABLE_NODE, &debug_igmp_events_cmd); + install_element(ENABLE_NODE, &no_debug_igmp_events_cmd); + install_element(ENABLE_NODE, &debug_igmp_packets_cmd); + install_element(ENABLE_NODE, &no_debug_igmp_packets_cmd); + install_element(ENABLE_NODE, &debug_igmp_trace_cmd); + install_element(ENABLE_NODE, &no_debug_igmp_trace_cmd); + install_element(ENABLE_NODE, &debug_mroute_cmd); + install_element(ENABLE_NODE, &debug_mroute_detail_cmd); + install_element(ENABLE_NODE, &no_debug_mroute_cmd); + install_element(ENABLE_NODE, &no_debug_mroute_detail_cmd); + install_element(ENABLE_NODE, &debug_static_cmd); + install_element(ENABLE_NODE, &no_debug_static_cmd); + install_element(ENABLE_NODE, &debug_pim_cmd); + install_element(ENABLE_NODE, &no_debug_pim_cmd); + install_element(ENABLE_NODE, &debug_pim_events_cmd); + install_element(ENABLE_NODE, &no_debug_pim_events_cmd); + install_element(ENABLE_NODE, &debug_pim_packets_cmd); + install_element(ENABLE_NODE, &no_debug_pim_packets_cmd); + install_element(ENABLE_NODE, &debug_pim_packetdump_send_cmd); + install_element(ENABLE_NODE, &no_debug_pim_packetdump_send_cmd); + install_element(ENABLE_NODE, &debug_pim_packetdump_recv_cmd); + install_element(ENABLE_NODE, &no_debug_pim_packetdump_recv_cmd); + install_element(ENABLE_NODE, &debug_pim_trace_cmd); + install_element(ENABLE_NODE, &no_debug_pim_trace_cmd); + install_element(ENABLE_NODE, &debug_ssmpingd_cmd); + install_element(ENABLE_NODE, &no_debug_ssmpingd_cmd); + install_element(ENABLE_NODE, &debug_pim_zebra_cmd); + install_element(ENABLE_NODE, &no_debug_pim_zebra_cmd); + install_element(ENABLE_NODE, &debug_msdp_cmd); + install_element(ENABLE_NODE, &no_debug_msdp_cmd); + install_element(ENABLE_NODE, &undebug_msdp_cmd); + install_element(ENABLE_NODE, &debug_msdp_events_cmd); + install_element(ENABLE_NODE, &no_debug_msdp_events_cmd); + install_element(ENABLE_NODE, &undebug_msdp_events_cmd); + install_element(ENABLE_NODE, &debug_msdp_packets_cmd); + install_element(ENABLE_NODE, &no_debug_msdp_packets_cmd); + install_element(ENABLE_NODE, &undebug_msdp_packets_cmd); + + install_element(CONFIG_NODE, &debug_igmp_cmd); + install_element(CONFIG_NODE, &no_debug_igmp_cmd); + install_element(CONFIG_NODE, &debug_igmp_events_cmd); + install_element(CONFIG_NODE, &no_debug_igmp_events_cmd); + install_element(CONFIG_NODE, &debug_igmp_packets_cmd); + install_element(CONFIG_NODE, &no_debug_igmp_packets_cmd); + install_element(CONFIG_NODE, &debug_igmp_trace_cmd); + install_element(CONFIG_NODE, &no_debug_igmp_trace_cmd); + install_element(CONFIG_NODE, &debug_mroute_cmd); + install_element(CONFIG_NODE, &debug_mroute_detail_cmd); + install_element(CONFIG_NODE, &no_debug_mroute_cmd); + install_element(CONFIG_NODE, &no_debug_mroute_detail_cmd); + install_element(CONFIG_NODE, &debug_static_cmd); + install_element(CONFIG_NODE, &no_debug_static_cmd); + install_element(CONFIG_NODE, &debug_pim_cmd); + install_element(CONFIG_NODE, &no_debug_pim_cmd); + install_element(CONFIG_NODE, &debug_pim_events_cmd); + install_element(CONFIG_NODE, &no_debug_pim_events_cmd); + install_element(CONFIG_NODE, &debug_pim_packets_cmd); + install_element(CONFIG_NODE, &no_debug_pim_packets_cmd); + install_element(CONFIG_NODE, &debug_pim_trace_cmd); + install_element(CONFIG_NODE, &no_debug_pim_trace_cmd); + install_element(CONFIG_NODE, &debug_ssmpingd_cmd); + install_element(CONFIG_NODE, &no_debug_ssmpingd_cmd); + install_element(CONFIG_NODE, &debug_pim_zebra_cmd); + install_element(CONFIG_NODE, &no_debug_pim_zebra_cmd); + install_element(CONFIG_NODE, &debug_msdp_cmd); + install_element(CONFIG_NODE, &no_debug_msdp_cmd); + install_element(CONFIG_NODE, &undebug_msdp_cmd); + install_element(CONFIG_NODE, &debug_msdp_events_cmd); + install_element(CONFIG_NODE, &no_debug_msdp_events_cmd); + install_element(CONFIG_NODE, &undebug_msdp_events_cmd); + install_element(CONFIG_NODE, &debug_msdp_packets_cmd); + install_element(CONFIG_NODE, &no_debug_msdp_packets_cmd); + install_element(CONFIG_NODE, &undebug_msdp_packets_cmd); + install_element(CONFIG_NODE, &ip_msdp_mesh_group_member_cmd); + install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_member_cmd); + install_element(CONFIG_NODE, &ip_msdp_mesh_group_source_cmd); + install_element(CONFIG_NODE, &no_ip_msdp_mesh_group_source_cmd); + install_element(VIEW_NODE, &show_ip_msdp_peer_detail_cmd); + install_element(VIEW_NODE, &show_ip_msdp_sa_detail_cmd); + install_element(VIEW_NODE, &show_ip_msdp_sa_sg_cmd); + install_element(VIEW_NODE, &show_ip_msdp_mesh_group_cmd); + install_element(VIEW_NODE, &show_ip_pim_ssm_range_cmd); + install_element(VIEW_NODE, &show_ip_pim_group_type_cmd); + install_element(INTERFACE_NODE, &interface_pim_use_source_cmd); + install_element(INTERFACE_NODE, &interface_no_pim_use_source_cmd); + /* Install BFD command */ + install_element(INTERFACE_NODE, &ip_pim_bfd_cmd); + install_element(INTERFACE_NODE, &ip_pim_bfd_param_cmd); + install_element(INTERFACE_NODE, &no_ip_pim_bfd_cmd); + install_element(INTERFACE_NODE, &no_ip_pim_bfd_param_cmd); } diff --git a/pimd/pim_hello.c b/pimd/pim_hello.c index 0c08cfa46..2592514f3 100644 --- a/pimd/pim_hello.c +++ b/pimd/pim_hello.c @@ -32,71 +32,66 @@ #include "pim_neighbor.h" #include "pim_upstream.h" -static void on_trace(const char *label, - struct interface *ifp, struct in_addr src) +static void on_trace(const char *label, struct interface *ifp, + struct in_addr src) { - if (PIM_DEBUG_PIM_TRACE) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src, src_str, sizeof(src_str)); - zlog_debug("%s: from %s on %s", - label, src_str, ifp->name); - } + if (PIM_DEBUG_PIM_TRACE) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src, src_str, sizeof(src_str)); + zlog_debug("%s: from %s on %s", label, src_str, ifp->name); + } } static void tlv_trace_bool(const char *label, const char *tlv_name, const char *ifname, struct in_addr src_addr, int isset, int value) { - if (isset) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: PIM hello option from %s on interface %s: %s=%d", - label, - src_str, ifname, - tlv_name, value); - } + if (isset) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); + zlog_debug( + "%s: PIM hello option from %s on interface %s: %s=%d", + label, src_str, ifname, tlv_name, value); + } } static void tlv_trace_uint16(const char *label, const char *tlv_name, const char *ifname, struct in_addr src_addr, int isset, uint16_t value) { - if (isset) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: PIM hello option from %s on interface %s: %s=%u", - label, - src_str, ifname, - tlv_name, value); - } + if (isset) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); + zlog_debug( + "%s: PIM hello option from %s on interface %s: %s=%u", + label, src_str, ifname, tlv_name, value); + } } static void tlv_trace_uint32(const char *label, const char *tlv_name, const char *ifname, struct in_addr src_addr, int isset, uint32_t value) { - if (isset) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: PIM hello option from %s on interface %s: %s=%u", - label, - src_str, ifname, - tlv_name, value); - } + if (isset) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); + zlog_debug( + "%s: PIM hello option from %s on interface %s: %s=%u", + label, src_str, ifname, tlv_name, value); + } } static void tlv_trace_uint32_hex(const char *label, const char *tlv_name, const char *ifname, struct in_addr src_addr, int isset, uint32_t value) { - if (isset) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: PIM hello option from %s on interface %s: %s=%08x", - label, - src_str, ifname, - tlv_name, value); - } + if (isset) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); + zlog_debug( + "%s: PIM hello option from %s on interface %s: %s=%08x", + label, src_str, ifname, tlv_name, value); + } } #if 0 @@ -119,418 +114,423 @@ static void tlv_trace_list(const char *label, const char *tlv_name, const char *ifname, struct in_addr src_addr, int isset, struct list *addr_list) { - if (isset) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: PIM hello option from %s on interface %s: %s size=%d list=%p", - label, - src_str, ifname, - tlv_name, - addr_list ? ((int) listcount(addr_list)) : -1, - (void *) addr_list); - } + if (isset) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); + zlog_debug( + "%s: PIM hello option from %s on interface %s: %s size=%d list=%p", + label, src_str, ifname, tlv_name, + addr_list ? ((int)listcount(addr_list)) : -1, + (void *)addr_list); + } } -#define FREE_ADDR_LIST \ - if (hello_option_addr_list) { \ - list_delete(hello_option_addr_list); \ - } +#define FREE_ADDR_LIST \ + if (hello_option_addr_list) { \ + list_delete(hello_option_addr_list); \ + } -#define FREE_ADDR_LIST_THEN_RETURN(code) \ -{ \ - FREE_ADDR_LIST \ - return (code); \ -} +#define FREE_ADDR_LIST_THEN_RETURN(code) \ + { \ + FREE_ADDR_LIST \ + return (code); \ + } -int pim_hello_recv(struct interface *ifp, - struct in_addr src_addr, +int pim_hello_recv(struct interface *ifp, struct in_addr src_addr, uint8_t *tlv_buf, int tlv_buf_size) { - struct pim_interface *pim_ifp; - struct pim_neighbor *neigh; - uint8_t *tlv_curr; - uint8_t *tlv_pastend; - pim_hello_options hello_options = 0; /* bit array recording options found */ - uint16_t hello_option_holdtime = 0; - uint16_t hello_option_propagation_delay = 0; - uint16_t hello_option_override_interval = 0; - uint32_t hello_option_dr_priority = 0; - uint32_t hello_option_generation_id = 0; - struct list *hello_option_addr_list = 0; - - if (PIM_DEBUG_PIM_HELLO) - on_trace(__PRETTY_FUNCTION__, ifp, src_addr); - - pim_ifp = ifp->info; - zassert(pim_ifp); - - ++pim_ifp->pim_ifstat_hello_recv; - - /* - Parse PIM hello TLVs - */ - zassert(tlv_buf_size >= 0); - tlv_curr = tlv_buf; - tlv_pastend = tlv_buf + tlv_buf_size; - - while (tlv_curr < tlv_pastend) { - uint16_t option_type; - uint16_t option_len; - int remain = tlv_pastend - tlv_curr; - - if (remain < PIM_TLV_MIN_SIZE) { - if (PIM_DEBUG_PIM_HELLO) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: short PIM hello TLV size=%d < min=%d from %s on interface %s", - __PRETTY_FUNCTION__, - remain, PIM_TLV_MIN_SIZE, - src_str, ifp->name); - } - FREE_ADDR_LIST_THEN_RETURN(-1); - } - - option_type = PIM_TLV_GET_TYPE(tlv_curr); - tlv_curr += PIM_TLV_TYPE_SIZE; - option_len = PIM_TLV_GET_LENGTH(tlv_curr); - tlv_curr += PIM_TLV_LENGTH_SIZE; - - if ((tlv_curr + option_len) > tlv_pastend) { - if (PIM_DEBUG_PIM_HELLO) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: long PIM hello TLV type=%d length=%d > left=%td from %s on interface %s", - __PRETTY_FUNCTION__, - option_type, option_len, tlv_pastend - tlv_curr, - src_str, ifp->name); - } - FREE_ADDR_LIST_THEN_RETURN(-2); - } - - if (PIM_DEBUG_PIM_HELLO) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: parse left_size=%d: PIM hello TLV type=%d length=%d from %s on %s", - __PRETTY_FUNCTION__, - remain, - option_type, option_len, - src_str, ifp->name); - } - - switch (option_type) { - case PIM_MSG_OPTION_TYPE_HOLDTIME: - if (pim_tlv_parse_holdtime(ifp->name, src_addr, - &hello_options, - &hello_option_holdtime, - option_len, - tlv_curr)) { - FREE_ADDR_LIST_THEN_RETURN(-3); - } - break; - case PIM_MSG_OPTION_TYPE_LAN_PRUNE_DELAY: - if (pim_tlv_parse_lan_prune_delay(ifp->name, src_addr, - &hello_options, - &hello_option_propagation_delay, - &hello_option_override_interval, - option_len, - tlv_curr)) { - FREE_ADDR_LIST_THEN_RETURN(-4); - } - break; - case PIM_MSG_OPTION_TYPE_DR_PRIORITY: - if (pim_tlv_parse_dr_priority(ifp->name, src_addr, - &hello_options, - &hello_option_dr_priority, - option_len, + struct pim_interface *pim_ifp; + struct pim_neighbor *neigh; + uint8_t *tlv_curr; + uint8_t *tlv_pastend; + pim_hello_options hello_options = + 0; /* bit array recording options found */ + uint16_t hello_option_holdtime = 0; + uint16_t hello_option_propagation_delay = 0; + uint16_t hello_option_override_interval = 0; + uint32_t hello_option_dr_priority = 0; + uint32_t hello_option_generation_id = 0; + struct list *hello_option_addr_list = 0; + + if (PIM_DEBUG_PIM_HELLO) + on_trace(__PRETTY_FUNCTION__, ifp, src_addr); + + pim_ifp = ifp->info; + zassert(pim_ifp); + + ++pim_ifp->pim_ifstat_hello_recv; + + /* + Parse PIM hello TLVs + */ + zassert(tlv_buf_size >= 0); + tlv_curr = tlv_buf; + tlv_pastend = tlv_buf + tlv_buf_size; + + while (tlv_curr < tlv_pastend) { + uint16_t option_type; + uint16_t option_len; + int remain = tlv_pastend - tlv_curr; + + if (remain < PIM_TLV_MIN_SIZE) { + if (PIM_DEBUG_PIM_HELLO) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, + sizeof(src_str)); + zlog_debug( + "%s: short PIM hello TLV size=%d < min=%d from %s on interface %s", + __PRETTY_FUNCTION__, remain, + PIM_TLV_MIN_SIZE, src_str, ifp->name); + } + FREE_ADDR_LIST_THEN_RETURN(-1); + } + + option_type = PIM_TLV_GET_TYPE(tlv_curr); + tlv_curr += PIM_TLV_TYPE_SIZE; + option_len = PIM_TLV_GET_LENGTH(tlv_curr); + tlv_curr += PIM_TLV_LENGTH_SIZE; + + if ((tlv_curr + option_len) > tlv_pastend) { + if (PIM_DEBUG_PIM_HELLO) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, + sizeof(src_str)); + zlog_debug( + "%s: long PIM hello TLV type=%d length=%d > left=%td from %s on interface %s", + __PRETTY_FUNCTION__, option_type, + option_len, tlv_pastend - tlv_curr, + src_str, ifp->name); + } + FREE_ADDR_LIST_THEN_RETURN(-2); + } + + if (PIM_DEBUG_PIM_HELLO) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, + sizeof(src_str)); + zlog_debug( + "%s: parse left_size=%d: PIM hello TLV type=%d length=%d from %s on %s", + __PRETTY_FUNCTION__, remain, option_type, + option_len, src_str, ifp->name); + } + + switch (option_type) { + case PIM_MSG_OPTION_TYPE_HOLDTIME: + if (pim_tlv_parse_holdtime(ifp->name, src_addr, + &hello_options, + &hello_option_holdtime, + option_len, tlv_curr)) { + FREE_ADDR_LIST_THEN_RETURN(-3); + } + break; + case PIM_MSG_OPTION_TYPE_LAN_PRUNE_DELAY: + if (pim_tlv_parse_lan_prune_delay( + ifp->name, src_addr, &hello_options, + &hello_option_propagation_delay, + &hello_option_override_interval, option_len, tlv_curr)) { - FREE_ADDR_LIST_THEN_RETURN(-5); - } - break; - case PIM_MSG_OPTION_TYPE_GENERATION_ID: - if (pim_tlv_parse_generation_id(ifp->name, src_addr, - &hello_options, - &hello_option_generation_id, - option_len, - tlv_curr)) { - FREE_ADDR_LIST_THEN_RETURN(-6); - } - break; - case PIM_MSG_OPTION_TYPE_ADDRESS_LIST: - if (pim_tlv_parse_addr_list(ifp->name, src_addr, - &hello_options, - &hello_option_addr_list, - option_len, - tlv_curr)) { - return -7; - } - break; - case PIM_MSG_OPTION_TYPE_DM_STATE_REFRESH: - if (PIM_DEBUG_PIM_HELLO) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: ignoring PIM hello dense-mode state refresh TLV option type=%d length=%d from %s on interface %s", - __PRETTY_FUNCTION__, - option_type, option_len, - src_str, ifp->name); - } - break; - default: - if (PIM_DEBUG_PIM_HELLO) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: ignoring unknown PIM hello TLV type=%d length=%d from %s on interface %s", - __PRETTY_FUNCTION__, - option_type, option_len, - src_str, ifp->name); - } - } - - tlv_curr += option_len; - } + FREE_ADDR_LIST_THEN_RETURN(-4); + } + break; + case PIM_MSG_OPTION_TYPE_DR_PRIORITY: + if (pim_tlv_parse_dr_priority(ifp->name, src_addr, + &hello_options, + &hello_option_dr_priority, + option_len, tlv_curr)) { + FREE_ADDR_LIST_THEN_RETURN(-5); + } + break; + case PIM_MSG_OPTION_TYPE_GENERATION_ID: + if (pim_tlv_parse_generation_id( + ifp->name, src_addr, &hello_options, + &hello_option_generation_id, option_len, + tlv_curr)) { + FREE_ADDR_LIST_THEN_RETURN(-6); + } + break; + case PIM_MSG_OPTION_TYPE_ADDRESS_LIST: + if (pim_tlv_parse_addr_list(ifp->name, src_addr, + &hello_options, + &hello_option_addr_list, + option_len, tlv_curr)) { + return -7; + } + break; + case PIM_MSG_OPTION_TYPE_DM_STATE_REFRESH: + if (PIM_DEBUG_PIM_HELLO) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, + sizeof(src_str)); + zlog_debug( + "%s: ignoring PIM hello dense-mode state refresh TLV option type=%d length=%d from %s on interface %s", + __PRETTY_FUNCTION__, option_type, + option_len, src_str, ifp->name); + } + break; + default: + if (PIM_DEBUG_PIM_HELLO) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, + sizeof(src_str)); + zlog_debug( + "%s: ignoring unknown PIM hello TLV type=%d length=%d from %s on interface %s", + __PRETTY_FUNCTION__, option_type, + option_len, src_str, ifp->name); + } + } + + tlv_curr += option_len; + } - /* - Check received PIM hello options - */ - - if (PIM_DEBUG_PIM_HELLO) { - tlv_trace_uint16(__PRETTY_FUNCTION__, "holdtime", - ifp->name, src_addr, - PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME), - hello_option_holdtime); - tlv_trace_uint16(__PRETTY_FUNCTION__, "propagation_delay", - ifp->name, src_addr, - PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY), - hello_option_propagation_delay); - tlv_trace_uint16(__PRETTY_FUNCTION__, "override_interval", - ifp->name, src_addr, - PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY), - hello_option_override_interval); - tlv_trace_bool(__PRETTY_FUNCTION__, "can_disable_join_suppression", - ifp->name, src_addr, - PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY), - PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION)); - tlv_trace_uint32(__PRETTY_FUNCTION__, "dr_priority", - ifp->name, src_addr, - PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_DR_PRIORITY), - hello_option_dr_priority); - tlv_trace_uint32_hex(__PRETTY_FUNCTION__, "generation_id", - ifp->name, src_addr, - PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_GENERATION_ID), - hello_option_generation_id); - tlv_trace_list(__PRETTY_FUNCTION__, "address_list", - ifp->name, src_addr, - PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_ADDRESS_LIST), - hello_option_addr_list); - } + /* + Check received PIM hello options + */ - if (!PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) { - if (PIM_DEBUG_PIM_HELLO) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: PIM hello missing holdtime from %s on interface %s", - __PRETTY_FUNCTION__, - src_str, ifp->name); - } - } + if (PIM_DEBUG_PIM_HELLO) { + tlv_trace_uint16(__PRETTY_FUNCTION__, "holdtime", ifp->name, + src_addr, + PIM_OPTION_IS_SET(hello_options, + PIM_OPTION_MASK_HOLDTIME), + hello_option_holdtime); + tlv_trace_uint16( + __PRETTY_FUNCTION__, "propagation_delay", ifp->name, + src_addr, + PIM_OPTION_IS_SET(hello_options, + PIM_OPTION_MASK_LAN_PRUNE_DELAY), + hello_option_propagation_delay); + tlv_trace_uint16( + __PRETTY_FUNCTION__, "override_interval", ifp->name, + src_addr, + PIM_OPTION_IS_SET(hello_options, + PIM_OPTION_MASK_LAN_PRUNE_DELAY), + hello_option_override_interval); + tlv_trace_bool( + __PRETTY_FUNCTION__, "can_disable_join_suppression", + ifp->name, src_addr, + PIM_OPTION_IS_SET(hello_options, + PIM_OPTION_MASK_LAN_PRUNE_DELAY), + PIM_OPTION_IS_SET( + hello_options, + PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION)); + tlv_trace_uint32(__PRETTY_FUNCTION__, "dr_priority", ifp->name, + src_addr, + PIM_OPTION_IS_SET(hello_options, + PIM_OPTION_MASK_DR_PRIORITY), + hello_option_dr_priority); + tlv_trace_uint32_hex( + __PRETTY_FUNCTION__, "generation_id", ifp->name, + src_addr, + PIM_OPTION_IS_SET(hello_options, + PIM_OPTION_MASK_GENERATION_ID), + hello_option_generation_id); + tlv_trace_list(__PRETTY_FUNCTION__, "address_list", ifp->name, + src_addr, + PIM_OPTION_IS_SET(hello_options, + PIM_OPTION_MASK_ADDRESS_LIST), + hello_option_addr_list); + } - /* - New neighbor? - */ - - neigh = pim_neighbor_find(ifp, src_addr); - if (!neigh) { - /* Add as new neighbor */ - - neigh = pim_neighbor_add(ifp, src_addr, - hello_options, - hello_option_holdtime, - hello_option_propagation_delay, - hello_option_override_interval, - hello_option_dr_priority, - hello_option_generation_id, - hello_option_addr_list, - PIM_NEIGHBOR_SEND_DELAY); - if (!neigh) { - if (PIM_DEBUG_PIM_HELLO) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: failure creating PIM neighbor %s on interface %s", - __PRETTY_FUNCTION__, - src_str, ifp->name); - } - FREE_ADDR_LIST_THEN_RETURN(-8); - } - - /* actual addr list has been saved under neighbor */ - return 0; - } + if (!PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) { + if (PIM_DEBUG_PIM_HELLO) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, + sizeof(src_str)); + zlog_debug( + "%s: PIM hello missing holdtime from %s on interface %s", + __PRETTY_FUNCTION__, src_str, ifp->name); + } + } - /* - Received generation ID ? - */ - - if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_GENERATION_ID)) { - /* GenID mismatch ? */ - if (!PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_GENERATION_ID) || - (hello_option_generation_id != neigh->generation_id)) { - /* GenID mismatch, then replace neighbor */ - - if (PIM_DEBUG_PIM_HELLO) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: GenId mismatch new=%08x old=%08x: replacing neighbor %s on %s", - __PRETTY_FUNCTION__, - hello_option_generation_id, - neigh->generation_id, - src_str, ifp->name); - } - - pim_upstream_rpf_genid_changed(neigh->source_addr); - - pim_neighbor_delete(ifp, neigh, "GenID mismatch"); - neigh = pim_neighbor_add(ifp, src_addr, - hello_options, - hello_option_holdtime, - hello_option_propagation_delay, - hello_option_override_interval, - hello_option_dr_priority, - hello_option_generation_id, - hello_option_addr_list, - PIM_NEIGHBOR_SEND_NOW); - if (!neigh) { - if (PIM_DEBUG_PIM_HELLO) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: failure re-creating PIM neighbor %s on interface %s", - __PRETTY_FUNCTION__, - src_str, ifp->name); + /* + New neighbor? + */ + + neigh = pim_neighbor_find(ifp, src_addr); + if (!neigh) { + /* Add as new neighbor */ + + neigh = pim_neighbor_add( + ifp, src_addr, hello_options, hello_option_holdtime, + hello_option_propagation_delay, + hello_option_override_interval, + hello_option_dr_priority, hello_option_generation_id, + hello_option_addr_list, PIM_NEIGHBOR_SEND_DELAY); + if (!neigh) { + if (PIM_DEBUG_PIM_HELLO) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, + sizeof(src_str)); + zlog_warn( + "%s: failure creating PIM neighbor %s on interface %s", + __PRETTY_FUNCTION__, src_str, + ifp->name); + } + FREE_ADDR_LIST_THEN_RETURN(-8); + } + + /* actual addr list has been saved under neighbor */ + return 0; } - FREE_ADDR_LIST_THEN_RETURN(-9); - } - /* actual addr list is saved under neighbor */ - return 0; - - } /* GenId mismatch: replace neighbor */ - - } /* GenId received */ - - /* - Update existing neighbor - */ - - pim_neighbor_update(neigh, - hello_options, - hello_option_holdtime, - hello_option_dr_priority, - hello_option_addr_list); - /* actual addr list is saved under neighbor */ - return 0; + + /* + Received generation ID ? + */ + + if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_GENERATION_ID)) { + /* GenID mismatch ? */ + if (!PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_GENERATION_ID) + || (hello_option_generation_id != neigh->generation_id)) { + /* GenID mismatch, then replace neighbor */ + + if (PIM_DEBUG_PIM_HELLO) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, + sizeof(src_str)); + zlog_debug( + "%s: GenId mismatch new=%08x old=%08x: replacing neighbor %s on %s", + __PRETTY_FUNCTION__, + hello_option_generation_id, + neigh->generation_id, src_str, + ifp->name); + } + + pim_upstream_rpf_genid_changed(neigh->source_addr); + + pim_neighbor_delete(ifp, neigh, "GenID mismatch"); + neigh = pim_neighbor_add(ifp, src_addr, hello_options, + hello_option_holdtime, + hello_option_propagation_delay, + hello_option_override_interval, + hello_option_dr_priority, + hello_option_generation_id, + hello_option_addr_list, + PIM_NEIGHBOR_SEND_NOW); + if (!neigh) { + if (PIM_DEBUG_PIM_HELLO) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, + src_str, + sizeof(src_str)); + zlog_debug( + "%s: failure re-creating PIM neighbor %s on interface %s", + __PRETTY_FUNCTION__, src_str, + ifp->name); + } + FREE_ADDR_LIST_THEN_RETURN(-9); + } + /* actual addr list is saved under neighbor */ + return 0; + + } /* GenId mismatch: replace neighbor */ + + } /* GenId received */ + + /* + Update existing neighbor + */ + + pim_neighbor_update(neigh, hello_options, hello_option_holdtime, + hello_option_dr_priority, hello_option_addr_list); + /* actual addr list is saved under neighbor */ + return 0; } -int pim_hello_build_tlv(struct interface *ifp, - uint8_t *tlv_buf, int tlv_buf_size, - uint16_t holdtime, - uint32_t dr_priority, - uint32_t generation_id, - uint16_t propagation_delay, - uint16_t override_interval, +int pim_hello_build_tlv(struct interface *ifp, uint8_t *tlv_buf, + int tlv_buf_size, uint16_t holdtime, + uint32_t dr_priority, uint32_t generation_id, + uint16_t propagation_delay, uint16_t override_interval, int can_disable_join_suppression) { - uint8_t *curr = tlv_buf; - uint8_t *pastend = tlv_buf + tlv_buf_size; - uint8_t *tmp; - - /* - * Append options - */ - - /* Holdtime */ - curr = pim_tlv_append_uint16(curr, - pastend, - PIM_MSG_OPTION_TYPE_HOLDTIME, - holdtime); - if (!curr) { - if (PIM_DEBUG_PIM_HELLO) { - zlog_debug("%s: could not set PIM hello Holdtime option for interface %s", - __PRETTY_FUNCTION__, ifp->name); - } - return -1; - } + uint8_t *curr = tlv_buf; + uint8_t *pastend = tlv_buf + tlv_buf_size; + uint8_t *tmp; + + /* + * Append options + */ + + /* Holdtime */ + curr = pim_tlv_append_uint16(curr, pastend, + PIM_MSG_OPTION_TYPE_HOLDTIME, holdtime); + if (!curr) { + if (PIM_DEBUG_PIM_HELLO) { + zlog_debug( + "%s: could not set PIM hello Holdtime option for interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + return -1; + } - /* LAN Prune Delay */ - tmp = pim_tlv_append_2uint16(curr, - pastend, - PIM_MSG_OPTION_TYPE_LAN_PRUNE_DELAY, - propagation_delay, - override_interval); - if (!tmp) { - if (PIM_DEBUG_PIM_HELLO) { - zlog_debug("%s: could not set PIM LAN Prune Delay option for interface %s", - __PRETTY_FUNCTION__, ifp->name); - } - return -1; - } - if (can_disable_join_suppression) { - *((uint8_t*)(curr) + 4) |= 0x80; /* enable T bit */ - } - curr = tmp; - - /* DR Priority */ - curr = pim_tlv_append_uint32(curr, - pastend, - PIM_MSG_OPTION_TYPE_DR_PRIORITY, - dr_priority); - if (!curr) { - if (PIM_DEBUG_PIM_HELLO) { - zlog_debug("%s: could not set PIM hello DR Priority option for interface %s", - __PRETTY_FUNCTION__, ifp->name); - } - return -2; - } + /* LAN Prune Delay */ + tmp = pim_tlv_append_2uint16(curr, pastend, + PIM_MSG_OPTION_TYPE_LAN_PRUNE_DELAY, + propagation_delay, override_interval); + if (!tmp) { + if (PIM_DEBUG_PIM_HELLO) { + zlog_debug( + "%s: could not set PIM LAN Prune Delay option for interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + return -1; + } + if (can_disable_join_suppression) { + *((uint8_t *)(curr) + 4) |= 0x80; /* enable T bit */ + } + curr = tmp; + + /* DR Priority */ + curr = pim_tlv_append_uint32( + curr, pastend, PIM_MSG_OPTION_TYPE_DR_PRIORITY, dr_priority); + if (!curr) { + if (PIM_DEBUG_PIM_HELLO) { + zlog_debug( + "%s: could not set PIM hello DR Priority option for interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + return -2; + } - /* Generation ID */ - curr = pim_tlv_append_uint32(curr, - pastend, - PIM_MSG_OPTION_TYPE_GENERATION_ID, - generation_id); - if (!curr) { - if (PIM_DEBUG_PIM_HELLO) { - zlog_debug("%s: could not set PIM hello Generation ID option for interface %s", - __PRETTY_FUNCTION__, ifp->name); - } - return -3; - } + /* Generation ID */ + curr = pim_tlv_append_uint32(curr, pastend, + PIM_MSG_OPTION_TYPE_GENERATION_ID, + generation_id); + if (!curr) { + if (PIM_DEBUG_PIM_HELLO) { + zlog_debug( + "%s: could not set PIM hello Generation ID option for interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + return -3; + } - /* Secondary Address List */ - if (ifp->connected->count) { - curr = pim_tlv_append_addrlist_ucast(curr, - pastend, - ifp->connected, - AF_INET); - if (!curr) { - if (PIM_DEBUG_PIM_HELLO) { - zlog_debug("%s: could not set PIM hello v4 Secondary Address List option for interface %s", - __PRETTY_FUNCTION__, ifp->name); - } - return -4; - } - if (pimg->send_v6_secondary) - { - curr = pim_tlv_append_addrlist_ucast(curr, - pastend, - ifp->connected, - AF_INET6); - if (!curr) { - if (PIM_DEBUG_PIM_HELLO) { - zlog_debug("%s: could not sent PIM hello v6 secondary Address List option for interface %s", - __PRETTY_FUNCTION__, ifp->name); - } - return -4; - } - } - } + /* Secondary Address List */ + if (ifp->connected->count) { + curr = pim_tlv_append_addrlist_ucast(curr, pastend, + ifp->connected, AF_INET); + if (!curr) { + if (PIM_DEBUG_PIM_HELLO) { + zlog_debug( + "%s: could not set PIM hello v4 Secondary Address List option for interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + return -4; + } + if (pimg->send_v6_secondary) { + curr = pim_tlv_append_addrlist_ucast( + curr, pastend, ifp->connected, AF_INET6); + if (!curr) { + if (PIM_DEBUG_PIM_HELLO) { + zlog_debug( + "%s: could not sent PIM hello v6 secondary Address List option for interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + return -4; + } + } + } - return curr - tlv_buf; + return curr - tlv_buf; } /* @@ -544,16 +544,16 @@ int pim_hello_build_tlv(struct interface *ifp, */ void pim_hello_require(struct interface *ifp) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - zassert(ifp); + zassert(ifp); - pim_ifp = ifp->info; + pim_ifp = ifp->info; - zassert(pim_ifp); + zassert(pim_ifp); - if (pim_ifp->pim_ifstat_hello_sent) - return; + if (pim_ifp->pim_ifstat_hello_sent) + return; - pim_hello_restart_now(ifp); /* Send hello and restart timer */ + pim_hello_restart_now(ifp); /* Send hello and restart timer */ } diff --git a/pimd/pim_hello.h b/pimd/pim_hello.h index ff799b20f..df41f97d9 100644 --- a/pimd/pim_hello.h +++ b/pimd/pim_hello.h @@ -24,17 +24,13 @@ #include "if.h" -int pim_hello_recv(struct interface *ifp, - struct in_addr src_addr, +int pim_hello_recv(struct interface *ifp, struct in_addr src_addr, uint8_t *tlv_buf, int tlv_buf_size); -int pim_hello_build_tlv(struct interface *ifp, - uint8_t *tlv_buf, int tlv_buf_size, - uint16_t holdtime, - uint32_t dr_priority, - uint32_t generation_id, - uint16_t propagation_delay, - uint16_t override_interval, +int pim_hello_build_tlv(struct interface *ifp, uint8_t *tlv_buf, + int tlv_buf_size, uint16_t holdtime, + uint32_t dr_priority, uint32_t generation_id, + uint16_t propagation_delay, uint16_t override_interval, int can_disable_join_suppression); void pim_hello_require(struct interface *ifp); diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index f4125af9b..820162524 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -50,907 +50,919 @@ static int pim_iface_vif_index[MAXVIFS]; static void pim_if_igmp_join_del_all(struct interface *ifp); static int igmp_join_sock(const char *ifname, ifindex_t ifindex, - struct in_addr group_addr, struct in_addr source_addr); + struct in_addr group_addr, + struct in_addr source_addr); -void -pim_if_init (void) +void pim_if_init(void) { - int i; + int i; - for (i = 0; i < MAXVIFS; i++) - pim_iface_vif_index[i] = 0; + for (i = 0; i < MAXVIFS; i++) + pim_iface_vif_index[i] = 0; - pim_ifchannel_list = list_new(); - pim_ifchannel_list->cmp = (int (*)(void *, void *))pim_ifchannel_compare; + pim_ifchannel_list = list_new(); + pim_ifchannel_list->cmp = + (int (*)(void *, void *))pim_ifchannel_compare; } -void -pim_if_terminate (void) +void pim_if_terminate(void) { - if (pim_ifchannel_list) - list_free (pim_ifchannel_list); + if (pim_ifchannel_list) + list_free(pim_ifchannel_list); } static void *if_list_clean(struct pim_interface *pim_ifp) { - if (pim_ifp->igmp_join_list) { - list_delete(pim_ifp->igmp_join_list); - } + if (pim_ifp->igmp_join_list) { + list_delete(pim_ifp->igmp_join_list); + } - if (pim_ifp->igmp_socket_list) { - list_delete(pim_ifp->igmp_socket_list); - } + if (pim_ifp->igmp_socket_list) { + list_delete(pim_ifp->igmp_socket_list); + } - if (pim_ifp->pim_neighbor_list) { - list_delete(pim_ifp->pim_neighbor_list); - } + if (pim_ifp->pim_neighbor_list) { + list_delete(pim_ifp->pim_neighbor_list); + } - if (pim_ifp->upstream_switch_list) - list_delete(pim_ifp->upstream_switch_list); + if (pim_ifp->upstream_switch_list) + list_delete(pim_ifp->upstream_switch_list); - if (pim_ifp->pim_ifchannel_list) { - list_delete(pim_ifp->pim_ifchannel_list); - } + if (pim_ifp->pim_ifchannel_list) { + list_delete(pim_ifp->pim_ifchannel_list); + } - if (pim_ifp->pim_ifchannel_hash) - hash_free(pim_ifp->pim_ifchannel_hash); + if (pim_ifp->pim_ifchannel_hash) + hash_free(pim_ifp->pim_ifchannel_hash); - XFREE(MTYPE_PIM_INTERFACE, pim_ifp); + XFREE(MTYPE_PIM_INTERFACE, pim_ifp); - return 0; + return 0; } struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim) { - struct pim_interface *pim_ifp; - - zassert(ifp); - zassert(!ifp->info); - - pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp)); - if (!pim_ifp) { - zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_ifp)); - return 0; - } - - pim_ifp->options = 0; - pim_ifp->mroute_vif_index = -1; - - pim_ifp->igmp_version = IGMP_DEFAULT_VERSION; - pim_ifp->igmp_default_robustness_variable = IGMP_DEFAULT_ROBUSTNESS_VARIABLE; - pim_ifp->igmp_default_query_interval = IGMP_GENERAL_QUERY_INTERVAL; - pim_ifp->igmp_query_max_response_time_dsec = IGMP_QUERY_MAX_RESPONSE_TIME_DSEC; - pim_ifp->igmp_specific_query_max_response_time_dsec = IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC; - - /* - RFC 3376: 8.3. Query Response Interval - The number of seconds represented by the [Query Response Interval] - must be less than the [Query Interval]. - */ - zassert(pim_ifp->igmp_query_max_response_time_dsec < pim_ifp->igmp_default_query_interval); - - if (pim) - PIM_IF_DO_PIM(pim_ifp->options); - if (igmp) - PIM_IF_DO_IGMP(pim_ifp->options); - - PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp->options); - - pim_ifp->igmp_join_list = NULL; - pim_ifp->igmp_socket_list = NULL; - pim_ifp->pim_neighbor_list = NULL; - pim_ifp->upstream_switch_list = NULL; - pim_ifp->pim_ifchannel_list = NULL; - pim_ifp->pim_ifchannel_hash = NULL; - pim_ifp->pim_generation_id = 0; - - /* list of struct igmp_sock */ - pim_ifp->igmp_socket_list = list_new(); - if (!pim_ifp->igmp_socket_list) { - zlog_err("%s %s: failure: igmp_socket_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return if_list_clean(pim_ifp); - } - pim_ifp->igmp_socket_list->del = (void (*)(void *)) igmp_sock_free; - - /* list of struct pim_neighbor */ - pim_ifp->pim_neighbor_list = list_new(); - if (!pim_ifp->pim_neighbor_list) { - zlog_err("%s %s: failure: pim_neighbor_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return if_list_clean(pim_ifp); - } - pim_ifp->pim_neighbor_list->del = (void (*)(void *)) pim_neighbor_free; - - pim_ifp->upstream_switch_list = list_new(); - if (!pim_ifp->upstream_switch_list) { - zlog_err("%s %s: failure: upstream_switch_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return if_list_clean(pim_ifp); - } - - /* list of struct pim_ifchannel */ - pim_ifp->pim_ifchannel_list = list_new(); - if (!pim_ifp->pim_ifchannel_list) { - zlog_err("%s %s: failure: pim_ifchannel_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return if_list_clean(pim_ifp); - } - pim_ifp->pim_ifchannel_list->del = (void (*)(void *)) pim_ifchannel_free; - pim_ifp->pim_ifchannel_list->cmp = (int (*)(void *, void *)) pim_ifchannel_compare; - - pim_ifp->pim_ifchannel_hash = hash_create (pim_ifchannel_hash_key, - pim_ifchannel_equal, NULL); - - ifp->info = pim_ifp; - - pim_sock_reset(ifp); - - pim_if_add_vif(ifp); - - return pim_ifp; + struct pim_interface *pim_ifp; + + zassert(ifp); + zassert(!ifp->info); + + pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp)); + if (!pim_ifp) { + zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_ifp)); + return 0; + } + + pim_ifp->options = 0; + pim_ifp->mroute_vif_index = -1; + + pim_ifp->igmp_version = IGMP_DEFAULT_VERSION; + pim_ifp->igmp_default_robustness_variable = + IGMP_DEFAULT_ROBUSTNESS_VARIABLE; + pim_ifp->igmp_default_query_interval = IGMP_GENERAL_QUERY_INTERVAL; + pim_ifp->igmp_query_max_response_time_dsec = + IGMP_QUERY_MAX_RESPONSE_TIME_DSEC; + pim_ifp->igmp_specific_query_max_response_time_dsec = + IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC; + + /* + RFC 3376: 8.3. Query Response Interval + The number of seconds represented by the [Query Response Interval] + must be less than the [Query Interval]. + */ + zassert(pim_ifp->igmp_query_max_response_time_dsec + < pim_ifp->igmp_default_query_interval); + + if (pim) + PIM_IF_DO_PIM(pim_ifp->options); + if (igmp) + PIM_IF_DO_IGMP(pim_ifp->options); + + PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp->options); + + pim_ifp->igmp_join_list = NULL; + pim_ifp->igmp_socket_list = NULL; + pim_ifp->pim_neighbor_list = NULL; + pim_ifp->upstream_switch_list = NULL; + pim_ifp->pim_ifchannel_list = NULL; + pim_ifp->pim_ifchannel_hash = NULL; + pim_ifp->pim_generation_id = 0; + + /* list of struct igmp_sock */ + pim_ifp->igmp_socket_list = list_new(); + if (!pim_ifp->igmp_socket_list) { + zlog_err("%s %s: failure: igmp_socket_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return if_list_clean(pim_ifp); + } + pim_ifp->igmp_socket_list->del = (void (*)(void *))igmp_sock_free; + + /* list of struct pim_neighbor */ + pim_ifp->pim_neighbor_list = list_new(); + if (!pim_ifp->pim_neighbor_list) { + zlog_err("%s %s: failure: pim_neighbor_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return if_list_clean(pim_ifp); + } + pim_ifp->pim_neighbor_list->del = (void (*)(void *))pim_neighbor_free; + + pim_ifp->upstream_switch_list = list_new(); + if (!pim_ifp->upstream_switch_list) { + zlog_err("%s %s: failure: upstream_switch_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return if_list_clean(pim_ifp); + } + + /* list of struct pim_ifchannel */ + pim_ifp->pim_ifchannel_list = list_new(); + if (!pim_ifp->pim_ifchannel_list) { + zlog_err("%s %s: failure: pim_ifchannel_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return if_list_clean(pim_ifp); + } + pim_ifp->pim_ifchannel_list->del = (void (*)(void *))pim_ifchannel_free; + pim_ifp->pim_ifchannel_list->cmp = + (int (*)(void *, void *))pim_ifchannel_compare; + + pim_ifp->pim_ifchannel_hash = + hash_create(pim_ifchannel_hash_key, pim_ifchannel_equal, NULL); + + ifp->info = pim_ifp; + + pim_sock_reset(ifp); + + pim_if_add_vif(ifp); + + return pim_ifp; } void pim_if_delete(struct interface *ifp) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - zassert(ifp); - pim_ifp = ifp->info; - zassert(pim_ifp); + zassert(ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - if (pim_ifp->igmp_join_list) { - pim_if_igmp_join_del_all(ifp); - } + if (pim_ifp->igmp_join_list) { + pim_if_igmp_join_del_all(ifp); + } - pim_ifchannel_delete_all (ifp); - igmp_sock_delete_all (ifp); + pim_ifchannel_delete_all(ifp); + igmp_sock_delete_all(ifp); - pim_neighbor_delete_all (ifp, "Interface removed from configuration"); + pim_neighbor_delete_all(ifp, "Interface removed from configuration"); - pim_if_del_vif(ifp); + pim_if_del_vif(ifp); - list_delete(pim_ifp->igmp_socket_list); - list_delete(pim_ifp->pim_neighbor_list); - list_delete(pim_ifp->upstream_switch_list); - list_delete(pim_ifp->pim_ifchannel_list); + list_delete(pim_ifp->igmp_socket_list); + list_delete(pim_ifp->pim_neighbor_list); + list_delete(pim_ifp->upstream_switch_list); + list_delete(pim_ifp->pim_ifchannel_list); - hash_free (pim_ifp->pim_ifchannel_hash); + hash_free(pim_ifp->pim_ifchannel_hash); - XFREE(MTYPE_PIM_INTERFACE, pim_ifp); + XFREE(MTYPE_PIM_INTERFACE, pim_ifp); - ifp->info = NULL; + ifp->info = NULL; } void pim_if_update_could_assert(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *next_node; - struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; + struct listnode *node; + struct listnode *next_node; + struct pim_ifchannel *ch; - pim_ifp = ifp->info; - zassert(pim_ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, ch)) { - pim_ifchannel_update_could_assert(ch); - } + for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, + ch)) { + pim_ifchannel_update_could_assert(ch); + } } static void pim_if_update_my_assert_metric(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *next_node; - struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; + struct listnode *node; + struct listnode *next_node; + struct pim_ifchannel *ch; - pim_ifp = ifp->info; - zassert(pim_ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, ch)) { - pim_ifchannel_update_my_assert_metric(ch); - } + for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, + ch)) { + pim_ifchannel_update_my_assert_metric(ch); + } } static void pim_addr_change(struct interface *ifp) { - struct pim_interface *pim_ifp; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - pim_if_dr_election(ifp); /* router's own DR Priority (addr) changes -- Done TODO T30 */ - pim_if_update_join_desired(pim_ifp); /* depends on DR */ - pim_if_update_could_assert(ifp); /* depends on DR */ - pim_if_update_my_assert_metric(ifp); /* depends on could_assert */ - pim_if_update_assert_tracking_desired(ifp); /* depends on DR, join_desired */ - - /* - RFC 4601: 4.3.1. Sending Hello Messages - - 1) Before an interface goes down or changes primary IP address, a - Hello message with a zero HoldTime should be sent immediately - (with the old IP address if the IP address changed). - -- FIXME See CAVEAT C13 - - 2) After an interface has changed its IP address, it MUST send a - Hello message with its new IP address. - -- DONE below - - 3) If an interface changes one of its secondary IP addresses, a - Hello message with an updated Address_List option and a non-zero - HoldTime should be sent immediately. - -- FIXME See TODO T31 - */ - pim_ifp->pim_ifstat_hello_sent = 0; /* reset hello counter */ - if (pim_ifp->pim_sock_fd < 0) - return; - pim_hello_restart_now(ifp); /* send hello and restart timer */ + struct pim_interface *pim_ifp; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + pim_if_dr_election(ifp); /* router's own DR Priority (addr) changes -- + Done TODO T30 */ + pim_if_update_join_desired(pim_ifp); /* depends on DR */ + pim_if_update_could_assert(ifp); /* depends on DR */ + pim_if_update_my_assert_metric(ifp); /* depends on could_assert */ + pim_if_update_assert_tracking_desired( + ifp); /* depends on DR, join_desired */ + + /* + RFC 4601: 4.3.1. Sending Hello Messages + + 1) Before an interface goes down or changes primary IP address, a + Hello message with a zero HoldTime should be sent immediately + (with the old IP address if the IP address changed). + -- FIXME See CAVEAT C13 + + 2) After an interface has changed its IP address, it MUST send a + Hello message with its new IP address. + -- DONE below + + 3) If an interface changes one of its secondary IP addresses, a + Hello message with an updated Address_List option and a non-zero + HoldTime should be sent immediately. + -- FIXME See TODO T31 + */ + pim_ifp->pim_ifstat_hello_sent = 0; /* reset hello counter */ + if (pim_ifp->pim_sock_fd < 0) + return; + pim_hello_restart_now(ifp); /* send hello and restart timer */ } static int detect_primary_address_change(struct interface *ifp, int force_prim_as_any, const char *caller) { - struct pim_interface *pim_ifp = ifp->info; - struct in_addr new_prim_addr; - int changed; - - if (force_prim_as_any) - new_prim_addr.s_addr = INADDR_ANY; - else - new_prim_addr = pim_find_primary_addr(ifp); - - changed = new_prim_addr.s_addr != pim_ifp->primary_address.s_addr; - - if (PIM_DEBUG_ZEBRA) { - char new_prim_str[INET_ADDRSTRLEN]; - char old_prim_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", new_prim_addr, new_prim_str, sizeof(new_prim_str)); - pim_inet4_dump("", pim_ifp->primary_address, old_prim_str, sizeof(old_prim_str)); - zlog_debug("%s: old=%s new=%s on interface %s: %s", - __PRETTY_FUNCTION__, - old_prim_str, new_prim_str, ifp->name, - changed ? "changed" : "unchanged"); - } - - if (changed) { - pim_ifp->primary_address = new_prim_addr; - } - - return changed; + struct pim_interface *pim_ifp = ifp->info; + struct in_addr new_prim_addr; + int changed; + + if (force_prim_as_any) + new_prim_addr.s_addr = INADDR_ANY; + else + new_prim_addr = pim_find_primary_addr(ifp); + + changed = new_prim_addr.s_addr != pim_ifp->primary_address.s_addr; + + if (PIM_DEBUG_ZEBRA) { + char new_prim_str[INET_ADDRSTRLEN]; + char old_prim_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", new_prim_addr, new_prim_str, + sizeof(new_prim_str)); + pim_inet4_dump("", pim_ifp->primary_address, old_prim_str, + sizeof(old_prim_str)); + zlog_debug("%s: old=%s new=%s on interface %s: %s", + __PRETTY_FUNCTION__, old_prim_str, new_prim_str, + ifp->name, changed ? "changed" : "unchanged"); + } + + if (changed) { + pim_ifp->primary_address = new_prim_addr; + } + + return changed; } static int pim_sec_addr_comp(const void *p1, const void *p2) { - const struct pim_secondary_addr *sec1 = p1; - const struct pim_secondary_addr *sec2 = p2; - - if (sec1->addr.family == AF_INET && - sec2->addr.family == AF_INET6) - return -1; - - if (sec1->addr.family == AF_INET6 && - sec2->addr.family == AF_INET) - return 1; - - if (sec1->addr.family == AF_INET) - { - if (ntohl(sec1->addr.u.prefix4.s_addr) < ntohl(sec2->addr.u.prefix4.s_addr)) - return -1; - - if (ntohl(sec1->addr.u.prefix4.s_addr) > ntohl(sec2->addr.u.prefix4.s_addr)) - return 1; - } - else - { - return memcmp (&sec1->addr.u.prefix6, - &sec2->addr.u.prefix6, - sizeof (struct in6_addr)); - } - - return 0; + const struct pim_secondary_addr *sec1 = p1; + const struct pim_secondary_addr *sec2 = p2; + + if (sec1->addr.family == AF_INET && sec2->addr.family == AF_INET6) + return -1; + + if (sec1->addr.family == AF_INET6 && sec2->addr.family == AF_INET) + return 1; + + if (sec1->addr.family == AF_INET) { + if (ntohl(sec1->addr.u.prefix4.s_addr) + < ntohl(sec2->addr.u.prefix4.s_addr)) + return -1; + + if (ntohl(sec1->addr.u.prefix4.s_addr) + > ntohl(sec2->addr.u.prefix4.s_addr)) + return 1; + } else { + return memcmp(&sec1->addr.u.prefix6, &sec2->addr.u.prefix6, + sizeof(struct in6_addr)); + } + + return 0; } static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr) { - XFREE(MTYPE_PIM_SEC_ADDR, sec_addr); + XFREE(MTYPE_PIM_SEC_ADDR, sec_addr); } static struct pim_secondary_addr * pim_sec_addr_find(struct pim_interface *pim_ifp, struct prefix *addr) { - struct pim_secondary_addr *sec_addr; - struct listnode *node; + struct pim_secondary_addr *sec_addr; + struct listnode *node; - if (!pim_ifp->sec_addr_list) { - return NULL; - } + if (!pim_ifp->sec_addr_list) { + return NULL; + } - for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { - if (prefix_cmp(&sec_addr->addr, addr)) { - return sec_addr; - } - } + for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { + if (prefix_cmp(&sec_addr->addr, addr)) { + return sec_addr; + } + } - return NULL; + return NULL; } static void pim_sec_addr_del(struct pim_interface *pim_ifp, - struct pim_secondary_addr *sec_addr) + struct pim_secondary_addr *sec_addr) { - listnode_delete(pim_ifp->sec_addr_list, sec_addr); - pim_sec_addr_free(sec_addr); + listnode_delete(pim_ifp->sec_addr_list, sec_addr); + pim_sec_addr_free(sec_addr); } static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct prefix *addr) { - int changed = 0; - struct pim_secondary_addr *sec_addr; - - sec_addr = pim_sec_addr_find(pim_ifp, addr); - if (sec_addr) { - sec_addr->flags &= ~PIM_SEC_ADDRF_STALE; - return changed; - } - - if (!pim_ifp->sec_addr_list) { - pim_ifp->sec_addr_list = list_new(); - pim_ifp->sec_addr_list->del = (void (*)(void *))pim_sec_addr_free; - pim_ifp->sec_addr_list->cmp = (int (*)(void *, void *))pim_sec_addr_comp; - } - - sec_addr = XCALLOC(MTYPE_PIM_SEC_ADDR, sizeof(*sec_addr)); - if (!sec_addr) { - if (list_isempty(pim_ifp->sec_addr_list)) { - list_free(pim_ifp->sec_addr_list); - pim_ifp->sec_addr_list = NULL; - } - return changed; - } - - changed = 1; - sec_addr->addr = *addr; - listnode_add_sort(pim_ifp->sec_addr_list, sec_addr); - - return changed; + int changed = 0; + struct pim_secondary_addr *sec_addr; + + sec_addr = pim_sec_addr_find(pim_ifp, addr); + if (sec_addr) { + sec_addr->flags &= ~PIM_SEC_ADDRF_STALE; + return changed; + } + + if (!pim_ifp->sec_addr_list) { + pim_ifp->sec_addr_list = list_new(); + pim_ifp->sec_addr_list->del = + (void (*)(void *))pim_sec_addr_free; + pim_ifp->sec_addr_list->cmp = + (int (*)(void *, void *))pim_sec_addr_comp; + } + + sec_addr = XCALLOC(MTYPE_PIM_SEC_ADDR, sizeof(*sec_addr)); + if (!sec_addr) { + if (list_isempty(pim_ifp->sec_addr_list)) { + list_free(pim_ifp->sec_addr_list); + pim_ifp->sec_addr_list = NULL; + } + return changed; + } + + changed = 1; + sec_addr->addr = *addr; + listnode_add_sort(pim_ifp->sec_addr_list, sec_addr); + + return changed; } static int pim_sec_addr_del_all(struct pim_interface *pim_ifp) { - int changed = 0; - - if (!pim_ifp->sec_addr_list) { - return changed; - } - if (!list_isempty(pim_ifp->sec_addr_list)) { - changed = 1; - /* remove all nodes and free up the list itself */ - list_delete_all_node(pim_ifp->sec_addr_list); - list_free(pim_ifp->sec_addr_list); - pim_ifp->sec_addr_list = NULL; - } - - return changed; + int changed = 0; + + if (!pim_ifp->sec_addr_list) { + return changed; + } + if (!list_isempty(pim_ifp->sec_addr_list)) { + changed = 1; + /* remove all nodes and free up the list itself */ + list_delete_all_node(pim_ifp->sec_addr_list); + list_free(pim_ifp->sec_addr_list); + pim_ifp->sec_addr_list = NULL; + } + + return changed; } static int pim_sec_addr_update(struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; - struct connected *ifc; - struct listnode *node; - struct listnode *nextnode; - struct pim_secondary_addr *sec_addr; - int changed = 0; - - if (pim_ifp->sec_addr_list) { - for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { - sec_addr->flags |= PIM_SEC_ADDRF_STALE; - } - } - - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { - struct prefix *p = ifc->address; - - if (PIM_INADDR_IS_ANY(p->u.prefix4)) { - continue; - } - - if (pim_ifp->primary_address.s_addr == p->u.prefix4.s_addr) { - /* don't add the primary address into the secondary address list */ - continue; - } - - if (pim_sec_addr_add(pim_ifp, p)) { - changed = 1; - } - } - - if (pim_ifp->sec_addr_list) { - /* Drop stale entries */ - for (ALL_LIST_ELEMENTS(pim_ifp->sec_addr_list, node, nextnode, sec_addr)) { - if (sec_addr->flags & PIM_SEC_ADDRF_STALE) { - pim_sec_addr_del(pim_ifp, sec_addr); - changed = 1; - } - } - - /* If the list went empty free it up */ - if (list_isempty(pim_ifp->sec_addr_list)) { - list_free(pim_ifp->sec_addr_list); - pim_ifp->sec_addr_list = NULL; - } - } - - return changed; + struct pim_interface *pim_ifp = ifp->info; + struct connected *ifc; + struct listnode *node; + struct listnode *nextnode; + struct pim_secondary_addr *sec_addr; + int changed = 0; + + if (pim_ifp->sec_addr_list) { + for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, + sec_addr)) { + sec_addr->flags |= PIM_SEC_ADDRF_STALE; + } + } + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { + struct prefix *p = ifc->address; + + if (PIM_INADDR_IS_ANY(p->u.prefix4)) { + continue; + } + + if (pim_ifp->primary_address.s_addr == p->u.prefix4.s_addr) { + /* don't add the primary address into the secondary + * address list */ + continue; + } + + if (pim_sec_addr_add(pim_ifp, p)) { + changed = 1; + } + } + + if (pim_ifp->sec_addr_list) { + /* Drop stale entries */ + for (ALL_LIST_ELEMENTS(pim_ifp->sec_addr_list, node, nextnode, + sec_addr)) { + if (sec_addr->flags & PIM_SEC_ADDRF_STALE) { + pim_sec_addr_del(pim_ifp, sec_addr); + changed = 1; + } + } + + /* If the list went empty free it up */ + if (list_isempty(pim_ifp->sec_addr_list)) { + list_free(pim_ifp->sec_addr_list); + pim_ifp->sec_addr_list = NULL; + } + } + + return changed; } static int detect_secondary_address_change(struct interface *ifp, - int force_prim_as_any, - const char *caller) + int force_prim_as_any, + const char *caller) { - struct pim_interface *pim_ifp = ifp->info; - int changed = 0; - - if (force_prim_as_any) { - /* if primary address is being forced to zero just flush the - * secondary address list */ - changed = pim_sec_addr_del_all(pim_ifp); - } else { - /* re-evaluate the secondary address list */ - changed = pim_sec_addr_update(ifp); - } - - return changed; + struct pim_interface *pim_ifp = ifp->info; + int changed = 0; + + if (force_prim_as_any) { + /* if primary address is being forced to zero just flush the + * secondary address list */ + changed = pim_sec_addr_del_all(pim_ifp); + } else { + /* re-evaluate the secondary address list */ + changed = pim_sec_addr_update(ifp); + } + + return changed; } -static void detect_address_change(struct interface *ifp, - int force_prim_as_any, - const char *caller) +static void detect_address_change(struct interface *ifp, int force_prim_as_any, + const char *caller) { - int changed = 0; - struct pim_interface *pim_ifp; + int changed = 0; + struct pim_interface *pim_ifp; - pim_ifp = ifp->info; - if (!pim_ifp) - return; + pim_ifp = ifp->info; + if (!pim_ifp) + return; - if (detect_primary_address_change(ifp, force_prim_as_any, caller)) { - changed = 1; - } + if (detect_primary_address_change(ifp, force_prim_as_any, caller)) { + changed = 1; + } - if (detect_secondary_address_change(ifp, force_prim_as_any, caller)) { - changed = 1; - } + if (detect_secondary_address_change(ifp, force_prim_as_any, caller)) { + changed = 1; + } - if (changed) { - if (!PIM_IF_TEST_PIM(pim_ifp->options)) { - return; - } + if (changed) { + if (!PIM_IF_TEST_PIM(pim_ifp->options)) { + return; + } - pim_addr_change(ifp); - } + pim_addr_change(ifp); + } - /* XXX: if we have unnumbered interfaces we need to run detect address - * address change on all of them when the lo address changes */ + /* XXX: if we have unnumbered interfaces we need to run detect address + * address change on all of them when the lo address changes */ } int pim_update_source_set(struct interface *ifp, struct in_addr source) { - struct pim_interface *pim_ifp = ifp->info; + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) { - return PIM_IFACE_NOT_FOUND; - } + if (!pim_ifp) { + return PIM_IFACE_NOT_FOUND; + } - if (pim_ifp->update_source.s_addr == source.s_addr) { - return PIM_UPDATE_SOURCE_DUP; - } + if (pim_ifp->update_source.s_addr == source.s_addr) { + return PIM_UPDATE_SOURCE_DUP; + } - pim_ifp->update_source = source; - detect_address_change(ifp, 0 /* force_prim_as_any */, - __PRETTY_FUNCTION__); + pim_ifp->update_source = source; + detect_address_change(ifp, 0 /* force_prim_as_any */, + __PRETTY_FUNCTION__); - return PIM_SUCCESS; + return PIM_SUCCESS; } void pim_if_addr_add(struct connected *ifc) { - struct pim_interface *pim_ifp; - struct interface *ifp; - struct in_addr ifaddr; - - zassert(ifc); - - ifp = ifc->ifp; - zassert(ifp); - pim_ifp = ifp->info; - if (!pim_ifp) - return; - - if (!if_is_operative(ifp)) - return; - - if (PIM_DEBUG_ZEBRA) { - char buf[BUFSIZ]; - prefix2str(ifc->address, buf, BUFSIZ); - zlog_debug("%s: %s ifindex=%d connected IP address %s %s", - __PRETTY_FUNCTION__, - ifp->name, ifp->ifindex, buf, - CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ? - "secondary" : "primary"); - } - - ifaddr = ifc->address->u.prefix4; - - detect_address_change(ifp, 0, __PRETTY_FUNCTION__); - - if (ifc->address->family != AF_INET) - return; - - if (PIM_IF_TEST_IGMP(pim_ifp->options)) { - struct igmp_sock *igmp; - - /* lookup IGMP socket */ - igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, - ifaddr); - if (!igmp) { - /* if addr new, add IGMP socket */ - pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr, ifp); - } - - /* Replay Static IGMP groups */ - if (pim_ifp->igmp_join_list) - { - struct listnode *node; - struct listnode *nextnode; - struct igmp_join *ij; - int join_fd; - - for (ALL_LIST_ELEMENTS (pim_ifp->igmp_join_list, node, nextnode, ij)) - { - /* Close socket and reopen with Source and Group */ - close(ij->sock_fd); - join_fd = igmp_join_sock(ifp->name, ifp->ifindex, ij->group_addr, ij->source_addr); - if (join_fd < 0) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", ij->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", ij->source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s", - __PRETTY_FUNCTION__, - group_str, source_str, ifp->name); - /* warning only */ - } - else - ij->sock_fd = join_fd; - } - } - } /* igmp */ - - if (PIM_IF_TEST_PIM(pim_ifp->options)) - { - - if (PIM_INADDR_ISNOT_ANY (pim_ifp->primary_address)) - { - - /* Interface has a valid socket ? */ - if (pim_ifp->pim_sock_fd < 0) - { - if (pim_sock_add (ifp)) - { - zlog_warn ("Failure creating PIM socket for interface %s", - ifp->name); - } - } - struct pim_nexthop_cache *pnc = NULL; - struct pim_rpf rpf; - struct zclient *zclient = NULL; - - zclient = pim_zebra_zclient_get (); - /* RP config might come prior to (local RP's interface) IF UP event. - In this case, pnc would not have pim enabled nexthops. - Once Interface is UP and pim info is available, reregister - with RNH address to receive update and add the interface as nexthop. */ - memset (&rpf, 0, sizeof (struct pim_rpf)); - rpf.rpf_addr.family = AF_INET; - rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN; - rpf.rpf_addr.u.prefix4 = ifc->address->u.prefix4; - pnc = pim_nexthop_cache_find (&rpf); - if (pnc) - pim_sendmsg_zebra_rnh (zclient, pnc, - ZEBRA_NEXTHOP_REGISTER); - } - } /* pim */ - - /* - PIM or IGMP is enabled on interface, and there is at least one - address assigned, then try to create a vif_index. - */ - if (pim_ifp->mroute_vif_index < 0) { - pim_if_add_vif(ifp); - } - pim_ifchannel_scan_forward_start (ifp); + struct pim_interface *pim_ifp; + struct interface *ifp; + struct in_addr ifaddr; + + zassert(ifc); + + ifp = ifc->ifp; + zassert(ifp); + pim_ifp = ifp->info; + if (!pim_ifp) + return; + + if (!if_is_operative(ifp)) + return; + + if (PIM_DEBUG_ZEBRA) { + char buf[BUFSIZ]; + prefix2str(ifc->address, buf, BUFSIZ); + zlog_debug("%s: %s ifindex=%d connected IP address %s %s", + __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, buf, + CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) + ? "secondary" + : "primary"); + } + + ifaddr = ifc->address->u.prefix4; + + detect_address_change(ifp, 0, __PRETTY_FUNCTION__); + + if (ifc->address->family != AF_INET) + return; + + if (PIM_IF_TEST_IGMP(pim_ifp->options)) { + struct igmp_sock *igmp; + + /* lookup IGMP socket */ + igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, + ifaddr); + if (!igmp) { + /* if addr new, add IGMP socket */ + pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr, + ifp); + } + + /* Replay Static IGMP groups */ + if (pim_ifp->igmp_join_list) { + struct listnode *node; + struct listnode *nextnode; + struct igmp_join *ij; + int join_fd; + + for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node, + nextnode, ij)) { + /* Close socket and reopen with Source and Group + */ + close(ij->sock_fd); + join_fd = igmp_join_sock( + ifp->name, ifp->ifindex, ij->group_addr, + ij->source_addr); + if (join_fd < 0) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", ij->group_addr, + group_str, + sizeof(group_str)); + pim_inet4_dump( + "", ij->source_addr, + source_str, sizeof(source_str)); + zlog_warn( + "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s", + __PRETTY_FUNCTION__, group_str, + source_str, ifp->name); + /* warning only */ + } else + ij->sock_fd = join_fd; + } + } + } /* igmp */ + + if (PIM_IF_TEST_PIM(pim_ifp->options)) { + + if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { + + /* Interface has a valid socket ? */ + if (pim_ifp->pim_sock_fd < 0) { + if (pim_sock_add(ifp)) { + zlog_warn( + "Failure creating PIM socket for interface %s", + ifp->name); + } + } + struct pim_nexthop_cache *pnc = NULL; + struct pim_rpf rpf; + struct zclient *zclient = NULL; + + zclient = pim_zebra_zclient_get(); + /* RP config might come prior to (local RP's interface) + IF UP event. + In this case, pnc would not have pim enabled + nexthops. + Once Interface is UP and pim info is available, + reregister + with RNH address to receive update and add the + interface as nexthop. */ + memset(&rpf, 0, sizeof(struct pim_rpf)); + rpf.rpf_addr.family = AF_INET; + rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN; + rpf.rpf_addr.u.prefix4 = ifc->address->u.prefix4; + pnc = pim_nexthop_cache_find(&rpf); + if (pnc) + pim_sendmsg_zebra_rnh(zclient, pnc, + ZEBRA_NEXTHOP_REGISTER); + } + } /* pim */ + + /* + PIM or IGMP is enabled on interface, and there is at least one + address assigned, then try to create a vif_index. + */ + if (pim_ifp->mroute_vif_index < 0) { + pim_if_add_vif(ifp); + } + pim_ifchannel_scan_forward_start(ifp); } static void pim_if_addr_del_igmp(struct connected *ifc) { - struct pim_interface *pim_ifp = ifc->ifp->info; - struct igmp_sock *igmp; - struct in_addr ifaddr; - - if (ifc->address->family != AF_INET) { - /* non-IPv4 address */ - return; - } - - if (!pim_ifp) { - /* IGMP not enabled on interface */ - return; - } - - ifaddr = ifc->address->u.prefix4; - - /* lookup IGMP socket */ - igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, - ifaddr); - if (igmp) { - /* if addr found, del IGMP socket */ - igmp_sock_delete(igmp); - } + struct pim_interface *pim_ifp = ifc->ifp->info; + struct igmp_sock *igmp; + struct in_addr ifaddr; + + if (ifc->address->family != AF_INET) { + /* non-IPv4 address */ + return; + } + + if (!pim_ifp) { + /* IGMP not enabled on interface */ + return; + } + + ifaddr = ifc->address->u.prefix4; + + /* lookup IGMP socket */ + igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr); + if (igmp) { + /* if addr found, del IGMP socket */ + igmp_sock_delete(igmp); + } } static void pim_if_addr_del_pim(struct connected *ifc) { - struct pim_interface *pim_ifp = ifc->ifp->info; - - if (ifc->address->family != AF_INET) { - /* non-IPv4 address */ - return; - } - - if (!pim_ifp) { - /* PIM not enabled on interface */ - return; - } - - if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { - /* Interface keeps a valid primary address */ - return; - } - - if (pim_ifp->pim_sock_fd < 0) { - /* Interface does not hold a valid socket any longer */ - return; - } - - /* - pim_sock_delete() closes the socket, stops read and timer threads, - and kills all neighbors. - */ - pim_sock_delete(ifc->ifp, "last address has been removed from interface"); -} + struct pim_interface *pim_ifp = ifc->ifp->info; -void pim_if_addr_del(struct connected *ifc, int force_prim_as_any) -{ - struct interface *ifp; + if (ifc->address->family != AF_INET) { + /* non-IPv4 address */ + return; + } - zassert(ifc); - ifp = ifc->ifp; - zassert(ifp); + if (!pim_ifp) { + /* PIM not enabled on interface */ + return; + } + + if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { + /* Interface keeps a valid primary address */ + return; + } - if (ifc->address->family != AF_INET) - return; + if (pim_ifp->pim_sock_fd < 0) { + /* Interface does not hold a valid socket any longer */ + return; + } - if (PIM_DEBUG_ZEBRA) { - char buf[BUFSIZ]; - prefix2str(ifc->address, buf, BUFSIZ); - zlog_debug("%s: %s ifindex=%d disconnected IP address %s %s", - __PRETTY_FUNCTION__, - ifp->name, ifp->ifindex, buf, - CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ? - "secondary" : "primary"); - } + /* + pim_sock_delete() closes the socket, stops read and timer threads, + and kills all neighbors. + */ + pim_sock_delete(ifc->ifp, + "last address has been removed from interface"); +} - detect_address_change(ifp, force_prim_as_any, __PRETTY_FUNCTION__); +void pim_if_addr_del(struct connected *ifc, int force_prim_as_any) +{ + struct interface *ifp; + + zassert(ifc); + ifp = ifc->ifp; + zassert(ifp); + + if (ifc->address->family != AF_INET) + return; + + if (PIM_DEBUG_ZEBRA) { + char buf[BUFSIZ]; + prefix2str(ifc->address, buf, BUFSIZ); + zlog_debug("%s: %s ifindex=%d disconnected IP address %s %s", + __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, buf, + CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) + ? "secondary" + : "primary"); + } - pim_if_addr_del_igmp(ifc); - pim_if_addr_del_pim(ifc); + detect_address_change(ifp, force_prim_as_any, __PRETTY_FUNCTION__); + + pim_if_addr_del_igmp(ifc); + pim_if_addr_del_pim(ifc); } void pim_if_addr_add_all(struct interface *ifp) { - struct connected *ifc; - struct listnode *node; - struct listnode *nextnode; - int v4_addrs = 0; - int v6_addrs = 0; - struct pim_interface *pim_ifp = ifp->info; - - - /* PIM/IGMP enabled ? */ - if (!pim_ifp) - return; - - for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { - struct prefix *p = ifc->address; - - if (p->family != AF_INET) - v6_addrs++; - else - v4_addrs++; - pim_if_addr_add(ifc); - } - - if (!v4_addrs && v6_addrs && !if_is_loopback (ifp)) - { - if (PIM_IF_TEST_PIM(pim_ifp->options)) { - - /* Interface has a valid primary address ? */ - if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { + struct connected *ifc; + struct listnode *node; + struct listnode *nextnode; + int v4_addrs = 0; + int v6_addrs = 0; + struct pim_interface *pim_ifp = ifp->info; + + + /* PIM/IGMP enabled ? */ + if (!pim_ifp) + return; + + for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { + struct prefix *p = ifc->address; + + if (p->family != AF_INET) + v6_addrs++; + else + v4_addrs++; + pim_if_addr_add(ifc); + } - /* Interface has a valid socket ? */ - if (pim_ifp->pim_sock_fd < 0) { - if (pim_sock_add(ifp)) { - zlog_warn("Failure creating PIM socket for interface %s", - ifp->name); - } - } - - } - } /* pim */ - } - /* - * PIM or IGMP is enabled on interface, and there is at least one - * address assigned, then try to create a vif_index. - */ - if (pim_ifp->mroute_vif_index < 0) { - pim_if_add_vif(ifp); - } - pim_ifchannel_scan_forward_start (ifp); - - pim_rp_setup(); - pim_rp_check_on_if_add(pim_ifp); + if (!v4_addrs && v6_addrs && !if_is_loopback(ifp)) { + if (PIM_IF_TEST_PIM(pim_ifp->options)) { + + /* Interface has a valid primary address ? */ + if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) { + + /* Interface has a valid socket ? */ + if (pim_ifp->pim_sock_fd < 0) { + if (pim_sock_add(ifp)) { + zlog_warn( + "Failure creating PIM socket for interface %s", + ifp->name); + } + } + } + } /* pim */ + } + /* + * PIM or IGMP is enabled on interface, and there is at least one + * address assigned, then try to create a vif_index. + */ + if (pim_ifp->mroute_vif_index < 0) { + pim_if_add_vif(ifp); + } + pim_ifchannel_scan_forward_start(ifp); + + pim_rp_setup(); + pim_rp_check_on_if_add(pim_ifp); } void pim_if_addr_del_all(struct interface *ifp) { - struct connected *ifc; - struct listnode *node; - struct listnode *nextnode; + struct connected *ifc; + struct listnode *node; + struct listnode *nextnode; + + /* PIM/IGMP enabled ? */ + if (!ifp->info) + return; - /* PIM/IGMP enabled ? */ - if (!ifp->info) - return; + for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { + struct prefix *p = ifc->address; - for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { - struct prefix *p = ifc->address; - - if (p->family != AF_INET) - continue; + if (p->family != AF_INET) + continue; - pim_if_addr_del(ifc, 1 /* force_prim_as_any=true */); - } + pim_if_addr_del(ifc, 1 /* force_prim_as_any=true */); + } - pim_rp_setup(); - pim_i_am_rp_re_evaluate(); + pim_rp_setup(); + pim_i_am_rp_re_evaluate(); } void pim_if_addr_del_all_igmp(struct interface *ifp) { - struct connected *ifc; - struct listnode *node; - struct listnode *nextnode; - - /* PIM/IGMP enabled ? */ - if (!ifp->info) - return; - - for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { - struct prefix *p = ifc->address; - - if (p->family != AF_INET) - continue; - - pim_if_addr_del_igmp(ifc); - } + struct connected *ifc; + struct listnode *node; + struct listnode *nextnode; + + /* PIM/IGMP enabled ? */ + if (!ifp->info) + return; + + for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { + struct prefix *p = ifc->address; + + if (p->family != AF_INET) + continue; + + pim_if_addr_del_igmp(ifc); + } } void pim_if_addr_del_all_pim(struct interface *ifp) { - struct connected *ifc; - struct listnode *node; - struct listnode *nextnode; - - /* PIM/IGMP enabled ? */ - if (!ifp->info) - return; - - for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { - struct prefix *p = ifc->address; - - if (p->family != AF_INET) - continue; - - pim_if_addr_del_pim(ifc); - } + struct connected *ifc; + struct listnode *node; + struct listnode *nextnode; + + /* PIM/IGMP enabled ? */ + if (!ifp->info) + return; + + for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) { + struct prefix *p = ifc->address; + + if (p->family != AF_INET) + continue; + + pim_if_addr_del_pim(ifc); + } } -struct in_addr -pim_find_primary_addr (struct interface *ifp) +struct in_addr pim_find_primary_addr(struct interface *ifp) { - struct connected *ifc; - struct listnode *node; - struct in_addr addr; - int v4_addrs = 0; - int v6_addrs = 0; - struct pim_interface *pim_ifp = ifp->info; - - if (pim_ifp && PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) { - return pim_ifp->update_source; - } - - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { - struct prefix *p = ifc->address; - - if (p->family != AF_INET) - { - v6_addrs++; - continue; - } - - if (PIM_INADDR_IS_ANY(p->u.prefix4)) { - zlog_warn("%s: null IPv4 address connected to interface %s", - __PRETTY_FUNCTION__, ifp->name); - continue; - } - - v4_addrs++; - - if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) - continue; - - return p->u.prefix4; - } - - /* - * If we have no v4_addrs and v6 is configured - * We probably are using unnumbered - * So let's grab the loopbacks v4 address - * and use that as the primary address - */ - if (!v4_addrs && v6_addrs && !if_is_loopback (ifp)) - { - struct interface *lo_ifp; - lo_ifp = if_lookup_by_name ("lo", VRF_DEFAULT); - if (lo_ifp) - return pim_find_primary_addr (lo_ifp); - } - - addr.s_addr = PIM_NET_INADDR_ANY; - - return addr; + struct connected *ifc; + struct listnode *node; + struct in_addr addr; + int v4_addrs = 0; + int v6_addrs = 0; + struct pim_interface *pim_ifp = ifp->info; + + if (pim_ifp && PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) { + return pim_ifp->update_source; + } + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { + struct prefix *p = ifc->address; + + if (p->family != AF_INET) { + v6_addrs++; + continue; + } + + if (PIM_INADDR_IS_ANY(p->u.prefix4)) { + zlog_warn( + "%s: null IPv4 address connected to interface %s", + __PRETTY_FUNCTION__, ifp->name); + continue; + } + + v4_addrs++; + + if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) + continue; + + return p->u.prefix4; + } + + /* + * If we have no v4_addrs and v6 is configured + * We probably are using unnumbered + * So let's grab the loopbacks v4 address + * and use that as the primary address + */ + if (!v4_addrs && v6_addrs && !if_is_loopback(ifp)) { + struct interface *lo_ifp; + lo_ifp = if_lookup_by_name("lo", VRF_DEFAULT); + if (lo_ifp) + return pim_find_primary_addr(lo_ifp); + } + + addr.s_addr = PIM_NET_INADDR_ANY; + + return addr; } -static int -pim_iface_next_vif_index (struct interface *ifp) +static int pim_iface_next_vif_index(struct interface *ifp) { - int i; - /* - * The pimreg vif is always going to be in index 0 - * of the table. - */ - if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) - return 0; - - for (i = 1 ; i < MAXVIFS; i++) - { - if (pim_iface_vif_index[i] == 0) - return i; - } - return MAXVIFS; + int i; + /* + * The pimreg vif is always going to be in index 0 + * of the table. + */ + if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) + return 0; + + for (i = 1; i < MAXVIFS; i++) { + if (pim_iface_vif_index[i] == 0) + return i; + } + return MAXVIFS; } /* @@ -960,130 +972,131 @@ pim_iface_next_vif_index (struct interface *ifp) */ int pim_if_add_vif(struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; - struct in_addr ifaddr; - unsigned char flags = 0; - - zassert(pim_ifp); - - if (pim_ifp->mroute_vif_index > 0) { - zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d", - __PRETTY_FUNCTION__, - pim_ifp->mroute_vif_index, ifp->name, ifp->ifindex); - return -1; - } - - if (ifp->ifindex < 0) { - zlog_warn("%s: ifindex=%d < 1 on interface %s", - __PRETTY_FUNCTION__, - ifp->ifindex, ifp->name); - return -2; - } - - ifaddr = pim_ifp->primary_address; - if (ifp->ifindex != PIM_OIF_PIM_REGISTER_VIF && PIM_INADDR_IS_ANY(ifaddr)) { - zlog_warn("%s: could not get address for interface %s ifindex=%d", - __PRETTY_FUNCTION__, - ifp->name, ifp->ifindex); - return -4; - } - - pim_ifp->mroute_vif_index = pim_iface_next_vif_index (ifp); - - if (pim_ifp->mroute_vif_index >= MAXVIFS) - { - zlog_warn("%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s", - __PRETTY_FUNCTION__, - MAXVIFS, ifp->name); - return -3; - } - - if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) - flags = VIFF_REGISTER; + struct pim_interface *pim_ifp = ifp->info; + struct in_addr ifaddr; + unsigned char flags = 0; + + zassert(pim_ifp); + + if (pim_ifp->mroute_vif_index > 0) { + zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d", + __PRETTY_FUNCTION__, pim_ifp->mroute_vif_index, + ifp->name, ifp->ifindex); + return -1; + } + + if (ifp->ifindex < 0) { + zlog_warn("%s: ifindex=%d < 1 on interface %s", + __PRETTY_FUNCTION__, ifp->ifindex, ifp->name); + return -2; + } + + ifaddr = pim_ifp->primary_address; + if (ifp->ifindex != PIM_OIF_PIM_REGISTER_VIF + && PIM_INADDR_IS_ANY(ifaddr)) { + zlog_warn( + "%s: could not get address for interface %s ifindex=%d", + __PRETTY_FUNCTION__, ifp->name, ifp->ifindex); + return -4; + } + + pim_ifp->mroute_vif_index = pim_iface_next_vif_index(ifp); + + if (pim_ifp->mroute_vif_index >= MAXVIFS) { + zlog_warn( + "%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s", + __PRETTY_FUNCTION__, MAXVIFS, ifp->name); + return -3; + } + + if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF) + flags = VIFF_REGISTER; #ifdef VIFF_USE_IFINDEX - else - flags = VIFF_USE_IFINDEX; + else + flags = VIFF_USE_IFINDEX; #endif - if (pim_mroute_add_vif(ifp, ifaddr, flags)) { - /* pim_mroute_add_vif reported error */ - return -5; - } + if (pim_mroute_add_vif(ifp, ifaddr, flags)) { + /* pim_mroute_add_vif reported error */ + return -5; + } - pim_iface_vif_index[pim_ifp->mroute_vif_index] = 1; - return 0; + pim_iface_vif_index[pim_ifp->mroute_vif_index] = 1; + return 0; } int pim_if_del_vif(struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; + struct pim_interface *pim_ifp = ifp->info; - if (pim_ifp->mroute_vif_index < 1) { - zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d", - __PRETTY_FUNCTION__, - pim_ifp->mroute_vif_index, ifp->name, ifp->ifindex); - return -1; - } + if (pim_ifp->mroute_vif_index < 1) { + zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d", + __PRETTY_FUNCTION__, pim_ifp->mroute_vif_index, + ifp->name, ifp->ifindex); + return -1; + } - pim_mroute_del_vif(pim_ifp->mroute_vif_index); + pim_mroute_del_vif(pim_ifp->mroute_vif_index); - /* - Update vif_index - */ - pim_iface_vif_index[pim_ifp->mroute_vif_index] = 0; + /* + Update vif_index + */ + pim_iface_vif_index[pim_ifp->mroute_vif_index] = 0; - pim_ifp->mroute_vif_index = -1; + pim_ifp->mroute_vif_index = -1; - return 0; + return 0; } void pim_if_add_vif_all() { - struct listnode *ifnode; - struct listnode *ifnextnode; - struct interface *ifp; + struct listnode *ifnode; + struct listnode *ifnextnode; + struct interface *ifp; - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { - if (!ifp->info) - continue; + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode, + ifp)) { + if (!ifp->info) + continue; - pim_if_add_vif(ifp); - } + pim_if_add_vif(ifp); + } } void pim_if_del_vif_all() { - struct listnode *ifnode; - struct listnode *ifnextnode; - struct interface *ifp; + struct listnode *ifnode; + struct listnode *ifnextnode; + struct interface *ifp; - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), ifnode, ifnextnode, ifp)) { - if (!ifp->info) - continue; + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), ifnode, ifnextnode, + ifp)) { + if (!ifp->info) + continue; - pim_if_del_vif(ifp); - } + pim_if_del_vif(ifp); + } } struct interface *pim_if_find_by_vif_index(ifindex_t vif_index) { - struct listnode *ifnode; - struct interface *ifp; + struct listnode *ifnode; + struct interface *ifp; - if (vif_index == 0) - return if_lookup_by_name ("pimreg", VRF_DEFAULT); + if (vif_index == 0) + return if_lookup_by_name("pimreg", VRF_DEFAULT); - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { - if (ifp->info) { - struct pim_interface *pim_ifp; - pim_ifp = ifp->info; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { + if (ifp->info) { + struct pim_interface *pim_ifp; + pim_ifp = ifp->info; - if (vif_index == pim_ifp->mroute_vif_index) - return ifp; - } - } + if (vif_index == pim_ifp->mroute_vif_index) + return ifp; + } + } - return 0; + return 0; } /* @@ -1091,69 +1104,67 @@ struct interface *pim_if_find_by_vif_index(ifindex_t vif_index) */ int pim_if_find_vifindex_by_ifindex(ifindex_t ifindex) { - struct pim_interface *pim_ifp; - struct interface *ifp; + struct pim_interface *pim_ifp; + struct interface *ifp; - ifp = if_lookup_by_index (ifindex, VRF_DEFAULT); - if (!ifp || !ifp->info) - return -1; - pim_ifp = ifp->info; + ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); + if (!ifp || !ifp->info) + return -1; + pim_ifp = ifp->info; - return pim_ifp->mroute_vif_index; + return pim_ifp->mroute_vif_index; } int pim_if_lan_delay_enabled(struct interface *ifp) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - pim_ifp = ifp->info; - zassert(pim_ifp); - zassert(pim_ifp->pim_number_of_nonlandelay_neighbors >= 0); + pim_ifp = ifp->info; + zassert(pim_ifp); + zassert(pim_ifp->pim_number_of_nonlandelay_neighbors >= 0); - return pim_ifp->pim_number_of_nonlandelay_neighbors == 0; + return pim_ifp->pim_number_of_nonlandelay_neighbors == 0; } uint16_t pim_if_effective_propagation_delay_msec(struct interface *ifp) { - if (pim_if_lan_delay_enabled(ifp)) { - struct pim_interface *pim_ifp; - pim_ifp = ifp->info; - return pim_ifp->pim_neighbors_highest_propagation_delay_msec; - } - else { - return PIM_DEFAULT_PROPAGATION_DELAY_MSEC; - } + if (pim_if_lan_delay_enabled(ifp)) { + struct pim_interface *pim_ifp; + pim_ifp = ifp->info; + return pim_ifp->pim_neighbors_highest_propagation_delay_msec; + } else { + return PIM_DEFAULT_PROPAGATION_DELAY_MSEC; + } } uint16_t pim_if_effective_override_interval_msec(struct interface *ifp) { - if (pim_if_lan_delay_enabled(ifp)) { - struct pim_interface *pim_ifp; - pim_ifp = ifp->info; - return pim_ifp->pim_neighbors_highest_override_interval_msec; - } - else { - return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC; - } + if (pim_if_lan_delay_enabled(ifp)) { + struct pim_interface *pim_ifp; + pim_ifp = ifp->info; + return pim_ifp->pim_neighbors_highest_override_interval_msec; + } else { + return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC; + } } int pim_if_t_override_msec(struct interface *ifp) { - int effective_override_interval_msec; - int t_override_msec; + int effective_override_interval_msec; + int t_override_msec; - effective_override_interval_msec = - pim_if_effective_override_interval_msec(ifp); + effective_override_interval_msec = + pim_if_effective_override_interval_msec(ifp); - t_override_msec = random() % (effective_override_interval_msec + 1); + t_override_msec = random() % (effective_override_interval_msec + 1); - return t_override_msec; + return t_override_msec; } uint16_t pim_if_jp_override_interval_msec(struct interface *ifp) { - return pim_if_effective_propagation_delay_msec(ifp) + - pim_if_effective_override_interval_msec(ifp); + return pim_if_effective_propagation_delay_msec(ifp) + + pim_if_effective_override_interval_msec(ifp); } /* @@ -1168,294 +1179,303 @@ uint16_t pim_if_jp_override_interval_msec(struct interface *ifp) struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp, struct in_addr addr) { - struct listnode *neighnode; - struct pim_neighbor *neigh; - struct pim_interface *pim_ifp; - struct prefix p; - - zassert(ifp); - - pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - ifp->name); - return 0; - } - - p.family = AF_INET; - p.u.prefix4 = addr; - p.prefixlen = IPV4_MAX_PREFIXLEN; - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) { - - /* primary address ? */ - if (neigh->source_addr.s_addr == addr.s_addr) - return neigh; - - /* secondary address ? */ - if (pim_neighbor_find_secondary(neigh, &p)) - return neigh; - } - - if (PIM_DEBUG_PIM_TRACE) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s: neighbor not found for address %s on interface %s", - __PRETTY_FUNCTION__, - addr_str, ifp->name); - } - - return NULL; + struct listnode *neighnode; + struct pim_neighbor *neigh; + struct pim_interface *pim_ifp; + struct prefix p; + + zassert(ifp); + + pim_ifp = ifp->info; + if (!pim_ifp) { + zlog_warn("%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, ifp->name); + return 0; + } + + p.family = AF_INET; + p.u.prefix4 = addr; + p.prefixlen = IPV4_MAX_PREFIXLEN; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, + neigh)) { + + /* primary address ? */ + if (neigh->source_addr.s_addr == addr.s_addr) + return neigh; + + /* secondary address ? */ + if (pim_neighbor_find_secondary(neigh, &p)) + return neigh; + } + + if (PIM_DEBUG_PIM_TRACE) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_debug( + "%s: neighbor not found for address %s on interface %s", + __PRETTY_FUNCTION__, addr_str, ifp->name); + } + + return NULL; } long pim_if_t_suppressed_msec(struct interface *ifp) { - struct pim_interface *pim_ifp; - long t_suppressed_msec; - uint32_t ramount = 0; + struct pim_interface *pim_ifp; + long t_suppressed_msec; + uint32_t ramount = 0; - pim_ifp = ifp->info; - zassert(pim_ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - /* join suppression disabled ? */ - if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options)) - return 0; + /* join suppression disabled ? */ + if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options)) + return 0; - /* t_suppressed = t_periodic * rand(1.1, 1.4) */ - ramount = 1100 + (random() % (1400 - 1100 + 1)); - t_suppressed_msec = qpim_t_periodic * ramount; + /* t_suppressed = t_periodic * rand(1.1, 1.4) */ + ramount = 1100 + (random() % (1400 - 1100 + 1)); + t_suppressed_msec = qpim_t_periodic * ramount; - return t_suppressed_msec; + return t_suppressed_msec; } static void igmp_join_free(struct igmp_join *ij) { - XFREE(MTYPE_PIM_IGMP_JOIN, ij); + XFREE(MTYPE_PIM_IGMP_JOIN, ij); } static struct igmp_join *igmp_join_find(struct list *join_list, struct in_addr group_addr, struct in_addr source_addr) { - struct listnode *node; - struct igmp_join *ij; + struct listnode *node; + struct igmp_join *ij; - zassert(join_list); + zassert(join_list); - for (ALL_LIST_ELEMENTS_RO(join_list, node, ij)) { - if ((group_addr.s_addr == ij->group_addr.s_addr) && - (source_addr.s_addr == ij->source_addr.s_addr)) - return ij; - } + for (ALL_LIST_ELEMENTS_RO(join_list, node, ij)) { + if ((group_addr.s_addr == ij->group_addr.s_addr) + && (source_addr.s_addr == ij->source_addr.s_addr)) + return ij; + } - return 0; + return 0; } -static int igmp_join_sock(const char *ifname, - ifindex_t ifindex, - struct in_addr group_addr, - struct in_addr source_addr) +static int igmp_join_sock(const char *ifname, ifindex_t ifindex, + struct in_addr group_addr, struct in_addr source_addr) { - int join_fd; + int join_fd; - join_fd = pim_socket_raw(IPPROTO_IGMP); - if (join_fd < 0) { - return -1; - } + join_fd = pim_socket_raw(IPPROTO_IGMP); + if (join_fd < 0) { + return -1; + } - if (pim_socket_join_source(join_fd, ifindex, group_addr, source_addr, ifname)) { - close(join_fd); - return -2; - } + if (pim_socket_join_source(join_fd, ifindex, group_addr, source_addr, + ifname)) { + close(join_fd); + return -2; + } - return join_fd; + return join_fd; } static struct igmp_join *igmp_join_new(struct interface *ifp, struct in_addr group_addr, struct in_addr source_addr) { - struct pim_interface *pim_ifp; - struct igmp_join *ij; - int join_fd; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr, source_addr); - if (join_fd < 0) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s", - __PRETTY_FUNCTION__, - group_str, source_str, ifp->name); - return 0; - } - - ij = XCALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij)); - if (!ij) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - zlog_err("%s: XCALLOC(%zu) failure for IGMP group %s source %s on interface %s", - __PRETTY_FUNCTION__, - sizeof(*ij), group_str, source_str, ifp->name); - close(join_fd); - return 0; - } - - ij->sock_fd = join_fd; - ij->group_addr = group_addr; - ij->source_addr = source_addr; - ij->sock_creation = pim_time_monotonic_sec(); - - listnode_add(pim_ifp->igmp_join_list, ij); - - return ij; + struct pim_interface *pim_ifp; + struct igmp_join *ij; + int join_fd; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr, + source_addr); + if (join_fd < 0) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("", source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s", + __PRETTY_FUNCTION__, group_str, source_str, ifp->name); + return 0; + } + + ij = XCALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij)); + if (!ij) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("", source_addr, source_str, + sizeof(source_str)); + zlog_err( + "%s: XCALLOC(%zu) failure for IGMP group %s source %s on interface %s", + __PRETTY_FUNCTION__, sizeof(*ij), group_str, source_str, + ifp->name); + close(join_fd); + return 0; + } + + ij->sock_fd = join_fd; + ij->group_addr = group_addr; + ij->source_addr = source_addr; + ij->sock_creation = pim_time_monotonic_sec(); + + listnode_add(pim_ifp->igmp_join_list, ij); + + return ij; } -int pim_if_igmp_join_add(struct interface *ifp, - struct in_addr group_addr, +int pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr, struct in_addr source_addr) { - struct pim_interface *pim_ifp; - struct igmp_join *ij; - - pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - ifp->name); - return -1; - } - - if (!pim_ifp->igmp_join_list) { - pim_ifp->igmp_join_list = list_new(); - if (!pim_ifp->igmp_join_list) { - zlog_err("%s %s: failure: igmp_join_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return -2; - } - pim_ifp->igmp_join_list->del = (void (*)(void *)) igmp_join_free; - } - - ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr); - if (ij) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: can't re-join existing IGMP group %s source %s on interface %s", - __PRETTY_FUNCTION__, - group_str, source_str, ifp->name); - return -3; - } - - ij = igmp_join_new(ifp, group_addr, source_addr); - if (!ij) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: igmp_join_new() failure for IGMP group %s source %s on interface %s", - __PRETTY_FUNCTION__, - group_str, source_str, ifp->name); - return -4; - } - - if (PIM_DEBUG_IGMP_EVENTS) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - zlog_debug("%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s", - __PRETTY_FUNCTION__, - source_str, group_str, ifp->name); - } - - return 0; -} + struct pim_interface *pim_ifp; + struct igmp_join *ij; + + pim_ifp = ifp->info; + if (!pim_ifp) { + zlog_warn("%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, ifp->name); + return -1; + } + + if (!pim_ifp->igmp_join_list) { + pim_ifp->igmp_join_list = list_new(); + if (!pim_ifp->igmp_join_list) { + zlog_err("%s %s: failure: igmp_join_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return -2; + } + pim_ifp->igmp_join_list->del = (void (*)(void *))igmp_join_free; + } + + ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr); + if (ij) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("", source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: can't re-join existing IGMP group %s source %s on interface %s", + __PRETTY_FUNCTION__, group_str, source_str, ifp->name); + return -3; + } + + ij = igmp_join_new(ifp, group_addr, source_addr); + if (!ij) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("", source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: igmp_join_new() failure for IGMP group %s source %s on interface %s", + __PRETTY_FUNCTION__, group_str, source_str, ifp->name); + return -4; + } + + if (PIM_DEBUG_IGMP_EVENTS) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("", source_addr, source_str, + sizeof(source_str)); + zlog_debug( + "%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s", + __PRETTY_FUNCTION__, source_str, group_str, ifp->name); + } + return 0; +} -int pim_if_igmp_join_del(struct interface *ifp, - struct in_addr group_addr, +int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr, struct in_addr source_addr) { - struct pim_interface *pim_ifp; - struct igmp_join *ij; - - pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - ifp->name); - return -1; - } - - if (!pim_ifp->igmp_join_list) { - zlog_warn("%s: no IGMP join on interface %s", - __PRETTY_FUNCTION__, - ifp->name); - return -2; - } - - ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr); - if (!ij) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: could not find IGMP group %s source %s on interface %s", - __PRETTY_FUNCTION__, - group_str, source_str, ifp->name); - return -3; - } - - if (close(ij->sock_fd)) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s", - __PRETTY_FUNCTION__, - ij->sock_fd, group_str, source_str, ifp->name, errno, safe_strerror(errno)); - /* warning only */ - } - listnode_delete(pim_ifp->igmp_join_list, ij); - igmp_join_free(ij); - if (listcount(pim_ifp->igmp_join_list) < 1) { - list_delete(pim_ifp->igmp_join_list); - pim_ifp->igmp_join_list = 0; - } - - return 0; + struct pim_interface *pim_ifp; + struct igmp_join *ij; + + pim_ifp = ifp->info; + if (!pim_ifp) { + zlog_warn("%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, ifp->name); + return -1; + } + + if (!pim_ifp->igmp_join_list) { + zlog_warn("%s: no IGMP join on interface %s", + __PRETTY_FUNCTION__, ifp->name); + return -2; + } + + ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr); + if (!ij) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("", source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: could not find IGMP group %s source %s on interface %s", + __PRETTY_FUNCTION__, group_str, source_str, ifp->name); + return -3; + } + + if (close(ij->sock_fd)) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("", source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s", + __PRETTY_FUNCTION__, ij->sock_fd, group_str, source_str, + ifp->name, errno, safe_strerror(errno)); + /* warning only */ + } + listnode_delete(pim_ifp->igmp_join_list, ij); + igmp_join_free(ij); + if (listcount(pim_ifp->igmp_join_list) < 1) { + list_delete(pim_ifp->igmp_join_list); + pim_ifp->igmp_join_list = 0; + } + + return 0; } static void pim_if_igmp_join_del_all(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *nextnode; - struct igmp_join *ij; - - pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - ifp->name); - return; - } - - if (!pim_ifp->igmp_join_list) - return; - - for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node, nextnode, ij)) - pim_if_igmp_join_del(ifp, ij->group_addr, ij->source_addr); + struct pim_interface *pim_ifp; + struct listnode *node; + struct listnode *nextnode; + struct igmp_join *ij; + + pim_ifp = ifp->info; + if (!pim_ifp) { + zlog_warn("%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, ifp->name); + return; + } + + if (!pim_ifp->igmp_join_list) + return; + + for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node, nextnode, ij)) + pim_if_igmp_join_del(ifp, ij->group_addr, ij->source_addr); } /* @@ -1475,63 +1495,66 @@ static void pim_if_igmp_join_del_all(struct interface *ifp) void pim_if_assert_on_neighbor_down(struct interface *ifp, struct in_addr neigh_addr) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *next_node; - struct pim_ifchannel *ch; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, ch)) { - /* Is (S,G,I) assert loser ? */ - if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) - continue; - /* Dead neighbor was winner ? */ - if (ch->ifassert_winner.s_addr != neigh_addr.s_addr) - continue; - - assert_action_a5(ch); - } + struct pim_interface *pim_ifp; + struct listnode *node; + struct listnode *next_node; + struct pim_ifchannel *ch; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, + ch)) { + /* Is (S,G,I) assert loser ? */ + if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) + continue; + /* Dead neighbor was winner ? */ + if (ch->ifassert_winner.s_addr != neigh_addr.s_addr) + continue; + + assert_action_a5(ch); + } } void pim_if_update_join_desired(struct pim_interface *pim_ifp) { - struct listnode *ch_node; - struct pim_ifchannel *ch; + struct listnode *ch_node; + struct pim_ifchannel *ch; - /* clear off flag from interface's upstreams */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(ch->upstream->flags); - } + /* clear off flag from interface's upstreams */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { + PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED( + ch->upstream->flags); + } - /* scan per-interface (S,G,I) state on this I interface */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - struct pim_upstream *up = ch->upstream; + /* scan per-interface (S,G,I) state on this I interface */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { + struct pim_upstream *up = ch->upstream; - if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up->flags)) - continue; + if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up->flags)) + continue; - /* update join_desired for the global (S,G) state */ - pim_upstream_update_join_desired(up); - PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up->flags); - } + /* update join_desired for the global (S,G) state */ + pim_upstream_update_join_desired(up); + PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up->flags); + } } void pim_if_update_assert_tracking_desired(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *next_node; - struct pim_ifchannel *ch; - - pim_ifp = ifp->info; - if (!pim_ifp) - return; - - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, ch)) { - pim_ifchannel_update_assert_tracking_desired(ch); - } + struct pim_interface *pim_ifp; + struct listnode *node; + struct listnode *next_node; + struct pim_ifchannel *ch; + + pim_ifp = ifp->info; + if (!pim_ifp) + return; + + for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, + ch)) { + pim_ifchannel_update_assert_tracking_desired(ch); + } } /* @@ -1539,52 +1562,48 @@ void pim_if_update_assert_tracking_desired(struct interface *ifp) * The pimreg is a special interface that we have that is not * quite an inteface but a VIF is created for it. */ -void pim_if_create_pimreg (void) +void pim_if_create_pimreg(void) { - if (!pim_regiface) { - pim_regiface = if_create("pimreg", strlen("pimreg"), VRF_DEFAULT); - pim_regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF; + if (!pim_regiface) { + pim_regiface = + if_create("pimreg", strlen("pimreg"), VRF_DEFAULT); + pim_regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF; - pim_if_new(pim_regiface, 0, 0); - } + pim_if_new(pim_regiface, 0, 0); + } } -int -pim_if_connected_to_source (struct interface *ifp, struct in_addr src) +int pim_if_connected_to_source(struct interface *ifp, struct in_addr src) { - struct listnode *cnode; - struct connected *c; - struct prefix p; - - if (!ifp) - return 0; - - p.family = AF_INET; - p.u.prefix4 = src; - p.prefixlen = IPV4_MAX_BITLEN; - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) - { - if ((c->address->family == AF_INET) && - prefix_match (CONNECTED_PREFIX (c), &p)) - { - return 1; - } - } - - return 0; + struct listnode *cnode; + struct connected *c; + struct prefix p; + + if (!ifp) + return 0; + + p.family = AF_INET; + p.u.prefix4 = src; + p.prefixlen = IPV4_MAX_BITLEN; + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { + if ((c->address->family == AF_INET) + && prefix_match(CONNECTED_PREFIX(c), &p)) { + return 1; + } + } + + return 0; } -struct interface * -pim_if_lookup_address_vrf (struct in_addr src, vrf_id_t vrf_id) +struct interface *pim_if_lookup_address_vrf(struct in_addr src, vrf_id_t vrf_id) { - struct listnode *ifnode; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist(vrf_id), ifnode, ifp)) - { - if (pim_if_connected_to_source (ifp, src) && ifp->info) - return ifp; - } - return NULL; + struct listnode *ifnode; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), ifnode, ifp)) { + if (pim_if_connected_to_source(ifp, src) && ifp->info) + return ifp; + } + return NULL; } diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index a1c2b692f..e742e68f6 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -56,81 +56,86 @@ #define PIM_I_am_DR(pim_ifp) (pim_ifp)->pim_dr_addr.s_addr == (pim_ifp)->primary_address.s_addr struct pim_iface_upstream_switch { - struct in_addr address; - struct list *us; + struct in_addr address; + struct list *us; }; enum pim_secondary_addr_flags { - PIM_SEC_ADDRF_NONE = 0, - PIM_SEC_ADDRF_STALE = (1 << 0) + PIM_SEC_ADDRF_NONE = 0, + PIM_SEC_ADDRF_STALE = (1 << 0) }; struct pim_secondary_addr { - struct prefix addr; - enum pim_secondary_addr_flags flags; + struct prefix addr; + enum pim_secondary_addr_flags flags; }; struct pim_interface { - uint32_t options; /* bit vector */ - ifindex_t mroute_vif_index; - struct in_addr primary_address; /* remember addr to detect change */ - struct list *sec_addr_list; /* list of struct pim_secondary_addr */ - struct in_addr update_source; /* user can statically set the primary - * address of the interface */ - - int igmp_version; /* IGMP version */ - int igmp_default_robustness_variable; /* IGMPv3 QRV */ - int igmp_default_query_interval; /* IGMPv3 secs between general queries */ - int igmp_query_max_response_time_dsec; /* IGMPv3 Max Response Time in dsecs for general queries */ - int igmp_specific_query_max_response_time_dsec; /* IGMPv3 Max Response Time in dsecs for specific queries */ - struct list *igmp_socket_list; /* list of struct igmp_sock */ - struct list *igmp_join_list; /* list of struct igmp_join */ - - int pim_sock_fd; /* PIM socket file descriptor */ - struct thread *t_pim_sock_read; /* thread for reading PIM socket */ - int64_t pim_sock_creation; /* timestamp of PIM socket creation */ - - struct thread *t_pim_hello_timer; - int pim_hello_period; - int pim_default_holdtime; - int pim_triggered_hello_delay; - uint32_t pim_generation_id; - uint16_t pim_propagation_delay_msec; /* config */ - uint16_t pim_override_interval_msec; /* config */ - struct list *pim_neighbor_list; /* list of struct pim_neighbor */ - struct list *upstream_switch_list; - struct list *pim_ifchannel_list; /* list of struct pim_ifchannel */ - struct hash *pim_ifchannel_hash; - - /* neighbors without lan_delay */ - int pim_number_of_nonlandelay_neighbors; - uint16_t pim_neighbors_highest_propagation_delay_msec; - uint16_t pim_neighbors_highest_override_interval_msec; - - /* DR Election */ - int64_t pim_dr_election_last; /* timestamp */ - int pim_dr_election_count; - int pim_dr_election_changes; - struct in_addr pim_dr_addr; - uint32_t pim_dr_priority; /* config */ - int pim_dr_num_nondrpri_neighbors; /* neighbors without dr_pri */ - - int64_t pim_ifstat_start; /* start timestamp for stats */ - uint32_t pim_ifstat_hello_sent; - uint32_t pim_ifstat_hello_sendfail; - uint32_t pim_ifstat_hello_recv; - uint32_t pim_ifstat_hello_recvfail; - uint32_t pim_ifstat_join_recv; - uint32_t pim_ifstat_join_send; - uint32_t pim_ifstat_prune_recv; - uint32_t pim_ifstat_prune_send; - uint32_t pim_ifstat_reg_recv; - uint32_t pim_ifstat_reg_send; - uint32_t pim_ifstat_reg_stop_recv; - uint32_t pim_ifstat_reg_stop_send; - uint32_t pim_ifstat_assert_recv; - uint32_t pim_ifstat_assert_send; - struct bfd_info *bfd_info; + uint32_t options; /* bit vector */ + ifindex_t mroute_vif_index; + struct in_addr primary_address; /* remember addr to detect change */ + struct list *sec_addr_list; /* list of struct pim_secondary_addr */ + struct in_addr update_source; /* user can statically set the primary + * address of the interface */ + + int igmp_version; /* IGMP version */ + int igmp_default_robustness_variable; /* IGMPv3 QRV */ + int + igmp_default_query_interval; /* IGMPv3 secs between general + queries */ + int igmp_query_max_response_time_dsec; /* IGMPv3 Max Response Time in + dsecs for general queries */ + int igmp_specific_query_max_response_time_dsec; /* IGMPv3 Max Response + Time in dsecs for + specific queries */ + struct list *igmp_socket_list; /* list of struct igmp_sock */ + struct list *igmp_join_list; /* list of struct igmp_join */ + + int pim_sock_fd; /* PIM socket file descriptor */ + struct thread *t_pim_sock_read; /* thread for reading PIM socket */ + int64_t pim_sock_creation; /* timestamp of PIM socket creation */ + + struct thread *t_pim_hello_timer; + int pim_hello_period; + int pim_default_holdtime; + int pim_triggered_hello_delay; + uint32_t pim_generation_id; + uint16_t pim_propagation_delay_msec; /* config */ + uint16_t pim_override_interval_msec; /* config */ + struct list *pim_neighbor_list; /* list of struct pim_neighbor */ + struct list *upstream_switch_list; + struct list *pim_ifchannel_list; /* list of struct pim_ifchannel */ + struct hash *pim_ifchannel_hash; + + /* neighbors without lan_delay */ + int pim_number_of_nonlandelay_neighbors; + uint16_t pim_neighbors_highest_propagation_delay_msec; + uint16_t pim_neighbors_highest_override_interval_msec; + + /* DR Election */ + int64_t pim_dr_election_last; /* timestamp */ + int pim_dr_election_count; + int pim_dr_election_changes; + struct in_addr pim_dr_addr; + uint32_t pim_dr_priority; /* config */ + int pim_dr_num_nondrpri_neighbors; /* neighbors without dr_pri */ + + int64_t pim_ifstat_start; /* start timestamp for stats */ + uint32_t pim_ifstat_hello_sent; + uint32_t pim_ifstat_hello_sendfail; + uint32_t pim_ifstat_hello_recv; + uint32_t pim_ifstat_hello_recvfail; + uint32_t pim_ifstat_join_recv; + uint32_t pim_ifstat_join_send; + uint32_t pim_ifstat_prune_recv; + uint32_t pim_ifstat_prune_send; + uint32_t pim_ifstat_reg_recv; + uint32_t pim_ifstat_reg_send; + uint32_t pim_ifstat_reg_stop_recv; + uint32_t pim_ifstat_reg_stop_send; + uint32_t pim_ifstat_assert_recv; + uint32_t pim_ifstat_assert_send; + struct bfd_info *bfd_info; }; extern struct interface *pim_regiface; @@ -139,16 +144,16 @@ extern struct list *pim_ifchannel_list; if default_holdtime is set (>= 0), use it; otherwise default_holdtime is 3.5 * hello_period */ -#define PIM_IF_DEFAULT_HOLDTIME(pim_ifp) \ - (((pim_ifp)->pim_default_holdtime < 0) ? \ - ((pim_ifp)->pim_hello_period * 7 / 2) : \ - ((pim_ifp)->pim_default_holdtime)) +#define PIM_IF_DEFAULT_HOLDTIME(pim_ifp) \ + (((pim_ifp)->pim_default_holdtime < 0) \ + ? ((pim_ifp)->pim_hello_period * 7 / 2) \ + : ((pim_ifp)->pim_default_holdtime)) void pim_if_init(void); -void pim_if_terminate (void); +void pim_if_terminate(void); struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim); -void pim_if_delete(struct interface *ifp); +void pim_if_delete(struct interface *ifp); void pim_if_addr_add(struct connected *ifc); void pim_if_addr_del(struct connected *ifc, int force_prim_as_any); void pim_if_addr_add_all(struct interface *ifp); @@ -156,7 +161,8 @@ void pim_if_addr_del_all(struct interface *ifp); void pim_if_addr_del_all_igmp(struct interface *ifp); void pim_if_addr_del_all_pim(struct interface *ifp); -struct interface *pim_if_lookup_address_vrf (struct in_addr src, vrf_id_t vrf_id); +struct interface *pim_if_lookup_address_vrf(struct in_addr src, + vrf_id_t vrf_id); int pim_if_add_vif(struct interface *ifp); int pim_if_del_vif(struct interface *ifp); @@ -178,11 +184,9 @@ int pim_if_t_override_msec(struct interface *ifp); struct in_addr pim_find_primary_addr(struct interface *ifp); -int pim_if_igmp_join_add(struct interface *ifp, - struct in_addr group_addr, +int pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr, struct in_addr source_addr); -int pim_if_igmp_join_del(struct interface *ifp, - struct in_addr group_addr, +int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr, struct in_addr source_addr); void pim_if_update_could_assert(struct interface *ifp); @@ -199,7 +203,7 @@ void pim_if_update_assert_tracking_desired(struct interface *ifp); void pim_if_create_pimreg(void); -int pim_if_connected_to_source (struct interface *ifp, struct in_addr src); +int pim_if_connected_to_source(struct interface *ifp, struct in_addr src); int pim_update_source_set(struct interface *ifp, struct in_addr source); #endif /* PIM_IFACE_H */ diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 021722dfc..d4916518e 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -43,34 +43,33 @@ #include "pim_upstream.h" #include "pim_ssm.h" -int -pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2) +int pim_ifchannel_compare(struct pim_ifchannel *ch1, struct pim_ifchannel *ch2) { - struct pim_interface *pim_ifp1; - struct pim_interface *pim_ifp2; + struct pim_interface *pim_ifp1; + struct pim_interface *pim_ifp2; - pim_ifp1 = ch1->interface->info; - pim_ifp2 = ch2->interface->info; + pim_ifp1 = ch1->interface->info; + pim_ifp2 = ch2->interface->info; - if (pim_ifp1->mroute_vif_index < pim_ifp2->mroute_vif_index) - return -1; + if (pim_ifp1->mroute_vif_index < pim_ifp2->mroute_vif_index) + return -1; - if (pim_ifp1->mroute_vif_index > pim_ifp2->mroute_vif_index) - return 1; + if (pim_ifp1->mroute_vif_index > pim_ifp2->mroute_vif_index) + return 1; - if (ntohl(ch1->sg.grp.s_addr) < ntohl(ch2->sg.grp.s_addr)) - return -1; + if (ntohl(ch1->sg.grp.s_addr) < ntohl(ch2->sg.grp.s_addr)) + return -1; - if (ntohl(ch1->sg.grp.s_addr) > ntohl(ch2->sg.grp.s_addr)) - return 1; + if (ntohl(ch1->sg.grp.s_addr) > ntohl(ch2->sg.grp.s_addr)) + return 1; - if (ntohl(ch1->sg.src.s_addr) < ntohl(ch2->sg.src.s_addr)) - return -1; + if (ntohl(ch1->sg.src.s_addr) < ntohl(ch2->sg.src.s_addr)) + return -1; - if (ntohl(ch1->sg.src.s_addr) > ntohl(ch2->sg.src.s_addr)) - return 1; + if (ntohl(ch1->sg.src.s_addr) > ntohl(ch2->sg.src.s_addr)) + return 1; - return 0; + return 0; } /* @@ -78,20 +77,18 @@ pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2) * remove the parent pointer from * those pointing at us */ -static void -pim_ifchannel_remove_children (struct pim_ifchannel *ch) +static void pim_ifchannel_remove_children(struct pim_ifchannel *ch) { - struct pim_ifchannel *child; + struct pim_ifchannel *child; - if (!ch->sources) - return; + if (!ch->sources) + return; - while (!list_isempty (ch->sources)) - { - child = listnode_head (ch->sources); - child->parent = NULL; - listnode_delete (ch->sources, child); - } + while (!list_isempty(ch->sources)) { + child = listnode_head(ch->sources); + child->parent = NULL; + listnode_delete(ch->sources, child); + } } /* @@ -99,284 +96,302 @@ pim_ifchannel_remove_children (struct pim_ifchannel *ch) * find all the children that would point * at us. */ -static void -pim_ifchannel_find_new_children (struct pim_ifchannel *ch) +static void pim_ifchannel_find_new_children(struct pim_ifchannel *ch) { - struct pim_interface *pim_ifp = ch->interface->info; - struct pim_ifchannel *child; - struct listnode *ch_node; - - // Basic Sanity that we are not being silly - if ((ch->sg.src.s_addr != INADDR_ANY) && - (ch->sg.grp.s_addr != INADDR_ANY)) - return; - - if ((ch->sg.src.s_addr == INADDR_ANY) && - (ch->sg.grp.s_addr == INADDR_ANY)) - return; - - for (ALL_LIST_ELEMENTS_RO (pim_ifp->pim_ifchannel_list, ch_node, child)) - { - if ((ch->sg.grp.s_addr != INADDR_ANY) && - (child->sg.grp.s_addr == ch->sg.grp.s_addr) && - (child != ch)) - { - child->parent = ch; - listnode_add_sort (ch->sources, child); + struct pim_interface *pim_ifp = ch->interface->info; + struct pim_ifchannel *child; + struct listnode *ch_node; + + // Basic Sanity that we are not being silly + if ((ch->sg.src.s_addr != INADDR_ANY) + && (ch->sg.grp.s_addr != INADDR_ANY)) + return; + + if ((ch->sg.src.s_addr == INADDR_ANY) + && (ch->sg.grp.s_addr == INADDR_ANY)) + return; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, + child)) { + if ((ch->sg.grp.s_addr != INADDR_ANY) + && (child->sg.grp.s_addr == ch->sg.grp.s_addr) + && (child != ch)) { + child->parent = ch; + listnode_add_sort(ch->sources, child); + } } - } } void pim_ifchannel_free(struct pim_ifchannel *ch) { - XFREE(MTYPE_PIM_IFCHANNEL, ch); + XFREE(MTYPE_PIM_IFCHANNEL, ch); } void pim_ifchannel_delete(struct pim_ifchannel *ch) { - struct pim_interface *pim_ifp; - - pim_ifp = ch->interface->info; - - if (ch->upstream->channel_oil) - { - uint32_t mask = PIM_OIF_FLAG_PROTO_PIM; - if (ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) - mask = PIM_OIF_FLAG_PROTO_IGMP; - - /* SGRpt entry could have empty oil */ - if (ch->upstream->channel_oil) - pim_channel_del_oif (ch->upstream->channel_oil, ch->interface, mask); - /* - * Do we have any S,G's that are inheriting? - * Nuke from on high too. - */ - if (ch->upstream->sources) - { - struct pim_upstream *child; - struct listnode *up_node; - - for (ALL_LIST_ELEMENTS_RO (ch->upstream->sources, up_node, child)) - pim_channel_del_oif (child->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); + struct pim_interface *pim_ifp; + + pim_ifp = ch->interface->info; + + if (ch->upstream->channel_oil) { + uint32_t mask = PIM_OIF_FLAG_PROTO_PIM; + if (ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) + mask = PIM_OIF_FLAG_PROTO_IGMP; + + /* SGRpt entry could have empty oil */ + if (ch->upstream->channel_oil) + pim_channel_del_oif(ch->upstream->channel_oil, + ch->interface, mask); + /* + * Do we have any S,G's that are inheriting? + * Nuke from on high too. + */ + if (ch->upstream->sources) { + struct pim_upstream *child; + struct listnode *up_node; + + for (ALL_LIST_ELEMENTS_RO(ch->upstream->sources, + up_node, child)) + pim_channel_del_oif(child->channel_oil, + ch->interface, + PIM_OIF_FLAG_PROTO_STAR); + } + } + + /* + * When this channel is removed + * we need to find all our children + * and make sure our pointers are fixed + */ + pim_ifchannel_remove_children(ch); + + if (ch->sources) + list_delete(ch->sources); + + listnode_delete(ch->upstream->ifchannels, ch); + + if (ch->ifjoin_state != PIM_IFJOIN_NOINFO) { + pim_upstream_update_join_desired(ch->upstream); } - } - - /* - * When this channel is removed - * we need to find all our children - * and make sure our pointers are fixed - */ - pim_ifchannel_remove_children (ch); - - if (ch->sources) - list_delete (ch->sources); - - listnode_delete(ch->upstream->ifchannels, ch); - - if (ch->ifjoin_state != PIM_IFJOIN_NOINFO) { - pim_upstream_update_join_desired(ch->upstream); - } - - /* upstream is common across ifchannels, check if upstream's - ifchannel list is empty before deleting upstream_del - ref count will take care of it. - */ - pim_upstream_del(ch->upstream, __PRETTY_FUNCTION__); - ch->upstream = NULL; - - THREAD_OFF(ch->t_ifjoin_expiry_timer); - THREAD_OFF(ch->t_ifjoin_prune_pending_timer); - THREAD_OFF(ch->t_ifassert_timer); - - if (ch->parent) - { - listnode_delete (ch->parent->sources, ch); - ch->parent = NULL; - } - /* - notice that listnode_delete() can't be moved - into pim_ifchannel_free() because the later is - called by list_delete_all_node() - */ - listnode_delete(pim_ifp->pim_ifchannel_list, ch); - hash_release(pim_ifp->pim_ifchannel_hash, ch); - listnode_delete(pim_ifchannel_list, ch); - - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s: ifchannel entry %s is deleted ", __PRETTY_FUNCTION__, ch->sg_str); - - pim_ifchannel_free(ch); + + /* upstream is common across ifchannels, check if upstream's + ifchannel list is empty before deleting upstream_del + ref count will take care of it. + */ + pim_upstream_del(ch->upstream, __PRETTY_FUNCTION__); + ch->upstream = NULL; + + THREAD_OFF(ch->t_ifjoin_expiry_timer); + THREAD_OFF(ch->t_ifjoin_prune_pending_timer); + THREAD_OFF(ch->t_ifassert_timer); + + if (ch->parent) { + listnode_delete(ch->parent->sources, ch); + ch->parent = NULL; + } + /* + notice that listnode_delete() can't be moved + into pim_ifchannel_free() because the later is + called by list_delete_all_node() + */ + listnode_delete(pim_ifp->pim_ifchannel_list, ch); + hash_release(pim_ifp->pim_ifchannel_hash, ch); + listnode_delete(pim_ifchannel_list, ch); + + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: ifchannel entry %s is deleted ", + __PRETTY_FUNCTION__, ch->sg_str); + + pim_ifchannel_free(ch); } -void -pim_ifchannel_delete_all (struct interface *ifp) +void pim_ifchannel_delete_all(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *ifchannel_node; - struct listnode *ifchannel_nextnode; - struct pim_ifchannel *ifchannel; - - pim_ifp = ifp->info; - if (!pim_ifp) - return; - - for (ALL_LIST_ELEMENTS (pim_ifp->pim_ifchannel_list, ifchannel_node, - ifchannel_nextnode, ifchannel)) - { - pim_ifchannel_delete (ifchannel); - } + struct pim_interface *pim_ifp; + struct listnode *ifchannel_node; + struct listnode *ifchannel_nextnode; + struct pim_ifchannel *ifchannel; + + pim_ifp = ifp->info; + if (!pim_ifp) + return; + + for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, ifchannel_node, + ifchannel_nextnode, ifchannel)) { + pim_ifchannel_delete(ifchannel); + } } - + static void delete_on_noinfo(struct pim_ifchannel *ch) { - if (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO && - ch->ifjoin_state == PIM_IFJOIN_NOINFO && - ch->t_ifjoin_expiry_timer == NULL) - pim_ifchannel_delete(ch); - + if (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO + && ch->ifjoin_state == PIM_IFJOIN_NOINFO + && ch->t_ifjoin_expiry_timer == NULL) + pim_ifchannel_delete(ch); } -void pim_ifchannel_ifjoin_switch(const char *caller, - struct pim_ifchannel *ch, +void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch, enum pim_ifjoin_state new_state) { - enum pim_ifjoin_state old_state = ch->ifjoin_state; - - if (PIM_DEBUG_PIM_EVENTS) - zlog_debug ("PIM_IFCHANNEL(%s): %s is switching from %s to %s", - ch->interface->name, - ch->sg_str, - pim_ifchannel_ifjoin_name (ch->ifjoin_state, ch->flags), - pim_ifchannel_ifjoin_name (new_state, 0)); - - - if (old_state == new_state) { - if (PIM_DEBUG_PIM_EVENTS) { - zlog_debug("%s calledby %s: non-transition on state %d (%s)", - __PRETTY_FUNCTION__, caller, new_state, - pim_ifchannel_ifjoin_name(new_state, 0)); - } - return; - } - - ch->ifjoin_state = new_state; - - if (ch->sg.src.s_addr == INADDR_ANY) - { - struct pim_upstream *up = ch->upstream; - struct pim_upstream *child; - struct listnode *up_node; - - if (up) - { - if (ch->ifjoin_state == PIM_IFJOIN_NOINFO) - { - for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) - { - struct channel_oil *c_oil = child->channel_oil; - struct pim_interface *pim_ifp = ch->interface->info; - - if (PIM_DEBUG_PIM_TRACE) - zlog_debug("%s %s: Prune(S,G)=%s from %s", - __FILE__, __PRETTY_FUNCTION__, - child->sg_str, up->sg_str); - if (!c_oil) - continue; - - if (!pim_upstream_evaluate_join_desired (child)) - { - pim_channel_del_oif (c_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); - pim_upstream_update_join_desired (child); - } - - /* - * If the S,G has no if channel and the c_oil still - * has output here then the *,G was supplying the implied - * if channel. So remove it. - * I think this is dead code now. is it? - */ - if (!ch && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) - pim_channel_del_oif (c_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); + enum pim_ifjoin_state old_state = ch->ifjoin_state; + + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug( + "PIM_IFCHANNEL(%s): %s is switching from %s to %s", + ch->interface->name, ch->sg_str, + pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags), + pim_ifchannel_ifjoin_name(new_state, 0)); + + + if (old_state == new_state) { + if (PIM_DEBUG_PIM_EVENTS) { + zlog_debug( + "%s calledby %s: non-transition on state %d (%s)", + __PRETTY_FUNCTION__, caller, new_state, + pim_ifchannel_ifjoin_name(new_state, 0)); } - } - if (ch->ifjoin_state == PIM_IFJOIN_JOIN) - { - for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) - { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug("%s %s: Join(S,G)=%s from %s", - __FILE__, __PRETTY_FUNCTION__, - child->sg_str, up->sg_str); - - if (pim_upstream_evaluate_join_desired (child)) - { - pim_channel_add_oif (child->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); - pim_upstream_update_join_desired (child); - } + return; + } + + ch->ifjoin_state = new_state; + + if (ch->sg.src.s_addr == INADDR_ANY) { + struct pim_upstream *up = ch->upstream; + struct pim_upstream *child; + struct listnode *up_node; + + if (up) { + if (ch->ifjoin_state == PIM_IFJOIN_NOINFO) { + for (ALL_LIST_ELEMENTS_RO(up->sources, up_node, + child)) { + struct channel_oil *c_oil = + child->channel_oil; + struct pim_interface *pim_ifp = + ch->interface->info; + + if (PIM_DEBUG_PIM_TRACE) + zlog_debug( + "%s %s: Prune(S,G)=%s from %s", + __FILE__, + __PRETTY_FUNCTION__, + child->sg_str, + up->sg_str); + if (!c_oil) + continue; + + if (!pim_upstream_evaluate_join_desired( + child)) { + pim_channel_del_oif( + c_oil, ch->interface, + PIM_OIF_FLAG_PROTO_STAR); + pim_upstream_update_join_desired( + child); + } + + /* + * If the S,G has no if channel and the + * c_oil still + * has output here then the *,G was + * supplying the implied + * if channel. So remove it. + * I think this is dead code now. is it? + */ + if (!ch + && c_oil->oil.mfcc_ttls + [pim_ifp->mroute_vif_index]) + pim_channel_del_oif( + c_oil, ch->interface, + PIM_OIF_FLAG_PROTO_STAR); + } + } + if (ch->ifjoin_state == PIM_IFJOIN_JOIN) { + for (ALL_LIST_ELEMENTS_RO(up->sources, up_node, + child)) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug( + "%s %s: Join(S,G)=%s from %s", + __FILE__, + __PRETTY_FUNCTION__, + child->sg_str, + up->sg_str); + + if (pim_upstream_evaluate_join_desired( + child)) { + pim_channel_add_oif( + child->channel_oil, + ch->interface, + PIM_OIF_FLAG_PROTO_STAR); + pim_upstream_update_join_desired( + child); + } + } + } } - } } - } - /* Transition to/from NOINFO ? */ - if ((old_state == PIM_IFJOIN_NOINFO) || - (new_state == PIM_IFJOIN_NOINFO)) { - - if (PIM_DEBUG_PIM_EVENTS) { - zlog_debug("PIM_IFCHANNEL_%s: (S,G)=%s on interface %s", - ((new_state == PIM_IFJOIN_NOINFO) ? "DOWN" : "UP"), - ch->sg_str, ch->interface->name); - } - - /* - Record uptime of state transition to/from NOINFO - */ - ch->ifjoin_creation = pim_time_monotonic_sec(); - - pim_upstream_update_join_desired(ch->upstream); - pim_ifchannel_update_could_assert(ch); - pim_ifchannel_update_assert_tracking_desired(ch); - } + /* Transition to/from NOINFO ? */ + if ((old_state == PIM_IFJOIN_NOINFO) + || (new_state == PIM_IFJOIN_NOINFO)) { + + if (PIM_DEBUG_PIM_EVENTS) { + zlog_debug("PIM_IFCHANNEL_%s: (S,G)=%s on interface %s", + ((new_state == PIM_IFJOIN_NOINFO) ? "DOWN" + : "UP"), + ch->sg_str, ch->interface->name); + } + + /* + Record uptime of state transition to/from NOINFO + */ + ch->ifjoin_creation = pim_time_monotonic_sec(); + + pim_upstream_update_join_desired(ch->upstream); + pim_ifchannel_update_could_assert(ch); + pim_ifchannel_update_assert_tracking_desired(ch); + } } const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state, - int flags) + int flags) { - switch (ifjoin_state) { - case PIM_IFJOIN_NOINFO: - if (PIM_IF_FLAG_TEST_S_G_RPT(flags)) - return "SGRpt"; - else - return "NOINFO"; - break; - case PIM_IFJOIN_JOIN: - return "JOIN"; - break; - case PIM_IFJOIN_PRUNE: - return "PRUNE"; - break; - case PIM_IFJOIN_PRUNE_PENDING: - return "PRUNEP"; - break; - case PIM_IFJOIN_PRUNE_TMP: - return "PRUNET"; - break; - case PIM_IFJOIN_PRUNE_PENDING_TMP: - return "PRUNEPT"; - break; - } - - return "ifjoin_bad_state"; + switch (ifjoin_state) { + case PIM_IFJOIN_NOINFO: + if (PIM_IF_FLAG_TEST_S_G_RPT(flags)) + return "SGRpt"; + else + return "NOINFO"; + break; + case PIM_IFJOIN_JOIN: + return "JOIN"; + break; + case PIM_IFJOIN_PRUNE: + return "PRUNE"; + break; + case PIM_IFJOIN_PRUNE_PENDING: + return "PRUNEP"; + break; + case PIM_IFJOIN_PRUNE_TMP: + return "PRUNET"; + break; + case PIM_IFJOIN_PRUNE_PENDING_TMP: + return "PRUNEPT"; + break; + } + + return "ifjoin_bad_state"; } const char *pim_ifchannel_ifassert_name(enum pim_ifassert_state ifassert_state) { - switch (ifassert_state) { - case PIM_IFASSERT_NOINFO: return "NOINFO"; - case PIM_IFASSERT_I_AM_WINNER: return "WINNER"; - case PIM_IFASSERT_I_AM_LOSER: return "LOSER"; - } + switch (ifassert_state) { + case PIM_IFASSERT_NOINFO: + return "NOINFO"; + case PIM_IFASSERT_I_AM_WINNER: + return "WINNER"; + case PIM_IFASSERT_I_AM_LOSER: + return "LOSER"; + } - return "ifassert_bad_state"; + return "ifassert_bad_state"; } /* @@ -387,88 +402,85 @@ const char *pim_ifchannel_ifassert_name(enum pim_ifassert_state ifassert_state) */ void reset_ifassert_state(struct pim_ifchannel *ch) { - struct in_addr any = { .s_addr = INADDR_ANY }; + struct in_addr any = {.s_addr = INADDR_ANY}; - THREAD_OFF(ch->t_ifassert_timer); + THREAD_OFF(ch->t_ifassert_timer); - pim_ifassert_winner_set(ch, - PIM_IFASSERT_NOINFO, - any, - qpim_infinite_assert_metric); + pim_ifassert_winner_set(ch, PIM_IFASSERT_NOINFO, any, + qpim_infinite_assert_metric); } struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp, struct prefix_sg *sg) { - struct pim_interface *pim_ifp; - struct pim_ifchannel *ch; - struct pim_ifchannel lookup; + struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; + struct pim_ifchannel lookup; - pim_ifp = ifp->info; + pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump (sg), - ifp->name); - return NULL; - } + if (!pim_ifp) { + zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(sg), ifp->name); + return NULL; + } - lookup.sg = *sg; - ch = hash_lookup (pim_ifp->pim_ifchannel_hash, &lookup); + lookup.sg = *sg; + ch = hash_lookup(pim_ifp->pim_ifchannel_hash, &lookup); - return ch; + return ch; } static void ifmembership_set(struct pim_ifchannel *ch, enum pim_ifmembership membership) { - if (ch->local_ifmembership == membership) - return; - - if (PIM_DEBUG_PIM_EVENTS) { - zlog_debug("%s: (S,G)=%s membership now is %s on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, - membership == PIM_IFMEMBERSHIP_INCLUDE ? "INCLUDE" : "NOINFO", - ch->interface->name); - } - - ch->local_ifmembership = membership; - - pim_upstream_update_join_desired(ch->upstream); - pim_ifchannel_update_could_assert(ch); - pim_ifchannel_update_assert_tracking_desired(ch); + if (ch->local_ifmembership == membership) + return; + + if (PIM_DEBUG_PIM_EVENTS) { + zlog_debug("%s: (S,G)=%s membership now is %s on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, + membership == PIM_IFMEMBERSHIP_INCLUDE ? "INCLUDE" + : "NOINFO", + ch->interface->name); + } + + ch->local_ifmembership = membership; + + pim_upstream_update_join_desired(ch->upstream); + pim_ifchannel_update_could_assert(ch); + pim_ifchannel_update_assert_tracking_desired(ch); } void pim_ifchannel_membership_clear(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *ch_node; - struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; + struct listnode *ch_node; + struct pim_ifchannel *ch; - pim_ifp = ifp->info; - zassert(pim_ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { - ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); - } + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) { + ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); + } } void pim_ifchannel_delete_on_noinfo(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *next_node; - struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; + struct listnode *node; + struct listnode *next_node; + struct pim_ifchannel *ch; - pim_ifp = ifp->info; - zassert(pim_ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, ch)) { - delete_on_noinfo(ch); - } + for (ALL_LIST_ELEMENTS(pim_ifp->pim_ifchannel_list, node, next_node, + ch)) { + delete_on_noinfo(ch); + } } /* @@ -477,682 +489,687 @@ void pim_ifchannel_delete_on_noinfo(struct interface *ifp) * If we are passed a *,G, find the *,* ifchannel * if we have it. */ -static struct pim_ifchannel * -pim_ifchannel_find_parent (struct pim_ifchannel *ch) +static struct pim_ifchannel *pim_ifchannel_find_parent(struct pim_ifchannel *ch) { - struct prefix_sg parent_sg = ch->sg; - struct pim_ifchannel *parent = NULL; - - // (S,G) - if ((parent_sg.src.s_addr != INADDR_ANY) && - (parent_sg.grp.s_addr != INADDR_ANY)) - { - parent_sg.src.s_addr = INADDR_ANY; - parent = pim_ifchannel_find (ch->interface, &parent_sg); - - if (parent) - listnode_add (parent->sources, ch); - return parent; - } - - return NULL; + struct prefix_sg parent_sg = ch->sg; + struct pim_ifchannel *parent = NULL; + + // (S,G) + if ((parent_sg.src.s_addr != INADDR_ANY) + && (parent_sg.grp.s_addr != INADDR_ANY)) { + parent_sg.src.s_addr = INADDR_ANY; + parent = pim_ifchannel_find(ch->interface, &parent_sg); + + if (parent) + listnode_add(parent->sources, ch); + return parent; + } + + return NULL; } -struct pim_ifchannel * -pim_ifchannel_add(struct interface *ifp, - struct prefix_sg *sg, int flags) +struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, + struct prefix_sg *sg, int flags) { - struct pim_interface *pim_ifp; - struct pim_ifchannel *ch; - struct pim_upstream *up; - - ch = pim_ifchannel_find(ifp, sg); - if (ch) - return ch; - - pim_ifp = ifp->info; - - up = pim_upstream_add(sg, NULL, flags, __PRETTY_FUNCTION__); - if (!up) { - zlog_err("%s: could not attach upstream (S,G)=%s on interface %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump (sg), ifp->name); - return NULL; - } - - ch = XCALLOC(MTYPE_PIM_IFCHANNEL, sizeof(*ch)); - if (!ch) { - zlog_warn("%s: pim_ifchannel_new() failure for (S,G)=%s on interface %s", - __PRETTY_FUNCTION__, - up->sg_str, ifp->name); - - pim_upstream_del (up, __PRETTY_FUNCTION__); - return NULL; - } - - ch->flags = 0; - ch->upstream = up; - ch->interface = ifp; - ch->sg = *sg; - pim_str_sg_set (sg, ch->sg_str); - ch->parent = pim_ifchannel_find_parent (ch); - if (ch->sg.src.s_addr == INADDR_ANY) - { - ch->sources = list_new (); - ch->sources->cmp = (int (*)(void *, void *))pim_ifchannel_compare; - } - else - ch->sources = NULL; - - pim_ifchannel_find_new_children (ch); - ch->local_ifmembership = PIM_IFMEMBERSHIP_NOINFO; - - ch->ifjoin_state = PIM_IFJOIN_NOINFO; - ch->t_ifjoin_expiry_timer = NULL; - ch->t_ifjoin_prune_pending_timer = NULL; - ch->ifjoin_creation = 0; - - ch->ifassert_my_metric = pim_macro_ch_my_assert_metric_eval(ch); - ch->ifassert_winner_metric = pim_macro_ch_my_assert_metric_eval (ch); - - ch->ifassert_winner.s_addr = 0; - - /* Assert state */ - ch->t_ifassert_timer = NULL; - ch->ifassert_state = PIM_IFASSERT_NOINFO; - reset_ifassert_state(ch); - if (pim_macro_ch_could_assert_eval(ch)) - PIM_IF_FLAG_SET_COULD_ASSERT(ch->flags); - else - PIM_IF_FLAG_UNSET_COULD_ASSERT(ch->flags); - - if (pim_macro_assert_tracking_desired_eval(ch)) - PIM_IF_FLAG_SET_ASSERT_TRACKING_DESIRED(ch->flags); - else - PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); - - /* Attach to list */ - listnode_add_sort(pim_ifp->pim_ifchannel_list, ch); - ch = hash_get (pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern); - listnode_add_sort(pim_ifchannel_list, ch); - - listnode_add_sort(up->ifchannels, ch); - - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s: ifchannel %s is created ", __PRETTY_FUNCTION__, ch->sg_str); - - return ch; + struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; + struct pim_upstream *up; + + ch = pim_ifchannel_find(ifp, sg); + if (ch) + return ch; + + pim_ifp = ifp->info; + + up = pim_upstream_add(sg, NULL, flags, __PRETTY_FUNCTION__); + if (!up) { + zlog_err( + "%s: could not attach upstream (S,G)=%s on interface %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(sg), ifp->name); + return NULL; + } + + ch = XCALLOC(MTYPE_PIM_IFCHANNEL, sizeof(*ch)); + if (!ch) { + zlog_warn( + "%s: pim_ifchannel_new() failure for (S,G)=%s on interface %s", + __PRETTY_FUNCTION__, up->sg_str, ifp->name); + + pim_upstream_del(up, __PRETTY_FUNCTION__); + return NULL; + } + + ch->flags = 0; + ch->upstream = up; + ch->interface = ifp; + ch->sg = *sg; + pim_str_sg_set(sg, ch->sg_str); + ch->parent = pim_ifchannel_find_parent(ch); + if (ch->sg.src.s_addr == INADDR_ANY) { + ch->sources = list_new(); + ch->sources->cmp = + (int (*)(void *, void *))pim_ifchannel_compare; + } else + ch->sources = NULL; + + pim_ifchannel_find_new_children(ch); + ch->local_ifmembership = PIM_IFMEMBERSHIP_NOINFO; + + ch->ifjoin_state = PIM_IFJOIN_NOINFO; + ch->t_ifjoin_expiry_timer = NULL; + ch->t_ifjoin_prune_pending_timer = NULL; + ch->ifjoin_creation = 0; + + ch->ifassert_my_metric = pim_macro_ch_my_assert_metric_eval(ch); + ch->ifassert_winner_metric = pim_macro_ch_my_assert_metric_eval(ch); + + ch->ifassert_winner.s_addr = 0; + + /* Assert state */ + ch->t_ifassert_timer = NULL; + ch->ifassert_state = PIM_IFASSERT_NOINFO; + reset_ifassert_state(ch); + if (pim_macro_ch_could_assert_eval(ch)) + PIM_IF_FLAG_SET_COULD_ASSERT(ch->flags); + else + PIM_IF_FLAG_UNSET_COULD_ASSERT(ch->flags); + + if (pim_macro_assert_tracking_desired_eval(ch)) + PIM_IF_FLAG_SET_ASSERT_TRACKING_DESIRED(ch->flags); + else + PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); + + /* Attach to list */ + listnode_add_sort(pim_ifp->pim_ifchannel_list, ch); + ch = hash_get(pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern); + listnode_add_sort(pim_ifchannel_list, ch); + + listnode_add_sort(up->ifchannels, ch); + + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: ifchannel %s is created ", __PRETTY_FUNCTION__, + ch->sg_str); + + return ch; } static void ifjoin_to_noinfo(struct pim_ifchannel *ch, bool ch_del) { - pim_forward_stop(ch); - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); - if (ch_del) - delete_on_noinfo(ch); + pim_forward_stop(ch); + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); + if (ch_del) + delete_on_noinfo(ch); } static int on_ifjoin_expiry_timer(struct thread *t) { - struct pim_ifchannel *ch; + struct pim_ifchannel *ch; - ch = THREAD_ARG(t); + ch = THREAD_ARG(t); - ifjoin_to_noinfo(ch, true); - /* ch may have been deleted */ + ifjoin_to_noinfo(ch, true); + /* ch may have been deleted */ - return 0; + return 0; } static int on_ifjoin_prune_pending_timer(struct thread *t) { - struct pim_ifchannel *ch; - int send_prune_echo; /* boolean */ - struct interface *ifp; - struct pim_interface *pim_ifp; - - ch = THREAD_ARG(t); - - if (ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING) - { - /* Send PruneEcho(S,G) ? */ - ifp = ch->interface; - pim_ifp = ifp->info; - send_prune_echo = (listcount(pim_ifp->pim_neighbor_list) > 1); - - if (send_prune_echo) - { - struct pim_rpf rpf; - - rpf.source_nexthop.interface = ifp; - rpf.rpf_addr.u.prefix4 = pim_ifp->primary_address; - pim_jp_agg_single_upstream_send(&rpf, ch->upstream, 0); - } - /* If SGRpt flag is set on ifchannel, Trigger SGRpt - message on RP path upon prune timer expiry. - */ - if (PIM_IF_FLAG_TEST_S_G_RPT (ch->flags)) - { - if (ch->upstream) - pim_upstream_update_join_desired(ch->upstream); - /* - ch->ifjoin_state transition to NOINFO state - ch_del is set to 0 for not deleteing from here. - Holdtime expiry (ch_del set to 1) delete the entry. - */ - ifjoin_to_noinfo(ch, false); - } - else - ifjoin_to_noinfo(ch, true); - /* from here ch may have been deleted */ - } - else - { - zlog_warn("%s: IFCHANNEL%s Prune Pending Timer Popped while in %s state", - __PRETTY_FUNCTION__, pim_str_sg_dump (&ch->sg), - pim_ifchannel_ifjoin_name (ch->ifjoin_state, ch->flags)); - } - - return 0; + struct pim_ifchannel *ch; + int send_prune_echo; /* boolean */ + struct interface *ifp; + struct pim_interface *pim_ifp; + + ch = THREAD_ARG(t); + + if (ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING) { + /* Send PruneEcho(S,G) ? */ + ifp = ch->interface; + pim_ifp = ifp->info; + send_prune_echo = (listcount(pim_ifp->pim_neighbor_list) > 1); + + if (send_prune_echo) { + struct pim_rpf rpf; + + rpf.source_nexthop.interface = ifp; + rpf.rpf_addr.u.prefix4 = pim_ifp->primary_address; + pim_jp_agg_single_upstream_send(&rpf, ch->upstream, 0); + } + /* If SGRpt flag is set on ifchannel, Trigger SGRpt + message on RP path upon prune timer expiry. + */ + if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) { + if (ch->upstream) + pim_upstream_update_join_desired(ch->upstream); + /* + ch->ifjoin_state transition to NOINFO state + ch_del is set to 0 for not deleteing from here. + Holdtime expiry (ch_del set to 1) delete the entry. + */ + ifjoin_to_noinfo(ch, false); + } else + ifjoin_to_noinfo(ch, true); + /* from here ch may have been deleted */ + } else { + zlog_warn( + "%s: IFCHANNEL%s Prune Pending Timer Popped while in %s state", + __PRETTY_FUNCTION__, pim_str_sg_dump(&ch->sg), + pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags)); + } + + return 0; } -static void check_recv_upstream(int is_join, - struct interface *recv_ifp, - struct in_addr upstream, - struct prefix_sg *sg, - uint8_t source_flags, - int holdtime) +static void check_recv_upstream(int is_join, struct interface *recv_ifp, + struct in_addr upstream, struct prefix_sg *sg, + uint8_t source_flags, int holdtime) { - struct pim_upstream *up; - - /* Upstream (S,G) in Joined state ? */ - up = pim_upstream_find(sg); - if (!up) - return; - if (up->join_state != PIM_UPSTREAM_JOINED) - return; - - /* Upstream (S,G) in Joined state */ - - if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { - /* RPF'(S,G) not found */ - zlog_warn("%s %s: RPF'%s not found", - __FILE__, __PRETTY_FUNCTION__, - up->sg_str); - return; - } - - /* upstream directed to RPF'(S,G) ? */ - if (upstream.s_addr != up->rpf.rpf_addr.u.prefix4.s_addr) { - char up_str[INET_ADDRSTRLEN]; - char rpf_str[PREFIX_STRLEN]; - pim_inet4_dump("", upstream, up_str, sizeof(up_str)); - pim_addr_dump("", &up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); - zlog_warn("%s %s: (S,G)=%s upstream=%s not directed to RPF'(S,G)=%s on interface %s", - __FILE__, __PRETTY_FUNCTION__, - up->sg_str, - up_str, rpf_str, recv_ifp->name); - return; - } - /* upstream directed to RPF'(S,G) */ - - if (is_join) { - /* Join(S,G) to RPF'(S,G) */ - pim_upstream_join_suppress(up, up->rpf.rpf_addr.u.prefix4, holdtime); - return; - } - - /* Prune to RPF'(S,G) */ - - if (source_flags & PIM_RPT_BIT_MASK) { - if (source_flags & PIM_WILDCARD_BIT_MASK) { - /* Prune(*,G) to RPF'(S,G) */ - pim_upstream_join_timer_decrease_to_t_override("Prune(*,G)", up); - return; - } - - /* Prune(S,G,rpt) to RPF'(S,G) */ - pim_upstream_join_timer_decrease_to_t_override("Prune(S,G,rpt)", up); - return; - } - - /* Prune(S,G) to RPF'(S,G) */ - pim_upstream_join_timer_decrease_to_t_override("Prune(S,G)", up); + struct pim_upstream *up; + + /* Upstream (S,G) in Joined state ? */ + up = pim_upstream_find(sg); + if (!up) + return; + if (up->join_state != PIM_UPSTREAM_JOINED) + return; + + /* Upstream (S,G) in Joined state */ + + if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { + /* RPF'(S,G) not found */ + zlog_warn("%s %s: RPF'%s not found", __FILE__, + __PRETTY_FUNCTION__, up->sg_str); + return; + } + + /* upstream directed to RPF'(S,G) ? */ + if (upstream.s_addr != up->rpf.rpf_addr.u.prefix4.s_addr) { + char up_str[INET_ADDRSTRLEN]; + char rpf_str[PREFIX_STRLEN]; + pim_inet4_dump("", upstream, up_str, sizeof(up_str)); + pim_addr_dump("", &up->rpf.rpf_addr, rpf_str, + sizeof(rpf_str)); + zlog_warn( + "%s %s: (S,G)=%s upstream=%s not directed to RPF'(S,G)=%s on interface %s", + __FILE__, __PRETTY_FUNCTION__, up->sg_str, up_str, + rpf_str, recv_ifp->name); + return; + } + /* upstream directed to RPF'(S,G) */ + + if (is_join) { + /* Join(S,G) to RPF'(S,G) */ + pim_upstream_join_suppress(up, up->rpf.rpf_addr.u.prefix4, + holdtime); + return; + } + + /* Prune to RPF'(S,G) */ + + if (source_flags & PIM_RPT_BIT_MASK) { + if (source_flags & PIM_WILDCARD_BIT_MASK) { + /* Prune(*,G) to RPF'(S,G) */ + pim_upstream_join_timer_decrease_to_t_override( + "Prune(*,G)", up); + return; + } + + /* Prune(S,G,rpt) to RPF'(S,G) */ + pim_upstream_join_timer_decrease_to_t_override("Prune(S,G,rpt)", + up); + return; + } + + /* Prune(S,G) to RPF'(S,G) */ + pim_upstream_join_timer_decrease_to_t_override("Prune(S,G)", up); } -static int -nonlocal_upstream(int is_join, - struct interface *recv_ifp, - struct in_addr upstream, - struct prefix_sg *sg, - uint8_t source_flags, - uint16_t holdtime) +static int nonlocal_upstream(int is_join, struct interface *recv_ifp, + struct in_addr upstream, struct prefix_sg *sg, + uint8_t source_flags, uint16_t holdtime) { - struct pim_interface *recv_pim_ifp; - int is_local; /* boolean */ - - recv_pim_ifp = recv_ifp->info; - zassert(recv_pim_ifp); - - is_local = (upstream.s_addr == recv_pim_ifp->primary_address.s_addr); - - if (is_local) - return 0; - - if (PIM_DEBUG_PIM_TRACE_DETAIL) { - char up_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", upstream, up_str, sizeof(up_str)); - zlog_warn("%s: recv %s (S,G)=%s to non-local upstream=%s on %s", - __PRETTY_FUNCTION__, - is_join ? "join" : "prune", - pim_str_sg_dump (sg), - up_str, recv_ifp->name); - } - - /* - * Since recv upstream addr was not directed to our primary - * address, check if we should react to it in any way. - */ - check_recv_upstream(is_join, recv_ifp, upstream, sg, - source_flags, holdtime); - - return 1; /* non-local */ + struct pim_interface *recv_pim_ifp; + int is_local; /* boolean */ + + recv_pim_ifp = recv_ifp->info; + zassert(recv_pim_ifp); + + is_local = (upstream.s_addr == recv_pim_ifp->primary_address.s_addr); + + if (is_local) + return 0; + + if (PIM_DEBUG_PIM_TRACE_DETAIL) { + char up_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", upstream, up_str, sizeof(up_str)); + zlog_warn("%s: recv %s (S,G)=%s to non-local upstream=%s on %s", + __PRETTY_FUNCTION__, is_join ? "join" : "prune", + pim_str_sg_dump(sg), up_str, recv_ifp->name); + } + + /* + * Since recv upstream addr was not directed to our primary + * address, check if we should react to it in any way. + */ + check_recv_upstream(is_join, recv_ifp, upstream, sg, source_flags, + holdtime); + + return 1; /* non-local */ } -void pim_ifchannel_join_add(struct interface *ifp, - struct in_addr neigh_addr, - struct in_addr upstream, - struct prefix_sg *sg, - uint8_t source_flags, - uint16_t holdtime) +void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr, + struct in_addr upstream, struct prefix_sg *sg, + uint8_t source_flags, uint16_t holdtime) { - struct pim_interface *pim_ifp; - struct pim_ifchannel *ch; - - if (nonlocal_upstream(1 /* join */, ifp, upstream, - sg, source_flags, holdtime)) { - return; - } - - ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); - if (!ch) - return; - - /* - RFC 4601: 4.6.1. (S,G) Assert Message State Machine - - Transitions from "I am Assert Loser" State - - Receive Join(S,G) on Interface I - - We receive a Join(S,G) that has the Upstream Neighbor Address - field set to my primary IP address on interface I. The action is - to transition to NoInfo state, delete this (S,G) assert state - (Actions A5 below), and allow the normal PIM Join/Prune mechanisms - to operate. - - Notice: The nonlocal_upstream() test above ensures the upstream - address of the join message is our primary address. - */ - if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { - char neigh_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", neigh_addr, neigh_str, sizeof(neigh_str)); - zlog_warn("%s: Assert Loser recv Join%s from %s on %s", - __PRETTY_FUNCTION__, - ch->sg_str, neigh_str, ifp->name); - - assert_action_a5(ch); - } - - pim_ifp = ifp->info; - zassert(pim_ifp); - - switch (ch->ifjoin_state) { - case PIM_IFJOIN_NOINFO: - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_JOIN); - if (pim_macro_chisin_oiflist(ch)) { - pim_upstream_inherited_olist (ch->upstream); - pim_forward_start(ch); - } - /* - * If we are going to be a LHR, we need to note it - */ - if (ch->upstream->parent && - (ch->upstream->parent->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) && - !(ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_LHR)) - { - pim_upstream_ref (ch->upstream, PIM_UPSTREAM_FLAG_MASK_SRC_LHR, __PRETTY_FUNCTION__); - pim_upstream_keep_alive_timer_start (ch->upstream, qpim_keep_alive_time); - } - break; - case PIM_IFJOIN_JOIN: - zassert(!ch->t_ifjoin_prune_pending_timer); - - /* - In the JOIN state ch->t_ifjoin_expiry_timer may be NULL due to a - previously received join message with holdtime=0xFFFF. - */ - if (ch->t_ifjoin_expiry_timer) { - unsigned long remain = - thread_timer_remain_second(ch->t_ifjoin_expiry_timer); - if (remain > holdtime) { + struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; + + if (nonlocal_upstream(1 /* join */, ifp, upstream, sg, source_flags, + holdtime)) { + return; + } + + ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); + if (!ch) + return; + /* - RFC 4601: 4.5.3. Receiving (S,G) Join/Prune Messages + RFC 4601: 4.6.1. (S,G) Assert Message State Machine + + Transitions from "I am Assert Loser" State - Transitions from Join State + Receive Join(S,G) on Interface I - The (S,G) downstream state machine on interface I remains in - Join state, and the Expiry Timer (ET) is restarted, set to - maximum of its current value and the HoldTime from the - triggering Join/Prune message. + We receive a Join(S,G) that has the Upstream Neighbor Address + field set to my primary IP address on interface I. The action is + to transition to NoInfo state, delete this (S,G) assert state + (Actions A5 below), and allow the normal PIM Join/Prune mechanisms + to operate. - Conclusion: Do not change the ET if the current value is - higher than the received join holdtime. + Notice: The nonlocal_upstream() test above ensures the upstream + address of the join message is our primary address. */ - return; - } - } - THREAD_OFF(ch->t_ifjoin_expiry_timer); - break; - case PIM_IFJOIN_PRUNE: - if (source_flags & PIM_ENCODE_RPT_BIT) - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); - break; - case PIM_IFJOIN_PRUNE_PENDING: - THREAD_OFF(ch->t_ifjoin_prune_pending_timer); - if (source_flags & PIM_ENCODE_RPT_BIT) - { - THREAD_OFF(ch->t_ifjoin_expiry_timer); - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); - } - else - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_JOIN); - break; - case PIM_IFJOIN_PRUNE_TMP: - break; - case PIM_IFJOIN_PRUNE_PENDING_TMP: - break; - } - - if (holdtime != 0xFFFF) { - thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, - &ch->t_ifjoin_expiry_timer); - } + if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { + char neigh_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", neigh_addr, neigh_str, + sizeof(neigh_str)); + zlog_warn("%s: Assert Loser recv Join%s from %s on %s", + __PRETTY_FUNCTION__, ch->sg_str, neigh_str, + ifp->name); + + assert_action_a5(ch); + } + + pim_ifp = ifp->info; + zassert(pim_ifp); + + switch (ch->ifjoin_state) { + case PIM_IFJOIN_NOINFO: + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, + PIM_IFJOIN_JOIN); + if (pim_macro_chisin_oiflist(ch)) { + pim_upstream_inherited_olist(ch->upstream); + pim_forward_start(ch); + } + /* + * If we are going to be a LHR, we need to note it + */ + if (ch->upstream->parent && (ch->upstream->parent->flags + & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) + && !(ch->upstream->flags + & PIM_UPSTREAM_FLAG_MASK_SRC_LHR)) { + pim_upstream_ref(ch->upstream, + PIM_UPSTREAM_FLAG_MASK_SRC_LHR, + __PRETTY_FUNCTION__); + pim_upstream_keep_alive_timer_start( + ch->upstream, qpim_keep_alive_time); + } + break; + case PIM_IFJOIN_JOIN: + zassert(!ch->t_ifjoin_prune_pending_timer); + + /* + In the JOIN state ch->t_ifjoin_expiry_timer may be NULL due to + a + previously received join message with holdtime=0xFFFF. + */ + if (ch->t_ifjoin_expiry_timer) { + unsigned long remain = thread_timer_remain_second( + ch->t_ifjoin_expiry_timer); + if (remain > holdtime) { + /* + RFC 4601: 4.5.3. Receiving (S,G) Join/Prune + Messages + + Transitions from Join State + + The (S,G) downstream state machine on + interface I remains in + Join state, and the Expiry Timer (ET) is + restarted, set to + maximum of its current value and the HoldTime + from the + triggering Join/Prune message. + + Conclusion: Do not change the ET if the + current value is + higher than the received join holdtime. + */ + return; + } + } + THREAD_OFF(ch->t_ifjoin_expiry_timer); + break; + case PIM_IFJOIN_PRUNE: + if (source_flags & PIM_ENCODE_RPT_BIT) + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, + PIM_IFJOIN_NOINFO); + break; + case PIM_IFJOIN_PRUNE_PENDING: + THREAD_OFF(ch->t_ifjoin_prune_pending_timer); + if (source_flags & PIM_ENCODE_RPT_BIT) { + THREAD_OFF(ch->t_ifjoin_expiry_timer); + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, + PIM_IFJOIN_NOINFO); + } else + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, + PIM_IFJOIN_JOIN); + break; + case PIM_IFJOIN_PRUNE_TMP: + break; + case PIM_IFJOIN_PRUNE_PENDING_TMP: + break; + } + + if (holdtime != 0xFFFF) { + thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, + &ch->t_ifjoin_expiry_timer); + } } -void pim_ifchannel_prune(struct interface *ifp, - struct in_addr upstream, - struct prefix_sg *sg, - uint8_t source_flags, +void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream, + struct prefix_sg *sg, uint8_t source_flags, uint16_t holdtime) { - struct pim_ifchannel *ch; - struct pim_interface *pim_ifp; - int jp_override_interval_msec; - - if (nonlocal_upstream(0 /* prune */, ifp, upstream, - sg, source_flags, holdtime)) { - return; - } - - ch = pim_ifchannel_find (ifp, sg); - if (!ch && !(source_flags & PIM_ENCODE_RPT_BIT)) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: Received prune with no relevant ifchannel %s(%s) state: %d", - __PRETTY_FUNCTION__, ifp->name, pim_str_sg_dump (sg), source_flags); - return; - } - - ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); - if (!ch) - return; - - pim_ifp = ifp->info; - - switch (ch->ifjoin_state) { - case PIM_IFJOIN_NOINFO: - if (source_flags & PIM_ENCODE_RPT_BIT) - { - if (!(source_flags & PIM_ENCODE_WC_BIT)) - PIM_IF_FLAG_SET_S_G_RPT(ch->flags); - - ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING; - if (listcount(pim_ifp->pim_neighbor_list) > 1) - jp_override_interval_msec = pim_if_jp_override_interval_msec(ifp); - else - jp_override_interval_msec = 0; /* schedule to expire immediately */ - /* If we called ifjoin_prune() directly instead, care should - be taken not to use "ch" afterwards since it would be - deleted. */ + struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; + int jp_override_interval_msec; - THREAD_OFF(ch->t_ifjoin_prune_pending_timer); - THREAD_OFF(ch->t_ifjoin_expiry_timer); - thread_add_timer_msec(master, on_ifjoin_prune_pending_timer, ch, - jp_override_interval_msec, - &ch->t_ifjoin_prune_pending_timer); - thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, - &ch->t_ifjoin_expiry_timer); - pim_upstream_update_join_desired(ch->upstream); - } - break; - case PIM_IFJOIN_PRUNE_PENDING: - /* nothing to do */ - break; - case PIM_IFJOIN_JOIN: - THREAD_OFF(ch->t_ifjoin_expiry_timer); - - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_PRUNE_PENDING); - - if (listcount(pim_ifp->pim_neighbor_list) > 1) - jp_override_interval_msec = pim_if_jp_override_interval_msec(ifp); - else - jp_override_interval_msec = 0; /* schedule to expire immediately */ - /* If we called ifjoin_prune() directly instead, care should - be taken not to use "ch" afterwards since it would be - deleted. */ - THREAD_OFF(ch->t_ifjoin_prune_pending_timer); - thread_add_timer_msec(master, on_ifjoin_prune_pending_timer, ch, - jp_override_interval_msec, - &ch->t_ifjoin_prune_pending_timer); - break; - case PIM_IFJOIN_PRUNE: - if (source_flags & PIM_ENCODE_RPT_BIT) - { - THREAD_OFF(ch->t_ifjoin_prune_pending_timer); - thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, - &ch->t_ifjoin_expiry_timer); - } - break; - case PIM_IFJOIN_PRUNE_TMP: - if (source_flags & PIM_ENCODE_RPT_BIT) - { - ch->ifjoin_state = PIM_IFJOIN_PRUNE; - THREAD_OFF(ch->t_ifjoin_expiry_timer); - thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, - &ch->t_ifjoin_expiry_timer); - } - break; - case PIM_IFJOIN_PRUNE_PENDING_TMP: - if (source_flags & PIM_ENCODE_RPT_BIT) - { - ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING; - THREAD_OFF(ch->t_ifjoin_expiry_timer); - thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime, - &ch->t_ifjoin_expiry_timer); - } - break; - } + if (nonlocal_upstream(0 /* prune */, ifp, upstream, sg, source_flags, + holdtime)) { + return; + } + + ch = pim_ifchannel_find(ifp, sg); + if (!ch && !(source_flags & PIM_ENCODE_RPT_BIT)) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: Received prune with no relevant ifchannel %s(%s) state: %d", + __PRETTY_FUNCTION__, ifp->name, + pim_str_sg_dump(sg), source_flags); + return; + } + + ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM); + if (!ch) + return; + + pim_ifp = ifp->info; + + switch (ch->ifjoin_state) { + case PIM_IFJOIN_NOINFO: + if (source_flags & PIM_ENCODE_RPT_BIT) { + if (!(source_flags & PIM_ENCODE_WC_BIT)) + PIM_IF_FLAG_SET_S_G_RPT(ch->flags); + + ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING; + if (listcount(pim_ifp->pim_neighbor_list) > 1) + jp_override_interval_msec = + pim_if_jp_override_interval_msec(ifp); + else + jp_override_interval_msec = + 0; /* schedule to expire immediately */ + /* If we called ifjoin_prune() directly instead, care + should + be taken not to use "ch" afterwards since it would be + deleted. */ + + THREAD_OFF(ch->t_ifjoin_prune_pending_timer); + THREAD_OFF(ch->t_ifjoin_expiry_timer); + thread_add_timer_msec( + master, on_ifjoin_prune_pending_timer, ch, + jp_override_interval_msec, + &ch->t_ifjoin_prune_pending_timer); + thread_add_timer(master, on_ifjoin_expiry_timer, ch, + holdtime, &ch->t_ifjoin_expiry_timer); + pim_upstream_update_join_desired(ch->upstream); + } + break; + case PIM_IFJOIN_PRUNE_PENDING: + /* nothing to do */ + break; + case PIM_IFJOIN_JOIN: + THREAD_OFF(ch->t_ifjoin_expiry_timer); + + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, + PIM_IFJOIN_PRUNE_PENDING); + + if (listcount(pim_ifp->pim_neighbor_list) > 1) + jp_override_interval_msec = + pim_if_jp_override_interval_msec(ifp); + else + jp_override_interval_msec = + 0; /* schedule to expire immediately */ + /* If we called ifjoin_prune() directly instead, care should + be taken not to use "ch" afterwards since it would be + deleted. */ + THREAD_OFF(ch->t_ifjoin_prune_pending_timer); + thread_add_timer_msec(master, on_ifjoin_prune_pending_timer, ch, + jp_override_interval_msec, + &ch->t_ifjoin_prune_pending_timer); + break; + case PIM_IFJOIN_PRUNE: + if (source_flags & PIM_ENCODE_RPT_BIT) { + THREAD_OFF(ch->t_ifjoin_prune_pending_timer); + thread_add_timer(master, on_ifjoin_expiry_timer, ch, + holdtime, &ch->t_ifjoin_expiry_timer); + } + break; + case PIM_IFJOIN_PRUNE_TMP: + if (source_flags & PIM_ENCODE_RPT_BIT) { + ch->ifjoin_state = PIM_IFJOIN_PRUNE; + THREAD_OFF(ch->t_ifjoin_expiry_timer); + thread_add_timer(master, on_ifjoin_expiry_timer, ch, + holdtime, &ch->t_ifjoin_expiry_timer); + } + break; + case PIM_IFJOIN_PRUNE_PENDING_TMP: + if (source_flags & PIM_ENCODE_RPT_BIT) { + ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING; + THREAD_OFF(ch->t_ifjoin_expiry_timer); + thread_add_timer(master, on_ifjoin_expiry_timer, ch, + holdtime, &ch->t_ifjoin_expiry_timer); + } + break; + } } -int -pim_ifchannel_local_membership_add(struct interface *ifp, - struct prefix_sg *sg) +int pim_ifchannel_local_membership_add(struct interface *ifp, + struct prefix_sg *sg) { - struct pim_ifchannel *ch, *starch; - struct pim_interface *pim_ifp; - - /* PIM enabled on interface? */ - pim_ifp = ifp->info; - if (!pim_ifp) - return 0; - if (!PIM_IF_TEST_PIM(pim_ifp->options)) - return 0; - - /* skip (*,G) ch creation if G is of type SSM */ - if (sg->src.s_addr == INADDR_ANY) - { - if (pim_is_grp_ssm (sg->grp)) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_debug("%s: local membership (S,G)=%s ignored as group is SSM", - __PRETTY_FUNCTION__, pim_str_sg_dump (sg)); - return 1; - } - } - - ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP); - if (!ch) { - return 0; - } - - ifmembership_set(ch, PIM_IFMEMBERSHIP_INCLUDE); - - if (sg->src.s_addr == INADDR_ANY) - { - struct pim_upstream *up = pim_upstream_find (sg); - struct pim_upstream *child; - struct listnode *up_node; - - starch = ch; - - for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) - { - if (PIM_DEBUG_EVENTS) - zlog_debug("%s %s: IGMP (S,G)=%s(%s) from %s", - __FILE__, __PRETTY_FUNCTION__, - child->sg_str, ifp->name, up->sg_str); - - ch = pim_ifchannel_find (ifp, &child->sg); - if (pim_upstream_evaluate_join_desired_interface (child, ch, starch)) - { - pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_STAR); - pim_upstream_switch (child, PIM_UPSTREAM_JOINED); - } - } - - if (pimg->spt.switchover == PIM_SPT_INFINITY) - { - if (pimg->spt.plist) - { - struct prefix_list *plist = prefix_list_lookup (AFI_IP, pimg->spt.plist); - struct prefix g; - g.family = AF_INET; - g.prefixlen = IPV4_MAX_PREFIXLEN; - g.u.prefix4 = up->sg.grp; - - if (prefix_list_apply (plist, &g) == PREFIX_DENY) - { - pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); - } - } - } - else - pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); - } - - return 1; + struct pim_ifchannel *ch, *starch; + struct pim_interface *pim_ifp; + + /* PIM enabled on interface? */ + pim_ifp = ifp->info; + if (!pim_ifp) + return 0; + if (!PIM_IF_TEST_PIM(pim_ifp->options)) + return 0; + + /* skip (*,G) ch creation if G is of type SSM */ + if (sg->src.s_addr == INADDR_ANY) { + if (pim_is_grp_ssm(sg->grp)) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug( + "%s: local membership (S,G)=%s ignored as group is SSM", + __PRETTY_FUNCTION__, + pim_str_sg_dump(sg)); + return 1; + } + } + + ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP); + if (!ch) { + return 0; + } + + ifmembership_set(ch, PIM_IFMEMBERSHIP_INCLUDE); + + if (sg->src.s_addr == INADDR_ANY) { + struct pim_upstream *up = pim_upstream_find(sg); + struct pim_upstream *child; + struct listnode *up_node; + + starch = ch; + + for (ALL_LIST_ELEMENTS_RO(up->sources, up_node, child)) { + if (PIM_DEBUG_EVENTS) + zlog_debug("%s %s: IGMP (S,G)=%s(%s) from %s", + __FILE__, __PRETTY_FUNCTION__, + child->sg_str, ifp->name, + up->sg_str); + + ch = pim_ifchannel_find(ifp, &child->sg); + if (pim_upstream_evaluate_join_desired_interface( + child, ch, starch)) { + pim_channel_add_oif(child->channel_oil, ifp, + PIM_OIF_FLAG_PROTO_STAR); + pim_upstream_switch(child, PIM_UPSTREAM_JOINED); + } + } + + if (pimg->spt.switchover == PIM_SPT_INFINITY) { + if (pimg->spt.plist) { + struct prefix_list *plist = prefix_list_lookup( + AFI_IP, pimg->spt.plist); + struct prefix g; + g.family = AF_INET; + g.prefixlen = IPV4_MAX_PREFIXLEN; + g.u.prefix4 = up->sg.grp; + + if (prefix_list_apply(plist, &g) + == PREFIX_DENY) { + pim_channel_add_oif( + up->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_IGMP); + } + } + } else + pim_channel_add_oif(up->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_IGMP); + } + + return 1; } void pim_ifchannel_local_membership_del(struct interface *ifp, struct prefix_sg *sg) { - struct pim_ifchannel *starch, *ch, *orig; - struct pim_interface *pim_ifp; - - /* PIM enabled on interface? */ - pim_ifp = ifp->info; - if (!pim_ifp) - return; - if (!PIM_IF_TEST_PIM(pim_ifp->options)) - return; - - orig = ch = pim_ifchannel_find(ifp, sg); - if (!ch) - return; - - ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); - - if (sg->src.s_addr == INADDR_ANY) - { - struct pim_upstream *up = pim_upstream_find (sg); - struct pim_upstream *child; - struct listnode *up_node, *up_nnode; - - starch = ch; - - for (ALL_LIST_ELEMENTS (up->sources, up_node, up_nnode, child)) - { - struct channel_oil *c_oil = child->channel_oil; - struct pim_ifchannel *chchannel = pim_ifchannel_find (ifp, &child->sg); - struct pim_interface *pim_ifp = ifp->info; - - if (PIM_DEBUG_EVENTS) - zlog_debug("%s %s: Prune(S,G)=%s(%s) from %s", - __FILE__, __PRETTY_FUNCTION__, - up->sg_str, ifp->name, child->sg_str); - - ch = pim_ifchannel_find (ifp, &child->sg); - if (c_oil && !pim_upstream_evaluate_join_desired_interface (child, ch, starch)) - pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_STAR); - - /* - * If the S,G has no if channel and the c_oil still - * has output here then the *,G was supplying the implied - * if channel. So remove it. - */ - if (!chchannel && c_oil && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) - pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_STAR); - - /* Child node removal/ref count-- will happen as part of parent' delete_no_info */ - } - } - delete_on_noinfo(orig); + struct pim_ifchannel *starch, *ch, *orig; + struct pim_interface *pim_ifp; + + /* PIM enabled on interface? */ + pim_ifp = ifp->info; + if (!pim_ifp) + return; + if (!PIM_IF_TEST_PIM(pim_ifp->options)) + return; + + orig = ch = pim_ifchannel_find(ifp, sg); + if (!ch) + return; + + ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); + + if (sg->src.s_addr == INADDR_ANY) { + struct pim_upstream *up = pim_upstream_find(sg); + struct pim_upstream *child; + struct listnode *up_node, *up_nnode; + + starch = ch; + + for (ALL_LIST_ELEMENTS(up->sources, up_node, up_nnode, child)) { + struct channel_oil *c_oil = child->channel_oil; + struct pim_ifchannel *chchannel = + pim_ifchannel_find(ifp, &child->sg); + struct pim_interface *pim_ifp = ifp->info; + + if (PIM_DEBUG_EVENTS) + zlog_debug("%s %s: Prune(S,G)=%s(%s) from %s", + __FILE__, __PRETTY_FUNCTION__, + up->sg_str, ifp->name, + child->sg_str); + + ch = pim_ifchannel_find(ifp, &child->sg); + if (c_oil + && !pim_upstream_evaluate_join_desired_interface( + child, ch, starch)) + pim_channel_del_oif(c_oil, ifp, + PIM_OIF_FLAG_PROTO_STAR); + + /* + * If the S,G has no if channel and the c_oil still + * has output here then the *,G was supplying the + * implied + * if channel. So remove it. + */ + if (!chchannel && c_oil + && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) + pim_channel_del_oif(c_oil, ifp, + PIM_OIF_FLAG_PROTO_STAR); + + /* Child node removal/ref count-- will happen as part of + * parent' delete_no_info */ + } + } + delete_on_noinfo(orig); } void pim_ifchannel_update_could_assert(struct pim_ifchannel *ch) { - int old_couldassert = PIM_FORCE_BOOLEAN(PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)); - int new_couldassert = PIM_FORCE_BOOLEAN(pim_macro_ch_could_assert_eval(ch)); - - if (new_couldassert == old_couldassert) - return; - - if (PIM_DEBUG_PIM_EVENTS) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", ch->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->sg.grp, grp_str, sizeof(grp_str)); - zlog_debug("%s: CouldAssert(%s,%s,%s) changed from %d to %d", - __PRETTY_FUNCTION__, - src_str, grp_str, ch->interface->name, - old_couldassert, new_couldassert); - } - - if (new_couldassert) { - /* CouldAssert(S,G,I) switched from FALSE to TRUE */ - PIM_IF_FLAG_SET_COULD_ASSERT(ch->flags); - } - else { - /* CouldAssert(S,G,I) switched from TRUE to FALSE */ - PIM_IF_FLAG_UNSET_COULD_ASSERT(ch->flags); - - if (ch->ifassert_state == PIM_IFASSERT_I_AM_WINNER) { - assert_action_a4(ch); - } - } - - pim_ifchannel_update_my_assert_metric(ch); + int old_couldassert = + PIM_FORCE_BOOLEAN(PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)); + int new_couldassert = + PIM_FORCE_BOOLEAN(pim_macro_ch_could_assert_eval(ch)); + + if (new_couldassert == old_couldassert) + return; + + if (PIM_DEBUG_PIM_EVENTS) { + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", ch->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", ch->sg.grp, grp_str, sizeof(grp_str)); + zlog_debug("%s: CouldAssert(%s,%s,%s) changed from %d to %d", + __PRETTY_FUNCTION__, src_str, grp_str, + ch->interface->name, old_couldassert, + new_couldassert); + } + + if (new_couldassert) { + /* CouldAssert(S,G,I) switched from FALSE to TRUE */ + PIM_IF_FLAG_SET_COULD_ASSERT(ch->flags); + } else { + /* CouldAssert(S,G,I) switched from TRUE to FALSE */ + PIM_IF_FLAG_UNSET_COULD_ASSERT(ch->flags); + + if (ch->ifassert_state == PIM_IFASSERT_I_AM_WINNER) { + assert_action_a4(ch); + } + } + + pim_ifchannel_update_my_assert_metric(ch); } /* @@ -1165,72 +1182,75 @@ void pim_ifchannel_update_could_assert(struct pim_ifchannel *ch) */ void pim_ifchannel_update_my_assert_metric(struct pim_ifchannel *ch) { - struct pim_assert_metric my_metric_new = pim_macro_ch_my_assert_metric_eval(ch); - - if (pim_assert_metric_match(&my_metric_new, &ch->ifassert_my_metric)) - return; - - if (PIM_DEBUG_PIM_EVENTS) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - char old_addr_str[INET_ADDRSTRLEN]; - char new_addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", ch->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->sg.grp, grp_str, sizeof(grp_str)); - pim_inet4_dump("", ch->ifassert_my_metric.ip_address, old_addr_str, sizeof(old_addr_str)); - pim_inet4_dump("", my_metric_new.ip_address, new_addr_str, sizeof(new_addr_str)); - zlog_debug("%s: my_assert_metric(%s,%s,%s) changed from %u,%u,%u,%s to %u,%u,%u,%s", - __PRETTY_FUNCTION__, - src_str, grp_str, ch->interface->name, - ch->ifassert_my_metric.rpt_bit_flag, - ch->ifassert_my_metric.metric_preference, - ch->ifassert_my_metric.route_metric, - old_addr_str, - my_metric_new.rpt_bit_flag, - my_metric_new.metric_preference, - my_metric_new.route_metric, - new_addr_str); - } - - ch->ifassert_my_metric = my_metric_new; - - if (pim_assert_metric_better(&ch->ifassert_my_metric, - &ch->ifassert_winner_metric)) { - assert_action_a5(ch); - } + struct pim_assert_metric my_metric_new = + pim_macro_ch_my_assert_metric_eval(ch); + + if (pim_assert_metric_match(&my_metric_new, &ch->ifassert_my_metric)) + return; + + if (PIM_DEBUG_PIM_EVENTS) { + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + char old_addr_str[INET_ADDRSTRLEN]; + char new_addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", ch->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", ch->sg.grp, grp_str, sizeof(grp_str)); + pim_inet4_dump("", ch->ifassert_my_metric.ip_address, + old_addr_str, sizeof(old_addr_str)); + pim_inet4_dump("", my_metric_new.ip_address, + new_addr_str, sizeof(new_addr_str)); + zlog_debug( + "%s: my_assert_metric(%s,%s,%s) changed from %u,%u,%u,%s to %u,%u,%u,%s", + __PRETTY_FUNCTION__, src_str, grp_str, + ch->interface->name, + ch->ifassert_my_metric.rpt_bit_flag, + ch->ifassert_my_metric.metric_preference, + ch->ifassert_my_metric.route_metric, old_addr_str, + my_metric_new.rpt_bit_flag, + my_metric_new.metric_preference, + my_metric_new.route_metric, new_addr_str); + } + + ch->ifassert_my_metric = my_metric_new; + + if (pim_assert_metric_better(&ch->ifassert_my_metric, + &ch->ifassert_winner_metric)) { + assert_action_a5(ch); + } } void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch) { - int old_atd = PIM_FORCE_BOOLEAN(PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags)); - int new_atd = PIM_FORCE_BOOLEAN(pim_macro_assert_tracking_desired_eval(ch)); - - if (new_atd == old_atd) - return; - - if (PIM_DEBUG_PIM_EVENTS) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", ch->sg.src, src_str, sizeof(src_str)); - pim_inet4_dump("", ch->sg.grp, grp_str, sizeof(grp_str)); - zlog_debug("%s: AssertTrackingDesired(%s,%s,%s) changed from %d to %d", - __PRETTY_FUNCTION__, - src_str, grp_str, ch->interface->name, - old_atd, new_atd); - } - - if (new_atd) { - /* AssertTrackingDesired(S,G,I) switched from FALSE to TRUE */ - PIM_IF_FLAG_SET_ASSERT_TRACKING_DESIRED(ch->flags); - } - else { - /* AssertTrackingDesired(S,G,I) switched from TRUE to FALSE */ - PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); - - if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { - assert_action_a5(ch); - } - } + int old_atd = PIM_FORCE_BOOLEAN( + PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags)); + int new_atd = + PIM_FORCE_BOOLEAN(pim_macro_assert_tracking_desired_eval(ch)); + + if (new_atd == old_atd) + return; + + if (PIM_DEBUG_PIM_EVENTS) { + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", ch->sg.src, src_str, sizeof(src_str)); + pim_inet4_dump("", ch->sg.grp, grp_str, sizeof(grp_str)); + zlog_debug( + "%s: AssertTrackingDesired(%s,%s,%s) changed from %d to %d", + __PRETTY_FUNCTION__, src_str, grp_str, + ch->interface->name, old_atd, new_atd); + } + + if (new_atd) { + /* AssertTrackingDesired(S,G,I) switched from FALSE to TRUE */ + PIM_IF_FLAG_SET_ASSERT_TRACKING_DESIRED(ch->flags); + } else { + /* AssertTrackingDesired(S,G,I) switched from TRUE to FALSE */ + PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); + + if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { + assert_action_a5(ch); + } + } } /* @@ -1239,36 +1259,34 @@ void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch) * their upstream out that way and turn on forwarding * for that ifchannel then. */ -void -pim_ifchannel_scan_forward_start (struct interface *new_ifp) +void pim_ifchannel_scan_forward_start(struct interface *new_ifp) { - struct listnode *ifnode; - struct interface *ifp; - struct pim_interface *new_pim_ifp = new_ifp->info; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) - { - struct pim_interface *loop_pim_ifp = ifp->info; - struct listnode *ch_node; - struct pim_ifchannel *ch; - - if (!loop_pim_ifp) - continue; - - if (new_pim_ifp == loop_pim_ifp) - continue; - - for (ALL_LIST_ELEMENTS_RO (loop_pim_ifp->pim_ifchannel_list, ch_node, ch)) - { - if (ch->ifjoin_state == PIM_IFJOIN_JOIN) - { - struct pim_upstream *up = ch->upstream; - if ((!up->channel_oil) && - (up->rpf.source_nexthop.interface == new_ifp)) - pim_forward_start (ch); - } - } - } + struct listnode *ifnode; + struct interface *ifp; + struct pim_interface *new_pim_ifp = new_ifp->info; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { + struct pim_interface *loop_pim_ifp = ifp->info; + struct listnode *ch_node; + struct pim_ifchannel *ch; + + if (!loop_pim_ifp) + continue; + + if (new_pim_ifp == loop_pim_ifp) + continue; + + for (ALL_LIST_ELEMENTS_RO(loop_pim_ifp->pim_ifchannel_list, + ch_node, ch)) { + if (ch->ifjoin_state == PIM_IFJOIN_JOIN) { + struct pim_upstream *up = ch->upstream; + if ((!up->channel_oil) + && (up->rpf.source_nexthop + .interface == new_ifp)) + pim_forward_start(ch); + } + } + } } /* @@ -1278,87 +1296,89 @@ pim_ifchannel_scan_forward_start (struct interface *new_ifp) * reception of a *,G join as well, when * we get End of Message */ -void -pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t source_flags, uint8_t join, uint8_t starg_alone) +void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom, + uint8_t source_flags, uint8_t join, + uint8_t starg_alone) { - struct pim_ifchannel *child; - struct listnode *ch_node; - - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s: %s %s eom: %d join %u", __PRETTY_FUNCTION__, - pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags), - ch->sg_str, eom, join); - if (!ch->sources) - return; - - for (ALL_LIST_ELEMENTS_RO (ch->sources, ch_node, child)) - { - /* Only *,G Join received and no (SG-RPT) prune. - eom = 1, only (W,G) join_alone is true, WC and RPT are set. - Scan all S,G associated to G and if any SG-RPT - remove the SG-RPT flag. - */ - if (eom && starg_alone && (source_flags & PIM_RPT_BIT_MASK) && - (source_flags & PIM_WILDCARD_BIT_MASK)) - { - if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) - { - struct pim_upstream *up = child->upstream; - - PIM_IF_FLAG_UNSET_S_G_RPT(child->flags); - if (up) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: SGRpt flag is cleared, add inherit oif to up %s", - __PRETTY_FUNCTION__, up->sg_str); - pim_channel_add_oif (up->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); - pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, child, PIM_IFJOIN_JOIN); - } - } - } - - if (!PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) - continue; - - switch (child->ifjoin_state) - { - case PIM_IFJOIN_NOINFO: - case PIM_IFJOIN_JOIN: - break; - case PIM_IFJOIN_PRUNE: - if (!eom) - child->ifjoin_state = PIM_IFJOIN_PRUNE_TMP; - break; - case PIM_IFJOIN_PRUNE_PENDING: - if (!eom) - child->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING_TMP; - break; - case PIM_IFJOIN_PRUNE_TMP: - case PIM_IFJOIN_PRUNE_PENDING_TMP: - if (eom) - child->ifjoin_state = PIM_IFJOIN_NOINFO; - break; + struct pim_ifchannel *child; + struct listnode *ch_node; + + if (PIM_DEBUG_PIM_TRACE) + zlog_debug( + "%s: %s %s eom: %d join %u", __PRETTY_FUNCTION__, + pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags), + ch->sg_str, eom, join); + if (!ch->sources) + return; + + for (ALL_LIST_ELEMENTS_RO(ch->sources, ch_node, child)) { + /* Only *,G Join received and no (SG-RPT) prune. + eom = 1, only (W,G) join_alone is true, WC and RPT are set. + Scan all S,G associated to G and if any SG-RPT + remove the SG-RPT flag. + */ + if (eom && starg_alone && (source_flags & PIM_RPT_BIT_MASK) + && (source_flags & PIM_WILDCARD_BIT_MASK)) { + if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) { + struct pim_upstream *up = child->upstream; + + PIM_IF_FLAG_UNSET_S_G_RPT(child->flags); + if (up) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: SGRpt flag is cleared, add inherit oif to up %s", + __PRETTY_FUNCTION__, + up->sg_str); + pim_channel_add_oif( + up->channel_oil, ch->interface, + PIM_OIF_FLAG_PROTO_STAR); + pim_ifchannel_ifjoin_switch( + __PRETTY_FUNCTION__, child, + PIM_IFJOIN_JOIN); + } + } + } + + if (!PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) + continue; + + switch (child->ifjoin_state) { + case PIM_IFJOIN_NOINFO: + case PIM_IFJOIN_JOIN: + break; + case PIM_IFJOIN_PRUNE: + if (!eom) + child->ifjoin_state = PIM_IFJOIN_PRUNE_TMP; + break; + case PIM_IFJOIN_PRUNE_PENDING: + if (!eom) + child->ifjoin_state = + PIM_IFJOIN_PRUNE_PENDING_TMP; + break; + case PIM_IFJOIN_PRUNE_TMP: + case PIM_IFJOIN_PRUNE_PENDING_TMP: + if (eom) + child->ifjoin_state = PIM_IFJOIN_NOINFO; + break; + } } - } } -unsigned int -pim_ifchannel_hash_key (void *arg) +unsigned int pim_ifchannel_hash_key(void *arg) { - struct pim_ifchannel *ch = (struct pim_ifchannel *)arg; + struct pim_ifchannel *ch = (struct pim_ifchannel *)arg; - return jhash_2words (ch->sg.src.s_addr, ch->sg.grp.s_addr, 0); + return jhash_2words(ch->sg.src.s_addr, ch->sg.grp.s_addr, 0); } -int -pim_ifchannel_equal (const void *arg1, const void *arg2) +int pim_ifchannel_equal(const void *arg1, const void *arg2) { - const struct pim_ifchannel *ch1 = (const struct pim_ifchannel *)arg1; - const struct pim_ifchannel *ch2 = (const struct pim_ifchannel *)arg2; + const struct pim_ifchannel *ch1 = (const struct pim_ifchannel *)arg1; + const struct pim_ifchannel *ch2 = (const struct pim_ifchannel *)arg2; - if ((ch1->sg.grp.s_addr == ch2->sg.grp.s_addr) && - (ch1->sg.src.s_addr == ch2->sg.src.s_addr)) - return 1; + if ((ch1->sg.grp.s_addr == ch2->sg.grp.s_addr) + && (ch1->sg.src.s_addr == ch2->sg.src.s_addr)) + return 1; - return 0; + return 0; } diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 455493a5b..2260fd451 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -28,31 +28,29 @@ struct pim_ifchannel; #include "pim_upstream.h" -enum pim_ifmembership { - PIM_IFMEMBERSHIP_NOINFO, - PIM_IFMEMBERSHIP_INCLUDE -}; +enum pim_ifmembership { PIM_IFMEMBERSHIP_NOINFO, PIM_IFMEMBERSHIP_INCLUDE }; enum pim_ifjoin_state { - PIM_IFJOIN_NOINFO, - PIM_IFJOIN_JOIN, - PIM_IFJOIN_PRUNE, - PIM_IFJOIN_PRUNE_PENDING, - PIM_IFJOIN_PRUNE_TMP, - PIM_IFJOIN_PRUNE_PENDING_TMP, + PIM_IFJOIN_NOINFO, + PIM_IFJOIN_JOIN, + PIM_IFJOIN_PRUNE, + PIM_IFJOIN_PRUNE_PENDING, + PIM_IFJOIN_PRUNE_TMP, + PIM_IFJOIN_PRUNE_PENDING_TMP, }; enum pim_ifassert_state { - PIM_IFASSERT_NOINFO, - PIM_IFASSERT_I_AM_WINNER, - PIM_IFASSERT_I_AM_LOSER + PIM_IFASSERT_NOINFO, + PIM_IFASSERT_I_AM_WINNER, + PIM_IFASSERT_I_AM_LOSER }; struct pim_assert_metric { - uint32_t rpt_bit_flag; - uint32_t metric_preference; - uint32_t route_metric; - struct in_addr ip_address; /* neighbor router that sourced the Assert message */ + uint32_t rpt_bit_flag; + uint32_t metric_preference; + uint32_t route_metric; + struct in_addr ip_address; /* neighbor router that sourced the Assert + message */ }; /* @@ -82,63 +80,58 @@ struct pim_assert_metric { Per-interface (S,G) state */ struct pim_ifchannel { - struct pim_ifchannel *parent; - struct list *sources; - struct prefix_sg sg; - char sg_str[PIM_SG_LEN]; - struct interface *interface; /* backpointer to interface */ - uint32_t flags; - - /* IGMPv3 determined interface has local members for (S,G) ? */ - enum pim_ifmembership local_ifmembership; - - /* Per-interface (S,G) Join/Prune State (Section 4.1.4 of RFC4601) */ - enum pim_ifjoin_state ifjoin_state; - struct thread *t_ifjoin_expiry_timer; - struct thread *t_ifjoin_prune_pending_timer; - int64_t ifjoin_creation; /* Record uptime of ifjoin state */ - - /* Per-interface (S,G) Assert State (Section 4.6.1 of RFC4601) */ - enum pim_ifassert_state ifassert_state; - struct thread *t_ifassert_timer; - struct in_addr ifassert_winner; - struct pim_assert_metric ifassert_winner_metric; - int64_t ifassert_creation; /* Record uptime of ifassert state */ - struct pim_assert_metric ifassert_my_metric; - - /* Upstream (S,G) state */ - struct pim_upstream *upstream; + struct pim_ifchannel *parent; + struct list *sources; + struct prefix_sg sg; + char sg_str[PIM_SG_LEN]; + struct interface *interface; /* backpointer to interface */ + uint32_t flags; + + /* IGMPv3 determined interface has local members for (S,G) ? */ + enum pim_ifmembership local_ifmembership; + + /* Per-interface (S,G) Join/Prune State (Section 4.1.4 of RFC4601) */ + enum pim_ifjoin_state ifjoin_state; + struct thread *t_ifjoin_expiry_timer; + struct thread *t_ifjoin_prune_pending_timer; + int64_t ifjoin_creation; /* Record uptime of ifjoin state */ + + /* Per-interface (S,G) Assert State (Section 4.6.1 of RFC4601) */ + enum pim_ifassert_state ifassert_state; + struct thread *t_ifassert_timer; + struct in_addr ifassert_winner; + struct pim_assert_metric ifassert_winner_metric; + int64_t ifassert_creation; /* Record uptime of ifassert state */ + struct pim_assert_metric ifassert_my_metric; + + /* Upstream (S,G) state */ + struct pim_upstream *upstream; }; void pim_ifchannel_free(struct pim_ifchannel *ch); void pim_ifchannel_delete(struct pim_ifchannel *ch); -void pim_ifchannel_delete_all (struct interface *ifp); +void pim_ifchannel_delete_all(struct interface *ifp); void pim_ifchannel_membership_clear(struct interface *ifp); void pim_ifchannel_delete_on_noinfo(struct interface *ifp); struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp, struct prefix_sg *sg); struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, struct prefix_sg *sg, int flags); -void pim_ifchannel_join_add(struct interface *ifp, - struct in_addr neigh_addr, - struct in_addr upstream, - struct prefix_sg *sg, - uint8_t source_flags, - uint16_t holdtime); -void pim_ifchannel_prune(struct interface *ifp, - struct in_addr upstream, - struct prefix_sg *sg, - uint8_t source_flags, +void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr, + struct in_addr upstream, struct prefix_sg *sg, + uint8_t source_flags, uint16_t holdtime); +void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream, + struct prefix_sg *sg, uint8_t source_flags, uint16_t holdtime); int pim_ifchannel_local_membership_add(struct interface *ifp, struct prefix_sg *sg); void pim_ifchannel_local_membership_del(struct interface *ifp, struct prefix_sg *sg); -void pim_ifchannel_ifjoin_switch(const char *caller, - struct pim_ifchannel *ch, +void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch, enum pim_ifjoin_state new_state); -const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state, int flags); +const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state, + int flags); const char *pim_ifchannel_ifassert_name(enum pim_ifassert_state ifassert_state); int pim_ifchannel_isin_oiflist(struct pim_ifchannel *ch); @@ -149,11 +142,13 @@ void pim_ifchannel_update_could_assert(struct pim_ifchannel *ch); void pim_ifchannel_update_my_assert_metric(struct pim_ifchannel *ch); void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch); -void pim_ifchannel_scan_forward_start (struct interface *new_ifp); -void pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t source_flags, uint8_t join, uint8_t starg_alone); +void pim_ifchannel_scan_forward_start(struct interface *new_ifp); +void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom, + uint8_t source_flags, uint8_t join, + uint8_t starg_alone); -int pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2); +int pim_ifchannel_compare(struct pim_ifchannel *ch1, struct pim_ifchannel *ch2); -unsigned int pim_ifchannel_hash_key (void *arg); -int pim_ifchannel_equal (const void *arg1, const void *arg2); +unsigned int pim_ifchannel_hash_key(void *arg); +int pim_ifchannel_equal(const void *arg1, const void *arg2); #endif /* PIM_IFCHANNEL_H */ diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index ae5f365b8..c693f30ac 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -43,62 +43,66 @@ static int pim_igmp_general_query(struct thread *t); /* This socket is used for TXing IGMP packets only, IGMP RX happens * in pim_mroute_msg() */ -static int igmp_sock_open(struct in_addr ifaddr, struct interface *ifp, uint32_t pim_options) +static int igmp_sock_open(struct in_addr ifaddr, struct interface *ifp, + uint32_t pim_options) { - int fd; - int join = 0; - struct in_addr group; - - fd = pim_socket_mcast(IPPROTO_IGMP, ifaddr, ifp, 1); - - if (fd < 0) - return -1; - - if (PIM_IF_TEST_IGMP_LISTEN_ALLROUTERS(pim_options)) { - if (inet_aton(PIM_ALL_ROUTERS, &group)) { - if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex)) - ++join; - } - else { - zlog_warn("%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), - PIM_ALL_ROUTERS, errno, safe_strerror(errno)); - } - } - - /* - IGMP routers periodically send IGMP general queries to AllSystems=224.0.0.1 - IGMP routers must receive general queries for querier election. - */ - if (inet_aton(PIM_ALL_SYSTEMS, &group)) { - if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex)) - ++join; - } - else { - zlog_warn("%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), - PIM_ALL_SYSTEMS, errno, safe_strerror(errno)); - } - - if (inet_aton(PIM_ALL_IGMP_ROUTERS, &group)) { - if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex)) { - ++join; - } - } - else { - zlog_warn("%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), - PIM_ALL_IGMP_ROUTERS, errno, safe_strerror(errno)); - } - - if (!join) { - zlog_err("IGMP socket fd=%d could not join any group on interface address %s", - fd, inet_ntoa(ifaddr)); - close(fd); - fd = -1; - } - - return fd; + int fd; + int join = 0; + struct in_addr group; + + fd = pim_socket_mcast(IPPROTO_IGMP, ifaddr, ifp, 1); + + if (fd < 0) + return -1; + + if (PIM_IF_TEST_IGMP_LISTEN_ALLROUTERS(pim_options)) { + if (inet_aton(PIM_ALL_ROUTERS, &group)) { + if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex)) + ++join; + } else { + zlog_warn( + "%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, fd, + inet_ntoa(ifaddr), PIM_ALL_ROUTERS, errno, + safe_strerror(errno)); + } + } + + /* + IGMP routers periodically send IGMP general queries to + AllSystems=224.0.0.1 + IGMP routers must receive general queries for querier election. + */ + if (inet_aton(PIM_ALL_SYSTEMS, &group)) { + if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex)) + ++join; + } else { + zlog_warn( + "%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), + PIM_ALL_SYSTEMS, errno, safe_strerror(errno)); + } + + if (inet_aton(PIM_ALL_IGMP_ROUTERS, &group)) { + if (!pim_socket_join(fd, group, ifaddr, ifp->ifindex)) { + ++join; + } + } else { + zlog_warn( + "%s %s: IGMP socket fd=%d interface %s: could not solve %s to group address: errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, fd, inet_ntoa(ifaddr), + PIM_ALL_IGMP_ROUTERS, errno, safe_strerror(errno)); + } + + if (!join) { + zlog_err( + "IGMP socket fd=%d could not join any group on interface address %s", + fd, inet_ntoa(ifaddr)); + close(fd); + fd = -1; + } + + return fd; } #undef IGMP_SOCK_DUMP @@ -106,828 +110,834 @@ static int igmp_sock_open(struct in_addr ifaddr, struct interface *ifp, uint32_t #ifdef IGMP_SOCK_DUMP static void igmp_sock_dump(array_t *igmp_sock_array) { - int size = array_size(igmp_sock_array); - for (int i = 0; i < size; ++i) { - - struct igmp_sock *igmp = array_get(igmp_sock_array, i); - - zlog_debug("%s %s: [%d/%d] igmp_addr=%s fd=%d", - __FILE__, __PRETTY_FUNCTION__, - i, size, - inet_ntoa(igmp->ifaddr), - igmp->fd); - } + int size = array_size(igmp_sock_array); + for (int i = 0; i < size; ++i) { + + struct igmp_sock *igmp = array_get(igmp_sock_array, i); + + zlog_debug("%s %s: [%d/%d] igmp_addr=%s fd=%d", __FILE__, + __PRETTY_FUNCTION__, i, size, + inet_ntoa(igmp->ifaddr), igmp->fd); + } } #endif struct igmp_sock *pim_igmp_sock_lookup_ifaddr(struct list *igmp_sock_list, struct in_addr ifaddr) { - struct listnode *sock_node; - struct igmp_sock *igmp; + struct listnode *sock_node; + struct igmp_sock *igmp; #ifdef IGMP_SOCK_DUMP - igmp_sock_dump(igmp_sock_list); + igmp_sock_dump(igmp_sock_list); #endif - for (ALL_LIST_ELEMENTS_RO(igmp_sock_list, sock_node, igmp)) - if (ifaddr.s_addr == igmp->ifaddr.s_addr) - return igmp; + for (ALL_LIST_ELEMENTS_RO(igmp_sock_list, sock_node, igmp)) + if (ifaddr.s_addr == igmp->ifaddr.s_addr) + return igmp; - return 0; + return 0; } -struct igmp_sock *igmp_sock_lookup_by_fd(struct list *igmp_sock_list, - int fd) +struct igmp_sock *igmp_sock_lookup_by_fd(struct list *igmp_sock_list, int fd) { - struct listnode *sock_node; - struct igmp_sock *igmp; + struct listnode *sock_node; + struct igmp_sock *igmp; - for (ALL_LIST_ELEMENTS_RO(igmp_sock_list, sock_node, igmp)) - if (fd == igmp->fd) - return igmp; + for (ALL_LIST_ELEMENTS_RO(igmp_sock_list, sock_node, igmp)) + if (fd == igmp->fd) + return igmp; - return 0; + return 0; } static int pim_igmp_other_querier_expire(struct thread *t) { - struct igmp_sock *igmp; - - igmp = THREAD_ARG(t); - - zassert(!igmp->t_igmp_query_timer); - - if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - zlog_debug("%s: Querier %s resuming", - __PRETTY_FUNCTION__, - ifaddr_str); - } - - /* - We are the current querier, then - re-start sending general queries. - RFC 2236 - sec 7 Other Querier - present timer expired (Send General - Query, Set Gen. Query. timer) - */ - pim_igmp_general_query(t); - - return 0; + struct igmp_sock *igmp; + + igmp = THREAD_ARG(t); + + zassert(!igmp->t_igmp_query_timer); + + if (PIM_DEBUG_IGMP_TRACE) { + char ifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + zlog_debug("%s: Querier %s resuming", __PRETTY_FUNCTION__, + ifaddr_str); + } + + /* + We are the current querier, then + re-start sending general queries. + RFC 2236 - sec 7 Other Querier + present timer expired (Send General + Query, Set Gen. Query. timer) + */ + pim_igmp_general_query(t); + + return 0; } void pim_igmp_other_querier_timer_on(struct igmp_sock *igmp) { - long other_querier_present_interval_msec; - struct pim_interface *pim_ifp; - - zassert(igmp); - zassert(igmp->interface); - zassert(igmp->interface->info); - - pim_ifp = igmp->interface->info; - - if (igmp->t_other_querier_timer) { - /* - There is other querier present already, - then reset the other-querier-present timer. - */ - - if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - zlog_debug("Querier %s resetting TIMER event for Other-Querier-Present", - ifaddr_str); - } - THREAD_OFF(igmp->t_other_querier_timer); - } - else { - /* - We are the current querier, then stop sending general queries: - igmp->t_igmp_query_timer = NULL; - */ - pim_igmp_general_query_off(igmp); - } - - /* - Since this socket is starting the other-querier-present timer, - there should not be periodic query timer for this socket. - */ - zassert(!igmp->t_igmp_query_timer); - - /* - RFC 3376: 8.5. Other Querier Present Interval - - The Other Querier Present Interval is the length of time that must - pass before a multicast router decides that there is no longer - another multicast router which should be the querier. This value - MUST be ((the Robustness Variable) times (the Query Interval)) plus - (one half of one Query Response Interval). - - other_querier_present_interval_msec = \ - igmp->querier_robustness_variable * \ - 1000 * igmp->querier_query_interval + \ - 100 * (pim_ifp->query_max_response_time_dsec >> 1); - */ - other_querier_present_interval_msec = - PIM_IGMP_OQPI_MSEC(igmp->querier_robustness_variable, - igmp->querier_query_interval, - pim_ifp->igmp_query_max_response_time_dsec); - - if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - zlog_debug("Querier %s scheduling %ld.%03ld sec TIMER event for Other-Querier-Present", - ifaddr_str, - other_querier_present_interval_msec / 1000, - other_querier_present_interval_msec % 1000); - } - - thread_add_timer_msec(master, pim_igmp_other_querier_expire, igmp, - other_querier_present_interval_msec, - &igmp->t_other_querier_timer); + long other_querier_present_interval_msec; + struct pim_interface *pim_ifp; + + zassert(igmp); + zassert(igmp->interface); + zassert(igmp->interface->info); + + pim_ifp = igmp->interface->info; + + if (igmp->t_other_querier_timer) { + /* + There is other querier present already, + then reset the other-querier-present timer. + */ + + if (PIM_DEBUG_IGMP_TRACE) { + char ifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + zlog_debug( + "Querier %s resetting TIMER event for Other-Querier-Present", + ifaddr_str); + } + THREAD_OFF(igmp->t_other_querier_timer); + } else { + /* + We are the current querier, then stop sending general queries: + igmp->t_igmp_query_timer = NULL; + */ + pim_igmp_general_query_off(igmp); + } + + /* + Since this socket is starting the other-querier-present timer, + there should not be periodic query timer for this socket. + */ + zassert(!igmp->t_igmp_query_timer); + + /* + RFC 3376: 8.5. Other Querier Present Interval + + The Other Querier Present Interval is the length of time that must + pass before a multicast router decides that there is no longer + another multicast router which should be the querier. This value + MUST be ((the Robustness Variable) times (the Query Interval)) plus + (one half of one Query Response Interval). + + other_querier_present_interval_msec = \ + igmp->querier_robustness_variable * \ + 1000 * igmp->querier_query_interval + \ + 100 * (pim_ifp->query_max_response_time_dsec >> 1); + */ + other_querier_present_interval_msec = PIM_IGMP_OQPI_MSEC( + igmp->querier_robustness_variable, igmp->querier_query_interval, + pim_ifp->igmp_query_max_response_time_dsec); + + if (PIM_DEBUG_IGMP_TRACE) { + char ifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + zlog_debug( + "Querier %s scheduling %ld.%03ld sec TIMER event for Other-Querier-Present", + ifaddr_str, other_querier_present_interval_msec / 1000, + other_querier_present_interval_msec % 1000); + } + + thread_add_timer_msec(master, pim_igmp_other_querier_expire, igmp, + other_querier_present_interval_msec, + &igmp->t_other_querier_timer); } void pim_igmp_other_querier_timer_off(struct igmp_sock *igmp) { - zassert(igmp); - - if (PIM_DEBUG_IGMP_TRACE) { - if (igmp->t_other_querier_timer) { - char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - zlog_debug("IGMP querier %s fd=%d cancelling other-querier-present TIMER event on %s", - ifaddr_str, igmp->fd, igmp->interface->name); - } - } - THREAD_OFF(igmp->t_other_querier_timer); + zassert(igmp); + + if (PIM_DEBUG_IGMP_TRACE) { + if (igmp->t_other_querier_timer) { + char ifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + zlog_debug( + "IGMP querier %s fd=%d cancelling other-querier-present TIMER event on %s", + ifaddr_str, igmp->fd, igmp->interface->name); + } + } + THREAD_OFF(igmp->t_other_querier_timer); } -static int -igmp_recv_query(struct igmp_sock *igmp, int query_version, - int max_resp_code, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len) +static int igmp_recv_query(struct igmp_sock *igmp, int query_version, + int max_resp_code, struct in_addr from, + const char *from_str, char *igmp_msg, + int igmp_msg_len) { - struct interface *ifp; - struct pim_interface *pim_ifp; - struct in_addr group_addr; - uint16_t recv_checksum; - uint16_t checksum; - - memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); - - ifp = igmp->interface; - pim_ifp = ifp->info; - - recv_checksum = *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET); - - /* for computing checksum */ - *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET) = 0; - - checksum = in_cksum(igmp_msg, igmp_msg_len); - if (checksum != recv_checksum) { - zlog_warn("Recv IGMP query v%d from %s on %s: checksum mismatch: received=%x computed=%x", - query_version, from_str, ifp->name, recv_checksum, checksum); - return -1; - } - - /* RFC 3376 defines some guidelines on operating in backwards compatibility - * with older versions of IGMP but there are some gaps in the logic: - * - * - once we drop from say version 3 to version 2 we will never go back to - * version 3 even if the node that TXed an IGMP v2 query upgrades to v3 - * - * - The node with the lowest IP is the querier so we will only know to drop - * from v3 to v2 if the node that is the querier is also the one that is - * running igmp v2. If a non-querier only supports igmp v2 we will have - * no way of knowing. - * - * For now we will simplify things and inform the user that they need to - * configure all PIM routers to use the same version of IGMP. - */ - if (query_version != pim_ifp->igmp_version) { - zlog_warn("Recv IGMP query v%d from %s on %s but we are using v%d, please " - "configure all PIM routers on this subnet to use the same " - "IGMP version", - query_version, from_str, ifp->name, pim_ifp->igmp_version); - return 0; - } - - if (PIM_DEBUG_IGMP_PACKETS) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - zlog_debug("Recv IGMP query v%d from %s on %s for group %s", - query_version, from_str, ifp->name, group_str); - } - - /* - RFC 3376: 6.6.2. Querier Election - - When a router receives a query with a lower IP address, it sets - the Other-Querier-Present timer to Other Querier Present Interval - and ceases to send queries on the network if it was the previously - elected querier. - */ - if (ntohl(from.s_addr) < ntohl(igmp->ifaddr.s_addr)) { - - if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - zlog_debug("%s: local address %s (%u) lost querier election to %s (%u)", - ifp->name, - ifaddr_str, ntohl(igmp->ifaddr.s_addr), - from_str, ntohl(from.s_addr)); - } - - pim_igmp_other_querier_timer_on(igmp); - } - - /* IGMP version 3 is the only one where we process the RXed query */ - if (query_version == 3) { - igmp_v3_recv_query(igmp, from_str, igmp_msg); - } - - return 0; + struct interface *ifp; + struct pim_interface *pim_ifp; + struct in_addr group_addr; + uint16_t recv_checksum; + uint16_t checksum; + + memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); + + ifp = igmp->interface; + pim_ifp = ifp->info; + + recv_checksum = *(uint16_t *)(igmp_msg + IGMP_CHECKSUM_OFFSET); + + /* for computing checksum */ + *(uint16_t *)(igmp_msg + IGMP_CHECKSUM_OFFSET) = 0; + + checksum = in_cksum(igmp_msg, igmp_msg_len); + if (checksum != recv_checksum) { + zlog_warn( + "Recv IGMP query v%d from %s on %s: checksum mismatch: received=%x computed=%x", + query_version, from_str, ifp->name, recv_checksum, + checksum); + return -1; + } + + /* RFC 3376 defines some guidelines on operating in backwards + * compatibility + * with older versions of IGMP but there are some gaps in the logic: + * + * - once we drop from say version 3 to version 2 we will never go back + * to + * version 3 even if the node that TXed an IGMP v2 query upgrades to + * v3 + * + * - The node with the lowest IP is the querier so we will only know to + * drop + * from v3 to v2 if the node that is the querier is also the one that + * is + * running igmp v2. If a non-querier only supports igmp v2 we will + * have + * no way of knowing. + * + * For now we will simplify things and inform the user that they need to + * configure all PIM routers to use the same version of IGMP. + */ + if (query_version != pim_ifp->igmp_version) { + zlog_warn( + "Recv IGMP query v%d from %s on %s but we are using v%d, please " + "configure all PIM routers on this subnet to use the same " + "IGMP version", + query_version, from_str, ifp->name, + pim_ifp->igmp_version); + return 0; + } + + if (PIM_DEBUG_IGMP_PACKETS) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group_addr, group_str, + sizeof(group_str)); + zlog_debug("Recv IGMP query v%d from %s on %s for group %s", + query_version, from_str, ifp->name, group_str); + } + + /* + RFC 3376: 6.6.2. Querier Election + + When a router receives a query with a lower IP address, it sets + the Other-Querier-Present timer to Other Querier Present Interval + and ceases to send queries on the network if it was the previously + elected querier. + */ + if (ntohl(from.s_addr) < ntohl(igmp->ifaddr.s_addr)) { + + if (PIM_DEBUG_IGMP_TRACE) { + char ifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + zlog_debug( + "%s: local address %s (%u) lost querier election to %s (%u)", + ifp->name, ifaddr_str, + ntohl(igmp->ifaddr.s_addr), from_str, + ntohl(from.s_addr)); + } + + pim_igmp_other_querier_timer_on(igmp); + } + + /* IGMP version 3 is the only one where we process the RXed query */ + if (query_version == 3) { + igmp_v3_recv_query(igmp, from_str, igmp_msg); + } + + return 0; } -static void on_trace(const char *label, - struct interface *ifp, struct in_addr from) +static void on_trace(const char *label, struct interface *ifp, + struct in_addr from) { - if (PIM_DEBUG_IGMP_TRACE) { - char from_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", from, from_str, sizeof(from_str)); - zlog_debug("%s: from %s on %s", - label, from_str, ifp->name); - } + if (PIM_DEBUG_IGMP_TRACE) { + char from_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", from, from_str, sizeof(from_str)); + zlog_debug("%s: from %s on %s", label, from_str, ifp->name); + } } -static int -igmp_v1_recv_report (struct igmp_sock *igmp, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len) +static int igmp_v1_recv_report(struct igmp_sock *igmp, struct in_addr from, + const char *from_str, char *igmp_msg, + int igmp_msg_len) { - struct interface *ifp = igmp->interface; - struct igmp_group *group; - struct in_addr group_addr; + struct interface *ifp = igmp->interface; + struct igmp_group *group; + struct in_addr group_addr; - on_trace(__PRETTY_FUNCTION__, igmp->interface, from); + on_trace(__PRETTY_FUNCTION__, igmp->interface, from); - if (igmp_msg_len != IGMP_V12_MSG_SIZE) { - zlog_warn("Recv IGMP report v1 from %s on %s: size=%d other than correct=%d", - from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); - return -1; - } + if (igmp_msg_len != IGMP_V12_MSG_SIZE) { + zlog_warn( + "Recv IGMP report v1 from %s on %s: size=%d other than correct=%d", + from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); + return -1; + } - if (PIM_DEBUG_IGMP_TRACE) { - zlog_warn("%s %s: FIXME WRITEME", - __FILE__, __PRETTY_FUNCTION__); - } + if (PIM_DEBUG_IGMP_TRACE) { + zlog_warn("%s %s: FIXME WRITEME", __FILE__, + __PRETTY_FUNCTION__); + } - memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); + memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); - /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr); - if (!group) { - return -1; - } + /* non-existant group is created as INCLUDE {empty} */ + group = igmp_add_group_by_addr(igmp, group_addr); + if (!group) { + return -1; + } - group->last_igmp_v1_report_dsec = pim_time_monotonic_dsec(); + group->last_igmp_v1_report_dsec = pim_time_monotonic_dsec(); - return 0; + return 0; } int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len) { - struct ip *ip_hdr; - size_t ip_hlen; /* ip header length in bytes */ - char *igmp_msg; - int igmp_msg_len; - int msg_type; - char from_str[INET_ADDRSTRLEN]; - char to_str[INET_ADDRSTRLEN]; - - if (len < sizeof(*ip_hdr)) { - zlog_warn("IGMP packet size=%zu shorter than minimum=%zu", - len, sizeof(*ip_hdr)); - return -1; - } - - ip_hdr = (struct ip *) buf; - - pim_inet4_dump("", ip_hdr->ip_src, from_str , sizeof(from_str)); - pim_inet4_dump("", ip_hdr->ip_dst, to_str , sizeof(to_str)); - - ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */ - - if (PIM_DEBUG_IGMP_PACKETS) { - zlog_debug("Recv IP packet from %s to %s on %s: size=%zu ip_header_size=%zu ip_proto=%d", - from_str, to_str, igmp->interface->name, len, ip_hlen, ip_hdr->ip_p); - } - - igmp_msg = buf + ip_hlen; - msg_type = *igmp_msg; - igmp_msg_len = len - ip_hlen; - - if (PIM_DEBUG_IGMP_PACKETS) { - zlog_debug("Recv IGMP packet from %s to %s on %s: ttl=%d msg_type=%d msg_size=%d", - from_str, to_str, igmp->interface->name, ip_hdr->ip_ttl, msg_type, - igmp_msg_len); - } - - if (igmp_msg_len < PIM_IGMP_MIN_LEN) { - zlog_warn("IGMP message size=%d shorter than minimum=%d", - igmp_msg_len, PIM_IGMP_MIN_LEN); - return -1; - } - - switch (msg_type) { - case PIM_IGMP_MEMBERSHIP_QUERY: - { - int max_resp_code = igmp_msg[1]; - int query_version; - - /* - RFC 3376: 7.1. Query Version Distinctions - IGMPv1 Query: length = 8 octets AND Max Resp Code field is zero - IGMPv2 Query: length = 8 octets AND Max Resp Code field is non-zero - IGMPv3 Query: length >= 12 octets - */ - - if (igmp_msg_len == 8) { - query_version = max_resp_code ? 2 : 1; - } - else if (igmp_msg_len >= 12) { - query_version = 3; - } - else { - zlog_warn("Unknown IGMP query version"); - return -1; - } + struct ip *ip_hdr; + size_t ip_hlen; /* ip header length in bytes */ + char *igmp_msg; + int igmp_msg_len; + int msg_type; + char from_str[INET_ADDRSTRLEN]; + char to_str[INET_ADDRSTRLEN]; + + if (len < sizeof(*ip_hdr)) { + zlog_warn("IGMP packet size=%zu shorter than minimum=%zu", len, + sizeof(*ip_hdr)); + return -1; + } + + ip_hdr = (struct ip *)buf; + + pim_inet4_dump("", ip_hdr->ip_src, from_str, sizeof(from_str)); + pim_inet4_dump("", ip_hdr->ip_dst, to_str, sizeof(to_str)); + + ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */ - return igmp_recv_query(igmp, query_version, max_resp_code, - ip_hdr->ip_src, from_str, - igmp_msg, igmp_msg_len); - } + if (PIM_DEBUG_IGMP_PACKETS) { + zlog_debug( + "Recv IP packet from %s to %s on %s: size=%zu ip_header_size=%zu ip_proto=%d", + from_str, to_str, igmp->interface->name, len, ip_hlen, + ip_hdr->ip_p); + } + + igmp_msg = buf + ip_hlen; + msg_type = *igmp_msg; + igmp_msg_len = len - ip_hlen; + + if (PIM_DEBUG_IGMP_PACKETS) { + zlog_debug( + "Recv IGMP packet from %s to %s on %s: ttl=%d msg_type=%d msg_size=%d", + from_str, to_str, igmp->interface->name, ip_hdr->ip_ttl, + msg_type, igmp_msg_len); + } - case PIM_IGMP_V3_MEMBERSHIP_REPORT: - return igmp_v3_recv_report(igmp, ip_hdr->ip_src, from_str, - igmp_msg, igmp_msg_len); + if (igmp_msg_len < PIM_IGMP_MIN_LEN) { + zlog_warn("IGMP message size=%d shorter than minimum=%d", + igmp_msg_len, PIM_IGMP_MIN_LEN); + return -1; + } + + switch (msg_type) { + case PIM_IGMP_MEMBERSHIP_QUERY: { + int max_resp_code = igmp_msg[1]; + int query_version; + + /* + RFC 3376: 7.1. Query Version Distinctions + IGMPv1 Query: length = 8 octets AND Max Resp Code field is + zero + IGMPv2 Query: length = 8 octets AND Max Resp Code field is + non-zero + IGMPv3 Query: length >= 12 octets + */ + + if (igmp_msg_len == 8) { + query_version = max_resp_code ? 2 : 1; + } else if (igmp_msg_len >= 12) { + query_version = 3; + } else { + zlog_warn("Unknown IGMP query version"); + return -1; + } + + return igmp_recv_query(igmp, query_version, max_resp_code, + ip_hdr->ip_src, from_str, igmp_msg, + igmp_msg_len); + } - case PIM_IGMP_V2_MEMBERSHIP_REPORT: - return igmp_v2_recv_report(igmp, ip_hdr->ip_src, from_str, - igmp_msg, igmp_msg_len); + case PIM_IGMP_V3_MEMBERSHIP_REPORT: + return igmp_v3_recv_report(igmp, ip_hdr->ip_src, from_str, + igmp_msg, igmp_msg_len); - case PIM_IGMP_V1_MEMBERSHIP_REPORT: - return igmp_v1_recv_report(igmp, ip_hdr->ip_src, from_str, - igmp_msg, igmp_msg_len); + case PIM_IGMP_V2_MEMBERSHIP_REPORT: + return igmp_v2_recv_report(igmp, ip_hdr->ip_src, from_str, + igmp_msg, igmp_msg_len); - case PIM_IGMP_V2_LEAVE_GROUP: - return igmp_v2_recv_leave(igmp, ip_hdr->ip_src, from_str, - igmp_msg, igmp_msg_len); - } + case PIM_IGMP_V1_MEMBERSHIP_REPORT: + return igmp_v1_recv_report(igmp, ip_hdr->ip_src, from_str, + igmp_msg, igmp_msg_len); - zlog_warn("Ignoring unsupported IGMP message type: %d", msg_type); + case PIM_IGMP_V2_LEAVE_GROUP: + return igmp_v2_recv_leave(igmp, ip_hdr->ip_src, from_str, + igmp_msg, igmp_msg_len); + } - return -1; + zlog_warn("Ignoring unsupported IGMP message type: %d", msg_type); + + return -1; } void pim_igmp_general_query_on(struct igmp_sock *igmp) { - struct pim_interface *pim_ifp; - int startup_mode; - int query_interval; - - /* - Since this socket is starting as querier, - there should not exist a timer for other-querier-present. - */ - zassert(!igmp->t_other_querier_timer); - pim_ifp = igmp->interface->info; - zassert(pim_ifp); - - /* - RFC 3376: 8.6. Startup Query Interval - - The Startup Query Interval is the interval between General Queries - sent by a Querier on startup. Default: 1/4 the Query Interval. - The first one should be sent out immediately instead of 125/4 - seconds from now. - */ - startup_mode = igmp->startup_query_count > 0; - if (startup_mode) { - /* - * If this is the first time we are sending a query on a - * newly configured igmp interface send it out in 1 second - * just to give the entire world a tiny bit of time to settle - * else the query interval is: - * query_interval = pim_ifp->igmp_default_query_interval >> 2; - */ - if (igmp->startup_query_count == igmp->querier_robustness_variable) - query_interval = 1; - else - query_interval = PIM_IGMP_SQI(pim_ifp->igmp_default_query_interval); - - --igmp->startup_query_count; - } - else { - query_interval = igmp->querier_query_interval; - } - - if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - zlog_debug("Querier %s scheduling %d-second (%s) TIMER event for IGMP query on fd=%d", - ifaddr_str, - query_interval, - startup_mode ? "startup" : "non-startup", - igmp->fd); - } - igmp->t_igmp_query_timer = NULL; - thread_add_timer(master, pim_igmp_general_query, igmp, query_interval, - &igmp->t_igmp_query_timer); + struct pim_interface *pim_ifp; + int startup_mode; + int query_interval; + + /* + Since this socket is starting as querier, + there should not exist a timer for other-querier-present. + */ + zassert(!igmp->t_other_querier_timer); + pim_ifp = igmp->interface->info; + zassert(pim_ifp); + + /* + RFC 3376: 8.6. Startup Query Interval + + The Startup Query Interval is the interval between General Queries + sent by a Querier on startup. Default: 1/4 the Query Interval. + The first one should be sent out immediately instead of 125/4 + seconds from now. + */ + startup_mode = igmp->startup_query_count > 0; + if (startup_mode) { + /* + * If this is the first time we are sending a query on a + * newly configured igmp interface send it out in 1 second + * just to give the entire world a tiny bit of time to settle + * else the query interval is: + * query_interval = pim_ifp->igmp_default_query_interval >> 2; + */ + if (igmp->startup_query_count + == igmp->querier_robustness_variable) + query_interval = 1; + else + query_interval = PIM_IGMP_SQI( + pim_ifp->igmp_default_query_interval); + + --igmp->startup_query_count; + } else { + query_interval = igmp->querier_query_interval; + } + + if (PIM_DEBUG_IGMP_TRACE) { + char ifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + zlog_debug( + "Querier %s scheduling %d-second (%s) TIMER event for IGMP query on fd=%d", + ifaddr_str, query_interval, + startup_mode ? "startup" : "non-startup", igmp->fd); + } + igmp->t_igmp_query_timer = NULL; + thread_add_timer(master, pim_igmp_general_query, igmp, query_interval, + &igmp->t_igmp_query_timer); } void pim_igmp_general_query_off(struct igmp_sock *igmp) { - zassert(igmp); - - if (PIM_DEBUG_IGMP_TRACE) { - if (igmp->t_igmp_query_timer) { - char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - zlog_debug("IGMP querier %s fd=%d cancelling query TIMER event on %s", - ifaddr_str, igmp->fd, igmp->interface->name); - } - } - THREAD_OFF(igmp->t_igmp_query_timer); + zassert(igmp); + + if (PIM_DEBUG_IGMP_TRACE) { + if (igmp->t_igmp_query_timer) { + char ifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + zlog_debug( + "IGMP querier %s fd=%d cancelling query TIMER event on %s", + ifaddr_str, igmp->fd, igmp->interface->name); + } + } + THREAD_OFF(igmp->t_igmp_query_timer); } /* Issue IGMP general query */ static int pim_igmp_general_query(struct thread *t) { - struct igmp_sock *igmp; - struct in_addr dst_addr; - struct in_addr group_addr; - struct pim_interface *pim_ifp; - int query_buf_size; - - igmp = THREAD_ARG(t); - - zassert(igmp->interface); - zassert(igmp->interface->info); - - pim_ifp = igmp->interface->info; - - if (pim_ifp->igmp_version == 3) { - query_buf_size = PIM_IGMP_BUFSIZE_WRITE; - } else { - query_buf_size = IGMP_V12_MSG_SIZE; - } - - char query_buf[query_buf_size]; - - /* - RFC3376: 4.1.12. IP Destination Addresses for Queries - - In IGMPv3, General Queries are sent with an IP destination address - of 224.0.0.1, the all-systems multicast address. Group-Specific - and Group-and-Source-Specific Queries are sent with an IP - destination address equal to the multicast address of interest. - */ - - dst_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); - group_addr.s_addr = PIM_NET_INADDR_ANY; - - if (PIM_DEBUG_IGMP_TRACE) { - char querier_str[INET_ADDRSTRLEN]; - char dst_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", igmp->ifaddr, querier_str, - sizeof(querier_str)); - pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); - zlog_debug("Querier %s issuing IGMP general query to %s on %s", - querier_str, dst_str, igmp->interface->name); - } - - igmp_send_query (pim_ifp->igmp_version, - 0 /* igmp_group */, - igmp->fd, - igmp->interface->name, - query_buf, - sizeof(query_buf), - 0 /* num_sources */, - dst_addr, - group_addr, - pim_ifp->igmp_query_max_response_time_dsec, - 1 /* s_flag: always set for general queries */, - igmp->querier_robustness_variable, - igmp->querier_query_interval); - - pim_igmp_general_query_on(igmp); - - return 0; + struct igmp_sock *igmp; + struct in_addr dst_addr; + struct in_addr group_addr; + struct pim_interface *pim_ifp; + int query_buf_size; + + igmp = THREAD_ARG(t); + + zassert(igmp->interface); + zassert(igmp->interface->info); + + pim_ifp = igmp->interface->info; + + if (pim_ifp->igmp_version == 3) { + query_buf_size = PIM_IGMP_BUFSIZE_WRITE; + } else { + query_buf_size = IGMP_V12_MSG_SIZE; + } + + char query_buf[query_buf_size]; + + /* + RFC3376: 4.1.12. IP Destination Addresses for Queries + + In IGMPv3, General Queries are sent with an IP destination address + of 224.0.0.1, the all-systems multicast address. Group-Specific + and Group-and-Source-Specific Queries are sent with an IP + destination address equal to the multicast address of interest. + */ + + dst_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); + group_addr.s_addr = PIM_NET_INADDR_ANY; + + if (PIM_DEBUG_IGMP_TRACE) { + char querier_str[INET_ADDRSTRLEN]; + char dst_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", igmp->ifaddr, querier_str, + sizeof(querier_str)); + pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); + zlog_debug("Querier %s issuing IGMP general query to %s on %s", + querier_str, dst_str, igmp->interface->name); + } + + igmp_send_query(pim_ifp->igmp_version, 0 /* igmp_group */, igmp->fd, + igmp->interface->name, query_buf, sizeof(query_buf), + 0 /* num_sources */, dst_addr, group_addr, + pim_ifp->igmp_query_max_response_time_dsec, + 1 /* s_flag: always set for general queries */, + igmp->querier_robustness_variable, + igmp->querier_query_interval); + + pim_igmp_general_query_on(igmp); + + return 0; } static void sock_close(struct igmp_sock *igmp) { - pim_igmp_other_querier_timer_off(igmp); - pim_igmp_general_query_off(igmp); - - if (PIM_DEBUG_IGMP_TRACE_DETAIL) { - if (igmp->t_igmp_read) { - zlog_debug("Cancelling READ event on IGMP socket %s fd=%d on interface %s", - inet_ntoa(igmp->ifaddr), igmp->fd, - igmp->interface->name); - } - } - THREAD_OFF(igmp->t_igmp_read); - - if (close(igmp->fd)) { - zlog_err("Failure closing IGMP socket %s fd=%d on interface %s: errno=%d: %s", - inet_ntoa(igmp->ifaddr), igmp->fd, igmp->interface->name, - errno, safe_strerror(errno)); - } - - if (PIM_DEBUG_IGMP_TRACE_DETAIL) { - zlog_debug("Deleted IGMP socket %s fd=%d on interface %s", - inet_ntoa(igmp->ifaddr), igmp->fd, igmp->interface->name); - } + pim_igmp_other_querier_timer_off(igmp); + pim_igmp_general_query_off(igmp); + + if (PIM_DEBUG_IGMP_TRACE_DETAIL) { + if (igmp->t_igmp_read) { + zlog_debug( + "Cancelling READ event on IGMP socket %s fd=%d on interface %s", + inet_ntoa(igmp->ifaddr), igmp->fd, + igmp->interface->name); + } + } + THREAD_OFF(igmp->t_igmp_read); + + if (close(igmp->fd)) { + zlog_err( + "Failure closing IGMP socket %s fd=%d on interface %s: errno=%d: %s", + inet_ntoa(igmp->ifaddr), igmp->fd, + igmp->interface->name, errno, safe_strerror(errno)); + } + + if (PIM_DEBUG_IGMP_TRACE_DETAIL) { + zlog_debug("Deleted IGMP socket %s fd=%d on interface %s", + inet_ntoa(igmp->ifaddr), igmp->fd, + igmp->interface->name); + } } void igmp_startup_mode_on(struct igmp_sock *igmp) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - pim_ifp = igmp->interface->info; + pim_ifp = igmp->interface->info; - /* - RFC 3376: 8.7. Startup Query Count + /* + RFC 3376: 8.7. Startup Query Count - The Startup Query Count is the number of Queries sent out on - startup, separated by the Startup Query Interval. Default: the - Robustness Variable. - */ - igmp->startup_query_count = igmp->querier_robustness_variable; + The Startup Query Count is the number of Queries sent out on + startup, separated by the Startup Query Interval. Default: the + Robustness Variable. + */ + igmp->startup_query_count = igmp->querier_robustness_variable; - /* - Since we're (re)starting, reset QQI to default Query Interval - */ - igmp->querier_query_interval = pim_ifp->igmp_default_query_interval; + /* + Since we're (re)starting, reset QQI to default Query Interval + */ + igmp->querier_query_interval = pim_ifp->igmp_default_query_interval; } static void igmp_group_free(struct igmp_group *group) { - list_free(group->group_source_list); + list_free(group->group_source_list); - XFREE(MTYPE_PIM_IGMP_GROUP, group); + XFREE(MTYPE_PIM_IGMP_GROUP, group); } static void igmp_group_delete(struct igmp_group *group) { - struct listnode *src_node; - struct listnode *src_nextnode; - struct igmp_source *src; - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("Deleting IGMP group %s from socket %d interface %s", - group_str, - group->group_igmp_sock->fd, - group->group_igmp_sock->interface->name); - } - - for (ALL_LIST_ELEMENTS(group->group_source_list, src_node, src_nextnode, src)) { - igmp_source_delete(src); - } - - if (group->t_group_query_retransmit_timer) { - THREAD_OFF(group->t_group_query_retransmit_timer); - } - - group_timer_off(group); - listnode_delete(group->group_igmp_sock->igmp_group_list, group); - hash_release (group->group_igmp_sock->igmp_group_hash, group); - - igmp_group_free(group); + struct listnode *src_node; + struct listnode *src_nextnode; + struct igmp_source *src; + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug("Deleting IGMP group %s from socket %d interface %s", + group_str, group->group_igmp_sock->fd, + group->group_igmp_sock->interface->name); + } + + for (ALL_LIST_ELEMENTS(group->group_source_list, src_node, src_nextnode, + src)) { + igmp_source_delete(src); + } + + if (group->t_group_query_retransmit_timer) { + THREAD_OFF(group->t_group_query_retransmit_timer); + } + + group_timer_off(group); + listnode_delete(group->group_igmp_sock->igmp_group_list, group); + hash_release(group->group_igmp_sock->igmp_group_hash, group); + + igmp_group_free(group); } void igmp_group_delete_empty_include(struct igmp_group *group) { - zassert(!group->group_filtermode_isexcl); - zassert(!listcount(group->group_source_list)); + zassert(!group->group_filtermode_isexcl); + zassert(!listcount(group->group_source_list)); - igmp_group_delete(group); + igmp_group_delete(group); } void igmp_sock_free(struct igmp_sock *igmp) { - zassert(!igmp->t_igmp_read); - zassert(!igmp->t_igmp_query_timer); - zassert(!igmp->t_other_querier_timer); - zassert(igmp->igmp_group_list); - zassert(!listcount(igmp->igmp_group_list)); + zassert(!igmp->t_igmp_read); + zassert(!igmp->t_igmp_query_timer); + zassert(!igmp->t_other_querier_timer); + zassert(igmp->igmp_group_list); + zassert(!listcount(igmp->igmp_group_list)); - list_free(igmp->igmp_group_list); - hash_free(igmp->igmp_group_hash); + list_free(igmp->igmp_group_list); + hash_free(igmp->igmp_group_hash); - XFREE(MTYPE_PIM_IGMP_SOCKET, igmp); + XFREE(MTYPE_PIM_IGMP_SOCKET, igmp); } void igmp_sock_delete(struct igmp_sock *igmp) { - struct pim_interface *pim_ifp; - struct listnode *grp_node; - struct listnode *grp_nextnode; - struct igmp_group *grp; - - for (ALL_LIST_ELEMENTS(igmp->igmp_group_list, grp_node, grp_nextnode, grp)) { - igmp_group_delete(grp); - } + struct pim_interface *pim_ifp; + struct listnode *grp_node; + struct listnode *grp_nextnode; + struct igmp_group *grp; + + for (ALL_LIST_ELEMENTS(igmp->igmp_group_list, grp_node, grp_nextnode, + grp)) { + igmp_group_delete(grp); + } - sock_close(igmp); + sock_close(igmp); - pim_ifp = igmp->interface->info; + pim_ifp = igmp->interface->info; - listnode_delete(pim_ifp->igmp_socket_list, igmp); + listnode_delete(pim_ifp->igmp_socket_list, igmp); - igmp_sock_free(igmp); + igmp_sock_free(igmp); } -void -igmp_sock_delete_all (struct interface *ifp) +void igmp_sock_delete_all(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *igmp_node, *igmp_nextnode; - struct igmp_sock *igmp; + struct pim_interface *pim_ifp; + struct listnode *igmp_node, *igmp_nextnode; + struct igmp_sock *igmp; - pim_ifp = ifp->info; + pim_ifp = ifp->info; - for (ALL_LIST_ELEMENTS (pim_ifp->igmp_socket_list, igmp_node, - igmp_nextnode, igmp)) - { - igmp_sock_delete(igmp); - } + for (ALL_LIST_ELEMENTS(pim_ifp->igmp_socket_list, igmp_node, + igmp_nextnode, igmp)) { + igmp_sock_delete(igmp); + } } -static unsigned int -igmp_group_hash_key (void *arg) +static unsigned int igmp_group_hash_key(void *arg) { - struct igmp_group *group = (struct igmp_group *)arg; + struct igmp_group *group = (struct igmp_group *)arg; - return jhash_1word(group->group_addr.s_addr, 0); + return jhash_1word(group->group_addr.s_addr, 0); } -static int -igmp_group_hash_equal (const void *arg1, const void *arg2) +static int igmp_group_hash_equal(const void *arg1, const void *arg2) { - const struct igmp_group *g1 = (const struct igmp_group *)arg1; - const struct igmp_group *g2 = (const struct igmp_group *)arg2; + const struct igmp_group *g1 = (const struct igmp_group *)arg1; + const struct igmp_group *g2 = (const struct igmp_group *)arg2; - if (g1->group_addr.s_addr == g2->group_addr.s_addr) - return 1; + if (g1->group_addr.s_addr == g2->group_addr.s_addr) + return 1; - return 0; + return 0; } -static struct igmp_sock *igmp_sock_new(int fd, - struct in_addr ifaddr, +static struct igmp_sock *igmp_sock_new(int fd, struct in_addr ifaddr, struct interface *ifp) { - struct pim_interface *pim_ifp; - struct igmp_sock *igmp; - - pim_ifp = ifp->info; - - if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug("Creating IGMP socket fd=%d for address %s on interface %s", - fd, inet_ntoa(ifaddr), ifp->name); - } - - igmp = XCALLOC(MTYPE_PIM_IGMP_SOCKET, sizeof(*igmp)); - if (!igmp) { - zlog_warn("%s %s: XCALLOC() failure", - __FILE__, __PRETTY_FUNCTION__); - return 0; - } - - igmp->igmp_group_list = list_new(); - if (!igmp->igmp_group_list) { - zlog_err("%s %s: failure: igmp_group_list = list_new()", - __FILE__, __PRETTY_FUNCTION__); - return 0; - } - igmp->igmp_group_list->del = (void (*)(void *)) igmp_group_free; - - igmp->igmp_group_hash = hash_create (igmp_group_hash_key, - igmp_group_hash_equal, NULL); - - igmp->fd = fd; - igmp->interface = ifp; - igmp->ifaddr = ifaddr; - igmp->t_igmp_read = NULL; - igmp->t_igmp_query_timer = NULL; - igmp->t_other_querier_timer = NULL; /* no other querier present */ - igmp->querier_robustness_variable = pim_ifp->igmp_default_robustness_variable; - igmp->sock_creation = pim_time_monotonic_sec(); - - /* - igmp_startup_mode_on() will reset QQI: - - igmp->querier_query_interval = pim_ifp->igmp_default_query_interval; - */ - igmp_startup_mode_on(igmp); - pim_igmp_general_query_on(igmp); - - return igmp; + struct pim_interface *pim_ifp; + struct igmp_sock *igmp; + + pim_ifp = ifp->info; + + if (PIM_DEBUG_IGMP_TRACE) { + zlog_debug( + "Creating IGMP socket fd=%d for address %s on interface %s", + fd, inet_ntoa(ifaddr), ifp->name); + } + + igmp = XCALLOC(MTYPE_PIM_IGMP_SOCKET, sizeof(*igmp)); + if (!igmp) { + zlog_warn("%s %s: XCALLOC() failure", __FILE__, + __PRETTY_FUNCTION__); + return 0; + } + + igmp->igmp_group_list = list_new(); + if (!igmp->igmp_group_list) { + zlog_err("%s %s: failure: igmp_group_list = list_new()", + __FILE__, __PRETTY_FUNCTION__); + return 0; + } + igmp->igmp_group_list->del = (void (*)(void *))igmp_group_free; + + igmp->igmp_group_hash = + hash_create(igmp_group_hash_key, igmp_group_hash_equal, NULL); + + igmp->fd = fd; + igmp->interface = ifp; + igmp->ifaddr = ifaddr; + igmp->t_igmp_read = NULL; + igmp->t_igmp_query_timer = NULL; + igmp->t_other_querier_timer = NULL; /* no other querier present */ + igmp->querier_robustness_variable = + pim_ifp->igmp_default_robustness_variable; + igmp->sock_creation = pim_time_monotonic_sec(); + + /* + igmp_startup_mode_on() will reset QQI: + + igmp->querier_query_interval = pim_ifp->igmp_default_query_interval; + */ + igmp_startup_mode_on(igmp); + pim_igmp_general_query_on(igmp); + + return igmp; } -static void igmp_read_on (struct igmp_sock *igmp); +static void igmp_read_on(struct igmp_sock *igmp); -static int -pim_igmp_read (struct thread *t) +static int pim_igmp_read(struct thread *t) { - uint8_t buf[10000]; - struct igmp_sock *igmp = (struct igmp_sock *)THREAD_ARG(t); - struct sockaddr_in from; - struct sockaddr_in to; - socklen_t fromlen = sizeof(from); - socklen_t tolen = sizeof(to); - ifindex_t ifindex = -1; - int cont = 1; - int len; - - while (cont) - { - len = pim_socket_recvfromto(igmp->fd, buf, sizeof(buf), - &from, &fromlen, - &to, &tolen, - &ifindex); - if (len < 0) - { - if (errno == EINTR) - continue; - if (errno == EWOULDBLOCK || errno == EAGAIN) - break; - - goto done; + uint8_t buf[10000]; + struct igmp_sock *igmp = (struct igmp_sock *)THREAD_ARG(t); + struct sockaddr_in from; + struct sockaddr_in to; + socklen_t fromlen = sizeof(from); + socklen_t tolen = sizeof(to); + ifindex_t ifindex = -1; + int cont = 1; + int len; + + while (cont) { + len = pim_socket_recvfromto(igmp->fd, buf, sizeof(buf), &from, + &fromlen, &to, &tolen, &ifindex); + if (len < 0) { + if (errno == EINTR) + continue; + if (errno == EWOULDBLOCK || errno == EAGAIN) + break; + + goto done; + } } - } - done: - igmp_read_on(igmp); - return 0; +done: + igmp_read_on(igmp); + return 0; } -static void -igmp_read_on (struct igmp_sock *igmp) +static void igmp_read_on(struct igmp_sock *igmp) { - if (PIM_DEBUG_IGMP_TRACE_DETAIL) { - zlog_debug("Scheduling READ event on IGMP socket fd=%d", - igmp->fd); - } - igmp->t_igmp_read = NULL; - thread_add_read(master, pim_igmp_read, igmp, igmp->fd, &igmp->t_igmp_read); - + if (PIM_DEBUG_IGMP_TRACE_DETAIL) { + zlog_debug("Scheduling READ event on IGMP socket fd=%d", + igmp->fd); + } + igmp->t_igmp_read = NULL; + thread_add_read(master, pim_igmp_read, igmp, igmp->fd, + &igmp->t_igmp_read); } struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list, struct in_addr ifaddr, struct interface *ifp) { - struct pim_interface *pim_ifp; - struct igmp_sock *igmp; - int fd; + struct pim_interface *pim_ifp; + struct igmp_sock *igmp; + int fd; - pim_ifp = ifp->info; + pim_ifp = ifp->info; - fd = igmp_sock_open(ifaddr, ifp, pim_ifp->options); - if (fd < 0) { - zlog_warn("Could not open IGMP socket for %s on %s", - inet_ntoa(ifaddr), ifp->name); - return 0; - } + fd = igmp_sock_open(ifaddr, ifp, pim_ifp->options); + if (fd < 0) { + zlog_warn("Could not open IGMP socket for %s on %s", + inet_ntoa(ifaddr), ifp->name); + return 0; + } - igmp = igmp_sock_new(fd, ifaddr, ifp); - if (!igmp) { - zlog_err("%s %s: igmp_sock_new() failure", - __FILE__, __PRETTY_FUNCTION__); - close(fd); - return 0; - } + igmp = igmp_sock_new(fd, ifaddr, ifp); + if (!igmp) { + zlog_err("%s %s: igmp_sock_new() failure", __FILE__, + __PRETTY_FUNCTION__); + close(fd); + return 0; + } - igmp_read_on (igmp); + igmp_read_on(igmp); - listnode_add(igmp_sock_list, igmp); + listnode_add(igmp_sock_list, igmp); #ifdef IGMP_SOCK_DUMP - igmp_sock_dump(igmp_sock_array); + igmp_sock_dump(igmp_sock_array); #endif - return igmp; + return igmp; } /* @@ -946,210 +956,203 @@ struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list, */ static int igmp_group_timer(struct thread *t) { - struct igmp_group *group; + struct igmp_group *group; - group = THREAD_ARG(t); + group = THREAD_ARG(t); - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("%s: Timer for group %s on interface %s", - __PRETTY_FUNCTION__, - group_str, group->group_igmp_sock->interface->name); - } + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug("%s: Timer for group %s on interface %s", + __PRETTY_FUNCTION__, group_str, + group->group_igmp_sock->interface->name); + } - zassert(group->group_filtermode_isexcl); + zassert(group->group_filtermode_isexcl); - group->group_filtermode_isexcl = 0; + group->group_filtermode_isexcl = 0; - /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ - igmp_anysource_forward_stop(group); + /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ + igmp_anysource_forward_stop(group); - igmp_source_delete_expired(group->group_source_list); + igmp_source_delete_expired(group->group_source_list); - zassert(!group->group_filtermode_isexcl); + zassert(!group->group_filtermode_isexcl); - /* - RFC 3376: 6.2.2. Definition of Group Timers + /* + RFC 3376: 6.2.2. Definition of Group Timers - If there are no more source records for the group, delete group - record. - */ - if (listcount(group->group_source_list) < 1) { - igmp_group_delete_empty_include(group); - } + If there are no more source records for the group, delete group + record. + */ + if (listcount(group->group_source_list) < 1) { + igmp_group_delete_empty_include(group); + } - return 0; + return 0; } static void group_timer_off(struct igmp_group *group) { - if (!group->t_group_timer) - return; - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("Cancelling TIMER event for group %s on %s", - group_str, group->group_igmp_sock->interface->name); - } - THREAD_OFF(group->t_group_timer); + if (!group->t_group_timer) + return; + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug("Cancelling TIMER event for group %s on %s", + group_str, group->group_igmp_sock->interface->name); + } + THREAD_OFF(group->t_group_timer); } -void igmp_group_timer_on(struct igmp_group *group, - long interval_msec, const char *ifname) +void igmp_group_timer_on(struct igmp_group *group, long interval_msec, + const char *ifname) { - group_timer_off(group); - - if (PIM_DEBUG_IGMP_EVENTS) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("Scheduling %ld.%03ld sec TIMER event for group %s on %s", - interval_msec / 1000, - interval_msec % 1000, - group_str, ifname); - } - - /* - RFC 3376: 6.2.2. Definition of Group Timers - - The group timer is only used when a group is in EXCLUDE mode and - it represents the time for the *filter-mode* of the group to - expire and switch to INCLUDE mode. - */ - zassert(group->group_filtermode_isexcl); - - thread_add_timer_msec(master, igmp_group_timer, group, interval_msec, - &group->t_group_timer); + group_timer_off(group); + + if (PIM_DEBUG_IGMP_EVENTS) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug( + "Scheduling %ld.%03ld sec TIMER event for group %s on %s", + interval_msec / 1000, interval_msec % 1000, group_str, + ifname); + } + + /* + RFC 3376: 6.2.2. Definition of Group Timers + + The group timer is only used when a group is in EXCLUDE mode and + it represents the time for the *filter-mode* of the group to + expire and switch to INCLUDE mode. + */ + zassert(group->group_filtermode_isexcl); + + thread_add_timer_msec(master, igmp_group_timer, group, interval_msec, + &group->t_group_timer); } -struct igmp_group * -find_group_by_addr (struct igmp_sock *igmp, - struct in_addr group_addr) +struct igmp_group *find_group_by_addr(struct igmp_sock *igmp, + struct in_addr group_addr) { - struct igmp_group lookup; + struct igmp_group lookup; - lookup.group_addr.s_addr = group_addr.s_addr; + lookup.group_addr.s_addr = group_addr.s_addr; - return hash_lookup(igmp->igmp_group_hash, &lookup); + return hash_lookup(igmp->igmp_group_hash, &lookup); } struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, struct in_addr group_addr) { - struct igmp_group *group; - - group = find_group_by_addr(igmp, group_addr); - if (group) { - return group; - } - - if (!pim_is_group_224_4 (group_addr)) - { - zlog_warn("%s: Group Specified is not part of 224.0.0.0/4", - __PRETTY_FUNCTION__); - return NULL; - } - - if (pim_is_group_224_0_0_0_24 (group_addr)) - { - zlog_warn("%s: Group specified is part of 224.0.0.0/24", - __PRETTY_FUNCTION__); - return NULL; - } - /* - Non-existant group is created as INCLUDE {empty}: - - RFC 3376 - 5.1. Action on Change of Interface State - - If no interface state existed for that multicast address before - the change (i.e., the change consisted of creating a new - per-interface record), or if no state exists after the change - (i.e., the change consisted of deleting a per-interface record), - then the "non-existent" state is considered to have a filter mode - of INCLUDE and an empty source list. - */ - - group = XCALLOC(MTYPE_PIM_IGMP_GROUP, sizeof(*group)); - if (!group) { - zlog_warn("%s %s: XCALLOC() failure", - __FILE__, __PRETTY_FUNCTION__); - return NULL; /* error, not found, could not create */ - } - - group->group_source_list = list_new(); - if (!group->group_source_list) { - zlog_warn("%s %s: list_new() failure", - __FILE__, __PRETTY_FUNCTION__); - XFREE(MTYPE_PIM_IGMP_GROUP, group); /* discard group */ - return NULL; /* error, not found, could not initialize */ - } - group->group_source_list->del = (void (*)(void *)) igmp_source_free; - - group->t_group_timer = NULL; - group->t_group_query_retransmit_timer = NULL; - group->group_specific_query_retransmit_count = 0; - group->group_addr = group_addr; - group->group_igmp_sock = igmp; - group->last_igmp_v1_report_dsec = -1; - group->last_igmp_v2_report_dsec = -1; - group->group_creation = pim_time_monotonic_sec(); - group->igmp_version = IGMP_DEFAULT_VERSION; - - /* initialize new group as INCLUDE {empty} */ - group->group_filtermode_isexcl = 0; /* 0=INCLUDE, 1=EXCLUDE */ - - listnode_add(igmp->igmp_group_list, group); - group = hash_get (igmp->igmp_group_hash, group, hash_alloc_intern); - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("Creating new IGMP group %s on socket %d interface %s", - group_str, igmp->fd, igmp->interface->name); - } - - /* - RFC 3376: 6.2.2. Definition of Group Timers - - The group timer is only used when a group is in EXCLUDE mode and - it represents the time for the *filter-mode* of the group to - expire and switch to INCLUDE mode. - */ - zassert(!group->group_filtermode_isexcl); /* INCLUDE mode */ - zassert(!group->t_group_timer); /* group timer == 0 */ - - /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ - igmp_anysource_forward_stop(group); - - return group; + struct igmp_group *group; + + group = find_group_by_addr(igmp, group_addr); + if (group) { + return group; + } + + if (!pim_is_group_224_4(group_addr)) { + zlog_warn("%s: Group Specified is not part of 224.0.0.0/4", + __PRETTY_FUNCTION__); + return NULL; + } + + if (pim_is_group_224_0_0_0_24(group_addr)) { + zlog_warn("%s: Group specified is part of 224.0.0.0/24", + __PRETTY_FUNCTION__); + return NULL; + } + /* + Non-existant group is created as INCLUDE {empty}: + + RFC 3376 - 5.1. Action on Change of Interface State + + If no interface state existed for that multicast address before + the change (i.e., the change consisted of creating a new + per-interface record), or if no state exists after the change + (i.e., the change consisted of deleting a per-interface record), + then the "non-existent" state is considered to have a filter mode + of INCLUDE and an empty source list. + */ + + group = XCALLOC(MTYPE_PIM_IGMP_GROUP, sizeof(*group)); + if (!group) { + zlog_warn("%s %s: XCALLOC() failure", __FILE__, + __PRETTY_FUNCTION__); + return NULL; /* error, not found, could not create */ + } + + group->group_source_list = list_new(); + if (!group->group_source_list) { + zlog_warn("%s %s: list_new() failure", __FILE__, + __PRETTY_FUNCTION__); + XFREE(MTYPE_PIM_IGMP_GROUP, group); /* discard group */ + return NULL; /* error, not found, could not initialize */ + } + group->group_source_list->del = (void (*)(void *))igmp_source_free; + + group->t_group_timer = NULL; + group->t_group_query_retransmit_timer = NULL; + group->group_specific_query_retransmit_count = 0; + group->group_addr = group_addr; + group->group_igmp_sock = igmp; + group->last_igmp_v1_report_dsec = -1; + group->last_igmp_v2_report_dsec = -1; + group->group_creation = pim_time_monotonic_sec(); + group->igmp_version = IGMP_DEFAULT_VERSION; + + /* initialize new group as INCLUDE {empty} */ + group->group_filtermode_isexcl = 0; /* 0=INCLUDE, 1=EXCLUDE */ + + listnode_add(igmp->igmp_group_list, group); + group = hash_get(igmp->igmp_group_hash, group, hash_alloc_intern); + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug( + "Creating new IGMP group %s on socket %d interface %s", + group_str, igmp->fd, igmp->interface->name); + } + + /* + RFC 3376: 6.2.2. Definition of Group Timers + + The group timer is only used when a group is in EXCLUDE mode and + it represents the time for the *filter-mode* of the group to + expire and switch to INCLUDE mode. + */ + zassert(!group->group_filtermode_isexcl); /* INCLUDE mode */ + zassert(!group->t_group_timer); /* group timer == 0 */ + + /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ + igmp_anysource_forward_stop(group); + + return group; } -void -igmp_send_query (int igmp_version, - struct igmp_group *group, - int fd, - const char *ifname, - char *query_buf, - int query_buf_size, - int num_sources, - struct in_addr dst_addr, - struct in_addr group_addr, - int query_max_response_time_dsec, - uint8_t s_flag, - uint8_t querier_robustness_variable, - uint16_t querier_query_interval) +void igmp_send_query(int igmp_version, struct igmp_group *group, int fd, + const char *ifname, char *query_buf, int query_buf_size, + int num_sources, struct in_addr dst_addr, + struct in_addr group_addr, + int query_max_response_time_dsec, uint8_t s_flag, + uint8_t querier_robustness_variable, + uint16_t querier_query_interval) { - if (igmp_version == 3) { - igmp_v3_send_query (group, fd, ifname, query_buf, - query_buf_size, num_sources, - dst_addr, group_addr, - query_max_response_time_dsec, s_flag, - querier_robustness_variable, - querier_query_interval); - } else if (igmp_version == 2) { - igmp_v2_send_query (group, fd, ifname, query_buf, - dst_addr, group_addr, - query_max_response_time_dsec); - } + if (igmp_version == 3) { + igmp_v3_send_query(group, fd, ifname, query_buf, query_buf_size, + num_sources, dst_addr, group_addr, + query_max_response_time_dsec, s_flag, + querier_robustness_variable, + querier_query_interval); + } else if (igmp_version == 2) { + igmp_v2_send_query(group, fd, ifname, query_buf, dst_addr, + group_addr, query_max_response_time_dsec); + } } diff --git a/pimd/pim_igmp.h b/pimd/pim_igmp.h index 2f36094bd..275f25f63 100644 --- a/pimd/pim_igmp.h +++ b/pimd/pim_igmp.h @@ -41,8 +41,8 @@ #define IGMP_V3_REPORT_HEADER_SIZE (8) #define IGMP_V3_GROUP_RECORD_MIN_SIZE (8) -#define IGMP_V3_MSG_MIN_SIZE (IGMP_V3_REPORT_HEADER_SIZE + \ - IGMP_V3_GROUP_RECORD_MIN_SIZE) +#define IGMP_V3_MSG_MIN_SIZE \ + (IGMP_V3_REPORT_HEADER_SIZE + IGMP_V3_GROUP_RECORD_MIN_SIZE) #define IGMP_V12_MSG_SIZE (8) #define IGMP_V3_GROUP_RECORD_TYPE_OFFSET (0) @@ -67,40 +67,40 @@ #define IGMP_DEFAULT_VERSION (3) struct igmp_join { - struct in_addr group_addr; - struct in_addr source_addr; - int sock_fd; - time_t sock_creation; + struct in_addr group_addr; + struct in_addr source_addr; + int sock_fd; + time_t sock_creation; }; struct igmp_sock { - int fd; - struct interface *interface; - struct in_addr ifaddr; - time_t sock_creation; - - struct thread *t_igmp_read; /* read: IGMP sockets */ - struct thread *t_igmp_query_timer; /* timer: issue IGMP general queries */ - struct thread *t_other_querier_timer; /* timer: other querier present */ - - int querier_query_interval; /* QQI */ - int querier_robustness_variable; /* QRV */ - int startup_query_count; - - struct list *igmp_group_list; /* list of struct igmp_group */ - struct hash *igmp_group_hash; + int fd; + struct interface *interface; + struct in_addr ifaddr; + time_t sock_creation; + + struct thread *t_igmp_read; /* read: IGMP sockets */ + struct thread + *t_igmp_query_timer; /* timer: issue IGMP general queries */ + struct thread *t_other_querier_timer; /* timer: other querier present */ + + int querier_query_interval; /* QQI */ + int querier_robustness_variable; /* QRV */ + int startup_query_count; + + struct list *igmp_group_list; /* list of struct igmp_group */ + struct hash *igmp_group_hash; }; struct igmp_sock *pim_igmp_sock_lookup_ifaddr(struct list *igmp_sock_list, struct in_addr ifaddr); -struct igmp_sock *igmp_sock_lookup_by_fd(struct list *igmp_sock_list, - int fd); +struct igmp_sock *igmp_sock_lookup_by_fd(struct list *igmp_sock_list, int fd); struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list, struct in_addr ifaddr, struct interface *ifp); void igmp_sock_delete(struct igmp_sock *igmp); void igmp_sock_free(struct igmp_sock *igmp); -void igmp_sock_delete_all (struct interface *ifp); +void igmp_sock_delete_all(struct interface *ifp); int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len); void pim_igmp_general_query_on(struct igmp_sock *igmp); @@ -122,52 +122,53 @@ void pim_igmp_other_querier_timer_off(struct igmp_sock *igmp); #define IGMP_SOURCE_DONT_SEND(flags) ((flags) &= ~IGMP_SOURCE_MASK_SEND) struct igmp_source { - struct in_addr source_addr; - struct thread *t_source_timer; - struct igmp_group *source_group; /* back pointer */ - time_t source_creation; - uint32_t source_flags; - struct channel_oil *source_channel_oil; - - /* - RFC 3376: 6.6.3.2. Building and Sending Group and Source Specific Queries - */ - int source_query_retransmit_count; + struct in_addr source_addr; + struct thread *t_source_timer; + struct igmp_group *source_group; /* back pointer */ + time_t source_creation; + uint32_t source_flags; + struct channel_oil *source_channel_oil; + + /* + RFC 3376: 6.6.3.2. Building and Sending Group and Source Specific + Queries + */ + int source_query_retransmit_count; }; struct igmp_group { - /* - RFC 3376: 6.2.2. Definition of Group Timers - - The group timer is only used when a group is in EXCLUDE mode and it - represents the time for the *filter-mode* of the group to expire and - switch to INCLUDE mode. - */ - struct thread *t_group_timer; - - /* Shared between group-specific and - group-and-source-specific retransmissions */ - struct thread *t_group_query_retransmit_timer; - - /* Counter exclusive for group-specific retransmissions - (not used by group-and-source-specific retransmissions, - since sources have their counters) */ - int group_specific_query_retransmit_count; - - /* compatibility mode - igmp v1, v2 or v3 */ - int igmp_version; - - struct in_addr group_addr; - int group_filtermode_isexcl; /* 0=INCLUDE, 1=EXCLUDE */ - struct list *group_source_list; /* list of struct igmp_source */ - time_t group_creation; - struct igmp_sock *group_igmp_sock; /* back pointer */ - int64_t last_igmp_v1_report_dsec; - int64_t last_igmp_v2_report_dsec; + /* + RFC 3376: 6.2.2. Definition of Group Timers + + The group timer is only used when a group is in EXCLUDE mode and it + represents the time for the *filter-mode* of the group to expire and + switch to INCLUDE mode. + */ + struct thread *t_group_timer; + + /* Shared between group-specific and + group-and-source-specific retransmissions */ + struct thread *t_group_query_retransmit_timer; + + /* Counter exclusive for group-specific retransmissions + (not used by group-and-source-specific retransmissions, + since sources have their counters) */ + int group_specific_query_retransmit_count; + + /* compatibility mode - igmp v1, v2 or v3 */ + int igmp_version; + + struct in_addr group_addr; + int group_filtermode_isexcl; /* 0=INCLUDE, 1=EXCLUDE */ + struct list *group_source_list; /* list of struct igmp_source */ + time_t group_creation; + struct igmp_sock *group_igmp_sock; /* back pointer */ + int64_t last_igmp_v1_report_dsec; + int64_t last_igmp_v2_report_dsec; }; -struct igmp_group *find_group_by_addr (struct igmp_sock *igmp, - struct in_addr group_addr); +struct igmp_group *find_group_by_addr(struct igmp_sock *igmp, + struct in_addr group_addr); struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, struct in_addr group_addr); @@ -175,24 +176,17 @@ void igmp_group_delete_empty_include(struct igmp_group *group); void igmp_startup_mode_on(struct igmp_sock *igmp); -void igmp_group_timer_on(struct igmp_group *group, - long interval_msec, const char *ifname); - -struct igmp_source * -source_new (struct igmp_group *group, - struct in_addr src_addr); - -void igmp_send_query(int igmp_version, - struct igmp_group *group, - int fd, - const char *ifname, - char *query_buf, - int query_buf_size, - int num_sources, - struct in_addr dst_addr, - struct in_addr group_addr, - int query_max_response_time_dsec, - uint8_t s_flag, - uint8_t querier_robustness_variable, - uint16_t querier_query_interval); +void igmp_group_timer_on(struct igmp_group *group, long interval_msec, + const char *ifname); + +struct igmp_source *source_new(struct igmp_group *group, + struct in_addr src_addr); + +void igmp_send_query(int igmp_version, struct igmp_group *group, int fd, + const char *ifname, char *query_buf, int query_buf_size, + int num_sources, struct in_addr dst_addr, + struct in_addr group_addr, + int query_max_response_time_dsec, uint8_t s_flag, + uint8_t querier_robustness_variable, + uint16_t querier_query_interval); #endif /* PIM_IGMP_H */ diff --git a/pimd/pim_igmp_join.h b/pimd/pim_igmp_join.h index 31fc1b047..abee08006 100644 --- a/pimd/pim_igmp_join.h +++ b/pimd/pim_igmp_join.h @@ -28,11 +28,10 @@ #ifndef MCAST_JOIN_SOURCE_GROUP #define MCAST_JOIN_SOURCE_GROUP 46 -struct group_source_req -{ - uint32_t gsr_interface; - struct sockaddr_storage gsr_group; - struct sockaddr_storage gsr_source; +struct group_source_req { + uint32_t gsr_interface; + struct sockaddr_storage gsr_group; + struct sockaddr_storage gsr_source; }; #endif @@ -40,29 +39,29 @@ static int pim_igmp_join_source(int fd, ifindex_t ifindex, struct in_addr group_addr, struct in_addr source_addr) { - struct group_source_req req; - struct sockaddr_in group; - struct sockaddr_in source; + struct group_source_req req; + struct sockaddr_in group; + struct sockaddr_in source; - memset(&req, 0, sizeof(req)); - memset(&group, 0, sizeof(group)); - group.sin_family = AF_INET; - group.sin_addr = group_addr; - group.sin_port = htons(0); - memcpy(&req.gsr_group, &group, sizeof(struct sockaddr_in)); + memset(&req, 0, sizeof(req)); + memset(&group, 0, sizeof(group)); + group.sin_family = AF_INET; + group.sin_addr = group_addr; + group.sin_port = htons(0); + memcpy(&req.gsr_group, &group, sizeof(struct sockaddr_in)); - memset(&source, 0, sizeof(source)); - source.sin_family = AF_INET; - source.sin_addr = source_addr; - source.sin_port = htons(0); - memcpy(&req.gsr_source, &source, sizeof(struct sockaddr_in)); + memset(&source, 0, sizeof(source)); + source.sin_family = AF_INET; + source.sin_addr = source_addr; + source.sin_port = htons(0); + memcpy(&req.gsr_source, &source, sizeof(struct sockaddr_in)); - req.gsr_interface = ifindex; + req.gsr_interface = ifindex; - return setsockopt(fd, SOL_IP, MCAST_JOIN_SOURCE_GROUP, - &req, sizeof(req)); + return setsockopt(fd, SOL_IP, MCAST_JOIN_SOURCE_GROUP, &req, + sizeof(req)); - return 0; + return 0; } #endif /* PIM_IGMP_JOIN_H */ diff --git a/pimd/pim_igmpv2.c b/pimd/pim_igmpv2.c index d4b3010d3..efa36e618 100644 --- a/pimd/pim_igmpv2.c +++ b/pimd/pim_igmpv2.c @@ -29,161 +29,161 @@ #include "pim_util.h" -static void -on_trace (const char *label, - struct interface *ifp, struct in_addr from) +static void on_trace(const char *label, struct interface *ifp, + struct in_addr from) { - if (PIM_DEBUG_IGMP_TRACE) { - char from_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", from, from_str, sizeof(from_str)); - zlog_debug("%s: from %s on %s", - label, from_str, ifp->name); - } + if (PIM_DEBUG_IGMP_TRACE) { + char from_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", from, from_str, sizeof(from_str)); + zlog_debug("%s: from %s on %s", label, from_str, ifp->name); + } } -void -igmp_v2_send_query (struct igmp_group *group, - int fd, - const char *ifname, - char *query_buf, - struct in_addr dst_addr, - struct in_addr group_addr, - int query_max_response_time_dsec) +void igmp_v2_send_query(struct igmp_group *group, int fd, const char *ifname, + char *query_buf, struct in_addr dst_addr, + struct in_addr group_addr, + int query_max_response_time_dsec) { - ssize_t msg_size = 8; - uint8_t max_resp_code; - ssize_t sent; - struct sockaddr_in to; - socklen_t tolen; - uint16_t checksum; - - /* max_resp_code must be non-zero else this will look like an IGMP v1 query */ - max_resp_code = igmp_msg_encode16to8(query_max_response_time_dsec); - zassert(max_resp_code > 0); - - query_buf[0] = PIM_IGMP_MEMBERSHIP_QUERY; - query_buf[1] = max_resp_code; - *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = 0; /* for computing checksum */ - memcpy(query_buf+4, &group_addr, sizeof(struct in_addr)); - - checksum = in_cksum(query_buf, msg_size); - *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum; - - if (PIM_DEBUG_IGMP_PACKETS) { - char dst_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - zlog_debug("Send IGMPv2 QUERY to %s on %s for group %s", - dst_str, ifname, group_str); - } - - memset(&to, 0, sizeof(to)); - to.sin_family = AF_INET; - to.sin_addr = dst_addr; - tolen = sizeof(to); - - sent = sendto(fd, query_buf, msg_size, MSG_DONTWAIT, - (struct sockaddr *)&to, tolen); - if (sent != (ssize_t) msg_size) { - char dst_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - if (sent < 0) { - zlog_warn("Send IGMPv2 QUERY failed due to %s on %s: group=%s msg_size=%zd: errno=%d: %s", - dst_str, ifname, group_str, msg_size, errno, safe_strerror(errno)); - } - else { - zlog_warn("Send IGMPv2 QUERY failed due to %s on %s: group=%s msg_size=%zd: sent=%zd", - dst_str, ifname, group_str, msg_size, sent); - } - return; - } + ssize_t msg_size = 8; + uint8_t max_resp_code; + ssize_t sent; + struct sockaddr_in to; + socklen_t tolen; + uint16_t checksum; + + /* max_resp_code must be non-zero else this will look like an IGMP v1 + * query */ + max_resp_code = igmp_msg_encode16to8(query_max_response_time_dsec); + zassert(max_resp_code > 0); + + query_buf[0] = PIM_IGMP_MEMBERSHIP_QUERY; + query_buf[1] = max_resp_code; + *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = + 0; /* for computing checksum */ + memcpy(query_buf + 4, &group_addr, sizeof(struct in_addr)); + + checksum = in_cksum(query_buf, msg_size); + *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum; + + if (PIM_DEBUG_IGMP_PACKETS) { + char dst_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); + pim_inet4_dump("", group_addr, group_str, + sizeof(group_str)); + zlog_debug("Send IGMPv2 QUERY to %s on %s for group %s", + dst_str, ifname, group_str); + } + + memset(&to, 0, sizeof(to)); + to.sin_family = AF_INET; + to.sin_addr = dst_addr; + tolen = sizeof(to); + + sent = sendto(fd, query_buf, msg_size, MSG_DONTWAIT, + (struct sockaddr *)&to, tolen); + if (sent != (ssize_t)msg_size) { + char dst_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); + pim_inet4_dump("", group_addr, group_str, + sizeof(group_str)); + if (sent < 0) { + zlog_warn( + "Send IGMPv2 QUERY failed due to %s on %s: group=%s msg_size=%zd: errno=%d: %s", + dst_str, ifname, group_str, msg_size, errno, + safe_strerror(errno)); + } else { + zlog_warn( + "Send IGMPv2 QUERY failed due to %s on %s: group=%s msg_size=%zd: sent=%zd", + dst_str, ifname, group_str, msg_size, sent); + } + return; + } } -int -igmp_v2_recv_report (struct igmp_sock *igmp, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len) +int igmp_v2_recv_report(struct igmp_sock *igmp, struct in_addr from, + const char *from_str, char *igmp_msg, int igmp_msg_len) { - struct interface *ifp = igmp->interface; - struct in_addr group_addr; - char group_str[INET_ADDRSTRLEN]; - - on_trace(__PRETTY_FUNCTION__, igmp->interface, from); - - if (igmp_msg_len != IGMP_V12_MSG_SIZE) { - zlog_warn("Recv IGMPv2 REPORT from %s on %s: size=%d other than correct=%d", - from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); - return -1; - } - - memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); - - if (PIM_DEBUG_IGMP_PACKETS) { - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - zlog_debug("Recv IGMPv2 REPORT from %s on %s for %s", - from_str, ifp->name, group_str); - } - - /* - * RFC 3376 - * 7.3.2. In the Presence of Older Version Group Members - * - * When Group Compatibility Mode is IGMPv2, a router internally - * translates the following IGMPv2 messages for that group to their - * IGMPv3 equivalents: - * - * IGMPv2 Message IGMPv3 Equivalent - * -------------- ----------------- - * Report IS_EX( {} ) - * Leave TO_IN( {} ) - */ - igmpv3_report_isex (igmp, from, group_addr, 0, NULL, 1); - - return 0; + struct interface *ifp = igmp->interface; + struct in_addr group_addr; + char group_str[INET_ADDRSTRLEN]; + + on_trace(__PRETTY_FUNCTION__, igmp->interface, from); + + if (igmp_msg_len != IGMP_V12_MSG_SIZE) { + zlog_warn( + "Recv IGMPv2 REPORT from %s on %s: size=%d other than correct=%d", + from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); + return -1; + } + + memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); + + if (PIM_DEBUG_IGMP_PACKETS) { + pim_inet4_dump("", group_addr, group_str, + sizeof(group_str)); + zlog_debug("Recv IGMPv2 REPORT from %s on %s for %s", from_str, + ifp->name, group_str); + } + + /* + * RFC 3376 + * 7.3.2. In the Presence of Older Version Group Members + * + * When Group Compatibility Mode is IGMPv2, a router internally + * translates the following IGMPv2 messages for that group to their + * IGMPv3 equivalents: + * + * IGMPv2 Message IGMPv3 Equivalent + * -------------- ----------------- + * Report IS_EX( {} ) + * Leave TO_IN( {} ) + */ + igmpv3_report_isex(igmp, from, group_addr, 0, NULL, 1); + + return 0; } -int -igmp_v2_recv_leave (struct igmp_sock *igmp, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len) +int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from, + const char *from_str, char *igmp_msg, int igmp_msg_len) { - struct interface *ifp = igmp->interface; - struct in_addr group_addr; - char group_str[INET_ADDRSTRLEN]; - - on_trace(__PRETTY_FUNCTION__, igmp->interface, from); - - if (igmp_msg_len != IGMP_V12_MSG_SIZE) { - zlog_warn("Recv IGMPv2 LEAVE from %s on %s: size=%d other than correct=%d", - from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); - return -1; - } - - memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); - - if (PIM_DEBUG_IGMP_PACKETS) { - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - zlog_debug("Recv IGMPv2 LEAVE from %s on %s for %s", - from_str, ifp->name, group_str); - } - - /* - * RFC 3376 - * 7.3.2. In the Presence of Older Version Group Members - * - * When Group Compatibility Mode is IGMPv2, a router internally - * translates the following IGMPv2 messages for that group to their - * IGMPv3 equivalents: - * - * IGMPv2 Message IGMPv3 Equivalent - * -------------- ----------------- - * Report IS_EX( {} ) - * Leave TO_IN( {} ) - */ - igmpv3_report_toin (igmp, from, group_addr, 0, NULL); - - return 0; + struct interface *ifp = igmp->interface; + struct in_addr group_addr; + char group_str[INET_ADDRSTRLEN]; + + on_trace(__PRETTY_FUNCTION__, igmp->interface, from); + + if (igmp_msg_len != IGMP_V12_MSG_SIZE) { + zlog_warn( + "Recv IGMPv2 LEAVE from %s on %s: size=%d other than correct=%d", + from_str, ifp->name, igmp_msg_len, IGMP_V12_MSG_SIZE); + return -1; + } + + memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); + + if (PIM_DEBUG_IGMP_PACKETS) { + pim_inet4_dump("", group_addr, group_str, + sizeof(group_str)); + zlog_debug("Recv IGMPv2 LEAVE from %s on %s for %s", from_str, + ifp->name, group_str); + } + + /* + * RFC 3376 + * 7.3.2. In the Presence of Older Version Group Members + * + * When Group Compatibility Mode is IGMPv2, a router internally + * translates the following IGMPv2 messages for that group to their + * IGMPv3 equivalents: + * + * IGMPv2 Message IGMPv3 Equivalent + * -------------- ----------------- + * Report IS_EX( {} ) + * Leave TO_IN( {} ) + */ + igmpv3_report_toin(igmp, from, group_addr, 0, NULL); + + return 0; } diff --git a/pimd/pim_igmpv2.h b/pimd/pim_igmpv2.h index fa8d16394..f0a6fdc5f 100644 --- a/pimd/pim_igmpv2.h +++ b/pimd/pim_igmpv2.h @@ -21,20 +21,15 @@ #ifndef PIM_IGMPV2_H #define PIM_IGMPV2_H -void igmp_v2_send_query (struct igmp_group *group, - int fd, - const char *ifname, - char *query_buf, - struct in_addr dst_addr, - struct in_addr group_addr, - int query_max_response_time_dsec); +void igmp_v2_send_query(struct igmp_group *group, int fd, const char *ifname, + char *query_buf, struct in_addr dst_addr, + struct in_addr group_addr, + int query_max_response_time_dsec); -int igmp_v2_recv_report (struct igmp_sock *igmp, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len); +int igmp_v2_recv_report(struct igmp_sock *igmp, struct in_addr from, + const char *from_str, char *igmp_msg, int igmp_msg_len); -int igmp_v2_recv_leave (struct igmp_sock *igmp, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len); +int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from, + const char *from_str, char *igmp_msg, int igmp_msg_len); #endif /* PIM_IGMPV2_H */ diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index ad37ad876..880d840ea 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -39,269 +39,270 @@ static void group_query_send(struct igmp_group *group); static void source_query_send_by_flag(struct igmp_group *group, int num_sources_tosend); -static void on_trace(const char *label, - struct interface *ifp, struct in_addr from, - struct in_addr group_addr, +static void on_trace(const char *label, struct interface *ifp, + struct in_addr from, struct in_addr group_addr, int num_sources, struct in_addr *sources) { - if (PIM_DEBUG_IGMP_TRACE) { - char from_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; + if (PIM_DEBUG_IGMP_TRACE) { + char from_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", from, from_str, sizeof(from_str)); - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); + pim_inet4_dump("", from, from_str, sizeof(from_str)); + pim_inet4_dump("", group_addr, group_str, + sizeof(group_str)); - zlog_debug("%s: from %s on %s: group=%s sources=%d", - label, from_str, ifp->name, group_str, num_sources); - } + zlog_debug("%s: from %s on %s: group=%s sources=%d", label, + from_str, ifp->name, group_str, num_sources); + } } void igmp_group_reset_gmi(struct igmp_group *group) { - long group_membership_interval_msec; - struct pim_interface *pim_ifp; - struct igmp_sock *igmp; - struct interface *ifp; - - igmp = group->group_igmp_sock; - ifp = igmp->interface; - pim_ifp = ifp->info; - - /* - RFC 3376: 8.4. Group Membership Interval - - The Group Membership Interval is the amount of time that must pass - before a multicast router decides there are no more members of a - group or a particular source on a network. - - This value MUST be ((the Robustness Variable) times (the Query - Interval)) plus (one Query Response Interval). - - group_membership_interval_msec = querier_robustness_variable * - (1000 * querier_query_interval) + - 100 * query_response_interval_dsec; - */ - group_membership_interval_msec = - PIM_IGMP_GMI_MSEC(igmp->querier_robustness_variable, - igmp->querier_query_interval, - pim_ifp->igmp_query_max_response_time_dsec); - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("Resetting group %s timer to GMI=%ld.%03ld sec on %s", - group_str, - group_membership_interval_msec / 1000, - group_membership_interval_msec % 1000, - ifp->name); - } - - /* - RFC 3376: 6.2.2. Definition of Group Timers - - The group timer is only used when a group is in EXCLUDE mode and - it represents the time for the *filter-mode* of the group to - expire and switch to INCLUDE mode. - */ - zassert(group->group_filtermode_isexcl); - - igmp_group_timer_on(group, group_membership_interval_msec, ifp->name); + long group_membership_interval_msec; + struct pim_interface *pim_ifp; + struct igmp_sock *igmp; + struct interface *ifp; + + igmp = group->group_igmp_sock; + ifp = igmp->interface; + pim_ifp = ifp->info; + + /* + RFC 3376: 8.4. Group Membership Interval + + The Group Membership Interval is the amount of time that must pass + before a multicast router decides there are no more members of a + group or a particular source on a network. + + This value MUST be ((the Robustness Variable) times (the Query + Interval)) plus (one Query Response Interval). + + group_membership_interval_msec = querier_robustness_variable * + (1000 * querier_query_interval) + + 100 * query_response_interval_dsec; + */ + group_membership_interval_msec = PIM_IGMP_GMI_MSEC( + igmp->querier_robustness_variable, igmp->querier_query_interval, + pim_ifp->igmp_query_max_response_time_dsec); + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug( + "Resetting group %s timer to GMI=%ld.%03ld sec on %s", + group_str, group_membership_interval_msec / 1000, + group_membership_interval_msec % 1000, ifp->name); + } + + /* + RFC 3376: 6.2.2. Definition of Group Timers + + The group timer is only used when a group is in EXCLUDE mode and + it represents the time for the *filter-mode* of the group to + expire and switch to INCLUDE mode. + */ + zassert(group->group_filtermode_isexcl); + + igmp_group_timer_on(group, group_membership_interval_msec, ifp->name); } static int igmp_source_timer(struct thread *t) { - struct igmp_source *source; - struct igmp_group *group; - - source = THREAD_ARG(t); - - group = source->source_group; - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); - zlog_debug("%s: Source timer expired for group %s source %s on %s", - __PRETTY_FUNCTION__, - group_str, source_str, - group->group_igmp_sock->interface->name); - } - - /* - RFC 3376: 6.3. IGMPv3 Source-Specific Forwarding Rules - - Group - Filter-Mode Source Timer Value Action - ----------- ------------------ ------ - INCLUDE TIMER == 0 Suggest to stop forwarding - traffic from source and - remove source record. If - there are no more source - records for the group, delete - group record. - - EXCLUDE TIMER == 0 Suggest to not forward - traffic from source - (DO NOT remove record) - - Source timer switched from (T > 0) to (T == 0): disable forwarding. - */ - - if (group->group_filtermode_isexcl) { - /* EXCLUDE mode */ - - igmp_source_forward_stop(source); - } - else { - /* INCLUDE mode */ - - /* igmp_source_delete() will stop forwarding source */ - igmp_source_delete(source); - - /* - If there are no more source records for the group, delete group - record. - */ - if (!listcount(group->group_source_list)) { - igmp_group_delete_empty_include(group); - } - } - - return 0; + struct igmp_source *source; + struct igmp_group *group; + + source = THREAD_ARG(t); + + group = source->source_group; + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group->group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("", source->source_addr, source_str, + sizeof(source_str)); + zlog_debug( + "%s: Source timer expired for group %s source %s on %s", + __PRETTY_FUNCTION__, group_str, source_str, + group->group_igmp_sock->interface->name); + } + + /* + RFC 3376: 6.3. IGMPv3 Source-Specific Forwarding Rules + + Group + Filter-Mode Source Timer Value Action + ----------- ------------------ ------ + INCLUDE TIMER == 0 Suggest to stop forwarding + traffic from source and + remove source record. If + there are no more source + records for the group, delete + group record. + + EXCLUDE TIMER == 0 Suggest to not forward + traffic from source + (DO NOT remove record) + + Source timer switched from (T > 0) to (T == 0): disable forwarding. + */ + + if (group->group_filtermode_isexcl) { + /* EXCLUDE mode */ + + igmp_source_forward_stop(source); + } else { + /* INCLUDE mode */ + + /* igmp_source_delete() will stop forwarding source */ + igmp_source_delete(source); + + /* + If there are no more source records for the group, delete + group + record. + */ + if (!listcount(group->group_source_list)) { + igmp_group_delete_empty_include(group); + } + } + + return 0; } static void source_timer_off(struct igmp_group *group, struct igmp_source *source) { - if (!source->t_source_timer) - return; - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); - zlog_debug("Cancelling TIMER event for group %s source %s on %s", - group_str, source_str, - group->group_igmp_sock->interface->name); - } - - THREAD_OFF(source->t_source_timer); + if (!source->t_source_timer) + return; + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group->group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("", source->source_addr, source_str, + sizeof(source_str)); + zlog_debug( + "Cancelling TIMER event for group %s source %s on %s", + group_str, source_str, + group->group_igmp_sock->interface->name); + } + + THREAD_OFF(source->t_source_timer); } static void igmp_source_timer_on(struct igmp_group *group, - struct igmp_source *source, - long interval_msec) + struct igmp_source *source, long interval_msec) { - source_timer_off(group, source); - - if (PIM_DEBUG_IGMP_EVENTS) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); - zlog_debug("Scheduling %ld.%03ld sec TIMER event for group %s source %s on %s", - interval_msec / 1000, - interval_msec % 1000, - group_str, source_str, - group->group_igmp_sock->interface->name); - } - - thread_add_timer_msec(master, igmp_source_timer, source, interval_msec, - &source->t_source_timer); - - /* - RFC 3376: 6.3. IGMPv3 Source-Specific Forwarding Rules - - Source timer switched from (T == 0) to (T > 0): enable forwarding. - */ - igmp_source_forward_start(source); + source_timer_off(group, source); + + if (PIM_DEBUG_IGMP_EVENTS) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group->group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("", source->source_addr, source_str, + sizeof(source_str)); + zlog_debug( + "Scheduling %ld.%03ld sec TIMER event for group %s source %s on %s", + interval_msec / 1000, interval_msec % 1000, group_str, + source_str, group->group_igmp_sock->interface->name); + } + + thread_add_timer_msec(master, igmp_source_timer, source, interval_msec, + &source->t_source_timer); + + /* + RFC 3376: 6.3. IGMPv3 Source-Specific Forwarding Rules + + Source timer switched from (T == 0) to (T > 0): enable forwarding. + */ + igmp_source_forward_start(source); } -void igmp_source_reset_gmi(struct igmp_sock *igmp, - struct igmp_group *group, +void igmp_source_reset_gmi(struct igmp_sock *igmp, struct igmp_group *group, struct igmp_source *source) { - long group_membership_interval_msec; - struct pim_interface *pim_ifp; - struct interface *ifp; - - ifp = igmp->interface; - pim_ifp = ifp->info; - - group_membership_interval_msec = - PIM_IGMP_GMI_MSEC(igmp->querier_robustness_variable, - igmp->querier_query_interval, - pim_ifp->igmp_query_max_response_time_dsec); - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); - - zlog_debug("Resetting source %s timer to GMI=%ld.%03ld sec for group %s on %s", - source_str, - group_membership_interval_msec / 1000, - group_membership_interval_msec % 1000, - group_str, - ifp->name); - } - - igmp_source_timer_on(group, source, - group_membership_interval_msec); + long group_membership_interval_msec; + struct pim_interface *pim_ifp; + struct interface *ifp; + + ifp = igmp->interface; + pim_ifp = ifp->info; + + group_membership_interval_msec = PIM_IGMP_GMI_MSEC( + igmp->querier_robustness_variable, igmp->querier_query_interval, + pim_ifp->igmp_query_max_response_time_dsec); + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + + pim_inet4_dump("", group->group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("", source->source_addr, source_str, + sizeof(source_str)); + + zlog_debug( + "Resetting source %s timer to GMI=%ld.%03ld sec for group %s on %s", + source_str, group_membership_interval_msec / 1000, + group_membership_interval_msec % 1000, group_str, + ifp->name); + } + + igmp_source_timer_on(group, source, group_membership_interval_msec); } static void source_mark_delete_flag(struct igmp_group *group) { - struct listnode *src_node; - struct igmp_source *src; + struct listnode *src_node; + struct igmp_source *src; - for (ALL_LIST_ELEMENTS_RO (group->group_source_list, src_node, src)) { - IGMP_SOURCE_DO_DELETE(src->source_flags); - } + for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { + IGMP_SOURCE_DO_DELETE(src->source_flags); + } } -static void source_mark_send_flag (struct igmp_group *group) +static void source_mark_send_flag(struct igmp_group *group) { - struct listnode *src_node; - struct igmp_source *src; + struct listnode *src_node; + struct igmp_source *src; - for (ALL_LIST_ELEMENTS_RO (group->group_source_list, src_node, src)) { - IGMP_SOURCE_DO_SEND(src->source_flags); - } + for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { + IGMP_SOURCE_DO_SEND(src->source_flags); + } } -static int source_mark_send_flag_by_timer (struct igmp_group *group) +static int source_mark_send_flag_by_timer(struct igmp_group *group) { - struct listnode *src_node; - struct igmp_source *src; - int num_marked_sources = 0; - - for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { - /* Is source timer running? */ - if (src->t_source_timer) { - IGMP_SOURCE_DO_SEND(src->source_flags); - ++num_marked_sources; - } - else { - IGMP_SOURCE_DONT_SEND(src->source_flags); - } - } - - return num_marked_sources; + struct listnode *src_node; + struct igmp_source *src; + int num_marked_sources = 0; + + for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { + /* Is source timer running? */ + if (src->t_source_timer) { + IGMP_SOURCE_DO_SEND(src->source_flags); + ++num_marked_sources; + } else { + IGMP_SOURCE_DONT_SEND(src->source_flags); + } + } + + return num_marked_sources; } static void source_clear_send_flag(struct list *source_list) { - struct listnode *src_node; - struct igmp_source *src; + struct listnode *src_node; + struct igmp_source *src; - for (ALL_LIST_ELEMENTS_RO(source_list, src_node, src)) { - IGMP_SOURCE_DONT_SEND(src->source_flags); - } + for (ALL_LIST_ELEMENTS_RO(source_list, src_node, src)) { + IGMP_SOURCE_DONT_SEND(src->source_flags); + } } /* @@ -309,27 +310,27 @@ static void source_clear_send_flag(struct list *source_list) */ static void group_exclude_fwd_anysrc_ifempty(struct igmp_group *group) { - zassert(group->group_filtermode_isexcl); + zassert(group->group_filtermode_isexcl); - if (listcount(group->group_source_list) < 1) { - igmp_anysource_forward_start(group); - } + if (listcount(group->group_source_list) < 1) { + igmp_anysource_forward_start(group); + } } void igmp_source_free(struct igmp_source *source) { - /* make sure there is no source timer running */ - zassert(!source->t_source_timer); + /* make sure there is no source timer running */ + zassert(!source->t_source_timer); - XFREE(MTYPE_PIM_IGMP_GROUP_SOURCE, source); + XFREE(MTYPE_PIM_IGMP_GROUP_SOURCE, source); } static void source_channel_oil_detach(struct igmp_source *source) { - if (source->source_channel_oil) { - pim_channel_oil_del(source->source_channel_oil); - source->source_channel_oil = NULL; - } + if (source->source_channel_oil) { + pim_channel_oil_del(source->source_channel_oil); + source->source_channel_oil = NULL; + } } /* @@ -338,662 +339,659 @@ static void source_channel_oil_detach(struct igmp_source *source) */ void igmp_source_delete(struct igmp_source *source) { - struct igmp_group *group; - struct in_addr src; - - group = source->source_group; - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); - zlog_debug("Deleting IGMP source %s for group %s from socket %d interface %s c_oil ref_count %d", - source_str, group_str, - group->group_igmp_sock->fd, - group->group_igmp_sock->interface->name, - source->source_channel_oil ? source->source_channel_oil->oil_ref_count : 0); - } - - source_timer_off(group, source); - igmp_source_forward_stop(source); - - /* sanity check that forwarding has been disabled */ - if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: forwarding=ON(!) IGMP source %s for group %s from socket %d interface %s", - __PRETTY_FUNCTION__, - source_str, group_str, - group->group_igmp_sock->fd, - group->group_igmp_sock->interface->name); - /* warning only */ - } - - source_channel_oil_detach(source); - - /* - notice that listnode_delete() can't be moved - into igmp_source_free() because the later is - called by list_delete_all_node() - */ - listnode_delete(group->group_source_list, source); - - src.s_addr = source->source_addr.s_addr; - igmp_source_free(source); - - /* Group source list is empty and current source is * then - *,G group going away so do not trigger start */ - if (group->group_filtermode_isexcl && - (listcount (group->group_source_list) != 0) && - src.s_addr != INADDR_ANY) - { - group_exclude_fwd_anysrc_ifempty (group); - } + struct igmp_group *group; + struct in_addr src; + + group = source->source_group; + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group->group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("", source->source_addr, source_str, + sizeof(source_str)); + zlog_debug( + "Deleting IGMP source %s for group %s from socket %d interface %s c_oil ref_count %d", + source_str, group_str, group->group_igmp_sock->fd, + group->group_igmp_sock->interface->name, + source->source_channel_oil + ? source->source_channel_oil->oil_ref_count + : 0); + } + + source_timer_off(group, source); + igmp_source_forward_stop(source); + + /* sanity check that forwarding has been disabled */ + if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group->group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("", source->source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: forwarding=ON(!) IGMP source %s for group %s from socket %d interface %s", + __PRETTY_FUNCTION__, source_str, group_str, + group->group_igmp_sock->fd, + group->group_igmp_sock->interface->name); + /* warning only */ + } + + source_channel_oil_detach(source); + + /* + notice that listnode_delete() can't be moved + into igmp_source_free() because the later is + called by list_delete_all_node() + */ + listnode_delete(group->group_source_list, source); + + src.s_addr = source->source_addr.s_addr; + igmp_source_free(source); + + /* Group source list is empty and current source is * then + *,G group going away so do not trigger start */ + if (group->group_filtermode_isexcl + && (listcount(group->group_source_list) != 0) + && src.s_addr != INADDR_ANY) { + group_exclude_fwd_anysrc_ifempty(group); + } } static void source_delete_by_flag(struct list *source_list) { - struct listnode *src_node; - struct listnode *src_nextnode; - struct igmp_source *src; - - for (ALL_LIST_ELEMENTS(source_list, src_node, src_nextnode, src)) - if (IGMP_SOURCE_TEST_DELETE(src->source_flags)) - igmp_source_delete(src); + struct listnode *src_node; + struct listnode *src_nextnode; + struct igmp_source *src; + + for (ALL_LIST_ELEMENTS(source_list, src_node, src_nextnode, src)) + if (IGMP_SOURCE_TEST_DELETE(src->source_flags)) + igmp_source_delete(src); } void igmp_source_delete_expired(struct list *source_list) { - struct listnode *src_node; - struct listnode *src_nextnode; - struct igmp_source *src; - - for (ALL_LIST_ELEMENTS(source_list, src_node, src_nextnode, src)) - if (!src->t_source_timer) - igmp_source_delete(src); + struct listnode *src_node; + struct listnode *src_nextnode; + struct igmp_source *src; + + for (ALL_LIST_ELEMENTS(source_list, src_node, src_nextnode, src)) + if (!src->t_source_timer) + igmp_source_delete(src); } struct igmp_source *igmp_find_source_by_addr(struct igmp_group *group, struct in_addr src_addr) { - struct listnode *src_node; - struct igmp_source *src; + struct listnode *src_node; + struct igmp_source *src; - for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) - if (src_addr.s_addr == src->source_addr.s_addr) - return src; + for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) + if (src_addr.s_addr == src->source_addr.s_addr) + return src; - return 0; + return 0; } -struct igmp_source * -source_new (struct igmp_group *group, - struct in_addr src_addr) +struct igmp_source *source_new(struct igmp_group *group, + struct in_addr src_addr) { - struct igmp_source *src; - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", src_addr, source_str, sizeof(source_str)); - zlog_debug("Creating new IGMP source %s for group %s on socket %d interface %s", - source_str, group_str, - group->group_igmp_sock->fd, - group->group_igmp_sock->interface->name); - } - - src = XCALLOC(MTYPE_PIM_IGMP_GROUP_SOURCE, sizeof(*src)); - if (!src) { - zlog_warn("%s %s: XCALLOC() failure", - __FILE__, __PRETTY_FUNCTION__); - return 0; /* error, not found, could not create */ - } - - src->t_source_timer = NULL; - src->source_group = group; /* back pointer */ - src->source_addr = src_addr; - src->source_creation = pim_time_monotonic_sec(); - src->source_flags = 0; - src->source_query_retransmit_count = 0; - src->source_channel_oil = NULL; - - listnode_add(group->group_source_list, src); - - /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ - igmp_anysource_forward_stop(group); - - return src; + struct igmp_source *src; + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group->group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("", src_addr, source_str, + sizeof(source_str)); + zlog_debug( + "Creating new IGMP source %s for group %s on socket %d interface %s", + source_str, group_str, group->group_igmp_sock->fd, + group->group_igmp_sock->interface->name); + } + + src = XCALLOC(MTYPE_PIM_IGMP_GROUP_SOURCE, sizeof(*src)); + if (!src) { + zlog_warn("%s %s: XCALLOC() failure", __FILE__, + __PRETTY_FUNCTION__); + return 0; /* error, not found, could not create */ + } + + src->t_source_timer = NULL; + src->source_group = group; /* back pointer */ + src->source_addr = src_addr; + src->source_creation = pim_time_monotonic_sec(); + src->source_flags = 0; + src->source_query_retransmit_count = 0; + src->source_channel_oil = NULL; + + listnode_add(group->group_source_list, src); + + /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ + igmp_anysource_forward_stop(group); + + return src; } static struct igmp_source *add_source_by_addr(struct igmp_sock *igmp, struct igmp_group *group, struct in_addr src_addr) { - struct igmp_source *src; + struct igmp_source *src; - src = igmp_find_source_by_addr(group, src_addr); - if (src) { - return src; - } + src = igmp_find_source_by_addr(group, src_addr); + if (src) { + return src; + } - src = source_new(group, src_addr); - if (!src) { - return 0; - } + src = source_new(group, src_addr); + if (!src) { + return 0; + } - return src; + return src; } static void allow(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources) + struct in_addr group_addr, int num_sources, + struct in_addr *sources) { - struct igmp_source *source; - struct igmp_group *group; - int i; - - /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr); - if (!group) { - return; - } - - /* scan received sources */ - for (i = 0; i < num_sources; ++i) { - struct in_addr *src_addr; - - src_addr = sources + i; - - source = add_source_by_addr(igmp, group, *src_addr); - if (!source) { - continue; - } - - /* - RFC 3376: 6.4.1. Reception of Current-State Records - - When receiving IS_IN reports for groups in EXCLUDE mode is - sources should be moved from set with (timers = 0) to set with - (timers > 0). - - igmp_source_reset_gmi() below, resetting the source timers to - GMI, accomplishes this. - */ - igmp_source_reset_gmi(igmp, group, source); - - } /* scan received sources */ - - if ((num_sources == 0) && - (group->group_filtermode_isexcl) && - (listcount (group->group_source_list) == 1)) - { - struct in_addr star = { .s_addr = INADDR_ANY }; - - source = igmp_find_source_by_addr (group, star); - if (source) - igmp_source_reset_gmi (igmp, group, source); - } + struct igmp_source *source; + struct igmp_group *group; + int i; + + /* non-existant group is created as INCLUDE {empty} */ + group = igmp_add_group_by_addr(igmp, group_addr); + if (!group) { + return; + } + + /* scan received sources */ + for (i = 0; i < num_sources; ++i) { + struct in_addr *src_addr; + + src_addr = sources + i; + + source = add_source_by_addr(igmp, group, *src_addr); + if (!source) { + continue; + } + + /* + RFC 3376: 6.4.1. Reception of Current-State Records + + When receiving IS_IN reports for groups in EXCLUDE mode is + sources should be moved from set with (timers = 0) to set with + (timers > 0). + + igmp_source_reset_gmi() below, resetting the source timers to + GMI, accomplishes this. + */ + igmp_source_reset_gmi(igmp, group, source); + + } /* scan received sources */ + + if ((num_sources == 0) && (group->group_filtermode_isexcl) + && (listcount(group->group_source_list) == 1)) { + struct in_addr star = {.s_addr = INADDR_ANY}; + + source = igmp_find_source_by_addr(group, star); + if (source) + igmp_source_reset_gmi(igmp, group, source); + } } void igmpv3_report_isin(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources) + struct in_addr group_addr, int num_sources, + struct in_addr *sources) { - on_trace(__PRETTY_FUNCTION__, - igmp->interface, from, group_addr, num_sources, sources); + on_trace(__PRETTY_FUNCTION__, igmp->interface, from, group_addr, + num_sources, sources); - allow(igmp, from, group_addr, num_sources, sources); + allow(igmp, from, group_addr, num_sources, sources); } -static void isex_excl(struct igmp_group *group, - int num_sources, struct in_addr *sources) +static void isex_excl(struct igmp_group *group, int num_sources, + struct in_addr *sources) { - struct igmp_source *source; - int i; - - /* EXCLUDE mode */ - zassert(group->group_filtermode_isexcl); - - /* E.1: set deletion flag for known sources (X,Y) */ - source_mark_delete_flag (group); - - /* scan received sources (A) */ - for (i = 0; i < num_sources; ++i) { - struct in_addr *src_addr; - - src_addr = sources + i; - - /* E.2: lookup reported source from (A) in (X,Y) */ - source = igmp_find_source_by_addr(group, *src_addr); - if (source) { - /* E.3: if found, clear deletion flag: (X*A) or (Y*A) */ - IGMP_SOURCE_DONT_DELETE(source->source_flags); - } - else { - /* E.4: if not found, create source with timer=GMI: (A-X-Y) */ - source = source_new(group, *src_addr); - if (!source) { - /* ugh, internal malloc failure, skip source */ - continue; - } - zassert(!source->t_source_timer); /* timer == 0 */ - igmp_source_reset_gmi(group->group_igmp_sock, group, source); - zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ - } - - } /* scan received sources */ - - /* - * If we are in isexcl mode and num_sources == 0 - * than that means we have a *,g entry that - * needs to be handled - */ - if (group->group_filtermode_isexcl && num_sources == 0) - { - struct in_addr star = { .s_addr = INADDR_ANY }; - source = igmp_find_source_by_addr (group, star); - if (source) - { - IGMP_SOURCE_DONT_DELETE(source->source_flags); - igmp_source_reset_gmi (group->group_igmp_sock, group, source); - } - } - - /* E.5: delete all sources marked with deletion flag: (X-A) and (Y-A) */ - source_delete_by_flag(group->group_source_list); + struct igmp_source *source; + int i; + + /* EXCLUDE mode */ + zassert(group->group_filtermode_isexcl); + + /* E.1: set deletion flag for known sources (X,Y) */ + source_mark_delete_flag(group); + + /* scan received sources (A) */ + for (i = 0; i < num_sources; ++i) { + struct in_addr *src_addr; + + src_addr = sources + i; + + /* E.2: lookup reported source from (A) in (X,Y) */ + source = igmp_find_source_by_addr(group, *src_addr); + if (source) { + /* E.3: if found, clear deletion flag: (X*A) or (Y*A) */ + IGMP_SOURCE_DONT_DELETE(source->source_flags); + } else { + /* E.4: if not found, create source with timer=GMI: + * (A-X-Y) */ + source = source_new(group, *src_addr); + if (!source) { + /* ugh, internal malloc failure, skip source */ + continue; + } + zassert(!source->t_source_timer); /* timer == 0 */ + igmp_source_reset_gmi(group->group_igmp_sock, group, + source); + zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ + } + + } /* scan received sources */ + + /* + * If we are in isexcl mode and num_sources == 0 + * than that means we have a *,g entry that + * needs to be handled + */ + if (group->group_filtermode_isexcl && num_sources == 0) { + struct in_addr star = {.s_addr = INADDR_ANY}; + source = igmp_find_source_by_addr(group, star); + if (source) { + IGMP_SOURCE_DONT_DELETE(source->source_flags); + igmp_source_reset_gmi(group->group_igmp_sock, group, + source); + } + } + + /* E.5: delete all sources marked with deletion flag: (X-A) and (Y-A) */ + source_delete_by_flag(group->group_source_list); } -static void isex_incl(struct igmp_group *group, - int num_sources, struct in_addr *sources) +static void isex_incl(struct igmp_group *group, int num_sources, + struct in_addr *sources) { - int i; - - /* INCLUDE mode */ - zassert(!group->group_filtermode_isexcl); - - /* I.1: set deletion flag for known sources (A) */ - source_mark_delete_flag (group); - - /* scan received sources (B) */ - for (i = 0; i < num_sources; ++i) { - struct igmp_source *source; - struct in_addr *src_addr; - - src_addr = sources + i; - - /* I.2: lookup reported source (B) */ - source = igmp_find_source_by_addr(group, *src_addr); - if (source) { - /* I.3: if found, clear deletion flag (A*B) */ - IGMP_SOURCE_DONT_DELETE(source->source_flags); - } - else { - /* I.4: if not found, create source with timer=0 (B-A) */ - source = source_new(group, *src_addr); - if (!source) { - /* ugh, internal malloc failure, skip source */ - continue; - } - zassert(!source->t_source_timer); /* (B-A) timer=0 */ - } - - } /* scan received sources */ - - /* I.5: delete all sources marked with deletion flag (A-B) */ - source_delete_by_flag(group->group_source_list); - - group->group_filtermode_isexcl = 1; /* boolean=true */ - - zassert(group->group_filtermode_isexcl); - - group_exclude_fwd_anysrc_ifempty(group); + int i; + + /* INCLUDE mode */ + zassert(!group->group_filtermode_isexcl); + + /* I.1: set deletion flag for known sources (A) */ + source_mark_delete_flag(group); + + /* scan received sources (B) */ + for (i = 0; i < num_sources; ++i) { + struct igmp_source *source; + struct in_addr *src_addr; + + src_addr = sources + i; + + /* I.2: lookup reported source (B) */ + source = igmp_find_source_by_addr(group, *src_addr); + if (source) { + /* I.3: if found, clear deletion flag (A*B) */ + IGMP_SOURCE_DONT_DELETE(source->source_flags); + } else { + /* I.4: if not found, create source with timer=0 (B-A) + */ + source = source_new(group, *src_addr); + if (!source) { + /* ugh, internal malloc failure, skip source */ + continue; + } + zassert(!source->t_source_timer); /* (B-A) timer=0 */ + } + + } /* scan received sources */ + + /* I.5: delete all sources marked with deletion flag (A-B) */ + source_delete_by_flag(group->group_source_list); + + group->group_filtermode_isexcl = 1; /* boolean=true */ + + zassert(group->group_filtermode_isexcl); + + group_exclude_fwd_anysrc_ifempty(group); } void igmpv3_report_isex(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources, - int from_igmp_v2_report) + struct in_addr group_addr, int num_sources, + struct in_addr *sources, int from_igmp_v2_report) { - struct interface *ifp = igmp->interface; - struct igmp_group *group; - - on_trace(__PRETTY_FUNCTION__, - ifp, from, group_addr, num_sources, sources); - - /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr); - if (!group) { - return; - } - - /* So we can display how we learned the group in our show command output */ - if (from_igmp_v2_report) - group->igmp_version = 2; - - if (group->group_filtermode_isexcl) { - /* EXCLUDE mode */ - isex_excl(group, num_sources, sources); - } - else { - /* INCLUDE mode */ - isex_incl(group, num_sources, sources); - zassert(group->group_filtermode_isexcl); - } - - zassert(group->group_filtermode_isexcl); - - igmp_group_reset_gmi(group); + struct interface *ifp = igmp->interface; + struct igmp_group *group; + + on_trace(__PRETTY_FUNCTION__, ifp, from, group_addr, num_sources, + sources); + + /* non-existant group is created as INCLUDE {empty} */ + group = igmp_add_group_by_addr(igmp, group_addr); + if (!group) { + return; + } + + /* So we can display how we learned the group in our show command output + */ + if (from_igmp_v2_report) + group->igmp_version = 2; + + if (group->group_filtermode_isexcl) { + /* EXCLUDE mode */ + isex_excl(group, num_sources, sources); + } else { + /* INCLUDE mode */ + isex_incl(group, num_sources, sources); + zassert(group->group_filtermode_isexcl); + } + + zassert(group->group_filtermode_isexcl); + + igmp_group_reset_gmi(group); } -static void toin_incl(struct igmp_group *group, - int num_sources, struct in_addr *sources) +static void toin_incl(struct igmp_group *group, int num_sources, + struct in_addr *sources) { - struct igmp_sock *igmp = group->group_igmp_sock; - int num_sources_tosend = listcount(group->group_source_list); - int i; - - /* Set SEND flag for all known sources (A) */ - source_mark_send_flag (group); - - /* Scan received sources (B) */ - for (i = 0; i < num_sources; ++i) { - struct igmp_source *source; - struct in_addr *src_addr; - - src_addr = sources + i; - - /* Lookup reported source (B) */ - source = igmp_find_source_by_addr(group, *src_addr); - if (source) { - /* If found, clear SEND flag (A*B) */ - IGMP_SOURCE_DONT_SEND(source->source_flags); - --num_sources_tosend; - } - else { - /* If not found, create new source */ - source = source_new(group, *src_addr); - if (!source) { - /* ugh, internal malloc failure, skip source */ - continue; - } - } - - /* (B)=GMI */ - igmp_source_reset_gmi(igmp, group, source); - } - - /* Send sources marked with SEND flag: Q(G,A-B) */ - if (num_sources_tosend > 0) { - source_query_send_by_flag(group, num_sources_tosend); - } + struct igmp_sock *igmp = group->group_igmp_sock; + int num_sources_tosend = listcount(group->group_source_list); + int i; + + /* Set SEND flag for all known sources (A) */ + source_mark_send_flag(group); + + /* Scan received sources (B) */ + for (i = 0; i < num_sources; ++i) { + struct igmp_source *source; + struct in_addr *src_addr; + + src_addr = sources + i; + + /* Lookup reported source (B) */ + source = igmp_find_source_by_addr(group, *src_addr); + if (source) { + /* If found, clear SEND flag (A*B) */ + IGMP_SOURCE_DONT_SEND(source->source_flags); + --num_sources_tosend; + } else { + /* If not found, create new source */ + source = source_new(group, *src_addr); + if (!source) { + /* ugh, internal malloc failure, skip source */ + continue; + } + } + + /* (B)=GMI */ + igmp_source_reset_gmi(igmp, group, source); + } + + /* Send sources marked with SEND flag: Q(G,A-B) */ + if (num_sources_tosend > 0) { + source_query_send_by_flag(group, num_sources_tosend); + } } -static void toin_excl(struct igmp_group *group, - int num_sources, struct in_addr *sources) +static void toin_excl(struct igmp_group *group, int num_sources, + struct in_addr *sources) { - struct igmp_sock *igmp = group->group_igmp_sock; - int num_sources_tosend; - int i; - - /* Set SEND flag for X (sources with timer > 0) */ - num_sources_tosend = source_mark_send_flag_by_timer (group); - - /* Scan received sources (A) */ - for (i = 0; i < num_sources; ++i) { - struct igmp_source *source; - struct in_addr *src_addr; - - src_addr = sources + i; - - /* Lookup reported source (A) */ - source = igmp_find_source_by_addr(group, *src_addr); - if (source) { - if (source->t_source_timer) { - /* If found and timer running, clear SEND flag (X*A) */ - IGMP_SOURCE_DONT_SEND(source->source_flags); - --num_sources_tosend; - } - } - else { - /* If not found, create new source */ - source = source_new(group, *src_addr); - if (!source) { - /* ugh, internal malloc failure, skip source */ - continue; - } - } - - /* (A)=GMI */ - igmp_source_reset_gmi(igmp, group, source); - } - - /* Send sources marked with SEND flag: Q(G,X-A) */ - if (num_sources_tosend > 0) { - source_query_send_by_flag(group, num_sources_tosend); - } - - /* Send Q(G) */ - group_query_send(group); + struct igmp_sock *igmp = group->group_igmp_sock; + int num_sources_tosend; + int i; + + /* Set SEND flag for X (sources with timer > 0) */ + num_sources_tosend = source_mark_send_flag_by_timer(group); + + /* Scan received sources (A) */ + for (i = 0; i < num_sources; ++i) { + struct igmp_source *source; + struct in_addr *src_addr; + + src_addr = sources + i; + + /* Lookup reported source (A) */ + source = igmp_find_source_by_addr(group, *src_addr); + if (source) { + if (source->t_source_timer) { + /* If found and timer running, clear SEND flag + * (X*A) */ + IGMP_SOURCE_DONT_SEND(source->source_flags); + --num_sources_tosend; + } + } else { + /* If not found, create new source */ + source = source_new(group, *src_addr); + if (!source) { + /* ugh, internal malloc failure, skip source */ + continue; + } + } + + /* (A)=GMI */ + igmp_source_reset_gmi(igmp, group, source); + } + + /* Send sources marked with SEND flag: Q(G,X-A) */ + if (num_sources_tosend > 0) { + source_query_send_by_flag(group, num_sources_tosend); + } + + /* Send Q(G) */ + group_query_send(group); } void igmpv3_report_toin(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources) + struct in_addr group_addr, int num_sources, + struct in_addr *sources) { - struct interface *ifp = igmp->interface; - struct igmp_group *group; - - on_trace(__PRETTY_FUNCTION__, - ifp, from, group_addr, num_sources, sources); - - /* - * If the requested filter mode is INCLUDE *and* the requested source - * list is empty, then the entry corresponding to the requested - * interface and multicast address is deleted if present. If no such - * entry is present, the request is ignored. - */ - if (num_sources) - { - /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr); - if (!group) { - return; - } - } - else - { - group = find_group_by_addr (igmp, group_addr); - if (!group) - return; - } - - if (group->group_filtermode_isexcl) { - /* EXCLUDE mode */ - toin_excl(group, num_sources, sources); - } - else { - /* INCLUDE mode */ - toin_incl(group, num_sources, sources); - } + struct interface *ifp = igmp->interface; + struct igmp_group *group; + + on_trace(__PRETTY_FUNCTION__, ifp, from, group_addr, num_sources, + sources); + + /* + * If the requested filter mode is INCLUDE *and* the requested source + * list is empty, then the entry corresponding to the requested + * interface and multicast address is deleted if present. If no such + * entry is present, the request is ignored. + */ + if (num_sources) { + /* non-existant group is created as INCLUDE {empty} */ + group = igmp_add_group_by_addr(igmp, group_addr); + if (!group) { + return; + } + } else { + group = find_group_by_addr(igmp, group_addr); + if (!group) + return; + } + + if (group->group_filtermode_isexcl) { + /* EXCLUDE mode */ + toin_excl(group, num_sources, sources); + } else { + /* INCLUDE mode */ + toin_incl(group, num_sources, sources); + } } -static void toex_incl(struct igmp_group *group, - int num_sources, struct in_addr *sources) +static void toex_incl(struct igmp_group *group, int num_sources, + struct in_addr *sources) { - int num_sources_tosend = 0; - int i; - - zassert(!group->group_filtermode_isexcl); - - /* Set DELETE flag for all known sources (A) */ - source_mark_delete_flag (group); - - /* Clear off SEND flag from all known sources (A) */ - source_clear_send_flag(group->group_source_list); - - /* Scan received sources (B) */ - for (i = 0; i < num_sources; ++i) { - struct igmp_source *source; - struct in_addr *src_addr; - - src_addr = sources + i; - - /* Lookup reported source (B) */ - source = igmp_find_source_by_addr(group, *src_addr); - if (source) { - /* If found, clear deletion flag: (A*B) */ - IGMP_SOURCE_DONT_DELETE(source->source_flags); - /* and set SEND flag (A*B) */ - IGMP_SOURCE_DO_SEND(source->source_flags); - ++num_sources_tosend; - } - else { - /* If source not found, create source with timer=0: (B-A)=0 */ - source = source_new(group, *src_addr); - if (!source) { - /* ugh, internal malloc failure, skip source */ - continue; - } - zassert(!source->t_source_timer); /* (B-A) timer=0 */ - } - - } /* Scan received sources (B) */ - - group->group_filtermode_isexcl = 1; /* boolean=true */ - - /* Delete all sources marked with DELETE flag (A-B) */ - source_delete_by_flag(group->group_source_list); - - /* Send sources marked with SEND flag: Q(G,A*B) */ - if (num_sources_tosend > 0) { - source_query_send_by_flag(group, num_sources_tosend); - } - - zassert(group->group_filtermode_isexcl); - - group_exclude_fwd_anysrc_ifempty(group); + int num_sources_tosend = 0; + int i; + + zassert(!group->group_filtermode_isexcl); + + /* Set DELETE flag for all known sources (A) */ + source_mark_delete_flag(group); + + /* Clear off SEND flag from all known sources (A) */ + source_clear_send_flag(group->group_source_list); + + /* Scan received sources (B) */ + for (i = 0; i < num_sources; ++i) { + struct igmp_source *source; + struct in_addr *src_addr; + + src_addr = sources + i; + + /* Lookup reported source (B) */ + source = igmp_find_source_by_addr(group, *src_addr); + if (source) { + /* If found, clear deletion flag: (A*B) */ + IGMP_SOURCE_DONT_DELETE(source->source_flags); + /* and set SEND flag (A*B) */ + IGMP_SOURCE_DO_SEND(source->source_flags); + ++num_sources_tosend; + } else { + /* If source not found, create source with timer=0: + * (B-A)=0 */ + source = source_new(group, *src_addr); + if (!source) { + /* ugh, internal malloc failure, skip source */ + continue; + } + zassert(!source->t_source_timer); /* (B-A) timer=0 */ + } + + } /* Scan received sources (B) */ + + group->group_filtermode_isexcl = 1; /* boolean=true */ + + /* Delete all sources marked with DELETE flag (A-B) */ + source_delete_by_flag(group->group_source_list); + + /* Send sources marked with SEND flag: Q(G,A*B) */ + if (num_sources_tosend > 0) { + source_query_send_by_flag(group, num_sources_tosend); + } + + zassert(group->group_filtermode_isexcl); + + group_exclude_fwd_anysrc_ifempty(group); } -static void toex_excl(struct igmp_group *group, - int num_sources, struct in_addr *sources) +static void toex_excl(struct igmp_group *group, int num_sources, + struct in_addr *sources) { - int num_sources_tosend = 0; - int i; - - /* set DELETE flag for all known sources (X,Y) */ - source_mark_delete_flag (group); - - /* clear off SEND flag from all known sources (X,Y) */ - source_clear_send_flag(group->group_source_list); - - if (num_sources == 0) - { - struct igmp_source *source; - struct in_addr any = { .s_addr = INADDR_ANY }; - - source = igmp_find_source_by_addr (group, any); - if (source) - IGMP_SOURCE_DONT_DELETE(source->source_flags); - } - - /* scan received sources (A) */ - for (i = 0; i < num_sources; ++i) { - struct igmp_source *source; - struct in_addr *src_addr; - - src_addr = sources + i; - - /* lookup reported source (A) in known sources (X,Y) */ - source = igmp_find_source_by_addr(group, *src_addr); - if (source) { - /* if found, clear off DELETE flag from reported source (A) */ - IGMP_SOURCE_DONT_DELETE(source->source_flags); - } - else { - /* if not found, create source with Group Timer: (A-X-Y)=Group Timer */ - long group_timer_msec; - source = source_new(group, *src_addr); - if (!source) { - /* ugh, internal malloc failure, skip source */ - continue; - } - - zassert(!source->t_source_timer); /* timer == 0 */ - group_timer_msec = igmp_group_timer_remain_msec(group); - igmp_source_timer_on(group, source, group_timer_msec); - zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ - - /* make sure source is created with DELETE flag unset */ - zassert(!IGMP_SOURCE_TEST_DELETE(source->source_flags)); - } - - /* make sure reported source has DELETE flag unset */ - zassert(!IGMP_SOURCE_TEST_DELETE(source->source_flags)); - - if (source->t_source_timer) { - /* if source timer>0 mark SEND flag: Q(G,A-Y) */ - IGMP_SOURCE_DO_SEND(source->source_flags); - ++num_sources_tosend; - } - - } /* scan received sources (A) */ - - /* - delete all sources marked with DELETE flag: - Delete (X-A) - Delete (Y-A) - */ - source_delete_by_flag(group->group_source_list); - - /* send sources marked with SEND flag: Q(G,A-Y) */ - if (num_sources_tosend > 0) { - source_query_send_by_flag(group, num_sources_tosend); - } + int num_sources_tosend = 0; + int i; + + /* set DELETE flag for all known sources (X,Y) */ + source_mark_delete_flag(group); + + /* clear off SEND flag from all known sources (X,Y) */ + source_clear_send_flag(group->group_source_list); + + if (num_sources == 0) { + struct igmp_source *source; + struct in_addr any = {.s_addr = INADDR_ANY}; + + source = igmp_find_source_by_addr(group, any); + if (source) + IGMP_SOURCE_DONT_DELETE(source->source_flags); + } + + /* scan received sources (A) */ + for (i = 0; i < num_sources; ++i) { + struct igmp_source *source; + struct in_addr *src_addr; + + src_addr = sources + i; + + /* lookup reported source (A) in known sources (X,Y) */ + source = igmp_find_source_by_addr(group, *src_addr); + if (source) { + /* if found, clear off DELETE flag from reported source + * (A) */ + IGMP_SOURCE_DONT_DELETE(source->source_flags); + } else { + /* if not found, create source with Group Timer: + * (A-X-Y)=Group Timer */ + long group_timer_msec; + source = source_new(group, *src_addr); + if (!source) { + /* ugh, internal malloc failure, skip source */ + continue; + } + + zassert(!source->t_source_timer); /* timer == 0 */ + group_timer_msec = igmp_group_timer_remain_msec(group); + igmp_source_timer_on(group, source, group_timer_msec); + zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ + + /* make sure source is created with DELETE flag unset */ + zassert(!IGMP_SOURCE_TEST_DELETE(source->source_flags)); + } + + /* make sure reported source has DELETE flag unset */ + zassert(!IGMP_SOURCE_TEST_DELETE(source->source_flags)); + + if (source->t_source_timer) { + /* if source timer>0 mark SEND flag: Q(G,A-Y) */ + IGMP_SOURCE_DO_SEND(source->source_flags); + ++num_sources_tosend; + } + + } /* scan received sources (A) */ + + /* + delete all sources marked with DELETE flag: + Delete (X-A) + Delete (Y-A) + */ + source_delete_by_flag(group->group_source_list); + + /* send sources marked with SEND flag: Q(G,A-Y) */ + if (num_sources_tosend > 0) { + source_query_send_by_flag(group, num_sources_tosend); + } } void igmpv3_report_toex(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources) + struct in_addr group_addr, int num_sources, + struct in_addr *sources) { - struct interface *ifp = igmp->interface; - struct igmp_group *group; - - on_trace(__PRETTY_FUNCTION__, - ifp, from, group_addr, num_sources, sources); - - /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr); - if (!group) { - return; - } - - if (group->group_filtermode_isexcl) { - /* EXCLUDE mode */ - toex_excl(group, num_sources, sources); - } - else { - /* INCLUDE mode */ - toex_incl(group, num_sources, sources); - zassert(group->group_filtermode_isexcl); - } - zassert(group->group_filtermode_isexcl); - - /* Group Timer=GMI */ - igmp_group_reset_gmi(group); + struct interface *ifp = igmp->interface; + struct igmp_group *group; + + on_trace(__PRETTY_FUNCTION__, ifp, from, group_addr, num_sources, + sources); + + /* non-existant group is created as INCLUDE {empty} */ + group = igmp_add_group_by_addr(igmp, group_addr); + if (!group) { + return; + } + + if (group->group_filtermode_isexcl) { + /* EXCLUDE mode */ + toex_excl(group, num_sources, sources); + } else { + /* INCLUDE mode */ + toex_incl(group, num_sources, sources); + zassert(group->group_filtermode_isexcl); + } + zassert(group->group_filtermode_isexcl); + + /* Group Timer=GMI */ + igmp_group_reset_gmi(group); } void igmpv3_report_allow(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources) + struct in_addr group_addr, int num_sources, + struct in_addr *sources) { - on_trace(__PRETTY_FUNCTION__, - igmp->interface, from, group_addr, num_sources, sources); + on_trace(__PRETTY_FUNCTION__, igmp->interface, from, group_addr, + num_sources, sources); - allow(igmp, from, group_addr, num_sources, sources); + allow(igmp, from, group_addr, num_sources, sources); } /* @@ -1005,67 +1003,64 @@ void igmpv3_report_allow(struct igmp_sock *igmp, struct in_addr from, */ static void group_retransmit_group(struct igmp_group *group) { - struct igmp_sock *igmp; - struct pim_interface *pim_ifp; - long lmqc; /* Last Member Query Count */ - long lmqi_msec; /* Last Member Query Interval */ - long lmqt_msec; /* Last Member Query Time */ - int s_flag; - int query_buf_size; - - igmp = group->group_igmp_sock; - pim_ifp = igmp->interface->info; - - if (pim_ifp->igmp_version == 3) { - query_buf_size = PIM_IGMP_BUFSIZE_WRITE; - } else { - query_buf_size = IGMP_V12_MSG_SIZE; - } - - char query_buf[query_buf_size]; - - lmqc = igmp->querier_robustness_variable; - lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; - lmqt_msec = lmqc * lmqi_msec; - - /* - RFC3376: 6.6.3.1. Building and Sending Group Specific Queries - - When transmitting a group specific query, if the group timer is - larger than LMQT, the "Suppress Router-Side Processing" bit is set - in the query message. - */ - s_flag = igmp_group_timer_remain_msec(group) > lmqt_msec; - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("retransmit_group_specific_query: group %s on %s: s_flag=%d count=%d", - group_str, igmp->interface->name, s_flag, - group->group_specific_query_retransmit_count); - } - - /* - RFC3376: 4.1.12. IP Destination Addresses for Queries - - Group-Specific and Group-and-Source-Specific Queries are sent with - an IP destination address equal to the multicast address of - interest. - */ - - igmp_send_query(pim_ifp->igmp_version, - group, - igmp->fd, - igmp->interface->name, - query_buf, - sizeof(query_buf), - 0 /* num_sources_tosend */, - group->group_addr /* dst_addr */, - group->group_addr /* group_addr */, - pim_ifp->igmp_specific_query_max_response_time_dsec, - s_flag, - igmp->querier_robustness_variable, - igmp->querier_query_interval); + struct igmp_sock *igmp; + struct pim_interface *pim_ifp; + long lmqc; /* Last Member Query Count */ + long lmqi_msec; /* Last Member Query Interval */ + long lmqt_msec; /* Last Member Query Time */ + int s_flag; + int query_buf_size; + + igmp = group->group_igmp_sock; + pim_ifp = igmp->interface->info; + + if (pim_ifp->igmp_version == 3) { + query_buf_size = PIM_IGMP_BUFSIZE_WRITE; + } else { + query_buf_size = IGMP_V12_MSG_SIZE; + } + + char query_buf[query_buf_size]; + + lmqc = igmp->querier_robustness_variable; + lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; + lmqt_msec = lmqc * lmqi_msec; + + /* + RFC3376: 6.6.3.1. Building and Sending Group Specific Queries + + When transmitting a group specific query, if the group timer is + larger than LMQT, the "Suppress Router-Side Processing" bit is set + in the query message. + */ + s_flag = igmp_group_timer_remain_msec(group) > lmqt_msec; + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug( + "retransmit_group_specific_query: group %s on %s: s_flag=%d count=%d", + group_str, igmp->interface->name, s_flag, + group->group_specific_query_retransmit_count); + } + + /* + RFC3376: 4.1.12. IP Destination Addresses for Queries + + Group-Specific and Group-and-Source-Specific Queries are sent with + an IP destination address equal to the multicast address of + interest. + */ + + igmp_send_query(pim_ifp->igmp_version, group, igmp->fd, + igmp->interface->name, query_buf, sizeof(query_buf), + 0 /* num_sources_tosend */, + group->group_addr /* dst_addr */, + group->group_addr /* group_addr */, + pim_ifp->igmp_specific_query_max_response_time_dsec, + s_flag, igmp->querier_robustness_variable, + igmp->querier_query_interval); } /* @@ -1083,205 +1078,214 @@ static void group_retransmit_group(struct igmp_group *group) static int group_retransmit_sources(struct igmp_group *group, int send_with_sflag_set) { - struct igmp_sock *igmp; - struct pim_interface *pim_ifp; - long lmqc; /* Last Member Query Count */ - long lmqi_msec; /* Last Member Query Interval */ - long lmqt_msec; /* Last Member Query Time */ - char query_buf1[PIM_IGMP_BUFSIZE_WRITE]; /* 1 = with s_flag set */ - char query_buf2[PIM_IGMP_BUFSIZE_WRITE]; /* 2 = with s_flag clear */ - int query_buf1_max_sources; - int query_buf2_max_sources; - struct in_addr *source_addr1; - struct in_addr *source_addr2; - int num_sources_tosend1; - int num_sources_tosend2; - struct listnode *src_node; - struct igmp_source *src; - int num_retransmit_sources_left = 0; - - source_addr1 = (struct in_addr *)(query_buf1 + IGMP_V3_SOURCES_OFFSET); - source_addr2 = (struct in_addr *)(query_buf2 + IGMP_V3_SOURCES_OFFSET); - - igmp = group->group_igmp_sock; - pim_ifp = igmp->interface->info; - - lmqc = igmp->querier_robustness_variable; - lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; - lmqt_msec = lmqc * lmqi_msec; - - /* Scan all group sources */ - for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { - - /* Source has retransmission state? */ - if (src->source_query_retransmit_count < 1) - continue; - - if (--src->source_query_retransmit_count > 0) { - ++num_retransmit_sources_left; - } - - /* Copy source address into appropriate query buffer */ - if (igmp_source_timer_remain_msec(src) > lmqt_msec) { - *source_addr1 = src->source_addr; - ++source_addr1; - } - else { - *source_addr2 = src->source_addr; - ++source_addr2; - } - - } - - num_sources_tosend1 = source_addr1 - (struct in_addr *)(query_buf1 + IGMP_V3_SOURCES_OFFSET); - num_sources_tosend2 = source_addr2 - (struct in_addr *)(query_buf2 + IGMP_V3_SOURCES_OFFSET); - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("retransmit_grp&src_specific_query: group %s on %s: srcs_with_sflag=%d srcs_wo_sflag=%d will_send_sflag=%d retransmit_src_left=%d", - group_str, igmp->interface->name, - num_sources_tosend1, - num_sources_tosend2, - send_with_sflag_set, - num_retransmit_sources_left); - } - - if (num_sources_tosend1 > 0) { - /* - Send group-and-source-specific query with s_flag set and all - sources with timers greater than LMQT. - */ - - if (send_with_sflag_set) { - - query_buf1_max_sources = (sizeof(query_buf1) - IGMP_V3_SOURCES_OFFSET) >> 2; - if (num_sources_tosend1 > query_buf1_max_sources) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - zlog_warn("%s: group %s on %s: s_flag=1 unable to fit %d sources into buf_size=%zu (max_sources=%d)", - __PRETTY_FUNCTION__, group_str, igmp->interface->name, - num_sources_tosend1, sizeof(query_buf1), query_buf1_max_sources); - } - else { - /* - RFC3376: 4.1.12. IP Destination Addresses for Queries - - Group-Specific and Group-and-Source-Specific Queries are sent with - an IP destination address equal to the multicast address of - interest. - */ - - igmp_send_query(pim_ifp->igmp_version, - group, - igmp->fd, - igmp->interface->name, - query_buf1, - sizeof(query_buf1), - num_sources_tosend1, - group->group_addr, - group->group_addr, - pim_ifp->igmp_specific_query_max_response_time_dsec, - 1 /* s_flag */, - igmp->querier_robustness_variable, - igmp->querier_query_interval); - } - - } /* send_with_sflag_set */ - - } - - if (num_sources_tosend2 > 0) { - /* - Send group-and-source-specific query with s_flag clear and all - sources with timers lower or equal to LMQT. - */ - - query_buf2_max_sources = (sizeof(query_buf2) - IGMP_V3_SOURCES_OFFSET) >> 2; - if (num_sources_tosend2 > query_buf2_max_sources) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - zlog_warn("%s: group %s on %s: s_flag=0 unable to fit %d sources into buf_size=%zu (max_sources=%d)", - __PRETTY_FUNCTION__, group_str, igmp->interface->name, - num_sources_tosend2, sizeof(query_buf2), query_buf2_max_sources); - } - else { - /* - RFC3376: 4.1.12. IP Destination Addresses for Queries - - Group-Specific and Group-and-Source-Specific Queries are sent with - an IP destination address equal to the multicast address of - interest. - */ - - igmp_send_query(pim_ifp->igmp_version, - group, - igmp->fd, - igmp->interface->name, - query_buf2, - sizeof(query_buf2), - num_sources_tosend2, - group->group_addr, - group->group_addr, - pim_ifp->igmp_specific_query_max_response_time_dsec, - 0 /* s_flag */, - igmp->querier_robustness_variable, - igmp->querier_query_interval); - } - } - - return num_retransmit_sources_left; + struct igmp_sock *igmp; + struct pim_interface *pim_ifp; + long lmqc; /* Last Member Query Count */ + long lmqi_msec; /* Last Member Query Interval */ + long lmqt_msec; /* Last Member Query Time */ + char query_buf1[PIM_IGMP_BUFSIZE_WRITE]; /* 1 = with s_flag set */ + char query_buf2[PIM_IGMP_BUFSIZE_WRITE]; /* 2 = with s_flag clear */ + int query_buf1_max_sources; + int query_buf2_max_sources; + struct in_addr *source_addr1; + struct in_addr *source_addr2; + int num_sources_tosend1; + int num_sources_tosend2; + struct listnode *src_node; + struct igmp_source *src; + int num_retransmit_sources_left = 0; + + source_addr1 = (struct in_addr *)(query_buf1 + IGMP_V3_SOURCES_OFFSET); + source_addr2 = (struct in_addr *)(query_buf2 + IGMP_V3_SOURCES_OFFSET); + + igmp = group->group_igmp_sock; + pim_ifp = igmp->interface->info; + + lmqc = igmp->querier_robustness_variable; + lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; + lmqt_msec = lmqc * lmqi_msec; + + /* Scan all group sources */ + for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { + + /* Source has retransmission state? */ + if (src->source_query_retransmit_count < 1) + continue; + + if (--src->source_query_retransmit_count > 0) { + ++num_retransmit_sources_left; + } + + /* Copy source address into appropriate query buffer */ + if (igmp_source_timer_remain_msec(src) > lmqt_msec) { + *source_addr1 = src->source_addr; + ++source_addr1; + } else { + *source_addr2 = src->source_addr; + ++source_addr2; + } + } + + num_sources_tosend1 = + source_addr1 + - (struct in_addr *)(query_buf1 + IGMP_V3_SOURCES_OFFSET); + num_sources_tosend2 = + source_addr2 + - (struct in_addr *)(query_buf2 + IGMP_V3_SOURCES_OFFSET); + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug( + "retransmit_grp&src_specific_query: group %s on %s: srcs_with_sflag=%d srcs_wo_sflag=%d will_send_sflag=%d retransmit_src_left=%d", + group_str, igmp->interface->name, num_sources_tosend1, + num_sources_tosend2, send_with_sflag_set, + num_retransmit_sources_left); + } + + if (num_sources_tosend1 > 0) { + /* + Send group-and-source-specific query with s_flag set and all + sources with timers greater than LMQT. + */ + + if (send_with_sflag_set) { + + query_buf1_max_sources = + (sizeof(query_buf1) - IGMP_V3_SOURCES_OFFSET) + >> 2; + if (num_sources_tosend1 > query_buf1_max_sources) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group->group_addr, + group_str, sizeof(group_str)); + zlog_warn( + "%s: group %s on %s: s_flag=1 unable to fit %d sources into buf_size=%zu (max_sources=%d)", + __PRETTY_FUNCTION__, group_str, + igmp->interface->name, + num_sources_tosend1, sizeof(query_buf1), + query_buf1_max_sources); + } else { + /* + RFC3376: 4.1.12. IP Destination Addresses for + Queries + + Group-Specific and Group-and-Source-Specific + Queries are sent with + an IP destination address equal to the + multicast address of + interest. + */ + + igmp_send_query( + pim_ifp->igmp_version, group, igmp->fd, + igmp->interface->name, query_buf1, + sizeof(query_buf1), num_sources_tosend1, + group->group_addr, group->group_addr, + pim_ifp->igmp_specific_query_max_response_time_dsec, + 1 /* s_flag */, + igmp->querier_robustness_variable, + igmp->querier_query_interval); + } + + } /* send_with_sflag_set */ + } + + if (num_sources_tosend2 > 0) { + /* + Send group-and-source-specific query with s_flag clear and all + sources with timers lower or equal to LMQT. + */ + + query_buf2_max_sources = + (sizeof(query_buf2) - IGMP_V3_SOURCES_OFFSET) >> 2; + if (num_sources_tosend2 > query_buf2_max_sources) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group->group_addr, group_str, + sizeof(group_str)); + zlog_warn( + "%s: group %s on %s: s_flag=0 unable to fit %d sources into buf_size=%zu (max_sources=%d)", + __PRETTY_FUNCTION__, group_str, + igmp->interface->name, num_sources_tosend2, + sizeof(query_buf2), query_buf2_max_sources); + } else { + /* + RFC3376: 4.1.12. IP Destination Addresses for Queries + + Group-Specific and Group-and-Source-Specific Queries + are sent with + an IP destination address equal to the multicast + address of + interest. + */ + + igmp_send_query( + pim_ifp->igmp_version, group, igmp->fd, + igmp->interface->name, query_buf2, + sizeof(query_buf2), num_sources_tosend2, + group->group_addr, group->group_addr, + pim_ifp->igmp_specific_query_max_response_time_dsec, + 0 /* s_flag */, + igmp->querier_robustness_variable, + igmp->querier_query_interval); + } + } + + return num_retransmit_sources_left; } static int igmp_group_retransmit(struct thread *t) { - struct igmp_group *group; - int num_retransmit_sources_left; - int send_with_sflag_set; /* boolean */ - - group = THREAD_ARG(t); - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("group_retransmit_timer: group %s on %s", - group_str, group->group_igmp_sock->interface->name); - } - - /* Retransmit group-specific queries? (RFC3376: 6.6.3.1) */ - if (group->group_specific_query_retransmit_count > 0) { - - /* Retransmit group-specific queries (RFC3376: 6.6.3.1) */ - group_retransmit_group(group); - --group->group_specific_query_retransmit_count; - - /* - RFC3376: 6.6.3.2 - If a group specific query is scheduled to be transmitted at the - same time as a group and source specific query for the same group, - then transmission of the group and source specific message with the - "Suppress Router-Side Processing" bit set may be suppressed. - */ - send_with_sflag_set = 0; /* boolean=false */ - } - else { - send_with_sflag_set = 1; /* boolean=true */ - } - - /* Retransmit group-and-source-specific queries (RFC3376: 6.6.3.2) */ - num_retransmit_sources_left = group_retransmit_sources(group, - send_with_sflag_set); - - /* - Keep group retransmit timer running if there is any retransmit - counter pending - */ - if ((num_retransmit_sources_left > 0) || - (group->group_specific_query_retransmit_count > 0)) { - group_retransmit_timer_on(group); - } - - return 0; + struct igmp_group *group; + int num_retransmit_sources_left; + int send_with_sflag_set; /* boolean */ + + group = THREAD_ARG(t); + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug("group_retransmit_timer: group %s on %s", group_str, + group->group_igmp_sock->interface->name); + } + + /* Retransmit group-specific queries? (RFC3376: 6.6.3.1) */ + if (group->group_specific_query_retransmit_count > 0) { + + /* Retransmit group-specific queries (RFC3376: 6.6.3.1) */ + group_retransmit_group(group); + --group->group_specific_query_retransmit_count; + + /* + RFC3376: 6.6.3.2 + If a group specific query is scheduled to be transmitted at + the + same time as a group and source specific query for the same + group, + then transmission of the group and source specific message + with the + "Suppress Router-Side Processing" bit set may be suppressed. + */ + send_with_sflag_set = 0; /* boolean=false */ + } else { + send_with_sflag_set = 1; /* boolean=true */ + } + + /* Retransmit group-and-source-specific queries (RFC3376: 6.6.3.2) */ + num_retransmit_sources_left = + group_retransmit_sources(group, send_with_sflag_set); + + /* + Keep group retransmit timer running if there is any retransmit + counter pending + */ + if ((num_retransmit_sources_left > 0) + || (group->group_specific_query_retransmit_count > 0)) { + group_retransmit_timer_on(group); + } + + return 0; } /* @@ -1291,42 +1295,42 @@ static int igmp_group_retransmit(struct thread *t) */ static void group_retransmit_timer_on(struct igmp_group *group) { - struct igmp_sock *igmp; - struct pim_interface *pim_ifp; - long lmqi_msec; /* Last Member Query Interval */ - - /* if group retransmit timer is running, do nothing */ - if (group->t_group_query_retransmit_timer) { - return; - } - - igmp = group->group_igmp_sock; - pim_ifp = igmp->interface->info; - - lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("Scheduling %ld.%03ld sec retransmit timer for group %s on %s", - lmqi_msec / 1000, - lmqi_msec % 1000, - group_str, - igmp->interface->name); - } - - thread_add_timer_msec(master, igmp_group_retransmit, group, lmqi_msec, - &group->t_group_query_retransmit_timer); + struct igmp_sock *igmp; + struct pim_interface *pim_ifp; + long lmqi_msec; /* Last Member Query Interval */ + + /* if group retransmit timer is running, do nothing */ + if (group->t_group_query_retransmit_timer) { + return; + } + + igmp = group->group_igmp_sock; + pim_ifp = igmp->interface->info; + + lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug( + "Scheduling %ld.%03ld sec retransmit timer for group %s on %s", + lmqi_msec / 1000, lmqi_msec % 1000, group_str, + igmp->interface->name); + } + + thread_add_timer_msec(master, igmp_group_retransmit, group, lmqi_msec, + &group->t_group_query_retransmit_timer); } static long igmp_group_timer_remain_msec(struct igmp_group *group) { - return pim_time_timer_remain_msec(group->t_group_timer); + return pim_time_timer_remain_msec(group->t_group_timer); } static long igmp_source_timer_remain_msec(struct igmp_source *source) { - return pim_time_timer_remain_msec(source->t_source_timer); + return pim_time_timer_remain_msec(source->t_source_timer); } /* @@ -1334,21 +1338,22 @@ static long igmp_source_timer_remain_msec(struct igmp_source *source) */ static void group_query_send(struct igmp_group *group) { - long lmqc; /* Last Member Query Count */ + long lmqc; /* Last Member Query Count */ - lmqc = group->group_igmp_sock->querier_robustness_variable; + lmqc = group->group_igmp_sock->querier_robustness_variable; - /* lower group timer to lmqt */ - igmp_group_timer_lower_to_lmqt(group); + /* lower group timer to lmqt */ + igmp_group_timer_lower_to_lmqt(group); - /* reset retransmission counter */ - group->group_specific_query_retransmit_count = lmqc; + /* reset retransmission counter */ + group->group_specific_query_retransmit_count = lmqc; - /* immediately send group specific query (decrease retransmit counter by 1)*/ - group_retransmit_group(group); + /* immediately send group specific query (decrease retransmit counter by + * 1)*/ + group_retransmit_group(group); - /* make sure group retransmit timer is running */ - group_retransmit_timer_on(group); + /* make sure group retransmit timer is running */ + group_retransmit_timer_on(group); } /* @@ -1357,612 +1362,674 @@ static void group_query_send(struct igmp_group *group) static void source_query_send_by_flag(struct igmp_group *group, int num_sources_tosend) { - struct igmp_sock *igmp; - struct pim_interface *pim_ifp; - struct listnode *src_node; - struct igmp_source *src; - long lmqc; /* Last Member Query Count */ - long lmqi_msec; /* Last Member Query Interval */ - long lmqt_msec; /* Last Member Query Time */ - - zassert(num_sources_tosend > 0); - - igmp = group->group_igmp_sock; - pim_ifp = igmp->interface->info; - - lmqc = igmp->querier_robustness_variable; - lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; - lmqt_msec = lmqc * lmqi_msec; - - /* - RFC3376: 6.6.3.2. Building and Sending Group and Source Specific Queries - - (...) for each of the sources in X of group G, with source timer larger - than LMQT: - o Set number of retransmissions for each source to [Last Member - Query Count]. - o Lower source timer to LMQT. - */ - for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { - if (IGMP_SOURCE_TEST_SEND(src->source_flags)) { - /* source "src" in X of group G */ - if (igmp_source_timer_remain_msec(src) > lmqt_msec) { - src->source_query_retransmit_count = lmqc; - igmp_source_timer_lower_to_lmqt(src); - } - } - } - - /* send group-and-source specific queries */ - group_retransmit_sources(group, 1 /* send_with_sflag_set=true */); - - /* make sure group retransmit timer is running */ - group_retransmit_timer_on(group); + struct igmp_sock *igmp; + struct pim_interface *pim_ifp; + struct listnode *src_node; + struct igmp_source *src; + long lmqc; /* Last Member Query Count */ + long lmqi_msec; /* Last Member Query Interval */ + long lmqt_msec; /* Last Member Query Time */ + + zassert(num_sources_tosend > 0); + + igmp = group->group_igmp_sock; + pim_ifp = igmp->interface->info; + + lmqc = igmp->querier_robustness_variable; + lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec; + lmqt_msec = lmqc * lmqi_msec; + + /* + RFC3376: 6.6.3.2. Building and Sending Group and Source Specific + Queries + + (...) for each of the sources in X of group G, with source timer + larger + than LMQT: + o Set number of retransmissions for each source to [Last Member + Query Count]. + o Lower source timer to LMQT. + */ + for (ALL_LIST_ELEMENTS_RO(group->group_source_list, src_node, src)) { + if (IGMP_SOURCE_TEST_SEND(src->source_flags)) { + /* source "src" in X of group G */ + if (igmp_source_timer_remain_msec(src) > lmqt_msec) { + src->source_query_retransmit_count = lmqc; + igmp_source_timer_lower_to_lmqt(src); + } + } + } + + /* send group-and-source specific queries */ + group_retransmit_sources(group, 1 /* send_with_sflag_set=true */); + + /* make sure group retransmit timer is running */ + group_retransmit_timer_on(group); } -static void block_excl(struct igmp_group *group, - int num_sources, struct in_addr *sources) +static void block_excl(struct igmp_group *group, int num_sources, + struct in_addr *sources) { - int num_sources_tosend = 0; - int i; - - /* 1. clear off SEND flag from all known sources (X,Y) */ - source_clear_send_flag(group->group_source_list); - - /* 2. scan received sources (A) */ - for (i = 0; i < num_sources; ++i) { - struct igmp_source *source; - struct in_addr *src_addr; - - src_addr = sources + i; - - /* lookup reported source (A) in known sources (X,Y) */ - source = igmp_find_source_by_addr(group, *src_addr); - if (!source) { - /* 3: if not found, create source with Group Timer: (A-X-Y)=Group Timer */ - long group_timer_msec; - source = source_new(group, *src_addr); - if (!source) { - /* ugh, internal malloc failure, skip source */ - continue; - } - - zassert(!source->t_source_timer); /* timer == 0 */ - group_timer_msec = igmp_group_timer_remain_msec(group); - igmp_source_timer_on(group, source, group_timer_msec); - zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ - } - - if (source->t_source_timer) { - /* 4. if source timer>0 mark SEND flag: Q(G,A-Y) */ - IGMP_SOURCE_DO_SEND(source->source_flags); - ++num_sources_tosend; - } - } - - /* 5. send sources marked with SEND flag: Q(G,A-Y) */ - if (num_sources_tosend > 0) { - source_query_send_by_flag(group, num_sources_tosend); - } + int num_sources_tosend = 0; + int i; + + /* 1. clear off SEND flag from all known sources (X,Y) */ + source_clear_send_flag(group->group_source_list); + + /* 2. scan received sources (A) */ + for (i = 0; i < num_sources; ++i) { + struct igmp_source *source; + struct in_addr *src_addr; + + src_addr = sources + i; + + /* lookup reported source (A) in known sources (X,Y) */ + source = igmp_find_source_by_addr(group, *src_addr); + if (!source) { + /* 3: if not found, create source with Group Timer: + * (A-X-Y)=Group Timer */ + long group_timer_msec; + source = source_new(group, *src_addr); + if (!source) { + /* ugh, internal malloc failure, skip source */ + continue; + } + + zassert(!source->t_source_timer); /* timer == 0 */ + group_timer_msec = igmp_group_timer_remain_msec(group); + igmp_source_timer_on(group, source, group_timer_msec); + zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */ + } + + if (source->t_source_timer) { + /* 4. if source timer>0 mark SEND flag: Q(G,A-Y) */ + IGMP_SOURCE_DO_SEND(source->source_flags); + ++num_sources_tosend; + } + } + + /* 5. send sources marked with SEND flag: Q(G,A-Y) */ + if (num_sources_tosend > 0) { + source_query_send_by_flag(group, num_sources_tosend); + } } -static void block_incl(struct igmp_group *group, - int num_sources, struct in_addr *sources) +static void block_incl(struct igmp_group *group, int num_sources, + struct in_addr *sources) { - int num_sources_tosend = 0; - int i; - - /* 1. clear off SEND flag from all known sources (B) */ - source_clear_send_flag(group->group_source_list); - - /* 2. scan received sources (A) */ - for (i = 0; i < num_sources; ++i) { - struct igmp_source *source; - struct in_addr *src_addr; - - src_addr = sources + i; - - /* lookup reported source (A) in known sources (B) */ - source = igmp_find_source_by_addr(group, *src_addr); - if (source) { - /* 3. if found (A*B), mark SEND flag: Q(G,A*B) */ - IGMP_SOURCE_DO_SEND(source->source_flags); - ++num_sources_tosend; - } - } - - /* 4. send sources marked with SEND flag: Q(G,A*B) */ - if (num_sources_tosend > 0) { - source_query_send_by_flag(group, num_sources_tosend); - } + int num_sources_tosend = 0; + int i; + + /* 1. clear off SEND flag from all known sources (B) */ + source_clear_send_flag(group->group_source_list); + + /* 2. scan received sources (A) */ + for (i = 0; i < num_sources; ++i) { + struct igmp_source *source; + struct in_addr *src_addr; + + src_addr = sources + i; + + /* lookup reported source (A) in known sources (B) */ + source = igmp_find_source_by_addr(group, *src_addr); + if (source) { + /* 3. if found (A*B), mark SEND flag: Q(G,A*B) */ + IGMP_SOURCE_DO_SEND(source->source_flags); + ++num_sources_tosend; + } + } + + /* 4. send sources marked with SEND flag: Q(G,A*B) */ + if (num_sources_tosend > 0) { + source_query_send_by_flag(group, num_sources_tosend); + } } void igmpv3_report_block(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources) + struct in_addr group_addr, int num_sources, + struct in_addr *sources) { - struct interface *ifp = igmp->interface; - struct igmp_group *group; - - on_trace(__PRETTY_FUNCTION__, - ifp, from, group_addr, num_sources, sources); - - /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr); - if (!group) { - return; - } - - if (group->group_filtermode_isexcl) { - /* EXCLUDE mode */ - block_excl(group, num_sources, sources); - } - else { - /* INCLUDE mode */ - block_incl(group, num_sources, sources); - } + struct interface *ifp = igmp->interface; + struct igmp_group *group; + + on_trace(__PRETTY_FUNCTION__, ifp, from, group_addr, num_sources, + sources); + + /* non-existant group is created as INCLUDE {empty} */ + group = igmp_add_group_by_addr(igmp, group_addr); + if (!group) { + return; + } + + if (group->group_filtermode_isexcl) { + /* EXCLUDE mode */ + block_excl(group, num_sources, sources); + } else { + /* INCLUDE mode */ + block_incl(group, num_sources, sources); + } } void igmp_group_timer_lower_to_lmqt(struct igmp_group *group) { - struct igmp_sock *igmp; - struct interface *ifp; - struct pim_interface *pim_ifp; - char *ifname; - int lmqi_dsec; /* Last Member Query Interval */ - int lmqc; /* Last Member Query Count */ - int lmqt_msec; /* Last Member Query Time */ - - /* - RFC 3376: 6.2.2. Definition of Group Timers - - The group timer is only used when a group is in EXCLUDE mode and - it represents the time for the *filter-mode* of the group to - expire and switch to INCLUDE mode. - */ - if (!group->group_filtermode_isexcl) { - return; - } - - igmp = group->group_igmp_sock; - ifp = igmp->interface; - pim_ifp = ifp->info; - ifname = ifp->name; - - lmqi_dsec = pim_ifp->igmp_specific_query_max_response_time_dsec; - lmqc = igmp->querier_robustness_variable; - lmqt_msec = PIM_IGMP_LMQT_MSEC(lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */ - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - zlog_debug("%s: group %s on %s: LMQC=%d LMQI=%d dsec LMQT=%d msec", - __PRETTY_FUNCTION__, - group_str, ifname, - lmqc, lmqi_dsec, lmqt_msec); - } - - zassert(group->group_filtermode_isexcl); - - igmp_group_timer_on(group, lmqt_msec, ifname); + struct igmp_sock *igmp; + struct interface *ifp; + struct pim_interface *pim_ifp; + char *ifname; + int lmqi_dsec; /* Last Member Query Interval */ + int lmqc; /* Last Member Query Count */ + int lmqt_msec; /* Last Member Query Time */ + + /* + RFC 3376: 6.2.2. Definition of Group Timers + + The group timer is only used when a group is in EXCLUDE mode and + it represents the time for the *filter-mode* of the group to + expire and switch to INCLUDE mode. + */ + if (!group->group_filtermode_isexcl) { + return; + } + + igmp = group->group_igmp_sock; + ifp = igmp->interface; + pim_ifp = ifp->info; + ifname = ifp->name; + + lmqi_dsec = pim_ifp->igmp_specific_query_max_response_time_dsec; + lmqc = igmp->querier_robustness_variable; + lmqt_msec = PIM_IGMP_LMQT_MSEC( + lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */ + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group->group_addr, group_str, + sizeof(group_str)); + zlog_debug( + "%s: group %s on %s: LMQC=%d LMQI=%d dsec LMQT=%d msec", + __PRETTY_FUNCTION__, group_str, ifname, lmqc, lmqi_dsec, + lmqt_msec); + } + + zassert(group->group_filtermode_isexcl); + + igmp_group_timer_on(group, lmqt_msec, ifname); } void igmp_source_timer_lower_to_lmqt(struct igmp_source *source) { - struct igmp_group *group; - struct igmp_sock *igmp; - struct interface *ifp; - struct pim_interface *pim_ifp; - char *ifname; - int lmqi_dsec; /* Last Member Query Interval */ - int lmqc; /* Last Member Query Count */ - int lmqt_msec; /* Last Member Query Time */ - - group = source->source_group; - igmp = group->group_igmp_sock; - ifp = igmp->interface; - pim_ifp = ifp->info; - ifname = ifp->name; - - lmqi_dsec = pim_ifp->igmp_specific_query_max_response_time_dsec; - lmqc = igmp->querier_robustness_variable; - lmqt_msec = PIM_IGMP_LMQT_MSEC(lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */ - - if (PIM_DEBUG_IGMP_TRACE) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); - zlog_debug("%s: group %s source %s on %s: LMQC=%d LMQI=%d dsec LMQT=%d msec", - __PRETTY_FUNCTION__, - group_str, source_str, ifname, - lmqc, lmqi_dsec, lmqt_msec); - } - - igmp_source_timer_on(group, source, lmqt_msec); + struct igmp_group *group; + struct igmp_sock *igmp; + struct interface *ifp; + struct pim_interface *pim_ifp; + char *ifname; + int lmqi_dsec; /* Last Member Query Interval */ + int lmqc; /* Last Member Query Count */ + int lmqt_msec; /* Last Member Query Time */ + + group = source->source_group; + igmp = group->group_igmp_sock; + ifp = igmp->interface; + pim_ifp = ifp->info; + ifname = ifp->name; + + lmqi_dsec = pim_ifp->igmp_specific_query_max_response_time_dsec; + lmqc = igmp->querier_robustness_variable; + lmqt_msec = PIM_IGMP_LMQT_MSEC( + lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */ + + if (PIM_DEBUG_IGMP_TRACE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group->group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("", source->source_addr, source_str, + sizeof(source_str)); + zlog_debug( + "%s: group %s source %s on %s: LMQC=%d LMQI=%d dsec LMQT=%d msec", + __PRETTY_FUNCTION__, group_str, source_str, ifname, + lmqc, lmqi_dsec, lmqt_msec); + } + + igmp_source_timer_on(group, source, lmqt_msec); } -void -igmp_v3_send_query (struct igmp_group *group, - int fd, - const char *ifname, - char *query_buf, - int query_buf_size, - int num_sources, - struct in_addr dst_addr, - struct in_addr group_addr, - int query_max_response_time_dsec, - uint8_t s_flag, - uint8_t querier_robustness_variable, - uint16_t querier_query_interval) +void igmp_v3_send_query(struct igmp_group *group, int fd, const char *ifname, + char *query_buf, int query_buf_size, int num_sources, + struct in_addr dst_addr, struct in_addr group_addr, + int query_max_response_time_dsec, uint8_t s_flag, + uint8_t querier_robustness_variable, + uint16_t querier_query_interval) { - ssize_t msg_size; - uint8_t max_resp_code; - uint8_t qqic; - ssize_t sent; - struct sockaddr_in to; - socklen_t tolen; - uint16_t checksum; - - zassert(num_sources >= 0); - - msg_size = IGMP_V3_SOURCES_OFFSET + (num_sources << 2); - if (msg_size > query_buf_size) { - zlog_err("%s %s: unable to send: msg_size=%zd larger than query_buf_size=%d", - __FILE__, __PRETTY_FUNCTION__, - msg_size, query_buf_size); - return; - } - - s_flag = PIM_FORCE_BOOLEAN(s_flag); - zassert((s_flag == 0) || (s_flag == 1)); - - max_resp_code = igmp_msg_encode16to8(query_max_response_time_dsec); - qqic = igmp_msg_encode16to8(querier_query_interval); - - /* - RFC 3376: 4.1.6. QRV (Querier's Robustness Variable) - - If non-zero, the QRV field contains the [Robustness Variable] - value used by the querier, i.e., the sender of the Query. If the - querier's [Robustness Variable] exceeds 7, the maximum value of - the QRV field, the QRV is set to zero. - */ - if (querier_robustness_variable > 7) { - querier_robustness_variable = 0; - } - - query_buf[0] = PIM_IGMP_MEMBERSHIP_QUERY; - query_buf[1] = max_resp_code; - *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = 0; /* for computing checksum */ - memcpy(query_buf+4, &group_addr, sizeof(struct in_addr)); - - query_buf[8] = (s_flag << 3) | querier_robustness_variable; - query_buf[9] = qqic; - *(uint16_t *)(query_buf + IGMP_V3_NUMSOURCES_OFFSET) = htons(num_sources); - - checksum = in_cksum(query_buf, msg_size); - *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum; - - if (PIM_DEBUG_IGMP_PACKETS) { - char dst_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - zlog_debug("Send IGMPv3 query to %s on %s for group %s, sources=%d msg_size=%zd s_flag=%x QRV=%u QQI=%u QQIC=%02x", - dst_str, ifname, group_str, - num_sources, msg_size, s_flag, querier_robustness_variable, - querier_query_interval, qqic); - } - - memset(&to, 0, sizeof(to)); - to.sin_family = AF_INET; - to.sin_addr = dst_addr; - tolen = sizeof(to); - - sent = sendto(fd, query_buf, msg_size, MSG_DONTWAIT, - (struct sockaddr *)&to, tolen); - if (sent != (ssize_t) msg_size) { - char dst_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - if (sent < 0) { - zlog_warn("Send IGMPv3 query failed due to %s on %s: group=%s msg_size=%zd: errno=%d: %s", - dst_str, ifname, group_str, msg_size, errno, safe_strerror(errno)); - } - else { - zlog_warn("Send IGMPv3 query failed due to %s on %s: group=%s msg_size=%zd: sent=%zd", - dst_str, ifname, group_str, msg_size, sent); - } - return; - } - - /* - s_flag sanity test: s_flag must be set for general queries - - RFC 3376: 6.6.1. Timer Updates - - When a router sends or receives a query with a clear Suppress - Router-Side Processing flag, it must update its timers to reflect - the correct timeout values for the group or sources being queried. - - General queries don't trigger timer update. - */ - if (!s_flag) { - /* general query? */ - if (PIM_INADDR_IS_ANY(group_addr)) { - char dst_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - zlog_warn("%s: to %s on %s: group=%s sources=%d: s_flag is clear for general query!", - __PRETTY_FUNCTION__, - dst_str, ifname, group_str, num_sources); - } - } + ssize_t msg_size; + uint8_t max_resp_code; + uint8_t qqic; + ssize_t sent; + struct sockaddr_in to; + socklen_t tolen; + uint16_t checksum; + + zassert(num_sources >= 0); + + msg_size = IGMP_V3_SOURCES_OFFSET + (num_sources << 2); + if (msg_size > query_buf_size) { + zlog_err( + "%s %s: unable to send: msg_size=%zd larger than query_buf_size=%d", + __FILE__, __PRETTY_FUNCTION__, msg_size, + query_buf_size); + return; + } + + s_flag = PIM_FORCE_BOOLEAN(s_flag); + zassert((s_flag == 0) || (s_flag == 1)); + + max_resp_code = igmp_msg_encode16to8(query_max_response_time_dsec); + qqic = igmp_msg_encode16to8(querier_query_interval); + + /* + RFC 3376: 4.1.6. QRV (Querier's Robustness Variable) + + If non-zero, the QRV field contains the [Robustness Variable] + value used by the querier, i.e., the sender of the Query. If the + querier's [Robustness Variable] exceeds 7, the maximum value of + the QRV field, the QRV is set to zero. + */ + if (querier_robustness_variable > 7) { + querier_robustness_variable = 0; + } + + query_buf[0] = PIM_IGMP_MEMBERSHIP_QUERY; + query_buf[1] = max_resp_code; + *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = + 0; /* for computing checksum */ + memcpy(query_buf + 4, &group_addr, sizeof(struct in_addr)); + + query_buf[8] = (s_flag << 3) | querier_robustness_variable; + query_buf[9] = qqic; + *(uint16_t *)(query_buf + IGMP_V3_NUMSOURCES_OFFSET) = + htons(num_sources); + + checksum = in_cksum(query_buf, msg_size); + *(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum; + + if (PIM_DEBUG_IGMP_PACKETS) { + char dst_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); + pim_inet4_dump("", group_addr, group_str, + sizeof(group_str)); + zlog_debug( + "Send IGMPv3 query to %s on %s for group %s, sources=%d msg_size=%zd s_flag=%x QRV=%u QQI=%u QQIC=%02x", + dst_str, ifname, group_str, num_sources, msg_size, + s_flag, querier_robustness_variable, + querier_query_interval, qqic); + } + + memset(&to, 0, sizeof(to)); + to.sin_family = AF_INET; + to.sin_addr = dst_addr; + tolen = sizeof(to); + + sent = sendto(fd, query_buf, msg_size, MSG_DONTWAIT, + (struct sockaddr *)&to, tolen); + if (sent != (ssize_t)msg_size) { + char dst_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", dst_addr, dst_str, sizeof(dst_str)); + pim_inet4_dump("", group_addr, group_str, + sizeof(group_str)); + if (sent < 0) { + zlog_warn( + "Send IGMPv3 query failed due to %s on %s: group=%s msg_size=%zd: errno=%d: %s", + dst_str, ifname, group_str, msg_size, errno, + safe_strerror(errno)); + } else { + zlog_warn( + "Send IGMPv3 query failed due to %s on %s: group=%s msg_size=%zd: sent=%zd", + dst_str, ifname, group_str, msg_size, sent); + } + return; + } + + /* + s_flag sanity test: s_flag must be set for general queries + + RFC 3376: 6.6.1. Timer Updates + + When a router sends or receives a query with a clear Suppress + Router-Side Processing flag, it must update its timers to reflect + the correct timeout values for the group or sources being queried. + + General queries don't trigger timer update. + */ + if (!s_flag) { + /* general query? */ + if (PIM_INADDR_IS_ANY(group_addr)) { + char dst_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", dst_addr, dst_str, + sizeof(dst_str)); + pim_inet4_dump("", group_addr, group_str, + sizeof(group_str)); + zlog_warn( + "%s: to %s on %s: group=%s sources=%d: s_flag is clear for general query!", + __PRETTY_FUNCTION__, dst_str, ifname, group_str, + num_sources); + } + } } -void -igmp_v3_recv_query (struct igmp_sock *igmp, const char *from_str, char *igmp_msg) +void igmp_v3_recv_query(struct igmp_sock *igmp, const char *from_str, + char *igmp_msg) { - struct interface *ifp; - struct pim_interface *pim_ifp; - struct in_addr group_addr; - uint8_t resv_s_qrv = 0; - uint8_t s_flag = 0; - uint8_t qrv = 0; - int i; - - memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); - ifp = igmp->interface; - pim_ifp = ifp->info; - - /* - * RFC 3376: 4.1.6. QRV (Querier's Robustness Variable) - * - * Routers adopt the QRV value from the most recently received Query - * as their own [Robustness Variable] value, unless that most - * recently received QRV was zero, in which case the receivers use - * the default [Robustness Variable] value specified in section 8.1 - * or a statically configured value. - */ - resv_s_qrv = igmp_msg[8]; - qrv = 7 & resv_s_qrv; - igmp->querier_robustness_variable = qrv ? qrv : pim_ifp->igmp_default_robustness_variable; - - /* - * RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code) - * - * Multicast routers that are not the current querier adopt the QQI - * value from the most recently received Query as their own [Query - * Interval] value, unless that most recently received QQI was zero, - * in which case the receiving routers use the default. - */ - if (igmp->t_other_querier_timer) { - /* other querier present */ - uint8_t qqic; - uint16_t qqi; - qqic = igmp_msg[9]; - qqi = igmp_msg_decode8to16(qqic); - igmp->querier_query_interval = qqi ? qqi : pim_ifp->igmp_default_query_interval; - - if (PIM_DEBUG_IGMP_TRACE) { - char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str)); - zlog_debug("Querier %s new query interval is %s QQI=%u sec (recv QQIC=%02x from %s)", - ifaddr_str, - qqi ? "recv-non-default" : "default", - igmp->querier_query_interval, - qqic, - from_str); - } - } - - /* - * RFC 3376: 6.6.1. Timer Updates - * - * When a router sends or receives a query with a clear Suppress - * Router-Side Processing flag, it must update its timers to reflect - * the correct timeout values for the group or sources being queried. - * - * General queries don't trigger timer update. - */ - s_flag = (1 << 3) & resv_s_qrv; - - if (!s_flag) { - /* s_flag is clear */ - - if (PIM_INADDR_IS_ANY(group_addr)) { - /* this is a general query */ - /* log that general query should have the s_flag set */ - zlog_warn("General IGMP query v3 from %s on %s: Suppress Router-Side Processing flag is clear", - from_str, ifp->name); - } else { - struct igmp_group *group; - - /* this is a non-general query: perform timer updates */ - - group = find_group_by_addr(igmp, group_addr); - if (group) { - int recv_num_sources = ntohs(*(uint16_t *)(igmp_msg + IGMP_V3_NUMSOURCES_OFFSET)); - - /* - * RFC 3376: 6.6.1. Timer Updates - * Query Q(G,A): Source Timer for sources in A are lowered to LMQT - * Query Q(G): Group Timer is lowered to LMQT - */ - if (recv_num_sources < 1) { - /* Query Q(G): Group Timer is lowered to LMQT */ - - igmp_group_timer_lower_to_lmqt(group); - } else { - /* Query Q(G,A): Source Timer for sources in A are lowered to LMQT */ - - /* Scan sources in query and lower their timers to LMQT */ - struct in_addr *sources = (struct in_addr *)(igmp_msg + IGMP_V3_SOURCES_OFFSET); - for (i = 0; i < recv_num_sources; ++i) { - struct in_addr src_addr; - struct igmp_source *src; - memcpy(&src_addr, sources + i, sizeof(struct in_addr)); - src = igmp_find_source_by_addr(group, src_addr); - if (src) { - igmp_source_timer_lower_to_lmqt(src); - } - } - } - } else { - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - zlog_warn("IGMP query v3 from %s on %s: could not find group %s for timer update", - from_str, ifp->name, group_str); - } - } - } /* s_flag is clear: timer updates */ + struct interface *ifp; + struct pim_interface *pim_ifp; + struct in_addr group_addr; + uint8_t resv_s_qrv = 0; + uint8_t s_flag = 0; + uint8_t qrv = 0; + int i; + + memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); + ifp = igmp->interface; + pim_ifp = ifp->info; + + /* + * RFC 3376: 4.1.6. QRV (Querier's Robustness Variable) + * + * Routers adopt the QRV value from the most recently received Query + * as their own [Robustness Variable] value, unless that most + * recently received QRV was zero, in which case the receivers use + * the default [Robustness Variable] value specified in section 8.1 + * or a statically configured value. + */ + resv_s_qrv = igmp_msg[8]; + qrv = 7 & resv_s_qrv; + igmp->querier_robustness_variable = + qrv ? qrv : pim_ifp->igmp_default_robustness_variable; + + /* + * RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code) + * + * Multicast routers that are not the current querier adopt the QQI + * value from the most recently received Query as their own [Query + * Interval] value, unless that most recently received QQI was zero, + * in which case the receiving routers use the default. + */ + if (igmp->t_other_querier_timer) { + /* other querier present */ + uint8_t qqic; + uint16_t qqi; + qqic = igmp_msg[9]; + qqi = igmp_msg_decode8to16(qqic); + igmp->querier_query_interval = + qqi ? qqi : pim_ifp->igmp_default_query_interval; + + if (PIM_DEBUG_IGMP_TRACE) { + char ifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", igmp->ifaddr, ifaddr_str, + sizeof(ifaddr_str)); + zlog_debug( + "Querier %s new query interval is %s QQI=%u sec (recv QQIC=%02x from %s)", + ifaddr_str, + qqi ? "recv-non-default" : "default", + igmp->querier_query_interval, qqic, from_str); + } + } + + /* + * RFC 3376: 6.6.1. Timer Updates + * + * When a router sends or receives a query with a clear Suppress + * Router-Side Processing flag, it must update its timers to reflect + * the correct timeout values for the group or sources being queried. + * + * General queries don't trigger timer update. + */ + s_flag = (1 << 3) & resv_s_qrv; + + if (!s_flag) { + /* s_flag is clear */ + + if (PIM_INADDR_IS_ANY(group_addr)) { + /* this is a general query */ + /* log that general query should have the s_flag set */ + zlog_warn( + "General IGMP query v3 from %s on %s: Suppress Router-Side Processing flag is clear", + from_str, ifp->name); + } else { + struct igmp_group *group; + + /* this is a non-general query: perform timer updates */ + + group = find_group_by_addr(igmp, group_addr); + if (group) { + int recv_num_sources = ntohs(*( + uint16_t + *)(igmp_msg + + IGMP_V3_NUMSOURCES_OFFSET)); + + /* + * RFC 3376: 6.6.1. Timer Updates + * Query Q(G,A): Source Timer for sources in A + * are lowered to LMQT + * Query Q(G): Group Timer is lowered to LMQT + */ + if (recv_num_sources < 1) { + /* Query Q(G): Group Timer is lowered to + * LMQT */ + + igmp_group_timer_lower_to_lmqt(group); + } else { + /* Query Q(G,A): Source Timer for + * sources in A are lowered to LMQT */ + + /* Scan sources in query and lower their + * timers to LMQT */ + struct in_addr *sources = + (struct in_addr + *)(igmp_msg + + IGMP_V3_SOURCES_OFFSET); + for (i = 0; i < recv_num_sources; ++i) { + struct in_addr src_addr; + struct igmp_source *src; + memcpy(&src_addr, sources + i, + sizeof(struct in_addr)); + src = igmp_find_source_by_addr( + group, src_addr); + if (src) { + igmp_source_timer_lower_to_lmqt( + src); + } + } + } + } else { + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group_addr, + group_str, sizeof(group_str)); + zlog_warn( + "IGMP query v3 from %s on %s: could not find group %s for timer update", + from_str, ifp->name, group_str); + } + } + } /* s_flag is clear: timer updates */ } -int -igmp_v3_recv_report (struct igmp_sock *igmp, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len) +int igmp_v3_recv_report(struct igmp_sock *igmp, struct in_addr from, + const char *from_str, char *igmp_msg, int igmp_msg_len) { - uint16_t recv_checksum; - uint16_t checksum; - int num_groups; - uint8_t *group_record; - uint8_t *report_pastend = (uint8_t *) igmp_msg + igmp_msg_len; - struct interface *ifp = igmp->interface; - int i; - int local_ncb = 0; - - if (igmp_msg_len < IGMP_V3_MSG_MIN_SIZE) { - zlog_warn("Recv IGMP report v3 from %s on %s: size=%d shorter than minimum=%d", - from_str, ifp->name, igmp_msg_len, IGMP_V3_MSG_MIN_SIZE); - return -1; - } - - recv_checksum = *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET); - - /* for computing checksum */ - *(uint16_t *) (igmp_msg + IGMP_CHECKSUM_OFFSET) = 0; - - checksum = in_cksum(igmp_msg, igmp_msg_len); - if (checksum != recv_checksum) { - zlog_warn("Recv IGMP report v3 from %s on %s: checksum mismatch: received=%x computed=%x", - from_str, ifp->name, recv_checksum, checksum); - return -1; - } - - num_groups = ntohs(*(uint16_t *) (igmp_msg + IGMP_V3_REPORT_NUMGROUPS_OFFSET)); - if (num_groups < 1) { - zlog_warn("Recv IGMP report v3 from %s on %s: missing group records", - from_str, ifp->name); - return -1; - } - - if (PIM_DEBUG_IGMP_PACKETS) { - zlog_debug("Recv IGMP report v3 from %s on %s: size=%d checksum=%x groups=%d", - from_str, ifp->name, igmp_msg_len, checksum, num_groups); - } - - group_record = (uint8_t *) igmp_msg + IGMP_V3_REPORT_GROUPPRECORD_OFFSET; - - /* Scan groups */ - for (i = 0; i < num_groups; ++i) { - struct in_addr rec_group; - uint8_t *sources; - uint8_t *src; - int rec_type; - int rec_auxdatalen; - int rec_num_sources; - int j; - struct prefix lncb; - struct prefix g; - - if ((group_record + IGMP_V3_GROUP_RECORD_MIN_SIZE) > report_pastend) { - zlog_warn("Recv IGMP report v3 from %s on %s: group record beyond report end", - from_str, ifp->name); - return -1; - } - - rec_type = group_record[IGMP_V3_GROUP_RECORD_TYPE_OFFSET]; - rec_auxdatalen = group_record[IGMP_V3_GROUP_RECORD_AUXDATALEN_OFFSET]; - rec_num_sources = ntohs(* (uint16_t *) (group_record + IGMP_V3_GROUP_RECORD_NUMSOURCES_OFFSET)); - - memcpy(&rec_group, group_record + IGMP_V3_GROUP_RECORD_GROUP_OFFSET, sizeof(struct in_addr)); - - if (PIM_DEBUG_IGMP_PACKETS) { - zlog_debug("Recv IGMP report v3 from %s on %s: record=%d type=%d auxdatalen=%d sources=%d group=%s", - from_str, ifp->name, i, rec_type, rec_auxdatalen, rec_num_sources, inet_ntoa(rec_group)); - } - - /* Scan sources */ - - sources = group_record + IGMP_V3_GROUP_RECORD_SOURCE_OFFSET; - - for (j = 0, src = sources; j < rec_num_sources; ++j, src += 4) { - - if ((src + 4) > report_pastend) { - zlog_warn("Recv IGMP report v3 from %s on %s: group source beyond report end", - from_str, ifp->name); - return -1; - } - - if (PIM_DEBUG_IGMP_PACKETS) { - char src_str[200]; - - if (!inet_ntop(AF_INET, src, src_str , sizeof(src_str))) - sprintf(src_str, ""); - - zlog_debug("Recv IGMP report v3 from %s on %s: record=%d group=%s source=%s", - from_str, ifp->name, i, inet_ntoa(rec_group), src_str); - } - } /* for (sources) */ - - - lncb.family = AF_INET; - lncb.u.prefix4.s_addr = 0x000000E0; - lncb.prefixlen = 24; - - g.family = AF_INET; - g.u.prefix4 = rec_group; - g.prefixlen = 32; - /* - * If we receive a igmp report with the group in 224.0.0.0/24 - * then we should ignore it - */ - if (prefix_match(&lncb, &g)) - local_ncb = 1; - - if (!local_ncb) - switch (rec_type) { - case IGMP_GRP_REC_TYPE_MODE_IS_INCLUDE: - igmpv3_report_isin(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); - break; - case IGMP_GRP_REC_TYPE_MODE_IS_EXCLUDE: - igmpv3_report_isex(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources, 0); - break; - case IGMP_GRP_REC_TYPE_CHANGE_TO_INCLUDE_MODE: - igmpv3_report_toin(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); - break; - case IGMP_GRP_REC_TYPE_CHANGE_TO_EXCLUDE_MODE: - igmpv3_report_toex(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); - break; - case IGMP_GRP_REC_TYPE_ALLOW_NEW_SOURCES: - igmpv3_report_allow(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); - break; - case IGMP_GRP_REC_TYPE_BLOCK_OLD_SOURCES: - igmpv3_report_block(igmp, from, rec_group, rec_num_sources, (struct in_addr *) sources); - break; - default: - zlog_warn("Recv IGMP report v3 from %s on %s: unknown record type: type=%d", - from_str, ifp->name, rec_type); - } - - group_record += 8 + (rec_num_sources << 2) + (rec_auxdatalen << 2); - local_ncb = 0; - - } /* for (group records) */ - - return 0; + uint16_t recv_checksum; + uint16_t checksum; + int num_groups; + uint8_t *group_record; + uint8_t *report_pastend = (uint8_t *)igmp_msg + igmp_msg_len; + struct interface *ifp = igmp->interface; + int i; + int local_ncb = 0; + + if (igmp_msg_len < IGMP_V3_MSG_MIN_SIZE) { + zlog_warn( + "Recv IGMP report v3 from %s on %s: size=%d shorter than minimum=%d", + from_str, ifp->name, igmp_msg_len, + IGMP_V3_MSG_MIN_SIZE); + return -1; + } + + recv_checksum = *(uint16_t *)(igmp_msg + IGMP_CHECKSUM_OFFSET); + + /* for computing checksum */ + *(uint16_t *)(igmp_msg + IGMP_CHECKSUM_OFFSET) = 0; + + checksum = in_cksum(igmp_msg, igmp_msg_len); + if (checksum != recv_checksum) { + zlog_warn( + "Recv IGMP report v3 from %s on %s: checksum mismatch: received=%x computed=%x", + from_str, ifp->name, recv_checksum, checksum); + return -1; + } + + num_groups = ntohs( + *(uint16_t *)(igmp_msg + IGMP_V3_REPORT_NUMGROUPS_OFFSET)); + if (num_groups < 1) { + zlog_warn( + "Recv IGMP report v3 from %s on %s: missing group records", + from_str, ifp->name); + return -1; + } + + if (PIM_DEBUG_IGMP_PACKETS) { + zlog_debug( + "Recv IGMP report v3 from %s on %s: size=%d checksum=%x groups=%d", + from_str, ifp->name, igmp_msg_len, checksum, + num_groups); + } + + group_record = (uint8_t *)igmp_msg + IGMP_V3_REPORT_GROUPPRECORD_OFFSET; + + /* Scan groups */ + for (i = 0; i < num_groups; ++i) { + struct in_addr rec_group; + uint8_t *sources; + uint8_t *src; + int rec_type; + int rec_auxdatalen; + int rec_num_sources; + int j; + struct prefix lncb; + struct prefix g; + + if ((group_record + IGMP_V3_GROUP_RECORD_MIN_SIZE) + > report_pastend) { + zlog_warn( + "Recv IGMP report v3 from %s on %s: group record beyond report end", + from_str, ifp->name); + return -1; + } + + rec_type = group_record[IGMP_V3_GROUP_RECORD_TYPE_OFFSET]; + rec_auxdatalen = + group_record[IGMP_V3_GROUP_RECORD_AUXDATALEN_OFFSET]; + rec_num_sources = ntohs(*( + uint16_t *)(group_record + + IGMP_V3_GROUP_RECORD_NUMSOURCES_OFFSET)); + + memcpy(&rec_group, + group_record + IGMP_V3_GROUP_RECORD_GROUP_OFFSET, + sizeof(struct in_addr)); + + if (PIM_DEBUG_IGMP_PACKETS) { + zlog_debug( + "Recv IGMP report v3 from %s on %s: record=%d type=%d auxdatalen=%d sources=%d group=%s", + from_str, ifp->name, i, rec_type, + rec_auxdatalen, rec_num_sources, + inet_ntoa(rec_group)); + } + + /* Scan sources */ + + sources = group_record + IGMP_V3_GROUP_RECORD_SOURCE_OFFSET; + + for (j = 0, src = sources; j < rec_num_sources; ++j, src += 4) { + + if ((src + 4) > report_pastend) { + zlog_warn( + "Recv IGMP report v3 from %s on %s: group source beyond report end", + from_str, ifp->name); + return -1; + } + + if (PIM_DEBUG_IGMP_PACKETS) { + char src_str[200]; + + if (!inet_ntop(AF_INET, src, src_str, + sizeof(src_str))) + sprintf(src_str, ""); + + zlog_debug( + "Recv IGMP report v3 from %s on %s: record=%d group=%s source=%s", + from_str, ifp->name, i, + inet_ntoa(rec_group), src_str); + } + } /* for (sources) */ + + + lncb.family = AF_INET; + lncb.u.prefix4.s_addr = 0x000000E0; + lncb.prefixlen = 24; + + g.family = AF_INET; + g.u.prefix4 = rec_group; + g.prefixlen = 32; + /* + * If we receive a igmp report with the group in 224.0.0.0/24 + * then we should ignore it + */ + if (prefix_match(&lncb, &g)) + local_ncb = 1; + + if (!local_ncb) + switch (rec_type) { + case IGMP_GRP_REC_TYPE_MODE_IS_INCLUDE: + igmpv3_report_isin(igmp, from, rec_group, + rec_num_sources, + (struct in_addr *)sources); + break; + case IGMP_GRP_REC_TYPE_MODE_IS_EXCLUDE: + igmpv3_report_isex( + igmp, from, rec_group, rec_num_sources, + (struct in_addr *)sources, 0); + break; + case IGMP_GRP_REC_TYPE_CHANGE_TO_INCLUDE_MODE: + igmpv3_report_toin(igmp, from, rec_group, + rec_num_sources, + (struct in_addr *)sources); + break; + case IGMP_GRP_REC_TYPE_CHANGE_TO_EXCLUDE_MODE: + igmpv3_report_toex(igmp, from, rec_group, + rec_num_sources, + (struct in_addr *)sources); + break; + case IGMP_GRP_REC_TYPE_ALLOW_NEW_SOURCES: + igmpv3_report_allow(igmp, from, rec_group, + rec_num_sources, + (struct in_addr *)sources); + break; + case IGMP_GRP_REC_TYPE_BLOCK_OLD_SOURCES: + igmpv3_report_block(igmp, from, rec_group, + rec_num_sources, + (struct in_addr *)sources); + break; + default: + zlog_warn( + "Recv IGMP report v3 from %s on %s: unknown record type: type=%d", + from_str, ifp->name, rec_type); + } + + group_record += + 8 + (rec_num_sources << 2) + (rec_auxdatalen << 2); + local_ncb = 0; + + } /* for (group records) */ + + return 0; } diff --git a/pimd/pim_igmpv3.h b/pimd/pim_igmpv3.h index 99f7b84b8..6abaef6e2 100644 --- a/pimd/pim_igmpv3.h +++ b/pimd/pim_igmpv3.h @@ -52,8 +52,7 @@ #define PIM_IGMP_OHPI_DSEC(qrv,qqi,qri_dsec) ((qrv) * (10 * (qqi)) + (qri_dsec)) void igmp_group_reset_gmi(struct igmp_group *group); -void igmp_source_reset_gmi(struct igmp_sock *igmp, - struct igmp_group *group, +void igmp_source_reset_gmi(struct igmp_sock *igmp, struct igmp_group *group, struct igmp_source *source); void igmp_source_free(struct igmp_source *source); @@ -61,24 +60,23 @@ void igmp_source_delete(struct igmp_source *source); void igmp_source_delete_expired(struct list *source_list); void igmpv3_report_isin(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources); + struct in_addr group_addr, int num_sources, + struct in_addr *sources); void igmpv3_report_isex(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources, - int from_igmp_v2_report); + struct in_addr group_addr, int num_sources, + struct in_addr *sources, int from_igmp_v2_report); void igmpv3_report_toin(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources); + struct in_addr group_addr, int num_sources, + struct in_addr *sources); void igmpv3_report_toex(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources); + struct in_addr group_addr, int num_sources, + struct in_addr *sources); void igmpv3_report_allow(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources); + struct in_addr group_addr, int num_sources, + struct in_addr *sources); void igmpv3_report_block(struct igmp_sock *igmp, struct in_addr from, - struct in_addr group_addr, - int num_sources, struct in_addr *sources); + struct in_addr group_addr, int num_sources, + struct in_addr *sources); void igmp_group_timer_lower_to_lmqt(struct igmp_group *group); void igmp_source_timer_lower_to_lmqt(struct igmp_source *source); @@ -86,24 +84,17 @@ void igmp_source_timer_lower_to_lmqt(struct igmp_source *source); struct igmp_source *igmp_find_source_by_addr(struct igmp_group *group, struct in_addr src_addr); -void igmp_v3_send_query (struct igmp_group *group, - int fd, - const char *ifname, - char *query_buf, - int query_buf_size, - int num_sources, - struct in_addr dst_addr, - struct in_addr group_addr, - int query_max_response_time_dsec, - uint8_t s_flag, - uint8_t querier_robustness_variable, - uint16_t querier_query_interval); - -void igmp_v3_recv_query (struct igmp_sock *igmp, const char *from_str, - char *igmp_msg); - -int igmp_v3_recv_report (struct igmp_sock *igmp, - struct in_addr from, const char *from_str, - char *igmp_msg, int igmp_msg_len); +void igmp_v3_send_query(struct igmp_group *group, int fd, const char *ifname, + char *query_buf, int query_buf_size, int num_sources, + struct in_addr dst_addr, struct in_addr group_addr, + int query_max_response_time_dsec, uint8_t s_flag, + uint8_t querier_robustness_variable, + uint16_t querier_query_interval); + +void igmp_v3_recv_query(struct igmp_sock *igmp, const char *from_str, + char *igmp_msg); + +int igmp_v3_recv_report(struct igmp_sock *igmp, struct in_addr from, + const char *from_str, char *igmp_msg, int igmp_msg_len); #endif /* PIM_IGMPV3_H */ diff --git a/pimd/pim_int.c b/pimd/pim_int.c index 577bf15c6..377839906 100644 --- a/pimd/pim_int.c +++ b/pimd/pim_int.c @@ -27,18 +27,18 @@ uint32_t pim_read_uint32_host(const uint8_t *buf) { - uint32_t val; - memcpy(&val, buf, sizeof(val)); - /* val is in netorder */ - val = ntohl(val); - /* val is in hostorder */ - return val; + uint32_t val; + memcpy(&val, buf, sizeof(val)); + /* val is in netorder */ + val = ntohl(val); + /* val is in hostorder */ + return val; } void pim_write_uint32(uint8_t *buf, uint32_t val_host) { - /* val_host is in host order */ - val_host = htonl(val_host); - /* val_host is in netorder */ - memcpy(buf, &val_host, sizeof(val_host)); + /* val_host is in host order */ + val_host = htonl(val_host); + /* val_host is in netorder */ + memcpy(buf, &val_host, sizeof(val_host)); } diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 35deecfd8..9bc5c2d9c 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -39,301 +39,295 @@ #include "pim_rp.h" #include "pim_jp_agg.h" -static void -on_trace (const char *label, - struct interface *ifp, struct in_addr src) +static void on_trace(const char *label, struct interface *ifp, + struct in_addr src) { - if (PIM_DEBUG_PIM_TRACE) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src, src_str, sizeof(src_str)); - zlog_debug("%s: from %s on %s", - label, src_str, ifp->name); - } + if (PIM_DEBUG_PIM_TRACE) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src, src_str, sizeof(src_str)); + zlog_debug("%s: from %s on %s", label, src_str, ifp->name); + } } -static void recv_join(struct interface *ifp, - struct pim_neighbor *neigh, - uint16_t holdtime, - struct in_addr upstream, - struct prefix_sg *sg, - uint8_t source_flags) +static void recv_join(struct interface *ifp, struct pim_neighbor *neigh, + uint16_t holdtime, struct in_addr upstream, + struct prefix_sg *sg, uint8_t source_flags) { - struct pim_interface *pim_ifp = NULL; - - if (PIM_DEBUG_PIM_TRACE) { - char up_str[INET_ADDRSTRLEN]; - char neigh_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", upstream, up_str, sizeof(up_str)); - pim_inet4_dump("", neigh->source_addr, neigh_str, sizeof(neigh_str)); - zlog_warn("%s: join (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump (sg), - source_flags & PIM_RPT_BIT_MASK, - source_flags & PIM_WILDCARD_BIT_MASK, - up_str, holdtime, neigh_str, ifp->name); - } - - pim_ifp = ifp->info; - zassert(pim_ifp); - - ++pim_ifp->pim_ifstat_join_recv; - - /* - * If the RPT and WC are set it's a (*,G) - * and the source is the RP - */ - if ((source_flags & PIM_RPT_BIT_MASK) && - (source_flags & PIM_WILDCARD_BIT_MASK)) - { - struct pim_rpf *rp = RP (sg->grp); - - /* - * If the RP sent in the message is not - * our RP for the group, drop the message - */ - if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr) - return; - - sg->src.s_addr = INADDR_ANY; - } - - /* Restart join expiry timer */ - pim_ifchannel_join_add(ifp, neigh->source_addr, upstream, - sg, source_flags, holdtime); - + struct pim_interface *pim_ifp = NULL; + + if (PIM_DEBUG_PIM_TRACE) { + char up_str[INET_ADDRSTRLEN]; + char neigh_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", upstream, up_str, sizeof(up_str)); + pim_inet4_dump("", neigh->source_addr, neigh_str, + sizeof(neigh_str)); + zlog_warn( + "%s: join (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(sg), + source_flags & PIM_RPT_BIT_MASK, + source_flags & PIM_WILDCARD_BIT_MASK, up_str, holdtime, + neigh_str, ifp->name); + } + + pim_ifp = ifp->info; + zassert(pim_ifp); + + ++pim_ifp->pim_ifstat_join_recv; + + /* + * If the RPT and WC are set it's a (*,G) + * and the source is the RP + */ + if ((source_flags & PIM_RPT_BIT_MASK) + && (source_flags & PIM_WILDCARD_BIT_MASK)) { + struct pim_rpf *rp = RP(sg->grp); + + /* + * If the RP sent in the message is not + * our RP for the group, drop the message + */ + if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr) + return; + + sg->src.s_addr = INADDR_ANY; + } + + /* Restart join expiry timer */ + pim_ifchannel_join_add(ifp, neigh->source_addr, upstream, sg, + source_flags, holdtime); } -static void recv_prune(struct interface *ifp, - struct pim_neighbor *neigh, - uint16_t holdtime, - struct in_addr upstream, - struct prefix_sg *sg, - uint8_t source_flags) +static void recv_prune(struct interface *ifp, struct pim_neighbor *neigh, + uint16_t holdtime, struct in_addr upstream, + struct prefix_sg *sg, uint8_t source_flags) { - struct pim_interface *pim_ifp = NULL; - - if (PIM_DEBUG_PIM_TRACE) { - char up_str[INET_ADDRSTRLEN]; - char neigh_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", upstream, up_str, sizeof(up_str)); - pim_inet4_dump("", neigh->source_addr, neigh_str, sizeof(neigh_str)); - zlog_warn("%s: prune (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump (sg), - source_flags & PIM_RPT_BIT_MASK, - source_flags & PIM_WILDCARD_BIT_MASK, - up_str, holdtime, neigh_str, ifp->name); - } - - pim_ifp = ifp->info; - zassert(pim_ifp); - - ++pim_ifp->pim_ifstat_prune_recv; - - if ((source_flags & PIM_RPT_BIT_MASK) && - (source_flags & PIM_WILDCARD_BIT_MASK)) - { - struct pim_rpf *rp = RP (sg->grp); - - // Ignoring Prune *,G's at the moment. - if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr) - return; - - sg->src.s_addr = INADDR_ANY; - } - - pim_ifchannel_prune(ifp, upstream, sg, source_flags, holdtime); - + struct pim_interface *pim_ifp = NULL; + + if (PIM_DEBUG_PIM_TRACE) { + char up_str[INET_ADDRSTRLEN]; + char neigh_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", upstream, up_str, sizeof(up_str)); + pim_inet4_dump("", neigh->source_addr, neigh_str, + sizeof(neigh_str)); + zlog_warn( + "%s: prune (S,G)=%s rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(sg), + source_flags & PIM_RPT_BIT_MASK, + source_flags & PIM_WILDCARD_BIT_MASK, up_str, holdtime, + neigh_str, ifp->name); + } + + pim_ifp = ifp->info; + zassert(pim_ifp); + + ++pim_ifp->pim_ifstat_prune_recv; + + if ((source_flags & PIM_RPT_BIT_MASK) + && (source_flags & PIM_WILDCARD_BIT_MASK)) { + struct pim_rpf *rp = RP(sg->grp); + + // Ignoring Prune *,G's at the moment. + if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr) + return; + + sg->src.s_addr = INADDR_ANY; + } + + pim_ifchannel_prune(ifp, upstream, sg, source_flags, holdtime); } -int pim_joinprune_recv(struct interface *ifp, - struct pim_neighbor *neigh, - struct in_addr src_addr, - uint8_t *tlv_buf, int tlv_buf_size) +int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, + struct in_addr src_addr, uint8_t *tlv_buf, + int tlv_buf_size) { - struct prefix msg_upstream_addr; - uint8_t msg_num_groups; - uint16_t msg_holdtime; - int addr_offset; - uint8_t *buf; - uint8_t *pastend; - int remain; - int group; - - buf = tlv_buf; - pastend = tlv_buf + tlv_buf_size; - - /* - Parse ucast addr - */ - addr_offset = pim_parse_addr_ucast (&msg_upstream_addr, - buf, pastend - buf); - if (addr_offset < 1) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s", - __PRETTY_FUNCTION__, - src_str, ifp->name); - return -1; - } - buf += addr_offset; - - /* - Check upstream address family - */ - if (msg_upstream_addr.family != AF_INET) { - if (PIM_DEBUG_PIM_J_P) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: ignoring join/prune directed to unexpected addr family=%d from %s on %s", - __PRETTY_FUNCTION__, - msg_upstream_addr.family, src_str, ifp->name); - } - return -2; - } - - remain = pastend - buf; - if (remain < 4) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: short join/prune message buffer for group list: size=%d minimum=%d from %s on %s", - __PRETTY_FUNCTION__, - remain, 4, src_str, ifp->name); - return -4; - } - - ++buf; /* skip reserved byte */ - msg_num_groups = *(const uint8_t *) buf; - ++buf; - msg_holdtime = ntohs(*(const uint16_t *) buf); - ++buf; - ++buf; - - if (PIM_DEBUG_PIM_J_P) { - char src_str[INET_ADDRSTRLEN]; - char upstream_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", msg_upstream_addr.u.prefix4, - upstream_str, sizeof(upstream_str)); - zlog_debug ("%s: join/prune upstream=%s groups=%d holdtime=%d from %s on %s", - __PRETTY_FUNCTION__, - upstream_str, msg_num_groups, msg_holdtime, - src_str, ifp->name); - } - - /* Scan groups */ - for (group = 0; group < msg_num_groups; ++group) { - struct prefix_sg sg; - uint8_t msg_source_flags; - uint16_t msg_num_joined_sources; - uint16_t msg_num_pruned_sources; - int source; - struct pim_ifchannel *starg_ch = NULL, *sg_ch = NULL; - uint8_t starg_alone = 0; - - memset (&sg, 0, sizeof (struct prefix_sg)); - addr_offset = pim_parse_addr_group (&sg, - buf, pastend - buf); - if (addr_offset < 1) { - return -5; - } - buf += addr_offset; - - remain = pastend - buf; - if (remain < 4) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: short join/prune buffer for source list: size=%d minimum=%d from %s on %s", - __PRETTY_FUNCTION__, - remain, 4, src_str, ifp->name); - return -6; - } - - msg_num_joined_sources = ntohs(*(const uint16_t *) buf); - buf += 2; - msg_num_pruned_sources = ntohs(*(const uint16_t *) buf); - buf += 2; - - if (PIM_DEBUG_PIM_J_P) { - char src_str[INET_ADDRSTRLEN]; - char upstream_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - pim_inet4_dump("", msg_upstream_addr.u.prefix4, - upstream_str, sizeof(upstream_str)); - pim_inet4_dump("", sg.grp, - group_str, sizeof(group_str)); - zlog_warn("%s: join/prune upstream=%s group=%s/32 join_src=%d prune_src=%d from %s on %s", - __PRETTY_FUNCTION__, - upstream_str, group_str, - msg_num_joined_sources, msg_num_pruned_sources, - src_str, ifp->name); - } - - /* Scan joined sources */ - for (source = 0; source < msg_num_joined_sources; ++source) { - addr_offset = pim_parse_addr_source (&sg, - &msg_source_flags, - buf, pastend - buf); - if (addr_offset < 1) { - return -7; - } - - buf += addr_offset; - - recv_join(ifp, neigh, msg_holdtime, - msg_upstream_addr.u.prefix4, - &sg, - msg_source_flags); - - if (sg.src.s_addr == INADDR_ANY) - { - starg_alone = 1; - starg_ch = pim_ifchannel_find (ifp, &sg); - if (starg_ch) - pim_ifchannel_set_star_g_join_state (starg_ch, 0, msg_source_flags, 1, starg_alone); - } - } - - /* Scan pruned sources */ - for (source = 0; source < msg_num_pruned_sources; ++source) { - addr_offset = pim_parse_addr_source (&sg, - &msg_source_flags, - buf, pastend - buf); - if (addr_offset < 1) { - return -8; - } - - sg_ch = pim_ifchannel_find (ifp, &sg); - - buf += addr_offset; - starg_alone = 0; - recv_prune(ifp, neigh, msg_holdtime, - msg_upstream_addr.u.prefix4, - &sg, - msg_source_flags); - - /* Received SG-RPT Prune delete oif from specific S,G */ - if (starg_ch && sg_ch && (msg_source_flags & PIM_RPT_BIT_MASK) - && !(msg_source_flags & PIM_WILDCARD_BIT_MASK)) - { - struct pim_upstream *up = sg_ch->upstream; - PIM_IF_FLAG_SET_S_G_RPT(sg_ch->flags); - if (up) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: SGRpt flag is set, del inherit oif from up %s", - __PRETTY_FUNCTION__, up->sg_str); - pim_channel_del_oif (up->channel_oil, starg_ch->interface, PIM_OIF_FLAG_PROTO_STAR); - } - } - } - if (starg_ch) - pim_ifchannel_set_star_g_join_state (starg_ch, 1, msg_source_flags, 0, starg_alone); - starg_ch = NULL; - } /* scan groups */ - - return 0; + struct prefix msg_upstream_addr; + uint8_t msg_num_groups; + uint16_t msg_holdtime; + int addr_offset; + uint8_t *buf; + uint8_t *pastend; + int remain; + int group; + + buf = tlv_buf; + pastend = tlv_buf + tlv_buf_size; + + /* + Parse ucast addr + */ + addr_offset = + pim_parse_addr_ucast(&msg_upstream_addr, buf, pastend - buf); + if (addr_offset < 1) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); + zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s", + __PRETTY_FUNCTION__, src_str, ifp->name); + return -1; + } + buf += addr_offset; + + /* + Check upstream address family + */ + if (msg_upstream_addr.family != AF_INET) { + if (PIM_DEBUG_PIM_J_P) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, + sizeof(src_str)); + zlog_warn( + "%s: ignoring join/prune directed to unexpected addr family=%d from %s on %s", + __PRETTY_FUNCTION__, msg_upstream_addr.family, + src_str, ifp->name); + } + return -2; + } + + remain = pastend - buf; + if (remain < 4) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); + zlog_warn( + "%s: short join/prune message buffer for group list: size=%d minimum=%d from %s on %s", + __PRETTY_FUNCTION__, remain, 4, src_str, ifp->name); + return -4; + } + + ++buf; /* skip reserved byte */ + msg_num_groups = *(const uint8_t *)buf; + ++buf; + msg_holdtime = ntohs(*(const uint16_t *)buf); + ++buf; + ++buf; + + if (PIM_DEBUG_PIM_J_P) { + char src_str[INET_ADDRSTRLEN]; + char upstream_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); + pim_inet4_dump("", msg_upstream_addr.u.prefix4, + upstream_str, sizeof(upstream_str)); + zlog_debug( + "%s: join/prune upstream=%s groups=%d holdtime=%d from %s on %s", + __PRETTY_FUNCTION__, upstream_str, msg_num_groups, + msg_holdtime, src_str, ifp->name); + } + + /* Scan groups */ + for (group = 0; group < msg_num_groups; ++group) { + struct prefix_sg sg; + uint8_t msg_source_flags; + uint16_t msg_num_joined_sources; + uint16_t msg_num_pruned_sources; + int source; + struct pim_ifchannel *starg_ch = NULL, *sg_ch = NULL; + uint8_t starg_alone = 0; + + memset(&sg, 0, sizeof(struct prefix_sg)); + addr_offset = pim_parse_addr_group(&sg, buf, pastend - buf); + if (addr_offset < 1) { + return -5; + } + buf += addr_offset; + + remain = pastend - buf; + if (remain < 4) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, + sizeof(src_str)); + zlog_warn( + "%s: short join/prune buffer for source list: size=%d minimum=%d from %s on %s", + __PRETTY_FUNCTION__, remain, 4, src_str, + ifp->name); + return -6; + } + + msg_num_joined_sources = ntohs(*(const uint16_t *)buf); + buf += 2; + msg_num_pruned_sources = ntohs(*(const uint16_t *)buf); + buf += 2; + + if (PIM_DEBUG_PIM_J_P) { + char src_str[INET_ADDRSTRLEN]; + char upstream_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, + sizeof(src_str)); + pim_inet4_dump("", msg_upstream_addr.u.prefix4, + upstream_str, sizeof(upstream_str)); + pim_inet4_dump("", sg.grp, group_str, + sizeof(group_str)); + zlog_warn( + "%s: join/prune upstream=%s group=%s/32 join_src=%d prune_src=%d from %s on %s", + __PRETTY_FUNCTION__, upstream_str, group_str, + msg_num_joined_sources, msg_num_pruned_sources, + src_str, ifp->name); + } + + /* Scan joined sources */ + for (source = 0; source < msg_num_joined_sources; ++source) { + addr_offset = pim_parse_addr_source( + &sg, &msg_source_flags, buf, pastend - buf); + if (addr_offset < 1) { + return -7; + } + + buf += addr_offset; + + recv_join(ifp, neigh, msg_holdtime, + msg_upstream_addr.u.prefix4, &sg, + msg_source_flags); + + if (sg.src.s_addr == INADDR_ANY) { + starg_alone = 1; + starg_ch = pim_ifchannel_find(ifp, &sg); + if (starg_ch) + pim_ifchannel_set_star_g_join_state( + starg_ch, 0, msg_source_flags, + 1, starg_alone); + } + } + + /* Scan pruned sources */ + for (source = 0; source < msg_num_pruned_sources; ++source) { + addr_offset = pim_parse_addr_source( + &sg, &msg_source_flags, buf, pastend - buf); + if (addr_offset < 1) { + return -8; + } + + sg_ch = pim_ifchannel_find(ifp, &sg); + + buf += addr_offset; + starg_alone = 0; + recv_prune(ifp, neigh, msg_holdtime, + msg_upstream_addr.u.prefix4, &sg, + msg_source_flags); + + /* Received SG-RPT Prune delete oif from specific S,G */ + if (starg_ch && sg_ch + && (msg_source_flags & PIM_RPT_BIT_MASK) + && !(msg_source_flags & PIM_WILDCARD_BIT_MASK)) { + struct pim_upstream *up = sg_ch->upstream; + PIM_IF_FLAG_SET_S_G_RPT(sg_ch->flags); + if (up) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: SGRpt flag is set, del inherit oif from up %s", + __PRETTY_FUNCTION__, + up->sg_str); + pim_channel_del_oif( + up->channel_oil, + starg_ch->interface, + PIM_OIF_FLAG_PROTO_STAR); + } + } + } + if (starg_ch) + pim_ifchannel_set_star_g_join_state( + starg_ch, 1, msg_source_flags, 0, starg_alone); + starg_ch = NULL; + } /* scan groups */ + + return 0; } /* @@ -402,177 +396,187 @@ int pim_joinprune_recv(struct interface *ifp, * | Pruned Source Address n (Encoded-Source format) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -int pim_joinprune_send(struct pim_rpf *rpf, - struct list *groups) +int pim_joinprune_send(struct pim_rpf *rpf, struct list *groups) { - struct pim_jp_agg_group *group; - struct pim_interface *pim_ifp = NULL; - struct pim_jp_groups *grp = NULL; - struct pim_jp *msg; - struct listnode *node, *nnode; - uint8_t pim_msg[10000]; - uint8_t *curr_ptr = pim_msg; - bool new_packet = true; - size_t packet_left = 0; - size_t packet_size = 0; - size_t group_size = 0; - - on_trace (__PRETTY_FUNCTION__, rpf->source_nexthop.interface, rpf->rpf_addr.u.prefix4); - - if (rpf->source_nexthop.interface) - pim_ifp = rpf->source_nexthop.interface->info; - else - { - zlog_warn ("%s: RPF interface is not present", __PRETTY_FUNCTION__); - return -1; - } - - if (!pim_ifp) - { - zlog_warn ("%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - rpf->source_nexthop.interface->name); - return -1; - } - - if (PIM_INADDR_IS_ANY(rpf->rpf_addr.u.prefix4)) - { - if (PIM_DEBUG_PIM_J_P) { - char dst_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", rpf->rpf_addr.u.prefix4, dst_str, sizeof(dst_str)); - zlog_debug("%s: upstream=%s is myself on interface %s", - __PRETTY_FUNCTION__, - dst_str, rpf->source_nexthop.interface->name); - } - return 0; - } - - /* - RFC 4601: 4.3.1. Sending Hello Messages - - Thus, if a router needs to send a Join/Prune or Assert message on - an interface on which it has not yet sent a Hello message with the - currently configured IP address, then it MUST immediately send the - relevant Hello message without waiting for the Hello Timer to - expire, followed by the Join/Prune or Assert message. - */ - pim_hello_require(rpf->source_nexthop.interface); - - for (ALL_LIST_ELEMENTS(groups, node, nnode, group)) - { - if (new_packet) - { - msg = (struct pim_jp *)pim_msg; - - memset(msg, 0, sizeof (*msg)); - - pim_msg_addr_encode_ipv4_ucast ((uint8_t *)&msg->addr, rpf->rpf_addr.u.prefix4); - msg->reserved = 0; - msg->holdtime = htons(PIM_JP_HOLDTIME); - - new_packet = false; - - grp = &msg->groups[0]; - curr_ptr = (uint8_t *)grp; - packet_size = sizeof (struct pim_msg_header); - packet_size += sizeof (struct pim_encoded_ipv4_unicast); - packet_size += 4; // reserved (1) + groups (1) + holdtime (2) - - packet_left = rpf->source_nexthop.interface->mtu - 24; - packet_left -= packet_size; - } - if (PIM_DEBUG_PIM_J_P) { - char dst_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", rpf->rpf_addr.u.prefix4, dst_str, sizeof(dst_str)); - pim_inet4_dump("", group->group, grp_str, sizeof(grp_str)); - zlog_debug("%s: sending (G)=%s to upstream=%s on interface %s", - __PRETTY_FUNCTION__, - grp_str, dst_str, rpf->source_nexthop.interface->name); - } - - group_size = pim_msg_get_jp_group_size (group->sources); - if (group_size > packet_left) - { - pim_msg_build_header (pim_msg, packet_size, PIM_MSG_TYPE_JOIN_PRUNE); - if (pim_msg_send(pim_ifp->pim_sock_fd, - pim_ifp->primary_address, - qpim_all_pim_routers_addr, - pim_msg, - packet_size, - rpf->source_nexthop.interface->name)) { - zlog_warn("%s: could not send PIM message on interface %s", - __PRETTY_FUNCTION__, rpf->source_nexthop.interface->name); - } - - msg = (struct pim_jp *)pim_msg; - memset(msg, 0, sizeof (*msg)); - - pim_msg_addr_encode_ipv4_ucast ((uint8_t *)&msg->addr, rpf->rpf_addr.u.prefix4); - msg->reserved = 0; - msg->holdtime = htons(PIM_JP_HOLDTIME); - - new_packet = false; - - grp = &msg->groups[0]; - curr_ptr = (uint8_t *)grp; - packet_size = sizeof (struct pim_msg_header); - packet_size += sizeof (struct pim_encoded_ipv4_unicast); - packet_size += 4; // reserved (1) + groups (1) + holdtime (2) - - packet_left = rpf->source_nexthop.interface->mtu - 24; - packet_left -= packet_size; - } - - msg->num_groups++; - /* - Build PIM message - */ - - curr_ptr += group_size; - packet_left -= group_size; - packet_size += group_size; - pim_msg_build_jp_groups (grp, group, group_size); - - pim_ifp->pim_ifstat_join_send += ntohs(grp->joins); - pim_ifp->pim_ifstat_prune_send += ntohs(grp->prunes); - - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s: interface %s num_joins %u num_prunes %u", __PRETTY_FUNCTION__, - rpf->source_nexthop.interface->name, ntohs(grp->joins), ntohs (grp->prunes)); - - grp = (struct pim_jp_groups *)curr_ptr; - if (packet_left < sizeof (struct pim_jp_groups) || msg->num_groups == 255) - { - pim_msg_build_header (pim_msg, packet_size, PIM_MSG_TYPE_JOIN_PRUNE); - if (pim_msg_send(pim_ifp->pim_sock_fd, - pim_ifp->primary_address, - qpim_all_pim_routers_addr, - pim_msg, - packet_size, - rpf->source_nexthop.interface->name)) { - zlog_warn("%s: could not send PIM message on interface %s", - __PRETTY_FUNCTION__, rpf->source_nexthop.interface->name); - } - - new_packet = true; - } - } - - - if (!new_packet) - { - //msg->num_groups = htons (msg->num_groups); - pim_msg_build_header (pim_msg, packet_size, PIM_MSG_TYPE_JOIN_PRUNE); - if (pim_msg_send(pim_ifp->pim_sock_fd, - pim_ifp->primary_address, - qpim_all_pim_routers_addr, - pim_msg, - packet_size, - rpf->source_nexthop.interface->name)) { - zlog_warn("%s: could not send PIM message on interface %s", - __PRETTY_FUNCTION__, rpf->source_nexthop.interface->name); - } - } - return 0; + struct pim_jp_agg_group *group; + struct pim_interface *pim_ifp = NULL; + struct pim_jp_groups *grp = NULL; + struct pim_jp *msg; + struct listnode *node, *nnode; + uint8_t pim_msg[10000]; + uint8_t *curr_ptr = pim_msg; + bool new_packet = true; + size_t packet_left = 0; + size_t packet_size = 0; + size_t group_size = 0; + + on_trace(__PRETTY_FUNCTION__, rpf->source_nexthop.interface, + rpf->rpf_addr.u.prefix4); + + if (rpf->source_nexthop.interface) + pim_ifp = rpf->source_nexthop.interface->info; + else { + zlog_warn("%s: RPF interface is not present", + __PRETTY_FUNCTION__); + return -1; + } + + if (!pim_ifp) { + zlog_warn("%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, + rpf->source_nexthop.interface->name); + return -1; + } + + if (PIM_INADDR_IS_ANY(rpf->rpf_addr.u.prefix4)) { + if (PIM_DEBUG_PIM_J_P) { + char dst_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", rpf->rpf_addr.u.prefix4, + dst_str, sizeof(dst_str)); + zlog_debug("%s: upstream=%s is myself on interface %s", + __PRETTY_FUNCTION__, dst_str, + rpf->source_nexthop.interface->name); + } + return 0; + } + + /* + RFC 4601: 4.3.1. Sending Hello Messages + + Thus, if a router needs to send a Join/Prune or Assert message on + an interface on which it has not yet sent a Hello message with the + currently configured IP address, then it MUST immediately send the + relevant Hello message without waiting for the Hello Timer to + expire, followed by the Join/Prune or Assert message. + */ + pim_hello_require(rpf->source_nexthop.interface); + + for (ALL_LIST_ELEMENTS(groups, node, nnode, group)) { + if (new_packet) { + msg = (struct pim_jp *)pim_msg; + + memset(msg, 0, sizeof(*msg)); + + pim_msg_addr_encode_ipv4_ucast((uint8_t *)&msg->addr, + rpf->rpf_addr.u.prefix4); + msg->reserved = 0; + msg->holdtime = htons(PIM_JP_HOLDTIME); + + new_packet = false; + + grp = &msg->groups[0]; + curr_ptr = (uint8_t *)grp; + packet_size = sizeof(struct pim_msg_header); + packet_size += sizeof(struct pim_encoded_ipv4_unicast); + packet_size += + 4; // reserved (1) + groups (1) + holdtime (2) + + packet_left = rpf->source_nexthop.interface->mtu - 24; + packet_left -= packet_size; + } + if (PIM_DEBUG_PIM_J_P) { + char dst_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", rpf->rpf_addr.u.prefix4, + dst_str, sizeof(dst_str)); + pim_inet4_dump("", group->group, grp_str, + sizeof(grp_str)); + zlog_debug( + "%s: sending (G)=%s to upstream=%s on interface %s", + __PRETTY_FUNCTION__, grp_str, dst_str, + rpf->source_nexthop.interface->name); + } + + group_size = pim_msg_get_jp_group_size(group->sources); + if (group_size > packet_left) { + pim_msg_build_header(pim_msg, packet_size, + PIM_MSG_TYPE_JOIN_PRUNE); + if (pim_msg_send(pim_ifp->pim_sock_fd, + pim_ifp->primary_address, + qpim_all_pim_routers_addr, pim_msg, + packet_size, + rpf->source_nexthop.interface->name)) { + zlog_warn( + "%s: could not send PIM message on interface %s", + __PRETTY_FUNCTION__, + rpf->source_nexthop.interface->name); + } + + msg = (struct pim_jp *)pim_msg; + memset(msg, 0, sizeof(*msg)); + + pim_msg_addr_encode_ipv4_ucast((uint8_t *)&msg->addr, + rpf->rpf_addr.u.prefix4); + msg->reserved = 0; + msg->holdtime = htons(PIM_JP_HOLDTIME); + + new_packet = false; + + grp = &msg->groups[0]; + curr_ptr = (uint8_t *)grp; + packet_size = sizeof(struct pim_msg_header); + packet_size += sizeof(struct pim_encoded_ipv4_unicast); + packet_size += + 4; // reserved (1) + groups (1) + holdtime (2) + + packet_left = rpf->source_nexthop.interface->mtu - 24; + packet_left -= packet_size; + } + + msg->num_groups++; + /* + Build PIM message + */ + + curr_ptr += group_size; + packet_left -= group_size; + packet_size += group_size; + pim_msg_build_jp_groups(grp, group, group_size); + + pim_ifp->pim_ifstat_join_send += ntohs(grp->joins); + pim_ifp->pim_ifstat_prune_send += ntohs(grp->prunes); + + if (PIM_DEBUG_PIM_TRACE) + zlog_debug( + "%s: interface %s num_joins %u num_prunes %u", + __PRETTY_FUNCTION__, + rpf->source_nexthop.interface->name, + ntohs(grp->joins), ntohs(grp->prunes)); + + grp = (struct pim_jp_groups *)curr_ptr; + if (packet_left < sizeof(struct pim_jp_groups) + || msg->num_groups == 255) { + pim_msg_build_header(pim_msg, packet_size, + PIM_MSG_TYPE_JOIN_PRUNE); + if (pim_msg_send(pim_ifp->pim_sock_fd, + pim_ifp->primary_address, + qpim_all_pim_routers_addr, pim_msg, + packet_size, + rpf->source_nexthop.interface->name)) { + zlog_warn( + "%s: could not send PIM message on interface %s", + __PRETTY_FUNCTION__, + rpf->source_nexthop.interface->name); + } + + new_packet = true; + } + } + + + if (!new_packet) { + // msg->num_groups = htons (msg->num_groups); + pim_msg_build_header(pim_msg, packet_size, + PIM_MSG_TYPE_JOIN_PRUNE); + if (pim_msg_send(pim_ifp->pim_sock_fd, pim_ifp->primary_address, + qpim_all_pim_routers_addr, pim_msg, + packet_size, + rpf->source_nexthop.interface->name)) { + zlog_warn( + "%s: could not send PIM message on interface %s", + __PRETTY_FUNCTION__, + rpf->source_nexthop.interface->name); + } + } + return 0; } diff --git a/pimd/pim_join.h b/pimd/pim_join.h index 6dc1b3e8f..5d28f2ba3 100644 --- a/pimd/pim_join.h +++ b/pimd/pim_join.h @@ -26,12 +26,10 @@ #include "pim_neighbor.h" -int pim_joinprune_recv(struct interface *ifp, - struct pim_neighbor *neigh, - struct in_addr src_addr, - uint8_t *tlv_buf, int tlv_buf_size); +int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, + struct in_addr src_addr, uint8_t *tlv_buf, + int tlv_buf_size); -int pim_joinprune_send(struct pim_rpf *nexthop, - struct list *groups); +int pim_joinprune_send(struct pim_rpf *nexthop, struct list *groups); #endif /* PIM_JOIN_H */ diff --git a/pimd/pim_jp_agg.c b/pimd/pim_jp_agg.c index 25530f40b..16d55d7bf 100644 --- a/pimd/pim_jp_agg.c +++ b/pimd/pim_jp_agg.c @@ -30,65 +30,63 @@ #include "pim_join.h" #include "pim_iface.h" -void -pim_jp_agg_group_list_free (struct pim_jp_agg_group *jag) +void pim_jp_agg_group_list_free(struct pim_jp_agg_group *jag) { - list_delete(jag->sources); + list_delete(jag->sources); - XFREE (MTYPE_PIM_JP_AGG_GROUP, jag); + XFREE(MTYPE_PIM_JP_AGG_GROUP, jag); } -static void -pim_jp_agg_src_free (struct pim_jp_sources *js) +static void pim_jp_agg_src_free(struct pim_jp_sources *js) { - struct pim_upstream *up = js->up; - - /* - * When we are being called here, we know - * that the neighbor is going away start - * the normal j/p timer so that it can - * pick this shit back up when the - * nbr comes back alive - */ - if (up) - join_timer_start(js->up); - XFREE (MTYPE_PIM_JP_AGG_SOURCE, js); + struct pim_upstream *up = js->up; + + /* + * When we are being called here, we know + * that the neighbor is going away start + * the normal j/p timer so that it can + * pick this shit back up when the + * nbr comes back alive + */ + if (up) + join_timer_start(js->up); + XFREE(MTYPE_PIM_JP_AGG_SOURCE, js); } -int -pim_jp_agg_group_list_cmp (void *arg1, void *arg2) +int pim_jp_agg_group_list_cmp(void *arg1, void *arg2) { - const struct pim_jp_agg_group *jag1 = (const struct pim_jp_agg_group *)arg1; - const struct pim_jp_agg_group *jag2 = (const struct pim_jp_agg_group *)arg2; + const struct pim_jp_agg_group *jag1 = + (const struct pim_jp_agg_group *)arg1; + const struct pim_jp_agg_group *jag2 = + (const struct pim_jp_agg_group *)arg2; - if (jag1->group.s_addr < jag2->group.s_addr) - return -1; + if (jag1->group.s_addr < jag2->group.s_addr) + return -1; - if (jag1->group.s_addr > jag2->group.s_addr) - return 1; + if (jag1->group.s_addr > jag2->group.s_addr) + return 1; - return 0; + return 0; } -static int -pim_jp_agg_src_cmp (void *arg1, void *arg2) +static int pim_jp_agg_src_cmp(void *arg1, void *arg2) { - const struct pim_jp_sources *js1 = (const struct pim_jp_sources *)arg1; - const struct pim_jp_sources *js2 = (const struct pim_jp_sources *)arg2; + const struct pim_jp_sources *js1 = (const struct pim_jp_sources *)arg1; + const struct pim_jp_sources *js2 = (const struct pim_jp_sources *)arg2; - if (js1->is_join && !js2->is_join) - return -1; + if (js1->is_join && !js2->is_join) + return -1; - if (!js1->is_join && js2->is_join) - return 1; + if (!js1->is_join && js2->is_join) + return 1; - if ((uint32_t)js1->up->sg.src.s_addr < (uint32_t)js2->up->sg.src.s_addr) - return -1; + if ((uint32_t)js1->up->sg.src.s_addr < (uint32_t)js2->up->sg.src.s_addr) + return -1; - if ((uint32_t)js1->up->sg.src.s_addr > (uint32_t)js2->up->sg.src.s_addr) - return 1; + if ((uint32_t)js1->up->sg.src.s_addr > (uint32_t)js2->up->sg.src.s_addr) + return 1; - return 0; + return 0; } /* @@ -97,119 +95,107 @@ pim_jp_agg_src_cmp (void *arg1, void *arg2) * figuring out where to send prunes * and joins. */ -void -pim_jp_agg_clear_group (struct list *group) +void pim_jp_agg_clear_group(struct list *group) { - struct listnode *gnode, *gnnode; - struct listnode *snode, *snnode; - struct pim_jp_agg_group *jag; - struct pim_jp_sources *js; - - for (ALL_LIST_ELEMENTS(group, gnode, gnnode, jag)) - { - for (ALL_LIST_ELEMENTS(jag->sources, snode, snnode, js)) - { - listnode_delete(jag->sources, js); - js->up = NULL; - XFREE(MTYPE_PIM_JP_AGG_SOURCE, js); - } - jag->sources = NULL; - listnode_delete(group, jag); - XFREE(MTYPE_PIM_JP_AGG_GROUP, jag); - } + struct listnode *gnode, *gnnode; + struct listnode *snode, *snnode; + struct pim_jp_agg_group *jag; + struct pim_jp_sources *js; + + for (ALL_LIST_ELEMENTS(group, gnode, gnnode, jag)) { + for (ALL_LIST_ELEMENTS(jag->sources, snode, snnode, js)) { + listnode_delete(jag->sources, js); + js->up = NULL; + XFREE(MTYPE_PIM_JP_AGG_SOURCE, js); + } + jag->sources = NULL; + listnode_delete(group, jag); + XFREE(MTYPE_PIM_JP_AGG_GROUP, jag); + } } static struct pim_iface_upstream_switch * -pim_jp_agg_get_interface_upstream_switch_list (struct pim_rpf *rpf) +pim_jp_agg_get_interface_upstream_switch_list(struct pim_rpf *rpf) { - struct pim_interface *pim_ifp = rpf->source_nexthop.interface->info; - struct pim_iface_upstream_switch *pius; - struct listnode *node, *nnode; - - /* Old interface is pim disabled */ - if (!pim_ifp) - return NULL; - - for (ALL_LIST_ELEMENTS(pim_ifp->upstream_switch_list, node, nnode, pius)) - { - if (pius->address.s_addr == rpf->rpf_addr.u.prefix4.s_addr) - break; - } - - if (!pius) - { - pius = XCALLOC(MTYPE_PIM_JP_AGG_GROUP, sizeof (struct pim_iface_upstream_switch)); - pius->address.s_addr = rpf->rpf_addr.u.prefix4.s_addr; - pius->us = list_new(); - listnode_add_sort (pim_ifp->upstream_switch_list, pius); - } - - return pius; + struct pim_interface *pim_ifp = rpf->source_nexthop.interface->info; + struct pim_iface_upstream_switch *pius; + struct listnode *node, *nnode; + + /* Old interface is pim disabled */ + if (!pim_ifp) + return NULL; + + for (ALL_LIST_ELEMENTS(pim_ifp->upstream_switch_list, node, nnode, + pius)) { + if (pius->address.s_addr == rpf->rpf_addr.u.prefix4.s_addr) + break; + } + + if (!pius) { + pius = XCALLOC(MTYPE_PIM_JP_AGG_GROUP, + sizeof(struct pim_iface_upstream_switch)); + pius->address.s_addr = rpf->rpf_addr.u.prefix4.s_addr; + pius->us = list_new(); + listnode_add_sort(pim_ifp->upstream_switch_list, pius); + } + + return pius; } -void -pim_jp_agg_remove_group (struct list *group, struct pim_upstream *up) +void pim_jp_agg_remove_group(struct list *group, struct pim_upstream *up) { - struct listnode *node, *nnode; - struct pim_jp_agg_group *jag = NULL; - struct pim_jp_sources *js = NULL; - - for (ALL_LIST_ELEMENTS(group, node, nnode, jag)) - { - if (jag->group.s_addr == up->sg.grp.s_addr) - break; - } - - if (!jag) - return; - - for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) - { - if (js->up == up) - break; - } - - if (js) - { - js->up = NULL; - listnode_delete(jag->sources, js); - XFREE(MTYPE_PIM_JP_AGG_SOURCE, js); - } - - if (jag->sources->count == 0) - { - list_delete(jag->sources); - jag->sources = NULL; - listnode_delete(group, jag); - XFREE(MTYPE_PIM_JP_AGG_GROUP, jag); - } - + struct listnode *node, *nnode; + struct pim_jp_agg_group *jag = NULL; + struct pim_jp_sources *js = NULL; + + for (ALL_LIST_ELEMENTS(group, node, nnode, jag)) { + if (jag->group.s_addr == up->sg.grp.s_addr) + break; + } + + if (!jag) + return; + + for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) { + if (js->up == up) + break; + } + + if (js) { + js->up = NULL; + listnode_delete(jag->sources, js); + XFREE(MTYPE_PIM_JP_AGG_SOURCE, js); + } + + if (jag->sources->count == 0) { + list_delete(jag->sources); + jag->sources = NULL; + listnode_delete(group, jag); + XFREE(MTYPE_PIM_JP_AGG_GROUP, jag); + } } -int -pim_jp_agg_is_in_list (struct list *group, struct pim_upstream *up) +int pim_jp_agg_is_in_list(struct list *group, struct pim_upstream *up) { - struct listnode *node, *nnode; - struct pim_jp_agg_group *jag = NULL; - struct pim_jp_sources *js = NULL; + struct listnode *node, *nnode; + struct pim_jp_agg_group *jag = NULL; + struct pim_jp_sources *js = NULL; - for (ALL_LIST_ELEMENTS (group, node, nnode, jag)) - { - if (jag->group.s_addr == up->sg.grp.s_addr) - break; - } + for (ALL_LIST_ELEMENTS(group, node, nnode, jag)) { + if (jag->group.s_addr == up->sg.grp.s_addr) + break; + } - if (!jag) - return 0; + if (!jag) + return 0; - for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) - { - if (js->up == up) - return 1; - } + for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) { + if (js->up == up) + return 1; + } - return 0; - } + return 0; +} //#define PIM_JP_AGG_DEBUG 1 /* @@ -224,148 +210,137 @@ pim_jp_agg_is_in_list (struct list *group, struct pim_upstream *up) * can be safely compiled out in real * builds */ -void -pim_jp_agg_upstream_verification (struct pim_upstream *up, bool ignore) +void pim_jp_agg_upstream_verification(struct pim_upstream *up, bool ignore) { #ifdef PIM_JP_AGG_DEBUG - struct listnode *node; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - struct pim_interface *pim_ifp = ifp->info; - struct listnode *nnode; - - if (ignore && ifp == up->rpf.source_nexthop.interface) - continue; - - if (pim_ifp) - { - struct pim_neighbor *neigh; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, nnode, neigh)) - { - assert (!pim_jp_agg_is_in_list(neigh->upstream_jp_agg, up)); - } - } - } + struct listnode *node; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + struct pim_interface *pim_ifp = ifp->info; + struct listnode *nnode; + + if (ignore && ifp == up->rpf.source_nexthop.interface) + continue; + + if (pim_ifp) { + struct pim_neighbor *neigh; + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, + nnode, neigh)) { + assert(!pim_jp_agg_is_in_list( + neigh->upstream_jp_agg, up)); + } + } + } #else - return; + return; #endif } -void -pim_jp_agg_add_group (struct list *group, struct pim_upstream *up, bool is_join) +void pim_jp_agg_add_group(struct list *group, struct pim_upstream *up, + bool is_join) { - struct listnode *node, *nnode; - struct pim_jp_agg_group *jag = NULL; - struct pim_jp_sources *js = NULL; - - for (ALL_LIST_ELEMENTS(group, node, nnode, jag)) - { - if (jag->group.s_addr == up->sg.grp.s_addr) - break; - } - - if (!jag) - { - jag = XCALLOC(MTYPE_PIM_JP_AGG_GROUP, sizeof (struct pim_jp_agg_group)); - jag->group.s_addr = up->sg.grp.s_addr; - jag->sources = list_new(); - jag->sources->cmp = pim_jp_agg_src_cmp; - jag->sources->del = (void (*)(void *))pim_jp_agg_src_free; - listnode_add_sort (group, jag); - } - - for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) - { - if (js->up == up) - break; - } - - if (!js) - { - js = XCALLOC(MTYPE_PIM_JP_AGG_SOURCE, sizeof (struct pim_jp_sources)); - js->up = up; - js->is_join = is_join; - listnode_add_sort (jag->sources, js); - } - else - { - if (js->is_join != is_join) - { - listnode_delete(jag->sources, js); - js->is_join = is_join; - listnode_add_sort (jag->sources, js); - } - } + struct listnode *node, *nnode; + struct pim_jp_agg_group *jag = NULL; + struct pim_jp_sources *js = NULL; + + for (ALL_LIST_ELEMENTS(group, node, nnode, jag)) { + if (jag->group.s_addr == up->sg.grp.s_addr) + break; + } + + if (!jag) { + jag = XCALLOC(MTYPE_PIM_JP_AGG_GROUP, + sizeof(struct pim_jp_agg_group)); + jag->group.s_addr = up->sg.grp.s_addr; + jag->sources = list_new(); + jag->sources->cmp = pim_jp_agg_src_cmp; + jag->sources->del = (void (*)(void *))pim_jp_agg_src_free; + listnode_add_sort(group, jag); + } + + for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) { + if (js->up == up) + break; + } + + if (!js) { + js = XCALLOC(MTYPE_PIM_JP_AGG_SOURCE, + sizeof(struct pim_jp_sources)); + js->up = up; + js->is_join = is_join; + listnode_add_sort(jag->sources, js); + } else { + if (js->is_join != is_join) { + listnode_delete(jag->sources, js); + js->is_join = is_join; + listnode_add_sort(jag->sources, js); + } + } } -void -pim_jp_agg_switch_interface (struct pim_rpf *orpf, - struct pim_rpf *nrpf, - struct pim_upstream *up) +void pim_jp_agg_switch_interface(struct pim_rpf *orpf, struct pim_rpf *nrpf, + struct pim_upstream *up) { - struct pim_iface_upstream_switch *opius; - struct pim_iface_upstream_switch *npius; - - opius = pim_jp_agg_get_interface_upstream_switch_list(orpf); - npius = pim_jp_agg_get_interface_upstream_switch_list(nrpf); - - /* - * RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages - * - * Transitions from Joined State - * - * RPF'(S,G) changes not due to an Assert - * - * The upstream (S,G) state machine remains in Joined - * state. Send Join(S,G) to the new upstream neighbor, which is - * the new value of RPF'(S,G). Send Prune(S,G) to the old - * upstream neighbor, which is the old value of RPF'(S,G). Set - * the Join Timer (JT) to expire after t_periodic seconds. - */ - - /* send Prune(S,G) to the old upstream neighbor */ - if (opius) - pim_jp_agg_add_group (opius->us, up, false); - - /* send Join(S,G) to the current upstream neighbor */ - pim_jp_agg_add_group (npius->us, up, true); - + struct pim_iface_upstream_switch *opius; + struct pim_iface_upstream_switch *npius; + + opius = pim_jp_agg_get_interface_upstream_switch_list(orpf); + npius = pim_jp_agg_get_interface_upstream_switch_list(nrpf); + + /* + * RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages + * + * Transitions from Joined State + * + * RPF'(S,G) changes not due to an Assert + * + * The upstream (S,G) state machine remains in Joined + * state. Send Join(S,G) to the new upstream neighbor, which is + * the new value of RPF'(S,G). Send Prune(S,G) to the old + * upstream neighbor, which is the old value of RPF'(S,G). Set + * the Join Timer (JT) to expire after t_periodic seconds. + */ + + /* send Prune(S,G) to the old upstream neighbor */ + if (opius) + pim_jp_agg_add_group(opius->us, up, false); + + /* send Join(S,G) to the current upstream neighbor */ + pim_jp_agg_add_group(npius->us, up, true); } -void -pim_jp_agg_single_upstream_send (struct pim_rpf *rpf, - struct pim_upstream *up, - bool is_join) +void pim_jp_agg_single_upstream_send(struct pim_rpf *rpf, + struct pim_upstream *up, bool is_join) { - static struct list *groups = NULL; - static struct pim_jp_agg_group jag; - static struct pim_jp_sources js; + static struct list *groups = NULL; + static struct pim_jp_agg_group jag; + static struct pim_jp_sources js; - static bool first = true; + static bool first = true; - /* skip JP upstream messages if source is directly connected */ - if (!up || !rpf->source_nexthop.interface || - pim_if_connected_to_source (rpf->source_nexthop.interface, up->sg.src)) - return; + /* skip JP upstream messages if source is directly connected */ + if (!up || !rpf->source_nexthop.interface || pim_if_connected_to_source( + rpf->source_nexthop + .interface, + up->sg.src)) + return; - if (first) - { - groups = list_new(); + if (first) { + groups = list_new(); - jag.sources = list_new(); + jag.sources = list_new(); - listnode_add(groups, &jag); - listnode_add(jag.sources, &js); + listnode_add(groups, &jag); + listnode_add(jag.sources, &js); - first = false; - } + first = false; + } - jag.group.s_addr = up->sg.grp.s_addr; - js.up = up; - js.is_join = is_join; + jag.group.s_addr = up->sg.grp.s_addr; + js.up = up; + js.is_join = is_join; - pim_joinprune_send(rpf, groups); + pim_joinprune_send(rpf, groups); } diff --git a/pimd/pim_jp_agg.h b/pimd/pim_jp_agg.h index c3955f32f..aa21aa981 100644 --- a/pimd/pim_jp_agg.h +++ b/pimd/pim_jp_agg.h @@ -20,35 +20,31 @@ #ifndef __PIM_JP_AGG_H__ #define __PIM_JP_AGG_H__ -struct pim_jp_sources -{ - struct pim_upstream *up; - int is_join; +struct pim_jp_sources { + struct pim_upstream *up; + int is_join; }; -struct pim_jp_agg_group -{ - struct in_addr group; - struct list *sources; +struct pim_jp_agg_group { + struct in_addr group; + struct list *sources; }; -void pim_jp_agg_upstream_verification (struct pim_upstream *up, bool ignore); -int pim_jp_agg_is_in_list (struct list *group, struct pim_upstream *up); +void pim_jp_agg_upstream_verification(struct pim_upstream *up, bool ignore); +int pim_jp_agg_is_in_list(struct list *group, struct pim_upstream *up); -void pim_jp_agg_group_list_free (struct pim_jp_agg_group *jag); -int pim_jp_agg_group_list_cmp (void *arg1, void *arg2); +void pim_jp_agg_group_list_free(struct pim_jp_agg_group *jag); +int pim_jp_agg_group_list_cmp(void *arg1, void *arg2); -void pim_jp_agg_clear_group (struct list *group); -void pim_jp_agg_remove_group (struct list *group, struct pim_upstream *up); +void pim_jp_agg_clear_group(struct list *group); +void pim_jp_agg_remove_group(struct list *group, struct pim_upstream *up); -void pim_jp_agg_add_group (struct list *group, - struct pim_upstream *up, bool is_join); +void pim_jp_agg_add_group(struct list *group, struct pim_upstream *up, + bool is_join); -void pim_jp_agg_switch_interface (struct pim_rpf *orpf, - struct pim_rpf *nrpf, - struct pim_upstream *up); +void pim_jp_agg_switch_interface(struct pim_rpf *orpf, struct pim_rpf *nrpf, + struct pim_upstream *up); -void pim_jp_agg_single_upstream_send (struct pim_rpf *rpf, - struct pim_upstream *up, - bool is_join); +void pim_jp_agg_single_upstream_send(struct pim_rpf *rpf, + struct pim_upstream *up, bool is_join); #endif diff --git a/pimd/pim_macro.c b/pimd/pim_macro.c index 1f3b29554..13f4240db 100644 --- a/pimd/pim_macro.c +++ b/pimd/pim_macro.c @@ -39,20 +39,19 @@ */ static int downstream_jpstate_isjoined(const struct pim_ifchannel *ch) { - switch (ch->ifjoin_state) - { - case PIM_IFJOIN_NOINFO: - case PIM_IFJOIN_PRUNE: - case PIM_IFJOIN_PRUNE_TMP: - case PIM_IFJOIN_PRUNE_PENDING_TMP: - return 0; - break; - case PIM_IFJOIN_JOIN: - case PIM_IFJOIN_PRUNE_PENDING: - return 1; - break; - } - return 0; + switch (ch->ifjoin_state) { + case PIM_IFJOIN_NOINFO: + case PIM_IFJOIN_PRUNE: + case PIM_IFJOIN_PRUNE_TMP: + case PIM_IFJOIN_PRUNE_PENDING_TMP: + return 0; + break; + case PIM_IFJOIN_JOIN: + case PIM_IFJOIN_PRUNE_PENDING: + return 1; + break; + } + return 0; } /* @@ -63,8 +62,8 @@ static int downstream_jpstate_isjoined(const struct pim_ifchannel *ch) */ static int local_receiver_include(const struct pim_ifchannel *ch) { - /* local_receiver_include(S,G,I) ? */ - return ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE; + /* local_receiver_include(S,G,I) ? */ + return ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE; } /* @@ -75,13 +74,13 @@ static int local_receiver_include(const struct pim_ifchannel *ch) joins(S,G) = { all interfaces I such that - DownstreamJPState(S,G,I) is either Join or Prune-Pending } + DownstreamJPState(S,G,I) is either Join or Prune-Pending } DownstreamJPState(S,G,I) is either Join or Prune-Pending ? */ int pim_macro_chisin_joins(const struct pim_ifchannel *ch) { - return downstream_jpstate_isjoined(ch); + return downstream_jpstate_isjoined(ch); } /* @@ -92,16 +91,16 @@ int pim_macro_chisin_joins(const struct pim_ifchannel *ch) lost_assert(S,G) = { all interfaces I such that - lost_assert(S,G,I) == TRUE } + lost_assert(S,G,I) == TRUE } bool lost_assert(S,G,I) { if ( RPF_interface(S) == I ) { - return FALSE + return FALSE } else { - return ( AssertWinner(S,G,I) != NULL AND - AssertWinner(S,G,I) != me AND - (AssertWinnerMetric(S,G,I) is better - than spt_assert_metric(S,I) ) + return ( AssertWinner(S,G,I) != NULL AND + AssertWinner(S,G,I) != me AND + (AssertWinnerMetric(S,G,I) is better + than spt_assert_metric(S,I) ) } } @@ -110,42 +109,40 @@ int pim_macro_chisin_joins(const struct pim_ifchannel *ch) */ int pim_macro_ch_lost_assert(const struct pim_ifchannel *ch) { - struct interface *ifp; - struct pim_interface *pim_ifp; - struct pim_assert_metric spt_assert_metric; - - ifp = ch->interface; - if (!ifp) { - zlog_warn("%s: (S,G)=%s: null interface", - __PRETTY_FUNCTION__, - ch->sg_str); - return 0; /* false */ - } - - /* RPF_interface(S) == I ? */ - if (ch->upstream->rpf.source_nexthop.interface == ifp) - return 0; /* false */ - - pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ifp->name); - return 0; /* false */ - } - - if (PIM_INADDR_IS_ANY(ch->ifassert_winner)) - return 0; /* false */ - - /* AssertWinner(S,G,I) == me ? */ - if (ch->ifassert_winner.s_addr == pim_ifp->primary_address.s_addr) - return 0; /* false */ - - spt_assert_metric = pim_macro_spt_assert_metric(&ch->upstream->rpf, - pim_ifp->primary_address); - - return pim_assert_metric_better(&ch->ifassert_winner_metric, - &spt_assert_metric); + struct interface *ifp; + struct pim_interface *pim_ifp; + struct pim_assert_metric spt_assert_metric; + + ifp = ch->interface; + if (!ifp) { + zlog_warn("%s: (S,G)=%s: null interface", __PRETTY_FUNCTION__, + ch->sg_str); + return 0; /* false */ + } + + /* RPF_interface(S) == I ? */ + if (ch->upstream->rpf.source_nexthop.interface == ifp) + return 0; /* false */ + + pim_ifp = ifp->info; + if (!pim_ifp) { + zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ifp->name); + return 0; /* false */ + } + + if (PIM_INADDR_IS_ANY(ch->ifassert_winner)) + return 0; /* false */ + + /* AssertWinner(S,G,I) == me ? */ + if (ch->ifassert_winner.s_addr == pim_ifp->primary_address.s_addr) + return 0; /* false */ + + spt_assert_metric = pim_macro_spt_assert_metric( + &ch->upstream->rpf, pim_ifp->primary_address); + + return pim_assert_metric_better(&ch->ifassert_winner_metric, + &spt_assert_metric); } /* @@ -153,47 +150,44 @@ int pim_macro_ch_lost_assert(const struct pim_ifchannel *ch) pim_include(S,G) = { all interfaces I such that: - ( (I_am_DR( I ) AND lost_assert(S,G,I) == FALSE ) - OR AssertWinner(S,G,I) == me ) - AND local_receiver_include(S,G,I) } + ( (I_am_DR( I ) AND lost_assert(S,G,I) == FALSE ) + OR AssertWinner(S,G,I) == me ) + AND local_receiver_include(S,G,I) } AssertWinner(S,G,I) is the IP source address of the Assert(S,G) packet that won an Assert. */ int pim_macro_chisin_pim_include(const struct pim_ifchannel *ch) { - struct pim_interface *pim_ifp = ch->interface->info; - - if (!pim_ifp) { - zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ch->interface->name); - return 0; /* false */ - } - - /* local_receiver_include(S,G,I) ? */ - if (!local_receiver_include(ch)) - return 0; /* false */ - - /* OR AssertWinner(S,G,I) == me ? */ - if (ch->ifassert_winner.s_addr == pim_ifp->primary_address.s_addr) - return 1; /* true */ - - return ( - /* I_am_DR( I ) ? */ - PIM_I_am_DR(pim_ifp) - && - /* lost_assert(S,G,I) == FALSE ? */ - (!pim_macro_ch_lost_assert(ch)) - ); + struct pim_interface *pim_ifp = ch->interface->info; + + if (!pim_ifp) { + zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name); + return 0; /* false */ + } + + /* local_receiver_include(S,G,I) ? */ + if (!local_receiver_include(ch)) + return 0; /* false */ + + /* OR AssertWinner(S,G,I) == me ? */ + if (ch->ifassert_winner.s_addr == pim_ifp->primary_address.s_addr) + return 1; /* true */ + + return ( + /* I_am_DR( I ) ? */ + PIM_I_am_DR(pim_ifp) && + /* lost_assert(S,G,I) == FALSE ? */ + (!pim_macro_ch_lost_assert(ch))); } int pim_macro_chisin_joins_or_include(const struct pim_ifchannel *ch) { - if (pim_macro_chisin_joins(ch)) - return 1; /* true */ + if (pim_macro_chisin_joins(ch)) + return 1; /* true */ - return pim_macro_chisin_pim_include(ch); + return pim_macro_chisin_pim_include(ch); } /* @@ -203,9 +197,9 @@ int pim_macro_chisin_joins_or_include(const struct pim_ifchannel *ch) SPTbit(S,G)==TRUE AND (RPF_interface(S) != I) AND (I in ( ( joins(*,*,RP(G)) (+) joins(*,G) (-) prunes(S,G,rpt) ) - (+) ( pim_include(*,G) (-) pim_exclude(S,G) ) - (-) lost_assert(*,G) - (+) joins(S,G) (+) pim_include(S,G) ) ) + (+) ( pim_include(*,G) (-) pim_exclude(S,G) ) + (-) lost_assert(*,G) + (+) joins(S,G) (+) pim_include(S,G) ) ) CouldAssert(S,G,I) is true for downstream interfaces that would be in the inherited_olist(S,G) if (S,G) assert information was not taken @@ -225,25 +219,25 @@ int pim_macro_chisin_joins_or_include(const struct pim_ifchannel *ch) */ int pim_macro_ch_could_assert_eval(const struct pim_ifchannel *ch) { - struct interface *ifp; + struct interface *ifp; - ifp = ch->interface; - if (!ifp) { - zlog_warn("%s: (S,G)=%s: null interface", - __PRETTY_FUNCTION__, ch->sg_str); - return 0; /* false */ - } + ifp = ch->interface; + if (!ifp) { + zlog_warn("%s: (S,G)=%s: null interface", __PRETTY_FUNCTION__, + ch->sg_str); + return 0; /* false */ + } - /* SPTbit(S,G) == TRUE */ - if (ch->upstream->sptbit == PIM_UPSTREAM_SPTBIT_FALSE) - return 0; /* false */ + /* SPTbit(S,G) == TRUE */ + if (ch->upstream->sptbit == PIM_UPSTREAM_SPTBIT_FALSE) + return 0; /* false */ - /* RPF_interface(S) != I ? */ - if (ch->upstream->rpf.source_nexthop.interface == ifp) - return 0; /* false */ + /* RPF_interface(S) != I ? */ + if (ch->upstream->rpf.source_nexthop.interface == ifp) + return 0; /* false */ - /* I in joins(S,G) (+) pim_include(S,G) ? */ - return pim_macro_chisin_joins_or_include(ch); + /* I in joins(S,G) (+) pim_include(S,G) ? */ + return pim_macro_chisin_joins_or_include(ch); } /* @@ -260,14 +254,14 @@ int pim_macro_ch_could_assert_eval(const struct pim_ifchannel *ch) struct pim_assert_metric pim_macro_spt_assert_metric(const struct pim_rpf *rpf, struct in_addr ifaddr) { - struct pim_assert_metric metric; + struct pim_assert_metric metric; - metric.rpt_bit_flag = 0; - metric.metric_preference = rpf->source_nexthop.mrib_metric_preference; - metric.route_metric = rpf->source_nexthop.mrib_route_metric; - metric.ip_address = ifaddr; + metric.rpt_bit_flag = 0; + metric.metric_preference = rpf->source_nexthop.mrib_metric_preference; + metric.route_metric = rpf->source_nexthop.mrib_route_metric; + metric.ip_address = ifaddr; - return metric; + return metric; } /* @@ -287,24 +281,26 @@ struct pim_assert_metric pim_macro_spt_assert_metric(const struct pim_rpf *rpf, } } */ -struct pim_assert_metric pim_macro_ch_my_assert_metric_eval(const struct pim_ifchannel *ch) +struct pim_assert_metric +pim_macro_ch_my_assert_metric_eval(const struct pim_ifchannel *ch) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - pim_ifp = ch->interface->info; + pim_ifp = ch->interface->info; - if (pim_ifp) { - if (PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { - return pim_macro_spt_assert_metric(&ch->upstream->rpf, pim_ifp->primary_address); - } - } + if (pim_ifp) { + if (PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { + return pim_macro_spt_assert_metric( + &ch->upstream->rpf, pim_ifp->primary_address); + } + } - return qpim_infinite_assert_metric; + return qpim_infinite_assert_metric; } /* RFC 4601 4.2. Data Packet Forwarding Rules - + Macro: inherited_olist(S,G) = inherited_olist(S,G,rpt) (+) @@ -312,10 +308,10 @@ struct pim_assert_metric pim_macro_ch_my_assert_metric_eval(const struct pim_ifc */ static int pim_macro_chisin_inherited_olist(const struct pim_ifchannel *ch) { - if (pim_macro_ch_lost_assert(ch)) - return 0; /* false */ + if (pim_macro_ch_lost_assert(ch)) + return 0; /* false */ - return pim_macro_chisin_joins_or_include(ch); + return pim_macro_chisin_joins_or_include(ch); } /* @@ -324,7 +320,7 @@ static int pim_macro_chisin_inherited_olist(const struct pim_ifchannel *ch) Additionally, the Packet forwarding rules of Section 4.2 can be simplified in a PIM-SSM-only router: - + iif is the incoming interface of the packet. oiflist = NULL if (iif == RPF_interface(S) AND UpstreamJPState(S,G) == Joined) { @@ -334,7 +330,7 @@ static int pim_macro_chisin_inherited_olist(const struct pim_ifchannel *ch) } oiflist = oiflist (-) iif forward packet on all interfaces in oiflist - + Macro: inherited_olist(S,G) = joins(S,G) (+) pim_include(S,G) (-) lost_assert(S,G) @@ -349,16 +345,16 @@ static int pim_macro_chisin_inherited_olist(const struct pim_ifchannel *ch) */ int pim_macro_chisin_oiflist(const struct pim_ifchannel *ch) { - if (ch->upstream->join_state == PIM_UPSTREAM_NOTJOINED) { - /* oiflist is NULL */ - return 0; /* false */ - } + if (ch->upstream->join_state == PIM_UPSTREAM_NOTJOINED) { + /* oiflist is NULL */ + return 0; /* false */ + } - /* oiflist = oiflist (-) iif */ - if (ch->interface == ch->upstream->rpf.source_nexthop.interface) - return 0; /* false */ + /* oiflist = oiflist (-) iif */ + if (ch->interface == ch->upstream->rpf.source_nexthop.interface) + return 0; /* false */ - return pim_macro_chisin_inherited_olist(ch); + return pim_macro_chisin_inherited_olist(ch); } /* @@ -380,45 +376,45 @@ int pim_macro_chisin_oiflist(const struct pim_ifchannel *ch) */ int pim_macro_assert_tracking_desired_eval(const struct pim_ifchannel *ch) { - struct pim_interface *pim_ifp; - struct interface *ifp; - - ifp = ch->interface; - if (!ifp) { - zlog_warn("%s: (S,G)=%s: null interface", - __PRETTY_FUNCTION__, ch->sg_str); - return 0; /* false */ - } - - pim_ifp = ifp->info; - if (!pim_ifp) { - zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", - __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name); - return 0; /* false */ - } - - /* I in joins(S,G) ? */ - if (pim_macro_chisin_joins(ch)) - return 1; /* true */ - - /* local_receiver_include(S,G,I) ? */ - if (local_receiver_include(ch)) { - /* I_am_DR(I) ? */ - if (PIM_I_am_DR(pim_ifp)) - return 1; /* true */ - - /* AssertWinner(S,G,I) == me ? */ - if (ch->ifassert_winner.s_addr == pim_ifp->primary_address.s_addr) - return 1; /* true */ - } - - /* RPF_interface(S) == I ? */ - if (ch->upstream->rpf.source_nexthop.interface == ifp) { - /* JoinDesired(S,G) ? */ - if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(ch->upstream->flags)) - return 1; /* true */ - } - - return 0; /* false */ + struct pim_interface *pim_ifp; + struct interface *ifp; + + ifp = ch->interface; + if (!ifp) { + zlog_warn("%s: (S,G)=%s: null interface", __PRETTY_FUNCTION__, + ch->sg_str); + return 0; /* false */ + } + + pim_ifp = ifp->info; + if (!pim_ifp) { + zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ch->interface->name); + return 0; /* false */ + } + + /* I in joins(S,G) ? */ + if (pim_macro_chisin_joins(ch)) + return 1; /* true */ + + /* local_receiver_include(S,G,I) ? */ + if (local_receiver_include(ch)) { + /* I_am_DR(I) ? */ + if (PIM_I_am_DR(pim_ifp)) + return 1; /* true */ + + /* AssertWinner(S,G,I) == me ? */ + if (ch->ifassert_winner.s_addr + == pim_ifp->primary_address.s_addr) + return 1; /* true */ + } + + /* RPF_interface(S) == I ? */ + if (ch->upstream->rpf.source_nexthop.interface == ifp) { + /* JoinDesired(S,G) ? */ + if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(ch->upstream->flags)) + return 1; /* true */ + } + + return 0; /* false */ } - diff --git a/pimd/pim_macro.h b/pimd/pim_macro.h index e07b2ece9..f310e244e 100644 --- a/pimd/pim_macro.h +++ b/pimd/pim_macro.h @@ -34,7 +34,8 @@ int pim_macro_chisin_joins_or_include(const struct pim_ifchannel *ch); int pim_macro_ch_could_assert_eval(const struct pim_ifchannel *ch); struct pim_assert_metric pim_macro_spt_assert_metric(const struct pim_rpf *rpf, struct in_addr ifaddr); -struct pim_assert_metric pim_macro_ch_my_assert_metric_eval(const struct pim_ifchannel *ch); +struct pim_assert_metric +pim_macro_ch_my_assert_metric_eval(const struct pim_ifchannel *ch); int pim_macro_chisin_oiflist(const struct pim_ifchannel *ch); int pim_macro_assert_tracking_desired_eval(const struct pim_ifchannel *ch); diff --git a/pimd/pim_main.c b/pimd/pim_main.c index a80059535..b8e6d8ad3 100644 --- a/pimd/pim_main.c +++ b/pimd/pim_main.c @@ -20,7 +20,7 @@ #include #include "log.h" -#include "privs.h" +#include "privs.h" #include "version.h" #include #include "command.h" @@ -49,115 +49,109 @@ extern struct host host; -struct option longopts[] = { - { 0 } -}; +struct option longopts[] = {{0}}; /* pimd privileges */ -zebra_capabilities_t _caps_p [] = -{ - ZCAP_NET_ADMIN, - ZCAP_SYS_ADMIN, - ZCAP_NET_RAW, - ZCAP_BIND, +zebra_capabilities_t _caps_p[] = { + ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN, ZCAP_NET_RAW, ZCAP_BIND, }; /* pimd privileges to run with */ -struct zebra_privs_t pimd_privs = -{ +struct zebra_privs_t pimd_privs = { #if defined(FRR_USER) && defined(FRR_GROUP) - .user = FRR_USER, - .group = FRR_GROUP, + .user = FRR_USER, + .group = FRR_GROUP, #endif #ifdef VTY_GROUP - .vty_group = VTY_GROUP, + .vty_group = VTY_GROUP, #endif - .caps_p = _caps_p, - .cap_num_p = sizeof(_caps_p)/sizeof(_caps_p[0]), - .cap_num_i = 0 -}; - -FRR_DAEMON_INFO(pimd, PIM, - .vty_port = PIMD_VTY_PORT, - - .proghelp = "Implementation of the PIM routing protocol.", - - .signals = pimd_signals, - .n_signals = 4 /* XXX array_size(pimd_signals) XXX*/, + .caps_p = _caps_p, + .cap_num_p = sizeof(_caps_p) / sizeof(_caps_p[0]), + .cap_num_i = 0}; - .privs = &pimd_privs, -) +FRR_DAEMON_INFO(pimd, PIM, .vty_port = PIMD_VTY_PORT, + .proghelp = "Implementation of the PIM routing protocol.", -int main(int argc, char** argv, char** envp) { - frr_preinit(&pimd_di, argc, argv); - frr_opt_add("", longopts, ""); + .signals = pimd_signals, + .n_signals = 4 /* XXX array_size(pimd_signals) XXX*/, - /* this while just reads the options */ - while (1) { - int opt; + .privs = &pimd_privs, ) - opt = frr_getopt(argc, argv, NULL); - if (opt == EOF) - break; - - switch (opt) { - case 0: - break; - default: - frr_help_exit (1); - break; - } - } - - master = frr_init(); - - /* - * Initializations - */ - pim_vrf_init (); - access_list_init(); - prefix_list_init (); - prefix_list_add_hook (pim_prefix_list_update); - prefix_list_delete_hook (pim_prefix_list_update); - - pim_route_map_init (); - pim_init(); - pim_msdp_init (master); - - /* - * Initialize zclient "update" and "lookup" sockets - */ - pim_zebra_init(); - pim_bfd_init (); - - frr_config_fork(); +int main(int argc, char **argv, char **envp) +{ + frr_preinit(&pimd_di, argc, argv); + frr_opt_add("", longopts, ""); + + /* this while just reads the options */ + while (1) { + int opt; + + opt = frr_getopt(argc, argv, NULL); + + if (opt == EOF) + break; + + switch (opt) { + case 0: + break; + default: + frr_help_exit(1); + break; + } + } + + master = frr_init(); + + /* + * Initializations + */ + pim_vrf_init(); + access_list_init(); + prefix_list_init(); + prefix_list_add_hook(pim_prefix_list_update); + prefix_list_delete_hook(pim_prefix_list_update); + + pim_route_map_init(); + pim_init(); + pim_msdp_init(master); + + /* + * Initialize zclient "update" and "lookup" sockets + */ + pim_zebra_init(); + pim_bfd_init(); + + frr_config_fork(); #ifdef PIM_DEBUG_BYDEFAULT - zlog_notice("PIM_DEBUG_BYDEFAULT: Enabling all debug commands"); - PIM_DO_DEBUG_PIM_EVENTS; - PIM_DO_DEBUG_PIM_PACKETS; - PIM_DO_DEBUG_PIM_TRACE; - PIM_DO_DEBUG_IGMP_EVENTS; - PIM_DO_DEBUG_IGMP_PACKETS; - PIM_DO_DEBUG_IGMP_TRACE; - PIM_DO_DEBUG_ZEBRA; + zlog_notice("PIM_DEBUG_BYDEFAULT: Enabling all debug commands"); + PIM_DO_DEBUG_PIM_EVENTS; + PIM_DO_DEBUG_PIM_PACKETS; + PIM_DO_DEBUG_PIM_TRACE; + PIM_DO_DEBUG_IGMP_EVENTS; + PIM_DO_DEBUG_IGMP_PACKETS; + PIM_DO_DEBUG_IGMP_TRACE; + PIM_DO_DEBUG_ZEBRA; #endif #ifdef PIM_CHECK_RECV_IFINDEX_SANITY - zlog_notice("PIM_CHECK_RECV_IFINDEX_SANITY: will match sock/recv ifindex"); + zlog_notice( + "PIM_CHECK_RECV_IFINDEX_SANITY: will match sock/recv ifindex"); #ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH - zlog_notice("PIM_REPORT_RECV_IFINDEX_MISMATCH: will report sock/recv ifindex mismatch"); + zlog_notice( + "PIM_REPORT_RECV_IFINDEX_MISMATCH: will report sock/recv ifindex mismatch"); #endif #endif #ifdef PIM_UNEXPECTED_KERNEL_UPCALL - zlog_notice("PIM_UNEXPECTED_KERNEL_UPCALL: report unexpected kernel upcall"); + zlog_notice( + "PIM_UNEXPECTED_KERNEL_UPCALL: report unexpected kernel upcall"); #endif - frr_run(master); + frr_run(master); - /* never reached */ - return 0; + /* never reached */ + return 0; } diff --git a/pimd/pim_memory.c b/pimd/pim_memory.c index d18b7f0c8..dff16c416 100644 --- a/pimd/pim_memory.c +++ b/pimd/pim_memory.c @@ -26,29 +26,29 @@ #include "pim_memory.h" DEFINE_MGROUP(PIMD, "pimd") -DEFINE_MTYPE(PIMD, PIM_CHANNEL_OIL, "PIM SSM (S,G) channel OIL") -DEFINE_MTYPE(PIMD, PIM_INTERFACE, "PIM interface") -DEFINE_MTYPE(PIMD, PIM_IGMP_JOIN, "PIM interface IGMP static join") -DEFINE_MTYPE(PIMD, PIM_IGMP_SOCKET, "PIM interface IGMP socket") -DEFINE_MTYPE(PIMD, PIM_IGMP_GROUP, "PIM interface IGMP group") +DEFINE_MTYPE(PIMD, PIM_CHANNEL_OIL, "PIM SSM (S,G) channel OIL") +DEFINE_MTYPE(PIMD, PIM_INTERFACE, "PIM interface") +DEFINE_MTYPE(PIMD, PIM_IGMP_JOIN, "PIM interface IGMP static join") +DEFINE_MTYPE(PIMD, PIM_IGMP_SOCKET, "PIM interface IGMP socket") +DEFINE_MTYPE(PIMD, PIM_IGMP_GROUP, "PIM interface IGMP group") DEFINE_MTYPE(PIMD, PIM_IGMP_GROUP_SOURCE, "PIM interface IGMP source") -DEFINE_MTYPE(PIMD, PIM_NEIGHBOR, "PIM interface neighbor") -DEFINE_MTYPE(PIMD, PIM_IFCHANNEL, "PIM interface (S,G) state") -DEFINE_MTYPE(PIMD, PIM_UPSTREAM, "PIM upstream (S,G) state") -DEFINE_MTYPE(PIMD, PIM_SSMPINGD, "PIM sspimgd socket") -DEFINE_MTYPE(PIMD, PIM_STATIC_ROUTE, "PIM Static Route") -DEFINE_MTYPE(PIMD, PIM_BR, "PIM Bridge Router info") -DEFINE_MTYPE(PIMD, PIM_RP, "PIM RP info") -DEFINE_MTYPE(PIMD, PIM_FILTER_NAME, "PIM RP filter info") -DEFINE_MTYPE(PIMD, PIM_MSDP_PEER, "PIM MSDP peer") -DEFINE_MTYPE(PIMD, PIM_MSDP_MG_NAME, "PIM MSDP mesh-group name") -DEFINE_MTYPE(PIMD, PIM_MSDP_SA, "PIM MSDP source-active cache") -DEFINE_MTYPE(PIMD, PIM_MSDP_MG, "PIM MSDP mesh group") -DEFINE_MTYPE(PIMD, PIM_MSDP_MG_MBR, "PIM MSDP mesh group mbr") -DEFINE_MTYPE(PIMD, PIM_SEC_ADDR, "PIM secondary address") -DEFINE_MTYPE(PIMD, PIM_JP_AGG_GROUP, "PIM JP AGG Group") -DEFINE_MTYPE(PIMD, PIM_JP_AGG_SOURCE, "PIM JP AGG Source") -DEFINE_MTYPE(PIMD, PIM_PIM_INSTANCE, "PIM global state") -DEFINE_MTYPE(PIMD, PIM_NEXTHOP_CACHE, "PIM nexthop cache state") -DEFINE_MTYPE(PIMD, PIM_SSM_INFO, "PIM SSM configuration") -DEFINE_MTYPE(PIMD, PIM_SPT_PLIST_NAME, "PIM SPT Prefix List Name") +DEFINE_MTYPE(PIMD, PIM_NEIGHBOR, "PIM interface neighbor") +DEFINE_MTYPE(PIMD, PIM_IFCHANNEL, "PIM interface (S,G) state") +DEFINE_MTYPE(PIMD, PIM_UPSTREAM, "PIM upstream (S,G) state") +DEFINE_MTYPE(PIMD, PIM_SSMPINGD, "PIM sspimgd socket") +DEFINE_MTYPE(PIMD, PIM_STATIC_ROUTE, "PIM Static Route") +DEFINE_MTYPE(PIMD, PIM_BR, "PIM Bridge Router info") +DEFINE_MTYPE(PIMD, PIM_RP, "PIM RP info") +DEFINE_MTYPE(PIMD, PIM_FILTER_NAME, "PIM RP filter info") +DEFINE_MTYPE(PIMD, PIM_MSDP_PEER, "PIM MSDP peer") +DEFINE_MTYPE(PIMD, PIM_MSDP_MG_NAME, "PIM MSDP mesh-group name") +DEFINE_MTYPE(PIMD, PIM_MSDP_SA, "PIM MSDP source-active cache") +DEFINE_MTYPE(PIMD, PIM_MSDP_MG, "PIM MSDP mesh group") +DEFINE_MTYPE(PIMD, PIM_MSDP_MG_MBR, "PIM MSDP mesh group mbr") +DEFINE_MTYPE(PIMD, PIM_SEC_ADDR, "PIM secondary address") +DEFINE_MTYPE(PIMD, PIM_JP_AGG_GROUP, "PIM JP AGG Group") +DEFINE_MTYPE(PIMD, PIM_JP_AGG_SOURCE, "PIM JP AGG Source") +DEFINE_MTYPE(PIMD, PIM_PIM_INSTANCE, "PIM global state") +DEFINE_MTYPE(PIMD, PIM_NEXTHOP_CACHE, "PIM nexthop cache state") +DEFINE_MTYPE(PIMD, PIM_SSM_INFO, "PIM SSM configuration") +DEFINE_MTYPE(PIMD, PIM_SPT_PLIST_NAME, "PIM SPT Prefix List Name") diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 01747268a..a92b01ca0 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -47,358 +47,360 @@ static void mroute_read_on(void); static int pim_mroute_set(int fd, int enable) { - int err; - int opt = enable ? MRT_INIT : MRT_DONE; - socklen_t opt_len = sizeof(opt); - int rcvbuf = 1024 * 1024 * 8; - long flags; - - err = setsockopt(fd, IPPROTO_IP, opt, &opt, opt_len); - if (err) { - zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,%s=%d): errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, - fd, enable ? "MRT_INIT" : "MRT_DONE", opt, errno, safe_strerror(errno)); - return -1; - } - - err = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)); - if (err) { - zlog_warn("%s: failure: setsockopt(fd=%d, SOL_SOCKET, %d): errno=%d: %s", - __PRETTY_FUNCTION__, fd, rcvbuf, errno, safe_strerror(errno)); - } - - flags = fcntl(fd, F_GETFL, 0); - if (flags < 0) - { - zlog_warn("Could not get flags on socket fd:%d %d %s", - fd, errno, safe_strerror(errno)); - close (fd); - return -1; - } - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) - { - zlog_warn("Could not set O_NONBLOCK on socket fd:%d %d %s", - fd, errno, safe_strerror(errno)); - close(fd); - return -1; - } + int err; + int opt = enable ? MRT_INIT : MRT_DONE; + socklen_t opt_len = sizeof(opt); + int rcvbuf = 1024 * 1024 * 8; + long flags; + + err = setsockopt(fd, IPPROTO_IP, opt, &opt, opt_len); + if (err) { + zlog_warn( + "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,%s=%d): errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, fd, + enable ? "MRT_INIT" : "MRT_DONE", opt, errno, + safe_strerror(errno)); + return -1; + } - if (enable) - { + err = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)); + if (err) { + zlog_warn( + "%s: failure: setsockopt(fd=%d, SOL_SOCKET, %d): errno=%d: %s", + __PRETTY_FUNCTION__, fd, rcvbuf, errno, + safe_strerror(errno)); + } + + flags = fcntl(fd, F_GETFL, 0); + if (flags < 0) { + zlog_warn("Could not get flags on socket fd:%d %d %s", fd, + errno, safe_strerror(errno)); + close(fd); + return -1; + } + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { + zlog_warn("Could not set O_NONBLOCK on socket fd:%d %d %s", fd, + errno, safe_strerror(errno)); + close(fd); + return -1; + } + + if (enable) { #if defined linux - int upcalls = IGMPMSG_WRVIFWHOLE; - opt = MRT_PIM; - - err = setsockopt (fd, IPPROTO_IP, opt, &upcalls, sizeof (upcalls)); - if (err) - { - zlog_warn ("Failure to register for VIFWHOLE and WRONGVIF upcalls %d %s", - errno, safe_strerror (errno)); - return -1; - } + int upcalls = IGMPMSG_WRVIFWHOLE; + opt = MRT_PIM; + + err = setsockopt(fd, IPPROTO_IP, opt, &upcalls, + sizeof(upcalls)); + if (err) { + zlog_warn( + "Failure to register for VIFWHOLE and WRONGVIF upcalls %d %s", + errno, safe_strerror(errno)); + return -1; + } #else - zlog_warn ("PIM-SM will not work properly on this platform, until the ability to receive the WRVIFWHOLE upcall"); + zlog_warn( + "PIM-SM will not work properly on this platform, until the ability to receive the WRVIFWHOLE upcall"); #endif - } - - return 0; + } + + return 0; } static const char *igmpmsgtype2str[IGMPMSG_WRVIFWHOLE + 1] = { - "", - "NOCACHE", - "WRONGVIF", - "WHOLEPKT", - "WRVIFWHOLE" }; - -static int -pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg) + "", "NOCACHE", "WRONGVIF", "WHOLEPKT", "WRVIFWHOLE"}; + +static int pim_mroute_msg_nocache(int fd, struct interface *ifp, + const struct igmpmsg *msg) { - struct pim_interface *pim_ifp = ifp->info; - struct pim_upstream *up; - struct pim_rpf *rpg; - struct prefix_sg sg; - - rpg = RP(msg->im_dst); - /* - * If the incoming interface is unknown OR - * the Interface type is SSM we don't need to - * do anything here - */ - if ((pim_rpf_addr_is_inaddr_none (rpg)) || - (!pim_ifp) || - (!(PIM_I_am_DR(pim_ifp)))) - { - if (PIM_DEBUG_MROUTE_DETAIL) - zlog_debug ("%s: Interface is not configured correctly to handle incoming packet: Could be !DR, !pim_ifp, !SM, !RP", - __PRETTY_FUNCTION__); - return 0; - } + struct pim_interface *pim_ifp = ifp->info; + struct pim_upstream *up; + struct pim_rpf *rpg; + struct prefix_sg sg; + + rpg = RP(msg->im_dst); + /* + * If the incoming interface is unknown OR + * the Interface type is SSM we don't need to + * do anything here + */ + if ((pim_rpf_addr_is_inaddr_none(rpg)) || (!pim_ifp) + || (!(PIM_I_am_DR(pim_ifp)))) { + if (PIM_DEBUG_MROUTE_DETAIL) + zlog_debug( + "%s: Interface is not configured correctly to handle incoming packet: Could be !DR, !pim_ifp, !SM, !RP", + __PRETTY_FUNCTION__); + return 0; + } - /* - * If we've received a multicast packet that isn't connected to - * us - */ - if (!pim_if_connected_to_source (ifp, msg->im_src)) - { - if (PIM_DEBUG_MROUTE_DETAIL) - zlog_debug ("%s: Received incoming packet that doesn't originate on our seg", - __PRETTY_FUNCTION__); - return 0; - } + /* + * If we've received a multicast packet that isn't connected to + * us + */ + if (!pim_if_connected_to_source(ifp, msg->im_src)) { + if (PIM_DEBUG_MROUTE_DETAIL) + zlog_debug( + "%s: Received incoming packet that doesn't originate on our seg", + __PRETTY_FUNCTION__); + return 0; + } - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = msg->im_src; - sg.grp = msg->im_dst; + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = msg->im_src; + sg.grp = msg->im_dst; + + up = pim_upstream_find_or_add(&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, + __PRETTY_FUNCTION__); + if (!up) { + if (PIM_DEBUG_MROUTE) { + zlog_debug( + "%s: Failure to add upstream information for %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg)); + } + return 0; + } - up = pim_upstream_find_or_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, __PRETTY_FUNCTION__); - if (!up) - { - if (PIM_DEBUG_MROUTE) - { - zlog_debug("%s: Failure to add upstream information for %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg)); - } - return 0; - } + /* + * I moved this debug till after the actual add because + * I want to take advantage of the up->sg_str being filled in. + */ + if (PIM_DEBUG_MROUTE) { + zlog_debug("%s: Adding a Route %s for WHOLEPKT consumption", + __PRETTY_FUNCTION__, up->sg_str); + } - /* - * I moved this debug till after the actual add because - * I want to take advantage of the up->sg_str being filled in. - */ - if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: Adding a Route %s for WHOLEPKT consumption", - __PRETTY_FUNCTION__, up->sg_str); - } - - PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); - pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); - - up->channel_oil->cc.pktcnt++; - PIM_UPSTREAM_FLAG_SET_FHR(up->flags); - // resolve mfcc_parent prior to mroute_add in channel_add_oif - if (up->channel_oil->oil.mfcc_parent >= MAXVIFS) - { - int vif_index = 0; - vif_index = - pim_if_find_vifindex_by_ifindex (up->rpf.source_nexthop. - interface->ifindex); - up->channel_oil->oil.mfcc_parent = vif_index; - } - pim_register_join (up); + PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); + pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); + + up->channel_oil->cc.pktcnt++; + PIM_UPSTREAM_FLAG_SET_FHR(up->flags); + // resolve mfcc_parent prior to mroute_add in channel_add_oif + if (up->channel_oil->oil.mfcc_parent >= MAXVIFS) { + int vif_index = 0; + vif_index = pim_if_find_vifindex_by_ifindex( + up->rpf.source_nexthop.interface->ifindex); + up->channel_oil->oil.mfcc_parent = vif_index; + } + pim_register_join(up); - return 0; + return 0; } -static int -pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf) +static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp, + const char *buf) { - struct pim_interface *pim_ifp; - struct prefix_sg sg; - struct pim_rpf *rpg; - const struct ip *ip_hdr; - struct pim_upstream *up; - - ip_hdr = (const struct ip *)buf; - - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = ip_hdr->ip_src; - sg.grp = ip_hdr->ip_dst; - - up = pim_upstream_find(&sg); - if (!up) { - struct prefix_sg star = sg; - star.src.s_addr = INADDR_ANY; - - up = pim_upstream_find(&star); - - if (up && PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) - { - up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_LHR, __PRETTY_FUNCTION__); - if (!up) - { - if (PIM_DEBUG_MROUTE) - zlog_debug ("%s: Unable to create upstream information for %s", - __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); - return 0; - } - pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); - pim_upstream_inherited_olist (up); - pim_upstream_switch(up, PIM_UPSTREAM_JOINED); - - if (PIM_DEBUG_MROUTE) - zlog_debug ("%s: Creating %s upstream on LHR", - __PRETTY_FUNCTION__, up->sg_str); - return 0; - } - if (PIM_DEBUG_MROUTE_DETAIL) { - zlog_debug("%s: Unable to find upstream channel WHOLEPKT%s", - __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); - } - return 0; - } + struct pim_interface *pim_ifp; + struct prefix_sg sg; + struct pim_rpf *rpg; + const struct ip *ip_hdr; + struct pim_upstream *up; + + ip_hdr = (const struct ip *)buf; + + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = ip_hdr->ip_src; + sg.grp = ip_hdr->ip_dst; + + up = pim_upstream_find(&sg); + if (!up) { + struct prefix_sg star = sg; + star.src.s_addr = INADDR_ANY; + + up = pim_upstream_find(&star); + + if (up && PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) { + up = pim_upstream_add(&sg, ifp, + PIM_UPSTREAM_FLAG_MASK_SRC_LHR, + __PRETTY_FUNCTION__); + if (!up) { + if (PIM_DEBUG_MROUTE) + zlog_debug( + "%s: Unable to create upstream information for %s", + __PRETTY_FUNCTION__, + pim_str_sg_dump(&sg)); + return 0; + } + pim_upstream_keep_alive_timer_start( + up, qpim_keep_alive_time); + pim_upstream_inherited_olist(up); + pim_upstream_switch(up, PIM_UPSTREAM_JOINED); + + if (PIM_DEBUG_MROUTE) + zlog_debug("%s: Creating %s upstream on LHR", + __PRETTY_FUNCTION__, up->sg_str); + return 0; + } + if (PIM_DEBUG_MROUTE_DETAIL) { + zlog_debug( + "%s: Unable to find upstream channel WHOLEPKT%s", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg)); + } + return 0; + } - pim_ifp = up->rpf.source_nexthop.interface->info; + pim_ifp = up->rpf.source_nexthop.interface->info; - rpg = RP(sg.grp); + rpg = RP(sg.grp); - if ((pim_rpf_addr_is_inaddr_none (rpg)) || - (!pim_ifp) || - (!(PIM_I_am_DR(pim_ifp)))) { - if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: Failed Check send packet", __PRETTY_FUNCTION__); - } - return 0; - } + if ((pim_rpf_addr_is_inaddr_none(rpg)) || (!pim_ifp) + || (!(PIM_I_am_DR(pim_ifp)))) { + if (PIM_DEBUG_MROUTE) { + zlog_debug("%s: Failed Check send packet", + __PRETTY_FUNCTION__); + } + return 0; + } - /* - * If we've received a register suppress - */ - if (!up->t_rs_timer) - { - if (pim_is_grp_ssm (sg.grp)) - { - if (PIM_DEBUG_PIM_REG) - zlog_debug ("%s register forward skipped as group is SSM", - pim_str_sg_dump (&sg)); - return 0; - } - pim_register_send((uint8_t *)buf + sizeof(struct ip), - ntohs (ip_hdr->ip_len) - sizeof (struct ip), - pim_ifp->primary_address, rpg, 0, up); - } - return 0; + /* + * If we've received a register suppress + */ + if (!up->t_rs_timer) { + if (pim_is_grp_ssm(sg.grp)) { + if (PIM_DEBUG_PIM_REG) + zlog_debug( + "%s register forward skipped as group is SSM", + pim_str_sg_dump(&sg)); + return 0; + } + pim_register_send((uint8_t *)buf + sizeof(struct ip), + ntohs(ip_hdr->ip_len) - sizeof(struct ip), + pim_ifp->primary_address, rpg, 0, up); + } + return 0; } -static int -pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *msg) +static int pim_mroute_msg_wrongvif(int fd, struct interface *ifp, + const struct igmpmsg *msg) { - struct pim_ifchannel *ch; - struct pim_interface *pim_ifp; - struct prefix_sg sg; + struct pim_ifchannel *ch; + struct pim_interface *pim_ifp; + struct prefix_sg sg; + + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = msg->im_src; + sg.grp = msg->im_dst; + + /* + Send Assert(S,G) on iif as response to WRONGVIF kernel upcall. + + RFC 4601 4.8.2. PIM-SSM-Only Routers + + iif is the incoming interface of the packet. + if (iif is in inherited_olist(S,G)) { + send Assert(S,G) on iif + } + */ + + if (!ifp) { + if (PIM_DEBUG_MROUTE) + zlog_debug( + "%s: WRONGVIF (S,G)=%s could not find input interface for input_vif_index=%d", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), + msg->im_vif); + return -1; + } - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = msg->im_src; - sg.grp = msg->im_dst; + pim_ifp = ifp->info; + if (!pim_ifp) { + if (PIM_DEBUG_MROUTE) + zlog_debug( + "%s: WRONGVIF (S,G)=%s multicast not enabled on interface %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), + ifp->name); + return -2; + } - /* - Send Assert(S,G) on iif as response to WRONGVIF kernel upcall. + ch = pim_ifchannel_find(ifp, &sg); + if (!ch) { + struct prefix_sg star_g = sg; + if (PIM_DEBUG_MROUTE) + zlog_debug( + "%s: WRONGVIF (S,G)=%s could not find channel on interface %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), + ifp->name); + + star_g.src.s_addr = INADDR_ANY; + ch = pim_ifchannel_find(ifp, &star_g); + if (!ch) { + if (PIM_DEBUG_MROUTE) + zlog_debug( + "%s: WRONGVIF (*,G)=%s could not find channel on interface %s", + __PRETTY_FUNCTION__, + pim_str_sg_dump(&star_g), ifp->name); + return -3; + } + } - RFC 4601 4.8.2. PIM-SSM-Only Routers + /* + RFC 4601: 4.6.1. (S,G) Assert Message State Machine + + Transitions from NoInfo State + + An (S,G) data packet arrives on interface I, AND + CouldAssert(S,G,I)==TRUE An (S,G) data packet arrived on an + downstream interface that is in our (S,G) outgoing interface + list. We optimistically assume that we will be the assert + winner for this (S,G), and so we transition to the "I am Assert + Winner" state and perform Actions A1 (below), which will + initiate the assert negotiation for (S,G). + */ + + if (ch->ifassert_state != PIM_IFASSERT_NOINFO) { + if (PIM_DEBUG_MROUTE) { + zlog_debug( + "%s: WRONGVIF (S,G)=%s channel is not on Assert NoInfo state for interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ifp->name); + } + return -4; + } - iif is the incoming interface of the packet. - if (iif is in inherited_olist(S,G)) { - send Assert(S,G) on iif - } - */ - - if (!ifp) { - if (PIM_DEBUG_MROUTE) - zlog_debug("%s: WRONGVIF (S,G)=%s could not find input interface for input_vif_index=%d", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), msg->im_vif); - return -1; - } - - pim_ifp = ifp->info; - if (!pim_ifp) { - if (PIM_DEBUG_MROUTE) - zlog_debug("%s: WRONGVIF (S,G)=%s multicast not enabled on interface %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), ifp->name); - return -2; - } - - ch = pim_ifchannel_find(ifp, &sg); - if (!ch) { - struct prefix_sg star_g = sg; - if (PIM_DEBUG_MROUTE) - zlog_debug("%s: WRONGVIF (S,G)=%s could not find channel on interface %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump(&sg), ifp->name); - - star_g.src.s_addr = INADDR_ANY; - ch = pim_ifchannel_find(ifp, &star_g); - if (!ch) { - if (PIM_DEBUG_MROUTE) - zlog_debug("%s: WRONGVIF (*,G)=%s could not find channel on interface %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump(&star_g), ifp->name); - return -3; - } - } - - /* - RFC 4601: 4.6.1. (S,G) Assert Message State Machine - - Transitions from NoInfo State - - An (S,G) data packet arrives on interface I, AND - CouldAssert(S,G,I)==TRUE An (S,G) data packet arrived on an - downstream interface that is in our (S,G) outgoing interface - list. We optimistically assume that we will be the assert - winner for this (S,G), and so we transition to the "I am Assert - Winner" state and perform Actions A1 (below), which will - initiate the assert negotiation for (S,G). - */ - - if (ch->ifassert_state != PIM_IFASSERT_NOINFO) { - if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: WRONGVIF (S,G)=%s channel is not on Assert NoInfo state for interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ifp->name); - } - return -4; - } - - if (!PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { - if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: WRONGVIF (S,G)=%s interface %s is not downstream for channel", - __PRETTY_FUNCTION__, - ch->sg_str, ifp->name); - } - return -5; - } - - if (assert_action_a1(ch)) { - if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: WRONGVIF (S,G)=%s assert_action_a1 failure on interface %s", - __PRETTY_FUNCTION__, - ch->sg_str, ifp->name); - } - return -6; - } + if (!PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) { + if (PIM_DEBUG_MROUTE) { + zlog_debug( + "%s: WRONGVIF (S,G)=%s interface %s is not downstream for channel", + __PRETTY_FUNCTION__, ch->sg_str, ifp->name); + } + return -5; + } + + if (assert_action_a1(ch)) { + if (PIM_DEBUG_MROUTE) { + zlog_debug( + "%s: WRONGVIF (S,G)=%s assert_action_a1 failure on interface %s", + __PRETTY_FUNCTION__, ch->sg_str, ifp->name); + } + return -6; + } - return 0; + return 0; } -static int -pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) +static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp, + const char *buf) { - const struct ip *ip_hdr = (const struct ip *)buf; - struct pim_interface *pim_ifp; - struct pim_ifchannel *ch; - struct pim_upstream *up; - struct prefix_sg star_g; - struct prefix_sg sg; - struct channel_oil *oil; - - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = ip_hdr->ip_src; - sg.grp = ip_hdr->ip_dst; - - ch = pim_ifchannel_find(ifp, &sg); - if (ch) - { - if (PIM_DEBUG_MROUTE) - zlog_debug ("WRVIFWHOLE (S,G)=%s found ifchannel on interface %s", - ch->sg_str, ifp->name); - return -1; - } + const struct ip *ip_hdr = (const struct ip *)buf; + struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; + struct pim_upstream *up; + struct prefix_sg star_g; + struct prefix_sg sg; + struct channel_oil *oil; + + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = ip_hdr->ip_src; + sg.grp = ip_hdr->ip_dst; + + ch = pim_ifchannel_find(ifp, &sg); + if (ch) { + if (PIM_DEBUG_MROUTE) + zlog_debug( + "WRVIFWHOLE (S,G)=%s found ifchannel on interface %s", + ch->sg_str, ifp->name); + return -1; + } - star_g = sg; - star_g.src.s_addr = INADDR_ANY; + star_g = sg; + star_g.src.s_addr = INADDR_ANY; #if 0 ch = pim_ifchannel_find(ifp, &star_g); if (ch) @@ -410,290 +412,313 @@ pim_mroute_msg_wrvifwhole (int fd, struct interface *ifp, const char *buf) } #endif - up = pim_upstream_find (&sg); - if (up) - { - struct pim_upstream *parent; - struct pim_nexthop source; - struct pim_rpf *rpf = RP (sg.grp); - if (!rpf || !rpf->source_nexthop.interface) - return 0; - - /* - * If we have received a WRVIFWHOLE and are at this - * point, we could be receiving the packet on the *,G - * tree, let's check and if so we can safely drop - * it. - */ - parent = pim_upstream_find (&star_g); - if (parent && parent->rpf.source_nexthop.interface == ifp) - return 0; - - pim_ifp = rpf->source_nexthop.interface->info; - - memset (&source, 0, sizeof (source)); - /* - * If we are the fhr that means we are getting a callback during - * the pimreg period, so I believe we can ignore this packet - */ - if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) - { - //No if channel, but upstream we are at the RP. - if (pim_nexthop_lookup (&source, up->upstream_register, 0) == 0) - pim_register_stop_send(source.interface, &sg, pim_ifp->primary_address, up->upstream_register); - if (!up->channel_oil) - up->channel_oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); - pim_upstream_inherited_olist (up); - if (!up->channel_oil->installed) - pim_mroute_add (up->channel_oil, __PRETTY_FUNCTION__); - pim_upstream_set_sptbit (up, ifp); - } - else - { - if (I_am_RP (up->sg.grp)) - { - if (pim_nexthop_lookup (&source, up->upstream_register, 0) == 0) - pim_register_stop_send(source.interface, &sg, pim_ifp->primary_address, up->upstream_register); - up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; - } - pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); - pim_upstream_inherited_olist (up); - pim_mroute_msg_wholepkt (fd, ifp, buf); - } - return 0; - } + up = pim_upstream_find(&sg); + if (up) { + struct pim_upstream *parent; + struct pim_nexthop source; + struct pim_rpf *rpf = RP(sg.grp); + if (!rpf || !rpf->source_nexthop.interface) + return 0; + + /* + * If we have received a WRVIFWHOLE and are at this + * point, we could be receiving the packet on the *,G + * tree, let's check and if so we can safely drop + * it. + */ + parent = pim_upstream_find(&star_g); + if (parent && parent->rpf.source_nexthop.interface == ifp) + return 0; + + pim_ifp = rpf->source_nexthop.interface->info; + + memset(&source, 0, sizeof(source)); + /* + * If we are the fhr that means we are getting a callback during + * the pimreg period, so I believe we can ignore this packet + */ + if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) { + // No if channel, but upstream we are at the RP. + if (pim_nexthop_lookup(&source, up->upstream_register, + 0) + == 0) + pim_register_stop_send(source.interface, &sg, + pim_ifp->primary_address, + up->upstream_register); + if (!up->channel_oil) + up->channel_oil = pim_channel_oil_add( + &sg, pim_ifp->mroute_vif_index); + pim_upstream_inherited_olist(up); + if (!up->channel_oil->installed) + pim_mroute_add(up->channel_oil, + __PRETTY_FUNCTION__); + pim_upstream_set_sptbit(up, ifp); + } else { + if (I_am_RP(up->sg.grp)) { + if (pim_nexthop_lookup(&source, + up->upstream_register, 0) + == 0) + pim_register_stop_send( + source.interface, &sg, + pim_ifp->primary_address, + up->upstream_register); + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + } + pim_upstream_keep_alive_timer_start( + up, qpim_keep_alive_time); + pim_upstream_inherited_olist(up); + pim_mroute_msg_wholepkt(fd, ifp, buf); + } + return 0; + } - pim_ifp = ifp->info; - oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); - if (!oil->installed) - pim_mroute_add (oil, __PRETTY_FUNCTION__); - if (pim_if_connected_to_source (ifp, sg.src)) - { - up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, __PRETTY_FUNCTION__); - if (!up) - { - if (PIM_DEBUG_MROUTE) - zlog_debug ("%s: WRONGVIF%s unable to create upstream on interface", - pim_str_sg_dump (&sg), ifp->name); - return -2; - } - PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); - pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); - up->channel_oil = oil; - up->channel_oil->cc.pktcnt++; - pim_register_join (up); - pim_upstream_inherited_olist (up); - - // Send the packet to the RP - pim_mroute_msg_wholepkt (fd, ifp, buf); - } + pim_ifp = ifp->info; + oil = pim_channel_oil_add(&sg, pim_ifp->mroute_vif_index); + if (!oil->installed) + pim_mroute_add(oil, __PRETTY_FUNCTION__); + if (pim_if_connected_to_source(ifp, sg.src)) { + up = pim_upstream_add(&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, + __PRETTY_FUNCTION__); + if (!up) { + if (PIM_DEBUG_MROUTE) + zlog_debug( + "%s: WRONGVIF%s unable to create upstream on interface", + pim_str_sg_dump(&sg), ifp->name); + return -2; + } + PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); + pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); + up->channel_oil = oil; + up->channel_oil->cc.pktcnt++; + pim_register_join(up); + pim_upstream_inherited_olist(up); + + // Send the packet to the RP + pim_mroute_msg_wholepkt(fd, ifp, buf); + } - return 0; + return 0; } int pim_mroute_msg(int fd, const char *buf, int buf_size) { - struct interface *ifp; - struct pim_interface *pim_ifp; - const struct ip *ip_hdr; - const struct igmpmsg *msg; - char ip_src_str[INET_ADDRSTRLEN] = ""; - char ip_dst_str[INET_ADDRSTRLEN] = ""; - char src_str[INET_ADDRSTRLEN] = ""; - char grp_str[INET_ADDRSTRLEN] = ""; - struct in_addr ifaddr; - struct igmp_sock *igmp; - - ip_hdr = (const struct ip *) buf; - - if (ip_hdr->ip_p == IPPROTO_IGMP) { - - /* We have the IP packet but we do not know which interface this packet was - * received on. Find the interface that is on the same subnet as the source - * of the IP packet. - */ - ifp = pim_if_lookup_address_vrf (ip_hdr->ip_src, VRF_DEFAULT); - - if (!ifp) { - if (PIM_DEBUG_MROUTE_DETAIL) { - pim_inet4_dump("", ip_hdr->ip_src, ip_src_str, sizeof(ip_src_str)); - pim_inet4_dump("", ip_hdr->ip_dst, ip_dst_str, sizeof(ip_dst_str)); - - zlog_warn("%s: igmp kernel upcall could not find usable interface for %s -> %s", - __PRETTY_FUNCTION__, - ip_src_str, - ip_dst_str); - } - return 0; - } - pim_ifp = ifp->info; - ifaddr = pim_find_primary_addr(ifp); - igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr); - - if (PIM_DEBUG_MROUTE) { - pim_inet4_dump("", ip_hdr->ip_src, ip_src_str, sizeof(ip_src_str)); - pim_inet4_dump("", ip_hdr->ip_dst, ip_dst_str, sizeof(ip_dst_str)); - - zlog_warn("%s: igmp kernel upcall on %s(%p) for %s -> %s", - __PRETTY_FUNCTION__, ifp->name, igmp, ip_src_str, ip_dst_str); - } - if (igmp) - pim_igmp_packet(igmp, (char *)buf, buf_size); - - } else if (ip_hdr->ip_p) { - if (PIM_DEBUG_MROUTE_DETAIL) { - pim_inet4_dump("", ip_hdr->ip_src, src_str, sizeof(src_str)); - pim_inet4_dump("", ip_hdr->ip_dst, grp_str, sizeof(grp_str)); - zlog_debug("%s: no kernel upcall proto=%d src: %s dst: %s msg_size=%d", - __PRETTY_FUNCTION__, ip_hdr->ip_p, src_str, grp_str, buf_size); - } - - } else { - msg = (const struct igmpmsg *) buf; - - ifp = pim_if_find_by_vif_index(msg->im_vif); - - if (!ifp) - return 0; - if (PIM_DEBUG_MROUTE) { - pim_inet4_dump("", msg->im_src, src_str, sizeof(src_str)); - pim_inet4_dump("", msg->im_dst, grp_str, sizeof(grp_str)); - zlog_warn("%s: pim kernel upcall %s type=%d ip_p=%d from fd=%d for (S,G)=(%s,%s) on %s vifi=%d size=%d", - __PRETTY_FUNCTION__, - igmpmsgtype2str[msg->im_msgtype], - msg->im_msgtype, - ip_hdr->ip_p, - fd, - src_str, - grp_str, - ifp->name, - msg->im_vif, buf_size); - } - - switch (msg->im_msgtype) { - case IGMPMSG_WRONGVIF: - return pim_mroute_msg_wrongvif(fd, ifp, msg); - break; - case IGMPMSG_NOCACHE: - return pim_mroute_msg_nocache(fd, ifp, msg); - break; - case IGMPMSG_WHOLEPKT: - return pim_mroute_msg_wholepkt(fd, ifp, (const char *)msg); - break; - case IGMPMSG_WRVIFWHOLE: - return pim_mroute_msg_wrvifwhole (fd, ifp, (const char *)msg); - break; - default: - break; - } - } + struct interface *ifp; + struct pim_interface *pim_ifp; + const struct ip *ip_hdr; + const struct igmpmsg *msg; + char ip_src_str[INET_ADDRSTRLEN] = ""; + char ip_dst_str[INET_ADDRSTRLEN] = ""; + char src_str[INET_ADDRSTRLEN] = ""; + char grp_str[INET_ADDRSTRLEN] = ""; + struct in_addr ifaddr; + struct igmp_sock *igmp; + + ip_hdr = (const struct ip *)buf; + + if (ip_hdr->ip_p == IPPROTO_IGMP) { + + /* We have the IP packet but we do not know which interface this + * packet was + * received on. Find the interface that is on the same subnet as + * the source + * of the IP packet. + */ + ifp = pim_if_lookup_address_vrf(ip_hdr->ip_src, VRF_DEFAULT); + + if (!ifp) { + if (PIM_DEBUG_MROUTE_DETAIL) { + pim_inet4_dump("", ip_hdr->ip_src, + ip_src_str, sizeof(ip_src_str)); + pim_inet4_dump("", ip_hdr->ip_dst, + ip_dst_str, sizeof(ip_dst_str)); + + zlog_warn( + "%s: igmp kernel upcall could not find usable interface for %s -> %s", + __PRETTY_FUNCTION__, ip_src_str, + ip_dst_str); + } + return 0; + } + pim_ifp = ifp->info; + ifaddr = pim_find_primary_addr(ifp); + igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, + ifaddr); + + if (PIM_DEBUG_MROUTE) { + pim_inet4_dump("", ip_hdr->ip_src, ip_src_str, + sizeof(ip_src_str)); + pim_inet4_dump("", ip_hdr->ip_dst, ip_dst_str, + sizeof(ip_dst_str)); + + zlog_warn( + "%s: igmp kernel upcall on %s(%p) for %s -> %s", + __PRETTY_FUNCTION__, ifp->name, igmp, + ip_src_str, ip_dst_str); + } + if (igmp) + pim_igmp_packet(igmp, (char *)buf, buf_size); + + } else if (ip_hdr->ip_p) { + if (PIM_DEBUG_MROUTE_DETAIL) { + pim_inet4_dump("", ip_hdr->ip_src, src_str, + sizeof(src_str)); + pim_inet4_dump("", ip_hdr->ip_dst, grp_str, + sizeof(grp_str)); + zlog_debug( + "%s: no kernel upcall proto=%d src: %s dst: %s msg_size=%d", + __PRETTY_FUNCTION__, ip_hdr->ip_p, src_str, + grp_str, buf_size); + } + + } else { + msg = (const struct igmpmsg *)buf; + + ifp = pim_if_find_by_vif_index(msg->im_vif); + + if (!ifp) + return 0; + if (PIM_DEBUG_MROUTE) { + pim_inet4_dump("", msg->im_src, src_str, + sizeof(src_str)); + pim_inet4_dump("", msg->im_dst, grp_str, + sizeof(grp_str)); + zlog_warn( + "%s: pim kernel upcall %s type=%d ip_p=%d from fd=%d for (S,G)=(%s,%s) on %s vifi=%d size=%d", + __PRETTY_FUNCTION__, + igmpmsgtype2str[msg->im_msgtype], + msg->im_msgtype, ip_hdr->ip_p, fd, src_str, + grp_str, ifp->name, msg->im_vif, buf_size); + } + + switch (msg->im_msgtype) { + case IGMPMSG_WRONGVIF: + return pim_mroute_msg_wrongvif(fd, ifp, msg); + break; + case IGMPMSG_NOCACHE: + return pim_mroute_msg_nocache(fd, ifp, msg); + break; + case IGMPMSG_WHOLEPKT: + return pim_mroute_msg_wholepkt(fd, ifp, + (const char *)msg); + break; + case IGMPMSG_WRVIFWHOLE: + return pim_mroute_msg_wrvifwhole(fd, ifp, + (const char *)msg); + break; + default: + break; + } + } - return 0; + return 0; } static int mroute_read(struct thread *t) { - static long long count; - char buf[10000]; - int result = 0; - int cont = 1; - int fd; - int rd; - - fd = THREAD_FD(t); - - while (cont) - { - rd = read(fd, buf, sizeof(buf)); - if (rd < 0) { - if (errno == EINTR) - continue; - if (errno == EWOULDBLOCK || errno == EAGAIN) - break; - - if (PIM_DEBUG_MROUTE) - zlog_warn("%s: failure reading fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); - goto done; - } - - result = pim_mroute_msg(fd, buf, rd); - - count++; - if (count % qpim_packet_process == 0) - cont = 0; - } - /* Keep reading */ - done: - mroute_read_on(); + static long long count; + char buf[10000]; + int result = 0; + int cont = 1; + int fd; + int rd; + + fd = THREAD_FD(t); + + while (cont) { + rd = read(fd, buf, sizeof(buf)); + if (rd < 0) { + if (errno == EINTR) + continue; + if (errno == EWOULDBLOCK || errno == EAGAIN) + break; + + if (PIM_DEBUG_MROUTE) + zlog_warn( + "%s: failure reading fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, fd, errno, + safe_strerror(errno)); + goto done; + } + + result = pim_mroute_msg(fd, buf, rd); + + count++; + if (count % qpim_packet_process == 0) + cont = 0; + } +/* Keep reading */ +done: + mroute_read_on(); - return result; + return result; } static void mroute_read_on() { - thread_add_read(master, mroute_read, 0, qpim_mroute_socket_fd, - &qpim_mroute_socket_reader); + thread_add_read(master, mroute_read, 0, qpim_mroute_socket_fd, + &qpim_mroute_socket_reader); } static void mroute_read_off() { - THREAD_OFF(qpim_mroute_socket_reader); + THREAD_OFF(qpim_mroute_socket_reader); } int pim_mroute_socket_enable() { - int fd; + int fd; - if ( pimd_privs.change (ZPRIVS_RAISE) ) - zlog_err ("pim_mroute_socket_enable: could not raise privs, %s", - safe_strerror (errno) ); + if (pimd_privs.change(ZPRIVS_RAISE)) + zlog_err("pim_mroute_socket_enable: could not raise privs, %s", + safe_strerror(errno)); - fd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP); + fd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP); - if ( pimd_privs.change (ZPRIVS_LOWER) ) - zlog_err ("pim_mroute_socket_enable: could not lower privs, %s", - safe_strerror (errno) ); + if (pimd_privs.change(ZPRIVS_LOWER)) + zlog_err("pim_mroute_socket_enable: could not lower privs, %s", + safe_strerror(errno)); - if (fd < 0) { - zlog_warn("Could not create mroute socket: errno=%d: %s", - errno, safe_strerror(errno)); - return -2; - } + if (fd < 0) { + zlog_warn("Could not create mroute socket: errno=%d: %s", errno, + safe_strerror(errno)); + return -2; + } - if (pim_mroute_set(fd, 1)) { - zlog_warn("Could not enable mroute on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - close(fd); - return -3; - } + if (pim_mroute_set(fd, 1)) { + zlog_warn( + "Could not enable mroute on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + close(fd); + return -3; + } - qpim_mroute_socket_fd = fd; + qpim_mroute_socket_fd = fd; - qpim_mroute_socket_creation = pim_time_monotonic_sec(); - mroute_read_on(); + qpim_mroute_socket_creation = pim_time_monotonic_sec(); + mroute_read_on(); - return 0; + return 0; } int pim_mroute_socket_disable() { - if (pim_mroute_set(qpim_mroute_socket_fd, 0)) { - zlog_warn("Could not disable mroute on socket fd=%d: errno=%d: %s", - qpim_mroute_socket_fd, errno, safe_strerror(errno)); - return -2; - } - - if (close(qpim_mroute_socket_fd)) { - zlog_warn("Failure closing mroute socket: fd=%d errno=%d: %s", - qpim_mroute_socket_fd, errno, safe_strerror(errno)); - return -3; - } - - mroute_read_off(); - qpim_mroute_socket_fd = -1; - - return 0; + if (pim_mroute_set(qpim_mroute_socket_fd, 0)) { + zlog_warn( + "Could not disable mroute on socket fd=%d: errno=%d: %s", + qpim_mroute_socket_fd, errno, safe_strerror(errno)); + return -2; + } + + if (close(qpim_mroute_socket_fd)) { + zlog_warn("Failure closing mroute socket: fd=%d errno=%d: %s", + qpim_mroute_socket_fd, errno, safe_strerror(errno)); + return -3; + } + + mroute_read_off(); + qpim_mroute_socket_fd = -1; + + return 0; } /* @@ -701,249 +726,248 @@ int pim_mroute_socket_disable() would be used for multicast forwarding, a corresponding multicast interface must be added to the kernel. */ -int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, unsigned char flags) +int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, + unsigned char flags) { - struct pim_interface *pim_ifp = ifp->info; - struct vifctl vc; - int err; + struct pim_interface *pim_ifp = ifp->info; + struct vifctl vc; + int err; - memset(&vc, 0, sizeof(vc)); - vc.vifc_vifi = pim_ifp->mroute_vif_index; + memset(&vc, 0, sizeof(vc)); + vc.vifc_vifi = pim_ifp->mroute_vif_index; #ifdef VIFF_USE_IFINDEX - vc.vifc_lcl_ifindex = ifp->ifindex; + vc.vifc_lcl_ifindex = ifp->ifindex; #else - if (ifaddr.s_addr == INADDR_ANY) { - zlog_warn("%s: unnumbered interfaces are not supported on this platform", - __PRETTY_FUNCTION__); - return -1; - } - memcpy(&vc.vifc_lcl_addr, &ifaddr, sizeof(vc.vifc_lcl_addr)); + if (ifaddr.s_addr == INADDR_ANY) { + zlog_warn( + "%s: unnumbered interfaces are not supported on this platform", + __PRETTY_FUNCTION__); + return -1; + } + memcpy(&vc.vifc_lcl_addr, &ifaddr, sizeof(vc.vifc_lcl_addr)); #endif - vc.vifc_flags = flags; - vc.vifc_threshold = PIM_MROUTE_MIN_TTL; - vc.vifc_rate_limit = 0; - -#ifdef PIM_DVMRP_TUNNEL - if (vc.vifc_flags & VIFF_TUNNEL) { - memcpy(&vc.vifc_rmt_addr, &vif_remote_addr, sizeof(vc.vifc_rmt_addr)); - } + vc.vifc_flags = flags; + vc.vifc_threshold = PIM_MROUTE_MIN_TTL; + vc.vifc_rate_limit = 0; + +#ifdef PIM_DVMRP_TUNNEL + if (vc.vifc_flags & VIFF_TUNNEL) { + memcpy(&vc.vifc_rmt_addr, &vif_remote_addr, + sizeof(vc.vifc_rmt_addr)); + } #endif - err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_VIF, (void*) &vc, sizeof(vc)); - if (err) { - char ifaddr_str[INET_ADDRSTRLEN]; + err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_VIF, + (void *)&vc, sizeof(vc)); + if (err) { + char ifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", ifaddr, ifaddr_str, sizeof(ifaddr_str)); + pim_inet4_dump("", ifaddr, ifaddr_str, + sizeof(ifaddr_str)); - zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_VIF,vif_index=%d,ifaddr=%s,flag=%d): errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, - qpim_mroute_socket_fd, ifp->ifindex, ifaddr_str, flags, - errno, safe_strerror(errno)); - return -2; - } + zlog_warn( + "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_VIF,vif_index=%d,ifaddr=%s,flag=%d): errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, qpim_mroute_socket_fd, + ifp->ifindex, ifaddr_str, flags, errno, + safe_strerror(errno)); + return -2; + } - return 0; + return 0; } int pim_mroute_del_vif(int vif_index) { - struct vifctl vc; - int err; - - if (PIM_DEBUG_MROUTE) - { - struct interface *ifp = pim_if_find_by_vif_index (vif_index); - zlog_debug ("%s %s: Del Vif %d (%s) ", __FILE__, - __PRETTY_FUNCTION__, vif_index, ifp ? ifp->name : "NULL"); - } - - memset(&vc, 0, sizeof(vc)); - vc.vifc_vifi = vif_index; + struct vifctl vc; + int err; + + if (PIM_DEBUG_MROUTE) { + struct interface *ifp = pim_if_find_by_vif_index(vif_index); + zlog_debug("%s %s: Del Vif %d (%s) ", __FILE__, + __PRETTY_FUNCTION__, vif_index, + ifp ? ifp->name : "NULL"); + } - err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_VIF, (void*) &vc, sizeof(vc)); - if (err) { - zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_VIF,vif_index=%d): errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, - qpim_mroute_socket_fd, vif_index, - errno, safe_strerror(errno)); - return -2; - } + memset(&vc, 0, sizeof(vc)); + vc.vifc_vifi = vif_index; + + err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_VIF, + (void *)&vc, sizeof(vc)); + if (err) { + zlog_warn( + "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_VIF,vif_index=%d): errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, qpim_mroute_socket_fd, + vif_index, errno, safe_strerror(errno)); + return -2; + } - return 0; + return 0; } int pim_mroute_add(struct channel_oil *c_oil, const char *name) { - int err; - int orig = 0; - int orig_iif_vif = 0; - - qpim_mroute_add_last = pim_time_monotonic_sec(); - ++qpim_mroute_add_events; - - /* Do not install route if incoming interface is undefined. */ - if (c_oil->oil.mfcc_parent >= MAXVIFS) - { - if (PIM_DEBUG_MROUTE) - { - char buf[1000]; - zlog_debug("%s(%s) %s Attempting to add vifi that is invalid to mroute table", - __PRETTY_FUNCTION__, name, pim_channel_oil_dump (c_oil, buf, sizeof(buf))); - } - return -2; - } - - /* The linux kernel *expects* the incoming - * vif to be part of the outgoing list - * in the case of a (*,G). - */ - if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) - { - orig = c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent]; - c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = 1; - } + int err; + int orig = 0; + int orig_iif_vif = 0; + + qpim_mroute_add_last = pim_time_monotonic_sec(); + ++qpim_mroute_add_events; + + /* Do not install route if incoming interface is undefined. */ + if (c_oil->oil.mfcc_parent >= MAXVIFS) { + if (PIM_DEBUG_MROUTE) { + char buf[1000]; + zlog_debug( + "%s(%s) %s Attempting to add vifi that is invalid to mroute table", + __PRETTY_FUNCTION__, name, + pim_channel_oil_dump(c_oil, buf, sizeof(buf))); + } + return -2; + } - /* - * If we have an unresolved cache entry for the S,G - * it is owned by the pimreg for the incoming IIF - * So set pimreg as the IIF temporarily to cause - * the packets to be forwarded. Then set it - * to the correct IIF afterwords. - */ - if (!c_oil->installed && c_oil->oil.mfcc_origin.s_addr != INADDR_ANY && - c_oil->oil.mfcc_parent != 0) - { - orig_iif_vif = c_oil->oil.mfcc_parent; - c_oil->oil.mfcc_parent = 0; - } - err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC, - &c_oil->oil, sizeof(c_oil->oil)); + /* The linux kernel *expects* the incoming + * vif to be part of the outgoing list + * in the case of a (*,G). + */ + if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) { + orig = c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent]; + c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = 1; + } - if (!err && !c_oil->installed && c_oil->oil.mfcc_origin.s_addr != INADDR_ANY && - orig_iif_vif != 0) - { - c_oil->oil.mfcc_parent = orig_iif_vif; - err = setsockopt (qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC, - &c_oil->oil, sizeof (c_oil->oil)); - } + /* + * If we have an unresolved cache entry for the S,G + * it is owned by the pimreg for the incoming IIF + * So set pimreg as the IIF temporarily to cause + * the packets to be forwarded. Then set it + * to the correct IIF afterwords. + */ + if (!c_oil->installed && c_oil->oil.mfcc_origin.s_addr != INADDR_ANY + && c_oil->oil.mfcc_parent != 0) { + orig_iif_vif = c_oil->oil.mfcc_parent; + c_oil->oil.mfcc_parent = 0; + } + err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC, + &c_oil->oil, sizeof(c_oil->oil)); + + if (!err && !c_oil->installed + && c_oil->oil.mfcc_origin.s_addr != INADDR_ANY + && orig_iif_vif != 0) { + c_oil->oil.mfcc_parent = orig_iif_vif; + err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC, + &c_oil->oil, sizeof(c_oil->oil)); + } - if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) - c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = orig; + if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY) + c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = orig; - if (err) { - zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_MFC): errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, - qpim_mroute_socket_fd, - errno, safe_strerror(errno)); - return -2; - } + if (err) { + zlog_warn( + "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_MFC): errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, qpim_mroute_socket_fd, + errno, safe_strerror(errno)); + return -2; + } - if (PIM_DEBUG_MROUTE) - { - char buf[1000]; - zlog_debug("%s(%s), Added Route: %s", - __PRETTY_FUNCTION__, name, - pim_channel_oil_dump (c_oil, buf, sizeof(buf))); - } + if (PIM_DEBUG_MROUTE) { + char buf[1000]; + zlog_debug("%s(%s), Added Route: %s", __PRETTY_FUNCTION__, name, + pim_channel_oil_dump(c_oil, buf, sizeof(buf))); + } - c_oil->installed = 1; - return 0; + c_oil->installed = 1; + return 0; } -int pim_mroute_del (struct channel_oil *c_oil, const char *name) +int pim_mroute_del(struct channel_oil *c_oil, const char *name) { - int err; - - qpim_mroute_del_last = pim_time_monotonic_sec(); - ++qpim_mroute_del_events; + int err; + + qpim_mroute_del_last = pim_time_monotonic_sec(); + ++qpim_mroute_del_events; + + if (!c_oil->installed) { + if (PIM_DEBUG_MROUTE) { + char buf[1000]; + zlog_debug( + "%s %s: vifi %d for route is %s not installed, do not need to send del req. ", + __FILE__, __PRETTY_FUNCTION__, + c_oil->oil.mfcc_parent, + pim_channel_oil_dump(c_oil, buf, sizeof(buf))); + } + return -2; + } - if (!c_oil->installed) - { - if (PIM_DEBUG_MROUTE) - { - char buf[1000]; - zlog_debug("%s %s: vifi %d for route is %s not installed, do not need to send del req. ", - __FILE__, __PRETTY_FUNCTION__, c_oil->oil.mfcc_parent, - pim_channel_oil_dump (c_oil, buf, sizeof(buf))); - } - return -2; - } + err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_MFC, + &c_oil->oil, sizeof(c_oil->oil)); + if (err) { + if (PIM_DEBUG_MROUTE) + zlog_warn( + "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_MFC): errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, + qpim_mroute_socket_fd, errno, + safe_strerror(errno)); + return -2; + } - err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_MFC, &c_oil->oil, sizeof(c_oil->oil)); - if (err) { - if (PIM_DEBUG_MROUTE) - zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_MFC): errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, - qpim_mroute_socket_fd, - errno, safe_strerror(errno)); - return -2; - } - - if (PIM_DEBUG_MROUTE) - { - char buf[1000]; - zlog_debug("%s(%s), Deleted Route: %s", - __PRETTY_FUNCTION__, name, - pim_channel_oil_dump (c_oil, buf, sizeof(buf))); - } + if (PIM_DEBUG_MROUTE) { + char buf[1000]; + zlog_debug("%s(%s), Deleted Route: %s", __PRETTY_FUNCTION__, + name, pim_channel_oil_dump(c_oil, buf, sizeof(buf))); + } - //Reset kernel installed flag - c_oil->installed = 0; + // Reset kernel installed flag + c_oil->installed = 0; - return 0; + return 0; } -void -pim_mroute_update_counters (struct channel_oil *c_oil) +void pim_mroute_update_counters(struct channel_oil *c_oil) { - struct sioc_sg_req sgreq; - - c_oil->cc.oldpktcnt = c_oil->cc.pktcnt; - c_oil->cc.oldbytecnt = c_oil->cc.bytecnt; - c_oil->cc.oldwrong_if = c_oil->cc.wrong_if; - - if (!c_oil->installed) - { - c_oil->cc.lastused = 100 * qpim_keep_alive_time; - if (PIM_DEBUG_MROUTE) - { - struct prefix_sg sg; - - sg.src = c_oil->oil.mfcc_origin; - sg.grp = c_oil->oil.mfcc_mcastgrp; - if (PIM_DEBUG_MROUTE) - zlog_debug("Channel(%s) is not installed no need to collect data from kernel", - pim_str_sg_dump (&sg)); + struct sioc_sg_req sgreq; + + c_oil->cc.oldpktcnt = c_oil->cc.pktcnt; + c_oil->cc.oldbytecnt = c_oil->cc.bytecnt; + c_oil->cc.oldwrong_if = c_oil->cc.wrong_if; + + if (!c_oil->installed) { + c_oil->cc.lastused = 100 * qpim_keep_alive_time; + if (PIM_DEBUG_MROUTE) { + struct prefix_sg sg; + + sg.src = c_oil->oil.mfcc_origin; + sg.grp = c_oil->oil.mfcc_mcastgrp; + if (PIM_DEBUG_MROUTE) + zlog_debug( + "Channel(%s) is not installed no need to collect data from kernel", + pim_str_sg_dump(&sg)); + } + return; } - return; - } - - memset (&sgreq, 0, sizeof(sgreq)); - sgreq.src = c_oil->oil.mfcc_origin; - sgreq.grp = c_oil->oil.mfcc_mcastgrp; - - pim_zlookup_sg_statistics (c_oil); - if (ioctl (qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) - { - if (PIM_DEBUG_MROUTE) - { - struct prefix_sg sg; - sg.src = c_oil->oil.mfcc_origin; - sg.grp = c_oil->oil.mfcc_mcastgrp; - - zlog_warn ("ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s): errno=%d: %s", - (unsigned long)SIOCGETSGCNT, - pim_str_sg_dump (&sg), - errno, - safe_strerror(errno)); + memset(&sgreq, 0, sizeof(sgreq)); + sgreq.src = c_oil->oil.mfcc_origin; + sgreq.grp = c_oil->oil.mfcc_mcastgrp; + + pim_zlookup_sg_statistics(c_oil); + if (ioctl(qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) { + if (PIM_DEBUG_MROUTE) { + struct prefix_sg sg; + + sg.src = c_oil->oil.mfcc_origin; + sg.grp = c_oil->oil.mfcc_mcastgrp; + + zlog_warn( + "ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s): errno=%d: %s", + (unsigned long)SIOCGETSGCNT, + pim_str_sg_dump(&sg), errno, + safe_strerror(errno)); + } + return; } - return; - } - c_oil->cc.pktcnt = sgreq.pktcnt; - c_oil->cc.bytecnt = sgreq.bytecnt; - c_oil->cc.wrong_if = sgreq.wrong_if; + c_oil->cc.pktcnt = sgreq.pktcnt; + c_oil->cc.bytecnt = sgreq.bytecnt; + c_oil->cc.wrong_if = sgreq.wrong_if; - return; + return; } diff --git a/pimd/pim_mroute.h b/pimd/pim_mroute.h index 36dce8e61..eb6c40b67 100644 --- a/pimd/pim_mroute.h +++ b/pimd/pim_mroute.h @@ -73,25 +73,25 @@ typedef unsigned short vifi_t; #ifndef HAVE_STRUCT_VIFCTL struct vifctl { - vifi_t vifc_vifi; /* Index of VIF */ - unsigned char vifc_flags; /* VIFF_ flags */ - unsigned char vifc_threshold; /* ttl limit */ - unsigned int vifc_rate_limit; /* Rate limiter values (NI) */ - struct in_addr vifc_lcl_addr; /* Our address */ - struct in_addr vifc_rmt_addr; /* IPIP tunnel addr */ + vifi_t vifc_vifi; /* Index of VIF */ + unsigned char vifc_flags; /* VIFF_ flags */ + unsigned char vifc_threshold; /* ttl limit */ + unsigned int vifc_rate_limit; /* Rate limiter values (NI) */ + struct in_addr vifc_lcl_addr; /* Our address */ + struct in_addr vifc_rmt_addr; /* IPIP tunnel addr */ }; #endif #ifndef HAVE_STRUCT_MFCCTL struct mfcctl { - struct in_addr mfcc_origin; /* Origin of mcast */ - struct in_addr mfcc_mcastgrp; /* Group in question */ - vifi_t mfcc_parent; /* Where it arrived */ - unsigned char mfcc_ttls[MAXVIFS]; /* Where it is going */ - unsigned int mfcc_pkt_cnt; /* pkt count for src-grp */ - unsigned int mfcc_byte_cnt; - unsigned int mfcc_wrong_if; - int mfcc_expire; + struct in_addr mfcc_origin; /* Origin of mcast */ + struct in_addr mfcc_mcastgrp; /* Group in question */ + vifi_t mfcc_parent; /* Where it arrived */ + unsigned char mfcc_ttls[MAXVIFS]; /* Where it is going */ + unsigned int mfcc_pkt_cnt; /* pkt count for src-grp */ + unsigned int mfcc_byte_cnt; + unsigned int mfcc_wrong_if; + int mfcc_expire; }; #endif @@ -107,11 +107,11 @@ struct mfcctl { */ #ifndef HAVE_STRUCT_SIOC_SG_REQ struct sioc_sg_req { - struct in_addr src; - struct in_addr grp; - unsigned long pktcnt; - unsigned long bytecnt; - unsigned long wrong_if; + struct in_addr src; + struct in_addr grp; + unsigned long pktcnt; + unsigned long bytecnt; + unsigned long wrong_if; }; #endif @@ -126,11 +126,11 @@ struct sioc_sg_req { */ #ifndef HAVE_STRUCT_SIOC_VIF_REQ struct sioc_vif_req { - vifi_t vifi; /* Which iface */ - unsigned long icount; /* In packets */ - unsigned long ocount; /* Out packets */ - unsigned long ibytes; /* In bytes */ - unsigned long obytes; /* Out bytes */ + vifi_t vifi; /* Which iface */ + unsigned long icount; /* In packets */ + unsigned long ocount; /* Out packets */ + unsigned long ibytes; /* In bytes */ + unsigned long obytes; /* Out bytes */ }; #endif @@ -144,14 +144,13 @@ struct sioc_vif_req { #endif #ifndef HAVE_STRUCT_IGMPMSG -struct igmpmsg -{ - uint32_t unused1,unused2; - unsigned char im_msgtype; /* What is this */ - unsigned char im_mbz; /* Must be zero */ - unsigned char im_vif; /* Interface (this ought to be a vifi_t!) */ - unsigned char unused3; - struct in_addr im_src,im_dst; +struct igmpmsg { + uint32_t unused1, unused2; + unsigned char im_msgtype; /* What is this */ + unsigned char im_mbz; /* Must be zero */ + unsigned char im_vif; /* Interface (this ought to be a vifi_t!) */ + unsigned char unused3; + struct in_addr im_src, im_dst; }; #endif #endif @@ -167,7 +166,8 @@ struct igmpmsg int pim_mroute_socket_enable(void); int pim_mroute_socket_disable(void); -int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, unsigned char flags); +int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, + unsigned char flags); int pim_mroute_del_vif(int vif_index); int pim_mroute_add(struct channel_oil *c_oil, const char *name); @@ -175,5 +175,5 @@ int pim_mroute_del(struct channel_oil *c_oil, const char *name); int pim_mroute_msg(int fd, const char *buf, int buf_size); -void pim_mroute_update_counters (struct channel_oil *c_oil); +void pim_mroute_update_counters(struct channel_oil *c_oil); #endif /* PIM_MROUTE_H */ diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 170692e7f..0f653e70a 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -47,119 +47,119 @@ struct pim_msdp pim_msdp, *msdp = &pim_msdp; static void pim_msdp_peer_listen(struct pim_msdp_peer *mp); static void pim_msdp_peer_cr_timer_setup(struct pim_msdp_peer *mp, bool start); static void pim_msdp_peer_ka_timer_setup(struct pim_msdp_peer *mp, bool start); -static void pim_msdp_peer_hold_timer_setup(struct pim_msdp_peer *mp, bool start); +static void pim_msdp_peer_hold_timer_setup(struct pim_msdp_peer *mp, + bool start); static void pim_msdp_peer_free(struct pim_msdp_peer *mp); static void pim_msdp_enable(void); static void pim_msdp_sa_adv_timer_setup(bool start); -static void pim_msdp_sa_deref(struct pim_msdp_sa *sa, enum pim_msdp_sa_flags flags); +static void pim_msdp_sa_deref(struct pim_msdp_sa *sa, + enum pim_msdp_sa_flags flags); static int pim_msdp_mg_mbr_comp(const void *p1, const void *p2); static void pim_msdp_mg_mbr_free(struct pim_msdp_mg_mbr *mbr); -static void pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg, struct pim_msdp_mg_mbr *mbr); +static void pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg, + struct pim_msdp_mg_mbr *mbr); /************************ SA cache management ******************************/ -static void -pim_msdp_sa_timer_expiry_log(struct pim_msdp_sa *sa, const char *timer_str) +static void pim_msdp_sa_timer_expiry_log(struct pim_msdp_sa *sa, + const char *timer_str) { - zlog_debug("MSDP SA %s %s timer expired", sa->sg_str, timer_str); + zlog_debug("MSDP SA %s %s timer expired", sa->sg_str, timer_str); } /* RFC-3618:Sec-5.1 - global active source advertisement timer */ -static int -pim_msdp_sa_adv_timer_cb(struct thread *t) +static int pim_msdp_sa_adv_timer_cb(struct thread *t) { - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA advertisment timer expired"); - } + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA advertisment timer expired"); + } - pim_msdp_sa_adv_timer_setup(true /* start */); - pim_msdp_pkt_sa_tx(); - return 0; + pim_msdp_sa_adv_timer_setup(true /* start */); + pim_msdp_pkt_sa_tx(); + return 0; } -static void -pim_msdp_sa_adv_timer_setup(bool start) +static void pim_msdp_sa_adv_timer_setup(bool start) { - THREAD_OFF(msdp->sa_adv_timer); - if (start) { - thread_add_timer(msdp->master, pim_msdp_sa_adv_timer_cb, NULL, - PIM_MSDP_SA_ADVERTISMENT_TIME, &msdp->sa_adv_timer); - } + THREAD_OFF(msdp->sa_adv_timer); + if (start) { + thread_add_timer(msdp->master, pim_msdp_sa_adv_timer_cb, NULL, + PIM_MSDP_SA_ADVERTISMENT_TIME, + &msdp->sa_adv_timer); + } } /* RFC-3618:Sec-5.3 - SA cache state timer */ -static int -pim_msdp_sa_state_timer_cb(struct thread *t) +static int pim_msdp_sa_state_timer_cb(struct thread *t) { - struct pim_msdp_sa *sa; + struct pim_msdp_sa *sa; - sa = THREAD_ARG(t); + sa = THREAD_ARG(t); - if (PIM_DEBUG_MSDP_EVENTS) { - pim_msdp_sa_timer_expiry_log(sa, "state"); - } + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_sa_timer_expiry_log(sa, "state"); + } - pim_msdp_sa_deref(sa, PIM_MSDP_SAF_PEER); - return 0; + pim_msdp_sa_deref(sa, PIM_MSDP_SAF_PEER); + return 0; } -static void -pim_msdp_sa_state_timer_setup(struct pim_msdp_sa *sa, bool start) +static void pim_msdp_sa_state_timer_setup(struct pim_msdp_sa *sa, bool start) { - THREAD_OFF(sa->sa_state_timer); - if (start) { - thread_add_timer(msdp->master, pim_msdp_sa_state_timer_cb, sa, - PIM_MSDP_SA_HOLD_TIME, &sa->sa_state_timer); - } + THREAD_OFF(sa->sa_state_timer); + if (start) { + thread_add_timer(msdp->master, pim_msdp_sa_state_timer_cb, sa, + PIM_MSDP_SA_HOLD_TIME, &sa->sa_state_timer); + } } -static void -pim_msdp_sa_upstream_del(struct pim_msdp_sa *sa) +static void pim_msdp_sa_upstream_del(struct pim_msdp_sa *sa) { - struct pim_upstream *up = sa->up; - if (!up) { - return; - } + struct pim_upstream *up = sa->up; + if (!up) { + return; + } - sa->up = NULL; - if (PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags)) { - PIM_UPSTREAM_FLAG_UNSET_SRC_MSDP(up->flags); - sa->flags |= PIM_MSDP_SAF_UP_DEL_IN_PROG; - pim_upstream_del(up, __PRETTY_FUNCTION__); - sa->flags &= ~PIM_MSDP_SAF_UP_DEL_IN_PROG; - } + sa->up = NULL; + if (PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags)) { + PIM_UPSTREAM_FLAG_UNSET_SRC_MSDP(up->flags); + sa->flags |= PIM_MSDP_SAF_UP_DEL_IN_PROG; + pim_upstream_del(up, __PRETTY_FUNCTION__); + sa->flags &= ~PIM_MSDP_SAF_UP_DEL_IN_PROG; + } - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA %s de-referenced SPT", sa->sg_str); - } + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA %s de-referenced SPT", sa->sg_str); + } } -static bool -pim_msdp_sa_upstream_add_ok(struct pim_msdp_sa *sa, struct pim_upstream *xg_up) +static bool pim_msdp_sa_upstream_add_ok(struct pim_msdp_sa *sa, + struct pim_upstream *xg_up) { - if (!(sa->flags & PIM_MSDP_SAF_PEER)) { - /* SA should have been rxed from a peer */ - return false; - } - /* check if we are RP */ - if (!I_am_RP(sa->sg.grp)) { - return false; - } + if (!(sa->flags & PIM_MSDP_SAF_PEER)) { + /* SA should have been rxed from a peer */ + return false; + } + /* check if we are RP */ + if (!I_am_RP(sa->sg.grp)) { + return false; + } - /* check if we have a (*, G) with a non-empty immediate OIL */ - if (!xg_up) { - struct prefix_sg sg; + /* check if we have a (*, G) with a non-empty immediate OIL */ + if (!xg_up) { + struct prefix_sg sg; - memset(&sg, 0, sizeof(sg)); - sg.grp = sa->sg.grp; + memset(&sg, 0, sizeof(sg)); + sg.grp = sa->sg.grp; - xg_up = pim_upstream_find(&sg); - } - if (!xg_up || (xg_up->join_state != PIM_UPSTREAM_JOINED)) { - /* join desired will be true for such (*, G) entries so we will - * just look at join_state and let the PIM state machine do the rest of - * the magic */ - return false; - } + xg_up = pim_upstream_find(&sg); + } + if (!xg_up || (xg_up->join_state != PIM_UPSTREAM_JOINED)) { + /* join desired will be true for such (*, G) entries so we will + * just look at join_state and let the PIM state machine do the + * rest of + * the magic */ + return false; + } - return true; + return true; } /* Upstream add evaluation needs to happen everytime - @@ -170,164 +170,164 @@ pim_msdp_sa_upstream_add_ok(struct pim_msdp_sa *sa, struct pim_upstream *xg_up) * (considering #4); but just in case an entry gets nuked without * upstream state transition * */ -static void -pim_msdp_sa_upstream_update(struct pim_msdp_sa *sa, - struct pim_upstream *xg_up, const char *ctx) -{ - struct pim_upstream *up; - - if (!pim_msdp_sa_upstream_add_ok(sa, xg_up)) { - pim_msdp_sa_upstream_del(sa); - return; - } - - if (sa->up) { - /* nothing to do */ - return; - } - - up = pim_upstream_find(&sa->sg); - if (up && (PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags))) { - /* somehow we lost track of the upstream ptr? best log it */ - sa->up = up; - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA %s SPT reference missing", sa->sg_str); - } - return; - } - - /* RFC3618: "RP triggers a (S, G) join event towards the data source - * as if a JP message was rxed addressed to the RP itself." */ - up = pim_upstream_add(&sa->sg, NULL /* iif */, - PIM_UPSTREAM_FLAG_MASK_SRC_MSDP, - __PRETTY_FUNCTION__); - - sa->up = up; - if (up) { - /* update inherited oil */ - pim_upstream_inherited_olist(up); - /* should we also start the kat in parallel? we will need it when the - * SA ages out */ - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA %s referenced SPT", sa->sg_str); - } - } else { - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA %s SPT reference failed", sa->sg_str); - } - } +static void pim_msdp_sa_upstream_update(struct pim_msdp_sa *sa, + struct pim_upstream *xg_up, + const char *ctx) +{ + struct pim_upstream *up; + + if (!pim_msdp_sa_upstream_add_ok(sa, xg_up)) { + pim_msdp_sa_upstream_del(sa); + return; + } + + if (sa->up) { + /* nothing to do */ + return; + } + + up = pim_upstream_find(&sa->sg); + if (up && (PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags))) { + /* somehow we lost track of the upstream ptr? best log it */ + sa->up = up; + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA %s SPT reference missing", + sa->sg_str); + } + return; + } + + /* RFC3618: "RP triggers a (S, G) join event towards the data source + * as if a JP message was rxed addressed to the RP itself." */ + up = pim_upstream_add(&sa->sg, NULL /* iif */, + PIM_UPSTREAM_FLAG_MASK_SRC_MSDP, + __PRETTY_FUNCTION__); + + sa->up = up; + if (up) { + /* update inherited oil */ + pim_upstream_inherited_olist(up); + /* should we also start the kat in parallel? we will need it + * when the + * SA ages out */ + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA %s referenced SPT", sa->sg_str); + } + } else { + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA %s SPT reference failed", + sa->sg_str); + } + } } /* release all mem associated with a sa */ -static void -pim_msdp_sa_free(struct pim_msdp_sa *sa) +static void pim_msdp_sa_free(struct pim_msdp_sa *sa) { - XFREE(MTYPE_PIM_MSDP_SA, sa); + XFREE(MTYPE_PIM_MSDP_SA, sa); } -static struct pim_msdp_sa * -pim_msdp_sa_new(struct prefix_sg *sg, struct in_addr rp) +static struct pim_msdp_sa *pim_msdp_sa_new(struct prefix_sg *sg, + struct in_addr rp) { - struct pim_msdp_sa *sa; + struct pim_msdp_sa *sa; - sa = XCALLOC(MTYPE_PIM_MSDP_SA, sizeof(*sa)); - if (!sa) { - zlog_err("%s: PIM XCALLOC(%zu) failure", - __PRETTY_FUNCTION__, sizeof(*sa)); - return NULL; - } + sa = XCALLOC(MTYPE_PIM_MSDP_SA, sizeof(*sa)); + if (!sa) { + zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, + sizeof(*sa)); + return NULL; + } - sa->sg = *sg; - pim_str_sg_set(sg, sa->sg_str); - sa->rp = rp; - sa->uptime = pim_time_monotonic_sec(); + sa->sg = *sg; + pim_str_sg_set(sg, sa->sg_str); + sa->rp = rp; + sa->uptime = pim_time_monotonic_sec(); - /* insert into misc tables for easy access */ - sa = hash_get(msdp->sa_hash, sa, hash_alloc_intern); - if (!sa) { - zlog_err("%s: PIM hash get failure", __PRETTY_FUNCTION__); - pim_msdp_sa_free(sa); - return NULL; - } - listnode_add_sort(msdp->sa_list, sa); + /* insert into misc tables for easy access */ + sa = hash_get(msdp->sa_hash, sa, hash_alloc_intern); + if (!sa) { + zlog_err("%s: PIM hash get failure", __PRETTY_FUNCTION__); + pim_msdp_sa_free(sa); + return NULL; + } + listnode_add_sort(msdp->sa_list, sa); - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA %s created", sa->sg_str); - } + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA %s created", sa->sg_str); + } - return sa; + return sa; } -static struct pim_msdp_sa * -pim_msdp_sa_find(struct prefix_sg *sg) +static struct pim_msdp_sa *pim_msdp_sa_find(struct prefix_sg *sg) { - struct pim_msdp_sa lookup; + struct pim_msdp_sa lookup; - lookup.sg = *sg; - return hash_lookup(msdp->sa_hash, &lookup); + lookup.sg = *sg; + return hash_lookup(msdp->sa_hash, &lookup); } -static struct pim_msdp_sa * -pim_msdp_sa_add(struct prefix_sg *sg, struct in_addr rp) +static struct pim_msdp_sa *pim_msdp_sa_add(struct prefix_sg *sg, + struct in_addr rp) { - struct pim_msdp_sa *sa; + struct pim_msdp_sa *sa; - sa = pim_msdp_sa_find(sg); - if (sa) { - return sa; - } + sa = pim_msdp_sa_find(sg); + if (sa) { + return sa; + } - return pim_msdp_sa_new(sg, rp); + return pim_msdp_sa_new(sg, rp); } -static void -pim_msdp_sa_del(struct pim_msdp_sa * sa) +static void pim_msdp_sa_del(struct pim_msdp_sa *sa) { - /* this is somewhat redundant - still want to be careful not to leave - * stale upstream references */ - pim_msdp_sa_upstream_del(sa); + /* this is somewhat redundant - still want to be careful not to leave + * stale upstream references */ + pim_msdp_sa_upstream_del(sa); - /* stop timers */ - pim_msdp_sa_state_timer_setup(sa, false /* start */); + /* stop timers */ + pim_msdp_sa_state_timer_setup(sa, false /* start */); - /* remove the entry from various tables */ - listnode_delete(msdp->sa_list, sa); - hash_release(msdp->sa_hash, sa); + /* remove the entry from various tables */ + listnode_delete(msdp->sa_list, sa); + hash_release(msdp->sa_hash, sa); - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA %s deleted", sa->sg_str); - } + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA %s deleted", sa->sg_str); + } - /* free up any associated memory */ - pim_msdp_sa_free(sa); + /* free up any associated memory */ + pim_msdp_sa_free(sa); } -static void -pim_msdp_sa_peer_ip_set(struct pim_msdp_sa *sa, struct pim_msdp_peer *mp, struct in_addr rp) +static void pim_msdp_sa_peer_ip_set(struct pim_msdp_sa *sa, + struct pim_msdp_peer *mp, struct in_addr rp) { - struct pim_msdp_peer *old_mp; + struct pim_msdp_peer *old_mp; - /* optimize the "no change" case as it will happen - * frequently/periodically */ - if (mp && (sa->peer.s_addr == mp->peer.s_addr)) { - return; - } + /* optimize the "no change" case as it will happen + * frequently/periodically */ + if (mp && (sa->peer.s_addr == mp->peer.s_addr)) { + return; + } - /* any time the peer ip changes also update the rp address */ - if (PIM_INADDR_ISNOT_ANY(sa->peer)) { - old_mp = pim_msdp_peer_find(sa->peer); - if (old_mp && old_mp->sa_cnt) { - --old_mp->sa_cnt; - } - } + /* any time the peer ip changes also update the rp address */ + if (PIM_INADDR_ISNOT_ANY(sa->peer)) { + old_mp = pim_msdp_peer_find(sa->peer); + if (old_mp && old_mp->sa_cnt) { + --old_mp->sa_cnt; + } + } - if (mp) { - ++mp->sa_cnt; - sa->peer = mp->peer; - } else { - sa->peer.s_addr = PIM_NET_INADDR_ANY; - } - sa->rp = rp; + if (mp) { + ++mp->sa_cnt; + sa->peer = mp->peer; + } else { + sa->peer.s_addr = PIM_NET_INADDR_ANY; + } + sa->rp = rp; } /* When a local active-source is removed there is no way to withdraw the @@ -335,88 +335,93 @@ pim_msdp_sa_peer_ip_set(struct pim_msdp_sa *sa, struct pim_msdp_peer *mp, struct * not be sent in supsequent SA updates. Peers will consequently timeout the * SA. * Similarly a "peer-added" SA is never explicitly deleted. It is simply - * aged out overtime if not seen in the SA updates from the peers. + * aged out overtime if not seen in the SA updates from the peers. * XXX: should we provide a knob to drop entries learnt from a peer when the * peer goes down? */ -static void -pim_msdp_sa_deref(struct pim_msdp_sa *sa, enum pim_msdp_sa_flags flags) -{ - bool update_up = false; - - if ((sa->flags &PIM_MSDP_SAF_LOCAL)) { - if (flags & PIM_MSDP_SAF_LOCAL) { - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA %s local reference removed", sa->sg_str); - } - if (msdp->local_cnt) - --msdp->local_cnt; - } - } - - if ((sa->flags &PIM_MSDP_SAF_PEER)) { - if (flags & PIM_MSDP_SAF_PEER) { - struct in_addr rp; - - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA %s peer reference removed", sa->sg_str); - } - pim_msdp_sa_state_timer_setup(sa, false /* start */); - rp.s_addr = INADDR_ANY; - pim_msdp_sa_peer_ip_set(sa, NULL /* mp */, rp); - /* if peer ref was removed we need to remove the msdp reference on the - * msdp entry */ - update_up = true; - } - } - - sa->flags &= ~flags; - if (update_up) { - pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "sa-deref"); - } - - if (!(sa->flags & PIM_MSDP_SAF_REF)) { - pim_msdp_sa_del(sa); - } -} - -void -pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, - struct in_addr rp) -{ - struct pim_msdp_sa *sa; - - sa = pim_msdp_sa_add(sg, rp); - if (!sa) { - return; - } - - /* reference it */ - if (mp) { - if (!(sa->flags & PIM_MSDP_SAF_PEER)) { - sa->flags |= PIM_MSDP_SAF_PEER; - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA %s added by peer", sa->sg_str); - } - } - pim_msdp_sa_peer_ip_set(sa, mp, rp); - /* start/re-start the state timer to prevent cache expiry */ - pim_msdp_sa_state_timer_setup(sa, true /* start */); - /* We re-evaluate SA "SPT-trigger" everytime we hear abt it from a - * peer. XXX: If this becomes too much of a periodic overhead we - * can make it event based */ - pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "peer-ref"); - } else { - if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { - sa->flags |= PIM_MSDP_SAF_LOCAL; - ++msdp->local_cnt; - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA %s added locally", sa->sg_str); - } - /* send an immediate SA update to peers */ - pim_msdp_pkt_sa_tx_one(sa); - } - sa->flags &= ~PIM_MSDP_SAF_STALE; - } +static void pim_msdp_sa_deref(struct pim_msdp_sa *sa, + enum pim_msdp_sa_flags flags) +{ + bool update_up = false; + + if ((sa->flags & PIM_MSDP_SAF_LOCAL)) { + if (flags & PIM_MSDP_SAF_LOCAL) { + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA %s local reference removed", + sa->sg_str); + } + if (msdp->local_cnt) + --msdp->local_cnt; + } + } + + if ((sa->flags & PIM_MSDP_SAF_PEER)) { + if (flags & PIM_MSDP_SAF_PEER) { + struct in_addr rp; + + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA %s peer reference removed", + sa->sg_str); + } + pim_msdp_sa_state_timer_setup(sa, false /* start */); + rp.s_addr = INADDR_ANY; + pim_msdp_sa_peer_ip_set(sa, NULL /* mp */, rp); + /* if peer ref was removed we need to remove the msdp + * reference on the + * msdp entry */ + update_up = true; + } + } + + sa->flags &= ~flags; + if (update_up) { + pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "sa-deref"); + } + + if (!(sa->flags & PIM_MSDP_SAF_REF)) { + pim_msdp_sa_del(sa); + } +} + +void pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, + struct in_addr rp) +{ + struct pim_msdp_sa *sa; + + sa = pim_msdp_sa_add(sg, rp); + if (!sa) { + return; + } + + /* reference it */ + if (mp) { + if (!(sa->flags & PIM_MSDP_SAF_PEER)) { + sa->flags |= PIM_MSDP_SAF_PEER; + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA %s added by peer", + sa->sg_str); + } + } + pim_msdp_sa_peer_ip_set(sa, mp, rp); + /* start/re-start the state timer to prevent cache expiry */ + pim_msdp_sa_state_timer_setup(sa, true /* start */); + /* We re-evaluate SA "SPT-trigger" everytime we hear abt it from + * a + * peer. XXX: If this becomes too much of a periodic overhead we + * can make it event based */ + pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "peer-ref"); + } else { + if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { + sa->flags |= PIM_MSDP_SAF_LOCAL; + ++msdp->local_cnt; + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP SA %s added locally", + sa->sg_str); + } + /* send an immediate SA update to peers */ + pim_msdp_pkt_sa_tx_one(sa); + } + sa->flags &= ~PIM_MSDP_SAF_STALE; + } } /* The following criteria must be met to originate an SA from the MSDP @@ -431,93 +436,100 @@ pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, * b. We rxed a pim register (null or data encapsulated) within the last * (3 * (1.5 * register_suppression_timer))). */ -static bool -pim_msdp_sa_local_add_ok(struct pim_upstream *up) +static bool pim_msdp_sa_local_add_ok(struct pim_upstream *up) { - if (!(msdp->flags & PIM_MSDPF_ENABLE)) { - return false; - } + if (!(msdp->flags & PIM_MSDPF_ENABLE)) { + return false; + } - if (!up->t_ka_timer) { - /* stream is not active */ - return false; - } + if (!up->t_ka_timer) { + /* stream is not active */ + return false; + } - if (!I_am_RP(up->sg.grp)) { - /* we are not RP for the group */ - return false; - } + if (!I_am_RP(up->sg.grp)) { + /* we are not RP for the group */ + return false; + } - /* we are the FHR-DR for this stream or we are RP and have seen registers - * from a FHR for this source */ - if (PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) || up->t_msdp_reg_timer) { - return true; - } + /* we are the FHR-DR for this stream or we are RP and have seen + * registers + * from a FHR for this source */ + if (PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) || up->t_msdp_reg_timer) { + return true; + } - return false; + return false; } -static void -pim_msdp_sa_local_add(struct prefix_sg *sg) +static void pim_msdp_sa_local_add(struct prefix_sg *sg) { - struct in_addr rp; - rp.s_addr = 0; - pim_msdp_sa_ref(NULL /* mp */, sg, rp); + struct in_addr rp; + rp.s_addr = 0; + pim_msdp_sa_ref(NULL /* mp */, sg, rp); } -void -pim_msdp_sa_local_del(struct prefix_sg *sg) +void pim_msdp_sa_local_del(struct prefix_sg *sg) { - struct pim_msdp_sa *sa; + struct pim_msdp_sa *sa; - sa = pim_msdp_sa_find(sg); - if (sa) { - pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); - } + sa = pim_msdp_sa_find(sg); + if (sa) { + pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); + } } /* we need to be very cautious with this API as SA del too can trigger an * upstream del and we will get stuck in a simple loop */ -static void -pim_msdp_sa_local_del_on_up_del(struct prefix_sg *sg) -{ - struct pim_msdp_sa *sa; - - sa = pim_msdp_sa_find(sg); - if (sa) { - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP local sa %s del on up del", sa->sg_str); - } - - /* if there is no local reference escape */ - if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP local sa %s del; no local ref", sa->sg_str); - } - return; - } - - if (sa->flags & PIM_MSDP_SAF_UP_DEL_IN_PROG) { - /* MSDP is the one that triggered the upstream del. if this happens - * we most certainly have a bug in the PIM upstream state machine. We - * will not have a local reference unless the KAT is running. And if the - * KAT is running there MUST be an additional source-stream reference to - * the flow. Accounting for such cases requires lot of changes; perhaps - * address this in the next release? - XXX */ - zlog_err("MSDP sa %s SPT teardown is causing the local entry to be removed", sa->sg_str); - return; - } - - /* we are dropping the sa on upstream del we should not have an - * upstream reference */ - if (sa->up) { - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP local sa %s del; up non-NULL", sa->sg_str); - } - sa->up = NULL; - } - pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); - } +static void pim_msdp_sa_local_del_on_up_del(struct prefix_sg *sg) +{ + struct pim_msdp_sa *sa; + + sa = pim_msdp_sa_find(sg); + if (sa) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP local sa %s del on up del", + sa->sg_str); + } + + /* if there is no local reference escape */ + if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP local sa %s del; no local ref", + sa->sg_str); + } + return; + } + + if (sa->flags & PIM_MSDP_SAF_UP_DEL_IN_PROG) { + /* MSDP is the one that triggered the upstream del. if + * this happens + * we most certainly have a bug in the PIM upstream + * state machine. We + * will not have a local reference unless the KAT is + * running. And if the + * KAT is running there MUST be an additional + * source-stream reference to + * the flow. Accounting for such cases requires lot of + * changes; perhaps + * address this in the next release? - XXX */ + zlog_err( + "MSDP sa %s SPT teardown is causing the local entry to be removed", + sa->sg_str); + return; + } + + /* we are dropping the sa on upstream del we should not have an + * upstream reference */ + if (sa->up) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP local sa %s del; up non-NULL", + sa->sg_str); + } + sa->up = NULL; + } + pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); + } } /* Local SA qualification needs to be re-evaluated when - @@ -529,1072 +541,1045 @@ pim_msdp_sa_local_del_on_up_del(struct prefix_sg *sg) * FHR is also the RP. * 4. When msdp_reg timer is started or stopped */ -void -pim_msdp_sa_local_update(struct pim_upstream *up) +void pim_msdp_sa_local_update(struct pim_upstream *up) { - if (pim_msdp_sa_local_add_ok(up)) { - pim_msdp_sa_local_add(&up->sg); - } else { - pim_msdp_sa_local_del(&up->sg); - } + if (pim_msdp_sa_local_add_ok(up)) { + pim_msdp_sa_local_add(&up->sg); + } else { + pim_msdp_sa_local_del(&up->sg); + } } -static void -pim_msdp_sa_local_setup(void) +static void pim_msdp_sa_local_setup(void) { - struct pim_upstream *up; - struct listnode *up_node; + struct pim_upstream *up; + struct listnode *up_node; - for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, up_node, up)) { - pim_msdp_sa_local_update(up); - } + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, up_node, up)) { + pim_msdp_sa_local_update(up); + } } /* whenever the RP changes we need to re-evaluate the "local" SA-cache */ /* XXX: needs to be tested */ -void -pim_msdp_i_am_rp_changed(void) -{ - struct listnode *sanode; - struct listnode *nextnode; - struct pim_msdp_sa *sa; - - if (!(msdp->flags & PIM_MSDPF_ENABLE)) { - /* if the feature is not enabled do nothing */ - return; - } - - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP i_am_rp changed"); - } - - /* mark all local entries as stale */ - for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { - if (sa->flags & PIM_MSDP_SAF_LOCAL) { - sa->flags |= PIM_MSDP_SAF_STALE; - } - } - - /* re-setup local SA entries */ - pim_msdp_sa_local_setup(); - - for (ALL_LIST_ELEMENTS(msdp->sa_list, sanode, nextnode, sa)) { - /* purge stale SA entries */ - if (sa->flags & PIM_MSDP_SAF_STALE) { - /* clear the stale flag; the entry may be kept even after - * "local-deref" */ - sa->flags &= ~PIM_MSDP_SAF_STALE; - /* sa_deref can end up freeing the sa; so don't access contents after */ - pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); - } else { - /* if the souce is still active check if we can influence SPT */ - pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, "rp-change"); - } - } +void pim_msdp_i_am_rp_changed(void) +{ + struct listnode *sanode; + struct listnode *nextnode; + struct pim_msdp_sa *sa; + + if (!(msdp->flags & PIM_MSDPF_ENABLE)) { + /* if the feature is not enabled do nothing */ + return; + } + + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP i_am_rp changed"); + } + + /* mark all local entries as stale */ + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + if (sa->flags & PIM_MSDP_SAF_LOCAL) { + sa->flags |= PIM_MSDP_SAF_STALE; + } + } + + /* re-setup local SA entries */ + pim_msdp_sa_local_setup(); + + for (ALL_LIST_ELEMENTS(msdp->sa_list, sanode, nextnode, sa)) { + /* purge stale SA entries */ + if (sa->flags & PIM_MSDP_SAF_STALE) { + /* clear the stale flag; the entry may be kept even + * after + * "local-deref" */ + sa->flags &= ~PIM_MSDP_SAF_STALE; + /* sa_deref can end up freeing the sa; so don't access + * contents after */ + pim_msdp_sa_deref(sa, PIM_MSDP_SAF_LOCAL); + } else { + /* if the souce is still active check if we can + * influence SPT */ + pim_msdp_sa_upstream_update(sa, NULL /* xg_up */, + "rp-change"); + } + } } /* We track the join state of (*, G) entries. If G has sources in the SA-cache * we need to setup or teardown SPT when the JoinDesired status changes for * (*, G) */ -void -pim_msdp_up_join_state_changed(struct pim_upstream *xg_up) -{ - struct listnode *sanode; - struct pim_msdp_sa *sa; - - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP join state changed for %s", xg_up->sg_str); - } - - /* If this is not really an XG entry just move on */ - if ((xg_up->sg.src.s_addr != INADDR_ANY) || - (xg_up->sg.grp.s_addr == INADDR_ANY)) { - return; - } - - /* XXX: Need to maintain SAs per-group to avoid all this unnecessary - * walking */ - for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { - if (sa->sg.grp.s_addr != xg_up->sg.grp.s_addr) { - continue; - } - pim_msdp_sa_upstream_update(sa, xg_up, "up-jp-change"); - } -} - -static void -pim_msdp_up_xg_del(struct prefix_sg *sg) -{ - struct listnode *sanode; - struct pim_msdp_sa *sa; - - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP %s del", pim_str_sg_dump(sg)); - } - - /* If this is not really an XG entry just move on */ - if ((sg->src.s_addr != INADDR_ANY) || - (sg->grp.s_addr == INADDR_ANY)) { - return; - } - - /* XXX: Need to maintain SAs per-group to avoid all this unnecessary - * walking */ - for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { - if (sa->sg.grp.s_addr != sg->grp.s_addr) { - continue; - } - pim_msdp_sa_upstream_update(sa, NULL /* xg */, "up-jp-change"); - } -} - -void -pim_msdp_up_del(struct prefix_sg *sg) -{ - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP up %s del", pim_str_sg_dump(sg)); - } - if (sg->src.s_addr == INADDR_ANY) { - pim_msdp_up_xg_del(sg); - } else { - pim_msdp_sa_local_del_on_up_del(sg); - } +void pim_msdp_up_join_state_changed(struct pim_upstream *xg_up) +{ + struct listnode *sanode; + struct pim_msdp_sa *sa; + + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP join state changed for %s", xg_up->sg_str); + } + + /* If this is not really an XG entry just move on */ + if ((xg_up->sg.src.s_addr != INADDR_ANY) + || (xg_up->sg.grp.s_addr == INADDR_ANY)) { + return; + } + + /* XXX: Need to maintain SAs per-group to avoid all this unnecessary + * walking */ + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + if (sa->sg.grp.s_addr != xg_up->sg.grp.s_addr) { + continue; + } + pim_msdp_sa_upstream_update(sa, xg_up, "up-jp-change"); + } +} + +static void pim_msdp_up_xg_del(struct prefix_sg *sg) +{ + struct listnode *sanode; + struct pim_msdp_sa *sa; + + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP %s del", pim_str_sg_dump(sg)); + } + + /* If this is not really an XG entry just move on */ + if ((sg->src.s_addr != INADDR_ANY) || (sg->grp.s_addr == INADDR_ANY)) { + return; + } + + /* XXX: Need to maintain SAs per-group to avoid all this unnecessary + * walking */ + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + if (sa->sg.grp.s_addr != sg->grp.s_addr) { + continue; + } + pim_msdp_sa_upstream_update(sa, NULL /* xg */, "up-jp-change"); + } +} + +void pim_msdp_up_del(struct prefix_sg *sg) +{ + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP up %s del", pim_str_sg_dump(sg)); + } + if (sg->src.s_addr == INADDR_ANY) { + pim_msdp_up_xg_del(sg); + } else { + pim_msdp_sa_local_del_on_up_del(sg); + } } /* sa hash and peer list helpers */ -static unsigned int -pim_msdp_sa_hash_key_make(void *p) +static unsigned int pim_msdp_sa_hash_key_make(void *p) { - struct pim_msdp_sa *sa = p; + struct pim_msdp_sa *sa = p; - return (jhash_2words(sa->sg.src.s_addr, sa->sg.grp.s_addr, 0)); + return (jhash_2words(sa->sg.src.s_addr, sa->sg.grp.s_addr, 0)); } -static int -pim_msdp_sa_hash_eq(const void *p1, const void *p2) +static int pim_msdp_sa_hash_eq(const void *p1, const void *p2) { - const struct pim_msdp_sa *sa1 = p1; - const struct pim_msdp_sa *sa2 = p2; + const struct pim_msdp_sa *sa1 = p1; + const struct pim_msdp_sa *sa2 = p2; - return ((sa1->sg.src.s_addr == sa2->sg.src.s_addr) && - (sa1->sg.grp.s_addr == sa2->sg.grp.s_addr)); + return ((sa1->sg.src.s_addr == sa2->sg.src.s_addr) + && (sa1->sg.grp.s_addr == sa2->sg.grp.s_addr)); } -static int -pim_msdp_sa_comp(const void *p1, const void *p2) +static int pim_msdp_sa_comp(const void *p1, const void *p2) { - const struct pim_msdp_sa *sa1 = p1; - const struct pim_msdp_sa *sa2 = p2; + const struct pim_msdp_sa *sa1 = p1; + const struct pim_msdp_sa *sa2 = p2; - if (ntohl(sa1->sg.grp.s_addr) < ntohl(sa2->sg.grp.s_addr)) - return -1; + if (ntohl(sa1->sg.grp.s_addr) < ntohl(sa2->sg.grp.s_addr)) + return -1; - if (ntohl(sa1->sg.grp.s_addr) > ntohl(sa2->sg.grp.s_addr)) - return 1; + if (ntohl(sa1->sg.grp.s_addr) > ntohl(sa2->sg.grp.s_addr)) + return 1; - if (ntohl(sa1->sg.src.s_addr) < ntohl(sa2->sg.src.s_addr)) - return -1; + if (ntohl(sa1->sg.src.s_addr) < ntohl(sa2->sg.src.s_addr)) + return -1; - if (ntohl(sa1->sg.src.s_addr) > ntohl(sa2->sg.src.s_addr)) - return 1; + if (ntohl(sa1->sg.src.s_addr) > ntohl(sa2->sg.src.s_addr)) + return 1; - return 0; + return 0; } /* RFC-3618:Sec-10.1.3 - Peer-RPF forwarding */ /* XXX: this can use a bit of refining and extensions */ -bool -pim_msdp_peer_rpf_check(struct pim_msdp_peer *mp, struct in_addr rp) +bool pim_msdp_peer_rpf_check(struct pim_msdp_peer *mp, struct in_addr rp) { - if (mp->peer.s_addr == rp.s_addr) { - return true; - } + if (mp->peer.s_addr == rp.s_addr) { + return true; + } - return false; + return false; } - + /************************ Peer session management **************************/ -char * -pim_msdp_state_dump(enum pim_msdp_peer_state state, char *buf, int buf_size) -{ - switch (state) { - case PIM_MSDP_DISABLED: - snprintf(buf, buf_size, "%s", "disabled"); - break; - case PIM_MSDP_INACTIVE: - snprintf(buf, buf_size, "%s", "inactive"); - break; - case PIM_MSDP_LISTEN: - snprintf(buf, buf_size, "%s", "listen"); - break; - case PIM_MSDP_CONNECTING: - snprintf(buf, buf_size, "%s", "connecting"); - break; - case PIM_MSDP_ESTABLISHED: - snprintf(buf, buf_size, "%s", "established"); - break; - default: - snprintf(buf, buf_size, "unk-%d", state); - } - return buf; -} - -char * -pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size, bool long_format) -{ - char peer_str[INET_ADDRSTRLEN]; - char local_str[INET_ADDRSTRLEN]; - - pim_inet4_dump("", mp->peer, peer_str, sizeof(peer_str)); - if (long_format) { - pim_inet4_dump("", mp->local, local_str, sizeof(local_str)); - snprintf(buf, buf_size, "MSDP peer %s local %s mg %s", - peer_str, local_str, mp->mesh_group_name); - } else { - snprintf(buf, buf_size, "MSDP peer %s", peer_str); - } - - return buf; -} - -static void -pim_msdp_peer_state_chg_log(struct pim_msdp_peer *mp) -{ - char state_str[PIM_MSDP_STATE_STRLEN]; - - pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); - zlog_debug("MSDP peer %s state chg to %s", mp->key_str, state_str); +char *pim_msdp_state_dump(enum pim_msdp_peer_state state, char *buf, + int buf_size) +{ + switch (state) { + case PIM_MSDP_DISABLED: + snprintf(buf, buf_size, "%s", "disabled"); + break; + case PIM_MSDP_INACTIVE: + snprintf(buf, buf_size, "%s", "inactive"); + break; + case PIM_MSDP_LISTEN: + snprintf(buf, buf_size, "%s", "listen"); + break; + case PIM_MSDP_CONNECTING: + snprintf(buf, buf_size, "%s", "connecting"); + break; + case PIM_MSDP_ESTABLISHED: + snprintf(buf, buf_size, "%s", "established"); + break; + default: + snprintf(buf, buf_size, "unk-%d", state); + } + return buf; +} + +char *pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size, + bool long_format) +{ + char peer_str[INET_ADDRSTRLEN]; + char local_str[INET_ADDRSTRLEN]; + + pim_inet4_dump("", mp->peer, peer_str, sizeof(peer_str)); + if (long_format) { + pim_inet4_dump("", mp->local, local_str, + sizeof(local_str)); + snprintf(buf, buf_size, "MSDP peer %s local %s mg %s", peer_str, + local_str, mp->mesh_group_name); + } else { + snprintf(buf, buf_size, "MSDP peer %s", peer_str); + } + + return buf; +} + +static void pim_msdp_peer_state_chg_log(struct pim_msdp_peer *mp) +{ + char state_str[PIM_MSDP_STATE_STRLEN]; + + pim_msdp_state_dump(mp->state, state_str, sizeof(state_str)); + zlog_debug("MSDP peer %s state chg to %s", mp->key_str, state_str); } /* MSDP Connection State Machine actions (defined in RFC-3618:Sec-11.2) */ /* 11.2.A2: active peer - start connect retry timer; when the timer fires * a tcp connection will be made */ -static void -pim_msdp_peer_connect(struct pim_msdp_peer *mp) +static void pim_msdp_peer_connect(struct pim_msdp_peer *mp) { - mp->state = PIM_MSDP_CONNECTING; - if (PIM_DEBUG_MSDP_EVENTS) { - pim_msdp_peer_state_chg_log(mp); - } + mp->state = PIM_MSDP_CONNECTING; + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_state_chg_log(mp); + } - pim_msdp_peer_cr_timer_setup(mp, true /* start */); + pim_msdp_peer_cr_timer_setup(mp, true /* start */); } /* 11.2.A3: passive peer - just listen for connections */ -static void -pim_msdp_peer_listen(struct pim_msdp_peer *mp) +static void pim_msdp_peer_listen(struct pim_msdp_peer *mp) { - mp->state = PIM_MSDP_LISTEN; - if (PIM_DEBUG_MSDP_EVENTS) { - pim_msdp_peer_state_chg_log(mp); - } + mp->state = PIM_MSDP_LISTEN; + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_state_chg_log(mp); + } - /* this is interntionally asymmetric i.e. we set up listen-socket when the - * first listening peer is configured; but don't bother tearing it down when - * all the peers go down */ - pim_msdp_sock_listen(); + /* this is interntionally asymmetric i.e. we set up listen-socket when + * the + * first listening peer is configured; but don't bother tearing it down + * when + * all the peers go down */ + pim_msdp_sock_listen(); } /* 11.2.A4 and 11.2.A5: transition active or passive peer to * established state */ -void -pim_msdp_peer_established(struct pim_msdp_peer *mp) +void pim_msdp_peer_established(struct pim_msdp_peer *mp) { - if (mp->state != PIM_MSDP_ESTABLISHED) { - ++mp->est_flaps; - } + if (mp->state != PIM_MSDP_ESTABLISHED) { + ++mp->est_flaps; + } - mp->state = PIM_MSDP_ESTABLISHED; - mp->uptime = pim_time_monotonic_sec(); + mp->state = PIM_MSDP_ESTABLISHED; + mp->uptime = pim_time_monotonic_sec(); - if (PIM_DEBUG_MSDP_EVENTS) { - pim_msdp_peer_state_chg_log(mp); - } + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_state_chg_log(mp); + } - /* stop retry timer on active peers */ - pim_msdp_peer_cr_timer_setup(mp, false /* start */); + /* stop retry timer on active peers */ + pim_msdp_peer_cr_timer_setup(mp, false /* start */); - /* send KA; start KA and hold timers */ - pim_msdp_pkt_ka_tx(mp); - pim_msdp_peer_ka_timer_setup(mp, true /* start */); - pim_msdp_peer_hold_timer_setup(mp, true /* start */); + /* send KA; start KA and hold timers */ + pim_msdp_pkt_ka_tx(mp); + pim_msdp_peer_ka_timer_setup(mp, true /* start */); + pim_msdp_peer_hold_timer_setup(mp, true /* start */); - pim_msdp_pkt_sa_tx_to_one_peer(mp); + pim_msdp_pkt_sa_tx_to_one_peer(mp); - PIM_MSDP_PEER_WRITE_ON(mp); - PIM_MSDP_PEER_READ_ON(mp); + PIM_MSDP_PEER_WRITE_ON(mp); + PIM_MSDP_PEER_READ_ON(mp); } /* 11.2.A6, 11.2.A7 and 11.2.A8: shutdown the peer tcp connection */ -void -pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state) -{ - if (chg_state) { - if (mp->state == PIM_MSDP_ESTABLISHED) { - ++mp->est_flaps; - } - mp->state = PIM_MSDP_INACTIVE; - if (PIM_DEBUG_MSDP_EVENTS) { - pim_msdp_peer_state_chg_log(mp); - } - } - - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s pim_msdp_peer_stop_tcp_conn", mp->key_str); - } - /* stop read and write threads */ - PIM_MSDP_PEER_READ_OFF(mp); - PIM_MSDP_PEER_WRITE_OFF(mp); - - /* reset buffers */ - mp->packet_size = 0; - if (mp->ibuf) - stream_reset(mp->ibuf); - if (mp->obuf) - stream_fifo_clean(mp->obuf); - - /* stop all peer timers */ - pim_msdp_peer_ka_timer_setup(mp, false /* start */); - pim_msdp_peer_cr_timer_setup(mp, false /* start */); - pim_msdp_peer_hold_timer_setup(mp, false /* start */); - - /* close connection */ - if (mp->fd >= 0) { - close(mp->fd); - mp->fd = -1; - } +void pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state) +{ + if (chg_state) { + if (mp->state == PIM_MSDP_ESTABLISHED) { + ++mp->est_flaps; + } + mp->state = PIM_MSDP_INACTIVE; + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_state_chg_log(mp); + } + } + + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s pim_msdp_peer_stop_tcp_conn", + mp->key_str); + } + /* stop read and write threads */ + PIM_MSDP_PEER_READ_OFF(mp); + PIM_MSDP_PEER_WRITE_OFF(mp); + + /* reset buffers */ + mp->packet_size = 0; + if (mp->ibuf) + stream_reset(mp->ibuf); + if (mp->obuf) + stream_fifo_clean(mp->obuf); + + /* stop all peer timers */ + pim_msdp_peer_ka_timer_setup(mp, false /* start */); + pim_msdp_peer_cr_timer_setup(mp, false /* start */); + pim_msdp_peer_hold_timer_setup(mp, false /* start */); + + /* close connection */ + if (mp->fd >= 0) { + close(mp->fd); + mp->fd = -1; + } } /* RFC-3618:Sec-5.6 - stop the peer tcp connection and startover */ -void -pim_msdp_peer_reset_tcp_conn(struct pim_msdp_peer *mp, const char *rc_str) +void pim_msdp_peer_reset_tcp_conn(struct pim_msdp_peer *mp, const char *rc_str) { - if (PIM_DEBUG_EVENTS) { - zlog_debug("MSDP peer %s tcp reset %s", mp->key_str, rc_str); - snprintf(mp->last_reset, sizeof(mp->last_reset), "%s", rc_str); - } + if (PIM_DEBUG_EVENTS) { + zlog_debug("MSDP peer %s tcp reset %s", mp->key_str, rc_str); + snprintf(mp->last_reset, sizeof(mp->last_reset), "%s", rc_str); + } - /* close the connection and transition to listening or connecting */ - pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); - if (PIM_MSDP_PEER_IS_LISTENER(mp)) { - pim_msdp_peer_listen(mp); - } else { - pim_msdp_peer_connect(mp); - } + /* close the connection and transition to listening or connecting */ + pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); + if (PIM_MSDP_PEER_IS_LISTENER(mp)) { + pim_msdp_peer_listen(mp); + } else { + pim_msdp_peer_connect(mp); + } } -static void -pim_msdp_peer_timer_expiry_log(struct pim_msdp_peer *mp, const char *timer_str) +static void pim_msdp_peer_timer_expiry_log(struct pim_msdp_peer *mp, + const char *timer_str) { - zlog_debug("MSDP peer %s %s timer expired", mp->key_str, timer_str); + zlog_debug("MSDP peer %s %s timer expired", mp->key_str, timer_str); } /* RFC-3618:Sec-5.4 - peer hold timer */ -static int -pim_msdp_peer_hold_timer_cb(struct thread *t) +static int pim_msdp_peer_hold_timer_cb(struct thread *t) { - struct pim_msdp_peer *mp; + struct pim_msdp_peer *mp; - mp = THREAD_ARG(t); + mp = THREAD_ARG(t); - if (PIM_DEBUG_MSDP_EVENTS) { - pim_msdp_peer_timer_expiry_log(mp, "hold"); - } + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_timer_expiry_log(mp, "hold"); + } - if (mp->state != PIM_MSDP_ESTABLISHED) { - return 0; - } + if (mp->state != PIM_MSDP_ESTABLISHED) { + return 0; + } - if (PIM_DEBUG_MSDP_EVENTS) { - pim_msdp_peer_state_chg_log(mp); - } - pim_msdp_peer_reset_tcp_conn(mp, "ht-expired"); - return 0; + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_state_chg_log(mp); + } + pim_msdp_peer_reset_tcp_conn(mp, "ht-expired"); + return 0; } -static void -pim_msdp_peer_hold_timer_setup(struct pim_msdp_peer *mp, bool start) +static void pim_msdp_peer_hold_timer_setup(struct pim_msdp_peer *mp, bool start) { - THREAD_OFF(mp->hold_timer); - if (start) { - thread_add_timer(msdp->master, pim_msdp_peer_hold_timer_cb, mp, - PIM_MSDP_PEER_HOLD_TIME, &mp->hold_timer); - } + THREAD_OFF(mp->hold_timer); + if (start) { + thread_add_timer(msdp->master, pim_msdp_peer_hold_timer_cb, mp, + PIM_MSDP_PEER_HOLD_TIME, &mp->hold_timer); + } } /* RFC-3618:Sec-5.5 - peer keepalive timer */ -static int -pim_msdp_peer_ka_timer_cb(struct thread *t) +static int pim_msdp_peer_ka_timer_cb(struct thread *t) { - struct pim_msdp_peer *mp; + struct pim_msdp_peer *mp; - mp = THREAD_ARG(t); + mp = THREAD_ARG(t); - if (PIM_DEBUG_MSDP_EVENTS) { - pim_msdp_peer_timer_expiry_log(mp, "ka"); - } + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_timer_expiry_log(mp, "ka"); + } - pim_msdp_pkt_ka_tx(mp); - pim_msdp_peer_ka_timer_setup(mp, true /* start */); - return 0; + pim_msdp_pkt_ka_tx(mp); + pim_msdp_peer_ka_timer_setup(mp, true /* start */); + return 0; } -static void -pim_msdp_peer_ka_timer_setup(struct pim_msdp_peer *mp, bool start) +static void pim_msdp_peer_ka_timer_setup(struct pim_msdp_peer *mp, bool start) { - THREAD_OFF(mp->ka_timer); - if (start) { - thread_add_timer(msdp->master, pim_msdp_peer_ka_timer_cb, mp, - PIM_MSDP_PEER_KA_TIME, &mp->ka_timer); - } + THREAD_OFF(mp->ka_timer); + if (start) { + thread_add_timer(msdp->master, pim_msdp_peer_ka_timer_cb, mp, + PIM_MSDP_PEER_KA_TIME, &mp->ka_timer); + } } -static void -pim_msdp_peer_active_connect(struct pim_msdp_peer *mp) +static void pim_msdp_peer_active_connect(struct pim_msdp_peer *mp) { - int rc; - ++mp->conn_attempts; - rc = pim_msdp_sock_connect(mp); + int rc; + ++mp->conn_attempts; + rc = pim_msdp_sock_connect(mp); - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s pim_msdp_peer_active_connect: %d", mp->key_str, rc); - } + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s pim_msdp_peer_active_connect: %d", + mp->key_str, rc); + } - switch (rc) { - case connect_error: - case -1: - /* connect failed restart the connect-retry timer */ - pim_msdp_peer_cr_timer_setup(mp, true /* start */); - break; + switch (rc) { + case connect_error: + case -1: + /* connect failed restart the connect-retry timer */ + pim_msdp_peer_cr_timer_setup(mp, true /* start */); + break; - case connect_success: - /* connect was sucessful move to established */ - pim_msdp_peer_established(mp); - break; + case connect_success: + /* connect was sucessful move to established */ + pim_msdp_peer_established(mp); + break; - case connect_in_progress: - /* for NB content we need to wait till sock is readable or - * writeable */ - PIM_MSDP_PEER_WRITE_ON(mp); - PIM_MSDP_PEER_READ_ON(mp); - /* also restart connect-retry timer to reset the socket if connect is - * not sucessful */ - pim_msdp_peer_cr_timer_setup(mp, true /* start */); - break; - } + case connect_in_progress: + /* for NB content we need to wait till sock is readable or + * writeable */ + PIM_MSDP_PEER_WRITE_ON(mp); + PIM_MSDP_PEER_READ_ON(mp); + /* also restart connect-retry timer to reset the socket if + * connect is + * not sucessful */ + pim_msdp_peer_cr_timer_setup(mp, true /* start */); + break; + } } /* RFC-3618:Sec-5.6 - connection retry on active peer */ -static int -pim_msdp_peer_cr_timer_cb(struct thread *t) +static int pim_msdp_peer_cr_timer_cb(struct thread *t) { - struct pim_msdp_peer *mp; + struct pim_msdp_peer *mp; - mp = THREAD_ARG(t); + mp = THREAD_ARG(t); - if (PIM_DEBUG_MSDP_EVENTS) { - pim_msdp_peer_timer_expiry_log(mp, "connect-retry"); - } + if (PIM_DEBUG_MSDP_EVENTS) { + pim_msdp_peer_timer_expiry_log(mp, "connect-retry"); + } - if (mp->state != PIM_MSDP_CONNECTING || PIM_MSDP_PEER_IS_LISTENER(mp)) { - return 0; - } + if (mp->state != PIM_MSDP_CONNECTING || PIM_MSDP_PEER_IS_LISTENER(mp)) { + return 0; + } - pim_msdp_peer_active_connect(mp); - return 0; + pim_msdp_peer_active_connect(mp); + return 0; } -static void -pim_msdp_peer_cr_timer_setup(struct pim_msdp_peer *mp, bool start) +static void pim_msdp_peer_cr_timer_setup(struct pim_msdp_peer *mp, bool start) { - THREAD_OFF(mp->cr_timer); - if (start) { - thread_add_timer(msdp->master, pim_msdp_peer_cr_timer_cb, mp, - PIM_MSDP_PEER_CONNECT_RETRY_TIME, &mp->cr_timer); - } + THREAD_OFF(mp->cr_timer); + if (start) { + thread_add_timer(msdp->master, pim_msdp_peer_cr_timer_cb, mp, + PIM_MSDP_PEER_CONNECT_RETRY_TIME, + &mp->cr_timer); + } } /* if a valid packet is rxed from the peer we can restart hold timer */ -void -pim_msdp_peer_pkt_rxed(struct pim_msdp_peer *mp) +void pim_msdp_peer_pkt_rxed(struct pim_msdp_peer *mp) { - if (mp->state == PIM_MSDP_ESTABLISHED) { - pim_msdp_peer_hold_timer_setup(mp, true /* start */); - } + if (mp->state == PIM_MSDP_ESTABLISHED) { + pim_msdp_peer_hold_timer_setup(mp, true /* start */); + } } /* if a valid packet is txed to the peer we can restart ka timer and avoid * unnecessary ka noise in the network */ -void -pim_msdp_peer_pkt_txed(struct pim_msdp_peer *mp) +void pim_msdp_peer_pkt_txed(struct pim_msdp_peer *mp) { - if (mp->state == PIM_MSDP_ESTABLISHED) { - pim_msdp_peer_ka_timer_setup(mp, true /* start */); - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP ka timer restart on pkt tx to %s", mp->key_str); - } - } + if (mp->state == PIM_MSDP_ESTABLISHED) { + pim_msdp_peer_ka_timer_setup(mp, true /* start */); + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP ka timer restart on pkt tx to %s", + mp->key_str); + } + } } static void pim_msdp_addr2su(union sockunion *su, struct in_addr addr) { - sockunion_init(su); - su->sin.sin_addr = addr; - su->sin.sin_family = AF_INET; + sockunion_init(su); + su->sin.sin_addr = addr; + su->sin.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - su->sin.sin_len = sizeof(struct sockaddr_in); + su->sin.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ } /* 11.2.A1: create a new peer and transition state to listen or connecting */ -static enum pim_msdp_err -pim_msdp_peer_new(struct in_addr peer_addr, struct in_addr local_addr, - const char *mesh_group_name, struct pim_msdp_peer **mp_p) -{ - struct pim_msdp_peer *mp; - - pim_msdp_enable(); - - mp = XCALLOC(MTYPE_PIM_MSDP_PEER, sizeof(*mp)); - if (!mp) { - zlog_err("%s: PIM XCALLOC(%zu) failure", - __PRETTY_FUNCTION__, sizeof(*mp)); - return PIM_MSDP_ERR_OOM; - } - - mp->peer = peer_addr; - pim_inet4_dump("", mp->peer, mp->key_str, sizeof(mp->key_str)); - pim_msdp_addr2su(&mp->su_peer, mp->peer); - mp->local = local_addr; - /* XXX: originator_id setting needs to move to the mesh group */ - msdp->originator_id = local_addr; - pim_msdp_addr2su(&mp->su_local, mp->local); - mp->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_MG_NAME, mesh_group_name); - mp->state = PIM_MSDP_INACTIVE; - mp->fd = -1; - strcpy(mp->last_reset, "-"); - /* higher IP address is listener */ - if (ntohl(mp->local.s_addr) > ntohl(mp->peer.s_addr)) { - mp->flags |= PIM_MSDP_PEERF_LISTENER; - } - - /* setup packet buffers */ - mp->ibuf = stream_new(PIM_MSDP_MAX_PACKET_SIZE); - mp->obuf = stream_fifo_new(); - - /* insert into misc tables for easy access */ - mp = hash_get(msdp->peer_hash, mp, hash_alloc_intern); - listnode_add_sort(msdp->peer_list, mp); - - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP peer %s created", mp->key_str); - - pim_msdp_peer_state_chg_log(mp); - } - - /* fireup the connect state machine */ - if (PIM_MSDP_PEER_IS_LISTENER(mp)) { - pim_msdp_peer_listen(mp); - } else { - pim_msdp_peer_connect(mp); - } - if (mp_p) { - *mp_p = mp; - } - return PIM_MSDP_ERR_NONE; -} - -struct pim_msdp_peer * -pim_msdp_peer_find(struct in_addr peer_addr) -{ - struct pim_msdp_peer lookup; - - lookup.peer = peer_addr; - return hash_lookup(msdp->peer_hash, &lookup); +static enum pim_msdp_err pim_msdp_peer_new(struct in_addr peer_addr, + struct in_addr local_addr, + const char *mesh_group_name, + struct pim_msdp_peer **mp_p) +{ + struct pim_msdp_peer *mp; + + pim_msdp_enable(); + + mp = XCALLOC(MTYPE_PIM_MSDP_PEER, sizeof(*mp)); + if (!mp) { + zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, + sizeof(*mp)); + return PIM_MSDP_ERR_OOM; + } + + mp->peer = peer_addr; + pim_inet4_dump("", mp->peer, mp->key_str, sizeof(mp->key_str)); + pim_msdp_addr2su(&mp->su_peer, mp->peer); + mp->local = local_addr; + /* XXX: originator_id setting needs to move to the mesh group */ + msdp->originator_id = local_addr; + pim_msdp_addr2su(&mp->su_local, mp->local); + mp->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_MG_NAME, mesh_group_name); + mp->state = PIM_MSDP_INACTIVE; + mp->fd = -1; + strcpy(mp->last_reset, "-"); + /* higher IP address is listener */ + if (ntohl(mp->local.s_addr) > ntohl(mp->peer.s_addr)) { + mp->flags |= PIM_MSDP_PEERF_LISTENER; + } + + /* setup packet buffers */ + mp->ibuf = stream_new(PIM_MSDP_MAX_PACKET_SIZE); + mp->obuf = stream_fifo_new(); + + /* insert into misc tables for easy access */ + mp = hash_get(msdp->peer_hash, mp, hash_alloc_intern); + listnode_add_sort(msdp->peer_list, mp); + + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP peer %s created", mp->key_str); + + pim_msdp_peer_state_chg_log(mp); + } + + /* fireup the connect state machine */ + if (PIM_MSDP_PEER_IS_LISTENER(mp)) { + pim_msdp_peer_listen(mp); + } else { + pim_msdp_peer_connect(mp); + } + if (mp_p) { + *mp_p = mp; + } + return PIM_MSDP_ERR_NONE; +} + +struct pim_msdp_peer *pim_msdp_peer_find(struct in_addr peer_addr) +{ + struct pim_msdp_peer lookup; + + lookup.peer = peer_addr; + return hash_lookup(msdp->peer_hash, &lookup); } /* add peer configuration if it doesn't already exist */ -enum pim_msdp_err -pim_msdp_peer_add(struct in_addr peer_addr, struct in_addr local_addr, - const char *mesh_group_name, struct pim_msdp_peer **mp_p) +enum pim_msdp_err pim_msdp_peer_add(struct in_addr peer_addr, + struct in_addr local_addr, + const char *mesh_group_name, + struct pim_msdp_peer **mp_p) { - struct pim_msdp_peer *mp; + struct pim_msdp_peer *mp; - if (mp_p) { - *mp_p = NULL; - } + if (mp_p) { + *mp_p = NULL; + } - if (peer_addr.s_addr == local_addr.s_addr) { - /* skip session setup if config is invalid */ - if (PIM_DEBUG_MSDP_EVENTS) { - char peer_str[INET_ADDRSTRLEN]; + if (peer_addr.s_addr == local_addr.s_addr) { + /* skip session setup if config is invalid */ + if (PIM_DEBUG_MSDP_EVENTS) { + char peer_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", peer_addr, peer_str, sizeof(peer_str)); - zlog_debug("%s add skipped as DIP=SIP", peer_str); - } - return PIM_MSDP_ERR_SIP_EQ_DIP; - } + pim_inet4_dump("", peer_addr, peer_str, + sizeof(peer_str)); + zlog_debug("%s add skipped as DIP=SIP", peer_str); + } + return PIM_MSDP_ERR_SIP_EQ_DIP; + } - mp = pim_msdp_peer_find(peer_addr); - if (mp) { - if (mp_p) { - *mp_p = mp; - } - return PIM_MSDP_ERR_PEER_EXISTS; - } + mp = pim_msdp_peer_find(peer_addr); + if (mp) { + if (mp_p) { + *mp_p = mp; + } + return PIM_MSDP_ERR_PEER_EXISTS; + } - return pim_msdp_peer_new(peer_addr, local_addr, mesh_group_name, mp_p); + return pim_msdp_peer_new(peer_addr, local_addr, mesh_group_name, mp_p); } /* release all mem associated with a peer */ -static void -pim_msdp_peer_free(struct pim_msdp_peer *mp) +static void pim_msdp_peer_free(struct pim_msdp_peer *mp) { - if (mp->ibuf) { - stream_free(mp->ibuf); - } + if (mp->ibuf) { + stream_free(mp->ibuf); + } - if (mp->obuf) { - stream_fifo_free(mp->obuf); - } + if (mp->obuf) { + stream_fifo_free(mp->obuf); + } - if (mp->mesh_group_name) { - XFREE(MTYPE_PIM_MSDP_MG_NAME, mp->mesh_group_name); - } - XFREE(MTYPE_PIM_MSDP_PEER, mp); + if (mp->mesh_group_name) { + XFREE(MTYPE_PIM_MSDP_MG_NAME, mp->mesh_group_name); + } + XFREE(MTYPE_PIM_MSDP_PEER, mp); } /* delete the peer config */ -static enum pim_msdp_err -pim_msdp_peer_do_del(struct pim_msdp_peer *mp) +static enum pim_msdp_err pim_msdp_peer_do_del(struct pim_msdp_peer *mp) { - /* stop the tcp connection and shutdown all timers */ - pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); + /* stop the tcp connection and shutdown all timers */ + pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); - /* remove the session from various tables */ - listnode_delete(msdp->peer_list, mp); - hash_release(msdp->peer_hash, mp); + /* remove the session from various tables */ + listnode_delete(msdp->peer_list, mp); + hash_release(msdp->peer_hash, mp); - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP peer %s deleted", mp->key_str); - } + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP peer %s deleted", mp->key_str); + } - /* free up any associated memory */ - pim_msdp_peer_free(mp); + /* free up any associated memory */ + pim_msdp_peer_free(mp); - return PIM_MSDP_ERR_NONE; + return PIM_MSDP_ERR_NONE; } -enum pim_msdp_err -pim_msdp_peer_del(struct in_addr peer_addr) +enum pim_msdp_err pim_msdp_peer_del(struct in_addr peer_addr) { - struct pim_msdp_peer *mp; + struct pim_msdp_peer *mp; - mp = pim_msdp_peer_find(peer_addr); - if (!mp) { - return PIM_MSDP_ERR_NO_PEER; - } + mp = pim_msdp_peer_find(peer_addr); + if (!mp) { + return PIM_MSDP_ERR_NO_PEER; + } - return pim_msdp_peer_do_del(mp); + return pim_msdp_peer_do_del(mp); } /* peer hash and peer list helpers */ -static unsigned int -pim_msdp_peer_hash_key_make(void *p) +static unsigned int pim_msdp_peer_hash_key_make(void *p) { - struct pim_msdp_peer *mp = p; - return (jhash_1word(mp->peer.s_addr, 0)); + struct pim_msdp_peer *mp = p; + return (jhash_1word(mp->peer.s_addr, 0)); } -static int -pim_msdp_peer_hash_eq(const void *p1, const void *p2) +static int pim_msdp_peer_hash_eq(const void *p1, const void *p2) { - const struct pim_msdp_peer *mp1 = p1; - const struct pim_msdp_peer *mp2 = p2; + const struct pim_msdp_peer *mp1 = p1; + const struct pim_msdp_peer *mp2 = p2; - return (mp1->peer.s_addr == mp2->peer.s_addr); + return (mp1->peer.s_addr == mp2->peer.s_addr); } -static int -pim_msdp_peer_comp(const void *p1, const void *p2) +static int pim_msdp_peer_comp(const void *p1, const void *p2) { - const struct pim_msdp_peer *mp1 = p1; - const struct pim_msdp_peer *mp2 = p2; + const struct pim_msdp_peer *mp1 = p1; + const struct pim_msdp_peer *mp2 = p2; - if (ntohl(mp1->peer.s_addr) < ntohl(mp2->peer.s_addr)) - return -1; + if (ntohl(mp1->peer.s_addr) < ntohl(mp2->peer.s_addr)) + return -1; - if (ntohl(mp1->peer.s_addr) > ntohl(mp2->peer.s_addr)) - return 1; + if (ntohl(mp1->peer.s_addr) > ntohl(mp2->peer.s_addr)) + return 1; - return 0; + return 0; } /************************** Mesh group management **************************/ -static void -pim_msdp_mg_free(struct pim_msdp_mg *mg) +static void pim_msdp_mg_free(struct pim_msdp_mg *mg) { - /* If the mesh-group has valid member or src_ip don't delete it */ - if (!mg || mg->mbr_cnt || (mg->src_ip.s_addr != INADDR_ANY)) { - return; - } + /* If the mesh-group has valid member or src_ip don't delete it */ + if (!mg || mg->mbr_cnt || (mg->src_ip.s_addr != INADDR_ANY)) { + return; + } - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP mesh-group %s deleted", mg->mesh_group_name); - } - if (mg->mesh_group_name) - XFREE(MTYPE_PIM_MSDP_MG_NAME, mg->mesh_group_name); + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP mesh-group %s deleted", mg->mesh_group_name); + } + if (mg->mesh_group_name) + XFREE(MTYPE_PIM_MSDP_MG_NAME, mg->mesh_group_name); - if (mg->mbr_list) - list_free(mg->mbr_list); + if (mg->mbr_list) + list_free(mg->mbr_list); - XFREE(MTYPE_PIM_MSDP_MG, mg); - msdp->mg = NULL; + XFREE(MTYPE_PIM_MSDP_MG, mg); + msdp->mg = NULL; } -static struct pim_msdp_mg * -pim_msdp_mg_new(const char *mesh_group_name) +static struct pim_msdp_mg *pim_msdp_mg_new(const char *mesh_group_name) { - struct pim_msdp_mg *mg; + struct pim_msdp_mg *mg; - mg = XCALLOC(MTYPE_PIM_MSDP_MG, sizeof(*mg)); - if (!mg) { - zlog_err("%s: PIM XCALLOC(%zu) failure", - __PRETTY_FUNCTION__, sizeof(*mg)); - return NULL; - } + mg = XCALLOC(MTYPE_PIM_MSDP_MG, sizeof(*mg)); + if (!mg) { + zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, + sizeof(*mg)); + return NULL; + } - mg->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_MG_NAME, mesh_group_name); - mg->mbr_list = list_new(); - mg->mbr_list->del = (void (*)(void *))pim_msdp_mg_mbr_free; - mg->mbr_list->cmp = (int (*)(void *, void *))pim_msdp_mg_mbr_comp; + mg->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_MG_NAME, mesh_group_name); + mg->mbr_list = list_new(); + mg->mbr_list->del = (void (*)(void *))pim_msdp_mg_mbr_free; + mg->mbr_list->cmp = (int (*)(void *, void *))pim_msdp_mg_mbr_comp; - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP mesh-group %s created", mg->mesh_group_name); - } - return mg; + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP mesh-group %s created", mg->mesh_group_name); + } + return mg; } -enum pim_msdp_err -pim_msdp_mg_del(const char *mesh_group_name) +enum pim_msdp_err pim_msdp_mg_del(const char *mesh_group_name) { - struct pim_msdp_mg *mg = msdp->mg; - struct pim_msdp_mg_mbr *mbr; + struct pim_msdp_mg *mg = msdp->mg; + struct pim_msdp_mg_mbr *mbr; - if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { - return PIM_MSDP_ERR_NO_MG; - } + if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { + return PIM_MSDP_ERR_NO_MG; + } - /* delete all the mesh-group members */ - while (!list_isempty(mg->mbr_list)) { - mbr = listnode_head(mg->mbr_list); - pim_msdp_mg_mbr_do_del(mg, mbr); - } + /* delete all the mesh-group members */ + while (!list_isempty(mg->mbr_list)) { + mbr = listnode_head(mg->mbr_list); + pim_msdp_mg_mbr_do_del(mg, mbr); + } - /* clear src ip */ - mg->src_ip.s_addr = INADDR_ANY; + /* clear src ip */ + mg->src_ip.s_addr = INADDR_ANY; - /* free up the mesh-group */ - pim_msdp_mg_free(mg); - return PIM_MSDP_ERR_NONE; + /* free up the mesh-group */ + pim_msdp_mg_free(mg); + return PIM_MSDP_ERR_NONE; } -static enum pim_msdp_err -pim_msdp_mg_add(const char *mesh_group_name) +static enum pim_msdp_err pim_msdp_mg_add(const char *mesh_group_name) { - if (msdp->mg) { - if (!strcmp(msdp->mg->mesh_group_name, mesh_group_name)) { - return PIM_MSDP_ERR_NONE; - } - /* currently only one mesh-group can exist at a time */ - return PIM_MSDP_ERR_MAX_MESH_GROUPS; - } + if (msdp->mg) { + if (!strcmp(msdp->mg->mesh_group_name, mesh_group_name)) { + return PIM_MSDP_ERR_NONE; + } + /* currently only one mesh-group can exist at a time */ + return PIM_MSDP_ERR_MAX_MESH_GROUPS; + } - msdp->mg = pim_msdp_mg_new(mesh_group_name); - if (!msdp->mg) { - return PIM_MSDP_ERR_OOM; - } + msdp->mg = pim_msdp_mg_new(mesh_group_name); + if (!msdp->mg) { + return PIM_MSDP_ERR_OOM; + } - return PIM_MSDP_ERR_NONE; + return PIM_MSDP_ERR_NONE; } -static int -pim_msdp_mg_mbr_comp(const void *p1, const void *p2) +static int pim_msdp_mg_mbr_comp(const void *p1, const void *p2) { - const struct pim_msdp_mg_mbr *mbr1 = p1; - const struct pim_msdp_mg_mbr *mbr2 = p2; + const struct pim_msdp_mg_mbr *mbr1 = p1; + const struct pim_msdp_mg_mbr *mbr2 = p2; - if (ntohl(mbr1->mbr_ip.s_addr) < ntohl(mbr2->mbr_ip.s_addr)) - return -1; + if (ntohl(mbr1->mbr_ip.s_addr) < ntohl(mbr2->mbr_ip.s_addr)) + return -1; - if (ntohl(mbr1->mbr_ip.s_addr) > ntohl(mbr2->mbr_ip.s_addr)) - return 1; + if (ntohl(mbr1->mbr_ip.s_addr) > ntohl(mbr2->mbr_ip.s_addr)) + return 1; - return 0; + return 0; } -static void -pim_msdp_mg_mbr_free(struct pim_msdp_mg_mbr *mbr) +static void pim_msdp_mg_mbr_free(struct pim_msdp_mg_mbr *mbr) { - XFREE(MTYPE_PIM_MSDP_MG_MBR, mbr); + XFREE(MTYPE_PIM_MSDP_MG_MBR, mbr); } -static struct pim_msdp_mg_mbr * -pim_msdp_mg_mbr_find(struct in_addr mbr_ip) +static struct pim_msdp_mg_mbr *pim_msdp_mg_mbr_find(struct in_addr mbr_ip) { - struct pim_msdp_mg_mbr *mbr; - struct listnode *mbr_node; + struct pim_msdp_mg_mbr *mbr; + struct listnode *mbr_node; - if (!msdp->mg) { - return NULL; - } - /* we can move this to a hash but considering that number of peers in - * a mesh-group that seems like bit of an overkill */ - for (ALL_LIST_ELEMENTS_RO(msdp->mg->mbr_list, mbr_node, mbr)) { - if (mbr->mbr_ip.s_addr == mbr_ip.s_addr) { - return mbr; - } - } - return mbr; + if (!msdp->mg) { + return NULL; + } + /* we can move this to a hash but considering that number of peers in + * a mesh-group that seems like bit of an overkill */ + for (ALL_LIST_ELEMENTS_RO(msdp->mg->mbr_list, mbr_node, mbr)) { + if (mbr->mbr_ip.s_addr == mbr_ip.s_addr) { + return mbr; + } + } + return mbr; } -enum pim_msdp_err -pim_msdp_mg_mbr_add(const char *mesh_group_name, struct in_addr mbr_ip) +enum pim_msdp_err pim_msdp_mg_mbr_add(const char *mesh_group_name, + struct in_addr mbr_ip) { - int rc; - struct pim_msdp_mg_mbr *mbr; - struct pim_msdp_mg *mg; + int rc; + struct pim_msdp_mg_mbr *mbr; + struct pim_msdp_mg *mg; - rc = pim_msdp_mg_add(mesh_group_name); - if (rc != PIM_MSDP_ERR_NONE) { - return rc; - } + rc = pim_msdp_mg_add(mesh_group_name); + if (rc != PIM_MSDP_ERR_NONE) { + return rc; + } - mg = msdp->mg; - mbr = pim_msdp_mg_mbr_find(mbr_ip); - if (mbr) { - return PIM_MSDP_ERR_MG_MBR_EXISTS; - } + mg = msdp->mg; + mbr = pim_msdp_mg_mbr_find(mbr_ip); + if (mbr) { + return PIM_MSDP_ERR_MG_MBR_EXISTS; + } - mbr = XCALLOC(MTYPE_PIM_MSDP_MG_MBR, sizeof(*mbr)); - if (!mbr) { - zlog_err("%s: PIM XCALLOC(%zu) failure", - __PRETTY_FUNCTION__, sizeof(*mbr)); - /* if there are no references to the mg free it */ - pim_msdp_mg_free(mg); - return PIM_MSDP_ERR_OOM; - } - mbr->mbr_ip = mbr_ip; - listnode_add_sort(mg->mbr_list, mbr); + mbr = XCALLOC(MTYPE_PIM_MSDP_MG_MBR, sizeof(*mbr)); + if (!mbr) { + zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, + sizeof(*mbr)); + /* if there are no references to the mg free it */ + pim_msdp_mg_free(mg); + return PIM_MSDP_ERR_OOM; + } + mbr->mbr_ip = mbr_ip; + listnode_add_sort(mg->mbr_list, mbr); - /* if valid SIP has been configured add peer session */ - if (mg->src_ip.s_addr != INADDR_ANY) { - pim_msdp_peer_add(mbr_ip, mg->src_ip, mesh_group_name, - &mbr->mp); - } + /* if valid SIP has been configured add peer session */ + if (mg->src_ip.s_addr != INADDR_ANY) { + pim_msdp_peer_add(mbr_ip, mg->src_ip, mesh_group_name, + &mbr->mp); + } - if (PIM_DEBUG_MSDP_EVENTS) { - char ip_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", mbr->mbr_ip, ip_str, sizeof(ip_str)); - zlog_debug("MSDP mesh-group %s mbr %s created", mg->mesh_group_name, ip_str); - } - ++mg->mbr_cnt; - return PIM_MSDP_ERR_NONE; + if (PIM_DEBUG_MSDP_EVENTS) { + char ip_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", mbr->mbr_ip, ip_str, sizeof(ip_str)); + zlog_debug("MSDP mesh-group %s mbr %s created", + mg->mesh_group_name, ip_str); + } + ++mg->mbr_cnt; + return PIM_MSDP_ERR_NONE; } -static void -pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg, struct pim_msdp_mg_mbr *mbr) +static void pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg, + struct pim_msdp_mg_mbr *mbr) { - /* Delete active peer session if any */ - if (mbr->mp) { - pim_msdp_peer_do_del(mbr->mp); - } + /* Delete active peer session if any */ + if (mbr->mp) { + pim_msdp_peer_do_del(mbr->mp); + } - listnode_delete(mg->mbr_list, mbr); - if (PIM_DEBUG_MSDP_EVENTS) { - char ip_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", mbr->mbr_ip, ip_str, sizeof(ip_str)); - zlog_debug("MSDP mesh-group %s mbr %s deleted", mg->mesh_group_name, ip_str); - } - pim_msdp_mg_mbr_free(mbr); - if (mg->mbr_cnt) { - --mg->mbr_cnt; - } + listnode_delete(mg->mbr_list, mbr); + if (PIM_DEBUG_MSDP_EVENTS) { + char ip_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", mbr->mbr_ip, ip_str, sizeof(ip_str)); + zlog_debug("MSDP mesh-group %s mbr %s deleted", + mg->mesh_group_name, ip_str); + } + pim_msdp_mg_mbr_free(mbr); + if (mg->mbr_cnt) { + --mg->mbr_cnt; + } } -enum pim_msdp_err -pim_msdp_mg_mbr_del(const char *mesh_group_name, struct in_addr mbr_ip) -{ - struct pim_msdp_mg_mbr *mbr; - struct pim_msdp_mg *mg = msdp->mg; - - if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { - return PIM_MSDP_ERR_NO_MG; - } - - mbr = pim_msdp_mg_mbr_find(mbr_ip); - if (!mbr) { - return PIM_MSDP_ERR_NO_MG_MBR; - } - - pim_msdp_mg_mbr_do_del(mg, mbr); - /* if there are no references to the mg free it */ - pim_msdp_mg_free(mg); - - return PIM_MSDP_ERR_NONE; -} - -static void -pim_msdp_mg_src_do_del(void) -{ - struct pim_msdp_mg_mbr *mbr; - struct listnode *mbr_node; - struct pim_msdp_mg *mg = msdp->mg; - - /* SIP is being removed - tear down all active peer sessions */ - for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbr_node, mbr)) { - if (mbr->mp) { - pim_msdp_peer_do_del(mbr->mp); - mbr->mp = NULL; - } - } - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP mesh-group %s src cleared", mg->mesh_group_name); - } -} - -enum pim_msdp_err -pim_msdp_mg_src_del(const char *mesh_group_name) -{ - struct pim_msdp_mg *mg = msdp->mg; - - if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { - return PIM_MSDP_ERR_NO_MG; - } - - if (mg->src_ip.s_addr != INADDR_ANY) { - mg->src_ip.s_addr = INADDR_ANY; - pim_msdp_mg_src_do_del(); - /* if there are no references to the mg free it */ - pim_msdp_mg_free(mg); - } - return PIM_MSDP_ERR_NONE; -} - -enum pim_msdp_err -pim_msdp_mg_src_add(const char *mesh_group_name, struct in_addr src_ip) -{ - int rc; - struct pim_msdp_mg_mbr *mbr; - struct listnode *mbr_node; - struct pim_msdp_mg *mg; - - if (src_ip.s_addr == INADDR_ANY) { - pim_msdp_mg_src_del(mesh_group_name); - return PIM_MSDP_ERR_NONE; - } - - rc = pim_msdp_mg_add(mesh_group_name); - if (rc != PIM_MSDP_ERR_NONE) { - return rc; - } - - mg = msdp->mg; - if (mg->src_ip.s_addr != INADDR_ANY) { - pim_msdp_mg_src_do_del(); - } - mg->src_ip = src_ip; +enum pim_msdp_err pim_msdp_mg_mbr_del(const char *mesh_group_name, + struct in_addr mbr_ip) +{ + struct pim_msdp_mg_mbr *mbr; + struct pim_msdp_mg *mg = msdp->mg; + + if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { + return PIM_MSDP_ERR_NO_MG; + } + + mbr = pim_msdp_mg_mbr_find(mbr_ip); + if (!mbr) { + return PIM_MSDP_ERR_NO_MG_MBR; + } + + pim_msdp_mg_mbr_do_del(mg, mbr); + /* if there are no references to the mg free it */ + pim_msdp_mg_free(mg); + + return PIM_MSDP_ERR_NONE; +} + +static void pim_msdp_mg_src_do_del(void) +{ + struct pim_msdp_mg_mbr *mbr; + struct listnode *mbr_node; + struct pim_msdp_mg *mg = msdp->mg; + + /* SIP is being removed - tear down all active peer sessions */ + for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbr_node, mbr)) { + if (mbr->mp) { + pim_msdp_peer_do_del(mbr->mp); + mbr->mp = NULL; + } + } + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_debug("MSDP mesh-group %s src cleared", + mg->mesh_group_name); + } +} + +enum pim_msdp_err pim_msdp_mg_src_del(const char *mesh_group_name) +{ + struct pim_msdp_mg *mg = msdp->mg; + + if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { + return PIM_MSDP_ERR_NO_MG; + } + + if (mg->src_ip.s_addr != INADDR_ANY) { + mg->src_ip.s_addr = INADDR_ANY; + pim_msdp_mg_src_do_del(); + /* if there are no references to the mg free it */ + pim_msdp_mg_free(mg); + } + return PIM_MSDP_ERR_NONE; +} + +enum pim_msdp_err pim_msdp_mg_src_add(const char *mesh_group_name, + struct in_addr src_ip) +{ + int rc; + struct pim_msdp_mg_mbr *mbr; + struct listnode *mbr_node; + struct pim_msdp_mg *mg; + + if (src_ip.s_addr == INADDR_ANY) { + pim_msdp_mg_src_del(mesh_group_name); + return PIM_MSDP_ERR_NONE; + } + + rc = pim_msdp_mg_add(mesh_group_name); + if (rc != PIM_MSDP_ERR_NONE) { + return rc; + } + + mg = msdp->mg; + if (mg->src_ip.s_addr != INADDR_ANY) { + pim_msdp_mg_src_do_del(); + } + mg->src_ip = src_ip; - for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbr_node, mbr)) { - pim_msdp_peer_add(mbr->mbr_ip, mg->src_ip, mesh_group_name, - &mbr->mp); - } + for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbr_node, mbr)) { + pim_msdp_peer_add(mbr->mbr_ip, mg->src_ip, mesh_group_name, + &mbr->mp); + } - if (PIM_DEBUG_MSDP_EVENTS) { - char ip_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", mg->src_ip, ip_str, sizeof(ip_str)); - zlog_debug("MSDP mesh-group %s src %s set", mg->mesh_group_name, ip_str); - } - return PIM_MSDP_ERR_NONE; + if (PIM_DEBUG_MSDP_EVENTS) { + char ip_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", mg->src_ip, ip_str, sizeof(ip_str)); + zlog_debug("MSDP mesh-group %s src %s set", mg->mesh_group_name, + ip_str); + } + return PIM_MSDP_ERR_NONE; } /*********************** MSDP feature APIs *********************************/ -int -pim_msdp_config_write(struct vty *vty) -{ - struct listnode *mbrnode; - struct pim_msdp_mg_mbr *mbr; - struct pim_msdp_mg *mg = msdp->mg; - char mbr_str[INET_ADDRSTRLEN]; - char src_str[INET_ADDRSTRLEN]; - int count = 0; - - if (!mg) { - return count; - } - - if (mg->src_ip.s_addr != INADDR_ANY) { - pim_inet4_dump("", mg->src_ip, src_str, sizeof(src_str)); - vty_out (vty, "ip msdp mesh-group %s source %s\n", - mg->mesh_group_name, src_str); - ++count; - } - - for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) { - pim_inet4_dump("", mbr->mbr_ip, mbr_str, sizeof(mbr_str)); - vty_out (vty, "ip msdp mesh-group %s member %s\n", - mg->mesh_group_name, mbr_str); - ++count; - } - return count; +int pim_msdp_config_write(struct vty *vty) +{ + struct listnode *mbrnode; + struct pim_msdp_mg_mbr *mbr; + struct pim_msdp_mg *mg = msdp->mg; + char mbr_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; + int count = 0; + + if (!mg) { + return count; + } + + if (mg->src_ip.s_addr != INADDR_ANY) { + pim_inet4_dump("", mg->src_ip, src_str, sizeof(src_str)); + vty_out(vty, "ip msdp mesh-group %s source %s\n", + mg->mesh_group_name, src_str); + ++count; + } + + for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) { + pim_inet4_dump("", mbr->mbr_ip, mbr_str, sizeof(mbr_str)); + vty_out(vty, "ip msdp mesh-group %s member %s\n", + mg->mesh_group_name, mbr_str); + ++count; + } + return count; } /* Enable feature including active/periodic timers etc. on the first peer * config. Till then MSDP should just stay quiet. */ -static void -pim_msdp_enable(void) +static void pim_msdp_enable(void) { - if (msdp->flags & PIM_MSDPF_ENABLE) { - /* feature is already enabled */ - return; - } - msdp->flags |= PIM_MSDPF_ENABLE; - msdp->work_obuf = stream_new(PIM_MSDP_MAX_PACKET_SIZE); - pim_msdp_sa_adv_timer_setup(true /* start */); - /* setup sa cache based on local sources */ - pim_msdp_sa_local_setup(); + if (msdp->flags & PIM_MSDPF_ENABLE) { + /* feature is already enabled */ + return; + } + msdp->flags |= PIM_MSDPF_ENABLE; + msdp->work_obuf = stream_new(PIM_MSDP_MAX_PACKET_SIZE); + pim_msdp_sa_adv_timer_setup(true /* start */); + /* setup sa cache based on local sources */ + pim_msdp_sa_local_setup(); } /* MSDP init */ -void -pim_msdp_init(struct thread_master *master) +void pim_msdp_init(struct thread_master *master) { - msdp->master = master; + msdp->master = master; - msdp->peer_hash = hash_create(pim_msdp_peer_hash_key_make, - pim_msdp_peer_hash_eq, NULL); - msdp->peer_list = list_new(); - msdp->peer_list->del = (void (*)(void *))pim_msdp_peer_free; - msdp->peer_list->cmp = (int (*)(void *, void *))pim_msdp_peer_comp; + msdp->peer_hash = hash_create(pim_msdp_peer_hash_key_make, + pim_msdp_peer_hash_eq, NULL); + msdp->peer_list = list_new(); + msdp->peer_list->del = (void (*)(void *))pim_msdp_peer_free; + msdp->peer_list->cmp = (int (*)(void *, void *))pim_msdp_peer_comp; - msdp->sa_hash = hash_create(pim_msdp_sa_hash_key_make, - pim_msdp_sa_hash_eq, NULL); - msdp->sa_list = list_new(); - msdp->sa_list->del = (void (*)(void *))pim_msdp_sa_free; - msdp->sa_list->cmp = (int (*)(void *, void *))pim_msdp_sa_comp; + msdp->sa_hash = hash_create(pim_msdp_sa_hash_key_make, + pim_msdp_sa_hash_eq, NULL); + msdp->sa_list = list_new(); + msdp->sa_list->del = (void (*)(void *))pim_msdp_sa_free; + msdp->sa_list->cmp = (int (*)(void *, void *))pim_msdp_sa_comp; } /* counterpart to MSDP init; XXX: unused currently */ -void -pim_msdp_exit(void) +void pim_msdp_exit(void) { - /* XXX: stop listener and delete all peer sessions */ + /* XXX: stop listener and delete all peer sessions */ - if (msdp->peer_hash) { - hash_free(msdp->peer_hash); - msdp->peer_hash = NULL; - } + if (msdp->peer_hash) { + hash_free(msdp->peer_hash); + msdp->peer_hash = NULL; + } - if (msdp->peer_list) { - list_free(msdp->peer_list); - msdp->peer_list = NULL; - } + if (msdp->peer_list) { + list_free(msdp->peer_list); + msdp->peer_list = NULL; + } } diff --git a/pimd/pim_msdp.h b/pimd/pim_msdp.h index 308b437a6..66e5457df 100644 --- a/pimd/pim_msdp.h +++ b/pimd/pim_msdp.h @@ -20,35 +20,35 @@ #define PIM_MSDP_H enum pim_msdp_peer_state { - PIM_MSDP_DISABLED, - PIM_MSDP_INACTIVE, - PIM_MSDP_LISTEN, - PIM_MSDP_CONNECTING, - PIM_MSDP_ESTABLISHED + PIM_MSDP_DISABLED, + PIM_MSDP_INACTIVE, + PIM_MSDP_LISTEN, + PIM_MSDP_CONNECTING, + PIM_MSDP_ESTABLISHED }; /* SA and KA TLVs are processed; rest ignored */ enum pim_msdp_tlv { - PIM_MSDP_V4_SOURCE_ACTIVE = 1, - PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST, - PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE, - PIM_MSDP_KEEPALIVE, - PIM_MSDP_RESERVED, - PIM_MSDP_TRACEROUTE_PROGRESS, - PIM_MSDP_TRACEROUTE_REPLY, + PIM_MSDP_V4_SOURCE_ACTIVE = 1, + PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST, + PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE, + PIM_MSDP_KEEPALIVE, + PIM_MSDP_RESERVED, + PIM_MSDP_TRACEROUTE_PROGRESS, + PIM_MSDP_TRACEROUTE_REPLY, }; /* MSDP error codes */ enum pim_msdp_err { - PIM_MSDP_ERR_NONE = 0, - PIM_MSDP_ERR_OOM = -1, - PIM_MSDP_ERR_PEER_EXISTS = -2, - PIM_MSDP_ERR_MAX_MESH_GROUPS = -3, - PIM_MSDP_ERR_NO_PEER = -4, - PIM_MSDP_ERR_MG_MBR_EXISTS = -5, - PIM_MSDP_ERR_NO_MG = -6, - PIM_MSDP_ERR_NO_MG_MBR = -7, - PIM_MSDP_ERR_SIP_EQ_DIP = -8, + PIM_MSDP_ERR_NONE = 0, + PIM_MSDP_ERR_OOM = -1, + PIM_MSDP_ERR_PEER_EXISTS = -2, + PIM_MSDP_ERR_MAX_MESH_GROUPS = -3, + PIM_MSDP_ERR_NO_PEER = -4, + PIM_MSDP_ERR_MG_MBR_EXISTS = -5, + PIM_MSDP_ERR_NO_MG = -6, + PIM_MSDP_ERR_NO_MG_MBR = -7, + PIM_MSDP_ERR_SIP_EQ_DIP = -8, }; #define PIM_MSDP_STATE_STRLEN 16 @@ -58,149 +58,155 @@ enum pim_msdp_err { #define PIM_MSDP_SOCKET_SNDBUF_SIZE 65536 enum pim_msdp_sa_flags { - PIM_MSDP_SAF_NONE = 0, - /* There are two cases where we can pickup an active source locally - - * 1. We are RP and got a source-register from the FHR - * 2. We are RP and FHR and learnt a new directly connected source on a - * DR interface */ - PIM_MSDP_SAF_LOCAL = (1 << 0), - /* We got this in the MSDP SA TLV from a peer (and this passed peer-RPF - * checks) */ - PIM_MSDP_SAF_PEER = (1 << 1), - PIM_MSDP_SAF_REF = (PIM_MSDP_SAF_LOCAL | PIM_MSDP_SAF_PEER), - PIM_MSDP_SAF_STALE = (1 << 2), /* local entries can get kicked out on - * misc pim events such as RP change */ - PIM_MSDP_SAF_UP_DEL_IN_PROG = (1 << 3) + PIM_MSDP_SAF_NONE = 0, + /* There are two cases where we can pickup an active source locally - + * 1. We are RP and got a source-register from the FHR + * 2. We are RP and FHR and learnt a new directly connected source on a + * DR interface */ + PIM_MSDP_SAF_LOCAL = (1 << 0), + /* We got this in the MSDP SA TLV from a peer (and this passed peer-RPF + * checks) */ + PIM_MSDP_SAF_PEER = (1 << 1), + PIM_MSDP_SAF_REF = (PIM_MSDP_SAF_LOCAL | PIM_MSDP_SAF_PEER), + PIM_MSDP_SAF_STALE = (1 << 2), /* local entries can get kicked out on + * misc pim events such as RP change */ + PIM_MSDP_SAF_UP_DEL_IN_PROG = (1 << 3) }; struct pim_msdp_sa { - struct prefix_sg sg; - char sg_str[PIM_SG_LEN]; - struct in_addr rp; /* Last RP address associated with this SA */ - struct in_addr peer; /* last peer from who we heard this SA */ - enum pim_msdp_sa_flags flags; - - /* rfc-3618 is missing default value for SA-hold-down-Period. pulled - * this number from industry-standards */ + struct prefix_sg sg; + char sg_str[PIM_SG_LEN]; + struct in_addr rp; /* Last RP address associated with this SA */ + struct in_addr peer; /* last peer from who we heard this SA */ + enum pim_msdp_sa_flags flags; + +/* rfc-3618 is missing default value for SA-hold-down-Period. pulled + * this number from industry-standards */ #define PIM_MSDP_SA_HOLD_TIME ((3*60)+30) - struct thread *sa_state_timer; // 5.6 - int64_t uptime; + struct thread *sa_state_timer; // 5.6 + int64_t uptime; - struct pim_upstream *up; + struct pim_upstream *up; }; enum pim_msdp_peer_flags { - PIM_MSDP_PEERF_NONE = 0, - PIM_MSDP_PEERF_LISTENER = (1 << 0), + PIM_MSDP_PEERF_NONE = 0, + PIM_MSDP_PEERF_LISTENER = (1 << 0), #define PIM_MSDP_PEER_IS_LISTENER(mp) (mp->flags & PIM_MSDP_PEERF_LISTENER) - PIM_MSDP_PEERF_SA_JUST_SENT = (1 << 1) + PIM_MSDP_PEERF_SA_JUST_SENT = (1 << 1) }; struct pim_msdp_peer { - /* configuration */ - struct in_addr local; - struct in_addr peer; - char *mesh_group_name; - char key_str[INET_ADDRSTRLEN]; - - /* state */ - enum pim_msdp_peer_state state; - enum pim_msdp_peer_flags flags; - - /* TCP socket info */ - union sockunion su_local; - union sockunion su_peer; - int fd; - - /* protocol timers */ + /* configuration */ + struct in_addr local; + struct in_addr peer; + char *mesh_group_name; + char key_str[INET_ADDRSTRLEN]; + + /* state */ + enum pim_msdp_peer_state state; + enum pim_msdp_peer_flags flags; + + /* TCP socket info */ + union sockunion su_local; + union sockunion su_peer; + int fd; + +/* protocol timers */ #define PIM_MSDP_PEER_HOLD_TIME 75 - struct thread *hold_timer; // 5.4 + struct thread *hold_timer; // 5.4 + /* $FRR indent$ */ +/* clang-format off */ #define PIM_MSDP_PEER_KA_TIME 60 - struct thread *ka_timer; // 5.5 + struct thread *ka_timer; // 5.5 + /* $FRR indent$ */ + /* clang-format off */ #define PIM_MSDP_PEER_CONNECT_RETRY_TIME 30 - struct thread *cr_timer; // 5.6 - - /* packet thread and buffers */ - uint32_t packet_size; - struct stream *ibuf; - struct stream_fifo *obuf; - struct thread *t_read; - struct thread *t_write; - - /* stats */ - uint32_t conn_attempts; - uint32_t est_flaps; - uint32_t sa_cnt; /* number of SAs attributed to this peer */ + struct thread *cr_timer; // 5.6 + + /* packet thread and buffers */ + uint32_t packet_size; + struct stream *ibuf; + struct stream_fifo *obuf; + struct thread *t_read; + struct thread *t_write; + + /* stats */ + uint32_t conn_attempts; + uint32_t est_flaps; + uint32_t sa_cnt; /* number of SAs attributed to this peer */ + /* $FRR indent$ */ + /* clang-format off */ #define PIM_MSDP_PEER_LAST_RESET_STR 20 - char last_reset[PIM_MSDP_PEER_LAST_RESET_STR]; + char last_reset[PIM_MSDP_PEER_LAST_RESET_STR]; - /* packet stats */ - uint32_t ka_tx_cnt; - uint32_t sa_tx_cnt; - uint32_t ka_rx_cnt; - uint32_t sa_rx_cnt; - uint32_t unk_rx_cnt; + /* packet stats */ + uint32_t ka_tx_cnt; + uint32_t sa_tx_cnt; + uint32_t ka_rx_cnt; + uint32_t sa_rx_cnt; + uint32_t unk_rx_cnt; - /* timestamps */ - int64_t uptime; + /* timestamps */ + int64_t uptime; }; struct pim_msdp_mg_mbr { - struct in_addr mbr_ip; - struct pim_msdp_peer *mp; + struct in_addr mbr_ip; + struct pim_msdp_peer *mp; }; /* PIM MSDP mesh-group */ struct pim_msdp_mg { - char *mesh_group_name; - struct in_addr src_ip; - uint32_t mbr_cnt; - struct list *mbr_list; + char *mesh_group_name; + struct in_addr src_ip; + uint32_t mbr_cnt; + struct list *mbr_list; }; enum pim_msdp_flags { - PIM_MSDPF_NONE = 0, - PIM_MSDPF_ENABLE = (1 << 0), - PIM_MSDPF_LISTENER = (1 << 1) + PIM_MSDPF_NONE = 0, + PIM_MSDPF_ENABLE = (1 << 0), + PIM_MSDPF_LISTENER = (1 << 1) }; struct pim_msdp_listener { - int fd; - union sockunion su; - struct thread *thread; + int fd; + union sockunion su; + struct thread *thread; }; struct pim_msdp { - enum pim_msdp_flags flags; - struct thread_master *master; - struct pim_msdp_listener listener; - uint32_t rejected_accepts; + enum pim_msdp_flags flags; + struct thread_master *master; + struct pim_msdp_listener listener; + uint32_t rejected_accepts; - /* MSDP peer info */ - struct hash *peer_hash; - struct list *peer_list; + /* MSDP peer info */ + struct hash *peer_hash; + struct list *peer_list; - /* MSDP active-source info */ +/* MSDP active-source info */ #define PIM_MSDP_SA_ADVERTISMENT_TIME 60 - struct thread *sa_adv_timer; // 5.6 - struct hash *sa_hash; - struct list *sa_list; - uint32_t local_cnt; + struct thread *sa_adv_timer; // 5.6 + struct hash *sa_hash; + struct list *sa_list; + uint32_t local_cnt; - /* keep a scratch pad for building SA TLVs */ - struct stream *work_obuf; + /* keep a scratch pad for building SA TLVs */ + struct stream *work_obuf; - struct in_addr originator_id; + struct in_addr originator_id; - /* currently only one mesh-group is supported - so just stash it here */ - struct pim_msdp_mg *mg; + /* currently only one mesh-group is supported - so just stash it here */ + struct pim_msdp_mg *mg; }; -#define PIM_MSDP_PEER_READ_ON(mp) \ - thread_add_read (msdp->master, pim_msdp_read, mp, mp->fd, &mp->t_read) +#define PIM_MSDP_PEER_READ_ON(mp) \ + thread_add_read(msdp->master, pim_msdp_read, mp, mp->fd, &mp->t_read) -#define PIM_MSDP_PEER_WRITE_ON(mp) \ - thread_add_write (msdp->master, pim_msdp_write, mp, mp->fd, &mp->t_write) +#define PIM_MSDP_PEER_WRITE_ON(mp) \ + thread_add_write(msdp->master, pim_msdp_write, mp, mp->fd, &mp->t_write) #define PIM_MSDP_PEER_READ_OFF(mp) THREAD_READ_OFF(mp->t_read) #define PIM_MSDP_PEER_WRITE_OFF(mp) THREAD_WRITE_OFF(mp->t_write) @@ -208,28 +214,36 @@ struct pim_msdp { extern struct pim_msdp *msdp; void pim_msdp_init(struct thread_master *master); void pim_msdp_exit(void); -enum pim_msdp_err pim_msdp_peer_add(struct in_addr peer, struct in_addr local, const char *mesh_group_name, struct pim_msdp_peer **mp_p); +enum pim_msdp_err pim_msdp_peer_add(struct in_addr peer, struct in_addr local, + const char *mesh_group_name, + struct pim_msdp_peer **mp_p); enum pim_msdp_err pim_msdp_peer_del(struct in_addr peer_addr); -char *pim_msdp_state_dump(enum pim_msdp_peer_state state, char *buf, int buf_size); +char *pim_msdp_state_dump(enum pim_msdp_peer_state state, char *buf, + int buf_size); struct pim_msdp_peer *pim_msdp_peer_find(struct in_addr peer_addr); void pim_msdp_peer_established(struct pim_msdp_peer *mp); void pim_msdp_peer_pkt_rxed(struct pim_msdp_peer *mp); void pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state); void pim_msdp_peer_reset_tcp_conn(struct pim_msdp_peer *mp, const char *rc_str); int pim_msdp_write(struct thread *thread); -char *pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size, bool long_format); +char *pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size, + bool long_format); int pim_msdp_config_write(struct vty *vty); void pim_msdp_peer_pkt_txed(struct pim_msdp_peer *mp); -void pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, struct in_addr rp); +void pim_msdp_sa_ref(struct pim_msdp_peer *mp, struct prefix_sg *sg, + struct in_addr rp); void pim_msdp_sa_local_update(struct pim_upstream *up); void pim_msdp_sa_local_del(struct prefix_sg *sg); void pim_msdp_i_am_rp_changed(void); bool pim_msdp_peer_rpf_check(struct pim_msdp_peer *mp, struct in_addr rp); void pim_msdp_up_join_state_changed(struct pim_upstream *xg_up); void pim_msdp_up_del(struct prefix_sg *sg); -enum pim_msdp_err pim_msdp_mg_mbr_add(const char *mesh_group_name, struct in_addr mbr_ip); -enum pim_msdp_err pim_msdp_mg_mbr_del(const char *mesh_group_name, struct in_addr mbr_ip); +enum pim_msdp_err pim_msdp_mg_mbr_add(const char *mesh_group_name, + struct in_addr mbr_ip); +enum pim_msdp_err pim_msdp_mg_mbr_del(const char *mesh_group_name, + struct in_addr mbr_ip); enum pim_msdp_err pim_msdp_mg_src_del(const char *mesh_group_name); -enum pim_msdp_err pim_msdp_mg_src_add(const char *mesh_group_name, struct in_addr src_ip); +enum pim_msdp_err pim_msdp_mg_src_add(const char *mesh_group_name, + struct in_addr src_ip); enum pim_msdp_err pim_msdp_mg_del(const char *mesh_group_name); #endif diff --git a/pimd/pim_msdp_packet.c b/pimd/pim_msdp_packet.c index 0a8679336..01ce293e3 100644 --- a/pimd/pim_msdp_packet.c +++ b/pimd/pim_msdp_packet.c @@ -31,665 +31,661 @@ #include "pim_msdp_packet.h" #include "pim_msdp_socket.h" -static char * -pim_msdp_pkt_type_dump(enum pim_msdp_tlv type, char *buf, int buf_size) +static char *pim_msdp_pkt_type_dump(enum pim_msdp_tlv type, char *buf, + int buf_size) { - switch (type) { - case PIM_MSDP_V4_SOURCE_ACTIVE: - snprintf(buf, buf_size, "%s", "SA"); - break; - case PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST: - snprintf(buf, buf_size, "%s", "SA_REQ"); - break; - case PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE: - snprintf(buf, buf_size, "%s", "SA_RESP"); - break; - case PIM_MSDP_KEEPALIVE: - snprintf(buf, buf_size, "%s", "KA"); - break; - case PIM_MSDP_RESERVED: - snprintf(buf, buf_size, "%s", "RSVD"); - break; - case PIM_MSDP_TRACEROUTE_PROGRESS: - snprintf(buf, buf_size, "%s", "TRACE_PROG"); - break; - case PIM_MSDP_TRACEROUTE_REPLY: - snprintf(buf, buf_size, "%s", "TRACE_REPLY"); - break; - default: - snprintf(buf, buf_size, "UNK-%d", type); - } - return buf; + switch (type) { + case PIM_MSDP_V4_SOURCE_ACTIVE: + snprintf(buf, buf_size, "%s", "SA"); + break; + case PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST: + snprintf(buf, buf_size, "%s", "SA_REQ"); + break; + case PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE: + snprintf(buf, buf_size, "%s", "SA_RESP"); + break; + case PIM_MSDP_KEEPALIVE: + snprintf(buf, buf_size, "%s", "KA"); + break; + case PIM_MSDP_RESERVED: + snprintf(buf, buf_size, "%s", "RSVD"); + break; + case PIM_MSDP_TRACEROUTE_PROGRESS: + snprintf(buf, buf_size, "%s", "TRACE_PROG"); + break; + case PIM_MSDP_TRACEROUTE_REPLY: + snprintf(buf, buf_size, "%s", "TRACE_REPLY"); + break; + default: + snprintf(buf, buf_size, "UNK-%d", type); + } + return buf; } -static void -pim_msdp_pkt_sa_dump_one(struct stream *s) +static void pim_msdp_pkt_sa_dump_one(struct stream *s) { - struct prefix_sg sg; + struct prefix_sg sg; - /* just throw away the three reserved bytes */ - stream_get3(s); - /* throw away the prefix length also */ - stream_getc(s); + /* just throw away the three reserved bytes */ + stream_get3(s); + /* throw away the prefix length also */ + stream_getc(s); - memset(&sg, 0, sizeof (struct prefix_sg)); - sg.grp.s_addr = stream_get_ipv4(s); - sg.src.s_addr = stream_get_ipv4(s); + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.grp.s_addr = stream_get_ipv4(s); + sg.src.s_addr = stream_get_ipv4(s); - zlog_debug(" sg %s", pim_str_sg_dump(&sg)); + zlog_debug(" sg %s", pim_str_sg_dump(&sg)); } -static void -pim_msdp_pkt_sa_dump(struct stream *s) +static void pim_msdp_pkt_sa_dump(struct stream *s) { - int entry_cnt; - int i; - struct in_addr rp; /* Last RP address associated with this SA */ - - entry_cnt = stream_getc(s); - rp.s_addr = stream_get_ipv4(s); - - if (PIM_DEBUG_MSDP_PACKETS) { - char rp_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", rp, rp_str, sizeof(rp_str)); - zlog_debug(" entry_cnt %d rp %s", entry_cnt, rp_str); - } - - /* dump SAs */ - for (i = 0; i < entry_cnt; ++i) { - pim_msdp_pkt_sa_dump_one(s); - } + int entry_cnt; + int i; + struct in_addr rp; /* Last RP address associated with this SA */ + + entry_cnt = stream_getc(s); + rp.s_addr = stream_get_ipv4(s); + + if (PIM_DEBUG_MSDP_PACKETS) { + char rp_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", rp, rp_str, sizeof(rp_str)); + zlog_debug(" entry_cnt %d rp %s", entry_cnt, rp_str); + } + + /* dump SAs */ + for (i = 0; i < entry_cnt; ++i) { + pim_msdp_pkt_sa_dump_one(s); + } } -static void -pim_msdp_pkt_dump(struct pim_msdp_peer *mp, int type, int len, bool rx, - struct stream *s) +static void pim_msdp_pkt_dump(struct pim_msdp_peer *mp, int type, int len, + bool rx, struct stream *s) { - char type_str[PIM_MSDP_PKT_TYPE_STRLEN]; + char type_str[PIM_MSDP_PKT_TYPE_STRLEN]; - pim_msdp_pkt_type_dump(type, type_str, sizeof(type_str)); + pim_msdp_pkt_type_dump(type, type_str, sizeof(type_str)); - zlog_debug("MSDP peer %s pkt %s type %s len %d", - mp->key_str, rx?"rx":"tx", type_str, len); + zlog_debug("MSDP peer %s pkt %s type %s len %d", mp->key_str, + rx ? "rx" : "tx", type_str, len); - if (!s) { - return; - } + if (!s) { + return; + } - switch(type) { - case PIM_MSDP_V4_SOURCE_ACTIVE: - pim_msdp_pkt_sa_dump(s); - break; - default:; - } + switch (type) { + case PIM_MSDP_V4_SOURCE_ACTIVE: + pim_msdp_pkt_sa_dump(s); + break; + default:; + } } /* Check file descriptor whether connect is established. */ -static void -pim_msdp_connect_check(struct pim_msdp_peer *mp) +static void pim_msdp_connect_check(struct pim_msdp_peer *mp) { - int status; - socklen_t slen; - int ret; - - if (mp->state != PIM_MSDP_CONNECTING) { - /* if we are here it means we are not in a connecting or established state - * for now treat this as a fatal error */ - pim_msdp_peer_reset_tcp_conn(mp, "invalid-state"); - return; - } - - PIM_MSDP_PEER_READ_OFF(mp); - PIM_MSDP_PEER_WRITE_OFF(mp); - - /* Check file descriptor. */ - slen = sizeof(status); - ret = getsockopt(mp->fd, SOL_SOCKET, SO_ERROR, (void *)&status, &slen); - - /* If getsockopt is fail, this is fatal error. */ - if (ret < 0) { - zlog_err("can't get sockopt for nonblocking connect"); - pim_msdp_peer_reset_tcp_conn(mp, "connect-failed"); - return; - } - - /* When status is 0 then TCP connection is established. */ - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s pim_connect_check %s", mp->key_str, status?"fail":"success"); - } - if (status == 0) { - pim_msdp_peer_established(mp); - } else { - pim_msdp_peer_reset_tcp_conn(mp, "connect-failed"); - } + int status; + socklen_t slen; + int ret; + + if (mp->state != PIM_MSDP_CONNECTING) { + /* if we are here it means we are not in a connecting or + * established state + * for now treat this as a fatal error */ + pim_msdp_peer_reset_tcp_conn(mp, "invalid-state"); + return; + } + + PIM_MSDP_PEER_READ_OFF(mp); + PIM_MSDP_PEER_WRITE_OFF(mp); + + /* Check file descriptor. */ + slen = sizeof(status); + ret = getsockopt(mp->fd, SOL_SOCKET, SO_ERROR, (void *)&status, &slen); + + /* If getsockopt is fail, this is fatal error. */ + if (ret < 0) { + zlog_err("can't get sockopt for nonblocking connect"); + pim_msdp_peer_reset_tcp_conn(mp, "connect-failed"); + return; + } + + /* When status is 0 then TCP connection is established. */ + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s pim_connect_check %s", mp->key_str, + status ? "fail" : "success"); + } + if (status == 0) { + pim_msdp_peer_established(mp); + } else { + pim_msdp_peer_reset_tcp_conn(mp, "connect-failed"); + } } -static void -pim_msdp_pkt_delete(struct pim_msdp_peer *mp) +static void pim_msdp_pkt_delete(struct pim_msdp_peer *mp) { - stream_free(stream_fifo_pop(mp->obuf)); + stream_free(stream_fifo_pop(mp->obuf)); } -static void -pim_msdp_pkt_add(struct pim_msdp_peer *mp, struct stream *s) +static void pim_msdp_pkt_add(struct pim_msdp_peer *mp, struct stream *s) { - stream_fifo_push(mp->obuf, s); + stream_fifo_push(mp->obuf, s); } -static void -pim_msdp_write_proceed_actions(struct pim_msdp_peer *mp) +static void pim_msdp_write_proceed_actions(struct pim_msdp_peer *mp) { - if (stream_fifo_head(mp->obuf)) { - PIM_MSDP_PEER_WRITE_ON(mp); - } + if (stream_fifo_head(mp->obuf)) { + PIM_MSDP_PEER_WRITE_ON(mp); + } } -int -pim_msdp_write(struct thread *thread) +int pim_msdp_write(struct thread *thread) { - struct pim_msdp_peer *mp; - struct stream *s; - int num; - enum pim_msdp_tlv type; - int len; - int work_cnt = 0; - int work_max_cnt = 100; - - mp = THREAD_ARG(thread); - mp->t_write = NULL; - - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s pim_msdp_write", mp->key_str); - } - if (mp->fd < 0) { - return -1; - } - - /* check if TCP connection is established */ - if (mp->state != PIM_MSDP_ESTABLISHED) { - pim_msdp_connect_check(mp); - return 0; - } - - s = stream_fifo_head(mp->obuf); - if (!s) { - pim_msdp_write_proceed_actions(mp); - return 0; - } - - sockopt_cork(mp->fd, 1); - - /* Nonblocking write until TCP output buffer is full */ - do - { - int writenum; - - /* Number of bytes to be sent */ - writenum = stream_get_endp(s) - stream_get_getp(s); - - /* Call write() system call */ - num = write(mp->fd, STREAM_PNT(s), writenum); - if (num < 0) { - /* write failed either retry needed or error */ - if (ERRNO_IO_RETRY(errno)) { - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s pim_msdp_write io retry", mp->key_str); - } - break; - } - - pim_msdp_peer_reset_tcp_conn(mp, "pkt-tx-failed"); - return 0; - } - - if (num != writenum) { - /* Partial write */ - stream_forward_getp(s, num); - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s pim_msdp_partial_write", mp->key_str); - } - break; - } - - /* Retrieve msdp packet type. */ - stream_set_getp(s,0); - type = stream_getc(s); - len = stream_getw(s); - switch (type) - { - case PIM_MSDP_KEEPALIVE: - mp->ka_tx_cnt++; - break; - case PIM_MSDP_V4_SOURCE_ACTIVE: - mp->sa_tx_cnt++; - break; - default:; - } - if (PIM_DEBUG_MSDP_PACKETS) { - pim_msdp_pkt_dump(mp, type, len, false /*rx*/, s); - } - - /* packet sent delete it. */ - pim_msdp_pkt_delete(mp); - - ++work_cnt; - /* may need to pause if we have done too much work in this - * loop */ - if (work_cnt >= work_max_cnt) { - break; - } - } while ((s = stream_fifo_head(mp->obuf)) != NULL); - pim_msdp_write_proceed_actions(mp); - - sockopt_cork(mp->fd, 0); - - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s pim_msdp_write wrote %d packets", mp->key_str, work_cnt); - } - - return 0; + struct pim_msdp_peer *mp; + struct stream *s; + int num; + enum pim_msdp_tlv type; + int len; + int work_cnt = 0; + int work_max_cnt = 100; + + mp = THREAD_ARG(thread); + mp->t_write = NULL; + + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s pim_msdp_write", mp->key_str); + } + if (mp->fd < 0) { + return -1; + } + + /* check if TCP connection is established */ + if (mp->state != PIM_MSDP_ESTABLISHED) { + pim_msdp_connect_check(mp); + return 0; + } + + s = stream_fifo_head(mp->obuf); + if (!s) { + pim_msdp_write_proceed_actions(mp); + return 0; + } + + sockopt_cork(mp->fd, 1); + + /* Nonblocking write until TCP output buffer is full */ + do { + int writenum; + + /* Number of bytes to be sent */ + writenum = stream_get_endp(s) - stream_get_getp(s); + + /* Call write() system call */ + num = write(mp->fd, STREAM_PNT(s), writenum); + if (num < 0) { + /* write failed either retry needed or error */ + if (ERRNO_IO_RETRY(errno)) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug( + "MSDP peer %s pim_msdp_write io retry", + mp->key_str); + } + break; + } + + pim_msdp_peer_reset_tcp_conn(mp, "pkt-tx-failed"); + return 0; + } + + if (num != writenum) { + /* Partial write */ + stream_forward_getp(s, num); + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug( + "MSDP peer %s pim_msdp_partial_write", + mp->key_str); + } + break; + } + + /* Retrieve msdp packet type. */ + stream_set_getp(s, 0); + type = stream_getc(s); + len = stream_getw(s); + switch (type) { + case PIM_MSDP_KEEPALIVE: + mp->ka_tx_cnt++; + break; + case PIM_MSDP_V4_SOURCE_ACTIVE: + mp->sa_tx_cnt++; + break; + default:; + } + if (PIM_DEBUG_MSDP_PACKETS) { + pim_msdp_pkt_dump(mp, type, len, false /*rx*/, s); + } + + /* packet sent delete it. */ + pim_msdp_pkt_delete(mp); + + ++work_cnt; + /* may need to pause if we have done too much work in this + * loop */ + if (work_cnt >= work_max_cnt) { + break; + } + } while ((s = stream_fifo_head(mp->obuf)) != NULL); + pim_msdp_write_proceed_actions(mp); + + sockopt_cork(mp->fd, 0); + + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s pim_msdp_write wrote %d packets", + mp->key_str, work_cnt); + } + + return 0; } -static void -pim_msdp_pkt_send(struct pim_msdp_peer *mp, struct stream *s) +static void pim_msdp_pkt_send(struct pim_msdp_peer *mp, struct stream *s) { - /* Add packet to the end of list. */ - pim_msdp_pkt_add(mp, s); + /* Add packet to the end of list. */ + pim_msdp_pkt_add(mp, s); - PIM_MSDP_PEER_WRITE_ON(mp); + PIM_MSDP_PEER_WRITE_ON(mp); } -void -pim_msdp_pkt_ka_tx(struct pim_msdp_peer *mp) +void pim_msdp_pkt_ka_tx(struct pim_msdp_peer *mp) { - struct stream *s; + struct stream *s; - if (mp->state != PIM_MSDP_ESTABLISHED) { - /* don't tx anything unless a session is established */ - return; - } - s = stream_new(PIM_MSDP_KA_TLV_MAX_SIZE); - stream_putc(s, PIM_MSDP_KEEPALIVE); - stream_putw(s, PIM_MSDP_KA_TLV_MAX_SIZE); + if (mp->state != PIM_MSDP_ESTABLISHED) { + /* don't tx anything unless a session is established */ + return; + } + s = stream_new(PIM_MSDP_KA_TLV_MAX_SIZE); + stream_putc(s, PIM_MSDP_KEEPALIVE); + stream_putw(s, PIM_MSDP_KA_TLV_MAX_SIZE); - pim_msdp_pkt_send(mp, s); + pim_msdp_pkt_send(mp, s); } -static void -pim_msdp_pkt_sa_push_to_one_peer(struct pim_msdp_peer *mp) +static void pim_msdp_pkt_sa_push_to_one_peer(struct pim_msdp_peer *mp) { - struct stream *s; - - if (mp->state != PIM_MSDP_ESTABLISHED) { - /* don't tx anything unless a session is established */ - return; - } - s = stream_dup(msdp->work_obuf); - if (s) { - pim_msdp_pkt_send(mp, s); - mp->flags |= PIM_MSDP_PEERF_SA_JUST_SENT; - } + struct stream *s; + + if (mp->state != PIM_MSDP_ESTABLISHED) { + /* don't tx anything unless a session is established */ + return; + } + s = stream_dup(msdp->work_obuf); + if (s) { + pim_msdp_pkt_send(mp, s); + mp->flags |= PIM_MSDP_PEERF_SA_JUST_SENT; + } } /* push the stream into the obuf fifo of all the peers */ -static void -pim_msdp_pkt_sa_push(struct pim_msdp_peer *mp) +static void pim_msdp_pkt_sa_push(struct pim_msdp_peer *mp) { - struct listnode *mpnode; - - if (mp) { - pim_msdp_pkt_sa_push_to_one_peer(mp); - } else { - for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s pim_msdp_pkt_sa_push", mp->key_str); - } - pim_msdp_pkt_sa_push_to_one_peer(mp); - } - } + struct listnode *mpnode; + + if (mp) { + pim_msdp_pkt_sa_push_to_one_peer(mp); + } else { + for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s pim_msdp_pkt_sa_push", + mp->key_str); + } + pim_msdp_pkt_sa_push_to_one_peer(mp); + } + } } -static int -pim_msdp_pkt_sa_fill_hdr(int local_cnt) +static int pim_msdp_pkt_sa_fill_hdr(int local_cnt) { - int curr_tlv_ecnt; - - stream_reset(msdp->work_obuf); - curr_tlv_ecnt = local_cnt>PIM_MSDP_SA_MAX_ENTRY_CNT?PIM_MSDP_SA_MAX_ENTRY_CNT:local_cnt; - local_cnt -= curr_tlv_ecnt; - stream_putc(msdp->work_obuf, PIM_MSDP_V4_SOURCE_ACTIVE); - stream_putw(msdp->work_obuf, PIM_MSDP_SA_ENTRY_CNT2SIZE(curr_tlv_ecnt)); - stream_putc(msdp->work_obuf, curr_tlv_ecnt); - stream_put_ipv4(msdp->work_obuf, msdp->originator_id.s_addr); - - return local_cnt; + int curr_tlv_ecnt; + + stream_reset(msdp->work_obuf); + curr_tlv_ecnt = local_cnt > PIM_MSDP_SA_MAX_ENTRY_CNT + ? PIM_MSDP_SA_MAX_ENTRY_CNT + : local_cnt; + local_cnt -= curr_tlv_ecnt; + stream_putc(msdp->work_obuf, PIM_MSDP_V4_SOURCE_ACTIVE); + stream_putw(msdp->work_obuf, PIM_MSDP_SA_ENTRY_CNT2SIZE(curr_tlv_ecnt)); + stream_putc(msdp->work_obuf, curr_tlv_ecnt); + stream_put_ipv4(msdp->work_obuf, msdp->originator_id.s_addr); + + return local_cnt; } -static void -pim_msdp_pkt_sa_fill_one(struct pim_msdp_sa *sa) +static void pim_msdp_pkt_sa_fill_one(struct pim_msdp_sa *sa) { - stream_put3(msdp->work_obuf, 0 /* reserved */); - stream_putc(msdp->work_obuf, 32 /* sprefix len */); - stream_put_ipv4(msdp->work_obuf, sa->sg.grp.s_addr); - stream_put_ipv4(msdp->work_obuf, sa->sg.src.s_addr); + stream_put3(msdp->work_obuf, 0 /* reserved */); + stream_putc(msdp->work_obuf, 32 /* sprefix len */); + stream_put_ipv4(msdp->work_obuf, sa->sg.grp.s_addr); + stream_put_ipv4(msdp->work_obuf, sa->sg.src.s_addr); } -static void -pim_msdp_pkt_sa_gen(struct pim_msdp_peer *mp) +static void pim_msdp_pkt_sa_gen(struct pim_msdp_peer *mp) { - struct listnode *sanode; - struct pim_msdp_sa *sa; - int sa_count; - int local_cnt = msdp->local_cnt; - - sa_count = 0; - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug(" sa gen %d", local_cnt); - } - - local_cnt = pim_msdp_pkt_sa_fill_hdr(local_cnt); - - for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { - if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { - /* current implementation of MSDP is for anycast i.e. full mesh. so - * no re-forwarding of SAs that we learnt from other peers */ - continue; - } - /* add sa into scratch pad */ - pim_msdp_pkt_sa_fill_one(sa); - ++sa_count; - if (sa_count >= PIM_MSDP_SA_MAX_ENTRY_CNT) { - pim_msdp_pkt_sa_push(mp); - /* reset headers */ - sa_count = 0; - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug(" sa gen for remainder %d", local_cnt); - } - local_cnt = pim_msdp_pkt_sa_fill_hdr(local_cnt); - } - } - - if (sa_count) { - pim_msdp_pkt_sa_push(mp); - } - return; + struct listnode *sanode; + struct pim_msdp_sa *sa; + int sa_count; + int local_cnt = msdp->local_cnt; + + sa_count = 0; + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug(" sa gen %d", local_cnt); + } + + local_cnt = pim_msdp_pkt_sa_fill_hdr(local_cnt); + + for (ALL_LIST_ELEMENTS_RO(msdp->sa_list, sanode, sa)) { + if (!(sa->flags & PIM_MSDP_SAF_LOCAL)) { + /* current implementation of MSDP is for anycast i.e. + * full mesh. so + * no re-forwarding of SAs that we learnt from other + * peers */ + continue; + } + /* add sa into scratch pad */ + pim_msdp_pkt_sa_fill_one(sa); + ++sa_count; + if (sa_count >= PIM_MSDP_SA_MAX_ENTRY_CNT) { + pim_msdp_pkt_sa_push(mp); + /* reset headers */ + sa_count = 0; + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug(" sa gen for remainder %d", + local_cnt); + } + local_cnt = pim_msdp_pkt_sa_fill_hdr(local_cnt); + } + } + + if (sa_count) { + pim_msdp_pkt_sa_push(mp); + } + return; } -static void -pim_msdp_pkt_sa_tx_done(void) +static void pim_msdp_pkt_sa_tx_done(void) { - struct listnode *mpnode; - struct pim_msdp_peer *mp; - - /* if SA were sent to the peers we restart ka timer and avoid - * unnecessary ka noise */ - for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { - if (mp->flags & PIM_MSDP_PEERF_SA_JUST_SENT) { - mp->flags &= ~PIM_MSDP_PEERF_SA_JUST_SENT; - pim_msdp_peer_pkt_txed(mp); - } - } + struct listnode *mpnode; + struct pim_msdp_peer *mp; + + /* if SA were sent to the peers we restart ka timer and avoid + * unnecessary ka noise */ + for (ALL_LIST_ELEMENTS_RO(msdp->peer_list, mpnode, mp)) { + if (mp->flags & PIM_MSDP_PEERF_SA_JUST_SENT) { + mp->flags &= ~PIM_MSDP_PEERF_SA_JUST_SENT; + pim_msdp_peer_pkt_txed(mp); + } + } } -void -pim_msdp_pkt_sa_tx(void) +void pim_msdp_pkt_sa_tx(void) { - pim_msdp_pkt_sa_gen(NULL /* mp */); - pim_msdp_pkt_sa_tx_done(); + pim_msdp_pkt_sa_gen(NULL /* mp */); + pim_msdp_pkt_sa_tx_done(); } -void -pim_msdp_pkt_sa_tx_one(struct pim_msdp_sa *sa) +void pim_msdp_pkt_sa_tx_one(struct pim_msdp_sa *sa) { - pim_msdp_pkt_sa_fill_hdr(1 /* cnt */); - pim_msdp_pkt_sa_fill_one(sa); - pim_msdp_pkt_sa_push(NULL); - pim_msdp_pkt_sa_tx_done(); + pim_msdp_pkt_sa_fill_hdr(1 /* cnt */); + pim_msdp_pkt_sa_fill_one(sa); + pim_msdp_pkt_sa_push(NULL); + pim_msdp_pkt_sa_tx_done(); } /* when a connection is first established we push all SAs immediately */ -void -pim_msdp_pkt_sa_tx_to_one_peer(struct pim_msdp_peer *mp) +void pim_msdp_pkt_sa_tx_to_one_peer(struct pim_msdp_peer *mp) { - pim_msdp_pkt_sa_gen(mp); - pim_msdp_pkt_sa_tx_done(); + pim_msdp_pkt_sa_gen(mp); + pim_msdp_pkt_sa_tx_done(); } -static void -pim_msdp_pkt_rxed_with_fatal_error(struct pim_msdp_peer *mp) +static void pim_msdp_pkt_rxed_with_fatal_error(struct pim_msdp_peer *mp) { - pim_msdp_peer_reset_tcp_conn(mp, "invalid-pkt-rx"); + pim_msdp_peer_reset_tcp_conn(mp, "invalid-pkt-rx"); } -static void -pim_msdp_pkt_ka_rx(struct pim_msdp_peer *mp, int len) +static void pim_msdp_pkt_ka_rx(struct pim_msdp_peer *mp, int len) { - mp->ka_rx_cnt++; - if (len != PIM_MSDP_KA_TLV_MAX_SIZE) { - pim_msdp_pkt_rxed_with_fatal_error(mp); - return; - } - pim_msdp_peer_pkt_rxed(mp); + mp->ka_rx_cnt++; + if (len != PIM_MSDP_KA_TLV_MAX_SIZE) { + pim_msdp_pkt_rxed_with_fatal_error(mp); + return; + } + pim_msdp_peer_pkt_rxed(mp); } -static void -pim_msdp_pkt_sa_rx_one(struct pim_msdp_peer *mp, struct in_addr rp) +static void pim_msdp_pkt_sa_rx_one(struct pim_msdp_peer *mp, struct in_addr rp) { - int prefix_len; - struct prefix_sg sg; - - /* just throw away the three reserved bytes */ - stream_get3(mp->ibuf); - prefix_len = stream_getc(mp->ibuf); - - memset(&sg, 0, sizeof (struct prefix_sg)); - sg.grp.s_addr = stream_get_ipv4(mp->ibuf); - sg.src.s_addr = stream_get_ipv4(mp->ibuf); - - if (prefix_len != 32) { - /* ignore SA update if the prefix length is not 32 */ - zlog_err("rxed sa update with invalid prefix length %d", prefix_len); - return; - } - if (PIM_DEBUG_MSDP_PACKETS) { - zlog_debug(" sg %s", pim_str_sg_dump(&sg)); - } - pim_msdp_sa_ref(mp, &sg, rp); + int prefix_len; + struct prefix_sg sg; + + /* just throw away the three reserved bytes */ + stream_get3(mp->ibuf); + prefix_len = stream_getc(mp->ibuf); + + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.grp.s_addr = stream_get_ipv4(mp->ibuf); + sg.src.s_addr = stream_get_ipv4(mp->ibuf); + + if (prefix_len != 32) { + /* ignore SA update if the prefix length is not 32 */ + zlog_err("rxed sa update with invalid prefix length %d", + prefix_len); + return; + } + if (PIM_DEBUG_MSDP_PACKETS) { + zlog_debug(" sg %s", pim_str_sg_dump(&sg)); + } + pim_msdp_sa_ref(mp, &sg, rp); } -static void -pim_msdp_pkt_sa_rx(struct pim_msdp_peer *mp, int len) +static void pim_msdp_pkt_sa_rx(struct pim_msdp_peer *mp, int len) { - int entry_cnt; - int i; - struct in_addr rp; /* Last RP address associated with this SA */ - - mp->sa_rx_cnt++; - - if (len < PIM_MSDP_SA_TLV_MIN_SIZE) { - pim_msdp_pkt_rxed_with_fatal_error(mp); - return; - } - - entry_cnt = stream_getc(mp->ibuf); - /* some vendors include the actual multicast data in the tlv (at the end). - * we will ignore such data. in the future we may consider pushing it down - * the RPT */ - if (len < PIM_MSDP_SA_ENTRY_CNT2SIZE(entry_cnt)) { - pim_msdp_pkt_rxed_with_fatal_error(mp); - return; - } - rp.s_addr = stream_get_ipv4(mp->ibuf); - - if (PIM_DEBUG_MSDP_PACKETS) { - char rp_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", rp, rp_str, sizeof(rp_str)); - zlog_debug(" entry_cnt %d rp %s", entry_cnt, rp_str); - } - - if (!pim_msdp_peer_rpf_check(mp, rp)) { - /* if peer-RPF check fails don't process the packet any further */ - if (PIM_DEBUG_MSDP_PACKETS) { - zlog_debug(" peer RPF check failed"); - } - return; - } - - pim_msdp_peer_pkt_rxed(mp); - - /* update SA cache */ - for (i = 0; i < entry_cnt; ++i) { - pim_msdp_pkt_sa_rx_one(mp, rp); - } + int entry_cnt; + int i; + struct in_addr rp; /* Last RP address associated with this SA */ + + mp->sa_rx_cnt++; + + if (len < PIM_MSDP_SA_TLV_MIN_SIZE) { + pim_msdp_pkt_rxed_with_fatal_error(mp); + return; + } + + entry_cnt = stream_getc(mp->ibuf); + /* some vendors include the actual multicast data in the tlv (at the + * end). + * we will ignore such data. in the future we may consider pushing it + * down + * the RPT */ + if (len < PIM_MSDP_SA_ENTRY_CNT2SIZE(entry_cnt)) { + pim_msdp_pkt_rxed_with_fatal_error(mp); + return; + } + rp.s_addr = stream_get_ipv4(mp->ibuf); + + if (PIM_DEBUG_MSDP_PACKETS) { + char rp_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", rp, rp_str, sizeof(rp_str)); + zlog_debug(" entry_cnt %d rp %s", entry_cnt, rp_str); + } + + if (!pim_msdp_peer_rpf_check(mp, rp)) { + /* if peer-RPF check fails don't process the packet any further + */ + if (PIM_DEBUG_MSDP_PACKETS) { + zlog_debug(" peer RPF check failed"); + } + return; + } + + pim_msdp_peer_pkt_rxed(mp); + + /* update SA cache */ + for (i = 0; i < entry_cnt; ++i) { + pim_msdp_pkt_sa_rx_one(mp, rp); + } } -static void -pim_msdp_pkt_rx(struct pim_msdp_peer *mp) +static void pim_msdp_pkt_rx(struct pim_msdp_peer *mp) { - enum pim_msdp_tlv type; - int len; - - /* re-read type and len */ - type = stream_getc_from(mp->ibuf, 0); - len = stream_getw_from(mp->ibuf, 1); - if (len < PIM_MSDP_HEADER_SIZE) { - pim_msdp_pkt_rxed_with_fatal_error(mp); - return; - } - - if (len > PIM_MSDP_SA_TLV_MAX_SIZE) { - /* if tlv size if greater than max just ignore the tlv */ - return; - } - - if (PIM_DEBUG_MSDP_PACKETS) { - pim_msdp_pkt_dump(mp, type, len, true /*rx*/, NULL /*s*/); - } - - switch(type) { - case PIM_MSDP_KEEPALIVE: - pim_msdp_pkt_ka_rx(mp, len); - break; - case PIM_MSDP_V4_SOURCE_ACTIVE: - mp->sa_rx_cnt++; - pim_msdp_pkt_sa_rx(mp, len); - break; - default: - mp->unk_rx_cnt++; - } + enum pim_msdp_tlv type; + int len; + + /* re-read type and len */ + type = stream_getc_from(mp->ibuf, 0); + len = stream_getw_from(mp->ibuf, 1); + if (len < PIM_MSDP_HEADER_SIZE) { + pim_msdp_pkt_rxed_with_fatal_error(mp); + return; + } + + if (len > PIM_MSDP_SA_TLV_MAX_SIZE) { + /* if tlv size if greater than max just ignore the tlv */ + return; + } + + if (PIM_DEBUG_MSDP_PACKETS) { + pim_msdp_pkt_dump(mp, type, len, true /*rx*/, NULL /*s*/); + } + + switch (type) { + case PIM_MSDP_KEEPALIVE: + pim_msdp_pkt_ka_rx(mp, len); + break; + case PIM_MSDP_V4_SOURCE_ACTIVE: + mp->sa_rx_cnt++; + pim_msdp_pkt_sa_rx(mp, len); + break; + default: + mp->unk_rx_cnt++; + } } /* pim msdp read utility function. */ -static int -pim_msdp_read_packet(struct pim_msdp_peer *mp) +static int pim_msdp_read_packet(struct pim_msdp_peer *mp) { - int nbytes; - int readsize; - int old_endp; - int new_endp; - - old_endp = stream_get_endp(mp->ibuf); - readsize = mp->packet_size - old_endp; - if (!readsize) { - return 0; - } - - /* Read packet from fd */ - nbytes = stream_read_try(mp->ibuf, mp->fd, readsize); - new_endp = stream_get_endp(mp->ibuf); - if (nbytes < 0) { - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s read failed %d", mp->key_str, nbytes); - } - if (nbytes == -2) { - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s pim_msdp_read io retry old_end: %d new_end: %d", mp->key_str, old_endp, new_endp); - } - /* transient error retry */ - return -1; - } - pim_msdp_pkt_rxed_with_fatal_error(mp); - return -1; - } - - if (!nbytes) { - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s read failed %d", mp->key_str, nbytes); - } - pim_msdp_peer_reset_tcp_conn(mp, "peer-down"); - return -1; - } - - /* We read partial packet. */ - if (stream_get_endp(mp->ibuf) != mp->packet_size) { - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s read partial len %d old_endp %d new_endp %d", mp->key_str, mp->packet_size, old_endp, new_endp); - } - return -1; - } - - return 0; + int nbytes; + int readsize; + int old_endp; + int new_endp; + + old_endp = stream_get_endp(mp->ibuf); + readsize = mp->packet_size - old_endp; + if (!readsize) { + return 0; + } + + /* Read packet from fd */ + nbytes = stream_read_try(mp->ibuf, mp->fd, readsize); + new_endp = stream_get_endp(mp->ibuf); + if (nbytes < 0) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s read failed %d", mp->key_str, + nbytes); + } + if (nbytes == -2) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug( + "MSDP peer %s pim_msdp_read io retry old_end: %d new_end: %d", + mp->key_str, old_endp, new_endp); + } + /* transient error retry */ + return -1; + } + pim_msdp_pkt_rxed_with_fatal_error(mp); + return -1; + } + + if (!nbytes) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s read failed %d", mp->key_str, + nbytes); + } + pim_msdp_peer_reset_tcp_conn(mp, "peer-down"); + return -1; + } + + /* We read partial packet. */ + if (stream_get_endp(mp->ibuf) != mp->packet_size) { + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug( + "MSDP peer %s read partial len %d old_endp %d new_endp %d", + mp->key_str, mp->packet_size, old_endp, + new_endp); + } + return -1; + } + + return 0; } -int -pim_msdp_read(struct thread *thread) +int pim_msdp_read(struct thread *thread) { - struct pim_msdp_peer *mp; - int rc; - uint32_t len; - - mp = THREAD_ARG(thread); - mp->t_read = NULL; - - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s pim_msdp_read", mp->key_str); - } - - if (mp->fd < 0) { - return -1; - } - - /* check if TCP connection is established */ - if (mp->state != PIM_MSDP_ESTABLISHED) { - pim_msdp_connect_check(mp); - return 0; - } - - PIM_MSDP_PEER_READ_ON(mp); - - if (!mp->packet_size) { - mp->packet_size = PIM_MSDP_HEADER_SIZE; - } - - if (stream_get_endp(mp->ibuf) < PIM_MSDP_HEADER_SIZE) { - /* start by reading the TLV header */ - rc = pim_msdp_read_packet(mp); - if (rc < 0) { - goto pim_msdp_read_end; - } - - /* Find TLV type and len */ - stream_getc(mp->ibuf); - len = stream_getw(mp->ibuf); - if (len < PIM_MSDP_HEADER_SIZE) { - pim_msdp_pkt_rxed_with_fatal_error(mp); - goto pim_msdp_read_end; - } - /* read complete TLV */ - mp->packet_size = len; - } - - rc = pim_msdp_read_packet(mp); - if (rc < 0) { - goto pim_msdp_read_end; - } - - pim_msdp_pkt_rx(mp); - - /* reset input buffers and get ready for the next packet */ - mp->packet_size = 0; - stream_reset(mp->ibuf); + struct pim_msdp_peer *mp; + int rc; + uint32_t len; + + mp = THREAD_ARG(thread); + mp->t_read = NULL; + + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s pim_msdp_read", mp->key_str); + } + + if (mp->fd < 0) { + return -1; + } + + /* check if TCP connection is established */ + if (mp->state != PIM_MSDP_ESTABLISHED) { + pim_msdp_connect_check(mp); + return 0; + } + + PIM_MSDP_PEER_READ_ON(mp); + + if (!mp->packet_size) { + mp->packet_size = PIM_MSDP_HEADER_SIZE; + } + + if (stream_get_endp(mp->ibuf) < PIM_MSDP_HEADER_SIZE) { + /* start by reading the TLV header */ + rc = pim_msdp_read_packet(mp); + if (rc < 0) { + goto pim_msdp_read_end; + } + + /* Find TLV type and len */ + stream_getc(mp->ibuf); + len = stream_getw(mp->ibuf); + if (len < PIM_MSDP_HEADER_SIZE) { + pim_msdp_pkt_rxed_with_fatal_error(mp); + goto pim_msdp_read_end; + } + /* read complete TLV */ + mp->packet_size = len; + } + + rc = pim_msdp_read_packet(mp); + if (rc < 0) { + goto pim_msdp_read_end; + } + + pim_msdp_pkt_rx(mp); + + /* reset input buffers and get ready for the next packet */ + mp->packet_size = 0; + stream_reset(mp->ibuf); pim_msdp_read_end: - return 0; + return 0; } diff --git a/pimd/pim_msdp_packet.h b/pimd/pim_msdp_packet.h index aa42bbfe4..986fa3b32 100644 --- a/pimd/pim_msdp_packet.h +++ b/pimd/pim_msdp_packet.h @@ -50,8 +50,8 @@ #define PIM_MSDP_SA_X_SIZE 8 #define PIM_MSDP_SA_ONE_ENTRY_SIZE 12 #define PIM_MSDP_SA_Y_SIZE(entry_cnt) (PIM_MSDP_SA_ONE_ENTRY_SIZE * entry_cnt) -#define PIM_MSDP_SA_ENTRY_CNT2SIZE(entry_cnt) (PIM_MSDP_SA_X_SIZE +\ - PIM_MSDP_SA_Y_SIZE(entry_cnt)) +#define PIM_MSDP_SA_ENTRY_CNT2SIZE(entry_cnt) \ + (PIM_MSDP_SA_X_SIZE + PIM_MSDP_SA_Y_SIZE(entry_cnt)) /* SA TLV has to have atleast only one entry in it so x=8 + y=12 */ #define PIM_MSDP_SA_TLV_MIN_SIZE PIM_MSDP_SA_ENTRY_CNT2SIZE(1) /* XXX: theoretically we can fix a max of 255 but that may result in packet diff --git a/pimd/pim_msdp_socket.c b/pimd/pim_msdp_socket.c index 9662f054e..0ce097101 100644 --- a/pimd/pim_msdp_socket.c +++ b/pimd/pim_msdp_socket.c @@ -31,199 +31,207 @@ #include "pim_msdp_socket.h" /* increase socket send buffer size */ -static void -pim_msdp_update_sock_send_buffer_size (int fd) +static void pim_msdp_update_sock_send_buffer_size(int fd) { - int size = PIM_MSDP_SOCKET_SNDBUF_SIZE; - int optval; - socklen_t optlen = sizeof(optval); - - if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &optval, &optlen) < 0) { - zlog_err("getsockopt of SO_SNDBUF failed %s\n", safe_strerror(errno)); - return; - } - - if (optval < size) { - if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) < 0) { - zlog_err("Couldn't increase send buffer: %s\n", safe_strerror(errno)); - } - } + int size = PIM_MSDP_SOCKET_SNDBUF_SIZE; + int optval; + socklen_t optlen = sizeof(optval); + + if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &optval, &optlen) < 0) { + zlog_err("getsockopt of SO_SNDBUF failed %s\n", + safe_strerror(errno)); + return; + } + + if (optval < size) { + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) + < 0) { + zlog_err("Couldn't increase send buffer: %s\n", + safe_strerror(errno)); + } + } } /* passive peer socket accept */ -static int -pim_msdp_sock_accept(struct thread *thread) +static int pim_msdp_sock_accept(struct thread *thread) { - union sockunion su; - struct pim_msdp_listener *listener = THREAD_ARG(thread); - int accept_sock; - int msdp_sock; - struct pim_msdp_peer *mp; - char buf[SU_ADDRSTRLEN]; - - sockunion_init(&su); - - /* re-register accept thread */ - accept_sock = THREAD_FD(thread); - if (accept_sock < 0) { - zlog_err ("accept_sock is negative value %d", accept_sock); - return -1; - } - listener->thread = NULL; - thread_add_read(master, pim_msdp_sock_accept, listener, accept_sock, - &listener->thread); - - /* accept client connection. */ - msdp_sock = sockunion_accept(accept_sock, &su); - if (msdp_sock < 0) { - zlog_err ("pim_msdp_sock_accept failed (%s)", safe_strerror (errno)); - return -1; - } - - /* see if have peer config for this */ - mp = pim_msdp_peer_find(su.sin.sin_addr); - if (!mp || !PIM_MSDP_PEER_IS_LISTENER(mp)) { - ++msdp->rejected_accepts; - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_err("msdp peer connection refused from %s", - sockunion2str(&su, buf, SU_ADDRSTRLEN)); - } - close(msdp_sock); - return -1; - } - - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s accept success%s", mp->key_str, mp->fd>=0?"(dup)":""); - } - - /* if we have an existing connection we need to kill that one - * with this one */ - if (mp->fd >= 0) { - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_err("msdp peer new connection from %s stop old connection", - sockunion2str(&su, buf, SU_ADDRSTRLEN)); - } - pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); - } - mp->fd = msdp_sock; - set_nonblocking(mp->fd); - pim_msdp_update_sock_send_buffer_size(mp->fd); - pim_msdp_peer_established(mp); - return 0; + union sockunion su; + struct pim_msdp_listener *listener = THREAD_ARG(thread); + int accept_sock; + int msdp_sock; + struct pim_msdp_peer *mp; + char buf[SU_ADDRSTRLEN]; + + sockunion_init(&su); + + /* re-register accept thread */ + accept_sock = THREAD_FD(thread); + if (accept_sock < 0) { + zlog_err("accept_sock is negative value %d", accept_sock); + return -1; + } + listener->thread = NULL; + thread_add_read(master, pim_msdp_sock_accept, listener, accept_sock, + &listener->thread); + + /* accept client connection. */ + msdp_sock = sockunion_accept(accept_sock, &su); + if (msdp_sock < 0) { + zlog_err("pim_msdp_sock_accept failed (%s)", + safe_strerror(errno)); + return -1; + } + + /* see if have peer config for this */ + mp = pim_msdp_peer_find(su.sin.sin_addr); + if (!mp || !PIM_MSDP_PEER_IS_LISTENER(mp)) { + ++msdp->rejected_accepts; + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_err("msdp peer connection refused from %s", + sockunion2str(&su, buf, SU_ADDRSTRLEN)); + } + close(msdp_sock); + return -1; + } + + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s accept success%s", mp->key_str, + mp->fd >= 0 ? "(dup)" : ""); + } + + /* if we have an existing connection we need to kill that one + * with this one */ + if (mp->fd >= 0) { + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_err( + "msdp peer new connection from %s stop old connection", + sockunion2str(&su, buf, SU_ADDRSTRLEN)); + } + pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); + } + mp->fd = msdp_sock; + set_nonblocking(mp->fd); + pim_msdp_update_sock_send_buffer_size(mp->fd); + pim_msdp_peer_established(mp); + return 0; } /* global listener for the MSDP well know TCP port */ -int -pim_msdp_sock_listen(void) +int pim_msdp_sock_listen(void) { - int sock; - int socklen; - struct sockaddr_in sin; - int rc; - struct pim_msdp_listener *listener = &msdp->listener; - - if (msdp->flags & PIM_MSDPF_LISTENER) { - /* listener already setup */ - return 0; - } - - sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock < 0) { - zlog_err ("socket: %s", safe_strerror (errno)); - return sock; - } - - memset(&sin, 0, sizeof(struct sockaddr_in)); - sin.sin_family = AF_INET; - sin.sin_port = htons(PIM_MSDP_TCP_PORT); - socklen = sizeof(struct sockaddr_in); + int sock; + int socklen; + struct sockaddr_in sin; + int rc; + struct pim_msdp_listener *listener = &msdp->listener; + + if (msdp->flags & PIM_MSDPF_LISTENER) { + /* listener already setup */ + return 0; + } + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + zlog_err("socket: %s", safe_strerror(errno)); + return sock; + } + + memset(&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; + sin.sin_port = htons(PIM_MSDP_TCP_PORT); + socklen = sizeof(struct sockaddr_in); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin.sin_len = socklen; + sin.sin_len = socklen; #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - sockopt_reuseaddr(sock); - sockopt_reuseport(sock); - - if (pimd_privs.change(ZPRIVS_RAISE)) { - zlog_err ("pim_msdp_socket: could not raise privs, %s", - safe_strerror (errno)); - } - - /* bind to well known TCP port */ - rc = bind(sock, (struct sockaddr *)&sin, socklen); - - if (pimd_privs.change(ZPRIVS_LOWER)) { - zlog_err ("pim_msdp_socket: could not lower privs, %s", - safe_strerror (errno)); - } - - if (rc < 0) { - zlog_err ("pim_msdp_socket bind to port %d: %s", ntohs(sin.sin_port), safe_strerror (errno)); - close(sock); - return rc; - } - - rc = listen(sock, 3 /* backlog */); - if (rc < 0) { - zlog_err ("pim_msdp_socket listen: %s", safe_strerror (errno)); - close(sock); - return rc; - } - - /* add accept thread */ - listener->fd = sock; - memcpy(&listener->su, &sin, socklen); - listener->thread = NULL; - thread_add_read(msdp->master, pim_msdp_sock_accept, listener, sock, - &listener->thread); - - msdp->flags |= PIM_MSDPF_LISTENER; - return 0; + sockopt_reuseaddr(sock); + sockopt_reuseport(sock); + + if (pimd_privs.change(ZPRIVS_RAISE)) { + zlog_err("pim_msdp_socket: could not raise privs, %s", + safe_strerror(errno)); + } + + /* bind to well known TCP port */ + rc = bind(sock, (struct sockaddr *)&sin, socklen); + + if (pimd_privs.change(ZPRIVS_LOWER)) { + zlog_err("pim_msdp_socket: could not lower privs, %s", + safe_strerror(errno)); + } + + if (rc < 0) { + zlog_err("pim_msdp_socket bind to port %d: %s", + ntohs(sin.sin_port), safe_strerror(errno)); + close(sock); + return rc; + } + + rc = listen(sock, 3 /* backlog */); + if (rc < 0) { + zlog_err("pim_msdp_socket listen: %s", safe_strerror(errno)); + close(sock); + return rc; + } + + /* add accept thread */ + listener->fd = sock; + memcpy(&listener->su, &sin, socklen); + listener->thread = NULL; + thread_add_read(msdp->master, pim_msdp_sock_accept, listener, sock, + &listener->thread); + + msdp->flags |= PIM_MSDPF_LISTENER; + return 0; } /* active peer socket setup */ -int -pim_msdp_sock_connect(struct pim_msdp_peer *mp) +int pim_msdp_sock_connect(struct pim_msdp_peer *mp) { - int rc; - - if (PIM_DEBUG_MSDP_INTERNAL) { - zlog_debug("MSDP peer %s attempt connect%s", mp->key_str, mp->fd<0?"":"(dup)"); - } - - /* if we have an existing connection we need to kill that one - * with this one */ - if (mp->fd >= 0) { - if (PIM_DEBUG_MSDP_EVENTS) { - zlog_err("msdp duplicate connect to %s nuke old connection", mp->key_str); - } - pim_msdp_peer_stop_tcp_conn(mp, false /* chg_state */); - } - - /* Make socket for the peer. */ - mp->fd = sockunion_socket(&mp->su_peer); - if (mp->fd < 0) { - zlog_err ("pim_msdp_socket socket failure: %s", safe_strerror (errno)); - return -1; - } - - set_nonblocking(mp->fd); - - /* Set socket send buffer size */ - pim_msdp_update_sock_send_buffer_size(mp->fd); - sockopt_reuseaddr(mp->fd); - sockopt_reuseport(mp->fd); - - /* source bind */ - rc = sockunion_bind(mp->fd, &mp->su_local, 0, &mp->su_local); - if (rc < 0) { - zlog_err ("pim_msdp_socket connect bind failure: %s", safe_strerror (errno)); - close(mp->fd); - mp->fd = -1; - return rc; - } - - /* Connect to the remote mp. */ - return (sockunion_connect(mp->fd, &mp->su_peer, htons(PIM_MSDP_TCP_PORT), 0)); + int rc; + + if (PIM_DEBUG_MSDP_INTERNAL) { + zlog_debug("MSDP peer %s attempt connect%s", mp->key_str, + mp->fd < 0 ? "" : "(dup)"); + } + + /* if we have an existing connection we need to kill that one + * with this one */ + if (mp->fd >= 0) { + if (PIM_DEBUG_MSDP_EVENTS) { + zlog_err( + "msdp duplicate connect to %s nuke old connection", + mp->key_str); + } + pim_msdp_peer_stop_tcp_conn(mp, false /* chg_state */); + } + + /* Make socket for the peer. */ + mp->fd = sockunion_socket(&mp->su_peer); + if (mp->fd < 0) { + zlog_err("pim_msdp_socket socket failure: %s", + safe_strerror(errno)); + return -1; + } + + set_nonblocking(mp->fd); + + /* Set socket send buffer size */ + pim_msdp_update_sock_send_buffer_size(mp->fd); + sockopt_reuseaddr(mp->fd); + sockopt_reuseport(mp->fd); + + /* source bind */ + rc = sockunion_bind(mp->fd, &mp->su_local, 0, &mp->su_local); + if (rc < 0) { + zlog_err("pim_msdp_socket connect bind failure: %s", + safe_strerror(errno)); + close(mp->fd); + mp->fd = -1; + return rc; + } + + /* Connect to the remote mp. */ + return (sockunion_connect(mp->fd, &mp->su_peer, + htons(PIM_MSDP_TCP_PORT), 0)); } - diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index e077a8516..04f1f4846 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -37,197 +37,202 @@ #include "pim_register.h" #include "pim_jp_agg.h" -void pim_msg_build_header(uint8_t *pim_msg, size_t pim_msg_size, uint8_t pim_msg_type) +void pim_msg_build_header(uint8_t *pim_msg, size_t pim_msg_size, + uint8_t pim_msg_type) { - struct pim_msg_header *header = (struct pim_msg_header *)pim_msg; - - /* - * Write header - */ - header->ver = PIM_PROTO_VERSION; - header->type = pim_msg_type; - header->reserved = 0; - - - header->checksum = 0; - /* - * The checksum for Registers is done only on the first 8 bytes of the packet, - * including the PIM header and the next 4 bytes, excluding the data packet portion - */ - if (pim_msg_type == PIM_MSG_TYPE_REGISTER) - header->checksum = in_cksum (pim_msg, PIM_MSG_REGISTER_LEN); - else - header->checksum = in_cksum (pim_msg, pim_msg_size); + struct pim_msg_header *header = (struct pim_msg_header *)pim_msg; + + /* + * Write header + */ + header->ver = PIM_PROTO_VERSION; + header->type = pim_msg_type; + header->reserved = 0; + + + header->checksum = 0; + /* + * The checksum for Registers is done only on the first 8 bytes of the + * packet, + * including the PIM header and the next 4 bytes, excluding the data + * packet portion + */ + if (pim_msg_type == PIM_MSG_TYPE_REGISTER) + header->checksum = in_cksum(pim_msg, PIM_MSG_REGISTER_LEN); + else + header->checksum = in_cksum(pim_msg, pim_msg_size); } uint8_t *pim_msg_addr_encode_ipv4_ucast(uint8_t *buf, struct in_addr addr) { - buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ - buf[1] = '\0'; /* native encoding */ - memcpy(buf+2, &addr, sizeof(struct in_addr)); + buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ + buf[1] = '\0'; /* native encoding */ + memcpy(buf + 2, &addr, sizeof(struct in_addr)); - return buf + PIM_ENCODED_IPV4_UCAST_SIZE; + return buf + PIM_ENCODED_IPV4_UCAST_SIZE; } uint8_t *pim_msg_addr_encode_ipv4_group(uint8_t *buf, struct in_addr addr) { - buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ - buf[1] = '\0'; /* native encoding */ - buf[2] = '\0'; /* reserved */ - buf[3] = 32; /* mask len */ - memcpy(buf+4, &addr, sizeof(struct in_addr)); + buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ + buf[1] = '\0'; /* native encoding */ + buf[2] = '\0'; /* reserved */ + buf[3] = 32; /* mask len */ + memcpy(buf + 4, &addr, sizeof(struct in_addr)); - return buf + PIM_ENCODED_IPV4_GROUP_SIZE; + return buf + PIM_ENCODED_IPV4_GROUP_SIZE; } -uint8_t * -pim_msg_addr_encode_ipv4_source(uint8_t *buf, - struct in_addr addr, uint8_t bits) +uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf, struct in_addr addr, + uint8_t bits) { - buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ - buf[1] = '\0'; /* native encoding */ - buf[2] = bits; - buf[3] = 32; /* mask len */ - memcpy(buf+4, &addr, sizeof(struct in_addr)); + buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */ + buf[1] = '\0'; /* native encoding */ + buf[2] = bits; + buf[3] = 32; /* mask len */ + memcpy(buf + 4, &addr, sizeof(struct in_addr)); - return buf + PIM_ENCODED_IPV4_SOURCE_SIZE; + return buf + PIM_ENCODED_IPV4_SOURCE_SIZE; } /* * For the given 'struct pim_jp_sources' list * determine the size_t it would take up. */ -size_t -pim_msg_get_jp_group_size (struct list *sources) +size_t pim_msg_get_jp_group_size(struct list *sources) { - struct pim_jp_sources *js; - size_t size = 0; - - size += sizeof (struct pim_encoded_group_ipv4); - size += 4; // Joined sources (2) + Pruned Sources (2) - - size += sizeof (struct pim_encoded_source_ipv4) * sources->count; - - js = listgetdata(listhead(sources)); - if (js && js->up->sg.src.s_addr == INADDR_ANY) - { - struct pim_upstream *child, *up; - struct listnode *up_node; - - up = js->up; - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("%s: Considering (%s) children for (S,G,rpt) prune", - __PRETTY_FUNCTION__, up->sg_str); - - for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) - { - if (child->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) - { - if (!pim_rpf_is_same(&up->rpf, &child->rpf)) - { - size += sizeof (struct pim_encoded_source_ipv4); - PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(child->flags); - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("%s: SPT Bit and RPF'(%s) != RPF'(S,G): Add Prune (%s,rpt) to compound message", - __PRETTY_FUNCTION__, up->sg_str, child->sg_str); - } - else - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("%s: SPT Bit and RPF'(%s) == RPF'(S,G): Not adding Prune for (%s,rpt)", - __PRETTY_FUNCTION__, up->sg_str, child->sg_str); - } - else if (pim_upstream_is_sg_rpt (child)) - { - if (pim_upstream_empty_inherited_olist (child)) - { - size += sizeof (struct pim_encoded_source_ipv4); - PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(child->flags); - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("%s: inherited_olist(%s,rpt) is NULL, Add Prune to compound message", - __PRETTY_FUNCTION__, child->sg_str); - } - else if (!pim_rpf_is_same (&up->rpf, &child->rpf)) - { - size += sizeof (struct pim_encoded_source_ipv4); - PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(child->flags); - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("%s: RPF'(%s) != RPF'(%s,rpt), Add Prune to compound message", - __PRETTY_FUNCTION__, up->sg_str, child->sg_str); - } - else - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("%s: RPF'(%s) == RPF'(%s,rpt), Do not add Prune to compound message", - __PRETTY_FUNCTION__, up->sg_str, child->sg_str); - } - else - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("%s: SPT bit is not set for (%s)", - __PRETTY_FUNCTION__, child->sg_str); - } - } - return size; + struct pim_jp_sources *js; + size_t size = 0; + + size += sizeof(struct pim_encoded_group_ipv4); + size += 4; // Joined sources (2) + Pruned Sources (2) + + size += sizeof(struct pim_encoded_source_ipv4) * sources->count; + + js = listgetdata(listhead(sources)); + if (js && js->up->sg.src.s_addr == INADDR_ANY) { + struct pim_upstream *child, *up; + struct listnode *up_node; + + up = js->up; + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "%s: Considering (%s) children for (S,G,rpt) prune", + __PRETTY_FUNCTION__, up->sg_str); + + for (ALL_LIST_ELEMENTS_RO(up->sources, up_node, child)) { + if (child->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) { + if (!pim_rpf_is_same(&up->rpf, &child->rpf)) { + size += sizeof( + struct pim_encoded_source_ipv4); + PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE( + child->flags); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "%s: SPT Bit and RPF'(%s) != RPF'(S,G): Add Prune (%s,rpt) to compound message", + __PRETTY_FUNCTION__, + up->sg_str, + child->sg_str); + } else if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "%s: SPT Bit and RPF'(%s) == RPF'(S,G): Not adding Prune for (%s,rpt)", + __PRETTY_FUNCTION__, up->sg_str, + child->sg_str); + } else if (pim_upstream_is_sg_rpt(child)) { + if (pim_upstream_empty_inherited_olist(child)) { + size += sizeof( + struct pim_encoded_source_ipv4); + PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE( + child->flags); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "%s: inherited_olist(%s,rpt) is NULL, Add Prune to compound message", + __PRETTY_FUNCTION__, + child->sg_str); + } else if (!pim_rpf_is_same(&up->rpf, + &child->rpf)) { + size += sizeof( + struct pim_encoded_source_ipv4); + PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE( + child->flags); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "%s: RPF'(%s) != RPF'(%s,rpt), Add Prune to compound message", + __PRETTY_FUNCTION__, + up->sg_str, + child->sg_str); + } else if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "%s: RPF'(%s) == RPF'(%s,rpt), Do not add Prune to compound message", + __PRETTY_FUNCTION__, up->sg_str, + child->sg_str); + } else if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("%s: SPT bit is not set for (%s)", + __PRETTY_FUNCTION__, child->sg_str); + } + } + return size; } -size_t -pim_msg_build_jp_groups (struct pim_jp_groups *grp, struct pim_jp_agg_group *sgs, size_t size) +size_t pim_msg_build_jp_groups(struct pim_jp_groups *grp, + struct pim_jp_agg_group *sgs, size_t size) { - struct listnode *node, *nnode; - struct pim_jp_sources *source; - struct pim_upstream *up = NULL; - struct in_addr stosend; - uint8_t bits; - uint8_t tgroups = 0; - - memset (grp, 0, size); - pim_msg_addr_encode_ipv4_group ((uint8_t *)&grp->g, sgs->group); - - for (ALL_LIST_ELEMENTS(sgs->sources, node, nnode, source)) - { - /* number of joined/pruned sources */ - if (source->is_join) - grp->joins++; - else - grp->prunes++; - - if (source->up->sg.src.s_addr == INADDR_ANY) - { - struct pim_rpf *rpf = pim_rp_g (source->up->sg.grp); - bits = PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_WC_BIT | PIM_ENCODE_RPT_BIT; - stosend = rpf->rpf_addr.u.prefix4; - /* Only Send SGRpt in case of *,G Join */ - if (source->is_join) - up = source->up; - } - else - { - bits = PIM_ENCODE_SPARSE_BIT; - stosend = source->up->sg.src; - } - - pim_msg_addr_encode_ipv4_source ((uint8_t *)&grp->s[tgroups], stosend, bits); - tgroups++; - } - - if (up) - { - struct pim_upstream *child; - - for (ALL_LIST_ELEMENTS(up->sources, node, nnode, child)) - { - if (PIM_UPSTREAM_FLAG_TEST_SEND_SG_RPT_PRUNE(child->flags)) - { - pim_msg_addr_encode_ipv4_source ((uint8_t *)&grp->s[tgroups], - child->sg.src, - PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_RPT_BIT); - tgroups++; - PIM_UPSTREAM_FLAG_UNSET_SEND_SG_RPT_PRUNE(child->flags); - grp->prunes++; - } - } - } - - grp->joins = htons(grp->joins); - grp->prunes = htons(grp->prunes); - - return size; + struct listnode *node, *nnode; + struct pim_jp_sources *source; + struct pim_upstream *up = NULL; + struct in_addr stosend; + uint8_t bits; + uint8_t tgroups = 0; + + memset(grp, 0, size); + pim_msg_addr_encode_ipv4_group((uint8_t *)&grp->g, sgs->group); + + for (ALL_LIST_ELEMENTS(sgs->sources, node, nnode, source)) { + /* number of joined/pruned sources */ + if (source->is_join) + grp->joins++; + else + grp->prunes++; + + if (source->up->sg.src.s_addr == INADDR_ANY) { + struct pim_rpf *rpf = pim_rp_g(source->up->sg.grp); + bits = PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_WC_BIT + | PIM_ENCODE_RPT_BIT; + stosend = rpf->rpf_addr.u.prefix4; + /* Only Send SGRpt in case of *,G Join */ + if (source->is_join) + up = source->up; + } else { + bits = PIM_ENCODE_SPARSE_BIT; + stosend = source->up->sg.src; + } + + pim_msg_addr_encode_ipv4_source((uint8_t *)&grp->s[tgroups], + stosend, bits); + tgroups++; + } + + if (up) { + struct pim_upstream *child; + + for (ALL_LIST_ELEMENTS(up->sources, node, nnode, child)) { + if (PIM_UPSTREAM_FLAG_TEST_SEND_SG_RPT_PRUNE( + child->flags)) { + pim_msg_addr_encode_ipv4_source( + (uint8_t *)&grp->s[tgroups], + child->sg.src, + PIM_ENCODE_SPARSE_BIT + | PIM_ENCODE_RPT_BIT); + tgroups++; + PIM_UPSTREAM_FLAG_UNSET_SEND_SG_RPT_PRUNE( + child->flags); + grp->prunes++; + } + } + } + + grp->joins = htons(grp->joins); + grp->prunes = htons(grp->prunes); + + return size; } diff --git a/pimd/pim_msg.h b/pimd/pim_msg.h index 38ffaf6a7..ad9b5d9c0 100644 --- a/pimd/pim_msg.h +++ b/pimd/pim_msg.h @@ -24,7 +24,7 @@ #include "pim_jp_agg.h" /* - Number Description + Number Description ---------- ------------------ 0 Reserved 1 IP (IP version 4) @@ -34,70 +34,72 @@ http://www.iana.org/assignments/address-family-numbers */ enum pim_msg_address_family { - PIM_MSG_ADDRESS_FAMILY_RESERVED, - PIM_MSG_ADDRESS_FAMILY_IPV4, - PIM_MSG_ADDRESS_FAMILY_IPV6, + PIM_MSG_ADDRESS_FAMILY_RESERVED, + PIM_MSG_ADDRESS_FAMILY_IPV4, + PIM_MSG_ADDRESS_FAMILY_IPV6, }; /* * Network Order pim_msg_hdr */ struct pim_msg_header { - uint8_t type:4; - uint8_t ver:4; - uint8_t reserved; - uint16_t checksum; -} __attribute__ ((packed)); + uint8_t type : 4; + uint8_t ver : 4; + uint8_t reserved; + uint16_t checksum; +} __attribute__((packed)); struct pim_encoded_ipv4_unicast { - uint8_t family; - uint8_t reserved; - struct in_addr addr; -} __attribute__ ((packed)); + uint8_t family; + uint8_t reserved; + struct in_addr addr; +} __attribute__((packed)); struct pim_encoded_group_ipv4 { - uint8_t ne; - uint8_t family; - uint8_t reserved; - uint8_t mask; - struct in_addr addr; -} __attribute__ ((packed)); + uint8_t ne; + uint8_t family; + uint8_t reserved; + uint8_t mask; + struct in_addr addr; +} __attribute__((packed)); struct pim_encoded_source_ipv4 { - uint8_t ne; - uint8_t family; - uint8_t bits; - uint8_t mask; - struct in_addr addr; -} __attribute__ ((packed)); + uint8_t ne; + uint8_t family; + uint8_t bits; + uint8_t mask; + struct in_addr addr; +} __attribute__((packed)); struct pim_jp_groups { - struct pim_encoded_group_ipv4 g; - uint16_t joins; - uint16_t prunes; - struct pim_encoded_source_ipv4 s[1]; -} __attribute__ ((packed)); + struct pim_encoded_group_ipv4 g; + uint16_t joins; + uint16_t prunes; + struct pim_encoded_source_ipv4 s[1]; +} __attribute__((packed)); struct pim_jp { - struct pim_msg_header header; - struct pim_encoded_ipv4_unicast addr; - uint8_t reserved; - uint8_t num_groups; - uint16_t holdtime; - struct pim_jp_groups groups[1]; -} __attribute__ ((packed)); + struct pim_msg_header header; + struct pim_encoded_ipv4_unicast addr; + uint8_t reserved; + uint8_t num_groups; + uint16_t holdtime; + struct pim_jp_groups groups[1]; +} __attribute__((packed)); -void pim_msg_build_header(uint8_t *pim_msg, size_t pim_msg_size, uint8_t pim_msg_type); +void pim_msg_build_header(uint8_t *pim_msg, size_t pim_msg_size, + uint8_t pim_msg_type); uint8_t *pim_msg_addr_encode_ipv4_ucast(uint8_t *buf, struct in_addr addr); uint8_t *pim_msg_addr_encode_ipv4_group(uint8_t *buf, struct in_addr addr); #define PIM_ENCODE_SPARSE_BIT 0x04 #define PIM_ENCODE_WC_BIT 0x02 #define PIM_ENCODE_RPT_BIT 0x01 -uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf, - struct in_addr addr, uint8_t bits); +uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf, struct in_addr addr, + uint8_t bits); -size_t pim_msg_get_jp_group_size (struct list *sources); -size_t pim_msg_build_jp_groups (struct pim_jp_groups *grp, struct pim_jp_agg_group *sgs, size_t size); +size_t pim_msg_get_jp_group_size(struct list *sources); +size_t pim_msg_build_jp_groups(struct pim_jp_groups *grp, + struct pim_jp_agg_group *sgs, size_t size); #endif /* PIM_MSG_H */ diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index 8b8946daf..70341a375 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -42,66 +42,61 @@ static void dr_election_by_addr(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct pim_neighbor *neigh; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - pim_ifp->pim_dr_addr = pim_ifp->primary_address; - - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: on interface %s", - __PRETTY_FUNCTION__, - ifp->name); - } - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { - if (ntohl(neigh->source_addr.s_addr) > ntohl(pim_ifp->pim_dr_addr.s_addr)) { - pim_ifp->pim_dr_addr = neigh->source_addr; - } - } + struct pim_interface *pim_ifp; + struct listnode *node; + struct pim_neighbor *neigh; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + pim_ifp->pim_dr_addr = pim_ifp->primary_address; + + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: on interface %s", __PRETTY_FUNCTION__, + ifp->name); + } + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { + if (ntohl(neigh->source_addr.s_addr) + > ntohl(pim_ifp->pim_dr_addr.s_addr)) { + pim_ifp->pim_dr_addr = neigh->source_addr; + } + } } static void dr_election_by_pri(struct interface *ifp) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct pim_neighbor *neigh; - uint32_t dr_pri; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - pim_ifp->pim_dr_addr = pim_ifp->primary_address; - dr_pri = pim_ifp->pim_dr_priority; - - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: dr pri %u on interface %s", - __PRETTY_FUNCTION__, - dr_pri, ifp->name); - } - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { - if (PIM_DEBUG_PIM_TRACE) { - zlog_info("%s: neigh pri %u addr %x if dr addr %x", - __PRETTY_FUNCTION__, - neigh->dr_priority, - ntohl(neigh->source_addr.s_addr), - ntohl(pim_ifp->pim_dr_addr.s_addr)); - } - if ( - (neigh->dr_priority > dr_pri) || - ( - (neigh->dr_priority == dr_pri) && - (ntohl(neigh->source_addr.s_addr) > ntohl(pim_ifp->pim_dr_addr.s_addr)) - ) - ) { - pim_ifp->pim_dr_addr = neigh->source_addr; - dr_pri = neigh->dr_priority; - } - } + struct pim_interface *pim_ifp; + struct listnode *node; + struct pim_neighbor *neigh; + uint32_t dr_pri; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + pim_ifp->pim_dr_addr = pim_ifp->primary_address; + dr_pri = pim_ifp->pim_dr_priority; + + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: dr pri %u on interface %s", __PRETTY_FUNCTION__, + dr_pri, ifp->name); + } + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { + if (PIM_DEBUG_PIM_TRACE) { + zlog_info("%s: neigh pri %u addr %x if dr addr %x", + __PRETTY_FUNCTION__, neigh->dr_priority, + ntohl(neigh->source_addr.s_addr), + ntohl(pim_ifp->pim_dr_addr.s_addr)); + } + if ((neigh->dr_priority > dr_pri) + || ((neigh->dr_priority == dr_pri) + && (ntohl(neigh->source_addr.s_addr) + > ntohl(pim_ifp->pim_dr_addr.s_addr)))) { + pim_ifp->pim_dr_addr = neigh->source_addr; + dr_pri = neigh->dr_priority; + } + } } /* @@ -113,359 +108,359 @@ static void dr_election_by_pri(struct interface *ifp) */ int pim_if_dr_election(struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; - struct in_addr old_dr_addr; - - ++pim_ifp->pim_dr_election_count; - - old_dr_addr = pim_ifp->pim_dr_addr; - - if (pim_ifp->pim_dr_num_nondrpri_neighbors) { - dr_election_by_addr(ifp); - } - else { - dr_election_by_pri(ifp); - } - - /* DR changed ? */ - if (old_dr_addr.s_addr != pim_ifp->pim_dr_addr.s_addr) { - - if (PIM_DEBUG_PIM_EVENTS) { - char dr_old_str[INET_ADDRSTRLEN]; - char dr_new_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", old_dr_addr, dr_old_str, sizeof(dr_old_str)); - pim_inet4_dump("", pim_ifp->pim_dr_addr, dr_new_str, sizeof(dr_new_str)); - zlog_debug("%s: DR was %s now is %s on interface %s", - __PRETTY_FUNCTION__, - dr_old_str, dr_new_str, ifp->name); - } - - pim_ifp->pim_dr_election_last = pim_time_monotonic_sec(); /* timestamp */ - ++pim_ifp->pim_dr_election_changes; - pim_if_update_join_desired(pim_ifp); - pim_if_update_could_assert(ifp); - pim_if_update_assert_tracking_desired(ifp); - return 1; - } - - return 0; + struct pim_interface *pim_ifp = ifp->info; + struct in_addr old_dr_addr; + + ++pim_ifp->pim_dr_election_count; + + old_dr_addr = pim_ifp->pim_dr_addr; + + if (pim_ifp->pim_dr_num_nondrpri_neighbors) { + dr_election_by_addr(ifp); + } else { + dr_election_by_pri(ifp); + } + + /* DR changed ? */ + if (old_dr_addr.s_addr != pim_ifp->pim_dr_addr.s_addr) { + + if (PIM_DEBUG_PIM_EVENTS) { + char dr_old_str[INET_ADDRSTRLEN]; + char dr_new_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", old_dr_addr, dr_old_str, + sizeof(dr_old_str)); + pim_inet4_dump("", pim_ifp->pim_dr_addr, + dr_new_str, sizeof(dr_new_str)); + zlog_debug("%s: DR was %s now is %s on interface %s", + __PRETTY_FUNCTION__, dr_old_str, dr_new_str, + ifp->name); + } + + pim_ifp->pim_dr_election_last = + pim_time_monotonic_sec(); /* timestamp */ + ++pim_ifp->pim_dr_election_changes; + pim_if_update_join_desired(pim_ifp); + pim_if_update_could_assert(ifp); + pim_if_update_assert_tracking_desired(ifp); + return 1; + } + + return 0; } static void update_dr_priority(struct pim_neighbor *neigh, pim_hello_options hello_options, uint32_t dr_priority) { - pim_hello_options will_set_pri; /* boolean */ - pim_hello_options bit_flip; /* boolean */ - pim_hello_options pri_change; /* boolean */ - - will_set_pri = PIM_OPTION_IS_SET(hello_options, - PIM_OPTION_MASK_DR_PRIORITY); - - bit_flip = - ( - will_set_pri != - PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_DR_PRIORITY) - ); - - if (bit_flip) { - struct pim_interface *pim_ifp = neigh->interface->info; - - /* update num. of neighbors without dr_pri */ - - if (will_set_pri) { - --pim_ifp->pim_dr_num_nondrpri_neighbors; - } - else { - ++pim_ifp->pim_dr_num_nondrpri_neighbors; - } - } - - pri_change = - ( - bit_flip - || - (neigh->dr_priority != dr_priority) - ); - - if (will_set_pri) { - neigh->dr_priority = dr_priority; - } - else { - neigh->dr_priority = 0; /* cosmetic unset */ - } - - if (pri_change) { - /* - RFC 4601: 4.3.2. DR Election - - A router's idea of the current DR on an interface can change when a - PIM Hello message is received, when a neighbor times out, or when a - router's own DR Priority changes. - */ - pim_if_dr_election(neigh->interface); // router's own DR Priority changes - } + pim_hello_options will_set_pri; /* boolean */ + pim_hello_options bit_flip; /* boolean */ + pim_hello_options pri_change; /* boolean */ + + will_set_pri = + PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_DR_PRIORITY); + + bit_flip = (will_set_pri + != PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_DR_PRIORITY)); + + if (bit_flip) { + struct pim_interface *pim_ifp = neigh->interface->info; + + /* update num. of neighbors without dr_pri */ + + if (will_set_pri) { + --pim_ifp->pim_dr_num_nondrpri_neighbors; + } else { + ++pim_ifp->pim_dr_num_nondrpri_neighbors; + } + } + + pri_change = (bit_flip || (neigh->dr_priority != dr_priority)); + + if (will_set_pri) { + neigh->dr_priority = dr_priority; + } else { + neigh->dr_priority = 0; /* cosmetic unset */ + } + + if (pri_change) { + /* + RFC 4601: 4.3.2. DR Election + + A router's idea of the current DR on an interface can change + when a + PIM Hello message is received, when a neighbor times out, or + when a + router's own DR Priority changes. + */ + pim_if_dr_election( + neigh->interface); // router's own DR Priority changes + } } static int on_neighbor_timer(struct thread *t) { - struct pim_neighbor *neigh; - struct interface *ifp; - char msg[100]; - - neigh = THREAD_ARG(t); - - ifp = neigh->interface; - - if (PIM_DEBUG_PIM_TRACE) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", neigh->source_addr, src_str, sizeof(src_str)); - zlog_debug("Expired %d sec holdtime for neighbor %s on interface %s", - neigh->holdtime, src_str, ifp->name); - } - - snprintf(msg, sizeof(msg), "%d-sec holdtime expired", neigh->holdtime); - pim_neighbor_delete(ifp, neigh, msg); - - /* - RFC 4601: 4.3.2. DR Election - - A router's idea of the current DR on an interface can change when a - PIM Hello message is received, when a neighbor times out, or when a - router's own DR Priority changes. - */ - pim_if_dr_election(ifp); // neighbor times out - - return 0; + struct pim_neighbor *neigh; + struct interface *ifp; + char msg[100]; + + neigh = THREAD_ARG(t); + + ifp = neigh->interface; + + if (PIM_DEBUG_PIM_TRACE) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", neigh->source_addr, src_str, + sizeof(src_str)); + zlog_debug( + "Expired %d sec holdtime for neighbor %s on interface %s", + neigh->holdtime, src_str, ifp->name); + } + + snprintf(msg, sizeof(msg), "%d-sec holdtime expired", neigh->holdtime); + pim_neighbor_delete(ifp, neigh, msg); + + /* + RFC 4601: 4.3.2. DR Election + + A router's idea of the current DR on an interface can change when a + PIM Hello message is received, when a neighbor times out, or when a + router's own DR Priority changes. + */ + pim_if_dr_election(ifp); // neighbor times out + + return 0; } void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime) { - neigh->holdtime = holdtime; - - THREAD_OFF(neigh->t_expire_timer); - - /* - 0xFFFF is request for no holdtime - */ - if (neigh->holdtime == 0xFFFF) { - return; - } - - if (PIM_DEBUG_PIM_TRACE_DETAIL) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", neigh->source_addr, src_str, sizeof(src_str)); - zlog_debug("%s: starting %u sec timer for neighbor %s on %s", - __PRETTY_FUNCTION__, - neigh->holdtime, src_str, neigh->interface->name); - } - - thread_add_timer(master, on_neighbor_timer, neigh, neigh->holdtime, - &neigh->t_expire_timer); + neigh->holdtime = holdtime; + + THREAD_OFF(neigh->t_expire_timer); + + /* + 0xFFFF is request for no holdtime + */ + if (neigh->holdtime == 0xFFFF) { + return; + } + + if (PIM_DEBUG_PIM_TRACE_DETAIL) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", neigh->source_addr, src_str, + sizeof(src_str)); + zlog_debug("%s: starting %u sec timer for neighbor %s on %s", + __PRETTY_FUNCTION__, neigh->holdtime, src_str, + neigh->interface->name); + } + + thread_add_timer(master, on_neighbor_timer, neigh, neigh->holdtime, + &neigh->t_expire_timer); } -static int -on_neighbor_jp_timer (struct thread *t) +static int on_neighbor_jp_timer(struct thread *t) { - struct pim_neighbor *neigh = THREAD_ARG(t); - struct pim_rpf rpf; - - if (PIM_DEBUG_PIM_TRACE) - { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", neigh->source_addr, src_str, sizeof(src_str)); - zlog_debug("%s:Sending JP Agg to %s on %s with %d groups", __PRETTY_FUNCTION__, - src_str, neigh->interface->name, neigh->upstream_jp_agg->count); - } + struct pim_neighbor *neigh = THREAD_ARG(t); + struct pim_rpf rpf; + + if (PIM_DEBUG_PIM_TRACE) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", neigh->source_addr, src_str, + sizeof(src_str)); + zlog_debug("%s:Sending JP Agg to %s on %s with %d groups", + __PRETTY_FUNCTION__, src_str, neigh->interface->name, + neigh->upstream_jp_agg->count); + } - rpf.source_nexthop.interface = neigh->interface; - rpf.rpf_addr.u.prefix4 = neigh->source_addr; - pim_joinprune_send(&rpf, neigh->upstream_jp_agg); + rpf.source_nexthop.interface = neigh->interface; + rpf.rpf_addr.u.prefix4 = neigh->source_addr; + pim_joinprune_send(&rpf, neigh->upstream_jp_agg); - thread_add_timer(master, on_neighbor_jp_timer, neigh, qpim_t_periodic, - &neigh->jp_timer); + thread_add_timer(master, on_neighbor_jp_timer, neigh, qpim_t_periodic, + &neigh->jp_timer); - return 0; + return 0; } -static void -pim_neighbor_start_jp_timer (struct pim_neighbor *neigh) +static void pim_neighbor_start_jp_timer(struct pim_neighbor *neigh) { - THREAD_TIMER_OFF(neigh->jp_timer); - thread_add_timer(master, on_neighbor_jp_timer, neigh, qpim_t_periodic, - &neigh->jp_timer); + THREAD_TIMER_OFF(neigh->jp_timer); + thread_add_timer(master, on_neighbor_jp_timer, neigh, qpim_t_periodic, + &neigh->jp_timer); } -static struct pim_neighbor *pim_neighbor_new(struct interface *ifp, - struct in_addr source_addr, - pim_hello_options hello_options, - uint16_t holdtime, - uint16_t propagation_delay, - uint16_t override_interval, - uint32_t dr_priority, - uint32_t generation_id, - struct list *addr_list) +static struct pim_neighbor * +pim_neighbor_new(struct interface *ifp, struct in_addr source_addr, + pim_hello_options hello_options, uint16_t holdtime, + uint16_t propagation_delay, uint16_t override_interval, + uint32_t dr_priority, uint32_t generation_id, + struct list *addr_list) { - struct pim_interface *pim_ifp; - struct pim_neighbor *neigh; - char src_str[INET_ADDRSTRLEN]; - - zassert(ifp); - pim_ifp = ifp->info; - zassert(pim_ifp); - - neigh = XCALLOC(MTYPE_PIM_NEIGHBOR, sizeof(*neigh)); - if (!neigh) { - zlog_err("%s: PIM XCALLOC(%zu) failure", - __PRETTY_FUNCTION__, sizeof(*neigh)); - return 0; - } - - neigh->creation = pim_time_monotonic_sec(); - neigh->source_addr = source_addr; - neigh->hello_options = hello_options; - neigh->propagation_delay_msec = propagation_delay; - neigh->override_interval_msec = override_interval; - neigh->dr_priority = dr_priority; - neigh->generation_id = generation_id; - neigh->prefix_list = addr_list; - neigh->t_expire_timer = NULL; - neigh->interface = ifp; - - neigh->upstream_jp_agg = list_new(); - neigh->upstream_jp_agg->cmp = pim_jp_agg_group_list_cmp; - neigh->upstream_jp_agg->del = (void (*)(void *))pim_jp_agg_group_list_free; - pim_neighbor_start_jp_timer(neigh); - - pim_neighbor_timer_reset(neigh, holdtime); - /* - * The pim_ifstat_hello_sent variable is used to decide if - * we should expedite a hello out the interface. If we - * establish a new neighbor, we unfortunately need to - * reset the value so that we can know to hurry up and - * hello - */ - pim_ifp->pim_ifstat_hello_sent = 0; - - pim_inet4_dump("", source_addr, src_str, sizeof(src_str)); - - if (PIM_DEBUG_PIM_EVENTS) { - zlog_debug("%s: creating PIM neighbor %s on interface %s", - __PRETTY_FUNCTION__, - src_str, ifp->name); - } - - zlog_info("PIM NEIGHBOR UP: neighbor %s on interface %s", - src_str, ifp->name); - - if (neigh->propagation_delay_msec > pim_ifp->pim_neighbors_highest_propagation_delay_msec) { - pim_ifp->pim_neighbors_highest_propagation_delay_msec = neigh->propagation_delay_msec; - } - if (neigh->override_interval_msec > pim_ifp->pim_neighbors_highest_override_interval_msec) { - pim_ifp->pim_neighbors_highest_override_interval_msec = neigh->override_interval_msec; - } - - if (!PIM_OPTION_IS_SET(neigh->hello_options, - PIM_OPTION_MASK_LAN_PRUNE_DELAY)) { - /* update num. of neighbors without hello option lan_delay */ - ++pim_ifp->pim_number_of_nonlandelay_neighbors; - } - - if (!PIM_OPTION_IS_SET(neigh->hello_options, - PIM_OPTION_MASK_DR_PRIORITY)) { - /* update num. of neighbors without hello option dr_pri */ - ++pim_ifp->pim_dr_num_nondrpri_neighbors; - } - - //Register PIM Neighbor with BFD - pim_bfd_trigger_event (pim_ifp, neigh, 1); - - return neigh; + struct pim_interface *pim_ifp; + struct pim_neighbor *neigh; + char src_str[INET_ADDRSTRLEN]; + + zassert(ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); + + neigh = XCALLOC(MTYPE_PIM_NEIGHBOR, sizeof(*neigh)); + if (!neigh) { + zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, + sizeof(*neigh)); + return 0; + } + + neigh->creation = pim_time_monotonic_sec(); + neigh->source_addr = source_addr; + neigh->hello_options = hello_options; + neigh->propagation_delay_msec = propagation_delay; + neigh->override_interval_msec = override_interval; + neigh->dr_priority = dr_priority; + neigh->generation_id = generation_id; + neigh->prefix_list = addr_list; + neigh->t_expire_timer = NULL; + neigh->interface = ifp; + + neigh->upstream_jp_agg = list_new(); + neigh->upstream_jp_agg->cmp = pim_jp_agg_group_list_cmp; + neigh->upstream_jp_agg->del = + (void (*)(void *))pim_jp_agg_group_list_free; + pim_neighbor_start_jp_timer(neigh); + + pim_neighbor_timer_reset(neigh, holdtime); + /* + * The pim_ifstat_hello_sent variable is used to decide if + * we should expedite a hello out the interface. If we + * establish a new neighbor, we unfortunately need to + * reset the value so that we can know to hurry up and + * hello + */ + pim_ifp->pim_ifstat_hello_sent = 0; + + pim_inet4_dump("", source_addr, src_str, sizeof(src_str)); + + if (PIM_DEBUG_PIM_EVENTS) { + zlog_debug("%s: creating PIM neighbor %s on interface %s", + __PRETTY_FUNCTION__, src_str, ifp->name); + } + + zlog_info("PIM NEIGHBOR UP: neighbor %s on interface %s", src_str, + ifp->name); + + if (neigh->propagation_delay_msec + > pim_ifp->pim_neighbors_highest_propagation_delay_msec) { + pim_ifp->pim_neighbors_highest_propagation_delay_msec = + neigh->propagation_delay_msec; + } + if (neigh->override_interval_msec + > pim_ifp->pim_neighbors_highest_override_interval_msec) { + pim_ifp->pim_neighbors_highest_override_interval_msec = + neigh->override_interval_msec; + } + + if (!PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_LAN_PRUNE_DELAY)) { + /* update num. of neighbors without hello option lan_delay */ + ++pim_ifp->pim_number_of_nonlandelay_neighbors; + } + + if (!PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_DR_PRIORITY)) { + /* update num. of neighbors without hello option dr_pri */ + ++pim_ifp->pim_dr_num_nondrpri_neighbors; + } + + // Register PIM Neighbor with BFD + pim_bfd_trigger_event(pim_ifp, neigh, 1); + + return neigh; } static void delete_prefix_list(struct pim_neighbor *neigh) { - if (neigh->prefix_list) { + if (neigh->prefix_list) { #ifdef DUMP_PREFIX_LIST - struct listnode *p_node; - struct prefix *p; - char addr_str[10]; - int list_size = neigh->prefix_list ? (int) listcount(neigh->prefix_list) : -1; - int i = 0; - for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, p_node, p)) { - pim_inet4_dump("", p->u.prefix4, addr_str, sizeof(addr_str)); - zlog_debug("%s: DUMP_PREFIX_LIST neigh=%x prefix_list=%x prefix=%x addr=%s [%d/%d]", - __PRETTY_FUNCTION__, - (unsigned) neigh, (unsigned) neigh->prefix_list, (unsigned) p, - addr_str, i, list_size); - ++i; - } + struct listnode *p_node; + struct prefix *p; + char addr_str[10]; + int list_size = neigh->prefix_list + ? (int)listcount(neigh->prefix_list) + : -1; + int i = 0; + for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, p_node, p)) { + pim_inet4_dump("", p->u.prefix4, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s: DUMP_PREFIX_LIST neigh=%x prefix_list=%x prefix=%x addr=%s [%d/%d]", + __PRETTY_FUNCTION__, (unsigned)neigh, + (unsigned)neigh->prefix_list, (unsigned)p, + addr_str, i, list_size); + ++i; + } #endif - list_delete(neigh->prefix_list); - neigh->prefix_list = 0; - } + list_delete(neigh->prefix_list); + neigh->prefix_list = 0; + } } void pim_neighbor_free(struct pim_neighbor *neigh) { - zassert(!neigh->t_expire_timer); + zassert(!neigh->t_expire_timer); - delete_prefix_list(neigh); + delete_prefix_list(neigh); - list_delete(neigh->upstream_jp_agg); - THREAD_OFF(neigh->jp_timer); + list_delete(neigh->upstream_jp_agg); + THREAD_OFF(neigh->jp_timer); - XFREE(MTYPE_PIM_NEIGHBOR, neigh); + XFREE(MTYPE_PIM_NEIGHBOR, neigh); } -struct pim_neighbor * -pim_neighbor_find_by_secondary (struct interface *ifp, - struct prefix *src) +struct pim_neighbor *pim_neighbor_find_by_secondary(struct interface *ifp, + struct prefix *src) { - struct pim_interface *pim_ifp; - struct listnode *node, *pnode; - struct pim_neighbor *neigh; - struct prefix *p; - - pim_ifp = ifp->info; - if (!pim_ifp) - return NULL; - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) - { - for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, pnode, p)) - { - if (prefix_same (p, src)) - return neigh; - } - } - - return NULL; + struct pim_interface *pim_ifp; + struct listnode *node, *pnode; + struct pim_neighbor *neigh; + struct prefix *p; + + pim_ifp = ifp->info; + if (!pim_ifp) + return NULL; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { + for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, pnode, p)) { + if (prefix_same(p, src)) + return neigh; + } + } + + return NULL; } struct pim_neighbor *pim_neighbor_find(struct interface *ifp, struct in_addr source_addr) { - struct pim_interface *pim_ifp; - struct listnode *node; - struct pim_neighbor *neigh; + struct pim_interface *pim_ifp; + struct listnode *node; + struct pim_neighbor *neigh; - if (!ifp) - return NULL; + if (!ifp) + return NULL; - pim_ifp = ifp->info; - if (!pim_ifp) - return NULL; + pim_ifp = ifp->info; + if (!pim_ifp) + return NULL; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { - if (source_addr.s_addr == neigh->source_addr.s_addr) { - return neigh; - } - } + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) { + if (source_addr.s_addr == neigh->source_addr.s_addr) { + return neigh; + } + } - return NULL; + return NULL; } /* @@ -473,263 +468,256 @@ struct pim_neighbor *pim_neighbor_find(struct interface *ifp, * this interface. If more than * one return NULL */ -struct pim_neighbor * -pim_neighbor_find_if (struct interface *ifp) +struct pim_neighbor *pim_neighbor_find_if(struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp || pim_ifp->pim_neighbor_list->count != 1) - return NULL; + if (!pim_ifp || pim_ifp->pim_neighbor_list->count != 1) + return NULL; - return listnode_head (pim_ifp->pim_neighbor_list); + return listnode_head(pim_ifp->pim_neighbor_list); } /* rpf info associated with an upstream entry needs to be re-evaluated * when an RPF neighbor comes or goes */ -static void -pim_neighbor_rpf_update(void) -{ - /* XXX: for the time being piggyback on the timer used on rib changes - * to scan and update the rpf nexthop. This is expensive processing - * and we should be able to optimize neighbor changes differently than - * nexthop changes. */ - sched_rpf_cache_refresh(); -} - -struct pim_neighbor *pim_neighbor_add(struct interface *ifp, - struct in_addr source_addr, - pim_hello_options hello_options, - uint16_t holdtime, - uint16_t propagation_delay, - uint16_t override_interval, - uint32_t dr_priority, - uint32_t generation_id, - struct list *addr_list, - int send_hello_now) +static void pim_neighbor_rpf_update(void) { - struct pim_interface *pim_ifp; - struct pim_neighbor *neigh; - - neigh = pim_neighbor_new(ifp, source_addr, - hello_options, - holdtime, - propagation_delay, - override_interval, - dr_priority, - generation_id, - addr_list); - if (!neigh) { - return 0; - } - - pim_ifp = ifp->info; - zassert(pim_ifp); - - listnode_add(pim_ifp->pim_neighbor_list, neigh); - - if (PIM_DEBUG_PIM_TRACE_DETAIL) - { - char str[INET_ADDRSTRLEN]; - pim_inet4_dump("", source_addr, str, sizeof (str)); - zlog_debug ("%s: neighbor %s added ", __PRETTY_FUNCTION__, str); - } - /* - RFC 4601: 4.3.2. DR Election - - A router's idea of the current DR on an interface can change when a - PIM Hello message is received, when a neighbor times out, or when a - router's own DR Priority changes. - */ - pim_if_dr_election(neigh->interface); // new neighbor -- should not trigger dr election... - - /* - RFC 4601: 4.3.1. Sending Hello Messages - - To allow new or rebooting routers to learn of PIM neighbors quickly, - when a Hello message is received from a new neighbor, or a Hello - message with a new GenID is received from an existing neighbor, a - new Hello message should be sent on this interface after a - randomized delay between 0 and Triggered_Hello_Delay. - - This is a bit silly to do it that way. If I get a new - genid we need to send the hello *now* because we've - lined up a bunch of join/prune messages to go out the - interface. - */ - if (send_hello_now) - pim_hello_restart_now (ifp); - else - pim_hello_restart_triggered(neigh->interface); - - pim_upstream_find_new_rpf(); - - /* RNH can send nexthop update prior to PIM neibhor UP - in that case nexthop cache would not consider this neighbor - as RPF. - Upon PIM neighbor UP, iterate all RPs and update - nexthop cache with this neighbor. - */ - pim_resolve_rp_nh (); - - pim_rp_setup (); - - pim_neighbor_rpf_update(); - return neigh; + /* XXX: for the time being piggyback on the timer used on rib changes + * to scan and update the rpf nexthop. This is expensive processing + * and we should be able to optimize neighbor changes differently than + * nexthop changes. */ + sched_rpf_cache_refresh(); } -static uint16_t -find_neighbors_next_highest_propagation_delay_msec(struct interface *ifp, - struct pim_neighbor *highest_neigh) +struct pim_neighbor * +pim_neighbor_add(struct interface *ifp, struct in_addr source_addr, + pim_hello_options hello_options, uint16_t holdtime, + uint16_t propagation_delay, uint16_t override_interval, + uint32_t dr_priority, uint32_t generation_id, + struct list *addr_list, int send_hello_now) { - struct pim_interface *pim_ifp; - struct listnode *neigh_node; - struct pim_neighbor *neigh; - uint16_t next_highest_delay_msec; - - pim_ifp = ifp->info; - zassert(pim_ifp); + struct pim_interface *pim_ifp; + struct pim_neighbor *neigh; + + neigh = pim_neighbor_new(ifp, source_addr, hello_options, holdtime, + propagation_delay, override_interval, + dr_priority, generation_id, addr_list); + if (!neigh) { + return 0; + } - next_highest_delay_msec = pim_ifp->pim_propagation_delay_msec; + pim_ifp = ifp->info; + zassert(pim_ifp); - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, neigh)) { - if (neigh == highest_neigh) - continue; - if (neigh->propagation_delay_msec > next_highest_delay_msec) - next_highest_delay_msec = neigh->propagation_delay_msec; - } + listnode_add(pim_ifp->pim_neighbor_list, neigh); - return next_highest_delay_msec; + if (PIM_DEBUG_PIM_TRACE_DETAIL) { + char str[INET_ADDRSTRLEN]; + pim_inet4_dump("", source_addr, str, sizeof(str)); + zlog_debug("%s: neighbor %s added ", __PRETTY_FUNCTION__, str); + } + /* + RFC 4601: 4.3.2. DR Election + + A router's idea of the current DR on an interface can change when a + PIM Hello message is received, when a neighbor times out, or when a + router's own DR Priority changes. + */ + pim_if_dr_election(neigh->interface); // new neighbor -- should not + // trigger dr election... + + /* + RFC 4601: 4.3.1. Sending Hello Messages + + To allow new or rebooting routers to learn of PIM neighbors quickly, + when a Hello message is received from a new neighbor, or a Hello + message with a new GenID is received from an existing neighbor, a + new Hello message should be sent on this interface after a + randomized delay between 0 and Triggered_Hello_Delay. + + This is a bit silly to do it that way. If I get a new + genid we need to send the hello *now* because we've + lined up a bunch of join/prune messages to go out the + interface. + */ + if (send_hello_now) + pim_hello_restart_now(ifp); + else + pim_hello_restart_triggered(neigh->interface); + + pim_upstream_find_new_rpf(); + + /* RNH can send nexthop update prior to PIM neibhor UP + in that case nexthop cache would not consider this neighbor + as RPF. + Upon PIM neighbor UP, iterate all RPs and update + nexthop cache with this neighbor. + */ + pim_resolve_rp_nh(); + + pim_rp_setup(); + + pim_neighbor_rpf_update(); + return neigh; } -static uint16_t -find_neighbors_next_highest_override_interval_msec(struct interface *ifp, - struct pim_neighbor *highest_neigh) +static uint16_t find_neighbors_next_highest_propagation_delay_msec( + struct interface *ifp, struct pim_neighbor *highest_neigh) { - struct pim_interface *pim_ifp; - struct listnode *neigh_node; - struct pim_neighbor *neigh; - uint16_t next_highest_interval_msec; - - pim_ifp = ifp->info; - zassert(pim_ifp); + struct pim_interface *pim_ifp; + struct listnode *neigh_node; + struct pim_neighbor *neigh; + uint16_t next_highest_delay_msec; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + next_highest_delay_msec = pim_ifp->pim_propagation_delay_msec; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, + neigh)) { + if (neigh == highest_neigh) + continue; + if (neigh->propagation_delay_msec > next_highest_delay_msec) + next_highest_delay_msec = neigh->propagation_delay_msec; + } - next_highest_interval_msec = pim_ifp->pim_override_interval_msec; + return next_highest_delay_msec; +} - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, neigh)) { - if (neigh == highest_neigh) - continue; - if (neigh->override_interval_msec > next_highest_interval_msec) - next_highest_interval_msec = neigh->override_interval_msec; - } +static uint16_t find_neighbors_next_highest_override_interval_msec( + struct interface *ifp, struct pim_neighbor *highest_neigh) +{ + struct pim_interface *pim_ifp; + struct listnode *neigh_node; + struct pim_neighbor *neigh; + uint16_t next_highest_interval_msec; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + next_highest_interval_msec = pim_ifp->pim_override_interval_msec; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, + neigh)) { + if (neigh == highest_neigh) + continue; + if (neigh->override_interval_msec > next_highest_interval_msec) + next_highest_interval_msec = + neigh->override_interval_msec; + } - return next_highest_interval_msec; + return next_highest_interval_msec; } -void pim_neighbor_delete(struct interface *ifp, - struct pim_neighbor *neigh, +void pim_neighbor_delete(struct interface *ifp, struct pim_neighbor *neigh, const char *delete_message) { - struct pim_interface *pim_ifp; - char src_str[INET_ADDRSTRLEN]; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - pim_inet4_dump("", neigh->source_addr, src_str, sizeof(src_str)); - zlog_info("PIM NEIGHBOR DOWN: neighbor %s on interface %s: %s", - src_str, ifp->name, delete_message); + struct pim_interface *pim_ifp; + char src_str[INET_ADDRSTRLEN]; - THREAD_OFF(neigh->t_expire_timer); + pim_ifp = ifp->info; + zassert(pim_ifp); - pim_if_assert_on_neighbor_down(ifp, neigh->source_addr); + pim_inet4_dump("", neigh->source_addr, src_str, sizeof(src_str)); + zlog_info("PIM NEIGHBOR DOWN: neighbor %s on interface %s: %s", src_str, + ifp->name, delete_message); - if (!PIM_OPTION_IS_SET(neigh->hello_options, - PIM_OPTION_MASK_LAN_PRUNE_DELAY)) { - /* update num. of neighbors without hello option lan_delay */ + THREAD_OFF(neigh->t_expire_timer); - --pim_ifp->pim_number_of_nonlandelay_neighbors; - } + pim_if_assert_on_neighbor_down(ifp, neigh->source_addr); - if (!PIM_OPTION_IS_SET(neigh->hello_options, - PIM_OPTION_MASK_DR_PRIORITY)) { - /* update num. of neighbors without dr_pri */ + if (!PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_LAN_PRUNE_DELAY)) { + /* update num. of neighbors without hello option lan_delay */ - --pim_ifp->pim_dr_num_nondrpri_neighbors; - } - - zassert(neigh->propagation_delay_msec <= pim_ifp->pim_neighbors_highest_propagation_delay_msec); - zassert(neigh->override_interval_msec <= pim_ifp->pim_neighbors_highest_override_interval_msec); + --pim_ifp->pim_number_of_nonlandelay_neighbors; + } - if (pim_if_lan_delay_enabled(ifp)) { + if (!PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_DR_PRIORITY)) { + /* update num. of neighbors without dr_pri */ - /* will delete a neighbor with highest propagation delay? */ - if (neigh->propagation_delay_msec == pim_ifp->pim_neighbors_highest_propagation_delay_msec) { - /* then find the next highest propagation delay */ - pim_ifp->pim_neighbors_highest_propagation_delay_msec = - find_neighbors_next_highest_propagation_delay_msec(ifp, neigh); - } + --pim_ifp->pim_dr_num_nondrpri_neighbors; + } - /* will delete a neighbor with highest override interval? */ - if (neigh->override_interval_msec == pim_ifp->pim_neighbors_highest_override_interval_msec) { - /* then find the next highest propagation delay */ - pim_ifp->pim_neighbors_highest_override_interval_msec = - find_neighbors_next_highest_override_interval_msec(ifp, neigh); - } - } + zassert(neigh->propagation_delay_msec + <= pim_ifp->pim_neighbors_highest_propagation_delay_msec); + zassert(neigh->override_interval_msec + <= pim_ifp->pim_neighbors_highest_override_interval_msec); + + if (pim_if_lan_delay_enabled(ifp)) { + + /* will delete a neighbor with highest propagation delay? */ + if (neigh->propagation_delay_msec + == pim_ifp->pim_neighbors_highest_propagation_delay_msec) { + /* then find the next highest propagation delay */ + pim_ifp->pim_neighbors_highest_propagation_delay_msec = + find_neighbors_next_highest_propagation_delay_msec( + ifp, neigh); + } + + /* will delete a neighbor with highest override interval? */ + if (neigh->override_interval_msec + == pim_ifp->pim_neighbors_highest_override_interval_msec) { + /* then find the next highest propagation delay */ + pim_ifp->pim_neighbors_highest_override_interval_msec = + find_neighbors_next_highest_override_interval_msec( + ifp, neigh); + } + } - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: deleting PIM neighbor %s on interface %s", - __PRETTY_FUNCTION__, - src_str, ifp->name); - } + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: deleting PIM neighbor %s on interface %s", + __PRETTY_FUNCTION__, src_str, ifp->name); + } - //De-Register PIM Neighbor with BFD - pim_bfd_trigger_event (pim_ifp, neigh, 0); + // De-Register PIM Neighbor with BFD + pim_bfd_trigger_event(pim_ifp, neigh, 0); - listnode_delete(pim_ifp->pim_neighbor_list, neigh); + listnode_delete(pim_ifp->pim_neighbor_list, neigh); - pim_neighbor_free(neigh); + pim_neighbor_free(neigh); - pim_neighbor_rpf_update(); + pim_neighbor_rpf_update(); } -void pim_neighbor_delete_all(struct interface *ifp, - const char *delete_message) +void pim_neighbor_delete_all(struct interface *ifp, const char *delete_message) { - struct pim_interface *pim_ifp; - struct listnode *neigh_node; - struct listnode *neigh_nextnode; - struct pim_neighbor *neigh; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list, neigh_node, - neigh_nextnode, neigh)) { - pim_neighbor_delete(ifp, neigh, delete_message); - } + struct pim_interface *pim_ifp; + struct listnode *neigh_node; + struct listnode *neigh_nextnode; + struct pim_neighbor *neigh; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list, neigh_node, + neigh_nextnode, neigh)) { + pim_neighbor_delete(ifp, neigh, delete_message); + } } struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh, struct prefix *addr) { - struct listnode *node; - struct prefix *p; + struct listnode *node; + struct prefix *p; - if (!neigh->prefix_list) - return 0; + if (!neigh->prefix_list) + return 0; - for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, node, p)) { - if (prefix_same (p, addr)) - return p; - } + for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, node, p)) { + if (prefix_same(p, addr)) + return p; + } - return NULL; + return NULL; } /* RFC 4601: 4.3.4. Maintaining Secondary Address Lists - + All the advertised secondary addresses in received Hello messages must be checked against those previously advertised by all other PIM neighbors on that interface. If there is a conflict and the @@ -742,104 +730,109 @@ static void delete_from_neigh_addr(struct interface *ifp, struct list *addr_list, struct in_addr neigh_addr) { - struct listnode *addr_node; - struct prefix *addr; - struct pim_interface *pim_ifp; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - zassert(addr_list); - - /* - Scan secondary address list - */ - for (ALL_LIST_ELEMENTS_RO(addr_list, addr_node, - addr)) { - struct listnode *neigh_node; - struct pim_neighbor *neigh; - - if (addr->family != AF_INET) - continue; - - /* - Scan neighbors - */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, - neigh)) { - { - struct prefix *p = pim_neighbor_find_secondary(neigh, addr); - if (p) { - char addr_str[INET_ADDRSTRLEN]; - char this_neigh_str[INET_ADDRSTRLEN]; - char other_neigh_str[INET_ADDRSTRLEN]; - - pim_inet4_dump("", addr->u.prefix4, addr_str, sizeof(addr_str)); - pim_inet4_dump("", neigh_addr, this_neigh_str, sizeof(this_neigh_str)); - pim_inet4_dump("", neigh->source_addr, other_neigh_str, sizeof(other_neigh_str)); - - zlog_info("secondary addr %s recvd from neigh %s deleted from neigh %s on %s", - addr_str, this_neigh_str, other_neigh_str, ifp->name); - - listnode_delete(neigh->prefix_list, p); - prefix_free(p); - } - } - - } /* scan neighbors */ - - } /* scan addr list */ - + struct listnode *addr_node; + struct prefix *addr; + struct pim_interface *pim_ifp; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + zassert(addr_list); + + /* + Scan secondary address list + */ + for (ALL_LIST_ELEMENTS_RO(addr_list, addr_node, addr)) { + struct listnode *neigh_node; + struct pim_neighbor *neigh; + + if (addr->family != AF_INET) + continue; + + /* + Scan neighbors + */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, + neigh_node, neigh)) { + { + struct prefix *p = pim_neighbor_find_secondary( + neigh, addr); + if (p) { + char addr_str[INET_ADDRSTRLEN]; + char this_neigh_str[INET_ADDRSTRLEN]; + char other_neigh_str[INET_ADDRSTRLEN]; + + pim_inet4_dump( + "", addr->u.prefix4, + addr_str, sizeof(addr_str)); + pim_inet4_dump("", neigh_addr, + this_neigh_str, + sizeof(this_neigh_str)); + pim_inet4_dump("", + neigh->source_addr, + other_neigh_str, + sizeof(other_neigh_str)); + + zlog_info( + "secondary addr %s recvd from neigh %s deleted from neigh %s on %s", + addr_str, this_neigh_str, + other_neigh_str, ifp->name); + + listnode_delete(neigh->prefix_list, p); + prefix_free(p); + } + } + + } /* scan neighbors */ + + } /* scan addr list */ } void pim_neighbor_update(struct pim_neighbor *neigh, - pim_hello_options hello_options, - uint16_t holdtime, - uint32_t dr_priority, - struct list *addr_list) + pim_hello_options hello_options, uint16_t holdtime, + uint32_t dr_priority, struct list *addr_list) { - struct pim_interface *pim_ifp = neigh->interface->info; - - /* Received holdtime ? */ - if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) { - pim_neighbor_timer_reset(neigh, holdtime); - } - else { - pim_neighbor_timer_reset(neigh, PIM_IF_DEFAULT_HOLDTIME(pim_ifp)); - } + struct pim_interface *pim_ifp = neigh->interface->info; + + /* Received holdtime ? */ + if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) { + pim_neighbor_timer_reset(neigh, holdtime); + } else { + pim_neighbor_timer_reset(neigh, + PIM_IF_DEFAULT_HOLDTIME(pim_ifp)); + } #ifdef DUMP_PREFIX_LIST - zlog_debug("%s: DUMP_PREFIX_LIST old_prefix_list=%x old_size=%d new_prefix_list=%x new_size=%d", - __PRETTY_FUNCTION__, - (unsigned) neigh->prefix_list, - neigh->prefix_list ? (int) listcount(neigh->prefix_list) : -1, - (unsigned) addr_list, - addr_list ? (int) listcount(addr_list) : -1); + zlog_debug( + "%s: DUMP_PREFIX_LIST old_prefix_list=%x old_size=%d new_prefix_list=%x new_size=%d", + __PRETTY_FUNCTION__, (unsigned)neigh->prefix_list, + neigh->prefix_list ? (int)listcount(neigh->prefix_list) : -1, + (unsigned)addr_list, + addr_list ? (int)listcount(addr_list) : -1); #endif - if (neigh->prefix_list == addr_list) { - if (addr_list) { - zlog_err("%s: internal error: trying to replace same prefix list=%p", - __PRETTY_FUNCTION__, (void *) addr_list); - } - } - else { - /* Delete existing secondary address list */ - delete_prefix_list(neigh); - } - - if (addr_list) { - delete_from_neigh_addr(neigh->interface, addr_list, neigh->source_addr); - } - - /* Replace secondary address list */ - neigh->prefix_list = addr_list; - - update_dr_priority(neigh, - hello_options, - dr_priority); - /* - Copy flags - */ - neigh->hello_options = hello_options; + if (neigh->prefix_list == addr_list) { + if (addr_list) { + zlog_err( + "%s: internal error: trying to replace same prefix list=%p", + __PRETTY_FUNCTION__, (void *)addr_list); + } + } else { + /* Delete existing secondary address list */ + delete_prefix_list(neigh); + } + + if (addr_list) { + delete_from_neigh_addr(neigh->interface, addr_list, + neigh->source_addr); + } + + /* Replace secondary address list */ + neigh->prefix_list = addr_list; + + update_dr_priority(neigh, hello_options, dr_priority); + /* + Copy flags + */ + neigh->hello_options = hello_options; } diff --git a/pimd/pim_neighbor.h b/pimd/pim_neighbor.h index eaaefd8fe..a4f2e10c8 100644 --- a/pimd/pim_neighbor.h +++ b/pimd/pim_neighbor.h @@ -29,54 +29,46 @@ #include "pim_tlv.h" struct pim_neighbor { - int64_t creation; /* timestamp of creation */ - struct in_addr source_addr; - pim_hello_options hello_options; - uint16_t holdtime; - uint16_t propagation_delay_msec; - uint16_t override_interval_msec; - uint32_t dr_priority; - uint32_t generation_id; - struct list *prefix_list; /* list of struct prefix */ - struct thread *t_expire_timer; - struct interface *interface; + int64_t creation; /* timestamp of creation */ + struct in_addr source_addr; + pim_hello_options hello_options; + uint16_t holdtime; + uint16_t propagation_delay_msec; + uint16_t override_interval_msec; + uint32_t dr_priority; + uint32_t generation_id; + struct list *prefix_list; /* list of struct prefix */ + struct thread *t_expire_timer; + struct interface *interface; - struct thread *jp_timer; - struct list *upstream_jp_agg; - struct bfd_info *bfd_info; + struct thread *jp_timer; + struct list *upstream_jp_agg; + struct bfd_info *bfd_info; }; void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime); void pim_neighbor_free(struct pim_neighbor *neigh); struct pim_neighbor *pim_neighbor_find(struct interface *ifp, struct in_addr source_addr); -struct pim_neighbor *pim_neighbor_find_by_secondary (struct interface *ifp, - struct prefix *src); -struct pim_neighbor *pim_neighbor_find_if (struct interface *ifp); +struct pim_neighbor *pim_neighbor_find_by_secondary(struct interface *ifp, + struct prefix *src); +struct pim_neighbor *pim_neighbor_find_if(struct interface *ifp); #define PIM_NEIGHBOR_SEND_DELAY 0 #define PIM_NEIGHBOR_SEND_NOW 1 -struct pim_neighbor *pim_neighbor_add(struct interface *ifp, - struct in_addr source_addr, - pim_hello_options hello_options, - uint16_t holdtime, - uint16_t propagation_delay, - uint16_t override_interval, - uint32_t dr_priority, - uint32_t generation_id, - struct list *addr_list, - int send_hello_now); -void pim_neighbor_delete(struct interface *ifp, - struct pim_neighbor *neigh, +struct pim_neighbor * +pim_neighbor_add(struct interface *ifp, struct in_addr source_addr, + pim_hello_options hello_options, uint16_t holdtime, + uint16_t propagation_delay, uint16_t override_interval, + uint32_t dr_priority, uint32_t generation_id, + struct list *addr_list, int send_hello_now); +void pim_neighbor_delete(struct interface *ifp, struct pim_neighbor *neigh, const char *delete_message); -void pim_neighbor_delete_all(struct interface *ifp, - const char *delete_message); +void pim_neighbor_delete_all(struct interface *ifp, const char *delete_message); void pim_neighbor_update(struct pim_neighbor *neigh, - pim_hello_options hello_options, - uint16_t holdtime, - uint32_t dr_priority, - struct list *addr_list); + pim_hello_options hello_options, uint16_t holdtime, + uint32_t dr_priority, struct list *addr_list); struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh, struct prefix *addr); int pim_if_dr_election(struct interface *ifp); diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index 4aa6ecd5f..f8bf2ac77 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -44,258 +44,247 @@ * pim_sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister * command to Zebra. */ -void -pim_sendmsg_zebra_rnh (struct zclient *zclient, struct pim_nexthop_cache *pnc, - int command) +void pim_sendmsg_zebra_rnh(struct zclient *zclient, + struct pim_nexthop_cache *pnc, int command) { - struct stream *s; - struct prefix *p; - int ret; - - /* Check socket. */ - if (!zclient || zclient->sock < 0) - return; - - p = &(pnc->rpf.rpf_addr); - s = zclient->obuf; - stream_reset (s); - zclient_create_header (s, command, VRF_DEFAULT); - /* get update for all routes for a prefix */ - stream_putc (s, 0); - - stream_putw (s, PREFIX_FAMILY (p)); - stream_putc (s, p->prefixlen); - switch (PREFIX_FAMILY (p)) - { - case AF_INET: - stream_put_in_addr (s, &p->u.prefix4); - break; - case AF_INET6: - stream_put (s, &(p->u.prefix6), 16); - break; - default: - break; - } - stream_putw_at (s, 0, stream_get_endp (s)); - - ret = zclient_send_message (zclient); - if (ret < 0) - zlog_warn ("sendmsg_nexthop: zclient_send_message() failed"); - - - if (PIM_DEBUG_TRACE) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str (p, buf, sizeof (buf)); - zlog_debug ("%s: NHT %sregistered addr %s with Zebra ret:%d ", - __PRETTY_FUNCTION__, - (command == ZEBRA_NEXTHOP_REGISTER) ? " " : "de", buf, ret); - } - - return; + struct stream *s; + struct prefix *p; + int ret; + + /* Check socket. */ + if (!zclient || zclient->sock < 0) + return; + + p = &(pnc->rpf.rpf_addr); + s = zclient->obuf; + stream_reset(s); + zclient_create_header(s, command, VRF_DEFAULT); + /* get update for all routes for a prefix */ + stream_putc(s, 0); + + stream_putw(s, PREFIX_FAMILY(p)); + stream_putc(s, p->prefixlen); + switch (PREFIX_FAMILY(p)) { + case AF_INET: + stream_put_in_addr(s, &p->u.prefix4); + break; + case AF_INET6: + stream_put(s, &(p->u.prefix6), 16); + break; + default: + break; + } + stream_putw_at(s, 0, stream_get_endp(s)); + + ret = zclient_send_message(zclient); + if (ret < 0) + zlog_warn("sendmsg_nexthop: zclient_send_message() failed"); + + + if (PIM_DEBUG_TRACE) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(p, buf, sizeof(buf)); + zlog_debug("%s: NHT %sregistered addr %s with Zebra ret:%d ", + __PRETTY_FUNCTION__, + (command == ZEBRA_NEXTHOP_REGISTER) ? " " : "de", + buf, ret); + } + + return; } -struct pim_nexthop_cache * -pim_nexthop_cache_find (struct pim_rpf *rpf) +struct pim_nexthop_cache *pim_nexthop_cache_find(struct pim_rpf *rpf) { - struct pim_nexthop_cache *pnc = NULL; - struct pim_nexthop_cache lookup; + struct pim_nexthop_cache *pnc = NULL; + struct pim_nexthop_cache lookup; - lookup.rpf.rpf_addr.family = rpf->rpf_addr.family; - lookup.rpf.rpf_addr.prefixlen = rpf->rpf_addr.prefixlen; - lookup.rpf.rpf_addr.u.prefix4.s_addr = rpf->rpf_addr.u.prefix4.s_addr; + lookup.rpf.rpf_addr.family = rpf->rpf_addr.family; + lookup.rpf.rpf_addr.prefixlen = rpf->rpf_addr.prefixlen; + lookup.rpf.rpf_addr.u.prefix4.s_addr = rpf->rpf_addr.u.prefix4.s_addr; - pnc = hash_lookup (pimg->rpf_hash, &lookup); - - return pnc; + pnc = hash_lookup(pimg->rpf_hash, &lookup); + return pnc; } -struct pim_nexthop_cache * -pim_nexthop_cache_add (struct pim_rpf *rpf_addr) +struct pim_nexthop_cache *pim_nexthop_cache_add(struct pim_rpf *rpf_addr) { - struct pim_nexthop_cache *pnc; - - pnc = XCALLOC (MTYPE_PIM_NEXTHOP_CACHE, sizeof (struct pim_nexthop_cache)); - if (!pnc) - { - zlog_err ("%s: NHT PIM XCALLOC failure ", __PRETTY_FUNCTION__); - return NULL; - } - pnc->rpf.rpf_addr.family = rpf_addr->rpf_addr.family; - pnc->rpf.rpf_addr.prefixlen = rpf_addr->rpf_addr.prefixlen; - pnc->rpf.rpf_addr.u.prefix4.s_addr = rpf_addr->rpf_addr.u.prefix4.s_addr; - - pnc = hash_get (pimg->rpf_hash, pnc, hash_alloc_intern); - - pnc->rp_list = list_new (); - pnc->rp_list->cmp = pim_rp_list_cmp; - - pnc->upstream_list = list_new (); - pnc->upstream_list->cmp = pim_upstream_compare; - - if (PIM_DEBUG_ZEBRA) - { - char rpf_str[PREFIX_STRLEN]; - pim_addr_dump ("", &rpf_addr->rpf_addr, rpf_str, - sizeof (rpf_str)); - zlog_debug ("%s: NHT hash node, RP and UP lists allocated for %s ", - __PRETTY_FUNCTION__, rpf_str); - } - - return pnc; + struct pim_nexthop_cache *pnc; + + pnc = XCALLOC(MTYPE_PIM_NEXTHOP_CACHE, + sizeof(struct pim_nexthop_cache)); + if (!pnc) { + zlog_err("%s: NHT PIM XCALLOC failure ", __PRETTY_FUNCTION__); + return NULL; + } + pnc->rpf.rpf_addr.family = rpf_addr->rpf_addr.family; + pnc->rpf.rpf_addr.prefixlen = rpf_addr->rpf_addr.prefixlen; + pnc->rpf.rpf_addr.u.prefix4.s_addr = + rpf_addr->rpf_addr.u.prefix4.s_addr; + + pnc = hash_get(pimg->rpf_hash, pnc, hash_alloc_intern); + + pnc->rp_list = list_new(); + pnc->rp_list->cmp = pim_rp_list_cmp; + + pnc->upstream_list = list_new(); + pnc->upstream_list->cmp = pim_upstream_compare; + + if (PIM_DEBUG_ZEBRA) { + char rpf_str[PREFIX_STRLEN]; + pim_addr_dump("", &rpf_addr->rpf_addr, rpf_str, + sizeof(rpf_str)); + zlog_debug( + "%s: NHT hash node, RP and UP lists allocated for %s ", + __PRETTY_FUNCTION__, rpf_str); + } + + return pnc; } /* This API is used to Register an address with Zebra ret 1 means nexthop cache is found. */ -int -pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up, - struct rp_info *rp, - struct pim_nexthop_cache *out_pnc) +int pim_find_or_track_nexthop(struct prefix *addr, struct pim_upstream *up, + struct rp_info *rp, + struct pim_nexthop_cache *out_pnc) { - struct pim_nexthop_cache *pnc = NULL; - struct pim_rpf rpf; - struct listnode *ch_node = NULL; - struct zclient *zclient = NULL; - - zclient = pim_zebra_zclient_get (); - memset (&rpf, 0, sizeof (struct pim_rpf)); - rpf.rpf_addr.family = addr->family; - rpf.rpf_addr.prefixlen = addr->prefixlen; - rpf.rpf_addr.u.prefix4 = addr->u.prefix4; - - pnc = pim_nexthop_cache_find (&rpf); - if (!pnc) - { - pnc = pim_nexthop_cache_add (&rpf); - if (pnc) - pim_sendmsg_zebra_rnh (zclient, pnc, ZEBRA_NEXTHOP_REGISTER); - else - { - char rpf_str[PREFIX_STRLEN]; - pim_addr_dump ("", addr, rpf_str, sizeof (rpf_str)); - zlog_warn ("%s: pnc node allocation failed. addr %s ", - __PRETTY_FUNCTION__, rpf_str); - return -1; - } - } - - if (rp != NULL) - { - ch_node = listnode_lookup (pnc->rp_list, rp); - if (ch_node == NULL) - { - if (PIM_DEBUG_ZEBRA) - { - char rp_str[PREFIX_STRLEN]; - pim_addr_dump ("", &rp->rp.rpf_addr, rp_str, - sizeof (rp_str)); - zlog_debug ("%s: Add RP %s node to pnc cached list", - __PRETTY_FUNCTION__, rp_str); - } - listnode_add_sort (pnc->rp_list, rp); - } - } - - if (up != NULL) - { - ch_node = listnode_lookup (pnc->upstream_list, up); - if (ch_node == NULL) - { - if (PIM_DEBUG_ZEBRA) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str (addr, buf, sizeof (buf)); - zlog_debug ("%s: Add upstream %s node to pnc cached list, rpf %s", - __PRETTY_FUNCTION__, up->sg_str, buf); - } - listnode_add_sort (pnc->upstream_list, up); - } - } - - if (pnc && CHECK_FLAG (pnc->flags, PIM_NEXTHOP_VALID)) - { - memcpy (out_pnc, pnc, sizeof (struct pim_nexthop_cache)); - return 1; - } - - return 0; + struct pim_nexthop_cache *pnc = NULL; + struct pim_rpf rpf; + struct listnode *ch_node = NULL; + struct zclient *zclient = NULL; + + zclient = pim_zebra_zclient_get(); + memset(&rpf, 0, sizeof(struct pim_rpf)); + rpf.rpf_addr.family = addr->family; + rpf.rpf_addr.prefixlen = addr->prefixlen; + rpf.rpf_addr.u.prefix4 = addr->u.prefix4; + + pnc = pim_nexthop_cache_find(&rpf); + if (!pnc) { + pnc = pim_nexthop_cache_add(&rpf); + if (pnc) + pim_sendmsg_zebra_rnh(zclient, pnc, + ZEBRA_NEXTHOP_REGISTER); + else { + char rpf_str[PREFIX_STRLEN]; + pim_addr_dump("", addr, rpf_str, + sizeof(rpf_str)); + zlog_warn("%s: pnc node allocation failed. addr %s ", + __PRETTY_FUNCTION__, rpf_str); + return -1; + } + } + + if (rp != NULL) { + ch_node = listnode_lookup(pnc->rp_list, rp); + if (ch_node == NULL) { + if (PIM_DEBUG_ZEBRA) { + char rp_str[PREFIX_STRLEN]; + pim_addr_dump("", &rp->rp.rpf_addr, rp_str, + sizeof(rp_str)); + zlog_debug( + "%s: Add RP %s node to pnc cached list", + __PRETTY_FUNCTION__, rp_str); + } + listnode_add_sort(pnc->rp_list, rp); + } + } + + if (up != NULL) { + ch_node = listnode_lookup(pnc->upstream_list, up); + if (ch_node == NULL) { + if (PIM_DEBUG_ZEBRA) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(addr, buf, sizeof(buf)); + zlog_debug( + "%s: Add upstream %s node to pnc cached list, rpf %s", + __PRETTY_FUNCTION__, up->sg_str, buf); + } + listnode_add_sort(pnc->upstream_list, up); + } + } + + if (pnc && CHECK_FLAG(pnc->flags, PIM_NEXTHOP_VALID)) { + memcpy(out_pnc, pnc, sizeof(struct pim_nexthop_cache)); + return 1; + } + + return 0; } -void -pim_delete_tracked_nexthop (struct prefix *addr, struct pim_upstream *up, - struct rp_info *rp) +void pim_delete_tracked_nexthop(struct prefix *addr, struct pim_upstream *up, + struct rp_info *rp) { - struct pim_nexthop_cache *pnc = NULL; - struct pim_nexthop_cache lookup; - struct zclient *zclient = NULL; - - zclient = pim_zebra_zclient_get (); - - /* Remove from RPF hash if it is the last entry */ - lookup.rpf.rpf_addr = *addr; - pnc = hash_lookup (pimg->rpf_hash, &lookup); - if (pnc) - { - if (rp) - listnode_delete (pnc->rp_list, rp); - if (up) - listnode_delete (pnc->upstream_list, up); - - if (PIM_DEBUG_ZEBRA) - zlog_debug ("%s: NHT rp_list count:%d upstream_list count:%d ", - __PRETTY_FUNCTION__, pnc->rp_list->count, - pnc->upstream_list->count); - - if (pnc->rp_list->count == 0 && pnc->upstream_list->count == 0) - { - pim_sendmsg_zebra_rnh (zclient, pnc, ZEBRA_NEXTHOP_UNREGISTER); - - list_delete (pnc->rp_list); - list_delete (pnc->upstream_list); - - hash_release (pimg->rpf_hash, pnc); - if (pnc->nexthop) - nexthops_free (pnc->nexthop); - XFREE (MTYPE_PIM_NEXTHOP_CACHE, pnc); - } - } + struct pim_nexthop_cache *pnc = NULL; + struct pim_nexthop_cache lookup; + struct zclient *zclient = NULL; + + zclient = pim_zebra_zclient_get(); + + /* Remove from RPF hash if it is the last entry */ + lookup.rpf.rpf_addr = *addr; + pnc = hash_lookup(pimg->rpf_hash, &lookup); + if (pnc) { + if (rp) + listnode_delete(pnc->rp_list, rp); + if (up) + listnode_delete(pnc->upstream_list, up); + + if (PIM_DEBUG_ZEBRA) + zlog_debug( + "%s: NHT rp_list count:%d upstream_list count:%d ", + __PRETTY_FUNCTION__, pnc->rp_list->count, + pnc->upstream_list->count); + + if (pnc->rp_list->count == 0 + && pnc->upstream_list->count == 0) { + pim_sendmsg_zebra_rnh(zclient, pnc, + ZEBRA_NEXTHOP_UNREGISTER); + + list_delete(pnc->rp_list); + list_delete(pnc->upstream_list); + + hash_release(pimg->rpf_hash, pnc); + if (pnc->nexthop) + nexthops_free(pnc->nexthop); + XFREE(MTYPE_PIM_NEXTHOP_CACHE, pnc); + } + } } /* Update RP nexthop info based on Nexthop update received from Zebra.*/ -int -pim_update_rp_nh (struct pim_nexthop_cache *pnc) +int pim_update_rp_nh(struct pim_nexthop_cache *pnc) { - struct listnode *node = NULL; - struct rp_info *rp_info = NULL; - int ret = 0; - - /*Traverse RP list and update each RP Nexthop info */ - for (ALL_LIST_ELEMENTS_RO (pnc->rp_list, node, rp_info)) - { - if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) - continue; - - //Compute PIM RPF using cached nexthop - ret = pim_ecmp_nexthop_search (pnc, &rp_info->rp.source_nexthop, - &rp_info->rp.rpf_addr, &rp_info->group, 1); - - if (PIM_DEBUG_TRACE) - { - char rp_str[PREFIX_STRLEN]; - pim_addr_dump ("", &rp_info->rp.rpf_addr, rp_str, - sizeof (rp_str)); - zlog_debug ("%s: NHT update, nexthop for RP %s is interface %s ", - __PRETTY_FUNCTION__, rp_str, - rp_info->rp.source_nexthop.interface->name); - } - } - - if (ret) - return 0; - - return 1; + struct listnode *node = NULL; + struct rp_info *rp_info = NULL; + int ret = 0; + + /*Traverse RP list and update each RP Nexthop info */ + for (ALL_LIST_ELEMENTS_RO(pnc->rp_list, node, rp_info)) { + if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) + continue; + + // Compute PIM RPF using cached nexthop + ret = pim_ecmp_nexthop_search(pnc, &rp_info->rp.source_nexthop, + &rp_info->rp.rpf_addr, + &rp_info->group, 1); + + if (PIM_DEBUG_TRACE) { + char rp_str[PREFIX_STRLEN]; + pim_addr_dump("", &rp_info->rp.rpf_addr, rp_str, + sizeof(rp_str)); + zlog_debug( + "%s: NHT update, nexthop for RP %s is interface %s ", + __PRETTY_FUNCTION__, rp_str, + rp_info->rp.source_nexthop.interface->name); + } + } + + if (ret) + return 0; + + return 1; } /* This API is used to traverse nexthop cache of RPF addr @@ -303,771 +292,779 @@ pim_update_rp_nh (struct pim_nexthop_cache *pnc) unresolved state and due to event like pim neighbor UP event if it can be resolved. */ -void -pim_resolve_upstream_nh (struct prefix *nht_p) +void pim_resolve_upstream_nh(struct prefix *nht_p) { - struct nexthop *nh_node = NULL; - struct pim_nexthop_cache pnc; - struct pim_neighbor *nbr = NULL; - - memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); - if ((pim_find_or_track_nexthop (nht_p, NULL, NULL, &pnc)) == 1) - { - for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) - { - if (nh_node->gate.ipv4.s_addr == 0) - { - struct interface *ifp1 = if_lookup_by_index(nh_node->ifindex, - VRF_DEFAULT); - nbr = pim_neighbor_find_if (ifp1); - if (nbr) - { - nh_node->gate.ipv4 = nbr->source_addr; - if (PIM_DEBUG_TRACE) - { - char str[PREFIX_STRLEN]; - char str1[INET_ADDRSTRLEN]; - pim_inet4_dump ("", nbr->source_addr, str1, - sizeof (str1)); - pim_addr_dump ("", nht_p, str, sizeof (str)); - zlog_debug ("%s: addr %s new nexthop addr %s interface %s", - __PRETTY_FUNCTION__, str, str1, ifp1->name); - } - } - } - } - } + struct nexthop *nh_node = NULL; + struct pim_nexthop_cache pnc; + struct pim_neighbor *nbr = NULL; + + memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); + if ((pim_find_or_track_nexthop(nht_p, NULL, NULL, &pnc)) == 1) { + for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) { + if (nh_node->gate.ipv4.s_addr == 0) { + struct interface *ifp1 = if_lookup_by_index( + nh_node->ifindex, VRF_DEFAULT); + nbr = pim_neighbor_find_if(ifp1); + if (nbr) { + nh_node->gate.ipv4 = nbr->source_addr; + if (PIM_DEBUG_TRACE) { + char str[PREFIX_STRLEN]; + char str1[INET_ADDRSTRLEN]; + pim_inet4_dump("", + nbr->source_addr, + str1, + sizeof(str1)); + pim_addr_dump("", + nht_p, str, + sizeof(str)); + zlog_debug( + "%s: addr %s new nexthop addr %s interface %s", + __PRETTY_FUNCTION__, + str, str1, ifp1->name); + } + } + } + } + } } /* Update Upstream nexthop info based on Nexthop update received from Zebra.*/ -static int -pim_update_upstream_nh (struct pim_nexthop_cache *pnc) +static int pim_update_upstream_nh(struct pim_nexthop_cache *pnc) { - struct listnode *up_node; - struct listnode *ifnode; - struct listnode *up_nextnode; - struct listnode *node; - struct pim_upstream *up = NULL; - struct interface *ifp = NULL; - int vif_index = 0; - - for (ALL_LIST_ELEMENTS (pnc->upstream_list, up_node, up_nextnode, up)) - { - enum pim_rpf_result rpf_result; - struct pim_rpf old; - - old.source_nexthop.interface = up->rpf.source_nexthop.interface; - rpf_result = pim_rpf_update (up, &old, 0); - if (rpf_result == PIM_RPF_FAILURE) - continue; - - /* update kernel multicast forwarding cache (MFC) */ - if (up->channel_oil) - { - ifindex_t ifindex = up->rpf.source_nexthop.interface->ifindex; - vif_index = pim_if_find_vifindex_by_ifindex (ifindex); - /* Pass Current selected NH vif index to mroute download */ - if (vif_index) - pim_scan_individual_oil (up->channel_oil, vif_index); - else - { - if (PIM_DEBUG_ZEBRA) - zlog_debug ("%s: NHT upstream %s channel_oil IIF %s vif_index is not valid", - __PRETTY_FUNCTION__, up->sg_str, - up->rpf.source_nexthop.interface->name); - } - } - - if (rpf_result == PIM_RPF_CHANGED) - { - struct pim_neighbor *nbr; - - nbr = pim_neighbor_find (old.source_nexthop.interface, - old.rpf_addr.u.prefix4); - if (nbr) - pim_jp_agg_remove_group (nbr->upstream_jp_agg, up); - - /* - * We have detected a case where we might need to rescan - * the inherited o_list so do it. - */ - if (up->channel_oil && up->channel_oil->oil_inherited_rescan) - { - pim_upstream_inherited_olist_decide (up); - up->channel_oil->oil_inherited_rescan = 0; - } - - if (up->join_state == PIM_UPSTREAM_JOINED) - { - /* - * If we come up real fast we can be here - * where the mroute has not been installed - * so install it. - */ - if (up->channel_oil && !up->channel_oil->installed) - pim_mroute_add (up->channel_oil, __PRETTY_FUNCTION__); - - /* - RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages - - Transitions from Joined State - - RPF'(S,G) changes not due to an Assert - - The upstream (S,G) state machine remains in Joined - state. Send Join(S,G) to the new upstream neighbor, which is - the new value of RPF'(S,G). Send Prune(S,G) to the old - upstream neighbor, which is the old value of RPF'(S,G). Set - the Join Timer (JT) to expire after t_periodic seconds. - */ - pim_jp_agg_switch_interface (&old, &up->rpf, up); - - pim_upstream_join_timer_restart (up, &old); - } /* up->join_state == PIM_UPSTREAM_JOINED */ - - /* FIXME can join_desired actually be changed by pim_rpf_update() - returning PIM_RPF_CHANGED ? */ - pim_upstream_update_join_desired (up); - - } /* PIM_RPF_CHANGED */ - - if (PIM_DEBUG_TRACE) - { - zlog_debug ("%s: NHT upstream %s old ifp %s new ifp %s", - __PRETTY_FUNCTION__, up->sg_str, - old.source_nexthop.interface->name, - up->rpf.source_nexthop.interface->name); - } - } /* for (pnc->upstream_list) */ - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) - if (ifp->info) - { - struct pim_interface *pim_ifp = ifp->info; - struct pim_iface_upstream_switch *us; - - for (ALL_LIST_ELEMENTS_RO (pim_ifp->upstream_switch_list, node, us)) - { - struct pim_rpf rpf; - rpf.source_nexthop.interface = ifp; - rpf.rpf_addr.u.prefix4 = us->address; - pim_joinprune_send (&rpf, us->us); - pim_jp_agg_clear_group (us->us); - } - } - - return 0; + struct listnode *up_node; + struct listnode *ifnode; + struct listnode *up_nextnode; + struct listnode *node; + struct pim_upstream *up = NULL; + struct interface *ifp = NULL; + int vif_index = 0; + + for (ALL_LIST_ELEMENTS(pnc->upstream_list, up_node, up_nextnode, up)) { + enum pim_rpf_result rpf_result; + struct pim_rpf old; + + old.source_nexthop.interface = up->rpf.source_nexthop.interface; + rpf_result = pim_rpf_update(up, &old, 0); + if (rpf_result == PIM_RPF_FAILURE) + continue; + + /* update kernel multicast forwarding cache (MFC) */ + if (up->channel_oil) { + ifindex_t ifindex = + up->rpf.source_nexthop.interface->ifindex; + vif_index = pim_if_find_vifindex_by_ifindex(ifindex); + /* Pass Current selected NH vif index to mroute download + */ + if (vif_index) + pim_scan_individual_oil(up->channel_oil, + vif_index); + else { + if (PIM_DEBUG_ZEBRA) + zlog_debug( + "%s: NHT upstream %s channel_oil IIF %s vif_index is not valid", + __PRETTY_FUNCTION__, up->sg_str, + up->rpf.source_nexthop + .interface->name); + } + } + + if (rpf_result == PIM_RPF_CHANGED) { + struct pim_neighbor *nbr; + + nbr = pim_neighbor_find(old.source_nexthop.interface, + old.rpf_addr.u.prefix4); + if (nbr) + pim_jp_agg_remove_group(nbr->upstream_jp_agg, + up); + + /* + * We have detected a case where we might need to rescan + * the inherited o_list so do it. + */ + if (up->channel_oil + && up->channel_oil->oil_inherited_rescan) { + pim_upstream_inherited_olist_decide(up); + up->channel_oil->oil_inherited_rescan = 0; + } + + if (up->join_state == PIM_UPSTREAM_JOINED) { + /* + * If we come up real fast we can be here + * where the mroute has not been installed + * so install it. + */ + if (up->channel_oil + && !up->channel_oil->installed) + pim_mroute_add(up->channel_oil, + __PRETTY_FUNCTION__); + + /* + RFC 4601: 4.5.7. Sending (S,G) Join/Prune + Messages + + Transitions from Joined State + + RPF'(S,G) changes not due to an Assert + + The upstream (S,G) state machine remains in + Joined + state. Send Join(S,G) to the new upstream + neighbor, which is + the new value of RPF'(S,G). Send Prune(S,G) + to the old + upstream neighbor, which is the old value of + RPF'(S,G). Set + the Join Timer (JT) to expire after + t_periodic seconds. + */ + pim_jp_agg_switch_interface(&old, &up->rpf, up); + + pim_upstream_join_timer_restart(up, &old); + } /* up->join_state == PIM_UPSTREAM_JOINED */ + + /* FIXME can join_desired actually be changed by + pim_rpf_update() + returning PIM_RPF_CHANGED ? */ + pim_upstream_update_join_desired(up); + + } /* PIM_RPF_CHANGED */ + + if (PIM_DEBUG_TRACE) { + zlog_debug("%s: NHT upstream %s old ifp %s new ifp %s", + __PRETTY_FUNCTION__, up->sg_str, + old.source_nexthop.interface->name, + up->rpf.source_nexthop.interface->name); + } + } /* for (pnc->upstream_list) */ + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) + if (ifp->info) { + struct pim_interface *pim_ifp = ifp->info; + struct pim_iface_upstream_switch *us; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list, + node, us)) { + struct pim_rpf rpf; + rpf.source_nexthop.interface = ifp; + rpf.rpf_addr.u.prefix4 = us->address; + pim_joinprune_send(&rpf, us->us); + pim_jp_agg_clear_group(us->us); + } + } + + return 0; } -uint32_t -pim_compute_ecmp_hash (struct prefix * src, struct prefix * grp) +uint32_t pim_compute_ecmp_hash(struct prefix *src, struct prefix *grp) { - uint32_t hash_val; - uint32_t s = 0, g = 0; - - if ((!src)) - return 0; - - switch (src->family) - { - case AF_INET: - { - s = src->u.prefix4.s_addr; - s = s == 0 ? 1 : s; - if (grp) - g = grp->u.prefix4.s_addr; - } - break; - default: - break; - } - - hash_val = jhash_2words (g, s, 101); - if (PIM_DEBUG_PIM_TRACE_DETAIL) - { - char buf[PREFIX2STR_BUFFER]; - char bufg[PREFIX2STR_BUFFER]; - prefix2str (src, buf, sizeof (buf)); - if (grp) - prefix2str (grp, bufg, sizeof (bufg)); - zlog_debug ("%s: addr %s %s hash_val %u", __PRETTY_FUNCTION__, buf, - grp ? bufg : "", hash_val); - - } - return hash_val; + uint32_t hash_val; + uint32_t s = 0, g = 0; + + if ((!src)) + return 0; + + switch (src->family) { + case AF_INET: { + s = src->u.prefix4.s_addr; + s = s == 0 ? 1 : s; + if (grp) + g = grp->u.prefix4.s_addr; + } break; + default: + break; + } + + hash_val = jhash_2words(g, s, 101); + if (PIM_DEBUG_PIM_TRACE_DETAIL) { + char buf[PREFIX2STR_BUFFER]; + char bufg[PREFIX2STR_BUFFER]; + prefix2str(src, buf, sizeof(buf)); + if (grp) + prefix2str(grp, bufg, sizeof(bufg)); + zlog_debug("%s: addr %s %s hash_val %u", __PRETTY_FUNCTION__, + buf, grp ? bufg : "", hash_val); + } + return hash_val; } -int -pim_ecmp_nexthop_search (struct pim_nexthop_cache *pnc, - struct pim_nexthop *nexthop, struct prefix *src, - struct prefix *grp, int neighbor_needed) +int pim_ecmp_nexthop_search(struct pim_nexthop_cache *pnc, + struct pim_nexthop *nexthop, struct prefix *src, + struct prefix *grp, int neighbor_needed) { - struct pim_neighbor *nbr = NULL; - struct nexthop *nh_node = NULL; - ifindex_t first_ifindex; - struct interface *ifp = NULL; - uint32_t hash_val = 0, mod_val = 0; - uint8_t nh_iter = 0, found = 0; - - if (!pnc || !pnc->nexthop_num || !nexthop) - return -1; - - //Current Nexthop is VALID, check to stay on the current path. - if (nexthop->interface && nexthop->interface->info && - nexthop->mrib_nexthop_addr.u.prefix4.s_addr != - PIM_NET_INADDR_ANY) - { - /* User configured knob to explicitly switch - to new path is disabled or current path - metric is less than nexthop update. - */ - - if (qpim_ecmp_rebalance_enable == 0) - { - uint8_t curr_route_valid = 0; - //Check if current nexthop is present in new updated Nexthop list. - //If the current nexthop is not valid, candidate to choose new Nexthop. - for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) - curr_route_valid = (nexthop->interface->ifindex == nh_node->ifindex); - - if (curr_route_valid && - !pim_if_connected_to_source (nexthop->interface, - src->u.prefix4)) - { - nbr = pim_neighbor_find (nexthop->interface, - nexthop->mrib_nexthop_addr.u.prefix4); - if (!nbr && !if_is_loopback (nexthop->interface)) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: current nexthop does not have nbr ", - __PRETTY_FUNCTION__); - } - else - { - if (PIM_DEBUG_TRACE) - { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("", src->u.prefix4, src_str, - sizeof (src_str)); - char grp_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("", grp->u.prefix4, grp_str, - sizeof (grp_str)); - zlog_debug ("%s: (%s, %s) current nexthop %s is valid, skipping new path selection", - __PRETTY_FUNCTION__, src_str, grp_str, - nexthop->interface->name); - } - return 0; - } - } - } - } - if (qpim_ecmp_enable) - { - //PIM ECMP flag is enable then choose ECMP path. - hash_val = pim_compute_ecmp_hash (src, grp); - mod_val = hash_val % pnc->nexthop_num; - if (PIM_DEBUG_PIM_TRACE_DETAIL) - zlog_debug ("%s: hash_val %u mod_val %u ", - __PRETTY_FUNCTION__, hash_val, mod_val); - } - - for (nh_node = pnc->nexthop; nh_node && (found == 0); - nh_node = nh_node->next) - { - first_ifindex = nh_node->ifindex; - ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); - if (!ifp) - { - if (PIM_DEBUG_ZEBRA) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("", src->u.prefix4, addr_str, - sizeof (addr_str)); - zlog_debug ("%s %s: could not find interface for ifindex %d (address %s)", - __FILE__, __PRETTY_FUNCTION__, first_ifindex, addr_str); - } - if (nh_iter == mod_val) - mod_val++; //Select nexthpath - nh_iter++; - continue; - } - if (!ifp->info) - { - if (PIM_DEBUG_ZEBRA) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("", src->u.prefix4, addr_str, - sizeof (addr_str)); - zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", - __PRETTY_FUNCTION__, ifp->name, first_ifindex, addr_str); - } - if (nh_iter == mod_val) - mod_val++; //Select nexthpath - nh_iter++; - continue; - } - - if (neighbor_needed - && !pim_if_connected_to_source (ifp, src->u.prefix4)) - { - nbr = pim_neighbor_find (ifp, nh_node->gate.ipv4); - if (PIM_DEBUG_PIM_TRACE_DETAIL) - zlog_debug ("ifp name: %s, pim nbr: %p", ifp->name, nbr); - if (!nbr && !if_is_loopback (ifp)) - { - if (PIM_DEBUG_ZEBRA) - zlog_debug ("%s: pim nbr not found on input interface %s", - __PRETTY_FUNCTION__, ifp->name); - if (nh_iter == mod_val) - mod_val++; //Select nexthpath - nh_iter++; - continue; - } - } - - if (nh_iter == mod_val) - { - nexthop->interface = ifp; - nexthop->mrib_nexthop_addr.family = AF_INET; - nexthop->mrib_nexthop_addr.prefixlen = IPV4_MAX_BITLEN; - nexthop->mrib_nexthop_addr.u.prefix4 = nh_node->gate.ipv4; - nexthop->mrib_metric_preference = pnc->distance; - nexthop->mrib_route_metric = pnc->metric; - nexthop->last_lookup = src->u.prefix4; - nexthop->last_lookup_time = pim_time_monotonic_usec (); - nexthop->nbr = nbr; - found = 1; - if (PIM_DEBUG_ZEBRA) - { - char buf[INET_ADDRSTRLEN]; - char buf2[INET_ADDRSTRLEN]; - char buf3[INET_ADDRSTRLEN]; - pim_inet4_dump ("", src->u.prefix4, buf2, sizeof (buf2)); - pim_inet4_dump ("", grp->u.prefix4, buf3, sizeof (buf3)); - pim_inet4_dump ("", - nexthop->mrib_nexthop_addr.u.prefix4, buf, - sizeof (buf)); - zlog_debug ("%s: (%s, %s) selected nhop interface %s addr %s mod_val %u iter %d ecmp %d", - __PRETTY_FUNCTION__, buf2, buf3, ifp->name, - buf, mod_val, nh_iter, qpim_ecmp_enable); - } - } - nh_iter++; - } - - if (found) - return 0; - else - return -1; + struct pim_neighbor *nbr = NULL; + struct nexthop *nh_node = NULL; + ifindex_t first_ifindex; + struct interface *ifp = NULL; + uint32_t hash_val = 0, mod_val = 0; + uint8_t nh_iter = 0, found = 0; + + if (!pnc || !pnc->nexthop_num || !nexthop) + return -1; + + // Current Nexthop is VALID, check to stay on the current path. + if (nexthop->interface && nexthop->interface->info + && nexthop->mrib_nexthop_addr.u.prefix4.s_addr + != PIM_NET_INADDR_ANY) { + /* User configured knob to explicitly switch + to new path is disabled or current path + metric is less than nexthop update. + */ + + if (qpim_ecmp_rebalance_enable == 0) { + uint8_t curr_route_valid = 0; + // Check if current nexthop is present in new updated + // Nexthop list. + // If the current nexthop is not valid, candidate to + // choose new Nexthop. + for (nh_node = pnc->nexthop; nh_node; + nh_node = nh_node->next) + curr_route_valid = (nexthop->interface->ifindex + == nh_node->ifindex); + + if (curr_route_valid + && !pim_if_connected_to_source(nexthop->interface, + src->u.prefix4)) { + nbr = pim_neighbor_find( + nexthop->interface, + nexthop->mrib_nexthop_addr.u.prefix4); + if (!nbr + && !if_is_loopback(nexthop->interface)) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: current nexthop does not have nbr ", + __PRETTY_FUNCTION__); + } else { + if (PIM_DEBUG_TRACE) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", + src->u.prefix4, + src_str, + sizeof(src_str)); + char grp_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", + grp->u.prefix4, + grp_str, + sizeof(grp_str)); + zlog_debug( + "%s: (%s, %s) current nexthop %s is valid, skipping new path selection", + __PRETTY_FUNCTION__, + src_str, grp_str, + nexthop->interface->name); + } + return 0; + } + } + } + } + if (qpim_ecmp_enable) { + // PIM ECMP flag is enable then choose ECMP path. + hash_val = pim_compute_ecmp_hash(src, grp); + mod_val = hash_val % pnc->nexthop_num; + if (PIM_DEBUG_PIM_TRACE_DETAIL) + zlog_debug("%s: hash_val %u mod_val %u ", + __PRETTY_FUNCTION__, hash_val, mod_val); + } + + for (nh_node = pnc->nexthop; nh_node && (found == 0); + nh_node = nh_node->next) { + first_ifindex = nh_node->ifindex; + ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); + if (!ifp) { + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src->u.prefix4, + addr_str, sizeof(addr_str)); + zlog_debug( + "%s %s: could not find interface for ifindex %d (address %s)", + __FILE__, __PRETTY_FUNCTION__, + first_ifindex, addr_str); + } + if (nh_iter == mod_val) + mod_val++; // Select nexthpath + nh_iter++; + continue; + } + if (!ifp->info) { + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src->u.prefix4, + addr_str, sizeof(addr_str)); + zlog_debug( + "%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", + __PRETTY_FUNCTION__, ifp->name, + first_ifindex, addr_str); + } + if (nh_iter == mod_val) + mod_val++; // Select nexthpath + nh_iter++; + continue; + } + + if (neighbor_needed + && !pim_if_connected_to_source(ifp, src->u.prefix4)) { + nbr = pim_neighbor_find(ifp, nh_node->gate.ipv4); + if (PIM_DEBUG_PIM_TRACE_DETAIL) + zlog_debug("ifp name: %s, pim nbr: %p", + ifp->name, nbr); + if (!nbr && !if_is_loopback(ifp)) { + if (PIM_DEBUG_ZEBRA) + zlog_debug( + "%s: pim nbr not found on input interface %s", + __PRETTY_FUNCTION__, ifp->name); + if (nh_iter == mod_val) + mod_val++; // Select nexthpath + nh_iter++; + continue; + } + } + + if (nh_iter == mod_val) { + nexthop->interface = ifp; + nexthop->mrib_nexthop_addr.family = AF_INET; + nexthop->mrib_nexthop_addr.prefixlen = IPV4_MAX_BITLEN; + nexthop->mrib_nexthop_addr.u.prefix4 = + nh_node->gate.ipv4; + nexthop->mrib_metric_preference = pnc->distance; + nexthop->mrib_route_metric = pnc->metric; + nexthop->last_lookup = src->u.prefix4; + nexthop->last_lookup_time = pim_time_monotonic_usec(); + nexthop->nbr = nbr; + found = 1; + if (PIM_DEBUG_ZEBRA) { + char buf[INET_ADDRSTRLEN]; + char buf2[INET_ADDRSTRLEN]; + char buf3[INET_ADDRSTRLEN]; + pim_inet4_dump("", src->u.prefix4, buf2, + sizeof(buf2)); + pim_inet4_dump("", grp->u.prefix4, buf3, + sizeof(buf3)); + pim_inet4_dump( + "", + nexthop->mrib_nexthop_addr.u.prefix4, + buf, sizeof(buf)); + zlog_debug( + "%s: (%s, %s) selected nhop interface %s addr %s mod_val %u iter %d ecmp %d", + __PRETTY_FUNCTION__, buf2, buf3, + ifp->name, buf, mod_val, nh_iter, + qpim_ecmp_enable); + } + } + nh_iter++; + } + + if (found) + return 0; + else + return -1; } -/* This API is used to parse Registered address nexthop update coming from Zebra */ -int -pim_parse_nexthop_update (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +/* This API is used to parse Registered address nexthop update coming from Zebra + */ +int pim_parse_nexthop_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct prefix p; - struct nexthop *nexthop; - struct nexthop *nhlist_head = NULL; - struct nexthop *nhlist_tail = NULL; - uint32_t metric, distance; - u_char nexthop_num = 0; - int i; - struct pim_rpf rpf; - struct pim_nexthop_cache *pnc = NULL; - struct pim_neighbor *nbr = NULL; - struct interface *ifp = NULL; - struct interface *ifp1 = NULL; - struct pim_interface *pim_ifp = NULL; - char str[INET_ADDRSTRLEN]; - - s = zclient->ibuf; - memset (&p, 0, sizeof (struct prefix)); - p.family = stream_getw (s); - p.prefixlen = stream_getc (s); - switch (p.family) - { - case AF_INET: - p.u.prefix4.s_addr = stream_get_ipv4 (s); - break; - case AF_INET6: - stream_get (&p.u.prefix6, s, 16); - break; - default: - break; - } - - if (command == ZEBRA_NEXTHOP_UPDATE) - { - rpf.rpf_addr.family = p.family; - rpf.rpf_addr.prefixlen = p.prefixlen; - rpf.rpf_addr.u.prefix4.s_addr = p.u.prefix4.s_addr; - pnc = pim_nexthop_cache_find (&rpf); - if (!pnc) - { - if (PIM_DEBUG_TRACE) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str (&rpf.rpf_addr, buf, sizeof (buf)); - zlog_debug ("%s: Skipping NHT update, addr %s is not in local cached DB.", - __PRETTY_FUNCTION__, buf); - } - return 0; - } - } - else - { - /* - * We do not currently handle ZEBRA_IMPORT_CHECK_UPDATE - */ - return 0; - } - - pnc->last_update = pim_time_monotonic_usec (); - distance = stream_getc (s); - metric = stream_getl (s); - nexthop_num = stream_getc (s); - - if (nexthop_num) - { - pnc->nexthop_num = 0; //Only increment for pim enabled rpf. - - for (i = 0; i < nexthop_num; i++) - { - nexthop = nexthop_new (); - nexthop->type = stream_getc (s); - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); - nexthop->ifindex = stream_getl (s); - break; - case NEXTHOP_TYPE_IFINDEX: - nexthop->ifindex = stream_getl (s); - break; - case NEXTHOP_TYPE_IPV4_IFINDEX: - nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); - nexthop->ifindex = stream_getl (s); - break; - case NEXTHOP_TYPE_IPV6: - stream_get (&nexthop->gate.ipv6, s, 16); - break; - case NEXTHOP_TYPE_IPV6_IFINDEX: - stream_get (&nexthop->gate.ipv6, s, 16); - nexthop->ifindex = stream_getl (s); - ifp1 = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT); - nbr = pim_neighbor_find_if (ifp1); - /* Overwrite with Nbr address as NH addr */ - if (nbr) - { - nexthop->gate.ipv4 = nbr->source_addr; - if (PIM_DEBUG_TRACE) - { - pim_inet4_dump ("", nbr->source_addr, str, - sizeof (str)); - zlog_debug ("%s: NHT using pim nbr addr %s interface %s as rpf", - __PRETTY_FUNCTION__, str, ifp1->name); - } - } - else - { - if (PIM_DEBUG_TRACE) - { - pim_ifp = ifp1->info; - zlog_debug ("%s: NHT pim nbr not found on interface %s nbr count:%d ", - __PRETTY_FUNCTION__, ifp1->name, - pim_ifp->pim_neighbor_list->count); - } - //Mark nexthop address to 0 until PIM Nbr is resolved. - nexthop->gate.ipv4.s_addr = PIM_NET_INADDR_ANY; - } - - break; - default: - /* do nothing */ - break; - } - - if (PIM_DEBUG_TRACE) - { - char p_str[PREFIX2STR_BUFFER]; - prefix2str (&p, p_str, sizeof (p_str)); - zlog_debug ("%s: NHT addr %s %d-nhop via %s type %d distance:%u metric:%u ", - __PRETTY_FUNCTION__, p_str, i + 1, - inet_ntoa (nexthop->gate.ipv4), nexthop->type, distance, - metric); - } - - ifp = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT); - if (!ifp) - { - if (PIM_DEBUG_ZEBRA) - { - char buf[NEXTHOP_STRLEN]; - zlog_debug ("%s: could not find interface for ifindex %d (addr %s)", - __PRETTY_FUNCTION__, nexthop->ifindex, - nexthop2str (nexthop, buf, sizeof (buf))); - } - nexthop_free (nexthop); - continue; - } - - if (!ifp->info) - { - if (PIM_DEBUG_ZEBRA) - { - char buf[NEXTHOP_STRLEN]; - zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, addr %s)", - __PRETTY_FUNCTION__, ifp->name, nexthop->ifindex, - nexthop2str (nexthop, buf, sizeof (buf))); - } - nexthop_free (nexthop); - continue; - } - - if (nhlist_tail) - { - nhlist_tail->next = nexthop; - nhlist_tail = nexthop; - } - else - { - nhlist_tail = nexthop; - nhlist_head = nexthop; - } - //Only keep track of nexthops which are PIM enabled. - pnc->nexthop_num++; - } - /* Reset existing pnc->nexthop before assigning new list */ - nexthops_free (pnc->nexthop); - pnc->nexthop = nhlist_head; - if (pnc->nexthop_num) - { - pnc->flags |= PIM_NEXTHOP_VALID; - pnc->distance = distance; - pnc->metric = metric; - } - } - else - { - pnc->flags &= ~PIM_NEXTHOP_VALID; - pnc->nexthop_num = nexthop_num; - nexthops_free (pnc->nexthop); - pnc->nexthop = NULL; - } - - if (PIM_DEBUG_TRACE) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str (&p, buf, sizeof (buf)); - zlog_debug ("%s: NHT Update for %s num_nh %d num_pim_nh %d vrf:%d up %d rp %d", - __PRETTY_FUNCTION__, buf, nexthop_num, pnc->nexthop_num, vrf_id, - listcount (pnc->upstream_list), listcount (pnc->rp_list)); - } - - pim_rpf_set_refresh_time (); - - if (listcount (pnc->rp_list)) - pim_update_rp_nh (pnc); - if (listcount (pnc->upstream_list)) - pim_update_upstream_nh (pnc); - - return 0; + struct stream *s; + struct prefix p; + struct nexthop *nexthop; + struct nexthop *nhlist_head = NULL; + struct nexthop *nhlist_tail = NULL; + uint32_t metric, distance; + u_char nexthop_num = 0; + int i; + struct pim_rpf rpf; + struct pim_nexthop_cache *pnc = NULL; + struct pim_neighbor *nbr = NULL; + struct interface *ifp = NULL; + struct interface *ifp1 = NULL; + struct pim_interface *pim_ifp = NULL; + char str[INET_ADDRSTRLEN]; + + s = zclient->ibuf; + memset(&p, 0, sizeof(struct prefix)); + p.family = stream_getw(s); + p.prefixlen = stream_getc(s); + switch (p.family) { + case AF_INET: + p.u.prefix4.s_addr = stream_get_ipv4(s); + break; + case AF_INET6: + stream_get(&p.u.prefix6, s, 16); + break; + default: + break; + } + + if (command == ZEBRA_NEXTHOP_UPDATE) { + rpf.rpf_addr.family = p.family; + rpf.rpf_addr.prefixlen = p.prefixlen; + rpf.rpf_addr.u.prefix4.s_addr = p.u.prefix4.s_addr; + pnc = pim_nexthop_cache_find(&rpf); + if (!pnc) { + if (PIM_DEBUG_TRACE) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&rpf.rpf_addr, buf, sizeof(buf)); + zlog_debug( + "%s: Skipping NHT update, addr %s is not in local cached DB.", + __PRETTY_FUNCTION__, buf); + } + return 0; + } + } else { + /* + * We do not currently handle ZEBRA_IMPORT_CHECK_UPDATE + */ + return 0; + } + + pnc->last_update = pim_time_monotonic_usec(); + distance = stream_getc(s); + metric = stream_getl(s); + nexthop_num = stream_getc(s); + + if (nexthop_num) { + pnc->nexthop_num = 0; // Only increment for pim enabled rpf. + + for (i = 0; i < nexthop_num; i++) { + nexthop = nexthop_new(); + nexthop->type = stream_getc(s); + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + nexthop->gate.ipv4.s_addr = stream_get_ipv4(s); + nexthop->ifindex = stream_getl(s); + break; + case NEXTHOP_TYPE_IFINDEX: + nexthop->ifindex = stream_getl(s); + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + nexthop->gate.ipv4.s_addr = stream_get_ipv4(s); + nexthop->ifindex = stream_getl(s); + break; + case NEXTHOP_TYPE_IPV6: + stream_get(&nexthop->gate.ipv6, s, 16); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + stream_get(&nexthop->gate.ipv6, s, 16); + nexthop->ifindex = stream_getl(s); + ifp1 = if_lookup_by_index(nexthop->ifindex, + VRF_DEFAULT); + nbr = pim_neighbor_find_if(ifp1); + /* Overwrite with Nbr address as NH addr */ + if (nbr) { + nexthop->gate.ipv4 = nbr->source_addr; + if (PIM_DEBUG_TRACE) { + pim_inet4_dump("", + nbr->source_addr, + str, + sizeof(str)); + zlog_debug( + "%s: NHT using pim nbr addr %s interface %s as rpf", + __PRETTY_FUNCTION__, + str, ifp1->name); + } + } else { + if (PIM_DEBUG_TRACE) { + pim_ifp = ifp1->info; + zlog_debug( + "%s: NHT pim nbr not found on interface %s nbr count:%d ", + __PRETTY_FUNCTION__, + ifp1->name, + pim_ifp->pim_neighbor_list + ->count); + } + // Mark nexthop address to 0 until PIM + // Nbr is resolved. + nexthop->gate.ipv4.s_addr = + PIM_NET_INADDR_ANY; + } + + break; + default: + /* do nothing */ + break; + } + + if (PIM_DEBUG_TRACE) { + char p_str[PREFIX2STR_BUFFER]; + prefix2str(&p, p_str, sizeof(p_str)); + zlog_debug( + "%s: NHT addr %s %d-nhop via %s type %d distance:%u metric:%u ", + __PRETTY_FUNCTION__, p_str, i + 1, + inet_ntoa(nexthop->gate.ipv4), + nexthop->type, distance, metric); + } + + ifp = if_lookup_by_index(nexthop->ifindex, VRF_DEFAULT); + if (!ifp) { + if (PIM_DEBUG_ZEBRA) { + char buf[NEXTHOP_STRLEN]; + zlog_debug( + "%s: could not find interface for ifindex %d (addr %s)", + __PRETTY_FUNCTION__, + nexthop->ifindex, + nexthop2str(nexthop, buf, + sizeof(buf))); + } + nexthop_free(nexthop); + continue; + } + + if (!ifp->info) { + if (PIM_DEBUG_ZEBRA) { + char buf[NEXTHOP_STRLEN]; + zlog_debug( + "%s: multicast not enabled on input interface %s (ifindex=%d, addr %s)", + __PRETTY_FUNCTION__, ifp->name, + nexthop->ifindex, + nexthop2str(nexthop, buf, + sizeof(buf))); + } + nexthop_free(nexthop); + continue; + } + + if (nhlist_tail) { + nhlist_tail->next = nexthop; + nhlist_tail = nexthop; + } else { + nhlist_tail = nexthop; + nhlist_head = nexthop; + } + // Only keep track of nexthops which are PIM enabled. + pnc->nexthop_num++; + } + /* Reset existing pnc->nexthop before assigning new list */ + nexthops_free(pnc->nexthop); + pnc->nexthop = nhlist_head; + if (pnc->nexthop_num) { + pnc->flags |= PIM_NEXTHOP_VALID; + pnc->distance = distance; + pnc->metric = metric; + } + } else { + pnc->flags &= ~PIM_NEXTHOP_VALID; + pnc->nexthop_num = nexthop_num; + nexthops_free(pnc->nexthop); + pnc->nexthop = NULL; + } + + if (PIM_DEBUG_TRACE) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&p, buf, sizeof(buf)); + zlog_debug( + "%s: NHT Update for %s num_nh %d num_pim_nh %d vrf:%d up %d rp %d", + __PRETTY_FUNCTION__, buf, nexthop_num, pnc->nexthop_num, + vrf_id, listcount(pnc->upstream_list), + listcount(pnc->rp_list)); + } + + pim_rpf_set_refresh_time(); + + if (listcount(pnc->rp_list)) + pim_update_rp_nh(pnc); + if (listcount(pnc->upstream_list)) + pim_update_upstream_nh(pnc); + + return 0; } -int -pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr, - struct prefix *src, struct prefix *grp, - int neighbor_needed) +int pim_ecmp_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, + struct prefix *src, struct prefix *grp, + int neighbor_needed) { - struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; - struct pim_neighbor *nbr = NULL; - int num_ifindex; - struct interface *ifp; - int first_ifindex; - int found = 0; - uint8_t i = 0; - uint32_t hash_val = 0, mod_val = 0; - - if (PIM_DEBUG_TRACE) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("", addr, addr_str, sizeof (addr_str)); - zlog_debug ("%s: Looking up: %s, last lookup time: %lld", - __PRETTY_FUNCTION__, addr_str, nexthop->last_lookup_time); - } - - memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM); - num_ifindex = zclient_lookup_nexthop (nexthop_tab, MULTIPATH_NUM, addr, - PIM_NEXTHOP_LOOKUP_MAX); - if (num_ifindex < 1) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("", addr, addr_str, sizeof (addr_str)); - zlog_warn ("%s %s: could not find nexthop ifindex for address %s", - __FILE__, __PRETTY_FUNCTION__, addr_str); - return -1; - } - - //If PIM ECMP enable then choose ECMP path. - if (qpim_ecmp_enable) - { - hash_val = pim_compute_ecmp_hash (src, grp); - mod_val = hash_val % num_ifindex; - if (PIM_DEBUG_PIM_TRACE_DETAIL) - zlog_debug ("%s: hash_val %u mod_val %u", - __PRETTY_FUNCTION__, hash_val, mod_val); - } - - while (!found && (i < num_ifindex)) - { - first_ifindex = nexthop_tab[i].ifindex; - - ifp = if_lookup_by_index (first_ifindex, VRF_DEFAULT); - if (!ifp) - { - if (PIM_DEBUG_ZEBRA) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("", addr, addr_str, sizeof (addr_str)); - zlog_debug ("%s %s: could not find interface for ifindex %d (address %s)", - __FILE__, __PRETTY_FUNCTION__, first_ifindex, addr_str); - } - if (i == mod_val) - mod_val++; - i++; - continue; - } - - if (!ifp->info) - { - if (PIM_DEBUG_ZEBRA) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("", addr, addr_str, sizeof (addr_str)); - zlog_debug ("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", - __PRETTY_FUNCTION__, ifp->name, first_ifindex, addr_str); - } - if (i == mod_val) - mod_val++; - i++; - continue; - } - if (neighbor_needed && !pim_if_connected_to_source (ifp, addr)) - { - nbr = pim_neighbor_find (ifp, nexthop_tab[i].nexthop_addr.u.prefix4); - if (PIM_DEBUG_PIM_TRACE_DETAIL) - zlog_debug ("ifp name: %s, pim nbr: %p", ifp->name, nbr); - if (!nbr && !if_is_loopback (ifp)) - { - if (i == mod_val) - mod_val++; - i++; - if (PIM_DEBUG_ZEBRA) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("", addr, addr_str, - sizeof (addr_str)); - zlog_debug ("%s: NBR not found on input interface %s (RPF for source %s)", - __PRETTY_FUNCTION__, ifp->name, addr_str); - } - continue; - } - } - - if (i == mod_val) - { - if (PIM_DEBUG_ZEBRA) - { - char nexthop_str[PREFIX_STRLEN]; - char addr_str[INET_ADDRSTRLEN]; - pim_addr_dump ("", &nexthop_tab[i].nexthop_addr, - nexthop_str, sizeof (nexthop_str)); - pim_inet4_dump ("", addr, addr_str, sizeof (addr_str)); - zlog_debug ("%s %s: found nhop %s for addr %s interface %s metric %d dist %d", - __FILE__, __PRETTY_FUNCTION__, nexthop_str, addr_str, - ifp->name, nexthop_tab[i].route_metric, - nexthop_tab[i].protocol_distance); - } - /* update nextop data */ - nexthop->interface = ifp; - nexthop->mrib_nexthop_addr = nexthop_tab[i].nexthop_addr; - nexthop->mrib_metric_preference = nexthop_tab[i].protocol_distance; - nexthop->mrib_route_metric = nexthop_tab[i].route_metric; - nexthop->last_lookup = addr; - nexthop->last_lookup_time = pim_time_monotonic_usec(); - nexthop->nbr = nbr; - found = 1; - } - i++; - } - if (found) - return 0; - else - return -1; + struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; + struct pim_neighbor *nbr = NULL; + int num_ifindex; + struct interface *ifp; + int first_ifindex; + int found = 0; + uint8_t i = 0; + uint32_t hash_val = 0, mod_val = 0; + + if (PIM_DEBUG_TRACE) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_debug("%s: Looking up: %s, last lookup time: %lld", + __PRETTY_FUNCTION__, addr_str, + nexthop->last_lookup_time); + } + + memset(nexthop_tab, 0, + sizeof(struct pim_zlookup_nexthop) * MULTIPATH_NUM); + num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, addr, + PIM_NEXTHOP_LOOKUP_MAX); + if (num_ifindex < 1) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_warn( + "%s %s: could not find nexthop ifindex for address %s", + __FILE__, __PRETTY_FUNCTION__, addr_str); + return -1; + } + + // If PIM ECMP enable then choose ECMP path. + if (qpim_ecmp_enable) { + hash_val = pim_compute_ecmp_hash(src, grp); + mod_val = hash_val % num_ifindex; + if (PIM_DEBUG_PIM_TRACE_DETAIL) + zlog_debug("%s: hash_val %u mod_val %u", + __PRETTY_FUNCTION__, hash_val, mod_val); + } + + while (!found && (i < num_ifindex)) { + first_ifindex = nexthop_tab[i].ifindex; + + ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); + if (!ifp) { + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s %s: could not find interface for ifindex %d (address %s)", + __FILE__, __PRETTY_FUNCTION__, + first_ifindex, addr_str); + } + if (i == mod_val) + mod_val++; + i++; + continue; + } + + if (!ifp->info) { + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", + __PRETTY_FUNCTION__, ifp->name, + first_ifindex, addr_str); + } + if (i == mod_val) + mod_val++; + i++; + continue; + } + if (neighbor_needed && !pim_if_connected_to_source(ifp, addr)) { + nbr = pim_neighbor_find( + ifp, nexthop_tab[i].nexthop_addr.u.prefix4); + if (PIM_DEBUG_PIM_TRACE_DETAIL) + zlog_debug("ifp name: %s, pim nbr: %p", + ifp->name, nbr); + if (!nbr && !if_is_loopback(ifp)) { + if (i == mod_val) + mod_val++; + i++; + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, + addr_str, + sizeof(addr_str)); + zlog_debug( + "%s: NBR not found on input interface %s (RPF for source %s)", + __PRETTY_FUNCTION__, ifp->name, + addr_str); + } + continue; + } + } + + if (i == mod_val) { + if (PIM_DEBUG_ZEBRA) { + char nexthop_str[PREFIX_STRLEN]; + char addr_str[INET_ADDRSTRLEN]; + pim_addr_dump("", + &nexthop_tab[i].nexthop_addr, + nexthop_str, sizeof(nexthop_str)); + pim_inet4_dump("", addr, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s %s: found nhop %s for addr %s interface %s metric %d dist %d", + __FILE__, __PRETTY_FUNCTION__, + nexthop_str, addr_str, ifp->name, + nexthop_tab[i].route_metric, + nexthop_tab[i].protocol_distance); + } + /* update nextop data */ + nexthop->interface = ifp; + nexthop->mrib_nexthop_addr = + nexthop_tab[i].nexthop_addr; + nexthop->mrib_metric_preference = + nexthop_tab[i].protocol_distance; + nexthop->mrib_route_metric = + nexthop_tab[i].route_metric; + nexthop->last_lookup = addr; + nexthop->last_lookup_time = pim_time_monotonic_usec(); + nexthop->nbr = nbr; + found = 1; + } + i++; + } + if (found) + return 0; + else + return -1; } -int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr, - struct prefix *src, struct prefix *grp) +int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr, struct prefix *src, + struct prefix *grp) { - struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; - int num_ifindex; - int vif_index; - ifindex_t first_ifindex; - uint32_t hash_val = 0, mod_val = 0; - - memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM); - num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, addr, - PIM_NEXTHOP_LOOKUP_MAX); - if (num_ifindex < 1) - { - if (PIM_DEBUG_ZEBRA) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s %s: could not find nexthop ifindex for address %s", - __FILE__, __PRETTY_FUNCTION__, - addr_str); - } - return -1; - } - - //If PIM ECMP enable then choose ECMP path. - if (qpim_ecmp_enable) - { - hash_val = pim_compute_ecmp_hash (src, grp); - mod_val = hash_val % num_ifindex; - if (PIM_DEBUG_PIM_TRACE_DETAIL) - zlog_debug ("%s: hash_val %u mod_val %u", - __PRETTY_FUNCTION__, hash_val, mod_val); - } - - first_ifindex = nexthop_tab[mod_val].ifindex; - - if (PIM_DEBUG_ZEBRA) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s %s: found nexthop ifindex=%d (interface %s) for address %s", - __FILE__, __PRETTY_FUNCTION__, - first_ifindex, ifindex2ifname(first_ifindex, VRF_DEFAULT), addr_str); - } - - vif_index = pim_if_find_vifindex_by_ifindex(first_ifindex); - - if (vif_index < 0) - { - if (PIM_DEBUG_ZEBRA) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s %s: low vif_index=%d < 1 nexthop for address %s", - __FILE__, __PRETTY_FUNCTION__, - vif_index, addr_str); - } - return -2; - } - - return vif_index; + struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; + int num_ifindex; + int vif_index; + ifindex_t first_ifindex; + uint32_t hash_val = 0, mod_val = 0; + + memset(nexthop_tab, 0, + sizeof(struct pim_zlookup_nexthop) * MULTIPATH_NUM); + num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, addr, + PIM_NEXTHOP_LOOKUP_MAX); + if (num_ifindex < 1) { + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s %s: could not find nexthop ifindex for address %s", + __FILE__, __PRETTY_FUNCTION__, addr_str); + } + return -1; + } + + // If PIM ECMP enable then choose ECMP path. + if (qpim_ecmp_enable) { + hash_val = pim_compute_ecmp_hash(src, grp); + mod_val = hash_val % num_ifindex; + if (PIM_DEBUG_PIM_TRACE_DETAIL) + zlog_debug("%s: hash_val %u mod_val %u", + __PRETTY_FUNCTION__, hash_val, mod_val); + } + + first_ifindex = nexthop_tab[mod_val].ifindex; + + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_debug( + "%s %s: found nexthop ifindex=%d (interface %s) for address %s", + __FILE__, __PRETTY_FUNCTION__, first_ifindex, + ifindex2ifname(first_ifindex, VRF_DEFAULT), addr_str); + } + + vif_index = pim_if_find_vifindex_by_ifindex(first_ifindex); + + if (vif_index < 0) { + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s %s: low vif_index=%d < 1 nexthop for address %s", + __FILE__, __PRETTY_FUNCTION__, vif_index, + addr_str); + } + return -2; + } + + return vif_index; } diff --git a/pimd/pim_nht.h b/pimd/pim_nht.h index 6bd224992..fb8d83623 100644 --- a/pimd/pim_nht.h +++ b/pimd/pim_nht.h @@ -30,42 +30,42 @@ #include "pim_rpf.h" /* PIM nexthop cache value structure. */ -struct pim_nexthop_cache -{ - struct pim_rpf rpf; - /* IGP route's metric. */ - u_int32_t metric; - uint32_t distance; - /* Nexthop number and nexthop linked list. */ - u_char nexthop_num; - struct nexthop *nexthop; - int64_t last_update; - u_int16_t flags; +struct pim_nexthop_cache { + struct pim_rpf rpf; + /* IGP route's metric. */ + u_int32_t metric; + uint32_t distance; + /* Nexthop number and nexthop linked list. */ + u_char nexthop_num; + struct nexthop *nexthop; + int64_t last_update; + u_int16_t flags; #define PIM_NEXTHOP_VALID (1 << 0) - struct list *rp_list; - struct list *upstream_list; + struct list *rp_list; + struct list *upstream_list; }; -int pim_parse_nexthop_update (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id); -int pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up, - struct rp_info *rp, struct pim_nexthop_cache *out_pnc); -void pim_delete_tracked_nexthop (struct prefix *addr, struct pim_upstream *up, - struct rp_info *rp); -struct pim_nexthop_cache *pim_nexthop_cache_add (struct pim_rpf *rpf_addr); -struct pim_nexthop_cache *pim_nexthop_cache_find (struct pim_rpf *rpf); -uint32_t pim_compute_ecmp_hash (struct prefix *src, struct prefix *grp); -int pim_ecmp_nexthop_search (struct pim_nexthop_cache * pnc, - struct pim_nexthop *nexthop, struct prefix *src, - struct prefix *grp, int neighbor_needed); -int pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr, - struct prefix *src, struct prefix *grp, - int neighbor_needed); -void pim_sendmsg_zebra_rnh (struct zclient *zclient, struct pim_nexthop_cache *pnc, - int command); -int pim_update_rp_nh (struct pim_nexthop_cache *pnc); -void pim_resolve_upstream_nh (struct prefix *nht_p); -int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr, - struct prefix *src, struct prefix *grp); +int pim_parse_nexthop_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id); +int pim_find_or_track_nexthop(struct prefix *addr, struct pim_upstream *up, + struct rp_info *rp, + struct pim_nexthop_cache *out_pnc); +void pim_delete_tracked_nexthop(struct prefix *addr, struct pim_upstream *up, + struct rp_info *rp); +struct pim_nexthop_cache *pim_nexthop_cache_add(struct pim_rpf *rpf_addr); +struct pim_nexthop_cache *pim_nexthop_cache_find(struct pim_rpf *rpf); +uint32_t pim_compute_ecmp_hash(struct prefix *src, struct prefix *grp); +int pim_ecmp_nexthop_search(struct pim_nexthop_cache *pnc, + struct pim_nexthop *nexthop, struct prefix *src, + struct prefix *grp, int neighbor_needed); +int pim_ecmp_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, + struct prefix *src, struct prefix *grp, + int neighbor_needed); +void pim_sendmsg_zebra_rnh(struct zclient *zclient, + struct pim_nexthop_cache *pnc, int command); +int pim_update_rp_nh(struct pim_nexthop_cache *pnc); +void pim_resolve_upstream_nh(struct prefix *nht_p); +int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr, struct prefix *src, + struct prefix *grp); #endif diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 66be2be6f..aeef0ff4e 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -35,435 +35,477 @@ struct list *pim_channel_oil_list = NULL; struct hash *pim_channel_oil_hash = NULL; -char * -pim_channel_oil_dump (struct channel_oil *c_oil, char *buf, size_t size) +char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size) { - struct prefix_sg sg; - int i; - - memset (buf, 0, size); - sg.src = c_oil->oil.mfcc_origin; - sg.grp = c_oil->oil.mfcc_mcastgrp; - sprintf(buf, "%s IIF: %d, OIFS: ", - pim_str_sg_dump (&sg), c_oil->oil.mfcc_parent); - - for (i = 0 ; i < MAXVIFS ; i++) - { - if (c_oil->oil.mfcc_ttls[i] != 0) - { - char buf1[10]; - sprintf(buf1, "%d ", i); - strcat(buf, buf1); - } - } - - return buf; + struct prefix_sg sg; + int i; + + memset(buf, 0, size); + sg.src = c_oil->oil.mfcc_origin; + sg.grp = c_oil->oil.mfcc_mcastgrp; + sprintf(buf, "%s IIF: %d, OIFS: ", pim_str_sg_dump(&sg), + c_oil->oil.mfcc_parent); + + for (i = 0; i < MAXVIFS; i++) { + if (c_oil->oil.mfcc_ttls[i] != 0) { + char buf1[10]; + sprintf(buf1, "%d ", i); + strcat(buf, buf1); + } + } + + return buf; } -static int -pim_channel_oil_compare (struct channel_oil *c1, struct channel_oil *c2) +static int pim_channel_oil_compare(struct channel_oil *c1, + struct channel_oil *c2) { - if (ntohl(c1->oil.mfcc_mcastgrp.s_addr) < ntohl(c2->oil.mfcc_mcastgrp.s_addr)) - return -1; + if (ntohl(c1->oil.mfcc_mcastgrp.s_addr) + < ntohl(c2->oil.mfcc_mcastgrp.s_addr)) + return -1; - if (ntohl(c1->oil.mfcc_mcastgrp.s_addr) > ntohl(c2->oil.mfcc_mcastgrp.s_addr)) - return 1; + if (ntohl(c1->oil.mfcc_mcastgrp.s_addr) + > ntohl(c2->oil.mfcc_mcastgrp.s_addr)) + return 1; - if (ntohl(c1->oil.mfcc_origin.s_addr) < ntohl(c2->oil.mfcc_origin.s_addr)) - return -1; + if (ntohl(c1->oil.mfcc_origin.s_addr) + < ntohl(c2->oil.mfcc_origin.s_addr)) + return -1; - if (ntohl(c1->oil.mfcc_origin.s_addr) > ntohl(c2->oil.mfcc_origin.s_addr)) - return 1; + if (ntohl(c1->oil.mfcc_origin.s_addr) + > ntohl(c2->oil.mfcc_origin.s_addr)) + return 1; - return 0; + return 0; } -static int -pim_oil_equal (const void *arg1, const void *arg2) +static int pim_oil_equal(const void *arg1, const void *arg2) { - const struct channel_oil *c1 = (const struct channel_oil *)arg1; - const struct channel_oil *c2 = (const struct channel_oil *)arg2; + const struct channel_oil *c1 = (const struct channel_oil *)arg1; + const struct channel_oil *c2 = (const struct channel_oil *)arg2; - if ((c1->oil.mfcc_mcastgrp.s_addr == c2->oil.mfcc_mcastgrp.s_addr) && - (c1->oil.mfcc_origin.s_addr == c2->oil.mfcc_origin.s_addr)) - return 1; + if ((c1->oil.mfcc_mcastgrp.s_addr == c2->oil.mfcc_mcastgrp.s_addr) + && (c1->oil.mfcc_origin.s_addr == c2->oil.mfcc_origin.s_addr)) + return 1; - return 0; + return 0; } -static unsigned int -pim_oil_hash_key (void *arg) +static unsigned int pim_oil_hash_key(void *arg) { - struct channel_oil *oil = (struct channel_oil *)arg; + struct channel_oil *oil = (struct channel_oil *)arg; - return jhash_2words (oil->oil.mfcc_mcastgrp.s_addr, oil->oil.mfcc_origin.s_addr, 0); + return jhash_2words(oil->oil.mfcc_mcastgrp.s_addr, + oil->oil.mfcc_origin.s_addr, 0); } -void -pim_oil_init (void) +void pim_oil_init(void) { - pim_channel_oil_hash = hash_create_size (8192, pim_oil_hash_key, - pim_oil_equal, NULL); - - pim_channel_oil_list = list_new(); - if (!pim_channel_oil_list) { - zlog_err("%s %s: failure: channel_oil_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return; - } - pim_channel_oil_list->del = (void (*)(void *)) pim_channel_oil_free; - pim_channel_oil_list->cmp = (int (*)(void *, void *)) pim_channel_oil_compare; + pim_channel_oil_hash = + hash_create_size(8192, pim_oil_hash_key, pim_oil_equal, NULL); + + pim_channel_oil_list = list_new(); + if (!pim_channel_oil_list) { + zlog_err("%s %s: failure: channel_oil_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return; + } + pim_channel_oil_list->del = (void (*)(void *))pim_channel_oil_free; + pim_channel_oil_list->cmp = + (int (*)(void *, void *))pim_channel_oil_compare; } -void -pim_oil_terminate (void) +void pim_oil_terminate(void) { - if (pim_channel_oil_list) - list_free(pim_channel_oil_list); - pim_channel_oil_list = NULL; + if (pim_channel_oil_list) + list_free(pim_channel_oil_list); + pim_channel_oil_list = NULL; - if (pim_channel_oil_hash) - hash_free (pim_channel_oil_hash); - pim_channel_oil_hash = NULL; + if (pim_channel_oil_hash) + hash_free(pim_channel_oil_hash); + pim_channel_oil_hash = NULL; } void pim_channel_oil_free(struct channel_oil *c_oil) { - XFREE(MTYPE_PIM_CHANNEL_OIL, c_oil); + XFREE(MTYPE_PIM_CHANNEL_OIL, c_oil); } -static struct channel_oil * -pim_find_channel_oil(struct prefix_sg *sg) +static struct channel_oil *pim_find_channel_oil(struct prefix_sg *sg) { - struct channel_oil *c_oil = NULL; - struct channel_oil lookup; + struct channel_oil *c_oil = NULL; + struct channel_oil lookup; - lookup.oil.mfcc_mcastgrp = sg->grp; - lookup.oil.mfcc_origin = sg->src; + lookup.oil.mfcc_mcastgrp = sg->grp; + lookup.oil.mfcc_origin = sg->src; - c_oil = hash_lookup (pim_channel_oil_hash, &lookup); + c_oil = hash_lookup(pim_channel_oil_hash, &lookup); - return c_oil; + return c_oil; } struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg, int input_vif_index) { - struct channel_oil *c_oil; - struct interface *ifp; - - c_oil = pim_find_channel_oil(sg); - if (c_oil) { - if (c_oil->oil.mfcc_parent != input_vif_index) - { - c_oil->oil_inherited_rescan = 1; - if (PIM_DEBUG_MROUTE) - zlog_debug ("%s: Existing channel oil %s points to %d, modifying to point at %d", - __PRETTY_FUNCTION__, pim_str_sg_dump(sg), c_oil->oil.mfcc_parent, input_vif_index); - } - c_oil->oil.mfcc_parent = input_vif_index; - ++c_oil->oil_ref_count; - c_oil->up = pim_upstream_find(sg); //channel might be present prior to upstream - return c_oil; - } - - ifp = pim_if_find_by_vif_index(input_vif_index); - if (!ifp) { - /* warning only */ - zlog_warn("%s: (S,G)=%s could not find input interface for input_vif_index=%d", - __PRETTY_FUNCTION__, - pim_str_sg_dump (sg), input_vif_index); - } - - c_oil = XCALLOC(MTYPE_PIM_CHANNEL_OIL, sizeof(*c_oil)); - if (!c_oil) { - zlog_err("PIM XCALLOC(%zu) failure", sizeof(*c_oil)); - return NULL; - } - - c_oil->oil.mfcc_mcastgrp = sg->grp; - c_oil->oil.mfcc_origin = sg->src; - c_oil = hash_get (pim_channel_oil_hash, c_oil, hash_alloc_intern); - - c_oil->oil.mfcc_parent = input_vif_index; - c_oil->oil_ref_count = 1; - c_oil->installed = 0; - c_oil->up = pim_upstream_find(sg); - - listnode_add_sort(pim_channel_oil_list, c_oil); - - return c_oil; + struct channel_oil *c_oil; + struct interface *ifp; + + c_oil = pim_find_channel_oil(sg); + if (c_oil) { + if (c_oil->oil.mfcc_parent != input_vif_index) { + c_oil->oil_inherited_rescan = 1; + if (PIM_DEBUG_MROUTE) + zlog_debug( + "%s: Existing channel oil %s points to %d, modifying to point at %d", + __PRETTY_FUNCTION__, + pim_str_sg_dump(sg), + c_oil->oil.mfcc_parent, + input_vif_index); + } + c_oil->oil.mfcc_parent = input_vif_index; + ++c_oil->oil_ref_count; + c_oil->up = pim_upstream_find( + sg); // channel might be present prior to upstream + return c_oil; + } + + ifp = pim_if_find_by_vif_index(input_vif_index); + if (!ifp) { + /* warning only */ + zlog_warn( + "%s: (S,G)=%s could not find input interface for input_vif_index=%d", + __PRETTY_FUNCTION__, pim_str_sg_dump(sg), + input_vif_index); + } + + c_oil = XCALLOC(MTYPE_PIM_CHANNEL_OIL, sizeof(*c_oil)); + if (!c_oil) { + zlog_err("PIM XCALLOC(%zu) failure", sizeof(*c_oil)); + return NULL; + } + + c_oil->oil.mfcc_mcastgrp = sg->grp; + c_oil->oil.mfcc_origin = sg->src; + c_oil = hash_get(pim_channel_oil_hash, c_oil, hash_alloc_intern); + + c_oil->oil.mfcc_parent = input_vif_index; + c_oil->oil_ref_count = 1; + c_oil->installed = 0; + c_oil->up = pim_upstream_find(sg); + + listnode_add_sort(pim_channel_oil_list, c_oil); + + return c_oil; } void pim_channel_oil_del(struct channel_oil *c_oil) { - --c_oil->oil_ref_count; - - if (c_oil->oil_ref_count < 1) { - /* - * notice that listnode_delete() can't be moved - * into pim_channel_oil_free() because the later is - * called by list_delete_all_node() - */ - c_oil->up = NULL; - listnode_delete(pim_channel_oil_list, c_oil); - hash_release (pim_channel_oil_hash, c_oil); - - pim_channel_oil_free(c_oil); - } + --c_oil->oil_ref_count; + + if (c_oil->oil_ref_count < 1) { + /* + * notice that listnode_delete() can't be moved + * into pim_channel_oil_free() because the later is + * called by list_delete_all_node() + */ + c_oil->up = NULL; + listnode_delete(pim_channel_oil_list, c_oil); + hash_release(pim_channel_oil_hash, c_oil); + + pim_channel_oil_free(c_oil); + } } -int -pim_channel_del_oif (struct channel_oil *channel_oil, - struct interface *oif, - uint32_t proto_mask) +int pim_channel_del_oif(struct channel_oil *channel_oil, struct interface *oif, + uint32_t proto_mask) { - struct pim_interface *pim_ifp; - - zassert (channel_oil); - zassert (oif); - - pim_ifp = oif->info; - - /* - * Don't do anything if we've been asked to remove a source - * that is not actually on it. - */ - if (!(channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask)) - { - if (PIM_DEBUG_MROUTE) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: no existing protocol mask %u(%u) for requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - proto_mask, channel_oil->oif_flags[pim_ifp->mroute_vif_index], - oif->name, pim_ifp->mroute_vif_index, - channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index], - source_str, group_str); + struct pim_interface *pim_ifp; + + zassert(channel_oil); + zassert(oif); + + pim_ifp = oif->info; + + /* + * Don't do anything if we've been asked to remove a source + * that is not actually on it. + */ + if (!(channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask)) { + if (PIM_DEBUG_MROUTE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", + channel_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("", + channel_oil->oil.mfcc_origin, source_str, + sizeof(source_str)); + zlog_debug( + "%s %s: no existing protocol mask %u(%u) for requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, proto_mask, + channel_oil + ->oif_flags[pim_ifp->mroute_vif_index], + oif->name, pim_ifp->mroute_vif_index, + channel_oil->oil + .mfcc_ttls[pim_ifp->mroute_vif_index], + source_str, group_str); + } + return 0; + } + + channel_oil->oif_flags[pim_ifp->mroute_vif_index] &= ~proto_mask; + + if (channel_oil->oif_flags[pim_ifp->mroute_vif_index]) { + if (PIM_DEBUG_MROUTE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", + channel_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("", + channel_oil->oil.mfcc_origin, source_str, + sizeof(source_str)); + zlog_debug( + "%s %s: other protocol masks remain for requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, oif->name, + pim_ifp->mroute_vif_index, + channel_oil->oil + .mfcc_ttls[pim_ifp->mroute_vif_index], + source_str, group_str); + } + return 0; + } + + channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = 0; + + if (pim_mroute_add(channel_oil, __PRETTY_FUNCTION__)) { + if (PIM_DEBUG_MROUTE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", + channel_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("", + channel_oil->oil.mfcc_origin, source_str, + sizeof(source_str)); + zlog_debug( + "%s %s: could not remove output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, oif->name, + pim_ifp->mroute_vif_index, source_str, + group_str); + } + return -1; } - return 0; - } - - channel_oil->oif_flags[pim_ifp->mroute_vif_index] &= ~proto_mask; - - if (channel_oil->oif_flags[pim_ifp->mroute_vif_index]) - { - if (PIM_DEBUG_MROUTE) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: other protocol masks remain for requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - oif->name, pim_ifp->mroute_vif_index, - channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index], - source_str, group_str); + + --channel_oil->oil_size; + + if (PIM_DEBUG_MROUTE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", channel_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("", channel_oil->oil.mfcc_origin, + source_str, sizeof(source_str)); + zlog_debug( + "%s %s: (S,G)=(%s,%s): proto_mask=%u IIF:%d OIF=%s vif_index=%d", + __FILE__, __PRETTY_FUNCTION__, source_str, group_str, + proto_mask, channel_oil->oil.mfcc_parent, oif->name, + pim_ifp->mroute_vif_index); } - return 0; - } - - channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = 0; - - if (pim_mroute_add (channel_oil, __PRETTY_FUNCTION__)) { - if (PIM_DEBUG_MROUTE) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: could not remove output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - oif->name, pim_ifp->mroute_vif_index, - source_str, group_str); - } - return -1; - } - - --channel_oil->oil_size; - - if (PIM_DEBUG_MROUTE) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u IIF:%d OIF=%s vif_index=%d", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str, - proto_mask, channel_oil->oil.mfcc_parent ,oif->name, pim_ifp->mroute_vif_index); - } - - return 0; + + return 0; } -int pim_channel_add_oif(struct channel_oil *channel_oil, - struct interface *oif, - uint32_t proto_mask) +int pim_channel_add_oif(struct channel_oil *channel_oil, struct interface *oif, + uint32_t proto_mask) { - struct pim_interface *pim_ifp; - int old_ttl; - - /* - * If we've gotten here we've gone bad, but let's - * not take down pim - */ - if (!channel_oil) - { - zlog_warn ("Attempt to Add OIF for non-existent channel oil"); - return -1; - } + struct pim_interface *pim_ifp; + int old_ttl; + + /* + * If we've gotten here we've gone bad, but let's + * not take down pim + */ + if (!channel_oil) { + zlog_warn("Attempt to Add OIF for non-existent channel oil"); + return -1; + } - pim_ifp = oif->info; + pim_ifp = oif->info; #ifdef PIM_ENFORCE_LOOPFREE_MFC - /* - Prevent creating MFC entry with OIF=IIF. - - This is a protection against implementation mistakes. - - PIM protocol implicitely ensures loopfree multicast topology. - - IGMP must be protected against adding looped MFC entries created - by both source and receiver attached to the same interface. See - TODO T22. - */ - if (pim_ifp->mroute_vif_index == channel_oil->oil.mfcc_parent) { - channel_oil->oil_inherited_rescan = 1; - if (PIM_DEBUG_MROUTE) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: refusing protocol mask %u request for IIF=OIF=%s (vif_index=%d) for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - proto_mask, oif->name, pim_ifp->mroute_vif_index, - source_str, group_str); - } - return -2; - } + /* + Prevent creating MFC entry with OIF=IIF. + + This is a protection against implementation mistakes. + + PIM protocol implicitely ensures loopfree multicast topology. + + IGMP must be protected against adding looped MFC entries created + by both source and receiver attached to the same interface. See + TODO T22. + */ + if (pim_ifp->mroute_vif_index == channel_oil->oil.mfcc_parent) { + channel_oil->oil_inherited_rescan = 1; + if (PIM_DEBUG_MROUTE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", + channel_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("", + channel_oil->oil.mfcc_origin, source_str, + sizeof(source_str)); + zlog_debug( + "%s %s: refusing protocol mask %u request for IIF=OIF=%s (vif_index=%d) for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, proto_mask, + oif->name, pim_ifp->mroute_vif_index, + source_str, group_str); + } + return -2; + } #endif - /* Prevent single protocol from subscribing same interface to - channel (S,G) multiple times */ - if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask) { - if (PIM_DEBUG_MROUTE) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: existing protocol mask %u requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - proto_mask, oif->name, pim_ifp->mroute_vif_index, - channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index], - source_str, group_str); - } - return -3; - } - - /* Allow other protocol to request subscription of same interface to - * channel (S,G), we need to note this information - */ - if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & PIM_OIF_FLAG_PROTO_ANY) { - - channel_oil->oif_creation[pim_ifp->mroute_vif_index] = pim_time_monotonic_sec(); - channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask; - /* Check the OIF really exists before returning, and only log - warning otherwise */ - if (channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] < 1) { - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_warn("%s %s: new protocol mask %u requested nonexistent OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - proto_mask, oif->name, pim_ifp->mroute_vif_index, - channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index], - source_str, group_str); - } - } - - return 0; - } - - old_ttl = channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]; - - if (old_ttl > 0) { - if (PIM_DEBUG_MROUTE) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: interface %s (vif_index=%d) is existing output for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - oif->name, pim_ifp->mroute_vif_index, - source_str, group_str); - } - return -4; - } - - channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = PIM_MROUTE_MIN_TTL; - - if (pim_mroute_add(channel_oil, __PRETTY_FUNCTION__)) { - if (PIM_DEBUG_MROUTE) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: could not add output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - oif->name, pim_ifp->mroute_vif_index, - source_str, group_str); - } - - channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = old_ttl; - return -5; - } - - channel_oil->oif_creation[pim_ifp->mroute_vif_index] = pim_time_monotonic_sec(); - ++channel_oil->oil_size; - channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask; - - if (PIM_DEBUG_MROUTE) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str, - proto_mask, oif->name, pim_ifp->mroute_vif_index); - } - - return 0; + /* Prevent single protocol from subscribing same interface to + channel (S,G) multiple times */ + if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask) { + if (PIM_DEBUG_MROUTE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", + channel_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("", + channel_oil->oil.mfcc_origin, source_str, + sizeof(source_str)); + zlog_debug( + "%s %s: existing protocol mask %u requested OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, proto_mask, + oif->name, pim_ifp->mroute_vif_index, + channel_oil->oil + .mfcc_ttls[pim_ifp->mroute_vif_index], + source_str, group_str); + } + return -3; + } + + /* Allow other protocol to request subscription of same interface to + * channel (S,G), we need to note this information + */ + if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] + & PIM_OIF_FLAG_PROTO_ANY) { + + channel_oil->oif_creation[pim_ifp->mroute_vif_index] = + pim_time_monotonic_sec(); + channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask; + /* Check the OIF really exists before returning, and only log + warning otherwise */ + if (channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] < 1) { + { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", + channel_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("", + channel_oil->oil.mfcc_origin, + source_str, sizeof(source_str)); + zlog_warn( + "%s %s: new protocol mask %u requested nonexistent OIF %s (vif_index=%d, min_ttl=%d) for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, + proto_mask, oif->name, + pim_ifp->mroute_vif_index, + channel_oil->oil.mfcc_ttls + [pim_ifp->mroute_vif_index], + source_str, group_str); + } + } + + return 0; + } + + old_ttl = channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]; + + if (old_ttl > 0) { + if (PIM_DEBUG_MROUTE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", + channel_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("", + channel_oil->oil.mfcc_origin, source_str, + sizeof(source_str)); + zlog_debug( + "%s %s: interface %s (vif_index=%d) is existing output for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, oif->name, + pim_ifp->mroute_vif_index, source_str, + group_str); + } + return -4; + } + + channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = + PIM_MROUTE_MIN_TTL; + + if (pim_mroute_add(channel_oil, __PRETTY_FUNCTION__)) { + if (PIM_DEBUG_MROUTE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", + channel_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("", + channel_oil->oil.mfcc_origin, source_str, + sizeof(source_str)); + zlog_debug( + "%s %s: could not add output interface %s (vif_index=%d) for channel (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, oif->name, + pim_ifp->mroute_vif_index, source_str, + group_str); + } + + channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = old_ttl; + return -5; + } + + channel_oil->oif_creation[pim_ifp->mroute_vif_index] = + pim_time_monotonic_sec(); + ++channel_oil->oil_size; + channel_oil->oif_flags[pim_ifp->mroute_vif_index] |= proto_mask; + + if (PIM_DEBUG_MROUTE) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", channel_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + pim_inet4_dump("", channel_oil->oil.mfcc_origin, + source_str, sizeof(source_str)); + zlog_debug( + "%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE", + __FILE__, __PRETTY_FUNCTION__, source_str, group_str, + proto_mask, oif->name, pim_ifp->mroute_vif_index); + } + + return 0; } -int -pim_channel_oil_empty (struct channel_oil *c_oil) +int pim_channel_oil_empty(struct channel_oil *c_oil) { - static uint32_t zero[MAXVIFS]; - static int inited = 0; - - if (!c_oil) - return 1; - /* - * Not sure that this is necessary, but I would rather ensure - * that this works. - */ - if (!inited) - { - memset(&zero, 0, sizeof(uint32_t) * MAXVIFS); - inited = 1; - } - - return !memcmp(c_oil->oif_flags, zero, MAXVIFS * sizeof(uint32_t)); + static uint32_t zero[MAXVIFS]; + static int inited = 0; + + if (!c_oil) + return 1; + /* + * Not sure that this is necessary, but I would rather ensure + * that this works. + */ + if (!inited) { + memset(&zero, 0, sizeof(uint32_t) * MAXVIFS); + inited = 1; + } + + return !memcmp(c_oil->oif_flags, zero, MAXVIFS * sizeof(uint32_t)); } diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h index 02c7e740e..f537062c7 100644 --- a/pimd/pim_oil.h +++ b/pimd/pim_oil.h @@ -34,10 +34,9 @@ #define PIM_OIF_FLAG_PROTO_PIM (1 << 1) #define PIM_OIF_FLAG_PROTO_SOURCE (1 << 2) #define PIM_OIF_FLAG_PROTO_STAR (1 << 3) -#define PIM_OIF_FLAG_PROTO_ANY (PIM_OIF_FLAG_PROTO_IGMP | \ - PIM_OIF_FLAG_PROTO_PIM | \ - PIM_OIF_FLAG_PROTO_SOURCE | \ - PIM_OIF_FLAG_PROTO_STAR) +#define PIM_OIF_FLAG_PROTO_ANY \ + (PIM_OIF_FLAG_PROTO_IGMP | PIM_OIF_FLAG_PROTO_PIM \ + | PIM_OIF_FLAG_PROTO_SOURCE | PIM_OIF_FLAG_PROTO_STAR) /* * We need a pimreg vif id from the kernel. @@ -50,16 +49,14 @@ #define PIM_OIF_PIM_REGISTER_VIF 0 #define PIM_MAX_USABLE_VIFS (MAXVIFS - 1) - -struct channel_counts -{ - unsigned long long lastused; - unsigned long pktcnt; - unsigned long oldpktcnt; - unsigned long bytecnt; - unsigned long oldbytecnt; - unsigned long wrong_if; - unsigned long oldwrong_if; +struct channel_counts { + unsigned long long lastused; + unsigned long pktcnt; + unsigned long oldpktcnt; + unsigned long bytecnt; + unsigned long oldbytecnt; + unsigned long wrong_if; + unsigned long oldwrong_if; }; /* @@ -70,35 +67,33 @@ struct channel_counts */ struct channel_oil { - struct mfcctl oil; - int installed; - int oil_inherited_rescan; - int oil_size; - int oil_ref_count; - time_t oif_creation[MAXVIFS]; - uint32_t oif_flags[MAXVIFS]; - struct channel_counts cc; - struct pim_upstream *up; + struct mfcctl oil; + int installed; + int oil_inherited_rescan; + int oil_size; + int oil_ref_count; + time_t oif_creation[MAXVIFS]; + uint32_t oif_flags[MAXVIFS]; + struct channel_counts cc; + struct pim_upstream *up; }; extern struct list *pim_channel_oil_list; -void pim_oil_init (void); -void pim_oil_terminate (void); +void pim_oil_init(void); +void pim_oil_terminate(void); void pim_channel_oil_free(struct channel_oil *c_oil); struct channel_oil *pim_channel_oil_add(struct prefix_sg *sg, int input_vif_index); void pim_channel_oil_del(struct channel_oil *c_oil); -int pim_channel_add_oif(struct channel_oil *c_oil, - struct interface *oif, +int pim_channel_add_oif(struct channel_oil *c_oil, struct interface *oif, + uint32_t proto_mask); +int pim_channel_del_oif(struct channel_oil *c_oil, struct interface *oif, uint32_t proto_mask); -int pim_channel_del_oif (struct channel_oil *c_oil, - struct interface *oif, - uint32_t proto_mask); -int pim_channel_oil_empty (struct channel_oil *c_oil); +int pim_channel_oil_empty(struct channel_oil *c_oil); -char *pim_channel_oil_dump (struct channel_oil *c_oil, char *buf, size_t size); +char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size); #endif /* PIM_OIL_H */ diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index f6a5bb122..21892f347 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -40,670 +40,673 @@ #include "pim_register.h" static int on_pim_hello_send(struct thread *t); -static int pim_hello_send(struct interface *ifp, - uint16_t holdtime); +static int pim_hello_send(struct interface *ifp, uint16_t holdtime); -static -const char *pim_pim_msgtype2str (enum pim_msg_type type) +static const char *pim_pim_msgtype2str(enum pim_msg_type type) { - switch (type) - { - case PIM_MSG_TYPE_HELLO: return "HELLO"; - case PIM_MSG_TYPE_REGISTER: return "REGISTER"; - case PIM_MSG_TYPE_REG_STOP: return "REGSTOP"; - case PIM_MSG_TYPE_JOIN_PRUNE: return "JOINPRUNE"; - case PIM_MSG_TYPE_BOOTSTRAP: return "BOOT"; - case PIM_MSG_TYPE_ASSERT: return "ASSERT"; - case PIM_MSG_TYPE_GRAFT: return "GRAFT"; - case PIM_MSG_TYPE_GRAFT_ACK: return "GACK"; - case PIM_MSG_TYPE_CANDIDATE: return "CANDIDATE"; - } - - return "UNKNOWN"; + switch (type) { + case PIM_MSG_TYPE_HELLO: + return "HELLO"; + case PIM_MSG_TYPE_REGISTER: + return "REGISTER"; + case PIM_MSG_TYPE_REG_STOP: + return "REGSTOP"; + case PIM_MSG_TYPE_JOIN_PRUNE: + return "JOINPRUNE"; + case PIM_MSG_TYPE_BOOTSTRAP: + return "BOOT"; + case PIM_MSG_TYPE_ASSERT: + return "ASSERT"; + case PIM_MSG_TYPE_GRAFT: + return "GRAFT"; + case PIM_MSG_TYPE_GRAFT_ACK: + return "GACK"; + case PIM_MSG_TYPE_CANDIDATE: + return "CANDIDATE"; + } + + return "UNKNOWN"; } static void sock_close(struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; - - if (PIM_DEBUG_PIM_TRACE) { - if (pim_ifp->t_pim_sock_read) { - zlog_debug("Cancelling READ event for PIM socket fd=%d on interface %s", - pim_ifp->pim_sock_fd, - ifp->name); - } - } - THREAD_OFF(pim_ifp->t_pim_sock_read); - - if (PIM_DEBUG_PIM_TRACE) { - if (pim_ifp->t_pim_hello_timer) { - zlog_debug("Cancelling PIM hello timer for interface %s", - ifp->name); - } - } - THREAD_OFF(pim_ifp->t_pim_hello_timer); - - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("Deleting PIM socket fd=%d on interface %s", - pim_ifp->pim_sock_fd, ifp->name); - } - - /* - * If the fd is already deleted no need to do anything here - */ - if (pim_ifp->pim_sock_fd > 0 && close(pim_ifp->pim_sock_fd)) { - zlog_warn("Failure closing PIM socket fd=%d on interface %s: errno=%d: %s", - pim_ifp->pim_sock_fd, ifp->name, - errno, safe_strerror(errno)); - } - - pim_ifp->pim_sock_fd = -1; - pim_ifp->pim_sock_creation = 0; + struct pim_interface *pim_ifp = ifp->info; + + if (PIM_DEBUG_PIM_TRACE) { + if (pim_ifp->t_pim_sock_read) { + zlog_debug( + "Cancelling READ event for PIM socket fd=%d on interface %s", + pim_ifp->pim_sock_fd, ifp->name); + } + } + THREAD_OFF(pim_ifp->t_pim_sock_read); + + if (PIM_DEBUG_PIM_TRACE) { + if (pim_ifp->t_pim_hello_timer) { + zlog_debug( + "Cancelling PIM hello timer for interface %s", + ifp->name); + } + } + THREAD_OFF(pim_ifp->t_pim_hello_timer); + + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("Deleting PIM socket fd=%d on interface %s", + pim_ifp->pim_sock_fd, ifp->name); + } + + /* + * If the fd is already deleted no need to do anything here + */ + if (pim_ifp->pim_sock_fd > 0 && close(pim_ifp->pim_sock_fd)) { + zlog_warn( + "Failure closing PIM socket fd=%d on interface %s: errno=%d: %s", + pim_ifp->pim_sock_fd, ifp->name, errno, + safe_strerror(errno)); + } + + pim_ifp->pim_sock_fd = -1; + pim_ifp->pim_sock_creation = 0; } void pim_sock_delete(struct interface *ifp, const char *delete_message) { - zlog_info("PIM INTERFACE DOWN: on interface %s: %s", - ifp->name, delete_message); - - if (!ifp->info) { - zlog_err("%s: %s: but PIM not enabled on interface %s (!)", - __PRETTY_FUNCTION__, delete_message, ifp->name); - return; - } - - /* - RFC 4601: 4.3.1. Sending Hello Messages - - Before an interface goes down or changes primary IP address, a Hello - message with a zero HoldTime should be sent immediately (with the - old IP address if the IP address changed). - */ - pim_hello_send(ifp, 0 /* zero-sec holdtime */); - - pim_neighbor_delete_all(ifp, delete_message); - - sock_close(ifp); + zlog_info("PIM INTERFACE DOWN: on interface %s: %s", ifp->name, + delete_message); + + if (!ifp->info) { + zlog_err("%s: %s: but PIM not enabled on interface %s (!)", + __PRETTY_FUNCTION__, delete_message, ifp->name); + return; + } + + /* + RFC 4601: 4.3.1. Sending Hello Messages + + Before an interface goes down or changes primary IP address, a Hello + message with a zero HoldTime should be sent immediately (with the + old IP address if the IP address changed). + */ + pim_hello_send(ifp, 0 /* zero-sec holdtime */); + + pim_neighbor_delete_all(ifp, delete_message); + + sock_close(ifp); } int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len) { - struct ip *ip_hdr; - size_t ip_hlen; /* ip header length in bytes */ - char src_str[INET_ADDRSTRLEN]; - char dst_str[INET_ADDRSTRLEN]; - uint8_t *pim_msg; - int pim_msg_len; - uint16_t pim_checksum; /* received checksum */ - uint16_t checksum; /* computed checksum */ - struct pim_neighbor *neigh; - struct pim_msg_header *header; - - if (len < sizeof(*ip_hdr)) { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("PIM packet size=%zu shorter than minimum=%zu", - len, sizeof(*ip_hdr)); - return -1; - } - - ip_hdr = (struct ip *) buf; - ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */ - - pim_msg = buf + ip_hlen; - pim_msg_len = len - ip_hlen; - - header = (struct pim_msg_header *)pim_msg; - if (pim_msg_len < PIM_PIM_MIN_LEN) { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("PIM message size=%d shorter than minimum=%d", - pim_msg_len, PIM_PIM_MIN_LEN); - return -1; - } - - if (header->ver != PIM_PROTO_VERSION) { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("Ignoring PIM pkt from %s with unsupported version: %d", - ifp->name, header->ver); - return -1; - } - - /* save received checksum */ - pim_checksum = header->checksum; - - /* for computing checksum */ - header->checksum = 0; - - if (header->type == PIM_MSG_TYPE_REGISTER) - { - /* First 8 byte header checksum */ - checksum = in_cksum (pim_msg, PIM_MSG_REGISTER_LEN); - if (checksum != pim_checksum) - { - checksum = in_cksum (pim_msg, pim_msg_len); - if (checksum != pim_checksum) - { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug - ("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x", - ifp->name, pim_checksum, checksum); - - return -1; - } - } - } - else - { - checksum = in_cksum (pim_msg, pim_msg_len); - if (checksum != pim_checksum) - { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug - ("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x", - ifp->name, pim_checksum, checksum); - - return -1; - } - } - - if (PIM_DEBUG_PIM_PACKETS) { - pim_inet4_dump("", ip_hdr->ip_src, src_str, sizeof(src_str)); - pim_inet4_dump("", ip_hdr->ip_dst, dst_str, sizeof(dst_str)); - zlog_debug("Recv PIM %s packet from %s to %s on %s: ttl=%d pim_version=%d pim_msg_size=%d checksum=%x", - pim_pim_msgtype2str (header->type), src_str, dst_str, ifp->name, - ip_hdr->ip_ttl, header->ver, pim_msg_len, checksum); - if (PIM_DEBUG_PIM_PACKETDUMP_RECV) { - pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_len); - } - } - - switch (header->type) - { - case PIM_MSG_TYPE_HELLO: - return pim_hello_recv (ifp, - ip_hdr->ip_src, - pim_msg + PIM_MSG_HEADER_LEN, - pim_msg_len - PIM_MSG_HEADER_LEN); - break; - case PIM_MSG_TYPE_REGISTER: - return pim_register_recv (ifp, - ip_hdr->ip_dst, - ip_hdr->ip_src, - pim_msg + PIM_MSG_HEADER_LEN, - pim_msg_len - PIM_MSG_HEADER_LEN); - break; - case PIM_MSG_TYPE_REG_STOP: - return pim_register_stop_recv (pim_msg + PIM_MSG_HEADER_LEN, - pim_msg_len - PIM_MSG_HEADER_LEN); - break; - case PIM_MSG_TYPE_JOIN_PRUNE: - neigh = pim_neighbor_find(ifp, ip_hdr->ip_src); - if (!neigh) { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s", - __FILE__, __PRETTY_FUNCTION__, - header->type, src_str, ifp->name); - return -1; - } - pim_neighbor_timer_reset(neigh, neigh->holdtime); - return pim_joinprune_recv(ifp, neigh, - ip_hdr->ip_src, - pim_msg + PIM_MSG_HEADER_LEN, - pim_msg_len - PIM_MSG_HEADER_LEN); - break; - case PIM_MSG_TYPE_ASSERT: - neigh = pim_neighbor_find(ifp, ip_hdr->ip_src); - if (!neigh) { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s", - __FILE__, __PRETTY_FUNCTION__, - header->type, src_str, ifp->name); + struct ip *ip_hdr; + size_t ip_hlen; /* ip header length in bytes */ + char src_str[INET_ADDRSTRLEN]; + char dst_str[INET_ADDRSTRLEN]; + uint8_t *pim_msg; + int pim_msg_len; + uint16_t pim_checksum; /* received checksum */ + uint16_t checksum; /* computed checksum */ + struct pim_neighbor *neigh; + struct pim_msg_header *header; + + if (len < sizeof(*ip_hdr)) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "PIM packet size=%zu shorter than minimum=%zu", + len, sizeof(*ip_hdr)); + return -1; + } + + ip_hdr = (struct ip *)buf; + ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */ + + pim_msg = buf + ip_hlen; + pim_msg_len = len - ip_hlen; + + header = (struct pim_msg_header *)pim_msg; + if (pim_msg_len < PIM_PIM_MIN_LEN) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "PIM message size=%d shorter than minimum=%d", + pim_msg_len, PIM_PIM_MIN_LEN); + return -1; + } + + if (header->ver != PIM_PROTO_VERSION) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "Ignoring PIM pkt from %s with unsupported version: %d", + ifp->name, header->ver); + return -1; + } + + /* save received checksum */ + pim_checksum = header->checksum; + + /* for computing checksum */ + header->checksum = 0; + + if (header->type == PIM_MSG_TYPE_REGISTER) { + /* First 8 byte header checksum */ + checksum = in_cksum(pim_msg, PIM_MSG_REGISTER_LEN); + if (checksum != pim_checksum) { + checksum = in_cksum(pim_msg, pim_msg_len); + if (checksum != pim_checksum) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x", + ifp->name, pim_checksum, + checksum); + + return -1; + } + } + } else { + checksum = in_cksum(pim_msg, pim_msg_len); + if (checksum != pim_checksum) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x", + ifp->name, pim_checksum, checksum); + + return -1; + } + } + + if (PIM_DEBUG_PIM_PACKETS) { + pim_inet4_dump("", ip_hdr->ip_src, src_str, + sizeof(src_str)); + pim_inet4_dump("", ip_hdr->ip_dst, dst_str, + sizeof(dst_str)); + zlog_debug( + "Recv PIM %s packet from %s to %s on %s: ttl=%d pim_version=%d pim_msg_size=%d checksum=%x", + pim_pim_msgtype2str(header->type), src_str, dst_str, + ifp->name, ip_hdr->ip_ttl, header->ver, pim_msg_len, + checksum); + if (PIM_DEBUG_PIM_PACKETDUMP_RECV) { + pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_len); + } + } + + switch (header->type) { + case PIM_MSG_TYPE_HELLO: + return pim_hello_recv(ifp, ip_hdr->ip_src, + pim_msg + PIM_MSG_HEADER_LEN, + pim_msg_len - PIM_MSG_HEADER_LEN); + break; + case PIM_MSG_TYPE_REGISTER: + return pim_register_recv(ifp, ip_hdr->ip_dst, ip_hdr->ip_src, + pim_msg + PIM_MSG_HEADER_LEN, + pim_msg_len - PIM_MSG_HEADER_LEN); + break; + case PIM_MSG_TYPE_REG_STOP: + return pim_register_stop_recv(pim_msg + PIM_MSG_HEADER_LEN, + pim_msg_len - PIM_MSG_HEADER_LEN); + break; + case PIM_MSG_TYPE_JOIN_PRUNE: + neigh = pim_neighbor_find(ifp, ip_hdr->ip_src); + if (!neigh) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "%s %s: non-hello PIM message type=%d from non-neighbor %s on %s", + __FILE__, __PRETTY_FUNCTION__, + header->type, src_str, ifp->name); + return -1; + } + pim_neighbor_timer_reset(neigh, neigh->holdtime); + return pim_joinprune_recv(ifp, neigh, ip_hdr->ip_src, + pim_msg + PIM_MSG_HEADER_LEN, + pim_msg_len - PIM_MSG_HEADER_LEN); + break; + case PIM_MSG_TYPE_ASSERT: + neigh = pim_neighbor_find(ifp, ip_hdr->ip_src); + if (!neigh) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "%s %s: non-hello PIM message type=%d from non-neighbor %s on %s", + __FILE__, __PRETTY_FUNCTION__, + header->type, src_str, ifp->name); + return -1; + } + pim_neighbor_timer_reset(neigh, neigh->holdtime); + return pim_assert_recv(ifp, neigh, ip_hdr->ip_src, + pim_msg + PIM_MSG_HEADER_LEN, + pim_msg_len - PIM_MSG_HEADER_LEN); + break; + default: + if (PIM_DEBUG_PIM_PACKETS) { + zlog_debug( + "Recv PIM packet type %d which is not currently understood", + header->type); + } + return -1; + } return -1; - } - pim_neighbor_timer_reset(neigh, neigh->holdtime); - return pim_assert_recv(ifp, neigh, - ip_hdr->ip_src, - pim_msg + PIM_MSG_HEADER_LEN, - pim_msg_len - PIM_MSG_HEADER_LEN); - break; - default: - if (PIM_DEBUG_PIM_PACKETS) { - zlog_debug("Recv PIM packet type %d which is not currently understood", - header->type); - } - return -1; - } - return -1; } static void pim_sock_read_on(struct interface *ifp); static int pim_sock_read(struct thread *t) { - struct interface *ifp; - struct pim_interface *pim_ifp; - int fd; - struct sockaddr_in from; - struct sockaddr_in to; - socklen_t fromlen = sizeof(from); - socklen_t tolen = sizeof(to); - uint8_t buf[PIM_PIM_BUFSIZE_READ]; - int len; - ifindex_t ifindex = -1; - int result = -1; /* defaults to bad */ - static long long count = 0; - int cont = 1; - - ifp = THREAD_ARG(t); - fd = THREAD_FD(t); - - pim_ifp = ifp->info; - - while (cont) - { - len = pim_socket_recvfromto(fd, buf, sizeof(buf), - &from, &fromlen, - &to, &tolen, - &ifindex); - if (len < 0) - { - if (errno == EINTR) - continue; - if (errno == EWOULDBLOCK || errno == EAGAIN) - break; - - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("Received errno: %d %s", errno, safe_strerror (errno)); - goto done; - } + struct interface *ifp; + struct pim_interface *pim_ifp; + int fd; + struct sockaddr_in from; + struct sockaddr_in to; + socklen_t fromlen = sizeof(from); + socklen_t tolen = sizeof(to); + uint8_t buf[PIM_PIM_BUFSIZE_READ]; + int len; + ifindex_t ifindex = -1; + int result = -1; /* defaults to bad */ + static long long count = 0; + int cont = 1; + + ifp = THREAD_ARG(t); + fd = THREAD_FD(t); + + pim_ifp = ifp->info; + + while (cont) { + len = pim_socket_recvfromto(fd, buf, sizeof(buf), &from, + &fromlen, &to, &tolen, &ifindex); + if (len < 0) { + if (errno == EINTR) + continue; + if (errno == EWOULDBLOCK || errno == EAGAIN) + break; + + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("Received errno: %d %s", errno, + safe_strerror(errno)); + goto done; + } #ifdef PIM_CHECK_RECV_IFINDEX_SANITY - /* ifindex sanity check */ - if (ifindex != (int) ifp->ifindex) { - char from_str[INET_ADDRSTRLEN]; - char to_str[INET_ADDRSTRLEN]; - struct interface *recv_ifp; - - if (!inet_ntop(AF_INET, &from.sin_addr, from_str , sizeof(from_str))) - sprintf(from_str, ""); - if (!inet_ntop(AF_INET, &to.sin_addr, to_str , sizeof(to_str))) - sprintf(to_str, ""); - - recv_ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); - if (recv_ifp) { - zassert(ifindex == (int) recv_ifp->ifindex); - } + /* ifindex sanity check */ + if (ifindex != (int)ifp->ifindex) { + char from_str[INET_ADDRSTRLEN]; + char to_str[INET_ADDRSTRLEN]; + struct interface *recv_ifp; + + if (!inet_ntop(AF_INET, &from.sin_addr, from_str, + sizeof(from_str))) + sprintf(from_str, ""); + if (!inet_ntop(AF_INET, &to.sin_addr, to_str, + sizeof(to_str))) + sprintf(to_str, ""); + + recv_ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); + if (recv_ifp) { + zassert(ifindex == (int)recv_ifp->ifindex); + } #ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH - zlog_warn("Interface mismatch: recv PIM pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)", - from_str, to_str, fd, - ifindex, recv_ifp ? recv_ifp->name : "", - ifp->ifindex, ifp->name); + zlog_warn( + "Interface mismatch: recv PIM pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)", + from_str, to_str, fd, ifindex, + recv_ifp ? recv_ifp->name : "", + ifp->ifindex, ifp->name); #endif - goto done; - } + goto done; + } #endif - int fail = pim_pim_packet(ifp, buf, len); - if (fail) { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("%s: pim_pim_packet() return=%d", - __PRETTY_FUNCTION__, fail); - goto done; - } - - count++; - if (count % qpim_packet_process == 0) - cont = 0; - } + int fail = pim_pim_packet(ifp, buf, len); + if (fail) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("%s: pim_pim_packet() return=%d", + __PRETTY_FUNCTION__, fail); + goto done; + } + + count++; + if (count % qpim_packet_process == 0) + cont = 0; + } - result = 0; /* good */ + result = 0; /* good */ - done: - pim_sock_read_on(ifp); +done: + pim_sock_read_on(ifp); - if (result) { - ++pim_ifp->pim_ifstat_hello_recvfail; - } + if (result) { + ++pim_ifp->pim_ifstat_hello_recvfail; + } - return result; + return result; } static void pim_sock_read_on(struct interface *ifp) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - zassert(ifp); - zassert(ifp->info); + zassert(ifp); + zassert(ifp->info); - pim_ifp = ifp->info; + pim_ifp = ifp->info; - if (PIM_DEBUG_PIM_TRACE_DETAIL) { - zlog_debug("Scheduling READ event on PIM socket fd=%d", - pim_ifp->pim_sock_fd); - } - pim_ifp->t_pim_sock_read = NULL; - thread_add_read(master, pim_sock_read, ifp, pim_ifp->pim_sock_fd, - &pim_ifp->t_pim_sock_read); + if (PIM_DEBUG_PIM_TRACE_DETAIL) { + zlog_debug("Scheduling READ event on PIM socket fd=%d", + pim_ifp->pim_sock_fd); + } + pim_ifp->t_pim_sock_read = NULL; + thread_add_read(master, pim_sock_read, ifp, pim_ifp->pim_sock_fd, + &pim_ifp->t_pim_sock_read); } static int pim_sock_open(struct interface *ifp) { - int fd; - struct pim_interface *pim_ifp = ifp->info; - - fd = pim_socket_mcast(IPPROTO_PIM, pim_ifp->primary_address, ifp, 0 /* loop=false */); - if (fd < 0) - return -1; - - if (pim_socket_join(fd, qpim_all_pim_routers_addr, pim_ifp->primary_address, ifp->ifindex)) { - close(fd); - return -2; - } + int fd; + struct pim_interface *pim_ifp = ifp->info; + + fd = pim_socket_mcast(IPPROTO_PIM, pim_ifp->primary_address, ifp, + 0 /* loop=false */); + if (fd < 0) + return -1; + + if (pim_socket_join(fd, qpim_all_pim_routers_addr, + pim_ifp->primary_address, ifp->ifindex)) { + close(fd); + return -2; + } - return fd; + return fd; } void pim_ifstat_reset(struct interface *ifp) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - zassert(ifp); + zassert(ifp); - pim_ifp = ifp->info; - if (!pim_ifp) { - return; - } + pim_ifp = ifp->info; + if (!pim_ifp) { + return; + } - pim_ifp->pim_ifstat_start = pim_time_monotonic_sec(); - pim_ifp->pim_ifstat_hello_sent = 0; - pim_ifp->pim_ifstat_hello_sendfail = 0; - pim_ifp->pim_ifstat_hello_recv = 0; - pim_ifp->pim_ifstat_hello_recvfail = 0; + pim_ifp->pim_ifstat_start = pim_time_monotonic_sec(); + pim_ifp->pim_ifstat_hello_sent = 0; + pim_ifp->pim_ifstat_hello_sendfail = 0; + pim_ifp->pim_ifstat_hello_recv = 0; + pim_ifp->pim_ifstat_hello_recvfail = 0; } void pim_sock_reset(struct interface *ifp) { - struct pim_interface *pim_ifp; - - zassert(ifp); - zassert(ifp->info); - - pim_ifp = ifp->info; - - pim_ifp->primary_address = pim_find_primary_addr(ifp); - - pim_ifp->pim_sock_fd = -1; - pim_ifp->pim_sock_creation = 0; - pim_ifp->t_pim_sock_read = NULL; - - pim_ifp->t_pim_hello_timer = NULL; - pim_ifp->pim_hello_period = PIM_DEFAULT_HELLO_PERIOD; - pim_ifp->pim_default_holdtime = -1; /* unset: means 3.5 * pim_hello_period */ - pim_ifp->pim_triggered_hello_delay = PIM_DEFAULT_TRIGGERED_HELLO_DELAY; - pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY; - pim_ifp->pim_propagation_delay_msec = PIM_DEFAULT_PROPAGATION_DELAY_MSEC; - pim_ifp->pim_override_interval_msec = PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC; - if (PIM_DEFAULT_CAN_DISABLE_JOIN_SUPPRESSION) { - PIM_IF_DO_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options); - } - else { - PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options); - } - - /* neighbors without lan_delay */ - pim_ifp->pim_number_of_nonlandelay_neighbors = 0; - pim_ifp->pim_neighbors_highest_propagation_delay_msec = 0; - pim_ifp->pim_neighbors_highest_override_interval_msec = 0; - - /* DR Election */ - pim_ifp->pim_dr_election_last = 0; /* timestamp */ - pim_ifp->pim_dr_election_count = 0; - pim_ifp->pim_dr_election_changes = 0; - pim_ifp->pim_dr_num_nondrpri_neighbors = 0; /* neighbors without dr_pri */ - pim_ifp->pim_dr_addr = pim_ifp->primary_address; - - pim_ifstat_reset(ifp); + struct pim_interface *pim_ifp; + + zassert(ifp); + zassert(ifp->info); + + pim_ifp = ifp->info; + + pim_ifp->primary_address = pim_find_primary_addr(ifp); + + pim_ifp->pim_sock_fd = -1; + pim_ifp->pim_sock_creation = 0; + pim_ifp->t_pim_sock_read = NULL; + + pim_ifp->t_pim_hello_timer = NULL; + pim_ifp->pim_hello_period = PIM_DEFAULT_HELLO_PERIOD; + pim_ifp->pim_default_holdtime = + -1; /* unset: means 3.5 * pim_hello_period */ + pim_ifp->pim_triggered_hello_delay = PIM_DEFAULT_TRIGGERED_HELLO_DELAY; + pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY; + pim_ifp->pim_propagation_delay_msec = + PIM_DEFAULT_PROPAGATION_DELAY_MSEC; + pim_ifp->pim_override_interval_msec = + PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC; + if (PIM_DEFAULT_CAN_DISABLE_JOIN_SUPPRESSION) { + PIM_IF_DO_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options); + } else { + PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options); + } + + /* neighbors without lan_delay */ + pim_ifp->pim_number_of_nonlandelay_neighbors = 0; + pim_ifp->pim_neighbors_highest_propagation_delay_msec = 0; + pim_ifp->pim_neighbors_highest_override_interval_msec = 0; + + /* DR Election */ + pim_ifp->pim_dr_election_last = 0; /* timestamp */ + pim_ifp->pim_dr_election_count = 0; + pim_ifp->pim_dr_election_changes = 0; + pim_ifp->pim_dr_num_nondrpri_neighbors = + 0; /* neighbors without dr_pri */ + pim_ifp->pim_dr_addr = pim_ifp->primary_address; + + pim_ifstat_reset(ifp); } static uint16_t ip_id = 0; -static int -pim_msg_send_frame (int fd, char *buf, size_t len, - struct sockaddr *dst, size_t salen) +static int pim_msg_send_frame(int fd, char *buf, size_t len, + struct sockaddr *dst, size_t salen) { - struct ip *ip = (struct ip *)buf; - - while (sendto (fd, buf, len, MSG_DONTWAIT, dst, salen) < 0) - { - char dst_str[INET_ADDRSTRLEN]; - - switch (errno) - { - case EMSGSIZE: - { - size_t hdrsize = sizeof (struct ip); - size_t newlen1 = ((len - hdrsize) / 2 ) & 0xFFF8; - size_t sendlen = newlen1 + hdrsize; - size_t offset = ntohs (ip->ip_off); - - ip->ip_len = htons (sendlen); - ip->ip_off = htons (offset | IP_MF); - if (pim_msg_send_frame (fd, buf, sendlen, dst, salen) == 0) - { - struct ip *ip2 = (struct ip *)(buf + newlen1); - size_t newlen2 = len - sendlen; - sendlen = newlen2 + hdrsize; - - memcpy (ip2, ip, hdrsize); - ip2->ip_len = htons (sendlen); - ip2->ip_off = htons (offset + (newlen1 >> 3)); - return pim_msg_send_frame (fd, (char *)ip2, sendlen, dst, salen); - } - } - - return -1; - break; - default: - if (PIM_DEBUG_PIM_PACKETS) - { - pim_inet4_dump ("", ip->ip_dst, dst_str, sizeof (dst_str)); - zlog_warn ("%s: sendto() failure to %s: fd=%d msg_size=%zd: errno=%d: %s", - __PRETTY_FUNCTION__, - dst_str, fd, len, - errno, safe_strerror(errno)); - } - return -1; - break; + struct ip *ip = (struct ip *)buf; + + while (sendto(fd, buf, len, MSG_DONTWAIT, dst, salen) < 0) { + char dst_str[INET_ADDRSTRLEN]; + + switch (errno) { + case EMSGSIZE: { + size_t hdrsize = sizeof(struct ip); + size_t newlen1 = ((len - hdrsize) / 2) & 0xFFF8; + size_t sendlen = newlen1 + hdrsize; + size_t offset = ntohs(ip->ip_off); + + ip->ip_len = htons(sendlen); + ip->ip_off = htons(offset | IP_MF); + if (pim_msg_send_frame(fd, buf, sendlen, dst, salen) + == 0) { + struct ip *ip2 = (struct ip *)(buf + newlen1); + size_t newlen2 = len - sendlen; + sendlen = newlen2 + hdrsize; + + memcpy(ip2, ip, hdrsize); + ip2->ip_len = htons(sendlen); + ip2->ip_off = htons(offset + (newlen1 >> 3)); + return pim_msg_send_frame(fd, (char *)ip2, + sendlen, dst, salen); + } + } + + return -1; + break; + default: + if (PIM_DEBUG_PIM_PACKETS) { + pim_inet4_dump("", ip->ip_dst, dst_str, + sizeof(dst_str)); + zlog_warn( + "%s: sendto() failure to %s: fd=%d msg_size=%zd: errno=%d: %s", + __PRETTY_FUNCTION__, dst_str, fd, len, + errno, safe_strerror(errno)); + } + return -1; + break; + } } - } - return 0; + return 0; } -int -pim_msg_send(int fd, struct in_addr src, - struct in_addr dst, uint8_t *pim_msg, - int pim_msg_size, const char *ifname) +int pim_msg_send(int fd, struct in_addr src, struct in_addr dst, + uint8_t *pim_msg, int pim_msg_size, const char *ifname) { - struct sockaddr_in to; - socklen_t tolen; - unsigned char buffer[10000]; - unsigned char *msg_start; - uint8_t ttl = MAXTTL; - struct pim_msg_header *header; - struct ip *ip; - - memset (buffer, 0, 10000); - int sendlen = sizeof (struct ip) + pim_msg_size; - - msg_start = buffer + sizeof (struct ip); - memcpy (msg_start, pim_msg, pim_msg_size); - - header = (struct pim_msg_header *)pim_msg; - /* - * Omnios apparently doesn't have a #define for IP default - * ttl that is the same as all other platforms. - */ + struct sockaddr_in to; + socklen_t tolen; + unsigned char buffer[10000]; + unsigned char *msg_start; + uint8_t ttl = MAXTTL; + struct pim_msg_header *header; + struct ip *ip; + + memset(buffer, 0, 10000); + int sendlen = sizeof(struct ip) + pim_msg_size; + + msg_start = buffer + sizeof(struct ip); + memcpy(msg_start, pim_msg, pim_msg_size); + + header = (struct pim_msg_header *)pim_msg; +/* + * Omnios apparently doesn't have a #define for IP default + * ttl that is the same as all other platforms. + */ #ifndef IPDEFTTL #define IPDEFTTL 64 #endif - /* TTL for packets destine to ALL-PIM-ROUTERS is 1 */ - switch (header->type) - { - case PIM_MSG_TYPE_HELLO: - case PIM_MSG_TYPE_JOIN_PRUNE: - case PIM_MSG_TYPE_BOOTSTRAP: - case PIM_MSG_TYPE_ASSERT: - ttl = 1; - break; - case PIM_MSG_TYPE_REGISTER: - case PIM_MSG_TYPE_REG_STOP: - case PIM_MSG_TYPE_GRAFT: - case PIM_MSG_TYPE_GRAFT_ACK: - case PIM_MSG_TYPE_CANDIDATE: - ttl = IPDEFTTL; - break; - default: - ttl = MAXTTL; - break; - } - - ip = (struct ip *) buffer; - ip->ip_id = htons (++ip_id); - ip->ip_hl = 5; - ip->ip_v = 4; - ip->ip_p = PIM_IP_PROTO_PIM; - ip->ip_src = src; - ip->ip_dst = dst; - ip->ip_ttl = ttl; - ip->ip_len = htons (sendlen); - - if (PIM_DEBUG_PIM_PACKETS) { - struct pim_msg_header *header = (struct pim_msg_header *)pim_msg; - char dst_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", dst, dst_str, sizeof(dst_str)); - zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x", - __PRETTY_FUNCTION__, - dst_str, ifname, pim_msg_size, - header->checksum); - } - - memset(&to, 0, sizeof(to)); - to.sin_family = AF_INET; - to.sin_addr = dst; - tolen = sizeof(to); - - if (PIM_DEBUG_PIM_PACKETDUMP_SEND) { - pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_size); - } - - pim_msg_send_frame (fd, (char *)buffer, sendlen, - (struct sockaddr *)&to, tolen); - return 0; + /* TTL for packets destine to ALL-PIM-ROUTERS is 1 */ + switch (header->type) { + case PIM_MSG_TYPE_HELLO: + case PIM_MSG_TYPE_JOIN_PRUNE: + case PIM_MSG_TYPE_BOOTSTRAP: + case PIM_MSG_TYPE_ASSERT: + ttl = 1; + break; + case PIM_MSG_TYPE_REGISTER: + case PIM_MSG_TYPE_REG_STOP: + case PIM_MSG_TYPE_GRAFT: + case PIM_MSG_TYPE_GRAFT_ACK: + case PIM_MSG_TYPE_CANDIDATE: + ttl = IPDEFTTL; + break; + default: + ttl = MAXTTL; + break; + } + + ip = (struct ip *)buffer; + ip->ip_id = htons(++ip_id); + ip->ip_hl = 5; + ip->ip_v = 4; + ip->ip_p = PIM_IP_PROTO_PIM; + ip->ip_src = src; + ip->ip_dst = dst; + ip->ip_ttl = ttl; + ip->ip_len = htons(sendlen); + + if (PIM_DEBUG_PIM_PACKETS) { + struct pim_msg_header *header = + (struct pim_msg_header *)pim_msg; + char dst_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", dst, dst_str, sizeof(dst_str)); + zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x", + __PRETTY_FUNCTION__, dst_str, ifname, pim_msg_size, + header->checksum); + } + + memset(&to, 0, sizeof(to)); + to.sin_family = AF_INET; + to.sin_addr = dst; + tolen = sizeof(to); + + if (PIM_DEBUG_PIM_PACKETDUMP_SEND) { + pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_size); + } + + pim_msg_send_frame(fd, (char *)buffer, sendlen, (struct sockaddr *)&to, + tolen); + return 0; } -static int hello_send(struct interface *ifp, - uint16_t holdtime) +static int hello_send(struct interface *ifp, uint16_t holdtime) { - uint8_t pim_msg[PIM_PIM_BUFSIZE_WRITE]; - struct pim_interface *pim_ifp; - int pim_tlv_size; - int pim_msg_size; - - pim_ifp = ifp->info; - - if (PIM_DEBUG_PIM_HELLO) { - char dst_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", qpim_all_pim_routers_addr, dst_str, sizeof(dst_str)); - zlog_debug("%s: to %s on %s: holdt=%u prop_d=%u overr_i=%u dis_join_supp=%d dr_prio=%u gen_id=%08x addrs=%d", - __PRETTY_FUNCTION__, - dst_str, ifp->name, - holdtime, - pim_ifp->pim_propagation_delay_msec, pim_ifp->pim_override_interval_msec, - PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options), - pim_ifp->pim_dr_priority, pim_ifp->pim_generation_id, - listcount(ifp->connected)); - } - - pim_tlv_size = pim_hello_build_tlv(ifp, - pim_msg + PIM_PIM_MIN_LEN, - sizeof(pim_msg) - PIM_PIM_MIN_LEN, - holdtime, - pim_ifp->pim_dr_priority, - pim_ifp->pim_generation_id, - pim_ifp->pim_propagation_delay_msec, - pim_ifp->pim_override_interval_msec, - PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options)); - if (pim_tlv_size < 0) { - return -1; - } - - pim_msg_size = pim_tlv_size + PIM_PIM_MIN_LEN; - - zassert(pim_msg_size >= PIM_PIM_MIN_LEN); - zassert(pim_msg_size <= PIM_PIM_BUFSIZE_WRITE); - - pim_msg_build_header(pim_msg, pim_msg_size, PIM_MSG_TYPE_HELLO); - - if (pim_msg_send(pim_ifp->pim_sock_fd, - pim_ifp->primary_address, - qpim_all_pim_routers_addr, - pim_msg, - pim_msg_size, - ifp->name)) { - if (PIM_DEBUG_PIM_HELLO) { - zlog_debug("%s: could not send PIM message on interface %s", - __PRETTY_FUNCTION__, ifp->name); - } - return -2; - } - - return 0; + uint8_t pim_msg[PIM_PIM_BUFSIZE_WRITE]; + struct pim_interface *pim_ifp; + int pim_tlv_size; + int pim_msg_size; + + pim_ifp = ifp->info; + + if (PIM_DEBUG_PIM_HELLO) { + char dst_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", qpim_all_pim_routers_addr, dst_str, + sizeof(dst_str)); + zlog_debug( + "%s: to %s on %s: holdt=%u prop_d=%u overr_i=%u dis_join_supp=%d dr_prio=%u gen_id=%08x addrs=%d", + __PRETTY_FUNCTION__, dst_str, ifp->name, holdtime, + pim_ifp->pim_propagation_delay_msec, + pim_ifp->pim_override_interval_msec, + PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION( + pim_ifp->options), + pim_ifp->pim_dr_priority, pim_ifp->pim_generation_id, + listcount(ifp->connected)); + } + + pim_tlv_size = pim_hello_build_tlv( + ifp, pim_msg + PIM_PIM_MIN_LEN, + sizeof(pim_msg) - PIM_PIM_MIN_LEN, holdtime, + pim_ifp->pim_dr_priority, pim_ifp->pim_generation_id, + pim_ifp->pim_propagation_delay_msec, + pim_ifp->pim_override_interval_msec, + PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options)); + if (pim_tlv_size < 0) { + return -1; + } + + pim_msg_size = pim_tlv_size + PIM_PIM_MIN_LEN; + + zassert(pim_msg_size >= PIM_PIM_MIN_LEN); + zassert(pim_msg_size <= PIM_PIM_BUFSIZE_WRITE); + + pim_msg_build_header(pim_msg, pim_msg_size, PIM_MSG_TYPE_HELLO); + + if (pim_msg_send(pim_ifp->pim_sock_fd, pim_ifp->primary_address, + qpim_all_pim_routers_addr, pim_msg, pim_msg_size, + ifp->name)) { + if (PIM_DEBUG_PIM_HELLO) { + zlog_debug( + "%s: could not send PIM message on interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + return -2; + } + + return 0; } -static int pim_hello_send(struct interface *ifp, - uint16_t holdtime) +static int pim_hello_send(struct interface *ifp, uint16_t holdtime) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - zassert(ifp); - pim_ifp = ifp->info; - zassert(pim_ifp); + zassert(ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - if (if_is_loopback (ifp)) - return 0; + if (if_is_loopback(ifp)) + return 0; - if (hello_send(ifp, holdtime)) { - ++pim_ifp->pim_ifstat_hello_sendfail; + if (hello_send(ifp, holdtime)) { + ++pim_ifp->pim_ifstat_hello_sendfail; - if (PIM_DEBUG_PIM_HELLO) { - zlog_warn("Could not send PIM hello on interface %s", - ifp->name); - } - return -1; - } + if (PIM_DEBUG_PIM_HELLO) { + zlog_warn("Could not send PIM hello on interface %s", + ifp->name); + } + return -1; + } - ++pim_ifp->pim_ifstat_hello_sent; + ++pim_ifp->pim_ifstat_hello_sent; - return 0; + return 0; } static void hello_resched(struct interface *ifp) { - struct pim_interface *pim_ifp; - - zassert(ifp); - pim_ifp = ifp->info; - zassert(pim_ifp); - - if (PIM_DEBUG_PIM_HELLO) { - zlog_debug("Rescheduling %d sec hello on interface %s", - pim_ifp->pim_hello_period, ifp->name); - } - THREAD_OFF(pim_ifp->t_pim_hello_timer); - thread_add_timer(master, on_pim_hello_send, ifp, pim_ifp->pim_hello_period, - &pim_ifp->t_pim_hello_timer); + struct pim_interface *pim_ifp; + + zassert(ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); + + if (PIM_DEBUG_PIM_HELLO) { + zlog_debug("Rescheduling %d sec hello on interface %s", + pim_ifp->pim_hello_period, ifp->name); + } + THREAD_OFF(pim_ifp->t_pim_hello_timer); + thread_add_timer(master, on_pim_hello_send, ifp, + pim_ifp->pim_hello_period, + &pim_ifp->t_pim_hello_timer); } /* @@ -711,22 +714,22 @@ static void hello_resched(struct interface *ifp) */ static int on_pim_hello_send(struct thread *t) { - struct pim_interface *pim_ifp; - struct interface *ifp; + struct pim_interface *pim_ifp; + struct interface *ifp; - ifp = THREAD_ARG(t); + ifp = THREAD_ARG(t); - pim_ifp = ifp->info; + pim_ifp = ifp->info; - /* - * Schedule next hello - */ - hello_resched(ifp); + /* + * Schedule next hello + */ + hello_resched(ifp); - /* - * Send hello - */ - return pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp)); + /* + * Send hello + */ + return pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp)); } /* @@ -740,21 +743,21 @@ static int on_pim_hello_send(struct thread *t) */ void pim_hello_restart_now(struct interface *ifp) { - struct pim_interface *pim_ifp; + struct pim_interface *pim_ifp; - zassert(ifp); - pim_ifp = ifp->info; - zassert(pim_ifp); + zassert(ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); - /* - * Reset next hello timer - */ - hello_resched(ifp); + /* + * Reset next hello timer + */ + hello_resched(ifp); - /* - * Immediately send hello - */ - pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp)); + /* + * Immediately send hello + */ + pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp)); } /* @@ -768,105 +771,109 @@ void pim_hello_restart_now(struct interface *ifp) */ void pim_hello_restart_triggered(struct interface *ifp) { - struct pim_interface *pim_ifp; - int triggered_hello_delay_msec; - int random_msec; - - zassert(ifp); - pim_ifp = ifp->info; - zassert(pim_ifp); - - /* - * There exists situations where we have the a RPF out this - * interface, but we haven't formed a neighbor yet. This - * happens especially during interface flaps. While - * we would like to handle this more gracefully in other - * parts of the code. In order to get us up and running - * let's just send the hello immediate'ish - * This should be revisited when we get nexthop tracking - * in and when we have a better handle on safely - * handling the rpf information for upstreams that - * we cannot legally reach yet. - */ - triggered_hello_delay_msec = 1; - //triggered_hello_delay_msec = 1000 * pim_ifp->pim_triggered_hello_delay; - - if (pim_ifp->t_pim_hello_timer) { - long remain_msec = pim_time_timer_remain_msec(pim_ifp->t_pim_hello_timer); - if (remain_msec <= triggered_hello_delay_msec) { - /* Rescheduling hello would increase the delay, then it's faster - to just wait for the scheduled periodic hello. */ - return; - } - - THREAD_OFF(pim_ifp->t_pim_hello_timer); - } - - random_msec = triggered_hello_delay_msec; - //random_msec = random() % (triggered_hello_delay_msec + 1); - - if (PIM_DEBUG_PIM_HELLO) { - zlog_debug("Scheduling %d msec triggered hello on interface %s", - random_msec, ifp->name); - } - - thread_add_timer_msec(master, on_pim_hello_send, ifp, random_msec, - &pim_ifp->t_pim_hello_timer); + struct pim_interface *pim_ifp; + int triggered_hello_delay_msec; + int random_msec; + + zassert(ifp); + pim_ifp = ifp->info; + zassert(pim_ifp); + + /* + * There exists situations where we have the a RPF out this + * interface, but we haven't formed a neighbor yet. This + * happens especially during interface flaps. While + * we would like to handle this more gracefully in other + * parts of the code. In order to get us up and running + * let's just send the hello immediate'ish + * This should be revisited when we get nexthop tracking + * in and when we have a better handle on safely + * handling the rpf information for upstreams that + * we cannot legally reach yet. + */ + triggered_hello_delay_msec = 1; + // triggered_hello_delay_msec = 1000 * + // pim_ifp->pim_triggered_hello_delay; + + if (pim_ifp->t_pim_hello_timer) { + long remain_msec = + pim_time_timer_remain_msec(pim_ifp->t_pim_hello_timer); + if (remain_msec <= triggered_hello_delay_msec) { + /* Rescheduling hello would increase the delay, then + it's faster + to just wait for the scheduled periodic hello. */ + return; + } + + THREAD_OFF(pim_ifp->t_pim_hello_timer); + } + + random_msec = triggered_hello_delay_msec; + // random_msec = random() % (triggered_hello_delay_msec + 1); + + if (PIM_DEBUG_PIM_HELLO) { + zlog_debug("Scheduling %d msec triggered hello on interface %s", + random_msec, ifp->name); + } + + thread_add_timer_msec(master, on_pim_hello_send, ifp, random_msec, + &pim_ifp->t_pim_hello_timer); } int pim_sock_add(struct interface *ifp) { - struct pim_interface *pim_ifp; - uint32_t old_genid; - - pim_ifp = ifp->info; - zassert(pim_ifp); - - if (pim_ifp->pim_sock_fd >= 0) { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("Can't recreate existing PIM socket fd=%d for interface %s", - pim_ifp->pim_sock_fd, ifp->name); - return -1; - } - - pim_ifp->pim_sock_fd = pim_sock_open(ifp); - if (pim_ifp->pim_sock_fd < 0) { - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("Could not open PIM socket on interface %s", - ifp->name); - return -2; - } - - pim_socket_ip_hdr (pim_ifp->pim_sock_fd); - - pim_ifp->t_pim_sock_read = NULL; - pim_ifp->pim_sock_creation = pim_time_monotonic_sec(); - - /* - * Just ensure that the new generation id - * actually chooses something different. - * Actually ran across a case where this - * happened, pre-switch to random(). - * While this is unlikely to happen now - * let's make sure it doesn't. - */ - old_genid = pim_ifp->pim_generation_id; - - while (old_genid == pim_ifp->pim_generation_id) - pim_ifp->pim_generation_id = random(); - - zlog_info("PIM INTERFACE UP: on interface %s ifindex=%d", - ifp->name, ifp->ifindex); - - /* - * Start receiving PIM messages - */ - pim_sock_read_on(ifp); - - /* - * Start sending PIM hello's - */ - pim_hello_restart_triggered(ifp); - - return 0; + struct pim_interface *pim_ifp; + uint32_t old_genid; + + pim_ifp = ifp->info; + zassert(pim_ifp); + + if (pim_ifp->pim_sock_fd >= 0) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "Can't recreate existing PIM socket fd=%d for interface %s", + pim_ifp->pim_sock_fd, ifp->name); + return -1; + } + + pim_ifp->pim_sock_fd = pim_sock_open(ifp); + if (pim_ifp->pim_sock_fd < 0) { + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug("Could not open PIM socket on interface %s", + ifp->name); + return -2; + } + + pim_socket_ip_hdr(pim_ifp->pim_sock_fd); + + pim_ifp->t_pim_sock_read = NULL; + pim_ifp->pim_sock_creation = pim_time_monotonic_sec(); + + /* + * Just ensure that the new generation id + * actually chooses something different. + * Actually ran across a case where this + * happened, pre-switch to random(). + * While this is unlikely to happen now + * let's make sure it doesn't. + */ + old_genid = pim_ifp->pim_generation_id; + + while (old_genid == pim_ifp->pim_generation_id) + pim_ifp->pim_generation_id = random(); + + zlog_info("PIM INTERFACE UP: on interface %s ifindex=%d", ifp->name, + ifp->ifindex); + + /* + * Start receiving PIM messages + */ + pim_sock_read_on(ifp); + + /* + * Start sending PIM hello's + */ + pim_hello_restart_triggered(ifp); + + return 0; } diff --git a/pimd/pim_pim.h b/pimd/pim_pim.h index 7e2872184..e930ab7c2 100644 --- a/pimd/pim_pim.h +++ b/pimd/pim_pim.h @@ -36,15 +36,15 @@ #define PIM_DEFAULT_T_PERIODIC (60) /* RFC 4601: 4.11. Timer Values */ enum pim_msg_type { - PIM_MSG_TYPE_HELLO = 0, - PIM_MSG_TYPE_REGISTER, - PIM_MSG_TYPE_REG_STOP, - PIM_MSG_TYPE_JOIN_PRUNE, - PIM_MSG_TYPE_BOOTSTRAP, - PIM_MSG_TYPE_ASSERT, - PIM_MSG_TYPE_GRAFT, - PIM_MSG_TYPE_GRAFT_ACK, - PIM_MSG_TYPE_CANDIDATE + PIM_MSG_TYPE_HELLO = 0, + PIM_MSG_TYPE_REGISTER, + PIM_MSG_TYPE_REG_STOP, + PIM_MSG_TYPE_JOIN_PRUNE, + PIM_MSG_TYPE_BOOTSTRAP, + PIM_MSG_TYPE_ASSERT, + PIM_MSG_TYPE_GRAFT, + PIM_MSG_TYPE_GRAFT_ACK, + PIM_MSG_TYPE_CANDIDATE }; void pim_ifstat_reset(struct interface *ifp); @@ -56,11 +56,7 @@ void pim_hello_restart_triggered(struct interface *ifp); int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len); -int pim_msg_send(int fd, - struct in_addr src, - struct in_addr dst, - uint8_t *pim_msg, - int pim_msg_size, - const char *ifname); +int pim_msg_send(int fd, struct in_addr src, struct in_addr dst, + uint8_t *pim_msg, int pim_msg_size, const char *ifname); #endif /* PIM_PIM_H */ diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 682a6401c..1cbe1dcf7 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -46,179 +46,173 @@ struct thread *send_test_packet_timer = NULL; -void -pim_register_join (struct pim_upstream *up) +void pim_register_join(struct pim_upstream *up) { - if (pim_is_grp_ssm (up->sg.grp)) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_debug ("%s register setup skipped as group is SSM", up->sg_str); - return; - } - - pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); - up->reg_state = PIM_REG_JOIN; + if (pim_is_grp_ssm(up->sg.grp)) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug("%s register setup skipped as group is SSM", + up->sg_str); + return; + } + + pim_channel_add_oif(up->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_PIM); + up->reg_state = PIM_REG_JOIN; } -void -pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, - struct in_addr src, struct in_addr originator) +void pim_register_stop_send(struct interface *ifp, struct prefix_sg *sg, + struct in_addr src, struct in_addr originator) { - struct pim_interface *pinfo; - unsigned char buffer[10000]; - unsigned int b1length = 0; - unsigned int length; - uint8_t *b1; - struct prefix p; - - if (PIM_DEBUG_PIM_REG) - { - zlog_debug ("Sending Register stop for %s to %s on %s", - pim_str_sg_dump (sg), inet_ntoa(originator), ifp->name); - } - - memset (buffer, 0, 10000); - b1 = (uint8_t *)buffer + PIM_MSG_REGISTER_STOP_LEN; - - length = pim_encode_addr_group (b1, AFI_IP, 0, 0, sg->grp); - b1length += length; - b1 += length; - - p.family = AF_INET; - p.u.prefix4 = sg->src; - p.prefixlen = 32; - length = pim_encode_addr_ucast (b1, &p); - b1length += length; - - pim_msg_build_header (buffer, b1length + PIM_MSG_REGISTER_STOP_LEN, PIM_MSG_TYPE_REG_STOP); - - pinfo = (struct pim_interface *)ifp->info; - if (!pinfo) - { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s: No pinfo!\n", __PRETTY_FUNCTION__); - return; - } - if (pim_msg_send (pinfo->pim_sock_fd, src, originator, - buffer, b1length + PIM_MSG_REGISTER_STOP_LEN, - ifp->name)) - { - if (PIM_DEBUG_PIM_TRACE) - { - zlog_debug ("%s: could not send PIM register stop message on interface %s", - __PRETTY_FUNCTION__, ifp->name); + struct pim_interface *pinfo; + unsigned char buffer[10000]; + unsigned int b1length = 0; + unsigned int length; + uint8_t *b1; + struct prefix p; + + if (PIM_DEBUG_PIM_REG) { + zlog_debug("Sending Register stop for %s to %s on %s", + pim_str_sg_dump(sg), inet_ntoa(originator), + ifp->name); + } + + memset(buffer, 0, 10000); + b1 = (uint8_t *)buffer + PIM_MSG_REGISTER_STOP_LEN; + + length = pim_encode_addr_group(b1, AFI_IP, 0, 0, sg->grp); + b1length += length; + b1 += length; + + p.family = AF_INET; + p.u.prefix4 = sg->src; + p.prefixlen = 32; + length = pim_encode_addr_ucast(b1, &p); + b1length += length; + + pim_msg_build_header(buffer, b1length + PIM_MSG_REGISTER_STOP_LEN, + PIM_MSG_TYPE_REG_STOP); + + pinfo = (struct pim_interface *)ifp->info; + if (!pinfo) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: No pinfo!\n", __PRETTY_FUNCTION__); + return; } - } - ++pinfo->pim_ifstat_reg_stop_send; + if (pim_msg_send(pinfo->pim_sock_fd, src, originator, buffer, + b1length + PIM_MSG_REGISTER_STOP_LEN, ifp->name)) { + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug( + "%s: could not send PIM register stop message on interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + } + ++pinfo->pim_ifstat_reg_stop_send; } -int -pim_register_stop_recv (uint8_t *buf, int buf_size) +int pim_register_stop_recv(uint8_t *buf, int buf_size) { - struct pim_upstream *upstream = NULL; - struct prefix source; - struct prefix_sg sg; - int l; - - memset (&sg, 0, sizeof (struct prefix_sg)); - l = pim_parse_addr_group (&sg, buf, buf_size); - buf += l; - buf_size -= l; - pim_parse_addr_ucast (&source, buf, buf_size); - sg.src = source.u.prefix4; - - upstream = pim_upstream_find (&sg); - if (!upstream) - { - return 0; - } - - if (PIM_DEBUG_PIM_REG) - zlog_debug ("Received Register stop for %s", - upstream->sg_str); - - switch (upstream->reg_state) - { - case PIM_REG_NOINFO: - case PIM_REG_PRUNE: - return 0; - break; - case PIM_REG_JOIN: - upstream->reg_state = PIM_REG_PRUNE; - pim_channel_del_oif (upstream->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); - pim_upstream_start_register_stop_timer (upstream, 0); - break; - case PIM_REG_JOIN_PENDING: - upstream->reg_state = PIM_REG_PRUNE; - pim_upstream_start_register_stop_timer (upstream, 0); - return 0; - break; - } - - return 0; + struct pim_upstream *upstream = NULL; + struct prefix source; + struct prefix_sg sg; + int l; + + memset(&sg, 0, sizeof(struct prefix_sg)); + l = pim_parse_addr_group(&sg, buf, buf_size); + buf += l; + buf_size -= l; + pim_parse_addr_ucast(&source, buf, buf_size); + sg.src = source.u.prefix4; + + upstream = pim_upstream_find(&sg); + if (!upstream) { + return 0; + } + + if (PIM_DEBUG_PIM_REG) + zlog_debug("Received Register stop for %s", upstream->sg_str); + + switch (upstream->reg_state) { + case PIM_REG_NOINFO: + case PIM_REG_PRUNE: + return 0; + break; + case PIM_REG_JOIN: + upstream->reg_state = PIM_REG_PRUNE; + pim_channel_del_oif(upstream->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_PIM); + pim_upstream_start_register_stop_timer(upstream, 0); + break; + case PIM_REG_JOIN_PENDING: + upstream->reg_state = PIM_REG_PRUNE; + pim_upstream_start_register_stop_timer(upstream, 0); + return 0; + break; + } + + return 0; } -void -pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct pim_rpf *rpg, int null_register, struct pim_upstream *up) +void pim_register_send(const uint8_t *buf, int buf_size, struct in_addr src, + struct pim_rpf *rpg, int null_register, + struct pim_upstream *up) { - unsigned char buffer[10000]; - unsigned char *b1; - struct pim_interface *pinfo; - struct interface *ifp; - - if (PIM_DEBUG_PIM_REG) - { - zlog_debug ("Sending %s %sRegister Packet to %s", - up->sg_str, null_register ? "NULL " : "", - inet_ntoa (rpg->rpf_addr.u.prefix4)); - } - - ifp = rpg->source_nexthop.interface; - if (!ifp) - { - if (PIM_DEBUG_PIM_REG) - zlog_debug ("%s: No interface to transmit register on", __PRETTY_FUNCTION__); - return; - } - pinfo = (struct pim_interface *)ifp->info; - if (!pinfo) { - if (PIM_DEBUG_PIM_REG) - zlog_debug("%s: Interface: %s not configured for pim to trasmit on!\n", __PRETTY_FUNCTION__, ifp->name); - return; - } - - if (PIM_DEBUG_PIM_REG) - { - char rp_str[INET_ADDRSTRLEN]; - strncpy (rp_str, inet_ntoa (rpg->rpf_addr.u.prefix4), INET_ADDRSTRLEN-1); - zlog_debug ("%s: Sending %s %sRegister Packet to %s on %s", - __PRETTY_FUNCTION__, up->sg_str, - null_register ? "NULL " : "", rp_str, ifp->name); - } - - memset(buffer, 0, 10000); - b1 = buffer + PIM_MSG_HEADER_LEN; - *b1 |= null_register << 6; - b1 = buffer + PIM_MSG_REGISTER_LEN; - - memcpy(b1, (const unsigned char *)buf, buf_size); - - pim_msg_build_header(buffer, buf_size + PIM_MSG_REGISTER_LEN, PIM_MSG_TYPE_REGISTER); - - ++pinfo->pim_ifstat_reg_send; - - if (pim_msg_send(pinfo->pim_sock_fd, - src, - rpg->rpf_addr.u.prefix4, - buffer, - buf_size + PIM_MSG_REGISTER_LEN, - ifp->name)) { - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: could not send PIM register message on interface %s", - __PRETTY_FUNCTION__, ifp->name); - } - return; - } + unsigned char buffer[10000]; + unsigned char *b1; + struct pim_interface *pinfo; + struct interface *ifp; + + if (PIM_DEBUG_PIM_REG) { + zlog_debug("Sending %s %sRegister Packet to %s", up->sg_str, + null_register ? "NULL " : "", + inet_ntoa(rpg->rpf_addr.u.prefix4)); + } + + ifp = rpg->source_nexthop.interface; + if (!ifp) { + if (PIM_DEBUG_PIM_REG) + zlog_debug("%s: No interface to transmit register on", + __PRETTY_FUNCTION__); + return; + } + pinfo = (struct pim_interface *)ifp->info; + if (!pinfo) { + if (PIM_DEBUG_PIM_REG) + zlog_debug( + "%s: Interface: %s not configured for pim to trasmit on!\n", + __PRETTY_FUNCTION__, ifp->name); + return; + } + + if (PIM_DEBUG_PIM_REG) { + char rp_str[INET_ADDRSTRLEN]; + strncpy(rp_str, inet_ntoa(rpg->rpf_addr.u.prefix4), + INET_ADDRSTRLEN - 1); + zlog_debug("%s: Sending %s %sRegister Packet to %s on %s", + __PRETTY_FUNCTION__, up->sg_str, + null_register ? "NULL " : "", rp_str, ifp->name); + } + + memset(buffer, 0, 10000); + b1 = buffer + PIM_MSG_HEADER_LEN; + *b1 |= null_register << 6; + b1 = buffer + PIM_MSG_REGISTER_LEN; + + memcpy(b1, (const unsigned char *)buf, buf_size); + + pim_msg_build_header(buffer, buf_size + PIM_MSG_REGISTER_LEN, + PIM_MSG_TYPE_REGISTER); + + ++pinfo->pim_ifstat_reg_send; + + if (pim_msg_send(pinfo->pim_sock_fd, src, rpg->rpf_addr.u.prefix4, + buffer, buf_size + PIM_MSG_REGISTER_LEN, ifp->name)) { + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug( + "%s: could not send PIM register message on interface %s", + __PRETTY_FUNCTION__, ifp->name); + } + return; + } } /* @@ -265,155 +259,160 @@ pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct * } * } */ -int -pim_register_recv (struct interface *ifp, - struct in_addr dest_addr, - struct in_addr src_addr, - uint8_t *tlv_buf, int tlv_buf_size) +int pim_register_recv(struct interface *ifp, struct in_addr dest_addr, + struct in_addr src_addr, uint8_t *tlv_buf, + int tlv_buf_size) { - int sentRegisterStop = 0; - struct ip *ip_hdr; - struct prefix_sg sg; - uint32_t *bits; - int i_am_rp = 0; - struct pim_interface *pim_ifp = NULL; + int sentRegisterStop = 0; + struct ip *ip_hdr; + struct prefix_sg sg; + uint32_t *bits; + int i_am_rp = 0; + struct pim_interface *pim_ifp = NULL; #define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4 - ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN); - - if (!pim_rp_check_is_my_ip_address (ip_hdr->ip_dst, dest_addr)) { - if (PIM_DEBUG_PIM_REG) { - char dest[INET_ADDRSTRLEN]; - - pim_inet4_dump ("", dest_addr, dest, sizeof(dest)); - zlog_debug ("%s: Received Register message for %s that I do not own", __func__, - dest); - } - return 0; - } - - pim_ifp = ifp->info; - zassert(pim_ifp); - ++pim_ifp->pim_ifstat_reg_recv; - - /* - * Please note this is not drawn to get the correct bit/data size - * - * The entirety of the REGISTER packet looks like this: - * ------------------------------------------------------------- - * | Ver | Type | Reserved | Checksum | - * |-----------------------------------------------------------| - * |B|N| Reserved 2 | - * |-----------------------------------------------------------| - * | Encap | IP HDR | - * | Mcast | | - * | Packet |--------------------------------------------------| - * | | Mcast Data | - * | | | - * ... - * - * tlv_buf when received from the caller points at the B bit - * We need to know the inner source and dest - */ - bits = (uint32_t *)tlv_buf; - - /* - * tlv_buf points to the start of the |B|N|... Reserved - * Line above. So we need to add 4 bytes to get to the - * start of the actual Encapsulated data. - */ - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = ip_hdr->ip_src; - sg.grp = ip_hdr->ip_dst; - - i_am_rp = I_am_RP (sg.grp); - - if (PIM_DEBUG_PIM_REG) - { - char src_str[INET_ADDRSTRLEN]; - - pim_inet4_dump ("", src_addr, src_str, sizeof (src_str)); - zlog_debug ("Received Register message(%s) from %s on %s, rp: %d", - pim_str_sg_dump (&sg), src_str, ifp->name, i_am_rp); - } - - if (i_am_rp && (dest_addr.s_addr == ((RP (sg.grp))->rpf_addr.u.prefix4.s_addr))) { - sentRegisterStop = 0; - - if (*bits & PIM_REGISTER_BORDER_BIT) { - struct in_addr pimbr = pim_br_get_pmbr (&sg); - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("%s: Received Register message with Border bit set", __func__); - - if (pimbr.s_addr == pim_br_unknown.s_addr) - pim_br_set_pmbr(&sg, src_addr); - else if (src_addr.s_addr != pimbr.s_addr) { - pim_register_stop_send (ifp, &sg, dest_addr, src_addr); - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug("%s: Sending register-Stop to %s and dropping mr. packet", - __func__, "Sender"); - /* Drop Packet Silently */ + ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN); + + if (!pim_rp_check_is_my_ip_address(ip_hdr->ip_dst, dest_addr)) { + if (PIM_DEBUG_PIM_REG) { + char dest[INET_ADDRSTRLEN]; + + pim_inet4_dump("", dest_addr, dest, sizeof(dest)); + zlog_debug( + "%s: Received Register message for %s that I do not own", + __func__, dest); + } + return 0; + } + + pim_ifp = ifp->info; + zassert(pim_ifp); + ++pim_ifp->pim_ifstat_reg_recv; + + /* + * Please note this is not drawn to get the correct bit/data size + * + * The entirety of the REGISTER packet looks like this: + * ------------------------------------------------------------- + * | Ver | Type | Reserved | Checksum | + * |-----------------------------------------------------------| + * |B|N| Reserved 2 | + * |-----------------------------------------------------------| + * | Encap | IP HDR | + * | Mcast | | + * | Packet |--------------------------------------------------| + * | | Mcast Data | + * | | | + * ... + * + * tlv_buf when received from the caller points at the B bit + * We need to know the inner source and dest + */ + bits = (uint32_t *)tlv_buf; + + /* + * tlv_buf points to the start of the |B|N|... Reserved + * Line above. So we need to add 4 bytes to get to the + * start of the actual Encapsulated data. + */ + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = ip_hdr->ip_src; + sg.grp = ip_hdr->ip_dst; + + i_am_rp = I_am_RP(sg.grp); + + if (PIM_DEBUG_PIM_REG) { + char src_str[INET_ADDRSTRLEN]; + + pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); + zlog_debug( + "Received Register message(%s) from %s on %s, rp: %d", + pim_str_sg_dump(&sg), src_str, ifp->name, i_am_rp); + } + + if (i_am_rp && (dest_addr.s_addr + == ((RP(sg.grp))->rpf_addr.u.prefix4.s_addr))) { + sentRegisterStop = 0; + + if (*bits & PIM_REGISTER_BORDER_BIT) { + struct in_addr pimbr = pim_br_get_pmbr(&sg); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "%s: Received Register message with Border bit set", + __func__); + + if (pimbr.s_addr == pim_br_unknown.s_addr) + pim_br_set_pmbr(&sg, src_addr); + else if (src_addr.s_addr != pimbr.s_addr) { + pim_register_stop_send(ifp, &sg, dest_addr, + src_addr); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug( + "%s: Sending register-Stop to %s and dropping mr. packet", + __func__, "Sender"); + /* Drop Packet Silently */ + return 0; + } + } + + struct pim_upstream *upstream = pim_upstream_find(&sg); + /* + * If we don't have a place to send ignore the packet + */ + if (!upstream) { + upstream = pim_upstream_add( + &sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, + __PRETTY_FUNCTION__); + if (!upstream) { + zlog_warn("Failure to create upstream state"); + return 1; + } + + upstream->upstream_register = src_addr; + } + + if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) + || ((SwitchToSptDesired(&sg)) + && pim_upstream_inherited_olist(upstream) == 0)) { + // pim_scan_individual_oil (upstream->channel_oil); + pim_register_stop_send(ifp, &sg, dest_addr, src_addr); + sentRegisterStop = 1; + } else { + if (PIM_DEBUG_PIM_REG) + zlog_debug("(%s) sptbit: %d", upstream->sg_str, + upstream->sptbit); + } + if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) + || (SwitchToSptDesired(&sg))) { + if (sentRegisterStop) { + pim_upstream_keep_alive_timer_start( + upstream, qpim_rp_keep_alive_time); + } else { + pim_upstream_keep_alive_timer_start( + upstream, qpim_keep_alive_time); + } + } + + if (!(upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) + && !(*bits & PIM_REGISTER_NR_BIT)) { + // decapsulate and forward the iner packet to + // inherited_olist(S,G,rpt) + // This is taken care of by the kernel for us + } + pim_upstream_msdp_reg_timer_start(upstream); + } else { + if (PIM_DEBUG_PIM_REG) { + if (!i_am_rp) + zlog_debug( + "Received Register packet for %s, Rejecting packet because I am not the RP configured for group", + pim_str_sg_dump(&sg)); + else + zlog_debug( + "Received Register packet for %s, Rejecting packet because the dst ip address is not the actual RP", + pim_str_sg_dump(&sg)); + } + pim_register_stop_send(ifp, &sg, dest_addr, src_addr); + } + return 0; - } - } - - struct pim_upstream *upstream = pim_upstream_find (&sg); - /* - * If we don't have a place to send ignore the packet - */ - if (!upstream) - { - upstream = pim_upstream_add (&sg, ifp, - PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, - __PRETTY_FUNCTION__); - if (!upstream) - { - zlog_warn ("Failure to create upstream state"); - return 1; - } - - upstream->upstream_register = src_addr; - } - - if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) || - ((SwitchToSptDesired(&sg)) && - pim_upstream_inherited_olist (upstream) == 0)) { - //pim_scan_individual_oil (upstream->channel_oil); - pim_register_stop_send (ifp, &sg, dest_addr, src_addr); - sentRegisterStop = 1; - } else { - if (PIM_DEBUG_PIM_REG) - zlog_debug ("(%s) sptbit: %d", upstream->sg_str, upstream->sptbit); - } - if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) || - (SwitchToSptDesired(&sg))) { - if (sentRegisterStop) { - pim_upstream_keep_alive_timer_start (upstream, qpim_rp_keep_alive_time); - } else { - pim_upstream_keep_alive_timer_start (upstream, qpim_keep_alive_time); - } - } - - if (!(upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) && - !(*bits & PIM_REGISTER_NR_BIT)) - { - //decapsulate and forward the iner packet to - //inherited_olist(S,G,rpt) - // This is taken care of by the kernel for us - } - pim_upstream_msdp_reg_timer_start(upstream); - } else { - if (PIM_DEBUG_PIM_REG) - { - if (!i_am_rp) - zlog_debug ("Received Register packet for %s, Rejecting packet because I am not the RP configured for group", - pim_str_sg_dump (&sg)); - else - zlog_debug ("Received Register packet for %s, Rejecting packet because the dst ip address is not the actual RP", - pim_str_sg_dump (&sg)); - } - pim_register_stop_send (ifp, &sg, dest_addr, src_addr); - } - - return 0; } diff --git a/pimd/pim_register.h b/pimd/pim_register.h index adb703c61..ad3deb2b2 100644 --- a/pimd/pim_register.h +++ b/pimd/pim_register.h @@ -30,15 +30,17 @@ #define PIM_MSG_REGISTER_LEN (8) #define PIM_MSG_REGISTER_STOP_LEN (4) -int pim_register_stop_recv (uint8_t *buf, int buf_size); - -int pim_register_recv (struct interface *ifp, - struct in_addr dest_addr, - struct in_addr src_addr, - uint8_t *tlv_buf, int tlv_buf_size); - -void pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct pim_rpf *rpg, int null_register, struct pim_upstream *up); -void pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg, struct in_addr src, struct in_addr originator); -void pim_register_join (struct pim_upstream *up); +int pim_register_stop_recv(uint8_t *buf, int buf_size); + +int pim_register_recv(struct interface *ifp, struct in_addr dest_addr, + struct in_addr src_addr, uint8_t *tlv_buf, + int tlv_buf_size); + +void pim_register_send(const uint8_t *buf, int buf_size, struct in_addr src, + struct pim_rpf *rpg, int null_register, + struct pim_upstream *up); +void pim_register_stop_send(struct interface *ifp, struct prefix_sg *sg, + struct in_addr src, struct in_addr originator); +void pim_register_join(struct pim_upstream *up); #endif diff --git a/pimd/pim_routemap.c b/pimd/pim_routemap.c index 20c716c3e..6d06229b9 100644 --- a/pimd/pim_routemap.c +++ b/pimd/pim_routemap.c @@ -27,55 +27,49 @@ #include "pimd.h" -static void -pim_route_map_mark_update (const char *rmap_name) +static void pim_route_map_mark_update(const char *rmap_name) { - // placeholder - return; + // placeholder + return; } -static void -pim_route_map_add (const char *rmap_name) +static void pim_route_map_add(const char *rmap_name) { - if (route_map_mark_updated(rmap_name, 0) == 0) - pim_route_map_mark_update(rmap_name); + if (route_map_mark_updated(rmap_name, 0) == 0) + pim_route_map_mark_update(rmap_name); - route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); } -static void -pim_route_map_delete (const char *rmap_name) +static void pim_route_map_delete(const char *rmap_name) { - if (route_map_mark_updated(rmap_name, 1) == 0) - pim_route_map_mark_update(rmap_name); + if (route_map_mark_updated(rmap_name, 1) == 0) + pim_route_map_mark_update(rmap_name); - route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED); + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED); } -static void -pim_route_map_event (route_map_event_t event, const char *rmap_name) +static void pim_route_map_event(route_map_event_t event, const char *rmap_name) { - if (route_map_mark_updated(rmap_name, 0) == 0) - pim_route_map_mark_update(rmap_name); + if (route_map_mark_updated(rmap_name, 0) == 0) + pim_route_map_mark_update(rmap_name); - route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); } -void -pim_route_map_init (void) +void pim_route_map_init(void) { - route_map_init (); + route_map_init(); - route_map_add_hook (pim_route_map_add); - route_map_delete_hook (pim_route_map_delete); - route_map_event_hook (pim_route_map_event); + route_map_add_hook(pim_route_map_add); + route_map_delete_hook(pim_route_map_delete); + route_map_event_hook(pim_route_map_event); } -void -pim_route_map_terminate (void) +void pim_route_map_terminate(void) { - route_map_add_hook (NULL); - route_map_delete_hook (NULL); - route_map_event_hook (NULL); - route_map_finish(); + route_map_add_hook(NULL); + route_map_delete_hook(NULL); + route_map_event_hook(NULL); + route_map_finish(); } diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 28300dbdf..2fe0143a8 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -48,158 +48,147 @@ static struct list *qpim_rp_list = NULL; static struct rp_info *tail = NULL; -static void -pim_rp_info_free (struct rp_info *rp_info) +static void pim_rp_info_free(struct rp_info *rp_info) { - XFREE (MTYPE_PIM_RP, rp_info); + XFREE(MTYPE_PIM_RP, rp_info); } -int -pim_rp_list_cmp (void *v1, void *v2) +int pim_rp_list_cmp(void *v1, void *v2) { - struct rp_info *rp1 = (struct rp_info *)v1; - struct rp_info *rp2 = (struct rp_info *)v2; - - /* - * Sort by RP IP address - */ - if (rp1->rp.rpf_addr.u.prefix4.s_addr < rp2->rp.rpf_addr.u.prefix4.s_addr) - return -1; - - if (rp1->rp.rpf_addr.u.prefix4.s_addr > rp2->rp.rpf_addr.u.prefix4.s_addr) - return 1; - - /* - * Sort by group IP address - */ - if (rp1->group.u.prefix4.s_addr < rp2->group.u.prefix4.s_addr) - return -1; - - if (rp1->group.u.prefix4.s_addr > rp2->group.u.prefix4.s_addr) - return 1; - - return 0; + struct rp_info *rp1 = (struct rp_info *)v1; + struct rp_info *rp2 = (struct rp_info *)v2; + + /* + * Sort by RP IP address + */ + if (rp1->rp.rpf_addr.u.prefix4.s_addr + < rp2->rp.rpf_addr.u.prefix4.s_addr) + return -1; + + if (rp1->rp.rpf_addr.u.prefix4.s_addr + > rp2->rp.rpf_addr.u.prefix4.s_addr) + return 1; + + /* + * Sort by group IP address + */ + if (rp1->group.u.prefix4.s_addr < rp2->group.u.prefix4.s_addr) + return -1; + + if (rp1->group.u.prefix4.s_addr > rp2->group.u.prefix4.s_addr) + return 1; + + return 0; } -void -pim_rp_init (void) +void pim_rp_init(void) { - struct rp_info *rp_info; + struct rp_info *rp_info; - qpim_rp_list = list_new (); - qpim_rp_list->del = (void (*)(void *))pim_rp_info_free; - qpim_rp_list->cmp = pim_rp_list_cmp; + qpim_rp_list = list_new(); + qpim_rp_list->del = (void (*)(void *))pim_rp_info_free; + qpim_rp_list->cmp = pim_rp_list_cmp; - rp_info = XCALLOC (MTYPE_PIM_RP, sizeof (*rp_info)); + rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info)); - if (!rp_info) - return; + if (!rp_info) + return; - str2prefix ("224.0.0.0/4", &rp_info->group); - rp_info->group.family = AF_INET; - rp_info->rp.rpf_addr.family = AF_INET; - rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN; - rp_info->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; - tail = rp_info; + str2prefix("224.0.0.0/4", &rp_info->group); + rp_info->group.family = AF_INET; + rp_info->rp.rpf_addr.family = AF_INET; + rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN; + rp_info->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; + tail = rp_info; - listnode_add (qpim_rp_list, rp_info); + listnode_add(qpim_rp_list, rp_info); } -void -pim_rp_free (void) +void pim_rp_free(void) { - if (qpim_rp_list) - list_delete (qpim_rp_list); - qpim_rp_list = NULL; + if (qpim_rp_list) + list_delete(qpim_rp_list); + qpim_rp_list = NULL; } /* * Given an RP's prefix-list, return the RP's rp_info for that prefix-list */ -static struct rp_info * -pim_rp_find_prefix_list (struct in_addr rp, const char *plist) +static struct rp_info *pim_rp_find_prefix_list(struct in_addr rp, + const char *plist) { - struct listnode *node; - struct rp_info *rp_info; - - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) - { - if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr && - rp_info->plist && strcmp(rp_info->plist, plist) == 0) - { - return rp_info; - } - } - - return NULL; + struct listnode *node; + struct rp_info *rp_info; + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr + && rp_info->plist && strcmp(rp_info->plist, plist) == 0) { + return rp_info; + } + } + + return NULL; } /* * Return true if plist is used by any rp_info */ -static int -pim_rp_prefix_list_used (const char *plist) +static int pim_rp_prefix_list_used(const char *plist) { - struct listnode *node; - struct rp_info *rp_info; - - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) - { - if (rp_info->plist && strcmp(rp_info->plist, plist) == 0) - { - return 1; - } - } - - return 0; + struct listnode *node; + struct rp_info *rp_info; + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (rp_info->plist && strcmp(rp_info->plist, plist) == 0) { + return 1; + } + } + + return 0; } /* - * Given an RP's address, return the RP's rp_info that is an exact match for 'group' + * Given an RP's address, return the RP's rp_info that is an exact match for + * 'group' */ -static struct rp_info * -pim_rp_find_exact (struct in_addr rp, struct prefix *group) +static struct rp_info *pim_rp_find_exact(struct in_addr rp, + struct prefix *group) { - struct listnode *node; - struct rp_info *rp_info; + struct listnode *node; + struct rp_info *rp_info; - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) - { - if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr && - prefix_same (&rp_info->group, group)) - return rp_info; - } + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr + && prefix_same(&rp_info->group, group)) + return rp_info; + } - return NULL; + return NULL; } /* * Given a group, return the rp_info for that group */ -static struct rp_info * -pim_rp_find_match_group (struct prefix *group) +static struct rp_info *pim_rp_find_match_group(struct prefix *group) { - struct listnode *node; - struct rp_info *rp_info; - struct prefix_list *plist; - - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) - { - if (rp_info->plist) - { - plist = prefix_list_lookup (AFI_IP, rp_info->plist); - - if (plist && prefix_list_apply (plist, group) == PREFIX_PERMIT) - return rp_info; - } - else - { - if (prefix_match (&rp_info->group, group)) - return rp_info; - } - } - - return NULL; + struct listnode *node; + struct rp_info *rp_info; + struct prefix_list *plist; + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (rp_info->plist) { + plist = prefix_list_lookup(AFI_IP, rp_info->plist); + + if (plist + && prefix_list_apply(plist, group) == PREFIX_PERMIT) + return rp_info; + } else { + if (prefix_match(&rp_info->group, group)) + return rp_info; + } + } + + return NULL; } /* @@ -209,480 +198,475 @@ pim_rp_find_match_group (struct prefix *group) * * This is a placeholder function for now. */ -static void -pim_rp_refresh_group_to_rp_mapping() +static void pim_rp_refresh_group_to_rp_mapping() { - pim_msdp_i_am_rp_changed(); + pim_msdp_i_am_rp_changed(); } -void -pim_rp_prefix_list_update (struct prefix_list *plist) +void pim_rp_prefix_list_update(struct prefix_list *plist) { - struct listnode *node; - struct rp_info *rp_info; - int refresh_needed = 0; - - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) - { - if (rp_info->plist && strcmp(rp_info->plist, prefix_list_name (plist)) == 0) - { - refresh_needed = 1; - break; - } - } - - if (refresh_needed) - pim_rp_refresh_group_to_rp_mapping(); + struct listnode *node; + struct rp_info *rp_info; + int refresh_needed = 0; + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (rp_info->plist + && strcmp(rp_info->plist, prefix_list_name(plist)) == 0) { + refresh_needed = 1; + break; + } + } + + if (refresh_needed) + pim_rp_refresh_group_to_rp_mapping(); } -static int -pim_rp_check_interface_addrs(struct rp_info *rp_info, - struct pim_interface *pim_ifp) +static int pim_rp_check_interface_addrs(struct rp_info *rp_info, + struct pim_interface *pim_ifp) { - struct listnode *node; - struct pim_secondary_addr *sec_addr; + struct listnode *node; + struct pim_secondary_addr *sec_addr; - if (pim_ifp->primary_address.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr) - return 1; + if (pim_ifp->primary_address.s_addr + == rp_info->rp.rpf_addr.u.prefix4.s_addr) + return 1; - if (!pim_ifp->sec_addr_list) { - return 0; - } + if (!pim_ifp->sec_addr_list) { + return 0; + } - for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { - if (prefix_same(&sec_addr->addr, &rp_info->rp.rpf_addr)) { - return 1; - } - } + for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { + if (prefix_same(&sec_addr->addr, &rp_info->rp.rpf_addr)) { + return 1; + } + } - return 0; + return 0; } -static void -pim_rp_check_interfaces (struct rp_info *rp_info) +static void pim_rp_check_interfaces(struct rp_info *rp_info) { - struct listnode *node; - struct interface *ifp; + struct listnode *node; + struct interface *ifp; - rp_info->i_am_rp = 0; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - struct pim_interface *pim_ifp = ifp->info; + rp_info->i_am_rp = 0; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + struct pim_interface *pim_ifp = ifp->info; - if (!pim_ifp) - continue; + if (!pim_ifp) + continue; - if (pim_rp_check_interface_addrs(rp_info, pim_ifp)) { - rp_info->i_am_rp = 1; - } - } + if (pim_rp_check_interface_addrs(rp_info, pim_ifp)) { + rp_info->i_am_rp = 1; + } + } } -int -pim_rp_new (const char *rp, const char *group_range, const char *plist) +int pim_rp_new(const char *rp, const char *group_range, const char *plist) { - int result = 0; - struct rp_info *rp_info; - struct rp_info *rp_all; - struct prefix group_all; - struct listnode *node, *nnode; - struct rp_info *tmp_rp_info; - char buffer[BUFSIZ]; - struct prefix nht_p; - struct pim_nexthop_cache pnc; - - rp_info = XCALLOC (MTYPE_PIM_RP, sizeof (*rp_info)); - if (!rp_info) - return PIM_MALLOC_FAIL; - - if (group_range == NULL) - result = str2prefix ("224.0.0.0/4", &rp_info->group); - else - result = str2prefix (group_range, &rp_info->group); - - if (!result) - { - XFREE (MTYPE_PIM_RP, rp_info); - return PIM_GROUP_BAD_ADDRESS; - } - - rp_info->rp.rpf_addr.family = AF_INET; - rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN; - result = inet_pton (rp_info->rp.rpf_addr.family, rp, &rp_info->rp.rpf_addr.u.prefix4); - - if (result <= 0) - { - XFREE (MTYPE_PIM_RP, rp_info); - return PIM_RP_BAD_ADDRESS; - } - - if (plist) - { - /* - * Return if the prefix-list is already configured for this RP - */ - if (pim_rp_find_prefix_list (rp_info->rp.rpf_addr.u.prefix4, plist)) - { - XFREE (MTYPE_PIM_RP, rp_info); - return PIM_SUCCESS; - } - - /* - * Barf if the prefix-list is already configured for an RP - */ - if (pim_rp_prefix_list_used (plist)) - { - XFREE (MTYPE_PIM_RP, rp_info); - return PIM_RP_PFXLIST_IN_USE; - } - - /* - * Free any existing rp_info entries for this RP - */ - for (ALL_LIST_ELEMENTS (qpim_rp_list, node, nnode, tmp_rp_info)) - { - if (rp_info->rp.rpf_addr.u.prefix4.s_addr == tmp_rp_info->rp.rpf_addr.u.prefix4.s_addr) - { - if (tmp_rp_info->plist) - pim_rp_del (rp, NULL, tmp_rp_info->plist); - else - pim_rp_del (rp, prefix2str(&tmp_rp_info->group, buffer, BUFSIZ), NULL); - } - } - - rp_info->plist = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist); - } - else - { - str2prefix ("224.0.0.0/4", &group_all); - rp_all = pim_rp_find_match_group(&group_all); - - /* - * Barf if group is a non-multicast subnet - */ - if (! prefix_match (&rp_all->group, &rp_info->group)) - { - XFREE (MTYPE_PIM_RP, rp_info); - return PIM_GROUP_BAD_ADDRESS; - } - - /* - * Remove any prefix-list rp_info entries for this RP - */ - for (ALL_LIST_ELEMENTS (qpim_rp_list, node, nnode, tmp_rp_info)) - { - if (tmp_rp_info->plist && - rp_info->rp.rpf_addr.u.prefix4.s_addr == tmp_rp_info->rp.rpf_addr.u.prefix4.s_addr) - { - pim_rp_del (rp, NULL, tmp_rp_info->plist); - } - } - - /* - * Take over the 224.0.0.0/4 group if the rp is INADDR_NONE - */ - if (prefix_same (&rp_all->group, &rp_info->group) && - pim_rpf_addr_is_inaddr_none (&rp_all->rp)) - { - rp_all->rp.rpf_addr = rp_info->rp.rpf_addr; - XFREE (MTYPE_PIM_RP, rp_info); - - /* Register addr with Zebra NHT */ - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = rp_all->rp.rpf_addr.u.prefix4; //RP address - if (PIM_DEBUG_PIM_TRACE) - { - char buf[PREFIX2STR_BUFFER]; - char buf1[PREFIX2STR_BUFFER]; - prefix2str (&nht_p, buf, sizeof (buf)); - prefix2str (&rp_all->group, buf1, sizeof (buf1)); - zlog_debug ("%s: NHT Register rp_all addr %s grp %s ", - __PRETTY_FUNCTION__, buf, buf1); - } - memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); - if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_all, &pnc)) == 1) - { - //Compute PIM RPF using Cached nexthop - if ((pim_ecmp_nexthop_search (&pnc, &rp_all->rp.source_nexthop, - &nht_p, &rp_all->group, 1)) != 0) - return PIM_RP_NO_PATH; - } - else - { - if (pim_nexthop_lookup (&rp_all->rp.source_nexthop, rp_all->rp.rpf_addr.u.prefix4, 1) != 0) - return PIM_RP_NO_PATH; - } - pim_rp_check_interfaces (rp_all); - pim_rp_refresh_group_to_rp_mapping (); - return PIM_SUCCESS; - } - - /* - * Return if the group is already configured for this RP - */ - if (pim_rp_find_exact (rp_info->rp.rpf_addr.u.prefix4, &rp_info->group)) - { - XFREE (MTYPE_PIM_RP, rp_info); - return PIM_SUCCESS; - } - - /* - * Barf if this group is already covered by some other RP - */ - tmp_rp_info = pim_rp_find_match_group (&rp_info->group); - - if (tmp_rp_info) - { - if (tmp_rp_info->plist) - { - XFREE (MTYPE_PIM_RP, rp_info); - return PIM_GROUP_PFXLIST_OVERLAP; - } - else - { - /* - * If the only RP that covers this group is an RP configured for - * 224.0.0.0/4 that is fine, ignore that one. For all others - * though we must return PIM_GROUP_OVERLAP - */ - if (! prefix_same (&group_all, &tmp_rp_info->group)) - { - XFREE (MTYPE_PIM_RP, rp_info); - return PIM_GROUP_OVERLAP; - } - } - } - } - - listnode_add_sort (qpim_rp_list, rp_info); - - /* Register addr with Zebra NHT */ - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; - if (PIM_DEBUG_PIM_TRACE) - { - char buf[PREFIX2STR_BUFFER]; - char buf1[PREFIX2STR_BUFFER]; - prefix2str (&nht_p, buf, sizeof (buf)); - prefix2str (&rp_info->group, buf1, sizeof (buf1)); - zlog_debug ("%s: NHT Register RP addr %s grp %s with Zebra ", - __PRETTY_FUNCTION__, buf, buf1); - } - - memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); - if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1) - { - //Compute PIM RPF using Cached nexthop - if (pim_ecmp_nexthop_search (&pnc, &rp_info->rp.source_nexthop, - &nht_p, &rp_info->group, 1) != 0) - return PIM_RP_NO_PATH; - } - else - { - if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1) != 0) - return PIM_RP_NO_PATH; - } - - pim_rp_check_interfaces (rp_info); - pim_rp_refresh_group_to_rp_mapping (); - return PIM_SUCCESS; + int result = 0; + struct rp_info *rp_info; + struct rp_info *rp_all; + struct prefix group_all; + struct listnode *node, *nnode; + struct rp_info *tmp_rp_info; + char buffer[BUFSIZ]; + struct prefix nht_p; + struct pim_nexthop_cache pnc; + + rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info)); + if (!rp_info) + return PIM_MALLOC_FAIL; + + if (group_range == NULL) + result = str2prefix("224.0.0.0/4", &rp_info->group); + else + result = str2prefix(group_range, &rp_info->group); + + if (!result) { + XFREE(MTYPE_PIM_RP, rp_info); + return PIM_GROUP_BAD_ADDRESS; + } + + rp_info->rp.rpf_addr.family = AF_INET; + rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN; + result = inet_pton(rp_info->rp.rpf_addr.family, rp, + &rp_info->rp.rpf_addr.u.prefix4); + + if (result <= 0) { + XFREE(MTYPE_PIM_RP, rp_info); + return PIM_RP_BAD_ADDRESS; + } + + if (plist) { + /* + * Return if the prefix-list is already configured for this RP + */ + if (pim_rp_find_prefix_list(rp_info->rp.rpf_addr.u.prefix4, + plist)) { + XFREE(MTYPE_PIM_RP, rp_info); + return PIM_SUCCESS; + } + + /* + * Barf if the prefix-list is already configured for an RP + */ + if (pim_rp_prefix_list_used(plist)) { + XFREE(MTYPE_PIM_RP, rp_info); + return PIM_RP_PFXLIST_IN_USE; + } + + /* + * Free any existing rp_info entries for this RP + */ + for (ALL_LIST_ELEMENTS(qpim_rp_list, node, nnode, + tmp_rp_info)) { + if (rp_info->rp.rpf_addr.u.prefix4.s_addr + == tmp_rp_info->rp.rpf_addr.u.prefix4.s_addr) { + if (tmp_rp_info->plist) + pim_rp_del(rp, NULL, + tmp_rp_info->plist); + else + pim_rp_del( + rp, + prefix2str(&tmp_rp_info->group, + buffer, BUFSIZ), + NULL); + } + } + + rp_info->plist = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist); + } else { + str2prefix("224.0.0.0/4", &group_all); + rp_all = pim_rp_find_match_group(&group_all); + + /* + * Barf if group is a non-multicast subnet + */ + if (!prefix_match(&rp_all->group, &rp_info->group)) { + XFREE(MTYPE_PIM_RP, rp_info); + return PIM_GROUP_BAD_ADDRESS; + } + + /* + * Remove any prefix-list rp_info entries for this RP + */ + for (ALL_LIST_ELEMENTS(qpim_rp_list, node, nnode, + tmp_rp_info)) { + if (tmp_rp_info->plist + && rp_info->rp.rpf_addr.u.prefix4.s_addr + == tmp_rp_info->rp.rpf_addr.u.prefix4 + .s_addr) { + pim_rp_del(rp, NULL, tmp_rp_info->plist); + } + } + + /* + * Take over the 224.0.0.0/4 group if the rp is INADDR_NONE + */ + if (prefix_same(&rp_all->group, &rp_info->group) + && pim_rpf_addr_is_inaddr_none(&rp_all->rp)) { + rp_all->rp.rpf_addr = rp_info->rp.rpf_addr; + XFREE(MTYPE_PIM_RP, rp_info); + + /* Register addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = + rp_all->rp.rpf_addr.u.prefix4; // RP address + if (PIM_DEBUG_PIM_TRACE) { + char buf[PREFIX2STR_BUFFER]; + char buf1[PREFIX2STR_BUFFER]; + prefix2str(&nht_p, buf, sizeof(buf)); + prefix2str(&rp_all->group, buf1, sizeof(buf1)); + zlog_debug( + "%s: NHT Register rp_all addr %s grp %s ", + __PRETTY_FUNCTION__, buf, buf1); + } + memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); + if ((pim_find_or_track_nexthop(&nht_p, NULL, rp_all, + &pnc)) + == 1) { + // Compute PIM RPF using Cached nexthop + if ((pim_ecmp_nexthop_search( + &pnc, &rp_all->rp.source_nexthop, + &nht_p, &rp_all->group, 1)) + != 0) + return PIM_RP_NO_PATH; + } else { + if (pim_nexthop_lookup( + &rp_all->rp.source_nexthop, + rp_all->rp.rpf_addr.u.prefix4, 1) + != 0) + return PIM_RP_NO_PATH; + } + pim_rp_check_interfaces(rp_all); + pim_rp_refresh_group_to_rp_mapping(); + return PIM_SUCCESS; + } + + /* + * Return if the group is already configured for this RP + */ + if (pim_rp_find_exact(rp_info->rp.rpf_addr.u.prefix4, + &rp_info->group)) { + XFREE(MTYPE_PIM_RP, rp_info); + return PIM_SUCCESS; + } + + /* + * Barf if this group is already covered by some other RP + */ + tmp_rp_info = pim_rp_find_match_group(&rp_info->group); + + if (tmp_rp_info) { + if (tmp_rp_info->plist) { + XFREE(MTYPE_PIM_RP, rp_info); + return PIM_GROUP_PFXLIST_OVERLAP; + } else { + /* + * If the only RP that covers this group is an + * RP configured for + * 224.0.0.0/4 that is fine, ignore that one. + * For all others + * though we must return PIM_GROUP_OVERLAP + */ + if (!prefix_same(&group_all, + &tmp_rp_info->group)) { + XFREE(MTYPE_PIM_RP, rp_info); + return PIM_GROUP_OVERLAP; + } + } + } + } + + listnode_add_sort(qpim_rp_list, rp_info); + + /* Register addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; + if (PIM_DEBUG_PIM_TRACE) { + char buf[PREFIX2STR_BUFFER]; + char buf1[PREFIX2STR_BUFFER]; + prefix2str(&nht_p, buf, sizeof(buf)); + prefix2str(&rp_info->group, buf1, sizeof(buf1)); + zlog_debug("%s: NHT Register RP addr %s grp %s with Zebra ", + __PRETTY_FUNCTION__, buf, buf1); + } + + memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); + if ((pim_find_or_track_nexthop(&nht_p, NULL, rp_info, &pnc)) == 1) { + // Compute PIM RPF using Cached nexthop + if (pim_ecmp_nexthop_search(&pnc, &rp_info->rp.source_nexthop, + &nht_p, &rp_info->group, 1) + != 0) + return PIM_RP_NO_PATH; + } else { + if (pim_nexthop_lookup(&rp_info->rp.source_nexthop, + rp_info->rp.rpf_addr.u.prefix4, 1) + != 0) + return PIM_RP_NO_PATH; + } + + pim_rp_check_interfaces(rp_info); + pim_rp_refresh_group_to_rp_mapping(); + return PIM_SUCCESS; } -int -pim_rp_del (const char *rp, const char *group_range, const char *plist) +int pim_rp_del(const char *rp, const char *group_range, const char *plist) { - struct prefix group; - struct in_addr rp_addr; - struct prefix g_all; - struct rp_info *rp_info; - struct rp_info *rp_all; - int result; - struct prefix nht_p; - - if (group_range == NULL) - result = str2prefix ("224.0.0.0/4", &group); - else - result = str2prefix (group_range, &group); - - if (!result) - return PIM_GROUP_BAD_ADDRESS; - - result = inet_pton (AF_INET, rp, &rp_addr); - if (result <= 0) - return PIM_RP_BAD_ADDRESS; - - if (plist) - rp_info = pim_rp_find_prefix_list (rp_addr, plist); - else - rp_info = pim_rp_find_exact (rp_addr, &group); - - if (!rp_info) - return PIM_RP_NOT_FOUND; - - if (rp_info->plist) - { - XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist); - rp_info->plist = NULL; - } - - /* Deregister addr with Zebra NHT */ - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; - if (PIM_DEBUG_PIM_TRACE) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str (&nht_p, buf, sizeof (buf)); - zlog_debug ("%s: Deregister RP addr %s with Zebra ", __PRETTY_FUNCTION__, - buf); - } - pim_delete_tracked_nexthop (&nht_p, NULL, rp_info); - - str2prefix ("224.0.0.0/4", &g_all); - rp_all = pim_rp_find_match_group (&g_all); - - if (rp_all == rp_info) - { - rp_all->rp.rpf_addr.family = AF_INET; - rp_all->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; - rp_all->i_am_rp = 0; - return PIM_SUCCESS; - } - - listnode_delete (qpim_rp_list, rp_info); - pim_rp_refresh_group_to_rp_mapping (); - return PIM_SUCCESS; + struct prefix group; + struct in_addr rp_addr; + struct prefix g_all; + struct rp_info *rp_info; + struct rp_info *rp_all; + int result; + struct prefix nht_p; + + if (group_range == NULL) + result = str2prefix("224.0.0.0/4", &group); + else + result = str2prefix(group_range, &group); + + if (!result) + return PIM_GROUP_BAD_ADDRESS; + + result = inet_pton(AF_INET, rp, &rp_addr); + if (result <= 0) + return PIM_RP_BAD_ADDRESS; + + if (plist) + rp_info = pim_rp_find_prefix_list(rp_addr, plist); + else + rp_info = pim_rp_find_exact(rp_addr, &group); + + if (!rp_info) + return PIM_RP_NOT_FOUND; + + if (rp_info->plist) { + XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist); + rp_info->plist = NULL; + } + + /* Deregister addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; + if (PIM_DEBUG_PIM_TRACE) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&nht_p, buf, sizeof(buf)); + zlog_debug("%s: Deregister RP addr %s with Zebra ", + __PRETTY_FUNCTION__, buf); + } + pim_delete_tracked_nexthop(&nht_p, NULL, rp_info); + + str2prefix("224.0.0.0/4", &g_all); + rp_all = pim_rp_find_match_group(&g_all); + + if (rp_all == rp_info) { + rp_all->rp.rpf_addr.family = AF_INET; + rp_all->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; + rp_all->i_am_rp = 0; + return PIM_SUCCESS; + } + + listnode_delete(qpim_rp_list, rp_info); + pim_rp_refresh_group_to_rp_mapping(); + return PIM_SUCCESS; } -int -pim_rp_setup (void) +int pim_rp_setup(void) { - struct listnode *node; - struct rp_info *rp_info; - int ret = 0; - struct prefix nht_p; - struct pim_nexthop_cache pnc; - - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) - { - if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) - continue; - - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; - memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); - if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1) - { - //Compute PIM RPF using Cached nexthop - if ((pim_ecmp_nexthop_search (&pnc, &rp_info->rp.source_nexthop, - &nht_p, &rp_info->group, 1)) != 0) - ret++; - } - else - { - if (PIM_DEBUG_ZEBRA) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str (&nht_p, buf, sizeof (buf)); - zlog_debug ("%s: NHT Local Nexthop not found for RP %s ", - __PRETTY_FUNCTION__, buf); - } - if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1) != 0) - { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("Unable to lookup nexthop for rp specified"); - ret++; - } - } - } - - if (ret) - return 0; - - return 1; + struct listnode *node; + struct rp_info *rp_info; + int ret = 0; + struct prefix nht_p; + struct pim_nexthop_cache pnc; + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) + continue; + + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; + memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); + if ((pim_find_or_track_nexthop(&nht_p, NULL, rp_info, &pnc)) + == 1) { + // Compute PIM RPF using Cached nexthop + if ((pim_ecmp_nexthop_search( + &pnc, &rp_info->rp.source_nexthop, &nht_p, + &rp_info->group, 1)) + != 0) + ret++; + } else { + if (PIM_DEBUG_ZEBRA) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&nht_p, buf, sizeof(buf)); + zlog_debug( + "%s: NHT Local Nexthop not found for RP %s ", + __PRETTY_FUNCTION__, buf); + } + if (pim_nexthop_lookup(&rp_info->rp.source_nexthop, + rp_info->rp.rpf_addr.u.prefix4, + 1) + != 0) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug( + "Unable to lookup nexthop for rp specified"); + ret++; + } + } + } + + if (ret) + return 0; + + return 1; } /* * Checks to see if we should elect ourself the actual RP when new if * addresses are added against an interface. */ -void -pim_rp_check_on_if_add(struct pim_interface *pim_ifp) +void pim_rp_check_on_if_add(struct pim_interface *pim_ifp) { - struct listnode *node; - struct rp_info *rp_info; - bool i_am_rp_changed = false; - - if (qpim_rp_list == NULL) - return; - - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) { - if (pim_rpf_addr_is_inaddr_none (&rp_info->rp)) - continue; - - /* if i_am_rp is already set nothing to be done (adding new addresses - * is not going to make a difference). */ - if (rp_info->i_am_rp) { - continue; - } - - if (pim_rp_check_interface_addrs(rp_info, pim_ifp)) { - i_am_rp_changed = true; - rp_info->i_am_rp = 1; - if (PIM_DEBUG_ZEBRA) { - char rp[PREFIX_STRLEN]; - pim_addr_dump("", &rp_info->rp.rpf_addr, rp, sizeof(rp)); - zlog_debug("%s: %s: i am rp", __func__, rp); - } - } - } - - if (i_am_rp_changed) { - pim_msdp_i_am_rp_changed(); - } + struct listnode *node; + struct rp_info *rp_info; + bool i_am_rp_changed = false; + + if (qpim_rp_list == NULL) + return; + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (pim_rpf_addr_is_inaddr_none(&rp_info->rp)) + continue; + + /* if i_am_rp is already set nothing to be done (adding new + * addresses + * is not going to make a difference). */ + if (rp_info->i_am_rp) { + continue; + } + + if (pim_rp_check_interface_addrs(rp_info, pim_ifp)) { + i_am_rp_changed = true; + rp_info->i_am_rp = 1; + if (PIM_DEBUG_ZEBRA) { + char rp[PREFIX_STRLEN]; + pim_addr_dump("", &rp_info->rp.rpf_addr, + rp, sizeof(rp)); + zlog_debug("%s: %s: i am rp", __func__, rp); + } + } + } + + if (i_am_rp_changed) { + pim_msdp_i_am_rp_changed(); + } } /* up-optimized re-evaluation of "i_am_rp". this is used when ifaddresses * are removed. Removing numbers is an uncommon event in an active network * so I have made no attempt to optimize it. */ -void -pim_i_am_rp_re_evaluate(void) +void pim_i_am_rp_re_evaluate(void) { - struct listnode *node; - struct rp_info *rp_info; - bool i_am_rp_changed = false; - int old_i_am_rp; - - if (qpim_rp_list == NULL) - return; - - for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { - if (pim_rpf_addr_is_inaddr_none(&rp_info->rp)) - continue; - - old_i_am_rp = rp_info->i_am_rp; - pim_rp_check_interfaces(rp_info); - - if (old_i_am_rp != rp_info->i_am_rp) { - i_am_rp_changed = true; - if (PIM_DEBUG_ZEBRA) { - char rp[PREFIX_STRLEN]; - pim_addr_dump("", &rp_info->rp.rpf_addr, rp, sizeof(rp)); - if (rp_info->i_am_rp) { - zlog_debug("%s: %s: i am rp", __func__, rp); - } else { - zlog_debug("%s: %s: i am no longer rp", __func__, rp); - } - } - } - } - - if (i_am_rp_changed) { - pim_msdp_i_am_rp_changed(); - } + struct listnode *node; + struct rp_info *rp_info; + bool i_am_rp_changed = false; + int old_i_am_rp; + + if (qpim_rp_list == NULL) + return; + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (pim_rpf_addr_is_inaddr_none(&rp_info->rp)) + continue; + + old_i_am_rp = rp_info->i_am_rp; + pim_rp_check_interfaces(rp_info); + + if (old_i_am_rp != rp_info->i_am_rp) { + i_am_rp_changed = true; + if (PIM_DEBUG_ZEBRA) { + char rp[PREFIX_STRLEN]; + pim_addr_dump("", &rp_info->rp.rpf_addr, + rp, sizeof(rp)); + if (rp_info->i_am_rp) { + zlog_debug("%s: %s: i am rp", __func__, + rp); + } else { + zlog_debug("%s: %s: i am no longer rp", + __func__, rp); + } + } + } + } + + if (i_am_rp_changed) { + pim_msdp_i_am_rp_changed(); + } } /* @@ -691,23 +675,22 @@ pim_i_am_rp_re_evaluate(void) * * Since we only have static RP, all groups are part of this RP */ -int -pim_rp_i_am_rp (struct in_addr group) +int pim_rp_i_am_rp(struct in_addr group) { - struct prefix g; - struct rp_info *rp_info; + struct prefix g; + struct rp_info *rp_info; - memset (&g, 0, sizeof (g)); - g.family = AF_INET; - g.prefixlen = 32; - g.u.prefix4 = group; + memset(&g, 0, sizeof(g)); + g.family = AF_INET; + g.prefixlen = 32; + g.u.prefix4 = group; - rp_info = pim_rp_find_match_group (&g); + rp_info = pim_rp_find_match_group(&g); - if (rp_info) - return rp_info->i_am_rp; + if (rp_info) + return rp_info->i_am_rp; - return 0; + return 0; } /* @@ -715,62 +698,60 @@ pim_rp_i_am_rp (struct in_addr group) * * Return the RP that the Group belongs too. */ -struct pim_rpf * -pim_rp_g (struct in_addr group) +struct pim_rpf *pim_rp_g(struct in_addr group) { - struct prefix g; - struct rp_info *rp_info; - - memset (&g, 0, sizeof (g)); - g.family = AF_INET; - g.prefixlen = 32; - g.u.prefix4 = group; - - rp_info = pim_rp_find_match_group (&g); - - if (rp_info) - { - struct prefix nht_p; - struct pim_nexthop_cache pnc; - /* Register addr with Zebra NHT */ - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; - if (PIM_DEBUG_PIM_TRACE) - { - char buf[PREFIX2STR_BUFFER]; - char buf1[PREFIX2STR_BUFFER]; - prefix2str (&nht_p, buf, sizeof (buf)); - prefix2str (&rp_info->group, buf1, sizeof (buf1)); - zlog_debug ("%s: NHT Register RP addr %s grp %s with Zebra", - __PRETTY_FUNCTION__, buf, buf1); - } - memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); - if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1) - { - //Compute PIM RPF using Cached nexthop - pim_ecmp_nexthop_search (&pnc, &rp_info->rp.source_nexthop, - &nht_p, &rp_info->group, 1); - } - else - { - if (PIM_DEBUG_ZEBRA) - { - char buf[PREFIX2STR_BUFFER]; - char buf1[PREFIX2STR_BUFFER]; - prefix2str (&nht_p, buf, sizeof (buf)); - prefix2str (&g, buf1, sizeof (buf1)); - zlog_debug ("%s: Nexthop cache not found for RP %s grp %s register with Zebra", - __PRETTY_FUNCTION__, buf, buf1); - } - pim_rpf_set_refresh_time (); - pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1); - } - return (&rp_info->rp); - } - - // About to Go Down - return NULL; + struct prefix g; + struct rp_info *rp_info; + + memset(&g, 0, sizeof(g)); + g.family = AF_INET; + g.prefixlen = 32; + g.u.prefix4 = group; + + rp_info = pim_rp_find_match_group(&g); + + if (rp_info) { + struct prefix nht_p; + struct pim_nexthop_cache pnc; + /* Register addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; + if (PIM_DEBUG_PIM_TRACE) { + char buf[PREFIX2STR_BUFFER]; + char buf1[PREFIX2STR_BUFFER]; + prefix2str(&nht_p, buf, sizeof(buf)); + prefix2str(&rp_info->group, buf1, sizeof(buf1)); + zlog_debug( + "%s: NHT Register RP addr %s grp %s with Zebra", + __PRETTY_FUNCTION__, buf, buf1); + } + memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); + if ((pim_find_or_track_nexthop(&nht_p, NULL, rp_info, &pnc)) + == 1) { + // Compute PIM RPF using Cached nexthop + pim_ecmp_nexthop_search(&pnc, + &rp_info->rp.source_nexthop, + &nht_p, &rp_info->group, 1); + } else { + if (PIM_DEBUG_ZEBRA) { + char buf[PREFIX2STR_BUFFER]; + char buf1[PREFIX2STR_BUFFER]; + prefix2str(&nht_p, buf, sizeof(buf)); + prefix2str(&g, buf1, sizeof(buf1)); + zlog_debug( + "%s: Nexthop cache not found for RP %s grp %s register with Zebra", + __PRETTY_FUNCTION__, buf, buf1); + } + pim_rpf_set_refresh_time(); + pim_nexthop_lookup(&rp_info->rp.source_nexthop, + rp_info->rp.rpf_addr.u.prefix4, 1); + } + return (&rp_info->rp); + } + + // About to Go Down + return NULL; } /* @@ -781,222 +762,253 @@ pim_rp_g (struct in_addr group) * then return failure. * */ -int -pim_rp_set_upstream_addr (struct in_addr *up, struct in_addr source, struct in_addr group) +int pim_rp_set_upstream_addr(struct in_addr *up, struct in_addr source, + struct in_addr group) { - struct rp_info *rp_info; - struct prefix g; + struct rp_info *rp_info; + struct prefix g; - memset (&g, 0, sizeof (g)); - g.family = AF_INET; - g.prefixlen = 32; - g.u.prefix4 = group; + memset(&g, 0, sizeof(g)); + g.family = AF_INET; + g.prefixlen = 32; + g.u.prefix4 = group; - rp_info = pim_rp_find_match_group (&g); + rp_info = pim_rp_find_match_group(&g); - if ((pim_rpf_addr_is_inaddr_none (&rp_info->rp)) && (source.s_addr == INADDR_ANY)) - { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug("%s: Received a (*,G) with no RP configured", __PRETTY_FUNCTION__); - return 0; - } + if ((pim_rpf_addr_is_inaddr_none(&rp_info->rp)) + && (source.s_addr == INADDR_ANY)) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug("%s: Received a (*,G) with no RP configured", + __PRETTY_FUNCTION__); + return 0; + } - *up = (source.s_addr == INADDR_ANY) ? rp_info->rp.rpf_addr.u.prefix4 : source; + *up = (source.s_addr == INADDR_ANY) ? rp_info->rp.rpf_addr.u.prefix4 + : source; - return 1; + return 1; } -int -pim_rp_config_write (struct vty *vty) +int pim_rp_config_write(struct vty *vty) { - struct listnode *node; - struct rp_info *rp_info; - char rp_buffer[32]; - char group_buffer[32]; - int count = 0; - - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) - { - if (pim_rpf_addr_is_inaddr_none (&rp_info->rp)) - continue; - - if (rp_info->plist) - vty_out (vty, "ip pim rp %s prefix-list %s\n", - inet_ntop(AF_INET, &rp_info->rp.rpf_addr.u.prefix4, rp_buffer, 32), - rp_info->plist); - else - vty_out (vty, "ip pim rp %s %s\n", - inet_ntop(AF_INET, &rp_info->rp.rpf_addr.u.prefix4, rp_buffer, 32), - prefix2str(&rp_info->group, group_buffer, 32)); - count++; - } - - return count; + struct listnode *node; + struct rp_info *rp_info; + char rp_buffer[32]; + char group_buffer[32]; + int count = 0; + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (pim_rpf_addr_is_inaddr_none(&rp_info->rp)) + continue; + + if (rp_info->plist) + vty_out(vty, "ip pim rp %s prefix-list %s\n", + inet_ntop(AF_INET, + &rp_info->rp.rpf_addr.u.prefix4, + rp_buffer, 32), + rp_info->plist); + else + vty_out(vty, "ip pim rp %s %s\n", + inet_ntop(AF_INET, + &rp_info->rp.rpf_addr.u.prefix4, + rp_buffer, 32), + prefix2str(&rp_info->group, group_buffer, 32)); + count++; + } + + return count; } -int -pim_rp_check_is_my_ip_address (struct in_addr group, struct in_addr dest_addr) +int pim_rp_check_is_my_ip_address(struct in_addr group, + struct in_addr dest_addr) { - struct rp_info *rp_info; - struct prefix g; - - memset (&g, 0, sizeof (g)); - g.family = AF_INET; - g.prefixlen = 32; - g.u.prefix4 = group; - - rp_info = pim_rp_find_match_group (&g); - /* - * See if we can short-cut some? - * This might not make sense if we ever leave a static RP - * type of configuration. - * Note - Premature optimization might bite our patooeys' here. - */ - if (I_am_RP(group)) - { - if (dest_addr.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr) - return 1; - } - - if (if_lookup_exact_address (&dest_addr, AF_INET, VRF_DEFAULT)) - return 1; - - return 0; + struct rp_info *rp_info; + struct prefix g; + + memset(&g, 0, sizeof(g)); + g.family = AF_INET; + g.prefixlen = 32; + g.u.prefix4 = group; + + rp_info = pim_rp_find_match_group(&g); + /* + * See if we can short-cut some? + * This might not make sense if we ever leave a static RP + * type of configuration. + * Note - Premature optimization might bite our patooeys' here. + */ + if (I_am_RP(group)) { + if (dest_addr.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr) + return 1; + } + + if (if_lookup_exact_address(&dest_addr, AF_INET, VRF_DEFAULT)) + return 1; + + return 0; } -void -pim_rp_show_information (struct vty *vty, u_char uj) +void pim_rp_show_information(struct vty *vty, u_char uj) { - struct rp_info *rp_info; - struct rp_info *prev_rp_info = NULL; - struct listnode *node; - - json_object *json = NULL; - json_object *json_rp_rows = NULL; - json_object *json_row = NULL; - - if (uj) - json = json_object_new_object(); - else - vty_out (vty, - "RP address group/prefix-list OIF I am RP\n"); - - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) - { - if (!pim_rpf_addr_is_inaddr_none (&rp_info->rp)) - { - char buf[48]; - - if (uj) - { - /* - * If we have moved on to a new RP then add the entry for the previous RP - */ - if (prev_rp_info && - prev_rp_info->rp.rpf_addr.u.prefix4.s_addr != rp_info->rp.rpf_addr.u.prefix4.s_addr) - { - json_object_object_add(json, inet_ntoa (prev_rp_info->rp.rpf_addr.u.prefix4), json_rp_rows); - json_rp_rows = NULL; - } - - if (!json_rp_rows) - json_rp_rows = json_object_new_array(); - - json_row = json_object_new_object(); - if (rp_info->rp.source_nexthop.interface) - json_object_string_add(json_row, "outboundInterface", rp_info->rp.source_nexthop.interface->name); - - if (rp_info->i_am_rp) - json_object_boolean_true_add(json_row, "iAmRP"); - - if (rp_info->plist) - json_object_string_add(json_row, "prefixList", rp_info->plist); - else - json_object_string_add(json_row, "group", prefix2str(&rp_info->group, buf, 48)); - - json_object_array_add(json_rp_rows, json_row); - } - else - { - vty_out (vty, "%-15s ", inet_ntoa (rp_info->rp.rpf_addr.u.prefix4)); - - if (rp_info->plist) - vty_out (vty, "%-18s ", rp_info->plist); - else - vty_out (vty, "%-18s ", prefix2str(&rp_info->group, buf, 48)); - - if (rp_info->rp.source_nexthop.interface) - vty_out (vty, "%-10s ", rp_info->rp.source_nexthop.interface->name); - else - vty_out (vty, "%-10s ", "(Unknown)"); - - if (rp_info->i_am_rp) - vty_out (vty, "yes\n"); - else - vty_out (vty, "no\n"); - } - - prev_rp_info = rp_info; - } - } - - if (uj) { - if (prev_rp_info && json_rp_rows) - json_object_object_add(json, inet_ntoa (prev_rp_info->rp.rpf_addr.u.prefix4), json_rp_rows); - - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } + struct rp_info *rp_info; + struct rp_info *prev_rp_info = NULL; + struct listnode *node; + + json_object *json = NULL; + json_object *json_rp_rows = NULL; + json_object *json_row = NULL; + + if (uj) + json = json_object_new_object(); + else + vty_out(vty, + "RP address group/prefix-list OIF I am RP\n"); + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (!pim_rpf_addr_is_inaddr_none(&rp_info->rp)) { + char buf[48]; + + if (uj) { + /* + * If we have moved on to a new RP then add the + * entry for the previous RP + */ + if (prev_rp_info + && prev_rp_info->rp.rpf_addr.u.prefix4 + .s_addr + != rp_info->rp.rpf_addr.u.prefix4 + .s_addr) { + json_object_object_add( + json, + inet_ntoa(prev_rp_info->rp + .rpf_addr.u + .prefix4), + json_rp_rows); + json_rp_rows = NULL; + } + + if (!json_rp_rows) + json_rp_rows = json_object_new_array(); + + json_row = json_object_new_object(); + if (rp_info->rp.source_nexthop.interface) + json_object_string_add( + json_row, "outboundInterface", + rp_info->rp.source_nexthop + .interface->name); + + if (rp_info->i_am_rp) + json_object_boolean_true_add(json_row, + "iAmRP"); + + if (rp_info->plist) + json_object_string_add(json_row, + "prefixList", + rp_info->plist); + else + json_object_string_add( + json_row, "group", + prefix2str(&rp_info->group, buf, + 48)); + + json_object_array_add(json_rp_rows, json_row); + } else { + vty_out(vty, "%-15s ", + inet_ntoa(rp_info->rp.rpf_addr.u + .prefix4)); + + if (rp_info->plist) + vty_out(vty, "%-18s ", rp_info->plist); + else + vty_out(vty, "%-18s ", + prefix2str(&rp_info->group, buf, + 48)); + + if (rp_info->rp.source_nexthop.interface) + vty_out(vty, "%-10s ", + rp_info->rp.source_nexthop + .interface->name); + else + vty_out(vty, "%-10s ", "(Unknown)"); + + if (rp_info->i_am_rp) + vty_out(vty, "yes\n"); + else + vty_out(vty, "no\n"); + } + + prev_rp_info = rp_info; + } + } + + if (uj) { + if (prev_rp_info && json_rp_rows) + json_object_object_add( + json, + inet_ntoa(prev_rp_info->rp.rpf_addr.u.prefix4), + json_rp_rows); + + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } -void -pim_resolve_rp_nh (void) +void pim_resolve_rp_nh(void) { - struct listnode *node = NULL; - struct rp_info *rp_info = NULL; - struct nexthop *nh_node = NULL; - struct prefix nht_p; - struct pim_nexthop_cache pnc; - struct pim_neighbor *nbr = NULL; - - for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info)) - { - if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) - continue; - - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; - memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); - if ((pim_find_or_track_nexthop (&nht_p, NULL, rp_info, &pnc)) == 1) - { - for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) - { - if (nh_node->gate.ipv4.s_addr == 0) - { - nbr = pim_neighbor_find_if (if_lookup_by_index - (nh_node->ifindex, VRF_DEFAULT)); - if (nbr) - { - nh_node->gate.ipv4 = nbr->source_addr; - if (PIM_DEBUG_TRACE) - { - char str[PREFIX_STRLEN]; - char str1[INET_ADDRSTRLEN]; - struct interface *ifp1 = if_lookup_by_index(nh_node->ifindex, - VRF_DEFAULT); - pim_inet4_dump ("", nbr->source_addr, - str1, sizeof (str1)); - pim_addr_dump ("", &nht_p, str, - sizeof (str)); - zlog_debug ("%s: addr %s new nexthop addr %s interface %s", - __PRETTY_FUNCTION__, str, str1, - ifp1->name); - } - } - } - } - } - } + struct listnode *node = NULL; + struct rp_info *rp_info = NULL; + struct nexthop *nh_node = NULL; + struct prefix nht_p; + struct pim_nexthop_cache pnc; + struct pim_neighbor *nbr = NULL; + + for (ALL_LIST_ELEMENTS_RO(qpim_rp_list, node, rp_info)) { + if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) + continue; + + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; + memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); + if ((pim_find_or_track_nexthop(&nht_p, NULL, rp_info, &pnc)) + == 1) { + for (nh_node = pnc.nexthop; nh_node; + nh_node = nh_node->next) { + if (nh_node->gate.ipv4.s_addr == 0) { + nbr = pim_neighbor_find_if( + if_lookup_by_index( + nh_node->ifindex, + VRF_DEFAULT)); + if (nbr) { + nh_node->gate.ipv4 = + nbr->source_addr; + if (PIM_DEBUG_TRACE) { + char str[PREFIX_STRLEN]; + char str1 + [INET_ADDRSTRLEN]; + struct interface *ifp1 = + if_lookup_by_index( + nh_node->ifindex, + VRF_DEFAULT); + pim_inet4_dump( + "", + nbr->source_addr, + str1, + sizeof(str1)); + pim_addr_dump( + "", + &nht_p, str, + sizeof(str)); + zlog_debug( + "%s: addr %s new nexthop addr %s interface %s", + __PRETTY_FUNCTION__, + str, str1, + ifp1->name); + } + } + } + } + } + } } diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index 319fe573c..7a7c26593 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -27,39 +27,40 @@ #include "pim_iface.h" #include "pim_rpf.h" -struct rp_info -{ - struct prefix group; - struct pim_rpf rp; - int i_am_rp; - char *plist; +struct rp_info { + struct prefix group; + struct pim_rpf rp; + int i_am_rp; + char *plist; }; -void pim_rp_init (void); -void pim_rp_free (void); +void pim_rp_init(void); +void pim_rp_free(void); -int pim_rp_new (const char *rp, const char *group, const char *plist); -int pim_rp_del (const char *rp, const char *group, const char *plist); -void pim_rp_prefix_list_update (struct prefix_list *plist); +int pim_rp_new(const char *rp, const char *group, const char *plist); +int pim_rp_del(const char *rp, const char *group, const char *plist); +void pim_rp_prefix_list_update(struct prefix_list *plist); -int pim_rp_config_write (struct vty *vty); +int pim_rp_config_write(struct vty *vty); -int pim_rp_setup (void); +int pim_rp_setup(void); -int pim_rp_i_am_rp (struct in_addr group); +int pim_rp_i_am_rp(struct in_addr group); void pim_rp_check_on_if_add(struct pim_interface *pim_ifp); void pim_i_am_rp_re_evaluate(void); -int pim_rp_check_is_my_ip_address (struct in_addr group, struct in_addr dest_addr); +int pim_rp_check_is_my_ip_address(struct in_addr group, + struct in_addr dest_addr); -int pim_rp_set_upstream_addr (struct in_addr *up, struct in_addr source, struct in_addr group); +int pim_rp_set_upstream_addr(struct in_addr *up, struct in_addr source, + struct in_addr group); -struct pim_rpf *pim_rp_g (struct in_addr group); +struct pim_rpf *pim_rp_g(struct in_addr group); #define I_am_RP(G) pim_rp_i_am_rp ((G)) #define RP(G) pim_rp_g ((G)) -void pim_rp_show_information (struct vty *vty, u_char uj); -void pim_resolve_rp_nh (void); -int pim_rp_list_cmp (void *v1, void *v2); +void pim_rp_show_information(struct vty *vty, u_char uj); +void pim_resolve_rp_nh(void); +int pim_rp_list_cmp(void *v1, void *v2); #endif diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index c5adf423c..4d0652c27 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -38,285 +38,281 @@ static long long last_route_change_time = -1; long long nexthop_lookups_avoided = 0; -static struct in_addr pim_rpf_find_rpf_addr (struct pim_upstream *up); +static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up); -void -pim_rpf_set_refresh_time (void) +void pim_rpf_set_refresh_time(void) { - last_route_change_time = pim_time_monotonic_usec(); - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: New last route change time: %lld", - __PRETTY_FUNCTION__, last_route_change_time); + last_route_change_time = pim_time_monotonic_usec(); + if (PIM_DEBUG_TRACE) + zlog_debug("%s: New last route change time: %lld", + __PRETTY_FUNCTION__, last_route_change_time); } -int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int neighbor_needed) +int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, + int neighbor_needed) { - struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; - struct pim_neighbor *nbr = NULL; - int num_ifindex; - struct interface *ifp = NULL; - ifindex_t first_ifindex = 0; - int found = 0; - int i = 0; - - if ((nexthop->last_lookup.s_addr == addr.s_addr) && - (nexthop->last_lookup_time > last_route_change_time)) - { - if (PIM_DEBUG_TRACE) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - char nexthop_str[PREFIX_STRLEN]; - pim_addr_dump("", &nexthop->mrib_nexthop_addr, - nexthop_str, sizeof(nexthop_str)); - zlog_debug ("%s: Using last lookup for %s at %lld, %lld addr%s", - __PRETTY_FUNCTION__, - addr_str, - nexthop->last_lookup_time, - last_route_change_time, nexthop_str); + struct pim_zlookup_nexthop nexthop_tab[MULTIPATH_NUM]; + struct pim_neighbor *nbr = NULL; + int num_ifindex; + struct interface *ifp = NULL; + ifindex_t first_ifindex = 0; + int found = 0; + int i = 0; + + if ((nexthop->last_lookup.s_addr == addr.s_addr) + && (nexthop->last_lookup_time > last_route_change_time)) { + if (PIM_DEBUG_TRACE) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, + sizeof(addr_str)); + char nexthop_str[PREFIX_STRLEN]; + pim_addr_dump("", &nexthop->mrib_nexthop_addr, + nexthop_str, sizeof(nexthop_str)); + zlog_debug( + "%s: Using last lookup for %s at %lld, %lld addr%s", + __PRETTY_FUNCTION__, addr_str, + nexthop->last_lookup_time, + last_route_change_time, nexthop_str); + } + nexthop_lookups_avoided++; + return 0; + } else { + if (PIM_DEBUG_TRACE) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s: Looking up: %s, last lookup time: %lld, %lld", + __PRETTY_FUNCTION__, addr_str, + nexthop->last_lookup_time, + last_route_change_time); + } } - nexthop_lookups_avoided++; - return 0; - } - else - { - if (PIM_DEBUG_TRACE) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_debug ("%s: Looking up: %s, last lookup time: %lld, %lld", - __PRETTY_FUNCTION__, - addr_str, - nexthop->last_lookup_time, - last_route_change_time); + + memset(nexthop_tab, 0, + sizeof(struct pim_zlookup_nexthop) * MULTIPATH_NUM); + num_ifindex = zclient_lookup_nexthop(nexthop_tab, MULTIPATH_NUM, addr, + PIM_NEXTHOP_LOOKUP_MAX); + if (num_ifindex < 1) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_warn( + "%s %s: could not find nexthop ifindex for address %s", + __FILE__, __PRETTY_FUNCTION__, addr_str); + return -1; + } + + while (!found && (i < num_ifindex)) { + first_ifindex = nexthop_tab[i].ifindex; + + ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); + if (!ifp) { + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s %s: could not find interface for ifindex %d (address %s)", + __FILE__, __PRETTY_FUNCTION__, + first_ifindex, addr_str); + } + i++; + continue; + } + + if (!ifp->info) { + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", + __PRETTY_FUNCTION__, ifp->name, + first_ifindex, addr_str); + } + i++; + } else if (neighbor_needed + && !pim_if_connected_to_source(ifp, addr)) { + nbr = pim_neighbor_find( + ifp, nexthop_tab[i].nexthop_addr.u.prefix4); + if (PIM_DEBUG_PIM_TRACE_DETAIL) + zlog_debug("ifp name: %s, pim nbr: %p", + ifp->name, nbr); + if (!nbr && !if_is_loopback(ifp)) + i++; + else + found = 1; + } else + found = 1; } - } - - memset (nexthop_tab, 0, sizeof (struct pim_zlookup_nexthop) * MULTIPATH_NUM); - num_ifindex = zclient_lookup_nexthop(nexthop_tab, - MULTIPATH_NUM, - addr, PIM_NEXTHOP_LOOKUP_MAX); - if (num_ifindex < 1) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_warn("%s %s: could not find nexthop ifindex for address %s", - __FILE__, __PRETTY_FUNCTION__, - addr_str); - return -1; - } - - while (!found && (i < num_ifindex)) - { - first_ifindex = nexthop_tab[i].ifindex; - - ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); - if (!ifp) - { - if (PIM_DEBUG_ZEBRA) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s %s: could not find interface for ifindex %d (address %s)", - __FILE__, __PRETTY_FUNCTION__, - first_ifindex, addr_str); - } - i++; - continue; - } - - if (!ifp->info) - { - if (PIM_DEBUG_ZEBRA) - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s: multicast not enabled on input interface %s (ifindex=%d, RPF for source %s)", - __PRETTY_FUNCTION__, - ifp->name, first_ifindex, addr_str); - } - i++; - } - else if (neighbor_needed && !pim_if_connected_to_source (ifp, addr)) - { - nbr = pim_neighbor_find (ifp, nexthop_tab[i].nexthop_addr.u.prefix4); - if (PIM_DEBUG_PIM_TRACE_DETAIL) - zlog_debug ("ifp name: %s, pim nbr: %p", ifp->name, nbr); - if (!nbr && !if_is_loopback (ifp)) - i++; - else - found = 1; - } - else - found = 1; - } - - if (found) - { - if (PIM_DEBUG_ZEBRA) { - char nexthop_str[PREFIX_STRLEN]; - char addr_str[INET_ADDRSTRLEN]; - pim_addr_dump("", &nexthop_tab[i].nexthop_addr, nexthop_str, sizeof(nexthop_str)); - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s %s: found nexthop %s for address %s: interface %s ifindex=%d metric=%d pref=%d", - __FILE__, __PRETTY_FUNCTION__, - nexthop_str, addr_str, - ifp->name, first_ifindex, - nexthop_tab[i].route_metric, - nexthop_tab[i].protocol_distance); - } - /* update nextop data */ - nexthop->interface = ifp; - nexthop->mrib_nexthop_addr = nexthop_tab[i].nexthop_addr; - nexthop->mrib_metric_preference = nexthop_tab[i].protocol_distance; - nexthop->mrib_route_metric = nexthop_tab[i].route_metric; - nexthop->last_lookup = addr; - nexthop->last_lookup_time = pim_time_monotonic_usec(); - nexthop->nbr = nbr; - return 0; - } - else - return -1; + + if (found) { + if (PIM_DEBUG_ZEBRA) { + char nexthop_str[PREFIX_STRLEN]; + char addr_str[INET_ADDRSTRLEN]; + pim_addr_dump("", + &nexthop_tab[i].nexthop_addr, nexthop_str, + sizeof(nexthop_str)); + pim_inet4_dump("", addr, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s %s: found nexthop %s for address %s: interface %s ifindex=%d metric=%d pref=%d", + __FILE__, __PRETTY_FUNCTION__, nexthop_str, + addr_str, ifp->name, first_ifindex, + nexthop_tab[i].route_metric, + nexthop_tab[i].protocol_distance); + } + /* update nextop data */ + nexthop->interface = ifp; + nexthop->mrib_nexthop_addr = nexthop_tab[i].nexthop_addr; + nexthop->mrib_metric_preference = + nexthop_tab[i].protocol_distance; + nexthop->mrib_route_metric = nexthop_tab[i].route_metric; + nexthop->last_lookup = addr; + nexthop->last_lookup_time = pim_time_monotonic_usec(); + nexthop->nbr = nbr; + return 0; + } else + return -1; } static int nexthop_mismatch(const struct pim_nexthop *nh1, const struct pim_nexthop *nh2) { - return (nh1->interface != nh2->interface) || - (nh1->mrib_nexthop_addr.u.prefix4.s_addr != nh2->mrib_nexthop_addr.u.prefix4.s_addr) || - (nh1->mrib_metric_preference != nh2->mrib_metric_preference) || - (nh1->mrib_route_metric != nh2->mrib_route_metric); + return (nh1->interface != nh2->interface) + || (nh1->mrib_nexthop_addr.u.prefix4.s_addr + != nh2->mrib_nexthop_addr.u.prefix4.s_addr) + || (nh1->mrib_metric_preference != nh2->mrib_metric_preference) + || (nh1->mrib_route_metric != nh2->mrib_route_metric); } -enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old, uint8_t is_new) +enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old, + uint8_t is_new) { - struct pim_rpf *rpf = &up->rpf; - struct pim_rpf saved; - struct prefix nht_p; - struct pim_nexthop_cache pnc; - int ret = 0; - struct prefix src, grp; - - saved.source_nexthop = rpf->source_nexthop; - saved.rpf_addr = rpf->rpf_addr; - - if (is_new && PIM_DEBUG_ZEBRA) - { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("", up->upstream_addr, source_str, - sizeof (source_str)); - zlog_debug ("%s: NHT Register upstream %s addr %s with Zebra.", - __PRETTY_FUNCTION__, up->sg_str, source_str); - } - /* Register addr with Zebra NHT */ - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; - - src.family = AF_INET; - src.prefixlen = IPV4_MAX_BITLEN; - src.u.prefix4 = up->upstream_addr; //RP or Src address - grp.family = AF_INET; - grp.prefixlen = IPV4_MAX_BITLEN; - grp.u.prefix4 = up->sg.grp; - memset (&pnc, 0, sizeof (struct pim_nexthop_cache)); - if ((ret = pim_find_or_track_nexthop (&nht_p, up, NULL, &pnc)) == 1) - { - if (pnc.nexthop_num) - { - //Compute PIM RPF using Cached nexthop - if (pim_ecmp_nexthop_search (&pnc, &up->rpf.source_nexthop, - &src, &grp, - !PIM_UPSTREAM_FLAG_TEST_FHR (up->flags) && - !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags))) - - { - return PIM_RPF_FAILURE; - } - } - } - else - { - if (pim_ecmp_nexthop_lookup (&rpf->source_nexthop, - up->upstream_addr, &src, &grp, - !PIM_UPSTREAM_FLAG_TEST_FHR (up->flags) && - !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags))) - { - return PIM_RPF_FAILURE; - } - } - - rpf->rpf_addr.family = AF_INET; - rpf->rpf_addr.u.prefix4 = pim_rpf_find_rpf_addr(up); - if (pim_rpf_addr_is_inaddr_any(rpf) && PIM_DEBUG_ZEBRA) - { - /* RPF'(S,G) not found */ - zlog_debug("%s %s: RPF'%s not found: won't send join upstream", - __FILE__, __PRETTY_FUNCTION__, - up->sg_str); - /* warning only */ - } - - /* detect change in pim_nexthop */ - if (nexthop_mismatch(&rpf->source_nexthop, &saved.source_nexthop)) { - - if (PIM_DEBUG_ZEBRA) { - char nhaddr_str[PREFIX_STRLEN]; - pim_addr_dump("", &rpf->source_nexthop.mrib_nexthop_addr, nhaddr_str, sizeof(nhaddr_str)); - zlog_debug("%s %s: (S,G)=%s source nexthop now is: interface=%s address=%s pref=%d metric=%d", + struct pim_rpf *rpf = &up->rpf; + struct pim_rpf saved; + struct prefix nht_p; + struct pim_nexthop_cache pnc; + int ret = 0; + struct prefix src, grp; + + saved.source_nexthop = rpf->source_nexthop; + saved.rpf_addr = rpf->rpf_addr; + + if (is_new && PIM_DEBUG_ZEBRA) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", up->upstream_addr, source_str, + sizeof(source_str)); + zlog_debug("%s: NHT Register upstream %s addr %s with Zebra.", + __PRETTY_FUNCTION__, up->sg_str, source_str); + } + /* Register addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; + + src.family = AF_INET; + src.prefixlen = IPV4_MAX_BITLEN; + src.u.prefix4 = up->upstream_addr; // RP or Src address + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = up->sg.grp; + memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); + if ((ret = pim_find_or_track_nexthop(&nht_p, up, NULL, &pnc)) == 1) { + if (pnc.nexthop_num) { + // Compute PIM RPF using Cached nexthop + if (pim_ecmp_nexthop_search( + &pnc, &up->rpf.source_nexthop, &src, &grp, + !PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) + && !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP( + up->flags))) + + { + return PIM_RPF_FAILURE; + } + } + } else { + if (pim_ecmp_nexthop_lookup( + &rpf->source_nexthop, up->upstream_addr, &src, &grp, + !PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) + && !PIM_UPSTREAM_FLAG_TEST_SRC_IGMP( + up->flags))) { + return PIM_RPF_FAILURE; + } + } + + rpf->rpf_addr.family = AF_INET; + rpf->rpf_addr.u.prefix4 = pim_rpf_find_rpf_addr(up); + if (pim_rpf_addr_is_inaddr_any(rpf) && PIM_DEBUG_ZEBRA) { + /* RPF'(S,G) not found */ + zlog_debug("%s %s: RPF'%s not found: won't send join upstream", + __FILE__, __PRETTY_FUNCTION__, up->sg_str); + /* warning only */ + } + + /* detect change in pim_nexthop */ + if (nexthop_mismatch(&rpf->source_nexthop, &saved.source_nexthop)) { + + if (PIM_DEBUG_ZEBRA) { + char nhaddr_str[PREFIX_STRLEN]; + pim_addr_dump("", + &rpf->source_nexthop.mrib_nexthop_addr, + nhaddr_str, sizeof(nhaddr_str)); + zlog_debug("%s %s: (S,G)=%s source nexthop now is: interface=%s address=%s pref=%d metric=%d", __FILE__, __PRETTY_FUNCTION__, up->sg_str, rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "", nhaddr_str, rpf->source_nexthop.mrib_metric_preference, rpf->source_nexthop.mrib_route_metric); - } + } - pim_upstream_update_join_desired(up); - pim_upstream_update_could_assert(up); - pim_upstream_update_my_assert_metric(up); - } + pim_upstream_update_join_desired(up); + pim_upstream_update_could_assert(up); + pim_upstream_update_my_assert_metric(up); + } - /* detect change in RPF_interface(S) */ - if (saved.source_nexthop.interface != rpf->source_nexthop.interface) { + /* detect change in RPF_interface(S) */ + if (saved.source_nexthop.interface != rpf->source_nexthop.interface) { - if (PIM_DEBUG_ZEBRA) { - zlog_debug("%s %s: (S,G)=%s RPF_interface(S) changed from %s to %s", + if (PIM_DEBUG_ZEBRA) { + zlog_debug("%s %s: (S,G)=%s RPF_interface(S) changed from %s to %s", __FILE__, __PRETTY_FUNCTION__, up->sg_str, saved.source_nexthop.interface ? saved.source_nexthop.interface->name : "", rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : ""); - /* warning only */ - } - - pim_upstream_rpf_interface_changed(up, saved.source_nexthop.interface); - } - - /* detect change in RPF'(S,G) */ - if (saved.rpf_addr.u.prefix4.s_addr != rpf->rpf_addr.u.prefix4.s_addr || - saved.source_nexthop.interface != rpf->source_nexthop.interface) - { - - /* return old rpf to caller ? */ - if (old) - { - old->source_nexthop = saved.source_nexthop; - old->rpf_addr = saved.rpf_addr; - } - return PIM_RPF_CHANGED; - } - - return PIM_RPF_OK; + /* warning only */ + } + + pim_upstream_rpf_interface_changed( + up, saved.source_nexthop.interface); + } + + /* detect change in RPF'(S,G) */ + if (saved.rpf_addr.u.prefix4.s_addr != rpf->rpf_addr.u.prefix4.s_addr + || saved.source_nexthop + .interface != rpf->source_nexthop.interface) { + + /* return old rpf to caller ? */ + if (old) { + old->source_nexthop = saved.source_nexthop; + old->rpf_addr = saved.rpf_addr; + } + return PIM_RPF_CHANGED; + } + + return PIM_RPF_OK; } /* RFC 4601: 4.1.6. State Summarization Macros neighbor RPF'(S,G) { - if ( I_Am_Assert_Loser(S, G, RPF_interface(S) )) { - return AssertWinner(S, G, RPF_interface(S) ) - } else { - return NBR( RPF_interface(S), MRIB.next_hop( S ) ) - } + if ( I_Am_Assert_Loser(S, G, RPF_interface(S) )) { + return AssertWinner(S, G, RPF_interface(S) ) + } else { + return NBR( RPF_interface(S), MRIB.next_hop( S ) ) + } } RPF'(*,G) and RPF'(S,G) indicate the neighbor from which data @@ -325,84 +321,78 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old, */ static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up) { - struct pim_ifchannel *rpf_ch; - struct pim_neighbor *neigh; - struct in_addr rpf_addr; - - if (!up->rpf.source_nexthop.interface) { - zlog_warn("%s: missing RPF interface for upstream (S,G)=%s", - __PRETTY_FUNCTION__, - up->sg_str); - - rpf_addr.s_addr = PIM_NET_INADDR_ANY; - return rpf_addr; - } - - rpf_ch = pim_ifchannel_find(up->rpf.source_nexthop.interface, - &up->sg); - if (rpf_ch) { - if (rpf_ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { - return rpf_ch->ifassert_winner; - } - } - - /* return NBR( RPF_interface(S), MRIB.next_hop( S ) ) */ - - neigh = pim_if_find_neighbor(up->rpf.source_nexthop.interface, - up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4); - if (neigh) - rpf_addr = neigh->source_addr; - else - rpf_addr.s_addr = PIM_NET_INADDR_ANY; - - return rpf_addr; + struct pim_ifchannel *rpf_ch; + struct pim_neighbor *neigh; + struct in_addr rpf_addr; + + if (!up->rpf.source_nexthop.interface) { + zlog_warn("%s: missing RPF interface for upstream (S,G)=%s", + __PRETTY_FUNCTION__, up->sg_str); + + rpf_addr.s_addr = PIM_NET_INADDR_ANY; + return rpf_addr; + } + + rpf_ch = pim_ifchannel_find(up->rpf.source_nexthop.interface, &up->sg); + if (rpf_ch) { + if (rpf_ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { + return rpf_ch->ifassert_winner; + } + } + + /* return NBR( RPF_interface(S), MRIB.next_hop( S ) ) */ + + neigh = pim_if_find_neighbor( + up->rpf.source_nexthop.interface, + up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4); + if (neigh) + rpf_addr = neigh->source_addr; + else + rpf_addr.s_addr = PIM_NET_INADDR_ANY; + + return rpf_addr; } -int -pim_rpf_addr_is_inaddr_none (struct pim_rpf *rpf) +int pim_rpf_addr_is_inaddr_none(struct pim_rpf *rpf) { - switch (rpf->rpf_addr.family) - { - case AF_INET: - return rpf->rpf_addr.u.prefix4.s_addr == INADDR_NONE; - break; - case AF_INET6: - zlog_warn ("%s: v6 Unimplmeneted", __PRETTY_FUNCTION__); - return 1; - break; - default: - return 0; - break; - } - - return 0; + switch (rpf->rpf_addr.family) { + case AF_INET: + return rpf->rpf_addr.u.prefix4.s_addr == INADDR_NONE; + break; + case AF_INET6: + zlog_warn("%s: v6 Unimplmeneted", __PRETTY_FUNCTION__); + return 1; + break; + default: + return 0; + break; + } + + return 0; } -int -pim_rpf_addr_is_inaddr_any (struct pim_rpf *rpf) +int pim_rpf_addr_is_inaddr_any(struct pim_rpf *rpf) { - switch (rpf->rpf_addr.family) - { - case AF_INET: - return rpf->rpf_addr.u.prefix4.s_addr == INADDR_ANY; - break; - case AF_INET6: - zlog_warn ("%s: v6 Unimplmented", __PRETTY_FUNCTION__); - return 1; - break; - default: - return 0; - break; - } - - return 0; + switch (rpf->rpf_addr.family) { + case AF_INET: + return rpf->rpf_addr.u.prefix4.s_addr == INADDR_ANY; + break; + case AF_INET6: + zlog_warn("%s: v6 Unimplmented", __PRETTY_FUNCTION__); + return 1; + break; + default: + return 0; + break; + } + + return 0; } -int -pim_rpf_is_same (struct pim_rpf *rpf1, struct pim_rpf *rpf2) +int pim_rpf_is_same(struct pim_rpf *rpf1, struct pim_rpf *rpf2) { - if (rpf1->source_nexthop.interface == rpf2->source_nexthop.interface) - return 1; + if (rpf1->source_nexthop.interface == rpf2->source_nexthop.interface) + return 1; - return 0; + return 0; } diff --git a/pimd/pim_rpf.h b/pimd/pim_rpf.h index bb7ee365b..083314356 100644 --- a/pimd/pim_rpf.h +++ b/pimd/pim_rpf.h @@ -38,36 +38,34 @@ units applicable to the unicast routing protocol used. */ struct pim_nexthop { - struct in_addr last_lookup; - long long last_lookup_time; - struct interface *interface; /* RPF_interface(S) */ - struct prefix mrib_nexthop_addr; /* MRIB.next_hop(S) */ - uint32_t mrib_metric_preference; /* MRIB.pref(S) */ - uint32_t mrib_route_metric; /* MRIB.metric(S) */ - struct pim_neighbor *nbr; + struct in_addr last_lookup; + long long last_lookup_time; + struct interface *interface; /* RPF_interface(S) */ + struct prefix mrib_nexthop_addr; /* MRIB.next_hop(S) */ + uint32_t mrib_metric_preference; /* MRIB.pref(S) */ + uint32_t mrib_route_metric; /* MRIB.metric(S) */ + struct pim_neighbor *nbr; }; struct pim_rpf { - struct pim_nexthop source_nexthop; - struct prefix rpf_addr; /* RPF'(S,G) */ + struct pim_nexthop source_nexthop; + struct prefix rpf_addr; /* RPF'(S,G) */ }; -enum pim_rpf_result { - PIM_RPF_OK = 0, - PIM_RPF_CHANGED, - PIM_RPF_FAILURE -}; +enum pim_rpf_result { PIM_RPF_OK = 0, PIM_RPF_CHANGED, PIM_RPF_FAILURE }; struct pim_upstream; extern long long nexthop_lookups_avoided; -int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int neighbor_needed); -enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old, uint8_t is_new); +int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, + int neighbor_needed); +enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old, + uint8_t is_new); -int pim_rpf_addr_is_inaddr_none (struct pim_rpf *rpf); -int pim_rpf_addr_is_inaddr_any (struct pim_rpf *rpf); +int pim_rpf_addr_is_inaddr_none(struct pim_rpf *rpf); +int pim_rpf_addr_is_inaddr_any(struct pim_rpf *rpf); -int pim_rpf_is_same (struct pim_rpf *rpf1, struct pim_rpf *rpf2); -void pim_rpf_set_refresh_time (void); +int pim_rpf_is_same(struct pim_rpf *rpf1, struct pim_rpf *rpf2); +void pim_rpf_set_refresh_time(void); #endif /* PIM_RPF_H */ diff --git a/pimd/pim_signals.c b/pimd/pim_signals.c index ef492d0d8..0e9b09bf8 100644 --- a/pimd/pim_signals.c +++ b/pimd/pim_signals.c @@ -35,44 +35,43 @@ static void pim_sighup() { - zlog_info ("SIGHUP received, ignoring"); + zlog_info("SIGHUP received, ignoring"); } static void pim_sigint() { - zlog_notice("Terminating on signal SIGINT"); - pim_terminate(); - exit(1); + zlog_notice("Terminating on signal SIGINT"); + pim_terminate(); + exit(1); } static void pim_sigterm() { - zlog_notice("Terminating on signal SIGTERM"); - pim_terminate(); - exit(1); + zlog_notice("Terminating on signal SIGTERM"); + pim_terminate(); + exit(1); } static void pim_sigusr1() { - zlog_rotate(); + zlog_rotate(); } -struct quagga_signal_t pimd_signals[] = -{ - { - .signal = SIGHUP, - .handler = &pim_sighup, - }, - { - .signal = SIGUSR1, - .handler = &pim_sigusr1, - }, - { - .signal = SIGINT, - .handler = &pim_sigint, - }, - { - .signal = SIGTERM, - .handler = &pim_sigterm, - }, +struct quagga_signal_t pimd_signals[] = { + { + .signal = SIGHUP, + .handler = &pim_sighup, + }, + { + .signal = SIGUSR1, + .handler = &pim_sigusr1, + }, + { + .signal = SIGINT, + .handler = &pim_sigint, + }, + { + .signal = SIGTERM, + .handler = &pim_sigterm, + }, }; diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index ba70cf2e1..a4d3d7e4b 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -42,292 +42,305 @@ /* GLOBAL VARS */ -int -pim_socket_raw (int protocol) +int pim_socket_raw(int protocol) { - int fd; + int fd; - if ( pimd_privs.change (ZPRIVS_RAISE) ) - zlog_err ("pim_sockek_raw: could not raise privs, %s", - safe_strerror (errno) ); + if (pimd_privs.change(ZPRIVS_RAISE)) + zlog_err("pim_sockek_raw: could not raise privs, %s", + safe_strerror(errno)); - fd = socket(AF_INET, SOCK_RAW, protocol); + fd = socket(AF_INET, SOCK_RAW, protocol); - if ( pimd_privs.change (ZPRIVS_LOWER) ) - zlog_err ("pim_socket_raw: could not lower privs, %s", - safe_strerror (errno) ); + if (pimd_privs.change(ZPRIVS_LOWER)) + zlog_err("pim_socket_raw: could not lower privs, %s", + safe_strerror(errno)); - if (fd < 0) { - zlog_warn("Could not create raw socket: errno=%d: %s", - errno, safe_strerror(errno)); - return PIM_SOCK_ERR_SOCKET; - } - - return fd; + if (fd < 0) { + zlog_warn("Could not create raw socket: errno=%d: %s", errno, + safe_strerror(errno)); + return PIM_SOCK_ERR_SOCKET; + } + + return fd; } -int -pim_socket_ip_hdr (int fd) +int pim_socket_ip_hdr(int fd) { - const int on = 1; - int ret; + const int on = 1; + int ret; - if (pimd_privs.change (ZPRIVS_RAISE)) - zlog_err ("%s: could not raise privs, %s", - __PRETTY_FUNCTION__, safe_strerror (errno)); + if (pimd_privs.change(ZPRIVS_RAISE)) + zlog_err("%s: could not raise privs, %s", __PRETTY_FUNCTION__, + safe_strerror(errno)); - ret = setsockopt (fd, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on)); + ret = setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)); - if (pimd_privs.change (ZPRIVS_LOWER)) - zlog_err ("%s: could not lower privs, %s", - __PRETTY_FUNCTION__, safe_strerror (errno)); + if (pimd_privs.change(ZPRIVS_LOWER)) + zlog_err("%s: could not lower privs, %s", __PRETTY_FUNCTION__, + safe_strerror(errno)); - return ret; + return ret; } /* * Given a socket and a interface, * Bind that socket to that interface */ -int -pim_socket_bind (int fd, struct interface *ifp) +int pim_socket_bind(int fd, struct interface *ifp) { - int ret = 0; + int ret = 0; #ifdef SO_BINDTODEVICE - if (pimd_privs.change (ZPRIVS_RAISE)) - zlog_err ("%s: could not raise privs, %s", - __PRETTY_FUNCTION__, safe_strerror (errno)); + if (pimd_privs.change(ZPRIVS_RAISE)) + zlog_err("%s: could not raise privs, %s", __PRETTY_FUNCTION__, + safe_strerror(errno)); - ret = setsockopt (fd, SOL_SOCKET, - SO_BINDTODEVICE, ifp->name, strlen (ifp->name)); + ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifp->name, + strlen(ifp->name)); - if (pimd_privs.change (ZPRIVS_LOWER)) - zlog_err ("%s: could not lower privs, %s", - __PRETTY_FUNCTION__, safe_strerror (errno)); + if (pimd_privs.change(ZPRIVS_LOWER)) + zlog_err("%s: could not lower privs, %s", __PRETTY_FUNCTION__, + safe_strerror(errno)); #endif - return ret; + return ret; } -int pim_socket_mcast(int protocol, struct in_addr ifaddr, struct interface *ifp, u_char loop) +int pim_socket_mcast(int protocol, struct in_addr ifaddr, struct interface *ifp, + u_char loop) { - int rcvbuf = 1024 * 1024 * 8; + int rcvbuf = 1024 * 1024 * 8; #ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX - struct ip_mreqn mreq; + struct ip_mreqn mreq; #else - struct ip_mreq mreq; + struct ip_mreq mreq; #endif - int fd; + int fd; - fd = pim_socket_raw(protocol); - if (fd < 0) { - zlog_warn("Could not create multicast socket: errno=%d: %s", - errno, safe_strerror(errno)); - return PIM_SOCK_ERR_SOCKET; - } + fd = pim_socket_raw(protocol); + if (fd < 0) { + zlog_warn("Could not create multicast socket: errno=%d: %s", + errno, safe_strerror(errno)); + return PIM_SOCK_ERR_SOCKET; + } #ifdef SO_BINDTODEVICE - if (protocol == IPPROTO_PIM) - { - int ret; - - ret = pim_socket_bind (fd, ifp); - if (ret) - { - close (fd); - zlog_warn("Could not set fd: %d for interface: %s to device", - fd, ifp->name); - return PIM_SOCK_ERR_BIND; + if (protocol == IPPROTO_PIM) { + int ret; + + ret = pim_socket_bind(fd, ifp); + if (ret) { + close(fd); + zlog_warn( + "Could not set fd: %d for interface: %s to device", + fd, ifp->name); + return PIM_SOCK_ERR_BIND; + } } - } #else - /* XXX: use IP_PKTINFO / IP_RECVIF to emulate behaviour? Or change to - * only use 1 socket for all interfaces? */ +/* XXX: use IP_PKTINFO / IP_RECVIF to emulate behaviour? Or change to + * only use 1 socket for all interfaces? */ #endif - /* Needed to obtain destination address from recvmsg() */ - { + /* Needed to obtain destination address from recvmsg() */ + { #if defined(HAVE_IP_PKTINFO) - /* Linux and Solaris IP_PKTINFO */ - int opt = 1; - if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt))) { - zlog_warn("Could not set IP_PKTINFO on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - } + /* Linux and Solaris IP_PKTINFO */ + int opt = 1; + if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt))) { + zlog_warn( + "Could not set IP_PKTINFO on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + } #elif defined(HAVE_IP_RECVDSTADDR) - /* BSD IP_RECVDSTADDR */ - int opt = 1; - if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt))) { - zlog_warn("Could not set IP_RECVDSTADDR on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - } + /* BSD IP_RECVDSTADDR */ + int opt = 1; + if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, + sizeof(opt))) { + zlog_warn( + "Could not set IP_RECVDSTADDR on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + } #else - zlog_err("%s %s: Missing IP_PKTINFO and IP_RECVDSTADDR: unable to get dst addr from recvmsg()", - __FILE__, __PRETTY_FUNCTION__); - close(fd); - return PIM_SOCK_ERR_DSTADDR; + zlog_err( + "%s %s: Missing IP_PKTINFO and IP_RECVDSTADDR: unable to get dst addr from recvmsg()", + __FILE__, __PRETTY_FUNCTION__); + close(fd); + return PIM_SOCK_ERR_DSTADDR; #endif - } - - - /* Set router alert (RFC 2113) for all IGMP messages (RFC 3376 4. Message Formats)*/ - if (protocol == IPPROTO_IGMP) { - uint8_t ra[4]; - ra[0] = 148; - ra[1] = 4; - ra[2] = 0; - ra[3] = 0; - if (setsockopt(fd, IPPROTO_IP, IP_OPTIONS, ra, 4)) { - zlog_warn("Could not set Router Alert Option on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_RA; - } - } - - { - int reuse = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, - (void *) &reuse, sizeof(reuse))) { - zlog_warn("Could not set Reuse Address Option on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_REUSE; - } - } - - { - const int MTTL = 1; - int ttl = MTTL; - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, - (void *) &ttl, sizeof(ttl))) { - zlog_warn("Could not set multicast TTL=%d on socket fd=%d: errno=%d: %s", - MTTL, fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_TTL; - } - } - - if (setsockopt_ipv4_multicast_loop (fd, loop)) { - zlog_warn("Could not %s Multicast Loopback Option on socket fd=%d: errno=%d: %s", - loop ? "enable" : "disable", - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_LOOP; - } - - memset (&mreq, 0, sizeof (mreq)); + } + + + /* Set router alert (RFC 2113) for all IGMP messages (RFC 3376 4. + * Message Formats)*/ + if (protocol == IPPROTO_IGMP) { + uint8_t ra[4]; + ra[0] = 148; + ra[1] = 4; + ra[2] = 0; + ra[3] = 0; + if (setsockopt(fd, IPPROTO_IP, IP_OPTIONS, ra, 4)) { + zlog_warn( + "Could not set Router Alert Option on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_RA; + } + } + + { + int reuse = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, + sizeof(reuse))) { + zlog_warn( + "Could not set Reuse Address Option on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_REUSE; + } + } + + { + const int MTTL = 1; + int ttl = MTTL; + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&ttl, + sizeof(ttl))) { + zlog_warn( + "Could not set multicast TTL=%d on socket fd=%d: errno=%d: %s", + MTTL, fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_TTL; + } + } + + if (setsockopt_ipv4_multicast_loop(fd, loop)) { + zlog_warn( + "Could not %s Multicast Loopback Option on socket fd=%d: errno=%d: %s", + loop ? "enable" : "disable", fd, errno, + safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_LOOP; + } + + memset(&mreq, 0, sizeof(mreq)); #ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX - mreq.imr_ifindex = ifp->ifindex; + mreq.imr_ifindex = ifp->ifindex; #else - /* - * I am not sure what to do here yet for *BSD - */ - //mreq.imr_interface = ifindex; +/* + * I am not sure what to do here yet for *BSD + */ +// mreq.imr_interface = ifindex; #endif - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (void *) &mreq, sizeof(mreq))) { - zlog_warn("Could not set Outgoing Interface Option on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_IFACE; - } - - if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf))) - zlog_warn("%s: Failure to set buffer size to %d", - __PRETTY_FUNCTION__, rcvbuf); - - { - long flags; - - flags = fcntl(fd, F_GETFL, 0); - if (flags < 0) { - zlog_warn("Could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_NONBLOCK_GETFL; - } - - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { - zlog_warn("Could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_NONBLOCK_SETFL; - } - } - - return fd; + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (void *)&mreq, + sizeof(mreq))) { + zlog_warn( + "Could not set Outgoing Interface Option on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_IFACE; + } + + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf))) + zlog_warn("%s: Failure to set buffer size to %d", + __PRETTY_FUNCTION__, rcvbuf); + + { + long flags; + + flags = fcntl(fd, F_GETFL, 0); + if (flags < 0) { + zlog_warn( + "Could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_NONBLOCK_GETFL; + } + + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { + zlog_warn( + "Could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_NONBLOCK_SETFL; + } + } + + return fd; } -int pim_socket_join(int fd, struct in_addr group, - struct in_addr ifaddr, ifindex_t ifindex) +int pim_socket_join(int fd, struct in_addr group, struct in_addr ifaddr, + ifindex_t ifindex) { - int ret; + int ret; #ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX - struct ip_mreqn opt; + struct ip_mreqn opt; #else - struct ip_mreq opt; + struct ip_mreq opt; #endif - opt.imr_multiaddr = group; + opt.imr_multiaddr = group; #ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX - opt.imr_address = ifaddr; - opt.imr_ifindex = ifindex; + opt.imr_address = ifaddr; + opt.imr_ifindex = ifindex; #else - opt.imr_interface = ifaddr; + opt.imr_interface = ifaddr; #endif - ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &opt, sizeof(opt)); - if (ret) { - char group_str[INET_ADDRSTRLEN]; - char ifaddr_str[INET_ADDRSTRLEN]; - if (!inet_ntop(AF_INET, &group, group_str , sizeof(group_str))) - sprintf(group_str, ""); - if (!inet_ntop(AF_INET, &ifaddr, ifaddr_str , sizeof(ifaddr_str))) - sprintf(ifaddr_str, ""); - - zlog_err("Failure socket joining fd=%d group %s on interface address %s: errno=%d: %s", - fd, group_str, ifaddr_str, errno, safe_strerror(errno)); - return ret; - } - - if (PIM_DEBUG_TRACE) { - char group_str[INET_ADDRSTRLEN]; - char ifaddr_str[INET_ADDRSTRLEN]; - if (!inet_ntop(AF_INET, &group, group_str , sizeof(group_str))) - sprintf(group_str, ""); - if (!inet_ntop(AF_INET, &ifaddr, ifaddr_str , sizeof(ifaddr_str))) - sprintf(ifaddr_str, ""); - - zlog_debug("Socket fd=%d joined group %s on interface address %s", - fd, group_str, ifaddr_str); - } - - return ret; + ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &opt, sizeof(opt)); + if (ret) { + char group_str[INET_ADDRSTRLEN]; + char ifaddr_str[INET_ADDRSTRLEN]; + if (!inet_ntop(AF_INET, &group, group_str, sizeof(group_str))) + sprintf(group_str, ""); + if (!inet_ntop(AF_INET, &ifaddr, ifaddr_str, + sizeof(ifaddr_str))) + sprintf(ifaddr_str, ""); + + zlog_err( + "Failure socket joining fd=%d group %s on interface address %s: errno=%d: %s", + fd, group_str, ifaddr_str, errno, safe_strerror(errno)); + return ret; + } + + if (PIM_DEBUG_TRACE) { + char group_str[INET_ADDRSTRLEN]; + char ifaddr_str[INET_ADDRSTRLEN]; + if (!inet_ntop(AF_INET, &group, group_str, sizeof(group_str))) + sprintf(group_str, ""); + if (!inet_ntop(AF_INET, &ifaddr, ifaddr_str, + sizeof(ifaddr_str))) + sprintf(ifaddr_str, ""); + + zlog_debug( + "Socket fd=%d joined group %s on interface address %s", + fd, group_str, ifaddr_str); + } + + return ret; } -int pim_socket_join_source(int fd, ifindex_t ifindex, - struct in_addr group_addr, - struct in_addr source_addr, - const char *ifname) +int pim_socket_join_source(int fd, ifindex_t ifindex, struct in_addr group_addr, + struct in_addr source_addr, const char *ifname) { - if (pim_igmp_join_source(fd, ifindex, group_addr, source_addr)) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group_addr, group_str, sizeof(group_str)); - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s", - __PRETTY_FUNCTION__, - fd, group_str, source_str, ifindex, ifname, - errno, safe_strerror(errno)); - return -1; - } - - return 0; + if (pim_igmp_join_source(fd, ifindex, group_addr, source_addr)) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group_addr, group_str, + sizeof(group_str)); + pim_inet4_dump("", source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s", + __PRETTY_FUNCTION__, fd, group_str, source_str, ifindex, + ifname, errno, safe_strerror(errno)); + return -1; + } + + return 0; } int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len, @@ -335,117 +348,121 @@ int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len, struct sockaddr_in *to, socklen_t *tolen, ifindex_t *ifindex) { - struct msghdr msgh; - struct cmsghdr *cmsg; - struct iovec iov; - char cbuf[1000]; - int err; - - /* - * IP_PKTINFO / IP_RECVDSTADDR don't yield sin_port. - * Use getsockname() to get sin_port. - */ - if (to) { - struct sockaddr_in si; - socklen_t si_len = sizeof(si); - - memset (&si, 0, sizeof (si)); - to->sin_family = AF_INET; - - pim_socket_getsockname(fd, (struct sockaddr *) &si, &si_len); - - to->sin_port = si.sin_port; - to->sin_addr = si.sin_addr; - - if (tolen) - *tolen = sizeof(si); - } - - memset(&msgh, 0, sizeof(struct msghdr)); - iov.iov_base = buf; - iov.iov_len = len; - msgh.msg_control = cbuf; - msgh.msg_controllen = sizeof(cbuf); - msgh.msg_name = from; - msgh.msg_namelen = fromlen ? *fromlen : 0; - msgh.msg_iov = &iov; - msgh.msg_iovlen = 1; - msgh.msg_flags = 0; - - err = recvmsg(fd, &msgh, 0); - if (err < 0) - return err; - - if (fromlen) - *fromlen = msgh.msg_namelen; - - for (cmsg = CMSG_FIRSTHDR(&msgh); - cmsg != NULL; - cmsg = CMSG_NXTHDR(&msgh,cmsg)) { + struct msghdr msgh; + struct cmsghdr *cmsg; + struct iovec iov; + char cbuf[1000]; + int err; + + /* + * IP_PKTINFO / IP_RECVDSTADDR don't yield sin_port. + * Use getsockname() to get sin_port. + */ + if (to) { + struct sockaddr_in si; + socklen_t si_len = sizeof(si); + + memset(&si, 0, sizeof(si)); + to->sin_family = AF_INET; + + pim_socket_getsockname(fd, (struct sockaddr *)&si, &si_len); + + to->sin_port = si.sin_port; + to->sin_addr = si.sin_addr; + + if (tolen) + *tolen = sizeof(si); + } + + memset(&msgh, 0, sizeof(struct msghdr)); + iov.iov_base = buf; + iov.iov_len = len; + msgh.msg_control = cbuf; + msgh.msg_controllen = sizeof(cbuf); + msgh.msg_name = from; + msgh.msg_namelen = fromlen ? *fromlen : 0; + msgh.msg_iov = &iov; + msgh.msg_iovlen = 1; + msgh.msg_flags = 0; + + err = recvmsg(fd, &msgh, 0); + if (err < 0) + return err; + + if (fromlen) + *fromlen = msgh.msg_namelen; + + for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; + cmsg = CMSG_NXTHDR(&msgh, cmsg)) { #ifdef HAVE_IP_PKTINFO - if ((cmsg->cmsg_level == IPPROTO_IP) && (cmsg->cmsg_type == IP_PKTINFO)) { - struct in_pktinfo *i = (struct in_pktinfo *) CMSG_DATA(cmsg); - if (to) - ((struct sockaddr_in *) to)->sin_addr = i->ipi_addr; - if (tolen) - *tolen = sizeof(struct sockaddr_in); - if (ifindex) - *ifindex = i->ipi_ifindex; - - break; - } + if ((cmsg->cmsg_level == IPPROTO_IP) + && (cmsg->cmsg_type == IP_PKTINFO)) { + struct in_pktinfo *i = + (struct in_pktinfo *)CMSG_DATA(cmsg); + if (to) + ((struct sockaddr_in *)to)->sin_addr = + i->ipi_addr; + if (tolen) + *tolen = sizeof(struct sockaddr_in); + if (ifindex) + *ifindex = i->ipi_ifindex; + + break; + } #endif #ifdef HAVE_IP_RECVDSTADDR - if ((cmsg->cmsg_level == IPPROTO_IP) && (cmsg->cmsg_type == IP_RECVDSTADDR)) { - struct in_addr *i = (struct in_addr *) CMSG_DATA(cmsg); - if (to) - ((struct sockaddr_in *) to)->sin_addr = *i; - if (tolen) - *tolen = sizeof(struct sockaddr_in); - - break; - } + if ((cmsg->cmsg_level == IPPROTO_IP) + && (cmsg->cmsg_type == IP_RECVDSTADDR)) { + struct in_addr *i = (struct in_addr *)CMSG_DATA(cmsg); + if (to) + ((struct sockaddr_in *)to)->sin_addr = *i; + if (tolen) + *tolen = sizeof(struct sockaddr_in); + + break; + } #endif #if defined(HAVE_IP_RECVIF) && defined(CMSG_IFINDEX) - if (cmsg->cmsg_type == IP_RECVIF) - if (ifindex) - *ifindex = CMSG_IFINDEX(cmsg); + if (cmsg->cmsg_type == IP_RECVIF) + if (ifindex) + *ifindex = CMSG_IFINDEX(cmsg); #endif - } /* for (cmsg) */ + } /* for (cmsg) */ - return err; /* len */ + return err; /* len */ } int pim_socket_mcastloop_get(int fd) { - int loop; - socklen_t loop_len = sizeof(loop); - - if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, - &loop, &loop_len)) { - int e = errno; - zlog_warn("Could not get Multicast Loopback Option on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - errno = e; - return PIM_SOCK_ERR_LOOP; - } - - return loop; + int loop; + socklen_t loop_len = sizeof(loop); + + if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, &loop_len)) { + int e = errno; + zlog_warn( + "Could not get Multicast Loopback Option on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + errno = e; + return PIM_SOCK_ERR_LOOP; + } + + return loop; } int pim_socket_getsockname(int fd, struct sockaddr *name, socklen_t *namelen) { - if (getsockname(fd, name, namelen)) { - int e = errno; - zlog_warn("Could not get Socket Name for socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - errno = e; - return PIM_SOCK_ERR_NAME; - } - - return PIM_SOCK_ERR_NONE; + if (getsockname(fd, name, namelen)) { + int e = errno; + zlog_warn( + "Could not get Socket Name for socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + errno = e; + return PIM_SOCK_ERR_NAME; + } + + return PIM_SOCK_ERR_NONE; } diff --git a/pimd/pim_sock.h b/pimd/pim_sock.h index 9fb64677c..aa46cd620 100644 --- a/pimd/pim_sock.h +++ b/pimd/pim_sock.h @@ -35,16 +35,15 @@ #define PIM_SOCK_ERR_NAME (-10) /* Socket name (getsockname) */ #define PIM_SOCK_ERR_BIND (-11) /* Can't bind to interface */ -int pim_socket_bind (int fd, struct interface *ifp); -int pim_socket_ip_hdr (int fd); +int pim_socket_bind(int fd, struct interface *ifp); +int pim_socket_ip_hdr(int fd); int pim_socket_raw(int protocol); -int pim_socket_mcast(int protocol, struct in_addr ifaddr, struct interface *ifp, u_char loop); -int pim_socket_join(int fd, struct in_addr group, - struct in_addr ifaddr, ifindex_t ifindex); -int pim_socket_join_source(int fd, ifindex_t ifindex, - struct in_addr group_addr, - struct in_addr source_addr, - const char *ifname); +int pim_socket_mcast(int protocol, struct in_addr ifaddr, struct interface *ifp, + u_char loop); +int pim_socket_join(int fd, struct in_addr group, struct in_addr ifaddr, + ifindex_t ifindex); +int pim_socket_join_source(int fd, ifindex_t ifindex, struct in_addr group_addr, + struct in_addr source_addr, const char *ifname); int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len, struct sockaddr_in *from, socklen_t *fromlen, struct sockaddr_in *to, socklen_t *tolen, diff --git a/pimd/pim_ssm.c b/pimd/pim_ssm.c index d4f88ec2c..3046e9429 100644 --- a/pimd/pim_ssm.c +++ b/pimd/pim_ssm.c @@ -29,129 +29,119 @@ #include "pim_ssm.h" #include "pim_zebra.h" -static void -pim_ssm_range_reevaluate (void) +static void pim_ssm_range_reevaluate(void) { - /* 1. Setup register state for (S,G) entries if G has changed from SSM to - * ASM. - * 2. check existing (*,G) IGMP registrations to see if they are - * still ASM. if they are now SSM delete them. - * 3. Allow channel setup for IGMP (*,G) members if G is now ASM - * 4. I could tear down all (*,G), (S,G,rpt) states. But that is an - * unnecessary sladge hammer and may not be particularly useful as it is - * likely the SPT switchover has already happened for flows along such RPTs. - * As for the RPT states it seems that the best thing to do is let them age - * out gracefully. As long as the FHR and LHR do the right thing RPTs will - * disappear in time for SSM groups. - */ - pim_upstream_register_reevaluate (); - igmp_source_forward_reevaluate_all (); + /* 1. Setup register state for (S,G) entries if G has changed from SSM + * to + * ASM. + * 2. check existing (*,G) IGMP registrations to see if they are + * still ASM. if they are now SSM delete them. + * 3. Allow channel setup for IGMP (*,G) members if G is now ASM + * 4. I could tear down all (*,G), (S,G,rpt) states. But that is an + * unnecessary sladge hammer and may not be particularly useful as it is + * likely the SPT switchover has already happened for flows along such + * RPTs. + * As for the RPT states it seems that the best thing to do is let them + * age + * out gracefully. As long as the FHR and LHR do the right thing RPTs + * will + * disappear in time for SSM groups. + */ + pim_upstream_register_reevaluate(); + igmp_source_forward_reevaluate_all(); } -void -pim_ssm_prefix_list_update (struct prefix_list *plist) +void pim_ssm_prefix_list_update(struct prefix_list *plist) { - struct pim_ssm *ssm = pimg->ssm_info; + struct pim_ssm *ssm = pimg->ssm_info; - if (!ssm->plist_name || strcmp (ssm->plist_name, prefix_list_name (plist))) - { - /* not ours */ - return; - } + if (!ssm->plist_name + || strcmp(ssm->plist_name, prefix_list_name(plist))) { + /* not ours */ + return; + } - pim_ssm_range_reevaluate (); + pim_ssm_range_reevaluate(); } -static int -pim_is_grp_standard_ssm (struct prefix *group) +static int pim_is_grp_standard_ssm(struct prefix *group) { - static int first = 1; - static struct prefix group_ssm; + static int first = 1; + static struct prefix group_ssm; - if (first) - { - str2prefix (PIM_SSM_STANDARD_RANGE, &group_ssm); - first = 0; - } + if (first) { + str2prefix(PIM_SSM_STANDARD_RANGE, &group_ssm); + first = 0; + } - return prefix_match (&group_ssm, group); + return prefix_match(&group_ssm, group); } -int -pim_is_grp_ssm (struct in_addr group_addr) +int pim_is_grp_ssm(struct in_addr group_addr) { - struct pim_ssm *ssm; - struct prefix group; - struct prefix_list *plist; - - memset (&group, 0, sizeof (group)); - group.family = AF_INET; - group.u.prefix4 = group_addr; - group.prefixlen = 32; - - ssm = pimg->ssm_info; - if (!ssm->plist_name) - { - return pim_is_grp_standard_ssm (&group); - } - - plist = prefix_list_lookup (AFI_IP, ssm->plist_name); - if (!plist) - return 0; - - return (prefix_list_apply (plist, &group) == PREFIX_PERMIT); + struct pim_ssm *ssm; + struct prefix group; + struct prefix_list *plist; + + memset(&group, 0, sizeof(group)); + group.family = AF_INET; + group.u.prefix4 = group_addr; + group.prefixlen = 32; + + ssm = pimg->ssm_info; + if (!ssm->plist_name) { + return pim_is_grp_standard_ssm(&group); + } + + plist = prefix_list_lookup(AFI_IP, ssm->plist_name); + if (!plist) + return 0; + + return (prefix_list_apply(plist, &group) == PREFIX_PERMIT); } -int -pim_ssm_range_set (vrf_id_t vrf_id, const char *plist_name) +int pim_ssm_range_set(vrf_id_t vrf_id, const char *plist_name) { - struct pim_ssm *ssm; - int change = 0; - - if (vrf_id != VRF_DEFAULT) - return PIM_SSM_ERR_NO_VRF; - - ssm = pimg->ssm_info; - if (plist_name) - { - if (ssm->plist_name) - { - if (!strcmp (ssm->plist_name, plist_name)) - return PIM_SSM_ERR_DUP; - XFREE (MTYPE_PIM_FILTER_NAME, ssm->plist_name); - } - ssm->plist_name = XSTRDUP (MTYPE_PIM_FILTER_NAME, plist_name); - change = 1; - } - else - { - if (ssm->plist_name) - { - change = 1; - XFREE (MTYPE_PIM_FILTER_NAME, ssm->plist_name); - } - } - - if (change) - pim_ssm_range_reevaluate (); - - return PIM_SSM_ERR_NONE; + struct pim_ssm *ssm; + int change = 0; + + if (vrf_id != VRF_DEFAULT) + return PIM_SSM_ERR_NO_VRF; + + ssm = pimg->ssm_info; + if (plist_name) { + if (ssm->plist_name) { + if (!strcmp(ssm->plist_name, plist_name)) + return PIM_SSM_ERR_DUP; + XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name); + } + ssm->plist_name = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist_name); + change = 1; + } else { + if (ssm->plist_name) { + change = 1; + XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name); + } + } + + if (change) + pim_ssm_range_reevaluate(); + + return PIM_SSM_ERR_NONE; } -void * -pim_ssm_init (vrf_id_t vrf_id) +void *pim_ssm_init(vrf_id_t vrf_id) { - struct pim_ssm *ssm; + struct pim_ssm *ssm; - ssm = XCALLOC (MTYPE_PIM_SSM_INFO, sizeof (*ssm)); - ssm->vrf_id = vrf_id; + ssm = XCALLOC(MTYPE_PIM_SSM_INFO, sizeof(*ssm)); + ssm->vrf_id = vrf_id; - return ssm; + return ssm; } -void -pim_ssm_terminate (struct pim_ssm *ssm) +void pim_ssm_terminate(struct pim_ssm *ssm) { - if (ssm && ssm->plist_name) - XFREE (MTYPE_PIM_FILTER_NAME, ssm->plist_name); + if (ssm && ssm->plist_name) + XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name); } diff --git a/pimd/pim_ssm.h b/pimd/pim_ssm.h index fe337be8f..9e89d0c80 100644 --- a/pimd/pim_ssm.h +++ b/pimd/pim_ssm.h @@ -22,22 +22,20 @@ #define PIM_SSM_STANDARD_RANGE "232.0.0.0/8" /* SSM error codes */ -enum pim_ssm_err -{ - PIM_SSM_ERR_NONE = 0, - PIM_SSM_ERR_NO_VRF = -1, - PIM_SSM_ERR_DUP = -2, +enum pim_ssm_err { + PIM_SSM_ERR_NONE = 0, + PIM_SSM_ERR_NO_VRF = -1, + PIM_SSM_ERR_DUP = -2, }; -struct pim_ssm -{ - vrf_id_t vrf_id; - char *plist_name; /* prefix list of group ranges */ +struct pim_ssm { + vrf_id_t vrf_id; + char *plist_name; /* prefix list of group ranges */ }; -void pim_ssm_prefix_list_update (struct prefix_list *plist); -int pim_is_grp_ssm (struct in_addr group_addr); -int pim_ssm_range_set (vrf_id_t vrf_id, const char *plist_name); -void *pim_ssm_init (vrf_id_t vrf_id); -void pim_ssm_terminate (struct pim_ssm *ssm); +void pim_ssm_prefix_list_update(struct prefix_list *plist); +int pim_is_grp_ssm(struct in_addr group_addr); +int pim_ssm_range_set(vrf_id_t vrf_id, const char *plist_name); +void *pim_ssm_init(vrf_id_t vrf_id); +void pim_ssm_terminate(struct pim_ssm *ssm); #endif diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c index dd92ff1b2..406183db8 100644 --- a/pimd/pim_ssmpingd.c +++ b/pimd/pim_ssmpingd.c @@ -30,402 +30,423 @@ #include "pim_time.h" #include "pim_sock.h" -static const char * const PIM_SSMPINGD_REPLY_GROUP = "232.43.211.234"; +static const char *const PIM_SSMPINGD_REPLY_GROUP = "232.43.211.234"; -enum { - PIM_SSMPINGD_REQUEST = 'Q', - PIM_SSMPINGD_REPLY = 'A' -}; +enum { PIM_SSMPINGD_REQUEST = 'Q', PIM_SSMPINGD_REPLY = 'A' }; static void ssmpingd_read_on(struct ssmpingd_sock *ss); void pim_ssmpingd_init() { - int result; + int result; - zassert(!qpim_ssmpingd_list); + zassert(!qpim_ssmpingd_list); - result = inet_pton(AF_INET, PIM_SSMPINGD_REPLY_GROUP, &qpim_ssmpingd_group_addr); - - zassert(result > 0); + result = inet_pton(AF_INET, PIM_SSMPINGD_REPLY_GROUP, + &qpim_ssmpingd_group_addr); + + zassert(result > 0); } void pim_ssmpingd_destroy() { - if (qpim_ssmpingd_list) { - list_free(qpim_ssmpingd_list); - qpim_ssmpingd_list = 0; - } + if (qpim_ssmpingd_list) { + list_free(qpim_ssmpingd_list); + qpim_ssmpingd_list = 0; + } } static struct ssmpingd_sock *ssmpingd_find(struct in_addr source_addr) { - struct listnode *node; - struct ssmpingd_sock *ss; + struct listnode *node; + struct ssmpingd_sock *ss; - if (!qpim_ssmpingd_list) - return 0; + if (!qpim_ssmpingd_list) + return 0; - for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) - if (source_addr.s_addr == ss->source_addr.s_addr) - return ss; + for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) + if (source_addr.s_addr == ss->source_addr.s_addr) + return ss; - return 0; + return 0; } static void ssmpingd_free(struct ssmpingd_sock *ss) { - XFREE(MTYPE_PIM_SSMPINGD, ss); + XFREE(MTYPE_PIM_SSMPINGD, ss); } static int ssmpingd_socket(struct in_addr addr, int port, int mttl) { - struct sockaddr_in sockaddr; - int fd; - - fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (fd < 0) { - zlog_err("%s: could not create socket: errno=%d: %s", - __PRETTY_FUNCTION__, errno, safe_strerror(errno)); - return -1; - } - - sockaddr.sin_family = AF_INET; - sockaddr.sin_addr = addr; - sockaddr.sin_port = htons(port); - - if (bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_warn("%s: bind(fd=%d,addr=%s,port=%d,len=%zu) failure: errno=%d: %s", - __PRETTY_FUNCTION__, - fd, addr_str, port, sizeof(sockaddr), - errno, safe_strerror(errno)); - close(fd); - return -1; - } - - /* Needed to obtain destination address from recvmsg() */ - { + struct sockaddr_in sockaddr; + int fd; + + fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (fd < 0) { + zlog_err("%s: could not create socket: errno=%d: %s", + __PRETTY_FUNCTION__, errno, safe_strerror(errno)); + return -1; + } + + sockaddr.sin_family = AF_INET; + sockaddr.sin_addr = addr; + sockaddr.sin_port = htons(port); + + if (bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_warn( + "%s: bind(fd=%d,addr=%s,port=%d,len=%zu) failure: errno=%d: %s", + __PRETTY_FUNCTION__, fd, addr_str, port, + sizeof(sockaddr), errno, safe_strerror(errno)); + close(fd); + return -1; + } + + /* Needed to obtain destination address from recvmsg() */ + { #if defined(HAVE_IP_PKTINFO) - /* Linux and Solaris IP_PKTINFO */ - int opt = 1; - if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt))) { - zlog_warn("%s: could not set IP_PKTINFO on socket fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); - } + /* Linux and Solaris IP_PKTINFO */ + int opt = 1; + if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt))) { + zlog_warn( + "%s: could not set IP_PKTINFO on socket fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, fd, errno, + safe_strerror(errno)); + } #elif defined(HAVE_IP_RECVDSTADDR) - /* BSD IP_RECVDSTADDR */ - int opt = 1; - if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt))) { - zlog_warn("%s: could not set IP_RECVDSTADDR on socket fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); - } + /* BSD IP_RECVDSTADDR */ + int opt = 1; + if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, + sizeof(opt))) { + zlog_warn( + "%s: could not set IP_RECVDSTADDR on socket fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, fd, errno, + safe_strerror(errno)); + } #else - zlog_err("%s %s: missing IP_PKTINFO and IP_RECVDSTADDR: unable to get dst addr from recvmsg()", - __FILE__, __PRETTY_FUNCTION__); - close(fd); - return -1; + zlog_err( + "%s %s: missing IP_PKTINFO and IP_RECVDSTADDR: unable to get dst addr from recvmsg()", + __FILE__, __PRETTY_FUNCTION__); + close(fd); + return -1; #endif - } - - { - int reuse = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, - (void *) &reuse, sizeof(reuse))) { - zlog_warn("%s: could not set Reuse Address Option on socket fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); - close(fd); - return -1; - } - } - - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, - (void *) &mttl, sizeof(mttl))) { - zlog_warn("%s: could not set multicast TTL=%d on socket fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, mttl, fd, errno, safe_strerror(errno)); - close(fd); - return -1; - } - - if (setsockopt_ipv4_multicast_loop (fd, 0)) { - zlog_warn("%s: could not disable Multicast Loopback Option on socket fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_LOOP; - } - - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (void *) &addr, sizeof(addr))) { - zlog_warn("%s: could not set Outgoing Interface Option on socket fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); - close(fd); - return -1; - } - - { - long flags; - - flags = fcntl(fd, F_GETFL, 0); - if (flags < 0) { - zlog_warn("%s: could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); - close(fd); - return -1; - } - - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { - zlog_warn("%s: could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); - close(fd); - return -1; - } - } - - return fd; + } + + { + int reuse = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, + sizeof(reuse))) { + zlog_warn( + "%s: could not set Reuse Address Option on socket fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, fd, errno, + safe_strerror(errno)); + close(fd); + return -1; + } + } + + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&mttl, + sizeof(mttl))) { + zlog_warn( + "%s: could not set multicast TTL=%d on socket fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, mttl, fd, errno, + safe_strerror(errno)); + close(fd); + return -1; + } + + if (setsockopt_ipv4_multicast_loop(fd, 0)) { + zlog_warn( + "%s: could not disable Multicast Loopback Option on socket fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_LOOP; + } + + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (void *)&addr, + sizeof(addr))) { + zlog_warn( + "%s: could not set Outgoing Interface Option on socket fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno)); + close(fd); + return -1; + } + + { + long flags; + + flags = fcntl(fd, F_GETFL, 0); + if (flags < 0) { + zlog_warn( + "%s: could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, fd, errno, + safe_strerror(errno)); + close(fd); + return -1; + } + + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { + zlog_warn( + "%s: could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, fd, errno, + safe_strerror(errno)); + close(fd); + return -1; + } + } + + return fd; } static void ssmpingd_delete(struct ssmpingd_sock *ss) { - zassert(ss); - zassert(qpim_ssmpingd_list); - - THREAD_OFF(ss->t_sock_read); - - if (close(ss->sock_fd)) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", ss->source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: failure closing ssmpingd sock_fd=%d for source %s: errno=%d: %s", - __PRETTY_FUNCTION__, - ss->sock_fd, source_str, errno, safe_strerror(errno)); - /* warning only */ - } - - listnode_delete(qpim_ssmpingd_list, ss); - ssmpingd_free(ss); + zassert(ss); + zassert(qpim_ssmpingd_list); + + THREAD_OFF(ss->t_sock_read); + + if (close(ss->sock_fd)) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", ss->source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: failure closing ssmpingd sock_fd=%d for source %s: errno=%d: %s", + __PRETTY_FUNCTION__, ss->sock_fd, source_str, errno, + safe_strerror(errno)); + /* warning only */ + } + + listnode_delete(qpim_ssmpingd_list, ss); + ssmpingd_free(ss); } -static void ssmpingd_sendto(struct ssmpingd_sock *ss, - const uint8_t *buf, - int len, - struct sockaddr_in to) +static void ssmpingd_sendto(struct ssmpingd_sock *ss, const uint8_t *buf, + int len, struct sockaddr_in to) { - socklen_t tolen = sizeof(to); - int sent; - - sent = sendto(ss->sock_fd, buf, len, MSG_DONTWAIT, - (struct sockaddr *)&to, tolen); - if (sent != len) { - char to_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", to.sin_addr, to_str, sizeof(to_str)); - if (sent < 0) { - zlog_warn("%s: sendto() failure to %s,%d: fd=%d len=%d: errno=%d: %s", - __PRETTY_FUNCTION__, - to_str, ntohs(to.sin_port), ss->sock_fd, len, - errno, safe_strerror(errno)); - } - else { - zlog_warn("%s: sendto() partial to %s,%d: fd=%d len=%d: sent=%d", - __PRETTY_FUNCTION__, - to_str, ntohs(to.sin_port), ss->sock_fd, - len, sent); - } - } + socklen_t tolen = sizeof(to); + int sent; + + sent = sendto(ss->sock_fd, buf, len, MSG_DONTWAIT, + (struct sockaddr *)&to, tolen); + if (sent != len) { + char to_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", to.sin_addr, to_str, sizeof(to_str)); + if (sent < 0) { + zlog_warn( + "%s: sendto() failure to %s,%d: fd=%d len=%d: errno=%d: %s", + __PRETTY_FUNCTION__, to_str, ntohs(to.sin_port), + ss->sock_fd, len, errno, safe_strerror(errno)); + } else { + zlog_warn( + "%s: sendto() partial to %s,%d: fd=%d len=%d: sent=%d", + __PRETTY_FUNCTION__, to_str, ntohs(to.sin_port), + ss->sock_fd, len, sent); + } + } } static int ssmpingd_read_msg(struct ssmpingd_sock *ss) { - struct interface *ifp; - struct sockaddr_in from; - struct sockaddr_in to; - socklen_t fromlen = sizeof(from); - socklen_t tolen = sizeof(to); - ifindex_t ifindex = -1; - uint8_t buf[1000]; - int len; - - ++ss->requests; - - len = pim_socket_recvfromto(ss->sock_fd, buf, sizeof(buf), - &from, &fromlen, - &to, &tolen, - &ifindex); - if (len < 0) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", ss->source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: failure receiving ssmping for source %s on fd=%d: errno=%d: %s", - __PRETTY_FUNCTION__, source_str, ss->sock_fd, errno, safe_strerror(errno)); - return -1; - } - - ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); - - if (buf[0] != PIM_SSMPINGD_REQUEST) { - char source_str[INET_ADDRSTRLEN]; - char from_str[INET_ADDRSTRLEN]; - char to_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", ss->source_addr, source_str, sizeof(source_str)); - pim_inet4_dump("", from.sin_addr, from_str, sizeof(from_str)); - pim_inet4_dump("", to.sin_addr, to_str, sizeof(to_str)); - zlog_warn("%s: bad ssmping type=%d from %s,%d to %s,%d on interface %s ifindex=%d fd=%d src=%s", - __PRETTY_FUNCTION__, - buf[0], - from_str, ntohs(from.sin_port), - to_str, ntohs(to.sin_port), - ifp ? ifp->name : "", - ifindex, ss->sock_fd, - source_str); - return 0; - } - - if (PIM_DEBUG_SSMPINGD) { - char source_str[INET_ADDRSTRLEN]; - char from_str[INET_ADDRSTRLEN]; - char to_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", ss->source_addr, source_str, sizeof(source_str)); - pim_inet4_dump("", from.sin_addr, from_str, sizeof(from_str)); - pim_inet4_dump("", to.sin_addr, to_str, sizeof(to_str)); - zlog_debug("%s: recv ssmping from %s,%d to %s,%d on interface %s ifindex=%d fd=%d src=%s", - __PRETTY_FUNCTION__, - from_str, ntohs(from.sin_port), - to_str, ntohs(to.sin_port), - ifp ? ifp->name : "", - ifindex, ss->sock_fd, - source_str); - } - - buf[0] = PIM_SSMPINGD_REPLY; - - /* unicast reply */ - ssmpingd_sendto(ss, buf, len, from); - - /* multicast reply */ - from.sin_addr = qpim_ssmpingd_group_addr; - ssmpingd_sendto(ss, buf, len, from); - - return 0; + struct interface *ifp; + struct sockaddr_in from; + struct sockaddr_in to; + socklen_t fromlen = sizeof(from); + socklen_t tolen = sizeof(to); + ifindex_t ifindex = -1; + uint8_t buf[1000]; + int len; + + ++ss->requests; + + len = pim_socket_recvfromto(ss->sock_fd, buf, sizeof(buf), &from, + &fromlen, &to, &tolen, &ifindex); + if (len < 0) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", ss->source_addr, source_str, + sizeof(source_str)); + zlog_warn( + "%s: failure receiving ssmping for source %s on fd=%d: errno=%d: %s", + __PRETTY_FUNCTION__, source_str, ss->sock_fd, errno, + safe_strerror(errno)); + return -1; + } + + ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); + + if (buf[0] != PIM_SSMPINGD_REQUEST) { + char source_str[INET_ADDRSTRLEN]; + char from_str[INET_ADDRSTRLEN]; + char to_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", ss->source_addr, source_str, + sizeof(source_str)); + pim_inet4_dump("", from.sin_addr, from_str, + sizeof(from_str)); + pim_inet4_dump("", to.sin_addr, to_str, sizeof(to_str)); + zlog_warn( + "%s: bad ssmping type=%d from %s,%d to %s,%d on interface %s ifindex=%d fd=%d src=%s", + __PRETTY_FUNCTION__, buf[0], from_str, + ntohs(from.sin_port), to_str, ntohs(to.sin_port), + ifp ? ifp->name : "", ifindex, ss->sock_fd, + source_str); + return 0; + } + + if (PIM_DEBUG_SSMPINGD) { + char source_str[INET_ADDRSTRLEN]; + char from_str[INET_ADDRSTRLEN]; + char to_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", ss->source_addr, source_str, + sizeof(source_str)); + pim_inet4_dump("", from.sin_addr, from_str, + sizeof(from_str)); + pim_inet4_dump("", to.sin_addr, to_str, sizeof(to_str)); + zlog_debug( + "%s: recv ssmping from %s,%d to %s,%d on interface %s ifindex=%d fd=%d src=%s", + __PRETTY_FUNCTION__, from_str, ntohs(from.sin_port), + to_str, ntohs(to.sin_port), + ifp ? ifp->name : "", ifindex, ss->sock_fd, + source_str); + } + + buf[0] = PIM_SSMPINGD_REPLY; + + /* unicast reply */ + ssmpingd_sendto(ss, buf, len, from); + + /* multicast reply */ + from.sin_addr = qpim_ssmpingd_group_addr; + ssmpingd_sendto(ss, buf, len, from); + + return 0; } static int ssmpingd_sock_read(struct thread *t) { - struct ssmpingd_sock *ss; - int result; + struct ssmpingd_sock *ss; + int result; - ss = THREAD_ARG(t); + ss = THREAD_ARG(t); - result = ssmpingd_read_msg(ss); + result = ssmpingd_read_msg(ss); - /* Keep reading */ - ssmpingd_read_on(ss); + /* Keep reading */ + ssmpingd_read_on(ss); - return result; + return result; } static void ssmpingd_read_on(struct ssmpingd_sock *ss) { - thread_add_read(master, ssmpingd_sock_read, ss, ss->sock_fd, - &ss->t_sock_read); + thread_add_read(master, ssmpingd_sock_read, ss, ss->sock_fd, + &ss->t_sock_read); } static struct ssmpingd_sock *ssmpingd_new(struct in_addr source_addr) { - struct ssmpingd_sock *ss; - int sock_fd; - - if (!qpim_ssmpingd_list) { - qpim_ssmpingd_list = list_new(); - if (!qpim_ssmpingd_list) { - zlog_err("%s %s: failure: qpim_ssmpingd_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return 0; - } - qpim_ssmpingd_list->del = (void (*)(void *)) ssmpingd_free; - } - - sock_fd = ssmpingd_socket(source_addr, /* port: */ 4321, /* mTTL: */ 64); - if (sock_fd < 0) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: ssmpingd_socket() failure for source %s", - __PRETTY_FUNCTION__, source_str); - return 0; - } - - ss = XCALLOC(MTYPE_PIM_SSMPINGD, sizeof(*ss)); - if (!ss) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - zlog_err("%s: XCALLOC(%zu) failure for ssmpingd source %s", - __PRETTY_FUNCTION__, - sizeof(*ss), source_str); - close(sock_fd); - return 0; - } - - ss->sock_fd = sock_fd; - ss->t_sock_read = NULL; - ss->source_addr = source_addr; - ss->creation = pim_time_monotonic_sec(); - ss->requests = 0; - - listnode_add(qpim_ssmpingd_list, ss); - - ssmpingd_read_on(ss); - - return ss; + struct ssmpingd_sock *ss; + int sock_fd; + + if (!qpim_ssmpingd_list) { + qpim_ssmpingd_list = list_new(); + if (!qpim_ssmpingd_list) { + zlog_err( + "%s %s: failure: qpim_ssmpingd_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return 0; + } + qpim_ssmpingd_list->del = (void (*)(void *))ssmpingd_free; + } + + sock_fd = + ssmpingd_socket(source_addr, /* port: */ 4321, /* mTTL: */ 64); + if (sock_fd < 0) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", source_addr, source_str, + sizeof(source_str)); + zlog_warn("%s: ssmpingd_socket() failure for source %s", + __PRETTY_FUNCTION__, source_str); + return 0; + } + + ss = XCALLOC(MTYPE_PIM_SSMPINGD, sizeof(*ss)); + if (!ss) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", source_addr, source_str, + sizeof(source_str)); + zlog_err("%s: XCALLOC(%zu) failure for ssmpingd source %s", + __PRETTY_FUNCTION__, sizeof(*ss), source_str); + close(sock_fd); + return 0; + } + + ss->sock_fd = sock_fd; + ss->t_sock_read = NULL; + ss->source_addr = source_addr; + ss->creation = pim_time_monotonic_sec(); + ss->requests = 0; + + listnode_add(qpim_ssmpingd_list, ss); + + ssmpingd_read_on(ss); + + return ss; } int pim_ssmpingd_start(struct in_addr source_addr) { - struct ssmpingd_sock *ss; - - ss = ssmpingd_find(source_addr); - if (ss) { - /* silently ignore request to recreate entry */ - return 0; - } - - { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - zlog_info("%s: starting ssmpingd for source %s", - __PRETTY_FUNCTION__, source_str); - } - - ss = ssmpingd_new(source_addr); - if (!ss) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: ssmpingd_new() failure for source %s", - __PRETTY_FUNCTION__, source_str); - return -1; - } - - return 0; + struct ssmpingd_sock *ss; + + ss = ssmpingd_find(source_addr); + if (ss) { + /* silently ignore request to recreate entry */ + return 0; + } + + { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", source_addr, source_str, + sizeof(source_str)); + zlog_info("%s: starting ssmpingd for source %s", + __PRETTY_FUNCTION__, source_str); + } + + ss = ssmpingd_new(source_addr); + if (!ss) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", source_addr, source_str, + sizeof(source_str)); + zlog_warn("%s: ssmpingd_new() failure for source %s", + __PRETTY_FUNCTION__, source_str); + return -1; + } + + return 0; } int pim_ssmpingd_stop(struct in_addr source_addr) { - struct ssmpingd_sock *ss; - - ss = ssmpingd_find(source_addr); - if (!ss) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - zlog_warn("%s: could not find ssmpingd for source %s", - __PRETTY_FUNCTION__, source_str); - return -1; - } - - { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", source_addr, source_str, sizeof(source_str)); - zlog_info("%s: stopping ssmpingd for source %s", - __PRETTY_FUNCTION__, source_str); - } - - ssmpingd_delete(ss); - - return 0; + struct ssmpingd_sock *ss; + + ss = ssmpingd_find(source_addr); + if (!ss) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", source_addr, source_str, + sizeof(source_str)); + zlog_warn("%s: could not find ssmpingd for source %s", + __PRETTY_FUNCTION__, source_str); + return -1; + } + + { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", source_addr, source_str, + sizeof(source_str)); + zlog_info("%s: stopping ssmpingd for source %s", + __PRETTY_FUNCTION__, source_str); + } + + ssmpingd_delete(ss); + + return 0; } diff --git a/pimd/pim_ssmpingd.h b/pimd/pim_ssmpingd.h index 02aa6271c..89fb320a7 100644 --- a/pimd/pim_ssmpingd.h +++ b/pimd/pim_ssmpingd.h @@ -27,11 +27,11 @@ #include "pim_iface.h" struct ssmpingd_sock { - int sock_fd; /* socket */ - struct thread *t_sock_read; /* thread for reading socket */ - struct in_addr source_addr; /* source address */ - int64_t creation; /* timestamp of socket creation */ - int64_t requests; /* counter */ + int sock_fd; /* socket */ + struct thread *t_sock_read; /* thread for reading socket */ + struct in_addr source_addr; /* source address */ + int64_t creation; /* timestamp of socket creation */ + int64_t requests; /* counter */ }; void pim_ssmpingd_init(void); diff --git a/pimd/pim_static.c b/pimd/pim_static.c index d373581fe..7c9aca47a 100644 --- a/pimd/pim_static.c +++ b/pimd/pim_static.c @@ -34,317 +34,337 @@ void pim_static_route_free(struct static_route *s_route) { - XFREE(MTYPE_PIM_STATIC_ROUTE, s_route); + XFREE(MTYPE_PIM_STATIC_ROUTE, s_route); } -static struct static_route * static_route_alloc() +static struct static_route *static_route_alloc() { - struct static_route *s_route; - - s_route = XCALLOC(MTYPE_PIM_STATIC_ROUTE, sizeof(*s_route)); - if (!s_route) { - zlog_err("PIM XCALLOC(%zu) failure", sizeof(*s_route)); - return 0; - } - return s_route; + struct static_route *s_route; + + s_route = XCALLOC(MTYPE_PIM_STATIC_ROUTE, sizeof(*s_route)); + if (!s_route) { + zlog_err("PIM XCALLOC(%zu) failure", sizeof(*s_route)); + return 0; + } + return s_route; } -static struct static_route *static_route_new(unsigned int iif, - unsigned int oif, - struct in_addr group, - struct in_addr source) +static struct static_route *static_route_new(unsigned int iif, unsigned int oif, + struct in_addr group, + struct in_addr source) { - struct static_route * s_route; - s_route = static_route_alloc(); - if (!s_route) { - return 0; - } - - s_route->group = group; - s_route->source = source; - s_route->iif = iif; - s_route->oif_ttls[oif] = 1; - s_route->c_oil.oil_ref_count = 1; - s_route->c_oil.oil.mfcc_origin = source; - s_route->c_oil.oil.mfcc_mcastgrp = group; - s_route->c_oil.oil.mfcc_parent = iif; - s_route->c_oil.oil.mfcc_ttls[oif] = 1; - s_route->c_oil.oif_creation[oif] = pim_time_monotonic_sec(); - - return s_route; + struct static_route *s_route; + s_route = static_route_alloc(); + if (!s_route) { + return 0; + } + + s_route->group = group; + s_route->source = source; + s_route->iif = iif; + s_route->oif_ttls[oif] = 1; + s_route->c_oil.oil_ref_count = 1; + s_route->c_oil.oil.mfcc_origin = source; + s_route->c_oil.oil.mfcc_mcastgrp = group; + s_route->c_oil.oil.mfcc_parent = iif; + s_route->c_oil.oil.mfcc_ttls[oif] = 1; + s_route->c_oil.oif_creation[oif] = pim_time_monotonic_sec(); + + return s_route; } -int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr group, struct in_addr source) +int pim_static_add(struct interface *iif, struct interface *oif, + struct in_addr group, struct in_addr source) { - struct listnode *node = NULL; - struct static_route *s_route = NULL; - struct static_route *original_s_route = NULL; - struct pim_interface *pim_iif = iif ? iif->info : NULL; - struct pim_interface *pim_oif = oif ? oif->info : NULL; - ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; - ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; - - if (!iif_index || !oif_index) { - zlog_warn("%s %s: Unable to add static route: Invalid interface index(iif=%d,oif=%d)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index); - return -2; - } + struct listnode *node = NULL; + struct static_route *s_route = NULL; + struct static_route *original_s_route = NULL; + struct pim_interface *pim_iif = iif ? iif->info : NULL; + struct pim_interface *pim_oif = oif ? oif->info : NULL; + ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; + ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; + + if (!iif_index || !oif_index) { + zlog_warn( + "%s %s: Unable to add static route: Invalid interface index(iif=%d,oif=%d)", + __FILE__, __PRETTY_FUNCTION__, iif_index, oif_index); + return -2; + } #ifdef PIM_ENFORCE_LOOPFREE_MFC - if (iif_index == oif_index) { - /* looped MFC entry */ - zlog_warn("%s %s: Unable to add static route: Looped MFC entry(iif=%d,oif=%d)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index); - return -4; - } + if (iif_index == oif_index) { + /* looped MFC entry */ + zlog_warn( + "%s %s: Unable to add static route: Looped MFC entry(iif=%d,oif=%d)", + __FILE__, __PRETTY_FUNCTION__, iif_index, oif_index); + return -4; + } #endif - for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { - if (s_route->group.s_addr == group.s_addr && - s_route->source.s_addr == source.s_addr) { - if (s_route->iif == iif_index && - s_route->oif_ttls[oif_index]) { - char gifaddr_str[INET_ADDRSTRLEN]; - char sifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group, gifaddr_str, sizeof(gifaddr_str)); - pim_inet4_dump("", source, sifaddr_str, sizeof(sifaddr_str)); - zlog_warn("%s %s: Unable to add static route: Route already exists (iif=%d,oif=%d,group=%s,source=%s)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index, - gifaddr_str, - sifaddr_str); - return -3; - } - - /* Ok, from here on out we will be making changes to the s_route structure, but if - * for some reason we fail to commit these changes to the kernel, we want to be able - * restore the state of the list. So copy the node data and if need be, we can copy - * back if it fails. - */ - original_s_route = static_route_alloc(); - if (!original_s_route) { - return -5; - } - memcpy(original_s_route, s_route, sizeof(struct static_route)); - - /* Route exists and has the same input interface, but adding a new output interface */ - if (s_route->iif == iif_index) { - s_route->oif_ttls[oif_index] = 1; - s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; - s_route->c_oil.oif_creation[oif_index] = pim_time_monotonic_sec(); - ++s_route->c_oil.oil_ref_count; - } else { - /* input interface changed */ - s_route->iif = iif_index; - s_route->c_oil.oil.mfcc_parent = iif_index; + for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) { + if (s_route->group.s_addr == group.s_addr + && s_route->source.s_addr == source.s_addr) { + if (s_route->iif == iif_index + && s_route->oif_ttls[oif_index]) { + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group, gifaddr_str, + sizeof(gifaddr_str)); + pim_inet4_dump("", source, sifaddr_str, + sizeof(sifaddr_str)); + zlog_warn( + "%s %s: Unable to add static route: Route already exists (iif=%d,oif=%d,group=%s,source=%s)", + __FILE__, __PRETTY_FUNCTION__, + iif_index, oif_index, gifaddr_str, + sifaddr_str); + return -3; + } + + /* Ok, from here on out we will be making changes to the + * s_route structure, but if + * for some reason we fail to commit these changes to + * the kernel, we want to be able + * restore the state of the list. So copy the node data + * and if need be, we can copy + * back if it fails. + */ + original_s_route = static_route_alloc(); + if (!original_s_route) { + return -5; + } + memcpy(original_s_route, s_route, + sizeof(struct static_route)); + + /* Route exists and has the same input interface, but + * adding a new output interface */ + if (s_route->iif == iif_index) { + s_route->oif_ttls[oif_index] = 1; + s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; + s_route->c_oil.oif_creation[oif_index] = + pim_time_monotonic_sec(); + ++s_route->c_oil.oil_ref_count; + } else { + /* input interface changed */ + s_route->iif = iif_index; + s_route->c_oil.oil.mfcc_parent = iif_index; #ifdef PIM_ENFORCE_LOOPFREE_MFC - /* check to make sure the new input was not an old output */ - if (s_route->oif_ttls[iif_index]) { - s_route->oif_ttls[iif_index] = 0; - s_route->c_oil.oif_creation[iif_index] = 0; - s_route->c_oil.oil.mfcc_ttls[iif_index] = 0; - --s_route->c_oil.oil_ref_count; - } + /* check to make sure the new input was not an + * old output */ + if (s_route->oif_ttls[iif_index]) { + s_route->oif_ttls[iif_index] = 0; + s_route->c_oil.oif_creation[iif_index] = + 0; + s_route->c_oil.oil + .mfcc_ttls[iif_index] = 0; + --s_route->c_oil.oil_ref_count; + } #endif - /* now add the new output, if it is new */ - if (!s_route->oif_ttls[oif_index]) { - s_route->oif_ttls[oif_index] = 1; - s_route->c_oil.oif_creation[oif_index] = pim_time_monotonic_sec(); - s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; - ++s_route->c_oil.oil_ref_count; - } - } - - break; - } - } - - /* If node is null then we reached the end of the list without finding a match */ - if (!node) { - s_route = static_route_new(iif_index, oif_index, group, source); - listnode_add(qpim_static_route_list, s_route); - } - - if (pim_mroute_add(&s_route->c_oil, __PRETTY_FUNCTION__)) - { - char gifaddr_str[INET_ADDRSTRLEN]; - char sifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group, gifaddr_str, sizeof(gifaddr_str)); - pim_inet4_dump("", source, sifaddr_str, sizeof(sifaddr_str)); - zlog_warn("%s %s: Unable to add static route(iif=%d,oif=%d,group=%s,source=%s)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index, - gifaddr_str, - sifaddr_str); - - /* Need to put s_route back to the way it was */ - if (original_s_route) { - memcpy(s_route, original_s_route, sizeof(struct static_route)); - } else { - /* we never stored off a copy, so it must have been a fresh new route */ - listnode_delete(qpim_static_route_list, s_route); - pim_static_route_free(s_route); - } - - if (original_s_route) { - pim_static_route_free(original_s_route); - } - - return -1; - } - - /* Make sure we free the memory for the route copy if used */ - if (original_s_route) { - pim_static_route_free(original_s_route); - } - - if (PIM_DEBUG_STATIC) { - char gifaddr_str[INET_ADDRSTRLEN]; - char sifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group, gifaddr_str, sizeof(gifaddr_str)); - pim_inet4_dump("", source, sifaddr_str, sizeof(sifaddr_str)); - zlog_debug("%s: Static route added(iif=%d,oif=%d,group=%s,source=%s)", - __PRETTY_FUNCTION__, - iif_index, - oif_index, - gifaddr_str, - sifaddr_str); - } - - return 0; + /* now add the new output, if it is new */ + if (!s_route->oif_ttls[oif_index]) { + s_route->oif_ttls[oif_index] = 1; + s_route->c_oil.oif_creation[oif_index] = + pim_time_monotonic_sec(); + s_route->c_oil.oil + .mfcc_ttls[oif_index] = 1; + ++s_route->c_oil.oil_ref_count; + } + } + + break; + } + } + + /* If node is null then we reached the end of the list without finding a + * match */ + if (!node) { + s_route = static_route_new(iif_index, oif_index, group, source); + listnode_add(qpim_static_route_list, s_route); + } + + if (pim_mroute_add(&s_route->c_oil, __PRETTY_FUNCTION__)) { + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group, gifaddr_str, + sizeof(gifaddr_str)); + pim_inet4_dump("", source, sifaddr_str, + sizeof(sifaddr_str)); + zlog_warn( + "%s %s: Unable to add static route(iif=%d,oif=%d,group=%s,source=%s)", + __FILE__, __PRETTY_FUNCTION__, iif_index, oif_index, + gifaddr_str, sifaddr_str); + + /* Need to put s_route back to the way it was */ + if (original_s_route) { + memcpy(s_route, original_s_route, + sizeof(struct static_route)); + } else { + /* we never stored off a copy, so it must have been a + * fresh new route */ + listnode_delete(qpim_static_route_list, s_route); + pim_static_route_free(s_route); + } + + if (original_s_route) { + pim_static_route_free(original_s_route); + } + + return -1; + } + + /* Make sure we free the memory for the route copy if used */ + if (original_s_route) { + pim_static_route_free(original_s_route); + } + + if (PIM_DEBUG_STATIC) { + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group, gifaddr_str, + sizeof(gifaddr_str)); + pim_inet4_dump("", source, sifaddr_str, + sizeof(sifaddr_str)); + zlog_debug( + "%s: Static route added(iif=%d,oif=%d,group=%s,source=%s)", + __PRETTY_FUNCTION__, iif_index, oif_index, gifaddr_str, + sifaddr_str); + } + + return 0; } -int pim_static_del(struct interface *iif, struct interface *oif, struct in_addr group, struct in_addr source) +int pim_static_del(struct interface *iif, struct interface *oif, + struct in_addr group, struct in_addr source) { - struct listnode *node = NULL; - struct listnode *nextnode = NULL; - struct static_route *s_route = NULL; - struct pim_interface *pim_iif = iif ? iif->info : 0; - struct pim_interface *pim_oif = oif ? oif->info : 0; - ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; - ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; - - if (!iif_index || !oif_index) { - zlog_warn("%s %s: Unable to remove static route: Invalid interface index(iif=%d,oif=%d)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index); - return -2; - } - - for (ALL_LIST_ELEMENTS(qpim_static_route_list, node, nextnode, s_route)) { - if (s_route->iif == iif_index && - s_route->group.s_addr == group.s_addr && - s_route->source.s_addr == source.s_addr && - s_route->oif_ttls[oif_index]) { - s_route->oif_ttls[oif_index] = 0; - s_route->c_oil.oil.mfcc_ttls[oif_index] = 0; - --s_route->c_oil.oil_ref_count; - - /* If there are no more outputs then delete the whole route, otherwise set the route with the new outputs */ - if (s_route->c_oil.oil_ref_count <= 0 ? - pim_mroute_del(&s_route->c_oil, __PRETTY_FUNCTION__) : pim_mroute_add(&s_route->c_oil, __PRETTY_FUNCTION__)) { - char gifaddr_str[INET_ADDRSTRLEN]; - char sifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group, gifaddr_str, sizeof(gifaddr_str)); - pim_inet4_dump("", source, sifaddr_str, sizeof(sifaddr_str)); - zlog_warn("%s %s: Unable to remove static route(iif=%d,oif=%d,group=%s,source=%s)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index, - gifaddr_str, - sifaddr_str); - - s_route->oif_ttls[oif_index] = 1; - s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; - ++s_route->c_oil.oil_ref_count; - - return -1; - } - - s_route->c_oil.oif_creation[oif_index] = 0; - - if (s_route->c_oil.oil_ref_count <= 0) { - listnode_delete(qpim_static_route_list, s_route); - pim_static_route_free(s_route); - } - - if (PIM_DEBUG_STATIC) { - char gifaddr_str[INET_ADDRSTRLEN]; - char sifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group, gifaddr_str, sizeof(gifaddr_str)); - pim_inet4_dump("", source, sifaddr_str, sizeof(sifaddr_str)); - zlog_debug("%s: Static route removed(iif=%d,oif=%d,group=%s,source=%s)", - __PRETTY_FUNCTION__, - iif_index, - oif_index, - gifaddr_str, - sifaddr_str); - } - - break; - } - } - - if (!node) { - char gifaddr_str[INET_ADDRSTRLEN]; - char sifaddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", group, gifaddr_str, sizeof(gifaddr_str)); - pim_inet4_dump("", source, sifaddr_str, sizeof(sifaddr_str)); - zlog_warn("%s %s: Unable to remove static route: Route does not exist(iif=%d,oif=%d,group=%s,source=%s)", - __FILE__, __PRETTY_FUNCTION__, - iif_index, - oif_index, - gifaddr_str, - sifaddr_str); - return -3; - } - - return 0; + struct listnode *node = NULL; + struct listnode *nextnode = NULL; + struct static_route *s_route = NULL; + struct pim_interface *pim_iif = iif ? iif->info : 0; + struct pim_interface *pim_oif = oif ? oif->info : 0; + ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; + ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; + + if (!iif_index || !oif_index) { + zlog_warn( + "%s %s: Unable to remove static route: Invalid interface index(iif=%d,oif=%d)", + __FILE__, __PRETTY_FUNCTION__, iif_index, oif_index); + return -2; + } + + for (ALL_LIST_ELEMENTS(qpim_static_route_list, node, nextnode, + s_route)) { + if (s_route->iif == iif_index + && s_route->group.s_addr == group.s_addr + && s_route->source.s_addr == source.s_addr + && s_route->oif_ttls[oif_index]) { + s_route->oif_ttls[oif_index] = 0; + s_route->c_oil.oil.mfcc_ttls[oif_index] = 0; + --s_route->c_oil.oil_ref_count; + + /* If there are no more outputs then delete the whole + * route, otherwise set the route with the new outputs + */ + if (s_route->c_oil.oil_ref_count <= 0 + ? pim_mroute_del(&s_route->c_oil, + __PRETTY_FUNCTION__) + : pim_mroute_add(&s_route->c_oil, + __PRETTY_FUNCTION__)) { + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group, gifaddr_str, + sizeof(gifaddr_str)); + pim_inet4_dump("", source, sifaddr_str, + sizeof(sifaddr_str)); + zlog_warn( + "%s %s: Unable to remove static route(iif=%d,oif=%d,group=%s,source=%s)", + __FILE__, __PRETTY_FUNCTION__, + iif_index, oif_index, gifaddr_str, + sifaddr_str); + + s_route->oif_ttls[oif_index] = 1; + s_route->c_oil.oil.mfcc_ttls[oif_index] = 1; + ++s_route->c_oil.oil_ref_count; + + return -1; + } + + s_route->c_oil.oif_creation[oif_index] = 0; + + if (s_route->c_oil.oil_ref_count <= 0) { + listnode_delete(qpim_static_route_list, + s_route); + pim_static_route_free(s_route); + } + + if (PIM_DEBUG_STATIC) { + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group, gifaddr_str, + sizeof(gifaddr_str)); + pim_inet4_dump("", source, sifaddr_str, + sizeof(sifaddr_str)); + zlog_debug( + "%s: Static route removed(iif=%d,oif=%d,group=%s,source=%s)", + __PRETTY_FUNCTION__, iif_index, + oif_index, gifaddr_str, sifaddr_str); + } + + break; + } + } + + if (!node) { + char gifaddr_str[INET_ADDRSTRLEN]; + char sifaddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", group, gifaddr_str, + sizeof(gifaddr_str)); + pim_inet4_dump("", source, sifaddr_str, + sizeof(sifaddr_str)); + zlog_warn( + "%s %s: Unable to remove static route: Route does not exist(iif=%d,oif=%d,group=%s,source=%s)", + __FILE__, __PRETTY_FUNCTION__, iif_index, oif_index, + gifaddr_str, sifaddr_str); + return -3; + } + + return 0; } -int -pim_static_write_mroute (struct vty *vty, struct interface *ifp) +int pim_static_write_mroute(struct vty *vty, struct interface *ifp) { - struct pim_interface *pim_ifp = ifp->info; - struct listnode *node; - struct static_route *sroute; - int count = 0; - char sbuf[INET_ADDRSTRLEN]; - char gbuf[INET_ADDRSTRLEN]; - - if (!pim_ifp) - return 0; - - for (ALL_LIST_ELEMENTS_RO (qpim_static_route_list, node, sroute)) - { - pim_inet4_dump ("", sroute->group, gbuf, sizeof (gbuf)); - pim_inet4_dump ("", sroute->source, sbuf, sizeof (sbuf)); - if (sroute->iif == pim_ifp->mroute_vif_index) - { - int i; - for (i = 0; i < MAXVIFS; i++) - if (sroute->oif_ttls[i]) - { - struct interface *oifp = pim_if_find_by_vif_index (i); - if (sroute->source.s_addr == 0) - vty_out (vty, " ip mroute %s %s\n", oifp->name, gbuf); - else - vty_out (vty, " ip mroute %s %s %s\n", oifp->name, gbuf, - sbuf); - count ++; - } - } - } - - return count; + struct pim_interface *pim_ifp = ifp->info; + struct listnode *node; + struct static_route *sroute; + int count = 0; + char sbuf[INET_ADDRSTRLEN]; + char gbuf[INET_ADDRSTRLEN]; + + if (!pim_ifp) + return 0; + + for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, sroute)) { + pim_inet4_dump("", sroute->group, gbuf, sizeof(gbuf)); + pim_inet4_dump("", sroute->source, sbuf, sizeof(sbuf)); + if (sroute->iif == pim_ifp->mroute_vif_index) { + int i; + for (i = 0; i < MAXVIFS; i++) + if (sroute->oif_ttls[i]) { + struct interface *oifp = + pim_if_find_by_vif_index(i); + if (sroute->source.s_addr == 0) + vty_out(vty, + " ip mroute %s %s\n", + oifp->name, gbuf); + else + vty_out(vty, + " ip mroute %s %s %s\n", + oifp->name, gbuf, sbuf); + count++; + } + } + } + + return count; } diff --git a/pimd/pim_static.h b/pimd/pim_static.h index 4b5ef7921..1114f4b67 100644 --- a/pimd/pim_static.h +++ b/pimd/pim_static.h @@ -25,19 +25,21 @@ #include "if.h" struct static_route { - /* Each static route is unique by these pair of addresses */ - struct in_addr group; - struct in_addr source; + /* Each static route is unique by these pair of addresses */ + struct in_addr group; + struct in_addr source; - struct channel_oil c_oil; - ifindex_t iif; - unsigned char oif_ttls[MAXVIFS]; + struct channel_oil c_oil; + ifindex_t iif; + unsigned char oif_ttls[MAXVIFS]; }; void pim_static_route_free(struct static_route *s_route); -int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr group, struct in_addr source); -int pim_static_del(struct interface *iif, struct interface *oif, struct in_addr group, struct in_addr source); -int pim_static_write_mroute (struct vty *vty, struct interface *ifp); +int pim_static_add(struct interface *iif, struct interface *oif, + struct in_addr group, struct in_addr source); +int pim_static_del(struct interface *iif, struct interface *oif, + struct in_addr group, struct in_addr source); +int pim_static_write_mroute(struct vty *vty, struct interface *ifp); #endif /* PIM_STATIC_H_ */ diff --git a/pimd/pim_str.c b/pimd/pim_str.c index d1219a868..fa1a6e624 100644 --- a/pimd/pim_str.c +++ b/pimd/pim_str.c @@ -27,62 +27,62 @@ #include "pim_str.h" -void pim_addr_dump (const char *onfail, struct prefix *p, char *buf, int buf_size) +void pim_addr_dump(const char *onfail, struct prefix *p, char *buf, + int buf_size) { - int save_errno = errno; + int save_errno = errno; - if (!inet_ntop(p->family, &p->u.prefix, buf, buf_size)) { - zlog_warn("pim_addr_dump: inet_ntop(buf_size=%d): errno=%d: %s", - buf_size, errno, safe_strerror(errno)); - if (onfail) - snprintf(buf, buf_size, "%s", onfail); - } + if (!inet_ntop(p->family, &p->u.prefix, buf, buf_size)) { + zlog_warn("pim_addr_dump: inet_ntop(buf_size=%d): errno=%d: %s", + buf_size, errno, safe_strerror(errno)); + if (onfail) + snprintf(buf, buf_size, "%s", onfail); + } - errno = save_errno; + errno = save_errno; } -void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, int buf_size) +void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, + int buf_size) { - int save_errno = errno; - - if (addr.s_addr == INADDR_ANY) - strcpy(buf, "*"); - else - { - if (!inet_ntop(AF_INET, &addr, buf, buf_size)) { - zlog_warn("pim_inet4_dump: inet_ntop(AF_INET,buf_size=%d): errno=%d: %s", - buf_size, errno, safe_strerror(errno)); - if (onfail) - snprintf(buf, buf_size, "%s", onfail); - } - } - - errno = save_errno; + int save_errno = errno; + + if (addr.s_addr == INADDR_ANY) + strcpy(buf, "*"); + else { + if (!inet_ntop(AF_INET, &addr, buf, buf_size)) { + zlog_warn( + "pim_inet4_dump: inet_ntop(AF_INET,buf_size=%d): errno=%d: %s", + buf_size, errno, safe_strerror(errno)); + if (onfail) + snprintf(buf, buf_size, "%s", onfail); + } + } + + errno = save_errno; } -char * -pim_str_sg_dump (const struct prefix_sg *sg) +char *pim_str_sg_dump(const struct prefix_sg *sg) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; - static char sg_str[PIM_SG_LEN]; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; + static char sg_str[PIM_SG_LEN]; - pim_inet4_dump ("", sg->src, src_str, sizeof(src_str)); - pim_inet4_dump ("", sg->grp, grp_str, sizeof(grp_str)); - snprintf (sg_str, PIM_SG_LEN, "(%s,%s)", src_str, grp_str); + pim_inet4_dump("", sg->src, src_str, sizeof(src_str)); + pim_inet4_dump("", sg->grp, grp_str, sizeof(grp_str)); + snprintf(sg_str, PIM_SG_LEN, "(%s,%s)", src_str, grp_str); - return sg_str; + return sg_str; } -char * -pim_str_sg_set (const struct prefix_sg *sg, char *sg_str) +char *pim_str_sg_set(const struct prefix_sg *sg, char *sg_str) { - char src_str[INET_ADDRSTRLEN]; - char grp_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; + char grp_str[INET_ADDRSTRLEN]; - pim_inet4_dump ("", sg->src, src_str, sizeof(src_str)); - pim_inet4_dump ("", sg->grp, grp_str, sizeof(grp_str)); - snprintf (sg_str, PIM_SG_LEN, "(%s,%s)", src_str, grp_str); + pim_inet4_dump("", sg->src, src_str, sizeof(src_str)); + pim_inet4_dump("", sg->grp, grp_str, sizeof(grp_str)); + snprintf(sg_str, PIM_SG_LEN, "(%s,%s)", src_str, grp_str); - return sg_str; + return sg_str; } diff --git a/pimd/pim_str.h b/pimd/pim_str.h index 0ca517102..12a33a810 100644 --- a/pimd/pim_str.h +++ b/pimd/pim_str.h @@ -35,9 +35,11 @@ */ #define PIM_SG_LEN 36 -void pim_addr_dump (const char *onfail, struct prefix *p, char *buf, int buf_size); -void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, int buf_size); -char *pim_str_sg_dump (const struct prefix_sg *sg); -char *pim_str_sg_set (const struct prefix_sg *sg, char *sg_str); +void pim_addr_dump(const char *onfail, struct prefix *p, char *buf, + int buf_size); +void pim_inet4_dump(const char *onfail, struct in_addr addr, char *buf, + int buf_size); +char *pim_str_sg_dump(const struct prefix_sg *sg); +char *pim_str_sg_set(const struct prefix_sg *sg, char *sg_str); #endif diff --git a/pimd/pim_time.c b/pimd/pim_time.c index 406fec58d..6f011da43 100644 --- a/pimd/pim_time.c +++ b/pimd/pim_time.c @@ -30,16 +30,15 @@ static int gettime_monotonic(struct timeval *tv) { - int result; + int result; - result = gettimeofday(tv, 0); - if (result) { - zlog_err("%s: gettimeofday() failure: errno=%d: %s", - __PRETTY_FUNCTION__, - errno, safe_strerror(errno)); - } + result = gettimeofday(tv, 0); + if (result) { + zlog_err("%s: gettimeofday() failure: errno=%d: %s", + __PRETTY_FUNCTION__, errno, safe_strerror(errno)); + } - return result; + return result; } /* @@ -48,16 +47,15 @@ static int gettime_monotonic(struct timeval *tv) */ int64_t pim_time_monotonic_sec() { - struct timeval now_tv; + struct timeval now_tv; - if (gettime_monotonic(&now_tv)) { - zlog_err("%s: gettime_monotonic() failure: errno=%d: %s", - __PRETTY_FUNCTION__, - errno, safe_strerror(errno)); - return -1; - } + if (gettime_monotonic(&now_tv)) { + zlog_err("%s: gettime_monotonic() failure: errno=%d: %s", + __PRETTY_FUNCTION__, errno, safe_strerror(errno)); + return -1; + } - return now_tv.tv_sec; + return now_tv.tv_sec; } /* @@ -66,117 +64,111 @@ int64_t pim_time_monotonic_sec() */ int64_t pim_time_monotonic_dsec() { - struct timeval now_tv; - int64_t now_dsec; + struct timeval now_tv; + int64_t now_dsec; - if (gettime_monotonic(&now_tv)) { - zlog_err("%s: gettime_monotonic() failure: errno=%d: %s", - __PRETTY_FUNCTION__, - errno, safe_strerror(errno)); - return -1; - } + if (gettime_monotonic(&now_tv)) { + zlog_err("%s: gettime_monotonic() failure: errno=%d: %s", + __PRETTY_FUNCTION__, errno, safe_strerror(errno)); + return -1; + } - now_dsec = ((int64_t) now_tv.tv_sec) * 10 + ((int64_t) now_tv.tv_usec) / 100000; + now_dsec = ((int64_t)now_tv.tv_sec) * 10 + + ((int64_t)now_tv.tv_usec) / 100000; - return now_dsec; + return now_dsec; } -int64_t -pim_time_monotonic_usec (void) +int64_t pim_time_monotonic_usec(void) { - struct timeval now_tv; - int64_t now_dsec; + struct timeval now_tv; + int64_t now_dsec; - if (gettime_monotonic(&now_tv)) { - zlog_err("%s: gettime_monotonic() failure: errno=%d: %s", - __PRETTY_FUNCTION__, - errno, safe_strerror(errno)); - return -1; - } + if (gettime_monotonic(&now_tv)) { + zlog_err("%s: gettime_monotonic() failure: errno=%d: %s", + __PRETTY_FUNCTION__, errno, safe_strerror(errno)); + return -1; + } - now_dsec = ((int64_t) now_tv.tv_sec) * 1000000 + ((int64_t) now_tv.tv_usec); - - return now_dsec; + now_dsec = + ((int64_t)now_tv.tv_sec) * 1000000 + ((int64_t)now_tv.tv_usec); + return now_dsec; } int pim_time_mmss(char *buf, int buf_size, long sec) { - long mm; - int wr; + long mm; + int wr; + + zassert(buf_size >= 5); - zassert(buf_size >= 5); + mm = sec / 60; + sec %= 60; - mm = sec / 60; - sec %= 60; - - wr = snprintf(buf, buf_size, "%02ld:%02ld", mm, sec); + wr = snprintf(buf, buf_size, "%02ld:%02ld", mm, sec); - return wr != 8; + return wr != 8; } static int pim_time_hhmmss(char *buf, int buf_size, long sec) { - long hh; - long mm; - int wr; + long hh; + long mm; + int wr; + + zassert(buf_size >= 8); - zassert(buf_size >= 8); + hh = sec / 3600; + sec %= 3600; + mm = sec / 60; + sec %= 60; - hh = sec / 3600; - sec %= 3600; - mm = sec / 60; - sec %= 60; - - wr = snprintf(buf, buf_size, "%02ld:%02ld:%02ld", hh, mm, sec); + wr = snprintf(buf, buf_size, "%02ld:%02ld:%02ld", hh, mm, sec); - return wr != 8; + return wr != 8; } void pim_time_timer_to_mmss(char *buf, int buf_size, struct thread *t_timer) { - if (t_timer) { - pim_time_mmss(buf, buf_size, - thread_timer_remain_second(t_timer)); - } - else { - snprintf(buf, buf_size, "--:--"); - } + if (t_timer) { + pim_time_mmss(buf, buf_size, + thread_timer_remain_second(t_timer)); + } else { + snprintf(buf, buf_size, "--:--"); + } } void pim_time_timer_to_hhmmss(char *buf, int buf_size, struct thread *t_timer) { - if (t_timer) { - pim_time_hhmmss(buf, buf_size, - thread_timer_remain_second(t_timer)); - } - else { - snprintf(buf, buf_size, "--:--:--"); - } + if (t_timer) { + pim_time_hhmmss(buf, buf_size, + thread_timer_remain_second(t_timer)); + } else { + snprintf(buf, buf_size, "--:--:--"); + } } void pim_time_uptime(char *buf, int buf_size, int64_t uptime_sec) { - zassert(buf_size >= 8); + zassert(buf_size >= 8); - pim_time_hhmmss(buf, buf_size, uptime_sec); + pim_time_hhmmss(buf, buf_size, uptime_sec); } void pim_time_uptime_begin(char *buf, int buf_size, int64_t now, int64_t begin) { - if (begin > 0) - pim_time_uptime(buf, buf_size, now - begin); - else - snprintf(buf, buf_size, "--:--:--"); + if (begin > 0) + pim_time_uptime(buf, buf_size, now - begin); + else + snprintf(buf, buf_size, "--:--:--"); } long pim_time_timer_remain_msec(struct thread *t_timer) { - /* FIXME: Actually fetch msec resolution from thread */ + /* FIXME: Actually fetch msec resolution from thread */ - /* no timer thread running means timer has expired: return 0 */ + /* no timer thread running means timer has expired: return 0 */ - return t_timer ? - 1000 * thread_timer_remain_second(t_timer) : - 0; + return t_timer ? 1000 * thread_timer_remain_second(t_timer) : 0; } diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c index 550fdde8e..6d7adf242 100644 --- a/pimd/pim_tlv.c +++ b/pimd/pim_tlv.c @@ -29,67 +29,61 @@ #include "pim_str.h" #include "pim_msg.h" -uint8_t *pim_tlv_append_uint16(uint8_t *buf, - const uint8_t *buf_pastend, - uint16_t option_type, - uint16_t option_value) +uint8_t *pim_tlv_append_uint16(uint8_t *buf, const uint8_t *buf_pastend, + uint16_t option_type, uint16_t option_value) { - uint16_t option_len = 2; + uint16_t option_len = 2; - if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) - return NULL; + if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) + return NULL; - *(uint16_t *) buf = htons(option_type); - buf += 2; - *(uint16_t *) buf = htons(option_len); - buf += 2; - *(uint16_t *) buf = htons(option_value); - buf += option_len; + *(uint16_t *)buf = htons(option_type); + buf += 2; + *(uint16_t *)buf = htons(option_len); + buf += 2; + *(uint16_t *)buf = htons(option_value); + buf += option_len; - return buf; + return buf; } -uint8_t *pim_tlv_append_2uint16(uint8_t *buf, - const uint8_t *buf_pastend, - uint16_t option_type, - uint16_t option_value1, +uint8_t *pim_tlv_append_2uint16(uint8_t *buf, const uint8_t *buf_pastend, + uint16_t option_type, uint16_t option_value1, uint16_t option_value2) { - uint16_t option_len = 4; + uint16_t option_len = 4; - if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) - return NULL; + if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) + return NULL; - *(uint16_t *) buf = htons(option_type); - buf += 2; - *(uint16_t *) buf = htons(option_len); - buf += 2; - *(uint16_t *) buf = htons(option_value1); - buf += 2; - *(uint16_t *) buf = htons(option_value2); - buf += 2; + *(uint16_t *)buf = htons(option_type); + buf += 2; + *(uint16_t *)buf = htons(option_len); + buf += 2; + *(uint16_t *)buf = htons(option_value1); + buf += 2; + *(uint16_t *)buf = htons(option_value2); + buf += 2; - return buf; + return buf; } -uint8_t *pim_tlv_append_uint32(uint8_t *buf, - const uint8_t *buf_pastend, - uint16_t option_type, - uint32_t option_value) +uint8_t *pim_tlv_append_uint32(uint8_t *buf, const uint8_t *buf_pastend, + uint16_t option_type, uint32_t option_value) { - uint16_t option_len = 4; + uint16_t option_len = 4; - if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) - return NULL; + if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend) + return NULL; - *(uint16_t *) buf = htons(option_type); - buf += 2; - *(uint16_t *) buf = htons(option_len); - buf += 2; - pim_write_uint32(buf, option_value); - buf += option_len; + *(uint16_t *)buf = htons(option_type); + buf += 2; + *(uint16_t *)buf = htons(option_len); + buf += 2; + pim_write_uint32(buf, option_value); + buf += option_len; - return buf; + return buf; } #define ucast_ipv4_encoding_len (2 + sizeof(struct in_addr)) @@ -108,7 +102,8 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf, * The PIM address family of the 'Unicast Address' field of this * address. * - * Values 0-127 are as assigned by the IANA for Internet Address * Families in [7]. Values 128-250 are reserved to be assigned by + * Values 0-127 are as assigned by the IANA for Internet Address * + * Families in [7]. Values 128-250 are reserved to be assigned by * the IANA for PIM-specific Address Families. Values 251 though * 255 are designated for private use. As there is no assignment * authority for this space, collisions should be expected. @@ -122,31 +117,33 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf, * The unicast address as represented by the given Address Family * and Encoding Type. */ -int -pim_encode_addr_ucast (uint8_t *buf, struct prefix *p) +int pim_encode_addr_ucast(uint8_t *buf, struct prefix *p) { - switch (p->family) - { - case AF_INET: - *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV4; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */ - ++buf; - *(uint8_t *)buf = 0; /* ucast IPv4 native encoding type (RFC 4601: 4.9.1) */ - ++buf; - memcpy (buf, &p->u.prefix4, sizeof (struct in_addr)); - return ucast_ipv4_encoding_len; - break; - case AF_INET6: - *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV6; - ++buf; - *(uint8_t *)buf = 0; - ++buf; - memcpy (buf, &p->u.prefix6, sizeof (struct in6_addr)); - return ucast_ipv6_encoding_len; - break; - default: - return 0; - break; - } + switch (p->family) { + case AF_INET: + *(uint8_t *)buf = + PIM_MSG_ADDRESS_FAMILY_IPV4; /* notice: AF_INET != + PIM_MSG_ADDRESS_FAMILY_IPV4 + */ + ++buf; + *(uint8_t *)buf = 0; /* ucast IPv4 native encoding type (RFC + 4601: 4.9.1) */ + ++buf; + memcpy(buf, &p->u.prefix4, sizeof(struct in_addr)); + return ucast_ipv4_encoding_len; + break; + case AF_INET6: + *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV6; + ++buf; + *(uint8_t *)buf = 0; + ++buf; + memcpy(buf, &p->u.prefix6, sizeof(struct in6_addr)); + return ucast_ipv6_encoding_len; + break; + default: + return 0; + break; + } } #define group_ipv4_encoding_len (4 + sizeof (struct in_addr)) @@ -194,614 +191,604 @@ pim_encode_addr_ucast (uint8_t *buf, struct prefix *p) * Group multicast Address * Contains the group address. */ -int -pim_encode_addr_group (uint8_t *buf, afi_t afi, int bidir, int scope, struct in_addr group) +int pim_encode_addr_group(uint8_t *buf, afi_t afi, int bidir, int scope, + struct in_addr group) { - uint8_t flags = 0; - - flags |= bidir << 8; - flags |= scope; - - switch (afi) - { - case AFI_IP: - *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV4; - ++buf; - *(uint8_t *)buf = 0; - ++buf; - *(uint8_t *)buf = flags; - ++buf; - *(uint8_t *)buf = 32; - ++buf; - memcpy (buf, &group, sizeof (struct in_addr)); - return group_ipv4_encoding_len; - break; - default: - return 0; - break; - } + uint8_t flags = 0; + + flags |= bidir << 8; + flags |= scope; + + switch (afi) { + case AFI_IP: + *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV4; + ++buf; + *(uint8_t *)buf = 0; + ++buf; + *(uint8_t *)buf = flags; + ++buf; + *(uint8_t *)buf = 32; + ++buf; + memcpy(buf, &group, sizeof(struct in_addr)); + return group_ipv4_encoding_len; + break; + default: + return 0; + break; + } } -uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, - const uint8_t *buf_pastend, - struct list *ifconnected, - int family) +uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend, + struct list *ifconnected, int family) { - struct listnode *node; - uint16_t option_len = 0; - uint8_t *curr; - size_t uel; - - node = listhead(ifconnected); - - /* Empty address list ? */ - if (!node) { - return buf; - } - - if (family == AF_INET) - uel = ucast_ipv4_encoding_len; - else - uel = ucast_ipv6_encoding_len; - - /* Scan secondary address list */ - curr = buf + 4; /* skip T and L */ - for (; node; node = listnextnode(node)) { - struct connected *ifc = listgetdata(node); - struct prefix *p = ifc->address; - int l_encode; - - if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) - continue; - - if ((curr + uel) > buf_pastend) - return 0; - - if (p->family != family) - continue; - - l_encode = pim_encode_addr_ucast (curr, p); - curr += l_encode; - option_len += l_encode; - } - - if (PIM_DEBUG_PIM_TRACE_DETAIL) { - zlog_debug("%s: number of encoded secondary unicast IPv4 addresses: %zu", - __PRETTY_FUNCTION__, - option_len / uel); - } - - if (option_len < 1) { - /* Empty secondary unicast IPv4 address list */ - return buf; - } - - /* - * Write T and L - */ - *(uint16_t *) buf = htons(PIM_MSG_OPTION_TYPE_ADDRESS_LIST); - *(uint16_t *) (buf + 2) = htons(option_len); - - return curr; + struct listnode *node; + uint16_t option_len = 0; + uint8_t *curr; + size_t uel; + + node = listhead(ifconnected); + + /* Empty address list ? */ + if (!node) { + return buf; + } + + if (family == AF_INET) + uel = ucast_ipv4_encoding_len; + else + uel = ucast_ipv6_encoding_len; + + /* Scan secondary address list */ + curr = buf + 4; /* skip T and L */ + for (; node; node = listnextnode(node)) { + struct connected *ifc = listgetdata(node); + struct prefix *p = ifc->address; + int l_encode; + + if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) + continue; + + if ((curr + uel) > buf_pastend) + return 0; + + if (p->family != family) + continue; + + l_encode = pim_encode_addr_ucast(curr, p); + curr += l_encode; + option_len += l_encode; + } + + if (PIM_DEBUG_PIM_TRACE_DETAIL) { + zlog_debug( + "%s: number of encoded secondary unicast IPv4 addresses: %zu", + __PRETTY_FUNCTION__, option_len / uel); + } + + if (option_len < 1) { + /* Empty secondary unicast IPv4 address list */ + return buf; + } + + /* + * Write T and L + */ + *(uint16_t *)buf = htons(PIM_MSG_OPTION_TYPE_ADDRESS_LIST); + *(uint16_t *)(buf + 2) = htons(option_len); + + return curr; } static int check_tlv_length(const char *label, const char *tlv_name, const char *ifname, struct in_addr src_addr, int correct_len, int option_len) { - if (option_len != correct_len) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: PIM hello %s TLV with incorrect value size=%d correct=%d from %s on interface %s", - label, tlv_name, - option_len, correct_len, - src_str, ifname); - return -1; - } - - return 0; + if (option_len != correct_len) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); + zlog_warn( + "%s: PIM hello %s TLV with incorrect value size=%d correct=%d from %s on interface %s", + label, tlv_name, option_len, correct_len, src_str, + ifname); + return -1; + } + + return 0; } -static void check_tlv_redefinition_uint16(const char *label, const char *tlv_name, - const char *ifname, struct in_addr src_addr, - pim_hello_options options, - pim_hello_options opt_mask, - uint16_t new, uint16_t old) +static void check_tlv_redefinition_uint16( + const char *label, const char *tlv_name, const char *ifname, + struct in_addr src_addr, pim_hello_options options, + pim_hello_options opt_mask, uint16_t new, uint16_t old) { - if (PIM_OPTION_IS_SET(options, opt_mask)) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s", - label, tlv_name, - new, old, - src_str, ifname); - } + if (PIM_OPTION_IS_SET(options, opt_mask)) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); + zlog_warn( + "%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s", + label, tlv_name, new, old, src_str, ifname); + } } -static void check_tlv_redefinition_uint32(const char *label, const char *tlv_name, - const char *ifname, struct in_addr src_addr, - pim_hello_options options, - pim_hello_options opt_mask, - uint32_t new, uint32_t old) +static void check_tlv_redefinition_uint32( + const char *label, const char *tlv_name, const char *ifname, + struct in_addr src_addr, pim_hello_options options, + pim_hello_options opt_mask, uint32_t new, uint32_t old) { - if (PIM_OPTION_IS_SET(options, opt_mask)) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s", - label, tlv_name, - new, old, - src_str, ifname); - } + if (PIM_OPTION_IS_SET(options, opt_mask)) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); + zlog_warn( + "%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s", + label, tlv_name, new, old, src_str, ifname); + } } -static void check_tlv_redefinition_uint32_hex(const char *label, const char *tlv_name, - const char *ifname, struct in_addr src_addr, - pim_hello_options options, - pim_hello_options opt_mask, - uint32_t new, uint32_t old) +static void check_tlv_redefinition_uint32_hex( + const char *label, const char *tlv_name, const char *ifname, + struct in_addr src_addr, pim_hello_options options, + pim_hello_options opt_mask, uint32_t new, uint32_t old) { - if (PIM_OPTION_IS_SET(options, opt_mask)) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: PIM hello TLV redefined %s=%08x old=%08x from %s on interface %s", - label, tlv_name, - new, old, - src_str, ifname); - } + if (PIM_OPTION_IS_SET(options, opt_mask)) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); + zlog_warn( + "%s: PIM hello TLV redefined %s=%08x old=%08x from %s on interface %s", + label, tlv_name, new, old, src_str, ifname); + } } int pim_tlv_parse_holdtime(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, - uint16_t *hello_option_holdtime, - uint16_t option_len, - const uint8_t *tlv_curr) + uint16_t *hello_option_holdtime, uint16_t option_len, + const uint8_t *tlv_curr) { - const char *label = "holdtime"; - - if (check_tlv_length(__PRETTY_FUNCTION__, label, - ifname, src_addr, - sizeof(uint16_t), option_len)) { - return -1; - } - - check_tlv_redefinition_uint16(__PRETTY_FUNCTION__, label, - ifname, src_addr, - *hello_options, PIM_OPTION_MASK_HOLDTIME, - PIM_TLV_GET_HOLDTIME(tlv_curr), - *hello_option_holdtime); - - PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_HOLDTIME); - - *hello_option_holdtime = PIM_TLV_GET_HOLDTIME(tlv_curr); - - return 0; + const char *label = "holdtime"; + + if (check_tlv_length(__PRETTY_FUNCTION__, label, ifname, src_addr, + sizeof(uint16_t), option_len)) { + return -1; + } + + check_tlv_redefinition_uint16( + __PRETTY_FUNCTION__, label, ifname, src_addr, *hello_options, + PIM_OPTION_MASK_HOLDTIME, PIM_TLV_GET_HOLDTIME(tlv_curr), + *hello_option_holdtime); + + PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_HOLDTIME); + + *hello_option_holdtime = PIM_TLV_GET_HOLDTIME(tlv_curr); + + return 0; } int pim_tlv_parse_lan_prune_delay(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, uint16_t *hello_option_propagation_delay, uint16_t *hello_option_override_interval, - uint16_t option_len, - const uint8_t *tlv_curr) + uint16_t option_len, const uint8_t *tlv_curr) { - if (check_tlv_length(__PRETTY_FUNCTION__, "lan_prune_delay", - ifname, src_addr, - sizeof(uint32_t), option_len)) { - return -1; - } - - check_tlv_redefinition_uint16(__PRETTY_FUNCTION__, "propagation_delay", - ifname, src_addr, - *hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY, - PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr), - *hello_option_propagation_delay); - - PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY); - - *hello_option_propagation_delay = PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr); - if (PIM_TLV_GET_CAN_DISABLE_JOIN_SUPPRESSION(tlv_curr)) { - PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION); - } - else { - PIM_OPTION_UNSET(*hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION); - } - ++tlv_curr; - ++tlv_curr; - *hello_option_override_interval = PIM_TLV_GET_OVERRIDE_INTERVAL(tlv_curr); - - return 0; + if (check_tlv_length(__PRETTY_FUNCTION__, "lan_prune_delay", ifname, + src_addr, sizeof(uint32_t), option_len)) { + return -1; + } + + check_tlv_redefinition_uint16(__PRETTY_FUNCTION__, "propagation_delay", + ifname, src_addr, *hello_options, + PIM_OPTION_MASK_LAN_PRUNE_DELAY, + PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr), + *hello_option_propagation_delay); + + PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY); + + *hello_option_propagation_delay = + PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr); + if (PIM_TLV_GET_CAN_DISABLE_JOIN_SUPPRESSION(tlv_curr)) { + PIM_OPTION_SET(*hello_options, + PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION); + } else { + PIM_OPTION_UNSET(*hello_options, + PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION); + } + ++tlv_curr; + ++tlv_curr; + *hello_option_override_interval = + PIM_TLV_GET_OVERRIDE_INTERVAL(tlv_curr); + + return 0; } int pim_tlv_parse_dr_priority(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, uint32_t *hello_option_dr_priority, - uint16_t option_len, - const uint8_t *tlv_curr) + uint16_t option_len, const uint8_t *tlv_curr) { - const char *label = "dr_priority"; - - if (check_tlv_length(__PRETTY_FUNCTION__, label, - ifname, src_addr, - sizeof(uint32_t), option_len)) { - return -1; - } - - check_tlv_redefinition_uint32(__PRETTY_FUNCTION__, label, - ifname, src_addr, - *hello_options, PIM_OPTION_MASK_DR_PRIORITY, - PIM_TLV_GET_DR_PRIORITY(tlv_curr), - *hello_option_dr_priority); - - PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_DR_PRIORITY); - - *hello_option_dr_priority = PIM_TLV_GET_DR_PRIORITY(tlv_curr); - - return 0; + const char *label = "dr_priority"; + + if (check_tlv_length(__PRETTY_FUNCTION__, label, ifname, src_addr, + sizeof(uint32_t), option_len)) { + return -1; + } + + check_tlv_redefinition_uint32( + __PRETTY_FUNCTION__, label, ifname, src_addr, *hello_options, + PIM_OPTION_MASK_DR_PRIORITY, PIM_TLV_GET_DR_PRIORITY(tlv_curr), + *hello_option_dr_priority); + + PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_DR_PRIORITY); + + *hello_option_dr_priority = PIM_TLV_GET_DR_PRIORITY(tlv_curr); + + return 0; } int pim_tlv_parse_generation_id(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, uint32_t *hello_option_generation_id, - uint16_t option_len, - const uint8_t *tlv_curr) + uint16_t option_len, const uint8_t *tlv_curr) { - const char *label = "generation_id"; - - if (check_tlv_length(__PRETTY_FUNCTION__, label, - ifname, src_addr, - sizeof(uint32_t), option_len)) { - return -1; - } - - check_tlv_redefinition_uint32_hex(__PRETTY_FUNCTION__, label, - ifname, src_addr, - *hello_options, PIM_OPTION_MASK_GENERATION_ID, - PIM_TLV_GET_GENERATION_ID(tlv_curr), - *hello_option_generation_id); - - PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_GENERATION_ID); - - *hello_option_generation_id = PIM_TLV_GET_GENERATION_ID(tlv_curr); - - return 0; + const char *label = "generation_id"; + + if (check_tlv_length(__PRETTY_FUNCTION__, label, ifname, src_addr, + sizeof(uint32_t), option_len)) { + return -1; + } + + check_tlv_redefinition_uint32_hex(__PRETTY_FUNCTION__, label, ifname, + src_addr, *hello_options, + PIM_OPTION_MASK_GENERATION_ID, + PIM_TLV_GET_GENERATION_ID(tlv_curr), + *hello_option_generation_id); + + PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_GENERATION_ID); + + *hello_option_generation_id = PIM_TLV_GET_GENERATION_ID(tlv_curr); + + return 0; } -int -pim_parse_addr_ucast (struct prefix *p, - const uint8_t *buf, - int buf_size) +int pim_parse_addr_ucast(struct prefix *p, const uint8_t *buf, int buf_size) { - const int ucast_encoding_min_len = 3; /* 1 family + 1 type + 1 addr */ - const uint8_t *addr; - const uint8_t *pastend; - int family; - int type; - - if (buf_size < ucast_encoding_min_len) { - zlog_warn("%s: unicast address encoding overflow: left=%d needed=%d", - __PRETTY_FUNCTION__, - buf_size, ucast_encoding_min_len); - return -1; - } - - addr = buf; - pastend = buf + buf_size; - - family = *addr++; - type = *addr++; - - if (type) { - zlog_warn("%s: unknown unicast address encoding type=%d", - __PRETTY_FUNCTION__, - type); - return -2; - } - - switch (family) { - case PIM_MSG_ADDRESS_FAMILY_IPV4: - if ((addr + sizeof(struct in_addr)) > pastend) { - zlog_warn("%s: IPv4 unicast address overflow: left=%zd needed=%zu", - __PRETTY_FUNCTION__, - pastend - addr, sizeof(struct in_addr)); - return -3; - } - - p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */ - memcpy(&p->u.prefix4, addr, sizeof(struct in_addr)); - p->prefixlen = IPV4_MAX_PREFIXLEN; - addr += sizeof(struct in_addr); - - break; - case PIM_MSG_ADDRESS_FAMILY_IPV6: - if ((addr + sizeof(struct in6_addr)) > pastend) { - zlog_warn ("%s: IPv6 unicast address overflow: left=%zd needed %zu", - __PRETTY_FUNCTION__, - pastend - addr, sizeof(struct in6_addr)); - return -3; - } - - p->family = AF_INET6; - p->prefixlen = IPV6_MAX_PREFIXLEN; - memcpy(&p->u.prefix6, addr, sizeof(struct in6_addr)); - addr += sizeof(struct in6_addr); - - break; - default: - { - zlog_warn("%s: unknown unicast address encoding family=%d from", - __PRETTY_FUNCTION__, - family); - return -4; - } - } - - return addr - buf; + const int ucast_encoding_min_len = 3; /* 1 family + 1 type + 1 addr */ + const uint8_t *addr; + const uint8_t *pastend; + int family; + int type; + + if (buf_size < ucast_encoding_min_len) { + zlog_warn( + "%s: unicast address encoding overflow: left=%d needed=%d", + __PRETTY_FUNCTION__, buf_size, ucast_encoding_min_len); + return -1; + } + + addr = buf; + pastend = buf + buf_size; + + family = *addr++; + type = *addr++; + + if (type) { + zlog_warn("%s: unknown unicast address encoding type=%d", + __PRETTY_FUNCTION__, type); + return -2; + } + + switch (family) { + case PIM_MSG_ADDRESS_FAMILY_IPV4: + if ((addr + sizeof(struct in_addr)) > pastend) { + zlog_warn( + "%s: IPv4 unicast address overflow: left=%zd needed=%zu", + __PRETTY_FUNCTION__, pastend - addr, + sizeof(struct in_addr)); + return -3; + } + + p->family = AF_INET; /* notice: AF_INET != + PIM_MSG_ADDRESS_FAMILY_IPV4 */ + memcpy(&p->u.prefix4, addr, sizeof(struct in_addr)); + p->prefixlen = IPV4_MAX_PREFIXLEN; + addr += sizeof(struct in_addr); + + break; + case PIM_MSG_ADDRESS_FAMILY_IPV6: + if ((addr + sizeof(struct in6_addr)) > pastend) { + zlog_warn( + "%s: IPv6 unicast address overflow: left=%zd needed %zu", + __PRETTY_FUNCTION__, pastend - addr, + sizeof(struct in6_addr)); + return -3; + } + + p->family = AF_INET6; + p->prefixlen = IPV6_MAX_PREFIXLEN; + memcpy(&p->u.prefix6, addr, sizeof(struct in6_addr)); + addr += sizeof(struct in6_addr); + + break; + default: { + zlog_warn("%s: unknown unicast address encoding family=%d from", + __PRETTY_FUNCTION__, family); + return -4; + } + } + + return addr - buf; } -int -pim_parse_addr_group (struct prefix_sg *sg, - const uint8_t *buf, - int buf_size) +int pim_parse_addr_group(struct prefix_sg *sg, const uint8_t *buf, int buf_size) { - const int grp_encoding_min_len = 4; /* 1 family + 1 type + 1 reserved + 1 addr */ - const uint8_t *addr; - const uint8_t *pastend; - int family; - int type; - int mask_len; - - if (buf_size < grp_encoding_min_len) { - zlog_warn("%s: group address encoding overflow: left=%d needed=%d", - __PRETTY_FUNCTION__, - buf_size, grp_encoding_min_len); - return -1; - } - - addr = buf; - pastend = buf + buf_size; - - family = *addr++; - type = *addr++; - //++addr; - ++addr; /* skip b_reserved_z fields */ - mask_len = *addr++; - - switch (family) { - case PIM_MSG_ADDRESS_FAMILY_IPV4: - if (type) { - zlog_warn("%s: unknown group address encoding type=%d from", - __PRETTY_FUNCTION__, type); - return -2; - } - - if ((addr + sizeof(struct in_addr)) > pastend) { - zlog_warn("%s: IPv4 group address overflow: left=%zd needed=%zu from", - __PRETTY_FUNCTION__, - pastend - addr, sizeof(struct in_addr)); - return -3; - } - - memcpy(&sg->grp.s_addr, addr, sizeof(struct in_addr)); - - addr += sizeof(struct in_addr); - - break; - default: - { - zlog_warn("%s: unknown group address encoding family=%d mask_len=%d from", - __PRETTY_FUNCTION__, family, mask_len); - return -4; - } - } - - return addr - buf; + const int grp_encoding_min_len = + 4; /* 1 family + 1 type + 1 reserved + 1 addr */ + const uint8_t *addr; + const uint8_t *pastend; + int family; + int type; + int mask_len; + + if (buf_size < grp_encoding_min_len) { + zlog_warn( + "%s: group address encoding overflow: left=%d needed=%d", + __PRETTY_FUNCTION__, buf_size, grp_encoding_min_len); + return -1; + } + + addr = buf; + pastend = buf + buf_size; + + family = *addr++; + type = *addr++; + //++addr; + ++addr; /* skip b_reserved_z fields */ + mask_len = *addr++; + + switch (family) { + case PIM_MSG_ADDRESS_FAMILY_IPV4: + if (type) { + zlog_warn( + "%s: unknown group address encoding type=%d from", + __PRETTY_FUNCTION__, type); + return -2; + } + + if ((addr + sizeof(struct in_addr)) > pastend) { + zlog_warn( + "%s: IPv4 group address overflow: left=%zd needed=%zu from", + __PRETTY_FUNCTION__, pastend - addr, + sizeof(struct in_addr)); + return -3; + } + + memcpy(&sg->grp.s_addr, addr, sizeof(struct in_addr)); + + addr += sizeof(struct in_addr); + + break; + default: { + zlog_warn( + "%s: unknown group address encoding family=%d mask_len=%d from", + __PRETTY_FUNCTION__, family, mask_len); + return -4; + } + } + + return addr - buf; } -int -pim_parse_addr_source(struct prefix_sg *sg, - uint8_t *flags, - const uint8_t *buf, - int buf_size) +int pim_parse_addr_source(struct prefix_sg *sg, uint8_t *flags, + const uint8_t *buf, int buf_size) { - const int src_encoding_min_len = 4; /* 1 family + 1 type + 1 reserved + 1 addr */ - const uint8_t *addr; - const uint8_t *pastend; - int family; - int type; - int mask_len; - - if (buf_size < src_encoding_min_len) { - zlog_warn("%s: source address encoding overflow: left=%d needed=%d", - __PRETTY_FUNCTION__, - buf_size, src_encoding_min_len); - return -1; - } - - addr = buf; - pastend = buf + buf_size; - - family = *addr++; - type = *addr++; - *flags = *addr++; - mask_len = *addr++; - - if (type) { - zlog_warn("%s: unknown source address encoding type=%d: %02x%02x%02x%02x%02x%02x%02x%02x", - __PRETTY_FUNCTION__, - type, - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); - return -2; - } - - switch (family) { - case PIM_MSG_ADDRESS_FAMILY_IPV4: - if ((addr + sizeof(struct in_addr)) > pastend) { - zlog_warn("%s: IPv4 source address overflow: left=%zd needed=%zu", - __PRETTY_FUNCTION__, - pastend - addr, sizeof(struct in_addr)); - return -3; - } - - memcpy(&sg->src, addr, sizeof(struct in_addr)); - - /* - RFC 4601: 4.9.1 Encoded Source and Group Address Formats - - Encoded-Source Address - - The mask length MUST be equal to the mask length in bits for - the given Address Family and Encoding Type (32 for IPv4 native - and 128 for IPv6 native). A router SHOULD ignore any messages - received with any other mask length. - */ - if (mask_len != 32) { - zlog_warn("%s: IPv4 bad source address mask: %d", - __PRETTY_FUNCTION__, mask_len); - return -4; - } - - addr += sizeof(struct in_addr); - - break; - default: - { - zlog_warn("%s: unknown source address encoding family=%d: %02x%02x%02x%02x%02x%02x%02x%02x", - __PRETTY_FUNCTION__, - family, - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); - return -5; - } - } - - return addr - buf; -} + const int src_encoding_min_len = + 4; /* 1 family + 1 type + 1 reserved + 1 addr */ + const uint8_t *addr; + const uint8_t *pastend; + int family; + int type; + int mask_len; + + if (buf_size < src_encoding_min_len) { + zlog_warn( + "%s: source address encoding overflow: left=%d needed=%d", + __PRETTY_FUNCTION__, buf_size, src_encoding_min_len); + return -1; + } + + addr = buf; + pastend = buf + buf_size; + + family = *addr++; + type = *addr++; + *flags = *addr++; + mask_len = *addr++; -#define FREE_ADDR_LIST(hello_option_addr_list) \ -{ \ - if (hello_option_addr_list) { \ - list_delete(hello_option_addr_list); \ - hello_option_addr_list = 0; \ - } \ + if (type) { + zlog_warn( + "%s: unknown source address encoding type=%d: %02x%02x%02x%02x%02x%02x%02x%02x", + __PRETTY_FUNCTION__, type, buf[0], buf[1], buf[2], + buf[3], buf[4], buf[5], buf[6], buf[7]); + return -2; + } + + switch (family) { + case PIM_MSG_ADDRESS_FAMILY_IPV4: + if ((addr + sizeof(struct in_addr)) > pastend) { + zlog_warn( + "%s: IPv4 source address overflow: left=%zd needed=%zu", + __PRETTY_FUNCTION__, pastend - addr, + sizeof(struct in_addr)); + return -3; + } + + memcpy(&sg->src, addr, sizeof(struct in_addr)); + + /* + RFC 4601: 4.9.1 Encoded Source and Group Address Formats + + Encoded-Source Address + + The mask length MUST be equal to the mask length in bits for + the given Address Family and Encoding Type (32 for IPv4 + native + and 128 for IPv6 native). A router SHOULD ignore any + messages + received with any other mask length. + */ + if (mask_len != 32) { + zlog_warn("%s: IPv4 bad source address mask: %d", + __PRETTY_FUNCTION__, mask_len); + return -4; + } + + addr += sizeof(struct in_addr); + + break; + default: { + zlog_warn( + "%s: unknown source address encoding family=%d: %02x%02x%02x%02x%02x%02x%02x%02x", + __PRETTY_FUNCTION__, family, buf[0], buf[1], buf[2], + buf[3], buf[4], buf[5], buf[6], buf[7]); + return -5; + } + } + + return addr - buf; } +#define FREE_ADDR_LIST(hello_option_addr_list) \ + { \ + if (hello_option_addr_list) { \ + list_delete(hello_option_addr_list); \ + hello_option_addr_list = 0; \ + } \ + } + int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, struct list **hello_option_addr_list, - uint16_t option_len, - const uint8_t *tlv_curr) + uint16_t option_len, const uint8_t *tlv_curr) { - const uint8_t *addr; - const uint8_t *pastend; - - zassert(hello_option_addr_list); - - /* - Scan addr list - */ - addr = tlv_curr; - pastend = tlv_curr + option_len; - while (addr < pastend) { - struct prefix tmp; - int addr_offset; - - /* - Parse ucast addr - */ - addr_offset = pim_parse_addr_ucast(&tmp, addr, pastend - addr); - if (addr_offset < 1) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s", - __PRETTY_FUNCTION__, - src_str, ifname); - FREE_ADDR_LIST(*hello_option_addr_list); - return -1; - } - addr += addr_offset; - - /* - Debug - */ - if (PIM_DEBUG_PIM_TRACE) { - switch (tmp.family) { - case AF_INET: - { - char addr_str[INET_ADDRSTRLEN]; - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", tmp.u.prefix4, addr_str, sizeof(addr_str)); - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: PIM hello TLV option: list_old_size=%d IPv4 address %s from %s on %s", - __PRETTY_FUNCTION__, - *hello_option_addr_list ? - ((int) listcount(*hello_option_addr_list)) : -1, - addr_str, src_str, ifname); - } - break; - case AF_INET6: - break; - default: - { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_debug("%s: PIM hello TLV option: list_old_size=%d UNKNOWN address family from %s on %s", - __PRETTY_FUNCTION__, - *hello_option_addr_list ? - ((int) listcount(*hello_option_addr_list)) : -1, - src_str, ifname); - } - } - } - - /* - Exclude neighbor's primary address if incorrectly included in - the secondary address list - */ - if (tmp.family == AF_INET) { - if (tmp.u.prefix4.s_addr == src_addr.s_addr) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", src_addr, src_str, sizeof(src_str)); - zlog_warn("%s: ignoring primary address in secondary list from %s on %s", - __PRETTY_FUNCTION__, - src_str, ifname); - continue; - } - } - - /* - Allocate list if needed - */ - if (!*hello_option_addr_list) { - *hello_option_addr_list = list_new(); - if (!*hello_option_addr_list) { - zlog_err("%s %s: failure: hello_option_addr_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return -2; - } - (*hello_option_addr_list)->del = (void (*)(void *)) prefix_free; - } - - /* - Attach addr to list - */ - { - struct prefix *p; - p = prefix_new(); - if (!p) { - zlog_err("%s %s: failure: prefix_new()", - __FILE__, __PRETTY_FUNCTION__); - FREE_ADDR_LIST(*hello_option_addr_list); - return -3; - } - prefix_copy(p, &tmp); - listnode_add(*hello_option_addr_list, p); - } - - } /* while (addr < pastend) */ - - /* - Mark hello option - */ - PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_ADDRESS_LIST); - - return 0; + const uint8_t *addr; + const uint8_t *pastend; + + zassert(hello_option_addr_list); + + /* + Scan addr list + */ + addr = tlv_curr; + pastend = tlv_curr + option_len; + while (addr < pastend) { + struct prefix tmp; + int addr_offset; + + /* + Parse ucast addr + */ + addr_offset = pim_parse_addr_ucast(&tmp, addr, pastend - addr); + if (addr_offset < 1) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, + sizeof(src_str)); + zlog_warn( + "%s: pim_parse_addr_ucast() failure: from %s on %s", + __PRETTY_FUNCTION__, src_str, ifname); + FREE_ADDR_LIST(*hello_option_addr_list); + return -1; + } + addr += addr_offset; + + /* + Debug + */ + if (PIM_DEBUG_PIM_TRACE) { + switch (tmp.family) { + case AF_INET: { + char addr_str[INET_ADDRSTRLEN]; + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", tmp.u.prefix4, + addr_str, sizeof(addr_str)); + pim_inet4_dump("", src_addr, src_str, + sizeof(src_str)); + zlog_debug( + "%s: PIM hello TLV option: list_old_size=%d IPv4 address %s from %s on %s", + __PRETTY_FUNCTION__, + *hello_option_addr_list + ? ((int)listcount( + *hello_option_addr_list)) + : -1, + addr_str, src_str, ifname); + } break; + case AF_INET6: + break; + default: { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, + sizeof(src_str)); + zlog_debug( + "%s: PIM hello TLV option: list_old_size=%d UNKNOWN address family from %s on %s", + __PRETTY_FUNCTION__, + *hello_option_addr_list + ? ((int)listcount( + *hello_option_addr_list)) + : -1, + src_str, ifname); + } + } + } + + /* + Exclude neighbor's primary address if incorrectly included in + the secondary address list + */ + if (tmp.family == AF_INET) { + if (tmp.u.prefix4.s_addr == src_addr.s_addr) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", src_addr, src_str, + sizeof(src_str)); + zlog_warn( + "%s: ignoring primary address in secondary list from %s on %s", + __PRETTY_FUNCTION__, src_str, ifname); + continue; + } + } + + /* + Allocate list if needed + */ + if (!*hello_option_addr_list) { + *hello_option_addr_list = list_new(); + if (!*hello_option_addr_list) { + zlog_err( + "%s %s: failure: hello_option_addr_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return -2; + } + (*hello_option_addr_list)->del = + (void (*)(void *))prefix_free; + } + + /* + Attach addr to list + */ + { + struct prefix *p; + p = prefix_new(); + if (!p) { + zlog_err("%s %s: failure: prefix_new()", + __FILE__, __PRETTY_FUNCTION__); + FREE_ADDR_LIST(*hello_option_addr_list); + return -3; + } + prefix_copy(p, &tmp); + listnode_add(*hello_option_addr_list, p); + } + + } /* while (addr < pastend) */ + + /* + Mark hello option + */ + PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_ADDRESS_LIST); + + return 0; } diff --git a/pimd/pim_tlv.h b/pimd/pim_tlv.h index f80e1fba2..657675b31 100644 --- a/pimd/pim_tlv.h +++ b/pimd/pim_tlv.h @@ -64,63 +64,46 @@ typedef uint32_t pim_hello_options; #define PIM_TLV_MIN_SIZE (PIM_TLV_TYPE_SIZE + PIM_TLV_LENGTH_SIZE) #define PIM_TLV_OPTION_SIZE(option_len) (PIM_TLV_MIN_SIZE + (option_len)) -uint8_t *pim_tlv_append_uint16(uint8_t *buf, - const uint8_t *buf_pastend, - uint16_t option_type, - uint16_t option_value); -uint8_t *pim_tlv_append_2uint16(uint8_t *buf, - const uint8_t *buf_pastend, - uint16_t option_type, - uint16_t option_value1, +uint8_t *pim_tlv_append_uint16(uint8_t *buf, const uint8_t *buf_pastend, + uint16_t option_type, uint16_t option_value); +uint8_t *pim_tlv_append_2uint16(uint8_t *buf, const uint8_t *buf_pastend, + uint16_t option_type, uint16_t option_value1, uint16_t option_value2); -uint8_t *pim_tlv_append_uint32(uint8_t *buf, - const uint8_t *buf_pastend, - uint16_t option_type, - uint32_t option_value); -uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, - const uint8_t *buf_pastend, - struct list *ifconnected, - int family); +uint8_t *pim_tlv_append_uint32(uint8_t *buf, const uint8_t *buf_pastend, + uint16_t option_type, uint32_t option_value); +uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend, + struct list *ifconnected, int family); int pim_tlv_parse_holdtime(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, - uint16_t *hello_option_holdtime, - uint16_t option_len, + uint16_t *hello_option_holdtime, uint16_t option_len, const uint8_t *tlv_curr); int pim_tlv_parse_lan_prune_delay(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, uint16_t *hello_option_propagation_delay, uint16_t *hello_option_override_interval, - uint16_t option_len, - const uint8_t *tlv_curr); + uint16_t option_len, const uint8_t *tlv_curr); int pim_tlv_parse_dr_priority(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, uint32_t *hello_option_dr_priority, - uint16_t option_len, - const uint8_t *tlv_curr); + uint16_t option_len, const uint8_t *tlv_curr); int pim_tlv_parse_generation_id(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, uint32_t *hello_option_generation_id, - uint16_t option_len, - const uint8_t *tlv_curr); + uint16_t option_len, const uint8_t *tlv_curr); int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, pim_hello_options *hello_options, struct list **hello_option_addr_list, - uint16_t option_len, - const uint8_t *tlv_curr); + uint16_t option_len, const uint8_t *tlv_curr); -int pim_encode_addr_ucast (uint8_t *buf, struct prefix *p); -int pim_encode_addr_group (uint8_t *buf, afi_t afi, int bidir, int scope, struct in_addr group); +int pim_encode_addr_ucast(uint8_t *buf, struct prefix *p); +int pim_encode_addr_group(uint8_t *buf, afi_t afi, int bidir, int scope, + struct in_addr group); -int pim_parse_addr_ucast (struct prefix *p, - const uint8_t *buf, - int buf_size); -int pim_parse_addr_group (struct prefix_sg *sg, - const uint8_t *buf, - int buf_size); -int pim_parse_addr_source(struct prefix_sg *sg, - uint8_t *flags, - const uint8_t *buf, - int buf_size); +int pim_parse_addr_ucast(struct prefix *p, const uint8_t *buf, int buf_size); +int pim_parse_addr_group(struct prefix_sg *sg, const uint8_t *buf, + int buf_size); +int pim_parse_addr_source(struct prefix_sg *sg, uint8_t *flags, + const uint8_t *buf, int buf_size); #endif /* PIM_TLV_H */ diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 442cb02a1..0ddd04c38 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -59,35 +59,33 @@ struct list *pim_upstream_list = NULL; struct timer_wheel *pim_upstream_sg_wheel = NULL; static void join_timer_stop(struct pim_upstream *up); -static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up); +static void +pim_upstream_update_assert_tracking_desired(struct pim_upstream *up); /* * A (*,G) or a (*,*) is going away * remove the parent pointer from * those pointing at us */ -static void -pim_upstream_remove_children (struct pim_upstream *up) +static void pim_upstream_remove_children(struct pim_upstream *up) { - struct pim_upstream *child; - - if (!up->sources) - return; - - while (!list_isempty (up->sources)) - { - child = listnode_head (up->sources); - listnode_delete (up->sources, child); - if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(child->flags)) - { - PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(child->flags); - child = pim_upstream_del(child, __PRETTY_FUNCTION__); - } - if (child) - child->parent = NULL; - } - list_delete(up->sources); - up->sources = NULL; + struct pim_upstream *child; + + if (!up->sources) + return; + + while (!list_isempty(up->sources)) { + child = listnode_head(up->sources); + listnode_delete(up->sources, child); + if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(child->flags)) { + PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(child->flags); + child = pim_upstream_del(child, __PRETTY_FUNCTION__); + } + if (child) + child->parent = NULL; + } + list_delete(up->sources); + up->sources = NULL; } /* @@ -95,30 +93,27 @@ pim_upstream_remove_children (struct pim_upstream *up) * Find the children that would point * at us. */ -static void -pim_upstream_find_new_children (struct pim_upstream *up) +static void pim_upstream_find_new_children(struct pim_upstream *up) { - struct pim_upstream *child; - struct listnode *ch_node; - - if ((up->sg.src.s_addr != INADDR_ANY) && - (up->sg.grp.s_addr != INADDR_ANY)) - return; - - if ((up->sg.src.s_addr == INADDR_ANY) && - (up->sg.grp.s_addr == INADDR_ANY)) - return; - - for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, ch_node, child)) - { - if ((up->sg.grp.s_addr != INADDR_ANY) && - (child->sg.grp.s_addr == up->sg.grp.s_addr) && - (child != up)) - { - child->parent = up; - listnode_add_sort (up->sources, child); + struct pim_upstream *child; + struct listnode *ch_node; + + if ((up->sg.src.s_addr != INADDR_ANY) + && (up->sg.grp.s_addr != INADDR_ANY)) + return; + + if ((up->sg.src.s_addr == INADDR_ANY) + && (up->sg.grp.s_addr == INADDR_ANY)) + return; + + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, ch_node, child)) { + if ((up->sg.grp.s_addr != INADDR_ANY) + && (child->sg.grp.s_addr == up->sg.grp.s_addr) + && (child != up)) { + child->parent = up; + listnode_add_sort(up->sources, child); + } } - } } /* @@ -126,218 +121,211 @@ pim_upstream_find_new_children (struct pim_upstream *up) * If we have a (S,G), find the (*,G) * If we have a (*,G), find the (*,*) */ -static struct pim_upstream * -pim_upstream_find_parent (struct pim_upstream *child) +static struct pim_upstream *pim_upstream_find_parent(struct pim_upstream *child) { - struct prefix_sg any = child->sg; - struct pim_upstream *up = NULL; + struct prefix_sg any = child->sg; + struct pim_upstream *up = NULL; - // (S,G) - if ((child->sg.src.s_addr != INADDR_ANY) && - (child->sg.grp.s_addr != INADDR_ANY)) - { - any.src.s_addr = INADDR_ANY; - up = pim_upstream_find (&any); + // (S,G) + if ((child->sg.src.s_addr != INADDR_ANY) + && (child->sg.grp.s_addr != INADDR_ANY)) { + any.src.s_addr = INADDR_ANY; + up = pim_upstream_find(&any); - if (up) - listnode_add (up->sources, child); + if (up) + listnode_add(up->sources, child); - return up; - } + return up; + } - return NULL; + return NULL; } void pim_upstream_free(struct pim_upstream *up) { - XFREE(MTYPE_PIM_UPSTREAM, up); - up = NULL; + XFREE(MTYPE_PIM_UPSTREAM, up); + up = NULL; } static void upstream_channel_oil_detach(struct pim_upstream *up) { - if (up->channel_oil) - { - /* Detaching from channel_oil, channel_oil may exist post del, - but upstream would not keep reference of it - */ - pim_channel_oil_del(up->channel_oil); - up->channel_oil = NULL; - } + if (up->channel_oil) { + /* Detaching from channel_oil, channel_oil may exist post del, + but upstream would not keep reference of it + */ + pim_channel_oil_del(up->channel_oil); + up->channel_oil = NULL; + } } -struct pim_upstream * -pim_upstream_del(struct pim_upstream *up, const char *name) +struct pim_upstream *pim_upstream_del(struct pim_upstream *up, const char *name) { - bool notify_msdp = false; - struct prefix nht_p; - - if (PIM_DEBUG_TRACE) - zlog_debug ("%s(%s): Delete %s ref count: %d , flags: %d c_oil ref count %d (Pre decrement)", - __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count, up->flags, - up->channel_oil->oil_ref_count); - - --up->ref_count; - - if (up->ref_count >= 1) - return up; - - THREAD_OFF(up->t_ka_timer); - THREAD_OFF(up->t_rs_timer); - THREAD_OFF(up->t_msdp_reg_timer); - - if (up->join_state == PIM_UPSTREAM_JOINED) { - pim_jp_agg_single_upstream_send (&up->rpf, up, 0); - - if (up->sg.src.s_addr == INADDR_ANY) { - /* if a (*, G) entry in the joined state is being deleted we - * need to notify MSDP */ - notify_msdp = true; - } - } - - join_timer_stop(up); - pim_jp_agg_upstream_verification (up, false); - up->rpf.source_nexthop.interface = NULL; - - if (up->sg.src.s_addr != INADDR_ANY) { - wheel_remove_item (pim_upstream_sg_wheel, up); - notify_msdp = true; - } - - pim_upstream_remove_children (up); - if (up->sources) - list_delete (up->sources); - up->sources = NULL; - pim_mroute_del (up->channel_oil, __PRETTY_FUNCTION__); - upstream_channel_oil_detach(up); - - list_delete (up->ifchannels); - up->ifchannels = NULL; - - /* - notice that listnode_delete() can't be moved - into pim_upstream_free() because the later is - called by list_delete_all_node() - */ - if (up->parent && up->parent->sources) - listnode_delete (up->parent->sources, up); - up->parent = NULL; - - listnode_delete (pim_upstream_list, up); - hash_release (pim_upstream_hash, up); - - if (notify_msdp) - { - pim_msdp_up_del (&up->sg); - } - - /* Deregister addr with Zebra NHT */ - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = up->upstream_addr; - if (PIM_DEBUG_TRACE) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str (&nht_p, buf, sizeof (buf)); - zlog_debug ("%s: Deregister upstream %s addr %s with Zebra NHT", - __PRETTY_FUNCTION__, up->sg_str, buf); - } - pim_delete_tracked_nexthop (&nht_p, up, NULL); - - pim_upstream_free (up); - - return NULL; + bool notify_msdp = false; + struct prefix nht_p; + + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s(%s): Delete %s ref count: %d , flags: %d c_oil ref count %d (Pre decrement)", + __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count, + up->flags, up->channel_oil->oil_ref_count); + + --up->ref_count; + + if (up->ref_count >= 1) + return up; + + THREAD_OFF(up->t_ka_timer); + THREAD_OFF(up->t_rs_timer); + THREAD_OFF(up->t_msdp_reg_timer); + + if (up->join_state == PIM_UPSTREAM_JOINED) { + pim_jp_agg_single_upstream_send(&up->rpf, up, 0); + + if (up->sg.src.s_addr == INADDR_ANY) { + /* if a (*, G) entry in the joined state is being + * deleted we + * need to notify MSDP */ + notify_msdp = true; + } + } + + join_timer_stop(up); + pim_jp_agg_upstream_verification(up, false); + up->rpf.source_nexthop.interface = NULL; + + if (up->sg.src.s_addr != INADDR_ANY) { + wheel_remove_item(pim_upstream_sg_wheel, up); + notify_msdp = true; + } + + pim_upstream_remove_children(up); + if (up->sources) + list_delete(up->sources); + up->sources = NULL; + pim_mroute_del(up->channel_oil, __PRETTY_FUNCTION__); + upstream_channel_oil_detach(up); + + list_delete(up->ifchannels); + up->ifchannels = NULL; + + /* + notice that listnode_delete() can't be moved + into pim_upstream_free() because the later is + called by list_delete_all_node() + */ + if (up->parent && up->parent->sources) + listnode_delete(up->parent->sources, up); + up->parent = NULL; + + listnode_delete(pim_upstream_list, up); + hash_release(pim_upstream_hash, up); + + if (notify_msdp) { + pim_msdp_up_del(&up->sg); + } + + /* Deregister addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = up->upstream_addr; + if (PIM_DEBUG_TRACE) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&nht_p, buf, sizeof(buf)); + zlog_debug("%s: Deregister upstream %s addr %s with Zebra NHT", + __PRETTY_FUNCTION__, up->sg_str, buf); + } + pim_delete_tracked_nexthop(&nht_p, up, NULL); + + pim_upstream_free(up); + + return NULL; } -void -pim_upstream_send_join (struct pim_upstream *up) +void pim_upstream_send_join(struct pim_upstream *up) { - if (PIM_DEBUG_TRACE) { - char rpf_str[PREFIX_STRLEN]; - pim_addr_dump("", &up->rpf.rpf_addr, rpf_str, sizeof(rpf_str)); - zlog_debug ("%s: RPF'%s=%s(%s) for Interface %s", __PRETTY_FUNCTION__, - up->sg_str, rpf_str, pim_upstream_state2str (up->join_state), - up->rpf.source_nexthop.interface->name); - if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { - zlog_debug("%s: can't send join upstream: RPF'%s=%s", - __PRETTY_FUNCTION__, - up->sg_str, rpf_str); - /* warning only */ - } - } - - /* send Join(S,G) to the current upstream neighbor */ - pim_jp_agg_single_upstream_send(&up->rpf, up, 1 /* join */); + if (PIM_DEBUG_TRACE) { + char rpf_str[PREFIX_STRLEN]; + pim_addr_dump("", &up->rpf.rpf_addr, rpf_str, + sizeof(rpf_str)); + zlog_debug("%s: RPF'%s=%s(%s) for Interface %s", + __PRETTY_FUNCTION__, up->sg_str, rpf_str, + pim_upstream_state2str(up->join_state), + up->rpf.source_nexthop.interface->name); + if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { + zlog_debug("%s: can't send join upstream: RPF'%s=%s", + __PRETTY_FUNCTION__, up->sg_str, rpf_str); + /* warning only */ + } + } + + /* send Join(S,G) to the current upstream neighbor */ + pim_jp_agg_single_upstream_send(&up->rpf, up, 1 /* join */); } static int on_join_timer(struct thread *t) { - struct pim_upstream *up; + struct pim_upstream *up; - up = THREAD_ARG(t); + up = THREAD_ARG(t); - /* - * In the case of a HFR we will not ahve anyone to send this to. - */ - if (PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) - return 0; + /* + * In the case of a HFR we will not ahve anyone to send this to. + */ + if (PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) + return 0; - /* - * Don't send the join if the outgoing interface is a loopback - * But since this might change leave the join timer running - */ - if (up->rpf.source_nexthop.interface && - !if_is_loopback (up->rpf.source_nexthop.interface)) - pim_upstream_send_join (up); + /* + * Don't send the join if the outgoing interface is a loopback + * But since this might change leave the join timer running + */ + if (up->rpf.source_nexthop + .interface && !if_is_loopback(up->rpf.source_nexthop.interface)) + pim_upstream_send_join(up); - join_timer_start(up); + join_timer_start(up); - return 0; + return 0; } static void join_timer_stop(struct pim_upstream *up) { - struct pim_neighbor *nbr; + struct pim_neighbor *nbr; - THREAD_OFF (up->t_join_timer); + THREAD_OFF(up->t_join_timer); - nbr = pim_neighbor_find (up->rpf.source_nexthop.interface, - up->rpf.rpf_addr.u.prefix4); + nbr = pim_neighbor_find(up->rpf.source_nexthop.interface, + up->rpf.rpf_addr.u.prefix4); - if (nbr) - pim_jp_agg_remove_group (nbr->upstream_jp_agg, up); + if (nbr) + pim_jp_agg_remove_group(nbr->upstream_jp_agg, up); - pim_jp_agg_upstream_verification (up, false); + pim_jp_agg_upstream_verification(up, false); } -void -join_timer_start(struct pim_upstream *up) +void join_timer_start(struct pim_upstream *up) { - struct pim_neighbor *nbr = NULL; - - if (up->rpf.source_nexthop.interface) - { - nbr = pim_neighbor_find (up->rpf.source_nexthop.interface, - up->rpf.rpf_addr.u.prefix4); - - if (PIM_DEBUG_PIM_EVENTS) { - zlog_debug("%s: starting %d sec timer for upstream (S,G)=%s", - __PRETTY_FUNCTION__, - qpim_t_periodic, - up->sg_str); - } - } - - if (nbr) - pim_jp_agg_add_group (nbr->upstream_jp_agg, up, 1); - else - { - THREAD_OFF (up->t_join_timer); - thread_add_timer(master, on_join_timer, up, qpim_t_periodic, - &up->t_join_timer); - } - pim_jp_agg_upstream_verification (up, true); + struct pim_neighbor *nbr = NULL; + + if (up->rpf.source_nexthop.interface) { + nbr = pim_neighbor_find(up->rpf.source_nexthop.interface, + up->rpf.rpf_addr.u.prefix4); + + if (PIM_DEBUG_PIM_EVENTS) { + zlog_debug( + "%s: starting %d sec timer for upstream (S,G)=%s", + __PRETTY_FUNCTION__, qpim_t_periodic, + up->sg_str); + } + } + + if (nbr) + pim_jp_agg_add_group(nbr->upstream_jp_agg, up, 1); + else { + THREAD_OFF(up->t_join_timer); + thread_add_timer(master, on_join_timer, up, qpim_t_periodic, + &up->t_join_timer); + } + pim_jp_agg_upstream_verification(up, true); } /* @@ -347,501 +335,488 @@ join_timer_start(struct pim_upstream *up) * As such we need to remove from the old list and * add to the new list. */ -void pim_upstream_join_timer_restart(struct pim_upstream *up, struct pim_rpf *old) +void pim_upstream_join_timer_restart(struct pim_upstream *up, + struct pim_rpf *old) { - //THREAD_OFF(up->t_join_timer); - join_timer_start(up); + // THREAD_OFF(up->t_join_timer); + join_timer_start(up); } static void pim_upstream_join_timer_restart_msec(struct pim_upstream *up, int interval_msec) { - if (PIM_DEBUG_PIM_EVENTS) { - zlog_debug("%s: restarting %d msec timer for upstream (S,G)=%s", - __PRETTY_FUNCTION__, - interval_msec, - up->sg_str); - } - - THREAD_OFF(up->t_join_timer); - thread_add_timer_msec(master, on_join_timer, up, interval_msec, - &up->t_join_timer); + if (PIM_DEBUG_PIM_EVENTS) { + zlog_debug("%s: restarting %d msec timer for upstream (S,G)=%s", + __PRETTY_FUNCTION__, interval_msec, up->sg_str); + } + + THREAD_OFF(up->t_join_timer); + thread_add_timer_msec(master, on_join_timer, up, interval_msec, + &up->t_join_timer); } void pim_upstream_join_suppress(struct pim_upstream *up, - struct in_addr rpf_addr, - int holdtime) + struct in_addr rpf_addr, int holdtime) { - long t_joinsuppress_msec; - long join_timer_remain_msec; - - t_joinsuppress_msec = MIN(pim_if_t_suppressed_msec(up->rpf.source_nexthop.interface), - 1000 * holdtime); - - join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer); - - if (PIM_DEBUG_TRACE) { - char rpf_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", rpf_addr, rpf_str, sizeof(rpf_str)); - zlog_debug("%s %s: detected Join%s to RPF'(S,G)=%s: join_timer=%ld msec t_joinsuppress=%ld msec", - __FILE__, __PRETTY_FUNCTION__, - up->sg_str, - rpf_str, - join_timer_remain_msec, t_joinsuppress_msec); - } - - if (join_timer_remain_msec < t_joinsuppress_msec) { - if (PIM_DEBUG_TRACE) { - zlog_debug("%s %s: suppressing Join(S,G)=%s for %ld msec", - __FILE__, __PRETTY_FUNCTION__, - up->sg_str, t_joinsuppress_msec); - } - - pim_upstream_join_timer_restart_msec(up, t_joinsuppress_msec); - } + long t_joinsuppress_msec; + long join_timer_remain_msec; + + t_joinsuppress_msec = + MIN(pim_if_t_suppressed_msec(up->rpf.source_nexthop.interface), + 1000 * holdtime); + + join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer); + + if (PIM_DEBUG_TRACE) { + char rpf_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", rpf_addr, rpf_str, sizeof(rpf_str)); + zlog_debug( + "%s %s: detected Join%s to RPF'(S,G)=%s: join_timer=%ld msec t_joinsuppress=%ld msec", + __FILE__, __PRETTY_FUNCTION__, up->sg_str, rpf_str, + join_timer_remain_msec, t_joinsuppress_msec); + } + + if (join_timer_remain_msec < t_joinsuppress_msec) { + if (PIM_DEBUG_TRACE) { + zlog_debug( + "%s %s: suppressing Join(S,G)=%s for %ld msec", + __FILE__, __PRETTY_FUNCTION__, up->sg_str, + t_joinsuppress_msec); + } + + pim_upstream_join_timer_restart_msec(up, t_joinsuppress_msec); + } } void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label, - struct pim_upstream *up) + struct pim_upstream *up) { - long join_timer_remain_msec; - int t_override_msec; - - join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer); - t_override_msec = pim_if_t_override_msec(up->rpf.source_nexthop.interface); - - if (PIM_DEBUG_TRACE) { - char rpf_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", up->rpf.rpf_addr.u.prefix4, rpf_str, sizeof(rpf_str)); - zlog_debug("%s: to RPF'%s=%s: join_timer=%ld msec t_override=%d msec", - debug_label, - up->sg_str, rpf_str, - join_timer_remain_msec, t_override_msec); - } - - if (join_timer_remain_msec > t_override_msec) { - if (PIM_DEBUG_TRACE) { - zlog_debug("%s: decreasing (S,G)=%s join timer to t_override=%d msec", - debug_label, - up->sg_str, - t_override_msec); - } - - pim_upstream_join_timer_restart_msec(up, t_override_msec); - } + long join_timer_remain_msec; + int t_override_msec; + + join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer); + t_override_msec = + pim_if_t_override_msec(up->rpf.source_nexthop.interface); + + if (PIM_DEBUG_TRACE) { + char rpf_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", up->rpf.rpf_addr.u.prefix4, rpf_str, + sizeof(rpf_str)); + zlog_debug( + "%s: to RPF'%s=%s: join_timer=%ld msec t_override=%d msec", + debug_label, up->sg_str, rpf_str, + join_timer_remain_msec, t_override_msec); + } + + if (join_timer_remain_msec > t_override_msec) { + if (PIM_DEBUG_TRACE) { + zlog_debug( + "%s: decreasing (S,G)=%s join timer to t_override=%d msec", + debug_label, up->sg_str, t_override_msec); + } + + pim_upstream_join_timer_restart_msec(up, t_override_msec); + } } static void forward_on(struct pim_upstream *up) { - struct listnode *chnode; - struct listnode *chnextnode; - struct pim_ifchannel *ch = NULL; + struct listnode *chnode; + struct listnode *chnextnode; + struct pim_ifchannel *ch = NULL; - /* scan (S,G) state */ - for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { - if (pim_macro_chisin_oiflist(ch)) - pim_forward_start(ch); + /* scan (S,G) state */ + for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { + if (pim_macro_chisin_oiflist(ch)) + pim_forward_start(ch); - } /* scan iface channel list */ + } /* scan iface channel list */ } static void forward_off(struct pim_upstream *up) { - struct listnode *chnode; - struct listnode *chnextnode; - struct pim_ifchannel *ch; + struct listnode *chnode; + struct listnode *chnextnode; + struct pim_ifchannel *ch; - /* scan per-interface (S,G) state */ - for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { + /* scan per-interface (S,G) state */ + for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { - pim_forward_stop(ch); + pim_forward_stop(ch); - } /* scan iface channel list */ + } /* scan iface channel list */ } -static int -pim_upstream_could_register (struct pim_upstream *up) +static int pim_upstream_could_register(struct pim_upstream *up) { - struct pim_interface *pim_ifp = NULL; - - if (up->rpf.source_nexthop.interface) - pim_ifp = up->rpf.source_nexthop.interface->info; - else - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: up %s RPF is not present", __PRETTY_FUNCTION__, up->sg_str); - } + struct pim_interface *pim_ifp = NULL; + + if (up->rpf.source_nexthop.interface) + pim_ifp = up->rpf.source_nexthop.interface->info; + else { + if (PIM_DEBUG_TRACE) + zlog_debug("%s: up %s RPF is not present", + __PRETTY_FUNCTION__, up->sg_str); + } - if (pim_ifp && PIM_I_am_DR (pim_ifp) && - pim_if_connected_to_source (up->rpf.source_nexthop.interface, up->sg.src)) - return 1; + if (pim_ifp && PIM_I_am_DR(pim_ifp) + && pim_if_connected_to_source(up->rpf.source_nexthop.interface, + up->sg.src)) + return 1; - return 0; + return 0; } /* Source registration is supressed for SSM groups. When the SSM range changes * we re-revaluate register setup for existing upstream entries */ -void -pim_upstream_register_reevaluate (void) +void pim_upstream_register_reevaluate(void) { - struct listnode *upnode; - struct pim_upstream *up; - - for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, upnode, up)) - { - /* If FHR is set CouldRegister is True. Also check if the flow - * is actually active; if it is not kat setup will trigger source - * registration whenever the flow becomes active. */ - if (!PIM_UPSTREAM_FLAG_TEST_FHR (up->flags) || !up->t_ka_timer) - continue; - - if (pim_is_grp_ssm (up->sg.grp)) - { - /* clear the register state for SSM groups */ - if (up->reg_state != PIM_REG_NOINFO) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_debug ("Clear register for %s as G is now SSM", - up->sg_str); - /* remove regiface from the OIL if it is there*/ - pim_channel_del_oif (up->channel_oil, pim_regiface, - PIM_OIF_FLAG_PROTO_PIM); - up->reg_state = PIM_REG_NOINFO; - } - } - else - { - /* register ASM sources with the RP */ - if (up->reg_state == PIM_REG_NOINFO) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_debug ("Register %s as G is now ASM", up->sg_str); - pim_channel_add_oif (up->channel_oil, pim_regiface, - PIM_OIF_FLAG_PROTO_PIM); - up->reg_state = PIM_REG_JOIN; - } - } - } + struct listnode *upnode; + struct pim_upstream *up; + + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, upnode, up)) { + /* If FHR is set CouldRegister is True. Also check if the flow + * is actually active; if it is not kat setup will trigger + * source + * registration whenever the flow becomes active. */ + if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) || !up->t_ka_timer) + continue; + + if (pim_is_grp_ssm(up->sg.grp)) { + /* clear the register state for SSM groups */ + if (up->reg_state != PIM_REG_NOINFO) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug( + "Clear register for %s as G is now SSM", + up->sg_str); + /* remove regiface from the OIL if it is there*/ + pim_channel_del_oif(up->channel_oil, + pim_regiface, + PIM_OIF_FLAG_PROTO_PIM); + up->reg_state = PIM_REG_NOINFO; + } + } else { + /* register ASM sources with the RP */ + if (up->reg_state == PIM_REG_NOINFO) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug( + "Register %s as G is now ASM", + up->sg_str); + pim_channel_add_oif(up->channel_oil, + pim_regiface, + PIM_OIF_FLAG_PROTO_PIM); + up->reg_state = PIM_REG_JOIN; + } + } + } } -void -pim_upstream_switch(struct pim_upstream *up, - enum pim_upstream_state new_state) +void pim_upstream_switch(struct pim_upstream *up, + enum pim_upstream_state new_state) { - enum pim_upstream_state old_state = up->join_state; - - if (PIM_DEBUG_PIM_EVENTS) - { - zlog_debug ("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s", - __PRETTY_FUNCTION__, - up->sg_str, - pim_upstream_state2str (up->join_state), - pim_upstream_state2str (new_state)); - } - - up->join_state = new_state; - if (old_state != new_state) - up->state_transition = pim_time_monotonic_sec(); - - pim_upstream_update_assert_tracking_desired(up); - - if (new_state == PIM_UPSTREAM_JOINED) { - if (old_state != PIM_UPSTREAM_JOINED) - { - int old_fhr = PIM_UPSTREAM_FLAG_TEST_FHR(up->flags); - forward_on(up); - pim_msdp_up_join_state_changed(up); - if (pim_upstream_could_register (up)) - { - PIM_UPSTREAM_FLAG_SET_FHR(up->flags); - if (!old_fhr && PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) - { - pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); - pim_register_join (up); - } - } - else - { - pim_upstream_send_join (up); - join_timer_start (up); - } - } - else - { - forward_on (up); - } - } - else { - - forward_off(up); - if (old_state == PIM_UPSTREAM_JOINED) - pim_msdp_up_join_state_changed(up); - - /* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT towards RP. - If I am RP for G then send S,G prune to its IIF. */ - if (pim_upstream_is_sg_rpt(up) && up->parent && !I_am_RP(up->sg.grp)) - { - if (PIM_DEBUG_PIM_TRACE_DETAIL) - zlog_debug ("%s: *,G IIF %s S,G IIF %s ", __PRETTY_FUNCTION__, - up->parent->rpf.source_nexthop.interface->name, - up->rpf.source_nexthop.interface->name); - pim_jp_agg_single_upstream_send(&up->parent->rpf, up->parent, 1 /* (W,G) Join */); - } - else - pim_jp_agg_single_upstream_send(&up->rpf, up, 0 /* prune */); - join_timer_stop(up); - } + enum pim_upstream_state old_state = up->join_state; + + if (PIM_DEBUG_PIM_EVENTS) { + zlog_debug("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s", + __PRETTY_FUNCTION__, up->sg_str, + pim_upstream_state2str(up->join_state), + pim_upstream_state2str(new_state)); + } + + up->join_state = new_state; + if (old_state != new_state) + up->state_transition = pim_time_monotonic_sec(); + + pim_upstream_update_assert_tracking_desired(up); + + if (new_state == PIM_UPSTREAM_JOINED) { + if (old_state != PIM_UPSTREAM_JOINED) { + int old_fhr = PIM_UPSTREAM_FLAG_TEST_FHR(up->flags); + forward_on(up); + pim_msdp_up_join_state_changed(up); + if (pim_upstream_could_register(up)) { + PIM_UPSTREAM_FLAG_SET_FHR(up->flags); + if (!old_fhr + && PIM_UPSTREAM_FLAG_TEST_SRC_STREAM( + up->flags)) { + pim_upstream_keep_alive_timer_start( + up, qpim_keep_alive_time); + pim_register_join(up); + } + } else { + pim_upstream_send_join(up); + join_timer_start(up); + } + } else { + forward_on(up); + } + } else { + + forward_off(up); + if (old_state == PIM_UPSTREAM_JOINED) + pim_msdp_up_join_state_changed(up); + + /* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT towards + RP. + If I am RP for G then send S,G prune to its IIF. */ + if (pim_upstream_is_sg_rpt(up) && up->parent + && !I_am_RP(up->sg.grp)) { + if (PIM_DEBUG_PIM_TRACE_DETAIL) + zlog_debug( + "%s: *,G IIF %s S,G IIF %s ", + __PRETTY_FUNCTION__, + up->parent->rpf.source_nexthop + .interface->name, + up->rpf.source_nexthop.interface->name); + pim_jp_agg_single_upstream_send(&up->parent->rpf, + up->parent, + 1 /* (W,G) Join */); + } else + pim_jp_agg_single_upstream_send(&up->rpf, up, + 0 /* prune */); + join_timer_stop(up); + } } -int -pim_upstream_compare (void *arg1, void *arg2) +int pim_upstream_compare(void *arg1, void *arg2) { - const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; - const struct pim_upstream *up2 = (const struct pim_upstream *)arg2; + const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; + const struct pim_upstream *up2 = (const struct pim_upstream *)arg2; - if (ntohl(up1->sg.grp.s_addr) < ntohl(up2->sg.grp.s_addr)) - return -1; + if (ntohl(up1->sg.grp.s_addr) < ntohl(up2->sg.grp.s_addr)) + return -1; - if (ntohl(up1->sg.grp.s_addr) > ntohl(up2->sg.grp.s_addr)) - return 1; + if (ntohl(up1->sg.grp.s_addr) > ntohl(up2->sg.grp.s_addr)) + return 1; - if (ntohl(up1->sg.src.s_addr) < ntohl(up2->sg.src.s_addr)) - return -1; + if (ntohl(up1->sg.src.s_addr) < ntohl(up2->sg.src.s_addr)) + return -1; - if (ntohl(up1->sg.src.s_addr) > ntohl(up2->sg.src.s_addr)) - return 1; + if (ntohl(up1->sg.src.s_addr) > ntohl(up2->sg.src.s_addr)) + return 1; - return 0; + return 0; } static struct pim_upstream * -pim_upstream_new (struct prefix_sg *sg, - struct interface *incoming, - int flags) +pim_upstream_new(struct prefix_sg *sg, struct interface *incoming, int flags) { - enum pim_rpf_result rpf_result; - struct pim_interface *pim_ifp; - struct pim_upstream *up; - - up = XCALLOC(MTYPE_PIM_UPSTREAM, sizeof(*up)); - if (!up) - { - zlog_err("%s: PIM XCALLOC(%zu) failure", - __PRETTY_FUNCTION__, sizeof(*up)); - return NULL; - } - - up->sg = *sg; - pim_str_sg_set (sg, up->sg_str); - up = hash_get (pim_upstream_hash, up, hash_alloc_intern); - if (!pim_rp_set_upstream_addr (&up->upstream_addr, sg->src, sg->grp)) - { - if (PIM_DEBUG_TRACE) - zlog_debug("%s: Received a (*,G) with no RP configured", __PRETTY_FUNCTION__); - - hash_release (pim_upstream_hash, up); - XFREE (MTYPE_PIM_UPSTREAM, up); - return NULL; - } - - up->parent = pim_upstream_find_parent (up); - if (up->sg.src.s_addr == INADDR_ANY) - { - up->sources = list_new (); - up->sources->cmp = pim_upstream_compare; - } - else - up->sources = NULL; - - pim_upstream_find_new_children (up); - up->flags = flags; - up->ref_count = 1; - up->t_join_timer = NULL; - up->t_ka_timer = NULL; - up->t_rs_timer = NULL; - up->t_msdp_reg_timer = NULL; - up->join_state = PIM_UPSTREAM_NOTJOINED; - up->reg_state = PIM_REG_NOINFO; - up->state_transition = pim_time_monotonic_sec(); - up->channel_oil = NULL; - up->sptbit = PIM_UPSTREAM_SPTBIT_FALSE; - - up->rpf.source_nexthop.interface = NULL; - up->rpf.source_nexthop.mrib_nexthop_addr.family = AF_INET; - up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY; - up->rpf.source_nexthop.mrib_metric_preference = qpim_infinite_assert_metric.metric_preference; - up->rpf.source_nexthop.mrib_route_metric = qpim_infinite_assert_metric.route_metric; - up->rpf.rpf_addr.family = AF_INET; - up->rpf.rpf_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY; - - up->ifchannels = list_new(); - up->ifchannels->cmp = (int (*)(void *, void *))pim_ifchannel_compare; - - if (up->sg.src.s_addr != INADDR_ANY) - wheel_add_item (pim_upstream_sg_wheel, up); - - rpf_result = pim_rpf_update(up, NULL, 1); - if (rpf_result == PIM_RPF_FAILURE) { - struct prefix nht_p; - - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: Attempting to create upstream(%s), Unable to RPF for source", __PRETTY_FUNCTION__, - up->sg_str); - - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = up->upstream_addr; - pim_delete_tracked_nexthop (&nht_p, up, NULL); - - if (up->parent) - { - listnode_delete (up->parent->sources, up); - up->parent = NULL; - } - - if (up->sg.src.s_addr != INADDR_ANY) - wheel_remove_item (pim_upstream_sg_wheel, up); - - pim_upstream_remove_children (up); - if (up->sources) - list_delete (up->sources); - - hash_release (pim_upstream_hash, up); - XFREE(MTYPE_PIM_UPSTREAM, up); - return NULL; - } - - if (up->rpf.source_nexthop.interface) - { - pim_ifp = up->rpf.source_nexthop.interface->info; - if (pim_ifp) - up->channel_oil = pim_channel_oil_add(&up->sg, pim_ifp->mroute_vif_index); - } - listnode_add_sort(pim_upstream_list, up); - - if (PIM_DEBUG_TRACE) - { - zlog_debug ("%s: Created Upstream %s upstream_addr %s ref count %d increment", - __PRETTY_FUNCTION__, up->sg_str, - inet_ntoa (up->upstream_addr), up->ref_count); - } - - return up; + enum pim_rpf_result rpf_result; + struct pim_interface *pim_ifp; + struct pim_upstream *up; + + up = XCALLOC(MTYPE_PIM_UPSTREAM, sizeof(*up)); + if (!up) { + zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, + sizeof(*up)); + return NULL; + } + + up->sg = *sg; + pim_str_sg_set(sg, up->sg_str); + up = hash_get(pim_upstream_hash, up, hash_alloc_intern); + if (!pim_rp_set_upstream_addr(&up->upstream_addr, sg->src, sg->grp)) { + if (PIM_DEBUG_TRACE) + zlog_debug("%s: Received a (*,G) with no RP configured", + __PRETTY_FUNCTION__); + + hash_release(pim_upstream_hash, up); + XFREE(MTYPE_PIM_UPSTREAM, up); + return NULL; + } + + up->parent = pim_upstream_find_parent(up); + if (up->sg.src.s_addr == INADDR_ANY) { + up->sources = list_new(); + up->sources->cmp = pim_upstream_compare; + } else + up->sources = NULL; + + pim_upstream_find_new_children(up); + up->flags = flags; + up->ref_count = 1; + up->t_join_timer = NULL; + up->t_ka_timer = NULL; + up->t_rs_timer = NULL; + up->t_msdp_reg_timer = NULL; + up->join_state = PIM_UPSTREAM_NOTJOINED; + up->reg_state = PIM_REG_NOINFO; + up->state_transition = pim_time_monotonic_sec(); + up->channel_oil = NULL; + up->sptbit = PIM_UPSTREAM_SPTBIT_FALSE; + + up->rpf.source_nexthop.interface = NULL; + up->rpf.source_nexthop.mrib_nexthop_addr.family = AF_INET; + up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4.s_addr = + PIM_NET_INADDR_ANY; + up->rpf.source_nexthop.mrib_metric_preference = + qpim_infinite_assert_metric.metric_preference; + up->rpf.source_nexthop.mrib_route_metric = + qpim_infinite_assert_metric.route_metric; + up->rpf.rpf_addr.family = AF_INET; + up->rpf.rpf_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY; + + up->ifchannels = list_new(); + up->ifchannels->cmp = (int (*)(void *, void *))pim_ifchannel_compare; + + if (up->sg.src.s_addr != INADDR_ANY) + wheel_add_item(pim_upstream_sg_wheel, up); + + rpf_result = pim_rpf_update(up, NULL, 1); + if (rpf_result == PIM_RPF_FAILURE) { + struct prefix nht_p; + + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: Attempting to create upstream(%s), Unable to RPF for source", + __PRETTY_FUNCTION__, up->sg_str); + + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = up->upstream_addr; + pim_delete_tracked_nexthop(&nht_p, up, NULL); + + if (up->parent) { + listnode_delete(up->parent->sources, up); + up->parent = NULL; + } + + if (up->sg.src.s_addr != INADDR_ANY) + wheel_remove_item(pim_upstream_sg_wheel, up); + + pim_upstream_remove_children(up); + if (up->sources) + list_delete(up->sources); + + hash_release(pim_upstream_hash, up); + XFREE(MTYPE_PIM_UPSTREAM, up); + return NULL; + } + + if (up->rpf.source_nexthop.interface) { + pim_ifp = up->rpf.source_nexthop.interface->info; + if (pim_ifp) + up->channel_oil = pim_channel_oil_add( + &up->sg, pim_ifp->mroute_vif_index); + } + listnode_add_sort(pim_upstream_list, up); + + if (PIM_DEBUG_TRACE) { + zlog_debug( + "%s: Created Upstream %s upstream_addr %s ref count %d increment", + __PRETTY_FUNCTION__, up->sg_str, + inet_ntoa(up->upstream_addr), up->ref_count); + } + + return up; } struct pim_upstream *pim_upstream_find(struct prefix_sg *sg) { - struct pim_upstream lookup; - struct pim_upstream *up = NULL; + struct pim_upstream lookup; + struct pim_upstream *up = NULL; - lookup.sg = *sg; - up = hash_lookup (pim_upstream_hash, &lookup); - return up; + lookup.sg = *sg; + up = hash_lookup(pim_upstream_hash, &lookup); + return up; } -struct pim_upstream * -pim_upstream_find_or_add(struct prefix_sg *sg, - struct interface *incoming, - int flags, const char *name) +struct pim_upstream *pim_upstream_find_or_add(struct prefix_sg *sg, + struct interface *incoming, + int flags, const char *name) { - struct pim_upstream *up; - - up = pim_upstream_find(sg); - - if (up) - { - if (!(up->flags & flags)) - { - up->flags |= flags; - up->ref_count++; - if (PIM_DEBUG_TRACE) - zlog_debug ("%s(%s): upstream %s ref count %d increment", - __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count); - } - } - else - up = pim_upstream_add (sg, incoming, flags, name); - - return up; + struct pim_upstream *up; + + up = pim_upstream_find(sg); + + if (up) { + if (!(up->flags & flags)) { + up->flags |= flags; + up->ref_count++; + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s(%s): upstream %s ref count %d increment", + __PRETTY_FUNCTION__, name, up->sg_str, + up->ref_count); + } + } else + up = pim_upstream_add(sg, incoming, flags, name); + + return up; } -void -pim_upstream_ref(struct pim_upstream *up, int flags, const char *name) +void pim_upstream_ref(struct pim_upstream *up, int flags, const char *name) { - up->flags |= flags; - ++up->ref_count; - if (PIM_DEBUG_TRACE) - zlog_debug ("%s(%s): upstream %s ref count %d increment", - __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count); + up->flags |= flags; + ++up->ref_count; + if (PIM_DEBUG_TRACE) + zlog_debug("%s(%s): upstream %s ref count %d increment", + __PRETTY_FUNCTION__, name, up->sg_str, + up->ref_count); } struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, - struct interface *incoming, - int flags, const char *name) + struct interface *incoming, int flags, + const char *name) { - struct pim_upstream *up = NULL; - int found = 0; - up = pim_upstream_find(sg); - if (up) { - pim_upstream_ref(up, flags, name); - found = 1; - } - else { - up = pim_upstream_new(sg, incoming, flags); - } - - if (PIM_DEBUG_TRACE) - { - if (up) - { - char buf[PREFIX2STR_BUFFER]; - prefix2str (&up->rpf.rpf_addr, buf, sizeof (buf)); - zlog_debug("%s(%s): %s, iif %s (%s) found: %d: ref_count: %d", + struct pim_upstream *up = NULL; + int found = 0; + up = pim_upstream_find(sg); + if (up) { + pim_upstream_ref(up, flags, name); + found = 1; + } else { + up = pim_upstream_new(sg, incoming, flags); + } + + if (PIM_DEBUG_TRACE) { + if (up) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&up->rpf.rpf_addr, buf, sizeof(buf)); + zlog_debug("%s(%s): %s, iif %s (%s) found: %d: ref_count: %d", __PRETTY_FUNCTION__, name, up->sg_str, buf, up->rpf.source_nexthop.interface ? up->rpf.source_nexthop.interface->name : "NIL" , found, up->ref_count); - } - else - zlog_debug("%s(%s): (%s) failure to create", - __PRETTY_FUNCTION__, name, - pim_str_sg_dump (sg)); - } + } else + zlog_debug("%s(%s): (%s) failure to create", + __PRETTY_FUNCTION__, name, + pim_str_sg_dump(sg)); + } - return up; + return up; } /* * Passed in up must be the upstream for ch. starch is NULL if no * information */ -int -pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up, - struct pim_ifchannel *ch, - struct pim_ifchannel *starch) +int pim_upstream_evaluate_join_desired_interface(struct pim_upstream *up, + struct pim_ifchannel *ch, + struct pim_ifchannel *starch) { - if (ch) - { - if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) - return 0; - - if (!pim_macro_ch_lost_assert(ch) && pim_macro_chisin_joins_or_include(ch)) - return 1; - } - - /* - * joins (*,G) - */ - if (starch) - { - if (PIM_IF_FLAG_TEST_S_G_RPT (starch->upstream->flags)) - return 0; - - if (!pim_macro_ch_lost_assert (starch) && pim_macro_chisin_joins_or_include (starch)) - return 1; - } - - return 0; + if (ch) { + if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) + return 0; + + if (!pim_macro_ch_lost_assert(ch) + && pim_macro_chisin_joins_or_include(ch)) + return 1; + } + + /* + * joins (*,G) + */ + if (starch) { + if (PIM_IF_FLAG_TEST_S_G_RPT(starch->upstream->flags)) + return 0; + + if (!pim_macro_ch_lost_assert(starch) + && pim_macro_chisin_joins_or_include(starch)) + return 1; + } + + return 0; } /* @@ -859,7 +834,7 @@ pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up, pim_ifp->pim_dr_addr ch->ifassert_winner_metric ch->ifassert_winner - ch->local_ifmembership + ch->local_ifmembership ch->ifjoin_state ch->upstream->rpf.source_nexthop.mrib_metric_preference ch->upstream->rpf.source_nexthop.mrib_route_metric @@ -869,31 +844,31 @@ pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up, */ int pim_upstream_evaluate_join_desired(struct pim_upstream *up) { - struct interface *ifp; - struct listnode *node; - struct pim_ifchannel *ch, *starch; - struct pim_upstream *starup = up->parent; - int ret = 0; + struct interface *ifp; + struct listnode *node; + struct pim_ifchannel *ch, *starch; + struct pim_upstream *starup = up->parent; + int ret = 0; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - if (!ifp->info) - continue; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + if (!ifp->info) + continue; - ch = pim_ifchannel_find (ifp, &up->sg); + ch = pim_ifchannel_find(ifp, &up->sg); - if (starup) - starch = pim_ifchannel_find (ifp, &starup->sg); - else - starch = NULL; + if (starup) + starch = pim_ifchannel_find(ifp, &starup->sg); + else + starch = NULL; - if (!ch && !starch) - continue; + if (!ch && !starch) + continue; - ret += pim_upstream_evaluate_join_desired_interface (up, ch, starch); - } /* scan iface channel list */ + ret += pim_upstream_evaluate_join_desired_interface(up, ch, + starch); + } /* scan iface channel list */ - return ret; /* false */ + return ret; /* false */ } /* @@ -901,28 +876,28 @@ int pim_upstream_evaluate_join_desired(struct pim_upstream *up) */ void pim_upstream_update_join_desired(struct pim_upstream *up) { - int was_join_desired; /* boolean */ - int is_join_desired; /* boolean */ - - was_join_desired = PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags); - - is_join_desired = pim_upstream_evaluate_join_desired(up); - if (is_join_desired) - PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED(up->flags); - else - PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED(up->flags); - - /* switched from false to true */ - if (is_join_desired && !was_join_desired) { - pim_upstream_switch(up, PIM_UPSTREAM_JOINED); - return; - } - - /* switched from true to false */ - if (!is_join_desired && was_join_desired) { - pim_upstream_switch(up, PIM_UPSTREAM_NOTJOINED); - return; - } + int was_join_desired; /* boolean */ + int is_join_desired; /* boolean */ + + was_join_desired = PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags); + + is_join_desired = pim_upstream_evaluate_join_desired(up); + if (is_join_desired) + PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED(up->flags); + else + PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED(up->flags); + + /* switched from false to true */ + if (is_join_desired && !was_join_desired) { + pim_upstream_switch(up, PIM_UPSTREAM_JOINED); + return; + } + + /* switched from true to false */ + if (!is_join_desired && was_join_desired) { + pim_upstream_switch(up, PIM_UPSTREAM_NOTJOINED); + return; + } } /* @@ -936,110 +911,110 @@ void pim_upstream_update_join_desired(struct pim_upstream *up) */ void pim_upstream_rpf_genid_changed(struct in_addr neigh_addr) { - struct listnode *up_node; - struct listnode *up_nextnode; - struct pim_upstream *up; - - /* - * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr - */ - for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { - - if (PIM_DEBUG_TRACE) { - char neigh_str[INET_ADDRSTRLEN]; - char rpf_addr_str[PREFIX_STRLEN]; - pim_inet4_dump("", neigh_addr, neigh_str, sizeof(neigh_str)); - pim_addr_dump("", &up->rpf.rpf_addr, rpf_addr_str, sizeof(rpf_addr_str)); - zlog_debug("%s: matching neigh=%s against upstream (S,G)=%s joined=%d rpf_addr=%s", - __PRETTY_FUNCTION__, - neigh_str, up->sg_str, - up->join_state == PIM_UPSTREAM_JOINED, - rpf_addr_str); - } - - /* consider only (S,G) upstream in Joined state */ - if (up->join_state != PIM_UPSTREAM_JOINED) - continue; - - /* match RPF'(S,G)=neigh_addr */ - if (up->rpf.rpf_addr.u.prefix4.s_addr != neigh_addr.s_addr) - continue; - - pim_upstream_join_timer_decrease_to_t_override("RPF'(S,G) GenID change", - up); - } + struct listnode *up_node; + struct listnode *up_nextnode; + struct pim_upstream *up; + + /* + * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr + */ + for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { + + if (PIM_DEBUG_TRACE) { + char neigh_str[INET_ADDRSTRLEN]; + char rpf_addr_str[PREFIX_STRLEN]; + pim_inet4_dump("", neigh_addr, neigh_str, + sizeof(neigh_str)); + pim_addr_dump("", &up->rpf.rpf_addr, rpf_addr_str, + sizeof(rpf_addr_str)); + zlog_debug( + "%s: matching neigh=%s against upstream (S,G)=%s joined=%d rpf_addr=%s", + __PRETTY_FUNCTION__, neigh_str, up->sg_str, + up->join_state == PIM_UPSTREAM_JOINED, + rpf_addr_str); + } + + /* consider only (S,G) upstream in Joined state */ + if (up->join_state != PIM_UPSTREAM_JOINED) + continue; + + /* match RPF'(S,G)=neigh_addr */ + if (up->rpf.rpf_addr.u.prefix4.s_addr != neigh_addr.s_addr) + continue; + + pim_upstream_join_timer_decrease_to_t_override( + "RPF'(S,G) GenID change", up); + } } void pim_upstream_rpf_interface_changed(struct pim_upstream *up, struct interface *old_rpf_ifp) { - struct listnode *chnode; - struct listnode *chnextnode; - struct pim_ifchannel *ch; - - /* search all ifchannels */ - for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { - if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { - if ( - /* RPF_interface(S) was NOT I */ - (old_rpf_ifp == ch->interface) - && - /* RPF_interface(S) stopped being I */ - (ch->upstream->rpf.source_nexthop.interface != ch->interface) - ) { - assert_action_a5(ch); - } - } /* PIM_IFASSERT_I_AM_LOSER */ - - pim_ifchannel_update_assert_tracking_desired(ch); - } + struct listnode *chnode; + struct listnode *chnextnode; + struct pim_ifchannel *ch; + + /* search all ifchannels */ + for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { + if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) { + if ( + /* RPF_interface(S) was NOT I */ + (old_rpf_ifp == ch->interface) && + /* RPF_interface(S) stopped being I */ + (ch->upstream->rpf.source_nexthop + .interface != ch->interface)) { + assert_action_a5(ch); + } + } /* PIM_IFASSERT_I_AM_LOSER */ + + pim_ifchannel_update_assert_tracking_desired(ch); + } } void pim_upstream_update_could_assert(struct pim_upstream *up) { - struct listnode *chnode; - struct listnode *chnextnode; - struct pim_ifchannel *ch; - - /* scan per-interface (S,G) state */ - for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { - pim_ifchannel_update_could_assert(ch); - } /* scan iface channel list */ + struct listnode *chnode; + struct listnode *chnextnode; + struct pim_ifchannel *ch; + + /* scan per-interface (S,G) state */ + for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { + pim_ifchannel_update_could_assert(ch); + } /* scan iface channel list */ } void pim_upstream_update_my_assert_metric(struct pim_upstream *up) { - struct listnode *chnode; - struct listnode *chnextnode; - struct pim_ifchannel *ch; + struct listnode *chnode; + struct listnode *chnextnode; + struct pim_ifchannel *ch; - /* scan per-interface (S,G) state */ - for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { - pim_ifchannel_update_my_assert_metric(ch); + /* scan per-interface (S,G) state */ + for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { + pim_ifchannel_update_my_assert_metric(ch); - } /* scan iface channel list */ + } /* scan iface channel list */ } static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up) { - struct listnode *chnode; - struct listnode *chnextnode; - struct pim_interface *pim_ifp; - struct pim_ifchannel *ch; - - /* scan per-interface (S,G) state */ - for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) - { - if (!ch->interface) - continue; - pim_ifp = ch->interface->info; - if (!pim_ifp) - continue; - - pim_ifchannel_update_assert_tracking_desired(ch); - - } /* scan iface channel list */ + struct listnode *chnode; + struct listnode *chnextnode; + struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; + + /* scan per-interface (S,G) state */ + for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { + if (!ch->interface) + continue; + pim_ifp = ch->interface->info; + if (!pim_ifp) + continue; + + pim_ifchannel_update_assert_tracking_desired(ch); + + } /* scan iface channel list */ } /* When kat is stopped CouldRegister goes to false so we need to @@ -1047,19 +1022,21 @@ static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up) * from the OIL */ static void pim_upstream_fhr_kat_expiry(struct pim_upstream *up) { - if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) - return; - - if (PIM_DEBUG_TRACE) - zlog_debug ("kat expired on %s; clear fhr reg state", up->sg_str); - - /* stop reg-stop timer */ - THREAD_OFF(up->t_rs_timer); - /* remove regiface from the OIL if it is there*/ - pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); - /* clear the register state */ - up->reg_state = PIM_REG_NOINFO; - PIM_UPSTREAM_FLAG_UNSET_FHR(up->flags); + if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) + return; + + if (PIM_DEBUG_TRACE) + zlog_debug("kat expired on %s; clear fhr reg state", + up->sg_str); + + /* stop reg-stop timer */ + THREAD_OFF(up->t_rs_timer); + /* remove regiface from the OIL if it is there*/ + pim_channel_del_oif(up->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_PIM); + /* clear the register state */ + up->reg_state = PIM_REG_NOINFO; + PIM_UPSTREAM_FLAG_UNSET_FHR(up->flags); } /* When kat is started CouldRegister can go to true. And if it does we @@ -1067,14 +1044,16 @@ static void pim_upstream_fhr_kat_expiry(struct pim_upstream *up) * to the OIL */ static void pim_upstream_fhr_kat_start(struct pim_upstream *up) { - if (pim_upstream_could_register(up)) { - if (PIM_DEBUG_TRACE) - zlog_debug ("kat started on %s; set fhr reg state to joined", up->sg_str); - - PIM_UPSTREAM_FLAG_SET_FHR(up->flags); - if (up->reg_state == PIM_REG_NOINFO) - pim_register_join (up); - } + if (pim_upstream_could_register(up)) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "kat started on %s; set fhr reg state to joined", + up->sg_str); + + PIM_UPSTREAM_FLAG_SET_FHR(up->flags); + if (up->reg_state == PIM_REG_NOINFO) + pim_register_join(up); + } } /* @@ -1083,80 +1062,73 @@ static void pim_upstream_fhr_kat_start(struct pim_upstream *up) * KAT expiry indicates that flow is inactive. If the flow was created or * maintained by activity now is the time to deref it. */ -static int -pim_upstream_keep_alive_timer (struct thread *t) +static int pim_upstream_keep_alive_timer(struct thread *t) { - struct pim_upstream *up; - - up = THREAD_ARG(t); - - if (I_am_RP (up->sg.grp)) - { - pim_br_clear_pmbr (&up->sg); - /* - * We need to do more here :) - * But this is the start. - */ - } - - /* source is no longer active - pull the SA from MSDP's cache */ - pim_msdp_sa_local_del(&up->sg); - - /* if entry was created because of activity we need to deref it */ - if (PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) - { - pim_upstream_fhr_kat_expiry(up); - if (PIM_DEBUG_TRACE) - zlog_debug ("kat expired on %s; remove stream reference", up->sg_str); - PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(up->flags); - pim_upstream_del(up, __PRETTY_FUNCTION__); - } - else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) - { - PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(up->flags); - pim_upstream_del(up, __PRETTY_FUNCTION__); - } - - return 0; + struct pim_upstream *up; + + up = THREAD_ARG(t); + + if (I_am_RP(up->sg.grp)) { + pim_br_clear_pmbr(&up->sg); + /* + * We need to do more here :) + * But this is the start. + */ + } + + /* source is no longer active - pull the SA from MSDP's cache */ + pim_msdp_sa_local_del(&up->sg); + + /* if entry was created because of activity we need to deref it */ + if (PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) { + pim_upstream_fhr_kat_expiry(up); + if (PIM_DEBUG_TRACE) + zlog_debug("kat expired on %s; remove stream reference", + up->sg_str); + PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(up->flags); + pim_upstream_del(up, __PRETTY_FUNCTION__); + } else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) { + PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(up->flags); + pim_upstream_del(up, __PRETTY_FUNCTION__); + } + + return 0; } -void -pim_upstream_keep_alive_timer_start (struct pim_upstream *up, - uint32_t time) +void pim_upstream_keep_alive_timer_start(struct pim_upstream *up, uint32_t time) { - if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) { - if (PIM_DEBUG_TRACE) - zlog_debug ("kat start on %s with no stream reference", up->sg_str); - } - THREAD_OFF (up->t_ka_timer); - thread_add_timer(master, pim_upstream_keep_alive_timer, up, time, - &up->t_ka_timer); - - /* any time keepalive is started against a SG we will have to - * re-evaluate our active source database */ - pim_msdp_sa_local_update(up); + if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) { + if (PIM_DEBUG_TRACE) + zlog_debug("kat start on %s with no stream reference", + up->sg_str); + } + THREAD_OFF(up->t_ka_timer); + thread_add_timer(master, pim_upstream_keep_alive_timer, up, time, + &up->t_ka_timer); + + /* any time keepalive is started against a SG we will have to + * re-evaluate our active source database */ + pim_msdp_sa_local_update(up); } /* MSDP on RP needs to know if a source is registerable to this RP */ -static int -pim_upstream_msdp_reg_timer(struct thread *t) +static int pim_upstream_msdp_reg_timer(struct thread *t) { - struct pim_upstream *up; + struct pim_upstream *up; - up = THREAD_ARG(t); + up = THREAD_ARG(t); - /* source is no longer active - pull the SA from MSDP's cache */ - pim_msdp_sa_local_del(&up->sg); - return 1; + /* source is no longer active - pull the SA from MSDP's cache */ + pim_msdp_sa_local_del(&up->sg); + return 1; } -void -pim_upstream_msdp_reg_timer_start(struct pim_upstream *up) +void pim_upstream_msdp_reg_timer_start(struct pim_upstream *up) { - THREAD_OFF(up->t_msdp_reg_timer); - thread_add_timer(master, pim_upstream_msdp_reg_timer, up, - PIM_MSDP_REG_RXED_PERIOD, &up->t_msdp_reg_timer); + THREAD_OFF(up->t_msdp_reg_timer); + thread_add_timer(master, pim_upstream_msdp_reg_timer, up, + PIM_MSDP_REG_RXED_PERIOD, &up->t_msdp_reg_timer); - pim_msdp_sa_local_update(up); + pim_msdp_sa_local_update(up); } /* @@ -1187,28 +1159,25 @@ pim_upstream_msdp_reg_timer_start(struct pim_upstream *up) * SwitchToSptDesired(S,G) return true once a single packet has been * received for the source and group. */ -int -pim_upstream_switch_to_spt_desired (struct prefix_sg *sg) +int pim_upstream_switch_to_spt_desired(struct prefix_sg *sg) { - if (I_am_RP (sg->grp)) - return 1; + if (I_am_RP(sg->grp)) + return 1; - return 0; + return 0; } -int -pim_upstream_is_sg_rpt (struct pim_upstream *up) +int pim_upstream_is_sg_rpt(struct pim_upstream *up) { - struct listnode *chnode; - struct pim_ifchannel *ch; + struct listnode *chnode; + struct pim_ifchannel *ch; - for (ALL_LIST_ELEMENTS_RO(up->ifchannels, chnode, ch)) - { - if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) - return 1; - } + for (ALL_LIST_ELEMENTS_RO(up->ifchannels, chnode, ch)) { + if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) + return 1; + } - return 0; + return 0; } /* * After receiving a packet set SPTbit: @@ -1226,241 +1195,238 @@ pim_upstream_is_sg_rpt (struct pim_upstream *up) * } * } */ -void -pim_upstream_set_sptbit (struct pim_upstream *up, struct interface *incoming) +void pim_upstream_set_sptbit(struct pim_upstream *up, + struct interface *incoming) { - struct pim_upstream *starup = up->parent; - - // iif == RPF_interfvace(S) - if (up->rpf.source_nexthop.interface != incoming) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: Incoming Interface: %s is different than RPF_interface(S) %s", - __PRETTY_FUNCTION__, incoming->name, up->rpf.source_nexthop.interface->name); - return; - } - - // AND JoinDesired(S,G) == TRUE - // FIXME - - // DirectlyConnected(S) == TRUE - if (pim_if_connected_to_source (up->rpf.source_nexthop.interface, up->sg.src)) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: %s is directly connected to the source", __PRETTY_FUNCTION__, - up->sg_str); - up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; - return; - } - - // OR RPF_interface(S) != RPF_interface(RP(G)) - if (!starup || up->rpf.source_nexthop.interface != starup->rpf.source_nexthop.interface) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: %s RPF_interface(S) != RPF_interface(RP(G))", - __PRETTY_FUNCTION__, up->sg_str); - up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; - return; - } - - // OR inherited_olist(S,G,rpt) == NULL - if (pim_upstream_is_sg_rpt(up) && pim_upstream_empty_inherited_olist(up)) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: %s OR inherited_olist(S,G,rpt) == NULL", __PRETTY_FUNCTION__, - up->sg_str); - up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; - return; - } - - // OR ( ( RPF'(S,G) == RPF'(*,G) ) AND - // ( RPF'(S,G) != NULL ) ) - if (up->parent && pim_rpf_is_same (&up->rpf, &up->parent->rpf)) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: %s RPF'(S,G) is the same as RPF'(*,G)", __PRETTY_FUNCTION__, - up->sg_str); - up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; - return; - } - - return; + struct pim_upstream *starup = up->parent; + + // iif == RPF_interfvace(S) + if (up->rpf.source_nexthop.interface != incoming) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: Incoming Interface: %s is different than RPF_interface(S) %s", + __PRETTY_FUNCTION__, incoming->name, + up->rpf.source_nexthop.interface->name); + return; + } + + // AND JoinDesired(S,G) == TRUE + // FIXME + + // DirectlyConnected(S) == TRUE + if (pim_if_connected_to_source(up->rpf.source_nexthop.interface, + up->sg.src)) { + if (PIM_DEBUG_TRACE) + zlog_debug("%s: %s is directly connected to the source", + __PRETTY_FUNCTION__, up->sg_str); + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + return; + } + + // OR RPF_interface(S) != RPF_interface(RP(G)) + if (!starup + || up->rpf.source_nexthop + .interface != starup->rpf.source_nexthop.interface) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: %s RPF_interface(S) != RPF_interface(RP(G))", + __PRETTY_FUNCTION__, up->sg_str); + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + return; + } + + // OR inherited_olist(S,G,rpt) == NULL + if (pim_upstream_is_sg_rpt(up) + && pim_upstream_empty_inherited_olist(up)) { + if (PIM_DEBUG_TRACE) + zlog_debug("%s: %s OR inherited_olist(S,G,rpt) == NULL", + __PRETTY_FUNCTION__, up->sg_str); + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + return; + } + + // OR ( ( RPF'(S,G) == RPF'(*,G) ) AND + // ( RPF'(S,G) != NULL ) ) + if (up->parent && pim_rpf_is_same(&up->rpf, &up->parent->rpf)) { + if (PIM_DEBUG_TRACE) + zlog_debug("%s: %s RPF'(S,G) is the same as RPF'(*,G)", + __PRETTY_FUNCTION__, up->sg_str); + up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE; + return; + } + + return; } -const char * -pim_upstream_state2str (enum pim_upstream_state join_state) +const char *pim_upstream_state2str(enum pim_upstream_state join_state) { - switch (join_state) - { - case PIM_UPSTREAM_NOTJOINED: - return "NotJoined"; - break; - case PIM_UPSTREAM_JOINED: - return "Joined"; - break; - } - return "Unknown"; + switch (join_state) { + case PIM_UPSTREAM_NOTJOINED: + return "NotJoined"; + break; + case PIM_UPSTREAM_JOINED: + return "Joined"; + break; + } + return "Unknown"; } -const char * -pim_reg_state2str (enum pim_reg_state reg_state, char *state_str) +const char *pim_reg_state2str(enum pim_reg_state reg_state, char *state_str) { - switch (reg_state) - { - case PIM_REG_NOINFO: - strcpy (state_str, "RegNoInfo"); - break; - case PIM_REG_JOIN: - strcpy (state_str, "RegJoined"); - break; - case PIM_REG_JOIN_PENDING: - strcpy (state_str, "RegJoinPend"); - break; - case PIM_REG_PRUNE: - strcpy (state_str, "RegPrune"); - break; - default: - strcpy (state_str, "RegUnknown"); - } - return state_str; + switch (reg_state) { + case PIM_REG_NOINFO: + strcpy(state_str, "RegNoInfo"); + break; + case PIM_REG_JOIN: + strcpy(state_str, "RegJoined"); + break; + case PIM_REG_JOIN_PENDING: + strcpy(state_str, "RegJoinPend"); + break; + case PIM_REG_PRUNE: + strcpy(state_str, "RegPrune"); + break; + default: + strcpy(state_str, "RegUnknown"); + } + return state_str; } -static int -pim_upstream_register_stop_timer (struct thread *t) +static int pim_upstream_register_stop_timer(struct thread *t) { - struct pim_interface *pim_ifp; - struct pim_upstream *up; - struct pim_rpf *rpg; - struct ip ip_hdr; - up = THREAD_ARG (t); - - if (PIM_DEBUG_TRACE) - { - char state_str[PIM_REG_STATE_STR_LEN]; - zlog_debug ("%s: (S,G)=%s upstream register stop timer %s", - __PRETTY_FUNCTION__, up->sg_str, - pim_reg_state2str(up->reg_state, state_str)); - } - - switch (up->reg_state) - { - case PIM_REG_JOIN_PENDING: - up->reg_state = PIM_REG_JOIN; - pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); - break; - case PIM_REG_JOIN: - break; - case PIM_REG_PRUNE: - pim_ifp = up->rpf.source_nexthop.interface->info; - if (!pim_ifp) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: Interface: %s is not configured for pim", - __PRETTY_FUNCTION__, up->rpf.source_nexthop.interface->name); - return 0; - } - up->reg_state = PIM_REG_JOIN_PENDING; - pim_upstream_start_register_stop_timer (up, 1); - - if (((up->channel_oil->cc.lastused/100) > PIM_KEEPALIVE_PERIOD) && - (I_am_RP (up->sg.grp))) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: Stop sending the register, because I am the RP and we haven't seen a packet in a while", __PRETTY_FUNCTION__); - return 0; + struct pim_interface *pim_ifp; + struct pim_upstream *up; + struct pim_rpf *rpg; + struct ip ip_hdr; + up = THREAD_ARG(t); + + if (PIM_DEBUG_TRACE) { + char state_str[PIM_REG_STATE_STR_LEN]; + zlog_debug("%s: (S,G)=%s upstream register stop timer %s", + __PRETTY_FUNCTION__, up->sg_str, + pim_reg_state2str(up->reg_state, state_str)); + } + + switch (up->reg_state) { + case PIM_REG_JOIN_PENDING: + up->reg_state = PIM_REG_JOIN; + pim_channel_add_oif(up->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_PIM); + break; + case PIM_REG_JOIN: + break; + case PIM_REG_PRUNE: + pim_ifp = up->rpf.source_nexthop.interface->info; + if (!pim_ifp) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: Interface: %s is not configured for pim", + __PRETTY_FUNCTION__, + up->rpf.source_nexthop.interface->name); + return 0; + } + up->reg_state = PIM_REG_JOIN_PENDING; + pim_upstream_start_register_stop_timer(up, 1); + + if (((up->channel_oil->cc.lastused / 100) + > PIM_KEEPALIVE_PERIOD) + && (I_am_RP(up->sg.grp))) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: Stop sending the register, because I am the RP and we haven't seen a packet in a while", + __PRETTY_FUNCTION__); + return 0; + } + rpg = RP(up->sg.grp); + memset(&ip_hdr, 0, sizeof(struct ip)); + ip_hdr.ip_p = PIM_IP_PROTO_PIM; + ip_hdr.ip_hl = 5; + ip_hdr.ip_v = 4; + ip_hdr.ip_src = up->sg.src; + ip_hdr.ip_dst = up->sg.grp; + ip_hdr.ip_len = htons(20); + // checksum is broken + pim_register_send((uint8_t *)&ip_hdr, sizeof(struct ip), + pim_ifp->primary_address, rpg, 1, up); + break; + default: + break; } - rpg = RP (up->sg.grp); - memset (&ip_hdr, 0, sizeof (struct ip)); - ip_hdr.ip_p = PIM_IP_PROTO_PIM; - ip_hdr.ip_hl = 5; - ip_hdr.ip_v = 4; - ip_hdr.ip_src = up->sg.src; - ip_hdr.ip_dst = up->sg.grp; - ip_hdr.ip_len = htons (20); - // checksum is broken - pim_register_send ((uint8_t *)&ip_hdr, sizeof (struct ip), - pim_ifp->primary_address, rpg, 1, up); - break; - default: - break; - } - - return 0; + + return 0; } -void -pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_register) +void pim_upstream_start_register_stop_timer(struct pim_upstream *up, + int null_register) { - uint32_t time; - - THREAD_TIMER_OFF (up->t_rs_timer); - - if (!null_register) - { - uint32_t lower = (0.5 * PIM_REGISTER_SUPPRESSION_PERIOD); - uint32_t upper = (1.5 * PIM_REGISTER_SUPPRESSION_PERIOD); - time = lower + (random () % (upper - lower + 1)) - PIM_REGISTER_PROBE_PERIOD; - } - else - time = PIM_REGISTER_PROBE_PERIOD; - - if (PIM_DEBUG_TRACE) - { - zlog_debug ("%s: (S,G)=%s Starting upstream register stop timer %d", - __PRETTY_FUNCTION__, up->sg_str, time); - } - thread_add_timer(master, pim_upstream_register_stop_timer, up, time, - &up->t_rs_timer); + uint32_t time; + + THREAD_TIMER_OFF(up->t_rs_timer); + + if (!null_register) { + uint32_t lower = (0.5 * PIM_REGISTER_SUPPRESSION_PERIOD); + uint32_t upper = (1.5 * PIM_REGISTER_SUPPRESSION_PERIOD); + time = lower + (random() % (upper - lower + 1)) + - PIM_REGISTER_PROBE_PERIOD; + } else + time = PIM_REGISTER_PROBE_PERIOD; + + if (PIM_DEBUG_TRACE) { + zlog_debug( + "%s: (S,G)=%s Starting upstream register stop timer %d", + __PRETTY_FUNCTION__, up->sg_str, time); + } + thread_add_timer(master, pim_upstream_register_stop_timer, up, time, + &up->t_rs_timer); } -int -pim_upstream_inherited_olist_decide (struct pim_upstream *up) +int pim_upstream_inherited_olist_decide(struct pim_upstream *up) { - struct interface *ifp; - struct pim_interface *pim_ifp = NULL; - struct pim_ifchannel *ch, *starch; - struct listnode *node; - struct pim_upstream *starup = up->parent; - int output_intf = 0; - - if (up->rpf.source_nexthop.interface) - pim_ifp = up->rpf.source_nexthop.interface->info; - else - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: up %s RPF is not present", __PRETTY_FUNCTION__, up->sg_str); - } - if (pim_ifp && !up->channel_oil) - up->channel_oil = pim_channel_oil_add (&up->sg, pim_ifp->mroute_vif_index); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - if (!ifp->info) - continue; - - ch = pim_ifchannel_find (ifp, &up->sg); - - if (starup) - starch = pim_ifchannel_find (ifp, &starup->sg); - else - starch = NULL; - - if (!ch && !starch) - continue; - - if (pim_upstream_evaluate_join_desired_interface (up, ch, starch)) - { - int flag = PIM_OIF_FLAG_PROTO_PIM; - - if (!ch) - flag = PIM_OIF_FLAG_PROTO_STAR; - - pim_channel_add_oif (up->channel_oil, ifp, flag); - output_intf++; - } - } - - return output_intf; + struct interface *ifp; + struct pim_interface *pim_ifp = NULL; + struct pim_ifchannel *ch, *starch; + struct listnode *node; + struct pim_upstream *starup = up->parent; + int output_intf = 0; + + if (up->rpf.source_nexthop.interface) + pim_ifp = up->rpf.source_nexthop.interface->info; + else { + if (PIM_DEBUG_TRACE) + zlog_debug("%s: up %s RPF is not present", + __PRETTY_FUNCTION__, up->sg_str); + } + if (pim_ifp && !up->channel_oil) + up->channel_oil = + pim_channel_oil_add(&up->sg, pim_ifp->mroute_vif_index); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + if (!ifp->info) + continue; + + ch = pim_ifchannel_find(ifp, &up->sg); + + if (starup) + starch = pim_ifchannel_find(ifp, &starup->sg); + else + starch = NULL; + + if (!ch && !starch) + continue; + + if (pim_upstream_evaluate_join_desired_interface(up, ch, + starch)) { + int flag = PIM_OIF_FLAG_PROTO_PIM; + + if (!ch) + flag = PIM_OIF_FLAG_PROTO_STAR; + + pim_channel_add_oif(up->channel_oil, ifp, flag); + output_intf++; + } + } + + return output_intf; } /* @@ -1479,29 +1445,27 @@ pim_upstream_inherited_olist_decide (struct pim_upstream *up) * return 1 if there are any output interfaces * return 0 if there are not any output interfaces */ -int -pim_upstream_inherited_olist (struct pim_upstream *up) +int pim_upstream_inherited_olist(struct pim_upstream *up) { - int output_intf = pim_upstream_inherited_olist_decide (up); - - /* - * If we have output_intf switch state to Join and work like normal - * If we don't have an output_intf that means we are probably a - * switch on a stick so turn on forwarding to just accept the - * incoming packets so we don't bother the other stuff! - */ - if (output_intf) - pim_upstream_switch (up, PIM_UPSTREAM_JOINED); - else - forward_on (up); - - return output_intf; + int output_intf = pim_upstream_inherited_olist_decide(up); + + /* + * If we have output_intf switch state to Join and work like normal + * If we don't have an output_intf that means we are probably a + * switch on a stick so turn on forwarding to just accept the + * incoming packets so we don't bother the other stuff! + */ + if (output_intf) + pim_upstream_switch(up, PIM_UPSTREAM_JOINED); + else + forward_on(up); + + return output_intf; } -int -pim_upstream_empty_inherited_olist (struct pim_upstream *up) +int pim_upstream_empty_inherited_olist(struct pim_upstream *up) { - return pim_channel_oil_empty (up->channel_oil); + return pim_channel_oil_empty(up->channel_oil); } /* @@ -1510,58 +1474,54 @@ pim_upstream_empty_inherited_olist (struct pim_upstream *up) * set and see if the new neighbor allows * the join to be sent */ -void -pim_upstream_find_new_rpf (void) +void pim_upstream_find_new_rpf(void) { - struct listnode *up_node; - struct listnode *up_nextnode; - struct pim_upstream *up; - - /* - * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr - */ - for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) - { - if (pim_rpf_addr_is_inaddr_any(&up->rpf)) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("Upstream %s without a path to send join, checking", - up->sg_str); - pim_rpf_update (up, NULL, 1); + struct listnode *up_node; + struct listnode *up_nextnode; + struct pim_upstream *up; + + /* + * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr + */ + for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { + if (pim_rpf_addr_is_inaddr_any(&up->rpf)) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "Upstream %s without a path to send join, checking", + up->sg_str); + pim_rpf_update(up, NULL, 1); + } } - } } -static unsigned int -pim_upstream_hash_key (void *arg) +static unsigned int pim_upstream_hash_key(void *arg) { - struct pim_upstream *up = (struct pim_upstream *)arg; + struct pim_upstream *up = (struct pim_upstream *)arg; - return jhash_2words (up->sg.src.s_addr, up->sg.grp.s_addr, 0); + return jhash_2words(up->sg.src.s_addr, up->sg.grp.s_addr, 0); } -void pim_upstream_terminate (void) +void pim_upstream_terminate(void) { - if (pim_upstream_list) - list_delete (pim_upstream_list); - pim_upstream_list = NULL; + if (pim_upstream_list) + list_delete(pim_upstream_list); + pim_upstream_list = NULL; - if (pim_upstream_hash) - hash_free (pim_upstream_hash); - pim_upstream_hash = NULL; + if (pim_upstream_hash) + hash_free(pim_upstream_hash); + pim_upstream_hash = NULL; } -static int -pim_upstream_equal (const void *arg1, const void *arg2) +static int pim_upstream_equal(const void *arg1, const void *arg2) { - const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; - const struct pim_upstream *up2 = (const struct pim_upstream *)arg2; + const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; + const struct pim_upstream *up2 = (const struct pim_upstream *)arg2; - if ((up1->sg.grp.s_addr == up2->sg.grp.s_addr) && - (up1->sg.src.s_addr == up2->sg.src.s_addr)) - return 1; + if ((up1->sg.grp.s_addr == up2->sg.grp.s_addr) + && (up1->sg.src.s_addr == up2->sg.src.s_addr)) + return 1; - return 0; + return 0; } /* rfc4601:section-4.2:"Data Packet Forwarding Rules" defines @@ -1580,129 +1540,128 @@ pim_upstream_equal (const void *arg1, const void *arg2) */ static bool pim_upstream_kat_start_ok(struct pim_upstream *up) { - /* "iif == RPF_interface(S)" check has to be done by the kernel or hw - * so we will skip that here */ - if (pim_if_connected_to_source(up->rpf.source_nexthop.interface, - up->sg.src)) { - return true; - } - - if ((up->join_state == PIM_UPSTREAM_JOINED) && - !pim_upstream_empty_inherited_olist(up)) { - /* XXX: I have added this RP check just for 3.2 and it's a digression from - * what rfc-4601 says. Till now we were only running KAT on FHR and RP and - * there is some angst around making the change to run it all routers that - * maintain the (S, G) state. This is tracked via CM-13601 and MUST be - * removed to handle spt turn-arounds correctly in a 3-tier clos */ - if (I_am_RP (up->sg.grp)) - return true; - } - - return false; + /* "iif == RPF_interface(S)" check has to be done by the kernel or hw + * so we will skip that here */ + if (pim_if_connected_to_source(up->rpf.source_nexthop.interface, + up->sg.src)) { + return true; + } + + if ((up->join_state == PIM_UPSTREAM_JOINED) + && !pim_upstream_empty_inherited_olist(up)) { + /* XXX: I have added this RP check just for 3.2 and it's a + * digression from + * what rfc-4601 says. Till now we were only running KAT on FHR + * and RP and + * there is some angst around making the change to run it all + * routers that + * maintain the (S, G) state. This is tracked via CM-13601 and + * MUST be + * removed to handle spt turn-arounds correctly in a 3-tier clos + */ + if (I_am_RP(up->sg.grp)) + return true; + } + + return false; } /* * Code to check and see if we've received packets on a S,G mroute * and if so to set the SPT bit appropriately */ -static void -pim_upstream_sg_running (void *arg) +static void pim_upstream_sg_running(void *arg) { - struct pim_upstream *up = (struct pim_upstream *)arg; - - // No packet can have arrived here if this is the case - if (!up->channel_oil || !up->channel_oil->installed) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: %s is not installed in mroute", - __PRETTY_FUNCTION__, up->sg_str); - return; - } - - /* - * This is a bit of a hack - * We've noted that we should rescan but - * we've missed the window for doing so in - * pim_zebra.c for some reason. I am - * only doing this at this point in time - * to get us up and working for the moment - */ - if (up->channel_oil->oil_inherited_rescan) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: Handling unscanned inherited_olist for %s", __PRETTY_FUNCTION__, up->sg_str); - pim_upstream_inherited_olist_decide (up); - up->channel_oil->oil_inherited_rescan = 0; - } - pim_mroute_update_counters (up->channel_oil); - - // Have we seen packets? - if ((up->channel_oil->cc.oldpktcnt >= up->channel_oil->cc.pktcnt) && - (up->channel_oil->cc.lastused/100 > 30)) - { - if (PIM_DEBUG_TRACE) - { - zlog_debug ("%s: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)", - __PRETTY_FUNCTION__, up->sg_str, - up->channel_oil->cc.oldpktcnt, - up->channel_oil->cc.pktcnt, - up->channel_oil->cc.lastused/100); + struct pim_upstream *up = (struct pim_upstream *)arg; + + // No packet can have arrived here if this is the case + if (!up->channel_oil || !up->channel_oil->installed) { + if (PIM_DEBUG_TRACE) + zlog_debug("%s: %s is not installed in mroute", + __PRETTY_FUNCTION__, up->sg_str); + return; + } + + /* + * This is a bit of a hack + * We've noted that we should rescan but + * we've missed the window for doing so in + * pim_zebra.c for some reason. I am + * only doing this at this point in time + * to get us up and working for the moment + */ + if (up->channel_oil->oil_inherited_rescan) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: Handling unscanned inherited_olist for %s", + __PRETTY_FUNCTION__, up->sg_str); + pim_upstream_inherited_olist_decide(up); + up->channel_oil->oil_inherited_rescan = 0; + } + pim_mroute_update_counters(up->channel_oil); + + // Have we seen packets? + if ((up->channel_oil->cc.oldpktcnt >= up->channel_oil->cc.pktcnt) + && (up->channel_oil->cc.lastused / 100 > 30)) { + if (PIM_DEBUG_TRACE) { + zlog_debug( + "%s: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)", + __PRETTY_FUNCTION__, up->sg_str, + up->channel_oil->cc.oldpktcnt, + up->channel_oil->cc.pktcnt, + up->channel_oil->cc.lastused / 100); + } + return; } - return; - } - - if (pim_upstream_kat_start_ok(up)) - { - /* Add a source reference to the stream if - * one doesn't already exist */ - if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("source reference created on kat restart %s", up->sg_str); - - pim_upstream_ref(up, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, __PRETTY_FUNCTION__); - PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); - pim_upstream_fhr_kat_start(up); + + if (pim_upstream_kat_start_ok(up)) { + /* Add a source reference to the stream if + * one doesn't already exist */ + if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "source reference created on kat restart %s", + up->sg_str); + + pim_upstream_ref(up, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, + __PRETTY_FUNCTION__); + PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); + pim_upstream_fhr_kat_start(up); + } + pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); + } else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) + pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); + + if (up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) { + pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface); } - pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); - } - else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) - pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time); - - if (up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) - { - pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface); - } - return; + return; } -void -pim_upstream_add_lhr_star_pimreg (void) +void pim_upstream_add_lhr_star_pimreg(void) { - struct pim_upstream *up; - struct listnode *node; + struct pim_upstream *up; + struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, node, up)) - { - if (up->sg.src.s_addr != INADDR_ANY) - continue; + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, node, up)) { + if (up->sg.src.s_addr != INADDR_ANY) + continue; - if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags)) - continue; + if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) + continue; - pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); - } + pim_channel_add_oif(up->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_IGMP); + } } -void -pim_upstream_spt_prefix_list_update (struct prefix_list *pl) +void pim_upstream_spt_prefix_list_update(struct prefix_list *pl) { - const char *pname = prefix_list_name (pl); + const char *pname = prefix_list_name(pl); - if (pimg->spt.plist && strcmp (pimg->spt.plist, pname) == 0) - { - pim_upstream_remove_lhr_star_pimreg (pname); - } + if (pimg->spt.plist && strcmp(pimg->spt.plist, pname) == 0) { + pim_upstream_remove_lhr_star_pimreg(pname); + } } /* @@ -1717,53 +1676,51 @@ pim_upstream_spt_prefix_list_update (struct prefix_list *pl) * the interface * */ -void -pim_upstream_remove_lhr_star_pimreg (const char *nlist) +void pim_upstream_remove_lhr_star_pimreg(const char *nlist) { - struct pim_upstream *up; - struct listnode *node; - struct prefix_list *np; - struct prefix g; - enum prefix_list_type apply_new; - - np = prefix_list_lookup (AFI_IP, nlist); - - g.family = AF_INET; - g.prefixlen = IPV4_MAX_PREFIXLEN; - - for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, node, up)) - { - if (up->sg.src.s_addr != INADDR_ANY) - continue; - - if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags)) - continue; - - if (!nlist) - { - pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); - continue; - } - g.u.prefix4 = up->sg.grp; - apply_new = prefix_list_apply (np, &g); - if (apply_new == PREFIX_DENY) - pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); - else - pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP); - } + struct pim_upstream *up; + struct listnode *node; + struct prefix_list *np; + struct prefix g; + enum prefix_list_type apply_new; + + np = prefix_list_lookup(AFI_IP, nlist); + + g.family = AF_INET; + g.prefixlen = IPV4_MAX_PREFIXLEN; + + for (ALL_LIST_ELEMENTS_RO(pim_upstream_list, node, up)) { + if (up->sg.src.s_addr != INADDR_ANY) + continue; + + if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) + continue; + + if (!nlist) { + pim_channel_del_oif(up->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_IGMP); + continue; + } + g.u.prefix4 = up->sg.grp; + apply_new = prefix_list_apply(np, &g); + if (apply_new == PREFIX_DENY) + pim_channel_add_oif(up->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_IGMP); + else + pim_channel_del_oif(up->channel_oil, pim_regiface, + PIM_OIF_FLAG_PROTO_IGMP); + } } -void -pim_upstream_init (void) +void pim_upstream_init(void) { - pim_upstream_sg_wheel = wheel_init (master, 31000, 100, - pim_upstream_hash_key, - pim_upstream_sg_running); - pim_upstream_hash = hash_create_size (8192, pim_upstream_hash_key, - pim_upstream_equal, NULL); - - pim_upstream_list = list_new (); - pim_upstream_list->del = (void (*)(void *)) pim_upstream_free; - pim_upstream_list->cmp = pim_upstream_compare; - + pim_upstream_sg_wheel = + wheel_init(master, 31000, 100, pim_upstream_hash_key, + pim_upstream_sg_running); + pim_upstream_hash = hash_create_size(8192, pim_upstream_hash_key, + pim_upstream_equal, NULL); + + pim_upstream_list = list_new(); + pim_upstream_list->del = (void (*)(void *))pim_upstream_free; + pim_upstream_list->cmp = pim_upstream_compare; } diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index acb4b17c7..b6a9729f0 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -70,100 +70,102 @@ #define PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_LHR) enum pim_upstream_state { - PIM_UPSTREAM_NOTJOINED, - PIM_UPSTREAM_JOINED, + PIM_UPSTREAM_NOTJOINED, + PIM_UPSTREAM_JOINED, }; enum pim_reg_state { - PIM_REG_NOINFO, - PIM_REG_JOIN, - PIM_REG_JOIN_PENDING, - PIM_REG_PRUNE, + PIM_REG_NOINFO, + PIM_REG_JOIN, + PIM_REG_JOIN_PENDING, + PIM_REG_PRUNE, }; enum pim_upstream_sptbit { - PIM_UPSTREAM_SPTBIT_FALSE, - PIM_UPSTREAM_SPTBIT_TRUE + PIM_UPSTREAM_SPTBIT_FALSE, + PIM_UPSTREAM_SPTBIT_TRUE }; /* Upstream (S,G) channel in Joined state - + (S,G) in the "Not Joined" state is not represented - + See RFC 4601: 4.5.7. Sending (S,G) Join/Prune Message */ struct pim_upstream { - struct pim_upstream *parent; - struct in_addr upstream_addr;/* Who we are talking to */ - struct in_addr upstream_register; /*Who we received a register from*/ - struct prefix_sg sg; /* (S,G) group key */ - char sg_str[PIM_SG_LEN]; - uint32_t flags; - struct channel_oil *channel_oil; - struct list *sources; - struct list *ifchannels; - - enum pim_upstream_state join_state; - enum pim_reg_state reg_state; - enum pim_upstream_sptbit sptbit; - - int ref_count; - - struct pim_rpf rpf; - - struct thread *t_join_timer; - - /* - * RST(S,G) - */ - struct thread *t_rs_timer; + struct pim_upstream *parent; + struct in_addr upstream_addr; /* Who we are talking to */ + struct in_addr upstream_register; /*Who we received a register from*/ + struct prefix_sg sg; /* (S,G) group key */ + char sg_str[PIM_SG_LEN]; + uint32_t flags; + struct channel_oil *channel_oil; + struct list *sources; + struct list *ifchannels; + + enum pim_upstream_state join_state; + enum pim_reg_state reg_state; + enum pim_upstream_sptbit sptbit; + + int ref_count; + + struct pim_rpf rpf; + + struct thread *t_join_timer; + + /* + * RST(S,G) + */ + struct thread *t_rs_timer; #define PIM_REGISTER_SUPPRESSION_PERIOD (60) #define PIM_REGISTER_PROBE_PERIOD (15) - /* - * KAT(S,G) - */ - struct thread *t_ka_timer; + /* + * KAT(S,G) + */ + struct thread *t_ka_timer; #define PIM_KEEPALIVE_PERIOD (210) #define PIM_RP_KEEPALIVE_PERIOD ( 3 * qpim_register_suppress_time + qpim_register_probe_time ) - /* on the RP we restart a timer to indicate if registers are being rxed for - * SG. This is needed by MSDP to determine its local SA cache */ - struct thread *t_msdp_reg_timer; + /* on the RP we restart a timer to indicate if registers are being rxed + * for + * SG. This is needed by MSDP to determine its local SA cache */ + struct thread *t_msdp_reg_timer; #define PIM_MSDP_REG_RXED_PERIOD (3 * (1.5 * qpim_register_suppress_time)) - int64_t state_transition; /* Record current state uptime */ + int64_t state_transition; /* Record current state uptime */ }; struct list *pim_upstream_list; struct hash *pim_upstream_hash; void pim_upstream_free(struct pim_upstream *up); -struct pim_upstream *pim_upstream_find (struct prefix_sg *sg); -struct pim_upstream *pim_upstream_find_or_add (struct prefix_sg *sg, - struct interface *ifp, int flags, - const char *name); -struct pim_upstream *pim_upstream_add (struct prefix_sg *sg, - struct interface *ifp, int flags, - const char *name); -void pim_upstream_ref (struct pim_upstream *up, int flags, const char *name); -struct pim_upstream *pim_upstream_del(struct pim_upstream *up, const char *name); +struct pim_upstream *pim_upstream_find(struct prefix_sg *sg); +struct pim_upstream *pim_upstream_find_or_add(struct prefix_sg *sg, + struct interface *ifp, int flags, + const char *name); +struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, + struct interface *ifp, int flags, + const char *name); +void pim_upstream_ref(struct pim_upstream *up, int flags, const char *name); +struct pim_upstream *pim_upstream_del(struct pim_upstream *up, + const char *name); int pim_upstream_evaluate_join_desired(struct pim_upstream *up); int pim_upstream_evaluate_join_desired_interface(struct pim_upstream *up, - struct pim_ifchannel *ch, - struct pim_ifchannel *starch); + struct pim_ifchannel *ch, + struct pim_ifchannel *starch); void pim_upstream_update_join_desired(struct pim_upstream *up); void pim_upstream_join_suppress(struct pim_upstream *up, - struct in_addr rpf_addr, - int holdtime); + struct in_addr rpf_addr, int holdtime); void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label, - struct pim_upstream *up); + struct pim_upstream *up); -void pim_upstream_join_timer_restart(struct pim_upstream *up, struct pim_rpf *old); +void pim_upstream_join_timer_restart(struct pim_upstream *up, + struct pim_rpf *old); void pim_upstream_rpf_genid_changed(struct in_addr neigh_addr); void pim_upstream_rpf_interface_changed(struct pim_upstream *up, struct interface *old_rpf_ifp); @@ -171,40 +173,44 @@ void pim_upstream_rpf_interface_changed(struct pim_upstream *up, void pim_upstream_update_could_assert(struct pim_upstream *up); void pim_upstream_update_my_assert_metric(struct pim_upstream *up); -void pim_upstream_keep_alive_timer_start (struct pim_upstream *up, uint32_t time); +void pim_upstream_keep_alive_timer_start(struct pim_upstream *up, + uint32_t time); -int pim_upstream_switch_to_spt_desired (struct prefix_sg *sg); +int pim_upstream_switch_to_spt_desired(struct prefix_sg *sg); #define SwitchToSptDesired(sg) pim_upstream_switch_to_spt_desired (sg) -int pim_upstream_is_sg_rpt (struct pim_upstream *up); +int pim_upstream_is_sg_rpt(struct pim_upstream *up); -void pim_upstream_set_sptbit (struct pim_upstream *up, struct interface *incoming); +void pim_upstream_set_sptbit(struct pim_upstream *up, + struct interface *incoming); -void pim_upstream_start_register_stop_timer (struct pim_upstream *up, int null_register); +void pim_upstream_start_register_stop_timer(struct pim_upstream *up, + int null_register); -void pim_upstream_send_join (struct pim_upstream *up); +void pim_upstream_send_join(struct pim_upstream *up); -void pim_upstream_switch (struct pim_upstream *up, enum pim_upstream_state new_state); +void pim_upstream_switch(struct pim_upstream *up, + enum pim_upstream_state new_state); -const char *pim_upstream_state2str (enum pim_upstream_state join_state); +const char *pim_upstream_state2str(enum pim_upstream_state join_state); #define PIM_REG_STATE_STR_LEN 12 -const char *pim_reg_state2str (enum pim_reg_state state, char *state_str); +const char *pim_reg_state2str(enum pim_reg_state state, char *state_str); -int pim_upstream_inherited_olist_decide (struct pim_upstream *up); -int pim_upstream_inherited_olist (struct pim_upstream *up); -int pim_upstream_empty_inherited_olist (struct pim_upstream *up); +int pim_upstream_inherited_olist_decide(struct pim_upstream *up); +int pim_upstream_inherited_olist(struct pim_upstream *up); +int pim_upstream_empty_inherited_olist(struct pim_upstream *up); -void pim_upstream_find_new_rpf (void); +void pim_upstream_find_new_rpf(void); void pim_upstream_msdp_reg_timer_start(struct pim_upstream *up); -void pim_upstream_init (void); -void pim_upstream_terminate (void); +void pim_upstream_init(void); +void pim_upstream_terminate(void); -void join_timer_start (struct pim_upstream *up); -int pim_upstream_compare (void *arg1, void *arg2); -void pim_upstream_register_reevaluate (void); +void join_timer_start(struct pim_upstream *up); +int pim_upstream_compare(void *arg1, void *arg2); +void pim_upstream_register_reevaluate(void); -void pim_upstream_add_lhr_star_pimreg (void); -void pim_upstream_remove_lhr_star_pimreg (const char *nlist); +void pim_upstream_add_lhr_star_pimreg(void); +void pim_upstream_remove_lhr_star_pimreg(const char *nlist); -void pim_upstream_spt_prefix_list_update (struct prefix_list *pl); +void pim_upstream_spt_prefix_list_update(struct prefix_list *pl); #endif /* PIM_UPSTREAM_H */ diff --git a/pimd/pim_util.c b/pimd/pim_util.c index 139c0e3fb..c2e4b2a46 100644 --- a/pimd/pim_util.c +++ b/pimd/pim_util.c @@ -26,18 +26,18 @@ /* RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code) - + If QQIC < 128, QQI = QQIC If QQIC >= 128, QQI = (mant | 0x10) << (exp + 3) - + 0 1 2 3 4 5 6 7 +-+-+-+-+-+-+-+-+ |1| exp | mant | +-+-+-+-+-+-+-+-+ - + Since exp=0..7 then (exp+3)=3..10, then QQI has one of the following bit patterns: - + exp=0: QQI = 0000.0000.1MMM.M000 exp=1: QQI = 0000.0001.MMMM.0000 ... @@ -48,33 +48,32 @@ */ uint8_t igmp_msg_encode16to8(uint16_t value) { - uint8_t code; - - if (value < 128) { - code = value; - } - else { - uint16_t mask = 0x4000; - uint8_t exp; - uint16_t mant; - for (exp = 7; exp > 0; --exp) { - if (mask & value) - break; - mask >>= 1; - } - mant = 0x000F & (value >> (exp + 3)); - code = ((uint8_t) 1 << 7) | ((uint8_t) exp << 4) | (uint8_t) mant; - } - - return code; + uint8_t code; + + if (value < 128) { + code = value; + } else { + uint16_t mask = 0x4000; + uint8_t exp; + uint16_t mant; + for (exp = 7; exp > 0; --exp) { + if (mask & value) + break; + mask >>= 1; + } + mant = 0x000F & (value >> (exp + 3)); + code = ((uint8_t)1 << 7) | ((uint8_t)exp << 4) | (uint8_t)mant; + } + + return code; } /* RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code) - + If QQIC < 128, QQI = QQIC If QQIC >= 128, QQI = (mant | 0x10) << (exp + 3) - + 0 1 2 3 4 5 6 7 +-+-+-+-+-+-+-+-+ |1| exp | mant | @@ -82,64 +81,57 @@ uint8_t igmp_msg_encode16to8(uint16_t value) */ uint16_t igmp_msg_decode8to16(uint8_t code) { - uint16_t value; - - if (code < 128) { - value = code; - } - else { - uint16_t mant = (code & 0x0F); - uint8_t exp = (code & 0x70) >> 4; - value = (mant | 0x10) << (exp + 3); - } - - return value; + uint16_t value; + + if (code < 128) { + value = code; + } else { + uint16_t mant = (code & 0x0F); + uint8_t exp = (code & 0x70) >> 4; + value = (mant | 0x10) << (exp + 3); + } + + return value; } void pim_pkt_dump(const char *label, const uint8_t *buf, int size) { - zlog_debug("%s: pkt dump size=%d", - label, - size); - zlog_hexdump(buf, size); + zlog_debug("%s: pkt dump size=%d", label, size); + zlog_hexdump(buf, size); } -int -pim_is_group_224_0_0_0_24 (struct in_addr group_addr) +int pim_is_group_224_0_0_0_24(struct in_addr group_addr) { - static int first = 1; - static struct prefix group_224; - struct prefix group; + static int first = 1; + static struct prefix group_224; + struct prefix group; - if (first) - { - str2prefix ("224.0.0.0/24", &group_224); - first = 0; - } + if (first) { + str2prefix("224.0.0.0/24", &group_224); + first = 0; + } - group.family = AF_INET; - group.u.prefix4 = group_addr; - group.prefixlen = 32; + group.family = AF_INET; + group.u.prefix4 = group_addr; + group.prefixlen = 32; - return prefix_match (&group_224, &group); + return prefix_match(&group_224, &group); } -int -pim_is_group_224_4 (struct in_addr group_addr) +int pim_is_group_224_4(struct in_addr group_addr) { - static int first = 1; - static struct prefix group_all; - struct prefix group; + static int first = 1; + static struct prefix group_all; + struct prefix group; - if (first) - { - str2prefix ("224.0.0.0/4", &group_all); - first = 0; - } + if (first) { + str2prefix("224.0.0.0/4", &group_all); + first = 0; + } - group.family = AF_INET; - group.u.prefix4 = group_addr; - group.prefixlen = 32; + group.family = AF_INET; + group.u.prefix4 = group_addr; + group.prefixlen = 32; - return prefix_match (&group_all, &group); + return prefix_match(&group_all, &group); } diff --git a/pimd/pim_util.h b/pimd/pim_util.h index 478800520..1b319cfe4 100644 --- a/pimd/pim_util.h +++ b/pimd/pim_util.h @@ -31,6 +31,6 @@ uint16_t igmp_msg_decode8to16(uint8_t code); void pim_pkt_dump(const char *label, const uint8_t *buf, int size); -int pim_is_group_224_0_0_0_24 (struct in_addr group_addr); -int pim_is_group_224_4 (struct in_addr group_addr); +int pim_is_group_224_0_0_0_24(struct in_addr group_addr); +int pim_is_group_224_4(struct in_addr group_addr); #endif /* PIM_UTIL_H */ diff --git a/pimd/pim_version.c b/pimd/pim_version.c index 1da4b9663..439f745ac 100644 --- a/pimd/pim_version.c +++ b/pimd/pim_version.c @@ -21,4 +21,4 @@ #include "pim_version.h" -const char * const PIMD_VERSION = PIMD_VERSION_STR; +const char *const PIMD_VERSION = PIMD_VERSION_STR; diff --git a/pimd/pim_version.h b/pimd/pim_version.h index 589c6f68a..c45d01a13 100644 --- a/pimd/pim_version.h +++ b/pimd/pim_version.h @@ -22,6 +22,6 @@ #define PIMD_VERSION_STR "0.166" -const char * const PIMD_VERSION; +const char *const PIMD_VERSION; #endif /* PIM_VERSION_H */ diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 81b49c630..a78776791 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -40,284 +40,287 @@ #include "pim_ssm.h" #include "pim_bfd.h" -int -pim_debug_config_write (struct vty *vty) +int pim_debug_config_write(struct vty *vty) { - int writes = 0; - - if (PIM_DEBUG_MSDP_EVENTS) { - vty_out (vty, "debug msdp events\n"); - ++writes; - } - if (PIM_DEBUG_MSDP_PACKETS) { - vty_out (vty, "debug msdp packets\n"); - ++writes; - } - if (PIM_DEBUG_MSDP_INTERNAL) { - vty_out (vty, "debug msdp internal\n"); - ++writes; - } - if (PIM_DEBUG_IGMP_EVENTS) { - vty_out (vty, "debug igmp events\n"); - ++writes; - } - if (PIM_DEBUG_IGMP_PACKETS) { - vty_out (vty, "debug igmp packets\n"); - ++writes; - } - if (PIM_DEBUG_IGMP_TRACE) { - vty_out (vty, "debug igmp trace\n"); - ++writes; - } - if (PIM_DEBUG_IGMP_TRACE_DETAIL) { - vty_out (vty, "debug igmp trace detail\n"); - ++writes; - } - - if (PIM_DEBUG_MROUTE) { - vty_out (vty, "debug mroute\n"); - ++writes; - } - - if (PIM_DEBUG_MROUTE_DETAIL) { - vty_out (vty, "debug mroute detail\n"); - ++writes; - } - - if (PIM_DEBUG_PIM_EVENTS) { - vty_out (vty, "debug pim events\n"); - ++writes; - } - if (PIM_DEBUG_PIM_PACKETS) { - vty_out (vty, "debug pim packets\n"); - ++writes; - } - if (PIM_DEBUG_PIM_PACKETDUMP_SEND) { - vty_out (vty, "debug pim packet-dump send\n"); - ++writes; - } - if (PIM_DEBUG_PIM_PACKETDUMP_RECV) { - vty_out (vty, "debug pim packet-dump receive\n"); - ++writes; - } - - if (PIM_DEBUG_PIM_TRACE) { - vty_out (vty, "debug pim trace\n"); - ++writes; - } - if (PIM_DEBUG_PIM_TRACE_DETAIL) { - vty_out (vty, "debug pim trace detail\n"); - ++writes; - } - - if (PIM_DEBUG_ZEBRA) { - vty_out (vty, "debug pim zebra\n"); - ++writes; - } - - if (PIM_DEBUG_SSMPINGD) { - vty_out (vty, "debug ssmpingd\n"); - ++writes; - } - - if (PIM_DEBUG_PIM_HELLO) { - vty_out (vty, "debug pim packets hello\n"); - ++writes; - } - - if (PIM_DEBUG_PIM_J_P) { - vty_out (vty, "debug pim packets joins\n"); - ++writes; - } - - if (PIM_DEBUG_PIM_REG) { - vty_out (vty, "debug pim packets register\n"); - ++writes; - } - - if (PIM_DEBUG_STATIC) { - vty_out (vty, "debug pim static\n"); - ++writes; - } - - return writes; + int writes = 0; + + if (PIM_DEBUG_MSDP_EVENTS) { + vty_out(vty, "debug msdp events\n"); + ++writes; + } + if (PIM_DEBUG_MSDP_PACKETS) { + vty_out(vty, "debug msdp packets\n"); + ++writes; + } + if (PIM_DEBUG_MSDP_INTERNAL) { + vty_out(vty, "debug msdp internal\n"); + ++writes; + } + if (PIM_DEBUG_IGMP_EVENTS) { + vty_out(vty, "debug igmp events\n"); + ++writes; + } + if (PIM_DEBUG_IGMP_PACKETS) { + vty_out(vty, "debug igmp packets\n"); + ++writes; + } + if (PIM_DEBUG_IGMP_TRACE) { + vty_out(vty, "debug igmp trace\n"); + ++writes; + } + if (PIM_DEBUG_IGMP_TRACE_DETAIL) { + vty_out(vty, "debug igmp trace detail\n"); + ++writes; + } + + if (PIM_DEBUG_MROUTE) { + vty_out(vty, "debug mroute\n"); + ++writes; + } + + if (PIM_DEBUG_MROUTE_DETAIL) { + vty_out(vty, "debug mroute detail\n"); + ++writes; + } + + if (PIM_DEBUG_PIM_EVENTS) { + vty_out(vty, "debug pim events\n"); + ++writes; + } + if (PIM_DEBUG_PIM_PACKETS) { + vty_out(vty, "debug pim packets\n"); + ++writes; + } + if (PIM_DEBUG_PIM_PACKETDUMP_SEND) { + vty_out(vty, "debug pim packet-dump send\n"); + ++writes; + } + if (PIM_DEBUG_PIM_PACKETDUMP_RECV) { + vty_out(vty, "debug pim packet-dump receive\n"); + ++writes; + } + + if (PIM_DEBUG_PIM_TRACE) { + vty_out(vty, "debug pim trace\n"); + ++writes; + } + if (PIM_DEBUG_PIM_TRACE_DETAIL) { + vty_out(vty, "debug pim trace detail\n"); + ++writes; + } + + if (PIM_DEBUG_ZEBRA) { + vty_out(vty, "debug pim zebra\n"); + ++writes; + } + + if (PIM_DEBUG_SSMPINGD) { + vty_out(vty, "debug ssmpingd\n"); + ++writes; + } + + if (PIM_DEBUG_PIM_HELLO) { + vty_out(vty, "debug pim packets hello\n"); + ++writes; + } + + if (PIM_DEBUG_PIM_J_P) { + vty_out(vty, "debug pim packets joins\n"); + ++writes; + } + + if (PIM_DEBUG_PIM_REG) { + vty_out(vty, "debug pim packets register\n"); + ++writes; + } + + if (PIM_DEBUG_STATIC) { + vty_out(vty, "debug pim static\n"); + ++writes; + } + + return writes; } int pim_global_config_write(struct vty *vty) { - int writes = 0; - struct pim_ssm *ssm = pimg->ssm_info; - - writes += pim_msdp_config_write (vty); - - if (!pimg->send_v6_secondary) - { - vty_out (vty, "no ip pim send-v6-secondary\n"); - ++writes; - } - - writes += pim_rp_config_write (vty); - - if (qpim_register_suppress_time != PIM_REGISTER_SUPPRESSION_TIME_DEFAULT) - { - vty_out (vty, "ip pim register-suppress-time %d\n", - qpim_register_suppress_time); - ++writes; - } - if (qpim_t_periodic != PIM_DEFAULT_T_PERIODIC) - { - vty_out (vty, "ip pim join-prune-interval %d\n", - qpim_t_periodic); - ++writes; - } - if (qpim_keep_alive_time != PIM_KEEPALIVE_PERIOD) - { - vty_out (vty, "ip pim keep-alive-timer %d\n", - qpim_keep_alive_time); - ++writes; - } - if (qpim_packet_process != PIM_DEFAULT_PACKET_PROCESS) - { - vty_out (vty, "ip pim packets %d\n", - qpim_packet_process); - ++writes; - } - if (ssm->plist_name) - { - vty_out (vty, "ip pim ssm prefix-list %s\n", - ssm->plist_name); - ++writes; - } - if (pimg->spt.switchover == PIM_SPT_INFINITY) - { - if (pimg->spt.plist) - vty_out (vty, "ip pim spt-switchover infinity-and-beyond prefix-list %s\n", - pimg->spt.plist); - else - vty_out (vty,"ip pim spt-switchover infinity-and-beyond\n"); - ++writes; - } - if (qpim_ecmp_rebalance_enable) - { - vty_out (vty, "ip pim ecmp rebalance\n"); - ++writes; - } - else if (qpim_ecmp_enable) - { - vty_out (vty, "ip pim ecmp\n"); - ++writes; - } - if (qpim_ssmpingd_list) { - struct listnode *node; - struct ssmpingd_sock *ss; - vty_out (vty, "!\n"); - ++writes; - for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", ss->source_addr, source_str, sizeof(source_str)); - vty_out (vty, "ip ssmpingd %s\n", source_str); - ++writes; - } - } - - return writes; -} + int writes = 0; + struct pim_ssm *ssm = pimg->ssm_info; -int pim_interface_config_write(struct vty *vty) -{ - int writes = 0; - struct listnode *node; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) { - - /* IF name */ - vty_out (vty, "interface %s\n", ifp->name); - ++writes; - - if (ifp->info) { - struct pim_interface *pim_ifp = ifp->info; - - if (PIM_IF_TEST_PIM(pim_ifp->options)) { - vty_out (vty, " ip pim sm\n"); - ++writes; - } - - /* IF ip pim drpriority */ - if (pim_ifp->pim_dr_priority != PIM_DEFAULT_DR_PRIORITY) { - vty_out (vty, " ip pim drpriority %u\n",pim_ifp->pim_dr_priority); - ++writes; - } - - /* IF ip pim hello */ - if (pim_ifp->pim_hello_period != PIM_DEFAULT_HELLO_PERIOD) { - vty_out(vty, " ip pim hello %d", pim_ifp->pim_hello_period); - if (pim_ifp->pim_default_holdtime != -1) - vty_out(vty, " %d", pim_ifp->pim_default_holdtime); - vty_out (vty, "\n"); - } - - /* update source */ - if (PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) { - char src_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", pim_ifp->update_source, src_str, - sizeof(src_str)); - vty_out (vty, " ip pim use-source %s\n", src_str); - ++writes; - } - - /* IF ip igmp */ - if (PIM_IF_TEST_IGMP(pim_ifp->options)) { - vty_out (vty, " ip igmp\n"); - ++writes; - } - - /* ip igmp version */ - if (pim_ifp->igmp_version != IGMP_DEFAULT_VERSION) - { - vty_out (vty, " ip igmp version %d\n", - pim_ifp->igmp_version); - ++writes; - } - - /* IF ip igmp query-interval */ - if (pim_ifp->igmp_default_query_interval != IGMP_GENERAL_QUERY_INTERVAL) - { - vty_out (vty, " ip igmp query-interval %d\n", - pim_ifp->igmp_default_query_interval); - ++writes; + writes += pim_msdp_config_write(vty); + + if (!pimg->send_v6_secondary) { + vty_out(vty, "no ip pim send-v6-secondary\n"); + ++writes; } - /* IF ip igmp query-max-response-time */ - if (pim_ifp->igmp_query_max_response_time_dsec != IGMP_QUERY_MAX_RESPONSE_TIME_DSEC) - { - vty_out (vty, " ip igmp query-max-response-time %d\n", - pim_ifp->igmp_query_max_response_time_dsec); - ++writes; + writes += pim_rp_config_write(vty); + + if (qpim_register_suppress_time + != PIM_REGISTER_SUPPRESSION_TIME_DEFAULT) { + vty_out(vty, "ip pim register-suppress-time %d\n", + qpim_register_suppress_time); + ++writes; } + if (qpim_t_periodic != PIM_DEFAULT_T_PERIODIC) { + vty_out(vty, "ip pim join-prune-interval %d\n", + qpim_t_periodic); + ++writes; + } + if (qpim_keep_alive_time != PIM_KEEPALIVE_PERIOD) { + vty_out(vty, "ip pim keep-alive-timer %d\n", + qpim_keep_alive_time); + ++writes; + } + if (qpim_packet_process != PIM_DEFAULT_PACKET_PROCESS) { + vty_out(vty, "ip pim packets %d\n", qpim_packet_process); + ++writes; + } + if (ssm->plist_name) { + vty_out(vty, "ip pim ssm prefix-list %s\n", ssm->plist_name); + ++writes; + } + if (pimg->spt.switchover == PIM_SPT_INFINITY) { + if (pimg->spt.plist) + vty_out(vty, + "ip pim spt-switchover infinity-and-beyond prefix-list %s\n", + pimg->spt.plist); + else + vty_out(vty, + "ip pim spt-switchover infinity-and-beyond\n"); + ++writes; + } + if (qpim_ecmp_rebalance_enable) { + vty_out(vty, "ip pim ecmp rebalance\n"); + ++writes; + } else if (qpim_ecmp_enable) { + vty_out(vty, "ip pim ecmp\n"); + ++writes; + } + if (qpim_ssmpingd_list) { + struct listnode *node; + struct ssmpingd_sock *ss; + vty_out(vty, "!\n"); + ++writes; + for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", ss->source_addr, source_str, + sizeof(source_str)); + vty_out(vty, "ip ssmpingd %s\n", source_str); + ++writes; + } + } + + return writes; +} - /* IF ip igmp join */ - if (pim_ifp->igmp_join_list) { +int pim_interface_config_write(struct vty *vty) +{ + int writes = 0; struct listnode *node; - struct igmp_join *ij; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_join_list, node, ij)) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", ij->group_addr, group_str, sizeof(group_str)); - inet_ntop(AF_INET, &ij->source_addr, source_str, sizeof(source_str)); - vty_out (vty, " ip igmp join %s %s\n", - group_str,source_str); - ++writes; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + + /* IF name */ + vty_out(vty, "interface %s\n", ifp->name); + ++writes; + + if (ifp->info) { + struct pim_interface *pim_ifp = ifp->info; + + if (PIM_IF_TEST_PIM(pim_ifp->options)) { + vty_out(vty, " ip pim sm\n"); + ++writes; + } + + /* IF ip pim drpriority */ + if (pim_ifp->pim_dr_priority + != PIM_DEFAULT_DR_PRIORITY) { + vty_out(vty, " ip pim drpriority %u\n", + pim_ifp->pim_dr_priority); + ++writes; + } + + /* IF ip pim hello */ + if (pim_ifp->pim_hello_period + != PIM_DEFAULT_HELLO_PERIOD) { + vty_out(vty, " ip pim hello %d", + pim_ifp->pim_hello_period); + if (pim_ifp->pim_default_holdtime != -1) + vty_out(vty, " %d", + pim_ifp->pim_default_holdtime); + vty_out(vty, "\n"); + } + + /* update source */ + if (PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) { + char src_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", pim_ifp->update_source, + src_str, sizeof(src_str)); + vty_out(vty, " ip pim use-source %s\n", + src_str); + ++writes; + } + + /* IF ip igmp */ + if (PIM_IF_TEST_IGMP(pim_ifp->options)) { + vty_out(vty, " ip igmp\n"); + ++writes; + } + + /* ip igmp version */ + if (pim_ifp->igmp_version != IGMP_DEFAULT_VERSION) { + vty_out(vty, " ip igmp version %d\n", + pim_ifp->igmp_version); + ++writes; + } + + /* IF ip igmp query-interval */ + if (pim_ifp->igmp_default_query_interval + != IGMP_GENERAL_QUERY_INTERVAL) { + vty_out(vty, " ip igmp query-interval %d\n", + pim_ifp->igmp_default_query_interval); + ++writes; + } + + /* IF ip igmp query-max-response-time */ + if (pim_ifp->igmp_query_max_response_time_dsec + != IGMP_QUERY_MAX_RESPONSE_TIME_DSEC) { + vty_out(vty, + " ip igmp query-max-response-time %d\n", + pim_ifp->igmp_query_max_response_time_dsec); + ++writes; + } + + /* IF ip igmp join */ + if (pim_ifp->igmp_join_list) { + struct listnode *node; + struct igmp_join *ij; + for (ALL_LIST_ELEMENTS_RO( + pim_ifp->igmp_join_list, node, + ij)) { + char group_str[INET_ADDRSTRLEN]; + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", ij->group_addr, + group_str, + sizeof(group_str)); + inet_ntop(AF_INET, &ij->source_addr, + source_str, + sizeof(source_str)); + vty_out(vty, " ip igmp join %s %s\n", + group_str, source_str); + ++writes; + } + } + + writes += pim_static_write_mroute(vty, ifp); + } + vty_out(vty, "!\n"); + ++writes; + /* PIM BFD write */ + pim_bfd_write_config(vty, ifp); } - } - - writes += pim_static_write_mroute (vty, ifp); - } - vty_out (vty, "!\n"); - ++writes; - /* PIM BFD write */ - pim_bfd_write_config (vty, ifp); - } - return writes; + return writes; } diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index b4fff9712..c5cca7d1b 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -58,906 +58,950 @@ static struct zclient *zclient = NULL; static int pim_router_id_update_zebra(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { - struct prefix router_id; + struct prefix router_id; - zebra_router_id_update_read(zclient->ibuf, &router_id); + zebra_router_id_update_read(zclient->ibuf, &router_id); - return 0; + return 0; } static int pim_zebra_if_add(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - - /* - zebra api adds/dels interfaces using the same call - interface_add_read below, see comments in lib/zclient.c - */ - ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); - if (!ifp) - return 0; - - if (PIM_DEBUG_ZEBRA) { - zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d", - __PRETTY_FUNCTION__, - ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, - ifp->mtu, if_is_operative(ifp)); - } - - if (if_is_operative(ifp)) - pim_if_addr_add_all(ifp); - - return 0; + struct interface *ifp; + + /* + zebra api adds/dels interfaces using the same call + interface_add_read below, see comments in lib/zclient.c + */ + ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); + if (!ifp) + return 0; + + if (PIM_DEBUG_ZEBRA) { + zlog_debug( + "%s: %s index %d flags %ld metric %d mtu %d operative %d", + __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, + (long)ifp->flags, ifp->metric, ifp->mtu, + if_is_operative(ifp)); + } + + if (if_is_operative(ifp)) + pim_if_addr_add_all(ifp); + + return 0; } static int pim_zebra_if_del(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - - /* - zebra api adds/dels interfaces using the same call - interface_add_read below, see comments in lib/zclient.c - - comments in lib/zclient.c seem to indicate that calling - zebra_interface_add_read is the correct call, but that - results in an attemted out of bounds read which causes - pimd to assert. Other clients use zebra_interface_state_read - and it appears to work just fine. - */ - ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); - if (!ifp) - return 0; - - if (PIM_DEBUG_ZEBRA) { - zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d", - __PRETTY_FUNCTION__, - ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, - ifp->mtu, if_is_operative(ifp)); - } - - if (!if_is_operative(ifp)) - pim_if_addr_del_all(ifp); - - return 0; + struct interface *ifp; + + /* + zebra api adds/dels interfaces using the same call + interface_add_read below, see comments in lib/zclient.c + + comments in lib/zclient.c seem to indicate that calling + zebra_interface_add_read is the correct call, but that + results in an attemted out of bounds read which causes + pimd to assert. Other clients use zebra_interface_state_read + and it appears to work just fine. + */ + ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); + if (!ifp) + return 0; + + if (PIM_DEBUG_ZEBRA) { + zlog_debug( + "%s: %s index %d flags %ld metric %d mtu %d operative %d", + __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, + (long)ifp->flags, ifp->metric, ifp->mtu, + if_is_operative(ifp)); + } + + if (!if_is_operative(ifp)) + pim_if_addr_del_all(ifp); + + return 0; } static int pim_zebra_if_state_up(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - - /* - zebra api notifies interface up/down events by using the same call - zebra_interface_state_read below, see comments in lib/zclient.c - */ - ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); - if (!ifp) - return 0; - - if (PIM_DEBUG_ZEBRA) { - zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d", - __PRETTY_FUNCTION__, - ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, - ifp->mtu, if_is_operative(ifp)); - } - - if (if_is_operative(ifp)) { - /* - pim_if_addr_add_all() suffices for bringing up both IGMP and PIM - */ - pim_if_addr_add_all(ifp); - } - - return 0; + struct interface *ifp; + + /* + zebra api notifies interface up/down events by using the same call + zebra_interface_state_read below, see comments in lib/zclient.c + */ + ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); + if (!ifp) + return 0; + + if (PIM_DEBUG_ZEBRA) { + zlog_debug( + "%s: %s index %d flags %ld metric %d mtu %d operative %d", + __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, + (long)ifp->flags, ifp->metric, ifp->mtu, + if_is_operative(ifp)); + } + + if (if_is_operative(ifp)) { + /* + pim_if_addr_add_all() suffices for bringing up both IGMP and + PIM + */ + pim_if_addr_add_all(ifp); + } + + return 0; } static int pim_zebra_if_state_down(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - - /* - zebra api notifies interface up/down events by using the same call - zebra_interface_state_read below, see comments in lib/zclient.c - */ - ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); - if (!ifp) - return 0; - - if (PIM_DEBUG_ZEBRA) { - zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d", - __PRETTY_FUNCTION__, - ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, - ifp->mtu, if_is_operative(ifp)); - } - - if (!if_is_operative(ifp)) { - pim_ifchannel_delete_all(ifp); - /* - pim_if_addr_del_all() suffices for shutting down IGMP, - but not for shutting down PIM - */ - pim_if_addr_del_all(ifp); - - /* - pim_sock_delete() closes the socket, stops read and timer threads, - and kills all neighbors. - */ - if (ifp->info) { - pim_sock_delete(ifp, "link down"); - } - } - - if (ifp->info) - pim_if_del_vif(ifp); - - return 0; + struct interface *ifp; + + /* + zebra api notifies interface up/down events by using the same call + zebra_interface_state_read below, see comments in lib/zclient.c + */ + ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); + if (!ifp) + return 0; + + if (PIM_DEBUG_ZEBRA) { + zlog_debug( + "%s: %s index %d flags %ld metric %d mtu %d operative %d", + __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, + (long)ifp->flags, ifp->metric, ifp->mtu, + if_is_operative(ifp)); + } + + if (!if_is_operative(ifp)) { + pim_ifchannel_delete_all(ifp); + /* + pim_if_addr_del_all() suffices for shutting down IGMP, + but not for shutting down PIM + */ + pim_if_addr_del_all(ifp); + + /* + pim_sock_delete() closes the socket, stops read and timer + threads, + and kills all neighbors. + */ + if (ifp->info) { + pim_sock_delete(ifp, "link down"); + } + } + + if (ifp->info) + pim_if_del_vif(ifp); + + return 0; } #ifdef PIM_DEBUG_IFADDR_DUMP static void dump_if_address(struct interface *ifp) { - struct connected *ifc; - struct listnode *node; - - zlog_debug("%s %s: interface %s addresses:", - __FILE__, __PRETTY_FUNCTION__, - ifp->name); - - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { - struct prefix *p = ifc->address; - - if (p->family != AF_INET) - continue; - - zlog_debug("%s %s: interface %s address %s %s", - __FILE__, __PRETTY_FUNCTION__, - ifp->name, - inet_ntoa(p->u.prefix4), - CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ? - "secondary" : "primary"); - } + struct connected *ifc; + struct listnode *node; + + zlog_debug("%s %s: interface %s addresses:", __FILE__, + __PRETTY_FUNCTION__, ifp->name); + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { + struct prefix *p = ifc->address; + + if (p->family != AF_INET) + continue; + + zlog_debug("%s %s: interface %s address %s %s", __FILE__, + __PRETTY_FUNCTION__, ifp->name, + inet_ntoa(p->u.prefix4), + CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) + ? "secondary" + : "primary"); + } } #endif static int pim_zebra_if_address_add(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { - struct connected *c; - struct prefix *p; - struct pim_interface *pim_ifp; - - /* - zebra api notifies address adds/dels events by using the same call - interface_add_read below, see comments in lib/zclient.c - - zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...) - will add address to interface list by calling - connected_add_by_prefix() - */ - c = zebra_interface_address_read(command, zclient->ibuf, vrf_id); - if (!c) - return 0; - - pim_ifp = c->ifp->info; - p = c->address; - - if (PIM_DEBUG_ZEBRA) { - char buf[BUFSIZ]; - prefix2str(p, buf, BUFSIZ); - zlog_debug("%s: %s connected IP address %s flags %u %s", - __PRETTY_FUNCTION__, - c->ifp->name, buf, c->flags, - CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) ? "secondary" : "primary"); - + struct connected *c; + struct prefix *p; + struct pim_interface *pim_ifp; + + /* + zebra api notifies address adds/dels events by using the same call + interface_add_read below, see comments in lib/zclient.c + + zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...) + will add address to interface list by calling + connected_add_by_prefix() + */ + c = zebra_interface_address_read(command, zclient->ibuf, vrf_id); + if (!c) + return 0; + + pim_ifp = c->ifp->info; + p = c->address; + + if (PIM_DEBUG_ZEBRA) { + char buf[BUFSIZ]; + prefix2str(p, buf, BUFSIZ); + zlog_debug("%s: %s connected IP address %s flags %u %s", + __PRETTY_FUNCTION__, c->ifp->name, buf, c->flags, + CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) + ? "secondary" + : "primary"); + #ifdef PIM_DEBUG_IFADDR_DUMP - dump_if_address(c->ifp); + dump_if_address(c->ifp); #endif - } + } - if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) { - /* trying to add primary address */ + if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) { + /* trying to add primary address */ - struct in_addr primary_addr = pim_find_primary_addr(c->ifp); - if (p->family != AF_INET || primary_addr.s_addr != p->u.prefix4.s_addr) { - if (PIM_DEBUG_ZEBRA) { - /* but we had a primary address already */ + struct in_addr primary_addr = pim_find_primary_addr(c->ifp); + if (p->family != AF_INET + || primary_addr.s_addr != p->u.prefix4.s_addr) { + if (PIM_DEBUG_ZEBRA) { + /* but we had a primary address already */ - char buf[BUFSIZ]; + char buf[BUFSIZ]; - prefix2str(p, buf, BUFSIZ); + prefix2str(p, buf, BUFSIZ); - zlog_warn("%s: %s : forcing secondary flag on %s", - __PRETTY_FUNCTION__, - c->ifp->name, buf); - } - SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY); - } - } + zlog_warn( + "%s: %s : forcing secondary flag on %s", + __PRETTY_FUNCTION__, c->ifp->name, buf); + } + SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY); + } + } - pim_if_addr_add(c); - if (pim_ifp) - pim_rp_check_on_if_add(pim_ifp); + pim_if_addr_add(c); + if (pim_ifp) + pim_rp_check_on_if_add(pim_ifp); - if (if_is_loopback (c->ifp)) - { - struct listnode *ifnode; - struct interface *ifp; + if (if_is_loopback(c->ifp)) { + struct listnode *ifnode; + struct interface *ifp; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) - { - if (!if_is_loopback (ifp) && if_is_operative (ifp)) - pim_if_addr_add_all (ifp); - } - } + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, + ifp)) { + if (!if_is_loopback(ifp) && if_is_operative(ifp)) + pim_if_addr_add_all(ifp); + } + } - return 0; + return 0; } static int pim_zebra_if_address_del(int command, struct zclient *client, zebra_size_t length, vrf_id_t vrf_id) { - struct connected *c; - struct prefix *p; - - /* - zebra api notifies address adds/dels events by using the same call - interface_add_read below, see comments in lib/zclient.c - - zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...) - will remove address from interface list by calling - connected_delete_by_prefix() - */ - c = zebra_interface_address_read(command, client->ibuf, vrf_id); - if (!c) - return 0; - - p = c->address; - if (p->family == AF_INET) - { - if (PIM_DEBUG_ZEBRA) { - char buf[BUFSIZ]; - prefix2str(p, buf, BUFSIZ); - zlog_debug("%s: %s disconnected IP address %s flags %u %s", - __PRETTY_FUNCTION__, - c->ifp->name, buf, c->flags, - CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) ? "secondary" : "primary"); + struct connected *c; + struct prefix *p; + + /* + zebra api notifies address adds/dels events by using the same call + interface_add_read below, see comments in lib/zclient.c + + zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...) + will remove address from interface list by calling + connected_delete_by_prefix() + */ + c = zebra_interface_address_read(command, client->ibuf, vrf_id); + if (!c) + return 0; + + p = c->address; + if (p->family == AF_INET) { + if (PIM_DEBUG_ZEBRA) { + char buf[BUFSIZ]; + prefix2str(p, buf, BUFSIZ); + zlog_debug( + "%s: %s disconnected IP address %s flags %u %s", + __PRETTY_FUNCTION__, c->ifp->name, buf, + c->flags, + CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) + ? "secondary" + : "primary"); #ifdef PIM_DEBUG_IFADDR_DUMP - dump_if_address(c->ifp); + dump_if_address(c->ifp); #endif - } + } - pim_if_addr_del(c, 0); - pim_rp_setup(); - pim_i_am_rp_re_evaluate(); - } + pim_if_addr_del(c, 0); + pim_rp_setup(); + pim_i_am_rp_re_evaluate(); + } - connected_free (c); - return 0; + connected_free(c); + return 0; } static void scan_upstream_rpf_cache() { - struct listnode *up_node; - struct listnode *ifnode; - struct listnode *up_nextnode; - struct listnode *node; - struct pim_upstream *up; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { - enum pim_rpf_result rpf_result; - struct pim_rpf old; - struct prefix nht_p; - - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; - pim_resolve_upstream_nh (&nht_p); - - old.source_nexthop.interface = up->rpf.source_nexthop.interface; - old.source_nexthop.nbr = up->rpf.source_nexthop.nbr; - rpf_result = pim_rpf_update(up, &old, 0); - - if (rpf_result == PIM_RPF_FAILURE) - continue; - - if (rpf_result == PIM_RPF_CHANGED) { - struct pim_neighbor *nbr; - - nbr = pim_neighbor_find (old.source_nexthop.interface, - old.rpf_addr.u.prefix4); - if (nbr) - pim_jp_agg_remove_group (nbr->upstream_jp_agg, up); - - /* - * We have detected a case where we might need to rescan - * the inherited o_list so do it. - */ - if (up->channel_oil->oil_inherited_rescan) - { - pim_upstream_inherited_olist_decide (up); - up->channel_oil->oil_inherited_rescan = 0; - } - - if (up->join_state == PIM_UPSTREAM_JOINED) { - /* - * If we come up real fast we can be here - * where the mroute has not been installed - * so install it. - */ - if (!up->channel_oil->installed) - pim_mroute_add (up->channel_oil, __PRETTY_FUNCTION__); - - /* - * RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages - * - * Transitions from Joined State - * - * RPF'(S,G) changes not due to an Assert - * - * The upstream (S,G) state machine remains in Joined - * state. Send Join(S,G) to the new upstream neighbor, which is - * the new value of RPF'(S,G). Send Prune(S,G) to the old - * upstream neighbor, which is the old value of RPF'(S,G). Set - * the Join Timer (JT) to expire after t_periodic seconds. - */ - pim_jp_agg_switch_interface (&old, &up->rpf, up); - - pim_upstream_join_timer_restart(up, &old); - } /* up->join_state == PIM_UPSTREAM_JOINED */ - - /* FIXME can join_desired actually be changed by pim_rpf_update() - returning PIM_RPF_CHANGED ? */ - pim_upstream_update_join_desired(up); - - } /* PIM_RPF_CHANGED */ - - } /* for (qpim_upstream_list) */ - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) - if (ifp->info) - { - struct pim_interface *pim_ifp = ifp->info; - struct pim_iface_upstream_switch *us; - - for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list, node, us)) - { - struct pim_rpf rpf; - rpf.source_nexthop.interface = ifp; - rpf.rpf_addr.u.prefix4 = us->address; - pim_joinprune_send(&rpf, us->us); - pim_jp_agg_clear_group(us->us); - } - } + struct listnode *up_node; + struct listnode *ifnode; + struct listnode *up_nextnode; + struct listnode *node; + struct pim_upstream *up; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS(pim_upstream_list, up_node, up_nextnode, up)) { + enum pim_rpf_result rpf_result; + struct pim_rpf old; + struct prefix nht_p; + + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; + pim_resolve_upstream_nh(&nht_p); + + old.source_nexthop.interface = up->rpf.source_nexthop.interface; + old.source_nexthop.nbr = up->rpf.source_nexthop.nbr; + rpf_result = pim_rpf_update(up, &old, 0); + + if (rpf_result == PIM_RPF_FAILURE) + continue; + + if (rpf_result == PIM_RPF_CHANGED) { + struct pim_neighbor *nbr; + + nbr = pim_neighbor_find(old.source_nexthop.interface, + old.rpf_addr.u.prefix4); + if (nbr) + pim_jp_agg_remove_group(nbr->upstream_jp_agg, + up); + + /* + * We have detected a case where we might need to rescan + * the inherited o_list so do it. + */ + if (up->channel_oil->oil_inherited_rescan) { + pim_upstream_inherited_olist_decide(up); + up->channel_oil->oil_inherited_rescan = 0; + } + + if (up->join_state == PIM_UPSTREAM_JOINED) { + /* + * If we come up real fast we can be here + * where the mroute has not been installed + * so install it. + */ + if (!up->channel_oil->installed) + pim_mroute_add(up->channel_oil, + __PRETTY_FUNCTION__); + + /* + * RFC 4601: 4.5.7. Sending (S,G) Join/Prune + * Messages + * + * Transitions from Joined State + * + * RPF'(S,G) changes not due to an Assert + * + * The upstream (S,G) state machine remains in + * Joined + * state. Send Join(S,G) to the new upstream + * neighbor, which is + * the new value of RPF'(S,G). Send Prune(S,G) + * to the old + * upstream neighbor, which is the old value of + * RPF'(S,G). Set + * the Join Timer (JT) to expire after + * t_periodic seconds. + */ + pim_jp_agg_switch_interface(&old, &up->rpf, up); + + pim_upstream_join_timer_restart(up, &old); + } /* up->join_state == PIM_UPSTREAM_JOINED */ + + /* FIXME can join_desired actually be changed by + pim_rpf_update() + returning PIM_RPF_CHANGED ? */ + pim_upstream_update_join_desired(up); + + } /* PIM_RPF_CHANGED */ + + } /* for (qpim_upstream_list) */ + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) + if (ifp->info) { + struct pim_interface *pim_ifp = ifp->info; + struct pim_iface_upstream_switch *us; + + for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list, + node, us)) { + struct pim_rpf rpf; + rpf.source_nexthop.interface = ifp; + rpf.rpf_addr.u.prefix4 = us->address; + pim_joinprune_send(&rpf, us->us); + pim_jp_agg_clear_group(us->us); + } + } } -void -pim_scan_individual_oil (struct channel_oil *c_oil, int in_vif_index) +void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index) { - struct in_addr vif_source; - int input_iface_vif_index; - int old_vif_index; - - if (!pim_rp_set_upstream_addr (&vif_source, c_oil->oil.mfcc_origin, c_oil->oil.mfcc_mcastgrp)) - return; - - if (in_vif_index) - input_iface_vif_index = in_vif_index; - else - { - struct prefix src, grp; - - src.family = AF_INET; - src.prefixlen = IPV4_MAX_BITLEN; - src.u.prefix4 = vif_source; - grp.family = AF_INET; - grp.prefixlen = IPV4_MAX_BITLEN; - grp.u.prefix4 = c_oil->oil.mfcc_mcastgrp; - - if (PIM_DEBUG_ZEBRA) - { - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - zlog_debug ("%s: channel_oil (%s, %s) upstream info is not present.", - __PRETTY_FUNCTION__, source_str, group_str); - } - input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(vif_source, &src, &grp); - } - - if (input_iface_vif_index < 1) - { - if (PIM_DEBUG_ZEBRA) - { - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - zlog_debug("%s %s: could not find input interface(%d) for (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, c_oil->oil.mfcc_parent, - source_str, group_str); - } - pim_mroute_del (c_oil, __PRETTY_FUNCTION__); - return; - } - - if (input_iface_vif_index == c_oil->oil.mfcc_parent) - { - if (!c_oil->installed) - pim_mroute_add (c_oil, __PRETTY_FUNCTION__); - - /* RPF unchanged */ - return; - } - - if (PIM_DEBUG_ZEBRA) - { - struct interface *old_iif = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); - struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index); - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - zlog_debug("%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str, - old_iif->name, c_oil->oil.mfcc_parent, - new_iif->name, input_iface_vif_index); - } - - /* new iif loops to existing oif ? */ - if (c_oil->oil.mfcc_ttls[input_iface_vif_index]) - { - struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index); - - if (PIM_DEBUG_ZEBRA) { - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - zlog_debug("%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str, - new_iif->name, input_iface_vif_index); - } - } - - /* update iif vif_index */ - old_vif_index = c_oil->oil.mfcc_parent; - c_oil->oil.mfcc_parent = input_iface_vif_index; - - /* update kernel multicast forwarding cache (MFC) */ - if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) - { - if (PIM_DEBUG_MROUTE) - { - /* just log warning */ - struct interface *old_iif = pim_if_find_by_vif_index(old_vif_index); - struct interface *new_iif = pim_if_find_by_vif_index(input_iface_vif_index); - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - zlog_debug("%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str, - old_iif ? old_iif->name : "", c_oil->oil.mfcc_parent, - new_iif ? new_iif->name : "", input_iface_vif_index); - } - } + struct in_addr vif_source; + int input_iface_vif_index; + int old_vif_index; + + if (!pim_rp_set_upstream_addr(&vif_source, c_oil->oil.mfcc_origin, + c_oil->oil.mfcc_mcastgrp)) + return; + + if (in_vif_index) + input_iface_vif_index = in_vif_index; + else { + struct prefix src, grp; + + src.family = AF_INET; + src.prefixlen = IPV4_MAX_BITLEN; + src.u.prefix4 = vif_source; + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = c_oil->oil.mfcc_mcastgrp; + + if (PIM_DEBUG_ZEBRA) { + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", c_oil->oil.mfcc_origin, + source_str, sizeof(source_str)); + pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + zlog_debug( + "%s: channel_oil (%s, %s) upstream info is not present.", + __PRETTY_FUNCTION__, source_str, group_str); + } + input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index( + vif_source, &src, &grp); + } + + if (input_iface_vif_index < 1) { + if (PIM_DEBUG_ZEBRA) { + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", c_oil->oil.mfcc_origin, + source_str, sizeof(source_str)); + pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + zlog_debug( + "%s %s: could not find input interface(%d) for (S,G)=(%s,%s)", + __FILE__, __PRETTY_FUNCTION__, + c_oil->oil.mfcc_parent, source_str, group_str); + } + pim_mroute_del(c_oil, __PRETTY_FUNCTION__); + return; + } + + if (input_iface_vif_index == c_oil->oil.mfcc_parent) { + if (!c_oil->installed) + pim_mroute_add(c_oil, __PRETTY_FUNCTION__); + + /* RPF unchanged */ + return; + } + + if (PIM_DEBUG_ZEBRA) { + struct interface *old_iif = + pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); + struct interface *new_iif = + pim_if_find_by_vif_index(input_iface_vif_index); + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", c_oil->oil.mfcc_origin, source_str, + sizeof(source_str)); + pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, group_str, + sizeof(group_str)); + zlog_debug( + "%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d", + __FILE__, __PRETTY_FUNCTION__, source_str, group_str, + old_iif->name, c_oil->oil.mfcc_parent, new_iif->name, + input_iface_vif_index); + } + + /* new iif loops to existing oif ? */ + if (c_oil->oil.mfcc_ttls[input_iface_vif_index]) { + struct interface *new_iif = + pim_if_find_by_vif_index(input_iface_vif_index); + + if (PIM_DEBUG_ZEBRA) { + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", c_oil->oil.mfcc_origin, + source_str, sizeof(source_str)); + pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + zlog_debug( + "%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d", + __FILE__, __PRETTY_FUNCTION__, source_str, + group_str, new_iif->name, + input_iface_vif_index); + } + } + + /* update iif vif_index */ + old_vif_index = c_oil->oil.mfcc_parent; + c_oil->oil.mfcc_parent = input_iface_vif_index; + + /* update kernel multicast forwarding cache (MFC) */ + if (pim_mroute_add(c_oil, __PRETTY_FUNCTION__)) { + if (PIM_DEBUG_MROUTE) { + /* just log warning */ + struct interface *old_iif = + pim_if_find_by_vif_index(old_vif_index); + struct interface *new_iif = + pim_if_find_by_vif_index(input_iface_vif_index); + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", c_oil->oil.mfcc_origin, + source_str, sizeof(source_str)); + pim_inet4_dump("", c_oil->oil.mfcc_mcastgrp, + group_str, sizeof(group_str)); + zlog_debug( + "%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d", + __FILE__, __PRETTY_FUNCTION__, source_str, + group_str, + old_iif ? old_iif->name : "", + c_oil->oil.mfcc_parent, + new_iif ? new_iif->name : "", + input_iface_vif_index); + } + } } void pim_scan_oil() { - struct listnode *node; - struct listnode *nextnode; - struct channel_oil *c_oil; - ifindex_t ifindex; - int vif_index = 0; - - qpim_scan_oil_last = pim_time_monotonic_sec(); - ++qpim_scan_oil_events; - - for (ALL_LIST_ELEMENTS(pim_channel_oil_list, node, nextnode, c_oil)) - { - if (c_oil->up && c_oil->up->rpf.source_nexthop.interface) - { - ifindex = c_oil->up->rpf.source_nexthop.interface->ifindex; - vif_index = pim_if_find_vifindex_by_ifindex (ifindex); - /* Pass Current selected NH vif index to mroute download */ - if (vif_index) - pim_scan_individual_oil (c_oil, vif_index); - } - else - pim_scan_individual_oil (c_oil, 0); - } + struct listnode *node; + struct listnode *nextnode; + struct channel_oil *c_oil; + ifindex_t ifindex; + int vif_index = 0; + + qpim_scan_oil_last = pim_time_monotonic_sec(); + ++qpim_scan_oil_events; + + for (ALL_LIST_ELEMENTS(pim_channel_oil_list, node, nextnode, c_oil)) { + if (c_oil->up && c_oil->up->rpf.source_nexthop.interface) { + ifindex = c_oil->up->rpf.source_nexthop + .interface->ifindex; + vif_index = pim_if_find_vifindex_by_ifindex(ifindex); + /* Pass Current selected NH vif index to mroute download + */ + if (vif_index) + pim_scan_individual_oil(c_oil, vif_index); + } else + pim_scan_individual_oil(c_oil, 0); + } } static int on_rpf_cache_refresh(struct thread *t) { - /* update PIM protocol state */ - scan_upstream_rpf_cache(); + /* update PIM protocol state */ + scan_upstream_rpf_cache(); - /* update kernel multicast forwarding cache (MFC) */ - pim_scan_oil(); + /* update kernel multicast forwarding cache (MFC) */ + pim_scan_oil(); - qpim_rpf_cache_refresh_last = pim_time_monotonic_sec(); - ++qpim_rpf_cache_refresh_events; + qpim_rpf_cache_refresh_last = pim_time_monotonic_sec(); + ++qpim_rpf_cache_refresh_events; - //It is called as part of pim_neighbor_add - //pim_rp_setup (); - return 0; + // It is called as part of pim_neighbor_add + // pim_rp_setup (); + return 0; } void sched_rpf_cache_refresh(void) { - ++qpim_rpf_cache_refresh_requests; + ++qpim_rpf_cache_refresh_requests; - pim_rpf_set_refresh_time (); + pim_rpf_set_refresh_time(); - if (qpim_rpf_cache_refresher) { - /* Refresh timer is already running */ - return; - } + if (qpim_rpf_cache_refresher) { + /* Refresh timer is already running */ + return; + } - /* Start refresh timer */ + /* Start refresh timer */ - if (PIM_DEBUG_ZEBRA) { - zlog_debug("%s: triggering %ld msec timer", - __PRETTY_FUNCTION__, - qpim_rpf_cache_refresh_delay_msec); - } + if (PIM_DEBUG_ZEBRA) { + zlog_debug("%s: triggering %ld msec timer", __PRETTY_FUNCTION__, + qpim_rpf_cache_refresh_delay_msec); + } - thread_add_timer_msec(master, on_rpf_cache_refresh, 0, - qpim_rpf_cache_refresh_delay_msec, - &qpim_rpf_cache_refresher); + thread_add_timer_msec(master, on_rpf_cache_refresh, 0, + qpim_rpf_cache_refresh_delay_msec, + &qpim_rpf_cache_refresher); } -static void -pim_zebra_connected (struct zclient *zclient) +static void pim_zebra_connected(struct zclient *zclient) { - /* Send the client registration */ - bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); + /* Send the client registration */ + bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); - zclient_send_reg_requests (zclient, VRF_DEFAULT); + zclient_send_reg_requests(zclient, VRF_DEFAULT); } void pim_zebra_init(void) { - int i; + int i; #ifdef HAVE_TCP_ZEBRA - zlog_notice("zclient update contacting ZEBRA daemon at socket TCP %s,%d", "127.0.0.1", ZEBRA_PORT); + zlog_notice( + "zclient update contacting ZEBRA daemon at socket TCP %s,%d", + "127.0.0.1", ZEBRA_PORT); #else - zlog_notice("zclient update contacting ZEBRA daemon at socket UNIX %s", zclient_serv_path_get()); + zlog_notice("zclient update contacting ZEBRA daemon at socket UNIX %s", + zclient_serv_path_get()); #endif - /* Socket for receiving updates from Zebra daemon */ - zclient = zclient_new (master); - - zclient->zebra_connected = pim_zebra_connected; - zclient->router_id_update = pim_router_id_update_zebra; - zclient->interface_add = pim_zebra_if_add; - zclient->interface_delete = pim_zebra_if_del; - zclient->interface_up = pim_zebra_if_state_up; - zclient->interface_down = pim_zebra_if_state_down; - zclient->interface_address_add = pim_zebra_if_address_add; - zclient->interface_address_delete = pim_zebra_if_address_del; - zclient->nexthop_update = pim_parse_nexthop_update; - - zclient_init(zclient, ZEBRA_ROUTE_PIM, 0); - if (PIM_DEBUG_PIM_TRACE) { - zlog_info("zclient_init cleared redistribution request"); - } - - zassert(zclient->redist_default == ZEBRA_ROUTE_PIM); - - /* Request all redistribution */ - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { - if (i == zclient->redist_default) - continue; - vrf_bitmap_set (zclient->redist[AFI_IP][i], VRF_DEFAULT);; - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: requesting redistribution for %s (%i)", - __PRETTY_FUNCTION__, zebra_route_string(i), i); - } - } - - /* Request default information */ - zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_ADD, - zclient, VRF_DEFAULT); - - if (PIM_DEBUG_PIM_TRACE) { - zlog_info("%s: requesting default information redistribution", - __PRETTY_FUNCTION__); - - zlog_notice("%s: zclient update socket initialized", - __PRETTY_FUNCTION__); - } - - zclient_lookup_new(); + /* Socket for receiving updates from Zebra daemon */ + zclient = zclient_new(master); + + zclient->zebra_connected = pim_zebra_connected; + zclient->router_id_update = pim_router_id_update_zebra; + zclient->interface_add = pim_zebra_if_add; + zclient->interface_delete = pim_zebra_if_del; + zclient->interface_up = pim_zebra_if_state_up; + zclient->interface_down = pim_zebra_if_state_down; + zclient->interface_address_add = pim_zebra_if_address_add; + zclient->interface_address_delete = pim_zebra_if_address_del; + zclient->nexthop_update = pim_parse_nexthop_update; + + zclient_init(zclient, ZEBRA_ROUTE_PIM, 0); + if (PIM_DEBUG_PIM_TRACE) { + zlog_info("zclient_init cleared redistribution request"); + } + + zassert(zclient->redist_default == ZEBRA_ROUTE_PIM); + + /* Request all redistribution */ + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (i == zclient->redist_default) + continue; + vrf_bitmap_set(zclient->redist[AFI_IP][i], VRF_DEFAULT); + ; + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: requesting redistribution for %s (%i)", + __PRETTY_FUNCTION__, zebra_route_string(i), + i); + } + } + + /* Request default information */ + zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, + VRF_DEFAULT); + + if (PIM_DEBUG_PIM_TRACE) { + zlog_info("%s: requesting default information redistribution", + __PRETTY_FUNCTION__); + + zlog_notice("%s: zclient update socket initialized", + __PRETTY_FUNCTION__); + } + + zclient_lookup_new(); } void igmp_anysource_forward_start(struct igmp_group *group) { - struct igmp_source *source; - struct in_addr src_addr = { .s_addr = 0 }; - /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ - zassert(group->group_filtermode_isexcl); - zassert(listcount(group->group_source_list) < 1); - - source = source_new (group, src_addr); - if (!source) - { - zlog_warn ("%s: Failure to create * source", __PRETTY_FUNCTION__); - return; - } - - igmp_source_forward_start (source); + struct igmp_source *source; + struct in_addr src_addr = {.s_addr = 0}; + /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ + zassert(group->group_filtermode_isexcl); + zassert(listcount(group->group_source_list) < 1); + + source = source_new(group, src_addr); + if (!source) { + zlog_warn("%s: Failure to create * source", + __PRETTY_FUNCTION__); + return; + } + + igmp_source_forward_start(source); } void igmp_anysource_forward_stop(struct igmp_group *group) { - struct igmp_source *source; - struct in_addr star = { .s_addr = 0 }; + struct igmp_source *source; + struct in_addr star = {.s_addr = 0}; - source = igmp_find_source_by_addr (group, star); - if (source) - igmp_source_forward_stop (source); + source = igmp_find_source_by_addr(group, star); + if (source) + igmp_source_forward_stop(source); } -static void -igmp_source_forward_reevaluate_one(struct igmp_source *source) +static void igmp_source_forward_reevaluate_one(struct igmp_source *source) { - struct prefix_sg sg; - struct igmp_group *group = source->source_group; - struct pim_ifchannel *ch; - - if ((source->source_addr.s_addr != INADDR_ANY) || - !IGMP_SOURCE_TEST_FORWARDING (source->source_flags)) - return; - - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = source->source_addr; - sg.grp = group->group_addr; - - ch = pim_ifchannel_find (group->group_igmp_sock->interface, &sg); - if (pim_is_grp_ssm (group->group_addr)) - { - /* If SSM group withdraw local membership */ - if (ch && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE)) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_debug ("local membership del for %s as G is now SSM", - pim_str_sg_dump (&sg)); - pim_ifchannel_local_membership_del (group->group_igmp_sock->interface, &sg); - } - } - else - { - /* If ASM group add local membership */ - if (!ch || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO)) - { - if (PIM_DEBUG_PIM_EVENTS) - zlog_debug ("local membership add for %s as G is now ASM", - pim_str_sg_dump (&sg)); - pim_ifchannel_local_membership_add (group->group_igmp_sock->interface, &sg); - } - } + struct prefix_sg sg; + struct igmp_group *group = source->source_group; + struct pim_ifchannel *ch; + + if ((source->source_addr.s_addr != INADDR_ANY) + || !IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) + return; + + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = source->source_addr; + sg.grp = group->group_addr; + + ch = pim_ifchannel_find(group->group_igmp_sock->interface, &sg); + if (pim_is_grp_ssm(group->group_addr)) { + /* If SSM group withdraw local membership */ + if (ch + && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE)) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug( + "local membership del for %s as G is now SSM", + pim_str_sg_dump(&sg)); + pim_ifchannel_local_membership_del( + group->group_igmp_sock->interface, &sg); + } + } else { + /* If ASM group add local membership */ + if (!ch + || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO)) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug( + "local membership add for %s as G is now ASM", + pim_str_sg_dump(&sg)); + pim_ifchannel_local_membership_add( + group->group_igmp_sock->interface, &sg); + } + } } -void -igmp_source_forward_reevaluate_all(void) +void igmp_source_forward_reevaluate_all(void) { - struct listnode *ifnode; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) - { - struct pim_interface *pim_ifp = ifp->info; - struct listnode *sock_node; - struct igmp_sock *igmp; - - if (!pim_ifp) - continue; - - /* scan igmp sockets */ - for (ALL_LIST_ELEMENTS_RO (pim_ifp->igmp_socket_list, sock_node, igmp)) - { - struct listnode *grpnode; - struct igmp_group *grp; - - /* scan igmp groups */ - for (ALL_LIST_ELEMENTS_RO (igmp->igmp_group_list, grpnode, grp)) - { - struct listnode *srcnode; - struct igmp_source *src; - - /* scan group sources */ - for (ALL_LIST_ELEMENTS_RO (grp->group_source_list, - srcnode, src)) - { - igmp_source_forward_reevaluate_one (src); - } /* scan group sources */ - } /* scan igmp groups */ - } /* scan igmp sockets */ - } /* scan interfaces */ + struct listnode *ifnode; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), ifnode, ifp)) { + struct pim_interface *pim_ifp = ifp->info; + struct listnode *sock_node; + struct igmp_sock *igmp; + + if (!pim_ifp) + continue; + + /* scan igmp sockets */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, + igmp)) { + struct listnode *grpnode; + struct igmp_group *grp; + + /* scan igmp groups */ + for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, + grpnode, grp)) { + struct listnode *srcnode; + struct igmp_source *src; + + /* scan group sources */ + for (ALL_LIST_ELEMENTS_RO( + grp->group_source_list, srcnode, + src)) { + igmp_source_forward_reevaluate_one(src); + } /* scan group sources */ + } /* scan igmp groups */ + } /* scan igmp sockets */ + } /* scan interfaces */ } void igmp_source_forward_start(struct igmp_source *source) { - struct igmp_group *group; - struct prefix_sg sg; - int result; - int input_iface_vif_index = 0; - - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = source->source_addr; - sg.grp = source->source_group->group_addr; - - if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug("%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), - source->source_group->group_igmp_sock->fd, - source->source_group->group_igmp_sock->interface->name, - IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); - } - - /* Prevent IGMP interface from installing multicast route multiple - times */ - if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { - return; - } - - group = source->source_group; - - if (!source->source_channel_oil) { - struct in_addr vif_source; - struct pim_interface *pim_oif; - struct prefix nht_p, src, grp; - int ret = 0; - struct pim_nexthop_cache out_pnc; - struct pim_nexthop nexthop; - struct pim_upstream *up = NULL; - - if (!pim_rp_set_upstream_addr (&vif_source, source->source_addr, sg.grp)) - return; - - /* Register addr with Zebra NHT */ - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = vif_source; - memset (&out_pnc, 0, sizeof (struct pim_nexthop_cache)); - - src.family = AF_INET; - src.prefixlen = IPV4_MAX_BITLEN; - src.u.prefix4 = vif_source; //RP or Src address - grp.family = AF_INET; - grp.prefixlen = IPV4_MAX_BITLEN; - grp.u.prefix4 = sg.grp; - - if ((ret = pim_find_or_track_nexthop (&nht_p, NULL, NULL, &out_pnc)) == 1) - { - if (out_pnc.nexthop_num) - { - up = pim_upstream_find (&sg); - memset (&nexthop, 0, sizeof (struct pim_nexthop)); - if (up) - memcpy (&nexthop, &up->rpf.source_nexthop, sizeof (struct pim_nexthop)); - //Compute PIM RPF using Cached nexthop - pim_ecmp_nexthop_search (&out_pnc, &nexthop, &src, &grp, 0); - if (nexthop.interface) - input_iface_vif_index = pim_if_find_vifindex_by_ifindex (nexthop.interface->ifindex); - } - else - { - if (PIM_DEBUG_ZEBRA) - { - char buf1[INET_ADDRSTRLEN]; - char buf2[INET_ADDRSTRLEN]; - pim_inet4_dump("", nht_p.u.prefix4, buf1, sizeof(buf1)); - pim_inet4_dump("", grp.u.prefix4, buf2, sizeof(buf2)); - zlog_debug ("%s: NHT Nexthop not found for addr %s grp %s" , - __PRETTY_FUNCTION__, buf1, buf2); - } - } - } - else - input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(vif_source, &src, &grp); - - if (PIM_DEBUG_ZEBRA) - { - char buf2[INET_ADDRSTRLEN]; - pim_inet4_dump("", vif_source, buf2, sizeof(buf2)); - zlog_debug ("%s: NHT %s vif_source %s vif_index:%d ", __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), buf2, input_iface_vif_index); - } - - if (input_iface_vif_index < 1) { - if (PIM_DEBUG_IGMP_TRACE) - { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", source->source_addr, source_str, sizeof(source_str)); - zlog_debug("%s %s: could not find input interface for source %s", - __FILE__, __PRETTY_FUNCTION__, - source_str); + struct igmp_group *group; + struct prefix_sg sg; + int result; + int input_iface_vif_index = 0; + + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = source->source_addr; + sg.grp = source->source_group->group_addr; + + if (PIM_DEBUG_IGMP_TRACE) { + zlog_debug( + "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), + source->source_group->group_igmp_sock->fd, + source->source_group->group_igmp_sock->interface->name, + IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); + } + + /* Prevent IGMP interface from installing multicast route multiple + times */ + if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { + return; } - return; - } - - /* - Protect IGMP against adding looped MFC entries created by both - source and receiver attached to the same interface. See TODO - T22. - */ - pim_oif = source->source_group->group_igmp_sock->interface->info; - if (!pim_oif) { - if (PIM_DEBUG_IGMP_TRACE) - { - zlog_debug("%s: multicast not enabled on oif=%s ?", - __PRETTY_FUNCTION__, - source->source_group->group_igmp_sock->interface->name); + + group = source->source_group; + + if (!source->source_channel_oil) { + struct in_addr vif_source; + struct pim_interface *pim_oif; + struct prefix nht_p, src, grp; + int ret = 0; + struct pim_nexthop_cache out_pnc; + struct pim_nexthop nexthop; + struct pim_upstream *up = NULL; + + if (!pim_rp_set_upstream_addr(&vif_source, source->source_addr, + sg.grp)) + return; + + /* Register addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = vif_source; + memset(&out_pnc, 0, sizeof(struct pim_nexthop_cache)); + + src.family = AF_INET; + src.prefixlen = IPV4_MAX_BITLEN; + src.u.prefix4 = vif_source; // RP or Src address + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = sg.grp; + + if ((ret = pim_find_or_track_nexthop(&nht_p, NULL, NULL, + &out_pnc)) + == 1) { + if (out_pnc.nexthop_num) { + up = pim_upstream_find(&sg); + memset(&nexthop, 0, sizeof(struct pim_nexthop)); + if (up) + memcpy(&nexthop, + &up->rpf.source_nexthop, + sizeof(struct pim_nexthop)); + // Compute PIM RPF using Cached nexthop + pim_ecmp_nexthop_search(&out_pnc, &nexthop, + &src, &grp, 0); + if (nexthop.interface) + input_iface_vif_index = + pim_if_find_vifindex_by_ifindex( + nexthop.interface->ifindex); + } else { + if (PIM_DEBUG_ZEBRA) { + char buf1[INET_ADDRSTRLEN]; + char buf2[INET_ADDRSTRLEN]; + pim_inet4_dump("", + nht_p.u.prefix4, buf1, + sizeof(buf1)); + pim_inet4_dump("", + grp.u.prefix4, buf2, + sizeof(buf2)); + zlog_debug( + "%s: NHT Nexthop not found for addr %s grp %s", + __PRETTY_FUNCTION__, buf1, + buf2); + } + } + } else + input_iface_vif_index = + pim_ecmp_fib_lookup_if_vif_index(vif_source, + &src, &grp); + + if (PIM_DEBUG_ZEBRA) { + char buf2[INET_ADDRSTRLEN]; + pim_inet4_dump("", vif_source, buf2, + sizeof(buf2)); + zlog_debug("%s: NHT %s vif_source %s vif_index:%d ", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), + buf2, input_iface_vif_index); + } + + if (input_iface_vif_index < 1) { + if (PIM_DEBUG_IGMP_TRACE) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", source->source_addr, + source_str, sizeof(source_str)); + zlog_debug( + "%s %s: could not find input interface for source %s", + __FILE__, __PRETTY_FUNCTION__, + source_str); + } + return; + } + + /* + Protect IGMP against adding looped MFC entries created by both + source and receiver attached to the same interface. See TODO + T22. + */ + pim_oif = + source->source_group->group_igmp_sock->interface->info; + if (!pim_oif) { + if (PIM_DEBUG_IGMP_TRACE) { + zlog_debug( + "%s: multicast not enabled on oif=%s ?", + __PRETTY_FUNCTION__, + source->source_group->group_igmp_sock + ->interface->name); + } + return; + } + + if (input_iface_vif_index == pim_oif->mroute_vif_index) { + /* ignore request for looped MFC entry */ + if (PIM_DEBUG_IGMP_TRACE) { + zlog_debug( + "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d", + __PRETTY_FUNCTION__, + pim_str_sg_dump(&sg), + source->source_group->group_igmp_sock + ->fd, + source->source_group->group_igmp_sock + ->interface->name, + input_iface_vif_index); + } + return; + } + + source->source_channel_oil = + pim_channel_oil_add(&sg, input_iface_vif_index); + if (!source->source_channel_oil) { + if (PIM_DEBUG_IGMP_TRACE) { + zlog_debug( + "%s %s: could not create OIL for channel (S,G)=%s", + __FILE__, __PRETTY_FUNCTION__, + pim_str_sg_dump(&sg)); + } + return; + } } - return; - } - - if (input_iface_vif_index == pim_oif->mroute_vif_index) { - /* ignore request for looped MFC entry */ - if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug("%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), - source->source_group->group_igmp_sock->fd, - source->source_group->group_igmp_sock->interface->name, - input_iface_vif_index); - } - return; - } - - source->source_channel_oil = pim_channel_oil_add(&sg, - input_iface_vif_index); - if (!source->source_channel_oil) { - if (PIM_DEBUG_IGMP_TRACE) - { - zlog_debug("%s %s: could not create OIL for channel (S,G)=%s", - __FILE__, __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg)); + + result = pim_channel_add_oif(source->source_channel_oil, + group->group_igmp_sock->interface, + PIM_OIF_FLAG_PROTO_IGMP); + if (result) { + if (PIM_DEBUG_MROUTE) { + zlog_warn("%s: add_oif() failed with return=%d", + __func__, result); + } + return; } - return; - } - } - - result = pim_channel_add_oif(source->source_channel_oil, - group->group_igmp_sock->interface, - PIM_OIF_FLAG_PROTO_IGMP); - if (result) { - if (PIM_DEBUG_MROUTE) - { - zlog_warn("%s: add_oif() failed with return=%d", - __func__, result); - } - return; - } - - /* - Feed IGMPv3-gathered local membership information into PIM - per-interface (S,G) state. - */ - if (!pim_ifchannel_local_membership_add(group->group_igmp_sock->interface, &sg)) - { - if (PIM_DEBUG_MROUTE) - zlog_warn ("%s: Failure to add local membership for %s", - __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); - return; - } - - IGMP_SOURCE_DO_FORWARDING(source->source_flags); + + /* + Feed IGMPv3-gathered local membership information into PIM + per-interface (S,G) state. + */ + if (!pim_ifchannel_local_membership_add( + group->group_igmp_sock->interface, &sg)) { + if (PIM_DEBUG_MROUTE) + zlog_warn("%s: Failure to add local membership for %s", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg)); + return; + } + + IGMP_SOURCE_DO_FORWARDING(source->source_flags); } /* @@ -966,203 +1010,219 @@ void igmp_source_forward_start(struct igmp_source *source) */ void igmp_source_forward_stop(struct igmp_source *source) { - struct igmp_group *group; - struct prefix_sg sg; - int result; - - memset (&sg, 0, sizeof (struct prefix_sg)); - sg.src = source->source_addr; - sg.grp = source->source_group->group_addr; - - if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug("%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg), - source->source_group->group_igmp_sock->fd, - source->source_group->group_igmp_sock->interface->name, - IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); - } - - /* Prevent IGMP interface from removing multicast route multiple - times */ - if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { - return; - } - - group = source->source_group; - - /* - It appears that in certain circumstances that - igmp_source_forward_stop is called when IGMP forwarding - was not enabled in oif_flags for this outgoing interface. - Possibly because of multiple calls. When that happens, we - enter the below if statement and this function returns early - which in turn triggers the calling function to assert. - Making the call to pim_channel_del_oif and ignoring the return code - fixes the issue without ill effect, similar to - pim_forward_stop below. - */ - result = pim_channel_del_oif(source->source_channel_oil, - group->group_igmp_sock->interface, - PIM_OIF_FLAG_PROTO_IGMP); - if (result) { - if (PIM_DEBUG_IGMP_TRACE) - zlog_debug("%s: pim_channel_del_oif() failed with return=%d", - __func__, result); - return; - } - - /* - Feed IGMPv3-gathered local membership information into PIM - per-interface (S,G) state. - */ - pim_ifchannel_local_membership_del(group->group_igmp_sock->interface, - &sg); - - IGMP_SOURCE_DONT_FORWARDING(source->source_flags); + struct igmp_group *group; + struct prefix_sg sg; + int result; + + memset(&sg, 0, sizeof(struct prefix_sg)); + sg.src = source->source_addr; + sg.grp = source->source_group->group_addr; + + if (PIM_DEBUG_IGMP_TRACE) { + zlog_debug( + "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), + source->source_group->group_igmp_sock->fd, + source->source_group->group_igmp_sock->interface->name, + IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); + } + + /* Prevent IGMP interface from removing multicast route multiple + times */ + if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { + return; + } + + group = source->source_group; + + /* + It appears that in certain circumstances that + igmp_source_forward_stop is called when IGMP forwarding + was not enabled in oif_flags for this outgoing interface. + Possibly because of multiple calls. When that happens, we + enter the below if statement and this function returns early + which in turn triggers the calling function to assert. + Making the call to pim_channel_del_oif and ignoring the return code + fixes the issue without ill effect, similar to + pim_forward_stop below. + */ + result = pim_channel_del_oif(source->source_channel_oil, + group->group_igmp_sock->interface, + PIM_OIF_FLAG_PROTO_IGMP); + if (result) { + if (PIM_DEBUG_IGMP_TRACE) + zlog_debug( + "%s: pim_channel_del_oif() failed with return=%d", + __func__, result); + return; + } + + /* + Feed IGMPv3-gathered local membership information into PIM + per-interface (S,G) state. + */ + pim_ifchannel_local_membership_del(group->group_igmp_sock->interface, + &sg); + + IGMP_SOURCE_DONT_FORWARDING(source->source_flags); } void pim_forward_start(struct pim_ifchannel *ch) { - struct pim_upstream *up = ch->upstream; - uint32_t mask = PIM_OIF_FLAG_PROTO_PIM; - int input_iface_vif_index = 0; - - if (PIM_DEBUG_PIM_TRACE) { - char source_str[INET_ADDRSTRLEN]; - char group_str[INET_ADDRSTRLEN]; - char upstream_str[INET_ADDRSTRLEN]; - - pim_inet4_dump("", ch->sg.src, source_str, sizeof(source_str)); - pim_inet4_dump("", ch->sg.grp, group_str, sizeof(group_str)); - pim_inet4_dump("", up->upstream_addr, upstream_str, sizeof(upstream_str)); - zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", - __PRETTY_FUNCTION__, - source_str, group_str, ch->interface->name, upstream_str); - } - - /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS, - as part of mroute_del called by pim_forward_stop. - */ - if (!up->channel_oil || - (up->channel_oil && up->channel_oil->oil.mfcc_parent >= MAXVIFS)) - { - struct prefix nht_p, src, grp; - int ret = 0; - struct pim_nexthop_cache out_pnc; - - /* Register addr with Zebra NHT */ - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; - grp.family = AF_INET; - grp.prefixlen = IPV4_MAX_BITLEN; - grp.u.prefix4 = up->sg.grp; - memset (&out_pnc, 0, sizeof (struct pim_nexthop_cache)); - - if ((ret = pim_find_or_track_nexthop (&nht_p, NULL, NULL, &out_pnc)) == 1) - { - if (out_pnc.nexthop_num) - { - src.family = AF_INET; - src.prefixlen = IPV4_MAX_BITLEN; - src.u.prefix4 = up->upstream_addr; //RP or Src address - grp.family = AF_INET; - grp.prefixlen = IPV4_MAX_BITLEN; - grp.u.prefix4 = up->sg.grp; - //Compute PIM RPF using Cached nexthop - if (pim_ecmp_nexthop_search (&out_pnc, &up->rpf.source_nexthop, &src, &grp, 0) == 0) - input_iface_vif_index = pim_if_find_vifindex_by_ifindex (up->rpf.source_nexthop.interface->ifindex); - else - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: Nexthop selection failed for %s ", __PRETTY_FUNCTION__, up->sg_str); - } - } - else - { - if (PIM_DEBUG_ZEBRA) - { - char buf1[INET_ADDRSTRLEN]; - char buf2[INET_ADDRSTRLEN]; - pim_inet4_dump("", nht_p.u.prefix4, buf1, sizeof(buf1)); - pim_inet4_dump("", grp.u.prefix4, buf2, sizeof(buf2)); - zlog_debug ("%s: NHT pnc is NULL for addr %s grp %s" , - __PRETTY_FUNCTION__, buf1, buf2); - } - } - } - else - input_iface_vif_index = pim_ecmp_fib_lookup_if_vif_index(up->upstream_addr, &src, &grp); - - if (input_iface_vif_index < 1) - { - if (PIM_DEBUG_PIM_TRACE) - { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", up->sg.src, source_str, sizeof(source_str)); - zlog_debug("%s %s: could not find input interface for source %s", - __FILE__, __PRETTY_FUNCTION__, - source_str); - } - return; - } - if (PIM_DEBUG_TRACE) - { - struct interface *in_intf = pim_if_find_by_vif_index (input_iface_vif_index); - zlog_debug ("%s: Update channel_oil IIF %s VIFI %d entry %s ", - __PRETTY_FUNCTION__, in_intf ? in_intf->name : "NIL", - input_iface_vif_index, up->sg_str); - } - up->channel_oil = pim_channel_oil_add (&up->sg, input_iface_vif_index); - if (!up->channel_oil) - { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug ("%s %s: could not create OIL for channel (S,G)=%s", - __FILE__, __PRETTY_FUNCTION__, up->sg_str); - return; - } - } - - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) - mask = PIM_OIF_FLAG_PROTO_IGMP; - - pim_channel_add_oif (up->channel_oil, ch->interface, mask); + struct pim_upstream *up = ch->upstream; + uint32_t mask = PIM_OIF_FLAG_PROTO_PIM; + int input_iface_vif_index = 0; + + if (PIM_DEBUG_PIM_TRACE) { + char source_str[INET_ADDRSTRLEN]; + char group_str[INET_ADDRSTRLEN]; + char upstream_str[INET_ADDRSTRLEN]; + + pim_inet4_dump("", ch->sg.src, source_str, + sizeof(source_str)); + pim_inet4_dump("", ch->sg.grp, group_str, + sizeof(group_str)); + pim_inet4_dump("", up->upstream_addr, upstream_str, + sizeof(upstream_str)); + zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__, + source_str, group_str, ch->interface->name, + upstream_str); + } + + /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS, + as part of mroute_del called by pim_forward_stop. + */ + if (!up->channel_oil + || (up->channel_oil + && up->channel_oil->oil.mfcc_parent >= MAXVIFS)) { + struct prefix nht_p, src, grp; + int ret = 0; + struct pim_nexthop_cache out_pnc; + + /* Register addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = up->sg.grp; + memset(&out_pnc, 0, sizeof(struct pim_nexthop_cache)); + + if ((ret = pim_find_or_track_nexthop(&nht_p, NULL, NULL, + &out_pnc)) + == 1) { + if (out_pnc.nexthop_num) { + src.family = AF_INET; + src.prefixlen = IPV4_MAX_BITLEN; + src.u.prefix4 = + up->upstream_addr; // RP or Src address + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = up->sg.grp; + // Compute PIM RPF using Cached nexthop + if (pim_ecmp_nexthop_search( + &out_pnc, &up->rpf.source_nexthop, + &src, &grp, 0) + == 0) + input_iface_vif_index = + pim_if_find_vifindex_by_ifindex( + up->rpf.source_nexthop + .interface->ifindex); + else { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: Nexthop selection failed for %s ", + __PRETTY_FUNCTION__, + up->sg_str); + } + } else { + if (PIM_DEBUG_ZEBRA) { + char buf1[INET_ADDRSTRLEN]; + char buf2[INET_ADDRSTRLEN]; + pim_inet4_dump("", + nht_p.u.prefix4, buf1, + sizeof(buf1)); + pim_inet4_dump("", + grp.u.prefix4, buf2, + sizeof(buf2)); + zlog_debug( + "%s: NHT pnc is NULL for addr %s grp %s", + __PRETTY_FUNCTION__, buf1, + buf2); + } + } + } else + input_iface_vif_index = + pim_ecmp_fib_lookup_if_vif_index( + up->upstream_addr, &src, &grp); + + if (input_iface_vif_index < 1) { + if (PIM_DEBUG_PIM_TRACE) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", up->sg.src, + source_str, sizeof(source_str)); + zlog_debug( + "%s %s: could not find input interface for source %s", + __FILE__, __PRETTY_FUNCTION__, + source_str); + } + return; + } + if (PIM_DEBUG_TRACE) { + struct interface *in_intf = + pim_if_find_by_vif_index(input_iface_vif_index); + zlog_debug( + "%s: Update channel_oil IIF %s VIFI %d entry %s ", + __PRETTY_FUNCTION__, + in_intf ? in_intf->name : "NIL", + input_iface_vif_index, up->sg_str); + } + up->channel_oil = + pim_channel_oil_add(&up->sg, input_iface_vif_index); + if (!up->channel_oil) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug( + "%s %s: could not create OIL for channel (S,G)=%s", + __FILE__, __PRETTY_FUNCTION__, + up->sg_str); + return; + } + } + + if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) + mask = PIM_OIF_FLAG_PROTO_IGMP; + + pim_channel_add_oif(up->channel_oil, ch->interface, mask); } void pim_forward_stop(struct pim_ifchannel *ch) { - struct pim_upstream *up = ch->upstream; + struct pim_upstream *up = ch->upstream; - if (PIM_DEBUG_PIM_TRACE) { - zlog_debug("%s: (S,G)=%s oif=%s", - __PRETTY_FUNCTION__, - ch->sg_str, ch->interface->name); - } + if (PIM_DEBUG_PIM_TRACE) { + zlog_debug("%s: (S,G)=%s oif=%s", __PRETTY_FUNCTION__, + ch->sg_str, ch->interface->name); + } - pim_channel_del_oif(up->channel_oil, - ch->interface, - PIM_OIF_FLAG_PROTO_PIM); + pim_channel_del_oif(up->channel_oil, ch->interface, + PIM_OIF_FLAG_PROTO_PIM); } -void -pim_zebra_zclient_update (struct vty *vty) +void pim_zebra_zclient_update(struct vty *vty) { - vty_out(vty, "Zclient update socket: "); - - if (zclient) { - vty_out (vty, "%d failures=%d\n", zclient->sock, - zclient->fail); - } - else { - vty_out (vty, "\n"); - } + vty_out(vty, "Zclient update socket: "); + + if (zclient) { + vty_out(vty, "%d failures=%d\n", zclient->sock, zclient->fail); + } else { + vty_out(vty, "\n"); + } } -struct zclient *pim_zebra_zclient_get (void) +struct zclient *pim_zebra_zclient_get(void) { - if (zclient) - return zclient; - else - return NULL; + if (zclient) + return zclient; + else + return NULL; } diff --git a/pimd/pim_zebra.h b/pimd/pim_zebra.h index 37024073e..9b5450d66 100644 --- a/pimd/pim_zebra.h +++ b/pimd/pim_zebra.h @@ -27,9 +27,9 @@ #include "pim_ifchannel.h" void pim_zebra_init(void); -void pim_zebra_zclient_update (struct vty *vty); +void pim_zebra_zclient_update(struct vty *vty); -void pim_scan_individual_oil (struct channel_oil *c_oil, int in_vif_index); +void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index); void pim_scan_oil(void); void igmp_anysource_forward_start(struct igmp_group *group); @@ -43,5 +43,5 @@ void pim_forward_start(struct pim_ifchannel *ch); void pim_forward_stop(struct pim_ifchannel *ch); void sched_rpf_cache_refresh(void); -struct zclient *pim_zebra_zclient_get (void); +struct zclient *pim_zebra_zclient_get(void); #endif /* PIM_ZEBRA_H */ diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index f405a39c9..027b18e12 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -43,491 +43,504 @@ static void zclient_lookup_sched(struct zclient *zlookup, int delay); /* Connect to zebra for nexthop lookup. */ static int zclient_lookup_connect(struct thread *t) { - struct zclient *zlookup; - - zlookup = THREAD_ARG(t); - - if (zlookup->sock >= 0) { - return 0; - } - - if (zclient_socket_connect(zlookup) < 0) { - ++zlookup->fail; - zlog_warn("%s: failure connecting zclient socket: failures=%d", - __PRETTY_FUNCTION__, zlookup->fail); - } - else { - zlookup->fail = 0; /* reset counter on connection */ - } - - if (zlookup->sock < 0) { - /* Since last connect failed, retry within 10 secs */ - zclient_lookup_sched(zlookup, 10); - return -1; - } - - return 0; + struct zclient *zlookup; + + zlookup = THREAD_ARG(t); + + if (zlookup->sock >= 0) { + return 0; + } + + if (zclient_socket_connect(zlookup) < 0) { + ++zlookup->fail; + zlog_warn("%s: failure connecting zclient socket: failures=%d", + __PRETTY_FUNCTION__, zlookup->fail); + } else { + zlookup->fail = 0; /* reset counter on connection */ + } + + if (zlookup->sock < 0) { + /* Since last connect failed, retry within 10 secs */ + zclient_lookup_sched(zlookup, 10); + return -1; + } + + return 0; } /* Schedule connection with delay. */ static void zclient_lookup_sched(struct zclient *zlookup, int delay) { - thread_add_timer(master, zclient_lookup_connect, zlookup, delay, - &zlookup->t_connect); + thread_add_timer(master, zclient_lookup_connect, zlookup, delay, + &zlookup->t_connect); - zlog_notice("%s: zclient lookup connection scheduled for %d seconds", - __PRETTY_FUNCTION__, delay); + zlog_notice("%s: zclient lookup connection scheduled for %d seconds", + __PRETTY_FUNCTION__, delay); } /* Schedule connection for now. */ static void zclient_lookup_sched_now(struct zclient *zlookup) { - thread_add_event(master, zclient_lookup_connect, zlookup, 0, - &zlookup->t_connect); + thread_add_event(master, zclient_lookup_connect, zlookup, 0, + &zlookup->t_connect); - zlog_notice("%s: zclient lookup immediate connection scheduled", - __PRETTY_FUNCTION__); + zlog_notice("%s: zclient lookup immediate connection scheduled", + __PRETTY_FUNCTION__); } /* Schedule reconnection, if needed. */ static void zclient_lookup_reconnect(struct zclient *zlookup) { - if (zlookup->t_connect) { - return; - } + if (zlookup->t_connect) { + return; + } - zclient_lookup_sched_now(zlookup); + zclient_lookup_sched_now(zlookup); } static void zclient_lookup_failed(struct zclient *zlookup) { - if (zlookup->sock >= 0) { - if (close(zlookup->sock)) { - zlog_warn("%s: closing fd=%d: errno=%d %s", __func__, zlookup->sock, - errno, safe_strerror(errno)); - } - zlookup->sock = -1; - } - - zclient_lookup_reconnect(zlookup); + if (zlookup->sock >= 0) { + if (close(zlookup->sock)) { + zlog_warn("%s: closing fd=%d: errno=%d %s", __func__, + zlookup->sock, errno, safe_strerror(errno)); + } + zlookup->sock = -1; + } + + zclient_lookup_reconnect(zlookup); } -void -zclient_lookup_free (void) +void zclient_lookup_free(void) { - zclient_stop (zlookup); - zclient_free (zlookup); - zlookup = NULL; + zclient_stop(zlookup); + zclient_free(zlookup); + zlookup = NULL; } -void -zclient_lookup_new (void) +void zclient_lookup_new(void) { - zlookup = zclient_new (master); - if (!zlookup) { - zlog_err("%s: zclient_new() failure", - __PRETTY_FUNCTION__); - return; - } - - zlookup->sock = -1; - zlookup->t_connect = NULL; + zlookup = zclient_new(master); + if (!zlookup) { + zlog_err("%s: zclient_new() failure", __PRETTY_FUNCTION__); + return; + } - zclient_lookup_sched_now(zlookup); + zlookup->sock = -1; + zlookup->t_connect = NULL; - zlog_notice("%s: zclient lookup socket initialized", - __PRETTY_FUNCTION__); + zclient_lookup_sched_now(zlookup); + zlog_notice("%s: zclient lookup socket initialized", + __PRETTY_FUNCTION__); } static int zclient_read_nexthop(struct zclient *zlookup, struct pim_zlookup_nexthop nexthop_tab[], - const int tab_size, - struct in_addr addr) + const int tab_size, struct in_addr addr) { - int num_ifindex = 0; - struct stream *s; - const uint16_t MIN_LEN = 10; /* getipv4=4 getc=1 getl=4 getc=1 */ - uint16_t length; - u_char marker; - u_char version; - vrf_id_t vrf_id; - uint16_t command = 0; - struct in_addr raddr; - uint8_t distance; - uint32_t metric; - int nexthop_num; - int i, err; - - if (PIM_DEBUG_PIM_TRACE_DETAIL) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s: addr=%s", - __PRETTY_FUNCTION__, - addr_str); - } - - s = zlookup->ibuf; - - while (command != ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB) - { - stream_reset(s); - err = zclient_read_header (s, zlookup->sock, &length, &marker, &version, - &vrf_id, &command); - if (err < 0) { - zlog_err("%s %s: zclient_read_header() failed", - __FILE__, __PRETTY_FUNCTION__); - zclient_lookup_failed(zlookup); - return -1; - } - - if (length < MIN_LEN) { - zlog_err("%s %s: failure reading zclient lookup socket: len=%d < MIN_LEN=%d", - __FILE__, __PRETTY_FUNCTION__, length, MIN_LEN); - zclient_lookup_failed(zlookup); - return -2; - } - } - - raddr.s_addr = stream_get_ipv4(s); - - if (raddr.s_addr != addr.s_addr) { - char addr_str[INET_ADDRSTRLEN]; - char raddr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - pim_inet4_dump("", raddr, raddr_str, sizeof(raddr_str)); - zlog_warn("%s: address mismatch: addr=%s raddr=%s", - __PRETTY_FUNCTION__, - addr_str, raddr_str); - /* warning only */ - } - - distance = stream_getc(s); - metric = stream_getl(s); - nexthop_num = stream_getc(s); - - if (nexthop_num < 1) { - zlog_err("%s: socket %d bad nexthop_num=%d", - __func__, zlookup->sock, nexthop_num); - return -6; - } - - for (i = 0; i < nexthop_num; ++i) { - enum nexthop_types_t nexthop_type; - struct pim_neighbor *nbr; - struct prefix p; - - nexthop_type = stream_getc(s); - if (num_ifindex >= tab_size) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_warn("%s %s: found too many nexthop ifindexes (%d > %d) for address %s", - __FILE__, __PRETTY_FUNCTION__, - (num_ifindex + 1), tab_size, addr_str); - return num_ifindex; - } - switch (nexthop_type) { - case NEXTHOP_TYPE_IFINDEX: - case NEXTHOP_TYPE_IPV4_IFINDEX: - case NEXTHOP_TYPE_IPV4: - nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; - if (nexthop_type == NEXTHOP_TYPE_IPV4_IFINDEX || - nexthop_type == NEXTHOP_TYPE_IPV4) { - nexthop_tab[num_ifindex].nexthop_addr.u.prefix4.s_addr = stream_get_ipv4(s); - } - else { - nexthop_tab[num_ifindex].nexthop_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY; - } - nexthop_tab[num_ifindex].ifindex = stream_getl(s); - nexthop_tab[num_ifindex].protocol_distance = distance; - nexthop_tab[num_ifindex].route_metric = metric; - ++num_ifindex; - break; - case NEXTHOP_TYPE_IPV6_IFINDEX: - nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET6; - stream_get (&nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, - s, - sizeof(struct in6_addr)); - nexthop_tab[num_ifindex].ifindex = stream_getl (s); - - p.family = AF_INET6; - p.prefixlen = IPV6_MAX_PREFIXLEN; - memcpy (&p.u.prefix6, - &nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, - sizeof(struct in6_addr)); - - /* - * If we are sending v6 secondary assume we receive v6 secondary - */ - if (pimg->send_v6_secondary) - nbr = pim_neighbor_find_by_secondary(if_lookup_by_index (nexthop_tab[num_ifindex].ifindex, VRF_DEFAULT), &p); - else - nbr = pim_neighbor_find_if (if_lookup_by_index (nexthop_tab[num_ifindex].ifindex, VRF_DEFAULT)); - if (nbr) - { - nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; - nexthop_tab[num_ifindex].nexthop_addr.u.prefix4 = nbr->source_addr; - } - ++num_ifindex; - break; - default: - /* do nothing */ - { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_warn("%s %s: found non-ifindex nexthop type=%d for address %s", - __FILE__, __PRETTY_FUNCTION__, - nexthop_type, addr_str); - } - break; - } - } - - return num_ifindex; + int num_ifindex = 0; + struct stream *s; + const uint16_t MIN_LEN = 10; /* getipv4=4 getc=1 getl=4 getc=1 */ + uint16_t length; + u_char marker; + u_char version; + vrf_id_t vrf_id; + uint16_t command = 0; + struct in_addr raddr; + uint8_t distance; + uint32_t metric; + int nexthop_num; + int i, err; + + if (PIM_DEBUG_PIM_TRACE_DETAIL) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_debug("%s: addr=%s", __PRETTY_FUNCTION__, addr_str); + } + + s = zlookup->ibuf; + + while (command != ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB) { + stream_reset(s); + err = zclient_read_header(s, zlookup->sock, &length, &marker, + &version, &vrf_id, &command); + if (err < 0) { + zlog_err("%s %s: zclient_read_header() failed", + __FILE__, __PRETTY_FUNCTION__); + zclient_lookup_failed(zlookup); + return -1; + } + + if (length < MIN_LEN) { + zlog_err( + "%s %s: failure reading zclient lookup socket: len=%d < MIN_LEN=%d", + __FILE__, __PRETTY_FUNCTION__, length, MIN_LEN); + zclient_lookup_failed(zlookup); + return -2; + } + } + + raddr.s_addr = stream_get_ipv4(s); + + if (raddr.s_addr != addr.s_addr) { + char addr_str[INET_ADDRSTRLEN]; + char raddr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + pim_inet4_dump("", raddr, raddr_str, sizeof(raddr_str)); + zlog_warn("%s: address mismatch: addr=%s raddr=%s", + __PRETTY_FUNCTION__, addr_str, raddr_str); + /* warning only */ + } + + distance = stream_getc(s); + metric = stream_getl(s); + nexthop_num = stream_getc(s); + + if (nexthop_num < 1) { + zlog_err("%s: socket %d bad nexthop_num=%d", __func__, + zlookup->sock, nexthop_num); + return -6; + } + + for (i = 0; i < nexthop_num; ++i) { + enum nexthop_types_t nexthop_type; + struct pim_neighbor *nbr; + struct prefix p; + + nexthop_type = stream_getc(s); + if (num_ifindex >= tab_size) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, + sizeof(addr_str)); + zlog_warn( + "%s %s: found too many nexthop ifindexes (%d > %d) for address %s", + __FILE__, __PRETTY_FUNCTION__, + (num_ifindex + 1), tab_size, addr_str); + return num_ifindex; + } + switch (nexthop_type) { + case NEXTHOP_TYPE_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4: + nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; + if (nexthop_type == NEXTHOP_TYPE_IPV4_IFINDEX + || nexthop_type == NEXTHOP_TYPE_IPV4) { + nexthop_tab[num_ifindex] + .nexthop_addr.u.prefix4.s_addr = + stream_get_ipv4(s); + } else { + nexthop_tab[num_ifindex] + .nexthop_addr.u.prefix4.s_addr = + PIM_NET_INADDR_ANY; + } + nexthop_tab[num_ifindex].ifindex = stream_getl(s); + nexthop_tab[num_ifindex].protocol_distance = distance; + nexthop_tab[num_ifindex].route_metric = metric; + ++num_ifindex; + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET6; + stream_get(&nexthop_tab[num_ifindex] + .nexthop_addr.u.prefix6, + s, sizeof(struct in6_addr)); + nexthop_tab[num_ifindex].ifindex = stream_getl(s); + + p.family = AF_INET6; + p.prefixlen = IPV6_MAX_PREFIXLEN; + memcpy(&p.u.prefix6, + &nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, + sizeof(struct in6_addr)); + + /* + * If we are sending v6 secondary assume we receive v6 + * secondary + */ + if (pimg->send_v6_secondary) + nbr = pim_neighbor_find_by_secondary( + if_lookup_by_index( + nexthop_tab[num_ifindex] + .ifindex, + VRF_DEFAULT), + &p); + else + nbr = pim_neighbor_find_if(if_lookup_by_index( + nexthop_tab[num_ifindex].ifindex, + VRF_DEFAULT)); + if (nbr) { + nexthop_tab[num_ifindex].nexthop_addr.family = + AF_INET; + nexthop_tab[num_ifindex] + .nexthop_addr.u.prefix4 = + nbr->source_addr; + } + ++num_ifindex; + break; + default: + /* do nothing */ + { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, + sizeof(addr_str)); + zlog_warn( + "%s %s: found non-ifindex nexthop type=%d for address %s", + __FILE__, __PRETTY_FUNCTION__, + nexthop_type, addr_str); + } + break; + } + } + + return num_ifindex; } -static int -zclient_lookup_nexthop_once (struct pim_zlookup_nexthop nexthop_tab[], - const int tab_size, - struct in_addr addr) +static int zclient_lookup_nexthop_once(struct pim_zlookup_nexthop nexthop_tab[], + const int tab_size, struct in_addr addr) { - struct stream *s; - int ret; - - if (PIM_DEBUG_PIM_TRACE_DETAIL) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s: addr=%s", - __PRETTY_FUNCTION__, - addr_str); - } - - /* Check socket. */ - if (zlookup->sock < 0) { - zlog_err("%s %s: zclient lookup socket is not connected", - __FILE__, __PRETTY_FUNCTION__); - zclient_lookup_failed(zlookup); - return -1; - } - - s = zlookup->obuf; - stream_reset(s); - zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, VRF_DEFAULT); - stream_put_in_addr(s, &addr); - stream_putw_at(s, 0, stream_get_endp(s)); - - ret = writen(zlookup->sock, s->data, stream_get_endp(s)); - if (ret < 0) { - zlog_err("%s %s: writen() failure: %d writing to zclient lookup socket", - __FILE__, __PRETTY_FUNCTION__, errno); - zclient_lookup_failed(zlookup); - return -2; - } - if (ret == 0) { - zlog_err("%s %s: connection closed on zclient lookup socket", - __FILE__, __PRETTY_FUNCTION__); - zclient_lookup_failed(zlookup); - return -3; - } - - return zclient_read_nexthop(zlookup, nexthop_tab, - tab_size, addr); + struct stream *s; + int ret; + + if (PIM_DEBUG_PIM_TRACE_DETAIL) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_debug("%s: addr=%s", __PRETTY_FUNCTION__, addr_str); + } + + /* Check socket. */ + if (zlookup->sock < 0) { + zlog_err("%s %s: zclient lookup socket is not connected", + __FILE__, __PRETTY_FUNCTION__); + zclient_lookup_failed(zlookup); + return -1; + } + + s = zlookup->obuf; + stream_reset(s); + zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, VRF_DEFAULT); + stream_put_in_addr(s, &addr); + stream_putw_at(s, 0, stream_get_endp(s)); + + ret = writen(zlookup->sock, s->data, stream_get_endp(s)); + if (ret < 0) { + zlog_err( + "%s %s: writen() failure: %d writing to zclient lookup socket", + __FILE__, __PRETTY_FUNCTION__, errno); + zclient_lookup_failed(zlookup); + return -2; + } + if (ret == 0) { + zlog_err("%s %s: connection closed on zclient lookup socket", + __FILE__, __PRETTY_FUNCTION__); + zclient_lookup_failed(zlookup); + return -3; + } + + return zclient_read_nexthop(zlookup, nexthop_tab, tab_size, addr); } -int -zclient_lookup_nexthop (struct pim_zlookup_nexthop nexthop_tab[], - const int tab_size, - struct in_addr addr, - int max_lookup) +int zclient_lookup_nexthop(struct pim_zlookup_nexthop nexthop_tab[], + const int tab_size, struct in_addr addr, + int max_lookup) { - int lookup; - uint32_t route_metric = 0xFFFFFFFF; - uint8_t protocol_distance = 0xFF; - - qpim_nexthop_lookups++; - - for (lookup = 0; lookup < max_lookup; ++lookup) { - int num_ifindex; - int first_ifindex; - struct prefix nexthop_addr; - - num_ifindex = zclient_lookup_nexthop_once(nexthop_tab, - tab_size, addr); - if (num_ifindex < 1) { - if (PIM_DEBUG_ZEBRA) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s %s: lookup=%d/%d: could not find nexthop ifindex for address %s", - __FILE__, __PRETTY_FUNCTION__, - lookup, max_lookup, addr_str); - } - return -1; - } - - if (lookup < 1) { - /* this is the non-recursive lookup - save original metric/distance */ - route_metric = nexthop_tab[0].route_metric; - protocol_distance = nexthop_tab[0].protocol_distance; - } - - /* - * FIXME: Non-recursive nexthop ensured only for first ifindex. - * However, recursive route lookup should really be fixed in zebra daemon. - * See also TODO T24. - * - * So Zebra for NEXTHOP_TYPE_IPV4 returns the ifindex now since - * it was being stored. This Doesn't solve all cases of - * recursive lookup but for the most common types it does. - */ - first_ifindex = nexthop_tab[0].ifindex; - nexthop_addr = nexthop_tab[0].nexthop_addr; - if (first_ifindex > 0) { - /* found: first ifindex is non-recursive nexthop */ - - if (lookup > 0) { - /* Report non-recursive success after first lookup */ + int lookup; + uint32_t route_metric = 0xFFFFFFFF; + uint8_t protocol_distance = 0xFF; + + qpim_nexthop_lookups++; + + for (lookup = 0; lookup < max_lookup; ++lookup) { + int num_ifindex; + int first_ifindex; + struct prefix nexthop_addr; + + num_ifindex = zclient_lookup_nexthop_once(nexthop_tab, tab_size, + addr); + if (num_ifindex < 1) { + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, + sizeof(addr_str)); + zlog_debug( + "%s %s: lookup=%d/%d: could not find nexthop ifindex for address %s", + __FILE__, __PRETTY_FUNCTION__, lookup, + max_lookup, addr_str); + } + return -1; + } + + if (lookup < 1) { + /* this is the non-recursive lookup - save original + * metric/distance */ + route_metric = nexthop_tab[0].route_metric; + protocol_distance = nexthop_tab[0].protocol_distance; + } + + /* + * FIXME: Non-recursive nexthop ensured only for first ifindex. + * However, recursive route lookup should really be fixed in + * zebra daemon. + * See also TODO T24. + * + * So Zebra for NEXTHOP_TYPE_IPV4 returns the ifindex now since + * it was being stored. This Doesn't solve all cases of + * recursive lookup but for the most common types it does. + */ + first_ifindex = nexthop_tab[0].ifindex; + nexthop_addr = nexthop_tab[0].nexthop_addr; + if (first_ifindex > 0) { + /* found: first ifindex is non-recursive nexthop */ + + if (lookup > 0) { + /* Report non-recursive success after first + * lookup */ + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, + addr_str, + sizeof(addr_str)); + zlog_debug( + "%s %s: lookup=%d/%d: found non-recursive ifindex=%d for address %s dist=%d met=%d", + __FILE__, __PRETTY_FUNCTION__, + lookup, max_lookup, + first_ifindex, addr_str, + nexthop_tab[0] + .protocol_distance, + nexthop_tab[0].route_metric); + } + + /* use last address as nexthop address */ + nexthop_tab[0].nexthop_addr.u.prefix4 = addr; + + /* report original route metric/distance */ + nexthop_tab[0].route_metric = route_metric; + nexthop_tab[0].protocol_distance = + protocol_distance; + } + + return num_ifindex; + } + + if (PIM_DEBUG_ZEBRA) { + char addr_str[INET_ADDRSTRLEN]; + char nexthop_str[PREFIX_STRLEN]; + pim_inet4_dump("", addr, addr_str, + sizeof(addr_str)); + pim_addr_dump("", &nexthop_addr, nexthop_str, + sizeof(nexthop_str)); + zlog_debug( + "%s %s: lookup=%d/%d: zebra returned recursive nexthop %s for address %s dist=%d met=%d", + __FILE__, __PRETTY_FUNCTION__, lookup, + max_lookup, nexthop_str, addr_str, + nexthop_tab[0].protocol_distance, + nexthop_tab[0].route_metric); + } + + addr = + nexthop_addr.u.prefix4; /* use nexthop addr for + recursive lookup */ + + } /* for (max_lookup) */ + if (PIM_DEBUG_ZEBRA) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_debug("%s %s: lookup=%d/%d: found non-recursive ifindex=%d for address %s dist=%d met=%d", - __FILE__, __PRETTY_FUNCTION__, - lookup, max_lookup, first_ifindex, addr_str, - nexthop_tab[0].protocol_distance, - nexthop_tab[0].route_metric); + char addr_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); + zlog_warn( + "%s %s: lookup=%d/%d: failure searching recursive nexthop ifindex for address %s", + __FILE__, __PRETTY_FUNCTION__, lookup, max_lookup, + addr_str); } - /* use last address as nexthop address */ - nexthop_tab[0].nexthop_addr.u.prefix4 = addr; - - /* report original route metric/distance */ - nexthop_tab[0].route_metric = route_metric; - nexthop_tab[0].protocol_distance = protocol_distance; - } - - return num_ifindex; - } - - if (PIM_DEBUG_ZEBRA) { - char addr_str[INET_ADDRSTRLEN]; - char nexthop_str[PREFIX_STRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - pim_addr_dump("", &nexthop_addr, nexthop_str, sizeof(nexthop_str)); - zlog_debug("%s %s: lookup=%d/%d: zebra returned recursive nexthop %s for address %s dist=%d met=%d", - __FILE__, __PRETTY_FUNCTION__, - lookup, max_lookup, nexthop_str, addr_str, - nexthop_tab[0].protocol_distance, - nexthop_tab[0].route_metric); - } - - addr = nexthop_addr.u.prefix4; /* use nexthop addr for recursive lookup */ - - } /* for (max_lookup) */ - - if (PIM_DEBUG_ZEBRA) { - char addr_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); - zlog_warn("%s %s: lookup=%d/%d: failure searching recursive nexthop ifindex for address %s", - __FILE__, __PRETTY_FUNCTION__, - lookup, max_lookup, addr_str); - } - - return -2; + return -2; } -void -pim_zlookup_show_ip_multicast (struct vty *vty) +void pim_zlookup_show_ip_multicast(struct vty *vty) { - vty_out(vty, "Zclient lookup socket: "); - if (zlookup) { - vty_out (vty, "%d failures=%d\n", zlookup->sock, - zlookup->fail); - } - else { - vty_out (vty, "\n"); - } + vty_out(vty, "Zclient lookup socket: "); + if (zlookup) { + vty_out(vty, "%d failures=%d\n", zlookup->sock, zlookup->fail); + } else { + vty_out(vty, "\n"); + } } -int -pim_zlookup_sg_statistics (struct channel_oil *c_oil) +int pim_zlookup_sg_statistics(struct channel_oil *c_oil) { - struct stream *s = zlookup->obuf; - uint16_t command = 0; - unsigned long long lastused; - struct prefix_sg sg; - int count = 0; - int ret; - struct interface *ifp = pim_if_find_by_vif_index (c_oil->oil.mfcc_parent); - - if (PIM_DEBUG_ZEBRA) - { - struct prefix_sg more; - - more.src = c_oil->oil.mfcc_origin; - more.grp = c_oil->oil.mfcc_mcastgrp; - zlog_debug ("Sending Request for New Channel Oil Information(%s) VIIF %d", - pim_str_sg_dump (&more), c_oil->oil.mfcc_parent); - } - - if (!ifp) - return -1; - - stream_reset (s); - zclient_create_header (s, ZEBRA_IPMR_ROUTE_STATS, VRF_DEFAULT); - stream_put_in_addr (s, &c_oil->oil.mfcc_origin); - stream_put_in_addr (s, &c_oil->oil.mfcc_mcastgrp); - stream_putl (s, ifp->ifindex); - stream_putw_at(s, 0, stream_get_endp(s)); - - count = stream_get_endp (s); - ret = writen (zlookup->sock, s->data, count); - if (ret <= 0) - { - zlog_err("%s %s: writen() failure: %d writing to zclient lookup socket", - __FILE__, __PRETTY_FUNCTION__, errno); - return -1; - } - - s = zlookup->ibuf; - - while (command != ZEBRA_IPMR_ROUTE_STATS) - { - int err; - uint16_t length = 0; - vrf_id_t vrf_id; - u_char marker; - u_char version; - - stream_reset (s); - err = zclient_read_header (s, zlookup->sock, &length, &marker, &version, - &vrf_id, &command); - if (err < 0) - { - zlog_err ("%s %s: zclient_read_header() failed", - __FILE__, __PRETTY_FUNCTION__); - zclient_lookup_failed(zlookup); - return -1; - } - } - - sg.src.s_addr = stream_get_ipv4 (s); - sg.grp.s_addr = stream_get_ipv4 (s); - if (sg.src.s_addr != c_oil->oil.mfcc_origin.s_addr || - sg.grp.s_addr != c_oil->oil.mfcc_mcastgrp.s_addr) - { - zlog_err ("%s: Received wrong %s information", - __PRETTY_FUNCTION__, pim_str_sg_dump (&sg)); - zclient_lookup_failed (zlookup); - return -3; - } - - stream_get (&lastused, s, sizeof (lastused)); - ret = stream_getl (s); - - if (PIM_DEBUG_ZEBRA) - zlog_debug ("Received %lld for %s success: %d", lastused, pim_str_sg_dump (&sg), ret); - - c_oil->cc.lastused = lastused; - - return 0; + struct stream *s = zlookup->obuf; + uint16_t command = 0; + unsigned long long lastused; + struct prefix_sg sg; + int count = 0; + int ret; + struct interface *ifp = + pim_if_find_by_vif_index(c_oil->oil.mfcc_parent); + + if (PIM_DEBUG_ZEBRA) { + struct prefix_sg more; + + more.src = c_oil->oil.mfcc_origin; + more.grp = c_oil->oil.mfcc_mcastgrp; + zlog_debug( + "Sending Request for New Channel Oil Information(%s) VIIF %d", + pim_str_sg_dump(&more), c_oil->oil.mfcc_parent); + } + + if (!ifp) + return -1; + + stream_reset(s); + zclient_create_header(s, ZEBRA_IPMR_ROUTE_STATS, VRF_DEFAULT); + stream_put_in_addr(s, &c_oil->oil.mfcc_origin); + stream_put_in_addr(s, &c_oil->oil.mfcc_mcastgrp); + stream_putl(s, ifp->ifindex); + stream_putw_at(s, 0, stream_get_endp(s)); + + count = stream_get_endp(s); + ret = writen(zlookup->sock, s->data, count); + if (ret <= 0) { + zlog_err( + "%s %s: writen() failure: %d writing to zclient lookup socket", + __FILE__, __PRETTY_FUNCTION__, errno); + return -1; + } + + s = zlookup->ibuf; + + while (command != ZEBRA_IPMR_ROUTE_STATS) { + int err; + uint16_t length = 0; + vrf_id_t vrf_id; + u_char marker; + u_char version; + + stream_reset(s); + err = zclient_read_header(s, zlookup->sock, &length, &marker, + &version, &vrf_id, &command); + if (err < 0) { + zlog_err("%s %s: zclient_read_header() failed", + __FILE__, __PRETTY_FUNCTION__); + zclient_lookup_failed(zlookup); + return -1; + } + } + + sg.src.s_addr = stream_get_ipv4(s); + sg.grp.s_addr = stream_get_ipv4(s); + if (sg.src.s_addr != c_oil->oil.mfcc_origin.s_addr + || sg.grp.s_addr != c_oil->oil.mfcc_mcastgrp.s_addr) { + zlog_err("%s: Received wrong %s information", + __PRETTY_FUNCTION__, pim_str_sg_dump(&sg)); + zclient_lookup_failed(zlookup); + return -3; + } + + stream_get(&lastused, s, sizeof(lastused)); + ret = stream_getl(s); + + if (PIM_DEBUG_ZEBRA) + zlog_debug("Received %lld for %s success: %d", lastused, + pim_str_sg_dump(&sg), ret); + + c_oil->cc.lastused = lastused; + return 0; } diff --git a/pimd/pim_zlookup.h b/pimd/pim_zlookup.h index 08c8768d1..d168464ce 100644 --- a/pimd/pim_zlookup.h +++ b/pimd/pim_zlookup.h @@ -27,21 +27,20 @@ #define PIM_NEXTHOP_LOOKUP_MAX (3) /* max. recursive route lookup */ struct pim_zlookup_nexthop { - struct prefix nexthop_addr; - ifindex_t ifindex; - uint32_t route_metric; - uint8_t protocol_distance; + struct prefix nexthop_addr; + ifindex_t ifindex; + uint32_t route_metric; + uint8_t protocol_distance; }; -void zclient_lookup_new (void); -void zclient_lookup_free (void); +void zclient_lookup_new(void); +void zclient_lookup_free(void); int zclient_lookup_nexthop(struct pim_zlookup_nexthop nexthop_tab[], - const int tab_size, - struct in_addr addr, + const int tab_size, struct in_addr addr, int max_lookup); -void pim_zlookup_show_ip_multicast (struct vty *vty); +void pim_zlookup_show_ip_multicast(struct vty *vty); -int pim_zlookup_sg_statistics (struct channel_oil *c_oil); +int pim_zlookup_sg_statistics(struct channel_oil *c_oil); #endif /* PIM_ZLOOKUP_H */ diff --git a/pimd/pimd.c b/pimd/pimd.c index b1d566f51..89b235bed 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -45,289 +45,272 @@ #include "pim_zlookup.h" #include "pim_nht.h" -const char *const PIM_ALL_SYSTEMS = MCAST_ALL_SYSTEMS; -const char *const PIM_ALL_ROUTERS = MCAST_ALL_ROUTERS; -const char *const PIM_ALL_PIM_ROUTERS = MCAST_ALL_PIM_ROUTERS; +const char *const PIM_ALL_SYSTEMS = MCAST_ALL_SYSTEMS; +const char *const PIM_ALL_ROUTERS = MCAST_ALL_ROUTERS; +const char *const PIM_ALL_PIM_ROUTERS = MCAST_ALL_PIM_ROUTERS; const char *const PIM_ALL_IGMP_ROUTERS = MCAST_ALL_IGMP_ROUTERS; -struct thread_master *master = NULL; -uint32_t qpim_debugs = 0; -int qpim_mroute_socket_fd = -1; -int64_t qpim_mroute_socket_creation = 0; /* timestamp of creation */ -int qpim_t_periodic = PIM_DEFAULT_T_PERIODIC; /* Period between Join/Prune Messages */ -struct pim_assert_metric qpim_infinite_assert_metric; -long qpim_rpf_cache_refresh_delay_msec = 50; -struct thread *qpim_rpf_cache_refresher = NULL; -int64_t qpim_rpf_cache_refresh_requests = 0; -int64_t qpim_rpf_cache_refresh_events = 0; -int64_t qpim_rpf_cache_refresh_last = 0; -struct list *qpim_ssmpingd_list = NULL; -struct in_addr qpim_ssmpingd_group_addr; -int64_t qpim_scan_oil_events = 0; -int64_t qpim_scan_oil_last = 0; -int64_t qpim_mroute_add_events = 0; -int64_t qpim_mroute_add_last = 0; -int64_t qpim_mroute_del_events = 0; -int64_t qpim_mroute_del_last = 0; -struct list *qpim_static_route_list = NULL; -unsigned int qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD; -signed int qpim_rp_keep_alive_time = 0; -int64_t qpim_nexthop_lookups = 0; -int qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS; -uint8_t qpim_ecmp_enable = 0; -uint8_t qpim_ecmp_rebalance_enable = 0; -struct pim_instance *pimg = NULL; +struct thread_master *master = NULL; +uint32_t qpim_debugs = 0; +int qpim_mroute_socket_fd = -1; +int64_t qpim_mroute_socket_creation = 0; /* timestamp of creation */ +int qpim_t_periodic = + PIM_DEFAULT_T_PERIODIC; /* Period between Join/Prune Messages */ +struct pim_assert_metric qpim_infinite_assert_metric; +long qpim_rpf_cache_refresh_delay_msec = 50; +struct thread *qpim_rpf_cache_refresher = NULL; +int64_t qpim_rpf_cache_refresh_requests = 0; +int64_t qpim_rpf_cache_refresh_events = 0; +int64_t qpim_rpf_cache_refresh_last = 0; +struct list *qpim_ssmpingd_list = NULL; +struct in_addr qpim_ssmpingd_group_addr; +int64_t qpim_scan_oil_events = 0; +int64_t qpim_scan_oil_last = 0; +int64_t qpim_mroute_add_events = 0; +int64_t qpim_mroute_add_last = 0; +int64_t qpim_mroute_del_events = 0; +int64_t qpim_mroute_del_last = 0; +struct list *qpim_static_route_list = NULL; +unsigned int qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD; +signed int qpim_rp_keep_alive_time = 0; +int64_t qpim_nexthop_lookups = 0; +int qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS; +uint8_t qpim_ecmp_enable = 0; +uint8_t qpim_ecmp_rebalance_enable = 0; +struct pim_instance *pimg = NULL; int32_t qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT; int32_t qpim_register_probe_time = PIM_REGISTER_PROBE_TIME_DEFAULT; -static struct pim_instance *pim_instance_init (vrf_id_t vrf_id, afi_t afi); -static void pim_instance_terminate (void); +static struct pim_instance *pim_instance_init(vrf_id_t vrf_id, afi_t afi); +static void pim_instance_terminate(void); -static int -pim_vrf_new (struct vrf *vrf) +static int pim_vrf_new(struct vrf *vrf) { - zlog_debug ("VRF Created: %s(%d)", vrf->name, vrf->vrf_id); - return 0; + zlog_debug("VRF Created: %s(%d)", vrf->name, vrf->vrf_id); + return 0; } -static int -pim_vrf_delete (struct vrf *vrf) +static int pim_vrf_delete(struct vrf *vrf) { - zlog_debug ("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id); - return 0; + zlog_debug("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id); + return 0; } -static int -pim_vrf_enable (struct vrf *vrf) +static int pim_vrf_enable(struct vrf *vrf) { - if (!vrf) // unexpected - return -1; - - if (vrf->vrf_id == VRF_DEFAULT) - { - pimg = pim_instance_init (VRF_DEFAULT, AFI_IP); - if (pimg == NULL) - { - zlog_err ("%s %s: pim class init failure ", __FILE__, - __PRETTY_FUNCTION__); - /* - * We will crash and burn otherwise - */ - exit(1); - } - - pimg->send_v6_secondary = 1; - - } - return 0; + if (!vrf) // unexpected + return -1; + + if (vrf->vrf_id == VRF_DEFAULT) { + pimg = pim_instance_init(VRF_DEFAULT, AFI_IP); + if (pimg == NULL) { + zlog_err("%s %s: pim class init failure ", __FILE__, + __PRETTY_FUNCTION__); + /* + * We will crash and burn otherwise + */ + exit(1); + } + + pimg->send_v6_secondary = 1; + } + return 0; } -static int -pim_vrf_disable (struct vrf *vrf) +static int pim_vrf_disable(struct vrf *vrf) { - if (vrf->vrf_id == VRF_DEFAULT) - return 0; + if (vrf->vrf_id == VRF_DEFAULT) + return 0; - if (vrf->vrf_id == VRF_DEFAULT) - pim_instance_terminate (); + if (vrf->vrf_id == VRF_DEFAULT) + pim_instance_terminate(); - /* Note: This is a callback, the VRF will be deleted by the caller. */ - return 0; + /* Note: This is a callback, the VRF will be deleted by the caller. */ + return 0; } -void -pim_vrf_init (void) +void pim_vrf_init(void) { - vrf_init (pim_vrf_new, - pim_vrf_enable, - pim_vrf_disable, - pim_vrf_delete); + vrf_init(pim_vrf_new, pim_vrf_enable, pim_vrf_disable, pim_vrf_delete); } -static void -pim_vrf_terminate (void) +static void pim_vrf_terminate(void) { - vrf_terminate (); + vrf_terminate(); } /* Key generate for pim->rpf_hash */ -static unsigned int -pim_rpf_hash_key (void *arg) +static unsigned int pim_rpf_hash_key(void *arg) { - struct pim_nexthop_cache *r = (struct pim_nexthop_cache *) arg; + struct pim_nexthop_cache *r = (struct pim_nexthop_cache *)arg; - return jhash_1word (r->rpf.rpf_addr.u.prefix4.s_addr, 0); + return jhash_1word(r->rpf.rpf_addr.u.prefix4.s_addr, 0); } /* Compare pim->rpf_hash node data */ -static int -pim_rpf_equal (const void *arg1, const void *arg2) +static int pim_rpf_equal(const void *arg1, const void *arg2) { - const struct pim_nexthop_cache *r1 = - (const struct pim_nexthop_cache *) arg1; - const struct pim_nexthop_cache *r2 = - (const struct pim_nexthop_cache *) arg2; + const struct pim_nexthop_cache *r1 = + (const struct pim_nexthop_cache *)arg1; + const struct pim_nexthop_cache *r2 = + (const struct pim_nexthop_cache *)arg2; - return prefix_same (&r1->rpf.rpf_addr, &r2->rpf.rpf_addr); + return prefix_same(&r1->rpf.rpf_addr, &r2->rpf.rpf_addr); } /* Cleanup pim->rpf_hash each node data */ -static void -pim_rp_list_hash_clean (void *data) +static void pim_rp_list_hash_clean(void *data) { - struct pim_nexthop_cache *pnc; + struct pim_nexthop_cache *pnc; - pnc = (struct pim_nexthop_cache *) data; - if (pnc->rp_list->count) - list_delete_all_node (pnc->rp_list); - if (pnc->upstream_list->count) - list_delete_all_node (pnc->upstream_list); + pnc = (struct pim_nexthop_cache *)data; + if (pnc->rp_list->count) + list_delete_all_node(pnc->rp_list); + if (pnc->upstream_list->count) + list_delete_all_node(pnc->upstream_list); } -void -pim_prefix_list_update (struct prefix_list *plist) +void pim_prefix_list_update(struct prefix_list *plist) { - pim_rp_prefix_list_update (plist); - pim_ssm_prefix_list_update (plist); - pim_upstream_spt_prefix_list_update (plist); + pim_rp_prefix_list_update(plist); + pim_ssm_prefix_list_update(plist); + pim_upstream_spt_prefix_list_update(plist); } -static void -pim_instance_terminate (void) +static void pim_instance_terminate(void) { - /* Traverse and cleanup rpf_hash */ - if (pimg->rpf_hash) - { - hash_clean (pimg->rpf_hash, (void *) pim_rp_list_hash_clean); - hash_free (pimg->rpf_hash); - pimg->rpf_hash = NULL; - } - - if (pimg->ssm_info) - { - pim_ssm_terminate (pimg->ssm_info); - pimg->ssm_info = NULL; - } - - XFREE (MTYPE_PIM_PIM_INSTANCE, pimg); + /* Traverse and cleanup rpf_hash */ + if (pimg->rpf_hash) { + hash_clean(pimg->rpf_hash, (void *)pim_rp_list_hash_clean); + hash_free(pimg->rpf_hash); + pimg->rpf_hash = NULL; + } + + if (pimg->ssm_info) { + pim_ssm_terminate(pimg->ssm_info); + pimg->ssm_info = NULL; + } + + XFREE(MTYPE_PIM_PIM_INSTANCE, pimg); } static void pim_free() { - pim_ssmpingd_destroy(); + pim_ssmpingd_destroy(); - pim_oil_terminate (); + pim_oil_terminate(); - pim_upstream_terminate (); + pim_upstream_terminate(); - if (qpim_static_route_list) - list_free(qpim_static_route_list); + if (qpim_static_route_list) + list_free(qpim_static_route_list); - pim_if_terminate (); - pim_rp_free (); + pim_if_terminate(); + pim_rp_free(); - pim_route_map_terminate(); + pim_route_map_terminate(); - zclient_lookup_free (); + zclient_lookup_free(); - zprivs_terminate(&pimd_privs); + zprivs_terminate(&pimd_privs); } -static struct pim_instance * -pim_instance_init (vrf_id_t vrf_id, afi_t afi) +static struct pim_instance *pim_instance_init(vrf_id_t vrf_id, afi_t afi) { - struct pim_instance *pim; + struct pim_instance *pim; - pim = XCALLOC (MTYPE_PIM_PIM_INSTANCE, sizeof (struct pim_instance)); - if (!pim) - return NULL; + pim = XCALLOC(MTYPE_PIM_PIM_INSTANCE, sizeof(struct pim_instance)); + if (!pim) + return NULL; - pim->vrf_id = vrf_id; - pim->afi = afi; + pim->vrf_id = vrf_id; + pim->afi = afi; - pim->spt.switchover = PIM_SPT_IMMEDIATE; - pim->spt.plist = NULL; + pim->spt.switchover = PIM_SPT_IMMEDIATE; + pim->spt.plist = NULL; - pim->rpf_hash = hash_create_size (256, pim_rpf_hash_key, pim_rpf_equal, NULL); + pim->rpf_hash = + hash_create_size(256, pim_rpf_hash_key, pim_rpf_equal, NULL); - if (PIM_DEBUG_ZEBRA) - zlog_debug ("%s: NHT rpf hash init ", __PRETTY_FUNCTION__); + if (PIM_DEBUG_ZEBRA) + zlog_debug("%s: NHT rpf hash init ", __PRETTY_FUNCTION__); - pim->ssm_info = pim_ssm_init (vrf_id); - if (!pim->ssm_info) { - pim_instance_terminate (); - return NULL; - } + pim->ssm_info = pim_ssm_init(vrf_id); + if (!pim->ssm_info) { + pim_instance_terminate(); + return NULL; + } - return pim; + return pim; } void pim_init() { - qpim_rp_keep_alive_time = PIM_RP_KEEPALIVE_PERIOD; - - pim_rp_init (); - - if (!inet_aton(PIM_ALL_PIM_ROUTERS, &qpim_all_pim_routers_addr)) { - zlog_err("%s %s: could not solve %s to group address: errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, - PIM_ALL_PIM_ROUTERS, errno, safe_strerror(errno)); - zassert(0); - return; - } - - pim_oil_init (); - - pim_upstream_init (); - - qpim_static_route_list = list_new(); - if (!qpim_static_route_list) { - zlog_err("%s %s: failure: static_route_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return; - } - qpim_static_route_list->del = (void (*)(void *)) pim_static_route_free; - - pim_mroute_socket_enable(); - - - /* - RFC 4601: 4.6.3. Assert Metrics - - assert_metric - infinite_assert_metric() { - return {1,infinity,infinity,0} - } - */ - qpim_infinite_assert_metric.rpt_bit_flag = 1; - qpim_infinite_assert_metric.metric_preference = PIM_ASSERT_METRIC_PREFERENCE_MAX; - qpim_infinite_assert_metric.route_metric = PIM_ASSERT_ROUTE_METRIC_MAX; - qpim_infinite_assert_metric.ip_address.s_addr = INADDR_ANY; - - pim_if_init(); - pim_cmd_init(); - pim_ssmpingd_init(); + qpim_rp_keep_alive_time = PIM_RP_KEEPALIVE_PERIOD; + + pim_rp_init(); + + if (!inet_aton(PIM_ALL_PIM_ROUTERS, &qpim_all_pim_routers_addr)) { + zlog_err( + "%s %s: could not solve %s to group address: errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, PIM_ALL_PIM_ROUTERS, + errno, safe_strerror(errno)); + zassert(0); + return; + } + + pim_oil_init(); + + pim_upstream_init(); + + qpim_static_route_list = list_new(); + if (!qpim_static_route_list) { + zlog_err("%s %s: failure: static_route_list=list_new()", + __FILE__, __PRETTY_FUNCTION__); + return; + } + qpim_static_route_list->del = (void (*)(void *))pim_static_route_free; + + pim_mroute_socket_enable(); + + + /* + RFC 4601: 4.6.3. Assert Metrics + + assert_metric + infinite_assert_metric() { + return {1,infinity,infinity,0} + } + */ + qpim_infinite_assert_metric.rpt_bit_flag = 1; + qpim_infinite_assert_metric.metric_preference = + PIM_ASSERT_METRIC_PREFERENCE_MAX; + qpim_infinite_assert_metric.route_metric = PIM_ASSERT_ROUTE_METRIC_MAX; + qpim_infinite_assert_metric.ip_address.s_addr = INADDR_ANY; + + pim_if_init(); + pim_cmd_init(); + pim_ssmpingd_init(); } void pim_terminate() { - struct zclient *zclient; + struct zclient *zclient; - pim_free(); + pim_free(); - /* reverse prefix_list_init */ - prefix_list_add_hook (NULL); - prefix_list_delete_hook (NULL); - prefix_list_reset (); + /* reverse prefix_list_init */ + prefix_list_add_hook(NULL); + prefix_list_delete_hook(NULL); + prefix_list_reset(); - pim_vrf_terminate (); + pim_vrf_terminate(); - zclient = pim_zebra_zclient_get (); - if (zclient) - { - zclient_stop (zclient); - zclient_free (zclient); - } + zclient = pim_zebra_zclient_get(); + if (zclient) { + zclient_stop(zclient); + zclient_free(zclient); + } } diff --git a/pimd/pimd.h b/pimd/pimd.h index 18520f57e..7934bce2d 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -65,10 +65,9 @@ * | Number of Joined Sources | Number of Pruned Sources | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -#define PIM_JP_GROUP_HEADER_SIZE (PIM_ENCODED_IPV4_UCAST_SIZE + \ - 1 + 1 + 2 + \ - PIM_ENCODED_IPV4_GROUP_SIZE + \ - 2 + 2) +#define PIM_JP_GROUP_HEADER_SIZE \ + (PIM_ENCODED_IPV4_UCAST_SIZE + 1 + 1 + 2 + PIM_ENCODED_IPV4_GROUP_SIZE \ + + 2 + 2) #define PIM_PROTO_VERSION (2) @@ -108,7 +107,6 @@ #define PIM_MASK_MSDP_PACKETS (1 << 20) #define PIM_MASK_MSDP_INTERNAL (1 << 21) - /* PIM error codes */ #define PIM_SUCCESS 0 #define PIM_MALLOC_FAIL -1 @@ -127,34 +125,34 @@ const char *const PIM_ALL_ROUTERS; const char *const PIM_ALL_PIM_ROUTERS; const char *const PIM_ALL_IGMP_ROUTERS; -extern struct thread_master *master; +extern struct thread_master *master; extern struct zebra_privs_t pimd_privs; -uint32_t qpim_debugs; -int qpim_mroute_socket_fd; -int64_t qpim_mroute_socket_creation; /* timestamp of creation */ -struct in_addr qpim_all_pim_routers_addr; -int qpim_t_periodic; /* Period between Join/Prune Messages */ -struct pim_assert_metric qpim_infinite_assert_metric; -long qpim_rpf_cache_refresh_delay_msec; -struct thread *qpim_rpf_cache_refresher; -int64_t qpim_rpf_cache_refresh_requests; -int64_t qpim_rpf_cache_refresh_events; -int64_t qpim_rpf_cache_refresh_last; -struct list *qpim_ssmpingd_list; /* list of struct ssmpingd_sock */ -struct in_addr qpim_ssmpingd_group_addr; -int64_t qpim_scan_oil_events; -int64_t qpim_scan_oil_last; -int64_t qpim_mroute_add_events; -int64_t qpim_mroute_add_last; -int64_t qpim_mroute_del_events; -int64_t qpim_mroute_del_last; -int64_t qpim_nexthop_lookups; -struct list *qpim_static_route_list; /* list of routes added statically */ -extern unsigned int qpim_keep_alive_time; -extern signed int qpim_rp_keep_alive_time; -extern int qpim_packet_process; -extern uint8_t qpim_ecmp_enable; -extern uint8_t qpim_ecmp_rebalance_enable; +uint32_t qpim_debugs; +int qpim_mroute_socket_fd; +int64_t qpim_mroute_socket_creation; /* timestamp of creation */ +struct in_addr qpim_all_pim_routers_addr; +int qpim_t_periodic; /* Period between Join/Prune Messages */ +struct pim_assert_metric qpim_infinite_assert_metric; +long qpim_rpf_cache_refresh_delay_msec; +struct thread *qpim_rpf_cache_refresher; +int64_t qpim_rpf_cache_refresh_requests; +int64_t qpim_rpf_cache_refresh_events; +int64_t qpim_rpf_cache_refresh_last; +struct list *qpim_ssmpingd_list; /* list of struct ssmpingd_sock */ +struct in_addr qpim_ssmpingd_group_addr; +int64_t qpim_scan_oil_events; +int64_t qpim_scan_oil_last; +int64_t qpim_mroute_add_events; +int64_t qpim_mroute_add_last; +int64_t qpim_mroute_del_events; +int64_t qpim_mroute_del_last; +int64_t qpim_nexthop_lookups; +struct list *qpim_static_route_list; /* list of routes added statically */ +extern unsigned int qpim_keep_alive_time; +extern signed int qpim_rp_keep_alive_time; +extern int qpim_packet_process; +extern uint8_t qpim_ecmp_enable; +extern uint8_t qpim_ecmp_rebalance_enable; #define PIM_DEFAULT_PACKET_PROCESS 3 @@ -239,36 +237,35 @@ extern int32_t qpim_register_probe_time; #define PIM_DONT_DEBUG_MSDP_INTERNAL (qpim_debugs &= ~PIM_MASK_MSDP_INTERNAL) enum pim_spt_switchover { - PIM_SPT_IMMEDIATE, - PIM_SPT_INFINITY, + PIM_SPT_IMMEDIATE, + PIM_SPT_INFINITY, }; /* Per VRF PIM DB */ -struct pim_instance -{ - afi_t afi; - vrf_id_t vrf_id; +struct pim_instance { + afi_t afi; + vrf_id_t vrf_id; + + struct { + enum pim_spt_switchover switchover; + char *plist; + } spt; - struct { - enum pim_spt_switchover switchover; - char *plist; - } spt; + struct hash *rpf_hash; - struct hash *rpf_hash; + void *ssm_info; /* per-vrf SSM configuration */ - void *ssm_info; /* per-vrf SSM configuration */ - - int send_v6_secondary; + int send_v6_secondary; }; -extern struct pim_instance *pimg; //Pim Global Instance +extern struct pim_instance *pimg; // Pim Global Instance void pim_init(void); void pim_terminate(void); -extern void pim_route_map_init (void); +extern void pim_route_map_init(void); extern void pim_route_map_terminate(void); -void pim_vrf_init (void); -void pim_prefix_list_update (struct prefix_list *plist); +void pim_vrf_init(void); +void pim_prefix_list_update(struct prefix_list *plist); #endif /* PIMD_H */ diff --git a/pimd/test_igmpv3_join.c b/pimd/test_igmpv3_join.c index f363152ad..14ec9fb02 100644 --- a/pimd/test_igmpv3_join.c +++ b/pimd/test_igmpv3_join.c @@ -36,114 +36,114 @@ const char *prog_name = 0; static int iface_solve_index(const char *ifname) { - struct if_nameindex *ini; - ifindex_t ifindex = -1; - int i; - - if (!ifname) - return -1; - - ini = if_nameindex(); - if (!ini) { - int err = errno; - fprintf(stderr, - "%s: interface=%s: failure solving index: errno=%d: %s\n", - prog_name, ifname, err, strerror(err)); - errno = err; - return -1; - } - - for (i = 0; ini[i].if_index; ++i) { + struct if_nameindex *ini; + ifindex_t ifindex = -1; + int i; + + if (!ifname) + return -1; + + ini = if_nameindex(); + if (!ini) { + int err = errno; + fprintf(stderr, + "%s: interface=%s: failure solving index: errno=%d: %s\n", + prog_name, ifname, err, strerror(err)); + errno = err; + return -1; + } + + for (i = 0; ini[i].if_index; ++i) { #if 0 fprintf(stderr, "%s: interface=%s matching against local ifname=%s ifindex=%d\n", prog_name, ifname, ini[i].if_name, ini[i].if_index); #endif - if (!strcmp(ini[i].if_name, ifname)) { - ifindex = ini[i].if_index; - break; - } - } + if (!strcmp(ini[i].if_name, ifname)) { + ifindex = ini[i].if_index; + break; + } + } - if_freenameindex(ini); + if_freenameindex(ini); - return ifindex; + return ifindex; } int main(int argc, const char *argv[]) { - struct in_addr group_addr; - struct in_addr source_addr; - const char *ifname; - const char *group; - const char *source; - ifindex_t ifindex; - int result; - int fd; - - prog_name = argv[0]; - - fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (fd < 0) { - fprintf(stderr, - "%s: could not create socket: socket(): errno=%d: %s\n", - prog_name, errno, strerror(errno)); - exit(1); - } - - if (argc != 4) { - fprintf(stderr, - "usage: %s interface group source\n" - "example: %s eth0 232.1.1.1 1.1.1.1\n", - prog_name, prog_name); - exit(1); - } - - ifname = argv[1]; - group = argv[2]; - source = argv[3]; - - ifindex = iface_solve_index(ifname); - if (ifindex < 0) { - fprintf(stderr, "%s: could not find interface: %s\n", - prog_name, ifname); - exit(1); - } - - result = inet_pton(AF_INET, group, &group_addr); - if (result <= 0) { - fprintf(stderr, "%s: bad group address: %s\n", - prog_name, group); - exit(1); - } - - result = inet_pton(AF_INET, source, &source_addr); - if (result <= 0) { - fprintf(stderr, "%s: bad source address: %s\n", - prog_name, source); - exit(1); - } - - result = pim_igmp_join_source(fd, ifindex, group_addr, source_addr); - if (result) { - fprintf(stderr, - "%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s\n", - prog_name, fd, group, source, ifindex, ifname, - errno, strerror(errno)); - exit(1); - } - - printf("%s: joined channel (S,G)=(%s,%s) on interface %s\n", - prog_name, source, group, ifname); - - printf("%s: waiting...\n", prog_name); - - getchar(); - - close(fd); - - printf("%s: left channel (S,G)=(%s,%s) on interface %s\n", - prog_name, source, group, ifname); - - exit(0); + struct in_addr group_addr; + struct in_addr source_addr; + const char *ifname; + const char *group; + const char *source; + ifindex_t ifindex; + int result; + int fd; + + prog_name = argv[0]; + + fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (fd < 0) { + fprintf(stderr, + "%s: could not create socket: socket(): errno=%d: %s\n", + prog_name, errno, strerror(errno)); + exit(1); + } + + if (argc != 4) { + fprintf(stderr, + "usage: %s interface group source\n" + "example: %s eth0 232.1.1.1 1.1.1.1\n", + prog_name, prog_name); + exit(1); + } + + ifname = argv[1]; + group = argv[2]; + source = argv[3]; + + ifindex = iface_solve_index(ifname); + if (ifindex < 0) { + fprintf(stderr, "%s: could not find interface: %s\n", prog_name, + ifname); + exit(1); + } + + result = inet_pton(AF_INET, group, &group_addr); + if (result <= 0) { + fprintf(stderr, "%s: bad group address: %s\n", prog_name, + group); + exit(1); + } + + result = inet_pton(AF_INET, source, &source_addr); + if (result <= 0) { + fprintf(stderr, "%s: bad source address: %s\n", prog_name, + source); + exit(1); + } + + result = pim_igmp_join_source(fd, ifindex, group_addr, source_addr); + if (result) { + fprintf(stderr, + "%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s\n", + prog_name, fd, group, source, ifindex, ifname, errno, + strerror(errno)); + exit(1); + } + + printf("%s: joined channel (S,G)=(%s,%s) on interface %s\n", prog_name, + source, group, ifname); + + printf("%s: waiting...\n", prog_name); + + getchar(); + + close(fd); + + printf("%s: left channel (S,G)=(%s,%s) on interface %s\n", prog_name, + source, group, ifname); + + exit(0); } diff --git a/qpb/linear_allocator.h b/qpb/linear_allocator.h index 273bc7369..40393a9a9 100644 --- a/qpb/linear_allocator.h +++ b/qpb/linear_allocator.h @@ -40,42 +40,41 @@ */ #define LINEAR_ALLOCATOR_ALIGNMENT 8 -#define LINEAR_ALLOCATOR_ALIGN(value) \ - (((value) + LINEAR_ALLOCATOR_ALIGNMENT - 1) & ~(LINEAR_ALLOCATOR_ALIGNMENT - 1)); +#define LINEAR_ALLOCATOR_ALIGN(value) \ + (((value) + LINEAR_ALLOCATOR_ALIGNMENT - 1) \ + & ~(LINEAR_ALLOCATOR_ALIGNMENT - 1)); /* * linear_allocator_align_ptr */ -static inline char * -linear_allocator_align_ptr (char *ptr) +static inline char *linear_allocator_align_ptr(char *ptr) { - return (char *) LINEAR_ALLOCATOR_ALIGN ((intptr_t) ptr); + return (char *)LINEAR_ALLOCATOR_ALIGN((intptr_t)ptr); } -typedef struct linear_allocator_t_ -{ - char *buf; - - /* - * Current location in the buffer. - */ - char *cur; - - /* - * End of buffer. - */ - char *end; - - /* - * Version number of the allocator, this is bumped up when the allocator - * is reset and helps identifies bad frees. - */ - uint32_t version; - - /* - * The number of blocks that are currently allocated. - */ - int num_allocated; +typedef struct linear_allocator_t_ { + char *buf; + + /* + * Current location in the buffer. + */ + char *cur; + + /* + * End of buffer. + */ + char *end; + + /* + * Version number of the allocator, this is bumped up when the allocator + * is reset and helps identifies bad frees. + */ + uint32_t version; + + /* + * The number of blocks that are currently allocated. + */ + int num_allocated; } linear_allocator_t; /* @@ -83,15 +82,14 @@ typedef struct linear_allocator_t_ * * Header structure at the begining of each block. */ -typedef struct linear_allocator_block_t_ -{ - uint32_t flags; - - /* - * The version of the allocator when this block was allocated. - */ - uint32_t version; - char data[0]; +typedef struct linear_allocator_block_t_ { + uint32_t flags; + + /* + * The version of the allocator when this block was allocated. + */ + uint32_t version; + char data[0]; } linear_allocator_block_t; #define LINEAR_ALLOCATOR_BLOCK_IN_USE 0x01 @@ -104,36 +102,33 @@ typedef struct linear_allocator_block_t_ * The total amount of space a block will take in the buffer, * including the size of the header. */ -static inline size_t -linear_allocator_block_size (size_t user_size) +static inline size_t linear_allocator_block_size(size_t user_size) { - return LINEAR_ALLOCATOR_ALIGN (LINEAR_ALLOCATOR_HDR_SIZE + user_size); + return LINEAR_ALLOCATOR_ALIGN(LINEAR_ALLOCATOR_HDR_SIZE + user_size); } /* * linear_allocator_ptr_to_block */ -static inline linear_allocator_block_t * -linear_allocator_ptr_to_block (void *ptr) +static inline linear_allocator_block_t *linear_allocator_ptr_to_block(void *ptr) { - void *block_ptr; - block_ptr = ((char *) ptr) - offsetof (linear_allocator_block_t, data); - return block_ptr; + void *block_ptr; + block_ptr = ((char *)ptr) - offsetof(linear_allocator_block_t, data); + return block_ptr; } /* * linear_allocator_init */ -static inline void -linear_allocator_init (linear_allocator_t * allocator, char *buf, - size_t buf_len) +static inline void linear_allocator_init(linear_allocator_t *allocator, + char *buf, size_t buf_len) { - memset (allocator, 0, sizeof (*allocator)); + memset(allocator, 0, sizeof(*allocator)); - assert (linear_allocator_align_ptr (buf) == buf); - allocator->buf = buf; - allocator->cur = buf; - allocator->end = buf + buf_len; + assert(linear_allocator_align_ptr(buf) == buf); + allocator->buf = buf; + allocator->cur = buf; + allocator->end = buf + buf_len; } /* @@ -143,64 +138,59 @@ linear_allocator_init (linear_allocator_t * allocator, char *buf, * * *** NOTE ** This implicitly frees all the blocks in the allocator. */ -static inline void -linear_allocator_reset (linear_allocator_t *allocator) +static inline void linear_allocator_reset(linear_allocator_t *allocator) { - allocator->num_allocated = 0; - allocator->version++; - allocator->cur = allocator->buf; + allocator->num_allocated = 0; + allocator->version++; + allocator->cur = allocator->buf; } /* * linear_allocator_alloc */ -static inline void * -linear_allocator_alloc (linear_allocator_t *allocator, size_t user_size) +static inline void *linear_allocator_alloc(linear_allocator_t *allocator, + size_t user_size) { - size_t block_size; - linear_allocator_block_t *block; + size_t block_size; + linear_allocator_block_t *block; - block_size = linear_allocator_block_size (user_size); + block_size = linear_allocator_block_size(user_size); - if (allocator->cur + block_size > allocator->end) - { - return NULL; - } + if (allocator->cur + block_size > allocator->end) { + return NULL; + } - block = (linear_allocator_block_t *) allocator->cur; - allocator->cur += block_size; + block = (linear_allocator_block_t *)allocator->cur; + allocator->cur += block_size; - block->flags = LINEAR_ALLOCATOR_BLOCK_IN_USE; - block->version = allocator->version; - allocator->num_allocated++; - return block->data; + block->flags = LINEAR_ALLOCATOR_BLOCK_IN_USE; + block->version = allocator->version; + allocator->num_allocated++; + return block->data; } /* * linear_allocator_free */ -static inline void -linear_allocator_free (linear_allocator_t *allocator, void *ptr) +static inline void linear_allocator_free(linear_allocator_t *allocator, + void *ptr) { - linear_allocator_block_t *block; - - if (((char *) ptr) < allocator->buf || ((char *) ptr) >= allocator->end) - { - assert (0); - return; - } - - block = linear_allocator_ptr_to_block (ptr); - if (block->version != allocator->version) - { - assert (0); - return; - } - - block->flags = block->flags & ~LINEAR_ALLOCATOR_BLOCK_IN_USE; - - if (--allocator->num_allocated < 0) - { - assert (0); - } + linear_allocator_block_t *block; + + if (((char *)ptr) < allocator->buf || ((char *)ptr) >= allocator->end) { + assert(0); + return; + } + + block = linear_allocator_ptr_to_block(ptr); + if (block->version != allocator->version) { + assert(0); + return; + } + + block->flags = block->flags & ~LINEAR_ALLOCATOR_BLOCK_IN_USE; + + if (--allocator->num_allocated < 0) { + assert(0); + } } diff --git a/qpb/qpb.c b/qpb/qpb.c index 9c47a80d2..8e130f5f5 100644 --- a/qpb/qpb.c +++ b/qpb/qpb.c @@ -25,4 +25,3 @@ /* * Main file for the qpb library. */ - diff --git a/qpb/qpb.h b/qpb/qpb.h index f5d00900f..fb5f56ac3 100644 --- a/qpb/qpb.h +++ b/qpb/qpb.h @@ -39,105 +39,103 @@ * qpb__address_family__set */ #define qpb_address_family_set qpb__address_family__set -static inline int -qpb__address_family__set (Qpb__AddressFamily *pb_family, u_char family) +static inline int qpb__address_family__set(Qpb__AddressFamily *pb_family, + u_char family) { - switch (family) { - case AF_INET: - *pb_family = QPB__ADDRESS_FAMILY__IPV4; - return 1; + switch (family) { + case AF_INET: + *pb_family = QPB__ADDRESS_FAMILY__IPV4; + return 1; - case AF_INET6: - *pb_family = QPB__ADDRESS_FAMILY__IPV6; - return 1; + case AF_INET6: + *pb_family = QPB__ADDRESS_FAMILY__IPV6; + return 1; - default: - *pb_family = QPB__ADDRESS_FAMILY__UNKNOWN_AF; - } + default: + *pb_family = QPB__ADDRESS_FAMILY__UNKNOWN_AF; + } - return 0; + return 0; } /* * qpb__address_family__get */ #define qpb_address_family_get qpb__address_family__get -static inline int -qpb__address_family__get (Qpb__AddressFamily pb_family, u_char *family) +static inline int qpb__address_family__get(Qpb__AddressFamily pb_family, + u_char *family) { - switch (pb_family) { - case QPB__ADDRESS_FAMILY__IPV4: - *family = AF_INET; - return 1; + switch (pb_family) { + case QPB__ADDRESS_FAMILY__IPV4: + *family = AF_INET; + return 1; - case QPB__ADDRESS_FAMILY__IPV6: - *family = AF_INET6; - return 1; + case QPB__ADDRESS_FAMILY__IPV6: + *family = AF_INET6; + return 1; - case QPB__ADDRESS_FAMILY__UNKNOWN_AF: - return 0; - default: /* protobuf "magic value" _QPB__ADDRESS_FAMILY_IS_INT_SIZE */ - return 0; - } + case QPB__ADDRESS_FAMILY__UNKNOWN_AF: + return 0; + default: /* protobuf "magic value" _QPB__ADDRESS_FAMILY_IS_INT_SIZE */ + return 0; + } - return 0; + return 0; } /* * qpb__l3_prefix__create */ #define qpb_l3_prefix_create qpb__l3_prefix__create -static inline Qpb__L3Prefix * -qpb__l3_prefix__create (qpb_allocator_t *allocator, struct prefix *p) +static inline Qpb__L3Prefix *qpb__l3_prefix__create(qpb_allocator_t *allocator, + struct prefix *p) { - Qpb__L3Prefix *prefix; - - prefix = QPB_ALLOC(allocator, typeof(*prefix)); - if (!prefix) { - return NULL; - } - qpb__l3_prefix__init(prefix); - prefix->length = p->prefixlen; - prefix->bytes.len = (p->prefixlen + 7)/8; - prefix->bytes.data = qpb_alloc(allocator, prefix->bytes.len); - if (!prefix->bytes.data) { - return NULL; - } - - memcpy(prefix->bytes.data, &p->u.prefix, prefix->bytes.len); - - return prefix; + Qpb__L3Prefix *prefix; + + prefix = QPB_ALLOC(allocator, typeof(*prefix)); + if (!prefix) { + return NULL; + } + qpb__l3_prefix__init(prefix); + prefix->length = p->prefixlen; + prefix->bytes.len = (p->prefixlen + 7) / 8; + prefix->bytes.data = qpb_alloc(allocator, prefix->bytes.len); + if (!prefix->bytes.data) { + return NULL; + } + + memcpy(prefix->bytes.data, &p->u.prefix, prefix->bytes.len); + + return prefix; } /* * qpb__l3_prefix__get */ #define qpb_l3_prefix_get qpb__l3_prefix__get -static inline int -qpb__l3_prefix__get (const Qpb__L3Prefix *pb_prefix, u_char family, - struct prefix *prefix) +static inline int qpb__l3_prefix__get(const Qpb__L3Prefix *pb_prefix, + u_char family, struct prefix *prefix) { - switch (family) - { + switch (family) { - case AF_INET: - memset(prefix, 0, sizeof(struct prefix_ipv4)); - break; + case AF_INET: + memset(prefix, 0, sizeof(struct prefix_ipv4)); + break; - case AF_INET6: - memset(prefix, 0, sizeof(struct prefix_ipv6)); - break; + case AF_INET6: + memset(prefix, 0, sizeof(struct prefix_ipv6)); + break; - default: - memset(prefix, 0, sizeof(*prefix)); - } + default: + memset(prefix, 0, sizeof(*prefix)); + } - prefix->prefixlen = pb_prefix->length; - prefix->family = family; - memcpy(&prefix->u.prefix, pb_prefix->bytes.data, pb_prefix->bytes.len); - return 1; + prefix->prefixlen = pb_prefix->length; + prefix->family = family; + memcpy(&prefix->u.prefix, pb_prefix->bytes.data, pb_prefix->bytes.len); + return 1; } /* @@ -146,103 +144,101 @@ qpb__l3_prefix__get (const Qpb__L3Prefix *pb_prefix, u_char family, * Translate a quagga route type to a protobuf protocol. */ #define qpb_protocol_set qpb__protocol__set -static inline int -qpb__protocol__set (Qpb__Protocol *pb_proto, int route_type) +static inline int qpb__protocol__set(Qpb__Protocol *pb_proto, int route_type) { - switch (route_type) { - case ZEBRA_ROUTE_KERNEL: - *pb_proto = QPB__PROTOCOL__KERNEL; - break; - - case ZEBRA_ROUTE_CONNECT: - *pb_proto = QPB__PROTOCOL__CONNECTED; - break; - - case ZEBRA_ROUTE_STATIC: - *pb_proto = QPB__PROTOCOL__STATIC; - break; - - case ZEBRA_ROUTE_RIP: - *pb_proto = QPB__PROTOCOL__RIP; - break; - - case ZEBRA_ROUTE_RIPNG: - *pb_proto = QPB__PROTOCOL__RIPNG; - break; - - case ZEBRA_ROUTE_OSPF: - case ZEBRA_ROUTE_OSPF6: - *pb_proto = QPB__PROTOCOL__OSPF; - break; - - case ZEBRA_ROUTE_ISIS: - *pb_proto = QPB__PROTOCOL__ISIS; - break; - - case ZEBRA_ROUTE_BGP: - *pb_proto = QPB__PROTOCOL__BGP; - break; - - case ZEBRA_ROUTE_HSLS: - case ZEBRA_ROUTE_OLSR: - case ZEBRA_ROUTE_MAX: - case ZEBRA_ROUTE_SYSTEM: - default: - *pb_proto = QPB__PROTOCOL__OTHER; - } - - return 1; + switch (route_type) { + case ZEBRA_ROUTE_KERNEL: + *pb_proto = QPB__PROTOCOL__KERNEL; + break; + + case ZEBRA_ROUTE_CONNECT: + *pb_proto = QPB__PROTOCOL__CONNECTED; + break; + + case ZEBRA_ROUTE_STATIC: + *pb_proto = QPB__PROTOCOL__STATIC; + break; + + case ZEBRA_ROUTE_RIP: + *pb_proto = QPB__PROTOCOL__RIP; + break; + + case ZEBRA_ROUTE_RIPNG: + *pb_proto = QPB__PROTOCOL__RIPNG; + break; + + case ZEBRA_ROUTE_OSPF: + case ZEBRA_ROUTE_OSPF6: + *pb_proto = QPB__PROTOCOL__OSPF; + break; + + case ZEBRA_ROUTE_ISIS: + *pb_proto = QPB__PROTOCOL__ISIS; + break; + + case ZEBRA_ROUTE_BGP: + *pb_proto = QPB__PROTOCOL__BGP; + break; + + case ZEBRA_ROUTE_HSLS: + case ZEBRA_ROUTE_OLSR: + case ZEBRA_ROUTE_MAX: + case ZEBRA_ROUTE_SYSTEM: + default: + *pb_proto = QPB__PROTOCOL__OTHER; + } + + return 1; } /* * qpb__ipv4_address__create */ static inline Qpb__Ipv4Address * -qpb__ipv4_address__create (qpb_allocator_t *allocator, - struct in_addr *addr) +qpb__ipv4_address__create(qpb_allocator_t *allocator, struct in_addr *addr) { - Qpb__Ipv4Address *v4; + Qpb__Ipv4Address *v4; - v4 = QPB_ALLOC(allocator, typeof(*v4)); - if (!v4) { - return NULL; - } - qpb__ipv4_address__init(v4); + v4 = QPB_ALLOC(allocator, typeof(*v4)); + if (!v4) { + return NULL; + } + qpb__ipv4_address__init(v4); - v4->value = ntohl(addr->s_addr); - return v4; + v4->value = ntohl(addr->s_addr); + return v4; } /* * qpb__ipv4_address__get */ -static inline int -qpb__ipv4_address__get (const Qpb__Ipv4Address *v4, struct in_addr *addr) +static inline int qpb__ipv4_address__get(const Qpb__Ipv4Address *v4, + struct in_addr *addr) { - addr->s_addr = htonl(v4->value); - return 1; + addr->s_addr = htonl(v4->value); + return 1; } /* * qpb__ipv6_address__create */ static inline Qpb__Ipv6Address * -qpb__ipv6_address__create (qpb_allocator_t *allocator, struct in6_addr *addr) +qpb__ipv6_address__create(qpb_allocator_t *allocator, struct in6_addr *addr) { - Qpb__Ipv6Address *v6; + Qpb__Ipv6Address *v6; - v6 = QPB_ALLOC(allocator, typeof(*v6)); - if (!v6) - return NULL; + v6 = QPB_ALLOC(allocator, typeof(*v6)); + if (!v6) + return NULL; - qpb__ipv6_address__init(v6); - v6->bytes.len = 16; - v6->bytes.data = qpb_alloc(allocator, 16); - if (!v6->bytes.data) - return NULL; + qpb__ipv6_address__init(v6); + v6->bytes.len = 16; + v6->bytes.data = qpb_alloc(allocator, 16); + if (!v6->bytes.data) + return NULL; - memcpy(v6->bytes.data, addr->s6_addr, v6->bytes.len); - return v6; + memcpy(v6->bytes.data, addr->s6_addr, v6->bytes.len); + return v6; } /* @@ -250,14 +246,14 @@ qpb__ipv6_address__create (qpb_allocator_t *allocator, struct in6_addr *addr) * * Read out information from a protobuf ipv6 address structure. */ -static inline int -qpb__ipv6_address__get (const Qpb__Ipv6Address *v6, struct in6_addr *addr) +static inline int qpb__ipv6_address__get(const Qpb__Ipv6Address *v6, + struct in6_addr *addr) { - if (v6->bytes.len != 16) - return 0; + if (v6->bytes.len != 16) + return 0; - memcpy(addr->s6_addr, v6->bytes.data, v6->bytes.len); - return 1; + memcpy(addr->s6_addr, v6->bytes.data, v6->bytes.len); + return 1; } /* @@ -265,34 +261,34 @@ qpb__ipv6_address__get (const Qpb__Ipv6Address *v6, struct in6_addr *addr) */ #define qpb_l3_address_create qpb__l3_address__create static inline Qpb__L3Address * -qpb__l3_address__create (qpb_allocator_t *allocator, union g_addr *addr, - u_char family) +qpb__l3_address__create(qpb_allocator_t *allocator, union g_addr *addr, + u_char family) { - Qpb__L3Address *l3_addr; + Qpb__L3Address *l3_addr; - l3_addr = QPB_ALLOC(allocator, typeof(*l3_addr)); - if (!l3_addr) - return NULL; + l3_addr = QPB_ALLOC(allocator, typeof(*l3_addr)); + if (!l3_addr) + return NULL; - qpb__l3_address__init(l3_addr); + qpb__l3_address__init(l3_addr); - switch (family) { + switch (family) { - case AF_INET: - l3_addr->v4 = qpb__ipv4_address__create (allocator, &addr->ipv4); - if (!l3_addr->v4) - return NULL; + case AF_INET: + l3_addr->v4 = qpb__ipv4_address__create(allocator, &addr->ipv4); + if (!l3_addr->v4) + return NULL; - break; + break; - case AF_INET6: - l3_addr->v6 = qpb__ipv6_address__create (allocator, &addr->ipv6); - if (!l3_addr->v6) - return NULL; + case AF_INET6: + l3_addr->v6 = qpb__ipv6_address__create(allocator, &addr->ipv6); + if (!l3_addr->v6) + return NULL; - break; - } - return l3_addr; + break; + } + return l3_addr; } /* @@ -301,25 +297,22 @@ qpb__l3_address__create (qpb_allocator_t *allocator, union g_addr *addr, * Read out a gateway address from a protobuf l3 address. */ #define qpb_l3_address_get qpb__l3_address__get -static inline int -qpb__l3_address__get (const Qpb__L3Address *l3_addr, - u_char *family, union g_addr *addr) +static inline int qpb__l3_address__get(const Qpb__L3Address *l3_addr, + u_char *family, union g_addr *addr) { - if (l3_addr->v4) - { - qpb__ipv4_address__get (l3_addr->v4, &addr->ipv4); - *family = AF_INET; - return 1; - } - - if (l3_addr->v6) - { - qpb__ipv6_address__get(l3_addr->v6, &addr->ipv6); - *family = AF_INET6; - return 1; - } - - return 0; + if (l3_addr->v4) { + qpb__ipv4_address__get(l3_addr->v4, &addr->ipv4); + *family = AF_INET; + return 1; + } + + if (l3_addr->v6) { + qpb__ipv6_address__get(l3_addr->v6, &addr->ipv6); + *family = AF_INET6; + return 1; + } + + return 0; } /* @@ -327,18 +320,18 @@ qpb__l3_address__get (const Qpb__L3Address *l3_addr, */ #define qpb_if_identifier_create qpb__if_identifier__create static inline Qpb__IfIdentifier * -qpb__if_identifier__create (qpb_allocator_t *allocator, uint if_index) +qpb__if_identifier__create(qpb_allocator_t *allocator, uint if_index) { - Qpb__IfIdentifier *if_id; - - if_id = QPB_ALLOC(allocator, typeof(*if_id)); - if (!if_id) { - return NULL; - } - qpb__if_identifier__init(if_id); - if_id->has_index = 1; - if_id->index = if_index; - return if_id; + Qpb__IfIdentifier *if_id; + + if_id = QPB_ALLOC(allocator, typeof(*if_id)); + if (!if_id) { + return NULL; + } + qpb__if_identifier__init(if_id); + if_id->has_index = 1; + if_id->index = if_index; + return if_id; } /* @@ -347,26 +340,25 @@ qpb__if_identifier__create (qpb_allocator_t *allocator, uint if_index) * Get interface name and/or if_index from an if identifier. */ #define qpb_if_identifier_get qpb__if_identifier__get -static inline int -qpb__if_identifier__get (Qpb__IfIdentifier *if_id, uint *if_index, - char **name) +static inline int qpb__if_identifier__get(Qpb__IfIdentifier *if_id, + uint *if_index, char **name) { - char *str; - uint ix; + char *str; + uint ix; - if (!if_index) - if_index = &ix; + if (!if_index) + if_index = &ix; - if (!name) - name = &str; + if (!name) + name = &str; - if (if_id->has_index) - *if_index = if_id->index; - else - *if_index = 0; + if (if_id->has_index) + *if_index = if_id->index; + else + *if_index = 0; - *name = if_id->name; - return 1; + *name = if_id->name; + return 1; } #endif diff --git a/qpb/qpb_allocator.c b/qpb/qpb_allocator.c index ae48d5589..8b0ee941a 100644 --- a/qpb/qpb_allocator.c +++ b/qpb/qpb_allocator.c @@ -29,38 +29,30 @@ /* * _qpb_alloc */ -static void * -_qpb_alloc (void *allocator_data, size_t size) +static void *_qpb_alloc(void *allocator_data, size_t size) { - return linear_allocator_alloc (allocator_data, size); + return linear_allocator_alloc(allocator_data, size); } /* * _qpb_free */ -static void -_qpb_free (void *allocator_data, void *ptr) +static void _qpb_free(void *allocator_data, void *ptr) { - linear_allocator_free (allocator_data, ptr); + linear_allocator_free(allocator_data, ptr); } -static ProtobufCAllocator allocator_template = { - _qpb_alloc, - _qpb_free, - NULL, - 8192, - NULL -}; +static ProtobufCAllocator allocator_template = {_qpb_alloc, _qpb_free, NULL, + 8192, NULL}; /* * qpb_allocator_init_linear * * Initialize qpb_allocator_t with the given linear allocator. */ -void -qpb_allocator_init_linear (qpb_allocator_t *allocator, - linear_allocator_t *linear_allocator) +void qpb_allocator_init_linear(qpb_allocator_t *allocator, + linear_allocator_t *linear_allocator) { - *allocator = allocator_template; - allocator->allocator_data = linear_allocator; + *allocator = allocator_template; + allocator->allocator_data = linear_allocator; } diff --git a/qpb/qpb_allocator.h b/qpb/qpb_allocator.h index bdf2dc0e7..c9022af71 100644 --- a/qpb/qpb_allocator.h +++ b/qpb/qpb_allocator.h @@ -41,10 +41,9 @@ typedef ProtobufCAllocator qpb_allocator_t; /* * qpb_alloc */ -static inline void * -qpb_alloc (qpb_allocator_t *allocator, size_t size) +static inline void *qpb_alloc(qpb_allocator_t *allocator, size_t size) { - return allocator->alloc (allocator->allocator_data, size); + return allocator->alloc(allocator->allocator_data, size); } /* @@ -52,19 +51,18 @@ qpb_alloc (qpb_allocator_t *allocator, size_t size) * * Allocate space for the specified number of pointers. */ -static inline void * -qpb_alloc_ptr_array (qpb_allocator_t *allocator, size_t num_ptrs) +static inline void *qpb_alloc_ptr_array(qpb_allocator_t *allocator, + size_t num_ptrs) { - return qpb_alloc (allocator, num_ptrs * sizeof (void *)); + return qpb_alloc(allocator, num_ptrs * sizeof(void *)); } /* * qpb_free */ -static inline void -qpb_free (qpb_allocator_t *allocator, void *ptr) +static inline void qpb_free(qpb_allocator_t *allocator, void *ptr) { - allocator->free (allocator->allocator_data, ptr); + allocator->free(allocator->allocator_data, ptr); } /* @@ -74,39 +72,36 @@ qpb_free (qpb_allocator_t *allocator, void *ptr) * incorrect size. It returns enough memory to store the given type, * and evaluates to an appropriately typed pointer. */ -#define QPB_ALLOC(allocator, type) \ - (type *) qpb_alloc(allocator, sizeof(type)) +#define QPB_ALLOC(allocator, type) (type *)qpb_alloc(allocator, sizeof(type)) /* * Externs. */ -extern void qpb_allocator_init_linear (qpb_allocator_t *, - struct linear_allocator_t_ *); +extern void qpb_allocator_init_linear(qpb_allocator_t *, + struct linear_allocator_t_ *); /* * The following macros are for the common case where a qpb allocator * is being used alongside a linear allocator that allocates memory * off of the stack. */ -#define QPB_DECLARE_STACK_ALLOCATOR(allocator, size) \ - qpb_allocator_t allocator; \ - linear_allocator_t lin_ ## allocator; \ - char lin_ ## allocator ## _buf[size] +#define QPB_DECLARE_STACK_ALLOCATOR(allocator, size) \ + qpb_allocator_t allocator; \ + linear_allocator_t lin_##allocator; \ + char lin_##allocator##_buf[size] -#define QPB_INIT_STACK_ALLOCATOR(allocator) \ - do \ - { \ - linear_allocator_init(&(lin_ ## allocator), \ - lin_ ## allocator ## _buf, \ - sizeof(lin_ ## allocator ## _buf)); \ - qpb_allocator_init_linear(&allocator, &(lin_ ## allocator)); \ - } while (0) +#define QPB_INIT_STACK_ALLOCATOR(allocator) \ + do { \ + linear_allocator_init(&(lin_##allocator), \ + lin_##allocator##_buf, \ + sizeof(lin_##allocator##_buf)); \ + qpb_allocator_init_linear(&allocator, &(lin_##allocator)); \ + } while (0) -#define QPB_RESET_STACK_ALLOCATOR(allocator) \ - do \ - { \ - linear_allocator_reset (&(lin_ ## allocator)); \ - } while (0) +#define QPB_RESET_STACK_ALLOCATOR(allocator) \ + do { \ + linear_allocator_reset(&(lin_##allocator)); \ + } while (0) #endif /* _QPB_ALLOCATOR_H_ */ diff --git a/ripd/rip_debug.c b/ripd/rip_debug.c index 04252a85f..b2c80817d 100644 --- a/ripd/rip_debug.c +++ b/ripd/rip_debug.c @@ -34,30 +34,28 @@ DEFUN (show_debugging_rip, DEBUG_STR RIP_STR) { - vty_out (vty, "RIP debugging status:\n"); - - if (IS_RIP_DEBUG_EVENT) - vty_out (vty, " RIP event debugging is on\n"); - - if (IS_RIP_DEBUG_PACKET) - { - if (IS_RIP_DEBUG_SEND && IS_RIP_DEBUG_RECV) - { - vty_out (vty," RIP packet debugging is on\n"); - } - else - { - if (IS_RIP_DEBUG_SEND) - vty_out (vty," RIP packet send debugging is on\n"); - else - vty_out (vty," RIP packet receive debugging is on\n"); + vty_out(vty, "RIP debugging status:\n"); + + if (IS_RIP_DEBUG_EVENT) + vty_out(vty, " RIP event debugging is on\n"); + + if (IS_RIP_DEBUG_PACKET) { + if (IS_RIP_DEBUG_SEND && IS_RIP_DEBUG_RECV) { + vty_out(vty, " RIP packet debugging is on\n"); + } else { + if (IS_RIP_DEBUG_SEND) + vty_out(vty, + " RIP packet send debugging is on\n"); + else + vty_out(vty, + " RIP packet receive debugging is on\n"); + } } - } - if (IS_RIP_DEBUG_ZEBRA) - vty_out (vty, " RIP zebra debugging is on\n"); + if (IS_RIP_DEBUG_ZEBRA) + vty_out(vty, " RIP zebra debugging is on\n"); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_rip_events, @@ -67,8 +65,8 @@ DEFUN (debug_rip_events, RIP_STR "RIP events\n") { - rip_debug_event = RIP_DEBUG_EVENT; - return CMD_WARNING_CONFIG_FAILED; + rip_debug_event = RIP_DEBUG_EVENT; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (debug_rip_packet, @@ -78,10 +76,10 @@ DEFUN (debug_rip_packet, RIP_STR "RIP packet\n") { - rip_debug_packet = RIP_DEBUG_PACKET; - rip_debug_packet |= RIP_DEBUG_SEND; - rip_debug_packet |= RIP_DEBUG_RECV; - return CMD_SUCCESS; + rip_debug_packet = RIP_DEBUG_PACKET; + rip_debug_packet |= RIP_DEBUG_SEND; + rip_debug_packet |= RIP_DEBUG_RECV; + return CMD_SUCCESS; } DEFUN (debug_rip_packet_direct, @@ -93,13 +91,17 @@ DEFUN (debug_rip_packet_direct, "RIP receive packet\n" "RIP send packet\n") { - int idx_recv_send = 3; - rip_debug_packet |= RIP_DEBUG_PACKET; - if (strncmp ("send", argv[idx_recv_send]->arg, strlen (argv[idx_recv_send]->arg)) == 0) - rip_debug_packet |= RIP_DEBUG_SEND; - if (strncmp ("recv", argv[idx_recv_send]->arg, strlen (argv[idx_recv_send]->arg)) == 0) - rip_debug_packet |= RIP_DEBUG_RECV; - return CMD_SUCCESS; + int idx_recv_send = 3; + rip_debug_packet |= RIP_DEBUG_PACKET; + if (strncmp("send", argv[idx_recv_send]->arg, + strlen(argv[idx_recv_send]->arg)) + == 0) + rip_debug_packet |= RIP_DEBUG_SEND; + if (strncmp("recv", argv[idx_recv_send]->arg, + strlen(argv[idx_recv_send]->arg)) + == 0) + rip_debug_packet |= RIP_DEBUG_RECV; + return CMD_SUCCESS; } DEFUN (debug_rip_zebra, @@ -109,8 +111,8 @@ DEFUN (debug_rip_zebra, RIP_STR "RIP and ZEBRA communication\n") { - rip_debug_zebra = RIP_DEBUG_ZEBRA; - return CMD_WARNING_CONFIG_FAILED; + rip_debug_zebra = RIP_DEBUG_ZEBRA; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (no_debug_rip_events, @@ -121,8 +123,8 @@ DEFUN (no_debug_rip_events, RIP_STR "RIP events\n") { - rip_debug_event = 0; - return CMD_SUCCESS; + rip_debug_event = 0; + return CMD_SUCCESS; } DEFUN (no_debug_rip_packet, @@ -133,8 +135,8 @@ DEFUN (no_debug_rip_packet, RIP_STR "RIP packet\n") { - rip_debug_packet = 0; - return CMD_SUCCESS; + rip_debug_packet = 0; + return CMD_SUCCESS; } DEFUN (no_debug_rip_packet_direct, @@ -147,22 +149,23 @@ DEFUN (no_debug_rip_packet_direct, "RIP option set for receive packet\n" "RIP option set for send packet\n") { - int idx_recv_send = 4; - if (strncmp ("send", argv[idx_recv_send]->arg, strlen (argv[idx_recv_send]->arg)) == 0) - { - if (IS_RIP_DEBUG_RECV) - rip_debug_packet &= ~RIP_DEBUG_SEND; - else - rip_debug_packet = 0; - } - else if (strncmp ("recv", argv[idx_recv_send]->arg, strlen (argv[idx_recv_send]->arg)) == 0) - { - if (IS_RIP_DEBUG_SEND) - rip_debug_packet &= ~RIP_DEBUG_RECV; - else - rip_debug_packet = 0; - } - return CMD_SUCCESS; + int idx_recv_send = 4; + if (strncmp("send", argv[idx_recv_send]->arg, + strlen(argv[idx_recv_send]->arg)) + == 0) { + if (IS_RIP_DEBUG_RECV) + rip_debug_packet &= ~RIP_DEBUG_SEND; + else + rip_debug_packet = 0; + } else if (strncmp("recv", argv[idx_recv_send]->arg, + strlen(argv[idx_recv_send]->arg)) + == 0) { + if (IS_RIP_DEBUG_SEND) + rip_debug_packet &= ~RIP_DEBUG_RECV; + else + rip_debug_packet = 0; + } + return CMD_SUCCESS; } DEFUN (no_debug_rip_zebra, @@ -173,85 +176,73 @@ DEFUN (no_debug_rip_zebra, RIP_STR "RIP and ZEBRA communication\n") { - rip_debug_zebra = 0; - return CMD_WARNING_CONFIG_FAILED; + rip_debug_zebra = 0; + return CMD_WARNING_CONFIG_FAILED; } /* Debug node. */ -static struct cmd_node debug_node = -{ - DEBUG_NODE, - "", /* Debug node has no interface. */ - 1 -}; +static struct cmd_node debug_node = {DEBUG_NODE, + "", /* Debug node has no interface. */ + 1}; -static int -config_write_debug (struct vty *vty) +static int config_write_debug(struct vty *vty) { - int write = 0; + int write = 0; - if (IS_RIP_DEBUG_EVENT) - { - vty_out (vty, "debug rip events\n"); - write++; - } - if (IS_RIP_DEBUG_PACKET) - { - if (IS_RIP_DEBUG_SEND && IS_RIP_DEBUG_RECV) - { - vty_out (vty,"debug rip packet\n"); - write++; + if (IS_RIP_DEBUG_EVENT) { + vty_out(vty, "debug rip events\n"); + write++; } - else - { - if (IS_RIP_DEBUG_SEND) - vty_out (vty,"debug rip packet send\n"); - else - vty_out (vty,"debug rip packet recv\n"); - write++; + if (IS_RIP_DEBUG_PACKET) { + if (IS_RIP_DEBUG_SEND && IS_RIP_DEBUG_RECV) { + vty_out(vty, "debug rip packet\n"); + write++; + } else { + if (IS_RIP_DEBUG_SEND) + vty_out(vty, "debug rip packet send\n"); + else + vty_out(vty, "debug rip packet recv\n"); + write++; + } } - } - if (IS_RIP_DEBUG_ZEBRA) - { - vty_out (vty, "debug rip zebra\n"); - write++; - } - return write; + if (IS_RIP_DEBUG_ZEBRA) { + vty_out(vty, "debug rip zebra\n"); + write++; + } + return write; } -void -rip_debug_reset (void) +void rip_debug_reset(void) { - rip_debug_event = 0; - rip_debug_packet = 0; - rip_debug_zebra = 0; + rip_debug_event = 0; + rip_debug_packet = 0; + rip_debug_zebra = 0; } -void -rip_debug_init (void) +void rip_debug_init(void) { - rip_debug_event = 0; - rip_debug_packet = 0; - rip_debug_zebra = 0; - - install_node (&debug_node, config_write_debug); - - install_element (ENABLE_NODE, &show_debugging_rip_cmd); - install_element (ENABLE_NODE, &debug_rip_events_cmd); - install_element (ENABLE_NODE, &debug_rip_packet_cmd); - install_element (ENABLE_NODE, &debug_rip_packet_direct_cmd); - install_element (ENABLE_NODE, &debug_rip_zebra_cmd); - install_element (ENABLE_NODE, &no_debug_rip_events_cmd); - install_element (ENABLE_NODE, &no_debug_rip_packet_cmd); - install_element (ENABLE_NODE, &no_debug_rip_packet_direct_cmd); - install_element (ENABLE_NODE, &no_debug_rip_zebra_cmd); - - install_element (CONFIG_NODE, &debug_rip_events_cmd); - install_element (CONFIG_NODE, &debug_rip_packet_cmd); - install_element (CONFIG_NODE, &debug_rip_packet_direct_cmd); - install_element (CONFIG_NODE, &debug_rip_zebra_cmd); - install_element (CONFIG_NODE, &no_debug_rip_events_cmd); - install_element (CONFIG_NODE, &no_debug_rip_packet_cmd); - install_element (CONFIG_NODE, &no_debug_rip_packet_direct_cmd); - install_element (CONFIG_NODE, &no_debug_rip_zebra_cmd); + rip_debug_event = 0; + rip_debug_packet = 0; + rip_debug_zebra = 0; + + install_node(&debug_node, config_write_debug); + + install_element(ENABLE_NODE, &show_debugging_rip_cmd); + install_element(ENABLE_NODE, &debug_rip_events_cmd); + install_element(ENABLE_NODE, &debug_rip_packet_cmd); + install_element(ENABLE_NODE, &debug_rip_packet_direct_cmd); + install_element(ENABLE_NODE, &debug_rip_zebra_cmd); + install_element(ENABLE_NODE, &no_debug_rip_events_cmd); + install_element(ENABLE_NODE, &no_debug_rip_packet_cmd); + install_element(ENABLE_NODE, &no_debug_rip_packet_direct_cmd); + install_element(ENABLE_NODE, &no_debug_rip_zebra_cmd); + + install_element(CONFIG_NODE, &debug_rip_events_cmd); + install_element(CONFIG_NODE, &debug_rip_packet_cmd); + install_element(CONFIG_NODE, &debug_rip_packet_direct_cmd); + install_element(CONFIG_NODE, &debug_rip_zebra_cmd); + install_element(CONFIG_NODE, &no_debug_rip_events_cmd); + install_element(CONFIG_NODE, &no_debug_rip_packet_cmd); + install_element(CONFIG_NODE, &no_debug_rip_packet_direct_cmd); + install_element(CONFIG_NODE, &no_debug_rip_zebra_cmd); } diff --git a/ripd/rip_debug.h b/ripd/rip_debug.h index e1dcd2fa7..c3b15d2e1 100644 --- a/ripd/rip_debug.h +++ b/ripd/rip_debug.h @@ -46,7 +46,7 @@ extern unsigned long rip_debug_event; extern unsigned long rip_debug_packet; extern unsigned long rip_debug_zebra; -extern void rip_debug_init (void); -extern void rip_debug_reset (void); +extern void rip_debug_init(void); +extern void rip_debug_reset(void); #endif /* _ZEBRA_RIP_DEBUG_H */ diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 357856e1e..a17047112 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -41,25 +41,22 @@ #include "ripd/rip_debug.h" #include "ripd/rip_interface.h" -DEFINE_HOOK(rip_ifaddr_add, (struct connected *ifc), (ifc)) -DEFINE_HOOK(rip_ifaddr_del, (struct connected *ifc), (ifc)) +DEFINE_HOOK(rip_ifaddr_add, (struct connected * ifc), (ifc)) +DEFINE_HOOK(rip_ifaddr_del, (struct connected * ifc), (ifc)) /* static prototypes */ -static void rip_enable_apply (struct interface *); -static void rip_passive_interface_apply (struct interface *); +static void rip_enable_apply(struct interface *); +static void rip_passive_interface_apply(struct interface *); static int rip_if_down(struct interface *ifp); -static int rip_enable_if_lookup (const char *ifname); -static int rip_enable_network_lookup2 (struct connected *connected); -static void rip_enable_apply_all (void); +static int rip_enable_if_lookup(const char *ifname); +static int rip_enable_network_lookup2(struct connected *connected); +static void rip_enable_apply_all(void); -const struct message ri_version_msg[] = -{ - {RI_RIP_VERSION_1, "1"}, - {RI_RIP_VERSION_2, "2"}, - {RI_RIP_VERSION_1_AND_2, "1 2"}, - {RI_RIP_VERSION_NONE, "none"}, - { 0 } -}; +const struct message ri_version_msg[] = {{RI_RIP_VERSION_1, "1"}, + {RI_RIP_VERSION_2, "2"}, + {RI_RIP_VERSION_1_AND_2, "1 2"}, + {RI_RIP_VERSION_NONE, "none"}, + {0}}; extern struct zebra_privs_t ripd_privs; @@ -70,167 +67,158 @@ vector rip_enable_interface; struct route_table *rip_enable_network; /* Vector to store passive-interface name. */ -static int passive_default; /* are we in passive-interface default mode? */ +static int passive_default; /* are we in passive-interface default mode? */ vector Vrip_passive_nondefault; /* Join to the RIP version 2 multicast group. */ -static int -ipv4_multicast_join (int sock, - struct in_addr group, - struct in_addr ifa, - ifindex_t ifindex) +static int ipv4_multicast_join(int sock, struct in_addr group, + struct in_addr ifa, ifindex_t ifindex) { - int ret; + int ret; - ret = setsockopt_ipv4_multicast (sock, - IP_ADD_MEMBERSHIP, - ifa, - group.s_addr, - ifindex); + ret = setsockopt_ipv4_multicast(sock, IP_ADD_MEMBERSHIP, ifa, + group.s_addr, ifindex); - if (ret < 0) - zlog_info("can't setsockopt IP_ADD_MEMBERSHIP %s", safe_strerror(errno)); + if (ret < 0) + zlog_info("can't setsockopt IP_ADD_MEMBERSHIP %s", + safe_strerror(errno)); - return ret; + return ret; } /* Leave from the RIP version 2 multicast group. */ -static int -ipv4_multicast_leave (int sock, - struct in_addr group, - struct in_addr ifa, - ifindex_t ifindex) +static int ipv4_multicast_leave(int sock, struct in_addr group, + struct in_addr ifa, ifindex_t ifindex) { - int ret; + int ret; - ret = setsockopt_ipv4_multicast (sock, - IP_DROP_MEMBERSHIP, - ifa, - group.s_addr, - ifindex); + ret = setsockopt_ipv4_multicast(sock, IP_DROP_MEMBERSHIP, ifa, + group.s_addr, ifindex); - if (ret < 0) - zlog_info("can't setsockopt IP_DROP_MEMBERSHIP"); + if (ret < 0) + zlog_info("can't setsockopt IP_DROP_MEMBERSHIP"); - return ret; + return ret; } -static void rip_interface_reset (struct rip_interface *); +static void rip_interface_reset(struct rip_interface *); /* Allocate new RIP's interface configuration. */ -static struct rip_interface * -rip_interface_new (void) +static struct rip_interface *rip_interface_new(void) { - struct rip_interface *ri; + struct rip_interface *ri; - ri = XCALLOC (MTYPE_RIP_INTERFACE, sizeof (struct rip_interface)); + ri = XCALLOC(MTYPE_RIP_INTERFACE, sizeof(struct rip_interface)); - rip_interface_reset (ri); + rip_interface_reset(ri); - return ri; + return ri; } -void -rip_interface_multicast_set (int sock, struct connected *connected) +void rip_interface_multicast_set(int sock, struct connected *connected) { - struct in_addr addr; + struct in_addr addr; - assert (connected != NULL); + assert(connected != NULL); - addr = CONNECTED_ID(connected)->u.prefix4; + addr = CONNECTED_ID(connected)->u.prefix4; + + if (setsockopt_ipv4_multicast_if(sock, addr, connected->ifp->ifindex) + < 0) { + zlog_warn( + "Can't setsockopt IP_MULTICAST_IF on fd %d to " + "ifindex %d for interface %s", + sock, connected->ifp->ifindex, connected->ifp->name); + } - if (setsockopt_ipv4_multicast_if (sock, addr, connected->ifp->ifindex) < 0) - { - zlog_warn ("Can't setsockopt IP_MULTICAST_IF on fd %d to " - "ifindex %d for interface %s", - sock, connected->ifp->ifindex, - connected->ifp->name); - } - - return; + return; } /* Send RIP request packet to specified interface. */ -static void -rip_request_interface_send (struct interface *ifp, u_char version) +static void rip_request_interface_send(struct interface *ifp, u_char version) { - struct sockaddr_in to; + struct sockaddr_in to; - /* RIPv2 support multicast. */ - if (version == RIPv2 && if_is_multicast (ifp)) - { - - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("multicast request on %s", ifp->name); + /* RIPv2 support multicast. */ + if (version == RIPv2 && if_is_multicast(ifp)) { - rip_request_send (NULL, ifp, version, NULL); - return; - } + if (IS_RIP_DEBUG_EVENT) + zlog_debug("multicast request on %s", ifp->name); - /* RIPv1 and non multicast interface. */ - if (if_is_pointopoint (ifp) || if_is_broadcast (ifp)) - { - struct listnode *cnode, *cnnode; - struct connected *connected; - - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("broadcast request to %s", ifp->name); + rip_request_send(NULL, ifp, version, NULL); + return; + } - for (ALL_LIST_ELEMENTS (ifp->connected, cnode, cnnode, connected)) - { - if (connected->address->family == AF_INET) - { - memset (&to, 0, sizeof (struct sockaddr_in)); - to.sin_port = htons (RIP_PORT_DEFAULT); - if (connected->destination) - /* use specified broadcast or peer destination addr */ - to.sin_addr = connected->destination->u.prefix4; - else if (connected->address->prefixlen < IPV4_MAX_PREFIXLEN) - /* calculate the appropriate broadcast address */ - to.sin_addr.s_addr = - ipv4_broadcast_addr(connected->address->u.prefix4.s_addr, - connected->address->prefixlen); - else - /* do not know where to send the packet */ - continue; - - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("SEND request to %s", inet_ntoa (to.sin_addr)); - - rip_request_send (&to, ifp, version, connected); - } + /* RIPv1 and non multicast interface. */ + if (if_is_pointopoint(ifp) || if_is_broadcast(ifp)) { + struct listnode *cnode, *cnnode; + struct connected *connected; + + if (IS_RIP_DEBUG_EVENT) + zlog_debug("broadcast request to %s", ifp->name); + + for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, + connected)) { + if (connected->address->family == AF_INET) { + memset(&to, 0, sizeof(struct sockaddr_in)); + to.sin_port = htons(RIP_PORT_DEFAULT); + if (connected->destination) + /* use specified broadcast or peer + * destination addr */ + to.sin_addr = connected->destination->u + .prefix4; + else if (connected->address->prefixlen + < IPV4_MAX_PREFIXLEN) + /* calculate the appropriate broadcast + * address */ + to.sin_addr + .s_addr = ipv4_broadcast_addr( + connected->address->u.prefix4 + .s_addr, + connected->address->prefixlen); + else + /* do not know where to send the packet + */ + continue; + + if (IS_RIP_DEBUG_EVENT) + zlog_debug("SEND request to %s", + inet_ntoa(to.sin_addr)); + + rip_request_send(&to, ifp, version, connected); + } + } } - } } /* This will be executed when interface goes up. */ -static void -rip_request_interface (struct interface *ifp) +static void rip_request_interface(struct interface *ifp) { - struct rip_interface *ri; + struct rip_interface *ri; - /* In default ripd doesn't send RIP_REQUEST to the loopback interface. */ - if (if_is_loopback (ifp)) - return; + /* In default ripd doesn't send RIP_REQUEST to the loopback interface. + */ + if (if_is_loopback(ifp)) + return; - /* If interface is down, don't send RIP packet. */ - if (! if_is_operative (ifp)) - return; + /* If interface is down, don't send RIP packet. */ + if (!if_is_operative(ifp)) + return; - /* Fetch RIP interface information. */ - ri = ifp->info; + /* Fetch RIP interface information. */ + ri = ifp->info; - /* If there is no version configuration in the interface, - use rip's version setting. */ - { - int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ? - rip->version_send : ri->ri_send); - if (vsend & RIPv1) - rip_request_interface_send (ifp, RIPv1); - if (vsend & RIPv2) - rip_request_interface_send (ifp, RIPv2); - } + /* If there is no version configuration in the interface, + use rip's version setting. */ + { + int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ? rip->version_send + : ri->ri_send); + if (vsend & RIPv1) + rip_request_interface_send(ifp, RIPv1); + if (vsend & RIPv2) + rip_request_interface_send(ifp, RIPv2); + } } #if 0 @@ -267,949 +255,892 @@ rip_request_neighbor_all (void) #endif /* Multicast packet receive socket. */ -static int -rip_multicast_join (struct interface *ifp, int sock) +static int rip_multicast_join(struct interface *ifp, int sock) { - struct listnode *cnode; - struct connected *ifc; + struct listnode *cnode; + struct connected *ifc; - if (if_is_operative (ifp) && if_is_multicast (ifp)) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("multicast join at %s", ifp->name); + if (if_is_operative(ifp) && if_is_multicast(ifp)) { + if (IS_RIP_DEBUG_EVENT) + zlog_debug("multicast join at %s", ifp->name); - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, ifc)) - { - struct prefix_ipv4 *p; - struct in_addr group; - - p = (struct prefix_ipv4 *) ifc->address; - - if (p->family != AF_INET) - continue; - - group.s_addr = htonl (INADDR_RIP_GROUP); - if (ipv4_multicast_join (sock, group, p->prefix, ifp->ifindex) < 0) - return -1; - else - return 0; + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, ifc)) { + struct prefix_ipv4 *p; + struct in_addr group; + + p = (struct prefix_ipv4 *)ifc->address; + + if (p->family != AF_INET) + continue; + + group.s_addr = htonl(INADDR_RIP_GROUP); + if (ipv4_multicast_join(sock, group, p->prefix, + ifp->ifindex) + < 0) + return -1; + else + return 0; + } } - } - return 0; + return 0; } /* Leave from multicast group. */ -static void -rip_multicast_leave (struct interface *ifp, int sock) +static void rip_multicast_leave(struct interface *ifp, int sock) { - struct listnode *cnode; - struct connected *connected; + struct listnode *cnode; + struct connected *connected; - if (if_is_up (ifp) && if_is_multicast (ifp)) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("multicast leave from %s", ifp->name); + if (if_is_up(ifp) && if_is_multicast(ifp)) { + if (IS_RIP_DEBUG_EVENT) + zlog_debug("multicast leave from %s", ifp->name); - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected)) - { - struct prefix_ipv4 *p; - struct in_addr group; - - p = (struct prefix_ipv4 *) connected->address; - - if (p->family != AF_INET) - continue; - - group.s_addr = htonl (INADDR_RIP_GROUP); - if (ipv4_multicast_leave (sock, group, p->prefix, ifp->ifindex) == 0) - return; - } - } + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) { + struct prefix_ipv4 *p; + struct in_addr group; + + p = (struct prefix_ipv4 *)connected->address; + + if (p->family != AF_INET) + continue; + + group.s_addr = htonl(INADDR_RIP_GROUP); + if (ipv4_multicast_leave(sock, group, p->prefix, + ifp->ifindex) + == 0) + return; + } + } } /* Is there and address on interface that I could use ? */ -static int -rip_if_ipv4_address_check (struct interface *ifp) +static int rip_if_ipv4_address_check(struct interface *ifp) { - struct listnode *nn; - struct connected *connected; - int count = 0; + struct listnode *nn; + struct connected *connected; + int count = 0; - for (ALL_LIST_ELEMENTS_RO (ifp->connected, nn, connected)) - { - struct prefix *p; + for (ALL_LIST_ELEMENTS_RO(ifp->connected, nn, connected)) { + struct prefix *p; - p = connected->address; + p = connected->address; + + if (p->family == AF_INET) + count++; + } - if (p->family == AF_INET) - count++; - } - - return count; + return count; } - - - + /* Does this address belongs to me ? */ -int -if_check_address (struct in_addr addr) -{ - struct listnode *node; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - struct listnode *cnode; - struct connected *connected; - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected)) - { - struct prefix_ipv4 *p; +int if_check_address(struct in_addr addr) +{ + struct listnode *node; + struct interface *ifp; - p = (struct prefix_ipv4 *) connected->address; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + struct listnode *cnode; + struct connected *connected; - if (p->family != AF_INET) - continue; + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) { + struct prefix_ipv4 *p; - if (IPV4_ADDR_CMP (&p->prefix, &addr) == 0) - return 1; + p = (struct prefix_ipv4 *)connected->address; + + if (p->family != AF_INET) + continue; + + if (IPV4_ADDR_CMP(&p->prefix, &addr) == 0) + return 1; + } } - } - return 0; + return 0; } /* Inteface link down message processing. */ -int -rip_interface_down (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +int rip_interface_down(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - struct stream *s; + struct interface *ifp; + struct stream *s; - s = zclient->ibuf; + s = zclient->ibuf; - /* zebra_interface_state_read() updates interface structure in - iflist. */ - ifp = zebra_interface_state_read (s, vrf_id); + /* zebra_interface_state_read() updates interface structure in + iflist. */ + ifp = zebra_interface_state_read(s, vrf_id); - if (ifp == NULL) - return 0; + if (ifp == NULL) + return 0; - rip_if_down(ifp); - - if (IS_RIP_DEBUG_ZEBRA) - zlog_debug ("interface %s index %d flags %llx metric %d mtu %d is down", - ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, - ifp->metric, ifp->mtu); + rip_if_down(ifp); - return 0; + if (IS_RIP_DEBUG_ZEBRA) + zlog_debug( + "interface %s index %d flags %llx metric %d mtu %d is down", + ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, + ifp->metric, ifp->mtu); + + return 0; } /* Inteface link up message processing */ -int -rip_interface_up (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +int rip_interface_up(int command, struct zclient *zclient, zebra_size_t length, + vrf_id_t vrf_id) { - struct interface *ifp; + struct interface *ifp; + + /* zebra_interface_state_read () updates interface structure in + iflist. */ + ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); - /* zebra_interface_state_read () updates interface structure in - iflist. */ - ifp = zebra_interface_state_read (zclient->ibuf, vrf_id); + if (ifp == NULL) + return 0; - if (ifp == NULL) - return 0; + if (IS_RIP_DEBUG_ZEBRA) + zlog_debug( + "interface %s index %d flags %#llx metric %d mtu %d is up", + ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, + ifp->metric, ifp->mtu); - if (IS_RIP_DEBUG_ZEBRA) - zlog_debug ("interface %s index %d flags %#llx metric %d mtu %d is up", - ifp->name, ifp->ifindex, (unsigned long long) ifp->flags, - ifp->metric, ifp->mtu); + /* Check if this interface is RIP enabled or not.*/ + rip_enable_apply(ifp); - /* Check if this interface is RIP enabled or not.*/ - rip_enable_apply (ifp); - - /* Check for a passive interface */ - rip_passive_interface_apply (ifp); + /* Check for a passive interface */ + rip_passive_interface_apply(ifp); - /* Apply distribute list to the all interface. */ - rip_distribute_update_interface (ifp); + /* Apply distribute list to the all interface. */ + rip_distribute_update_interface(ifp); - return 0; + return 0; } /* Inteface addition message from zebra. */ -int -rip_interface_add (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +int rip_interface_add(int command, struct zclient *zclient, zebra_size_t length, + vrf_id_t vrf_id) { - struct interface *ifp; + struct interface *ifp; - ifp = zebra_interface_add_read (zclient->ibuf, vrf_id); + ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); - if (IS_RIP_DEBUG_ZEBRA) - zlog_debug ("interface add %s index %d flags %#llx metric %d mtu %d", - ifp->name, ifp->ifindex, (unsigned long long) ifp->flags, - ifp->metric, ifp->mtu); + if (IS_RIP_DEBUG_ZEBRA) + zlog_debug( + "interface add %s index %d flags %#llx metric %d mtu %d", + ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, + ifp->metric, ifp->mtu); - /* Check if this interface is RIP enabled or not.*/ - rip_enable_apply (ifp); - - /* Check for a passive interface */ - rip_passive_interface_apply (ifp); + /* Check if this interface is RIP enabled or not.*/ + rip_enable_apply(ifp); - /* Apply distribute list to the all interface. */ - rip_distribute_update_interface (ifp); + /* Check for a passive interface */ + rip_passive_interface_apply(ifp); - /* rip_request_neighbor_all (); */ + /* Apply distribute list to the all interface. */ + rip_distribute_update_interface(ifp); - /* Check interface routemap. */ - rip_if_rmap_update_interface (ifp); + /* rip_request_neighbor_all (); */ - return 0; + /* Check interface routemap. */ + rip_if_rmap_update_interface(ifp); + + return 0; } -int -rip_interface_delete (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +int rip_interface_delete(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - struct stream *s; + struct interface *ifp; + struct stream *s; + + s = zclient->ibuf; + /* zebra_interface_state_read() updates interface structure in iflist */ + ifp = zebra_interface_state_read(s, vrf_id); - s = zclient->ibuf; - /* zebra_interface_state_read() updates interface structure in iflist */ - ifp = zebra_interface_state_read (s, vrf_id); + if (ifp == NULL) + return 0; + + if (if_is_up(ifp)) { + rip_if_down(ifp); + } - if (ifp == NULL) - return 0; + zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d", + ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, + ifp->metric, ifp->mtu); - if (if_is_up (ifp)) { - rip_if_down(ifp); - } - - zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d", - ifp->name, ifp->ifindex, (unsigned long long) ifp->flags, - ifp->metric, ifp->mtu); - - /* To support pseudo interface do not free interface structure. */ - /* if_delete(ifp); */ - ifp->ifindex = IFINDEX_DELETED; + /* To support pseudo interface do not free interface structure. */ + /* if_delete(ifp); */ + ifp->ifindex = IFINDEX_DELETED; - return 0; + return 0; } -static void -rip_interface_clean (struct rip_interface *ri) +static void rip_interface_clean(struct rip_interface *ri) { - ri->enable_network = 0; - ri->enable_interface = 0; - ri->running = 0; + ri->enable_network = 0; + ri->enable_interface = 0; + ri->running = 0; - if (ri->t_wakeup) - { - thread_cancel (ri->t_wakeup); - ri->t_wakeup = NULL; - } + if (ri->t_wakeup) { + thread_cancel(ri->t_wakeup); + ri->t_wakeup = NULL; + } } -void -rip_interfaces_clean (void) +void rip_interfaces_clean(void) { - struct listnode *node; - struct interface *ifp; + struct listnode *node; + struct interface *ifp; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - rip_interface_clean (ifp->info); + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) + rip_interface_clean(ifp->info); } -static void -rip_interface_reset (struct rip_interface *ri) +static void rip_interface_reset(struct rip_interface *ri) { - /* Default authentication type is simple password for Cisco - compatibility. */ - ri->auth_type = RIP_NO_AUTH; - ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE; + /* Default authentication type is simple password for Cisco + compatibility. */ + ri->auth_type = RIP_NO_AUTH; + ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE; - /* Set default split-horizon behavior. If the interface is Frame - Relay or SMDS is enabled, the default value for split-horizon is - off. But currently Zebra does detect Frame Relay or SMDS - interface. So all interface is set to split horizon. */ - ri->split_horizon_default = RIP_SPLIT_HORIZON; - ri->split_horizon = ri->split_horizon_default; + /* Set default split-horizon behavior. If the interface is Frame + Relay or SMDS is enabled, the default value for split-horizon is + off. But currently Zebra does detect Frame Relay or SMDS + interface. So all interface is set to split horizon. */ + ri->split_horizon_default = RIP_SPLIT_HORIZON; + ri->split_horizon = ri->split_horizon_default; - ri->ri_send = RI_RIP_UNSPEC; - ri->ri_receive = RI_RIP_UNSPEC; + ri->ri_send = RI_RIP_UNSPEC; + ri->ri_receive = RI_RIP_UNSPEC; - ri->v2_broadcast = 0; + ri->v2_broadcast = 0; - if (ri->auth_str) - { - free (ri->auth_str); - ri->auth_str = NULL; - } - if (ri->key_chain) - { - free (ri->key_chain); - ri->key_chain = NULL; - } + if (ri->auth_str) { + free(ri->auth_str); + ri->auth_str = NULL; + } + if (ri->key_chain) { + free(ri->key_chain); + ri->key_chain = NULL; + } + + ri->list[RIP_FILTER_IN] = NULL; + ri->list[RIP_FILTER_OUT] = NULL; - ri->list[RIP_FILTER_IN] = NULL; - ri->list[RIP_FILTER_OUT] = NULL; + ri->prefix[RIP_FILTER_IN] = NULL; + ri->prefix[RIP_FILTER_OUT] = NULL; - ri->prefix[RIP_FILTER_IN] = NULL; - ri->prefix[RIP_FILTER_OUT] = NULL; + ri->recv_badpackets = 0; + ri->recv_badroutes = 0; + ri->sent_updates = 0; - ri->recv_badpackets = 0; - ri->recv_badroutes = 0; - ri->sent_updates = 0; + ri->passive = 0; - ri->passive = 0; - - rip_interface_clean (ri); + rip_interface_clean(ri); } -void -rip_interfaces_reset (void) +void rip_interfaces_reset(void) { - struct listnode *node; - struct interface *ifp; + struct listnode *node; + struct interface *ifp; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - rip_interface_reset (ifp->info); + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) + rip_interface_reset(ifp->info); } -int -rip_if_down(struct interface *ifp) +int rip_if_down(struct interface *ifp) { - struct route_node *rp; - struct rip_info *rinfo; - struct rip_interface *ri = NULL; - struct list *list = NULL; - struct listnode *listnode = NULL, *nextnode = NULL; - if (rip) - { - for (rp = route_top (rip->table); rp; rp = route_next (rp)) - if ((list = rp->info) != NULL) - for (ALL_LIST_ELEMENTS (list, listnode, nextnode, rinfo)) - if (rinfo->ifindex == ifp->ifindex) - rip_ecmp_delete (rinfo); - - ri = ifp->info; - - if (ri->running) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("turn off %s", ifp->name); - - /* Leave from multicast group. */ - rip_multicast_leave (ifp, rip->sock); - - ri->running = 0; - } - } - - return 0; + struct route_node *rp; + struct rip_info *rinfo; + struct rip_interface *ri = NULL; + struct list *list = NULL; + struct listnode *listnode = NULL, *nextnode = NULL; + if (rip) { + for (rp = route_top(rip->table); rp; rp = route_next(rp)) + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS(list, listnode, nextnode, + rinfo)) + if (rinfo->ifindex == ifp->ifindex) + rip_ecmp_delete(rinfo); + + ri = ifp->info; + + if (ri->running) { + if (IS_RIP_DEBUG_EVENT) + zlog_debug("turn off %s", ifp->name); + + /* Leave from multicast group. */ + rip_multicast_leave(ifp, rip->sock); + + ri->running = 0; + } + } + + return 0; } /* Needed for stop RIP process. */ -void -rip_if_down_all () +void rip_if_down_all() { - struct interface *ifp; - struct listnode *node, *nnode; + struct interface *ifp; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp)) - rip_if_down (ifp); + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), node, nnode, ifp)) + rip_if_down(ifp); } -static void -rip_apply_address_add (struct connected *ifc) +static void rip_apply_address_add(struct connected *ifc) { - struct prefix_ipv4 address; - struct prefix *p; + struct prefix_ipv4 address; + struct prefix *p; - if (!rip) - return; - - if (! if_is_up(ifc->ifp)) - return; + if (!rip) + return; - p = ifc->address; + if (!if_is_up(ifc->ifp)) + return; - memset (&address, 0, sizeof (address)); - address.family = p->family; - address.prefix = p->u.prefix4; - address.prefixlen = p->prefixlen; - apply_mask_ipv4(&address); + p = ifc->address; - /* Check if this interface is RIP enabled or not - or Check if this address's prefix is RIP enabled */ - if ((rip_enable_if_lookup(ifc->ifp->name) >= 0) || - (rip_enable_network_lookup2(ifc) >= 0)) - rip_redistribute_add(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, - &address, ifc->ifp->ifindex, NULL, 0, 0, 0); + memset(&address, 0, sizeof(address)); + address.family = p->family; + address.prefix = p->u.prefix4; + address.prefixlen = p->prefixlen; + apply_mask_ipv4(&address); + /* Check if this interface is RIP enabled or not + or Check if this address's prefix is RIP enabled */ + if ((rip_enable_if_lookup(ifc->ifp->name) >= 0) + || (rip_enable_network_lookup2(ifc) >= 0)) + rip_redistribute_add(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, + &address, ifc->ifp->ifindex, NULL, 0, 0, + 0); } -int -rip_interface_address_add (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +int rip_interface_address_add(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct connected *ifc; - struct prefix *p; + struct connected *ifc; + struct prefix *p; - ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD, - zclient->ibuf, vrf_id); + ifc = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, + zclient->ibuf, vrf_id); - if (ifc == NULL) - return 0; + if (ifc == NULL) + return 0; - p = ifc->address; + p = ifc->address; - if (p->family == AF_INET) - { - if (IS_RIP_DEBUG_ZEBRA) - zlog_debug ("connected address %s/%d is added", - inet_ntoa (p->u.prefix4), p->prefixlen); + if (p->family == AF_INET) { + if (IS_RIP_DEBUG_ZEBRA) + zlog_debug("connected address %s/%d is added", + inet_ntoa(p->u.prefix4), p->prefixlen); - rip_enable_apply(ifc->ifp); - /* Check if this prefix needs to be redistributed */ - rip_apply_address_add(ifc); + rip_enable_apply(ifc->ifp); + /* Check if this prefix needs to be redistributed */ + rip_apply_address_add(ifc); - hook_call(rip_ifaddr_add, ifc); - } + hook_call(rip_ifaddr_add, ifc); + } - return 0; + return 0; } -static void -rip_apply_address_del (struct connected *ifc) { - struct prefix_ipv4 address; - struct prefix *p; +static void rip_apply_address_del(struct connected *ifc) +{ + struct prefix_ipv4 address; + struct prefix *p; - if (!rip) - return; + if (!rip) + return; - if (! if_is_up(ifc->ifp)) - return; + if (!if_is_up(ifc->ifp)) + return; - p = ifc->address; + p = ifc->address; - memset (&address, 0, sizeof (address)); - address.family = p->family; - address.prefix = p->u.prefix4; - address.prefixlen = p->prefixlen; - apply_mask_ipv4(&address); + memset(&address, 0, sizeof(address)); + address.family = p->family; + address.prefix = p->u.prefix4; + address.prefixlen = p->prefixlen; + apply_mask_ipv4(&address); - rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, - &address, ifc->ifp->ifindex); + rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, + &address, ifc->ifp->ifindex); } -int -rip_interface_address_delete (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +int rip_interface_address_delete(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct connected *ifc; - struct prefix *p; - - ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE, - zclient->ibuf, vrf_id); - - if (ifc) - { - p = ifc->address; - if (p->family == AF_INET) - { - if (IS_RIP_DEBUG_ZEBRA) - zlog_debug ("connected address %s/%d is deleted", - inet_ntoa (p->u.prefix4), p->prefixlen); + struct connected *ifc; + struct prefix *p; - hook_call(rip_ifaddr_del, ifc); + ifc = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, + zclient->ibuf, vrf_id); - /* Chech wether this prefix needs to be removed */ - rip_apply_address_del(ifc); + if (ifc) { + p = ifc->address; + if (p->family == AF_INET) { + if (IS_RIP_DEBUG_ZEBRA) + zlog_debug("connected address %s/%d is deleted", + inet_ntoa(p->u.prefix4), + p->prefixlen); - } + hook_call(rip_ifaddr_del, ifc); - connected_free (ifc); + /* Chech wether this prefix needs to be removed */ + rip_apply_address_del(ifc); + } - } + connected_free(ifc); + } - return 0; + return 0; } /* Check interface is enabled by network statement. */ /* Check wether the interface has at least a connected prefix that * is within the ripng_enable_network table. */ -static int -rip_enable_network_lookup_if (struct interface *ifp) -{ - struct listnode *node, *nnode; - struct connected *connected; - struct prefix_ipv4 address; - - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected)) - { - struct prefix *p; - struct route_node *node; - - p = connected->address; - - if (p->family == AF_INET) - { - address.family = AF_INET; - address.prefix = p->u.prefix4; - address.prefixlen = IPV4_MAX_BITLEN; - - node = route_node_match (rip_enable_network, - (struct prefix *)&address); - if (node) - { - route_unlock_node (node); - return 1; - } - } - } - return -1; +static int rip_enable_network_lookup_if(struct interface *ifp) +{ + struct listnode *node, *nnode; + struct connected *connected; + struct prefix_ipv4 address; + + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) { + struct prefix *p; + struct route_node *node; + + p = connected->address; + + if (p->family == AF_INET) { + address.family = AF_INET; + address.prefix = p->u.prefix4; + address.prefixlen = IPV4_MAX_BITLEN; + + node = route_node_match(rip_enable_network, + (struct prefix *)&address); + if (node) { + route_unlock_node(node); + return 1; + } + } + } + return -1; } /* Check wether connected is within the ripng_enable_network table. */ -int -rip_enable_network_lookup2 (struct connected *connected) +int rip_enable_network_lookup2(struct connected *connected) { - struct prefix_ipv4 address; - struct prefix *p; + struct prefix_ipv4 address; + struct prefix *p; - p = connected->address; + p = connected->address; - if (p->family == AF_INET) { - struct route_node *node; + if (p->family == AF_INET) { + struct route_node *node; - address.family = p->family; - address.prefix = p->u.prefix4; - address.prefixlen = IPV4_MAX_BITLEN; + address.family = p->family; + address.prefix = p->u.prefix4; + address.prefixlen = IPV4_MAX_BITLEN; - /* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within rip_enable_network */ - node = route_node_match (rip_enable_network, - (struct prefix *)&address); + /* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within + * rip_enable_network */ + node = route_node_match(rip_enable_network, + (struct prefix *)&address); - if (node) { - route_unlock_node (node); - return 1; - } - } + if (node) { + route_unlock_node(node); + return 1; + } + } - return -1; + return -1; } /* Add RIP enable network. */ -static int -rip_enable_network_add (struct prefix *p) +static int rip_enable_network_add(struct prefix *p) { - struct route_node *node; + struct route_node *node; - node = route_node_get (rip_enable_network, p); + node = route_node_get(rip_enable_network, p); - if (node->info) - { - route_unlock_node (node); - return -1; - } - else - node->info = (void *)1; + if (node->info) { + route_unlock_node(node); + return -1; + } else + node->info = (void *)1; - /* XXX: One should find a better solution than a generic one */ - rip_enable_apply_all(); + /* XXX: One should find a better solution than a generic one */ + rip_enable_apply_all(); - return 1; + return 1; } /* Delete RIP enable network. */ -static int -rip_enable_network_delete (struct prefix *p) +static int rip_enable_network_delete(struct prefix *p) { - struct route_node *node; + struct route_node *node; - node = route_node_lookup (rip_enable_network, p); - if (node) - { - node->info = NULL; + node = route_node_lookup(rip_enable_network, p); + if (node) { + node->info = NULL; - /* Unlock info lock. */ - route_unlock_node (node); + /* Unlock info lock. */ + route_unlock_node(node); - /* Unlock lookup lock. */ - route_unlock_node (node); + /* Unlock lookup lock. */ + route_unlock_node(node); - /* XXX: One should find a better solution than a generic one */ - rip_enable_apply_all (); + /* XXX: One should find a better solution than a generic one */ + rip_enable_apply_all(); - return 1; - } - return -1; + return 1; + } + return -1; } /* Check interface is enabled by ifname statement. */ -static int -rip_enable_if_lookup (const char *ifname) +static int rip_enable_if_lookup(const char *ifname) { - unsigned int i; - char *str; + unsigned int i; + char *str; - for (i = 0; i < vector_active (rip_enable_interface); i++) - if ((str = vector_slot (rip_enable_interface, i)) != NULL) - if (strcmp (str, ifname) == 0) - return i; - return -1; + for (i = 0; i < vector_active(rip_enable_interface); i++) + if ((str = vector_slot(rip_enable_interface, i)) != NULL) + if (strcmp(str, ifname) == 0) + return i; + return -1; } /* Add interface to rip_enable_if. */ -static int -rip_enable_if_add (const char *ifname) +static int rip_enable_if_add(const char *ifname) { - int ret; + int ret; - ret = rip_enable_if_lookup (ifname); - if (ret >= 0) - return -1; + ret = rip_enable_if_lookup(ifname); + if (ret >= 0) + return -1; - vector_set (rip_enable_interface, strdup (ifname)); + vector_set(rip_enable_interface, strdup(ifname)); - rip_enable_apply_all(); /* TODOVJ */ + rip_enable_apply_all(); /* TODOVJ */ - return 1; + return 1; } /* Delete interface from rip_enable_if. */ -static int -rip_enable_if_delete (const char *ifname) +static int rip_enable_if_delete(const char *ifname) { - int index; - char *str; + int index; + char *str; - index = rip_enable_if_lookup (ifname); - if (index < 0) - return -1; + index = rip_enable_if_lookup(ifname); + if (index < 0) + return -1; - str = vector_slot (rip_enable_interface, index); - free (str); - vector_unset (rip_enable_interface, index); + str = vector_slot(rip_enable_interface, index); + free(str); + vector_unset(rip_enable_interface, index); - rip_enable_apply_all(); /* TODOVJ */ + rip_enable_apply_all(); /* TODOVJ */ - return 1; + return 1; } /* Join to multicast group and send request to the interface. */ -static int -rip_interface_wakeup (struct thread *t) +static int rip_interface_wakeup(struct thread *t) { - struct interface *ifp; - struct rip_interface *ri; - - /* Get interface. */ - ifp = THREAD_ARG (t); - - ri = ifp->info; - ri->t_wakeup = NULL; + struct interface *ifp; + struct rip_interface *ri; - /* Join to multicast group. */ - if (rip_multicast_join (ifp, rip->sock) < 0) - { - zlog_err ("multicast join failed, interface %s not running", ifp->name); - return 0; - } + /* Get interface. */ + ifp = THREAD_ARG(t); - /* Set running flag. */ - ri->running = 1; + ri = ifp->info; + ri->t_wakeup = NULL; - /* Send RIP request to the interface. */ - rip_request_interface (ifp); - - return 0; -} + /* Join to multicast group. */ + if (rip_multicast_join(ifp, rip->sock) < 0) { + zlog_err("multicast join failed, interface %s not running", + ifp->name); + return 0; + } -static void -rip_connect_set (struct interface *ifp, int set) -{ - struct listnode *node, *nnode; - struct connected *connected; - struct prefix_ipv4 address; - - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected)) - { - struct prefix *p; - p = connected->address; - - if (p->family != AF_INET) - continue; - - address.family = AF_INET; - address.prefix = p->u.prefix4; - address.prefixlen = p->prefixlen; - apply_mask_ipv4 (&address); - - if (set) { - /* Check once more wether this prefix is within a "network IF_OR_PREF" one */ - if ((rip_enable_if_lookup(connected->ifp->name) >= 0) || - (rip_enable_network_lookup2(connected) >= 0)) - rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, - &address, connected->ifp->ifindex, - NULL, 0, 0, 0); - } else - { - rip_redistribute_delete (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, - &address, connected->ifp->ifindex); - if (rip_redistribute_check (ZEBRA_ROUTE_CONNECT)) - rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_REDISTRIBUTE, - &address, connected->ifp->ifindex, - NULL, 0, 0, 0); - } - } + /* Set running flag. */ + ri->running = 1; + + /* Send RIP request to the interface. */ + rip_request_interface(ifp); + + return 0; +} + +static void rip_connect_set(struct interface *ifp, int set) +{ + struct listnode *node, *nnode; + struct connected *connected; + struct prefix_ipv4 address; + + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) { + struct prefix *p; + p = connected->address; + + if (p->family != AF_INET) + continue; + + address.family = AF_INET; + address.prefix = p->u.prefix4; + address.prefixlen = p->prefixlen; + apply_mask_ipv4(&address); + + if (set) { + /* Check once more wether this prefix is within a + * "network IF_OR_PREF" one */ + if ((rip_enable_if_lookup(connected->ifp->name) >= 0) + || (rip_enable_network_lookup2(connected) >= 0)) + rip_redistribute_add( + ZEBRA_ROUTE_CONNECT, + RIP_ROUTE_INTERFACE, &address, + connected->ifp->ifindex, NULL, 0, 0, 0); + } else { + rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, + RIP_ROUTE_INTERFACE, &address, + connected->ifp->ifindex); + if (rip_redistribute_check(ZEBRA_ROUTE_CONNECT)) + rip_redistribute_add( + ZEBRA_ROUTE_CONNECT, + RIP_ROUTE_REDISTRIBUTE, &address, + connected->ifp->ifindex, NULL, 0, 0, 0); + } + } } /* Update interface status. */ -void -rip_enable_apply (struct interface *ifp) +void rip_enable_apply(struct interface *ifp) { - int ret; - struct rip_interface *ri = NULL; + int ret; + struct rip_interface *ri = NULL; - /* Check interface. */ - if (! if_is_operative (ifp)) - return; + /* Check interface. */ + if (!if_is_operative(ifp)) + return; - ri = ifp->info; - - /* Check network configuration. */ - ret = rip_enable_network_lookup_if (ifp); - - /* If the interface is matched. */ - if (ret > 0) - ri->enable_network = 1; - else - ri->enable_network = 0; - - /* Check interface name configuration. */ - ret = rip_enable_if_lookup (ifp->name); - if (ret >= 0) - ri->enable_interface = 1; - else - ri->enable_interface = 0; - - /* any interface MUST have an IPv4 address */ - if ( ! rip_if_ipv4_address_check (ifp) ) - { - ri->enable_network = 0; - ri->enable_interface = 0; - } - - /* Update running status of the interface. */ - if (ri->enable_network || ri->enable_interface) - { - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("turn on %s", ifp->name); + ri = ifp->info; + + /* Check network configuration. */ + ret = rip_enable_network_lookup_if(ifp); + + /* If the interface is matched. */ + if (ret > 0) + ri->enable_network = 1; + else + ri->enable_network = 0; + + /* Check interface name configuration. */ + ret = rip_enable_if_lookup(ifp->name); + if (ret >= 0) + ri->enable_interface = 1; + else + ri->enable_interface = 0; - /* Add interface wake up thread. */ - thread_add_timer(master, rip_interface_wakeup, ifp, 1, - &ri->t_wakeup); - rip_connect_set (ifp, 1); + /* any interface MUST have an IPv4 address */ + if (!rip_if_ipv4_address_check(ifp)) { + ri->enable_network = 0; + ri->enable_interface = 0; } - } - else - { - if (ri->running) - { - /* Might as well clean up the route table as well - * rip_if_down sets to 0 ri->running, and displays "turn off %s" - **/ - rip_if_down(ifp); - rip_connect_set (ifp, 0); + /* Update running status of the interface. */ + if (ri->enable_network || ri->enable_interface) { + { + if (IS_RIP_DEBUG_EVENT) + zlog_debug("turn on %s", ifp->name); + + /* Add interface wake up thread. */ + thread_add_timer(master, rip_interface_wakeup, ifp, 1, + &ri->t_wakeup); + rip_connect_set(ifp, 1); + } + } else { + if (ri->running) { + /* Might as well clean up the route table as well + * rip_if_down sets to 0 ri->running, and displays "turn + *off %s" + **/ + rip_if_down(ifp); + + rip_connect_set(ifp, 0); + } } - } } /* Apply network configuration to all interface. */ -void -rip_enable_apply_all () +void rip_enable_apply_all() { - struct interface *ifp; - struct listnode *node, *nnode; + struct interface *ifp; + struct listnode *node, *nnode; - /* Check each interface. */ - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp)) - rip_enable_apply (ifp); + /* Check each interface. */ + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), node, nnode, ifp)) + rip_enable_apply(ifp); } -int -rip_neighbor_lookup (struct sockaddr_in *from) +int rip_neighbor_lookup(struct sockaddr_in *from) { - struct prefix_ipv4 p; - struct route_node *node; + struct prefix_ipv4 p; + struct route_node *node; - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefix = from->sin_addr; - p.prefixlen = IPV4_MAX_BITLEN; + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefix = from->sin_addr; + p.prefixlen = IPV4_MAX_BITLEN; - node = route_node_lookup (rip->neighbor, (struct prefix *) &p); - if (node) - { - route_unlock_node (node); - return 1; - } - return 0; + node = route_node_lookup(rip->neighbor, (struct prefix *)&p); + if (node) { + route_unlock_node(node); + return 1; + } + return 0; } /* Add new RIP neighbor to the neighbor tree. */ -static int -rip_neighbor_add (struct prefix_ipv4 *p) +static int rip_neighbor_add(struct prefix_ipv4 *p) { - struct route_node *node; + struct route_node *node; - node = route_node_get (rip->neighbor, (struct prefix *) p); + node = route_node_get(rip->neighbor, (struct prefix *)p); - if (node->info) - return -1; + if (node->info) + return -1; - node->info = rip->neighbor; + node->info = rip->neighbor; - return 0; + return 0; } /* Delete RIP neighbor from the neighbor tree. */ -static int -rip_neighbor_delete (struct prefix_ipv4 *p) +static int rip_neighbor_delete(struct prefix_ipv4 *p) { - struct route_node *node; + struct route_node *node; - /* Lock for look up. */ - node = route_node_lookup (rip->neighbor, (struct prefix *) p); - if (! node) - return -1; - - node->info = NULL; + /* Lock for look up. */ + node = route_node_lookup(rip->neighbor, (struct prefix *)p); + if (!node) + return -1; - /* Unlock lookup lock. */ - route_unlock_node (node); + node->info = NULL; - /* Unlock real neighbor information lock. */ - route_unlock_node (node); + /* Unlock lookup lock. */ + route_unlock_node(node); - return 0; + /* Unlock real neighbor information lock. */ + route_unlock_node(node); + + return 0; } /* Clear all network and neighbor configuration. */ -void -rip_clean_network () -{ - unsigned int i; - char *str; - struct route_node *rn; - - /* rip_enable_network. */ - for (rn = route_top (rip_enable_network); rn; rn = route_next (rn)) - if (rn->info) - { - rn->info = NULL; - route_unlock_node (rn); - } - - /* rip_enable_interface. */ - for (i = 0; i < vector_active (rip_enable_interface); i++) - if ((str = vector_slot (rip_enable_interface, i)) != NULL) - { - free (str); - vector_slot (rip_enable_interface, i) = NULL; - } +void rip_clean_network() +{ + unsigned int i; + char *str; + struct route_node *rn; + + /* rip_enable_network. */ + for (rn = route_top(rip_enable_network); rn; rn = route_next(rn)) + if (rn->info) { + rn->info = NULL; + route_unlock_node(rn); + } + + /* rip_enable_interface. */ + for (i = 0; i < vector_active(rip_enable_interface); i++) + if ((str = vector_slot(rip_enable_interface, i)) != NULL) { + free(str); + vector_slot(rip_enable_interface, i) = NULL; + } } /* Utility function for looking up passive interface settings. */ -static int -rip_passive_nondefault_lookup (const char *ifname) +static int rip_passive_nondefault_lookup(const char *ifname) { - unsigned int i; - char *str; + unsigned int i; + char *str; - for (i = 0; i < vector_active (Vrip_passive_nondefault); i++) - if ((str = vector_slot (Vrip_passive_nondefault, i)) != NULL) - if (strcmp (str, ifname) == 0) - return i; - return -1; + for (i = 0; i < vector_active(Vrip_passive_nondefault); i++) + if ((str = vector_slot(Vrip_passive_nondefault, i)) != NULL) + if (strcmp(str, ifname) == 0) + return i; + return -1; } -void -rip_passive_interface_apply (struct interface *ifp) +void rip_passive_interface_apply(struct interface *ifp) { - struct rip_interface *ri; + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->passive = ((rip_passive_nondefault_lookup (ifp->name) < 0) ? - passive_default : !passive_default); + ri->passive = ((rip_passive_nondefault_lookup(ifp->name) < 0) + ? passive_default + : !passive_default); - if (IS_RIP_DEBUG_ZEBRA) - zlog_debug ("interface %s: passive = %d",ifp->name,ri->passive); + if (IS_RIP_DEBUG_ZEBRA) + zlog_debug("interface %s: passive = %d", ifp->name, + ri->passive); } -static void -rip_passive_interface_apply_all (void) +static void rip_passive_interface_apply_all(void) { - struct interface *ifp; - struct listnode *node, *nnode; + struct interface *ifp; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp)) - rip_passive_interface_apply (ifp); + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), node, nnode, ifp)) + rip_passive_interface_apply(ifp); } /* Passive interface. */ -static int -rip_passive_nondefault_set (struct vty *vty, const char *ifname) +static int rip_passive_nondefault_set(struct vty *vty, const char *ifname) { - if (rip_passive_nondefault_lookup (ifname) >= 0) - return CMD_WARNING_CONFIG_FAILED; + if (rip_passive_nondefault_lookup(ifname) >= 0) + return CMD_WARNING_CONFIG_FAILED; - vector_set (Vrip_passive_nondefault, strdup (ifname)); + vector_set(Vrip_passive_nondefault, strdup(ifname)); - rip_passive_interface_apply_all (); + rip_passive_interface_apply_all(); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -rip_passive_nondefault_unset (struct vty *vty, const char *ifname) +static int rip_passive_nondefault_unset(struct vty *vty, const char *ifname) { - int i; - char *str; + int i; + char *str; - i = rip_passive_nondefault_lookup (ifname); - if (i < 0) - return CMD_WARNING_CONFIG_FAILED; + i = rip_passive_nondefault_lookup(ifname); + if (i < 0) + return CMD_WARNING_CONFIG_FAILED; - str = vector_slot (Vrip_passive_nondefault, i); - free (str); - vector_unset (Vrip_passive_nondefault, i); + str = vector_slot(Vrip_passive_nondefault, i); + free(str); + vector_unset(Vrip_passive_nondefault, i); - rip_passive_interface_apply_all (); + rip_passive_interface_apply_all(); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Free all configured RIP passive-interface settings. */ -void -rip_passive_nondefault_clean (void) +void rip_passive_nondefault_clean(void) { - unsigned int i; - char *str; + unsigned int i; + char *str; - for (i = 0; i < vector_active (Vrip_passive_nondefault); i++) - if ((str = vector_slot (Vrip_passive_nondefault, i)) != NULL) - { - free (str); - vector_slot (Vrip_passive_nondefault, i) = NULL; - } - rip_passive_interface_apply_all (); + for (i = 0; i < vector_active(Vrip_passive_nondefault); i++) + if ((str = vector_slot(Vrip_passive_nondefault, i)) != NULL) { + free(str); + vector_slot(Vrip_passive_nondefault, i) = NULL; + } + rip_passive_interface_apply_all(); } /* RIP enable network or interface configuration. */ @@ -1220,25 +1151,24 @@ DEFUN (rip_network, "IP prefix /, e.g., 35.0.0.0/8\n" "Interface name\n") { - int idx_ipv4_word = 1; - int ret; - struct prefix_ipv4 p; + int idx_ipv4_word = 1; + int ret; + struct prefix_ipv4 p; - ret = str2prefix_ipv4 (argv[idx_ipv4_word]->arg, &p); + ret = str2prefix_ipv4(argv[idx_ipv4_word]->arg, &p); - if (ret) - ret = rip_enable_network_add ((struct prefix *) &p); - else - ret = rip_enable_if_add (argv[idx_ipv4_word]->arg); + if (ret) + ret = rip_enable_network_add((struct prefix *)&p); + else + ret = rip_enable_if_add(argv[idx_ipv4_word]->arg); - if (ret < 0) - { - vty_out (vty, "There is a same network configuration %s\n", - argv[idx_ipv4_word]->arg); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret < 0) { + vty_out(vty, "There is a same network configuration %s\n", + argv[idx_ipv4_word]->arg); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* RIP enable network or interface configuration. */ @@ -1250,25 +1180,24 @@ DEFUN (no_rip_network, "IP prefix /, e.g., 35.0.0.0/8\n" "Interface name\n") { - int idx_ipv4_word = 2; - int ret; - struct prefix_ipv4 p; + int idx_ipv4_word = 2; + int ret; + struct prefix_ipv4 p; - ret = str2prefix_ipv4 (argv[idx_ipv4_word]->arg, &p); + ret = str2prefix_ipv4(argv[idx_ipv4_word]->arg, &p); - if (ret) - ret = rip_enable_network_delete ((struct prefix *) &p); - else - ret = rip_enable_if_delete (argv[idx_ipv4_word]->arg); + if (ret) + ret = rip_enable_network_delete((struct prefix *)&p); + else + ret = rip_enable_if_delete(argv[idx_ipv4_word]->arg); - if (ret < 0) - { - vty_out (vty, "Can't find network configuration %s\n", - argv[idx_ipv4_word]->arg); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret < 0) { + vty_out(vty, "Can't find network configuration %s\n", + argv[idx_ipv4_word]->arg); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* RIP neighbor configuration set. */ @@ -1278,21 +1207,20 @@ DEFUN (rip_neighbor, "Specify a neighbor router\n" "Neighbor address\n") { - int idx_ipv4 = 1; - int ret; - struct prefix_ipv4 p; + int idx_ipv4 = 1; + int ret; + struct prefix_ipv4 p; - ret = str2prefix_ipv4 (argv[idx_ipv4]->arg, &p); + ret = str2prefix_ipv4(argv[idx_ipv4]->arg, &p); + + if (ret <= 0) { + vty_out(vty, "Please specify address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (ret <= 0) - { - vty_out (vty, "Please specify address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } + rip_neighbor_add(&p); - rip_neighbor_add (&p); - - return CMD_SUCCESS; + return CMD_SUCCESS; } /* RIP neighbor configuration unset. */ @@ -1303,21 +1231,20 @@ DEFUN (no_rip_neighbor, "Specify a neighbor router\n" "Neighbor address\n") { - int idx_ipv4 = 2; - int ret; - struct prefix_ipv4 p; + int idx_ipv4 = 2; + int ret; + struct prefix_ipv4 p; - ret = str2prefix_ipv4 (argv[idx_ipv4]->arg, &p); + ret = str2prefix_ipv4(argv[idx_ipv4]->arg, &p); - if (ret <= 0) - { - vty_out (vty, "Please specify address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret <= 0) { + vty_out(vty, "Please specify address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + rip_neighbor_delete(&p); - rip_neighbor_delete (&p); - - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_rip_receive_version, @@ -1330,28 +1257,27 @@ DEFUN (ip_rip_receive_version, "RIP version\n" "None\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_type = 4; - struct rip_interface *ri; - - ri = ifp->info; - - switch (argv[idx_type]->arg[0]) - { - case '1': - ri->ri_receive = RI_RIP_VERSION_1; - return CMD_SUCCESS; - case '2': - ri->ri_receive = RI_RIP_VERSION_2; - return CMD_SUCCESS; - case 'n': - ri->ri_receive = RI_RIP_VERSION_NONE; - return CMD_SUCCESS; - default: - break; - } + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_type = 4; + struct rip_interface *ri; + + ri = ifp->info; + + switch (argv[idx_type]->arg[0]) { + case '1': + ri->ri_receive = RI_RIP_VERSION_1; + return CMD_SUCCESS; + case '2': + ri->ri_receive = RI_RIP_VERSION_2; + return CMD_SUCCESS; + case 'n': + ri->ri_receive = RI_RIP_VERSION_NONE; + return CMD_SUCCESS; + default: + break; + } - return CMD_WARNING_CONFIG_FAILED; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (ip_rip_receive_version_1, @@ -1366,14 +1292,14 @@ DEFUN (ip_rip_receive_version_1, "RIP version 2\n" "RIP version 1\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - /* Version 1 and 2. */ - ri->ri_receive = RI_RIP_VERSION_1_AND_2; - return CMD_SUCCESS; + /* Version 1 and 2. */ + ri->ri_receive = RI_RIP_VERSION_1_AND_2; + return CMD_SUCCESS; } DEFUN (no_ip_rip_receive_version, @@ -1386,13 +1312,13 @@ DEFUN (no_ip_rip_receive_version, "Version control\n" "RIP version\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->ri_receive = RI_RIP_UNSPEC; - return CMD_SUCCESS; + ri->ri_receive = RI_RIP_UNSPEC; + return CMD_SUCCESS; } @@ -1405,24 +1331,22 @@ DEFUN (ip_rip_send_version, "Version control\n" "RIP version\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_type = 4; - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_type = 4; + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - /* Version 1. */ - if (atoi (argv[idx_type]->arg) == 1) - { - ri->ri_send = RI_RIP_VERSION_1; - return CMD_SUCCESS; - } - if (atoi (argv[idx_type]->arg) == 2) - { - ri->ri_send = RI_RIP_VERSION_2; - return CMD_SUCCESS; - } - return CMD_WARNING_CONFIG_FAILED; + /* Version 1. */ + if (atoi(argv[idx_type]->arg) == 1) { + ri->ri_send = RI_RIP_VERSION_1; + return CMD_SUCCESS; + } + if (atoi(argv[idx_type]->arg) == 2) { + ri->ri_send = RI_RIP_VERSION_2; + return CMD_SUCCESS; + } + return CMD_WARNING_CONFIG_FAILED; } DEFUN (ip_rip_send_version_1, @@ -1437,14 +1361,14 @@ DEFUN (ip_rip_send_version_1, "RIP version 2\n" "RIP version 1\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - /* Version 1 and 2. */ - ri->ri_send = RI_RIP_VERSION_1_AND_2; - return CMD_SUCCESS; + /* Version 1 and 2. */ + ri->ri_send = RI_RIP_VERSION_1_AND_2; + return CMD_SUCCESS; } DEFUN (no_ip_rip_send_version, @@ -1457,13 +1381,13 @@ DEFUN (no_ip_rip_send_version, "Version control\n" "RIP version\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->ri_send = RI_RIP_UNSPEC; - return CMD_SUCCESS; + ri->ri_send = RI_RIP_UNSPEC; + return CMD_SUCCESS; } @@ -1474,13 +1398,13 @@ DEFUN (ip_rip_v2_broadcast, "Routing Information Protocol\n" "Send ip broadcast v2 update\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->v2_broadcast = 1; - return CMD_SUCCESS; + ri->v2_broadcast = 1; + return CMD_SUCCESS; } DEFUN (no_ip_rip_v2_broadcast, @@ -1491,13 +1415,13 @@ DEFUN (no_ip_rip_v2_broadcast, "Routing Information Protocol\n" "Send ip broadcast v2 update\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->v2_broadcast = 0; - return CMD_SUCCESS; + ri->v2_broadcast = 0; + return CMD_SUCCESS; } DEFUN (ip_rip_authentication_mode, @@ -1513,40 +1437,38 @@ DEFUN (ip_rip_authentication_mode, "RFC compatible\n" "Old ripd compatible\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - char *cryptmode = argv[4]->text; - char *authlen = (argc > 5) ? argv[6]->text : NULL; - struct rip_interface *ri; - int auth_type; - - ri = ifp->info; - - if (strmatch ("md5", cryptmode)) - auth_type = RIP_AUTH_MD5; - else { - assert (strmatch ("text", cryptmode)); - auth_type = RIP_AUTH_SIMPLE_PASSWORD; - } - - ri->auth_type = auth_type; - - if (argc > 5) - { - if (auth_type != RIP_AUTH_MD5) - { - vty_out (vty, "auth length argument only valid for md5\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (strmatch ("rfc", authlen)) - ri->md5_auth_len = RIP_AUTH_MD5_SIZE; - else - { - assert (strmatch ("old-ripd", authlen)); - ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE; - } - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + char *cryptmode = argv[4]->text; + char *authlen = (argc > 5) ? argv[6]->text : NULL; + struct rip_interface *ri; + int auth_type; + + ri = ifp->info; + + if (strmatch("md5", cryptmode)) + auth_type = RIP_AUTH_MD5; + else { + assert(strmatch("text", cryptmode)); + auth_type = RIP_AUTH_SIMPLE_PASSWORD; + } + + ri->auth_type = auth_type; + + if (argc > 5) { + if (auth_type != RIP_AUTH_MD5) { + vty_out(vty, + "auth length argument only valid for md5\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (strmatch("rfc", authlen)) + ri->md5_auth_len = RIP_AUTH_MD5_SIZE; + else { + assert(strmatch("old-ripd", authlen)); + ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE; + } + } + + return CMD_SUCCESS; } DEFUN (no_ip_rip_authentication_mode, @@ -1563,15 +1485,15 @@ DEFUN (no_ip_rip_authentication_mode, "RFC compatible\n" "Old ripd compatible\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->auth_type = RIP_NO_AUTH; - ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE; + ri->auth_type = RIP_NO_AUTH; + ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_rip_authentication_string, @@ -1583,31 +1505,29 @@ DEFUN (ip_rip_authentication_string, "Authentication string\n" "Authentication string\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_line = 4; - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_line = 4; + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - if (strlen (argv[idx_line]->arg) > 16) - { - vty_out (vty, - "%% RIPv2 authentication string must be shorter than 16\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (strlen(argv[idx_line]->arg) > 16) { + vty_out(vty, + "%% RIPv2 authentication string must be shorter than 16\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (ri->key_chain) - { - vty_out (vty, "%% key-chain configuration exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (ri->key_chain) { + vty_out(vty, "%% key-chain configuration exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (ri->auth_str) - free (ri->auth_str); + if (ri->auth_str) + free(ri->auth_str); - ri->auth_str = strdup (argv[idx_line]->arg); + ri->auth_str = strdup(argv[idx_line]->arg); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_rip_authentication_string, @@ -1620,17 +1540,17 @@ DEFUN (no_ip_rip_authentication_string, "Authentication string\n" "Authentication string\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - if (ri->auth_str) - free (ri->auth_str); + if (ri->auth_str) + free(ri->auth_str); - ri->auth_str = NULL; + ri->auth_str = NULL; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1643,24 +1563,23 @@ DEFUN (ip_rip_authentication_key_chain, "Authentication key-chain\n" "name of key-chain\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_line = 4; - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_line = 4; + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - if (ri->auth_str) - { - vty_out (vty,"%% authentication string configuration exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (ri->auth_str) { + vty_out(vty, "%% authentication string configuration exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (ri->key_chain) - free (ri->key_chain); + if (ri->key_chain) + free(ri->key_chain); - ri->key_chain = strdup (argv[idx_line]->arg); + ri->key_chain = strdup(argv[idx_line]->arg); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_rip_authentication_key_chain, @@ -1673,17 +1592,17 @@ DEFUN (no_ip_rip_authentication_key_chain, "Authentication key-chain\n" "name of key-chain\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - if (ri->key_chain) - free (ri->key_chain); + if (ri->key_chain) + free(ri->key_chain); - ri->key_chain = NULL; + ri->key_chain = NULL; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1698,13 +1617,13 @@ DEFUN (ip_rip_split_horizon, "Routing Information Protocol\n" "Perform split horizon\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->split_horizon = RIP_SPLIT_HORIZON; - return CMD_SUCCESS; + ri->split_horizon = RIP_SPLIT_HORIZON; + return CMD_SUCCESS; } DEFUN (ip_rip_split_horizon_poisoned_reverse, @@ -1715,13 +1634,13 @@ DEFUN (ip_rip_split_horizon_poisoned_reverse, "Perform split horizon\n" "With poisoned-reverse\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->split_horizon = RIP_SPLIT_HORIZON_POISONED_REVERSE; - return CMD_SUCCESS; + ri->split_horizon = RIP_SPLIT_HORIZON_POISONED_REVERSE; + return CMD_SUCCESS; } /* CHANGED: no ip rip split-horizon @@ -1736,13 +1655,13 @@ DEFUN (no_ip_rip_split_horizon, "Routing Information Protocol\n" "Perform split horizon\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->split_horizon = RIP_NO_SPLIT_HORIZON; - return CMD_SUCCESS; + ri->split_horizon = RIP_NO_SPLIT_HORIZON; + return CMD_SUCCESS; } DEFUN (no_ip_rip_split_horizon_poisoned_reverse, @@ -1754,20 +1673,19 @@ DEFUN (no_ip_rip_split_horizon_poisoned_reverse, "Perform split horizon\n" "With poisoned-reverse\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - switch( ri->split_horizon ) - { - case RIP_SPLIT_HORIZON_POISONED_REVERSE: - ri->split_horizon = RIP_SPLIT_HORIZON; - default: - break; - } + switch (ri->split_horizon) { + case RIP_SPLIT_HORIZON_POISONED_REVERSE: + ri->split_horizon = RIP_SPLIT_HORIZON; + default: + break; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (rip_passive_interface, @@ -1777,15 +1695,15 @@ DEFUN (rip_passive_interface, "Interface name\n" "default for all interfaces\n") { - if (argv[1]->type == WORD_TKN) { // user passed 'default' - passive_default = 1; - rip_passive_nondefault_clean(); - return CMD_SUCCESS; - } - if (passive_default) - return rip_passive_nondefault_unset (vty, argv[1]->arg); - else - return rip_passive_nondefault_set (vty, argv[1]->arg); + if (argv[1]->type == WORD_TKN) { // user passed 'default' + passive_default = 1; + rip_passive_nondefault_clean(); + return CMD_SUCCESS; + } + if (passive_default) + return rip_passive_nondefault_unset(vty, argv[1]->arg); + else + return rip_passive_nondefault_set(vty, argv[1]->arg); } DEFUN (no_rip_passive_interface, @@ -1796,224 +1714,217 @@ DEFUN (no_rip_passive_interface, "Interface name\n" "default for all interfaces\n") { - if (argv[2]->type == WORD_TKN) { - passive_default = 0; - rip_passive_nondefault_clean(); - return CMD_SUCCESS; - } - if (passive_default) - return rip_passive_nondefault_set (vty, argv[2]->arg); - else - return rip_passive_nondefault_unset (vty, argv[2]->arg); + if (argv[2]->type == WORD_TKN) { + passive_default = 0; + rip_passive_nondefault_clean(); + return CMD_SUCCESS; + } + if (passive_default) + return rip_passive_nondefault_set(vty, argv[2]->arg); + else + return rip_passive_nondefault_unset(vty, argv[2]->arg); } /* Write rip configuration of each interface. */ -static int -rip_interface_config_write (struct vty *vty) -{ - struct listnode *node; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - struct rip_interface *ri; - - if (ifp->ifindex == IFINDEX_DELETED) - continue; - - ri = ifp->info; - - /* Do not display the interface if there is no - * configuration about it. - **/ - if ((!ifp->desc) && - (ri->split_horizon == ri->split_horizon_default) && - (ri->ri_send == RI_RIP_UNSPEC) && - (ri->ri_receive == RI_RIP_UNSPEC) && - (ri->auth_type != RIP_AUTH_MD5) && - (!ri->v2_broadcast) && - (ri->md5_auth_len != RIP_AUTH_MD5_SIZE) && - (!ri->auth_str) && - (!ri->key_chain) ) - continue; - - vty_out (vty, "interface %s\n",ifp->name); - - if (ifp->desc) - vty_out (vty, " description %s\n",ifp->desc); - - /* Split horizon. */ - if (ri->split_horizon != ri->split_horizon_default) - { - switch (ri->split_horizon) { - case RIP_SPLIT_HORIZON: - vty_out (vty, " ip rip split-horizon\n"); - break; - case RIP_SPLIT_HORIZON_POISONED_REVERSE: - vty_out (vty," ip rip split-horizon poisoned-reverse\n"); - break; - case RIP_NO_SPLIT_HORIZON: - default: - vty_out (vty, " no ip rip split-horizon\n"); - break; - } +static int rip_interface_config_write(struct vty *vty) +{ + struct listnode *node; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + struct rip_interface *ri; + + if (ifp->ifindex == IFINDEX_DELETED) + continue; + + ri = ifp->info; + + /* Do not display the interface if there is no + * configuration about it. + **/ + if ((!ifp->desc) + && (ri->split_horizon == ri->split_horizon_default) + && (ri->ri_send == RI_RIP_UNSPEC) + && (ri->ri_receive == RI_RIP_UNSPEC) + && (ri->auth_type != RIP_AUTH_MD5) && (!ri->v2_broadcast) + && (ri->md5_auth_len != RIP_AUTH_MD5_SIZE) + && (!ri->auth_str) && (!ri->key_chain)) + continue; + + vty_out(vty, "interface %s\n", ifp->name); + + if (ifp->desc) + vty_out(vty, " description %s\n", ifp->desc); + + /* Split horizon. */ + if (ri->split_horizon != ri->split_horizon_default) { + switch (ri->split_horizon) { + case RIP_SPLIT_HORIZON: + vty_out(vty, " ip rip split-horizon\n"); + break; + case RIP_SPLIT_HORIZON_POISONED_REVERSE: + vty_out(vty, + " ip rip split-horizon poisoned-reverse\n"); + break; + case RIP_NO_SPLIT_HORIZON: + default: + vty_out(vty, " no ip rip split-horizon\n"); + break; + } + } + + /* RIP version setting. */ + if (ri->ri_send != RI_RIP_UNSPEC) + vty_out(vty, " ip rip send version %s\n", + lookup_msg(ri_version_msg, ri->ri_send, NULL)); + + if (ri->ri_receive != RI_RIP_UNSPEC) + vty_out(vty, " ip rip receive version %s \n", + lookup_msg(ri_version_msg, ri->ri_receive, + NULL)); + + if (ri->v2_broadcast) + vty_out(vty, " ip rip v2-broadcast\n"); + + /* RIP authentication. */ + if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD) + vty_out(vty, " ip rip authentication mode text\n"); + + if (ri->auth_type == RIP_AUTH_MD5) { + vty_out(vty, " ip rip authentication mode md5"); + if (ri->md5_auth_len == RIP_AUTH_MD5_COMPAT_SIZE) + vty_out(vty, " auth-length old-ripd"); + else + vty_out(vty, " auth-length rfc"); + vty_out(vty, "\n"); + } + + if (ri->auth_str) + vty_out(vty, " ip rip authentication string %s\n", + ri->auth_str); + + if (ri->key_chain) + vty_out(vty, " ip rip authentication key-chain %s\n", + ri->key_chain); + + vty_out(vty, "!\n"); + } + return 0; +} + +int config_write_rip_network(struct vty *vty, int config_mode) +{ + unsigned int i; + char *ifname; + struct route_node *node; + + /* Network type RIP enable interface statement. */ + for (node = route_top(rip_enable_network); node; + node = route_next(node)) + if (node->info) + vty_out(vty, "%s%s/%d\n", + config_mode ? " network " : " ", + inet_ntoa(node->p.u.prefix4), + node->p.prefixlen); + + /* Interface name RIP enable statement. */ + for (i = 0; i < vector_active(rip_enable_interface); i++) + if ((ifname = vector_slot(rip_enable_interface, i)) != NULL) + vty_out(vty, "%s%s\n", + config_mode ? " network " : " ", ifname); + + /* RIP neighbors listing. */ + for (node = route_top(rip->neighbor); node; node = route_next(node)) + if (node->info) + vty_out(vty, "%s%s\n", + config_mode ? " neighbor " : " ", + inet_ntoa(node->p.u.prefix4)); + + /* RIP passive interface listing. */ + if (config_mode) { + if (passive_default) + vty_out(vty, " passive-interface default\n"); + for (i = 0; i < vector_active(Vrip_passive_nondefault); i++) + if ((ifname = vector_slot(Vrip_passive_nondefault, i)) + != NULL) + vty_out(vty, " %spassive-interface %s\n", + (passive_default ? "no " : ""), ifname); } - /* RIP version setting. */ - if (ri->ri_send != RI_RIP_UNSPEC) - vty_out (vty, " ip rip send version %s\n", - lookup_msg(ri_version_msg, ri->ri_send, NULL)); - - if (ri->ri_receive != RI_RIP_UNSPEC) - vty_out (vty, " ip rip receive version %s \n", - lookup_msg(ri_version_msg, ri->ri_receive, NULL)); - - if (ri->v2_broadcast) - vty_out (vty, " ip rip v2-broadcast\n"); - - /* RIP authentication. */ - if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD) - vty_out (vty, " ip rip authentication mode text\n"); - - if (ri->auth_type == RIP_AUTH_MD5) - { - vty_out (vty, " ip rip authentication mode md5"); - if (ri->md5_auth_len == RIP_AUTH_MD5_COMPAT_SIZE) - vty_out (vty, " auth-length old-ripd"); - else - vty_out (vty, " auth-length rfc"); - vty_out (vty, "\n"); - } - - if (ri->auth_str) - vty_out (vty, " ip rip authentication string %s\n", - ri->auth_str); - - if (ri->key_chain) - vty_out (vty, " ip rip authentication key-chain %s\n", - ri->key_chain); - - vty_out (vty, "!\n"); - } - return 0; -} - -int -config_write_rip_network (struct vty *vty, int config_mode) -{ - unsigned int i; - char *ifname; - struct route_node *node; - - /* Network type RIP enable interface statement. */ - for (node = route_top (rip_enable_network); node; node = route_next (node)) - if (node->info) - vty_out (vty, "%s%s/%d\n", - config_mode ? " network " : " ", - inet_ntoa (node->p.u.prefix4), - node->p.prefixlen); - - /* Interface name RIP enable statement. */ - for (i = 0; i < vector_active (rip_enable_interface); i++) - if ((ifname = vector_slot (rip_enable_interface, i)) != NULL) - vty_out (vty, "%s%s\n", - config_mode ? " network " : " ", - ifname); - - /* RIP neighbors listing. */ - for (node = route_top (rip->neighbor); node; node = route_next (node)) - if (node->info) - vty_out (vty, "%s%s\n", - config_mode ? " neighbor " : " ", - inet_ntoa(node->p.u.prefix4)); - - /* RIP passive interface listing. */ - if (config_mode) { - if (passive_default) - vty_out (vty, " passive-interface default\n"); - for (i = 0; i < vector_active (Vrip_passive_nondefault); i++) - if ((ifname = vector_slot (Vrip_passive_nondefault, i)) != NULL) - vty_out (vty, " %spassive-interface %s\n", - (passive_default ? "no " : ""), ifname); - } - - return 0; -} - -static struct cmd_node interface_node = -{ - INTERFACE_NODE, - "%s(config-if)# ", - 1, + return 0; +} + +static struct cmd_node interface_node = { + INTERFACE_NODE, "%s(config-if)# ", 1, }; /* Called when interface structure allocated. */ -static int -rip_interface_new_hook (struct interface *ifp) +static int rip_interface_new_hook(struct interface *ifp) { - ifp->info = rip_interface_new (); - return 0; + ifp->info = rip_interface_new(); + return 0; } /* Called when interface structure deleted. */ -static int -rip_interface_delete_hook (struct interface *ifp) +static int rip_interface_delete_hook(struct interface *ifp) { - XFREE (MTYPE_RIP_INTERFACE, ifp->info); - ifp->info = NULL; - return 0; + XFREE(MTYPE_RIP_INTERFACE, ifp->info); + ifp->info = NULL; + return 0; } /* Allocate and initialize interface vector. */ -void -rip_if_init (void) +void rip_if_init(void) { - /* Default initial size of interface vector. */ - if_add_hook (IF_NEW_HOOK, rip_interface_new_hook); - if_add_hook (IF_DELETE_HOOK, rip_interface_delete_hook); - - /* RIP network init. */ - rip_enable_interface = vector_init (1); - rip_enable_network = route_table_init (); + /* Default initial size of interface vector. */ + if_add_hook(IF_NEW_HOOK, rip_interface_new_hook); + if_add_hook(IF_DELETE_HOOK, rip_interface_delete_hook); + + /* RIP network init. */ + rip_enable_interface = vector_init(1); + rip_enable_network = route_table_init(); - /* RIP passive interface. */ - Vrip_passive_nondefault = vector_init (1); + /* RIP passive interface. */ + Vrip_passive_nondefault = vector_init(1); - /* Install interface node. */ - install_node (&interface_node, rip_interface_config_write); - if_cmd_init (); + /* Install interface node. */ + install_node(&interface_node, rip_interface_config_write); + if_cmd_init(); - /* Install commands. */ - install_element (RIP_NODE, &rip_network_cmd); - install_element (RIP_NODE, &no_rip_network_cmd); - install_element (RIP_NODE, &rip_neighbor_cmd); - install_element (RIP_NODE, &no_rip_neighbor_cmd); + /* Install commands. */ + install_element(RIP_NODE, &rip_network_cmd); + install_element(RIP_NODE, &no_rip_network_cmd); + install_element(RIP_NODE, &rip_neighbor_cmd); + install_element(RIP_NODE, &no_rip_neighbor_cmd); - install_element (RIP_NODE, &rip_passive_interface_cmd); - install_element (RIP_NODE, &no_rip_passive_interface_cmd); + install_element(RIP_NODE, &rip_passive_interface_cmd); + install_element(RIP_NODE, &no_rip_passive_interface_cmd); - install_element (INTERFACE_NODE, &ip_rip_send_version_cmd); - install_element (INTERFACE_NODE, &ip_rip_send_version_1_cmd); - install_element (INTERFACE_NODE, &no_ip_rip_send_version_cmd); + install_element(INTERFACE_NODE, &ip_rip_send_version_cmd); + install_element(INTERFACE_NODE, &ip_rip_send_version_1_cmd); + install_element(INTERFACE_NODE, &no_ip_rip_send_version_cmd); - install_element (INTERFACE_NODE, &ip_rip_receive_version_cmd); - install_element (INTERFACE_NODE, &ip_rip_receive_version_1_cmd); - install_element (INTERFACE_NODE, &no_ip_rip_receive_version_cmd); + install_element(INTERFACE_NODE, &ip_rip_receive_version_cmd); + install_element(INTERFACE_NODE, &ip_rip_receive_version_1_cmd); + install_element(INTERFACE_NODE, &no_ip_rip_receive_version_cmd); - install_element (INTERFACE_NODE, &ip_rip_v2_broadcast_cmd); - install_element (INTERFACE_NODE, &no_ip_rip_v2_broadcast_cmd); + install_element(INTERFACE_NODE, &ip_rip_v2_broadcast_cmd); + install_element(INTERFACE_NODE, &no_ip_rip_v2_broadcast_cmd); - install_element (INTERFACE_NODE, &ip_rip_authentication_mode_cmd); - install_element (INTERFACE_NODE, &no_ip_rip_authentication_mode_cmd); + install_element(INTERFACE_NODE, &ip_rip_authentication_mode_cmd); + install_element(INTERFACE_NODE, &no_ip_rip_authentication_mode_cmd); - install_element (INTERFACE_NODE, &ip_rip_authentication_key_chain_cmd); - install_element (INTERFACE_NODE, &no_ip_rip_authentication_key_chain_cmd); + install_element(INTERFACE_NODE, &ip_rip_authentication_key_chain_cmd); + install_element(INTERFACE_NODE, + &no_ip_rip_authentication_key_chain_cmd); - install_element (INTERFACE_NODE, &ip_rip_authentication_string_cmd); - install_element (INTERFACE_NODE, &no_ip_rip_authentication_string_cmd); + install_element(INTERFACE_NODE, &ip_rip_authentication_string_cmd); + install_element(INTERFACE_NODE, &no_ip_rip_authentication_string_cmd); - install_element (INTERFACE_NODE, &ip_rip_split_horizon_cmd); - install_element (INTERFACE_NODE, &ip_rip_split_horizon_poisoned_reverse_cmd); - install_element (INTERFACE_NODE, &no_ip_rip_split_horizon_cmd); - install_element (INTERFACE_NODE, &no_ip_rip_split_horizon_poisoned_reverse_cmd); + install_element(INTERFACE_NODE, &ip_rip_split_horizon_cmd); + install_element(INTERFACE_NODE, + &ip_rip_split_horizon_poisoned_reverse_cmd); + install_element(INTERFACE_NODE, &no_ip_rip_split_horizon_cmd); + install_element(INTERFACE_NODE, + &no_ip_rip_split_horizon_poisoned_reverse_cmd); } diff --git a/ripd/rip_interface.h b/ripd/rip_interface.h index 9513bafc2..8723388e7 100644 --- a/ripd/rip_interface.h +++ b/ripd/rip_interface.h @@ -20,17 +20,13 @@ #ifndef _QUAGGA_RIP_INTERFACE_H #define _QUAGGA_RIP_INTERFACE_H -extern int rip_interface_down (int , struct zclient *, zebra_size_t, - vrf_id_t); -extern int rip_interface_up (int , struct zclient *, zebra_size_t, - vrf_id_t); -extern int rip_interface_add (int , struct zclient *, zebra_size_t, - vrf_id_t); -extern int rip_interface_delete (int , struct zclient *, zebra_size_t, - vrf_id_t); -extern int rip_interface_address_add (int , struct zclient *, zebra_size_t, - vrf_id_t); -extern int rip_interface_address_delete (int , struct zclient *, zebra_size_t, - vrf_id_t); +extern int rip_interface_down(int, struct zclient *, zebra_size_t, vrf_id_t); +extern int rip_interface_up(int, struct zclient *, zebra_size_t, vrf_id_t); +extern int rip_interface_add(int, struct zclient *, zebra_size_t, vrf_id_t); +extern int rip_interface_delete(int, struct zclient *, zebra_size_t, vrf_id_t); +extern int rip_interface_address_add(int, struct zclient *, zebra_size_t, + vrf_id_t); +extern int rip_interface_address_delete(int, struct zclient *, zebra_size_t, + vrf_id_t); #endif /* _QUAGGA_RIP_INTERFACE_H */ diff --git a/ripd/rip_main.c b/ripd/rip_main.c index 1a7d03bca..91b623beb 100644 --- a/ripd/rip_main.c +++ b/ripd/rip_main.c @@ -39,34 +39,24 @@ #include "ripd/ripd.h" /* ripd options. */ -static struct option longopts[] = -{ - { "retain", no_argument, NULL, 'r'}, - { 0 } -}; +static struct option longopts[] = {{"retain", no_argument, NULL, 'r'}, {0}}; /* ripd privileges */ -zebra_capabilities_t _caps_p [] = -{ - ZCAP_NET_RAW, - ZCAP_BIND -}; +zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND}; -struct zebra_privs_t ripd_privs = -{ +struct zebra_privs_t ripd_privs = { #if defined(FRR_USER) - .user = FRR_USER, + .user = FRR_USER, #endif #if defined FRR_GROUP - .group = FRR_GROUP, + .group = FRR_GROUP, #endif #ifdef VTY_GROUP - .vty_group = VTY_GROUP, + .vty_group = VTY_GROUP, #endif - .caps_p = _caps_p, - .cap_num_p = 2, - .cap_num_i = 0 -}; + .caps_p = _caps_p, + .cap_num_p = 2, + .cap_num_i = 0}; /* Route retain mode flag. */ int retain_mode = 0; @@ -77,119 +67,110 @@ struct thread_master *master; static struct frr_daemon_info ripd_di; /* SIGHUP handler. */ -static void -sighup (void) +static void sighup(void) { - zlog_info ("SIGHUP received"); - rip_clean (); - rip_reset (); - zlog_info ("ripd restarting!"); + zlog_info("SIGHUP received"); + rip_clean(); + rip_reset(); + zlog_info("ripd restarting!"); - /* Reload config file. */ - vty_read_config (ripd_di.config_file, config_default); + /* Reload config file. */ + vty_read_config(ripd_di.config_file, config_default); - /* Try to return to normal operation. */ + /* Try to return to normal operation. */ } /* SIGINT handler. */ -static void -sigint (void) +static void sigint(void) { - zlog_notice ("Terminating on signal"); + zlog_notice("Terminating on signal"); - if (! retain_mode) - rip_clean (); + if (!retain_mode) + rip_clean(); - rip_zclient_stop (); + rip_zclient_stop(); - exit (0); + exit(0); } /* SIGUSR1 handler. */ -static void -sigusr1 (void) +static void sigusr1(void) { - zlog_rotate(); + zlog_rotate(); } -static struct quagga_signal_t ripd_signals[] = -{ - { - .signal = SIGHUP, - .handler = &sighup, - }, - { - .signal = SIGUSR1, - .handler = &sigusr1, - }, - { - .signal = SIGINT, - .handler = &sigint, - }, - { - .signal = SIGTERM, - .handler = &sigint, - }, -}; - -FRR_DAEMON_INFO(ripd, RIP, - .vty_port = RIP_VTY_PORT, - - .proghelp = "Implementation of the RIP routing protocol.", - - .signals = ripd_signals, - .n_signals = array_size(ripd_signals), - - .privs = &ripd_privs, -) +static struct quagga_signal_t ripd_signals[] = { + { + .signal = SIGHUP, + .handler = &sighup, + }, + { + .signal = SIGUSR1, + .handler = &sigusr1, + }, + { + .signal = SIGINT, + .handler = &sigint, + }, + { + .signal = SIGTERM, + .handler = &sigint, + }, +}; -/* Main routine of ripd. */ -int -main (int argc, char **argv) -{ - frr_preinit (&ripd_di, argc, argv); - frr_opt_add ("r", longopts, - " -r, --retain When program terminates, retain added route by ripd.\n"); +FRR_DAEMON_INFO(ripd, RIP, .vty_port = RIP_VTY_PORT, - /* Command line option parse. */ - while (1) - { - int opt; + .proghelp = "Implementation of the RIP routing protocol.", - opt = frr_getopt (argc, argv, NULL); - - if (opt == EOF) - break; + .signals = ripd_signals, .n_signals = array_size(ripd_signals), - switch (opt) - { - case 0: - break; - case 'r': - retain_mode = 1; - break; - default: - frr_help_exit (1); - break; + .privs = &ripd_privs, ) + +/* Main routine of ripd. */ +int main(int argc, char **argv) +{ + frr_preinit(&ripd_di, argc, argv); + frr_opt_add( + "r", longopts, + " -r, --retain When program terminates, retain added route by ripd.\n"); + + /* Command line option parse. */ + while (1) { + int opt; + + opt = frr_getopt(argc, argv, NULL); + + if (opt == EOF) + break; + + switch (opt) { + case 0: + break; + case 'r': + retain_mode = 1; + break; + default: + frr_help_exit(1); + break; + } } - } - /* Prepare master thread. */ - master = frr_init (); + /* Prepare master thread. */ + master = frr_init(); - /* Library initialization. */ - keychain_init (); - vrf_init (NULL, NULL, NULL, NULL); + /* Library initialization. */ + keychain_init(); + vrf_init(NULL, NULL, NULL, NULL); - /* RIP related initialization. */ - rip_init (); - rip_if_init (); - rip_zclient_init(master); - rip_peer_init (); + /* RIP related initialization. */ + rip_init(); + rip_if_init(); + rip_zclient_init(master); + rip_peer_init(); - frr_config_fork (); - frr_run (master); + frr_config_fork(); + frr_run(master); - /* Not reached. */ - return (0); + /* Not reached. */ + return (0); } diff --git a/ripd/rip_memory.c b/ripd/rip_memory.c index 662a6cced..4cdd3df04 100644 --- a/ripd/rip_memory.c +++ b/ripd/rip_memory.c @@ -26,9 +26,9 @@ #include "rip_memory.h" DEFINE_MGROUP(RIPD, "ripd") -DEFINE_MTYPE(RIPD, RIP, "RIP structure") -DEFINE_MTYPE(RIPD, RIP_INFO, "RIP route info") -DEFINE_MTYPE(RIPD, RIP_INTERFACE, "RIP interface") -DEFINE_MTYPE(RIPD, RIP_PEER, "RIP peer") +DEFINE_MTYPE(RIPD, RIP, "RIP structure") +DEFINE_MTYPE(RIPD, RIP_INFO, "RIP route info") +DEFINE_MTYPE(RIPD, RIP_INTERFACE, "RIP interface") +DEFINE_MTYPE(RIPD, RIP_PEER, "RIP peer") DEFINE_MTYPE(RIPD, RIP_OFFSET_LIST, "RIP offset list") -DEFINE_MTYPE(RIPD, RIP_DISTANCE, "RIP distance") +DEFINE_MTYPE(RIPD, RIP_DISTANCE, "RIP distance") diff --git a/ripd/rip_offset.c b/ripd/rip_offset.c index 63f93d139..6b539046f 100644 --- a/ripd/rip_offset.c +++ b/ripd/rip_offset.c @@ -33,165 +33,148 @@ #define RIP_OFFSET_LIST_OUT 1 #define RIP_OFFSET_LIST_MAX 2 -struct rip_offset_list -{ - char *ifname; - - struct - { - char *alist_name; - /* struct access_list *alist; */ - int metric; - } direct[RIP_OFFSET_LIST_MAX]; +struct rip_offset_list { + char *ifname; + + struct { + char *alist_name; + /* struct access_list *alist; */ + int metric; + } direct[RIP_OFFSET_LIST_MAX]; }; static struct list *rip_offset_list_master; -static int -strcmp_safe (const char *s1, const char *s2) +static int strcmp_safe(const char *s1, const char *s2) { - if (s1 == NULL && s2 == NULL) - return 0; - if (s1 == NULL) - return -1; - if (s2 == NULL) - return 1; - return strcmp (s1, s2); + if (s1 == NULL && s2 == NULL) + return 0; + if (s1 == NULL) + return -1; + if (s2 == NULL) + return 1; + return strcmp(s1, s2); } -static struct rip_offset_list * -rip_offset_list_new (void) +static struct rip_offset_list *rip_offset_list_new(void) { - return XCALLOC (MTYPE_RIP_OFFSET_LIST, sizeof (struct rip_offset_list)); + return XCALLOC(MTYPE_RIP_OFFSET_LIST, sizeof(struct rip_offset_list)); } -static void -rip_offset_list_free (struct rip_offset_list *offset) +static void rip_offset_list_free(struct rip_offset_list *offset) { - XFREE (MTYPE_RIP_OFFSET_LIST, offset); + XFREE(MTYPE_RIP_OFFSET_LIST, offset); } -static struct rip_offset_list * -rip_offset_list_lookup (const char *ifname) +static struct rip_offset_list *rip_offset_list_lookup(const char *ifname) { - struct rip_offset_list *offset; - struct listnode *node, *nnode; + struct rip_offset_list *offset; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (rip_offset_list_master, node, nnode, offset)) - { - if (strcmp_safe (offset->ifname, ifname) == 0) - return offset; - } - return NULL; + for (ALL_LIST_ELEMENTS(rip_offset_list_master, node, nnode, offset)) { + if (strcmp_safe(offset->ifname, ifname) == 0) + return offset; + } + return NULL; } -static struct rip_offset_list * -rip_offset_list_get (const char *ifname) +static struct rip_offset_list *rip_offset_list_get(const char *ifname) { - struct rip_offset_list *offset; - - offset = rip_offset_list_lookup (ifname); - if (offset) - return offset; - - offset = rip_offset_list_new (); - if (ifname) - offset->ifname = strdup (ifname); - listnode_add_sort (rip_offset_list_master, offset); - - return offset; + struct rip_offset_list *offset; + + offset = rip_offset_list_lookup(ifname); + if (offset) + return offset; + + offset = rip_offset_list_new(); + if (ifname) + offset->ifname = strdup(ifname); + listnode_add_sort(rip_offset_list_master, offset); + + return offset; } -static int -rip_offset_list_set (struct vty *vty, const char *alist, const char *direct_str, - const char *metric_str, const char *ifname) +static int rip_offset_list_set(struct vty *vty, const char *alist, + const char *direct_str, const char *metric_str, + const char *ifname) { - int direct; - int metric; - struct rip_offset_list *offset; - - /* Check direction. */ - if (strncmp (direct_str, "i", 1) == 0) - direct = RIP_OFFSET_LIST_IN; - else if (strncmp (direct_str, "o", 1) == 0) - direct = RIP_OFFSET_LIST_OUT; - else - { - vty_out (vty, "Invalid direction: %s\n", direct_str); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check metric. */ - metric = atoi (metric_str); - if (metric < 0 || metric > 16) - { - vty_out (vty, "Invalid metric: %s\n", metric_str); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Get offset-list structure with interface name. */ - offset = rip_offset_list_get (ifname); - - if (offset->direct[direct].alist_name) - free (offset->direct[direct].alist_name); - offset->direct[direct].alist_name = strdup (alist); - offset->direct[direct].metric = metric; - - return CMD_SUCCESS; + int direct; + int metric; + struct rip_offset_list *offset; + + /* Check direction. */ + if (strncmp(direct_str, "i", 1) == 0) + direct = RIP_OFFSET_LIST_IN; + else if (strncmp(direct_str, "o", 1) == 0) + direct = RIP_OFFSET_LIST_OUT; + else { + vty_out(vty, "Invalid direction: %s\n", direct_str); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Check metric. */ + metric = atoi(metric_str); + if (metric < 0 || metric > 16) { + vty_out(vty, "Invalid metric: %s\n", metric_str); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Get offset-list structure with interface name. */ + offset = rip_offset_list_get(ifname); + + if (offset->direct[direct].alist_name) + free(offset->direct[direct].alist_name); + offset->direct[direct].alist_name = strdup(alist); + offset->direct[direct].metric = metric; + + return CMD_SUCCESS; } -static int -rip_offset_list_unset (struct vty *vty, const char *alist, - const char *direct_str, const char *metric_str, - const char *ifname) +static int rip_offset_list_unset(struct vty *vty, const char *alist, + const char *direct_str, const char *metric_str, + const char *ifname) { - int direct; - int metric; - struct rip_offset_list *offset; - - /* Check direction. */ - if (strncmp (direct_str, "i", 1) == 0) - direct = RIP_OFFSET_LIST_IN; - else if (strncmp (direct_str, "o", 1) == 0) - direct = RIP_OFFSET_LIST_OUT; - else - { - vty_out (vty, "Invalid direction: %s\n", direct_str); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check metric. */ - metric = atoi (metric_str); - if (metric < 0 || metric > 16) - { - vty_out (vty, "Invalid metric: %s\n", metric_str); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Get offset-list structure with interface name. */ - offset = rip_offset_list_lookup (ifname); - - if (offset) - { - if (offset->direct[direct].alist_name) - free (offset->direct[direct].alist_name); - offset->direct[direct].alist_name = NULL; - - if (offset->direct[RIP_OFFSET_LIST_IN].alist_name == NULL && - offset->direct[RIP_OFFSET_LIST_OUT].alist_name == NULL) - { - listnode_delete (rip_offset_list_master, offset); - if (offset->ifname) - free (offset->ifname); - rip_offset_list_free (offset); + int direct; + int metric; + struct rip_offset_list *offset; + + /* Check direction. */ + if (strncmp(direct_str, "i", 1) == 0) + direct = RIP_OFFSET_LIST_IN; + else if (strncmp(direct_str, "o", 1) == 0) + direct = RIP_OFFSET_LIST_OUT; + else { + vty_out(vty, "Invalid direction: %s\n", direct_str); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Check metric. */ + metric = atoi(metric_str); + if (metric < 0 || metric > 16) { + vty_out(vty, "Invalid metric: %s\n", metric_str); + return CMD_WARNING_CONFIG_FAILED; } - } - else - { - vty_out (vty, "Can't find offset-list\n"); - return CMD_WARNING_CONFIG_FAILED; - } - return CMD_SUCCESS; + + /* Get offset-list structure with interface name. */ + offset = rip_offset_list_lookup(ifname); + + if (offset) { + if (offset->direct[direct].alist_name) + free(offset->direct[direct].alist_name); + offset->direct[direct].alist_name = NULL; + + if (offset->direct[RIP_OFFSET_LIST_IN].alist_name == NULL + && offset->direct[RIP_OFFSET_LIST_OUT].alist_name == NULL) { + listnode_delete(rip_offset_list_master, offset); + if (offset->ifname) + free(offset->ifname); + rip_offset_list_free(offset); + } + } else { + vty_out(vty, "Can't find offset-list\n"); + return CMD_WARNING_CONFIG_FAILED; + } + return CMD_SUCCESS; } #define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIP_OFFSET_LIST_IN].alist_name) @@ -201,82 +184,78 @@ rip_offset_list_unset (struct vty *vty, const char *alist, #define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_OUT].metric) /* If metric is modifed return 1. */ -int -rip_offset_list_apply_in (struct prefix_ipv4 *p, struct interface *ifp, - u_int32_t *metric) +int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp, + u_int32_t *metric) { - struct rip_offset_list *offset; - struct access_list *alist; - - /* Look up offset-list with interface name. */ - offset = rip_offset_list_lookup (ifp->name); - if (offset && OFFSET_LIST_IN_NAME (offset)) - { - alist = access_list_lookup (AFI_IP, OFFSET_LIST_IN_NAME (offset)); - - if (alist - && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT) - { - *metric += OFFSET_LIST_IN_METRIC (offset); - return 1; + struct rip_offset_list *offset; + struct access_list *alist; + + /* Look up offset-list with interface name. */ + offset = rip_offset_list_lookup(ifp->name); + if (offset && OFFSET_LIST_IN_NAME(offset)) { + alist = access_list_lookup(AFI_IP, OFFSET_LIST_IN_NAME(offset)); + + if (alist + && access_list_apply(alist, (struct prefix *)p) + == FILTER_PERMIT) { + *metric += OFFSET_LIST_IN_METRIC(offset); + return 1; + } + return 0; } - return 0; - } - /* Look up offset-list without interface name. */ - offset = rip_offset_list_lookup (NULL); - if (offset && OFFSET_LIST_IN_NAME (offset)) - { - alist = access_list_lookup (AFI_IP, OFFSET_LIST_IN_NAME (offset)); - - if (alist - && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT) - { - *metric += OFFSET_LIST_IN_METRIC (offset); - return 1; + /* Look up offset-list without interface name. */ + offset = rip_offset_list_lookup(NULL); + if (offset && OFFSET_LIST_IN_NAME(offset)) { + alist = access_list_lookup(AFI_IP, OFFSET_LIST_IN_NAME(offset)); + + if (alist + && access_list_apply(alist, (struct prefix *)p) + == FILTER_PERMIT) { + *metric += OFFSET_LIST_IN_METRIC(offset); + return 1; + } + return 0; } - return 0; - } - return 0; + return 0; } /* If metric is modifed return 1. */ -int -rip_offset_list_apply_out (struct prefix_ipv4 *p, struct interface *ifp, - u_int32_t *metric) +int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp, + u_int32_t *metric) { - struct rip_offset_list *offset; - struct access_list *alist; - - /* Look up offset-list with interface name. */ - offset = rip_offset_list_lookup (ifp->name); - if (offset && OFFSET_LIST_OUT_NAME (offset)) - { - alist = access_list_lookup (AFI_IP, OFFSET_LIST_OUT_NAME (offset)); - - if (alist - && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT) - { - *metric += OFFSET_LIST_OUT_METRIC (offset); - return 1; + struct rip_offset_list *offset; + struct access_list *alist; + + /* Look up offset-list with interface name. */ + offset = rip_offset_list_lookup(ifp->name); + if (offset && OFFSET_LIST_OUT_NAME(offset)) { + alist = access_list_lookup(AFI_IP, + OFFSET_LIST_OUT_NAME(offset)); + + if (alist + && access_list_apply(alist, (struct prefix *)p) + == FILTER_PERMIT) { + *metric += OFFSET_LIST_OUT_METRIC(offset); + return 1; + } + return 0; } - return 0; - } - - /* Look up offset-list without interface name. */ - offset = rip_offset_list_lookup (NULL); - if (offset && OFFSET_LIST_OUT_NAME (offset)) - { - alist = access_list_lookup (AFI_IP, OFFSET_LIST_OUT_NAME (offset)); - - if (alist - && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT) - { - *metric += OFFSET_LIST_OUT_METRIC (offset); - return 1; + + /* Look up offset-list without interface name. */ + offset = rip_offset_list_lookup(NULL); + if (offset && OFFSET_LIST_OUT_NAME(offset)) { + alist = access_list_lookup(AFI_IP, + OFFSET_LIST_OUT_NAME(offset)); + + if (alist + && access_list_apply(alist, (struct prefix *)p) + == FILTER_PERMIT) { + *metric += OFFSET_LIST_OUT_METRIC(offset); + return 1; + } + return 0; } - return 0; - } - return 0; + return 0; } DEFUN (rip_offset_list, @@ -288,10 +267,12 @@ DEFUN (rip_offset_list, "For outgoing updates\n" "Metric value\n") { - int idx_word = 1; - int idx_in_out = 2; - int idx_number = 3; - return rip_offset_list_set (vty, argv[idx_word]->arg, argv[idx_in_out]->arg, argv[idx_number]->arg, NULL); + int idx_word = 1; + int idx_in_out = 2; + int idx_number = 3; + return rip_offset_list_set(vty, argv[idx_word]->arg, + argv[idx_in_out]->arg, argv[idx_number]->arg, + NULL); } DEFUN (rip_offset_list_ifname, @@ -304,11 +285,13 @@ DEFUN (rip_offset_list_ifname, "Metric value\n" "Interface to match\n") { - int idx_word = 1; - int idx_in_out = 2; - int idx_number = 3; - int idx_ifname = 4; - return rip_offset_list_set (vty, argv[idx_word]->arg, argv[idx_in_out]->arg, argv[idx_number]->arg, argv[idx_ifname]->arg); + int idx_word = 1; + int idx_in_out = 2; + int idx_number = 3; + int idx_ifname = 4; + return rip_offset_list_set(vty, argv[idx_word]->arg, + argv[idx_in_out]->arg, argv[idx_number]->arg, + argv[idx_ifname]->arg); } DEFUN (no_rip_offset_list, @@ -321,10 +304,12 @@ DEFUN (no_rip_offset_list, "For outgoing updates\n" "Metric value\n") { - int idx_word = 2; - int idx_in_out = 3; - int idx_number = 4; - return rip_offset_list_unset (vty, argv[idx_word]->arg, argv[idx_in_out]->arg, argv[idx_number]->arg, NULL); + int idx_word = 2; + int idx_in_out = 3; + int idx_number = 4; + return rip_offset_list_unset(vty, argv[idx_word]->arg, + argv[idx_in_out]->arg, + argv[idx_number]->arg, NULL); } DEFUN (no_rip_offset_list_ifname, @@ -338,87 +323,89 @@ DEFUN (no_rip_offset_list_ifname, "Metric value\n" "Interface to match\n") { - int idx_word = 2; - int idx_in_out = 3; - int idx_number = 4; - int idx_ifname = 5; - return rip_offset_list_unset (vty, argv[idx_word]->arg, argv[idx_in_out]->arg, argv[idx_number]->arg, argv[idx_ifname]->arg); + int idx_word = 2; + int idx_in_out = 3; + int idx_number = 4; + int idx_ifname = 5; + return rip_offset_list_unset( + vty, argv[idx_word]->arg, argv[idx_in_out]->arg, + argv[idx_number]->arg, argv[idx_ifname]->arg); } -static int -offset_list_cmp (struct rip_offset_list *o1, struct rip_offset_list *o2) +static int offset_list_cmp(struct rip_offset_list *o1, + struct rip_offset_list *o2) { - return strcmp_safe (o1->ifname, o2->ifname); + return strcmp_safe(o1->ifname, o2->ifname); } -static void -offset_list_del (struct rip_offset_list *offset) +static void offset_list_del(struct rip_offset_list *offset) { - if (OFFSET_LIST_IN_NAME (offset)) - free (OFFSET_LIST_IN_NAME (offset)); - if (OFFSET_LIST_OUT_NAME (offset)) - free (OFFSET_LIST_OUT_NAME (offset)); - if (offset->ifname) - free (offset->ifname); - rip_offset_list_free (offset); + if (OFFSET_LIST_IN_NAME(offset)) + free(OFFSET_LIST_IN_NAME(offset)); + if (OFFSET_LIST_OUT_NAME(offset)) + free(OFFSET_LIST_OUT_NAME(offset)); + if (offset->ifname) + free(offset->ifname); + rip_offset_list_free(offset); } -void -rip_offset_init () +void rip_offset_init() { - rip_offset_list_master = list_new (); - rip_offset_list_master->cmp = (int (*)(void *, void *)) offset_list_cmp; - rip_offset_list_master->del = (void (*)(void *)) offset_list_del; - - install_element (RIP_NODE, &rip_offset_list_cmd); - install_element (RIP_NODE, &rip_offset_list_ifname_cmd); - install_element (RIP_NODE, &no_rip_offset_list_cmd); - install_element (RIP_NODE, &no_rip_offset_list_ifname_cmd); + rip_offset_list_master = list_new(); + rip_offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp; + rip_offset_list_master->del = (void (*)(void *))offset_list_del; + + install_element(RIP_NODE, &rip_offset_list_cmd); + install_element(RIP_NODE, &rip_offset_list_ifname_cmd); + install_element(RIP_NODE, &no_rip_offset_list_cmd); + install_element(RIP_NODE, &no_rip_offset_list_ifname_cmd); } -void -rip_offset_clean () +void rip_offset_clean() { - list_delete (rip_offset_list_master); + list_delete(rip_offset_list_master); - rip_offset_list_master = list_new (); - rip_offset_list_master->cmp = (int (*)(void *, void *)) offset_list_cmp; - rip_offset_list_master->del = (void (*)(void *)) offset_list_del; + rip_offset_list_master = list_new(); + rip_offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp; + rip_offset_list_master->del = (void (*)(void *))offset_list_del; } -int -config_write_rip_offset_list (struct vty *vty) +int config_write_rip_offset_list(struct vty *vty) { - struct listnode *node, *nnode; - struct rip_offset_list *offset; - - for (ALL_LIST_ELEMENTS (rip_offset_list_master, node, nnode, offset)) - { - if (! offset->ifname) - { - if (offset->direct[RIP_OFFSET_LIST_IN].alist_name) - vty_out (vty, " offset-list %s in %d\n", - offset->direct[RIP_OFFSET_LIST_IN].alist_name, - offset->direct[RIP_OFFSET_LIST_IN].metric); - if (offset->direct[RIP_OFFSET_LIST_OUT].alist_name) - vty_out (vty, " offset-list %s out %d\n", - offset->direct[RIP_OFFSET_LIST_OUT].alist_name, - offset->direct[RIP_OFFSET_LIST_OUT].metric); - } - else - { - if (offset->direct[RIP_OFFSET_LIST_IN].alist_name) - vty_out (vty, " offset-list %s in %d %s\n", - offset->direct[RIP_OFFSET_LIST_IN].alist_name, - offset->direct[RIP_OFFSET_LIST_IN].metric, - offset->ifname); - if (offset->direct[RIP_OFFSET_LIST_OUT].alist_name) - vty_out (vty, " offset-list %s out %d %s\n", - offset->direct[RIP_OFFSET_LIST_OUT].alist_name, - offset->direct[RIP_OFFSET_LIST_OUT].metric, - offset->ifname); + struct listnode *node, *nnode; + struct rip_offset_list *offset; + + for (ALL_LIST_ELEMENTS(rip_offset_list_master, node, nnode, offset)) { + if (!offset->ifname) { + if (offset->direct[RIP_OFFSET_LIST_IN].alist_name) + vty_out(vty, " offset-list %s in %d\n", + offset->direct[RIP_OFFSET_LIST_IN] + .alist_name, + offset->direct[RIP_OFFSET_LIST_IN] + .metric); + if (offset->direct[RIP_OFFSET_LIST_OUT].alist_name) + vty_out(vty, " offset-list %s out %d\n", + offset->direct[RIP_OFFSET_LIST_OUT] + .alist_name, + offset->direct[RIP_OFFSET_LIST_OUT] + .metric); + } else { + if (offset->direct[RIP_OFFSET_LIST_IN].alist_name) + vty_out(vty, " offset-list %s in %d %s\n", + offset->direct[RIP_OFFSET_LIST_IN] + .alist_name, + offset->direct[RIP_OFFSET_LIST_IN] + .metric, + offset->ifname); + if (offset->direct[RIP_OFFSET_LIST_OUT].alist_name) + vty_out(vty, " offset-list %s out %d %s\n", + offset->direct[RIP_OFFSET_LIST_OUT] + .alist_name, + offset->direct[RIP_OFFSET_LIST_OUT] + .metric, + offset->ifname); + } } - } - return 0; + return 0; } diff --git a/ripd/rip_peer.c b/ripd/rip_peer.c index 7f494a098..763bfc142 100644 --- a/ripd/rip_peer.c +++ b/ripd/rip_peer.c @@ -32,175 +32,155 @@ /* Linked list of RIP peer. */ struct list *peer_list; -static struct rip_peer * -rip_peer_new (void) +static struct rip_peer *rip_peer_new(void) { - return XCALLOC (MTYPE_RIP_PEER, sizeof (struct rip_peer)); + return XCALLOC(MTYPE_RIP_PEER, sizeof(struct rip_peer)); } -static void -rip_peer_free (struct rip_peer *peer) +static void rip_peer_free(struct rip_peer *peer) { - XFREE (MTYPE_RIP_PEER, peer); + XFREE(MTYPE_RIP_PEER, peer); } -struct rip_peer * -rip_peer_lookup (struct in_addr *addr) +struct rip_peer *rip_peer_lookup(struct in_addr *addr) { - struct rip_peer *peer; - struct listnode *node, *nnode; - - for (ALL_LIST_ELEMENTS (peer_list, node, nnode, peer)) - { - if (IPV4_ADDR_SAME (&peer->addr, addr)) - return peer; - } - return NULL; + struct rip_peer *peer; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) { + if (IPV4_ADDR_SAME(&peer->addr, addr)) + return peer; + } + return NULL; } -struct rip_peer * -rip_peer_lookup_next (struct in_addr *addr) +struct rip_peer *rip_peer_lookup_next(struct in_addr *addr) { - struct rip_peer *peer; - struct listnode *node, *nnode; - - for (ALL_LIST_ELEMENTS (peer_list, node, nnode, peer)) - { - if (htonl (peer->addr.s_addr) > htonl (addr->s_addr)) - return peer; - } - return NULL; + struct rip_peer *peer; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) { + if (htonl(peer->addr.s_addr) > htonl(addr->s_addr)) + return peer; + } + return NULL; } /* RIP peer is timeout. */ -static int -rip_peer_timeout (struct thread *t) +static int rip_peer_timeout(struct thread *t) { - struct rip_peer *peer; + struct rip_peer *peer; - peer = THREAD_ARG (t); - listnode_delete (peer_list, peer); - rip_peer_free (peer); + peer = THREAD_ARG(t); + listnode_delete(peer_list, peer); + rip_peer_free(peer); - return 0; + return 0; } /* Get RIP peer. At the same time update timeout thread. */ -static struct rip_peer * -rip_peer_get (struct in_addr *addr) +static struct rip_peer *rip_peer_get(struct in_addr *addr) { - struct rip_peer *peer; - - peer = rip_peer_lookup (addr); - - if (peer) - { - if (peer->t_timeout) - thread_cancel (peer->t_timeout); - } - else - { - peer = rip_peer_new (); - peer->addr = *addr; - listnode_add_sort (peer_list, peer); - } - - /* Update timeout thread. */ - peer->t_timeout = NULL; - thread_add_timer(master, rip_peer_timeout, peer, RIP_PEER_TIMER_DEFAULT, - &peer->t_timeout); - - /* Last update time set. */ - time (&peer->uptime); - - return peer; + struct rip_peer *peer; + + peer = rip_peer_lookup(addr); + + if (peer) { + if (peer->t_timeout) + thread_cancel(peer->t_timeout); + } else { + peer = rip_peer_new(); + peer->addr = *addr; + listnode_add_sort(peer_list, peer); + } + + /* Update timeout thread. */ + peer->t_timeout = NULL; + thread_add_timer(master, rip_peer_timeout, peer, RIP_PEER_TIMER_DEFAULT, + &peer->t_timeout); + + /* Last update time set. */ + time(&peer->uptime); + + return peer; } -void -rip_peer_update (struct sockaddr_in *from, u_char version) +void rip_peer_update(struct sockaddr_in *from, u_char version) { - struct rip_peer *peer; - peer = rip_peer_get (&from->sin_addr); - peer->version = version; + struct rip_peer *peer; + peer = rip_peer_get(&from->sin_addr); + peer->version = version; } -void -rip_peer_bad_route (struct sockaddr_in *from) +void rip_peer_bad_route(struct sockaddr_in *from) { - struct rip_peer *peer; - peer = rip_peer_get (&from->sin_addr); - peer->recv_badroutes++; + struct rip_peer *peer; + peer = rip_peer_get(&from->sin_addr); + peer->recv_badroutes++; } -void -rip_peer_bad_packet (struct sockaddr_in *from) +void rip_peer_bad_packet(struct sockaddr_in *from) { - struct rip_peer *peer; - peer = rip_peer_get (&from->sin_addr); - peer->recv_badpackets++; + struct rip_peer *peer; + peer = rip_peer_get(&from->sin_addr); + peer->recv_badpackets++; } /* Display peer uptime. */ -static char * -rip_peer_uptime (struct rip_peer *peer, char *buf, size_t len) +static char *rip_peer_uptime(struct rip_peer *peer, char *buf, size_t len) { - time_t uptime; - struct tm *tm; - - /* If there is no connection has been done before print `never'. */ - if (peer->uptime == 0) - { - snprintf (buf, len, "never "); - return buf; - } - - /* Get current time. */ - uptime = time (NULL); - uptime -= peer->uptime; - tm = gmtime (&uptime); - - /* Making formatted timer strings. */ + time_t uptime; + struct tm *tm; + + /* If there is no connection has been done before print `never'. */ + if (peer->uptime == 0) { + snprintf(buf, len, "never "); + return buf; + } + + /* Get current time. */ + uptime = time(NULL); + uptime -= peer->uptime; + tm = gmtime(&uptime); + +/* Making formatted timer strings. */ #define ONE_DAY_SECOND 60*60*24 #define ONE_WEEK_SECOND 60*60*24*7 - if (uptime < ONE_DAY_SECOND) - snprintf (buf, len, "%02d:%02d:%02d", - tm->tm_hour, tm->tm_min, tm->tm_sec); - else if (uptime < ONE_WEEK_SECOND) - snprintf (buf, len, "%dd%02dh%02dm", - tm->tm_yday, tm->tm_hour, tm->tm_min); - else - snprintf (buf, len, "%02dw%dd%02dh", - tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); - return buf; + if (uptime < ONE_DAY_SECOND) + snprintf(buf, len, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, + tm->tm_sec); + else if (uptime < ONE_WEEK_SECOND) + snprintf(buf, len, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour, + tm->tm_min); + else + snprintf(buf, len, "%02dw%dd%02dh", tm->tm_yday / 7, + tm->tm_yday - ((tm->tm_yday / 7) * 7), tm->tm_hour); + return buf; } -void -rip_peer_display (struct vty *vty) +void rip_peer_display(struct vty *vty) { - struct rip_peer *peer; - struct listnode *node, *nnode; + struct rip_peer *peer; + struct listnode *node, *nnode; #define RIP_UPTIME_LEN 25 - char timebuf[RIP_UPTIME_LEN]; - - for (ALL_LIST_ELEMENTS (peer_list, node, nnode, peer)) - { - vty_out (vty, " %-16s %9d %9d %9d %s\n", inet_ntoa (peer->addr), - peer->recv_badpackets, peer->recv_badroutes, - ZEBRA_RIP_DISTANCE_DEFAULT, - rip_peer_uptime(peer, timebuf, RIP_UPTIME_LEN)); - } + char timebuf[RIP_UPTIME_LEN]; + + for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) { + vty_out(vty, " %-16s %9d %9d %9d %s\n", + inet_ntoa(peer->addr), peer->recv_badpackets, + peer->recv_badroutes, ZEBRA_RIP_DISTANCE_DEFAULT, + rip_peer_uptime(peer, timebuf, RIP_UPTIME_LEN)); + } } -static int -rip_peer_list_cmp (struct rip_peer *p1, struct rip_peer *p2) +static int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2) { - return htonl (p1->addr.s_addr) > htonl (p2->addr.s_addr); + return htonl(p1->addr.s_addr) > htonl(p2->addr.s_addr); } -void -rip_peer_init (void) +void rip_peer_init(void) { - peer_list = list_new (); - peer_list->cmp = (int (*)(void *, void *)) rip_peer_list_cmp; + peer_list = list_new(); + peer_list->cmp = (int (*)(void *, void *))rip_peer_list_cmp; } diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c index 3f1495c0f..7255df5e6 100644 --- a/ripd/rip_routemap.c +++ b/ripd/rip_routemap.c @@ -28,620 +28,552 @@ #include "command.h" #include "filter.h" #include "log.h" -#include "sockunion.h" /* for inet_aton () */ +#include "sockunion.h" /* for inet_aton () */ #include "plist.h" #include "vrf.h" #include "ripd/ripd.h" -struct rip_metric_modifier -{ - enum - { - metric_increment, - metric_decrement, - metric_absolute - } type; - - u_char metric; +struct rip_metric_modifier { + enum { metric_increment, metric_decrement, metric_absolute } type; + + u_char metric; }; /* Hook function for updating route_map assignment. */ /* ARGSUSED */ -static void -rip_route_map_update (const char *notused) +static void rip_route_map_update(const char *notused) { - int i; - - if (rip) - { - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - if (rip->route_map[i].name) - rip->route_map[i].map = - route_map_lookup_by_name (rip->route_map[i].name); + int i; + + if (rip) { + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (rip->route_map[i].name) + rip->route_map[i].map = + route_map_lookup_by_name( + rip->route_map[i].name); + } } - } } /* `match metric METRIC' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_metric (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - u_int32_t *metric; - u_int32_t check; - struct rip_info *rinfo; - - if (type == RMAP_RIP) - { - metric = rule; - rinfo = object; - - /* If external metric is available, the route-map should - work on this one (for redistribute purpose) */ - check = (rinfo->external_metric) ? rinfo->external_metric : - rinfo->metric; - if (check == *metric) - return RMAP_MATCH; - else +static route_map_result_t route_match_metric(void *rule, struct prefix *prefix, + route_map_object_t type, + void *object) +{ + u_int32_t *metric; + u_int32_t check; + struct rip_info *rinfo; + + if (type == RMAP_RIP) { + metric = rule; + rinfo = object; + + /* If external metric is available, the route-map should + work on this one (for redistribute purpose) */ + check = (rinfo->external_metric) ? rinfo->external_metric + : rinfo->metric; + if (check == *metric) + return RMAP_MATCH; + else + return RMAP_NOMATCH; + } return RMAP_NOMATCH; - } - return RMAP_NOMATCH; } /* Route map `match metric' match statement. `arg' is METRIC value */ -static void * -route_match_metric_compile (const char *arg) +static void *route_match_metric_compile(const char *arg) { - u_int32_t *metric; + u_int32_t *metric; - metric = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); - *metric = atoi (arg); + metric = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t)); + *metric = atoi(arg); - if(*metric > 0) - return metric; + if (*metric > 0) + return metric; - XFREE (MTYPE_ROUTE_MAP_COMPILED, metric); - return NULL; + XFREE(MTYPE_ROUTE_MAP_COMPILED, metric); + return NULL; } /* Free route map's compiled `match metric' value. */ -static void -route_match_metric_free (void *rule) +static void route_match_metric_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for metric matching. */ -struct route_map_rule_cmd route_match_metric_cmd = -{ - "metric", - route_match_metric, - route_match_metric_compile, - route_match_metric_free -}; +struct route_map_rule_cmd route_match_metric_cmd = { + "metric", route_match_metric, route_match_metric_compile, + route_match_metric_free}; /* `match interface IFNAME' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_interface (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_interface(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct rip_info *rinfo; - struct interface *ifp; - char *ifname; + struct rip_info *rinfo; + struct interface *ifp; + char *ifname; - if (type == RMAP_RIP) - { - ifname = rule; - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); + if (type == RMAP_RIP) { + ifname = rule; + ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - if (!ifp) - return RMAP_NOMATCH; + if (!ifp) + return RMAP_NOMATCH; - rinfo = object; + rinfo = object; - if (rinfo->ifindex_out == ifp->ifindex || rinfo->ifindex == ifp->ifindex) - return RMAP_MATCH; - else + if (rinfo->ifindex_out == ifp->ifindex + || rinfo->ifindex == ifp->ifindex) + return RMAP_MATCH; + else + return RMAP_NOMATCH; + } return RMAP_NOMATCH; - } - return RMAP_NOMATCH; } /* Route map `match interface' match statement. `arg' is IFNAME value */ /* XXX I don`t know if I need to check does interface exist? */ -static void * -route_match_interface_compile (const char *arg) +static void *route_match_interface_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `match interface' value. */ -static void -route_match_interface_free (void *rule) +static void route_match_interface_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for interface matching. */ -struct route_map_rule_cmd route_match_interface_cmd = -{ - "interface", - route_match_interface, - route_match_interface_compile, - route_match_interface_free -}; +struct route_map_rule_cmd route_match_interface_cmd = { + "interface", route_match_interface, route_match_interface_compile, + route_match_interface_free}; /* `match ip next-hop IP_ACCESS_LIST' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_ip_next_hop (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct access_list *alist; - struct rip_info *rinfo; - struct prefix_ipv4 p; - - if (type == RMAP_RIP) - { - rinfo = object; - p.family = AF_INET; - p.prefix = (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from; - p.prefixlen = IPV4_MAX_BITLEN; - - alist = access_list_lookup (AFI_IP, (char *) rule); - if (alist == NULL) +static route_map_result_t route_match_ip_next_hop(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct access_list *alist; + struct rip_info *rinfo; + struct prefix_ipv4 p; + + if (type == RMAP_RIP) { + rinfo = object; + p.family = AF_INET; + p.prefix = + (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from; + p.prefixlen = IPV4_MAX_BITLEN; + + alist = access_list_lookup(AFI_IP, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; + + return (access_list_apply(alist, &p) == FILTER_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } return RMAP_NOMATCH; - - return (access_list_apply (alist, &p) == FILTER_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; } /* Route map `ip next-hop' match statement. `arg' should be access-list name. */ -static void * -route_match_ip_next_hop_compile (const char *arg) +static void *route_match_ip_next_hop_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `. */ -static void -route_match_ip_next_hop_free (void *rule) +static void route_match_ip_next_hop_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip next-hop matching. */ -static struct route_map_rule_cmd route_match_ip_next_hop_cmd = -{ - "ip next-hop", - route_match_ip_next_hop, - route_match_ip_next_hop_compile, - route_match_ip_next_hop_free -}; +static struct route_map_rule_cmd route_match_ip_next_hop_cmd = { + "ip next-hop", route_match_ip_next_hop, route_match_ip_next_hop_compile, + route_match_ip_next_hop_free}; /* `match ip next-hop prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - struct prefix_list *plist; - struct rip_info *rinfo; - struct prefix_ipv4 p; - - if (type == RMAP_RIP) - { - rinfo = object; - p.family = AF_INET; - p.prefix = (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from; - p.prefixlen = IPV4_MAX_BITLEN; - - plist = prefix_list_lookup (AFI_IP, (char *) rule); - if (plist == NULL) - return RMAP_NOMATCH; - - return (prefix_list_apply (plist, &p) == PREFIX_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; + struct prefix_list *plist; + struct rip_info *rinfo; + struct prefix_ipv4 p; + + if (type == RMAP_RIP) { + rinfo = object; + p.family = AF_INET; + p.prefix = + (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from; + p.prefixlen = IPV4_MAX_BITLEN; + + plist = prefix_list_lookup(AFI_IP, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; + + return (prefix_list_apply(plist, &p) == PREFIX_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } + return RMAP_NOMATCH; } -static void * -route_match_ip_next_hop_prefix_list_compile (const char *arg) +static void *route_match_ip_next_hop_prefix_list_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ip_next_hop_prefix_list_free (void *rule) +static void route_match_ip_next_hop_prefix_list_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = -{ - "ip next-hop prefix-list", - route_match_ip_next_hop_prefix_list, - route_match_ip_next_hop_prefix_list_compile, - route_match_ip_next_hop_prefix_list_free -}; +static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = { + "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list, + route_match_ip_next_hop_prefix_list_compile, + route_match_ip_next_hop_prefix_list_free}; /* `match ip address IP_ACCESS_LIST' */ /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t -route_match_ip_address (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_ip_address(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct access_list *alist; + struct access_list *alist; - if (type == RMAP_RIP) - { - alist = access_list_lookup (AFI_IP, (char *) rule); - if (alist == NULL) + if (type == RMAP_RIP) { + alist = access_list_lookup(AFI_IP, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; + + return (access_list_apply(alist, prefix) == FILTER_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } return RMAP_NOMATCH; - - return (access_list_apply (alist, prefix) == FILTER_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; } /* Route map `ip address' match statement. `arg' should be access-list name. */ -static void * -route_match_ip_address_compile (const char *arg) +static void *route_match_ip_address_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `ip address' value. */ -static void -route_match_ip_address_free (void *rule) +static void route_match_ip_address_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip address matching. */ -static struct route_map_rule_cmd route_match_ip_address_cmd = -{ - "ip address", - route_match_ip_address, - route_match_ip_address_compile, - route_match_ip_address_free -}; +static struct route_map_rule_cmd route_match_ip_address_cmd = { + "ip address", route_match_ip_address, route_match_ip_address_compile, + route_match_ip_address_free}; /* `match ip address prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_address_prefix_list (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - struct prefix_list *plist; + struct prefix_list *plist; - if (type == RMAP_RIP) - { - plist = prefix_list_lookup (AFI_IP, (char *) rule); - if (plist == NULL) + if (type == RMAP_RIP) { + plist = prefix_list_lookup(AFI_IP, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; + + return (prefix_list_apply(plist, prefix) == PREFIX_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } return RMAP_NOMATCH; - - return (prefix_list_apply (plist, prefix) == PREFIX_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; } -static void * -route_match_ip_address_prefix_list_compile (const char *arg) +static void *route_match_ip_address_prefix_list_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ip_address_prefix_list_free (void *rule) +static void route_match_ip_address_prefix_list_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = -{ - "ip address prefix-list", - route_match_ip_address_prefix_list, - route_match_ip_address_prefix_list_compile, - route_match_ip_address_prefix_list_free -}; +static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { + "ip address prefix-list", route_match_ip_address_prefix_list, + route_match_ip_address_prefix_list_compile, + route_match_ip_address_prefix_list_free}; /* `match tag TAG' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_tag (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - route_tag_t *tag; - struct rip_info *rinfo; - route_tag_t rinfo_tag; - - if (type == RMAP_RIP) - { - tag = rule; - rinfo = object; - - /* The information stored by rinfo is host ordered. */ - rinfo_tag = rinfo->tag; - if (rinfo_tag == *tag) - return RMAP_MATCH; - else +static route_map_result_t route_match_tag(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + route_tag_t *tag; + struct rip_info *rinfo; + route_tag_t rinfo_tag; + + if (type == RMAP_RIP) { + tag = rule; + rinfo = object; + + /* The information stored by rinfo is host ordered. */ + rinfo_tag = rinfo->tag; + if (rinfo_tag == *tag) + return RMAP_MATCH; + else + return RMAP_NOMATCH; + } return RMAP_NOMATCH; - } - return RMAP_NOMATCH; } /* Route map commands for tag matching. */ -static struct route_map_rule_cmd route_match_tag_cmd = -{ - "tag", - route_match_tag, - route_map_rule_tag_compile, - route_map_rule_tag_free, +static struct route_map_rule_cmd route_match_tag_cmd = { + "tag", route_match_tag, route_map_rule_tag_compile, + route_map_rule_tag_free, }; /* `set metric METRIC' */ /* Set metric to attribute. */ -static route_map_result_t -route_set_metric (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - if (type == RMAP_RIP) - { - struct rip_metric_modifier *mod; - struct rip_info *rinfo; - - mod = rule; - rinfo = object; - - if (mod->type == metric_increment) - rinfo->metric_out += mod->metric; - else if (mod->type == metric_decrement) - rinfo->metric_out -= mod->metric; - else if (mod->type == metric_absolute) - rinfo->metric_out = mod->metric; - - if ((signed int)rinfo->metric_out < 1) - rinfo->metric_out = 1; - if (rinfo->metric_out > RIP_METRIC_INFINITY) - rinfo->metric_out = RIP_METRIC_INFINITY; - - rinfo->metric_set = 1; - } - return RMAP_OKAY; +static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, + route_map_object_t type, + void *object) +{ + if (type == RMAP_RIP) { + struct rip_metric_modifier *mod; + struct rip_info *rinfo; + + mod = rule; + rinfo = object; + + if (mod->type == metric_increment) + rinfo->metric_out += mod->metric; + else if (mod->type == metric_decrement) + rinfo->metric_out -= mod->metric; + else if (mod->type == metric_absolute) + rinfo->metric_out = mod->metric; + + if ((signed int)rinfo->metric_out < 1) + rinfo->metric_out = 1; + if (rinfo->metric_out > RIP_METRIC_INFINITY) + rinfo->metric_out = RIP_METRIC_INFINITY; + + rinfo->metric_set = 1; + } + return RMAP_OKAY; } /* set metric compilation. */ -static void * -route_set_metric_compile (const char *arg) -{ - int len; - const char *pnt; - int type; - long metric; - char *endptr = NULL; - struct rip_metric_modifier *mod; - - len = strlen (arg); - pnt = arg; - - if (len == 0) - return NULL; - - /* Examine first character. */ - if (arg[0] == '+') - { - type = metric_increment; - pnt++; - } - else if (arg[0] == '-') - { - type = metric_decrement; - pnt++; - } - else - type = metric_absolute; - - /* Check beginning with digit string. */ - if (*pnt < '0' || *pnt > '9') - return NULL; - - /* Convert string to integer. */ - metric = strtol (pnt, &endptr, 10); - - if (metric == LONG_MAX || *endptr != '\0') - return NULL; - if (metric < 0 || metric > RIP_METRIC_INFINITY) - return NULL; - - mod = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, - sizeof (struct rip_metric_modifier)); - mod->type = type; - mod->metric = metric; - - return mod; +static void *route_set_metric_compile(const char *arg) +{ + int len; + const char *pnt; + int type; + long metric; + char *endptr = NULL; + struct rip_metric_modifier *mod; + + len = strlen(arg); + pnt = arg; + + if (len == 0) + return NULL; + + /* Examine first character. */ + if (arg[0] == '+') { + type = metric_increment; + pnt++; + } else if (arg[0] == '-') { + type = metric_decrement; + pnt++; + } else + type = metric_absolute; + + /* Check beginning with digit string. */ + if (*pnt < '0' || *pnt > '9') + return NULL; + + /* Convert string to integer. */ + metric = strtol(pnt, &endptr, 10); + + if (metric == LONG_MAX || *endptr != '\0') + return NULL; + if (metric < 0 || metric > RIP_METRIC_INFINITY) + return NULL; + + mod = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, + sizeof(struct rip_metric_modifier)); + mod->type = type; + mod->metric = metric; + + return mod; } /* Free route map's compiled `set metric' value. */ -static void -route_set_metric_free (void *rule) +static void route_set_metric_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Set metric rule structure. */ -static struct route_map_rule_cmd route_set_metric_cmd = -{ - "metric", - route_set_metric, - route_set_metric_compile, - route_set_metric_free, +static struct route_map_rule_cmd route_set_metric_cmd = { + "metric", route_set_metric, route_set_metric_compile, + route_set_metric_free, }; /* `set ip next-hop IP_ADDRESS' */ /* Set nexthop to object. ojbect must be pointer to struct attr. */ -static route_map_result_t -route_set_ip_nexthop (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_ip_nexthop(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct in_addr *address; - struct rip_info *rinfo; - - if(type == RMAP_RIP) - { - /* Fetch routemap's rule information. */ - address = rule; - rinfo = object; - - /* Set next hop value. */ - rinfo->nexthop_out = *address; - } - - return RMAP_OKAY; + struct in_addr *address; + struct rip_info *rinfo; + + if (type == RMAP_RIP) { + /* Fetch routemap's rule information. */ + address = rule; + rinfo = object; + + /* Set next hop value. */ + rinfo->nexthop_out = *address; + } + + return RMAP_OKAY; } /* Route map `ip nexthop' compile function. Given string is converted to struct in_addr structure. */ -static void * -route_set_ip_nexthop_compile (const char *arg) +static void *route_set_ip_nexthop_compile(const char *arg) { - int ret; - struct in_addr *address; + int ret; + struct in_addr *address; - address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr)); + address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr)); - ret = inet_aton (arg, address); + ret = inet_aton(arg, address); - if (ret == 0) - { - XFREE (MTYPE_ROUTE_MAP_COMPILED, address); - return NULL; - } + if (ret == 0) { + XFREE(MTYPE_ROUTE_MAP_COMPILED, address); + return NULL; + } - return address; + return address; } /* Free route map's compiled `ip nexthop' value. */ -static void -route_set_ip_nexthop_free (void *rule) +static void route_set_ip_nexthop_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip nexthop set. */ -static struct route_map_rule_cmd route_set_ip_nexthop_cmd = -{ - "ip next-hop", - route_set_ip_nexthop, - route_set_ip_nexthop_compile, - route_set_ip_nexthop_free -}; +static struct route_map_rule_cmd route_set_ip_nexthop_cmd = { + "ip next-hop", route_set_ip_nexthop, route_set_ip_nexthop_compile, + route_set_ip_nexthop_free}; /* `set tag TAG' */ /* Set tag to object. ojbect must be pointer to struct attr. */ -static route_map_result_t -route_set_tag (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_tag(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - route_tag_t *tag; - struct rip_info *rinfo; - - if(type == RMAP_RIP) - { - /* Fetch routemap's rule information. */ - tag = rule; - rinfo = object; - - /* Set next hop value. */ - rinfo->tag_out = *tag; - } - - return RMAP_OKAY; + route_tag_t *tag; + struct rip_info *rinfo; + + if (type == RMAP_RIP) { + /* Fetch routemap's rule information. */ + tag = rule; + rinfo = object; + + /* Set next hop value. */ + rinfo->tag_out = *tag; + } + + return RMAP_OKAY; } /* Route map commands for tag set. */ -static struct route_map_rule_cmd route_set_tag_cmd = -{ - "tag", - route_set_tag, - route_map_rule_tag_compile, - route_map_rule_tag_free -}; +static struct route_map_rule_cmd route_set_tag_cmd = { + "tag", route_set_tag, route_map_rule_tag_compile, + route_map_rule_tag_free}; #define MATCH_STR "Match values from routing table\n" #define SET_STR "Set values in destination routing protocol\n" -void -rip_route_map_reset () +void rip_route_map_reset() { - ; + ; } /* Route-map init */ -void -rip_route_map_init () +void rip_route_map_init() { - route_map_init (); + route_map_init(); - route_map_add_hook (rip_route_map_update); - route_map_delete_hook (rip_route_map_update); + route_map_add_hook(rip_route_map_update); + route_map_delete_hook(rip_route_map_update); - route_map_match_interface_hook (generic_match_add); - route_map_no_match_interface_hook (generic_match_delete); + route_map_match_interface_hook(generic_match_add); + route_map_no_match_interface_hook(generic_match_delete); - route_map_match_ip_address_hook (generic_match_add); - route_map_no_match_ip_address_hook (generic_match_delete); + route_map_match_ip_address_hook(generic_match_add); + route_map_no_match_ip_address_hook(generic_match_delete); - route_map_match_ip_address_prefix_list_hook (generic_match_add); - route_map_no_match_ip_address_prefix_list_hook (generic_match_delete); + route_map_match_ip_address_prefix_list_hook(generic_match_add); + route_map_no_match_ip_address_prefix_list_hook(generic_match_delete); - route_map_match_ip_next_hop_hook (generic_match_add); - route_map_no_match_ip_next_hop_hook (generic_match_delete); + route_map_match_ip_next_hop_hook(generic_match_add); + route_map_no_match_ip_next_hop_hook(generic_match_delete); - route_map_match_ip_next_hop_prefix_list_hook (generic_match_add); - route_map_no_match_ip_next_hop_prefix_list_hook (generic_match_delete); + route_map_match_ip_next_hop_prefix_list_hook(generic_match_add); + route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete); - route_map_match_metric_hook (generic_match_add); - route_map_no_match_metric_hook (generic_match_delete); + route_map_match_metric_hook(generic_match_add); + route_map_no_match_metric_hook(generic_match_delete); - route_map_match_tag_hook (generic_match_add); - route_map_no_match_tag_hook (generic_match_delete); + route_map_match_tag_hook(generic_match_add); + route_map_no_match_tag_hook(generic_match_delete); - route_map_set_ip_nexthop_hook (generic_set_add); - route_map_no_set_ip_nexthop_hook (generic_set_delete); + route_map_set_ip_nexthop_hook(generic_set_add); + route_map_no_set_ip_nexthop_hook(generic_set_delete); - route_map_set_metric_hook (generic_set_add); - route_map_no_set_metric_hook (generic_set_delete); + route_map_set_metric_hook(generic_set_add); + route_map_no_set_metric_hook(generic_set_delete); - route_map_set_tag_hook (generic_set_add); - route_map_no_set_tag_hook (generic_set_delete); + route_map_set_tag_hook(generic_set_add); + route_map_no_set_tag_hook(generic_set_delete); - route_map_install_match (&route_match_metric_cmd); - route_map_install_match (&route_match_interface_cmd); - route_map_install_match (&route_match_ip_next_hop_cmd); - route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd); - route_map_install_match (&route_match_ip_address_cmd); - route_map_install_match (&route_match_ip_address_prefix_list_cmd); - route_map_install_match (&route_match_tag_cmd); + route_map_install_match(&route_match_metric_cmd); + route_map_install_match(&route_match_interface_cmd); + route_map_install_match(&route_match_ip_next_hop_cmd); + route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd); + route_map_install_match(&route_match_ip_address_cmd); + route_map_install_match(&route_match_ip_address_prefix_list_cmd); + route_map_install_match(&route_match_tag_cmd); - route_map_install_set (&route_set_metric_cmd); - route_map_install_set (&route_set_ip_nexthop_cmd); - route_map_install_set (&route_set_tag_cmd); + route_map_install_set(&route_set_metric_cmd); + route_map_install_set(&route_set_ip_nexthop_cmd); + route_map_install_set(&route_set_tag_cmd); } diff --git a/ripd/rip_snmp.c b/ripd/rip_snmp.c index 6a4ae11ae..45bb2e377 100644 --- a/ripd/rip_snmp.c +++ b/ripd/rip_snmp.c @@ -82,319 +82,311 @@ SNMP_LOCAL_VARIABLES /* RIP-MIB instances. */ -static oid rip_oid [] = { RIPV2MIB }; +static oid rip_oid[] = {RIPV2MIB}; /* Interface cache table sorted by interface's address. */ static struct route_table *rip_ifaddr_table; /* Hook functions. */ -static u_char *rip2Globals (struct variable *, oid [], size_t *, - int, size_t *, WriteMethod **); -static u_char *rip2IfStatEntry (struct variable *, oid [], size_t *, - int, size_t *, WriteMethod **); -static u_char *rip2IfConfAddress (struct variable *, oid [], size_t *, - int, size_t *, WriteMethod **); -static u_char *rip2PeerTable (struct variable *, oid [], size_t *, - int, size_t *, WriteMethod **); - -static struct variable rip_variables[] = -{ - /* RIP Global Counters. */ - {RIP2GLOBALROUTECHANGES, COUNTER, RONLY, rip2Globals, - 2, {1, 1}}, - {RIP2GLOBALQUERIES, COUNTER, RONLY, rip2Globals, - 2, {1, 2}}, - /* RIP Interface Tables. */ - {RIP2IFSTATADDRESS, IPADDRESS, RONLY, rip2IfStatEntry, - 3, {2, 1, 1}}, - {RIP2IFSTATRCVBADPACKETS, COUNTER, RONLY, rip2IfStatEntry, - 3, {2, 1, 2}}, - {RIP2IFSTATRCVBADROUTES, COUNTER, RONLY, rip2IfStatEntry, - 3, {2, 1, 3}}, - {RIP2IFSTATSENTUPDATES, COUNTER, RONLY, rip2IfStatEntry, - 3, {2, 1, 4}}, - {RIP2IFSTATSTATUS, COUNTER, RWRITE, rip2IfStatEntry, - 3, {2, 1, 5}}, - {RIP2IFCONFADDRESS, IPADDRESS, RONLY, rip2IfConfAddress, - /* RIP Interface Configuration Table. */ - 3, {3, 1, 1}}, - {RIP2IFCONFDOMAIN, STRING, RONLY, rip2IfConfAddress, - 3, {3, 1, 2}}, - {RIP2IFCONFAUTHTYPE, COUNTER, RONLY, rip2IfConfAddress, - 3, {3, 1, 3}}, - {RIP2IFCONFAUTHKEY, STRING, RONLY, rip2IfConfAddress, - 3, {3, 1, 4}}, - {RIP2IFCONFSEND, COUNTER, RONLY, rip2IfConfAddress, - 3, {3, 1, 5}}, - {RIP2IFCONFRECEIVE, COUNTER, RONLY, rip2IfConfAddress, - 3, {3, 1, 6}}, - {RIP2IFCONFDEFAULTMETRIC, COUNTER, RONLY, rip2IfConfAddress, - 3, {3, 1, 7}}, - {RIP2IFCONFSTATUS, COUNTER, RONLY, rip2IfConfAddress, - 3, {3, 1, 8}}, - {RIP2IFCONFSRCADDRESS, IPADDRESS, RONLY, rip2IfConfAddress, - 3, {3, 1, 9}}, - {RIP2PEERADDRESS, IPADDRESS, RONLY, rip2PeerTable, - /* RIP Peer Table. */ - 3, {4, 1, 1}}, - {RIP2PEERDOMAIN, STRING, RONLY, rip2PeerTable, - 3, {4, 1, 2}}, - {RIP2PEERLASTUPDATE, TIMETICKS, RONLY, rip2PeerTable, - 3, {4, 1, 3}}, - {RIP2PEERVERSION, INTEGER, RONLY, rip2PeerTable, - 3, {4, 1, 4}}, - {RIP2PEERRCVBADPACKETS, COUNTER, RONLY, rip2PeerTable, - 3, {4, 1, 5}}, - {RIP2PEERRCVBADROUTES, COUNTER, RONLY, rip2PeerTable, - 3, {4, 1, 6}} -}; +static u_char *rip2Globals(struct variable *, oid[], size_t *, int, size_t *, + WriteMethod **); +static u_char *rip2IfStatEntry(struct variable *, oid[], size_t *, int, + size_t *, WriteMethod **); +static u_char *rip2IfConfAddress(struct variable *, oid[], size_t *, int, + size_t *, WriteMethod **); +static u_char *rip2PeerTable(struct variable *, oid[], size_t *, int, size_t *, + WriteMethod **); + +static struct variable rip_variables[] = { + /* RIP Global Counters. */ + {RIP2GLOBALROUTECHANGES, COUNTER, RONLY, rip2Globals, 2, {1, 1}}, + {RIP2GLOBALQUERIES, COUNTER, RONLY, rip2Globals, 2, {1, 2}}, + /* RIP Interface Tables. */ + {RIP2IFSTATADDRESS, IPADDRESS, RONLY, rip2IfStatEntry, 3, {2, 1, 1}}, + {RIP2IFSTATRCVBADPACKETS, + COUNTER, + RONLY, + rip2IfStatEntry, + 3, + {2, 1, 2}}, + {RIP2IFSTATRCVBADROUTES, COUNTER, RONLY, rip2IfStatEntry, 3, {2, 1, 3}}, + {RIP2IFSTATSENTUPDATES, COUNTER, RONLY, rip2IfStatEntry, 3, {2, 1, 4}}, + {RIP2IFSTATSTATUS, COUNTER, RWRITE, rip2IfStatEntry, 3, {2, 1, 5}}, + {RIP2IFCONFADDRESS, + IPADDRESS, + RONLY, + rip2IfConfAddress, + /* RIP Interface Configuration Table. */ + 3, + {3, 1, 1}}, + {RIP2IFCONFDOMAIN, STRING, RONLY, rip2IfConfAddress, 3, {3, 1, 2}}, + {RIP2IFCONFAUTHTYPE, COUNTER, RONLY, rip2IfConfAddress, 3, {3, 1, 3}}, + {RIP2IFCONFAUTHKEY, STRING, RONLY, rip2IfConfAddress, 3, {3, 1, 4}}, + {RIP2IFCONFSEND, COUNTER, RONLY, rip2IfConfAddress, 3, {3, 1, 5}}, + {RIP2IFCONFRECEIVE, COUNTER, RONLY, rip2IfConfAddress, 3, {3, 1, 6}}, + {RIP2IFCONFDEFAULTMETRIC, + COUNTER, + RONLY, + rip2IfConfAddress, + 3, + {3, 1, 7}}, + {RIP2IFCONFSTATUS, COUNTER, RONLY, rip2IfConfAddress, 3, {3, 1, 8}}, + {RIP2IFCONFSRCADDRESS, + IPADDRESS, + RONLY, + rip2IfConfAddress, + 3, + {3, 1, 9}}, + {RIP2PEERADDRESS, + IPADDRESS, + RONLY, + rip2PeerTable, + /* RIP Peer Table. */ + 3, + {4, 1, 1}}, + {RIP2PEERDOMAIN, STRING, RONLY, rip2PeerTable, 3, {4, 1, 2}}, + {RIP2PEERLASTUPDATE, TIMETICKS, RONLY, rip2PeerTable, 3, {4, 1, 3}}, + {RIP2PEERVERSION, INTEGER, RONLY, rip2PeerTable, 3, {4, 1, 4}}, + {RIP2PEERRCVBADPACKETS, COUNTER, RONLY, rip2PeerTable, 3, {4, 1, 5}}, + {RIP2PEERRCVBADROUTES, COUNTER, RONLY, rip2PeerTable, 3, {4, 1, 6}}}; extern struct thread_master *master; -static u_char * -rip2Globals (struct variable *v, oid name[], size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *rip2Globals(struct variable *v, oid name[], size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - if (smux_header_generic(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - /* Retrun global counter. */ - switch (v->magic) - { - case RIP2GLOBALROUTECHANGES: - return SNMP_INTEGER (rip_global_route_changes); - break; - case RIP2GLOBALQUERIES: - return SNMP_INTEGER (rip_global_queries); - break; - default: - return NULL; - break; - } - return NULL; + if (smux_header_generic(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + /* Retrun global counter. */ + switch (v->magic) { + case RIP2GLOBALROUTECHANGES: + return SNMP_INTEGER(rip_global_route_changes); + break; + case RIP2GLOBALQUERIES: + return SNMP_INTEGER(rip_global_queries); + break; + default: + return NULL; + break; + } + return NULL; } -static int -rip_snmp_ifaddr_add (struct connected *ifc) +static int rip_snmp_ifaddr_add(struct connected *ifc) { - struct interface *ifp = ifc->ifp; - struct prefix *p; - struct route_node *rn; + struct interface *ifp = ifc->ifp; + struct prefix *p; + struct route_node *rn; - p = ifc->address; + p = ifc->address; - if (p->family != AF_INET) - return 0; + if (p->family != AF_INET) + return 0; - rn = route_node_get (rip_ifaddr_table, p); - rn->info = ifp; - return 0; + rn = route_node_get(rip_ifaddr_table, p); + rn->info = ifp; + return 0; } -static int -rip_snmp_ifaddr_del (struct connected *ifc) +static int rip_snmp_ifaddr_del(struct connected *ifc) { - struct interface *ifp = ifc->ifp; - struct prefix *p; - struct route_node *rn; - struct interface *i; - - p = ifc->address; - - if (p->family != AF_INET) - return 0; - - rn = route_node_lookup (rip_ifaddr_table, p); - if (! rn) - return 0; - i = rn->info; - if (rn && !strncmp(i->name,ifp->name,INTERFACE_NAMSIZ)) - { - rn->info = NULL; - route_unlock_node (rn); - route_unlock_node (rn); - } - return 0; + struct interface *ifp = ifc->ifp; + struct prefix *p; + struct route_node *rn; + struct interface *i; + + p = ifc->address; + + if (p->family != AF_INET) + return 0; + + rn = route_node_lookup(rip_ifaddr_table, p); + if (!rn) + return 0; + i = rn->info; + if (rn && !strncmp(i->name, ifp->name, INTERFACE_NAMSIZ)) { + rn->info = NULL; + route_unlock_node(rn); + route_unlock_node(rn); + } + return 0; } -static struct interface * -rip_ifaddr_lookup_next (struct in_addr *addr) +static struct interface *rip_ifaddr_lookup_next(struct in_addr *addr) { - struct prefix_ipv4 p; - struct route_node *rn; - struct interface *ifp; - - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - p.prefix = *addr; - - rn = route_node_get (rip_ifaddr_table, (struct prefix *) &p); - - for (rn = route_next (rn); rn; rn = route_next (rn)) - if (rn->info) - break; - - if (rn && rn->info) - { - ifp = rn->info; - *addr = rn->p.u.prefix4; - route_unlock_node (rn); - return ifp; - } - return NULL; + struct prefix_ipv4 p; + struct route_node *rn; + struct interface *ifp; + + p.family = AF_INET; + p.prefixlen = IPV4_MAX_BITLEN; + p.prefix = *addr; + + rn = route_node_get(rip_ifaddr_table, (struct prefix *)&p); + + for (rn = route_next(rn); rn; rn = route_next(rn)) + if (rn->info) + break; + + if (rn && rn->info) { + ifp = rn->info; + *addr = rn->p.u.prefix4; + route_unlock_node(rn); + return ifp; + } + return NULL; } -static struct interface * -rip2IfLookup (struct variable *v, oid name[], size_t *length, - struct in_addr *addr, int exact) +static struct interface *rip2IfLookup(struct variable *v, oid name[], + size_t *length, struct in_addr *addr, + int exact) { - int len; - struct interface *ifp; - - if (exact) - { - /* Check the length. */ - if (*length - v->namelen != sizeof (struct in_addr)) - return NULL; + int len; + struct interface *ifp; - oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr); + if (exact) { + /* Check the length. */ + if (*length - v->namelen != sizeof(struct in_addr)) + return NULL; - return if_lookup_exact_address ((void *)addr, AF_INET, VRF_DEFAULT); - } - else - { - len = *length - v->namelen; - if (len > 4) len = 4; + oid2in_addr(name + v->namelen, sizeof(struct in_addr), addr); - oid2in_addr (name + v->namelen, len, addr); + return if_lookup_exact_address((void *)addr, AF_INET, + VRF_DEFAULT); + } else { + len = *length - v->namelen; + if (len > 4) + len = 4; - ifp = rip_ifaddr_lookup_next (addr); + oid2in_addr(name + v->namelen, len, addr); - if (ifp == NULL) - return NULL; + ifp = rip_ifaddr_lookup_next(addr); - oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr)); + if (ifp == NULL) + return NULL; - *length = v->namelen + sizeof (struct in_addr); + oid_copy_addr(name + v->namelen, addr, sizeof(struct in_addr)); - return ifp; - } - return NULL; -} + *length = v->namelen + sizeof(struct in_addr); -static struct rip_peer * -rip2PeerLookup (struct variable *v, oid name[], size_t *length, - struct in_addr *addr, int exact) -{ - int len; - struct rip_peer *peer; - - if (exact) - { - /* Check the length. */ - if (*length - v->namelen != sizeof (struct in_addr) + 1) + return ifp; + } return NULL; +} - oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr); - - peer = rip_peer_lookup (addr); - - if (peer->domain == (int)name[v->namelen + sizeof (struct in_addr)]) - return peer; - - return NULL; - } - else - { - len = *length - v->namelen; - if (len > 4) len = 4; - - oid2in_addr (name + v->namelen, len, addr); - - len = *length - v->namelen; - peer = rip_peer_lookup (addr); - if (peer) - { - if ((len < (int)sizeof (struct in_addr) + 1) || - (peer->domain > (int)name[v->namelen + sizeof (struct in_addr)])) - { - oid_copy_addr (name + v->namelen, &peer->addr, - sizeof (struct in_addr)); - name[v->namelen + sizeof (struct in_addr)] = peer->domain; - *length = sizeof (struct in_addr) + v->namelen + 1; - return peer; - } - } - peer = rip_peer_lookup_next (addr); - - if (! peer) +static struct rip_peer *rip2PeerLookup(struct variable *v, oid name[], + size_t *length, struct in_addr *addr, + int exact) +{ + int len; + struct rip_peer *peer; + + if (exact) { + /* Check the length. */ + if (*length - v->namelen != sizeof(struct in_addr) + 1) + return NULL; + + oid2in_addr(name + v->namelen, sizeof(struct in_addr), addr); + + peer = rip_peer_lookup(addr); + + if (peer->domain + == (int)name[v->namelen + sizeof(struct in_addr)]) + return peer; + + return NULL; + } else { + len = *length - v->namelen; + if (len > 4) + len = 4; + + oid2in_addr(name + v->namelen, len, addr); + + len = *length - v->namelen; + peer = rip_peer_lookup(addr); + if (peer) { + if ((len < (int)sizeof(struct in_addr) + 1) + || (peer->domain + > (int)name[v->namelen + + sizeof(struct in_addr)])) { + oid_copy_addr(name + v->namelen, &peer->addr, + sizeof(struct in_addr)); + name[v->namelen + sizeof(struct in_addr)] = + peer->domain; + *length = + sizeof(struct in_addr) + v->namelen + 1; + return peer; + } + } + peer = rip_peer_lookup_next(addr); + + if (!peer) + return NULL; + + oid_copy_addr(name + v->namelen, &peer->addr, + sizeof(struct in_addr)); + name[v->namelen + sizeof(struct in_addr)] = peer->domain; + *length = sizeof(struct in_addr) + v->namelen + 1; + + return peer; + } return NULL; - - oid_copy_addr (name + v->namelen, &peer->addr, - sizeof (struct in_addr)); - name[v->namelen + sizeof (struct in_addr)] = peer->domain; - *length = sizeof (struct in_addr) + v->namelen + 1; - - return peer; - } - return NULL; } -static u_char * -rip2IfStatEntry (struct variable *v, oid name[], size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *rip2IfStatEntry(struct variable *v, oid name[], size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - struct interface *ifp; - struct rip_interface *ri; - static struct in_addr addr; - static long valid = SNMP_VALID; - - if (smux_header_table(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - memset (&addr, 0, sizeof (struct in_addr)); - - /* Lookup interface. */ - ifp = rip2IfLookup (v, name, length, &addr, exact); - if (! ifp) - return NULL; - - /* Fetch rip_interface information. */ - ri = ifp->info; - - switch (v->magic) - { - case RIP2IFSTATADDRESS: - return SNMP_IPADDRESS (addr); - break; - case RIP2IFSTATRCVBADPACKETS: - *var_len = sizeof (long); - return (u_char *) &ri->recv_badpackets; - - case RIP2IFSTATRCVBADROUTES: - *var_len = sizeof (long); - return (u_char *) &ri->recv_badroutes; - - case RIP2IFSTATSENTUPDATES: - *var_len = sizeof (long); - return (u_char *) &ri->sent_updates; - - case RIP2IFSTATSTATUS: - *var_len = sizeof (long); - v->type = ASN_INTEGER; - return (u_char *) &valid; - - default: - return NULL; - - } - return NULL; + struct interface *ifp; + struct rip_interface *ri; + static struct in_addr addr; + static long valid = SNMP_VALID; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + memset(&addr, 0, sizeof(struct in_addr)); + + /* Lookup interface. */ + ifp = rip2IfLookup(v, name, length, &addr, exact); + if (!ifp) + return NULL; + + /* Fetch rip_interface information. */ + ri = ifp->info; + + switch (v->magic) { + case RIP2IFSTATADDRESS: + return SNMP_IPADDRESS(addr); + break; + case RIP2IFSTATRCVBADPACKETS: + *var_len = sizeof(long); + return (u_char *)&ri->recv_badpackets; + + case RIP2IFSTATRCVBADROUTES: + *var_len = sizeof(long); + return (u_char *)&ri->recv_badroutes; + + case RIP2IFSTATSENTUPDATES: + *var_len = sizeof(long); + return (u_char *)&ri->sent_updates; + + case RIP2IFSTATSTATUS: + *var_len = sizeof(long); + v->type = ASN_INTEGER; + return (u_char *)&valid; + + default: + return NULL; + } + return NULL; } -static long -rip2IfConfSend (struct rip_interface *ri) +static long rip2IfConfSend(struct rip_interface *ri) { #define doNotSend 1 #define ripVersion1 2 @@ -403,156 +395,151 @@ rip2IfConfSend (struct rip_interface *ri) #define ripV1Demand 5 #define ripV2Demand 6 - if (! ri->running) - return doNotSend; - - if (ri->ri_send & RIPv2) - return ripVersion2; - else if (ri->ri_send & RIPv1) - return ripVersion1; - else if (rip) - { - if (rip->version_send == RIPv2) - return ripVersion2; - else if (rip->version_send == RIPv1) - return ripVersion1; - } - return doNotSend; + if (!ri->running) + return doNotSend; + + if (ri->ri_send & RIPv2) + return ripVersion2; + else if (ri->ri_send & RIPv1) + return ripVersion1; + else if (rip) { + if (rip->version_send == RIPv2) + return ripVersion2; + else if (rip->version_send == RIPv1) + return ripVersion1; + } + return doNotSend; } -static long -rip2IfConfReceive (struct rip_interface *ri) +static long rip2IfConfReceive(struct rip_interface *ri) { #define rip1 1 #define rip2 2 #define rip1OrRip2 3 #define doNotReceive 4 - int recvv; - - if (! ri->running) - return doNotReceive; - - recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv : - ri->ri_receive; - if (recvv == RI_RIP_VERSION_1_AND_2) - return rip1OrRip2; - else if (recvv & RIPv2) - return rip2; - else if (recvv & RIPv1) - return rip1; - else - return doNotReceive; + int recvv; + + if (!ri->running) + return doNotReceive; + + recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv + : ri->ri_receive; + if (recvv == RI_RIP_VERSION_1_AND_2) + return rip1OrRip2; + else if (recvv & RIPv2) + return rip2; + else if (recvv & RIPv1) + return rip1; + else + return doNotReceive; } -static u_char * -rip2IfConfAddress (struct variable *v, oid name[], size_t *length, - int exact, size_t *val_len, WriteMethod **write_method) +static u_char *rip2IfConfAddress(struct variable *v, oid name[], size_t *length, + int exact, size_t *val_len, + WriteMethod **write_method) { - static struct in_addr addr; - static long valid = SNMP_INVALID; - static long domain = 0; - static long config = 0; - static u_int auth = 0; - struct interface *ifp; - struct rip_interface *ri; - - if (smux_header_table(v, name, length, exact, val_len, write_method) - == MATCH_FAILED) - return NULL; - - memset (&addr, 0, sizeof (struct in_addr)); - - /* Lookup interface. */ - ifp = rip2IfLookup (v, name, length, &addr, exact); - if (! ifp) - return NULL; - - /* Fetch rip_interface information. */ - ri = ifp->info; - - switch (v->magic) - { - case RIP2IFCONFADDRESS: - *val_len = sizeof (struct in_addr); - return (u_char *) &addr; - - case RIP2IFCONFDOMAIN: - *val_len = 2; - return (u_char *) &domain; - - case RIP2IFCONFAUTHTYPE: - auth = ri->auth_type; - *val_len = sizeof (long); - v->type = ASN_INTEGER; - return (u_char *)&auth; - - case RIP2IFCONFAUTHKEY: - *val_len = 0; - return (u_char *) &domain; - case RIP2IFCONFSEND: - config = rip2IfConfSend (ri); - *val_len = sizeof (long); - v->type = ASN_INTEGER; - return (u_char *) &config; - case RIP2IFCONFRECEIVE: - config = rip2IfConfReceive (ri); - *val_len = sizeof (long); - v->type = ASN_INTEGER; - return (u_char *) &config; - - case RIP2IFCONFDEFAULTMETRIC: - *val_len = sizeof (long); - v->type = ASN_INTEGER; - return (u_char *) &ifp->metric; - case RIP2IFCONFSTATUS: - *val_len = sizeof (long); - v->type = ASN_INTEGER; - return (u_char *) &valid; - case RIP2IFCONFSRCADDRESS: - *val_len = sizeof (struct in_addr); - return (u_char *) &addr; - - default: - return NULL; - - } - return NULL; + static struct in_addr addr; + static long valid = SNMP_INVALID; + static long domain = 0; + static long config = 0; + static u_int auth = 0; + struct interface *ifp; + struct rip_interface *ri; + + if (smux_header_table(v, name, length, exact, val_len, write_method) + == MATCH_FAILED) + return NULL; + + memset(&addr, 0, sizeof(struct in_addr)); + + /* Lookup interface. */ + ifp = rip2IfLookup(v, name, length, &addr, exact); + if (!ifp) + return NULL; + + /* Fetch rip_interface information. */ + ri = ifp->info; + + switch (v->magic) { + case RIP2IFCONFADDRESS: + *val_len = sizeof(struct in_addr); + return (u_char *)&addr; + + case RIP2IFCONFDOMAIN: + *val_len = 2; + return (u_char *)&domain; + + case RIP2IFCONFAUTHTYPE: + auth = ri->auth_type; + *val_len = sizeof(long); + v->type = ASN_INTEGER; + return (u_char *)&auth; + + case RIP2IFCONFAUTHKEY: + *val_len = 0; + return (u_char *)&domain; + case RIP2IFCONFSEND: + config = rip2IfConfSend(ri); + *val_len = sizeof(long); + v->type = ASN_INTEGER; + return (u_char *)&config; + case RIP2IFCONFRECEIVE: + config = rip2IfConfReceive(ri); + *val_len = sizeof(long); + v->type = ASN_INTEGER; + return (u_char *)&config; + + case RIP2IFCONFDEFAULTMETRIC: + *val_len = sizeof(long); + v->type = ASN_INTEGER; + return (u_char *)&ifp->metric; + case RIP2IFCONFSTATUS: + *val_len = sizeof(long); + v->type = ASN_INTEGER; + return (u_char *)&valid; + case RIP2IFCONFSRCADDRESS: + *val_len = sizeof(struct in_addr); + return (u_char *)&addr; + + default: + return NULL; + } + return NULL; } -static u_char * -rip2PeerTable (struct variable *v, oid name[], size_t *length, - int exact, size_t *val_len, WriteMethod **write_method) +static u_char *rip2PeerTable(struct variable *v, oid name[], size_t *length, + int exact, size_t *val_len, + WriteMethod **write_method) { - static struct in_addr addr; - static int domain = 0; - static int version; - /* static time_t uptime; */ - - struct rip_peer *peer; - - if (smux_header_table(v, name, length, exact, val_len, write_method) - == MATCH_FAILED) - return NULL; - - memset (&addr, 0, sizeof (struct in_addr)); - - /* Lookup interface. */ - peer = rip2PeerLookup (v, name, length, &addr, exact); - if (! peer) - return NULL; - - switch (v->magic) - { - case RIP2PEERADDRESS: - *val_len = sizeof (struct in_addr); - return (u_char *) &peer->addr; - - case RIP2PEERDOMAIN: - *val_len = 2; - return (u_char *) &domain; - - case RIP2PEERLASTUPDATE: + static struct in_addr addr; + static int domain = 0; + static int version; + /* static time_t uptime; */ + + struct rip_peer *peer; + + if (smux_header_table(v, name, length, exact, val_len, write_method) + == MATCH_FAILED) + return NULL; + + memset(&addr, 0, sizeof(struct in_addr)); + + /* Lookup interface. */ + peer = rip2PeerLookup(v, name, length, &addr, exact); + if (!peer) + return NULL; + + switch (v->magic) { + case RIP2PEERADDRESS: + *val_len = sizeof(struct in_addr); + return (u_char *)&peer->addr; + + case RIP2PEERDOMAIN: + *val_len = 2; + return (u_char *)&domain; + + case RIP2PEERLASTUPDATE: #if 0 /* We don't know the SNMP agent startup time. We have two choices here: * - assume ripd startup time equals SNMP agent startup time @@ -563,53 +550,47 @@ rip2PeerTable (struct variable *v, oid name[], size_t *length, uptime = peer->uptime; /* now - snmp_agent_startup - peer->uptime */ return (u_char *) &uptime; #else - return (u_char *) NULL; + return (u_char *)NULL; #endif - case RIP2PEERVERSION: - *val_len = sizeof (int); - version = peer->version; - return (u_char *) &version; + case RIP2PEERVERSION: + *val_len = sizeof(int); + version = peer->version; + return (u_char *)&version; - case RIP2PEERRCVBADPACKETS: - *val_len = sizeof (int); - return (u_char *) &peer->recv_badpackets; + case RIP2PEERRCVBADPACKETS: + *val_len = sizeof(int); + return (u_char *)&peer->recv_badpackets; - case RIP2PEERRCVBADROUTES: - *val_len = sizeof (int); - return (u_char *) &peer->recv_badroutes; + case RIP2PEERRCVBADROUTES: + *val_len = sizeof(int); + return (u_char *)&peer->recv_badroutes; - default: - return NULL; - - } - return NULL; + default: + return NULL; + } + return NULL; } /* Register RIPv2-MIB. */ -static int -rip_snmp_init (struct thread_master *master) +static int rip_snmp_init(struct thread_master *master) { - rip_ifaddr_table = route_table_init (); + rip_ifaddr_table = route_table_init(); - smux_init (master); - REGISTER_MIB("mibII/rip", rip_variables, variable, rip_oid); - return 0; + smux_init(master); + REGISTER_MIB("mibII/rip", rip_variables, variable, rip_oid); + return 0; } -static int -rip_snmp_module_init (void) +static int rip_snmp_module_init(void) { - hook_register(rip_ifaddr_add, rip_snmp_ifaddr_add); - hook_register(rip_ifaddr_del, rip_snmp_ifaddr_del); + hook_register(rip_ifaddr_add, rip_snmp_ifaddr_add); + hook_register(rip_ifaddr_del, rip_snmp_ifaddr_del); - hook_register(frr_late_init, rip_snmp_init); - return 0; + hook_register(frr_late_init, rip_snmp_init); + return 0; } -FRR_MODULE_SETUP( - .name = "ripd_snmp", - .version = FRR_VERSION, - .description = "ripd AgentX SNMP module", - .init = rip_snmp_module_init, -) +FRR_MODULE_SETUP(.name = "ripd_snmp", .version = FRR_VERSION, + .description = "ripd AgentX SNMP module", + .init = rip_snmp_module_init, ) diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index dffa9db7c..961a846db 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -37,274 +37,265 @@ struct zclient *zclient = NULL; /* Send ECMP routes to zebra. */ -static void -rip_zebra_ipv4_send (struct route_node *rp, u_char cmd) +static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd) { - static struct in_addr **nexthops = NULL; - static unsigned int nexthops_len = 0; - - struct list *list = (struct list *)rp->info; - struct zapi_ipv4 api; - struct listnode *listnode = NULL; - struct rip_info *rinfo = NULL; - int count = 0; - - if (vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], VRF_DEFAULT)) - { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_RIP; - api.instance = 0; - api.flags = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - - if (nexthops_len < listcount (list)) - { - nexthops_len = listcount (list); - nexthops = XREALLOC (MTYPE_TMP, nexthops, - nexthops_len * sizeof (struct in_addr *)); - } - - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) - { - nexthops[count++] = &rinfo->nexthop; - if (cmd == ZEBRA_IPV4_ROUTE_ADD) - SET_FLAG (rinfo->flags, RIP_RTF_FIB); - else - UNSET_FLAG (rinfo->flags, RIP_RTF_FIB); - } - - api.nexthop = nexthops; - api.nexthop_num = count; - api.ifindex_num = 0; - - rinfo = listgetdata (listhead (list)); - - SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); - api.metric = rinfo->metric; - - if (rinfo->distance && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT) - { - SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = rinfo->distance; - } - - if (rinfo->tag) - { - SET_FLAG (api.message, ZAPI_MESSAGE_TAG); - api.tag = rinfo->tag; - } - - zapi_ipv4_route (cmd, zclient, - (struct prefix_ipv4 *)&rp->p, &api); - - if (IS_RIP_DEBUG_ZEBRA) - { - if (rip->ecmp) - zlog_debug ("%s: %s/%d nexthops %d", - (cmd == ZEBRA_IPV4_ROUTE_ADD) ? \ - "Install into zebra" : "Delete from zebra", - inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen, count); - else - zlog_debug ("%s: %s/%d", - (cmd == ZEBRA_IPV4_ROUTE_ADD) ? \ - "Install into zebra" : "Delete from zebra", - inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen); - } - - rip_global_route_changes++; - } + static struct in_addr **nexthops = NULL; + static unsigned int nexthops_len = 0; + + struct list *list = (struct list *)rp->info; + struct zapi_ipv4 api; + struct listnode *listnode = NULL; + struct rip_info *rinfo = NULL; + int count = 0; + + if (vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], + VRF_DEFAULT)) { + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_RIP; + api.instance = 0; + api.flags = 0; + api.message = 0; + api.safi = SAFI_UNICAST; + + if (nexthops_len < listcount(list)) { + nexthops_len = listcount(list); + nexthops = XREALLOC(MTYPE_TMP, nexthops, + nexthops_len + * sizeof(struct in_addr *)); + } + + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { + nexthops[count++] = &rinfo->nexthop; + if (cmd == ZEBRA_IPV4_ROUTE_ADD) + SET_FLAG(rinfo->flags, RIP_RTF_FIB); + else + UNSET_FLAG(rinfo->flags, RIP_RTF_FIB); + } + + api.nexthop = nexthops; + api.nexthop_num = count; + api.ifindex_num = 0; + + rinfo = listgetdata(listhead(list)); + + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = rinfo->metric; + + if (rinfo->distance + && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT) { + SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = rinfo->distance; + } + + if (rinfo->tag) { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = rinfo->tag; + } + + zapi_ipv4_route(cmd, zclient, (struct prefix_ipv4 *)&rp->p, + &api); + + if (IS_RIP_DEBUG_ZEBRA) { + if (rip->ecmp) + zlog_debug("%s: %s/%d nexthops %d", + (cmd == ZEBRA_IPV4_ROUTE_ADD) + ? "Install into zebra" + : "Delete from zebra", + inet_ntoa(rp->p.u.prefix4), + rp->p.prefixlen, count); + else + zlog_debug("%s: %s/%d", + (cmd == ZEBRA_IPV4_ROUTE_ADD) + ? "Install into zebra" + : "Delete from zebra", + inet_ntoa(rp->p.u.prefix4), + rp->p.prefixlen); + } + + rip_global_route_changes++; + } } /* Add/update ECMP routes to zebra. */ -void -rip_zebra_ipv4_add (struct route_node *rp) +void rip_zebra_ipv4_add(struct route_node *rp) { - rip_zebra_ipv4_send (rp, ZEBRA_IPV4_ROUTE_ADD); + rip_zebra_ipv4_send(rp, ZEBRA_IPV4_ROUTE_ADD); } /* Delete ECMP routes from zebra. */ -void -rip_zebra_ipv4_delete (struct route_node *rp) +void rip_zebra_ipv4_delete(struct route_node *rp) { - rip_zebra_ipv4_send (rp, ZEBRA_IPV4_ROUTE_DELETE); + rip_zebra_ipv4_send(rp, ZEBRA_IPV4_ROUTE_DELETE); } /* Zebra route add and delete treatment. */ -static int -rip_zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int rip_zebra_read_ipv4(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv4 api; - unsigned long ifindex; - struct in_addr nexthop; - struct prefix_ipv4 p; - - if (!rip) - return 0; - - s = zclient->ibuf; - ifindex = 0; - nexthop.s_addr = 0; - - /* Type, flags, message. */ - api.type = stream_getc (s); - api.instance = stream_getw (s); - api.flags = stream_getl (s); - api.message = stream_getc (s); - - /* IPv4 prefix. */ - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc (s)); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) - { - api.nexthop_num = stream_getc (s); - nexthop.s_addr = stream_get_ipv4 (s); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) - { - api.ifindex_num = stream_getc (s); - ifindex = stream_getl (s); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc (s); - else - api.distance = 255; - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl (s); - else - api.metric = 0; - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl (s); - else - api.tag = 0; - - /* Then fetch IPv4 prefixes. */ - if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) - rip_redistribute_add (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex, - &nexthop, api.metric, api.distance, api.tag); - else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) - rip_redistribute_delete (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex); - - return 0; + struct stream *s; + struct zapi_ipv4 api; + unsigned long ifindex; + struct in_addr nexthop; + struct prefix_ipv4 p; + + if (!rip) + return 0; + + s = zclient->ibuf; + ifindex = 0; + nexthop.s_addr = 0; + + /* Type, flags, message. */ + api.type = stream_getc(s); + api.instance = stream_getw(s); + api.flags = stream_getl(s); + api.message = stream_getc(s); + + /* IPv4 prefix. */ + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); + stream_get(&p.prefix, s, PSIZE(p.prefixlen)); + + /* Nexthop, ifindex, distance, metric. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { + api.nexthop_num = stream_getc(s); + nexthop.s_addr = stream_get_ipv4(s); + } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { + api.ifindex_num = stream_getc(s); + ifindex = stream_getl(s); + } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) + api.distance = stream_getc(s); + else + api.distance = 255; + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) + api.metric = stream_getl(s); + else + api.metric = 0; + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getl(s); + else + api.tag = 0; + + /* Then fetch IPv4 prefixes. */ + if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) + rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE, &p, + ifindex, &nexthop, api.metric, + api.distance, api.tag); + else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) + rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE, &p, + ifindex); + + return 0; } -void -rip_zclient_reset (void) +void rip_zclient_reset(void) { - zclient_reset (zclient); + zclient_reset(zclient); } /* RIP route-map set for redistribution */ -static void -rip_routemap_set (int type, const char *name) +static void rip_routemap_set(int type, const char *name) { - if (rip->route_map[type].name) - free(rip->route_map[type].name); + if (rip->route_map[type].name) + free(rip->route_map[type].name); - rip->route_map[type].name = strdup (name); - rip->route_map[type].map = route_map_lookup_by_name (name); + rip->route_map[type].name = strdup(name); + rip->route_map[type].map = route_map_lookup_by_name(name); } -static void -rip_redistribute_metric_set (int type, unsigned int metric) +static void rip_redistribute_metric_set(int type, unsigned int metric) { - rip->route_map[type].metric_config = 1; - rip->route_map[type].metric = metric; + rip->route_map[type].metric_config = 1; + rip->route_map[type].metric = metric; } -static int -rip_metric_unset (int type, unsigned int metric) +static int rip_metric_unset(int type, unsigned int metric) { #define DONT_CARE_METRIC_RIP 17 - if (metric != DONT_CARE_METRIC_RIP && - rip->route_map[type].metric != metric) - return 1; - rip->route_map[type].metric_config = 0; - rip->route_map[type].metric = 0; - return 0; + if (metric != DONT_CARE_METRIC_RIP + && rip->route_map[type].metric != metric) + return 1; + rip->route_map[type].metric_config = 0; + rip->route_map[type].metric = 0; + return 0; } /* RIP route-map unset for redistribution */ -static int -rip_routemap_unset (int type, const char *name) +static int rip_routemap_unset(int type, const char *name) { - if (! rip->route_map[type].name || - (name != NULL && strcmp(rip->route_map[type].name,name))) - return 1; + if (!rip->route_map[type].name + || (name != NULL && strcmp(rip->route_map[type].name, name))) + return 1; - free (rip->route_map[type].name); - rip->route_map[type].name = NULL; - rip->route_map[type].map = NULL; + free(rip->route_map[type].name); + rip->route_map[type].name = NULL; + rip->route_map[type].map = NULL; - return 0; + return 0; } /* Redistribution types */ static struct { - int type; - int str_min_len; - const char *str; -} redist_type[] = { - {ZEBRA_ROUTE_KERNEL, 1, "kernel"}, - {ZEBRA_ROUTE_CONNECT, 1, "connected"}, - {ZEBRA_ROUTE_STATIC, 1, "static"}, - {ZEBRA_ROUTE_OSPF, 1, "ospf"}, - {ZEBRA_ROUTE_BGP, 2, "bgp"}, - {ZEBRA_ROUTE_VNC, 1, "vnc"}, - {0, 0, NULL} -}; - -static int -rip_redistribute_unset (int type) + int type; + int str_min_len; + const char *str; +} redist_type[] = {{ZEBRA_ROUTE_KERNEL, 1, "kernel"}, + {ZEBRA_ROUTE_CONNECT, 1, "connected"}, + {ZEBRA_ROUTE_STATIC, 1, "static"}, + {ZEBRA_ROUTE_OSPF, 1, "ospf"}, + {ZEBRA_ROUTE_BGP, 2, "bgp"}, + {ZEBRA_ROUTE_VNC, 1, "vnc"}, + {0, 0, NULL}}; + +static int rip_redistribute_unset(int type) { - if (! vrf_bitmap_check (zclient->redist[AFI_IP][type], VRF_DEFAULT)) - return CMD_SUCCESS; + if (!vrf_bitmap_check(zclient->redist[AFI_IP][type], VRF_DEFAULT)) + return CMD_SUCCESS; - vrf_bitmap_unset (zclient->redist[AFI_IP][type], VRF_DEFAULT); + vrf_bitmap_unset(zclient->redist[AFI_IP][type], VRF_DEFAULT); - if (zclient->sock > 0) - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, type, 0, VRF_DEFAULT); + if (zclient->sock > 0) + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, + AFI_IP, type, 0, VRF_DEFAULT); - /* Remove the routes from RIP table. */ - rip_redistribute_withdraw (type); + /* Remove the routes from RIP table. */ + rip_redistribute_withdraw(type); - return CMD_SUCCESS; + return CMD_SUCCESS; } -int -rip_redistribute_check (int type) +int rip_redistribute_check(int type) { - return vrf_bitmap_check (zclient->redist[AFI_IP][type], VRF_DEFAULT); + return vrf_bitmap_check(zclient->redist[AFI_IP][type], VRF_DEFAULT); } -void -rip_redistribute_clean (void) +void rip_redistribute_clean(void) { - int i; - - for (i = 0; redist_type[i].str; i++) - { - if (vrf_bitmap_check (zclient->redist[AFI_IP][redist_type[i].type], VRF_DEFAULT)) - { - if (zclient->sock > 0) - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, - zclient, AFI_IP, redist_type[i].type, 0, - VRF_DEFAULT); - - vrf_bitmap_unset (zclient->redist[AFI_IP][redist_type[i].type], VRF_DEFAULT); - - /* Remove the routes from RIP table. */ - rip_redistribute_withdraw (redist_type[i].type); + int i; + + for (i = 0; redist_type[i].str; i++) { + if (vrf_bitmap_check( + zclient->redist[AFI_IP][redist_type[i].type], + VRF_DEFAULT)) { + if (zclient->sock > 0) + zebra_redistribute_send( + ZEBRA_REDISTRIBUTE_DELETE, zclient, + AFI_IP, redist_type[i].type, 0, + VRF_DEFAULT); + + vrf_bitmap_unset( + zclient->redist[AFI_IP][redist_type[i].type], + VRF_DEFAULT); + + /* Remove the routes from RIP table. */ + rip_redistribute_withdraw(redist_type[i].type); + } } - } } DEFUN (rip_redistribute_rip, @@ -313,8 +304,8 @@ DEFUN (rip_redistribute_rip, "Redistribute information from another routing protocol\n" "Routing Information Protocol (RIP)\n") { - vrf_bitmap_set (zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], VRF_DEFAULT); - return CMD_SUCCESS; + vrf_bitmap_set(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], VRF_DEFAULT); + return CMD_SUCCESS; } DEFUN (no_rip_redistribute_rip, @@ -324,8 +315,8 @@ DEFUN (no_rip_redistribute_rip, "Redistribute information from another routing protocol\n" "Routing Information Protocol (RIP)\n") { - vrf_bitmap_unset (zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], VRF_DEFAULT); - return CMD_SUCCESS; + vrf_bitmap_unset(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], VRF_DEFAULT); + return CMD_SUCCESS; } DEFUN (rip_redistribute_type, @@ -334,22 +325,22 @@ DEFUN (rip_redistribute_type, REDIST_STR FRR_REDIST_HELP_STR_RIPD) { - int i; - - for(i = 0; redist_type[i].str; i++) - { - if (strncmp (redist_type[i].str, argv[1]->arg, - redist_type[i].str_min_len) == 0) - { - zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, - AFI_IP, redist_type[i].type, 0, VRF_DEFAULT); - return CMD_SUCCESS; + int i; + + for (i = 0; redist_type[i].str; i++) { + if (strncmp(redist_type[i].str, argv[1]->arg, + redist_type[i].str_min_len) + == 0) { + zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, + AFI_IP, redist_type[i].type, 0, + VRF_DEFAULT); + return CMD_SUCCESS; + } } - } - vty_out (vty, "Invalid type %s\n",argv[1]->arg); + vty_out(vty, "Invalid type %s\n", argv[1]->arg); - return CMD_WARNING_CONFIG_FAILED; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (no_rip_redistribute_type, @@ -359,23 +350,23 @@ DEFUN (no_rip_redistribute_type, REDIST_STR FRR_REDIST_HELP_STR_RIPD) { - int i; - - for (i = 0; redist_type[i].str; i++) - { - if (strncmp(redist_type[i].str, argv[2]->arg, - redist_type[i].str_min_len) == 0) - { - rip_metric_unset (redist_type[i].type, DONT_CARE_METRIC_RIP); - rip_routemap_unset (redist_type[i].type,NULL); - rip_redistribute_unset (redist_type[i].type); - return CMD_SUCCESS; - } - } - - vty_out (vty, "Invalid type %s\n",argv[2]->arg); - - return CMD_WARNING_CONFIG_FAILED; + int i; + + for (i = 0; redist_type[i].str; i++) { + if (strncmp(redist_type[i].str, argv[2]->arg, + redist_type[i].str_min_len) + == 0) { + rip_metric_unset(redist_type[i].type, + DONT_CARE_METRIC_RIP); + rip_routemap_unset(redist_type[i].type, NULL); + rip_redistribute_unset(redist_type[i].type); + return CMD_SUCCESS; + } + } + + vty_out(vty, "Invalid type %s\n", argv[2]->arg); + + return CMD_WARNING_CONFIG_FAILED; } DEFUN (rip_redistribute_type_routemap, @@ -386,23 +377,24 @@ DEFUN (rip_redistribute_type_routemap, "Route map reference\n" "Pointer to route-map entries\n") { - int idx_protocol = 1; - int idx_word = 3; - int i; - - for (i = 0; redist_type[i].str; i++) { - if (strmatch (redist_type[i].str, argv[idx_protocol]->text)) - { - rip_routemap_set (redist_type[i].type, argv[idx_word]->arg); - zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, - redist_type[i].type, 0, VRF_DEFAULT); - return CMD_SUCCESS; - } - } + int idx_protocol = 1; + int idx_word = 3; + int i; + + for (i = 0; redist_type[i].str; i++) { + if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) { + rip_routemap_set(redist_type[i].type, + argv[idx_word]->arg); + zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, + AFI_IP, redist_type[i].type, 0, + VRF_DEFAULT); + return CMD_SUCCESS; + } + } - vty_out (vty, "Invalid type %s\n", argv[idx_protocol]->text); + vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text); - return CMD_WARNING_CONFIG_FAILED; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (no_rip_redistribute_type_routemap, @@ -414,23 +406,23 @@ DEFUN (no_rip_redistribute_type_routemap, "Route map reference\n" "Pointer to route-map entries\n") { - int idx_protocol = 2; - int idx_word = 4; - int i; - - for (i = 0; redist_type[i].str; i++) { - if (strmatch (redist_type[i].str, argv[idx_protocol]->text)) - { - if (rip_routemap_unset (redist_type[i].type,argv[idx_word]->arg)) - return CMD_WARNING_CONFIG_FAILED; - rip_redistribute_unset (redist_type[i].type); - return CMD_SUCCESS; - } - } - - vty_out (vty, "Invalid type %s\n", argv[idx_protocol]->text); - - return CMD_WARNING_CONFIG_FAILED; + int idx_protocol = 2; + int idx_word = 4; + int i; + + for (i = 0; redist_type[i].str; i++) { + if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) { + if (rip_routemap_unset(redist_type[i].type, + argv[idx_word]->arg)) + return CMD_WARNING_CONFIG_FAILED; + rip_redistribute_unset(redist_type[i].type); + return CMD_SUCCESS; + } + } + + vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text); + + return CMD_WARNING_CONFIG_FAILED; } DEFUN (rip_redistribute_type_metric, @@ -441,26 +433,27 @@ DEFUN (rip_redistribute_type_metric, "Metric\n" "Metric value\n") { - int idx_protocol = 1; - int idx_number = 3; - int i; - int metric; - - metric = atoi (argv[idx_number]->arg); - - for (i = 0; redist_type[i].str; i++) { - if (strmatch (redist_type[i].str, argv[idx_protocol]->text)) - { - rip_redistribute_metric_set (redist_type[i].type, metric); - zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, - redist_type[i].type, 0, VRF_DEFAULT); - return CMD_SUCCESS; - } - } + int idx_protocol = 1; + int idx_number = 3; + int i; + int metric; + + metric = atoi(argv[idx_number]->arg); + + for (i = 0; redist_type[i].str; i++) { + if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) { + rip_redistribute_metric_set(redist_type[i].type, + metric); + zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, + AFI_IP, redist_type[i].type, 0, + VRF_DEFAULT); + return CMD_SUCCESS; + } + } - vty_out (vty, "Invalid type %s\n", argv[idx_protocol]->text); + vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text); - return CMD_WARNING_CONFIG_FAILED; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (no_rip_redistribute_type_metric, @@ -472,23 +465,23 @@ DEFUN (no_rip_redistribute_type_metric, "Metric\n" "Metric value\n") { - int idx_protocol = 2; - int idx_number = 4; - int i; - - for (i = 0; redist_type[i].str; i++) { - if (strmatch (redist_type[i].str, argv[idx_protocol]->text)) - { - if (rip_metric_unset (redist_type[i].type, atoi(argv[idx_number]->arg))) - return CMD_WARNING_CONFIG_FAILED; - rip_redistribute_unset (redist_type[i].type); - return CMD_SUCCESS; - } - } - - vty_out (vty, "Invalid type %s\n", argv[idx_protocol]->text); - - return CMD_WARNING_CONFIG_FAILED; + int idx_protocol = 2; + int idx_number = 4; + int i; + + for (i = 0; redist_type[i].str; i++) { + if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) { + if (rip_metric_unset(redist_type[i].type, + atoi(argv[idx_number]->arg))) + return CMD_WARNING_CONFIG_FAILED; + rip_redistribute_unset(redist_type[i].type); + return CMD_SUCCESS; + } + } + + vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text); + + return CMD_WARNING_CONFIG_FAILED; } DEFUN (rip_redistribute_type_metric_routemap, @@ -501,28 +494,30 @@ DEFUN (rip_redistribute_type_metric_routemap, "Route map reference\n" "Pointer to route-map entries\n") { - int idx_protocol = 1; - int idx_number = 3; - int idx_word = 5; - int i; - int metric; - - metric = atoi (argv[idx_number]->arg); - - for (i = 0; redist_type[i].str; i++) { - if (strmatch (redist_type[i].str, argv[idx_protocol]->text)) - { - rip_redistribute_metric_set (redist_type[i].type, metric); - rip_routemap_set (redist_type[i].type, argv[idx_word]->arg); - zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, - redist_type[i].type, 0, VRF_DEFAULT); - return CMD_SUCCESS; - } - } + int idx_protocol = 1; + int idx_number = 3; + int idx_word = 5; + int i; + int metric; + + metric = atoi(argv[idx_number]->arg); + + for (i = 0; redist_type[i].str; i++) { + if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) { + rip_redistribute_metric_set(redist_type[i].type, + metric); + rip_routemap_set(redist_type[i].type, + argv[idx_word]->arg); + zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, + AFI_IP, redist_type[i].type, 0, + VRF_DEFAULT); + return CMD_SUCCESS; + } + } - vty_out (vty, "Invalid type %s\n", argv[idx_protocol]->text); + vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text); - return CMD_WARNING_CONFIG_FAILED; + return CMD_WARNING_CONFIG_FAILED; } @@ -537,29 +532,31 @@ DEFUN (no_rip_redistribute_type_metric_routemap, "Route map reference\n" "Pointer to route-map entries\n") { - int idx_protocol = 2; - int idx_number = 4; - int idx_word = 6; - int i; - - for (i = 0; redist_type[i].str; i++) { - if (strmatch (redist_type[i].str, argv[idx_protocol]->text)) - { - if (rip_metric_unset (redist_type[i].type, atoi(argv[idx_number]->arg))) - return CMD_WARNING_CONFIG_FAILED; - if (rip_routemap_unset (redist_type[i].type, argv[idx_word]->arg)) - { - rip_redistribute_metric_set(redist_type[i].type, atoi(argv[idx_number]->arg)); - return CMD_WARNING_CONFIG_FAILED; - } - rip_redistribute_unset (redist_type[i].type); - return CMD_SUCCESS; - } - } - - vty_out (vty, "Invalid type %s\n", argv[idx_protocol]->text); - - return CMD_WARNING_CONFIG_FAILED; + int idx_protocol = 2; + int idx_number = 4; + int idx_word = 6; + int i; + + for (i = 0; redist_type[i].str; i++) { + if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) { + if (rip_metric_unset(redist_type[i].type, + atoi(argv[idx_number]->arg))) + return CMD_WARNING_CONFIG_FAILED; + if (rip_routemap_unset(redist_type[i].type, + argv[idx_word]->arg)) { + rip_redistribute_metric_set( + redist_type[i].type, + atoi(argv[idx_number]->arg)); + return CMD_WARNING_CONFIG_FAILED; + } + rip_redistribute_unset(redist_type[i].type); + return CMD_SUCCESS; + } + } + + vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text); + + return CMD_WARNING_CONFIG_FAILED; } /* Default information originate. */ @@ -570,20 +567,19 @@ DEFUN (rip_default_information_originate, "Control distribution of default route\n" "Distribute a default route\n") { - struct prefix_ipv4 p; + struct prefix_ipv4 p; + + if (!rip->default_information) { + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; - if (! rip->default_information) - { - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; + rip->default_information = 1; - rip->default_information = 1; - - rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0, - NULL, 0, 0, 0); - } + rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0, + NULL, 0, 0, 0); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_rip_default_information_originate, @@ -593,128 +589,125 @@ DEFUN (no_rip_default_information_originate, "Control distribution of default route\n" "Distribute a default route\n") { - struct prefix_ipv4 p; + struct prefix_ipv4 p; + + if (rip->default_information) { + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; - if (rip->default_information) - { - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; + rip->default_information = 0; - rip->default_information = 0; - - rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0); - } + rip_redistribute_delete(ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, + 0); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* RIP configuration write function. */ -static int -config_write_zebra (struct vty *vty) +static int config_write_zebra(struct vty *vty) { - if (! zclient->enable) - { - vty_out (vty, "no router zebra\n"); - return 1; - } - else if (! vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], VRF_DEFAULT)) - { - vty_out (vty, "router zebra\n"); - vty_out (vty, " no redistribute rip\n"); - return 1; - } - return 0; + if (!zclient->enable) { + vty_out(vty, "no router zebra\n"); + return 1; + } else if (!vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], + VRF_DEFAULT)) { + vty_out(vty, "router zebra\n"); + vty_out(vty, " no redistribute rip\n"); + return 1; + } + return 0; } -int -config_write_rip_redistribute (struct vty *vty, int config_mode) +int config_write_rip_redistribute(struct vty *vty, int config_mode) { - int i; - - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (i != zclient->redist_default && - vrf_bitmap_check (zclient->redist[AFI_IP][i], VRF_DEFAULT)) - { - if (config_mode) - { - if (rip->route_map[i].metric_config) - { - if (rip->route_map[i].name) - vty_out (vty, " redistribute %s metric %d route-map %s\n", - zebra_route_string(i), rip->route_map[i].metric, - rip->route_map[i].name); - else - vty_out (vty, " redistribute %s metric %d\n", - zebra_route_string(i),rip->route_map[i].metric); - } - else - { - if (rip->route_map[i].name) - vty_out (vty, " redistribute %s route-map %s\n", - zebra_route_string(i),rip->route_map[i].name); - else - vty_out (vty, " redistribute %s\n",zebra_route_string(i)); - } - } - else - vty_out (vty, " %s", zebra_route_string(i)); - } - return 0; + int i; + + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (i != zclient->redist_default + && vrf_bitmap_check(zclient->redist[AFI_IP][i], + VRF_DEFAULT)) { + if (config_mode) { + if (rip->route_map[i].metric_config) { + if (rip->route_map[i].name) + vty_out(vty, + " redistribute %s metric %d route-map %s\n", + zebra_route_string(i), + rip->route_map[i] + .metric, + rip->route_map[i].name); + else + vty_out(vty, + " redistribute %s metric %d\n", + zebra_route_string(i), + rip->route_map[i] + .metric); + } else { + if (rip->route_map[i].name) + vty_out(vty, + " redistribute %s route-map %s\n", + zebra_route_string(i), + rip->route_map[i].name); + else + vty_out(vty, + " redistribute %s\n", + zebra_route_string(i)); + } + } else + vty_out(vty, " %s", zebra_route_string(i)); + } + return 0; } /* Zebra node structure. */ -static struct cmd_node zebra_node = -{ - ZEBRA_NODE, - "%s(config-router)# ", +static struct cmd_node zebra_node = { + ZEBRA_NODE, "%s(config-router)# ", }; -static void -rip_zebra_connected (struct zclient *zclient) +static void rip_zebra_connected(struct zclient *zclient) { - zclient_send_reg_requests (zclient, VRF_DEFAULT); + zclient_send_reg_requests(zclient, VRF_DEFAULT); } -void -rip_zclient_init (struct thread_master *master) +void rip_zclient_init(struct thread_master *master) { - /* Set default value to the zebra client structure. */ - zclient = zclient_new(master); - zclient_init (zclient, ZEBRA_ROUTE_RIP, 0); - zclient->zebra_connected = rip_zebra_connected; - zclient->interface_add = rip_interface_add; - zclient->interface_delete = rip_interface_delete; - zclient->interface_address_add = rip_interface_address_add; - zclient->interface_address_delete = rip_interface_address_delete; - zclient->interface_up = rip_interface_up; - zclient->interface_down = rip_interface_down; - zclient->redistribute_route_ipv4_add = rip_zebra_read_ipv4; - zclient->redistribute_route_ipv4_del = rip_zebra_read_ipv4; - - /* Install zebra node. */ - install_node (&zebra_node, config_write_zebra); - - /* Install command elements to zebra node. */ - install_default (ZEBRA_NODE); - install_element (ZEBRA_NODE, &rip_redistribute_rip_cmd); - install_element (ZEBRA_NODE, &no_rip_redistribute_rip_cmd); - - /* Install command elements to rip node. */ - install_element (RIP_NODE, &rip_redistribute_type_cmd); - install_element (RIP_NODE, &rip_redistribute_type_routemap_cmd); - install_element (RIP_NODE, &rip_redistribute_type_metric_cmd); - install_element (RIP_NODE, &rip_redistribute_type_metric_routemap_cmd); - install_element (RIP_NODE, &no_rip_redistribute_type_cmd); - install_element (RIP_NODE, &no_rip_redistribute_type_routemap_cmd); - install_element (RIP_NODE, &no_rip_redistribute_type_metric_cmd); - install_element (RIP_NODE, &no_rip_redistribute_type_metric_routemap_cmd); - install_element (RIP_NODE, &rip_default_information_originate_cmd); - install_element (RIP_NODE, &no_rip_default_information_originate_cmd); + /* Set default value to the zebra client structure. */ + zclient = zclient_new(master); + zclient_init(zclient, ZEBRA_ROUTE_RIP, 0); + zclient->zebra_connected = rip_zebra_connected; + zclient->interface_add = rip_interface_add; + zclient->interface_delete = rip_interface_delete; + zclient->interface_address_add = rip_interface_address_add; + zclient->interface_address_delete = rip_interface_address_delete; + zclient->interface_up = rip_interface_up; + zclient->interface_down = rip_interface_down; + zclient->redistribute_route_ipv4_add = rip_zebra_read_ipv4; + zclient->redistribute_route_ipv4_del = rip_zebra_read_ipv4; + + /* Install zebra node. */ + install_node(&zebra_node, config_write_zebra); + + /* Install command elements to zebra node. */ + install_default(ZEBRA_NODE); + install_element(ZEBRA_NODE, &rip_redistribute_rip_cmd); + install_element(ZEBRA_NODE, &no_rip_redistribute_rip_cmd); + + /* Install command elements to rip node. */ + install_element(RIP_NODE, &rip_redistribute_type_cmd); + install_element(RIP_NODE, &rip_redistribute_type_routemap_cmd); + install_element(RIP_NODE, &rip_redistribute_type_metric_cmd); + install_element(RIP_NODE, &rip_redistribute_type_metric_routemap_cmd); + install_element(RIP_NODE, &no_rip_redistribute_type_cmd); + install_element(RIP_NODE, &no_rip_redistribute_type_routemap_cmd); + install_element(RIP_NODE, &no_rip_redistribute_type_metric_cmd); + install_element(RIP_NODE, + &no_rip_redistribute_type_metric_routemap_cmd); + install_element(RIP_NODE, &rip_default_information_originate_cmd); + install_element(RIP_NODE, &no_rip_default_information_originate_cmd); } -void -rip_zclient_stop (void) +void rip_zclient_stop(void) { - zclient_stop (zclient); - zclient_free (zclient); + zclient_stop(zclient); + zclient_free(zclient); } diff --git a/ripd/ripd.c b/ripd/ripd.c index 8578dc3d2..d9b38bba8 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -65,187 +65,171 @@ long rip_global_route_changes = 0; long rip_global_queries = 0; /* Prototypes. */ -static void rip_event (enum rip_event, int); -static void rip_output_process (struct connected *, struct sockaddr_in *, int, u_char); -static int rip_triggered_update (struct thread *); -static int rip_update_jitter (unsigned long); +static void rip_event(enum rip_event, int); +static void rip_output_process(struct connected *, struct sockaddr_in *, int, + u_char); +static int rip_triggered_update(struct thread *); +static int rip_update_jitter(unsigned long); /* RIP output routes type. */ -enum -{ - rip_all_route, - rip_changed_route -}; +enum { rip_all_route, rip_changed_route }; /* RIP command strings. */ -static const struct message rip_msg[] = -{ - {RIP_REQUEST, "REQUEST"}, - {RIP_RESPONSE, "RESPONSE"}, - {RIP_TRACEON, "TRACEON"}, - {RIP_TRACEOFF, "TRACEOFF"}, - {RIP_POLL, "POLL"}, - {RIP_POLL_ENTRY, "POLL ENTRY"}, - { 0 } -}; +static const struct message rip_msg[] = {{RIP_REQUEST, "REQUEST"}, + {RIP_RESPONSE, "RESPONSE"}, + {RIP_TRACEON, "TRACEON"}, + {RIP_TRACEOFF, "TRACEOFF"}, + {RIP_POLL, "POLL"}, + {RIP_POLL_ENTRY, "POLL ENTRY"}, + {0}}; /* Utility function to set boradcast option to the socket. */ -static int -sockopt_broadcast (int sock) +static int sockopt_broadcast(int sock) { - int ret; - int on = 1; + int ret; + int on = 1; - ret = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *) &on, sizeof on); - if (ret < 0) - { - zlog_warn ("can't set sockopt SO_BROADCAST to socket %d", sock); - return -1; - } - return 0; + ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&on, + sizeof on); + if (ret < 0) { + zlog_warn("can't set sockopt SO_BROADCAST to socket %d", sock); + return -1; + } + return 0; } -static int -rip_route_rte (struct rip_info *rinfo) +static int rip_route_rte(struct rip_info *rinfo) { - return (rinfo->type == ZEBRA_ROUTE_RIP && rinfo->sub_type == RIP_ROUTE_RTE); + return (rinfo->type == ZEBRA_ROUTE_RIP + && rinfo->sub_type == RIP_ROUTE_RTE); } -static struct rip_info * -rip_info_new (void) +static struct rip_info *rip_info_new(void) { - return XCALLOC (MTYPE_RIP_INFO, sizeof (struct rip_info)); + return XCALLOC(MTYPE_RIP_INFO, sizeof(struct rip_info)); } -void -rip_info_free (struct rip_info *rinfo) +void rip_info_free(struct rip_info *rinfo) { - XFREE (MTYPE_RIP_INFO, rinfo); + XFREE(MTYPE_RIP_INFO, rinfo); } /* RIP route garbage collect timer. */ -static int -rip_garbage_collect (struct thread *t) +static int rip_garbage_collect(struct thread *t) { - struct rip_info *rinfo; - struct route_node *rp; + struct rip_info *rinfo; + struct route_node *rp; + + rinfo = THREAD_ARG(t); + rinfo->t_garbage_collect = NULL; - rinfo = THREAD_ARG (t); - rinfo->t_garbage_collect = NULL; + /* Off timeout timer. */ + RIP_TIMER_OFF(rinfo->t_timeout); - /* Off timeout timer. */ - RIP_TIMER_OFF (rinfo->t_timeout); - - /* Get route_node pointer. */ - rp = rinfo->rp; + /* Get route_node pointer. */ + rp = rinfo->rp; - /* Unlock route_node. */ - listnode_delete (rp->info, rinfo); - if (list_isempty ((struct list *)rp->info)) - { - list_free (rp->info); - rp->info = NULL; - route_unlock_node (rp); - } + /* Unlock route_node. */ + listnode_delete(rp->info, rinfo); + if (list_isempty((struct list *)rp->info)) { + list_free(rp->info); + rp->info = NULL; + route_unlock_node(rp); + } - /* Free RIP routing information. */ - rip_info_free (rinfo); + /* Free RIP routing information. */ + rip_info_free(rinfo); - return 0; + return 0; } -static void rip_timeout_update (struct rip_info *rinfo); +static void rip_timeout_update(struct rip_info *rinfo); /* Add new route to the ECMP list. * RETURN: the new entry added in the list, or NULL if it is not the first * entry and ECMP is not allowed. */ -struct rip_info * -rip_ecmp_add (struct rip_info *rinfo_new) +struct rip_info *rip_ecmp_add(struct rip_info *rinfo_new) { - struct route_node *rp = rinfo_new->rp; - struct rip_info *rinfo = NULL; - struct list *list = NULL; + struct route_node *rp = rinfo_new->rp; + struct rip_info *rinfo = NULL; + struct list *list = NULL; - if (rp->info == NULL) - rp->info = list_new (); - list = (struct list *)rp->info; + if (rp->info == NULL) + rp->info = list_new(); + list = (struct list *)rp->info; - /* If ECMP is not allowed and some entry already exists in the list, - * do nothing. */ - if (listcount (list) && !rip->ecmp) - return NULL; + /* If ECMP is not allowed and some entry already exists in the list, + * do nothing. */ + if (listcount(list) && !rip->ecmp) + return NULL; - rinfo = rip_info_new (); - memcpy (rinfo, rinfo_new, sizeof (struct rip_info)); - listnode_add (list, rinfo); + rinfo = rip_info_new(); + memcpy(rinfo, rinfo_new, sizeof(struct rip_info)); + listnode_add(list, rinfo); - if (rip_route_rte (rinfo)) - { - rip_timeout_update (rinfo); - rip_zebra_ipv4_add (rp); - } + if (rip_route_rte(rinfo)) { + rip_timeout_update(rinfo); + rip_zebra_ipv4_add(rp); + } - /* Set the route change flag on the first entry. */ - rinfo = listgetdata (listhead (list)); - SET_FLAG (rinfo->flags, RIP_RTF_CHANGED); + /* Set the route change flag on the first entry. */ + rinfo = listgetdata(listhead(list)); + SET_FLAG(rinfo->flags, RIP_RTF_CHANGED); - /* Signal the output process to trigger an update (see section 2.5). */ - rip_event (RIP_TRIGGERED_UPDATE, 0); + /* Signal the output process to trigger an update (see section 2.5). */ + rip_event(RIP_TRIGGERED_UPDATE, 0); - return rinfo; + return rinfo; } /* Replace the ECMP list with the new route. * RETURN: the new entry added in the list */ -struct rip_info * -rip_ecmp_replace (struct rip_info *rinfo_new) -{ - struct route_node *rp = rinfo_new->rp; - struct list *list = (struct list *)rp->info; - struct rip_info *rinfo = NULL, *tmp_rinfo = NULL; - struct listnode *node = NULL, *nextnode = NULL; - - if (list == NULL || listcount (list) == 0) - return rip_ecmp_add (rinfo_new); - - /* Get the first entry */ - rinfo = listgetdata (listhead (list)); - - /* Learnt route replaced by a local one. Delete it from zebra. */ - if (rip_route_rte (rinfo) && !rip_route_rte (rinfo_new)) - if (CHECK_FLAG (rinfo->flags, RIP_RTF_FIB)) - rip_zebra_ipv4_delete (rp); - - /* Re-use the first entry, and delete the others. */ - for (ALL_LIST_ELEMENTS (list, node, nextnode, tmp_rinfo)) - if (tmp_rinfo != rinfo) - { - RIP_TIMER_OFF (tmp_rinfo->t_timeout); - RIP_TIMER_OFF (tmp_rinfo->t_garbage_collect); - list_delete_node (list, node); - rip_info_free (tmp_rinfo); - } +struct rip_info *rip_ecmp_replace(struct rip_info *rinfo_new) +{ + struct route_node *rp = rinfo_new->rp; + struct list *list = (struct list *)rp->info; + struct rip_info *rinfo = NULL, *tmp_rinfo = NULL; + struct listnode *node = NULL, *nextnode = NULL; + + if (list == NULL || listcount(list) == 0) + return rip_ecmp_add(rinfo_new); + + /* Get the first entry */ + rinfo = listgetdata(listhead(list)); + + /* Learnt route replaced by a local one. Delete it from zebra. */ + if (rip_route_rte(rinfo) && !rip_route_rte(rinfo_new)) + if (CHECK_FLAG(rinfo->flags, RIP_RTF_FIB)) + rip_zebra_ipv4_delete(rp); + + /* Re-use the first entry, and delete the others. */ + for (ALL_LIST_ELEMENTS(list, node, nextnode, tmp_rinfo)) + if (tmp_rinfo != rinfo) { + RIP_TIMER_OFF(tmp_rinfo->t_timeout); + RIP_TIMER_OFF(tmp_rinfo->t_garbage_collect); + list_delete_node(list, node); + rip_info_free(tmp_rinfo); + } - RIP_TIMER_OFF (rinfo->t_timeout); - RIP_TIMER_OFF (rinfo->t_garbage_collect); - memcpy (rinfo, rinfo_new, sizeof (struct rip_info)); + RIP_TIMER_OFF(rinfo->t_timeout); + RIP_TIMER_OFF(rinfo->t_garbage_collect); + memcpy(rinfo, rinfo_new, sizeof(struct rip_info)); - if (rip_route_rte (rinfo)) - { - rip_timeout_update (rinfo); - /* The ADD message implies an update. */ - rip_zebra_ipv4_add (rp); - } + if (rip_route_rte(rinfo)) { + rip_timeout_update(rinfo); + /* The ADD message implies an update. */ + rip_zebra_ipv4_add(rp); + } - /* Set the route change flag. */ - SET_FLAG (rinfo->flags, RIP_RTF_CHANGED); + /* Set the route change flag. */ + SET_FLAG(rinfo->flags, RIP_RTF_CHANGED); - /* Signal the output process to trigger an update (see section 2.5). */ - rip_event (RIP_TRIGGERED_UPDATE, 0); + /* Signal the output process to trigger an update (see section 2.5). */ + rip_event(RIP_TRIGGERED_UPDATE, 0); - return rinfo; + return rinfo; } /* Delete one route from the ECMP list. @@ -254,692 +238,694 @@ rip_ecmp_replace (struct rip_info *rinfo_new) * the entry - the entry is the last one in the list; its metric is set * to INFINITY, and the garbage collector is started for it */ -struct rip_info * -rip_ecmp_delete (struct rip_info *rinfo) -{ - struct route_node *rp = rinfo->rp; - struct list *list = (struct list *)rp->info; - - RIP_TIMER_OFF (rinfo->t_timeout); - - if (listcount (list) > 1) - { - /* Some other ECMP entries still exist. Just delete this entry. */ - RIP_TIMER_OFF (rinfo->t_garbage_collect); - listnode_delete (list, rinfo); - if (rip_route_rte (rinfo) && CHECK_FLAG (rinfo->flags, RIP_RTF_FIB)) - /* The ADD message implies the update. */ - rip_zebra_ipv4_add (rp); - rip_info_free (rinfo); - rinfo = NULL; - } - else - { - assert (rinfo == listgetdata (listhead (list))); - - /* This is the only entry left in the list. We must keep it in - * the list for garbage collection time, with INFINITY metric. */ - - rinfo->metric = RIP_METRIC_INFINITY; - RIP_TIMER_ON (rinfo->t_garbage_collect, - rip_garbage_collect, rip->garbage_time); - - if (rip_route_rte (rinfo) && CHECK_FLAG (rinfo->flags, RIP_RTF_FIB)) - rip_zebra_ipv4_delete (rp); - } +struct rip_info *rip_ecmp_delete(struct rip_info *rinfo) +{ + struct route_node *rp = rinfo->rp; + struct list *list = (struct list *)rp->info; + + RIP_TIMER_OFF(rinfo->t_timeout); + + if (listcount(list) > 1) { + /* Some other ECMP entries still exist. Just delete this entry. + */ + RIP_TIMER_OFF(rinfo->t_garbage_collect); + listnode_delete(list, rinfo); + if (rip_route_rte(rinfo) + && CHECK_FLAG(rinfo->flags, RIP_RTF_FIB)) + /* The ADD message implies the update. */ + rip_zebra_ipv4_add(rp); + rip_info_free(rinfo); + rinfo = NULL; + } else { + assert(rinfo == listgetdata(listhead(list))); + + /* This is the only entry left in the list. We must keep it in + * the list for garbage collection time, with INFINITY metric. + */ + + rinfo->metric = RIP_METRIC_INFINITY; + RIP_TIMER_ON(rinfo->t_garbage_collect, rip_garbage_collect, + rip->garbage_time); + + if (rip_route_rte(rinfo) + && CHECK_FLAG(rinfo->flags, RIP_RTF_FIB)) + rip_zebra_ipv4_delete(rp); + } - /* Set the route change flag on the first entry. */ - rinfo = listgetdata (listhead (list)); - SET_FLAG (rinfo->flags, RIP_RTF_CHANGED); + /* Set the route change flag on the first entry. */ + rinfo = listgetdata(listhead(list)); + SET_FLAG(rinfo->flags, RIP_RTF_CHANGED); - /* Signal the output process to trigger an update (see section 2.5). */ - rip_event (RIP_TRIGGERED_UPDATE, 0); + /* Signal the output process to trigger an update (see section 2.5). */ + rip_event(RIP_TRIGGERED_UPDATE, 0); - return rinfo; + return rinfo; } /* Timeout RIP routes. */ -static int -rip_timeout (struct thread *t) +static int rip_timeout(struct thread *t) { - rip_ecmp_delete ((struct rip_info *)THREAD_ARG (t)); - return 0; + rip_ecmp_delete((struct rip_info *)THREAD_ARG(t)); + return 0; } -static void -rip_timeout_update (struct rip_info *rinfo) -{ - if (rinfo->metric != RIP_METRIC_INFINITY) - { - RIP_TIMER_OFF (rinfo->t_timeout); - RIP_TIMER_ON (rinfo->t_timeout, rip_timeout, rip->timeout_time); - } -} - -static int -rip_filter (int rip_distribute, struct prefix_ipv4 *p, struct rip_interface *ri) -{ - struct distribute *dist; - struct access_list *alist; - struct prefix_list *plist; - int distribute = rip_distribute == RIP_FILTER_OUT ? - DISTRIBUTE_V4_OUT : DISTRIBUTE_V4_IN; - const char *inout = rip_distribute == RIP_FILTER_OUT ? "out" : "in"; - - /* Input distribute-list filtering. */ - if (ri->list[rip_distribute]) - { - if (access_list_apply (ri->list[rip_distribute], - (struct prefix *) p) == FILTER_DENY) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("%s/%d filtered by distribute %s", - inet_ntoa (p->prefix), p->prefixlen, inout); - return -1; - } - } - if (ri->prefix[rip_distribute]) +static void rip_timeout_update(struct rip_info *rinfo) { - if (prefix_list_apply (ri->prefix[rip_distribute], - (struct prefix *) p) == PREFIX_DENY) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("%s/%d filtered by prefix-list %s", - inet_ntoa (p->prefix), p->prefixlen, inout); - return -1; - } - } - - /* All interface filter check. */ - dist = distribute_lookup (NULL); - if (dist) - { - if (dist->list[distribute]) - { - alist = access_list_lookup (AFI_IP, dist->list[distribute]); - - if (alist) - { - if (access_list_apply (alist, (struct prefix *) p) == FILTER_DENY) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("%s/%d filtered by distribute %s", - inet_ntoa (p->prefix), p->prefixlen, inout); - return -1; + if (rinfo->metric != RIP_METRIC_INFINITY) { + RIP_TIMER_OFF(rinfo->t_timeout); + RIP_TIMER_ON(rinfo->t_timeout, rip_timeout, rip->timeout_time); + } +} + +static int rip_filter(int rip_distribute, struct prefix_ipv4 *p, + struct rip_interface *ri) +{ + struct distribute *dist; + struct access_list *alist; + struct prefix_list *plist; + int distribute = rip_distribute == RIP_FILTER_OUT ? DISTRIBUTE_V4_OUT + : DISTRIBUTE_V4_IN; + const char *inout = rip_distribute == RIP_FILTER_OUT ? "out" : "in"; + + /* Input distribute-list filtering. */ + if (ri->list[rip_distribute]) { + if (access_list_apply(ri->list[rip_distribute], + (struct prefix *)p) + == FILTER_DENY) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug("%s/%d filtered by distribute %s", + inet_ntoa(p->prefix), p->prefixlen, + inout); + return -1; } - } } - if (dist->prefix[distribute]) - { - plist = prefix_list_lookup (AFI_IP, dist->prefix[distribute]); - - if (plist) - { - if (prefix_list_apply (plist, - (struct prefix *) p) == PREFIX_DENY) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("%s/%d filtered by prefix-list %s", - inet_ntoa (p->prefix), p->prefixlen, inout); - return -1; + if (ri->prefix[rip_distribute]) { + if (prefix_list_apply(ri->prefix[rip_distribute], + (struct prefix *)p) + == PREFIX_DENY) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug("%s/%d filtered by prefix-list %s", + inet_ntoa(p->prefix), p->prefixlen, + inout); + return -1; } - } } - } - return 0; + + /* All interface filter check. */ + dist = distribute_lookup(NULL); + if (dist) { + if (dist->list[distribute]) { + alist = access_list_lookup(AFI_IP, + dist->list[distribute]); + + if (alist) { + if (access_list_apply(alist, (struct prefix *)p) + == FILTER_DENY) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "%s/%d filtered by distribute %s", + inet_ntoa(p->prefix), + p->prefixlen, inout); + return -1; + } + } + } + if (dist->prefix[distribute]) { + plist = prefix_list_lookup(AFI_IP, + dist->prefix[distribute]); + + if (plist) { + if (prefix_list_apply(plist, (struct prefix *)p) + == PREFIX_DENY) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "%s/%d filtered by prefix-list %s", + inet_ntoa(p->prefix), + p->prefixlen, inout); + return -1; + } + } + } + } + return 0; } /* Check nexthop address validity. */ -static int -rip_nexthop_check (struct in_addr *addr) +static int rip_nexthop_check(struct in_addr *addr) { - struct listnode *node; - struct listnode *cnode; - struct interface *ifp; - struct connected *ifc; - struct prefix *p; + struct listnode *node; + struct listnode *cnode; + struct interface *ifp; + struct connected *ifc; + struct prefix *p; - /* If nexthop address matches local configured address then it is - invalid nexthop. */ + /* If nexthop address matches local configured address then it is + invalid nexthop. */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, ifc)) - { - p = ifc->address; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, ifc)) { + p = ifc->address; - if (p->family == AF_INET - && IPV4_ADDR_SAME (&p->u.prefix4, addr)) - return -1; + if (p->family == AF_INET + && IPV4_ADDR_SAME(&p->u.prefix4, addr)) + return -1; + } } - } - return 0; + return 0; } /* RIP add route to routing table. */ -static void -rip_rte_process (struct rte *rte, struct sockaddr_in *from, - struct interface *ifp) -{ - int ret; - struct prefix_ipv4 p; - struct route_node *rp; - struct rip_info *rinfo = NULL, newinfo; - struct rip_interface *ri; - struct in_addr *nexthop; - int same = 0; - unsigned char old_dist, new_dist; - struct list *list = NULL; - struct listnode *node = NULL; - - /* Make prefix structure. */ - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefix = rte->prefix; - p.prefixlen = ip_masklen (rte->mask); - - /* Make sure mask is applied. */ - apply_mask_ipv4 (&p); - - /* Apply input filters. */ - ri = ifp->info; - - ret = rip_filter (RIP_FILTER_IN, &p, ri); - if (ret < 0) - return; - - memset (&newinfo, 0, sizeof (newinfo)); - newinfo.type = ZEBRA_ROUTE_RIP; - newinfo.sub_type = RIP_ROUTE_RTE; - newinfo.nexthop = rte->nexthop; - newinfo.from = from->sin_addr; - newinfo.ifindex = ifp->ifindex; - newinfo.metric = rte->metric; - newinfo.metric_out = rte->metric; /* XXX */ - newinfo.tag = ntohs (rte->tag); /* XXX */ - - /* Modify entry according to the interface routemap. */ - if (ri->routemap[RIP_FILTER_IN]) - { - int ret; - - /* The object should be of the type of rip_info */ - ret = route_map_apply (ri->routemap[RIP_FILTER_IN], - (struct prefix *) &p, RMAP_RIP, &newinfo); - - if (ret == RMAP_DENYMATCH) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("RIP %s/%d is filtered by route-map in", - inet_ntoa (p.prefix), p.prefixlen); - return; - } - - /* Get back the object */ - rte->nexthop = newinfo.nexthop_out; - rte->tag = htons (newinfo.tag_out); /* XXX */ - rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */ - } - - /* Once the entry has been validated, update the metric by - adding the cost of the network on wich the message - arrived. If the result is greater than infinity, use infinity - (RFC2453 Sec. 3.9.2) */ - /* Zebra ripd can handle offset-list in. */ - ret = rip_offset_list_apply_in (&p, ifp, &rte->metric); - - /* If offset-list does not modify the metric use interface's - metric. */ - if (!ret) - rte->metric += ifp->metric ? ifp->metric : 1; - - if (rte->metric > RIP_METRIC_INFINITY) - rte->metric = RIP_METRIC_INFINITY; - - /* Set nexthop pointer. */ - if (rte->nexthop.s_addr == 0) - nexthop = &from->sin_addr; - else - nexthop = &rte->nexthop; - - /* Check if nexthop address is myself, then do nothing. */ - if (rip_nexthop_check (nexthop) < 0) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("Nexthop address %s is myself", inet_ntoa (*nexthop)); - return; - } - - /* Get index for the prefix. */ - rp = route_node_get (rip->table, (struct prefix *) &p); - - newinfo.rp = rp; - newinfo.nexthop = *nexthop; - newinfo.metric = rte->metric; - newinfo.tag = ntohs (rte->tag); - newinfo.distance = rip_distance_apply (&newinfo); - - new_dist = newinfo.distance ? newinfo.distance : ZEBRA_RIP_DISTANCE_DEFAULT; - - /* Check to see whether there is already RIP route on the table. */ - if ((list = rp->info) != NULL) - for (ALL_LIST_ELEMENTS_RO (list, node, rinfo)) - { - /* Need to compare with redistributed entry or local entry */ - if (!rip_route_rte (rinfo)) - break; - - if (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr) && - IPV4_ADDR_SAME (&rinfo->nexthop, nexthop)) - break; - - if (!listnextnode (node)) - { - /* Not found in the list */ - - if (rte->metric > rinfo->metric) - { - /* New route has a greater metric. Discard it. */ - route_unlock_node (rp); - return; - } - - if (rte->metric < rinfo->metric) - /* New route has a smaller metric. Replace the ECMP list - * with the new one in below. */ - break; - - /* Metrics are same. We compare the distances. */ - old_dist = rinfo->distance ? \ - rinfo->distance : ZEBRA_RIP_DISTANCE_DEFAULT; - - if (new_dist > old_dist) - { - /* New route has a greater distance. Discard it. */ - route_unlock_node (rp); - return; - } - - if (new_dist < old_dist) - /* New route has a smaller distance. Replace the ECMP list - * with the new one in below. */ - break; - - /* Metrics and distances are both same. Keep "rinfo" null and - * the new route is added in the ECMP list in below. */ - } - } - - if (rinfo) - { - /* Local static route. */ - if (rinfo->type == ZEBRA_ROUTE_RIP - && ((rinfo->sub_type == RIP_ROUTE_STATIC) || - (rinfo->sub_type == RIP_ROUTE_DEFAULT)) - && rinfo->metric != RIP_METRIC_INFINITY) - { - route_unlock_node (rp); - return; - } - - /* Redistributed route check. */ - if (rinfo->type != ZEBRA_ROUTE_RIP - && rinfo->metric != RIP_METRIC_INFINITY) - { - old_dist = rinfo->distance; - /* Only routes directly connected to an interface (nexthop == 0) - * may have a valid NULL distance */ - if (rinfo->nexthop.s_addr != 0) - old_dist = old_dist ? old_dist : ZEBRA_RIP_DISTANCE_DEFAULT; - /* If imported route does not have STRICT precedence, - mark it as a ghost */ - if (new_dist <= old_dist && rte->metric != RIP_METRIC_INFINITY) - rip_ecmp_replace (&newinfo); - - route_unlock_node (rp); - return; - } - } - - if (!rinfo) - { - if (rp->info) - route_unlock_node (rp); - - /* Now, check to see whether there is already an explicit route - for the destination prefix. If there is no such route, add - this route to the routing table, unless the metric is - infinity (there is no point in adding a route which - unusable). */ - if (rte->metric != RIP_METRIC_INFINITY) - rip_ecmp_add (&newinfo); - } - else - { - /* Route is there but we are not sure the route is RIP or not. */ - - /* If there is an existing route, compare the next hop address - to the address of the router from which the datagram came. - If this datagram is from the same router as the existing - route, reinitialize the timeout. */ - same = (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr) - && (rinfo->ifindex == ifp->ifindex)); - - old_dist = rinfo->distance ? \ - rinfo->distance : ZEBRA_RIP_DISTANCE_DEFAULT; - - /* Next, compare the metrics. If the datagram is from the same - router as the existing route, and the new metric is different - than the old one; or, if the new metric is lower than the old - one, or if the tag has been changed; or if there is a route - with a lower administrave distance; or an update of the - distance on the actual route; do the following actions: */ - if ((same && rinfo->metric != rte->metric) - || (rte->metric < rinfo->metric) - || ((same) - && (rinfo->metric == rte->metric) - && (newinfo.tag != rinfo->tag)) - || (old_dist > new_dist) - || ((old_dist != new_dist) && same)) - { - if (listcount (list) == 1) - { - if (newinfo.metric != RIP_METRIC_INFINITY) - rip_ecmp_replace (&newinfo); - else - rip_ecmp_delete (rinfo); - } - else - { - if (newinfo.metric < rinfo->metric) - rip_ecmp_replace (&newinfo); - else if (newinfo.metric > rinfo->metric) - rip_ecmp_delete (rinfo); - else if (new_dist < old_dist) - rip_ecmp_replace (&newinfo); - else if (new_dist > old_dist) - rip_ecmp_delete (rinfo); - else - { - int update = CHECK_FLAG (rinfo->flags, RIP_RTF_FIB) ? 1 : 0; - - assert (newinfo.metric != RIP_METRIC_INFINITY); - - RIP_TIMER_OFF (rinfo->t_timeout); - RIP_TIMER_OFF (rinfo->t_garbage_collect); - memcpy (rinfo, &newinfo, sizeof (struct rip_info)); - rip_timeout_update (rinfo); - - if (update) - rip_zebra_ipv4_add (rp); - - /* - Set the route change flag on the first entry. */ - rinfo = listgetdata (listhead (list)); - SET_FLAG (rinfo->flags, RIP_RTF_CHANGED); - rip_event (RIP_TRIGGERED_UPDATE, 0); - } - } - } - else /* same & no change */ - rip_timeout_update (rinfo); - - /* Unlock tempolary lock of the route. */ - route_unlock_node (rp); - } -} +static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, + struct interface *ifp) +{ + int ret; + struct prefix_ipv4 p; + struct route_node *rp; + struct rip_info *rinfo = NULL, newinfo; + struct rip_interface *ri; + struct in_addr *nexthop; + int same = 0; + unsigned char old_dist, new_dist; + struct list *list = NULL; + struct listnode *node = NULL; + + /* Make prefix structure. */ + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefix = rte->prefix; + p.prefixlen = ip_masklen(rte->mask); + + /* Make sure mask is applied. */ + apply_mask_ipv4(&p); + + /* Apply input filters. */ + ri = ifp->info; -/* Dump RIP packet */ -static void -rip_packet_dump (struct rip_packet *packet, int size, const char *sndrcv) -{ - caddr_t lim; - struct rte *rte; - const char *command_str; - char pbuf[BUFSIZ], nbuf[BUFSIZ]; - u_char netmask = 0; - u_char *p; - - /* Set command string. */ - if (packet->command > 0 && packet->command < RIP_COMMAND_MAX) - command_str = lookup_msg (rip_msg, packet->command, NULL); - else - command_str = "unknown"; - - /* Dump packet header. */ - zlog_debug ("%s %s version %d packet size %d", - sndrcv, command_str, packet->version, size); - - /* Dump each routing table entry. */ - rte = packet->rte; - - for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++) - { - if (packet->version == RIPv2) - { - netmask = ip_masklen (rte->mask); + ret = rip_filter(RIP_FILTER_IN, &p, ri); + if (ret < 0) + return; + + memset(&newinfo, 0, sizeof(newinfo)); + newinfo.type = ZEBRA_ROUTE_RIP; + newinfo.sub_type = RIP_ROUTE_RTE; + newinfo.nexthop = rte->nexthop; + newinfo.from = from->sin_addr; + newinfo.ifindex = ifp->ifindex; + newinfo.metric = rte->metric; + newinfo.metric_out = rte->metric; /* XXX */ + newinfo.tag = ntohs(rte->tag); /* XXX */ + + /* Modify entry according to the interface routemap. */ + if (ri->routemap[RIP_FILTER_IN]) { + int ret; + + /* The object should be of the type of rip_info */ + ret = route_map_apply(ri->routemap[RIP_FILTER_IN], + (struct prefix *)&p, RMAP_RIP, &newinfo); + + if (ret == RMAP_DENYMATCH) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "RIP %s/%d is filtered by route-map in", + inet_ntoa(p.prefix), p.prefixlen); + return; + } + + /* Get back the object */ + rte->nexthop = newinfo.nexthop_out; + rte->tag = htons(newinfo.tag_out); /* XXX */ + rte->metric = + newinfo.metric_out; /* XXX: the routemap uses the + metric_out field */ + } + + /* Once the entry has been validated, update the metric by + adding the cost of the network on wich the message + arrived. If the result is greater than infinity, use infinity + (RFC2453 Sec. 3.9.2) */ + /* Zebra ripd can handle offset-list in. */ + ret = rip_offset_list_apply_in(&p, ifp, &rte->metric); - if (rte->family == htons (RIP_FAMILY_AUTH)) - { - if (rte->tag == htons (RIP_AUTH_SIMPLE_PASSWORD)) - { - p = (u_char *)&rte->prefix; + /* If offset-list does not modify the metric use interface's + metric. */ + if (!ret) + rte->metric += ifp->metric ? ifp->metric : 1; - zlog_debug (" family 0x%X type %d auth string: %s", - ntohs (rte->family), ntohs (rte->tag), p); + if (rte->metric > RIP_METRIC_INFINITY) + rte->metric = RIP_METRIC_INFINITY; + + /* Set nexthop pointer. */ + if (rte->nexthop.s_addr == 0) + nexthop = &from->sin_addr; + else + nexthop = &rte->nexthop; + + /* Check if nexthop address is myself, then do nothing. */ + if (rip_nexthop_check(nexthop) < 0) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug("Nexthop address %s is myself", + inet_ntoa(*nexthop)); + return; + } + + /* Get index for the prefix. */ + rp = route_node_get(rip->table, (struct prefix *)&p); + + newinfo.rp = rp; + newinfo.nexthop = *nexthop; + newinfo.metric = rte->metric; + newinfo.tag = ntohs(rte->tag); + newinfo.distance = rip_distance_apply(&newinfo); + + new_dist = newinfo.distance ? newinfo.distance + : ZEBRA_RIP_DISTANCE_DEFAULT; + + /* Check to see whether there is already RIP route on the table. */ + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS_RO(list, node, rinfo)) { + /* Need to compare with redistributed entry or local + * entry */ + if (!rip_route_rte(rinfo)) + break; + + if (IPV4_ADDR_SAME(&rinfo->from, &from->sin_addr) + && IPV4_ADDR_SAME(&rinfo->nexthop, nexthop)) + break; + + if (!listnextnode(node)) { + /* Not found in the list */ + + if (rte->metric > rinfo->metric) { + /* New route has a greater metric. + * Discard it. */ + route_unlock_node(rp); + return; + } + + if (rte->metric < rinfo->metric) + /* New route has a smaller metric. + * Replace the ECMP list + * with the new one in below. */ + break; + + /* Metrics are same. We compare the distances. + */ + old_dist = rinfo->distance + ? rinfo->distance + : ZEBRA_RIP_DISTANCE_DEFAULT; + + if (new_dist > old_dist) { + /* New route has a greater distance. + * Discard it. */ + route_unlock_node(rp); + return; + } + + if (new_dist < old_dist) + /* New route has a smaller distance. + * Replace the ECMP list + * with the new one in below. */ + break; + + /* Metrics and distances are both same. Keep + * "rinfo" null and + * the new route is added in the ECMP list in + * below. */ + } } - else if (rte->tag == htons (RIP_AUTH_MD5)) - { - struct rip_md5_info *md5; - - md5 = (struct rip_md5_info *) &packet->rte; - - zlog_debug (" family 0x%X type %d (MD5 authentication)", - ntohs (md5->family), ntohs (md5->type)); - zlog_debug (" RIP-2 packet len %d Key ID %d" - " Auth Data len %d", - ntohs (md5->packet_len), md5->keyid, - md5->auth_len); - zlog_debug (" Sequence Number %ld", - (u_long) ntohl (md5->sequence)); + + if (rinfo) { + /* Local static route. */ + if (rinfo->type == ZEBRA_ROUTE_RIP + && ((rinfo->sub_type == RIP_ROUTE_STATIC) + || (rinfo->sub_type == RIP_ROUTE_DEFAULT)) + && rinfo->metric != RIP_METRIC_INFINITY) { + route_unlock_node(rp); + return; } - else if (rte->tag == htons (RIP_AUTH_DATA)) - { - p = (u_char *)&rte->prefix; - - zlog_debug (" family 0x%X type %d (MD5 data)", - ntohs (rte->family), ntohs (rte->tag)); - zlog_debug (" MD5: %02X%02X%02X%02X%02X%02X%02X%02X" - "%02X%02X%02X%02X%02X%02X%02X%02X", - p[0], p[1], p[2], p[3], p[4], p[5], p[6], - p[7], p[8], p[9], p[10], p[11], p[12], p[13], - p[14], p[15]); + + /* Redistributed route check. */ + if (rinfo->type != ZEBRA_ROUTE_RIP + && rinfo->metric != RIP_METRIC_INFINITY) { + old_dist = rinfo->distance; + /* Only routes directly connected to an interface + * (nexthop == 0) + * may have a valid NULL distance */ + if (rinfo->nexthop.s_addr != 0) + old_dist = old_dist + ? old_dist + : ZEBRA_RIP_DISTANCE_DEFAULT; + /* If imported route does not have STRICT precedence, + mark it as a ghost */ + if (new_dist <= old_dist + && rte->metric != RIP_METRIC_INFINITY) + rip_ecmp_replace(&newinfo); + + route_unlock_node(rp); + return; } - else - { - zlog_debug (" family 0x%X type %d (Unknown auth type)", - ntohs (rte->family), ntohs (rte->tag)); + } + + if (!rinfo) { + if (rp->info) + route_unlock_node(rp); + + /* Now, check to see whether there is already an explicit route + for the destination prefix. If there is no such route, add + this route to the routing table, unless the metric is + infinity (there is no point in adding a route which + unusable). */ + if (rte->metric != RIP_METRIC_INFINITY) + rip_ecmp_add(&newinfo); + } else { + /* Route is there but we are not sure the route is RIP or not. + */ + + /* If there is an existing route, compare the next hop address + to the address of the router from which the datagram came. + If this datagram is from the same router as the existing + route, reinitialize the timeout. */ + same = (IPV4_ADDR_SAME(&rinfo->from, &from->sin_addr) + && (rinfo->ifindex == ifp->ifindex)); + + old_dist = rinfo->distance ? rinfo->distance + : ZEBRA_RIP_DISTANCE_DEFAULT; + + /* Next, compare the metrics. If the datagram is from the same + router as the existing route, and the new metric is different + than the old one; or, if the new metric is lower than the old + one, or if the tag has been changed; or if there is a route + with a lower administrave distance; or an update of the + distance on the actual route; do the following actions: */ + if ((same && rinfo->metric != rte->metric) + || (rte->metric < rinfo->metric) + || ((same) && (rinfo->metric == rte->metric) + && (newinfo.tag != rinfo->tag)) + || (old_dist > new_dist) + || ((old_dist != new_dist) && same)) { + if (listcount(list) == 1) { + if (newinfo.metric != RIP_METRIC_INFINITY) + rip_ecmp_replace(&newinfo); + else + rip_ecmp_delete(rinfo); + } else { + if (newinfo.metric < rinfo->metric) + rip_ecmp_replace(&newinfo); + else if (newinfo.metric > rinfo->metric) + rip_ecmp_delete(rinfo); + else if (new_dist < old_dist) + rip_ecmp_replace(&newinfo); + else if (new_dist > old_dist) + rip_ecmp_delete(rinfo); + else { + int update = CHECK_FLAG(rinfo->flags, + RIP_RTF_FIB) + ? 1 + : 0; + + assert(newinfo.metric + != RIP_METRIC_INFINITY); + + RIP_TIMER_OFF(rinfo->t_timeout); + RIP_TIMER_OFF(rinfo->t_garbage_collect); + memcpy(rinfo, &newinfo, + sizeof(struct rip_info)); + rip_timeout_update(rinfo); + + if (update) + rip_zebra_ipv4_add(rp); + + /* - Set the route change flag on the + * first entry. */ + rinfo = listgetdata(listhead(list)); + SET_FLAG(rinfo->flags, RIP_RTF_CHANGED); + rip_event(RIP_TRIGGERED_UPDATE, 0); + } + } + } else /* same & no change */ + rip_timeout_update(rinfo); + + /* Unlock tempolary lock of the route. */ + route_unlock_node(rp); + } +} + +/* Dump RIP packet */ +static void rip_packet_dump(struct rip_packet *packet, int size, + const char *sndrcv) +{ + caddr_t lim; + struct rte *rte; + const char *command_str; + char pbuf[BUFSIZ], nbuf[BUFSIZ]; + u_char netmask = 0; + u_char *p; + + /* Set command string. */ + if (packet->command > 0 && packet->command < RIP_COMMAND_MAX) + command_str = lookup_msg(rip_msg, packet->command, NULL); + else + command_str = "unknown"; + + /* Dump packet header. */ + zlog_debug("%s %s version %d packet size %d", sndrcv, command_str, + packet->version, size); + + /* Dump each routing table entry. */ + rte = packet->rte; + + for (lim = (caddr_t)packet + size; (caddr_t)rte < lim; rte++) { + if (packet->version == RIPv2) { + netmask = ip_masklen(rte->mask); + + if (rte->family == htons(RIP_FAMILY_AUTH)) { + if (rte->tag + == htons(RIP_AUTH_SIMPLE_PASSWORD)) { + p = (u_char *)&rte->prefix; + + zlog_debug( + " family 0x%X type %d auth string: %s", + ntohs(rte->family), + ntohs(rte->tag), p); + } else if (rte->tag == htons(RIP_AUTH_MD5)) { + struct rip_md5_info *md5; + + md5 = (struct rip_md5_info *)&packet + ->rte; + + zlog_debug( + " family 0x%X type %d (MD5 authentication)", + ntohs(md5->family), + ntohs(md5->type)); + zlog_debug( + " RIP-2 packet len %d Key ID %d" + " Auth Data len %d", + ntohs(md5->packet_len), + md5->keyid, md5->auth_len); + zlog_debug( + " Sequence Number %ld", + (u_long)ntohl(md5->sequence)); + } else if (rte->tag == htons(RIP_AUTH_DATA)) { + p = (u_char *)&rte->prefix; + + zlog_debug( + " family 0x%X type %d (MD5 data)", + ntohs(rte->family), + ntohs(rte->tag)); + zlog_debug( + " MD5: %02X%02X%02X%02X%02X%02X%02X%02X" + "%02X%02X%02X%02X%02X%02X%02X%02X", + p[0], p[1], p[2], p[3], p[4], + p[5], p[6], p[7], p[8], p[9], + p[10], p[11], p[12], p[13], + p[14], p[15]); + } else { + zlog_debug( + " family 0x%X type %d (Unknown auth type)", + ntohs(rte->family), + ntohs(rte->tag)); + } + } else + zlog_debug( + " %s/%d -> %s family %d tag %" ROUTE_TAG_PRI + " metric %ld", + inet_ntop(AF_INET, &rte->prefix, pbuf, + BUFSIZ), + netmask, + inet_ntop(AF_INET, &rte->nexthop, nbuf, + BUFSIZ), + ntohs(rte->family), + (route_tag_t)ntohs(rte->tag), + (u_long)ntohl(rte->metric)); + } else { + zlog_debug( + " %s family %d tag %" ROUTE_TAG_PRI + " metric %ld", + inet_ntop(AF_INET, &rte->prefix, pbuf, BUFSIZ), + ntohs(rte->family), + (route_tag_t)ntohs(rte->tag), + (u_long)ntohl(rte->metric)); } - } - else - zlog_debug (" %s/%d -> %s family %d tag %"ROUTE_TAG_PRI" metric %ld", - inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ), - netmask, inet_ntop (AF_INET, &rte->nexthop, nbuf, - BUFSIZ), ntohs (rte->family), - (route_tag_t)ntohs (rte->tag), - (u_long) ntohl (rte->metric)); - } - else - { - zlog_debug (" %s family %d tag %"ROUTE_TAG_PRI" metric %ld", - inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ), - ntohs (rte->family), (route_tag_t)ntohs (rte->tag), - (u_long)ntohl (rte->metric)); } - } } /* Check if the destination address is valid (unicast; not net 0 or 127) (RFC2453 Section 3.9.2 - Page 26). But we don't check net 0 because we accept default route. */ -static int -rip_destination_check (struct in_addr addr) +static int rip_destination_check(struct in_addr addr) { - u_int32_t destination; + u_int32_t destination; - /* Convert to host byte order. */ - destination = ntohl (addr.s_addr); + /* Convert to host byte order. */ + destination = ntohl(addr.s_addr); - if (IPV4_NET127 (destination)) - return 0; + if (IPV4_NET127(destination)) + return 0; - /* Net 0 may match to the default route. */ - if (IPV4_NET0 (destination) && destination != 0) - return 0; + /* Net 0 may match to the default route. */ + if (IPV4_NET0(destination) && destination != 0) + return 0; - /* Unicast address must belong to class A, B, C. */ - if (IN_CLASSA (destination)) - return 1; - if (IN_CLASSB (destination)) - return 1; - if (IN_CLASSC (destination)) - return 1; + /* Unicast address must belong to class A, B, C. */ + if (IN_CLASSA(destination)) + return 1; + if (IN_CLASSB(destination)) + return 1; + if (IN_CLASSC(destination)) + return 1; - return 0; + return 0; } /* RIP version 2 authentication. */ -static int -rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from, - struct interface *ifp) -{ - struct rip_interface *ri; - char *auth_str = (char *) &rte->prefix; - int i; - - /* reject passwords with zeros in the middle of the string */ - for (i = strlen (auth_str); i < 16; i++) - { - if (auth_str[i] != '\0') - return 0; - } - - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("RIPv2 simple password authentication from %s", - inet_ntoa (from->sin_addr)); - - ri = ifp->info; - - if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD - || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD)) - return 0; - - /* Simple password authentication. */ - if (ri->auth_str) - { - if (strncmp (auth_str, ri->auth_str, 16) == 0) - return 1; - } - if (ri->key_chain) - { - struct keychain *keychain; - struct key *key; - - keychain = keychain_lookup (ri->key_chain); - if (keychain == NULL) - return 0; +static int rip_auth_simple_password(struct rte *rte, struct sockaddr_in *from, + struct interface *ifp) +{ + struct rip_interface *ri; + char *auth_str = (char *)&rte->prefix; + int i; + + /* reject passwords with zeros in the middle of the string */ + for (i = strlen(auth_str); i < 16; i++) { + if (auth_str[i] != '\0') + return 0; + } + + if (IS_RIP_DEBUG_EVENT) + zlog_debug("RIPv2 simple password authentication from %s", + inet_ntoa(from->sin_addr)); + + ri = ifp->info; + + if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD + || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD)) + return 0; - key = key_match_for_accept (keychain, auth_str); - if (key) - return 1; - } - return 0; + /* Simple password authentication. */ + if (ri->auth_str) { + if (strncmp(auth_str, ri->auth_str, 16) == 0) + return 1; + } + if (ri->key_chain) { + struct keychain *keychain; + struct key *key; + + keychain = keychain_lookup(ri->key_chain); + if (keychain == NULL) + return 0; + + key = key_match_for_accept(keychain, auth_str); + if (key) + return 1; + } + return 0; } /* RIP version 2 authentication with MD5. */ -static int -rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from, - int length, struct interface *ifp) -{ - struct rip_interface *ri; - struct rip_md5_info *md5; - struct rip_md5_data *md5data; - struct keychain *keychain; - struct key *key; - MD5_CTX ctx; - u_char digest[RIP_AUTH_MD5_SIZE]; - u_int16_t packet_len; - char auth_str[RIP_AUTH_MD5_SIZE]; - - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("RIPv2 MD5 authentication from %s", - inet_ntoa (from->sin_addr)); - - ri = ifp->info; - md5 = (struct rip_md5_info *) &packet->rte; - - /* Check auth type. */ - if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5)) - return 0; - - /* If the authentication length is less than 16, then it must be wrong for - * any interpretation of rfc2082. Some implementations also interpret - * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka RIP_AUTH_MD5_COMPAT_SIZE. - */ - if ( !((md5->auth_len == RIP_AUTH_MD5_SIZE) - || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE))) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("RIPv2 MD5 authentication, strange authentication " - "length field %d", md5->auth_len); - return 0; - } - - /* grab and verify check packet length */ - packet_len = ntohs (md5->packet_len); - - if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE)) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("RIPv2 MD5 authentication, packet length field %d " - "greater than received length %d!", - md5->packet_len, length); - return 0; - } - - /* retrieve authentication data */ - md5data = (struct rip_md5_data *) (((u_char *) packet) + packet_len); - - memset (auth_str, 0, RIP_AUTH_MD5_SIZE); - - if (ri->key_chain) - { - keychain = keychain_lookup (ri->key_chain); - if (keychain == NULL) - return 0; +static int rip_auth_md5(struct rip_packet *packet, struct sockaddr_in *from, + int length, struct interface *ifp) +{ + struct rip_interface *ri; + struct rip_md5_info *md5; + struct rip_md5_data *md5data; + struct keychain *keychain; + struct key *key; + MD5_CTX ctx; + u_char digest[RIP_AUTH_MD5_SIZE]; + u_int16_t packet_len; + char auth_str[RIP_AUTH_MD5_SIZE]; + + if (IS_RIP_DEBUG_EVENT) + zlog_debug("RIPv2 MD5 authentication from %s", + inet_ntoa(from->sin_addr)); - key = key_lookup_for_accept (keychain, md5->keyid); - if (key == NULL) - return 0; + ri = ifp->info; + md5 = (struct rip_md5_info *)&packet->rte; + + /* Check auth type. */ + if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5)) + return 0; + + /* If the authentication length is less than 16, then it must be wrong + * for + * any interpretation of rfc2082. Some implementations also interpret + * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka + * RIP_AUTH_MD5_COMPAT_SIZE. + */ + if (!((md5->auth_len == RIP_AUTH_MD5_SIZE) + || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE))) { + if (IS_RIP_DEBUG_EVENT) + zlog_debug( + "RIPv2 MD5 authentication, strange authentication " + "length field %d", + md5->auth_len); + return 0; + } + + /* grab and verify check packet length */ + packet_len = ntohs(md5->packet_len); - strncpy (auth_str, key->string, RIP_AUTH_MD5_SIZE); - } - else if (ri->auth_str) - strncpy (auth_str, ri->auth_str, RIP_AUTH_MD5_SIZE); - - if (auth_str[0] == 0) - return 0; - - /* MD5 digest authentication. */ - memset (&ctx, 0, sizeof(ctx)); - MD5Init(&ctx); - MD5Update(&ctx, packet, packet_len + RIP_HEADER_SIZE); - MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE); - MD5Final(digest, &ctx); - - if (memcmp (md5data->digest, digest, RIP_AUTH_MD5_SIZE) == 0) - return packet_len; - else - return 0; + if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE)) { + if (IS_RIP_DEBUG_EVENT) + zlog_debug( + "RIPv2 MD5 authentication, packet length field %d " + "greater than received length %d!", + md5->packet_len, length); + return 0; + } + + /* retrieve authentication data */ + md5data = (struct rip_md5_data *)(((u_char *)packet) + packet_len); + + memset(auth_str, 0, RIP_AUTH_MD5_SIZE); + + if (ri->key_chain) { + keychain = keychain_lookup(ri->key_chain); + if (keychain == NULL) + return 0; + + key = key_lookup_for_accept(keychain, md5->keyid); + if (key == NULL) + return 0; + + strncpy(auth_str, key->string, RIP_AUTH_MD5_SIZE); + } else if (ri->auth_str) + strncpy(auth_str, ri->auth_str, RIP_AUTH_MD5_SIZE); + + if (auth_str[0] == 0) + return 0; + + /* MD5 digest authentication. */ + memset(&ctx, 0, sizeof(ctx)); + MD5Init(&ctx); + MD5Update(&ctx, packet, packet_len + RIP_HEADER_SIZE); + MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE); + MD5Final(digest, &ctx); + + if (memcmp(md5data->digest, digest, RIP_AUTH_MD5_SIZE) == 0) + return packet_len; + else + return 0; } /* Pick correct auth string for sends, prepare auth_str buffer for use. @@ -950,39 +936,37 @@ rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from, * zero padded. * */ -static void -rip_auth_prepare_str_send (struct rip_interface *ri, struct key *key, - char *auth_str, int len) +static void rip_auth_prepare_str_send(struct rip_interface *ri, struct key *key, + char *auth_str, int len) { - assert (ri || key); + assert(ri || key); - memset (auth_str, 0, len); - if (key && key->string) - strncpy (auth_str, key->string, len); - else if (ri->auth_str) - strncpy (auth_str, ri->auth_str, len); + memset(auth_str, 0, len); + if (key && key->string) + strncpy(auth_str, key->string, len); + else if (ri->auth_str) + strncpy(auth_str, ri->auth_str, len); - return; + return; } /* Write RIPv2 simple password authentication information * - * auth_str is presumed to be 2 bytes and correctly prepared + * auth_str is presumed to be 2 bytes and correctly prepared * (left justified and zero padded). */ -static void -rip_auth_simple_write (struct stream *s, char *auth_str, int len) +static void rip_auth_simple_write(struct stream *s, char *auth_str, int len) { - assert (s && len == RIP_AUTH_SIMPLE_SIZE); - - stream_putw (s, RIP_FAMILY_AUTH); - stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD); - stream_put (s, auth_str, RIP_AUTH_SIMPLE_SIZE); - - return; + assert(s && len == RIP_AUTH_SIMPLE_SIZE); + + stream_putw(s, RIP_FAMILY_AUTH); + stream_putw(s, RIP_AUTH_SIMPLE_PASSWORD); + stream_put(s, auth_str, RIP_AUTH_SIMPLE_SIZE); + + return; } -/* write RIPv2 MD5 "authentication header" +/* write RIPv2 MD5 "authentication header" * (uses the auth key data field) * * Digest offset field is set to 0. @@ -990,1814 +974,1818 @@ rip_auth_simple_write (struct stream *s, char *auth_str, int len) * returns: offset of the digest offset field, which must be set when * length to the auth-data MD5 digest is known. */ -static size_t -rip_auth_md5_ah_write (struct stream *s, struct rip_interface *ri, - struct key *key) -{ - size_t doff = 0; - - assert (s && ri && ri->auth_type == RIP_AUTH_MD5); - - /* MD5 authentication. */ - stream_putw (s, RIP_FAMILY_AUTH); - stream_putw (s, RIP_AUTH_MD5); - - /* MD5 AH digest offset field. - * - * Set to placeholder value here, to true value when RIP-2 Packet length - * is known. Actual value is set in .....(). - */ - doff = stream_get_endp(s); - stream_putw (s, 0); - - /* Key ID. */ - if (key) - stream_putc (s, key->index % 256); - else - stream_putc (s, 1); - - /* Auth Data Len. Set 16 for MD5 authentication data. Older ripds - * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for this - * to be configurable. - */ - stream_putc (s, ri->md5_auth_len); - - /* Sequence Number (non-decreasing). */ - /* RFC2080: The value used in the sequence number is - arbitrary, but two suggestions are the time of the - message's creation or a simple message counter. */ - stream_putl (s, time (NULL)); - - /* Reserved field must be zero. */ - stream_putl (s, 0); - stream_putl (s, 0); - - return doff; +static size_t rip_auth_md5_ah_write(struct stream *s, struct rip_interface *ri, + struct key *key) +{ + size_t doff = 0; + + assert(s && ri && ri->auth_type == RIP_AUTH_MD5); + + /* MD5 authentication. */ + stream_putw(s, RIP_FAMILY_AUTH); + stream_putw(s, RIP_AUTH_MD5); + + /* MD5 AH digest offset field. + * + * Set to placeholder value here, to true value when RIP-2 Packet length + * is known. Actual value is set in .....(). + */ + doff = stream_get_endp(s); + stream_putw(s, 0); + + /* Key ID. */ + if (key) + stream_putc(s, key->index % 256); + else + stream_putc(s, 1); + + /* Auth Data Len. Set 16 for MD5 authentication data. Older ripds + * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for + * this + * to be configurable. + */ + stream_putc(s, ri->md5_auth_len); + + /* Sequence Number (non-decreasing). */ + /* RFC2080: The value used in the sequence number is + arbitrary, but two suggestions are the time of the + message's creation or a simple message counter. */ + stream_putl(s, time(NULL)); + + /* Reserved field must be zero. */ + stream_putl(s, 0); + stream_putl(s, 0); + + return doff; } /* If authentication is in used, write the appropriate header * returns stream offset to which length must later be written * or 0 if this is not required */ -static size_t -rip_auth_header_write (struct stream *s, struct rip_interface *ri, - struct key *key, char *auth_str, int len) -{ - assert (ri->auth_type != RIP_NO_AUTH); - - switch (ri->auth_type) - { - case RIP_AUTH_SIMPLE_PASSWORD: - rip_auth_prepare_str_send (ri, key, auth_str, len); - rip_auth_simple_write (s, auth_str, len); - return 0; - case RIP_AUTH_MD5: - return rip_auth_md5_ah_write (s, ri, key); - } - assert (1); - return 0; +static size_t rip_auth_header_write(struct stream *s, struct rip_interface *ri, + struct key *key, char *auth_str, int len) +{ + assert(ri->auth_type != RIP_NO_AUTH); + + switch (ri->auth_type) { + case RIP_AUTH_SIMPLE_PASSWORD: + rip_auth_prepare_str_send(ri, key, auth_str, len); + rip_auth_simple_write(s, auth_str, len); + return 0; + case RIP_AUTH_MD5: + return rip_auth_md5_ah_write(s, ri, key); + } + assert(1); + return 0; } /* Write RIPv2 MD5 authentication data trailer */ -static void -rip_auth_md5_set (struct stream *s, struct rip_interface *ri, size_t doff, - char *auth_str, int authlen) -{ - unsigned long len; - MD5_CTX ctx; - unsigned char digest[RIP_AUTH_MD5_SIZE]; - - /* Make it sure this interface is configured as MD5 - authentication. */ - assert ((ri->auth_type == RIP_AUTH_MD5) && (authlen == RIP_AUTH_MD5_SIZE)); - assert (doff > 0); - - /* Get packet length. */ - len = stream_get_endp(s); - - /* Check packet length. */ - if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE)) - { - zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len); - return; - } - - /* Set the digest offset length in the header */ - stream_putw_at (s, doff, len); - - /* Set authentication data. */ - stream_putw (s, RIP_FAMILY_AUTH); - stream_putw (s, RIP_AUTH_DATA); - - /* Generate a digest for the RIP packet. */ - memset(&ctx, 0, sizeof(ctx)); - MD5Init(&ctx); - MD5Update(&ctx, STREAM_DATA (s), stream_get_endp (s)); - MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE); - MD5Final(digest, &ctx); - - /* Copy the digest to the packet. */ - stream_write (s, digest, RIP_AUTH_MD5_SIZE); +static void rip_auth_md5_set(struct stream *s, struct rip_interface *ri, + size_t doff, char *auth_str, int authlen) +{ + unsigned long len; + MD5_CTX ctx; + unsigned char digest[RIP_AUTH_MD5_SIZE]; + + /* Make it sure this interface is configured as MD5 + authentication. */ + assert((ri->auth_type == RIP_AUTH_MD5) + && (authlen == RIP_AUTH_MD5_SIZE)); + assert(doff > 0); + + /* Get packet length. */ + len = stream_get_endp(s); + + /* Check packet length. */ + if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE)) { + zlog_err( + "rip_auth_md5_set(): packet length %ld is less than minimum length.", + len); + return; + } + + /* Set the digest offset length in the header */ + stream_putw_at(s, doff, len); + + /* Set authentication data. */ + stream_putw(s, RIP_FAMILY_AUTH); + stream_putw(s, RIP_AUTH_DATA); + + /* Generate a digest for the RIP packet. */ + memset(&ctx, 0, sizeof(ctx)); + MD5Init(&ctx); + MD5Update(&ctx, STREAM_DATA(s), stream_get_endp(s)); + MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE); + MD5Final(digest, &ctx); + + /* Copy the digest to the packet. */ + stream_write(s, digest, RIP_AUTH_MD5_SIZE); } /* RIP routing information. */ -static void -rip_response_process (struct rip_packet *packet, int size, - struct sockaddr_in *from, struct connected *ifc) -{ - caddr_t lim; - struct rte *rte; - struct prefix_ipv4 ifaddr; - struct prefix_ipv4 ifaddrclass; - int subnetted; - - memset(&ifaddr, 0, sizeof(ifaddr)); - /* We don't know yet. */ - subnetted = -1; - - /* The Response must be ignored if it is not from the RIP - port. (RFC2453 - Sec. 3.9.2)*/ - if (from->sin_port != htons(RIP_PORT_DEFAULT)) - { - zlog_info ("response doesn't come from RIP port: %d", - from->sin_port); - rip_peer_bad_packet (from); - return; - } - - /* The datagram's IPv4 source address should be checked to see - whether the datagram is from a valid neighbor; the source of the - datagram must be on a directly connected network (RFC2453 - Sec. 3.9.2) */ - if (if_lookup_address((void *)&from->sin_addr, AF_INET, VRF_DEFAULT) == NULL) - { - zlog_info ("This datagram doesn't came from a valid neighbor: %s", - inet_ntoa (from->sin_addr)); - rip_peer_bad_packet (from); - return; - } - - /* It is also worth checking to see whether the response is from one - of the router's own addresses. */ - - ; /* Alredy done in rip_read () */ - - /* Update RIP peer. */ - rip_peer_update (from, packet->version); - - /* Set RTE pointer. */ - rte = packet->rte; - - for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++) - { - /* RIPv2 authentication check. */ - /* If the Address Family Identifier of the first (and only the - first) entry in the message is 0xFFFF, then the remainder of - the entry contains the authentication. */ - /* If the packet gets here it means authentication enabled */ - /* Check is done in rip_read(). So, just skipping it */ - if (packet->version == RIPv2 && - rte == packet->rte && - rte->family == htons(RIP_FAMILY_AUTH)) - continue; - - if (rte->family != htons(AF_INET)) - { - /* Address family check. RIP only supports AF_INET. */ - zlog_info ("Unsupported family %d from %s.", - ntohs (rte->family), inet_ntoa (from->sin_addr)); - continue; - } - - /* - is the destination address valid (e.g., unicast; not net 0 - or 127) */ - if (! rip_destination_check (rte->prefix)) - { - zlog_info ("Network is net 0 or net 127 or it is not unicast network"); - rip_peer_bad_route (from); - continue; - } - - /* Convert metric value to host byte order. */ - rte->metric = ntohl (rte->metric); - - /* - is the metric valid (i.e., between 1 and 16, inclusive) */ - if (! (rte->metric >= 1 && rte->metric <= 16)) - { - zlog_info ("Route's metric is not in the 1-16 range."); - rip_peer_bad_route (from); - continue; +static void rip_response_process(struct rip_packet *packet, int size, + struct sockaddr_in *from, + struct connected *ifc) +{ + caddr_t lim; + struct rte *rte; + struct prefix_ipv4 ifaddr; + struct prefix_ipv4 ifaddrclass; + int subnetted; + + memset(&ifaddr, 0, sizeof(ifaddr)); + /* We don't know yet. */ + subnetted = -1; + + /* The Response must be ignored if it is not from the RIP + port. (RFC2453 - Sec. 3.9.2)*/ + if (from->sin_port != htons(RIP_PORT_DEFAULT)) { + zlog_info("response doesn't come from RIP port: %d", + from->sin_port); + rip_peer_bad_packet(from); + return; } - /* RIPv1 does not have nexthop value. */ - if (packet->version == RIPv1 && rte->nexthop.s_addr != 0) - { - zlog_info ("RIPv1 packet with nexthop value %s", - inet_ntoa (rte->nexthop)); - rip_peer_bad_route (from); - continue; + /* The datagram's IPv4 source address should be checked to see + whether the datagram is from a valid neighbor; the source of the + datagram must be on a directly connected network (RFC2453 - Sec. + 3.9.2) */ + if (if_lookup_address((void *)&from->sin_addr, AF_INET, VRF_DEFAULT) + == NULL) { + zlog_info( + "This datagram doesn't came from a valid neighbor: %s", + inet_ntoa(from->sin_addr)); + rip_peer_bad_packet(from); + return; } - /* That is, if the provided information is ignored, a possibly - sub-optimal, but absolutely valid, route may be taken. If - the received Next Hop is not directly reachable, it should be - treated as 0.0.0.0. */ - if (packet->version == RIPv2 && rte->nexthop.s_addr != 0) - { - u_int32_t addrval; - - /* Multicast address check. */ - addrval = ntohl (rte->nexthop.s_addr); - if (IN_CLASSD (addrval)) - { - zlog_info ("Nexthop %s is multicast address, skip this rte", - inet_ntoa (rte->nexthop)); - continue; - } - - if (! if_lookup_address ((void *)&rte->nexthop, AF_INET, VRF_DEFAULT)) - { - struct route_node *rn; - struct rip_info *rinfo; - - rn = route_node_match_ipv4 (rip->table, &rte->nexthop); - - if (rn) - { - rinfo = rn->info; - - if (rinfo->type == ZEBRA_ROUTE_RIP - && rinfo->sub_type == RIP_ROUTE_RTE) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("Next hop %s is on RIP network. Set nexthop to the packet's originator", inet_ntoa (rte->nexthop)); - rte->nexthop = rinfo->from; - } - else - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop)); - rte->nexthop.s_addr = 0; - } - - route_unlock_node (rn); + /* It is also worth checking to see whether the response is from one + of the router's own addresses. */ + + ; /* Alredy done in rip_read () */ + + /* Update RIP peer. */ + rip_peer_update(from, packet->version); + + /* Set RTE pointer. */ + rte = packet->rte; + + for (lim = (caddr_t)packet + size; (caddr_t)rte < lim; rte++) { + /* RIPv2 authentication check. */ + /* If the Address Family Identifier of the first (and only the + first) entry in the message is 0xFFFF, then the remainder of + the entry contains the authentication. */ + /* If the packet gets here it means authentication enabled */ + /* Check is done in rip_read(). So, just skipping it */ + if (packet->version == RIPv2 && rte == packet->rte + && rte->family == htons(RIP_FAMILY_AUTH)) + continue; + + if (rte->family != htons(AF_INET)) { + /* Address family check. RIP only supports AF_INET. */ + zlog_info("Unsupported family %d from %s.", + ntohs(rte->family), + inet_ntoa(from->sin_addr)); + continue; } - else - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop)); - rte->nexthop.s_addr = 0; + + /* - is the destination address valid (e.g., unicast; not net 0 + or 127) */ + if (!rip_destination_check(rte->prefix)) { + zlog_info( + "Network is net 0 or net 127 or it is not unicast network"); + rip_peer_bad_route(from); + continue; } - } - } + /* Convert metric value to host byte order. */ + rte->metric = ntohl(rte->metric); - /* For RIPv1, there won't be a valid netmask. + /* - is the metric valid (i.e., between 1 and 16, inclusive) */ + if (!(rte->metric >= 1 && rte->metric <= 16)) { + zlog_info("Route's metric is not in the 1-16 range."); + rip_peer_bad_route(from); + continue; + } - This is a best guess at the masks. If everyone was using old - Ciscos before the 'ip subnet zero' option, it would be almost - right too :-) - - Cisco summarize ripv1 advertisments to the classful boundary - (/16 for class B's) except when the RIP packet does to inside - the classful network in question. */ + /* RIPv1 does not have nexthop value. */ + if (packet->version == RIPv1 && rte->nexthop.s_addr != 0) { + zlog_info("RIPv1 packet with nexthop value %s", + inet_ntoa(rte->nexthop)); + rip_peer_bad_route(from); + continue; + } - if ((packet->version == RIPv1 && rte->prefix.s_addr != 0) - || (packet->version == RIPv2 - && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0))) - { - u_int32_t destination; - - if (subnetted == -1) - { - memcpy (&ifaddr, ifc->address, sizeof (struct prefix_ipv4)); - memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4)); - apply_classful_mask_ipv4 (&ifaddrclass); - subnetted = 0; - if (ifaddr.prefixlen > ifaddrclass.prefixlen) - subnetted = 1; - } - - destination = ntohl (rte->prefix.s_addr); - - if (IN_CLASSA (destination)) - masklen2ip (8, &rte->mask); - else if (IN_CLASSB (destination)) - masklen2ip (16, &rte->mask); - else if (IN_CLASSC (destination)) - masklen2ip (24, &rte->mask); - - if (subnetted == 1) - masklen2ip (ifaddrclass.prefixlen, - (struct in_addr *) &destination); - if ((subnetted == 1) && ((rte->prefix.s_addr & destination) == - ifaddrclass.prefix.s_addr)) - { - masklen2ip (ifaddr.prefixlen, &rte->mask); - if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr) - masklen2ip (32, &rte->mask); - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("Subnetted route %s", inet_ntoa (rte->prefix)); - } - else - { - if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr) - continue; - } - - if (IS_RIP_DEBUG_EVENT) - { - zlog_debug ("Resultant route %s", inet_ntoa (rte->prefix)); - zlog_debug ("Resultant mask %s", inet_ntoa (rte->mask)); - } - } - - /* In case of RIPv2, if prefix in RTE is not netmask applied one - ignore the entry. */ - if ((packet->version == RIPv2) - && (rte->mask.s_addr != 0) - && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)) - { - zlog_warn ("RIPv2 address %s is not mask /%d applied one", - inet_ntoa (rte->prefix), ip_masklen (rte->mask)); - rip_peer_bad_route (from); - continue; - } + /* That is, if the provided information is ignored, a possibly + sub-optimal, but absolutely valid, route may be taken. If + the received Next Hop is not directly reachable, it should be + treated as 0.0.0.0. */ + if (packet->version == RIPv2 && rte->nexthop.s_addr != 0) { + u_int32_t addrval; + + /* Multicast address check. */ + addrval = ntohl(rte->nexthop.s_addr); + if (IN_CLASSD(addrval)) { + zlog_info( + "Nexthop %s is multicast address, skip this rte", + inet_ntoa(rte->nexthop)); + continue; + } + + if (!if_lookup_address((void *)&rte->nexthop, AF_INET, + VRF_DEFAULT)) { + struct route_node *rn; + struct rip_info *rinfo; + + rn = route_node_match_ipv4(rip->table, + &rte->nexthop); + + if (rn) { + rinfo = rn->info; + + if (rinfo->type == ZEBRA_ROUTE_RIP + && rinfo->sub_type + == RIP_ROUTE_RTE) { + if (IS_RIP_DEBUG_EVENT) + zlog_debug( + "Next hop %s is on RIP network. Set nexthop to the packet's originator", + inet_ntoa( + rte->nexthop)); + rte->nexthop = rinfo->from; + } else { + if (IS_RIP_DEBUG_EVENT) + zlog_debug( + "Next hop %s is not directly reachable. Treat it as 0.0.0.0", + inet_ntoa( + rte->nexthop)); + rte->nexthop.s_addr = 0; + } + + route_unlock_node(rn); + } else { + if (IS_RIP_DEBUG_EVENT) + zlog_debug( + "Next hop %s is not directly reachable. Treat it as 0.0.0.0", + inet_ntoa( + rte->nexthop)); + rte->nexthop.s_addr = 0; + } + } + } - /* Default route's netmask is ignored. */ - if (packet->version == RIPv2 - && (rte->prefix.s_addr == 0) - && (rte->mask.s_addr != 0)) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("Default route with non-zero netmask. Set zero to netmask"); - rte->mask.s_addr = 0; + /* For RIPv1, there won't be a valid netmask. + + This is a best guess at the masks. If everyone was using old + Ciscos before the 'ip subnet zero' option, it would be almost + right too :-) + + Cisco summarize ripv1 advertisments to the classful boundary + (/16 for class B's) except when the RIP packet does to inside + the classful network in question. */ + + if ((packet->version == RIPv1 && rte->prefix.s_addr != 0) + || (packet->version == RIPv2 + && (rte->prefix.s_addr != 0 + && rte->mask.s_addr == 0))) { + u_int32_t destination; + + if (subnetted == -1) { + memcpy(&ifaddr, ifc->address, + sizeof(struct prefix_ipv4)); + memcpy(&ifaddrclass, &ifaddr, + sizeof(struct prefix_ipv4)); + apply_classful_mask_ipv4(&ifaddrclass); + subnetted = 0; + if (ifaddr.prefixlen > ifaddrclass.prefixlen) + subnetted = 1; + } + + destination = ntohl(rte->prefix.s_addr); + + if (IN_CLASSA(destination)) + masklen2ip(8, &rte->mask); + else if (IN_CLASSB(destination)) + masklen2ip(16, &rte->mask); + else if (IN_CLASSC(destination)) + masklen2ip(24, &rte->mask); + + if (subnetted == 1) + masklen2ip(ifaddrclass.prefixlen, + (struct in_addr *)&destination); + if ((subnetted == 1) + && ((rte->prefix.s_addr & destination) + == ifaddrclass.prefix.s_addr)) { + masklen2ip(ifaddr.prefixlen, &rte->mask); + if ((rte->prefix.s_addr & rte->mask.s_addr) + != rte->prefix.s_addr) + masklen2ip(32, &rte->mask); + if (IS_RIP_DEBUG_EVENT) + zlog_debug("Subnetted route %s", + inet_ntoa(rte->prefix)); + } else { + if ((rte->prefix.s_addr & rte->mask.s_addr) + != rte->prefix.s_addr) + continue; + } + + if (IS_RIP_DEBUG_EVENT) { + zlog_debug("Resultant route %s", + inet_ntoa(rte->prefix)); + zlog_debug("Resultant mask %s", + inet_ntoa(rte->mask)); + } + } + + /* In case of RIPv2, if prefix in RTE is not netmask applied one + ignore the entry. */ + if ((packet->version == RIPv2) && (rte->mask.s_addr != 0) + && ((rte->prefix.s_addr & rte->mask.s_addr) + != rte->prefix.s_addr)) { + zlog_warn( + "RIPv2 address %s is not mask /%d applied one", + inet_ntoa(rte->prefix), ip_masklen(rte->mask)); + rip_peer_bad_route(from); + continue; + } + + /* Default route's netmask is ignored. */ + if (packet->version == RIPv2 && (rte->prefix.s_addr == 0) + && (rte->mask.s_addr != 0)) { + if (IS_RIP_DEBUG_EVENT) + zlog_debug( + "Default route with non-zero netmask. Set zero to netmask"); + rte->mask.s_addr = 0; + } + + /* Routing table updates. */ + rip_rte_process(rte, from, ifc->ifp); } - - /* Routing table updates. */ - rip_rte_process (rte, from, ifc->ifp); - } } /* Make socket for RIP protocol. */ -static int -rip_create_socket (void) -{ - int ret; - int sock; - struct sockaddr_in addr; - - memset (&addr, 0, sizeof (struct sockaddr_in)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; +static int rip_create_socket(void) +{ + int ret; + int sock; + struct sockaddr_in addr; + + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - addr.sin_len = sizeof (struct sockaddr_in); + addr.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - /* sending port must always be the RIP port */ - addr.sin_port = htons (RIP_PORT_DEFAULT); - - /* Make datagram socket. */ - sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (sock < 0) - { - zlog_err("Cannot create UDP socket: %s", safe_strerror(errno)); - exit (1); - } - - sockopt_broadcast (sock); - sockopt_reuseaddr (sock); - sockopt_reuseport (sock); - setsockopt_ipv4_multicast_loop (sock, 0); + /* sending port must always be the RIP port */ + addr.sin_port = htons(RIP_PORT_DEFAULT); + + /* Make datagram socket. */ + sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sock < 0) { + zlog_err("Cannot create UDP socket: %s", safe_strerror(errno)); + exit(1); + } + + sockopt_broadcast(sock); + sockopt_reuseaddr(sock); + sockopt_reuseport(sock); + setsockopt_ipv4_multicast_loop(sock, 0); #ifdef RIP_RECVMSG - setsockopt_pktinfo (sock); + setsockopt_pktinfo(sock); #endif /* RIP_RECVMSG */ #ifdef IPTOS_PREC_INTERNETCONTROL - setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL); + setsockopt_ipv4_tos(sock, IPTOS_PREC_INTERNETCONTROL); #endif - if (ripd_privs.change (ZPRIVS_RAISE)) - zlog_err ("rip_create_socket: could not raise privs"); - setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF); - if ( (ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr))) < 0) - - { - int save_errno = errno; - if (ripd_privs.change (ZPRIVS_LOWER)) - zlog_err ("rip_create_socket: could not lower privs"); - - zlog_err("%s: Can't bind socket %d to %s port %d: %s", __func__, - sock, inet_ntoa(addr.sin_addr), - (int) ntohs(addr.sin_port), - safe_strerror(save_errno)); - - close (sock); - return ret; - } - - if (ripd_privs.change (ZPRIVS_LOWER)) - zlog_err ("rip_create_socket: could not lower privs"); - - return sock; + if (ripd_privs.change(ZPRIVS_RAISE)) + zlog_err("rip_create_socket: could not raise privs"); + setsockopt_so_recvbuf(sock, RIP_UDP_RCV_BUF); + if ((ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr))) < 0) + + { + int save_errno = errno; + if (ripd_privs.change(ZPRIVS_LOWER)) + zlog_err("rip_create_socket: could not lower privs"); + + zlog_err("%s: Can't bind socket %d to %s port %d: %s", __func__, + sock, inet_ntoa(addr.sin_addr), + (int)ntohs(addr.sin_port), safe_strerror(save_errno)); + + close(sock); + return ret; + } + + if (ripd_privs.change(ZPRIVS_LOWER)) + zlog_err("rip_create_socket: could not lower privs"); + + return sock; } /* RIP packet send to destination address, on interface denoted by * by connected argument. NULL to argument denotes destination should be * should be RIP multicast group */ -static int -rip_send_packet (u_char * buf, int size, struct sockaddr_in *to, - struct connected *ifc) -{ - int ret; - struct sockaddr_in sin; - - assert (ifc != NULL); - - if (IS_RIP_DEBUG_PACKET) - { +static int rip_send_packet(u_char *buf, int size, struct sockaddr_in *to, + struct connected *ifc) +{ + int ret; + struct sockaddr_in sin; + + assert(ifc != NULL); + + if (IS_RIP_DEBUG_PACKET) { #define ADDRESS_SIZE 20 - char dst[ADDRESS_SIZE]; - dst[ADDRESS_SIZE - 1] = '\0'; - - if (to) - { - strncpy (dst, inet_ntoa(to->sin_addr), ADDRESS_SIZE - 1); - } - else - { - sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP); - strncpy (dst, inet_ntoa(sin.sin_addr), ADDRESS_SIZE - 1); - } + char dst[ADDRESS_SIZE]; + dst[ADDRESS_SIZE - 1] = '\0'; + + if (to) { + strncpy(dst, inet_ntoa(to->sin_addr), ADDRESS_SIZE - 1); + } else { + sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP); + strncpy(dst, inet_ntoa(sin.sin_addr), ADDRESS_SIZE - 1); + } #undef ADDRESS_SIZE - zlog_debug("rip_send_packet %s > %s (%s)", - inet_ntoa(ifc->address->u.prefix4), - dst, ifc->ifp->name); - } - - if ( CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY) ) - { - /* - * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured - * with multiple addresses on the same subnet: the first address - * on the subnet is configured "primary", and all subsequent addresses - * on that subnet are treated as "secondary" addresses. - * In order to avoid routing-table bloat on other rip listeners, - * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs. - * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY - * flag is set, we would end up sending a packet for a "secondary" - * source address on non-linux systems. - */ - if (IS_RIP_DEBUG_PACKET) - zlog_debug("duplicate dropped"); - return 0; - } - - /* Make destination address. */ - memset (&sin, 0, sizeof (struct sockaddr_in)); - sin.sin_family = AF_INET; + zlog_debug("rip_send_packet %s > %s (%s)", + inet_ntoa(ifc->address->u.prefix4), dst, + ifc->ifp->name); + } + + if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) { + /* + * ZEBRA_IFA_SECONDARY is set on linux when an interface is + * configured + * with multiple addresses on the same subnet: the first address + * on the subnet is configured "primary", and all subsequent + * addresses + * on that subnet are treated as "secondary" addresses. + * In order to avoid routing-table bloat on other rip listeners, + * we do not send out RIP packets with ZEBRA_IFA_SECONDARY + * source addrs. + * XXX Since Linux is the only system for which the + * ZEBRA_IFA_SECONDARY + * flag is set, we would end up sending a packet for a + * "secondary" + * source address on non-linux systems. + */ + if (IS_RIP_DEBUG_PACKET) + zlog_debug("duplicate dropped"); + return 0; + } + + /* Make destination address. */ + memset(&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin.sin_len = sizeof (struct sockaddr_in); + sin.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - /* When destination is specified, use it's port and address. */ - if (to) - { - sin.sin_port = to->sin_port; - sin.sin_addr = to->sin_addr; - } - else - { - sin.sin_port = htons (RIP_PORT_DEFAULT); - sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP); + /* When destination is specified, use it's port and address. */ + if (to) { + sin.sin_port = to->sin_port; + sin.sin_addr = to->sin_addr; + } else { + sin.sin_port = htons(RIP_PORT_DEFAULT); + sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP); - rip_interface_multicast_set (rip->sock, ifc); - } + rip_interface_multicast_set(rip->sock, ifc); + } - ret = sendto (rip->sock, buf, size, 0, (struct sockaddr *)&sin, - sizeof (struct sockaddr_in)); + ret = sendto(rip->sock, buf, size, 0, (struct sockaddr *)&sin, + sizeof(struct sockaddr_in)); - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("SEND to %s.%d", inet_ntoa(sin.sin_addr), - ntohs (sin.sin_port)); + if (IS_RIP_DEBUG_EVENT) + zlog_debug("SEND to %s.%d", inet_ntoa(sin.sin_addr), + ntohs(sin.sin_port)); - if (ret < 0) - zlog_warn ("can't send packet : %s", safe_strerror (errno)); + if (ret < 0) + zlog_warn("can't send packet : %s", safe_strerror(errno)); - return ret; + return ret; } /* Add redistributed route to RIP table. */ -void -rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p, - ifindex_t ifindex, struct in_addr *nexthop, - unsigned int metric, unsigned char distance, - route_tag_t tag) -{ - int ret; - struct route_node *rp = NULL; - struct rip_info *rinfo = NULL, newinfo; - struct list *list = NULL; +void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p, + ifindex_t ifindex, struct in_addr *nexthop, + unsigned int metric, unsigned char distance, + route_tag_t tag) +{ + int ret; + struct route_node *rp = NULL; + struct rip_info *rinfo = NULL, newinfo; + struct list *list = NULL; + + /* Redistribute route */ + ret = rip_destination_check(p->prefix); + if (!ret) + return; + + rp = route_node_get(rip->table, (struct prefix *)p); + + memset(&newinfo, 0, sizeof(struct rip_info)); + newinfo.type = type; + newinfo.sub_type = sub_type; + newinfo.ifindex = ifindex; + newinfo.metric = 1; + newinfo.external_metric = metric; + newinfo.distance = distance; + if (tag <= UINT16_MAX) /* RIP only supports 16 bit tags */ + newinfo.tag = tag; + newinfo.rp = rp; + if (nexthop) + newinfo.nexthop = *nexthop; + + if ((list = rp->info) != NULL && listcount(list) != 0) { + rinfo = listgetdata(listhead(list)); + + if (rinfo->type == ZEBRA_ROUTE_CONNECT + && rinfo->sub_type == RIP_ROUTE_INTERFACE + && rinfo->metric != RIP_METRIC_INFINITY) { + route_unlock_node(rp); + return; + } - /* Redistribute route */ - ret = rip_destination_check (p->prefix); - if (! ret) - return; - - rp = route_node_get (rip->table, (struct prefix *) p); - - memset (&newinfo, 0, sizeof (struct rip_info)); - newinfo.type = type; - newinfo.sub_type = sub_type; - newinfo.ifindex = ifindex; - newinfo.metric = 1; - newinfo.external_metric = metric; - newinfo.distance = distance; - if (tag <= UINT16_MAX) /* RIP only supports 16 bit tags */ - newinfo.tag = tag; - newinfo.rp = rp; - if (nexthop) - newinfo.nexthop = *nexthop; - - if ((list = rp->info) != NULL && listcount (list) != 0) - { - rinfo = listgetdata (listhead (list)); - - if (rinfo->type == ZEBRA_ROUTE_CONNECT - && rinfo->sub_type == RIP_ROUTE_INTERFACE - && rinfo->metric != RIP_METRIC_INFINITY) - { - route_unlock_node (rp); - return; + /* Manually configured RIP route check. */ + if (rinfo->type == ZEBRA_ROUTE_RIP + && ((rinfo->sub_type == RIP_ROUTE_STATIC) + || (rinfo->sub_type == RIP_ROUTE_DEFAULT))) { + if (type != ZEBRA_ROUTE_RIP + || ((sub_type != RIP_ROUTE_STATIC) + && (sub_type != RIP_ROUTE_DEFAULT))) { + route_unlock_node(rp); + return; + } + } + + rinfo = rip_ecmp_replace(&newinfo); + route_unlock_node(rp); + } else + rinfo = rip_ecmp_add(&newinfo); + + if (IS_RIP_DEBUG_EVENT) { + if (!nexthop) + zlog_debug( + "Redistribute new prefix %s/%d on the interface %s", + inet_ntoa(p->prefix), p->prefixlen, + ifindex2ifname(ifindex, VRF_DEFAULT)); + else + zlog_debug( + "Redistribute new prefix %s/%d with nexthop %s on the interface %s", + inet_ntoa(p->prefix), p->prefixlen, + inet_ntoa(rinfo->nexthop), + ifindex2ifname(ifindex, VRF_DEFAULT)); } - /* Manually configured RIP route check. */ - if (rinfo->type == ZEBRA_ROUTE_RIP - && ((rinfo->sub_type == RIP_ROUTE_STATIC) || - (rinfo->sub_type == RIP_ROUTE_DEFAULT)) ) - { - if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) && - (sub_type != RIP_ROUTE_DEFAULT))) - { - route_unlock_node (rp); - return; - } - } - - rinfo = rip_ecmp_replace (&newinfo); - route_unlock_node (rp); - } - else - rinfo = rip_ecmp_add (&newinfo); - - if (IS_RIP_DEBUG_EVENT) { - if (!nexthop) - zlog_debug ("Redistribute new prefix %s/%d on the interface %s", - inet_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(ifindex, VRF_DEFAULT)); - else - zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s", - inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop), - ifindex2ifname(ifindex, VRF_DEFAULT)); - } - - rip_event (RIP_TRIGGERED_UPDATE, 0); + rip_event(RIP_TRIGGERED_UPDATE, 0); } /* Delete redistributed route from RIP table. */ -void -rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p, - ifindex_t ifindex) -{ - int ret; - struct route_node *rp; - struct rip_info *rinfo; - - ret = rip_destination_check (p->prefix); - if (! ret) - return; - - rp = route_node_lookup (rip->table, (struct prefix *) p); - if (rp) - { - struct list *list = rp->info; - - if (list != NULL && listcount (list) != 0) - { - rinfo = listgetdata (listhead (list)); - if (rinfo != NULL - && rinfo->type == type - && rinfo->sub_type == sub_type - && rinfo->ifindex == ifindex) - { - /* Perform poisoned reverse. */ - rinfo->metric = RIP_METRIC_INFINITY; - RIP_TIMER_ON (rinfo->t_garbage_collect, - rip_garbage_collect, rip->garbage_time); - RIP_TIMER_OFF (rinfo->t_timeout); - rinfo->flags |= RIP_RTF_CHANGED; - - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("Poisone %s/%d on the interface %s with an " - "infinity metric [delete]", - inet_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(ifindex, VRF_DEFAULT)); - - rip_event (RIP_TRIGGERED_UPDATE, 0); - } - } - route_unlock_node (rp); - } +void rip_redistribute_delete(int type, int sub_type, struct prefix_ipv4 *p, + ifindex_t ifindex) +{ + int ret; + struct route_node *rp; + struct rip_info *rinfo; + + ret = rip_destination_check(p->prefix); + if (!ret) + return; + + rp = route_node_lookup(rip->table, (struct prefix *)p); + if (rp) { + struct list *list = rp->info; + + if (list != NULL && listcount(list) != 0) { + rinfo = listgetdata(listhead(list)); + if (rinfo != NULL && rinfo->type == type + && rinfo->sub_type == sub_type + && rinfo->ifindex == ifindex) { + /* Perform poisoned reverse. */ + rinfo->metric = RIP_METRIC_INFINITY; + RIP_TIMER_ON(rinfo->t_garbage_collect, + rip_garbage_collect, + rip->garbage_time); + RIP_TIMER_OFF(rinfo->t_timeout); + rinfo->flags |= RIP_RTF_CHANGED; + + if (IS_RIP_DEBUG_EVENT) + zlog_debug( + "Poisone %s/%d on the interface %s with an " + "infinity metric [delete]", + inet_ntoa(p->prefix), + p->prefixlen, + ifindex2ifname(ifindex, + VRF_DEFAULT)); + + rip_event(RIP_TRIGGERED_UPDATE, 0); + } + } + route_unlock_node(rp); + } } /* Response to request called from rip_read ().*/ -static void -rip_request_process (struct rip_packet *packet, int size, - struct sockaddr_in *from, struct connected *ifc) -{ - caddr_t lim; - struct rte *rte; - struct prefix_ipv4 p; - struct route_node *rp; - struct rip_info *rinfo; - struct rip_interface *ri; - - /* Does not reponse to the requests on the loopback interfaces */ - if (if_is_loopback (ifc->ifp)) - return; - - /* Check RIP process is enabled on this interface. */ - ri = ifc->ifp->info; - if (! ri->running) - return; - - /* When passive interface is specified, suppress responses */ - if (ri->passive) - return; - - /* RIP peer update. */ - rip_peer_update (from, packet->version); - - lim = ((caddr_t) packet) + size; - rte = packet->rte; - - /* The Request is processed entry by entry. If there are no - entries, no response is given. */ - if (lim == (caddr_t) rte) - return; - - /* There is one special case. If there is exactly one entry in the - request, and it has an address family identifier of zero and a - metric of infinity (i.e., 16), then this is a request to send the - entire routing table. */ - if (lim == ((caddr_t) (rte + 1)) && - ntohs (rte->family) == 0 && - ntohl (rte->metric) == RIP_METRIC_INFINITY) - { - /* All route with split horizon */ - rip_output_process (ifc, from, rip_all_route, packet->version); - } - else - { - if (ntohs (rte->family) != AF_INET) - return; +static void rip_request_process(struct rip_packet *packet, int size, + struct sockaddr_in *from, struct connected *ifc) +{ + caddr_t lim; + struct rte *rte; + struct prefix_ipv4 p; + struct route_node *rp; + struct rip_info *rinfo; + struct rip_interface *ri; + + /* Does not reponse to the requests on the loopback interfaces */ + if (if_is_loopback(ifc->ifp)) + return; + + /* Check RIP process is enabled on this interface. */ + ri = ifc->ifp->info; + if (!ri->running) + return; + + /* When passive interface is specified, suppress responses */ + if (ri->passive) + return; + + /* RIP peer update. */ + rip_peer_update(from, packet->version); + + lim = ((caddr_t)packet) + size; + rte = packet->rte; + + /* The Request is processed entry by entry. If there are no + entries, no response is given. */ + if (lim == (caddr_t)rte) + return; + + /* There is one special case. If there is exactly one entry in the + request, and it has an address family identifier of zero and a + metric of infinity (i.e., 16), then this is a request to send the + entire routing table. */ + if (lim == ((caddr_t)(rte + 1)) && ntohs(rte->family) == 0 + && ntohl(rte->metric) == RIP_METRIC_INFINITY) { + /* All route with split horizon */ + rip_output_process(ifc, from, rip_all_route, packet->version); + } else { + if (ntohs(rte->family) != AF_INET) + return; + + /* Examine the list of RTEs in the Request one by one. For each + entry, look up the destination in the router's routing + database and, if there is a route, put that route's metric in + the metric field of the RTE. If there is no explicit route + to the specified destination, put infinity in the metric + field. Once all the entries have been filled in, change the + command from Request to Response and send the datagram back + to the requestor. */ + p.family = AF_INET; + + for (; ((caddr_t)rte) < lim; rte++) { + p.prefix = rte->prefix; + p.prefixlen = ip_masklen(rte->mask); + apply_mask_ipv4(&p); + + rp = route_node_lookup(rip->table, (struct prefix *)&p); + if (rp) { + rinfo = listgetdata( + listhead((struct list *)rp->info)); + rte->metric = htonl(rinfo->metric); + route_unlock_node(rp); + } else + rte->metric = htonl(RIP_METRIC_INFINITY); + } + packet->command = RIP_RESPONSE; - /* Examine the list of RTEs in the Request one by one. For each - entry, look up the destination in the router's routing - database and, if there is a route, put that route's metric in - the metric field of the RTE. If there is no explicit route - to the specified destination, put infinity in the metric - field. Once all the entries have been filled in, change the - command from Request to Response and send the datagram back - to the requestor. */ - p.family = AF_INET; - - for (; ((caddr_t) rte) < lim; rte++) - { - p.prefix = rte->prefix; - p.prefixlen = ip_masklen (rte->mask); - apply_mask_ipv4 (&p); - - rp = route_node_lookup (rip->table, (struct prefix *) &p); - if (rp) - { - rinfo = listgetdata (listhead ((struct list *)rp->info)); - rte->metric = htonl (rinfo->metric); - route_unlock_node (rp); - } - else - rte->metric = htonl (RIP_METRIC_INFINITY); - } - packet->command = RIP_RESPONSE; - - rip_send_packet ((u_char *)packet, size, from, ifc); - } - rip_global_queries++; + rip_send_packet((u_char *)packet, size, from, ifc); + } + rip_global_queries++; } #if RIP_RECVMSG /* Set IPv6 packet info to the socket. */ -static int -setsockopt_pktinfo (int sock) +static int setsockopt_pktinfo(int sock) { - int ret; - int val = 1; - - ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val)); - if (ret < 0) - zlog_warn ("Can't setsockopt IP_PKTINFO : %s", safe_strerror (errno)); - return ret; + int ret; + int val = 1; + + ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val)); + if (ret < 0) + zlog_warn("Can't setsockopt IP_PKTINFO : %s", + safe_strerror(errno)); + return ret; } /* Read RIP packet by recvmsg function. */ -int -rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from, - ifindex_t *ifindex) -{ - int ret; - struct msghdr msg; - struct iovec iov; - struct cmsghdr *ptr; - char adata[1024]; - - msg.msg_name = (void *) from; - msg.msg_namelen = sizeof (struct sockaddr_in); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = (void *) adata; - msg.msg_controllen = sizeof adata; - iov.iov_base = buf; - iov.iov_len = size; - - ret = recvmsg (sock, &msg, 0); - if (ret < 0) - return ret; - - for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr)) - if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO) - { - struct in_pktinfo *pktinfo; - int i; +int rip_recvmsg(int sock, u_char *buf, int size, struct sockaddr_in *from, + ifindex_t *ifindex) +{ + int ret; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *ptr; + char adata[1024]; + + msg.msg_name = (void *)from; + msg.msg_namelen = sizeof(struct sockaddr_in); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = (void *)adata; + msg.msg_controllen = sizeof adata; + iov.iov_base = buf; + iov.iov_len = size; + + ret = recvmsg(sock, &msg, 0); + if (ret < 0) + return ret; - pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr); - i = pktinfo->ipi_ifindex; - } - return ret; + for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; + ptr = CMSG_NXTHDR(&msg, ptr)) + if (ptr->cmsg_level == IPPROTO_IP + && ptr->cmsg_type == IP_PKTINFO) { + struct in_pktinfo *pktinfo; + int i; + + pktinfo = (struct in_pktinfo *)CMSG_DATA(ptr); + i = pktinfo->ipi_ifindex; + } + return ret; } /* RIP packet read function. */ -int -rip_read_new (struct thread *t) -{ - int ret; - int sock; - char buf[RIP_PACKET_MAXSIZ]; - struct sockaddr_in from; - ifindex_t ifindex; - - /* Fetch socket then register myself. */ - sock = THREAD_FD (t); - rip_event (RIP_READ, sock); - - /* Read RIP packet. */ - ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex); - if (ret < 0) - { - zlog_warn ("Can't read RIP packet: %s", safe_strerror (errno)); - return ret; - } - - return ret; +int rip_read_new(struct thread *t) +{ + int ret; + int sock; + char buf[RIP_PACKET_MAXSIZ]; + struct sockaddr_in from; + ifindex_t ifindex; + + /* Fetch socket then register myself. */ + sock = THREAD_FD(t); + rip_event(RIP_READ, sock); + + /* Read RIP packet. */ + ret = rip_recvmsg(sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex); + if (ret < 0) { + zlog_warn("Can't read RIP packet: %s", safe_strerror(errno)); + return ret; + } + + return ret; } #endif /* RIP_RECVMSG */ /* First entry point of RIP packet. */ -static int -rip_read (struct thread *t) -{ - int sock; - int ret; - int rtenum; - union rip_buf rip_buf; - struct rip_packet *packet; - struct sockaddr_in from; - int len; - int vrecv; - socklen_t fromlen; - struct interface *ifp = NULL; - struct connected *ifc; - struct rip_interface *ri; - struct prefix p; - - /* Fetch socket then register myself. */ - sock = THREAD_FD (t); - rip->t_read = NULL; - - /* Add myself to tne next event */ - rip_event (RIP_READ, sock); - - /* RIPd manages only IPv4. */ - memset (&from, 0, sizeof (struct sockaddr_in)); - fromlen = sizeof (struct sockaddr_in); - - len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0, - (struct sockaddr *) &from, &fromlen); - if (len < 0) - { - zlog_info ("recvfrom failed: %s", safe_strerror (errno)); - return len; - } - - /* Check is this packet comming from myself? */ - if (if_check_address (from.sin_addr)) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("ignore packet comes from myself"); - return -1; - } - - /* Which interface is this packet comes from. */ - ifc = if_lookup_address ((void *)&from.sin_addr, AF_INET, VRF_DEFAULT); - if (ifc) - ifp = ifc->ifp; - - /* RIP packet received */ - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("RECV packet from %s port %d on %s", - inet_ntoa (from.sin_addr), ntohs (from.sin_port), - ifp ? ifp->name : "unknown"); - - /* If this packet come from unknown interface, ignore it. */ - if (ifp == NULL) - { - zlog_info ("rip_read: cannot find interface for packet from %s port %d", - inet_ntoa(from.sin_addr), ntohs (from.sin_port)); - return -1; - } - - p.family = AF_INET; - p.u.prefix4 = from.sin_addr; - p.prefixlen = IPV4_MAX_BITLEN; - - ifc = connected_lookup_prefix (ifp, &p); - - if (ifc == NULL) - { - zlog_info ("rip_read: cannot find connected address for packet from %s " - "port %d on interface %s", - inet_ntoa(from.sin_addr), ntohs (from.sin_port), ifp->name); - return -1; - } - - /* Packet length check. */ - if (len < RIP_PACKET_MINSIZ) - { - zlog_warn ("packet size %d is smaller than minimum size %d", - len, RIP_PACKET_MINSIZ); - rip_peer_bad_packet (&from); - return len; - } - if (len > RIP_PACKET_MAXSIZ) - { - zlog_warn ("packet size %d is larger than max size %d", - len, RIP_PACKET_MAXSIZ); - rip_peer_bad_packet (&from); - return len; - } - - /* Packet alignment check. */ - if ((len - RIP_PACKET_MINSIZ) % 20) - { - zlog_warn ("packet size %d is wrong for RIP packet alignment", len); - rip_peer_bad_packet (&from); - return len; - } - - /* Set RTE number. */ - rtenum = ((len - RIP_PACKET_MINSIZ) / 20); - - /* For easy to handle. */ - packet = &rip_buf.rip_packet; - - /* RIP version check. */ - if (packet->version == 0) - { - zlog_info ("version 0 with command %d received.", packet->command); - rip_peer_bad_packet (&from); - return -1; - } - - /* Dump RIP packet. */ - if (IS_RIP_DEBUG_RECV) - rip_packet_dump (packet, len, "RECV"); - - /* RIP version adjust. This code should rethink now. RFC1058 says - that "Version 1 implementations are to ignore this extra data and - process only the fields specified in this document.". So RIPv3 - packet should be treated as RIPv1 ignoring must be zero field. */ - if (packet->version > RIPv2) - packet->version = RIPv2; - - /* Is RIP running or is this RIP neighbor ?*/ - ri = ifp->info; - if (! ri->running && ! rip_neighbor_lookup (&from)) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("RIP is not enabled on interface %s.", ifp->name); - rip_peer_bad_packet (&from); - return -1; - } - - /* RIP Version check. RFC2453, 4.6 and 5.1 */ - vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ? - rip->version_recv : ri->ri_receive); - if (vrecv == RI_RIP_VERSION_NONE || - ((packet->version == RIPv1) && !(vrecv & RIPv1)) || - ((packet->version == RIPv2) && !(vrecv & RIPv2))) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug (" packet's v%d doesn't fit to if version spec", - packet->version); - rip_peer_bad_packet (&from); - return -1; - } - - /* RFC2453 5.2 If the router is not configured to authenticate RIP-2 - messages, then RIP-1 and unauthenticated RIP-2 messages will be - accepted; authenticated RIP-2 messages shall be discarded. */ - if ((ri->auth_type == RIP_NO_AUTH) - && rtenum - && (packet->version == RIPv2) - && (packet->rte->family == htons(RIP_FAMILY_AUTH))) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("packet RIPv%d is dropped because authentication disabled", - packet->version); - rip_peer_bad_packet (&from); - return -1; - } - - /* RFC: - If the router is configured to authenticate RIP-2 messages, then - RIP-1 messages and RIP-2 messages which pass authentication - testing shall be accepted; unauthenticated and failed - authentication RIP-2 messages shall be discarded. For maximum - security, RIP-1 messages should be ignored when authentication is - in use (see section 4.1); otherwise, the routing information from - authenticated messages will be propagated by RIP-1 routers in an - unauthenticated manner. - */ - /* We make an exception for RIPv1 REQUEST packets, to which we'll - * always reply regardless of authentication settings, because: - * - * - if there other authorised routers on-link, the REQUESTor can - * passively obtain the routing updates anyway - * - if there are no other authorised routers on-link, RIP can - * easily be disabled for the link to prevent giving out information - * on state of this routers RIP routing table.. - * - * I.e. if RIPv1 has any place anymore these days, it's as a very - * simple way to distribute routing information (e.g. to embedded - * hosts / appliances) and the ability to give out RIPv1 - * routing-information freely, while still requiring RIPv2 - * authentication for any RESPONSEs might be vaguely useful. - */ - if (ri->auth_type != RIP_NO_AUTH - && packet->version == RIPv1) - { - /* Discard RIPv1 messages other than REQUESTs */ - if (packet->command != RIP_REQUEST) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("RIPv1" " dropped because authentication enabled"); - rip_peer_bad_packet (&from); - return -1; - } - } - else if (ri->auth_type != RIP_NO_AUTH) - { - const char *auth_desc; - - if (rtenum == 0) - { - /* There definitely is no authentication in the packet. */ - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("RIPv2 authentication failed: no auth RTE in packet"); - rip_peer_bad_packet (&from); - return -1; - } - - /* First RTE must be an Authentication Family RTE */ - if (packet->rte->family != htons(RIP_FAMILY_AUTH)) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("RIPv2" " dropped because authentication enabled"); - rip_peer_bad_packet (&from); - return -1; - } - - /* Check RIPv2 authentication. */ - switch (ntohs(packet->rte->tag)) - { - case RIP_AUTH_SIMPLE_PASSWORD: - auth_desc = "simple"; - ret = rip_auth_simple_password (packet->rte, &from, ifp); - break; - - case RIP_AUTH_MD5: - auth_desc = "MD5"; - ret = rip_auth_md5 (packet, &from, len, ifp); - /* Reset RIP packet length to trim MD5 data. */ - len = ret; - break; - - default: - ret = 0; - auth_desc = "unknown type"; - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("RIPv2 Unknown authentication type %d", - ntohs (packet->rte->tag)); - } - - if (ret) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("RIPv2 %s authentication success", auth_desc); - } - else - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("RIPv2 %s authentication failure", auth_desc); - rip_peer_bad_packet (&from); - return -1; - } - } - - /* Process each command. */ - switch (packet->command) - { - case RIP_RESPONSE: - rip_response_process (packet, len, &from, ifc); - break; - case RIP_REQUEST: - case RIP_POLL: - rip_request_process (packet, len, &from, ifc); - break; - case RIP_TRACEON: - case RIP_TRACEOFF: - zlog_info ("Obsolete command %s received, please sent it to routed", - lookup_msg (rip_msg, packet->command, NULL)); - rip_peer_bad_packet (&from); - break; - case RIP_POLL_ENTRY: - zlog_info ("Obsolete command %s received", - lookup_msg (rip_msg, packet->command, NULL)); - rip_peer_bad_packet (&from); - break; - default: - zlog_info ("Unknown RIP command %d received", packet->command); - rip_peer_bad_packet (&from); - break; - } - - return len; +static int rip_read(struct thread *t) +{ + int sock; + int ret; + int rtenum; + union rip_buf rip_buf; + struct rip_packet *packet; + struct sockaddr_in from; + int len; + int vrecv; + socklen_t fromlen; + struct interface *ifp = NULL; + struct connected *ifc; + struct rip_interface *ri; + struct prefix p; + + /* Fetch socket then register myself. */ + sock = THREAD_FD(t); + rip->t_read = NULL; + + /* Add myself to tne next event */ + rip_event(RIP_READ, sock); + + /* RIPd manages only IPv4. */ + memset(&from, 0, sizeof(struct sockaddr_in)); + fromlen = sizeof(struct sockaddr_in); + + len = recvfrom(sock, (char *)&rip_buf.buf, sizeof(rip_buf.buf), 0, + (struct sockaddr *)&from, &fromlen); + if (len < 0) { + zlog_info("recvfrom failed: %s", safe_strerror(errno)); + return len; + } + + /* Check is this packet comming from myself? */ + if (if_check_address(from.sin_addr)) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug("ignore packet comes from myself"); + return -1; + } + + /* Which interface is this packet comes from. */ + ifc = if_lookup_address((void *)&from.sin_addr, AF_INET, VRF_DEFAULT); + if (ifc) + ifp = ifc->ifp; + + /* RIP packet received */ + if (IS_RIP_DEBUG_EVENT) + zlog_debug("RECV packet from %s port %d on %s", + inet_ntoa(from.sin_addr), ntohs(from.sin_port), + ifp ? ifp->name : "unknown"); + + /* If this packet come from unknown interface, ignore it. */ + if (ifp == NULL) { + zlog_info( + "rip_read: cannot find interface for packet from %s port %d", + inet_ntoa(from.sin_addr), ntohs(from.sin_port)); + return -1; + } + + p.family = AF_INET; + p.u.prefix4 = from.sin_addr; + p.prefixlen = IPV4_MAX_BITLEN; + + ifc = connected_lookup_prefix(ifp, &p); + + if (ifc == NULL) { + zlog_info( + "rip_read: cannot find connected address for packet from %s " + "port %d on interface %s", + inet_ntoa(from.sin_addr), ntohs(from.sin_port), + ifp->name); + return -1; + } + + /* Packet length check. */ + if (len < RIP_PACKET_MINSIZ) { + zlog_warn("packet size %d is smaller than minimum size %d", len, + RIP_PACKET_MINSIZ); + rip_peer_bad_packet(&from); + return len; + } + if (len > RIP_PACKET_MAXSIZ) { + zlog_warn("packet size %d is larger than max size %d", len, + RIP_PACKET_MAXSIZ); + rip_peer_bad_packet(&from); + return len; + } + + /* Packet alignment check. */ + if ((len - RIP_PACKET_MINSIZ) % 20) { + zlog_warn("packet size %d is wrong for RIP packet alignment", + len); + rip_peer_bad_packet(&from); + return len; + } + + /* Set RTE number. */ + rtenum = ((len - RIP_PACKET_MINSIZ) / 20); + + /* For easy to handle. */ + packet = &rip_buf.rip_packet; + + /* RIP version check. */ + if (packet->version == 0) { + zlog_info("version 0 with command %d received.", + packet->command); + rip_peer_bad_packet(&from); + return -1; + } + + /* Dump RIP packet. */ + if (IS_RIP_DEBUG_RECV) + rip_packet_dump(packet, len, "RECV"); + + /* RIP version adjust. This code should rethink now. RFC1058 says + that "Version 1 implementations are to ignore this extra data and + process only the fields specified in this document.". So RIPv3 + packet should be treated as RIPv1 ignoring must be zero field. */ + if (packet->version > RIPv2) + packet->version = RIPv2; + + /* Is RIP running or is this RIP neighbor ?*/ + ri = ifp->info; + if (!ri->running && !rip_neighbor_lookup(&from)) { + if (IS_RIP_DEBUG_EVENT) + zlog_debug("RIP is not enabled on interface %s.", + ifp->name); + rip_peer_bad_packet(&from); + return -1; + } + + /* RIP Version check. RFC2453, 4.6 and 5.1 */ + vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv + : ri->ri_receive); + if (vrecv == RI_RIP_VERSION_NONE + || ((packet->version == RIPv1) && !(vrecv & RIPv1)) + || ((packet->version == RIPv2) && !(vrecv & RIPv2))) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + " packet's v%d doesn't fit to if version spec", + packet->version); + rip_peer_bad_packet(&from); + return -1; + } + + /* RFC2453 5.2 If the router is not configured to authenticate RIP-2 + messages, then RIP-1 and unauthenticated RIP-2 messages will be + accepted; authenticated RIP-2 messages shall be discarded. */ + if ((ri->auth_type == RIP_NO_AUTH) && rtenum + && (packet->version == RIPv2) + && (packet->rte->family == htons(RIP_FAMILY_AUTH))) { + if (IS_RIP_DEBUG_EVENT) + zlog_debug( + "packet RIPv%d is dropped because authentication disabled", + packet->version); + rip_peer_bad_packet(&from); + return -1; + } + + /* RFC: + If the router is configured to authenticate RIP-2 messages, then + RIP-1 messages and RIP-2 messages which pass authentication + testing shall be accepted; unauthenticated and failed + authentication RIP-2 messages shall be discarded. For maximum + security, RIP-1 messages should be ignored when authentication is + in use (see section 4.1); otherwise, the routing information from + authenticated messages will be propagated by RIP-1 routers in an + unauthenticated manner. + */ + /* We make an exception for RIPv1 REQUEST packets, to which we'll + * always reply regardless of authentication settings, because: + * + * - if there other authorised routers on-link, the REQUESTor can + * passively obtain the routing updates anyway + * - if there are no other authorised routers on-link, RIP can + * easily be disabled for the link to prevent giving out information + * on state of this routers RIP routing table.. + * + * I.e. if RIPv1 has any place anymore these days, it's as a very + * simple way to distribute routing information (e.g. to embedded + * hosts / appliances) and the ability to give out RIPv1 + * routing-information freely, while still requiring RIPv2 + * authentication for any RESPONSEs might be vaguely useful. + */ + if (ri->auth_type != RIP_NO_AUTH && packet->version == RIPv1) { + /* Discard RIPv1 messages other than REQUESTs */ + if (packet->command != RIP_REQUEST) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "RIPv1" + " dropped because authentication enabled"); + rip_peer_bad_packet(&from); + return -1; + } + } else if (ri->auth_type != RIP_NO_AUTH) { + const char *auth_desc; + + if (rtenum == 0) { + /* There definitely is no authentication in the packet. + */ + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "RIPv2 authentication failed: no auth RTE in packet"); + rip_peer_bad_packet(&from); + return -1; + } + + /* First RTE must be an Authentication Family RTE */ + if (packet->rte->family != htons(RIP_FAMILY_AUTH)) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "RIPv2" + " dropped because authentication enabled"); + rip_peer_bad_packet(&from); + return -1; + } + + /* Check RIPv2 authentication. */ + switch (ntohs(packet->rte->tag)) { + case RIP_AUTH_SIMPLE_PASSWORD: + auth_desc = "simple"; + ret = rip_auth_simple_password(packet->rte, &from, ifp); + break; + + case RIP_AUTH_MD5: + auth_desc = "MD5"; + ret = rip_auth_md5(packet, &from, len, ifp); + /* Reset RIP packet length to trim MD5 data. */ + len = ret; + break; + + default: + ret = 0; + auth_desc = "unknown type"; + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "RIPv2 Unknown authentication type %d", + ntohs(packet->rte->tag)); + } + + if (ret) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug("RIPv2 %s authentication success", + auth_desc); + } else { + if (IS_RIP_DEBUG_PACKET) + zlog_debug("RIPv2 %s authentication failure", + auth_desc); + rip_peer_bad_packet(&from); + return -1; + } + } + + /* Process each command. */ + switch (packet->command) { + case RIP_RESPONSE: + rip_response_process(packet, len, &from, ifc); + break; + case RIP_REQUEST: + case RIP_POLL: + rip_request_process(packet, len, &from, ifc); + break; + case RIP_TRACEON: + case RIP_TRACEOFF: + zlog_info( + "Obsolete command %s received, please sent it to routed", + lookup_msg(rip_msg, packet->command, NULL)); + rip_peer_bad_packet(&from); + break; + case RIP_POLL_ENTRY: + zlog_info("Obsolete command %s received", + lookup_msg(rip_msg, packet->command, NULL)); + rip_peer_bad_packet(&from); + break; + default: + zlog_info("Unknown RIP command %d received", packet->command); + rip_peer_bad_packet(&from); + break; + } + + return len; } /* Write routing table entry to the stream and return next index of the routing table entry in the stream. */ -static int -rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p, - u_char version, struct rip_info *rinfo) -{ - struct in_addr mask; - - /* Write routing table entry. */ - if (version == RIPv1) - { - stream_putw (s, AF_INET); - stream_putw (s, 0); - stream_put_ipv4 (s, p->prefix.s_addr); - stream_put_ipv4 (s, 0); - stream_put_ipv4 (s, 0); - stream_putl (s, rinfo->metric_out); - } - else - { - masklen2ip (p->prefixlen, &mask); - - stream_putw (s, AF_INET); - stream_putw (s, rinfo->tag_out); - stream_put_ipv4 (s, p->prefix.s_addr); - stream_put_ipv4 (s, mask.s_addr); - stream_put_ipv4 (s, rinfo->nexthop_out.s_addr); - stream_putl (s, rinfo->metric_out); - } - - return ++num; +static int rip_write_rte(int num, struct stream *s, struct prefix_ipv4 *p, + u_char version, struct rip_info *rinfo) +{ + struct in_addr mask; + + /* Write routing table entry. */ + if (version == RIPv1) { + stream_putw(s, AF_INET); + stream_putw(s, 0); + stream_put_ipv4(s, p->prefix.s_addr); + stream_put_ipv4(s, 0); + stream_put_ipv4(s, 0); + stream_putl(s, rinfo->metric_out); + } else { + masklen2ip(p->prefixlen, &mask); + + stream_putw(s, AF_INET); + stream_putw(s, rinfo->tag_out); + stream_put_ipv4(s, p->prefix.s_addr); + stream_put_ipv4(s, mask.s_addr); + stream_put_ipv4(s, rinfo->nexthop_out.s_addr); + stream_putl(s, rinfo->metric_out); + } + + return ++num; } /* Send update to the ifp or spcified neighbor. */ -void -rip_output_process (struct connected *ifc, struct sockaddr_in *to, - int route_type, u_char version) -{ - int ret; - struct stream *s; - struct route_node *rp; - struct rip_info *rinfo; - struct rip_interface *ri; - struct prefix_ipv4 *p; - struct prefix_ipv4 classfull; - struct prefix_ipv4 ifaddrclass; - struct key *key = NULL; - /* this might need to made dynamic if RIP ever supported auth methods - with larger key string sizes */ - char auth_str[RIP_AUTH_SIMPLE_SIZE]; - size_t doff = 0; /* offset of digest offset field */ - int num = 0; - int rtemax; - int subnetted = 0; - struct list *list = NULL; - struct listnode *listnode = NULL; +void rip_output_process(struct connected *ifc, struct sockaddr_in *to, + int route_type, u_char version) +{ + int ret; + struct stream *s; + struct route_node *rp; + struct rip_info *rinfo; + struct rip_interface *ri; + struct prefix_ipv4 *p; + struct prefix_ipv4 classfull; + struct prefix_ipv4 ifaddrclass; + struct key *key = NULL; + /* this might need to made dynamic if RIP ever supported auth methods + with larger key string sizes */ + char auth_str[RIP_AUTH_SIMPLE_SIZE]; + size_t doff = 0; /* offset of digest offset field */ + int num = 0; + int rtemax; + int subnetted = 0; + struct list *list = NULL; + struct listnode *listnode = NULL; + + /* Logging output event. */ + if (IS_RIP_DEBUG_EVENT) { + if (to) + zlog_debug("update routes to neighbor %s", + inet_ntoa(to->sin_addr)); + else + zlog_debug("update routes on interface %s ifindex %d", + ifc->ifp->name, ifc->ifp->ifindex); + } - /* Logging output event. */ - if (IS_RIP_DEBUG_EVENT) - { - if (to) - zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr)); - else - zlog_debug ("update routes on interface %s ifindex %d", - ifc->ifp->name, ifc->ifp->ifindex); - } - - /* Set output stream. */ - s = rip->obuf; - - /* Reset stream and RTE counter. */ - stream_reset (s); - rtemax = RIP_MAX_RTE; - - /* Get RIP interface. */ - ri = ifc->ifp->info; - - /* If output interface is in simple password authentication mode, we - need space for authentication data. */ - if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD) - rtemax -= 1; - - /* If output interface is in MD5 authentication mode, we need space - for authentication header and data. */ - if (ri->auth_type == RIP_AUTH_MD5) - rtemax -= 2; - - /* If output interface is in simple password authentication mode - and string or keychain is specified we need space for auth. data */ - if (ri->auth_type != RIP_NO_AUTH) - { - if (ri->key_chain) - { - struct keychain *keychain; - - keychain = keychain_lookup (ri->key_chain); - if (keychain) - key = key_lookup_for_send (keychain); - } - /* to be passed to auth functions later */ - rip_auth_prepare_str_send (ri, key, auth_str, RIP_AUTH_SIMPLE_SIZE); - } - - if (version == RIPv1) - { - memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4)); - apply_classful_mask_ipv4 (&ifaddrclass); - subnetted = 0; - if (ifc->address->prefixlen > ifaddrclass.prefixlen) - subnetted = 1; - } - - for (rp = route_top (rip->table); rp; rp = route_next (rp)) - if ((list = rp->info) != NULL && listcount (list) != 0) - { - rinfo = listgetdata (listhead (list)); - /* For RIPv1, if we are subnetted, output subnets in our network */ - /* that have the same mask as the output "interface". For other */ - /* networks, only the classfull version is output. */ - - if (version == RIPv1) - { - p = (struct prefix_ipv4 *) &rp->p; - - if (IS_RIP_DEBUG_PACKET) - zlog_debug("RIPv1 mask check, %s/%d considered for output", - inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen); - - if (subnetted && - prefix_match ((struct prefix *) &ifaddrclass, &rp->p)) - { - if ((ifc->address->prefixlen != rp->p.prefixlen) && - (rp->p.prefixlen != 32)) - continue; - } - else - { - memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4)); - apply_classful_mask_ipv4(&classfull); - if (rp->p.u.prefix4.s_addr != 0 && - classfull.prefixlen != rp->p.prefixlen) - continue; - } - if (IS_RIP_DEBUG_PACKET) - zlog_debug("RIPv1 mask check, %s/%d made it through", - inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen); - } - else - p = (struct prefix_ipv4 *) &rp->p; - - /* Apply output filters. */ - ret = rip_filter (RIP_FILTER_OUT, p, ri); - if (ret < 0) - continue; - - /* Changed route only output. */ - if (route_type == rip_changed_route && - (! (rinfo->flags & RIP_RTF_CHANGED))) - continue; - - /* Split horizon. */ - /* if (split_horizon == rip_split_horizon) */ - if (ri->split_horizon == RIP_SPLIT_HORIZON) - { - /* - * We perform split horizon for RIP and connected route. - * For rip routes, we want to suppress the route if we would - * end up sending the route back on the interface that we - * learned it from, with a higher metric. For connected routes, - * we suppress the route if the prefix is a subset of the - * source address that we are going to use for the packet - * (in order to handle the case when multiple subnets are - * configured on the same interface). - */ - int suppress = 0; - struct rip_info *tmp_rinfo = NULL; - - for (ALL_LIST_ELEMENTS_RO (list, listnode, tmp_rinfo)) - if (tmp_rinfo->type == ZEBRA_ROUTE_RIP && - tmp_rinfo->ifindex == ifc->ifp->ifindex) - { - suppress = 1; - break; - } - - if (!suppress && rinfo->type == ZEBRA_ROUTE_CONNECT && - prefix_match((struct prefix *)p, ifc->address)) - suppress = 1; - - if (suppress) - continue; - } - - /* Preparation for route-map. */ - rinfo->metric_set = 0; - rinfo->nexthop_out.s_addr = 0; - rinfo->metric_out = rinfo->metric; - rinfo->tag_out = rinfo->tag; - rinfo->ifindex_out = ifc->ifp->ifindex; - - /* In order to avoid some local loops, - * if the RIP route has a nexthop via this interface, keep the nexthop, - * otherwise set it to 0. The nexthop should not be propagated - * beyond the local broadcast/multicast area in order - * to avoid an IGP multi-level recursive look-up. - * see (4.4) - */ - if (rinfo->ifindex == ifc->ifp->ifindex) - rinfo->nexthop_out = rinfo->nexthop; - - /* Interface route-map */ - if (ri->routemap[RIP_FILTER_OUT]) - { - ret = route_map_apply (ri->routemap[RIP_FILTER_OUT], - (struct prefix *) p, RMAP_RIP, - rinfo); - - if (ret == RMAP_DENYMATCH) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("RIP %s/%d is filtered by route-map out", - inet_ntoa (p->prefix), p->prefixlen); - continue; - } - } - - /* Apply redistribute route map - continue, if deny */ - if (rip->route_map[rinfo->type].name - && rinfo->sub_type != RIP_ROUTE_INTERFACE) - { - ret = route_map_apply (rip->route_map[rinfo->type].map, - (struct prefix *)p, RMAP_RIP, rinfo); - - if (ret == RMAP_DENYMATCH) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("%s/%d is filtered by route-map", - inet_ntoa (p->prefix), p->prefixlen); - continue; - } - } - - /* When route-map does not set metric. */ - if (! rinfo->metric_set) - { - /* If redistribute metric is set. */ - if (rip->route_map[rinfo->type].metric_config - && rinfo->metric != RIP_METRIC_INFINITY) - { - rinfo->metric_out = rip->route_map[rinfo->type].metric; - } - else - { - /* If the route is not connected or localy generated - one, use default-metric value*/ - if (rinfo->type != ZEBRA_ROUTE_RIP - && rinfo->type != ZEBRA_ROUTE_CONNECT - && rinfo->metric != RIP_METRIC_INFINITY) - rinfo->metric_out = rip->default_metric; - } - } - - /* Apply offset-list */ - if (rinfo->metric != RIP_METRIC_INFINITY) - rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out); - - if (rinfo->metric_out > RIP_METRIC_INFINITY) - rinfo->metric_out = RIP_METRIC_INFINITY; - - /* Perform split-horizon with poisoned reverse - * for RIP and connected routes. - **/ - if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) { - /* - * We perform split horizon for RIP and connected route. - * For rip routes, we want to suppress the route if we would - * end up sending the route back on the interface that we - * learned it from, with a higher metric. For connected routes, - * we suppress the route if the prefix is a subset of the - * source address that we are going to use for the packet - * (in order to handle the case when multiple subnets are - * configured on the same interface). - */ - struct rip_info *tmp_rinfo = NULL; - - for (ALL_LIST_ELEMENTS_RO (list, listnode, tmp_rinfo)) - if (tmp_rinfo->type == ZEBRA_ROUTE_RIP && - tmp_rinfo->ifindex == ifc->ifp->ifindex) - rinfo->metric_out = RIP_METRIC_INFINITY; - if (tmp_rinfo->type == ZEBRA_ROUTE_CONNECT && - prefix_match((struct prefix *)p, ifc->address)) - rinfo->metric_out = RIP_METRIC_INFINITY; - } - - /* Prepare preamble, auth headers, if needs be */ - if (num == 0) - { - stream_putc (s, RIP_RESPONSE); - stream_putc (s, version); - stream_putw (s, 0); - - /* auth header for !v1 && !no_auth */ - if ( (ri->auth_type != RIP_NO_AUTH) && (version != RIPv1) ) - doff = rip_auth_header_write (s, ri, key, auth_str, - RIP_AUTH_SIMPLE_SIZE); - } - - /* Write RTE to the stream. */ - num = rip_write_rte (num, s, p, version, rinfo); - if (num == rtemax) - { - if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5) - rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE); - - ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), - to, ifc); - - if (ret >= 0 && IS_RIP_DEBUG_SEND) - rip_packet_dump ((struct rip_packet *)STREAM_DATA (s), - stream_get_endp(s), "SEND"); - num = 0; - stream_reset (s); - } - } - - /* Flush unwritten RTE. */ - if (num != 0) - { - if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5) - rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE); - - ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc); - - if (ret >= 0 && IS_RIP_DEBUG_SEND) - rip_packet_dump ((struct rip_packet *)STREAM_DATA (s), - stream_get_endp (s), "SEND"); - stream_reset (s); - } - - /* Statistics updates. */ - ri->sent_updates++; + /* Set output stream. */ + s = rip->obuf; + + /* Reset stream and RTE counter. */ + stream_reset(s); + rtemax = RIP_MAX_RTE; + + /* Get RIP interface. */ + ri = ifc->ifp->info; + + /* If output interface is in simple password authentication mode, we + need space for authentication data. */ + if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD) + rtemax -= 1; + + /* If output interface is in MD5 authentication mode, we need space + for authentication header and data. */ + if (ri->auth_type == RIP_AUTH_MD5) + rtemax -= 2; + + /* If output interface is in simple password authentication mode + and string or keychain is specified we need space for auth. data */ + if (ri->auth_type != RIP_NO_AUTH) { + if (ri->key_chain) { + struct keychain *keychain; + + keychain = keychain_lookup(ri->key_chain); + if (keychain) + key = key_lookup_for_send(keychain); + } + /* to be passed to auth functions later */ + rip_auth_prepare_str_send(ri, key, auth_str, + RIP_AUTH_SIMPLE_SIZE); + } + + if (version == RIPv1) { + memcpy(&ifaddrclass, ifc->address, sizeof(struct prefix_ipv4)); + apply_classful_mask_ipv4(&ifaddrclass); + subnetted = 0; + if (ifc->address->prefixlen > ifaddrclass.prefixlen) + subnetted = 1; + } + + for (rp = route_top(rip->table); rp; rp = route_next(rp)) + if ((list = rp->info) != NULL && listcount(list) != 0) { + rinfo = listgetdata(listhead(list)); + /* For RIPv1, if we are subnetted, output subnets in our + * network */ + /* that have the same mask as the output "interface". + * For other */ + /* networks, only the classfull version is output. */ + + if (version == RIPv1) { + p = (struct prefix_ipv4 *)&rp->p; + + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "RIPv1 mask check, %s/%d considered for output", + inet_ntoa(rp->p.u.prefix4), + rp->p.prefixlen); + + if (subnetted + && prefix_match( + (struct prefix *)&ifaddrclass, + &rp->p)) { + if ((ifc->address->prefixlen + != rp->p.prefixlen) + && (rp->p.prefixlen != 32)) + continue; + } else { + memcpy(&classfull, &rp->p, + sizeof(struct prefix_ipv4)); + apply_classful_mask_ipv4(&classfull); + if (rp->p.u.prefix4.s_addr != 0 + && classfull.prefixlen + != rp->p.prefixlen) + continue; + } + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "RIPv1 mask check, %s/%d made it through", + inet_ntoa(rp->p.u.prefix4), + rp->p.prefixlen); + } else + p = (struct prefix_ipv4 *)&rp->p; + + /* Apply output filters. */ + ret = rip_filter(RIP_FILTER_OUT, p, ri); + if (ret < 0) + continue; + + /* Changed route only output. */ + if (route_type == rip_changed_route + && (!(rinfo->flags & RIP_RTF_CHANGED))) + continue; + + /* Split horizon. */ + /* if (split_horizon == rip_split_horizon) */ + if (ri->split_horizon == RIP_SPLIT_HORIZON) { + /* + * We perform split horizon for RIP and + * connected route. + * For rip routes, we want to suppress the route + * if we would + * end up sending the route back on the + * interface that we + * learned it from, with a higher metric. For + * connected routes, + * we suppress the route if the prefix is a + * subset of the + * source address that we are going to use for + * the packet + * (in order to handle the case when multiple + * subnets are + * configured on the same interface). + */ + int suppress = 0; + struct rip_info *tmp_rinfo = NULL; + + for (ALL_LIST_ELEMENTS_RO(list, listnode, + tmp_rinfo)) + if (tmp_rinfo->type == ZEBRA_ROUTE_RIP + && tmp_rinfo->ifindex + == ifc->ifp->ifindex) { + suppress = 1; + break; + } + + if (!suppress + && rinfo->type == ZEBRA_ROUTE_CONNECT + && prefix_match((struct prefix *)p, + ifc->address)) + suppress = 1; + + if (suppress) + continue; + } + + /* Preparation for route-map. */ + rinfo->metric_set = 0; + rinfo->nexthop_out.s_addr = 0; + rinfo->metric_out = rinfo->metric; + rinfo->tag_out = rinfo->tag; + rinfo->ifindex_out = ifc->ifp->ifindex; + + /* In order to avoid some local loops, + * if the RIP route has a nexthop via this interface, + * keep the nexthop, + * otherwise set it to 0. The nexthop should not be + * propagated + * beyond the local broadcast/multicast area in order + * to avoid an IGP multi-level recursive look-up. + * see (4.4) + */ + if (rinfo->ifindex == ifc->ifp->ifindex) + rinfo->nexthop_out = rinfo->nexthop; + + /* Interface route-map */ + if (ri->routemap[RIP_FILTER_OUT]) { + ret = route_map_apply( + ri->routemap[RIP_FILTER_OUT], + (struct prefix *)p, RMAP_RIP, rinfo); + + if (ret == RMAP_DENYMATCH) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "RIP %s/%d is filtered by route-map out", + inet_ntoa(p->prefix), + p->prefixlen); + continue; + } + } + + /* Apply redistribute route map - continue, if deny */ + if (rip->route_map[rinfo->type].name + && rinfo->sub_type != RIP_ROUTE_INTERFACE) { + ret = route_map_apply( + rip->route_map[rinfo->type].map, + (struct prefix *)p, RMAP_RIP, rinfo); + + if (ret == RMAP_DENYMATCH) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "%s/%d is filtered by route-map", + inet_ntoa(p->prefix), + p->prefixlen); + continue; + } + } + + /* When route-map does not set metric. */ + if (!rinfo->metric_set) { + /* If redistribute metric is set. */ + if (rip->route_map[rinfo->type].metric_config + && rinfo->metric != RIP_METRIC_INFINITY) { + rinfo->metric_out = + rip->route_map[rinfo->type] + .metric; + } else { + /* If the route is not connected or + localy generated + one, use default-metric value*/ + if (rinfo->type != ZEBRA_ROUTE_RIP + && rinfo->type + != ZEBRA_ROUTE_CONNECT + && rinfo->metric + != RIP_METRIC_INFINITY) + rinfo->metric_out = + rip->default_metric; + } + } + + /* Apply offset-list */ + if (rinfo->metric != RIP_METRIC_INFINITY) + rip_offset_list_apply_out(p, ifc->ifp, + &rinfo->metric_out); + + if (rinfo->metric_out > RIP_METRIC_INFINITY) + rinfo->metric_out = RIP_METRIC_INFINITY; + + /* Perform split-horizon with poisoned reverse + * for RIP and connected routes. + **/ + if (ri->split_horizon + == RIP_SPLIT_HORIZON_POISONED_REVERSE) { + /* + * We perform split horizon for RIP and + * connected route. + * For rip routes, we want to suppress the route + * if we would + * end up sending the route back on the + * interface that we + * learned it from, with a higher metric. For + * connected routes, + * we suppress the route if the prefix is a + * subset of the + * source address that we are going to use for + * the packet + * (in order to handle the case when multiple + * subnets are + * configured on the same interface). + */ + struct rip_info *tmp_rinfo = NULL; + + for (ALL_LIST_ELEMENTS_RO(list, listnode, + tmp_rinfo)) + if (tmp_rinfo->type == ZEBRA_ROUTE_RIP + && tmp_rinfo->ifindex + == ifc->ifp->ifindex) + rinfo->metric_out = + RIP_METRIC_INFINITY; + if (tmp_rinfo->type == ZEBRA_ROUTE_CONNECT + && prefix_match((struct prefix *)p, + ifc->address)) + rinfo->metric_out = RIP_METRIC_INFINITY; + } + + /* Prepare preamble, auth headers, if needs be */ + if (num == 0) { + stream_putc(s, RIP_RESPONSE); + stream_putc(s, version); + stream_putw(s, 0); + + /* auth header for !v1 && !no_auth */ + if ((ri->auth_type != RIP_NO_AUTH) + && (version != RIPv1)) + doff = rip_auth_header_write( + s, ri, key, auth_str, + RIP_AUTH_SIMPLE_SIZE); + } + + /* Write RTE to the stream. */ + num = rip_write_rte(num, s, p, version, rinfo); + if (num == rtemax) { + if (version == RIPv2 + && ri->auth_type == RIP_AUTH_MD5) + rip_auth_md5_set(s, ri, doff, auth_str, + RIP_AUTH_SIMPLE_SIZE); + + ret = rip_send_packet(STREAM_DATA(s), + stream_get_endp(s), to, + ifc); + + if (ret >= 0 && IS_RIP_DEBUG_SEND) + rip_packet_dump((struct rip_packet *) + STREAM_DATA(s), + stream_get_endp(s), + "SEND"); + num = 0; + stream_reset(s); + } + } + + /* Flush unwritten RTE. */ + if (num != 0) { + if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5) + rip_auth_md5_set(s, ri, doff, auth_str, + RIP_AUTH_SIMPLE_SIZE); + + ret = rip_send_packet(STREAM_DATA(s), stream_get_endp(s), to, + ifc); + + if (ret >= 0 && IS_RIP_DEBUG_SEND) + rip_packet_dump((struct rip_packet *)STREAM_DATA(s), + stream_get_endp(s), "SEND"); + stream_reset(s); + } + + /* Statistics updates. */ + ri->sent_updates++; } /* Send RIP packet to the interface. */ -static void -rip_update_interface (struct connected *ifc, u_char version, int route_type) -{ - struct interface *ifp = ifc->ifp; - struct rip_interface *ri = ifp->info; - struct sockaddr_in to; - - /* When RIP version is 2 and multicast enable interface. */ - if (version == RIPv2 && !ri->v2_broadcast && if_is_multicast (ifp)) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("multicast announce on %s ", ifp->name); - - rip_output_process (ifc, NULL, route_type, version); - return; - } - - /* If we can't send multicast packet, send it with unicast. */ - if (if_is_broadcast (ifp) || if_is_pointopoint (ifp)) - { - if (ifc->address->family == AF_INET) - { - /* Destination address and port setting. */ - memset (&to, 0, sizeof (struct sockaddr_in)); - if (ifc->destination) - /* use specified broadcast or peer destination addr */ - to.sin_addr = ifc->destination->u.prefix4; - else if (ifc->address->prefixlen < IPV4_MAX_PREFIXLEN) - /* calculate the appropriate broadcast address */ - to.sin_addr.s_addr = - ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr, - ifc->address->prefixlen); - else - /* do not know where to send the packet */ - return; - to.sin_port = htons (RIP_PORT_DEFAULT); - - if (IS_RIP_DEBUG_EVENT) - zlog_debug("%s announce to %s on %s", - CONNECTED_PEER(ifc) ? "unicast" : "broadcast", - inet_ntoa (to.sin_addr), ifp->name); - - rip_output_process (ifc, &to, route_type, version); - } - } +static void rip_update_interface(struct connected *ifc, u_char version, + int route_type) +{ + struct interface *ifp = ifc->ifp; + struct rip_interface *ri = ifp->info; + struct sockaddr_in to; + + /* When RIP version is 2 and multicast enable interface. */ + if (version == RIPv2 && !ri->v2_broadcast && if_is_multicast(ifp)) { + if (IS_RIP_DEBUG_EVENT) + zlog_debug("multicast announce on %s ", ifp->name); + + rip_output_process(ifc, NULL, route_type, version); + return; + } + + /* If we can't send multicast packet, send it with unicast. */ + if (if_is_broadcast(ifp) || if_is_pointopoint(ifp)) { + if (ifc->address->family == AF_INET) { + /* Destination address and port setting. */ + memset(&to, 0, sizeof(struct sockaddr_in)); + if (ifc->destination) + /* use specified broadcast or peer destination + * addr */ + to.sin_addr = ifc->destination->u.prefix4; + else if (ifc->address->prefixlen < IPV4_MAX_PREFIXLEN) + /* calculate the appropriate broadcast address + */ + to.sin_addr.s_addr = ipv4_broadcast_addr( + ifc->address->u.prefix4.s_addr, + ifc->address->prefixlen); + else + /* do not know where to send the packet */ + return; + to.sin_port = htons(RIP_PORT_DEFAULT); + + if (IS_RIP_DEBUG_EVENT) + zlog_debug("%s announce to %s on %s", + CONNECTED_PEER(ifc) ? "unicast" + : "broadcast", + inet_ntoa(to.sin_addr), ifp->name); + + rip_output_process(ifc, &to, route_type, version); + } + } } /* Update send to all interface and neighbor. */ -static void -rip_update_process (int route_type) -{ - struct listnode *node; - struct listnode *ifnode, *ifnnode; - struct connected *connected; - struct interface *ifp; - struct rip_interface *ri; - struct route_node *rp; - struct sockaddr_in to; - struct prefix *p; - - /* Send RIP update to each interface. */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - if (if_is_loopback (ifp)) - continue; - - if (! if_is_operative (ifp)) - continue; - - /* Fetch RIP interface information. */ - ri = ifp->info; - - /* When passive interface is specified, suppress announce to the - interface. */ - if (ri->passive) - continue; - - if (ri->running) - { - /* - * If there is no version configuration in the interface, - * use rip's version setting. - */ - int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ? - rip->version_send : ri->ri_send); - - if (IS_RIP_DEBUG_EVENT) - zlog_debug("SEND UPDATE to %s ifindex %d", - ifp->name, ifp->ifindex); - - /* send update on each connected network */ - for (ALL_LIST_ELEMENTS (ifp->connected, ifnode, ifnnode, connected)) - { - if (connected->address->family == AF_INET) - { - if (vsend & RIPv1) - rip_update_interface (connected, RIPv1, route_type); - if ((vsend & RIPv2) && if_is_multicast(ifp)) - rip_update_interface (connected, RIPv2, route_type); +static void rip_update_process(int route_type) +{ + struct listnode *node; + struct listnode *ifnode, *ifnnode; + struct connected *connected; + struct interface *ifp; + struct rip_interface *ri; + struct route_node *rp; + struct sockaddr_in to; + struct prefix *p; + + /* Send RIP update to each interface. */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + if (if_is_loopback(ifp)) + continue; + + if (!if_is_operative(ifp)) + continue; + + /* Fetch RIP interface information. */ + ri = ifp->info; + + /* When passive interface is specified, suppress announce to the + interface. */ + if (ri->passive) + continue; + + if (ri->running) { + /* + * If there is no version configuration in the + * interface, + * use rip's version setting. + */ + int vsend = ((ri->ri_send == RI_RIP_UNSPEC) + ? rip->version_send + : ri->ri_send); + + if (IS_RIP_DEBUG_EVENT) + zlog_debug("SEND UPDATE to %s ifindex %d", + ifp->name, ifp->ifindex); + + /* send update on each connected network */ + for (ALL_LIST_ELEMENTS(ifp->connected, ifnode, ifnnode, + connected)) { + if (connected->address->family == AF_INET) { + if (vsend & RIPv1) + rip_update_interface( + connected, RIPv1, + route_type); + if ((vsend & RIPv2) + && if_is_multicast(ifp)) + rip_update_interface( + connected, RIPv2, + route_type); + } + } + } + } + + /* RIP send updates to each neighbor. */ + for (rp = route_top(rip->neighbor); rp; rp = route_next(rp)) + if (rp->info != NULL) { + p = &rp->p; + + connected = if_lookup_address(&p->u.prefix4, AF_INET, + VRF_DEFAULT); + if (!connected) { + zlog_warn( + "Neighbor %s doesnt have connected interface!", + inet_ntoa(p->u.prefix4)); + continue; + } + + /* Set destination address and port */ + memset(&to, 0, sizeof(struct sockaddr_in)); + to.sin_addr = p->u.prefix4; + to.sin_port = htons(RIP_PORT_DEFAULT); + + /* RIP version is rip's configuration. */ + rip_output_process(connected, &to, route_type, + rip->version_send); } - } - } - } - - /* RIP send updates to each neighbor. */ - for (rp = route_top (rip->neighbor); rp; rp = route_next (rp)) - if (rp->info != NULL) - { - p = &rp->p; - - connected = if_lookup_address (&p->u.prefix4, AF_INET, VRF_DEFAULT); - if (! connected) - { - zlog_warn ("Neighbor %s doesnt have connected interface!", - inet_ntoa (p->u.prefix4)); - continue; - } - - /* Set destination address and port */ - memset (&to, 0, sizeof (struct sockaddr_in)); - to.sin_addr = p->u.prefix4; - to.sin_port = htons (RIP_PORT_DEFAULT); - - /* RIP version is rip's configuration. */ - rip_output_process (connected, &to, route_type, rip->version_send); - } } /* RIP's periodical timer. */ -static int -rip_update (struct thread *t) +static int rip_update(struct thread *t) { - /* Clear timer pointer. */ - rip->t_update = NULL; + /* Clear timer pointer. */ + rip->t_update = NULL; - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("update timer fire!"); + if (IS_RIP_DEBUG_EVENT) + zlog_debug("update timer fire!"); - /* Process update output. */ - rip_update_process (rip_all_route); + /* Process update output. */ + rip_update_process(rip_all_route); - /* Triggered updates may be suppressed if a regular update is due by - the time the triggered update would be sent. */ - RIP_TIMER_OFF (rip->t_triggered_interval); - rip->trigger = 0; + /* Triggered updates may be suppressed if a regular update is due by + the time the triggered update would be sent. */ + RIP_TIMER_OFF(rip->t_triggered_interval); + rip->trigger = 0; - /* Register myself. */ - rip_event (RIP_UPDATE_EVENT, 0); + /* Register myself. */ + rip_event(RIP_UPDATE_EVENT, 0); - return 0; + return 0; } /* Walk down the RIP routing table then clear changed flag. */ -static void -rip_clear_changed_flag (void) +static void rip_clear_changed_flag(void) { - struct route_node *rp; - struct rip_info *rinfo = NULL; - struct list *list = NULL; - struct listnode *listnode = NULL; + struct route_node *rp; + struct rip_info *rinfo = NULL; + struct list *list = NULL; + struct listnode *listnode = NULL; - for (rp = route_top (rip->table); rp; rp = route_next (rp)) - if ((list = rp->info) != NULL) - for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) - { - UNSET_FLAG (rinfo->flags, RIP_RTF_CHANGED); - /* This flag can be set only on the first entry. */ - break; - } + for (rp = route_top(rip->table); rp; rp = route_next(rp)) + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { + UNSET_FLAG(rinfo->flags, RIP_RTF_CHANGED); + /* This flag can be set only on the first entry. + */ + break; + } } /* Triggered update interval timer. */ -static int -rip_triggered_interval (struct thread *t) +static int rip_triggered_interval(struct thread *t) { - int rip_triggered_update (struct thread *); + int rip_triggered_update(struct thread *); - rip->t_triggered_interval = NULL; + rip->t_triggered_interval = NULL; - if (rip->trigger) - { - rip->trigger = 0; - rip_triggered_update (t); - } - return 0; -} + if (rip->trigger) { + rip->trigger = 0; + rip_triggered_update(t); + } + return 0; +} /* Execute triggered update. */ -static int -rip_triggered_update (struct thread *t) +static int rip_triggered_update(struct thread *t) { - int interval; + int interval; - /* Clear thred pointer. */ - rip->t_triggered_update = NULL; + /* Clear thred pointer. */ + rip->t_triggered_update = NULL; - /* Cancel interval timer. */ - RIP_TIMER_OFF (rip->t_triggered_interval); - rip->trigger = 0; + /* Cancel interval timer. */ + RIP_TIMER_OFF(rip->t_triggered_interval); + rip->trigger = 0; - /* Logging triggered update. */ - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("triggered update!"); + /* Logging triggered update. */ + if (IS_RIP_DEBUG_EVENT) + zlog_debug("triggered update!"); - /* Split Horizon processing is done when generating triggered - updates as well as normal updates (see section 2.6). */ - rip_update_process (rip_changed_route); + /* Split Horizon processing is done when generating triggered + updates as well as normal updates (see section 2.6). */ + rip_update_process(rip_changed_route); - /* Once all of the triggered updates have been generated, the route - change flags should be cleared. */ - rip_clear_changed_flag (); + /* Once all of the triggered updates have been generated, the route + change flags should be cleared. */ + rip_clear_changed_flag(); - /* After a triggered update is sent, a timer should be set for a - random interval between 1 and 5 seconds. If other changes that - would trigger updates occur before the timer expires, a single - update is triggered when the timer expires. */ - interval = (random () % 5) + 1; + /* After a triggered update is sent, a timer should be set for a + random interval between 1 and 5 seconds. If other changes that + would trigger updates occur before the timer expires, a single + update is triggered when the timer expires. */ + interval = (random() % 5) + 1; - rip->t_triggered_interval = NULL; - thread_add_timer(master, rip_triggered_interval, NULL, interval, - &rip->t_triggered_interval); + rip->t_triggered_interval = NULL; + thread_add_timer(master, rip_triggered_interval, NULL, interval, + &rip->t_triggered_interval); - return 0; + return 0; } /* Withdraw redistributed route. */ -void -rip_redistribute_withdraw (int type) +void rip_redistribute_withdraw(int type) +{ + struct route_node *rp; + struct rip_info *rinfo = NULL; + struct list *list = NULL; + + if (!rip) + return; + + for (rp = route_top(rip->table); rp; rp = route_next(rp)) + if ((list = rp->info) != NULL) { + rinfo = listgetdata(listhead(list)); + if (rinfo->type == type + && rinfo->sub_type != RIP_ROUTE_INTERFACE) { + /* Perform poisoned reverse. */ + rinfo->metric = RIP_METRIC_INFINITY; + RIP_TIMER_ON(rinfo->t_garbage_collect, + rip_garbage_collect, + rip->garbage_time); + RIP_TIMER_OFF(rinfo->t_timeout); + rinfo->flags |= RIP_RTF_CHANGED; + + if (IS_RIP_DEBUG_EVENT) { + struct prefix_ipv4 *p = + (struct prefix_ipv4 *)&rp->p; + + zlog_debug( + "Poisone %s/%d on the interface %s with an infinity metric [withdraw]", + inet_ntoa(p->prefix), + p->prefixlen, + ifindex2ifname(rinfo->ifindex, + VRF_DEFAULT)); + } + + rip_event(RIP_TRIGGERED_UPDATE, 0); + } + } +} + +/* Create new RIP instance and set it to global variable. */ +static int rip_create(void) { - struct route_node *rp; - struct rip_info *rinfo = NULL; - struct list *list = NULL; + rip = XCALLOC(MTYPE_RIP, sizeof(struct rip)); - if (!rip) - return; + /* Set initial value. */ + rip->version_send = RI_RIP_VERSION_2; + rip->version_recv = RI_RIP_VERSION_1_AND_2; + rip->update_time = RIP_UPDATE_TIMER_DEFAULT; + rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT; + rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT; + rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT; - for (rp = route_top (rip->table); rp; rp = route_next (rp)) - if ((list = rp->info) != NULL) - { - rinfo = listgetdata (listhead (list)); - if (rinfo->type == type - && rinfo->sub_type != RIP_ROUTE_INTERFACE) - { - /* Perform poisoned reverse. */ - rinfo->metric = RIP_METRIC_INFINITY; - RIP_TIMER_ON (rinfo->t_garbage_collect, - rip_garbage_collect, rip->garbage_time); - RIP_TIMER_OFF (rinfo->t_timeout); - rinfo->flags |= RIP_RTF_CHANGED; + /* Initialize RIP routig table. */ + rip->table = route_table_init(); + rip->route = route_table_init(); + rip->neighbor = route_table_init(); - if (IS_RIP_DEBUG_EVENT) { - struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p; + /* Make output stream. */ + rip->obuf = stream_new(1500); - zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]", - inet_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(rinfo->ifindex, VRF_DEFAULT)); - } + /* Make socket. */ + rip->sock = rip_create_socket(); + if (rip->sock < 0) + return rip->sock; - rip_event (RIP_TRIGGERED_UPDATE, 0); - } - } -} + /* Create read and timer thread. */ + rip_event(RIP_READ, rip->sock); + rip_event(RIP_UPDATE_EVENT, 1); -/* Create new RIP instance and set it to global variable. */ -static int -rip_create (void) -{ - rip = XCALLOC (MTYPE_RIP, sizeof (struct rip)); + QOBJ_REG(rip, rip); - /* Set initial value. */ - rip->version_send = RI_RIP_VERSION_2; - rip->version_recv = RI_RIP_VERSION_1_AND_2; - rip->update_time = RIP_UPDATE_TIMER_DEFAULT; - rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT; - rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT; - rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT; - - /* Initialize RIP routig table. */ - rip->table = route_table_init (); - rip->route = route_table_init (); - rip->neighbor = route_table_init (); + return 0; +} - /* Make output stream. */ - rip->obuf = stream_new (1500); +/* Sned RIP request to the destination. */ +int rip_request_send(struct sockaddr_in *to, struct interface *ifp, + u_char version, struct connected *connected) +{ + struct rte *rte; + struct rip_packet rip_packet; + struct listnode *node, *nnode; + + memset(&rip_packet, 0, sizeof(rip_packet)); + + rip_packet.command = RIP_REQUEST; + rip_packet.version = version; + rte = rip_packet.rte; + rte->metric = htonl(RIP_METRIC_INFINITY); + + if (connected) { + /* + * connected is only sent for ripv1 case, or when + * interface does not support multicast. Caller loops + * over each connected address for this case. + */ + if (rip_send_packet((u_char *)&rip_packet, sizeof(rip_packet), + to, connected) + != sizeof(rip_packet)) + return -1; + else + return sizeof(rip_packet); + } - /* Make socket. */ - rip->sock = rip_create_socket (); - if (rip->sock < 0) - return rip->sock; + /* send request on each connected network */ + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) { + struct prefix_ipv4 *p; - /* Create read and timer thread. */ - rip_event (RIP_READ, rip->sock); - rip_event (RIP_UPDATE_EVENT, 1); + p = (struct prefix_ipv4 *)connected->address; - QOBJ_REG (rip, rip); + if (p->family != AF_INET) + continue; - return 0; + if (rip_send_packet((u_char *)&rip_packet, sizeof(rip_packet), + to, connected) + != sizeof(rip_packet)) + return -1; + } + return sizeof(rip_packet); } -/* Sned RIP request to the destination. */ -int -rip_request_send (struct sockaddr_in *to, struct interface *ifp, - u_char version, struct connected *connected) -{ - struct rte *rte; - struct rip_packet rip_packet; - struct listnode *node, *nnode; - - memset (&rip_packet, 0, sizeof (rip_packet)); - - rip_packet.command = RIP_REQUEST; - rip_packet.version = version; - rte = rip_packet.rte; - rte->metric = htonl (RIP_METRIC_INFINITY); - - if (connected) - { - /* - * connected is only sent for ripv1 case, or when - * interface does not support multicast. Caller loops - * over each connected address for this case. - */ - if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet), - to, connected) != sizeof (rip_packet)) - return -1; - else - return sizeof (rip_packet); - } - - /* send request on each connected network */ - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected)) - { - struct prefix_ipv4 *p; - - p = (struct prefix_ipv4 *) connected->address; - - if (p->family != AF_INET) - continue; - - if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet), - to, connected) != sizeof (rip_packet)) - return -1; - } - return sizeof (rip_packet); -} - -static int -rip_update_jitter (unsigned long time) +static int rip_update_jitter(unsigned long time) { #define JITTER_BOUND 4 - /* We want to get the jitter to +/- 1/JITTER_BOUND the interval. - Given that, we cannot let time be less than JITTER_BOUND seconds. - The RIPv2 RFC says jitter should be small compared to - update_time. We consider 1/JITTER_BOUND to be small. - */ - - int jitter_input = time; - int jitter; - - if (jitter_input < JITTER_BOUND) - jitter_input = JITTER_BOUND; - - jitter = (((random () % ((jitter_input * 2) + 1)) - jitter_input)); - - return jitter/JITTER_BOUND; -} - -void -rip_event (enum rip_event event, int sock) -{ - int jitter = 0; - - switch (event) - { - case RIP_READ: - rip->t_read = NULL; - thread_add_read(master, rip_read, NULL, sock, &rip->t_read); - break; - case RIP_UPDATE_EVENT: - RIP_TIMER_OFF (rip->t_update); - jitter = rip_update_jitter (rip->update_time); - thread_add_timer(master, rip_update, NULL, sock ? 2 : rip->update_time + jitter, - &rip->t_update); - break; - case RIP_TRIGGERED_UPDATE: - if (rip->t_triggered_interval) - rip->trigger = 1; - else thread_add_event(master, rip_triggered_update, NULL, 0, - &rip->t_triggered_update); - break; - default: - break; - } + /* We want to get the jitter to +/- 1/JITTER_BOUND the interval. + Given that, we cannot let time be less than JITTER_BOUND seconds. + The RIPv2 RFC says jitter should be small compared to + update_time. We consider 1/JITTER_BOUND to be small. + */ + + int jitter_input = time; + int jitter; + + if (jitter_input < JITTER_BOUND) + jitter_input = JITTER_BOUND; + + jitter = (((random() % ((jitter_input * 2) + 1)) - jitter_input)); + + return jitter / JITTER_BOUND; +} + +void rip_event(enum rip_event event, int sock) +{ + int jitter = 0; + + switch (event) { + case RIP_READ: + rip->t_read = NULL; + thread_add_read(master, rip_read, NULL, sock, &rip->t_read); + break; + case RIP_UPDATE_EVENT: + RIP_TIMER_OFF(rip->t_update); + jitter = rip_update_jitter(rip->update_time); + thread_add_timer(master, rip_update, NULL, + sock ? 2 : rip->update_time + jitter, + &rip->t_update); + break; + case RIP_TRIGGERED_UPDATE: + if (rip->t_triggered_interval) + rip->trigger = 1; + else + thread_add_event(master, rip_triggered_update, NULL, 0, + &rip->t_triggered_update); + break; + default: + break; + } } DEFUN_NOSH (router_rip, @@ -2806,21 +2794,19 @@ DEFUN_NOSH (router_rip, "Enable a routing process\n" "Routing Information Protocol (RIP)\n") { - int ret; + int ret; - /* If rip is not enabled before. */ - if (! rip) - { - ret = rip_create (); - if (ret < 0) - { - zlog_info ("Can't create RIP"); - return CMD_WARNING_CONFIG_FAILED; + /* If rip is not enabled before. */ + if (!rip) { + ret = rip_create(); + if (ret < 0) { + zlog_info("Can't create RIP"); + return CMD_WARNING_CONFIG_FAILED; + } } - } - VTY_PUSH_CONTEXT(RIP_NODE, rip); + VTY_PUSH_CONTEXT(RIP_NODE, rip); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_router_rip, @@ -2830,9 +2816,9 @@ DEFUN (no_router_rip, "Enable a routing process\n" "Routing Information Protocol (RIP)\n") { - if (rip) - rip_clean (); - return CMD_SUCCESS; + if (rip) + rip_clean(); + return CMD_SUCCESS; } DEFUN (rip_version, @@ -2841,19 +2827,18 @@ DEFUN (rip_version, "Set routing protocol version\n" "version\n") { - int idx_number = 1; - int version; + int idx_number = 1; + int version; - version = atoi (argv[idx_number]->arg); - if (version != RIPv1 && version != RIPv2) - { - vty_out (vty, "invalid rip version %d\n",version); - return CMD_WARNING_CONFIG_FAILED; - } - rip->version_send = version; - rip->version_recv = version; + version = atoi(argv[idx_number]->arg); + if (version != RIPv1 && version != RIPv2) { + vty_out(vty, "invalid rip version %d\n", version); + return CMD_WARNING_CONFIG_FAILED; + } + rip->version_send = version; + rip->version_recv = version; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_rip_version, @@ -2863,11 +2848,11 @@ DEFUN (no_rip_version, "Set routing protocol version\n" "Version\n") { - /* Set RIP version to the default. */ - rip->version_send = RI_RIP_VERSION_2; - rip->version_recv = RI_RIP_VERSION_1_AND_2; + /* Set RIP version to the default. */ + rip->version_send = RI_RIP_VERSION_2; + rip->version_recv = RI_RIP_VERSION_1_AND_2; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -2877,34 +2862,33 @@ DEFUN (rip_route, "RIP static route configuration\n" "IP prefix /\n") { - int idx_ipv4_prefixlen = 1; - int ret; - struct prefix_ipv4 p; - struct route_node *node; + int idx_ipv4_prefixlen = 1; + int ret; + struct prefix_ipv4 p; + struct route_node *node; - ret = str2prefix_ipv4 (argv[idx_ipv4_prefixlen]->arg, &p); - if (ret < 0) - { - vty_out (vty, "Malformed address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - apply_mask_ipv4 (&p); + ret = str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + if (ret < 0) { + vty_out(vty, "Malformed address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + apply_mask_ipv4(&p); - /* For router rip configuration. */ - node = route_node_get (rip->route, (struct prefix *) &p); + /* For router rip configuration. */ + node = route_node_get(rip->route, (struct prefix *)&p); - if (node->info) - { - vty_out (vty, "There is already same static route.\n"); - route_unlock_node (node); - return CMD_WARNING_CONFIG_FAILED; - } + if (node->info) { + vty_out(vty, "There is already same static route.\n"); + route_unlock_node(node); + return CMD_WARNING_CONFIG_FAILED; + } - node->info = (void *)1; + node->info = (void *)1; - rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL, 0, 0, 0); + rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL, 0, + 0, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_rip_route, @@ -2914,34 +2898,33 @@ DEFUN (no_rip_route, "RIP static route configuration\n" "IP prefix /\n") { - int idx_ipv4_prefixlen = 2; - int ret; - struct prefix_ipv4 p; - struct route_node *node; + int idx_ipv4_prefixlen = 2; + int ret; + struct prefix_ipv4 p; + struct route_node *node; - ret = str2prefix_ipv4 (argv[idx_ipv4_prefixlen]->arg, &p); - if (ret < 0) - { - vty_out (vty, "Malformed address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - apply_mask_ipv4 (&p); - - /* For router rip configuration. */ - node = route_node_lookup (rip->route, (struct prefix *) &p); - if (! node) - { - vty_out (vty, "Can't find route %s.\n",argv[idx_ipv4_prefixlen]->arg); - return CMD_WARNING_CONFIG_FAILED; - } + ret = str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + if (ret < 0) { + vty_out(vty, "Malformed address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + apply_mask_ipv4(&p); + + /* For router rip configuration. */ + node = route_node_lookup(rip->route, (struct prefix *)&p); + if (!node) { + vty_out(vty, "Can't find route %s.\n", + argv[idx_ipv4_prefixlen]->arg); + return CMD_WARNING_CONFIG_FAILED; + } - rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0); - route_unlock_node (node); + rip_redistribute_delete(ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0); + route_unlock_node(node); - node->info = NULL; - route_unlock_node (node); + node->info = NULL; + route_unlock_node(node); - return CMD_SUCCESS; + return CMD_SUCCESS; } #if 0 @@ -2967,13 +2950,12 @@ DEFUN (rip_default_metric, "Set a metric of redistribute routes\n" "Default metric\n") { - int idx_number = 1; - if (rip) - { - rip->default_metric = atoi (argv[idx_number]->arg); - /* rip_update_default_metric (); */ - } - return CMD_SUCCESS; + int idx_number = 1; + if (rip) { + rip->default_metric = atoi(argv[idx_number]->arg); + /* rip_update_default_metric (); */ + } + return CMD_SUCCESS; } DEFUN (no_rip_default_metric, @@ -2983,12 +2965,11 @@ DEFUN (no_rip_default_metric, "Set a metric of redistribute routes\n" "Default metric\n") { - if (rip) - { - rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT; - /* rip_update_default_metric (); */ - } - return CMD_SUCCESS; + if (rip) { + rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT; + /* rip_update_default_metric (); */ + } + return CMD_SUCCESS; } @@ -3001,46 +2982,46 @@ DEFUN (rip_timers, "Routing information timeout timer. Default is 180.\n" "Garbage collection timer. Default is 120.\n") { - int idx_number = 2; - int idx_number_2 = 3; - int idx_number_3 = 4; - unsigned long update; - unsigned long timeout; - unsigned long garbage; - char *endptr = NULL; - unsigned long RIP_TIMER_MAX = 2147483647; - unsigned long RIP_TIMER_MIN = 5; - - update = strtoul (argv[idx_number]->arg, &endptr, 10); - if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0') - { - vty_out (vty, "update timer value error\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - timeout = strtoul (argv[idx_number_2]->arg, &endptr, 10); - if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0') - { - vty_out (vty, "timeout timer value error\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - garbage = strtoul (argv[idx_number_3]->arg, &endptr, 10); - if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0') - { - vty_out (vty, "garbage timer value error\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Set each timer value. */ - rip->update_time = update; - rip->timeout_time = timeout; - rip->garbage_time = garbage; - - /* Reset update timer thread. */ - rip_event (RIP_UPDATE_EVENT, 0); - - return CMD_SUCCESS; + int idx_number = 2; + int idx_number_2 = 3; + int idx_number_3 = 4; + unsigned long update; + unsigned long timeout; + unsigned long garbage; + char *endptr = NULL; + unsigned long RIP_TIMER_MAX = 2147483647; + unsigned long RIP_TIMER_MIN = 5; + + update = strtoul(argv[idx_number]->arg, &endptr, 10); + if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN + || *endptr != '\0') { + vty_out(vty, "update timer value error\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + timeout = strtoul(argv[idx_number_2]->arg, &endptr, 10); + if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN + || *endptr != '\0') { + vty_out(vty, "timeout timer value error\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + garbage = strtoul(argv[idx_number_3]->arg, &endptr, 10); + if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN + || *endptr != '\0') { + vty_out(vty, "garbage timer value error\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Set each timer value. */ + rip->update_time = update; + rip->timeout_time = timeout; + rip->garbage_time = garbage; + + /* Reset update timer thread. */ + rip_event(RIP_UPDATE_EVENT, 0); + + return CMD_SUCCESS; } DEFUN (no_rip_timers, @@ -3053,210 +3034,193 @@ DEFUN (no_rip_timers, "Routing information timeout timer. Default is 180.\n" "Garbage collection timer. Default is 120.\n") { - /* Set each timer value to the default. */ - rip->update_time = RIP_UPDATE_TIMER_DEFAULT; - rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT; - rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT; + /* Set each timer value to the default. */ + rip->update_time = RIP_UPDATE_TIMER_DEFAULT; + rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT; + rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT; - /* Reset update timer thread. */ - rip_event (RIP_UPDATE_EVENT, 0); + /* Reset update timer thread. */ + rip_event(RIP_UPDATE_EVENT, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } - struct route_table *rip_distance_table; -struct rip_distance -{ - /* Distance value for the IP source prefix. */ - u_char distance; +struct rip_distance { + /* Distance value for the IP source prefix. */ + u_char distance; - /* Name of the access-list to be matched. */ - char *access_list; + /* Name of the access-list to be matched. */ + char *access_list; }; -static struct rip_distance * -rip_distance_new (void) +static struct rip_distance *rip_distance_new(void) { - return XCALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance)); + return XCALLOC(MTYPE_RIP_DISTANCE, sizeof(struct rip_distance)); } -static void -rip_distance_free (struct rip_distance *rdistance) -{ - XFREE (MTYPE_RIP_DISTANCE, rdistance); -} - -static int -rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str, - const char *access_list_str) -{ - int ret; - struct prefix_ipv4 p; - u_char distance; - struct route_node *rn; - struct rip_distance *rdistance; - - ret = str2prefix_ipv4 (ip_str, &p); - if (ret == 0) - { - vty_out (vty, "Malformed prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - distance = atoi (distance_str); - - /* Get RIP distance node. */ - rn = route_node_get (rip_distance_table, (struct prefix *) &p); - if (rn->info) - { - rdistance = rn->info; - route_unlock_node (rn); - } - else - { - rdistance = rip_distance_new (); - rn->info = rdistance; - } - - /* Set distance value. */ - rdistance->distance = distance; - - /* Reset access-list configuration. */ - if (rdistance->access_list) - { - free (rdistance->access_list); - rdistance->access_list = NULL; - } - if (access_list_str) - rdistance->access_list = strdup (access_list_str); - - return CMD_SUCCESS; -} - -static int -rip_distance_unset (struct vty *vty, const char *distance_str, - const char *ip_str, const char *access_list_str) -{ - int ret; - struct prefix_ipv4 p; - struct route_node *rn; - struct rip_distance *rdistance; - - ret = str2prefix_ipv4 (ip_str, &p); - if (ret == 0) - { - vty_out (vty, "Malformed prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - rn = route_node_lookup (rip_distance_table, (struct prefix *)&p); - if (! rn) - { - vty_out (vty, "Can't find specified prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - rdistance = rn->info; - - if (rdistance->access_list) - free (rdistance->access_list); - rip_distance_free (rdistance); - - rn->info = NULL; - route_unlock_node (rn); - route_unlock_node (rn); - - return CMD_SUCCESS; +static void rip_distance_free(struct rip_distance *rdistance) +{ + XFREE(MTYPE_RIP_DISTANCE, rdistance); } -static void -rip_distance_reset (void) +static int rip_distance_set(struct vty *vty, const char *distance_str, + const char *ip_str, const char *access_list_str) { - struct route_node *rn; - struct rip_distance *rdistance; + int ret; + struct prefix_ipv4 p; + u_char distance; + struct route_node *rn; + struct rip_distance *rdistance; + + ret = str2prefix_ipv4(ip_str, &p); + if (ret == 0) { + vty_out(vty, "Malformed prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + distance = atoi(distance_str); + + /* Get RIP distance node. */ + rn = route_node_get(rip_distance_table, (struct prefix *)&p); + if (rn->info) { + rdistance = rn->info; + route_unlock_node(rn); + } else { + rdistance = rip_distance_new(); + rn->info = rdistance; + } + + /* Set distance value. */ + rdistance->distance = distance; + + /* Reset access-list configuration. */ + if (rdistance->access_list) { + free(rdistance->access_list); + rdistance->access_list = NULL; + } + if (access_list_str) + rdistance->access_list = strdup(access_list_str); + + return CMD_SUCCESS; +} + +static int rip_distance_unset(struct vty *vty, const char *distance_str, + const char *ip_str, const char *access_list_str) +{ + int ret; + struct prefix_ipv4 p; + struct route_node *rn; + struct rip_distance *rdistance; + + ret = str2prefix_ipv4(ip_str, &p); + if (ret == 0) { + vty_out(vty, "Malformed prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + rn = route_node_lookup(rip_distance_table, (struct prefix *)&p); + if (!rn) { + vty_out(vty, "Can't find specified prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + rdistance = rn->info; - for (rn = route_top (rip_distance_table); rn; rn = route_next (rn)) - if ((rdistance = rn->info) != NULL) - { if (rdistance->access_list) - free (rdistance->access_list); - rip_distance_free (rdistance); + free(rdistance->access_list); + rip_distance_free(rdistance); + rn->info = NULL; - route_unlock_node (rn); - } + route_unlock_node(rn); + route_unlock_node(rn); + + return CMD_SUCCESS; } -/* Apply RIP information to distance method. */ -u_char -rip_distance_apply (struct rip_info *rinfo) -{ - struct route_node *rn; - struct prefix_ipv4 p; - struct rip_distance *rdistance; - struct access_list *alist; - - if (! rip) - return 0; - - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefix = rinfo->from; - p.prefixlen = IPV4_MAX_BITLEN; - - /* Check source address. */ - rn = route_node_match (rip_distance_table, (struct prefix *) &p); - if (rn) - { - rdistance = rn->info; - route_unlock_node (rn); - - if (rdistance->access_list) - { - alist = access_list_lookup (AFI_IP, rdistance->access_list); - if (alist == NULL) - return 0; - if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY) - return 0; +static void rip_distance_reset(void) +{ + struct route_node *rn; + struct rip_distance *rdistance; - return rdistance->distance; + for (rn = route_top(rip_distance_table); rn; rn = route_next(rn)) + if ((rdistance = rn->info) != NULL) { + if (rdistance->access_list) + free(rdistance->access_list); + rip_distance_free(rdistance); + rn->info = NULL; + route_unlock_node(rn); + } +} + +/* Apply RIP information to distance method. */ +u_char rip_distance_apply(struct rip_info *rinfo) +{ + struct route_node *rn; + struct prefix_ipv4 p; + struct rip_distance *rdistance; + struct access_list *alist; + + if (!rip) + return 0; + + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefix = rinfo->from; + p.prefixlen = IPV4_MAX_BITLEN; + + /* Check source address. */ + rn = route_node_match(rip_distance_table, (struct prefix *)&p); + if (rn) { + rdistance = rn->info; + route_unlock_node(rn); + + if (rdistance->access_list) { + alist = access_list_lookup(AFI_IP, + rdistance->access_list); + if (alist == NULL) + return 0; + if (access_list_apply(alist, &rinfo->rp->p) + == FILTER_DENY) + return 0; + + return rdistance->distance; + } else + return rdistance->distance; } - else - return rdistance->distance; - } - if (rip->distance) - return rip->distance; + if (rip->distance) + return rip->distance; - return 0; + return 0; } -static void -rip_distance_show (struct vty *vty) -{ - struct route_node *rn; - struct rip_distance *rdistance; - int header = 1; - char buf[BUFSIZ]; - - vty_out (vty, " Distance: (default is %d)\n", - rip->distance ? rip->distance : ZEBRA_RIP_DISTANCE_DEFAULT); - - for (rn = route_top (rip_distance_table); rn; rn = route_next (rn)) - if ((rdistance = rn->info) != NULL) - { - if (header) - { - vty_out (vty," Address Distance List\n"); - header = 0; - } - sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen); - vty_out (vty, " %-20s %4d %s\n", - buf, rdistance->distance, - rdistance->access_list ? rdistance->access_list : ""); - } +static void rip_distance_show(struct vty *vty) +{ + struct route_node *rn; + struct rip_distance *rdistance; + int header = 1; + char buf[BUFSIZ]; + + vty_out(vty, " Distance: (default is %d)\n", + rip->distance ? rip->distance : ZEBRA_RIP_DISTANCE_DEFAULT); + + for (rn = route_top(rip_distance_table); rn; rn = route_next(rn)) + if ((rdistance = rn->info) != NULL) { + if (header) { + vty_out(vty, + " Address Distance List\n"); + header = 0; + } + sprintf(buf, "%s/%d", inet_ntoa(rn->p.u.prefix4), + rn->p.prefixlen); + vty_out(vty, " %-20s %4d %s\n", buf, + rdistance->distance, + rdistance->access_list ? rdistance->access_list + : ""); + } } DEFUN (rip_distance, @@ -3265,9 +3229,9 @@ DEFUN (rip_distance, "Administrative distance\n" "Distance value\n") { - int idx_number = 1; - rip->distance = atoi (argv[idx_number]->arg); - return CMD_SUCCESS; + int idx_number = 1; + rip->distance = atoi(argv[idx_number]->arg); + return CMD_SUCCESS; } DEFUN (no_rip_distance, @@ -3277,8 +3241,8 @@ DEFUN (no_rip_distance, "Administrative distance\n" "Distance value\n") { - rip->distance = 0; - return CMD_SUCCESS; + rip->distance = 0; + return CMD_SUCCESS; } DEFUN (rip_distance_source, @@ -3288,10 +3252,11 @@ DEFUN (rip_distance_source, "Distance value\n" "IP source prefix\n") { - int idx_number = 1; - int idx_ipv4_prefixlen = 2; - rip_distance_set (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, NULL); - return CMD_SUCCESS; + int idx_number = 1; + int idx_ipv4_prefixlen = 2; + rip_distance_set(vty, argv[idx_number]->arg, + argv[idx_ipv4_prefixlen]->arg, NULL); + return CMD_SUCCESS; } DEFUN (no_rip_distance_source, @@ -3302,10 +3267,11 @@ DEFUN (no_rip_distance_source, "Distance value\n" "IP source prefix\n") { - int idx_number = 2; - int idx_ipv4_prefixlen = 3; - rip_distance_unset (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, NULL); - return CMD_SUCCESS; + int idx_number = 2; + int idx_ipv4_prefixlen = 3; + rip_distance_unset(vty, argv[idx_number]->arg, + argv[idx_ipv4_prefixlen]->arg, NULL); + return CMD_SUCCESS; } DEFUN (rip_distance_source_access_list, @@ -3316,11 +3282,12 @@ DEFUN (rip_distance_source_access_list, "IP source prefix\n" "Access list name\n") { - int idx_number = 1; - int idx_ipv4_prefixlen = 2; - int idx_word = 3; - rip_distance_set (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg); - return CMD_SUCCESS; + int idx_number = 1; + int idx_ipv4_prefixlen = 2; + int idx_word = 3; + rip_distance_set(vty, argv[idx_number]->arg, + argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg); + return CMD_SUCCESS; } DEFUN (no_rip_distance_source_access_list, @@ -3332,51 +3299,50 @@ DEFUN (no_rip_distance_source_access_list, "IP source prefix\n" "Access list name\n") { - int idx_number = 2; - int idx_ipv4_prefixlen = 3; - int idx_word = 4; - rip_distance_unset (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg); - return CMD_SUCCESS; + int idx_number = 2; + int idx_ipv4_prefixlen = 3; + int idx_word = 4; + rip_distance_unset(vty, argv[idx_number]->arg, + argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg); + return CMD_SUCCESS; } /* Update ECMP routes to zebra when ECMP is disabled. */ -static void -rip_ecmp_disable (void) -{ - struct route_node *rp; - struct rip_info *rinfo, *tmp_rinfo; - struct list *list; - struct listnode *node, *nextnode; - - if (!rip) - return; - - for (rp = route_top (rip->table); rp; rp = route_next (rp)) - if ((list = rp->info) != NULL && listcount (list) > 1) - { - rinfo = listgetdata (listhead (list)); - if (!rip_route_rte (rinfo)) - continue; - - /* Drop all other entries, except the first one. */ - for (ALL_LIST_ELEMENTS (list, node, nextnode, tmp_rinfo)) - if (tmp_rinfo != rinfo) - { - RIP_TIMER_OFF (tmp_rinfo->t_timeout); - RIP_TIMER_OFF (tmp_rinfo->t_garbage_collect); - list_delete_node (list, node); - rip_info_free (tmp_rinfo); - } - - /* Update zebra. */ - rip_zebra_ipv4_add (rp); - - /* Set the route change flag. */ - SET_FLAG (rinfo->flags, RIP_RTF_CHANGED); - - /* Signal the output process to trigger an update. */ - rip_event (RIP_TRIGGERED_UPDATE, 0); - } +static void rip_ecmp_disable(void) +{ + struct route_node *rp; + struct rip_info *rinfo, *tmp_rinfo; + struct list *list; + struct listnode *node, *nextnode; + + if (!rip) + return; + + for (rp = route_top(rip->table); rp; rp = route_next(rp)) + if ((list = rp->info) != NULL && listcount(list) > 1) { + rinfo = listgetdata(listhead(list)); + if (!rip_route_rte(rinfo)) + continue; + + /* Drop all other entries, except the first one. */ + for (ALL_LIST_ELEMENTS(list, node, nextnode, tmp_rinfo)) + if (tmp_rinfo != rinfo) { + RIP_TIMER_OFF(tmp_rinfo->t_timeout); + RIP_TIMER_OFF( + tmp_rinfo->t_garbage_collect); + list_delete_node(list, node); + rip_info_free(tmp_rinfo); + } + + /* Update zebra. */ + rip_zebra_ipv4_add(rp); + + /* Set the route change flag. */ + SET_FLAG(rinfo->flags, RIP_RTF_CHANGED); + + /* Signal the output process to trigger an update. */ + rip_event(RIP_TRIGGERED_UPDATE, 0); + } } DEFUN (rip_allow_ecmp, @@ -3384,15 +3350,14 @@ DEFUN (rip_allow_ecmp, "allow-ecmp", "Allow Equal Cost MultiPath\n") { - if (rip->ecmp) - { - vty_out (vty, "ECMP is already enabled.\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (rip->ecmp) { + vty_out(vty, "ECMP is already enabled.\n"); + return CMD_WARNING_CONFIG_FAILED; + } - rip->ecmp = 1; - zlog_info ("ECMP is enabled."); - return CMD_SUCCESS; + rip->ecmp = 1; + zlog_info("ECMP is enabled."); + return CMD_SUCCESS; } DEFUN (no_rip_allow_ecmp, @@ -3401,62 +3366,55 @@ DEFUN (no_rip_allow_ecmp, NO_STR "Allow Equal Cost MultiPath\n") { - if (!rip->ecmp) - { - vty_out (vty, "ECMP is already disabled.\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!rip->ecmp) { + vty_out(vty, "ECMP is already disabled.\n"); + return CMD_WARNING_CONFIG_FAILED; + } - rip->ecmp = 0; - zlog_info ("ECMP is disabled."); - rip_ecmp_disable (); - return CMD_SUCCESS; + rip->ecmp = 0; + zlog_info("ECMP is disabled."); + rip_ecmp_disable(); + return CMD_SUCCESS; } /* Print out routes update time. */ -static void -rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo) +static void rip_vty_out_uptime(struct vty *vty, struct rip_info *rinfo) { - time_t clock; - struct tm *tm; + time_t clock; + struct tm *tm; #define TIME_BUF 25 - char timebuf [TIME_BUF]; - struct thread *thread; - - if ((thread = rinfo->t_timeout) != NULL) - { - clock = thread_timer_remain_second (thread); - tm = gmtime (&clock); - strftime (timebuf, TIME_BUF, "%M:%S", tm); - vty_out (vty, "%5s", timebuf); - } - else if ((thread = rinfo->t_garbage_collect) != NULL) - { - clock = thread_timer_remain_second (thread); - tm = gmtime (&clock); - strftime (timebuf, TIME_BUF, "%M:%S", tm); - vty_out (vty, "%5s", timebuf); - } -} - -static const char * -rip_route_type_print (int sub_type) -{ - switch (sub_type) - { - case RIP_ROUTE_RTE: - return "n"; - case RIP_ROUTE_STATIC: - return "s"; - case RIP_ROUTE_DEFAULT: - return "d"; - case RIP_ROUTE_REDISTRIBUTE: - return "r"; - case RIP_ROUTE_INTERFACE: - return "i"; - default: - return "?"; - } + char timebuf[TIME_BUF]; + struct thread *thread; + + if ((thread = rinfo->t_timeout) != NULL) { + clock = thread_timer_remain_second(thread); + tm = gmtime(&clock); + strftime(timebuf, TIME_BUF, "%M:%S", tm); + vty_out(vty, "%5s", timebuf); + } else if ((thread = rinfo->t_garbage_collect) != NULL) { + clock = thread_timer_remain_second(thread); + tm = gmtime(&clock); + strftime(timebuf, TIME_BUF, "%M:%S", tm); + vty_out(vty, "%5s", timebuf); + } +} + +static const char *rip_route_type_print(int sub_type) +{ + switch (sub_type) { + case RIP_ROUTE_RTE: + return "n"; + case RIP_ROUTE_STATIC: + return "s"; + case RIP_ROUTE_DEFAULT: + return "d"; + case RIP_ROUTE_REDISTRIBUTE: + return "r"; + case RIP_ROUTE_INTERFACE: + return "i"; + default: + return "?"; + } } DEFUN (show_ip_rip, @@ -3466,76 +3424,83 @@ DEFUN (show_ip_rip, IP_STR "Show RIP routes\n") { - struct route_node *np; - struct rip_info *rinfo = NULL; - struct list *list = NULL; - struct listnode *listnode = NULL; - - if (! rip) - return CMD_SUCCESS; - - vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP\n" - "Sub-codes:\n" - " (n) - normal, (s) - static, (d) - default, (r) - redistribute,\n" - " (i) - interface\n\n" - " Network Next Hop Metric From Tag Time\n"); - - for (np = route_top (rip->table); np; np = route_next (np)) - if ((list = np->info) != NULL) - for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) - { - int len; - - len = vty_out (vty, "%c(%s) %s/%d", - /* np->lock, For debugging. */ - zebra_route_char(rinfo->type), - rip_route_type_print (rinfo->sub_type), - inet_ntoa (np->p.u.prefix4), np->p.prefixlen); - - len = 24 - len; - - if (len > 0) - vty_out (vty, "%*s", len, " "); - - if (rinfo->nexthop.s_addr) - vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop), - rinfo->metric); - else - vty_out (vty, "0.0.0.0 %2d ", rinfo->metric); - - /* Route which exist in kernel routing table. */ - if ((rinfo->type == ZEBRA_ROUTE_RIP) && - (rinfo->sub_type == RIP_ROUTE_RTE)) - { - vty_out (vty, "%-15s ", inet_ntoa (rinfo->from)); - vty_out (vty, "%3"ROUTE_TAG_PRI" ", (route_tag_t)rinfo->tag); - rip_vty_out_uptime (vty, rinfo); - } - else if (rinfo->metric == RIP_METRIC_INFINITY) - { - vty_out (vty, "self "); - vty_out (vty, "%3"ROUTE_TAG_PRI" ", (route_tag_t)rinfo->tag); - rip_vty_out_uptime (vty, rinfo); - } - else - { - if (rinfo->external_metric) - { - len = vty_out (vty, "self (%s:%d)", - zebra_route_string(rinfo->type), - rinfo->external_metric); - len = 16 - len; - if (len > 0) - vty_out (vty, "%*s", len, " "); - } - else - vty_out (vty, "self "); - vty_out (vty, "%3"ROUTE_TAG_PRI, (route_tag_t)rinfo->tag); - } - - vty_out (vty, "\n"); - } - return CMD_SUCCESS; + struct route_node *np; + struct rip_info *rinfo = NULL; + struct list *list = NULL; + struct listnode *listnode = NULL; + + if (!rip) + return CMD_SUCCESS; + + vty_out(vty, + "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP\n" + "Sub-codes:\n" + " (n) - normal, (s) - static, (d) - default, (r) - redistribute,\n" + " (i) - interface\n\n" + " Network Next Hop Metric From Tag Time\n"); + + for (np = route_top(rip->table); np; np = route_next(np)) + if ((list = np->info) != NULL) + for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { + int len; + + len = vty_out( + vty, "%c(%s) %s/%d", + /* np->lock, For debugging. */ + zebra_route_char(rinfo->type), + rip_route_type_print(rinfo->sub_type), + inet_ntoa(np->p.u.prefix4), + np->p.prefixlen); + + len = 24 - len; + + if (len > 0) + vty_out(vty, "%*s", len, " "); + + if (rinfo->nexthop.s_addr) + vty_out(vty, "%-20s %2d ", + inet_ntoa(rinfo->nexthop), + rinfo->metric); + else + vty_out(vty, + "0.0.0.0 %2d ", + rinfo->metric); + + /* Route which exist in kernel routing table. */ + if ((rinfo->type == ZEBRA_ROUTE_RIP) + && (rinfo->sub_type == RIP_ROUTE_RTE)) { + vty_out(vty, "%-15s ", + inet_ntoa(rinfo->from)); + vty_out(vty, "%3" ROUTE_TAG_PRI " ", + (route_tag_t)rinfo->tag); + rip_vty_out_uptime(vty, rinfo); + } else if (rinfo->metric + == RIP_METRIC_INFINITY) { + vty_out(vty, "self "); + vty_out(vty, "%3" ROUTE_TAG_PRI " ", + (route_tag_t)rinfo->tag); + rip_vty_out_uptime(vty, rinfo); + } else { + if (rinfo->external_metric) { + len = vty_out( + vty, "self (%s:%d)", + zebra_route_string( + rinfo->type), + rinfo->external_metric); + len = 16 - len; + if (len > 0) + vty_out(vty, "%*s", len, + " "); + } else + vty_out(vty, + "self "); + vty_out(vty, "%3" ROUTE_TAG_PRI, + (route_tag_t)rinfo->tag); + } + + vty_out(vty, "\n"); + } + return CMD_SUCCESS; } /* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */ @@ -3547,534 +3512,508 @@ DEFUN (show_ip_rip_status, "Show RIP routes\n" "IP routing protocol process parameters and statistics\n") { - struct listnode *node; - struct interface *ifp; - struct rip_interface *ri; - extern const struct message ri_version_msg[]; - const char *send_version; - const char *receive_version; - - if (! rip) - return CMD_SUCCESS; - - vty_out (vty, "Routing Protocol is \"rip\"\n"); - vty_out (vty, " Sending updates every %ld seconds with +/-50%%,", - rip->update_time); - vty_out (vty, " next due in %lu seconds\n", - thread_timer_remain_second(rip->t_update)); - vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time); - vty_out (vty, " garbage collect after %ld seconds\n",rip->garbage_time); - - /* Filtering status show. */ - config_show_distribute (vty); - - /* Default metric information. */ - vty_out (vty, " Default redistribution metric is %d\n", - rip->default_metric); - - /* Redistribute information. */ - vty_out (vty, " Redistributing:"); - config_write_rip_redistribute (vty, 0); - vty_out (vty, "\n"); - - vty_out (vty, " Default version control: send version %s,", - lookup_msg(ri_version_msg,rip->version_send, NULL)); - if (rip->version_recv == RI_RIP_VERSION_1_AND_2) - vty_out (vty, " receive any version \n"); - else - vty_out (vty, " receive version %s \n", - lookup_msg(ri_version_msg,rip->version_recv, NULL)); - - vty_out (vty, " Interface Send Recv Key-chain\n"); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - ri = ifp->info; - - if (!ri->running) - continue; - - if (ri->enable_network || ri->enable_interface) - { - if (ri->ri_send == RI_RIP_UNSPEC) - send_version = lookup_msg(ri_version_msg, rip->version_send, NULL); - else - send_version = lookup_msg(ri_version_msg, ri->ri_send, NULL); - - if (ri->ri_receive == RI_RIP_UNSPEC) - receive_version = lookup_msg(ri_version_msg, rip->version_recv, NULL); - else - receive_version = lookup_msg(ri_version_msg, ri->ri_receive, NULL); - - vty_out (vty, " %-17s%-3s %-3s %s\n", ifp->name, - send_version, - receive_version, - ri->key_chain ? ri->key_chain : ""); - } - } - - vty_out (vty, " Routing for Networks:\n"); - config_write_rip_network (vty, 0); - - { - int found_passive = 0; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - ri = ifp->info; - - if ((ri->enable_network || ri->enable_interface) && ri->passive) - { - if (!found_passive) - { - vty_out (vty, " Passive Interface(s):\n"); - found_passive = 1; - } - vty_out (vty, " %s\n", ifp->name); - } - } - } - - vty_out (vty, " Routing Information Sources:\n"); - vty_out (vty, - " Gateway BadPackets BadRoutes Distance Last Update\n"); - rip_peer_display (vty); - - rip_distance_show (vty); + struct listnode *node; + struct interface *ifp; + struct rip_interface *ri; + extern const struct message ri_version_msg[]; + const char *send_version; + const char *receive_version; + + if (!rip) + return CMD_SUCCESS; + + vty_out(vty, "Routing Protocol is \"rip\"\n"); + vty_out(vty, " Sending updates every %ld seconds with +/-50%%,", + rip->update_time); + vty_out(vty, " next due in %lu seconds\n", + thread_timer_remain_second(rip->t_update)); + vty_out(vty, " Timeout after %ld seconds,", rip->timeout_time); + vty_out(vty, " garbage collect after %ld seconds\n", rip->garbage_time); + + /* Filtering status show. */ + config_show_distribute(vty); + + /* Default metric information. */ + vty_out(vty, " Default redistribution metric is %d\n", + rip->default_metric); + + /* Redistribute information. */ + vty_out(vty, " Redistributing:"); + config_write_rip_redistribute(vty, 0); + vty_out(vty, "\n"); + + vty_out(vty, " Default version control: send version %s,", + lookup_msg(ri_version_msg, rip->version_send, NULL)); + if (rip->version_recv == RI_RIP_VERSION_1_AND_2) + vty_out(vty, " receive any version \n"); + else + vty_out(vty, " receive version %s \n", + lookup_msg(ri_version_msg, rip->version_recv, NULL)); + + vty_out(vty, " Interface Send Recv Key-chain\n"); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + ri = ifp->info; + + if (!ri->running) + continue; + + if (ri->enable_network || ri->enable_interface) { + if (ri->ri_send == RI_RIP_UNSPEC) + send_version = + lookup_msg(ri_version_msg, + rip->version_send, NULL); + else + send_version = lookup_msg(ri_version_msg, + ri->ri_send, NULL); + + if (ri->ri_receive == RI_RIP_UNSPEC) + receive_version = + lookup_msg(ri_version_msg, + rip->version_recv, NULL); + else + receive_version = lookup_msg( + ri_version_msg, ri->ri_receive, NULL); + + vty_out(vty, " %-17s%-3s %-3s %s\n", ifp->name, + send_version, receive_version, + ri->key_chain ? ri->key_chain : ""); + } + } - return CMD_SUCCESS; -} + vty_out(vty, " Routing for Networks:\n"); + config_write_rip_network(vty, 0); -/* RIP configuration write function. */ -static int -config_write_rip (struct vty *vty) -{ - int write = 0; - struct route_node *rn; - struct rip_distance *rdistance; - - if (rip) - { - /* Router RIP statement. */ - vty_out (vty, "router rip\n"); - write++; - - /* RIP version statement. Default is RIP version 2. */ - if (rip->version_send != RI_RIP_VERSION_2 - || rip->version_recv != RI_RIP_VERSION_1_AND_2) - vty_out (vty, " version %d\n",rip->version_send); - - /* RIP timer configuration. */ - if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT - || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT - || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT) - vty_out (vty, " timers basic %lu %lu %lu\n", - rip->update_time, - rip->timeout_time, - rip->garbage_time); - - /* Default information configuration. */ - if (rip->default_information) { - if (rip->default_information_route_map) - vty_out (vty, " default-information originate route-map %s\n", - rip->default_information_route_map); - else - vty_out (vty," default-information originate\n"); + int found_passive = 0; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + ri = ifp->info; + + if ((ri->enable_network || ri->enable_interface) + && ri->passive) { + if (!found_passive) { + vty_out(vty, + " Passive Interface(s):\n"); + found_passive = 1; + } + vty_out(vty, " %s\n", ifp->name); + } + } } - /* Redistribute configuration. */ - config_write_rip_redistribute (vty, 1); - - /* RIP offset-list configuration. */ - config_write_rip_offset_list (vty); + vty_out(vty, " Routing Information Sources:\n"); + vty_out(vty, + " Gateway BadPackets BadRoutes Distance Last Update\n"); + rip_peer_display(vty); - /* RIP enabled network and interface configuration. */ - config_write_rip_network (vty, 1); - - /* RIP default metric configuration */ - if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT) - vty_out (vty, " default-metric %d\n", - rip->default_metric); + rip_distance_show(vty); - /* Distribute configuration. */ - write += config_write_distribute (vty); + return CMD_SUCCESS; +} - /* Interface routemap configuration */ - write += config_write_if_rmap (vty); +/* RIP configuration write function. */ +static int config_write_rip(struct vty *vty) +{ + int write = 0; + struct route_node *rn; + struct rip_distance *rdistance; + + if (rip) { + /* Router RIP statement. */ + vty_out(vty, "router rip\n"); + write++; + + /* RIP version statement. Default is RIP version 2. */ + if (rip->version_send != RI_RIP_VERSION_2 + || rip->version_recv != RI_RIP_VERSION_1_AND_2) + vty_out(vty, " version %d\n", rip->version_send); + + /* RIP timer configuration. */ + if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT + || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT + || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT) + vty_out(vty, " timers basic %lu %lu %lu\n", + rip->update_time, rip->timeout_time, + rip->garbage_time); + + /* Default information configuration. */ + if (rip->default_information) { + if (rip->default_information_route_map) + vty_out(vty, + " default-information originate route-map %s\n", + rip->default_information_route_map); + else + vty_out(vty, + " default-information originate\n"); + } - /* Distance configuration. */ - if (rip->distance) - vty_out (vty, " distance %d\n", rip->distance); + /* Redistribute configuration. */ + config_write_rip_redistribute(vty, 1); + + /* RIP offset-list configuration. */ + config_write_rip_offset_list(vty); + + /* RIP enabled network and interface configuration. */ + config_write_rip_network(vty, 1); + + /* RIP default metric configuration */ + if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT) + vty_out(vty, " default-metric %d\n", + rip->default_metric); + + /* Distribute configuration. */ + write += config_write_distribute(vty); + + /* Interface routemap configuration */ + write += config_write_if_rmap(vty); + + /* Distance configuration. */ + if (rip->distance) + vty_out(vty, " distance %d\n", rip->distance); + + /* RIP source IP prefix distance configuration. */ + for (rn = route_top(rip_distance_table); rn; + rn = route_next(rn)) + if ((rdistance = rn->info) != NULL) + vty_out(vty, " distance %d %s/%d %s\n", + rdistance->distance, + inet_ntoa(rn->p.u.prefix4), + rn->p.prefixlen, + rdistance->access_list + ? rdistance->access_list + : ""); + + /* ECMP configuration. */ + if (rip->ecmp) + vty_out(vty, " allow-ecmp\n"); + + /* RIP static route configuration. */ + for (rn = route_top(rip->route); rn; rn = route_next(rn)) + if (rn->info) + vty_out(vty, " route %s/%d\n", + inet_ntoa(rn->p.u.prefix4), + rn->p.prefixlen); + } + return write; +} - /* RIP source IP prefix distance configuration. */ - for (rn = route_top (rip_distance_table); rn; rn = route_next (rn)) - if ((rdistance = rn->info) != NULL) - vty_out (vty, " distance %d %s/%d %s\n", rdistance->distance, - inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen, - rdistance->access_list ? rdistance->access_list : ""); +/* RIP node structure. */ +static struct cmd_node rip_node = {RIP_NODE, "%s(config-router)# ", 1}; - /* ECMP configuration. */ - if (rip->ecmp) - vty_out (vty, " allow-ecmp\n"); +/* Distribute-list update functions. */ +static void rip_distribute_update(struct distribute *dist) +{ + struct interface *ifp; + struct rip_interface *ri; + struct access_list *alist; + struct prefix_list *plist; - /* RIP static route configuration. */ - for (rn = route_top (rip->route); rn; rn = route_next (rn)) - if (rn->info) - vty_out (vty, " route %s/%d\n", - inet_ntoa (rn->p.u.prefix4), - rn->p.prefixlen); + if (!dist->ifname) + return; - } - return write; -} + ifp = if_lookup_by_name(dist->ifname, VRF_DEFAULT); + if (ifp == NULL) + return; -/* RIP node structure. */ -static struct cmd_node rip_node = -{ - RIP_NODE, - "%s(config-router)# ", - 1 -}; + ri = ifp->info; -/* Distribute-list update functions. */ -static void -rip_distribute_update (struct distribute *dist) -{ - struct interface *ifp; - struct rip_interface *ri; - struct access_list *alist; - struct prefix_list *plist; - - if (! dist->ifname) - return; - - ifp = if_lookup_by_name (dist->ifname, VRF_DEFAULT); - if (ifp == NULL) - return; - - ri = ifp->info; - - if (dist->list[DISTRIBUTE_V4_IN]) - { - alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_V4_IN]); - if (alist) - ri->list[RIP_FILTER_IN] = alist; - else - ri->list[RIP_FILTER_IN] = NULL; - } - else - ri->list[RIP_FILTER_IN] = NULL; - - if (dist->list[DISTRIBUTE_V4_OUT]) - { - alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_V4_OUT]); - if (alist) - ri->list[RIP_FILTER_OUT] = alist; - else - ri->list[RIP_FILTER_OUT] = NULL; - } - else - ri->list[RIP_FILTER_OUT] = NULL; - - if (dist->prefix[DISTRIBUTE_V4_IN]) - { - plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_V4_IN]); - if (plist) - ri->prefix[RIP_FILTER_IN] = plist; - else - ri->prefix[RIP_FILTER_IN] = NULL; - } - else - ri->prefix[RIP_FILTER_IN] = NULL; - - if (dist->prefix[DISTRIBUTE_V4_OUT]) - { - plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_V4_OUT]); - if (plist) - ri->prefix[RIP_FILTER_OUT] = plist; - else - ri->prefix[RIP_FILTER_OUT] = NULL; - } - else - ri->prefix[RIP_FILTER_OUT] = NULL; -} - -void -rip_distribute_update_interface (struct interface *ifp) -{ - struct distribute *dist; - - dist = distribute_lookup (ifp->name); - if (dist) - rip_distribute_update (dist); + if (dist->list[DISTRIBUTE_V4_IN]) { + alist = access_list_lookup(AFI_IP, + dist->list[DISTRIBUTE_V4_IN]); + if (alist) + ri->list[RIP_FILTER_IN] = alist; + else + ri->list[RIP_FILTER_IN] = NULL; + } else + ri->list[RIP_FILTER_IN] = NULL; + + if (dist->list[DISTRIBUTE_V4_OUT]) { + alist = access_list_lookup(AFI_IP, + dist->list[DISTRIBUTE_V4_OUT]); + if (alist) + ri->list[RIP_FILTER_OUT] = alist; + else + ri->list[RIP_FILTER_OUT] = NULL; + } else + ri->list[RIP_FILTER_OUT] = NULL; + + if (dist->prefix[DISTRIBUTE_V4_IN]) { + plist = prefix_list_lookup(AFI_IP, + dist->prefix[DISTRIBUTE_V4_IN]); + if (plist) + ri->prefix[RIP_FILTER_IN] = plist; + else + ri->prefix[RIP_FILTER_IN] = NULL; + } else + ri->prefix[RIP_FILTER_IN] = NULL; + + if (dist->prefix[DISTRIBUTE_V4_OUT]) { + plist = prefix_list_lookup(AFI_IP, + dist->prefix[DISTRIBUTE_V4_OUT]); + if (plist) + ri->prefix[RIP_FILTER_OUT] = plist; + else + ri->prefix[RIP_FILTER_OUT] = NULL; + } else + ri->prefix[RIP_FILTER_OUT] = NULL; +} + +void rip_distribute_update_interface(struct interface *ifp) +{ + struct distribute *dist; + + dist = distribute_lookup(ifp->name); + if (dist) + rip_distribute_update(dist); } /* Update all interface's distribute list. */ /* ARGSUSED */ -static void -rip_distribute_update_all (struct prefix_list *notused) +static void rip_distribute_update_all(struct prefix_list *notused) { - struct interface *ifp; - struct listnode *node, *nnode; + struct interface *ifp; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp)) - rip_distribute_update_interface (ifp); + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), node, nnode, ifp)) + rip_distribute_update_interface(ifp); } /* ARGSUSED */ -static void -rip_distribute_update_all_wrapper(struct access_list *notused) +static void rip_distribute_update_all_wrapper(struct access_list *notused) { - rip_distribute_update_all(NULL); + rip_distribute_update_all(NULL); } /* Delete all added rip route. */ -void -rip_clean (void) +void rip_clean(void) { - int i; - struct route_node *rp; - struct rip_info *rinfo = NULL; - struct list *list = NULL; - struct listnode *listnode = NULL; + int i; + struct route_node *rp; + struct rip_info *rinfo = NULL; + struct list *list = NULL; + struct listnode *listnode = NULL; + + if (rip) { + QOBJ_UNREG(rip); + + /* Clear RIP routes */ + for (rp = route_top(rip->table); rp; rp = route_next(rp)) + if ((list = rp->info) != NULL) { + rinfo = listgetdata(listhead(list)); + if (rip_route_rte(rinfo)) + rip_zebra_ipv4_delete(rp); + + for (ALL_LIST_ELEMENTS_RO(list, listnode, + rinfo)) { + RIP_TIMER_OFF(rinfo->t_timeout); + RIP_TIMER_OFF(rinfo->t_garbage_collect); + rip_info_free(rinfo); + } + list_delete(list); + rp->info = NULL; + route_unlock_node(rp); + } + + /* Cancel RIP related timers. */ + RIP_TIMER_OFF(rip->t_update); + RIP_TIMER_OFF(rip->t_triggered_update); + RIP_TIMER_OFF(rip->t_triggered_interval); + + /* Cancel read thread. */ + THREAD_READ_OFF(rip->t_read); + + /* Close RIP socket. */ + if (rip->sock >= 0) { + close(rip->sock); + rip->sock = -1; + } - if (rip) - { - QOBJ_UNREG (rip); - - /* Clear RIP routes */ - for (rp = route_top (rip->table); rp; rp = route_next (rp)) - if ((list = rp->info) != NULL) - { - rinfo = listgetdata (listhead (list)); - if (rip_route_rte (rinfo)) - rip_zebra_ipv4_delete (rp); - - for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) - { - RIP_TIMER_OFF (rinfo->t_timeout); - RIP_TIMER_OFF (rinfo->t_garbage_collect); - rip_info_free (rinfo); - } - list_delete (list); - rp->info = NULL; - route_unlock_node (rp); - } - - /* Cancel RIP related timers. */ - RIP_TIMER_OFF (rip->t_update); - RIP_TIMER_OFF (rip->t_triggered_update); - RIP_TIMER_OFF (rip->t_triggered_interval); - - /* Cancel read thread. */ - THREAD_READ_OFF (rip->t_read); - - /* Close RIP socket. */ - if (rip->sock >= 0) - { - close (rip->sock); - rip->sock = -1; - } - - /* Static RIP route configuration. */ - for (rp = route_top (rip->route); rp; rp = route_next (rp)) - if (rp->info) - { - rp->info = NULL; - route_unlock_node (rp); - } - - /* RIP neighbor configuration. */ - for (rp = route_top (rip->neighbor); rp; rp = route_next (rp)) - if (rp->info) - { - rp->info = NULL; - route_unlock_node (rp); - } - - /* Redistribute related clear. */ - if (rip->default_information_route_map) - free (rip->default_information_route_map); - - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (rip->route_map[i].name) - free (rip->route_map[i].name); - - XFREE (MTYPE_ROUTE_TABLE, rip->table); - XFREE (MTYPE_ROUTE_TABLE, rip->route); - XFREE (MTYPE_ROUTE_TABLE, rip->neighbor); - - XFREE (MTYPE_RIP, rip); - rip = NULL; - } - - rip_clean_network (); - rip_passive_nondefault_clean (); - rip_offset_clean (); - rip_interfaces_clean (); - rip_distance_reset (); - rip_redistribute_clean (); + /* Static RIP route configuration. */ + for (rp = route_top(rip->route); rp; rp = route_next(rp)) + if (rp->info) { + rp->info = NULL; + route_unlock_node(rp); + } + + /* RIP neighbor configuration. */ + for (rp = route_top(rip->neighbor); rp; rp = route_next(rp)) + if (rp->info) { + rp->info = NULL; + route_unlock_node(rp); + } + + /* Redistribute related clear. */ + if (rip->default_information_route_map) + free(rip->default_information_route_map); + + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (rip->route_map[i].name) + free(rip->route_map[i].name); + + XFREE(MTYPE_ROUTE_TABLE, rip->table); + XFREE(MTYPE_ROUTE_TABLE, rip->route); + XFREE(MTYPE_ROUTE_TABLE, rip->neighbor); + + XFREE(MTYPE_RIP, rip); + rip = NULL; + } + + rip_clean_network(); + rip_passive_nondefault_clean(); + rip_offset_clean(); + rip_interfaces_clean(); + rip_distance_reset(); + rip_redistribute_clean(); } /* Reset all values to the default settings. */ -void -rip_reset (void) +void rip_reset(void) { - /* Reset global counters. */ - rip_global_route_changes = 0; - rip_global_queries = 0; + /* Reset global counters. */ + rip_global_route_changes = 0; + rip_global_queries = 0; - /* Call ripd related reset functions. */ - rip_debug_reset (); - rip_route_map_reset (); + /* Call ripd related reset functions. */ + rip_debug_reset(); + rip_route_map_reset(); - /* Call library reset functions. */ - vty_reset (); - access_list_reset (); - prefix_list_reset (); + /* Call library reset functions. */ + vty_reset(); + access_list_reset(); + prefix_list_reset(); - distribute_list_reset (); + distribute_list_reset(); - rip_interfaces_reset (); - rip_distance_reset (); + rip_interfaces_reset(); + rip_distance_reset(); - rip_zclient_reset (); + rip_zclient_reset(); } -static void -rip_if_rmap_update (struct if_rmap *if_rmap) +static void rip_if_rmap_update(struct if_rmap *if_rmap) { - struct interface *ifp; - struct rip_interface *ri; - struct route_map *rmap; + struct interface *ifp; + struct rip_interface *ri; + struct route_map *rmap; - ifp = if_lookup_by_name (if_rmap->ifname, VRF_DEFAULT); - if (ifp == NULL) - return; + ifp = if_lookup_by_name(if_rmap->ifname, VRF_DEFAULT); + if (ifp == NULL) + return; - ri = ifp->info; + ri = ifp->info; - if (if_rmap->routemap[IF_RMAP_IN]) - { - rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]); - if (rmap) - ri->routemap[IF_RMAP_IN] = rmap; - else - ri->routemap[IF_RMAP_IN] = NULL; - } - else - ri->routemap[RIP_FILTER_IN] = NULL; + if (if_rmap->routemap[IF_RMAP_IN]) { + rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_IN]); + if (rmap) + ri->routemap[IF_RMAP_IN] = rmap; + else + ri->routemap[IF_RMAP_IN] = NULL; + } else + ri->routemap[RIP_FILTER_IN] = NULL; - if (if_rmap->routemap[IF_RMAP_OUT]) - { - rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]); - if (rmap) - ri->routemap[IF_RMAP_OUT] = rmap; - else - ri->routemap[IF_RMAP_OUT] = NULL; - } - else - ri->routemap[RIP_FILTER_OUT] = NULL; + if (if_rmap->routemap[IF_RMAP_OUT]) { + rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_OUT]); + if (rmap) + ri->routemap[IF_RMAP_OUT] = rmap; + else + ri->routemap[IF_RMAP_OUT] = NULL; + } else + ri->routemap[RIP_FILTER_OUT] = NULL; } -void -rip_if_rmap_update_interface (struct interface *ifp) +void rip_if_rmap_update_interface(struct interface *ifp) { - struct if_rmap *if_rmap; + struct if_rmap *if_rmap; - if_rmap = if_rmap_lookup (ifp->name); - if (if_rmap) - rip_if_rmap_update (if_rmap); + if_rmap = if_rmap_lookup(ifp->name); + if (if_rmap) + rip_if_rmap_update(if_rmap); } -static void -rip_routemap_update_redistribute (void) +static void rip_routemap_update_redistribute(void) { - int i; + int i; - if (rip) - { - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - if (rip->route_map[i].name) - rip->route_map[i].map = - route_map_lookup_by_name (rip->route_map[i].name); + if (rip) { + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (rip->route_map[i].name) + rip->route_map[i].map = + route_map_lookup_by_name( + rip->route_map[i].name); + } } - } } /* ARGSUSED */ -static void -rip_routemap_update (const char *notused) +static void rip_routemap_update(const char *notused) { - struct interface *ifp; - struct listnode *node, *nnode; + struct interface *ifp; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp)) - rip_if_rmap_update_interface (ifp); + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), node, nnode, ifp)) + rip_if_rmap_update_interface(ifp); - rip_routemap_update_redistribute (); + rip_routemap_update_redistribute(); } /* Allocate new rip structure and set default value. */ -void -rip_init (void) -{ - /* Install top nodes. */ - install_node (&rip_node, config_write_rip); - - /* Install rip commands. */ - install_element (VIEW_NODE, &show_ip_rip_cmd); - install_element (VIEW_NODE, &show_ip_rip_status_cmd); - install_element (CONFIG_NODE, &router_rip_cmd); - install_element (CONFIG_NODE, &no_router_rip_cmd); - - install_default (RIP_NODE); - install_element (RIP_NODE, &rip_version_cmd); - install_element (RIP_NODE, &no_rip_version_cmd); - install_element (RIP_NODE, &rip_default_metric_cmd); - install_element (RIP_NODE, &no_rip_default_metric_cmd); - install_element (RIP_NODE, &rip_timers_cmd); - install_element (RIP_NODE, &no_rip_timers_cmd); - install_element (RIP_NODE, &rip_route_cmd); - install_element (RIP_NODE, &no_rip_route_cmd); - install_element (RIP_NODE, &rip_distance_cmd); - install_element (RIP_NODE, &no_rip_distance_cmd); - install_element (RIP_NODE, &rip_distance_source_cmd); - install_element (RIP_NODE, &no_rip_distance_source_cmd); - install_element (RIP_NODE, &rip_distance_source_access_list_cmd); - install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd); - install_element (RIP_NODE, &rip_allow_ecmp_cmd); - install_element (RIP_NODE, &no_rip_allow_ecmp_cmd); - - /* Debug related init. */ - rip_debug_init (); - - /* Access list install. */ - access_list_init (); - access_list_add_hook (rip_distribute_update_all_wrapper); - access_list_delete_hook (rip_distribute_update_all_wrapper); - - /* Prefix list initialize.*/ - prefix_list_init (); - prefix_list_add_hook (rip_distribute_update_all); - prefix_list_delete_hook (rip_distribute_update_all); - - /* Distribute list install. */ - distribute_list_init (RIP_NODE); - distribute_list_add_hook (rip_distribute_update); - distribute_list_delete_hook (rip_distribute_update); - - /* Route-map */ - rip_route_map_init (); - rip_offset_init (); - - route_map_add_hook (rip_routemap_update); - route_map_delete_hook (rip_routemap_update); - - if_rmap_init (RIP_NODE); - if_rmap_hook_add (rip_if_rmap_update); - if_rmap_hook_delete (rip_if_rmap_update); - - /* Distance control. */ - rip_distance_table = route_table_init (); +void rip_init(void) +{ + /* Install top nodes. */ + install_node(&rip_node, config_write_rip); + + /* Install rip commands. */ + install_element(VIEW_NODE, &show_ip_rip_cmd); + install_element(VIEW_NODE, &show_ip_rip_status_cmd); + install_element(CONFIG_NODE, &router_rip_cmd); + install_element(CONFIG_NODE, &no_router_rip_cmd); + + install_default(RIP_NODE); + install_element(RIP_NODE, &rip_version_cmd); + install_element(RIP_NODE, &no_rip_version_cmd); + install_element(RIP_NODE, &rip_default_metric_cmd); + install_element(RIP_NODE, &no_rip_default_metric_cmd); + install_element(RIP_NODE, &rip_timers_cmd); + install_element(RIP_NODE, &no_rip_timers_cmd); + install_element(RIP_NODE, &rip_route_cmd); + install_element(RIP_NODE, &no_rip_route_cmd); + install_element(RIP_NODE, &rip_distance_cmd); + install_element(RIP_NODE, &no_rip_distance_cmd); + install_element(RIP_NODE, &rip_distance_source_cmd); + install_element(RIP_NODE, &no_rip_distance_source_cmd); + install_element(RIP_NODE, &rip_distance_source_access_list_cmd); + install_element(RIP_NODE, &no_rip_distance_source_access_list_cmd); + install_element(RIP_NODE, &rip_allow_ecmp_cmd); + install_element(RIP_NODE, &no_rip_allow_ecmp_cmd); + + /* Debug related init. */ + rip_debug_init(); + + /* Access list install. */ + access_list_init(); + access_list_add_hook(rip_distribute_update_all_wrapper); + access_list_delete_hook(rip_distribute_update_all_wrapper); + + /* Prefix list initialize.*/ + prefix_list_init(); + prefix_list_add_hook(rip_distribute_update_all); + prefix_list_delete_hook(rip_distribute_update_all); + + /* Distribute list install. */ + distribute_list_init(RIP_NODE); + distribute_list_add_hook(rip_distribute_update); + distribute_list_delete_hook(rip_distribute_update); + + /* Route-map */ + rip_route_map_init(); + rip_offset_init(); + + route_map_add_hook(rip_routemap_update); + route_map_delete_hook(rip_routemap_update); + + if_rmap_init(RIP_NODE); + if_rmap_hook_add(rip_if_rmap_update); + if_rmap_hook_delete(rip_if_rmap_update); + + /* Distance control. */ + rip_distance_table = route_table_init(); } diff --git a/ripd/ripd.h b/ripd/ripd.h index a8e65d123..895a48c3d 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -98,255 +98,245 @@ #define RIP_AUTH_MD5_COMPAT_SIZE RIP_RTE_SIZE /* RIP structure. */ -struct rip -{ - /* RIP socket. */ - int sock; - - /* Default version of rip instance. */ - int version_send; /* version 1 or 2 (but not both) */ - int version_recv; /* version 1 or 2 or both */ - - /* Output buffer of RIP. */ - struct stream *obuf; - - /* RIP routing information base. */ - struct route_table *table; - - /* RIP only static routing information. */ - struct route_table *route; - - /* RIP neighbor. */ - struct route_table *neighbor; - - /* RIP threads. */ - struct thread *t_read; - - /* Update and garbage timer. */ - struct thread *t_update; - - /* Triggered update hack. */ - int trigger; - struct thread *t_triggered_update; - struct thread *t_triggered_interval; - - /* RIP timer values. */ - unsigned long update_time; - unsigned long timeout_time; - unsigned long garbage_time; - - /* RIP default metric. */ - int default_metric; - - /* RIP default-information originate. */ - u_char default_information; - char *default_information_route_map; - - /* RIP default distance. */ - u_char distance; - struct route_table *distance_table; - - /* RIP ECMP flag */ - unsigned int ecmp; - - /* For redistribute route map. */ - struct - { - char *name; - struct route_map *map; - int metric_config; - u_int32_t metric; - } route_map[ZEBRA_ROUTE_MAX]; - - QOBJ_FIELDS +struct rip { + /* RIP socket. */ + int sock; + + /* Default version of rip instance. */ + int version_send; /* version 1 or 2 (but not both) */ + int version_recv; /* version 1 or 2 or both */ + + /* Output buffer of RIP. */ + struct stream *obuf; + + /* RIP routing information base. */ + struct route_table *table; + + /* RIP only static routing information. */ + struct route_table *route; + + /* RIP neighbor. */ + struct route_table *neighbor; + + /* RIP threads. */ + struct thread *t_read; + + /* Update and garbage timer. */ + struct thread *t_update; + + /* Triggered update hack. */ + int trigger; + struct thread *t_triggered_update; + struct thread *t_triggered_interval; + + /* RIP timer values. */ + unsigned long update_time; + unsigned long timeout_time; + unsigned long garbage_time; + + /* RIP default metric. */ + int default_metric; + + /* RIP default-information originate. */ + u_char default_information; + char *default_information_route_map; + + /* RIP default distance. */ + u_char distance; + struct route_table *distance_table; + + /* RIP ECMP flag */ + unsigned int ecmp; + + /* For redistribute route map. */ + struct { + char *name; + struct route_map *map; + int metric_config; + u_int32_t metric; + } route_map[ZEBRA_ROUTE_MAX]; + + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(rip) /* RIP routing table entry which belong to rip_packet. */ -struct rte -{ - u_int16_t family; /* Address family of this route. */ - u_int16_t tag; /* Route Tag which included in RIP2 packet. */ - struct in_addr prefix; /* Prefix of rip route. */ - struct in_addr mask; /* Netmask of rip route. */ - struct in_addr nexthop; /* Next hop of rip route. */ - u_int32_t metric; /* Metric value of rip route. */ +struct rte { + u_int16_t family; /* Address family of this route. */ + u_int16_t tag; /* Route Tag which included in RIP2 packet. */ + struct in_addr prefix; /* Prefix of rip route. */ + struct in_addr mask; /* Netmask of rip route. */ + struct in_addr nexthop; /* Next hop of rip route. */ + u_int32_t metric; /* Metric value of rip route. */ }; /* RIP packet structure. */ -struct rip_packet -{ - unsigned char command; /* Command type of RIP packet. */ - unsigned char version; /* RIP version which coming from peer. */ - unsigned char pad1; /* Padding of RIP packet header. */ - unsigned char pad2; /* Same as above. */ - struct rte rte[1]; /* Address structure. */ +struct rip_packet { + unsigned char command; /* Command type of RIP packet. */ + unsigned char version; /* RIP version which coming from peer. */ + unsigned char pad1; /* Padding of RIP packet header. */ + unsigned char pad2; /* Same as above. */ + struct rte rte[1]; /* Address structure. */ }; /* Buffer to read RIP packet. */ -union rip_buf -{ - struct rip_packet rip_packet; - char buf[RIP_PACKET_MAXSIZ]; +union rip_buf { + struct rip_packet rip_packet; + char buf[RIP_PACKET_MAXSIZ]; }; /* RIP route information. */ -struct rip_info -{ - /* This route's type. */ - int type; +struct rip_info { + /* This route's type. */ + int type; - /* Sub type. */ - int sub_type; + /* Sub type. */ + int sub_type; - /* RIP nexthop. */ - struct in_addr nexthop; - struct in_addr from; + /* RIP nexthop. */ + struct in_addr nexthop; + struct in_addr from; - /* Which interface does this route come from. */ - ifindex_t ifindex; + /* Which interface does this route come from. */ + ifindex_t ifindex; - /* Metric of this route. */ - u_int32_t metric; + /* Metric of this route. */ + u_int32_t metric; - /* External metric of this route. - if learnt from an externalm proto */ - u_int32_t external_metric; + /* External metric of this route. + if learnt from an externalm proto */ + u_int32_t external_metric; - /* Tag information of this route. */ - u_int16_t tag; + /* Tag information of this route. */ + u_int16_t tag; - /* Flags of RIP route. */ +/* Flags of RIP route. */ #define RIP_RTF_FIB 1 #define RIP_RTF_CHANGED 2 - u_char flags; + u_char flags; - /* Garbage collect timer. */ - struct thread *t_timeout; - struct thread *t_garbage_collect; + /* Garbage collect timer. */ + struct thread *t_timeout; + struct thread *t_garbage_collect; - /* Route-map futures - this variables can be changed. */ - struct in_addr nexthop_out; - u_char metric_set; - u_int32_t metric_out; - u_int16_t tag_out; - ifindex_t ifindex_out; + /* Route-map futures - this variables can be changed. */ + struct in_addr nexthop_out; + u_char metric_set; + u_int32_t metric_out; + u_int16_t tag_out; + ifindex_t ifindex_out; - struct route_node *rp; + struct route_node *rp; - u_char distance; + u_char distance; #ifdef NEW_RIP_TABLE - struct rip_info *next; - struct rip_info *prev; + struct rip_info *next; + struct rip_info *prev; #endif /* NEW_RIP_TABLE */ }; typedef enum { - RIP_NO_SPLIT_HORIZON = 0, - RIP_SPLIT_HORIZON, - RIP_SPLIT_HORIZON_POISONED_REVERSE + RIP_NO_SPLIT_HORIZON = 0, + RIP_SPLIT_HORIZON, + RIP_SPLIT_HORIZON_POISONED_REVERSE } split_horizon_policy_t; /* RIP specific interface configuration. */ -struct rip_interface -{ - /* RIP is enabled on this interface. */ - int enable_network; - int enable_interface; +struct rip_interface { + /* RIP is enabled on this interface. */ + int enable_network; + int enable_interface; - /* RIP is running on this interface. */ - int running; + /* RIP is running on this interface. */ + int running; - /* RIP version control. */ - int ri_send; - int ri_receive; + /* RIP version control. */ + int ri_send; + int ri_receive; - /* RIPv2 broadcast mode */ - int v2_broadcast; + /* RIPv2 broadcast mode */ + int v2_broadcast; - /* RIPv2 authentication type. */ - int auth_type; + /* RIPv2 authentication type. */ + int auth_type; - /* RIPv2 authentication string. */ - char *auth_str; + /* RIPv2 authentication string. */ + char *auth_str; - /* RIPv2 authentication key chain. */ - char *key_chain; + /* RIPv2 authentication key chain. */ + char *key_chain; - /* value to use for md5->auth_len */ - u_int8_t md5_auth_len; + /* value to use for md5->auth_len */ + u_int8_t md5_auth_len; - /* Split horizon flag. */ - split_horizon_policy_t split_horizon; - split_horizon_policy_t split_horizon_default; + /* Split horizon flag. */ + split_horizon_policy_t split_horizon; + split_horizon_policy_t split_horizon_default; - /* For filter type slot. */ +/* For filter type slot. */ #define RIP_FILTER_IN 0 #define RIP_FILTER_OUT 1 #define RIP_FILTER_MAX 2 - /* Access-list. */ - struct access_list *list[RIP_FILTER_MAX]; + /* Access-list. */ + struct access_list *list[RIP_FILTER_MAX]; - /* Prefix-list. */ - struct prefix_list *prefix[RIP_FILTER_MAX]; + /* Prefix-list. */ + struct prefix_list *prefix[RIP_FILTER_MAX]; - /* Route-map. */ - struct route_map *routemap[RIP_FILTER_MAX]; + /* Route-map. */ + struct route_map *routemap[RIP_FILTER_MAX]; - /* Wake up thread. */ - struct thread *t_wakeup; + /* Wake up thread. */ + struct thread *t_wakeup; - /* Interface statistics. */ - int recv_badpackets; - int recv_badroutes; - int sent_updates; + /* Interface statistics. */ + int recv_badpackets; + int recv_badroutes; + int sent_updates; - /* Passive interface. */ - int passive; + /* Passive interface. */ + int passive; }; /* RIP peer information. */ -struct rip_peer -{ - /* Peer address. */ - struct in_addr addr; +struct rip_peer { + /* Peer address. */ + struct in_addr addr; - /* Peer RIP tag value. */ - int domain; + /* Peer RIP tag value. */ + int domain; - /* Last update time. */ - time_t uptime; + /* Last update time. */ + time_t uptime; - /* Peer RIP version. */ - u_char version; + /* Peer RIP version. */ + u_char version; - /* Statistics. */ - int recv_badpackets; - int recv_badroutes; + /* Statistics. */ + int recv_badpackets; + int recv_badroutes; - /* Timeout thread. */ - struct thread *t_timeout; + /* Timeout thread. */ + struct thread *t_timeout; }; -struct rip_md5_info -{ - u_int16_t family; - u_int16_t type; - u_int16_t packet_len; - u_char keyid; - u_char auth_len; - u_int32_t sequence; - u_int32_t reserv1; - u_int32_t reserv2; +struct rip_md5_info { + u_int16_t family; + u_int16_t type; + u_int16_t packet_len; + u_char keyid; + u_char auth_len; + u_int32_t sequence; + u_int32_t reserv1; + u_int32_t reserv2; }; -struct rip_md5_data -{ - u_int16_t family; - u_int16_t type; - u_char digest[16]; +struct rip_md5_data { + u_int16_t family; + u_int16_t type; + u_char digest[16]; }; /* RIP accepet/announce methods. */ @@ -362,11 +352,10 @@ struct rip_md5_data #define RIP_DEFAULT_METRIC_DEFAULT 1 /* RIP event. */ -enum rip_event -{ - RIP_READ, - RIP_UPDATE_EVENT, - RIP_TRIGGERED_UPDATE, +enum rip_event { + RIP_READ, + RIP_UPDATE_EVENT, + RIP_TRIGGERED_UPDATE, }; /* Macro for timer turn on. */ @@ -376,62 +365,64 @@ enum rip_event #define RIP_TIMER_OFF(X) THREAD_TIMER_OFF(X) /* Prototypes. */ -extern void rip_init (void); -extern void rip_reset (void); -extern void rip_clean (void); -extern void rip_clean_network (void); -extern void rip_interfaces_clean (void); -extern void rip_interfaces_reset (void); -extern void rip_passive_nondefault_clean (void); -extern void rip_if_init (void); -extern void rip_if_down_all (void); -extern void rip_route_map_init (void); -extern void rip_route_map_reset (void); +extern void rip_init(void); +extern void rip_reset(void); +extern void rip_clean(void); +extern void rip_clean_network(void); +extern void rip_interfaces_clean(void); +extern void rip_interfaces_reset(void); +extern void rip_passive_nondefault_clean(void); +extern void rip_if_init(void); +extern void rip_if_down_all(void); +extern void rip_route_map_init(void); +extern void rip_route_map_reset(void); extern void rip_zclient_init(struct thread_master *); extern void rip_zclient_stop(void); -extern void rip_zclient_reset (void); -extern void rip_offset_init (void); -extern int if_check_address (struct in_addr addr); - -extern int rip_request_send (struct sockaddr_in *, struct interface *, u_char, - struct connected *); -extern int rip_neighbor_lookup (struct sockaddr_in *); - -extern int rip_redistribute_check (int); -extern void rip_redistribute_add (int, int, struct prefix_ipv4 *, ifindex_t, - struct in_addr *, unsigned int, unsigned char, - route_tag_t); -extern void rip_redistribute_delete (int, int, struct prefix_ipv4 *, ifindex_t); -extern void rip_redistribute_withdraw (int); -extern void rip_zebra_ipv4_add (struct route_node *); -extern void rip_zebra_ipv4_delete (struct route_node *); -extern void rip_interface_multicast_set (int, struct connected *); -extern void rip_distribute_update_interface (struct interface *); -extern void rip_if_rmap_update_interface (struct interface *); - -extern int config_write_rip_network (struct vty *, int); -extern int config_write_rip_offset_list (struct vty *); -extern int config_write_rip_redistribute (struct vty *, int); - -extern void rip_peer_init (void); -extern void rip_peer_update (struct sockaddr_in *, u_char); -extern void rip_peer_bad_route (struct sockaddr_in *); -extern void rip_peer_bad_packet (struct sockaddr_in *); -extern void rip_peer_display (struct vty *); -extern struct rip_peer *rip_peer_lookup (struct in_addr *); -extern struct rip_peer *rip_peer_lookup_next (struct in_addr *); - -extern int rip_offset_list_apply_in (struct prefix_ipv4 *, struct interface *, u_int32_t *); -extern int rip_offset_list_apply_out (struct prefix_ipv4 *, struct interface *, u_int32_t *); -extern void rip_offset_clean (void); - -extern void rip_info_free (struct rip_info *); -extern u_char rip_distance_apply (struct rip_info *); -extern void rip_redistribute_clean (void); - -extern struct rip_info *rip_ecmp_add (struct rip_info *); -extern struct rip_info *rip_ecmp_replace (struct rip_info *); -extern struct rip_info *rip_ecmp_delete (struct rip_info *); +extern void rip_zclient_reset(void); +extern void rip_offset_init(void); +extern int if_check_address(struct in_addr addr); + +extern int rip_request_send(struct sockaddr_in *, struct interface *, u_char, + struct connected *); +extern int rip_neighbor_lookup(struct sockaddr_in *); + +extern int rip_redistribute_check(int); +extern void rip_redistribute_add(int, int, struct prefix_ipv4 *, ifindex_t, + struct in_addr *, unsigned int, unsigned char, + route_tag_t); +extern void rip_redistribute_delete(int, int, struct prefix_ipv4 *, ifindex_t); +extern void rip_redistribute_withdraw(int); +extern void rip_zebra_ipv4_add(struct route_node *); +extern void rip_zebra_ipv4_delete(struct route_node *); +extern void rip_interface_multicast_set(int, struct connected *); +extern void rip_distribute_update_interface(struct interface *); +extern void rip_if_rmap_update_interface(struct interface *); + +extern int config_write_rip_network(struct vty *, int); +extern int config_write_rip_offset_list(struct vty *); +extern int config_write_rip_redistribute(struct vty *, int); + +extern void rip_peer_init(void); +extern void rip_peer_update(struct sockaddr_in *, u_char); +extern void rip_peer_bad_route(struct sockaddr_in *); +extern void rip_peer_bad_packet(struct sockaddr_in *); +extern void rip_peer_display(struct vty *); +extern struct rip_peer *rip_peer_lookup(struct in_addr *); +extern struct rip_peer *rip_peer_lookup_next(struct in_addr *); + +extern int rip_offset_list_apply_in(struct prefix_ipv4 *, struct interface *, + u_int32_t *); +extern int rip_offset_list_apply_out(struct prefix_ipv4 *, struct interface *, + u_int32_t *); +extern void rip_offset_clean(void); + +extern void rip_info_free(struct rip_info *); +extern u_char rip_distance_apply(struct rip_info *); +extern void rip_redistribute_clean(void); + +extern struct rip_info *rip_ecmp_add(struct rip_info *); +extern struct rip_info *rip_ecmp_replace(struct rip_info *); +extern struct rip_info *rip_ecmp_delete(struct rip_info *); /* There is only one rip strucutre. */ extern struct rip *rip; @@ -443,7 +434,7 @@ extern struct thread_master *master; extern long rip_global_route_changes; extern long rip_global_queries; -DECLARE_HOOK(rip_ifaddr_add, (struct connected *ifc), (ifc)) -DECLARE_HOOK(rip_ifaddr_del, (struct connected *ifc), (ifc)) +DECLARE_HOOK(rip_ifaddr_add, (struct connected * ifc), (ifc)) +DECLARE_HOOK(rip_ifaddr_del, (struct connected * ifc), (ifc)) #endif /* _ZEBRA_RIP_H */ diff --git a/ripngd/ripng_debug.c b/ripngd/ripng_debug.c index 3bc9b4b21..5d7a2cf9f 100644 --- a/ripngd/ripng_debug.c +++ b/ripngd/ripng_debug.c @@ -35,30 +35,28 @@ DEFUN (show_debugging_ripng, DEBUG_STR "RIPng configuration\n") { - vty_out (vty, "RIPng debugging status:\n"); - - if (IS_RIPNG_DEBUG_EVENT) - vty_out (vty, " RIPng event debugging is on\n"); - - if (IS_RIPNG_DEBUG_PACKET) - { - if (IS_RIPNG_DEBUG_SEND && IS_RIPNG_DEBUG_RECV) - { - vty_out (vty," RIPng packet debugging is on\n"); - } - else - { - if (IS_RIPNG_DEBUG_SEND) - vty_out (vty," RIPng packet send debugging is on\n"); - else - vty_out (vty," RIPng packet receive debugging is on\n"); + vty_out(vty, "RIPng debugging status:\n"); + + if (IS_RIPNG_DEBUG_EVENT) + vty_out(vty, " RIPng event debugging is on\n"); + + if (IS_RIPNG_DEBUG_PACKET) { + if (IS_RIPNG_DEBUG_SEND && IS_RIPNG_DEBUG_RECV) { + vty_out(vty, " RIPng packet debugging is on\n"); + } else { + if (IS_RIPNG_DEBUG_SEND) + vty_out(vty, + " RIPng packet send debugging is on\n"); + else + vty_out(vty, + " RIPng packet receive debugging is on\n"); + } } - } - if (IS_RIPNG_DEBUG_ZEBRA) - vty_out (vty, " RIPng zebra debugging is on\n"); + if (IS_RIPNG_DEBUG_ZEBRA) + vty_out(vty, " RIPng zebra debugging is on\n"); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_ripng_events, @@ -68,8 +66,8 @@ DEFUN (debug_ripng_events, "RIPng configuration\n" "Debug option set for ripng events\n") { - ripng_debug_event = RIPNG_DEBUG_EVENT; - return CMD_WARNING_CONFIG_FAILED; + ripng_debug_event = RIPNG_DEBUG_EVENT; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (debug_ripng_packet, @@ -79,10 +77,10 @@ DEFUN (debug_ripng_packet, "RIPng configuration\n" "Debug option set for ripng packet\n") { - ripng_debug_packet = RIPNG_DEBUG_PACKET; - ripng_debug_packet |= RIPNG_DEBUG_SEND; - ripng_debug_packet |= RIPNG_DEBUG_RECV; - return CMD_SUCCESS; + ripng_debug_packet = RIPNG_DEBUG_PACKET; + ripng_debug_packet |= RIPNG_DEBUG_SEND; + ripng_debug_packet |= RIPNG_DEBUG_RECV; + return CMD_SUCCESS; } DEFUN (debug_ripng_packet_direct, @@ -94,14 +92,18 @@ DEFUN (debug_ripng_packet_direct, "Debug option set for receive packet\n" "Debug option set for send packet\n") { - int idx_recv_send = 3; - ripng_debug_packet |= RIPNG_DEBUG_PACKET; - if (strncmp ("send", argv[idx_recv_send]->arg, strlen (argv[idx_recv_send]->arg)) == 0) - ripng_debug_packet |= RIPNG_DEBUG_SEND; - if (strncmp ("recv", argv[idx_recv_send]->arg, strlen (argv[idx_recv_send]->arg)) == 0) - ripng_debug_packet |= RIPNG_DEBUG_RECV; - - return CMD_SUCCESS; + int idx_recv_send = 3; + ripng_debug_packet |= RIPNG_DEBUG_PACKET; + if (strncmp("send", argv[idx_recv_send]->arg, + strlen(argv[idx_recv_send]->arg)) + == 0) + ripng_debug_packet |= RIPNG_DEBUG_SEND; + if (strncmp("recv", argv[idx_recv_send]->arg, + strlen(argv[idx_recv_send]->arg)) + == 0) + ripng_debug_packet |= RIPNG_DEBUG_RECV; + + return CMD_SUCCESS; } DEFUN (debug_ripng_zebra, @@ -111,8 +113,8 @@ DEFUN (debug_ripng_zebra, "RIPng configuration\n" "Debug option set for ripng and zebra communication\n") { - ripng_debug_zebra = RIPNG_DEBUG_ZEBRA; - return CMD_WARNING_CONFIG_FAILED; + ripng_debug_zebra = RIPNG_DEBUG_ZEBRA; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (no_debug_ripng_events, @@ -123,8 +125,8 @@ DEFUN (no_debug_ripng_events, "RIPng configuration\n" "Debug option set for ripng events\n") { - ripng_debug_event = 0; - return CMD_SUCCESS; + ripng_debug_event = 0; + return CMD_SUCCESS; } DEFUN (no_debug_ripng_packet, @@ -135,8 +137,8 @@ DEFUN (no_debug_ripng_packet, "RIPng configuration\n" "Debug option set for ripng packet\n") { - ripng_debug_packet = 0; - return CMD_SUCCESS; + ripng_debug_packet = 0; + return CMD_SUCCESS; } DEFUN (no_debug_ripng_packet_direct, @@ -149,22 +151,23 @@ DEFUN (no_debug_ripng_packet_direct, "Debug option set for receive packet\n" "Debug option set for send packet\n") { - int idx_recv_send = 4; - if (strncmp ("send", argv[idx_recv_send]->arg, strlen (argv[idx_recv_send]->arg)) == 0) - { - if (IS_RIPNG_DEBUG_RECV) - ripng_debug_packet &= ~RIPNG_DEBUG_SEND; - else - ripng_debug_packet = 0; - } - else if (strncmp ("recv", argv[idx_recv_send]->arg, strlen (argv[idx_recv_send]->arg)) == 0) - { - if (IS_RIPNG_DEBUG_SEND) - ripng_debug_packet &= ~RIPNG_DEBUG_RECV; - else - ripng_debug_packet = 0; - } - return CMD_SUCCESS; + int idx_recv_send = 4; + if (strncmp("send", argv[idx_recv_send]->arg, + strlen(argv[idx_recv_send]->arg)) + == 0) { + if (IS_RIPNG_DEBUG_RECV) + ripng_debug_packet &= ~RIPNG_DEBUG_SEND; + else + ripng_debug_packet = 0; + } else if (strncmp("recv", argv[idx_recv_send]->arg, + strlen(argv[idx_recv_send]->arg)) + == 0) { + if (IS_RIPNG_DEBUG_SEND) + ripng_debug_packet &= ~RIPNG_DEBUG_RECV; + else + ripng_debug_packet = 0; + } + return CMD_SUCCESS; } DEFUN (no_debug_ripng_zebra, @@ -175,86 +178,75 @@ DEFUN (no_debug_ripng_zebra, "RIPng configuration\n" "Debug option set for ripng and zebra communication\n") { - ripng_debug_zebra = 0; - return CMD_WARNING_CONFIG_FAILED; + ripng_debug_zebra = 0; + return CMD_WARNING_CONFIG_FAILED; } /* Debug node. */ -static struct cmd_node debug_node = -{ - DEBUG_NODE, - "", /* Debug node has no interface. */ - 1 /* VTYSH */ +static struct cmd_node debug_node = { + DEBUG_NODE, "", /* Debug node has no interface. */ + 1 /* VTYSH */ }; -static int -config_write_debug (struct vty *vty) +static int config_write_debug(struct vty *vty) { - int write = 0; + int write = 0; - if (IS_RIPNG_DEBUG_EVENT) - { - vty_out (vty, "debug ripng events\n"); - write++; - } - if (IS_RIPNG_DEBUG_PACKET) - { - if (IS_RIPNG_DEBUG_SEND && IS_RIPNG_DEBUG_RECV) - { - vty_out (vty,"debug ripng packet\n"); - write++; + if (IS_RIPNG_DEBUG_EVENT) { + vty_out(vty, "debug ripng events\n"); + write++; } - else - { - if (IS_RIPNG_DEBUG_SEND) - vty_out (vty,"debug ripng packet send\n"); - else - vty_out (vty,"debug ripng packet recv\n"); - write++; + if (IS_RIPNG_DEBUG_PACKET) { + if (IS_RIPNG_DEBUG_SEND && IS_RIPNG_DEBUG_RECV) { + vty_out(vty, "debug ripng packet\n"); + write++; + } else { + if (IS_RIPNG_DEBUG_SEND) + vty_out(vty, "debug ripng packet send\n"); + else + vty_out(vty, "debug ripng packet recv\n"); + write++; + } } - } - if (IS_RIPNG_DEBUG_ZEBRA) - { - vty_out (vty, "debug ripng zebra\n"); - write++; - } - return write; + if (IS_RIPNG_DEBUG_ZEBRA) { + vty_out(vty, "debug ripng zebra\n"); + write++; + } + return write; } -void -ripng_debug_reset () +void ripng_debug_reset() { - ripng_debug_event = 0; - ripng_debug_packet = 0; - ripng_debug_zebra = 0; + ripng_debug_event = 0; + ripng_debug_packet = 0; + ripng_debug_zebra = 0; } -void -ripng_debug_init () +void ripng_debug_init() { - ripng_debug_event = 0; - ripng_debug_packet = 0; - ripng_debug_zebra = 0; - - install_node (&debug_node, config_write_debug); - - install_element (VIEW_NODE, &show_debugging_ripng_cmd); - - install_element (ENABLE_NODE, &debug_ripng_events_cmd); - install_element (ENABLE_NODE, &debug_ripng_packet_cmd); - install_element (ENABLE_NODE, &debug_ripng_packet_direct_cmd); - install_element (ENABLE_NODE, &debug_ripng_zebra_cmd); - install_element (ENABLE_NODE, &no_debug_ripng_events_cmd); - install_element (ENABLE_NODE, &no_debug_ripng_packet_cmd); - install_element (ENABLE_NODE, &no_debug_ripng_packet_direct_cmd); - install_element (ENABLE_NODE, &no_debug_ripng_zebra_cmd); - - install_element (CONFIG_NODE, &debug_ripng_events_cmd); - install_element (CONFIG_NODE, &debug_ripng_packet_cmd); - install_element (CONFIG_NODE, &debug_ripng_packet_direct_cmd); - install_element (CONFIG_NODE, &debug_ripng_zebra_cmd); - install_element (CONFIG_NODE, &no_debug_ripng_events_cmd); - install_element (CONFIG_NODE, &no_debug_ripng_packet_cmd); - install_element (CONFIG_NODE, &no_debug_ripng_packet_direct_cmd); - install_element (CONFIG_NODE, &no_debug_ripng_zebra_cmd); + ripng_debug_event = 0; + ripng_debug_packet = 0; + ripng_debug_zebra = 0; + + install_node(&debug_node, config_write_debug); + + install_element(VIEW_NODE, &show_debugging_ripng_cmd); + + install_element(ENABLE_NODE, &debug_ripng_events_cmd); + install_element(ENABLE_NODE, &debug_ripng_packet_cmd); + install_element(ENABLE_NODE, &debug_ripng_packet_direct_cmd); + install_element(ENABLE_NODE, &debug_ripng_zebra_cmd); + install_element(ENABLE_NODE, &no_debug_ripng_events_cmd); + install_element(ENABLE_NODE, &no_debug_ripng_packet_cmd); + install_element(ENABLE_NODE, &no_debug_ripng_packet_direct_cmd); + install_element(ENABLE_NODE, &no_debug_ripng_zebra_cmd); + + install_element(CONFIG_NODE, &debug_ripng_events_cmd); + install_element(CONFIG_NODE, &debug_ripng_packet_cmd); + install_element(CONFIG_NODE, &debug_ripng_packet_direct_cmd); + install_element(CONFIG_NODE, &debug_ripng_zebra_cmd); + install_element(CONFIG_NODE, &no_debug_ripng_events_cmd); + install_element(CONFIG_NODE, &no_debug_ripng_packet_cmd); + install_element(CONFIG_NODE, &no_debug_ripng_packet_direct_cmd); + install_element(CONFIG_NODE, &no_debug_ripng_zebra_cmd); } diff --git a/ripngd/ripng_debug.h b/ripngd/ripng_debug.h index b4e1455ad..8124a1a0c 100644 --- a/ripngd/ripng_debug.h +++ b/ripngd/ripng_debug.h @@ -44,7 +44,7 @@ extern unsigned long ripng_debug_event; extern unsigned long ripng_debug_packet; extern unsigned long ripng_debug_zebra; -extern void ripng_debug_init (void); -extern void ripng_debug_reset (void); +extern void ripng_debug_init(void); +extern void ripng_debug_reset(void); #endif /* _ZEBRA_RIPNG_DEBUG_H */ diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c index e4b45c54a..c762d8ace 100644 --- a/ripngd/ripng_interface.c +++ b/ripngd/ripng_interface.c @@ -50,439 +50,431 @@ extern struct zebra_privs_t ripngd_privs; /* Static utility function. */ -static void ripng_enable_apply (struct interface *); -static void ripng_passive_interface_apply (struct interface *); -static int ripng_enable_if_lookup (const char *); -static int ripng_enable_network_lookup2 (struct connected *); -static void ripng_enable_apply_all (void); +static void ripng_enable_apply(struct interface *); +static void ripng_passive_interface_apply(struct interface *); +static int ripng_enable_if_lookup(const char *); +static int ripng_enable_network_lookup2(struct connected *); +static void ripng_enable_apply_all(void); /* Join to the all rip routers multicast group. */ -static int -ripng_multicast_join (struct interface *ifp) +static int ripng_multicast_join(struct interface *ifp) { - int ret; - struct ipv6_mreq mreq; - int save_errno; - - if (if_is_multicast (ifp)) { - memset (&mreq, 0, sizeof (mreq)); - inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr); - mreq.ipv6mr_interface = ifp->ifindex; - - /* - * NetBSD 1.6.2 requires root to join groups on gif(4). - * While this is bogus, privs are available and easy to use - * for this call as a workaround. - */ - if (ripngd_privs.change (ZPRIVS_RAISE)) - zlog_err ("ripng_multicast_join: could not raise privs"); - - ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, - (char *) &mreq, sizeof (mreq)); - save_errno = errno; - - if (ripngd_privs.change (ZPRIVS_LOWER)) - zlog_err ("ripng_multicast_join: could not lower privs"); - - if (ret < 0 && save_errno == EADDRINUSE) - { - /* - * Group is already joined. This occurs due to sloppy group - * management, in particular declining to leave the group on - * an interface that has just gone down. - */ - zlog_warn ("ripng join on %s EADDRINUSE (ignoring)\n", ifp->name); - return 0; /* not an error */ - } - - if (ret < 0) - zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", - safe_strerror (save_errno)); - - if (IS_RIPNG_DEBUG_EVENT) - zlog_debug ("RIPng %s join to all-rip-routers multicast group", ifp->name); - - if (ret < 0) - return -1; - } - return 0; + int ret; + struct ipv6_mreq mreq; + int save_errno; + + if (if_is_multicast(ifp)) { + memset(&mreq, 0, sizeof(mreq)); + inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr); + mreq.ipv6mr_interface = ifp->ifindex; + + /* + * NetBSD 1.6.2 requires root to join groups on gif(4). + * While this is bogus, privs are available and easy to use + * for this call as a workaround. + */ + if (ripngd_privs.change(ZPRIVS_RAISE)) + zlog_err("ripng_multicast_join: could not raise privs"); + + ret = setsockopt(ripng->sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, + (char *)&mreq, sizeof(mreq)); + save_errno = errno; + + if (ripngd_privs.change(ZPRIVS_LOWER)) + zlog_err("ripng_multicast_join: could not lower privs"); + + if (ret < 0 && save_errno == EADDRINUSE) { + /* + * Group is already joined. This occurs due to sloppy + * group + * management, in particular declining to leave the + * group on + * an interface that has just gone down. + */ + zlog_warn("ripng join on %s EADDRINUSE (ignoring)\n", + ifp->name); + return 0; /* not an error */ + } + + if (ret < 0) + zlog_warn("can't setsockopt IPV6_JOIN_GROUP: %s", + safe_strerror(save_errno)); + + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug( + "RIPng %s join to all-rip-routers multicast group", + ifp->name); + + if (ret < 0) + return -1; + } + return 0; } /* Leave from the all rip routers multicast group. */ -static int -ripng_multicast_leave (struct interface *ifp) +static int ripng_multicast_leave(struct interface *ifp) { - int ret; - struct ipv6_mreq mreq; - - if (if_is_multicast (ifp)) { - memset (&mreq, 0, sizeof (mreq)); - inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr); - mreq.ipv6mr_interface = ifp->ifindex; - - ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, - (char *) &mreq, sizeof (mreq)); - if (ret < 0) - zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s\n", safe_strerror (errno)); - - if (IS_RIPNG_DEBUG_EVENT) - zlog_debug ("RIPng %s leave from all-rip-routers multicast group", - ifp->name); - - if (ret < 0) - return -1; - } + int ret; + struct ipv6_mreq mreq; + + if (if_is_multicast(ifp)) { + memset(&mreq, 0, sizeof(mreq)); + inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr); + mreq.ipv6mr_interface = ifp->ifindex; + + ret = setsockopt(ripng->sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, + (char *)&mreq, sizeof(mreq)); + if (ret < 0) + zlog_warn("can't setsockopt IPV6_LEAVE_GROUP: %s\n", + safe_strerror(errno)); + + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug( + "RIPng %s leave from all-rip-routers multicast group", + ifp->name); + + if (ret < 0) + return -1; + } - return 0; + return 0; } /* How many link local IPv6 address could be used on the interface ? */ -static int -ripng_if_ipv6_lladdress_check (struct interface *ifp) +static int ripng_if_ipv6_lladdress_check(struct interface *ifp) { - struct listnode *nn; - struct connected *connected; - int count = 0; + struct listnode *nn; + struct connected *connected; + int count = 0; - for (ALL_LIST_ELEMENTS_RO (ifp->connected, nn, connected)) - { - struct prefix *p; - p = connected->address; + for (ALL_LIST_ELEMENTS_RO(ifp->connected, nn, connected)) { + struct prefix *p; + p = connected->address; - if ((p->family == AF_INET6) && - IN6_IS_ADDR_LINKLOCAL (&p->u.prefix6)) - count++; - } + if ((p->family == AF_INET6) + && IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6)) + count++; + } - return count; + return count; } -static int -ripng_if_down (struct interface *ifp) +static int ripng_if_down(struct interface *ifp) { - struct route_node *rp; - struct ripng_info *rinfo; - struct ripng_interface *ri; - struct list *list = NULL; - struct listnode *listnode = NULL, *nextnode = NULL; - - if (ripng) - for (rp = route_top (ripng->table); rp; rp = route_next (rp)) - if ((list = rp->info) != NULL) - for (ALL_LIST_ELEMENTS (list, listnode, nextnode, rinfo)) - if (rinfo->ifindex == ifp->ifindex) - ripng_ecmp_delete (rinfo); - - ri = ifp->info; - - if (ri->running) - { - if (IS_RIPNG_DEBUG_EVENT) - zlog_debug ("turn off %s", ifp->name); - - /* Leave from multicast group. */ - ripng_multicast_leave (ifp); - - ri->running = 0; - } - - return 0; + struct route_node *rp; + struct ripng_info *rinfo; + struct ripng_interface *ri; + struct list *list = NULL; + struct listnode *listnode = NULL, *nextnode = NULL; + + if (ripng) + for (rp = route_top(ripng->table); rp; rp = route_next(rp)) + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS(list, listnode, nextnode, + rinfo)) + if (rinfo->ifindex == ifp->ifindex) + ripng_ecmp_delete(rinfo); + + ri = ifp->info; + + if (ri->running) { + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug("turn off %s", ifp->name); + + /* Leave from multicast group. */ + ripng_multicast_leave(ifp); + + ri->running = 0; + } + + return 0; } /* Inteface link up message processing. */ -int -ripng_interface_up (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +int ripng_interface_up(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct interface *ifp; + struct stream *s; + struct interface *ifp; - /* zebra_interface_state_read() updates interface structure in iflist. */ - s = zclient->ibuf; - ifp = zebra_interface_state_read (s, vrf_id); + /* zebra_interface_state_read() updates interface structure in iflist. + */ + s = zclient->ibuf; + ifp = zebra_interface_state_read(s, vrf_id); - if (ifp == NULL) - return 0; + if (ifp == NULL) + return 0; - if (IS_RIPNG_DEBUG_ZEBRA) - zlog_debug ("interface up %s index %d flags %llx metric %d mtu %d", - ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, - ifp->metric, ifp->mtu6); + if (IS_RIPNG_DEBUG_ZEBRA) + zlog_debug( + "interface up %s index %d flags %llx metric %d mtu %d", + ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, + ifp->metric, ifp->mtu6); - /* Check if this interface is RIPng enabled or not. */ - ripng_enable_apply (ifp); + /* Check if this interface is RIPng enabled or not. */ + ripng_enable_apply(ifp); - /* Check for a passive interface. */ - ripng_passive_interface_apply (ifp); + /* Check for a passive interface. */ + ripng_passive_interface_apply(ifp); - /* Apply distribute list to the all interface. */ - ripng_distribute_update_interface (ifp); + /* Apply distribute list to the all interface. */ + ripng_distribute_update_interface(ifp); - return 0; + return 0; } /* Inteface link down message processing. */ -int -ripng_interface_down (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +int ripng_interface_down(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct interface *ifp; + struct stream *s; + struct interface *ifp; - /* zebra_interface_state_read() updates interface structure in iflist. */ - s = zclient->ibuf; - ifp = zebra_interface_state_read (s, vrf_id); + /* zebra_interface_state_read() updates interface structure in iflist. + */ + s = zclient->ibuf; + ifp = zebra_interface_state_read(s, vrf_id); - if (ifp == NULL) - return 0; + if (ifp == NULL) + return 0; - ripng_if_down (ifp); + ripng_if_down(ifp); - if (IS_RIPNG_DEBUG_ZEBRA) - zlog_debug ("interface down %s index %d flags %#llx metric %d mtu %d", - ifp->name, ifp->ifindex, - (unsigned long long) ifp->flags, ifp->metric, ifp->mtu6); + if (IS_RIPNG_DEBUG_ZEBRA) + zlog_debug( + "interface down %s index %d flags %#llx metric %d mtu %d", + ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, + ifp->metric, ifp->mtu6); - return 0; + return 0; } /* Inteface addition message from zebra. */ -int -ripng_interface_add (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +int ripng_interface_add(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; + struct interface *ifp; - ifp = zebra_interface_add_read (zclient->ibuf, vrf_id); + ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); - if (IS_RIPNG_DEBUG_ZEBRA) - zlog_debug ("RIPng interface add %s index %d flags %#llx metric %d mtu %d", - ifp->name, ifp->ifindex, (unsigned long long) ifp->flags, - ifp->metric, ifp->mtu6); + if (IS_RIPNG_DEBUG_ZEBRA) + zlog_debug( + "RIPng interface add %s index %d flags %#llx metric %d mtu %d", + ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, + ifp->metric, ifp->mtu6); - /* Check is this interface is RIP enabled or not.*/ - ripng_enable_apply (ifp); + /* Check is this interface is RIP enabled or not.*/ + ripng_enable_apply(ifp); - /* Apply distribute list to the interface. */ - ripng_distribute_update_interface (ifp); + /* Apply distribute list to the interface. */ + ripng_distribute_update_interface(ifp); - /* Check interface routemap. */ - ripng_if_rmap_update_interface (ifp); + /* Check interface routemap. */ + ripng_if_rmap_update_interface(ifp); - return 0; + return 0; } -int -ripng_interface_delete (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +int ripng_interface_delete(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - struct stream *s; + struct interface *ifp; + struct stream *s; - s = zclient->ibuf; - /* zebra_interface_state_read() updates interface structure in iflist */ - ifp = zebra_interface_state_read (s, vrf_id); + s = zclient->ibuf; + /* zebra_interface_state_read() updates interface structure in iflist + */ + ifp = zebra_interface_state_read(s, vrf_id); - if (ifp == NULL) - return 0; + if (ifp == NULL) + return 0; - if (if_is_up (ifp)) { - ripng_if_down(ifp); - } + if (if_is_up(ifp)) { + ripng_if_down(ifp); + } - zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d", - ifp->name, ifp->ifindex, (unsigned long long) ifp->flags, - ifp->metric, ifp->mtu6); + zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d", + ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, + ifp->metric, ifp->mtu6); - /* To support pseudo interface do not free interface structure. */ - /* if_delete(ifp); */ - ifp->ifindex = IFINDEX_DELETED; + /* To support pseudo interface do not free interface structure. */ + /* if_delete(ifp); */ + ifp->ifindex = IFINDEX_DELETED; - return 0; + return 0; } -void -ripng_interface_clean (void) +void ripng_interface_clean(void) { - struct listnode *node, *nnode; - struct interface *ifp; - struct ripng_interface *ri; - - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp)) - { - ri = ifp->info; - - ri->enable_network = 0; - ri->enable_interface = 0; - ri->running = 0; - - if (ri->t_wakeup) - { - thread_cancel (ri->t_wakeup); - ri->t_wakeup = NULL; - } - } -} + struct listnode *node, *nnode; + struct interface *ifp; + struct ripng_interface *ri; -void -ripng_interface_reset (void) -{ - struct listnode *node; - struct interface *ifp; - struct ripng_interface *ri; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - ri = ifp->info; - - ri->enable_network = 0; - ri->enable_interface = 0; - ri->running = 0; + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), node, nnode, ifp)) { + ri = ifp->info; - ri->split_horizon = RIPNG_NO_SPLIT_HORIZON; - ri->split_horizon_default = RIPNG_NO_SPLIT_HORIZON; + ri->enable_network = 0; + ri->enable_interface = 0; + ri->running = 0; - ri->list[RIPNG_FILTER_IN] = NULL; - ri->list[RIPNG_FILTER_OUT] = NULL; - - ri->prefix[RIPNG_FILTER_IN] = NULL; - ri->prefix[RIPNG_FILTER_OUT] = NULL; + if (ri->t_wakeup) { + thread_cancel(ri->t_wakeup); + ri->t_wakeup = NULL; + } + } +} - if (ri->t_wakeup) - { - thread_cancel (ri->t_wakeup); - ri->t_wakeup = NULL; - } +void ripng_interface_reset(void) +{ + struct listnode *node; + struct interface *ifp; + struct ripng_interface *ri; - ri->passive = 0; - } -} + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + ri = ifp->info; -static void -ripng_apply_address_add (struct connected *ifc) { - struct prefix_ipv6 address; - struct prefix *p; + ri->enable_network = 0; + ri->enable_interface = 0; + ri->running = 0; - if (!ripng) - return; + ri->split_horizon = RIPNG_NO_SPLIT_HORIZON; + ri->split_horizon_default = RIPNG_NO_SPLIT_HORIZON; - if (! if_is_up(ifc->ifp)) - return; + ri->list[RIPNG_FILTER_IN] = NULL; + ri->list[RIPNG_FILTER_OUT] = NULL; - p = ifc->address; + ri->prefix[RIPNG_FILTER_IN] = NULL; + ri->prefix[RIPNG_FILTER_OUT] = NULL; - memset (&address, 0, sizeof (address)); - address.family = p->family; - address.prefix = p->u.prefix6; - address.prefixlen = p->prefixlen; - apply_mask_ipv6(&address); + if (ri->t_wakeup) { + thread_cancel(ri->t_wakeup); + ri->t_wakeup = NULL; + } - /* Check if this interface is RIP enabled or not - or Check if this address's prefix is RIP enabled */ - if ((ripng_enable_if_lookup(ifc->ifp->name) >= 0) || - (ripng_enable_network_lookup2(ifc) >= 0)) - ripng_redistribute_add(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE, - &address, ifc->ifp->ifindex, NULL, 0); + ri->passive = 0; + } +} +static void ripng_apply_address_add(struct connected *ifc) +{ + struct prefix_ipv6 address; + struct prefix *p; + + if (!ripng) + return; + + if (!if_is_up(ifc->ifp)) + return; + + p = ifc->address; + + memset(&address, 0, sizeof(address)); + address.family = p->family; + address.prefix = p->u.prefix6; + address.prefixlen = p->prefixlen; + apply_mask_ipv6(&address); + + /* Check if this interface is RIP enabled or not + or Check if this address's prefix is RIP enabled */ + if ((ripng_enable_if_lookup(ifc->ifp->name) >= 0) + || (ripng_enable_network_lookup2(ifc) >= 0)) + ripng_redistribute_add(ZEBRA_ROUTE_CONNECT, + RIPNG_ROUTE_INTERFACE, &address, + ifc->ifp->ifindex, NULL, 0); } -int -ripng_interface_address_add (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +int ripng_interface_address_add(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct connected *c; - struct prefix *p; + struct connected *c; + struct prefix *p; - c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD, - zclient->ibuf, vrf_id); + c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, + zclient->ibuf, vrf_id); - if (c == NULL) - return 0; + if (c == NULL) + return 0; - p = c->address; + p = c->address; - if (p->family == AF_INET6) - { - struct ripng_interface *ri = c->ifp->info; - - if (IS_RIPNG_DEBUG_ZEBRA) - zlog_debug ("RIPng connected address %s/%d add", - inet6_ntoa(p->u.prefix6), - p->prefixlen); - - /* Check is this prefix needs to be redistributed. */ - ripng_apply_address_add(c); + if (p->family == AF_INET6) { + struct ripng_interface *ri = c->ifp->info; - /* Let's try once again whether the interface could be activated */ - if (!ri->running) { - /* Check if this interface is RIP enabled or not.*/ - ripng_enable_apply (c->ifp); + if (IS_RIPNG_DEBUG_ZEBRA) + zlog_debug("RIPng connected address %s/%d add", + inet6_ntoa(p->u.prefix6), p->prefixlen); - /* Apply distribute list to the interface. */ - ripng_distribute_update_interface (c->ifp); + /* Check is this prefix needs to be redistributed. */ + ripng_apply_address_add(c); - /* Check interface routemap. */ - ripng_if_rmap_update_interface (c->ifp); - } + /* Let's try once again whether the interface could be activated + */ + if (!ri->running) { + /* Check if this interface is RIP enabled or not.*/ + ripng_enable_apply(c->ifp); - } + /* Apply distribute list to the interface. */ + ripng_distribute_update_interface(c->ifp); - return 0; + /* Check interface routemap. */ + ripng_if_rmap_update_interface(c->ifp); + } + } + + return 0; } -static void -ripng_apply_address_del (struct connected *ifc) { - struct prefix_ipv6 address; - struct prefix *p; +static void ripng_apply_address_del(struct connected *ifc) +{ + struct prefix_ipv6 address; + struct prefix *p; - if (!ripng) - return; + if (!ripng) + return; - if (! if_is_up(ifc->ifp)) - return; + if (!if_is_up(ifc->ifp)) + return; - p = ifc->address; + p = ifc->address; - memset (&address, 0, sizeof (address)); - address.family = p->family; - address.prefix = p->u.prefix6; - address.prefixlen = p->prefixlen; - apply_mask_ipv6(&address); + memset(&address, 0, sizeof(address)); + address.family = p->family; + address.prefix = p->u.prefix6; + address.prefixlen = p->prefixlen; + apply_mask_ipv6(&address); - ripng_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE, - &address, ifc->ifp->ifindex); + ripng_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE, + &address, ifc->ifp->ifindex); } -int -ripng_interface_address_delete (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +int ripng_interface_address_delete(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct connected *ifc; - struct prefix *p; - char buf[INET6_ADDRSTRLEN]; - - ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE, - zclient->ibuf, vrf_id); - - if (ifc) - { - p = ifc->address; - - if (p->family == AF_INET6) - { - if (IS_RIPNG_DEBUG_ZEBRA) - zlog_debug ("RIPng connected address %s/%d delete", - inet_ntop (AF_INET6, &p->u.prefix6, buf, - INET6_ADDRSTRLEN), - p->prefixlen); - - /* Check wether this prefix needs to be removed. */ - ripng_apply_address_del(ifc); + struct connected *ifc; + struct prefix *p; + char buf[INET6_ADDRSTRLEN]; + + ifc = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, + zclient->ibuf, vrf_id); + + if (ifc) { + p = ifc->address; + + if (p->family == AF_INET6) { + if (IS_RIPNG_DEBUG_ZEBRA) + zlog_debug( + "RIPng connected address %s/%d delete", + inet_ntop(AF_INET6, &p->u.prefix6, buf, + INET6_ADDRSTRLEN), + p->prefixlen); + + /* Check wether this prefix needs to be removed. */ + ripng_apply_address_del(ifc); + } + connected_free(ifc); } - connected_free (ifc); - } - return 0; + return 0; } /* RIPng enable interface vector. */ @@ -494,449 +486,426 @@ struct route_table *ripng_enable_network; /* Lookup RIPng enable network. */ /* Check wether the interface has at least a connected prefix that * is within the ripng_enable_network table. */ -static int -ripng_enable_network_lookup_if (struct interface *ifp) +static int ripng_enable_network_lookup_if(struct interface *ifp) { - struct listnode *node; - struct connected *connected; - struct prefix_ipv6 address; - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) - { - struct prefix *p; - struct route_node *node; - - p = connected->address; - - if (p->family == AF_INET6) - { - address.family = AF_INET6; - address.prefix = p->u.prefix6; - address.prefixlen = IPV6_MAX_BITLEN; - - node = route_node_match (ripng_enable_network, - (struct prefix *)&address); - if (node) - { - route_unlock_node (node); - return 1; - } - } - } - return -1; + struct listnode *node; + struct connected *connected; + struct prefix_ipv6 address; + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { + struct prefix *p; + struct route_node *node; + + p = connected->address; + + if (p->family == AF_INET6) { + address.family = AF_INET6; + address.prefix = p->u.prefix6; + address.prefixlen = IPV6_MAX_BITLEN; + + node = route_node_match(ripng_enable_network, + (struct prefix *)&address); + if (node) { + route_unlock_node(node); + return 1; + } + } + } + return -1; } /* Check wether connected is within the ripng_enable_network table. */ -static int -ripng_enable_network_lookup2 (struct connected *connected) +static int ripng_enable_network_lookup2(struct connected *connected) { - struct prefix_ipv6 address; - struct prefix *p; + struct prefix_ipv6 address; + struct prefix *p; - p = connected->address; + p = connected->address; - if (p->family == AF_INET6) { - struct route_node *node; + if (p->family == AF_INET6) { + struct route_node *node; - address.family = p->family; - address.prefix = p->u.prefix6; - address.prefixlen = IPV6_MAX_BITLEN; + address.family = p->family; + address.prefix = p->u.prefix6; + address.prefixlen = IPV6_MAX_BITLEN; - /* LPM on p->family, p->u.prefix6/IPV6_MAX_BITLEN within ripng_enable_network */ - node = route_node_match (ripng_enable_network, - (struct prefix *)&address); + /* LPM on p->family, p->u.prefix6/IPV6_MAX_BITLEN within + * ripng_enable_network */ + node = route_node_match(ripng_enable_network, + (struct prefix *)&address); - if (node) { - route_unlock_node (node); - return 1; - } - } + if (node) { + route_unlock_node(node); + return 1; + } + } - return -1; + return -1; } /* Add RIPng enable network. */ -static int -ripng_enable_network_add (struct prefix *p) +static int ripng_enable_network_add(struct prefix *p) { - struct route_node *node; + struct route_node *node; - node = route_node_get (ripng_enable_network, p); + node = route_node_get(ripng_enable_network, p); - if (node->info) - { - route_unlock_node (node); - return -1; - } - else - node->info = (void *)1; + if (node->info) { + route_unlock_node(node); + return -1; + } else + node->info = (void *)1; - /* XXX: One should find a better solution than a generic one */ - ripng_enable_apply_all(); + /* XXX: One should find a better solution than a generic one */ + ripng_enable_apply_all(); - return 1; + return 1; } /* Delete RIPng enable network. */ -static int -ripng_enable_network_delete (struct prefix *p) +static int ripng_enable_network_delete(struct prefix *p) { - struct route_node *node; + struct route_node *node; - node = route_node_lookup (ripng_enable_network, p); - if (node) - { - node->info = NULL; + node = route_node_lookup(ripng_enable_network, p); + if (node) { + node->info = NULL; - /* Unlock info lock. */ - route_unlock_node (node); + /* Unlock info lock. */ + route_unlock_node(node); - /* Unlock lookup lock. */ - route_unlock_node (node); + /* Unlock lookup lock. */ + route_unlock_node(node); - return 1; - } - return -1; + return 1; + } + return -1; } /* Lookup function. */ -static int -ripng_enable_if_lookup (const char *ifname) +static int ripng_enable_if_lookup(const char *ifname) { - unsigned int i; - char *str; - - for (i = 0; i < vector_active (ripng_enable_if); i++) - if ((str = vector_slot (ripng_enable_if, i)) != NULL) - if (strcmp (str, ifname) == 0) - return i; - return -1; + unsigned int i; + char *str; + + for (i = 0; i < vector_active(ripng_enable_if); i++) + if ((str = vector_slot(ripng_enable_if, i)) != NULL) + if (strcmp(str, ifname) == 0) + return i; + return -1; } /* Add interface to ripng_enable_if. */ -static int -ripng_enable_if_add (const char *ifname) +static int ripng_enable_if_add(const char *ifname) { - int ret; + int ret; - ret = ripng_enable_if_lookup (ifname); - if (ret >= 0) - return -1; + ret = ripng_enable_if_lookup(ifname); + if (ret >= 0) + return -1; - vector_set (ripng_enable_if, strdup (ifname)); + vector_set(ripng_enable_if, strdup(ifname)); - ripng_enable_apply_all(); + ripng_enable_apply_all(); - return 1; + return 1; } /* Delete interface from ripng_enable_if. */ -static int -ripng_enable_if_delete (const char *ifname) +static int ripng_enable_if_delete(const char *ifname) { - int index; - char *str; + int index; + char *str; - index = ripng_enable_if_lookup (ifname); - if (index < 0) - return -1; + index = ripng_enable_if_lookup(ifname); + if (index < 0) + return -1; - str = vector_slot (ripng_enable_if, index); - free (str); - vector_unset (ripng_enable_if, index); + str = vector_slot(ripng_enable_if, index); + free(str); + vector_unset(ripng_enable_if, index); - ripng_enable_apply_all(); + ripng_enable_apply_all(); - return 1; + return 1; } /* Wake up interface. */ -static int -ripng_interface_wakeup (struct thread *t) +static int ripng_interface_wakeup(struct thread *t) { - struct interface *ifp; - struct ripng_interface *ri; + struct interface *ifp; + struct ripng_interface *ri; - /* Get interface. */ - ifp = THREAD_ARG (t); + /* Get interface. */ + ifp = THREAD_ARG(t); - ri = ifp->info; - ri->t_wakeup = NULL; + ri = ifp->info; + ri->t_wakeup = NULL; - /* Join to multicast group. */ - if (ripng_multicast_join (ifp) < 0) { - zlog_err ("multicast join failed, interface %s not running", ifp->name); - return 0; - } - - /* Set running flag. */ - ri->running = 1; + /* Join to multicast group. */ + if (ripng_multicast_join(ifp) < 0) { + zlog_err("multicast join failed, interface %s not running", + ifp->name); + return 0; + } + + /* Set running flag. */ + ri->running = 1; - /* Send RIP request to the interface. */ - ripng_request (ifp); + /* Send RIP request to the interface. */ + ripng_request(ifp); - return 0; + return 0; } -static void -ripng_connect_set (struct interface *ifp, int set) +static void ripng_connect_set(struct interface *ifp, int set) { - struct listnode *node, *nnode; - struct connected *connected; - struct prefix_ipv6 address; - - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected)) - { - struct prefix *p; - p = connected->address; - - if (p->family != AF_INET6) - continue; - - address.family = AF_INET6; - address.prefix = p->u.prefix6; - address.prefixlen = p->prefixlen; - apply_mask_ipv6 (&address); - - if (set) { - /* Check once more wether this prefix is within a "network IF_OR_PREF" one */ - if ((ripng_enable_if_lookup(connected->ifp->name) >= 0) || - (ripng_enable_network_lookup2(connected) >= 0)) - ripng_redistribute_add (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE, - &address, connected->ifp->ifindex, NULL, 0); - } else { - ripng_redistribute_delete (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE, - &address, connected->ifp->ifindex); - if (ripng_redistribute_check (ZEBRA_ROUTE_CONNECT)) - ripng_redistribute_add (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_REDISTRIBUTE, - &address, connected->ifp->ifindex, NULL, 0); - } - } + struct listnode *node, *nnode; + struct connected *connected; + struct prefix_ipv6 address; + + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) { + struct prefix *p; + p = connected->address; + + if (p->family != AF_INET6) + continue; + + address.family = AF_INET6; + address.prefix = p->u.prefix6; + address.prefixlen = p->prefixlen; + apply_mask_ipv6(&address); + + if (set) { + /* Check once more wether this prefix is within a + * "network IF_OR_PREF" one */ + if ((ripng_enable_if_lookup(connected->ifp->name) >= 0) + || (ripng_enable_network_lookup2(connected) >= 0)) + ripng_redistribute_add( + ZEBRA_ROUTE_CONNECT, + RIPNG_ROUTE_INTERFACE, &address, + connected->ifp->ifindex, NULL, 0); + } else { + ripng_redistribute_delete( + ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE, + &address, connected->ifp->ifindex); + if (ripng_redistribute_check(ZEBRA_ROUTE_CONNECT)) + ripng_redistribute_add( + ZEBRA_ROUTE_CONNECT, + RIPNG_ROUTE_REDISTRIBUTE, &address, + connected->ifp->ifindex, NULL, 0); + } + } } /* Check RIPng is enabed on this interface. */ -void -ripng_enable_apply (struct interface *ifp) +void ripng_enable_apply(struct interface *ifp) { - int ret; - struct ripng_interface *ri = NULL; - - /* Check interface. */ - if (! if_is_up (ifp)) - return; - - ri = ifp->info; - - /* Is this interface a candidate for RIPng ? */ - ret = ripng_enable_network_lookup_if (ifp); - - /* If the interface is matched. */ - if (ret > 0) - ri->enable_network = 1; - else - ri->enable_network = 0; - - /* Check interface name configuration. */ - ret = ripng_enable_if_lookup (ifp->name); - if (ret >= 0) - ri->enable_interface = 1; - else - ri->enable_interface = 0; - - /* any candidate interface MUST have a link-local IPv6 address */ - if ((! ripng_if_ipv6_lladdress_check (ifp)) && - (ri->enable_network || ri->enable_interface)) { - ri->enable_network = 0; - ri->enable_interface = 0; - zlog_warn("Interface %s does not have any link-local address", - ifp->name); - } - - /* Update running status of the interface. */ - if (ri->enable_network || ri->enable_interface) - { - zlog_info ("RIPng INTERFACE ON %s", ifp->name); - - /* Add interface wake up thread. */ - thread_add_timer(master, ripng_interface_wakeup, ifp, 1, - &ri->t_wakeup); - - ripng_connect_set (ifp, 1); - } - else - { - if (ri->running) - { - /* Might as well clean up the route table as well - * ripng_if_down sets to 0 ri->running, and displays "turn off %s" - **/ - ripng_if_down(ifp); - - ripng_connect_set (ifp, 0); + int ret; + struct ripng_interface *ri = NULL; + + /* Check interface. */ + if (!if_is_up(ifp)) + return; + + ri = ifp->info; + + /* Is this interface a candidate for RIPng ? */ + ret = ripng_enable_network_lookup_if(ifp); + + /* If the interface is matched. */ + if (ret > 0) + ri->enable_network = 1; + else + ri->enable_network = 0; + + /* Check interface name configuration. */ + ret = ripng_enable_if_lookup(ifp->name); + if (ret >= 0) + ri->enable_interface = 1; + else + ri->enable_interface = 0; + + /* any candidate interface MUST have a link-local IPv6 address */ + if ((!ripng_if_ipv6_lladdress_check(ifp)) + && (ri->enable_network || ri->enable_interface)) { + ri->enable_network = 0; + ri->enable_interface = 0; + zlog_warn("Interface %s does not have any link-local address", + ifp->name); + } + + /* Update running status of the interface. */ + if (ri->enable_network || ri->enable_interface) { + zlog_info("RIPng INTERFACE ON %s", ifp->name); + + /* Add interface wake up thread. */ + thread_add_timer(master, ripng_interface_wakeup, ifp, 1, + &ri->t_wakeup); + + ripng_connect_set(ifp, 1); + } else { + if (ri->running) { + /* Might as well clean up the route table as well + * ripng_if_down sets to 0 ri->running, and displays + *"turn off %s" + **/ + ripng_if_down(ifp); + + ripng_connect_set(ifp, 0); + } } - } } /* Set distribute list to all interfaces. */ -static void -ripng_enable_apply_all (void) +static void ripng_enable_apply_all(void) { - struct interface *ifp; - struct listnode *node; + struct interface *ifp; + struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - ripng_enable_apply (ifp); + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) + ripng_enable_apply(ifp); } /* Clear all network and neighbor configuration */ -void -ripng_clean_network () +void ripng_clean_network() { - unsigned int i; - char *str; - struct route_node *rn; - - /* ripng_enable_network */ - for (rn = route_top (ripng_enable_network); rn; rn = route_next (rn)) - if (rn->info) { - rn->info = NULL; - route_unlock_node(rn); - } - - /* ripng_enable_if */ - for (i = 0; i < vector_active (ripng_enable_if); i++) - if ((str = vector_slot (ripng_enable_if, i)) != NULL) { - free (str); - vector_slot (ripng_enable_if, i) = NULL; - } + unsigned int i; + char *str; + struct route_node *rn; + + /* ripng_enable_network */ + for (rn = route_top(ripng_enable_network); rn; rn = route_next(rn)) + if (rn->info) { + rn->info = NULL; + route_unlock_node(rn); + } + + /* ripng_enable_if */ + for (i = 0; i < vector_active(ripng_enable_if); i++) + if ((str = vector_slot(ripng_enable_if, i)) != NULL) { + free(str); + vector_slot(ripng_enable_if, i) = NULL; + } } /* Vector to store passive-interface name. */ vector Vripng_passive_interface; /* Utility function for looking up passive interface settings. */ -static int -ripng_passive_interface_lookup (const char *ifname) +static int ripng_passive_interface_lookup(const char *ifname) { - unsigned int i; - char *str; - - for (i = 0; i < vector_active (Vripng_passive_interface); i++) - if ((str = vector_slot (Vripng_passive_interface, i)) != NULL) - if (strcmp (str, ifname) == 0) - return i; - return -1; + unsigned int i; + char *str; + + for (i = 0; i < vector_active(Vripng_passive_interface); i++) + if ((str = vector_slot(Vripng_passive_interface, i)) != NULL) + if (strcmp(str, ifname) == 0) + return i; + return -1; } -void -ripng_passive_interface_apply (struct interface *ifp) +void ripng_passive_interface_apply(struct interface *ifp) { - int ret; - struct ripng_interface *ri; + int ret; + struct ripng_interface *ri; - ri = ifp->info; + ri = ifp->info; - ret = ripng_passive_interface_lookup (ifp->name); - if (ret < 0) - ri->passive = 0; - else - ri->passive = 1; + ret = ripng_passive_interface_lookup(ifp->name); + if (ret < 0) + ri->passive = 0; + else + ri->passive = 1; } -static void -ripng_passive_interface_apply_all (void) +static void ripng_passive_interface_apply_all(void) { - struct interface *ifp; - struct listnode *node; + struct interface *ifp; + struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - ripng_passive_interface_apply (ifp); + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) + ripng_passive_interface_apply(ifp); } /* Passive interface. */ -static int -ripng_passive_interface_set (struct vty *vty, const char *ifname) +static int ripng_passive_interface_set(struct vty *vty, const char *ifname) { - if (ripng_passive_interface_lookup (ifname) >= 0) - return CMD_WARNING_CONFIG_FAILED; + if (ripng_passive_interface_lookup(ifname) >= 0) + return CMD_WARNING_CONFIG_FAILED; - vector_set (Vripng_passive_interface, strdup (ifname)); + vector_set(Vripng_passive_interface, strdup(ifname)); - ripng_passive_interface_apply_all (); + ripng_passive_interface_apply_all(); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -ripng_passive_interface_unset (struct vty *vty, const char *ifname) +static int ripng_passive_interface_unset(struct vty *vty, const char *ifname) { - int i; - char *str; + int i; + char *str; - i = ripng_passive_interface_lookup (ifname); - if (i < 0) - return CMD_WARNING_CONFIG_FAILED; + i = ripng_passive_interface_lookup(ifname); + if (i < 0) + return CMD_WARNING_CONFIG_FAILED; - str = vector_slot (Vripng_passive_interface, i); - free (str); - vector_unset (Vripng_passive_interface, i); + str = vector_slot(Vripng_passive_interface, i); + free(str); + vector_unset(Vripng_passive_interface, i); - ripng_passive_interface_apply_all (); + ripng_passive_interface_apply_all(); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Free all configured RIP passive-interface settings. */ -void -ripng_passive_interface_clean (void) +void ripng_passive_interface_clean(void) { - unsigned int i; - char *str; - - for (i = 0; i < vector_active (Vripng_passive_interface); i++) - if ((str = vector_slot (Vripng_passive_interface, i)) != NULL) - { - free (str); - vector_slot (Vripng_passive_interface, i) = NULL; - } - ripng_passive_interface_apply_all (); + unsigned int i; + char *str; + + for (i = 0; i < vector_active(Vripng_passive_interface); i++) + if ((str = vector_slot(Vripng_passive_interface, i)) != NULL) { + free(str); + vector_slot(Vripng_passive_interface, i) = NULL; + } + ripng_passive_interface_apply_all(); } /* Write RIPng enable network and interface to the vty. */ -int -ripng_network_write (struct vty *vty, int config_mode) +int ripng_network_write(struct vty *vty, int config_mode) { - unsigned int i; - const char *ifname; - struct route_node *node; - char buf[BUFSIZ]; - - /* Write enable network. */ - for (node = route_top (ripng_enable_network); node; node = route_next (node)) - if (node->info) - { - struct prefix *p = &node->p; - vty_out (vty, "%s%s/%d\n", - config_mode ? " network " : " ", - inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), - p->prefixlen); - - } - - /* Write enable interface. */ - for (i = 0; i < vector_active (ripng_enable_if); i++) - if ((ifname = vector_slot (ripng_enable_if, i)) != NULL) - vty_out (vty, "%s%s\n", - config_mode ? " network " : " ", - ifname); - - /* Write passive interface. */ - if (config_mode) - for (i = 0; i < vector_active (Vripng_passive_interface); i++) - if ((ifname = vector_slot (Vripng_passive_interface, i)) != NULL) - vty_out (vty, " passive-interface %s\n", ifname); - - return 0; + unsigned int i; + const char *ifname; + struct route_node *node; + char buf[BUFSIZ]; + + /* Write enable network. */ + for (node = route_top(ripng_enable_network); node; + node = route_next(node)) + if (node->info) { + struct prefix *p = &node->p; + vty_out(vty, "%s%s/%d\n", + config_mode ? " network " : " ", + inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), + p->prefixlen); + } + + /* Write enable interface. */ + for (i = 0; i < vector_active(ripng_enable_if); i++) + if ((ifname = vector_slot(ripng_enable_if, i)) != NULL) + vty_out(vty, "%s%s\n", + config_mode ? " network " : " ", ifname); + + /* Write passive interface. */ + if (config_mode) + for (i = 0; i < vector_active(Vripng_passive_interface); i++) + if ((ifname = vector_slot(Vripng_passive_interface, i)) + != NULL) + vty_out(vty, " passive-interface %s\n", ifname); + + return 0; } /* RIPng enable on specified interface or matched network. */ @@ -946,26 +915,25 @@ DEFUN (ripng_network, "RIPng enable on specified interface or network.\n" "Interface or address\n") { - int idx_if_or_addr = 1; - int ret; - struct prefix p; - - ret = str2prefix (argv[idx_if_or_addr]->arg, &p); - - /* Given string is IPv6 network or interface name. */ - if (ret) - ret = ripng_enable_network_add (&p); - else - ret = ripng_enable_if_add (argv[idx_if_or_addr]->arg); - - if (ret < 0) - { - vty_out (vty, "There is same network configuration %s\n", - argv[idx_if_or_addr]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + int idx_if_or_addr = 1; + int ret; + struct prefix p; + + ret = str2prefix(argv[idx_if_or_addr]->arg, &p); + + /* Given string is IPv6 network or interface name. */ + if (ret) + ret = ripng_enable_network_add(&p); + else + ret = ripng_enable_if_add(argv[idx_if_or_addr]->arg); + + if (ret < 0) { + vty_out(vty, "There is same network configuration %s\n", + argv[idx_if_or_addr]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } /* RIPng enable on specified interface or matched network. */ @@ -976,25 +944,25 @@ DEFUN (no_ripng_network, "RIPng enable on specified interface or network.\n" "Interface or address\n") { - int idx_if_or_addr = 2; - int ret; - struct prefix p; - - ret = str2prefix (argv[idx_if_or_addr]->arg, &p); - - /* Given string is interface name. */ - if (ret) - ret = ripng_enable_network_delete (&p); - else - ret = ripng_enable_if_delete (argv[idx_if_or_addr]->arg); - - if (ret < 0) - { - vty_out (vty, "can't find network %s\n",argv[idx_if_or_addr]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + int idx_if_or_addr = 2; + int ret; + struct prefix p; + + ret = str2prefix(argv[idx_if_or_addr]->arg, &p); + + /* Given string is interface name. */ + if (ret) + ret = ripng_enable_network_delete(&p); + else + ret = ripng_enable_if_delete(argv[idx_if_or_addr]->arg); + + if (ret < 0) { + vty_out(vty, "can't find network %s\n", + argv[idx_if_or_addr]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } DEFUN (ipv6_ripng_split_horizon, @@ -1004,13 +972,13 @@ DEFUN (ipv6_ripng_split_horizon, "Routing Information Protocol\n" "Perform split horizon\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct ripng_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ripng_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->split_horizon = RIPNG_SPLIT_HORIZON; - return CMD_SUCCESS; + ri->split_horizon = RIPNG_SPLIT_HORIZON; + return CMD_SUCCESS; } DEFUN (ipv6_ripng_split_horizon_poisoned_reverse, @@ -1021,13 +989,13 @@ DEFUN (ipv6_ripng_split_horizon_poisoned_reverse, "Perform split horizon\n" "With poisoned-reverse\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct ripng_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ripng_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->split_horizon = RIPNG_SPLIT_HORIZON_POISONED_REVERSE; - return CMD_SUCCESS; + ri->split_horizon = RIPNG_SPLIT_HORIZON_POISONED_REVERSE; + return CMD_SUCCESS; } DEFUN (no_ipv6_ripng_split_horizon, @@ -1039,13 +1007,13 @@ DEFUN (no_ipv6_ripng_split_horizon, "Perform split horizon\n" "With poisoned-reverse\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct ripng_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ripng_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->split_horizon = RIPNG_NO_SPLIT_HORIZON; - return CMD_SUCCESS; + ri->split_horizon = RIPNG_NO_SPLIT_HORIZON; + return CMD_SUCCESS; } DEFUN (ripng_passive_interface, @@ -1054,8 +1022,8 @@ DEFUN (ripng_passive_interface, "Suppress routing updates on an interface\n" "Interface name\n") { - int idx_ifname = 1; - return ripng_passive_interface_set (vty, argv[idx_ifname]->arg); + int idx_ifname = 1; + return ripng_passive_interface_set(vty, argv[idx_ifname]->arg); } DEFUN (no_ripng_passive_interface, @@ -1065,125 +1033,117 @@ DEFUN (no_ripng_passive_interface, "Suppress routing updates on an interface\n" "Interface name\n") { - int idx_ifname = 2; - return ripng_passive_interface_unset (vty, argv[idx_ifname]->arg); + int idx_ifname = 2; + return ripng_passive_interface_unset(vty, argv[idx_ifname]->arg); } -static struct ripng_interface * -ri_new (void) +static struct ripng_interface *ri_new(void) { - struct ripng_interface *ri; - ri = XCALLOC (MTYPE_IF, sizeof (struct ripng_interface)); + struct ripng_interface *ri; + ri = XCALLOC(MTYPE_IF, sizeof(struct ripng_interface)); - /* Set default split-horizon behavior. If the interface is Frame - Relay or SMDS is enabled, the default value for split-horizon is - off. But currently Zebra does detect Frame Relay or SMDS - interface. So all interface is set to split horizon. */ - ri->split_horizon_default = RIPNG_SPLIT_HORIZON; - ri->split_horizon = ri->split_horizon_default; + /* Set default split-horizon behavior. If the interface is Frame + Relay or SMDS is enabled, the default value for split-horizon is + off. But currently Zebra does detect Frame Relay or SMDS + interface. So all interface is set to split horizon. */ + ri->split_horizon_default = RIPNG_SPLIT_HORIZON; + ri->split_horizon = ri->split_horizon_default; - return ri; + return ri; } -static int -ripng_if_new_hook (struct interface *ifp) +static int ripng_if_new_hook(struct interface *ifp) { - ifp->info = ri_new (); - return 0; + ifp->info = ri_new(); + return 0; } /* Called when interface structure deleted. */ -static int -ripng_if_delete_hook (struct interface *ifp) +static int ripng_if_delete_hook(struct interface *ifp) { - XFREE (MTYPE_IF, ifp->info); - ifp->info = NULL; - return 0; + XFREE(MTYPE_IF, ifp->info); + ifp->info = NULL; + return 0; } /* Configuration write function for ripngd. */ -static int -interface_config_write (struct vty *vty) +static int interface_config_write(struct vty *vty) { - struct listnode *node; - struct interface *ifp; - struct ripng_interface *ri; - int write = 0; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - ri = ifp->info; - - /* Do not display the interface if there is no - * configuration about it. - **/ - if ((!ifp->desc) && - (ri->split_horizon == ri->split_horizon_default)) - continue; - - vty_out (vty, "interface %s\n",ifp->name); - if (ifp->desc) - vty_out (vty, " description %s\n",ifp->desc); - - /* Split horizon. */ - if (ri->split_horizon != ri->split_horizon_default) - { - switch (ri->split_horizon) { - case RIPNG_SPLIT_HORIZON: - vty_out (vty, " ipv6 ripng split-horizon\n"); - break; - case RIPNG_SPLIT_HORIZON_POISONED_REVERSE: - vty_out (vty," ipv6 ripng split-horizon poisoned-reverse\n"); - break; - case RIPNG_NO_SPLIT_HORIZON: - default: - vty_out (vty, " no ipv6 ripng split-horizon\n"); - break; - } + struct listnode *node; + struct interface *ifp; + struct ripng_interface *ri; + int write = 0; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + ri = ifp->info; + + /* Do not display the interface if there is no + * configuration about it. + **/ + if ((!ifp->desc) + && (ri->split_horizon == ri->split_horizon_default)) + continue; + + vty_out(vty, "interface %s\n", ifp->name); + if (ifp->desc) + vty_out(vty, " description %s\n", ifp->desc); + + /* Split horizon. */ + if (ri->split_horizon != ri->split_horizon_default) { + switch (ri->split_horizon) { + case RIPNG_SPLIT_HORIZON: + vty_out(vty, " ipv6 ripng split-horizon\n"); + break; + case RIPNG_SPLIT_HORIZON_POISONED_REVERSE: + vty_out(vty, + " ipv6 ripng split-horizon poisoned-reverse\n"); + break; + case RIPNG_NO_SPLIT_HORIZON: + default: + vty_out(vty, " no ipv6 ripng split-horizon\n"); + break; + } + } + + vty_out(vty, "!\n"); + + write++; } - - vty_out (vty, "!\n"); - - write++; - } - return write; + return write; } /* ripngd's interface node. */ -static struct cmd_node interface_node = -{ - INTERFACE_NODE, - "%s(config-if)# ", - 1 /* VTYSH */ +static struct cmd_node interface_node = { + INTERFACE_NODE, "%s(config-if)# ", 1 /* VTYSH */ }; /* Initialization of interface. */ -void -ripng_if_init () +void ripng_if_init() { - /* Interface initialize. */ - if_add_hook (IF_NEW_HOOK, ripng_if_new_hook); - if_add_hook (IF_DELETE_HOOK, ripng_if_delete_hook); + /* Interface initialize. */ + if_add_hook(IF_NEW_HOOK, ripng_if_new_hook); + if_add_hook(IF_DELETE_HOOK, ripng_if_delete_hook); - /* RIPng enable network init. */ - ripng_enable_network = route_table_init (); + /* RIPng enable network init. */ + ripng_enable_network = route_table_init(); - /* RIPng enable interface init. */ - ripng_enable_if = vector_init (1); + /* RIPng enable interface init. */ + ripng_enable_if = vector_init(1); - /* RIPng passive interface. */ - Vripng_passive_interface = vector_init (1); + /* RIPng passive interface. */ + Vripng_passive_interface = vector_init(1); - /* Install interface node. */ - install_node (&interface_node, interface_config_write); - if_cmd_init (); + /* Install interface node. */ + install_node(&interface_node, interface_config_write); + if_cmd_init(); - install_element (RIPNG_NODE, &ripng_network_cmd); - install_element (RIPNG_NODE, &no_ripng_network_cmd); - install_element (RIPNG_NODE, &ripng_passive_interface_cmd); - install_element (RIPNG_NODE, &no_ripng_passive_interface_cmd); + install_element(RIPNG_NODE, &ripng_network_cmd); + install_element(RIPNG_NODE, &no_ripng_network_cmd); + install_element(RIPNG_NODE, &ripng_passive_interface_cmd); + install_element(RIPNG_NODE, &no_ripng_passive_interface_cmd); - install_element (INTERFACE_NODE, &ipv6_ripng_split_horizon_cmd); - install_element (INTERFACE_NODE, &ipv6_ripng_split_horizon_poisoned_reverse_cmd); - install_element (INTERFACE_NODE, &no_ipv6_ripng_split_horizon_cmd); + install_element(INTERFACE_NODE, &ipv6_ripng_split_horizon_cmd); + install_element(INTERFACE_NODE, + &ipv6_ripng_split_horizon_poisoned_reverse_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ripng_split_horizon_cmd); } diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c index 9d700305e..0cb54d433 100644 --- a/ripngd/ripng_main.c +++ b/ripngd/ripng_main.c @@ -40,34 +40,24 @@ #include "ripngd/ripngd.h" /* RIPngd options. */ -struct option longopts[] = -{ - { "retain", no_argument, NULL, 'r'}, - { 0 } -}; +struct option longopts[] = {{"retain", no_argument, NULL, 'r'}, {0}}; /* ripngd privileges */ -zebra_capabilities_t _caps_p [] = -{ - ZCAP_NET_RAW, - ZCAP_BIND -}; +zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND}; -struct zebra_privs_t ripngd_privs = -{ +struct zebra_privs_t ripngd_privs = { #if defined(FRR_USER) - .user = FRR_USER, + .user = FRR_USER, #endif #if defined FRR_GROUP - .group = FRR_GROUP, + .group = FRR_GROUP, #endif #ifdef VTY_GROUP - .vty_group = VTY_GROUP, + .vty_group = VTY_GROUP, #endif - .caps_p = _caps_p, - .cap_num_p = 2, - .cap_num_i = 0 -}; + .caps_p = _caps_p, + .cap_num_p = 2, + .cap_num_i = 0}; /* RIPngd program name */ @@ -81,113 +71,105 @@ struct thread_master *master; static struct frr_daemon_info ripngd_di; /* SIGHUP handler. */ -static void -sighup (void) +static void sighup(void) { - zlog_info ("SIGHUP received"); - ripng_clean (); - ripng_reset (); + zlog_info("SIGHUP received"); + ripng_clean(); + ripng_reset(); - /* Reload config file. */ - vty_read_config (ripngd_di.config_file, config_default); + /* Reload config file. */ + vty_read_config(ripngd_di.config_file, config_default); - /* Try to return to normal operation. */ + /* Try to return to normal operation. */ } /* SIGINT handler. */ -static void -sigint (void) +static void sigint(void) { - zlog_notice ("Terminating on signal"); + zlog_notice("Terminating on signal"); - if (! retain_mode) - ripng_clean (); + if (!retain_mode) + ripng_clean(); - ripng_zebra_stop (); - exit (0); + ripng_zebra_stop(); + exit(0); } /* SIGUSR1 handler. */ -static void -sigusr1 (void) +static void sigusr1(void) { - zlog_rotate(); + zlog_rotate(); } -struct quagga_signal_t ripng_signals[] = -{ - { - .signal = SIGHUP, - .handler = &sighup, - }, - { - .signal = SIGUSR1, - .handler = &sigusr1, - }, - { - .signal = SIGINT, - .handler = &sigint, - }, - { - .signal = SIGTERM, - .handler = &sigint, - }, +struct quagga_signal_t ripng_signals[] = { + { + .signal = SIGHUP, + .handler = &sighup, + }, + { + .signal = SIGUSR1, + .handler = &sigusr1, + }, + { + .signal = SIGINT, + .handler = &sigint, + }, + { + .signal = SIGTERM, + .handler = &sigint, + }, }; -FRR_DAEMON_INFO(ripngd, RIPNG, - .vty_port = RIPNG_VTY_PORT, +FRR_DAEMON_INFO(ripngd, RIPNG, .vty_port = RIPNG_VTY_PORT, - .proghelp = "Implementation of the RIPng routing protocol.", + .proghelp = "Implementation of the RIPng routing protocol.", - .signals = ripng_signals, - .n_signals = array_size(ripng_signals), + .signals = ripng_signals, + .n_signals = array_size(ripng_signals), - .privs = &ripngd_privs, -) + .privs = &ripngd_privs, ) /* RIPngd main routine. */ -int -main (int argc, char **argv) +int main(int argc, char **argv) { - frr_preinit (&ripngd_di, argc, argv); - frr_opt_add ("r", longopts, - " -r, --retain When program terminates, retain added route by ripd.\n"); - - while (1) - { - int opt; - - opt = frr_getopt (argc, argv, NULL); - - if (opt == EOF) - break; - - switch (opt) - { - case 0: - break; - case 'r': - retain_mode = 1; - break; - default: - frr_help_exit (1); - break; + frr_preinit(&ripngd_di, argc, argv); + frr_opt_add( + "r", longopts, + " -r, --retain When program terminates, retain added route by ripd.\n"); + + while (1) { + int opt; + + opt = frr_getopt(argc, argv, NULL); + + if (opt == EOF) + break; + + switch (opt) { + case 0: + break; + case 'r': + retain_mode = 1; + break; + default: + frr_help_exit(1); + break; + } } - } - master = frr_init (); + master = frr_init(); - /* Library inits. */ - vrf_init (NULL, NULL, NULL, NULL); + /* Library inits. */ + vrf_init(NULL, NULL, NULL, NULL); - /* RIPngd inits. */ - ripng_init (); - zebra_init(master); - ripng_peer_init (); + /* RIPngd inits. */ + ripng_init(); + zebra_init(master); + ripng_peer_init(); - frr_config_fork (); - frr_run (master); + frr_config_fork(); + frr_run(master); - /* Not reached. */ - return 0; + /* Not reached. */ + return 0; } diff --git a/ripngd/ripng_memory.c b/ripngd/ripng_memory.c index 60fb1751d..0cb24052e 100644 --- a/ripngd/ripng_memory.c +++ b/ripngd/ripng_memory.c @@ -26,9 +26,9 @@ #include "ripng_memory.h" DEFINE_MGROUP(RIPNGD, "ripngd") -DEFINE_MTYPE(RIPNGD, RIPNG, "RIPng structure") -DEFINE_MTYPE(RIPNGD, RIPNG_ROUTE, "RIPng route info") -DEFINE_MTYPE(RIPNGD, RIPNG_AGGREGATE, "RIPng aggregate") -DEFINE_MTYPE(RIPNGD, RIPNG_PEER, "RIPng peer") +DEFINE_MTYPE(RIPNGD, RIPNG, "RIPng structure") +DEFINE_MTYPE(RIPNGD, RIPNG_ROUTE, "RIPng route info") +DEFINE_MTYPE(RIPNGD, RIPNG_AGGREGATE, "RIPng aggregate") +DEFINE_MTYPE(RIPNGD, RIPNG_PEER, "RIPng peer") DEFINE_MTYPE(RIPNGD, RIPNG_OFFSET_LIST, "RIPng offset lst") -DEFINE_MTYPE(RIPNGD, RIPNG_RTE_DATA, "RIPng rte data") +DEFINE_MTYPE(RIPNGD, RIPNG_RTE_DATA, "RIPng rte data") diff --git a/ripngd/ripng_nexthop.c b/ripngd/ripng_nexthop.c index 0af636efc..75b3c9dfe 100644 --- a/ripngd/ripng_nexthop.c +++ b/ripngd/ripng_nexthop.c @@ -44,41 +44,41 @@ #define min(a, b) ((a) < (b) ? (a) : (b)) struct ripng_rte_data { - struct prefix_ipv6 *p; - struct ripng_info *rinfo; - struct ripng_aggregate *aggregate; + struct prefix_ipv6 *p; + struct ripng_info *rinfo; + struct ripng_aggregate *aggregate; }; void _ripng_rte_del(struct ripng_rte_data *A); int _ripng_rte_cmp(struct ripng_rte_data *A, struct ripng_rte_data *B); -#define METRIC_OUT(a) \ - ((a)->rinfo ? (a)->rinfo->metric_out : (a)->aggregate->metric_out) -#define NEXTHOP_OUT_PTR(a) \ - ((a)->rinfo ? &((a)->rinfo->nexthop_out) : &((a)->aggregate->nexthop_out)) -#define TAG_OUT(a) \ - ((a)->rinfo ? (a)->rinfo->tag_out : (a)->aggregate->tag_out) +#define METRIC_OUT(a) \ + ((a)->rinfo ? (a)->rinfo->metric_out : (a)->aggregate->metric_out) +#define NEXTHOP_OUT_PTR(a) \ + ((a)->rinfo ? &((a)->rinfo->nexthop_out) \ + : &((a)->aggregate->nexthop_out)) +#define TAG_OUT(a) ((a)->rinfo ? (a)->rinfo->tag_out : (a)->aggregate->tag_out) -struct list * -ripng_rte_new(void) { - struct list *rte; +struct list *ripng_rte_new(void) +{ + struct list *rte; - rte = list_new(); - rte->cmp = (int (*)(void *, void *)) _ripng_rte_cmp; - rte->del = (void (*)(void *)) _ripng_rte_del; + rte = list_new(); + rte->cmp = (int (*)(void *, void *))_ripng_rte_cmp; + rte->del = (void (*)(void *))_ripng_rte_del; - return rte; + return rte; } -void -ripng_rte_free(struct list *ripng_rte_list) { - list_delete(ripng_rte_list); +void ripng_rte_free(struct list *ripng_rte_list) +{ + list_delete(ripng_rte_list); } /* Delete RTE */ -void -_ripng_rte_del(struct ripng_rte_data *A) { - XFREE(MTYPE_RIPNG_RTE_DATA, A); +void _ripng_rte_del(struct ripng_rte_data *A) +{ + XFREE(MTYPE_RIPNG_RTE_DATA, A); } /* Compare RTE: @@ -86,128 +86,138 @@ _ripng_rte_del(struct ripng_rte_data *A) { * 0 if A = B * - if A < B */ -int -_ripng_rte_cmp(struct ripng_rte_data *A, struct ripng_rte_data *B) { - return addr6_cmp(NEXTHOP_OUT_PTR(A), NEXTHOP_OUT_PTR(B)); +int _ripng_rte_cmp(struct ripng_rte_data *A, struct ripng_rte_data *B) +{ + return addr6_cmp(NEXTHOP_OUT_PTR(A), NEXTHOP_OUT_PTR(B)); } /* Add routing table entry */ -void -ripng_rte_add(struct list *ripng_rte_list, struct prefix_ipv6 *p, - struct ripng_info *rinfo, struct ripng_aggregate *aggregate) { +void ripng_rte_add(struct list *ripng_rte_list, struct prefix_ipv6 *p, + struct ripng_info *rinfo, struct ripng_aggregate *aggregate) +{ - struct ripng_rte_data *data; + struct ripng_rte_data *data; - /* At least one should not be null */ - assert(!rinfo || !aggregate); + /* At least one should not be null */ + assert(!rinfo || !aggregate); - data = XMALLOC(MTYPE_RIPNG_RTE_DATA, sizeof(*data)); - data->p = p; - data->rinfo = rinfo; - data->aggregate = aggregate; + data = XMALLOC(MTYPE_RIPNG_RTE_DATA, sizeof(*data)); + data->p = p; + data->rinfo = rinfo; + data->aggregate = aggregate; - listnode_add_sort(ripng_rte_list, data); -} + listnode_add_sort(ripng_rte_list, data); +} /* Send the RTE with the nexthop support */ -void -ripng_rte_send(struct list *ripng_rte_list, struct interface *ifp, - struct sockaddr_in6 *to) { - - struct ripng_rte_data *data; - struct listnode *node, *nnode; - - struct in6_addr last_nexthop; - struct in6_addr myself_nexthop; - - struct stream *s; - int num; - int mtu; - int rtemax; - int ret; - - /* Most of the time, there is no nexthop */ - memset(&last_nexthop, 0, sizeof(last_nexthop)); - - /* Use myself_nexthop if the nexthop is not a link-local address, because - * we remain a right path without beeing the optimal one. - */ - memset(&myself_nexthop, 0, sizeof(myself_nexthop)); - - /* Output stream get from ripng structre. XXX this should be - interface structure. */ - s = ripng->obuf; - - /* Reset stream and RTE counter. */ - stream_reset (s); - num = 0; - - mtu = ifp->mtu6; - if (mtu < 0) - mtu = IFMINMTU; - - rtemax = (min (mtu, RIPNG_MAX_PACKET_SIZE) - - IPV6_HDRLEN - - sizeof (struct udphdr) - - sizeof (struct ripng_packet) + - sizeof (struct rte)) / sizeof (struct rte); - - for (ALL_LIST_ELEMENTS (ripng_rte_list, node, nnode, data)) { - /* (2.1) Next hop support */ - if (!IPV6_ADDR_SAME(&last_nexthop, NEXTHOP_OUT_PTR(data))) { - - /* A nexthop entry should be at least followed by 1 RTE */ - if (num == (rtemax-1)) { - ret = ripng_send_packet ((caddr_t) STREAM_DATA (s), stream_get_endp (s), - to, ifp); - - if (ret >= 0 && IS_RIPNG_DEBUG_SEND) - ripng_packet_dump((struct ripng_packet *)STREAM_DATA (s), - stream_get_endp(s), "SEND"); - num = 0; - stream_reset (s); - } - - /* Add the nexthop (2.1) */ - - /* If the received next hop address is not a link-local address, - * it should be treated as 0:0:0:0:0:0:0:0. - */ - if (!IN6_IS_ADDR_LINKLOCAL(NEXTHOP_OUT_PTR(data))) - last_nexthop = myself_nexthop; - else - last_nexthop = *NEXTHOP_OUT_PTR(data); - - num = ripng_write_rte(num, s, NULL, &last_nexthop, 0, RIPNG_METRIC_NEXTHOP); - } else { - /* Rewrite the nexthop for each new packet */ - if ((num == 0) && !IPV6_ADDR_SAME(&last_nexthop, &myself_nexthop)) - num = ripng_write_rte(num, s, NULL, &last_nexthop, 0, RIPNG_METRIC_NEXTHOP); - } - num = ripng_write_rte(num, s, data->p, NULL, - TAG_OUT(data), METRIC_OUT(data)); - - if (num == rtemax) { - ret = ripng_send_packet ((caddr_t) STREAM_DATA (s), stream_get_endp (s), - to, ifp); - - if (ret >= 0 && IS_RIPNG_DEBUG_SEND) - ripng_packet_dump((struct ripng_packet *)STREAM_DATA (s), - stream_get_endp(s), "SEND"); - num = 0; - stream_reset (s); - } - } - - /* If unwritten RTE exist, flush it. */ - if (num != 0) { - ret = ripng_send_packet ((caddr_t) STREAM_DATA (s), stream_get_endp (s), - to, ifp); - - if (ret >= 0 && IS_RIPNG_DEBUG_SEND) - ripng_packet_dump ((struct ripng_packet *)STREAM_DATA (s), - stream_get_endp (s), "SEND"); - stream_reset (s); - } +void ripng_rte_send(struct list *ripng_rte_list, struct interface *ifp, + struct sockaddr_in6 *to) +{ + + struct ripng_rte_data *data; + struct listnode *node, *nnode; + + struct in6_addr last_nexthop; + struct in6_addr myself_nexthop; + + struct stream *s; + int num; + int mtu; + int rtemax; + int ret; + + /* Most of the time, there is no nexthop */ + memset(&last_nexthop, 0, sizeof(last_nexthop)); + + /* Use myself_nexthop if the nexthop is not a link-local address, + * because + * we remain a right path without beeing the optimal one. + */ + memset(&myself_nexthop, 0, sizeof(myself_nexthop)); + + /* Output stream get from ripng structre. XXX this should be + interface structure. */ + s = ripng->obuf; + + /* Reset stream and RTE counter. */ + stream_reset(s); + num = 0; + + mtu = ifp->mtu6; + if (mtu < 0) + mtu = IFMINMTU; + + rtemax = (min(mtu, RIPNG_MAX_PACKET_SIZE) - IPV6_HDRLEN + - sizeof(struct udphdr) - sizeof(struct ripng_packet) + + sizeof(struct rte)) + / sizeof(struct rte); + + for (ALL_LIST_ELEMENTS(ripng_rte_list, node, nnode, data)) { + /* (2.1) Next hop support */ + if (!IPV6_ADDR_SAME(&last_nexthop, NEXTHOP_OUT_PTR(data))) { + + /* A nexthop entry should be at least followed by 1 RTE + */ + if (num == (rtemax - 1)) { + ret = ripng_send_packet((caddr_t)STREAM_DATA(s), + stream_get_endp(s), to, + ifp); + + if (ret >= 0 && IS_RIPNG_DEBUG_SEND) + ripng_packet_dump( + (struct ripng_packet *) + STREAM_DATA(s), + stream_get_endp(s), "SEND"); + num = 0; + stream_reset(s); + } + + /* Add the nexthop (2.1) */ + + /* If the received next hop address is not a link-local + * address, + * it should be treated as 0:0:0:0:0:0:0:0. + */ + if (!IN6_IS_ADDR_LINKLOCAL(NEXTHOP_OUT_PTR(data))) + last_nexthop = myself_nexthop; + else + last_nexthop = *NEXTHOP_OUT_PTR(data); + + num = ripng_write_rte(num, s, NULL, &last_nexthop, 0, + RIPNG_METRIC_NEXTHOP); + } else { + /* Rewrite the nexthop for each new packet */ + if ((num == 0) + && !IPV6_ADDR_SAME(&last_nexthop, &myself_nexthop)) + num = ripng_write_rte(num, s, NULL, + &last_nexthop, 0, + RIPNG_METRIC_NEXTHOP); + } + num = ripng_write_rte(num, s, data->p, NULL, TAG_OUT(data), + METRIC_OUT(data)); + + if (num == rtemax) { + ret = ripng_send_packet((caddr_t)STREAM_DATA(s), + stream_get_endp(s), to, ifp); + + if (ret >= 0 && IS_RIPNG_DEBUG_SEND) + ripng_packet_dump( + (struct ripng_packet *)STREAM_DATA(s), + stream_get_endp(s), "SEND"); + num = 0; + stream_reset(s); + } + } + + /* If unwritten RTE exist, flush it. */ + if (num != 0) { + ret = ripng_send_packet((caddr_t)STREAM_DATA(s), + stream_get_endp(s), to, ifp); + + if (ret >= 0 && IS_RIPNG_DEBUG_SEND) + ripng_packet_dump((struct ripng_packet *)STREAM_DATA(s), + stream_get_endp(s), "SEND"); + stream_reset(s); + } } diff --git a/ripngd/ripng_nexthop.h b/ripngd/ripng_nexthop.h index 76873f80e..92ab7e0cd 100644 --- a/ripngd/ripng_nexthop.h +++ b/ripngd/ripng_nexthop.h @@ -26,38 +26,39 @@ #include "ripngd/ripng_route.h" #include "ripngd/ripngd.h" -extern struct list * ripng_rte_new(void); +extern struct list *ripng_rte_new(void); extern void ripng_rte_free(struct list *ripng_rte_list); extern void ripng_rte_add(struct list *ripng_rte_list, struct prefix_ipv6 *p, - struct ripng_info *rinfo, - struct ripng_aggregate *aggregate); + struct ripng_info *rinfo, + struct ripng_aggregate *aggregate); extern void ripng_rte_send(struct list *ripng_rte_list, struct interface *ifp, - struct sockaddr_in6 *to); + struct sockaddr_in6 *to); /*** * 1 if A > B * 0 if A = B * -1 if A < B **/ -static inline int -addr6_cmp(struct in6_addr *A, struct in6_addr *B) +static inline int addr6_cmp(struct in6_addr *A, struct in6_addr *B) { #define a(i) A->s6_addr32[i] #define b(i) B->s6_addr32[i] - if (a(3) > b(3)) - return 1; - else if ((a(3) == b(3)) && (a(2) > b(2))) - return 1; - else if ((a(3) == b(3)) && (a(2) == b(2)) && (a(1) > b(1))) - return 1; - else if ((a(3) == b(3)) && (a(2) == b(2)) && (a(1) == b(1)) && (a(0) > b(0))) - return 1; + if (a(3) > b(3)) + return 1; + else if ((a(3) == b(3)) && (a(2) > b(2))) + return 1; + else if ((a(3) == b(3)) && (a(2) == b(2)) && (a(1) > b(1))) + return 1; + else if ((a(3) == b(3)) && (a(2) == b(2)) && (a(1) == b(1)) + && (a(0) > b(0))) + return 1; - if ((a(3) == b(3)) && (a(2) == b(2)) && (a(1) == b(1)) && (a(0) == b(0))) - return 0; + if ((a(3) == b(3)) && (a(2) == b(2)) && (a(1) == b(1)) + && (a(0) == b(0))) + return 0; - return -1; + return -1; } #endif /* _ZEBRA_RIPNG_RIPNG_NEXTHOP_H */ diff --git a/ripngd/ripng_offset.c b/ripngd/ripng_offset.c index 81e892d7d..efbdc1ffe 100644 --- a/ripngd/ripng_offset.c +++ b/ripngd/ripng_offset.c @@ -18,9 +18,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - /* RIPng support by Vincent Jardin - * Copyright (C) 2002 6WIND - */ +/* RIPng support by Vincent Jardin + * Copyright (C) 2002 6WIND + */ #include @@ -37,169 +37,153 @@ #define RIPNG_OFFSET_LIST_OUT 1 #define RIPNG_OFFSET_LIST_MAX 2 -struct ripng_offset_list -{ - char *ifname; - - struct - { - char *alist_name; - /* struct access_list *alist; */ - int metric; - } direct[RIPNG_OFFSET_LIST_MAX]; +struct ripng_offset_list { + char *ifname; + + struct { + char *alist_name; + /* struct access_list *alist; */ + int metric; + } direct[RIPNG_OFFSET_LIST_MAX]; }; static struct list *ripng_offset_list_master; -static int -strcmp_safe (const char *s1, const char *s2) +static int strcmp_safe(const char *s1, const char *s2) { - if (s1 == NULL && s2 == NULL) - return 0; - if (s1 == NULL) - return -1; - if (s2 == NULL) - return 1; - return strcmp (s1, s2); + if (s1 == NULL && s2 == NULL) + return 0; + if (s1 == NULL) + return -1; + if (s2 == NULL) + return 1; + return strcmp(s1, s2); } -static struct ripng_offset_list * -ripng_offset_list_new (void) +static struct ripng_offset_list *ripng_offset_list_new(void) { - struct ripng_offset_list *new; + struct ripng_offset_list *new; - new = XCALLOC (MTYPE_RIPNG_OFFSET_LIST, sizeof (struct ripng_offset_list)); - return new; + new = XCALLOC(MTYPE_RIPNG_OFFSET_LIST, + sizeof(struct ripng_offset_list)); + return new; } -static void -ripng_offset_list_free (struct ripng_offset_list *offset) +static void ripng_offset_list_free(struct ripng_offset_list *offset) { - XFREE (MTYPE_RIPNG_OFFSET_LIST, offset); + XFREE(MTYPE_RIPNG_OFFSET_LIST, offset); } -static struct ripng_offset_list * -ripng_offset_list_lookup (const char *ifname) +static struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname) { - struct ripng_offset_list *offset; - struct listnode *node, *nnode; + struct ripng_offset_list *offset; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (ripng_offset_list_master, node, nnode, offset)) - { - if (strcmp_safe (offset->ifname, ifname) == 0) - return offset; - } - return NULL; + for (ALL_LIST_ELEMENTS(ripng_offset_list_master, node, nnode, offset)) { + if (strcmp_safe(offset->ifname, ifname) == 0) + return offset; + } + return NULL; } -static struct ripng_offset_list * -ripng_offset_list_get (const char *ifname) +static struct ripng_offset_list *ripng_offset_list_get(const char *ifname) { - struct ripng_offset_list *offset; - - offset = ripng_offset_list_lookup (ifname); - if (offset) - return offset; - - offset = ripng_offset_list_new (); - if (ifname) - offset->ifname = strdup (ifname); - listnode_add_sort (ripng_offset_list_master, offset); - - return offset; + struct ripng_offset_list *offset; + + offset = ripng_offset_list_lookup(ifname); + if (offset) + return offset; + + offset = ripng_offset_list_new(); + if (ifname) + offset->ifname = strdup(ifname); + listnode_add_sort(ripng_offset_list_master, offset); + + return offset; } -static int -ripng_offset_list_set (struct vty *vty, const char *alist, - const char *direct_str, const char *metric_str, - const char *ifname) +static int ripng_offset_list_set(struct vty *vty, const char *alist, + const char *direct_str, const char *metric_str, + const char *ifname) { - int direct; - int metric; - struct ripng_offset_list *offset; - - /* Check direction. */ - if (strncmp (direct_str, "i", 1) == 0) - direct = RIPNG_OFFSET_LIST_IN; - else if (strncmp (direct_str, "o", 1) == 0) - direct = RIPNG_OFFSET_LIST_OUT; - else - { - vty_out (vty, "Invalid direction: %s\n", direct_str); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check metric. */ - metric = atoi (metric_str); - if (metric < 0 || metric > 16) - { - vty_out (vty, "Invalid metric: %s\n", metric_str); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Get offset-list structure with interface name. */ - offset = ripng_offset_list_get (ifname); - - if (offset->direct[direct].alist_name) - free (offset->direct[direct].alist_name); - offset->direct[direct].alist_name = strdup (alist); - offset->direct[direct].metric = metric; - - return CMD_SUCCESS; + int direct; + int metric; + struct ripng_offset_list *offset; + + /* Check direction. */ + if (strncmp(direct_str, "i", 1) == 0) + direct = RIPNG_OFFSET_LIST_IN; + else if (strncmp(direct_str, "o", 1) == 0) + direct = RIPNG_OFFSET_LIST_OUT; + else { + vty_out(vty, "Invalid direction: %s\n", direct_str); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Check metric. */ + metric = atoi(metric_str); + if (metric < 0 || metric > 16) { + vty_out(vty, "Invalid metric: %s\n", metric_str); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Get offset-list structure with interface name. */ + offset = ripng_offset_list_get(ifname); + + if (offset->direct[direct].alist_name) + free(offset->direct[direct].alist_name); + offset->direct[direct].alist_name = strdup(alist); + offset->direct[direct].metric = metric; + + return CMD_SUCCESS; } -static int -ripng_offset_list_unset (struct vty *vty, const char *alist, - const char *direct_str, const char *metric_str, - const char *ifname) +static int ripng_offset_list_unset(struct vty *vty, const char *alist, + const char *direct_str, + const char *metric_str, const char *ifname) { - int direct; - int metric; - struct ripng_offset_list *offset; - - /* Check direction. */ - if (strncmp (direct_str, "i", 1) == 0) - direct = RIPNG_OFFSET_LIST_IN; - else if (strncmp (direct_str, "o", 1) == 0) - direct = RIPNG_OFFSET_LIST_OUT; - else - { - vty_out (vty, "Invalid direction: %s\n", direct_str); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check metric. */ - metric = atoi (metric_str); - if (metric < 0 || metric > 16) - { - vty_out (vty, "Invalid metric: %s\n", metric_str); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Get offset-list structure with interface name. */ - offset = ripng_offset_list_lookup (ifname); - - if (offset) - { - if (offset->direct[direct].alist_name) - free (offset->direct[direct].alist_name); - offset->direct[direct].alist_name = NULL; - - if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name == NULL && - offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name == NULL) - { - listnode_delete (ripng_offset_list_master, offset); - if (offset->ifname) - free (offset->ifname); - ripng_offset_list_free (offset); + int direct; + int metric; + struct ripng_offset_list *offset; + + /* Check direction. */ + if (strncmp(direct_str, "i", 1) == 0) + direct = RIPNG_OFFSET_LIST_IN; + else if (strncmp(direct_str, "o", 1) == 0) + direct = RIPNG_OFFSET_LIST_OUT; + else { + vty_out(vty, "Invalid direction: %s\n", direct_str); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Check metric. */ + metric = atoi(metric_str); + if (metric < 0 || metric > 16) { + vty_out(vty, "Invalid metric: %s\n", metric_str); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Get offset-list structure with interface name. */ + offset = ripng_offset_list_lookup(ifname); + + if (offset) { + if (offset->direct[direct].alist_name) + free(offset->direct[direct].alist_name); + offset->direct[direct].alist_name = NULL; + + if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name == NULL + && offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name + == NULL) { + listnode_delete(ripng_offset_list_master, offset); + if (offset->ifname) + free(offset->ifname); + ripng_offset_list_free(offset); + } + } else { + vty_out(vty, "Can't find offset-list\n"); + return CMD_WARNING_CONFIG_FAILED; } - } - else - { - vty_out (vty, "Can't find offset-list\n"); - return CMD_WARNING_CONFIG_FAILED; - } - return CMD_SUCCESS; + return CMD_SUCCESS; } #define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].alist_name) @@ -209,82 +193,80 @@ ripng_offset_list_unset (struct vty *vty, const char *alist, #define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].metric) /* If metric is modifed return 1. */ -int -ripng_offset_list_apply_in (struct prefix_ipv6 *p, struct interface *ifp, - u_char *metric) +int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp, + u_char *metric) { - struct ripng_offset_list *offset; - struct access_list *alist; - - /* Look up offset-list with interface name. */ - offset = ripng_offset_list_lookup (ifp->name); - if (offset && OFFSET_LIST_IN_NAME (offset)) - { - alist = access_list_lookup (AFI_IP6, OFFSET_LIST_IN_NAME (offset)); - - if (alist - && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT) - { - *metric += OFFSET_LIST_IN_METRIC (offset); - return 1; + struct ripng_offset_list *offset; + struct access_list *alist; + + /* Look up offset-list with interface name. */ + offset = ripng_offset_list_lookup(ifp->name); + if (offset && OFFSET_LIST_IN_NAME(offset)) { + alist = access_list_lookup(AFI_IP6, + OFFSET_LIST_IN_NAME(offset)); + + if (alist + && access_list_apply(alist, (struct prefix *)p) + == FILTER_PERMIT) { + *metric += OFFSET_LIST_IN_METRIC(offset); + return 1; + } + return 0; } - return 0; - } - /* Look up offset-list without interface name. */ - offset = ripng_offset_list_lookup (NULL); - if (offset && OFFSET_LIST_IN_NAME (offset)) - { - alist = access_list_lookup (AFI_IP6, OFFSET_LIST_IN_NAME (offset)); - - if (alist - && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT) - { - *metric += OFFSET_LIST_IN_METRIC (offset); - return 1; + /* Look up offset-list without interface name. */ + offset = ripng_offset_list_lookup(NULL); + if (offset && OFFSET_LIST_IN_NAME(offset)) { + alist = access_list_lookup(AFI_IP6, + OFFSET_LIST_IN_NAME(offset)); + + if (alist + && access_list_apply(alist, (struct prefix *)p) + == FILTER_PERMIT) { + *metric += OFFSET_LIST_IN_METRIC(offset); + return 1; + } + return 0; } - return 0; - } - return 0; + return 0; } /* If metric is modifed return 1. */ -int -ripng_offset_list_apply_out (struct prefix_ipv6 *p, struct interface *ifp, - u_char *metric) +int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp, + u_char *metric) { - struct ripng_offset_list *offset; - struct access_list *alist; - - /* Look up offset-list with interface name. */ - offset = ripng_offset_list_lookup (ifp->name); - if (offset && OFFSET_LIST_OUT_NAME (offset)) - { - alist = access_list_lookup (AFI_IP6, OFFSET_LIST_OUT_NAME (offset)); - - if (alist - && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT) - { - *metric += OFFSET_LIST_OUT_METRIC (offset); - return 1; + struct ripng_offset_list *offset; + struct access_list *alist; + + /* Look up offset-list with interface name. */ + offset = ripng_offset_list_lookup(ifp->name); + if (offset && OFFSET_LIST_OUT_NAME(offset)) { + alist = access_list_lookup(AFI_IP6, + OFFSET_LIST_OUT_NAME(offset)); + + if (alist + && access_list_apply(alist, (struct prefix *)p) + == FILTER_PERMIT) { + *metric += OFFSET_LIST_OUT_METRIC(offset); + return 1; + } + return 0; } - return 0; - } - - /* Look up offset-list without interface name. */ - offset = ripng_offset_list_lookup (NULL); - if (offset && OFFSET_LIST_OUT_NAME (offset)) - { - alist = access_list_lookup (AFI_IP6, OFFSET_LIST_OUT_NAME (offset)); - - if (alist - && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT) - { - *metric += OFFSET_LIST_OUT_METRIC (offset); - return 1; + + /* Look up offset-list without interface name. */ + offset = ripng_offset_list_lookup(NULL); + if (offset && OFFSET_LIST_OUT_NAME(offset)) { + alist = access_list_lookup(AFI_IP6, + OFFSET_LIST_OUT_NAME(offset)); + + if (alist + && access_list_apply(alist, (struct prefix *)p) + == FILTER_PERMIT) { + *metric += OFFSET_LIST_OUT_METRIC(offset); + return 1; + } + return 0; } - return 0; - } - return 0; + return 0; } DEFUN (ripng_offset_list, @@ -296,10 +278,12 @@ DEFUN (ripng_offset_list, "For outgoing updates\n" "Metric value\n") { - int idx_word = 1; - int idx_in_out = 2; - int idx_number = 3; - return ripng_offset_list_set (vty, argv[idx_word]->arg, argv[idx_in_out]->arg, argv[idx_number]->arg, NULL); + int idx_word = 1; + int idx_in_out = 2; + int idx_number = 3; + return ripng_offset_list_set(vty, argv[idx_word]->arg, + argv[idx_in_out]->arg, + argv[idx_number]->arg, NULL); } DEFUN (ripng_offset_list_ifname, @@ -312,11 +296,13 @@ DEFUN (ripng_offset_list_ifname, "Metric value\n" "Interface to match\n") { - int idx_word = 1; - int idx_in_out = 2; - int idx_number = 3; - int idx_ifname = 4; - return ripng_offset_list_set (vty, argv[idx_word]->arg, argv[idx_in_out]->arg, argv[idx_number]->arg, argv[idx_ifname]->arg); + int idx_word = 1; + int idx_in_out = 2; + int idx_number = 3; + int idx_ifname = 4; + return ripng_offset_list_set( + vty, argv[idx_word]->arg, argv[idx_in_out]->arg, + argv[idx_number]->arg, argv[idx_ifname]->arg); } DEFUN (no_ripng_offset_list, @@ -329,10 +315,12 @@ DEFUN (no_ripng_offset_list, "For outgoing updates\n" "Metric value\n") { - int idx_word = 2; - int idx_in_out = 3; - int idx_number = 4; - return ripng_offset_list_unset (vty, argv[idx_word]->arg, argv[idx_in_out]->arg, argv[idx_number]->arg, NULL); + int idx_word = 2; + int idx_in_out = 3; + int idx_number = 4; + return ripng_offset_list_unset(vty, argv[idx_word]->arg, + argv[idx_in_out]->arg, + argv[idx_number]->arg, NULL); } DEFUN (no_ripng_offset_list_ifname, @@ -346,87 +334,91 @@ DEFUN (no_ripng_offset_list_ifname, "Metric value\n" "Interface to match\n") { - int idx_word = 2; - int idx_in_out = 3; - int idx_number = 4; - int idx_ifname = 5; - return ripng_offset_list_unset (vty, argv[idx_word]->arg, argv[idx_in_out]->arg, argv[idx_number]->arg, argv[idx_ifname]->arg); + int idx_word = 2; + int idx_in_out = 3; + int idx_number = 4; + int idx_ifname = 5; + return ripng_offset_list_unset( + vty, argv[idx_word]->arg, argv[idx_in_out]->arg, + argv[idx_number]->arg, argv[idx_ifname]->arg); } -static int -offset_list_cmp (struct ripng_offset_list *o1, struct ripng_offset_list *o2) +static int offset_list_cmp(struct ripng_offset_list *o1, + struct ripng_offset_list *o2) { - return strcmp_safe (o1->ifname, o2->ifname); + return strcmp_safe(o1->ifname, o2->ifname); } -static void -offset_list_del (struct ripng_offset_list *offset) +static void offset_list_del(struct ripng_offset_list *offset) { - if (OFFSET_LIST_IN_NAME (offset)) - free (OFFSET_LIST_IN_NAME (offset)); - if (OFFSET_LIST_OUT_NAME (offset)) - free (OFFSET_LIST_OUT_NAME (offset)); - if (offset->ifname) - free (offset->ifname); - ripng_offset_list_free (offset); + if (OFFSET_LIST_IN_NAME(offset)) + free(OFFSET_LIST_IN_NAME(offset)); + if (OFFSET_LIST_OUT_NAME(offset)) + free(OFFSET_LIST_OUT_NAME(offset)); + if (offset->ifname) + free(offset->ifname); + ripng_offset_list_free(offset); } -void -ripng_offset_init (void) +void ripng_offset_init(void) { - ripng_offset_list_master = list_new (); - ripng_offset_list_master->cmp = (int (*)(void *, void *)) offset_list_cmp; - ripng_offset_list_master->del = (void (*)(void *)) offset_list_del; - - install_element (RIPNG_NODE, &ripng_offset_list_cmd); - install_element (RIPNG_NODE, &ripng_offset_list_ifname_cmd); - install_element (RIPNG_NODE, &no_ripng_offset_list_cmd); - install_element (RIPNG_NODE, &no_ripng_offset_list_ifname_cmd); + ripng_offset_list_master = list_new(); + ripng_offset_list_master->cmp = + (int (*)(void *, void *))offset_list_cmp; + ripng_offset_list_master->del = (void (*)(void *))offset_list_del; + + install_element(RIPNG_NODE, &ripng_offset_list_cmd); + install_element(RIPNG_NODE, &ripng_offset_list_ifname_cmd); + install_element(RIPNG_NODE, &no_ripng_offset_list_cmd); + install_element(RIPNG_NODE, &no_ripng_offset_list_ifname_cmd); } -void -ripng_offset_clean (void) +void ripng_offset_clean(void) { - list_delete (ripng_offset_list_master); + list_delete(ripng_offset_list_master); - ripng_offset_list_master = list_new (); - ripng_offset_list_master->cmp = (int (*)(void *, void *)) offset_list_cmp; - ripng_offset_list_master->del = (void (*)(void *)) offset_list_del; + ripng_offset_list_master = list_new(); + ripng_offset_list_master->cmp = + (int (*)(void *, void *))offset_list_cmp; + ripng_offset_list_master->del = (void (*)(void *))offset_list_del; } -int -config_write_ripng_offset_list (struct vty *vty) +int config_write_ripng_offset_list(struct vty *vty) { - struct listnode *node, *nnode; - struct ripng_offset_list *offset; - - for (ALL_LIST_ELEMENTS (ripng_offset_list_master, node, nnode, offset)) - { - if (! offset->ifname) - { - if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name) - vty_out (vty, " offset-list %s in %d\n", - offset->direct[RIPNG_OFFSET_LIST_IN].alist_name, - offset->direct[RIPNG_OFFSET_LIST_IN].metric); - if (offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name) - vty_out (vty, " offset-list %s out %d\n", - offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name, - offset->direct[RIPNG_OFFSET_LIST_OUT].metric); - } - else - { - if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name) - vty_out (vty, " offset-list %s in %d %s\n", - offset->direct[RIPNG_OFFSET_LIST_IN].alist_name, - offset->direct[RIPNG_OFFSET_LIST_IN].metric, - offset->ifname); - if (offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name) - vty_out (vty, " offset-list %s out %d %s\n", - offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name, - offset->direct[RIPNG_OFFSET_LIST_OUT].metric, - offset->ifname); + struct listnode *node, *nnode; + struct ripng_offset_list *offset; + + for (ALL_LIST_ELEMENTS(ripng_offset_list_master, node, nnode, offset)) { + if (!offset->ifname) { + if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name) + vty_out(vty, " offset-list %s in %d\n", + offset->direct[RIPNG_OFFSET_LIST_IN] + .alist_name, + offset->direct[RIPNG_OFFSET_LIST_IN] + .metric); + if (offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name) + vty_out(vty, " offset-list %s out %d\n", + offset->direct[RIPNG_OFFSET_LIST_OUT] + .alist_name, + offset->direct[RIPNG_OFFSET_LIST_OUT] + .metric); + } else { + if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name) + vty_out(vty, " offset-list %s in %d %s\n", + offset->direct[RIPNG_OFFSET_LIST_IN] + .alist_name, + offset->direct[RIPNG_OFFSET_LIST_IN] + .metric, + offset->ifname); + if (offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name) + vty_out(vty, " offset-list %s out %d %s\n", + offset->direct[RIPNG_OFFSET_LIST_OUT] + .alist_name, + offset->direct[RIPNG_OFFSET_LIST_OUT] + .metric, + offset->ifname); + } } - } - return 0; + return 0; } diff --git a/ripngd/ripng_peer.c b/ripngd/ripng_peer.c index f27c33f37..2a412f9b6 100644 --- a/ripngd/ripng_peer.c +++ b/ripngd/ripng_peer.c @@ -38,178 +38,157 @@ /* Linked list of RIPng peer. */ struct list *peer_list; -static struct ripng_peer * -ripng_peer_new (void) +static struct ripng_peer *ripng_peer_new(void) { - return XCALLOC (MTYPE_RIPNG_PEER, sizeof (struct ripng_peer)); + return XCALLOC(MTYPE_RIPNG_PEER, sizeof(struct ripng_peer)); } -static void -ripng_peer_free (struct ripng_peer *peer) +static void ripng_peer_free(struct ripng_peer *peer) { - XFREE (MTYPE_RIPNG_PEER, peer); + XFREE(MTYPE_RIPNG_PEER, peer); } -struct ripng_peer * -ripng_peer_lookup (struct in6_addr *addr) +struct ripng_peer *ripng_peer_lookup(struct in6_addr *addr) { - struct ripng_peer *peer; - struct listnode *node, *nnode; - - for (ALL_LIST_ELEMENTS (peer_list, node, nnode, peer)) - { - if (IPV6_ADDR_SAME (&peer->addr, addr)) - return peer; - } - return NULL; + struct ripng_peer *peer; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) { + if (IPV6_ADDR_SAME(&peer->addr, addr)) + return peer; + } + return NULL; } -struct ripng_peer * -ripng_peer_lookup_next (struct in6_addr *addr) +struct ripng_peer *ripng_peer_lookup_next(struct in6_addr *addr) { - struct ripng_peer *peer; - struct listnode *node, *nnode; - - for (ALL_LIST_ELEMENTS (peer_list, node, nnode, peer)) - { - if (addr6_cmp(&peer->addr, addr) > 0) - return peer; - } - return NULL; + struct ripng_peer *peer; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) { + if (addr6_cmp(&peer->addr, addr) > 0) + return peer; + } + return NULL; } /* RIPng peer is timeout. * Garbage collector. **/ -static int -ripng_peer_timeout (struct thread *t) +static int ripng_peer_timeout(struct thread *t) { - struct ripng_peer *peer; + struct ripng_peer *peer; - peer = THREAD_ARG (t); - listnode_delete (peer_list, peer); - ripng_peer_free (peer); + peer = THREAD_ARG(t); + listnode_delete(peer_list, peer); + ripng_peer_free(peer); - return 0; + return 0; } /* Get RIPng peer. At the same time update timeout thread. */ -static struct ripng_peer * -ripng_peer_get (struct in6_addr *addr) +static struct ripng_peer *ripng_peer_get(struct in6_addr *addr) { - struct ripng_peer *peer; - - peer = ripng_peer_lookup (addr); - - if (peer) - { - if (peer->t_timeout) - thread_cancel (peer->t_timeout); - } - else - { - peer = ripng_peer_new (); - peer->addr = *addr; /* XXX */ - listnode_add_sort (peer_list, peer); - } - - /* Update timeout thread. */ - peer->t_timeout = NULL; - thread_add_timer(master, ripng_peer_timeout, peer, RIPNG_PEER_TIMER_DEFAULT, - &peer->t_timeout); - - /* Last update time set. */ - time (&peer->uptime); - - return peer; + struct ripng_peer *peer; + + peer = ripng_peer_lookup(addr); + + if (peer) { + if (peer->t_timeout) + thread_cancel(peer->t_timeout); + } else { + peer = ripng_peer_new(); + peer->addr = *addr; /* XXX */ + listnode_add_sort(peer_list, peer); + } + + /* Update timeout thread. */ + peer->t_timeout = NULL; + thread_add_timer(master, ripng_peer_timeout, peer, + RIPNG_PEER_TIMER_DEFAULT, &peer->t_timeout); + + /* Last update time set. */ + time(&peer->uptime); + + return peer; } -void -ripng_peer_update (struct sockaddr_in6 *from, u_char version) +void ripng_peer_update(struct sockaddr_in6 *from, u_char version) { - struct ripng_peer *peer; - peer = ripng_peer_get (&from->sin6_addr); - peer->version = version; + struct ripng_peer *peer; + peer = ripng_peer_get(&from->sin6_addr); + peer->version = version; } -void -ripng_peer_bad_route (struct sockaddr_in6 *from) +void ripng_peer_bad_route(struct sockaddr_in6 *from) { - struct ripng_peer *peer; - peer = ripng_peer_get (&from->sin6_addr); - peer->recv_badroutes++; + struct ripng_peer *peer; + peer = ripng_peer_get(&from->sin6_addr); + peer->recv_badroutes++; } -void -ripng_peer_bad_packet (struct sockaddr_in6 *from) +void ripng_peer_bad_packet(struct sockaddr_in6 *from) { - struct ripng_peer *peer; - peer = ripng_peer_get (&from->sin6_addr); - peer->recv_badpackets++; + struct ripng_peer *peer; + peer = ripng_peer_get(&from->sin6_addr); + peer->recv_badpackets++; } /* Display peer uptime. */ -static char * -ripng_peer_uptime (struct ripng_peer *peer, char *buf, size_t len) +static char *ripng_peer_uptime(struct ripng_peer *peer, char *buf, size_t len) { - time_t uptime; - struct tm *tm; - - /* If there is no connection has been done before print `never'. */ - if (peer->uptime == 0) - { - snprintf (buf, len, "never "); - return buf; - } - - /* Get current time. */ - uptime = time (NULL); - uptime -= peer->uptime; - tm = gmtime (&uptime); - - /* Making formatted timer strings. */ + time_t uptime; + struct tm *tm; + + /* If there is no connection has been done before print `never'. */ + if (peer->uptime == 0) { + snprintf(buf, len, "never "); + return buf; + } + + /* Get current time. */ + uptime = time(NULL); + uptime -= peer->uptime; + tm = gmtime(&uptime); + +/* Making formatted timer strings. */ #define ONE_DAY_SECOND 60*60*24 #define ONE_WEEK_SECOND 60*60*24*7 - if (uptime < ONE_DAY_SECOND) - snprintf (buf, len, "%02d:%02d:%02d", - tm->tm_hour, tm->tm_min, tm->tm_sec); - else if (uptime < ONE_WEEK_SECOND) - snprintf (buf, len, "%dd%02dh%02dm", - tm->tm_yday, tm->tm_hour, tm->tm_min); - else - snprintf (buf, len, "%02dw%dd%02dh", - tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); - return buf; + if (uptime < ONE_DAY_SECOND) + snprintf(buf, len, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, + tm->tm_sec); + else if (uptime < ONE_WEEK_SECOND) + snprintf(buf, len, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour, + tm->tm_min); + else + snprintf(buf, len, "%02dw%dd%02dh", tm->tm_yday / 7, + tm->tm_yday - ((tm->tm_yday / 7) * 7), tm->tm_hour); + return buf; } -void -ripng_peer_display (struct vty *vty) +void ripng_peer_display(struct vty *vty) { - struct ripng_peer *peer; - struct listnode *node, *nnode; + struct ripng_peer *peer; + struct listnode *node, *nnode; #define RIPNG_UPTIME_LEN 25 - char timebuf[RIPNG_UPTIME_LEN]; - - for (ALL_LIST_ELEMENTS (peer_list, node, nnode, peer)) - { - vty_out (vty, " %s \n%14s %10d %10d %10d %s\n", inet6_ntoa (peer->addr), - " ", - peer->recv_badpackets, peer->recv_badroutes, - ZEBRA_RIPNG_DISTANCE_DEFAULT, - ripng_peer_uptime(peer, timebuf, RIPNG_UPTIME_LEN)); - } + char timebuf[RIPNG_UPTIME_LEN]; + + for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) { + vty_out(vty, " %s \n%14s %10d %10d %10d %s\n", + inet6_ntoa(peer->addr), " ", peer->recv_badpackets, + peer->recv_badroutes, ZEBRA_RIPNG_DISTANCE_DEFAULT, + ripng_peer_uptime(peer, timebuf, RIPNG_UPTIME_LEN)); + } } -static int -ripng_peer_list_cmp (struct ripng_peer *p1, struct ripng_peer *p2) +static int ripng_peer_list_cmp(struct ripng_peer *p1, struct ripng_peer *p2) { - return addr6_cmp(&p1->addr, &p2->addr) > 0; + return addr6_cmp(&p1->addr, &p2->addr) > 0; } -void -ripng_peer_init () +void ripng_peer_init() { - peer_list = list_new (); - peer_list->cmp = (int (*)(void *, void *)) ripng_peer_list_cmp; + peer_list = list_new(); + peer_list->cmp = (int (*)(void *, void *))ripng_peer_list_cmp; } diff --git a/ripngd/ripng_route.c b/ripngd/ripng_route.c index f7d3ef89f..83cb59c8b 100644 --- a/ripngd/ripng_route.c +++ b/ripngd/ripng_route.c @@ -30,151 +30,138 @@ #include "ripngd/ripngd.h" #include "ripngd/ripng_route.h" -static struct ripng_aggregate * -ripng_aggregate_new (void) +static struct ripng_aggregate *ripng_aggregate_new(void) { - struct ripng_aggregate *new; + struct ripng_aggregate *new; - new = XCALLOC (MTYPE_RIPNG_AGGREGATE, sizeof (struct ripng_aggregate)); - return new; + new = XCALLOC(MTYPE_RIPNG_AGGREGATE, sizeof(struct ripng_aggregate)); + return new; } -void -ripng_aggregate_free (struct ripng_aggregate *aggregate) +void ripng_aggregate_free(struct ripng_aggregate *aggregate) { - XFREE (MTYPE_RIPNG_AGGREGATE, aggregate); + XFREE(MTYPE_RIPNG_AGGREGATE, aggregate); } /* Aggregate count increment check. */ -void -ripng_aggregate_increment (struct route_node *child, struct ripng_info *rinfo) +void ripng_aggregate_increment(struct route_node *child, + struct ripng_info *rinfo) { - struct route_node *np; - struct ripng_aggregate *aggregate; - - for (np = child; np; np = np->parent) - if ((aggregate = np->aggregate) != NULL) - { - aggregate->count++; - rinfo->suppress++; - } + struct route_node *np; + struct ripng_aggregate *aggregate; + + for (np = child; np; np = np->parent) + if ((aggregate = np->aggregate) != NULL) { + aggregate->count++; + rinfo->suppress++; + } } /* Aggregate count decrement check. */ -void -ripng_aggregate_decrement (struct route_node *child, struct ripng_info *rinfo) +void ripng_aggregate_decrement(struct route_node *child, + struct ripng_info *rinfo) { - struct route_node *np; - struct ripng_aggregate *aggregate; - - for (np = child; np; np = np->parent) - if ((aggregate = np->aggregate) != NULL) - { - aggregate->count--; - rinfo->suppress--; - } + struct route_node *np; + struct ripng_aggregate *aggregate; + + for (np = child; np; np = np->parent) + if ((aggregate = np->aggregate) != NULL) { + aggregate->count--; + rinfo->suppress--; + } } /* Aggregate count decrement check for a list. */ -void -ripng_aggregate_decrement_list (struct route_node *child, struct list *list) +void ripng_aggregate_decrement_list(struct route_node *child, struct list *list) { - struct route_node *np; - struct ripng_aggregate *aggregate; - struct ripng_info *rinfo = NULL; - struct listnode *node = NULL; + struct route_node *np; + struct ripng_aggregate *aggregate; + struct ripng_info *rinfo = NULL; + struct listnode *node = NULL; - for (np = child; np; np = np->parent) - if ((aggregate = np->aggregate) != NULL) - aggregate->count -= listcount (list); + for (np = child; np; np = np->parent) + if ((aggregate = np->aggregate) != NULL) + aggregate->count -= listcount(list); - for (ALL_LIST_ELEMENTS_RO (list, node, rinfo)) - rinfo->suppress--; + for (ALL_LIST_ELEMENTS_RO(list, node, rinfo)) + rinfo->suppress--; } /* RIPng routes treatment. */ -int -ripng_aggregate_add (struct prefix *p) +int ripng_aggregate_add(struct prefix *p) { - struct route_node *top; - struct route_node *rp; - struct ripng_info *rinfo; - struct ripng_aggregate *aggregate; - struct ripng_aggregate *sub; - struct list *list = NULL; - struct listnode *node = NULL; - - /* Get top node for aggregation. */ - top = route_node_get (ripng->table, p); - - /* Allocate new aggregate. */ - aggregate = ripng_aggregate_new (); - aggregate->metric = 1; - - top->aggregate = aggregate; - - /* Suppress routes match to the aggregate. */ - for (rp = route_lock_node (top); rp; rp = route_next_until (rp, top)) - { - /* Suppress normal route. */ - if ((list = rp->info) != NULL) - for (ALL_LIST_ELEMENTS_RO (list, node, rinfo)) - { - aggregate->count++; - rinfo->suppress++; - } - /* Suppress aggregate route. This may not need. */ - if (rp != top && (sub = rp->aggregate) != NULL) - { - aggregate->count++; - sub->suppress++; + struct route_node *top; + struct route_node *rp; + struct ripng_info *rinfo; + struct ripng_aggregate *aggregate; + struct ripng_aggregate *sub; + struct list *list = NULL; + struct listnode *node = NULL; + + /* Get top node for aggregation. */ + top = route_node_get(ripng->table, p); + + /* Allocate new aggregate. */ + aggregate = ripng_aggregate_new(); + aggregate->metric = 1; + + top->aggregate = aggregate; + + /* Suppress routes match to the aggregate. */ + for (rp = route_lock_node(top); rp; rp = route_next_until(rp, top)) { + /* Suppress normal route. */ + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS_RO(list, node, rinfo)) { + aggregate->count++; + rinfo->suppress++; + } + /* Suppress aggregate route. This may not need. */ + if (rp != top && (sub = rp->aggregate) != NULL) { + aggregate->count++; + sub->suppress++; + } } - } - return 0; + return 0; } /* Delete RIPng static route. */ -int -ripng_aggregate_delete (struct prefix *p) +int ripng_aggregate_delete(struct prefix *p) { - struct route_node *top; - struct route_node *rp; - struct ripng_info *rinfo; - struct ripng_aggregate *aggregate; - struct ripng_aggregate *sub; - struct list *list = NULL; - struct listnode *node = NULL; - - /* Get top node for aggregation. */ - top = route_node_get (ripng->table, p); - - /* Allocate new aggregate. */ - aggregate = top->aggregate; - - /* Suppress routes match to the aggregate. */ - for (rp = route_lock_node (top); rp; rp = route_next_until (rp, top)) - { - /* Suppress normal route. */ - if ((list = rp->info) != NULL) - for (ALL_LIST_ELEMENTS_RO (list, node, rinfo)) - { - aggregate->count--; - rinfo->suppress--; - } - - if (rp != top && (sub = rp->aggregate) != NULL) - { - aggregate->count--; - sub->suppress--; + struct route_node *top; + struct route_node *rp; + struct ripng_info *rinfo; + struct ripng_aggregate *aggregate; + struct ripng_aggregate *sub; + struct list *list = NULL; + struct listnode *node = NULL; + + /* Get top node for aggregation. */ + top = route_node_get(ripng->table, p); + + /* Allocate new aggregate. */ + aggregate = top->aggregate; + + /* Suppress routes match to the aggregate. */ + for (rp = route_lock_node(top); rp; rp = route_next_until(rp, top)) { + /* Suppress normal route. */ + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS_RO(list, node, rinfo)) { + aggregate->count--; + rinfo->suppress--; + } + + if (rp != top && (sub = rp->aggregate) != NULL) { + aggregate->count--; + sub->suppress--; + } } - } - top->aggregate = NULL; - ripng_aggregate_free (aggregate); + top->aggregate = NULL; + ripng_aggregate_free(aggregate); - route_unlock_node (top); - route_unlock_node (top); + route_unlock_node(top); + route_unlock_node(top); - return 0; + return 0; } diff --git a/ripngd/ripng_route.h b/ripngd/ripng_route.h index 90dae0470..3db1279b5 100644 --- a/ripngd/ripng_route.h +++ b/ripngd/ripng_route.h @@ -22,35 +22,34 @@ #ifndef _ZEBRA_RIPNG_ROUTE_H #define _ZEBRA_RIPNG_ROUTE_H -struct ripng_aggregate -{ - /* Aggregate route count. */ - unsigned int count; +struct ripng_aggregate { + /* Aggregate route count. */ + unsigned int count; - /* Suppressed route count. */ - unsigned int suppress; + /* Suppressed route count. */ + unsigned int suppress; - /* Metric of this route. */ - u_char metric; + /* Metric of this route. */ + u_char metric; - /* Tag field of RIPng packet.*/ - u_int16_t tag; + /* Tag field of RIPng packet.*/ + u_int16_t tag; - /* Route-map futures - this variables can be changed. */ - struct in6_addr nexthop_out; - u_char metric_set; - u_char metric_out; - u_int16_t tag_out; + /* Route-map futures - this variables can be changed. */ + struct in6_addr nexthop_out; + u_char metric_set; + u_char metric_out; + u_int16_t tag_out; }; -extern void ripng_aggregate_increment (struct route_node *rp, - struct ripng_info *rinfo); -extern void ripng_aggregate_decrement (struct route_node *rp, - struct ripng_info *rinfo); -extern void ripng_aggregate_decrement_list (struct route_node *rp, - struct list *list); -extern int ripng_aggregate_add (struct prefix *p); -extern int ripng_aggregate_delete (struct prefix *p); -extern void ripng_aggregate_free (struct ripng_aggregate *aggregate); +extern void ripng_aggregate_increment(struct route_node *rp, + struct ripng_info *rinfo); +extern void ripng_aggregate_decrement(struct route_node *rp, + struct ripng_info *rinfo); +extern void ripng_aggregate_decrement_list(struct route_node *rp, + struct list *list); +extern int ripng_aggregate_add(struct prefix *p); +extern int ripng_aggregate_delete(struct prefix *p); +extern void ripng_aggregate_free(struct ripng_aggregate *aggregate); #endif /* _ZEBRA_RIPNG_ROUTE_H */ diff --git a/ripngd/ripng_routemap.c b/ripngd/ripng_routemap.c index 69ff84b22..3080801fb 100644 --- a/ripngd/ripng_routemap.c +++ b/ripngd/ripng_routemap.c @@ -30,383 +30,335 @@ #include "ripngd/ripngd.h" -struct rip_metric_modifier -{ - enum - { - metric_increment, - metric_decrement, - metric_absolute - } type; - - u_char metric; +struct rip_metric_modifier { + enum { metric_increment, metric_decrement, metric_absolute } type; + + u_char metric; }; /* `match metric METRIC' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_metric (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_metric(void *rule, struct prefix *prefix, + route_map_object_t type, + void *object) { - u_int32_t *metric; - struct ripng_info *rinfo; - - if (type == RMAP_RIPNG) - { - metric = rule; - rinfo = object; - - if (rinfo->metric == *metric) - return RMAP_MATCH; - else + u_int32_t *metric; + struct ripng_info *rinfo; + + if (type == RMAP_RIPNG) { + metric = rule; + rinfo = object; + + if (rinfo->metric == *metric) + return RMAP_MATCH; + else + return RMAP_NOMATCH; + } return RMAP_NOMATCH; - } - return RMAP_NOMATCH; } /* Route map `match metric' match statement. `arg' is METRIC value */ -static void * -route_match_metric_compile (const char *arg) +static void *route_match_metric_compile(const char *arg) { - u_int32_t *metric; + u_int32_t *metric; - metric = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); - *metric = atoi (arg); + metric = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t)); + *metric = atoi(arg); - if(*metric > 0) - return metric; + if (*metric > 0) + return metric; - XFREE (MTYPE_ROUTE_MAP_COMPILED, metric); - return NULL; + XFREE(MTYPE_ROUTE_MAP_COMPILED, metric); + return NULL; } /* Free route map's compiled `match metric' value. */ -static void -route_match_metric_free (void *rule) +static void route_match_metric_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for metric matching. */ -static struct route_map_rule_cmd route_match_metric_cmd = -{ - "metric", - route_match_metric, - route_match_metric_compile, - route_match_metric_free -}; +static struct route_map_rule_cmd route_match_metric_cmd = { + "metric", route_match_metric, route_match_metric_compile, + route_match_metric_free}; /* `match interface IFNAME' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_interface (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_interface(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct ripng_info *rinfo; - struct interface *ifp; - char *ifname; + struct ripng_info *rinfo; + struct interface *ifp; + char *ifname; - if (type == RMAP_RIPNG) - { - ifname = rule; - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); + if (type == RMAP_RIPNG) { + ifname = rule; + ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - if (!ifp) - return RMAP_NOMATCH; + if (!ifp) + return RMAP_NOMATCH; - rinfo = object; + rinfo = object; - if (rinfo->ifindex == ifp->ifindex) - return RMAP_MATCH; - else + if (rinfo->ifindex == ifp->ifindex) + return RMAP_MATCH; + else + return RMAP_NOMATCH; + } return RMAP_NOMATCH; - } - return RMAP_NOMATCH; } /* Route map `match interface' match statement. `arg' is IFNAME value */ -static void * -route_match_interface_compile (const char *arg) +static void *route_match_interface_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_interface_free (void *rule) +static void route_match_interface_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -static struct route_map_rule_cmd route_match_interface_cmd = -{ - "interface", - route_match_interface, - route_match_interface_compile, - route_match_interface_free -}; +static struct route_map_rule_cmd route_match_interface_cmd = { + "interface", route_match_interface, route_match_interface_compile, + route_match_interface_free}; /* `match tag TAG' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_tag (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_tag(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - route_tag_t *tag; - struct ripng_info *rinfo; - route_tag_t rinfo_tag; - - if (type == RMAP_RIPNG) - { - tag = rule; - rinfo = object; - - /* The information stored by rinfo is host ordered. */ - rinfo_tag = rinfo->tag; - if (rinfo_tag == *tag) - return RMAP_MATCH; - else + route_tag_t *tag; + struct ripng_info *rinfo; + route_tag_t rinfo_tag; + + if (type == RMAP_RIPNG) { + tag = rule; + rinfo = object; + + /* The information stored by rinfo is host ordered. */ + rinfo_tag = rinfo->tag; + if (rinfo_tag == *tag) + return RMAP_MATCH; + else + return RMAP_NOMATCH; + } return RMAP_NOMATCH; - } - return RMAP_NOMATCH; } -static struct route_map_rule_cmd route_match_tag_cmd = -{ - "tag", - route_match_tag, - route_map_rule_tag_compile, - route_map_rule_tag_free, +static struct route_map_rule_cmd route_match_tag_cmd = { + "tag", route_match_tag, route_map_rule_tag_compile, + route_map_rule_tag_free, }; /* `set metric METRIC' */ /* Set metric to attribute. */ -static route_map_result_t -route_set_metric (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, + route_map_object_t type, + void *object) { - if (type == RMAP_RIPNG) - { - struct rip_metric_modifier *mod; - struct ripng_info *rinfo; - - mod = rule; - rinfo = object; - - if (mod->type == metric_increment) - rinfo->metric_out += mod->metric; - else if (mod->type == metric_decrement) - rinfo->metric_out-= mod->metric; - else if (mod->type == metric_absolute) - rinfo->metric_out = mod->metric; - - if (rinfo->metric_out < 1) - rinfo->metric_out = 1; - if (rinfo->metric_out > RIPNG_METRIC_INFINITY) - rinfo->metric_out = RIPNG_METRIC_INFINITY; - - rinfo->metric_set = 1; - } - return RMAP_OKAY; + if (type == RMAP_RIPNG) { + struct rip_metric_modifier *mod; + struct ripng_info *rinfo; + + mod = rule; + rinfo = object; + + if (mod->type == metric_increment) + rinfo->metric_out += mod->metric; + else if (mod->type == metric_decrement) + rinfo->metric_out -= mod->metric; + else if (mod->type == metric_absolute) + rinfo->metric_out = mod->metric; + + if (rinfo->metric_out < 1) + rinfo->metric_out = 1; + if (rinfo->metric_out > RIPNG_METRIC_INFINITY) + rinfo->metric_out = RIPNG_METRIC_INFINITY; + + rinfo->metric_set = 1; + } + return RMAP_OKAY; } /* set metric compilation. */ -static void * -route_set_metric_compile (const char *arg) +static void *route_set_metric_compile(const char *arg) { - int len; - const char *pnt; - int type; - long metric; - char *endptr = NULL; - struct rip_metric_modifier *mod; - - len = strlen (arg); - pnt = arg; - - if (len == 0) - return NULL; - - /* Examine first character. */ - if (arg[0] == '+') - { - type = metric_increment; - pnt++; - } - else if (arg[0] == '-') - { - type = metric_decrement; - pnt++; - } - else - type = metric_absolute; - - /* Check beginning with digit string. */ - if (*pnt < '0' || *pnt > '9') - return NULL; - - /* Convert string to integer. */ - metric = strtol (pnt, &endptr, 10); - - if (metric == LONG_MAX || *endptr != '\0') - return NULL; - /* Commented out by Hasso Tepper, to avoid problems in vtysh. */ - /* if (metric < 0 || metric > RIPNG_METRIC_INFINITY) */ - if (metric < 0) - return NULL; - - mod = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, - sizeof (struct rip_metric_modifier)); - mod->type = type; - mod->metric = metric; - - return mod; + int len; + const char *pnt; + int type; + long metric; + char *endptr = NULL; + struct rip_metric_modifier *mod; + + len = strlen(arg); + pnt = arg; + + if (len == 0) + return NULL; + + /* Examine first character. */ + if (arg[0] == '+') { + type = metric_increment; + pnt++; + } else if (arg[0] == '-') { + type = metric_decrement; + pnt++; + } else + type = metric_absolute; + + /* Check beginning with digit string. */ + if (*pnt < '0' || *pnt > '9') + return NULL; + + /* Convert string to integer. */ + metric = strtol(pnt, &endptr, 10); + + if (metric == LONG_MAX || *endptr != '\0') + return NULL; + /* Commented out by Hasso Tepper, to avoid problems in vtysh. */ + /* if (metric < 0 || metric > RIPNG_METRIC_INFINITY) */ + if (metric < 0) + return NULL; + + mod = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, + sizeof(struct rip_metric_modifier)); + mod->type = type; + mod->metric = metric; + + return mod; } /* Free route map's compiled `set metric' value. */ -static void -route_set_metric_free (void *rule) +static void route_set_metric_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -static struct route_map_rule_cmd route_set_metric_cmd = -{ - "metric", - route_set_metric, - route_set_metric_compile, - route_set_metric_free, +static struct route_map_rule_cmd route_set_metric_cmd = { + "metric", route_set_metric, route_set_metric_compile, + route_set_metric_free, }; /* `set ipv6 next-hop local IP_ADDRESS' */ /* Set nexthop to object. ojbect must be pointer to struct attr. */ -static route_map_result_t -route_set_ipv6_nexthop_local (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_ipv6_nexthop_local(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct in6_addr *address; - struct ripng_info *rinfo; - - if(type == RMAP_RIPNG) - { - /* Fetch routemap's rule information. */ - address = rule; - rinfo = object; - - /* Set next hop value. */ - rinfo->nexthop_out = *address; - } - - return RMAP_OKAY; + struct in6_addr *address; + struct ripng_info *rinfo; + + if (type == RMAP_RIPNG) { + /* Fetch routemap's rule information. */ + address = rule; + rinfo = object; + + /* Set next hop value. */ + rinfo->nexthop_out = *address; + } + + return RMAP_OKAY; } /* Route map `ipv6 nexthop local' compile function. Given string is converted to struct in6_addr structure. */ -static void * -route_set_ipv6_nexthop_local_compile (const char *arg) +static void *route_set_ipv6_nexthop_local_compile(const char *arg) { - int ret; - struct in6_addr *address; + int ret; + struct in6_addr *address; - address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr)); + address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr)); - ret = inet_pton (AF_INET6, arg, address); + ret = inet_pton(AF_INET6, arg, address); - if (ret == 0) - { - XFREE (MTYPE_ROUTE_MAP_COMPILED, address); - return NULL; - } + if (ret == 0) { + XFREE(MTYPE_ROUTE_MAP_COMPILED, address); + return NULL; + } - return address; + return address; } /* Free route map's compiled `ipv6 nexthop local' value. */ -static void -route_set_ipv6_nexthop_local_free (void *rule) +static void route_set_ipv6_nexthop_local_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ipv6 nexthop local set. */ -static struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd = -{ - "ipv6 next-hop local", - route_set_ipv6_nexthop_local, - route_set_ipv6_nexthop_local_compile, - route_set_ipv6_nexthop_local_free -}; +static struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd = { + "ipv6 next-hop local", route_set_ipv6_nexthop_local, + route_set_ipv6_nexthop_local_compile, + route_set_ipv6_nexthop_local_free}; /* `set tag TAG' */ /* Set tag to object. ojbect must be pointer to struct attr. */ -static route_map_result_t -route_set_tag (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_tag(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - route_tag_t *tag; - struct ripng_info *rinfo; - - if(type == RMAP_RIPNG) - { - /* Fetch routemap's rule information. */ - tag = rule; - rinfo = object; - - /* Set next hop value. */ - rinfo->tag_out = *tag; - } - - return RMAP_OKAY; + route_tag_t *tag; + struct ripng_info *rinfo; + + if (type == RMAP_RIPNG) { + /* Fetch routemap's rule information. */ + tag = rule; + rinfo = object; + + /* Set next hop value. */ + rinfo->tag_out = *tag; + } + + return RMAP_OKAY; } /* Route map commands for tag set. */ -static struct route_map_rule_cmd route_set_tag_cmd = -{ - "tag", - route_set_tag, - route_map_rule_tag_compile, - route_map_rule_tag_free -}; +static struct route_map_rule_cmd route_set_tag_cmd = { + "tag", route_set_tag, route_map_rule_tag_compile, + route_map_rule_tag_free}; #define MATCH_STR "Match values from routing table\n" #define SET_STR "Set values in destination routing protocol\n" -void -ripng_route_map_reset () +void ripng_route_map_reset() { - /* XXX ??? */ - ; + /* XXX ??? */ + ; } -void -ripng_route_map_init () +void ripng_route_map_init() { - route_map_init (); + route_map_init(); - route_map_match_interface_hook (generic_match_add); - route_map_no_match_interface_hook (generic_match_delete); + route_map_match_interface_hook(generic_match_add); + route_map_no_match_interface_hook(generic_match_delete); - route_map_match_metric_hook (generic_match_add); - route_map_no_match_metric_hook (generic_match_delete); + route_map_match_metric_hook(generic_match_add); + route_map_no_match_metric_hook(generic_match_delete); - route_map_match_tag_hook (generic_match_add); - route_map_no_match_tag_hook (generic_match_delete); + route_map_match_tag_hook(generic_match_add); + route_map_no_match_tag_hook(generic_match_delete); - route_map_set_ipv6_nexthop_local_hook (generic_set_add); - route_map_no_set_ipv6_nexthop_local_hook (generic_set_delete); + route_map_set_ipv6_nexthop_local_hook(generic_set_add); + route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete); - route_map_set_metric_hook (generic_set_add); - route_map_no_set_metric_hook (generic_set_delete); + route_map_set_metric_hook(generic_set_add); + route_map_no_set_metric_hook(generic_set_delete); - route_map_set_tag_hook (generic_set_add); - route_map_no_set_tag_hook (generic_set_delete); + route_map_set_tag_hook(generic_set_add); + route_map_no_set_tag_hook(generic_set_delete); - route_map_install_match (&route_match_metric_cmd); - route_map_install_match (&route_match_interface_cmd); - route_map_install_match (&route_match_tag_cmd); - route_map_install_set (&route_set_metric_cmd); - route_map_install_set (&route_set_ipv6_nexthop_local_cmd); - route_map_install_set (&route_set_tag_cmd); + route_map_install_match(&route_match_metric_cmd); + route_map_install_match(&route_match_interface_cmd); + route_map_install_match(&route_match_tag_cmd); + route_map_install_set(&route_set_metric_cmd); + route_map_install_set(&route_set_ipv6_nexthop_local_cmd); + route_map_install_set(&route_set_tag_cmd); } diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c index b49de9902..386bee43b 100644 --- a/ripngd/ripng_zebra.c +++ b/ripngd/ripng_zebra.c @@ -37,270 +37,261 @@ struct zclient *zclient = NULL; /* Send ECMP routes to zebra. */ -static void -ripng_zebra_ipv6_send (struct route_node *rp, u_char cmd) +static void ripng_zebra_ipv6_send(struct route_node *rp, u_char cmd) { - static struct in6_addr **nexthops = NULL; - static ifindex_t *ifindexes = NULL; - static unsigned int nexthops_len = 0; - - struct list *list = (struct list *)rp->info; - struct zapi_ipv6 api; - struct listnode *listnode = NULL; - struct ripng_info *rinfo = NULL; - int count = 0; - - if (vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], VRF_DEFAULT)) - { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_RIPNG; - api.instance = 0; - api.flags = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - - if (nexthops_len < listcount (list)) - { - nexthops_len = listcount (list); - nexthops = XREALLOC (MTYPE_TMP, nexthops, - nexthops_len * sizeof (struct in6_addr *)); - ifindexes = XREALLOC (MTYPE_TMP, ifindexes, - nexthops_len * sizeof (unsigned int)); - } - - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); - for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) - { - nexthops[count] = &rinfo->nexthop; - ifindexes[count] = rinfo->ifindex; - count++; - if (cmd == ZEBRA_IPV6_ROUTE_ADD) - SET_FLAG (rinfo->flags, RIPNG_RTF_FIB); - else - UNSET_FLAG (rinfo->flags, RIPNG_RTF_FIB); - } - - api.nexthop = nexthops; - api.nexthop_num = count; - api.ifindex = ifindexes; - api.ifindex_num = count; - - rinfo = listgetdata (listhead (list)); - - SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); - api.metric = rinfo->metric; - - if (rinfo->tag) - { - SET_FLAG (api.message, ZAPI_MESSAGE_TAG); - api.tag = rinfo->tag; - } - - zapi_ipv6_route (cmd, zclient, - (struct prefix_ipv6 *)&rp->p, NULL, &api); - - if (IS_RIPNG_DEBUG_ZEBRA) - { - if (ripng->ecmp) - zlog_debug ("%s: %s/%d nexthops %d", - (cmd == ZEBRA_IPV6_ROUTE_ADD) ? \ - "Install into zebra" : "Delete from zebra", - inet6_ntoa (rp->p.u.prefix6), rp->p.prefixlen, count); - else - zlog_debug ("%s: %s/%d", - (cmd == ZEBRA_IPV6_ROUTE_ADD) ? \ - "Install into zebra" : "Delete from zebra", - inet6_ntoa (rp->p.u.prefix6), rp->p.prefixlen); - } - } + static struct in6_addr **nexthops = NULL; + static ifindex_t *ifindexes = NULL; + static unsigned int nexthops_len = 0; + + struct list *list = (struct list *)rp->info; + struct zapi_ipv6 api; + struct listnode *listnode = NULL; + struct ripng_info *rinfo = NULL; + int count = 0; + + if (vrf_bitmap_check(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], + VRF_DEFAULT)) { + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_RIPNG; + api.instance = 0; + api.flags = 0; + api.message = 0; + api.safi = SAFI_UNICAST; + + if (nexthops_len < listcount(list)) { + nexthops_len = listcount(list); + nexthops = XREALLOC( + MTYPE_TMP, nexthops, + nexthops_len * sizeof(struct in6_addr *)); + ifindexes = + XREALLOC(MTYPE_TMP, ifindexes, + nexthops_len * sizeof(unsigned int)); + } + + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); + for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { + nexthops[count] = &rinfo->nexthop; + ifindexes[count] = rinfo->ifindex; + count++; + if (cmd == ZEBRA_IPV6_ROUTE_ADD) + SET_FLAG(rinfo->flags, RIPNG_RTF_FIB); + else + UNSET_FLAG(rinfo->flags, RIPNG_RTF_FIB); + } + + api.nexthop = nexthops; + api.nexthop_num = count; + api.ifindex = ifindexes; + api.ifindex_num = count; + + rinfo = listgetdata(listhead(list)); + + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = rinfo->metric; + + if (rinfo->tag) { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = rinfo->tag; + } + + zapi_ipv6_route(cmd, zclient, (struct prefix_ipv6 *)&rp->p, + NULL, &api); + + if (IS_RIPNG_DEBUG_ZEBRA) { + if (ripng->ecmp) + zlog_debug("%s: %s/%d nexthops %d", + (cmd == ZEBRA_IPV6_ROUTE_ADD) + ? "Install into zebra" + : "Delete from zebra", + inet6_ntoa(rp->p.u.prefix6), + rp->p.prefixlen, count); + else + zlog_debug("%s: %s/%d", + (cmd == ZEBRA_IPV6_ROUTE_ADD) + ? "Install into zebra" + : "Delete from zebra", + inet6_ntoa(rp->p.u.prefix6), + rp->p.prefixlen); + } + } } /* Add/update ECMP routes to zebra. */ -void -ripng_zebra_ipv6_add (struct route_node *rp) +void ripng_zebra_ipv6_add(struct route_node *rp) { - ripng_zebra_ipv6_send (rp, ZEBRA_IPV6_ROUTE_ADD); + ripng_zebra_ipv6_send(rp, ZEBRA_IPV6_ROUTE_ADD); } /* Delete ECMP routes from zebra. */ -void -ripng_zebra_ipv6_delete (struct route_node *rp) +void ripng_zebra_ipv6_delete(struct route_node *rp) { - ripng_zebra_ipv6_send (rp, ZEBRA_IPV6_ROUTE_DELETE); + ripng_zebra_ipv6_send(rp, ZEBRA_IPV6_ROUTE_DELETE); } /* Zebra route add and delete treatment. */ -static int -ripng_zebra_read_ipv6 (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int ripng_zebra_read_ipv6(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv6 api; - unsigned long ifindex; - struct in6_addr nexthop; - struct prefix_ipv6 p, src_p; - - s = zclient->ibuf; - ifindex = 0; - memset (&nexthop, 0, sizeof (struct in6_addr)); - - /* Type, flags, message. */ - api.type = stream_getc (s); - api.instance = stream_getw (s); - api.flags = stream_getl (s); - api.message = stream_getc (s); - - /* IPv6 prefix. */ - memset (&p, 0, sizeof (struct prefix_ipv6)); - p.family = AF_INET6; - p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc (s)); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); - - memset (&src_p, 0, sizeof (struct prefix_ipv6)); - src_p.family = AF_INET6; - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_SRCPFX)) - { - src_p.prefixlen = stream_getc (s); - stream_get (&src_p.prefix, s, PSIZE (src_p.prefixlen)); - } - - if (src_p.prefixlen) - /* we completely ignore srcdest routes for now. */ - return 0; - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) - { - api.nexthop_num = stream_getc (s); - stream_get (&nexthop, s, 16); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) - { - api.ifindex_num = stream_getc (s); - ifindex = stream_getl (s); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc (s); - else - api.distance = 0; - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl (s); - else - api.metric = 0; - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl (s); - else - api.tag = 0; - - if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) - ripng_redistribute_add (api.type, RIPNG_ROUTE_REDISTRIBUTE, &p, ifindex, &nexthop, api.tag); - else - ripng_redistribute_delete (api.type, RIPNG_ROUTE_REDISTRIBUTE, &p, ifindex); - - return 0; + struct stream *s; + struct zapi_ipv6 api; + unsigned long ifindex; + struct in6_addr nexthop; + struct prefix_ipv6 p, src_p; + + s = zclient->ibuf; + ifindex = 0; + memset(&nexthop, 0, sizeof(struct in6_addr)); + + /* Type, flags, message. */ + api.type = stream_getc(s); + api.instance = stream_getw(s); + api.flags = stream_getl(s); + api.message = stream_getc(s); + + /* IPv6 prefix. */ + memset(&p, 0, sizeof(struct prefix_ipv6)); + p.family = AF_INET6; + p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc(s)); + stream_get(&p.prefix, s, PSIZE(p.prefixlen)); + + memset(&src_p, 0, sizeof(struct prefix_ipv6)); + src_p.family = AF_INET6; + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { + src_p.prefixlen = stream_getc(s); + stream_get(&src_p.prefix, s, PSIZE(src_p.prefixlen)); + } + + if (src_p.prefixlen) + /* we completely ignore srcdest routes for now. */ + return 0; + + /* Nexthop, ifindex, distance, metric. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { + api.nexthop_num = stream_getc(s); + stream_get(&nexthop, s, 16); + } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { + api.ifindex_num = stream_getc(s); + ifindex = stream_getl(s); + } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) + api.distance = stream_getc(s); + else + api.distance = 0; + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) + api.metric = stream_getl(s); + else + api.metric = 0; + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getl(s); + else + api.tag = 0; + + if (command == ZEBRA_REDISTRIBUTE_IPV6_ADD) + ripng_redistribute_add(api.type, RIPNG_ROUTE_REDISTRIBUTE, &p, + ifindex, &nexthop, api.tag); + else + ripng_redistribute_delete(api.type, RIPNG_ROUTE_REDISTRIBUTE, + &p, ifindex); + + return 0; } -void -ripng_zclient_reset (void) +void ripng_zclient_reset(void) { - zclient_reset (zclient); + zclient_reset(zclient); } -static int -ripng_redistribute_unset (int type) +static int ripng_redistribute_unset(int type) { - if (! vrf_bitmap_check (zclient->redist[AFI_IP6][type], VRF_DEFAULT)) - return CMD_SUCCESS; + if (!vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT)) + return CMD_SUCCESS; + + vrf_bitmap_set(zclient->redist[AFI_IP6][type], VRF_DEFAULT); - vrf_bitmap_set (zclient->redist[AFI_IP6][type], VRF_DEFAULT); + if (zclient->sock > 0) + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, + AFI_IP6, type, 0, VRF_DEFAULT); - if (zclient->sock > 0) - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP6, type, 0, VRF_DEFAULT); + ripng_redistribute_withdraw(type); - ripng_redistribute_withdraw (type); - - return CMD_SUCCESS; + return CMD_SUCCESS; } -int -ripng_redistribute_check (int type) +int ripng_redistribute_check(int type) { - return vrf_bitmap_check (zclient->redist[AFI_IP6][type], VRF_DEFAULT); + return vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT); } -static void -ripng_redistribute_metric_set (int type, int metric) +static void ripng_redistribute_metric_set(int type, int metric) { - ripng->route_map[type].metric_config = 1; - ripng->route_map[type].metric = metric; + ripng->route_map[type].metric_config = 1; + ripng->route_map[type].metric = metric; } -static int -ripng_redistribute_metric_unset (int type) +static int ripng_redistribute_metric_unset(int type) { - ripng->route_map[type].metric_config = 0; - ripng->route_map[type].metric = 0; - return 0; + ripng->route_map[type].metric_config = 0; + ripng->route_map[type].metric = 0; + return 0; } -static void -ripng_redistribute_routemap_set (int type, const char *name) +static void ripng_redistribute_routemap_set(int type, const char *name) { - if (ripng->route_map[type].name) - free (ripng->route_map[type].name); + if (ripng->route_map[type].name) + free(ripng->route_map[type].name); - ripng->route_map[type].name = strdup (name); - ripng->route_map[type].map = route_map_lookup_by_name (name); + ripng->route_map[type].name = strdup(name); + ripng->route_map[type].map = route_map_lookup_by_name(name); } -static void -ripng_redistribute_routemap_unset (int type) +static void ripng_redistribute_routemap_unset(int type) { - if (ripng->route_map[type].name) - free (ripng->route_map[type].name); + if (ripng->route_map[type].name) + free(ripng->route_map[type].name); - ripng->route_map[type].name = NULL; - ripng->route_map[type].map = NULL; + ripng->route_map[type].name = NULL; + ripng->route_map[type].map = NULL; } /* Redistribution types */ static struct { - int type; - int str_min_len; - const char *str; -} redist_type[] = { - {ZEBRA_ROUTE_KERNEL, 1, "kernel"}, - {ZEBRA_ROUTE_CONNECT, 1, "connected"}, - {ZEBRA_ROUTE_STATIC, 1, "static"}, - {ZEBRA_ROUTE_OSPF6, 1, "ospf6"}, - {ZEBRA_ROUTE_BGP, 2, "bgp"}, - {ZEBRA_ROUTE_VNC, 1, "vnc"}, - {0, 0, NULL} -}; - -void -ripng_redistribute_clean () + int type; + int str_min_len; + const char *str; +} redist_type[] = {{ZEBRA_ROUTE_KERNEL, 1, "kernel"}, + {ZEBRA_ROUTE_CONNECT, 1, "connected"}, + {ZEBRA_ROUTE_STATIC, 1, "static"}, + {ZEBRA_ROUTE_OSPF6, 1, "ospf6"}, + {ZEBRA_ROUTE_BGP, 2, "bgp"}, + {ZEBRA_ROUTE_VNC, 1, "vnc"}, + {0, 0, NULL}}; + +void ripng_redistribute_clean() { - int i; - - for (i = 0; redist_type[i].str; i++) - { - if (vrf_bitmap_check (zclient->redist[AFI_IP6][redist_type[i].type], VRF_DEFAULT)) - { - if (zclient->sock > 0) - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, - zclient, AFI_IP6, redist_type[i].type, 0, - VRF_DEFAULT); - - vrf_bitmap_unset (zclient->redist[AFI_IP6][redist_type[i].type], VRF_DEFAULT); - - /* Remove the routes from RIPng table. */ - ripng_redistribute_withdraw (redist_type[i].type); - } - } + int i; + + for (i = 0; redist_type[i].str; i++) { + if (vrf_bitmap_check( + zclient->redist[AFI_IP6][redist_type[i].type], + VRF_DEFAULT)) { + if (zclient->sock > 0) + zebra_redistribute_send( + ZEBRA_REDISTRIBUTE_DELETE, zclient, + AFI_IP6, redist_type[i].type, 0, + VRF_DEFAULT); + + vrf_bitmap_unset( + zclient->redist[AFI_IP6][redist_type[i].type], + VRF_DEFAULT); + + /* Remove the routes from RIPng table. */ + ripng_redistribute_withdraw(redist_type[i].type); + } + } } DEFUN (ripng_redistribute_ripng, @@ -309,8 +300,9 @@ DEFUN (ripng_redistribute_ripng, "Redistribute information from another routing protocol\n" "RIPng route\n") { - vrf_bitmap_set (zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], VRF_DEFAULT); - return CMD_SUCCESS; + vrf_bitmap_set(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], + VRF_DEFAULT); + return CMD_SUCCESS; } DEFUN (no_ripng_redistribute_ripng, @@ -320,8 +312,9 @@ DEFUN (no_ripng_redistribute_ripng, "Redistribute information from another routing protocol\n" "RIPng route\n") { - vrf_bitmap_unset (zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], VRF_DEFAULT); - return CMD_SUCCESS; + vrf_bitmap_unset(zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], + VRF_DEFAULT); + return CMD_SUCCESS; } DEFUN (ripng_redistribute_type, @@ -330,19 +323,19 @@ DEFUN (ripng_redistribute_type, "Redistribute\n" FRR_REDIST_HELP_STR_RIPNGD) { - int type; + int type; - char *proto = argv[argc - 1]->text; - type = proto_redistnum(AFI_IP6, proto); + char *proto = argv[argc - 1]->text; + type = proto_redistnum(AFI_IP6, proto); - if (type < 0) - { - vty_out (vty, "Invalid type %s\n", proto); - return CMD_WARNING_CONFIG_FAILED; - } + if (type < 0) { + vty_out(vty, "Invalid type %s\n", proto); + return CMD_WARNING_CONFIG_FAILED; + } - zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0, VRF_DEFAULT); - return CMD_SUCCESS; + zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0, + VRF_DEFAULT); + return CMD_SUCCESS; } DEFUN (no_ripng_redistribute_type, @@ -356,20 +349,19 @@ DEFUN (no_ripng_redistribute_type, "Route map reference\n" "Pointer to route-map entries\n") { - int type; + int type; - char *proto = argv[2]->text; - type = proto_redistnum(AFI_IP6, proto); + char *proto = argv[2]->text; + type = proto_redistnum(AFI_IP6, proto); - if (type < 0) - { - vty_out (vty, "Invalid type %s\n", proto); - return CMD_WARNING_CONFIG_FAILED; - } + if (type < 0) { + vty_out(vty, "Invalid type %s\n", proto); + return CMD_WARNING_CONFIG_FAILED; + } - ripng_redistribute_metric_unset (type); - ripng_redistribute_routemap_unset (type); - return ripng_redistribute_unset (type); + ripng_redistribute_metric_unset(type); + ripng_redistribute_routemap_unset(type); + return ripng_redistribute_unset(type); } @@ -381,24 +373,23 @@ DEFUN (ripng_redistribute_type_metric, "Metric\n" "Metric value\n") { - int idx_protocol = 1; - int idx_number = 3; - int type; - int metric; - - metric = atoi (argv[idx_number]->arg); - type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text); - - if (type < 0) - { - vty_out (vty, "Invalid type %s\n", argv[idx_protocol]->text); - return CMD_WARNING_CONFIG_FAILED; - } - - ripng_redistribute_metric_set (type, metric); - zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0, - VRF_DEFAULT); - return CMD_SUCCESS; + int idx_protocol = 1; + int idx_number = 3; + int type; + int metric; + + metric = atoi(argv[idx_number]->arg); + type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text); + + if (type < 0) { + vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text); + return CMD_WARNING_CONFIG_FAILED; + } + + ripng_redistribute_metric_set(type, metric); + zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0, + VRF_DEFAULT); + return CMD_SUCCESS; } DEFUN (ripng_redistribute_type_routemap, @@ -409,22 +400,21 @@ DEFUN (ripng_redistribute_type_routemap, "Route map reference\n" "Pointer to route-map entries\n") { - int idx_protocol = 1; - int idx_word = 3; - int type; - - type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text); - - if (type < 0) - { - vty_out (vty, "Invalid type %s\n", argv[idx_protocol]->text); - return CMD_WARNING_CONFIG_FAILED; - } - - ripng_redistribute_routemap_set (type, argv[idx_word]->text); - zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0, - VRF_DEFAULT); - return CMD_SUCCESS; + int idx_protocol = 1; + int idx_word = 3; + int type; + + type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text); + + if (type < 0) { + vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text); + return CMD_WARNING_CONFIG_FAILED; + } + + ripng_redistribute_routemap_set(type, argv[idx_word]->text); + zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0, + VRF_DEFAULT); + return CMD_SUCCESS; } DEFUN (ripng_redistribute_type_metric_routemap, @@ -437,130 +427,130 @@ DEFUN (ripng_redistribute_type_metric_routemap, "Route map reference\n" "Pointer to route-map entries\n") { - int idx_protocol = 1; - int idx_number = 3; - int idx_word = 5; - int type; - int metric; - - type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text); - metric = atoi (argv[idx_number]->arg); - - if (type < 0) - { - vty_out (vty, "Invalid type %s\n", argv[idx_protocol]->text); - return CMD_WARNING_CONFIG_FAILED; - } - - ripng_redistribute_metric_set (type, metric); - ripng_redistribute_routemap_set (type, argv[idx_word]->text); - zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0, VRF_DEFAULT); - return CMD_SUCCESS; + int idx_protocol = 1; + int idx_number = 3; + int idx_word = 5; + int type; + int metric; + + type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text); + metric = atoi(argv[idx_number]->arg); + + if (type < 0) { + vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text); + return CMD_WARNING_CONFIG_FAILED; + } + + ripng_redistribute_metric_set(type, metric); + ripng_redistribute_routemap_set(type, argv[idx_word]->text); + zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, type, 0, + VRF_DEFAULT); + return CMD_SUCCESS; } -void -ripng_redistribute_write (struct vty *vty, int config_mode) +void ripng_redistribute_write(struct vty *vty, int config_mode) { - int i; - - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (i != zclient->redist_default && - vrf_bitmap_check (zclient->redist[AFI_IP6][i], VRF_DEFAULT)) - { - if (config_mode) - { - if (ripng->route_map[i].metric_config) - { - if (ripng->route_map[i].name) - vty_out (vty, " redistribute %s metric %d route-map %s\n", - zebra_route_string(i), ripng->route_map[i].metric, - ripng->route_map[i].name); - else - vty_out (vty, " redistribute %s metric %d\n", - zebra_route_string(i),ripng->route_map[i].metric); - } - else - { - if (ripng->route_map[i].name) - vty_out (vty, " redistribute %s route-map %s\n", - zebra_route_string(i),ripng->route_map[i].name); - else - vty_out (vty, " redistribute %s\n",zebra_route_string(i)); - } - } - else - vty_out (vty, " %s", zebra_route_string(i)); - } + int i; + + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (i != zclient->redist_default + && vrf_bitmap_check(zclient->redist[AFI_IP6][i], + VRF_DEFAULT)) { + if (config_mode) { + if (ripng->route_map[i].metric_config) { + if (ripng->route_map[i].name) + vty_out(vty, + " redistribute %s metric %d route-map %s\n", + zebra_route_string(i), + ripng->route_map[i] + .metric, + ripng->route_map[i] + .name); + else + vty_out(vty, + " redistribute %s metric %d\n", + zebra_route_string(i), + ripng->route_map[i] + .metric); + } else { + if (ripng->route_map[i].name) + vty_out(vty, + " redistribute %s route-map %s\n", + zebra_route_string(i), + ripng->route_map[i] + .name); + else + vty_out(vty, + " redistribute %s\n", + zebra_route_string(i)); + } + } else + vty_out(vty, " %s", zebra_route_string(i)); + } } /* RIPng configuration write function. */ -static int -zebra_config_write (struct vty *vty) +static int zebra_config_write(struct vty *vty) { - if (! zclient->enable) - { - vty_out (vty, "no router zebra\n"); - return 1; - } - else if (! vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], VRF_DEFAULT)) - { - vty_out (vty, "router zebra\n"); - vty_out (vty, " no redistribute ripng\n"); - return 1; - } - return 0; + if (!zclient->enable) { + vty_out(vty, "no router zebra\n"); + return 1; + } else if (!vrf_bitmap_check( + zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], + VRF_DEFAULT)) { + vty_out(vty, "router zebra\n"); + vty_out(vty, " no redistribute ripng\n"); + return 1; + } + return 0; } /* Zebra node structure. */ -static struct cmd_node zebra_node = -{ - ZEBRA_NODE, - "%s(config-router)# ", +static struct cmd_node zebra_node = { + ZEBRA_NODE, "%s(config-router)# ", }; -static void -ripng_zebra_connected (struct zclient *zclient) +static void ripng_zebra_connected(struct zclient *zclient) { - zclient_send_reg_requests (zclient, VRF_DEFAULT); + zclient_send_reg_requests(zclient, VRF_DEFAULT); } /* Initialize zebra structure and it's commands. */ -void -zebra_init (struct thread_master *master) +void zebra_init(struct thread_master *master) { - /* Allocate zebra structure. */ - zclient = zclient_new(master); - zclient_init (zclient, ZEBRA_ROUTE_RIPNG, 0); - - zclient->zebra_connected = ripng_zebra_connected; - zclient->interface_up = ripng_interface_up; - zclient->interface_down = ripng_interface_down; - zclient->interface_add = ripng_interface_add; - zclient->interface_delete = ripng_interface_delete; - zclient->interface_address_add = ripng_interface_address_add; - zclient->interface_address_delete = ripng_interface_address_delete; - zclient->redistribute_route_ipv6_add = ripng_zebra_read_ipv6; - zclient->redistribute_route_ipv6_del = ripng_zebra_read_ipv6; - - /* Install zebra node. */ - install_node (&zebra_node, zebra_config_write); - - /* Install command element for zebra node. */ - install_default (ZEBRA_NODE); - install_element (ZEBRA_NODE, &ripng_redistribute_ripng_cmd); - install_element (ZEBRA_NODE, &no_ripng_redistribute_ripng_cmd); - - /* Install command elements to ripng node */ - install_element (RIPNG_NODE, &ripng_redistribute_type_cmd); - install_element (RIPNG_NODE, &ripng_redistribute_type_routemap_cmd); - install_element (RIPNG_NODE, &ripng_redistribute_type_metric_cmd); - install_element (RIPNG_NODE, &ripng_redistribute_type_metric_routemap_cmd); - install_element (RIPNG_NODE, &no_ripng_redistribute_type_cmd); + /* Allocate zebra structure. */ + zclient = zclient_new(master); + zclient_init(zclient, ZEBRA_ROUTE_RIPNG, 0); + + zclient->zebra_connected = ripng_zebra_connected; + zclient->interface_up = ripng_interface_up; + zclient->interface_down = ripng_interface_down; + zclient->interface_add = ripng_interface_add; + zclient->interface_delete = ripng_interface_delete; + zclient->interface_address_add = ripng_interface_address_add; + zclient->interface_address_delete = ripng_interface_address_delete; + zclient->redistribute_route_ipv6_add = ripng_zebra_read_ipv6; + zclient->redistribute_route_ipv6_del = ripng_zebra_read_ipv6; + + /* Install zebra node. */ + install_node(&zebra_node, zebra_config_write); + + /* Install command element for zebra node. */ + install_default(ZEBRA_NODE); + install_element(ZEBRA_NODE, &ripng_redistribute_ripng_cmd); + install_element(ZEBRA_NODE, &no_ripng_redistribute_ripng_cmd); + + /* Install command elements to ripng node */ + install_element(RIPNG_NODE, &ripng_redistribute_type_cmd); + install_element(RIPNG_NODE, &ripng_redistribute_type_routemap_cmd); + install_element(RIPNG_NODE, &ripng_redistribute_type_metric_cmd); + install_element(RIPNG_NODE, + &ripng_redistribute_type_metric_routemap_cmd); + install_element(RIPNG_NODE, &no_ripng_redistribute_type_cmd); } -void -ripng_zebra_stop (void) +void ripng_zebra_stop(void) { - zclient_stop (zclient); - zclient_free (zclient); + zclient_stop(zclient); + zclient_free(zclient); } diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 8b4c3e850..2883698f4 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -46,493 +46,470 @@ ripng->fd must be negative value. */ struct ripng *ripng = NULL; -enum -{ - ripng_all_route, - ripng_changed_route, +enum { ripng_all_route, + ripng_changed_route, }; extern struct zebra_privs_t ripngd_privs; /* Prototypes. */ -void -ripng_output_process (struct interface *, struct sockaddr_in6 *, int); +void ripng_output_process(struct interface *, struct sockaddr_in6 *, int); -int -ripng_triggered_update (struct thread *); +int ripng_triggered_update(struct thread *); /* RIPng next hop specification. */ -struct ripng_nexthop -{ - enum ripng_nexthop_type - { - RIPNG_NEXTHOP_UNSPEC, - RIPNG_NEXTHOP_ADDRESS - } flag; - struct in6_addr address; +struct ripng_nexthop { + enum ripng_nexthop_type { + RIPNG_NEXTHOP_UNSPEC, + RIPNG_NEXTHOP_ADDRESS + } flag; + struct in6_addr address; }; -static int -ripng_route_rte (struct ripng_info *rinfo) +static int ripng_route_rte(struct ripng_info *rinfo) { - return (rinfo->type == ZEBRA_ROUTE_RIPNG && rinfo->sub_type == RIPNG_ROUTE_RTE); + return (rinfo->type == ZEBRA_ROUTE_RIPNG + && rinfo->sub_type == RIPNG_ROUTE_RTE); } /* Allocate new ripng information. */ -struct ripng_info * -ripng_info_new () +struct ripng_info *ripng_info_new() { - struct ripng_info *new; + struct ripng_info *new; - new = XCALLOC (MTYPE_RIPNG_ROUTE, sizeof (struct ripng_info)); - return new; + new = XCALLOC(MTYPE_RIPNG_ROUTE, sizeof(struct ripng_info)); + return new; } /* Free ripng information. */ -void -ripng_info_free (struct ripng_info *rinfo) +void ripng_info_free(struct ripng_info *rinfo) { - XFREE (MTYPE_RIPNG_ROUTE, rinfo); + XFREE(MTYPE_RIPNG_ROUTE, rinfo); } /* Create ripng socket. */ -static int -ripng_make_socket (void) +static int ripng_make_socket(void) { - int ret; - int sock; - struct sockaddr_in6 ripaddr; + int ret; + int sock; + struct sockaddr_in6 ripaddr; - sock = socket (AF_INET6, SOCK_DGRAM, 0); - if (sock < 0) - { - zlog_err("Can't make ripng socket"); - return sock; - } + sock = socket(AF_INET6, SOCK_DGRAM, 0); + if (sock < 0) { + zlog_err("Can't make ripng socket"); + return sock; + } - setsockopt_so_recvbuf (sock, 8096); - ret = setsockopt_ipv6_pktinfo (sock, 1); - if (ret < 0) - return ret; + setsockopt_so_recvbuf(sock, 8096); + ret = setsockopt_ipv6_pktinfo(sock, 1); + if (ret < 0) + return ret; #ifdef IPTOS_PREC_INTERNETCONTROL - ret = setsockopt_ipv6_tclass (sock, IPTOS_PREC_INTERNETCONTROL); - if (ret < 0) - return ret; + ret = setsockopt_ipv6_tclass(sock, IPTOS_PREC_INTERNETCONTROL); + if (ret < 0) + return ret; #endif - ret = setsockopt_ipv6_multicast_hops (sock, 255); - if (ret < 0) - return ret; - ret = setsockopt_ipv6_multicast_loop (sock, 0); - if (ret < 0) - return ret; - ret = setsockopt_ipv6_hoplimit (sock, 1); - if (ret < 0) - return ret; - - memset (&ripaddr, 0, sizeof (ripaddr)); - ripaddr.sin6_family = AF_INET6; + ret = setsockopt_ipv6_multicast_hops(sock, 255); + if (ret < 0) + return ret; + ret = setsockopt_ipv6_multicast_loop(sock, 0); + if (ret < 0) + return ret; + ret = setsockopt_ipv6_hoplimit(sock, 1); + if (ret < 0) + return ret; + + memset(&ripaddr, 0, sizeof(ripaddr)); + ripaddr.sin6_family = AF_INET6; #ifdef SIN6_LEN - ripaddr.sin6_len = sizeof (struct sockaddr_in6); + ripaddr.sin6_len = sizeof(struct sockaddr_in6); #endif /* SIN6_LEN */ - ripaddr.sin6_port = htons (RIPNG_PORT_DEFAULT); + ripaddr.sin6_port = htons(RIPNG_PORT_DEFAULT); - if (ripngd_privs.change (ZPRIVS_RAISE)) - zlog_err ("ripng_make_socket: could not raise privs"); - - ret = bind (sock, (struct sockaddr *) &ripaddr, sizeof (ripaddr)); - if (ret < 0) - { - zlog_err("Can't bind ripng socket: %s.", safe_strerror(errno)); - if (ripngd_privs.change (ZPRIVS_LOWER)) - zlog_err ("ripng_make_socket: could not lower privs"); - return ret; - } - if (ripngd_privs.change (ZPRIVS_LOWER)) - zlog_err ("ripng_make_socket: could not lower privs"); - return sock; + if (ripngd_privs.change(ZPRIVS_RAISE)) + zlog_err("ripng_make_socket: could not raise privs"); + + ret = bind(sock, (struct sockaddr *)&ripaddr, sizeof(ripaddr)); + if (ret < 0) { + zlog_err("Can't bind ripng socket: %s.", safe_strerror(errno)); + if (ripngd_privs.change(ZPRIVS_LOWER)) + zlog_err("ripng_make_socket: could not lower privs"); + return ret; + } + if (ripngd_privs.change(ZPRIVS_LOWER)) + zlog_err("ripng_make_socket: could not lower privs"); + return sock; } /* Send RIPng packet. */ -int -ripng_send_packet (caddr_t buf, int bufsize, struct sockaddr_in6 *to, - struct interface *ifp) -{ - int ret; - struct msghdr msg; - struct iovec iov; - struct cmsghdr *cmsgptr; - char adata [256]; - struct in6_pktinfo *pkt; - struct sockaddr_in6 addr; - - if (IS_RIPNG_DEBUG_SEND) { - if (to) - zlog_debug ("send to %s", inet6_ntoa (to->sin6_addr)); - zlog_debug (" send interface %s", ifp->name); - zlog_debug (" send packet size %d", bufsize); - } - - memset (&addr, 0, sizeof (struct sockaddr_in6)); - addr.sin6_family = AF_INET6; +int ripng_send_packet(caddr_t buf, int bufsize, struct sockaddr_in6 *to, + struct interface *ifp) +{ + int ret; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsgptr; + char adata[256]; + struct in6_pktinfo *pkt; + struct sockaddr_in6 addr; + + if (IS_RIPNG_DEBUG_SEND) { + if (to) + zlog_debug("send to %s", inet6_ntoa(to->sin6_addr)); + zlog_debug(" send interface %s", ifp->name); + zlog_debug(" send packet size %d", bufsize); + } + + memset(&addr, 0, sizeof(struct sockaddr_in6)); + addr.sin6_family = AF_INET6; #ifdef SIN6_LEN - addr.sin6_len = sizeof (struct sockaddr_in6); + addr.sin6_len = sizeof(struct sockaddr_in6); #endif /* SIN6_LEN */ - addr.sin6_flowinfo = htonl (RIPNG_PRIORITY_DEFAULT); - - /* When destination is specified. */ - if (to != NULL) - { - addr.sin6_addr = to->sin6_addr; - addr.sin6_port = to->sin6_port; - } - else - { - inet_pton(AF_INET6, RIPNG_GROUP, &addr.sin6_addr); - addr.sin6_port = htons (RIPNG_PORT_DEFAULT); - } - - msg.msg_name = (void *) &addr; - msg.msg_namelen = sizeof (struct sockaddr_in6); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = (void *) adata; - msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); - - iov.iov_base = buf; - iov.iov_len = bufsize; - - cmsgptr = (struct cmsghdr *)adata; - cmsgptr->cmsg_len = CMSG_LEN(sizeof (struct in6_pktinfo)); - cmsgptr->cmsg_level = IPPROTO_IPV6; - cmsgptr->cmsg_type = IPV6_PKTINFO; - - pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr); - memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr)); - pkt->ipi6_ifindex = ifp->ifindex; - - ret = sendmsg (ripng->sock, &msg, 0); + addr.sin6_flowinfo = htonl(RIPNG_PRIORITY_DEFAULT); + + /* When destination is specified. */ + if (to != NULL) { + addr.sin6_addr = to->sin6_addr; + addr.sin6_port = to->sin6_port; + } else { + inet_pton(AF_INET6, RIPNG_GROUP, &addr.sin6_addr); + addr.sin6_port = htons(RIPNG_PORT_DEFAULT); + } - if (ret < 0) { - if (to) - zlog_err ("RIPng send fail on %s to %s: %s", ifp->name, - inet6_ntoa (to->sin6_addr), safe_strerror (errno)); - else - zlog_err ("RIPng send fail on %s: %s", ifp->name, safe_strerror (errno)); - } + msg.msg_name = (void *)&addr; + msg.msg_namelen = sizeof(struct sockaddr_in6); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = (void *)adata; + msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); + + iov.iov_base = buf; + iov.iov_len = bufsize; + + cmsgptr = (struct cmsghdr *)adata; + cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + cmsgptr->cmsg_level = IPPROTO_IPV6; + cmsgptr->cmsg_type = IPV6_PKTINFO; + + pkt = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); + memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr)); + pkt->ipi6_ifindex = ifp->ifindex; + + ret = sendmsg(ripng->sock, &msg, 0); + + if (ret < 0) { + if (to) + zlog_err("RIPng send fail on %s to %s: %s", ifp->name, + inet6_ntoa(to->sin6_addr), + safe_strerror(errno)); + else + zlog_err("RIPng send fail on %s: %s", ifp->name, + safe_strerror(errno)); + } - return ret; + return ret; } /* Receive UDP RIPng packet from socket. */ -static int -ripng_recv_packet (int sock, u_char *buf, int bufsize, - struct sockaddr_in6 *from, ifindex_t *ifindex, - int *hoplimit) -{ - int ret; - struct msghdr msg; - struct iovec iov; - struct cmsghdr *cmsgptr; - struct in6_addr dst = { .s6_addr = { 0 } }; - - memset(&dst, 0, sizeof(struct in6_addr)); - - /* Ancillary data. This store cmsghdr and in6_pktinfo. But at this - point I can't determine size of cmsghdr */ - char adata[1024]; - - /* Fill in message and iovec. */ - msg.msg_name = (void *) from; - msg.msg_namelen = sizeof (struct sockaddr_in6); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = (void *) adata; - msg.msg_controllen = sizeof adata; - iov.iov_base = buf; - iov.iov_len = bufsize; - - /* If recvmsg fail return minus value. */ - ret = recvmsg (sock, &msg, 0); - if (ret < 0) - return ret; - - for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL; - cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) - { - /* I want interface index which this packet comes from. */ - if (cmsgptr->cmsg_level == IPPROTO_IPV6 && - cmsgptr->cmsg_type == IPV6_PKTINFO) - { - struct in6_pktinfo *ptr; - - ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr); - *ifindex = ptr->ipi6_ifindex; - dst = ptr->ipi6_addr; - - if (*ifindex == 0) - zlog_warn ("Interface index returned by IPV6_PKTINFO is zero"); - } - - /* Incoming packet's multicast hop limit. */ - if (cmsgptr->cmsg_level == IPPROTO_IPV6 && - cmsgptr->cmsg_type == IPV6_HOPLIMIT) - { - int *phoplimit = (int *) CMSG_DATA (cmsgptr); - *hoplimit = *phoplimit; +static int ripng_recv_packet(int sock, u_char *buf, int bufsize, + struct sockaddr_in6 *from, ifindex_t *ifindex, + int *hoplimit) +{ + int ret; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsgptr; + struct in6_addr dst = {.s6_addr = {0}}; + + memset(&dst, 0, sizeof(struct in6_addr)); + + /* Ancillary data. This store cmsghdr and in6_pktinfo. But at this + point I can't determine size of cmsghdr */ + char adata[1024]; + + /* Fill in message and iovec. */ + msg.msg_name = (void *)from; + msg.msg_namelen = sizeof(struct sockaddr_in6); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = (void *)adata; + msg.msg_controllen = sizeof adata; + iov.iov_base = buf; + iov.iov_len = bufsize; + + /* If recvmsg fail return minus value. */ + ret = recvmsg(sock, &msg, 0); + if (ret < 0) + return ret; + + for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL; + cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { + /* I want interface index which this packet comes from. */ + if (cmsgptr->cmsg_level == IPPROTO_IPV6 + && cmsgptr->cmsg_type == IPV6_PKTINFO) { + struct in6_pktinfo *ptr; + + ptr = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); + *ifindex = ptr->ipi6_ifindex; + dst = ptr->ipi6_addr; + + if (*ifindex == 0) + zlog_warn( + "Interface index returned by IPV6_PKTINFO is zero"); + } + + /* Incoming packet's multicast hop limit. */ + if (cmsgptr->cmsg_level == IPPROTO_IPV6 + && cmsgptr->cmsg_type == IPV6_HOPLIMIT) { + int *phoplimit = (int *)CMSG_DATA(cmsgptr); + *hoplimit = *phoplimit; + } } - } - /* Hoplimit check shold be done when destination address is - multicast address. */ - if (! IN6_IS_ADDR_MULTICAST (&dst)) - *hoplimit = -1; + /* Hoplimit check shold be done when destination address is + multicast address. */ + if (!IN6_IS_ADDR_MULTICAST(&dst)) + *hoplimit = -1; - return ret; + return ret; } /* Dump rip packet */ -void -ripng_packet_dump (struct ripng_packet *packet, int size, const char *sndrcv) -{ - caddr_t lim; - struct rte *rte; - const char *command_str; - - /* Set command string. */ - if (packet->command == RIPNG_REQUEST) - command_str = "request"; - else if (packet->command == RIPNG_RESPONSE) - command_str = "response"; - else - command_str = "unknown"; - - /* Dump packet header. */ - zlog_debug ("%s %s version %d packet size %d", - sndrcv, command_str, packet->version, size); - - /* Dump each routing table entry. */ - rte = packet->rte; - - for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++) - { - if (rte->metric == RIPNG_METRIC_NEXTHOP) - zlog_debug (" nexthop %s/%d", inet6_ntoa (rte->addr), rte->prefixlen); - else - zlog_debug (" %s/%d metric %d tag %"ROUTE_TAG_PRI, - inet6_ntoa (rte->addr), rte->prefixlen, - rte->metric, (route_tag_t)ntohs (rte->tag)); - } +void ripng_packet_dump(struct ripng_packet *packet, int size, + const char *sndrcv) +{ + caddr_t lim; + struct rte *rte; + const char *command_str; + + /* Set command string. */ + if (packet->command == RIPNG_REQUEST) + command_str = "request"; + else if (packet->command == RIPNG_RESPONSE) + command_str = "response"; + else + command_str = "unknown"; + + /* Dump packet header. */ + zlog_debug("%s %s version %d packet size %d", sndrcv, command_str, + packet->version, size); + + /* Dump each routing table entry. */ + rte = packet->rte; + + for (lim = (caddr_t)packet + size; (caddr_t)rte < lim; rte++) { + if (rte->metric == RIPNG_METRIC_NEXTHOP) + zlog_debug(" nexthop %s/%d", inet6_ntoa(rte->addr), + rte->prefixlen); + else + zlog_debug(" %s/%d metric %d tag %" ROUTE_TAG_PRI, + inet6_ntoa(rte->addr), rte->prefixlen, + rte->metric, (route_tag_t)ntohs(rte->tag)); + } } /* RIPng next hop address RTE (Route Table Entry). */ -static void -ripng_nexthop_rte (struct rte *rte, - struct sockaddr_in6 *from, - struct ripng_nexthop *nexthop) -{ - char buf[INET6_BUFSIZ]; - - /* Logging before checking RTE. */ - if (IS_RIPNG_DEBUG_RECV) - zlog_debug ("RIPng nexthop RTE address %s tag %"ROUTE_TAG_PRI" prefixlen %d", - inet6_ntoa (rte->addr), (route_tag_t)ntohs (rte->tag), rte->prefixlen); - - /* RFC2080 2.1.1 Next Hop: - The route tag and prefix length in the next hop RTE must be - set to zero on sending and ignored on receiption. */ - if (ntohs (rte->tag) != 0) - zlog_warn ("RIPng nexthop RTE with non zero tag value %"ROUTE_TAG_PRI" from %s", - (route_tag_t)ntohs (rte->tag), inet6_ntoa (from->sin6_addr)); - - if (rte->prefixlen != 0) - zlog_warn ("RIPng nexthop RTE with non zero prefixlen value %d from %s", - rte->prefixlen, inet6_ntoa (from->sin6_addr)); - - /* Specifying a value of 0:0:0:0:0:0:0:0 in the prefix field of a - next hop RTE indicates that the next hop address should be the - originator of the RIPng advertisement. An address specified as a - next hop must be a link-local address. */ - if (IN6_IS_ADDR_UNSPECIFIED (&rte->addr)) - { - nexthop->flag = RIPNG_NEXTHOP_UNSPEC; - memset (&nexthop->address, 0, sizeof (struct in6_addr)); - return; - } +static void ripng_nexthop_rte(struct rte *rte, struct sockaddr_in6 *from, + struct ripng_nexthop *nexthop) +{ + char buf[INET6_BUFSIZ]; + + /* Logging before checking RTE. */ + if (IS_RIPNG_DEBUG_RECV) + zlog_debug("RIPng nexthop RTE address %s tag %" ROUTE_TAG_PRI + " prefixlen %d", + inet6_ntoa(rte->addr), (route_tag_t)ntohs(rte->tag), + rte->prefixlen); + + /* RFC2080 2.1.1 Next Hop: + The route tag and prefix length in the next hop RTE must be + set to zero on sending and ignored on receiption. */ + if (ntohs(rte->tag) != 0) + zlog_warn( + "RIPng nexthop RTE with non zero tag value %" ROUTE_TAG_PRI + " from %s", + (route_tag_t)ntohs(rte->tag), + inet6_ntoa(from->sin6_addr)); + + if (rte->prefixlen != 0) + zlog_warn( + "RIPng nexthop RTE with non zero prefixlen value %d from %s", + rte->prefixlen, inet6_ntoa(from->sin6_addr)); + + /* Specifying a value of 0:0:0:0:0:0:0:0 in the prefix field of a + next hop RTE indicates that the next hop address should be the + originator of the RIPng advertisement. An address specified as a + next hop must be a link-local address. */ + if (IN6_IS_ADDR_UNSPECIFIED(&rte->addr)) { + nexthop->flag = RIPNG_NEXTHOP_UNSPEC; + memset(&nexthop->address, 0, sizeof(struct in6_addr)); + return; + } - if (IN6_IS_ADDR_LINKLOCAL (&rte->addr)) - { - nexthop->flag = RIPNG_NEXTHOP_ADDRESS; - IPV6_ADDR_COPY (&nexthop->address, &rte->addr); - return; - } + if (IN6_IS_ADDR_LINKLOCAL(&rte->addr)) { + nexthop->flag = RIPNG_NEXTHOP_ADDRESS; + IPV6_ADDR_COPY(&nexthop->address, &rte->addr); + return; + } - /* The purpose of the next hop RTE is to eliminate packets being - routed through extra hops in the system. It is particularly useful - when RIPng is not being run on all of the routers on a network. - Note that next hop RTE is "advisory". That is, if the provided - information is ignored, a possibly sub-optimal, but absolutely - valid, route may be taken. If the received next hop address is not - a link-local address, it should be treated as 0:0:0:0:0:0:0:0. */ - zlog_warn ("RIPng nexthop RTE with non link-local address %s from %s", - inet6_ntoa (rte->addr), - inet_ntop (AF_INET6, &from->sin6_addr, buf, INET6_BUFSIZ)); + /* The purpose of the next hop RTE is to eliminate packets being + routed through extra hops in the system. It is particularly useful + when RIPng is not being run on all of the routers on a network. + Note that next hop RTE is "advisory". That is, if the provided + information is ignored, a possibly sub-optimal, but absolutely + valid, route may be taken. If the received next hop address is not + a link-local address, it should be treated as 0:0:0:0:0:0:0:0. */ + zlog_warn("RIPng nexthop RTE with non link-local address %s from %s", + inet6_ntoa(rte->addr), + inet_ntop(AF_INET6, &from->sin6_addr, buf, INET6_BUFSIZ)); - nexthop->flag = RIPNG_NEXTHOP_UNSPEC; - memset (&nexthop->address, 0, sizeof (struct in6_addr)); + nexthop->flag = RIPNG_NEXTHOP_UNSPEC; + memset(&nexthop->address, 0, sizeof(struct in6_addr)); - return; + return; } /* If ifp has same link-local address then return 1. */ -static int -ripng_lladdr_check (struct interface *ifp, struct in6_addr *addr) +static int ripng_lladdr_check(struct interface *ifp, struct in6_addr *addr) { - struct listnode *node; - struct connected *connected; - struct prefix *p; + struct listnode *node; + struct connected *connected; + struct prefix *p; - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) - { - p = connected->address; + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { + p = connected->address; - if (p->family == AF_INET6 && - IN6_IS_ADDR_LINKLOCAL (&p->u.prefix6) && - IN6_ARE_ADDR_EQUAL (&p->u.prefix6, addr)) - return 1; - } - return 0; + if (p->family == AF_INET6 + && IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6) + && IN6_ARE_ADDR_EQUAL(&p->u.prefix6, addr)) + return 1; + } + return 0; } /* RIPng route garbage collect timer. */ -static int -ripng_garbage_collect (struct thread *t) +static int ripng_garbage_collect(struct thread *t) { - struct ripng_info *rinfo; - struct route_node *rp; + struct ripng_info *rinfo; + struct route_node *rp; - rinfo = THREAD_ARG (t); - rinfo->t_garbage_collect = NULL; + rinfo = THREAD_ARG(t); + rinfo->t_garbage_collect = NULL; - /* Off timeout timer. */ - RIPNG_TIMER_OFF (rinfo->t_timeout); - - /* Get route_node pointer. */ - rp = rinfo->rp; + /* Off timeout timer. */ + RIPNG_TIMER_OFF(rinfo->t_timeout); - /* Unlock route_node. */ - listnode_delete (rp->info, rinfo); - if (list_isempty ((struct list *)rp->info)) - { - list_free (rp->info); - rp->info = NULL; - route_unlock_node (rp); - } + /* Get route_node pointer. */ + rp = rinfo->rp; + + /* Unlock route_node. */ + listnode_delete(rp->info, rinfo); + if (list_isempty((struct list *)rp->info)) { + list_free(rp->info); + rp->info = NULL; + route_unlock_node(rp); + } - /* Free RIPng routing information. */ - ripng_info_free (rinfo); + /* Free RIPng routing information. */ + ripng_info_free(rinfo); - return 0; + return 0; } -static void ripng_timeout_update (struct ripng_info *rinfo); +static void ripng_timeout_update(struct ripng_info *rinfo); /* Add new route to the ECMP list. * RETURN: the new entry added in the list, or NULL if it is not the first * entry and ECMP is not allowed. */ -struct ripng_info * -ripng_ecmp_add (struct ripng_info *rinfo_new) +struct ripng_info *ripng_ecmp_add(struct ripng_info *rinfo_new) { - struct route_node *rp = rinfo_new->rp; - struct ripng_info *rinfo = NULL; - struct list *list = NULL; + struct route_node *rp = rinfo_new->rp; + struct ripng_info *rinfo = NULL; + struct list *list = NULL; - if (rp->info == NULL) - rp->info = list_new (); - list = (struct list *)rp->info; + if (rp->info == NULL) + rp->info = list_new(); + list = (struct list *)rp->info; - /* If ECMP is not allowed and some entry already exists in the list, - * do nothing. */ - if (listcount (list) && !ripng->ecmp) - return NULL; + /* If ECMP is not allowed and some entry already exists in the list, + * do nothing. */ + if (listcount(list) && !ripng->ecmp) + return NULL; - rinfo = ripng_info_new (); - memcpy (rinfo, rinfo_new, sizeof (struct ripng_info)); - listnode_add (list, rinfo); + rinfo = ripng_info_new(); + memcpy(rinfo, rinfo_new, sizeof(struct ripng_info)); + listnode_add(list, rinfo); - if (ripng_route_rte (rinfo)) - { - ripng_timeout_update (rinfo); - ripng_zebra_ipv6_add (rp); - } + if (ripng_route_rte(rinfo)) { + ripng_timeout_update(rinfo); + ripng_zebra_ipv6_add(rp); + } - ripng_aggregate_increment (rp, rinfo); + ripng_aggregate_increment(rp, rinfo); - /* Set the route change flag on the first entry. */ - rinfo = listgetdata (listhead (list)); - SET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED); + /* Set the route change flag on the first entry. */ + rinfo = listgetdata(listhead(list)); + SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED); - /* Signal the output process to trigger an update. */ - ripng_event (RIPNG_TRIGGERED_UPDATE, 0); + /* Signal the output process to trigger an update. */ + ripng_event(RIPNG_TRIGGERED_UPDATE, 0); - return rinfo; + return rinfo; } /* Replace the ECMP list with the new route. * RETURN: the new entry added in the list */ -struct ripng_info * -ripng_ecmp_replace (struct ripng_info *rinfo_new) -{ - struct route_node *rp = rinfo_new->rp; - struct list *list = (struct list *)rp->info; - struct ripng_info *rinfo = NULL, *tmp_rinfo = NULL; - struct listnode *node = NULL, *nextnode = NULL; - - if (list == NULL || listcount (list) == 0) - return ripng_ecmp_add (rinfo_new); - - /* Get the first entry */ - rinfo = listgetdata (listhead (list)); - - /* Learnt route replaced by a local one. Delete it from zebra. */ - if (ripng_route_rte (rinfo) && !ripng_route_rte (rinfo_new)) - if (CHECK_FLAG (rinfo->flags, RIPNG_RTF_FIB)) - ripng_zebra_ipv6_delete (rp); - - if (rinfo->metric != RIPNG_METRIC_INFINITY) - ripng_aggregate_decrement_list (rp, list); - - /* Re-use the first entry, and delete the others. */ - for (ALL_LIST_ELEMENTS (list, node, nextnode, tmp_rinfo)) - if (tmp_rinfo != rinfo) - { - RIPNG_TIMER_OFF (tmp_rinfo->t_timeout); - RIPNG_TIMER_OFF (tmp_rinfo->t_garbage_collect); - list_delete_node (list, node); - ripng_info_free (tmp_rinfo); - } - - RIPNG_TIMER_OFF (rinfo->t_timeout); - RIPNG_TIMER_OFF (rinfo->t_garbage_collect); - memcpy (rinfo, rinfo_new, sizeof (struct ripng_info)); - - if (ripng_route_rte (rinfo)) - { - ripng_timeout_update (rinfo); - /* The ADD message implies an update. */ - ripng_zebra_ipv6_add (rp); - } +struct ripng_info *ripng_ecmp_replace(struct ripng_info *rinfo_new) +{ + struct route_node *rp = rinfo_new->rp; + struct list *list = (struct list *)rp->info; + struct ripng_info *rinfo = NULL, *tmp_rinfo = NULL; + struct listnode *node = NULL, *nextnode = NULL; + + if (list == NULL || listcount(list) == 0) + return ripng_ecmp_add(rinfo_new); + + /* Get the first entry */ + rinfo = listgetdata(listhead(list)); + + /* Learnt route replaced by a local one. Delete it from zebra. */ + if (ripng_route_rte(rinfo) && !ripng_route_rte(rinfo_new)) + if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB)) + ripng_zebra_ipv6_delete(rp); + + if (rinfo->metric != RIPNG_METRIC_INFINITY) + ripng_aggregate_decrement_list(rp, list); + + /* Re-use the first entry, and delete the others. */ + for (ALL_LIST_ELEMENTS(list, node, nextnode, tmp_rinfo)) + if (tmp_rinfo != rinfo) { + RIPNG_TIMER_OFF(tmp_rinfo->t_timeout); + RIPNG_TIMER_OFF(tmp_rinfo->t_garbage_collect); + list_delete_node(list, node); + ripng_info_free(tmp_rinfo); + } - ripng_aggregate_increment (rp, rinfo); + RIPNG_TIMER_OFF(rinfo->t_timeout); + RIPNG_TIMER_OFF(rinfo->t_garbage_collect); + memcpy(rinfo, rinfo_new, sizeof(struct ripng_info)); - /* Set the route change flag. */ - SET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED); + if (ripng_route_rte(rinfo)) { + ripng_timeout_update(rinfo); + /* The ADD message implies an update. */ + ripng_zebra_ipv6_add(rp); + } + + ripng_aggregate_increment(rp, rinfo); + + /* Set the route change flag. */ + SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED); - /* Signal the output process to trigger an update. */ - ripng_event (RIPNG_TRIGGERED_UPDATE, 0); + /* Signal the output process to trigger an update. */ + ripng_event(RIPNG_TRIGGERED_UPDATE, 0); - return rinfo; + return rinfo; } /* Delete one route from the ECMP list. @@ -541,1448 +518,1426 @@ ripng_ecmp_replace (struct ripng_info *rinfo_new) * the entry - the entry is the last one in the list; its metric is set * to INFINITY, and the garbage collector is started for it */ -struct ripng_info * -ripng_ecmp_delete (struct ripng_info *rinfo) -{ - struct route_node *rp = rinfo->rp; - struct list *list = (struct list *)rp->info; - - RIPNG_TIMER_OFF (rinfo->t_timeout); - - if (rinfo->metric != RIPNG_METRIC_INFINITY) - ripng_aggregate_decrement (rp, rinfo); - - if (listcount (list) > 1) - { - /* Some other ECMP entries still exist. Just delete this entry. */ - RIPNG_TIMER_OFF (rinfo->t_garbage_collect); - listnode_delete (list, rinfo); - if (ripng_route_rte (rinfo) && CHECK_FLAG (rinfo->flags, RIPNG_RTF_FIB)) - /* The ADD message implies the update. */ - ripng_zebra_ipv6_add (rp); - ripng_info_free (rinfo); - rinfo = NULL; - } - else - { - assert (rinfo == listgetdata (listhead (list))); - - /* This is the only entry left in the list. We must keep it in - * the list for garbage collection time, with INFINITY metric. */ - - rinfo->metric = RIPNG_METRIC_INFINITY; - RIPNG_TIMER_ON (rinfo->t_garbage_collect, - ripng_garbage_collect, ripng->garbage_time); - - if (ripng_route_rte (rinfo) && CHECK_FLAG (rinfo->flags, RIPNG_RTF_FIB)) - ripng_zebra_ipv6_delete (rp); - } +struct ripng_info *ripng_ecmp_delete(struct ripng_info *rinfo) +{ + struct route_node *rp = rinfo->rp; + struct list *list = (struct list *)rp->info; + + RIPNG_TIMER_OFF(rinfo->t_timeout); + + if (rinfo->metric != RIPNG_METRIC_INFINITY) + ripng_aggregate_decrement(rp, rinfo); + + if (listcount(list) > 1) { + /* Some other ECMP entries still exist. Just delete this entry. + */ + RIPNG_TIMER_OFF(rinfo->t_garbage_collect); + listnode_delete(list, rinfo); + if (ripng_route_rte(rinfo) + && CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB)) + /* The ADD message implies the update. */ + ripng_zebra_ipv6_add(rp); + ripng_info_free(rinfo); + rinfo = NULL; + } else { + assert(rinfo == listgetdata(listhead(list))); + + /* This is the only entry left in the list. We must keep it in + * the list for garbage collection time, with INFINITY metric. + */ + + rinfo->metric = RIPNG_METRIC_INFINITY; + RIPNG_TIMER_ON(rinfo->t_garbage_collect, ripng_garbage_collect, + ripng->garbage_time); + + if (ripng_route_rte(rinfo) + && CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB)) + ripng_zebra_ipv6_delete(rp); + } - /* Set the route change flag on the first entry. */ - rinfo = listgetdata (listhead (list)); - SET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED); + /* Set the route change flag on the first entry. */ + rinfo = listgetdata(listhead(list)); + SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED); - /* Signal the output process to trigger an update. */ - ripng_event (RIPNG_TRIGGERED_UPDATE, 0); + /* Signal the output process to trigger an update. */ + ripng_event(RIPNG_TRIGGERED_UPDATE, 0); - return rinfo; + return rinfo; } /* Timeout RIPng routes. */ -static int -ripng_timeout (struct thread *t) +static int ripng_timeout(struct thread *t) { - ripng_ecmp_delete ((struct ripng_info *)THREAD_ARG (t)); - return 0; + ripng_ecmp_delete((struct ripng_info *)THREAD_ARG(t)); + return 0; } -static void -ripng_timeout_update (struct ripng_info *rinfo) +static void ripng_timeout_update(struct ripng_info *rinfo) { - if (rinfo->metric != RIPNG_METRIC_INFINITY) - { - RIPNG_TIMER_OFF (rinfo->t_timeout); - RIPNG_TIMER_ON (rinfo->t_timeout, ripng_timeout, ripng->timeout_time); - } + if (rinfo->metric != RIPNG_METRIC_INFINITY) { + RIPNG_TIMER_OFF(rinfo->t_timeout); + RIPNG_TIMER_ON(rinfo->t_timeout, ripng_timeout, + ripng->timeout_time); + } } -static int -ripng_filter (int ripng_distribute, struct prefix_ipv6 *p, - struct ripng_interface *ri) -{ - struct distribute *dist; - struct access_list *alist; - struct prefix_list *plist; - int distribute = ripng_distribute == RIPNG_FILTER_OUT ? - DISTRIBUTE_V6_OUT : DISTRIBUTE_V6_IN; - const char *inout = ripng_distribute == RIPNG_FILTER_OUT ? "out" : "in"; - - /* Input distribute-list filtering. */ - if (ri->list[ripng_distribute]) - { - if (access_list_apply (ri->list[ripng_distribute], - (struct prefix *) p) == FILTER_DENY) - { - if (IS_RIPNG_DEBUG_PACKET) - zlog_debug ("%s/%d filtered by distribute %s", - inet6_ntoa (p->prefix), p->prefixlen, inout); - return -1; +static int ripng_filter(int ripng_distribute, struct prefix_ipv6 *p, + struct ripng_interface *ri) +{ + struct distribute *dist; + struct access_list *alist; + struct prefix_list *plist; + int distribute = ripng_distribute == RIPNG_FILTER_OUT + ? DISTRIBUTE_V6_OUT + : DISTRIBUTE_V6_IN; + const char *inout = ripng_distribute == RIPNG_FILTER_OUT ? "out" : "in"; + + /* Input distribute-list filtering. */ + if (ri->list[ripng_distribute]) { + if (access_list_apply(ri->list[ripng_distribute], + (struct prefix *)p) + == FILTER_DENY) { + if (IS_RIPNG_DEBUG_PACKET) + zlog_debug("%s/%d filtered by distribute %s", + inet6_ntoa(p->prefix), p->prefixlen, + inout); + return -1; + } + } + if (ri->prefix[ripng_distribute]) { + if (prefix_list_apply(ri->prefix[ripng_distribute], + (struct prefix *)p) + == PREFIX_DENY) { + if (IS_RIPNG_DEBUG_PACKET) + zlog_debug("%s/%d filtered by prefix-list %s", + inet6_ntoa(p->prefix), p->prefixlen, + inout); + return -1; } - } - if (ri->prefix[ripng_distribute]) -{ - if (prefix_list_apply (ri->prefix[ripng_distribute], - (struct prefix *) p) == PREFIX_DENY) - { - if (IS_RIPNG_DEBUG_PACKET) - zlog_debug ("%s/%d filtered by prefix-list %s", - inet6_ntoa (p->prefix), p->prefixlen, inout); - return -1; } - } - /* All interface filter check. */ - dist = distribute_lookup (NULL); - if (dist) - { - if (dist->list[distribute]) - { - alist = access_list_lookup (AFI_IP6, dist->list[distribute]); - - if (alist) - { - if (access_list_apply (alist, - (struct prefix *) p) == FILTER_DENY) - { - if (IS_RIPNG_DEBUG_PACKET) - zlog_debug ("%s/%d filtered by distribute %s", - inet6_ntoa (p->prefix), p->prefixlen, inout); - return -1; + /* All interface filter check. */ + dist = distribute_lookup(NULL); + if (dist) { + if (dist->list[distribute]) { + alist = access_list_lookup(AFI_IP6, + dist->list[distribute]); + + if (alist) { + if (access_list_apply(alist, (struct prefix *)p) + == FILTER_DENY) { + if (IS_RIPNG_DEBUG_PACKET) + zlog_debug( + "%s/%d filtered by distribute %s", + inet6_ntoa(p->prefix), + p->prefixlen, inout); + return -1; + } + } } - } - } - if (dist->prefix[distribute]) - { - plist = prefix_list_lookup (AFI_IP6, dist->prefix[distribute]); - - if (plist) - { - if (prefix_list_apply (plist, - (struct prefix *) p) == PREFIX_DENY) - { - if (IS_RIPNG_DEBUG_PACKET) - zlog_debug ("%s/%d filtered by prefix-list %s", - inet6_ntoa (p->prefix), p->prefixlen, inout); - return -1; + if (dist->prefix[distribute]) { + plist = prefix_list_lookup(AFI_IP6, + dist->prefix[distribute]); + + if (plist) { + if (prefix_list_apply(plist, (struct prefix *)p) + == PREFIX_DENY) { + if (IS_RIPNG_DEBUG_PACKET) + zlog_debug( + "%s/%d filtered by prefix-list %s", + inet6_ntoa(p->prefix), + p->prefixlen, inout); + return -1; + } + } } - } } - } - return 0; + return 0; } /* Process RIPng route according to RFC2080. */ -static void -ripng_route_process (struct rte *rte, struct sockaddr_in6 *from, - struct ripng_nexthop *ripng_nexthop, - struct interface *ifp) -{ - int ret; - struct prefix_ipv6 p; - struct route_node *rp; - struct ripng_info *rinfo = NULL, newinfo; - struct ripng_interface *ri; - struct in6_addr *nexthop; - int same = 0; - struct list *list = NULL; - struct listnode *node = NULL; - - /* Make prefix structure. */ - memset (&p, 0, sizeof (struct prefix_ipv6)); - p.family = AF_INET6; - /* p.prefix = rte->addr; */ - IPV6_ADDR_COPY (&p.prefix, &rte->addr); - p.prefixlen = rte->prefixlen; - - /* Make sure mask is applied. */ - /* XXX We have to check the prefix is valid or not before call - apply_mask_ipv6. */ - apply_mask_ipv6 (&p); - - /* Apply input filters. */ - ri = ifp->info; - - ret = ripng_filter (RIPNG_FILTER_IN, &p, ri); - if (ret < 0) - return; - - memset (&newinfo, 0, sizeof (newinfo)); - newinfo.type = ZEBRA_ROUTE_RIPNG; - newinfo.sub_type = RIPNG_ROUTE_RTE; - if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) - newinfo.nexthop = ripng_nexthop->address; - else - newinfo.nexthop = from->sin6_addr; - newinfo.from = from->sin6_addr; - newinfo.ifindex = ifp->ifindex; - newinfo.metric = rte->metric; - newinfo.metric_out = rte->metric; /* XXX */ - newinfo.tag = ntohs (rte->tag); /* XXX */ - - /* Modify entry. */ - if (ri->routemap[RIPNG_FILTER_IN]) - { - int ret; - - ret = route_map_apply (ri->routemap[RIPNG_FILTER_IN], - (struct prefix *)&p, RMAP_RIPNG, &newinfo); - - if (ret == RMAP_DENYMATCH) - { - if (IS_RIPNG_DEBUG_PACKET) - zlog_debug ("RIPng %s/%d is filtered by route-map in", - inet6_ntoa (p.prefix), p.prefixlen); - return; - } - - /* Get back the object */ - if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) { - if (! IPV6_ADDR_SAME(&newinfo.nexthop, &ripng_nexthop->address) ) { - /* the nexthop get changed by the routemap */ - if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop)) - ripng_nexthop->address = newinfo.nexthop; - else - ripng_nexthop->address = in6addr_any; - } - } else { - if (! IPV6_ADDR_SAME(&newinfo.nexthop, &from->sin6_addr) ) { - /* the nexthop get changed by the routemap */ - if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop)) { - ripng_nexthop->flag = RIPNG_NEXTHOP_ADDRESS; - ripng_nexthop->address = newinfo.nexthop; - } - } - } - rte->tag = htons(newinfo.tag_out); /* XXX */ - rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */ - } +static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from, + struct ripng_nexthop *ripng_nexthop, + struct interface *ifp) +{ + int ret; + struct prefix_ipv6 p; + struct route_node *rp; + struct ripng_info *rinfo = NULL, newinfo; + struct ripng_interface *ri; + struct in6_addr *nexthop; + int same = 0; + struct list *list = NULL; + struct listnode *node = NULL; + + /* Make prefix structure. */ + memset(&p, 0, sizeof(struct prefix_ipv6)); + p.family = AF_INET6; + /* p.prefix = rte->addr; */ + IPV6_ADDR_COPY(&p.prefix, &rte->addr); + p.prefixlen = rte->prefixlen; + + /* Make sure mask is applied. */ + /* XXX We have to check the prefix is valid or not before call + apply_mask_ipv6. */ + apply_mask_ipv6(&p); + + /* Apply input filters. */ + ri = ifp->info; + + ret = ripng_filter(RIPNG_FILTER_IN, &p, ri); + if (ret < 0) + return; + + memset(&newinfo, 0, sizeof(newinfo)); + newinfo.type = ZEBRA_ROUTE_RIPNG; + newinfo.sub_type = RIPNG_ROUTE_RTE; + if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) + newinfo.nexthop = ripng_nexthop->address; + else + newinfo.nexthop = from->sin6_addr; + newinfo.from = from->sin6_addr; + newinfo.ifindex = ifp->ifindex; + newinfo.metric = rte->metric; + newinfo.metric_out = rte->metric; /* XXX */ + newinfo.tag = ntohs(rte->tag); /* XXX */ + + /* Modify entry. */ + if (ri->routemap[RIPNG_FILTER_IN]) { + int ret; + + ret = route_map_apply(ri->routemap[RIPNG_FILTER_IN], + (struct prefix *)&p, RMAP_RIPNG, + &newinfo); + + if (ret == RMAP_DENYMATCH) { + if (IS_RIPNG_DEBUG_PACKET) + zlog_debug( + "RIPng %s/%d is filtered by route-map in", + inet6_ntoa(p.prefix), p.prefixlen); + return; + } - /* Once the entry has been validated, update the metric by - * adding the cost of the network on wich the message - * arrived. If the result is greater than infinity, use infinity - * (RFC2453 Sec. 3.9.2) - **/ - - /* Zebra ripngd can handle offset-list in. */ - ret = ripng_offset_list_apply_in (&p, ifp, &rte->metric); - - /* If offset-list does not modify the metric use interface's - * one. */ - if (! ret) - rte->metric += ifp->metric ? ifp->metric : 1; - - if (rte->metric > RIPNG_METRIC_INFINITY) - rte->metric = RIPNG_METRIC_INFINITY; - - /* Set nexthop pointer. */ - if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) - nexthop = &ripng_nexthop->address; - else - nexthop = &from->sin6_addr; - - /* Lookup RIPng routing table. */ - rp = route_node_get (ripng->table, (struct prefix *) &p); - - newinfo.rp = rp; - newinfo.nexthop = *nexthop; - newinfo.metric = rte->metric; - newinfo.tag = ntohs (rte->tag); - - /* Check to see whether there is already RIPng route on the table. */ - if ((list = rp->info) != NULL) - for (ALL_LIST_ELEMENTS_RO (list, node, rinfo)) - { - /* Need to compare with redistributed entry or local entry */ - if (!ripng_route_rte (rinfo)) - break; - - if (IPV6_ADDR_SAME (&rinfo->from, &from->sin6_addr) && - IPV6_ADDR_SAME (&rinfo->nexthop, nexthop)) - break; - - if (!listnextnode (node)) - { - /* Not found in the list */ - - if (rte->metric > rinfo->metric) - { - /* New route has a greater metric. Discard it. */ - route_unlock_node (rp); - return; - } - - if (rte->metric < rinfo->metric) - /* New route has a smaller metric. Replace the ECMP list - * with the new one in below. */ - break; - - /* Metrics are same. Unless ECMP is disabled, keep "rinfo" null and - * the new route is added in the ECMP list in below. */ - if (! ripng->ecmp) - break; - } - } - - if (rinfo) - { - /* Redistributed route check. */ - if (rinfo->type != ZEBRA_ROUTE_RIPNG - && rinfo->metric != RIPNG_METRIC_INFINITY) - { - route_unlock_node (rp); - return; - } - - /* Local static route. */ - if (rinfo->type == ZEBRA_ROUTE_RIPNG - && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) || - (rinfo->sub_type == RIPNG_ROUTE_DEFAULT)) - && rinfo->metric != RIPNG_METRIC_INFINITY) - { - route_unlock_node (rp); - return; - } - } + /* Get back the object */ + if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) { + if (!IPV6_ADDR_SAME(&newinfo.nexthop, + &ripng_nexthop->address)) { + /* the nexthop get changed by the routemap */ + if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop)) + ripng_nexthop->address = + newinfo.nexthop; + else + ripng_nexthop->address = in6addr_any; + } + } else { + if (!IPV6_ADDR_SAME(&newinfo.nexthop, + &from->sin6_addr)) { + /* the nexthop get changed by the routemap */ + if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop)) { + ripng_nexthop->flag = + RIPNG_NEXTHOP_ADDRESS; + ripng_nexthop->address = + newinfo.nexthop; + } + } + } + rte->tag = htons(newinfo.tag_out); /* XXX */ + rte->metric = + newinfo.metric_out; /* XXX: the routemap uses the + metric_out field */ + } - if (!rinfo) - { - /* Now, check to see whether there is already an explicit route - for the destination prefix. If there is no such route, add - this route to the routing table, unless the metric is - infinity (there is no point in adding a route which - unusable). */ - if (rte->metric != RIPNG_METRIC_INFINITY) - ripng_ecmp_add (&newinfo); - } - else - { - /* If there is an existing route, compare the next hop address - to the address of the router from which the datagram came. - If this datagram is from the same router as the existing - route, reinitialize the timeout. */ - same = (IN6_ARE_ADDR_EQUAL (&rinfo->from, &from->sin6_addr) - && (rinfo->ifindex == ifp->ifindex)); - - /* - * RFC 2080 - Section 2.4.2: - * "If the new metric is the same as the old one, examine the timeout - * for the existing route. If it is at least halfway to the expiration - * point, switch to the new route. This heuristic is optional, but - * highly recommended". - */ - if (!ripng->ecmp && !same && - rinfo->metric == rte->metric && rinfo->t_timeout && - (thread_timer_remain_second (rinfo->t_timeout) < (ripng->timeout_time / 2))) - { - ripng_ecmp_replace (&newinfo); - } - /* Next, compare the metrics. If the datagram is from the same - router as the existing route, and the new metric is different - than the old one; or, if the new metric is lower than the old - one; do the following actions: */ - else if ((same && rinfo->metric != rte->metric) || - rte->metric < rinfo->metric) - { - if (listcount (list) == 1) - { - if (newinfo.metric != RIPNG_METRIC_INFINITY) - ripng_ecmp_replace (&newinfo); - else - ripng_ecmp_delete (rinfo); - } - else - { - if (newinfo.metric < rinfo->metric) - ripng_ecmp_replace (&newinfo); - else /* newinfo.metric > rinfo->metric */ - ripng_ecmp_delete (rinfo); - } - } - else /* same & no change */ - ripng_timeout_update (rinfo); - - /* Unlock tempolary lock of the route. */ - route_unlock_node (rp); - } -} + /* Once the entry has been validated, update the metric by + * adding the cost of the network on wich the message + * arrived. If the result is greater than infinity, use infinity + * (RFC2453 Sec. 3.9.2) + **/ + + /* Zebra ripngd can handle offset-list in. */ + ret = ripng_offset_list_apply_in(&p, ifp, &rte->metric); + + /* If offset-list does not modify the metric use interface's + * one. */ + if (!ret) + rte->metric += ifp->metric ? ifp->metric : 1; + + if (rte->metric > RIPNG_METRIC_INFINITY) + rte->metric = RIPNG_METRIC_INFINITY; + + /* Set nexthop pointer. */ + if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) + nexthop = &ripng_nexthop->address; + else + nexthop = &from->sin6_addr; + + /* Lookup RIPng routing table. */ + rp = route_node_get(ripng->table, (struct prefix *)&p); + + newinfo.rp = rp; + newinfo.nexthop = *nexthop; + newinfo.metric = rte->metric; + newinfo.tag = ntohs(rte->tag); + + /* Check to see whether there is already RIPng route on the table. */ + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS_RO(list, node, rinfo)) { + /* Need to compare with redistributed entry or local + * entry */ + if (!ripng_route_rte(rinfo)) + break; + + if (IPV6_ADDR_SAME(&rinfo->from, &from->sin6_addr) + && IPV6_ADDR_SAME(&rinfo->nexthop, nexthop)) + break; + + if (!listnextnode(node)) { + /* Not found in the list */ + + if (rte->metric > rinfo->metric) { + /* New route has a greater metric. + * Discard it. */ + route_unlock_node(rp); + return; + } + + if (rte->metric < rinfo->metric) + /* New route has a smaller metric. + * Replace the ECMP list + * with the new one in below. */ + break; + + /* Metrics are same. Unless ECMP is disabled, + * keep "rinfo" null and + * the new route is added in the ECMP list in + * below. */ + if (!ripng->ecmp) + break; + } + } -/* Add redistributed route to RIPng table. */ -void -ripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p, - ifindex_t ifindex, struct in6_addr *nexthop, - route_tag_t tag) -{ - struct route_node *rp; - struct ripng_info *rinfo = NULL, newinfo; - struct list *list = NULL; - - /* Redistribute route */ - if (IN6_IS_ADDR_LINKLOCAL (&p->prefix)) - return; - if (IN6_IS_ADDR_LOOPBACK (&p->prefix)) - return; - - rp = route_node_get (ripng->table, (struct prefix *) p); - - memset (&newinfo, 0, sizeof (struct ripng_info)); - newinfo.type = type; - newinfo.sub_type = sub_type; - newinfo.ifindex = ifindex; - newinfo.metric = 1; - if (tag <= UINT16_MAX) /* RIPng only supports 16 bit tags */ - newinfo.tag = tag; - newinfo.rp = rp; - if (nexthop && IN6_IS_ADDR_LINKLOCAL(nexthop)) - newinfo.nexthop = *nexthop; - - if ((list = rp->info) != NULL && listcount (list) != 0) - { - rinfo = listgetdata (listhead (list)); - - if (rinfo->type == ZEBRA_ROUTE_CONNECT - && rinfo->sub_type == RIPNG_ROUTE_INTERFACE - && rinfo->metric != RIPNG_METRIC_INFINITY) { - route_unlock_node (rp); - return; - } - - /* Manually configured RIPng route check. - * They have the precedence on all the other entries. - **/ - if (rinfo->type == ZEBRA_ROUTE_RIPNG - && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) || - (rinfo->sub_type == RIPNG_ROUTE_DEFAULT)) ) { - if (type != ZEBRA_ROUTE_RIPNG || ((sub_type != RIPNG_ROUTE_STATIC) && - (sub_type != RIPNG_ROUTE_DEFAULT))) { - route_unlock_node (rp); - return; - } - } - - ripng_ecmp_replace (&newinfo); - route_unlock_node (rp); - } - else - ripng_ecmp_add (&newinfo); + if (rinfo) { + /* Redistributed route check. */ + if (rinfo->type != ZEBRA_ROUTE_RIPNG + && rinfo->metric != RIPNG_METRIC_INFINITY) { + route_unlock_node(rp); + return; + } - if (IS_RIPNG_DEBUG_EVENT) { - if (!nexthop) - zlog_debug ("Redistribute new prefix %s/%d on the interface %s", - inet6_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(ifindex, VRF_DEFAULT)); - else - zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s", - inet6_ntoa(p->prefix), p->prefixlen, inet6_ntoa(*nexthop), - ifindex2ifname(ifindex, VRF_DEFAULT)); - } + /* Local static route. */ + if (rinfo->type == ZEBRA_ROUTE_RIPNG + && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) + || (rinfo->sub_type == RIPNG_ROUTE_DEFAULT)) + && rinfo->metric != RIPNG_METRIC_INFINITY) { + route_unlock_node(rp); + return; + } + } - ripng_event (RIPNG_TRIGGERED_UPDATE, 0); + if (!rinfo) { + /* Now, check to see whether there is already an explicit route + for the destination prefix. If there is no such route, add + this route to the routing table, unless the metric is + infinity (there is no point in adding a route which + unusable). */ + if (rte->metric != RIPNG_METRIC_INFINITY) + ripng_ecmp_add(&newinfo); + } else { + /* If there is an existing route, compare the next hop address + to the address of the router from which the datagram came. + If this datagram is from the same router as the existing + route, reinitialize the timeout. */ + same = (IN6_ARE_ADDR_EQUAL(&rinfo->from, &from->sin6_addr) + && (rinfo->ifindex == ifp->ifindex)); + + /* + * RFC 2080 - Section 2.4.2: + * "If the new metric is the same as the old one, examine the + * timeout + * for the existing route. If it is at least halfway to the + * expiration + * point, switch to the new route. This heuristic is optional, + * but + * highly recommended". + */ + if (!ripng->ecmp && !same && rinfo->metric == rte->metric + && rinfo->t_timeout + && (thread_timer_remain_second(rinfo->t_timeout) + < (ripng->timeout_time / 2))) { + ripng_ecmp_replace(&newinfo); + } + /* Next, compare the metrics. If the datagram is from the same + router as the existing route, and the new metric is different + than the old one; or, if the new metric is lower than the old + one; do the following actions: */ + else if ((same && rinfo->metric != rte->metric) + || rte->metric < rinfo->metric) { + if (listcount(list) == 1) { + if (newinfo.metric != RIPNG_METRIC_INFINITY) + ripng_ecmp_replace(&newinfo); + else + ripng_ecmp_delete(rinfo); + } else { + if (newinfo.metric < rinfo->metric) + ripng_ecmp_replace(&newinfo); + else /* newinfo.metric > rinfo->metric */ + ripng_ecmp_delete(rinfo); + } + } else /* same & no change */ + ripng_timeout_update(rinfo); + + /* Unlock tempolary lock of the route. */ + route_unlock_node(rp); + } } -/* Delete redistributed route to RIPng table. */ -void -ripng_redistribute_delete (int type, int sub_type, struct prefix_ipv6 *p, - ifindex_t ifindex) -{ - struct route_node *rp; - struct ripng_info *rinfo; +/* Add redistributed route to RIPng table. */ +void ripng_redistribute_add(int type, int sub_type, struct prefix_ipv6 *p, + ifindex_t ifindex, struct in6_addr *nexthop, + route_tag_t tag) +{ + struct route_node *rp; + struct ripng_info *rinfo = NULL, newinfo; + struct list *list = NULL; + + /* Redistribute route */ + if (IN6_IS_ADDR_LINKLOCAL(&p->prefix)) + return; + if (IN6_IS_ADDR_LOOPBACK(&p->prefix)) + return; + + rp = route_node_get(ripng->table, (struct prefix *)p); + + memset(&newinfo, 0, sizeof(struct ripng_info)); + newinfo.type = type; + newinfo.sub_type = sub_type; + newinfo.ifindex = ifindex; + newinfo.metric = 1; + if (tag <= UINT16_MAX) /* RIPng only supports 16 bit tags */ + newinfo.tag = tag; + newinfo.rp = rp; + if (nexthop && IN6_IS_ADDR_LINKLOCAL(nexthop)) + newinfo.nexthop = *nexthop; + + if ((list = rp->info) != NULL && listcount(list) != 0) { + rinfo = listgetdata(listhead(list)); + + if (rinfo->type == ZEBRA_ROUTE_CONNECT + && rinfo->sub_type == RIPNG_ROUTE_INTERFACE + && rinfo->metric != RIPNG_METRIC_INFINITY) { + route_unlock_node(rp); + return; + } + + /* Manually configured RIPng route check. + * They have the precedence on all the other entries. + **/ + if (rinfo->type == ZEBRA_ROUTE_RIPNG + && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) + || (rinfo->sub_type == RIPNG_ROUTE_DEFAULT))) { + if (type != ZEBRA_ROUTE_RIPNG + || ((sub_type != RIPNG_ROUTE_STATIC) + && (sub_type != RIPNG_ROUTE_DEFAULT))) { + route_unlock_node(rp); + return; + } + } - if (IN6_IS_ADDR_LINKLOCAL (&p->prefix)) - return; - if (IN6_IS_ADDR_LOOPBACK (&p->prefix)) - return; + ripng_ecmp_replace(&newinfo); + route_unlock_node(rp); + } else + ripng_ecmp_add(&newinfo); + + if (IS_RIPNG_DEBUG_EVENT) { + if (!nexthop) + zlog_debug( + "Redistribute new prefix %s/%d on the interface %s", + inet6_ntoa(p->prefix), p->prefixlen, + ifindex2ifname(ifindex, VRF_DEFAULT)); + else + zlog_debug( + "Redistribute new prefix %s/%d with nexthop %s on the interface %s", + inet6_ntoa(p->prefix), p->prefixlen, + inet6_ntoa(*nexthop), + ifindex2ifname(ifindex, VRF_DEFAULT)); + } - rp = route_node_lookup (ripng->table, (struct prefix *) p); + ripng_event(RIPNG_TRIGGERED_UPDATE, 0); +} - if (rp) - { - struct list *list = rp->info; - - if (list != NULL && listcount (list) != 0) - { - rinfo = listgetdata (listhead (list)); - if (rinfo != NULL - && rinfo->type == type - && rinfo->sub_type == sub_type - && rinfo->ifindex == ifindex) - { - /* Perform poisoned reverse. */ - rinfo->metric = RIPNG_METRIC_INFINITY; - RIPNG_TIMER_ON (rinfo->t_garbage_collect, - ripng_garbage_collect, ripng->garbage_time); - RIPNG_TIMER_OFF (rinfo->t_timeout); - - /* Aggregate count decrement. */ - ripng_aggregate_decrement (rp, rinfo); - - rinfo->flags |= RIPNG_RTF_CHANGED; - - if (IS_RIPNG_DEBUG_EVENT) - zlog_debug ("Poisone %s/%d on the interface %s with an " - "infinity metric [delete]", - inet6_ntoa (p->prefix), p->prefixlen, - ifindex2ifname (ifindex, VRF_DEFAULT)); - - ripng_event (RIPNG_TRIGGERED_UPDATE, 0); - } - } - route_unlock_node (rp); - } +/* Delete redistributed route to RIPng table. */ +void ripng_redistribute_delete(int type, int sub_type, struct prefix_ipv6 *p, + ifindex_t ifindex) +{ + struct route_node *rp; + struct ripng_info *rinfo; + + if (IN6_IS_ADDR_LINKLOCAL(&p->prefix)) + return; + if (IN6_IS_ADDR_LOOPBACK(&p->prefix)) + return; + + rp = route_node_lookup(ripng->table, (struct prefix *)p); + + if (rp) { + struct list *list = rp->info; + + if (list != NULL && listcount(list) != 0) { + rinfo = listgetdata(listhead(list)); + if (rinfo != NULL && rinfo->type == type + && rinfo->sub_type == sub_type + && rinfo->ifindex == ifindex) { + /* Perform poisoned reverse. */ + rinfo->metric = RIPNG_METRIC_INFINITY; + RIPNG_TIMER_ON(rinfo->t_garbage_collect, + ripng_garbage_collect, + ripng->garbage_time); + RIPNG_TIMER_OFF(rinfo->t_timeout); + + /* Aggregate count decrement. */ + ripng_aggregate_decrement(rp, rinfo); + + rinfo->flags |= RIPNG_RTF_CHANGED; + + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug( + "Poisone %s/%d on the interface %s with an " + "infinity metric [delete]", + inet6_ntoa(p->prefix), + p->prefixlen, + ifindex2ifname(ifindex, + VRF_DEFAULT)); + + ripng_event(RIPNG_TRIGGERED_UPDATE, 0); + } + } + route_unlock_node(rp); + } } /* Withdraw redistributed route. */ -void -ripng_redistribute_withdraw (int type) -{ - struct route_node *rp; - struct ripng_info *rinfo = NULL; - struct list *list = NULL; +void ripng_redistribute_withdraw(int type) +{ + struct route_node *rp; + struct ripng_info *rinfo = NULL; + struct list *list = NULL; + + if (!ripng) + return; + + for (rp = route_top(ripng->table); rp; rp = route_next(rp)) + if ((list = rp->info) != NULL) { + rinfo = listgetdata(listhead(list)); + if ((rinfo->type == type) + && (rinfo->sub_type != RIPNG_ROUTE_INTERFACE)) { + /* Perform poisoned reverse. */ + rinfo->metric = RIPNG_METRIC_INFINITY; + RIPNG_TIMER_ON(rinfo->t_garbage_collect, + ripng_garbage_collect, + ripng->garbage_time); + RIPNG_TIMER_OFF(rinfo->t_timeout); + + /* Aggregate count decrement. */ + ripng_aggregate_decrement(rp, rinfo); + + rinfo->flags |= RIPNG_RTF_CHANGED; + + if (IS_RIPNG_DEBUG_EVENT) { + struct prefix_ipv6 *p = + (struct prefix_ipv6 *)&rp->p; + + zlog_debug( + "Poisone %s/%d on the interface %s [withdraw]", + inet6_ntoa(p->prefix), + p->prefixlen, + ifindex2ifname(rinfo->ifindex, + VRF_DEFAULT)); + } + + ripng_event(RIPNG_TRIGGERED_UPDATE, 0); + } + } +} - if (!ripng) - return; - - for (rp = route_top (ripng->table); rp; rp = route_next (rp)) - if ((list = rp->info) != NULL) - { - rinfo = listgetdata (listhead (list)); - if ((rinfo->type == type) - && (rinfo->sub_type != RIPNG_ROUTE_INTERFACE)) - { - /* Perform poisoned reverse. */ - rinfo->metric = RIPNG_METRIC_INFINITY; - RIPNG_TIMER_ON (rinfo->t_garbage_collect, - ripng_garbage_collect, ripng->garbage_time); - RIPNG_TIMER_OFF (rinfo->t_timeout); +/* RIP routing information. */ +static void ripng_response_process(struct ripng_packet *packet, int size, + struct sockaddr_in6 *from, + struct interface *ifp, int hoplimit) +{ + caddr_t lim; + struct rte *rte; + struct ripng_nexthop nexthop; + + /* RFC2080 2.4.2 Response Messages: + The Response must be ignored if it is not from the RIPng port. */ + if (ntohs(from->sin6_port) != RIPNG_PORT_DEFAULT) { + zlog_warn("RIPng packet comes from non RIPng port %d from %s", + ntohs(from->sin6_port), inet6_ntoa(from->sin6_addr)); + ripng_peer_bad_packet(from); + return; + } - /* Aggregate count decrement. */ - ripng_aggregate_decrement (rp, rinfo); + /* The datagram's IPv6 source address should be checked to see + whether the datagram is from a valid neighbor; the source of the + datagram must be a link-local address. */ + if (!IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr)) { + zlog_warn("RIPng packet comes from non link local address %s", + inet6_ntoa(from->sin6_addr)); + ripng_peer_bad_packet(from); + return; + } - rinfo->flags |= RIPNG_RTF_CHANGED; + /* It is also worth checking to see whether the response is from one + of the router's own addresses. Interfaces on broadcast networks + may receive copies of their own multicasts immediately. If a + router processes its own output as new input, confusion is likely, + and such datagrams must be ignored. */ + if (ripng_lladdr_check(ifp, &from->sin6_addr)) { + zlog_warn( + "RIPng packet comes from my own link local address %s", + inet6_ntoa(from->sin6_addr)); + ripng_peer_bad_packet(from); + return; + } - if (IS_RIPNG_DEBUG_EVENT) { - struct prefix_ipv6 *p = (struct prefix_ipv6 *) &rp->p; + /* As an additional check, periodic advertisements must have their + hop counts set to 255, and inbound, multicast packets sent from the + RIPng port (i.e. periodic advertisement or triggered update + packets) must be examined to ensure that the hop count is 255. */ + if (hoplimit >= 0 && hoplimit != 255) { + zlog_warn( + "RIPng packet comes with non 255 hop count %d from %s", + hoplimit, inet6_ntoa(from->sin6_addr)); + ripng_peer_bad_packet(from); + return; + } - zlog_debug ("Poisone %s/%d on the interface %s [withdraw]", - inet6_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(rinfo->ifindex, VRF_DEFAULT)); - } + /* Update RIPng peer. */ + ripng_peer_update(from, packet->version); - ripng_event (RIPNG_TRIGGERED_UPDATE, 0); - } - } -} + /* Reset nexthop. */ + memset(&nexthop, 0, sizeof(struct ripng_nexthop)); + nexthop.flag = RIPNG_NEXTHOP_UNSPEC; -/* RIP routing information. */ -static void -ripng_response_process (struct ripng_packet *packet, int size, - struct sockaddr_in6 *from, struct interface *ifp, - int hoplimit) -{ - caddr_t lim; - struct rte *rte; - struct ripng_nexthop nexthop; - - /* RFC2080 2.4.2 Response Messages: - The Response must be ignored if it is not from the RIPng port. */ - if (ntohs (from->sin6_port) != RIPNG_PORT_DEFAULT) - { - zlog_warn ("RIPng packet comes from non RIPng port %d from %s", - ntohs (from->sin6_port), inet6_ntoa (from->sin6_addr)); - ripng_peer_bad_packet (from); - return; - } + /* Set RTE pointer. */ + rte = packet->rte; - /* The datagram's IPv6 source address should be checked to see - whether the datagram is from a valid neighbor; the source of the - datagram must be a link-local address. */ - if (! IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr)) - { - zlog_warn ("RIPng packet comes from non link local address %s", - inet6_ntoa (from->sin6_addr)); - ripng_peer_bad_packet (from); - return; - } + for (lim = ((caddr_t)packet) + size; (caddr_t)rte < lim; rte++) { + /* First of all, we have to check this RTE is next hop RTE or + not. Next hop RTE is completely different with normal RTE so + we need special treatment. */ + if (rte->metric == RIPNG_METRIC_NEXTHOP) { + ripng_nexthop_rte(rte, from, &nexthop); + continue; + } - /* It is also worth checking to see whether the response is from one - of the router's own addresses. Interfaces on broadcast networks - may receive copies of their own multicasts immediately. If a - router processes its own output as new input, confusion is likely, - and such datagrams must be ignored. */ - if (ripng_lladdr_check (ifp, &from->sin6_addr)) - { - zlog_warn ("RIPng packet comes from my own link local address %s", - inet6_ntoa (from->sin6_addr)); - ripng_peer_bad_packet (from); - return; - } + /* RTE information validation. */ + + /* - is the destination prefix valid (e.g., not a multicast + prefix and not a link-local address) A link-local address + should never be present in an RTE. */ + if (IN6_IS_ADDR_MULTICAST(&rte->addr)) { + zlog_warn( + "Destination prefix is a multicast address %s/%d [%d]", + inet6_ntoa(rte->addr), rte->prefixlen, + rte->metric); + ripng_peer_bad_route(from); + continue; + } + if (IN6_IS_ADDR_LINKLOCAL(&rte->addr)) { + zlog_warn( + "Destination prefix is a link-local address %s/%d [%d]", + inet6_ntoa(rte->addr), rte->prefixlen, + rte->metric); + ripng_peer_bad_route(from); + continue; + } + if (IN6_IS_ADDR_LOOPBACK(&rte->addr)) { + zlog_warn( + "Destination prefix is a loopback address %s/%d [%d]", + inet6_ntoa(rte->addr), rte->prefixlen, + rte->metric); + ripng_peer_bad_route(from); + continue; + } - /* As an additional check, periodic advertisements must have their - hop counts set to 255, and inbound, multicast packets sent from the - RIPng port (i.e. periodic advertisement or triggered update - packets) must be examined to ensure that the hop count is 255. */ - if (hoplimit >= 0 && hoplimit != 255) - { - zlog_warn ("RIPng packet comes with non 255 hop count %d from %s", - hoplimit, inet6_ntoa (from->sin6_addr)); - ripng_peer_bad_packet (from); - return; - } + /* - is the prefix length valid (i.e., between 0 and 128, + inclusive) */ + if (rte->prefixlen > 128) { + zlog_warn("Invalid prefix length %s/%d from %s%%%s", + inet6_ntoa(rte->addr), rte->prefixlen, + inet6_ntoa(from->sin6_addr), ifp->name); + ripng_peer_bad_route(from); + continue; + } - /* Update RIPng peer. */ - ripng_peer_update (from, packet->version); - - /* Reset nexthop. */ - memset (&nexthop, 0, sizeof (struct ripng_nexthop)); - nexthop.flag = RIPNG_NEXTHOP_UNSPEC; + /* - is the metric valid (i.e., between 1 and 16, inclusive) */ + if (!(rte->metric >= 1 && rte->metric <= 16)) { + zlog_warn("Invalid metric %d from %s%%%s", rte->metric, + inet6_ntoa(from->sin6_addr), ifp->name); + ripng_peer_bad_route(from); + continue; + } - /* Set RTE pointer. */ - rte = packet->rte; + /* Vincent: XXX Should we compute the direclty reachable nexthop + * for our RIPng network ? + **/ - for (lim = ((caddr_t) packet) + size; (caddr_t) rte < lim; rte++) - { - /* First of all, we have to check this RTE is next hop RTE or - not. Next hop RTE is completely different with normal RTE so - we need special treatment. */ - if (rte->metric == RIPNG_METRIC_NEXTHOP) - { - ripng_nexthop_rte (rte, from, &nexthop); - continue; - } - - /* RTE information validation. */ - - /* - is the destination prefix valid (e.g., not a multicast - prefix and not a link-local address) A link-local address - should never be present in an RTE. */ - if (IN6_IS_ADDR_MULTICAST (&rte->addr)) - { - zlog_warn ("Destination prefix is a multicast address %s/%d [%d]", - inet6_ntoa (rte->addr), rte->prefixlen, rte->metric); - ripng_peer_bad_route (from); - continue; - } - if (IN6_IS_ADDR_LINKLOCAL (&rte->addr)) - { - zlog_warn ("Destination prefix is a link-local address %s/%d [%d]", - inet6_ntoa (rte->addr), rte->prefixlen, rte->metric); - ripng_peer_bad_route (from); - continue; - } - if (IN6_IS_ADDR_LOOPBACK (&rte->addr)) - { - zlog_warn ("Destination prefix is a loopback address %s/%d [%d]", - inet6_ntoa (rte->addr), rte->prefixlen, rte->metric); - ripng_peer_bad_route (from); - continue; - } - - /* - is the prefix length valid (i.e., between 0 and 128, - inclusive) */ - if (rte->prefixlen > 128) - { - zlog_warn ("Invalid prefix length %s/%d from %s%%%s", - inet6_ntoa (rte->addr), rte->prefixlen, - inet6_ntoa (from->sin6_addr), ifp->name); - ripng_peer_bad_route (from); - continue; - } - - /* - is the metric valid (i.e., between 1 and 16, inclusive) */ - if (! (rte->metric >= 1 && rte->metric <= 16)) - { - zlog_warn ("Invalid metric %d from %s%%%s", rte->metric, - inet6_ntoa (from->sin6_addr), ifp->name); - ripng_peer_bad_route (from); - continue; - } - - /* Vincent: XXX Should we compute the direclty reachable nexthop - * for our RIPng network ? - **/ - - /* Routing table updates. */ - ripng_route_process (rte, from, &nexthop, ifp); - } + /* Routing table updates. */ + ripng_route_process(rte, from, &nexthop, ifp); + } } /* Response to request message. */ -static void -ripng_request_process (struct ripng_packet *packet,int size, - struct sockaddr_in6 *from, struct interface *ifp) -{ - caddr_t lim; - struct rte *rte; - struct prefix_ipv6 p; - struct route_node *rp; - struct ripng_info *rinfo; - struct ripng_interface *ri; - - /* Does not reponse to the requests on the loopback interfaces */ - if (if_is_loopback (ifp)) - return; - - /* Check RIPng process is enabled on this interface. */ - ri = ifp->info; - if (! ri->running) - return; - - /* When passive interface is specified, suppress responses */ - if (ri->passive) - return; - - /* RIPng peer update. */ - ripng_peer_update (from, packet->version); - - lim = ((caddr_t) packet) + size; - rte = packet->rte; - - /* The Request is processed entry by entry. If there are no - entries, no response is given. */ - if (lim == (caddr_t) rte) - return; - - /* There is one special case. If there is exactly one entry in the - request, and it has a destination prefix of zero, a prefix length - of zero, and a metric of infinity (i.e., 16), then this is a - request to send the entire routing table. In that case, a call - is made to the output process to send the routing table to the - requesting address/port. */ - if (lim == ((caddr_t) (rte + 1)) && - IN6_IS_ADDR_UNSPECIFIED (&rte->addr) && - rte->prefixlen == 0 && - rte->metric == RIPNG_METRIC_INFINITY) - { - /* All route with split horizon */ - ripng_output_process (ifp, from, ripng_all_route); - } - else - { - /* Except for this special case, processing is quite simple. - Examine the list of RTEs in the Request one by one. For each - entry, look up the destination in the router's routing - database and, if there is a route, put that route's metric in - the metric field of the RTE. If there is no explicit route - to the specified destination, put infinity in the metric - field. Once all the entries have been filled in, change the - command from Request to Response and send the datagram back - to the requestor. */ - memset (&p, 0, sizeof (struct prefix_ipv6)); - p.family = AF_INET6; - - for (; ((caddr_t) rte) < lim; rte++) - { - p.prefix = rte->addr; - p.prefixlen = rte->prefixlen; - apply_mask_ipv6 (&p); - - rp = route_node_lookup (ripng->table, (struct prefix *) &p); - - if (rp) - { - rinfo = listgetdata (listhead ((struct list *)rp->info)); - rte->metric = rinfo->metric; - route_unlock_node (rp); - } - else - rte->metric = RIPNG_METRIC_INFINITY; - } - packet->command = RIPNG_RESPONSE; - - ripng_send_packet ((caddr_t) packet, size, from, ifp); - } +static void ripng_request_process(struct ripng_packet *packet, int size, + struct sockaddr_in6 *from, + struct interface *ifp) +{ + caddr_t lim; + struct rte *rte; + struct prefix_ipv6 p; + struct route_node *rp; + struct ripng_info *rinfo; + struct ripng_interface *ri; + + /* Does not reponse to the requests on the loopback interfaces */ + if (if_is_loopback(ifp)) + return; + + /* Check RIPng process is enabled on this interface. */ + ri = ifp->info; + if (!ri->running) + return; + + /* When passive interface is specified, suppress responses */ + if (ri->passive) + return; + + /* RIPng peer update. */ + ripng_peer_update(from, packet->version); + + lim = ((caddr_t)packet) + size; + rte = packet->rte; + + /* The Request is processed entry by entry. If there are no + entries, no response is given. */ + if (lim == (caddr_t)rte) + return; + + /* There is one special case. If there is exactly one entry in the + request, and it has a destination prefix of zero, a prefix length + of zero, and a metric of infinity (i.e., 16), then this is a + request to send the entire routing table. In that case, a call + is made to the output process to send the routing table to the + requesting address/port. */ + if (lim == ((caddr_t)(rte + 1)) && IN6_IS_ADDR_UNSPECIFIED(&rte->addr) + && rte->prefixlen == 0 && rte->metric == RIPNG_METRIC_INFINITY) { + /* All route with split horizon */ + ripng_output_process(ifp, from, ripng_all_route); + } else { + /* Except for this special case, processing is quite simple. + Examine the list of RTEs in the Request one by one. For each + entry, look up the destination in the router's routing + database and, if there is a route, put that route's metric in + the metric field of the RTE. If there is no explicit route + to the specified destination, put infinity in the metric + field. Once all the entries have been filled in, change the + command from Request to Response and send the datagram back + to the requestor. */ + memset(&p, 0, sizeof(struct prefix_ipv6)); + p.family = AF_INET6; + + for (; ((caddr_t)rte) < lim; rte++) { + p.prefix = rte->addr; + p.prefixlen = rte->prefixlen; + apply_mask_ipv6(&p); + + rp = route_node_lookup(ripng->table, + (struct prefix *)&p); + + if (rp) { + rinfo = listgetdata( + listhead((struct list *)rp->info)); + rte->metric = rinfo->metric; + route_unlock_node(rp); + } else + rte->metric = RIPNG_METRIC_INFINITY; + } + packet->command = RIPNG_RESPONSE; + + ripng_send_packet((caddr_t)packet, size, from, ifp); + } } /* First entry point of reading RIPng packet. */ -static int -ripng_read (struct thread *thread) -{ - int len; - int sock; - struct sockaddr_in6 from; - struct ripng_packet *packet; - ifindex_t ifindex = 0; - struct interface *ifp; - int hoplimit = -1; - - /* Check ripng is active and alive. */ - assert (ripng != NULL); - assert (ripng->sock >= 0); - - /* Fetch thread data and set read pointer to empty for event - managing. `sock' sould be same as ripng->sock. */ - sock = THREAD_FD (thread); - ripng->t_read = NULL; - - /* Add myself to the next event. */ - ripng_event (RIPNG_READ, sock); - - /* Read RIPng packet. */ - len = ripng_recv_packet (sock, STREAM_DATA (ripng->ibuf), - STREAM_SIZE (ripng->ibuf), &from, &ifindex, - &hoplimit); - if (len < 0) - { - zlog_warn ("RIPng recvfrom failed: %s.", safe_strerror (errno)); - return len; - } +static int ripng_read(struct thread *thread) +{ + int len; + int sock; + struct sockaddr_in6 from; + struct ripng_packet *packet; + ifindex_t ifindex = 0; + struct interface *ifp; + int hoplimit = -1; + + /* Check ripng is active and alive. */ + assert(ripng != NULL); + assert(ripng->sock >= 0); + + /* Fetch thread data and set read pointer to empty for event + managing. `sock' sould be same as ripng->sock. */ + sock = THREAD_FD(thread); + ripng->t_read = NULL; + + /* Add myself to the next event. */ + ripng_event(RIPNG_READ, sock); + + /* Read RIPng packet. */ + len = ripng_recv_packet(sock, STREAM_DATA(ripng->ibuf), + STREAM_SIZE(ripng->ibuf), &from, &ifindex, + &hoplimit); + if (len < 0) { + zlog_warn("RIPng recvfrom failed: %s.", safe_strerror(errno)); + return len; + } - /* Check RTE boundary. RTE size (Packet length - RIPng header size - (4)) must be multiple size of one RTE size (20). */ - if (((len - 4) % 20) != 0) - { - zlog_warn ("RIPng invalid packet size %d from %s", len, - inet6_ntoa (from.sin6_addr)); - ripng_peer_bad_packet (&from); - return 0; - } + /* Check RTE boundary. RTE size (Packet length - RIPng header size + (4)) must be multiple size of one RTE size (20). */ + if (((len - 4) % 20) != 0) { + zlog_warn("RIPng invalid packet size %d from %s", len, + inet6_ntoa(from.sin6_addr)); + ripng_peer_bad_packet(&from); + return 0; + } - packet = (struct ripng_packet *) STREAM_DATA (ripng->ibuf); - ifp = if_lookup_by_index (ifindex, VRF_DEFAULT); + packet = (struct ripng_packet *)STREAM_DATA(ripng->ibuf); + ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); - /* RIPng packet received. */ - if (IS_RIPNG_DEBUG_EVENT) - zlog_debug ("RIPng packet received from %s port %d on %s", - inet6_ntoa (from.sin6_addr), ntohs (from.sin6_port), - ifp ? ifp->name : "unknown"); + /* RIPng packet received. */ + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug("RIPng packet received from %s port %d on %s", + inet6_ntoa(from.sin6_addr), ntohs(from.sin6_port), + ifp ? ifp->name : "unknown"); - /* Logging before packet checking. */ - if (IS_RIPNG_DEBUG_RECV) - ripng_packet_dump (packet, len, "RECV"); + /* Logging before packet checking. */ + if (IS_RIPNG_DEBUG_RECV) + ripng_packet_dump(packet, len, "RECV"); - /* Packet comes from unknown interface. */ - if (ifp == NULL) - { - zlog_warn ("RIPng packet comes from unknown interface %d", ifindex); - return 0; - } + /* Packet comes from unknown interface. */ + if (ifp == NULL) { + zlog_warn("RIPng packet comes from unknown interface %d", + ifindex); + return 0; + } - /* Packet version mismatch checking. */ - if (packet->version != ripng->version) - { - zlog_warn ("RIPng packet version %d doesn't fit to my version %d", - packet->version, ripng->version); - ripng_peer_bad_packet (&from); - return 0; - } + /* Packet version mismatch checking. */ + if (packet->version != ripng->version) { + zlog_warn( + "RIPng packet version %d doesn't fit to my version %d", + packet->version, ripng->version); + ripng_peer_bad_packet(&from); + return 0; + } - /* Process RIPng packet. */ - switch (packet->command) - { - case RIPNG_REQUEST: - ripng_request_process (packet, len, &from, ifp); - break; - case RIPNG_RESPONSE: - ripng_response_process (packet, len, &from, ifp, hoplimit); - break; - default: - zlog_warn ("Invalid RIPng command %d", packet->command); - ripng_peer_bad_packet (&from); - break; - } - return 0; + /* Process RIPng packet. */ + switch (packet->command) { + case RIPNG_REQUEST: + ripng_request_process(packet, len, &from, ifp); + break; + case RIPNG_RESPONSE: + ripng_response_process(packet, len, &from, ifp, hoplimit); + break; + default: + zlog_warn("Invalid RIPng command %d", packet->command); + ripng_peer_bad_packet(&from); + break; + } + return 0; } /* Walk down the RIPng routing table then clear changed flag. */ -static void -ripng_clear_changed_flag (void) +static void ripng_clear_changed_flag(void) { - struct route_node *rp; - struct ripng_info *rinfo = NULL; - struct list *list = NULL; - struct listnode *listnode = NULL; + struct route_node *rp; + struct ripng_info *rinfo = NULL; + struct list *list = NULL; + struct listnode *listnode = NULL; - for (rp = route_top (ripng->table); rp; rp = route_next (rp)) - if ((list = rp->info) != NULL) - for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) - { - UNSET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED); - /* This flag can be set only on the first entry. */ - break; - } + for (rp = route_top(ripng->table); rp; rp = route_next(rp)) + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { + UNSET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED); + /* This flag can be set only on the first entry. + */ + break; + } } /* Regular update of RIPng route. Send all routing formation to RIPng enabled interface. */ -static int -ripng_update (struct thread *t) +static int ripng_update(struct thread *t) { - struct listnode *node; - struct interface *ifp; - struct ripng_interface *ri; + struct listnode *node; + struct interface *ifp; + struct ripng_interface *ri; - /* Clear update timer thread. */ - ripng->t_update = NULL; + /* Clear update timer thread. */ + ripng->t_update = NULL; - /* Logging update event. */ - if (IS_RIPNG_DEBUG_EVENT) - zlog_debug ("RIPng update timer expired!"); + /* Logging update event. */ + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug("RIPng update timer expired!"); - /* Supply routes to each interface. */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - ri = ifp->info; + /* Supply routes to each interface. */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + ri = ifp->info; - if (if_is_loopback (ifp) || ! if_is_up (ifp)) - continue; + if (if_is_loopback(ifp) || !if_is_up(ifp)) + continue; - if (! ri->running) - continue; + if (!ri->running) + continue; - /* When passive interface is specified, suppress announce to the - interface. */ - if (ri->passive) - continue; + /* When passive interface is specified, suppress announce to the + interface. */ + if (ri->passive) + continue; #if RIPNG_ADVANCED - if (ri->ri_send == RIPNG_SEND_OFF) - { - if (IS_RIPNG_DEBUG_EVENT) - zlog_debug ("[Event] RIPng send to if %d is suppressed by config", - ifp->ifindex); - continue; - } + if (ri->ri_send == RIPNG_SEND_OFF) { + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug( + "[Event] RIPng send to if %d is suppressed by config", + ifp->ifindex); + continue; + } #endif /* RIPNG_ADVANCED */ - ripng_output_process (ifp, NULL, ripng_all_route); - } + ripng_output_process(ifp, NULL, ripng_all_route); + } - /* Triggered updates may be suppressed if a regular update is due by - the time the triggered update would be sent. */ - if (ripng->t_triggered_interval) - { - thread_cancel (ripng->t_triggered_interval); - ripng->t_triggered_interval = NULL; - } - ripng->trigger = 0; + /* Triggered updates may be suppressed if a regular update is due by + the time the triggered update would be sent. */ + if (ripng->t_triggered_interval) { + thread_cancel(ripng->t_triggered_interval); + ripng->t_triggered_interval = NULL; + } + ripng->trigger = 0; - /* Reset flush event. */ - ripng_event (RIPNG_UPDATE_EVENT, 0); + /* Reset flush event. */ + ripng_event(RIPNG_UPDATE_EVENT, 0); - return 0; + return 0; } /* Triggered update interval timer. */ -static int -ripng_triggered_interval (struct thread *t) +static int ripng_triggered_interval(struct thread *t) { - ripng->t_triggered_interval = NULL; + ripng->t_triggered_interval = NULL; - if (ripng->trigger) - { - ripng->trigger = 0; - ripng_triggered_update (t); - } - return 0; -} + if (ripng->trigger) { + ripng->trigger = 0; + ripng_triggered_update(t); + } + return 0; +} /* Execute triggered update. */ -int -ripng_triggered_update (struct thread *t) +int ripng_triggered_update(struct thread *t) { - struct listnode *node; - struct interface *ifp; - struct ripng_interface *ri; - int interval; + struct listnode *node; + struct interface *ifp; + struct ripng_interface *ri; + int interval; - ripng->t_triggered_update = NULL; + ripng->t_triggered_update = NULL; - /* Cancel interval timer. */ - if (ripng->t_triggered_interval) - { - thread_cancel (ripng->t_triggered_interval); - ripng->t_triggered_interval = NULL; - } - ripng->trigger = 0; + /* Cancel interval timer. */ + if (ripng->t_triggered_interval) { + thread_cancel(ripng->t_triggered_interval); + ripng->t_triggered_interval = NULL; + } + ripng->trigger = 0; - /* Logging triggered update. */ - if (IS_RIPNG_DEBUG_EVENT) - zlog_debug ("RIPng triggered update!"); + /* Logging triggered update. */ + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug("RIPng triggered update!"); - /* Split Horizon processing is done when generating triggered - updates as well as normal updates (see section 2.6). */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - ri = ifp->info; + /* Split Horizon processing is done when generating triggered + updates as well as normal updates (see section 2.6). */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + ri = ifp->info; - if (if_is_loopback (ifp) || ! if_is_up (ifp)) - continue; + if (if_is_loopback(ifp) || !if_is_up(ifp)) + continue; - if (! ri->running) - continue; + if (!ri->running) + continue; - /* When passive interface is specified, suppress announce to the - interface. */ - if (ri->passive) - continue; + /* When passive interface is specified, suppress announce to the + interface. */ + if (ri->passive) + continue; - ripng_output_process (ifp, NULL, ripng_changed_route); - } + ripng_output_process(ifp, NULL, ripng_changed_route); + } - /* Once all of the triggered updates have been generated, the route - change flags should be cleared. */ - ripng_clear_changed_flag (); + /* Once all of the triggered updates have been generated, the route + change flags should be cleared. */ + ripng_clear_changed_flag(); - /* After a triggered update is sent, a timer should be set for a - random interval between 1 and 5 seconds. If other changes that - would trigger updates occur before the timer expires, a single - update is triggered when the timer expires. */ - interval = (random () % 5) + 1; + /* After a triggered update is sent, a timer should be set for a + random interval between 1 and 5 seconds. If other changes that + would trigger updates occur before the timer expires, a single + update is triggered when the timer expires. */ + interval = (random() % 5) + 1; - ripng->t_triggered_interval = NULL; - thread_add_timer(master, ripng_triggered_interval, NULL, interval, - &ripng->t_triggered_interval); + ripng->t_triggered_interval = NULL; + thread_add_timer(master, ripng_triggered_interval, NULL, interval, + &ripng->t_triggered_interval); - return 0; + return 0; } /* Write routing table entry to the stream and return next index of the routing table entry in the stream. */ -int -ripng_write_rte (int num, struct stream *s, struct prefix_ipv6 *p, - struct in6_addr *nexthop, u_int16_t tag, u_char metric) -{ - /* RIPng packet header. */ - if (num == 0) - { - stream_putc (s, RIPNG_RESPONSE); - stream_putc (s, RIPNG_V1); - stream_putw (s, 0); - } +int ripng_write_rte(int num, struct stream *s, struct prefix_ipv6 *p, + struct in6_addr *nexthop, u_int16_t tag, u_char metric) +{ + /* RIPng packet header. */ + if (num == 0) { + stream_putc(s, RIPNG_RESPONSE); + stream_putc(s, RIPNG_V1); + stream_putw(s, 0); + } - /* Write routing table entry. */ - if (!nexthop) - stream_write (s, (u_char *) &p->prefix, sizeof (struct in6_addr)); - else - stream_write (s, (u_char *) nexthop, sizeof (struct in6_addr)); - stream_putw (s, tag); - if (p) - stream_putc (s, p->prefixlen); - else - stream_putc (s, 0); - stream_putc (s, metric); + /* Write routing table entry. */ + if (!nexthop) + stream_write(s, (u_char *)&p->prefix, sizeof(struct in6_addr)); + else + stream_write(s, (u_char *)nexthop, sizeof(struct in6_addr)); + stream_putw(s, tag); + if (p) + stream_putc(s, p->prefixlen); + else + stream_putc(s, 0); + stream_putc(s, metric); - return ++num; + return ++num; } /* Send RESPONSE message to specified destination. */ -void -ripng_output_process (struct interface *ifp, struct sockaddr_in6 *to, - int route_type) -{ - int ret; - struct route_node *rp; - struct ripng_info *rinfo; - struct ripng_interface *ri; - struct ripng_aggregate *aggregate; - struct prefix_ipv6 *p; - struct list * ripng_rte_list; - struct list *list = NULL; - struct listnode *listnode = NULL; - - if (IS_RIPNG_DEBUG_EVENT) { - if (to) - zlog_debug ("RIPng update routes to neighbor %s", - inet6_ntoa(to->sin6_addr)); - else - zlog_debug ("RIPng update routes on interface %s", ifp->name); - } - - /* Get RIPng interface. */ - ri = ifp->info; - - ripng_rte_list = ripng_rte_new(); - - for (rp = route_top (ripng->table); rp; rp = route_next (rp)) - { - if ((list = rp->info) != NULL && - (rinfo = listgetdata (listhead (list))) != NULL && - rinfo->suppress == 0) - { - /* If no route-map are applied, the RTE will be these following - * informations. - */ - p = (struct prefix_ipv6 *) &rp->p; - rinfo->metric_out = rinfo->metric; - rinfo->tag_out = rinfo->tag; - memset(&rinfo->nexthop_out, 0, sizeof(rinfo->nexthop_out)); - /* In order to avoid some local loops, - * if the RIPng route has a nexthop via this interface, keep the nexthop, - * otherwise set it to 0. The nexthop should not be propagated - * beyond the local broadcast/multicast area in order - * to avoid an IGP multi-level recursive look-up. - */ - if (rinfo->ifindex == ifp->ifindex) - rinfo->nexthop_out = rinfo->nexthop; - - /* Apply output filters. */ - ret = ripng_filter (RIPNG_FILTER_OUT, p, ri); - if (ret < 0) - continue; - - /* Changed route only output. */ - if (route_type == ripng_changed_route && - (! (rinfo->flags & RIPNG_RTF_CHANGED))) - continue; - - /* Split horizon. */ - if (ri->split_horizon == RIPNG_SPLIT_HORIZON) - { - /* We perform split horizon for RIPng routes. */ - int suppress = 0; - struct ripng_info *tmp_rinfo = NULL; - - for (ALL_LIST_ELEMENTS_RO (list, listnode, tmp_rinfo)) - if (tmp_rinfo->type == ZEBRA_ROUTE_RIPNG && - tmp_rinfo->ifindex == ifp->ifindex) - { - suppress = 1; - break; - } - if (suppress) - continue; - } - - /* Preparation for route-map. */ - rinfo->metric_set = 0; - /* nexthop_out, - * metric_out - * and tag_out are already initialized. - */ - - /* Interface route-map */ - if (ri->routemap[RIPNG_FILTER_OUT]) - { - int ret; - - ret = route_map_apply (ri->routemap[RIPNG_FILTER_OUT], - (struct prefix *) p, RMAP_RIPNG, - rinfo); - - if (ret == RMAP_DENYMATCH) - { - if (IS_RIPNG_DEBUG_PACKET) - zlog_debug ("RIPng %s/%d is filtered by route-map out", - inet6_ntoa (p->prefix), p->prefixlen); - continue; - } - - } - - /* Redistribute route-map. */ - if (ripng->route_map[rinfo->type].name) - { - int ret; - - ret = route_map_apply (ripng->route_map[rinfo->type].map, - (struct prefix *) p, RMAP_RIPNG, - rinfo); +void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to, + int route_type) +{ + int ret; + struct route_node *rp; + struct ripng_info *rinfo; + struct ripng_interface *ri; + struct ripng_aggregate *aggregate; + struct prefix_ipv6 *p; + struct list *ripng_rte_list; + struct list *list = NULL; + struct listnode *listnode = NULL; + + if (IS_RIPNG_DEBUG_EVENT) { + if (to) + zlog_debug("RIPng update routes to neighbor %s", + inet6_ntoa(to->sin6_addr)); + else + zlog_debug("RIPng update routes on interface %s", + ifp->name); + } - if (ret == RMAP_DENYMATCH) - { - if (IS_RIPNG_DEBUG_PACKET) - zlog_debug ("RIPng %s/%d is filtered by route-map", - inet6_ntoa (p->prefix), p->prefixlen); - continue; - } - } - - /* When the route-map does not set metric. */ - if (! rinfo->metric_set) - { - /* If the redistribute metric is set. */ - if (ripng->route_map[rinfo->type].metric_config - && rinfo->metric != RIPNG_METRIC_INFINITY) - { - rinfo->metric_out = ripng->route_map[rinfo->type].metric; - } - else - { - /* If the route is not connected or localy generated - one, use default-metric value */ - if (rinfo->type != ZEBRA_ROUTE_RIPNG - && rinfo->type != ZEBRA_ROUTE_CONNECT - && rinfo->metric != RIPNG_METRIC_INFINITY) - rinfo->metric_out = ripng->default_metric; + /* Get RIPng interface. */ + ri = ifp->info; + + ripng_rte_list = ripng_rte_new(); + + for (rp = route_top(ripng->table); rp; rp = route_next(rp)) { + if ((list = rp->info) != NULL + && (rinfo = listgetdata(listhead(list))) != NULL + && rinfo->suppress == 0) { + /* If no route-map are applied, the RTE will be these + * following + * informations. + */ + p = (struct prefix_ipv6 *)&rp->p; + rinfo->metric_out = rinfo->metric; + rinfo->tag_out = rinfo->tag; + memset(&rinfo->nexthop_out, 0, + sizeof(rinfo->nexthop_out)); + /* In order to avoid some local loops, + * if the RIPng route has a nexthop via this interface, + * keep the nexthop, + * otherwise set it to 0. The nexthop should not be + * propagated + * beyond the local broadcast/multicast area in order + * to avoid an IGP multi-level recursive look-up. + */ + if (rinfo->ifindex == ifp->ifindex) + rinfo->nexthop_out = rinfo->nexthop; + + /* Apply output filters. */ + ret = ripng_filter(RIPNG_FILTER_OUT, p, ri); + if (ret < 0) + continue; + + /* Changed route only output. */ + if (route_type == ripng_changed_route + && (!(rinfo->flags & RIPNG_RTF_CHANGED))) + continue; + + /* Split horizon. */ + if (ri->split_horizon == RIPNG_SPLIT_HORIZON) { + /* We perform split horizon for RIPng routes. */ + int suppress = 0; + struct ripng_info *tmp_rinfo = NULL; + + for (ALL_LIST_ELEMENTS_RO(list, listnode, + tmp_rinfo)) + if (tmp_rinfo->type == ZEBRA_ROUTE_RIPNG + && tmp_rinfo->ifindex + == ifp->ifindex) { + suppress = 1; + break; + } + if (suppress) + continue; + } + + /* Preparation for route-map. */ + rinfo->metric_set = 0; + /* nexthop_out, + * metric_out + * and tag_out are already initialized. + */ + + /* Interface route-map */ + if (ri->routemap[RIPNG_FILTER_OUT]) { + int ret; + + ret = route_map_apply( + ri->routemap[RIPNG_FILTER_OUT], + (struct prefix *)p, RMAP_RIPNG, rinfo); + + if (ret == RMAP_DENYMATCH) { + if (IS_RIPNG_DEBUG_PACKET) + zlog_debug( + "RIPng %s/%d is filtered by route-map out", + inet6_ntoa(p->prefix), + p->prefixlen); + continue; + } + } + + /* Redistribute route-map. */ + if (ripng->route_map[rinfo->type].name) { + int ret; + + ret = route_map_apply( + ripng->route_map[rinfo->type].map, + (struct prefix *)p, RMAP_RIPNG, rinfo); + + if (ret == RMAP_DENYMATCH) { + if (IS_RIPNG_DEBUG_PACKET) + zlog_debug( + "RIPng %s/%d is filtered by route-map", + inet6_ntoa(p->prefix), + p->prefixlen); + continue; + } + } + + /* When the route-map does not set metric. */ + if (!rinfo->metric_set) { + /* If the redistribute metric is set. */ + if (ripng->route_map[rinfo->type].metric_config + && rinfo->metric != RIPNG_METRIC_INFINITY) { + rinfo->metric_out = + ripng->route_map[rinfo->type] + .metric; + } else { + /* If the route is not connected or + localy generated + one, use default-metric value */ + if (rinfo->type != ZEBRA_ROUTE_RIPNG + && rinfo->type + != ZEBRA_ROUTE_CONNECT + && rinfo->metric + != RIPNG_METRIC_INFINITY) + rinfo->metric_out = + ripng->default_metric; + } + } + + /* Apply offset-list */ + if (rinfo->metric_out != RIPNG_METRIC_INFINITY) + ripng_offset_list_apply_out(p, ifp, + &rinfo->metric_out); + + if (rinfo->metric_out > RIPNG_METRIC_INFINITY) + rinfo->metric_out = RIPNG_METRIC_INFINITY; + + /* Perform split-horizon with poisoned reverse + * for RIPng routes. + **/ + if (ri->split_horizon + == RIPNG_SPLIT_HORIZON_POISONED_REVERSE) { + struct ripng_info *tmp_rinfo = NULL; + + for (ALL_LIST_ELEMENTS_RO(list, listnode, + tmp_rinfo)) + if ((tmp_rinfo->type + == ZEBRA_ROUTE_RIPNG) + && tmp_rinfo->ifindex + == ifp->ifindex) + rinfo->metric_out = + RIPNG_METRIC_INFINITY; + } + + /* Add RTE to the list */ + ripng_rte_add(ripng_rte_list, p, rinfo, NULL); } - } - - /* Apply offset-list */ - if (rinfo->metric_out != RIPNG_METRIC_INFINITY) - ripng_offset_list_apply_out (p, ifp, &rinfo->metric_out); - - if (rinfo->metric_out > RIPNG_METRIC_INFINITY) - rinfo->metric_out = RIPNG_METRIC_INFINITY; - - /* Perform split-horizon with poisoned reverse - * for RIPng routes. - **/ - if (ri->split_horizon == RIPNG_SPLIT_HORIZON_POISONED_REVERSE) { - struct ripng_info *tmp_rinfo = NULL; - - for (ALL_LIST_ELEMENTS_RO (list, listnode, tmp_rinfo)) - if ((tmp_rinfo->type == ZEBRA_ROUTE_RIPNG) && - tmp_rinfo->ifindex == ifp->ifindex) - rinfo->metric_out = RIPNG_METRIC_INFINITY; - } - - /* Add RTE to the list */ - ripng_rte_add(ripng_rte_list, p, rinfo, NULL); - } - - /* Process the aggregated RTE entry */ - if ((aggregate = rp->aggregate) != NULL && - aggregate->count > 0 && - aggregate->suppress == 0) - { - /* If no route-map are applied, the RTE will be these following - * informations. - */ - p = (struct prefix_ipv6 *) &rp->p; - aggregate->metric_set = 0; - aggregate->metric_out = aggregate->metric; - aggregate->tag_out = aggregate->tag; - memset(&aggregate->nexthop_out, 0, sizeof(aggregate->nexthop_out)); - - /* Apply output filters.*/ - ret = ripng_filter (RIPNG_FILTER_OUT, p, ri); - if (ret < 0) - continue; - - /* Interface route-map */ - if (ri->routemap[RIPNG_FILTER_OUT]) - { - int ret; - struct ripng_info newinfo; - - /* let's cast the aggregate structure to ripng_info */ - memset (&newinfo, 0, sizeof (struct ripng_info)); - /* the nexthop is :: */ - newinfo.metric = aggregate->metric; - newinfo.metric_out = aggregate->metric_out; - newinfo.tag = aggregate->tag; - newinfo.tag_out = aggregate->tag_out; - - ret = route_map_apply (ri->routemap[RIPNG_FILTER_OUT], - (struct prefix *) p, RMAP_RIPNG, - &newinfo); - - if (ret == RMAP_DENYMATCH) - { - if (IS_RIPNG_DEBUG_PACKET) - zlog_debug ("RIPng %s/%d is filtered by route-map out", - inet6_ntoa (p->prefix), p->prefixlen); - continue; - } - - aggregate->metric_out = newinfo.metric_out; - aggregate->tag_out = newinfo.tag_out; - if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop_out)) - aggregate->nexthop_out = newinfo.nexthop_out; - } - - /* There is no redistribute routemap for the aggregated RTE */ - - /* Changed route only output. */ - /* XXX, vincent, in order to increase time convergence, - * it should be announced if a child has changed. - */ - if (route_type == ripng_changed_route) - continue; - - /* Apply offset-list */ - if (aggregate->metric_out != RIPNG_METRIC_INFINITY) - ripng_offset_list_apply_out (p, ifp, &aggregate->metric_out); - - if (aggregate->metric_out > RIPNG_METRIC_INFINITY) - aggregate->metric_out = RIPNG_METRIC_INFINITY; - /* Add RTE to the list */ - ripng_rte_add(ripng_rte_list, p, NULL, aggregate); + /* Process the aggregated RTE entry */ + if ((aggregate = rp->aggregate) != NULL && aggregate->count > 0 + && aggregate->suppress == 0) { + /* If no route-map are applied, the RTE will be these + * following + * informations. + */ + p = (struct prefix_ipv6 *)&rp->p; + aggregate->metric_set = 0; + aggregate->metric_out = aggregate->metric; + aggregate->tag_out = aggregate->tag; + memset(&aggregate->nexthop_out, 0, + sizeof(aggregate->nexthop_out)); + + /* Apply output filters.*/ + ret = ripng_filter(RIPNG_FILTER_OUT, p, ri); + if (ret < 0) + continue; + + /* Interface route-map */ + if (ri->routemap[RIPNG_FILTER_OUT]) { + int ret; + struct ripng_info newinfo; + + /* let's cast the aggregate structure to + * ripng_info */ + memset(&newinfo, 0, sizeof(struct ripng_info)); + /* the nexthop is :: */ + newinfo.metric = aggregate->metric; + newinfo.metric_out = aggregate->metric_out; + newinfo.tag = aggregate->tag; + newinfo.tag_out = aggregate->tag_out; + + ret = route_map_apply( + ri->routemap[RIPNG_FILTER_OUT], + (struct prefix *)p, RMAP_RIPNG, + &newinfo); + + if (ret == RMAP_DENYMATCH) { + if (IS_RIPNG_DEBUG_PACKET) + zlog_debug( + "RIPng %s/%d is filtered by route-map out", + inet6_ntoa(p->prefix), + p->prefixlen); + continue; + } + + aggregate->metric_out = newinfo.metric_out; + aggregate->tag_out = newinfo.tag_out; + if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop_out)) + aggregate->nexthop_out = + newinfo.nexthop_out; + } + + /* There is no redistribute routemap for the aggregated + * RTE */ + + /* Changed route only output. */ + /* XXX, vincent, in order to increase time convergence, + * it should be announced if a child has changed. + */ + if (route_type == ripng_changed_route) + continue; + + /* Apply offset-list */ + if (aggregate->metric_out != RIPNG_METRIC_INFINITY) + ripng_offset_list_apply_out( + p, ifp, &aggregate->metric_out); + + if (aggregate->metric_out > RIPNG_METRIC_INFINITY) + aggregate->metric_out = RIPNG_METRIC_INFINITY; + + /* Add RTE to the list */ + ripng_rte_add(ripng_rte_list, p, NULL, aggregate); + } } - } - - /* Flush the list */ - ripng_rte_send(ripng_rte_list, ifp, to); - ripng_rte_free(ripng_rte_list); + /* Flush the list */ + ripng_rte_send(ripng_rte_list, ifp, to); + ripng_rte_free(ripng_rte_list); } /* Create new RIPng instance and set it to global variable. */ -static int -ripng_create (void) +static int ripng_create(void) { - /* ripng should be NULL. */ - assert (ripng == NULL); + /* ripng should be NULL. */ + assert(ripng == NULL); - /* Allocaste RIPng instance. */ - ripng = XCALLOC (MTYPE_RIPNG, sizeof (struct ripng)); + /* Allocaste RIPng instance. */ + ripng = XCALLOC(MTYPE_RIPNG, sizeof(struct ripng)); - /* Default version and timer values. */ - ripng->version = RIPNG_V1; - ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT; - ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT; - ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT; - ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT; - - /* Make buffer. */ - ripng->ibuf = stream_new (RIPNG_MAX_PACKET_SIZE * 5); - ripng->obuf = stream_new (RIPNG_MAX_PACKET_SIZE); + /* Default version and timer values. */ + ripng->version = RIPNG_V1; + ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT; + ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT; + ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT; + ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT; + + /* Make buffer. */ + ripng->ibuf = stream_new(RIPNG_MAX_PACKET_SIZE * 5); + ripng->obuf = stream_new(RIPNG_MAX_PACKET_SIZE); + + /* Initialize RIPng routig table. */ + ripng->table = route_table_init(); + ripng->route = route_table_init(); + ripng->aggregate = route_table_init(); - /* Initialize RIPng routig table. */ - ripng->table = route_table_init (); - ripng->route = route_table_init (); - ripng->aggregate = route_table_init (); - - /* Make socket. */ - ripng->sock = ripng_make_socket (); - if (ripng->sock < 0) - return ripng->sock; + /* Make socket. */ + ripng->sock = ripng_make_socket(); + if (ripng->sock < 0) + return ripng->sock; - /* Threads. */ - ripng_event (RIPNG_READ, ripng->sock); - ripng_event (RIPNG_UPDATE_EVENT, 1); + /* Threads. */ + ripng_event(RIPNG_READ, ripng->sock); + ripng_event(RIPNG_UPDATE_EVENT, 1); - return 0; + return 0; } /* Send RIPng request to the interface. */ -int -ripng_request (struct interface *ifp) +int ripng_request(struct interface *ifp) { - struct rte *rte; - struct ripng_packet ripng_packet; + struct rte *rte; + struct ripng_packet ripng_packet; - /* In default ripd doesn't send RIP_REQUEST to the loopback interface. */ - if (if_is_loopback(ifp)) - return 0; + /* In default ripd doesn't send RIP_REQUEST to the loopback interface. + */ + if (if_is_loopback(ifp)) + return 0; - /* If interface is down, don't send RIP packet. */ - if (! if_is_up (ifp)) - return 0; + /* If interface is down, don't send RIP packet. */ + if (!if_is_up(ifp)) + return 0; - if (IS_RIPNG_DEBUG_EVENT) - zlog_debug ("RIPng send request to %s", ifp->name); + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug("RIPng send request to %s", ifp->name); - memset (&ripng_packet, 0, sizeof (ripng_packet)); - ripng_packet.command = RIPNG_REQUEST; - ripng_packet.version = RIPNG_V1; - rte = ripng_packet.rte; - rte->metric = RIPNG_METRIC_INFINITY; + memset(&ripng_packet, 0, sizeof(ripng_packet)); + ripng_packet.command = RIPNG_REQUEST; + ripng_packet.version = RIPNG_V1; + rte = ripng_packet.rte; + rte->metric = RIPNG_METRIC_INFINITY; - return ripng_send_packet ((caddr_t) &ripng_packet, sizeof (ripng_packet), - NULL, ifp); + return ripng_send_packet((caddr_t)&ripng_packet, sizeof(ripng_packet), + NULL, ifp); } -static int -ripng_update_jitter (int time) +static int ripng_update_jitter(int time) { - return ((random () % (time + 1)) - (time / 2)); + return ((random() % (time + 1)) - (time / 2)); } -void -ripng_event (enum ripng_event event, int sock) +void ripng_event(enum ripng_event event, int sock) { - int jitter = 0; + int jitter = 0; - switch (event) - { - case RIPNG_READ: - thread_add_read(master, ripng_read, NULL, sock, &ripng->t_read); - break; - case RIPNG_UPDATE_EVENT: - if (ripng->t_update) - { - thread_cancel (ripng->t_update); - ripng->t_update = NULL; - } - /* Update timer jitter. */ - jitter = ripng_update_jitter (ripng->update_time); - - ripng->t_update = NULL; - thread_add_timer(master, ripng_update, NULL, sock ? 2 : ripng->update_time + jitter, - &ripng->t_update); - break; - case RIPNG_TRIGGERED_UPDATE: - if (ripng->t_triggered_interval) - ripng->trigger = 1; - else thread_add_event(master, ripng_triggered_update, NULL, 0, - &ripng->t_triggered_update); - break; - default: - break; - } + switch (event) { + case RIPNG_READ: + thread_add_read(master, ripng_read, NULL, sock, &ripng->t_read); + break; + case RIPNG_UPDATE_EVENT: + if (ripng->t_update) { + thread_cancel(ripng->t_update); + ripng->t_update = NULL; + } + /* Update timer jitter. */ + jitter = ripng_update_jitter(ripng->update_time); + + ripng->t_update = NULL; + thread_add_timer(master, ripng_update, NULL, + sock ? 2 : ripng->update_time + jitter, + &ripng->t_update); + break; + case RIPNG_TRIGGERED_UPDATE: + if (ripng->t_triggered_interval) + ripng->trigger = 1; + else + thread_add_event(master, ripng_triggered_update, NULL, + 0, &ripng->t_triggered_update); + break; + default: + break; + } } /* Print out routes update time. */ -static void -ripng_vty_out_uptime (struct vty *vty, struct ripng_info *rinfo) +static void ripng_vty_out_uptime(struct vty *vty, struct ripng_info *rinfo) { - time_t clock; - struct tm *tm; + time_t clock; + struct tm *tm; #define TIME_BUF 25 - char timebuf [TIME_BUF]; - struct thread *thread; - - if ((thread = rinfo->t_timeout) != NULL) - { - clock = thread_timer_remain_second (thread); - tm = gmtime (&clock); - strftime (timebuf, TIME_BUF, "%M:%S", tm); - vty_out (vty, "%5s", timebuf); - } - else if ((thread = rinfo->t_garbage_collect) != NULL) - { - clock = thread_timer_remain_second (thread); - tm = gmtime (&clock); - strftime (timebuf, TIME_BUF, "%M:%S", tm); - vty_out (vty, "%5s", timebuf); - } + char timebuf[TIME_BUF]; + struct thread *thread; + + if ((thread = rinfo->t_timeout) != NULL) { + clock = thread_timer_remain_second(thread); + tm = gmtime(&clock); + strftime(timebuf, TIME_BUF, "%M:%S", tm); + vty_out(vty, "%5s", timebuf); + } else if ((thread = rinfo->t_garbage_collect) != NULL) { + clock = thread_timer_remain_second(thread); + tm = gmtime(&clock); + strftime(timebuf, TIME_BUF, "%M:%S", tm); + vty_out(vty, "%5s", timebuf); + } } -static char * -ripng_route_subtype_print (struct ripng_info *rinfo) -{ - static char str[3]; - memset(str, 0, 3); - - if (rinfo->suppress) - strcat(str, "S"); +static char *ripng_route_subtype_print(struct ripng_info *rinfo) +{ + static char str[3]; + memset(str, 0, 3); + + if (rinfo->suppress) + strcat(str, "S"); + + switch (rinfo->sub_type) { + case RIPNG_ROUTE_RTE: + strcat(str, "n"); + break; + case RIPNG_ROUTE_STATIC: + strcat(str, "s"); + break; + case RIPNG_ROUTE_DEFAULT: + strcat(str, "d"); + break; + case RIPNG_ROUTE_REDISTRIBUTE: + strcat(str, "r"); + break; + case RIPNG_ROUTE_INTERFACE: + strcat(str, "i"); + break; + default: + strcat(str, "?"); + break; + } - switch (rinfo->sub_type) - { - case RIPNG_ROUTE_RTE: - strcat(str, "n"); - break; - case RIPNG_ROUTE_STATIC: - strcat(str, "s"); - break; - case RIPNG_ROUTE_DEFAULT: - strcat(str, "d"); - break; - case RIPNG_ROUTE_REDISTRIBUTE: - strcat(str, "r"); - break; - case RIPNG_ROUTE_INTERFACE: - strcat(str, "i"); - break; - default: - strcat(str, "?"); - break; - } - - return str; + return str; } DEFUN (show_ipv6_ripng, @@ -1992,106 +1947,106 @@ DEFUN (show_ipv6_ripng, IPV6_STR "Show RIPng routes\n") { - struct route_node *rp; - struct ripng_info *rinfo; - struct ripng_aggregate *aggregate; - struct prefix_ipv6 *p; - struct list *list = NULL; - struct listnode *listnode = NULL; - int len; - - if (! ripng) - return CMD_SUCCESS; - - /* Header of display. */ - vty_out (vty, "Codes: R - RIPng, C - connected, S - Static, O - OSPF, B - BGP\n" - "Sub-codes:\n" - " (n) - normal, (s) - static, (d) - default, (r) - redistribute,\n" - " (i) - interface, (a/S) - aggregated/Suppressed\n\n" - " Network Next Hop Via Metric Tag Time\n"); - - for (rp = route_top (ripng->table); rp; rp = route_next (rp)) - { - if ((aggregate = rp->aggregate) != NULL) - { - p = (struct prefix_ipv6 *) &rp->p; + struct route_node *rp; + struct ripng_info *rinfo; + struct ripng_aggregate *aggregate; + struct prefix_ipv6 *p; + struct list *list = NULL; + struct listnode *listnode = NULL; + int len; + + if (!ripng) + return CMD_SUCCESS; + + /* Header of display. */ + vty_out(vty, + "Codes: R - RIPng, C - connected, S - Static, O - OSPF, B - BGP\n" + "Sub-codes:\n" + " (n) - normal, (s) - static, (d) - default, (r) - redistribute,\n" + " (i) - interface, (a/S) - aggregated/Suppressed\n\n" + " Network Next Hop Via Metric Tag Time\n"); + + for (rp = route_top(ripng->table); rp; rp = route_next(rp)) { + if ((aggregate = rp->aggregate) != NULL) { + p = (struct prefix_ipv6 *)&rp->p; #ifdef DEBUG - vty_out (vty, "R(a) %d/%d %s/%d ", - aggregate->count, aggregate->suppress, - inet6_ntoa (p->prefix), p->prefixlen); + vty_out(vty, "R(a) %d/%d %s/%d ", aggregate->count, + aggregate->suppress, inet6_ntoa(p->prefix), + p->prefixlen); #else - vty_out (vty, "R(a) %s/%d ", - inet6_ntoa (p->prefix), p->prefixlen); + vty_out(vty, "R(a) %s/%d ", inet6_ntoa(p->prefix), + p->prefixlen); #endif /* DEBUG */ - vty_out (vty, "\n"); - vty_out (vty, "%*s", 18, " "); + vty_out(vty, "\n"); + vty_out(vty, "%*s", 18, " "); - vty_out (vty, "%*s", 28, " "); - vty_out (vty, "self %2d %3"ROUTE_TAG_PRI"\n", aggregate->metric, - (route_tag_t)aggregate->tag); - } + vty_out(vty, "%*s", 28, " "); + vty_out(vty, "self %2d %3" ROUTE_TAG_PRI "\n", + aggregate->metric, (route_tag_t)aggregate->tag); + } - if ((list = rp->info) != NULL) - for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) - { - p = (struct prefix_ipv6 *) &rp->p; + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { + p = (struct prefix_ipv6 *)&rp->p; #ifdef DEBUG - vty_out (vty, "%c(%s) 0/%d %s/%d ", - zebra_route_char(rinfo->type), - ripng_route_subtype_print(rinfo), - rinfo->suppress, - inet6_ntoa (p->prefix), p->prefixlen); + vty_out(vty, "%c(%s) 0/%d %s/%d ", + zebra_route_char(rinfo->type), + ripng_route_subtype_print(rinfo), + rinfo->suppress, inet6_ntoa(p->prefix), + p->prefixlen); #else - vty_out (vty, "%c(%s) %s/%d ", - zebra_route_char(rinfo->type), - ripng_route_subtype_print(rinfo), - inet6_ntoa (p->prefix), p->prefixlen); + vty_out(vty, "%c(%s) %s/%d ", + zebra_route_char(rinfo->type), + ripng_route_subtype_print(rinfo), + inet6_ntoa(p->prefix), p->prefixlen); #endif /* DEBUG */ - vty_out (vty, "\n"); - vty_out (vty, "%*s", 18, " "); - len = vty_out (vty, "%s", inet6_ntoa (rinfo->nexthop)); - - len = 28 - len; - if (len > 0) - len = vty_out (vty, "%*s", len, " "); - - /* from */ - if ((rinfo->type == ZEBRA_ROUTE_RIPNG) && - (rinfo->sub_type == RIPNG_ROUTE_RTE)) - { - len = vty_out (vty, "%s", ifindex2ifname(rinfo->ifindex, VRF_DEFAULT)); - } else if (rinfo->metric == RIPNG_METRIC_INFINITY) - { - len = vty_out (vty, "kill"); - } else - len = vty_out (vty, "self"); - - len = 9 - len; - if (len > 0) - vty_out (vty, "%*s", len, " "); - - vty_out (vty, " %2d %3"ROUTE_TAG_PRI" ", - rinfo->metric, (route_tag_t)rinfo->tag); - - /* time */ - if ((rinfo->type == ZEBRA_ROUTE_RIPNG) && - (rinfo->sub_type == RIPNG_ROUTE_RTE)) - { - /* RTE from remote RIP routers */ - ripng_vty_out_uptime (vty, rinfo); - } else if (rinfo->metric == RIPNG_METRIC_INFINITY) - { - /* poisonous reversed routes (gc) */ - ripng_vty_out_uptime (vty, rinfo); - } - - vty_out (vty, "\n"); + vty_out(vty, "\n"); + vty_out(vty, "%*s", 18, " "); + len = vty_out(vty, "%s", + inet6_ntoa(rinfo->nexthop)); + + len = 28 - len; + if (len > 0) + len = vty_out(vty, "%*s", len, " "); + + /* from */ + if ((rinfo->type == ZEBRA_ROUTE_RIPNG) + && (rinfo->sub_type == RIPNG_ROUTE_RTE)) { + len = vty_out( + vty, "%s", + ifindex2ifname(rinfo->ifindex, + VRF_DEFAULT)); + } else if (rinfo->metric + == RIPNG_METRIC_INFINITY) { + len = vty_out(vty, "kill"); + } else + len = vty_out(vty, "self"); + + len = 9 - len; + if (len > 0) + vty_out(vty, "%*s", len, " "); + + vty_out(vty, " %2d %3" ROUTE_TAG_PRI " ", + rinfo->metric, (route_tag_t)rinfo->tag); + + /* time */ + if ((rinfo->type == ZEBRA_ROUTE_RIPNG) + && (rinfo->sub_type == RIPNG_ROUTE_RTE)) { + /* RTE from remote RIP routers */ + ripng_vty_out_uptime(vty, rinfo); + } else if (rinfo->metric + == RIPNG_METRIC_INFINITY) { + /* poisonous reversed routes (gc) */ + ripng_vty_out_uptime(vty, rinfo); + } + + vty_out(vty, "\n"); + } } - } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ipv6_ripng_status, @@ -2102,61 +2057,60 @@ DEFUN (show_ipv6_ripng_status, "Show RIPng routes\n" "IPv6 routing protocol process parameters and statistics\n") { - struct listnode *node; - struct interface *ifp; + struct listnode *node; + struct interface *ifp; - if (! ripng) - return CMD_SUCCESS; + if (!ripng) + return CMD_SUCCESS; - vty_out (vty, "Routing Protocol is \"RIPng\"\n"); - vty_out (vty, " Sending updates every %ld seconds with +/-50%%,", - ripng->update_time); - vty_out (vty, " next due in %lu seconds\n", - thread_timer_remain_second(ripng->t_update)); - vty_out (vty, " Timeout after %ld seconds,", ripng->timeout_time); - vty_out (vty, " garbage collect after %ld seconds\n",ripng->garbage_time); + vty_out(vty, "Routing Protocol is \"RIPng\"\n"); + vty_out(vty, " Sending updates every %ld seconds with +/-50%%,", + ripng->update_time); + vty_out(vty, " next due in %lu seconds\n", + thread_timer_remain_second(ripng->t_update)); + vty_out(vty, " Timeout after %ld seconds,", ripng->timeout_time); + vty_out(vty, " garbage collect after %ld seconds\n", + ripng->garbage_time); - /* Filtering status show. */ - config_show_distribute (vty); + /* Filtering status show. */ + config_show_distribute(vty); - /* Default metric information. */ - vty_out (vty, " Default redistribution metric is %d\n", - ripng->default_metric); + /* Default metric information. */ + vty_out(vty, " Default redistribution metric is %d\n", + ripng->default_metric); - /* Redistribute information. */ - vty_out (vty, " Redistributing:"); - ripng_redistribute_write (vty, 0); - vty_out (vty, "\n"); + /* Redistribute information. */ + vty_out(vty, " Redistributing:"); + ripng_redistribute_write(vty, 0); + vty_out(vty, "\n"); - vty_out (vty, " Default version control: send version %d,", ripng->version); - vty_out (vty, " receive version %d \n",ripng->version); + vty_out(vty, " Default version control: send version %d,", + ripng->version); + vty_out(vty, " receive version %d \n", ripng->version); - vty_out (vty, " Interface Send Recv\n"); + vty_out(vty, " Interface Send Recv\n"); - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - struct ripng_interface *ri; - - ri = ifp->info; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + struct ripng_interface *ri; + + ri = ifp->info; - if (ri->enable_network || ri->enable_interface) - { + if (ri->enable_network || ri->enable_interface) { - vty_out (vty, " %-17s%-3d %-3d\n", ifp->name, - ripng->version, - ripng->version); + vty_out(vty, " %-17s%-3d %-3d\n", ifp->name, + ripng->version, ripng->version); + } } - } - vty_out (vty, " Routing for Networks:\n"); - ripng_network_write (vty, 0); + vty_out(vty, " Routing for Networks:\n"); + ripng_network_write(vty, 0); - vty_out (vty, " Routing Information Sources:\n"); - vty_out (vty, - " Gateway BadPackets BadRoutes Distance Last Update\n"); - ripng_peer_display (vty); + vty_out(vty, " Routing Information Sources:\n"); + vty_out(vty, + " Gateway BadPackets BadRoutes Distance Last Update\n"); + ripng_peer_display(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (clear_ipv6_rip, @@ -2166,45 +2120,41 @@ DEFUN (clear_ipv6_rip, IPV6_STR "Clear IPv6 RIP database\n") { - struct route_node *rp; - struct ripng_info *rinfo; - struct list *list; - struct listnode *listnode; + struct route_node *rp; + struct ripng_info *rinfo; + struct list *list; + struct listnode *listnode; - /* Clear received RIPng routes */ - for (rp = route_top (ripng->table); rp; rp = route_next (rp)) - { - list = rp->info; - if (list == NULL) - continue; + /* Clear received RIPng routes */ + for (rp = route_top(ripng->table); rp; rp = route_next(rp)) { + list = rp->info; + if (list == NULL) + continue; - for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) - { - if (! ripng_route_rte (rinfo)) - continue; + for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { + if (!ripng_route_rte(rinfo)) + continue; - if (CHECK_FLAG (rinfo->flags, RIPNG_RTF_FIB)) - ripng_zebra_ipv6_delete (rp); - break; - } + if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB)) + ripng_zebra_ipv6_delete(rp); + break; + } - if (rinfo) - { - RIPNG_TIMER_OFF (rinfo->t_timeout); - RIPNG_TIMER_OFF (rinfo->t_garbage_collect); - listnode_delete (list, rinfo); - ripng_info_free (rinfo); - } + if (rinfo) { + RIPNG_TIMER_OFF(rinfo->t_timeout); + RIPNG_TIMER_OFF(rinfo->t_garbage_collect); + listnode_delete(list, rinfo); + ripng_info_free(rinfo); + } - if (list_isempty (list)) - { - list_free (list); - rp->info = NULL; - route_unlock_node (rp); + if (list_isempty(list)) { + list_free(list); + rp->info = NULL; + route_unlock_node(rp); + } } - } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_NOSH (router_ripng, @@ -2213,23 +2163,21 @@ DEFUN_NOSH (router_ripng, "Enable a routing process\n" "Make RIPng instance command\n") { - int ret; + int ret; - vty->node = RIPNG_NODE; + vty->node = RIPNG_NODE; - if (!ripng) - { - ret = ripng_create (); + if (!ripng) { + ret = ripng_create(); - /* Notice to user we couldn't create RIPng. */ - if (ret < 0) - { - zlog_warn ("can't create RIPng"); - return CMD_WARNING_CONFIG_FAILED; + /* Notice to user we couldn't create RIPng. */ + if (ret < 0) { + zlog_warn("can't create RIPng"); + return CMD_WARNING_CONFIG_FAILED; + } } - } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_router_ripng, @@ -2239,9 +2187,9 @@ DEFUN (no_router_ripng, "Enable a routing process\n" "Make RIPng instance command\n") { - if(ripng) - ripng_clean(); - return CMD_SUCCESS; + if (ripng) + ripng_clean(); + return CMD_SUCCESS; } DEFUN (ripng_route, @@ -2250,31 +2198,31 @@ DEFUN (ripng_route, "Static route setup\n" "Set static RIPng route announcement\n") { - int idx_ipv6addr = 1; - int ret; - struct prefix_ipv6 p; - struct route_node *rp; + int idx_ipv6addr = 1; + int ret; + struct prefix_ipv6 p; + struct route_node *rp; - ret = str2prefix_ipv6 (argv[idx_ipv6addr]->arg, (struct prefix_ipv6 *)&p); - if (ret <= 0) - { - vty_out (vty, "Malformed address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - apply_mask_ipv6 (&p); + ret = str2prefix_ipv6(argv[idx_ipv6addr]->arg, + (struct prefix_ipv6 *)&p); + if (ret <= 0) { + vty_out(vty, "Malformed address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + apply_mask_ipv6(&p); - rp = route_node_get (ripng->route, (struct prefix *) &p); - if (rp->info) - { - vty_out (vty, "There is already same static route.\n"); - route_unlock_node (rp); - return CMD_WARNING_CONFIG_FAILED; - } - rp->info = (void *)1; + rp = route_node_get(ripng->route, (struct prefix *)&p); + if (rp->info) { + vty_out(vty, "There is already same static route.\n"); + route_unlock_node(rp); + return CMD_WARNING_CONFIG_FAILED; + } + rp->info = (void *)1; - ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0, NULL, 0); + ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0, + NULL, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ripng_route, @@ -2284,33 +2232,32 @@ DEFUN (no_ripng_route, "Static route setup\n" "Delete static RIPng route announcement\n") { - int idx_ipv6addr = 2; - int ret; - struct prefix_ipv6 p; - struct route_node *rp; + int idx_ipv6addr = 2; + int ret; + struct prefix_ipv6 p; + struct route_node *rp; - ret = str2prefix_ipv6 (argv[idx_ipv6addr]->arg, (struct prefix_ipv6 *)&p); - if (ret <= 0) - { - vty_out (vty, "Malformed address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - apply_mask_ipv6 (&p); + ret = str2prefix_ipv6(argv[idx_ipv6addr]->arg, + (struct prefix_ipv6 *)&p); + if (ret <= 0) { + vty_out(vty, "Malformed address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + apply_mask_ipv6(&p); - rp = route_node_lookup (ripng->route, (struct prefix *) &p); - if (! rp) - { - vty_out (vty, "Can't find static route.\n"); - return CMD_WARNING_CONFIG_FAILED; - } + rp = route_node_lookup(ripng->route, (struct prefix *)&p); + if (!rp) { + vty_out(vty, "Can't find static route.\n"); + return CMD_WARNING_CONFIG_FAILED; + } - ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0); - route_unlock_node (rp); + ripng_redistribute_delete(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0); + route_unlock_node(rp); - rp->info = NULL; - route_unlock_node (rp); + rp->info = NULL; + route_unlock_node(rp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ripng_aggregate_address, @@ -2319,31 +2266,30 @@ DEFUN (ripng_aggregate_address, "Set aggregate RIPng route announcement\n" "Aggregate network\n") { - int idx_ipv6_prefixlen = 1; - int ret; - struct prefix p; - struct route_node *node; + int idx_ipv6_prefixlen = 1; + int ret; + struct prefix p; + struct route_node *node; - ret = str2prefix_ipv6 (argv[idx_ipv6_prefixlen]->arg, (struct prefix_ipv6 *)&p); - if (ret <= 0) - { - vty_out (vty, "Malformed address\n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = str2prefix_ipv6(argv[idx_ipv6_prefixlen]->arg, + (struct prefix_ipv6 *)&p); + if (ret <= 0) { + vty_out(vty, "Malformed address\n"); + return CMD_WARNING_CONFIG_FAILED; + } - /* Check aggregate alredy exist or not. */ - node = route_node_get (ripng->aggregate, &p); - if (node->info) - { - vty_out (vty, "There is already same aggregate route.\n"); - route_unlock_node (node); - return CMD_WARNING_CONFIG_FAILED; - } - node->info = (void *)1; + /* Check aggregate alredy exist or not. */ + node = route_node_get(ripng->aggregate, &p); + if (node->info) { + vty_out(vty, "There is already same aggregate route.\n"); + route_unlock_node(node); + return CMD_WARNING_CONFIG_FAILED; + } + node->info = (void *)1; - ripng_aggregate_add (&p); + ripng_aggregate_add(&p); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ripng_aggregate_address, @@ -2353,31 +2299,30 @@ DEFUN (no_ripng_aggregate_address, "Delete aggregate RIPng route announcement\n" "Aggregate network\n") { - int idx_ipv6_prefixlen = 2; - int ret; - struct prefix p; - struct route_node *rn; + int idx_ipv6_prefixlen = 2; + int ret; + struct prefix p; + struct route_node *rn; - ret = str2prefix_ipv6 (argv[idx_ipv6_prefixlen]->arg, (struct prefix_ipv6 *) &p); - if (ret <= 0) - { - vty_out (vty, "Malformed address\n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = str2prefix_ipv6(argv[idx_ipv6_prefixlen]->arg, + (struct prefix_ipv6 *)&p); + if (ret <= 0) { + vty_out(vty, "Malformed address\n"); + return CMD_WARNING_CONFIG_FAILED; + } - rn = route_node_lookup (ripng->aggregate, &p); - if (! rn) - { - vty_out (vty, "Can't find aggregate route.\n"); - return CMD_WARNING_CONFIG_FAILED; - } - route_unlock_node (rn); - rn->info = NULL; - route_unlock_node (rn); + rn = route_node_lookup(ripng->aggregate, &p); + if (!rn) { + vty_out(vty, "Can't find aggregate route.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + route_unlock_node(rn); + rn->info = NULL; + route_unlock_node(rn); - ripng_aggregate_delete (&p); + ripng_aggregate_delete(&p); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ripng_default_metric, @@ -2386,12 +2331,11 @@ DEFUN (ripng_default_metric, "Set a metric of redistribute routes\n" "Default metric\n") { - int idx_number = 1; - if (ripng) - { - ripng->default_metric = atoi (argv[idx_number]->arg); - } - return CMD_SUCCESS; + int idx_number = 1; + if (ripng) { + ripng->default_metric = atoi(argv[idx_number]->arg); + } + return CMD_SUCCESS; } DEFUN (no_ripng_default_metric, @@ -2401,11 +2345,10 @@ DEFUN (no_ripng_default_metric, "Set a metric of redistribute routes\n" "Default metric\n") { - if (ripng) - { - ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT; - } - return CMD_SUCCESS; + if (ripng) { + ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT; + } + return CMD_SUCCESS; } @@ -2521,26 +2464,26 @@ DEFUN (ripng_timers, "Routing information timeout timer. Default is 180.\n" "Garbage collection timer. Default is 120.\n") { - int idx_number = 2; - int idx_number_2 = 3; - int idx_number_3 = 4; - unsigned long update; - unsigned long timeout; - unsigned long garbage; + int idx_number = 2; + int idx_number_2 = 3; + int idx_number_3 = 4; + unsigned long update; + unsigned long timeout; + unsigned long garbage; - update = strtoul(argv[idx_number]->arg, NULL, 10); - timeout = strtoul(argv[idx_number_2]->arg, NULL, 10); - garbage = strtoul(argv[idx_number_3]->arg, NULL, 10); + update = strtoul(argv[idx_number]->arg, NULL, 10); + timeout = strtoul(argv[idx_number_2]->arg, NULL, 10); + garbage = strtoul(argv[idx_number_3]->arg, NULL, 10); - /* Set each timer value. */ - ripng->update_time = update; - ripng->timeout_time = timeout; - ripng->garbage_time = garbage; + /* Set each timer value. */ + ripng->update_time = update; + ripng->timeout_time = timeout; + ripng->garbage_time = garbage; - /* Reset update timer thread. */ - ripng_event (RIPNG_UPDATE_EVENT, 0); + /* Reset update timer thread. */ + ripng_event(RIPNG_UPDATE_EVENT, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ripng_timers, @@ -2553,15 +2496,15 @@ DEFUN (no_ripng_timers, "Routing information timeout timer. Default is 180.\n" "Garbage collection timer. Default is 120.\n") { - /* Set each timer value to the default. */ - ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT; - ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT; - ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT; + /* Set each timer value to the default. */ + ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT; + ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT; + ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT; - /* Reset update timer thread. */ - ripng_event (RIPNG_UPDATE_EVENT, 0); + /* Reset update timer thread. */ + ripng_event(RIPNG_UPDATE_EVENT, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } #if 0 @@ -2598,16 +2541,17 @@ DEFUN (ripng_default_information_originate, "Default route information\n" "Distribute default route\n") { - struct prefix_ipv6 p; + struct prefix_ipv6 p; - if (! ripng ->default_information) { - ripng->default_information = 1; + if (!ripng->default_information) { + ripng->default_information = 1; - str2prefix_ipv6 ("::/0", &p); - ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0, NULL, 0); - } + str2prefix_ipv6("::/0", &p); + ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, + &p, 0, NULL, 0); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ripng_default_information_originate, @@ -2617,56 +2561,55 @@ DEFUN (no_ripng_default_information_originate, "Default route information\n" "Distribute default route\n") { - struct prefix_ipv6 p; + struct prefix_ipv6 p; - if (ripng->default_information) { - ripng->default_information = 0; + if (ripng->default_information) { + ripng->default_information = 0; - str2prefix_ipv6 ("::/0", &p); - ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0); - } + str2prefix_ipv6("::/0", &p); + ripng_redistribute_delete(ZEBRA_ROUTE_RIPNG, + RIPNG_ROUTE_DEFAULT, &p, 0); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Update ECMP routes to zebra when ECMP is disabled. */ -static void -ripng_ecmp_disable (void) -{ - struct route_node *rp; - struct ripng_info *rinfo, *tmp_rinfo; - struct list *list; - struct listnode *node, *nextnode; - - if (!ripng) - return; - - for (rp = route_top (ripng->table); rp; rp = route_next (rp)) - if ((list = rp->info) != NULL && listcount (list) > 1) - { - rinfo = listgetdata (listhead (list)); - if (!ripng_route_rte (rinfo)) - continue; - - /* Drop all other entries, except the first one. */ - for (ALL_LIST_ELEMENTS (list, node, nextnode, tmp_rinfo)) - if (tmp_rinfo != rinfo) - { - RIPNG_TIMER_OFF (tmp_rinfo->t_timeout); - RIPNG_TIMER_OFF (tmp_rinfo->t_garbage_collect); - list_delete_node (list, node); - ripng_info_free (tmp_rinfo); - } - - /* Update zebra. */ - ripng_zebra_ipv6_add (rp); - - /* Set the route change flag. */ - SET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED); - - /* Signal the output process to trigger an update. */ - ripng_event (RIPNG_TRIGGERED_UPDATE, 0); - } +static void ripng_ecmp_disable(void) +{ + struct route_node *rp; + struct ripng_info *rinfo, *tmp_rinfo; + struct list *list; + struct listnode *node, *nextnode; + + if (!ripng) + return; + + for (rp = route_top(ripng->table); rp; rp = route_next(rp)) + if ((list = rp->info) != NULL && listcount(list) > 1) { + rinfo = listgetdata(listhead(list)); + if (!ripng_route_rte(rinfo)) + continue; + + /* Drop all other entries, except the first one. */ + for (ALL_LIST_ELEMENTS(list, node, nextnode, tmp_rinfo)) + if (tmp_rinfo != rinfo) { + RIPNG_TIMER_OFF(tmp_rinfo->t_timeout); + RIPNG_TIMER_OFF( + tmp_rinfo->t_garbage_collect); + list_delete_node(list, node); + ripng_info_free(tmp_rinfo); + } + + /* Update zebra. */ + ripng_zebra_ipv6_add(rp); + + /* Set the route change flag. */ + SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED); + + /* Signal the output process to trigger an update. */ + ripng_event(RIPNG_TRIGGERED_UPDATE, 0); + } } DEFUN (ripng_allow_ecmp, @@ -2674,15 +2617,14 @@ DEFUN (ripng_allow_ecmp, "allow-ecmp", "Allow Equal Cost MultiPath\n") { - if (ripng->ecmp) - { - vty_out (vty, "ECMP is already enabled.\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (ripng->ecmp) { + vty_out(vty, "ECMP is already enabled.\n"); + return CMD_WARNING_CONFIG_FAILED; + } - ripng->ecmp = 1; - zlog_info ("ECMP is enabled."); - return CMD_SUCCESS; + ripng->ecmp = 1; + zlog_info("ECMP is enabled."); + return CMD_SUCCESS; } DEFUN (no_ripng_allow_ecmp, @@ -2691,75 +2633,71 @@ DEFUN (no_ripng_allow_ecmp, NO_STR "Allow Equal Cost MultiPath\n") { - if (!ripng->ecmp) - { - vty_out (vty, "ECMP is already disabled.\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!ripng->ecmp) { + vty_out(vty, "ECMP is already disabled.\n"); + return CMD_WARNING_CONFIG_FAILED; + } - ripng->ecmp = 0; - zlog_info ("ECMP is disabled."); - ripng_ecmp_disable (); - return CMD_SUCCESS; + ripng->ecmp = 0; + zlog_info("ECMP is disabled."); + ripng_ecmp_disable(); + return CMD_SUCCESS; } /* RIPng configuration write function. */ -static int -ripng_config_write (struct vty *vty) -{ - int ripng_network_write (struct vty *, int); - void ripng_redistribute_write (struct vty *, int); - int write = 0; - struct route_node *rp; - - if (ripng) - { - - /* RIPng router. */ - vty_out (vty, "router ripng\n"); - - if (ripng->default_information) - vty_out (vty, " default-information originate\n"); - - ripng_network_write (vty, 1); - - /* RIPng default metric configuration */ - if (ripng->default_metric != RIPNG_DEFAULT_METRIC_DEFAULT) - vty_out (vty, " default-metric %d\n", - ripng->default_metric); - - ripng_redistribute_write (vty, 1); - - /* RIP offset-list configuration. */ - config_write_ripng_offset_list (vty); - - /* RIPng aggregate routes. */ - for (rp = route_top (ripng->aggregate); rp; rp = route_next (rp)) - if (rp->info != NULL) - vty_out (vty, " aggregate-address %s/%d\n", - inet6_ntoa (rp->p.u.prefix6), - rp->p.prefixlen); - - /* ECMP configuration. */ - if (ripng->ecmp) - vty_out (vty, " allow-ecmp\n"); - - /* RIPng static routes. */ - for (rp = route_top (ripng->route); rp; rp = route_next (rp)) - if (rp->info != NULL) - vty_out (vty, " route %s/%d\n", inet6_ntoa (rp->p.u.prefix6), - rp->p.prefixlen); - - /* RIPng timers configuration. */ - if (ripng->update_time != RIPNG_UPDATE_TIMER_DEFAULT || - ripng->timeout_time != RIPNG_TIMEOUT_TIMER_DEFAULT || - ripng->garbage_time != RIPNG_GARBAGE_TIMER_DEFAULT) - { - vty_out (vty, " timers basic %ld %ld %ld\n", - ripng->update_time, - ripng->timeout_time, - ripng->garbage_time); - } +static int ripng_config_write(struct vty *vty) +{ + int ripng_network_write(struct vty *, int); + void ripng_redistribute_write(struct vty *, int); + int write = 0; + struct route_node *rp; + + if (ripng) { + + /* RIPng router. */ + vty_out(vty, "router ripng\n"); + + if (ripng->default_information) + vty_out(vty, " default-information originate\n"); + + ripng_network_write(vty, 1); + + /* RIPng default metric configuration */ + if (ripng->default_metric != RIPNG_DEFAULT_METRIC_DEFAULT) + vty_out(vty, " default-metric %d\n", + ripng->default_metric); + + ripng_redistribute_write(vty, 1); + + /* RIP offset-list configuration. */ + config_write_ripng_offset_list(vty); + + /* RIPng aggregate routes. */ + for (rp = route_top(ripng->aggregate); rp; rp = route_next(rp)) + if (rp->info != NULL) + vty_out(vty, " aggregate-address %s/%d\n", + inet6_ntoa(rp->p.u.prefix6), + rp->p.prefixlen); + + /* ECMP configuration. */ + if (ripng->ecmp) + vty_out(vty, " allow-ecmp\n"); + + /* RIPng static routes. */ + for (rp = route_top(ripng->route); rp; rp = route_next(rp)) + if (rp->info != NULL) + vty_out(vty, " route %s/%d\n", + inet6_ntoa(rp->p.u.prefix6), + rp->p.prefixlen); + + /* RIPng timers configuration. */ + if (ripng->update_time != RIPNG_UPDATE_TIMER_DEFAULT + || ripng->timeout_time != RIPNG_TIMEOUT_TIMER_DEFAULT + || ripng->garbage_time != RIPNG_GARBAGE_TIMER_DEFAULT) { + vty_out(vty, " timers basic %ld %ld %ld\n", + ripng->update_time, ripng->timeout_time, + ripng->garbage_time); + } #if 0 if (ripng->update_time != RIPNG_UPDATE_TIMER_DEFAULT) vty_out (vty, " update-timer %d\n", ripng->update_time); @@ -2769,326 +2707,301 @@ ripng_config_write (struct vty *vty) vty_out (vty, " garbage-timer %d\n", ripng->garbage_time); #endif /* 0 */ - write += config_write_distribute (vty); + write += config_write_distribute(vty); - write += config_write_if_rmap (vty); + write += config_write_if_rmap(vty); - write++; - } - return write; + write++; + } + return write; } /* RIPng node structure. */ -static struct cmd_node cmd_ripng_node = -{ - RIPNG_NODE, - "%s(config-router)# ", - 1, +static struct cmd_node cmd_ripng_node = { + RIPNG_NODE, "%s(config-router)# ", 1, }; -static void -ripng_distribute_update (struct distribute *dist) -{ - struct interface *ifp; - struct ripng_interface *ri; - struct access_list *alist; - struct prefix_list *plist; - - if (! dist->ifname) - return; - - ifp = if_lookup_by_name (dist->ifname, VRF_DEFAULT); - if (ifp == NULL) - return; - - ri = ifp->info; - - if (dist->list[DISTRIBUTE_V6_IN]) - { - alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_V6_IN]); - if (alist) - ri->list[RIPNG_FILTER_IN] = alist; - else - ri->list[RIPNG_FILTER_IN] = NULL; - } - else - ri->list[RIPNG_FILTER_IN] = NULL; - - if (dist->list[DISTRIBUTE_V6_OUT]) - { - alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_V6_OUT]); - if (alist) - ri->list[RIPNG_FILTER_OUT] = alist; - else - ri->list[RIPNG_FILTER_OUT] = NULL; - } - else - ri->list[RIPNG_FILTER_OUT] = NULL; - - if (dist->prefix[DISTRIBUTE_V6_IN]) - { - plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_V6_IN]); - if (plist) - ri->prefix[RIPNG_FILTER_IN] = plist; - else - ri->prefix[RIPNG_FILTER_IN] = NULL; - } - else - ri->prefix[RIPNG_FILTER_IN] = NULL; - - if (dist->prefix[DISTRIBUTE_V6_OUT]) - { - plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_V6_OUT]); - if (plist) - ri->prefix[RIPNG_FILTER_OUT] = plist; - else - ri->prefix[RIPNG_FILTER_OUT] = NULL; - } - else - ri->prefix[RIPNG_FILTER_OUT] = NULL; -} - -void -ripng_distribute_update_interface (struct interface *ifp) -{ - struct distribute *dist; - - dist = distribute_lookup (ifp->name); - if (dist) - ripng_distribute_update (dist); +static void ripng_distribute_update(struct distribute *dist) +{ + struct interface *ifp; + struct ripng_interface *ri; + struct access_list *alist; + struct prefix_list *plist; + + if (!dist->ifname) + return; + + ifp = if_lookup_by_name(dist->ifname, VRF_DEFAULT); + if (ifp == NULL) + return; + + ri = ifp->info; + + if (dist->list[DISTRIBUTE_V6_IN]) { + alist = access_list_lookup(AFI_IP6, + dist->list[DISTRIBUTE_V6_IN]); + if (alist) + ri->list[RIPNG_FILTER_IN] = alist; + else + ri->list[RIPNG_FILTER_IN] = NULL; + } else + ri->list[RIPNG_FILTER_IN] = NULL; + + if (dist->list[DISTRIBUTE_V6_OUT]) { + alist = access_list_lookup(AFI_IP6, + dist->list[DISTRIBUTE_V6_OUT]); + if (alist) + ri->list[RIPNG_FILTER_OUT] = alist; + else + ri->list[RIPNG_FILTER_OUT] = NULL; + } else + ri->list[RIPNG_FILTER_OUT] = NULL; + + if (dist->prefix[DISTRIBUTE_V6_IN]) { + plist = prefix_list_lookup(AFI_IP6, + dist->prefix[DISTRIBUTE_V6_IN]); + if (plist) + ri->prefix[RIPNG_FILTER_IN] = plist; + else + ri->prefix[RIPNG_FILTER_IN] = NULL; + } else + ri->prefix[RIPNG_FILTER_IN] = NULL; + + if (dist->prefix[DISTRIBUTE_V6_OUT]) { + plist = prefix_list_lookup(AFI_IP6, + dist->prefix[DISTRIBUTE_V6_OUT]); + if (plist) + ri->prefix[RIPNG_FILTER_OUT] = plist; + else + ri->prefix[RIPNG_FILTER_OUT] = NULL; + } else + ri->prefix[RIPNG_FILTER_OUT] = NULL; +} + +void ripng_distribute_update_interface(struct interface *ifp) +{ + struct distribute *dist; + + dist = distribute_lookup(ifp->name); + if (dist) + ripng_distribute_update(dist); } /* Update all interface's distribute list. */ -static void -ripng_distribute_update_all (struct prefix_list *notused) +static void ripng_distribute_update_all(struct prefix_list *notused) { - struct interface *ifp; - struct listnode *node; + struct interface *ifp; + struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - ripng_distribute_update_interface (ifp); + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) + ripng_distribute_update_interface(ifp); } -static void -ripng_distribute_update_all_wrapper (struct access_list *notused) +static void ripng_distribute_update_all_wrapper(struct access_list *notused) { - ripng_distribute_update_all(NULL); + ripng_distribute_update_all(NULL); } /* delete all the added ripng routes. */ -void -ripng_clean() -{ - int i; - struct route_node *rp; - struct ripng_info *rinfo; - struct ripng_aggregate *aggregate; - struct list *list = NULL; - struct listnode *listnode = NULL; - - if (ripng) { - /* Clear RIPng routes */ - for (rp = route_top (ripng->table); rp; rp = route_next (rp)) - { - if ((list = rp->info) != NULL) - { - rinfo = listgetdata (listhead (list)); - if (ripng_route_rte (rinfo)) - ripng_zebra_ipv6_delete (rp); - - for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) - { - RIPNG_TIMER_OFF (rinfo->t_timeout); - RIPNG_TIMER_OFF (rinfo->t_garbage_collect); - ripng_info_free (rinfo); - } - list_delete (list); - rp->info = NULL; - route_unlock_node (rp); - } - - if ((aggregate = rp->aggregate) != NULL) - { - ripng_aggregate_free (aggregate); - rp->aggregate = NULL; - route_unlock_node (rp); - } - } +void ripng_clean() +{ + int i; + struct route_node *rp; + struct ripng_info *rinfo; + struct ripng_aggregate *aggregate; + struct list *list = NULL; + struct listnode *listnode = NULL; + + if (ripng) { + /* Clear RIPng routes */ + for (rp = route_top(ripng->table); rp; rp = route_next(rp)) { + if ((list = rp->info) != NULL) { + rinfo = listgetdata(listhead(list)); + if (ripng_route_rte(rinfo)) + ripng_zebra_ipv6_delete(rp); + + for (ALL_LIST_ELEMENTS_RO(list, listnode, + rinfo)) { + RIPNG_TIMER_OFF(rinfo->t_timeout); + RIPNG_TIMER_OFF( + rinfo->t_garbage_collect); + ripng_info_free(rinfo); + } + list_delete(list); + rp->info = NULL; + route_unlock_node(rp); + } + + if ((aggregate = rp->aggregate) != NULL) { + ripng_aggregate_free(aggregate); + rp->aggregate = NULL; + route_unlock_node(rp); + } + } - /* Cancel the RIPng timers */ - RIPNG_TIMER_OFF (ripng->t_update); - RIPNG_TIMER_OFF (ripng->t_triggered_update); - RIPNG_TIMER_OFF (ripng->t_triggered_interval); + /* Cancel the RIPng timers */ + RIPNG_TIMER_OFF(ripng->t_update); + RIPNG_TIMER_OFF(ripng->t_triggered_update); + RIPNG_TIMER_OFF(ripng->t_triggered_interval); - /* Cancel the read thread */ - if (ripng->t_read) { - thread_cancel (ripng->t_read); - ripng->t_read = NULL; - } + /* Cancel the read thread */ + if (ripng->t_read) { + thread_cancel(ripng->t_read); + ripng->t_read = NULL; + } - /* Close the RIPng socket */ - if (ripng->sock >= 0) { - close(ripng->sock); - ripng->sock = -1; - } + /* Close the RIPng socket */ + if (ripng->sock >= 0) { + close(ripng->sock); + ripng->sock = -1; + } - /* Static RIPng route configuration. */ - for (rp = route_top (ripng->route); rp; rp = route_next (rp)) - if (rp->info) { - rp->info = NULL; - route_unlock_node (rp); - } + /* Static RIPng route configuration. */ + for (rp = route_top(ripng->route); rp; rp = route_next(rp)) + if (rp->info) { + rp->info = NULL; + route_unlock_node(rp); + } - /* RIPng aggregated prefixes */ - for (rp = route_top (ripng->aggregate); rp; rp = route_next (rp)) - if (rp->info) { - rp->info = NULL; - route_unlock_node (rp); - } + /* RIPng aggregated prefixes */ + for (rp = route_top(ripng->aggregate); rp; rp = route_next(rp)) + if (rp->info) { + rp->info = NULL; + route_unlock_node(rp); + } - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (ripng->route_map[i].name) - free (ripng->route_map[i].name); + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (ripng->route_map[i].name) + free(ripng->route_map[i].name); - XFREE (MTYPE_ROUTE_TABLE, ripng->table); - XFREE (MTYPE_ROUTE_TABLE, ripng->route); - XFREE (MTYPE_ROUTE_TABLE, ripng->aggregate); + XFREE(MTYPE_ROUTE_TABLE, ripng->table); + XFREE(MTYPE_ROUTE_TABLE, ripng->route); + XFREE(MTYPE_ROUTE_TABLE, ripng->aggregate); - stream_free (ripng->ibuf); - stream_free (ripng->obuf); + stream_free(ripng->ibuf); + stream_free(ripng->obuf); - XFREE (MTYPE_RIPNG, ripng); - ripng = NULL; - } /* if (ripng) */ + XFREE(MTYPE_RIPNG, ripng); + ripng = NULL; + } /* if (ripng) */ - ripng_clean_network(); - ripng_passive_interface_clean (); - ripng_offset_clean (); - ripng_interface_clean (); - ripng_redistribute_clean (); + ripng_clean_network(); + ripng_passive_interface_clean(); + ripng_offset_clean(); + ripng_interface_clean(); + ripng_redistribute_clean(); } /* Reset all values to the default settings. */ -void -ripng_reset () +void ripng_reset() { - /* Call ripd related reset functions. */ - ripng_debug_reset (); - ripng_route_map_reset (); + /* Call ripd related reset functions. */ + ripng_debug_reset(); + ripng_route_map_reset(); - /* Call library reset functions. */ - vty_reset (); - access_list_reset (); - prefix_list_reset (); + /* Call library reset functions. */ + vty_reset(); + access_list_reset(); + prefix_list_reset(); - distribute_list_reset (); + distribute_list_reset(); - ripng_interface_reset (); + ripng_interface_reset(); - ripng_zclient_reset (); + ripng_zclient_reset(); } -static void -ripng_if_rmap_update (struct if_rmap *if_rmap) +static void ripng_if_rmap_update(struct if_rmap *if_rmap) { - struct interface *ifp; - struct ripng_interface *ri; - struct route_map *rmap; + struct interface *ifp; + struct ripng_interface *ri; + struct route_map *rmap; - ifp = if_lookup_by_name (if_rmap->ifname, VRF_DEFAULT); - if (ifp == NULL) - return; + ifp = if_lookup_by_name(if_rmap->ifname, VRF_DEFAULT); + if (ifp == NULL) + return; - ri = ifp->info; + ri = ifp->info; - if (if_rmap->routemap[IF_RMAP_IN]) - { - rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]); - if (rmap) - ri->routemap[IF_RMAP_IN] = rmap; - else - ri->routemap[IF_RMAP_IN] = NULL; - } - else - ri->routemap[RIPNG_FILTER_IN] = NULL; + if (if_rmap->routemap[IF_RMAP_IN]) { + rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_IN]); + if (rmap) + ri->routemap[IF_RMAP_IN] = rmap; + else + ri->routemap[IF_RMAP_IN] = NULL; + } else + ri->routemap[RIPNG_FILTER_IN] = NULL; - if (if_rmap->routemap[IF_RMAP_OUT]) - { - rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]); - if (rmap) - ri->routemap[IF_RMAP_OUT] = rmap; - else - ri->routemap[IF_RMAP_OUT] = NULL; - } - else - ri->routemap[RIPNG_FILTER_OUT] = NULL; + if (if_rmap->routemap[IF_RMAP_OUT]) { + rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_OUT]); + if (rmap) + ri->routemap[IF_RMAP_OUT] = rmap; + else + ri->routemap[IF_RMAP_OUT] = NULL; + } else + ri->routemap[RIPNG_FILTER_OUT] = NULL; } -void -ripng_if_rmap_update_interface (struct interface *ifp) +void ripng_if_rmap_update_interface(struct interface *ifp) { - struct if_rmap *if_rmap; + struct if_rmap *if_rmap; - if_rmap = if_rmap_lookup (ifp->name); - if (if_rmap) - ripng_if_rmap_update (if_rmap); + if_rmap = if_rmap_lookup(ifp->name); + if (if_rmap) + ripng_if_rmap_update(if_rmap); } -static void -ripng_routemap_update_redistribute (void) +static void ripng_routemap_update_redistribute(void) { - int i; + int i; - if (ripng) - { - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - if (ripng->route_map[i].name) - ripng->route_map[i].map = - route_map_lookup_by_name (ripng->route_map[i].name); + if (ripng) { + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (ripng->route_map[i].name) + ripng->route_map[i].map = + route_map_lookup_by_name( + ripng->route_map[i].name); + } } - } } -static void -ripng_routemap_update (const char *unused) +static void ripng_routemap_update(const char *unused) { - struct interface *ifp; - struct listnode *node; + struct interface *ifp; + struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - ripng_if_rmap_update_interface (ifp); + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) + ripng_if_rmap_update_interface(ifp); - ripng_routemap_update_redistribute (); + ripng_routemap_update_redistribute(); } /* Initialize ripng structure and set commands. */ -void -ripng_init () +void ripng_init() { - /* Install RIPNG_NODE. */ - install_node (&cmd_ripng_node, ripng_config_write); + /* Install RIPNG_NODE. */ + install_node(&cmd_ripng_node, ripng_config_write); - /* Install ripng commands. */ - install_element (VIEW_NODE, &show_ipv6_ripng_cmd); - install_element (VIEW_NODE, &show_ipv6_ripng_status_cmd); + /* Install ripng commands. */ + install_element(VIEW_NODE, &show_ipv6_ripng_cmd); + install_element(VIEW_NODE, &show_ipv6_ripng_status_cmd); - install_element (ENABLE_NODE, &clear_ipv6_rip_cmd); + install_element(ENABLE_NODE, &clear_ipv6_rip_cmd); - install_element (CONFIG_NODE, &router_ripng_cmd); - install_element (CONFIG_NODE, &no_router_ripng_cmd); + install_element(CONFIG_NODE, &router_ripng_cmd); + install_element(CONFIG_NODE, &no_router_ripng_cmd); - install_default (RIPNG_NODE); - install_element (RIPNG_NODE, &ripng_route_cmd); - install_element (RIPNG_NODE, &no_ripng_route_cmd); - install_element (RIPNG_NODE, &ripng_aggregate_address_cmd); - install_element (RIPNG_NODE, &no_ripng_aggregate_address_cmd); + install_default(RIPNG_NODE); + install_element(RIPNG_NODE, &ripng_route_cmd); + install_element(RIPNG_NODE, &no_ripng_route_cmd); + install_element(RIPNG_NODE, &ripng_aggregate_address_cmd); + install_element(RIPNG_NODE, &no_ripng_aggregate_address_cmd); - install_element (RIPNG_NODE, &ripng_default_metric_cmd); - install_element (RIPNG_NODE, &no_ripng_default_metric_cmd); + install_element(RIPNG_NODE, &ripng_default_metric_cmd); + install_element(RIPNG_NODE, &no_ripng_default_metric_cmd); - install_element (RIPNG_NODE, &ripng_timers_cmd); - install_element (RIPNG_NODE, &no_ripng_timers_cmd); + install_element(RIPNG_NODE, &ripng_timers_cmd); + install_element(RIPNG_NODE, &no_ripng_timers_cmd); #if 0 install_element (VIEW_NODE, &show_ipv6_protocols_cmd); install_element (RIPNG_NODE, &ripng_update_timer_cmd); @@ -3099,38 +3012,39 @@ ripng_init () install_element (RIPNG_NODE, &no_ripng_garbage_timer_cmd); #endif /* 0 */ - install_element (RIPNG_NODE, &ripng_default_information_originate_cmd); - install_element (RIPNG_NODE, &no_ripng_default_information_originate_cmd); + install_element(RIPNG_NODE, &ripng_default_information_originate_cmd); + install_element(RIPNG_NODE, + &no_ripng_default_information_originate_cmd); - install_element (RIPNG_NODE, &ripng_allow_ecmp_cmd); - install_element (RIPNG_NODE, &no_ripng_allow_ecmp_cmd); + install_element(RIPNG_NODE, &ripng_allow_ecmp_cmd); + install_element(RIPNG_NODE, &no_ripng_allow_ecmp_cmd); - ripng_if_init (); - ripng_debug_init (); + ripng_if_init(); + ripng_debug_init(); - /* Access list install. */ - access_list_init (); - access_list_add_hook (ripng_distribute_update_all_wrapper); - access_list_delete_hook (ripng_distribute_update_all_wrapper); + /* Access list install. */ + access_list_init(); + access_list_add_hook(ripng_distribute_update_all_wrapper); + access_list_delete_hook(ripng_distribute_update_all_wrapper); - /* Prefix list initialize.*/ - prefix_list_init (); - prefix_list_add_hook (ripng_distribute_update_all); - prefix_list_delete_hook (ripng_distribute_update_all); + /* Prefix list initialize.*/ + prefix_list_init(); + prefix_list_add_hook(ripng_distribute_update_all); + prefix_list_delete_hook(ripng_distribute_update_all); - /* Distribute list install. */ - distribute_list_init (RIPNG_NODE); - distribute_list_add_hook (ripng_distribute_update); - distribute_list_delete_hook (ripng_distribute_update); + /* Distribute list install. */ + distribute_list_init(RIPNG_NODE); + distribute_list_add_hook(ripng_distribute_update); + distribute_list_delete_hook(ripng_distribute_update); - /* Route-map for interface. */ - ripng_route_map_init (); - ripng_offset_init (); + /* Route-map for interface. */ + ripng_route_map_init(); + ripng_offset_init(); - route_map_add_hook (ripng_routemap_update); - route_map_delete_hook (ripng_routemap_update); + route_map_add_hook(ripng_routemap_update); + route_map_delete_hook(ripng_routemap_update); - if_rmap_init (RIPNG_NODE); - if_rmap_hook_add (ripng_if_rmap_update); - if_rmap_hook_delete (ripng_if_rmap_update); + if_rmap_init(RIPNG_NODE); + if_rmap_hook_add(ripng_if_rmap_update); + if_rmap_hook_delete(ripng_if_rmap_update); } diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index ce8ea07a4..9a609cab8 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -90,120 +90,115 @@ #endif /* IFMINMTU */ /* RIPng structure. */ -struct ripng -{ - /* RIPng socket. */ - int sock; - - /* RIPng Parameters.*/ - u_char command; - u_char version; - unsigned long update_time; - unsigned long timeout_time; - unsigned long garbage_time; - int max_mtu; - int default_metric; - int default_information; - - /* Input/output buffer of RIPng. */ - struct stream *ibuf; - struct stream *obuf; - - /* RIPng routing information base. */ - struct route_table *table; - - /* RIPng only static route information. */ - struct route_table *route; - - /* RIPng aggregate route information. */ - struct route_table *aggregate; - - /* RIPng threads. */ - struct thread *t_read; - struct thread *t_write; - struct thread *t_update; - struct thread *t_garbage; - struct thread *t_zebra; - - /* Triggered update hack. */ - int trigger; - struct thread *t_triggered_update; - struct thread *t_triggered_interval; - - /* RIPng ECMP flag */ - unsigned int ecmp; - - /* For redistribute route map. */ - struct - { - char *name; - struct route_map *map; - int metric_config; - u_int32_t metric; - } route_map[ZEBRA_ROUTE_MAX]; +struct ripng { + /* RIPng socket. */ + int sock; + + /* RIPng Parameters.*/ + u_char command; + u_char version; + unsigned long update_time; + unsigned long timeout_time; + unsigned long garbage_time; + int max_mtu; + int default_metric; + int default_information; + + /* Input/output buffer of RIPng. */ + struct stream *ibuf; + struct stream *obuf; + + /* RIPng routing information base. */ + struct route_table *table; + + /* RIPng only static route information. */ + struct route_table *route; + + /* RIPng aggregate route information. */ + struct route_table *aggregate; + + /* RIPng threads. */ + struct thread *t_read; + struct thread *t_write; + struct thread *t_update; + struct thread *t_garbage; + struct thread *t_zebra; + + /* Triggered update hack. */ + int trigger; + struct thread *t_triggered_update; + struct thread *t_triggered_interval; + + /* RIPng ECMP flag */ + unsigned int ecmp; + + /* For redistribute route map. */ + struct { + char *name; + struct route_map *map; + int metric_config; + u_int32_t metric; + } route_map[ZEBRA_ROUTE_MAX]; }; /* Routing table entry. */ -struct rte -{ - struct in6_addr addr; /* RIPng destination prefix */ - u_int16_t tag; /* RIPng tag */ - u_char prefixlen; /* Length of the RIPng prefix */ - u_char metric; /* Metric of the RIPng route */ - /* The nexthop is stored by the structure - * ripng_nexthop within ripngd.c */ +struct rte { + struct in6_addr addr; /* RIPng destination prefix */ + u_int16_t tag; /* RIPng tag */ + u_char prefixlen; /* Length of the RIPng prefix */ + u_char metric; /* Metric of the RIPng route */ + /* The nexthop is stored by the structure + * ripng_nexthop within ripngd.c */ }; /* RIPNG send packet. */ -struct ripng_packet -{ - u_char command; - u_char version; - u_int16_t zero; - struct rte rte[1]; +struct ripng_packet { + u_char command; + u_char version; + u_int16_t zero; + struct rte rte[1]; }; /* Each route's information. */ -struct ripng_info -{ - /* This route's type. Static, ripng or aggregate. */ - u_char type; +struct ripng_info { + /* This route's type. Static, ripng or aggregate. */ + u_char type; - /* Sub type for static route. */ - u_char sub_type; + /* Sub type for static route. */ + u_char sub_type; - /* RIPng specific information */ - struct in6_addr nexthop; - struct in6_addr from; + /* RIPng specific information */ + struct in6_addr nexthop; + struct in6_addr from; - /* Which interface does this route come from. */ - ifindex_t ifindex; + /* Which interface does this route come from. */ + ifindex_t ifindex; - /* Metric of this route. */ - u_char metric; + /* Metric of this route. */ + u_char metric; - /* Tag field of RIPng packet.*/ - u_int16_t tag; + /* Tag field of RIPng packet.*/ + u_int16_t tag; - /* For aggregation. */ - unsigned int suppress; + /* For aggregation. */ + unsigned int suppress; - /* Flags of RIPng route. */ +/* Flags of RIPng route. */ #define RIPNG_RTF_FIB 1 #define RIPNG_RTF_CHANGED 2 - u_char flags; + u_char flags; - /* Garbage collect timer. */ - struct thread *t_timeout; - struct thread *t_garbage_collect; + /* Garbage collect timer. */ + struct thread *t_timeout; + struct thread *t_garbage_collect; - /* Route-map features - this variables can be changed. */ - struct in6_addr nexthop_out; - u_char metric_set; - u_char metric_out; - u_int16_t tag_out; + /* Route-map features - this variables can be changed. */ + struct in6_addr nexthop_out; + u_char metric_set; + u_char metric_out; + u_int16_t tag_out; - struct route_node *rp; + struct route_node *rp; }; #ifdef notyet @@ -236,38 +231,37 @@ struct ripng_tag #endif /* not yet */ typedef enum { - RIPNG_NO_SPLIT_HORIZON = 0, - RIPNG_SPLIT_HORIZON, - RIPNG_SPLIT_HORIZON_POISONED_REVERSE + RIPNG_NO_SPLIT_HORIZON = 0, + RIPNG_SPLIT_HORIZON, + RIPNG_SPLIT_HORIZON_POISONED_REVERSE } split_horizon_policy_t; /* RIPng specific interface configuration. */ -struct ripng_interface -{ - /* RIPng is enabled on this interface. */ - int enable_network; - int enable_interface; - - /* RIPng is running on this interface. */ - int running; - - /* Split horizon flag. */ - split_horizon_policy_t split_horizon; - split_horizon_policy_t split_horizon_default; - - /* For filter type slot. */ +struct ripng_interface { + /* RIPng is enabled on this interface. */ + int enable_network; + int enable_interface; + + /* RIPng is running on this interface. */ + int running; + + /* Split horizon flag. */ + split_horizon_policy_t split_horizon; + split_horizon_policy_t split_horizon_default; + +/* For filter type slot. */ #define RIPNG_FILTER_IN 0 #define RIPNG_FILTER_OUT 1 #define RIPNG_FILTER_MAX 2 - /* Access-list. */ - struct access_list *list[RIPNG_FILTER_MAX]; + /* Access-list. */ + struct access_list *list[RIPNG_FILTER_MAX]; - /* Prefix-list. */ - struct prefix_list *prefix[RIPNG_FILTER_MAX]; + /* Prefix-list. */ + struct prefix_list *prefix[RIPNG_FILTER_MAX]; - /* Route-map. */ - struct route_map *routemap[RIPNG_FILTER_MAX]; + /* Route-map. */ + struct route_map *routemap[RIPNG_FILTER_MAX]; #ifdef notyet #if 0 @@ -276,63 +270,60 @@ struct ripng_interface #endif /* 0 */ #endif /* notyet */ - /* Default information originate. */ - u_char default_originate; + /* Default information originate. */ + u_char default_originate; - /* Default information only. */ - u_char default_only; + /* Default information only. */ + u_char default_only; - /* Wake up thread. */ - struct thread *t_wakeup; + /* Wake up thread. */ + struct thread *t_wakeup; - /* Passive interface. */ - int passive; + /* Passive interface. */ + int passive; }; /* RIPng peer information. */ -struct ripng_peer -{ - /* Peer address. */ - struct in6_addr addr; +struct ripng_peer { + /* Peer address. */ + struct in6_addr addr; - /* Peer RIPng tag value. */ - int domain; + /* Peer RIPng tag value. */ + int domain; - /* Last update time. */ - time_t uptime; + /* Last update time. */ + time_t uptime; - /* Peer RIP version. */ - u_char version; + /* Peer RIP version. */ + u_char version; - /* Statistics. */ - int recv_badpackets; - int recv_badroutes; + /* Statistics. */ + int recv_badpackets; + int recv_badroutes; - /* Timeout thread. */ - struct thread *t_timeout; + /* Timeout thread. */ + struct thread *t_timeout; }; /* All RIPng events. */ -enum ripng_event -{ - RIPNG_READ, - RIPNG_ZEBRA, - RIPNG_REQUEST_EVENT, - RIPNG_UPDATE_EVENT, - RIPNG_TRIGGERED_UPDATE, +enum ripng_event { + RIPNG_READ, + RIPNG_ZEBRA, + RIPNG_REQUEST_EVENT, + RIPNG_UPDATE_EVENT, + RIPNG_TRIGGERED_UPDATE, }; /* RIPng timer on/off macro. */ #define RIPNG_TIMER_ON(T,F,V) thread_add_timer (master, (F), rinfo, (V), &(T)) -#define RIPNG_TIMER_OFF(T) \ -do { \ - if (T) \ - { \ - thread_cancel(T); \ - (T) = NULL; \ - } \ -} while (0) +#define RIPNG_TIMER_OFF(T) \ + do { \ + if (T) { \ + thread_cancel(T); \ + (T) = NULL; \ + } \ + } while (0) /* Extern variables. */ extern struct ripng *ripng; @@ -340,85 +331,85 @@ extern struct ripng *ripng; extern struct thread_master *master; /* Prototypes. */ -extern void ripng_init (void); -extern void ripng_reset (void); -extern void ripng_clean (void); -extern void ripng_clean_network (void); -extern void ripng_interface_clean (void); -extern void ripng_interface_reset (void); -extern void ripng_passive_interface_clean (void); -extern void ripng_if_init (void); -extern void ripng_route_map_init (void); -extern void ripng_route_map_reset (void); -extern void ripng_terminate (void); - /* zclient_init() is done by ripng_zebra.c:zebra_init() */ +extern void ripng_init(void); +extern void ripng_reset(void); +extern void ripng_clean(void); +extern void ripng_clean_network(void); +extern void ripng_interface_clean(void); +extern void ripng_interface_reset(void); +extern void ripng_passive_interface_clean(void); +extern void ripng_if_init(void); +extern void ripng_route_map_init(void); +extern void ripng_route_map_reset(void); +extern void ripng_terminate(void); +/* zclient_init() is done by ripng_zebra.c:zebra_init() */ extern void zebra_init(struct thread_master *); -extern void ripng_zebra_stop (void); -extern void ripng_zclient_reset (void); -extern void ripng_offset_init (void); - -extern int config_write_ripng_offset_list (struct vty *); - -extern void ripng_peer_init (void); -extern void ripng_peer_update (struct sockaddr_in6 *, u_char); -extern void ripng_peer_bad_route (struct sockaddr_in6 *); -extern void ripng_peer_bad_packet (struct sockaddr_in6 *); -extern void ripng_peer_display (struct vty *); -extern struct ripng_peer *ripng_peer_lookup (struct in6_addr *); -extern struct ripng_peer *ripng_peer_lookup_next (struct in6_addr *); - -extern int ripng_offset_list_apply_in (struct prefix_ipv6 *, - struct interface *, u_char *); -extern int ripng_offset_list_apply_out (struct prefix_ipv6 *, - struct interface *, u_char *); -extern void ripng_offset_clean (void); - -extern struct ripng_info * ripng_info_new (void); -extern void ripng_info_free (struct ripng_info *rinfo); -extern void ripng_event (enum ripng_event, int); -extern int ripng_request (struct interface *ifp); -extern void ripng_redistribute_add (int, int, struct prefix_ipv6 *, - ifindex_t, struct in6_addr *, route_tag_t); -extern void ripng_redistribute_delete (int, int, struct prefix_ipv6 *, - ifindex_t); -extern void ripng_redistribute_withdraw (int type); - -extern void ripng_distribute_update_interface (struct interface *); -extern void ripng_if_rmap_update_interface (struct interface *); - -extern void ripng_zebra_ipv6_add (struct route_node *); -extern void ripng_zebra_ipv6_delete (struct route_node *); - -extern void ripng_redistribute_clean (void); -extern int ripng_redistribute_check (int); -extern void ripng_redistribute_write (struct vty *, int); - -extern int ripng_write_rte (int num, struct stream *s, struct prefix_ipv6 *p, - struct in6_addr *nexthop, - u_int16_t tag, u_char metric); -extern int ripng_send_packet (caddr_t buf, int bufsize, - struct sockaddr_in6 *to, struct interface *ifp); - -extern void ripng_packet_dump (struct ripng_packet *packet, int size, - const char *sndrcv); - -extern int ripng_interface_up (int command, struct zclient *, zebra_size_t, - vrf_id_t); -extern int ripng_interface_down (int command, struct zclient *, zebra_size_t, - vrf_id_t); -extern int ripng_interface_add (int command, struct zclient *, zebra_size_t, - vrf_id_t); -extern int ripng_interface_delete (int command, struct zclient *, zebra_size_t, - vrf_id_t); -extern int ripng_interface_address_add (int command, struct zclient *, zebra_size_t, - vrf_id_t); -extern int ripng_interface_address_delete (int command, struct zclient *, zebra_size_t, - vrf_id_t); - -extern int ripng_network_write (struct vty *, int); - -extern struct ripng_info *ripng_ecmp_add (struct ripng_info *); -extern struct ripng_info *ripng_ecmp_replace (struct ripng_info *); -extern struct ripng_info *ripng_ecmp_delete (struct ripng_info *); +extern void ripng_zebra_stop(void); +extern void ripng_zclient_reset(void); +extern void ripng_offset_init(void); + +extern int config_write_ripng_offset_list(struct vty *); + +extern void ripng_peer_init(void); +extern void ripng_peer_update(struct sockaddr_in6 *, u_char); +extern void ripng_peer_bad_route(struct sockaddr_in6 *); +extern void ripng_peer_bad_packet(struct sockaddr_in6 *); +extern void ripng_peer_display(struct vty *); +extern struct ripng_peer *ripng_peer_lookup(struct in6_addr *); +extern struct ripng_peer *ripng_peer_lookup_next(struct in6_addr *); + +extern int ripng_offset_list_apply_in(struct prefix_ipv6 *, struct interface *, + u_char *); +extern int ripng_offset_list_apply_out(struct prefix_ipv6 *, struct interface *, + u_char *); +extern void ripng_offset_clean(void); + +extern struct ripng_info *ripng_info_new(void); +extern void ripng_info_free(struct ripng_info *rinfo); +extern void ripng_event(enum ripng_event, int); +extern int ripng_request(struct interface *ifp); +extern void ripng_redistribute_add(int, int, struct prefix_ipv6 *, ifindex_t, + struct in6_addr *, route_tag_t); +extern void ripng_redistribute_delete(int, int, struct prefix_ipv6 *, + ifindex_t); +extern void ripng_redistribute_withdraw(int type); + +extern void ripng_distribute_update_interface(struct interface *); +extern void ripng_if_rmap_update_interface(struct interface *); + +extern void ripng_zebra_ipv6_add(struct route_node *); +extern void ripng_zebra_ipv6_delete(struct route_node *); + +extern void ripng_redistribute_clean(void); +extern int ripng_redistribute_check(int); +extern void ripng_redistribute_write(struct vty *, int); + +extern int ripng_write_rte(int num, struct stream *s, struct prefix_ipv6 *p, + struct in6_addr *nexthop, u_int16_t tag, + u_char metric); +extern int ripng_send_packet(caddr_t buf, int bufsize, struct sockaddr_in6 *to, + struct interface *ifp); + +extern void ripng_packet_dump(struct ripng_packet *packet, int size, + const char *sndrcv); + +extern int ripng_interface_up(int command, struct zclient *, zebra_size_t, + vrf_id_t); +extern int ripng_interface_down(int command, struct zclient *, zebra_size_t, + vrf_id_t); +extern int ripng_interface_add(int command, struct zclient *, zebra_size_t, + vrf_id_t); +extern int ripng_interface_delete(int command, struct zclient *, zebra_size_t, + vrf_id_t); +extern int ripng_interface_address_add(int command, struct zclient *, + zebra_size_t, vrf_id_t); +extern int ripng_interface_address_delete(int command, struct zclient *, + zebra_size_t, vrf_id_t); + +extern int ripng_network_write(struct vty *, int); + +extern struct ripng_info *ripng_ecmp_add(struct ripng_info *); +extern struct ripng_info *ripng_ecmp_replace(struct ripng_info *); +extern struct ripng_info *ripng_ecmp_delete(struct ripng_info *); #endif /* _ZEBRA_RIPNG_RIPNGD_H */ diff --git a/tests/bgpd/test_aspath.c b/tests/bgpd/test_aspath.c index 461fb829d..46462d79c 100644 --- a/tests/bgpd/test_aspath.c +++ b/tests/bgpd/test_aspath.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2005 Sun Microsystems, Inc. * * This file is part of Quagga. @@ -44,1345 +44,1346 @@ struct thread_master *master = NULL; static int failed = 0; /* specification for a test - what the results should be */ -struct test_spec -{ - const char *shouldbe; /* the string the path should parse to */ - const char *shouldbe_delete_confed; /* ditto, but once confeds are deleted */ - const unsigned int hops; /* aspath_count_hops result */ - const unsigned int confeds; /* aspath_count_confeds */ - const int private_as; /* whether the private_as check should pass or fail */ +struct test_spec { + const char *shouldbe; /* the string the path should parse to */ + const char *shouldbe_delete_confed; /* ditto, but once confeds are + deleted */ + const unsigned int hops; /* aspath_count_hops result */ + const unsigned int confeds; /* aspath_count_confeds */ + const int private_as; /* whether the private_as check should pass or + fail */ #define NOT_ALL_PRIVATE 0 #define ALL_PRIVATE 1 - const as_t does_loop; /* an ASN which should trigger loop-check */ - const as_t doesnt_loop; /* one which should not */ - const as_t first; /* the first ASN, if there is one */ + const as_t does_loop; /* an ASN which should trigger loop-check */ + const as_t doesnt_loop; /* one which should not */ + const as_t first; /* the first ASN, if there is one */ #define NULL_ASN 0 }; /* test segments to parse and validate, and use for other tests */ static struct test_segment { - const char *name; - const char *desc; - const u_char asdata[1024]; - int len; - struct test_spec sp; -} test_segments [] = -{ - { /* 0 */ - "seq1", - "seq(8466,3,52737,4096)", - { 0x2,0x4, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00 }, - 10, - { "8466 3 52737 4096", - "8466 3 52737 4096", - 4, 0, NOT_ALL_PRIVATE, 4096, 4, 8466 }, - }, - { /* 1 */ - "seq2", - "seq(8722) seq(4)", - { 0x2,0x1, 0x22,0x12, - 0x2,0x1, 0x00,0x04 }, - 8, - { "8722 4", - "8722 4", - 2, 0, NOT_ALL_PRIVATE, 4, 5, 8722, }, - }, - { /* 2 */ - "seq3", - "seq(8466,3,52737,4096,8722,4)", - { 0x2,0x6, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, - 0x22,0x12, 0x00,0x04}, - 14, - { "8466 3 52737 4096 8722 4", - "8466 3 52737 4096 8722 4", - 6, 0, NOT_ALL_PRIVATE, 3, 5, 8466 }, - }, - { /* 3 */ - "seqset", - "seq(8482,51457) set(5204)", - { 0x2,0x2, 0x21,0x22, 0xc9,0x01, - 0x1,0x1, 0x14,0x54 }, - 10, - { "8482 51457 {5204}", - "8482 51457 {5204}", - 3, 0, NOT_ALL_PRIVATE, 5204, 51456, 8482}, - }, - { /* 4 */ - "seqset2", - "seq(8467, 59649) set(4196,48658) set(17322,30745)", - { 0x2,0x2, 0x21,0x13, 0xe9,0x01, - 0x1,0x2, 0x10,0x64, 0xbe,0x12, - 0x1,0x2, 0x43,0xaa, 0x78,0x19 }, - 18, - { "8467 59649 {4196,48658} {17322,30745}", - "8467 59649 {4196,48658} {17322,30745}", - 4, 0, NOT_ALL_PRIVATE, 48658, 1, 8467}, - }, - { /* 5 */ - "multi", - "seq(6435,59408,21665) set(2457,61697,4369), seq(1842,41590,51793)", - { 0x2,0x3, 0x19,0x23, 0xe8,0x10, 0x54,0xa1, - 0x1,0x3, 0x09,0x99, 0xf1,0x01, 0x11,0x11, - 0x2,0x3, 0x07,0x32, 0xa2,0x76, 0xca,0x51 }, - 24, - { "6435 59408 21665 {2457,4369,61697} 1842 41590 51793", - "6435 59408 21665 {2457,4369,61697} 1842 41590 51793", - 7, 0, NOT_ALL_PRIVATE, 51793, 1, 6435 }, - }, - { /* 6 */ - "confed", - "confseq(123,456,789)", - { 0x3,0x3, 0x00,0x7b, 0x01,0xc8, 0x03,0x15 }, - 8, - { "(123 456 789)", - "", - 0, 3, NOT_ALL_PRIVATE, 789, 1, NULL_ASN }, - }, - { /* 7 */ - "confed2", - "confseq(123,456,789) confseq(111,222)", - { 0x3,0x3, 0x00,0x7b, 0x01,0xc8, 0x03,0x15, - 0x3,0x2, 0x00,0x6f, 0x00,0xde }, - 14, - { "(123 456 789) (111 222)", - "", - 0, 5, NOT_ALL_PRIVATE, 111, 1, NULL_ASN }, - }, - { /* 8 */ - "confset", - "confset(456,123,789)", - { 0x4,0x3, 0x01,0xc8, 0x00,0x7b, 0x03,0x15 }, - 8, - { "[123,456,789]", - "", - 0, 1, NOT_ALL_PRIVATE, 123, 1, NULL_ASN }, - }, - { /* 9 */ - "confmulti", - "confseq(123,456,789) confset(222,111) seq(8722) set(4196,48658)", - { 0x3,0x3, 0x00,0x7b, 0x01,0xc8, 0x03,0x15, - 0x4,0x2, 0x00,0xde, 0x00,0x6f, - 0x2,0x1, 0x22,0x12, - 0x1,0x2, 0x10,0x64, 0xbe,0x12 }, - 24, - { "(123 456 789) [111,222] 8722 {4196,48658}", - "8722 {4196,48658}", - 2, 4, NOT_ALL_PRIVATE, 123, 1, NULL_ASN }, - }, - { /* 10 */ - "seq4", - "seq(8466,2,52737,4096,8722,4)", - { 0x2,0x6, 0x21,0x12, 0x00,0x02, 0xce,0x01, 0x10,0x00, - 0x22,0x12, 0x00,0x04}, - 14, - { "8466 2 52737 4096 8722 4", - "8466 2 52737 4096 8722 4", - 6, 0, NOT_ALL_PRIVATE, 4096, 1, 8466 }, - }, - { /* 11 */ - "tripleseq1", - "seq(8466,2,52737) seq(4096,8722,4) seq(8722)", - { 0x2,0x3, 0x21,0x12, 0x00,0x02, 0xce,0x01, - 0x2,0x3, 0x10,0x00, 0x22,0x12, 0x00,0x04, - 0x2,0x1, 0x22,0x12}, - 20, - { "8466 2 52737 4096 8722 4 8722", - "8466 2 52737 4096 8722 4 8722", - 7, 0, NOT_ALL_PRIVATE, 4096, 1, 8466 }, - }, - { /* 12 */ - "someprivate", - "seq(8466,64512,52737,65535)", - { 0x2,0x4, 0x21,0x12, 0xfc,0x00, 0xce,0x01, 0xff,0xff }, - 10, - { "8466 64512 52737 65535", - "8466 64512 52737 65535", - 4, 0, NOT_ALL_PRIVATE, 65535, 4, 8466 }, - }, - { /* 13 */ - "allprivate", - "seq(65534,64512,64513,65535)", - { 0x2,0x4, 0xff,0xfe, 0xfc,0x00, 0xfc,0x01, 0xff,0xff }, - 10, - { "65534 64512 64513 65535", - "65534 64512 64513 65535", - 4, 0, ALL_PRIVATE, 65534, 4, 65534 }, - }, - { /* 14 */ - "long", - "seq(8466,3,52737,4096,34285,)", - { 0x2,0xfa, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, - 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, }, - 502, - { "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285", - - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285", - 250, 0, NOT_ALL_PRIVATE, 4096, 4, 8466 }, - }, - { /* 15 */ - "seq1extra", - "seq(8466,3,52737,4096,3456)", - { 0x2,0x5, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x0d,0x80 }, - 12, - { "8466 3 52737 4096 3456", - "8466 3 52737 4096 3456", - 5, 0, NOT_ALL_PRIVATE, 4096, 4, 8466 }, - }, - { /* 16 */ - "empty", - "", - {}, - 0, - { "", "", 0, 0, 0, 0, 0, 0 }, - }, - { /* 17 */ - "redundantset", - "seq(8466,3,52737,4096,3456) set(7099,8153,8153,8153)", - { 0x2,0x5, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x0d,0x80, - 0x1,0x4, 0x1b,0xbb, 0x1f,0xd9, 0x1f,0xd9, 0x1f,0xd9 }, - 22, - { - /* We shouldn't ever /generate/ such paths. However, we should - * cope with them fine. - */ - "8466 3 52737 4096 3456 {7099,8153}", - "8466 3 52737 4096 3456 {7099,8153}", - 6, 0, NOT_ALL_PRIVATE, 4096, 4, 8466 }, - }, - { /* 18 */ - "reconcile_lead_asp", - "seq(6435,59408,21665) set(23456,23456,23456), seq(23456,23456,23456)", - { 0x2,0x3, 0x19,0x23, 0xe8,0x10, 0x54,0xa1, - 0x1,0x3, 0x5b,0xa0, 0x5b,0xa0, 0x5b,0xa0, - 0x2,0x3, 0x5b,0xa0, 0x5b,0xa0, 0x5b,0xa0 }, - 24, - { "6435 59408 21665 {23456} 23456 23456 23456", - "6435 59408 21665 {23456} 23456 23456 23456", - 7, 0, NOT_ALL_PRIVATE, 23456, 1, 6435 }, - }, - { /* 19 */ - "reconcile_new_asp", - "set(2457,61697,4369), seq(1842,41591,51793)", - { - 0x1,0x3, 0x09,0x99, 0xf1,0x01, 0x11,0x11, - 0x2,0x3, 0x07,0x32, 0xa2,0x77, 0xca,0x51 }, - 16, - { "{2457,4369,61697} 1842 41591 51793", - "{2457,4369,61697} 1842 41591 51793", - 4, 0, NOT_ALL_PRIVATE, 51793, 1, 2457 }, - }, - { /* 20 */ - "reconcile_confed", - "confseq(123,456,789) confset(456,124,788) seq(6435,59408,21665)" - " set(23456,23456,23456), seq(23456,23456,23456)", - { 0x3,0x3, 0x00,0x7b, 0x01,0xc8, 0x03,0x15, - 0x4,0x3, 0x01,0xc8, 0x00,0x7c, 0x03,0x14, - 0x2,0x3, 0x19,0x23, 0xe8,0x10, 0x54,0xa1, - 0x1,0x3, 0x5b,0xa0, 0x5b,0xa0, 0x5b,0xa0, - 0x2,0x3, 0x5b,0xa0, 0x5b,0xa0, 0x5b,0xa0 }, - 40, - { "(123 456 789) [124,456,788] 6435 59408 21665" - " {23456} 23456 23456 23456", - "6435 59408 21665 {23456} 23456 23456 23456", - 7, 4, NOT_ALL_PRIVATE, 23456, 1, 6435 }, - }, - { /* 21 */ - "reconcile_start_trans", - "seq(23456,23456,23456) seq(6435,59408,21665)", - { 0x2,0x3, 0x5b,0xa0, 0x5b,0xa0, 0x5b,0xa0, - 0x2,0x3, 0x19,0x23, 0xe8,0x10, 0x54,0xa1, }, - 16, - { "23456 23456 23456 6435 59408 21665", - "23456 23456 23456 6435 59408 21665", - 6, 0, NOT_ALL_PRIVATE, 21665, 1, 23456 }, - }, - { /* 22 */ - "reconcile_start_trans4", - "seq(1842,41591,51793) seq(6435,59408,21665)", - { 0x2,0x3, 0x07,0x32, 0xa2,0x77, 0xca,0x51, - 0x2,0x3, 0x19,0x23, 0xe8,0x10, 0x54,0xa1, }, - 16, - { "1842 41591 51793 6435 59408 21665", - "1842 41591 51793 6435 59408 21665", - 6, 0, NOT_ALL_PRIVATE, 41591, 1, 1842 }, - }, - { /* 23 */ - "reconcile_start_trans_error", - "seq(23456,23456,23456) seq(6435,59408)", - { 0x2,0x3, 0x5b,0xa0, 0x5b,0xa0, 0x5b,0xa0, - 0x2,0x2, 0x19,0x23, 0xe8,0x10, }, - 14, - { "23456 23456 23456 6435 59408", - "23456 23456 23456 6435 59408", - 5, 0, NOT_ALL_PRIVATE, 59408, 1, 23456 }, - }, - { /* 24 */ - "redundantset2", - "seq(8466,3,52737,4096,3456) set(7099,8153,8153,8153,7099)", - { 0x2,0x5, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x0d,0x80, - 0x1,0x5, 0x1b,0xbb, 0x1f,0xd9, 0x1f,0xd9, 0x1f,0xd9, 0x1b,0xbb,}, - 24, - { - /* We should weed out duplicate set members. */ - "8466 3 52737 4096 3456 {7099,8153}", - "8466 3 52737 4096 3456 {7099,8153}", - 6, 0, NOT_ALL_PRIVATE, 4096, 4, 8466 }, - }, - { /* 25 */ - "zero-size overflow", - "#ASNs = 0, data = seq(8466 3 52737 4096 3456)", - { 0x2,0x0, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x0d,0x80 }, - 12, - { NULL, NULL, - 0, 0, 0, 0, 0, 0 }, - }, - { /* 26 */ - "zero-size overflow + valid segment", - "seq(#AS=0:8466 3 52737),seq(4096 3456)", - { 0x2,0x0, 0x21,0x12, 0x00,0x03, 0xce,0x01, - 0x2,0x2, 0x10,0x00, 0x0d,0x80 }, - 14 - , - { NULL, NULL, - 0, 0, 0, 0, 0, 0 }, - }, - { /* 27 */ - "invalid segment type", - "type=8(4096 3456)", - { 0x8,0x2, 0x10,0x00, 0x0d,0x80 }, - 14 - , - { NULL, NULL, - 0, 0, 0, 0, 0, 0 }, - }, { NULL, NULL, {0}, 0, { NULL, 0, 0 } } -}; + const char *name; + const char *desc; + const u_char asdata[1024]; + int len; + struct test_spec sp; +} test_segments[] = { + { + /* 0 */ + "seq1", + "seq(8466,3,52737,4096)", + {0x2, 0x4, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00}, + 10, + {"8466 3 52737 4096", "8466 3 52737 4096", 4, 0, + NOT_ALL_PRIVATE, 4096, 4, 8466}, + }, + { + /* 1 */ + "seq2", + "seq(8722) seq(4)", + {0x2, 0x1, 0x22, 0x12, 0x2, 0x1, 0x00, 0x04}, + 8, + { + "8722 4", "8722 4", 2, 0, NOT_ALL_PRIVATE, 4, 5, 8722, + }, + }, + { + /* 2 */ + "seq3", + "seq(8466,3,52737,4096,8722,4)", + {0x2, 0x6, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x22, + 0x12, 0x00, 0x04}, + 14, + {"8466 3 52737 4096 8722 4", "8466 3 52737 4096 8722 4", 6, 0, + NOT_ALL_PRIVATE, 3, 5, 8466}, + }, + { + /* 3 */ + "seqset", + "seq(8482,51457) set(5204)", + {0x2, 0x2, 0x21, 0x22, 0xc9, 0x01, 0x1, 0x1, 0x14, 0x54}, + 10, + {"8482 51457 {5204}", "8482 51457 {5204}", 3, 0, + NOT_ALL_PRIVATE, 5204, 51456, 8482}, + }, + { + /* 4 */ + "seqset2", + "seq(8467, 59649) set(4196,48658) set(17322,30745)", + {0x2, 0x2, 0x21, 0x13, 0xe9, 0x01, 0x1, 0x2, 0x10, 0x64, 0xbe, + 0x12, 0x1, 0x2, 0x43, 0xaa, 0x78, 0x19}, + 18, + {"8467 59649 {4196,48658} {17322,30745}", + "8467 59649 {4196,48658} {17322,30745}", 4, 0, NOT_ALL_PRIVATE, + 48658, 1, 8467}, + }, + { + /* 5 */ + "multi", + "seq(6435,59408,21665) set(2457,61697,4369), seq(1842,41590,51793)", + {0x2, 0x3, 0x19, 0x23, 0xe8, 0x10, 0x54, 0xa1, + 0x1, 0x3, 0x09, 0x99, 0xf1, 0x01, 0x11, 0x11, + 0x2, 0x3, 0x07, 0x32, 0xa2, 0x76, 0xca, 0x51}, + 24, + {"6435 59408 21665 {2457,4369,61697} 1842 41590 51793", + "6435 59408 21665 {2457,4369,61697} 1842 41590 51793", 7, 0, + NOT_ALL_PRIVATE, 51793, 1, 6435}, + }, + { + /* 6 */ + "confed", + "confseq(123,456,789)", + {0x3, 0x3, 0x00, 0x7b, 0x01, 0xc8, 0x03, 0x15}, + 8, + {"(123 456 789)", "", 0, 3, NOT_ALL_PRIVATE, 789, 1, NULL_ASN}, + }, + { + /* 7 */ + "confed2", + "confseq(123,456,789) confseq(111,222)", + {0x3, 0x3, 0x00, 0x7b, 0x01, 0xc8, 0x03, 0x15, 0x3, 0x2, 0x00, + 0x6f, 0x00, 0xde}, + 14, + {"(123 456 789) (111 222)", "", 0, 5, NOT_ALL_PRIVATE, 111, 1, + NULL_ASN}, + }, + { + /* 8 */ + "confset", + "confset(456,123,789)", + {0x4, 0x3, 0x01, 0xc8, 0x00, 0x7b, 0x03, 0x15}, + 8, + {"[123,456,789]", "", 0, 1, NOT_ALL_PRIVATE, 123, 1, NULL_ASN}, + }, + { + /* 9 */ + "confmulti", + "confseq(123,456,789) confset(222,111) seq(8722) set(4196,48658)", + {0x3, 0x3, 0x00, 0x7b, 0x01, 0xc8, 0x03, 0x15, + 0x4, 0x2, 0x00, 0xde, 0x00, 0x6f, 0x2, 0x1, + 0x22, 0x12, 0x1, 0x2, 0x10, 0x64, 0xbe, 0x12}, + 24, + {"(123 456 789) [111,222] 8722 {4196,48658}", + "8722 {4196,48658}", 2, 4, NOT_ALL_PRIVATE, 123, 1, NULL_ASN}, + }, + { + /* 10 */ + "seq4", + "seq(8466,2,52737,4096,8722,4)", + {0x2, 0x6, 0x21, 0x12, 0x00, 0x02, 0xce, 0x01, 0x10, 0x00, 0x22, + 0x12, 0x00, 0x04}, + 14, + {"8466 2 52737 4096 8722 4", "8466 2 52737 4096 8722 4", 6, 0, + NOT_ALL_PRIVATE, 4096, 1, 8466}, + }, + { + /* 11 */ + "tripleseq1", + "seq(8466,2,52737) seq(4096,8722,4) seq(8722)", + {0x2, 0x3, 0x21, 0x12, 0x00, 0x02, 0xce, 0x01, 0x2, 0x3, + 0x10, 0x00, 0x22, 0x12, 0x00, 0x04, 0x2, 0x1, 0x22, 0x12}, + 20, + {"8466 2 52737 4096 8722 4 8722", + "8466 2 52737 4096 8722 4 8722", 7, 0, NOT_ALL_PRIVATE, 4096, + 1, 8466}, + }, + { + /* 12 */ + "someprivate", + "seq(8466,64512,52737,65535)", + {0x2, 0x4, 0x21, 0x12, 0xfc, 0x00, 0xce, 0x01, 0xff, 0xff}, + 10, + {"8466 64512 52737 65535", "8466 64512 52737 65535", 4, 0, + NOT_ALL_PRIVATE, 65535, 4, 8466}, + }, + { + /* 13 */ + "allprivate", + "seq(65534,64512,64513,65535)", + {0x2, 0x4, 0xff, 0xfe, 0xfc, 0x00, 0xfc, 0x01, 0xff, 0xff}, + 10, + {"65534 64512 64513 65535", "65534 64512 64513 65535", 4, 0, + ALL_PRIVATE, 65534, 4, 65534}, + }, + { + /* 14 */ + "long", + "seq(8466,3,52737,4096,34285,)", + { + 0x2, 0xfa, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, + 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, + 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, + 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, + 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, + 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, + 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, + 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, + 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, + 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, + 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, + 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, + 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, + 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, + 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, + 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, + 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, + 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, + 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, + 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, + 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, + 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, + 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, + 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, + 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, + 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, + 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, + 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, + 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, + 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, + 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, + 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, + 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, + 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, + 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, + 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, + 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, + 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, + 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, + 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, + 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, + 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, + 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, + 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, + 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, + 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, + 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, + 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, + 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, + 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, + 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, + 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, + 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, 0xce, + 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, 0x03, + 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, 0x21, 0x12, 0x00, + 0x03, 0xce, 0x01, 0x10, 0x00, 0x85, 0xed, + }, + 502, + {"8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285", -#define COMMON_ATTRS \ - BGP_ATTR_FLAG_TRANS, \ - BGP_ATTR_ORIGIN, \ - 1, \ - BGP_ORIGIN_EGP, \ - BGP_ATTR_FLAG_TRANS, \ - BGP_ATTR_NEXT_HOP, \ - 4, 192, 0, 2, 0 + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285", + 250, 0, NOT_ALL_PRIVATE, 4096, 4, 8466}, + }, + { + /* 15 */ + "seq1extra", + "seq(8466,3,52737,4096,3456)", + {0x2, 0x5, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x0d, + 0x80}, + 12, + {"8466 3 52737 4096 3456", "8466 3 52737 4096 3456", 5, 0, + NOT_ALL_PRIVATE, 4096, 4, 8466}, + }, + { + /* 16 */ + "empty", + "", + {}, + 0, + {"", "", 0, 0, 0, 0, 0, 0}, + }, + { + /* 17 */ + "redundantset", + "seq(8466,3,52737,4096,3456) set(7099,8153,8153,8153)", + {0x2, 0x5, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, + 0x10, 0x00, 0x0d, 0x80, 0x1, 0x4, 0x1b, 0xbb, + 0x1f, 0xd9, 0x1f, 0xd9, 0x1f, 0xd9}, + 22, + {/* We shouldn't ever /generate/ such paths. However, we should + * cope with them fine. + */ + "8466 3 52737 4096 3456 {7099,8153}", + "8466 3 52737 4096 3456 {7099,8153}", 6, 0, NOT_ALL_PRIVATE, + 4096, 4, 8466}, + }, + { + /* 18 */ + "reconcile_lead_asp", + "seq(6435,59408,21665) set(23456,23456,23456), seq(23456,23456,23456)", + {0x2, 0x3, 0x19, 0x23, 0xe8, 0x10, 0x54, 0xa1, + 0x1, 0x3, 0x5b, 0xa0, 0x5b, 0xa0, 0x5b, 0xa0, + 0x2, 0x3, 0x5b, 0xa0, 0x5b, 0xa0, 0x5b, 0xa0}, + 24, + {"6435 59408 21665 {23456} 23456 23456 23456", + "6435 59408 21665 {23456} 23456 23456 23456", 7, 0, + NOT_ALL_PRIVATE, 23456, 1, 6435}, + }, + { + /* 19 */ + "reconcile_new_asp", + "set(2457,61697,4369), seq(1842,41591,51793)", + {0x1, 0x3, 0x09, 0x99, 0xf1, 0x01, 0x11, 0x11, 0x2, 0x3, 0x07, + 0x32, 0xa2, 0x77, 0xca, 0x51}, + 16, + {"{2457,4369,61697} 1842 41591 51793", + "{2457,4369,61697} 1842 41591 51793", 4, 0, NOT_ALL_PRIVATE, + 51793, 1, 2457}, + }, + { + /* 20 */ + "reconcile_confed", + "confseq(123,456,789) confset(456,124,788) seq(6435,59408,21665)" + " set(23456,23456,23456), seq(23456,23456,23456)", + {0x3, 0x3, 0x00, 0x7b, 0x01, 0xc8, 0x03, 0x15, 0x4, 0x3, + 0x01, 0xc8, 0x00, 0x7c, 0x03, 0x14, 0x2, 0x3, 0x19, 0x23, + 0xe8, 0x10, 0x54, 0xa1, 0x1, 0x3, 0x5b, 0xa0, 0x5b, 0xa0, + 0x5b, 0xa0, 0x2, 0x3, 0x5b, 0xa0, 0x5b, 0xa0, 0x5b, 0xa0}, + 40, + {"(123 456 789) [124,456,788] 6435 59408 21665" + " {23456} 23456 23456 23456", + "6435 59408 21665 {23456} 23456 23456 23456", 7, 4, + NOT_ALL_PRIVATE, 23456, 1, 6435}, + }, + { + /* 21 */ + "reconcile_start_trans", + "seq(23456,23456,23456) seq(6435,59408,21665)", + { + 0x2, 0x3, 0x5b, 0xa0, 0x5b, 0xa0, 0x5b, 0xa0, 0x2, 0x3, + 0x19, 0x23, 0xe8, 0x10, 0x54, 0xa1, + }, + 16, + {"23456 23456 23456 6435 59408 21665", + "23456 23456 23456 6435 59408 21665", 6, 0, NOT_ALL_PRIVATE, + 21665, 1, 23456}, + }, + { + /* 22 */ + "reconcile_start_trans4", + "seq(1842,41591,51793) seq(6435,59408,21665)", + { + 0x2, 0x3, 0x07, 0x32, 0xa2, 0x77, 0xca, 0x51, 0x2, 0x3, + 0x19, 0x23, 0xe8, 0x10, 0x54, 0xa1, + }, + 16, + {"1842 41591 51793 6435 59408 21665", + "1842 41591 51793 6435 59408 21665", 6, 0, NOT_ALL_PRIVATE, + 41591, 1, 1842}, + }, + { + /* 23 */ + "reconcile_start_trans_error", + "seq(23456,23456,23456) seq(6435,59408)", + { + 0x2, 0x3, 0x5b, 0xa0, 0x5b, 0xa0, 0x5b, 0xa0, 0x2, 0x2, + 0x19, 0x23, 0xe8, 0x10, + }, + 14, + {"23456 23456 23456 6435 59408", "23456 23456 23456 6435 59408", + 5, 0, NOT_ALL_PRIVATE, 59408, 1, 23456}, + }, + { + /* 24 */ + "redundantset2", + "seq(8466,3,52737,4096,3456) set(7099,8153,8153,8153,7099)", + { + 0x2, 0x5, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, + 0x10, 0x00, 0x0d, 0x80, 0x1, 0x5, 0x1b, 0xbb, + 0x1f, 0xd9, 0x1f, 0xd9, 0x1f, 0xd9, 0x1b, 0xbb, + }, + 24, + {/* We should weed out duplicate set members. */ + "8466 3 52737 4096 3456 {7099,8153}", + "8466 3 52737 4096 3456 {7099,8153}", 6, 0, NOT_ALL_PRIVATE, + 4096, 4, 8466}, + }, + { + /* 25 */ + "zero-size overflow", + "#ASNs = 0, data = seq(8466 3 52737 4096 3456)", + {0x2, 0x0, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x0d, + 0x80}, + 12, + {NULL, NULL, 0, 0, 0, 0, 0, 0}, + }, + { + /* 26 */ + "zero-size overflow + valid segment", + "seq(#AS=0:8466 3 52737),seq(4096 3456)", + {0x2, 0x0, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x2, 0x2, 0x10, + 0x00, 0x0d, 0x80}, + 14, + {NULL, NULL, 0, 0, 0, 0, 0, 0}, + }, + { + /* 27 */ + "invalid segment type", + "type=8(4096 3456)", + {0x8, 0x2, 0x10, 0x00, 0x0d, 0x80}, + 14, + {NULL, NULL, 0, 0, 0, 0, 0, 0}, + }, + {NULL, NULL, {0}, 0, {NULL, 0, 0}}}; + +#define COMMON_ATTRS \ + BGP_ATTR_FLAG_TRANS, BGP_ATTR_ORIGIN, 1, BGP_ORIGIN_EGP, \ + BGP_ATTR_FLAG_TRANS, BGP_ATTR_NEXT_HOP, 4, 192, 0, 2, 0 #define COMMON_ATTR_SIZE 11 /* */ static struct aspath_tests { - const char *desc; - const struct test_segment *segment; - const char *shouldbe; /* String it should evaluate to */ - const enum as4 { AS4_DATA, AS2_DATA } - as4; /* whether data should be as4 or not (ie as2) */ - const int result; /* expected result for bgp_attr_parse */ - const int cap; /* capabilities to set for peer */ - const char attrheader [1024]; - size_t len; - const struct test_segment *old_segment; -} aspath_tests [] = -{ - /* 0 */ - { - "basic test", - &test_segments[0], - "8466 3 52737 4096", - AS2_DATA, 0, - 0, - { COMMON_ATTRS, - BGP_ATTR_FLAG_TRANS, - BGP_ATTR_AS_PATH, - 10, - }, - COMMON_ATTR_SIZE + 3, - }, - /* 1 */ - { - "length too short", - &test_segments[0], - "8466 3 52737 4096", - AS2_DATA, -1, - 0, - { COMMON_ATTRS, - BGP_ATTR_FLAG_TRANS, - BGP_ATTR_AS_PATH, - 8, - }, - COMMON_ATTR_SIZE + 3, - }, - /* 2 */ - { - "length too long", - &test_segments[0], - "8466 3 52737 4096", - AS2_DATA, -1, - 0, - { COMMON_ATTRS, - BGP_ATTR_FLAG_TRANS, - BGP_ATTR_AS_PATH, - 12, - }, - COMMON_ATTR_SIZE + 3, - }, - /* 3 */ - { - "incorrect flag", - &test_segments[0], - "8466 3 52737 4096", - AS2_DATA, -1, - 0, - { COMMON_ATTRS, - BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL, - BGP_ATTR_AS_PATH, - 10, - }, - COMMON_ATTR_SIZE + 3, - }, - /* 4 */ - { - "as4_path, with as2 format data", - &test_segments[0], - "8466 3 52737 4096", - AS2_DATA, -1, - 0, - { COMMON_ATTRS, - BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL, - BGP_ATTR_AS4_PATH, - 10, - }, - COMMON_ATTR_SIZE + 3, - }, - /* 5 */ - { - "as4, with incorrect attr length", - &test_segments[0], - "8466 3 52737 4096", - AS4_DATA, -1, - PEER_CAP_AS4_RCV, - { COMMON_ATTRS, - BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL, - BGP_ATTR_AS4_PATH, - 10, - }, - COMMON_ATTR_SIZE + 3, - }, - /* 6 */ - { - "basic 4-byte as-path", - &test_segments[0], - "8466 3 52737 4096", - AS4_DATA, 0, - PEER_CAP_AS4_RCV|PEER_CAP_AS4_ADV, - { COMMON_ATTRS, - BGP_ATTR_FLAG_TRANS, - BGP_ATTR_AS_PATH, - 18, - }, - COMMON_ATTR_SIZE + 3, - }, - /* 7 */ - { - "4b AS_PATH: too short", - &test_segments[0], - "8466 3 52737 4096", - AS4_DATA, -1, - PEER_CAP_AS4_RCV|PEER_CAP_AS4_ADV, - { COMMON_ATTRS, - BGP_ATTR_FLAG_TRANS, - BGP_ATTR_AS_PATH, - 16, - }, - COMMON_ATTR_SIZE + 3, - }, - /* 8 */ - { - "4b AS_PATH: too long", - &test_segments[0], - "8466 3 52737 4096", - AS4_DATA, -1, - PEER_CAP_AS4_RCV|PEER_CAP_AS4_ADV, - { COMMON_ATTRS, - BGP_ATTR_FLAG_TRANS, - BGP_ATTR_AS_PATH, - 20, - }, - COMMON_ATTR_SIZE + 3, - }, - /* 9 */ - { - "4b AS_PATH: too long2", - &test_segments[0], - "8466 3 52737 4096", - AS4_DATA, -1, - PEER_CAP_AS4_RCV|PEER_CAP_AS4_ADV, - { COMMON_ATTRS, - BGP_ATTR_FLAG_TRANS, - BGP_ATTR_AS_PATH, - 22, - }, - COMMON_ATTR_SIZE + 3, - }, - /* 10 */ - { - "4b AS_PATH: bad flags", - &test_segments[0], - "8466 3 52737 4096", - AS4_DATA, -1, - PEER_CAP_AS4_RCV|PEER_CAP_AS4_ADV, - { COMMON_ATTRS, - BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL, - BGP_ATTR_AS_PATH, - 18, - }, - COMMON_ATTR_SIZE + 3, - }, - /* 11 */ - { - "4b AS4_PATH w/o AS_PATH", - &test_segments[6], - NULL, - AS4_DATA, -1, - PEER_CAP_AS4_ADV, - { COMMON_ATTRS, - BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL, - BGP_ATTR_AS4_PATH, - 14, - }, - COMMON_ATTR_SIZE + 3, - }, - /* 12 */ - { - "4b AS4_PATH: confed", - &test_segments[6], - "8466 3 52737 4096 (123 456 789)", - AS4_DATA, 0, - PEER_CAP_AS4_ADV, - { COMMON_ATTRS, - BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL, - BGP_ATTR_AS4_PATH, - 14, - }, - COMMON_ATTR_SIZE + 3, - &test_segments[0], - }, - { NULL, NULL, NULL, 0, 0, 0, { 0 }, 0 }, + const char *desc; + const struct test_segment *segment; + const char *shouldbe; /* String it should evaluate to */ + const enum as4 { + AS4_DATA, + AS2_DATA + } as4; /* whether data should be as4 or not (ie as2) */ + const int result; /* expected result for bgp_attr_parse */ + const int cap; /* capabilities to set for peer */ + const char attrheader[1024]; + size_t len; + const struct test_segment *old_segment; +} aspath_tests[] = { + /* 0 */ + { + "basic test", + &test_segments[0], + "8466 3 52737 4096", + AS2_DATA, + 0, + 0, + { + COMMON_ATTRS, BGP_ATTR_FLAG_TRANS, BGP_ATTR_AS_PATH, 10, + }, + COMMON_ATTR_SIZE + 3, + }, + /* 1 */ + { + "length too short", + &test_segments[0], + "8466 3 52737 4096", + AS2_DATA, + -1, + 0, + { + COMMON_ATTRS, BGP_ATTR_FLAG_TRANS, BGP_ATTR_AS_PATH, 8, + }, + COMMON_ATTR_SIZE + 3, + }, + /* 2 */ + { + "length too long", + &test_segments[0], + "8466 3 52737 4096", + AS2_DATA, + -1, + 0, + { + COMMON_ATTRS, BGP_ATTR_FLAG_TRANS, BGP_ATTR_AS_PATH, 12, + }, + COMMON_ATTR_SIZE + 3, + }, + /* 3 */ + { + "incorrect flag", + &test_segments[0], + "8466 3 52737 4096", + AS2_DATA, + -1, + 0, + { + COMMON_ATTRS, + BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_AS_PATH, 10, + }, + COMMON_ATTR_SIZE + 3, + }, + /* 4 */ + { + "as4_path, with as2 format data", + &test_segments[0], + "8466 3 52737 4096", + AS2_DATA, + -1, + 0, + { + COMMON_ATTRS, + BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_AS4_PATH, 10, + }, + COMMON_ATTR_SIZE + 3, + }, + /* 5 */ + { + "as4, with incorrect attr length", + &test_segments[0], + "8466 3 52737 4096", + AS4_DATA, + -1, + PEER_CAP_AS4_RCV, + { + COMMON_ATTRS, + BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_AS4_PATH, 10, + }, + COMMON_ATTR_SIZE + 3, + }, + /* 6 */ + { + "basic 4-byte as-path", + &test_segments[0], + "8466 3 52737 4096", + AS4_DATA, + 0, + PEER_CAP_AS4_RCV | PEER_CAP_AS4_ADV, + { + COMMON_ATTRS, BGP_ATTR_FLAG_TRANS, BGP_ATTR_AS_PATH, 18, + }, + COMMON_ATTR_SIZE + 3, + }, + /* 7 */ + { + "4b AS_PATH: too short", + &test_segments[0], + "8466 3 52737 4096", + AS4_DATA, + -1, + PEER_CAP_AS4_RCV | PEER_CAP_AS4_ADV, + { + COMMON_ATTRS, BGP_ATTR_FLAG_TRANS, BGP_ATTR_AS_PATH, 16, + }, + COMMON_ATTR_SIZE + 3, + }, + /* 8 */ + { + "4b AS_PATH: too long", + &test_segments[0], + "8466 3 52737 4096", + AS4_DATA, + -1, + PEER_CAP_AS4_RCV | PEER_CAP_AS4_ADV, + { + COMMON_ATTRS, BGP_ATTR_FLAG_TRANS, BGP_ATTR_AS_PATH, 20, + }, + COMMON_ATTR_SIZE + 3, + }, + /* 9 */ + { + "4b AS_PATH: too long2", + &test_segments[0], + "8466 3 52737 4096", + AS4_DATA, + -1, + PEER_CAP_AS4_RCV | PEER_CAP_AS4_ADV, + { + COMMON_ATTRS, BGP_ATTR_FLAG_TRANS, BGP_ATTR_AS_PATH, 22, + }, + COMMON_ATTR_SIZE + 3, + }, + /* 10 */ + { + "4b AS_PATH: bad flags", + &test_segments[0], + "8466 3 52737 4096", + AS4_DATA, + -1, + PEER_CAP_AS4_RCV | PEER_CAP_AS4_ADV, + { + COMMON_ATTRS, + BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_AS_PATH, 18, + }, + COMMON_ATTR_SIZE + 3, + }, + /* 11 */ + { + "4b AS4_PATH w/o AS_PATH", + &test_segments[6], + NULL, + AS4_DATA, + -1, + PEER_CAP_AS4_ADV, + { + COMMON_ATTRS, + BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_AS4_PATH, 14, + }, + COMMON_ATTR_SIZE + 3, + }, + /* 12 */ + { + "4b AS4_PATH: confed", + &test_segments[6], + "8466 3 52737 4096 (123 456 789)", + AS4_DATA, + 0, + PEER_CAP_AS4_ADV, + { + COMMON_ATTRS, + BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_AS4_PATH, 14, + }, + COMMON_ATTR_SIZE + 3, + &test_segments[0], + }, + {NULL, NULL, NULL, 0, 0, 0, {0}, 0}, }; /* prepending tests */ static struct tests { - const struct test_segment *test1; - const struct test_segment *test2; - struct test_spec sp; -} prepend_tests[] = -{ - /* 0 */ - { &test_segments[0], &test_segments[1], - { "8466 3 52737 4096 8722 4", - "8466 3 52737 4096 8722 4", - 6, 0, NOT_ALL_PRIVATE, 4096, 1, 8466 }, - }, - /* 1 */ - { &test_segments[1], &test_segments[3], - { "8722 4 8482 51457 {5204}", - "8722 4 8482 51457 {5204}", - 5, 0, NOT_ALL_PRIVATE, 5204, 1, 8722 } - }, - /* 2 */ - { &test_segments[3], &test_segments[4], - { "8482 51457 {5204} 8467 59649 {4196,48658} {17322,30745}", - "8482 51457 {5204} 8467 59649 {4196,48658} {17322,30745}", - 7, 0, NOT_ALL_PRIVATE, 5204, 1, 8482 }, - }, - /* 3 */ - { &test_segments[4], &test_segments[5], - { "8467 59649 {4196,48658} {17322,30745} 6435 59408 21665" - " {2457,4369,61697} 1842 41590 51793", - "8467 59649 {4196,48658} {17322,30745} 6435 59408 21665" - " {2457,4369,61697} 1842 41590 51793", - 11, 0, NOT_ALL_PRIVATE, 61697, 1, 8467 } - }, - /* 4 */ - { &test_segments[5], &test_segments[6], - { "6435 59408 21665 {2457,4369,61697} 1842 41590 51793", - "6435 59408 21665 {2457,4369,61697} 1842 41590 51793", - 7, 0, NOT_ALL_PRIVATE, 1842, 1, 6435 }, - }, - /* 5 */ - { &test_segments[6], &test_segments[7], - { "(123 456 789) (123 456 789) (111 222)", - "", - 0, 8, NOT_ALL_PRIVATE, 111, 1, 0 } - }, - { &test_segments[7], &test_segments[8], - { "(123 456 789) (111 222) [123,456,789]", - "", - 0, 6, NOT_ALL_PRIVATE, 111, 1, 0 } - }, - { &test_segments[8], &test_segments[9], - { "[123,456,789] (123 456 789) [111,222] 8722 {4196,48658}", - "8722 {4196,48658}", - 2, 5, NOT_ALL_PRIVATE, 456, 1, NULL_ASN }, - }, - { &test_segments[9], &test_segments[8], - { "(123 456 789) [111,222] 8722 {4196,48658} [123,456,789]", - "8722 {4196,48658}", - 2, 5, NOT_ALL_PRIVATE, 48658, 1, NULL_ASN }, - }, - { &test_segments[14], &test_segments[11], - { "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 2 52737 4096 8722 4 8722", - - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " - "8466 2 52737 4096 8722 4 8722", - 257, 0, NOT_ALL_PRIVATE, 4096, 1000, 8466 }, - }, - { NULL, NULL, { NULL, 0, 0, 0, 0, 0, 0, } }, + const struct test_segment *test1; + const struct test_segment *test2; + struct test_spec sp; +} prepend_tests[] = { + /* 0 */ + { + &test_segments[0], + &test_segments[1], + {"8466 3 52737 4096 8722 4", "8466 3 52737 4096 8722 4", 6, 0, + NOT_ALL_PRIVATE, 4096, 1, 8466}, + }, + /* 1 */ + {&test_segments[1], + &test_segments[3], + {"8722 4 8482 51457 {5204}", "8722 4 8482 51457 {5204}", 5, 0, + NOT_ALL_PRIVATE, 5204, 1, 8722}}, + /* 2 */ + { + &test_segments[3], + &test_segments[4], + {"8482 51457 {5204} 8467 59649 {4196,48658} {17322,30745}", + "8482 51457 {5204} 8467 59649 {4196,48658} {17322,30745}", 7, + 0, NOT_ALL_PRIVATE, 5204, 1, 8482}, + }, + /* 3 */ + {&test_segments[4], + &test_segments[5], + {"8467 59649 {4196,48658} {17322,30745} 6435 59408 21665" + " {2457,4369,61697} 1842 41590 51793", + "8467 59649 {4196,48658} {17322,30745} 6435 59408 21665" + " {2457,4369,61697} 1842 41590 51793", + 11, 0, NOT_ALL_PRIVATE, 61697, 1, 8467}}, + /* 4 */ + { + &test_segments[5], + &test_segments[6], + {"6435 59408 21665 {2457,4369,61697} 1842 41590 51793", + "6435 59408 21665 {2457,4369,61697} 1842 41590 51793", 7, 0, + NOT_ALL_PRIVATE, 1842, 1, 6435}, + }, + /* 5 */ + {&test_segments[6], + &test_segments[7], + {"(123 456 789) (123 456 789) (111 222)", "", 0, 8, NOT_ALL_PRIVATE, + 111, 1, 0}}, + {&test_segments[7], + &test_segments[8], + {"(123 456 789) (111 222) [123,456,789]", "", 0, 6, NOT_ALL_PRIVATE, + 111, 1, 0}}, + { + &test_segments[8], + &test_segments[9], + {"[123,456,789] (123 456 789) [111,222] 8722 {4196,48658}", + "8722 {4196,48658}", 2, 5, NOT_ALL_PRIVATE, 456, 1, NULL_ASN}, + }, + { + &test_segments[9], + &test_segments[8], + {"(123 456 789) [111,222] 8722 {4196,48658} [123,456,789]", + "8722 {4196,48658}", 2, 5, NOT_ALL_PRIVATE, 48658, 1, + NULL_ASN}, + }, + { + &test_segments[14], + &test_segments[11], + {"8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 2 52737 4096 8722 4 8722", + + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " + "8466 2 52737 4096 8722 4 8722", + 257, 0, NOT_ALL_PRIVATE, 4096, 1000, 8466}, + }, + {NULL, + NULL, + { + NULL, 0, 0, 0, 0, 0, 0, + }}, }; -struct tests reconcile_tests[] = -{ - { &test_segments[18], &test_segments[19], - { "6435 59408 21665 {2457,4369,61697} 1842 41591 51793", - "6435 59408 21665 {2457,4369,61697} 1842 41591 51793", - 7, 0, NOT_ALL_PRIVATE, 51793, 1, 6435 }, - }, - { &test_segments[19], &test_segments[18], - /* AS_PATH (19) has more hops than NEW_AS_PATH, - * so just AS_PATH should be used (though, this practice - * is bad imho). - */ - { "{2457,4369,61697} 1842 41591 51793 6435 59408 21665 {23456} 23456 23456 23456", - "{2457,4369,61697} 1842 41591 51793 6435 59408 21665 {23456} 23456 23456 23456", - 11, 0, NOT_ALL_PRIVATE, 51793, 1, 6435 }, - }, - { &test_segments[20], &test_segments[19], - { "(123 456 789) [124,456,788] 6435 59408 21665" - " {2457,4369,61697} 1842 41591 51793", - "6435 59408 21665 {2457,4369,61697} 1842 41591 51793", - 7, 4, NOT_ALL_PRIVATE, 51793, 1, 6435 }, - }, - { &test_segments[21], &test_segments[22], - { "1842 41591 51793 6435 59408 21665", - "1842 41591 51793 6435 59408 21665", - 6, 0, NOT_ALL_PRIVATE, 51793, 1, 1842 }, - }, - { &test_segments[23], &test_segments[22], - { "23456 23456 23456 6435 59408 1842 41591 51793 6435 59408 21665", - "23456 23456 23456 6435 59408 1842 41591 51793 6435 59408 21665", - 11, 0, NOT_ALL_PRIVATE, 51793, 1, 1842 }, - }, - { NULL, NULL, { NULL, 0, 0, 0, 0, 0, 0, } }, +struct tests reconcile_tests[] = { + { + &test_segments[18], + &test_segments[19], + {"6435 59408 21665 {2457,4369,61697} 1842 41591 51793", + "6435 59408 21665 {2457,4369,61697} 1842 41591 51793", 7, 0, + NOT_ALL_PRIVATE, 51793, 1, 6435}, + }, + { + &test_segments[19], + &test_segments[18], + /* AS_PATH (19) has more hops than NEW_AS_PATH, + * so just AS_PATH should be used (though, this practice + * is bad imho). + */ + {"{2457,4369,61697} 1842 41591 51793 6435 59408 21665 {23456} 23456 23456 23456", + "{2457,4369,61697} 1842 41591 51793 6435 59408 21665 {23456} 23456 23456 23456", + 11, 0, NOT_ALL_PRIVATE, 51793, 1, 6435}, + }, + { + &test_segments[20], + &test_segments[19], + {"(123 456 789) [124,456,788] 6435 59408 21665" + " {2457,4369,61697} 1842 41591 51793", + "6435 59408 21665 {2457,4369,61697} 1842 41591 51793", 7, 4, + NOT_ALL_PRIVATE, 51793, 1, 6435}, + }, + { + &test_segments[21], + &test_segments[22], + {"1842 41591 51793 6435 59408 21665", + "1842 41591 51793 6435 59408 21665", 6, 0, NOT_ALL_PRIVATE, + 51793, 1, 1842}, + }, + { + &test_segments[23], + &test_segments[22], + {"23456 23456 23456 6435 59408 1842 41591 51793 6435 59408 21665", + "23456 23456 23456 6435 59408 1842 41591 51793 6435 59408 21665", + 11, 0, NOT_ALL_PRIVATE, 51793, 1, 1842}, + }, + {NULL, + NULL, + { + NULL, 0, 0, 0, 0, 0, 0, + }}, }; - -struct tests aggregate_tests[] = -{ - { &test_segments[0], &test_segments[2], - { "8466 3 52737 4096 {4,8722}", - "8466 3 52737 4096 {4,8722}", - 5, 0, NOT_ALL_PRIVATE, 4, 1, 8466 }, - }, - { &test_segments[2], &test_segments[0], - { "8466 3 52737 4096 {4,8722}", - "8466 3 52737 4096 {4,8722}", - 5, 0, NOT_ALL_PRIVATE, 8722, 1, 8466 }, - }, - { &test_segments[2], &test_segments[10], - { "8466 {2,3,4,4096,8722,52737}", - "8466 {2,3,4,4096,8722,52737}", - 2, 0, NOT_ALL_PRIVATE, 8722, 5, 8466 }, - }, - { &test_segments[10], &test_segments[2], - { "8466 {2,3,4,4096,8722,52737}", - "8466 {2,3,4,4096,8722,52737}", - 2, 0, NOT_ALL_PRIVATE, 2, 20000, 8466 }, - }, - - { &test_segments[5], &test_segments[18], - { "6435 59408 21665 {1842,2457,4369,23456,41590,51793,61697}", - "6435 59408 21665 {1842,2457,4369,23456,41590,51793,61697}", - 4, 0, NOT_ALL_PRIVATE, 41590, 1, 6435 }, - }, - - { NULL, NULL, { NULL, 0, 0} }, + +struct tests aggregate_tests[] = { + { + &test_segments[0], + &test_segments[2], + {"8466 3 52737 4096 {4,8722}", "8466 3 52737 4096 {4,8722}", 5, + 0, NOT_ALL_PRIVATE, 4, 1, 8466}, + }, + { + &test_segments[2], + &test_segments[0], + {"8466 3 52737 4096 {4,8722}", "8466 3 52737 4096 {4,8722}", 5, + 0, NOT_ALL_PRIVATE, 8722, 1, 8466}, + }, + { + &test_segments[2], + &test_segments[10], + {"8466 {2,3,4,4096,8722,52737}", "8466 {2,3,4,4096,8722,52737}", + 2, 0, NOT_ALL_PRIVATE, 8722, 5, 8466}, + }, + { + &test_segments[10], + &test_segments[2], + {"8466 {2,3,4,4096,8722,52737}", "8466 {2,3,4,4096,8722,52737}", + 2, 0, NOT_ALL_PRIVATE, 2, 20000, 8466}, + }, + + { + &test_segments[5], + &test_segments[18], + {"6435 59408 21665 {1842,2457,4369,23456,41590,51793,61697}", + "6435 59408 21665 {1842,2457,4369,23456,41590,51793,61697}", 4, + 0, NOT_ALL_PRIVATE, 41590, 1, 6435}, + }, + + {NULL, NULL, {NULL, 0, 0}}, }; -struct compare_tests -{ - int test_index1; - int test_index2; +struct compare_tests { + int test_index1; + int test_index2; #define CMP_RES_YES 1 #define CMP_RES_NO 0 - char shouldbe_cmp; - char shouldbe_confed; -} left_compare [] = -{ - { 0, 1, CMP_RES_NO, CMP_RES_NO }, - { 0, 2, CMP_RES_YES, CMP_RES_NO }, - { 0, 11, CMP_RES_YES, CMP_RES_NO }, - { 0, 15, CMP_RES_YES, CMP_RES_NO }, - { 0, 16, CMP_RES_NO, CMP_RES_NO }, - { 1, 11, CMP_RES_NO, CMP_RES_NO }, - { 6, 7, CMP_RES_NO, CMP_RES_YES }, - { 6, 8, CMP_RES_NO, CMP_RES_NO }, - { 7, 8, CMP_RES_NO, CMP_RES_NO }, - { 1, 9, CMP_RES_YES, CMP_RES_NO }, - { 0, 9, CMP_RES_NO, CMP_RES_NO }, - { 3, 9, CMP_RES_NO, CMP_RES_NO }, - { 0, 6, CMP_RES_NO, CMP_RES_NO }, - { 1, 6, CMP_RES_NO, CMP_RES_NO }, - { 0, 8, CMP_RES_NO, CMP_RES_NO }, - { 1, 8, CMP_RES_NO, CMP_RES_NO }, - { 11, 6, CMP_RES_NO, CMP_RES_NO }, - { 11, 7, CMP_RES_NO, CMP_RES_NO }, - { 11, 8, CMP_RES_NO, CMP_RES_NO }, - { 9, 6, CMP_RES_NO, CMP_RES_YES }, - { 9, 7, CMP_RES_NO, CMP_RES_YES }, - { 9, 8, CMP_RES_NO, CMP_RES_NO }, + char shouldbe_cmp; + char shouldbe_confed; +} left_compare[] = { + {0, 1, CMP_RES_NO, CMP_RES_NO}, {0, 2, CMP_RES_YES, CMP_RES_NO}, + {0, 11, CMP_RES_YES, CMP_RES_NO}, {0, 15, CMP_RES_YES, CMP_RES_NO}, + {0, 16, CMP_RES_NO, CMP_RES_NO}, {1, 11, CMP_RES_NO, CMP_RES_NO}, + {6, 7, CMP_RES_NO, CMP_RES_YES}, {6, 8, CMP_RES_NO, CMP_RES_NO}, + {7, 8, CMP_RES_NO, CMP_RES_NO}, {1, 9, CMP_RES_YES, CMP_RES_NO}, + {0, 9, CMP_RES_NO, CMP_RES_NO}, {3, 9, CMP_RES_NO, CMP_RES_NO}, + {0, 6, CMP_RES_NO, CMP_RES_NO}, {1, 6, CMP_RES_NO, CMP_RES_NO}, + {0, 8, CMP_RES_NO, CMP_RES_NO}, {1, 8, CMP_RES_NO, CMP_RES_NO}, + {11, 6, CMP_RES_NO, CMP_RES_NO}, {11, 7, CMP_RES_NO, CMP_RES_NO}, + {11, 8, CMP_RES_NO, CMP_RES_NO}, {9, 6, CMP_RES_NO, CMP_RES_YES}, + {9, 7, CMP_RES_NO, CMP_RES_YES}, {9, 8, CMP_RES_NO, CMP_RES_NO}, }; /* make an aspath from a data stream */ -static struct aspath * -make_aspath (const u_char *data, size_t len, int use32bit) +static struct aspath *make_aspath(const u_char *data, size_t len, int use32bit) { - struct stream *s = NULL; - struct aspath *as; - - if (len) - { - s = stream_new (len); - stream_put (s, data, len); - } - as = aspath_parse (s, len, use32bit); - - if (s) - stream_free (s); - - return as; + struct stream *s = NULL; + struct aspath *as; + + if (len) { + s = stream_new(len); + stream_put(s, data, len); + } + as = aspath_parse(s, len, use32bit); + + if (s) + stream_free(s); + + return as; } -static void -printbytes (const u_char *bytes, int len) +static void printbytes(const u_char *bytes, int len) { - int i = 0; - while (i < len) - { - if (i % 2) - printf ("%02hhx%s", bytes[i], " "); - else - printf ("0x%02hhx", bytes[i]); - i++; - } - printf ("\n"); -} + int i = 0; + while (i < len) { + if (i % 2) + printf("%02hhx%s", bytes[i], " "); + else + printf("0x%02hhx", bytes[i]); + i++; + } + printf("\n"); +} /* validate the given aspath */ -static int -validate (struct aspath *as, const struct test_spec *sp) +static int validate(struct aspath *as, const struct test_spec *sp) { - size_t bytes, bytes4; - int fails = 0; - const u_char *out; - static struct stream *s; - struct aspath *asinout, *asconfeddel, *asstr, *as4; - - if (as == NULL && sp->shouldbe == NULL) - { - printf ("Correctly failed to parse\n"); - return fails; - } - - out = aspath_snmp_pathseg (as, &bytes); - asinout = make_aspath (out, bytes, 0); - - /* Excercise AS4 parsing a bit, with a dogfood test */ - if (!s) - s = stream_new (4096); - bytes4 = aspath_put (s, as, 1); - as4 = make_aspath (STREAM_DATA(s), bytes4, 1); - - asstr = aspath_str2aspath (sp->shouldbe); - - asconfeddel = aspath_delete_confed_seq (aspath_dup (asinout)); - - printf ("got: %s\n", aspath_print(as)); - - /* the parsed path should match the specified 'shouldbe' string. - * We should pass the "eat our own dog food" test, be able to output - * this path and then input it again. Ie the path resulting from: - * - * aspath_parse(aspath_put(as)) - * - * should: - * - * - also match the specified 'shouldbe' value - * - hash to same value as original path - * - have same hops and confed counts as original, and as the - * the specified counts - * - * aspath_str2aspath() and shouldbe should match - * - * We do the same for: - * - * aspath_parse(aspath_put(as,USE32BIT)) - * - * Confederation related tests: - * - aspath_delete_confed_seq(aspath) should match shouldbe_confed - * - aspath_delete_confed_seq should be idempotent. - */ - if (strcmp(aspath_print (as), sp->shouldbe) - /* hash validation */ - || (aspath_key_make (as) != aspath_key_make (asinout)) - /* by string */ - || strcmp(aspath_print (asinout), sp->shouldbe) - /* By 4-byte parsing */ - || strcmp(aspath_print (as4), sp->shouldbe) - /* by various path counts */ - || (aspath_count_hops (as) != sp->hops) - || (aspath_count_confeds (as) != sp->confeds) - || (aspath_count_hops (asinout) != sp->hops) - || (aspath_count_confeds (asinout) != sp->confeds)) - { - failed++; - fails++; - printf ("shouldbe:\n%s\n", sp->shouldbe); - printf ("as4:\n%s\n", aspath_print (as4)); - printf ("hash keys: in: %d out->in: %d\n", - aspath_key_make (as), aspath_key_make (asinout)); - printf ("hops: %d, counted %d %d\n", sp->hops, - aspath_count_hops (as), - aspath_count_hops (asinout) ); - printf ("confeds: %d, counted %d %d\n", sp->confeds, - aspath_count_confeds (as), - aspath_count_confeds (asinout)); - printf ("out->in:\n%s\nbytes: ", aspath_print(asinout)); - printbytes (out, bytes); - } - /* basic confed related tests */ - if ((aspath_print (asconfeddel) == NULL - && sp->shouldbe_delete_confed != NULL) - || (aspath_print (asconfeddel) != NULL - && sp->shouldbe_delete_confed == NULL) - || strcmp(aspath_print (asconfeddel), sp->shouldbe_delete_confed) - /* delete_confed_seq should be idempotent */ - || (aspath_key_make (asconfeddel) - != aspath_key_make (aspath_delete_confed_seq (asconfeddel)))) - { - failed++; - fails++; - printf ("as-path minus confeds is: %s\n", aspath_print (asconfeddel)); - printf ("as-path minus confeds should be: %s\n", sp->shouldbe_delete_confed); - } - /* aspath_str2aspath test */ - if ((aspath_print (asstr) == NULL && sp->shouldbe != NULL) - || (aspath_print (asstr) != NULL && sp->shouldbe == NULL) - || strcmp(aspath_print (asstr), sp->shouldbe)) - { - failed++; - fails++; - printf ("asstr: %s\n", aspath_print (asstr)); - } - - /* loop, private and first as checks */ - if ((sp->does_loop && aspath_loop_check (as, sp->does_loop) == 0) - || (sp->doesnt_loop && aspath_loop_check (as, sp->doesnt_loop) != 0) - || (aspath_private_as_check (as) != sp->private_as) - || (aspath_firstas_check (as,sp->first) - && sp->first == 0)) - { - failed++; - fails++; - printf ("firstas: %d, got %d\n", sp->first, - aspath_firstas_check (as,sp->first)); - printf ("loop does: %d %d, doesnt: %d %d\n", - sp->does_loop, aspath_loop_check (as, sp->does_loop), - sp->doesnt_loop, aspath_loop_check (as, sp->doesnt_loop)); - printf ("private check: %d %d\n", sp->private_as, - aspath_private_as_check (as)); - } - aspath_unintern (&asinout); - aspath_unintern (&as4); - - aspath_free (asconfeddel); - aspath_free (asstr); - stream_reset (s); - - return fails; + size_t bytes, bytes4; + int fails = 0; + const u_char *out; + static struct stream *s; + struct aspath *asinout, *asconfeddel, *asstr, *as4; + + if (as == NULL && sp->shouldbe == NULL) { + printf("Correctly failed to parse\n"); + return fails; + } + + out = aspath_snmp_pathseg(as, &bytes); + asinout = make_aspath(out, bytes, 0); + + /* Excercise AS4 parsing a bit, with a dogfood test */ + if (!s) + s = stream_new(4096); + bytes4 = aspath_put(s, as, 1); + as4 = make_aspath(STREAM_DATA(s), bytes4, 1); + + asstr = aspath_str2aspath(sp->shouldbe); + + asconfeddel = aspath_delete_confed_seq(aspath_dup(asinout)); + + printf("got: %s\n", aspath_print(as)); + + /* the parsed path should match the specified 'shouldbe' string. + * We should pass the "eat our own dog food" test, be able to output + * this path and then input it again. Ie the path resulting from: + * + * aspath_parse(aspath_put(as)) + * + * should: + * + * - also match the specified 'shouldbe' value + * - hash to same value as original path + * - have same hops and confed counts as original, and as the + * the specified counts + * + * aspath_str2aspath() and shouldbe should match + * + * We do the same for: + * + * aspath_parse(aspath_put(as,USE32BIT)) + * + * Confederation related tests: + * - aspath_delete_confed_seq(aspath) should match shouldbe_confed + * - aspath_delete_confed_seq should be idempotent. + */ + if (strcmp(aspath_print(as), sp->shouldbe) + /* hash validation */ + || (aspath_key_make(as) != aspath_key_make(asinout)) + /* by string */ + || strcmp(aspath_print(asinout), sp->shouldbe) + /* By 4-byte parsing */ + || strcmp(aspath_print(as4), sp->shouldbe) + /* by various path counts */ + || (aspath_count_hops(as) != sp->hops) + || (aspath_count_confeds(as) != sp->confeds) + || (aspath_count_hops(asinout) != sp->hops) + || (aspath_count_confeds(asinout) != sp->confeds)) { + failed++; + fails++; + printf("shouldbe:\n%s\n", sp->shouldbe); + printf("as4:\n%s\n", aspath_print(as4)); + printf("hash keys: in: %d out->in: %d\n", aspath_key_make(as), + aspath_key_make(asinout)); + printf("hops: %d, counted %d %d\n", sp->hops, + aspath_count_hops(as), aspath_count_hops(asinout)); + printf("confeds: %d, counted %d %d\n", sp->confeds, + aspath_count_confeds(as), aspath_count_confeds(asinout)); + printf("out->in:\n%s\nbytes: ", aspath_print(asinout)); + printbytes(out, bytes); + } + /* basic confed related tests */ + if ((aspath_print(asconfeddel) == NULL + && sp->shouldbe_delete_confed != NULL) + || (aspath_print(asconfeddel) != NULL + && sp->shouldbe_delete_confed == NULL) + || strcmp(aspath_print(asconfeddel), sp->shouldbe_delete_confed) + /* delete_confed_seq should be idempotent */ + || (aspath_key_make(asconfeddel) + != aspath_key_make(aspath_delete_confed_seq(asconfeddel)))) { + failed++; + fails++; + printf("as-path minus confeds is: %s\n", + aspath_print(asconfeddel)); + printf("as-path minus confeds should be: %s\n", + sp->shouldbe_delete_confed); + } + /* aspath_str2aspath test */ + if ((aspath_print(asstr) == NULL && sp->shouldbe != NULL) + || (aspath_print(asstr) != NULL && sp->shouldbe == NULL) + || strcmp(aspath_print(asstr), sp->shouldbe)) { + failed++; + fails++; + printf("asstr: %s\n", aspath_print(asstr)); + } + + /* loop, private and first as checks */ + if ((sp->does_loop && aspath_loop_check(as, sp->does_loop) == 0) + || (sp->doesnt_loop && aspath_loop_check(as, sp->doesnt_loop) != 0) + || (aspath_private_as_check(as) != sp->private_as) + || (aspath_firstas_check(as, sp->first) && sp->first == 0)) { + failed++; + fails++; + printf("firstas: %d, got %d\n", sp->first, + aspath_firstas_check(as, sp->first)); + printf("loop does: %d %d, doesnt: %d %d\n", sp->does_loop, + aspath_loop_check(as, sp->does_loop), sp->doesnt_loop, + aspath_loop_check(as, sp->doesnt_loop)); + printf("private check: %d %d\n", sp->private_as, + aspath_private_as_check(as)); + } + aspath_unintern(&asinout); + aspath_unintern(&as4); + + aspath_free(asconfeddel); + aspath_free(asstr); + stream_reset(s); + + return fails; } -static void -empty_get_test () +static void empty_get_test() { - struct aspath *as = aspath_empty_get (); - struct test_spec sp = { "", "", 0, 0, 0, 0, 0, 0 }; - - printf ("empty_get_test, as: %s\n",aspath_print (as)); - if (!validate (as, &sp)) - printf ("%s\n", OK); - else - printf ("%s!\n", FAILED); - - printf ("\n"); - - aspath_free (as); + struct aspath *as = aspath_empty_get(); + struct test_spec sp = {"", "", 0, 0, 0, 0, 0, 0}; + + printf("empty_get_test, as: %s\n", aspath_print(as)); + if (!validate(as, &sp)) + printf("%s\n", OK); + else + printf("%s!\n", FAILED); + + printf("\n"); + + aspath_free(as); } /* basic parsing test */ -static void -parse_test (struct test_segment *t) +static void parse_test(struct test_segment *t) { - struct aspath *asp; - - printf ("%s: %s\n", t->name, t->desc); - - asp = make_aspath (t->asdata, t->len, 0); - - printf ("aspath: %s\nvalidating...:\n", aspath_print (asp)); - - if (!validate (asp, &t->sp)) - printf (OK "\n"); - else - printf (FAILED "\n"); - - printf ("\n"); - - if (asp) - aspath_unintern (&asp); + struct aspath *asp; + + printf("%s: %s\n", t->name, t->desc); + + asp = make_aspath(t->asdata, t->len, 0); + + printf("aspath: %s\nvalidating...:\n", aspath_print(asp)); + + if (!validate(asp, &t->sp)) + printf(OK "\n"); + else + printf(FAILED "\n"); + + printf("\n"); + + if (asp) + aspath_unintern(&asp); } /* prepend testing */ -static void -prepend_test (struct tests *t) +static void prepend_test(struct tests *t) { - struct aspath *asp1, *asp2, *ascratch; - - printf ("prepend %s: %s\n", t->test1->name, t->test1->desc); - printf ("to %s: %s\n", t->test2->name, t->test2->desc); - - asp1 = make_aspath (t->test1->asdata, t->test1->len, 0); - asp2 = make_aspath (t->test2->asdata, t->test2->len, 0); - - ascratch = aspath_dup (asp2); - aspath_unintern (&asp2); - - asp2 = aspath_prepend (asp1, ascratch); - - printf ("aspath: %s\n", aspath_print (asp2)); - - if (!validate (asp2, &t->sp)) - printf ("%s\n", OK); - else - printf ("%s!\n", FAILED); - - printf ("\n"); - aspath_unintern (&asp1); - aspath_free (asp2); + struct aspath *asp1, *asp2, *ascratch; + + printf("prepend %s: %s\n", t->test1->name, t->test1->desc); + printf("to %s: %s\n", t->test2->name, t->test2->desc); + + asp1 = make_aspath(t->test1->asdata, t->test1->len, 0); + asp2 = make_aspath(t->test2->asdata, t->test2->len, 0); + + ascratch = aspath_dup(asp2); + aspath_unintern(&asp2); + + asp2 = aspath_prepend(asp1, ascratch); + + printf("aspath: %s\n", aspath_print(asp2)); + + if (!validate(asp2, &t->sp)) + printf("%s\n", OK); + else + printf("%s!\n", FAILED); + + printf("\n"); + aspath_unintern(&asp1); + aspath_free(asp2); } /* empty-prepend testing */ -static void -empty_prepend_test (struct test_segment *t) +static void empty_prepend_test(struct test_segment *t) { - struct aspath *asp1, *asp2, *ascratch; - - printf ("empty prepend %s: %s\n", t->name, t->desc); - - asp1 = make_aspath (t->asdata, t->len, 0); - asp2 = aspath_empty (); - - ascratch = aspath_dup (asp2); - aspath_unintern (&asp2); - - asp2 = aspath_prepend (asp1, ascratch); - - printf ("aspath: %s\n", aspath_print (asp2)); - - if (!validate (asp2, &t->sp)) - printf (OK "\n"); - else - printf (FAILED "!\n"); - - printf ("\n"); - if (asp1) - aspath_unintern (&asp1); - aspath_free (asp2); + struct aspath *asp1, *asp2, *ascratch; + + printf("empty prepend %s: %s\n", t->name, t->desc); + + asp1 = make_aspath(t->asdata, t->len, 0); + asp2 = aspath_empty(); + + ascratch = aspath_dup(asp2); + aspath_unintern(&asp2); + + asp2 = aspath_prepend(asp1, ascratch); + + printf("aspath: %s\n", aspath_print(asp2)); + + if (!validate(asp2, &t->sp)) + printf(OK "\n"); + else + printf(FAILED "!\n"); + + printf("\n"); + if (asp1) + aspath_unintern(&asp1); + aspath_free(asp2); } /* as2+as4 reconciliation testing */ -static void -as4_reconcile_test (struct tests *t) +static void as4_reconcile_test(struct tests *t) { - struct aspath *asp1, *asp2, *ascratch; - - printf ("reconciling %s:\n %s\n", t->test1->name, t->test1->desc); - printf ("with %s:\n %s\n", t->test2->name, t->test2->desc); - - asp1 = make_aspath (t->test1->asdata, t->test1->len, 0); - asp2 = make_aspath (t->test2->asdata, t->test2->len, 0); - - ascratch = aspath_reconcile_as4 (asp1, asp2); - - if (!validate (ascratch, &t->sp)) - printf (OK "\n"); - else - printf (FAILED "!\n"); - - printf ("\n"); - aspath_unintern (&asp1); - aspath_unintern (&asp2); - aspath_free (ascratch); + struct aspath *asp1, *asp2, *ascratch; + + printf("reconciling %s:\n %s\n", t->test1->name, t->test1->desc); + printf("with %s:\n %s\n", t->test2->name, t->test2->desc); + + asp1 = make_aspath(t->test1->asdata, t->test1->len, 0); + asp2 = make_aspath(t->test2->asdata, t->test2->len, 0); + + ascratch = aspath_reconcile_as4(asp1, asp2); + + if (!validate(ascratch, &t->sp)) + printf(OK "\n"); + else + printf(FAILED "!\n"); + + printf("\n"); + aspath_unintern(&asp1); + aspath_unintern(&asp2); + aspath_free(ascratch); } /* aggregation testing */ -static void -aggregate_test (struct tests *t) +static void aggregate_test(struct tests *t) { - struct aspath *asp1, *asp2, *ascratch; - - printf ("aggregate %s: %s\n", t->test1->name, t->test1->desc); - printf ("with %s: %s\n", t->test2->name, t->test2->desc); - - asp1 = make_aspath (t->test1->asdata, t->test1->len, 0); - asp2 = make_aspath (t->test2->asdata, t->test2->len, 0); - - ascratch = aspath_aggregate (asp1, asp2); - - if (!validate (ascratch, &t->sp)) - printf (OK "\n"); - else - printf (FAILED "!\n"); - - printf ("\n"); - aspath_unintern (&asp1); - aspath_unintern (&asp2); - aspath_free (ascratch); -/* aspath_unintern (ascratch);*/ + struct aspath *asp1, *asp2, *ascratch; + + printf("aggregate %s: %s\n", t->test1->name, t->test1->desc); + printf("with %s: %s\n", t->test2->name, t->test2->desc); + + asp1 = make_aspath(t->test1->asdata, t->test1->len, 0); + asp2 = make_aspath(t->test2->asdata, t->test2->len, 0); + + ascratch = aspath_aggregate(asp1, asp2); + + if (!validate(ascratch, &t->sp)) + printf(OK "\n"); + else + printf(FAILED "!\n"); + + printf("\n"); + aspath_unintern(&asp1); + aspath_unintern(&asp2); + aspath_free(ascratch); + /* aspath_unintern (ascratch);*/ } /* cmp_left tests */ -static void -cmp_test () +static void cmp_test() { - unsigned int i; -#define CMP_TESTS_MAX \ - (sizeof(left_compare) / sizeof (struct compare_tests)) - - for (i = 0; i < CMP_TESTS_MAX; i++) - { - struct test_segment *t1 = &test_segments[left_compare[i].test_index1]; - struct test_segment *t2 = &test_segments[left_compare[i].test_index2]; - struct aspath *asp1, *asp2; - - printf ("left cmp %s: %s\n", t1->name, t1->desc); - printf ("and %s: %s\n", t2->name, t2->desc); - - asp1 = make_aspath (t1->asdata, t1->len, 0); - asp2 = make_aspath (t2->asdata, t2->len, 0); - - if (aspath_cmp_left (asp1, asp2) != left_compare[i].shouldbe_cmp - || aspath_cmp_left (asp2, asp1) != left_compare[i].shouldbe_cmp - || aspath_cmp_left_confed (asp1, asp2) - != left_compare[i].shouldbe_confed - || aspath_cmp_left_confed (asp2, asp1) - != left_compare[i].shouldbe_confed) - { - failed++; - printf (FAILED "\n"); - printf ("result should be: cmp: %d, confed: %d\n", - left_compare[i].shouldbe_cmp, - left_compare[i].shouldbe_confed); - printf ("got: cmp %d, cmp_confed: %d\n", - aspath_cmp_left (asp1, asp2), - aspath_cmp_left_confed (asp1, asp2)); - printf("path1: %s\npath2: %s\n", aspath_print (asp1), - aspath_print (asp2)); - } - else - printf (OK "\n"); - - printf ("\n"); - aspath_unintern (&asp1); - aspath_unintern (&asp2); - } + unsigned int i; +#define CMP_TESTS_MAX (sizeof(left_compare) / sizeof(struct compare_tests)) + + for (i = 0; i < CMP_TESTS_MAX; i++) { + struct test_segment *t1 = + &test_segments[left_compare[i].test_index1]; + struct test_segment *t2 = + &test_segments[left_compare[i].test_index2]; + struct aspath *asp1, *asp2; + + printf("left cmp %s: %s\n", t1->name, t1->desc); + printf("and %s: %s\n", t2->name, t2->desc); + + asp1 = make_aspath(t1->asdata, t1->len, 0); + asp2 = make_aspath(t2->asdata, t2->len, 0); + + if (aspath_cmp_left(asp1, asp2) != left_compare[i].shouldbe_cmp + || aspath_cmp_left(asp2, asp1) + != left_compare[i].shouldbe_cmp + || aspath_cmp_left_confed(asp1, asp2) + != left_compare[i].shouldbe_confed + || aspath_cmp_left_confed(asp2, asp1) + != left_compare[i].shouldbe_confed) { + failed++; + printf(FAILED "\n"); + printf("result should be: cmp: %d, confed: %d\n", + left_compare[i].shouldbe_cmp, + left_compare[i].shouldbe_confed); + printf("got: cmp %d, cmp_confed: %d\n", + aspath_cmp_left(asp1, asp2), + aspath_cmp_left_confed(asp1, asp2)); + printf("path1: %s\npath2: %s\n", aspath_print(asp1), + aspath_print(asp2)); + } else + printf(OK "\n"); + + printf("\n"); + aspath_unintern(&asp1); + aspath_unintern(&asp2); + } } -static int -handle_attr_test (struct aspath_tests *t) +static int handle_attr_test(struct aspath_tests *t) { - struct bgp bgp = { 0 }; - struct peer peer = { 0 }; - struct attr attr = { 0 }; - int ret; - int initfail = failed; - struct aspath *asp; - size_t datalen; - - asp = make_aspath (t->segment->asdata, t->segment->len, 0); - - peer.ibuf = stream_new (BGP_MAX_PACKET_SIZE); - peer.obuf = stream_fifo_new (); - peer.bgp = &bgp; - peer.host = (char *)"none"; - peer.fd = -1; - peer.cap = t->cap; - - stream_write (peer.ibuf, t->attrheader, t->len); - datalen = aspath_put (peer.ibuf, asp, t->as4 == AS4_DATA); - if (t->old_segment) - { - char dummyaspath[] = { BGP_ATTR_FLAG_TRANS, BGP_ATTR_AS_PATH, - t->old_segment->len }; - stream_write (peer.ibuf, dummyaspath, sizeof (dummyaspath)); - stream_write (peer.ibuf, t->old_segment->asdata, t->old_segment->len); - datalen += sizeof (dummyaspath) + t->old_segment->len; - } - - ret = bgp_attr_parse (&peer, &attr, t->len + datalen, NULL, NULL); - - if (ret != t->result) - { - printf ("bgp_attr_parse returned %d, expected %d\n", ret, t->result); - printf ("datalen %zd\n", datalen); - failed++; - } - if (ret != 0) - goto out; - - if (t->shouldbe && attr.aspath == NULL) - { - printf ("aspath is NULL, but should be: %s\n", t->shouldbe); - failed++; - } - if (t->shouldbe && attr.aspath && strcmp (attr.aspath->str, t->shouldbe)) - { - printf ("attr str and 'shouldbe' mismatched!\n" - "attr str: %s\n" - "shouldbe: %s\n", - attr.aspath->str, t->shouldbe); - failed++; - } - if (!t->shouldbe && attr.aspath) - { - printf ("aspath should be NULL, but is: %s\n", attr.aspath->str); - failed++; - } + struct bgp bgp = {0}; + struct peer peer = {0}; + struct attr attr = {0}; + int ret; + int initfail = failed; + struct aspath *asp; + size_t datalen; + + asp = make_aspath(t->segment->asdata, t->segment->len, 0); + + peer.ibuf = stream_new(BGP_MAX_PACKET_SIZE); + peer.obuf = stream_fifo_new(); + peer.bgp = &bgp; + peer.host = (char *)"none"; + peer.fd = -1; + peer.cap = t->cap; + + stream_write(peer.ibuf, t->attrheader, t->len); + datalen = aspath_put(peer.ibuf, asp, t->as4 == AS4_DATA); + if (t->old_segment) { + char dummyaspath[] = {BGP_ATTR_FLAG_TRANS, BGP_ATTR_AS_PATH, + t->old_segment->len}; + stream_write(peer.ibuf, dummyaspath, sizeof(dummyaspath)); + stream_write(peer.ibuf, t->old_segment->asdata, + t->old_segment->len); + datalen += sizeof(dummyaspath) + t->old_segment->len; + } + + ret = bgp_attr_parse(&peer, &attr, t->len + datalen, NULL, NULL); + + if (ret != t->result) { + printf("bgp_attr_parse returned %d, expected %d\n", ret, + t->result); + printf("datalen %zd\n", datalen); + failed++; + } + if (ret != 0) + goto out; + + if (t->shouldbe && attr.aspath == NULL) { + printf("aspath is NULL, but should be: %s\n", t->shouldbe); + failed++; + } + if (t->shouldbe && attr.aspath + && strcmp(attr.aspath->str, t->shouldbe)) { + printf("attr str and 'shouldbe' mismatched!\n" + "attr str: %s\n" + "shouldbe: %s\n", + attr.aspath->str, t->shouldbe); + failed++; + } + if (!t->shouldbe && attr.aspath) { + printf("aspath should be NULL, but is: %s\n", attr.aspath->str); + failed++; + } out: - if (attr.aspath) - aspath_unintern (&attr.aspath); - if (asp) - aspath_unintern (&asp); - return failed - initfail; + if (attr.aspath) + aspath_unintern(&attr.aspath); + if (asp) + aspath_unintern(&asp); + return failed - initfail; } -static void -attr_test (struct aspath_tests *t) +static void attr_test(struct aspath_tests *t) { - printf ("%s\n", t->desc); - printf ("%s\n\n", handle_attr_test (t) ? FAILED : OK); + printf("%s\n", t->desc); + printf("%s\n\n", handle_attr_test(t) ? FAILED : OK); } -int -main (void) +int main(void) { - int i = 0; - qobj_init (); - bgp_master_init (thread_master_create(NULL)); - master = bm->master; - bgp_option_set (BGP_OPT_NO_LISTEN); - bgp_attr_init (); - - while (test_segments[i].name) - { - printf ("test %u\n", i); - parse_test (&test_segments[i]); - empty_prepend_test (&test_segments[i++]); - } - - i = 0; - while (prepend_tests[i].test1) - { - printf ("prepend test %u\n", i); - prepend_test (&prepend_tests[i++]); - } - - i = 0; - while (aggregate_tests[i].test1) - { - printf ("aggregate test %u\n", i); - aggregate_test (&aggregate_tests[i++]); - } - - i = 0; - - while (reconcile_tests[i].test1) - { - printf ("reconcile test %u\n", i); - as4_reconcile_test (&reconcile_tests[i++]); - } - - i = 0; - - cmp_test(); - - i = 0; - - empty_get_test(); - - i = 0; - - while (aspath_tests[i].desc) - { - printf ("aspath_attr test %d\n", i); - attr_test (&aspath_tests[i++]); - } - - printf ("failures: %d\n", failed); - printf ("aspath count: %ld\n", aspath_count()); - - return (failed + aspath_count()); + int i = 0; + qobj_init(); + bgp_master_init(thread_master_create(NULL)); + master = bm->master; + bgp_option_set(BGP_OPT_NO_LISTEN); + bgp_attr_init(); + + while (test_segments[i].name) { + printf("test %u\n", i); + parse_test(&test_segments[i]); + empty_prepend_test(&test_segments[i++]); + } + + i = 0; + while (prepend_tests[i].test1) { + printf("prepend test %u\n", i); + prepend_test(&prepend_tests[i++]); + } + + i = 0; + while (aggregate_tests[i].test1) { + printf("aggregate test %u\n", i); + aggregate_test(&aggregate_tests[i++]); + } + + i = 0; + + while (reconcile_tests[i].test1) { + printf("reconcile test %u\n", i); + as4_reconcile_test(&reconcile_tests[i++]); + } + + i = 0; + + cmp_test(); + + i = 0; + + empty_get_test(); + + i = 0; + + while (aspath_tests[i].desc) { + printf("aspath_attr test %d\n", i); + attr_test(&aspath_tests[i++]); + } + + printf("failures: %d\n", failed); + printf("aspath count: %ld\n", aspath_count()); + + return (failed + aspath_count()); } diff --git a/tests/bgpd/test_capability.c b/tests/bgpd/test_capability.c index be0ca37b1..9ec2b5df1 100644 --- a/tests/bgpd/test_capability.c +++ b/tests/bgpd/test_capability.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2007 Sun Microsystems, Inc. * * This file is part of Quagga. @@ -38,7 +38,6 @@ #define VT100_GREEN "\x1b[32m" #define VT100_YELLOW "\x1b[33m" - #define CAPABILITY 0 #define DYNCAP 1 #define OPT_PARAM 2 @@ -52,649 +51,900 @@ static int tty = 0; /* test segments to parse and validate, and use for other tests */ static struct test_segment { - const char *name; - const char *desc; - const u_char data[1024]; - int len; + const char *name; + const char *desc; + const u_char data[1024]; + int len; #define SHOULD_PARSE 0 #define SHOULD_ERR -1 - int parses; /* whether it should parse or not */ - as_t peek_for; /* what peek_for_as4_capability should say */ - - /* AFI/SAFI validation */ - int validate_afi; - afi_t afi; - safi_t safi; + int parses; /* whether it should parse or not */ + as_t peek_for; /* what peek_for_as4_capability should say */ + + /* AFI/SAFI validation */ + int validate_afi; + afi_t afi; + safi_t safi; #define VALID_AFI 1 #define INVALID_AFI 0 - int afi_valid; -} test_segments [] = -{ - /* 0 */ - { "caphdr", - "capability header, and no more", - { CAPABILITY_CODE_REFRESH, 0x0 }, - 2, SHOULD_PARSE, - }, - /* 1 */ - { "nodata", - "header, no data but length says there is", - { 0x1, 0xa }, - 2, SHOULD_ERR, - }, - /* 2 */ - { "padded", - "valid, with padding", - { CAPABILITY_CODE_REFRESH, 0x2, 0x0, 0x0 }, - 4, SHOULD_PARSE, - }, - /* 3 */ - { "minsize", - "violates minsize requirement", - { CAPABILITY_CODE_ORF, 0x2, 0x0, 0x0 }, - 4, SHOULD_ERR, - }, - { NULL, NULL, {0}, 0, 0}, + int afi_valid; +} test_segments[] = { + /* 0 */ + { + "caphdr", + "capability header, and no more", + {CAPABILITY_CODE_REFRESH, 0x0}, + 2, + SHOULD_PARSE, + }, + /* 1 */ + { + "nodata", + "header, no data but length says there is", + {0x1, 0xa}, + 2, + SHOULD_ERR, + }, + /* 2 */ + { + "padded", + "valid, with padding", + {CAPABILITY_CODE_REFRESH, 0x2, 0x0, 0x0}, + 4, + SHOULD_PARSE, + }, + /* 3 */ + { + "minsize", + "violates minsize requirement", + {CAPABILITY_CODE_ORF, 0x2, 0x0, 0x0}, + 4, + SHOULD_ERR, + }, + {NULL, NULL, {0}, 0, 0}, }; -static struct test_segment mp_segments[] = -{ - { "MP4", - "MP IP/Uni", - { 0x1, 0x4, 0x0, 0x1, 0x0, 0x1 }, - 6, SHOULD_PARSE, 0, - 1, AFI_IP, SAFI_UNICAST, VALID_AFI, - }, - { "MPv6", - "MP IPv6/Uni", - { 0x1, 0x4, 0x0, 0x2, 0x0, 0x1 }, - 6, SHOULD_PARSE, 0, - 1, AFI_IP6, SAFI_UNICAST, VALID_AFI, - }, - /* 5 */ - { "MP2", - "MP IP/Multicast", - { CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x2 }, - 6, SHOULD_PARSE, 0, - 1, AFI_IP, SAFI_MULTICAST, VALID_AFI, - }, - /* 6 */ - { "MP3", - "MP IP6/MPLS-labeled VPN", - { CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x80 }, - 6, SHOULD_PARSE, 0, - 1, AFI_IP6, IANA_SAFI_MPLS_VPN, VALID_AFI, - }, - /* 7 */ - { "MP5", - "MP IP6/MPLS-VPN", - { CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x4 }, - 6, SHOULD_PARSE, 0, - 1, AFI_IP6, IANA_SAFI_MPLS_VPN, VALID_AFI, - }, - /* 8 */ - { "MP6", - "MP IP4/MPLS-laveled VPN", - { CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x80 }, - 6, SHOULD_PARSE, 0, - 1, AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, - }, - /* 10 */ - { "MP8", - "MP unknown AFI/SAFI", - { CAPABILITY_CODE_MP, 0x4, 0x0, 0xa, 0x0, 0x81 }, - 6, SHOULD_PARSE, 0, - 1, 0xa, 0x81, INVALID_AFI, /* parses, but unknown */ - }, - /* 11 */ - { "MP-short", - "MP IP4/Unicast, length too short (< minimum)", - { CAPABILITY_CODE_MP, 0x2, 0x0, 0x1, 0x0, 0x1 }, - 6, SHOULD_ERR, - }, - /* 12 */ - { "MP-overflow", - "MP IP4/Unicast, length too long", - { CAPABILITY_CODE_MP, 0x6, 0x0, 0x1, 0x0, 0x1 }, - 6, SHOULD_ERR, 0, - 1, AFI_IP, SAFI_UNICAST, VALID_AFI, - }, - { NULL, NULL, {0}, 0, 0} -}; +static struct test_segment mp_segments[] = { + { + "MP4", + "MP IP/Uni", + {0x1, 0x4, 0x0, 0x1, 0x0, 0x1}, + 6, + SHOULD_PARSE, + 0, + 1, + AFI_IP, + SAFI_UNICAST, + VALID_AFI, + }, + { + "MPv6", + "MP IPv6/Uni", + {0x1, 0x4, 0x0, 0x2, 0x0, 0x1}, + 6, + SHOULD_PARSE, + 0, + 1, + AFI_IP6, + SAFI_UNICAST, + VALID_AFI, + }, + /* 5 */ + { + "MP2", + "MP IP/Multicast", + {CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x2}, + 6, + SHOULD_PARSE, + 0, + 1, + AFI_IP, + SAFI_MULTICAST, + VALID_AFI, + }, + /* 6 */ + { + "MP3", + "MP IP6/MPLS-labeled VPN", + {CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x80}, + 6, + SHOULD_PARSE, + 0, + 1, + AFI_IP6, + IANA_SAFI_MPLS_VPN, + VALID_AFI, + }, + /* 7 */ + { + "MP5", + "MP IP6/MPLS-VPN", + {CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x4}, + 6, + SHOULD_PARSE, + 0, + 1, + AFI_IP6, + IANA_SAFI_MPLS_VPN, + VALID_AFI, + }, + /* 8 */ + { + "MP6", + "MP IP4/MPLS-laveled VPN", + {CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x80}, + 6, + SHOULD_PARSE, + 0, + 1, + AFI_IP, + IANA_SAFI_MPLS_VPN, + VALID_AFI, + }, + /* 10 */ + { + "MP8", + "MP unknown AFI/SAFI", + {CAPABILITY_CODE_MP, 0x4, 0x0, 0xa, 0x0, 0x81}, + 6, + SHOULD_PARSE, + 0, + 1, + 0xa, + 0x81, + INVALID_AFI, /* parses, but unknown */ + }, + /* 11 */ + { + "MP-short", + "MP IP4/Unicast, length too short (< minimum)", + {CAPABILITY_CODE_MP, 0x2, 0x0, 0x1, 0x0, 0x1}, + 6, + SHOULD_ERR, + }, + /* 12 */ + { + "MP-overflow", + "MP IP4/Unicast, length too long", + {CAPABILITY_CODE_MP, 0x6, 0x0, 0x1, 0x0, 0x1}, + 6, + SHOULD_ERR, + 0, + 1, + AFI_IP, + SAFI_UNICAST, + VALID_AFI, + }, + {NULL, NULL, {0}, 0, 0}}; static struct test_segment misc_segments[] = -{ - /* 13 */ - { "ORF", - "ORF, simple, single entry, single tuple", - { /* hdr */ CAPABILITY_CODE_ORF, 0x7, - /* mpc */ 0x0, 0x1, 0x0, 0x1, - /* num */ 0x1, - /* tuples */ 0x40, 0x3 - }, - 9, SHOULD_PARSE, - }, - /* 14 */ - { "ORF-many", - "ORF, multi entry/tuple", - { /* hdr */ CAPABILITY_CODE_ORF, 0x21, - /* mpc */ 0x0, 0x1, 0x0, 0x1, - /* num */ 0x3, - /* tuples */ 0x40, ORF_MODE_BOTH, - 0x80, ORF_MODE_RECEIVE, - 0x80, ORF_MODE_SEND, - /* mpc */ 0x0, 0x2, 0x0, 0x1, - /* num */ 0x3, - /* tuples */ 0x40, ORF_MODE_BOTH, - 0x80, ORF_MODE_RECEIVE, - 0x80, ORF_MODE_SEND, - /* mpc */ 0x0, 0x2, 0x0, 0x2, - /* num */ 0x3, - /* tuples */ 0x40, ORF_MODE_RECEIVE, - 0x80, ORF_MODE_SEND, - 0x80, ORF_MODE_BOTH, - }, - 35, SHOULD_PARSE, - }, - /* 15 */ - { "ORFlo", - "ORF, multi entry/tuple, hdr length too short", - { /* hdr */ CAPABILITY_CODE_ORF, 0x15, - /* mpc */ 0x0, 0x1, 0x0, 0x1, - /* num */ 0x3, - /* tuples */ 0x40, 0x3, - 0x80, 0x1, - 0x80, 0x2, - /* mpc */ 0x0, 0x1, 0x0, 0x1, - /* num */ 0x3, - /* tuples */ 0x40, 0x3, - 0x80, 0x1, - 0x80, 0x2, - /* mpc */ 0x0, 0x2, 0x0, 0x2, - /* num */ 0x3, - /* tuples */ 0x40, 0x3, - 0x80, 0x1, - 0x80, 0x2, - }, - 35, SHOULD_ERR, /* It should error on invalid Route-Refresh.. */ - }, - /* 16 */ - { "ORFlu", - "ORF, multi entry/tuple, length too long", - { /* hdr */ 0x3, 0x22, - /* mpc */ 0x0, 0x1, 0x0, 0x1, - /* num */ 0x3, - /* tuples */ 0x40, 0x3, - 0x80, 0x1, - 0x80, 0x2, - /* mpc */ 0x0, 0x2, 0x0, 0x1, - /* num */ 0x3, - /* tuples */ 0x40, 0x3, - 0x80, 0x1, - 0x80, 0x2, - /* mpc */ 0x0, 0x2, 0x0, 0x2, - /* num */ 0x3, - /* tuples */ 0x40, 0x3, - 0x80, 0x1, - 0x80, 0x2, - }, - 35, SHOULD_ERR - }, - /* 17 */ - { "ORFnu", - "ORF, multi entry/tuple, entry number too long", - { /* hdr */ 0x3, 0x21, - /* mpc */ 0x0, 0x1, 0x0, 0x1, - /* num */ 0x3, - /* tuples */ 0x40, 0x3, - 0x80, 0x1, - 0x80, 0x2, - /* mpc */ 0x0, 0x2, 0x0, 0x1, - /* num */ 0x4, - /* tuples */ 0x40, 0x3, - 0x80, 0x1, - 0x80, 0x2, - /* mpc */ 0x0, 0x2, 0x0, 0x2, - /* num */ 0x3, - /* tuples */ 0x40, 0x3, - 0x80, 0x1, - 0x80, 0x2, - }, - 35, SHOULD_PARSE, /* parses, but last few tuples should be gibberish */ - }, - /* 18 */ - { "ORFno", - "ORF, multi entry/tuple, entry number too short", - { /* hdr */ 0x3, 0x21, - /* mpc */ 0x0, 0x1, 0x0, 0x1, - /* num */ 0x3, - /* tuples */ 0x40, 0x3, - 0x80, 0x1, - 0x80, 0x2, - /* mpc */ 0x0, 0x2, 0x0, 0x1, - /* num */ 0x1, - /* tuples */ 0x40, 0x3, - 0x80, 0x1, - 0x80, 0x2, - /* mpc */ 0x0, 0x2, 0x0, 0x2, - /* num */ 0x3, - /* tuples */ 0x40, 0x3, - 0x80, 0x1, - 0x80, 0x2, - }, - 35, SHOULD_PARSE, /* Parses, but should get gibberish afi/safis */ - }, - /* 17 */ - { "ORFpad", - "ORF, multi entry/tuple, padded to align", - { /* hdr */ 0x3, 0x22, - /* mpc */ 0x0, 0x1, 0x0, 0x1, - /* num */ 0x3, - /* tuples */ 0x40, 0x3, - 0x80, 0x1, - 0x80, 0x2, - /* mpc */ 0x0, 0x2, 0x0, 0x1, - /* num */ 0x3, - /* tuples */ 0x40, 0x3, - 0x80, 0x1, - 0x80, 0x2, - /* mpc */ 0x0, 0x2, 0x0, 0x2, - /* num */ 0x3, - /* tuples */ 0x40, 0x3, - 0x80, 0x1, - 0x80, 0x2, - 0x00, - }, - 36, SHOULD_PARSE, - }, - /* 19 */ - { "AS4", - "AS4 capability", - { 0x41, 0x4, 0xab, 0xcd, 0xef, 0x12 }, /* AS: 2882400018 */ - 6, SHOULD_PARSE, 2882400018, - }, - { "AS4", - "AS4 capability: short", - { 0x41, 0x4, 0xab, 0xcd, 0xef }, /* AS: 2882400018 */ - 5, SHOULD_ERR, - }, - { "AS4", - "AS4 capability: long", - { 0x41, 0x4, 0xab, 0xcd, 0xef, 0x12, 0x12 }, - 7, SHOULD_ERR, 2882400018, - }, - { "GR", - "GR capability", - { /* hdr */ CAPABILITY_CODE_RESTART, 0xe, - /* R-bit, time */ 0xf1, 0x12, - /* afi */ 0x0, 0x1, - /* safi */ 0x1, - /* flags */ 0xf, - /* afi */ 0x0, 0x2, - /* safi */ 0x1, - /* flags */ 0x0, - /* afi */ 0x0, 0x2, - /* safi */ 0x2, - /* flags */ 0x1, - }, - 16, SHOULD_PARSE, - }, - { "GR-short", - "GR capability, but header length too short", - { /* hdr */ 0x40, 0xa, - /* R-bit, time */ 0xf1, 0x12, - /* afi */ 0x0, 0x1, - /* safi */ 0x1, - /* flags */ 0xf, - /* afi */ 0x0, 0x2, - /* safi */ 0x1, - /* flags */ 0x0, - /* afi */ 0x0, 0x2, - /* safi */ 0x2, - /* flags */ 0x1, - }, - 15 /* array is 16 though */, SHOULD_ERR, - }, - { "GR-long", - "GR capability, but header length too long", - { /* hdr */ 0x40, 0xf, - /* R-bit, time */ 0xf1, 0x12, - /* afi */ 0x0, 0x1, - /* safi */ 0x1, - /* flags */ 0xf, - /* afi */ 0x0, 0x2, - /* safi */ 0x1, - /* flags */ 0x0, - /* afi */ 0x0, 0x2, - /* safi */ 0x2, - /* flags */ 0x01, - }, - 16, SHOULD_ERR, - }, - { "GR-trunc", - "GR capability, but truncated", - { /* hdr */ 0x40, 0xf, - /* R-bit, time */ 0xf1, 0x12, - /* afi */ 0x0, 0x1, - /* safi */ 0x1, - /* flags */ 0xf, - /* afi */ 0x0, 0x2, - /* safi */ 0x1, - /* flags */ 0x0, - /* afi */ 0x0, 0x2, - /* safi */ 0x2, - /* flags */ 0x1, - }, - 15, SHOULD_ERR, - }, - { "GR-empty", - "GR capability, but empty.", - { /* hdr */ 0x40, 0x0, - }, - 2, SHOULD_ERR, - }, - { "MP-empty", - "MP capability, but empty.", - { /* hdr */ 0x1, 0x0, - }, - 2, SHOULD_ERR, - }, - { "ORF-empty", - "ORF capability, but empty.", - { /* hdr */ 0x3, 0x0, - }, - 2, SHOULD_ERR, - }, - { "AS4-empty", - "AS4 capability, but empty.", - { /* hdr */ 0x41, 0x0, - }, - 2, SHOULD_ERR, - }, - { "dyn-empty", - "Dynamic capability, but empty.", - { /* hdr */ 0x42, 0x0, - }, - 2, SHOULD_PARSE, - }, - { "dyn-old", - "Dynamic capability (deprecated version)", - { CAPABILITY_CODE_DYNAMIC, 0x0 }, - 2, SHOULD_PARSE, - }, - { NULL, NULL, {0}, 0, 0} -}; + { + /* 13 */ + { + "ORF", + "ORF, simple, single entry, single tuple", + {/* hdr */ CAPABILITY_CODE_ORF, 0x7, + /* mpc */ 0x0, 0x1, 0x0, 0x1, + /* num */ 0x1, + /* tuples */ 0x40, 0x3}, + 9, + SHOULD_PARSE, + }, + /* 14 */ + { + "ORF-many", + "ORF, multi entry/tuple", + { + /* hdr */ CAPABILITY_CODE_ORF, + 0x21, + /* mpc */ 0x0, + 0x1, + 0x0, + 0x1, + /* num */ 0x3, + /* tuples */ 0x40, + ORF_MODE_BOTH, + 0x80, + ORF_MODE_RECEIVE, + 0x80, + ORF_MODE_SEND, + /* mpc */ 0x0, + 0x2, + 0x0, + 0x1, + /* num */ 0x3, + /* tuples */ 0x40, + ORF_MODE_BOTH, + 0x80, + ORF_MODE_RECEIVE, + 0x80, + ORF_MODE_SEND, + /* mpc */ 0x0, + 0x2, + 0x0, + 0x2, + /* num */ 0x3, + /* tuples */ 0x40, + ORF_MODE_RECEIVE, + 0x80, + ORF_MODE_SEND, + 0x80, + ORF_MODE_BOTH, + }, + 35, + SHOULD_PARSE, + }, + /* 15 */ + { + "ORFlo", + "ORF, multi entry/tuple, hdr length too short", + { + /* hdr */ CAPABILITY_CODE_ORF, + 0x15, + /* mpc */ 0x0, + 0x1, + 0x0, + 0x1, + /* num */ 0x3, + /* tuples */ 0x40, + 0x3, + 0x80, + 0x1, + 0x80, + 0x2, + /* mpc */ 0x0, + 0x1, + 0x0, + 0x1, + /* num */ 0x3, + /* tuples */ 0x40, + 0x3, + 0x80, + 0x1, + 0x80, + 0x2, + /* mpc */ 0x0, + 0x2, + 0x0, + 0x2, + /* num */ 0x3, + /* tuples */ 0x40, + 0x3, + 0x80, + 0x1, + 0x80, + 0x2, + }, + 35, + SHOULD_ERR, /* It should error on invalid + Route-Refresh.. */ + }, + /* 16 */ + {"ORFlu", + "ORF, multi entry/tuple, length too long", + { + /* hdr */ 0x3, + 0x22, + /* mpc */ 0x0, + 0x1, + 0x0, + 0x1, + /* num */ 0x3, + /* tuples */ 0x40, + 0x3, + 0x80, + 0x1, + 0x80, + 0x2, + /* mpc */ 0x0, + 0x2, + 0x0, + 0x1, + /* num */ 0x3, + /* tuples */ 0x40, + 0x3, + 0x80, + 0x1, + 0x80, + 0x2, + /* mpc */ 0x0, + 0x2, + 0x0, + 0x2, + /* num */ 0x3, + /* tuples */ 0x40, + 0x3, + 0x80, + 0x1, + 0x80, + 0x2, + }, + 35, + SHOULD_ERR}, + /* 17 */ + { + "ORFnu", + "ORF, multi entry/tuple, entry number too long", + { + /* hdr */ 0x3, + 0x21, + /* mpc */ 0x0, + 0x1, + 0x0, + 0x1, + /* num */ 0x3, + /* tuples */ 0x40, + 0x3, + 0x80, + 0x1, + 0x80, + 0x2, + /* mpc */ 0x0, + 0x2, + 0x0, + 0x1, + /* num */ 0x4, + /* tuples */ 0x40, + 0x3, + 0x80, + 0x1, + 0x80, + 0x2, + /* mpc */ 0x0, + 0x2, + 0x0, + 0x2, + /* num */ 0x3, + /* tuples */ 0x40, + 0x3, + 0x80, + 0x1, + 0x80, + 0x2, + }, + 35, + SHOULD_PARSE, /* parses, but last few tuples should be + gibberish */ + }, + /* 18 */ + { + "ORFno", + "ORF, multi entry/tuple, entry number too short", + { + /* hdr */ 0x3, + 0x21, + /* mpc */ 0x0, + 0x1, + 0x0, + 0x1, + /* num */ 0x3, + /* tuples */ 0x40, + 0x3, + 0x80, + 0x1, + 0x80, + 0x2, + /* mpc */ 0x0, + 0x2, + 0x0, + 0x1, + /* num */ 0x1, + /* tuples */ 0x40, + 0x3, + 0x80, + 0x1, + 0x80, + 0x2, + /* mpc */ 0x0, + 0x2, + 0x0, + 0x2, + /* num */ 0x3, + /* tuples */ 0x40, + 0x3, + 0x80, + 0x1, + 0x80, + 0x2, + }, + 35, + SHOULD_PARSE, /* Parses, but should get gibberish + afi/safis */ + }, + /* 17 */ + { + "ORFpad", + "ORF, multi entry/tuple, padded to align", + { + /* hdr */ 0x3, + 0x22, + /* mpc */ 0x0, + 0x1, + 0x0, + 0x1, + /* num */ 0x3, + /* tuples */ 0x40, + 0x3, + 0x80, + 0x1, + 0x80, + 0x2, + /* mpc */ 0x0, + 0x2, + 0x0, + 0x1, + /* num */ 0x3, + /* tuples */ 0x40, + 0x3, + 0x80, + 0x1, + 0x80, + 0x2, + /* mpc */ 0x0, + 0x2, + 0x0, + 0x2, + /* num */ 0x3, + /* tuples */ 0x40, + 0x3, + 0x80, + 0x1, + 0x80, + 0x2, + 0x00, + }, + 36, + SHOULD_PARSE, + }, + /* 19 */ + { + "AS4", + "AS4 capability", + {0x41, 0x4, 0xab, 0xcd, 0xef, + 0x12}, /* AS: 2882400018 */ + 6, + SHOULD_PARSE, + 2882400018, + }, + { + "AS4", + "AS4 capability: short", + {0x41, 0x4, 0xab, 0xcd, 0xef}, /* AS: 2882400018 */ + 5, + SHOULD_ERR, + }, + { + "AS4", + "AS4 capability: long", + {0x41, 0x4, 0xab, 0xcd, 0xef, 0x12, 0x12}, + 7, + SHOULD_ERR, + 2882400018, + }, + { + "GR", + "GR capability", + { + /* hdr */ CAPABILITY_CODE_RESTART, 0xe, + /* R-bit, time */ 0xf1, 0x12, + /* afi */ 0x0, 0x1, + /* safi */ 0x1, + /* flags */ 0xf, + /* afi */ 0x0, 0x2, + /* safi */ 0x1, + /* flags */ 0x0, + /* afi */ 0x0, 0x2, + /* safi */ 0x2, + /* flags */ 0x1, + }, + 16, + SHOULD_PARSE, + }, + { + "GR-short", + "GR capability, but header length too short", + { + /* hdr */ 0x40, 0xa, + /* R-bit, time */ 0xf1, 0x12, + /* afi */ 0x0, 0x1, + /* safi */ 0x1, + /* flags */ 0xf, + /* afi */ 0x0, 0x2, + /* safi */ 0x1, + /* flags */ 0x0, + /* afi */ 0x0, 0x2, + /* safi */ 0x2, + /* flags */ 0x1, + }, + 15 /* array is 16 though */, + SHOULD_ERR, + }, + { + "GR-long", + "GR capability, but header length too long", + { + /* hdr */ 0x40, 0xf, + /* R-bit, time */ 0xf1, 0x12, + /* afi */ 0x0, 0x1, + /* safi */ 0x1, + /* flags */ 0xf, + /* afi */ 0x0, 0x2, + /* safi */ 0x1, + /* flags */ 0x0, + /* afi */ 0x0, 0x2, + /* safi */ 0x2, + /* flags */ 0x01, + }, + 16, + SHOULD_ERR, + }, + { + "GR-trunc", + "GR capability, but truncated", + { + /* hdr */ 0x40, 0xf, + /* R-bit, time */ 0xf1, 0x12, + /* afi */ 0x0, 0x1, + /* safi */ 0x1, + /* flags */ 0xf, + /* afi */ 0x0, 0x2, + /* safi */ 0x1, + /* flags */ 0x0, + /* afi */ 0x0, 0x2, + /* safi */ 0x2, + /* flags */ 0x1, + }, + 15, + SHOULD_ERR, + }, + { + "GR-empty", + "GR capability, but empty.", + { + /* hdr */ 0x40, 0x0, + }, + 2, + SHOULD_ERR, + }, + { + "MP-empty", + "MP capability, but empty.", + { + /* hdr */ 0x1, 0x0, + }, + 2, + SHOULD_ERR, + }, + { + "ORF-empty", + "ORF capability, but empty.", + { + /* hdr */ 0x3, 0x0, + }, + 2, + SHOULD_ERR, + }, + { + "AS4-empty", + "AS4 capability, but empty.", + { + /* hdr */ 0x41, 0x0, + }, + 2, + SHOULD_ERR, + }, + { + "dyn-empty", + "Dynamic capability, but empty.", + { + /* hdr */ 0x42, 0x0, + }, + 2, + SHOULD_PARSE, + }, + { + "dyn-old", + "Dynamic capability (deprecated version)", + {CAPABILITY_CODE_DYNAMIC, 0x0}, + 2, + SHOULD_PARSE, + }, + {NULL, NULL, {0}, 0, 0}}; /* DYNAMIC message */ -struct test_segment dynamic_cap_msgs[] = -{ - { "DynCap", - "Dynamic Capability Message, IP/Multicast", - { 0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2 }, - 7, SHOULD_PARSE, /* horrible alignment, just as with ORF */ - }, - { "DynCapLong", - "Dynamic Capability Message, IP/Multicast, truncated", - { 0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2 }, - 5, SHOULD_ERR, - }, - { "DynCapPadded", - "Dynamic Capability Message, IP/Multicast, padded", - { 0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2, 0x0 }, - 8, SHOULD_ERR, /* No way to tell padding from data.. */ - }, - { "DynCapMPCpadded", - "Dynamic Capability Message, IP/Multicast, cap data padded", - { 0x0, 0x1, 0x5, 0x0, 0x1, 0x0, 0x2, 0x0 }, - 8, SHOULD_PARSE, /* You can though add padding to the capability data */ - }, - { "DynCapMPCoverflow", - "Dynamic Capability Message, IP/Multicast, cap data != length", - { 0x0, 0x1, 0x3, 0x0, 0x1, 0x0, 0x2, 0x0 }, - 8, SHOULD_ERR, - }, - { NULL, NULL, {0}, 0, 0} -}; +struct test_segment dynamic_cap_msgs[] = { + { + "DynCap", + "Dynamic Capability Message, IP/Multicast", + {0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2}, + 7, + SHOULD_PARSE, /* horrible alignment, just as with ORF */ + }, + { + "DynCapLong", + "Dynamic Capability Message, IP/Multicast, truncated", + {0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2}, + 5, + SHOULD_ERR, + }, + { + "DynCapPadded", + "Dynamic Capability Message, IP/Multicast, padded", + {0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2, 0x0}, + 8, + SHOULD_ERR, /* No way to tell padding from data.. */ + }, + { + "DynCapMPCpadded", + "Dynamic Capability Message, IP/Multicast, cap data padded", + {0x0, 0x1, 0x5, 0x0, 0x1, 0x0, 0x2, 0x0}, + 8, + SHOULD_PARSE, /* You can though add padding to the capability + data */ + }, + { + "DynCapMPCoverflow", + "Dynamic Capability Message, IP/Multicast, cap data != length", + {0x0, 0x1, 0x3, 0x0, 0x1, 0x0, 0x2, 0x0}, + 8, + SHOULD_ERR, + }, + {NULL, NULL, {0}, 0, 0}}; /* Entire Optional-Parameters block */ -struct test_segment opt_params[] = -{ - { "Cap-singlets", - "One capability per Optional-Param", - { 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */ - 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */ - 0x02, 0x02, 0x80, 0x00, /* RR (old) */ - 0x02, 0x02, 0x02, 0x00, /* RR */ - }, - 24, SHOULD_PARSE, - }, - { "Cap-series", - "Series of capability, one Optional-Param", - { 0x02, 0x10, - 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */ - 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */ - 0x80, 0x00, /* RR (old) */ - 0x02, 0x00, /* RR */ - }, - 18, SHOULD_PARSE, - }, - { "AS4more", - "AS4 capability after other caps (singlets)", - { 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */ - 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */ - 0x02, 0x02, 0x80, 0x00, /* RR (old) */ - 0x02, 0x02, 0x02, 0x00, /* RR */ - 0x02, 0x06, 0x41, 0x04, 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */ - }, - 32, SHOULD_PARSE, 196614, - }, - { "AS4series", - "AS4 capability, in series of capabilities", - { 0x02, 0x16, - 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */ - 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */ - 0x80, 0x00, /* RR (old) */ - 0x02, 0x00, /* RR */ - 0x41, 0x04, 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */ - }, - 24, SHOULD_PARSE, 196614, - }, - { "AS4real", - "AS4 capability, in series of capabilities", - { - 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/uni */ - 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/uni */ - 0x02, 0x02, 0x80, 0x00, /* RR old */ - 0x02, 0x02, 0x02, 0x00, /* RR */ - 0x02, 0x06, 0x41, 0x04, 0x00, 0x03, 0x00, 0x06, /* AS4 */ - }, - 32, SHOULD_PARSE, 196614, - }, - { "AS4real2", - "AS4 capability, in series of capabilities", - { - 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, - 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, - 0x02, 0x02, 0x80, 0x00, - 0x02, 0x02, 0x02, 0x00, - 0x02, 0x06, 0x41, 0x04, 0x00, 0x00, 0xfc, 0x03, - 0x02, 0x09, 0x82, 0x07, 0x00, 0x01, 0x00, 0x01, 0x01, 0x80, 0x03, - 0x02, 0x09, 0x03, 0x07, 0x00, 0x01, 0x00, 0x01, 0x01, 0x40, 0x03, - 0x02, 0x02, 0x42, 0x00, - }, - 58, SHOULD_PARSE, 64515, - }, - - { NULL, NULL, {0}, 0, 0} -}; +struct test_segment opt_params[] = { + { + "Cap-singlets", + "One capability per Optional-Param", + { + 0x02, 0x06, 0x01, 0x04, + 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */ + 0x02, 0x06, 0x01, 0x04, + 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */ + 0x02, 0x02, 0x80, 0x00, /* RR (old) */ + 0x02, 0x02, 0x02, 0x00, /* RR */ + }, + 24, + SHOULD_PARSE, + }, + { + "Cap-series", + "Series of capability, one Optional-Param", + { + 0x02, 0x10, 0x01, 0x04, 0x00, 0x01, 0x00, + 0x01, /* MP IPv4/Uni */ + 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */ + 0x80, 0x00, /* RR (old) */ + 0x02, 0x00, /* RR */ + }, + 18, + SHOULD_PARSE, + }, + { + "AS4more", + "AS4 capability after other caps (singlets)", + { + 0x02, 0x06, 0x01, 0x04, + 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */ + 0x02, 0x06, 0x01, 0x04, + 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */ + 0x02, 0x02, 0x80, 0x00, /* RR (old) */ + 0x02, 0x02, 0x02, 0x00, /* RR */ + 0x02, 0x06, 0x41, 0x04, + 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */ + }, + 32, + SHOULD_PARSE, + 196614, + }, + { + "AS4series", + "AS4 capability, in series of capabilities", + { + 0x02, 0x16, 0x01, 0x04, 0x00, 0x01, + 0x00, 0x01, /* MP IPv4/Uni */ + 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */ + 0x80, 0x00, /* RR (old) */ + 0x02, 0x00, /* RR */ + 0x41, 0x04, 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */ + }, + 24, + SHOULD_PARSE, + 196614, + }, + { + "AS4real", + "AS4 capability, in series of capabilities", + { + 0x02, 0x06, 0x01, 0x04, + 0x00, 0x01, 0x00, 0x01, /* MP IPv4/uni */ + 0x02, 0x06, 0x01, 0x04, + 0x00, 0x02, 0x00, 0x01, /* MP IPv6/uni */ + 0x02, 0x02, 0x80, 0x00, /* RR old */ + 0x02, 0x02, 0x02, 0x00, /* RR */ + 0x02, 0x06, 0x41, 0x04, + 0x00, 0x03, 0x00, 0x06, /* AS4 */ + }, + 32, + SHOULD_PARSE, + 196614, + }, + { + "AS4real2", + "AS4 capability, in series of capabilities", + { + 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, 0x02, + 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, 0x02, 0x02, + 0x80, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x06, 0x41, + 0x04, 0x00, 0x00, 0xfc, 0x03, 0x02, 0x09, 0x82, 0x07, + 0x00, 0x01, 0x00, 0x01, 0x01, 0x80, 0x03, 0x02, 0x09, + 0x03, 0x07, 0x00, 0x01, 0x00, 0x01, 0x01, 0x40, 0x03, + 0x02, 0x02, 0x42, 0x00, + }, + 58, + SHOULD_PARSE, + 64515, + }, + + {NULL, NULL, {0}, 0, 0}}; /* basic parsing test */ -static void -parse_test (struct peer *peer, struct test_segment *t, int type) +static void parse_test(struct peer *peer, struct test_segment *t, int type) { - int ret; - int capability = 0; - as_t as4 = 0; - int oldfailed = failed; - int len = t->len; + int ret; + int capability = 0; + as_t as4 = 0; + int oldfailed = failed; + int len = t->len; #define RANDOM_FUZZ 35 - - stream_reset (peer->ibuf); - stream_put (peer->ibuf, NULL, RANDOM_FUZZ); - stream_set_getp (peer->ibuf, RANDOM_FUZZ); - - switch (type) - { - case CAPABILITY: - stream_putc (peer->ibuf, BGP_OPEN_OPT_CAP); - stream_putc (peer->ibuf, t->len); - break; - case DYNCAP: -/* for (i = 0; i < BGP_MARKER_SIZE; i++) - stream_putc (peer->, 0xff); - stream_putw (s, 0); - stream_putc (s, BGP_MSG_CAPABILITY);*/ - break; - } - stream_write (peer->ibuf, t->data, t->len); - - printf ("%s: %s\n", t->name, t->desc); - - switch (type) - { - case CAPABILITY: - len += 2; /* to cover the OPT-Param header */ - case OPT_PARAM: - printf ("len: %u\n", len); - /* peek_for_as4 wants getp at capibility*/ - as4 = peek_for_as4_capability (peer, len); - printf ("peek_for_as4: as4 is %u\n", as4); - /* and it should leave getp as it found it */ - assert (stream_get_getp (peer->ibuf) == RANDOM_FUZZ); - - ret = bgp_open_option_parse (peer, len, &capability); - break; - case DYNCAP: - ret = bgp_capability_receive (peer, t->len); - break; - default: - printf ("unknown type %u\n", type); - exit(1); - } - - if (!ret && t->validate_afi) - { - afi_t afi; - safi_t safi; - - /* Convert AFI, SAFI to internal values, check. */ - if (bgp_map_afi_safi_iana2int (afi_int2iana(t->afi), t->safi, &afi, &safi)) - { - if (t->afi_valid == VALID_AFI) - failed++; - } - printf ("MP: %u(%u)/%u(%u): recv %u, nego %u\n", - t->afi, afi, t->safi, safi, - peer->afc_recv[afi][safi], - peer->afc_nego[afi][safi]); - - if (t->afi_valid == VALID_AFI) - { - - if (!peer->afc_recv[afi][safi]) - failed++; - if (!peer->afc_nego[afi][safi]) - failed++; - } - } - - if (as4 != t->peek_for) - { - printf ("as4 %u != %u\n", as4, t->peek_for); - failed++; - } - - printf ("parsed?: %s\n", ret ? "no" : "yes"); - - if (ret != t->parses) - failed++; - - if (tty) - printf ("%s", (failed > oldfailed) ? VT100_RED "failed!" VT100_RESET - : VT100_GREEN "OK" VT100_RESET); - else - printf ("%s", (failed > oldfailed) ? "failed!" : "OK" ); - - if (failed) - printf (" (%u)", failed); - - printf ("\n\n"); + stream_reset(peer->ibuf); + stream_put(peer->ibuf, NULL, RANDOM_FUZZ); + stream_set_getp(peer->ibuf, RANDOM_FUZZ); + + switch (type) { + case CAPABILITY: + stream_putc(peer->ibuf, BGP_OPEN_OPT_CAP); + stream_putc(peer->ibuf, t->len); + break; + case DYNCAP: + /* for (i = 0; i < BGP_MARKER_SIZE; i++) + stream_putc (peer->, 0xff); + stream_putw (s, 0); + stream_putc (s, BGP_MSG_CAPABILITY);*/ + break; + } + stream_write(peer->ibuf, t->data, t->len); + + printf("%s: %s\n", t->name, t->desc); + + switch (type) { + case CAPABILITY: + len += 2; /* to cover the OPT-Param header */ + case OPT_PARAM: + printf("len: %u\n", len); + /* peek_for_as4 wants getp at capibility*/ + as4 = peek_for_as4_capability(peer, len); + printf("peek_for_as4: as4 is %u\n", as4); + /* and it should leave getp as it found it */ + assert(stream_get_getp(peer->ibuf) == RANDOM_FUZZ); + + ret = bgp_open_option_parse(peer, len, &capability); + break; + case DYNCAP: + ret = bgp_capability_receive(peer, t->len); + break; + default: + printf("unknown type %u\n", type); + exit(1); + } + + if (!ret && t->validate_afi) { + afi_t afi; + safi_t safi; + + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_iana2int(afi_int2iana(t->afi), t->safi, + &afi, &safi)) { + if (t->afi_valid == VALID_AFI) + failed++; + } + printf("MP: %u(%u)/%u(%u): recv %u, nego %u\n", t->afi, afi, + t->safi, safi, peer->afc_recv[afi][safi], + peer->afc_nego[afi][safi]); + + if (t->afi_valid == VALID_AFI) { + + if (!peer->afc_recv[afi][safi]) + failed++; + if (!peer->afc_nego[afi][safi]) + failed++; + } + } + + if (as4 != t->peek_for) { + printf("as4 %u != %u\n", as4, t->peek_for); + failed++; + } + + printf("parsed?: %s\n", ret ? "no" : "yes"); + + if (ret != t->parses) + failed++; + + if (tty) + printf("%s", + (failed > oldfailed) ? VT100_RED "failed!" VT100_RESET + : VT100_GREEN "OK" VT100_RESET); + else + printf("%s", (failed > oldfailed) ? "failed!" : "OK"); + + if (failed) + printf(" (%u)", failed); + + printf("\n\n"); } static struct bgp *bgp; static as_t asn = 100; -int -main (void) +int main(void) { - struct peer *peer; - int i, j; - - conf_bgp_debug_neighbor_events = -1UL; - conf_bgp_debug_packet = -1UL; - conf_bgp_debug_as4 = -1UL; - term_bgp_debug_neighbor_events = -1UL; - term_bgp_debug_packet = -1UL; - term_bgp_debug_as4 = -1UL; - - qobj_init (); - master = thread_master_create(NULL); - bgp_master_init (master); - vrf_init (NULL, NULL, NULL, NULL); - bgp_option_set (BGP_OPT_NO_LISTEN); - - if (fileno (stdout) >= 0) - tty = isatty (fileno (stdout)); - - if (bgp_get (&bgp, &asn, NULL, BGP_INSTANCE_TYPE_DEFAULT)) - return -1; - - peer = peer_create_accept (bgp); - peer->host = (char *) "foo"; - - for (i = AFI_IP; i < AFI_MAX; i++) - for (j = SAFI_UNICAST; j < SAFI_MAX; j++) - { - peer->afc[i][j] = 1; - peer->afc_adv[i][j] = 1; - } - - i = 0; - while (mp_segments[i].name) - parse_test (peer, &mp_segments[i++], CAPABILITY); - - /* These tests assume mp_segments tests set at least - * one of the afc_nego's - */ - i = 0; - while (test_segments[i].name) - parse_test (peer, &test_segments[i++], CAPABILITY); - - i = 0; - while (misc_segments[i].name) - parse_test (peer, &misc_segments[i++], CAPABILITY); - - i = 0; - while (opt_params[i].name) - parse_test (peer, &opt_params[i++], OPT_PARAM); - - SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV); - peer->status = Established; - - i = 0; - while (dynamic_cap_msgs[i].name) - parse_test (peer, &dynamic_cap_msgs[i++], DYNCAP); - - printf ("failures: %d\n", failed); - return failed; + struct peer *peer; + int i, j; + + conf_bgp_debug_neighbor_events = -1UL; + conf_bgp_debug_packet = -1UL; + conf_bgp_debug_as4 = -1UL; + term_bgp_debug_neighbor_events = -1UL; + term_bgp_debug_packet = -1UL; + term_bgp_debug_as4 = -1UL; + + qobj_init(); + master = thread_master_create(NULL); + bgp_master_init(master); + vrf_init(NULL, NULL, NULL, NULL); + bgp_option_set(BGP_OPT_NO_LISTEN); + + if (fileno(stdout) >= 0) + tty = isatty(fileno(stdout)); + + if (bgp_get(&bgp, &asn, NULL, BGP_INSTANCE_TYPE_DEFAULT)) + return -1; + + peer = peer_create_accept(bgp); + peer->host = (char *)"foo"; + + for (i = AFI_IP; i < AFI_MAX; i++) + for (j = SAFI_UNICAST; j < SAFI_MAX; j++) { + peer->afc[i][j] = 1; + peer->afc_adv[i][j] = 1; + } + + i = 0; + while (mp_segments[i].name) + parse_test(peer, &mp_segments[i++], CAPABILITY); + + /* These tests assume mp_segments tests set at least + * one of the afc_nego's + */ + i = 0; + while (test_segments[i].name) + parse_test(peer, &test_segments[i++], CAPABILITY); + + i = 0; + while (misc_segments[i].name) + parse_test(peer, &misc_segments[i++], CAPABILITY); + + i = 0; + while (opt_params[i].name) + parse_test(peer, &opt_params[i++], OPT_PARAM); + + SET_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV); + peer->status = Established; + + i = 0; + while (dynamic_cap_msgs[i].name) + parse_test(peer, &dynamic_cap_msgs[i++], DYNCAP); + + printf("failures: %d\n", failed); + return failed; } diff --git a/tests/bgpd/test_ecommunity.c b/tests/bgpd/test_ecommunity.c index 564d47129..3de8a9fc7 100644 --- a/tests/bgpd/test_ecommunity.c +++ b/tests/bgpd/test_ecommunity.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2007 Sun Microsystems, Inc. * * This file is part of Quagga. @@ -36,127 +36,114 @@ struct thread_master *master = NULL; static int failed = 0; /* specification for a test - what the results should be */ -struct test_spec -{ - const char *shouldbe; /* the string the path should parse to */ +struct test_spec { + const char *shouldbe; /* the string the path should parse to */ }; /* test segments to parse and validate, and use for other tests */ static struct test_segment { - const char *name; - const char *desc; - const u_int8_t data[1024]; - int len; - struct test_spec sp; -} test_segments [] = -{ - { /* 0 */ - "ipaddr", - "rt 1.2.3.4:257", - { ECOMMUNITY_ENCODE_IP, ECOMMUNITY_ROUTE_TARGET, - 0x1,0x2,0x3,0x4, 0x1,0x1 }, - 8, - { "rt 1.2.3.4:257" } - }, - { /* 1 */ - "ipaddr-so", - "soo 1.2.3.4:257", - { ECOMMUNITY_ENCODE_IP, ECOMMUNITY_SITE_ORIGIN, - 0x1,0x2,0x3,0x4, 0x1,0x1}, - 8, - { "soo 1.2.3.4:257" } - }, - { /* 2 */ - "asn", - "rt 23456:987654321", - { ECOMMUNITY_ENCODE_AS, ECOMMUNITY_SITE_ORIGIN, - 0x5b,0xa0, 0x3a,0xde,0x68,0xb1 }, - 8, - { "soo 23456:987654321" } - }, - { /* 3 */ - "asn4", - "rt 168450976:4321", - { ECOMMUNITY_ENCODE_AS4, ECOMMUNITY_SITE_ORIGIN, - 0xa,0xa,0x5b,0xa0, 0x10,0xe1 }, - 8, - { "soo 168450976:4321" } - }, - { NULL, NULL, {0}, 0, { NULL } } -}; + const char *name; + const char *desc; + const u_int8_t data[1024]; + int len; + struct test_spec sp; +} test_segments[] = {{/* 0 */ + "ipaddr", + "rt 1.2.3.4:257", + {ECOMMUNITY_ENCODE_IP, ECOMMUNITY_ROUTE_TARGET, 0x1, 0x2, + 0x3, 0x4, 0x1, 0x1}, + 8, + {"rt 1.2.3.4:257"}}, + {/* 1 */ + "ipaddr-so", + "soo 1.2.3.4:257", + {ECOMMUNITY_ENCODE_IP, ECOMMUNITY_SITE_ORIGIN, 0x1, 0x2, + 0x3, 0x4, 0x1, 0x1}, + 8, + {"soo 1.2.3.4:257"}}, + {/* 2 */ + "asn", + "rt 23456:987654321", + {ECOMMUNITY_ENCODE_AS, ECOMMUNITY_SITE_ORIGIN, 0x5b, 0xa0, + 0x3a, 0xde, 0x68, 0xb1}, + 8, + {"soo 23456:987654321"}}, + {/* 3 */ + "asn4", + "rt 168450976:4321", + {ECOMMUNITY_ENCODE_AS4, ECOMMUNITY_SITE_ORIGIN, 0xa, 0xa, + 0x5b, 0xa0, 0x10, 0xe1}, + 8, + {"soo 168450976:4321"}}, + {NULL, NULL, {0}, 0, {NULL}}}; /* validate the given aspath */ -static int -validate (struct ecommunity *ecom, const struct test_spec *sp) +static int validate(struct ecommunity *ecom, const struct test_spec *sp) { - int fails = 0; - struct ecommunity *etmp; - char *str1, *str2; - - printf ("got:\n %s\n", ecommunity_str (ecom)); - str1 = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_COMMUNITY_LIST, 0); - etmp = ecommunity_str2com (str1, 0, 1); - if (etmp) - str2 = ecommunity_ecom2str (etmp, ECOMMUNITY_FORMAT_COMMUNITY_LIST, 0); - else - str2 = NULL; - - if (strcmp (sp->shouldbe, str1)) - { - failed++; - fails++; - printf ("shouldbe: %s\n%s\n", str1, sp->shouldbe); - } - if (!etmp || strcmp (str1, str2)) - { - failed++; - fails++; - printf ("dogfood: in %s\n" - " in->out %s\n", - str1, - (etmp && str2) ? str2 : "NULL"); - } - ecommunity_free (&etmp); - XFREE (MTYPE_ECOMMUNITY_STR, str1); - XFREE (MTYPE_ECOMMUNITY_STR, str2); - - return fails; + int fails = 0; + struct ecommunity *etmp; + char *str1, *str2; + + printf("got:\n %s\n", ecommunity_str(ecom)); + str1 = ecommunity_ecom2str(ecom, ECOMMUNITY_FORMAT_COMMUNITY_LIST, 0); + etmp = ecommunity_str2com(str1, 0, 1); + if (etmp) + str2 = ecommunity_ecom2str(etmp, + ECOMMUNITY_FORMAT_COMMUNITY_LIST, 0); + else + str2 = NULL; + + if (strcmp(sp->shouldbe, str1)) { + failed++; + fails++; + printf("shouldbe: %s\n%s\n", str1, sp->shouldbe); + } + if (!etmp || strcmp(str1, str2)) { + failed++; + fails++; + printf("dogfood: in %s\n" + " in->out %s\n", + str1, (etmp && str2) ? str2 : "NULL"); + } + ecommunity_free(&etmp); + XFREE(MTYPE_ECOMMUNITY_STR, str1); + XFREE(MTYPE_ECOMMUNITY_STR, str2); + + return fails; } /* basic parsing test */ -static void -parse_test (struct test_segment *t) +static void parse_test(struct test_segment *t) { - struct ecommunity *ecom; - - printf ("%s: %s\n", t->name, t->desc); + struct ecommunity *ecom; + + printf("%s: %s\n", t->name, t->desc); + + ecom = ecommunity_parse((u_int8_t *)t->data, t->len); - ecom = ecommunity_parse ((u_int8_t *)t->data, t->len); + printf("ecom: %s\nvalidating...:\n", ecommunity_str(ecom)); - printf ("ecom: %s\nvalidating...:\n", ecommunity_str (ecom)); + if (!validate(ecom, &t->sp)) + printf("OK\n"); + else + printf("failed\n"); - if (!validate (ecom, &t->sp)) - printf ("OK\n"); - else - printf ("failed\n"); - - printf ("\n"); - ecommunity_unintern (&ecom); + printf("\n"); + ecommunity_unintern(&ecom); } - -int -main (void) + +int main(void) { - int i = 0; - ecommunity_init(); - while (test_segments[i].name) - parse_test (&test_segments[i++]); - - printf ("failures: %d\n", failed); - //printf ("aspath count: %ld\n", aspath_count()); - return failed; - //return (failed + aspath_count()); + int i = 0; + ecommunity_init(); + while (test_segments[i].name) + parse_test(&test_segments[i++]); + + printf("failures: %d\n", failed); + // printf ("aspath count: %ld\n", aspath_count()); + return failed; + // return (failed + aspath_count()); } diff --git a/tests/bgpd/test_mp_attr.c b/tests/bgpd/test_mp_attr.c index f6f0fb70a..7c0afa1b9 100644 --- a/tests/bgpd/test_mp_attr.c +++ b/tests/bgpd/test_mp_attr.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2008 Sun Microsystems, Inc. * * This file is part of Quagga. @@ -42,7 +42,6 @@ #define VT100_GREEN "\x1b[32m" #define VT100_YELLOW "\x1b[33m" - #define CAPABILITY 0 #define DYNCAP 1 #define OPT_PARAM 2 @@ -56,729 +55,1080 @@ static int tty = 0; /* test segments to parse and validate, and use for other tests */ static struct test_segment { - const char *name; - const char *desc; - const u_char data[1024]; - int len; + const char *name; + const char *desc; + const u_char data[1024]; + int len; #define SHOULD_PARSE 0 #define SHOULD_ERR -1 - int parses; /* whether it should parse or not */ - - /* AFI/SAFI validation */ - afi_t afi; - safi_t safi; + int parses; /* whether it should parse or not */ + + /* AFI/SAFI validation */ + afi_t afi; + safi_t safi; #define VALID_AFI 1 #define INVALID_AFI 0 - int afi_valid; -} mp_reach_segments [] = -{ - { "IPv6", - "IPV6 MP Reach, global nexthop, 1 NLRI", - { - /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, - /* nexthop bytes */ 16, - /* Nexthop (global) */ 0xff, 0xfe, 0x1, 0x2, - 0xaa, 0xbb, 0xcc, 0xdd, - 0x3, 0x4, 0x5, 0x6, - 0xa1, 0xa2, 0xa3, 0xa4, - /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 32, 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ - }, - (4 + 16 + 1 + 5), - SHOULD_PARSE, - AFI_IP6, SAFI_UNICAST, VALID_AFI, - }, - { "IPv6-2", - "IPV6 MP Reach, global nexthop, 2 NLRIs", - { - /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, - /* nexthop bytes */ 16, - /* Nexthop (global) */ 0xff, 0xfe, 0x1, 0x2, /* ffee:102:... */ - 0xaa, 0xbb, 0xcc, 0xdd, - 0x3, 0x4, 0x5, 0x6, - 0xa1, 0xa2, 0xa3, 0xa4, - /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 32, - 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ - 64, - 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ - 0x0, 0x2, 0x0, 0x3, - }, - (4 + 16 + 1 + 5 + 9), - SHOULD_PARSE, - AFI_IP6, SAFI_UNICAST, VALID_AFI, - }, - { "IPv6-default", - "IPV6 MP Reach, global nexthop, 2 NLRIs + default", - { - /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, - /* nexthop bytes */ 16, - /* Nexthop (global) */ 0xff, 0xfe, 0x1, 0x2, - 0xaa, 0xbb, 0xcc, 0xdd, - 0x3, 0x4, 0x5, 0x6, - 0xa1, 0xa2, 0xa3, 0xa4, - /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 32, - 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ - 64, - 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ - 0x0, 0x2, 0x0, 0x3, - 0x0, /* ::/0 */ - }, - (4 + 16 + 1 + 5 + 9 + 1), - SHOULD_PARSE, - AFI_IP6, SAFI_UNICAST, VALID_AFI, - }, - { "IPv6-lnh", - "IPV6 MP Reach, global+local nexthops, 2 NLRIs + default", - { - /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, - /* nexthop bytes */ 32, - /* Nexthop (global) */ 0xff, 0xfe, 0x1, 0x2, /* fffe:102:... */ - 0xaa, 0xbb, 0xcc, 0xdd, - 0x3, 0x4, 0x5, 0x6, - 0xa1, 0xa2, 0xa3, 0xa4, - /* Nexthop (local) */ 0xfe, 0x80, 0x0, 0x0, /* fe80::210:2ff:.. */ - 0x0, 0x0, 0x0, 0x0, - 0x2, 0x10, 0x2, 0xff, - 0x1, 0x2, 0x3, 0x4, - /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 32, - 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ - 64, - 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ - 0x0, 0x2, 0x0, 0x3, - 0x0, /* ::/0 */ - }, - (4 + 32 + 1 + 5 + 9 + 1), - SHOULD_PARSE, - AFI_IP6, SAFI_UNICAST, VALID_AFI, - }, - { "IPv6-nhlen", - "IPV6 MP Reach, inappropriate nexthop length", - { - /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, - /* nexthop bytes */ 4, - /* Nexthop (global) */ 0xff, 0xfe, 0x1, 0x2, /* fffe:102:... */ - 0xaa, 0xbb, 0xcc, 0xdd, - 0x3, 0x4, 0x5, 0x6, - 0xa1, 0xa2, 0xa3, 0xa4, - /* Nexthop (local) */ 0xfe, 0x80, 0x0, 0x0, /* fe80::210:2ff:.. */ - 0x0, 0x0, 0x0, 0x0, - 0x2, 0x10, 0x2, 0xff, - 0x1, 0x2, 0x3, 0x4, - /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 32, - 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ - 64, - 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ - 0x0, 0x2, 0x0, 0x3, - 0x0, /* ::/0 */ - }, - (4 + 32 + 1 + 5 + 9 + 1), - SHOULD_ERR, - AFI_IP6, SAFI_UNICAST, VALID_AFI, - }, - { "IPv6-nhlen2", - "IPV6 MP Reach, invalid nexthop length", - { - /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, - /* nexthop bytes */ 5, - /* Nexthop (global) */ 0xff, 0xfe, 0x1, 0x2, /* fffe:102:... */ - 0xaa, 0xbb, 0xcc, 0xdd, - 0x3, 0x4, 0x5, 0x6, - 0xa1, 0xa2, 0xa3, 0xa4, - /* Nexthop (local) */ 0xfe, 0x80, 0x0, 0x0, /* fe80::210:2ff:.. */ - 0x0, 0x0, 0x0, 0x0, - 0x2, 0x10, 0x2, 0xff, - 0x1, 0x2, 0x3, 0x4, - /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 32, - 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ - 64, - 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ - 0x0, 0x2, 0x0, 0x3, - 0x0, /* ::/0 */ - }, - (4 + 32 + 1 + 5 + 9 + 1), - SHOULD_ERR, - AFI_IP6, SAFI_UNICAST, VALID_AFI, - }, - { "IPv6-nhlen3", - "IPV6 MP Reach, nexthop length overflow", - { - /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, - /* nexthop bytes */ 32, - /* Nexthop (global) */ 0xff, 0xfe, 0x1, 0x2, /* fffe:102:... */ - 0xaa, 0xbb, 0xcc, 0xdd, - 0x3, 0x4, 0x5, 0x6, - 0xa1, 0xa2, 0xa3, 0xa4, - }, - (4 + 16), - SHOULD_ERR, - AFI_IP6, SAFI_UNICAST, VALID_AFI, - }, - { "IPv6-nhlen4", - "IPV6 MP Reach, nexthop length short", - { - /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, - /* nexthop bytes */ 16, - /* Nexthop (global) */ 0xff, 0xfe, 0x1, 0x2, /* fffe:102:... */ - 0xaa, 0xbb, 0xcc, 0xdd, - 0x3, 0x4, 0x5, 0x6, - 0xa1, 0xa2, 0xa3, 0xa4, - /* Nexthop (local) */ 0xfe, 0x80, 0x0, 0x0, /* fe80::210:2ff:.. */ - 0x0, 0x0, 0x0, 0x0, - 0x2, 0x10, 0x2, 0xff, - 0x1, 0x2, 0x3, 0x4, - /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 32, - 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ - 64, - 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ - 0x0, 0x2, 0x0, 0x3, - 0x0, /* ::/0 */ - }, - (4 + 32 + 1 + 5 + 9 + 1), - SHOULD_ERR, - AFI_IP6, SAFI_UNICAST, VALID_AFI, - }, - { "IPv6-nlri", - "IPV6 MP Reach, NLRI bitlen overflow", - { - /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, - /* nexthop bytes */ 32, - /* Nexthop (global) */ 0xff, 0xfe, 0x1, 0x2, /* fffe:102:... */ - 0xaa, 0xbb, 0xcc, 0xdd, - 0x3, 0x4, 0x5, 0x6, - 0xa1, 0xa2, 0xa3, 0xa4, - /* Nexthop (local) */ 0xfe, 0x80, 0x0, 0x0, /* fe80::210:2ff:.. */ - 0x0, 0x0, 0x0, 0x0, - 0x2, 0x10, 0x2, 0xff, - 0x1, 0x2, 0x3, 0x4, - /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 120, - 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ - 64, - 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ - 0x0, 0x2, 0x0, 0x3, - 0, /* ::/0 */ - }, - (4 + 32 + 1 + 5 + 9 + 1), - SHOULD_ERR, - AFI_IP6, SAFI_UNICAST, VALID_AFI, - }, - { "IPv4", - "IPv4 MP Reach, 2 NLRIs + default", - { - /* AFI / SAFI */ 0x0, AFI_IP, SAFI_UNICAST, - /* nexthop bytes */ 4, - /* Nexthop */ 192, 168, 0, 1, - /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ - 17, 10, 2, 3, /* 10.2.3/17 */ - 0, /* 0/0 */ - }, - (4 + 4 + 1 + 3 + 4 + 1), - SHOULD_PARSE, - AFI_IP, SAFI_UNICAST, VALID_AFI, - }, - { "IPv4-nhlen", - "IPv4 MP Reach, nexthop lenth overflow", - { - /* AFI / SAFI */ 0x0, AFI_IP, SAFI_UNICAST, - /* nexthop bytes */ 32, - /* Nexthop */ 192, 168, 0, 1, - /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ - 17, 10, 2, 3, /* 10.2.3/17 */ - 0, /* 0/0 */ - }, - (4 + 4 + 1 + 3 + 4 + 1), - SHOULD_ERR, - AFI_IP, SAFI_UNICAST, VALID_AFI, - }, - { "IPv4-nlrilen", - "IPv4 MP Reach, nlri lenth overflow", - { - /* AFI / SAFI */ 0x0, AFI_IP, SAFI_UNICAST, - /* nexthop bytes */ 4, - /* Nexthop */ 192, 168, 0, 1, - /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ - 30, 10, - 0, /* 0/0 */ - }, - (4 + 4 + 1 + 3 + 2 + 1), - SHOULD_ERR, - AFI_IP, SAFI_UNICAST, VALID_AFI, - }, - { "IPv4-VPNv4", - "IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs", - { - /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, - /* nexthop bytes */ 12, - /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ - 0, 0, 0, 0, - /* Nexthop */ 192, 168, 0, 1, - /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 88 + 16, - 0, 1, 2, /* tag */ - /* rd, 8 octets */ - 0, 0, /* RD_TYPE_AS */ - 0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */ - 10, 1, /* 10.1/16 */ - 88 + 17, - 0xff, 0, 0, /* tag */ - /* rd, 8 octets */ - 0, 0, /* RD_TYPE_IP */ - 192, 168, 0, 1, /* IPv4 */ - 10, 2, 3, /* 10.2.3/17 */ - }, - (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)), - SHOULD_PARSE, - AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, - }, - { "IPv4-VPNv4-bogus-plen", - "IPv4/MPLS-labeled VPN MP Reach, RD, Nexthop, NLRI / bogus p'len", - { - /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, - /* nexthop bytes */ 12, - /* RD */ 0, 0, 1, 2, - 0, 0xff, 3, 4, - /* Nexthop */ 192, 168, 0, 1, - /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ - 17, 10, 2, 3, /* 10.2.3/17 */ - 0, /* 0/0 */ - }, - (3 + 1 + 3*4 + 1 + 3 + 4 + 1), - SHOULD_ERR, - AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, - }, - { "IPv4-VPNv4-plen1-short", - "IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, 1st plen short", - { - /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, - /* nexthop bytes */ 12, - /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ - 0, 0, 0, 0, - /* Nexthop */ 192, 168, 0, 1, - /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 88 + 1, - 0, 1, 2, /* tag */ - /* rd, 8 octets */ - 0, 0, /* RD_TYPE_AS */ - 0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */ - 10, 1, /* 10.1/16 */ - 88 + 17, - 0xff, 0, 0, /* tag */ - /* rd, 8 octets */ - 0, 0, /* RD_TYPE_IP */ - 192, 168, 0, 1, /* IPv4 */ - 10, 2, 3, /* 10.2.3/17 */ - }, - (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)), - SHOULD_ERR, - AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, - }, - { "IPv4-VPNv4-plen1-long", - "IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, 1st plen long", - { - /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, - /* nexthop bytes */ 12, - /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ - 0, 0, 0, 0, - /* Nexthop */ 192, 168, 0, 1, - /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 88 + 32, - 0, 1, 2, /* tag */ - /* rd, 8 octets */ - 0, 0, /* RD_TYPE_AS */ - 0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */ - 10, 1, /* 10.1/16 */ - 88 + 17, - 0xff, 0, 0, /* tag */ - /* rd, 8 octets */ - 0, 0, /* RD_TYPE_IP */ - 192, 168, 0, 1, /* IPv4 */ - 10, 2, 3, /* 10.2.3/17 */ - }, - (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)), - SHOULD_ERR, - AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, - }, - { "IPv4-VPNv4-plenn-long", - "IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRIs, last plen long", - { - /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, - /* nexthop bytes */ 12, - /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ - 0, 0, 0, 0, - /* Nexthop */ 192, 168, 0, 1, - /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 88 + 16, - 0, 1, 2, /* tag */ - /* rd, 8 octets */ - 0, 0, /* RD_TYPE_AS */ - 0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */ - 10, 1, /* 10.1/16 */ - 88 + 17, - 0xff, 0, 0, /* tag */ - /* rd, 8 octets */ - 0, 0, /* RD_TYPE_IP */ - 192, 168, 0, 1, /* IPv4 */ - 10, 2, 3, /* 10.2.3/17 */ - 88 + 1, /* bogus */ - }, - (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3) + 1), - SHOULD_ERR, - AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, - }, - { "IPv4-VPNv4-plenn-short", - "IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, last plen short", - { - /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, - /* nexthop bytes */ 12, - /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ - 0, 0, 0, 0, - /* Nexthop */ 192, 168, 0, 1, - /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 88 + 16, - 0, 1, 2, /* tag */ - /* rd, 8 octets */ - 0, 0, /* RD_TYPE_AS */ - 0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */ - 10, 1, /* 10.1/16 */ - 88 + 2, - 0xff, 0, 0, /* tag */ - /* rd, 8 octets */ - 0, 0, /* RD_TYPE_IP */ - 192, 168, 0, 1, /* IPv4 */ - 10, 2, 3, /* 10.2.3/17 */ - }, - (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)), - SHOULD_ERR, - AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, - }, - { "IPv4-VPNv4-bogus-rd-type", - "IPv4/VPNv4 MP Reach, RD, NH, 2 NLRI, unknown RD in 1st (log, but parse)", - { - /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, - /* nexthop bytes */ 12, - /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ - 0, 0, 0, 0, - /* Nexthop */ 192, 168, 0, 1, - /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 88 + 16, - 0, 1, 2, /* tag */ - /* rd, 8 octets */ - 0xff, 0, /* Bogus RD */ - 0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */ - 10, 1, /* 10.1/16 */ - 88 + 17, - 0xff, 0, 0, /* tag */ - /* rd, 8 octets */ - 0, 0, /* RD_TYPE_IP */ - 192, 168, 0, 1, /* IPv4 */ - 10, 2, 3, /* 10.2.3/17 */ - }, - (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)), - SHOULD_PARSE, - AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, - }, - { "IPv4-VPNv4-0-nlri", - "IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRI, 3rd 0 bogus", - { - /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, - /* nexthop bytes */ 12, - /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ - 0, 0, 0, 0, - /* Nexthop */ 192, 168, 0, 1, - /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 88 + 16, - 0, 1, 2, /* tag */ - /* rd, 8 octets */ - 0, 0, /* RD_TYPE_AS */ - 0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */ - 10, 1, /* 10.1/16 */ - 88 + 17, - 0xff, 0, 0, /* tag */ - /* rd, 8 octets */ - 0, 0, /* RD_TYPE_IP */ - 192, 168, 0, 1, /* IPv4 */ - 10, 2, 3, /* 10.2.3/17 */ - 0 /* 0/0, bogus for vpnv4 ?? */ - }, - (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3) + 1), - SHOULD_ERR, - AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, - }, - - /* From bug #385 */ - { "IPv6-bug", - "IPv6, global nexthop, 1 default NLRI", - { - /* AFI / SAFI */ 0x0, 0x2, 0x1, - /* nexthop bytes */ 0x20, - /* Nexthop (global) */ 0x20, 0x01, 0x04, 0x70, - 0x00, 0x01, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, - /* Nexthop (local) */ 0xfe, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x02, 0x0c, 0xdb, 0xff, - 0xfe, 0xfe, 0xeb, 0x00, - /* SNPA (defunct, MBZ) */ 0, - /* NLRI tuples */ /* Should have 0 here for ::/0, but dont */ - }, - 37, - SHOULD_ERR, - AFI_IP6, SAFI_UNICAST, VALID_AFI, - }, - - { NULL, NULL, {0}, 0, 0} -}; + int afi_valid; +} mp_reach_segments[] = { + { + "IPv6", + "IPV6 MP Reach, global nexthop, 1 NLRI", + { + /* AFI / SAFI */ 0x0, + AFI_IP6, + SAFI_UNICAST, + /* nexthop bytes */ 16, + /* Nexthop (global) */ 0xff, + 0xfe, + 0x1, + 0x2, + 0xaa, + 0xbb, + 0xcc, + 0xdd, + 0x3, + 0x4, + 0x5, + 0x6, + 0xa1, + 0xa2, + 0xa3, + 0xa4, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 32, + 0xff, + 0xfe, + 0x1, + 0x2, /* fffe:102::/32 */ + }, + (4 + 16 + 1 + 5), + SHOULD_PARSE, + AFI_IP6, + SAFI_UNICAST, + VALID_AFI, + }, + { + "IPv6-2", + "IPV6 MP Reach, global nexthop, 2 NLRIs", + { + /* AFI / SAFI */ 0x0, + AFI_IP6, + SAFI_UNICAST, + /* nexthop bytes */ 16, + /* Nexthop (global) */ 0xff, + 0xfe, + 0x1, + 0x2, /* ffee:102:... */ + 0xaa, + 0xbb, + 0xcc, + 0xdd, + 0x3, + 0x4, + 0x5, + 0x6, + 0xa1, + 0xa2, + 0xa3, + 0xa4, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 32, + 0xff, + 0xfe, + 0x1, + 0x2, /* fffe:102::/32 */ + 64, + 0xff, + 0xfe, + 0x0, + 0x1, /* fffe:1:2:3::/64 */ + 0x0, + 0x2, + 0x0, + 0x3, + }, + (4 + 16 + 1 + 5 + 9), + SHOULD_PARSE, + AFI_IP6, + SAFI_UNICAST, + VALID_AFI, + }, + { + "IPv6-default", + "IPV6 MP Reach, global nexthop, 2 NLRIs + default", + { + /* AFI / SAFI */ 0x0, + AFI_IP6, + SAFI_UNICAST, + /* nexthop bytes */ 16, + /* Nexthop (global) */ 0xff, + 0xfe, + 0x1, + 0x2, + 0xaa, + 0xbb, + 0xcc, + 0xdd, + 0x3, + 0x4, + 0x5, + 0x6, + 0xa1, + 0xa2, + 0xa3, + 0xa4, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 32, + 0xff, + 0xfe, + 0x1, + 0x2, /* fffe:102::/32 */ + 64, + 0xff, + 0xfe, + 0x0, + 0x1, /* fffe:1:2:3::/64 */ + 0x0, + 0x2, + 0x0, + 0x3, + 0x0, /* ::/0 */ + }, + (4 + 16 + 1 + 5 + 9 + 1), + SHOULD_PARSE, + AFI_IP6, + SAFI_UNICAST, + VALID_AFI, + }, + { + "IPv6-lnh", + "IPV6 MP Reach, global+local nexthops, 2 NLRIs + default", + { + /* AFI / SAFI */ 0x0, + AFI_IP6, + SAFI_UNICAST, + /* nexthop bytes */ 32, + /* Nexthop (global) */ 0xff, + 0xfe, + 0x1, + 0x2, /* fffe:102:... */ + 0xaa, + 0xbb, + 0xcc, + 0xdd, + 0x3, + 0x4, + 0x5, + 0x6, + 0xa1, + 0xa2, + 0xa3, + 0xa4, + /* Nexthop (local) */ 0xfe, + 0x80, + 0x0, + 0x0, /* fe80::210:2ff:.. */ + 0x0, + 0x0, + 0x0, + 0x0, + 0x2, + 0x10, + 0x2, + 0xff, + 0x1, + 0x2, + 0x3, + 0x4, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 32, + 0xff, + 0xfe, + 0x1, + 0x2, /* fffe:102::/32 */ + 64, + 0xff, + 0xfe, + 0x0, + 0x1, /* fffe:1:2:3::/64 */ + 0x0, + 0x2, + 0x0, + 0x3, + 0x0, /* ::/0 */ + }, + (4 + 32 + 1 + 5 + 9 + 1), + SHOULD_PARSE, + AFI_IP6, + SAFI_UNICAST, + VALID_AFI, + }, + { + "IPv6-nhlen", + "IPV6 MP Reach, inappropriate nexthop length", + { + /* AFI / SAFI */ 0x0, + AFI_IP6, + SAFI_UNICAST, + /* nexthop bytes */ 4, + /* Nexthop (global) */ 0xff, + 0xfe, + 0x1, + 0x2, /* fffe:102:... */ + 0xaa, + 0xbb, + 0xcc, + 0xdd, + 0x3, + 0x4, + 0x5, + 0x6, + 0xa1, + 0xa2, + 0xa3, + 0xa4, + /* Nexthop (local) */ 0xfe, + 0x80, + 0x0, + 0x0, /* fe80::210:2ff:.. */ + 0x0, + 0x0, + 0x0, + 0x0, + 0x2, + 0x10, + 0x2, + 0xff, + 0x1, + 0x2, + 0x3, + 0x4, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 32, + 0xff, + 0xfe, + 0x1, + 0x2, /* fffe:102::/32 */ + 64, + 0xff, + 0xfe, + 0x0, + 0x1, /* fffe:1:2:3::/64 */ + 0x0, + 0x2, + 0x0, + 0x3, + 0x0, /* ::/0 */ + }, + (4 + 32 + 1 + 5 + 9 + 1), + SHOULD_ERR, + AFI_IP6, + SAFI_UNICAST, + VALID_AFI, + }, + { + "IPv6-nhlen2", + "IPV6 MP Reach, invalid nexthop length", + { + /* AFI / SAFI */ 0x0, + AFI_IP6, + SAFI_UNICAST, + /* nexthop bytes */ 5, + /* Nexthop (global) */ 0xff, + 0xfe, + 0x1, + 0x2, /* fffe:102:... */ + 0xaa, + 0xbb, + 0xcc, + 0xdd, + 0x3, + 0x4, + 0x5, + 0x6, + 0xa1, + 0xa2, + 0xa3, + 0xa4, + /* Nexthop (local) */ 0xfe, + 0x80, + 0x0, + 0x0, /* fe80::210:2ff:.. */ + 0x0, + 0x0, + 0x0, + 0x0, + 0x2, + 0x10, + 0x2, + 0xff, + 0x1, + 0x2, + 0x3, + 0x4, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 32, + 0xff, + 0xfe, + 0x1, + 0x2, /* fffe:102::/32 */ + 64, + 0xff, + 0xfe, + 0x0, + 0x1, /* fffe:1:2:3::/64 */ + 0x0, + 0x2, + 0x0, + 0x3, + 0x0, /* ::/0 */ + }, + (4 + 32 + 1 + 5 + 9 + 1), + SHOULD_ERR, + AFI_IP6, + SAFI_UNICAST, + VALID_AFI, + }, + { + "IPv6-nhlen3", + "IPV6 MP Reach, nexthop length overflow", + { + /* AFI / SAFI */ 0x0, + AFI_IP6, + SAFI_UNICAST, + /* nexthop bytes */ 32, + /* Nexthop (global) */ 0xff, + 0xfe, + 0x1, + 0x2, /* fffe:102:... */ + 0xaa, + 0xbb, + 0xcc, + 0xdd, + 0x3, + 0x4, + 0x5, + 0x6, + 0xa1, + 0xa2, + 0xa3, + 0xa4, + }, + (4 + 16), + SHOULD_ERR, + AFI_IP6, + SAFI_UNICAST, + VALID_AFI, + }, + { + "IPv6-nhlen4", + "IPV6 MP Reach, nexthop length short", + { + /* AFI / SAFI */ 0x0, + AFI_IP6, + SAFI_UNICAST, + /* nexthop bytes */ 16, + /* Nexthop (global) */ 0xff, + 0xfe, + 0x1, + 0x2, /* fffe:102:... */ + 0xaa, + 0xbb, + 0xcc, + 0xdd, + 0x3, + 0x4, + 0x5, + 0x6, + 0xa1, + 0xa2, + 0xa3, + 0xa4, + /* Nexthop (local) */ 0xfe, + 0x80, + 0x0, + 0x0, /* fe80::210:2ff:.. */ + 0x0, + 0x0, + 0x0, + 0x0, + 0x2, + 0x10, + 0x2, + 0xff, + 0x1, + 0x2, + 0x3, + 0x4, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 32, + 0xff, + 0xfe, + 0x1, + 0x2, /* fffe:102::/32 */ + 64, + 0xff, + 0xfe, + 0x0, + 0x1, /* fffe:1:2:3::/64 */ + 0x0, + 0x2, + 0x0, + 0x3, + 0x0, /* ::/0 */ + }, + (4 + 32 + 1 + 5 + 9 + 1), + SHOULD_ERR, + AFI_IP6, + SAFI_UNICAST, + VALID_AFI, + }, + { + "IPv6-nlri", + "IPV6 MP Reach, NLRI bitlen overflow", + { + /* AFI / SAFI */ 0x0, + AFI_IP6, + SAFI_UNICAST, + /* nexthop bytes */ 32, + /* Nexthop (global) */ 0xff, + 0xfe, + 0x1, + 0x2, /* fffe:102:... */ + 0xaa, + 0xbb, + 0xcc, + 0xdd, + 0x3, + 0x4, + 0x5, + 0x6, + 0xa1, + 0xa2, + 0xa3, + 0xa4, + /* Nexthop (local) */ 0xfe, + 0x80, + 0x0, + 0x0, /* fe80::210:2ff:.. */ + 0x0, + 0x0, + 0x0, + 0x0, + 0x2, + 0x10, + 0x2, + 0xff, + 0x1, + 0x2, + 0x3, + 0x4, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 120, + 0xff, + 0xfe, + 0x1, + 0x2, /* fffe:102::/32 */ + 64, + 0xff, + 0xfe, + 0x0, + 0x1, /* fffe:1:2:3::/64 */ + 0x0, + 0x2, + 0x0, + 0x3, + 0, /* ::/0 */ + }, + (4 + 32 + 1 + 5 + 9 + 1), + SHOULD_ERR, + AFI_IP6, + SAFI_UNICAST, + VALID_AFI, + }, + { + "IPv4", + "IPv4 MP Reach, 2 NLRIs + default", + { + /* AFI / SAFI */ 0x0, AFI_IP, SAFI_UNICAST, + /* nexthop bytes */ 4, + /* Nexthop */ 192, 168, 0, 1, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ + 17, 10, 2, 3, /* 10.2.3/17 */ + 0, /* 0/0 */ + }, + (4 + 4 + 1 + 3 + 4 + 1), + SHOULD_PARSE, + AFI_IP, + SAFI_UNICAST, + VALID_AFI, + }, + { + "IPv4-nhlen", + "IPv4 MP Reach, nexthop lenth overflow", + { + /* AFI / SAFI */ 0x0, AFI_IP, SAFI_UNICAST, + /* nexthop bytes */ 32, + /* Nexthop */ 192, 168, 0, 1, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ + 17, 10, 2, 3, /* 10.2.3/17 */ + 0, /* 0/0 */ + }, + (4 + 4 + 1 + 3 + 4 + 1), + SHOULD_ERR, + AFI_IP, + SAFI_UNICAST, + VALID_AFI, + }, + { + "IPv4-nlrilen", + "IPv4 MP Reach, nlri lenth overflow", + { + /* AFI / SAFI */ 0x0, AFI_IP, SAFI_UNICAST, + /* nexthop bytes */ 4, + /* Nexthop */ 192, 168, 0, 1, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ + 30, 10, 0, /* 0/0 */ + }, + (4 + 4 + 1 + 3 + 2 + 1), + SHOULD_ERR, + AFI_IP, + SAFI_UNICAST, + VALID_AFI, + }, + { + "IPv4-VPNv4", + "IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs", + { + /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, + /* nexthop bytes */ 12, + /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ + 0, 0, 0, 0, + /* Nexthop */ 192, 168, 0, 1, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 88 + 16, 0, 1, 2, /* tag */ + /* rd, 8 octets */ + 0, 0, /* RD_TYPE_AS */ + 0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */ + 10, 1, /* 10.1/16 */ + 88 + 17, 0xff, 0, 0, /* tag */ + /* rd, 8 octets */ + 0, 0, /* RD_TYPE_IP */ + 192, 168, 0, 1, /* IPv4 */ + 10, 2, 3, /* 10.2.3/17 */ + }, + (4 + 12 + 1 + (1 + 3 + 8 + 2) + (1 + 3 + 8 + 3)), + SHOULD_PARSE, + AFI_IP, + IANA_SAFI_MPLS_VPN, + VALID_AFI, + }, + { + "IPv4-VPNv4-bogus-plen", + "IPv4/MPLS-labeled VPN MP Reach, RD, Nexthop, NLRI / bogus p'len", + { + /* AFI / SAFI */ 0x0, + AFI_IP, + IANA_SAFI_MPLS_VPN, + /* nexthop bytes */ 12, + /* RD */ 0, + 0, + 1, + 2, + 0, + 0xff, + 3, + 4, + /* Nexthop */ 192, + 168, + 0, + 1, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 16, + 10, + 1, /* 10.1/16 */ + 17, + 10, + 2, + 3, /* 10.2.3/17 */ + 0, /* 0/0 */ + }, + (3 + 1 + 3 * 4 + 1 + 3 + 4 + 1), + SHOULD_ERR, + AFI_IP, + IANA_SAFI_MPLS_VPN, + VALID_AFI, + }, + { + "IPv4-VPNv4-plen1-short", + "IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, 1st plen short", + { + /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, + /* nexthop bytes */ 12, + /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ + 0, 0, 0, 0, + /* Nexthop */ 192, 168, 0, 1, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 88 + 1, 0, 1, 2, /* tag */ + /* rd, 8 octets */ + 0, 0, /* RD_TYPE_AS */ + 0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */ + 10, 1, /* 10.1/16 */ + 88 + 17, 0xff, 0, 0, /* tag */ + /* rd, 8 octets */ + 0, 0, /* RD_TYPE_IP */ + 192, 168, 0, 1, /* IPv4 */ + 10, 2, 3, /* 10.2.3/17 */ + }, + (4 + 12 + 1 + (1 + 3 + 8 + 2) + (1 + 3 + 8 + 3)), + SHOULD_ERR, + AFI_IP, + IANA_SAFI_MPLS_VPN, + VALID_AFI, + }, + { + "IPv4-VPNv4-plen1-long", + "IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, 1st plen long", + { + /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, + /* nexthop bytes */ 12, + /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ + 0, 0, 0, 0, + /* Nexthop */ 192, 168, 0, 1, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 88 + 32, 0, 1, 2, /* tag */ + /* rd, 8 octets */ + 0, 0, /* RD_TYPE_AS */ + 0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */ + 10, 1, /* 10.1/16 */ + 88 + 17, 0xff, 0, 0, /* tag */ + /* rd, 8 octets */ + 0, 0, /* RD_TYPE_IP */ + 192, 168, 0, 1, /* IPv4 */ + 10, 2, 3, /* 10.2.3/17 */ + }, + (4 + 12 + 1 + (1 + 3 + 8 + 2) + (1 + 3 + 8 + 3)), + SHOULD_ERR, + AFI_IP, + IANA_SAFI_MPLS_VPN, + VALID_AFI, + }, + { + "IPv4-VPNv4-plenn-long", + "IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRIs, last plen long", + { + /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, + /* nexthop bytes */ 12, + /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ + 0, 0, 0, 0, + /* Nexthop */ 192, 168, 0, 1, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 88 + 16, 0, 1, 2, /* tag */ + /* rd, 8 octets */ + 0, 0, /* RD_TYPE_AS */ + 0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */ + 10, 1, /* 10.1/16 */ + 88 + 17, 0xff, 0, 0, /* tag */ + /* rd, 8 octets */ + 0, 0, /* RD_TYPE_IP */ + 192, 168, 0, 1, /* IPv4 */ + 10, 2, 3, /* 10.2.3/17 */ + 88 + 1, /* bogus */ + }, + (4 + 12 + 1 + (1 + 3 + 8 + 2) + (1 + 3 + 8 + 3) + 1), + SHOULD_ERR, + AFI_IP, + IANA_SAFI_MPLS_VPN, + VALID_AFI, + }, + { + "IPv4-VPNv4-plenn-short", + "IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, last plen short", + { + /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, + /* nexthop bytes */ 12, + /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ + 0, 0, 0, 0, + /* Nexthop */ 192, 168, 0, 1, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 88 + 16, 0, 1, 2, /* tag */ + /* rd, 8 octets */ + 0, 0, /* RD_TYPE_AS */ + 0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */ + 10, 1, /* 10.1/16 */ + 88 + 2, 0xff, 0, 0, /* tag */ + /* rd, 8 octets */ + 0, 0, /* RD_TYPE_IP */ + 192, 168, 0, 1, /* IPv4 */ + 10, 2, 3, /* 10.2.3/17 */ + }, + (4 + 12 + 1 + (1 + 3 + 8 + 2) + (1 + 3 + 8 + 3)), + SHOULD_ERR, + AFI_IP, + IANA_SAFI_MPLS_VPN, + VALID_AFI, + }, + { + "IPv4-VPNv4-bogus-rd-type", + "IPv4/VPNv4 MP Reach, RD, NH, 2 NLRI, unknown RD in 1st (log, but parse)", + { + /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, + /* nexthop bytes */ 12, + /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ + 0, 0, 0, 0, + /* Nexthop */ 192, 168, 0, 1, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 88 + 16, 0, 1, 2, /* tag */ + /* rd, 8 octets */ + 0xff, 0, /* Bogus RD */ + 0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */ + 10, 1, /* 10.1/16 */ + 88 + 17, 0xff, 0, 0, /* tag */ + /* rd, 8 octets */ + 0, 0, /* RD_TYPE_IP */ + 192, 168, 0, 1, /* IPv4 */ + 10, 2, 3, /* 10.2.3/17 */ + }, + (4 + 12 + 1 + (1 + 3 + 8 + 2) + (1 + 3 + 8 + 3)), + SHOULD_PARSE, + AFI_IP, + IANA_SAFI_MPLS_VPN, + VALID_AFI, + }, + { + "IPv4-VPNv4-0-nlri", + "IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRI, 3rd 0 bogus", + { + /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, + /* nexthop bytes */ 12, + /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ + 0, 0, 0, 0, + /* Nexthop */ 192, 168, 0, 1, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 88 + 16, 0, 1, 2, /* tag */ + /* rd, 8 octets */ + 0, 0, /* RD_TYPE_AS */ + 0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */ + 10, 1, /* 10.1/16 */ + 88 + 17, 0xff, 0, 0, /* tag */ + /* rd, 8 octets */ + 0, 0, /* RD_TYPE_IP */ + 192, 168, 0, 1, /* IPv4 */ + 10, 2, 3, /* 10.2.3/17 */ + 0 /* 0/0, bogus for vpnv4 ?? */ + }, + (4 + 12 + 1 + (1 + 3 + 8 + 2) + (1 + 3 + 8 + 3) + 1), + SHOULD_ERR, + AFI_IP, + IANA_SAFI_MPLS_VPN, + VALID_AFI, + }, + + /* From bug #385 */ + { + "IPv6-bug", + "IPv6, global nexthop, 1 default NLRI", + { + /* AFI / SAFI */ 0x0, + 0x2, + 0x1, + /* nexthop bytes */ 0x20, + /* Nexthop (global) */ 0x20, + 0x01, + 0x04, + 0x70, + 0x00, + 0x01, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + /* Nexthop (local) */ 0xfe, + 0x80, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x0c, + 0xdb, + 0xff, + 0xfe, + 0xfe, + 0xeb, + 0x00, + /* SNPA (defunct, MBZ) */ 0, + /* NLRI tuples */ /* Should have 0 here for ::/0, but + dont */ + }, + 37, + SHOULD_ERR, + AFI_IP6, + SAFI_UNICAST, + VALID_AFI, + }, + + {NULL, NULL, {0}, 0, 0}}; /* MP_UNREACH_NLRI tests */ -static struct test_segment mp_unreach_segments [] = -{ - { "IPv6-unreach", - "IPV6 MP Unreach, 1 NLRI", - { - /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, - /* NLRI tuples */ 32, 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ - }, - (3 + 5), - SHOULD_PARSE, - AFI_IP6, SAFI_UNICAST, VALID_AFI, - }, - { "IPv6-unreach2", - "IPV6 MP Unreach, 2 NLRIs", - { - /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, - /* NLRI tuples */ 32, - 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ - 64, - 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ - 0x0, 0x2, 0x0, 0x3, - }, - (3 + 5 + 9), - SHOULD_PARSE, - AFI_IP6, SAFI_UNICAST, VALID_AFI, - }, - { "IPv6-unreach-default", - "IPV6 MP Unreach, 2 NLRIs + default", - { - /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, - /* NLRI tuples */ 32, - 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ - 64, - 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ - 0x0, 0x2, 0x0, 0x3, - 0x0, /* ::/0 */ - }, - (3 + 5 + 9 + 1), - SHOULD_PARSE, - AFI_IP6, SAFI_UNICAST, VALID_AFI, - }, - { "IPv6-unreach-nlri", - "IPV6 MP Unreach, NLRI bitlen overflow", - { - /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, - /* NLRI tuples */ 120, - 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ - 64, - 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ - 0x0, 0x2, 0x0, 0x3, - 0, /* ::/0 */ - }, - (3 + 5 + 9 + 1), - SHOULD_ERR, - AFI_IP6, SAFI_UNICAST, VALID_AFI, - }, - { "IPv4-unreach", - "IPv4 MP Unreach, 2 NLRIs + default", - { - /* AFI / SAFI */ 0x0, AFI_IP, SAFI_UNICAST, - /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ - 17, 10, 2, 3, /* 10.2.3/17 */ - 0, /* 0/0 */ - }, - (3 + 3 + 4 + 1), - SHOULD_PARSE, - AFI_IP, SAFI_UNICAST, VALID_AFI, - }, - { "IPv4-unreach-nlrilen", - "IPv4 MP Unreach, nlri length overflow", - { - /* AFI / SAFI */ 0x0, AFI_IP, SAFI_UNICAST, - /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ - 30, 10, - 0, /* 0/0 */ - }, - (3 + 3 + 2 + 1), - SHOULD_ERR, - AFI_IP, SAFI_UNICAST, VALID_AFI, - }, - { "IPv4-unreach-VPNv4", - "IPv4/MPLS-labeled VPN MP Unreach, RD, 3 NLRIs", - { - /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, - /* NLRI tuples */ 88 + 16, - 0, 1, 2, /* tag */ - /* rd, 8 octets */ - 0, 0, /* RD_TYPE_AS */ - 0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */ - 10, 1, /* 10.1/16 */ - 88 + 17, - 0xff, 0, 0, /* tag */ - /* rd, 8 octets */ - 0, 0, /* RD_TYPE_IP */ - 192, 168, 0, 1, /* IPv4 */ - 10, 2, 3, /* 10.2.3/17 */ - }, - (3 + (1+3+8+2) + (1+3+8+3)), - SHOULD_PARSE, - AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, - }, - { NULL, NULL, {0}, 0, 0} -}; +static struct test_segment mp_unreach_segments[] = { + { + "IPv6-unreach", + "IPV6 MP Unreach, 1 NLRI", + { + /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, + /* NLRI tuples */ 32, 0xff, 0xfe, 0x1, + 0x2, /* fffe:102::/32 */ + }, + (3 + 5), + SHOULD_PARSE, + AFI_IP6, + SAFI_UNICAST, + VALID_AFI, + }, + { + "IPv6-unreach2", + "IPV6 MP Unreach, 2 NLRIs", + { + /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, + /* NLRI tuples */ 32, 0xff, 0xfe, 0x1, + 0x2, /* fffe:102::/32 */ + 64, 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ + 0x0, 0x2, 0x0, 0x3, + }, + (3 + 5 + 9), + SHOULD_PARSE, + AFI_IP6, + SAFI_UNICAST, + VALID_AFI, + }, + { + "IPv6-unreach-default", + "IPV6 MP Unreach, 2 NLRIs + default", + { + /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, + /* NLRI tuples */ 32, 0xff, 0xfe, 0x1, + 0x2, /* fffe:102::/32 */ + 64, 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ + 0x0, 0x2, 0x0, 0x3, 0x0, /* ::/0 */ + }, + (3 + 5 + 9 + 1), + SHOULD_PARSE, + AFI_IP6, + SAFI_UNICAST, + VALID_AFI, + }, + { + "IPv6-unreach-nlri", + "IPV6 MP Unreach, NLRI bitlen overflow", + { + /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, + /* NLRI tuples */ 120, 0xff, 0xfe, 0x1, + 0x2, /* fffe:102::/32 */ + 64, 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ + 0x0, 0x2, 0x0, 0x3, 0, /* ::/0 */ + }, + (3 + 5 + 9 + 1), + SHOULD_ERR, + AFI_IP6, + SAFI_UNICAST, + VALID_AFI, + }, + { + "IPv4-unreach", + "IPv4 MP Unreach, 2 NLRIs + default", + { + /* AFI / SAFI */ 0x0, AFI_IP, SAFI_UNICAST, + /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ + 17, 10, 2, 3, /* 10.2.3/17 */ + 0, /* 0/0 */ + }, + (3 + 3 + 4 + 1), + SHOULD_PARSE, + AFI_IP, + SAFI_UNICAST, + VALID_AFI, + }, + { + "IPv4-unreach-nlrilen", + "IPv4 MP Unreach, nlri length overflow", + { + /* AFI / SAFI */ 0x0, AFI_IP, SAFI_UNICAST, + /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ + 30, 10, 0, /* 0/0 */ + }, + (3 + 3 + 2 + 1), + SHOULD_ERR, + AFI_IP, + SAFI_UNICAST, + VALID_AFI, + }, + { + "IPv4-unreach-VPNv4", + "IPv4/MPLS-labeled VPN MP Unreach, RD, 3 NLRIs", + { + /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, + /* NLRI tuples */ 88 + 16, 0, 1, 2, /* tag */ + /* rd, 8 octets */ + 0, 0, /* RD_TYPE_AS */ + 0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */ + 10, 1, /* 10.1/16 */ + 88 + 17, 0xff, 0, 0, /* tag */ + /* rd, 8 octets */ + 0, 0, /* RD_TYPE_IP */ + 192, 168, 0, 1, /* IPv4 */ + 10, 2, 3, /* 10.2.3/17 */ + }, + (3 + (1 + 3 + 8 + 2) + (1 + 3 + 8 + 3)), + SHOULD_PARSE, + AFI_IP, + IANA_SAFI_MPLS_VPN, + VALID_AFI, + }, + {NULL, NULL, {0}, 0, 0}}; /* nlri_parse indicates 0 on successful parse, and -1 otherwise. * attr_parse indicates BGP_ATTR_PARSE_PROCEED/0 on success, * and BGP_ATTR_PARSE_ERROR/-1 or lower negative ret on err. */ -static void -handle_result (struct peer *peer, struct test_segment *t, - int parse_ret, int nlri_ret) +static void handle_result(struct peer *peer, struct test_segment *t, + int parse_ret, int nlri_ret) { - int oldfailed = failed; - - printf ("mp attr parsed?: %s\n", parse_ret ? "no" : "yes"); - if (!parse_ret) - printf ("nrli parsed?: %s\n", nlri_ret ? "no" : "yes"); - printf ("should parse?: %s\n", t->parses ? "no" : "yes"); - - if ((parse_ret != 0 || nlri_ret != 0) != (t->parses != 0)) - failed++; - - - if (tty) - printf ("%s", (failed > oldfailed) ? VT100_RED "failed!" VT100_RESET - : VT100_GREEN "OK" VT100_RESET); - else - printf ("%s", (failed > oldfailed) ? "failed!" : "OK" ); - - if (failed) - printf (" (%u)", failed); - - printf ("\n\n"); + int oldfailed = failed; + + printf("mp attr parsed?: %s\n", parse_ret ? "no" : "yes"); + if (!parse_ret) + printf("nrli parsed?: %s\n", nlri_ret ? "no" : "yes"); + printf("should parse?: %s\n", t->parses ? "no" : "yes"); + + if ((parse_ret != 0 || nlri_ret != 0) != (t->parses != 0)) + failed++; + + + if (tty) + printf("%s", + (failed > oldfailed) ? VT100_RED "failed!" VT100_RESET + : VT100_GREEN "OK" VT100_RESET); + else + printf("%s", (failed > oldfailed) ? "failed!" : "OK"); + + if (failed) + printf(" (%u)", failed); + + printf("\n\n"); } /* basic parsing test */ -static void -parse_test (struct peer *peer, struct test_segment *t, int type) +static void parse_test(struct peer *peer, struct test_segment *t, int type) { - int parse_ret = 0, nlri_ret = 0; - struct attr attr = { }; - struct bgp_nlri nlri = { }; - struct bgp_attr_parser_args attr_args = { - .peer = peer, - .length = t->len, - .total = 1, - .attr = &attr, - .type = type, - .flags = BGP_ATTR_FLAG_OPTIONAL, - .startp = BGP_INPUT_PNT (peer), - }; + int parse_ret = 0, nlri_ret = 0; + struct attr attr = {}; + struct bgp_nlri nlri = {}; + struct bgp_attr_parser_args attr_args = { + .peer = peer, + .length = t->len, + .total = 1, + .attr = &attr, + .type = type, + .flags = BGP_ATTR_FLAG_OPTIONAL, + .startp = BGP_INPUT_PNT(peer), + }; #define RANDOM_FUZZ 35 - - stream_reset (peer->ibuf); - stream_put (peer->ibuf, NULL, RANDOM_FUZZ); - stream_set_getp (peer->ibuf, RANDOM_FUZZ); - - stream_write (peer->ibuf, t->data, t->len); - - printf ("%s: %s\n", t->name, t->desc); - - if (type == BGP_ATTR_MP_REACH_NLRI) - parse_ret = bgp_mp_reach_parse (&attr_args, &nlri); - else - parse_ret = bgp_mp_unreach_parse (&attr_args, &nlri); - if (!parse_ret) - { - iana_afi_t pkt_afi; - safi_t pkt_safi; - - /* Convert AFI, SAFI to internal values, check. */ - if (bgp_map_afi_safi_int2iana (nlri.afi, nlri.safi, &pkt_afi, &pkt_safi)) - assert (0); - - printf ("MP: %u(%u)/%u(%u): recv %u, nego %u\n", - nlri.afi , pkt_afi, nlri.safi, pkt_safi, - peer->afc_recv[nlri.afi][nlri.safi], - peer->afc_nego[nlri.afi][nlri.safi]); - } - - if (!parse_ret) - { - if (type == BGP_ATTR_MP_REACH_NLRI) - nlri_ret = bgp_nlri_parse (peer, &attr, &nlri, 0); - else - nlri_ret = bgp_nlri_parse (peer, &attr, &nlri, 1); - } - handle_result (peer, t, parse_ret, nlri_ret); + stream_reset(peer->ibuf); + stream_put(peer->ibuf, NULL, RANDOM_FUZZ); + stream_set_getp(peer->ibuf, RANDOM_FUZZ); + + stream_write(peer->ibuf, t->data, t->len); + + printf("%s: %s\n", t->name, t->desc); + + if (type == BGP_ATTR_MP_REACH_NLRI) + parse_ret = bgp_mp_reach_parse(&attr_args, &nlri); + else + parse_ret = bgp_mp_unreach_parse(&attr_args, &nlri); + if (!parse_ret) { + iana_afi_t pkt_afi; + safi_t pkt_safi; + + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_int2iana(nlri.afi, nlri.safi, &pkt_afi, + &pkt_safi)) + assert(0); + + printf("MP: %u(%u)/%u(%u): recv %u, nego %u\n", nlri.afi, + pkt_afi, nlri.safi, pkt_safi, + peer->afc_recv[nlri.afi][nlri.safi], + peer->afc_nego[nlri.afi][nlri.safi]); + } + + if (!parse_ret) { + if (type == BGP_ATTR_MP_REACH_NLRI) + nlri_ret = bgp_nlri_parse(peer, &attr, &nlri, 0); + else + nlri_ret = bgp_nlri_parse(peer, &attr, &nlri, 1); + } + handle_result(peer, t, parse_ret, nlri_ret); } static struct bgp *bgp; static as_t asn = 100; -int -main (void) +int main(void) { - struct peer *peer; - int i, j; - - conf_bgp_debug_neighbor_events = -1UL; - conf_bgp_debug_packet = -1UL; - conf_bgp_debug_as4 = -1UL; - term_bgp_debug_neighbor_events = -1UL; - term_bgp_debug_packet = -1UL; - term_bgp_debug_as4 = -1UL; - - qobj_init (); - master = thread_master_create(NULL); - bgp_master_init (master); - vrf_init (NULL, NULL, NULL, NULL); - bgp_option_set (BGP_OPT_NO_LISTEN); - bgp_attr_init (); - - if (fileno (stdout) >= 0) - tty = isatty (fileno (stdout)); - - if (bgp_get (&bgp, &asn, NULL, BGP_INSTANCE_TYPE_DEFAULT)) - return -1; - - peer = peer_create_accept (bgp); - peer->host = (char *)"foo"; - peer->status = Established; - - for (i = AFI_IP; i < AFI_MAX; i++) - for (j = SAFI_UNICAST; j < SAFI_MAX; j++) - { - peer->afc[i][j] = 1; - peer->afc_adv[i][j] = 1; - } - - i = 0; - while (mp_reach_segments[i].name) - parse_test (peer, &mp_reach_segments[i++], BGP_ATTR_MP_REACH_NLRI); - - i = 0; - while (mp_unreach_segments[i].name) - parse_test (peer, &mp_unreach_segments[i++], BGP_ATTR_MP_UNREACH_NLRI); - - printf ("failures: %d\n", failed); - return failed; + struct peer *peer; + int i, j; + + conf_bgp_debug_neighbor_events = -1UL; + conf_bgp_debug_packet = -1UL; + conf_bgp_debug_as4 = -1UL; + term_bgp_debug_neighbor_events = -1UL; + term_bgp_debug_packet = -1UL; + term_bgp_debug_as4 = -1UL; + + qobj_init(); + master = thread_master_create(NULL); + bgp_master_init(master); + vrf_init(NULL, NULL, NULL, NULL); + bgp_option_set(BGP_OPT_NO_LISTEN); + bgp_attr_init(); + + if (fileno(stdout) >= 0) + tty = isatty(fileno(stdout)); + + if (bgp_get(&bgp, &asn, NULL, BGP_INSTANCE_TYPE_DEFAULT)) + return -1; + + peer = peer_create_accept(bgp); + peer->host = (char *)"foo"; + peer->status = Established; + + for (i = AFI_IP; i < AFI_MAX; i++) + for (j = SAFI_UNICAST; j < SAFI_MAX; j++) { + peer->afc[i][j] = 1; + peer->afc_adv[i][j] = 1; + } + + i = 0; + while (mp_reach_segments[i].name) + parse_test(peer, &mp_reach_segments[i++], + BGP_ATTR_MP_REACH_NLRI); + + i = 0; + while (mp_unreach_segments[i].name) + parse_test(peer, &mp_unreach_segments[i++], + BGP_ATTR_MP_UNREACH_NLRI); + + printf("failures: %d\n", failed); + return failed; } diff --git a/tests/bgpd/test_mpath.c b/tests/bgpd/test_mpath.c index 3309a9322..ccd3b6f4c 100644 --- a/tests/bgpd/test_mpath.c +++ b/tests/bgpd/test_mpath.c @@ -48,13 +48,12 @@ #define TEST_PASSED 0 #define TEST_FAILED -1 -#define EXPECT_TRUE(expr, res) \ - if (!(expr)) \ - { \ - printf ("Test failure in %s line %u: %s\n", \ - __FUNCTION__, __LINE__, #expr); \ - (res) = TEST_FAILED; \ - } +#define EXPECT_TRUE(expr, res) \ + if (!(expr)) { \ + printf("Test failure in %s line %u: %s\n", __FUNCTION__, \ + __LINE__, #expr); \ + (res) = TEST_FAILED; \ + } typedef struct testcase_t__ testcase_t; @@ -63,224 +62,227 @@ typedef int (*test_run_func)(testcase_t *); typedef int (*test_cleanup_func)(testcase_t *); struct testcase_t__ { - const char *desc; - void *test_data; - void *verify_data; - void *tmp_data; - test_setup_func setup; - test_run_func run; - test_cleanup_func cleanup; + const char *desc; + void *test_data; + void *verify_data; + void *tmp_data; + test_setup_func setup; + test_run_func run; + test_cleanup_func cleanup; }; /* need these to link in libbgp */ struct thread_master *master = NULL; struct zclient *zclient; -struct zebra_privs_t bgpd_privs = -{ - .user = NULL, - .group = NULL, - .vty_group = NULL, +struct zebra_privs_t bgpd_privs = { + .user = NULL, + .group = NULL, + .vty_group = NULL, }; static int tty = 0; /* Create fake bgp instance */ -static struct bgp * -bgp_create_fake (as_t *as, const char *name) +static struct bgp *bgp_create_fake(as_t *as, const char *name) { - struct bgp *bgp; - afi_t afi; - safi_t safi; - - if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL) - return NULL; - - bgp_lock (bgp); - //bgp->peer_self = peer_new (bgp); - //bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement"); - - bgp->peer = list_new (); - //bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp; - - bgp->group = list_new (); - //bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - bgp->route[afi][safi] = bgp_table_init (afi, safi); - bgp->aggregate[afi][safi] = bgp_table_init (afi, safi); - bgp->rib[afi][safi] = bgp_table_init (afi, safi); - bgp->maxpaths[afi][safi].maxpaths_ebgp = MULTIPATH_NUM; - bgp->maxpaths[afi][safi].maxpaths_ibgp = MULTIPATH_NUM; - } - - bgp_scan_init (bgp); - bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF; - bgp->default_holdtime = BGP_DEFAULT_HOLDTIME; - bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE; - bgp->restart_time = BGP_DEFAULT_RESTART_TIME; - bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME; - - bgp->as = *as; - - if (name) - bgp->name = strdup (name); - - return bgp; + struct bgp *bgp; + afi_t afi; + safi_t safi; + + if ((bgp = XCALLOC(MTYPE_BGP, sizeof(struct bgp))) == NULL) + return NULL; + + bgp_lock(bgp); + // bgp->peer_self = peer_new (bgp); + // bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static + // announcement"); + + bgp->peer = list_new(); + // bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp; + + bgp->group = list_new(); + // bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + bgp->route[afi][safi] = bgp_table_init(afi, safi); + bgp->aggregate[afi][safi] = bgp_table_init(afi, safi); + bgp->rib[afi][safi] = bgp_table_init(afi, safi); + bgp->maxpaths[afi][safi].maxpaths_ebgp = MULTIPATH_NUM; + bgp->maxpaths[afi][safi].maxpaths_ibgp = MULTIPATH_NUM; + } + + bgp_scan_init(bgp); + bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF; + bgp->default_holdtime = BGP_DEFAULT_HOLDTIME; + bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE; + bgp->restart_time = BGP_DEFAULT_RESTART_TIME; + bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME; + + bgp->as = *as; + + if (name) + bgp->name = strdup(name); + + return bgp; } /*========================================================= * Testcase for maximum-paths configuration */ -static int -setup_bgp_cfg_maximum_paths (testcase_t *t) +static int setup_bgp_cfg_maximum_paths(testcase_t *t) { - as_t asn = 1; - t->tmp_data = bgp_create_fake (&asn, NULL); - if (!t->tmp_data) - return -1; - return 0; + as_t asn = 1; + t->tmp_data = bgp_create_fake(&asn, NULL); + if (!t->tmp_data) + return -1; + return 0; } -static int -run_bgp_cfg_maximum_paths (testcase_t *t) +static int run_bgp_cfg_maximum_paths(testcase_t *t) { - afi_t afi; - safi_t safi; - struct bgp *bgp; - int api_result; - int test_result = TEST_PASSED; - - bgp = t->tmp_data; - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - /* test bgp_maximum_paths_set */ - api_result = bgp_maximum_paths_set (bgp, afi, safi, BGP_PEER_EBGP, 10, 0); - EXPECT_TRUE (api_result == 0, test_result); - api_result = bgp_maximum_paths_set (bgp, afi, safi, BGP_PEER_IBGP, 10, 0); - EXPECT_TRUE (api_result == 0, test_result); - EXPECT_TRUE (bgp->maxpaths[afi][safi].maxpaths_ebgp == 10, test_result); - EXPECT_TRUE (bgp->maxpaths[afi][safi].maxpaths_ibgp == 10, test_result); - - /* test bgp_maximum_paths_unset */ - api_result = bgp_maximum_paths_unset (bgp, afi, safi, BGP_PEER_EBGP); - EXPECT_TRUE (api_result == 0, test_result); - api_result = bgp_maximum_paths_unset (bgp, afi, safi, BGP_PEER_IBGP); - EXPECT_TRUE (api_result == 0, test_result); - EXPECT_TRUE ((bgp->maxpaths[afi][safi].maxpaths_ebgp == - MULTIPATH_NUM), test_result); - EXPECT_TRUE ((bgp->maxpaths[afi][safi].maxpaths_ibgp == - MULTIPATH_NUM), test_result); - } - - return test_result; + afi_t afi; + safi_t safi; + struct bgp *bgp; + int api_result; + int test_result = TEST_PASSED; + + bgp = t->tmp_data; + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + /* test bgp_maximum_paths_set */ + api_result = bgp_maximum_paths_set( + bgp, afi, safi, BGP_PEER_EBGP, 10, 0); + EXPECT_TRUE(api_result == 0, test_result); + api_result = bgp_maximum_paths_set( + bgp, afi, safi, BGP_PEER_IBGP, 10, 0); + EXPECT_TRUE(api_result == 0, test_result); + EXPECT_TRUE(bgp->maxpaths[afi][safi].maxpaths_ebgp + == 10, + test_result); + EXPECT_TRUE(bgp->maxpaths[afi][safi].maxpaths_ibgp + == 10, + test_result); + + /* test bgp_maximum_paths_unset */ + api_result = bgp_maximum_paths_unset(bgp, afi, safi, + BGP_PEER_EBGP); + EXPECT_TRUE(api_result == 0, test_result); + api_result = bgp_maximum_paths_unset(bgp, afi, safi, + BGP_PEER_IBGP); + EXPECT_TRUE(api_result == 0, test_result); + EXPECT_TRUE((bgp->maxpaths[afi][safi].maxpaths_ebgp + == MULTIPATH_NUM), + test_result); + EXPECT_TRUE((bgp->maxpaths[afi][safi].maxpaths_ibgp + == MULTIPATH_NUM), + test_result); + } + + return test_result; } -static int -cleanup_bgp_cfg_maximum_paths (testcase_t *t) +static int cleanup_bgp_cfg_maximum_paths(testcase_t *t) { - return bgp_delete ((struct bgp *)t->tmp_data); + return bgp_delete((struct bgp *)t->tmp_data); } testcase_t test_bgp_cfg_maximum_paths = { - .desc = "Test bgp maximum-paths config", - .setup = setup_bgp_cfg_maximum_paths, - .run = run_bgp_cfg_maximum_paths, - .cleanup = cleanup_bgp_cfg_maximum_paths, + .desc = "Test bgp maximum-paths config", + .setup = setup_bgp_cfg_maximum_paths, + .run = run_bgp_cfg_maximum_paths, + .cleanup = cleanup_bgp_cfg_maximum_paths, }; /*========================================================= * Testcase for bgp_mp_list */ struct peer test_mp_list_peer[] = { - { .local_as = 1, .as = 2 }, - { .local_as = 1, .as = 2 }, - { .local_as = 1, .as = 2 }, - { .local_as = 1, .as = 2 }, - { .local_as = 1, .as = 2 }, + {.local_as = 1, .as = 2}, {.local_as = 1, .as = 2}, + {.local_as = 1, .as = 2}, {.local_as = 1, .as = 2}, + {.local_as = 1, .as = 2}, }; -int test_mp_list_peer_count = sizeof (test_mp_list_peer)/ sizeof (struct peer); +int test_mp_list_peer_count = sizeof(test_mp_list_peer) / sizeof(struct peer); struct attr test_mp_list_attr[4]; struct bgp_info test_mp_list_info[] = { - { .peer = &test_mp_list_peer[0], .attr = &test_mp_list_attr[0] }, - { .peer = &test_mp_list_peer[1], .attr = &test_mp_list_attr[1] }, - { .peer = &test_mp_list_peer[2], .attr = &test_mp_list_attr[1] }, - { .peer = &test_mp_list_peer[3], .attr = &test_mp_list_attr[2] }, - { .peer = &test_mp_list_peer[4], .attr = &test_mp_list_attr[3] }, + {.peer = &test_mp_list_peer[0], .attr = &test_mp_list_attr[0]}, + {.peer = &test_mp_list_peer[1], .attr = &test_mp_list_attr[1]}, + {.peer = &test_mp_list_peer[2], .attr = &test_mp_list_attr[1]}, + {.peer = &test_mp_list_peer[3], .attr = &test_mp_list_attr[2]}, + {.peer = &test_mp_list_peer[4], .attr = &test_mp_list_attr[3]}, }; int test_mp_list_info_count = - sizeof (test_mp_list_info)/sizeof (struct bgp_info); + sizeof(test_mp_list_info) / sizeof(struct bgp_info); -static int -setup_bgp_mp_list (testcase_t *t) +static int setup_bgp_mp_list(testcase_t *t) { - test_mp_list_attr[0].nexthop.s_addr = 0x01010101; - test_mp_list_attr[1].nexthop.s_addr = 0x02020202; - test_mp_list_attr[2].nexthop.s_addr = 0x03030303; - test_mp_list_attr[3].nexthop.s_addr = 0x04040404; - - if ((test_mp_list_peer[0].su_remote = sockunion_str2su ("1.1.1.1")) == NULL) - return -1; - if ((test_mp_list_peer[1].su_remote = sockunion_str2su ("2.2.2.2")) == NULL) - return -1; - if ((test_mp_list_peer[2].su_remote = sockunion_str2su ("3.3.3.3")) == NULL) - return -1; - if ((test_mp_list_peer[3].su_remote = sockunion_str2su ("4.4.4.4")) == NULL) - return -1; - if ((test_mp_list_peer[4].su_remote = sockunion_str2su ("5.5.5.5")) == NULL) - return -1; - - return 0; + test_mp_list_attr[0].nexthop.s_addr = 0x01010101; + test_mp_list_attr[1].nexthop.s_addr = 0x02020202; + test_mp_list_attr[2].nexthop.s_addr = 0x03030303; + test_mp_list_attr[3].nexthop.s_addr = 0x04040404; + + if ((test_mp_list_peer[0].su_remote = sockunion_str2su("1.1.1.1")) + == NULL) + return -1; + if ((test_mp_list_peer[1].su_remote = sockunion_str2su("2.2.2.2")) + == NULL) + return -1; + if ((test_mp_list_peer[2].su_remote = sockunion_str2su("3.3.3.3")) + == NULL) + return -1; + if ((test_mp_list_peer[3].su_remote = sockunion_str2su("4.4.4.4")) + == NULL) + return -1; + if ((test_mp_list_peer[4].su_remote = sockunion_str2su("5.5.5.5")) + == NULL) + return -1; + + return 0; } -static int -run_bgp_mp_list (testcase_t *t) +static int run_bgp_mp_list(testcase_t *t) { - struct list mp_list; - struct listnode *mp_node; - struct bgp_info *info; - int i; - int test_result = TEST_PASSED; - bgp_mp_list_init (&mp_list); - EXPECT_TRUE (listcount(&mp_list) == 0, test_result); - - bgp_mp_list_add (&mp_list, &test_mp_list_info[1]); - bgp_mp_list_add (&mp_list, &test_mp_list_info[4]); - bgp_mp_list_add (&mp_list, &test_mp_list_info[2]); - bgp_mp_list_add (&mp_list, &test_mp_list_info[3]); - bgp_mp_list_add (&mp_list, &test_mp_list_info[0]); - - for (i = 0, mp_node = mp_list.head; i < test_mp_list_info_count; - i++, mp_node = listnextnode(mp_node)) - { - info = listgetdata(mp_node); - EXPECT_TRUE (info == &test_mp_list_info[i], test_result); - } - - bgp_mp_list_clear (&mp_list); - EXPECT_TRUE (listcount(&mp_list) == 0, test_result); - - return test_result; + struct list mp_list; + struct listnode *mp_node; + struct bgp_info *info; + int i; + int test_result = TEST_PASSED; + bgp_mp_list_init(&mp_list); + EXPECT_TRUE(listcount(&mp_list) == 0, test_result); + + bgp_mp_list_add(&mp_list, &test_mp_list_info[1]); + bgp_mp_list_add(&mp_list, &test_mp_list_info[4]); + bgp_mp_list_add(&mp_list, &test_mp_list_info[2]); + bgp_mp_list_add(&mp_list, &test_mp_list_info[3]); + bgp_mp_list_add(&mp_list, &test_mp_list_info[0]); + + for (i = 0, mp_node = mp_list.head; i < test_mp_list_info_count; + i++, mp_node = listnextnode(mp_node)) { + info = listgetdata(mp_node); + EXPECT_TRUE(info == &test_mp_list_info[i], test_result); + } + + bgp_mp_list_clear(&mp_list); + EXPECT_TRUE(listcount(&mp_list) == 0, test_result); + + return test_result; } -static int -cleanup_bgp_mp_list (testcase_t *t) +static int cleanup_bgp_mp_list(testcase_t *t) { - int i; + int i; - for (i = 0; i < test_mp_list_peer_count; i++) - sockunion_free (test_mp_list_peer[i].su_remote); + for (i = 0; i < test_mp_list_peer_count; i++) + sockunion_free(test_mp_list_peer[i].su_remote); - return 0; + return 0; } testcase_t test_bgp_mp_list = { - .desc = "Test bgp_mp_list", - .setup = setup_bgp_mp_list, - .run = run_bgp_mp_list, - .cleanup = cleanup_bgp_mp_list, + .desc = "Test bgp_mp_list", + .setup = setup_bgp_mp_list, + .run = run_bgp_mp_list, + .cleanup = cleanup_bgp_mp_list, }; /*========================================================= @@ -289,195 +291,185 @@ testcase_t test_bgp_mp_list = { struct bgp_node test_rn; -static int -setup_bgp_info_mpath_update (testcase_t *t) +static int setup_bgp_info_mpath_update(testcase_t *t) { - int i; - str2prefix ("42.1.1.0/24", &test_rn.p); - setup_bgp_mp_list (t); - for (i = 0; i < test_mp_list_info_count; i++) - bgp_info_add (&test_rn, &test_mp_list_info[i]); - return 0; + int i; + str2prefix("42.1.1.0/24", &test_rn.p); + setup_bgp_mp_list(t); + for (i = 0; i < test_mp_list_info_count; i++) + bgp_info_add(&test_rn, &test_mp_list_info[i]); + return 0; } -static int -run_bgp_info_mpath_update (testcase_t *t) +static int run_bgp_info_mpath_update(testcase_t *t) { - struct bgp_info *new_best, *old_best, *mpath; - struct list mp_list; - struct bgp_maxpaths_cfg mp_cfg = { 3, 3 }; - int test_result = TEST_PASSED; - bgp_mp_list_init (&mp_list); - bgp_mp_list_add (&mp_list, &test_mp_list_info[4]); - bgp_mp_list_add (&mp_list, &test_mp_list_info[3]); - bgp_mp_list_add (&mp_list, &test_mp_list_info[0]); - bgp_mp_list_add (&mp_list, &test_mp_list_info[1]); - new_best = &test_mp_list_info[3]; - old_best = NULL; - bgp_info_mpath_update (&test_rn, new_best, old_best, &mp_list, &mp_cfg); - bgp_mp_list_clear (&mp_list); - EXPECT_TRUE (bgp_info_mpath_count (new_best) == 2, test_result); - mpath = bgp_info_mpath_first (new_best); - EXPECT_TRUE (mpath == &test_mp_list_info[0], test_result); - EXPECT_TRUE (CHECK_FLAG (mpath->flags, BGP_INFO_MULTIPATH), test_result); - mpath = bgp_info_mpath_next (mpath); - EXPECT_TRUE (mpath == &test_mp_list_info[1], test_result); - EXPECT_TRUE (CHECK_FLAG (mpath->flags, BGP_INFO_MULTIPATH), test_result); - - bgp_mp_list_add (&mp_list, &test_mp_list_info[0]); - bgp_mp_list_add (&mp_list, &test_mp_list_info[1]); - new_best = &test_mp_list_info[0]; - old_best = &test_mp_list_info[3]; - bgp_info_mpath_update (&test_rn, new_best, old_best, &mp_list, &mp_cfg); - bgp_mp_list_clear (&mp_list); - EXPECT_TRUE (bgp_info_mpath_count (new_best) == 1, test_result); - mpath = bgp_info_mpath_first (new_best); - EXPECT_TRUE (mpath == &test_mp_list_info[1], test_result); - EXPECT_TRUE (CHECK_FLAG (mpath->flags, BGP_INFO_MULTIPATH), test_result); - EXPECT_TRUE (!CHECK_FLAG (test_mp_list_info[0].flags, BGP_INFO_MULTIPATH), - test_result); - - return test_result; + struct bgp_info *new_best, *old_best, *mpath; + struct list mp_list; + struct bgp_maxpaths_cfg mp_cfg = {3, 3}; + int test_result = TEST_PASSED; + bgp_mp_list_init(&mp_list); + bgp_mp_list_add(&mp_list, &test_mp_list_info[4]); + bgp_mp_list_add(&mp_list, &test_mp_list_info[3]); + bgp_mp_list_add(&mp_list, &test_mp_list_info[0]); + bgp_mp_list_add(&mp_list, &test_mp_list_info[1]); + new_best = &test_mp_list_info[3]; + old_best = NULL; + bgp_info_mpath_update(&test_rn, new_best, old_best, &mp_list, &mp_cfg); + bgp_mp_list_clear(&mp_list); + EXPECT_TRUE(bgp_info_mpath_count(new_best) == 2, test_result); + mpath = bgp_info_mpath_first(new_best); + EXPECT_TRUE(mpath == &test_mp_list_info[0], test_result); + EXPECT_TRUE(CHECK_FLAG(mpath->flags, BGP_INFO_MULTIPATH), test_result); + mpath = bgp_info_mpath_next(mpath); + EXPECT_TRUE(mpath == &test_mp_list_info[1], test_result); + EXPECT_TRUE(CHECK_FLAG(mpath->flags, BGP_INFO_MULTIPATH), test_result); + + bgp_mp_list_add(&mp_list, &test_mp_list_info[0]); + bgp_mp_list_add(&mp_list, &test_mp_list_info[1]); + new_best = &test_mp_list_info[0]; + old_best = &test_mp_list_info[3]; + bgp_info_mpath_update(&test_rn, new_best, old_best, &mp_list, &mp_cfg); + bgp_mp_list_clear(&mp_list); + EXPECT_TRUE(bgp_info_mpath_count(new_best) == 1, test_result); + mpath = bgp_info_mpath_first(new_best); + EXPECT_TRUE(mpath == &test_mp_list_info[1], test_result); + EXPECT_TRUE(CHECK_FLAG(mpath->flags, BGP_INFO_MULTIPATH), test_result); + EXPECT_TRUE(!CHECK_FLAG(test_mp_list_info[0].flags, BGP_INFO_MULTIPATH), + test_result); + + return test_result; } -static int -cleanup_bgp_info_mpath_update (testcase_t *t) +static int cleanup_bgp_info_mpath_update(testcase_t *t) { - int i; + int i; - for (i = 0; i < test_mp_list_peer_count; i++) - sockunion_free (test_mp_list_peer[i].su_remote); + for (i = 0; i < test_mp_list_peer_count; i++) + sockunion_free(test_mp_list_peer[i].su_remote); - return 0; + return 0; } testcase_t test_bgp_info_mpath_update = { - .desc = "Test bgp_info_mpath_update", - .setup = setup_bgp_info_mpath_update, - .run = run_bgp_info_mpath_update, - .cleanup = cleanup_bgp_info_mpath_update, + .desc = "Test bgp_info_mpath_update", + .setup = setup_bgp_info_mpath_update, + .run = run_bgp_info_mpath_update, + .cleanup = cleanup_bgp_info_mpath_update, }; /*========================================================= * Set up testcase vector */ testcase_t *all_tests[] = { - &test_bgp_cfg_maximum_paths, - &test_bgp_mp_list, - &test_bgp_info_mpath_update, + &test_bgp_cfg_maximum_paths, &test_bgp_mp_list, + &test_bgp_info_mpath_update, }; -int all_tests_count = (sizeof(all_tests)/sizeof(testcase_t *)); +int all_tests_count = (sizeof(all_tests) / sizeof(testcase_t *)); /*========================================================= * Test Driver Functions */ -static int -global_test_init (void) +static int global_test_init(void) { - qobj_init (); - master = thread_master_create(NULL); - zclient = zclient_new(master); - bgp_master_init (master); - vrf_init (NULL, NULL, NULL, NULL); - bgp_option_set (BGP_OPT_NO_LISTEN); - - if (fileno (stdout) >= 0) - tty = isatty (fileno (stdout)); - return 0; + qobj_init(); + master = thread_master_create(NULL); + zclient = zclient_new(master); + bgp_master_init(master); + vrf_init(NULL, NULL, NULL, NULL); + bgp_option_set(BGP_OPT_NO_LISTEN); + + if (fileno(stdout) >= 0) + tty = isatty(fileno(stdout)); + return 0; } -static int -global_test_cleanup (void) +static int global_test_cleanup(void) { - if (zclient != NULL) - zclient_free (zclient); - thread_master_free (master); - return 0; + if (zclient != NULL) + zclient_free(zclient); + thread_master_free(master); + return 0; } -static void -display_result (testcase_t *test, int result) +static void display_result(testcase_t *test, int result) { - if (tty) - printf ("%s: %s\n", test->desc, result == TEST_PASSED ? OK : FAILED); - else - printf ("%s: %s\n", test->desc, result == TEST_PASSED ? "OK" : "FAILED"); + if (tty) + printf("%s: %s\n", test->desc, + result == TEST_PASSED ? OK : FAILED); + else + printf("%s: %s\n", test->desc, + result == TEST_PASSED ? "OK" : "FAILED"); } -static int -setup_test (testcase_t *t) +static int setup_test(testcase_t *t) { - int res = 0; - if (t->setup) - res = t->setup (t); - return res; + int res = 0; + if (t->setup) + res = t->setup(t); + return res; } -static int -cleanup_test (testcase_t *t) +static int cleanup_test(testcase_t *t) { - int res = 0; - if (t->cleanup) - res = t->cleanup (t); - return res; + int res = 0; + if (t->cleanup) + res = t->cleanup(t); + return res; } -static void -run_tests (testcase_t *tests[], int num_tests, int *pass_count, int *fail_count) +static void run_tests(testcase_t *tests[], int num_tests, int *pass_count, + int *fail_count) { - int test_index, result; - testcase_t *cur_test; - - *pass_count = *fail_count = 0; - - for (test_index = 0; test_index < num_tests; test_index++) - { - cur_test = tests[test_index]; - if (!cur_test->desc) - { - printf ("error: test %d has no description!\n", test_index); - continue; - } - if (!cur_test->run) - { - printf ("error: test %s has no run function!\n", cur_test->desc); - continue; - } - if (setup_test (cur_test) != 0) - { - printf ("error: setup failed for test %s\n", cur_test->desc); - continue; - } - result = cur_test->run (cur_test); - if (result == TEST_PASSED) - *pass_count += 1; - else - *fail_count += 1; - display_result (cur_test, result); - if (cleanup_test (cur_test) != 0) - { - printf ("error: cleanup failed for test %s\n", cur_test->desc); - continue; - } - } + int test_index, result; + testcase_t *cur_test; + + *pass_count = *fail_count = 0; + + for (test_index = 0; test_index < num_tests; test_index++) { + cur_test = tests[test_index]; + if (!cur_test->desc) { + printf("error: test %d has no description!\n", + test_index); + continue; + } + if (!cur_test->run) { + printf("error: test %s has no run function!\n", + cur_test->desc); + continue; + } + if (setup_test(cur_test) != 0) { + printf("error: setup failed for test %s\n", + cur_test->desc); + continue; + } + result = cur_test->run(cur_test); + if (result == TEST_PASSED) + *pass_count += 1; + else + *fail_count += 1; + display_result(cur_test, result); + if (cleanup_test(cur_test) != 0) { + printf("error: cleanup failed for test %s\n", + cur_test->desc); + continue; + } + } } -int -main (void) +int main(void) { - int pass_count, fail_count; - time_t cur_time; - - time (&cur_time); - printf("BGP Multipath Tests Run at %s", ctime(&cur_time)); - if (global_test_init () != 0) - { - printf("Global init failed. Terminating.\n"); - exit(1); - } - run_tests (all_tests, all_tests_count, &pass_count, &fail_count); - global_test_cleanup (); - printf("Total pass/fail: %d/%d\n", pass_count, fail_count); - return fail_count; + int pass_count, fail_count; + time_t cur_time; + + time(&cur_time); + printf("BGP Multipath Tests Run at %s", ctime(&cur_time)); + if (global_test_init() != 0) { + printf("Global init failed. Terminating.\n"); + exit(1); + } + run_tests(all_tests, all_tests_count, &pass_count, &fail_count); + global_test_cleanup(); + printf("Total pass/fail: %d/%d\n", pass_count, fail_count); + return fail_count; } diff --git a/tests/helpers/c/main.c b/tests/helpers/c/main.c index f842b0372..9bf56dde1 100644 --- a/tests/helpers/c/main.c +++ b/tests/helpers/c/main.c @@ -32,57 +32,50 @@ extern void test_init(); struct thread_master *master; -struct option longopts[] = -{ - { "daemon", no_argument, NULL, 'd'}, - { "config_file", required_argument, NULL, 'f'}, - { "help", no_argument, NULL, 'h'}, - { "vty_addr", required_argument, NULL, 'A'}, - { "vty_port", required_argument, NULL, 'P'}, - { "version", no_argument, NULL, 'v'}, - { 0 } -}; +struct option longopts[] = {{"daemon", no_argument, NULL, 'd'}, + {"config_file", required_argument, NULL, 'f'}, + {"help", no_argument, NULL, 'h'}, + {"vty_addr", required_argument, NULL, 'A'}, + {"vty_port", required_argument, NULL, 'P'}, + {"version", no_argument, NULL, 'v'}, + {0}}; DEFUN (daemon_exit, daemon_exit_cmd, "daemon-exit", "Make the daemon exit\n") { - exit(0); + exit(0); } static int timer_count; -static int -test_timer (struct thread *thread) +static int test_timer(struct thread *thread) { - int *count = THREAD_ARG(thread); - - printf ("run %d of timer\n", (*count)++); - thread_add_timer(master, test_timer, count, 5, NULL); - return 0; + int *count = THREAD_ARG(thread); + + printf("run %d of timer\n", (*count)++); + thread_add_timer(master, test_timer, count, 5, NULL); + return 0; } -static void -test_timer_init() +static void test_timer_init() { - thread_add_timer(master, test_timer, &timer_count, 10, NULL); + thread_add_timer(master, test_timer, &timer_count, 10, NULL); } -static void -test_vty_init() +static void test_vty_init() { - install_element (VIEW_NODE, &daemon_exit_cmd); + install_element(VIEW_NODE, &daemon_exit_cmd); } /* Help information display. */ -static void -usage (char *progname, int status) +static void usage(char *progname, int status) { - if (status != 0) - fprintf (stderr, "Try `%s --help' for more information.\n", progname); - else - { - printf ("Usage : %s [OPTION...]\n\ + if (status != 0) + fprintf(stderr, "Try `%s --help' for more information.\n", + progname); + else { + printf("Usage : %s [OPTION...]\n\ Daemon which does 'slow' things.\n\n\ -d, --daemon Runs in daemon mode\n\ -f, --config_file Set configuration file name\n\ @@ -91,110 +84,105 @@ Daemon which does 'slow' things.\n\n\ -v, --version Print program version\n\ -h, --help Display this help and exit\n\ \n\ -Report bugs to %s\n", progname, FRR_BUG_ADDRESS); - } - exit (status); +Report bugs to %s\n", + progname, FRR_BUG_ADDRESS); + } + exit(status); } /* main routine. */ -int -main (int argc, char **argv) +int main(int argc, char **argv) { - char *p; - char *vty_addr = NULL; - int vty_port = 4000; - int daemon_mode = 0; - char *progname; - struct thread thread; - char *config_file = NULL; - - /* Set umask before anything for security */ - umask (0027); - - /* get program name */ - progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]); - - /* master init. */ - master = thread_master_create(NULL); - - while (1) - { - int opt; - - opt = getopt_long (argc, argv, "dhf:A:P:v", longopts, 0); - - if (opt == EOF) - break; - - switch (opt) - { - case 0: - break; - case 'f': - config_file = optarg; - break; - case 'd': - daemon_mode = 1; - break; - case 'A': - vty_addr = optarg; - break; - case 'P': - /* Deal with atoi() returning 0 on failure */ - if (strcmp(optarg, "0") == 0) - { - vty_port = 0; - break; - } - vty_port = atoi (optarg); - vty_port = (vty_port ? vty_port : 4000); - break; - case 'v': - print_version (progname); - exit (0); - break; - case 'h': - usage (progname, 0); - break; - default: - usage (progname, 1); - break; + char *p; + char *vty_addr = NULL; + int vty_port = 4000; + int daemon_mode = 0; + char *progname; + struct thread thread; + char *config_file = NULL; + + /* Set umask before anything for security */ + umask(0027); + + /* get program name */ + progname = ((p = strrchr(argv[0], '/')) ? ++p : argv[0]); + + /* master init. */ + master = thread_master_create(NULL); + + while (1) { + int opt; + + opt = getopt_long(argc, argv, "dhf:A:P:v", longopts, 0); + + if (opt == EOF) + break; + + switch (opt) { + case 0: + break; + case 'f': + config_file = optarg; + break; + case 'd': + daemon_mode = 1; + break; + case 'A': + vty_addr = optarg; + break; + case 'P': + /* Deal with atoi() returning 0 on failure */ + if (strcmp(optarg, "0") == 0) { + vty_port = 0; + break; + } + vty_port = atoi(optarg); + vty_port = (vty_port ? vty_port : 4000); + break; + case 'v': + print_version(progname); + exit(0); + break; + case 'h': + usage(progname, 0); + break; + default: + usage(progname, 1); + break; + } } - } - - /* Library inits. */ - cmd_init (1); - vty_init (master); - memory_init (); - - /* OSPF vty inits. */ - test_vty_init (); - - /* Change to the daemon program. */ - if (daemon_mode && daemon (0, 0) < 0) - { - fprintf(stderr, "daemon failed: %s", strerror(errno)); - exit (1); - } - - /* Create VTY socket */ - vty_serv_sock (vty_addr, vty_port, "/tmp/.heavy.sock"); - - /* Configuration file read*/ - if (!config_file) - usage (progname, 1); - vty_read_config (config_file, NULL); - - test_timer_init(); - - test_init(); - - /* Fetch next active thread. */ - while (thread_fetch (master, &thread)) - thread_call (&thread); - - /* Not reached. */ - exit (0); -} + /* Library inits. */ + cmd_init(1); + vty_init(master); + memory_init(); + + /* OSPF vty inits. */ + test_vty_init(); + + /* Change to the daemon program. */ + if (daemon_mode && daemon(0, 0) < 0) { + fprintf(stderr, "daemon failed: %s", strerror(errno)); + exit(1); + } + + /* Create VTY socket */ + vty_serv_sock(vty_addr, vty_port, "/tmp/.heavy.sock"); + + /* Configuration file read*/ + if (!config_file) + usage(progname, 1); + vty_read_config(config_file, NULL); + + test_timer_init(); + + test_init(); + + /* Fetch next active thread. */ + while (thread_fetch(master, &thread)) + thread_call(&thread); + + /* Not reached. */ + exit(0); +} diff --git a/tests/helpers/c/prng.c b/tests/helpers/c/prng.c index 0f78366fc..e2173d451 100644 --- a/tests/helpers/c/prng.c +++ b/tests/helpers/c/prng.c @@ -31,20 +31,18 @@ #include "prng.h" -struct prng -{ - uint64_t state; +struct prng { + uint64_t state; }; -struct prng* -prng_new(unsigned long long seed) +struct prng *prng_new(unsigned long long seed) { - struct prng *rv = calloc(sizeof(*rv), 1); - assert(rv); + struct prng *rv = calloc(sizeof(*rv), 1); + assert(rv); - rv->state = seed; + rv->state = seed; - return rv; + return rv; } /* @@ -54,62 +52,57 @@ prng_new(unsigned long long seed) * It is a simple LCG which D.E. Knuth attributes to C.E. Haynes in * TAOCP Vol2 3.3.4 */ -int -prng_rand(struct prng *prng) +int prng_rand(struct prng *prng) { - prng->state = 6364136223846793005ULL*prng->state + 1; - return prng->state>>33; + prng->state = 6364136223846793005ULL * prng->state + 1; + return prng->state >> 33; } -const char * -prng_fuzz(struct prng *prng, - const char *string, - const char *charset, - unsigned int operations) +const char *prng_fuzz(struct prng *prng, const char *string, + const char *charset, unsigned int operations) { - static char buf[256]; - unsigned int charset_len; - unsigned int i; - unsigned int offset; - unsigned int op; - unsigned int character; + static char buf[256]; + unsigned int charset_len; + unsigned int i; + unsigned int offset; + unsigned int op; + unsigned int character; - assert(strlen(string) < sizeof(buf)); + assert(strlen(string) < sizeof(buf)); - strncpy(buf, string, sizeof(buf)); - charset_len = strlen(charset); + strncpy(buf, string, sizeof(buf)); + charset_len = strlen(charset); - for (i = 0; i < operations; i++) - { - offset = prng_rand(prng) % strlen(buf); - op = prng_rand(prng) % 3; + for (i = 0; i < operations; i++) { + offset = prng_rand(prng) % strlen(buf); + op = prng_rand(prng) % 3; - switch (op) - { - case 0: - /* replace */ - character = prng_rand(prng) % charset_len; - buf[offset] = charset[character]; - break; - case 1: - /* remove */ - memmove(buf + offset, buf + offset + 1, strlen(buf) - offset); - break; - case 2: - /* insert */ - assert(strlen(buf) + 1 < sizeof(buf)); + switch (op) { + case 0: + /* replace */ + character = prng_rand(prng) % charset_len; + buf[offset] = charset[character]; + break; + case 1: + /* remove */ + memmove(buf + offset, buf + offset + 1, + strlen(buf) - offset); + break; + case 2: + /* insert */ + assert(strlen(buf) + 1 < sizeof(buf)); - memmove(buf + offset + 1, buf + offset, strlen(buf) + 1 - offset); - character = prng_rand(prng) % charset_len; - buf[offset] = charset[character]; - break; - } - } - return buf; + memmove(buf + offset + 1, buf + offset, + strlen(buf) + 1 - offset); + character = prng_rand(prng) % charset_len; + buf[offset] = charset[character]; + break; + } + } + return buf; } -void -prng_free(struct prng *prng) +void prng_free(struct prng *prng) { - free(prng); + free(prng); } diff --git a/tests/helpers/c/prng.h b/tests/helpers/c/prng.h index 7b2ab924e..23f702b07 100644 --- a/tests/helpers/c/prng.h +++ b/tests/helpers/c/prng.h @@ -26,12 +26,10 @@ struct prng; -struct prng* prng_new(unsigned long long seed); -int prng_rand(struct prng*); -const char * prng_fuzz(struct prng*, - const char *string, - const char *charset, - unsigned int operations); +struct prng *prng_new(unsigned long long seed); +int prng_rand(struct prng *); +const char *prng_fuzz(struct prng *, const char *string, const char *charset, + unsigned int operations); void prng_free(struct prng *); #endif diff --git a/tests/helpers/c/tests.h b/tests/helpers/c/tests.h index aaf35c27d..53e9c7844 100644 --- a/tests/helpers/c/tests.h +++ b/tests/helpers/c/tests.h @@ -24,7 +24,7 @@ #ifndef _QUAGGA_TESTS_H #define _QUAGGA_TESTS_H -extern void test_init (void); -extern void test_init_cmd (void); +extern void test_init(void); +extern void test_init_cmd(void); #endif /* _QUAGGA_TESTS_H */ diff --git a/tests/lib/cli/common_cli.c b/tests/lib/cli/common_cli.c index f1b07ce22..b6df6d3b8 100644 --- a/tests/lib/cli/common_cli.c +++ b/tests/lib/cli/common_cli.c @@ -32,65 +32,63 @@ struct thread_master *master; -int dump_args(struct vty *vty, const char *descr, - int argc, struct cmd_token *argv[]) +int dump_args(struct vty *vty, const char *descr, int argc, + struct cmd_token *argv[]) { - int i; - vty_out (vty, "%s with %d args.\n", descr, argc); - for (i = 0; i < argc; i++) - { - vty_out (vty, "[%02d] %s@%s: %s\n", i, argv[i]->text, argv[i]->varname, argv[i]->arg); - } - - return CMD_SUCCESS; + int i; + vty_out(vty, "%s with %d args.\n", descr, argc); + for (i = 0; i < argc; i++) { + vty_out(vty, "[%02d] %s@%s: %s\n", i, argv[i]->text, + argv[i]->varname, argv[i]->arg); + } + + return CMD_SUCCESS; } static void vty_do_exit(void) { - printf ("\nend.\n"); - cmd_terminate (); - vty_terminate (); - thread_master_free (master); - closezlog (); - - log_memstats_stderr ("testcli"); - exit (0); + printf("\nend.\n"); + cmd_terminate(); + vty_terminate(); + thread_master_free(master); + closezlog(); + + log_memstats_stderr("testcli"); + exit(0); } /* main routine. */ -int -main (int argc, char **argv) +int main(int argc, char **argv) { - struct thread thread; + struct thread thread; - /* Set umask before anything for security */ - umask (0027); + /* Set umask before anything for security */ + umask(0027); - /* master init. */ - master = thread_master_create(NULL); + /* master init. */ + master = thread_master_create(NULL); - openzlog("common-cli", "NONE", 0, LOG_CONS | LOG_NDELAY | LOG_PID, - LOG_DAEMON); - zlog_set_level(ZLOG_DEST_SYSLOG, ZLOG_DISABLED); - zlog_set_level(ZLOG_DEST_STDOUT, ZLOG_DISABLED); - zlog_set_level(ZLOG_DEST_MONITOR, LOG_DEBUG); + openzlog("common-cli", "NONE", 0, LOG_CONS | LOG_NDELAY | LOG_PID, + LOG_DAEMON); + zlog_set_level(ZLOG_DEST_SYSLOG, ZLOG_DISABLED); + zlog_set_level(ZLOG_DEST_STDOUT, ZLOG_DISABLED); + zlog_set_level(ZLOG_DEST_MONITOR, LOG_DEBUG); - /* Library inits. */ - cmd_init (1); - cmd_hostname_set ("test"); + /* Library inits. */ + cmd_init(1); + cmd_hostname_set("test"); - vty_init (master); - memory_init (); + vty_init(master); + memory_init(); - test_init (argc, argv); + test_init(argc, argv); - vty_stdio (vty_do_exit); + vty_stdio(vty_do_exit); - /* Fetch next active thread. */ - while (thread_fetch (master, &thread)) - thread_call (&thread); + /* Fetch next active thread. */ + while (thread_fetch(master, &thread)) + thread_call(&thread); - /* Not reached. */ - exit (0); + /* Not reached. */ + exit(0); } - diff --git a/tests/lib/cli/common_cli.h b/tests/lib/cli/common_cli.h index 9a0ef47c8..15abe3b85 100644 --- a/tests/lib/cli/common_cli.h +++ b/tests/lib/cli/common_cli.h @@ -27,22 +27,24 @@ #include "command.h" /* function to be implemented by test */ -extern void test_init (int argc, char **argv); +extern void test_init(int argc, char **argv); /* functions provided by common cli * (includes main()) */ extern struct thread_master *master; -extern int dump_args(struct vty *vty, const char *descr, - int argc, struct cmd_token *argv[]); +extern int dump_args(struct vty *vty, const char *descr, int argc, + struct cmd_token *argv[]); -#define DUMMY_HELPSTR \ - "00\n01\n02\n03\n04\n05\n06\n07\n08\n09\n" \ - "10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n" \ - "20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n" -#define DUMMY_DEFUN(name, cmdstr) \ - DEFUN (name, name ## _cmd, cmdstr, DUMMY_HELPSTR) \ - { return dump_args(vty, #name, argc, argv); } +#define DUMMY_HELPSTR \ + "00\n01\n02\n03\n04\n05\n06\n07\n08\n09\n" \ + "10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n" \ + "20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n" +#define DUMMY_DEFUN(name, cmdstr) \ + DEFUN(name, name##_cmd, cmdstr, DUMMY_HELPSTR) \ + { \ + return dump_args(vty, #name, argc, argv); \ + } #endif /* _COMMON_CLI_H */ diff --git a/tests/lib/cli/test_cli.c b/tests/lib/cli/test_cli.c index a4d3fb4e8..8f062d8b5 100644 --- a/tests/lib/cli/test_cli.c +++ b/tests/lib/cli/test_cli.c @@ -24,21 +24,22 @@ #include "prefix.h" #include "common_cli.h" -DUMMY_DEFUN(cmd0, "arg ipv4 A.B.C.D"); -DUMMY_DEFUN(cmd1, "arg ipv4m A.B.C.D/M"); -DUMMY_DEFUN(cmd2, "arg ipv6 X:X::X:X$foo"); -DUMMY_DEFUN(cmd3, "arg ipv6m X:X::X:X/M"); -DUMMY_DEFUN(cmd4, "arg range (5-15)"); -DUMMY_DEFUN(cmd5, "pat a < a|b>"); -DUMMY_DEFUN(cmd6, "pat b "); -DUMMY_DEFUN(cmd7, "pat c A.B.C.D"); -DUMMY_DEFUN(cmd8, "pat d { foo A.B.C.D$foo|bar X:X::X:X$bar| baz } [final]"); -DUMMY_DEFUN(cmd9, "pat e [ WORD ]"); +DUMMY_DEFUN(cmd0, "arg ipv4 A.B.C.D"); +DUMMY_DEFUN(cmd1, "arg ipv4m A.B.C.D/M"); +DUMMY_DEFUN(cmd2, "arg ipv6 X:X::X:X$foo"); +DUMMY_DEFUN(cmd3, "arg ipv6m X:X::X:X/M"); +DUMMY_DEFUN(cmd4, "arg range (5-15)"); +DUMMY_DEFUN(cmd5, "pat a < a|b>"); +DUMMY_DEFUN(cmd6, "pat b "); +DUMMY_DEFUN(cmd7, "pat c A.B.C.D"); +DUMMY_DEFUN(cmd8, "pat d { foo A.B.C.D$foo|bar X:X::X:X$bar| baz } [final]"); +DUMMY_DEFUN(cmd9, "pat e [ WORD ]"); DUMMY_DEFUN(cmd10, "pat f [key]"); DUMMY_DEFUN(cmd11, "alt a WORD"); DUMMY_DEFUN(cmd12, "alt a A.B.C.D"); DUMMY_DEFUN(cmd13, "alt a X:X::X:X"); -DUMMY_DEFUN(cmd14, "pat g { foo A.B.C.D$foo|foo|bar X:X::X:X$bar| baz } [final]"); +DUMMY_DEFUN(cmd14, + "pat g { foo A.B.C.D$foo|foo|bar X:X::X:X$bar| baz } [final]"); #include "tests/lib/cli/test_cli_clippy.c" @@ -46,40 +47,41 @@ DEFPY(magic_test, magic_test_cmd, "magic (0-100) {ipv4net A.B.C.D/M|X:X::X:X$ipv6}", "1\n2\n3\n4\n5\n") { - char buf[256]; - vty_out(vty, "def: %s\n", self->string); - vty_out(vty, "num: %ld\n", magic); - vty_out(vty, "ipv4: %s\n", prefix2str(ipv4net, buf, sizeof(buf))); - vty_out(vty, "ipv6: %s\n", inet_ntop(AF_INET6, &ipv6, buf, sizeof(buf))); - return CMD_SUCCESS; + char buf[256]; + vty_out(vty, "def: %s\n", self->string); + vty_out(vty, "num: %ld\n", magic); + vty_out(vty, "ipv4: %s\n", prefix2str(ipv4net, buf, sizeof(buf))); + vty_out(vty, "ipv6: %s\n", + inet_ntop(AF_INET6, &ipv6, buf, sizeof(buf))); + return CMD_SUCCESS; } void test_init(int argc, char **argv) { - size_t repeat = argc > 1 ? strtoul(argv[1], NULL, 0) : 223; + size_t repeat = argc > 1 ? strtoul(argv[1], NULL, 0) : 223; - install_element (ENABLE_NODE, &cmd0_cmd); - install_element (ENABLE_NODE, &cmd1_cmd); - install_element (ENABLE_NODE, &cmd2_cmd); - install_element (ENABLE_NODE, &cmd3_cmd); - install_element (ENABLE_NODE, &cmd4_cmd); - install_element (ENABLE_NODE, &cmd5_cmd); - install_element (ENABLE_NODE, &cmd6_cmd); - install_element (ENABLE_NODE, &cmd7_cmd); - install_element (ENABLE_NODE, &cmd8_cmd); - install_element (ENABLE_NODE, &cmd9_cmd); - install_element (ENABLE_NODE, &cmd10_cmd); - install_element (ENABLE_NODE, &cmd11_cmd); - install_element (ENABLE_NODE, &cmd12_cmd); - install_element (ENABLE_NODE, &cmd13_cmd); - for (size_t i = 0; i < repeat; i++) { - uninstall_element (ENABLE_NODE, &cmd5_cmd); - install_element (ENABLE_NODE, &cmd5_cmd); - } - for (size_t i = 0; i < repeat; i++) { - uninstall_element (ENABLE_NODE, &cmd13_cmd); - install_element (ENABLE_NODE, &cmd13_cmd); - } - install_element (ENABLE_NODE, &cmd14_cmd); - install_element (ENABLE_NODE, &magic_test_cmd); + install_element(ENABLE_NODE, &cmd0_cmd); + install_element(ENABLE_NODE, &cmd1_cmd); + install_element(ENABLE_NODE, &cmd2_cmd); + install_element(ENABLE_NODE, &cmd3_cmd); + install_element(ENABLE_NODE, &cmd4_cmd); + install_element(ENABLE_NODE, &cmd5_cmd); + install_element(ENABLE_NODE, &cmd6_cmd); + install_element(ENABLE_NODE, &cmd7_cmd); + install_element(ENABLE_NODE, &cmd8_cmd); + install_element(ENABLE_NODE, &cmd9_cmd); + install_element(ENABLE_NODE, &cmd10_cmd); + install_element(ENABLE_NODE, &cmd11_cmd); + install_element(ENABLE_NODE, &cmd12_cmd); + install_element(ENABLE_NODE, &cmd13_cmd); + for (size_t i = 0; i < repeat; i++) { + uninstall_element(ENABLE_NODE, &cmd5_cmd); + install_element(ENABLE_NODE, &cmd5_cmd); + } + for (size_t i = 0; i < repeat; i++) { + uninstall_element(ENABLE_NODE, &cmd13_cmd); + install_element(ENABLE_NODE, &cmd13_cmd); + } + install_element(ENABLE_NODE, &cmd14_cmd); + install_element(ENABLE_NODE, &magic_test_cmd); } diff --git a/tests/lib/cli/test_commands.c b/tests/lib/cli/test_commands.c index 249a6f760..48dd99d28 100644 --- a/tests/lib/cli/test_commands.c +++ b/tests/lib/cli/test_commands.c @@ -48,360 +48,297 @@ struct thread_master *master; /* dummy for libfrr*/ static vector test_cmds; static char test_buf[32768]; -static struct cmd_node bgp_node = -{ - BGP_NODE, - "%s(config-router)# ", +static struct cmd_node bgp_node = { + BGP_NODE, "%s(config-router)# ", }; -static struct cmd_node rip_node = -{ - RIP_NODE, - "%s(config-router)# ", +static struct cmd_node rip_node = { + RIP_NODE, "%s(config-router)# ", }; -static struct cmd_node isis_node = -{ - ISIS_NODE, - "%s(config-router)# ", +static struct cmd_node isis_node = { + ISIS_NODE, "%s(config-router)# ", }; -static struct cmd_node interface_node = -{ - INTERFACE_NODE, - "%s(config-if)# ", +static struct cmd_node interface_node = { + INTERFACE_NODE, "%s(config-if)# ", }; -static struct cmd_node rmap_node = -{ - RMAP_NODE, - "%s(config-route-map)# " -}; +static struct cmd_node rmap_node = {RMAP_NODE, "%s(config-route-map)# "}; -static struct cmd_node zebra_node = -{ - ZEBRA_NODE, - "%s(config-router)# " -}; +static struct cmd_node zebra_node = {ZEBRA_NODE, "%s(config-router)# "}; -static struct cmd_node bgp_vpnv4_node = -{ - BGP_VPNV4_NODE, - "%s(config-router-af)# " -}; +static struct cmd_node bgp_vpnv4_node = {BGP_VPNV4_NODE, + "%s(config-router-af)# "}; -static struct cmd_node bgp_ipv4_node = -{ - BGP_IPV4_NODE, - "%s(config-router-af)# " -}; +static struct cmd_node bgp_ipv4_node = {BGP_IPV4_NODE, + "%s(config-router-af)# "}; -static struct cmd_node bgp_ipv4m_node = -{ - BGP_IPV4M_NODE, - "%s(config-router-af)# " -}; +static struct cmd_node bgp_ipv4m_node = {BGP_IPV4M_NODE, + "%s(config-router-af)# "}; -static struct cmd_node bgp_ipv6_node = -{ - BGP_IPV6_NODE, - "%s(config-router-af)# " -}; +static struct cmd_node bgp_ipv6_node = {BGP_IPV6_NODE, + "%s(config-router-af)# "}; -static struct cmd_node bgp_ipv6m_node = -{ - BGP_IPV6M_NODE, - "%s(config-router-af)# " -}; +static struct cmd_node bgp_ipv6m_node = {BGP_IPV6M_NODE, + "%s(config-router-af)# "}; -static struct cmd_node ospf_node = -{ - OSPF_NODE, - "%s(config-router)# " -}; +static struct cmd_node ospf_node = {OSPF_NODE, "%s(config-router)# "}; -static struct cmd_node ripng_node = -{ - RIPNG_NODE, - "%s(config-router)# " -}; +static struct cmd_node ripng_node = {RIPNG_NODE, "%s(config-router)# "}; -static struct cmd_node ospf6_node = -{ - OSPF6_NODE, - "%s(config-ospf6)# " -}; +static struct cmd_node ospf6_node = {OSPF6_NODE, "%s(config-ospf6)# "}; -static struct cmd_node keychain_node = -{ - KEYCHAIN_NODE, - "%s(config-keychain)# " -}; +static struct cmd_node keychain_node = {KEYCHAIN_NODE, "%s(config-keychain)# "}; -static struct cmd_node keychain_key_node = -{ - KEYCHAIN_KEY_NODE, - "%s(config-keychain-key)# " -}; +static struct cmd_node keychain_key_node = {KEYCHAIN_KEY_NODE, + "%s(config-keychain-key)# "}; -static int -test_callback(const struct cmd_element *cmd, struct vty *vty, int argc, struct cmd_token *argv[]) +static int test_callback(const struct cmd_element *cmd, struct vty *vty, + int argc, struct cmd_token *argv[]) { - int offset; - int rv; - int i; - - offset = 0; - rv = snprintf(test_buf, sizeof(test_buf), "'%s'", cmd->string); - if (rv < 0) - abort(); - - offset += rv; - - for (i = 0; i < argc; i++) - { - rv = snprintf(test_buf + offset, sizeof(test_buf) - offset, "%s'%s'", - (i == 0) ? ": " : ", ", argv[i]->arg); - if (rv < 0) - abort(); - offset += rv; - } - - return CMD_SUCCESS; + int offset; + int rv; + int i; + + offset = 0; + rv = snprintf(test_buf, sizeof(test_buf), "'%s'", cmd->string); + if (rv < 0) + abort(); + + offset += rv; + + for (i = 0; i < argc; i++) { + rv = snprintf(test_buf + offset, sizeof(test_buf) - offset, + "%s'%s'", (i == 0) ? ": " : ", ", argv[i]->arg); + if (rv < 0) + abort(); + offset += rv; + } + + return CMD_SUCCESS; } -static void -test_load(void) +static void test_load(void) { - char line[4096]; - - test_cmds = vector_init(VECTOR_MIN_SIZE); - - while (fgets(line, sizeof(line), stdin) != NULL) - { - if (strlen(line)) - line[strlen(line) - 1] = '\0'; - if (line[0] == '#') - continue; - vector_set(test_cmds, XSTRDUP(MTYPE_STRVEC, line)); - } + char line[4096]; + + test_cmds = vector_init(VECTOR_MIN_SIZE); + + while (fgets(line, sizeof(line), stdin) != NULL) { + if (strlen(line)) + line[strlen(line) - 1] = '\0'; + if (line[0] == '#') + continue; + vector_set(test_cmds, XSTRDUP(MTYPE_STRVEC, line)); + } } -static void -test_init(void) +static void test_init(void) { - unsigned int node; - unsigned int i; - struct cmd_node *cnode; - struct cmd_element *cmd; - - cmd_init(1); - - install_node (&bgp_node, NULL); - install_node (&rip_node, NULL); - install_node (&interface_node, NULL); - install_node (&rmap_node, NULL); - install_node (&zebra_node, NULL); - install_node (&bgp_vpnv4_node, NULL); - install_node (&bgp_ipv4_node, NULL); - install_node (&bgp_ipv4m_node, NULL); - install_node (&bgp_ipv6_node, NULL); - install_node (&bgp_ipv6m_node, NULL); - install_node (&ospf_node, NULL); - install_node (&ripng_node, NULL); - install_node (&ospf6_node, NULL); - install_node (&keychain_node, NULL); - install_node (&keychain_key_node, NULL); - install_node (&isis_node, NULL); - install_node (&vty_node, NULL); - - test_init_cmd(); - - for (node = 0; node < vector_active(cmdvec); node++) - if ((cnode = vector_slot(cmdvec, node)) != NULL) - for (i = 0; i < vector_active(cnode->cmd_vector); i++) - if ((cmd = vector_slot(cnode->cmd_vector, i)) != NULL) - { - cmd->daemon = 0; - cmd->func = test_callback; - } - test_load(); - vty_init_vtysh(); + unsigned int node; + unsigned int i; + struct cmd_node *cnode; + struct cmd_element *cmd; + + cmd_init(1); + + install_node(&bgp_node, NULL); + install_node(&rip_node, NULL); + install_node(&interface_node, NULL); + install_node(&rmap_node, NULL); + install_node(&zebra_node, NULL); + install_node(&bgp_vpnv4_node, NULL); + install_node(&bgp_ipv4_node, NULL); + install_node(&bgp_ipv4m_node, NULL); + install_node(&bgp_ipv6_node, NULL); + install_node(&bgp_ipv6m_node, NULL); + install_node(&ospf_node, NULL); + install_node(&ripng_node, NULL); + install_node(&ospf6_node, NULL); + install_node(&keychain_node, NULL); + install_node(&keychain_key_node, NULL); + install_node(&isis_node, NULL); + install_node(&vty_node, NULL); + + test_init_cmd(); + + for (node = 0; node < vector_active(cmdvec); node++) + if ((cnode = vector_slot(cmdvec, node)) != NULL) + for (i = 0; i < vector_active(cnode->cmd_vector); i++) + if ((cmd = vector_slot(cnode->cmd_vector, i)) + != NULL) { + cmd->daemon = 0; + cmd->func = test_callback; + } + test_load(); + vty_init_vtysh(); } -static void -test_terminate(void) +static void test_terminate(void) { - unsigned int i; + unsigned int i; - vty_terminate(); - for (i = 0; i < vector_active(test_cmds); i++) - XFREE(MTYPE_STRVEC, vector_slot(test_cmds, i)); - vector_free(test_cmds); - cmd_terminate(); + vty_terminate(); + for (i = 0; i < vector_active(test_cmds); i++) + XFREE(MTYPE_STRVEC, vector_slot(test_cmds, i)); + vector_free(test_cmds); + cmd_terminate(); } -static void -test_run(struct prng *prng, struct vty *vty, const char *cmd, unsigned int edit_dist, unsigned int node_index, int verbose) +static void test_run(struct prng *prng, struct vty *vty, const char *cmd, + unsigned int edit_dist, unsigned int node_index, + int verbose) { - const char *test_str; - vector vline; - int ret; - unsigned int i; - char **completions; - unsigned int j; - struct cmd_node *cnode; - vector descriptions; - int appended_null; - int no_match; - - test_str = prng_fuzz(prng, cmd, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_:. /", edit_dist); - vline = cmd_make_strvec(test_str); - - if (vline == NULL) - return; - - appended_null = 0; - for (i = 0; i < vector_active(cmdvec); i++) - if ((cnode = vector_slot(cmdvec, i)) != NULL) - { - if (node_index != (unsigned int)-1 && i != node_index) - continue; - - if (appended_null) - { - vector_unset(vline, vector_active(vline) - 1); - appended_null = 0; - } - vty->node = cnode->node; - test_buf[0] = '\0'; - ret = cmd_execute_command(vline, vty, NULL, 0); - no_match = (ret == CMD_ERR_NO_MATCH); - if (verbose || !no_match) - printf("execute relaxed '%s'@%d: rv==%d%s%s\n", - test_str, - cnode->node, - ret, - (test_buf[0] != '\0') ? ", " : "", - test_buf); - - vty->node = cnode->node; - test_buf[0] = '\0'; - ret = cmd_execute_command_strict(vline, vty, NULL); - if (verbose || !no_match) - printf("execute strict '%s'@%d: rv==%d%s%s\n", - test_str, - cnode->node, - ret, - (test_buf[0] != '\0') ? ", " : "", - test_buf); - - if (isspace((int) test_str[strlen(test_str) - 1])) - { - vector_set (vline, NULL); - appended_null = 1; - } - - vty->node = cnode->node; - completions = cmd_complete_command(vline, vty, &ret); - if (verbose || !no_match) - printf("complete '%s'@%d: rv==%d\n", - test_str, - cnode->node, - ret); - if (completions != NULL) - { - for (j = 0; completions[j] != NULL; j++) - { - printf(" '%s'\n", completions[j]); - XFREE(MTYPE_TMP, completions[j]); - } - XFREE(MTYPE_TMP, completions); - } - - vty->node = cnode->node; - descriptions = cmd_describe_command(vline, vty, &ret); - if (verbose || !no_match) - printf("describe '%s'@%d: rv==%d\n", - test_str, - cnode->node, - ret); - if (descriptions != NULL) - { - for (j = 0; j < vector_active(descriptions); j++) - { - struct cmd_token *cmd = vector_slot(descriptions, j); - printf(" '%s' '%s'\n", cmd->text, cmd->desc); - } - vector_free(descriptions); - } - } - cmd_free_strvec(vline); + const char *test_str; + vector vline; + int ret; + unsigned int i; + char **completions; + unsigned int j; + struct cmd_node *cnode; + vector descriptions; + int appended_null; + int no_match; + + test_str = prng_fuzz( + prng, cmd, + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_:. /", + edit_dist); + vline = cmd_make_strvec(test_str); + + if (vline == NULL) + return; + + appended_null = 0; + for (i = 0; i < vector_active(cmdvec); i++) + if ((cnode = vector_slot(cmdvec, i)) != NULL) { + if (node_index != (unsigned int)-1 && i != node_index) + continue; + + if (appended_null) { + vector_unset(vline, vector_active(vline) - 1); + appended_null = 0; + } + vty->node = cnode->node; + test_buf[0] = '\0'; + ret = cmd_execute_command(vline, vty, NULL, 0); + no_match = (ret == CMD_ERR_NO_MATCH); + if (verbose || !no_match) + printf("execute relaxed '%s'@%d: rv==%d%s%s\n", + test_str, cnode->node, ret, + (test_buf[0] != '\0') ? ", " : "", + test_buf); + + vty->node = cnode->node; + test_buf[0] = '\0'; + ret = cmd_execute_command_strict(vline, vty, NULL); + if (verbose || !no_match) + printf("execute strict '%s'@%d: rv==%d%s%s\n", + test_str, cnode->node, ret, + (test_buf[0] != '\0') ? ", " : "", + test_buf); + + if (isspace((int)test_str[strlen(test_str) - 1])) { + vector_set(vline, NULL); + appended_null = 1; + } + + vty->node = cnode->node; + completions = cmd_complete_command(vline, vty, &ret); + if (verbose || !no_match) + printf("complete '%s'@%d: rv==%d\n", test_str, + cnode->node, ret); + if (completions != NULL) { + for (j = 0; completions[j] != NULL; j++) { + printf(" '%s'\n", completions[j]); + XFREE(MTYPE_TMP, completions[j]); + } + XFREE(MTYPE_TMP, completions); + } + + vty->node = cnode->node; + descriptions = cmd_describe_command(vline, vty, &ret); + if (verbose || !no_match) + printf("describe '%s'@%d: rv==%d\n", test_str, + cnode->node, ret); + if (descriptions != NULL) { + for (j = 0; j < vector_active(descriptions); + j++) { + struct cmd_token *cmd = + vector_slot(descriptions, j); + printf(" '%s' '%s'\n", cmd->text, + cmd->desc); + } + vector_free(descriptions); + } + } + cmd_free_strvec(vline); } -int -main(int argc, char **argv) +int main(int argc, char **argv) { - int opt; - struct prng *prng; - struct vty *vty; - unsigned int edit_distance; - unsigned int max_edit_distance; - unsigned int node_index; - int verbose; - unsigned int test_cmd; - unsigned int iteration; - unsigned int num_iterations; - - max_edit_distance = 3; - node_index = -1; - verbose = 0; - - while ((opt = getopt(argc, argv, "e:n:v")) != -1) - { - switch (opt) - { - case 'e': - max_edit_distance = atoi(optarg); - break; - case 'n': - node_index = atoi(optarg); - break; - case 'v': - verbose++; - break; - default: - fprintf(stderr, "Usage: %s [-e ] [-n ] [-v]\n", argv[0]); - exit(1); - break; - } - } - - test_init(); - prng = prng_new(0); - - vty = vty_new(); - vty->type = VTY_TERM; - - fprintf(stderr, "Progress:\n0/%u", vector_active(test_cmds)); - for (test_cmd = 0; test_cmd < vector_active(test_cmds); test_cmd++) - { - for (edit_distance = 0; - edit_distance <= max_edit_distance; - edit_distance++) - { - num_iterations = 1 << edit_distance; - num_iterations *= num_iterations * num_iterations; - - for (iteration = 0; iteration < num_iterations; iteration++) - test_run(prng, vty, vector_slot(test_cmds, test_cmd), edit_distance, node_index, verbose); - } - fprintf(stderr, "\r%u/%u", test_cmd + 1, vector_active(test_cmds)); - } - fprintf(stderr, "\nDone.\n"); - - vty_close(vty); - prng_free(prng); - test_terminate(); - return 0; + int opt; + struct prng *prng; + struct vty *vty; + unsigned int edit_distance; + unsigned int max_edit_distance; + unsigned int node_index; + int verbose; + unsigned int test_cmd; + unsigned int iteration; + unsigned int num_iterations; + + max_edit_distance = 3; + node_index = -1; + verbose = 0; + + while ((opt = getopt(argc, argv, "e:n:v")) != -1) { + switch (opt) { + case 'e': + max_edit_distance = atoi(optarg); + break; + case 'n': + node_index = atoi(optarg); + break; + case 'v': + verbose++; + break; + default: + fprintf(stderr, + "Usage: %s [-e ] [-n ] [-v]\n", + argv[0]); + exit(1); + break; + } + } + + test_init(); + prng = prng_new(0); + + vty = vty_new(); + vty->type = VTY_TERM; + + fprintf(stderr, "Progress:\n0/%u", vector_active(test_cmds)); + for (test_cmd = 0; test_cmd < vector_active(test_cmds); test_cmd++) { + for (edit_distance = 0; edit_distance <= max_edit_distance; + edit_distance++) { + num_iterations = 1 << edit_distance; + num_iterations *= num_iterations * num_iterations; + + for (iteration = 0; iteration < num_iterations; + iteration++) + test_run(prng, vty, + vector_slot(test_cmds, test_cmd), + edit_distance, node_index, verbose); + } + fprintf(stderr, "\r%u/%u", test_cmd + 1, + vector_active(test_cmds)); + } + fprintf(stderr, "\nDone.\n"); + + vty_close(vty); + prng_free(prng); + test_terminate(); + return 0; } diff --git a/tests/lib/test_buffer.c b/tests/lib/test_buffer.c index b9f5fd725..b56cc30cf 100644 --- a/tests/lib/test_buffer.c +++ b/tests/lib/test_buffer.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2004 Paul Jakma * * This file is part of Quagga. @@ -25,35 +25,33 @@ struct thread_master *master; -int -main(int argc, char **argv) +int main(int argc, char **argv) { - struct buffer *b1, *b2; - int n; - char junk[3]; - char c = 'a'; + struct buffer *b1, *b2; + int n; + char junk[3]; + char c = 'a'; - memory_init(); - - if ((argc != 2) || (sscanf(argv[1], "%d%1s", &n, junk) != 1)) - { - fprintf(stderr, "Usage: %s \n", *argv); - return 1; - } + memory_init(); - b1 = buffer_new(0); - b2 = buffer_new(1024); - - while (n-- > 0) - { - buffer_put(b1, &c, 1); - buffer_put(b2, &c, 1); - if (c++ == 'z') - c = 'a'; - buffer_reset(b1); - buffer_reset(b2); - } - buffer_free(b1); - buffer_free(b2); - return 0; + if ((argc != 2) || (sscanf(argv[1], "%d%1s", &n, junk) != 1)) { + fprintf(stderr, "Usage: %s \n", + *argv); + return 1; + } + + b1 = buffer_new(0); + b2 = buffer_new(1024); + + while (n-- > 0) { + buffer_put(b1, &c, 1); + buffer_put(b2, &c, 1); + if (c++ == 'z') + c = 'a'; + buffer_reset(b1); + buffer_reset(b2); + } + buffer_free(b1); + buffer_free(b2); + return 0; } diff --git a/tests/lib/test_checksum.c b/tests/lib/test_checksum.c index 267a057cc..c265e164e 100644 --- a/tests/lib/test_checksum.c +++ b/tests/lib/test_checksum.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2008 Sun Microsystems, Inc. * * This file is part of Quagga. @@ -27,14 +27,14 @@ struct thread_master *master; struct acc_vals { - int c0; - int c1; + int c0; + int c1; }; struct csum_vals { - struct acc_vals a; - int x; - int y; + struct acc_vals a; + int x; + int y; }; static struct csum_vals ospfd_vals, isisd_vals; @@ -46,26 +46,26 @@ typedef uint16_t testoff_t; #define MODX 4102U /* The final reduction phase. - * This one should be the original ospfd version + * This one should be the original ospfd version */ -static u_int16_t -reduce_ospfd (struct csum_vals *vals, testsz_t len, testoff_t off) +static u_int16_t reduce_ospfd(struct csum_vals *vals, testsz_t len, + testoff_t off) { #define x vals->x #define y vals->y #define c0 vals->a.c0 #define c1 vals->a.c1 - x = ((len - off - 1) * c0 - c1) % 255; - - if (x <= 0) - x += 255; - y = 510 - c0 - x; - if (y > 255) - y -= 255; + x = ((len - off - 1) * c0 - c1) % 255; - /* take care endian issue. */ - return htons ((x << 8) + y); + if (x <= 0) + x += 255; + y = 510 - c0 - x; + if (y > 255) + y -= 255; + + /* take care endian issue. */ + return htons((x << 8) + y); #undef x #undef y #undef c0 @@ -73,23 +73,23 @@ reduce_ospfd (struct csum_vals *vals, testsz_t len, testoff_t off) } /* slightly different concatenation */ -static u_int16_t -reduce_ospfd1 (struct csum_vals *vals, testsz_t len, testoff_t off) +static u_int16_t reduce_ospfd1(struct csum_vals *vals, testsz_t len, + testoff_t off) { #define x vals->x #define y vals->y #define c0 vals->a.c0 #define c1 vals->a.c1 - x = ((len - off - 1) * c0 - c1) % 255; - if (x <= 0) - x += 255; - y = 510 - c0 - x; - if (y > 255) - y -= 255; + x = ((len - off - 1) * c0 - c1) % 255; + if (x <= 0) + x += 255; + y = 510 - c0 - x; + if (y > 255) + y -= 255; - /* take care endian issue. */ - return htons ((x << 8) | (y & 0xff)); + /* take care endian issue. */ + return htons((x << 8) | (y & 0xff)); #undef x #undef y #undef c0 @@ -97,33 +97,33 @@ reduce_ospfd1 (struct csum_vals *vals, testsz_t len, testoff_t off) } /* original isisd version */ -static u_int16_t -reduce_isisd (struct csum_vals *vals, testsz_t len, testoff_t off) +static u_int16_t reduce_isisd(struct csum_vals *vals, testsz_t len, + testoff_t off) { #define x vals->x #define y vals->y #define c0 vals->a.c0 #define c1 vals->a.c1 - u_int32_t mul; - - mul = (len - off)*(c0); - x = mul - c0 - c1; - y = c1 - mul - 1; + u_int32_t mul; + + mul = (len - off) * (c0); + x = mul - c0 - c1; + y = c1 - mul - 1; - if (y > 0) - y++; - if (x < 0) - x--; + if (y > 0) + y++; + if (x < 0) + x--; - x %= 255; - y %= 255; + x %= 255; + y %= 255; - if (x == 0) - x = 255; - if (y == 0) - y = 1; + if (x == 0) + x = 255; + if (y == 0) + y = 1; - return htons ((x << 8) | (y & 0xff)); + return htons((x << 8) | (y & 0xff)); #undef x #undef y @@ -132,33 +132,33 @@ reduce_isisd (struct csum_vals *vals, testsz_t len, testoff_t off) } /* Is the -1 in y wrong perhaps? */ -static u_int16_t -reduce_isisd_yfix (struct csum_vals *vals, testsz_t len, testoff_t off) +static u_int16_t reduce_isisd_yfix(struct csum_vals *vals, testsz_t len, + testoff_t off) { #define x vals->x #define y vals->y #define c0 vals->a.c0 #define c1 vals->a.c1 - u_int32_t mul; - - mul = (len - off)*(c0); - x = mul - c0 - c1; - y = c1 - mul; + u_int32_t mul; + + mul = (len - off) * (c0); + x = mul - c0 - c1; + y = c1 - mul; - if (y > 0) - y++; - if (x < 0) - x--; + if (y > 0) + y++; + if (x < 0) + x--; - x %= 255; - y %= 255; + x %= 255; + y %= 255; - if (x == 0) - x = 255; - if (y == 0) - y = 1; + if (x == 0) + x = 255; + if (y == 0) + y = 1; - return htons ((x << 8) | (y & 0xff)); + return htons((x << 8) | (y & 0xff)); #undef x #undef y @@ -167,33 +167,33 @@ reduce_isisd_yfix (struct csum_vals *vals, testsz_t len, testoff_t off) } /* Move the mods yp */ -static u_int16_t -reduce_isisd_mod (struct csum_vals *vals, testsz_t len, testoff_t off) +static u_int16_t reduce_isisd_mod(struct csum_vals *vals, testsz_t len, + testoff_t off) { #define x vals->x #define y vals->y #define c0 vals->a.c0 #define c1 vals->a.c1 - u_int32_t mul; - - mul = (len - off)*(c0); - x = mul - c1 - c0; - y = c1 - mul - 1; + u_int32_t mul; - x %= 255; - y %= 255; + mul = (len - off) * (c0); + x = mul - c1 - c0; + y = c1 - mul - 1; - if (y > 0) - y++; - if (x < 0) - x--; + x %= 255; + y %= 255; - if (x == 0) - x = 255; - if (y == 0) - y = 1; + if (y > 0) + y++; + if (x < 0) + x--; - return htons ((x << 8) | (y & 0xff)); + if (x == 0) + x = 255; + if (y == 0) + y = 1; + + return htons((x << 8) | (y & 0xff)); #undef x #undef y @@ -202,33 +202,33 @@ reduce_isisd_mod (struct csum_vals *vals, testsz_t len, testoff_t off) } /* Move the mods up + fix y */ -static u_int16_t -reduce_isisd_mody (struct csum_vals *vals, testsz_t len, testoff_t off) +static u_int16_t reduce_isisd_mody(struct csum_vals *vals, testsz_t len, + testoff_t off) { #define x vals->x #define y vals->y #define c0 vals->a.c0 #define c1 vals->a.c1 - u_int32_t mul; - - mul = (len - off)*(c0); - x = mul - c0 - c1; - y = c1 - mul; + u_int32_t mul; + + mul = (len - off) * (c0); + x = mul - c0 - c1; + y = c1 - mul; - x %= 255; - y %= 255; + x %= 255; + y %= 255; - if (y > 0) - y++; - if (x < 0) - x--; + if (y > 0) + y++; + if (x < 0) + x--; - if (x == 0) - x = 255; - if (y == 0) - y = 1; + if (x == 0) + x = 255; + if (y == 0) + y = 1; - return htons ((x << 8) | (y & 0xff)); + return htons((x << 8) | (y & 0xff)); #undef x #undef y @@ -237,184 +237,175 @@ reduce_isisd_mody (struct csum_vals *vals, testsz_t len, testoff_t off) } struct reductions_t { - const char *name; - u_int16_t (*f) (struct csum_vals *, testsz_t, testoff_t); + const char *name; + u_int16_t (*f)(struct csum_vals *, testsz_t, testoff_t); } reducts[] = { - { .name = "ospfd", .f = reduce_ospfd }, - { .name = "ospfd-1", .f = reduce_ospfd1 }, - { .name = "isisd", .f = reduce_isisd }, - { .name = "isisd-yfix", .f = reduce_isisd_yfix }, - { .name = "isisd-mod", .f = reduce_isisd_mod }, - { .name = "isisd-mody", .f = reduce_isisd_mody }, - { NULL, NULL }, + {.name = "ospfd", .f = reduce_ospfd}, + {.name = "ospfd-1", .f = reduce_ospfd1}, + {.name = "isisd", .f = reduce_isisd}, + {.name = "isisd-yfix", .f = reduce_isisd_yfix}, + {.name = "isisd-mod", .f = reduce_isisd_mod}, + {.name = "isisd-mody", .f = reduce_isisd_mody}, + {NULL, NULL}, }; /* The original ospfd checksum */ -static u_int16_t -ospfd_checksum (u_char *buffer, testsz_t len, testoff_t off) +static u_int16_t ospfd_checksum(u_char *buffer, testsz_t len, testoff_t off) { - u_char *sp, *ep, *p, *q; - int c0 = 0, c1 = 0; - int x, y; - u_int16_t checksum, *csum; - - csum = (u_int16_t *) (buffer + off); - *(csum) = 0; - - sp = buffer; - - for (ep = sp + len; sp < ep; sp = q) - { - q = sp + MODX; - if (q > ep) - q = ep; - for (p = sp; p < q; p++) - { - c0 += *p; - c1 += c0; - } - c0 %= 255; - c1 %= 255; - } - - ospfd_vals.a.c0 = c0; - ospfd_vals.a.c1 = c1; - - //printf ("%s: len %u, off %u, c0 %d, c1 %d\n", - // __func__, len, off, c0, c1); - - x = ((int)(len - off - 1) * (int)c0 - (int)c1) % 255; - - if (x <= 0) - x += 255; - y = 510 - c0 - x; - if (y > 255) - y -= 255; - - ospfd_vals.x = x; - ospfd_vals.y = y; - - buffer[off] = x; - buffer[off + 1] = y; - - /* take care endian issue. */ - checksum = htons ((x << 8) | (y & 0xff)); - - return (checksum); + u_char *sp, *ep, *p, *q; + int c0 = 0, c1 = 0; + int x, y; + u_int16_t checksum, *csum; + + csum = (u_int16_t *)(buffer + off); + *(csum) = 0; + + sp = buffer; + + for (ep = sp + len; sp < ep; sp = q) { + q = sp + MODX; + if (q > ep) + q = ep; + for (p = sp; p < q; p++) { + c0 += *p; + c1 += c0; + } + c0 %= 255; + c1 %= 255; + } + + ospfd_vals.a.c0 = c0; + ospfd_vals.a.c1 = c1; + + // printf ("%s: len %u, off %u, c0 %d, c1 %d\n", + // __func__, len, off, c0, c1); + + x = ((int)(len - off - 1) * (int)c0 - (int)c1) % 255; + + if (x <= 0) + x += 255; + y = 510 - c0 - x; + if (y > 255) + y -= 255; + + ospfd_vals.x = x; + ospfd_vals.y = y; + + buffer[off] = x; + buffer[off + 1] = y; + + /* take care endian issue. */ + checksum = htons((x << 8) | (y & 0xff)); + + return (checksum); } /* the original, broken isisd checksum */ -static u_int16_t -iso_csum_create (u_char * buffer, testsz_t len, testoff_t off) +static u_int16_t iso_csum_create(u_char *buffer, testsz_t len, testoff_t off) { - u_int8_t *p; - int x; - int y; - u_int32_t mul; - u_int32_t c0; - u_int32_t c1; - u_int16_t checksum, *csum; - int i, init_len, partial_len; - - checksum = 0; - - csum = (u_int16_t *) (buffer + off); - *(csum) = checksum; - - p = buffer; - c0 = 0; - c1 = 0; - init_len = len; - - while (len != 0) - { - partial_len = MIN(len, MODX); - - for (i = 0; i < partial_len; i++) - { - c0 = c0 + *(p++); - c1 += c0; + u_int8_t *p; + int x; + int y; + u_int32_t mul; + u_int32_t c0; + u_int32_t c1; + u_int16_t checksum, *csum; + int i, init_len, partial_len; + + checksum = 0; + + csum = (u_int16_t *)(buffer + off); + *(csum) = checksum; + + p = buffer; + c0 = 0; + c1 = 0; + init_len = len; + + while (len != 0) { + partial_len = MIN(len, MODX); + + for (i = 0; i < partial_len; i++) { + c0 = c0 + *(p++); + c1 += c0; + } + + c0 = c0 % 255; + c1 = c1 % 255; + + len -= partial_len; } - c0 = c0 % 255; - c1 = c1 % 255; - - len -= partial_len; - } - - isisd_vals.a.c0 = c0; - isisd_vals.a.c1 = c1; - - mul = (init_len - off) * c0; - - x = mul - c1 - c0; - y = c1 - mul - 1; - - if (y > 0) - y++; - if (x < 0) - x--; - - x %= 255; - y %= 255; - - if (x == 0) - x = 255; - if (y == 0) - y = 1; - - isisd_vals.x = x; - isisd_vals.y = y; - - checksum = htons((x << 8) | (y & 0xFF)); - - *(csum) = checksum; - - /* return the checksum for user usage */ - return checksum; + isisd_vals.a.c0 = c0; + isisd_vals.a.c1 = c1; + + mul = (init_len - off) * c0; + + x = mul - c1 - c0; + y = c1 - mul - 1; + + if (y > 0) + y++; + if (x < 0) + x--; + + x %= 255; + y %= 255; + + if (x == 0) + x = 255; + if (y == 0) + y = 1; + + isisd_vals.x = x; + isisd_vals.y = y; + + checksum = htons((x << 8) | (y & 0xFF)); + + *(csum) = checksum; + + /* return the checksum for user usage */ + return checksum; } -static int -verify (u_char * buffer, testsz_t len) +static int verify(u_char *buffer, testsz_t len) { - u_int8_t *p; - u_int32_t c0; - u_int32_t c1; - int i, partial_len; - - p = buffer; - - c0 = 0; - c1 = 0; - - while (len) - { - partial_len = MIN(len, 5803U); - - for (i = 0; i < partial_len; i++) - { - c0 = c0 + *(p++); - c1 += c0; - } - c0 = c0 % 255; - c1 = c1 % 255; - - len -= partial_len; - } - - if (c0 == 0 && c1 == 0) - return 0; - - return 1; + u_int8_t *p; + u_int32_t c0; + u_int32_t c1; + int i, partial_len; + + p = buffer; + + c0 = 0; + c1 = 0; + + while (len) { + partial_len = MIN(len, 5803U); + + for (i = 0; i < partial_len; i++) { + c0 = c0 + *(p++); + c1 += c0; + } + c0 = c0 % 255; + c1 = c1 % 255; + + len -= partial_len; + } + + if (c0 == 0 && c1 == 0) + return 0; + + return 1; } -static int /* return checksum in low-order 16 bits */ -in_cksum_optimized(void *parg, int nbytes) +static int /* return checksum in low-order 16 bits */ + in_cksum_optimized(void *parg, int nbytes) { u_short *ptr = parg; - register long sum; /* assumes long == 32 bits */ - register u_short answer; /* assumes u_short == 16 bits */ + register long sum; /* assumes long == 32 bits */ + register u_short answer; /* assumes u_short == 16 bits */ register int count; /* * Our algorithm is simple, using a 32-bit accumulator (sum), @@ -424,126 +415,129 @@ in_cksum_optimized(void *parg, int nbytes) sum = 0; count = nbytes >> 1; /* div by 2 */ - for(ptr--; count; --count) - sum += *++ptr; + for (ptr--; count; --count) + sum += *++ptr; - if (nbytes & 1) /* Odd */ - sum += *(u_char *)(++ptr); /* one byte only */ + if (nbytes & 1) /* Odd */ + sum += *(u_char *)(++ptr); /* one byte only */ /* * Add back carry outs from top 16 bits to low 16 bits. */ - sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */ - sum += (sum >> 16); /* add carry */ - answer = ~sum; /* ones-complement, then truncate to 16 bits */ - return(answer); + sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* ones-complement, then truncate to 16 bits */ + return (answer); } static int /* return checksum in low-order 16 bits */ -in_cksum_rfc(void *parg, int count) + in_cksum_rfc(void *parg, int count) /* from RFC 1071 */ { u_short *addr = parg; /* Compute Internet Checksum for "count" bytes * beginning at location "addr". */ - register long sum = 0; + register long sum = 0; - while (count > 1) { - /* This is the inner loop */ - sum += *addr++; - count -= 2; + while (count > 1) { + /* This is the inner loop */ + sum += *addr++; + count -= 2; } /* Add left-over byte, if any */ if (count > 0) { - sum += *(u_char *)addr; + sum += *(u_char *)addr; } /* Fold 32-bit sum to 16 bits */ - while (sum>>16) - sum = (sum & 0xffff) + (sum >> 16); + while (sum >> 16) + sum = (sum & 0xffff) + (sum >> 16); return ~sum; } -int -main(int argc, char **argv) +int main(int argc, char **argv) { /* 60017 65629 702179 */ #define MAXDATALEN 60017 #define BUFSIZE MAXDATALEN + sizeof(u_int16_t) - u_char buffer[BUFSIZE]; - int exercise = 0; + u_char buffer[BUFSIZE]; + int exercise = 0; #define EXERCISESTEP 257 - - srandom (time (NULL)); - - while (1) { - u_int16_t ospfd, isisd, lib, in_csum, in_csum_res, in_csum_rfc; - int i,j; - - exercise += EXERCISESTEP; - exercise %= MAXDATALEN; - - for (i = 0; i < exercise; i += sizeof (long int)) { - long int rand = random (); - - for (j = sizeof (long int); j > 0; j--) - buffer[i + (sizeof (long int) - j)] = (rand >> (j * 8)) & 0xff; - } - - in_csum = in_cksum(buffer, exercise); - in_csum_res = in_cksum_optimized(buffer, exercise); - in_csum_rfc = in_cksum_rfc(buffer, exercise); - if (in_csum_res != in_csum || in_csum != in_csum_rfc) - printf ("verify: in_chksum failed in_csum:%x, in_csum_res:%x," - "in_csum_rfc %x, len:%d\n", - in_csum, in_csum_res, in_csum_rfc, exercise); - - ospfd = ospfd_checksum (buffer, exercise + sizeof(u_int16_t), exercise); - if (verify (buffer, exercise + sizeof(u_int16_t))) - printf ("verify: ospfd failed\n"); - isisd = iso_csum_create (buffer, exercise + sizeof(u_int16_t), exercise); - if (verify (buffer, exercise + sizeof(u_int16_t))) - printf ("verify: isisd failed\n"); - lib = fletcher_checksum (buffer, exercise + sizeof(u_int16_t), exercise); - if (verify (buffer, exercise + sizeof(u_int16_t))) - printf ("verify: lib failed\n"); - - if (ospfd != lib) { - printf ("Mismatch in values at size %u\n" - "ospfd: 0x%04x\tc0: %d\tc1: %d\tx: %d\ty: %d\n" - "isisd: 0x%04x\tc0: %d\tc1: %d\tx: %d\ty: %d\n" - "lib: 0x%04x\n", - exercise, - ospfd, ospfd_vals.a.c0, ospfd_vals.a.c1, ospfd_vals.x, ospfd_vals.y, - isisd, isisd_vals.a.c0, isisd_vals.a.c1, isisd_vals.x, isisd_vals.y, - lib - ); - - /* Investigate reduction phase discrepencies */ - if (ospfd_vals.a.c0 == isisd_vals.a.c0 - && ospfd_vals.a.c1 == isisd_vals.a.c1) { - printf ("\n"); - for (i = 0; reducts[i].name != NULL; i++) { - ospfd = reducts[i].f (&ospfd_vals, - exercise + sizeof (u_int16_t), - exercise); - printf ("%20s: x: %02x, y %02x, checksum 0x%04x\n", - reducts[i].name, ospfd_vals.x & 0xff, ospfd_vals.y & 0xff, ospfd); - } - } - - printf ("\n u_char testdata [] = {\n "); - for (i = 0; i < exercise; i++) { - printf ("0x%02x,%s", - buffer[i], - (i + 1) % 8 ? " " : "\n "); - } - printf ("\n}\n"); - exit (1); - } - } + srandom(time(NULL)); + + while (1) { + u_int16_t ospfd, isisd, lib, in_csum, in_csum_res, in_csum_rfc; + int i, j; + + exercise += EXERCISESTEP; + exercise %= MAXDATALEN; + + for (i = 0; i < exercise; i += sizeof(long int)) { + long int rand = random(); + + for (j = sizeof(long int); j > 0; j--) + buffer[i + (sizeof(long int) - j)] = + (rand >> (j * 8)) & 0xff; + } + + in_csum = in_cksum(buffer, exercise); + in_csum_res = in_cksum_optimized(buffer, exercise); + in_csum_rfc = in_cksum_rfc(buffer, exercise); + if (in_csum_res != in_csum || in_csum != in_csum_rfc) + printf("verify: in_chksum failed in_csum:%x, in_csum_res:%x," + "in_csum_rfc %x, len:%d\n", + in_csum, in_csum_res, in_csum_rfc, exercise); + + ospfd = ospfd_checksum(buffer, exercise + sizeof(u_int16_t), + exercise); + if (verify(buffer, exercise + sizeof(u_int16_t))) + printf("verify: ospfd failed\n"); + isisd = iso_csum_create(buffer, exercise + sizeof(u_int16_t), + exercise); + if (verify(buffer, exercise + sizeof(u_int16_t))) + printf("verify: isisd failed\n"); + lib = fletcher_checksum(buffer, exercise + sizeof(u_int16_t), + exercise); + if (verify(buffer, exercise + sizeof(u_int16_t))) + printf("verify: lib failed\n"); + + if (ospfd != lib) { + printf("Mismatch in values at size %u\n" + "ospfd: 0x%04x\tc0: %d\tc1: %d\tx: %d\ty: %d\n" + "isisd: 0x%04x\tc0: %d\tc1: %d\tx: %d\ty: %d\n" + "lib: 0x%04x\n", + exercise, ospfd, ospfd_vals.a.c0, + ospfd_vals.a.c1, ospfd_vals.x, ospfd_vals.y, + isisd, isisd_vals.a.c0, isisd_vals.a.c1, + isisd_vals.x, isisd_vals.y, lib); + + /* Investigate reduction phase discrepencies */ + if (ospfd_vals.a.c0 == isisd_vals.a.c0 + && ospfd_vals.a.c1 == isisd_vals.a.c1) { + printf("\n"); + for (i = 0; reducts[i].name != NULL; i++) { + ospfd = reducts[i].f( + &ospfd_vals, + exercise + sizeof(u_int16_t), + exercise); + printf("%20s: x: %02x, y %02x, checksum 0x%04x\n", + reducts[i].name, + ospfd_vals.x & 0xff, + ospfd_vals.y & 0xff, ospfd); + } + } + + printf("\n u_char testdata [] = {\n "); + for (i = 0; i < exercise; i++) { + printf("0x%02x,%s", buffer[i], + (i + 1) % 8 ? " " : "\n "); + } + printf("\n}\n"); + exit(1); + } + } } diff --git a/tests/lib/test_heavy.c b/tests/lib/test_heavy.c index c6f6bbba2..604a5733c 100644 --- a/tests/lib/test_heavy.c +++ b/tests/lib/test_heavy.c @@ -37,46 +37,42 @@ #include "tests.h" -enum -{ - ITERS_FIRST = 0, - ITERS_ERR = 100, - ITERS_LATER = 400, - ITERS_PRINT = 10, - ITERS_MAX = 1000, +enum { ITERS_FIRST = 0, + ITERS_ERR = 100, + ITERS_LATER = 400, + ITERS_PRINT = 10, + ITERS_MAX = 1000, }; -static void -slow_func (struct vty *vty, const char *str, const int i) +static void slow_func(struct vty *vty, const char *str, const int i) { - double x = 1; - int j; - - for (j = 0; j < 300; j++) - x += sin(x)*j; - - if ((i % ITERS_LATER) == 0) - printf ("%s: %d, temporary error, save this somehow and do it later..\n", - __func__, i); - - if ((i % ITERS_ERR) == 0) - printf ("%s: hard error\n", __func__); - - if ((i % ITERS_PRINT) == 0) - printf ("%s did %d, x = %g\n", str, i, x); + double x = 1; + int j; + + for (j = 0; j < 300; j++) + x += sin(x) * j; + + if ((i % ITERS_LATER) == 0) + printf("%s: %d, temporary error, save this somehow and do it later..\n", + __func__, i); + + if ((i % ITERS_ERR) == 0) + printf("%s: hard error\n", __func__); + + if ((i % ITERS_PRINT) == 0) + printf("%s did %d, x = %g\n", str, i, x); } -static void -clear_something (struct vty *vty, const char *str) +static void clear_something(struct vty *vty, const char *str) { - int i; - - /* this could be like iterating through 150k of route_table - * or worse, iterating through a list of peers, to bgp_stop them with - * each having 150k route tables to process... - */ - for (i = ITERS_FIRST; i < ITERS_MAX; i++) - slow_func (vty, str, i); + int i; + + /* this could be like iterating through 150k of route_table + * or worse, iterating through a list of peers, to bgp_stop them with + * each having 150k route tables to process... + */ + for (i = ITERS_FIRST; i < ITERS_MAX; i++) + slow_func(vty, str, i); } DEFUN (clear_foo, @@ -85,28 +81,25 @@ DEFUN (clear_foo, "clear command\n" "arbitrary string\n") { - char *str; - if (!argc) - { - vty_out (vty, "%% string argument required\n"); - return CMD_WARNING; - } - - str = argv_concat (argv, argc, 0); - - clear_something (vty, str); - XFREE (MTYPE_TMP, str); - return CMD_SUCCESS; + char *str; + if (!argc) { + vty_out(vty, "%% string argument required\n"); + return CMD_WARNING; + } + + str = argv_concat(argv, argc, 0); + + clear_something(vty, str); + XFREE(MTYPE_TMP, str); + return CMD_SUCCESS; } -static void -slow_vty_init() +static void slow_vty_init() { - install_element (VIEW_NODE, &clear_foo_cmd); + install_element(VIEW_NODE, &clear_foo_cmd); } -void -test_init() +void test_init() { - slow_vty_init(); + slow_vty_init(); } diff --git a/tests/lib/test_heavy_thread.c b/tests/lib/test_heavy_thread.c index 9e1d70adc..9a7578006 100644 --- a/tests/lib/test_heavy_thread.c +++ b/tests/lib/test_heavy_thread.c @@ -40,65 +40,60 @@ extern struct thread_master *master; -enum -{ - ITERS_FIRST = 0, - ITERS_ERR = 100, - ITERS_LATER = 400, - ITERS_PRINT = 10, - ITERS_MAX = 1000, +enum { ITERS_FIRST = 0, + ITERS_ERR = 100, + ITERS_LATER = 400, + ITERS_PRINT = 10, + ITERS_MAX = 1000, }; struct work_state { - struct vty *vty; - char *str; - int i; + struct vty *vty; + char *str; + int i; }; -static void -slow_func (struct vty *vty, const char *str, const int i) +static void slow_func(struct vty *vty, const char *str, const int i) { - double x = 1; - int j; - - for (j = 0; j < 300; j++) - x += sin(x)*j; - - if ((i % ITERS_LATER) == 0) - printf ("%s: %d, temporary error, save this somehow and do it later..\n", - __func__, i); - - if ((i % ITERS_ERR) == 0) - printf ("%s: hard error\n", __func__); - - if ((i % ITERS_PRINT) == 0) - printf ("%s did %d, x = %g\n", str, i, x); + double x = 1; + int j; + + for (j = 0; j < 300; j++) + x += sin(x) * j; + + if ((i % ITERS_LATER) == 0) + printf("%s: %d, temporary error, save this somehow and do it later..\n", + __func__, i); + + if ((i % ITERS_ERR) == 0) + printf("%s: hard error\n", __func__); + + if ((i % ITERS_PRINT) == 0) + printf("%s did %d, x = %g\n", str, i, x); } -static int -clear_something (struct thread *thread) +static int clear_something(struct thread *thread) { - struct work_state *ws = THREAD_ARG(thread); - - /* this could be like iterating through 150k of route_table - * or worse, iterating through a list of peers, to bgp_stop them with - * each having 150k route tables to process... - */ - while (ws->i < ITERS_MAX) - { - slow_func(ws->vty, ws->str, ws->i); - ws->i++; - if (thread_should_yield(thread)) - { - thread_add_timer_msec (master, clear_something, ws, 0, NULL); - return 0; - } - } - - /* All done! */ - XFREE (MTYPE_TMP, ws->str); - XFREE (MTYPE_TMP, ws); - return 0; + struct work_state *ws = THREAD_ARG(thread); + + /* this could be like iterating through 150k of route_table + * or worse, iterating through a list of peers, to bgp_stop them with + * each having 150k route tables to process... + */ + while (ws->i < ITERS_MAX) { + slow_func(ws->vty, ws->str, ws->i); + ws->i++; + if (thread_should_yield(thread)) { + thread_add_timer_msec(master, clear_something, ws, 0, + NULL); + return 0; + } + } + + /* All done! */ + XFREE(MTYPE_TMP, ws->str); + XFREE(MTYPE_TMP, ws); + return 0; } DEFUN (clear_foo, @@ -107,40 +102,36 @@ DEFUN (clear_foo, "clear command\n" "arbitrary string\n") { - char *str; - struct work_state *ws; - - if (!argc) - { - vty_out (vty, "%% string argument required\n"); - return CMD_WARNING; - } - - str = argv_concat (argv, argc, 0); - - if ((ws = XMALLOC(MTYPE_TMP, sizeof(*ws))) == NULL) - { - zlog_err ("%s: unable to allocate work_state", __func__); - return CMD_WARNING; - } - - if (!(ws->str = XSTRDUP (MTYPE_TMP, str))) - { - zlog_err ("%s: unable to xstrdup", __func__); - XFREE (MTYPE_TMP, ws); - return CMD_WARNING; - } - - ws->vty = vty; - ws->i = ITERS_FIRST; - - thread_add_timer_msec (master, clear_something, ws, 0, NULL); - - return CMD_SUCCESS; + char *str; + struct work_state *ws; + + if (!argc) { + vty_out(vty, "%% string argument required\n"); + return CMD_WARNING; + } + + str = argv_concat(argv, argc, 0); + + if ((ws = XMALLOC(MTYPE_TMP, sizeof(*ws))) == NULL) { + zlog_err("%s: unable to allocate work_state", __func__); + return CMD_WARNING; + } + + if (!(ws->str = XSTRDUP(MTYPE_TMP, str))) { + zlog_err("%s: unable to xstrdup", __func__); + XFREE(MTYPE_TMP, ws); + return CMD_WARNING; + } + + ws->vty = vty; + ws->i = ITERS_FIRST; + + thread_add_timer_msec(master, clear_something, ws, 0, NULL); + + return CMD_SUCCESS; } -void -test_init() +void test_init() { - install_element (VIEW_NODE, &clear_foo_cmd); + install_element(VIEW_NODE, &clear_foo_cmd); } diff --git a/tests/lib/test_heavy_wq.c b/tests/lib/test_heavy_wq.c index 18b80d081..0f474dc5d 100644 --- a/tests/lib/test_heavy_wq.c +++ b/tests/lib/test_heavy_wq.c @@ -44,97 +44,88 @@ DEFINE_MTYPE_STATIC(TEST_HEAVYWQ, WQ_NODE_STR, "heavy_wq_node->str") extern struct thread_master *master; static struct work_queue *heavy_wq; -struct heavy_wq_node -{ - char *str; - int i; +struct heavy_wq_node { + char *str; + int i; }; -enum -{ - ITERS_FIRST = 0, - ITERS_ERR = 100, - ITERS_LATER = 400, - ITERS_PRINT = 10, - ITERS_MAX = 1000, +enum { ITERS_FIRST = 0, + ITERS_ERR = 100, + ITERS_LATER = 400, + ITERS_PRINT = 10, + ITERS_MAX = 1000, }; -static void -heavy_wq_add (struct vty *vty, const char *str, int i) +static void heavy_wq_add(struct vty *vty, const char *str, int i) { - struct heavy_wq_node *hn; - - if ((hn = XCALLOC (MTYPE_WQ_NODE, sizeof(struct heavy_wq_node))) == NULL) - { - zlog_err ("%s: unable to allocate hn", __func__); - return; - } - - hn->i = i; - if (!(hn->str = XSTRDUP (MTYPE_WQ_NODE_STR, str))) - { - zlog_err ("%s: unable to xstrdup", __func__); - XFREE (MTYPE_WQ_NODE, hn); - return; - } - - work_queue_add (heavy_wq, hn); - - return; + struct heavy_wq_node *hn; + + if ((hn = XCALLOC(MTYPE_WQ_NODE, sizeof(struct heavy_wq_node))) + == NULL) { + zlog_err("%s: unable to allocate hn", __func__); + return; + } + + hn->i = i; + if (!(hn->str = XSTRDUP(MTYPE_WQ_NODE_STR, str))) { + zlog_err("%s: unable to xstrdup", __func__); + XFREE(MTYPE_WQ_NODE, hn); + return; + } + + work_queue_add(heavy_wq, hn); + + return; } -static void -slow_func_err (struct work_queue *wq, struct work_queue_item *item) +static void slow_func_err(struct work_queue *wq, struct work_queue_item *item) { - printf ("%s: running error function\n", __func__); + printf("%s: running error function\n", __func__); } -static void -slow_func_del (struct work_queue *wq, void *data) +static void slow_func_del(struct work_queue *wq, void *data) { - struct heavy_wq_node *hn = data; - assert (hn && hn->str); - printf ("%s: %s\n", __func__, hn->str); - XFREE (MTYPE_WQ_NODE_STR, hn->str); - hn->str = NULL; - XFREE(MTYPE_WQ_NODE, hn); + struct heavy_wq_node *hn = data; + assert(hn && hn->str); + printf("%s: %s\n", __func__, hn->str); + XFREE(MTYPE_WQ_NODE_STR, hn->str); + hn->str = NULL; + XFREE(MTYPE_WQ_NODE, hn); } -static wq_item_status -slow_func (struct work_queue *wq, void *data) +static wq_item_status slow_func(struct work_queue *wq, void *data) { - struct heavy_wq_node *hn = data; - double x = 1; - int j; - - assert (hn && hn->str); - - for (j = 0; j < 300; j++) - x += sin(x)*j; - - if ((hn->i % ITERS_LATER) == 0) - return WQ_RETRY_LATER; - - if ((hn->i % ITERS_ERR) == 0) - return WQ_RETRY_NOW; - - if ((hn->i % ITERS_PRINT) == 0) - printf ("%s did %d, x = %g\n", hn->str, hn->i, x); - - return WQ_SUCCESS; + struct heavy_wq_node *hn = data; + double x = 1; + int j; + + assert(hn && hn->str); + + for (j = 0; j < 300; j++) + x += sin(x) * j; + + if ((hn->i % ITERS_LATER) == 0) + return WQ_RETRY_LATER; + + if ((hn->i % ITERS_ERR) == 0) + return WQ_RETRY_NOW; + + if ((hn->i % ITERS_PRINT) == 0) + printf("%s did %d, x = %g\n", hn->str, hn->i, x); + + return WQ_SUCCESS; } -static void -clear_something (struct vty *vty, const char *str) +static void clear_something(struct vty *vty, const char *str) { - int i; - - /* this could be like iterating through 150k of route_table - * or worse, iterating through a list of peers, to bgp_stop them with - * each having 150k route tables to process... - */ - for (i = ITERS_FIRST; i < ITERS_MAX; i++) - heavy_wq_add (vty, str, i); + int i; + + /* this could be like iterating through 150k of route_table + * or worse, iterating through a list of peers, to bgp_stop them with + * each having 150k route tables to process... + */ + for (i = ITERS_FIRST; i < ITERS_MAX; i++) + heavy_wq_add(vty, str, i); } DEFUN (clear_foo, @@ -143,41 +134,37 @@ DEFUN (clear_foo, "clear command\n" "arbitrary string\n") { - char *str; - if (!argc) - { - vty_out (vty, "%% string argument required\n"); - return CMD_WARNING; - } - - str = argv_concat (argv, argc, 0); - - clear_something (vty, str); - XFREE (MTYPE_TMP, str); - return CMD_SUCCESS; + char *str; + if (!argc) { + vty_out(vty, "%% string argument required\n"); + return CMD_WARNING; + } + + str = argv_concat(argv, argc, 0); + + clear_something(vty, str); + XFREE(MTYPE_TMP, str); + return CMD_SUCCESS; } -static int -heavy_wq_init () +static int heavy_wq_init() { - if (! (heavy_wq = work_queue_new (master, "heavy_work_queue"))) - { - zlog_err ("%s: could not get new work queue!", __func__); - return -1; - } - - heavy_wq->spec.workfunc = &slow_func; - heavy_wq->spec.errorfunc = &slow_func_err; - heavy_wq->spec.del_item_data = &slow_func_del; - heavy_wq->spec.max_retries = 3; - heavy_wq->spec.hold = 1000; - - return 0; + if (!(heavy_wq = work_queue_new(master, "heavy_work_queue"))) { + zlog_err("%s: could not get new work queue!", __func__); + return -1; + } + + heavy_wq->spec.workfunc = &slow_func; + heavy_wq->spec.errorfunc = &slow_func_err; + heavy_wq->spec.del_item_data = &slow_func_del; + heavy_wq->spec.max_retries = 3; + heavy_wq->spec.hold = 1000; + + return 0; } -void -test_init() +void test_init() { - install_element (VIEW_NODE, &clear_foo_cmd); - heavy_wq_init(); + install_element(VIEW_NODE, &clear_foo_cmd); + heavy_wq_init(); } diff --git a/tests/lib/test_memory.c b/tests/lib/test_memory.c index 633ee0d56..84be9cb76 100644 --- a/tests/lib/test_memory.c +++ b/tests/lib/test_memory.c @@ -1,4 +1,4 @@ -/* +/* * This file is part of Quagga. * * Quagga is free software; you can redistribute it and/or modify it @@ -44,81 +44,77 @@ struct thread_master *master; #define TIMES 10 -int -main(int argc, char **argv) +int main(int argc, char **argv) { - void *a[10]; - int i; + void *a[10]; + int i; - printf ("malloc x, malloc x, free, malloc x, free free\n\n"); - /* simple case, test cache */ - for (i = 0; i < TIMES; i++) - { - a[0] = XMALLOC (MTYPE_TEST, 1024); - memset (a[0], 1, 1024); - a[1] = XMALLOC (MTYPE_TEST, 1024); - memset (a[1], 1, 1024); - XFREE(MTYPE_TEST, a[0]); /* should go to cache */ - a[0] = XMALLOC (MTYPE_TEST, 1024); /* should be satisfied from cache */ - XFREE(MTYPE_TEST, a[0]); - XFREE(MTYPE_TEST, a[1]); - } - - printf ("malloc x, malloc y, free x, malloc y, free free\n\n"); - /* cache should go invalid, valid, invalid, etc.. */ - for (i = 0; i < TIMES; i++) - { - a[0] = XMALLOC (MTYPE_TEST, 512); - memset (a[0], 1, 512); - a[1] = XMALLOC (MTYPE_TEST, 1024); /* invalidate cache */ - memset (a[1], 1, 1024); - XFREE(MTYPE_TEST, a[0]); - a[0] = XMALLOC (MTYPE_TEST, 1024); - XFREE(MTYPE_TEST, a[0]); - XFREE(MTYPE_TEST, a[1]); - /* cache should become valid again on next request */ - } + printf("malloc x, malloc x, free, malloc x, free free\n\n"); + /* simple case, test cache */ + for (i = 0; i < TIMES; i++) { + a[0] = XMALLOC(MTYPE_TEST, 1024); + memset(a[0], 1, 1024); + a[1] = XMALLOC(MTYPE_TEST, 1024); + memset(a[1], 1, 1024); + XFREE(MTYPE_TEST, a[0]); /* should go to cache */ + a[0] = XMALLOC(MTYPE_TEST, + 1024); /* should be satisfied from cache */ + XFREE(MTYPE_TEST, a[0]); + XFREE(MTYPE_TEST, a[1]); + } - printf ("calloc\n\n"); - /* test calloc */ - for (i = 0; i < TIMES; i++) - { - a[0] = XCALLOC (MTYPE_TEST, 1024); - memset (a[0], 1, 1024); - a[1] = XCALLOC (MTYPE_TEST, 512); /* invalidate cache */ - memset (a[1], 1, 512); - XFREE(MTYPE_TEST, a[1]); - XFREE(MTYPE_TEST, a[0]); - /* alloc == 0, cache can become valid again on next request */ - } - - printf ("calloc and realloc\n\n"); - /* check calloc + realloc */ - for (i = 0; i < TIMES; i++) - { - printf ("calloc a0 1024\n"); - a[0] = XCALLOC (MTYPE_TEST, 1024); - memset (a[0], 1, 1024/2); - - printf ("calloc 1 1024\n"); - a[1] = XCALLOC (MTYPE_TEST, 1024); - memset (a[1], 1, 1024/2); - - printf ("realloc 0 1024\n"); - a[3] = XREALLOC (MTYPE_TEST, a[0], 2048); /* invalidate cache */ - if (a[3] != NULL) - a[0] = a[3]; - memset (a[0], 1, 1024); - - printf ("calloc 2 512\n"); - a[2] = XCALLOC (MTYPE_TEST, 512); - memset (a[2], 1, 512); - - printf ("free 1 0 2\n"); - XFREE(MTYPE_TEST, a[1]); - XFREE(MTYPE_TEST, a[0]); - XFREE(MTYPE_TEST, a[2]); - /* alloc == 0, cache valid next request */ - } - return 0; + printf("malloc x, malloc y, free x, malloc y, free free\n\n"); + /* cache should go invalid, valid, invalid, etc.. */ + for (i = 0; i < TIMES; i++) { + a[0] = XMALLOC(MTYPE_TEST, 512); + memset(a[0], 1, 512); + a[1] = XMALLOC(MTYPE_TEST, 1024); /* invalidate cache */ + memset(a[1], 1, 1024); + XFREE(MTYPE_TEST, a[0]); + a[0] = XMALLOC(MTYPE_TEST, 1024); + XFREE(MTYPE_TEST, a[0]); + XFREE(MTYPE_TEST, a[1]); + /* cache should become valid again on next request */ + } + + printf("calloc\n\n"); + /* test calloc */ + for (i = 0; i < TIMES; i++) { + a[0] = XCALLOC(MTYPE_TEST, 1024); + memset(a[0], 1, 1024); + a[1] = XCALLOC(MTYPE_TEST, 512); /* invalidate cache */ + memset(a[1], 1, 512); + XFREE(MTYPE_TEST, a[1]); + XFREE(MTYPE_TEST, a[0]); + /* alloc == 0, cache can become valid again on next request */ + } + + printf("calloc and realloc\n\n"); + /* check calloc + realloc */ + for (i = 0; i < TIMES; i++) { + printf("calloc a0 1024\n"); + a[0] = XCALLOC(MTYPE_TEST, 1024); + memset(a[0], 1, 1024 / 2); + + printf("calloc 1 1024\n"); + a[1] = XCALLOC(MTYPE_TEST, 1024); + memset(a[1], 1, 1024 / 2); + + printf("realloc 0 1024\n"); + a[3] = XREALLOC(MTYPE_TEST, a[0], 2048); /* invalidate cache */ + if (a[3] != NULL) + a[0] = a[3]; + memset(a[0], 1, 1024); + + printf("calloc 2 512\n"); + a[2] = XCALLOC(MTYPE_TEST, 512); + memset(a[2], 1, 512); + + printf("free 1 0 2\n"); + XFREE(MTYPE_TEST, a[1]); + XFREE(MTYPE_TEST, a[0]); + XFREE(MTYPE_TEST, a[2]); + /* alloc == 0, cache valid next request */ + } + return 0; } diff --git a/tests/lib/test_nexthop_iter.c b/tests/lib/test_nexthop_iter.c index 18628ec16..8d7353d4d 100644 --- a/tests/lib/test_nexthop_iter.c +++ b/tests/lib/test_nexthop_iter.c @@ -29,178 +29,155 @@ struct thread_master *master; static int verbose; -static void -str_append(char **buf, const char *repr) +static void str_append(char **buf, const char *repr) { - if (*buf) - { - *buf = realloc(*buf, strlen(*buf) + strlen(repr) + 1); - assert(*buf); - strncpy((*buf) + strlen(*buf), repr, strlen(repr) + 1); - } - else - { - *buf = strdup(repr); - assert(*buf); - } + if (*buf) { + *buf = realloc(*buf, strlen(*buf) + strlen(repr) + 1); + assert(*buf); + strncpy((*buf) + strlen(*buf), repr, strlen(repr) + 1); + } else { + *buf = strdup(repr); + assert(*buf); + } } -static void -str_appendf(char **buf, const char *format, ...) +static void str_appendf(char **buf, const char *format, ...) { - va_list ap; - int rv; - char *pbuf; + va_list ap; + int rv; + char *pbuf; - va_start(ap, format); - rv = vasprintf(&pbuf, format, ap); - va_end(ap); - assert(rv >= 0); + va_start(ap, format); + rv = vasprintf(&pbuf, format, ap); + va_end(ap); + assert(rv >= 0); - str_append(buf, pbuf); - free(pbuf); + str_append(buf, pbuf); + free(pbuf); } /* This structure contains a nexthop chain * and its expected representation */ -struct nexthop_chain -{ - /* Head of the chain */ - struct nexthop *head; - /* Last nexthop in top chain */ - struct nexthop *current_top; - /* Last nexthop in current recursive chain */ - struct nexthop *current_recursive; - /* Expected string representation. */ - char *repr; +struct nexthop_chain { + /* Head of the chain */ + struct nexthop *head; + /* Last nexthop in top chain */ + struct nexthop *current_top; + /* Last nexthop in current recursive chain */ + struct nexthop *current_recursive; + /* Expected string representation. */ + char *repr; }; -static struct nexthop_chain* -nexthop_chain_new(void) +static struct nexthop_chain *nexthop_chain_new(void) { - struct nexthop_chain *rv; + struct nexthop_chain *rv; - rv = calloc(sizeof(*rv), 1); - assert(rv); - return rv; + rv = calloc(sizeof(*rv), 1); + assert(rv); + return rv; } -static void -nexthop_chain_add_top(struct nexthop_chain *nc) +static void nexthop_chain_add_top(struct nexthop_chain *nc) { - struct nexthop *nh; - - nh = calloc(sizeof(*nh), 1); - assert(nh); - - if (nc->head) - { - nc->current_top->next = nh; - nh->prev = nc->current_top; - nc->current_top = nh; - } - else - { - nc->head = nc->current_top = nh; - } - nc->current_recursive = NULL; - str_appendf(&nc->repr, "%p\n", nh); + struct nexthop *nh; + + nh = calloc(sizeof(*nh), 1); + assert(nh); + + if (nc->head) { + nc->current_top->next = nh; + nh->prev = nc->current_top; + nc->current_top = nh; + } else { + nc->head = nc->current_top = nh; + } + nc->current_recursive = NULL; + str_appendf(&nc->repr, "%p\n", nh); } -static void -add_string_representation (char **repr, struct nexthop *nh) +static void add_string_representation(char **repr, struct nexthop *nh) { - struct nexthop *parent; - - /* add indentations first */ - parent = nh->rparent; - while (parent) - { - str_appendf(repr, " "); - parent = parent->rparent; - } - str_appendf(repr, "%p\n", nh); + struct nexthop *parent; + + /* add indentations first */ + parent = nh->rparent; + while (parent) { + str_appendf(repr, " "); + parent = parent->rparent; + } + str_appendf(repr, "%p\n", nh); } -static void -start_recursive_chain (struct nexthop_chain *nc, struct nexthop *nh) +static void start_recursive_chain(struct nexthop_chain *nc, struct nexthop *nh) { - SET_FLAG(nc->current_top->flags, NEXTHOP_FLAG_RECURSIVE); - nc->current_top->resolved = nh; - nh->rparent = nc->current_top; - nc->current_recursive = nh; + SET_FLAG(nc->current_top->flags, NEXTHOP_FLAG_RECURSIVE); + nc->current_top->resolved = nh; + nh->rparent = nc->current_top; + nc->current_recursive = nh; } -static void -nexthop_chain_add_recursive(struct nexthop_chain *nc) +static void nexthop_chain_add_recursive(struct nexthop_chain *nc) { - struct nexthop *nh; - - nh = calloc(sizeof(*nh), 1); - assert(nh); - - assert(nc->current_top); - if (nc->current_recursive) - { - nc->current_recursive->next = nh; - nh->prev = nc->current_recursive; - nh->rparent = nc->current_recursive->rparent; - nc->current_recursive = nh; - } - else - start_recursive_chain (nc, nh); - - add_string_representation (&nc->repr, nh); + struct nexthop *nh; + + nh = calloc(sizeof(*nh), 1); + assert(nh); + + assert(nc->current_top); + if (nc->current_recursive) { + nc->current_recursive->next = nh; + nh->prev = nc->current_recursive; + nh->rparent = nc->current_recursive->rparent; + nc->current_recursive = nh; + } else + start_recursive_chain(nc, nh); + + add_string_representation(&nc->repr, nh); } -static void -nexthop_chain_add_recursive_level(struct nexthop_chain *nc) +static void nexthop_chain_add_recursive_level(struct nexthop_chain *nc) { - struct nexthop *nh; - - nh = calloc(sizeof(*nh), 1); - assert(nh); - - assert(nc->current_top); - if (nc->current_recursive) - { - SET_FLAG(nc->current_recursive->flags, NEXTHOP_FLAG_RECURSIVE); - nc->current_recursive->resolved = nh; - nh->rparent = nc->current_recursive; - nc->current_recursive = nh; - } - else - start_recursive_chain (nc, nh); - - add_string_representation (&nc->repr, nh); + struct nexthop *nh; + + nh = calloc(sizeof(*nh), 1); + assert(nh); + + assert(nc->current_top); + if (nc->current_recursive) { + SET_FLAG(nc->current_recursive->flags, NEXTHOP_FLAG_RECURSIVE); + nc->current_recursive->resolved = nh; + nh->rparent = nc->current_recursive; + nc->current_recursive = nh; + } else + start_recursive_chain(nc, nh); + + add_string_representation(&nc->repr, nh); } -static void -nexthop_clear_recursive (struct nexthop *tcur) +static void nexthop_clear_recursive(struct nexthop *tcur) { - if (!tcur) - return; - if (CHECK_FLAG(tcur->flags, NEXTHOP_FLAG_RECURSIVE)) - nexthop_clear_recursive (tcur->resolved); - if (tcur->next) - nexthop_clear_recursive (tcur->next); - free (tcur); + if (!tcur) + return; + if (CHECK_FLAG(tcur->flags, NEXTHOP_FLAG_RECURSIVE)) + nexthop_clear_recursive(tcur->resolved); + if (tcur->next) + nexthop_clear_recursive(tcur->next); + free(tcur); } -static void -nexthop_chain_clear(struct nexthop_chain *nc) +static void nexthop_chain_clear(struct nexthop_chain *nc) { - nexthop_clear_recursive (nc->head); - nc->head = nc->current_top = nc->current_recursive = NULL; - free(nc->repr); - nc->repr = NULL; + nexthop_clear_recursive(nc->head); + nc->head = nc->current_top = nc->current_recursive = NULL; + free(nc->repr); + nc->repr = NULL; } -static void -nexthop_chain_free(struct nexthop_chain *nc) +static void nexthop_chain_free(struct nexthop_chain *nc) { - if (!nc) - return; - nexthop_chain_clear(nc); - free(nc); + if (!nc) + return; + nexthop_chain_clear(nc); + free(nc); } /* This function builds a string representation of @@ -209,19 +186,19 @@ nexthop_chain_free(struct nexthop_chain *nc) * correctly over the nexthop chain by comparing the * generated representation with the expected representation. */ -static void -nexthop_chain_verify_iter(struct nexthop_chain *nc) +static void nexthop_chain_verify_iter(struct nexthop_chain *nc) { - struct nexthop *nh; - char *repr = NULL; + struct nexthop *nh; + char *repr = NULL; - for (ALL_NEXTHOPS(nc->head, nh)) - add_string_representation (&repr, nh); + for (ALL_NEXTHOPS(nc->head, nh)) + add_string_representation(&repr, nh); - if (repr && verbose) - printf("===\n%s", repr); - assert((!repr && !nc->repr) || (repr && nc->repr && !strcmp(repr, nc->repr))); - free(repr); + if (repr && verbose) + printf("===\n%s", repr); + assert((!repr && !nc->repr) + || (repr && nc->repr && !strcmp(repr, nc->repr))); + free(repr); } /* This test run builds a simple nexthop chain @@ -229,110 +206,106 @@ nexthop_chain_verify_iter(struct nexthop_chain *nc) * the iterator works correctly in each stage along * the way. */ -static void -test_run_first(void) +static void test_run_first(void) { - struct nexthop_chain *nc; + struct nexthop_chain *nc; - nc = nexthop_chain_new(); - nexthop_chain_verify_iter(nc); + nc = nexthop_chain_new(); + nexthop_chain_verify_iter(nc); - nexthop_chain_add_top(nc); - nexthop_chain_verify_iter(nc); + nexthop_chain_add_top(nc); + nexthop_chain_verify_iter(nc); - nexthop_chain_add_top(nc); - nexthop_chain_verify_iter(nc); + nexthop_chain_add_top(nc); + nexthop_chain_verify_iter(nc); - nexthop_chain_add_recursive(nc); - nexthop_chain_verify_iter(nc); + nexthop_chain_add_recursive(nc); + nexthop_chain_verify_iter(nc); - nexthop_chain_add_recursive(nc); - nexthop_chain_verify_iter(nc); + nexthop_chain_add_recursive(nc); + nexthop_chain_verify_iter(nc); - nexthop_chain_add_top(nc); - nexthop_chain_verify_iter(nc); + nexthop_chain_add_top(nc); + nexthop_chain_verify_iter(nc); - nexthop_chain_add_top(nc); - nexthop_chain_verify_iter(nc); + nexthop_chain_add_top(nc); + nexthop_chain_verify_iter(nc); - nexthop_chain_add_top(nc); - nexthop_chain_verify_iter(nc); + nexthop_chain_add_top(nc); + nexthop_chain_verify_iter(nc); - nexthop_chain_add_recursive(nc); - nexthop_chain_verify_iter(nc); + nexthop_chain_add_recursive(nc); + nexthop_chain_verify_iter(nc); - nexthop_chain_add_recursive(nc); - nexthop_chain_verify_iter(nc); + nexthop_chain_add_recursive(nc); + nexthop_chain_verify_iter(nc); - nexthop_chain_add_recursive(nc); - nexthop_chain_verify_iter(nc); + nexthop_chain_add_recursive(nc); + nexthop_chain_verify_iter(nc); - nexthop_chain_add_recursive_level(nc); - nexthop_chain_verify_iter(nc); + nexthop_chain_add_recursive_level(nc); + nexthop_chain_verify_iter(nc); - nexthop_chain_add_recursive(nc); - nexthop_chain_verify_iter(nc); + nexthop_chain_add_recursive(nc); + nexthop_chain_verify_iter(nc); - nexthop_chain_add_recursive(nc); - nexthop_chain_verify_iter(nc); + nexthop_chain_add_recursive(nc); + nexthop_chain_verify_iter(nc); - nexthop_chain_add_top(nc); - nexthop_chain_verify_iter(nc); + nexthop_chain_add_top(nc); + nexthop_chain_verify_iter(nc); - nexthop_chain_free(nc); + nexthop_chain_free(nc); } /* This test run builds numerous random * nexthop chain configurations and verifies * that the iterator correctly progresses * through each. */ -static void -test_run_prng(void) +static void test_run_prng(void) { - struct nexthop_chain *nc; - struct prng *prng; - int i; - - nc = nexthop_chain_new(); - prng = prng_new(0); - - for (i = 0; i < 1000000; i++) - { - switch (prng_rand(prng) % 10) - { - case 0: - nexthop_chain_clear(nc); - break; - case 1: - case 2: - case 3: - case 4: - case 5: - nexthop_chain_add_top(nc); - break; - case 6: - case 7: - case 8: - if (nc->current_top) - nexthop_chain_add_recursive(nc); - break; - case 9: - if (nc->current_top) - nexthop_chain_add_recursive_level(nc); - break; - } - nexthop_chain_verify_iter(nc); - } - nexthop_chain_free(nc); - prng_free(prng); + struct nexthop_chain *nc; + struct prng *prng; + int i; + + nc = nexthop_chain_new(); + prng = prng_new(0); + + for (i = 0; i < 1000000; i++) { + switch (prng_rand(prng) % 10) { + case 0: + nexthop_chain_clear(nc); + break; + case 1: + case 2: + case 3: + case 4: + case 5: + nexthop_chain_add_top(nc); + break; + case 6: + case 7: + case 8: + if (nc->current_top) + nexthop_chain_add_recursive(nc); + break; + case 9: + if (nc->current_top) + nexthop_chain_add_recursive_level(nc); + break; + } + nexthop_chain_verify_iter(nc); + } + nexthop_chain_free(nc); + prng_free(prng); } int main(int argc, char **argv) { - if (argc >= 2 && !strcmp("-v", argv[1])) - verbose = 1; - test_run_first(); - printf("Simple test passed.\n"); - test_run_prng(); - printf("PRNG test passed.\n"); + if (argc >= 2 && !strcmp("-v", argv[1])) + verbose = 1; + test_run_first(); + printf("Simple test passed.\n"); + test_run_prng(); + printf("PRNG test passed.\n"); } diff --git a/tests/lib/test_privs.c b/tests/lib/test_privs.c index 26f3b5f69..c2cb5c2ea 100644 --- a/tests/lib/test_privs.c +++ b/tests/lib/test_privs.c @@ -26,127 +26,115 @@ #include "memory.h" #include "memory_vty.h" -zebra_capabilities_t _caps_p [] = -{ - ZCAP_NET_RAW, - ZCAP_BIND, - ZCAP_NET_ADMIN, - ZCAP_DAC_OVERRIDE, +zebra_capabilities_t _caps_p[] = { + ZCAP_NET_RAW, ZCAP_BIND, ZCAP_NET_ADMIN, ZCAP_DAC_OVERRIDE, }; -struct zebra_privs_t test_privs = -{ +struct zebra_privs_t test_privs = { #if defined(FRR_USER) && defined(FRR_GROUP) - .user = FRR_USER, - .group = FRR_GROUP, + .user = FRR_USER, + .group = FRR_GROUP, #endif #if defined(VTY_GROUP) - .vty_group = VTY_GROUP, + .vty_group = VTY_GROUP, #endif - .caps_p = _caps_p, - .cap_num_p = sizeof(_caps_p)/sizeof(_caps_p[0]), - .cap_num_i = 0 -}; + .caps_p = _caps_p, + .cap_num_p = sizeof(_caps_p) / sizeof(_caps_p[0]), + .cap_num_i = 0}; -struct option longopts[] = -{ - { "help", no_argument, NULL, 'h'}, - { "user", required_argument, NULL, 'u'}, - { "group", required_argument, NULL, 'g'}, - { 0 } -}; +struct option longopts[] = {{"help", no_argument, NULL, 'h'}, + {"user", required_argument, NULL, 'u'}, + {"group", required_argument, NULL, 'g'}, + {0}}; /* Help information display. */ -static void -usage (char *progname, int status) +static void usage(char *progname, int status) { - if (status != 0) - fprintf (stderr, "Try `%s --help' for more information.\n", progname); - else - { - printf ("Usage : %s [OPTION...]\n\ + if (status != 0) + fprintf(stderr, "Try `%s --help' for more information.\n", + progname); + else { + printf("Usage : %s [OPTION...]\n\ Daemon which does 'slow' things.\n\n\ -u, --user User to run as\n\ -g, --group Group to run as\n\ -h, --help Display this help and exit\n\ \n\ -Report bugs to %s\n", progname, FRR_BUG_ADDRESS); - } - exit (status); +Report bugs to %s\n", + progname, FRR_BUG_ADDRESS); + } + exit(status); } struct thread_master *master; /* main routine. */ -int -main (int argc, char **argv) +int main(int argc, char **argv) { - char *p; - char *progname; - struct zprivs_ids_t ids; - - /* Set umask before anything for security */ - umask (0027); - - /* get program name */ - progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]); - - while (1) - { - int opt; - - opt = getopt_long (argc, argv, "hu:g:", longopts, 0); - - if (opt == EOF) - break; - - switch (opt) - { - case 0: - break; - case 'u': - test_privs.user = optarg; - break; - case 'g': - test_privs.group = optarg; - break; - case 'h': - usage (progname, 0); - break; - default: - usage (progname, 1); - break; + char *p; + char *progname; + struct zprivs_ids_t ids; + + /* Set umask before anything for security */ + umask(0027); + + /* get program name */ + progname = ((p = strrchr(argv[0], '/')) ? ++p : argv[0]); + + while (1) { + int opt; + + opt = getopt_long(argc, argv, "hu:g:", longopts, 0); + + if (opt == EOF) + break; + + switch (opt) { + case 0: + break; + case 'u': + test_privs.user = optarg; + break; + case 'g': + test_privs.group = optarg; + break; + case 'h': + usage(progname, 0); + break; + default: + usage(progname, 1); + break; + } } - } - - /* Library inits. */ - memory_init (); - zprivs_init (&test_privs); - -#define PRIV_STATE() \ - ((test_privs.current_state() == ZPRIVS_RAISED) ? "Raised" : "Lowered") - - printf ("%s\n", PRIV_STATE()); - test_privs.change(ZPRIVS_RAISE); - - printf ("%s\n", PRIV_STATE()); - test_privs.change(ZPRIVS_LOWER); - - printf ("%s\n", PRIV_STATE()); - zprivs_get_ids (&ids); - - /* terminate privileges */ - zprivs_terminate(&test_privs); - - /* but these should continue to work... */ - printf ("%s\n", PRIV_STATE()); - test_privs.change(ZPRIVS_RAISE); - - printf ("%s\n", PRIV_STATE()); - test_privs.change(ZPRIVS_LOWER); - - printf ("%s\n", PRIV_STATE()); - zprivs_get_ids (&ids); - - printf ("terminating\n"); - return 0; + + /* Library inits. */ + memory_init(); + zprivs_init(&test_privs); + +#define PRIV_STATE() \ + ((test_privs.current_state() == ZPRIVS_RAISED) ? "Raised" : "Lowered") + + printf("%s\n", PRIV_STATE()); + test_privs.change(ZPRIVS_RAISE); + + printf("%s\n", PRIV_STATE()); + test_privs.change(ZPRIVS_LOWER); + + printf("%s\n", PRIV_STATE()); + zprivs_get_ids(&ids); + + /* terminate privileges */ + zprivs_terminate(&test_privs); + + /* but these should continue to work... */ + printf("%s\n", PRIV_STATE()); + test_privs.change(ZPRIVS_RAISE); + + printf("%s\n", PRIV_STATE()); + test_privs.change(ZPRIVS_LOWER); + + printf("%s\n", PRIV_STATE()); + zprivs_get_ids(&ids); + + printf("terminating\n"); + return 0; } diff --git a/tests/lib/test_segv.c b/tests/lib/test_segv.c index 14384f432..3c9b57f04 100644 --- a/tests/lib/test_segv.c +++ b/tests/lib/test_segv.c @@ -28,32 +28,29 @@ #include "lib/log.h" #include "lib/memory.h" -struct quagga_signal_t sigs[] = -{ -}; +struct quagga_signal_t sigs[] = {}; struct thread_master *master; -static int -threadfunc (struct thread *thread) +static int threadfunc(struct thread *thread) { - int *null = NULL; - *null += 1; - return 0; + int *null = NULL; + *null += 1; + return 0; } -int -main (void) +int main(void) { - master = thread_master_create(NULL); - signal_init (master, array_size(sigs), sigs); + master = thread_master_create(NULL); + signal_init(master, array_size(sigs), sigs); - openzlog("testsegv", "NONE", 0, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON); - zlog_set_level(ZLOG_DEST_SYSLOG, ZLOG_DISABLED); - zlog_set_level(ZLOG_DEST_STDOUT, LOG_DEBUG); - zlog_set_level(ZLOG_DEST_MONITOR, ZLOG_DISABLED); + openzlog("testsegv", "NONE", 0, LOG_CONS | LOG_NDELAY | LOG_PID, + LOG_DAEMON); + zlog_set_level(ZLOG_DEST_SYSLOG, ZLOG_DISABLED); + zlog_set_level(ZLOG_DEST_STDOUT, LOG_DEBUG); + zlog_set_level(ZLOG_DEST_MONITOR, ZLOG_DISABLED); - thread_execute (master, threadfunc, 0, 0); + thread_execute(master, threadfunc, 0, 0); - exit (0); + exit(0); } diff --git a/tests/lib/test_sig.c b/tests/lib/test_sig.c index 1ffc6692f..cf63a3d04 100644 --- a/tests/lib/test_sig.c +++ b/tests/lib/test_sig.c @@ -1,4 +1,4 @@ -/* +/* * This file is part of Quagga. * * Quagga is free software; you can redistribute it and/or modify it @@ -21,56 +21,50 @@ #include "lib/log.h" #include "lib/memory.h" -static void -sighup (void) +static void sighup(void) { - printf ("processed hup\n"); + printf("processed hup\n"); } -static void -sigusr1 (void) +static void sigusr1(void) { - printf ("processed usr1\n"); + printf("processed usr1\n"); } -static void -sigusr2 (void) +static void sigusr2(void) { - printf ("processed usr2\n"); + printf("processed usr2\n"); } -struct quagga_signal_t sigs[] = -{ - { - .signal = SIGHUP, - .handler = &sighup, - }, - { - .signal = SIGUSR1, - .handler = &sigusr1, - }, - { - .signal = SIGUSR2, - .handler = &sigusr2, - } -}; +struct quagga_signal_t sigs[] = {{ + .signal = SIGHUP, + .handler = &sighup, + }, + { + .signal = SIGUSR1, + .handler = &sigusr1, + }, + { + .signal = SIGUSR2, + .handler = &sigusr2, + }}; struct thread_master *master; struct thread t; -int -main (void) +int main(void) { - master = thread_master_create(NULL); - signal_init (master, array_size(sigs), sigs); + master = thread_master_create(NULL); + signal_init(master, array_size(sigs), sigs); - openzlog("testsig", "NONE", 0, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON); - zlog_set_level(ZLOG_DEST_SYSLOG, ZLOG_DISABLED); - zlog_set_level(ZLOG_DEST_STDOUT, LOG_DEBUG); - zlog_set_level(ZLOG_DEST_MONITOR, ZLOG_DISABLED); + openzlog("testsig", "NONE", 0, LOG_CONS | LOG_NDELAY | LOG_PID, + LOG_DAEMON); + zlog_set_level(ZLOG_DEST_SYSLOG, ZLOG_DISABLED); + zlog_set_level(ZLOG_DEST_STDOUT, LOG_DEBUG); + zlog_set_level(ZLOG_DEST_MONITOR, ZLOG_DISABLED); - while (thread_fetch (master, &t)) - thread_call (&t); + while (thread_fetch(master, &t)) + thread_call(&t); - exit (0); + exit(0); } diff --git a/tests/lib/test_srcdest_table.c b/tests/lib/test_srcdest_table.c index 111b11a1e..408f4e058 100644 --- a/tests/lib/test_srcdest_table.c +++ b/tests/lib/test_srcdest_table.c @@ -47,416 +47,397 @@ struct thread_master *master; /* This structure is copied from lib/srcdest_table.c to which it is * private as far as other parts of Quagga are concerned. */ -struct srcdest_rnode -{ - /* must be first in structure for casting to/from route_node */ - ROUTE_NODE_FIELDS; +struct srcdest_rnode { + /* must be first in structure for casting to/from route_node */ + ROUTE_NODE_FIELDS; - struct route_table *src_table; + struct route_table *src_table; }; -struct test_state -{ - struct route_table *table; - struct hash *log; +struct test_state { + struct route_table *table; + struct hash *log; }; -static char * -format_srcdest(const struct prefix_ipv6 *dst_p, - const struct prefix_ipv6 *src_p) +static char *format_srcdest(const struct prefix_ipv6 *dst_p, + const struct prefix_ipv6 *src_p) { - char dst_str[BUFSIZ]; - char src_str[BUFSIZ]; - char *rv; - int ec; - - prefix2str((const struct prefix*)dst_p, dst_str, sizeof(dst_str)); - if (src_p && src_p->prefixlen) - prefix2str((const struct prefix*)src_p, src_str, sizeof(src_str)); - else - src_str[0] = '\0'; - - ec = asprintf(&rv, "%s%s%s", dst_str, - (src_str[0] != '\0') ? " from " : "", - src_str); - - assert(ec > 0); - return rv; + char dst_str[BUFSIZ]; + char src_str[BUFSIZ]; + char *rv; + int ec; + + prefix2str((const struct prefix *)dst_p, dst_str, sizeof(dst_str)); + if (src_p && src_p->prefixlen) + prefix2str((const struct prefix *)src_p, src_str, + sizeof(src_str)); + else + src_str[0] = '\0'; + + ec = asprintf(&rv, "%s%s%s", dst_str, + (src_str[0] != '\0') ? " from " : "", src_str); + + assert(ec > 0); + return rv; } static unsigned int log_key(void *data) { - struct prefix *hash_entry = data; - struct prefix_ipv6 *dst_p = (struct prefix_ipv6*) &hash_entry[0]; - struct prefix_ipv6 *src_p = (struct prefix_ipv6*) &hash_entry[1]; - unsigned int hash = 0; - unsigned int i; - - hash = (hash * 33) ^ (unsigned int)dst_p->prefixlen; - for (i = 0; i < 4; i++) - hash = (hash * 33) ^ (unsigned int)dst_p->prefix.s6_addr32[i]; - - hash = (hash * 33) ^ (unsigned int)src_p->prefixlen; - if (src_p->prefixlen) - for (i = 0; i < 4; i++) - hash = (hash * 33) ^ (unsigned int)src_p->prefix.s6_addr32[i]; - - return hash; + struct prefix *hash_entry = data; + struct prefix_ipv6 *dst_p = (struct prefix_ipv6 *)&hash_entry[0]; + struct prefix_ipv6 *src_p = (struct prefix_ipv6 *)&hash_entry[1]; + unsigned int hash = 0; + unsigned int i; + + hash = (hash * 33) ^ (unsigned int)dst_p->prefixlen; + for (i = 0; i < 4; i++) + hash = (hash * 33) ^ (unsigned int)dst_p->prefix.s6_addr32[i]; + + hash = (hash * 33) ^ (unsigned int)src_p->prefixlen; + if (src_p->prefixlen) + for (i = 0; i < 4; i++) + hash = (hash * 33) + ^ (unsigned int)src_p->prefix.s6_addr32[i]; + + return hash; } -static int -log_cmp(const void *a, const void *b) +static int log_cmp(const void *a, const void *b) { - if (a == NULL && b != NULL) - return 0; - if (b == NULL && a != NULL) - return 0; + if (a == NULL && b != NULL) + return 0; + if (b == NULL && a != NULL) + return 0; - return !memcmp(a, b, 2 * sizeof(struct prefix)); + return !memcmp(a, b, 2 * sizeof(struct prefix)); } -static void -log_free(void *data) +static void log_free(void *data) { - XFREE(MTYPE_TMP, data); + XFREE(MTYPE_TMP, data); } -static void * -log_alloc(void *data) +static void *log_alloc(void *data) { - void *rv = XMALLOC(MTYPE_TMP, 2 * sizeof(struct prefix)); - memcpy(rv, data, 2 * sizeof(struct prefix)); - return rv; + void *rv = XMALLOC(MTYPE_TMP, 2 * sizeof(struct prefix)); + memcpy(rv, data, 2 * sizeof(struct prefix)); + return rv; } -static struct test_state * -test_state_new(void) +static struct test_state *test_state_new(void) { - struct test_state *rv; + struct test_state *rv; - rv = XCALLOC(MTYPE_TMP, sizeof(*rv)); - assert(rv); + rv = XCALLOC(MTYPE_TMP, sizeof(*rv)); + assert(rv); - rv->table = srcdest_table_init(); - assert(rv->table); + rv->table = srcdest_table_init(); + assert(rv->table); - rv->log = hash_create(log_key, log_cmp, NULL); - return rv; + rv->log = hash_create(log_key, log_cmp, NULL); + return rv; } -static void -test_state_free(struct test_state *test) +static void test_state_free(struct test_state *test) { - route_table_finish(test->table); - hash_clean(test->log, log_free); - hash_free(test->log); - XFREE(MTYPE_TMP, test); + route_table_finish(test->table); + hash_clean(test->log, log_free); + hash_free(test->log); + XFREE(MTYPE_TMP, test); } -static void -test_state_add_route(struct test_state *test, - struct prefix_ipv6 *dst_p, - struct prefix_ipv6 *src_p) +static void test_state_add_route(struct test_state *test, + struct prefix_ipv6 *dst_p, + struct prefix_ipv6 *src_p) { - struct route_node *rn = srcdest_rnode_get( - test->table, (struct prefix*)dst_p, src_p - ); - struct prefix hash_entry[2]; - - memset(hash_entry, 0, sizeof(hash_entry)); - memcpy(&hash_entry[0], dst_p, sizeof(*dst_p)); - memcpy(&hash_entry[1], src_p, sizeof(*src_p)); - - if (rn->info) { - route_unlock_node(rn); - assert(hash_lookup(test->log, hash_entry) != NULL); - return; - } else { - assert(hash_lookup(test->log, hash_entry) == NULL); - } - - rn->info = (void*) 0xdeadbeef; - hash_get(test->log, hash_entry, log_alloc); + struct route_node *rn = + srcdest_rnode_get(test->table, (struct prefix *)dst_p, src_p); + struct prefix hash_entry[2]; + + memset(hash_entry, 0, sizeof(hash_entry)); + memcpy(&hash_entry[0], dst_p, sizeof(*dst_p)); + memcpy(&hash_entry[1], src_p, sizeof(*src_p)); + + if (rn->info) { + route_unlock_node(rn); + assert(hash_lookup(test->log, hash_entry) != NULL); + return; + } else { + assert(hash_lookup(test->log, hash_entry) == NULL); + } + + rn->info = (void *)0xdeadbeef; + hash_get(test->log, hash_entry, log_alloc); }; -static void -test_state_del_route(struct test_state *test, - struct prefix_ipv6 *dst_p, - struct prefix_ipv6 *src_p) +static void test_state_del_route(struct test_state *test, + struct prefix_ipv6 *dst_p, + struct prefix_ipv6 *src_p) { - struct route_node *rn = srcdest_rnode_lookup( - test->table, (struct prefix*)dst_p, src_p - ); - struct prefix hash_entry[2]; - - memset(hash_entry, 0, sizeof(hash_entry)); - memcpy(&hash_entry[0], dst_p, sizeof(*dst_p)); - memcpy(&hash_entry[1], src_p, sizeof(*src_p)); - - if (!rn) { - assert(!hash_lookup(test->log, hash_entry)); - return; - } - - assert(rn->info == (void*)0xdeadbeef); - rn->info = NULL; - route_unlock_node(rn); - route_unlock_node(rn); - - struct prefix *hash_entry_intern = hash_release(test->log, hash_entry); - assert(hash_entry_intern != NULL); - XFREE(MTYPE_TMP, hash_entry_intern); + struct route_node *rn = srcdest_rnode_lookup( + test->table, (struct prefix *)dst_p, src_p); + struct prefix hash_entry[2]; + + memset(hash_entry, 0, sizeof(hash_entry)); + memcpy(&hash_entry[0], dst_p, sizeof(*dst_p)); + memcpy(&hash_entry[1], src_p, sizeof(*src_p)); + + if (!rn) { + assert(!hash_lookup(test->log, hash_entry)); + return; + } + + assert(rn->info == (void *)0xdeadbeef); + rn->info = NULL; + route_unlock_node(rn); + route_unlock_node(rn); + + struct prefix *hash_entry_intern = hash_release(test->log, hash_entry); + assert(hash_entry_intern != NULL); + XFREE(MTYPE_TMP, hash_entry_intern); } -static void -verify_log(struct hash_backet* backet, void *arg) +static void verify_log(struct hash_backet *backet, void *arg) { - struct test_state *test = arg; - struct prefix *hash_entry = backet->data; - struct prefix *dst_p = &hash_entry[0]; - struct prefix_ipv6 *src_p = (struct prefix_ipv6*)&hash_entry[1]; - struct route_node *rn = srcdest_rnode_lookup(test->table, dst_p, src_p); + struct test_state *test = arg; + struct prefix *hash_entry = backet->data; + struct prefix *dst_p = &hash_entry[0]; + struct prefix_ipv6 *src_p = (struct prefix_ipv6 *)&hash_entry[1]; + struct route_node *rn = srcdest_rnode_lookup(test->table, dst_p, src_p); - assert(rn); - assert(rn->info == (void*)0xdeadbeef); + assert(rn); + assert(rn->info == (void *)0xdeadbeef); - route_unlock_node(rn); + route_unlock_node(rn); } -static void -dump_log(struct hash_backet* backet, void *arg) +static void dump_log(struct hash_backet *backet, void *arg) { - struct prefix *hash_entry = backet->data; - struct prefix_ipv6 *dst_p = (struct prefix_ipv6*)&hash_entry[0]; - struct prefix_ipv6 *src_p = (struct prefix_ipv6*)&hash_entry[1]; - char *route_id = format_srcdest(dst_p, src_p); + struct prefix *hash_entry = backet->data; + struct prefix_ipv6 *dst_p = (struct prefix_ipv6 *)&hash_entry[0]; + struct prefix_ipv6 *src_p = (struct prefix_ipv6 *)&hash_entry[1]; + char *route_id = format_srcdest(dst_p, src_p); - fprintf(stderr, " %s\n", route_id); - free(route_id); + fprintf(stderr, " %s\n", route_id); + free(route_id); } -static void -test_dump(struct test_state *test) +static void test_dump(struct test_state *test) { - fprintf(stderr, "Contents of hash table:\n"); - hash_iterate(test->log, dump_log, test); - fprintf(stderr, "\n"); + fprintf(stderr, "Contents of hash table:\n"); + hash_iterate(test->log, dump_log, test); + fprintf(stderr, "\n"); } -static void -test_failed(struct test_state *test, const char *message, - struct prefix_ipv6 *dst_p, struct prefix_ipv6 *src_p) +static void test_failed(struct test_state *test, const char *message, + struct prefix_ipv6 *dst_p, struct prefix_ipv6 *src_p) { - char *route_id = format_srcdest(dst_p, src_p); + char *route_id = format_srcdest(dst_p, src_p); - fprintf(stderr, "Test failed. Error: %s\n", message); - fprintf(stderr, "Route in question: %s\n", route_id); - free(route_id); + fprintf(stderr, "Test failed. Error: %s\n", message); + fprintf(stderr, "Route in question: %s\n", route_id); + free(route_id); - test_dump(test); - assert(3 == 4); + test_dump(test); + assert(3 == 4); } -static void -test_state_verify(struct test_state *test) +static void test_state_verify(struct test_state *test) { - struct route_node *rn; - struct prefix hash_entry[2]; - - memset(hash_entry, 0, sizeof(hash_entry)); - - /* Verify that there are no elements in the table which have never - * been added */ - for (rn = route_top(test->table); rn; rn = srcdest_route_next(rn)) - { - struct prefix_ipv6 *dst_p, *src_p; - - /* While we are iterating, we hold a lock on the current route_node, - * so all the lock counts we check for take that into account; in idle - * state all the numbers will be exactly one less. - * - * Also this makes quite some assumptions based on the current - * implementation details of route_table and srcdest_table - another - * valid implementation might trigger assertions here. - */ - - if (rnode_is_dstnode(rn)) - { - struct srcdest_rnode *srn = (struct srcdest_rnode *)rn; - unsigned int expected_lock = 1; /* We are in the loop */ - - if (rn->info != NULL) /* The route node is not internal */ - expected_lock++; - if (srn->src_table != NULL) /* There's a source table associated with rn */ - expected_lock++; - - if (rn->lock != expected_lock) - test_failed(test, "Dest rnode lock count doesn't match expected count!", - (struct prefix_ipv6*)&rn->p, NULL); - } - else - { - unsigned int expected_lock = 1; /* We are in the loop */ - - if (rn->info != NULL) /* The route node is not internal */ - expected_lock++; - - if (rn->lock != expected_lock) - { - struct prefix_ipv6 *dst_p, *src_p; - srcdest_rnode_prefixes(rn, (struct prefix**)&dst_p, - (struct prefix**)&src_p); - - test_failed(test, "Src rnode lock count doesn't match expected count!", - dst_p, src_p); - } - } - - if (!rn->info) - continue; - - assert(rn->info == (void*)0xdeadbeef); - - srcdest_rnode_prefixes(rn, (struct prefix**)&dst_p, (struct prefix**)&src_p); - memcpy(&hash_entry[0], dst_p, sizeof(*dst_p)); - if (src_p) - memcpy(&hash_entry[1], src_p, sizeof(*src_p)); - else - memset(&hash_entry[1], 0, sizeof(hash_entry[1])); - - if (hash_lookup(test->log, hash_entry) == NULL) - test_failed(test, "Route is missing in hash", dst_p, src_p); - } - - /* Verify that all added elements are still in the table */ - hash_iterate(test->log, verify_log, test); + struct route_node *rn; + struct prefix hash_entry[2]; + + memset(hash_entry, 0, sizeof(hash_entry)); + + /* Verify that there are no elements in the table which have never + * been added */ + for (rn = route_top(test->table); rn; rn = srcdest_route_next(rn)) { + struct prefix_ipv6 *dst_p, *src_p; + + /* While we are iterating, we hold a lock on the current + * route_node, + * so all the lock counts we check for take that into account; + * in idle + * state all the numbers will be exactly one less. + * + * Also this makes quite some assumptions based on the current + * implementation details of route_table and srcdest_table - + * another + * valid implementation might trigger assertions here. + */ + + if (rnode_is_dstnode(rn)) { + struct srcdest_rnode *srn = (struct srcdest_rnode *)rn; + unsigned int expected_lock = 1; /* We are in the loop */ + + if (rn->info + != NULL) /* The route node is not internal */ + expected_lock++; + if (srn->src_table != NULL) /* There's a source table + associated with rn */ + expected_lock++; + + if (rn->lock != expected_lock) + test_failed( + test, + "Dest rnode lock count doesn't match expected count!", + (struct prefix_ipv6 *)&rn->p, NULL); + } else { + unsigned int expected_lock = 1; /* We are in the loop */ + + if (rn->info + != NULL) /* The route node is not internal */ + expected_lock++; + + if (rn->lock != expected_lock) { + struct prefix_ipv6 *dst_p, *src_p; + srcdest_rnode_prefixes( + rn, (struct prefix **)&dst_p, + (struct prefix **)&src_p); + + test_failed( + test, + "Src rnode lock count doesn't match expected count!", + dst_p, src_p); + } + } + + if (!rn->info) + continue; + + assert(rn->info == (void *)0xdeadbeef); + + srcdest_rnode_prefixes(rn, (struct prefix **)&dst_p, + (struct prefix **)&src_p); + memcpy(&hash_entry[0], dst_p, sizeof(*dst_p)); + if (src_p) + memcpy(&hash_entry[1], src_p, sizeof(*src_p)); + else + memset(&hash_entry[1], 0, sizeof(hash_entry[1])); + + if (hash_lookup(test->log, hash_entry) == NULL) + test_failed(test, "Route is missing in hash", dst_p, + src_p); + } + + /* Verify that all added elements are still in the table */ + hash_iterate(test->log, verify_log, test); } -static void -get_rand_prefix(struct prng *prng, struct prefix_ipv6 *p) +static void get_rand_prefix(struct prng *prng, struct prefix_ipv6 *p) { - int i; + int i; - memset(p, 0, sizeof(*p)); + memset(p, 0, sizeof(*p)); - for (i = 0; i < 4; i++) - p->prefix.s6_addr32[i] = prng_rand(prng); - p->prefixlen = prng_rand(prng) % 129; - p->family = AF_INET6; + for (i = 0; i < 4; i++) + p->prefix.s6_addr32[i] = prng_rand(prng); + p->prefixlen = prng_rand(prng) % 129; + p->family = AF_INET6; - apply_mask((struct prefix*)p); + apply_mask((struct prefix *)p); } -static void -get_rand_prefix_pair(struct prng *prng, struct prefix_ipv6 *dst_p, - struct prefix_ipv6 *src_p) +static void get_rand_prefix_pair(struct prng *prng, struct prefix_ipv6 *dst_p, + struct prefix_ipv6 *src_p) { - get_rand_prefix(prng, dst_p); - if ((prng_rand(prng) % 4) == 0) - { - get_rand_prefix(prng, src_p); - if (src_p->prefixlen) - return; - } - - memset(src_p, 0, sizeof(*src_p)); + get_rand_prefix(prng, dst_p); + if ((prng_rand(prng) % 4) == 0) { + get_rand_prefix(prng, src_p); + if (src_p->prefixlen) + return; + } + + memset(src_p, 0, sizeof(*src_p)); } -static void -test_state_add_rand_route(struct test_state *test, - struct prng *prng) +static void test_state_add_rand_route(struct test_state *test, + struct prng *prng) { - struct prefix_ipv6 dst_p, src_p; + struct prefix_ipv6 dst_p, src_p; - get_rand_prefix_pair(prng, &dst_p, &src_p); - test_state_add_route(test, &dst_p, &src_p); + get_rand_prefix_pair(prng, &dst_p, &src_p); + test_state_add_route(test, &dst_p, &src_p); } -static void -test_state_del_rand_route(struct test_state *test, - struct prng *prng) +static void test_state_del_rand_route(struct test_state *test, + struct prng *prng) { - struct prefix_ipv6 dst_p, src_p; + struct prefix_ipv6 dst_p, src_p; - get_rand_prefix_pair(prng, &dst_p, &src_p); - test_state_del_route(test, &dst_p, &src_p); + get_rand_prefix_pair(prng, &dst_p, &src_p); + test_state_del_route(test, &dst_p, &src_p); } -static void -test_state_del_one_route(struct test_state *test, - struct prng *prng) +static void test_state_del_one_route(struct test_state *test, struct prng *prng) { - unsigned int which_route; - - if (test->log->count == 0) - return; - - which_route = prng_rand(prng) % test->log->count; - - struct route_node *rn; - struct prefix *dst_p, *src_p; - struct prefix_ipv6 dst6_p, src6_p; - - for (rn = route_top(test->table); rn; rn = srcdest_route_next(rn)) - { - if (!rn->info) - continue; - if (!which_route) { - route_unlock_node(rn); - break; - } - which_route--; - } - - assert(rn); - srcdest_rnode_prefixes(rn, &dst_p, &src_p); - memcpy(&dst6_p, dst_p, sizeof(dst6_p)); - if (src_p) - memcpy(&src6_p, src_p, sizeof(src6_p)); - else - memset(&src6_p, 0, sizeof(src6_p)); - - test_state_del_route(test, &dst6_p, &src6_p); + unsigned int which_route; + + if (test->log->count == 0) + return; + + which_route = prng_rand(prng) % test->log->count; + + struct route_node *rn; + struct prefix *dst_p, *src_p; + struct prefix_ipv6 dst6_p, src6_p; + + for (rn = route_top(test->table); rn; rn = srcdest_route_next(rn)) { + if (!rn->info) + continue; + if (!which_route) { + route_unlock_node(rn); + break; + } + which_route--; + } + + assert(rn); + srcdest_rnode_prefixes(rn, &dst_p, &src_p); + memcpy(&dst6_p, dst_p, sizeof(dst6_p)); + if (src_p) + memcpy(&src6_p, src_p, sizeof(src6_p)); + else + memset(&src6_p, 0, sizeof(src6_p)); + + test_state_del_route(test, &dst6_p, &src6_p); } -static void -run_prng_test(void) +static void run_prng_test(void) { - struct test_state *test = test_state_new(); - struct prng *prng = prng_new(0); - size_t i; - - for (i = 0; i < 1000; i++) - { - switch (prng_rand(prng) % 10) - { - case 0: - case 1: - case 2: - case 3: - case 4: - test_state_add_rand_route(test, prng); - break; - case 5: - case 6: - case 7: - test_state_del_one_route(test, prng); - break; - case 8: - case 9: - test_state_del_rand_route(test, prng); - break; - } - test_state_verify(test); - } - - prng_free(prng); - test_state_free(test); + struct test_state *test = test_state_new(); + struct prng *prng = prng_new(0); + size_t i; + + for (i = 0; i < 1000; i++) { + switch (prng_rand(prng) % 10) { + case 0: + case 1: + case 2: + case 3: + case 4: + test_state_add_rand_route(test, prng); + break; + case 5: + case 6: + case 7: + test_state_del_one_route(test, prng); + break; + case 8: + case 9: + test_state_del_rand_route(test, prng); + break; + } + test_state_verify(test); + } + + prng_free(prng); + test_state_free(test); } int main(int argc, char *argv[]) { - run_prng_test(); - printf("PRNG Test successful.\n"); - return 0; + run_prng_test(); + printf("PRNG Test successful.\n"); + return 0; } diff --git a/tests/lib/test_stream.c b/tests/lib/test_stream.c index 596b73afc..5dc751a1b 100644 --- a/tests/lib/test_stream.c +++ b/tests/lib/test_stream.c @@ -26,50 +26,45 @@ static unsigned long long ham = 0xdeadbeefdeadbeef; struct thread_master *master; -static void -print_stream (struct stream *s) +static void print_stream(struct stream *s) { - size_t getp = stream_get_getp (s); - - printf ("endp: %zu, readable: %zu, writeable: %zu\n", - stream_get_endp (s), - STREAM_READABLE (s), - STREAM_WRITEABLE (s)); - - while (STREAM_READABLE (s)) - { - printf ("0x%x ", *stream_pnt (s)); - stream_forward_getp (s, 1); - } - - printf ("\n"); - - /* put getp back to where it was */ - stream_set_getp (s, getp); + size_t getp = stream_get_getp(s); + + printf("endp: %zu, readable: %zu, writeable: %zu\n", stream_get_endp(s), + STREAM_READABLE(s), STREAM_WRITEABLE(s)); + + while (STREAM_READABLE(s)) { + printf("0x%x ", *stream_pnt(s)); + stream_forward_getp(s, 1); + } + + printf("\n"); + + /* put getp back to where it was */ + stream_set_getp(s, getp); } -int -main (void) +int main(void) { - struct stream *s; - - s = stream_new (1024); - - stream_putc (s, ham); - stream_putw (s, ham); - stream_putl (s, ham); - stream_putq (s, ham); - - print_stream (s); - - stream_resize (s, stream_get_endp (s)); - - print_stream (s); - - printf ("c: 0x%hhx\n", stream_getc (s)); - printf ("w: 0x%hx\n", stream_getw (s)); - printf ("l: 0x%x\n", stream_getl (s)); - printf ("q: 0x%" PRIx64 "\n", stream_getq (s)); - - return 0; + struct stream *s; + + s = stream_new(1024); + + stream_putc(s, ham); + stream_putw(s, ham); + stream_putl(s, ham); + stream_putq(s, ham); + + print_stream(s); + + stream_resize(s, stream_get_endp(s)); + + print_stream(s); + + printf("c: 0x%hhx\n", stream_getc(s)); + printf("w: 0x%hx\n", stream_getw(s)); + printf("l: 0x%x\n", stream_getl(s)); + printf("q: 0x%" PRIx64 "\n", stream_getq(s)); + + return 0; } diff --git a/tests/lib/test_table.c b/tests/lib/test_table.c index 8c98bc948..2c2a01053 100644 --- a/tests/lib/test_table.c +++ b/tests/lib/test_table.c @@ -29,14 +29,13 @@ * * Information that is kept for each node in the radix tree. */ -typedef struct test_node_t_ -{ +typedef struct test_node_t_ { - /* - * Human readable representation of the string. Allocated using - * malloc()/dup(). - */ - char *prefix_str; + /* + * Human readable representation of the string. Allocated using + * malloc()/dup(). + */ + char *prefix_str; } test_node_t; struct thread_master *master; @@ -46,32 +45,29 @@ struct thread_master *master; * * Add the given prefix (passed in as a string) to the given table. */ -static void -add_node (struct route_table *table, const char *prefix_str) +static void add_node(struct route_table *table, const char *prefix_str) { - struct prefix_ipv4 p; - test_node_t *node; - struct route_node *rn; - - assert (prefix_str); - - if (str2prefix_ipv4 (prefix_str, &p) <= 0) - { - assert (0); - } - - rn = route_node_get (table, (struct prefix *) &p); - if (rn->info) - { - assert (0); - return; - } - - node = malloc (sizeof (test_node_t)); - assert (node); - node->prefix_str = strdup (prefix_str); - assert (node->prefix_str); - rn->info = node; + struct prefix_ipv4 p; + test_node_t *node; + struct route_node *rn; + + assert(prefix_str); + + if (str2prefix_ipv4(prefix_str, &p) <= 0) { + assert(0); + } + + rn = route_node_get(table, (struct prefix *)&p); + if (rn->info) { + assert(0); + return; + } + + node = malloc(sizeof(test_node_t)); + assert(node); + node->prefix_str = strdup(prefix_str); + assert(node->prefix_str); + rn->info = node; } /* @@ -82,22 +78,20 @@ add_node (struct route_table *table, const char *prefix_str) * The arguments must be prefixes in string format, with a NULL as the * last argument. */ -static void -add_nodes (struct route_table *table, ...) +static void add_nodes(struct route_table *table, ...) { - va_list arglist; - char *prefix; + va_list arglist; + char *prefix; - va_start (arglist, table); + va_start(arglist, table); - prefix = va_arg (arglist, char *); - while (prefix) - { - add_node (table, prefix); - prefix = va_arg (arglist, char *); - } + prefix = va_arg(arglist, char *); + while (prefix) { + add_node(table, prefix); + prefix = va_arg(arglist, char *); + } - va_end (arglist); + va_end(arglist); } /* @@ -107,35 +101,31 @@ add_nodes (struct route_table *table, ...) * * @see print_table */ -static void -print_subtree (struct route_node *rn, const char *legend, int indent_level) +static void print_subtree(struct route_node *rn, const char *legend, + int indent_level) { - char buf[PREFIX2STR_BUFFER]; - int i; - - /* - * Print this node first. - */ - for (i = 0; i < indent_level; i++) - { - printf (" "); - } - - prefix2str (&rn->p, buf, sizeof (buf)); - printf ("%s: %s", legend, buf); - if (!rn->info) - { - printf (" (internal)"); - } - printf ("\n"); - if (rn->l_left) - { - print_subtree (rn->l_left, "Left", indent_level + 1); - } - if (rn->l_right) - { - print_subtree (rn->l_right, "Right", indent_level + 1); - } + char buf[PREFIX2STR_BUFFER]; + int i; + + /* + * Print this node first. + */ + for (i = 0; i < indent_level; i++) { + printf(" "); + } + + prefix2str(&rn->p, buf, sizeof(buf)); + printf("%s: %s", legend, buf); + if (!rn->info) { + printf(" (internal)"); + } + printf("\n"); + if (rn->l_left) { + print_subtree(rn->l_left, "Left", indent_level + 1); + } + if (rn->l_right) { + print_subtree(rn->l_right, "Right", indent_level + 1); + } } /* @@ -143,20 +133,18 @@ print_subtree (struct route_node *rn, const char *legend, int indent_level) * * Function that prints out the internal structure of a route table. */ -static void -print_table (struct route_table *table) +static void print_table(struct route_table *table) { - struct route_node *rn; + struct route_node *rn; - rn = table->top; + rn = table->top; - if (!rn) - { - printf ("\n"); - return; - } + if (!rn) { + printf("\n"); + return; + } - print_subtree (rn, "Top", 0); + print_subtree(rn, "Top", 0); } /* @@ -164,31 +152,28 @@ print_table (struct route_table *table) * * Remove all nodes from the given table. */ -static void -clear_table (struct route_table *table) +static void clear_table(struct route_table *table) { - route_table_iter_t iter; - struct route_node *rn; - test_node_t *node; - - route_table_iter_init (&iter, table); - - while ((rn = route_table_iter_next (&iter))) - { - node = rn->info; - if (!node) - { - continue; + route_table_iter_t iter; + struct route_node *rn; + test_node_t *node; + + route_table_iter_init(&iter, table); + + while ((rn = route_table_iter_next(&iter))) { + node = rn->info; + if (!node) { + continue; + } + rn->info = NULL; + route_unlock_node(rn); + free(node->prefix_str); + free(node); } - rn->info = NULL; - route_unlock_node (rn); - free (node->prefix_str); - free (node); - } - route_table_iter_cleanup (&iter); + route_table_iter_cleanup(&iter); - assert (table->top == NULL); + assert(table->top == NULL); } /* @@ -198,29 +183,26 @@ clear_table (struct route_table *table) * target_pfx is the expected one. Note that target_pfx may not be * present in the tree. */ -static void -verify_next_by_iterating (struct route_table *table, - struct prefix *target_pfx, struct prefix *next_pfx) +static void verify_next_by_iterating(struct route_table *table, + struct prefix *target_pfx, + struct prefix *next_pfx) { - route_table_iter_t iter; - struct route_node *rn; - - route_table_iter_init (&iter, table); - while ((rn = route_table_iter_next (&iter))) - { - if (route_table_prefix_iter_cmp (&rn->p, target_pfx) > 0) - { - assert (!prefix_cmp (&rn->p, next_pfx)); - break; + route_table_iter_t iter; + struct route_node *rn; + + route_table_iter_init(&iter, table); + while ((rn = route_table_iter_next(&iter))) { + if (route_table_prefix_iter_cmp(&rn->p, target_pfx) > 0) { + assert(!prefix_cmp(&rn->p, next_pfx)); + break; + } } - } - if (!rn) - { - assert (!next_pfx); - } + if (!rn) { + assert(!next_pfx); + } - route_table_iter_cleanup (&iter); + route_table_iter_cleanup(&iter); } /* @@ -229,200 +211,190 @@ verify_next_by_iterating (struct route_table *table, * Verifies that route_table_get_next() returns the expected result * (result) for the prefix string 'target'. */ -static void -verify_next (struct route_table *table, const char *target, const char *next) +static void verify_next(struct route_table *table, const char *target, + const char *next) { - struct prefix_ipv4 target_pfx, next_pfx; - struct route_node *rn; - char result_buf[PREFIX2STR_BUFFER]; - - if (str2prefix_ipv4 (target, &target_pfx) <= 0) - { - assert (0); - } - - rn = route_table_get_next (table, (struct prefix *) &target_pfx); - if (rn) - { - prefix2str (&rn->p, result_buf, sizeof (result_buf)); - } - else - { - snprintf (result_buf, sizeof (result_buf), "(Null)"); - } - - printf ("\n"); - print_table (table); - printf ("Verifying successor of %s. Expected: %s, Result: %s\n", target, - next ? next : "(Null)", result_buf); - - if (!rn) - { - assert (!next); - verify_next_by_iterating (table, (struct prefix *) &target_pfx, NULL); - return; - } - - assert (next); - - if (str2prefix_ipv4 (next, &next_pfx) <= 0) - { - assert (0); - } - - if (prefix_cmp (&rn->p, (struct prefix *) &next_pfx)) - { - assert (0); - } - route_unlock_node (rn); - - verify_next_by_iterating (table, (struct prefix *) &target_pfx, - (struct prefix *) &next_pfx); + struct prefix_ipv4 target_pfx, next_pfx; + struct route_node *rn; + char result_buf[PREFIX2STR_BUFFER]; + + if (str2prefix_ipv4(target, &target_pfx) <= 0) { + assert(0); + } + + rn = route_table_get_next(table, (struct prefix *)&target_pfx); + if (rn) { + prefix2str(&rn->p, result_buf, sizeof(result_buf)); + } else { + snprintf(result_buf, sizeof(result_buf), "(Null)"); + } + + printf("\n"); + print_table(table); + printf("Verifying successor of %s. Expected: %s, Result: %s\n", target, + next ? next : "(Null)", result_buf); + + if (!rn) { + assert(!next); + verify_next_by_iterating(table, (struct prefix *)&target_pfx, + NULL); + return; + } + + assert(next); + + if (str2prefix_ipv4(next, &next_pfx) <= 0) { + assert(0); + } + + if (prefix_cmp(&rn->p, (struct prefix *)&next_pfx)) { + assert(0); + } + route_unlock_node(rn); + + verify_next_by_iterating(table, (struct prefix *)&target_pfx, + (struct prefix *)&next_pfx); } /* * test_get_next */ -static void -test_get_next (void) +static void test_get_next(void) { - struct route_table *table; - - printf ("\n\nTesting route_table_get_next()\n"); - table = route_table_init (); - - /* - * Target exists in tree, but has no successor. - */ - add_nodes (table, "1.0.1.0/24", NULL); - verify_next (table, "1.0.1.0/24", NULL); - clear_table (table); - - /* - * Target exists in tree, and there is a node in its left subtree. - */ - add_nodes (table, "1.0.1.0/24", "1.0.1.0/25", NULL); - verify_next (table, "1.0.1.0/24", "1.0.1.0/25"); - clear_table (table); - - /* - * Target exists in tree, and there is a node in its right subtree. - */ - add_nodes (table, "1.0.1.0/24", "1.0.1.128/25", NULL); - verify_next (table, "1.0.1.0/24", "1.0.1.128/25"); - clear_table (table); - - /* - * Target exists in the tree, next node is outside subtree. - */ - add_nodes (table, "1.0.1.0/24", "1.1.0.0/16", NULL); - verify_next (table, "1.0.1.0/24", "1.1.0.0/16"); - clear_table (table); - - /* - * The target node does not exist in the tree for all the test cases - * below this point. - */ - - /* - * There is no successor in the tree. - */ - add_nodes (table, "1.0.0.0/16", NULL); - verify_next (table, "1.0.1.0/24", NULL); - clear_table (table); - - /* - * There exists a node that would be in the target's left subtree. - */ - add_nodes (table, "1.0.0.0/16", "1.0.1.0/25", NULL); - verify_next (table, "1.0.1.0/24", "1.0.1.0/25"); - clear_table (table); - - /* - * There exists a node would be in the target's right subtree. - */ - add_nodes (table, "1.0.0.0/16", "1.0.1.128/25", NULL); - verify_next (table, "1.0.1.0/24", "1.0.1.128/25"); - clear_table (table); - - /* - * A search for the target reaches a node where there are no child - * nodes in the direction of the target (left), but the node has a - * right child. - */ - add_nodes (table, "1.0.0.0/16", "1.0.128.0/17", NULL); - verify_next (table, "1.0.0.0/17", "1.0.128.0/17"); - clear_table (table); - - /* - * A search for the target reaches a node with no children. We have - * to go upwards in the tree to find a successor. - */ - add_nodes (table, "1.0.0.0/16", "1.0.0.0/24", "1.0.1.0/24", - "1.0.128.0/17", NULL); - verify_next (table, "1.0.1.0/25", "1.0.128.0/17"); - clear_table (table); - - /* - * A search for the target reaches a node where neither the node nor - * the target prefix contain each other. - * - * In first case below the node succeeds the target. - * - * In the second case, the node comes before the target, so we have - * to go up the tree looking for a successor. - */ - add_nodes (table, "1.0.0.0/16", "1.0.1.0/24", NULL); - verify_next (table, "1.0.0.0/24", "1.0.1.0/24"); - clear_table (table); - - add_nodes (table, "1.0.0.0/16", "1.0.0.0/24", "1.0.1.0/25", - "1.0.128.0/17", NULL); - verify_next (table, "1.0.1.128/25", "1.0.128.0/17"); - clear_table (table); - - route_table_finish (table); + struct route_table *table; + + printf("\n\nTesting route_table_get_next()\n"); + table = route_table_init(); + + /* + * Target exists in tree, but has no successor. + */ + add_nodes(table, "1.0.1.0/24", NULL); + verify_next(table, "1.0.1.0/24", NULL); + clear_table(table); + + /* + * Target exists in tree, and there is a node in its left subtree. + */ + add_nodes(table, "1.0.1.0/24", "1.0.1.0/25", NULL); + verify_next(table, "1.0.1.0/24", "1.0.1.0/25"); + clear_table(table); + + /* + * Target exists in tree, and there is a node in its right subtree. + */ + add_nodes(table, "1.0.1.0/24", "1.0.1.128/25", NULL); + verify_next(table, "1.0.1.0/24", "1.0.1.128/25"); + clear_table(table); + + /* + * Target exists in the tree, next node is outside subtree. + */ + add_nodes(table, "1.0.1.0/24", "1.1.0.0/16", NULL); + verify_next(table, "1.0.1.0/24", "1.1.0.0/16"); + clear_table(table); + + /* + * The target node does not exist in the tree for all the test cases + * below this point. + */ + + /* + * There is no successor in the tree. + */ + add_nodes(table, "1.0.0.0/16", NULL); + verify_next(table, "1.0.1.0/24", NULL); + clear_table(table); + + /* + * There exists a node that would be in the target's left subtree. + */ + add_nodes(table, "1.0.0.0/16", "1.0.1.0/25", NULL); + verify_next(table, "1.0.1.0/24", "1.0.1.0/25"); + clear_table(table); + + /* + * There exists a node would be in the target's right subtree. + */ + add_nodes(table, "1.0.0.0/16", "1.0.1.128/25", NULL); + verify_next(table, "1.0.1.0/24", "1.0.1.128/25"); + clear_table(table); + + /* + * A search for the target reaches a node where there are no child + * nodes in the direction of the target (left), but the node has a + * right child. + */ + add_nodes(table, "1.0.0.0/16", "1.0.128.0/17", NULL); + verify_next(table, "1.0.0.0/17", "1.0.128.0/17"); + clear_table(table); + + /* + * A search for the target reaches a node with no children. We have + * to go upwards in the tree to find a successor. + */ + add_nodes(table, "1.0.0.0/16", "1.0.0.0/24", "1.0.1.0/24", + "1.0.128.0/17", NULL); + verify_next(table, "1.0.1.0/25", "1.0.128.0/17"); + clear_table(table); + + /* + * A search for the target reaches a node where neither the node nor + * the target prefix contain each other. + * + * In first case below the node succeeds the target. + * + * In the second case, the node comes before the target, so we have + * to go up the tree looking for a successor. + */ + add_nodes(table, "1.0.0.0/16", "1.0.1.0/24", NULL); + verify_next(table, "1.0.0.0/24", "1.0.1.0/24"); + clear_table(table); + + add_nodes(table, "1.0.0.0/16", "1.0.0.0/24", "1.0.1.0/25", + "1.0.128.0/17", NULL); + verify_next(table, "1.0.1.128/25", "1.0.128.0/17"); + clear_table(table); + + route_table_finish(table); } /* * verify_prefix_iter_cmp */ -static void -verify_prefix_iter_cmp (const char *p1, const char *p2, int exp_result) +static void verify_prefix_iter_cmp(const char *p1, const char *p2, + int exp_result) { - struct prefix_ipv4 p1_pfx, p2_pfx; - int result; + struct prefix_ipv4 p1_pfx, p2_pfx; + int result; - if (str2prefix_ipv4 (p1, &p1_pfx) <= 0) - { - assert (0); - } + if (str2prefix_ipv4(p1, &p1_pfx) <= 0) { + assert(0); + } - if (str2prefix_ipv4 (p2, &p2_pfx) <= 0) - { - assert (0); - } + if (str2prefix_ipv4(p2, &p2_pfx) <= 0) { + assert(0); + } - result = route_table_prefix_iter_cmp ((struct prefix *) &p1_pfx, - (struct prefix *) &p2_pfx); + result = route_table_prefix_iter_cmp((struct prefix *)&p1_pfx, + (struct prefix *)&p2_pfx); - printf ("Verifying cmp(%s, %s) returns %d\n", p1, p2, exp_result); + printf("Verifying cmp(%s, %s) returns %d\n", p1, p2, exp_result); - assert (exp_result == result); + assert(exp_result == result); - /* - * Also check the reverse comparision. - */ - result = route_table_prefix_iter_cmp ((struct prefix *) &p2_pfx, - (struct prefix *) &p1_pfx); + /* + * Also check the reverse comparision. + */ + result = route_table_prefix_iter_cmp((struct prefix *)&p2_pfx, + (struct prefix *)&p1_pfx); - if (exp_result) - { - exp_result = -exp_result; - } + if (exp_result) { + exp_result = -exp_result; + } - printf ("Verifying cmp(%s, %s) returns %d\n", p1, p2, exp_result); - assert (result == exp_result); + printf("Verifying cmp(%s, %s) returns %d\n", p1, p2, exp_result); + assert(result == exp_result); } /* @@ -430,16 +402,15 @@ verify_prefix_iter_cmp (const char *p1, const char *p2, int exp_result) * * Tests comparision of prefixes according to order of iteration. */ -static void -test_prefix_iter_cmp () +static void test_prefix_iter_cmp() { - printf ("\n\nTesting route_table_prefix_iter_cmp()\n"); + printf("\n\nTesting route_table_prefix_iter_cmp()\n"); - verify_prefix_iter_cmp ("1.0.0.0/8", "1.0.0.0/8", 0); + verify_prefix_iter_cmp("1.0.0.0/8", "1.0.0.0/8", 0); - verify_prefix_iter_cmp ("1.0.0.0/8", "1.0.0.0/16", -1); + verify_prefix_iter_cmp("1.0.0.0/8", "1.0.0.0/16", -1); - verify_prefix_iter_cmp ("1.0.0.0/16", "1.128.0.0/16", -1); + verify_prefix_iter_cmp("1.0.0.0/16", "1.128.0.0/16", -1); } /* @@ -449,105 +420,92 @@ test_prefix_iter_cmp () * iterator that pauses at each node. Verifies that the two methods * yield the same results. */ -static void -verify_iter_with_pause (struct route_table *table) +static void verify_iter_with_pause(struct route_table *table) { - unsigned long num_nodes; - struct route_node *rn, *iter_rn; - route_table_iter_t iter_space; - route_table_iter_t *iter = &iter_space; - - route_table_iter_init (iter, table); - num_nodes = 0; - - for (rn = route_top (table); rn; rn = route_next (rn)) - { - num_nodes++; - route_table_iter_pause (iter); - - assert (iter->current == NULL); - if (route_table_iter_started (iter)) - { - assert (iter->state == RT_ITER_STATE_PAUSED); - } - else - { - assert (rn == table->top); - assert (iter->state == RT_ITER_STATE_INIT); + unsigned long num_nodes; + struct route_node *rn, *iter_rn; + route_table_iter_t iter_space; + route_table_iter_t *iter = &iter_space; + + route_table_iter_init(iter, table); + num_nodes = 0; + + for (rn = route_top(table); rn; rn = route_next(rn)) { + num_nodes++; + route_table_iter_pause(iter); + + assert(iter->current == NULL); + if (route_table_iter_started(iter)) { + assert(iter->state == RT_ITER_STATE_PAUSED); + } else { + assert(rn == table->top); + assert(iter->state == RT_ITER_STATE_INIT); + } + + iter_rn = route_table_iter_next(iter); + + /* + * Make sure both iterations return the same node. + */ + assert(rn == iter_rn); } - iter_rn = route_table_iter_next (iter); - - /* - * Make sure both iterations return the same node. - */ - assert (rn == iter_rn); - } + assert(num_nodes == route_table_count(table)); - assert (num_nodes == route_table_count (table)); + route_table_iter_pause(iter); + iter_rn = route_table_iter_next(iter); - route_table_iter_pause (iter); - iter_rn = route_table_iter_next (iter); + assert(iter_rn == NULL); + assert(iter->state == RT_ITER_STATE_DONE); - assert (iter_rn == NULL); - assert (iter->state == RT_ITER_STATE_DONE); + assert(route_table_iter_next(iter) == NULL); + assert(iter->state == RT_ITER_STATE_DONE); - assert (route_table_iter_next (iter) == NULL); - assert (iter->state == RT_ITER_STATE_DONE); + route_table_iter_cleanup(iter); - route_table_iter_cleanup (iter); - - print_table (table); - printf ("Verified pausing iteration on tree with %lu nodes\n", num_nodes); + print_table(table); + printf("Verified pausing iteration on tree with %lu nodes\n", + num_nodes); } /* * test_iter_pause */ -static void -test_iter_pause (void) +static void test_iter_pause(void) { - struct route_table *table; - int i, num_prefixes; - const char *prefixes[] = { - "1.0.1.0/24", - "1.0.1.0/25", - "1.0.1.128/25", - "1.0.2.0/24", - "2.0.0.0/8" - }; - - num_prefixes = sizeof (prefixes) / sizeof (prefixes[0]); - - printf ("\n\nTesting that route_table_iter_pause() works as expected\n"); - table = route_table_init (); - for (i = 0; i < num_prefixes; i++) - { - add_nodes (table, prefixes[i], NULL); - } - - verify_iter_with_pause (table); - - clear_table (table); - route_table_finish (table); + struct route_table *table; + int i, num_prefixes; + const char *prefixes[] = {"1.0.1.0/24", "1.0.1.0/25", "1.0.1.128/25", + "1.0.2.0/24", "2.0.0.0/8"}; + + num_prefixes = sizeof(prefixes) / sizeof(prefixes[0]); + + printf("\n\nTesting that route_table_iter_pause() works as expected\n"); + table = route_table_init(); + for (i = 0; i < num_prefixes; i++) { + add_nodes(table, prefixes[i], NULL); + } + + verify_iter_with_pause(table); + + clear_table(table); + route_table_finish(table); } /* * run_tests */ -static void -run_tests (void) +static void run_tests(void) { - test_prefix_iter_cmp (); - test_get_next (); - test_iter_pause (); + test_prefix_iter_cmp(); + test_get_next(); + test_iter_pause(); } /* * main */ -int -main (void) +int main(void) { - run_tests (); + run_tests(); } diff --git a/tests/lib/test_timer_correctness.c b/tests/lib/test_timer_correctness.c index 8fbe5bcbd..43e79ba9d 100644 --- a/tests/lib/test_timer_correctness.c +++ b/tests/lib/test_timer_correctness.c @@ -55,144 +55,137 @@ static int timers_pending; static void terminate_test(void) { - int exit_code; - - if (strcmp(log_buf, expected_buf)) - { - fprintf(stderr, "Expected output and received output differ.\n"); - fprintf(stderr, "---Expected output: ---\n%s", expected_buf); - fprintf(stderr, "---Actual output: ---\n%s", log_buf); - exit_code = 1; - } - else - { - printf("Expected output and actual output match.\n"); - exit_code = 0; - } - - thread_master_free(master); - XFREE(MTYPE_TMP, log_buf); - XFREE(MTYPE_TMP, expected_buf); - prng_free(prng); - XFREE(MTYPE_TMP, timers); - - exit(exit_code); + int exit_code; + + if (strcmp(log_buf, expected_buf)) { + fprintf(stderr, + "Expected output and received output differ.\n"); + fprintf(stderr, "---Expected output: ---\n%s", expected_buf); + fprintf(stderr, "---Actual output: ---\n%s", log_buf); + exit_code = 1; + } else { + printf("Expected output and actual output match.\n"); + exit_code = 0; + } + + thread_master_free(master); + XFREE(MTYPE_TMP, log_buf); + XFREE(MTYPE_TMP, expected_buf); + prng_free(prng); + XFREE(MTYPE_TMP, timers); + + exit(exit_code); } static int timer_func(struct thread *thread) { - int rv; + int rv; - rv = snprintf(log_buf + log_buf_pos, log_buf_len - log_buf_pos, - "%s\n", (char*)thread->arg); - assert(rv >= 0); - log_buf_pos += rv; - assert(log_buf_pos < log_buf_len); - XFREE(MTYPE_TMP, thread->arg); + rv = snprintf(log_buf + log_buf_pos, log_buf_len - log_buf_pos, "%s\n", + (char *)thread->arg); + assert(rv >= 0); + log_buf_pos += rv; + assert(log_buf_pos < log_buf_len); + XFREE(MTYPE_TMP, thread->arg); - timers_pending--; - if (!timers_pending) - terminate_test(); + timers_pending--; + if (!timers_pending) + terminate_test(); - return 0; + return 0; } -static int cmp_timeval(const void* a, const void *b) +static int cmp_timeval(const void *a, const void *b) { - const struct timeval *ta = *(struct timeval * const *)a; - const struct timeval *tb = *(struct timeval * const *)b; - - if (timercmp(ta, tb, <)) - return -1; - if (timercmp(ta, tb, >)) - return 1; - return 0; + const struct timeval *ta = *(struct timeval * const *)a; + const struct timeval *tb = *(struct timeval * const *)b; + + if (timercmp(ta, tb, <)) + return -1; + if (timercmp(ta, tb, >)) + return 1; + return 0; } int main(int argc, char **argv) { - int i, j; - struct thread t; - struct timeval **alarms; - - master = thread_master_create(NULL); - - log_buf_len = SCHEDULE_TIMERS * (TIMESTR_LEN + 1) + 1; - log_buf_pos = 0; - log_buf = XMALLOC(MTYPE_TMP, log_buf_len); - - expected_buf_len = SCHEDULE_TIMERS * (TIMESTR_LEN + 1) + 1; - expected_buf_pos = 0; - expected_buf = XMALLOC(MTYPE_TMP, expected_buf_len); - - prng = prng_new(0); - - timers = XMALLOC(MTYPE_TMP, SCHEDULE_TIMERS * sizeof(*timers)); - - for (i = 0; i < SCHEDULE_TIMERS; i++) - { - long interval_msec; - int ret; - char *arg; - - /* Schedule timers to expire in 0..5 seconds */ - interval_msec = prng_rand(prng) % 5000; - arg = XMALLOC(MTYPE_TMP, TIMESTR_LEN + 1); - timers[i] = NULL; - thread_add_timer_msec(master, timer_func, arg, interval_msec, - &timers[i]); - ret = snprintf(arg, TIMESTR_LEN + 1, "%lld.%06lld", - (long long)timers[i]->u.sands.tv_sec, - (long long)timers[i]->u.sands.tv_usec); - assert(ret > 0); - assert((size_t)ret < TIMESTR_LEN + 1); - timers_pending++; - } - - for (i = 0; i < REMOVE_TIMERS; i++) - { - int index; - - index = prng_rand(prng) % SCHEDULE_TIMERS; - if (!timers[index]) - continue; - - XFREE(MTYPE_TMP, timers[index]->arg); - thread_cancel(timers[index]); - timers[index] = NULL; - timers_pending--; - } - - /* We create an array of pointers to the alarm times and sort - * that array. That sorted array is used to generate a string - * representing the expected "output" of the timers when they - * are run. */ - j = 0; - alarms = XMALLOC(MTYPE_TMP, timers_pending * sizeof(*alarms)); - for (i = 0; i < SCHEDULE_TIMERS; i++) - { - if (!timers[i]) - continue; - alarms[j++] = &timers[i]->u.sands; - } - qsort(alarms, j, sizeof(*alarms), cmp_timeval); - for (i = 0; i < j; i++) - { - int ret; - - ret = snprintf(expected_buf + expected_buf_pos, - expected_buf_len - expected_buf_pos, - "%lld.%06lld\n", - (long long)alarms[i]->tv_sec, - (long long)alarms[i]->tv_usec); - assert(ret > 0); - expected_buf_pos += ret; - assert(expected_buf_pos < expected_buf_len); - } - XFREE(MTYPE_TMP, alarms); - - while (thread_fetch(master, &t)) - thread_call(&t); - - return 0; + int i, j; + struct thread t; + struct timeval **alarms; + + master = thread_master_create(NULL); + + log_buf_len = SCHEDULE_TIMERS * (TIMESTR_LEN + 1) + 1; + log_buf_pos = 0; + log_buf = XMALLOC(MTYPE_TMP, log_buf_len); + + expected_buf_len = SCHEDULE_TIMERS * (TIMESTR_LEN + 1) + 1; + expected_buf_pos = 0; + expected_buf = XMALLOC(MTYPE_TMP, expected_buf_len); + + prng = prng_new(0); + + timers = XMALLOC(MTYPE_TMP, SCHEDULE_TIMERS * sizeof(*timers)); + + for (i = 0; i < SCHEDULE_TIMERS; i++) { + long interval_msec; + int ret; + char *arg; + + /* Schedule timers to expire in 0..5 seconds */ + interval_msec = prng_rand(prng) % 5000; + arg = XMALLOC(MTYPE_TMP, TIMESTR_LEN + 1); + timers[i] = NULL; + thread_add_timer_msec(master, timer_func, arg, interval_msec, + &timers[i]); + ret = snprintf(arg, TIMESTR_LEN + 1, "%lld.%06lld", + (long long)timers[i]->u.sands.tv_sec, + (long long)timers[i]->u.sands.tv_usec); + assert(ret > 0); + assert((size_t)ret < TIMESTR_LEN + 1); + timers_pending++; + } + + for (i = 0; i < REMOVE_TIMERS; i++) { + int index; + + index = prng_rand(prng) % SCHEDULE_TIMERS; + if (!timers[index]) + continue; + + XFREE(MTYPE_TMP, timers[index]->arg); + thread_cancel(timers[index]); + timers[index] = NULL; + timers_pending--; + } + + /* We create an array of pointers to the alarm times and sort + * that array. That sorted array is used to generate a string + * representing the expected "output" of the timers when they + * are run. */ + j = 0; + alarms = XMALLOC(MTYPE_TMP, timers_pending * sizeof(*alarms)); + for (i = 0; i < SCHEDULE_TIMERS; i++) { + if (!timers[i]) + continue; + alarms[j++] = &timers[i]->u.sands; + } + qsort(alarms, j, sizeof(*alarms), cmp_timeval); + for (i = 0; i < j; i++) { + int ret; + + ret = snprintf(expected_buf + expected_buf_pos, + expected_buf_len - expected_buf_pos, + "%lld.%06lld\n", (long long)alarms[i]->tv_sec, + (long long)alarms[i]->tv_usec); + assert(ret > 0); + expected_buf_pos += ret; + assert(expected_buf_pos < expected_buf_len); + } + XFREE(MTYPE_TMP, alarms); + + while (thread_fetch(master, &t)) + thread_call(&t); + + return 0; } diff --git a/tests/lib/test_timer_performance.c b/tests/lib/test_timer_performance.c index 2bd02b5b0..f9a244e25 100644 --- a/tests/lib/test_timer_performance.c +++ b/tests/lib/test_timer_performance.c @@ -38,70 +38,68 @@ struct thread_master *master; static int dummy_func(struct thread *thread) { - return 0; + return 0; } int main(int argc, char **argv) { - struct prng *prng; - int i; - struct thread **timers; - struct timeval tv_start, tv_lap, tv_stop; - unsigned long t_schedule, t_remove; - - master = thread_master_create(NULL); - prng = prng_new(0); - timers = calloc(SCHEDULE_TIMERS, sizeof(*timers)); - - /* create thread structures so they won't be allocated during the - * time measurement */ - for (i = 0; i < SCHEDULE_TIMERS; i++) { - timers[i] = NULL; - thread_add_timer_msec(master, dummy_func, NULL, 0, &timers[i]); - } - for (i = 0; i < SCHEDULE_TIMERS; i++) - thread_cancel(timers[i]); - - monotime(&tv_start); - - for (i = 0; i < SCHEDULE_TIMERS; i++) - { - long interval_msec; - - interval_msec = prng_rand(prng) % (100 * SCHEDULE_TIMERS); - timers[i] = NULL; - thread_add_timer_msec(master, dummy_func, NULL, interval_msec, - &timers[i]); - } - - monotime(&tv_lap); - - for (i = 0; i < REMOVE_TIMERS; i++) - { - int index; - - index = prng_rand(prng) % SCHEDULE_TIMERS; - if (timers[index]) - thread_cancel(timers[index]); - timers[index] = NULL; - } - - monotime(&tv_stop); - - t_schedule = 1000 * (tv_lap.tv_sec - tv_start.tv_sec); - t_schedule += (tv_lap.tv_usec - tv_start.tv_usec) / 1000; - - t_remove = 1000 * (tv_stop.tv_sec - tv_lap.tv_sec); - t_remove += (tv_stop.tv_usec - tv_lap.tv_usec) / 1000; - - printf("Scheduling %d random timers took %ld.%03ld seconds.\n", - SCHEDULE_TIMERS, t_schedule/1000, t_schedule%1000); - printf("Removing %d random timers took %ld.%03ld seconds.\n", - REMOVE_TIMERS, t_remove/1000, t_remove%1000); - fflush(stdout); - - free(timers); - thread_master_free(master); - prng_free(prng); - return 0; + struct prng *prng; + int i; + struct thread **timers; + struct timeval tv_start, tv_lap, tv_stop; + unsigned long t_schedule, t_remove; + + master = thread_master_create(NULL); + prng = prng_new(0); + timers = calloc(SCHEDULE_TIMERS, sizeof(*timers)); + + /* create thread structures so they won't be allocated during the + * time measurement */ + for (i = 0; i < SCHEDULE_TIMERS; i++) { + timers[i] = NULL; + thread_add_timer_msec(master, dummy_func, NULL, 0, &timers[i]); + } + for (i = 0; i < SCHEDULE_TIMERS; i++) + thread_cancel(timers[i]); + + monotime(&tv_start); + + for (i = 0; i < SCHEDULE_TIMERS; i++) { + long interval_msec; + + interval_msec = prng_rand(prng) % (100 * SCHEDULE_TIMERS); + timers[i] = NULL; + thread_add_timer_msec(master, dummy_func, NULL, interval_msec, + &timers[i]); + } + + monotime(&tv_lap); + + for (i = 0; i < REMOVE_TIMERS; i++) { + int index; + + index = prng_rand(prng) % SCHEDULE_TIMERS; + if (timers[index]) + thread_cancel(timers[index]); + timers[index] = NULL; + } + + monotime(&tv_stop); + + t_schedule = 1000 * (tv_lap.tv_sec - tv_start.tv_sec); + t_schedule += (tv_lap.tv_usec - tv_start.tv_usec) / 1000; + + t_remove = 1000 * (tv_stop.tv_sec - tv_lap.tv_sec); + t_remove += (tv_stop.tv_usec - tv_lap.tv_usec) / 1000; + + printf("Scheduling %d random timers took %ld.%03ld seconds.\n", + SCHEDULE_TIMERS, t_schedule / 1000, t_schedule % 1000); + printf("Removing %d random timers took %ld.%03ld seconds.\n", + REMOVE_TIMERS, t_remove / 1000, t_remove % 1000); + fflush(stdout); + + free(timers); + thread_master_free(master); + prng_free(prng); + return 0; } diff --git a/tests/ospf6d/test_lsdb.c b/tests/ospf6d/test_lsdb.c index efacace7b..310c4a732 100644 --- a/tests/ospf6d/test_lsdb.c +++ b/tests/ospf6d/test_lsdb.c @@ -116,12 +116,11 @@ static void lsa_show_oneline(struct vty *vty, struct ospf6_lsa *lsa) vty_out(vty, "lsa = NULL\n"); return; } - inet_ntop(AF_INET, &lsa->header->id, - id, sizeof (id)); - inet_ntop(AF_INET, &lsa->header->adv_router, - adv_router, sizeof (adv_router)); - vty_out(vty, "type %u adv %s id %s\n", - ntohs(lsa->header->type), adv_router, id); + inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id)); + inet_ntop(AF_INET, &lsa->header->adv_router, adv_router, + sizeof(adv_router)); + vty_out(vty, "type %u adv %s id %s\n", ntohs(lsa->header->type), + adv_router, id); } DEFPY(lsdb_walk, lsdb_walk_cmd, diff --git a/tests/test_lblmgr.c b/tests/test_lblmgr.c index a659447e7..afc5ba663 100644 --- a/tests/test_lblmgr.c +++ b/tests/test_lblmgr.c @@ -33,117 +33,112 @@ u_short instance = 1; const char *sequence = "GGRGGGRRG"; -static int zebra_send_get_label_chunk (void); -static int zebra_send_release_label_chunk (uint32_t start, uint32_t end); +static int zebra_send_get_label_chunk(void); +static int zebra_send_release_label_chunk(uint32_t start, uint32_t end); -static void -process_next_call (uint32_t start, uint32_t end) +static void process_next_call(uint32_t start, uint32_t end) { - sleep (3); - if (!*sequence) - exit (0); - if (*sequence == 'G') - zebra_send_get_label_chunk (); - else if (*sequence == 'R') - zebra_send_release_label_chunk (start, end); + sleep(3); + if (!*sequence) + exit(0); + if (*sequence == 'G') + zebra_send_get_label_chunk(); + else if (*sequence == 'R') + zebra_send_release_label_chunk(start, end); } /* Connect to Label Manager */ -static int -zebra_send_label_manager_connect () +static int zebra_send_label_manager_connect() { - int ret; + int ret; - printf("Connect to Label Manager\n"); + printf("Connect to Label Manager\n"); - ret = lm_label_manager_connect (zclient); - printf ("Label Manager connection result: %u \n", ret); - if (ret != 0 ) { - fprintf (stderr, "Error %d connecting to Label Manager %s\n", ret, - strerror(errno)); - exit (1); - } + ret = lm_label_manager_connect(zclient); + printf("Label Manager connection result: %u \n", ret); + if (ret != 0) { + fprintf(stderr, "Error %d connecting to Label Manager %s\n", + ret, strerror(errno)); + exit(1); + } - process_next_call (0, 0); + process_next_call(0, 0); } /* Get Label Chunk */ -static int -zebra_send_get_label_chunk () +static int zebra_send_get_label_chunk() { - uint32_t start; - uint32_t end; - int ret; + uint32_t start; + uint32_t end; + int ret; - printf("Ask for label chunk \n"); + printf("Ask for label chunk \n"); - ret = lm_get_label_chunk (zclient, KEEP, CHUNK_SIZE, &start, &end); - if (ret != 0 ) { - fprintf (stderr, "Error %d requesting label chunk %s\n", ret, strerror(errno)); - exit (1); - } + ret = lm_get_label_chunk(zclient, KEEP, CHUNK_SIZE, &start, &end); + if (ret != 0) { + fprintf(stderr, "Error %d requesting label chunk %s\n", ret, + strerror(errno)); + exit(1); + } - sequence++; + sequence++; - printf ("Label Chunk assign: %u - %u \n", - start, end); + printf("Label Chunk assign: %u - %u \n", start, end); - process_next_call (start, end); + process_next_call(start, end); } /* Release Label Chunk */ -static int -zebra_send_release_label_chunk (uint32_t start, uint32_t end) +static int zebra_send_release_label_chunk(uint32_t start, uint32_t end) { - struct stream *s; - int ret; + struct stream *s; + int ret; - printf("Release label chunk: %u - %u\n", start, end); + printf("Release label chunk: %u - %u\n", start, end); - ret = lm_release_label_chunk (zclient, start, end); - if (ret != 0 ) { - fprintf (stderr, "Error releasing label chunk\n"); - exit (1); - } + ret = lm_release_label_chunk(zclient, start, end); + if (ret != 0) { + fprintf(stderr, "Error releasing label chunk\n"); + exit(1); + } - sequence++; + sequence++; - process_next_call (start-CHUNK_SIZE, end-CHUNK_SIZE); + process_next_call(start - CHUNK_SIZE, end - CHUNK_SIZE); } -void init_zclient (struct thread_master *master, char *lm_zserv_path) +void init_zclient(struct thread_master *master, char *lm_zserv_path) { - if (lm_zserv_path) - zclient_serv_path_set(lm_zserv_path); - - zclient = zclient_new(master); - /* zclient_init(zclient, ZEBRA_LABEL_MANAGER, 0); */ - zclient->sock = -1; - zclient->redist_default = ZEBRA_ROUTE_LDP; - zclient->instance = instance; - if (zclient_socket_connect (zclient) < 0) { - printf ("Error connecting synchronous zclient!\n"); - exit (1); - } - + if (lm_zserv_path) + zclient_serv_path_set(lm_zserv_path); + + zclient = zclient_new(master); + /* zclient_init(zclient, ZEBRA_LABEL_MANAGER, 0); */ + zclient->sock = -1; + zclient->redist_default = ZEBRA_ROUTE_LDP; + zclient->instance = instance; + if (zclient_socket_connect(zclient) < 0) { + printf("Error connecting synchronous zclient!\n"); + exit(1); + } } -int main (int argc, char *argv[]) +int main(int argc, char *argv[]) { - struct thread_master *master; - struct thread thread; - int ret; + struct thread_master *master; + struct thread thread; + int ret; - printf ("Sequence to be tested: %s\n", sequence); + printf("Sequence to be tested: %s\n", sequence); - master = thread_master_create(NULL); - init_zclient (master, ZSERV_PATH); + master = thread_master_create(NULL); + init_zclient(master, ZSERV_PATH); - zebra_send_label_manager_connect (); + zebra_send_label_manager_connect(); - return 0; + return 0; } diff --git a/tools/cocci.h b/tools/cocci.h index 50199fa82..d25fcbbe2 100644 --- a/tools/cocci.h +++ b/tools/cocci.h @@ -1,35 +1,29 @@ -/* some of this stuff doesn't seem to parse properly in coccinelle +/* some of this stuff doesn't seem to parse properly in coccinelle */ -#define DEFUN(funcname, cmdname, str, help) \ - static int funcname \ - (const struct cmd_element *self, \ - struct vty *vty, \ - int argc, \ - struct cmd_token *argv[]) -#define DEFUN_HIDDEN(funcname, cmdname, str, help) \ - static int funcname \ - (const struct cmd_element *self, \ - struct vty *vty, \ - int argc, \ - struct cmd_token *argv[]) +#define DEFUN(funcname, cmdname, str, help) \ + static int funcname(const struct cmd_element *self, struct vty *vty, \ + int argc, struct cmd_token *argv[]) +#define DEFUN_HIDDEN(funcname, cmdname, str, help) \ + static int funcname(const struct cmd_element *self, struct vty *vty, \ + int argc, struct cmd_token *argv[]) #define ENABLE_BGP_VNC 1 -#define ALL_LIST_ELEMENTS_RO(list,node,data) \ - (node) = listhead(list), ((data) = NULL);\ - (node) != NULL && ((data) = listgetdata(node)); \ - (node) = listnextnode(node), ((data) = NULL) -#define ALL_LIST_ELEMENTS(list,node,nextnode,data) \ - (node) = listhead(list), ((data) = NULL); \ - (node) != NULL && \ - ((data) = listgetdata(node),(nextnode) = node->next); \ - (node) = (nextnode), ((data) = NULL) -#define LIST_HEAD(name, type) \ - struct name { \ - struct type *lh_first; /* first element */ \ - } -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} +#define ALL_LIST_ELEMENTS_RO(list, node, data) \ + (node) = listhead(list), ((data) = NULL); \ + (node) != NULL && ((data) = listgetdata(node)); \ + (node) = listnextnode(node), ((data) = NULL) +#define ALL_LIST_ELEMENTS(list, node, nextnode, data) \ + (node) = listhead(list), ((data) = NULL); \ + (node) != NULL \ + && ((data) = listgetdata(node), (nextnode) = node->next); \ + (node) = (nextnode), ((data) = NULL) +#define LIST_HEAD(name, type) \ + struct name { \ + struct type *lh_first; /* first element */ \ + } +#define LIST_ENTRY(type) \ + struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ + } diff --git a/tools/permutations.c b/tools/permutations.c index fa1817a8e..80441753e 100644 --- a/tools/permutations.c +++ b/tools/permutations.c @@ -26,74 +26,66 @@ #define USAGE "usage: permutations " -void -permute (struct graph_node *); -void -pretty_print_graph (struct graph_node *start, int level); +void permute(struct graph_node *); +void pretty_print_graph(struct graph_node *start, int level); -int main (int argc, char *argv[]) +int main(int argc, char *argv[]) { - if (argc < 2) - { - fprintf(stdout, USAGE"\n"); - exit(EXIT_SUCCESS); - } - struct cmd_element *cmd = calloc (1, sizeof (struct cmd_element)); - cmd->string = strdup(argv[1]); + if (argc < 2) { + fprintf(stdout, USAGE "\n"); + exit(EXIT_SUCCESS); + } + struct cmd_element *cmd = calloc(1, sizeof(struct cmd_element)); + cmd->string = strdup(argv[1]); - struct graph *graph = graph_new(); - struct cmd_token *token = cmd_token_new (START_TKN, cmd->attr, NULL, NULL); - graph_new_node (graph, token, NULL); - cmd_graph_parse (graph, cmd); + struct graph *graph = graph_new(); + struct cmd_token *token = + cmd_token_new(START_TKN, cmd->attr, NULL, NULL); + graph_new_node(graph, token, NULL); + cmd_graph_parse(graph, cmd); - permute (vector_slot (graph->nodes, 0)); + permute(vector_slot(graph->nodes, 0)); } -void -permute (struct graph_node *start) +void permute(struct graph_node *start) { - static struct list *position = NULL; - if (!position) position = list_new (); + static struct list *position = NULL; + if (!position) + position = list_new(); - struct cmd_token *stok = start->data; - struct graph_node *gnn; - struct listnode *ln; + struct cmd_token *stok = start->data; + struct graph_node *gnn; + struct listnode *ln; - // recursive dfs - listnode_add (position, start); - for (unsigned int i = 0; i < vector_active (start->to); i++) - { - struct graph_node *gn = vector_slot (start->to, i); - struct cmd_token *tok = gn->data; - if (tok->attr == CMD_ATTR_HIDDEN || - tok->attr == CMD_ATTR_DEPRECATED) - continue; - else if (tok->type == END_TKN || gn == start) - { - fprintf (stdout, " "); - for (ALL_LIST_ELEMENTS_RO (position,ln,gnn)) - { - struct cmd_token *tt = gnn->data; - if (tt->type < SPECIAL_TKN) - fprintf (stdout, " %s", tt->text); - } - if (gn == start) - fprintf (stdout, "..."); - fprintf (stdout, "\n"); - } - else - { - bool skip = false; - if (stok->type == FORK_TKN && tok->type != FORK_TKN) - for (ALL_LIST_ELEMENTS_RO (position, ln, gnn)) - if (gnn == gn) - { - skip = true; - break; - } - if (!skip) - permute (gn); - } - } - list_delete_node (position, listtail(position)); + // recursive dfs + listnode_add(position, start); + for (unsigned int i = 0; i < vector_active(start->to); i++) { + struct graph_node *gn = vector_slot(start->to, i); + struct cmd_token *tok = gn->data; + if (tok->attr == CMD_ATTR_HIDDEN + || tok->attr == CMD_ATTR_DEPRECATED) + continue; + else if (tok->type == END_TKN || gn == start) { + fprintf(stdout, " "); + for (ALL_LIST_ELEMENTS_RO(position, ln, gnn)) { + struct cmd_token *tt = gnn->data; + if (tt->type < SPECIAL_TKN) + fprintf(stdout, " %s", tt->text); + } + if (gn == start) + fprintf(stdout, "..."); + fprintf(stdout, "\n"); + } else { + bool skip = false; + if (stok->type == FORK_TKN && tok->type != FORK_TKN) + for (ALL_LIST_ELEMENTS_RO(position, ln, gnn)) + if (gnn == gn) { + skip = true; + break; + } + if (!skip) + permute(gn); + } + } + list_delete_node(position, listtail(position)); } diff --git a/tools/start-stop-daemon.c b/tools/start-stop-daemon.c index f1a252a26..39527eca7 100644 --- a/tools/start-stop-daemon.c +++ b/tools/start-stop-daemon.c @@ -106,7 +106,8 @@ static struct schedule_item *schedule = NULL; LIST_HEAD(namespace_head, namespace); -struct namespace { +struct namespace +{ LIST_ENTRY(namespace) list; const char *path; int nstype; @@ -117,20 +118,19 @@ static struct namespace_head namespace_head; static void *xmalloc(int size); static void push(struct pid_list **list, pid_t pid); static void do_help(void); -static void parse_options(int argc, char * const *argv); +static void parse_options(int argc, char *const *argv); static int pid_is_user(pid_t pid, uid_t uid); static int pid_is_cmd(pid_t pid, const char *name); static void check(pid_t pid); static void do_pidfile(const char *name); -static void do_stop(int signal_nr, int quietmode, - int *n_killed, int *n_notkilled, int retry_nr); +static void do_stop(int signal_nr, int quietmode, int *n_killed, + int *n_notkilled, int retry_nr); static int pid_is_exec(pid_t pid, const struct stat *esb); #ifdef __GNUC__ static void fatal(const char *format, ...) __attribute__((noreturn, format(printf, 1, 2))); -static void badusage(const char *msg) - __attribute__((noreturn)); +static void badusage(const char *msg) __attribute__((noreturn)); #else static void fatal(const char *format, ...); static void badusage(const char *msg); @@ -149,26 +149,32 @@ static void badusage(const char *msg); * subtraction (before any resulting multiplication or what have you). * TVELEM must be linear in TVADJUST. */ -typedef long tvselector(const struct timeval*); -static long tvselector_sec(const struct timeval *tv) { return tv->tv_sec; } -static long tvselector_usec(const struct timeval *tv) { return tv->tv_usec; } -#define TVCALC_ELEM(result, expr, sec, adj) \ -{ \ - const long TVADJUST = adj; \ - long (*const TVELEM)(const struct timeval*) = tvselector_##sec; \ - (result).tv_##sec = (expr); \ +typedef long tvselector(const struct timeval *); +static long tvselector_sec(const struct timeval *tv) +{ + return tv->tv_sec; } -#define TVCALC(result,expr) \ -do { \ - TVCALC_ELEM(result, expr, sec, (-1)); \ - TVCALC_ELEM(result, expr, usec, (+1000000)); \ - (result).tv_sec += (result).tv_usec / 1000000; \ - (result).tv_usec %= 1000000; \ -} while(0) +static long tvselector_usec(const struct timeval *tv) +{ + return tv->tv_usec; +} +#define TVCALC_ELEM(result, expr, sec, adj) \ + { \ + const long TVADJUST = adj; \ + long (*const TVELEM)(const struct timeval *) = \ + tvselector_##sec; \ + (result).tv_##sec = (expr); \ + } +#define TVCALC(result, expr) \ + do { \ + TVCALC_ELEM(result, expr, sec, (-1)); \ + TVCALC_ELEM(result, expr, usec, (+1000000)); \ + (result).tv_sec += (result).tv_usec / 1000000; \ + (result).tv_usec %= 1000000; \ + } while (0) -static void -fatal(const char *format, ...) +static void fatal(const char *format, ...) { va_list arglist; @@ -181,8 +187,7 @@ fatal(const char *format, ...) } -static void * -xmalloc(int size) +static void *xmalloc(int size) { void *ptr; @@ -192,15 +197,13 @@ xmalloc(int size) fatal("malloc(%d) failed", size); } -static void -xgettimeofday(struct timeval *tv) +static void xgettimeofday(struct timeval *tv) { - if (gettimeofday(tv,0) != 0) + if (gettimeofday(tv, 0) != 0) fatal("gettimeofday failed: %s", strerror(errno)); } -static void -push(struct pid_list **list, pid_t pid) +static void push(struct pid_list **list, pid_t pid) { struct pid_list *p; @@ -210,8 +213,7 @@ push(struct pid_list **list, pid_t pid) *list = p; } -static void -clear(struct pid_list **list) +static void clear(struct pid_list **list) { struct pid_list *here, *next; @@ -224,8 +226,7 @@ clear(struct pid_list **list) } #ifdef linux -static const char * -next_dirname(const char *s) +static const char *next_dirname(const char *s) { const char *cur; @@ -243,8 +244,7 @@ next_dirname(const char *s) return cur; } -static void -add_namespace(const char *path) +static void add_namespace(const char *path) { int nstype; const char *nsdirname, *nsname, *cur; @@ -258,7 +258,7 @@ add_namespace(const char *path) nsname = cur; } - if (!memcmp(nsdirname, "ipcns/", strlen("ipcns/"))) + if (!memcmp(nsdirname, "ipcns/", strlen("ipcns/"))) nstype = CLONE_NEWIPC; else if (!memcmp(nsdirname, "netns/", strlen("netns/"))) nstype = CLONE_NEWNET; @@ -275,71 +275,69 @@ add_namespace(const char *path) #endif #ifdef HAVE_LXC -static void -set_namespaces() +static void set_namespaces() { struct namespace *namespace; int fd; - LIST_FOREACH(namespace, &namespace_head, list) { + LIST_FOREACH(namespace, &namespace_head, list) + { if ((fd = open(namespace->path, O_RDONLY)) == -1) - fatal("open namespace %s: %s", namespace->path, strerror(errno)); + fatal("open namespace %s: %s", namespace->path, + strerror(errno)); if (setns(fd, namespace->nstype) == -1) fatal("setns %s: %s", namespace->path, strerror(errno)); } } #else -static void -set_namespaces() +static void set_namespaces() { if (!LIST_EMPTY(&namespace_head)) fatal("LCX namespaces not supported"); } #endif -static void -do_help(void) +static void do_help(void) { - printf( -"start-stop-daemon " VERSION " for Debian - small and fast C version written by\n" -"Marek Michalkiewicz , public domain.\n" -"\n" -"Usage:\n" -" start-stop-daemon -S|--start options ... -- arguments ...\n" -" start-stop-daemon -K|--stop options ...\n" -" start-stop-daemon -H|--help\n" -" start-stop-daemon -V|--version\n" -"\n" -"Options (at least one of --exec|--pidfile|--user is required):\n" -" -x|--exec program to start/check if it is running\n" -" -p|--pidfile pid file to check\n" -" -c|--chuid \n" -" change to this user/group before starting process\n" -" -u|--user | stop processes owned by this user\n" -" -n|--name stop processes with this name\n" -" -s|--signal signal to send (default TERM)\n" -" -a|--startas program to start (default is )\n" -" -N|--nicelevel add incr to the process's nice level\n" -" -b|--background force the process to detach\n" -" -m|--make-pidfile create the pidfile before starting\n" -" -R|--retry check whether processes die, and retry\n" -" -t|--test test mode, don't do anything\n" -" -o|--oknodo exit status 0 (not 1) if nothing done\n" -" -q|--quiet be more quiet\n" -" -v|--verbose be more verbose\n" -"Retry is |//... where is one of\n" -" -|[-] send that signal\n" -" wait that many seconds\n" -" forever repeat remainder forever\n" -"or may be just , meaning //KILL/\n" -"\n" -"Exit status: 0 = done 1 = nothing done (=> 0 if --oknodo)\n" -" 3 = trouble 2 = with --retry, processes wouldn't die\n"); + printf("start-stop-daemon " VERSION + " for Debian - small and fast C version written by\n" + "Marek Michalkiewicz , public domain.\n" + "\n" + "Usage:\n" + " start-stop-daemon -S|--start options ... -- arguments ...\n" + " start-stop-daemon -K|--stop options ...\n" + " start-stop-daemon -H|--help\n" + " start-stop-daemon -V|--version\n" + "\n" + "Options (at least one of --exec|--pidfile|--user is required):\n" + " -x|--exec program to start/check if it is running\n" + " -p|--pidfile pid file to check\n" + " -c|--chuid \n" + " change to this user/group before starting process\n" + " -u|--user | stop processes owned by this user\n" + " -n|--name stop processes with this name\n" + " -s|--signal signal to send (default TERM)\n" + " -a|--startas program to start (default is )\n" + " -N|--nicelevel add incr to the process's nice level\n" + " -b|--background force the process to detach\n" + " -m|--make-pidfile create the pidfile before starting\n" + " -R|--retry check whether processes die, and retry\n" + " -t|--test test mode, don't do anything\n" + " -o|--oknodo exit status 0 (not 1) if nothing done\n" + " -q|--quiet be more quiet\n" + " -v|--verbose be more verbose\n" + "Retry is |//... where is one of\n" + " -|[-] send that signal\n" + " wait that many seconds\n" + " forever repeat remainder forever\n" + "or may be just , meaning //KILL/\n" + "\n" + "Exit status: 0 = done 1 = nothing done (=> 0 if --oknodo)\n" + " 3 = trouble 2 = with --retry, processes wouldn't die\n"); } -static void -badusage(const char *msg) +static void badusage(const char *msg) { if (msg) fprintf(stderr, "%s: %s\n", progname, msg); @@ -353,51 +351,39 @@ struct sigpair { }; const struct sigpair siglist[] = { - { "ABRT", SIGABRT }, - { "ALRM", SIGALRM }, - { "FPE", SIGFPE }, - { "HUP", SIGHUP }, - { "ILL", SIGILL }, - { "INT", SIGINT }, - { "KILL", SIGKILL }, - { "PIPE", SIGPIPE }, - { "QUIT", SIGQUIT }, - { "SEGV", SIGSEGV }, - { "TERM", SIGTERM }, - { "USR1", SIGUSR1 }, - { "USR2", SIGUSR2 }, - { "CHLD", SIGCHLD }, - { "CONT", SIGCONT }, - { "STOP", SIGSTOP }, - { "TSTP", SIGTSTP }, - { "TTIN", SIGTTIN }, - { "TTOU", SIGTTOU } -}; - -static int parse_integer (const char *string, int *value_r) { + {"ABRT", SIGABRT}, {"ALRM", SIGALRM}, {"FPE", SIGFPE}, + {"HUP", SIGHUP}, {"ILL", SIGILL}, {"INT", SIGINT}, + {"KILL", SIGKILL}, {"PIPE", SIGPIPE}, {"QUIT", SIGQUIT}, + {"SEGV", SIGSEGV}, {"TERM", SIGTERM}, {"USR1", SIGUSR1}, + {"USR2", SIGUSR2}, {"CHLD", SIGCHLD}, {"CONT", SIGCONT}, + {"STOP", SIGSTOP}, {"TSTP", SIGTSTP}, {"TTIN", SIGTTIN}, + {"TTOU", SIGTTOU}}; + +static int parse_integer(const char *string, int *value_r) +{ unsigned long ul; char *ep; if (!string[0]) return -1; - ul= strtoul(string,&ep,10); + ul = strtoul(string, &ep, 10); if (ul > INT_MAX || *ep != '\0') return -1; - *value_r= ul; + *value_r = ul; return 0; } -static int parse_signal (const char *signal_str, int *signal_nr) +static int parse_signal(const char *signal_str, int *signal_nr) { unsigned int i; if (parse_integer(signal_str, signal_nr) == 0) return 0; - for (i = 0; i < sizeof (siglist) / sizeof (siglist[0]); i++) { - if (strcmp (signal_str, siglist[i].name) == 0) { + for (i = 0; i < sizeof(siglist) / sizeof(siglist[0]); i++) { + if (strcmp(signal_str, siglist[i].name) == 0) { *signal_nr = siglist[i].signal; return 0; } @@ -405,27 +391,28 @@ static int parse_signal (const char *signal_str, int *signal_nr) return -1; } -static void -parse_schedule_item(const char *string, struct schedule_item *item) { +static void parse_schedule_item(const char *string, struct schedule_item *item) +{ const char *after_hyph; - if (!strcmp(string,"forever")) { + if (!strcmp(string, "forever")) { item->type = sched_forever; } else if (isdigit(string[0])) { item->type = sched_timeout; if (parse_integer(string, &item->value) != 0) badusage("invalid timeout value in schedule"); - } else if ((after_hyph = string + (string[0] == '-')) && - parse_signal(after_hyph, &item->value) == 0) { + } else if ((after_hyph = string + (string[0] == '-')) + && parse_signal(after_hyph, &item->value) == 0) { item->type = sched_signal; } else { - badusage("invalid schedule item (must be [-], " - "-, or `forever'"); + badusage( + "invalid schedule item (must be [-], " + "-, or `forever'"); } } -static void -parse_schedule(const char *schedule_str) { +static void parse_schedule(const char *schedule_str) +{ char item_buf[20]; const char *slash; int count, repeatat; @@ -436,7 +423,7 @@ parse_schedule(const char *schedule_str) { if (*slash == '/') count++; - schedule_length = (count == 0) ? 4 : count+1; + schedule_length = (count == 0) ? 4 : count + 1; schedule = xmalloc(sizeof(*schedule) * schedule_length); if (count == 0) { @@ -444,30 +431,34 @@ parse_schedule(const char *schedule_str) { schedule[0].value = signal_nr; parse_schedule_item(schedule_str, &schedule[1]); if (schedule[1].type != sched_timeout) { - badusage ("--retry takes timeout, or schedule list" - " of at least two items"); + badusage( + "--retry takes timeout, or schedule list" + " of at least two items"); } schedule[2].type = sched_signal; schedule[2].value = SIGKILL; - schedule[3]= schedule[1]; + schedule[3] = schedule[1]; } else { count = 0; repeatat = -1; while (schedule_str != NULL) { - slash = strchr(schedule_str,'/'); - str_len = slash ? slash - schedule_str : (ptrdiff_t)strlen(schedule_str); + slash = strchr(schedule_str, '/'); + str_len = slash ? slash - schedule_str + : (ptrdiff_t)strlen(schedule_str); if (str_len >= (ptrdiff_t)sizeof(item_buf)) - badusage("invalid schedule item: far too long" - " (you must delimit items with slashes)"); + badusage( + "invalid schedule item: far too long" + " (you must delimit items with slashes)"); memcpy(item_buf, schedule_str, str_len); item_buf[str_len] = 0; - schedule_str = slash ? slash+1 : NULL; + schedule_str = slash ? slash + 1 : NULL; parse_schedule_item(item_buf, &schedule[count]); if (schedule[count].type == sched_forever) { if (repeatat >= 0) - badusage("invalid schedule: `forever'" - " appears more than once"); + badusage( + "invalid schedule: `forever'" + " appears more than once"); repeatat = count; continue; } @@ -482,91 +473,79 @@ parse_schedule(const char *schedule_str) { } } -static void -parse_options(int argc, char * const *argv) +static void parse_options(int argc, char *const *argv) { static struct option longopts[] = { - { "help", 0, NULL, 'H'}, - { "stop", 0, NULL, 'K'}, - { "start", 0, NULL, 'S'}, - { "version", 0, NULL, 'V'}, - { "startas", 1, NULL, 'a'}, - { "name", 1, NULL, 'n'}, - { "oknodo", 0, NULL, 'o'}, - { "pidfile", 1, NULL, 'p'}, - { "quiet", 0, NULL, 'q'}, - { "signal", 1, NULL, 's'}, - { "test", 0, NULL, 't'}, - { "user", 1, NULL, 'u'}, - { "chroot", 1, NULL, 'r'}, - { "namespace", 1, NULL, 'd'}, - { "verbose", 0, NULL, 'v'}, - { "exec", 1, NULL, 'x'}, - { "chuid", 1, NULL, 'c'}, - { "nicelevel", 1, NULL, 'N'}, - { "background", 0, NULL, 'b'}, - { "make-pidfile", 0, NULL, 'm'}, - { "retry", 1, NULL, 'R'}, - { NULL, 0, NULL, 0} - }; + {"help", 0, NULL, 'H'}, {"stop", 0, NULL, 'K'}, + {"start", 0, NULL, 'S'}, {"version", 0, NULL, 'V'}, + {"startas", 1, NULL, 'a'}, {"name", 1, NULL, 'n'}, + {"oknodo", 0, NULL, 'o'}, {"pidfile", 1, NULL, 'p'}, + {"quiet", 0, NULL, 'q'}, {"signal", 1, NULL, 's'}, + {"test", 0, NULL, 't'}, {"user", 1, NULL, 'u'}, + {"chroot", 1, NULL, 'r'}, {"namespace", 1, NULL, 'd'}, + {"verbose", 0, NULL, 'v'}, {"exec", 1, NULL, 'x'}, + {"chuid", 1, NULL, 'c'}, {"nicelevel", 1, NULL, 'N'}, + {"background", 0, NULL, 'b'}, {"make-pidfile", 0, NULL, 'm'}, + {"retry", 1, NULL, 'R'}, {NULL, 0, NULL, 0}}; int c; for (;;) { - c = getopt_long(argc, argv, "HKSVa:n:op:qr:d:s:tu:vx:c:N:bmR:", - longopts, (int *) 0); + c = getopt_long(argc, argv, + "HKSVa:n:op:qr:d:s:tu:vx:c:N:bmR:", longopts, + (int *)0); if (c == -1) break; switch (c) { - case 'H': /* --help */ + case 'H': /* --help */ do_help(); exit(0); - case 'K': /* --stop */ + case 'K': /* --stop */ stop = 1; break; - case 'S': /* --start */ + case 'S': /* --start */ start = 1; break; - case 'V': /* --version */ + case 'V': /* --version */ printf("start-stop-daemon " VERSION "\n"); exit(0); - case 'a': /* --startas */ + case 'a': /* --startas */ startas = optarg; break; - case 'n': /* --name */ + case 'n': /* --name */ cmdname = optarg; break; - case 'o': /* --oknodo */ + case 'o': /* --oknodo */ exitnodo = 0; break; - case 'p': /* --pidfile */ + case 'p': /* --pidfile */ pidfile = optarg; break; - case 'q': /* --quiet */ + case 'q': /* --quiet */ quietmode = 1; break; - case 's': /* --signal */ + case 's': /* --signal */ signal_str = optarg; break; - case 't': /* --test */ + case 't': /* --test */ testmode = 1; break; - case 'u': /* --user | */ + case 'u': /* --user | */ userspec = optarg; break; - case 'v': /* --verbose */ + case 'v': /* --verbose */ quietmode = -1; break; - case 'x': /* --exec */ + case 'x': /* --exec */ execname = optarg; break; - case 'c': /* --chuid | */ + case 'c': /* --chuid | */ /* we copy the string just in case we need the * argument later. */ changeuser = strdup(optarg); changeuser = strtok(changeuser, ":"); changegroup = strtok(NULL, ":"); break; - case 'r': /* --chroot /new/root */ + case 'r': /* --chroot /new/root */ changeroot = optarg; break; case 'd': /* --namespace /.../||/name */ @@ -574,27 +553,28 @@ parse_options(int argc, char * const *argv) add_namespace(optarg); #endif break; - case 'N': /* --nice */ + case 'N': /* --nice */ nicelevel = atoi(optarg); break; - case 'b': /* --background */ + case 'b': /* --background */ background = 1; break; - case 'm': /* --make-pidfile */ + case 'm': /* --make-pidfile */ mpidfile = 1; break; - case 'R': /* --retry | */ + case 'R': /* --retry | */ schedule_str = optarg; break; default: - badusage(NULL); /* message printed by getopt */ + badusage(NULL); /* message printed by getopt */ } } if (signal_str != NULL) { - if (parse_signal (signal_str, &signal_nr) != 0) - badusage("signal value must be numeric or name" - " of signal (KILL, INTR, ...)"); + if (parse_signal(signal_str, &signal_nr) != 0) + badusage( + "signal value must be numeric or name" + " of signal (KILL, INTR, ...)"); } if (schedule_str != NULL) { @@ -605,7 +585,8 @@ parse_options(int argc, char * const *argv) badusage("need one of --start or --stop"); if (!execname && !pidfile && !userspec && !cmdname) - badusage("need at least one of --exec, --pidfile, --user or --name"); + badusage( + "need at least one of --exec, --pidfile, --user or --name"); if (!startas) startas = execname; @@ -618,11 +599,9 @@ parse_options(int argc, char * const *argv) if (background && !start) badusage("--background is only relevant with --start"); - } -static int -pid_is_exec(pid_t pid, const struct stat *esb) +static int pid_is_exec(pid_t pid, const struct stat *esb) { struct stat sb; char buf[32]; @@ -634,8 +613,7 @@ pid_is_exec(pid_t pid, const struct stat *esb) } -static int -pid_is_user(pid_t pid, uid_t uid) +static int pid_is_user(pid_t pid, uid_t uid) { struct stat sb; char buf[32]; @@ -647,8 +625,7 @@ pid_is_user(pid_t pid, uid_t uid) } -static int -pid_is_cmd(pid_t pid, const char *name) +static int pid_is_cmd(pid_t pid, const char *name) { char buf[32]; FILE *f; @@ -672,8 +649,7 @@ pid_is_cmd(pid_t pid, const char *name) } -static void -check(pid_t pid) +static void check(pid_t pid) { if (execname && !pid_is_exec(pid, &exec_stat)) return; @@ -684,8 +660,7 @@ check(pid_t pid) push(&found, pid); } -static void -do_pidfile(const char *name) +static void do_pidfile(const char *name) { FILE *f; pid_t pid; @@ -697,13 +672,11 @@ do_pidfile(const char *name) fclose(f); } else if (errno != ENOENT) fatal("open pidfile %s: %s", name, strerror(errno)); - } /* WTA: this needs to be an autoconf check for /proc/pid existance. */ -static void -do_procinit(void) +static void do_procinit(void) { DIR *procdir; struct dirent *entry; @@ -726,11 +699,10 @@ do_procinit(void) fatal("nothing in /proc - not mounted?"); } -static void -do_findprocs(void) +static void do_findprocs(void) { clear(&found); - + if (pidfile) do_pidfile(pidfile); else @@ -738,57 +710,56 @@ do_findprocs(void) } /* return 1 on failure */ -static void -do_stop(int signal_nr, int quietmode, int *n_killed, int *n_notkilled, int retry_nr) +static void do_stop(int signal_nr, int quietmode, int *n_killed, + int *n_notkilled, int retry_nr) { struct pid_list *p; - do_findprocs(); - - *n_killed = 0; - *n_notkilled = 0; - - if (!found) - return; - - clear(&killed); + do_findprocs(); + + *n_killed = 0; + *n_notkilled = 0; + + if (!found) + return; + + clear(&killed); for (p = found; p; p = p->next) { if (testmode) - printf("Would send signal %d to %d.\n", - signal_nr, p->pid); - else if (kill(p->pid, signal_nr) == 0) { + printf("Would send signal %d to %d.\n", signal_nr, + p->pid); + else if (kill(p->pid, signal_nr) == 0) { push(&killed, p->pid); - (*n_killed)++; + (*n_killed)++; } else { - printf("%s: warning: failed to kill %d: %s\n", - progname, p->pid, strerror(errno)); - (*n_notkilled)++; + printf("%s: warning: failed to kill %d: %s\n", progname, + p->pid, strerror(errno)); + (*n_notkilled)++; } } if (quietmode < 0 && killed) { - printf("Stopped %s (pid", what_stop); + printf("Stopped %s (pid", what_stop); for (p = killed; p; p = p->next) printf(" %d", p->pid); - putchar(')'); - if (retry_nr > 0) - printf(", retry #%d", retry_nr); - printf(".\n"); + putchar(')'); + if (retry_nr > 0) + printf(", retry #%d", retry_nr); + printf(".\n"); } } -static void -set_what_stop(const char *str) +static void set_what_stop(const char *str) { strncpy(what_stop, str, sizeof(what_stop)); - what_stop[sizeof(what_stop)-1] = '\0'; + what_stop[sizeof(what_stop) - 1] = '\0'; } -static int -run_stop_schedule(void) +static int run_stop_schedule(void) { - int r, position, n_killed, n_notkilled, value, ratio, anykilled, retry_nr; + int r, position, n_killed, n_notkilled, value, ratio, anykilled, + retry_nr; struct timeval stopat, before, after, interval, maxinterval; if (testmode) { @@ -822,8 +793,8 @@ run_stop_schedule(void) goto x_finished; } - for (position = 0; position < schedule_length; ) { - value= schedule[position].value; + for (position = 0; position < schedule_length;) { + value = schedule[position].value; n_notkilled = 0; switch (schedule[position].type) { @@ -833,7 +804,8 @@ run_stop_schedule(void) continue; case sched_signal: - do_stop(value, quietmode, &n_killed, &n_notkilled, retry_nr++); + do_stop(value, quietmode, &n_killed, &n_notkilled, + retry_nr++); if (!n_killed) goto x_finished; else @@ -841,33 +813,48 @@ run_stop_schedule(void) goto next_item; case sched_timeout: - /* We want to keep polling for the processes, to see if they've exited, - * or until the timeout expires. - * - * This is a somewhat complicated algorithm to try to ensure that we - * notice reasonably quickly when all the processes have exited, but - * don't spend too much CPU time polling. In particular, on a fast - * machine with quick-exiting daemons we don't want to delay system - * shutdown too much, whereas on a slow one, or where processes are - * taking some time to exit, we want to increase the polling - * interval. - * - * The algorithm is as follows: we measure the elapsed time it takes - * to do one poll(), and wait a multiple of this time for the next - * poll. However, if that would put us past the end of the timeout - * period we wait only as long as the timeout period, but in any case - * we always wait at least MIN_POLL_INTERVAL (20ms). The multiple - * (`ratio') starts out as 2, and increases by 1 for each poll to a - * maximum of 10; so we use up to between 30% and 10% of the - * machine's resources (assuming a few reasonable things about system - * performance). - */ + /* We want to keep polling for the processes, to see if + * they've exited, + * or until the timeout expires. + * + * This is a somewhat complicated algorithm to try to + * ensure that we + * notice reasonably quickly when all the processes have + * exited, but + * don't spend too much CPU time polling. In + * particular, on a fast + * machine with quick-exiting daemons we don't want to + * delay system + * shutdown too much, whereas on a slow one, or where + * processes are + * taking some time to exit, we want to increase the + * polling + * interval. + * + * The algorithm is as follows: we measure the elapsed + * time it takes + * to do one poll(), and wait a multiple of this time + * for the next + * poll. However, if that would put us past the end of + * the timeout + * period we wait only as long as the timeout period, + * but in any case + * we always wait at least MIN_POLL_INTERVAL (20ms). + * The multiple + * (`ratio') starts out as 2, and increases by 1 for + * each poll to a + * maximum of 10; so we use up to between 30% and 10% of + * the + * machine's resources (assuming a few reasonable things + * about system + * performance). + */ xgettimeofday(&stopat); stopat.tv_sec += value; ratio = 1; for (;;) { xgettimeofday(&before); - if (timercmp(&before,&stopat,>)) + if (timercmp(&before, &stopat, >)) goto next_item; do_stop(0, 1, &n_killed, &n_notkilled, 0); @@ -876,23 +863,27 @@ run_stop_schedule(void) xgettimeofday(&after); - if (!timercmp(&after,&stopat,<)) + if (!timercmp(&after, &stopat, <)) goto next_item; if (ratio < 10) ratio++; - TVCALC(interval, ratio * (TVELEM(&after) - TVELEM(&before) + TVADJUST)); - TVCALC(maxinterval, TVELEM(&stopat) - TVELEM(&after) + TVADJUST); + TVCALC(interval, + ratio * (TVELEM(&after) - TVELEM(&before) + + TVADJUST)); + TVCALC(maxinterval, + TVELEM(&stopat) - TVELEM(&after) + + TVADJUST); - if (timercmp(&interval,&maxinterval,>)) + if (timercmp(&interval, &maxinterval, >)) interval = maxinterval; - if (interval.tv_sec == 0 && - interval.tv_usec <= MIN_POLL_INTERVAL) - interval.tv_usec = MIN_POLL_INTERVAL; + if (interval.tv_sec == 0 + && interval.tv_usec <= MIN_POLL_INTERVAL) + interval.tv_usec = MIN_POLL_INTERVAL; - r = select(0,0,0,0,&interval); + r = select(0, 0, 0, 0, &interval); if (r < 0 && errno != EINTR) fatal("select() failed for pause: %s", strerror(errno)); @@ -900,7 +891,6 @@ run_stop_schedule(void) default: assert(!"schedule[].type value must be valid"); - } next_item: @@ -916,7 +906,8 @@ run_stop_schedule(void) x_finished: if (!anykilled) { if (quietmode <= 0) - printf("No %s found running; none killed.\n", what_stop); + printf("No %s found running; none killed.\n", + what_stop); return exitnodo; } else { return 0; @@ -927,8 +918,7 @@ x_finished: int main(int argc, char **argv) NONRETURNING; */ -int -main(int argc, char **argv) +int main(int argc, char **argv) { progname = argv[0]; @@ -962,7 +952,8 @@ main(int argc, char **argv) if (!pw) fatal("user `%s' not found\n", changeuser); runas_uid = pw->pw_uid; - if (changegroup == NULL) { /* pass the default group of this user */ + if (changegroup + == NULL) { /* pass the default group of this user */ changegroup = ""; /* just empty */ runas_gid = pw->pw_gid; } @@ -987,7 +978,8 @@ main(int argc, char **argv) if (changeuser != NULL) { printf(" (as user %s[%d]", changeuser, runas_uid); if (changegroup != NULL) - printf(", and group %s[%d])", changegroup, runas_gid); + printf(", and group %s[%d])", changegroup, + runas_gid); else printf(")"); } @@ -1008,10 +1000,11 @@ main(int argc, char **argv) fatal("Unable to chroot() to %s", changeroot); } if (changeuser != NULL) { - if (setgid(runas_gid)) - fatal("Unable to set gid to %d", runas_gid); + if (setgid(runas_gid)) + fatal("Unable to set gid to %d", runas_gid); if (initgroups(changeuser, runas_gid)) - fatal("Unable to set initgroups() with gid %d", runas_gid); + fatal("Unable to set initgroups() with gid %d", + runas_gid); if (setuid(runas_uid)) fatal("Unable to set uid to %s", changeuser); } @@ -1021,7 +1014,7 @@ main(int argc, char **argv) if (quietmode < 0) printf("Detatching to start %s...", startas); i = fork(); - if (i<0) { + if (i < 0) { fatal("Unable to fork.\n"); } if (i) { /* parent */ @@ -1029,32 +1022,34 @@ main(int argc, char **argv) printf("done.\n"); exit(0); } - /* child continues here */ - /* now close all extra fds */ - for (i=getdtablesize()-1; i>=0; --i) close(i); - /* change tty */ + /* child continues here */ + /* now close all extra fds */ + for (i = getdtablesize() - 1; i >= 0; --i) + close(i); + /* change tty */ fd = open("/dev/tty", O_RDWR); ioctl(fd, TIOCNOTTY, 0); close(fd); chdir("/"); - umask(022); /* set a default for dumb programs */ - setpgid(0,0); /* set the process group */ - fd=open("/dev/null", O_RDWR); /* stdin */ - dup(fd); /* stdout */ - dup(fd); /* stderr */ + umask(022); /* set a default for dumb programs */ + setpgid(0, 0); /* set the process group */ + fd = open("/dev/null", O_RDWR); /* stdin */ + dup(fd); /* stdout */ + dup(fd); /* stderr */ } if (nicelevel) { errno = 0; if (nice(nicelevel) < 0 && errno) fatal("Unable to alter nice level by %i: %s", nicelevel, - strerror(errno)); + strerror(errno)); } - if (mpidfile && pidfile != NULL) { /* user wants _us_ to make the pidfile :) */ + if (mpidfile + && pidfile != NULL) { /* user wants _us_ to make the pidfile :) */ FILE *pidf = fopen(pidfile, "w"); pid_t pidt = getpid(); if (pidf == NULL) - fatal("Unable to open pidfile `%s' for writing: %s", pidfile, - strerror(errno)); + fatal("Unable to open pidfile `%s' for writing: %s", + pidfile, strerror(errno)); fprintf(pidf, "%d\n", pidt); fclose(pidf); } diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index ec8a365c3..666f3049d 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -53,792 +53,764 @@ struct vty *vty; char *vtysh_pager_name = NULL; /* VTY shell client structure. */ -struct vtysh_client -{ - int fd; - const char *name; - int flag; - char path[MAXPATHLEN]; - struct vtysh_client *next; +struct vtysh_client { + int fd; + const char *name; + int flag; + char path[MAXPATHLEN]; + struct vtysh_client *next; }; -struct vtysh_client vtysh_client[] = -{ - { .fd = -1, .name = "zebra", .flag = VTYSH_ZEBRA, .next = NULL}, - { .fd = -1, .name = "ripd", .flag = VTYSH_RIPD, .next = NULL}, - { .fd = -1, .name = "ripngd", .flag = VTYSH_RIPNGD, .next = NULL}, - { .fd = -1, .name = "ospfd", .flag = VTYSH_OSPFD, .next = NULL}, - { .fd = -1, .name = "ospf6d", .flag = VTYSH_OSPF6D, .next = NULL}, - { .fd = -1, .name = "ldpd", .flag = VTYSH_LDPD, .next = NULL}, - { .fd = -1, .name = "bgpd", .flag = VTYSH_BGPD, .next = NULL}, - { .fd = -1, .name = "isisd", .flag = VTYSH_ISISD, .next = NULL}, - { .fd = -1, .name = "pimd", .flag = VTYSH_PIMD, .next = NULL}, - { .fd = -1, .name = "nhrpd", .flag = VTYSH_NHRPD, .next = NULL}, - { .fd = -1, .name = "eigrpd", .flag = VTYSH_EIGRPD, .next = NULL}, - { .fd = -1, .name = "babeld", .flag = VTYSH_BABELD, .next = NULL}, - { .fd = -1, .name = "watchfrr", .flag = VTYSH_WATCHFRR, .next = NULL}, +struct vtysh_client vtysh_client[] = { + {.fd = -1, .name = "zebra", .flag = VTYSH_ZEBRA, .next = NULL}, + {.fd = -1, .name = "ripd", .flag = VTYSH_RIPD, .next = NULL}, + {.fd = -1, .name = "ripngd", .flag = VTYSH_RIPNGD, .next = NULL}, + {.fd = -1, .name = "ospfd", .flag = VTYSH_OSPFD, .next = NULL}, + {.fd = -1, .name = "ospf6d", .flag = VTYSH_OSPF6D, .next = NULL}, + {.fd = -1, .name = "ldpd", .flag = VTYSH_LDPD, .next = NULL}, + {.fd = -1, .name = "bgpd", .flag = VTYSH_BGPD, .next = NULL}, + {.fd = -1, .name = "isisd", .flag = VTYSH_ISISD, .next = NULL}, + {.fd = -1, .name = "pimd", .flag = VTYSH_PIMD, .next = NULL}, + {.fd = -1, .name = "nhrpd", .flag = VTYSH_NHRPD, .next = NULL}, + {.fd = -1, .name = "eigrpd", .flag = VTYSH_EIGRPD, .next = NULL}, + {.fd = -1, .name = "babeld", .flag = VTYSH_BABELD, .next = NULL}, + {.fd = -1, .name = "watchfrr", .flag = VTYSH_WATCHFRR, .next = NULL}, }; -enum vtysh_write_integrated vtysh_write_integrated = WRITE_INTEGRATED_UNSPECIFIED; +enum vtysh_write_integrated vtysh_write_integrated = + WRITE_INTEGRATED_UNSPECIFIED; -static void -vclient_close (struct vtysh_client *vclient) +static void vclient_close(struct vtysh_client *vclient) { - if (vclient->fd >= 0) - { - fprintf(stderr, - "Warning: closing connection to %s because of an I/O error!\n", - vclient->name); - close (vclient->fd); - vclient->fd = -1; - } + if (vclient->fd >= 0) { + fprintf(stderr, + "Warning: closing connection to %s because of an I/O error!\n", + vclient->name); + close(vclient->fd); + vclient->fd = -1; + } } /* Return true if str begins with prefix, else return false */ -static int -begins_with(const char *str, const char *prefix) -{ - if (!str || !prefix) - return 0; - size_t lenstr = strlen(str); - size_t lenprefix = strlen(prefix); - if (lenprefix > lenstr) - return 0; - return strncmp(str, prefix, lenprefix) == 0; -} - -static int -vtysh_client_run (struct vtysh_client *vclient, const char *line, FILE *fp, - void (*callback)(void *, const char *), void *cbarg) -{ - int ret; - char stackbuf[4096]; - char *buf = stackbuf; - size_t bufsz = sizeof(stackbuf); - char *bufvalid, *end = NULL; - char terminator[3] = {0, 0, 0}; - - if (vclient->fd < 0) - return CMD_SUCCESS; - - ret = write (vclient->fd, line, strlen (line) + 1); - if (ret <= 0) - goto out_err; - - bufvalid = buf; - do - { - ssize_t nread = read (vclient->fd, bufvalid, buf + bufsz - bufvalid); - - if (nread < 0 && (errno == EINTR || errno == EAGAIN)) - continue; - - if (nread <= 0) - { - fprintf (stderr, "vtysh: error reading from %s: %s (%d)", - vclient->name, safe_strerror(errno), errno); - goto out_err; - } - - bufvalid += nread; - - end = memmem (buf, bufvalid - buf, terminator, sizeof(terminator)); - if (end + sizeof(terminator) + 1 > bufvalid) - /* found \0\0\0 but return code hasn't been read yet */ - end = NULL; - if (end) - ret = end[sizeof(terminator)]; - - while (bufvalid > buf && (end > buf || !end)) - { - size_t textlen = (end ? end : bufvalid) - buf; - char *eol = memchr (buf, '\n', textlen); - if (eol) - /* line break */ - *eol++ = '\0'; - else if (end == buf) - /* no line break, end of input, no text left before end - * => don't insert an empty line at the end */ - break; - else if (end) - /* no line break, end of input, but some text left */ - eol = end; - else - /* continue reading */ - break; - - /* eol is at a line end now, either \n => \0 or \0\0\0 */ - assert(eol && eol <= bufvalid); - - if (fp) - { - fputs (buf, fp); - fputc ('\n', fp); - } - if (callback) - callback(cbarg, buf); - - if (eol == end) - /* \n\0\0\0 */ - break; - - memmove (buf, eol, bufvalid - eol); - bufvalid -= eol - buf; - if (end) - end -= eol - buf; - } - - if (bufvalid == buf + bufsz) - { - char *new; - bufsz *= 2; - if (buf == stackbuf) - { - new = XMALLOC (MTYPE_TMP, bufsz); - memcpy (new, stackbuf, sizeof(stackbuf)); - } - else - new = XREALLOC (MTYPE_TMP, buf, bufsz); - - bufvalid = bufvalid - buf + new; - buf = new; - /* if end != NULL, we won't be reading more data... */ - assert (end == NULL); - } - } - while (!end); - goto out; +static int begins_with(const char *str, const char *prefix) +{ + if (!str || !prefix) + return 0; + size_t lenstr = strlen(str); + size_t lenprefix = strlen(prefix); + if (lenprefix > lenstr) + return 0; + return strncmp(str, prefix, lenprefix) == 0; +} + +static int vtysh_client_run(struct vtysh_client *vclient, const char *line, + FILE *fp, void (*callback)(void *, const char *), + void *cbarg) +{ + int ret; + char stackbuf[4096]; + char *buf = stackbuf; + size_t bufsz = sizeof(stackbuf); + char *bufvalid, *end = NULL; + char terminator[3] = {0, 0, 0}; + + if (vclient->fd < 0) + return CMD_SUCCESS; + + ret = write(vclient->fd, line, strlen(line) + 1); + if (ret <= 0) + goto out_err; + + bufvalid = buf; + do { + ssize_t nread = + read(vclient->fd, bufvalid, buf + bufsz - bufvalid); + + if (nread < 0 && (errno == EINTR || errno == EAGAIN)) + continue; + + if (nread <= 0) { + fprintf(stderr, "vtysh: error reading from %s: %s (%d)", + vclient->name, safe_strerror(errno), errno); + goto out_err; + } + + bufvalid += nread; + + end = memmem(buf, bufvalid - buf, terminator, + sizeof(terminator)); + if (end + sizeof(terminator) + 1 > bufvalid) + /* found \0\0\0 but return code hasn't been read yet */ + end = NULL; + if (end) + ret = end[sizeof(terminator)]; + + while (bufvalid > buf && (end > buf || !end)) { + size_t textlen = (end ? end : bufvalid) - buf; + char *eol = memchr(buf, '\n', textlen); + if (eol) + /* line break */ + *eol++ = '\0'; + else if (end == buf) + /* no line break, end of input, no text left + * before end + * => don't insert an empty line at the end */ + break; + else if (end) + /* no line break, end of input, but some text + * left */ + eol = end; + else + /* continue reading */ + break; + + /* eol is at a line end now, either \n => \0 or \0\0\0 + */ + assert(eol && eol <= bufvalid); + + if (fp) { + fputs(buf, fp); + fputc('\n', fp); + } + if (callback) + callback(cbarg, buf); + + if (eol == end) + /* \n\0\0\0 */ + break; + + memmove(buf, eol, bufvalid - eol); + bufvalid -= eol - buf; + if (end) + end -= eol - buf; + } + + if (bufvalid == buf + bufsz) { + char *new; + bufsz *= 2; + if (buf == stackbuf) { + new = XMALLOC(MTYPE_TMP, bufsz); + memcpy(new, stackbuf, sizeof(stackbuf)); + } else + new = XREALLOC(MTYPE_TMP, buf, bufsz); + + bufvalid = bufvalid - buf + new; + buf = new; + /* if end != NULL, we won't be reading more data... */ + assert(end == NULL); + } + } while (!end); + goto out; out_err: - vclient_close (vclient); - ret = CMD_SUCCESS; + vclient_close(vclient); + ret = CMD_SUCCESS; out: - if (buf != stackbuf) - XFREE (MTYPE_TMP, buf); - return ret; + if (buf != stackbuf) + XFREE(MTYPE_TMP, buf); + return ret; } -static int -vtysh_client_run_all (struct vtysh_client *head_client, const char *line, - int continue_on_err, FILE *fp, - void (*callback)(void *, const char *), void *cbarg) +static int vtysh_client_run_all(struct vtysh_client *head_client, + const char *line, int continue_on_err, FILE *fp, + void (*callback)(void *, const char *), + void *cbarg) { - struct vtysh_client *client; - int rc, rc_all = CMD_SUCCESS; + struct vtysh_client *client; + int rc, rc_all = CMD_SUCCESS; - for (client = head_client; client; client = client->next) - { - rc = vtysh_client_run(client, line, fp, callback, cbarg); - if (rc != CMD_SUCCESS) - { - if (!continue_on_err) - return rc; - rc_all = rc; - } - } - return rc_all; + for (client = head_client; client; client = client->next) { + rc = vtysh_client_run(client, line, fp, callback, cbarg); + if (rc != CMD_SUCCESS) { + if (!continue_on_err) + return rc; + rc_all = rc; + } + } + return rc_all; } -static int -vtysh_client_execute (struct vtysh_client *head_client, const char *line, - FILE *fp) +static int vtysh_client_execute(struct vtysh_client *head_client, + const char *line, FILE *fp) { - return vtysh_client_run_all (head_client, line, 0, fp, NULL, NULL); + return vtysh_client_run_all(head_client, line, 0, fp, NULL, NULL); } -static void -vtysh_client_config (struct vtysh_client *head_client, char *line) +static void vtysh_client_config(struct vtysh_client *head_client, char *line) { - vtysh_client_run_all (head_client, line, 1, NULL, vtysh_config_parse_line, NULL); + vtysh_client_run_all(head_client, line, 1, NULL, + vtysh_config_parse_line, NULL); } -void -vtysh_pager_init (void) +void vtysh_pager_init(void) { - char *pager_defined; + char *pager_defined; - pager_defined = getenv ("VTYSH_PAGER"); + pager_defined = getenv("VTYSH_PAGER"); - if (pager_defined) - vtysh_pager_name = strdup (pager_defined); - else - vtysh_pager_name = strdup (VTYSH_PAGER); + if (pager_defined) + vtysh_pager_name = strdup(pager_defined); + else + vtysh_pager_name = strdup(VTYSH_PAGER); } /* Command execution over the vty interface. */ -static int -vtysh_execute_func (const char *line, int pager) -{ - int ret, cmd_stat; - u_int i; - vector vline; - const struct cmd_element *cmd; - FILE *fp = NULL; - int closepager = 0; - int tried = 0; - int saved_ret, saved_node; - - /* Split readline string up into the vector. */ - vline = cmd_make_strvec (line); - - if (vline == NULL) - return CMD_SUCCESS; - - saved_ret = ret = cmd_execute_command (vline, vty, &cmd, 1); - saved_node = vty->node; - - /* If command doesn't succeeded in current node, try to walk up in node tree. - * Changing vty->node is enough to try it just out without actual walkup in - * the vtysh. */ - while (ret != CMD_SUCCESS && ret != CMD_SUCCESS_DAEMON && ret != CMD_WARNING - && ret != CMD_WARNING_CONFIG_FAILED - && vty->node > CONFIG_NODE) - { - vty->node = node_parent(vty->node); - ret = cmd_execute_command (vline, vty, &cmd, 1); - tried++; - } - - vty->node = saved_node; - - /* If command succeeded in any other node than current (tried > 0) we have - * to move into node in the vtysh where it succeeded. */ - if (ret == CMD_SUCCESS || ret == CMD_SUCCESS_DAEMON || ret == CMD_WARNING) - { - if ((saved_node == BGP_VPNV4_NODE || saved_node == BGP_VPNV6_NODE - || saved_node == BGP_IPV4_NODE - || saved_node == BGP_IPV6_NODE || saved_node == BGP_IPV4M_NODE - || saved_node == BGP_IPV4L_NODE || saved_node == BGP_IPV6L_NODE - || saved_node == BGP_IPV6M_NODE || saved_node == BGP_EVPN_NODE) - && (tried == 1)) - { - vtysh_execute("exit-address-family"); - } - else if ((saved_node == BGP_EVPN_VNI_NODE) && (tried == 1)) - { - vtysh_execute("exit-vni"); - } - else if (saved_node == BGP_VRF_POLICY_NODE && (tried == 1)) - { - vtysh_execute("exit-vrf-policy"); - } - else if ((saved_node == BGP_VNC_DEFAULTS_NODE - || saved_node == BGP_VNC_NVE_GROUP_NODE - || saved_node == BGP_VNC_L2_GROUP_NODE) && (tried == 1)) - { - vtysh_execute("exit-vnc"); +static int vtysh_execute_func(const char *line, int pager) +{ + int ret, cmd_stat; + u_int i; + vector vline; + const struct cmd_element *cmd; + FILE *fp = NULL; + int closepager = 0; + int tried = 0; + int saved_ret, saved_node; + + /* Split readline string up into the vector. */ + vline = cmd_make_strvec(line); + + if (vline == NULL) + return CMD_SUCCESS; + + saved_ret = ret = cmd_execute_command(vline, vty, &cmd, 1); + saved_node = vty->node; + + /* If command doesn't succeeded in current node, try to walk up in node + * tree. + * Changing vty->node is enough to try it just out without actual walkup + * in + * the vtysh. */ + while (ret != CMD_SUCCESS && ret != CMD_SUCCESS_DAEMON + && ret != CMD_WARNING && ret != CMD_WARNING_CONFIG_FAILED + && vty->node > CONFIG_NODE) { + vty->node = node_parent(vty->node); + ret = cmd_execute_command(vline, vty, &cmd, 1); + tried++; } - else if ((saved_node == KEYCHAIN_KEY_NODE - || saved_node == LDP_PSEUDOWIRE_NODE - || saved_node == LDP_IPV4_IFACE_NODE - || saved_node == LDP_IPV6_IFACE_NODE) - && (tried == 1)) - { - vtysh_execute("exit"); + + vty->node = saved_node; + + /* If command succeeded in any other node than current (tried > 0) we + * have + * to move into node in the vtysh where it succeeded. */ + if (ret == CMD_SUCCESS || ret == CMD_SUCCESS_DAEMON + || ret == CMD_WARNING) { + if ((saved_node == BGP_VPNV4_NODE + || saved_node == BGP_VPNV6_NODE + || saved_node == BGP_IPV4_NODE + || saved_node == BGP_IPV6_NODE + || saved_node == BGP_IPV4M_NODE + || saved_node == BGP_IPV4L_NODE + || saved_node == BGP_IPV6L_NODE + || saved_node == BGP_IPV6M_NODE + || saved_node == BGP_EVPN_NODE) + && (tried == 1)) { + vtysh_execute("exit-address-family"); + } else if ((saved_node == BGP_EVPN_VNI_NODE) && (tried == 1)) { + vtysh_execute("exit-vni"); + } else if (saved_node == BGP_VRF_POLICY_NODE && (tried == 1)) { + vtysh_execute("exit-vrf-policy"); + } else if ((saved_node == BGP_VNC_DEFAULTS_NODE + || saved_node == BGP_VNC_NVE_GROUP_NODE + || saved_node == BGP_VNC_L2_GROUP_NODE) + && (tried == 1)) { + vtysh_execute("exit-vnc"); + } else if ((saved_node == KEYCHAIN_KEY_NODE + || saved_node == LDP_PSEUDOWIRE_NODE + || saved_node == LDP_IPV4_IFACE_NODE + || saved_node == LDP_IPV6_IFACE_NODE) + && (tried == 1)) { + vtysh_execute("exit"); + } else if (tried) { + vtysh_execute("end"); + vtysh_execute("configure terminal"); + } } - else if (tried) - { - vtysh_execute ("end"); - vtysh_execute ("configure terminal"); + /* If command didn't succeed in any node, continue with return value + * from + * first try. */ + else if (tried) { + ret = saved_ret; } - } - /* If command didn't succeed in any node, continue with return value from - * first try. */ - else if (tried) - { - ret = saved_ret; - } - - cmd_free_strvec (vline); - - cmd_stat = ret; - switch (ret) - { - case CMD_WARNING: - case CMD_WARNING_CONFIG_FAILED: - if (vty->type == VTY_FILE) - fprintf (stdout,"Warning...\n"); - break; - case CMD_ERR_AMBIGUOUS: - fprintf (stdout,"%% Ambiguous command.\n"); - break; - case CMD_ERR_NO_MATCH: - fprintf (stdout,"%% Unknown command.\n"); - break; - case CMD_ERR_INCOMPLETE: - fprintf (stdout,"%% Command incomplete.\n"); - break; - case CMD_SUCCESS_DAEMON: - { - /* FIXME: Don't open pager for exit commands. popen() causes problems - * if exited from vtysh at all. This hack shouldn't cause any problem - * but is really ugly. */ - if (pager && vtysh_pager_name && (strncmp(line, "exit", 4) != 0)) - { - fp = popen (vtysh_pager_name, "w"); - if (fp == NULL) - { - perror ("popen failed for pager"); - fp = stdout; - } - else - closepager=1; - } - else - fp = stdout; - - if (! strcmp(cmd->string,"configure terminal")) - { - for (i = 0; i < array_size(vtysh_client); i++) - { - cmd_stat = vtysh_client_execute(&vtysh_client[i], line, fp); - if (cmd_stat == CMD_WARNING) - break; - } - - if (cmd_stat) - { - line = "end"; - vline = cmd_make_strvec (line); - if (vline == NULL) - { - if (pager && vtysh_pager_name && fp && closepager) - { - if (pclose (fp) == -1) - { - perror ("pclose failed for pager"); - } - fp = NULL; - } - return CMD_SUCCESS; - } - - ret = cmd_execute_command (vline, vty, &cmd, 1); - cmd_free_strvec (vline); - if (ret != CMD_SUCCESS_DAEMON) - break; - } - else - if (cmd->func) - { - (*cmd->func) (cmd, vty, 0, NULL); - break; + cmd_free_strvec(vline); + + cmd_stat = ret; + switch (ret) { + case CMD_WARNING: + case CMD_WARNING_CONFIG_FAILED: + if (vty->type == VTY_FILE) + fprintf(stdout, "Warning...\n"); + break; + case CMD_ERR_AMBIGUOUS: + fprintf(stdout, "%% Ambiguous command.\n"); + break; + case CMD_ERR_NO_MATCH: + fprintf(stdout, "%% Unknown command.\n"); + break; + case CMD_ERR_INCOMPLETE: + fprintf(stdout, "%% Command incomplete.\n"); + break; + case CMD_SUCCESS_DAEMON: { + /* FIXME: Don't open pager for exit commands. popen() causes + * problems + * if exited from vtysh at all. This hack shouldn't cause any + * problem + * but is really ugly. */ + if (pager && vtysh_pager_name + && (strncmp(line, "exit", 4) != 0)) { + fp = popen(vtysh_pager_name, "w"); + if (fp == NULL) { + perror("popen failed for pager"); + fp = stdout; + } else + closepager = 1; + } else + fp = stdout; + + if (!strcmp(cmd->string, "configure terminal")) { + for (i = 0; i < array_size(vtysh_client); i++) { + cmd_stat = vtysh_client_execute( + &vtysh_client[i], line, fp); + if (cmd_stat == CMD_WARNING) + break; + } + + if (cmd_stat) { + line = "end"; + vline = cmd_make_strvec(line); + + if (vline == NULL) { + if (pager && vtysh_pager_name && fp + && closepager) { + if (pclose(fp) == -1) { + perror("pclose failed for pager"); + } + fp = NULL; + } + return CMD_SUCCESS; + } + + ret = cmd_execute_command(vline, vty, &cmd, 1); + cmd_free_strvec(vline); + if (ret != CMD_SUCCESS_DAEMON) + break; + } else if (cmd->func) { + (*cmd->func)(cmd, vty, 0, NULL); + break; + } } - } - cmd_stat = CMD_SUCCESS; - for (i = 0; i < array_size(vtysh_client); i++) - { - if (cmd->daemon & vtysh_client[i].flag) - { - cmd_stat = vtysh_client_execute(&vtysh_client[i], line, fp); + cmd_stat = CMD_SUCCESS; + for (i = 0; i < array_size(vtysh_client); i++) { + if (cmd->daemon & vtysh_client[i].flag) { + cmd_stat = vtysh_client_execute( + &vtysh_client[i], line, fp); + if (cmd_stat != CMD_SUCCESS) + break; + } + } if (cmd_stat != CMD_SUCCESS) - break; - } - } - if (cmd_stat != CMD_SUCCESS) - break; - - if (cmd->func) - (*cmd->func) (cmd, vty, 0, NULL); - } - } - if (pager && vtysh_pager_name && fp && closepager) - { - if (pclose (fp) == -1) - { - perror ("pclose failed for pager"); + break; + + if (cmd->func) + (*cmd->func)(cmd, vty, 0, NULL); + } } - fp = NULL; - } - return cmd_stat; + if (pager && vtysh_pager_name && fp && closepager) { + if (pclose(fp) == -1) { + perror("pclose failed for pager"); + } + fp = NULL; + } + return cmd_stat; } -int -vtysh_execute_no_pager (const char *line) +int vtysh_execute_no_pager(const char *line) { - return vtysh_execute_func (line, 0); + return vtysh_execute_func(line, 0); } -int -vtysh_execute (const char *line) +int vtysh_execute(const char *line) { - return vtysh_execute_func (line, 1); + return vtysh_execute_func(line, 1); } -static char * -trim (char *s) +static char *trim(char *s) { - size_t size; - char *end; + size_t size; + char *end; - size = strlen(s); + size = strlen(s); - if (!size) - return s; + if (!size) + return s; - end = s + size - 1; - while (end >= s && isspace(*end)) - end--; - *(end + 1) = '\0'; + end = s + size - 1; + while (end >= s && isspace(*end)) + end--; + *(end + 1) = '\0'; - while (*s && isspace(*s)) - s++; + while (*s && isspace(*s)) + s++; - return s; + return s; } -int -vtysh_mark_file (const char *filename) +int vtysh_mark_file(const char *filename) { - struct vty *vty; - FILE *confp = NULL; - int ret; - vector vline; - int tried = 0; - const struct cmd_element *cmd; - int saved_ret, prev_node; - int lineno = 0; - char *vty_buf_copy = NULL; - char *vty_buf_trimmed = NULL; + struct vty *vty; + FILE *confp = NULL; + int ret; + vector vline; + int tried = 0; + const struct cmd_element *cmd; + int saved_ret, prev_node; + int lineno = 0; + char *vty_buf_copy = NULL; + char *vty_buf_trimmed = NULL; - if (strncmp("-", filename, 1) == 0) - confp = stdin; - else - confp = fopen (filename, "r"); + if (strncmp("-", filename, 1) == 0) + confp = stdin; + else + confp = fopen(filename, "r"); - if (confp == NULL) - { - fprintf (stderr, "%% Can't open config file %s due to '%s'.\n", - filename, safe_strerror (errno)); - return (CMD_ERR_NO_FILE); - } + if (confp == NULL) { + fprintf(stderr, "%% Can't open config file %s due to '%s'.\n", + filename, safe_strerror(errno)); + return (CMD_ERR_NO_FILE); + } - vty = vty_new (); - vty->fd = 0; /* stdout */ - vty->type = VTY_TERM; - vty->node = CONFIG_NODE; + vty = vty_new(); + vty->fd = 0; /* stdout */ + vty->type = VTY_TERM; + vty->node = CONFIG_NODE; - vtysh_execute_no_pager ("enable"); - vtysh_execute_no_pager ("configure terminal"); - vty_buf_copy = XCALLOC (MTYPE_VTYSH_CMD, VTY_BUFSIZ); + vtysh_execute_no_pager("enable"); + vtysh_execute_no_pager("configure terminal"); + vty_buf_copy = XCALLOC(MTYPE_VTYSH_CMD, VTY_BUFSIZ); - while (fgets (vty->buf, VTY_BUFSIZ, confp)) - { - lineno++; - tried = 0; - strcpy(vty_buf_copy, vty->buf); - vty_buf_trimmed = trim(vty_buf_copy); + while (fgets(vty->buf, VTY_BUFSIZ, confp)) { + lineno++; + tried = 0; + strcpy(vty_buf_copy, vty->buf); + vty_buf_trimmed = trim(vty_buf_copy); - if (vty_buf_trimmed[0] == '!' || vty_buf_trimmed[0] == '#') - { - fprintf(stdout, "%s", vty->buf); - continue; - } + if (vty_buf_trimmed[0] == '!' || vty_buf_trimmed[0] == '#') { + fprintf(stdout, "%s", vty->buf); + continue; + } - /* Split readline string up into the vector. */ - vline = cmd_make_strvec (vty->buf); + /* Split readline string up into the vector. */ + vline = cmd_make_strvec(vty->buf); - if (vline == NULL) - { - fprintf(stdout, "%s", vty->buf); - continue; - } + if (vline == NULL) { + fprintf(stdout, "%s", vty->buf); + continue; + } - /* Ignore the "end" lines, we will generate these where appropriate */ - if (strlen(vty_buf_trimmed) == 3 && strncmp("end", vty_buf_trimmed, 3) == 0) - { - continue; - } - - prev_node = vty->node; - saved_ret = ret = cmd_execute_command_strict (vline, vty, &cmd); - - /* If command doesn't succeeded in current node, try to walk up in node tree. - * Changing vty->node is enough to try it just out without actual walkup in - * the vtysh. */ - while (ret != CMD_SUCCESS && ret != CMD_SUCCESS_DAEMON && ret != CMD_WARNING - && ret != CMD_WARNING_CONFIG_FAILED - && vty->node > CONFIG_NODE) - { - vty->node = node_parent(vty->node); - ret = cmd_execute_command_strict (vline, vty, &cmd); - tried++; - } + /* Ignore the "end" lines, we will generate these where + * appropriate */ + if (strlen(vty_buf_trimmed) == 3 + && strncmp("end", vty_buf_trimmed, 3) == 0) { + continue; + } - /* If command succeeded in any other node than current (tried > 0) we have - * to move into node in the vtysh where it succeeded. */ - if (ret == CMD_SUCCESS || ret == CMD_SUCCESS_DAEMON || ret == CMD_WARNING) - { - if ((prev_node == BGP_VPNV4_NODE || prev_node == BGP_VPNV6_NODE - || prev_node == BGP_IPV4_NODE || prev_node == BGP_IPV6_NODE - || prev_node == BGP_IPV4L_NODE || prev_node == BGP_IPV6L_NODE - || prev_node == BGP_IPV4M_NODE || prev_node == BGP_IPV6M_NODE - || prev_node == BGP_EVPN_NODE) - && (tried == 1)) - { - fprintf(stdout, "exit-address-family\n"); - } - else if ((prev_node == BGP_EVPN_VNI_NODE) && (tried == 1)) - { - fprintf(stdout, "exit-vni\n"); - } - else if ((prev_node == KEYCHAIN_KEY_NODE) && (tried == 1)) - { - fprintf(stdout, "exit\n"); - } - else if (tried) - { - fprintf(stdout, "end\n"); - } - } - /* If command didn't succeed in any node, continue with return value from - * first try. */ - else if (tried) - { - ret = saved_ret; - vty->node = prev_node; - } + prev_node = vty->node; + saved_ret = ret = cmd_execute_command_strict(vline, vty, &cmd); + + /* If command doesn't succeeded in current node, try to walk up + * in node tree. + * Changing vty->node is enough to try it just out without + * actual walkup in + * the vtysh. */ + while (ret != CMD_SUCCESS && ret != CMD_SUCCESS_DAEMON + && ret != CMD_WARNING && ret != CMD_WARNING_CONFIG_FAILED + && vty->node > CONFIG_NODE) { + vty->node = node_parent(vty->node); + ret = cmd_execute_command_strict(vline, vty, &cmd); + tried++; + } - cmd_free_strvec (vline); - switch (ret) - { - case CMD_WARNING: - case CMD_WARNING_CONFIG_FAILED: - if (vty->type == VTY_FILE) - fprintf (stderr,"line %d: Warning...: %s\n", lineno, vty->buf); - fclose(confp); - vty_close(vty); - XFREE(MTYPE_VTYSH_CMD, vty_buf_copy); - return ret; - case CMD_ERR_AMBIGUOUS: - fprintf (stderr,"line %d: %% Ambiguous command: %s\n", lineno, vty->buf); - fclose(confp); - vty_close(vty); - XFREE(MTYPE_VTYSH_CMD, vty_buf_copy); - return CMD_ERR_AMBIGUOUS; - case CMD_ERR_NO_MATCH: - fprintf (stderr,"line %d: %% Unknown command: %s\n", lineno, vty->buf); - fclose(confp); - vty_close(vty); - XFREE(MTYPE_VTYSH_CMD, vty_buf_copy); - return CMD_ERR_NO_MATCH; - case CMD_ERR_INCOMPLETE: - fprintf (stderr,"line %d: %% Command incomplete: %s\n", lineno, vty->buf); - fclose(confp); - vty_close(vty); - XFREE(MTYPE_VTYSH_CMD, vty_buf_copy); - return CMD_ERR_INCOMPLETE; - case CMD_SUCCESS: - fprintf(stdout, "%s", vty->buf); - break; - case CMD_SUCCESS_DAEMON: - { - u_int i; - int cmd_stat = CMD_SUCCESS; - - fprintf(stdout, "%s", vty->buf); - for (i = 0; i < array_size(vtysh_client); i++) - { - if (cmd->daemon & vtysh_client[i].flag) - { - cmd_stat = vtysh_client_execute (&vtysh_client[i], - vty->buf, stdout); - if (cmd_stat != CMD_SUCCESS) - break; - } - } - if (cmd_stat != CMD_SUCCESS) - break; - - if (cmd->func) - (*cmd->func) (cmd, vty, 0, NULL); - } + /* If command succeeded in any other node than current (tried > + * 0) we have + * to move into node in the vtysh where it succeeded. */ + if (ret == CMD_SUCCESS || ret == CMD_SUCCESS_DAEMON + || ret == CMD_WARNING) { + if ((prev_node == BGP_VPNV4_NODE + || prev_node == BGP_VPNV6_NODE + || prev_node == BGP_IPV4_NODE + || prev_node == BGP_IPV6_NODE + || prev_node == BGP_IPV4L_NODE + || prev_node == BGP_IPV6L_NODE + || prev_node == BGP_IPV4M_NODE + || prev_node == BGP_IPV6M_NODE + || prev_node == BGP_EVPN_NODE) + && (tried == 1)) { + fprintf(stdout, "exit-address-family\n"); + } else if ((prev_node == BGP_EVPN_VNI_NODE) + && (tried == 1)) { + fprintf(stdout, "exit-vni\n"); + } else if ((prev_node == KEYCHAIN_KEY_NODE) + && (tried == 1)) { + fprintf(stdout, "exit\n"); + } else if (tried) { + fprintf(stdout, "end\n"); + } + } + /* If command didn't succeed in any node, continue with return + * value from + * first try. */ + else if (tried) { + ret = saved_ret; + vty->node = prev_node; + } + + cmd_free_strvec(vline); + switch (ret) { + case CMD_WARNING: + case CMD_WARNING_CONFIG_FAILED: + if (vty->type == VTY_FILE) + fprintf(stderr, "line %d: Warning...: %s\n", + lineno, vty->buf); + fclose(confp); + vty_close(vty); + XFREE(MTYPE_VTYSH_CMD, vty_buf_copy); + return ret; + case CMD_ERR_AMBIGUOUS: + fprintf(stderr, "line %d: %% Ambiguous command: %s\n", + lineno, vty->buf); + fclose(confp); + vty_close(vty); + XFREE(MTYPE_VTYSH_CMD, vty_buf_copy); + return CMD_ERR_AMBIGUOUS; + case CMD_ERR_NO_MATCH: + fprintf(stderr, "line %d: %% Unknown command: %s\n", + lineno, vty->buf); + fclose(confp); + vty_close(vty); + XFREE(MTYPE_VTYSH_CMD, vty_buf_copy); + return CMD_ERR_NO_MATCH; + case CMD_ERR_INCOMPLETE: + fprintf(stderr, "line %d: %% Command incomplete: %s\n", + lineno, vty->buf); + fclose(confp); + vty_close(vty); + XFREE(MTYPE_VTYSH_CMD, vty_buf_copy); + return CMD_ERR_INCOMPLETE; + case CMD_SUCCESS: + fprintf(stdout, "%s", vty->buf); + break; + case CMD_SUCCESS_DAEMON: { + u_int i; + int cmd_stat = CMD_SUCCESS; + + fprintf(stdout, "%s", vty->buf); + for (i = 0; i < array_size(vtysh_client); i++) { + if (cmd->daemon & vtysh_client[i].flag) { + cmd_stat = vtysh_client_execute( + &vtysh_client[i], vty->buf, + stdout); + if (cmd_stat != CMD_SUCCESS) + break; + } + } + if (cmd_stat != CMD_SUCCESS) + break; + + if (cmd->func) + (*cmd->func)(cmd, vty, 0, NULL); + } + } } - } - /* This is the end */ - fprintf(stdout, "\nend\n"); - vty_close(vty); - XFREE(MTYPE_VTYSH_CMD, vty_buf_copy); + /* This is the end */ + fprintf(stdout, "\nend\n"); + vty_close(vty); + XFREE(MTYPE_VTYSH_CMD, vty_buf_copy); - if (confp != stdin) - fclose(confp); + if (confp != stdin) + fclose(confp); - return (0); + return (0); } /* Configration make from file. */ -int -vtysh_config_from_file (struct vty *vty, FILE *fp) +int vtysh_config_from_file(struct vty *vty, FILE *fp) +{ + int ret; + const struct cmd_element *cmd; + int lineno = 0; + int retcode = CMD_SUCCESS; + + while (fgets(vty->buf, VTY_BUFSIZ, fp)) { + lineno++; + + ret = command_config_read_one_line(vty, &cmd, 1); + + switch (ret) { + case CMD_WARNING: + case CMD_WARNING_CONFIG_FAILED: + if (vty->type == VTY_FILE) + fprintf(stderr, "line %d: Warning[%d]...: %s\n", + lineno, vty->node, vty->buf); + retcode = ret; /* once we have an error, we remember & + return that */ + break; + case CMD_ERR_AMBIGUOUS: + fprintf(stderr, + "line %d: %% Ambiguous command[%d]: %s\n", + lineno, vty->node, vty->buf); + retcode = CMD_ERR_AMBIGUOUS; /* once we have an error, + we remember & return + that */ + break; + case CMD_ERR_NO_MATCH: + fprintf(stderr, "line %d: %% Unknown command[%d]: %s", + lineno, vty->node, vty->buf); + retcode = + CMD_ERR_NO_MATCH; /* once we have an error, we + remember & return that */ + break; + case CMD_ERR_INCOMPLETE: + fprintf(stderr, + "line %d: %% Command incomplete[%d]: %s\n", + lineno, vty->node, vty->buf); + retcode = CMD_ERR_INCOMPLETE; /* once we have an error, + we remember & return + that */ + break; + case CMD_SUCCESS_DAEMON: { + u_int i; + int cmd_stat = CMD_SUCCESS; + + for (i = 0; i < array_size(vtysh_client); i++) { + if (cmd->daemon & vtysh_client[i].flag) { + cmd_stat = vtysh_client_execute( + &vtysh_client[i], vty->buf, + stdout); + /* + * CMD_WARNING - Can mean that the + * command was + * parsed successfully but it was + * already entered + * in a few spots. As such if we + * receive a + * CMD_WARNING from a daemon we + * shouldn't stop + * talking to the other daemons for the + * particular + * command. + */ + if (cmd_stat != CMD_SUCCESS + && cmd_stat != CMD_WARNING) { + fprintf(stderr, + "line %d: Failure to communicate[%d] to %s, line: %s\n", + lineno, cmd_stat, + vtysh_client[i].name, + vty->buf); + break; + } + } + } + if (cmd_stat != CMD_SUCCESS) + break; + + if (cmd->func) + (*cmd->func)(cmd, vty, 0, NULL); + } + } + } + + return (retcode); +} + +/* We don't care about the point of the cursor when '?' is typed. */ +static int vtysh_rl_describe(void) { - int ret; - const struct cmd_element *cmd; - int lineno = 0; - int retcode = CMD_SUCCESS; + int ret; + unsigned int i; + vector vline; + vector describe; + int width; + struct cmd_token *token; - while (fgets (vty->buf, VTY_BUFSIZ, fp)) - { - lineno++; + vline = cmd_make_strvec(rl_line_buffer); - ret = command_config_read_one_line (vty, &cmd, 1); + /* In case of '> ?'. */ + if (vline == NULL) { + vline = vector_init(1); + vector_set(vline, NULL); + } else if (rl_end && isspace((int)rl_line_buffer[rl_end - 1])) + vector_set(vline, NULL); - switch (ret) - { - case CMD_WARNING: - case CMD_WARNING_CONFIG_FAILED: - if (vty->type == VTY_FILE) - fprintf (stderr,"line %d: Warning[%d]...: %s\n", lineno, vty->node, vty->buf); - retcode = ret; /* once we have an error, we remember & return that */ - break; + describe = cmd_describe_command(vline, vty, &ret); + + fprintf(stdout, "\n"); + + /* Ambiguous and no match error. */ + switch (ret) { case CMD_ERR_AMBIGUOUS: - fprintf (stderr,"line %d: %% Ambiguous command[%d]: %s\n", lineno, vty->node, vty->buf); - retcode = CMD_ERR_AMBIGUOUS; /* once we have an error, we remember & return that */ - break; + cmd_free_strvec(vline); + fprintf(stdout, "%% Ambiguous command.\n"); + rl_on_new_line(); + return 0; + break; case CMD_ERR_NO_MATCH: - fprintf (stderr,"line %d: %% Unknown command[%d]: %s", lineno, vty->node, vty->buf); - retcode = CMD_ERR_NO_MATCH; /* once we have an error, we remember & return that */ - break; - case CMD_ERR_INCOMPLETE: - fprintf (stderr,"line %d: %% Command incomplete[%d]: %s\n", lineno, vty->node, vty->buf); - retcode = CMD_ERR_INCOMPLETE; /* once we have an error, we remember & return that */ - break; - case CMD_SUCCESS_DAEMON: - { - u_int i; - int cmd_stat = CMD_SUCCESS; - - for (i = 0; i < array_size(vtysh_client); i++) - { - if (cmd->daemon & vtysh_client[i].flag) - { - cmd_stat = vtysh_client_execute (&vtysh_client[i], - vty->buf, stdout); - /* - * CMD_WARNING - Can mean that the command was - * parsed successfully but it was already entered - * in a few spots. As such if we receive a - * CMD_WARNING from a daemon we shouldn't stop - * talking to the other daemons for the particular - * command. - */ - if (cmd_stat != CMD_SUCCESS && cmd_stat != CMD_WARNING) - { - fprintf (stderr, "line %d: Failure to communicate[%d] to %s, line: %s\n", - lineno, cmd_stat, vtysh_client[i].name, vty->buf); - break; - } - } - } - if (cmd_stat != CMD_SUCCESS) - break; - - if (cmd->func) - (*cmd->func) (cmd, vty, 0, NULL); - } + cmd_free_strvec(vline); + fprintf(stdout, "%% There is no matched command.\n"); + rl_on_new_line(); + return 0; + break; } - } - - return (retcode); -} - -/* We don't care about the point of the cursor when '?' is typed. */ -static int -vtysh_rl_describe (void) -{ - int ret; - unsigned int i; - vector vline; - vector describe; - int width; - struct cmd_token *token; - - vline = cmd_make_strvec (rl_line_buffer); - - /* In case of '> ?'. */ - if (vline == NULL) - { - vline = vector_init (1); - vector_set (vline, NULL); - } - else - if (rl_end && isspace ((int) rl_line_buffer[rl_end - 1])) - vector_set (vline, NULL); - - describe = cmd_describe_command (vline, vty, &ret); - - fprintf (stdout,"\n"); - - /* Ambiguous and no match error. */ - switch (ret) - { - case CMD_ERR_AMBIGUOUS: - cmd_free_strvec (vline); - fprintf (stdout,"%% Ambiguous command.\n"); - rl_on_new_line (); - return 0; - break; - case CMD_ERR_NO_MATCH: - cmd_free_strvec (vline); - fprintf (stdout,"%% There is no matched command.\n"); - rl_on_new_line (); - return 0; - break; - } - - /* Get width of command string. */ - width = 0; - for (i = 0; i < vector_active (describe); i++) - if ((token = vector_slot (describe, i)) != NULL) - { - if (token->text[0] == '\0') - continue; - - int len = strlen (token->text); - - if (width < len) - width = len; - } - - for (i = 0; i < vector_active (describe); i++) - if ((token = vector_slot (describe, i)) != NULL) - { - if (! token->desc) - fprintf (stdout," %-s\n", - token->text); - else - fprintf (stdout," %-*s %s\n", - width, - token->text, - token->desc); - - if (IS_VARYING_TOKEN(token->type)) - { - const char *ref = vector_slot(vline, vector_active(vline) - 1); - vector varcomps = vector_init (VECTOR_MIN_SIZE); - cmd_variable_complete (token, ref, varcomps); + /* Get width of command string. */ + width = 0; + for (i = 0; i < vector_active(describe); i++) + if ((token = vector_slot(describe, i)) != NULL) { + if (token->text[0] == '\0') + continue; - if (vector_active (varcomps) > 0) - { - int rows, cols; - rl_get_screen_size(&rows, &cols); + int len = strlen(token->text); - char *ac = cmd_variable_comp2str(varcomps, cols); - fprintf(stdout, "%s\n", ac); - XFREE(MTYPE_TMP, ac); - } + if (width < len) + width = len; + } - vector_free (varcomps); - } - } + for (i = 0; i < vector_active(describe); i++) + if ((token = vector_slot(describe, i)) != NULL) { + if (!token->desc) + fprintf(stdout, " %-s\n", token->text); + else + fprintf(stdout, " %-*s %s\n", width, + token->text, token->desc); + + if (IS_VARYING_TOKEN(token->type)) { + const char *ref = vector_slot( + vline, vector_active(vline) - 1); + + vector varcomps = vector_init(VECTOR_MIN_SIZE); + cmd_variable_complete(token, ref, varcomps); + + if (vector_active(varcomps) > 0) { + int rows, cols; + rl_get_screen_size(&rows, &cols); + + char *ac = cmd_variable_comp2str( + varcomps, cols); + fprintf(stdout, "%s\n", ac); + XFREE(MTYPE_TMP, ac); + } + + vector_free(varcomps); + } + } - cmd_free_strvec (vline); - vector_free (describe); + cmd_free_strvec(vline); + vector_free(describe); - rl_on_new_line(); + rl_on_new_line(); - return 0; + return 0; } /* Result of cmd_complete_command() call will be stored here @@ -846,1241 +818,893 @@ vtysh_rl_describe (void) * correct places only. */ int complete_status; -static char * -command_generator (const char *text, int state) +static char *command_generator(const char *text, int state) { - vector vline; - static char **matched = NULL; - static int index = 0; + vector vline; + static char **matched = NULL; + static int index = 0; - /* First call. */ - if (! state) - { - index = 0; + /* First call. */ + if (!state) { + index = 0; - if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE) - return NULL; + if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE) + return NULL; - vline = cmd_make_strvec (rl_line_buffer); - if (vline == NULL) - return NULL; + vline = cmd_make_strvec(rl_line_buffer); + if (vline == NULL) + return NULL; - if (rl_end && isspace ((int) rl_line_buffer[rl_end - 1])) - vector_set (vline, NULL); + if (rl_end && isspace((int)rl_line_buffer[rl_end - 1])) + vector_set(vline, NULL); - matched = cmd_complete_command (vline, vty, &complete_status); - cmd_free_strvec (vline); - } + matched = cmd_complete_command(vline, vty, &complete_status); + cmd_free_strvec(vline); + } - if (matched && matched[index]) - /* this is free()'d by readline, but we leak 1 count of MTYPE_COMPLETION */ - return matched[index++]; + if (matched && matched[index]) + /* this is free()'d by readline, but we leak 1 count of + * MTYPE_COMPLETION */ + return matched[index++]; - XFREE (MTYPE_TMP, matched); - matched = NULL; + XFREE(MTYPE_TMP, matched); + matched = NULL; - return NULL; + return NULL; } -static char ** -new_completion (char *text, int start, int end) +static char **new_completion(char *text, int start, int end) { - char **matches; + char **matches; - matches = rl_completion_matches (text, command_generator); + matches = rl_completion_matches(text, command_generator); - if (matches) - { - rl_point = rl_end; - if (complete_status != CMD_COMPLETE_FULL_MATCH) - /* only append a space on full match */ - rl_completion_append_character = '\0'; - } + if (matches) { + rl_point = rl_end; + if (complete_status != CMD_COMPLETE_FULL_MATCH) + /* only append a space on full match */ + rl_completion_append_character = '\0'; + } - return matches; + return matches; } /* Vty node structures. */ -static struct cmd_node bgp_node = -{ - BGP_NODE, - "%s(config-router)# ", +static struct cmd_node bgp_node = { + BGP_NODE, "%s(config-router)# ", }; -static struct cmd_node rip_node = -{ - RIP_NODE, - "%s(config-router)# ", +static struct cmd_node rip_node = { + RIP_NODE, "%s(config-router)# ", }; -static struct cmd_node isis_node = -{ - ISIS_NODE, - "%s(config-router)# ", +static struct cmd_node isis_node = { + ISIS_NODE, "%s(config-router)# ", }; -static struct cmd_node interface_node = -{ - INTERFACE_NODE, - "%s(config-if)# ", +static struct cmd_node interface_node = { + INTERFACE_NODE, "%s(config-if)# ", }; -static struct cmd_node ns_node = -{ - NS_NODE, - "%s(config-logical-router)# ", +static struct cmd_node ns_node = { + NS_NODE, "%s(config-logical-router)# ", }; -static struct cmd_node vrf_node = -{ - VRF_NODE, - "%s(config-vrf)# ", +static struct cmd_node vrf_node = { + VRF_NODE, "%s(config-vrf)# ", }; -static struct cmd_node rmap_node = -{ - RMAP_NODE, - "%s(config-route-map)# " -}; +static struct cmd_node rmap_node = {RMAP_NODE, "%s(config-route-map)# "}; -static struct cmd_node zebra_node = -{ - ZEBRA_NODE, - "%s(config-router)# " -}; +static struct cmd_node zebra_node = {ZEBRA_NODE, "%s(config-router)# "}; -static struct cmd_node bgp_vpnv4_node = -{ - BGP_VPNV4_NODE, - "%s(config-router-af)# " -}; +static struct cmd_node bgp_vpnv4_node = {BGP_VPNV4_NODE, + "%s(config-router-af)# "}; -static struct cmd_node bgp_vpnv6_node = -{ - BGP_VPNV6_NODE, - "%s(config-router-af)# " -}; +static struct cmd_node bgp_vpnv6_node = {BGP_VPNV6_NODE, + "%s(config-router-af)# "}; -static struct cmd_node bgp_ipv4_node = -{ - BGP_IPV4_NODE, - "%s(config-router-af)# " -}; +static struct cmd_node bgp_ipv4_node = {BGP_IPV4_NODE, + "%s(config-router-af)# "}; -static struct cmd_node bgp_ipv4m_node = -{ - BGP_IPV4M_NODE, - "%s(config-router-af)# " -}; +static struct cmd_node bgp_ipv4m_node = {BGP_IPV4M_NODE, + "%s(config-router-af)# "}; -static struct cmd_node bgp_ipv4l_node = -{ - BGP_IPV4L_NODE, - "%s(config-router-af)# " -}; +static struct cmd_node bgp_ipv4l_node = {BGP_IPV4L_NODE, + "%s(config-router-af)# "}; -static struct cmd_node bgp_ipv6_node = -{ - BGP_IPV6_NODE, - "%s(config-router-af)# " -}; +static struct cmd_node bgp_ipv6_node = {BGP_IPV6_NODE, + "%s(config-router-af)# "}; -static struct cmd_node bgp_ipv6m_node = -{ - BGP_IPV6M_NODE, - "%s(config-router-af)# " -}; +static struct cmd_node bgp_ipv6m_node = {BGP_IPV6M_NODE, + "%s(config-router-af)# "}; -static struct cmd_node bgp_evpn_node = -{ - BGP_EVPN_NODE, - "%s(config-router-af)# " -}; +static struct cmd_node bgp_evpn_node = {BGP_EVPN_NODE, + "%s(config-router-af)# "}; -static struct cmd_node bgp_evpn_vni_node = -{ - BGP_EVPN_VNI_NODE, - "%s(config-router-af-vni)# " -}; +static struct cmd_node bgp_evpn_vni_node = {BGP_EVPN_VNI_NODE, + "%s(config-router-af-vni)# "}; -static struct cmd_node bgp_ipv6l_node = -{ - BGP_IPV6L_NODE, - "%s(config-router-af)# " -}; +static struct cmd_node bgp_ipv6l_node = {BGP_IPV6L_NODE, + "%s(config-router-af)# "}; -static struct cmd_node bgp_vnc_defaults_node = -{ - BGP_VNC_DEFAULTS_NODE, - "%s(config-router-vnc-defaults)# " -}; +static struct cmd_node bgp_vnc_defaults_node = { + BGP_VNC_DEFAULTS_NODE, "%s(config-router-vnc-defaults)# "}; -static struct cmd_node bgp_vnc_nve_group_node = -{ - BGP_VNC_NVE_GROUP_NODE, - "%s(config-router-vnc-nve-group)# " -}; +static struct cmd_node bgp_vnc_nve_group_node = { + BGP_VNC_NVE_GROUP_NODE, "%s(config-router-vnc-nve-group)# "}; -static struct cmd_node bgp_vrf_policy_node = { - BGP_VRF_POLICY_NODE, - "%s(config-router-vrf-policy)# " -}; +static struct cmd_node bgp_vrf_policy_node = {BGP_VRF_POLICY_NODE, + "%s(config-router-vrf-policy)# "}; -static struct cmd_node bgp_vnc_l2_group_node = -{ - BGP_VNC_L2_GROUP_NODE, - "%s(config-router-vnc-l2-group)# " -}; +static struct cmd_node bgp_vnc_l2_group_node = { + BGP_VNC_L2_GROUP_NODE, "%s(config-router-vnc-l2-group)# "}; -static struct cmd_node ospf_node = -{ - OSPF_NODE, - "%s(config-router)# " +static struct cmd_node ospf_node = {OSPF_NODE, "%s(config-router)# "}; + +static struct cmd_node eigrp_node = {EIGRP_NODE, "%s(config-router)# "}; + +static struct cmd_node babel_node = {BABEL_NODE, "%s(config-router)# "}; + +static struct cmd_node ripng_node = {RIPNG_NODE, "%s(config-router)# "}; + +static struct cmd_node ospf6_node = {OSPF6_NODE, "%s(config-ospf6)# "}; + +static struct cmd_node ldp_node = {LDP_NODE, "%s(config-ldp)# "}; + +static struct cmd_node ldp_ipv4_node = {LDP_IPV4_NODE, "%s(config-ldp-af)# "}; + +static struct cmd_node ldp_ipv6_node = {LDP_IPV6_NODE, "%s(config-ldp-af)# "}; + +static struct cmd_node ldp_ipv4_iface_node = {LDP_IPV4_IFACE_NODE, + "%s(config-ldp-af-if)# "}; + +static struct cmd_node ldp_ipv6_iface_node = {LDP_IPV6_IFACE_NODE, + "%s(config-ldp-af-if)# "}; + +static struct cmd_node ldp_l2vpn_node = {LDP_L2VPN_NODE, "%s(config-l2vpn)# "}; + +static struct cmd_node ldp_pseudowire_node = {LDP_PSEUDOWIRE_NODE, + "%s(config-l2vpn-pw)# "}; + +static struct cmd_node keychain_node = {KEYCHAIN_NODE, "%s(config-keychain)# "}; + +static struct cmd_node keychain_key_node = {KEYCHAIN_KEY_NODE, + "%s(config-keychain-key)# "}; + +struct cmd_node link_params_node = { + LINK_PARAMS_NODE, "%s(config-link-params)# ", }; -static struct cmd_node eigrp_node = +/* Defined in lib/vty.c */ +extern struct cmd_node vty_node; + +/* When '^Z' is received from vty, move down to the enable mode. */ +static int vtysh_end(void) +{ + switch (vty->node) { + case VIEW_NODE: + case ENABLE_NODE: + /* Nothing to do. */ + break; + default: + vty->node = ENABLE_NODE; + break; + } + return CMD_SUCCESS; +} + +DEFUNSH(VTYSH_REALLYALL, vtysh_end_all, vtysh_end_all_cmd, "end", + "End current mode and change to enable mode\n") { - EIGRP_NODE, - "%s(config-router)# " -}; + return vtysh_end(); +} -static struct cmd_node babel_node = +DEFUNSH(VTYSH_BGPD, router_bgp, router_bgp_cmd, + "router bgp [(1-4294967295) [ WORD]]", + ROUTER_STR BGP_STR AS_STR + "BGP view\nBGP VRF\n" + "View/VRF name\n") { - BABEL_NODE, - "%s(config-router)# " -}; + vty->node = BGP_NODE; + return CMD_SUCCESS; +} -static struct cmd_node ripng_node = +DEFUNSH(VTYSH_BGPD, address_family_vpnv4, address_family_vpnv4_cmd, + "address-family vpnv4 [unicast]", + "Enter Address Family command mode\n" + "Address Family\n" + "Address Family modifier\n") { - RIPNG_NODE, - "%s(config-router)# " -}; + vty->node = BGP_VPNV4_NODE; + return CMD_SUCCESS; +} -static struct cmd_node ospf6_node = +DEFUNSH(VTYSH_BGPD, address_family_vpnv6, address_family_vpnv6_cmd, + "address-family vpnv6 [unicast]", + "Enter Address Family command mode\n" + "Address Family\n" + "Address Family modifier\n") { - OSPF6_NODE, - "%s(config-ospf6)# " -}; + vty->node = BGP_VPNV6_NODE; + return CMD_SUCCESS; +} -static struct cmd_node ldp_node = +DEFUNSH(VTYSH_BGPD, address_family_ipv4, address_family_ipv4_cmd, + "address-family ipv4 [unicast]", + "Enter Address Family command mode\n" + "Address Family\n" + "Address Family Modifier\n") { - LDP_NODE, - "%s(config-ldp)# " -}; + vty->node = BGP_IPV4_NODE; + return CMD_SUCCESS; +} -static struct cmd_node ldp_ipv4_node = +DEFUNSH(VTYSH_BGPD, address_family_ipv4_multicast, + address_family_ipv4_multicast_cmd, "address-family ipv4 multicast", + "Enter Address Family command mode\n" + "Address Family\n" + "Address Family modifier\n") { - LDP_IPV4_NODE, - "%s(config-ldp-af)# " -}; + vty->node = BGP_IPV4M_NODE; + return CMD_SUCCESS; +} -static struct cmd_node ldp_ipv6_node = +DEFUNSH(VTYSH_BGPD, address_family_ipv4_vpn, address_family_ipv4_vpn_cmd, + "address-family ipv4 vpn", + "Enter Address Family command mode\n" + "Address Family\n" + "Address Family modifier\n") { - LDP_IPV6_NODE, - "%s(config-ldp-af)# " -}; + vty->node = BGP_VPNV4_NODE; + return CMD_SUCCESS; +} -static struct cmd_node ldp_ipv4_iface_node = +DEFUNSH(VTYSH_BGPD, address_family_ipv4_labeled_unicast, + address_family_ipv4_labeled_unicast_cmd, + "address-family ipv4 labeled-unicast", + "Enter Address Family command mode\n" + "Address Family\n" + "Address Family modifier\n") { - LDP_IPV4_IFACE_NODE, - "%s(config-ldp-af-if)# " -}; + vty->node = BGP_IPV4L_NODE; + return CMD_SUCCESS; +} -static struct cmd_node ldp_ipv6_iface_node = +DEFUNSH(VTYSH_BGPD, address_family_ipv6, address_family_ipv6_cmd, + "address-family ipv6 [unicast]", + "Enter Address Family command mode\n" + "Address Family\n" + "Address Family modifier\n") { - LDP_IPV6_IFACE_NODE, - "%s(config-ldp-af-if)# " -}; + vty->node = BGP_IPV6_NODE; + return CMD_SUCCESS; +} -static struct cmd_node ldp_l2vpn_node = +DEFUNSH(VTYSH_BGPD, address_family_ipv6_multicast, + address_family_ipv6_multicast_cmd, "address-family ipv6 multicast", + "Enter Address Family command mode\n" + "Address Family\n" + "Address Family modifier\n") { - LDP_L2VPN_NODE, - "%s(config-l2vpn)# " -}; + vty->node = BGP_IPV6M_NODE; + return CMD_SUCCESS; +} -static struct cmd_node ldp_pseudowire_node = +DEFUNSH(VTYSH_BGPD, address_family_ipv6_vpn, address_family_ipv6_vpn_cmd, + "address-family ipv6 vpn", + "Enter Address Family command mode\n" + "Address Family\n" + "Address Family modifier\n") { - LDP_PSEUDOWIRE_NODE, - "%s(config-l2vpn-pw)# " -}; + vty->node = BGP_VPNV6_NODE; + return CMD_SUCCESS; +} -static struct cmd_node keychain_node = +DEFUNSH(VTYSH_BGPD, address_family_ipv6_labeled_unicast, + address_family_ipv6_labeled_unicast_cmd, + "address-family ipv6 labeled-unicast", + "Enter Address Family command mode\n" + "Address Family\n" + "Address Family modifier\n") { - KEYCHAIN_NODE, - "%s(config-keychain)# " -}; + vty->node = BGP_IPV6L_NODE; + return CMD_SUCCESS; +} -static struct cmd_node keychain_key_node = +DEFUNSH(VTYSH_BGPD, address_family_evpn, address_family_evpn_cmd, + "address-family ", + "Enter Address Family command mode\n" + "Address Family\n" + "Address Family modifier\n") { - KEYCHAIN_KEY_NODE, - "%s(config-keychain-key)# " -}; + vty->node = BGP_EVPN_NODE; + return CMD_SUCCESS; +} -struct cmd_node link_params_node = +#if defined(HAVE_CUMULUS) +DEFUNSH(VTYSH_BGPD, address_family_evpn2, address_family_evpn2_cmd, + "address-family evpn", + "Enter Address Family command mode\n" + "EVPN Address family\n") { - LINK_PARAMS_NODE, - "%s(config-link-params)# ", -}; + vty->node = BGP_EVPN_NODE; + return CMD_SUCCESS; +} +#endif -/* Defined in lib/vty.c */ -extern struct cmd_node vty_node; +DEFUNSH(VTYSH_BGPD, bgp_evpn_vni, bgp_evpn_vni_cmd, "vni (1-16777215)", + "VXLAN Network Identifier\n" + "VNI number\n") +{ + vty->node = BGP_EVPN_VNI_NODE; + return CMD_SUCCESS; +} -/* When '^Z' is received from vty, move down to the enable mode. */ -static int -vtysh_end (void) -{ - switch (vty->node) - { - case VIEW_NODE: - case ENABLE_NODE: - /* Nothing to do. */ - break; - default: - vty->node = ENABLE_NODE; - break; - } - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_REALLYALL, - vtysh_end_all, - vtysh_end_all_cmd, - "end", - "End current mode and change to enable mode\n") -{ - return vtysh_end (); -} - -DEFUNSH (VTYSH_BGPD, - router_bgp, - router_bgp_cmd, - "router bgp [(1-4294967295) [ WORD]]", - ROUTER_STR - BGP_STR - AS_STR - "BGP view\nBGP VRF\n" - "View/VRF name\n") +#if defined(ENABLE_BGP_VNC) +DEFUNSH(VTYSH_BGPD, vnc_defaults, vnc_defaults_cmd, "vnc defaults", + "VNC/RFP related configuration\n" + "Configure default NVE group\n") { - vty->node = BGP_NODE; - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_BGPD, - address_family_vpnv4, - address_family_vpnv4_cmd, - "address-family vpnv4 [unicast]", - "Enter Address Family command mode\n" - "Address Family\n" - "Address Family modifier\n") + vty->node = BGP_VNC_DEFAULTS_NODE; + return CMD_SUCCESS; +} + +DEFUNSH(VTYSH_BGPD, vnc_nve_group, vnc_nve_group_cmd, "vnc nve-group NAME", + "VNC/RFP related configuration\n" + "Configure a NVE group\n" + "Group name\n") { - vty->node = BGP_VPNV4_NODE; - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_BGPD, - address_family_vpnv6, - address_family_vpnv6_cmd, - "address-family vpnv6 [unicast]", - "Enter Address Family command mode\n" - "Address Family\n" - "Address Family modifier\n") + vty->node = BGP_VNC_NVE_GROUP_NODE; + return CMD_SUCCESS; +} + +DEFUNSH(VTYSH_BGPD, vnc_vrf_policy, vnc_vrf_policy_cmd, "vrf-policy NAME", + "Configure a VRF policy group\n" + "Group name\n") { - vty->node = BGP_VPNV6_NODE; - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_BGPD, - address_family_ipv4, - address_family_ipv4_cmd, - "address-family ipv4 [unicast]", - "Enter Address Family command mode\n" - "Address Family\n" - "Address Family Modifier\n") + vty->node = BGP_VRF_POLICY_NODE; + return CMD_SUCCESS; +} + +DEFUNSH(VTYSH_BGPD, vnc_l2_group, vnc_l2_group_cmd, "vnc l2-group NAME", + "VNC/RFP related configuration\n" + "Configure a L2 group\n" + "Group name\n") { - vty->node = BGP_IPV4_NODE; - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_BGPD, - address_family_ipv4_multicast, - address_family_ipv4_multicast_cmd, - "address-family ipv4 multicast", - "Enter Address Family command mode\n" - "Address Family\n" - "Address Family modifier\n") -{ - vty->node = BGP_IPV4M_NODE; - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_BGPD, - address_family_ipv4_vpn, - address_family_ipv4_vpn_cmd, - "address-family ipv4 vpn", - "Enter Address Family command mode\n" - "Address Family\n" - "Address Family modifier\n") -{ - vty->node = BGP_VPNV4_NODE; - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_BGPD, - address_family_ipv4_labeled_unicast, - address_family_ipv4_labeled_unicast_cmd, - "address-family ipv4 labeled-unicast", - "Enter Address Family command mode\n" - "Address Family\n" - "Address Family modifier\n") -{ - vty->node = BGP_IPV4L_NODE; - return CMD_SUCCESS; + vty->node = BGP_VNC_L2_GROUP_NODE; + return CMD_SUCCESS; } +#endif -DEFUNSH (VTYSH_BGPD, - address_family_ipv6, - address_family_ipv6_cmd, - "address-family ipv6 [unicast]", - "Enter Address Family command mode\n" - "Address Family\n" - "Address Family modifier\n") +DEFUNSH(VTYSH_RIPD, key_chain, key_chain_cmd, "key chain WORD", + "Authentication key management\n" + "Key-chain management\n" + "Key-chain name\n") { - vty->node = BGP_IPV6_NODE; - return CMD_SUCCESS; + vty->node = KEYCHAIN_NODE; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_BGPD, - address_family_ipv6_multicast, - address_family_ipv6_multicast_cmd, - "address-family ipv6 multicast", - "Enter Address Family command mode\n" - "Address Family\n" - "Address Family modifier\n") +DEFUNSH(VTYSH_RIPD, key, key_cmd, "key (0-2147483647)", + "Configure a key\n" + "Key identifier number\n") { - vty->node = BGP_IPV6M_NODE; - return CMD_SUCCESS; + vty->node = KEYCHAIN_KEY_NODE; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_BGPD, - address_family_ipv6_vpn, - address_family_ipv6_vpn_cmd, - "address-family ipv6 vpn", - "Enter Address Family command mode\n" - "Address Family\n" - "Address Family modifier\n") +DEFUNSH(VTYSH_RIPD, router_rip, router_rip_cmd, "router rip", + ROUTER_STR "RIP\n") { - vty->node = BGP_VPNV6_NODE; - return CMD_SUCCESS; + vty->node = RIP_NODE; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_BGPD, - address_family_ipv6_labeled_unicast, - address_family_ipv6_labeled_unicast_cmd, - "address-family ipv6 labeled-unicast", - "Enter Address Family command mode\n" - "Address Family\n" - "Address Family modifier\n") +DEFUNSH(VTYSH_RIPNGD, router_ripng, router_ripng_cmd, "router ripng", + ROUTER_STR "RIPng\n") { - vty->node = BGP_IPV6L_NODE; - return CMD_SUCCESS; + vty->node = RIPNG_NODE; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_BGPD, - address_family_evpn, - address_family_evpn_cmd, - "address-family ", - "Enter Address Family command mode\n" - "Address Family\n" - "Address Family modifier\n") +DEFUNSH(VTYSH_OSPFD, router_ospf, router_ospf_cmd, "router ospf [(1-65535)]", + "Enable a routing process\n" + "Start OSPF configuration\n" + "Instance ID\n") { - vty->node = BGP_EVPN_NODE; - return CMD_SUCCESS; + vty->node = OSPF_NODE; + return CMD_SUCCESS; } -#if defined (HAVE_CUMULUS) -DEFUNSH (VTYSH_BGPD, - address_family_evpn2, - address_family_evpn2_cmd, - "address-family evpn", - "Enter Address Family command mode\n" - "EVPN Address family\n") +DEFUNSH(VTYSH_EIGRPD, router_eigrp, router_eigrp_cmd, "router eigrp (1-65535)", + "Enable a routing process\n" + "Start EIGRP configuration\n" + "AS number to use\n") { - vty->node = BGP_EVPN_NODE; - return CMD_SUCCESS; + vty->node = EIGRP_NODE; + return CMD_SUCCESS; } -#endif -DEFUNSH (VTYSH_BGPD, - bgp_evpn_vni, - bgp_evpn_vni_cmd, - "vni (1-16777215)", - "VXLAN Network Identifier\n" - "VNI number\n") +DEFUNSH(VTYSH_BABELD, router_babel, router_babel_cmd, "router babel", + "Enable a routing process\n" + "Make Babel instance command\n") { - vty->node = BGP_EVPN_VNI_NODE; - return CMD_SUCCESS; + vty->node = BABEL_NODE; + return CMD_SUCCESS; } -#if defined (ENABLE_BGP_VNC) -DEFUNSH (VTYSH_BGPD, - vnc_defaults, - vnc_defaults_cmd, - "vnc defaults", - "VNC/RFP related configuration\n" - "Configure default NVE group\n") +DEFUNSH(VTYSH_OSPF6D, router_ospf6, router_ospf6_cmd, "router ospf6", + ROUTER_STR OSPF6_STR) { - vty->node = BGP_VNC_DEFAULTS_NODE; - return CMD_SUCCESS; + vty->node = OSPF6_NODE; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_BGPD, - vnc_nve_group, - vnc_nve_group_cmd, - "vnc nve-group NAME", - "VNC/RFP related configuration\n" - "Configure a NVE group\n" - "Group name\n") +#if defined(HAVE_LDPD) +DEFUNSH(VTYSH_LDPD, ldp_mpls_ldp, ldp_mpls_ldp_cmd, "mpls ldp", + "Global MPLS configuration subcommands\n" + "Label Distribution Protocol\n") { - vty->node = BGP_VNC_NVE_GROUP_NODE; - return CMD_SUCCESS; + vty->node = LDP_NODE; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_BGPD, - vnc_vrf_policy, - vnc_vrf_policy_cmd, - "vrf-policy NAME", - "Configure a VRF policy group\n" - "Group name\n") +DEFUNSH(VTYSH_LDPD, ldp_address_family_ipv4, ldp_address_family_ipv4_cmd, + "address-family ipv4", + "Configure Address Family and its parameters\n" + "IPv4\n") { - vty->node = BGP_VRF_POLICY_NODE; - return CMD_SUCCESS; + vty->node = LDP_IPV4_NODE; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_BGPD, - vnc_l2_group, - vnc_l2_group_cmd, - "vnc l2-group NAME", - "VNC/RFP related configuration\n" - "Configure a L2 group\n" - "Group name\n") +DEFUNSH(VTYSH_LDPD, ldp_address_family_ipv6, ldp_address_family_ipv6_cmd, + "address-family ipv6", + "Configure Address Family and its parameters\n" + "IPv6\n") { - vty->node = BGP_VNC_L2_GROUP_NODE; - return CMD_SUCCESS; + vty->node = LDP_IPV6_NODE; + return CMD_SUCCESS; } -#endif -DEFUNSH (VTYSH_RIPD, - key_chain, - key_chain_cmd, - "key chain WORD", - "Authentication key management\n" - "Key-chain management\n" - "Key-chain name\n") +DEFUNSH(VTYSH_LDPD, ldp_interface_ifname, ldp_interface_ifname_cmd, + "interface IFNAME", + "Enable LDP on an interface and enter interface submode\n" + "Interface's name\n") { - vty->node = KEYCHAIN_NODE; - return CMD_SUCCESS; -} + switch (vty->node) { + case LDP_IPV4_NODE: + vty->node = LDP_IPV4_IFACE_NODE; + break; + case LDP_IPV6_NODE: + vty->node = LDP_IPV6_IFACE_NODE; + break; + default: + break; + } + + return CMD_SUCCESS; +} -DEFUNSH (VTYSH_RIPD, - key, - key_cmd, - "key (0-2147483647)", - "Configure a key\n" - "Key identifier number\n") +DEFUNSH(VTYSH_LDPD, ldp_l2vpn_word_type_vpls, ldp_l2vpn_word_type_vpls_cmd, + "l2vpn WORD type vpls", + "Configure l2vpn commands\n" + "L2VPN name\n" + "L2VPN type\n" + "Virtual Private LAN Service\n") { - vty->node = KEYCHAIN_KEY_NODE; - return CMD_SUCCESS; + vty->node = LDP_L2VPN_NODE; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_RIPD, - router_rip, - router_rip_cmd, - "router rip", - ROUTER_STR - "RIP\n") +DEFUNSH(VTYSH_LDPD, ldp_member_pseudowire_ifname, + ldp_member_pseudowire_ifname_cmd, "member pseudowire IFNAME", + "L2VPN member configuration\n" + "Pseudowire interface\n" + "Interface's name\n") { - vty->node = RIP_NODE; - return CMD_SUCCESS; + vty->node = LDP_PSEUDOWIRE_NODE; + return CMD_SUCCESS; } +#endif -DEFUNSH (VTYSH_RIPNGD, - router_ripng, - router_ripng_cmd, - "router ripng", - ROUTER_STR - "RIPng\n") -{ - vty->node = RIPNG_NODE; - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_OSPFD, - router_ospf, - router_ospf_cmd, - "router ospf [(1-65535)]", - "Enable a routing process\n" - "Start OSPF configuration\n" - "Instance ID\n") -{ - vty->node = OSPF_NODE; - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_EIGRPD, - router_eigrp, - router_eigrp_cmd, - "router eigrp (1-65535)", - "Enable a routing process\n" - "Start EIGRP configuration\n" - "AS number to use\n") -{ - vty->node = EIGRP_NODE; - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_BABELD, - router_babel, - router_babel_cmd, - "router babel", - "Enable a routing process\n" - "Make Babel instance command\n") -{ - vty->node = BABEL_NODE; - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_OSPF6D, - router_ospf6, - router_ospf6_cmd, - "router ospf6", - ROUTER_STR - OSPF6_STR) -{ - vty->node = OSPF6_NODE; - return CMD_SUCCESS; -} - -#if defined (HAVE_LDPD) -DEFUNSH (VTYSH_LDPD, - ldp_mpls_ldp, - ldp_mpls_ldp_cmd, - "mpls ldp", - "Global MPLS configuration subcommands\n" - "Label Distribution Protocol\n") -{ - vty->node = LDP_NODE; - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_LDPD, - ldp_address_family_ipv4, - ldp_address_family_ipv4_cmd, - "address-family ipv4", - "Configure Address Family and its parameters\n" - "IPv4\n") +DEFUNSH(VTYSH_ISISD, router_isis, router_isis_cmd, "router isis WORD", + ROUTER_STR + "ISO IS-IS\n" + "ISO Routing area tag") +{ + vty->node = ISIS_NODE; + return CMD_SUCCESS; +} + +DEFUNSH(VTYSH_RMAP, vtysh_route_map, vtysh_route_map_cmd, + "route-map WORD (1-65535)", + "Create route-map or enter route-map command mode\n" + "Route map tag\n" + "Route map denies set operations\n" + "Route map permits set operations\n" + "Sequence to insert to/delete from existing route-map entry\n") +{ + vty->node = RMAP_NODE; + return CMD_SUCCESS; +} + +DEFUNSH(VTYSH_ALL, vtysh_line_vty, vtysh_line_vty_cmd, "line vty", + "Configure a terminal line\n" + "Virtual terminal\n") +{ + vty->node = VTY_NODE; + return CMD_SUCCESS; +} + +DEFUNSH(VTYSH_REALLYALL, vtysh_enable, vtysh_enable_cmd, "enable", + "Turn on privileged mode command\n") +{ + vty->node = ENABLE_NODE; + return CMD_SUCCESS; +} + +DEFUNSH(VTYSH_REALLYALL, vtysh_disable, vtysh_disable_cmd, "disable", + "Turn off privileged mode command\n") +{ + if (vty->node == ENABLE_NODE) + vty->node = VIEW_NODE; + return CMD_SUCCESS; +} + +DEFUNSH(VTYSH_REALLYALL, vtysh_config_terminal, vtysh_config_terminal_cmd, + "configure terminal", + "Configuration from vty interface\n" + "Configuration terminal\n") +{ + vty->node = CONFIG_NODE; + return CMD_SUCCESS; +} + +static int vtysh_exit(struct vty *vty) +{ + switch (vty->node) { + case VIEW_NODE: + case ENABLE_NODE: + exit(0); + break; + case CONFIG_NODE: + vty->node = ENABLE_NODE; + break; + case INTERFACE_NODE: + case NS_NODE: + case VRF_NODE: + case ZEBRA_NODE: + case BGP_NODE: + case RIP_NODE: + case RIPNG_NODE: + case OSPF_NODE: + case OSPF6_NODE: + case EIGRP_NODE: + case BABEL_NODE: + case LDP_NODE: + case LDP_L2VPN_NODE: + case ISIS_NODE: + case MASC_NODE: + case RMAP_NODE: + case VTY_NODE: + case KEYCHAIN_NODE: + vtysh_execute("end"); + vtysh_execute("configure terminal"); + vty->node = CONFIG_NODE; + break; + case BGP_VPNV4_NODE: + case BGP_VPNV6_NODE: + case BGP_IPV4_NODE: + case BGP_IPV4M_NODE: + case BGP_IPV4L_NODE: + case BGP_IPV6_NODE: + case BGP_IPV6M_NODE: + case BGP_IPV6L_NODE: + case BGP_VRF_POLICY_NODE: + case BGP_EVPN_NODE: + case BGP_VNC_DEFAULTS_NODE: + case BGP_VNC_NVE_GROUP_NODE: + case BGP_VNC_L2_GROUP_NODE: + vty->node = BGP_NODE; + break; + case BGP_EVPN_VNI_NODE: + vty->node = BGP_EVPN_NODE; + break; + case LDP_IPV4_NODE: + case LDP_IPV6_NODE: + vty->node = LDP_NODE; + break; + case LDP_IPV4_IFACE_NODE: + vty->node = LDP_IPV4_NODE; + break; + case LDP_IPV6_IFACE_NODE: + vty->node = LDP_IPV6_NODE; + break; + case LDP_PSEUDOWIRE_NODE: + vty->node = LDP_L2VPN_NODE; + break; + case KEYCHAIN_KEY_NODE: + vty->node = KEYCHAIN_NODE; + break; + case LINK_PARAMS_NODE: + vty->node = INTERFACE_NODE; + break; + default: + break; + } + return CMD_SUCCESS; +} + +DEFUNSH(VTYSH_REALLYALL, vtysh_exit_all, vtysh_exit_all_cmd, "exit", + "Exit current mode and down to previous mode\n") { - vty->node = LDP_IPV4_NODE; - return CMD_SUCCESS; + return vtysh_exit(vty); } -DEFUNSH (VTYSH_LDPD, - ldp_address_family_ipv6, - ldp_address_family_ipv6_cmd, - "address-family ipv6", - "Configure Address Family and its parameters\n" - "IPv6\n") +DEFUNSH(VTYSH_ALL, vtysh_quit_all, vtysh_quit_all_cmd, "quit", + "Exit current mode and down to previous mode\n") { - vty->node = LDP_IPV6_NODE; - return CMD_SUCCESS; -} + return vtysh_exit_all(self, vty, argc, argv); +} -DEFUNSH (VTYSH_LDPD, - ldp_interface_ifname, - ldp_interface_ifname_cmd, - "interface IFNAME", - "Enable LDP on an interface and enter interface submode\n" - "Interface's name\n") +DEFUNSH(VTYSH_BGPD, exit_address_family, exit_address_family_cmd, + "exit-address-family", "Exit from Address Family configuration mode\n") { - switch (vty->node) - { - case LDP_IPV4_NODE: - vty->node = LDP_IPV4_IFACE_NODE; - break; - case LDP_IPV6_NODE: - vty->node = LDP_IPV6_IFACE_NODE; - break; - default: - break; - } + if (vty->node == BGP_IPV4_NODE || vty->node == BGP_IPV4M_NODE + || vty->node == BGP_IPV4L_NODE || vty->node == BGP_VPNV4_NODE + || vty->node == BGP_VPNV6_NODE || vty->node == BGP_IPV6_NODE + || vty->node == BGP_IPV6L_NODE || vty->node == BGP_IPV6M_NODE + || vty->node == BGP_EVPN_NODE) + vty->node = BGP_NODE; + return CMD_SUCCESS; +} - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_LDPD, - ldp_l2vpn_word_type_vpls, - ldp_l2vpn_word_type_vpls_cmd, - "l2vpn WORD type vpls", - "Configure l2vpn commands\n" - "L2VPN name\n" - "L2VPN type\n" - "Virtual Private LAN Service\n") +DEFUNSH(VTYSH_BGPD, exit_vni, exit_vni_cmd, "exit-vni", "Exit from VNI mode\n") { - vty->node = LDP_L2VPN_NODE; - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_LDPD, - ldp_member_pseudowire_ifname, - ldp_member_pseudowire_ifname_cmd, - "member pseudowire IFNAME", - "L2VPN member configuration\n" - "Pseudowire interface\n" - "Interface's name\n") + if (vty->node == BGP_EVPN_VNI_NODE) + vty->node = BGP_EVPN_NODE; + return CMD_SUCCESS; +} + +DEFUNSH(VTYSH_BGPD, exit_vnc_config, exit_vnc_config_cmd, "exit-vnc", + "Exit from VNC configuration mode\n") { - vty->node = LDP_PSEUDOWIRE_NODE; - return CMD_SUCCESS; + if (vty->node == BGP_VNC_DEFAULTS_NODE + || vty->node == BGP_VNC_NVE_GROUP_NODE + || vty->node == BGP_VNC_L2_GROUP_NODE) + vty->node = BGP_NODE; + return CMD_SUCCESS; } -#endif -DEFUNSH (VTYSH_ISISD, - router_isis, - router_isis_cmd, - "router isis WORD", - ROUTER_STR - "ISO IS-IS\n" - "ISO Routing area tag") -{ - vty->node = ISIS_NODE; - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_RMAP, - vtysh_route_map, - vtysh_route_map_cmd, - "route-map WORD (1-65535)", - "Create route-map or enter route-map command mode\n" - "Route map tag\n" - "Route map denies set operations\n" - "Route map permits set operations\n" - "Sequence to insert to/delete from existing route-map entry\n") -{ - vty->node = RMAP_NODE; - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_ALL, - vtysh_line_vty, - vtysh_line_vty_cmd, - "line vty", - "Configure a terminal line\n" - "Virtual terminal\n") -{ - vty->node = VTY_NODE; - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_REALLYALL, - vtysh_enable, - vtysh_enable_cmd, - "enable", - "Turn on privileged mode command\n") -{ - vty->node = ENABLE_NODE; - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_REALLYALL, - vtysh_disable, - vtysh_disable_cmd, - "disable", - "Turn off privileged mode command\n") -{ - if (vty->node == ENABLE_NODE) - vty->node = VIEW_NODE; - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_REALLYALL, - vtysh_config_terminal, - vtysh_config_terminal_cmd, - "configure terminal", - "Configuration from vty interface\n" - "Configuration terminal\n") -{ - vty->node = CONFIG_NODE; - return CMD_SUCCESS; -} - -static int -vtysh_exit (struct vty *vty) -{ - switch (vty->node) - { - case VIEW_NODE: - case ENABLE_NODE: - exit (0); - break; - case CONFIG_NODE: - vty->node = ENABLE_NODE; - break; - case INTERFACE_NODE: - case NS_NODE: - case VRF_NODE: - case ZEBRA_NODE: - case BGP_NODE: - case RIP_NODE: - case RIPNG_NODE: - case OSPF_NODE: - case OSPF6_NODE: - case EIGRP_NODE: - case BABEL_NODE: - case LDP_NODE: - case LDP_L2VPN_NODE: - case ISIS_NODE: - case MASC_NODE: - case RMAP_NODE: - case VTY_NODE: - case KEYCHAIN_NODE: - vtysh_execute("end"); - vtysh_execute("configure terminal"); - vty->node = CONFIG_NODE; - break; - case BGP_VPNV4_NODE: - case BGP_VPNV6_NODE: - case BGP_IPV4_NODE: - case BGP_IPV4M_NODE: - case BGP_IPV4L_NODE: - case BGP_IPV6_NODE: - case BGP_IPV6M_NODE: - case BGP_IPV6L_NODE: - case BGP_VRF_POLICY_NODE: - case BGP_EVPN_NODE: - case BGP_VNC_DEFAULTS_NODE: - case BGP_VNC_NVE_GROUP_NODE: - case BGP_VNC_L2_GROUP_NODE: - vty->node = BGP_NODE; - break; - case BGP_EVPN_VNI_NODE: - vty->node = BGP_EVPN_NODE; - break; - case LDP_IPV4_NODE: - case LDP_IPV6_NODE: - vty->node = LDP_NODE; - break; - case LDP_IPV4_IFACE_NODE: - vty->node = LDP_IPV4_NODE; - break; - case LDP_IPV6_IFACE_NODE: - vty->node = LDP_IPV6_NODE; - break; - case LDP_PSEUDOWIRE_NODE: - vty->node = LDP_L2VPN_NODE; - break; - case KEYCHAIN_KEY_NODE: - vty->node = KEYCHAIN_NODE; - break; - case LINK_PARAMS_NODE: - vty->node = INTERFACE_NODE; - break; - default: - break; - } - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_REALLYALL, - vtysh_exit_all, - vtysh_exit_all_cmd, - "exit", - "Exit current mode and down to previous mode\n") -{ - return vtysh_exit (vty); -} - -DEFUNSH (VTYSH_ALL, - vtysh_quit_all, - vtysh_quit_all_cmd, - "quit", - "Exit current mode and down to previous mode\n") -{ - return vtysh_exit_all (self, vty, argc, argv); -} - -DEFUNSH (VTYSH_BGPD, - exit_address_family, - exit_address_family_cmd, - "exit-address-family", - "Exit from Address Family configuration mode\n") -{ - if (vty->node == BGP_IPV4_NODE - || vty->node == BGP_IPV4M_NODE - || vty->node == BGP_IPV4L_NODE - || vty->node == BGP_VPNV4_NODE - || vty->node == BGP_VPNV6_NODE - || vty->node == BGP_IPV6_NODE - || vty->node == BGP_IPV6L_NODE - || vty->node == BGP_IPV6M_NODE - || vty->node == BGP_EVPN_NODE) - vty->node = BGP_NODE; - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_BGPD, - exit_vni, - exit_vni_cmd, - "exit-vni", - "Exit from VNI mode\n") -{ - if (vty->node == BGP_EVPN_VNI_NODE) - vty->node = BGP_EVPN_NODE; - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_BGPD, - exit_vnc_config, - exit_vnc_config_cmd, - "exit-vnc", - "Exit from VNC configuration mode\n") -{ - if (vty->node == BGP_VNC_DEFAULTS_NODE - || vty->node == BGP_VNC_NVE_GROUP_NODE - || vty->node == BGP_VNC_L2_GROUP_NODE) - vty->node = BGP_NODE; - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_BGPD, - exit_vrf_policy, - exit_vrf_policy_cmd, - "exit-vrf-policy", - "Exit from VRF configuration mode\n") +DEFUNSH(VTYSH_BGPD, exit_vrf_policy, exit_vrf_policy_cmd, "exit-vrf-policy", + "Exit from VRF configuration mode\n") { - if (vty->node == BGP_VRF_POLICY_NODE) - vty->node = BGP_NODE; - return CMD_SUCCESS; + if (vty->node == BGP_VRF_POLICY_NODE) + vty->node = BGP_NODE; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_RIPD, - vtysh_exit_ripd, - vtysh_exit_ripd_cmd, - "exit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_RIPD, vtysh_exit_ripd, vtysh_exit_ripd_cmd, "exit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit (vty); + return vtysh_exit(vty); } -DEFUNSH (VTYSH_RIPD, - vtysh_quit_ripd, - vtysh_quit_ripd_cmd, - "quit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_RIPD, vtysh_quit_ripd, vtysh_quit_ripd_cmd, "quit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit_ripd (self, vty, argc, argv); + return vtysh_exit_ripd(self, vty, argc, argv); } -DEFUNSH (VTYSH_RIPNGD, - vtysh_exit_ripngd, - vtysh_exit_ripngd_cmd, - "exit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_RIPNGD, vtysh_exit_ripngd, vtysh_exit_ripngd_cmd, "exit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit (vty); + return vtysh_exit(vty); } -DEFUNSH (VTYSH_RIPNGD, - vtysh_quit_ripngd, - vtysh_quit_ripngd_cmd, - "quit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_RIPNGD, vtysh_quit_ripngd, vtysh_quit_ripngd_cmd, "quit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit_ripngd (self, vty, argc, argv); + return vtysh_exit_ripngd(self, vty, argc, argv); } -DEFUNSH (VTYSH_RMAP, - vtysh_exit_rmap, - vtysh_exit_rmap_cmd, - "exit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_RMAP, vtysh_exit_rmap, vtysh_exit_rmap_cmd, "exit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit (vty); + return vtysh_exit(vty); } -DEFUNSH (VTYSH_RMAP, - vtysh_quit_rmap, - vtysh_quit_rmap_cmd, - "quit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_RMAP, vtysh_quit_rmap, vtysh_quit_rmap_cmd, "quit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit_rmap (self, vty, argc, argv); + return vtysh_exit_rmap(self, vty, argc, argv); } -DEFUNSH (VTYSH_BGPD, - vtysh_exit_bgpd, - vtysh_exit_bgpd_cmd, - "exit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_BGPD, vtysh_exit_bgpd, vtysh_exit_bgpd_cmd, "exit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit (vty); + return vtysh_exit(vty); } -DEFUNSH (VTYSH_BGPD, - vtysh_quit_bgpd, - vtysh_quit_bgpd_cmd, - "quit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_BGPD, vtysh_quit_bgpd, vtysh_quit_bgpd_cmd, "quit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit_bgpd (self, vty, argc, argv); + return vtysh_exit_bgpd(self, vty, argc, argv); } -DEFUNSH (VTYSH_OSPFD, - vtysh_exit_ospfd, - vtysh_exit_ospfd_cmd, - "exit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_OSPFD, vtysh_exit_ospfd, vtysh_exit_ospfd_cmd, "exit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit (vty); + return vtysh_exit(vty); } -DEFUNSH (VTYSH_OSPFD, - vtysh_quit_ospfd, - vtysh_quit_ospfd_cmd, - "quit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_OSPFD, vtysh_quit_ospfd, vtysh_quit_ospfd_cmd, "quit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit_ospfd (self, vty, argc, argv); + return vtysh_exit_ospfd(self, vty, argc, argv); } -DEFUNSH (VTYSH_EIGRPD, - vtysh_exit_eigrpd, - vtysh_exit_eigrpd_cmd, - "exit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_EIGRPD, vtysh_exit_eigrpd, vtysh_exit_eigrpd_cmd, "exit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit (vty); + return vtysh_exit(vty); } -DEFUNSH (VTYSH_EIGRPD, - vtysh_quit_eigrpd, - vtysh_quit_eigrpd_cmd, - "quit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_EIGRPD, vtysh_quit_eigrpd, vtysh_quit_eigrpd_cmd, "quit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit (vty); + return vtysh_exit(vty); } -DEFUNSH (VTYSH_EIGRPD, - vtysh_exit_babeld, - vtysh_exit_babeld_cmd, - "exit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_EIGRPD, vtysh_exit_babeld, vtysh_exit_babeld_cmd, "exit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit (vty); + return vtysh_exit(vty); } -DEFUNSH (VTYSH_BABELD, - vtysh_quit_babeld, - vtysh_quit_babeld_cmd, - "quit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_BABELD, vtysh_quit_babeld, vtysh_quit_babeld_cmd, "quit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit (vty); + return vtysh_exit(vty); } -DEFUNSH (VTYSH_OSPF6D, - vtysh_exit_ospf6d, - vtysh_exit_ospf6d_cmd, - "exit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_OSPF6D, vtysh_exit_ospf6d, vtysh_exit_ospf6d_cmd, "exit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit (vty); + return vtysh_exit(vty); } -DEFUNSH (VTYSH_OSPF6D, - vtysh_quit_ospf6d, - vtysh_quit_ospf6d_cmd, - "quit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_OSPF6D, vtysh_quit_ospf6d, vtysh_quit_ospf6d_cmd, "quit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit_ospf6d (self, vty, argc, argv); + return vtysh_exit_ospf6d(self, vty, argc, argv); } -#if defined (HAVE_LDPD) -DEFUNSH (VTYSH_LDPD, - vtysh_exit_ldpd, - vtysh_exit_ldpd_cmd, - "exit", - "Exit current mode and down to previous mode\n") +#if defined(HAVE_LDPD) +DEFUNSH(VTYSH_LDPD, vtysh_exit_ldpd, vtysh_exit_ldpd_cmd, "exit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit (vty); + return vtysh_exit(vty); } -ALIAS (vtysh_exit_ldpd, - vtysh_quit_ldpd_cmd, - "quit", - "Exit current mode and down to previous mode\n") +ALIAS(vtysh_exit_ldpd, vtysh_quit_ldpd_cmd, "quit", + "Exit current mode and down to previous mode\n") #endif -DEFUNSH (VTYSH_ISISD, - vtysh_exit_isisd, - vtysh_exit_isisd_cmd, - "exit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_ISISD, vtysh_exit_isisd, vtysh_exit_isisd_cmd, "exit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit (vty); + return vtysh_exit(vty); } -DEFUNSH (VTYSH_ISISD, - vtysh_quit_isisd, - vtysh_quit_isisd_cmd, - "quit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_ISISD, vtysh_quit_isisd, vtysh_quit_isisd_cmd, "quit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit_isisd (self, vty, argc, argv); + return vtysh_exit_isisd(self, vty, argc, argv); } -DEFUNSH (VTYSH_ALL, - vtysh_exit_line_vty, - vtysh_exit_line_vty_cmd, - "exit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_ALL, vtysh_exit_line_vty, vtysh_exit_line_vty_cmd, "exit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit (vty); + return vtysh_exit(vty); } -DEFUNSH (VTYSH_ALL, - vtysh_quit_line_vty, - vtysh_quit_line_vty_cmd, - "quit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_ALL, vtysh_quit_line_vty, vtysh_quit_line_vty_cmd, "quit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit_line_vty (self, vty, argc, argv); + return vtysh_exit_line_vty(self, vty, argc, argv); } -DEFUNSH (VTYSH_INTERFACE, - vtysh_interface, - vtysh_interface_cmd, - "interface IFNAME [vrf NAME]", - "Select an interface to configure\n" - "Interface's name\n" - VRF_CMD_HELP_STR) +DEFUNSH(VTYSH_INTERFACE, vtysh_interface, vtysh_interface_cmd, + "interface IFNAME [vrf NAME]", + "Select an interface to configure\n" + "Interface's name\n" VRF_CMD_HELP_STR) { - vty->node = INTERFACE_NODE; - return CMD_SUCCESS; + vty->node = INTERFACE_NODE; + return CMD_SUCCESS; } /* TODO Implement "no interface command in isisd. */ -DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_EIGRPD, - vtysh_no_interface_cmd, - "no interface IFNAME", - NO_STR - "Delete a pseudo interface's configuration\n" - "Interface's name\n") +DEFSH(VTYSH_ZEBRA | VTYSH_RIPD | VTYSH_RIPNGD | VTYSH_OSPFD | VTYSH_OSPF6D + | VTYSH_EIGRPD, + vtysh_no_interface_cmd, "no interface IFNAME", NO_STR + "Delete a pseudo interface's configuration\n" + "Interface's name\n") -DEFSH (VTYSH_ZEBRA, - vtysh_no_interface_vrf_cmd, - "no interface IFNAME vrf NAME", - NO_STR - "Delete a pseudo interface's configuration\n" - "Interface's name\n" - VRF_CMD_HELP_STR) +DEFSH(VTYSH_ZEBRA, vtysh_no_interface_vrf_cmd, "no interface IFNAME vrf NAME", + NO_STR + "Delete a pseudo interface's configuration\n" + "Interface's name\n" VRF_CMD_HELP_STR) -DEFUNSH (VTYSH_NS, - vtysh_ns, - vtysh_ns_cmd, - "logical-router (1-65535) ns NAME", - "Enable a logical-router\n" - "Specify the logical-router indentifier\n" - "The Name Space\n" - "The file name in " NS_RUN_DIR ", or a full pathname\n") +DEFUNSH(VTYSH_NS, vtysh_ns, vtysh_ns_cmd, "logical-router (1-65535) ns NAME", + "Enable a logical-router\n" + "Specify the logical-router indentifier\n" + "The Name Space\n" + "The file name in " NS_RUN_DIR ", or a full pathname\n") { - vty->node = NS_NODE; - return CMD_SUCCESS; + vty->node = NS_NODE; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_VRF, - vtysh_vrf, - vtysh_vrf_cmd, - "vrf NAME", - "Select a VRF to configure\n" - "VRF's name\n") +DEFUNSH(VTYSH_VRF, vtysh_vrf, vtysh_vrf_cmd, "vrf NAME", + "Select a VRF to configure\n" + "VRF's name\n") { - vty->node = VRF_NODE; - return CMD_SUCCESS; + vty->node = VRF_NODE; + return CMD_SUCCESS; } -DEFSH (VTYSH_ZEBRA, - vtysh_no_vrf_cmd, - "no vrf NAME", - NO_STR - "Delete a pseudo vrf's configuration\n" - "VRF's name\n") +DEFSH(VTYSH_ZEBRA, vtysh_no_vrf_cmd, "no vrf NAME", NO_STR + "Delete a pseudo vrf's configuration\n" + "VRF's name\n") -DEFUNSH (VTYSH_NS, - vtysh_exit_ns, - vtysh_exit_ns_cmd, - "exit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_NS, vtysh_exit_ns, vtysh_exit_ns_cmd, "exit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit (vty); + return vtysh_exit(vty); } -DEFUNSH (VTYSH_NS, - vtysh_quit_ns, - vtysh_quit_ns_cmd, - "quit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_NS, vtysh_quit_ns, vtysh_quit_ns_cmd, "quit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit_ns(self, vty, argc, argv); + return vtysh_exit_ns(self, vty, argc, argv); } -DEFUNSH (VTYSH_VRF, - vtysh_exit_vrf, - vtysh_exit_vrf_cmd, - "exit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_VRF, vtysh_exit_vrf, vtysh_exit_vrf_cmd, "exit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit (vty); + return vtysh_exit(vty); } -DEFUNSH (VTYSH_VRF, - vtysh_quit_vrf, - vtysh_quit_vrf_cmd, - "quit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_VRF, vtysh_quit_vrf, vtysh_quit_vrf_cmd, "quit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit_vrf (self, vty, argc, argv); + return vtysh_exit_vrf(self, vty, argc, argv); } /* TODO Implement interface description commands in ripngd, ospf6d * and isisd. */ -DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD|VTYSH_EIGRPD, - vtysh_interface_desc_cmd, - "description LINE...", - "Interface specific description\n" - "Characters describing this interface\n") - -DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD|VTYSH_EIGRPD, - vtysh_no_interface_desc_cmd, - "no description", - NO_STR - "Interface specific description\n") +DEFSH(VTYSH_ZEBRA | VTYSH_RIPD | VTYSH_OSPFD | VTYSH_EIGRPD, + vtysh_interface_desc_cmd, "description LINE...", + "Interface specific description\n" + "Characters describing this interface\n") -DEFUNSH (VTYSH_INTERFACE, - vtysh_exit_interface, - vtysh_exit_interface_cmd, - "exit", - "Exit current mode and down to previous mode\n") +DEFSH(VTYSH_ZEBRA | VTYSH_RIPD | VTYSH_OSPFD | VTYSH_EIGRPD, + vtysh_no_interface_desc_cmd, "no description", + NO_STR "Interface specific description\n") + +DEFUNSH(VTYSH_INTERFACE, vtysh_exit_interface, vtysh_exit_interface_cmd, "exit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit (vty); + return vtysh_exit(vty); } -DEFUNSH (VTYSH_INTERFACE, - vtysh_quit_interface, - vtysh_quit_interface_cmd, - "quit", - "Exit current mode and down to previous mode\n") +DEFUNSH(VTYSH_INTERFACE, vtysh_quit_interface, vtysh_quit_interface_cmd, "quit", + "Exit current mode and down to previous mode\n") { - return vtysh_exit_interface (self, vty, argc, argv); + return vtysh_exit_interface(self, vty, argc, argv); } DEFUN (vtysh_show_thread, @@ -2091,23 +1715,24 @@ DEFUN (vtysh_show_thread, "Thread CPU usage\n" "Display filter (rwtexb)\n") { - unsigned int i; - int idx = 0; - int ret = CMD_SUCCESS; - char line[100]; + unsigned int i; + int idx = 0; + int ret = CMD_SUCCESS; + char line[100]; - const char *filter = argv_find (argv, argc, "FILTER", &idx) ? argv[idx]->arg : ""; + const char *filter = + argv_find(argv, argc, "FILTER", &idx) ? argv[idx]->arg : ""; - snprintf(line, sizeof(line), "do show thread cpu %s\n", filter); - for (i = 0; i < array_size(vtysh_client); i++) - if ( vtysh_client[i].fd >= 0 ) - { - fprintf (stdout, "Thread statistics for %s:\n", - vtysh_client[i].name); - ret = vtysh_client_execute (&vtysh_client[i], line, stdout); - fprintf (stdout,"\n"); - } - return ret; + snprintf(line, sizeof(line), "do show thread cpu %s\n", filter); + for (i = 0; i < array_size(vtysh_client); i++) + if (vtysh_client[i].fd >= 0) { + fprintf(stdout, "Thread statistics for %s:\n", + vtysh_client[i].name); + ret = vtysh_client_execute(&vtysh_client[i], line, + stdout); + fprintf(stdout, "\n"); + } + return ret; } DEFUN (vtysh_show_work_queues, @@ -2116,20 +1741,20 @@ DEFUN (vtysh_show_work_queues, SHOW_STR "Work Queue information\n") { - unsigned int i; - int ret = CMD_SUCCESS; - char line[] = "do show work-queues\n"; + unsigned int i; + int ret = CMD_SUCCESS; + char line[] = "do show work-queues\n"; - for (i = 0; i < array_size(vtysh_client); i++) - if ( vtysh_client[i].fd >= 0 ) - { - fprintf (stdout, "Work queue statistics for %s:\n", - vtysh_client[i].name); - ret = vtysh_client_execute (&vtysh_client[i], line, stdout); - fprintf (stdout,"\n"); - } + for (i = 0; i < array_size(vtysh_client); i++) + if (vtysh_client[i].fd >= 0) { + fprintf(stdout, "Work queue statistics for %s:\n", + vtysh_client[i].name); + ret = vtysh_client_execute(&vtysh_client[i], line, + stdout); + fprintf(stdout, "\n"); + } - return ret; + return ret; } DEFUN (vtysh_show_work_queues_daemon, @@ -2145,19 +1770,19 @@ DEFUN (vtysh_show_work_queues_daemon, "For the bgp daemon\n" "For the isis daemon\n") { - int idx_protocol = 2; - unsigned int i; - int ret = CMD_SUCCESS; + int idx_protocol = 2; + unsigned int i; + int ret = CMD_SUCCESS; - for (i = 0; i < array_size(vtysh_client); i++) - { - if (strmatch(vtysh_client[i].name, argv[idx_protocol]->text)) - break; - } + for (i = 0; i < array_size(vtysh_client); i++) { + if (strmatch(vtysh_client[i].name, argv[idx_protocol]->text)) + break; + } - ret = vtysh_client_execute(&vtysh_client[i], "show work-queues\n", stdout); + ret = vtysh_client_execute(&vtysh_client[i], "show work-queues\n", + stdout); - return ret; + return ret; } DEFUN (vtysh_show_hashtable, @@ -2167,64 +1792,60 @@ DEFUN (vtysh_show_hashtable, "Statistics about hash tables\n" "Statistics about hash tables\n") { - char cmd[] = "do show hashtable statistics"; - unsigned long i; - int ret = CMD_SUCCESS; + char cmd[] = "do show hashtable statistics"; + unsigned long i; + int ret = CMD_SUCCESS; - fprintf (stdout, "\n"); - fprintf (stdout, "Load factor (LF) - average number of elements across all buckets\n"); - fprintf (stdout, "Full load factor (FLF) - average number of elements across full buckets\n\n"); + fprintf(stdout, "\n"); + fprintf(stdout, + "Load factor (LF) - average number of elements across all buckets\n"); + fprintf(stdout, + "Full load factor (FLF) - average number of elements across full buckets\n\n"); - fprintf (stdout, "Standard deviation (SD) is calculated for both the LF and FLF\n"); - fprintf (stdout, "and indicates the typical deviation of bucket chain length\n"); - fprintf (stdout, "from the value in the corresponding load factor.\n\n"); + fprintf(stdout, + "Standard deviation (SD) is calculated for both the LF and FLF\n"); + fprintf(stdout, + "and indicates the typical deviation of bucket chain length\n"); + fprintf(stdout, "from the value in the corresponding load factor.\n\n"); - for (i = 0; i < array_size(vtysh_client); i++) - if ( vtysh_client[i].fd >= 0 ) { - ret = vtysh_client_execute (&vtysh_client[i], cmd, stdout); - fprintf (stdout, "\n"); - } - return ret; + for (i = 0; i < array_size(vtysh_client); i++) + if (vtysh_client[i].fd >= 0) { + ret = vtysh_client_execute(&vtysh_client[i], cmd, + stdout); + fprintf(stdout, "\n"); + } + return ret; } -DEFUNSH (VTYSH_ZEBRA, - vtysh_link_params, - vtysh_link_params_cmd, - "link-params", - LINK_PARAMS_STR - ) +DEFUNSH(VTYSH_ZEBRA, vtysh_link_params, vtysh_link_params_cmd, "link-params", + LINK_PARAMS_STR) { - vty->node = LINK_PARAMS_NODE; - return CMD_SUCCESS; + vty->node = LINK_PARAMS_NODE; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_ZEBRA, - exit_link_params, - exit_link_params_cmd, - "exit-link-params", - "Exit from Link Params configuration node\n") +DEFUNSH(VTYSH_ZEBRA, exit_link_params, exit_link_params_cmd, "exit-link-params", + "Exit from Link Params configuration node\n") { - if (vty->node == LINK_PARAMS_NODE) - vty->node = INTERFACE_NODE; - return CMD_SUCCESS; + if (vty->node == LINK_PARAMS_NODE) + vty->node = INTERFACE_NODE; + return CMD_SUCCESS; } -static int -show_per_daemon (const char *line, const char *headline) +static int show_per_daemon(const char *line, const char *headline) { - unsigned int i; - int ret = CMD_SUCCESS; + unsigned int i; + int ret = CMD_SUCCESS; - for (i = 0; i < array_size(vtysh_client); i++) - if ( vtysh_client[i].fd >= 0 ) - { - fprintf (stdout, headline, - vtysh_client[i].name); - ret = vtysh_client_execute (&vtysh_client[i], line, stdout); - fprintf (stdout,"\n"); - } + for (i = 0; i < array_size(vtysh_client); i++) + if (vtysh_client[i].fd >= 0) { + fprintf(stdout, headline, vtysh_client[i].name); + ret = vtysh_client_execute(&vtysh_client[i], line, + stdout); + fprintf(stdout, "\n"); + } - return ret; + return ret; } /* Memory */ @@ -2234,7 +1855,7 @@ DEFUN (vtysh_show_memory, SHOW_STR "Memory statistics\n") { - return show_per_daemon ("show memory\n", "Memory statistics for %s:\n"); + return show_per_daemon("show memory\n", "Memory statistics for %s:\n"); } DEFUN (vtysh_show_modules, @@ -2243,7 +1864,8 @@ DEFUN (vtysh_show_modules, SHOW_STR "Loaded modules\n") { - return show_per_daemon ("show modules\n", "Module information for %s:\n"); + return show_per_daemon("show modules\n", + "Module information for %s:\n"); } /* Logging commands. */ @@ -2253,284 +1875,223 @@ DEFUN (vtysh_show_logging, SHOW_STR "Show current logging configuration\n") { - unsigned int i; - int ret = CMD_SUCCESS; - char line[] = "do show logging\n"; - - for (i = 0; i < array_size(vtysh_client); i++) - if ( vtysh_client[i].fd >= 0 ) - { - fprintf (stdout,"Logging configuration for %s:\n", - vtysh_client[i].name); - ret = vtysh_client_execute (&vtysh_client[i], line, stdout); - fprintf (stdout,"\n"); - } - - return ret; -} - -DEFUNSH (VTYSH_ALL, - vtysh_log_stdout, - vtysh_log_stdout_cmd, - "log stdout", - "Logging control\n" - "Set stdout logging level\n") -{ - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_ALL, - vtysh_log_stdout_level, - vtysh_log_stdout_level_cmd, - "log stdout ", - "Logging control\n" - "Set stdout logging level\n" - LOG_LEVEL_DESC) + unsigned int i; + int ret = CMD_SUCCESS; + char line[] = "do show logging\n"; + + for (i = 0; i < array_size(vtysh_client); i++) + if (vtysh_client[i].fd >= 0) { + fprintf(stdout, "Logging configuration for %s:\n", + vtysh_client[i].name); + ret = vtysh_client_execute(&vtysh_client[i], line, + stdout); + fprintf(stdout, "\n"); + } + + return ret; +} + +DEFUNSH(VTYSH_ALL, vtysh_log_stdout, vtysh_log_stdout_cmd, "log stdout", + "Logging control\n" + "Set stdout logging level\n") { - return CMD_SUCCESS; -} - -DEFUNSH (VTYSH_ALL, - no_vtysh_log_stdout, - no_vtysh_log_stdout_cmd, - "no log stdout [LEVEL]", - NO_STR - "Logging control\n" - "Cancel logging to stdout\n" - "Logging level\n") + return CMD_SUCCESS; +} + +DEFUNSH(VTYSH_ALL, vtysh_log_stdout_level, vtysh_log_stdout_level_cmd, + "log stdout ", + "Logging control\n" + "Set stdout logging level\n" LOG_LEVEL_DESC) { - return CMD_SUCCESS; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_ALL, - vtysh_log_file, - vtysh_log_file_cmd, - "log file FILENAME", - "Logging control\n" - "Logging to file\n" - "Logging filename\n") +DEFUNSH(VTYSH_ALL, no_vtysh_log_stdout, no_vtysh_log_stdout_cmd, + "no log stdout [LEVEL]", NO_STR + "Logging control\n" + "Cancel logging to stdout\n" + "Logging level\n") { - return CMD_SUCCESS; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_ALL, - vtysh_log_file_level, - vtysh_log_file_level_cmd, - "log file FILENAME ", - "Logging control\n" - "Logging to file\n" - "Logging filename\n" - LOG_LEVEL_DESC) +DEFUNSH(VTYSH_ALL, vtysh_log_file, vtysh_log_file_cmd, "log file FILENAME", + "Logging control\n" + "Logging to file\n" + "Logging filename\n") { - return CMD_SUCCESS; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_ALL, - no_vtysh_log_file, - no_vtysh_log_file_cmd, - "no log file [FILENAME [LEVEL]]", - NO_STR - "Logging control\n" - "Cancel logging to file\n" - "Logging file name\n" - "Logging level\n") +DEFUNSH(VTYSH_ALL, vtysh_log_file_level, vtysh_log_file_level_cmd, + "log file FILENAME ", + "Logging control\n" + "Logging to file\n" + "Logging filename\n" LOG_LEVEL_DESC) { - return CMD_SUCCESS; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_ALL, - vtysh_log_monitor, - vtysh_log_monitor_cmd, - "log monitor []", - "Logging control\n" - "Set terminal line (monitor) logging level\n" - LOG_LEVEL_DESC) +DEFUNSH(VTYSH_ALL, no_vtysh_log_file, no_vtysh_log_file_cmd, + "no log file [FILENAME [LEVEL]]", NO_STR + "Logging control\n" + "Cancel logging to file\n" + "Logging file name\n" + "Logging level\n") { - return CMD_SUCCESS; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_ALL, - no_vtysh_log_monitor, - no_vtysh_log_monitor_cmd, - "no log monitor [LEVEL]", - NO_STR - "Logging control\n" - "Disable terminal line (monitor) logging\n" - "Logging level\n") +DEFUNSH(VTYSH_ALL, vtysh_log_monitor, vtysh_log_monitor_cmd, + "log monitor []", + "Logging control\n" + "Set terminal line (monitor) logging level\n" LOG_LEVEL_DESC) { - return CMD_SUCCESS; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_ALL, - vtysh_log_syslog, - vtysh_log_syslog_cmd, - "log syslog []", - "Logging control\n" - "Set syslog logging level\n" - LOG_LEVEL_DESC) +DEFUNSH(VTYSH_ALL, no_vtysh_log_monitor, no_vtysh_log_monitor_cmd, + "no log monitor [LEVEL]", NO_STR + "Logging control\n" + "Disable terminal line (monitor) logging\n" + "Logging level\n") { - return CMD_SUCCESS; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_ALL, - no_vtysh_log_syslog, - no_vtysh_log_syslog_cmd, - "no log syslog [LEVEL]", - NO_STR - "Logging control\n" - "Cancel logging to syslog\n" - "Logging level\n") +DEFUNSH(VTYSH_ALL, vtysh_log_syslog, vtysh_log_syslog_cmd, + "log syslog []", + "Logging control\n" + "Set syslog logging level\n" LOG_LEVEL_DESC) { - return CMD_SUCCESS; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_ALL, - vtysh_log_facility, - vtysh_log_facility_cmd, - "log facility ", - "Logging control\n" - "Facility parameter for syslog messages\n" - LOG_FACILITY_DESC) +DEFUNSH(VTYSH_ALL, no_vtysh_log_syslog, no_vtysh_log_syslog_cmd, + "no log syslog [LEVEL]", NO_STR + "Logging control\n" + "Cancel logging to syslog\n" + "Logging level\n") +{ + return CMD_SUCCESS; +} + +DEFUNSH(VTYSH_ALL, vtysh_log_facility, vtysh_log_facility_cmd, + "log facility ", + "Logging control\n" + "Facility parameter for syslog messages\n" LOG_FACILITY_DESC) { - return CMD_SUCCESS; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_ALL, - no_vtysh_log_facility, - no_vtysh_log_facility_cmd, - "no log facility [FACILITY]", - NO_STR - "Logging control\n" - "Reset syslog facility to default (daemon)\n" - "Syslog facility\n") +DEFUNSH(VTYSH_ALL, no_vtysh_log_facility, no_vtysh_log_facility_cmd, + "no log facility [FACILITY]", NO_STR + "Logging control\n" + "Reset syslog facility to default (daemon)\n" + "Syslog facility\n") { - return CMD_SUCCESS; + return CMD_SUCCESS; } -DEFUNSH_DEPRECATED (VTYSH_ALL, - vtysh_log_trap, - vtysh_log_trap_cmd, - "log trap ", - "Logging control\n" - "(Deprecated) Set logging level and default for all destinations\n" - LOG_LEVEL_DESC) +DEFUNSH_DEPRECATED( + VTYSH_ALL, vtysh_log_trap, vtysh_log_trap_cmd, + "log trap ", + "Logging control\n" + "(Deprecated) Set logging level and default for all destinations\n" LOG_LEVEL_DESC) { - return CMD_SUCCESS; + return CMD_SUCCESS; } -DEFUNSH_DEPRECATED (VTYSH_ALL, - no_vtysh_log_trap, - no_vtysh_log_trap_cmd, - "no log trap [LEVEL]", - NO_STR - "Logging control\n" - "Permit all logging information\n" - "Logging level\n") +DEFUNSH_DEPRECATED(VTYSH_ALL, no_vtysh_log_trap, no_vtysh_log_trap_cmd, + "no log trap [LEVEL]", NO_STR + "Logging control\n" + "Permit all logging information\n" + "Logging level\n") { - return CMD_SUCCESS; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_ALL, - vtysh_log_record_priority, - vtysh_log_record_priority_cmd, - "log record-priority", - "Logging control\n" - "Log the priority of the message within the message\n") +DEFUNSH(VTYSH_ALL, vtysh_log_record_priority, vtysh_log_record_priority_cmd, + "log record-priority", + "Logging control\n" + "Log the priority of the message within the message\n") { - return CMD_SUCCESS; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_ALL, - no_vtysh_log_record_priority, - no_vtysh_log_record_priority_cmd, - "no log record-priority", - NO_STR - "Logging control\n" - "Do not log the priority of the message within the message\n") +DEFUNSH(VTYSH_ALL, no_vtysh_log_record_priority, + no_vtysh_log_record_priority_cmd, "no log record-priority", NO_STR + "Logging control\n" + "Do not log the priority of the message within the message\n") { - return CMD_SUCCESS; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_ALL, - vtysh_log_timestamp_precision, - vtysh_log_timestamp_precision_cmd, - "log timestamp precision (0-6)", - "Logging control\n" - "Timestamp configuration\n" - "Set the timestamp precision\n" - "Number of subsecond digits\n") +DEFUNSH(VTYSH_ALL, vtysh_log_timestamp_precision, + vtysh_log_timestamp_precision_cmd, "log timestamp precision (0-6)", + "Logging control\n" + "Timestamp configuration\n" + "Set the timestamp precision\n" + "Number of subsecond digits\n") { - return CMD_SUCCESS; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_ALL, - no_vtysh_log_timestamp_precision, - no_vtysh_log_timestamp_precision_cmd, - "no log timestamp precision", - NO_STR - "Logging control\n" - "Timestamp configuration\n" - "Reset the timestamp precision to the default value of 0\n") +DEFUNSH(VTYSH_ALL, no_vtysh_log_timestamp_precision, + no_vtysh_log_timestamp_precision_cmd, "no log timestamp precision", + NO_STR + "Logging control\n" + "Timestamp configuration\n" + "Reset the timestamp precision to the default value of 0\n") { - return CMD_SUCCESS; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_ALL, - vtysh_service_password_encrypt, - vtysh_service_password_encrypt_cmd, - "service password-encryption", - "Set up miscellaneous service\n" - "Enable encrypted passwords\n") +DEFUNSH(VTYSH_ALL, vtysh_service_password_encrypt, + vtysh_service_password_encrypt_cmd, "service password-encryption", + "Set up miscellaneous service\n" + "Enable encrypted passwords\n") { - return CMD_SUCCESS; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_ALL, - no_vtysh_service_password_encrypt, - no_vtysh_service_password_encrypt_cmd, - "no service password-encryption", - NO_STR - "Set up miscellaneous service\n" - "Enable encrypted passwords\n") +DEFUNSH(VTYSH_ALL, no_vtysh_service_password_encrypt, + no_vtysh_service_password_encrypt_cmd, "no service password-encryption", + NO_STR + "Set up miscellaneous service\n" + "Enable encrypted passwords\n") { - return CMD_SUCCESS; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_ALL, - vtysh_config_password, - vtysh_password_cmd, - "password [(8-8)] LINE", - "Assign the terminal connection password\n" - "Specifies a HIDDEN password will follow\n" - "The password string\n") +DEFUNSH(VTYSH_ALL, vtysh_config_password, vtysh_password_cmd, + "password [(8-8)] LINE", + "Assign the terminal connection password\n" + "Specifies a HIDDEN password will follow\n" + "The password string\n") { - return CMD_SUCCESS; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_ALL, - vtysh_config_enable_password, - vtysh_enable_password_cmd, - "enable password [(8-8)] LINE", - "Modify enable password parameters\n" - "Assign the privileged level password\n" - "Specifies a HIDDEN password will follow\n" - "The 'enable' password string\n") +DEFUNSH(VTYSH_ALL, vtysh_config_enable_password, vtysh_enable_password_cmd, + "enable password [(8-8)] LINE", + "Modify enable password parameters\n" + "Assign the privileged level password\n" + "Specifies a HIDDEN password will follow\n" + "The 'enable' password string\n") { - return CMD_SUCCESS; + return CMD_SUCCESS; } -DEFUNSH (VTYSH_ALL, - no_vtysh_config_enable_password, - no_vtysh_enable_password_cmd, - "no enable password", - NO_STR - "Modify enable password parameters\n" - "Assign the privileged level password\n") +DEFUNSH(VTYSH_ALL, no_vtysh_config_enable_password, + no_vtysh_enable_password_cmd, "no enable password", NO_STR + "Modify enable password parameters\n" + "Assign the privileged level password\n") { - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (vtysh_write_terminal, @@ -2548,48 +2109,44 @@ DEFUN (vtysh_write_terminal, "For the isis daemon\n" "For the pim daemon\n") { - u_int i; - char line[] = "do write terminal\n"; - FILE *fp = NULL; - - if (vtysh_pager_name) - { - fp = popen (vtysh_pager_name, "w"); - if (fp == NULL) - { - perror ("popen"); - exit (1); - } - } - else - fp = stdout; - - vty_out (vty, "Building configuration...\n"); - vty_out (vty, "\nCurrent configuration:\n"); - vty_out (vty, "!\n"); - - for (i = 0; i < array_size(vtysh_client); i++) - if ((argc < 3 ) || (strmatch (vtysh_client[i].name, argv[2]->text))) - vtysh_client_config (&vtysh_client[i], line); - - /* Integrate vtysh specific configuration. */ - vtysh_config_write (); - - vtysh_config_dump (fp); - - if (vtysh_pager_name && fp) - { - fflush (fp); - if (pclose (fp) == -1) - { - perror ("pclose"); - exit (1); - } - fp = NULL; - } - - vty_out (vty, "end\n"); - return CMD_SUCCESS; + u_int i; + char line[] = "do write terminal\n"; + FILE *fp = NULL; + + if (vtysh_pager_name) { + fp = popen(vtysh_pager_name, "w"); + if (fp == NULL) { + perror("popen"); + exit(1); + } + } else + fp = stdout; + + vty_out(vty, "Building configuration...\n"); + vty_out(vty, "\nCurrent configuration:\n"); + vty_out(vty, "!\n"); + + for (i = 0; i < array_size(vtysh_client); i++) + if ((argc < 3) + || (strmatch(vtysh_client[i].name, argv[2]->text))) + vtysh_client_config(&vtysh_client[i], line); + + /* Integrate vtysh specific configuration. */ + vtysh_config_write(); + + vtysh_config_dump(fp); + + if (vtysh_pager_name && fp) { + fflush(fp); + if (pclose(fp) == -1) { + perror("pclose"); + exit(1); + } + fp = NULL; + } + + vty_out(vty, "end\n"); + return CMD_SUCCESS; } DEFUN (vtysh_show_running_config, @@ -2607,7 +2164,7 @@ DEFUN (vtysh_show_running_config, "For the isis daemon\n" "For the pim daemon\n") { - return vtysh_write_terminal (self, vty, argc, argv); + return vtysh_write_terminal(self, vty, argc, argv); } DEFUN (vtysh_integrated_config, @@ -2616,8 +2173,8 @@ DEFUN (vtysh_integrated_config, "Set up miscellaneous service\n" "Write configuration into integrated file\n") { - vtysh_write_integrated = WRITE_INTEGRATED_YES; - return CMD_SUCCESS; + vtysh_write_integrated = WRITE_INTEGRATED_YES; + return CMD_SUCCESS; } DEFUN (no_vtysh_integrated_config, @@ -2627,132 +2184,123 @@ DEFUN (no_vtysh_integrated_config, "Set up miscellaneous service\n" "Write configuration into integrated file\n") { - vtysh_write_integrated = WRITE_INTEGRATED_NO; - return CMD_SUCCESS; + vtysh_write_integrated = WRITE_INTEGRATED_NO; + return CMD_SUCCESS; } -static void -backup_config_file (const char *fbackup) +static void backup_config_file(const char *fbackup) { - char *integrate_sav = NULL; + char *integrate_sav = NULL; - integrate_sav = malloc (strlen (fbackup) + - strlen (CONF_BACKUP_EXT) + 1); - strcpy (integrate_sav, fbackup); - strcat (integrate_sav, CONF_BACKUP_EXT); + integrate_sav = malloc(strlen(fbackup) + strlen(CONF_BACKUP_EXT) + 1); + strcpy(integrate_sav, fbackup); + strcat(integrate_sav, CONF_BACKUP_EXT); - /* Move current configuration file to backup config file. */ - unlink (integrate_sav); - rename (fbackup, integrate_sav); - free (integrate_sav); + /* Move current configuration file to backup config file. */ + unlink(integrate_sav); + rename(fbackup, integrate_sav); + free(integrate_sav); } -int -vtysh_write_config_integrated(void) +int vtysh_write_config_integrated(void) { - u_int i; - char line[] = "do write terminal\n"; - FILE *fp; - int fd; - struct passwd *pwentry; - struct group *grentry; - uid_t uid = -1; - gid_t gid = -1; - struct stat st; - int err = 0; + u_int i; + char line[] = "do write terminal\n"; + FILE *fp; + int fd; + struct passwd *pwentry; + struct group *grentry; + uid_t uid = -1; + gid_t gid = -1; + struct stat st; + int err = 0; - fprintf (stdout,"Building Configuration...\n"); + fprintf(stdout, "Building Configuration...\n"); - backup_config_file(quagga_config); - fp = fopen (quagga_config, "w"); - if (fp == NULL) - { - fprintf (stdout,"%% Error: failed to open configuration file %s: %s\n", - quagga_config, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - fd = fileno (fp); + backup_config_file(quagga_config); + fp = fopen(quagga_config, "w"); + if (fp == NULL) { + fprintf(stdout, + "%% Error: failed to open configuration file %s: %s\n", + quagga_config, safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + fd = fileno(fp); - for (i = 0; i < array_size(vtysh_client); i++) - vtysh_client_config (&vtysh_client[i], line); + for (i = 0; i < array_size(vtysh_client); i++) + vtysh_client_config(&vtysh_client[i], line); - vtysh_config_write (); - vtysh_config_dump (fp); + vtysh_config_write(); + vtysh_config_dump(fp); - if (fchmod (fd, CONFIGFILE_MASK) != 0) - { - printf ("%% Warning: can't chmod configuration file %s: %s\n", - quagga_config, safe_strerror(errno)); - err++; - } + if (fchmod(fd, CONFIGFILE_MASK) != 0) { + printf("%% Warning: can't chmod configuration file %s: %s\n", + quagga_config, safe_strerror(errno)); + err++; + } #ifdef FRR_USER - pwentry = getpwnam (FRR_USER); - if (pwentry) - uid = pwentry->pw_uid; - else - { - printf ("%% Warning: could not look up user \"%s\"\n", FRR_USER); - err++; - } + pwentry = getpwnam(FRR_USER); + if (pwentry) + uid = pwentry->pw_uid; + else { + printf("%% Warning: could not look up user \"%s\"\n", FRR_USER); + err++; + } #endif #ifdef FRR_GROUP - grentry = getgrnam (FRR_GROUP); - if (grentry) - gid = grentry->gr_gid; - else - { - printf ("%% Warning: could not look up group \"%s\"\n", FRR_GROUP); - err++; - } + grentry = getgrnam(FRR_GROUP); + if (grentry) + gid = grentry->gr_gid; + else { + printf("%% Warning: could not look up group \"%s\"\n", + FRR_GROUP); + err++; + } #endif - if (!fstat (fd, &st)) - { - if (st.st_uid == uid) - uid = -1; - if (st.st_gid == gid) - gid = -1; - if ((uid != (uid_t)-1 || gid != (gid_t)-1) && fchown (fd, uid, gid)) - { - printf ("%% Warning: can't chown configuration file %s: %s\n", - quagga_config, safe_strerror(errno)); - err++; - } - } - else - { - printf ("%% Warning: stat() failed on %s: %s\n", - quagga_config, safe_strerror(errno)); - err++; - } - - fclose (fp); - - printf ("Integrated configuration saved to %s\n", quagga_config); - if (err) - return CMD_WARNING; - - printf ("[OK]\n"); - return CMD_SUCCESS; + if (!fstat(fd, &st)) { + if (st.st_uid == uid) + uid = -1; + if (st.st_gid == gid) + gid = -1; + if ((uid != (uid_t)-1 || gid != (gid_t)-1) + && fchown(fd, uid, gid)) { + printf("%% Warning: can't chown configuration file %s: %s\n", + quagga_config, safe_strerror(errno)); + err++; + } + } else { + printf("%% Warning: stat() failed on %s: %s\n", quagga_config, + safe_strerror(errno)); + err++; + } + + fclose(fp); + + printf("Integrated configuration saved to %s\n", quagga_config); + if (err) + return CMD_WARNING; + + printf("[OK]\n"); + return CMD_SUCCESS; } static bool want_config_integrated(void) { - struct stat s; - - switch (vtysh_write_integrated) - { - case WRITE_INTEGRATED_UNSPECIFIED: - if (stat(quagga_config, &s) && errno == ENOENT) - return false; - return true; - case WRITE_INTEGRATED_NO: - return false; - case WRITE_INTEGRATED_YES: - return true; - } - return true; + struct stat s; + + switch (vtysh_write_integrated) { + case WRITE_INTEGRATED_UNSPECIFIED: + if (stat(quagga_config, &s) && errno == ENOENT) + return false; + return true; + case WRITE_INTEGRATED_NO: + return false; + case WRITE_INTEGRATED_YES: + return true; + } + return true; } DEFUN (vtysh_write_memory, @@ -2762,38 +2310,39 @@ DEFUN (vtysh_write_memory, "Write configuration to the file (same as write file)\n" "Write configuration to the file (same as write memory)\n") { - int ret = CMD_SUCCESS; - char line[] = "do write memory\n"; - u_int i; - - fprintf (stdout, "Note: this version of vtysh never writes vtysh.conf\n"); - - /* If integrated frr.conf explicitely set. */ - if (want_config_integrated()) - { - ret = CMD_WARNING_CONFIG_FAILED; - for (i = 0; i < array_size(vtysh_client); i++) - if (vtysh_client[i].flag == VTYSH_WATCHFRR) - break; - if (i < array_size(vtysh_client) && vtysh_client[i].fd != -1) - ret = vtysh_client_execute (&vtysh_client[i], "do write integrated", stdout); - - if (ret != CMD_SUCCESS) - { - printf("\nWarning: attempting direct configuration write without " - "watchfrr.\nFile permissions and ownership may be " - "incorrect, or write may fail.\n\n"); - ret = vtysh_write_config_integrated(); - } - return ret; - } + int ret = CMD_SUCCESS; + char line[] = "do write memory\n"; + u_int i; + + fprintf(stdout, + "Note: this version of vtysh never writes vtysh.conf\n"); + + /* If integrated frr.conf explicitely set. */ + if (want_config_integrated()) { + ret = CMD_WARNING_CONFIG_FAILED; + for (i = 0; i < array_size(vtysh_client); i++) + if (vtysh_client[i].flag == VTYSH_WATCHFRR) + break; + if (i < array_size(vtysh_client) && vtysh_client[i].fd != -1) + ret = vtysh_client_execute(&vtysh_client[i], + "do write integrated", + stdout); + + if (ret != CMD_SUCCESS) { + printf("\nWarning: attempting direct configuration write without " + "watchfrr.\nFile permissions and ownership may be " + "incorrect, or write may fail.\n\n"); + ret = vtysh_write_config_integrated(); + } + return ret; + } - fprintf (stdout,"Building Configuration...\n"); + fprintf(stdout, "Building Configuration...\n"); - for (i = 0; i < array_size(vtysh_client); i++) - ret = vtysh_client_execute (&vtysh_client[i], line, stdout); + for (i = 0; i < array_size(vtysh_client); i++) + ret = vtysh_client_execute(&vtysh_client[i], line, stdout); - return ret; + return ret; } DEFUN (vtysh_copy_running_config, @@ -2803,7 +2352,7 @@ DEFUN (vtysh_copy_running_config, "Copy from current system configuration\n" "Copy to startup configuration\n") { - return vtysh_write_memory (self, vty, argc, argv); + return vtysh_write_memory(self, vty, argc, argv); } DEFUN (vtysh_terminal_length, @@ -2813,31 +2362,28 @@ DEFUN (vtysh_terminal_length, "Set number of lines on a screen\n" "Number of lines on screen (0 for no pausing)\n") { - int idx_number = 2; - int lines; - char *endptr = NULL; - char default_pager[10]; + int idx_number = 2; + int lines; + char *endptr = NULL; + char default_pager[10]; - lines = strtol (argv[idx_number]->arg, &endptr, 10); - if (lines < 0 || lines > 512 || *endptr != '\0') - { - vty_out (vty, "length is malformed\n"); - return CMD_WARNING; - } + lines = strtol(argv[idx_number]->arg, &endptr, 10); + if (lines < 0 || lines > 512 || *endptr != '\0') { + vty_out(vty, "length is malformed\n"); + return CMD_WARNING; + } - if (vtysh_pager_name) - { - free (vtysh_pager_name); - vtysh_pager_name = NULL; - } + if (vtysh_pager_name) { + free(vtysh_pager_name); + vtysh_pager_name = NULL; + } - if (lines != 0) - { - snprintf(default_pager, 10, "more -%i", lines); - vtysh_pager_name = strdup (default_pager); - } + if (lines != 0) { + snprintf(default_pager, 10, "more -%i", lines); + vtysh_pager_name = strdup(default_pager); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (vtysh_terminal_no_length, @@ -2847,14 +2393,13 @@ DEFUN (vtysh_terminal_no_length, NO_STR "Set number of lines on a screen\n") { - if (vtysh_pager_name) - { - free (vtysh_pager_name); - vtysh_pager_name = NULL; - } + if (vtysh_pager_name) { + free(vtysh_pager_name); + vtysh_pager_name = NULL; + } - vtysh_pager_init(); - return CMD_SUCCESS; + vtysh_pager_init(); + return CMD_SUCCESS; } DEFUN (vtysh_show_daemons, @@ -2863,60 +2408,55 @@ DEFUN (vtysh_show_daemons, SHOW_STR "Show list of running daemons\n") { - u_int i; + u_int i; - for (i = 0; i < array_size(vtysh_client); i++) - if ( vtysh_client[i].fd >= 0 ) - vty_out(vty, " %s", vtysh_client[i].name); - vty_out (vty, "\n"); + for (i = 0; i < array_size(vtysh_client); i++) + if (vtysh_client[i].fd >= 0) + vty_out(vty, " %s", vtysh_client[i].name); + vty_out(vty, "\n"); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Execute command in child process. */ -static void -execute_command (const char *command, int argc, struct cmd_token *arg1, - const char *arg2) -{ - pid_t pid; - int status; - - /* Call fork(). */ - pid = fork (); - - if (pid < 0) - { - /* Failure of fork(). */ - fprintf (stderr, "Can't fork: %s\n", safe_strerror (errno)); - exit (1); - } - else if (pid == 0) - { - /* This is child process. */ - switch (argc) - { - case 0: - execlp (command, command, (const char *)NULL); - break; - case 1: - execlp (command, command, arg1, (const char *)NULL); - break; - case 2: - execlp (command, command, arg1, arg2, (const char *)NULL); - break; - } +static void execute_command(const char *command, int argc, + struct cmd_token *arg1, const char *arg2) +{ + pid_t pid; + int status; + + /* Call fork(). */ + pid = fork(); + + if (pid < 0) { + /* Failure of fork(). */ + fprintf(stderr, "Can't fork: %s\n", safe_strerror(errno)); + exit(1); + } else if (pid == 0) { + /* This is child process. */ + switch (argc) { + case 0: + execlp(command, command, (const char *)NULL); + break; + case 1: + execlp(command, command, arg1, (const char *)NULL); + break; + case 2: + execlp(command, command, arg1, arg2, + (const char *)NULL); + break; + } - /* When execlp suceed, this part is not executed. */ - fprintf (stderr, "Can't execute %s: %s\n", command, safe_strerror (errno)); - exit (1); - } - else - { - /* This is parent. */ - execute_flag = 1; - wait4 (pid, &status, 0, NULL); - execute_flag = 0; - } + /* When execlp suceed, this part is not executed. */ + fprintf(stderr, "Can't execute %s: %s\n", command, + safe_strerror(errno)); + exit(1); + } else { + /* This is parent. */ + execute_flag = 1; + wait4(pid, &status, 0, NULL); + execute_flag = 0; + } } DEFUN (vtysh_ping, @@ -2925,16 +2465,14 @@ DEFUN (vtysh_ping, "Send echo messages\n" "Ping destination address or hostname\n") { - execute_command ("ping", 1, argv[0], NULL); - return CMD_SUCCESS; + execute_command("ping", 1, argv[0], NULL); + return CMD_SUCCESS; } -ALIAS (vtysh_ping, - vtysh_ping_ip_cmd, - "ping ip WORD", - "Send echo messages\n" - "IP echo\n" - "Ping destination address or hostname\n") +ALIAS(vtysh_ping, vtysh_ping_ip_cmd, "ping ip WORD", + "Send echo messages\n" + "IP echo\n" + "Ping destination address or hostname\n") DEFUN (vtysh_traceroute, vtysh_traceroute_cmd, @@ -2942,16 +2480,14 @@ DEFUN (vtysh_traceroute, "Trace route to destination\n" "Trace route to destination address or hostname\n") { - execute_command ("traceroute", 1, argv[0], NULL); - return CMD_SUCCESS; + execute_command("traceroute", 1, argv[0], NULL); + return CMD_SUCCESS; } -ALIAS (vtysh_traceroute, - vtysh_traceroute_ip_cmd, - "traceroute ip WORD", - "Trace route to destination\n" - "IP trace\n" - "Trace route to destination address or hostname\n") +ALIAS(vtysh_traceroute, vtysh_traceroute_ip_cmd, "traceroute ip WORD", + "Trace route to destination\n" + "IP trace\n" + "Trace route to destination address or hostname\n") DEFUN (vtysh_ping6, vtysh_ping6_cmd, @@ -2960,8 +2496,8 @@ DEFUN (vtysh_ping6, "IPv6 echo\n" "Ping destination address or hostname\n") { - execute_command ("ping6", 1, argv[0], NULL); - return CMD_SUCCESS; + execute_command("ping6", 1, argv[0], NULL); + return CMD_SUCCESS; } DEFUN (vtysh_traceroute6, @@ -2971,8 +2507,8 @@ DEFUN (vtysh_traceroute6, "IPv6 trace\n" "Trace route to destination address or hostname\n") { - execute_command ("traceroute6", 1, argv[0], NULL); - return CMD_SUCCESS; + execute_command("traceroute6", 1, argv[0], NULL); + return CMD_SUCCESS; } #if defined(HAVE_SHELL_ACCESS) @@ -2982,8 +2518,8 @@ DEFUN (vtysh_telnet, "Open a telnet connection\n" "IP address or hostname of a remote system\n") { - execute_command ("telnet", 1, argv[0], NULL); - return CMD_SUCCESS; + execute_command("telnet", 1, argv[0], NULL); + return CMD_SUCCESS; } DEFUN (vtysh_telnet_port, @@ -2993,8 +2529,8 @@ DEFUN (vtysh_telnet_port, "IP address or hostname of a remote system\n" "TCP Port number\n") { - execute_command ("telnet", 2, argv[0], argv[1]); - return CMD_SUCCESS; + execute_command("telnet", 2, argv[0], argv[1]); + return CMD_SUCCESS; } DEFUN (vtysh_ssh, @@ -3003,8 +2539,8 @@ DEFUN (vtysh_ssh, "Open an ssh connection\n" "[user@]host\n") { - execute_command ("ssh", 1, argv[0], NULL); - return CMD_SUCCESS; + execute_command("ssh", 1, argv[0], NULL); + return CMD_SUCCESS; } DEFUN (vtysh_start_shell, @@ -3012,8 +2548,8 @@ DEFUN (vtysh_start_shell, "start-shell", "Start UNIX shell\n") { - execute_command ("sh", 0, NULL, NULL); - return CMD_SUCCESS; + execute_command("sh", 0, NULL, NULL); + return CMD_SUCCESS; } DEFUN (vtysh_start_bash, @@ -3022,8 +2558,8 @@ DEFUN (vtysh_start_bash, "Start UNIX shell\n" "Start bash\n") { - execute_command ("bash", 0, NULL, NULL); - return CMD_SUCCESS; + execute_command("bash", 0, NULL, NULL); + return CMD_SUCCESS; } DEFUN (vtysh_start_zsh, @@ -3032,8 +2568,8 @@ DEFUN (vtysh_start_zsh, "Start UNIX shell\n" "Start Z shell\n") { - execute_command ("zsh", 0, NULL, NULL); - return CMD_SUCCESS; + execute_command("zsh", 0, NULL, NULL); + return CMD_SUCCESS; } #endif @@ -3043,642 +2579,619 @@ DEFUN (config_list, "Print command list\n" "Print all possible command permutations\n") { - return cmd_list_cmds (vty, argc == 2); + return cmd_list_cmds(vty, argc == 2); } -static void -vtysh_install_default (enum node_type node) +static void vtysh_install_default(enum node_type node) { - install_element (node, &config_list_cmd); + install_element(node, &config_list_cmd); } /* Making connection to protocol daemon. */ -static int -vtysh_connect (struct vtysh_client *vclient) -{ - int ret; - int sock, len; - struct sockaddr_un addr; - struct stat s_stat; - const char *path; - - if (!vclient->path[0]) - snprintf(vclient->path, sizeof(vclient->path), "%s/%s.vty", - vty_sock_path, vclient->name); - path = vclient->path; - - /* Stat socket to see if we have permission to access it. */ - ret = stat (path, &s_stat); - if (ret < 0 && errno != ENOENT) - { - fprintf (stderr, "vtysh_connect(%s): stat = %s\n", - path, safe_strerror(errno)); - exit (1); - } - - if (ret >= 0) - { - if (! S_ISSOCK(s_stat.st_mode)) - { - fprintf (stderr, "vtysh_connect(%s): Not a socket\n", - path); - exit (1); +static int vtysh_connect(struct vtysh_client *vclient) +{ + int ret; + int sock, len; + struct sockaddr_un addr; + struct stat s_stat; + const char *path; + + if (!vclient->path[0]) + snprintf(vclient->path, sizeof(vclient->path), "%s/%s.vty", + vty_sock_path, vclient->name); + path = vclient->path; + + /* Stat socket to see if we have permission to access it. */ + ret = stat(path, &s_stat); + if (ret < 0 && errno != ENOENT) { + fprintf(stderr, "vtysh_connect(%s): stat = %s\n", path, + safe_strerror(errno)); + exit(1); + } + + if (ret >= 0) { + if (!S_ISSOCK(s_stat.st_mode)) { + fprintf(stderr, "vtysh_connect(%s): Not a socket\n", + path); + exit(1); + } } - - } - sock = socket (AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) - { + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { #ifdef DEBUG - fprintf(stderr, "vtysh_connect(%s): socket = %s\n", path, - safe_strerror(errno)); + fprintf(stderr, "vtysh_connect(%s): socket = %s\n", path, + safe_strerror(errno)); #endif /* DEBUG */ - return -1; - } + return -1; + } - memset (&addr, 0, sizeof (struct sockaddr_un)); - addr.sun_family = AF_UNIX; - strlcpy (addr.sun_path, path, sizeof (addr.sun_path)); + memset(&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_UNIX; + strlcpy(addr.sun_path, path, sizeof(addr.sun_path)); #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN - len = addr.sun_len = SUN_LEN(&addr); + len = addr.sun_len = SUN_LEN(&addr); #else - len = sizeof (addr.sun_family) + strlen (addr.sun_path); + len = sizeof(addr.sun_family) + strlen(addr.sun_path); #endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */ - ret = connect (sock, (struct sockaddr *) &addr, len); - if (ret < 0) - { + ret = connect(sock, (struct sockaddr *)&addr, len); + if (ret < 0) { #ifdef DEBUG - fprintf(stderr, "vtysh_connect(%s): connect = %s\n", path, - safe_strerror(errno)); + fprintf(stderr, "vtysh_connect(%s): connect = %s\n", path, + safe_strerror(errno)); #endif /* DEBUG */ - close (sock); - return -1; - } - vclient->fd = sock; + close(sock); + return -1; + } + vclient->fd = sock; - return 0; + return 0; } /* Return true if str ends with suffix, else return false */ -static int -ends_with(const char *str, const char *suffix) +static int ends_with(const char *str, const char *suffix) { - if (!str || !suffix) - return 0; - size_t lenstr = strlen(str); - size_t lensuffix = strlen(suffix); - if (lensuffix > lenstr) - return 0; - return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0; + if (!str || !suffix) + return 0; + size_t lenstr = strlen(str); + size_t lensuffix = strlen(suffix); + if (lensuffix > lenstr) + return 0; + return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0; } -static void -vtysh_client_sorted_insert (struct vtysh_client *head_client, - struct vtysh_client *client) +static void vtysh_client_sorted_insert(struct vtysh_client *head_client, + struct vtysh_client *client) { - struct vtysh_client *prev_node, *current_node; + struct vtysh_client *prev_node, *current_node; - prev_node = head_client; - current_node = head_client->next; - while (current_node) - { - if (strcmp(current_node->path, client->path) > 0) - break; + prev_node = head_client; + current_node = head_client->next; + while (current_node) { + if (strcmp(current_node->path, client->path) > 0) + break; - prev_node = current_node; - current_node = current_node->next; - } - client->next = current_node; - prev_node->next = client; + prev_node = current_node; + current_node = current_node->next; + } + client->next = current_node; + prev_node->next = client; } #define MAXIMUM_INSTANCES 10 -static void -vtysh_update_all_insances(struct vtysh_client * head_client) -{ - struct vtysh_client *client; - DIR *dir; - struct dirent *file; - int n = 0; - - if (head_client->flag != VTYSH_OSPFD) return; - - /* ls vty_sock_dir and look for all files ending in .vty */ - dir = opendir(vty_sock_path); - if (dir) - { - while ((file = readdir(dir)) != NULL) - { - if (begins_with(file->d_name, "ospfd-") && ends_with(file->d_name, ".vty")) - { - if (n == MAXIMUM_INSTANCES) - { - fprintf(stderr, - "Parsing %s, client limit(%d) reached!\n", - vty_sock_path, n); - break; - } - client = (struct vtysh_client *) malloc(sizeof(struct vtysh_client)); - client->fd = -1; - client->name = "ospfd"; - client->flag = VTYSH_OSPFD; - snprintf(client->path, sizeof(client->path), "%s/%s", - vty_sock_path, file->d_name); - client->next = NULL; - vtysh_client_sorted_insert(head_client, client); - n++; - } - } - closedir(dir); - } -} - -static int -vtysh_connect_all_instances (struct vtysh_client *head_client) -{ - struct vtysh_client *client; - int rc = 0; - - vtysh_update_all_insances(head_client); - - client = head_client->next; - while (client) - { - if (vtysh_connect(client) == 0) - rc++; - client = client->next; - } - - return rc; -} - -int -vtysh_connect_all(const char *daemon_name) -{ - u_int i; - int rc = 0; - int matches = 0; - - for (i = 0; i < array_size(vtysh_client); i++) - { - if (!daemon_name || !strcmp(daemon_name, vtysh_client[i].name)) - { - matches++; - if (vtysh_connect(&vtysh_client[i]) == 0) - rc++; - - rc += vtysh_connect_all_instances(&vtysh_client[i]); - } - } - if (!matches) - fprintf(stderr, "Error: no daemons match name %s!\n", daemon_name); - return rc; +static void vtysh_update_all_insances(struct vtysh_client *head_client) +{ + struct vtysh_client *client; + DIR *dir; + struct dirent *file; + int n = 0; + + if (head_client->flag != VTYSH_OSPFD) + return; + + /* ls vty_sock_dir and look for all files ending in .vty */ + dir = opendir(vty_sock_path); + if (dir) { + while ((file = readdir(dir)) != NULL) { + if (begins_with(file->d_name, "ospfd-") + && ends_with(file->d_name, ".vty")) { + if (n == MAXIMUM_INSTANCES) { + fprintf(stderr, + "Parsing %s, client limit(%d) reached!\n", + vty_sock_path, n); + break; + } + client = (struct vtysh_client *)malloc( + sizeof(struct vtysh_client)); + client->fd = -1; + client->name = "ospfd"; + client->flag = VTYSH_OSPFD; + snprintf(client->path, sizeof(client->path), + "%s/%s", vty_sock_path, file->d_name); + client->next = NULL; + vtysh_client_sorted_insert(head_client, client); + n++; + } + } + closedir(dir); + } +} + +static int vtysh_connect_all_instances(struct vtysh_client *head_client) +{ + struct vtysh_client *client; + int rc = 0; + + vtysh_update_all_insances(head_client); + + client = head_client->next; + while (client) { + if (vtysh_connect(client) == 0) + rc++; + client = client->next; + } + + return rc; +} + +int vtysh_connect_all(const char *daemon_name) +{ + u_int i; + int rc = 0; + int matches = 0; + + for (i = 0; i < array_size(vtysh_client); i++) { + if (!daemon_name + || !strcmp(daemon_name, vtysh_client[i].name)) { + matches++; + if (vtysh_connect(&vtysh_client[i]) == 0) + rc++; + + rc += vtysh_connect_all_instances(&vtysh_client[i]); + } + } + if (!matches) + fprintf(stderr, "Error: no daemons match name %s!\n", + daemon_name); + return rc; } /* To disable readline's filename completion. */ -static char * -vtysh_completion_entry_function (const char *ignore, int invoking_key) +static char *vtysh_completion_entry_function(const char *ignore, + int invoking_key) { - return NULL; + return NULL; } -void -vtysh_readline_init (void) +void vtysh_readline_init(void) { - /* readline related settings. */ - rl_initialize (); - rl_bind_key ('?', (rl_command_func_t *) vtysh_rl_describe); - rl_completion_entry_function = vtysh_completion_entry_function; - rl_attempted_completion_function = (rl_completion_func_t *)new_completion; + /* readline related settings. */ + rl_initialize(); + rl_bind_key('?', (rl_command_func_t *)vtysh_rl_describe); + rl_completion_entry_function = vtysh_completion_entry_function; + rl_attempted_completion_function = + (rl_completion_func_t *)new_completion; } -char * -vtysh_prompt (void) +char *vtysh_prompt(void) { - static struct utsname names; - static char buf[100]; - const char*hostname; - extern struct host host; + static struct utsname names; + static char buf[100]; + const char *hostname; + extern struct host host; - hostname = host.name; + hostname = host.name; - if (!hostname) - { - if (!names.nodename[0]) - uname (&names); - hostname = names.nodename; - } + if (!hostname) { + if (!names.nodename[0]) + uname(&names); + hostname = names.nodename; + } - snprintf (buf, sizeof buf, cmd_prompt (vty->node), hostname); + snprintf(buf, sizeof buf, cmd_prompt(vty->node), hostname); - return buf; + return buf; } static void vtysh_ac_line(void *arg, const char *line) { - vector comps = arg; - size_t i; - for (i = 0; i < vector_active(comps); i++) - if (!strcmp(line, (char *)vector_slot(comps, i))) - return; - vector_set(comps, XSTRDUP(MTYPE_COMPLETION, line)); + vector comps = arg; + size_t i; + for (i = 0; i < vector_active(comps); i++) + if (!strcmp(line, (char *)vector_slot(comps, i))) + return; + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, line)); } static void vtysh_autocomplete(vector comps, struct cmd_token *token) { - char accmd[256]; - size_t i; + char accmd[256]; + size_t i; - snprintf(accmd, sizeof(accmd), "autocomplete %d %s %s", token->type, - token->text, token->varname ? token->varname : "-"); + snprintf(accmd, sizeof(accmd), "autocomplete %d %s %s", token->type, + token->text, token->varname ? token->varname : "-"); - for (i = 0; i < array_size(vtysh_client); i++) - vtysh_client_run_all (&vtysh_client[i], accmd, 1, NULL, - vtysh_ac_line, comps); + for (i = 0; i < array_size(vtysh_client); i++) + vtysh_client_run_all(&vtysh_client[i], accmd, 1, NULL, + vtysh_ac_line, comps); } static const struct cmd_variable_handler vtysh_var_handler[] = { - { - /* match all */ - .tokenname = NULL, - .varname = NULL, - .completions = vtysh_autocomplete - }, { - .completions = NULL - } -}; - -void -vtysh_init_vty (void) -{ - /* Make vty structure. */ - vty = vty_new (); - vty->type = VTY_SHELL; - vty->node = VIEW_NODE; - - /* Initialize commands. */ - cmd_init (0); - cmd_variable_handler_register(vtysh_var_handler); - - /* Install nodes. */ - install_node (&bgp_node, NULL); - install_node (&rip_node, NULL); - install_node (&interface_node, NULL); - install_node (&link_params_node, NULL); - install_node (&ns_node, NULL); - install_node (&vrf_node, NULL); - install_node (&rmap_node, NULL); - install_node (&zebra_node, NULL); - install_node (&bgp_vpnv4_node, NULL); - install_node (&bgp_vpnv6_node, NULL); - install_node (&bgp_ipv4_node, NULL); - install_node (&bgp_ipv4m_node, NULL); - install_node (&bgp_ipv4l_node, NULL); - install_node (&bgp_ipv6_node, NULL); - install_node (&bgp_ipv6m_node, NULL); - install_node (&bgp_ipv6l_node, NULL); - install_node (&bgp_vrf_policy_node, NULL); - install_node (&bgp_evpn_node, NULL); - install_node (&bgp_evpn_vni_node, NULL); - install_node (&bgp_vnc_defaults_node, NULL); - install_node (&bgp_vnc_nve_group_node, NULL); - install_node (&bgp_vnc_l2_group_node, NULL); - install_node (&ospf_node, NULL); - install_node (&eigrp_node, NULL); - install_node (&babel_node, NULL); - install_node (&ripng_node, NULL); - install_node (&ospf6_node, NULL); - install_node (&ldp_node, NULL); - install_node (&ldp_ipv4_node, NULL); - install_node (&ldp_ipv6_node, NULL); - install_node (&ldp_ipv4_iface_node, NULL); - install_node (&ldp_ipv6_iface_node, NULL); - install_node (&ldp_l2vpn_node, NULL); - install_node (&ldp_pseudowire_node, NULL); - install_node (&keychain_node, NULL); - install_node (&keychain_key_node, NULL); - install_node (&isis_node, NULL); - install_node (&vty_node, NULL); - - vtysh_install_default (VIEW_NODE); - vtysh_install_default (CONFIG_NODE); - vtysh_install_default (BGP_NODE); - vtysh_install_default (RIP_NODE); - vtysh_install_default (INTERFACE_NODE); - vtysh_install_default (LINK_PARAMS_NODE); - vtysh_install_default (NS_NODE); - vtysh_install_default (VRF_NODE); - vtysh_install_default (RMAP_NODE); - vtysh_install_default (ZEBRA_NODE); - vtysh_install_default (BGP_VPNV4_NODE); - vtysh_install_default (BGP_VPNV6_NODE); - vtysh_install_default (BGP_IPV4_NODE); - vtysh_install_default (BGP_IPV4M_NODE); - vtysh_install_default (BGP_IPV4L_NODE); - vtysh_install_default (BGP_IPV6_NODE); - vtysh_install_default (BGP_IPV6M_NODE); - vtysh_install_default (BGP_EVPN_NODE); - vtysh_install_default (BGP_EVPN_VNI_NODE); - vtysh_install_default (BGP_IPV6L_NODE); + {/* match all */ + .tokenname = NULL, + .varname = NULL, + .completions = vtysh_autocomplete}, + {.completions = NULL}}; + +void vtysh_init_vty(void) +{ + /* Make vty structure. */ + vty = vty_new(); + vty->type = VTY_SHELL; + vty->node = VIEW_NODE; + + /* Initialize commands. */ + cmd_init(0); + cmd_variable_handler_register(vtysh_var_handler); + + /* Install nodes. */ + install_node(&bgp_node, NULL); + install_node(&rip_node, NULL); + install_node(&interface_node, NULL); + install_node(&link_params_node, NULL); + install_node(&ns_node, NULL); + install_node(&vrf_node, NULL); + install_node(&rmap_node, NULL); + install_node(&zebra_node, NULL); + install_node(&bgp_vpnv4_node, NULL); + install_node(&bgp_vpnv6_node, NULL); + install_node(&bgp_ipv4_node, NULL); + install_node(&bgp_ipv4m_node, NULL); + install_node(&bgp_ipv4l_node, NULL); + install_node(&bgp_ipv6_node, NULL); + install_node(&bgp_ipv6m_node, NULL); + install_node(&bgp_ipv6l_node, NULL); + install_node(&bgp_vrf_policy_node, NULL); + install_node(&bgp_evpn_node, NULL); + install_node(&bgp_evpn_vni_node, NULL); + install_node(&bgp_vnc_defaults_node, NULL); + install_node(&bgp_vnc_nve_group_node, NULL); + install_node(&bgp_vnc_l2_group_node, NULL); + install_node(&ospf_node, NULL); + install_node(&eigrp_node, NULL); + install_node(&babel_node, NULL); + install_node(&ripng_node, NULL); + install_node(&ospf6_node, NULL); + install_node(&ldp_node, NULL); + install_node(&ldp_ipv4_node, NULL); + install_node(&ldp_ipv6_node, NULL); + install_node(&ldp_ipv4_iface_node, NULL); + install_node(&ldp_ipv6_iface_node, NULL); + install_node(&ldp_l2vpn_node, NULL); + install_node(&ldp_pseudowire_node, NULL); + install_node(&keychain_node, NULL); + install_node(&keychain_key_node, NULL); + install_node(&isis_node, NULL); + install_node(&vty_node, NULL); + + vtysh_install_default(VIEW_NODE); + vtysh_install_default(CONFIG_NODE); + vtysh_install_default(BGP_NODE); + vtysh_install_default(RIP_NODE); + vtysh_install_default(INTERFACE_NODE); + vtysh_install_default(LINK_PARAMS_NODE); + vtysh_install_default(NS_NODE); + vtysh_install_default(VRF_NODE); + vtysh_install_default(RMAP_NODE); + vtysh_install_default(ZEBRA_NODE); + vtysh_install_default(BGP_VPNV4_NODE); + vtysh_install_default(BGP_VPNV6_NODE); + vtysh_install_default(BGP_IPV4_NODE); + vtysh_install_default(BGP_IPV4M_NODE); + vtysh_install_default(BGP_IPV4L_NODE); + vtysh_install_default(BGP_IPV6_NODE); + vtysh_install_default(BGP_IPV6M_NODE); + vtysh_install_default(BGP_EVPN_NODE); + vtysh_install_default(BGP_EVPN_VNI_NODE); + vtysh_install_default(BGP_IPV6L_NODE); #if ENABLE_BGP_VNC - vtysh_install_default (BGP_VRF_POLICY_NODE); - vtysh_install_default (BGP_VNC_DEFAULTS_NODE); - vtysh_install_default (BGP_VNC_NVE_GROUP_NODE); - vtysh_install_default (BGP_VNC_L2_GROUP_NODE); + vtysh_install_default(BGP_VRF_POLICY_NODE); + vtysh_install_default(BGP_VNC_DEFAULTS_NODE); + vtysh_install_default(BGP_VNC_NVE_GROUP_NODE); + vtysh_install_default(BGP_VNC_L2_GROUP_NODE); #endif - vtysh_install_default (OSPF_NODE); - vtysh_install_default (EIGRP_NODE); - vtysh_install_default (BABEL_NODE); - vtysh_install_default (RIPNG_NODE); - vtysh_install_default (OSPF6_NODE); - vtysh_install_default (LDP_NODE); - vtysh_install_default (LDP_IPV4_NODE); - vtysh_install_default (LDP_IPV6_NODE); - vtysh_install_default (LDP_IPV4_IFACE_NODE); - vtysh_install_default (LDP_IPV6_IFACE_NODE); - vtysh_install_default (LDP_L2VPN_NODE); - vtysh_install_default (LDP_PSEUDOWIRE_NODE); - vtysh_install_default (ISIS_NODE); - vtysh_install_default (KEYCHAIN_NODE); - vtysh_install_default (KEYCHAIN_KEY_NODE); - vtysh_install_default (VTY_NODE); - - install_element (VIEW_NODE, &vtysh_enable_cmd); - install_element (ENABLE_NODE, &vtysh_config_terminal_cmd); - install_element (ENABLE_NODE, &vtysh_disable_cmd); - - /* "exit" command. */ - install_element (VIEW_NODE, &vtysh_exit_all_cmd); - install_element (CONFIG_NODE, &vtysh_exit_all_cmd); - install_element (VIEW_NODE, &vtysh_quit_all_cmd); - install_element (CONFIG_NODE, &vtysh_quit_all_cmd); - install_element (RIP_NODE, &vtysh_exit_ripd_cmd); - install_element (RIP_NODE, &vtysh_quit_ripd_cmd); - install_element (RIPNG_NODE, &vtysh_exit_ripngd_cmd); - install_element (RIPNG_NODE, &vtysh_quit_ripngd_cmd); - install_element (OSPF_NODE, &vtysh_exit_ospfd_cmd); - install_element (OSPF_NODE, &vtysh_quit_ospfd_cmd); - install_element (EIGRP_NODE, &vtysh_exit_eigrpd_cmd); - install_element (EIGRP_NODE, &vtysh_quit_eigrpd_cmd); - install_element (BABEL_NODE, &vtysh_exit_babeld_cmd); - install_element (BABEL_NODE, &vtysh_quit_babeld_cmd); - install_element (OSPF6_NODE, &vtysh_exit_ospf6d_cmd); - install_element (OSPF6_NODE, &vtysh_quit_ospf6d_cmd); -#if defined (HAVE_LDPD) - install_element (LDP_NODE, &vtysh_exit_ldpd_cmd); - install_element (LDP_NODE, &vtysh_quit_ldpd_cmd); - install_element (LDP_IPV4_NODE, &vtysh_exit_ldpd_cmd); - install_element (LDP_IPV4_NODE, &vtysh_quit_ldpd_cmd); - install_element (LDP_IPV6_NODE, &vtysh_exit_ldpd_cmd); - install_element (LDP_IPV6_NODE, &vtysh_quit_ldpd_cmd); - install_element (LDP_IPV4_IFACE_NODE, &vtysh_exit_ldpd_cmd); - install_element (LDP_IPV4_IFACE_NODE, &vtysh_quit_ldpd_cmd); - install_element (LDP_IPV6_IFACE_NODE, &vtysh_exit_ldpd_cmd); - install_element (LDP_IPV6_IFACE_NODE, &vtysh_quit_ldpd_cmd); - install_element (LDP_L2VPN_NODE, &vtysh_exit_ldpd_cmd); - install_element (LDP_L2VPN_NODE, &vtysh_quit_ldpd_cmd); - install_element (LDP_PSEUDOWIRE_NODE, &vtysh_exit_ldpd_cmd); - install_element (LDP_PSEUDOWIRE_NODE, &vtysh_quit_ldpd_cmd); + vtysh_install_default(OSPF_NODE); + vtysh_install_default(EIGRP_NODE); + vtysh_install_default(BABEL_NODE); + vtysh_install_default(RIPNG_NODE); + vtysh_install_default(OSPF6_NODE); + vtysh_install_default(LDP_NODE); + vtysh_install_default(LDP_IPV4_NODE); + vtysh_install_default(LDP_IPV6_NODE); + vtysh_install_default(LDP_IPV4_IFACE_NODE); + vtysh_install_default(LDP_IPV6_IFACE_NODE); + vtysh_install_default(LDP_L2VPN_NODE); + vtysh_install_default(LDP_PSEUDOWIRE_NODE); + vtysh_install_default(ISIS_NODE); + vtysh_install_default(KEYCHAIN_NODE); + vtysh_install_default(KEYCHAIN_KEY_NODE); + vtysh_install_default(VTY_NODE); + + install_element(VIEW_NODE, &vtysh_enable_cmd); + install_element(ENABLE_NODE, &vtysh_config_terminal_cmd); + install_element(ENABLE_NODE, &vtysh_disable_cmd); + + /* "exit" command. */ + install_element(VIEW_NODE, &vtysh_exit_all_cmd); + install_element(CONFIG_NODE, &vtysh_exit_all_cmd); + install_element(VIEW_NODE, &vtysh_quit_all_cmd); + install_element(CONFIG_NODE, &vtysh_quit_all_cmd); + install_element(RIP_NODE, &vtysh_exit_ripd_cmd); + install_element(RIP_NODE, &vtysh_quit_ripd_cmd); + install_element(RIPNG_NODE, &vtysh_exit_ripngd_cmd); + install_element(RIPNG_NODE, &vtysh_quit_ripngd_cmd); + install_element(OSPF_NODE, &vtysh_exit_ospfd_cmd); + install_element(OSPF_NODE, &vtysh_quit_ospfd_cmd); + install_element(EIGRP_NODE, &vtysh_exit_eigrpd_cmd); + install_element(EIGRP_NODE, &vtysh_quit_eigrpd_cmd); + install_element(BABEL_NODE, &vtysh_exit_babeld_cmd); + install_element(BABEL_NODE, &vtysh_quit_babeld_cmd); + install_element(OSPF6_NODE, &vtysh_exit_ospf6d_cmd); + install_element(OSPF6_NODE, &vtysh_quit_ospf6d_cmd); +#if defined(HAVE_LDPD) + install_element(LDP_NODE, &vtysh_exit_ldpd_cmd); + install_element(LDP_NODE, &vtysh_quit_ldpd_cmd); + install_element(LDP_IPV4_NODE, &vtysh_exit_ldpd_cmd); + install_element(LDP_IPV4_NODE, &vtysh_quit_ldpd_cmd); + install_element(LDP_IPV6_NODE, &vtysh_exit_ldpd_cmd); + install_element(LDP_IPV6_NODE, &vtysh_quit_ldpd_cmd); + install_element(LDP_IPV4_IFACE_NODE, &vtysh_exit_ldpd_cmd); + install_element(LDP_IPV4_IFACE_NODE, &vtysh_quit_ldpd_cmd); + install_element(LDP_IPV6_IFACE_NODE, &vtysh_exit_ldpd_cmd); + install_element(LDP_IPV6_IFACE_NODE, &vtysh_quit_ldpd_cmd); + install_element(LDP_L2VPN_NODE, &vtysh_exit_ldpd_cmd); + install_element(LDP_L2VPN_NODE, &vtysh_quit_ldpd_cmd); + install_element(LDP_PSEUDOWIRE_NODE, &vtysh_exit_ldpd_cmd); + install_element(LDP_PSEUDOWIRE_NODE, &vtysh_quit_ldpd_cmd); #endif - install_element (BGP_NODE, &vtysh_exit_bgpd_cmd); - install_element (BGP_NODE, &vtysh_quit_bgpd_cmd); - install_element (BGP_VPNV4_NODE, &vtysh_exit_bgpd_cmd); - install_element (BGP_VPNV4_NODE, &vtysh_quit_bgpd_cmd); - install_element (BGP_VPNV6_NODE, &vtysh_exit_bgpd_cmd); - install_element (BGP_VPNV6_NODE, &vtysh_quit_bgpd_cmd); - install_element (BGP_IPV4_NODE, &vtysh_exit_bgpd_cmd); - install_element (BGP_IPV4_NODE, &vtysh_quit_bgpd_cmd); - install_element (BGP_IPV4M_NODE, &vtysh_exit_bgpd_cmd); - install_element (BGP_IPV4M_NODE, &vtysh_quit_bgpd_cmd); - install_element (BGP_IPV4L_NODE, &vtysh_exit_bgpd_cmd); - install_element (BGP_IPV4L_NODE, &vtysh_quit_bgpd_cmd); - install_element (BGP_IPV6_NODE, &vtysh_exit_bgpd_cmd); - install_element (BGP_IPV6_NODE, &vtysh_quit_bgpd_cmd); - install_element (BGP_IPV6M_NODE, &vtysh_exit_bgpd_cmd); - install_element (BGP_IPV6M_NODE, &vtysh_quit_bgpd_cmd); - install_element (BGP_EVPN_NODE, &vtysh_quit_bgpd_cmd); - install_element (BGP_EVPN_NODE, &vtysh_exit_bgpd_cmd); - install_element (BGP_EVPN_VNI_NODE, &vtysh_exit_bgpd_cmd); - install_element (BGP_EVPN_VNI_NODE, &vtysh_quit_bgpd_cmd); - install_element (BGP_IPV6L_NODE, &vtysh_exit_bgpd_cmd); - install_element (BGP_IPV6L_NODE, &vtysh_quit_bgpd_cmd); -#if defined (ENABLE_BGP_VNC) - install_element (BGP_VRF_POLICY_NODE, &vtysh_exit_bgpd_cmd); - install_element (BGP_VRF_POLICY_NODE, &vtysh_quit_bgpd_cmd); - install_element (BGP_VNC_DEFAULTS_NODE, &vtysh_exit_bgpd_cmd); - install_element (BGP_VNC_DEFAULTS_NODE, &vtysh_quit_bgpd_cmd); - install_element (BGP_VNC_NVE_GROUP_NODE, &vtysh_exit_bgpd_cmd); - install_element (BGP_VNC_NVE_GROUP_NODE, &vtysh_quit_bgpd_cmd); - install_element (BGP_VNC_L2_GROUP_NODE, &vtysh_exit_bgpd_cmd); - install_element (BGP_VNC_L2_GROUP_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_VPNV4_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_VPNV4_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_VPNV6_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_VPNV6_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_IPV4_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_IPV4_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_IPV4M_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_IPV4M_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_IPV4L_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_IPV4L_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_IPV6_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_IPV6_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_IPV6M_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_IPV6M_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_EVPN_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_EVPN_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_EVPN_VNI_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_EVPN_VNI_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_IPV6L_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_IPV6L_NODE, &vtysh_quit_bgpd_cmd); +#if defined(ENABLE_BGP_VNC) + install_element(BGP_VRF_POLICY_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_VRF_POLICY_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_VNC_DEFAULTS_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_VNC_DEFAULTS_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, &vtysh_quit_bgpd_cmd); + install_element(BGP_VNC_L2_GROUP_NODE, &vtysh_exit_bgpd_cmd); + install_element(BGP_VNC_L2_GROUP_NODE, &vtysh_quit_bgpd_cmd); #endif - install_element (ISIS_NODE, &vtysh_exit_isisd_cmd); - install_element (ISIS_NODE, &vtysh_quit_isisd_cmd); - install_element (KEYCHAIN_NODE, &vtysh_exit_ripd_cmd); - install_element (KEYCHAIN_NODE, &vtysh_quit_ripd_cmd); - install_element (KEYCHAIN_KEY_NODE, &vtysh_exit_ripd_cmd); - install_element (KEYCHAIN_KEY_NODE, &vtysh_quit_ripd_cmd); - install_element (RMAP_NODE, &vtysh_exit_rmap_cmd); - install_element (RMAP_NODE, &vtysh_quit_rmap_cmd); - install_element (VTY_NODE, &vtysh_exit_line_vty_cmd); - install_element (VTY_NODE, &vtysh_quit_line_vty_cmd); - - /* "end" command. */ - install_element (CONFIG_NODE, &vtysh_end_all_cmd); - install_element (ENABLE_NODE, &vtysh_end_all_cmd); - install_element (RIP_NODE, &vtysh_end_all_cmd); - install_element (RIPNG_NODE, &vtysh_end_all_cmd); - install_element (OSPF_NODE, &vtysh_end_all_cmd); - install_element (EIGRP_NODE, &vtysh_end_all_cmd); - install_element (BABEL_NODE, &vtysh_end_all_cmd); - install_element (OSPF6_NODE, &vtysh_end_all_cmd); - install_element (LDP_NODE, &vtysh_end_all_cmd); - install_element (LDP_IPV4_NODE, &vtysh_end_all_cmd); - install_element (LDP_IPV6_NODE, &vtysh_end_all_cmd); - install_element (LDP_IPV4_IFACE_NODE, &vtysh_end_all_cmd); - install_element (LDP_IPV6_IFACE_NODE, &vtysh_end_all_cmd); - install_element (LDP_L2VPN_NODE, &vtysh_end_all_cmd); - install_element (LDP_PSEUDOWIRE_NODE, &vtysh_end_all_cmd); - install_element (BGP_NODE, &vtysh_end_all_cmd); - install_element (BGP_IPV4_NODE, &vtysh_end_all_cmd); - install_element (BGP_IPV4M_NODE, &vtysh_end_all_cmd); - install_element (BGP_IPV4L_NODE, &vtysh_end_all_cmd); - install_element (BGP_VPNV4_NODE, &vtysh_end_all_cmd); - install_element (BGP_VPNV6_NODE, &vtysh_end_all_cmd); - install_element (BGP_IPV6_NODE, &vtysh_end_all_cmd); - install_element (BGP_IPV6M_NODE, &vtysh_end_all_cmd); - install_element (BGP_IPV6L_NODE, &vtysh_end_all_cmd); - install_element (BGP_VRF_POLICY_NODE, &vtysh_end_all_cmd); - install_element (BGP_EVPN_NODE, &vtysh_end_all_cmd); - install_element (BGP_EVPN_VNI_NODE, &vtysh_end_all_cmd); - install_element (BGP_VNC_DEFAULTS_NODE, &vtysh_end_all_cmd); - install_element (BGP_VNC_NVE_GROUP_NODE, &vtysh_end_all_cmd); - install_element (BGP_VNC_L2_GROUP_NODE, &vtysh_end_all_cmd); - install_element (ISIS_NODE, &vtysh_end_all_cmd); - install_element (KEYCHAIN_NODE, &vtysh_end_all_cmd); - install_element (KEYCHAIN_KEY_NODE, &vtysh_end_all_cmd); - install_element (RMAP_NODE, &vtysh_end_all_cmd); - install_element (VTY_NODE, &vtysh_end_all_cmd); - - install_element (INTERFACE_NODE, &vtysh_interface_desc_cmd); - install_element (INTERFACE_NODE, &vtysh_no_interface_desc_cmd); - install_element (INTERFACE_NODE, &vtysh_end_all_cmd); - install_element (INTERFACE_NODE, &vtysh_exit_interface_cmd); - install_element (LINK_PARAMS_NODE, &exit_link_params_cmd); - install_element (LINK_PARAMS_NODE, &vtysh_end_all_cmd); - install_element (LINK_PARAMS_NODE, &vtysh_exit_interface_cmd); - install_element (INTERFACE_NODE, &vtysh_quit_interface_cmd); - - install_element (NS_NODE, &vtysh_end_all_cmd); - - install_element (CONFIG_NODE, &vtysh_ns_cmd); - install_element (NS_NODE, &vtysh_exit_ns_cmd); - install_element (NS_NODE, &vtysh_quit_ns_cmd); - - install_element (VRF_NODE, &vtysh_end_all_cmd); - install_element (VRF_NODE, &vtysh_exit_vrf_cmd); - install_element (VRF_NODE, &vtysh_quit_vrf_cmd); - - install_element (CONFIG_NODE, &router_eigrp_cmd); - install_element (CONFIG_NODE, &router_babel_cmd); - install_element (CONFIG_NODE, &router_rip_cmd); - install_element (CONFIG_NODE, &router_ripng_cmd); - install_element (CONFIG_NODE, &router_ospf_cmd); - install_element (CONFIG_NODE, &router_ospf6_cmd); -#if defined (HAVE_LDPD) - install_element (CONFIG_NODE, &ldp_mpls_ldp_cmd); - install_element (LDP_NODE, &ldp_address_family_ipv4_cmd); - install_element (LDP_NODE, &ldp_address_family_ipv6_cmd); - install_element (LDP_IPV4_NODE, &ldp_interface_ifname_cmd); - install_element (LDP_IPV6_NODE, &ldp_interface_ifname_cmd); - install_element (CONFIG_NODE, &ldp_l2vpn_word_type_vpls_cmd); - install_element (LDP_L2VPN_NODE, &ldp_member_pseudowire_ifname_cmd); + install_element(ISIS_NODE, &vtysh_exit_isisd_cmd); + install_element(ISIS_NODE, &vtysh_quit_isisd_cmd); + install_element(KEYCHAIN_NODE, &vtysh_exit_ripd_cmd); + install_element(KEYCHAIN_NODE, &vtysh_quit_ripd_cmd); + install_element(KEYCHAIN_KEY_NODE, &vtysh_exit_ripd_cmd); + install_element(KEYCHAIN_KEY_NODE, &vtysh_quit_ripd_cmd); + install_element(RMAP_NODE, &vtysh_exit_rmap_cmd); + install_element(RMAP_NODE, &vtysh_quit_rmap_cmd); + install_element(VTY_NODE, &vtysh_exit_line_vty_cmd); + install_element(VTY_NODE, &vtysh_quit_line_vty_cmd); + + /* "end" command. */ + install_element(CONFIG_NODE, &vtysh_end_all_cmd); + install_element(ENABLE_NODE, &vtysh_end_all_cmd); + install_element(RIP_NODE, &vtysh_end_all_cmd); + install_element(RIPNG_NODE, &vtysh_end_all_cmd); + install_element(OSPF_NODE, &vtysh_end_all_cmd); + install_element(EIGRP_NODE, &vtysh_end_all_cmd); + install_element(BABEL_NODE, &vtysh_end_all_cmd); + install_element(OSPF6_NODE, &vtysh_end_all_cmd); + install_element(LDP_NODE, &vtysh_end_all_cmd); + install_element(LDP_IPV4_NODE, &vtysh_end_all_cmd); + install_element(LDP_IPV6_NODE, &vtysh_end_all_cmd); + install_element(LDP_IPV4_IFACE_NODE, &vtysh_end_all_cmd); + install_element(LDP_IPV6_IFACE_NODE, &vtysh_end_all_cmd); + install_element(LDP_L2VPN_NODE, &vtysh_end_all_cmd); + install_element(LDP_PSEUDOWIRE_NODE, &vtysh_end_all_cmd); + install_element(BGP_NODE, &vtysh_end_all_cmd); + install_element(BGP_IPV4_NODE, &vtysh_end_all_cmd); + install_element(BGP_IPV4M_NODE, &vtysh_end_all_cmd); + install_element(BGP_IPV4L_NODE, &vtysh_end_all_cmd); + install_element(BGP_VPNV4_NODE, &vtysh_end_all_cmd); + install_element(BGP_VPNV6_NODE, &vtysh_end_all_cmd); + install_element(BGP_IPV6_NODE, &vtysh_end_all_cmd); + install_element(BGP_IPV6M_NODE, &vtysh_end_all_cmd); + install_element(BGP_IPV6L_NODE, &vtysh_end_all_cmd); + install_element(BGP_VRF_POLICY_NODE, &vtysh_end_all_cmd); + install_element(BGP_EVPN_NODE, &vtysh_end_all_cmd); + install_element(BGP_EVPN_VNI_NODE, &vtysh_end_all_cmd); + install_element(BGP_VNC_DEFAULTS_NODE, &vtysh_end_all_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, &vtysh_end_all_cmd); + install_element(BGP_VNC_L2_GROUP_NODE, &vtysh_end_all_cmd); + install_element(ISIS_NODE, &vtysh_end_all_cmd); + install_element(KEYCHAIN_NODE, &vtysh_end_all_cmd); + install_element(KEYCHAIN_KEY_NODE, &vtysh_end_all_cmd); + install_element(RMAP_NODE, &vtysh_end_all_cmd); + install_element(VTY_NODE, &vtysh_end_all_cmd); + + install_element(INTERFACE_NODE, &vtysh_interface_desc_cmd); + install_element(INTERFACE_NODE, &vtysh_no_interface_desc_cmd); + install_element(INTERFACE_NODE, &vtysh_end_all_cmd); + install_element(INTERFACE_NODE, &vtysh_exit_interface_cmd); + install_element(LINK_PARAMS_NODE, &exit_link_params_cmd); + install_element(LINK_PARAMS_NODE, &vtysh_end_all_cmd); + install_element(LINK_PARAMS_NODE, &vtysh_exit_interface_cmd); + install_element(INTERFACE_NODE, &vtysh_quit_interface_cmd); + + install_element(NS_NODE, &vtysh_end_all_cmd); + + install_element(CONFIG_NODE, &vtysh_ns_cmd); + install_element(NS_NODE, &vtysh_exit_ns_cmd); + install_element(NS_NODE, &vtysh_quit_ns_cmd); + + install_element(VRF_NODE, &vtysh_end_all_cmd); + install_element(VRF_NODE, &vtysh_exit_vrf_cmd); + install_element(VRF_NODE, &vtysh_quit_vrf_cmd); + + install_element(CONFIG_NODE, &router_eigrp_cmd); + install_element(CONFIG_NODE, &router_babel_cmd); + install_element(CONFIG_NODE, &router_rip_cmd); + install_element(CONFIG_NODE, &router_ripng_cmd); + install_element(CONFIG_NODE, &router_ospf_cmd); + install_element(CONFIG_NODE, &router_ospf6_cmd); +#if defined(HAVE_LDPD) + install_element(CONFIG_NODE, &ldp_mpls_ldp_cmd); + install_element(LDP_NODE, &ldp_address_family_ipv4_cmd); + install_element(LDP_NODE, &ldp_address_family_ipv6_cmd); + install_element(LDP_IPV4_NODE, &ldp_interface_ifname_cmd); + install_element(LDP_IPV6_NODE, &ldp_interface_ifname_cmd); + install_element(CONFIG_NODE, &ldp_l2vpn_word_type_vpls_cmd); + install_element(LDP_L2VPN_NODE, &ldp_member_pseudowire_ifname_cmd); #endif - install_element (CONFIG_NODE, &router_isis_cmd); - install_element (CONFIG_NODE, &router_bgp_cmd); - install_element (BGP_NODE, &address_family_vpnv4_cmd); - install_element (BGP_NODE, &address_family_vpnv6_cmd); + install_element(CONFIG_NODE, &router_isis_cmd); + install_element(CONFIG_NODE, &router_bgp_cmd); + install_element(BGP_NODE, &address_family_vpnv4_cmd); + install_element(BGP_NODE, &address_family_vpnv6_cmd); #if defined(ENABLE_BGP_VNC) - install_element (BGP_NODE, &vnc_vrf_policy_cmd); - install_element (BGP_NODE, &vnc_defaults_cmd); - install_element (BGP_NODE, &vnc_nve_group_cmd); - install_element (BGP_NODE, &vnc_l2_group_cmd); + install_element(BGP_NODE, &vnc_vrf_policy_cmd); + install_element(BGP_NODE, &vnc_defaults_cmd); + install_element(BGP_NODE, &vnc_nve_group_cmd); + install_element(BGP_NODE, &vnc_l2_group_cmd); #endif - install_element (BGP_NODE, &address_family_ipv4_cmd); - install_element (BGP_NODE, &address_family_ipv4_multicast_cmd); - install_element (BGP_NODE, &address_family_ipv4_vpn_cmd); - install_element (BGP_NODE, &address_family_ipv4_labeled_unicast_cmd); - install_element (BGP_NODE, &address_family_ipv6_cmd); - install_element (BGP_NODE, &address_family_ipv6_multicast_cmd); - install_element (BGP_NODE, &address_family_ipv6_vpn_cmd); - install_element (BGP_NODE, &address_family_ipv6_labeled_unicast_cmd); - install_element (BGP_NODE, &address_family_evpn_cmd); -#if defined (HAVE_CUMULUS) - install_element (BGP_NODE, &address_family_evpn2_cmd); + install_element(BGP_NODE, &address_family_ipv4_cmd); + install_element(BGP_NODE, &address_family_ipv4_multicast_cmd); + install_element(BGP_NODE, &address_family_ipv4_vpn_cmd); + install_element(BGP_NODE, &address_family_ipv4_labeled_unicast_cmd); + install_element(BGP_NODE, &address_family_ipv6_cmd); + install_element(BGP_NODE, &address_family_ipv6_multicast_cmd); + install_element(BGP_NODE, &address_family_ipv6_vpn_cmd); + install_element(BGP_NODE, &address_family_ipv6_labeled_unicast_cmd); + install_element(BGP_NODE, &address_family_evpn_cmd); +#if defined(HAVE_CUMULUS) + install_element(BGP_NODE, &address_family_evpn2_cmd); #endif - install_element (BGP_VPNV4_NODE, &exit_address_family_cmd); - install_element (BGP_VPNV6_NODE, &exit_address_family_cmd); - install_element (BGP_IPV4_NODE, &exit_address_family_cmd); - install_element (BGP_IPV4M_NODE, &exit_address_family_cmd); - install_element (BGP_IPV4L_NODE, &exit_address_family_cmd); - install_element (BGP_IPV6_NODE, &exit_address_family_cmd); - install_element (BGP_IPV6M_NODE, &exit_address_family_cmd); - install_element (BGP_EVPN_NODE, &exit_address_family_cmd); - install_element (BGP_IPV6L_NODE, &exit_address_family_cmd); - - /* EVPN commands */ - install_element (BGP_EVPN_NODE, &bgp_evpn_vni_cmd); - install_element (BGP_EVPN_VNI_NODE, &exit_vni_cmd); - - install_element (BGP_VRF_POLICY_NODE, &exit_vrf_policy_cmd); - install_element (BGP_VNC_DEFAULTS_NODE, &exit_vnc_config_cmd); - install_element (BGP_VNC_NVE_GROUP_NODE, &exit_vnc_config_cmd); - install_element (BGP_VNC_L2_GROUP_NODE, &exit_vnc_config_cmd); - - install_element (CONFIG_NODE, &key_chain_cmd); - install_element (CONFIG_NODE, &vtysh_route_map_cmd); - install_element (CONFIG_NODE, &vtysh_line_vty_cmd); - install_element (KEYCHAIN_NODE, &key_cmd); - install_element (KEYCHAIN_NODE, &key_chain_cmd); - install_element (KEYCHAIN_KEY_NODE, &key_chain_cmd); - install_element (CONFIG_NODE, &vtysh_interface_cmd); - install_element (CONFIG_NODE, &vtysh_no_interface_cmd); - install_element (CONFIG_NODE, &vtysh_no_interface_vrf_cmd); - install_element (INTERFACE_NODE, &vtysh_link_params_cmd); - install_element (ENABLE_NODE, &vtysh_show_running_config_cmd); - install_element (ENABLE_NODE, &vtysh_copy_running_config_cmd); - - install_element (CONFIG_NODE, &vtysh_vrf_cmd); - install_element (CONFIG_NODE, &vtysh_no_vrf_cmd); - - /* "write terminal" command. */ - install_element (ENABLE_NODE, &vtysh_write_terminal_cmd); - - install_element (CONFIG_NODE, &vtysh_integrated_config_cmd); - install_element (CONFIG_NODE, &no_vtysh_integrated_config_cmd); - - /* "write memory" command. */ - install_element (ENABLE_NODE, &vtysh_write_memory_cmd); - - install_element (VIEW_NODE, &vtysh_terminal_length_cmd); - install_element (VIEW_NODE, &vtysh_terminal_no_length_cmd); - install_element (VIEW_NODE, &vtysh_show_daemons_cmd); - - install_element (VIEW_NODE, &vtysh_ping_cmd); - install_element (VIEW_NODE, &vtysh_ping_ip_cmd); - install_element (VIEW_NODE, &vtysh_traceroute_cmd); - install_element (VIEW_NODE, &vtysh_traceroute_ip_cmd); - install_element (VIEW_NODE, &vtysh_ping6_cmd); - install_element (VIEW_NODE, &vtysh_traceroute6_cmd); + install_element(BGP_VPNV4_NODE, &exit_address_family_cmd); + install_element(BGP_VPNV6_NODE, &exit_address_family_cmd); + install_element(BGP_IPV4_NODE, &exit_address_family_cmd); + install_element(BGP_IPV4M_NODE, &exit_address_family_cmd); + install_element(BGP_IPV4L_NODE, &exit_address_family_cmd); + install_element(BGP_IPV6_NODE, &exit_address_family_cmd); + install_element(BGP_IPV6M_NODE, &exit_address_family_cmd); + install_element(BGP_EVPN_NODE, &exit_address_family_cmd); + install_element(BGP_IPV6L_NODE, &exit_address_family_cmd); + + /* EVPN commands */ + install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd); + install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd); + + install_element(BGP_VRF_POLICY_NODE, &exit_vrf_policy_cmd); + install_element(BGP_VNC_DEFAULTS_NODE, &exit_vnc_config_cmd); + install_element(BGP_VNC_NVE_GROUP_NODE, &exit_vnc_config_cmd); + install_element(BGP_VNC_L2_GROUP_NODE, &exit_vnc_config_cmd); + + install_element(CONFIG_NODE, &key_chain_cmd); + install_element(CONFIG_NODE, &vtysh_route_map_cmd); + install_element(CONFIG_NODE, &vtysh_line_vty_cmd); + install_element(KEYCHAIN_NODE, &key_cmd); + install_element(KEYCHAIN_NODE, &key_chain_cmd); + install_element(KEYCHAIN_KEY_NODE, &key_chain_cmd); + install_element(CONFIG_NODE, &vtysh_interface_cmd); + install_element(CONFIG_NODE, &vtysh_no_interface_cmd); + install_element(CONFIG_NODE, &vtysh_no_interface_vrf_cmd); + install_element(INTERFACE_NODE, &vtysh_link_params_cmd); + install_element(ENABLE_NODE, &vtysh_show_running_config_cmd); + install_element(ENABLE_NODE, &vtysh_copy_running_config_cmd); + + install_element(CONFIG_NODE, &vtysh_vrf_cmd); + install_element(CONFIG_NODE, &vtysh_no_vrf_cmd); + + /* "write terminal" command. */ + install_element(ENABLE_NODE, &vtysh_write_terminal_cmd); + + install_element(CONFIG_NODE, &vtysh_integrated_config_cmd); + install_element(CONFIG_NODE, &no_vtysh_integrated_config_cmd); + + /* "write memory" command. */ + install_element(ENABLE_NODE, &vtysh_write_memory_cmd); + + install_element(VIEW_NODE, &vtysh_terminal_length_cmd); + install_element(VIEW_NODE, &vtysh_terminal_no_length_cmd); + install_element(VIEW_NODE, &vtysh_show_daemons_cmd); + + install_element(VIEW_NODE, &vtysh_ping_cmd); + install_element(VIEW_NODE, &vtysh_ping_ip_cmd); + install_element(VIEW_NODE, &vtysh_traceroute_cmd); + install_element(VIEW_NODE, &vtysh_traceroute_ip_cmd); + install_element(VIEW_NODE, &vtysh_ping6_cmd); + install_element(VIEW_NODE, &vtysh_traceroute6_cmd); #if defined(HAVE_SHELL_ACCESS) - install_element (VIEW_NODE, &vtysh_telnet_cmd); - install_element (VIEW_NODE, &vtysh_telnet_port_cmd); - install_element (VIEW_NODE, &vtysh_ssh_cmd); + install_element(VIEW_NODE, &vtysh_telnet_cmd); + install_element(VIEW_NODE, &vtysh_telnet_port_cmd); + install_element(VIEW_NODE, &vtysh_ssh_cmd); #endif #if defined(HAVE_SHELL_ACCESS) - install_element (ENABLE_NODE, &vtysh_start_shell_cmd); - install_element (ENABLE_NODE, &vtysh_start_bash_cmd); - install_element (ENABLE_NODE, &vtysh_start_zsh_cmd); + install_element(ENABLE_NODE, &vtysh_start_shell_cmd); + install_element(ENABLE_NODE, &vtysh_start_bash_cmd); + install_element(ENABLE_NODE, &vtysh_start_zsh_cmd); #endif - install_element (VIEW_NODE, &vtysh_show_memory_cmd); - install_element (VIEW_NODE, &vtysh_show_modules_cmd); - - install_element (VIEW_NODE, &vtysh_show_work_queues_cmd); - install_element (VIEW_NODE, &vtysh_show_work_queues_daemon_cmd); - - install_element (VIEW_NODE, &vtysh_show_hashtable_cmd); - - install_element (VIEW_NODE, &vtysh_show_thread_cmd); - - /* Logging */ - install_element (VIEW_NODE, &vtysh_show_logging_cmd); - install_element (CONFIG_NODE, &vtysh_log_stdout_cmd); - install_element (CONFIG_NODE, &vtysh_log_stdout_level_cmd); - install_element (CONFIG_NODE, &no_vtysh_log_stdout_cmd); - install_element (CONFIG_NODE, &vtysh_log_file_cmd); - install_element (CONFIG_NODE, &vtysh_log_file_level_cmd); - install_element (CONFIG_NODE, &no_vtysh_log_file_cmd); - install_element (CONFIG_NODE, &vtysh_log_monitor_cmd); - install_element (CONFIG_NODE, &no_vtysh_log_monitor_cmd); - install_element (CONFIG_NODE, &vtysh_log_syslog_cmd); - install_element (CONFIG_NODE, &no_vtysh_log_syslog_cmd); - install_element (CONFIG_NODE, &vtysh_log_trap_cmd); - install_element (CONFIG_NODE, &no_vtysh_log_trap_cmd); - install_element (CONFIG_NODE, &vtysh_log_facility_cmd); - install_element (CONFIG_NODE, &no_vtysh_log_facility_cmd); - install_element (CONFIG_NODE, &vtysh_log_record_priority_cmd); - install_element (CONFIG_NODE, &no_vtysh_log_record_priority_cmd); - install_element (CONFIG_NODE, &vtysh_log_timestamp_precision_cmd); - install_element (CONFIG_NODE, &no_vtysh_log_timestamp_precision_cmd); - - install_element (CONFIG_NODE, &vtysh_service_password_encrypt_cmd); - install_element (CONFIG_NODE, &no_vtysh_service_password_encrypt_cmd); - - install_element (CONFIG_NODE, &vtysh_password_cmd); - install_element (CONFIG_NODE, &vtysh_enable_password_cmd); - install_element (CONFIG_NODE, &no_vtysh_enable_password_cmd); + install_element(VIEW_NODE, &vtysh_show_memory_cmd); + install_element(VIEW_NODE, &vtysh_show_modules_cmd); + + install_element(VIEW_NODE, &vtysh_show_work_queues_cmd); + install_element(VIEW_NODE, &vtysh_show_work_queues_daemon_cmd); + + install_element(VIEW_NODE, &vtysh_show_hashtable_cmd); + + install_element(VIEW_NODE, &vtysh_show_thread_cmd); + + /* Logging */ + install_element(VIEW_NODE, &vtysh_show_logging_cmd); + install_element(CONFIG_NODE, &vtysh_log_stdout_cmd); + install_element(CONFIG_NODE, &vtysh_log_stdout_level_cmd); + install_element(CONFIG_NODE, &no_vtysh_log_stdout_cmd); + install_element(CONFIG_NODE, &vtysh_log_file_cmd); + install_element(CONFIG_NODE, &vtysh_log_file_level_cmd); + install_element(CONFIG_NODE, &no_vtysh_log_file_cmd); + install_element(CONFIG_NODE, &vtysh_log_monitor_cmd); + install_element(CONFIG_NODE, &no_vtysh_log_monitor_cmd); + install_element(CONFIG_NODE, &vtysh_log_syslog_cmd); + install_element(CONFIG_NODE, &no_vtysh_log_syslog_cmd); + install_element(CONFIG_NODE, &vtysh_log_trap_cmd); + install_element(CONFIG_NODE, &no_vtysh_log_trap_cmd); + install_element(CONFIG_NODE, &vtysh_log_facility_cmd); + install_element(CONFIG_NODE, &no_vtysh_log_facility_cmd); + install_element(CONFIG_NODE, &vtysh_log_record_priority_cmd); + install_element(CONFIG_NODE, &no_vtysh_log_record_priority_cmd); + install_element(CONFIG_NODE, &vtysh_log_timestamp_precision_cmd); + install_element(CONFIG_NODE, &no_vtysh_log_timestamp_precision_cmd); + + install_element(CONFIG_NODE, &vtysh_service_password_encrypt_cmd); + install_element(CONFIG_NODE, &no_vtysh_service_password_encrypt_cmd); + + install_element(CONFIG_NODE, &vtysh_password_cmd); + install_element(CONFIG_NODE, &vtysh_enable_password_cmd); + install_element(CONFIG_NODE, &no_vtysh_enable_password_cmd); } diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h index 71a0d876f..67ee8898c 100644 --- a/vtysh/vtysh.h +++ b/vtysh/vtysh.h @@ -63,41 +63,41 @@ extern enum vtysh_write_integrated vtysh_write_integrated; extern char *quagga_config; -void vtysh_init_vty (void); -void vtysh_init_cmd (void); -extern int vtysh_connect_all (const char *optional_daemon_name); -void vtysh_readline_init (void); -void vtysh_user_init (void); +void vtysh_init_vty(void); +void vtysh_init_cmd(void); +extern int vtysh_connect_all(const char *optional_daemon_name); +void vtysh_readline_init(void); +void vtysh_user_init(void); -int vtysh_execute (const char *); -int vtysh_execute_no_pager (const char *); +int vtysh_execute(const char *); +int vtysh_execute_no_pager(const char *); -char *vtysh_prompt (void); +char *vtysh_prompt(void); -void vtysh_config_write (void); +void vtysh_config_write(void); -int vtysh_config_from_file (struct vty *, FILE *); +int vtysh_config_from_file(struct vty *, FILE *); -void config_add_line (struct list *, const char *); +void config_add_line(struct list *, const char *); int vtysh_mark_file(const char *filename); -int vtysh_read_config (const char *); -int vtysh_write_config_integrated (void); +int vtysh_read_config(const char *); +int vtysh_write_config_integrated(void); -void vtysh_config_parse_line (void *, const char *); +void vtysh_config_parse_line(void *, const char *); -void vtysh_config_dump (FILE *); +void vtysh_config_dump(FILE *); -void vtysh_config_init (void); +void vtysh_config_init(void); -void vtysh_pager_init (void); +void vtysh_pager_init(void); /* Child process execution flag. */ extern int execute_flag; extern struct vty *vty; -extern const char * vty_sock_path; +extern const char *vty_sock_path; #endif /* VTYSH_H */ diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c index 4dd373ed9..74509d1ec 100644 --- a/vtysh/vtysh_config.c +++ b/vtysh/vtysh_config.c @@ -28,414 +28,410 @@ #include "vtysh/vtysh_user.h" DEFINE_MGROUP(MVTYSH, "vtysh") -DEFINE_MTYPE_STATIC(MVTYSH, VTYSH_CONFIG, "Vtysh configuration") +DEFINE_MTYPE_STATIC(MVTYSH, VTYSH_CONFIG, "Vtysh configuration") DEFINE_MTYPE_STATIC(MVTYSH, VTYSH_CONFIG_LINE, "Vtysh configuration line") vector configvec; -struct config -{ - /* Configuration node name. */ - char *name; +struct config { + /* Configuration node name. */ + char *name; - /* Configuration string line. */ - struct list *line; + /* Configuration string line. */ + struct list *line; - /* Configuration can be nest. */ - struct config *config; + /* Configuration can be nest. */ + struct config *config; - /* Index of this config. */ - u_int32_t index; + /* Index of this config. */ + u_int32_t index; }; struct list *config_top; -static int -line_cmp (char *c1, char *c2) +static int line_cmp(char *c1, char *c2) { - return strcmp (c1, c2); + return strcmp(c1, c2); } -static void -line_del (char *line) +static void line_del(char *line) { - XFREE (MTYPE_VTYSH_CONFIG_LINE, line); + XFREE(MTYPE_VTYSH_CONFIG_LINE, line); } -static struct config * -config_new (void) +static struct config *config_new(void) { - struct config *config; - config = XCALLOC (MTYPE_VTYSH_CONFIG, sizeof (struct config)); - return config; + struct config *config; + config = XCALLOC(MTYPE_VTYSH_CONFIG, sizeof(struct config)); + return config; } -static int -config_cmp (struct config *c1, struct config *c2) +static int config_cmp(struct config *c1, struct config *c2) { - return strcmp (c1->name, c2->name); + return strcmp(c1->name, c2->name); } -static void -config_del (struct config* config) +static void config_del(struct config *config) { - list_delete (config->line); - if (config->name) - XFREE (MTYPE_VTYSH_CONFIG_LINE, config->name); - XFREE (MTYPE_VTYSH_CONFIG, config); + list_delete(config->line); + if (config->name) + XFREE(MTYPE_VTYSH_CONFIG_LINE, config->name); + XFREE(MTYPE_VTYSH_CONFIG, config); } -static struct config * -config_get (int index, const char *line) +static struct config *config_get(int index, const char *line) { - struct config *config; - struct config *config_loop; - struct list *master; - struct listnode *node, *nnode; - - config = config_loop = NULL; - - master = vector_lookup_ensure (configvec, index); - - if (! master) - { - master = list_new (); - master->del = (void (*) (void *))config_del; - master->cmp = (int (*)(void *, void *)) config_cmp; - vector_set_index (configvec, index, master); - } - - for (ALL_LIST_ELEMENTS (master, node, nnode, config_loop)) - { - if (strcmp (config_loop->name, line) == 0) - config = config_loop; - } - - if (! config) - { - config = config_new (); - config->line = list_new (); - config->line->del = (void (*) (void *))line_del; - config->line->cmp = (int (*)(void *, void *)) line_cmp; - config->name = XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line); - config->index = index; - listnode_add (master, config); - } - return config; + struct config *config; + struct config *config_loop; + struct list *master; + struct listnode *node, *nnode; + + config = config_loop = NULL; + + master = vector_lookup_ensure(configvec, index); + + if (!master) { + master = list_new(); + master->del = (void (*)(void *))config_del; + master->cmp = (int (*)(void *, void *))config_cmp; + vector_set_index(configvec, index, master); + } + + for (ALL_LIST_ELEMENTS(master, node, nnode, config_loop)) { + if (strcmp(config_loop->name, line) == 0) + config = config_loop; + } + + if (!config) { + config = config_new(); + config->line = list_new(); + config->line->del = (void (*)(void *))line_del; + config->line->cmp = (int (*)(void *, void *))line_cmp; + config->name = XSTRDUP(MTYPE_VTYSH_CONFIG_LINE, line); + config->index = index; + listnode_add(master, config); + } + return config; } -void -config_add_line (struct list *config, const char *line) +void config_add_line(struct list *config, const char *line) { - listnode_add (config, XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line)); + listnode_add(config, XSTRDUP(MTYPE_VTYSH_CONFIG_LINE, line)); } -static void -config_add_line_uniq (struct list *config, const char *line) +static void config_add_line_uniq(struct list *config, const char *line) { - struct listnode *node, *nnode; - char *pnt; - - for (ALL_LIST_ELEMENTS (config, node, nnode, pnt)) - { - if (strcmp (pnt, line) == 0) - return; - } - listnode_add_sort (config, XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line)); + struct listnode *node, *nnode; + char *pnt; + + for (ALL_LIST_ELEMENTS(config, node, nnode, pnt)) { + if (strcmp(pnt, line) == 0) + return; + } + listnode_add_sort(config, XSTRDUP(MTYPE_VTYSH_CONFIG_LINE, line)); } -void -vtysh_config_parse_line (void *arg, const char *line) +void vtysh_config_parse_line(void *arg, const char *line) { - char c; - static struct config *config = NULL; - - if (! line) - return; - - c = line[0]; - - if (c == '\0') - return; - - /* printf ("[%s]\n", line); */ - - switch (c) - { - /* Suppress exclamation points ! and commented lines. The !s are generated - * dynamically in vtysh_config_dump() */ - case '!': - case '#': - break; - case ' ': - /* Store line to current configuration. */ - if (config) - { - if (strncmp (line, " link-params", strlen (" link-params")) == 0) - { - config_add_line (config->line, line); - config->index = LINK_PARAMS_NODE; - } - else if (config->index == LINK_PARAMS_NODE && - strncmp (line, " exit-link-params", strlen (" exit")) == 0) - { - config_add_line (config->line, line); - config->index = INTERFACE_NODE; - } - else if (config->index == RMAP_NODE || - config->index == INTERFACE_NODE || - config->index == NS_NODE || - config->index == VTY_NODE || - config->index == VRF_NODE) - config_add_line_uniq (config->line, line); - else - config_add_line (config->line, line); - } - else - config_add_line (config_top, line); - break; - default: - if (strncmp (line, "interface", strlen ("interface")) == 0) - config = config_get (INTERFACE_NODE, line); - else if (strncmp (line, "logical-router", strlen ("ns")) == 0) - config = config_get (NS_NODE, line); - else if (strncmp (line, "vrf", strlen ("vrf")) == 0) - config = config_get (VRF_NODE, line); - else if (strncmp (line, "router-id", strlen ("router-id")) == 0) - config = config_get (ZEBRA_NODE, line); - else if (strncmp (line, "router rip", strlen ("router rip")) == 0) - config = config_get (RIP_NODE, line); - else if (strncmp (line, "router ripng", strlen ("router ripng")) == 0) - config = config_get (RIPNG_NODE, line); - else if (strncmp (line, "router eigrp", strlen ("router eigrp")) == 0) - config = config_get (EIGRP_NODE, line); - else if (strncmp (line, "router babel", strlen ("router babel")) == 0) - config = config_get (BABEL_NODE, line); - else if (strncmp (line, "router ospf", strlen ("router ospf")) == 0) - config = config_get (OSPF_NODE, line); - else if (strncmp (line, "router ospf6", strlen ("router ospf6")) == 0) - config = config_get (OSPF6_NODE, line); - else if (strncmp (line, "mpls ldp", strlen ("mpls ldp")) == 0) - config = config_get (LDP_NODE, line); - else if (strncmp (line, "l2vpn", strlen ("l2vpn")) == 0) - config = config_get (LDP_L2VPN_NODE, line); - else if (strncmp (line, "router bgp", strlen ("router bgp")) == 0) - config = config_get (BGP_NODE, line); - else if (strncmp (line, "router isis", strlen ("router isis")) == 0) - config = config_get (ISIS_NODE, line); - else if (strncmp (line, "route-map", strlen ("route-map")) == 0) - config = config_get (RMAP_NODE, line); - else if (strncmp (line, "access-list", strlen ("access-list")) == 0) - config = config_get (ACCESS_NODE, line); - else if (strncmp (line, "ipv6 access-list", - strlen ("ipv6 access-list")) == 0) - config = config_get (ACCESS_IPV6_NODE, line); - else if (strncmp (line, "ip prefix-list", - strlen ("ip prefix-list")) == 0) - config = config_get (PREFIX_NODE, line); - else if (strncmp (line, "ipv6 prefix-list", - strlen ("ipv6 prefix-list")) == 0) - config = config_get (PREFIX_IPV6_NODE, line); - else if (strncmp (line, "ip as-path access-list", - strlen ("ip as-path access-list")) == 0) - config = config_get (AS_LIST_NODE, line); - else if (strncmp (line, "ip community-list", strlen ("ip community-list")) == 0 || - strncmp (line, "ip extcommunity-list", strlen ("ip extcommunity-list")) == 0) - config = config_get (COMMUNITY_LIST_NODE, line); - else if (strncmp (line, "ip route", strlen ("ip route")) == 0) - config = config_get (IP_NODE, line); - else if (strncmp (line, "ipv6 route", strlen ("ipv6 route")) == 0) - config = config_get (IP_NODE, line); - else if (strncmp (line, "key", strlen ("key")) == 0) - config = config_get (KEYCHAIN_NODE, line); - else if (strncmp (line, "line", strlen ("line")) == 0) - config = config_get (VTY_NODE, line); - else if ( (strncmp (line, "ipv6 forwarding", - strlen ("ipv6 forwarding")) == 0) - || (strncmp (line, "ip forwarding", - strlen ("ip forwarding")) == 0) ) - config = config_get (FORWARDING_NODE, line); - else if (strncmp (line, "service", strlen ("service")) == 0) - config = config_get (SERVICE_NODE, line); - else if (strncmp (line, "debug vrf", strlen ("debug vrf")) == 0) - config = config_get (VRF_DEBUG_NODE, line); - else if (strncmp (line, "debug", strlen ("debug")) == 0) - config = config_get (DEBUG_NODE, line); - else if (strncmp (line, "password", strlen ("password")) == 0 - || strncmp (line, "enable password", - strlen ("enable password")) == 0) - config = config_get (AAA_NODE, line); - else if (strncmp (line, "ip protocol", strlen ("ip protocol")) == 0) - config = config_get (PROTOCOL_NODE, line); - else if (strncmp (line, "ipv6 protocol", strlen ("ipv6 protocol")) == 0) - config = config_get (PROTOCOL_NODE, line); - else if (strncmp (line, "ip nht", strlen ("ip nht")) == 0) - config = config_get (PROTOCOL_NODE, line); - else if (strncmp (line, "ipv6 nht", strlen ("ipv6 nht")) == 0) - config = config_get (PROTOCOL_NODE, line); - else if (strncmp (line, "mpls", strlen ("mpls")) == 0) - config = config_get (MPLS_NODE, line); - else - { - if (strncmp (line, "log", strlen ("log")) == 0 - || strncmp (line, "hostname", strlen ("hostname")) == 0 - || strncmp (line, "frr", strlen ("frr")) == 0 - || strncmp (line, "agentx", strlen ("agentx")) == 0 - || strncmp (line, "no log", strlen ("no log")) == 0 - ) - config_add_line_uniq (config_top, line); - else - config_add_line (config_top, line); - config = NULL; + char c; + static struct config *config = NULL; + + if (!line) + return; + + c = line[0]; + + if (c == '\0') + return; + + /* printf ("[%s]\n", line); */ + + switch (c) { + /* Suppress exclamation points ! and commented lines. The !s are + * generated + * dynamically in vtysh_config_dump() */ + case '!': + case '#': + break; + case ' ': + /* Store line to current configuration. */ + if (config) { + if (strncmp(line, " link-params", + strlen(" link-params")) + == 0) { + config_add_line(config->line, line); + config->index = LINK_PARAMS_NODE; + } else if (config->index == LINK_PARAMS_NODE + && strncmp(line, " exit-link-params", + strlen(" exit")) + == 0) { + config_add_line(config->line, line); + config->index = INTERFACE_NODE; + } else if (config->index == RMAP_NODE + || config->index == INTERFACE_NODE + || config->index == NS_NODE + || config->index == VTY_NODE + || config->index == VRF_NODE) + config_add_line_uniq(config->line, line); + else + config_add_line(config->line, line); + } else + config_add_line(config_top, line); + break; + default: + if (strncmp(line, "interface", strlen("interface")) == 0) + config = config_get(INTERFACE_NODE, line); + else if (strncmp(line, "logical-router", strlen("ns")) == 0) + config = config_get(NS_NODE, line); + else if (strncmp(line, "vrf", strlen("vrf")) == 0) + config = config_get(VRF_NODE, line); + else if (strncmp(line, "router-id", strlen("router-id")) == 0) + config = config_get(ZEBRA_NODE, line); + else if (strncmp(line, "router rip", strlen("router rip")) == 0) + config = config_get(RIP_NODE, line); + else if (strncmp(line, "router ripng", strlen("router ripng")) + == 0) + config = config_get(RIPNG_NODE, line); + else if (strncmp(line, "router eigrp", strlen("router eigrp")) + == 0) + config = config_get(EIGRP_NODE, line); + else if (strncmp(line, "router babel", strlen("router babel")) + == 0) + config = config_get(BABEL_NODE, line); + else if (strncmp(line, "router ospf", strlen("router ospf")) + == 0) + config = config_get(OSPF_NODE, line); + else if (strncmp(line, "router ospf6", strlen("router ospf6")) + == 0) + config = config_get(OSPF6_NODE, line); + else if (strncmp(line, "mpls ldp", strlen("mpls ldp")) == 0) + config = config_get(LDP_NODE, line); + else if (strncmp(line, "l2vpn", strlen("l2vpn")) == 0) + config = config_get(LDP_L2VPN_NODE, line); + else if (strncmp(line, "router bgp", strlen("router bgp")) == 0) + config = config_get(BGP_NODE, line); + else if (strncmp(line, "router isis", strlen("router isis")) + == 0) + config = config_get(ISIS_NODE, line); + else if (strncmp(line, "route-map", strlen("route-map")) == 0) + config = config_get(RMAP_NODE, line); + else if (strncmp(line, "access-list", strlen("access-list")) + == 0) + config = config_get(ACCESS_NODE, line); + else if (strncmp(line, "ipv6 access-list", + strlen("ipv6 access-list")) + == 0) + config = config_get(ACCESS_IPV6_NODE, line); + else if (strncmp(line, "ip prefix-list", + strlen("ip prefix-list")) + == 0) + config = config_get(PREFIX_NODE, line); + else if (strncmp(line, "ipv6 prefix-list", + strlen("ipv6 prefix-list")) + == 0) + config = config_get(PREFIX_IPV6_NODE, line); + else if (strncmp(line, "ip as-path access-list", + strlen("ip as-path access-list")) + == 0) + config = config_get(AS_LIST_NODE, line); + else if (strncmp(line, "ip community-list", + strlen("ip community-list")) + == 0 + || strncmp(line, "ip extcommunity-list", + strlen("ip extcommunity-list")) + == 0) + config = config_get(COMMUNITY_LIST_NODE, line); + else if (strncmp(line, "ip route", strlen("ip route")) == 0) + config = config_get(IP_NODE, line); + else if (strncmp(line, "ipv6 route", strlen("ipv6 route")) == 0) + config = config_get(IP_NODE, line); + else if (strncmp(line, "key", strlen("key")) == 0) + config = config_get(KEYCHAIN_NODE, line); + else if (strncmp(line, "line", strlen("line")) == 0) + config = config_get(VTY_NODE, line); + else if ((strncmp(line, "ipv6 forwarding", + strlen("ipv6 forwarding")) + == 0) + || (strncmp(line, "ip forwarding", + strlen("ip forwarding")) + == 0)) + config = config_get(FORWARDING_NODE, line); + else if (strncmp(line, "service", strlen("service")) == 0) + config = config_get(SERVICE_NODE, line); + else if (strncmp(line, "debug vrf", strlen("debug vrf")) == 0) + config = config_get(VRF_DEBUG_NODE, line); + else if (strncmp(line, "debug", strlen("debug")) == 0) + config = config_get(DEBUG_NODE, line); + else if (strncmp(line, "password", strlen("password")) == 0 + || strncmp(line, "enable password", + strlen("enable password")) + == 0) + config = config_get(AAA_NODE, line); + else if (strncmp(line, "ip protocol", strlen("ip protocol")) + == 0) + config = config_get(PROTOCOL_NODE, line); + else if (strncmp(line, "ipv6 protocol", strlen("ipv6 protocol")) + == 0) + config = config_get(PROTOCOL_NODE, line); + else if (strncmp(line, "ip nht", strlen("ip nht")) == 0) + config = config_get(PROTOCOL_NODE, line); + else if (strncmp(line, "ipv6 nht", strlen("ipv6 nht")) == 0) + config = config_get(PROTOCOL_NODE, line); + else if (strncmp(line, "mpls", strlen("mpls")) == 0) + config = config_get(MPLS_NODE, line); + else { + if (strncmp(line, "log", strlen("log")) == 0 + || strncmp(line, "hostname", strlen("hostname")) + == 0 + || strncmp(line, "frr", strlen("frr")) == 0 + || strncmp(line, "agentx", strlen("agentx")) == 0 + || strncmp(line, "no log", strlen("no log")) == 0) + config_add_line_uniq(config_top, line); + else + config_add_line(config_top, line); + config = NULL; + } + break; } - break; - } } /* Macro to check delimiter is needed between each configuration line * or not. */ -#define NO_DELIMITER(I) \ - ((I) == ACCESS_NODE || (I) == PREFIX_NODE || (I) == IP_NODE \ - || (I) == AS_LIST_NODE || (I) == COMMUNITY_LIST_NODE || \ - (I) == ACCESS_IPV6_NODE || (I) == PREFIX_IPV6_NODE \ - || (I) == SERVICE_NODE || (I) == FORWARDING_NODE || (I) == DEBUG_NODE \ - || (I) == AAA_NODE || (I) == VRF_DEBUG_NODE || (I) == MPLS_NODE) +#define NO_DELIMITER(I) \ + ((I) == ACCESS_NODE || (I) == PREFIX_NODE || (I) == IP_NODE \ + || (I) == AS_LIST_NODE || (I) == COMMUNITY_LIST_NODE \ + || (I) == ACCESS_IPV6_NODE || (I) == PREFIX_IPV6_NODE \ + || (I) == SERVICE_NODE || (I) == FORWARDING_NODE || (I) == DEBUG_NODE \ + || (I) == AAA_NODE || (I) == VRF_DEBUG_NODE || (I) == MPLS_NODE) /* Display configuration to file pointer. */ -void -vtysh_config_dump (FILE *fp) +void vtysh_config_dump(FILE *fp) { - struct listnode *node, *nnode; - struct listnode *mnode, *mnnode; - struct config *config; - struct list *master; - char *line; - unsigned int i; - - for (ALL_LIST_ELEMENTS (config_top, node, nnode, line)) - { - fprintf (fp, "%s\n", line); - fflush (fp); - } - fprintf (fp, "!\n"); - fflush (fp); - - for (i = 0; i < vector_active (configvec); i++) - if ((master = vector_slot (configvec, i)) != NULL) - { - for (ALL_LIST_ELEMENTS (master, node, nnode, config)) - { - /* Don't print empty sections for interface/vrf. Route maps on the - * other hand could have a legitimate empty section at the end. - */ - if ((config->index == INTERFACE_NODE || config->index == VRF_NODE) - && list_isempty (config->line)) - continue; - - fprintf (fp, "%s\n", config->name); - fflush (fp); - - for (ALL_LIST_ELEMENTS (config->line, mnode, mnnode, line)) - { - fprintf (fp, "%s\n", line); - fflush (fp); - } - if (! NO_DELIMITER (i)) - { - fprintf (fp, "!\n"); - fflush (fp); - } - } - if (NO_DELIMITER (i)) - { - fprintf (fp, "!\n"); - fflush (fp); - } - } - - for (i = 0; i < vector_active (configvec); i++) - if ((master = vector_slot (configvec, i)) != NULL) - { - list_delete (master); - vector_slot (configvec, i) = NULL; - } - list_delete_all_node (config_top); + struct listnode *node, *nnode; + struct listnode *mnode, *mnnode; + struct config *config; + struct list *master; + char *line; + unsigned int i; + + for (ALL_LIST_ELEMENTS(config_top, node, nnode, line)) { + fprintf(fp, "%s\n", line); + fflush(fp); + } + fprintf(fp, "!\n"); + fflush(fp); + + for (i = 0; i < vector_active(configvec); i++) + if ((master = vector_slot(configvec, i)) != NULL) { + for (ALL_LIST_ELEMENTS(master, node, nnode, config)) { + /* Don't print empty sections for interface/vrf. + * Route maps on the + * other hand could have a legitimate empty + * section at the end. + */ + if ((config->index == INTERFACE_NODE + || config->index == VRF_NODE) + && list_isempty(config->line)) + continue; + + fprintf(fp, "%s\n", config->name); + fflush(fp); + + for (ALL_LIST_ELEMENTS(config->line, mnode, + mnnode, line)) { + fprintf(fp, "%s\n", line); + fflush(fp); + } + if (!NO_DELIMITER(i)) { + fprintf(fp, "!\n"); + fflush(fp); + } + } + if (NO_DELIMITER(i)) { + fprintf(fp, "!\n"); + fflush(fp); + } + } + + for (i = 0; i < vector_active(configvec); i++) + if ((master = vector_slot(configvec, i)) != NULL) { + list_delete(master); + vector_slot(configvec, i) = NULL; + } + list_delete_all_node(config_top); } /* Read up configuration file from file_name. */ -static int -vtysh_read_file (FILE *confp) +static int vtysh_read_file(FILE *confp) { - struct vty *vty; - int ret; + struct vty *vty; + int ret; + + vty = vty_new(); + vty->fd = 0; /* stdout */ + vty->type = VTY_TERM; + vty->node = CONFIG_NODE; - vty = vty_new (); - vty->fd = 0; /* stdout */ - vty->type = VTY_TERM; - vty->node = CONFIG_NODE; - - vtysh_execute_no_pager ("enable"); - vtysh_execute_no_pager ("configure terminal"); + vtysh_execute_no_pager("enable"); + vtysh_execute_no_pager("configure terminal"); - /* Execute configuration file. */ - ret = vtysh_config_from_file (vty, confp); + /* Execute configuration file. */ + ret = vtysh_config_from_file(vty, confp); - vtysh_execute_no_pager ("end"); - vtysh_execute_no_pager ("disable"); + vtysh_execute_no_pager("end"); + vtysh_execute_no_pager("disable"); - vty_close (vty); + vty_close(vty); - return (ret); + return (ret); } /* Read up configuration file from config_default_dir. */ -int -vtysh_read_config (const char *config_default_dir) +int vtysh_read_config(const char *config_default_dir) { - FILE *confp = NULL; - int ret; - - confp = fopen (config_default_dir, "r"); - if (confp == NULL) - { - fprintf (stderr, "%% Can't open configuration file %s due to '%s'.\n", - config_default_dir, safe_strerror (errno)); - return (CMD_ERR_NO_FILE); - } + FILE *confp = NULL; + int ret; + + confp = fopen(config_default_dir, "r"); + if (confp == NULL) { + fprintf(stderr, + "%% Can't open configuration file %s due to '%s'.\n", + config_default_dir, safe_strerror(errno)); + return (CMD_ERR_NO_FILE); + } - ret = vtysh_read_file (confp); - fclose (confp); + ret = vtysh_read_file(confp); + fclose(confp); - return (ret); + return (ret); } /* We don't write vtysh specific into file from vtysh. vtysh.conf should * be edited by hand. So, we handle only "write terminal" case here and * integrate vtysh specific conf with conf from daemons. */ -void -vtysh_config_write () +void vtysh_config_write() { - char line[81]; - extern struct host host; - - if (host.name) - { - sprintf (line, "hostname %s", host.name); - vtysh_config_parse_line(NULL, line); - } - if (vtysh_write_integrated == WRITE_INTEGRATED_NO) - vtysh_config_parse_line (NULL, "no service integrated-vtysh-config"); - if (vtysh_write_integrated == WRITE_INTEGRATED_YES) - vtysh_config_parse_line (NULL, "service integrated-vtysh-config"); - - user_config_write (); + char line[81]; + extern struct host host; + + if (host.name) { + sprintf(line, "hostname %s", host.name); + vtysh_config_parse_line(NULL, line); + } + if (vtysh_write_integrated == WRITE_INTEGRATED_NO) + vtysh_config_parse_line(NULL, + "no service integrated-vtysh-config"); + if (vtysh_write_integrated == WRITE_INTEGRATED_YES) + vtysh_config_parse_line(NULL, + "service integrated-vtysh-config"); + + user_config_write(); } -void -vtysh_config_init () +void vtysh_config_init() { - config_top = list_new (); - config_top->del = (void (*) (void *))line_del; - configvec = vector_init (1); + config_top = list_new(); + config_top->del = (void (*)(void *))line_del; + configvec = vector_init(1); } diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c index d2ac56c36..8145bf364 100644 --- a/vtysh/vtysh_main.c +++ b/vtysh/vtysh_main.c @@ -54,7 +54,7 @@ char history_file[MAXPATHLEN]; int execute_flag = 0; /* VTY Socket prefix */ -const char * vty_sock_path = NULL; +const char *vty_sock_path = NULL; /* For sigsetjmp() & siglongjmp(). */ static sigjmp_buf jmpbuf; @@ -72,585 +72,561 @@ struct thread_master *master; FILE *logfile; /* SIGTSTP handler. This function care user's ^Z input. */ -static void -sigtstp (int sig) +static void sigtstp(int sig) { - /* Execute "end" command. */ - vtysh_execute ("end"); - - /* Initialize readline. */ - rl_initialize (); - printf ("\n"); + /* Execute "end" command. */ + vtysh_execute("end"); - /* Check jmpflag for duplicate siglongjmp(). */ - if (! jmpflag) - return; + /* Initialize readline. */ + rl_initialize(); + printf("\n"); - jmpflag = 0; + /* Check jmpflag for duplicate siglongjmp(). */ + if (!jmpflag) + return; - /* Back to main command loop. */ - siglongjmp (jmpbuf, 1); + jmpflag = 0; + + /* Back to main command loop. */ + siglongjmp(jmpbuf, 1); } /* SIGINT handler. This function care user's ^Z input. */ -static void -sigint (int sig) +static void sigint(int sig) { - /* Check this process is not child process. */ - if (! execute_flag) - { - rl_initialize (); - printf ("\n"); - rl_forced_update_display (); - } + /* Check this process is not child process. */ + if (!execute_flag) { + rl_initialize(); + printf("\n"); + rl_forced_update_display(); + } } /* Signale wrapper for vtysh. We don't use sigevent because * vtysh doesn't use threads. TODO */ -static void -vtysh_signal_set (int signo, void (*func)(int)) +static void vtysh_signal_set(int signo, void (*func)(int)) { - struct sigaction sig; - struct sigaction osig; + struct sigaction sig; + struct sigaction osig; - sig.sa_handler = func; - sigemptyset (&sig.sa_mask); - sig.sa_flags = 0; + sig.sa_handler = func; + sigemptyset(&sig.sa_mask); + sig.sa_flags = 0; #ifdef SA_RESTART - sig.sa_flags |= SA_RESTART; + sig.sa_flags |= SA_RESTART; #endif /* SA_RESTART */ - sigaction (signo, &sig, &osig); + sigaction(signo, &sig, &osig); } /* Initialization of signal handles. */ -static void -vtysh_signal_init (void) +static void vtysh_signal_init(void) { - vtysh_signal_set (SIGINT, sigint); - vtysh_signal_set (SIGTSTP, sigtstp); - vtysh_signal_set (SIGPIPE, SIG_IGN); + vtysh_signal_set(SIGINT, sigint); + vtysh_signal_set(SIGTSTP, sigtstp); + vtysh_signal_set(SIGPIPE, SIG_IGN); } /* Help information display. */ -static void -usage (int status) +static void usage(int status) { - if (status != 0) - fprintf (stderr, "Try `%s --help' for more information.\n", progname); - else - printf ("Usage : %s [OPTION...]\n\n" \ - "Integrated shell for FRR. \n\n" \ - "-b, --boot Execute boot startup configuration\n" \ - "-c, --command Execute argument as command\n" \ - "-d, --daemon Connect only to the specified daemon\n" \ - "-f, --inputfile Execute commands from specific file and exit\n" \ - "-E, --echo Echo prompt and command in -c mode\n" \ - "-C, --dryrun Check configuration for validity and exit\n" \ - "-m, --markfile Mark input file with context end\n" \ - " --vty_socket Override vty socket path\n" \ - " --config_dir Override config directory path\n" \ - "-w, --writeconfig Write integrated config (frr.conf) and exit\n" \ - "-h, --help Display this help and exit\n\n" \ - "Note that multiple commands may be executed from the command\n" \ - "line by passing multiple -c args, or by embedding linefeed\n" \ - "characters in one or more of the commands.\n\n" \ - "Report bugs to %s\n", progname, FRR_BUG_ADDRESS); - - exit (status); + if (status != 0) + fprintf(stderr, "Try `%s --help' for more information.\n", + progname); + else + printf("Usage : %s [OPTION...]\n\n" + "Integrated shell for FRR. \n\n" + "-b, --boot Execute boot startup configuration\n" + "-c, --command Execute argument as command\n" + "-d, --daemon Connect only to the specified daemon\n" + "-f, --inputfile Execute commands from specific file and exit\n" + "-E, --echo Echo prompt and command in -c mode\n" + "-C, --dryrun Check configuration for validity and exit\n" + "-m, --markfile Mark input file with context end\n" + " --vty_socket Override vty socket path\n" + " --config_dir Override config directory path\n" + "-w, --writeconfig Write integrated config (frr.conf) and exit\n" + "-h, --help Display this help and exit\n\n" + "Note that multiple commands may be executed from the command\n" + "line by passing multiple -c args, or by embedding linefeed\n" + "characters in one or more of the commands.\n\n" + "Report bugs to %s\n", + progname, FRR_BUG_ADDRESS); + + exit(status); } /* VTY shell options, we use GNU getopt library. */ #define OPTION_VTYSOCK 1000 #define OPTION_CONFDIR 1001 -struct option longopts[] = -{ - { "boot", no_argument, NULL, 'b'}, - /* For compatibility with older zebra/quagga versions */ - { "eval", required_argument, NULL, 'e'}, - { "command", required_argument, NULL, 'c'}, - { "daemon", required_argument, NULL, 'd'}, - { "vty_socket", required_argument, NULL, OPTION_VTYSOCK}, - { "config_dir", required_argument, NULL, OPTION_CONFDIR}, - { "inputfile", required_argument, NULL, 'f'}, - { "echo", no_argument, NULL, 'E'}, - { "dryrun", no_argument, NULL, 'C'}, - { "help", no_argument, NULL, 'h'}, - { "noerror", no_argument, NULL, 'n'}, - { "mark", no_argument, NULL, 'm'}, - { "writeconfig", no_argument, NULL, 'w'}, - { 0 } -}; +struct option longopts[] = { + {"boot", no_argument, NULL, 'b'}, + /* For compatibility with older zebra/quagga versions */ + {"eval", required_argument, NULL, 'e'}, + {"command", required_argument, NULL, 'c'}, + {"daemon", required_argument, NULL, 'd'}, + {"vty_socket", required_argument, NULL, OPTION_VTYSOCK}, + {"config_dir", required_argument, NULL, OPTION_CONFDIR}, + {"inputfile", required_argument, NULL, 'f'}, + {"echo", no_argument, NULL, 'E'}, + {"dryrun", no_argument, NULL, 'C'}, + {"help", no_argument, NULL, 'h'}, + {"noerror", no_argument, NULL, 'n'}, + {"mark", no_argument, NULL, 'm'}, + {"writeconfig", no_argument, NULL, 'w'}, + {0}}; /* Read a string, and return a pointer to it. Returns NULL on EOF. */ -static char * -vtysh_rl_gets (void) +static char *vtysh_rl_gets(void) { - HIST_ENTRY *last; - /* If the buffer has already been allocated, return the memory - * to the free pool. */ - if (line_read) - { - free (line_read); - line_read = NULL; - } - - /* Get a line from the user. Change prompt according to node. XXX. */ - line_read = readline (vtysh_prompt ()); - - /* If the line has any text in it, save it on the history. But only if - * last command in history isn't the same one. */ - if (line_read && *line_read) - { - using_history(); - last = previous_history(); - if (!last || strcmp (last->line, line_read) != 0) { - add_history (line_read); - append_history(1,history_file); - } - } - - return (line_read); + HIST_ENTRY *last; + /* If the buffer has already been allocated, return the memory + * to the free pool. */ + if (line_read) { + free(line_read); + line_read = NULL; + } + + /* Get a line from the user. Change prompt according to node. XXX. */ + line_read = readline(vtysh_prompt()); + + /* If the line has any text in it, save it on the history. But only if + * last command in history isn't the same one. */ + if (line_read && *line_read) { + using_history(); + last = previous_history(); + if (!last || strcmp(last->line, line_read) != 0) { + add_history(line_read); + append_history(1, history_file); + } + } + + return (line_read); } static void log_it(const char *line) { - time_t t = time(NULL); - struct tm *tmp = localtime(&t); - const char *user = getenv("USER"); - char tod[64]; + time_t t = time(NULL); + struct tm *tmp = localtime(&t); + const char *user = getenv("USER"); + char tod[64]; - if (!user) - user = "boot"; + if (!user) + user = "boot"; - strftime(tod, sizeof tod, "%Y%m%d-%H:%M.%S", tmp); - - fprintf(logfile, "%s:%s %s\n", tod, user, line); + strftime(tod, sizeof tod, "%Y%m%d-%H:%M.%S", tmp); + + fprintf(logfile, "%s:%s %s\n", tod, user, line); } static int flock_fd; -static void -vtysh_flock_config (const char *flock_file) +static void vtysh_flock_config(const char *flock_file) { - int count = 0; - - flock_fd = open (flock_file, O_RDONLY, 0644); - if (flock_fd < 0) - { - fprintf (stderr, "Unable to create lock file: %s, %s\n", - flock_file, safe_strerror (errno)); - return; - } - - while (count < 400 && (flock (flock_fd, LOCK_EX | LOCK_NB) < 0)) - { - count++; - usleep (500000); - } - - if (count >= 400) - fprintf(stderr, "Flock of %s failed, continuing this may cause issues\n", - flock_file); + int count = 0; + + flock_fd = open(flock_file, O_RDONLY, 0644); + if (flock_fd < 0) { + fprintf(stderr, "Unable to create lock file: %s, %s\n", + flock_file, safe_strerror(errno)); + return; + } + + while (count < 400 && (flock(flock_fd, LOCK_EX | LOCK_NB) < 0)) { + count++; + usleep(500000); + } + + if (count >= 400) + fprintf(stderr, + "Flock of %s failed, continuing this may cause issues\n", + flock_file); } -static void -vtysh_unflock_config (void) +static void vtysh_unflock_config(void) { - flock (flock_fd, LOCK_UN); - close (flock_fd); + flock(flock_fd, LOCK_UN); + close(flock_fd); } /* VTY shell main routine. */ -int -main (int argc, char **argv, char **env) +int main(int argc, char **argv, char **env) { - char *p; - int opt; - int dryrun = 0; - int boot_flag = 0; - const char *daemon_name = NULL; - const char *inputfile = NULL; - const char *vtysh_configfile_name; - struct cmd_rec { - char *line; - struct cmd_rec *next; - } *cmd = NULL; - struct cmd_rec *tail = NULL; - int echo_command = 0; - int no_error = 0; - int markfile = 0; - int writeconfig = 0; - int ret = 0; - char *homedir = NULL; - - /* check for restricted functionality if vtysh is run setuid */ - int restricted = (getuid() != geteuid()) || (getgid() != getegid()); - - /* Preserve name of myself. */ - progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]); - - /* if logging open now */ - if ((p = getenv("VTYSH_LOG")) != NULL) - logfile = fopen(p, "a"); - - /* Option handling. */ - while (1) - { - opt = getopt_long (argc, argv, "be:c:d:nf:mEhCw", longopts, 0); - - if (opt == EOF) - break; - - switch (opt) - { - case 0: - break; - case 'b': - boot_flag = 1; - break; - case 'e': - case 'c': - { - struct cmd_rec *cr; - cr = XMALLOC(MTYPE_TMP, sizeof(*cr)); - cr->line = optarg; - cr->next = NULL; - if (tail) - tail->next = cr; - else - cmd = cr; - tail = cr; - } - break; - case OPTION_VTYSOCK: - vty_sock_path = optarg; - break; - case OPTION_CONFDIR: - /* - * Skip option for Config Directory if setuid - */ - if (restricted) - { - fprintf (stderr, "Overriding of Config Directory blocked for vtysh with setuid"); - return 1; - } - /* - * Overwrite location for vtysh.conf - */ - vtysh_configfile_name = strrchr(VTYSH_DEFAULT_CONFIG, '/'); - if (vtysh_configfile_name) - /* skip '/' */ - vtysh_configfile_name++; - else - /* - * VTYSH_DEFAULT_CONFIG configured with relative path - * during config? Should really never happen for - * sensible config - */ - vtysh_configfile_name = (char *) VTYSH_DEFAULT_CONFIG; - strlcpy(vtysh_config_always, optarg, sizeof(vtysh_config_always)); - strlcat(vtysh_config_always, "/", sizeof(vtysh_config_always)); - strlcat(vtysh_config_always, vtysh_configfile_name, - sizeof(vtysh_config_always)); - /* - * Overwrite location for frr.conf - */ - vtysh_configfile_name = strrchr(FRR_DEFAULT_CONFIG, '/'); - if (vtysh_configfile_name) - /* skip '/' */ - vtysh_configfile_name++; - else - /* - * FRR_DEFAULT_CONFIG configured with relative path - * during config? Should really never happen for - * sensible config - */ - vtysh_configfile_name = (char *) FRR_DEFAULT_CONFIG; - strlcpy(quagga_config_default, optarg, sizeof(vtysh_config_always)); - strlcat(quagga_config_default, "/", sizeof(vtysh_config_always)); - strlcat(quagga_config_default, vtysh_configfile_name, - sizeof(quagga_config_default)); - break; - case 'd': - daemon_name = optarg; - break; - case 'f': - inputfile = optarg; - break; - case 'm': - markfile = 1; - break; - case 'n': - no_error = 1; - break; - case 'E': - echo_command = 1; - break; - case 'C': - dryrun = 1; - break; - case 'w': - writeconfig = 1; - break; - case 'h': - usage (0); - break; - default: - usage (1); - break; + char *p; + int opt; + int dryrun = 0; + int boot_flag = 0; + const char *daemon_name = NULL; + const char *inputfile = NULL; + const char *vtysh_configfile_name; + struct cmd_rec { + char *line; + struct cmd_rec *next; + } *cmd = NULL; + struct cmd_rec *tail = NULL; + int echo_command = 0; + int no_error = 0; + int markfile = 0; + int writeconfig = 0; + int ret = 0; + char *homedir = NULL; + + /* check for restricted functionality if vtysh is run setuid */ + int restricted = (getuid() != geteuid()) || (getgid() != getegid()); + + /* Preserve name of myself. */ + progname = ((p = strrchr(argv[0], '/')) ? ++p : argv[0]); + + /* if logging open now */ + if ((p = getenv("VTYSH_LOG")) != NULL) + logfile = fopen(p, "a"); + + /* Option handling. */ + while (1) { + opt = getopt_long(argc, argv, "be:c:d:nf:mEhCw", longopts, 0); + + if (opt == EOF) + break; + + switch (opt) { + case 0: + break; + case 'b': + boot_flag = 1; + break; + case 'e': + case 'c': { + struct cmd_rec *cr; + cr = XMALLOC(MTYPE_TMP, sizeof(*cr)); + cr->line = optarg; + cr->next = NULL; + if (tail) + tail->next = cr; + else + cmd = cr; + tail = cr; + } break; + case OPTION_VTYSOCK: + vty_sock_path = optarg; + break; + case OPTION_CONFDIR: + /* + * Skip option for Config Directory if setuid + */ + if (restricted) { + fprintf(stderr, + "Overriding of Config Directory blocked for vtysh with setuid"); + return 1; + } + /* + * Overwrite location for vtysh.conf + */ + vtysh_configfile_name = + strrchr(VTYSH_DEFAULT_CONFIG, '/'); + if (vtysh_configfile_name) + /* skip '/' */ + vtysh_configfile_name++; + else + /* + * VTYSH_DEFAULT_CONFIG configured with relative + * path + * during config? Should really never happen for + * sensible config + */ + vtysh_configfile_name = + (char *)VTYSH_DEFAULT_CONFIG; + strlcpy(vtysh_config_always, optarg, + sizeof(vtysh_config_always)); + strlcat(vtysh_config_always, "/", + sizeof(vtysh_config_always)); + strlcat(vtysh_config_always, vtysh_configfile_name, + sizeof(vtysh_config_always)); + /* + * Overwrite location for frr.conf + */ + vtysh_configfile_name = + strrchr(FRR_DEFAULT_CONFIG, '/'); + if (vtysh_configfile_name) + /* skip '/' */ + vtysh_configfile_name++; + else + /* + * FRR_DEFAULT_CONFIG configured with relative + * path + * during config? Should really never happen for + * sensible config + */ + vtysh_configfile_name = + (char *)FRR_DEFAULT_CONFIG; + strlcpy(quagga_config_default, optarg, + sizeof(vtysh_config_always)); + strlcat(quagga_config_default, "/", + sizeof(vtysh_config_always)); + strlcat(quagga_config_default, vtysh_configfile_name, + sizeof(quagga_config_default)); + break; + case 'd': + daemon_name = optarg; + break; + case 'f': + inputfile = optarg; + break; + case 'm': + markfile = 1; + break; + case 'n': + no_error = 1; + break; + case 'E': + echo_command = 1; + break; + case 'C': + dryrun = 1; + break; + case 'w': + writeconfig = 1; + break; + case 'h': + usage(0); + break; + default: + usage(1); + break; + } + } + + if (!vty_sock_path) + vty_sock_path = frr_vtydir; + + if (markfile + writeconfig + dryrun + boot_flag > 1) { + fprintf(stderr, + "Invalid combination of arguments. Please specify at " + "most one of:\n\t-b, -C, -m, -w\n"); + return 1; + } + if (inputfile && (writeconfig || boot_flag)) { + fprintf(stderr, + "WARNING: Combinining the -f option with -b or -w is " + "NOT SUPPORTED since its\nresults are inconsistent!\n"); + } + + /* Initialize user input buffer. */ + line_read = NULL; + setlinebuf(stdout); + + /* Signal and others. */ + vtysh_signal_init(); + + /* Make vty structure and register commands. */ + vtysh_init_vty(); + vtysh_init_cmd(); + vtysh_user_init(); + vtysh_config_init(); + + vty_init_vtysh(); + + /* Read vtysh configuration file before connecting to daemons. */ + vtysh_read_config(vtysh_config_always); + + if (markfile) { + if (!inputfile) { + fprintf(stderr, + "-f option MUST be specified with -m option\n"); + return (1); + } + return (vtysh_mark_file(inputfile)); + } + + /* Start execution only if not in dry-run mode */ + if (dryrun && !cmd) { + if (inputfile) { + ret = vtysh_read_config(inputfile); + } else { + ret = vtysh_read_config(quagga_config_default); + } + + exit(ret); } - } - - if (!vty_sock_path) - vty_sock_path = frr_vtydir; - - if (markfile + writeconfig + dryrun + boot_flag > 1) - { - fprintf (stderr, "Invalid combination of arguments. Please specify at " - "most one of:\n\t-b, -C, -m, -w\n"); - return 1; - } - if (inputfile && (writeconfig || boot_flag)) - { - fprintf (stderr, "WARNING: Combinining the -f option with -b or -w is " - "NOT SUPPORTED since its\nresults are inconsistent!\n"); - } - - /* Initialize user input buffer. */ - line_read = NULL; - setlinebuf(stdout); - - /* Signal and others. */ - vtysh_signal_init (); - - /* Make vty structure and register commands. */ - vtysh_init_vty (); - vtysh_init_cmd (); - vtysh_user_init (); - vtysh_config_init (); - - vty_init_vtysh (); - - /* Read vtysh configuration file before connecting to daemons. */ - vtysh_read_config(vtysh_config_always); - - if (markfile) - { - if (!inputfile) - { - fprintf(stderr, "-f option MUST be specified with -m option\n"); - return(1); + + if (dryrun && cmd) { + vtysh_execute("enable"); + while (cmd) { + struct cmd_rec *cr; + char *cmdnow = cmd->line, *next; + do { + next = strchr(cmdnow, '\n'); + if (next) + *next++ = '\0'; + + if (echo_command) + printf("%s%s\n", vtysh_prompt(), + cmdnow); + + ret = vtysh_execute_no_pager(cmdnow); + if (!no_error + && !(ret == CMD_SUCCESS + || ret == CMD_SUCCESS_DAEMON + || ret == CMD_WARNING)) + exit(1); + } while ((cmdnow = next) != NULL); + + cr = cmd; + cmd = cmd->next; + XFREE(MTYPE_TMP, cr); + } + exit(ret); } - return(vtysh_mark_file(inputfile)); - } - - /* Start execution only if not in dry-run mode */ - if (dryrun && !cmd) - { - if (inputfile) - { - ret = vtysh_read_config(inputfile); + + /* Ignore error messages */ + if (no_error) { + if (freopen("/dev/null", "w", stdout) == NULL) { + fprintf(stderr, + "Exiting: Failed to duplicate stdout with -n option"); + exit(1); + } } - else - { - ret = vtysh_read_config(quagga_config_default); + + /* Make sure we pass authentication before proceeding. */ + vtysh_auth(); + + /* Do not connect until we have passed authentication. */ + if (vtysh_connect_all(daemon_name) <= 0) { + fprintf(stderr, "Exiting: failed to connect to any daemons.\n"); + if (no_error) + exit(0); + else + exit(1); } - exit(ret); - } - - if (dryrun && cmd) - { - vtysh_execute ("enable"); - while (cmd) - { - struct cmd_rec *cr; - char *cmdnow = cmd->line, *next; - do - { - next = strchr(cmdnow, '\n'); - if (next) - *next++ = '\0'; - - if (echo_command) - printf("%s%s\n", vtysh_prompt(), cmdnow); - - ret = vtysh_execute_no_pager(cmdnow); - if (!no_error && - ! (ret == CMD_SUCCESS || - ret == CMD_SUCCESS_DAEMON || - ret == CMD_WARNING)) - exit(1); - } - while ((cmdnow = next) != NULL); - - cr = cmd; - cmd = cmd->next; - XFREE(MTYPE_TMP, cr); - } - exit(ret); - } - - /* Ignore error messages */ - if (no_error) - { - if (freopen("/dev/null", "w", stdout) == NULL) - { - fprintf(stderr, "Exiting: Failed to duplicate stdout with -n option"); - exit(1); + if (writeconfig) { + vtysh_execute("enable"); + return vtysh_write_config_integrated(); } - } - - /* Make sure we pass authentication before proceeding. */ - vtysh_auth (); - - /* Do not connect until we have passed authentication. */ - if (vtysh_connect_all (daemon_name) <= 0) - { - fprintf(stderr, "Exiting: failed to connect to any daemons.\n"); - if (no_error) - exit(0); - else - exit(1); - } - - if (writeconfig) - { - vtysh_execute ("enable"); - return vtysh_write_config_integrated (); - } - - if (inputfile) - { - vtysh_flock_config (inputfile); - ret = vtysh_read_config(inputfile); - vtysh_unflock_config (); - exit(ret); - } - - /* - * Setup history file for use by both -c and regular input - * If we can't find the home directory, then don't store - * the history information - */ - homedir = vtysh_get_home (); - if (homedir) - { - snprintf(history_file, sizeof(history_file), "%s/.history_quagga", homedir); - if (read_history (history_file) != 0) - { - int fp; - - fp = open (history_file, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); - if (fp) - close (fp); - - read_history (history_file); + + if (inputfile) { + vtysh_flock_config(inputfile); + ret = vtysh_read_config(inputfile); + vtysh_unflock_config(); + exit(ret); } - } - - /* If eval mode. */ - if (cmd) - { - /* Enter into enable node. */ - vtysh_execute ("enable"); - - while (cmd != NULL) - { - int ret; - char *eol; - - while ((eol = strchr(cmd->line, '\n')) != NULL) - { - *eol = '\0'; - - add_history (cmd->line); - append_history (1, history_file); - - if (echo_command) - printf("%s%s\n", vtysh_prompt(), cmd->line); - - if (logfile) - log_it(cmd->line); - - ret = vtysh_execute_no_pager(cmd->line); - if (!no_error && - ! (ret == CMD_SUCCESS || - ret == CMD_SUCCESS_DAEMON || - ret == CMD_WARNING)) - exit(1); - - cmd->line = eol+1; - } - - add_history (cmd->line); - append_history (1, history_file); - - if (echo_command) - printf("%s%s\n", vtysh_prompt(), cmd->line); - - if (logfile) - log_it(cmd->line); - - ret = vtysh_execute_no_pager(cmd->line); - if (!no_error && - ! (ret == CMD_SUCCESS || - ret == CMD_SUCCESS_DAEMON || - ret == CMD_WARNING)) - exit(1); - - { - struct cmd_rec *cr; - cr = cmd; - cmd = cmd->next; - XFREE(MTYPE_TMP, cr); - } - } - - history_truncate_file(history_file,1000); - exit (0); - } - - /* Boot startup configuration file. */ - if (boot_flag) - { - vtysh_flock_config (quagga_config); - int ret = vtysh_read_config (quagga_config); - vtysh_unflock_config (); - if (ret) - { - fprintf (stderr, "Configuration file[%s] processing failure: %d\n", - quagga_config, ret); - if (no_error) - exit (0); - else - exit (ret); + + /* + * Setup history file for use by both -c and regular input + * If we can't find the home directory, then don't store + * the history information + */ + homedir = vtysh_get_home(); + if (homedir) { + snprintf(history_file, sizeof(history_file), + "%s/.history_quagga", homedir); + if (read_history(history_file) != 0) { + int fp; + + fp = open(history_file, O_CREAT | O_EXCL, + S_IRUSR | S_IWUSR); + if (fp) + close(fp); + + read_history(history_file); + } + } + + /* If eval mode. */ + if (cmd) { + /* Enter into enable node. */ + vtysh_execute("enable"); + + while (cmd != NULL) { + int ret; + char *eol; + + while ((eol = strchr(cmd->line, '\n')) != NULL) { + *eol = '\0'; + + add_history(cmd->line); + append_history(1, history_file); + + if (echo_command) + printf("%s%s\n", vtysh_prompt(), + cmd->line); + + if (logfile) + log_it(cmd->line); + + ret = vtysh_execute_no_pager(cmd->line); + if (!no_error + && !(ret == CMD_SUCCESS + || ret == CMD_SUCCESS_DAEMON + || ret == CMD_WARNING)) + exit(1); + + cmd->line = eol + 1; + } + + add_history(cmd->line); + append_history(1, history_file); + + if (echo_command) + printf("%s%s\n", vtysh_prompt(), cmd->line); + + if (logfile) + log_it(cmd->line); + + ret = vtysh_execute_no_pager(cmd->line); + if (!no_error + && !(ret == CMD_SUCCESS || ret == CMD_SUCCESS_DAEMON + || ret == CMD_WARNING)) + exit(1); + + { + struct cmd_rec *cr; + cr = cmd; + cmd = cmd->next; + XFREE(MTYPE_TMP, cr); + } + } + + history_truncate_file(history_file, 1000); + exit(0); + } + + /* Boot startup configuration file. */ + if (boot_flag) { + vtysh_flock_config(quagga_config); + int ret = vtysh_read_config(quagga_config); + vtysh_unflock_config(); + if (ret) { + fprintf(stderr, + "Configuration file[%s] processing failure: %d\n", + quagga_config, ret); + if (no_error) + exit(0); + else + exit(ret); + } else + exit(0); } - else - exit (0); - } - vtysh_pager_init (); + vtysh_pager_init(); - vtysh_readline_init (); + vtysh_readline_init(); - vty_hello (vty); + vty_hello(vty); - /* Enter into enable node. */ - vtysh_execute ("enable"); + /* Enter into enable node. */ + vtysh_execute("enable"); - /* Preparation for longjmp() in sigtstp(). */ - sigsetjmp (jmpbuf, 1); - jmpflag = 1; + /* Preparation for longjmp() in sigtstp(). */ + sigsetjmp(jmpbuf, 1); + jmpflag = 1; - /* Main command loop. */ - while (vtysh_rl_gets ()) - vtysh_execute (line_read); + /* Main command loop. */ + while (vtysh_rl_gets()) + vtysh_execute(line_read); - history_truncate_file(history_file,1000); - printf ("\n"); + history_truncate_file(history_file, 1000); + printf("\n"); - /* Rest in peace. */ - exit (0); + /* Rest in peace. */ + exit(0); } diff --git a/vtysh/vtysh_user.c b/vtysh/vtysh_user.c index 97720e9fd..88af18d82 100644 --- a/vtysh/vtysh_user.c +++ b/vtysh/vtysh_user.c @@ -38,7 +38,7 @@ #include "command.h" #include "vtysh/vtysh_user.h" -/* +/* * Compiler is warning about prototypes not being declared. * The DEFUNSH and DEFUN macro's are messing with the * compiler I believe. This is just to make it happy. @@ -53,27 +53,22 @@ extern struct list *config_top; extern void config_add_line(struct list *config, const char *line); #ifdef USE_PAM -static struct pam_conv conv = -{ - PAM_CONV_FUNC, - NULL -}; +static struct pam_conv conv = {PAM_CONV_FUNC, NULL}; -static int -vtysh_pam (const char *user) +static int vtysh_pam(const char *user) { - int ret; - pam_handle_t *pamh = NULL; + int ret; + pam_handle_t *pamh = NULL; - /* Start PAM. */ - ret = pam_start(FRR_PAM_NAME, user, &conv, &pamh); - /* printf ("ret %d\n", ret); */ + /* Start PAM. */ + ret = pam_start(FRR_PAM_NAME, user, &conv, &pamh); + /* printf ("ret %d\n", ret); */ + + /* Is user really user? */ + if (ret == PAM_SUCCESS) + ret = pam_authenticate(pamh, 0); +/* printf ("ret %d\n", ret); */ - /* Is user really user? */ - if (ret == PAM_SUCCESS) - ret = pam_authenticate (pamh, 0); - /* printf ("ret %d\n", ret); */ - #if 0 /* Permitted access? */ if (ret == PAM_SUCCESS) @@ -83,85 +78,76 @@ vtysh_pam (const char *user) if (ret == PAM_AUTHINFO_UNAVAIL) ret = PAM_SUCCESS; #endif /* 0 */ - - /* This is where we have been authorized or not. */ + +/* This is where we have been authorized or not. */ #ifdef DEBUG - if (ret == PAM_SUCCESS) - printf("Authenticated\n"); - else - printf("Not Authenticated\n"); + if (ret == PAM_SUCCESS) + printf("Authenticated\n"); + else + printf("Not Authenticated\n"); #endif /* DEBUG */ - /* close Linux-PAM */ - if (pam_end (pamh, ret) != PAM_SUCCESS) - { - pamh = NULL; - fprintf(stderr, "vtysh_pam: failed to release authenticator\n"); - exit(1); - } + /* close Linux-PAM */ + if (pam_end(pamh, ret) != PAM_SUCCESS) { + pamh = NULL; + fprintf(stderr, "vtysh_pam: failed to release authenticator\n"); + exit(1); + } - return ret == PAM_SUCCESS ? 0 : 1; + return ret == PAM_SUCCESS ? 0 : 1; } #endif /* USE_PAM */ -struct vtysh_user -{ - char *name; - u_char nopassword; +struct vtysh_user { + char *name; + u_char nopassword; }; struct list *userlist; -static struct vtysh_user * -user_new (void) +static struct vtysh_user *user_new(void) { - return XCALLOC (MTYPE_TMP, sizeof (struct vtysh_user)); + return XCALLOC(MTYPE_TMP, sizeof(struct vtysh_user)); } -static struct vtysh_user * -user_lookup (const char *name) +static struct vtysh_user *user_lookup(const char *name) { - struct listnode *node, *nnode; - struct vtysh_user *user; + struct listnode *node, *nnode; + struct vtysh_user *user; - for (ALL_LIST_ELEMENTS (userlist, node, nnode, user)) - { - if (strcmp (user->name, name) == 0) - return user; - } - return NULL; + for (ALL_LIST_ELEMENTS(userlist, node, nnode, user)) { + if (strcmp(user->name, name) == 0) + return user; + } + return NULL; } -void -user_config_write () +void user_config_write() { - struct listnode *node, *nnode; - struct vtysh_user *user; - char line[128]; - - for (ALL_LIST_ELEMENTS (userlist, node, nnode, user)) - { - if (user->nopassword) - { - sprintf(line, "username %s nopassword", user->name); - config_add_line (config_top, line); + struct listnode *node, *nnode; + struct vtysh_user *user; + char line[128]; + + for (ALL_LIST_ELEMENTS(userlist, node, nnode, user)) { + if (user->nopassword) { + sprintf(line, "username %s nopassword", user->name); + config_add_line(config_top, line); + } } - } } -static struct vtysh_user * -user_get (const char *name) +static struct vtysh_user *user_get(const char *name) { - struct vtysh_user *user; - user = user_lookup (name); - if (user) - return user; + struct vtysh_user *user; + user = user_lookup(name); + if (user) + return user; - user = user_new (); - user->name = strdup (name); - listnode_add (userlist, user); + user = user_new(); + user->name = strdup(name); + listnode_add(userlist, user); - return user; + return user; } DEFUN (vtysh_banner_motd_file, @@ -172,8 +158,8 @@ DEFUN (vtysh_banner_motd_file, "Banner from a file\n" "Filename\n") { - int idx_file = 3; - return cmd_banner_motd_file (argv[idx_file]->arg); + int idx_file = 3; + return cmd_banner_motd_file(argv[idx_file]->arg); } DEFUN (username_nopassword, @@ -183,57 +169,53 @@ DEFUN (username_nopassword, "\n" "\n") { - int idx_word = 1; - struct vtysh_user *user; - user = user_get (argv[idx_word]->arg); - user->nopassword = 1; - return CMD_SUCCESS; + int idx_word = 1; + struct vtysh_user *user; + user = user_get(argv[idx_word]->arg); + user->nopassword = 1; + return CMD_SUCCESS; } -int -vtysh_auth (void) +int vtysh_auth(void) { - struct vtysh_user *user; - struct passwd *passwd; - - if ((passwd = getpwuid (geteuid ())) == NULL) - { - fprintf (stderr, "could not lookup user ID %d\n", (int) geteuid()); - exit (1); - } - - user = user_lookup (passwd->pw_name); - if (user && user->nopassword) - /* Pass through */; - else - { + struct vtysh_user *user; + struct passwd *passwd; + + if ((passwd = getpwuid(geteuid())) == NULL) { + fprintf(stderr, "could not lookup user ID %d\n", + (int)geteuid()); + exit(1); + } + + user = user_lookup(passwd->pw_name); + if (user && user->nopassword) + /* Pass through */; + else { #ifdef USE_PAM - if (vtysh_pam (passwd->pw_name)) - exit (0); + if (vtysh_pam(passwd->pw_name)) + exit(0); #endif /* USE_PAM */ - } - return 0; + } + return 0; } -char * -vtysh_get_home (void) +char *vtysh_get_home(void) { - struct passwd *passwd; - char * homedir; + struct passwd *passwd; + char *homedir; - if ((homedir = getenv("HOME")) != 0) - return homedir; + if ((homedir = getenv("HOME")) != 0) + return homedir; - /* Fallback if HOME is undefined */ - passwd = getpwuid (getuid ()); + /* Fallback if HOME is undefined */ + passwd = getpwuid(getuid()); - return passwd ? passwd->pw_dir : NULL; + return passwd ? passwd->pw_dir : NULL; } -void -vtysh_user_init (void) +void vtysh_user_init(void) { - userlist = list_new (); - install_element (CONFIG_NODE, &username_nopassword_cmd); - install_element (CONFIG_NODE, &vtysh_banner_motd_file_cmd); + userlist = list_new(); + install_element(CONFIG_NODE, &username_nopassword_cmd); + install_element(CONFIG_NODE, &vtysh_banner_motd_file_cmd); } diff --git a/vtysh/vtysh_user.h b/vtysh/vtysh_user.h index 9d8f4ae62..2b31589f2 100644 --- a/vtysh/vtysh_user.h +++ b/vtysh/vtysh_user.h @@ -21,10 +21,10 @@ #ifndef _VTYSH_USER_H #define _VTYSH_USER_H -int vtysh_auth (void); -void vtysh_user_init (void); +int vtysh_auth(void); +void vtysh_user_init(void); void user_config_write(void); -char *vtysh_get_home (void); +char *vtysh_get_home(void); #endif /* _VTYSH_USER_H */ diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c index 53d58668d..1aa25b41d 100644 --- a/watchfrr/watchfrr.c +++ b/watchfrr/watchfrr.c @@ -129,18 +129,22 @@ static struct global_state { struct restart_info restart; int unresponsive_restart; int loglevel; - struct daemon *special; /* points to zebra when doing phased restart */ + struct daemon *special; /* points to zebra when doing phased restart */ int numdaemons; int numpids; - int numdown; /* # of daemons that are not UP or UNRESPONSIVE */ + int numdown; /* # of daemons that are not UP or UNRESPONSIVE */ } gs = { -.mode = MODE_MONITOR,.phase = PHASE_NONE,.vtydir = VTYDIR,.period = - 1000 * DEFAULT_PERIOD,.timeout = - DEFAULT_TIMEOUT,.restart_timeout = - DEFAULT_RESTART_TIMEOUT,.loglevel = - DEFAULT_LOGLEVEL,.min_restart_interval = - DEFAULT_MIN_RESTART,.max_restart_interval = - DEFAULT_MAX_RESTART,.do_ping = 1,}; + .mode = MODE_MONITOR, + .phase = PHASE_NONE, + .vtydir = VTYDIR, + .period = 1000 * DEFAULT_PERIOD, + .timeout = DEFAULT_TIMEOUT, + .restart_timeout = DEFAULT_RESTART_TIMEOUT, + .loglevel = DEFAULT_LOGLEVEL, + .min_restart_interval = DEFAULT_MIN_RESTART, + .max_restart_interval = DEFAULT_MAX_RESTART, + .do_ping = 1, +}; typedef enum { DAEMON_INIT, @@ -150,15 +154,11 @@ typedef enum { DAEMON_UNRESPONSIVE } daemon_state_t; -#define IS_UP(DMN) \ - (((DMN)->state == DAEMON_UP) || ((DMN)->state == DAEMON_UNRESPONSIVE)) +#define IS_UP(DMN) \ + (((DMN)->state == DAEMON_UP) || ((DMN)->state == DAEMON_UNRESPONSIVE)) static const char *state_str[] = { - "Init", - "Down", - "Connecting", - "Up", - "Unresponsive", + "Init", "Down", "Connecting", "Up", "Unresponsive", }; struct daemon { @@ -192,14 +192,13 @@ static const struct option longopts[] = { {"all-restart", no_argument, NULL, 'a'}, {"always-all-restart", no_argument, NULL, 'A'}, {"unresponsive-restart", no_argument, NULL, 'z'}, - {"min-restart-interval", required_argument, NULL, OPTION_MINRESTART }, - {"max-restart-interval", required_argument, NULL, OPTION_MAXRESTART }, + {"min-restart-interval", required_argument, NULL, OPTION_MINRESTART}, + {"max-restart-interval", required_argument, NULL, OPTION_MAXRESTART}, {"pid-file", required_argument, NULL, 'p'}, {"blank-string", required_argument, NULL, 'b'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'}, - {NULL, 0, NULL, 0} -}; + {NULL, 0, NULL, 0}}; static int try_connect(struct daemon *dmn); static int wakeup_send_echo(struct thread *t_wakeup); @@ -209,7 +208,8 @@ static void phase_check(void); static const char *progname; static void printhelp(FILE *target) { - fprintf(target, "Usage : %s [OPTION...] ...\n\n\ + fprintf(target, + "Usage : %s [OPTION...] ...\n\n\ Watchdog program to monitor status of frr daemons and try to restart\n\ them if they are down or unresponsive. It determines whether a daemon is\n\ up based on whether it can connect to the daemon's vty unix stream socket.\n\ @@ -253,9 +253,13 @@ the -m and -M options allow you to control the minimum delay between\n\ restart commands. The minimum restart delay is recalculated each time\n\ a restart is attempted: if the time since the last restart attempt exceeds\n\ twice the -M value, then the restart delay is set to the -m value.\n\ -Otherwise, the interval is doubled (but capped at the -M value).\n\n", progname, mode_str[0], progname, mode_str[1], progname, mode_str[2], progname, mode_str[3], progname, mode_str[4], progname, mode_str[2], mode_str[3]); +Otherwise, the interval is doubled (but capped at the -M value).\n\n", + progname, mode_str[0], progname, mode_str[1], progname, + mode_str[2], progname, mode_str[3], progname, mode_str[4], + progname, mode_str[2], mode_str[3]); - fprintf(target, "Options:\n\ + fprintf(target, + "Options:\n\ -d, --daemon Run in daemon mode. In this mode, error messages are sent\n\ to syslog instead of stdout.\n\ -S, --statedir Set the vty socket directory (default is %s)\n\ @@ -313,7 +317,10 @@ Otherwise, the interval is doubled (but capped at the -M value).\n\n", progname, it with a space. This is an ugly hack to circumvent problems\n\ passing command-line arguments with embedded spaces.\n\ -v, --version Print program version\n\ --h, --help Display this help and exit\n", VTYDIR, DEFAULT_LOGLEVEL, LOG_EMERG, LOG_DEBUG, LOG_DEBUG, DEFAULT_MIN_RESTART, DEFAULT_MAX_RESTART, DEFAULT_PERIOD, DEFAULT_TIMEOUT, DEFAULT_RESTART_TIMEOUT, DEFAULT_PIDFILE); +-h, --help Display this help and exit\n", + VTYDIR, DEFAULT_LOGLEVEL, LOG_EMERG, LOG_DEBUG, LOG_DEBUG, + DEFAULT_MIN_RESTART, DEFAULT_MAX_RESTART, DEFAULT_PERIOD, + DEFAULT_TIMEOUT, DEFAULT_RESTART_TIMEOUT, DEFAULT_PIDFILE); } static pid_t run_background(char *shell_cmd) @@ -322,22 +329,23 @@ static pid_t run_background(char *shell_cmd) switch (child = fork()) { case -1: - zlog_err("fork failed, cannot run command [%s]: %s", - shell_cmd, safe_strerror(errno)); + zlog_err("fork failed, cannot run command [%s]: %s", shell_cmd, + safe_strerror(errno)); return -1; case 0: /* Child process. */ - /* Use separate process group so child processes can be killed easily. */ + /* Use separate process group so child processes can be killed + * easily. */ if (setpgid(0, 0) < 0) zlog_warn("warning: setpgid(0,0) failed: %s", safe_strerror(errno)); { char shell[] = "sh"; char dashc[] = "-c"; - char *const argv[4] = { shell, dashc, shell_cmd, NULL }; + char *const argv[4] = {shell, dashc, shell_cmd, NULL}; execv("/bin/sh", argv); - zlog_err("execv(/bin/sh -c '%s') failed: %s", - shell_cmd, safe_strerror(errno)); + zlog_err("execv(/bin/sh -c '%s') failed: %s", shell_cmd, + safe_strerror(errno)); _exit(127); } default: @@ -367,10 +375,11 @@ static int restart_kill(struct thread *t_kill) struct timeval delay; time_elapsed(&delay, &restart->time); - zlog_warn("Warning: %s %s child process %d still running after " - "%ld seconds, sending signal %d", - restart->what, restart->name, (int)restart->pid, - (long)delay.tv_sec, (restart->kills ? SIGKILL : SIGTERM)); + zlog_warn( + "Warning: %s %s child process %d still running after " + "%ld seconds, sending signal %d", + restart->what, restart->name, (int)restart->pid, + (long)delay.tv_sec, (restart->kills ? SIGKILL : SIGTERM)); kill(-restart->pid, (restart->kills ? SIGKILL : SIGTERM)); restart->kills++; restart->t_kill = NULL; @@ -423,26 +432,27 @@ static void sigchild(void) gs.numpids--; thread_cancel(restart->t_kill); restart->t_kill = NULL; - /* Update restart time to reflect the time the command completed. */ + /* Update restart time to reflect the time the command + * completed. */ gettimeofday(&restart->time, NULL); } else { - zlog_err - ("waitpid returned status for an unknown child process %d", - (int)child); + zlog_err( + "waitpid returned status for an unknown child process %d", + (int)child); name = "(unknown)"; what = "background"; } if (WIFSTOPPED(status)) - zlog_warn("warning: %s %s process %d is stopped", - what, name, (int)child); + zlog_warn("warning: %s %s process %d is stopped", what, name, + (int)child); else if (WIFSIGNALED(status)) - zlog_warn("%s %s process %d terminated due to signal %d", - what, name, (int)child, WTERMSIG(status)); + zlog_warn("%s %s process %d terminated due to signal %d", what, + name, (int)child, WTERMSIG(status)); else if (WIFEXITED(status)) { if (WEXITSTATUS(status) != 0) - zlog_warn - ("%s %s process %d exited with non-zero status %d", - what, name, (int)child, WEXITSTATUS(status)); + zlog_warn( + "%s %s process %d exited with non-zero status %d", + what, name, (int)child, WEXITSTATUS(status)); else zlog_debug("%s %s process %d exited normally", what, name, (int)child); @@ -452,9 +462,8 @@ static void sigchild(void) phase_check(); } -static int -run_job(struct restart_info *restart, const char *cmdtype, const char *command, - int force, int update_interval) +static int run_job(struct restart_info *restart, const char *cmdtype, + const char *command, int force, int update_interval) { struct timeval delay; @@ -463,22 +472,24 @@ run_job(struct restart_info *restart, const char *cmdtype, const char *command, if (restart->pid) { if (gs.loglevel > LOG_DEBUG + 1) - zlog_debug - ("cannot %s %s, previous pid %d still running", - cmdtype, restart->name, (int)restart->pid); + zlog_debug( + "cannot %s %s, previous pid %d still running", + cmdtype, restart->name, (int)restart->pid); return -1; } - /* Note: time_elapsed test must come before the force test, since we need + /* Note: time_elapsed test must come before the force test, since we + need to make sure that delay is initialized for use below in updating the restart interval. */ if ((time_elapsed(&delay, &restart->time)->tv_sec < restart->interval) && !force) { if (gs.loglevel > LOG_DEBUG + 1) - zlog_debug("postponing %s %s: " - "elapsed time %ld < retry interval %ld", - cmdtype, restart->name, (long)delay.tv_sec, - restart->interval); + zlog_debug( + "postponing %s %s: " + "elapsed time %ld < retry interval %ld", + cmdtype, restart->name, (long)delay.tv_sec, + restart->interval); return -1; } @@ -489,8 +500,8 @@ run_job(struct restart_info *restart, const char *cmdtype, const char *command, snprintf(cmd, sizeof(cmd), command, restart->name); if ((restart->pid = run_background(cmd)) > 0) { restart->t_kill = NULL; - thread_add_timer(master, restart_kill, restart, gs.restart_timeout, - &restart->t_kill); + thread_add_timer(master, restart_kill, restart, + gs.restart_timeout, &restart->t_kill); restart->what = cmdtype; gs.numpids++; } else @@ -510,32 +521,33 @@ run_job(struct restart_info *restart, const char *cmdtype, const char *command, return restart->pid; } -#define SET_READ_HANDLER(DMN) \ - do { \ - (DMN)->t_read = NULL; \ - thread_add_read (master, handle_read, (DMN), (DMN)->fd, &(DMN)->t_read); \ - } while (0); - -#define SET_WAKEUP_DOWN(DMN) \ - do { \ - (DMN)->t_wakeup = NULL; \ - thread_add_timer_msec (master, wakeup_down, (DMN), FUZZY(gs.period), \ - &(DMN)->t_wakeup); \ - } while (0); - -#define SET_WAKEUP_UNRESPONSIVE(DMN) \ - do { \ - (DMN)->t_wakeup = NULL; \ - thread_add_timer_msec (master, wakeup_unresponsive, (DMN), \ - FUZZY(gs.period), &(DMN)->t_wakeup); \ - } while (0); - -#define SET_WAKEUP_ECHO(DMN) \ - do { \ - (DMN)->t_wakeup = NULL; \ - thread_add_timer_msec (master, wakeup_send_echo, (DMN), \ - FUZZY(gs.period), &(DMN)->t_wakeup); \ - } while (0); +#define SET_READ_HANDLER(DMN) \ + do { \ + (DMN)->t_read = NULL; \ + thread_add_read(master, handle_read, (DMN), (DMN)->fd, \ + &(DMN)->t_read); \ + } while (0); + +#define SET_WAKEUP_DOWN(DMN) \ + do { \ + (DMN)->t_wakeup = NULL; \ + thread_add_timer_msec(master, wakeup_down, (DMN), \ + FUZZY(gs.period), &(DMN)->t_wakeup); \ + } while (0); + +#define SET_WAKEUP_UNRESPONSIVE(DMN) \ + do { \ + (DMN)->t_wakeup = NULL; \ + thread_add_timer_msec(master, wakeup_unresponsive, (DMN), \ + FUZZY(gs.period), &(DMN)->t_wakeup); \ + } while (0); + +#define SET_WAKEUP_ECHO(DMN) \ + do { \ + (DMN)->t_wakeup = NULL; \ + thread_add_timer_msec(master, wakeup_send_echo, (DMN), \ + FUZZY(gs.period), &(DMN)->t_wakeup); \ + } while (0); static int wakeup_down(struct thread *t_wakeup) { @@ -626,8 +638,8 @@ static int handle_read(struct thread *t_read) char why[100 + sizeof(buf)]; snprintf(why, sizeof(why), "read returned bad echo response of %d bytes " - "(expecting %u): %.*s", (int)rc, (u_int) sizeof(resp), - (int)rc, buf); + "(expecting %u): %.*s", + (int)rc, (u_int)sizeof(resp), (int)rc, buf); daemon_down(dmn, why); return 0; } @@ -637,15 +649,17 @@ static int handle_read(struct thread *t_read) if (dmn->state == DAEMON_UNRESPONSIVE) { if (delay.tv_sec < gs.timeout) { dmn->state = DAEMON_UP; - zlog_warn - ("%s state -> up : echo response received after %ld.%06ld " - "seconds", dmn->name, (long)delay.tv_sec, - (long)delay.tv_usec); + zlog_warn( + "%s state -> up : echo response received after %ld.%06ld " + "seconds", + dmn->name, (long)delay.tv_sec, + (long)delay.tv_usec); } else - zlog_warn - ("%s: slow echo response finally received after %ld.%06ld " - "seconds", dmn->name, (long)delay.tv_sec, - (long)delay.tv_usec); + zlog_warn( + "%s: slow echo response finally received after %ld.%06ld " + "seconds", + dmn->name, (long)delay.tv_sec, + (long)delay.tv_usec); } else if (gs.loglevel > LOG_DEBUG + 1) zlog_debug("%s: echo response received after %ld.%06ld seconds", dmn->name, (long)delay.tv_sec, (long)delay.tv_usec); @@ -670,8 +684,8 @@ static void daemon_send_ready(void) fp = fopen(DAEMON_VTY_DIR "/watchfrr.started", "w"); fclose(fp); - zlog_notice - ("Watchfrr: Notifying Systemd we are up and running"); + zlog_notice( + "Watchfrr: Notifying Systemd we are up and running"); systemd_send_started(master, 0); sent = 1; } @@ -706,9 +720,10 @@ static int check_connect(struct thread *t_write) } if ((reslen == sizeof(sockerr)) && sockerr) { char why[100]; - snprintf(why, sizeof(why), - "getsockopt reports that connection attempt failed: %s", - safe_strerror(sockerr)); + snprintf( + why, sizeof(why), + "getsockopt reports that connection attempt failed: %s", + safe_strerror(sockerr)); daemon_down(dmn, why); return 0; } @@ -742,13 +757,13 @@ static int try_connect(struct daemon *dmn) memset(&addr, 0, sizeof(struct sockaddr_un)); addr.sun_family = AF_UNIX; - snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s.vty", - gs.vtydir, dmn->name); + snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s.vty", gs.vtydir, + dmn->name); #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN len = addr.sun_len = SUN_LEN(&addr); #else len = sizeof(addr.sun_family) + strlen(addr.sun_path); -#endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */ +#endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */ /* Quick check to see if we might succeed before we go to the trouble of creating a socket. */ @@ -761,14 +776,14 @@ static int try_connect(struct daemon *dmn) } if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { - zlog_err("%s(%s): cannot make socket: %s", - __func__, addr.sun_path, safe_strerror(errno)); + zlog_err("%s(%s): cannot make socket: %s", __func__, + addr.sun_path, safe_strerror(errno)); return -1; } if (set_nonblocking(sock) < 0 || set_cloexec(sock) < 0) { - zlog_err("%s(%s): set_nonblocking/cloexec(%d) failed", - __func__, addr.sun_path, sock); + zlog_err("%s(%s): set_nonblocking/cloexec(%d) failed", __func__, + addr.sun_path, sock); close(sock); return -1; } @@ -788,9 +803,10 @@ static int try_connect(struct daemon *dmn) dmn->fd = sock; dmn->t_write = NULL; thread_add_write(master, check_connect, dmn, dmn->fd, - &dmn->t_write);dmn->t_wakeup = NULL; - thread_add_timer(master, wakeup_connect_hanging, dmn, gs.timeout, - &dmn->t_wakeup); + &dmn->t_write); + dmn->t_wakeup = NULL; + thread_add_timer(master, wakeup_connect_hanging, dmn, + gs.timeout, &dmn->t_wakeup); SET_READ_HANDLER(dmn); return 0; } @@ -828,11 +844,11 @@ static void phase_check(void) case PHASE_STOPS_PENDING: if (gs.numpids) break; - zlog_info - ("Phased restart: all routing daemon stop jobs have completed."); + zlog_info( + "Phased restart: all routing daemon stop jobs have completed."); set_phase(PHASE_WAITING_DOWN); - /*FALLTHRU*/ + /*FALLTHRU*/ case PHASE_WAITING_DOWN: if (gs.numdown + IS_UP(gs.special) < gs.numdaemons) break; @@ -841,7 +857,7 @@ static void phase_check(void) 1); set_phase(PHASE_ZEBRA_RESTART_PENDING); - /*FALLTHRU*/ + /*FALLTHRU*/ case PHASE_ZEBRA_RESTART_PENDING: if (gs.special->restart.pid) break; @@ -849,7 +865,7 @@ static void phase_check(void) gs.special->name); set_phase(PHASE_WAITING_ZEBRA_UP); - /*FALLTHRU*/ + /*FALLTHRU*/ case PHASE_WAITING_ZEBRA_UP: if (!IS_UP(gs.special)) break; @@ -887,35 +903,36 @@ static void try_restart(struct daemon *dmn) run_job(&dmn->restart, "restart", gs.restart_command, 0, 1); else - zlog_debug - ("%s: postponing restart attempt because master %s daemon " - "not up [%s], or phased restart in progress", - dmn->name, gs.special->name, - state_str[gs.special->state]); + zlog_debug( + "%s: postponing restart attempt because master %s daemon " + "not up [%s], or phased restart in progress", + dmn->name, gs.special->name, + state_str[gs.special->state]); break; } - /*FALLTHRU*/ + /*FALLTHRU*/ case MODE_PHASED_ALL_RESTART: if ((gs.phase != PHASE_NONE) || gs.numpids) { if (gs.loglevel > LOG_DEBUG + 1) - zlog_debug - ("postponing phased global restart: restart already in " - "progress [%s], or outstanding child processes [%d]", - phase_str[gs.phase], gs.numpids); + zlog_debug( + "postponing phased global restart: restart already in " + "progress [%s], or outstanding child processes [%d]", + phase_str[gs.phase], gs.numpids); break; } /* Is it too soon for a restart? */ { struct timeval delay; - if (time_elapsed(&delay, &gs.special->restart.time)-> - tv_sec < gs.special->restart.interval) { + if (time_elapsed(&delay, &gs.special->restart.time) + ->tv_sec + < gs.special->restart.interval) { if (gs.loglevel > LOG_DEBUG + 1) - zlog_debug - ("postponing phased global restart: " - "elapsed time %ld < retry interval %ld", - (long)delay.tv_sec, - gs.special->restart.interval); + zlog_debug( + "postponing phased global restart: " + "elapsed time %ld < retry interval %ld", + (long)delay.tv_sec, + gs.special->restart.interval); break; } } @@ -933,9 +950,10 @@ static int wakeup_unresponsive(struct thread *t_wakeup) dmn->t_wakeup = NULL; if (dmn->state != DAEMON_UNRESPONSIVE) - zlog_err("%s: no longer unresponsive (now %s), " - "wakeup should have been cancelled!", - dmn->name, state_str[dmn->state]); + zlog_err( + "%s: no longer unresponsive (now %s), " + "wakeup should have been cancelled!", + dmn->name, state_str[dmn->state]); else { SET_WAKEUP_UNRESPONSIVE(dmn); try_restart(dmn); @@ -949,8 +967,10 @@ static int wakeup_no_answer(struct thread *t_wakeup) dmn->t_wakeup = NULL; dmn->state = DAEMON_UNRESPONSIVE; - zlog_err("%s state -> unresponsive : no response yet to ping " - "sent %ld seconds ago", dmn->name, gs.timeout); + zlog_err( + "%s state -> unresponsive : no response yet to ping " + "sent %ld seconds ago", + dmn->name, gs.timeout); if (gs.unresponsive_restart) { SET_WAKEUP_UNRESPONSIVE(dmn); try_restart(dmn); @@ -965,12 +985,12 @@ static int wakeup_send_echo(struct thread *t_wakeup) struct daemon *dmn = THREAD_ARG(t_wakeup); dmn->t_wakeup = NULL; - if (((rc = write(dmn->fd, echocmd, sizeof(echocmd))) < 0) || - ((size_t) rc != sizeof(echocmd))) { + if (((rc = write(dmn->fd, echocmd, sizeof(echocmd))) < 0) + || ((size_t)rc != sizeof(echocmd))) { char why[100 + sizeof(echocmd)]; snprintf(why, sizeof(why), "write '%s' returned %d instead of %u", echocmd, - (int)rc, (u_int) sizeof(echocmd)); + (int)rc, (u_int)sizeof(echocmd)); daemon_down(dmn, why); } else { gettimeofday(&dmn->echo_sent, NULL); @@ -993,7 +1013,7 @@ static int valid_command(const char *cmd) char *p; return ((p = strchr(cmd, '%')) != NULL) && (*(p + 1) == 's') - && !strchr(p + 1, '%'); + && !strchr(p + 1, '%'); } /* This is an ugly hack to circumvent problems with passing command-line @@ -1038,17 +1058,16 @@ static struct quagga_signal_t watchfrr_signals[] = { }; FRR_DAEMON_INFO(watchfrr, WATCHFRR, - .flags = FRR_NO_PRIVSEP | FRR_NO_TCPVTY | FRR_LIMITED_CLI - | FRR_NO_CFG_PID_DRY | FRR_NO_ZCLIENT, + .flags = FRR_NO_PRIVSEP | FRR_NO_TCPVTY | FRR_LIMITED_CLI + | FRR_NO_CFG_PID_DRY | FRR_NO_ZCLIENT, - .printhelp = printhelp, - .copyright = "Copyright 2004 Andrew J. Schorr", + .printhelp = printhelp, + .copyright = "Copyright 2004 Andrew J. Schorr", - .signals = watchfrr_signals, - .n_signals = array_size(watchfrr_signals), + .signals = watchfrr_signals, + .n_signals = array_size(watchfrr_signals), - .privs = &watchfrr_privs, -) + .privs = &watchfrr_privs, ) int main(int argc, char **argv) { @@ -1100,68 +1119,59 @@ int main(int argc, char **argv) } gs.stop_command = optarg; break; - case 'l': - { - char garbage[3]; - if ((sscanf - (optarg, "%d%1s", &gs.loglevel, - garbage) != 1) - || (gs.loglevel < LOG_EMERG)) { - fprintf(stderr, - "Invalid loglevel argument: %s\n", - optarg); - frr_help_exit(1); - } + case 'l': { + char garbage[3]; + if ((sscanf(optarg, "%d%1s", &gs.loglevel, garbage) + != 1) + || (gs.loglevel < LOG_EMERG)) { + fprintf(stderr, + "Invalid loglevel argument: %s\n", + optarg); + frr_help_exit(1); } - break; - case OPTION_MINRESTART: - { - char garbage[3]; - if ((sscanf(optarg, "%ld%1s", - &gs.min_restart_interval, - garbage) != 1) - || (gs.min_restart_interval < 0)) { - fprintf(stderr, - "Invalid min_restart_interval argument: %s\n", - optarg); - frr_help_exit(1); - } + } break; + case OPTION_MINRESTART: { + char garbage[3]; + if ((sscanf(optarg, "%ld%1s", &gs.min_restart_interval, + garbage) + != 1) + || (gs.min_restart_interval < 0)) { + fprintf(stderr, + "Invalid min_restart_interval argument: %s\n", + optarg); + frr_help_exit(1); } - break; - case OPTION_MAXRESTART: - { - char garbage[3]; - if ((sscanf(optarg, "%ld%1s", - &gs.max_restart_interval, - garbage) != 1) - || (gs.max_restart_interval < 0)) { - fprintf(stderr, - "Invalid max_restart_interval argument: %s\n", - optarg); - frr_help_exit(1); - } + } break; + case OPTION_MAXRESTART: { + char garbage[3]; + if ((sscanf(optarg, "%ld%1s", &gs.max_restart_interval, + garbage) + != 1) + || (gs.max_restart_interval < 0)) { + fprintf(stderr, + "Invalid max_restart_interval argument: %s\n", + optarg); + frr_help_exit(1); } - break; - case 'i': - { - char garbage[3]; - int period; - if ((sscanf(optarg, "%d%1s", &period, garbage) - != 1) || (gs.period < 1)) { - fprintf(stderr, - "Invalid interval argument: %s\n", - optarg); - frr_help_exit(1); - } - gs.period = 1000 * period; + } break; + case 'i': { + char garbage[3]; + int period; + if ((sscanf(optarg, "%d%1s", &period, garbage) != 1) + || (gs.period < 1)) { + fprintf(stderr, + "Invalid interval argument: %s\n", + optarg); + frr_help_exit(1); } - break; + gs.period = 1000 * period; + } break; case 'p': pidfile = optarg; break; case 'r': - if ((gs.mode == MODE_GLOBAL_RESTART) || - (gs.mode == MODE_SEPARATE_RESTART)) { + if ((gs.mode == MODE_GLOBAL_RESTART) + || (gs.mode == MODE_SEPARATE_RESTART)) { fputs("Ambiguous operating mode selected.\n", stderr); frr_help_exit(1); @@ -1203,33 +1213,29 @@ int main(int argc, char **argv) case 'S': gs.vtydir = optarg; break; - case 't': - { - char garbage[3]; - if ((sscanf - (optarg, "%ld%1s", &gs.timeout, - garbage) != 1) || (gs.timeout < 1)) { - fprintf(stderr, - "Invalid timeout argument: %s\n", - optarg); - frr_help_exit(1); - } + case 't': { + char garbage[3]; + if ((sscanf(optarg, "%ld%1s", &gs.timeout, garbage) + != 1) + || (gs.timeout < 1)) { + fprintf(stderr, + "Invalid timeout argument: %s\n", + optarg); + frr_help_exit(1); } - break; - case 'T': - { - char garbage[3]; - if ((sscanf - (optarg, "%ld%1s", &gs.restart_timeout, - garbage) != 1) - || (gs.restart_timeout < 1)) { - fprintf(stderr, - "Invalid restart timeout argument: %s\n", - optarg); - frr_help_exit(1); - } + } break; + case 'T': { + char garbage[3]; + if ((sscanf(optarg, "%ld%1s", &gs.restart_timeout, + garbage) + != 1) + || (gs.restart_timeout < 1)) { + fprintf(stderr, + "Invalid restart timeout argument: %s\n", + optarg); + frr_help_exit(1); } - break; + } break; case 'z': gs.unresponsive_restart = 1; break; @@ -1255,7 +1261,8 @@ int main(int argc, char **argv) break; case MODE_GLOBAL_RESTART: case MODE_SEPARATE_RESTART: - if (!gs.restart_command || gs.start_command || gs.stop_command) { + if (!gs.restart_command || gs.start_command + || gs.stop_command) { fprintf(stderr, "No start/kill commands needed in [%s] mode.\n", mode_str[gs.mode]); @@ -1277,13 +1284,13 @@ int main(int argc, char **argv) if (blankstr) { if (gs.restart_command) gs.restart_command = - translate_blanks(gs.restart_command, blankstr); + translate_blanks(gs.restart_command, blankstr); if (gs.start_command) gs.start_command = - translate_blanks(gs.start_command, blankstr); + translate_blanks(gs.start_command, blankstr); if (gs.stop_command) gs.stop_command = - translate_blanks(gs.stop_command, blankstr); + translate_blanks(gs.stop_command, blankstr); } gs.restart.interval = gs.min_restart_interval; @@ -1293,10 +1300,10 @@ int main(int argc, char **argv) zlog_set_level(ZLOG_DEST_MONITOR, ZLOG_DISABLED); if (watchfrr_di.daemon_mode) { zlog_set_level(ZLOG_DEST_SYSLOG, MIN(gs.loglevel, LOG_DEBUG)); - if (daemon (0, 0) < 0) { + if (daemon(0, 0) < 0) { fprintf(stderr, "Watchfrr daemon failed: %s", - strerror(errno)); - exit (1); + strerror(errno)); + exit(1); } } else zlog_set_level(ZLOG_DEST_STDOUT, MIN(gs.loglevel, LOG_DEBUG)); @@ -1314,7 +1321,7 @@ int main(int argc, char **argv) if (!(dmn = (struct daemon *)calloc(1, sizeof(*dmn)))) { fprintf(stderr, "calloc(1,%u) failed: %s\n", - (u_int) sizeof(*dmn), + (u_int)sizeof(*dmn), safe_strerror(errno)); return 1; } @@ -1324,7 +1331,8 @@ int main(int argc, char **argv) gs.numdown++; dmn->fd = -1; dmn->t_wakeup = NULL; - thread_add_timer_msec(master, wakeup_init, dmn, 100 + (random() % 900), + thread_add_timer_msec(master, wakeup_init, dmn, + 100 + (random() % 900), &dmn->t_wakeup); dmn->restart.interval = gs.min_restart_interval; if (tail) @@ -1333,9 +1341,9 @@ int main(int argc, char **argv) gs.daemons = dmn; tail = dmn; - if (((gs.mode == MODE_PHASED_ZEBRA_RESTART) || - (gs.mode == MODE_PHASED_ALL_RESTART)) && - !strcmp(dmn->name, special)) + if (((gs.mode == MODE_PHASED_ZEBRA_RESTART) + || (gs.mode == MODE_PHASED_ALL_RESTART)) + && !strcmp(dmn->name, special)) gs.special = dmn; } } @@ -1343,8 +1351,9 @@ int main(int argc, char **argv) fputs("Must specify one or more daemons to monitor.\n", stderr); frr_help_exit(1); } - if (((gs.mode == MODE_PHASED_ZEBRA_RESTART) || - (gs.mode == MODE_PHASED_ALL_RESTART)) && !gs.special) { + if (((gs.mode == MODE_PHASED_ZEBRA_RESTART) + || (gs.mode == MODE_PHASED_ALL_RESTART)) + && !gs.special) { fprintf(stderr, "In mode [%s], but cannot find master daemon %s\n", mode_str[gs.mode], special); @@ -1372,9 +1381,8 @@ int main(int argc, char **argv) strcpy(p, dmn->name); p += strlen(p); } - zlog_notice("%s %s watching [%s], mode [%s]", - progname, FRR_VERSION, buf, - mode_str[gs.mode]); + zlog_notice("%s %s watching [%s], mode [%s]", progname, + FRR_VERSION, buf, mode_str[gs.mode]); } } diff --git a/watchfrr/watchfrr.h b/watchfrr/watchfrr.h index e7aba643d..53b92bd83 100644 --- a/watchfrr/watchfrr.h +++ b/watchfrr/watchfrr.h @@ -26,4 +26,4 @@ extern void watchfrr_vty_init(void); extern pid_t integrated_write_pid; extern void integrated_write_sigchld(int status); -#endif /* FRR_WATCHFRR_H */ +#endif /* FRR_WATCHFRR_H */ diff --git a/watchfrr/watchfrr_vty.c b/watchfrr/watchfrr_vty.c index 276e186c4..9cfdab44a 100644 --- a/watchfrr/watchfrr_vty.c +++ b/watchfrr/watchfrr_vty.c @@ -41,7 +41,7 @@ DEFUN(config_write_integrated, sigset_t oldmask, sigmask; if (integrated_write_pid != -1) { - vty_out (vty,"%% configuration write already in progress.\n"); + vty_out(vty, "%% configuration write already in progress.\n"); return CMD_WARNING; } @@ -59,19 +59,23 @@ DEFUN(config_write_integrated, child = fork(); if (child == -1) { - vty_out (vty, "%% configuration write fork() failed: %s.\n", + vty_out(vty, "%% configuration write fork() failed: %s.\n", safe_strerror(errno)); sigprocmask(SIG_SETMASK, &oldmask, NULL); return CMD_WARNING; } if (child != 0) { - /* note: the VTY won't write a command return value to vtysh; the - * session temporarily enters an intentional "hang" state. This is + /* note: the VTY won't write a command return value to vtysh; + * the + * session temporarily enters an intentional "hang" state. This + * is * to make sure latency in vtysh doing the config write (several - * seconds is not rare to see) does not interfere with watchfrr's + * seconds is not rare to see) does not interfere with + * watchfrr's * supervisor job. * - * The fd is duplicated here so we don't need to hold a vty pointer + * The fd is duplicated here so we don't need to hold a vty + * pointer * (which could become invalid in the meantime). */ integrated_write_pid = child; @@ -91,15 +95,15 @@ DEFUN(config_write_integrated, /* unbuffered write; we just messed with stdout... */ char msg[512]; - snprintf(msg, sizeof(msg), "error executing %s: %s\n", - VTYSH_BIN_PATH, safe_strerror(errno)); + snprintf(msg, sizeof(msg), "error executing %s: %s\n", VTYSH_BIN_PATH, + safe_strerror(errno)); write(1, msg, strlen(msg)); exit(1); } void integrated_write_sigchld(int status) { - uint8_t reply[4] = { 0, 0, 0, CMD_WARNING }; + uint8_t reply[4] = {0, 0, 0, CMD_WARNING}; if (WIFEXITED(status)) { zlog_info("configuration write completed with exit code %d", diff --git a/zebra/client_main.c b/zebra/client_main.c index 2903b8425..17130c602 100644 --- a/zebra/client_main.c +++ b/zebra/client_main.c @@ -38,194 +38,176 @@ struct zclient *zclient = NULL; int sock; /* IPv4 route add and delete test. */ -void -zebra_test_ipv4 (int command, int type, char *prefix, char *gateway, - u_char distance) +void zebra_test_ipv4(int command, int type, char *prefix, char *gateway, + u_char distance) { - struct zapi_ipv4 api; - struct prefix_ipv4 p; - struct in_addr gate; - struct in_addr *gpnt; - - str2prefix_ipv4 (prefix, &p); - if (!inet_aton (gateway, &gate)) - { - printf("Gateway specified: %s is illegal\n", gateway); - return; - } - - gpnt = &gate; - - api.vrf_id = VRF_DEFAULT; - api.type = type; - api.flags = 0; - - api.message = 0; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 1; - api.nexthop = &gpnt; - api.ifindex_num = 0; - if (distance) - { - SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = distance; - } - - - switch (command) - { - case ZEBRA_IPV4_ROUTE_ADD: - zapi_ipv4_add (zclient, &p, &api); - break; - case ZEBRA_IPV4_ROUTE_DELETE: - zapi_ipv4_delete (zclient, &p, &api); - break; - } + struct zapi_ipv4 api; + struct prefix_ipv4 p; + struct in_addr gate; + struct in_addr *gpnt; + + str2prefix_ipv4(prefix, &p); + if (!inet_aton(gateway, &gate)) { + printf("Gateway specified: %s is illegal\n", gateway); + return; + } + + gpnt = &gate; + + api.vrf_id = VRF_DEFAULT; + api.type = type; + api.flags = 0; + + api.message = 0; + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + api.nexthop_num = 1; + api.nexthop = &gpnt; + api.ifindex_num = 0; + if (distance) { + SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = distance; + } + + + switch (command) { + case ZEBRA_IPV4_ROUTE_ADD: + zapi_ipv4_add(zclient, &p, &api); + break; + case ZEBRA_IPV4_ROUTE_DELETE: + zapi_ipv4_delete(zclient, &p, &api); + break; + } } /* IPv6 route add and delete test. */ -void -zebra_test_v6 (int sock) +void zebra_test_v6(int sock) { - struct prefix_ipv6 p; - struct in6_addr nexthop; + struct prefix_ipv6 p; + struct in6_addr nexthop; - str2prefix_ipv6 ("3ffe:506::2/128", &p); - inet_pton (AF_INET6, "::1", &nexthop); + str2prefix_ipv6("3ffe:506::2/128", &p); + inet_pton(AF_INET6, "::1", &nexthop); - /* zebra_ipv6_add (sock, ZEBRA_ROUTE_STATIC, 0, &p, &nexthop, 1); */ + /* zebra_ipv6_add (sock, ZEBRA_ROUTE_STATIC, 0, &p, &nexthop, 1); */ - sleep (5); - /* zebra_ipv6_delete (sock, ZEBRA_ROUTE_STATIC, 0, &p, &nexthop, 1); */ + sleep(5); + /* zebra_ipv6_delete (sock, ZEBRA_ROUTE_STATIC, 0, &p, &nexthop, 1); */ } /* Print out usage and exit. */ -void -usage_exit () +void usage_exit() { - fprintf (stderr, "Usage: client filename\n"); - exit (1); + fprintf(stderr, "Usage: client filename\n"); + exit(1); } -struct zebra_info -{ - char *str; - int type; -} zebra_type[] = -{ - { "static", ZEBRA_ROUTE_STATIC }, - { "rip", ZEBRA_ROUTE_RIP }, - { "ripng", ZEBRA_ROUTE_RIPNG }, - { "ospf", ZEBRA_ROUTE_OSPF }, - { "ospf6", ZEBRA_ROUTE_OSPF6 }, - { "bgp", ZEBRA_ROUTE_BGP }, - { "nhrp", ZEBRA_ROUTE_NHRP }, - { "pim", ZEBRA_ROUTE_PIM }, - { NULL, 0 } -}; +struct zebra_info { + char *str; + int type; +} zebra_type[] = {{"static", ZEBRA_ROUTE_STATIC}, + {"rip", ZEBRA_ROUTE_RIP}, + {"ripng", ZEBRA_ROUTE_RIPNG}, + {"ospf", ZEBRA_ROUTE_OSPF}, + {"ospf6", ZEBRA_ROUTE_OSPF6}, + {"bgp", ZEBRA_ROUTE_BGP}, + {"nhrp", ZEBRA_ROUTE_NHRP}, + {"pim", ZEBRA_ROUTE_PIM}, + {NULL, 0}}; /* Zebra route simulator. */ -void -zebra_sim (FILE *fp) +void zebra_sim(FILE *fp) { - char buf[BUFSIZ]; - char distance_str[BUFSIZ]; - u_char distance; - - while (fgets (buf, sizeof buf, fp)) - { - int i; - int ret; - int type; - char str[BUFSIZ], command[BUFSIZ], prefix[BUFSIZ], gateway[BUFSIZ]; - - distance = 0; - - if (*buf == '#') - continue; - - type = ZEBRA_ROUTE_STATIC; - - ret = sscanf (buf, "%s %s %s %s %s\n", command, str, prefix, gateway, - distance_str); - - if (ret == 5) - { - distance = atoi (distance_str); - } - else - { - ret = sscanf (buf, "%s %s %s %s\n", command, str, prefix, gateway); - - if (ret != 4) - continue; + char buf[BUFSIZ]; + char distance_str[BUFSIZ]; + u_char distance; + + while (fgets(buf, sizeof buf, fp)) { + int i; + int ret; + int type; + char str[BUFSIZ], command[BUFSIZ], prefix[BUFSIZ], + gateway[BUFSIZ]; + + distance = 0; + + if (*buf == '#') + continue; + + type = ZEBRA_ROUTE_STATIC; + + ret = sscanf(buf, "%s %s %s %s %s\n", command, str, prefix, + gateway, distance_str); + + if (ret == 5) { + distance = atoi(distance_str); + } else { + ret = sscanf(buf, "%s %s %s %s\n", command, str, prefix, + gateway); + + if (ret != 4) + continue; + } + + for (i = 0; i < 10; i++) { + if (!zebra_type[i].str) + break; + if (strcmp(zebra_type[i].str, str) == 0) { + type = zebra_type[i].type; + break; + } + } + + if (strcmp(command, "add") == 0) { + zebra_test_ipv4(ZEBRA_IPV4_ROUTE_ADD, type, prefix, + gateway, distance); + printf("%s", buf); + continue; + } + + if (strcmp(command, "del") == 0) { + zebra_test_ipv4(ZEBRA_IPV4_ROUTE_DELETE, type, prefix, + gateway, distance); + printf("%s", buf); + continue; + } } - - for (i = 0; i < 10; i++) - { - if (!zebra_type[i].str) - break; - if (strcmp (zebra_type[i].str, str) == 0) - { - type = zebra_type[i].type; - break; - } - } - - if (strcmp (command, "add") == 0) - { - zebra_test_ipv4 (ZEBRA_IPV4_ROUTE_ADD, type, prefix, gateway, - distance); - printf ("%s", buf); - continue; - } - - if (strcmp (command, "del") == 0) - { - zebra_test_ipv4 (ZEBRA_IPV4_ROUTE_DELETE, type, prefix, gateway, - distance); - printf ("%s", buf); - continue; - } - } } /* Test zebra client main routine. */ -int -main (int argc, char **argv) +int main(int argc, char **argv) { - struct thread_master *master; - FILE *fp; + struct thread_master *master; + FILE *fp; - if (argc == 1) - usage_exit (); + if (argc == 1) + usage_exit(); - master = thread_master_create(NULL); - /* Establish connection to zebra. */ - zclient = zclient_new(master); - zclient->enable = 1; + master = thread_master_create(NULL); + /* Establish connection to zebra. */ + zclient = zclient_new(master); + zclient->enable = 1; #ifdef HAVE_TCP_ZEBRA - zclient->sock = zclient_socket (); + zclient->sock = zclient_socket(); #else - zclient->sock = zclient_socket_un (ZEBRA_SERV_PATH); + zclient->sock = zclient_socket_un(ZEBRA_SERV_PATH); #endif /* HAVE_TCP_ZEBRA */ - /* Open simulation file. */ - fp = fopen (argv[1], "r"); - if (fp == NULL) - { - fprintf (stderr,"%% Can't open configuration file %s due to '%s'\n", - argv[1], safe_strerror(errno)); - exit (1); - } + /* Open simulation file. */ + fp = fopen(argv[1], "r"); + if (fp == NULL) { + fprintf(stderr, + "%% Can't open configuration file %s due to '%s'\n", + argv[1], safe_strerror(errno)); + exit(1); + } - /* Do main work. */ - zebra_sim (fp); + /* Do main work. */ + zebra_sim(fp); - sleep (100); + sleep(100); - fclose (fp); - close (sock); + fclose(fp); + close(sock); - return 0; + return 0; } diff --git a/zebra/connected.c b/zebra/connected.c index 4d8fe9f6d..80f9ebe5e 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -42,533 +42,528 @@ #include "zebra/debug.h" /* communicate the withdrawal of a connected address */ -static void -connected_withdraw (struct connected *ifc) +static void connected_withdraw(struct connected *ifc) { - if (! ifc) - return; + if (!ifc) + return; - /* Update interface address information to protocol daemon. */ - if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) - { - zebra_interface_address_delete_update (ifc->ifp, ifc); + /* Update interface address information to protocol daemon. */ + if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) { + zebra_interface_address_delete_update(ifc->ifp, ifc); - if (ifc->address->family == AF_INET) - if_subnet_delete (ifc->ifp, ifc); + if (ifc->address->family == AF_INET) + if_subnet_delete(ifc->ifp, ifc); - if (ifc->address->family == AF_INET) - connected_down_ipv4 (ifc->ifp, ifc); - else - connected_down_ipv6 (ifc->ifp, ifc); + if (ifc->address->family == AF_INET) + connected_down_ipv4(ifc->ifp, ifc); + else + connected_down_ipv6(ifc->ifp, ifc); - UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL); - } + UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL); + } - /* The address is not in the kernel anymore, so clear the flag */ - UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + /* The address is not in the kernel anymore, so clear the flag */ + UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); - if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) - { - listnode_delete (ifc->ifp->connected, ifc); - connected_free (ifc); - } + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) { + listnode_delete(ifc->ifp->connected, ifc); + connected_free(ifc); + } } -static void -connected_announce (struct interface *ifp, struct connected *ifc) +static void connected_announce(struct interface *ifp, struct connected *ifc) { - if (!ifc) - return; - - if (!if_is_loopback(ifp) && ifc->address->family == AF_INET) - { - if (ifc->address->prefixlen == 32) - SET_FLAG (ifc->flags, ZEBRA_IFA_UNNUMBERED); - else - UNSET_FLAG (ifc->flags, ZEBRA_IFA_UNNUMBERED); - } - - listnode_add (ifp->connected, ifc); - - /* Update interface address information to protocol daemon. */ - if (ifc->address->family == AF_INET) - if_subnet_add (ifp, ifc); - - zebra_interface_address_add_update (ifp, ifc); - - if (if_is_operative(ifp)) - { - if (ifc->address->family == AF_INET) - connected_up_ipv4 (ifp, ifc); - else - connected_up_ipv6 (ifp, ifc); - } + if (!ifc) + return; + + if (!if_is_loopback(ifp) && ifc->address->family == AF_INET) { + if (ifc->address->prefixlen == 32) + SET_FLAG(ifc->flags, ZEBRA_IFA_UNNUMBERED); + else + UNSET_FLAG(ifc->flags, ZEBRA_IFA_UNNUMBERED); + } + + listnode_add(ifp->connected, ifc); + + /* Update interface address information to protocol daemon. */ + if (ifc->address->family == AF_INET) + if_subnet_add(ifp, ifc); + + zebra_interface_address_add_update(ifp, ifc); + + if (if_is_operative(ifp)) { + if (ifc->address->family == AF_INET) + connected_up_ipv4(ifp, ifc); + else + connected_up_ipv6(ifp, ifc); + } } /* If same interface address is already exist... */ -struct connected * -connected_check (struct interface *ifp, struct prefix *p) +struct connected *connected_check(struct interface *ifp, struct prefix *p) { - struct connected *ifc; - struct listnode *node; + struct connected *ifc; + struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc)) - if (prefix_same (ifc->address, p)) - return ifc; + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) + if (prefix_same(ifc->address, p)) + return ifc; - return NULL; + return NULL; } /* Check if two ifc's describe the same address in the same state */ -static int -connected_same (struct connected *ifc1, struct connected *ifc2) +static int connected_same(struct connected *ifc1, struct connected *ifc2) { - if (ifc1->ifp != ifc2->ifp) - return 0; - - if (ifc1->destination) - if (!ifc2->destination) - return 0; - if (ifc2->destination) - if (!ifc1->destination) - return 0; - - if (ifc1->destination && ifc2->destination) - if (!prefix_same (ifc1->destination, ifc2->destination)) - return 0; - - if (ifc1->flags != ifc2->flags) - return 0; - - if (ifc1->conf != ifc2->conf) - return 0; - - return 1; + if (ifc1->ifp != ifc2->ifp) + return 0; + + if (ifc1->destination) + if (!ifc2->destination) + return 0; + if (ifc2->destination) + if (!ifc1->destination) + return 0; + + if (ifc1->destination && ifc2->destination) + if (!prefix_same(ifc1->destination, ifc2->destination)) + return 0; + + if (ifc1->flags != ifc2->flags) + return 0; + + if (ifc1->conf != ifc2->conf) + return 0; + + return 1; } /* Handle changes to addresses and send the neccesary announcements * to clients. */ -static void -connected_update(struct interface *ifp, struct connected *ifc) +static void connected_update(struct interface *ifp, struct connected *ifc) { - struct connected *current; - - /* Check same connected route. */ - if ((current = connected_check (ifp, (struct prefix *) ifc->address))) - { - if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED)) - SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); - - /* Avoid spurious withdraws, this might be just the kernel 'reflecting' - * back an address we have already added. - */ - if (connected_same (current, ifc)) - { - /* nothing to do */ - connected_free (ifc); - return; - } - - /* Clear the configured flag on the old ifc, so it will be freed by - * connected withdraw. */ - UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED); - connected_withdraw (current); /* implicit withdraw - freebsd does this */ - } - - /* If the connected is new or has changed, announce it, if it is usable */ - if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) - connected_announce(ifp, ifc); + struct connected *current; + + /* Check same connected route. */ + if ((current = connected_check(ifp, (struct prefix *)ifc->address))) { + if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED)) + SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); + + /* Avoid spurious withdraws, this might be just the kernel + * 'reflecting' + * back an address we have already added. + */ + if (connected_same(current, ifc)) { + /* nothing to do */ + connected_free(ifc); + return; + } + + /* Clear the configured flag on the old ifc, so it will be freed + * by + * connected withdraw. */ + UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED); + connected_withdraw( + current); /* implicit withdraw - freebsd does this */ + } + + /* If the connected is new or has changed, announce it, if it is usable + */ + if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) + connected_announce(ifp, ifc); } /* Called from if_up(). */ -void -connected_up_ipv4 (struct interface *ifp, struct connected *ifc) +void connected_up_ipv4(struct interface *ifp, struct connected *ifc) { - struct prefix p; - - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) - return; - - PREFIX_COPY_IPV4((struct prefix_ipv4 *)&p, CONNECTED_PREFIX(ifc)); - - /* Apply mask to the network. */ - apply_mask (&p); - - /* In case of connected address is 0.0.0.0/0 we treat it tunnel - address. */ - if (prefix_ipv4_any ((struct prefix_ipv4 *)&p)) - return; - - rib_add (AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, NULL, NULL, ifp->ifindex, - RT_TABLE_MAIN, ifp->metric, 0, 0); - - rib_add (AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, NULL, NULL, ifp->ifindex, - RT_TABLE_MAIN, ifp->metric, 0, 0); - - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IF %s IPv4 address add/up, scheduling RIB processing", - ifp->vrf_id, ifp->name); - rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); - - /* Schedule LSP forwarding entries for processing, if appropriate. */ - if (ifp->vrf_id == VRF_DEFAULT) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("%u: IF %s IPv4 address add/up, scheduling MPLS processing", - ifp->vrf_id, ifp->name); - mpls_mark_lsps_for_processing (vrf_info_lookup(ifp->vrf_id)); - } + struct prefix p; + + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) + return; + + PREFIX_COPY_IPV4((struct prefix_ipv4 *)&p, CONNECTED_PREFIX(ifc)); + + /* Apply mask to the network. */ + apply_mask(&p); + + /* In case of connected address is 0.0.0.0/0 we treat it tunnel + address. */ + if (prefix_ipv4_any((struct prefix_ipv4 *)&p)) + return; + + rib_add(AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, + &p, NULL, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric, + 0, 0); + + rib_add(AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, + &p, NULL, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric, + 0, 0); + + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IF %s IPv4 address add/up, scheduling RIB processing", + ifp->vrf_id, ifp->name); + rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE); + + /* Schedule LSP forwarding entries for processing, if appropriate. */ + if (ifp->vrf_id == VRF_DEFAULT) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug( + "%u: IF %s IPv4 address add/up, scheduling MPLS processing", + ifp->vrf_id, ifp->name); + mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id)); + } } /* Add connected IPv4 route to the interface. */ -void -connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, - u_char prefixlen, struct in_addr *broad, - const char *label) +void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr, + u_char prefixlen, struct in_addr *broad, + const char *label) { - struct prefix_ipv4 *p; - struct connected *ifc; - - if (ipv4_martian(addr)) - return; - - /* Make connected structure. */ - ifc = connected_new (); - ifc->ifp = ifp; - ifc->flags = flags; - /* If we get a notification from the kernel, - * we can safely assume the address is known to the kernel */ - SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); - - /* Allocate new connected address. */ - p = prefix_ipv4_new (); - p->family = AF_INET; - p->prefix = *addr; - p->prefixlen = prefixlen; - ifc->address = (struct prefix *) p; - - /* If there is broadcast or peer address. */ - if (broad) - { - p = prefix_ipv4_new (); - p->family = AF_INET; - p->prefix = *broad; - p->prefixlen = prefixlen; - ifc->destination = (struct prefix *) p; - - /* validate the destination address */ - if (CONNECTED_PEER(ifc)) - { - if (IPV4_ADDR_SAME(addr,broad)) - zlog_warn("warning: interface %s has same local and peer " - "address %s, routing protocols may malfunction", - ifp->name,inet_ntoa(*addr)); - } - else - { - if (broad->s_addr != ipv4_broadcast_addr(addr->s_addr,prefixlen)) - { - char buf[2][INET_ADDRSTRLEN]; - struct in_addr bcalc; - bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr,prefixlen); - zlog_warn("warning: interface %s broadcast addr %s/%d != " - "calculated %s, routing protocols may malfunction", - ifp->name, - inet_ntop (AF_INET, broad, buf[0], sizeof(buf[0])), - prefixlen, - inet_ntop (AF_INET, &bcalc, buf[1], sizeof(buf[1]))); - } - } - - } - else - { - if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) - { - zlog_warn("warning: %s called for interface %s " - "with peer flag set, but no peer address supplied", - __func__, ifp->name); - UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER); + struct prefix_ipv4 *p; + struct connected *ifc; + + if (ipv4_martian(addr)) + return; + + /* Make connected structure. */ + ifc = connected_new(); + ifc->ifp = ifp; + ifc->flags = flags; + /* If we get a notification from the kernel, + * we can safely assume the address is known to the kernel */ + SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + + /* Allocate new connected address. */ + p = prefix_ipv4_new(); + p->family = AF_INET; + p->prefix = *addr; + p->prefixlen = prefixlen; + ifc->address = (struct prefix *)p; + + /* If there is broadcast or peer address. */ + if (broad) { + p = prefix_ipv4_new(); + p->family = AF_INET; + p->prefix = *broad; + p->prefixlen = prefixlen; + ifc->destination = (struct prefix *)p; + + /* validate the destination address */ + if (CONNECTED_PEER(ifc)) { + if (IPV4_ADDR_SAME(addr, broad)) + zlog_warn( + "warning: interface %s has same local and peer " + "address %s, routing protocols may malfunction", + ifp->name, inet_ntoa(*addr)); + } else { + if (broad->s_addr + != ipv4_broadcast_addr(addr->s_addr, prefixlen)) { + char buf[2][INET_ADDRSTRLEN]; + struct in_addr bcalc; + bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr, + prefixlen); + zlog_warn( + "warning: interface %s broadcast addr %s/%d != " + "calculated %s, routing protocols may malfunction", + ifp->name, + inet_ntop(AF_INET, broad, buf[0], + sizeof(buf[0])), + prefixlen, + inet_ntop(AF_INET, &bcalc, buf[1], + sizeof(buf[1]))); + } + } + + } else { + if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) { + zlog_warn( + "warning: %s called for interface %s " + "with peer flag set, but no peer address supplied", + __func__, ifp->name); + UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER); + } + + /* no broadcast or destination address was supplied */ + if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp)) + zlog_warn( + "warning: PtP interface %s with addr %s/%d needs a " + "peer address", + ifp->name, inet_ntoa(*addr), prefixlen); } - /* no broadcast or destination address was supplied */ - if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp)) - zlog_warn("warning: PtP interface %s with addr %s/%d needs a " - "peer address",ifp->name,inet_ntoa(*addr),prefixlen); - } + /* Label of this address. */ + if (label) + ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label); - /* Label of this address. */ - if (label) - ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); + /* For all that I know an IPv4 address is always ready when we receive + * the notification. So it should be safe to set the REAL flag here. */ + SET_FLAG(ifc->conf, ZEBRA_IFC_REAL); - /* For all that I know an IPv4 address is always ready when we receive - * the notification. So it should be safe to set the REAL flag here. */ - SET_FLAG(ifc->conf, ZEBRA_IFC_REAL); - - connected_update(ifp, ifc); + connected_update(ifp, ifc); } -void -connected_down_ipv4 (struct interface *ifp, struct connected *ifc) +void connected_down_ipv4(struct interface *ifp, struct connected *ifc) { - struct prefix p; + struct prefix p; - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) - return; + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) + return; - PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); + PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); - /* Apply mask to the network. */ - apply_mask (&p); + /* Apply mask to the network. */ + apply_mask(&p); - /* In case of connected address is 0.0.0.0/0 we treat it tunnel - address. */ - if (prefix_ipv4_any ((struct prefix_ipv4 *)&p)) - return; + /* In case of connected address is 0.0.0.0/0 we treat it tunnel + address. */ + if (prefix_ipv4_any((struct prefix_ipv4 *)&p)) + return; - /* Same logic as for connected_up_ipv4(): push the changes into the head. */ - rib_delete (AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, NULL, ifp->ifindex, 0); + /* Same logic as for connected_up_ipv4(): push the changes into the + * head. */ + rib_delete(AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, + &p, NULL, NULL, ifp->ifindex, 0); - rib_delete (AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, NULL, ifp->ifindex, 0); + rib_delete(AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, + 0, &p, NULL, NULL, ifp->ifindex, 0); - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IF %s IPv4 address down, scheduling RIB processing", - ifp->vrf_id, ifp->name); + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IF %s IPv4 address down, scheduling RIB processing", + ifp->vrf_id, ifp->name); - rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); + rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE); - /* Schedule LSP forwarding entries for processing, if appropriate. */ - if (ifp->vrf_id == VRF_DEFAULT) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("%u: IF %s IPv4 address add/up, scheduling MPLS processing", - ifp->vrf_id, ifp->name); - mpls_mark_lsps_for_processing (vrf_info_lookup(ifp->vrf_id)); - } + /* Schedule LSP forwarding entries for processing, if appropriate. */ + if (ifp->vrf_id == VRF_DEFAULT) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug( + "%u: IF %s IPv4 address add/up, scheduling MPLS processing", + ifp->vrf_id, ifp->name); + mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id)); + } } /* Delete connected IPv4 route to the interface. */ -void -connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, - u_char prefixlen, struct in_addr *broad) +void connected_delete_ipv4(struct interface *ifp, int flags, + struct in_addr *addr, u_char prefixlen, + struct in_addr *broad) { - struct prefix_ipv4 p; - struct connected *ifc; - - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefix = *addr; - p.prefixlen = prefixlen; - - ifc = connected_check (ifp, (struct prefix *) &p); - if (! ifc) - return; - - connected_withdraw (ifc); - - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IF %s IPv4 address del, scheduling RIB processing", - ifp->vrf_id, ifp->name); - - rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); - - /* Schedule LSP forwarding entries for processing, if appropriate. */ - if (ifp->vrf_id == VRF_DEFAULT) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("%u: IF %s IPv4 address add/up, scheduling MPLS processing", - ifp->vrf_id, ifp->name); - mpls_mark_lsps_for_processing (vrf_info_lookup(ifp->vrf_id)); - } + struct prefix_ipv4 p; + struct connected *ifc; + + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefix = *addr; + p.prefixlen = prefixlen; + + ifc = connected_check(ifp, (struct prefix *)&p); + if (!ifc) + return; + + connected_withdraw(ifc); + + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IF %s IPv4 address del, scheduling RIB processing", + ifp->vrf_id, ifp->name); + + rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE); + + /* Schedule LSP forwarding entries for processing, if appropriate. */ + if (ifp->vrf_id == VRF_DEFAULT) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug( + "%u: IF %s IPv4 address add/up, scheduling MPLS processing", + ifp->vrf_id, ifp->name); + mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id)); + } } -void -connected_up_ipv6 (struct interface *ifp, struct connected *ifc) +void connected_up_ipv6(struct interface *ifp, struct connected *ifc) { - struct prefix p; + struct prefix p; - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) - return; + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) + return; - PREFIX_COPY_IPV6((struct prefix_ipv6 *)&p, CONNECTED_PREFIX(ifc)); + PREFIX_COPY_IPV6((struct prefix_ipv6 *)&p, CONNECTED_PREFIX(ifc)); - /* Apply mask to the network. */ - apply_mask (&p); + /* Apply mask to the network. */ + apply_mask(&p); #ifndef LINUX - /* XXX: It is already done by rib_bogus_ipv6 within rib_add */ - if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) - return; + /* XXX: It is already done by rib_bogus_ipv6 within rib_add */ + if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6)) + return; #endif - rib_add (AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, NULL, NULL, ifp->ifindex, - RT_TABLE_MAIN, ifp->metric, 0, 0); + rib_add(AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, + &p, NULL, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric, + 0, 0); - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IF %s IPv6 address down, scheduling RIB processing", - ifp->vrf_id, ifp->name); + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IF %s IPv6 address down, scheduling RIB processing", + ifp->vrf_id, ifp->name); - rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); + rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE); - /* Schedule LSP forwarding entries for processing, if appropriate. */ - if (ifp->vrf_id == VRF_DEFAULT) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("%u: IF %s IPv4 address add/up, scheduling MPLS processing", - ifp->vrf_id, ifp->name); - mpls_mark_lsps_for_processing (vrf_info_lookup(ifp->vrf_id)); - } + /* Schedule LSP forwarding entries for processing, if appropriate. */ + if (ifp->vrf_id == VRF_DEFAULT) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug( + "%u: IF %s IPv4 address add/up, scheduling MPLS processing", + ifp->vrf_id, ifp->name); + mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id)); + } } /* Add connected IPv6 route to the interface. */ -void -connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr, - u_char prefixlen, struct in6_addr *broad, - const char *label) +void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr, + u_char prefixlen, struct in6_addr *broad, + const char *label) { - struct prefix_ipv6 *p; - struct connected *ifc; - - if (ipv6_martian(addr)) - return; - - /* Make connected structure. */ - ifc = connected_new (); - ifc->ifp = ifp; - ifc->flags = flags; - /* If we get a notification from the kernel, - * we can safely assume the address is known to the kernel */ - SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); - - /* Allocate new connected address. */ - p = prefix_ipv6_new (); - p->family = AF_INET6; - IPV6_ADDR_COPY (&p->prefix, addr); - p->prefixlen = prefixlen; - ifc->address = (struct prefix *) p; - - /* If there is broadcast or peer address. */ - if (broad) - { - if (IN6_IS_ADDR_UNSPECIFIED(broad)) - zlog_warn("warning: %s called for interface %s with unspecified " - "destination address; ignoring!", __func__, ifp->name); - else - { - p = prefix_ipv6_new (); - p->family = AF_INET6; - IPV6_ADDR_COPY (&p->prefix, broad); - p->prefixlen = prefixlen; - ifc->destination = (struct prefix *) p; + struct prefix_ipv6 *p; + struct connected *ifc; + + if (ipv6_martian(addr)) + return; + + /* Make connected structure. */ + ifc = connected_new(); + ifc->ifp = ifp; + ifc->flags = flags; + /* If we get a notification from the kernel, + * we can safely assume the address is known to the kernel */ + SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + + /* Allocate new connected address. */ + p = prefix_ipv6_new(); + p->family = AF_INET6; + IPV6_ADDR_COPY(&p->prefix, addr); + p->prefixlen = prefixlen; + ifc->address = (struct prefix *)p; + + /* If there is broadcast or peer address. */ + if (broad) { + if (IN6_IS_ADDR_UNSPECIFIED(broad)) + zlog_warn( + "warning: %s called for interface %s with unspecified " + "destination address; ignoring!", + __func__, ifp->name); + else { + p = prefix_ipv6_new(); + p->family = AF_INET6; + IPV6_ADDR_COPY(&p->prefix, broad); + p->prefixlen = prefixlen; + ifc->destination = (struct prefix *)p; + } + } + if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination) { + zlog_warn( + "warning: %s called for interface %s " + "with peer flag set, but no peer address supplied", + __func__, ifp->name); + UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER); } - } - if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination) - { - zlog_warn("warning: %s called for interface %s " - "with peer flag set, but no peer address supplied", - __func__, ifp->name); - UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER); - } - - /* Label of this address. */ - if (label) - ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); - - /* On Linux, we only get here when DAD is complete, therefore we can set - * ZEBRA_IFC_REAL. - * - * On BSD, there currently doesn't seem to be a way to check for completion of - * DAD, so we replicate the old behaviour and set ZEBRA_IFC_REAL, although DAD - * might still be running. - */ - SET_FLAG(ifc->conf, ZEBRA_IFC_REAL); - connected_update(ifp, ifc); + + /* Label of this address. */ + if (label) + ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label); + + /* On Linux, we only get here when DAD is complete, therefore we can set + * ZEBRA_IFC_REAL. + * + * On BSD, there currently doesn't seem to be a way to check for + * completion of + * DAD, so we replicate the old behaviour and set ZEBRA_IFC_REAL, + * although DAD + * might still be running. + */ + SET_FLAG(ifc->conf, ZEBRA_IFC_REAL); + connected_update(ifp, ifc); } -void -connected_down_ipv6 (struct interface *ifp, struct connected *ifc) +void connected_down_ipv6(struct interface *ifp, struct connected *ifc) { - struct prefix p; + struct prefix p; - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) - return; + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) + return; - PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc)); + PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc)); - apply_mask (&p); + apply_mask(&p); - if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) - return; + if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6)) + return; - rib_delete (AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, NULL, ifp->ifindex, 0); + rib_delete(AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, + 0, &p, NULL, NULL, ifp->ifindex, 0); - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IF %s IPv6 address down, scheduling RIB processing", - ifp->vrf_id, ifp->name); + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IF %s IPv6 address down, scheduling RIB processing", + ifp->vrf_id, ifp->name); - rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); + rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE); - /* Schedule LSP forwarding entries for processing, if appropriate. */ - if (ifp->vrf_id == VRF_DEFAULT) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("%u: IF %s IPv4 address add/up, scheduling MPLS processing", - ifp->vrf_id, ifp->name); - mpls_mark_lsps_for_processing (vrf_info_lookup(ifp->vrf_id)); - } + /* Schedule LSP forwarding entries for processing, if appropriate. */ + if (ifp->vrf_id == VRF_DEFAULT) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug( + "%u: IF %s IPv4 address add/up, scheduling MPLS processing", + ifp->vrf_id, ifp->name); + mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id)); + } } -void -connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address, - u_char prefixlen, struct in6_addr *broad) +void connected_delete_ipv6(struct interface *ifp, struct in6_addr *address, + u_char prefixlen, struct in6_addr *broad) { - struct prefix_ipv6 p; - struct connected *ifc; - - memset (&p, 0, sizeof (struct prefix_ipv6)); - p.family = AF_INET6; - memcpy (&p.prefix, address, sizeof (struct in6_addr)); - p.prefixlen = prefixlen; - - ifc = connected_check (ifp, (struct prefix *) &p); - if (! ifc) - return; - - connected_withdraw (ifc); - - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IF %s IPv6 address del, scheduling RIB processing", - ifp->vrf_id, ifp->name); - - rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); - - /* Schedule LSP forwarding entries for processing, if appropriate. */ - if (ifp->vrf_id == VRF_DEFAULT) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("%u: IF %s IPv4 address add/up, scheduling MPLS processing", - ifp->vrf_id, ifp->name); - mpls_mark_lsps_for_processing (vrf_info_lookup(ifp->vrf_id)); - } + struct prefix_ipv6 p; + struct connected *ifc; + + memset(&p, 0, sizeof(struct prefix_ipv6)); + p.family = AF_INET6; + memcpy(&p.prefix, address, sizeof(struct in6_addr)); + p.prefixlen = prefixlen; + + ifc = connected_check(ifp, (struct prefix *)&p); + if (!ifc) + return; + + connected_withdraw(ifc); + + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IF %s IPv6 address del, scheduling RIB processing", + ifp->vrf_id, ifp->name); + + rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE); + + /* Schedule LSP forwarding entries for processing, if appropriate. */ + if (ifp->vrf_id == VRF_DEFAULT) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug( + "%u: IF %s IPv4 address add/up, scheduling MPLS processing", + ifp->vrf_id, ifp->name); + mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id)); + } } -int -connected_is_unnumbered (struct interface *ifp) +int connected_is_unnumbered(struct interface *ifp) { - struct connected *connected; - struct listnode *node; - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) - { - if (CHECK_FLAG (connected->conf, ZEBRA_IFC_REAL) && - connected->address->family == AF_INET) - return CHECK_FLAG(connected->flags, ZEBRA_IFA_UNNUMBERED); - } - return 0; + struct connected *connected; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { + if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL) + && connected->address->family == AF_INET) + return CHECK_FLAG(connected->flags, + ZEBRA_IFA_UNNUMBERED); + } + return 0; } diff --git a/zebra/connected.h b/zebra/connected.h index 3e3734685..eaf79fe9a 100644 --- a/zebra/connected.h +++ b/zebra/connected.h @@ -22,35 +22,32 @@ #ifndef _ZEBRA_CONNECTED_H #define _ZEBRA_CONNECTED_H -extern struct connected * -connected_check (struct interface *ifp, struct prefix *p); +extern struct connected *connected_check(struct interface *ifp, + struct prefix *p); -extern void -connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, - u_char prefixlen, struct in_addr *broad, - const char *label); +extern void connected_add_ipv4(struct interface *ifp, int flags, + struct in_addr *addr, u_char prefixlen, + struct in_addr *broad, const char *label); -extern void -connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, - u_char prefixlen, struct in_addr *broad); +extern void connected_delete_ipv4(struct interface *ifp, int flags, + struct in_addr *addr, u_char prefixlen, + struct in_addr *broad); -extern void -connected_delete_ipv4_unnumbered (struct connected *ifc); +extern void connected_delete_ipv4_unnumbered(struct connected *ifc); -extern void connected_up_ipv4 (struct interface *, struct connected *); -extern void connected_down_ipv4 (struct interface *, struct connected *); +extern void connected_up_ipv4(struct interface *, struct connected *); +extern void connected_down_ipv4(struct interface *, struct connected *); -extern void -connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *address, - u_char prefixlen, struct in6_addr *broad, - const char *label); -extern void -connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address, - u_char prefixlen, struct in6_addr *broad); +extern void connected_add_ipv6(struct interface *ifp, int flags, + struct in6_addr *address, u_char prefixlen, + struct in6_addr *broad, const char *label); +extern void connected_delete_ipv6(struct interface *ifp, + struct in6_addr *address, u_char prefixlen, + struct in6_addr *broad); -extern void connected_up_ipv6 (struct interface *, struct connected *); -extern void connected_down_ipv6 (struct interface *ifp, struct connected *); +extern void connected_up_ipv6(struct interface *, struct connected *); +extern void connected_down_ipv6(struct interface *ifp, struct connected *); -extern int connected_is_unnumbered (struct interface *); +extern int connected_is_unnumbered(struct interface *); #endif /*_ZEBRA_CONNECTED_H */ diff --git a/zebra/debug.c b/zebra/debug.c index 1c3cf9a3d..dfee6b74c 100644 --- a/zebra/debug.c +++ b/zebra/debug.c @@ -40,50 +40,50 @@ DEFUN (show_debugging_zebra, "Debugging information\n" "Zebra configuration\n") { - vty_out (vty, "Zebra debugging status:\n"); - - if (IS_ZEBRA_DEBUG_EVENT) - vty_out (vty, " Zebra event debugging is on\n"); - - if (IS_ZEBRA_DEBUG_PACKET) - { - if (IS_ZEBRA_DEBUG_SEND && IS_ZEBRA_DEBUG_RECV) - { - vty_out (vty, " Zebra packet%s debugging is on\n", - IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); + vty_out(vty, "Zebra debugging status:\n"); + + if (IS_ZEBRA_DEBUG_EVENT) + vty_out(vty, " Zebra event debugging is on\n"); + + if (IS_ZEBRA_DEBUG_PACKET) { + if (IS_ZEBRA_DEBUG_SEND && IS_ZEBRA_DEBUG_RECV) { + vty_out(vty, " Zebra packet%s debugging is on\n", + IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); + } else { + if (IS_ZEBRA_DEBUG_SEND) + vty_out(vty, + " Zebra packet send%s debugging is on\n", + IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); + else + vty_out(vty, + " Zebra packet receive%s debugging is on\n", + IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); + } } - else - { - if (IS_ZEBRA_DEBUG_SEND) - vty_out (vty, " Zebra packet send%s debugging is on\n", - IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); - else - vty_out (vty, " Zebra packet receive%s debugging is on\n", - IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); - } - } - - if (IS_ZEBRA_DEBUG_KERNEL) - vty_out (vty, " Zebra kernel debugging is on\n"); - if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) - vty_out (vty, " Zebra kernel netlink message dumps (send) are on\n"); - if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) - vty_out (vty, " Zebra kernel netlink message dumps (recv) are on\n"); - - /* Check here using flags as the 'macro' does an OR */ - if (CHECK_FLAG (zebra_debug_rib, ZEBRA_DEBUG_RIB)) - vty_out (vty, " Zebra RIB debugging is on\n"); - if (CHECK_FLAG (zebra_debug_rib, ZEBRA_DEBUG_RIB_DETAILED)) - vty_out (vty, " Zebra RIB detailed debugging is on\n"); - - if (IS_ZEBRA_DEBUG_FPM) - vty_out (vty, " Zebra FPM debugging is on\n"); - if (IS_ZEBRA_DEBUG_NHT) - vty_out (vty, " Zebra next-hop tracking debugging is on\n"); - if (IS_ZEBRA_DEBUG_MPLS) - vty_out (vty, " Zebra MPLS debugging is on\n"); - - return CMD_SUCCESS; + + if (IS_ZEBRA_DEBUG_KERNEL) + vty_out(vty, " Zebra kernel debugging is on\n"); + if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) + vty_out(vty, + " Zebra kernel netlink message dumps (send) are on\n"); + if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) + vty_out(vty, + " Zebra kernel netlink message dumps (recv) are on\n"); + + /* Check here using flags as the 'macro' does an OR */ + if (CHECK_FLAG(zebra_debug_rib, ZEBRA_DEBUG_RIB)) + vty_out(vty, " Zebra RIB debugging is on\n"); + if (CHECK_FLAG(zebra_debug_rib, ZEBRA_DEBUG_RIB_DETAILED)) + vty_out(vty, " Zebra RIB detailed debugging is on\n"); + + if (IS_ZEBRA_DEBUG_FPM) + vty_out(vty, " Zebra FPM debugging is on\n"); + if (IS_ZEBRA_DEBUG_NHT) + vty_out(vty, " Zebra next-hop tracking debugging is on\n"); + if (IS_ZEBRA_DEBUG_MPLS) + vty_out(vty, " Zebra MPLS debugging is on\n"); + + return CMD_SUCCESS; } DEFUN (debug_zebra_events, @@ -93,8 +93,8 @@ DEFUN (debug_zebra_events, "Zebra configuration\n" "Debug option set for zebra events\n") { - zebra_debug_event = ZEBRA_DEBUG_EVENT; - return CMD_WARNING_CONFIG_FAILED; + zebra_debug_event = ZEBRA_DEBUG_EVENT; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (debug_zebra_nht, @@ -104,8 +104,8 @@ DEFUN (debug_zebra_nht, "Zebra configuration\n" "Debug option set for zebra next hop tracking\n") { - zebra_debug_nht = ZEBRA_DEBUG_NHT; - return CMD_WARNING_CONFIG_FAILED; + zebra_debug_nht = ZEBRA_DEBUG_NHT; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (debug_zebra_mpls, @@ -115,8 +115,8 @@ DEFUN (debug_zebra_mpls, "Zebra configuration\n" "Debug option set for zebra MPLS LSPs\n") { - zebra_debug_mpls = ZEBRA_DEBUG_MPLS; - return CMD_WARNING_CONFIG_FAILED; + zebra_debug_mpls = ZEBRA_DEBUG_MPLS; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (debug_zebra_vxlan, @@ -126,8 +126,8 @@ DEFUN (debug_zebra_vxlan, "Zebra configuration\n" "Debug option set for zebra VxLAN (EVPN)\n") { - zebra_debug_vxlan = ZEBRA_DEBUG_VXLAN; - return CMD_WARNING; + zebra_debug_vxlan = ZEBRA_DEBUG_VXLAN; + return CMD_WARNING; } DEFUN (debug_zebra_packet, @@ -140,24 +140,23 @@ DEFUN (debug_zebra_packet, "Debug option set for send packet\n" "Debug option set for detailed info\n") { - int idx = 0; - zebra_debug_packet = ZEBRA_DEBUG_PACKET; - - if (argv_find (argv, argc, "send", &idx)) - SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_SEND); - idx = 0; - if (argv_find (argv, argc, "recv", &idx)) - SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_RECV); - idx = 0; - if (argv_find (argv, argc, "detail", &idx)) - SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_DETAIL); - - if (!(zebra_debug_packet & ZEBRA_DEBUG_SEND & ZEBRA_DEBUG_RECV)) - { - SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_SEND); - SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_RECV); - } - return CMD_SUCCESS; + int idx = 0; + zebra_debug_packet = ZEBRA_DEBUG_PACKET; + + if (argv_find(argv, argc, "send", &idx)) + SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_SEND); + idx = 0; + if (argv_find(argv, argc, "recv", &idx)) + SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_RECV); + idx = 0; + if (argv_find(argv, argc, "detail", &idx)) + SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_DETAIL); + + if (!(zebra_debug_packet & ZEBRA_DEBUG_SEND & ZEBRA_DEBUG_RECV)) { + SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_SEND); + SET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_RECV); + } + return CMD_SUCCESS; } DEFUN (debug_zebra_kernel, @@ -167,8 +166,8 @@ DEFUN (debug_zebra_kernel, "Zebra configuration\n" "Debug option set for zebra between kernel interface\n") { - SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL); - return CMD_SUCCESS; + SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL); + return CMD_SUCCESS; } DEFUN (debug_zebra_kernel_msgdump, @@ -181,13 +180,13 @@ DEFUN (debug_zebra_kernel_msgdump, "Dump raw netlink messages received\n" "Dump raw netlink messages sent\n") { - int idx = 0; - if (argc == 4 || argv_find (argv, argc, "recv", &idx)) - SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV); - if (argc == 4 || argv_find (argv, argc, "send", &idx)) - SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND); + int idx = 0; + if (argc == 4 || argv_find(argv, argc, "recv", &idx)) + SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV); + if (argc == 4 || argv_find(argv, argc, "send", &idx)) + SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_zebra_rib, @@ -197,8 +196,8 @@ DEFUN (debug_zebra_rib, "Zebra configuration\n" "Debug RIB events\n") { - SET_FLAG (zebra_debug_rib, ZEBRA_DEBUG_RIB); - return CMD_SUCCESS; + SET_FLAG(zebra_debug_rib, ZEBRA_DEBUG_RIB); + return CMD_SUCCESS; } DEFUN (debug_zebra_rib_detailed, @@ -209,8 +208,8 @@ DEFUN (debug_zebra_rib_detailed, "Debug RIB events\n" "Detailed debugs\n") { - SET_FLAG (zebra_debug_rib, ZEBRA_DEBUG_RIB_DETAILED); - return CMD_SUCCESS; + SET_FLAG(zebra_debug_rib, ZEBRA_DEBUG_RIB_DETAILED); + return CMD_SUCCESS; } DEFUN (debug_zebra_fpm, @@ -220,8 +219,8 @@ DEFUN (debug_zebra_fpm, "Zebra configuration\n" "Debug zebra FPM events\n") { - SET_FLAG (zebra_debug_fpm, ZEBRA_DEBUG_FPM); - return CMD_SUCCESS; + SET_FLAG(zebra_debug_fpm, ZEBRA_DEBUG_FPM); + return CMD_SUCCESS; } DEFUN (no_debug_zebra_events, @@ -232,8 +231,8 @@ DEFUN (no_debug_zebra_events, "Zebra configuration\n" "Debug option set for zebra events\n") { - zebra_debug_event = 0; - return CMD_SUCCESS; + zebra_debug_event = 0; + return CMD_SUCCESS; } DEFUN (no_debug_zebra_nht, @@ -244,8 +243,8 @@ DEFUN (no_debug_zebra_nht, "Zebra configuration\n" "Debug option set for zebra next hop tracking\n") { - zebra_debug_nht = 0; - return CMD_SUCCESS; + zebra_debug_nht = 0; + return CMD_SUCCESS; } DEFUN (no_debug_zebra_mpls, @@ -256,8 +255,8 @@ DEFUN (no_debug_zebra_mpls, "Zebra configuration\n" "Debug option set for zebra MPLS LSPs\n") { - zebra_debug_mpls = 0; - return CMD_SUCCESS; + zebra_debug_mpls = 0; + return CMD_SUCCESS; } DEFUN (no_debug_zebra_vxlan, @@ -268,8 +267,8 @@ DEFUN (no_debug_zebra_vxlan, "Zebra configuration\n" "Debug option set for zebra VxLAN (EVPN)\n") { - zebra_debug_vxlan = 0; - return CMD_SUCCESS; + zebra_debug_vxlan = 0; + return CMD_SUCCESS; } DEFUN (no_debug_zebra_packet, @@ -282,12 +281,12 @@ DEFUN (no_debug_zebra_packet, "Debug option set for receive packet\n" "Debug option set for send packet\n") { - int idx = 0; - if (argc == 4 || argv_find (argv, argc, "send", &idx)) - UNSET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_SEND); - if (argc == 4 || argv_find (argv, argc, "recv", &idx)) - UNSET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_RECV); - return CMD_SUCCESS; + int idx = 0; + if (argc == 4 || argv_find(argv, argc, "send", &idx)) + UNSET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_SEND); + if (argc == 4 || argv_find(argv, argc, "recv", &idx)) + UNSET_FLAG(zebra_debug_packet, ZEBRA_DEBUG_RECV); + return CMD_SUCCESS; } DEFUN (no_debug_zebra_kernel, @@ -298,8 +297,8 @@ DEFUN (no_debug_zebra_kernel, "Zebra configuration\n" "Debug option set for zebra between kernel interface\n") { - UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL); - return CMD_SUCCESS; + UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL); + return CMD_SUCCESS; } DEFUN (no_debug_zebra_kernel_msgdump, @@ -313,13 +312,13 @@ DEFUN (no_debug_zebra_kernel_msgdump, "Dump raw netlink messages received\n" "Dump raw netlink messages sent\n") { - int idx = 0; - if (argc == 5 || argv_find (argv, argc, "recv", &idx)) - UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV); - if (argc == 5 || argv_find (argv, argc, "send", &idx)) - UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND); + int idx = 0; + if (argc == 5 || argv_find(argv, argc, "recv", &idx)) + UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV); + if (argc == 5 || argv_find(argv, argc, "send", &idx)) + UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_debug_zebra_rib, @@ -330,8 +329,8 @@ DEFUN (no_debug_zebra_rib, "Zebra configuration\n" "Debug zebra RIB\n") { - zebra_debug_rib = 0; - return CMD_SUCCESS; + zebra_debug_rib = 0; + return CMD_SUCCESS; } DEFUN (no_debug_zebra_rib_detailed, @@ -343,8 +342,8 @@ DEFUN (no_debug_zebra_rib_detailed, "Debug zebra RIB\n" "Detailed debugs\n") { - UNSET_FLAG (zebra_debug_rib, ZEBRA_DEBUG_RIB_DETAILED); - return CMD_SUCCESS; + UNSET_FLAG(zebra_debug_rib, ZEBRA_DEBUG_RIB_DETAILED); + return CMD_SUCCESS; } DEFUN (no_debug_zebra_fpm, @@ -355,150 +354,130 @@ DEFUN (no_debug_zebra_fpm, "Zebra configuration\n" "Debug zebra FPM events\n") { - zebra_debug_fpm = 0; - return CMD_SUCCESS; + zebra_debug_fpm = 0; + return CMD_SUCCESS; } /* Debug node. */ -struct cmd_node debug_node = -{ - DEBUG_NODE, - "", /* Debug node has no interface. */ - 1 -}; +struct cmd_node debug_node = {DEBUG_NODE, "", /* Debug node has no interface. */ + 1}; -static int -config_write_debug (struct vty *vty) +static int config_write_debug(struct vty *vty) { - int write = 0; - - if (IS_ZEBRA_DEBUG_EVENT) - { - vty_out (vty, "debug zebra events\n"); - write++; - } - if (IS_ZEBRA_DEBUG_PACKET) - { - if (IS_ZEBRA_DEBUG_SEND && IS_ZEBRA_DEBUG_RECV) - { - vty_out (vty, "debug zebra packet%s\n", - IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); - write++; + int write = 0; + + if (IS_ZEBRA_DEBUG_EVENT) { + vty_out(vty, "debug zebra events\n"); + write++; + } + if (IS_ZEBRA_DEBUG_PACKET) { + if (IS_ZEBRA_DEBUG_SEND && IS_ZEBRA_DEBUG_RECV) { + vty_out(vty, "debug zebra packet%s\n", + IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); + write++; + } else { + if (IS_ZEBRA_DEBUG_SEND) + vty_out(vty, "debug zebra packet send%s\n", + IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); + else + vty_out(vty, "debug zebra packet recv%s\n", + IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); + write++; + } + } + if (IS_ZEBRA_DEBUG_KERNEL) { + vty_out(vty, "debug zebra kernel\n"); + write++; + } + if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) { + vty_out(vty, "debug zebra kernel msgdump recv\n"); + write++; + } + if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) { + vty_out(vty, "debug zebra kernel msgdump send\n"); + write++; + } + /* Check here using flags as the 'macro' does an OR */ + if (CHECK_FLAG(zebra_debug_rib, ZEBRA_DEBUG_RIB)) { + vty_out(vty, "debug zebra rib\n"); + write++; + } + if (CHECK_FLAG(zebra_debug_rib, ZEBRA_DEBUG_RIB_DETAILED)) { + vty_out(vty, "debug zebra rib detailed\n"); + write++; + } + if (IS_ZEBRA_DEBUG_FPM) { + vty_out(vty, "debug zebra fpm\n"); + write++; + } + if (IS_ZEBRA_DEBUG_NHT) { + vty_out(vty, "debug zebra nht\n"); + write++; + } + if (IS_ZEBRA_DEBUG_MPLS) { + vty_out(vty, "debug zebra mpls\n"); + write++; } - else - { - if (IS_ZEBRA_DEBUG_SEND) - vty_out (vty, "debug zebra packet send%s\n", - IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); - else - vty_out (vty, "debug zebra packet recv%s\n", - IS_ZEBRA_DEBUG_DETAIL ? " detail" : ""); - write++; + if (IS_ZEBRA_DEBUG_VXLAN) { + vty_out(vty, "debug zebra vxlan\n"); + write++; } - } - if (IS_ZEBRA_DEBUG_KERNEL) - { - vty_out (vty, "debug zebra kernel\n"); - write++; - } - if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) - { - vty_out (vty, "debug zebra kernel msgdump recv\n"); - write++; - } - if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) - { - vty_out (vty, "debug zebra kernel msgdump send\n"); - write++; - } - /* Check here using flags as the 'macro' does an OR */ - if (CHECK_FLAG (zebra_debug_rib, ZEBRA_DEBUG_RIB)) - { - vty_out (vty, "debug zebra rib\n"); - write++; - } - if (CHECK_FLAG (zebra_debug_rib, ZEBRA_DEBUG_RIB_DETAILED)) - { - vty_out (vty, "debug zebra rib detailed\n"); - write++; - } - if (IS_ZEBRA_DEBUG_FPM) - { - vty_out (vty, "debug zebra fpm\n"); - write++; - } - if (IS_ZEBRA_DEBUG_NHT) - { - vty_out (vty, "debug zebra nht\n"); - write++; - } - if (IS_ZEBRA_DEBUG_MPLS) - { - vty_out (vty, "debug zebra mpls\n"); - write++; - } - if (IS_ZEBRA_DEBUG_VXLAN) - { - vty_out (vty, "debug zebra vxlan\n"); - write++; - } - return write; + return write; } -void -zebra_debug_init (void) +void zebra_debug_init(void) { - zebra_debug_event = 0; - zebra_debug_packet = 0; - zebra_debug_kernel = 0; - zebra_debug_rib = 0; - zebra_debug_fpm = 0; - zebra_debug_mpls = 0; - zebra_debug_vxlan = 0; - - install_node (&debug_node, config_write_debug); - - install_element (VIEW_NODE, &show_debugging_zebra_cmd); - - install_element (ENABLE_NODE, &debug_zebra_events_cmd); - install_element (ENABLE_NODE, &debug_zebra_nht_cmd); - install_element (ENABLE_NODE, &debug_zebra_mpls_cmd); - install_element (ENABLE_NODE, &debug_zebra_vxlan_cmd); - install_element (ENABLE_NODE, &debug_zebra_packet_cmd); - install_element (ENABLE_NODE, &debug_zebra_kernel_cmd); - install_element (ENABLE_NODE, &debug_zebra_kernel_msgdump_cmd); - install_element (ENABLE_NODE, &debug_zebra_rib_cmd); - install_element (ENABLE_NODE, &debug_zebra_rib_detailed_cmd); - install_element (ENABLE_NODE, &debug_zebra_fpm_cmd); - install_element (ENABLE_NODE, &no_debug_zebra_events_cmd); - install_element (ENABLE_NODE, &no_debug_zebra_nht_cmd); - install_element (ENABLE_NODE, &no_debug_zebra_mpls_cmd); - install_element (ENABLE_NODE, &no_debug_zebra_vxlan_cmd); - install_element (ENABLE_NODE, &no_debug_zebra_packet_cmd); - install_element (ENABLE_NODE, &no_debug_zebra_kernel_cmd); - install_element (ENABLE_NODE, &no_debug_zebra_kernel_msgdump_cmd); - install_element (ENABLE_NODE, &no_debug_zebra_rib_cmd); - install_element (ENABLE_NODE, &no_debug_zebra_rib_detailed_cmd); - install_element (ENABLE_NODE, &no_debug_zebra_fpm_cmd); - - install_element (CONFIG_NODE, &debug_zebra_events_cmd); - install_element (CONFIG_NODE, &debug_zebra_nht_cmd); - install_element (CONFIG_NODE, &debug_zebra_mpls_cmd); - install_element (CONFIG_NODE, &debug_zebra_vxlan_cmd); - install_element (CONFIG_NODE, &debug_zebra_packet_cmd); - install_element (CONFIG_NODE, &debug_zebra_kernel_cmd); - install_element (CONFIG_NODE, &debug_zebra_kernel_msgdump_cmd); - install_element (CONFIG_NODE, &debug_zebra_rib_cmd); - install_element (CONFIG_NODE, &debug_zebra_rib_detailed_cmd); - install_element (CONFIG_NODE, &debug_zebra_fpm_cmd); - install_element (CONFIG_NODE, &no_debug_zebra_events_cmd); - install_element (CONFIG_NODE, &no_debug_zebra_nht_cmd); - install_element (CONFIG_NODE, &no_debug_zebra_mpls_cmd); - install_element (CONFIG_NODE, &no_debug_zebra_vxlan_cmd); - install_element (CONFIG_NODE, &no_debug_zebra_packet_cmd); - install_element (CONFIG_NODE, &no_debug_zebra_kernel_cmd); - install_element (CONFIG_NODE, &no_debug_zebra_kernel_msgdump_cmd); - install_element (CONFIG_NODE, &no_debug_zebra_rib_cmd); - install_element (CONFIG_NODE, &no_debug_zebra_rib_detailed_cmd); - install_element (CONFIG_NODE, &no_debug_zebra_fpm_cmd); + zebra_debug_event = 0; + zebra_debug_packet = 0; + zebra_debug_kernel = 0; + zebra_debug_rib = 0; + zebra_debug_fpm = 0; + zebra_debug_mpls = 0; + zebra_debug_vxlan = 0; + + install_node(&debug_node, config_write_debug); + + install_element(VIEW_NODE, &show_debugging_zebra_cmd); + + install_element(ENABLE_NODE, &debug_zebra_events_cmd); + install_element(ENABLE_NODE, &debug_zebra_nht_cmd); + install_element(ENABLE_NODE, &debug_zebra_mpls_cmd); + install_element(ENABLE_NODE, &debug_zebra_vxlan_cmd); + install_element(ENABLE_NODE, &debug_zebra_packet_cmd); + install_element(ENABLE_NODE, &debug_zebra_kernel_cmd); + install_element(ENABLE_NODE, &debug_zebra_kernel_msgdump_cmd); + install_element(ENABLE_NODE, &debug_zebra_rib_cmd); + install_element(ENABLE_NODE, &debug_zebra_rib_detailed_cmd); + install_element(ENABLE_NODE, &debug_zebra_fpm_cmd); + install_element(ENABLE_NODE, &no_debug_zebra_events_cmd); + install_element(ENABLE_NODE, &no_debug_zebra_nht_cmd); + install_element(ENABLE_NODE, &no_debug_zebra_mpls_cmd); + install_element(ENABLE_NODE, &no_debug_zebra_vxlan_cmd); + install_element(ENABLE_NODE, &no_debug_zebra_packet_cmd); + install_element(ENABLE_NODE, &no_debug_zebra_kernel_cmd); + install_element(ENABLE_NODE, &no_debug_zebra_kernel_msgdump_cmd); + install_element(ENABLE_NODE, &no_debug_zebra_rib_cmd); + install_element(ENABLE_NODE, &no_debug_zebra_rib_detailed_cmd); + install_element(ENABLE_NODE, &no_debug_zebra_fpm_cmd); + + install_element(CONFIG_NODE, &debug_zebra_events_cmd); + install_element(CONFIG_NODE, &debug_zebra_nht_cmd); + install_element(CONFIG_NODE, &debug_zebra_mpls_cmd); + install_element(CONFIG_NODE, &debug_zebra_vxlan_cmd); + install_element(CONFIG_NODE, &debug_zebra_packet_cmd); + install_element(CONFIG_NODE, &debug_zebra_kernel_cmd); + install_element(CONFIG_NODE, &debug_zebra_kernel_msgdump_cmd); + install_element(CONFIG_NODE, &debug_zebra_rib_cmd); + install_element(CONFIG_NODE, &debug_zebra_rib_detailed_cmd); + install_element(CONFIG_NODE, &debug_zebra_fpm_cmd); + install_element(CONFIG_NODE, &no_debug_zebra_events_cmd); + install_element(CONFIG_NODE, &no_debug_zebra_nht_cmd); + install_element(CONFIG_NODE, &no_debug_zebra_mpls_cmd); + install_element(CONFIG_NODE, &no_debug_zebra_vxlan_cmd); + install_element(CONFIG_NODE, &no_debug_zebra_packet_cmd); + install_element(CONFIG_NODE, &no_debug_zebra_kernel_cmd); + install_element(CONFIG_NODE, &no_debug_zebra_kernel_msgdump_cmd); + install_element(CONFIG_NODE, &no_debug_zebra_rib_cmd); + install_element(CONFIG_NODE, &no_debug_zebra_rib_detailed_cmd); + install_element(CONFIG_NODE, &no_debug_zebra_fpm_cmd); } diff --git a/zebra/debug.h b/zebra/debug.h index 5687a3516..b52bb7d0e 100644 --- a/zebra/debug.h +++ b/zebra/debug.h @@ -53,13 +53,13 @@ #define IS_ZEBRA_DEBUG_DETAIL (zebra_debug_packet & ZEBRA_DEBUG_DETAIL) #define IS_ZEBRA_DEBUG_KERNEL (zebra_debug_kernel & ZEBRA_DEBUG_KERNEL) -#define IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND \ - (zebra_debug_kernel & ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) -#define IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV \ - (zebra_debug_kernel & ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) +#define IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND \ + (zebra_debug_kernel & ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) +#define IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV \ + (zebra_debug_kernel & ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) -#define IS_ZEBRA_DEBUG_RIB \ - (zebra_debug_rib & (ZEBRA_DEBUG_RIB | ZEBRA_DEBUG_RIB_DETAILED)) +#define IS_ZEBRA_DEBUG_RIB \ + (zebra_debug_rib & (ZEBRA_DEBUG_RIB | ZEBRA_DEBUG_RIB_DETAILED)) #define IS_ZEBRA_DEBUG_RIB_DETAILED (zebra_debug_rib & ZEBRA_DEBUG_RIB_DETAILED) #define IS_ZEBRA_DEBUG_FPM (zebra_debug_fpm & ZEBRA_DEBUG_FPM) @@ -76,6 +76,6 @@ extern unsigned long zebra_debug_nht; extern unsigned long zebra_debug_mpls; extern unsigned long zebra_debug_vxlan; -extern void zebra_debug_init (void); +extern void zebra_debug_init(void); #endif /* _ZEBRA_DEBUG_H */ diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c index 73da04965..2d5d604a8 100644 --- a/zebra/if_ioctl.c +++ b/zebra/if_ioctl.c @@ -38,306 +38,293 @@ #include /* Interface looking up using infamous SIOCGIFCONF. */ -static int -interface_list_ioctl (void) +static int interface_list_ioctl(void) { - int ret; - int sock; + int ret; + int sock; #define IFNUM_BASE 32 - int ifnum; - struct ifreq *ifreq; - struct ifconf ifconf; - struct interface *ifp; - int n; - int lastlen; - - /* Normally SIOCGIFCONF works with AF_INET socket. */ - sock = socket (AF_INET, SOCK_DGRAM, 0); - if (sock < 0) - { - zlog_warn ("Can't make AF_INET socket stream: %s", safe_strerror (errno)); - return -1; - } - - /* Set initial ifreq count. This will be double when SIOCGIFCONF - fail. Solaris has SIOCGIFNUM. */ + int ifnum; + struct ifreq *ifreq; + struct ifconf ifconf; + struct interface *ifp; + int n; + int lastlen; + + /* Normally SIOCGIFCONF works with AF_INET socket. */ + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + zlog_warn("Can't make AF_INET socket stream: %s", + safe_strerror(errno)); + return -1; + } + +/* Set initial ifreq count. This will be double when SIOCGIFCONF + fail. Solaris has SIOCGIFNUM. */ #ifdef SIOCGIFNUM - ret = ioctl (sock, SIOCGIFNUM, &ifnum); - if (ret < 0) - ifnum = IFNUM_BASE; - else - ifnum++; + ret = ioctl(sock, SIOCGIFNUM, &ifnum); + if (ret < 0) + ifnum = IFNUM_BASE; + else + ifnum++; #else - ifnum = IFNUM_BASE; + ifnum = IFNUM_BASE; #endif /* SIOCGIFNUM */ - ifconf.ifc_buf = NULL; - - lastlen = 0; - /* Loop until SIOCGIFCONF success. */ - for (;;) - { - ifconf.ifc_len = sizeof (struct ifreq) * ifnum; - ifconf.ifc_buf = XREALLOC(MTYPE_TMP, ifconf.ifc_buf, ifconf.ifc_len); - - ret = ioctl(sock, SIOCGIFCONF, &ifconf); - - if (ret < 0) - { - zlog_warn ("SIOCGIFCONF: %s", safe_strerror(errno)); - goto end; - } - /* Repeatedly get info til buffer fails to grow. */ - if (ifconf.ifc_len > lastlen) - { - lastlen = ifconf.ifc_len; - ifnum += 10; - continue; + ifconf.ifc_buf = NULL; + + lastlen = 0; + /* Loop until SIOCGIFCONF success. */ + for (;;) { + ifconf.ifc_len = sizeof(struct ifreq) * ifnum; + ifconf.ifc_buf = + XREALLOC(MTYPE_TMP, ifconf.ifc_buf, ifconf.ifc_len); + + ret = ioctl(sock, SIOCGIFCONF, &ifconf); + + if (ret < 0) { + zlog_warn("SIOCGIFCONF: %s", safe_strerror(errno)); + goto end; + } + /* Repeatedly get info til buffer fails to grow. */ + if (ifconf.ifc_len > lastlen) { + lastlen = ifconf.ifc_len; + ifnum += 10; + continue; + } + /* Success. */ + break; } - /* Success. */ - break; - } - /* Allocate interface. */ - ifreq = ifconf.ifc_req; + /* Allocate interface. */ + ifreq = ifconf.ifc_req; #ifdef OPEN_BSD - for (n = 0; n < ifconf.ifc_len; ) - { - unsigned int size; - - ifreq = (struct ifreq *)((caddr_t) ifconf.ifc_req + n); - ifp = if_get_by_name_len(ifreq->ifr_name, - strnlen(ifreq->ifr_name, - sizeof(ifreq->ifr_name)), - VRF_DEFAULT, 0); - if_add_update (ifp); - size = ifreq->ifr_addr.sa_len; - if (size < sizeof (ifreq->ifr_addr)) - size = sizeof (ifreq->ifr_addr); - size += sizeof (ifreq->ifr_name); - n += size; - } + for (n = 0; n < ifconf.ifc_len;) { + unsigned int size; + + ifreq = (struct ifreq *)((caddr_t)ifconf.ifc_req + n); + ifp = if_get_by_name_len( + ifreq->ifr_name, + strnlen(ifreq->ifr_name, sizeof(ifreq->ifr_name)), + VRF_DEFAULT, 0); + if_add_update(ifp); + size = ifreq->ifr_addr.sa_len; + if (size < sizeof(ifreq->ifr_addr)) + size = sizeof(ifreq->ifr_addr); + size += sizeof(ifreq->ifr_name); + n += size; + } #else - for (n = 0; n < ifconf.ifc_len; n += sizeof(struct ifreq)) - { - ifp = if_get_by_name_len(ifreq->ifr_name, - strnlen(ifreq->ifr_name, - sizeof(ifreq->ifr_name)), - VRF_DEFAULT, 0); - if_add_update (ifp); - ifreq++; - } + for (n = 0; n < ifconf.ifc_len; n += sizeof(struct ifreq)) { + ifp = if_get_by_name_len( + ifreq->ifr_name, + strnlen(ifreq->ifr_name, sizeof(ifreq->ifr_name)), + VRF_DEFAULT, 0); + if_add_update(ifp); + ifreq++; + } #endif /* OPEN_BSD */ - end: - close (sock); - XFREE (MTYPE_TMP, ifconf.ifc_buf); +end: + close(sock); + XFREE(MTYPE_TMP, ifconf.ifc_buf); - return ret; + return ret; } /* Get interface's index by ioctl. */ -static int -if_get_index (struct interface *ifp) +static int if_get_index(struct interface *ifp) { - ifp->ifindex = if_nametoindex(ifp->name); - return ifp->ifindex; + ifp->ifindex = if_nametoindex(ifp->name); + return ifp->ifindex; } #ifdef SIOCGIFHWADDR -static int -if_get_hwaddr (struct interface *ifp) +static int if_get_hwaddr(struct interface *ifp) { - int ret; - struct ifreq ifreq; - int i; - - strncpy (ifreq.ifr_name, ifp->name, IFNAMSIZ); - ifreq.ifr_addr.sa_family = AF_INET; - - /* Fetch Hardware address if available. */ - ret = if_ioctl (SIOCGIFHWADDR, (caddr_t) &ifreq); - if (ret < 0) - ifp->hw_addr_len = 0; - else - { - memcpy (ifp->hw_addr, ifreq.ifr_hwaddr.sa_data, 6); - - for (i = 0; i < 6; i++) - if (ifp->hw_addr[i] != 0) - break; - - if (i == 6) - ifp->hw_addr_len = 0; - else - ifp->hw_addr_len = 6; - } - return 0; + int ret; + struct ifreq ifreq; + int i; + + strncpy(ifreq.ifr_name, ifp->name, IFNAMSIZ); + ifreq.ifr_addr.sa_family = AF_INET; + + /* Fetch Hardware address if available. */ + ret = if_ioctl(SIOCGIFHWADDR, (caddr_t)&ifreq); + if (ret < 0) + ifp->hw_addr_len = 0; + else { + memcpy(ifp->hw_addr, ifreq.ifr_hwaddr.sa_data, 6); + + for (i = 0; i < 6; i++) + if (ifp->hw_addr[i] != 0) + break; + + if (i == 6) + ifp->hw_addr_len = 0; + else + ifp->hw_addr_len = 6; + } + return 0; } #endif /* SIOCGIFHWADDR */ -static int -if_getaddrs (void) +static int if_getaddrs(void) { - int ret; - struct ifaddrs *ifap; - struct ifaddrs *ifapfree; - struct interface *ifp; - int prefixlen; - - ret = getifaddrs (&ifap); - if (ret != 0) - { - zlog_err ("getifaddrs(): %s", safe_strerror (errno)); - return -1; - } - - for (ifapfree = ifap; ifap; ifap = ifap->ifa_next) - { - if (ifap->ifa_addr == NULL) - { - zlog_err ("%s: nonsensical ifaddr with NULL ifa_addr, ifname %s", - __func__, (ifap->ifa_name ? ifap->ifa_name : "(null)")); - continue; - } - - ifp = if_lookup_by_name (ifap->ifa_name, VRF_DEFAULT); - if (ifp == NULL) - { - zlog_err ("if_getaddrs(): Can't lookup interface %s\n", - ifap->ifa_name); - continue; + int ret; + struct ifaddrs *ifap; + struct ifaddrs *ifapfree; + struct interface *ifp; + int prefixlen; + + ret = getifaddrs(&ifap); + if (ret != 0) { + zlog_err("getifaddrs(): %s", safe_strerror(errno)); + return -1; } - if (ifap->ifa_addr->sa_family == AF_INET) - { - struct sockaddr_in *addr; - struct sockaddr_in *mask; - struct sockaddr_in *dest; - struct in_addr *dest_pnt; - int flags = 0; - - addr = (struct sockaddr_in *) ifap->ifa_addr; - mask = (struct sockaddr_in *) ifap->ifa_netmask; - prefixlen = ip_masklen (mask->sin_addr); - - dest_pnt = NULL; - - if (ifap->ifa_dstaddr && - !IPV4_ADDR_SAME(&addr->sin_addr, - &((struct sockaddr_in *) - ifap->ifa_dstaddr)->sin_addr)) - { - dest = (struct sockaddr_in *) ifap->ifa_dstaddr; - dest_pnt = &dest->sin_addr; - flags = ZEBRA_IFA_PEER; - } - else if (ifap->ifa_broadaddr && - !IPV4_ADDR_SAME(&addr->sin_addr, - &((struct sockaddr_in *) - ifap->ifa_broadaddr)->sin_addr)) - { - dest = (struct sockaddr_in *) ifap->ifa_broadaddr; - dest_pnt = &dest->sin_addr; - } - - connected_add_ipv4 (ifp, flags, &addr->sin_addr, - prefixlen, dest_pnt, NULL); - } - if (ifap->ifa_addr->sa_family == AF_INET6) - { - struct sockaddr_in6 *addr; - struct sockaddr_in6 *mask; - struct sockaddr_in6 *dest; - struct in6_addr *dest_pnt; - int flags = 0; - - addr = (struct sockaddr_in6 *) ifap->ifa_addr; - mask = (struct sockaddr_in6 *) ifap->ifa_netmask; - prefixlen = ip6_masklen (mask->sin6_addr); - - dest_pnt = NULL; - - if (ifap->ifa_dstaddr && - !IPV6_ADDR_SAME(&addr->sin6_addr, - &((struct sockaddr_in6 *) - ifap->ifa_dstaddr)->sin6_addr)) - { - dest = (struct sockaddr_in6 *) ifap->ifa_dstaddr; - dest_pnt = &dest->sin6_addr; - flags = ZEBRA_IFA_PEER; - } - else if (ifap->ifa_broadaddr && - !IPV6_ADDR_SAME(&addr->sin6_addr, - &((struct sockaddr_in6 *) - ifap->ifa_broadaddr)->sin6_addr)) - { - dest = (struct sockaddr_in6 *) ifap->ifa_broadaddr; - dest_pnt = &dest->sin6_addr; - } + for (ifapfree = ifap; ifap; ifap = ifap->ifa_next) { + if (ifap->ifa_addr == NULL) { + zlog_err( + "%s: nonsensical ifaddr with NULL ifa_addr, ifname %s", + __func__, + (ifap->ifa_name ? ifap->ifa_name : "(null)")); + continue; + } + + ifp = if_lookup_by_name(ifap->ifa_name, VRF_DEFAULT); + if (ifp == NULL) { + zlog_err("if_getaddrs(): Can't lookup interface %s\n", + ifap->ifa_name); + continue; + } + + if (ifap->ifa_addr->sa_family == AF_INET) { + struct sockaddr_in *addr; + struct sockaddr_in *mask; + struct sockaddr_in *dest; + struct in_addr *dest_pnt; + int flags = 0; + + addr = (struct sockaddr_in *)ifap->ifa_addr; + mask = (struct sockaddr_in *)ifap->ifa_netmask; + prefixlen = ip_masklen(mask->sin_addr); + + dest_pnt = NULL; + + if (ifap->ifa_dstaddr + && !IPV4_ADDR_SAME(&addr->sin_addr, + &((struct sockaddr_in *) + ifap->ifa_dstaddr) + ->sin_addr)) { + dest = (struct sockaddr_in *)ifap->ifa_dstaddr; + dest_pnt = &dest->sin_addr; + flags = ZEBRA_IFA_PEER; + } else if (ifap->ifa_broadaddr + && !IPV4_ADDR_SAME( + &addr->sin_addr, + &((struct sockaddr_in *) + ifap->ifa_broadaddr) + ->sin_addr)) { + dest = (struct sockaddr_in *) + ifap->ifa_broadaddr; + dest_pnt = &dest->sin_addr; + } + + connected_add_ipv4(ifp, flags, &addr->sin_addr, + prefixlen, dest_pnt, NULL); + } + if (ifap->ifa_addr->sa_family == AF_INET6) { + struct sockaddr_in6 *addr; + struct sockaddr_in6 *mask; + struct sockaddr_in6 *dest; + struct in6_addr *dest_pnt; + int flags = 0; + + addr = (struct sockaddr_in6 *)ifap->ifa_addr; + mask = (struct sockaddr_in6 *)ifap->ifa_netmask; + prefixlen = ip6_masklen(mask->sin6_addr); + + dest_pnt = NULL; + + if (ifap->ifa_dstaddr + && !IPV6_ADDR_SAME(&addr->sin6_addr, + &((struct sockaddr_in6 *) + ifap->ifa_dstaddr) + ->sin6_addr)) { + dest = (struct sockaddr_in6 *)ifap->ifa_dstaddr; + dest_pnt = &dest->sin6_addr; + flags = ZEBRA_IFA_PEER; + } else if (ifap->ifa_broadaddr + && !IPV6_ADDR_SAME( + &addr->sin6_addr, + &((struct sockaddr_in6 *) + ifap->ifa_broadaddr) + ->sin6_addr)) { + dest = (struct sockaddr_in6 *) + ifap->ifa_broadaddr; + dest_pnt = &dest->sin6_addr; + } #if defined(KAME) - if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) - { - addr->sin6_scope_id = - ntohs(*(u_int16_t *)&addr->sin6_addr.s6_addr[2]); - addr->sin6_addr.s6_addr[2] = addr->sin6_addr.s6_addr[3] = 0; - } -#endif - - connected_add_ipv6 (ifp, flags, &addr->sin6_addr, prefixlen, - dest_pnt, NULL); + if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) { + addr->sin6_scope_id = + ntohs(*(u_int16_t *)&addr->sin6_addr + .s6_addr[2]); + addr->sin6_addr.s6_addr[2] = + addr->sin6_addr.s6_addr[3] = 0; + } +#endif + + connected_add_ipv6(ifp, flags, &addr->sin6_addr, + prefixlen, dest_pnt, NULL); + } } - } - freeifaddrs (ifapfree); + freeifaddrs(ifapfree); - return 0; + return 0; } /* Fetch interface information via ioctl(). */ -static void -interface_info_ioctl () +static void interface_info_ioctl() { - struct listnode *node, *nnode; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp)) - { - if_get_index (ifp); + struct listnode *node, *nnode; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), node, nnode, ifp)) { + if_get_index(ifp); #ifdef SIOCGIFHWADDR - if_get_hwaddr (ifp); + if_get_hwaddr(ifp); #endif /* SIOCGIFHWADDR */ - if_get_flags (ifp); - if_get_mtu (ifp); - if_get_metric (ifp); - } + if_get_flags(ifp); + if_get_mtu(ifp); + if_get_metric(ifp); + } } /* Lookup all interface information. */ -void -interface_list (struct zebra_ns *zns) +void interface_list(struct zebra_ns *zns) { - zlog_info ("interface_list: NS %u", zns->ns_id); + zlog_info("interface_list: NS %u", zns->ns_id); - /* Linux can do both proc & ioctl, ioctl is the only way to get - interface aliases in 2.2 series kernels. */ +/* Linux can do both proc & ioctl, ioctl is the only way to get + interface aliases in 2.2 series kernels. */ #ifdef HAVE_PROC_NET_DEV - interface_list_proc (); + interface_list_proc(); #endif /* HAVE_PROC_NET_DEV */ - interface_list_ioctl (); + interface_list_ioctl(); - /* After listing is done, get index, address, flags and other - interface's information. */ - interface_info_ioctl (); + /* After listing is done, get index, address, flags and other + interface's information. */ + interface_info_ioctl(); - if_getaddrs (); + if_getaddrs(); #if defined(HAVE_PROC_NET_IF_INET6) - /* Linux provides interface's IPv6 address via - /proc/net/if_inet6. */ - ifaddr_proc_ipv6 (); + /* Linux provides interface's IPv6 address via + /proc/net/if_inet6. */ + ifaddr_proc_ipv6(); #endif /* HAVE_PROC_NET_IF_INET6 */ } diff --git a/zebra/if_ioctl_solaris.c b/zebra/if_ioctl_solaris.c index 08af2aa35..fce36ebc1 100644 --- a/zebra/if_ioctl_solaris.c +++ b/zebra/if_ioctl_solaris.c @@ -37,338 +37,324 @@ #include "zebra/ioctl_solaris.h" #include "zebra/rib.h" -static int if_get_addr (struct interface *, struct sockaddr *, const char *); -static void interface_info_ioctl (struct interface *); +static int if_get_addr(struct interface *, struct sockaddr *, const char *); +static void interface_info_ioctl(struct interface *); extern struct zebra_privs_t zserv_privs; -static int -interface_list_ioctl (int af) +static int interface_list_ioctl(int af) { - int ret; - int sock; + int ret; + int sock; #define IFNUM_BASE 32 - struct lifnum lifn; - int ifnum; - struct lifreq *lifreq; - struct lifconf lifconf; - struct interface *ifp; - int n; - int save_errno; - size_t needed, lastneeded = 0; - char *buf = NULL; - - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - - sock = socket (af, SOCK_DGRAM, 0); - if (sock < 0) - { - zlog_warn ("Can't make %s socket stream: %s", - (af == AF_INET ? "AF_INET" : "AF_INET6"), safe_strerror (errno)); - - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - - return -1; - } - -calculate_lifc_len: /* must hold privileges to enter here */ - lifn.lifn_family = af; - lifn.lifn_flags = LIFC_NOXMIT; /* we want NOXMIT interfaces too */ - ret = ioctl (sock, SIOCGLIFNUM, &lifn); - save_errno = errno; - - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - - if (ret < 0) - { - zlog_warn ("interface_list_ioctl: SIOCGLIFNUM failed %s", - safe_strerror (save_errno)); - close (sock); - return -1; - } - ifnum = lifn.lifn_count; - - /* - * When calculating the buffer size needed, add a small number - * of interfaces to those we counted. We do this to capture - * the interface status of potential interfaces which may have - * been plumbed between the SIOCGLIFNUM and the SIOCGLIFCONF. - */ - needed = (ifnum + 4) * sizeof (struct lifreq); - if (needed > lastneeded || needed < lastneeded / 2) - { - if (buf != NULL) - XFREE (MTYPE_TMP, buf); - if ((buf = XMALLOC (MTYPE_TMP, needed)) == NULL) - { - zlog_warn ("interface_list_ioctl: malloc failed"); - close (sock); - return -1; - } - } - lastneeded = needed; - - lifconf.lifc_family = af; - lifconf.lifc_flags = LIFC_NOXMIT; - lifconf.lifc_len = needed; - lifconf.lifc_buf = buf; - - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - - ret = ioctl (sock, SIOCGLIFCONF, &lifconf); - - if (ret < 0) - { - if (errno == EINVAL) - goto calculate_lifc_len; /* deliberately hold privileges */ - - zlog_warn ("SIOCGLIFCONF: %s", safe_strerror (errno)); - - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - - goto end; - } - - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - - /* Allocate interface. */ - lifreq = lifconf.lifc_req; - - for (n = 0; n < lifconf.lifc_len; n += sizeof (struct lifreq)) - { - /* we treat Solaris logical interfaces as addresses, because that is - * how PF_ROUTE on Solaris treats them. Hence we can not directly use - * the lifreq_name to get the ifp. We need to normalise the name - * before attempting get. - * - * Solaris logical interface names are in the form of: - * : - */ - unsigned int normallen = 0; - uint64_t lifflags; - - /* We should exclude ~IFF_UP interfaces, as we'll find out about them - * coming up later through RTM_NEWADDR message on the route socket. - */ - if (if_get_flags_direct (lifreq->lifr_name, &lifflags, - lifreq->lifr_addr.ss_family) - || !CHECK_FLAG (lifflags, IFF_UP)) - { - lifreq++; - continue; - } - - /* Find the normalised name */ - while ( (normallen < sizeof(lifreq->lifr_name)) - && ( *(lifreq->lifr_name + normallen) != '\0') - && ( *(lifreq->lifr_name + normallen) != ':') ) - normallen++; - - ifp = if_get_by_name_len(lifreq->lifr_name, normallen, VRF_DEFAULT, 0); - - if (lifreq->lifr_addr.ss_family == AF_INET) - ifp->flags |= IFF_IPV4; - - if (lifreq->lifr_addr.ss_family == AF_INET6) - { - ifp->flags |= IFF_IPV6; - } - - if_add_update (ifp); - - interface_info_ioctl (ifp); - - /* If a logical interface pass the full name so it can be - * as a label on the address - */ - if ( *(lifreq->lifr_name + normallen) != '\0') - if_get_addr (ifp, (struct sockaddr *) &lifreq->lifr_addr, - lifreq->lifr_name); - else - if_get_addr (ifp, (struct sockaddr *) &lifreq->lifr_addr, NULL); - - /* Poke the interface flags. Lets IFF_UP mangling kick in */ - if_flags_update (ifp, ifp->flags); - - lifreq++; - } + struct lifnum lifn; + int ifnum; + struct lifreq *lifreq; + struct lifconf lifconf; + struct interface *ifp; + int n; + int save_errno; + size_t needed, lastneeded = 0; + char *buf = NULL; + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + + sock = socket(af, SOCK_DGRAM, 0); + if (sock < 0) { + zlog_warn("Can't make %s socket stream: %s", + (af == AF_INET ? "AF_INET" : "AF_INET6"), + safe_strerror(errno)); + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + return -1; + } + +calculate_lifc_len: /* must hold privileges to enter here */ + lifn.lifn_family = af; + lifn.lifn_flags = LIFC_NOXMIT; /* we want NOXMIT interfaces too */ + ret = ioctl(sock, SIOCGLIFNUM, &lifn); + save_errno = errno; + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + if (ret < 0) { + zlog_warn("interface_list_ioctl: SIOCGLIFNUM failed %s", + safe_strerror(save_errno)); + close(sock); + return -1; + } + ifnum = lifn.lifn_count; + + /* + * When calculating the buffer size needed, add a small number + * of interfaces to those we counted. We do this to capture + * the interface status of potential interfaces which may have + * been plumbed between the SIOCGLIFNUM and the SIOCGLIFCONF. + */ + needed = (ifnum + 4) * sizeof(struct lifreq); + if (needed > lastneeded || needed < lastneeded / 2) { + if (buf != NULL) + XFREE(MTYPE_TMP, buf); + if ((buf = XMALLOC(MTYPE_TMP, needed)) == NULL) { + zlog_warn("interface_list_ioctl: malloc failed"); + close(sock); + return -1; + } + } + lastneeded = needed; + + lifconf.lifc_family = af; + lifconf.lifc_flags = LIFC_NOXMIT; + lifconf.lifc_len = needed; + lifconf.lifc_buf = buf; + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + + ret = ioctl(sock, SIOCGLIFCONF, &lifconf); + + if (ret < 0) { + if (errno == EINVAL) + goto calculate_lifc_len; /* deliberately hold privileges + */ + + zlog_warn("SIOCGLIFCONF: %s", safe_strerror(errno)); + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + goto end; + } + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + /* Allocate interface. */ + lifreq = lifconf.lifc_req; + + for (n = 0; n < lifconf.lifc_len; n += sizeof(struct lifreq)) { + /* we treat Solaris logical interfaces as addresses, because + * that is + * how PF_ROUTE on Solaris treats them. Hence we can not + * directly use + * the lifreq_name to get the ifp. We need to normalise the + * name + * before attempting get. + * + * Solaris logical interface names are in the form of: + * : + */ + unsigned int normallen = 0; + uint64_t lifflags; + + /* We should exclude ~IFF_UP interfaces, as we'll find out about + * them + * coming up later through RTM_NEWADDR message on the route + * socket. + */ + if (if_get_flags_direct(lifreq->lifr_name, &lifflags, + lifreq->lifr_addr.ss_family) + || !CHECK_FLAG(lifflags, IFF_UP)) { + lifreq++; + continue; + } + + /* Find the normalised name */ + while ((normallen < sizeof(lifreq->lifr_name)) + && (*(lifreq->lifr_name + normallen) != '\0') + && (*(lifreq->lifr_name + normallen) != ':')) + normallen++; + + ifp = if_get_by_name_len(lifreq->lifr_name, normallen, + VRF_DEFAULT, 0); + + if (lifreq->lifr_addr.ss_family == AF_INET) + ifp->flags |= IFF_IPV4; + + if (lifreq->lifr_addr.ss_family == AF_INET6) { + ifp->flags |= IFF_IPV6; + } + + if_add_update(ifp); + + interface_info_ioctl(ifp); + + /* If a logical interface pass the full name so it can be + * as a label on the address + */ + if (*(lifreq->lifr_name + normallen) != '\0') + if_get_addr(ifp, (struct sockaddr *)&lifreq->lifr_addr, + lifreq->lifr_name); + else + if_get_addr(ifp, (struct sockaddr *)&lifreq->lifr_addr, + NULL); + + /* Poke the interface flags. Lets IFF_UP mangling kick in */ + if_flags_update(ifp, ifp->flags); + + lifreq++; + } end: - close (sock); - XFREE (MTYPE_TMP, lifconf.lifc_buf); - return ret; + close(sock); + XFREE(MTYPE_TMP, lifconf.lifc_buf); + return ret; } /* Get interface's index by ioctl. */ -static int -if_get_index (struct interface *ifp) +static int if_get_index(struct interface *ifp) { - int ret; - struct lifreq lifreq; + int ret; + struct lifreq lifreq; - lifreq_set_name (&lifreq, ifp->name); + lifreq_set_name(&lifreq, ifp->name); - if (ifp->flags & IFF_IPV4) - ret = AF_IOCTL (AF_INET, SIOCGLIFINDEX, (caddr_t) & lifreq); - else if (ifp->flags & IFF_IPV6) - ret = AF_IOCTL (AF_INET6, SIOCGLIFINDEX, (caddr_t) & lifreq); - else - ret = -1; + if (ifp->flags & IFF_IPV4) + ret = AF_IOCTL(AF_INET, SIOCGLIFINDEX, (caddr_t)&lifreq); + else if (ifp->flags & IFF_IPV6) + ret = AF_IOCTL(AF_INET6, SIOCGLIFINDEX, (caddr_t)&lifreq); + else + ret = -1; - if (ret < 0) - { - zlog_warn ("SIOCGLIFINDEX(%s) failed", ifp->name); - return ret; - } + if (ret < 0) { + zlog_warn("SIOCGLIFINDEX(%s) failed", ifp->name); + return ret; + } - /* OK we got interface index. */ +/* OK we got interface index. */ #ifdef ifr_ifindex - ifp->ifindex = lifreq.lifr_ifindex; + ifp->ifindex = lifreq.lifr_ifindex; #else - ifp->ifindex = lifreq.lifr_index; + ifp->ifindex = lifreq.lifr_index; #endif - return ifp->ifindex; - + return ifp->ifindex; } /* Interface address lookup by ioctl. This function only looks up IPv4 address. */ -#define ADDRLEN(sa) (((sa)->sa_family == AF_INET ? \ - sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6))) +#define ADDRLEN(sa) \ + (((sa)->sa_family == AF_INET ? sizeof(struct sockaddr_in) \ + : sizeof(struct sockaddr_in6))) #define SIN(s) ((struct sockaddr_in *)(s)) #define SIN6(s) ((struct sockaddr_in6 *)(s)) /* Retrieve address information for the given ifp */ -static int -if_get_addr (struct interface *ifp, struct sockaddr *addr, const char *label) +static int if_get_addr(struct interface *ifp, struct sockaddr *addr, + const char *label) { - int ret; - struct lifreq lifreq; - struct sockaddr_storage mask, dest; - char *dest_pnt = NULL; - u_char prefixlen = 0; - afi_t af; - int flags = 0; - - /* Interface's name and address family. - * We need to use the logical interface name / label, if we've been - * given one, in order to get the right address - */ - strncpy (lifreq.lifr_name, (label ? label : ifp->name), IFNAMSIZ); - - /* Interface's address. */ - memcpy (&lifreq.lifr_addr, addr, ADDRLEN (addr)); - af = addr->sa_family; - - /* Point to point or broad cast address pointer init. */ - dest_pnt = NULL; - - if (AF_IOCTL (af, SIOCGLIFDSTADDR, (caddr_t) & lifreq) >= 0) - { - memcpy (&dest, &lifreq.lifr_dstaddr, ADDRLEN (addr)); - if (af == AF_INET) - dest_pnt = (char *) &(SIN (&dest)->sin_addr); - else - dest_pnt = (char *) &(SIN6 (&dest)->sin6_addr); - flags = ZEBRA_IFA_PEER; - } - - if (af == AF_INET) - { - ret = if_ioctl (SIOCGLIFNETMASK, (caddr_t) & lifreq); - - if (ret < 0) - { - if (errno != EADDRNOTAVAIL) - { - zlog_warn ("SIOCGLIFNETMASK (%s) fail: %s", ifp->name, - safe_strerror (errno)); - return ret; - } - return 0; - } - memcpy (&mask, &lifreq.lifr_addr, ADDRLEN (addr)); - - prefixlen = ip_masklen (SIN (&mask)->sin_addr); - if (!dest_pnt && (if_ioctl (SIOCGLIFBRDADDR, (caddr_t) & lifreq) >= 0)) - { - memcpy (&dest, &lifreq.lifr_broadaddr, sizeof (struct sockaddr_in)); - dest_pnt = (char *) &SIN (&dest)->sin_addr; - } - } - else if (af == AF_INET6) - { - if (if_ioctl_ipv6 (SIOCGLIFSUBNET, (caddr_t) & lifreq) < 0) - { - if (ifp->flags & IFF_POINTOPOINT) - prefixlen = IPV6_MAX_BITLEN; - else - zlog_warn ("SIOCGLIFSUBNET (%s) fail: %s", - ifp->name, safe_strerror (errno)); + int ret; + struct lifreq lifreq; + struct sockaddr_storage mask, dest; + char *dest_pnt = NULL; + u_char prefixlen = 0; + afi_t af; + int flags = 0; + + /* Interface's name and address family. + * We need to use the logical interface name / label, if we've been + * given one, in order to get the right address + */ + strncpy(lifreq.lifr_name, (label ? label : ifp->name), IFNAMSIZ); + + /* Interface's address. */ + memcpy(&lifreq.lifr_addr, addr, ADDRLEN(addr)); + af = addr->sa_family; + + /* Point to point or broad cast address pointer init. */ + dest_pnt = NULL; + + if (AF_IOCTL(af, SIOCGLIFDSTADDR, (caddr_t)&lifreq) >= 0) { + memcpy(&dest, &lifreq.lifr_dstaddr, ADDRLEN(addr)); + if (af == AF_INET) + dest_pnt = (char *)&(SIN(&dest)->sin_addr); + else + dest_pnt = (char *)&(SIN6(&dest)->sin6_addr); + flags = ZEBRA_IFA_PEER; } - else - { - prefixlen = lifreq.lifr_addrlen; + + if (af == AF_INET) { + ret = if_ioctl(SIOCGLIFNETMASK, (caddr_t)&lifreq); + + if (ret < 0) { + if (errno != EADDRNOTAVAIL) { + zlog_warn("SIOCGLIFNETMASK (%s) fail: %s", + ifp->name, safe_strerror(errno)); + return ret; + } + return 0; + } + memcpy(&mask, &lifreq.lifr_addr, ADDRLEN(addr)); + + prefixlen = ip_masklen(SIN(&mask)->sin_addr); + if (!dest_pnt + && (if_ioctl(SIOCGLIFBRDADDR, (caddr_t)&lifreq) >= 0)) { + memcpy(&dest, &lifreq.lifr_broadaddr, + sizeof(struct sockaddr_in)); + dest_pnt = (char *)&SIN(&dest)->sin_addr; + } + } else if (af == AF_INET6) { + if (if_ioctl_ipv6(SIOCGLIFSUBNET, (caddr_t)&lifreq) < 0) { + if (ifp->flags & IFF_POINTOPOINT) + prefixlen = IPV6_MAX_BITLEN; + else + zlog_warn("SIOCGLIFSUBNET (%s) fail: %s", + ifp->name, safe_strerror(errno)); + } else { + prefixlen = lifreq.lifr_addrlen; + } } - } - /* Set address to the interface. */ - if (af == AF_INET) - connected_add_ipv4 (ifp, flags, &SIN (addr)->sin_addr, prefixlen, - (struct in_addr *) dest_pnt, label); - else if (af == AF_INET6) - connected_add_ipv6 (ifp, flags, &SIN6 (addr)->sin6_addr, prefixlen, - (struct in6_addr *) dest_pnt, label); + /* Set address to the interface. */ + if (af == AF_INET) + connected_add_ipv4(ifp, flags, &SIN(addr)->sin_addr, prefixlen, + (struct in_addr *)dest_pnt, label); + else if (af == AF_INET6) + connected_add_ipv6(ifp, flags, &SIN6(addr)->sin6_addr, + prefixlen, (struct in6_addr *)dest_pnt, + label); - return 0; + return 0; } /* Fetch interface information via ioctl(). */ -static void -interface_info_ioctl (struct interface *ifp) +static void interface_info_ioctl(struct interface *ifp) { - if_get_index (ifp); - if_get_flags (ifp); - if_get_mtu (ifp); - if_get_metric (ifp); + if_get_index(ifp); + if_get_flags(ifp); + if_get_mtu(ifp); + if_get_metric(ifp); } /* Lookup all interface information. */ -void -interface_list (struct zebra_ns *zns) +void interface_list(struct zebra_ns *zns) { - if (zns->ns_id != NS_DEFAULT) - { - zlog_warn ("interface_list: ignore NS %u", zns->ns_id); - return; - } - interface_list_ioctl (AF_INET); - interface_list_ioctl (AF_INET6); - interface_list_ioctl (AF_UNSPEC); + if (zns->ns_id != NS_DEFAULT) { + zlog_warn("interface_list: ignore NS %u", zns->ns_id); + return; + } + interface_list_ioctl(AF_INET); + interface_list_ioctl(AF_INET6); + interface_list_ioctl(AF_UNSPEC); } -struct connected * -if_lookup_linklocal (struct interface *ifp) +struct connected *if_lookup_linklocal(struct interface *ifp) { - struct listnode *node; - struct connected *ifc; + struct listnode *node; + struct connected *ifc; - if (ifp == NULL) - return NULL; + if (ifp == NULL) + return NULL; - for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) - { - if ((ifc->address->family == AF_INET6) && - (IN6_IS_ADDR_LINKLOCAL (&ifc->address->u.prefix6))) - return ifc; - } + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { + if ((ifc->address->family == AF_INET6) + && (IN6_IS_ADDR_LINKLOCAL(&ifc->address->u.prefix6))) + return ifc; + } - return NULL; + return NULL; } diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index d0907a267..acec2db52 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -66,143 +66,192 @@ /* Note: on netlink systems, there should be a 1-to-1 mapping between interface names and ifindex values. */ -static void -set_ifindex(struct interface *ifp, ifindex_t ifi_index, struct zebra_ns *zns) +static void set_ifindex(struct interface *ifp, ifindex_t ifi_index, + struct zebra_ns *zns) { - struct interface *oifp; - - if (((oifp = if_lookup_by_index_per_ns (zns, ifi_index)) != NULL) && (oifp != ifp)) - { - if (ifi_index == IFINDEX_INTERNAL) - zlog_err("Netlink is setting interface %s ifindex to reserved " - "internal value %u", ifp->name, ifi_index); - else - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("interface index %d was renamed from %s to %s", - ifi_index, oifp->name, ifp->name); - if (if_is_up(oifp)) - zlog_err("interface rename detected on up interface: index %d " - "was renamed from %s to %s, results are uncertain!", - ifi_index, oifp->name, ifp->name); - if_delete_update(oifp); - } - } - ifp->ifindex = ifi_index; + struct interface *oifp; + + if (((oifp = if_lookup_by_index_per_ns(zns, ifi_index)) != NULL) + && (oifp != ifp)) { + if (ifi_index == IFINDEX_INTERNAL) + zlog_err( + "Netlink is setting interface %s ifindex to reserved " + "internal value %u", + ifp->name, ifi_index); + else { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "interface index %d was renamed from %s to %s", + ifi_index, oifp->name, ifp->name); + if (if_is_up(oifp)) + zlog_err( + "interface rename detected on up interface: index %d " + "was renamed from %s to %s, results are uncertain!", + ifi_index, oifp->name, ifp->name); + if_delete_update(oifp); + } + } + ifp->ifindex = ifi_index; } /* Utility function to parse hardware link-layer address and update ifp */ -static void -netlink_interface_update_hw_addr (struct rtattr **tb, struct interface *ifp) +static void netlink_interface_update_hw_addr(struct rtattr **tb, + struct interface *ifp) { - int i; - - if (tb[IFLA_ADDRESS]) - { - int hw_addr_len; - - hw_addr_len = RTA_PAYLOAD (tb[IFLA_ADDRESS]); - - if (hw_addr_len > INTERFACE_HWADDR_MAX) - zlog_warn ("Hardware address is too large: %d", hw_addr_len); - else - { - ifp->hw_addr_len = hw_addr_len; - memcpy (ifp->hw_addr, RTA_DATA (tb[IFLA_ADDRESS]), hw_addr_len); - - for (i = 0; i < hw_addr_len; i++) - if (ifp->hw_addr[i] != 0) - break; - - if (i == hw_addr_len) - ifp->hw_addr_len = 0; - else - ifp->hw_addr_len = hw_addr_len; - } - } + int i; + + if (tb[IFLA_ADDRESS]) { + int hw_addr_len; + + hw_addr_len = RTA_PAYLOAD(tb[IFLA_ADDRESS]); + + if (hw_addr_len > INTERFACE_HWADDR_MAX) + zlog_warn("Hardware address is too large: %d", + hw_addr_len); + else { + ifp->hw_addr_len = hw_addr_len; + memcpy(ifp->hw_addr, RTA_DATA(tb[IFLA_ADDRESS]), + hw_addr_len); + + for (i = 0; i < hw_addr_len; i++) + if (ifp->hw_addr[i] != 0) + break; + + if (i == hw_addr_len) + ifp->hw_addr_len = 0; + else + ifp->hw_addr_len = hw_addr_len; + } + } } -static enum zebra_link_type -netlink_to_zebra_link_type (unsigned int hwt) +static enum zebra_link_type netlink_to_zebra_link_type(unsigned int hwt) { - switch (hwt) - { - case ARPHRD_ETHER: return ZEBRA_LLT_ETHER; - case ARPHRD_EETHER: return ZEBRA_LLT_EETHER; - case ARPHRD_AX25: return ZEBRA_LLT_AX25; - case ARPHRD_PRONET: return ZEBRA_LLT_PRONET; - case ARPHRD_IEEE802: return ZEBRA_LLT_IEEE802; - case ARPHRD_ARCNET: return ZEBRA_LLT_ARCNET; - case ARPHRD_APPLETLK: return ZEBRA_LLT_APPLETLK; - case ARPHRD_DLCI: return ZEBRA_LLT_DLCI; - case ARPHRD_ATM: return ZEBRA_LLT_ATM; - case ARPHRD_METRICOM: return ZEBRA_LLT_METRICOM; - case ARPHRD_IEEE1394: return ZEBRA_LLT_IEEE1394; - case ARPHRD_EUI64: return ZEBRA_LLT_EUI64; - case ARPHRD_INFINIBAND: return ZEBRA_LLT_INFINIBAND; - case ARPHRD_SLIP: return ZEBRA_LLT_SLIP; - case ARPHRD_CSLIP: return ZEBRA_LLT_CSLIP; - case ARPHRD_SLIP6: return ZEBRA_LLT_SLIP6; - case ARPHRD_CSLIP6: return ZEBRA_LLT_CSLIP6; - case ARPHRD_RSRVD: return ZEBRA_LLT_RSRVD; - case ARPHRD_ADAPT: return ZEBRA_LLT_ADAPT; - case ARPHRD_ROSE: return ZEBRA_LLT_ROSE; - case ARPHRD_X25: return ZEBRA_LLT_X25; - case ARPHRD_PPP: return ZEBRA_LLT_PPP; - case ARPHRD_CISCO: return ZEBRA_LLT_CHDLC; - case ARPHRD_LAPB: return ZEBRA_LLT_LAPB; - case ARPHRD_RAWHDLC: return ZEBRA_LLT_RAWHDLC; - case ARPHRD_TUNNEL: return ZEBRA_LLT_IPIP; - case ARPHRD_TUNNEL6: return ZEBRA_LLT_IPIP6; - case ARPHRD_FRAD: return ZEBRA_LLT_FRAD; - case ARPHRD_SKIP: return ZEBRA_LLT_SKIP; - case ARPHRD_LOOPBACK: return ZEBRA_LLT_LOOPBACK; - case ARPHRD_LOCALTLK: return ZEBRA_LLT_LOCALTLK; - case ARPHRD_FDDI: return ZEBRA_LLT_FDDI; - case ARPHRD_SIT: return ZEBRA_LLT_SIT; - case ARPHRD_IPDDP: return ZEBRA_LLT_IPDDP; - case ARPHRD_IPGRE: return ZEBRA_LLT_IPGRE; - case ARPHRD_PIMREG: return ZEBRA_LLT_PIMREG; - case ARPHRD_HIPPI: return ZEBRA_LLT_HIPPI; - case ARPHRD_ECONET: return ZEBRA_LLT_ECONET; - case ARPHRD_IRDA: return ZEBRA_LLT_IRDA; - case ARPHRD_FCPP: return ZEBRA_LLT_FCPP; - case ARPHRD_FCAL: return ZEBRA_LLT_FCAL; - case ARPHRD_FCPL: return ZEBRA_LLT_FCPL; - case ARPHRD_FCFABRIC: return ZEBRA_LLT_FCFABRIC; - case ARPHRD_IEEE802_TR: return ZEBRA_LLT_IEEE802_TR; - case ARPHRD_IEEE80211: return ZEBRA_LLT_IEEE80211; - case ARPHRD_IEEE802154: return ZEBRA_LLT_IEEE802154; + switch (hwt) { + case ARPHRD_ETHER: + return ZEBRA_LLT_ETHER; + case ARPHRD_EETHER: + return ZEBRA_LLT_EETHER; + case ARPHRD_AX25: + return ZEBRA_LLT_AX25; + case ARPHRD_PRONET: + return ZEBRA_LLT_PRONET; + case ARPHRD_IEEE802: + return ZEBRA_LLT_IEEE802; + case ARPHRD_ARCNET: + return ZEBRA_LLT_ARCNET; + case ARPHRD_APPLETLK: + return ZEBRA_LLT_APPLETLK; + case ARPHRD_DLCI: + return ZEBRA_LLT_DLCI; + case ARPHRD_ATM: + return ZEBRA_LLT_ATM; + case ARPHRD_METRICOM: + return ZEBRA_LLT_METRICOM; + case ARPHRD_IEEE1394: + return ZEBRA_LLT_IEEE1394; + case ARPHRD_EUI64: + return ZEBRA_LLT_EUI64; + case ARPHRD_INFINIBAND: + return ZEBRA_LLT_INFINIBAND; + case ARPHRD_SLIP: + return ZEBRA_LLT_SLIP; + case ARPHRD_CSLIP: + return ZEBRA_LLT_CSLIP; + case ARPHRD_SLIP6: + return ZEBRA_LLT_SLIP6; + case ARPHRD_CSLIP6: + return ZEBRA_LLT_CSLIP6; + case ARPHRD_RSRVD: + return ZEBRA_LLT_RSRVD; + case ARPHRD_ADAPT: + return ZEBRA_LLT_ADAPT; + case ARPHRD_ROSE: + return ZEBRA_LLT_ROSE; + case ARPHRD_X25: + return ZEBRA_LLT_X25; + case ARPHRD_PPP: + return ZEBRA_LLT_PPP; + case ARPHRD_CISCO: + return ZEBRA_LLT_CHDLC; + case ARPHRD_LAPB: + return ZEBRA_LLT_LAPB; + case ARPHRD_RAWHDLC: + return ZEBRA_LLT_RAWHDLC; + case ARPHRD_TUNNEL: + return ZEBRA_LLT_IPIP; + case ARPHRD_TUNNEL6: + return ZEBRA_LLT_IPIP6; + case ARPHRD_FRAD: + return ZEBRA_LLT_FRAD; + case ARPHRD_SKIP: + return ZEBRA_LLT_SKIP; + case ARPHRD_LOOPBACK: + return ZEBRA_LLT_LOOPBACK; + case ARPHRD_LOCALTLK: + return ZEBRA_LLT_LOCALTLK; + case ARPHRD_FDDI: + return ZEBRA_LLT_FDDI; + case ARPHRD_SIT: + return ZEBRA_LLT_SIT; + case ARPHRD_IPDDP: + return ZEBRA_LLT_IPDDP; + case ARPHRD_IPGRE: + return ZEBRA_LLT_IPGRE; + case ARPHRD_PIMREG: + return ZEBRA_LLT_PIMREG; + case ARPHRD_HIPPI: + return ZEBRA_LLT_HIPPI; + case ARPHRD_ECONET: + return ZEBRA_LLT_ECONET; + case ARPHRD_IRDA: + return ZEBRA_LLT_IRDA; + case ARPHRD_FCPP: + return ZEBRA_LLT_FCPP; + case ARPHRD_FCAL: + return ZEBRA_LLT_FCAL; + case ARPHRD_FCPL: + return ZEBRA_LLT_FCPL; + case ARPHRD_FCFABRIC: + return ZEBRA_LLT_FCFABRIC; + case ARPHRD_IEEE802_TR: + return ZEBRA_LLT_IEEE802_TR; + case ARPHRD_IEEE80211: + return ZEBRA_LLT_IEEE80211; + case ARPHRD_IEEE802154: + return ZEBRA_LLT_IEEE802154; #ifdef ARPHRD_IP6GRE - case ARPHRD_IP6GRE: return ZEBRA_LLT_IP6GRE; + case ARPHRD_IP6GRE: + return ZEBRA_LLT_IP6GRE; #endif #ifdef ARPHRD_IEEE802154_PHY - case ARPHRD_IEEE802154_PHY: return ZEBRA_LLT_IEEE802154_PHY; + case ARPHRD_IEEE802154_PHY: + return ZEBRA_LLT_IEEE802154_PHY; #endif - default: return ZEBRA_LLT_UNKNOWN; - } + default: + return ZEBRA_LLT_UNKNOWN; + } } -static void -netlink_determine_zebra_iftype (char *kind, zebra_iftype_t *zif_type) +static void netlink_determine_zebra_iftype(char *kind, zebra_iftype_t *zif_type) { - *zif_type = ZEBRA_IF_OTHER; - - if (!kind) - return; - - if (strcmp(kind, "vrf") == 0) - *zif_type = ZEBRA_IF_VRF; - else if (strcmp(kind, "bridge") == 0) - *zif_type = ZEBRA_IF_BRIDGE; - else if (strcmp(kind, "vlan") == 0) - *zif_type = ZEBRA_IF_VLAN; - else if (strcmp(kind, "vxlan") == 0) - *zif_type = ZEBRA_IF_VXLAN; + *zif_type = ZEBRA_IF_OTHER; + + if (!kind) + return; + + if (strcmp(kind, "vrf") == 0) + *zif_type = ZEBRA_IF_VRF; + else if (strcmp(kind, "bridge") == 0) + *zif_type = ZEBRA_IF_BRIDGE; + else if (strcmp(kind, "vlan") == 0) + *zif_type = ZEBRA_IF_VLAN; + else if (strcmp(kind, "vxlan") == 0) + *zif_type = ZEBRA_IF_VXLAN; } -//Temporary Assignments to compile on older platforms. +// Temporary Assignments to compile on older platforms. #ifndef IFLA_BR_MAX #define IFLA_BR_MAX 39 #endif @@ -243,198 +292,196 @@ netlink_determine_zebra_iftype (char *kind, zebra_iftype_t *zif_type) #define IFLA_BR_VLAN_FILTERING 7 #endif -#define parse_rtattr_nested(tb, max, rta) \ - netlink_parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)) +#define parse_rtattr_nested(tb, max, rta) \ + netlink_parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)) -static void -netlink_vrf_change (struct nlmsghdr *h, struct rtattr *tb, const char *name) +static void netlink_vrf_change(struct nlmsghdr *h, struct rtattr *tb, + const char *name) { - struct ifinfomsg *ifi; - struct rtattr *linkinfo[IFLA_INFO_MAX+1]; - struct rtattr *attr[IFLA_VRF_MAX+1]; - struct vrf *vrf; - struct zebra_vrf *zvrf; - u_int32_t nl_table_id; - - ifi = NLMSG_DATA (h); - - memset (linkinfo, 0, sizeof linkinfo); - parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb); - - if (!linkinfo[IFLA_INFO_DATA]) { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: IFLA_INFO_DATA missing from VRF message: %s", __func__, name); - return; - } - - memset (attr, 0, sizeof attr); - parse_rtattr_nested(attr, IFLA_VRF_MAX, linkinfo[IFLA_INFO_DATA]); - if (!attr[IFLA_VRF_TABLE]) { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: IFLA_VRF_TABLE missing from VRF message: %s", __func__, name); - return; - } - - nl_table_id = *(u_int32_t *)RTA_DATA(attr[IFLA_VRF_TABLE]); - - if (h->nlmsg_type == RTM_NEWLINK) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("RTM_NEWLINK for VRF %s(%u) table %u", - name, ifi->ifi_index, nl_table_id); - - /* - * vrf_get is implied creation if it does not exist - */ - vrf = vrf_get((vrf_id_t)ifi->ifi_index, name); // It would create vrf - if (!vrf) - { - zlog_err ("VRF %s id %u not created", name, ifi->ifi_index); - return; - } - - /* Enable the created VRF. */ - if (!vrf_enable (vrf)) - { - zlog_err ("Failed to enable VRF %s id %u", name, ifi->ifi_index); - return; - } - - /* - * This is the only place that we get the actual kernel table_id - * being used. We need it to set the table_id of the routes - * we are passing to the kernel.... And to throw some totally - * awesome parties. that too. - */ - zvrf = (struct zebra_vrf *)vrf->info; - zvrf->table_id = nl_table_id; - } - else //h->nlmsg_type == RTM_DELLINK - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("RTM_DELLINK for VRF %s(%u)", name, ifi->ifi_index); - - vrf = vrf_lookup_by_id ((vrf_id_t)ifi->ifi_index); - - if (!vrf) - { - zlog_warn ("%s: vrf not found", __func__); - return; + struct ifinfomsg *ifi; + struct rtattr *linkinfo[IFLA_INFO_MAX + 1]; + struct rtattr *attr[IFLA_VRF_MAX + 1]; + struct vrf *vrf; + struct zebra_vrf *zvrf; + u_int32_t nl_table_id; + + ifi = NLMSG_DATA(h); + + memset(linkinfo, 0, sizeof linkinfo); + parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb); + + if (!linkinfo[IFLA_INFO_DATA]) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "%s: IFLA_INFO_DATA missing from VRF message: %s", + __func__, name); + return; + } + + memset(attr, 0, sizeof attr); + parse_rtattr_nested(attr, IFLA_VRF_MAX, linkinfo[IFLA_INFO_DATA]); + if (!attr[IFLA_VRF_TABLE]) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "%s: IFLA_VRF_TABLE missing from VRF message: %s", + __func__, name); + return; } - vrf_delete (vrf); - } + nl_table_id = *(u_int32_t *)RTA_DATA(attr[IFLA_VRF_TABLE]); + + if (h->nlmsg_type == RTM_NEWLINK) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("RTM_NEWLINK for VRF %s(%u) table %u", name, + ifi->ifi_index, nl_table_id); + + /* + * vrf_get is implied creation if it does not exist + */ + vrf = vrf_get((vrf_id_t)ifi->ifi_index, + name); // It would create vrf + if (!vrf) { + zlog_err("VRF %s id %u not created", name, + ifi->ifi_index); + return; + } + + /* Enable the created VRF. */ + if (!vrf_enable(vrf)) { + zlog_err("Failed to enable VRF %s id %u", name, + ifi->ifi_index); + return; + } + + /* + * This is the only place that we get the actual kernel table_id + * being used. We need it to set the table_id of the routes + * we are passing to the kernel.... And to throw some totally + * awesome parties. that too. + */ + zvrf = (struct zebra_vrf *)vrf->info; + zvrf->table_id = nl_table_id; + } else // h->nlmsg_type == RTM_DELLINK + { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("RTM_DELLINK for VRF %s(%u)", name, + ifi->ifi_index); + + vrf = vrf_lookup_by_id((vrf_id_t)ifi->ifi_index); + + if (!vrf) { + zlog_warn("%s: vrf not found", __func__); + return; + } + + vrf_delete(vrf); + } } -static int -get_iflink_speed (const char *ifname) +static int get_iflink_speed(const char *ifname) { - struct ifreq ifdata; - struct ethtool_cmd ecmd; - int sd; - int rc; - - /* initialize struct */ - memset(&ifdata, 0, sizeof(ifdata)); - - /* set interface name */ - strcpy(ifdata.ifr_name, ifname); - - /* initialize ethtool interface */ - memset(&ecmd, 0, sizeof(ecmd)); - ecmd.cmd = ETHTOOL_GSET; /* ETHTOOL_GLINK */ - ifdata.ifr_data = (__caddr_t) &ecmd; - - /* use ioctl to get IP address of an interface */ - sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); - if(sd < 0) { - zlog_debug ("Failure to read interface %s speed: %d %s", - ifname, errno, safe_strerror(errno)); - return 0; - } - - /* Get the current link state for the interface */ - rc = ioctl(sd, SIOCETHTOOL, (char *)&ifdata); - if(rc < 0) { - zlog_debug("IOCTL failure to read interface %s speed: %d %s", - ifname, errno, safe_strerror(errno)); - ecmd.speed_hi = 0; - ecmd.speed = 0; - } - - close(sd); - - return (ecmd.speed_hi << 16 ) | ecmd.speed; + struct ifreq ifdata; + struct ethtool_cmd ecmd; + int sd; + int rc; + + /* initialize struct */ + memset(&ifdata, 0, sizeof(ifdata)); + + /* set interface name */ + strcpy(ifdata.ifr_name, ifname); + + /* initialize ethtool interface */ + memset(&ecmd, 0, sizeof(ecmd)); + ecmd.cmd = ETHTOOL_GSET; /* ETHTOOL_GLINK */ + ifdata.ifr_data = (__caddr_t)&ecmd; + + /* use ioctl to get IP address of an interface */ + sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); + if (sd < 0) { + zlog_debug("Failure to read interface %s speed: %d %s", ifname, + errno, safe_strerror(errno)); + return 0; + } + + /* Get the current link state for the interface */ + rc = ioctl(sd, SIOCETHTOOL, (char *)&ifdata); + if (rc < 0) { + zlog_debug("IOCTL failure to read interface %s speed: %d %s", + ifname, errno, safe_strerror(errno)); + ecmd.speed_hi = 0; + ecmd.speed = 0; + } + + close(sd); + + return (ecmd.speed_hi << 16) | ecmd.speed; } -static int -netlink_extract_bridge_info (struct rtattr *link_data, - struct zebra_l2info_bridge *bridge_info) +static int netlink_extract_bridge_info(struct rtattr *link_data, + struct zebra_l2info_bridge *bridge_info) { - struct rtattr *attr[IFLA_BR_MAX+1]; - - memset (bridge_info, 0, sizeof (*bridge_info)); - memset (attr, 0, sizeof attr); - parse_rtattr_nested(attr, IFLA_BR_MAX, link_data); - if (attr[IFLA_BR_VLAN_FILTERING]) - bridge_info->vlan_aware = *(u_char *)RTA_DATA(attr[IFLA_BR_VLAN_FILTERING]); - return 0; + struct rtattr *attr[IFLA_BR_MAX + 1]; + + memset(bridge_info, 0, sizeof(*bridge_info)); + memset(attr, 0, sizeof attr); + parse_rtattr_nested(attr, IFLA_BR_MAX, link_data); + if (attr[IFLA_BR_VLAN_FILTERING]) + bridge_info->vlan_aware = + *(u_char *)RTA_DATA(attr[IFLA_BR_VLAN_FILTERING]); + return 0; } -static int -netlink_extract_vlan_info (struct rtattr *link_data, - struct zebra_l2info_vlan *vlan_info) +static int netlink_extract_vlan_info(struct rtattr *link_data, + struct zebra_l2info_vlan *vlan_info) { - struct rtattr *attr[IFLA_VLAN_MAX+1]; - vlanid_t vid_in_msg; - - memset (vlan_info, 0, sizeof (*vlan_info)); - memset (attr, 0, sizeof attr); - parse_rtattr_nested(attr, IFLA_VLAN_MAX, link_data); - if (!attr[IFLA_VLAN_ID]) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("IFLA_VLAN_ID missing from VLAN IF message"); - return -1; - } - - vid_in_msg = *(vlanid_t *)RTA_DATA(attr[IFLA_VLAN_ID]); - vlan_info->vid = vid_in_msg; - return 0; + struct rtattr *attr[IFLA_VLAN_MAX + 1]; + vlanid_t vid_in_msg; + + memset(vlan_info, 0, sizeof(*vlan_info)); + memset(attr, 0, sizeof attr); + parse_rtattr_nested(attr, IFLA_VLAN_MAX, link_data); + if (!attr[IFLA_VLAN_ID]) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("IFLA_VLAN_ID missing from VLAN IF message"); + return -1; + } + + vid_in_msg = *(vlanid_t *)RTA_DATA(attr[IFLA_VLAN_ID]); + vlan_info->vid = vid_in_msg; + return 0; } -static int -netlink_extract_vxlan_info (struct rtattr *link_data, - struct zebra_l2info_vxlan *vxl_info) +static int netlink_extract_vxlan_info(struct rtattr *link_data, + struct zebra_l2info_vxlan *vxl_info) { - struct rtattr *attr[IFLA_VXLAN_MAX+1]; - vni_t vni_in_msg; - struct in_addr vtep_ip_in_msg; - - memset (vxl_info, 0, sizeof (*vxl_info)); - memset (attr, 0, sizeof attr); - parse_rtattr_nested(attr, IFLA_VXLAN_MAX, link_data); - if (!attr[IFLA_VXLAN_ID]) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("IFLA_VXLAN_ID missing from VXLAN IF message"); - return -1; - } - - vni_in_msg = *(vni_t *)RTA_DATA(attr[IFLA_VXLAN_ID]); - vxl_info->vni = vni_in_msg; - if (!attr[IFLA_VXLAN_LOCAL]) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("IFLA_VXLAN_LOCAL missing from VXLAN IF message"); - } - else - { - vtep_ip_in_msg = *(struct in_addr *)RTA_DATA(attr[IFLA_VXLAN_LOCAL]); - vxl_info->vtep_ip = vtep_ip_in_msg; - } - - return 0; + struct rtattr *attr[IFLA_VXLAN_MAX + 1]; + vni_t vni_in_msg; + struct in_addr vtep_ip_in_msg; + + memset(vxl_info, 0, sizeof(*vxl_info)); + memset(attr, 0, sizeof attr); + parse_rtattr_nested(attr, IFLA_VXLAN_MAX, link_data); + if (!attr[IFLA_VXLAN_ID]) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "IFLA_VXLAN_ID missing from VXLAN IF message"); + return -1; + } + + vni_in_msg = *(vni_t *)RTA_DATA(attr[IFLA_VXLAN_ID]); + vxl_info->vni = vni_in_msg; + if (!attr[IFLA_VXLAN_LOCAL]) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "IFLA_VXLAN_LOCAL missing from VXLAN IF message"); + } else { + vtep_ip_in_msg = + *(struct in_addr *)RTA_DATA(attr[IFLA_VXLAN_LOCAL]); + vxl_info->vtep_ip = vtep_ip_in_msg; + } + + return 0; } /* @@ -442,756 +489,732 @@ netlink_extract_vxlan_info (struct rtattr *link_data, * bridge interface is added or updated, take further actions to map * its members. Likewise, for VxLAN interface. */ -static void -netlink_interface_update_l2info (struct interface *ifp, - struct rtattr *link_data, - int add) +static void netlink_interface_update_l2info(struct interface *ifp, + struct rtattr *link_data, int add) { - if (!link_data) - return; - - if (IS_ZEBRA_IF_BRIDGE(ifp)) - { - struct zebra_l2info_bridge bridge_info; - - netlink_extract_bridge_info (link_data, &bridge_info); - zebra_l2_bridge_add_update (ifp, &bridge_info, add); - } - else if (IS_ZEBRA_IF_VLAN(ifp)) - { - struct zebra_l2info_vlan vlan_info; - - netlink_extract_vlan_info (link_data, &vlan_info); - zebra_l2_vlanif_update (ifp, &vlan_info); - } - else if (IS_ZEBRA_IF_VXLAN(ifp)) - { - struct zebra_l2info_vxlan vxlan_info; - - netlink_extract_vxlan_info (link_data, &vxlan_info); - zebra_l2_vxlanif_add_update (ifp, &vxlan_info, add); - } + if (!link_data) + return; + + if (IS_ZEBRA_IF_BRIDGE(ifp)) { + struct zebra_l2info_bridge bridge_info; + + netlink_extract_bridge_info(link_data, &bridge_info); + zebra_l2_bridge_add_update(ifp, &bridge_info, add); + } else if (IS_ZEBRA_IF_VLAN(ifp)) { + struct zebra_l2info_vlan vlan_info; + + netlink_extract_vlan_info(link_data, &vlan_info); + zebra_l2_vlanif_update(ifp, &vlan_info); + } else if (IS_ZEBRA_IF_VXLAN(ifp)) { + struct zebra_l2info_vxlan vxlan_info; + + netlink_extract_vxlan_info(link_data, &vxlan_info); + zebra_l2_vxlanif_add_update(ifp, &vxlan_info, add); + } } -static int -netlink_bridge_interface (struct nlmsghdr *h, int len, - ns_id_t ns_id, int startup) +static int netlink_bridge_interface(struct nlmsghdr *h, int len, ns_id_t ns_id, + int startup) { - char *name = NULL; - struct ifinfomsg *ifi; - struct rtattr *tb[IFLA_MAX + 1]; - struct interface *ifp; - struct rtattr *aftb[IFLA_BRIDGE_MAX + 1]; - struct - { - u_int16_t flags; - u_int16_t vid; - } *vinfo; - vlanid_t access_vlan; - - /* Fetch name and ifindex */ - ifi = NLMSG_DATA (h); - memset (tb, 0, sizeof tb); - netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len); - - if (tb[IFLA_IFNAME] == NULL) - return -1; - name = (char *) RTA_DATA (tb[IFLA_IFNAME]); - - /* The interface should already be known, if not discard. */ - ifp = if_lookup_by_index_per_ns (zebra_ns_lookup (ns_id), - ifi->ifi_index); - if (!ifp) - { - zlog_warn ("Cannot find bridge IF %s(%u)", - name, ifi->ifi_index); - return 0; - } - if (!IS_ZEBRA_IF_VXLAN(ifp)) - return 0; - - /* We are only interested in the access VLAN i.e., AF_SPEC */ - if (!tb[IFLA_AF_SPEC]) - return 0; - - /* There is a 1-to-1 mapping of VLAN to VxLAN - hence - * only 1 access VLAN is accepted. - */ - memset (aftb, 0, sizeof aftb); - parse_rtattr_nested(aftb, IFLA_BRIDGE_MAX, tb[IFLA_AF_SPEC]); - if (!aftb[IFLA_BRIDGE_VLAN_INFO]) - return 0; - - vinfo = RTA_DATA(aftb[IFLA_BRIDGE_VLAN_INFO]); - if (!(vinfo->flags & BRIDGE_VLAN_INFO_PVID)) - return 0; - - access_vlan = (vlanid_t) vinfo->vid; - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("Access VLAN %u for VxLAN IF %s(%u)", - access_vlan, name, ifi->ifi_index); - zebra_l2_vxlanif_update_access_vlan (ifp, access_vlan); - return 0; + char *name = NULL; + struct ifinfomsg *ifi; + struct rtattr *tb[IFLA_MAX + 1]; + struct interface *ifp; + struct rtattr *aftb[IFLA_BRIDGE_MAX + 1]; + struct { + u_int16_t flags; + u_int16_t vid; + } * vinfo; + vlanid_t access_vlan; + + /* Fetch name and ifindex */ + ifi = NLMSG_DATA(h); + memset(tb, 0, sizeof tb); + netlink_parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); + + if (tb[IFLA_IFNAME] == NULL) + return -1; + name = (char *)RTA_DATA(tb[IFLA_IFNAME]); + + /* The interface should already be known, if not discard. */ + ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), ifi->ifi_index); + if (!ifp) { + zlog_warn("Cannot find bridge IF %s(%u)", name, ifi->ifi_index); + return 0; + } + if (!IS_ZEBRA_IF_VXLAN(ifp)) + return 0; + + /* We are only interested in the access VLAN i.e., AF_SPEC */ + if (!tb[IFLA_AF_SPEC]) + return 0; + + /* There is a 1-to-1 mapping of VLAN to VxLAN - hence + * only 1 access VLAN is accepted. + */ + memset(aftb, 0, sizeof aftb); + parse_rtattr_nested(aftb, IFLA_BRIDGE_MAX, tb[IFLA_AF_SPEC]); + if (!aftb[IFLA_BRIDGE_VLAN_INFO]) + return 0; + + vinfo = RTA_DATA(aftb[IFLA_BRIDGE_VLAN_INFO]); + if (!(vinfo->flags & BRIDGE_VLAN_INFO_PVID)) + return 0; + + access_vlan = (vlanid_t)vinfo->vid; + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("Access VLAN %u for VxLAN IF %s(%u)", access_vlan, + name, ifi->ifi_index); + zebra_l2_vxlanif_update_access_vlan(ifp, access_vlan); + return 0; } /* Called from interface_lookup_netlink(). This function is only used during bootstrap. */ -static int -netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +static int netlink_interface(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup) { - int len; - struct ifinfomsg *ifi; - struct rtattr *tb[IFLA_MAX + 1]; - struct rtattr *linkinfo[IFLA_MAX + 1]; - struct interface *ifp; - char *name = NULL; - char *kind = NULL; - char *slave_kind = NULL; - struct zebra_ns *zns; - vrf_id_t vrf_id = VRF_DEFAULT; - zebra_iftype_t zif_type = ZEBRA_IF_OTHER; - zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE; - ifindex_t bridge_ifindex = IFINDEX_INTERNAL; - ifindex_t link_ifindex = IFINDEX_INTERNAL; - - zns = zebra_ns_lookup (ns_id); - ifi = NLMSG_DATA (h); - - if (h->nlmsg_type != RTM_NEWLINK) - return 0; - - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg)); - if (len < 0) - return -1; - - /* We are interested in some AF_BRIDGE notifications. */ - if (ifi->ifi_family == AF_BRIDGE) - return netlink_bridge_interface (h, len, ns_id, startup); - - /* Looking up interface name. */ - memset (tb, 0, sizeof tb); - memset (linkinfo, 0, sizeof linkinfo); - netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len); + int len; + struct ifinfomsg *ifi; + struct rtattr *tb[IFLA_MAX + 1]; + struct rtattr *linkinfo[IFLA_MAX + 1]; + struct interface *ifp; + char *name = NULL; + char *kind = NULL; + char *slave_kind = NULL; + struct zebra_ns *zns; + vrf_id_t vrf_id = VRF_DEFAULT; + zebra_iftype_t zif_type = ZEBRA_IF_OTHER; + zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE; + ifindex_t bridge_ifindex = IFINDEX_INTERNAL; + ifindex_t link_ifindex = IFINDEX_INTERNAL; + + zns = zebra_ns_lookup(ns_id); + ifi = NLMSG_DATA(h); + + if (h->nlmsg_type != RTM_NEWLINK) + return 0; + + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg)); + if (len < 0) + return -1; + + /* We are interested in some AF_BRIDGE notifications. */ + if (ifi->ifi_family == AF_BRIDGE) + return netlink_bridge_interface(h, len, ns_id, startup); + + /* Looking up interface name. */ + memset(tb, 0, sizeof tb); + memset(linkinfo, 0, sizeof linkinfo); + netlink_parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); #ifdef IFLA_WIRELESS - /* check for wireless messages to ignore */ - if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__); - return 0; - } + /* check for wireless messages to ignore */ + if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: ignoring IFLA_WIRELESS message", + __func__); + return 0; + } #endif /* IFLA_WIRELESS */ - if (tb[IFLA_IFNAME] == NULL) - return -1; - name = (char *) RTA_DATA (tb[IFLA_IFNAME]); + if (tb[IFLA_IFNAME] == NULL) + return -1; + name = (char *)RTA_DATA(tb[IFLA_IFNAME]); - if (tb[IFLA_LINKINFO]) - { - parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); + if (tb[IFLA_LINKINFO]) { + parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); - if (linkinfo[IFLA_INFO_KIND]) - kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); + if (linkinfo[IFLA_INFO_KIND]) + kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); #if HAVE_DECL_IFLA_INFO_SLAVE_KIND - if (linkinfo[IFLA_INFO_SLAVE_KIND]) - slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); + if (linkinfo[IFLA_INFO_SLAVE_KIND]) + slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); #endif - netlink_determine_zebra_iftype (kind, &zif_type); - } - - /* If VRF, create the VRF structure itself. */ - if (zif_type == ZEBRA_IF_VRF) - { - netlink_vrf_change(h, tb[IFLA_LINKINFO], name); - vrf_id = (vrf_id_t)ifi->ifi_index; - } - - if (tb[IFLA_MASTER]) - { - if (slave_kind && (strcmp(slave_kind, "vrf") == 0)) - { - zif_slave_type = ZEBRA_IF_SLAVE_VRF; - vrf_id = *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]); - } - else if (slave_kind && (strcmp(slave_kind, "bridge") == 0)) - { - zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE; - bridge_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]); - } - else - zif_slave_type = ZEBRA_IF_SLAVE_OTHER; - } - - /* If linking to another interface, note it. */ - if (tb[IFLA_LINK]) - link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]); - - /* Add interface. */ - ifp = if_get_by_name (name, vrf_id); - set_ifindex(ifp, ifi->ifi_index, zns); - ifp->flags = ifi->ifi_flags & 0x0000fffff; - if (IS_ZEBRA_IF_VRF(ifp)) - SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); - ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); - ifp->metric = 0; - ifp->speed = get_iflink_speed (name); - ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; - - /* Set zebra interface type */ - zebra_if_set_ziftype (ifp, zif_type, zif_slave_type); - - /* Update link. */ - zebra_if_update_link (ifp, link_ifindex); - - /* Hardware type and address. */ - ifp->ll_type = netlink_to_zebra_link_type (ifi->ifi_type); - netlink_interface_update_hw_addr (tb, ifp); - - if_add_update (ifp); - - /* Extract and save L2 interface information, take additional actions. */ - netlink_interface_update_l2info (ifp, linkinfo[IFLA_INFO_DATA], 1); - if (IS_ZEBRA_IF_BRIDGE_SLAVE (ifp)) - zebra_l2if_update_bridge_slave (ifp, bridge_ifindex); - - return 0; + netlink_determine_zebra_iftype(kind, &zif_type); + } + + /* If VRF, create the VRF structure itself. */ + if (zif_type == ZEBRA_IF_VRF) { + netlink_vrf_change(h, tb[IFLA_LINKINFO], name); + vrf_id = (vrf_id_t)ifi->ifi_index; + } + + if (tb[IFLA_MASTER]) { + if (slave_kind && (strcmp(slave_kind, "vrf") == 0)) { + zif_slave_type = ZEBRA_IF_SLAVE_VRF; + vrf_id = *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]); + } else if (slave_kind && (strcmp(slave_kind, "bridge") == 0)) { + zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE; + bridge_ifindex = + *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]); + } else + zif_slave_type = ZEBRA_IF_SLAVE_OTHER; + } + + /* If linking to another interface, note it. */ + if (tb[IFLA_LINK]) + link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]); + + /* Add interface. */ + ifp = if_get_by_name(name, vrf_id); + set_ifindex(ifp, ifi->ifi_index, zns); + ifp->flags = ifi->ifi_flags & 0x0000fffff; + if (IS_ZEBRA_IF_VRF(ifp)) + SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); + ifp->mtu6 = ifp->mtu = *(uint32_t *)RTA_DATA(tb[IFLA_MTU]); + ifp->metric = 0; + ifp->speed = get_iflink_speed(name); + ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; + + /* Set zebra interface type */ + zebra_if_set_ziftype(ifp, zif_type, zif_slave_type); + + /* Update link. */ + zebra_if_update_link(ifp, link_ifindex); + + /* Hardware type and address. */ + ifp->ll_type = netlink_to_zebra_link_type(ifi->ifi_type); + netlink_interface_update_hw_addr(tb, ifp); + + if_add_update(ifp); + + /* Extract and save L2 interface information, take additional actions. + */ + netlink_interface_update_l2info(ifp, linkinfo[IFLA_INFO_DATA], 1); + if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) + zebra_l2if_update_bridge_slave(ifp, bridge_ifindex); + + return 0; } /* Request for specific interface or address information from the kernel */ -static int -netlink_request_intf_addr (struct zebra_ns *zns, - int family, int type, - u_int32_t filter_mask) +static int netlink_request_intf_addr(struct zebra_ns *zns, int family, int type, + u_int32_t filter_mask) { - struct - { - struct nlmsghdr n; - struct ifinfomsg ifm; - char buf[256]; - } req; - - /* Form the request, specifying filter (rtattr) if needed. */ - memset (&req, 0, sizeof (req)); - req.n.nlmsg_type = type; - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); - req.ifm.ifi_family = family; - - /* Include filter, if specified. */ - if (filter_mask) - addattr32 (&req.n, sizeof(req), IFLA_EXT_MASK, filter_mask); - - return netlink_request (&zns->netlink_cmd, &req.n); + struct { + struct nlmsghdr n; + struct ifinfomsg ifm; + char buf[256]; + } req; + + /* Form the request, specifying filter (rtattr) if needed. */ + memset(&req, 0, sizeof(req)); + req.n.nlmsg_type = type; + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + req.ifm.ifi_family = family; + + /* Include filter, if specified. */ + if (filter_mask) + addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filter_mask); + + return netlink_request(&zns->netlink_cmd, &req.n); } /* Interface lookup by netlink socket. */ -int -interface_lookup_netlink (struct zebra_ns *zns) +int interface_lookup_netlink(struct zebra_ns *zns) { - int ret; - - /* Get interface information. */ - ret = netlink_request_intf_addr (zns, AF_PACKET, RTM_GETLINK, 0); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_interface, &zns->netlink_cmd, zns, 0, 1); - if (ret < 0) - return ret; - - /* Get interface information - for bridge interfaces. */ - ret = netlink_request_intf_addr (zns, AF_BRIDGE, RTM_GETLINK, - RTEXT_FILTER_BRVLAN); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_interface, &zns->netlink_cmd, zns, 0, 0); - if (ret < 0) - return ret; - - /* Get interface information - for bridge interfaces. */ - ret = netlink_request_intf_addr (zns, AF_BRIDGE, RTM_GETLINK, - RTEXT_FILTER_BRVLAN); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_interface, &zns->netlink_cmd, zns, 0, 0); - if (ret < 0) - return ret; - - /* Get IPv4 address of the interfaces. */ - ret = netlink_request_intf_addr (zns, AF_INET, RTM_GETADDR, 0); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0, 1); - if (ret < 0) - return ret; - - /* Get IPv6 address of the interfaces. */ - ret = netlink_request_intf_addr (zns, AF_INET6, RTM_GETADDR, 0); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0, 1); - if (ret < 0) - return ret; - - return 0; + int ret; + + /* Get interface information. */ + ret = netlink_request_intf_addr(zns, AF_PACKET, RTM_GETLINK, 0); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_interface, &zns->netlink_cmd, zns, 0, + 1); + if (ret < 0) + return ret; + + /* Get interface information - for bridge interfaces. */ + ret = netlink_request_intf_addr(zns, AF_BRIDGE, RTM_GETLINK, + RTEXT_FILTER_BRVLAN); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_interface, &zns->netlink_cmd, zns, 0, + 0); + if (ret < 0) + return ret; + + /* Get interface information - for bridge interfaces. */ + ret = netlink_request_intf_addr(zns, AF_BRIDGE, RTM_GETLINK, + RTEXT_FILTER_BRVLAN); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_interface, &zns->netlink_cmd, zns, 0, + 0); + if (ret < 0) + return ret; + + /* Get IPv4 address of the interfaces. */ + ret = netlink_request_intf_addr(zns, AF_INET, RTM_GETADDR, 0); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_interface_addr, &zns->netlink_cmd, zns, + 0, 1); + if (ret < 0) + return ret; + + /* Get IPv6 address of the interfaces. */ + ret = netlink_request_intf_addr(zns, AF_INET6, RTM_GETADDR, 0); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_interface_addr, &zns->netlink_cmd, zns, + 0, 1); + if (ret < 0) + return ret; + + return 0; } /* Interface address modification. */ -static int -netlink_address (int cmd, int family, struct interface *ifp, - struct connected *ifc) +static int netlink_address(int cmd, int family, struct interface *ifp, + struct connected *ifc) { - int bytelen; - struct prefix *p; + int bytelen; + struct prefix *p; - struct - { - struct nlmsghdr n; - struct ifaddrmsg ifa; - char buf[NL_PKT_BUF_SIZE]; - } req; + struct { + struct nlmsghdr n; + struct ifaddrmsg ifa; + char buf[NL_PKT_BUF_SIZE]; + } req; - struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); + struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); - p = ifc->address; - memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); + p = ifc->address; + memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE); - bytelen = (family == AF_INET ? 4 : 16); + bytelen = (family == AF_INET ? 4 : 16); - req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg)); - req.n.nlmsg_flags = NLM_F_REQUEST; - req.n.nlmsg_type = cmd; - req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = cmd; + req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; - req.ifa.ifa_family = family; + req.ifa.ifa_family = family; - req.ifa.ifa_index = ifp->ifindex; - req.ifa.ifa_prefixlen = p->prefixlen; + req.ifa.ifa_index = ifp->ifindex; + req.ifa.ifa_prefixlen = p->prefixlen; - addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen); + addattr_l(&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen); - if (family == AF_INET && cmd == RTM_NEWADDR) - { - if (!CONNECTED_PEER(ifc) && ifc->destination) - { - p = ifc->destination; - addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix, - bytelen); - } - } + if (family == AF_INET && cmd == RTM_NEWADDR) { + if (!CONNECTED_PEER(ifc) && ifc->destination) { + p = ifc->destination; + addattr_l(&req.n, sizeof req, IFA_BROADCAST, + &p->u.prefix, bytelen); + } + } - if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY)) - SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY); + if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) + SET_FLAG(req.ifa.ifa_flags, IFA_F_SECONDARY); - if (ifc->label) - addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label, - strlen (ifc->label) + 1); + if (ifc->label) + addattr_l(&req.n, sizeof req, IFA_LABEL, ifc->label, + strlen(ifc->label) + 1); - return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); + return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, + 0); } -int -kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc) +int kernel_address_add_ipv4(struct interface *ifp, struct connected *ifc) { - return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc); + return netlink_address(RTM_NEWADDR, AF_INET, ifp, ifc); } -int -kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc) +int kernel_address_delete_ipv4(struct interface *ifp, struct connected *ifc) { - return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc); + return netlink_address(RTM_DELADDR, AF_INET, ifp, ifc); } -int -netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +int netlink_interface_addr(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup) { - int len; - struct ifaddrmsg *ifa; - struct rtattr *tb[IFA_MAX + 1]; - struct interface *ifp; - void *addr; - void *broad; - u_char flags = 0; - char *label = NULL; - struct zebra_ns *zns; - - zns = zebra_ns_lookup (ns_id); - ifa = NLMSG_DATA (h); - - if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6) - return 0; - - if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR) - return 0; - - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifaddrmsg)); - if (len < 0) - return -1; - - memset (tb, 0, sizeof tb); - netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len); - - ifp = if_lookup_by_index_per_ns (zns, ifa->ifa_index); - if (ifp == NULL) - { - zlog_err ("netlink_interface_addr can't find interface by index %d", - ifa->ifa_index); - return -1; - } - - if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */ - { - char buf[BUFSIZ]; - zlog_debug ("netlink_interface_addr %s %s flags 0x%x:", - nl_msg_type_to_str (h->nlmsg_type), ifp->name, - ifa->ifa_flags); - if (tb[IFA_LOCAL]) - zlog_debug (" IFA_LOCAL %s/%d", - inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]), - buf, BUFSIZ), ifa->ifa_prefixlen); - if (tb[IFA_ADDRESS]) - zlog_debug (" IFA_ADDRESS %s/%d", - inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_ADDRESS]), - buf, BUFSIZ), ifa->ifa_prefixlen); - if (tb[IFA_BROADCAST]) - zlog_debug (" IFA_BROADCAST %s/%d", - inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_BROADCAST]), - buf, BUFSIZ), ifa->ifa_prefixlen); - if (tb[IFA_LABEL] && strcmp (ifp->name, RTA_DATA (tb[IFA_LABEL]))) - zlog_debug (" IFA_LABEL %s", (char *)RTA_DATA (tb[IFA_LABEL])); - - if (tb[IFA_CACHEINFO]) - { - struct ifa_cacheinfo *ci = RTA_DATA (tb[IFA_CACHEINFO]); - zlog_debug (" IFA_CACHEINFO pref %d, valid %d", - ci->ifa_prefered, ci->ifa_valid); - } - } - - /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */ - if (tb[IFA_LOCAL] == NULL) - tb[IFA_LOCAL] = tb[IFA_ADDRESS]; - if (tb[IFA_ADDRESS] == NULL) - tb[IFA_ADDRESS] = tb[IFA_LOCAL]; - - /* local interface address */ - addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL); - - /* is there a peer address? */ - if (tb[IFA_ADDRESS] && - memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_ADDRESS]))) - { - broad = RTA_DATA(tb[IFA_ADDRESS]); - SET_FLAG (flags, ZEBRA_IFA_PEER); - } - else - /* seeking a broadcast address */ - broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST]) : NULL); - - /* addr is primary key, SOL if we don't have one */ - if (addr == NULL) - { - zlog_debug ("%s: NULL address", __func__); - return -1; - } - - /* Flags. */ - if (ifa->ifa_flags & IFA_F_SECONDARY) - SET_FLAG (flags, ZEBRA_IFA_SECONDARY); - - /* Label */ - if (tb[IFA_LABEL]) - label = (char *) RTA_DATA (tb[IFA_LABEL]); - - if (ifp && label && strcmp (ifp->name, label) == 0) - label = NULL; - - /* Register interface address to the interface. */ - if (ifa->ifa_family == AF_INET) - { - if (h->nlmsg_type == RTM_NEWADDR) - connected_add_ipv4 (ifp, flags, - (struct in_addr *) addr, ifa->ifa_prefixlen, - (struct in_addr *) broad, label); - else - connected_delete_ipv4 (ifp, flags, - (struct in_addr *) addr, ifa->ifa_prefixlen, - (struct in_addr *) broad); - } - if (ifa->ifa_family == AF_INET6) - { - if (h->nlmsg_type == RTM_NEWADDR) - { - /* Only consider valid addresses; we'll not get a notification from - * the kernel till IPv6 DAD has completed, but at init time, Quagga - * does query for and will receive all addresses. - */ - if (!(ifa->ifa_flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))) - connected_add_ipv6 (ifp, flags, (struct in6_addr *) addr, - ifa->ifa_prefixlen, (struct in6_addr *) broad, label); - } - else - connected_delete_ipv6 (ifp, - (struct in6_addr *) addr, ifa->ifa_prefixlen, - (struct in6_addr *) broad); - } - - return 0; + int len; + struct ifaddrmsg *ifa; + struct rtattr *tb[IFA_MAX + 1]; + struct interface *ifp; + void *addr; + void *broad; + u_char flags = 0; + char *label = NULL; + struct zebra_ns *zns; + + zns = zebra_ns_lookup(ns_id); + ifa = NLMSG_DATA(h); + + if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6) + return 0; + + if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR) + return 0; + + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg)); + if (len < 0) + return -1; + + memset(tb, 0, sizeof tb); + netlink_parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), len); + + ifp = if_lookup_by_index_per_ns(zns, ifa->ifa_index); + if (ifp == NULL) { + zlog_err( + "netlink_interface_addr can't find interface by index %d", + ifa->ifa_index); + return -1; + } + + if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */ + { + char buf[BUFSIZ]; + zlog_debug("netlink_interface_addr %s %s flags 0x%x:", + nl_msg_type_to_str(h->nlmsg_type), ifp->name, + ifa->ifa_flags); + if (tb[IFA_LOCAL]) + zlog_debug(" IFA_LOCAL %s/%d", + inet_ntop(ifa->ifa_family, + RTA_DATA(tb[IFA_LOCAL]), buf, + BUFSIZ), + ifa->ifa_prefixlen); + if (tb[IFA_ADDRESS]) + zlog_debug(" IFA_ADDRESS %s/%d", + inet_ntop(ifa->ifa_family, + RTA_DATA(tb[IFA_ADDRESS]), buf, + BUFSIZ), + ifa->ifa_prefixlen); + if (tb[IFA_BROADCAST]) + zlog_debug(" IFA_BROADCAST %s/%d", + inet_ntop(ifa->ifa_family, + RTA_DATA(tb[IFA_BROADCAST]), buf, + BUFSIZ), + ifa->ifa_prefixlen); + if (tb[IFA_LABEL] && strcmp(ifp->name, RTA_DATA(tb[IFA_LABEL]))) + zlog_debug(" IFA_LABEL %s", + (char *)RTA_DATA(tb[IFA_LABEL])); + + if (tb[IFA_CACHEINFO]) { + struct ifa_cacheinfo *ci = RTA_DATA(tb[IFA_CACHEINFO]); + zlog_debug(" IFA_CACHEINFO pref %d, valid %d", + ci->ifa_prefered, ci->ifa_valid); + } + } + + /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */ + if (tb[IFA_LOCAL] == NULL) + tb[IFA_LOCAL] = tb[IFA_ADDRESS]; + if (tb[IFA_ADDRESS] == NULL) + tb[IFA_ADDRESS] = tb[IFA_LOCAL]; + + /* local interface address */ + addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL); + + /* is there a peer address? */ + if (tb[IFA_ADDRESS] + && memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), + RTA_PAYLOAD(tb[IFA_ADDRESS]))) { + broad = RTA_DATA(tb[IFA_ADDRESS]); + SET_FLAG(flags, ZEBRA_IFA_PEER); + } else + /* seeking a broadcast address */ + broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST]) + : NULL); + + /* addr is primary key, SOL if we don't have one */ + if (addr == NULL) { + zlog_debug("%s: NULL address", __func__); + return -1; + } + + /* Flags. */ + if (ifa->ifa_flags & IFA_F_SECONDARY) + SET_FLAG(flags, ZEBRA_IFA_SECONDARY); + + /* Label */ + if (tb[IFA_LABEL]) + label = (char *)RTA_DATA(tb[IFA_LABEL]); + + if (ifp && label && strcmp(ifp->name, label) == 0) + label = NULL; + + /* Register interface address to the interface. */ + if (ifa->ifa_family == AF_INET) { + if (h->nlmsg_type == RTM_NEWADDR) + connected_add_ipv4(ifp, flags, (struct in_addr *)addr, + ifa->ifa_prefixlen, + (struct in_addr *)broad, label); + else + connected_delete_ipv4( + ifp, flags, (struct in_addr *)addr, + ifa->ifa_prefixlen, (struct in_addr *)broad); + } + if (ifa->ifa_family == AF_INET6) { + if (h->nlmsg_type == RTM_NEWADDR) { + /* Only consider valid addresses; we'll not get a + * notification from + * the kernel till IPv6 DAD has completed, but at init + * time, Quagga + * does query for and will receive all addresses. + */ + if (!(ifa->ifa_flags + & (IFA_F_DADFAILED | IFA_F_TENTATIVE))) + connected_add_ipv6( + ifp, flags, (struct in6_addr *)addr, + ifa->ifa_prefixlen, + (struct in6_addr *)broad, label); + } else + connected_delete_ipv6(ifp, (struct in6_addr *)addr, + ifa->ifa_prefixlen, + (struct in6_addr *)broad); + } + + return 0; } -int -netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +int netlink_link_change(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup) { - int len; - struct ifinfomsg *ifi; - struct rtattr *tb[IFLA_MAX + 1]; - struct rtattr *linkinfo[IFLA_MAX + 1]; - struct interface *ifp; - char *name = NULL; - char *kind = NULL; - char *slave_kind = NULL; - struct zebra_ns *zns; - vrf_id_t vrf_id = VRF_DEFAULT; - zebra_iftype_t zif_type = ZEBRA_IF_OTHER; - zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE; - ifindex_t bridge_ifindex = IFINDEX_INTERNAL; - ifindex_t link_ifindex = IFINDEX_INTERNAL; - - - zns = zebra_ns_lookup (ns_id); - ifi = NLMSG_DATA (h); - - if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) - { - /* If this is not link add/delete message so print warning. */ - zlog_warn ("netlink_link_change: wrong kernel message %d", - h->nlmsg_type); - return 0; - } - - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg)); - if (len < 0) - return -1; - - /* We are interested in some AF_BRIDGE notifications. */ - if (ifi->ifi_family == AF_BRIDGE) - return netlink_bridge_interface (h, len, ns_id, startup); - - /* Looking up interface name. */ - memset (tb, 0, sizeof tb); - memset (linkinfo, 0, sizeof linkinfo); - netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len); + int len; + struct ifinfomsg *ifi; + struct rtattr *tb[IFLA_MAX + 1]; + struct rtattr *linkinfo[IFLA_MAX + 1]; + struct interface *ifp; + char *name = NULL; + char *kind = NULL; + char *slave_kind = NULL; + struct zebra_ns *zns; + vrf_id_t vrf_id = VRF_DEFAULT; + zebra_iftype_t zif_type = ZEBRA_IF_OTHER; + zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE; + ifindex_t bridge_ifindex = IFINDEX_INTERNAL; + ifindex_t link_ifindex = IFINDEX_INTERNAL; + + + zns = zebra_ns_lookup(ns_id); + ifi = NLMSG_DATA(h); + + if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) { + /* If this is not link add/delete message so print warning. */ + zlog_warn("netlink_link_change: wrong kernel message %d", + h->nlmsg_type); + return 0; + } + + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg)); + if (len < 0) + return -1; + + /* We are interested in some AF_BRIDGE notifications. */ + if (ifi->ifi_family == AF_BRIDGE) + return netlink_bridge_interface(h, len, ns_id, startup); + + /* Looking up interface name. */ + memset(tb, 0, sizeof tb); + memset(linkinfo, 0, sizeof linkinfo); + netlink_parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); #ifdef IFLA_WIRELESS - /* check for wireless messages to ignore */ - if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__); - return 0; - } + /* check for wireless messages to ignore */ + if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0)) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: ignoring IFLA_WIRELESS message", + __func__); + return 0; + } #endif /* IFLA_WIRELESS */ - if (tb[IFLA_IFNAME] == NULL) - return -1; - name = (char *) RTA_DATA (tb[IFLA_IFNAME]); + if (tb[IFLA_IFNAME] == NULL) + return -1; + name = (char *)RTA_DATA(tb[IFLA_IFNAME]); - if (tb[IFLA_LINKINFO]) - { - parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); + if (tb[IFLA_LINKINFO]) { + parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); - if (linkinfo[IFLA_INFO_KIND]) - kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); + if (linkinfo[IFLA_INFO_KIND]) + kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); #if HAVE_DECL_IFLA_INFO_SLAVE_KIND - if (linkinfo[IFLA_INFO_SLAVE_KIND]) - slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); + if (linkinfo[IFLA_INFO_SLAVE_KIND]) + slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); #endif - netlink_determine_zebra_iftype (kind, &zif_type); - } - - /* If linking to another interface, note it. */ - if (tb[IFLA_LINK]) - link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]); + netlink_determine_zebra_iftype(kind, &zif_type); + } - /* If VRF, create or update the VRF structure itself. */ - if (zif_type == ZEBRA_IF_VRF) - { - netlink_vrf_change(h, tb[IFLA_LINKINFO], name); - vrf_id = (vrf_id_t)ifi->ifi_index; - } + /* If linking to another interface, note it. */ + if (tb[IFLA_LINK]) + link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]); - /* See if interface is present. */ - ifp = if_lookup_by_name_per_ns (zns, name); + /* If VRF, create or update the VRF structure itself. */ + if (zif_type == ZEBRA_IF_VRF) { + netlink_vrf_change(h, tb[IFLA_LINKINFO], name); + vrf_id = (vrf_id_t)ifi->ifi_index; + } - if (h->nlmsg_type == RTM_NEWLINK) - { - if (tb[IFLA_MASTER]) - { - if (slave_kind && (strcmp(slave_kind, "vrf") == 0)) - { - zif_slave_type = ZEBRA_IF_SLAVE_VRF; - vrf_id = *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]); - } - else if (slave_kind && (strcmp(slave_kind, "bridge") == 0)) - { - zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE; - bridge_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]); - } - else - zif_slave_type = ZEBRA_IF_SLAVE_OTHER; + /* See if interface is present. */ + ifp = if_lookup_by_name_per_ns(zns, name); + + if (h->nlmsg_type == RTM_NEWLINK) { + if (tb[IFLA_MASTER]) { + if (slave_kind && (strcmp(slave_kind, "vrf") == 0)) { + zif_slave_type = ZEBRA_IF_SLAVE_VRF; + vrf_id = + *(u_int32_t *)RTA_DATA(tb[IFLA_MASTER]); + } else if (slave_kind + && (strcmp(slave_kind, "bridge") == 0)) { + zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE; + bridge_ifindex = + *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]); + } else + zif_slave_type = ZEBRA_IF_SLAVE_OTHER; + } + + if (ifp == NULL + || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + /* Add interface notification from kernel */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "RTM_NEWLINK ADD for %s(%u) vrf_id %u type %d " + "sl_type %d master %u flags 0x%x", + name, ifi->ifi_index, vrf_id, zif_type, + zif_slave_type, bridge_ifindex, + ifi->ifi_flags); + + if (ifp == NULL) { + /* unknown interface */ + ifp = if_get_by_name(name, vrf_id); + } else { + /* pre-configured interface, learnt now */ + if (ifp->vrf_id != vrf_id) + if_update_to_new_vrf(ifp, vrf_id); + } + + /* Update interface information. */ + set_ifindex(ifp, ifi->ifi_index, zns); + ifp->flags = ifi->ifi_flags & 0x0000fffff; + if (IS_ZEBRA_IF_VRF(ifp)) + SET_FLAG(ifp->status, + ZEBRA_INTERFACE_VRF_LOOPBACK); + ifp->mtu6 = ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]); + ifp->metric = 0; + ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; + + /* Set interface type */ + zebra_if_set_ziftype(ifp, zif_type, zif_slave_type); + + /* Update link. */ + zebra_if_update_link(ifp, link_ifindex); + + netlink_interface_update_hw_addr(tb, ifp); + + /* Inform clients, install any configured addresses. */ + if_add_update(ifp); + + /* Extract and save L2 interface information, take + * additional actions. */ + netlink_interface_update_l2info( + ifp, linkinfo[IFLA_INFO_DATA], 1); + if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) + zebra_l2if_update_bridge_slave(ifp, + bridge_ifindex); + } else if (ifp->vrf_id != vrf_id) { + /* VRF change for an interface. */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "RTM_NEWLINK vrf-change for %s(%u) " + "vrf_id %u -> %u flags 0x%x", + name, ifp->ifindex, ifp->vrf_id, vrf_id, + ifi->ifi_flags); + + if_handle_vrf_change(ifp, vrf_id); + } else { + int was_bridge_slave; + + /* Interface update. */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "RTM_NEWLINK update for %s(%u) " + "sl_type %d master %u flags 0x%x", + name, ifp->ifindex, zif_slave_type, + bridge_ifindex, ifi->ifi_flags); + + set_ifindex(ifp, ifi->ifi_index, zns); + ifp->mtu6 = ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]); + ifp->metric = 0; + + /* Update interface type - NOTE: Only slave_type can + * change. */ + was_bridge_slave = IS_ZEBRA_IF_BRIDGE_SLAVE(ifp); + zebra_if_set_ziftype(ifp, zif_type, zif_slave_type); + + netlink_interface_update_hw_addr(tb, ifp); + + if (if_is_no_ptm_operative(ifp)) { + ifp->flags = ifi->ifi_flags & 0x0000fffff; + if (!if_is_no_ptm_operative(ifp)) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "Intf %s(%u) has gone DOWN", + name, ifp->ifindex); + if_down(ifp); + } else if (if_is_operative(ifp)) { + /* Must notify client daemons of new + * interface status. */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "Intf %s(%u) PTM up, notifying clients", + name, ifp->ifindex); + zebra_interface_up_update(ifp); + } + } else { + ifp->flags = ifi->ifi_flags & 0x0000fffff; + if (if_is_operative(ifp)) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "Intf %s(%u) has come UP", + name, ifp->ifindex); + if_up(ifp); + } + } + + /* Extract and save L2 interface information, take + * additional actions. */ + netlink_interface_update_l2info( + ifp, linkinfo[IFLA_INFO_DATA], 0); + if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) || was_bridge_slave) + zebra_l2if_update_bridge_slave(ifp, + bridge_ifindex); + } + } else { + /* Delete interface notification from kernel */ + if (ifp == NULL) { + zlog_warn("RTM_DELLINK for unknown interface %s(%u)", + name, ifi->ifi_index); + return 0; + } + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("RTM_DELLINK for %s(%u)", name, + ifp->ifindex); + + UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); + + /* Special handling for bridge or VxLAN interfaces. */ + if (IS_ZEBRA_IF_BRIDGE(ifp)) + zebra_l2_bridge_del(ifp); + else if (IS_ZEBRA_IF_VXLAN(ifp)) + zebra_l2_vxlanif_del(ifp); + + if (!IS_ZEBRA_IF_VRF(ifp)) + if_delete_update(ifp); } - if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) - { - /* Add interface notification from kernel */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("RTM_NEWLINK ADD for %s(%u) vrf_id %u type %d " - "sl_type %d master %u flags 0x%x", - name, ifi->ifi_index, vrf_id, zif_type, zif_slave_type, - bridge_ifindex, ifi->ifi_flags); - - if (ifp == NULL) - { - /* unknown interface */ - ifp = if_get_by_name (name, vrf_id); - } - else - { - /* pre-configured interface, learnt now */ - if (ifp->vrf_id != vrf_id) - if_update_to_new_vrf (ifp, vrf_id); - } - - /* Update interface information. */ - set_ifindex(ifp, ifi->ifi_index, zns); - ifp->flags = ifi->ifi_flags & 0x0000fffff; - if (IS_ZEBRA_IF_VRF(ifp)) - SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); - ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); - ifp->metric = 0; - ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; - - /* Set interface type */ - zebra_if_set_ziftype (ifp, zif_type, zif_slave_type); - - /* Update link. */ - zebra_if_update_link (ifp, link_ifindex); - - netlink_interface_update_hw_addr (tb, ifp); - - /* Inform clients, install any configured addresses. */ - if_add_update (ifp); - - /* Extract and save L2 interface information, take additional actions. */ - netlink_interface_update_l2info (ifp, linkinfo[IFLA_INFO_DATA], 1); - if (IS_ZEBRA_IF_BRIDGE_SLAVE (ifp)) - zebra_l2if_update_bridge_slave (ifp, bridge_ifindex); - } - else if (ifp->vrf_id != vrf_id) - { - /* VRF change for an interface. */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("RTM_NEWLINK vrf-change for %s(%u) " - "vrf_id %u -> %u flags 0x%x", - name, ifp->ifindex, ifp->vrf_id, - vrf_id, ifi->ifi_flags); - - if_handle_vrf_change (ifp, vrf_id); - } - else - { - int was_bridge_slave; - - /* Interface update. */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("RTM_NEWLINK update for %s(%u) " - "sl_type %d master %u flags 0x%x", - name, ifp->ifindex, zif_slave_type, - bridge_ifindex, ifi->ifi_flags); - - set_ifindex(ifp, ifi->ifi_index, zns); - ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); - ifp->metric = 0; - - /* Update interface type - NOTE: Only slave_type can change. */ - was_bridge_slave = IS_ZEBRA_IF_BRIDGE_SLAVE (ifp); - zebra_if_set_ziftype (ifp, zif_type, zif_slave_type); - - netlink_interface_update_hw_addr (tb, ifp); - - if (if_is_no_ptm_operative (ifp)) - { - ifp->flags = ifi->ifi_flags & 0x0000fffff; - if (!if_is_no_ptm_operative (ifp)) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("Intf %s(%u) has gone DOWN", - name, ifp->ifindex); - if_down (ifp); - } - else if (if_is_operative (ifp)) - { - /* Must notify client daemons of new interface status. */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("Intf %s(%u) PTM up, notifying clients", - name, ifp->ifindex); - zebra_interface_up_update (ifp); - } - } - else - { - ifp->flags = ifi->ifi_flags & 0x0000fffff; - if (if_is_operative (ifp)) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("Intf %s(%u) has come UP", name, ifp->ifindex); - if_up (ifp); - } - } - - /* Extract and save L2 interface information, take additional actions. */ - netlink_interface_update_l2info (ifp, linkinfo[IFLA_INFO_DATA], 0); - if (IS_ZEBRA_IF_BRIDGE_SLAVE (ifp) || was_bridge_slave) - zebra_l2if_update_bridge_slave (ifp, bridge_ifindex); - } - } - else - { - /* Delete interface notification from kernel */ - if (ifp == NULL) - { - zlog_warn ("RTM_DELLINK for unknown interface %s(%u)", - name, ifi->ifi_index); - return 0; - } - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("RTM_DELLINK for %s(%u)", name, ifp->ifindex); - - UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); - - /* Special handling for bridge or VxLAN interfaces. */ - if (IS_ZEBRA_IF_BRIDGE (ifp)) - zebra_l2_bridge_del (ifp); - else if (IS_ZEBRA_IF_VXLAN (ifp)) - zebra_l2_vxlanif_del (ifp); - - if (!IS_ZEBRA_IF_VRF(ifp)) - if_delete_update (ifp); - } - - return 0; + return 0; } /* Interface information read by netlink. */ -void -interface_list (struct zebra_ns *zns) +void interface_list(struct zebra_ns *zns) { - interface_lookup_netlink (zns); + interface_lookup_netlink(zns); } diff --git a/zebra/if_netlink.h b/zebra/if_netlink.h index 0c1b488fb..769c68a87 100644 --- a/zebra/if_netlink.h +++ b/zebra/if_netlink.h @@ -23,11 +23,11 @@ #ifdef HAVE_NETLINK -extern int netlink_interface_addr (struct sockaddr_nl *snl, - struct nlmsghdr *h, ns_id_t ns_id, int startup); -extern int netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup); -extern int interface_lookup_netlink (struct zebra_ns *zns); +extern int netlink_interface_addr(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup); +extern int netlink_link_change(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup); +extern int interface_lookup_netlink(struct zebra_ns *zns); #endif /* HAVE_NETLINK */ diff --git a/zebra/if_sysctl.c b/zebra/if_sysctl.c index dbf5abd12..99b0f9d94 100644 --- a/zebra/if_sysctl.c +++ b/zebra/if_sysctl.c @@ -36,124 +36,101 @@ #include "zebra/kernel_socket.h" #include "zebra/rib.h" -void -ifstat_update_sysctl (void) +void ifstat_update_sysctl(void) { - caddr_t ref, buf, end; - size_t bufsiz; - struct if_msghdr *ifm; - struct interface *ifp; + caddr_t ref, buf, end; + size_t bufsiz; + struct if_msghdr *ifm; + struct interface *ifp; #define MIBSIZ 6 - int mib[MIBSIZ] = - { - CTL_NET, - PF_ROUTE, - 0, - 0, /* AF_INET & AF_INET6 */ - NET_RT_IFLIST, - 0 - }; - - /* Query buffer size. */ - if (sysctl (mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) - { - zlog_warn ("sysctl() error by %s", safe_strerror (errno)); - return; - } - - /* We free this memory at the end of this function. */ - ref = buf = XMALLOC (MTYPE_TMP, bufsiz); - - /* Fetch interface informations into allocated buffer. */ - if (sysctl (mib, MIBSIZ, buf, &bufsiz, NULL, 0) < 0) - { - zlog_warn("sysctl error by %s", safe_strerror(errno)); - XFREE(MTYPE_TMP, ref); - return; - } - - /* Parse both interfaces and addresses. */ - for (end = buf + bufsiz; buf < end; buf += ifm->ifm_msglen) - { - ifm = (struct if_msghdr *) buf; - if (ifm->ifm_type == RTM_IFINFO) - { - ifp = if_lookup_by_index (ifm->ifm_index, VRF_DEFAULT); - if (ifp) - ifp->stats = ifm->ifm_data; + int mib[MIBSIZ] = { + CTL_NET, PF_ROUTE, 0, 0, /* AF_INET & AF_INET6 */ + NET_RT_IFLIST, 0}; + + /* Query buffer size. */ + if (sysctl(mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) { + zlog_warn("sysctl() error by %s", safe_strerror(errno)); + return; } - } - /* Free sysctl buffer. */ - XFREE (MTYPE_TMP, ref); + /* We free this memory at the end of this function. */ + ref = buf = XMALLOC(MTYPE_TMP, bufsiz); - return; + /* Fetch interface informations into allocated buffer. */ + if (sysctl(mib, MIBSIZ, buf, &bufsiz, NULL, 0) < 0) { + zlog_warn("sysctl error by %s", safe_strerror(errno)); + XFREE(MTYPE_TMP, ref); + return; + } + + /* Parse both interfaces and addresses. */ + for (end = buf + bufsiz; buf < end; buf += ifm->ifm_msglen) { + ifm = (struct if_msghdr *)buf; + if (ifm->ifm_type == RTM_IFINFO) { + ifp = if_lookup_by_index(ifm->ifm_index, VRF_DEFAULT); + if (ifp) + ifp->stats = ifm->ifm_data; + } + } + + /* Free sysctl buffer. */ + XFREE(MTYPE_TMP, ref); + + return; } /* Interface listing up function using sysctl(). */ -void -interface_list (struct zebra_ns *zns) +void interface_list(struct zebra_ns *zns) { - caddr_t ref, buf, end; - size_t bufsiz; - struct if_msghdr *ifm; + caddr_t ref, buf, end; + size_t bufsiz; + struct if_msghdr *ifm; #define MIBSIZ 6 - int mib[MIBSIZ] = - { - CTL_NET, - PF_ROUTE, - 0, - 0, /* AF_INET & AF_INET6 */ - NET_RT_IFLIST, - 0 - }; - - if (zns->ns_id != NS_DEFAULT) - { - zlog_warn ("interface_list: ignore NS %u", zns->ns_id); - return; - } - - /* Query buffer size. */ - if (sysctl (mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) - { - zlog_warn("sysctl() error by %s", safe_strerror(errno)); - return; - } - - /* We free this memory at the end of this function. */ - ref = buf = XMALLOC (MTYPE_TMP, bufsiz); - - /* Fetch interface informations into allocated buffer. */ - if (sysctl (mib, MIBSIZ, buf, &bufsiz, NULL, 0) < 0) - { - zlog_warn("sysctl error by %s", safe_strerror(errno)); - return; - } - - /* Parse both interfaces and addresses. */ - for (end = buf + bufsiz; buf < end; buf += ifm->ifm_msglen) - { - ifm = (struct if_msghdr *) buf; - - switch (ifm->ifm_type) - { - case RTM_IFINFO: - ifm_read (ifm); - break; - case RTM_NEWADDR: - ifam_read ((struct ifa_msghdr *) ifm); - break; - default: - zlog_info ("interfaces_list(): unexpected message type"); - XFREE (MTYPE_TMP, ref); - return; - break; + int mib[MIBSIZ] = { + CTL_NET, PF_ROUTE, 0, 0, /* AF_INET & AF_INET6 */ + NET_RT_IFLIST, 0}; + + if (zns->ns_id != NS_DEFAULT) { + zlog_warn("interface_list: ignore NS %u", zns->ns_id); + return; + } + + /* Query buffer size. */ + if (sysctl(mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) { + zlog_warn("sysctl() error by %s", safe_strerror(errno)); + return; + } + + /* We free this memory at the end of this function. */ + ref = buf = XMALLOC(MTYPE_TMP, bufsiz); + + /* Fetch interface informations into allocated buffer. */ + if (sysctl(mib, MIBSIZ, buf, &bufsiz, NULL, 0) < 0) { + zlog_warn("sysctl error by %s", safe_strerror(errno)); + return; + } + + /* Parse both interfaces and addresses. */ + for (end = buf + bufsiz; buf < end; buf += ifm->ifm_msglen) { + ifm = (struct if_msghdr *)buf; + + switch (ifm->ifm_type) { + case RTM_IFINFO: + ifm_read(ifm); + break; + case RTM_NEWADDR: + ifam_read((struct ifa_msghdr *)ifm); + break; + default: + zlog_info("interfaces_list(): unexpected message type"); + XFREE(MTYPE_TMP, ref); + return; + break; + } } - } - /* Free sysctl buffer. */ - XFREE (MTYPE_TMP, ref); + /* Free sysctl buffer. */ + XFREE(MTYPE_TMP, ref); } diff --git a/zebra/interface.c b/zebra/interface.c index 9618e9bb1..26b243382 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -51,287 +51,280 @@ #define ZEBRA_PTM_SUPPORT -#if defined (HAVE_RTADV) +#if defined(HAVE_RTADV) /* Order is intentional. Matches RFC4191. This array is also used for command matching, so only modify with care. */ -const char *rtadv_pref_strs[] = { "medium", "high", "INVALID", "low", 0 }; +const char *rtadv_pref_strs[] = {"medium", "high", "INVALID", "low", 0}; #endif /* HAVE_RTADV */ -static void if_down_del_nbr_connected (struct interface *ifp); +static void if_down_del_nbr_connected(struct interface *ifp); -static void -zebra_if_node_destroy (route_table_delegate_t *delegate, - struct route_table *table, struct route_node *node) +static void zebra_if_node_destroy(route_table_delegate_t *delegate, + struct route_table *table, + struct route_node *node) { - if (node->info) - list_delete (node->info); - route_node_destroy (delegate, table, node); + if (node->info) + list_delete(node->info); + route_node_destroy(delegate, table, node); } route_table_delegate_t zebra_if_table_delegate = { - .create_node = route_node_create, - .destroy_node = zebra_if_node_destroy -}; + .create_node = route_node_create, + .destroy_node = zebra_if_node_destroy}; /* Called when new interface is added. */ -static int -if_zebra_new_hook (struct interface *ifp) -{ - struct zebra_if *zebra_if; - - zebra_if = XCALLOC (MTYPE_TMP, sizeof (struct zebra_if)); - - zebra_if->multicast = IF_ZEBRA_MULTICAST_UNSPEC; - zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_OFF; - zebra_ptm_if_init(zebra_if); - - ifp->ptm_enable = zebra_ptm_get_enable_state(); -#if defined (HAVE_RTADV) - { - /* Set default router advertise values. */ - struct rtadvconf *rtadv; - - rtadv = &zebra_if->rtadv; - - rtadv->AdvSendAdvertisements = 0; - rtadv->MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL; - rtadv->MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL; - rtadv->AdvIntervalTimer = 0; - rtadv->AdvManagedFlag = 0; - rtadv->AdvOtherConfigFlag = 0; - rtadv->AdvHomeAgentFlag = 0; - rtadv->AdvLinkMTU = 0; - rtadv->AdvReachableTime = 0; - rtadv->AdvRetransTimer = 0; - rtadv->AdvCurHopLimit = 0; - rtadv->AdvDefaultLifetime = -1; /* derive from MaxRtrAdvInterval */ - rtadv->HomeAgentPreference = 0; - rtadv->HomeAgentLifetime = -1; /* derive from AdvDefaultLifetime */ - rtadv->AdvIntervalOption = 0; - rtadv->DefaultPreference = RTADV_PREF_MEDIUM; - - rtadv->AdvPrefixList = list_new (); - } +static int if_zebra_new_hook(struct interface *ifp) +{ + struct zebra_if *zebra_if; + + zebra_if = XCALLOC(MTYPE_TMP, sizeof(struct zebra_if)); + + zebra_if->multicast = IF_ZEBRA_MULTICAST_UNSPEC; + zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_OFF; + zebra_ptm_if_init(zebra_if); + + ifp->ptm_enable = zebra_ptm_get_enable_state(); +#if defined(HAVE_RTADV) + { + /* Set default router advertise values. */ + struct rtadvconf *rtadv; + + rtadv = &zebra_if->rtadv; + + rtadv->AdvSendAdvertisements = 0; + rtadv->MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL; + rtadv->MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL; + rtadv->AdvIntervalTimer = 0; + rtadv->AdvManagedFlag = 0; + rtadv->AdvOtherConfigFlag = 0; + rtadv->AdvHomeAgentFlag = 0; + rtadv->AdvLinkMTU = 0; + rtadv->AdvReachableTime = 0; + rtadv->AdvRetransTimer = 0; + rtadv->AdvCurHopLimit = 0; + rtadv->AdvDefaultLifetime = + -1; /* derive from MaxRtrAdvInterval */ + rtadv->HomeAgentPreference = 0; + rtadv->HomeAgentLifetime = + -1; /* derive from AdvDefaultLifetime */ + rtadv->AdvIntervalOption = 0; + rtadv->DefaultPreference = RTADV_PREF_MEDIUM; + + rtadv->AdvPrefixList = list_new(); + } #endif /* HAVE_RTADV */ - /* Initialize installed address chains tree. */ - zebra_if->ipv4_subnets = route_table_init_with_delegate (&zebra_if_table_delegate); + /* Initialize installed address chains tree. */ + zebra_if->ipv4_subnets = + route_table_init_with_delegate(&zebra_if_table_delegate); - ifp->info = zebra_if; + ifp->info = zebra_if; - zebra_vrf_static_route_interface_fixup (ifp); - return 0; + zebra_vrf_static_route_interface_fixup(ifp); + return 0; } /* Called when interface is deleted. */ -static int -if_zebra_delete_hook (struct interface *ifp) +static int if_zebra_delete_hook(struct interface *ifp) { - struct zebra_if *zebra_if; - - if (ifp->info) - { - zebra_if = ifp->info; + struct zebra_if *zebra_if; - /* Free installed address chains tree. */ - if (zebra_if->ipv4_subnets) - route_table_finish (zebra_if->ipv4_subnets); - #if defined (HAVE_RTADV) + if (ifp->info) { + zebra_if = ifp->info; - struct rtadvconf *rtadv; + /* Free installed address chains tree. */ + if (zebra_if->ipv4_subnets) + route_table_finish(zebra_if->ipv4_subnets); +#if defined(HAVE_RTADV) - rtadv = &zebra_if->rtadv; - list_free (rtadv->AdvPrefixList); - #endif /* HAVE_RTADV */ + struct rtadvconf *rtadv; - XFREE (MTYPE_TMP, zebra_if); - } + rtadv = &zebra_if->rtadv; + list_free(rtadv->AdvPrefixList); +#endif /* HAVE_RTADV */ - return 0; + XFREE(MTYPE_TMP, zebra_if); + } + + return 0; } /* Build the table key */ -static void -if_build_key (u_int32_t ifindex, struct prefix *p) +static void if_build_key(u_int32_t ifindex, struct prefix *p) { - p->family = AF_INET; - p->prefixlen = IPV4_MAX_BITLEN; - p->u.prefix4.s_addr = ifindex; + p->family = AF_INET; + p->prefixlen = IPV4_MAX_BITLEN; + p->u.prefix4.s_addr = ifindex; } /* Link an interface in a per NS interface tree */ -struct interface * -if_link_per_ns (struct zebra_ns *ns, struct interface *ifp) +struct interface *if_link_per_ns(struct zebra_ns *ns, struct interface *ifp) { - struct prefix p; - struct route_node *rn; + struct prefix p; + struct route_node *rn; - if (ifp->ifindex == IFINDEX_INTERNAL) - return NULL; + if (ifp->ifindex == IFINDEX_INTERNAL) + return NULL; - if_build_key (ifp->ifindex, &p); - rn = route_node_get (ns->if_table, &p); - if (rn->info) - { - ifp = (struct interface *)rn->info; - route_unlock_node (rn); /* get */ - return ifp; - } + if_build_key(ifp->ifindex, &p); + rn = route_node_get(ns->if_table, &p); + if (rn->info) { + ifp = (struct interface *)rn->info; + route_unlock_node(rn); /* get */ + return ifp; + } - rn->info = ifp; - ifp->node = rn; + rn->info = ifp; + ifp->node = rn; - return ifp; + return ifp; } /* Delete a VRF. This is called in vrf_terminate(). */ -void -if_unlink_per_ns (struct interface *ifp) +void if_unlink_per_ns(struct interface *ifp) { - ifp->node->info = NULL; - route_unlock_node(ifp->node); - ifp->node = NULL; + ifp->node->info = NULL; + route_unlock_node(ifp->node); + ifp->node = NULL; } /* Look up an interface by identifier within a NS */ -struct interface * -if_lookup_by_index_per_ns (struct zebra_ns *ns, u_int32_t ifindex) -{ - struct prefix p; - struct route_node *rn; - struct interface *ifp = NULL; - - if_build_key (ifindex, &p); - rn = route_node_lookup (ns->if_table, &p); - if (rn) - { - ifp = (struct interface *)rn->info; - route_unlock_node (rn); /* lookup */ - } - return ifp; +struct interface *if_lookup_by_index_per_ns(struct zebra_ns *ns, + u_int32_t ifindex) +{ + struct prefix p; + struct route_node *rn; + struct interface *ifp = NULL; + + if_build_key(ifindex, &p); + rn = route_node_lookup(ns->if_table, &p); + if (rn) { + ifp = (struct interface *)rn->info; + route_unlock_node(rn); /* lookup */ + } + return ifp; } /* Look up an interface by name within a NS */ -struct interface * -if_lookup_by_name_per_ns (struct zebra_ns *ns, const char *ifname) +struct interface *if_lookup_by_name_per_ns(struct zebra_ns *ns, + const char *ifname) { - struct route_node *rn; - struct interface *ifp; + struct route_node *rn; + struct interface *ifp; - for (rn = route_top (ns->if_table); rn; rn = route_next (rn)) - { - ifp = (struct interface *)rn->info; - if (ifp && strcmp (ifp->name, ifname) == 0) - return (ifp); - } + for (rn = route_top(ns->if_table); rn; rn = route_next(rn)) { + ifp = (struct interface *)rn->info; + if (ifp && strcmp(ifp->name, ifname) == 0) + return (ifp); + } - return NULL; + return NULL; } -const char * -ifindex2ifname_per_ns (struct zebra_ns *zns, unsigned int ifindex) +const char *ifindex2ifname_per_ns(struct zebra_ns *zns, unsigned int ifindex) { - struct interface *ifp; + struct interface *ifp; - return ((ifp = if_lookup_by_index_per_ns (zns, ifindex)) != NULL) ? - ifp->name : "unknown"; + return ((ifp = if_lookup_by_index_per_ns(zns, ifindex)) != NULL) + ? ifp->name + : "unknown"; } /* Tie an interface address to its derived subnet list of addresses. */ -int -if_subnet_add (struct interface *ifp, struct connected *ifc) -{ - struct route_node *rn; - struct zebra_if *zebra_if; - struct prefix cp; - struct list *addr_list; - - assert (ifp && ifp->info && ifc); - zebra_if = ifp->info; - - /* Get address derived subnet node and associated address list, while marking - address secondary attribute appropriately. */ - cp = *ifc->address; - apply_mask (&cp); - rn = route_node_get (zebra_if->ipv4_subnets, &cp); - - if ((addr_list = rn->info)) - SET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY); - else - { - UNSET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY); - rn->info = addr_list = list_new (); - route_lock_node (rn); - } - - /* Tie address at the tail of address list. */ - listnode_add (addr_list, ifc); - - /* Return list element count. */ - return (addr_list->count); +int if_subnet_add(struct interface *ifp, struct connected *ifc) +{ + struct route_node *rn; + struct zebra_if *zebra_if; + struct prefix cp; + struct list *addr_list; + + assert(ifp && ifp->info && ifc); + zebra_if = ifp->info; + + /* Get address derived subnet node and associated address list, while + marking + address secondary attribute appropriately. */ + cp = *ifc->address; + apply_mask(&cp); + rn = route_node_get(zebra_if->ipv4_subnets, &cp); + + if ((addr_list = rn->info)) + SET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY); + else { + UNSET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY); + rn->info = addr_list = list_new(); + route_lock_node(rn); + } + + /* Tie address at the tail of address list. */ + listnode_add(addr_list, ifc); + + /* Return list element count. */ + return (addr_list->count); } /* Untie an interface address from its derived subnet list of addresses. */ -int -if_subnet_delete (struct interface *ifp, struct connected *ifc) -{ - struct route_node *rn; - struct zebra_if *zebra_if; - struct list *addr_list; - - assert (ifp && ifp->info && ifc); - zebra_if = ifp->info; - - /* Get address derived subnet node. */ - rn = route_node_lookup (zebra_if->ipv4_subnets, ifc->address); - if (! (rn && rn->info)) - { - zlog_warn("Trying to remove an address from an unknown subnet." - " (please report this bug)"); - return -1; - } - route_unlock_node (rn); - - /* Untie address from subnet's address list. */ - addr_list = rn->info; - - /* Deleting an address that is not registered is a bug. - * In any case, we shouldn't decrement the lock counter if the address - * is unknown. */ - if (!listnode_lookup(addr_list, ifc)) - { - zlog_warn("Trying to remove an address from a subnet where it is not" - " currently registered. (please report this bug)"); - return -1; - } - - listnode_delete (addr_list, ifc); - route_unlock_node (rn); - - /* Return list element count, if not empty. */ - if (addr_list->count) - { - /* If deleted address is primary, mark subsequent one as such and distribute. */ - if (! CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY)) - { - ifc = listgetdata ((struct listnode *)listhead (addr_list)); - zebra_interface_address_delete_update (ifp, ifc); - UNSET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY); - /* XXX: Linux kernel removes all the secondary addresses when the primary - * address is removed. We could try to work around that, though this is - * non-trivial. */ - zebra_interface_address_add_update (ifp, ifc); - } - - return addr_list->count; - } - - /* Otherwise, free list and route node. */ - list_free (addr_list); - rn->info = NULL; - route_unlock_node (rn); - - return 0; +int if_subnet_delete(struct interface *ifp, struct connected *ifc) +{ + struct route_node *rn; + struct zebra_if *zebra_if; + struct list *addr_list; + + assert(ifp && ifp->info && ifc); + zebra_if = ifp->info; + + /* Get address derived subnet node. */ + rn = route_node_lookup(zebra_if->ipv4_subnets, ifc->address); + if (!(rn && rn->info)) { + zlog_warn( + "Trying to remove an address from an unknown subnet." + " (please report this bug)"); + return -1; + } + route_unlock_node(rn); + + /* Untie address from subnet's address list. */ + addr_list = rn->info; + + /* Deleting an address that is not registered is a bug. + * In any case, we shouldn't decrement the lock counter if the address + * is unknown. */ + if (!listnode_lookup(addr_list, ifc)) { + zlog_warn( + "Trying to remove an address from a subnet where it is not" + " currently registered. (please report this bug)"); + return -1; + } + + listnode_delete(addr_list, ifc); + route_unlock_node(rn); + + /* Return list element count, if not empty. */ + if (addr_list->count) { + /* If deleted address is primary, mark subsequent one as such + * and distribute. */ + if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) { + ifc = listgetdata( + (struct listnode *)listhead(addr_list)); + zebra_interface_address_delete_update(ifp, ifc); + UNSET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY); + /* XXX: Linux kernel removes all the secondary addresses + * when the primary + * address is removed. We could try to work around that, + * though this is + * non-trivial. */ + zebra_interface_address_add_update(ifp, ifc); + } + + return addr_list->count; + } + + /* Otherwise, free list and route node. */ + list_free(addr_list); + rn->info = NULL; + route_unlock_node(rn); + + return 0; } /* if_flags_mangle: A place for hacks that require mangling @@ -340,10 +333,10 @@ if_subnet_delete (struct interface *ifp, struct connected *ifc) * ******************** Solaris flags hacks ************************** * * Solaris IFF_UP flag reflects only the primary interface as the - * routing socket only sends IFINFO for the primary interface. Hence - * ~IFF_UP does not per se imply all the logical interfaces are also + * routing socket only sends IFINFO for the primary interface. Hence + * ~IFF_UP does not per se imply all the logical interfaces are also * down - which we only know of as addresses. Instead we must determine - * whether the interface really is up or not according to how many + * whether the interface really is up or not according to how many * addresses are still attached. (Solaris always sends RTM_DELADDR if * an interface, logical or not, goes ~IFF_UP). * @@ -358,19 +351,18 @@ if_subnet_delete (struct interface *ifp, struct connected *ifc) * interface will affect only the primary interface/address on Solaris. ************************End Solaris flags hacks *********************** */ -static void -if_flags_mangle (struct interface *ifp, uint64_t *newflags) +static void if_flags_mangle(struct interface *ifp, uint64_t *newflags) { #ifdef SUNOS_5 - struct zebra_if *zif = ifp->info; - - zif->primary_state = *newflags & (IFF_UP & 0xff); - - if (CHECK_FLAG (zif->primary_state, IFF_UP) - || listcount(ifp->connected) > 0) - SET_FLAG (*newflags, IFF_UP); - else - UNSET_FLAG (*newflags, IFF_UP); + struct zebra_if *zif = ifp->info; + + zif->primary_state = *newflags & (IFF_UP & 0xff); + + if (CHECK_FLAG(zif->primary_state, IFF_UP) + || listcount(ifp->connected) > 0) + SET_FLAG(*newflags, IFF_UP); + else + UNSET_FLAG(*newflags, IFF_UP); #endif /* SUNOS_5 */ } @@ -380,1034 +372,1003 @@ if_flags_mangle (struct interface *ifp, uint64_t *newflags) * * newflags should be the raw value, as obtained from the OS. */ -void -if_flags_update (struct interface *ifp, uint64_t newflags) -{ - if_flags_mangle (ifp, &newflags); - - if (if_is_no_ptm_operative (ifp)) - { - /* operative -> inoperative? */ - ifp->flags = newflags; - if (!if_is_operative (ifp)) - if_down (ifp); - } - else - { - /* inoperative -> operative? */ - ifp->flags = newflags; - if (if_is_operative (ifp)) - if_up (ifp); - } +void if_flags_update(struct interface *ifp, uint64_t newflags) +{ + if_flags_mangle(ifp, &newflags); + + if (if_is_no_ptm_operative(ifp)) { + /* operative -> inoperative? */ + ifp->flags = newflags; + if (!if_is_operative(ifp)) + if_down(ifp); + } else { + /* inoperative -> operative? */ + ifp->flags = newflags; + if (if_is_operative(ifp)) + if_up(ifp); + } } /* Wake up configured address if it is not in current kernel address. */ -static void -if_addr_wakeup (struct interface *ifp) -{ - struct listnode *node, *nnode; - struct connected *ifc; - struct prefix *p; - int ret; - - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, ifc)) - { - p = ifc->address; - - if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED) - && ! CHECK_FLAG (ifc->conf, ZEBRA_IFC_QUEUED)) - { - /* Address check. */ - if (p->family == AF_INET) - { - if (! if_is_up (ifp)) - { - /* Assume zebra is configured like following: - * - * interface gre0 - * ip addr 192.0.2.1/24 - * ! - * - * As soon as zebra becomes first aware that gre0 exists in the - * kernel, it will set gre0 up and configure its addresses. - * - * (This may happen at startup when the interface already exists - * or during runtime when the interface is added to the kernel) - * - * XXX: IRDP code is calling here via if_add_update - this seems - * somewhat weird. - * XXX: RUNNING is not a settable flag on any system - * I (paulj) am aware of. - */ - if_set_flags (ifp, IFF_UP | IFF_RUNNING); - if_refresh (ifp); - } - - ret = if_set_prefix (ifp, ifc); - if (ret < 0) - { - zlog_warn ("Can't set interface's address: %s", - safe_strerror(errno)); - continue; - } +static void if_addr_wakeup(struct interface *ifp) +{ + struct listnode *node, *nnode; + struct connected *ifc; + struct prefix *p; + int ret; - SET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); - /* The address will be advertised to zebra clients when the notification - * from the kernel has been received. - * It will also be added to the interface's subnet list then. */ - } - if (p->family == AF_INET6) - { - if (! if_is_up (ifp)) - { - /* See long comment above */ - if_set_flags (ifp, IFF_UP | IFF_RUNNING); - if_refresh (ifp); - } + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, ifc)) { + p = ifc->address; - ret = if_prefix_add_ipv6 (ifp, ifc); - if (ret < 0) - { - zlog_warn ("Can't set interface's address: %s", - safe_strerror(errno)); - continue; + if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED) + && !CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)) { + /* Address check. */ + if (p->family == AF_INET) { + if (!if_is_up(ifp)) { + /* Assume zebra is configured like + * following: + * + * interface gre0 + * ip addr 192.0.2.1/24 + * ! + * + * As soon as zebra becomes first aware + * that gre0 exists in the + * kernel, it will set gre0 up and + * configure its addresses. + * + * (This may happen at startup when the + * interface already exists + * or during runtime when the interface + * is added to the kernel) + * + * XXX: IRDP code is calling here via + * if_add_update - this seems + * somewhat weird. + * XXX: RUNNING is not a settable flag + * on any system + * I (paulj) am aware of. + */ + if_set_flags(ifp, IFF_UP | IFF_RUNNING); + if_refresh(ifp); + } + + ret = if_set_prefix(ifp, ifc); + if (ret < 0) { + zlog_warn( + "Can't set interface's address: %s", + safe_strerror(errno)); + continue; + } + + SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + /* The address will be advertised to zebra + * clients when the notification + * from the kernel has been received. + * It will also be added to the interface's + * subnet list then. */ + } + if (p->family == AF_INET6) { + if (!if_is_up(ifp)) { + /* See long comment above */ + if_set_flags(ifp, IFF_UP | IFF_RUNNING); + if_refresh(ifp); + } + + ret = if_prefix_add_ipv6(ifp, ifc); + if (ret < 0) { + zlog_warn( + "Can't set interface's address: %s", + safe_strerror(errno)); + continue; + } + + SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + /* The address will be advertised to zebra + * clients when the notification + * from the kernel has been received. */ + } } - - SET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); - /* The address will be advertised to zebra clients when the notification - * from the kernel has been received. */ - } } - } } /* Handle interface addition */ -void -if_add_update (struct interface *ifp) +void if_add_update(struct interface *ifp) { - struct zebra_if *if_data; + struct zebra_if *if_data; - if_link_per_ns(zebra_ns_lookup (NS_DEFAULT), ifp); + if_link_per_ns(zebra_ns_lookup(NS_DEFAULT), ifp); - if_data = ifp->info; - assert(if_data); + if_data = ifp->info; + assert(if_data); - if (if_data->multicast == IF_ZEBRA_MULTICAST_ON) - if_set_flags (ifp, IFF_MULTICAST); - else if (if_data->multicast == IF_ZEBRA_MULTICAST_OFF) - if_unset_flags (ifp, IFF_MULTICAST); + if (if_data->multicast == IF_ZEBRA_MULTICAST_ON) + if_set_flags(ifp, IFF_MULTICAST); + else if (if_data->multicast == IF_ZEBRA_MULTICAST_OFF) + if_unset_flags(ifp, IFF_MULTICAST); - zebra_ptm_if_set_ptm_state(ifp, if_data); + zebra_ptm_if_set_ptm_state(ifp, if_data); - zebra_interface_add_update (ifp); + zebra_interface_add_update(ifp); - if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) - { - SET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE); + if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + SET_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE); - if (if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("interface %s vrf %u index %d is shutdown. " - "Won't wake it up.", - ifp->name, ifp->vrf_id, ifp->ifindex); - return; - } + if (if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "interface %s vrf %u index %d is shutdown. " + "Won't wake it up.", + ifp->name, ifp->vrf_id, ifp->ifindex); + return; + } - if_addr_wakeup (ifp); + if_addr_wakeup(ifp); - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("interface %s vrf %u index %d becomes active.", - ifp->name, ifp->vrf_id, ifp->ifindex); - } - else - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("interface %s vrf %u index %d is added.", - ifp->name, ifp->vrf_id, ifp->ifindex); - } + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "interface %s vrf %u index %d becomes active.", + ifp->name, ifp->vrf_id, ifp->ifindex); + } else { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("interface %s vrf %u index %d is added.", + ifp->name, ifp->vrf_id, ifp->ifindex); + } } /* Install connected routes corresponding to an interface. */ -static void -if_install_connected (struct interface *ifp) -{ - struct listnode *node; - struct listnode *next; - struct connected *ifc; - struct prefix *p; - - if (ifp->connected) - { - for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc)) - { - if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) - zebra_interface_address_add_update (ifp, ifc); - - p = ifc->address; - if (p->family == AF_INET) - connected_up_ipv4 (ifp, ifc); - else if (p->family == AF_INET6) - connected_up_ipv6 (ifp, ifc); +static void if_install_connected(struct interface *ifp) +{ + struct listnode *node; + struct listnode *next; + struct connected *ifc; + struct prefix *p; + + if (ifp->connected) { + for (ALL_LIST_ELEMENTS(ifp->connected, node, next, ifc)) { + if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) + zebra_interface_address_add_update(ifp, ifc); + + p = ifc->address; + if (p->family == AF_INET) + connected_up_ipv4(ifp, ifc); + else if (p->family == AF_INET6) + connected_up_ipv6(ifp, ifc); + } } - } } /* Uninstall connected routes corresponding to an interface. */ -static void -if_uninstall_connected (struct interface *ifp) -{ - struct listnode *node; - struct listnode *next; - struct connected *ifc; - struct prefix *p; - - if (ifp->connected) - { - for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc)) - { - p = ifc->address; - zebra_interface_address_delete_update (ifp, ifc); - - if (p->family == AF_INET) - connected_down_ipv4 (ifp, ifc); - else if (p->family == AF_INET6) - connected_down_ipv6 (ifp, ifc); +static void if_uninstall_connected(struct interface *ifp) +{ + struct listnode *node; + struct listnode *next; + struct connected *ifc; + struct prefix *p; + + if (ifp->connected) { + for (ALL_LIST_ELEMENTS(ifp->connected, node, next, ifc)) { + p = ifc->address; + zebra_interface_address_delete_update(ifp, ifc); + + if (p->family == AF_INET) + connected_down_ipv4(ifp, ifc); + else if (p->family == AF_INET6) + connected_down_ipv6(ifp, ifc); + } } - } } /* Uninstall and delete connected routes corresponding to an interface. */ /* TODO - Check why IPv4 handling here is different from install or if_down */ -static void -if_delete_connected (struct interface *ifp) -{ - struct connected *ifc; - struct prefix *p; - struct route_node *rn; - struct zebra_if *zebra_if; - - zebra_if = ifp->info; - - if (ifp->connected) - { - struct listnode *node; - struct listnode *last = NULL; - - while ((node = (last ? last->next : listhead (ifp->connected)))) - { - ifc = listgetdata (node); - p = ifc->address; - - if (p->family == AF_INET - && (rn = route_node_lookup (zebra_if->ipv4_subnets, p))) - { - struct listnode *anode; - struct listnode *next; - struct listnode *first; - struct list *addr_list; - - route_unlock_node (rn); - addr_list = (struct list *) rn->info; - - /* Remove addresses, secondaries first. */ - first = listhead (addr_list); - for (anode = first->next; anode || first; anode = next) - { - if (!anode) - { - anode = first; - first = NULL; - } - next = anode->next; - - ifc = listgetdata (anode); - connected_down_ipv4 (ifp, ifc); - - /* XXX: We have to send notifications here explicitly, because we destroy - * the ifc before receiving the notification about the address being deleted. - */ - zebra_interface_address_delete_update (ifp, ifc); - - UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL); - UNSET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); - - /* Remove from subnet chain. */ - list_delete_node (addr_list, anode); - route_unlock_node (rn); - - /* Remove from interface address list (unconditionally). */ - if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) - { - listnode_delete (ifp->connected, ifc); - connected_free (ifc); - } - else - last = node; - } - - /* Free chain list and respective route node. */ - list_delete (addr_list); - rn->info = NULL; - route_unlock_node (rn); - } - else if (p->family == AF_INET6) - { - connected_down_ipv6 (ifp, ifc); - - zebra_interface_address_delete_update (ifp, ifc); - - UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL); - UNSET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); - - if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) - last = node; - else - { - listnode_delete (ifp->connected, ifc); - connected_free (ifc); +static void if_delete_connected(struct interface *ifp) +{ + struct connected *ifc; + struct prefix *p; + struct route_node *rn; + struct zebra_if *zebra_if; + + zebra_if = ifp->info; + + if (ifp->connected) { + struct listnode *node; + struct listnode *last = NULL; + + while ((node = (last ? last->next + : listhead(ifp->connected)))) { + ifc = listgetdata(node); + p = ifc->address; + + if (p->family == AF_INET + && (rn = route_node_lookup(zebra_if->ipv4_subnets, + p))) { + struct listnode *anode; + struct listnode *next; + struct listnode *first; + struct list *addr_list; + + route_unlock_node(rn); + addr_list = (struct list *)rn->info; + + /* Remove addresses, secondaries first. */ + first = listhead(addr_list); + for (anode = first->next; anode || first; + anode = next) { + if (!anode) { + anode = first; + first = NULL; + } + next = anode->next; + + ifc = listgetdata(anode); + connected_down_ipv4(ifp, ifc); + + /* XXX: We have to send notifications + * here explicitly, because we destroy + * the ifc before receiving the + * notification about the address being + * deleted. + */ + zebra_interface_address_delete_update( + ifp, ifc); + + UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL); + UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + + /* Remove from subnet chain. */ + list_delete_node(addr_list, anode); + route_unlock_node(rn); + + /* Remove from interface address list + * (unconditionally). */ + if (!CHECK_FLAG(ifc->conf, + ZEBRA_IFC_CONFIGURED)) { + listnode_delete(ifp->connected, + ifc); + connected_free(ifc); + } else + last = node; + } + + /* Free chain list and respective route node. */ + list_delete(addr_list); + rn->info = NULL; + route_unlock_node(rn); + } else if (p->family == AF_INET6) { + connected_down_ipv6(ifp, ifc); + + zebra_interface_address_delete_update(ifp, ifc); + + UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL); + UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + + if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) + last = node; + else { + listnode_delete(ifp->connected, ifc); + connected_free(ifc); + } + } else { + last = node; + } } - } - else - { - last = node; - } } - } } /* Handle an interface delete event */ -void -if_delete_update (struct interface *ifp) +void if_delete_update(struct interface *ifp) { - struct zebra_if *zif; - - if (if_is_up(ifp)) - { - zlog_err ("interface %s vrf %u index %d is still up while being deleted.", - ifp->name, ifp->vrf_id, ifp->ifindex); - return; - } - - /* Mark interface as inactive */ - UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE); - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("interface %s vrf %u index %d is now inactive.", - ifp->name, ifp->vrf_id, ifp->ifindex); - - /* Delete connected routes from the kernel. */ - if_delete_connected (ifp); - - /* Send out notification on interface delete. */ - zebra_interface_delete_update (ifp); + struct zebra_if *zif; - if_unlink_per_ns(ifp); - - /* Update ifindex after distributing the delete message. This is in - case any client needs to have the old value of ifindex available - while processing the deletion. Each client daemon is responsible - for setting ifindex to IFINDEX_INTERNAL after processing the - interface deletion message. */ - ifp->ifindex = IFINDEX_INTERNAL; - ifp->node = NULL; - - /* if the ifp is in a vrf, move it to default so vrf can be deleted if desired */ - if (ifp->vrf_id) - if_handle_vrf_change (ifp, VRF_DEFAULT); + if (if_is_up(ifp)) { + zlog_err( + "interface %s vrf %u index %d is still up while being deleted.", + ifp->name, ifp->vrf_id, ifp->ifindex); + return; + } - /* Reset some zebra interface params to default values. */ - zif = ifp->info; - if (zif) - { - zif->zif_type = ZEBRA_IF_OTHER; - zif->zif_slave_type = ZEBRA_IF_SLAVE_NONE; - memset (&zif->l2info, 0, sizeof (union zebra_l2if_info)); - memset (&zif->brslave_info, 0, sizeof (struct zebra_l2info_brslave)); - } + /* Mark interface as inactive */ + UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE); + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("interface %s vrf %u index %d is now inactive.", + ifp->name, ifp->vrf_id, ifp->ifindex); + + /* Delete connected routes from the kernel. */ + if_delete_connected(ifp); + + /* Send out notification on interface delete. */ + zebra_interface_delete_update(ifp); + + if_unlink_per_ns(ifp); + + /* Update ifindex after distributing the delete message. This is in + case any client needs to have the old value of ifindex available + while processing the deletion. Each client daemon is responsible + for setting ifindex to IFINDEX_INTERNAL after processing the + interface deletion message. */ + ifp->ifindex = IFINDEX_INTERNAL; + ifp->node = NULL; + + /* if the ifp is in a vrf, move it to default so vrf can be deleted if + * desired */ + if (ifp->vrf_id) + if_handle_vrf_change(ifp, VRF_DEFAULT); + + /* Reset some zebra interface params to default values. */ + zif = ifp->info; + if (zif) { + zif->zif_type = ZEBRA_IF_OTHER; + zif->zif_slave_type = ZEBRA_IF_SLAVE_NONE; + memset(&zif->l2info, 0, sizeof(union zebra_l2if_info)); + memset(&zif->brslave_info, 0, + sizeof(struct zebra_l2info_brslave)); + } } /* VRF change for an interface */ -void -if_handle_vrf_change (struct interface *ifp, vrf_id_t vrf_id) +void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id) { - vrf_id_t old_vrf_id; + vrf_id_t old_vrf_id; - old_vrf_id = ifp->vrf_id; + old_vrf_id = ifp->vrf_id; - /* Uninstall connected routes. */ - if_uninstall_connected (ifp); + /* Uninstall connected routes. */ + if_uninstall_connected(ifp); - /* Delete any IPv4 neighbors created to implement RFC 5549 */ - if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp); + /* Delete any IPv4 neighbors created to implement RFC 5549 */ + if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp); - /* Delete all neighbor addresses learnt through IPv6 RA */ - if_down_del_nbr_connected (ifp); + /* Delete all neighbor addresses learnt through IPv6 RA */ + if_down_del_nbr_connected(ifp); - /* Send out notification on interface VRF change. */ - /* This is to issue an UPDATE or a DELETE, as appropriate. */ - zebra_interface_vrf_update_del (ifp, vrf_id); + /* Send out notification on interface VRF change. */ + /* This is to issue an UPDATE or a DELETE, as appropriate. */ + zebra_interface_vrf_update_del(ifp, vrf_id); - /* update VRF */ - if_update_to_new_vrf (ifp, vrf_id); + /* update VRF */ + if_update_to_new_vrf(ifp, vrf_id); - /* Send out notification on interface VRF change. */ - /* This is to issue an ADD, if needed. */ - zebra_interface_vrf_update_add (ifp, old_vrf_id); + /* Send out notification on interface VRF change. */ + /* This is to issue an ADD, if needed. */ + zebra_interface_vrf_update_add(ifp, old_vrf_id); - /* Install connected routes (in new VRF). */ - if_install_connected (ifp); + /* Install connected routes (in new VRF). */ + if_install_connected(ifp); - /* Due to connected route change, schedule RIB processing for both old - * and new VRF. - */ - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IF %s VRF change, scheduling RIB processing", - ifp->vrf_id, ifp->name); - rib_update (old_vrf_id, RIB_UPDATE_IF_CHANGE); - rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); + /* Due to connected route change, schedule RIB processing for both old + * and new VRF. + */ + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug("%u: IF %s VRF change, scheduling RIB processing", + ifp->vrf_id, ifp->name); + rib_update(old_vrf_id, RIB_UPDATE_IF_CHANGE); + rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE); - zebra_vrf_static_route_interface_fixup (ifp); + zebra_vrf_static_route_interface_fixup(ifp); } -static void -ipv6_ll_address_to_mac (struct in6_addr *address, u_char *mac) +static void ipv6_ll_address_to_mac(struct in6_addr *address, u_char *mac) { - mac[0] = address->s6_addr[8] ^ 0x02; - mac[1] = address->s6_addr[9]; - mac[2] = address->s6_addr[10]; - mac[3] = address->s6_addr[13]; - mac[4] = address->s6_addr[14]; - mac[5] = address->s6_addr[15]; + mac[0] = address->s6_addr[8] ^ 0x02; + mac[1] = address->s6_addr[9]; + mac[2] = address->s6_addr[10]; + mac[3] = address->s6_addr[13]; + mac[4] = address->s6_addr[14]; + mac[5] = address->s6_addr[15]; } -void -if_nbr_ipv6ll_to_ipv4ll_neigh_update (struct interface *ifp, - struct in6_addr *address, - int add) +void if_nbr_ipv6ll_to_ipv4ll_neigh_update(struct interface *ifp, + struct in6_addr *address, int add) { - struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id); - char buf[16] = "169.254.0.1"; - struct in_addr ipv4_ll; - char mac[6]; + struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id); + char buf[16] = "169.254.0.1"; + struct in_addr ipv4_ll; + char mac[6]; - inet_pton (AF_INET, buf, &ipv4_ll); + inet_pton(AF_INET, buf, &ipv4_ll); - ipv6_ll_address_to_mac(address, (u_char *)mac); - kernel_neigh_update (add, ifp->ifindex, ipv4_ll.s_addr, mac, 6); - zvrf->neigh_updates++; + ipv6_ll_address_to_mac(address, (u_char *)mac); + kernel_neigh_update(add, ifp->ifindex, ipv4_ll.s_addr, mac, 6); + zvrf->neigh_updates++; } -static void -if_nbr_ipv6ll_to_ipv4ll_neigh_add_all (struct interface *ifp) +static void if_nbr_ipv6ll_to_ipv4ll_neigh_add_all(struct interface *ifp) { - if (listhead(ifp->nbr_connected)) - { - struct nbr_connected *nbr_connected; - struct listnode *node; + if (listhead(ifp->nbr_connected)) { + struct nbr_connected *nbr_connected; + struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (ifp->nbr_connected, node, nbr_connected)) - if_nbr_ipv6ll_to_ipv4ll_neigh_update (ifp, - &nbr_connected->address->u.prefix6, - 1); - } + for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node, + nbr_connected)) + if_nbr_ipv6ll_to_ipv4ll_neigh_update( + ifp, &nbr_connected->address->u.prefix6, 1); + } } -void -if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (struct interface *ifp) +void if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(struct interface *ifp) { - if (listhead(ifp->nbr_connected)) - { - struct nbr_connected *nbr_connected; - struct listnode *node; + if (listhead(ifp->nbr_connected)) { + struct nbr_connected *nbr_connected; + struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (ifp->nbr_connected, node, nbr_connected)) - if_nbr_ipv6ll_to_ipv4ll_neigh_update (ifp, - &nbr_connected->address->u.prefix6, - 0); - } + for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node, + nbr_connected)) + if_nbr_ipv6ll_to_ipv4ll_neigh_update( + ifp, &nbr_connected->address->u.prefix6, 0); + } } -static void -if_down_del_nbr_connected (struct interface *ifp) +static void if_down_del_nbr_connected(struct interface *ifp) { - struct nbr_connected *nbr_connected; - struct listnode *node, *nnode; + struct nbr_connected *nbr_connected; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (ifp->nbr_connected, node, nnode, nbr_connected)) - { - listnode_delete (ifp->nbr_connected, nbr_connected); - nbr_connected_free (nbr_connected); - } + for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, + nbr_connected)) { + listnode_delete(ifp->nbr_connected, nbr_connected); + nbr_connected_free(nbr_connected); + } } /* Interface is up. */ -void -if_up (struct interface *ifp) -{ - struct zebra_if *zif; - struct interface *link_if; - - zif = ifp->info; - zif->up_count++; - quagga_timestamp (2, zif->up_last, sizeof (zif->up_last)); - - /* Notify the protocol daemons. */ - if (ifp->ptm_enable && (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN)) { - zlog_warn("%s: interface %s hasn't passed ptm check\n", __func__, - ifp->name); - return; - } - zebra_interface_up_update (ifp); - - if_nbr_ipv6ll_to_ipv4ll_neigh_add_all (ifp); - -#if defined (HAVE_RTADV) - /* Enable fast tx of RA if enabled && RA interval is not in msecs */ - if (zif->rtadv.AdvSendAdvertisements && - (zif->rtadv.MaxRtrAdvInterval >= 1000)) - { - zif->rtadv.inFastRexmit = 1; - zif->rtadv.NumFastReXmitsRemain = RTADV_NUM_FAST_REXMITS; - } +void if_up(struct interface *ifp) +{ + struct zebra_if *zif; + struct interface *link_if; + + zif = ifp->info; + zif->up_count++; + quagga_timestamp(2, zif->up_last, sizeof(zif->up_last)); + + /* Notify the protocol daemons. */ + if (ifp->ptm_enable && (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN)) { + zlog_warn("%s: interface %s hasn't passed ptm check\n", + __func__, ifp->name); + return; + } + zebra_interface_up_update(ifp); + + if_nbr_ipv6ll_to_ipv4ll_neigh_add_all(ifp); + +#if defined(HAVE_RTADV) + /* Enable fast tx of RA if enabled && RA interval is not in msecs */ + if (zif->rtadv.AdvSendAdvertisements + && (zif->rtadv.MaxRtrAdvInterval >= 1000)) { + zif->rtadv.inFastRexmit = 1; + zif->rtadv.NumFastReXmitsRemain = RTADV_NUM_FAST_REXMITS; + } #endif - /* Install connected routes to the kernel. */ - if_install_connected (ifp); - - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IF %s up, scheduling RIB processing", - ifp->vrf_id, ifp->name); - rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); - - zebra_vrf_static_route_interface_fixup (ifp); - - /* Handle interface up for specific types for EVPN. Non-VxLAN interfaces - * are checked to see if (remote) neighbor entries need to be installed - * on them for ARP suppression. - */ - if (IS_ZEBRA_IF_VXLAN (ifp)) - zebra_vxlan_if_up (ifp); - else if (IS_ZEBRA_IF_BRIDGE (ifp)) - { - link_if = ifp; - zebra_vxlan_svi_up (ifp, link_if); - } - else if (IS_ZEBRA_IF_VLAN (ifp)) - { - link_if = zif->link; - if (link_if) - zebra_vxlan_svi_up (ifp, link_if); - } + /* Install connected routes to the kernel. */ + if_install_connected(ifp); + + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug("%u: IF %s up, scheduling RIB processing", + ifp->vrf_id, ifp->name); + rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE); + + zebra_vrf_static_route_interface_fixup(ifp); + + /* Handle interface up for specific types for EVPN. Non-VxLAN interfaces + * are checked to see if (remote) neighbor entries need to be installed + * on them for ARP suppression. + */ + if (IS_ZEBRA_IF_VXLAN(ifp)) + zebra_vxlan_if_up(ifp); + else if (IS_ZEBRA_IF_BRIDGE(ifp)) { + link_if = ifp; + zebra_vxlan_svi_up(ifp, link_if); + } else if (IS_ZEBRA_IF_VLAN(ifp)) { + link_if = zif->link; + if (link_if) + zebra_vxlan_svi_up(ifp, link_if); + } } /* Interface goes down. We have to manage different behavior of based OS. */ -void -if_down (struct interface *ifp) -{ - struct zebra_if *zif; - struct interface *link_if; - - zif = ifp->info; - zif->down_count++; - quagga_timestamp (2, zif->down_last, sizeof (zif->down_last)); - - /* Handle interface down for specific types for EVPN. Non-VxLAN interfaces - * are checked to see if (remote) neighbor entries need to be purged - * for ARP suppression. - */ - if (IS_ZEBRA_IF_VXLAN (ifp)) - zebra_vxlan_if_down (ifp); - else if (IS_ZEBRA_IF_BRIDGE (ifp)) - { - link_if = ifp; - zebra_vxlan_svi_down (ifp, link_if); - } - else if (IS_ZEBRA_IF_VLAN (ifp)) - { - link_if = zif->link; - if (link_if) - zebra_vxlan_svi_down (ifp, link_if); - } +void if_down(struct interface *ifp) +{ + struct zebra_if *zif; + struct interface *link_if; + + zif = ifp->info; + zif->down_count++; + quagga_timestamp(2, zif->down_last, sizeof(zif->down_last)); + + /* Handle interface down for specific types for EVPN. Non-VxLAN + * interfaces + * are checked to see if (remote) neighbor entries need to be purged + * for ARP suppression. + */ + if (IS_ZEBRA_IF_VXLAN(ifp)) + zebra_vxlan_if_down(ifp); + else if (IS_ZEBRA_IF_BRIDGE(ifp)) { + link_if = ifp; + zebra_vxlan_svi_down(ifp, link_if); + } else if (IS_ZEBRA_IF_VLAN(ifp)) { + link_if = zif->link; + if (link_if) + zebra_vxlan_svi_down(ifp, link_if); + } - /* Notify to the protocol daemons. */ - zebra_interface_down_update (ifp); + /* Notify to the protocol daemons. */ + zebra_interface_down_update(ifp); - /* Uninstall connected routes from the kernel. */ - if_uninstall_connected (ifp); + /* Uninstall connected routes from the kernel. */ + if_uninstall_connected(ifp); - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IF %s down, scheduling RIB processing", - ifp->vrf_id, ifp->name); - rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug("%u: IF %s down, scheduling RIB processing", + ifp->vrf_id, ifp->name); + rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE); - if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp); + if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp); - /* Delete all neighbor addresses learnt through IPv6 RA */ - if_down_del_nbr_connected (ifp); + /* Delete all neighbor addresses learnt through IPv6 RA */ + if_down_del_nbr_connected(ifp); } -void -if_refresh (struct interface *ifp) +void if_refresh(struct interface *ifp) { - if_get_flags (ifp); + if_get_flags(ifp); } -void -zebra_if_update_link (struct interface *ifp, ifindex_t link_ifindex) +void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex) { - struct zebra_if *zif; + struct zebra_if *zif; - zif = (struct zebra_if *)ifp->info; - zif->link_ifindex = link_ifindex; - zif->link = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT), - link_ifindex); + zif = (struct zebra_if *)ifp->info; + zif->link_ifindex = link_ifindex; + zif->link = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), + link_ifindex); } /* Output prefix string to vty. */ -static int -prefix_vty_out (struct vty *vty, struct prefix *p) +static int prefix_vty_out(struct vty *vty, struct prefix *p) { - char str[INET6_ADDRSTRLEN]; + char str[INET6_ADDRSTRLEN]; - inet_ntop (p->family, &p->u.prefix, str, sizeof (str)); - vty_out (vty, "%s", str); - return strlen (str); + inet_ntop(p->family, &p->u.prefix, str, sizeof(str)); + vty_out(vty, "%s", str); + return strlen(str); } /* Dump if address information to vty. */ -static void -connected_dump_vty (struct vty *vty, struct connected *connected) +static void connected_dump_vty(struct vty *vty, struct connected *connected) { - struct prefix *p; + struct prefix *p; - /* Print interface address. */ - p = connected->address; - vty_out (vty, " %s ", prefix_family_str (p)); - prefix_vty_out (vty, p); - vty_out (vty, "/%d", p->prefixlen); + /* Print interface address. */ + p = connected->address; + vty_out(vty, " %s ", prefix_family_str(p)); + prefix_vty_out(vty, p); + vty_out(vty, "/%d", p->prefixlen); - /* If there is destination address, print it. */ - if (connected->destination) - { - vty_out (vty, (CONNECTED_PEER(connected) ? " peer " : " broadcast ")); - prefix_vty_out (vty, connected->destination); - } + /* If there is destination address, print it. */ + if (connected->destination) { + vty_out(vty, + (CONNECTED_PEER(connected) ? " peer " : " broadcast ")); + prefix_vty_out(vty, connected->destination); + } - if (CHECK_FLAG (connected->flags, ZEBRA_IFA_SECONDARY)) - vty_out (vty, " secondary"); + if (CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY)) + vty_out(vty, " secondary"); - if (CHECK_FLAG (connected->flags, ZEBRA_IFA_UNNUMBERED)) - vty_out (vty, " unnumbered"); + if (CHECK_FLAG(connected->flags, ZEBRA_IFA_UNNUMBERED)) + vty_out(vty, " unnumbered"); - if (connected->label) - vty_out (vty, " %s", connected->label); + if (connected->label) + vty_out(vty, " %s", connected->label); - vty_out (vty, "\n"); + vty_out(vty, "\n"); } /* Dump interface neighbor address information to vty. */ -static void -nbr_connected_dump_vty (struct vty *vty, struct nbr_connected *connected) +static void nbr_connected_dump_vty(struct vty *vty, + struct nbr_connected *connected) { - struct prefix *p; + struct prefix *p; - /* Print interface address. */ - p = connected->address; - vty_out (vty, " %s ", prefix_family_str (p)); - prefix_vty_out (vty, p); - vty_out (vty, "/%d", p->prefixlen); + /* Print interface address. */ + p = connected->address; + vty_out(vty, " %s ", prefix_family_str(p)); + prefix_vty_out(vty, p); + vty_out(vty, "/%d", p->prefixlen); - vty_out (vty, "\n"); + vty_out(vty, "\n"); } -#if defined (HAVE_RTADV) +#if defined(HAVE_RTADV) /* Dump interface ND information to vty. */ -static void -nd_dump_vty (struct vty *vty, struct interface *ifp) -{ - struct zebra_if *zif; - struct rtadvconf *rtadv; - int interval; - - zif = (struct zebra_if *) ifp->info; - rtadv = &zif->rtadv; - - if (rtadv->AdvSendAdvertisements) - { - vty_out (vty, " ND advertised reachable time is %d milliseconds\n", - rtadv->AdvReachableTime); - vty_out (vty, " ND advertised retransmit interval is %d milliseconds\n", - rtadv->AdvRetransTimer); - vty_out (vty, " ND router advertisements sent: %d rcvd: %d\n", - zif->ra_sent, zif->ra_rcvd); - interval = rtadv->MaxRtrAdvInterval; - if (interval % 1000) - vty_out (vty, " ND router advertisements are sent every " - "%d milliseconds\n",interval); - else - vty_out (vty, " ND router advertisements are sent every " - "%d seconds\n",interval / 1000); - if (rtadv->AdvDefaultLifetime != -1) - vty_out (vty, " ND router advertisements live for %d seconds\n", - rtadv->AdvDefaultLifetime); - else - vty_out (vty, - " ND router advertisements lifetime tracks ra-interval\n"); - vty_out (vty, " ND router advertisement default router preference is " - "%s\n",rtadv_pref_strs[rtadv->DefaultPreference]); - if (rtadv->AdvManagedFlag) - vty_out (vty," Hosts use DHCP to obtain routable addresses.\n"); - else - vty_out (vty," Hosts use stateless autoconfig for addresses.\n"); - if (rtadv->AdvHomeAgentFlag) - { - vty_out (vty, - " ND router advertisements with Home Agent flag bit set.\n"); - if (rtadv->HomeAgentLifetime != -1) - vty_out (vty, " Home Agent lifetime is %u seconds\n", - rtadv->HomeAgentLifetime); - else - vty_out (vty," Home Agent lifetime tracks ra-lifetime\n"); - vty_out (vty, " Home Agent preference is %u\n", - rtadv->HomeAgentPreference); - } - if (rtadv->AdvIntervalOption) - vty_out (vty, - " ND router advertisements with Adv. Interval option.\n"); - } +static void nd_dump_vty(struct vty *vty, struct interface *ifp) +{ + struct zebra_if *zif; + struct rtadvconf *rtadv; + int interval; + + zif = (struct zebra_if *)ifp->info; + rtadv = &zif->rtadv; + + if (rtadv->AdvSendAdvertisements) { + vty_out(vty, + " ND advertised reachable time is %d milliseconds\n", + rtadv->AdvReachableTime); + vty_out(vty, + " ND advertised retransmit interval is %d milliseconds\n", + rtadv->AdvRetransTimer); + vty_out(vty, " ND router advertisements sent: %d rcvd: %d\n", + zif->ra_sent, zif->ra_rcvd); + interval = rtadv->MaxRtrAdvInterval; + if (interval % 1000) + vty_out(vty, + " ND router advertisements are sent every " + "%d milliseconds\n", + interval); + else + vty_out(vty, + " ND router advertisements are sent every " + "%d seconds\n", + interval / 1000); + if (rtadv->AdvDefaultLifetime != -1) + vty_out(vty, + " ND router advertisements live for %d seconds\n", + rtadv->AdvDefaultLifetime); + else + vty_out(vty, + " ND router advertisements lifetime tracks ra-interval\n"); + vty_out(vty, + " ND router advertisement default router preference is " + "%s\n", + rtadv_pref_strs[rtadv->DefaultPreference]); + if (rtadv->AdvManagedFlag) + vty_out(vty, + " Hosts use DHCP to obtain routable addresses.\n"); + else + vty_out(vty, + " Hosts use stateless autoconfig for addresses.\n"); + if (rtadv->AdvHomeAgentFlag) { + vty_out(vty, + " ND router advertisements with Home Agent flag bit set.\n"); + if (rtadv->HomeAgentLifetime != -1) + vty_out(vty, + " Home Agent lifetime is %u seconds\n", + rtadv->HomeAgentLifetime); + else + vty_out(vty, + " Home Agent lifetime tracks ra-lifetime\n"); + vty_out(vty, " Home Agent preference is %u\n", + rtadv->HomeAgentPreference); + } + if (rtadv->AdvIntervalOption) + vty_out(vty, + " ND router advertisements with Adv. Interval option.\n"); + } } #endif /* HAVE_RTADV */ -static const char * -zebra_ziftype_2str (zebra_iftype_t zif_type) +static const char *zebra_ziftype_2str(zebra_iftype_t zif_type) { - switch (zif_type) - { - case ZEBRA_IF_OTHER: - return "Other"; - break; + switch (zif_type) { + case ZEBRA_IF_OTHER: + return "Other"; + break; - case ZEBRA_IF_BRIDGE: - return "Bridge"; - break; + case ZEBRA_IF_BRIDGE: + return "Bridge"; + break; - case ZEBRA_IF_VLAN: - return "Vlan"; - break; + case ZEBRA_IF_VLAN: + return "Vlan"; + break; - case ZEBRA_IF_VXLAN: - return "Vxlan"; - break; + case ZEBRA_IF_VXLAN: + return "Vxlan"; + break; - case ZEBRA_IF_VRF: - return "VRF"; - break; + case ZEBRA_IF_VRF: + return "VRF"; + break; - default: - return "Unknown"; - break; - } + default: + return "Unknown"; + break; + } } /* Interface's information print out to vty interface. */ -static void -if_dump_vty (struct vty *vty, struct interface *ifp) -{ - struct connected *connected; - struct nbr_connected *nbr_connected; - struct listnode *node; - struct route_node *rn; - struct zebra_if *zebra_if; - struct vrf *vrf; - - zebra_if = ifp->info; - - vty_out (vty, "Interface %s is ", ifp->name); - if (if_is_up(ifp)) { - vty_out (vty, "up, line protocol "); - - if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) { - if (if_is_running(ifp)) - vty_out (vty, "is up\n"); - else - vty_out (vty, "is down\n"); - } else { - vty_out (vty, "detection is disabled\n"); - } - } else { - vty_out (vty, "down\n"); - } - - vty_out (vty, " Link ups: %5u last: %s\n", zebra_if->up_count, - zebra_if->up_last[0] ? zebra_if->up_last : "(never)"); - vty_out (vty, " Link downs: %5u last: %s\n", zebra_if->down_count, - zebra_if->down_last[0] ? zebra_if->down_last : "(never)"); - - zebra_ptm_show_status(vty, ifp); - - vrf = vrf_lookup_by_id (ifp->vrf_id); - vty_out (vty, " vrf: %s\n", vrf->name); - - if (ifp->desc) - vty_out (vty, " Description: %s\n",ifp->desc); - if (ifp->ifindex == IFINDEX_INTERNAL) - { - vty_out (vty, " pseudo interface\n"); - return; - } - else if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) - { - vty_out (vty, " index %d inactive interface\n", - ifp->ifindex); - return; - } - - vty_out (vty, " index %d metric %d mtu %d speed %u ", - ifp->ifindex, ifp->metric, ifp->mtu, ifp->speed); - if (ifp->mtu6 != ifp->mtu) - vty_out (vty, "mtu6 %d ", ifp->mtu6); - vty_out (vty, "\n flags: %s\n", - if_flag_dump(ifp->flags)); - - /* Hardware address. */ - vty_out (vty, " Type: %s\n", if_link_type_str(ifp->ll_type)); - if (ifp->hw_addr_len != 0) - { - int i; - - vty_out (vty, " HWaddr: "); - for (i = 0; i < ifp->hw_addr_len; i++) - vty_out (vty, "%s%02x", i == 0 ? "" : ":", ifp->hw_addr[i]); - vty_out (vty, "\n"); - } - - /* Bandwidth in Mbps */ - if (ifp->bandwidth != 0) - { - vty_out(vty, " bandwidth %u Mbps", ifp->bandwidth); - vty_out (vty, "\n"); - } - - for (rn = route_top (zebra_if->ipv4_subnets); rn; rn = route_next (rn)) - { - if (! rn->info) - continue; - - for (ALL_LIST_ELEMENTS_RO ((struct list *)rn->info, node, connected)) - connected_dump_vty (vty, connected); - } - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) - { - if (CHECK_FLAG (connected->conf, ZEBRA_IFC_REAL) && - (connected->address->family == AF_INET6)) - connected_dump_vty (vty, connected); - } - - vty_out(vty, " Interface Type %s\n", - zebra_ziftype_2str (zebra_if->zif_type)); - if (IS_ZEBRA_IF_BRIDGE (ifp)) - { - struct zebra_l2info_bridge *bridge_info; - - bridge_info = &zebra_if->l2info.br; - vty_out(vty, " Bridge VLAN-aware: %s\n", - bridge_info->vlan_aware ? "yes" : "no"); - } - else if (IS_ZEBRA_IF_VLAN(ifp)) - { - struct zebra_l2info_vlan *vlan_info; - - vlan_info = &zebra_if->l2info.vl; - vty_out(vty, " VLAN Id %u\n", - vlan_info->vid); - } - else if (IS_ZEBRA_IF_VXLAN (ifp)) - { - struct zebra_l2info_vxlan *vxlan_info; - - vxlan_info = &zebra_if->l2info.vxl; - vty_out(vty, " VxLAN Id %u", vxlan_info->vni); - if (vxlan_info->vtep_ip.s_addr != INADDR_ANY) - vty_out(vty, " VTEP IP: %s", inet_ntoa (vxlan_info->vtep_ip)); - if (vxlan_info->access_vlan) - vty_out(vty, " Access VLAN Id %u", vxlan_info->access_vlan); - vty_out(vty, "\n"); - } - - if (IS_ZEBRA_IF_BRIDGE_SLAVE (ifp)) - { - struct zebra_l2info_brslave *br_slave; - - br_slave = &zebra_if->brslave_info; - if (br_slave->bridge_ifindex != IFINDEX_INTERNAL) - vty_out(vty, " Master (bridge) ifindex %u\n", - br_slave->bridge_ifindex); - } - - if (zebra_if->link_ifindex != IFINDEX_INTERNAL) - vty_out(vty, " Link ifindex %u\n", - zebra_if->link_ifindex); - - if (HAS_LINK_PARAMS(ifp)) - { - int i; - struct if_link_params *iflp = ifp->link_params; - vty_out (vty, " Traffic Engineering Link Parameters:\n"); - if (IS_PARAM_SET(iflp, LP_TE_METRIC)) - vty_out (vty, " TE metric %u\n",iflp->te_metric); - if (IS_PARAM_SET(iflp, LP_MAX_BW)) - vty_out (vty, " Maximum Bandwidth %g (Byte/s)\n", iflp->max_bw); - if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW)) - vty_out (vty, " Maximum Reservable Bandwidth %g (Byte/s)\n", - iflp->max_rsv_bw); - if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) { - vty_out (vty, " Unreserved Bandwidth per Class Type in Byte/s:\n"); - for (i = 0; i < MAX_CLASS_TYPE; i+=2) - vty_out (vty, " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n", - i, iflp->unrsv_bw[i], i+1, iflp->unrsv_bw[i + 1]); - } - - if (IS_PARAM_SET(iflp, LP_ADM_GRP)) - vty_out (vty, " Administrative Group:%u\n", iflp->admin_grp); - if (IS_PARAM_SET(iflp, LP_DELAY)) - { - vty_out(vty, " Link Delay Average: %u (micro-sec.)", iflp->av_delay); - if (IS_PARAM_SET(iflp, LP_MM_DELAY)) - { - vty_out(vty, " Min: %u (micro-sec.)", iflp->min_delay); - vty_out(vty, " Max: %u (micro-sec.)", iflp->max_delay); - } - vty_out (vty, "\n"); - } - if (IS_PARAM_SET(iflp, LP_DELAY_VAR)) - vty_out (vty, " Link Delay Variation %u (micro-sec.)\n", - iflp->delay_var); - if (IS_PARAM_SET(iflp, LP_PKT_LOSS)) - vty_out (vty, " Link Packet Loss %g (in %%)\n", iflp->pkt_loss); - if (IS_PARAM_SET(iflp, LP_AVA_BW)) - vty_out (vty, " Available Bandwidth %g (Byte/s)\n", iflp->ava_bw); - if (IS_PARAM_SET(iflp, LP_RES_BW)) - vty_out (vty, " Residual Bandwidth %g (Byte/s)\n", iflp->res_bw); - if (IS_PARAM_SET(iflp, LP_USE_BW)) - vty_out (vty, " Utilized Bandwidth %g (Byte/s)\n", iflp->use_bw); - if (IS_PARAM_SET(iflp, LP_RMT_AS)) - vty_out (vty, " Neighbor ASBR IP: %s AS: %u \n", inet_ntoa(iflp->rmt_ip), - iflp->rmt_as); - } - - #ifdef RTADV - nd_dump_vty (vty, ifp); - #endif /* RTADV */ -#if defined (HAVE_RTADV) - nd_dump_vty (vty, ifp); +static void if_dump_vty(struct vty *vty, struct interface *ifp) +{ + struct connected *connected; + struct nbr_connected *nbr_connected; + struct listnode *node; + struct route_node *rn; + struct zebra_if *zebra_if; + struct vrf *vrf; + + zebra_if = ifp->info; + + vty_out(vty, "Interface %s is ", ifp->name); + if (if_is_up(ifp)) { + vty_out(vty, "up, line protocol "); + + if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) { + if (if_is_running(ifp)) + vty_out(vty, "is up\n"); + else + vty_out(vty, "is down\n"); + } else { + vty_out(vty, "detection is disabled\n"); + } + } else { + vty_out(vty, "down\n"); + } + + vty_out(vty, " Link ups: %5u last: %s\n", zebra_if->up_count, + zebra_if->up_last[0] ? zebra_if->up_last : "(never)"); + vty_out(vty, " Link downs: %5u last: %s\n", zebra_if->down_count, + zebra_if->down_last[0] ? zebra_if->down_last : "(never)"); + + zebra_ptm_show_status(vty, ifp); + + vrf = vrf_lookup_by_id(ifp->vrf_id); + vty_out(vty, " vrf: %s\n", vrf->name); + + if (ifp->desc) + vty_out(vty, " Description: %s\n", ifp->desc); + if (ifp->ifindex == IFINDEX_INTERNAL) { + vty_out(vty, " pseudo interface\n"); + return; + } else if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + vty_out(vty, " index %d inactive interface\n", ifp->ifindex); + return; + } + + vty_out(vty, " index %d metric %d mtu %d speed %u ", ifp->ifindex, + ifp->metric, ifp->mtu, ifp->speed); + if (ifp->mtu6 != ifp->mtu) + vty_out(vty, "mtu6 %d ", ifp->mtu6); + vty_out(vty, "\n flags: %s\n", if_flag_dump(ifp->flags)); + + /* Hardware address. */ + vty_out(vty, " Type: %s\n", if_link_type_str(ifp->ll_type)); + if (ifp->hw_addr_len != 0) { + int i; + + vty_out(vty, " HWaddr: "); + for (i = 0; i < ifp->hw_addr_len; i++) + vty_out(vty, "%s%02x", i == 0 ? "" : ":", + ifp->hw_addr[i]); + vty_out(vty, "\n"); + } + + /* Bandwidth in Mbps */ + if (ifp->bandwidth != 0) { + vty_out(vty, " bandwidth %u Mbps", ifp->bandwidth); + vty_out(vty, "\n"); + } + + for (rn = route_top(zebra_if->ipv4_subnets); rn; rn = route_next(rn)) { + if (!rn->info) + continue; + + for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node, + connected)) + connected_dump_vty(vty, connected); + } + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { + if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL) + && (connected->address->family == AF_INET6)) + connected_dump_vty(vty, connected); + } + + vty_out(vty, " Interface Type %s\n", + zebra_ziftype_2str(zebra_if->zif_type)); + if (IS_ZEBRA_IF_BRIDGE(ifp)) { + struct zebra_l2info_bridge *bridge_info; + + bridge_info = &zebra_if->l2info.br; + vty_out(vty, " Bridge VLAN-aware: %s\n", + bridge_info->vlan_aware ? "yes" : "no"); + } else if (IS_ZEBRA_IF_VLAN(ifp)) { + struct zebra_l2info_vlan *vlan_info; + + vlan_info = &zebra_if->l2info.vl; + vty_out(vty, " VLAN Id %u\n", vlan_info->vid); + } else if (IS_ZEBRA_IF_VXLAN(ifp)) { + struct zebra_l2info_vxlan *vxlan_info; + + vxlan_info = &zebra_if->l2info.vxl; + vty_out(vty, " VxLAN Id %u", vxlan_info->vni); + if (vxlan_info->vtep_ip.s_addr != INADDR_ANY) + vty_out(vty, " VTEP IP: %s", + inet_ntoa(vxlan_info->vtep_ip)); + if (vxlan_info->access_vlan) + vty_out(vty, " Access VLAN Id %u", + vxlan_info->access_vlan); + vty_out(vty, "\n"); + } + + if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) { + struct zebra_l2info_brslave *br_slave; + + br_slave = &zebra_if->brslave_info; + if (br_slave->bridge_ifindex != IFINDEX_INTERNAL) + vty_out(vty, " Master (bridge) ifindex %u\n", + br_slave->bridge_ifindex); + } + + if (zebra_if->link_ifindex != IFINDEX_INTERNAL) + vty_out(vty, " Link ifindex %u\n", zebra_if->link_ifindex); + + if (HAS_LINK_PARAMS(ifp)) { + int i; + struct if_link_params *iflp = ifp->link_params; + vty_out(vty, " Traffic Engineering Link Parameters:\n"); + if (IS_PARAM_SET(iflp, LP_TE_METRIC)) + vty_out(vty, " TE metric %u\n", iflp->te_metric); + if (IS_PARAM_SET(iflp, LP_MAX_BW)) + vty_out(vty, " Maximum Bandwidth %g (Byte/s)\n", + iflp->max_bw); + if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW)) + vty_out(vty, + " Maximum Reservable Bandwidth %g (Byte/s)\n", + iflp->max_rsv_bw); + if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) { + vty_out(vty, + " Unreserved Bandwidth per Class Type in Byte/s:\n"); + for (i = 0; i < MAX_CLASS_TYPE; i += 2) + vty_out(vty, + " [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n", + i, iflp->unrsv_bw[i], i + 1, + iflp->unrsv_bw[i + 1]); + } + + if (IS_PARAM_SET(iflp, LP_ADM_GRP)) + vty_out(vty, " Administrative Group:%u\n", + iflp->admin_grp); + if (IS_PARAM_SET(iflp, LP_DELAY)) { + vty_out(vty, " Link Delay Average: %u (micro-sec.)", + iflp->av_delay); + if (IS_PARAM_SET(iflp, LP_MM_DELAY)) { + vty_out(vty, " Min: %u (micro-sec.)", + iflp->min_delay); + vty_out(vty, " Max: %u (micro-sec.)", + iflp->max_delay); + } + vty_out(vty, "\n"); + } + if (IS_PARAM_SET(iflp, LP_DELAY_VAR)) + vty_out(vty, + " Link Delay Variation %u (micro-sec.)\n", + iflp->delay_var); + if (IS_PARAM_SET(iflp, LP_PKT_LOSS)) + vty_out(vty, " Link Packet Loss %g (in %%)\n", + iflp->pkt_loss); + if (IS_PARAM_SET(iflp, LP_AVA_BW)) + vty_out(vty, " Available Bandwidth %g (Byte/s)\n", + iflp->ava_bw); + if (IS_PARAM_SET(iflp, LP_RES_BW)) + vty_out(vty, " Residual Bandwidth %g (Byte/s)\n", + iflp->res_bw); + if (IS_PARAM_SET(iflp, LP_USE_BW)) + vty_out(vty, " Utilized Bandwidth %g (Byte/s)\n", + iflp->use_bw); + if (IS_PARAM_SET(iflp, LP_RMT_AS)) + vty_out(vty, " Neighbor ASBR IP: %s AS: %u \n", + inet_ntoa(iflp->rmt_ip), iflp->rmt_as); + } + +#ifdef RTADV + nd_dump_vty(vty, ifp); +#endif /* RTADV */ +#if defined(HAVE_RTADV) + nd_dump_vty(vty, ifp); #endif /* HAVE_RTADV */ - if (listhead(ifp->nbr_connected)) - vty_out (vty, " Neighbor address(s):\n"); - for (ALL_LIST_ELEMENTS_RO (ifp->nbr_connected, node, nbr_connected)) - nbr_connected_dump_vty (vty, nbr_connected); + if (listhead(ifp->nbr_connected)) + vty_out(vty, " Neighbor address(s):\n"); + for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node, nbr_connected)) + nbr_connected_dump_vty(vty, nbr_connected); #ifdef HAVE_PROC_NET_DEV - /* Statistics print out using proc file system. */ - vty_out (vty, " %lu input packets (%lu multicast), %lu bytes, " - "%lu dropped\n", - ifp->stats.rx_packets, ifp->stats.rx_multicast, - ifp->stats.rx_bytes, ifp->stats.rx_dropped); - - vty_out (vty, " %lu input errors, %lu length, %lu overrun," - " %lu CRC, %lu frame\n", - ifp->stats.rx_errors, ifp->stats.rx_length_errors, - ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors, - ifp->stats.rx_frame_errors); - - vty_out (vty, " %lu fifo, %lu missed\n", ifp->stats.rx_fifo_errors, - ifp->stats.rx_missed_errors); - - vty_out (vty, " %lu output packets, %lu bytes, %lu dropped\n", - ifp->stats.tx_packets, ifp->stats.tx_bytes, - ifp->stats.tx_dropped); - - vty_out (vty, " %lu output errors, %lu aborted, %lu carrier," - " %lu fifo, %lu heartbeat\n", - ifp->stats.tx_errors, ifp->stats.tx_aborted_errors, - ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors, - ifp->stats.tx_heartbeat_errors); - - vty_out (vty, " %lu window, %lu collisions\n", - ifp->stats.tx_window_errors, ifp->stats.collisions); + /* Statistics print out using proc file system. */ + vty_out(vty, + " %lu input packets (%lu multicast), %lu bytes, " + "%lu dropped\n", + ifp->stats.rx_packets, ifp->stats.rx_multicast, + ifp->stats.rx_bytes, ifp->stats.rx_dropped); + + vty_out(vty, + " %lu input errors, %lu length, %lu overrun," + " %lu CRC, %lu frame\n", + ifp->stats.rx_errors, ifp->stats.rx_length_errors, + ifp->stats.rx_over_errors, ifp->stats.rx_crc_errors, + ifp->stats.rx_frame_errors); + + vty_out(vty, " %lu fifo, %lu missed\n", ifp->stats.rx_fifo_errors, + ifp->stats.rx_missed_errors); + + vty_out(vty, " %lu output packets, %lu bytes, %lu dropped\n", + ifp->stats.tx_packets, ifp->stats.tx_bytes, + ifp->stats.tx_dropped); + + vty_out(vty, + " %lu output errors, %lu aborted, %lu carrier," + " %lu fifo, %lu heartbeat\n", + ifp->stats.tx_errors, ifp->stats.tx_aborted_errors, + ifp->stats.tx_carrier_errors, ifp->stats.tx_fifo_errors, + ifp->stats.tx_heartbeat_errors); + + vty_out(vty, " %lu window, %lu collisions\n", + ifp->stats.tx_window_errors, ifp->stats.collisions); #endif /* HAVE_PROC_NET_DEV */ #ifdef HAVE_NET_RT_IFLIST -#if defined (__bsdi__) || defined (__NetBSD__) - /* Statistics print out using sysctl (). */ - vty_out (vty, " input packets %llu, bytes %llu, dropped %llu," - " multicast packets %llu\n", - (unsigned long long)ifp->stats.ifi_ipackets, - (unsigned long long)ifp->stats.ifi_ibytes, - (unsigned long long)ifp->stats.ifi_iqdrops, - (unsigned long long)ifp->stats.ifi_imcasts); - - vty_out (vty, " input errors %llu\n", - (unsigned long long)ifp->stats.ifi_ierrors); - - vty_out (vty, " output packets %llu, bytes %llu," - " multicast packets %llu\n", - (unsigned long long)ifp->stats.ifi_opackets, - (unsigned long long)ifp->stats.ifi_obytes, - (unsigned long long)ifp->stats.ifi_omcasts); - - vty_out (vty, " output errors %llu\n", - (unsigned long long)ifp->stats.ifi_oerrors); - - vty_out (vty, " collisions %llu\n", - (unsigned long long)ifp->stats.ifi_collisions); +#if defined(__bsdi__) || defined(__NetBSD__) + /* Statistics print out using sysctl (). */ + vty_out(vty, + " input packets %llu, bytes %llu, dropped %llu," + " multicast packets %llu\n", + (unsigned long long)ifp->stats.ifi_ipackets, + (unsigned long long)ifp->stats.ifi_ibytes, + (unsigned long long)ifp->stats.ifi_iqdrops, + (unsigned long long)ifp->stats.ifi_imcasts); + + vty_out(vty, " input errors %llu\n", + (unsigned long long)ifp->stats.ifi_ierrors); + + vty_out(vty, + " output packets %llu, bytes %llu," + " multicast packets %llu\n", + (unsigned long long)ifp->stats.ifi_opackets, + (unsigned long long)ifp->stats.ifi_obytes, + (unsigned long long)ifp->stats.ifi_omcasts); + + vty_out(vty, " output errors %llu\n", + (unsigned long long)ifp->stats.ifi_oerrors); + + vty_out(vty, " collisions %llu\n", + (unsigned long long)ifp->stats.ifi_collisions); #else - /* Statistics print out using sysctl (). */ - vty_out (vty, " input packets %lu, bytes %lu, dropped %lu," - " multicast packets %lu\n", - ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes, - ifp->stats.ifi_iqdrops,ifp->stats.ifi_imcasts); + /* Statistics print out using sysctl (). */ + vty_out(vty, + " input packets %lu, bytes %lu, dropped %lu," + " multicast packets %lu\n", + ifp->stats.ifi_ipackets, ifp->stats.ifi_ibytes, + ifp->stats.ifi_iqdrops, ifp->stats.ifi_imcasts); - vty_out (vty, " input errors %lu\n", - ifp->stats.ifi_ierrors); + vty_out(vty, " input errors %lu\n", ifp->stats.ifi_ierrors); - vty_out (vty, " output packets %lu, bytes %lu, multicast packets %lu\n", - ifp->stats.ifi_opackets, ifp->stats.ifi_obytes, - ifp->stats.ifi_omcasts); + vty_out(vty, + " output packets %lu, bytes %lu, multicast packets %lu\n", + ifp->stats.ifi_opackets, ifp->stats.ifi_obytes, + ifp->stats.ifi_omcasts); - vty_out (vty, " output errors %lu\n", - ifp->stats.ifi_oerrors); + vty_out(vty, " output errors %lu\n", ifp->stats.ifi_oerrors); - vty_out (vty, " collisions %lu\n", - ifp->stats.ifi_collisions); + vty_out(vty, " collisions %lu\n", ifp->stats.ifi_collisions); #endif /* __bsdi__ || __NetBSD__ */ #endif /* HAVE_NET_RT_IFLIST */ } -static void -interface_update_stats (void) +static void interface_update_stats(void) { #ifdef HAVE_PROC_NET_DEV - /* If system has interface statistics via proc file system, update - statistics. */ - ifstat_update_proc (); + /* If system has interface statistics via proc file system, update + statistics. */ + ifstat_update_proc(); #endif /* HAVE_PROC_NET_DEV */ #ifdef HAVE_NET_RT_IFLIST - ifstat_update_sysctl (); + ifstat_update_sysctl(); #endif /* HAVE_NET_RT_IFLIST */ } -struct cmd_node interface_node = -{ - INTERFACE_NODE, - "%s(config-if)# ", - 1 -}; +struct cmd_node interface_node = {INTERFACE_NODE, "%s(config-if)# ", 1}; /* Show all interfaces to vty. */ DEFUN (show_interface, @@ -1417,20 +1378,20 @@ DEFUN (show_interface, "Interface status and configuration\n" VRF_CMD_HELP_STR) { - struct listnode *node; - struct interface *ifp; - vrf_id_t vrf_id = VRF_DEFAULT; + struct listnode *node; + struct interface *ifp; + vrf_id_t vrf_id = VRF_DEFAULT; - interface_update_stats (); + interface_update_stats(); - if (argc > 2) - VRF_GET_ID (vrf_id, argv[3]->arg); + if (argc > 2) + VRF_GET_ID(vrf_id, argv[3]->arg); - /* All interface print. */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) - if_dump_vty (vty, ifp); + /* All interface print. */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) + if_dump_vty(vty, ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1442,18 +1403,18 @@ DEFUN (show_interface_vrf_all, "Interface status and configuration\n" VRF_ALL_CMD_HELP_STR) { - struct vrf *vrf; - struct listnode *node; - struct interface *ifp; + struct vrf *vrf; + struct listnode *node; + struct interface *ifp; - interface_update_stats (); + interface_update_stats(); - /* All interface print. */ - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp)) - if_dump_vty (vty, ifp); + /* All interface print. */ + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + for (ALL_LIST_ELEMENTS_RO(vrf->iflist, node, ifp)) + if_dump_vty(vty, ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Show specified interface to vty. */ @@ -1466,25 +1427,25 @@ DEFUN (show_interface_name_vrf, "Interface name\n" VRF_CMD_HELP_STR) { - int idx_ifname = 2; - int idx_name = 4; - struct interface *ifp; - vrf_id_t vrf_id = VRF_DEFAULT; + int idx_ifname = 2; + int idx_name = 4; + struct interface *ifp; + vrf_id_t vrf_id = VRF_DEFAULT; - interface_update_stats (); + interface_update_stats(); - VRF_GET_ID (vrf_id, argv[idx_name]->arg); + VRF_GET_ID(vrf_id, argv[idx_name]->arg); - /* Specified interface print. */ - ifp = if_lookup_by_name (argv[idx_ifname]->arg, vrf_id); - if (ifp == NULL) - { - vty_out (vty, "%% Can't find interface %s\n",argv[idx_ifname]->arg); - return CMD_WARNING; - } - if_dump_vty (vty, ifp); + /* Specified interface print. */ + ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id); + if (ifp == NULL) { + vty_out(vty, "%% Can't find interface %s\n", + argv[idx_ifname]->arg); + return CMD_WARNING; + } + if_dump_vty(vty, ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Show specified interface to vty. */ @@ -1496,73 +1457,65 @@ DEFUN (show_interface_name_vrf_all, "Interface name\n" VRF_ALL_CMD_HELP_STR) { - int idx_ifname = 2; - struct vrf *vrf; - struct interface *ifp; - int found = 0; + int idx_ifname = 2; + struct vrf *vrf; + struct interface *ifp; + int found = 0; - interface_update_stats (); + interface_update_stats(); - /* All interface print. */ - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - /* Specified interface print. */ - ifp = if_lookup_by_name (argv[idx_ifname]->arg, vrf->vrf_id); - if (ifp) - { - if_dump_vty (vty, ifp); - found++; - } - } + /* All interface print. */ + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + /* Specified interface print. */ + ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf->vrf_id); + if (ifp) { + if_dump_vty(vty, ifp); + found++; + } + } - if (!found) - { - vty_out (vty, "%% Can't find interface %s\n", argv[idx_ifname]->arg); - return CMD_WARNING; - } + if (!found) { + vty_out(vty, "%% Can't find interface %s\n", + argv[idx_ifname]->arg); + return CMD_WARNING; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } -static void -if_show_description (struct vty *vty, vrf_id_t vrf_id) +static void if_show_description(struct vty *vty, vrf_id_t vrf_id) { - struct listnode *node; - struct interface *ifp; + struct listnode *node; + struct interface *ifp; - vty_out (vty, "Interface Status Protocol Description\n"); - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) - { - int len; + vty_out(vty, "Interface Status Protocol Description\n"); + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id), node, ifp)) { + int len; - len = vty_out (vty, "%s", ifp->name); - vty_out (vty, "%*s", (16 - len), " "); - - if (if_is_up(ifp)) - { - vty_out (vty, "up "); - if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) - { - if (if_is_running(ifp)) - vty_out (vty, "up "); - else - vty_out (vty, "down "); - } - else - { - vty_out (vty, "unknown "); - } - } - else - { - vty_out (vty, "down down "); - } + len = vty_out(vty, "%s", ifp->name); + vty_out(vty, "%*s", (16 - len), " "); + + if (if_is_up(ifp)) { + vty_out(vty, "up "); + if (CHECK_FLAG(ifp->status, + ZEBRA_INTERFACE_LINKDETECTION)) { + if (if_is_running(ifp)) + vty_out(vty, "up "); + else + vty_out(vty, "down "); + } else { + vty_out(vty, "unknown "); + } + } else { + vty_out(vty, "down down "); + } - if (ifp->desc) - vty_out (vty, "%s", ifp->desc); - vty_out (vty, "\n"); - } + if (ifp->desc) + vty_out(vty, "%s", ifp->desc); + vty_out(vty, "\n"); + } } DEFUN (show_interface_desc, @@ -1573,14 +1526,14 @@ DEFUN (show_interface_desc, "Interface description\n" VRF_CMD_HELP_STR) { - vrf_id_t vrf_id = VRF_DEFAULT; + vrf_id_t vrf_id = VRF_DEFAULT; - if (argc > 3) - VRF_GET_ID (vrf_id, argv[4]->arg); + if (argc > 3) + VRF_GET_ID(vrf_id, argv[4]->arg); - if_show_description (vty, vrf_id); + if_show_description(vty, vrf_id); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1592,16 +1545,15 @@ DEFUN (show_interface_desc_vrf_all, "Interface description\n" VRF_ALL_CMD_HELP_STR) { - struct vrf *vrf; + struct vrf *vrf; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if (!list_isempty (vrf->iflist)) - { - vty_out (vty, "\n\tVRF %u\n\n", vrf->vrf_id); - if_show_description (vty, vrf->vrf_id); - } + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + if (!list_isempty(vrf->iflist)) { + vty_out(vty, "\n\tVRF %u\n\n", vrf->vrf_id); + if_show_description(vty, vrf->vrf_id); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (multicast, @@ -1609,24 +1561,22 @@ DEFUN (multicast, "multicast", "Set multicast flag to interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - int ret; - struct zebra_if *if_data; + VTY_DECLVAR_CONTEXT(interface, ifp); + int ret; + struct zebra_if *if_data; - if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) - { - ret = if_set_flags (ifp, IFF_MULTICAST); - if (ret < 0) - { - vty_out (vty, "Can't set multicast flag\n"); - return CMD_WARNING_CONFIG_FAILED; + if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + ret = if_set_flags(ifp, IFF_MULTICAST); + if (ret < 0) { + vty_out(vty, "Can't set multicast flag\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if_refresh(ifp); } - if_refresh (ifp); - } - if_data = ifp->info; - if_data->multicast = IF_ZEBRA_MULTICAST_ON; + if_data = ifp->info; + if_data->multicast = IF_ZEBRA_MULTICAST_ON; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_multicast, @@ -1635,24 +1585,22 @@ DEFUN (no_multicast, NO_STR "Unset multicast flag to interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - int ret; - struct zebra_if *if_data; + VTY_DECLVAR_CONTEXT(interface, ifp); + int ret; + struct zebra_if *if_data; - if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) - { - ret = if_unset_flags (ifp, IFF_MULTICAST); - if (ret < 0) - { - vty_out (vty, "Can't unset multicast flag\n"); - return CMD_WARNING_CONFIG_FAILED; + if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + ret = if_unset_flags(ifp, IFF_MULTICAST); + if (ret < 0) { + vty_out(vty, "Can't unset multicast flag\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if_refresh(ifp); } - if_refresh (ifp); - } - if_data = ifp->info; - if_data->multicast = IF_ZEBRA_MULTICAST_OFF; + if_data = ifp->info; + if_data->multicast = IF_ZEBRA_MULTICAST_OFF; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (linkdetect, @@ -1660,19 +1608,20 @@ DEFUN (linkdetect, "link-detect", "Enable link detection on interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - int if_was_operative; - - if_was_operative = if_is_no_ptm_operative(ifp); - SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION); + VTY_DECLVAR_CONTEXT(interface, ifp); + int if_was_operative; - /* When linkdetection is enabled, if might come down */ - if (!if_is_no_ptm_operative(ifp) && if_was_operative) if_down(ifp); + if_was_operative = if_is_no_ptm_operative(ifp); + SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION); - /* FIXME: Will defer status change forwarding if interface - does not come down! */ + /* When linkdetection is enabled, if might come down */ + if (!if_is_no_ptm_operative(ifp) && if_was_operative) + if_down(ifp); - return CMD_SUCCESS; + /* FIXME: Will defer status change forwarding if interface + does not come down! */ + + return CMD_SUCCESS; } @@ -1682,18 +1631,19 @@ DEFUN (no_linkdetect, NO_STR "Disable link detection on interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - int if_was_operative; + VTY_DECLVAR_CONTEXT(interface, ifp); + int if_was_operative; + + if_was_operative = if_is_no_ptm_operative(ifp); + UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION); - if_was_operative = if_is_no_ptm_operative(ifp); - UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION); - - /* Interface may come up after disabling link detection */ - if (if_is_operative(ifp) && !if_was_operative) if_up(ifp); + /* Interface may come up after disabling link detection */ + if (if_is_operative(ifp) && !if_was_operative) + if_up(ifp); - /* FIXME: see linkdetect_cmd */ + /* FIXME: see linkdetect_cmd */ - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (shutdown_if, @@ -1701,24 +1651,22 @@ DEFUN (shutdown_if, "shutdown", "Shutdown the selected interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - int ret; - struct zebra_if *if_data; + VTY_DECLVAR_CONTEXT(interface, ifp); + int ret; + struct zebra_if *if_data; - if (ifp->ifindex != IFINDEX_INTERNAL) - { - ret = if_unset_flags (ifp, IFF_UP); - if (ret < 0) - { - vty_out (vty, "Can't shutdown interface\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if_refresh (ifp); - } - if_data = ifp->info; - if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON; + if (ifp->ifindex != IFINDEX_INTERNAL) { + ret = if_unset_flags(ifp, IFF_UP); + if (ret < 0) { + vty_out(vty, "Can't shutdown interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if_refresh(ifp); + } + if_data = ifp->info; + if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_shutdown_if, @@ -1727,30 +1675,29 @@ DEFUN (no_shutdown_if, NO_STR "Shutdown the selected interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - int ret; - struct zebra_if *if_data; + VTY_DECLVAR_CONTEXT(interface, ifp); + int ret; + struct zebra_if *if_data; - if (ifp->ifindex != IFINDEX_INTERNAL) - { - ret = if_set_flags (ifp, IFF_UP | IFF_RUNNING); - if (ret < 0) - { - vty_out (vty, "Can't up interface\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if_refresh (ifp); + if (ifp->ifindex != IFINDEX_INTERNAL) { + ret = if_set_flags(ifp, IFF_UP | IFF_RUNNING); + if (ret < 0) { + vty_out(vty, "Can't up interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if_refresh(ifp); - /* Some addresses (in particular, IPv6 addresses on Linux) get - * removed when the interface goes down. They need to be readded. - */ - if_addr_wakeup(ifp); - } + /* Some addresses (in particular, IPv6 addresses on Linux) get + * removed when the interface goes down. They need to be + * readded. + */ + if_addr_wakeup(ifp); + } - if_data = ifp->info; - if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF; + if_data = ifp->info; + if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (bandwidth_if, @@ -1759,26 +1706,25 @@ DEFUN (bandwidth_if, "Set bandwidth informational parameter\n" "Bandwidth in megabits\n") { - int idx_number = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); - unsigned int bandwidth; - - bandwidth = strtol(argv[idx_number]->arg, NULL, 10); + int idx_number = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); + unsigned int bandwidth; + + bandwidth = strtol(argv[idx_number]->arg, NULL, 10); + + /* bandwidth range is <1-100000> */ + if (bandwidth < 1 || bandwidth > 100000) { + vty_out(vty, "Bandwidth is invalid\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ifp->bandwidth = bandwidth; - /* bandwidth range is <1-100000> */ - if (bandwidth < 1 || bandwidth > 100000) - { - vty_out (vty, "Bandwidth is invalid\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ifp->bandwidth = bandwidth; + /* force protocols to recalculate routes due to cost change */ + if (if_is_operative(ifp)) + zebra_interface_up_update(ifp); - /* force protocols to recalculate routes due to cost change */ - if (if_is_operative (ifp)) - zebra_interface_up_update (ifp); - - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_bandwidth_if, @@ -1788,69 +1734,63 @@ DEFUN (no_bandwidth_if, "Set bandwidth informational parameter\n" "Bandwidth in megabits\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - ifp->bandwidth = 0; - - /* force protocols to recalculate routes due to cost change */ - if (if_is_operative (ifp)) - zebra_interface_up_update (ifp); + ifp->bandwidth = 0; - return CMD_SUCCESS; + /* force protocols to recalculate routes due to cost change */ + if (if_is_operative(ifp)) + zebra_interface_up_update(ifp); + + return CMD_SUCCESS; } -struct cmd_node link_params_node = -{ - LINK_PARAMS_NODE, - "%s(config-link-params)# ", - 1, +struct cmd_node link_params_node = { + LINK_PARAMS_NODE, "%s(config-link-params)# ", 1, }; -static void -link_param_cmd_set_uint32 (struct interface *ifp, uint32_t *field, - uint32_t type, uint32_t value) +static void link_param_cmd_set_uint32(struct interface *ifp, uint32_t *field, + uint32_t type, uint32_t value) { - /* Update field as needed */ - if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) - { - *field = value; - SET_PARAM(ifp->link_params, type); + /* Update field as needed */ + if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) { + *field = value; + SET_PARAM(ifp->link_params, type); - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative (ifp)) - zebra_interface_parameters_update (ifp); - } + /* force protocols to update LINK STATE due to parameters change + */ + if (if_is_operative(ifp)) + zebra_interface_parameters_update(ifp); + } } -static void -link_param_cmd_set_float (struct interface *ifp, float *field, - uint32_t type, float value) +static void link_param_cmd_set_float(struct interface *ifp, float *field, + uint32_t type, float value) { - /* Update field as needed */ - if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) - { - *field = value; - SET_PARAM(ifp->link_params, type); + /* Update field as needed */ + if (IS_PARAM_UNSET(ifp->link_params, type) || *field != value) { + *field = value; + SET_PARAM(ifp->link_params, type); - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative (ifp)) - zebra_interface_parameters_update (ifp); - } + /* force protocols to update LINK STATE due to parameters change + */ + if (if_is_operative(ifp)) + zebra_interface_parameters_update(ifp); + } } -static void -link_param_cmd_unset (struct interface *ifp, uint32_t type) +static void link_param_cmd_unset(struct interface *ifp, uint32_t type) { - if (ifp->link_params == NULL) - return; + if (ifp->link_params == NULL) + return; - /* Unset field */ - UNSET_PARAM(ifp->link_params, type); + /* Unset field */ + UNSET_PARAM(ifp->link_params, type); - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative (ifp)) - zebra_interface_parameters_update (ifp); + /* force protocols to update LINK STATE due to parameters change */ + if (if_is_operative(ifp)) + zebra_interface_parameters_update(ifp); } DEFUN_NOSH (link_params, @@ -1858,10 +1798,10 @@ DEFUN_NOSH (link_params, "link-params", LINK_PARAMS_STR) { - /* vty->qobj_index stays the same @ interface pointer */ - vty->node = LINK_PARAMS_NODE; + /* vty->qobj_index stays the same @ interface pointer */ + vty->node = LINK_PARAMS_NODE; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_NOSH (exit_link_params, @@ -1869,9 +1809,9 @@ DEFUN_NOSH (exit_link_params, "exit-link-params", "Exit from Link Params configuration mode\n") { - if (vty->node == LINK_PARAMS_NODE) - vty->node = INTERFACE_NODE; - return CMD_SUCCESS; + if (vty->node == LINK_PARAMS_NODE) + vty->node = INTERFACE_NODE; + return CMD_SUCCESS; } /* Specific Traffic Engineering parameters commands */ @@ -1880,27 +1820,30 @@ DEFUN (link_params_enable, "enable", "Activate link parameters on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - /* This command could be issue at startup, when activate MPLS TE */ - /* on a new interface or after a ON / OFF / ON toggle */ - /* In all case, TE parameters are reset to their default factory */ - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("Link-params: enable TE link parameters on interface %s", ifp->name); + /* This command could be issue at startup, when activate MPLS TE */ + /* on a new interface or after a ON / OFF / ON toggle */ + /* In all case, TE parameters are reset to their default factory */ + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "Link-params: enable TE link parameters on interface %s", + ifp->name); - if (!if_link_params_get (ifp)) - { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("Link-params: failed to init TE link parameters %s", ifp->name); + if (!if_link_params_get(ifp)) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "Link-params: failed to init TE link parameters %s", + ifp->name); - return CMD_WARNING_CONFIG_FAILED; - } + return CMD_WARNING_CONFIG_FAILED; + } - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative (ifp)) - zebra_interface_parameters_update (ifp); + /* force protocols to update LINK STATE due to parameters change */ + if (if_is_operative(ifp)) + zebra_interface_parameters_update(ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_link_params_enable, @@ -1909,17 +1852,18 @@ DEFUN (no_link_params_enable, NO_STR "Disable link parameters on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - zlog_debug ("MPLS-TE: disable TE link parameters on interface %s", ifp->name); + zlog_debug("MPLS-TE: disable TE link parameters on interface %s", + ifp->name); - if_link_params_free (ifp); + if_link_params_free(ifp); - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative (ifp)) - zebra_interface_parameters_update (ifp); + /* force protocols to update LINK STATE due to parameters change */ + if (if_is_operative(ifp)) + zebra_interface_parameters_update(ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* STANDARD TE metrics */ @@ -1929,17 +1873,17 @@ DEFUN (link_params_metric, "Link metric for MPLS-TE purpose\n" "Metric value in decimal\n") { - int idx_number = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - u_int32_t metric; + int idx_number = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + u_int32_t metric; - metric = strtoul(argv[idx_number]->arg, NULL, 10); + metric = strtoul(argv[idx_number]->arg, NULL, 10); - /* Update TE metric if needed */ - link_param_cmd_set_uint32 (ifp, &iflp->te_metric, LP_TE_METRIC, metric); + /* Update TE metric if needed */ + link_param_cmd_set_uint32(ifp, &iflp->te_metric, LP_TE_METRIC, metric); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_link_params_metric, @@ -1948,12 +1892,12 @@ DEFUN (no_link_params_metric, NO_STR "Disable Link Metric on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - /* Unset TE Metric */ - link_param_cmd_unset(ifp, LP_TE_METRIC); + /* Unset TE Metric */ + link_param_cmd_unset(ifp, LP_TE_METRIC); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (link_params_maxbw, @@ -1962,41 +1906,35 @@ DEFUN (link_params_maxbw, "Maximum bandwidth that can be used\n" "Bytes/second (IEEE floating point format)\n") { - int idx_bandwidth = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - - float bw; - - if (sscanf (argv[idx_bandwidth]->arg, "%g", &bw) != 1) - { - vty_out (vty, "link_params_maxbw: fscanf: %s\n",safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check that Maximum bandwidth is not lower than other bandwidth parameters */ - if ((bw <= iflp->max_rsv_bw) - || (bw <= iflp->unrsv_bw[0]) - || (bw <= iflp->unrsv_bw[1]) - || (bw <= iflp->unrsv_bw[2]) - || (bw <= iflp->unrsv_bw[3]) - || (bw <= iflp->unrsv_bw[4]) - || (bw <= iflp->unrsv_bw[5]) - || (bw <= iflp->unrsv_bw[6]) - || (bw <= iflp->unrsv_bw[7]) - || (bw <= iflp->ava_bw) - || (bw <= iflp->res_bw) - || (bw <= iflp->use_bw)) - { - vty_out (vty, - "Maximum Bandwidth could not be lower than others bandwidth\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Update Maximum Bandwidth if needed */ - link_param_cmd_set_float (ifp, &iflp->max_bw, LP_MAX_BW, bw); - - return CMD_SUCCESS; + int idx_bandwidth = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + + float bw; + + if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) { + vty_out(vty, "link_params_maxbw: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Check that Maximum bandwidth is not lower than other bandwidth + * parameters */ + if ((bw <= iflp->max_rsv_bw) || (bw <= iflp->unrsv_bw[0]) + || (bw <= iflp->unrsv_bw[1]) || (bw <= iflp->unrsv_bw[2]) + || (bw <= iflp->unrsv_bw[3]) || (bw <= iflp->unrsv_bw[4]) + || (bw <= iflp->unrsv_bw[5]) || (bw <= iflp->unrsv_bw[6]) + || (bw <= iflp->unrsv_bw[7]) || (bw <= iflp->ava_bw) + || (bw <= iflp->res_bw) || (bw <= iflp->use_bw)) { + vty_out(vty, + "Maximum Bandwidth could not be lower than others bandwidth\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Update Maximum Bandwidth if needed */ + link_param_cmd_set_float(ifp, &iflp->max_bw, LP_MAX_BW, bw); + + return CMD_SUCCESS; } DEFUN (link_params_max_rsv_bw, @@ -2005,31 +1943,30 @@ DEFUN (link_params_max_rsv_bw, "Maximum bandwidth that may be reserved\n" "Bytes/second (IEEE floating point format)\n") { - int idx_bandwidth = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - float bw; + int idx_bandwidth = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + float bw; - if (sscanf (argv[idx_bandwidth]->arg, "%g", &bw) != 1) - { - vty_out (vty, "link_params_max_rsv_bw: fscanf: %s\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) { + vty_out(vty, "link_params_max_rsv_bw: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - /* Check that bandwidth is not greater than maximum bandwidth parameter */ - if (bw > iflp->max_bw) - { - vty_out (vty, - "Maximum Reservable Bandwidth could not be greater than Maximum Bandwidth (%g)\n", - iflp->max_bw); - return CMD_WARNING_CONFIG_FAILED; - } + /* Check that bandwidth is not greater than maximum bandwidth parameter + */ + if (bw > iflp->max_bw) { + vty_out(vty, + "Maximum Reservable Bandwidth could not be greater than Maximum Bandwidth (%g)\n", + iflp->max_bw); + return CMD_WARNING_CONFIG_FAILED; + } - /* Update Maximum Reservable Bandwidth if needed */ - link_param_cmd_set_float (ifp, &iflp->max_rsv_bw, LP_MAX_RSV_BW, bw); + /* Update Maximum Reservable Bandwidth if needed */ + link_param_cmd_set_float(ifp, &iflp->max_rsv_bw, LP_MAX_RSV_BW, bw); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (link_params_unrsv_bw, @@ -2039,41 +1976,40 @@ DEFUN (link_params_unrsv_bw, "Priority\n" "Bytes/second (IEEE floating point format)\n") { - int idx_number = 1; - int idx_bandwidth = 2; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - int priority; - float bw; - - /* We don't have to consider about range check here. */ - if (sscanf (argv[idx_number]->arg, "%d", &priority) != 1) - { - vty_out (vty, "link_params_unrsv_bw: fscanf: %s\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - if (sscanf (argv[idx_bandwidth]->arg, "%g", &bw) != 1) - { - vty_out (vty, "link_params_unrsv_bw: fscanf: %s\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check that bandwidth is not greater than maximum bandwidth parameter */ - if (bw > iflp->max_bw) - { - vty_out (vty, - "UnReserved Bandwidth could not be greater than Maximum Bandwidth (%g)\n", - iflp->max_bw); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Update Unreserved Bandwidth if needed */ - link_param_cmd_set_float (ifp, &iflp->unrsv_bw[priority], LP_UNRSV_BW, bw); - - return CMD_SUCCESS; + int idx_number = 1; + int idx_bandwidth = 2; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + int priority; + float bw; + + /* We don't have to consider about range check here. */ + if (sscanf(argv[idx_number]->arg, "%d", &priority) != 1) { + vty_out(vty, "link_params_unrsv_bw: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) { + vty_out(vty, "link_params_unrsv_bw: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Check that bandwidth is not greater than maximum bandwidth parameter + */ + if (bw > iflp->max_bw) { + vty_out(vty, + "UnReserved Bandwidth could not be greater than Maximum Bandwidth (%g)\n", + iflp->max_bw); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Update Unreserved Bandwidth if needed */ + link_param_cmd_set_float(ifp, &iflp->unrsv_bw[priority], LP_UNRSV_BW, + bw); + + return CMD_SUCCESS; } DEFUN (link_params_admin_grp, @@ -2082,22 +2018,21 @@ DEFUN (link_params_admin_grp, "Administrative group membership\n" "32-bit Hexadecimal value (e.g. 0xa1)\n") { - int idx_bitpattern = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - unsigned long value; + int idx_bitpattern = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + unsigned long value; - if (sscanf (argv[idx_bitpattern]->arg, "0x%lx", &value) != 1) - { - vty_out (vty, "link_params_admin_grp: fscanf: %s\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + if (sscanf(argv[idx_bitpattern]->arg, "0x%lx", &value) != 1) { + vty_out(vty, "link_params_admin_grp: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - /* Update Administrative Group if needed */ - link_param_cmd_set_uint32 (ifp, &iflp->admin_grp, LP_ADM_GRP, value); + /* Update Administrative Group if needed */ + link_param_cmd_set_uint32(ifp, &iflp->admin_grp, LP_ADM_GRP, value); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_link_params_admin_grp, @@ -2106,12 +2041,12 @@ DEFUN (no_link_params_admin_grp, NO_STR "Disable Administrative group membership on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - /* Unset Admin Group */ - link_param_cmd_unset(ifp, LP_ADM_GRP); + /* Unset Admin Group */ + link_param_cmd_unset(ifp, LP_ADM_GRP); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* RFC5392 & RFC5316: INTER-AS */ @@ -2123,37 +2058,35 @@ DEFUN (link_params_inter_as, "Remote AS number\n" "AS number in the range <1-4294967295>\n") { - int idx_ipv4 = 1; - int idx_number = 3; + int idx_ipv4 = 1; + int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - struct in_addr addr; - u_int32_t as; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + struct in_addr addr; + u_int32_t as; - if (!inet_aton (argv[idx_ipv4]->arg, &addr)) - { - vty_out (vty, "Please specify Router-Addr by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!inet_aton(argv[idx_ipv4]->arg, &addr)) { + vty_out(vty, "Please specify Router-Addr by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - as = strtoul(argv[idx_number]->arg, NULL, 10); + as = strtoul(argv[idx_number]->arg, NULL, 10); - /* Update Remote IP and Remote AS fields if needed */ - if (IS_PARAM_UNSET(iflp, LP_RMT_AS) - || iflp->rmt_as != as - || iflp->rmt_ip.s_addr != addr.s_addr) - { + /* Update Remote IP and Remote AS fields if needed */ + if (IS_PARAM_UNSET(iflp, LP_RMT_AS) || iflp->rmt_as != as + || iflp->rmt_ip.s_addr != addr.s_addr) { - iflp->rmt_as = as; - iflp->rmt_ip.s_addr = addr.s_addr; - SET_PARAM(iflp, LP_RMT_AS); + iflp->rmt_as = as; + iflp->rmt_ip.s_addr = addr.s_addr; + SET_PARAM(iflp, LP_RMT_AS); - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative (ifp)) - zebra_interface_parameters_update (ifp); - } - return CMD_SUCCESS; + /* force protocols to update LINK STATE due to parameters change + */ + if (if_is_operative(ifp)) + zebra_interface_parameters_update(ifp); + } + return CMD_SUCCESS; } DEFUN (no_link_params_inter_as, @@ -2162,22 +2095,23 @@ DEFUN (no_link_params_inter_as, NO_STR "Remove Neighbor IP address and AS number for Inter-AS TE\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); - /* Reset Remote IP and AS neighbor */ - iflp->rmt_as = 0; - iflp->rmt_ip.s_addr = 0; - UNSET_PARAM(iflp, LP_RMT_AS); + /* Reset Remote IP and AS neighbor */ + iflp->rmt_as = 0; + iflp->rmt_ip.s_addr = 0; + UNSET_PARAM(iflp, LP_RMT_AS); - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative (ifp)) - zebra_interface_parameters_update (ifp); + /* force protocols to update LINK STATE due to parameters change */ + if (if_is_operative(ifp)) + zebra_interface_parameters_update(ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } -/* RFC7471: OSPF Traffic Engineering (TE) Metric extensions & draft-ietf-isis-metric-extensions-07.txt */ +/* RFC7471: OSPF Traffic Engineering (TE) Metric extensions & + * draft-ietf-isis-metric-extensions-07.txt */ DEFUN (link_params_delay, link_params_delay_cmd, "delay (0-16777215) [min (0-16777215) max (0-16777215)]", @@ -2188,75 +2122,68 @@ DEFUN (link_params_delay, "Maximum delay\n" "Maximum delay in micro-second as decimal (0...16777215)\n") { - /* Get and Check new delay values */ - u_int32_t delay = 0, low = 0, high = 0; - delay = strtoul(argv[1]->arg, NULL, 10); - if (argc == 6) - { - low = strtoul(argv[3]->arg, NULL, 10); - high = strtoul(argv[5]->arg, NULL, 10); - } - - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - u_int8_t update = 0; - - if (argc == 2) - { - /* Check new delay value against old Min and Max delays if set */ - if (IS_PARAM_SET(iflp, LP_MM_DELAY) - && (delay <= iflp->min_delay || delay >= iflp->max_delay)) - { - vty_out (vty, "Average delay should be comprise between Min (%d) and Max (%d) delay\n", - iflp->min_delay, iflp->max_delay); - return CMD_WARNING_CONFIG_FAILED; - } - /* Update delay if value is not set or change */ - if (IS_PARAM_UNSET(iflp, LP_DELAY)|| iflp->av_delay != delay) - { - iflp->av_delay = delay; - SET_PARAM(iflp, LP_DELAY); - update = 1; - } - /* Unset Min and Max delays if already set */ - if (IS_PARAM_SET(iflp, LP_MM_DELAY)) - { - iflp->min_delay = 0; - iflp->max_delay = 0; - UNSET_PARAM(iflp, LP_MM_DELAY); - update = 1; - } - } - else - { - /* Check new delays value coherency */ - if (delay <= low || delay >= high) - { - vty_out (vty, "Average delay should be comprise between Min (%d) and Max (%d) delay\n", - low, high); - return CMD_WARNING_CONFIG_FAILED; - } - /* Update Delays if needed */ - if (IS_PARAM_UNSET(iflp, LP_DELAY) - || IS_PARAM_UNSET(iflp, LP_MM_DELAY) - || iflp->av_delay != delay - || iflp->min_delay != low - || iflp->max_delay != high) - { - iflp->av_delay = delay; - SET_PARAM(iflp, LP_DELAY); - iflp->min_delay = low; - iflp->max_delay = high; - SET_PARAM(iflp, LP_MM_DELAY); - update = 1; - } - } - - /* force protocols to update LINK STATE due to parameters change */ - if (update == 1 && if_is_operative (ifp)) - zebra_interface_parameters_update (ifp); - - return CMD_SUCCESS; + /* Get and Check new delay values */ + u_int32_t delay = 0, low = 0, high = 0; + delay = strtoul(argv[1]->arg, NULL, 10); + if (argc == 6) { + low = strtoul(argv[3]->arg, NULL, 10); + high = strtoul(argv[5]->arg, NULL, 10); + } + + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + u_int8_t update = 0; + + if (argc == 2) { + /* Check new delay value against old Min and Max delays if set + */ + if (IS_PARAM_SET(iflp, LP_MM_DELAY) + && (delay <= iflp->min_delay || delay >= iflp->max_delay)) { + vty_out(vty, + "Average delay should be comprise between Min (%d) and Max (%d) delay\n", + iflp->min_delay, iflp->max_delay); + return CMD_WARNING_CONFIG_FAILED; + } + /* Update delay if value is not set or change */ + if (IS_PARAM_UNSET(iflp, LP_DELAY) || iflp->av_delay != delay) { + iflp->av_delay = delay; + SET_PARAM(iflp, LP_DELAY); + update = 1; + } + /* Unset Min and Max delays if already set */ + if (IS_PARAM_SET(iflp, LP_MM_DELAY)) { + iflp->min_delay = 0; + iflp->max_delay = 0; + UNSET_PARAM(iflp, LP_MM_DELAY); + update = 1; + } + } else { + /* Check new delays value coherency */ + if (delay <= low || delay >= high) { + vty_out(vty, + "Average delay should be comprise between Min (%d) and Max (%d) delay\n", + low, high); + return CMD_WARNING_CONFIG_FAILED; + } + /* Update Delays if needed */ + if (IS_PARAM_UNSET(iflp, LP_DELAY) + || IS_PARAM_UNSET(iflp, LP_MM_DELAY) + || iflp->av_delay != delay || iflp->min_delay != low + || iflp->max_delay != high) { + iflp->av_delay = delay; + SET_PARAM(iflp, LP_DELAY); + iflp->min_delay = low; + iflp->max_delay = high; + SET_PARAM(iflp, LP_MM_DELAY); + update = 1; + } + } + + /* force protocols to update LINK STATE due to parameters change */ + if (update == 1 && if_is_operative(ifp)) + zebra_interface_parameters_update(ifp); + + return CMD_SUCCESS; } DEFUN (no_link_params_delay, @@ -2265,21 +2192,21 @@ DEFUN (no_link_params_delay, NO_STR "Disable Unidirectional Average, Min & Max Link Delay on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); - /* Unset Delays */ - iflp->av_delay = 0; - UNSET_PARAM(iflp, LP_DELAY); - iflp->min_delay = 0; - iflp->max_delay = 0; - UNSET_PARAM(iflp, LP_MM_DELAY); + /* Unset Delays */ + iflp->av_delay = 0; + UNSET_PARAM(iflp, LP_DELAY); + iflp->min_delay = 0; + iflp->max_delay = 0; + UNSET_PARAM(iflp, LP_MM_DELAY); - /* force protocols to update LINK STATE due to parameters change */ - if (if_is_operative (ifp)) - zebra_interface_parameters_update (ifp); + /* force protocols to update LINK STATE due to parameters change */ + if (if_is_operative(ifp)) + zebra_interface_parameters_update(ifp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (link_params_delay_var, @@ -2288,17 +2215,17 @@ DEFUN (link_params_delay_var, "Unidirectional Link Delay Variation\n" "delay variation in micro-second as decimal (0...16777215)\n") { - int idx_number = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - u_int32_t value; + int idx_number = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + u_int32_t value; - value = strtoul(argv[idx_number]->arg, NULL, 10); + value = strtoul(argv[idx_number]->arg, NULL, 10); - /* Update Delay Variation if needed */ - link_param_cmd_set_uint32 (ifp, &iflp->delay_var, LP_DELAY_VAR, value); + /* Update Delay Variation if needed */ + link_param_cmd_set_uint32(ifp, &iflp->delay_var, LP_DELAY_VAR, value); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_link_params_delay_var, @@ -2307,12 +2234,12 @@ DEFUN (no_link_params_delay_var, NO_STR "Disable Unidirectional Delay Variation on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - /* Unset Delay Variation */ - link_param_cmd_unset(ifp, LP_DELAY_VAR); + /* Unset Delay Variation */ + link_param_cmd_unset(ifp, LP_DELAY_VAR); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (link_params_pkt_loss, @@ -2321,25 +2248,24 @@ DEFUN (link_params_pkt_loss, "Unidirectional Link Packet Loss\n" "percentage of total traffic by 0.000003% step and less than 50.331642%\n") { - int idx_percentage = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - float fval; + int idx_percentage = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + float fval; - if (sscanf (argv[idx_percentage]->arg, "%g", &fval) != 1) - { - vty_out (vty, "link_params_pkt_loss: fscanf: %s\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + if (sscanf(argv[idx_percentage]->arg, "%g", &fval) != 1) { + vty_out(vty, "link_params_pkt_loss: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - if (fval > MAX_PKT_LOSS) - fval = MAX_PKT_LOSS; + if (fval > MAX_PKT_LOSS) + fval = MAX_PKT_LOSS; - /* Update Packet Loss if needed */ - link_param_cmd_set_float (ifp, &iflp->pkt_loss, LP_PKT_LOSS, fval); + /* Update Packet Loss if needed */ + link_param_cmd_set_float(ifp, &iflp->pkt_loss, LP_PKT_LOSS, fval); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_link_params_pkt_loss, @@ -2348,12 +2274,12 @@ DEFUN (no_link_params_pkt_loss, NO_STR "Disable Unidirectional Link Packet Loss on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - /* Unset Packet Loss */ - link_param_cmd_unset(ifp, LP_PKT_LOSS); + /* Unset Packet Loss */ + link_param_cmd_unset(ifp, LP_PKT_LOSS); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (link_params_res_bw, @@ -2362,30 +2288,30 @@ DEFUN (link_params_res_bw, "Unidirectional Residual Bandwidth\n" "Bytes/second (IEEE floating point format)\n") { - int idx_bandwidth = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - float bw; + int idx_bandwidth = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + float bw; - if (sscanf (argv[idx_bandwidth]->arg, "%g", &bw) != 1) - { - vty_out (vty, "link_params_res_bw: fscanf: %s\n",safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) { + vty_out(vty, "link_params_res_bw: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - /* Check that bandwidth is not greater than maximum bandwidth parameter */ - if (bw > iflp->max_bw) - { - vty_out (vty, - "Residual Bandwidth could not be greater than Maximum Bandwidth (%g)\n", - iflp->max_bw); - return CMD_WARNING_CONFIG_FAILED; - } + /* Check that bandwidth is not greater than maximum bandwidth parameter + */ + if (bw > iflp->max_bw) { + vty_out(vty, + "Residual Bandwidth could not be greater than Maximum Bandwidth (%g)\n", + iflp->max_bw); + return CMD_WARNING_CONFIG_FAILED; + } - /* Update Residual Bandwidth if needed */ - link_param_cmd_set_float (ifp, &iflp->res_bw, LP_RES_BW, bw); + /* Update Residual Bandwidth if needed */ + link_param_cmd_set_float(ifp, &iflp->res_bw, LP_RES_BW, bw); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_link_params_res_bw, @@ -2394,12 +2320,12 @@ DEFUN (no_link_params_res_bw, NO_STR "Disable Unidirectional Residual Bandwidth on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - /* Unset Residual Bandwidth */ - link_param_cmd_unset(ifp, LP_RES_BW); + /* Unset Residual Bandwidth */ + link_param_cmd_unset(ifp, LP_RES_BW); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (link_params_ava_bw, @@ -2408,30 +2334,30 @@ DEFUN (link_params_ava_bw, "Unidirectional Available Bandwidth\n" "Bytes/second (IEEE floating point format)\n") { - int idx_bandwidth = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - float bw; + int idx_bandwidth = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + float bw; - if (sscanf (argv[idx_bandwidth]->arg, "%g", &bw) != 1) - { - vty_out (vty, "link_params_ava_bw: fscanf: %s\n",safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) { + vty_out(vty, "link_params_ava_bw: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - /* Check that bandwidth is not greater than maximum bandwidth parameter */ - if (bw > iflp->max_bw) - { - vty_out (vty, - "Available Bandwidth could not be greater than Maximum Bandwidth (%g)\n", - iflp->max_bw); - return CMD_WARNING_CONFIG_FAILED; - } + /* Check that bandwidth is not greater than maximum bandwidth parameter + */ + if (bw > iflp->max_bw) { + vty_out(vty, + "Available Bandwidth could not be greater than Maximum Bandwidth (%g)\n", + iflp->max_bw); + return CMD_WARNING_CONFIG_FAILED; + } - /* Update Residual Bandwidth if needed */ - link_param_cmd_set_float (ifp, &iflp->ava_bw, LP_AVA_BW, bw); + /* Update Residual Bandwidth if needed */ + link_param_cmd_set_float(ifp, &iflp->ava_bw, LP_AVA_BW, bw); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_link_params_ava_bw, @@ -2440,12 +2366,12 @@ DEFUN (no_link_params_ava_bw, NO_STR "Disable Unidirectional Available Bandwidth on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - /* Unset Available Bandwidth */ - link_param_cmd_unset(ifp, LP_AVA_BW); + /* Unset Available Bandwidth */ + link_param_cmd_unset(ifp, LP_AVA_BW); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (link_params_use_bw, @@ -2454,30 +2380,30 @@ DEFUN (link_params_use_bw, "Unidirectional Utilised Bandwidth\n" "Bytes/second (IEEE floating point format)\n") { - int idx_bandwidth = 1; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct if_link_params *iflp = if_link_params_get (ifp); - float bw; + int idx_bandwidth = 1; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct if_link_params *iflp = if_link_params_get(ifp); + float bw; - if (sscanf (argv[idx_bandwidth]->arg, "%g", &bw) != 1) - { - vty_out (vty, "link_params_use_bw: fscanf: %s\n",safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + if (sscanf(argv[idx_bandwidth]->arg, "%g", &bw) != 1) { + vty_out(vty, "link_params_use_bw: fscanf: %s\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } - /* Check that bandwidth is not greater than maximum bandwidth parameter */ - if (bw > iflp->max_bw) - { - vty_out (vty, - "Utilised Bandwidth could not be greater than Maximum Bandwidth (%g)\n", - iflp->max_bw); - return CMD_WARNING_CONFIG_FAILED; - } + /* Check that bandwidth is not greater than maximum bandwidth parameter + */ + if (bw > iflp->max_bw) { + vty_out(vty, + "Utilised Bandwidth could not be greater than Maximum Bandwidth (%g)\n", + iflp->max_bw); + return CMD_WARNING_CONFIG_FAILED; + } - /* Update Utilized Bandwidth if needed */ - link_param_cmd_set_float (ifp, &iflp->use_bw, LP_USE_BW, bw); + /* Update Utilized Bandwidth if needed */ + link_param_cmd_set_float(ifp, &iflp->use_bw, LP_USE_BW, bw); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_link_params_use_bw, @@ -2486,153 +2412,142 @@ DEFUN (no_link_params_use_bw, NO_STR "Disable Unidirectional Utilised Bandwidth on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - /* Unset Utilised Bandwidth */ - link_param_cmd_unset(ifp, LP_USE_BW); + /* Unset Utilised Bandwidth */ + link_param_cmd_unset(ifp, LP_USE_BW); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -ip_address_install (struct vty *vty, struct interface *ifp, - const char *addr_str, const char *peer_str, - const char *label) +static int ip_address_install(struct vty *vty, struct interface *ifp, + const char *addr_str, const char *peer_str, + const char *label) { - struct zebra_if *if_data; - struct prefix_ipv4 cp; - struct connected *ifc; - struct prefix_ipv4 *p; - int ret; + struct zebra_if *if_data; + struct prefix_ipv4 cp; + struct connected *ifc; + struct prefix_ipv4 *p; + int ret; - if_data = ifp->info; + if_data = ifp->info; - ret = str2prefix_ipv4 (addr_str, &cp); - if (ret <= 0) - { - vty_out (vty, "%% Malformed address \n"); - return CMD_WARNING_CONFIG_FAILED; - } + ret = str2prefix_ipv4(addr_str, &cp); + if (ret <= 0) { + vty_out(vty, "%% Malformed address \n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (ipv4_martian(&cp.prefix)) - { - vty_out (vty, "%% Invalid address\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (ipv4_martian(&cp.prefix)) { + vty_out(vty, "%% Invalid address\n"); + return CMD_WARNING_CONFIG_FAILED; + } - ifc = connected_check (ifp, (struct prefix *) &cp); - if (! ifc) - { - ifc = connected_new (); - ifc->ifp = ifp; + ifc = connected_check(ifp, (struct prefix *)&cp); + if (!ifc) { + ifc = connected_new(); + ifc->ifp = ifp; + + /* Address. */ + p = prefix_ipv4_new(); + *p = cp; + ifc->address = (struct prefix *)p; + + /* Broadcast. */ + if (p->prefixlen <= IPV4_MAX_PREFIXLEN - 2) { + p = prefix_ipv4_new(); + *p = cp; + p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr, + p->prefixlen); + ifc->destination = (struct prefix *)p; + } - /* Address. */ - p = prefix_ipv4_new (); - *p = cp; - ifc->address = (struct prefix *) p; + /* Label. */ + if (label) + ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label); - /* Broadcast. */ - if (p->prefixlen <= IPV4_MAX_PREFIXLEN-2) - { - p = prefix_ipv4_new (); - *p = cp; - p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,p->prefixlen); - ifc->destination = (struct prefix *) p; - } - - /* Label. */ - if (label) - ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); - - /* Add to linked list. */ - listnode_add (ifp->connected, ifc); - } - - /* This address is configured from zebra. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) - SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED); - - /* In case of this route need to install kernel. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_QUEUED) - && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE) - && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) - { - /* Some system need to up the interface to set IP address. */ - if (! if_is_up (ifp)) - { - if_set_flags (ifp, IFF_UP | IFF_RUNNING); - if_refresh (ifp); + /* Add to linked list. */ + listnode_add(ifp->connected, ifc); } - ret = if_set_prefix (ifp, ifc); - if (ret < 0) - { - vty_out (vty, "%% Can't set interface IP address: %s.\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - SET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); - /* The address will be advertised to zebra clients when the notification - * from the kernel has been received. - * It will also be added to the subnet chain list, then. */ - } - - return CMD_SUCCESS; -} - -static int -ip_address_uninstall (struct vty *vty, struct interface *ifp, - const char *addr_str, const char *peer_str, - const char *label) -{ - struct prefix_ipv4 cp; - struct connected *ifc; - int ret; - - /* Convert to prefix structure. */ - ret = str2prefix_ipv4 (addr_str, &cp); - if (ret <= 0) - { - vty_out (vty, "%% Malformed address \n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check current interface address. */ - ifc = connected_check (ifp, (struct prefix *) &cp); - if (! ifc) - { - vty_out (vty, "%% Can't find address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* This is not configured address. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) - return CMD_WARNING_CONFIG_FAILED; - - UNSET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED); - - /* This is not real address or interface is not active. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_QUEUED) - || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) - { - listnode_delete (ifp->connected, ifc); - connected_free (ifc); - return CMD_WARNING_CONFIG_FAILED; - } - - /* This is real route. */ - ret = if_unset_prefix (ifp, ifc); - if (ret < 0) - { - vty_out (vty, "%% Can't unset interface IP address: %s.\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - UNSET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); - /* we will receive a kernel notification about this route being removed. - * this will trigger its removal from the connected list. */ - return CMD_SUCCESS; + /* This address is configured from zebra. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) + SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); + + /* In case of this route need to install kernel. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) + && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) + && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) { + /* Some system need to up the interface to set IP address. */ + if (!if_is_up(ifp)) { + if_set_flags(ifp, IFF_UP | IFF_RUNNING); + if_refresh(ifp); + } + + ret = if_set_prefix(ifp, ifc); + if (ret < 0) { + vty_out(vty, "%% Can't set interface IP address: %s.\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + /* The address will be advertised to zebra clients when the + * notification + * from the kernel has been received. + * It will also be added to the subnet chain list, then. */ + } + + return CMD_SUCCESS; +} + +static int ip_address_uninstall(struct vty *vty, struct interface *ifp, + const char *addr_str, const char *peer_str, + const char *label) +{ + struct prefix_ipv4 cp; + struct connected *ifc; + int ret; + + /* Convert to prefix structure. */ + ret = str2prefix_ipv4(addr_str, &cp); + if (ret <= 0) { + vty_out(vty, "%% Malformed address \n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Check current interface address. */ + ifc = connected_check(ifp, (struct prefix *)&cp); + if (!ifc) { + vty_out(vty, "%% Can't find address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* This is not configured address. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) + return CMD_WARNING_CONFIG_FAILED; + + UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); + + /* This is not real address or interface is not active. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) + || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + listnode_delete(ifp->connected, ifc); + connected_free(ifc); + return CMD_WARNING_CONFIG_FAILED; + } + + /* This is real route. */ + ret = if_unset_prefix(ifp, ifc); + if (ret < 0) { + vty_out(vty, "%% Can't unset interface IP address: %s.\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + /* we will receive a kernel notification about this route being removed. + * this will trigger its removal from the connected list. */ + return CMD_SUCCESS; } DEFUN (ip_address, @@ -2642,9 +2557,10 @@ DEFUN (ip_address, "Set the IP address of an interface\n" "IP address (e.g. 10.0.0.1/8)\n") { - int idx_ipv4_prefixlen = 2; - VTY_DECLVAR_CONTEXT (interface, ifp); - return ip_address_install (vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL, NULL); + int idx_ipv4_prefixlen = 2; + VTY_DECLVAR_CONTEXT(interface, ifp); + return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL, + NULL); } DEFUN (no_ip_address, @@ -2655,9 +2571,10 @@ DEFUN (no_ip_address, "Set the IP address of an interface\n" "IP Address (e.g. 10.0.0.1/8)") { - int idx_ipv4_prefixlen = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - return ip_address_uninstall (vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL, NULL); + int idx_ipv4_prefixlen = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg, + NULL, NULL); } @@ -2671,10 +2588,11 @@ DEFUN (ip_address_label, "Label of this address\n" "Label\n") { - int idx_ipv4_prefixlen = 2; - int idx_line = 4; - VTY_DECLVAR_CONTEXT (interface, ifp); - return ip_address_install (vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL, argv[idx_line]->arg); + int idx_ipv4_prefixlen = 2; + int idx_line = 4; + VTY_DECLVAR_CONTEXT(interface, ifp); + return ip_address_install(vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL, + argv[idx_line]->arg); } DEFUN (no_ip_address_label, @@ -2687,162 +2605,152 @@ DEFUN (no_ip_address_label, "Label of this address\n" "Label\n") { - int idx_ipv4_prefixlen = 3; - int idx_line = 5; - VTY_DECLVAR_CONTEXT (interface, ifp); - return ip_address_uninstall (vty, ifp, argv[idx_ipv4_prefixlen]->arg, NULL, argv[idx_line]->arg); + int idx_ipv4_prefixlen = 3; + int idx_line = 5; + VTY_DECLVAR_CONTEXT(interface, ifp); + return ip_address_uninstall(vty, ifp, argv[idx_ipv4_prefixlen]->arg, + NULL, argv[idx_line]->arg); } #endif /* HAVE_NETLINK */ -static int -ipv6_address_install (struct vty *vty, struct interface *ifp, - const char *addr_str, const char *peer_str, - const char *label, int secondary) -{ - struct zebra_if *if_data; - struct prefix_ipv6 cp; - struct connected *ifc; - struct prefix_ipv6 *p; - int ret; - - if_data = ifp->info; - - ret = str2prefix_ipv6 (addr_str, &cp); - if (ret <= 0) - { - vty_out (vty, "%% Malformed address \n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (ipv6_martian(&cp.prefix)) - { - vty_out (vty, "%% Invalid address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ifc = connected_check (ifp, (struct prefix *) &cp); - if (! ifc) - { - ifc = connected_new (); - ifc->ifp = ifp; - - /* Address. */ - p = prefix_ipv6_new (); - *p = cp; - ifc->address = (struct prefix *) p; - - /* Secondary. */ - if (secondary) - SET_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY); - - /* Label. */ - if (label) - ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); - - /* Add to linked list. */ - listnode_add (ifp->connected, ifc); - } - - /* This address is configured from zebra. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) - SET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED); - - /* In case of this route need to install kernel. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_QUEUED) - && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE) - && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) - { - /* Some system need to up the interface to set IP address. */ - if (! if_is_up (ifp)) - { - if_set_flags (ifp, IFF_UP | IFF_RUNNING); - if_refresh (ifp); +static int ipv6_address_install(struct vty *vty, struct interface *ifp, + const char *addr_str, const char *peer_str, + const char *label, int secondary) +{ + struct zebra_if *if_data; + struct prefix_ipv6 cp; + struct connected *ifc; + struct prefix_ipv6 *p; + int ret; + + if_data = ifp->info; + + ret = str2prefix_ipv6(addr_str, &cp); + if (ret <= 0) { + vty_out(vty, "%% Malformed address \n"); + return CMD_WARNING_CONFIG_FAILED; } - ret = if_prefix_add_ipv6 (ifp, ifc); + if (ipv6_martian(&cp.prefix)) { + vty_out(vty, "%% Invalid address\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (ret < 0) - { - vty_out (vty, "%% Can't set interface IP address: %s.\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; + ifc = connected_check(ifp, (struct prefix *)&cp); + if (!ifc) { + ifc = connected_new(); + ifc->ifp = ifp; + + /* Address. */ + p = prefix_ipv6_new(); + *p = cp; + ifc->address = (struct prefix *)p; + + /* Secondary. */ + if (secondary) + SET_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY); + + /* Label. */ + if (label) + ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label); + + /* Add to linked list. */ + listnode_add(ifp->connected, ifc); } - SET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); - /* The address will be advertised to zebra clients when the notification - * from the kernel has been received. */ - } + /* This address is configured from zebra. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) + SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); + + /* In case of this route need to install kernel. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) + && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) + && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) { + /* Some system need to up the interface to set IP address. */ + if (!if_is_up(ifp)) { + if_set_flags(ifp, IFF_UP | IFF_RUNNING); + if_refresh(ifp); + } + + ret = if_prefix_add_ipv6(ifp, ifc); + + if (ret < 0) { + vty_out(vty, "%% Can't set interface IP address: %s.\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + /* The address will be advertised to zebra clients when the + * notification + * from the kernel has been received. */ + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Return true if an ipv6 address is configured on ifp */ -int -ipv6_address_configured (struct interface *ifp) -{ - struct connected *connected; - struct listnode *node; - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) - if (CHECK_FLAG (connected->conf, ZEBRA_IFC_REAL) && (connected->address->family == AF_INET6)) - return 1; - - return 0; -} - -static int -ipv6_address_uninstall (struct vty *vty, struct interface *ifp, - const char *addr_str, const char *peer_str, - const char *label, int secondry) -{ - struct prefix_ipv6 cp; - struct connected *ifc; - int ret; - - /* Convert to prefix structure. */ - ret = str2prefix_ipv6 (addr_str, &cp); - if (ret <= 0) - { - vty_out (vty, "%% Malformed address \n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check current interface address. */ - ifc = connected_check (ifp, (struct prefix *) &cp); - if (! ifc) - { - vty_out (vty, "%% Can't find address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* This is not configured address. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) - return CMD_WARNING_CONFIG_FAILED; - - UNSET_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED); - - /* This is not real address or interface is not active. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_QUEUED) - || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) - { - listnode_delete (ifp->connected, ifc); - connected_free (ifc); - return CMD_WARNING_CONFIG_FAILED; - } - - /* This is real route. */ - ret = if_prefix_delete_ipv6 (ifp, ifc); - if (ret < 0) - { - vty_out (vty, "%% Can't unset interface IP address: %s.\n", - safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - UNSET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); - /* This information will be propagated to the zclients when the - * kernel notification is received. */ - return CMD_SUCCESS; +int ipv6_address_configured(struct interface *ifp) +{ + struct connected *connected; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) + if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL) + && (connected->address->family == AF_INET6)) + return 1; + + return 0; +} + +static int ipv6_address_uninstall(struct vty *vty, struct interface *ifp, + const char *addr_str, const char *peer_str, + const char *label, int secondry) +{ + struct prefix_ipv6 cp; + struct connected *ifc; + int ret; + + /* Convert to prefix structure. */ + ret = str2prefix_ipv6(addr_str, &cp); + if (ret <= 0) { + vty_out(vty, "%% Malformed address \n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Check current interface address. */ + ifc = connected_check(ifp, (struct prefix *)&cp); + if (!ifc) { + vty_out(vty, "%% Can't find address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* This is not configured address. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) + return CMD_WARNING_CONFIG_FAILED; + + UNSET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); + + /* This is not real address or interface is not active. */ + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) + || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + listnode_delete(ifp->connected, ifc); + connected_free(ifc); + return CMD_WARNING_CONFIG_FAILED; + } + + /* This is real route. */ + ret = if_prefix_delete_ipv6(ifp, ifc); + if (ret < 0) { + vty_out(vty, "%% Can't unset interface IP address: %s.\n", + safe_strerror(errno)); + return CMD_WARNING_CONFIG_FAILED; + } + + UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + /* This information will be propagated to the zclients when the + * kernel notification is received. */ + return CMD_SUCCESS; } DEFUN (ipv6_address, @@ -2852,9 +2760,10 @@ DEFUN (ipv6_address, "Set the IP address of an interface\n" "IPv6 address (e.g. 3ffe:506::1/48)\n") { - int idx_ipv6_prefixlen = 2; - VTY_DECLVAR_CONTEXT (interface, ifp); - return ipv6_address_install (vty, ifp, argv[idx_ipv6_prefixlen]->arg, NULL, NULL, 0); + int idx_ipv6_prefixlen = 2; + VTY_DECLVAR_CONTEXT(interface, ifp); + return ipv6_address_install(vty, ifp, argv[idx_ipv6_prefixlen]->arg, + NULL, NULL, 0); } DEFUN (no_ipv6_address, @@ -2865,209 +2774,204 @@ DEFUN (no_ipv6_address, "Set the IP address of an interface\n" "IPv6 address (e.g. 3ffe:506::1/48)\n") { - int idx_ipv6_prefixlen = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - return ipv6_address_uninstall (vty, ifp, argv[idx_ipv6_prefixlen]->arg, NULL, NULL, 0); -} - -static int -link_params_config_write (struct vty *vty, struct interface *ifp) -{ - int i; - - if ((ifp == NULL) || !HAS_LINK_PARAMS(ifp)) - return -1; - - struct if_link_params *iflp = ifp->link_params; - - vty_out (vty, " link-params\n"); - vty_out (vty, " enable\n"); - if (IS_PARAM_SET(iflp, LP_TE_METRIC) && iflp->te_metric != ifp->metric) - vty_out (vty, " metric %u\n",iflp->te_metric); - if (IS_PARAM_SET(iflp, LP_MAX_BW) && iflp->max_bw != iflp->default_bw) - vty_out (vty, " max-bw %g\n", iflp->max_bw); - if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW) && iflp->max_rsv_bw != iflp->default_bw) - vty_out (vty, " max-rsv-bw %g\n", iflp->max_rsv_bw); - if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) - { - for (i = 0; i < 8; i++) - if (iflp->unrsv_bw[i] != iflp->default_bw) - vty_out (vty, " unrsv-bw %d %g\n", - i, iflp->unrsv_bw[i]); - } - if (IS_PARAM_SET(iflp, LP_ADM_GRP)) - vty_out (vty, " admin-grp 0x%x\n", iflp->admin_grp); - if (IS_PARAM_SET(iflp, LP_DELAY)) - { - vty_out(vty, " delay %u", iflp->av_delay); - if (IS_PARAM_SET(iflp, LP_MM_DELAY)) - { - vty_out(vty, " min %u", iflp->min_delay); - vty_out(vty, " max %u", iflp->max_delay); - } - vty_out (vty, "\n"); - } - if (IS_PARAM_SET(iflp, LP_DELAY_VAR)) - vty_out (vty, " delay-variation %u\n", iflp->delay_var); - if (IS_PARAM_SET(iflp, LP_PKT_LOSS)) - vty_out (vty, " packet-loss %g\n", iflp->pkt_loss); - if (IS_PARAM_SET(iflp, LP_AVA_BW)) - vty_out (vty, " ava-bw %g\n", iflp->ava_bw); - if (IS_PARAM_SET(iflp, LP_RES_BW)) - vty_out (vty, " res-bw %g\n", iflp->res_bw); - if (IS_PARAM_SET(iflp, LP_USE_BW)) - vty_out (vty, " use-bw %g\n", iflp->use_bw); - if (IS_PARAM_SET(iflp, LP_RMT_AS)) - vty_out (vty, " neighbor %s as %u\n", inet_ntoa(iflp->rmt_ip), - iflp->rmt_as); - vty_out (vty, " exit-link-params\n"); - return 0; -} - -static int -if_config_write (struct vty *vty) -{ - struct vrf *vrf; - struct listnode *node; - struct interface *ifp; - - zebra_ptm_write (vty); - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp)) - { - struct zebra_if *if_data; - struct listnode *addrnode; - struct connected *ifc; - struct prefix *p; - struct vrf *vrf; - - if_data = ifp->info; - vrf = vrf_lookup_by_id (ifp->vrf_id); - - if (ifp->vrf_id == VRF_DEFAULT) - vty_out (vty, "interface %s\n", ifp->name); - else - vty_out (vty, "interface %s vrf %s\n", ifp->name,vrf->name); - - if (if_data) - { - if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) - vty_out (vty, " shutdown\n"); + int idx_ipv6_prefixlen = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + return ipv6_address_uninstall(vty, ifp, argv[idx_ipv6_prefixlen]->arg, + NULL, NULL, 0); +} + +static int link_params_config_write(struct vty *vty, struct interface *ifp) +{ + int i; + + if ((ifp == NULL) || !HAS_LINK_PARAMS(ifp)) + return -1; - zebra_ptm_if_write(vty, if_data); + struct if_link_params *iflp = ifp->link_params; + + vty_out(vty, " link-params\n"); + vty_out(vty, " enable\n"); + if (IS_PARAM_SET(iflp, LP_TE_METRIC) && iflp->te_metric != ifp->metric) + vty_out(vty, " metric %u\n", iflp->te_metric); + if (IS_PARAM_SET(iflp, LP_MAX_BW) && iflp->max_bw != iflp->default_bw) + vty_out(vty, " max-bw %g\n", iflp->max_bw); + if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW) + && iflp->max_rsv_bw != iflp->default_bw) + vty_out(vty, " max-rsv-bw %g\n", iflp->max_rsv_bw); + if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) { + for (i = 0; i < 8; i++) + if (iflp->unrsv_bw[i] != iflp->default_bw) + vty_out(vty, " unrsv-bw %d %g\n", i, + iflp->unrsv_bw[i]); + } + if (IS_PARAM_SET(iflp, LP_ADM_GRP)) + vty_out(vty, " admin-grp 0x%x\n", iflp->admin_grp); + if (IS_PARAM_SET(iflp, LP_DELAY)) { + vty_out(vty, " delay %u", iflp->av_delay); + if (IS_PARAM_SET(iflp, LP_MM_DELAY)) { + vty_out(vty, " min %u", iflp->min_delay); + vty_out(vty, " max %u", iflp->max_delay); + } + vty_out(vty, "\n"); } + if (IS_PARAM_SET(iflp, LP_DELAY_VAR)) + vty_out(vty, " delay-variation %u\n", iflp->delay_var); + if (IS_PARAM_SET(iflp, LP_PKT_LOSS)) + vty_out(vty, " packet-loss %g\n", iflp->pkt_loss); + if (IS_PARAM_SET(iflp, LP_AVA_BW)) + vty_out(vty, " ava-bw %g\n", iflp->ava_bw); + if (IS_PARAM_SET(iflp, LP_RES_BW)) + vty_out(vty, " res-bw %g\n", iflp->res_bw); + if (IS_PARAM_SET(iflp, LP_USE_BW)) + vty_out(vty, " use-bw %g\n", iflp->use_bw); + if (IS_PARAM_SET(iflp, LP_RMT_AS)) + vty_out(vty, " neighbor %s as %u\n", inet_ntoa(iflp->rmt_ip), + iflp->rmt_as); + vty_out(vty, " exit-link-params\n"); + return 0; +} + +static int if_config_write(struct vty *vty) +{ + struct vrf *vrf; + struct listnode *node; + struct interface *ifp; + + zebra_ptm_write(vty); + + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + for (ALL_LIST_ELEMENTS_RO(vrf->iflist, node, ifp)) { + struct zebra_if *if_data; + struct listnode *addrnode; + struct connected *ifc; + struct prefix *p; + struct vrf *vrf; + + if_data = ifp->info; + vrf = vrf_lookup_by_id(ifp->vrf_id); + + if (ifp->vrf_id == VRF_DEFAULT) + vty_out(vty, "interface %s\n", ifp->name); + else + vty_out(vty, "interface %s vrf %s\n", ifp->name, + vrf->name); + + if (if_data) { + if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) + vty_out(vty, " shutdown\n"); + + zebra_ptm_if_write(vty, if_data); + } - if (ifp->desc) - vty_out (vty, " description %s\n",ifp->desc); + if (ifp->desc) + vty_out(vty, " description %s\n", ifp->desc); - /* Assign bandwidth here to avoid unnecessary interface flap - while processing config script */ - if (ifp->bandwidth != 0) - vty_out (vty, " bandwidth %u\n", ifp->bandwidth); + /* Assign bandwidth here to avoid unnecessary interface flap + while processing config script */ + if (ifp->bandwidth != 0) + vty_out(vty, " bandwidth %u\n", ifp->bandwidth); - if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) - vty_out (vty, " no link-detect\n"); + if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) + vty_out(vty, " no link-detect\n"); - for (ALL_LIST_ELEMENTS_RO (ifp->connected, addrnode, ifc)) - { - if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) - { - char buf[INET6_ADDRSTRLEN]; - p = ifc->address; - vty_out (vty, " ip%s address %s", - p->family == AF_INET ? "" : "v6", - prefix2str (p, buf, sizeof(buf))); + for (ALL_LIST_ELEMENTS_RO(ifp->connected, addrnode, ifc)) { + if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) { + char buf[INET6_ADDRSTRLEN]; + p = ifc->address; + vty_out(vty, " ip%s address %s", + p->family == AF_INET ? "" : "v6", + prefix2str(p, buf, sizeof(buf))); - if (ifc->label) - vty_out (vty, " label %s", ifc->label); + if (ifc->label) + vty_out(vty, " label %s", ifc->label); - vty_out (vty, "\n"); - } - } + vty_out(vty, "\n"); + } + } - if (if_data) - { - if (if_data->multicast != IF_ZEBRA_MULTICAST_UNSPEC) - vty_out (vty, " %smulticast\n", - if_data->multicast == IF_ZEBRA_MULTICAST_ON ? "" : "no "); - } + if (if_data) { + if (if_data->multicast != IF_ZEBRA_MULTICAST_UNSPEC) + vty_out(vty, " %smulticast\n", + if_data->multicast + == IF_ZEBRA_MULTICAST_ON + ? "" + : "no "); + } -#if defined (HAVE_RTADV) - rtadv_config_write (vty, ifp); +#if defined(HAVE_RTADV) + rtadv_config_write(vty, ifp); #endif /* HAVE_RTADV */ #ifdef HAVE_IRDP - irdp_config_write (vty, ifp); + irdp_config_write(vty, ifp); #endif /* IRDP */ - link_params_config_write (vty, ifp); + link_params_config_write(vty, ifp); - vty_out (vty, "!\n"); - } - return 0; + vty_out(vty, "!\n"); + } + return 0; } /* Allocate and initialize interface vector. */ -void -zebra_if_init (void) -{ - /* Initialize interface and new hook. */ - if_add_hook (IF_NEW_HOOK, if_zebra_new_hook); - if_add_hook (IF_DELETE_HOOK, if_zebra_delete_hook); - - /* Install configuration write function. */ - install_node (&interface_node, if_config_write); - install_node (&link_params_node, NULL); - if_cmd_init (); - - install_element (VIEW_NODE, &show_interface_cmd); - install_element (VIEW_NODE, &show_interface_vrf_all_cmd); - install_element (VIEW_NODE, &show_interface_name_vrf_cmd); - install_element (VIEW_NODE, &show_interface_name_vrf_all_cmd); - - install_element (ENABLE_NODE, &show_interface_desc_cmd); - install_element (ENABLE_NODE, &show_interface_desc_vrf_all_cmd); - install_element (INTERFACE_NODE, &multicast_cmd); - install_element (INTERFACE_NODE, &no_multicast_cmd); - install_element (INTERFACE_NODE, &linkdetect_cmd); - install_element (INTERFACE_NODE, &no_linkdetect_cmd); - install_element (INTERFACE_NODE, &shutdown_if_cmd); - install_element (INTERFACE_NODE, &no_shutdown_if_cmd); - install_element (INTERFACE_NODE, &bandwidth_if_cmd); - install_element (INTERFACE_NODE, &no_bandwidth_if_cmd); - install_element (INTERFACE_NODE, &ip_address_cmd); - install_element (INTERFACE_NODE, &no_ip_address_cmd); - install_element (INTERFACE_NODE, &ipv6_address_cmd); - install_element (INTERFACE_NODE, &no_ipv6_address_cmd); +void zebra_if_init(void) +{ + /* Initialize interface and new hook. */ + if_add_hook(IF_NEW_HOOK, if_zebra_new_hook); + if_add_hook(IF_DELETE_HOOK, if_zebra_delete_hook); + + /* Install configuration write function. */ + install_node(&interface_node, if_config_write); + install_node(&link_params_node, NULL); + if_cmd_init(); + + install_element(VIEW_NODE, &show_interface_cmd); + install_element(VIEW_NODE, &show_interface_vrf_all_cmd); + install_element(VIEW_NODE, &show_interface_name_vrf_cmd); + install_element(VIEW_NODE, &show_interface_name_vrf_all_cmd); + + install_element(ENABLE_NODE, &show_interface_desc_cmd); + install_element(ENABLE_NODE, &show_interface_desc_vrf_all_cmd); + install_element(INTERFACE_NODE, &multicast_cmd); + install_element(INTERFACE_NODE, &no_multicast_cmd); + install_element(INTERFACE_NODE, &linkdetect_cmd); + install_element(INTERFACE_NODE, &no_linkdetect_cmd); + install_element(INTERFACE_NODE, &shutdown_if_cmd); + install_element(INTERFACE_NODE, &no_shutdown_if_cmd); + install_element(INTERFACE_NODE, &bandwidth_if_cmd); + install_element(INTERFACE_NODE, &no_bandwidth_if_cmd); + install_element(INTERFACE_NODE, &ip_address_cmd); + install_element(INTERFACE_NODE, &no_ip_address_cmd); + install_element(INTERFACE_NODE, &ipv6_address_cmd); + install_element(INTERFACE_NODE, &no_ipv6_address_cmd); #ifdef HAVE_NETLINK - install_element (INTERFACE_NODE, &ip_address_label_cmd); - install_element (INTERFACE_NODE, &no_ip_address_label_cmd); + install_element(INTERFACE_NODE, &ip_address_label_cmd); + install_element(INTERFACE_NODE, &no_ip_address_label_cmd); #endif /* HAVE_NETLINK */ - install_element(INTERFACE_NODE, &link_params_cmd); - install_default(LINK_PARAMS_NODE); - install_element(LINK_PARAMS_NODE, &link_params_enable_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_enable_cmd); - install_element(LINK_PARAMS_NODE, &link_params_metric_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_metric_cmd); - install_element(LINK_PARAMS_NODE, &link_params_maxbw_cmd); - install_element(LINK_PARAMS_NODE, &link_params_max_rsv_bw_cmd); - install_element(LINK_PARAMS_NODE, &link_params_unrsv_bw_cmd); - install_element(LINK_PARAMS_NODE, &link_params_admin_grp_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_admin_grp_cmd); - install_element(LINK_PARAMS_NODE, &link_params_inter_as_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_inter_as_cmd); - install_element(LINK_PARAMS_NODE, &link_params_delay_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_delay_cmd); - install_element(LINK_PARAMS_NODE, &link_params_delay_var_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_delay_var_cmd); - install_element(LINK_PARAMS_NODE, &link_params_pkt_loss_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_pkt_loss_cmd); - install_element(LINK_PARAMS_NODE, &link_params_ava_bw_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_ava_bw_cmd); - install_element(LINK_PARAMS_NODE, &link_params_res_bw_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_res_bw_cmd); - install_element(LINK_PARAMS_NODE, &link_params_use_bw_cmd); - install_element(LINK_PARAMS_NODE, &no_link_params_use_bw_cmd); - install_element(LINK_PARAMS_NODE, &exit_link_params_cmd); + install_element(INTERFACE_NODE, &link_params_cmd); + install_default(LINK_PARAMS_NODE); + install_element(LINK_PARAMS_NODE, &link_params_enable_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_enable_cmd); + install_element(LINK_PARAMS_NODE, &link_params_metric_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_metric_cmd); + install_element(LINK_PARAMS_NODE, &link_params_maxbw_cmd); + install_element(LINK_PARAMS_NODE, &link_params_max_rsv_bw_cmd); + install_element(LINK_PARAMS_NODE, &link_params_unrsv_bw_cmd); + install_element(LINK_PARAMS_NODE, &link_params_admin_grp_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_admin_grp_cmd); + install_element(LINK_PARAMS_NODE, &link_params_inter_as_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_inter_as_cmd); + install_element(LINK_PARAMS_NODE, &link_params_delay_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_delay_cmd); + install_element(LINK_PARAMS_NODE, &link_params_delay_var_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_delay_var_cmd); + install_element(LINK_PARAMS_NODE, &link_params_pkt_loss_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_pkt_loss_cmd); + install_element(LINK_PARAMS_NODE, &link_params_ava_bw_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_ava_bw_cmd); + install_element(LINK_PARAMS_NODE, &link_params_res_bw_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_res_bw_cmd); + install_element(LINK_PARAMS_NODE, &link_params_use_bw_cmd); + install_element(LINK_PARAMS_NODE, &no_link_params_use_bw_cmd); + install_element(LINK_PARAMS_NODE, &exit_link_params_cmd); } diff --git a/zebra/interface.h b/zebra/interface.h index f5ca00c4a..ea7226469 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -39,142 +39,144 @@ #define IF_ZEBRA_SHUTDOWN_OFF 0 #define IF_ZEBRA_SHUTDOWN_ON 1 -#if defined (HAVE_RTADV) +#if defined(HAVE_RTADV) /* Router advertisement parameter. From RFC4861, RFC6275 and RFC4191. */ -struct rtadvconf -{ - /* A flag indicating whether or not the router sends periodic Router - Advertisements and responds to Router Solicitations. - Default: FALSE */ - int AdvSendAdvertisements; - - /* The maximum time allowed between sending unsolicited multicast - Router Advertisements from the interface, in milliseconds. - MUST be no less than 70 ms [RFC6275 7.5] and no greater - than 1800000 ms [RFC4861 6.2.1]. - - Default: 600000 milliseconds */ - int MaxRtrAdvInterval; +struct rtadvconf { + /* A flag indicating whether or not the router sends periodic Router + Advertisements and responds to Router Solicitations. + Default: FALSE */ + int AdvSendAdvertisements; + + /* The maximum time allowed between sending unsolicited multicast + Router Advertisements from the interface, in milliseconds. + MUST be no less than 70 ms [RFC6275 7.5] and no greater + than 1800000 ms [RFC4861 6.2.1]. + + Default: 600000 milliseconds */ + int MaxRtrAdvInterval; #define RTADV_MAX_RTR_ADV_INTERVAL 600000 - /* The minimum time allowed between sending unsolicited multicast - Router Advertisements from the interface, in milliseconds. - MUST be no less than 30 ms [RFC6275 7.5]. - MUST be no greater than .75 * MaxRtrAdvInterval. + /* The minimum time allowed between sending unsolicited multicast + Router Advertisements from the interface, in milliseconds. + MUST be no less than 30 ms [RFC6275 7.5]. + MUST be no greater than .75 * MaxRtrAdvInterval. - Default: 0.33 * MaxRtrAdvInterval */ - int MinRtrAdvInterval; /* This field is currently unused. */ + Default: 0.33 * MaxRtrAdvInterval */ + int MinRtrAdvInterval; /* This field is currently unused. */ + /* $FRR indent$ */ + /* clang-format off */ #define RTADV_MIN_RTR_ADV_INTERVAL (0.33 * RTADV_MAX_RTR_ADV_INTERVAL) - /* Unsolicited Router Advertisements' interval timer. */ - int AdvIntervalTimer; + /* Unsolicited Router Advertisements' interval timer. */ + int AdvIntervalTimer; - /* The TRUE/FALSE value to be placed in the "Managed address - configuration" flag field in the Router Advertisement. See - [ADDRCONF]. - - Default: FALSE */ - int AdvManagedFlag; + /* The TRUE/FALSE value to be placed in the "Managed address + configuration" flag field in the Router Advertisement. See + [ADDRCONF]. + Default: FALSE */ + int AdvManagedFlag; - /* The TRUE/FALSE value to be placed in the "Other stateful - configuration" flag field in the Router Advertisement. See - [ADDRCONF]. - Default: FALSE */ - int AdvOtherConfigFlag; + /* The TRUE/FALSE value to be placed in the "Other stateful + configuration" flag field in the Router Advertisement. See + [ADDRCONF]. - /* The value to be placed in MTU options sent by the router. A - value of zero indicates that no MTU options are sent. + Default: FALSE */ + int AdvOtherConfigFlag; - Default: 0 */ - int AdvLinkMTU; + /* The value to be placed in MTU options sent by the router. A + value of zero indicates that no MTU options are sent. + Default: 0 */ + int AdvLinkMTU; - /* The value to be placed in the Reachable Time field in the Router - Advertisement messages sent by the router. The value zero means - unspecified (by this router). MUST be no greater than 3,600,000 - milliseconds (1 hour). - Default: 0 */ - u_int32_t AdvReachableTime; -#define RTADV_MAX_REACHABLE_TIME 3600000 + /* The value to be placed in the Reachable Time field in the Router + Advertisement messages sent by the router. The value zero means + unspecified (by this router). MUST be no greater than 3,600,000 + milliseconds (1 hour). + Default: 0 */ + u_int32_t AdvReachableTime; +#define RTADV_MAX_REACHABLE_TIME 3600000 - /* The value to be placed in the Retrans Timer field in the Router - Advertisement messages sent by the router. The value zero means - unspecified (by this router). + /* The value to be placed in the Retrans Timer field in the Router + Advertisement messages sent by the router. The value zero means + unspecified (by this router). - Default: 0 */ - int AdvRetransTimer; + Default: 0 */ + int AdvRetransTimer; - /* The default value to be placed in the Cur Hop Limit field in the - Router Advertisement messages sent by the router. The value - should be set to that current diameter of the Internet. The - value zero means unspecified (by this router). + /* The default value to be placed in the Cur Hop Limit field in the + Router Advertisement messages sent by the router. The value + should be set to that current diameter of the Internet. The + value zero means unspecified (by this router). - Default: The value specified in the "Assigned Numbers" RFC - [ASSIGNED] that was in effect at the time of implementation. */ - int AdvCurHopLimit; + Default: The value specified in the "Assigned Numbers" RFC + [ASSIGNED] that was in effect at the time of implementation. */ + int AdvCurHopLimit; - /* The value to be placed in the Router Lifetime field of Router - Advertisements sent from the interface, in seconds. MUST be - either zero or between MaxRtrAdvInterval and 9000 seconds. A - value of zero indicates that the router is not to be used as a - default router. + /* The value to be placed in the Router Lifetime field of Router + Advertisements sent from the interface, in seconds. MUST be + either zero or between MaxRtrAdvInterval and 9000 seconds. A + value of zero indicates that the router is not to be used as a + default router. - Default: 3 * MaxRtrAdvInterval */ - int AdvDefaultLifetime; + Default: 3 * MaxRtrAdvInterval */ + int AdvDefaultLifetime; #define RTADV_MAX_RTRLIFETIME 9000 /* 2.5 hours */ - /* A list of prefixes to be placed in Prefix Information options in - Router Advertisement messages sent from the interface. + /* A list of prefixes to be placed in Prefix Information options in + Router Advertisement messages sent from the interface. - Default: all prefixes that the router advertises via routing - protocols as being on-link for the interface from which the - advertisement is sent. The link-local prefix SHOULD NOT be - included in the list of advertised prefixes. */ - struct list *AdvPrefixList; + Default: all prefixes that the router advertises via routing + protocols as being on-link for the interface from which the + advertisement is sent. The link-local prefix SHOULD NOT be + included in the list of advertised prefixes. */ + struct list *AdvPrefixList; - /* The TRUE/FALSE value to be placed in the "Home agent" - flag field in the Router Advertisement. See [RFC6275 7.1]. + /* The TRUE/FALSE value to be placed in the "Home agent" + flag field in the Router Advertisement. See [RFC6275 7.1]. - Default: FALSE */ - int AdvHomeAgentFlag; + Default: FALSE */ + int AdvHomeAgentFlag; #ifndef ND_RA_FLAG_HOME_AGENT #define ND_RA_FLAG_HOME_AGENT 0x20 #endif - /* The value to be placed in Home Agent Information option if Home - Flag is set. - Default: 0 */ - int HomeAgentPreference; - - /* The value to be placed in Home Agent Information option if Home - Flag is set. Lifetime (seconds) MUST not be greater than 18.2 - hours. - The value 0 has special meaning: use of AdvDefaultLifetime value. - - Default: 0 */ - int HomeAgentLifetime; + /* The value to be placed in Home Agent Information option if Home + Flag is set. + Default: 0 */ + int HomeAgentPreference; + + /* The value to be placed in Home Agent Information option if Home + Flag is set. Lifetime (seconds) MUST not be greater than 18.2 + hours. + The value 0 has special meaning: use of AdvDefaultLifetime value. + + Default: 0 */ + int HomeAgentLifetime; #define RTADV_MAX_HALIFETIME 65520 /* 18.2 hours */ - /* The TRUE/FALSE value to insert or not an Advertisement Interval - option. See [RFC 6275 7.3] + /* The TRUE/FALSE value to insert or not an Advertisement Interval + option. See [RFC 6275 7.3] - Default: FALSE */ - int AdvIntervalOption; + Default: FALSE */ + int AdvIntervalOption; - /* The value to be placed in the Default Router Preference field of - a router advertisement. See [RFC 4191 2.1 & 2.2] + /* The value to be placed in the Default Router Preference field of + a router advertisement. See [RFC 4191 2.1 & 2.2] - Default: 0 (medium) */ - int DefaultPreference; + Default: 0 (medium) */ + int DefaultPreference; #define RTADV_PREF_MEDIUM 0x0 /* Per RFC4191. */ - u_char inFastRexmit; /* True if we're rexmits faster than usual */ - u_char configured; /* Has operator configured RA? */ - int NumFastReXmitsRemain; /* Loaded first with number of fast rexmits to do */ + u_char inFastRexmit; /* True if we're rexmits faster than usual */ + u_char configured; /* Has operator configured RA? */ + int + NumFastReXmitsRemain; /* Loaded first with number of fast + rexmits to do */ #define RTADV_FAST_REXMIT_PERIOD 1 /* 1 sec */ #define RTADV_NUM_FAST_REXMITS 4 /* Fast Rexmit RA 4 times on certain events */ @@ -183,158 +185,161 @@ struct rtadvconf #endif /* HAVE_RTADV */ /* Zebra interface type - ones of interest. */ -typedef enum -{ - ZEBRA_IF_VXLAN, /* VxLAN interface */ - ZEBRA_IF_VRF, /* VRF device */ - ZEBRA_IF_BRIDGE, /* bridge device */ - ZEBRA_IF_VLAN, /* VLAN sub-interface */ - ZEBRA_IF_OTHER, /* Anything else */ +typedef enum { + ZEBRA_IF_VXLAN, /* VxLAN interface */ + ZEBRA_IF_VRF, /* VRF device */ + ZEBRA_IF_BRIDGE, /* bridge device */ + ZEBRA_IF_VLAN, /* VLAN sub-interface */ + ZEBRA_IF_OTHER, /* Anything else */ } zebra_iftype_t; /* Zebra "slave" interface type */ -typedef enum -{ - ZEBRA_IF_SLAVE_NONE, /* Not a slave */ - ZEBRA_IF_SLAVE_VRF, /* Member of a VRF */ - ZEBRA_IF_SLAVE_BRIDGE, /* Member of a bridge */ - ZEBRA_IF_SLAVE_OTHER, /* Something else - e.g., bond slave */ +typedef enum { + ZEBRA_IF_SLAVE_NONE, /* Not a slave */ + ZEBRA_IF_SLAVE_VRF, /* Member of a VRF */ + ZEBRA_IF_SLAVE_BRIDGE, /* Member of a bridge */ + ZEBRA_IF_SLAVE_OTHER, /* Something else - e.g., bond slave */ } zebra_slave_iftype_t; /* `zebra' daemon local interface structure. */ -struct zebra_if -{ - /* Shutdown configuration. */ - u_char shutdown; +struct zebra_if { + /* Shutdown configuration. */ + u_char shutdown; - /* Multicast configuration. */ - u_char multicast; + /* Multicast configuration. */ + u_char multicast; - /* Router advertise configuration. */ - u_char rtadv_enable; + /* Router advertise configuration. */ + u_char rtadv_enable; - /* Installed addresses chains tree. */ - struct route_table *ipv4_subnets; + /* Installed addresses chains tree. */ + struct route_table *ipv4_subnets; - /* Information about up/down changes */ - unsigned int up_count; - char up_last[QUAGGA_TIMESTAMP_LEN]; - unsigned int down_count; - char down_last[QUAGGA_TIMESTAMP_LEN]; + /* Information about up/down changes */ + unsigned int up_count; + char up_last[QUAGGA_TIMESTAMP_LEN]; + unsigned int down_count; + char down_last[QUAGGA_TIMESTAMP_LEN]; #if defined(HAVE_RTADV) - struct rtadvconf rtadv; - unsigned int ra_sent, ra_rcvd; + struct rtadvconf rtadv; + unsigned int ra_sent, ra_rcvd; #endif /* HAVE_RTADV */ #ifdef HAVE_IRDP - struct irdp_interface irdp; + struct irdp_interface irdp; #endif #ifdef HAVE_STRUCT_SOCKADDR_DL - union { - /* note that sdl_storage is never accessed, it only exists to make space. - * all actual uses refer to sdl - but use sizeof(sdl_storage)! this fits - * best with C aliasing rules. */ - struct sockaddr_dl sdl; - struct sockaddr_storage sdl_storage; - }; + union { + /* note that sdl_storage is never accessed, it only exists to + * make space. + * all actual uses refer to sdl - but use sizeof(sdl_storage)! + * this fits + * best with C aliasing rules. */ + struct sockaddr_dl sdl; + struct sockaddr_storage sdl_storage; + }; #endif #ifdef SUNOS_5 - /* the real IFF_UP state of the primary interface. - * need this to differentiate between all interfaces being - * down (but primary still plumbed) and primary having gone - * ~IFF_UP, and all addresses gone. - */ - u_char primary_state; + /* the real IFF_UP state of the primary interface. + * need this to differentiate between all interfaces being + * down (but primary still plumbed) and primary having gone + * ~IFF_UP, and all addresses gone. + */ + u_char primary_state; #endif /* SUNOS_5 */ - /* ptm enable configuration */ - u_char ptm_enable; + /* ptm enable configuration */ + u_char ptm_enable; - /* Zebra interface and "slave" interface type */ - zebra_iftype_t zif_type; - zebra_slave_iftype_t zif_slave_type; + /* Zebra interface and "slave" interface type */ + zebra_iftype_t zif_type; + zebra_slave_iftype_t zif_slave_type; - /* Additional L2 info, depends on zif_type */ - union zebra_l2if_info l2info; + /* Additional L2 info, depends on zif_type */ + union zebra_l2if_info l2info; - /* For members of a bridge, link to bridge. */ - /* Note: If additional fields become necessary, this can be modified to - * be a pointer to a dynamically allocd struct. - */ - struct zebra_l2info_brslave brslave_info; + /* For members of a bridge, link to bridge. */ + /* Note: If additional fields become necessary, this can be modified to + * be a pointer to a dynamically allocd struct. + */ + struct zebra_l2info_brslave brslave_info; - /* Link fields - for sub-interfaces. */ - ifindex_t link_ifindex; - struct interface *link; + /* Link fields - for sub-interfaces. */ + ifindex_t link_ifindex; + struct interface *link; }; -static inline void -zebra_if_set_ziftype (struct interface *ifp, zebra_iftype_t zif_type, - zebra_slave_iftype_t zif_slave_type) +static inline void zebra_if_set_ziftype(struct interface *ifp, + zebra_iftype_t zif_type, + zebra_slave_iftype_t zif_slave_type) { - struct zebra_if *zif; + struct zebra_if *zif; - zif = (struct zebra_if *)ifp->info; - zif->zif_type = zif_type; - zif->zif_slave_type = zif_slave_type; + zif = (struct zebra_if *)ifp->info; + zif->zif_type = zif_type; + zif->zif_slave_type = zif_slave_type; } -#define IS_ZEBRA_IF_VRF(ifp) \ - (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VRF) - -#define IS_ZEBRA_IF_BRIDGE(ifp) \ - (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_BRIDGE) - -#define IS_ZEBRA_IF_VLAN(ifp) \ - (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VLAN) - -#define IS_ZEBRA_IF_VXLAN(ifp) \ - (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VXLAN) - -#define IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) \ - (((struct zebra_if *)(ifp->info))->zif_slave_type == ZEBRA_IF_SLAVE_BRIDGE) - -#define IS_ZEBRA_IF_VRF_SLAVE(ifp) \ - (((struct zebra_if *)(ifp->info))->zif_slave_type == ZEBRA_IF_SLAVE_VRF) - -extern struct interface *if_lookup_by_index_per_ns (struct zebra_ns *, u_int32_t); -extern struct interface *if_lookup_by_name_per_ns (struct zebra_ns *, const char *); -extern struct interface *if_link_per_ns (struct zebra_ns *, struct interface *); -extern const char *ifindex2ifname_per_ns (struct zebra_ns *, unsigned int); - -extern void if_unlink_per_ns (struct interface *); -extern void if_nbr_ipv6ll_to_ipv4ll_neigh_update (struct interface *ifp, - struct in6_addr *address, int add); -extern void if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (struct interface *ifp); -extern void if_delete_update (struct interface *ifp); -extern void if_add_update (struct interface *ifp); -extern void if_up (struct interface *); -extern void if_down (struct interface *); -extern void if_refresh (struct interface *); -extern void if_flags_update (struct interface *, uint64_t); -extern int if_subnet_add (struct interface *, struct connected *); -extern int if_subnet_delete (struct interface *, struct connected *); -extern int ipv6_address_configured (struct interface *ifp); -extern void if_handle_vrf_change (struct interface *ifp, vrf_id_t vrf_id); -extern void zebra_if_update_link (struct interface *ifp, ifindex_t link_ifindex); - -extern void vrf_add_update (struct vrf *vrfp); +#define IS_ZEBRA_IF_VRF(ifp) \ + (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VRF) + +#define IS_ZEBRA_IF_BRIDGE(ifp) \ + (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_BRIDGE) + +#define IS_ZEBRA_IF_VLAN(ifp) \ + (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VLAN) + +#define IS_ZEBRA_IF_VXLAN(ifp) \ + (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VXLAN) + +#define IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) \ + (((struct zebra_if *)(ifp->info))->zif_slave_type \ + == ZEBRA_IF_SLAVE_BRIDGE) + +#define IS_ZEBRA_IF_VRF_SLAVE(ifp) \ + (((struct zebra_if *)(ifp->info))->zif_slave_type == ZEBRA_IF_SLAVE_VRF) + +extern struct interface *if_lookup_by_index_per_ns(struct zebra_ns *, + u_int32_t); +extern struct interface *if_lookup_by_name_per_ns(struct zebra_ns *, + const char *); +extern struct interface *if_link_per_ns(struct zebra_ns *, struct interface *); +extern const char *ifindex2ifname_per_ns(struct zebra_ns *, unsigned int); + +extern void if_unlink_per_ns(struct interface *); +extern void if_nbr_ipv6ll_to_ipv4ll_neigh_update(struct interface *ifp, + struct in6_addr *address, + int add); +extern void if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(struct interface *ifp); +extern void if_delete_update(struct interface *ifp); +extern void if_add_update(struct interface *ifp); +extern void if_up(struct interface *); +extern void if_down(struct interface *); +extern void if_refresh(struct interface *); +extern void if_flags_update(struct interface *, uint64_t); +extern int if_subnet_add(struct interface *, struct connected *); +extern int if_subnet_delete(struct interface *, struct connected *); +extern int ipv6_address_configured(struct interface *ifp); +extern void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id); +extern void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex); + +extern void vrf_add_update(struct vrf *vrfp); #ifdef HAVE_PROC_NET_DEV -extern void ifstat_update_proc (void); +extern void ifstat_update_proc(void); #endif /* HAVE_PROC_NET_DEV */ #ifdef HAVE_NET_RT_IFLIST -extern void ifstat_update_sysctl (void); +extern void ifstat_update_sysctl(void); #endif /* HAVE_NET_RT_IFLIST */ #ifdef HAVE_PROC_NET_DEV -extern int interface_list_proc (void); +extern int interface_list_proc(void); #endif /* HAVE_PROC_NET_DEV */ #ifdef HAVE_PROC_NET_IF_INET6 -extern int ifaddr_proc_ipv6 (void); +extern int ifaddr_proc_ipv6(void); #endif /* HAVE_PROC_NET_IF_INET6 */ #endif /* _ZEBRA_INTERFACE_H */ diff --git a/zebra/ioctl.c b/zebra/ioctl.c index 25aeea18f..72d98943e 100644 --- a/zebra/ioctl.c +++ b/zebra/ioctl.c @@ -40,551 +40,525 @@ extern struct zebra_privs_t zserv_privs; /* clear and set interface name string */ -void -ifreq_set_name (struct ifreq *ifreq, struct interface *ifp) +void ifreq_set_name(struct ifreq *ifreq, struct interface *ifp) { - strncpy (ifreq->ifr_name, ifp->name, IFNAMSIZ); + strncpy(ifreq->ifr_name, ifp->name, IFNAMSIZ); } /* call ioctl system call */ -int -if_ioctl (u_long request, caddr_t buffer) +int if_ioctl(u_long request, caddr_t buffer) { - int sock; - int ret; - int err = 0; - - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - sock = socket (AF_INET, SOCK_DGRAM, 0); - if (sock < 0) - { - int save_errno = errno; - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - zlog_err("Cannot create UDP socket: %s", safe_strerror(save_errno)); - exit (1); - } - if ((ret = ioctl (sock, request, buffer)) < 0) - err = errno; - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - close (sock); - - if (ret < 0) - { - errno = err; - return ret; - } - return 0; + int sock; + int ret; + int err = 0; + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + int save_errno = errno; + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + zlog_err("Cannot create UDP socket: %s", + safe_strerror(save_errno)); + exit(1); + } + if ((ret = ioctl(sock, request, buffer)) < 0) + err = errno; + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + close(sock); + + if (ret < 0) { + errno = err; + return ret; + } + return 0; } -static int -if_ioctl_ipv6 (u_long request, caddr_t buffer) +static int if_ioctl_ipv6(u_long request, caddr_t buffer) { - int sock; - int ret; - int err = 0; - - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - sock = socket (AF_INET6, SOCK_DGRAM, 0); - if (sock < 0) - { - int save_errno = errno; - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - zlog_err("Cannot create IPv6 datagram socket: %s", - safe_strerror(save_errno)); - exit (1); - } - - if ((ret = ioctl (sock, request, buffer)) < 0) - err = errno; - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - close (sock); - - if (ret < 0) - { - errno = err; - return ret; - } - return 0; + int sock; + int ret; + int err = 0; + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + sock = socket(AF_INET6, SOCK_DGRAM, 0); + if (sock < 0) { + int save_errno = errno; + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + zlog_err("Cannot create IPv6 datagram socket: %s", + safe_strerror(save_errno)); + exit(1); + } + + if ((ret = ioctl(sock, request, buffer)) < 0) + err = errno; + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + close(sock); + + if (ret < 0) { + errno = err; + return ret; + } + return 0; } /* * get interface metric * -- if value is not avaliable set -1 */ -void -if_get_metric (struct interface *ifp) +void if_get_metric(struct interface *ifp) { #ifdef SIOCGIFMETRIC - struct ifreq ifreq; + struct ifreq ifreq; - ifreq_set_name (&ifreq, ifp); + ifreq_set_name(&ifreq, ifp); - if (if_ioctl (SIOCGIFMETRIC, (caddr_t) &ifreq) < 0) - return; - ifp->metric = ifreq.ifr_metric; - if (ifp->metric == 0) - ifp->metric = 1; -#else /* SIOCGIFMETRIC */ - ifp->metric = -1; + if (if_ioctl(SIOCGIFMETRIC, (caddr_t)&ifreq) < 0) + return; + ifp->metric = ifreq.ifr_metric; + if (ifp->metric == 0) + ifp->metric = 1; +#else /* SIOCGIFMETRIC */ + ifp->metric = -1; #endif /* SIOCGIFMETRIC */ } /* get interface MTU */ -void -if_get_mtu (struct interface *ifp) +void if_get_mtu(struct interface *ifp) { - struct ifreq ifreq; + struct ifreq ifreq; - ifreq_set_name (&ifreq, ifp); + ifreq_set_name(&ifreq, ifp); #if defined(SIOCGIFMTU) - if (if_ioctl (SIOCGIFMTU, (caddr_t) & ifreq) < 0) - { - zlog_info ("Can't lookup mtu by ioctl(SIOCGIFMTU)"); - ifp->mtu6 = ifp->mtu = -1; - return; - } + if (if_ioctl(SIOCGIFMTU, (caddr_t)&ifreq) < 0) { + zlog_info("Can't lookup mtu by ioctl(SIOCGIFMTU)"); + ifp->mtu6 = ifp->mtu = -1; + return; + } #ifdef SUNOS_5 - ifp->mtu6 = ifp->mtu = ifreq.ifr_metric; + ifp->mtu6 = ifp->mtu = ifreq.ifr_metric; #else - ifp->mtu6 = ifp->mtu = ifreq.ifr_mtu; + ifp->mtu6 = ifp->mtu = ifreq.ifr_mtu; #endif /* SUNOS_5 */ - /* propogate */ - zebra_interface_up_update(ifp); + /* propogate */ + zebra_interface_up_update(ifp); #else - zlog_info("Can't lookup mtu on this system"); - ifp->mtu6 = ifp->mtu = -1; + zlog_info("Can't lookup mtu on this system"); + ifp->mtu6 = ifp->mtu = -1; #endif } #ifdef HAVE_NETLINK /* Interface address setting via netlink interface. */ -int -if_set_prefix (struct interface *ifp, struct connected *ifc) +int if_set_prefix(struct interface *ifp, struct connected *ifc) { - return kernel_address_add_ipv4 (ifp, ifc); + return kernel_address_add_ipv4(ifp, ifc); } /* Interface address is removed using netlink interface. */ -int -if_unset_prefix (struct interface *ifp, struct connected *ifc) +int if_unset_prefix(struct interface *ifp, struct connected *ifc) { - return kernel_address_delete_ipv4 (ifp, ifc); + return kernel_address_delete_ipv4(ifp, ifc); } #else /* ! HAVE_NETLINK */ #ifdef HAVE_STRUCT_IFALIASREQ /* Set up interface's IP address, netmask (and broadcas? ). *BSD may has ifaliasreq structure. */ -int -if_set_prefix (struct interface *ifp, struct connected *ifc) +int if_set_prefix(struct interface *ifp, struct connected *ifc) { - int ret; - struct ifaliasreq addreq; - struct sockaddr_in addr; - struct sockaddr_in mask; - struct prefix_ipv4 *p; + int ret; + struct ifaliasreq addreq; + struct sockaddr_in addr; + struct sockaddr_in mask; + struct prefix_ipv4 *p; - p = (struct prefix_ipv4 *) ifc->address; - rib_lookup_and_pushup (p, ifp->vrf_id); + p = (struct prefix_ipv4 *)ifc->address; + rib_lookup_and_pushup(p, ifp->vrf_id); - memset (&addreq, 0, sizeof addreq); - strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); + memset(&addreq, 0, sizeof addreq); + strncpy((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); - memset (&addr, 0, sizeof (struct sockaddr_in)); - addr.sin_addr = p->prefix; - addr.sin_family = p->family; + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_addr = p->prefix; + addr.sin_family = p->family; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - addr.sin_len = sizeof (struct sockaddr_in); + addr.sin_len = sizeof(struct sockaddr_in); #endif - memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in)); + memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in)); - memset (&mask, 0, sizeof (struct sockaddr_in)); - masklen2ip (p->prefixlen, &mask.sin_addr); - mask.sin_family = p->family; + memset(&mask, 0, sizeof(struct sockaddr_in)); + masklen2ip(p->prefixlen, &mask.sin_addr); + mask.sin_family = p->family; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - mask.sin_len = sizeof (struct sockaddr_in); + mask.sin_len = sizeof(struct sockaddr_in); #endif - memcpy (&addreq.ifra_mask, &mask, sizeof (struct sockaddr_in)); - - ret = if_ioctl (SIOCAIFADDR, (caddr_t) &addreq); - if (ret < 0) - return ret; - return 0; + memcpy(&addreq.ifra_mask, &mask, sizeof(struct sockaddr_in)); + + ret = if_ioctl(SIOCAIFADDR, (caddr_t)&addreq); + if (ret < 0) + return ret; + return 0; } /* Set up interface's IP address, netmask (and broadcas? ). *BSD may has ifaliasreq structure. */ -int -if_unset_prefix (struct interface *ifp, struct connected *ifc) +int if_unset_prefix(struct interface *ifp, struct connected *ifc) { - int ret; - struct ifaliasreq addreq; - struct sockaddr_in addr; - struct sockaddr_in mask; - struct prefix_ipv4 *p; + int ret; + struct ifaliasreq addreq; + struct sockaddr_in addr; + struct sockaddr_in mask; + struct prefix_ipv4 *p; - p = (struct prefix_ipv4 *)ifc->address; + p = (struct prefix_ipv4 *)ifc->address; - memset (&addreq, 0, sizeof addreq); - strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); + memset(&addreq, 0, sizeof addreq); + strncpy((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); - memset (&addr, 0, sizeof (struct sockaddr_in)); - addr.sin_addr = p->prefix; - addr.sin_family = p->family; + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_addr = p->prefix; + addr.sin_family = p->family; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - addr.sin_len = sizeof (struct sockaddr_in); + addr.sin_len = sizeof(struct sockaddr_in); #endif - memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in)); + memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in)); - memset (&mask, 0, sizeof (struct sockaddr_in)); - masklen2ip (p->prefixlen, &mask.sin_addr); - mask.sin_family = p->family; + memset(&mask, 0, sizeof(struct sockaddr_in)); + masklen2ip(p->prefixlen, &mask.sin_addr); + mask.sin_family = p->family; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - mask.sin_len = sizeof (struct sockaddr_in); + mask.sin_len = sizeof(struct sockaddr_in); #endif - memcpy (&addreq.ifra_mask, &mask, sizeof (struct sockaddr_in)); - - ret = if_ioctl (SIOCDIFADDR, (caddr_t) &addreq); - if (ret < 0) - return ret; - return 0; + memcpy(&addreq.ifra_mask, &mask, sizeof(struct sockaddr_in)); + + ret = if_ioctl(SIOCDIFADDR, (caddr_t)&addreq); + if (ret < 0) + return ret; + return 0; } #else /* Set up interface's address, netmask (and broadcas? ). Linux or Solaris uses ifname:number semantics to set IP address aliases. */ -int -if_set_prefix (struct interface *ifp, struct connected *ifc) +int if_set_prefix(struct interface *ifp, struct connected *ifc) { - int ret; - struct ifreq ifreq; - struct sockaddr_in addr; - struct sockaddr_in broad; - struct sockaddr_in mask; - struct prefix_ipv4 ifaddr; - struct prefix_ipv4 *p; - - p = (struct prefix_ipv4 *) ifc->address; - - ifaddr = *p; - - ifreq_set_name (&ifreq, ifp); - - addr.sin_addr = p->prefix; - addr.sin_family = p->family; - memcpy (&ifreq.ifr_addr, &addr, sizeof (struct sockaddr_in)); - ret = if_ioctl (SIOCSIFADDR, (caddr_t) &ifreq); - if (ret < 0) - return ret; - - /* We need mask for make broadcast addr. */ - masklen2ip (p->prefixlen, &mask.sin_addr); - - if (if_is_broadcast (ifp)) - { - apply_mask_ipv4 (&ifaddr); - addr.sin_addr = ifaddr.prefix; - - broad.sin_addr.s_addr = (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr); - broad.sin_family = p->family; - - memcpy (&ifreq.ifr_broadaddr, &broad, sizeof (struct sockaddr_in)); - ret = if_ioctl (SIOCSIFBRDADDR, (caddr_t) &ifreq); - if (ret < 0) - return ret; - } - - mask.sin_family = p->family; + int ret; + struct ifreq ifreq; + struct sockaddr_in addr; + struct sockaddr_in broad; + struct sockaddr_in mask; + struct prefix_ipv4 ifaddr; + struct prefix_ipv4 *p; + + p = (struct prefix_ipv4 *)ifc->address; + + ifaddr = *p; + + ifreq_set_name(&ifreq, ifp); + + addr.sin_addr = p->prefix; + addr.sin_family = p->family; + memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in)); + ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq); + if (ret < 0) + return ret; + + /* We need mask for make broadcast addr. */ + masklen2ip(p->prefixlen, &mask.sin_addr); + + if (if_is_broadcast(ifp)) { + apply_mask_ipv4(&ifaddr); + addr.sin_addr = ifaddr.prefix; + + broad.sin_addr.s_addr = + (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr); + broad.sin_family = p->family; + + memcpy(&ifreq.ifr_broadaddr, &broad, + sizeof(struct sockaddr_in)); + ret = if_ioctl(SIOCSIFBRDADDR, (caddr_t)&ifreq); + if (ret < 0) + return ret; + } + + mask.sin_family = p->family; #ifdef SUNOS_5 - memcpy (&mask, &ifreq.ifr_addr, sizeof (mask)); + memcpy(&mask, &ifreq.ifr_addr, sizeof(mask)); #else - memcpy (&ifreq.ifr_netmask, &mask, sizeof (struct sockaddr_in)); + memcpy(&ifreq.ifr_netmask, &mask, sizeof(struct sockaddr_in)); #endif /* SUNOS5 */ - ret = if_ioctl (SIOCSIFNETMASK, (caddr_t) &ifreq); - if (ret < 0) - return ret; + ret = if_ioctl(SIOCSIFNETMASK, (caddr_t)&ifreq); + if (ret < 0) + return ret; - return 0; + return 0; } /* Set up interface's address, netmask (and broadcas? ). Linux or Solaris uses ifname:number semantics to set IP address aliases. */ -int -if_unset_prefix (struct interface *ifp, struct connected *ifc) +int if_unset_prefix(struct interface *ifp, struct connected *ifc) { - int ret; - struct ifreq ifreq; - struct sockaddr_in addr; - struct prefix_ipv4 *p; + int ret; + struct ifreq ifreq; + struct sockaddr_in addr; + struct prefix_ipv4 *p; - p = (struct prefix_ipv4 *) ifc->address; + p = (struct prefix_ipv4 *)ifc->address; - ifreq_set_name (&ifreq, ifp); + ifreq_set_name(&ifreq, ifp); - memset (&addr, 0, sizeof (struct sockaddr_in)); - addr.sin_family = p->family; - memcpy (&ifreq.ifr_addr, &addr, sizeof (struct sockaddr_in)); - ret = if_ioctl (SIOCSIFADDR, (caddr_t) &ifreq); - if (ret < 0) - return ret; + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = p->family; + memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in)); + ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq); + if (ret < 0) + return ret; - return 0; + return 0; } #endif /* HAVE_STRUCT_IFALIASREQ */ #endif /* HAVE_NETLINK */ /* get interface flags */ -void -if_get_flags (struct interface *ifp) +void if_get_flags(struct interface *ifp) { - int ret; - struct ifreq ifreq; + int ret; + struct ifreq ifreq; #ifdef HAVE_BSD_LINK_DETECT - struct ifmediareq ifmr; + struct ifmediareq ifmr; #endif /* HAVE_BSD_LINK_DETECT */ - ifreq_set_name (&ifreq, ifp); + ifreq_set_name(&ifreq, ifp); - ret = if_ioctl (SIOCGIFFLAGS, (caddr_t) &ifreq); - if (ret < 0) - { - zlog_err("if_ioctl(SIOCGIFFLAGS) failed: %s", safe_strerror(errno)); - return; - } + ret = if_ioctl(SIOCGIFFLAGS, (caddr_t)&ifreq); + if (ret < 0) { + zlog_err("if_ioctl(SIOCGIFFLAGS) failed: %s", + safe_strerror(errno)); + return; + } #ifdef HAVE_BSD_LINK_DETECT /* Detect BSD link-state at start-up */ - /* Per-default, IFF_RUNNING is held high, unless link-detect says - * otherwise - we abuse IFF_RUNNING inside zebra as a link-state flag, - * following practice on Linux and Solaris kernels - */ - SET_FLAG(ifreq.ifr_flags, IFF_RUNNING); - - if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) - { - (void) memset(&ifmr, 0, sizeof(ifmr)); - strncpy (ifmr.ifm_name, ifp->name, IFNAMSIZ); - - /* Seems not all interfaces implement this ioctl */ - if (if_ioctl(SIOCGIFMEDIA, (caddr_t) &ifmr) < 0) - zlog_err("if_ioctl(SIOCGIFMEDIA) failed: %s", safe_strerror(errno)); - else if (ifmr.ifm_status & IFM_AVALID) /* Link state is valid */ - { - if (ifmr.ifm_status & IFM_ACTIVE) - SET_FLAG(ifreq.ifr_flags, IFF_RUNNING); - else - UNSET_FLAG(ifreq.ifr_flags, IFF_RUNNING); - } - } + /* Per-default, IFF_RUNNING is held high, unless link-detect says + * otherwise - we abuse IFF_RUNNING inside zebra as a link-state flag, + * following practice on Linux and Solaris kernels + */ + SET_FLAG(ifreq.ifr_flags, IFF_RUNNING); + + if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) { + (void)memset(&ifmr, 0, sizeof(ifmr)); + strncpy(ifmr.ifm_name, ifp->name, IFNAMSIZ); + + /* Seems not all interfaces implement this ioctl */ + if (if_ioctl(SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) + zlog_err("if_ioctl(SIOCGIFMEDIA) failed: %s", + safe_strerror(errno)); + else if (ifmr.ifm_status & IFM_AVALID) /* Link state is valid */ + { + if (ifmr.ifm_status & IFM_ACTIVE) + SET_FLAG(ifreq.ifr_flags, IFF_RUNNING); + else + UNSET_FLAG(ifreq.ifr_flags, IFF_RUNNING); + } + } #endif /* HAVE_BSD_LINK_DETECT */ - if_flags_update (ifp, (ifreq.ifr_flags & 0x0000ffff)); + if_flags_update(ifp, (ifreq.ifr_flags & 0x0000ffff)); } /* Set interface flags */ -int -if_set_flags (struct interface *ifp, uint64_t flags) +int if_set_flags(struct interface *ifp, uint64_t flags) { - int ret; - struct ifreq ifreq; + int ret; + struct ifreq ifreq; - memset (&ifreq, 0, sizeof(struct ifreq)); - ifreq_set_name (&ifreq, ifp); + memset(&ifreq, 0, sizeof(struct ifreq)); + ifreq_set_name(&ifreq, ifp); - ifreq.ifr_flags = ifp->flags; - ifreq.ifr_flags |= flags; + ifreq.ifr_flags = ifp->flags; + ifreq.ifr_flags |= flags; - ret = if_ioctl (SIOCSIFFLAGS, (caddr_t) &ifreq); + ret = if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq); - if (ret < 0) - { - zlog_info ("can't set interface flags"); - return ret; - } - return 0; + if (ret < 0) { + zlog_info("can't set interface flags"); + return ret; + } + return 0; } /* Unset interface's flag. */ -int -if_unset_flags (struct interface *ifp, uint64_t flags) +int if_unset_flags(struct interface *ifp, uint64_t flags) { - int ret; - struct ifreq ifreq; + int ret; + struct ifreq ifreq; - memset (&ifreq, 0, sizeof(struct ifreq)); - ifreq_set_name (&ifreq, ifp); + memset(&ifreq, 0, sizeof(struct ifreq)); + ifreq_set_name(&ifreq, ifp); - ifreq.ifr_flags = ifp->flags; - ifreq.ifr_flags &= ~flags; + ifreq.ifr_flags = ifp->flags; + ifreq.ifr_flags &= ~flags; - ret = if_ioctl (SIOCSIFFLAGS, (caddr_t) &ifreq); + ret = if_ioctl(SIOCSIFFLAGS, (caddr_t)&ifreq); - if (ret < 0) - { - zlog_info ("can't unset interface flags"); - return ret; - } - return 0; + if (ret < 0) { + zlog_info("can't unset interface flags"); + return ret; + } + return 0; } #ifdef LINUX_IPV6 #ifndef _LINUX_IN6_H /* linux/include/net/ipv6.h */ -struct in6_ifreq -{ - struct in6_addr ifr6_addr; - u_int32_t ifr6_prefixlen; - int ifr6_ifindex; +struct in6_ifreq { + struct in6_addr ifr6_addr; + u_int32_t ifr6_prefixlen; + int ifr6_ifindex; }; #endif /* _LINUX_IN6_H */ /* Interface's address add/delete functions. */ -int -if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc) +int if_prefix_add_ipv6(struct interface *ifp, struct connected *ifc) { - int ret; - struct prefix_ipv6 *p; - struct in6_ifreq ifreq; + int ret; + struct prefix_ipv6 *p; + struct in6_ifreq ifreq; - p = (struct prefix_ipv6 *) ifc->address; + p = (struct prefix_ipv6 *)ifc->address; - memset (&ifreq, 0, sizeof (struct in6_ifreq)); + memset(&ifreq, 0, sizeof(struct in6_ifreq)); - memcpy (&ifreq.ifr6_addr, &p->prefix, sizeof (struct in6_addr)); - ifreq.ifr6_ifindex = ifp->ifindex; - ifreq.ifr6_prefixlen = p->prefixlen; + memcpy(&ifreq.ifr6_addr, &p->prefix, sizeof(struct in6_addr)); + ifreq.ifr6_ifindex = ifp->ifindex; + ifreq.ifr6_prefixlen = p->prefixlen; - ret = if_ioctl_ipv6 (SIOCSIFADDR, (caddr_t) &ifreq); + ret = if_ioctl_ipv6(SIOCSIFADDR, (caddr_t)&ifreq); - return ret; + return ret; } -int -if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc) +int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc) { - int ret; - struct prefix_ipv6 *p; - struct in6_ifreq ifreq; + int ret; + struct prefix_ipv6 *p; + struct in6_ifreq ifreq; - p = (struct prefix_ipv6 *) ifc->address; + p = (struct prefix_ipv6 *)ifc->address; - memset (&ifreq, 0, sizeof (struct in6_ifreq)); + memset(&ifreq, 0, sizeof(struct in6_ifreq)); - memcpy (&ifreq.ifr6_addr, &p->prefix, sizeof (struct in6_addr)); - ifreq.ifr6_ifindex = ifp->ifindex; - ifreq.ifr6_prefixlen = p->prefixlen; + memcpy(&ifreq.ifr6_addr, &p->prefix, sizeof(struct in6_addr)); + ifreq.ifr6_ifindex = ifp->ifindex; + ifreq.ifr6_prefixlen = p->prefixlen; - ret = if_ioctl_ipv6 (SIOCDIFADDR, (caddr_t) &ifreq); + ret = if_ioctl_ipv6(SIOCDIFADDR, (caddr_t)&ifreq); - return ret; + return ret; } #else /* LINUX_IPV6 */ #ifdef HAVE_STRUCT_IN6_ALIASREQ #ifndef ND6_INFINITE_LIFETIME #define ND6_INFINITE_LIFETIME 0xffffffffL #endif /* ND6_INFINITE_LIFETIME */ -int -if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc) +int if_prefix_add_ipv6(struct interface *ifp, struct connected *ifc) { - int ret; - struct in6_aliasreq addreq; - struct sockaddr_in6 addr; - struct sockaddr_in6 mask; - struct prefix_ipv6 *p; + int ret; + struct in6_aliasreq addreq; + struct sockaddr_in6 addr; + struct sockaddr_in6 mask; + struct prefix_ipv6 *p; - p = (struct prefix_ipv6 * ) ifc->address; + p = (struct prefix_ipv6 *)ifc->address; - memset (&addreq, 0, sizeof addreq); - strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); + memset(&addreq, 0, sizeof addreq); + strncpy((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); - memset (&addr, 0, sizeof (struct sockaddr_in6)); - addr.sin6_addr = p->prefix; - addr.sin6_family = p->family; + memset(&addr, 0, sizeof(struct sockaddr_in6)); + addr.sin6_addr = p->prefix; + addr.sin6_family = p->family; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - addr.sin6_len = sizeof (struct sockaddr_in6); + addr.sin6_len = sizeof(struct sockaddr_in6); #endif - memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in6)); + memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in6)); - memset (&mask, 0, sizeof (struct sockaddr_in6)); - masklen2ip6 (p->prefixlen, &mask.sin6_addr); - mask.sin6_family = p->family; + memset(&mask, 0, sizeof(struct sockaddr_in6)); + masklen2ip6(p->prefixlen, &mask.sin6_addr); + mask.sin6_family = p->family; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - mask.sin6_len = sizeof (struct sockaddr_in6); + mask.sin6_len = sizeof(struct sockaddr_in6); #endif - memcpy (&addreq.ifra_prefixmask, &mask, sizeof (struct sockaddr_in6)); - - addreq.ifra_lifetime.ia6t_vltime = 0xffffffff; - addreq.ifra_lifetime.ia6t_pltime = 0xffffffff; - -#ifdef HAVE_STRUCT_IF6_ALIASREQ_IFRA_LIFETIME - addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; - addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; + memcpy(&addreq.ifra_prefixmask, &mask, sizeof(struct sockaddr_in6)); + + addreq.ifra_lifetime.ia6t_vltime = 0xffffffff; + addreq.ifra_lifetime.ia6t_pltime = 0xffffffff; + +#ifdef HAVE_STRUCT_IF6_ALIASREQ_IFRA_LIFETIME + addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; + addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; #endif - ret = if_ioctl_ipv6 (SIOCAIFADDR_IN6, (caddr_t) &addreq); - if (ret < 0) - return ret; - return 0; + ret = if_ioctl_ipv6(SIOCAIFADDR_IN6, (caddr_t)&addreq); + if (ret < 0) + return ret; + return 0; } -int -if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc) +int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc) { - int ret; - struct in6_aliasreq addreq; - struct sockaddr_in6 addr; - struct sockaddr_in6 mask; - struct prefix_ipv6 *p; + int ret; + struct in6_aliasreq addreq; + struct sockaddr_in6 addr; + struct sockaddr_in6 mask; + struct prefix_ipv6 *p; - p = (struct prefix_ipv6 *) ifc->address; + p = (struct prefix_ipv6 *)ifc->address; - memset (&addreq, 0, sizeof addreq); - strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); + memset(&addreq, 0, sizeof addreq); + strncpy((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); - memset (&addr, 0, sizeof (struct sockaddr_in6)); - addr.sin6_addr = p->prefix; - addr.sin6_family = p->family; + memset(&addr, 0, sizeof(struct sockaddr_in6)); + addr.sin6_addr = p->prefix; + addr.sin6_family = p->family; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - addr.sin6_len = sizeof (struct sockaddr_in6); + addr.sin6_len = sizeof(struct sockaddr_in6); #endif - memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in6)); + memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in6)); - memset (&mask, 0, sizeof (struct sockaddr_in6)); - masklen2ip6 (p->prefixlen, &mask.sin6_addr); - mask.sin6_family = p->family; + memset(&mask, 0, sizeof(struct sockaddr_in6)); + masklen2ip6(p->prefixlen, &mask.sin6_addr); + mask.sin6_family = p->family; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - mask.sin6_len = sizeof (struct sockaddr_in6); + mask.sin6_len = sizeof(struct sockaddr_in6); #endif - memcpy (&addreq.ifra_prefixmask, &mask, sizeof (struct sockaddr_in6)); + memcpy(&addreq.ifra_prefixmask, &mask, sizeof(struct sockaddr_in6)); #ifdef HAVE_STRUCT_IF6_ALIASREQ_IFRA_LIFETIME - addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; - addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; + addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; + addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; #endif - ret = if_ioctl_ipv6 (SIOCDIFADDR_IN6, (caddr_t) &addreq); - if (ret < 0) - return ret; - return 0; + ret = if_ioctl_ipv6(SIOCDIFADDR_IN6, (caddr_t)&addreq); + if (ret < 0) + return ret; + return 0; } #else -int -if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc) +int if_prefix_add_ipv6(struct interface *ifp, struct connected *ifc) { - return 0; + return 0; } -int -if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc) +int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc) { - return 0; + return 0; } #endif /* HAVE_STRUCT_IN6_ALIASREQ */ diff --git a/zebra/ioctl.h b/zebra/ioctl.h index b11a90f19..02f8e6b88 100644 --- a/zebra/ioctl.h +++ b/zebra/ioctl.h @@ -23,30 +23,30 @@ #define _ZEBRA_IOCTL_H /* Prototypes. */ -extern void ifreq_set_name (struct ifreq *, struct interface *); -extern int if_ioctl (u_long, caddr_t); +extern void ifreq_set_name(struct ifreq *, struct interface *); +extern int if_ioctl(u_long, caddr_t); -extern int if_set_flags (struct interface *, uint64_t); -extern int if_unset_flags (struct interface *, uint64_t); -extern void if_get_flags (struct interface *); +extern int if_set_flags(struct interface *, uint64_t); +extern int if_unset_flags(struct interface *, uint64_t); +extern void if_get_flags(struct interface *); -extern int if_set_prefix (struct interface *, struct connected *); -extern int if_unset_prefix (struct interface *, struct connected *); +extern int if_set_prefix(struct interface *, struct connected *); +extern int if_unset_prefix(struct interface *, struct connected *); -extern void if_get_metric (struct interface *); -extern void if_get_mtu (struct interface *); +extern void if_get_metric(struct interface *); +extern void if_get_mtu(struct interface *); -extern int if_prefix_add_ipv6 (struct interface *, struct connected *); -extern int if_prefix_delete_ipv6 (struct interface *, struct connected *); +extern int if_prefix_add_ipv6(struct interface *, struct connected *); +extern int if_prefix_delete_ipv6(struct interface *, struct connected *); #ifdef SOLARIS_IPV6 extern int if_ioctl_ipv6(u_long, caddr_t); -extern struct connected *if_lookup_linklocal( struct interface *); +extern struct connected *if_lookup_linklocal(struct interface *); -#define AF_IOCTL(af, request, buffer) \ - ((af) == AF_INET? if_ioctl(request, buffer) : \ - if_ioctl_ipv6(request, buffer)) -#else /* SOLARIS_IPV6 */ +#define AF_IOCTL(af, request, buffer) \ + ((af) == AF_INET ? if_ioctl(request, buffer) \ + : if_ioctl_ipv6(request, buffer)) +#else /* SOLARIS_IPV6 */ #define AF_IOCTL(af, request, buffer) if_ioctl(request, buffer) diff --git a/zebra/ioctl_solaris.c b/zebra/ioctl_solaris.c index 4bdbdaa58..df1554ae6 100644 --- a/zebra/ioctl_solaris.c +++ b/zebra/ioctl_solaris.c @@ -37,245 +37,231 @@ extern struct zebra_privs_t zserv_privs; /* clear and set interface name string */ -void -lifreq_set_name (struct lifreq *lifreq, const char *ifname) +void lifreq_set_name(struct lifreq *lifreq, const char *ifname) { - strncpy (lifreq->lifr_name, ifname, IFNAMSIZ); + strncpy(lifreq->lifr_name, ifname, IFNAMSIZ); } /* call ioctl system call */ -int -if_ioctl (u_long request, caddr_t buffer) +int if_ioctl(u_long request, caddr_t buffer) { - int sock; - int ret; - int err; - - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - - sock = socket (AF_INET, SOCK_DGRAM, 0); - if (sock < 0) - { - int save_errno = errno; - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - zlog_err("Cannot create UDP socket: %s", safe_strerror(save_errno)); - exit (1); - } - - if ((ret = ioctl (sock, request, buffer)) < 0) - err = errno; - - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - - close (sock); - - if (ret < 0) - { - errno = err; - return ret; - } - return 0; + int sock; + int ret; + int err; + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + int save_errno = errno; + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + zlog_err("Cannot create UDP socket: %s", + safe_strerror(save_errno)); + exit(1); + } + + if ((ret = ioctl(sock, request, buffer)) < 0) + err = errno; + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + close(sock); + + if (ret < 0) { + errno = err; + return ret; + } + return 0; } -int -if_ioctl_ipv6 (u_long request, caddr_t buffer) +int if_ioctl_ipv6(u_long request, caddr_t buffer) { - int sock; - int ret; - int err; - - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - - sock = socket (AF_INET6, SOCK_DGRAM, 0); - if (sock < 0) - { - int save_errno = errno; - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - zlog_err("Cannot create IPv6 datagram socket: %s", - safe_strerror(save_errno)); - exit (1); - } - - if ((ret = ioctl (sock, request, buffer)) < 0) - err = errno; - - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - - close (sock); - - if (ret < 0) - { - errno = err; - return ret; - } - - return 0; + int sock; + int ret; + int err; + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + + sock = socket(AF_INET6, SOCK_DGRAM, 0); + if (sock < 0) { + int save_errno = errno; + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + zlog_err("Cannot create IPv6 datagram socket: %s", + safe_strerror(save_errno)); + exit(1); + } + + if ((ret = ioctl(sock, request, buffer)) < 0) + err = errno; + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + close(sock); + + if (ret < 0) { + errno = err; + return ret; + } + + return 0; } /* * get interface metric * -- if value is not avaliable set -1 */ -void -if_get_metric (struct interface *ifp) +void if_get_metric(struct interface *ifp) { - struct lifreq lifreq; - int ret; + struct lifreq lifreq; + int ret; - lifreq_set_name (&lifreq, ifp->name); + lifreq_set_name(&lifreq, ifp->name); - if (ifp->flags & IFF_IPV4) - ret = AF_IOCTL (AF_INET, SIOCGLIFMETRIC, (caddr_t) & lifreq); + if (ifp->flags & IFF_IPV4) + ret = AF_IOCTL(AF_INET, SIOCGLIFMETRIC, (caddr_t)&lifreq); #ifdef SOLARIS_IPV6 - else if (ifp->flags & IFF_IPV6) - ret = AF_IOCTL (AF_INET6, SIOCGLIFMETRIC, (caddr_t) & lifreq); + else if (ifp->flags & IFF_IPV6) + ret = AF_IOCTL(AF_INET6, SIOCGLIFMETRIC, (caddr_t)&lifreq); #endif /* SOLARIS_IPV6 */ - else - ret = -1; - - if (ret < 0) - return; + else + ret = -1; - ifp->metric = lifreq.lifr_metric; + if (ret < 0) + return; - if (ifp->metric == 0) - ifp->metric = 1; + ifp->metric = lifreq.lifr_metric; + + if (ifp->metric == 0) + ifp->metric = 1; } /* get interface MTU */ -void -if_get_mtu (struct interface *ifp) +void if_get_mtu(struct interface *ifp) { - struct lifreq lifreq; - int ret; - u_char changed = 0; - - if (ifp->flags & IFF_IPV4) - { - lifreq_set_name (&lifreq, ifp->name); - ret = AF_IOCTL (AF_INET, SIOCGLIFMTU, (caddr_t) & lifreq); - if (ret < 0) - { - zlog_info ("Can't lookup mtu on %s by ioctl(SIOCGLIFMTU)", - ifp->name); - ifp->mtu = -1; - } - else - { - ifp->mtu = lifreq.lifr_metric; - changed = 1; - } - } - - if (ifp->flags & IFF_IPV6) - { - memset(&lifreq, 0, sizeof(lifreq)); - lifreq_set_name (&lifreq, ifp->name); - - ret = AF_IOCTL (AF_INET6, SIOCGLIFMTU, (caddr_t) & lifreq); - if (ret < 0) - { - zlog_info ("Can't lookup mtu6 on %s by ioctl(SIOCGIFMTU)", ifp->name); - ifp->mtu6 = -1; - } - else - { - ifp->mtu6 = lifreq.lifr_metric; - changed = 1; - } - } - - if (changed) - zebra_interface_up_update(ifp); + struct lifreq lifreq; + int ret; + u_char changed = 0; + + if (ifp->flags & IFF_IPV4) { + lifreq_set_name(&lifreq, ifp->name); + ret = AF_IOCTL(AF_INET, SIOCGLIFMTU, (caddr_t)&lifreq); + if (ret < 0) { + zlog_info( + "Can't lookup mtu on %s by ioctl(SIOCGLIFMTU)", + ifp->name); + ifp->mtu = -1; + } else { + ifp->mtu = lifreq.lifr_metric; + changed = 1; + } + } + + if (ifp->flags & IFF_IPV6) { + memset(&lifreq, 0, sizeof(lifreq)); + lifreq_set_name(&lifreq, ifp->name); + + ret = AF_IOCTL(AF_INET6, SIOCGLIFMTU, (caddr_t)&lifreq); + if (ret < 0) { + zlog_info( + "Can't lookup mtu6 on %s by ioctl(SIOCGIFMTU)", + ifp->name); + ifp->mtu6 = -1; + } else { + ifp->mtu6 = lifreq.lifr_metric; + changed = 1; + } + } + + if (changed) + zebra_interface_up_update(ifp); } /* Set up interface's address, netmask (and broadcast? ). Solaris uses ifname:number semantics to set IP address aliases. */ -int -if_set_prefix (struct interface *ifp, struct connected *ifc) +int if_set_prefix(struct interface *ifp, struct connected *ifc) { - int ret; - struct ifreq ifreq; - struct sockaddr_in addr; - struct sockaddr_in broad; - struct sockaddr_in mask; - struct prefix_ipv4 ifaddr; - struct prefix_ipv4 *p; + int ret; + struct ifreq ifreq; + struct sockaddr_in addr; + struct sockaddr_in broad; + struct sockaddr_in mask; + struct prefix_ipv4 ifaddr; + struct prefix_ipv4 *p; - p = (struct prefix_ipv4 *) ifc->address; + p = (struct prefix_ipv4 *)ifc->address; - ifaddr = *p; + ifaddr = *p; - strncpy (ifreq.ifr_name, ifp->name, IFNAMSIZ); + strncpy(ifreq.ifr_name, ifp->name, IFNAMSIZ); - addr.sin_addr = p->prefix; - addr.sin_family = p->family; - memcpy (&ifreq.ifr_addr, &addr, sizeof (struct sockaddr_in)); + addr.sin_addr = p->prefix; + addr.sin_family = p->family; + memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in)); - ret = if_ioctl (SIOCSIFADDR, (caddr_t) & ifreq); + ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq); - if (ret < 0) - return ret; + if (ret < 0) + return ret; - /* We need mask for make broadcast addr. */ - masklen2ip (p->prefixlen, &mask.sin_addr); + /* We need mask for make broadcast addr. */ + masklen2ip(p->prefixlen, &mask.sin_addr); - if (if_is_broadcast (ifp)) - { - apply_mask_ipv4 (&ifaddr); - addr.sin_addr = ifaddr.prefix; + if (if_is_broadcast(ifp)) { + apply_mask_ipv4(&ifaddr); + addr.sin_addr = ifaddr.prefix; - broad.sin_addr.s_addr = (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr); - broad.sin_family = p->family; + broad.sin_addr.s_addr = + (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr); + broad.sin_family = p->family; - memcpy (&ifreq.ifr_broadaddr, &broad, sizeof (struct sockaddr_in)); - ret = if_ioctl (SIOCSIFBRDADDR, (caddr_t) & ifreq); - if (ret < 0) - return ret; - } + memcpy(&ifreq.ifr_broadaddr, &broad, + sizeof(struct sockaddr_in)); + ret = if_ioctl(SIOCSIFBRDADDR, (caddr_t)&ifreq); + if (ret < 0) + return ret; + } - mask.sin_family = p->family; + mask.sin_family = p->family; #ifdef SUNOS_5 - memcpy (&mask, &ifreq.ifr_addr, sizeof (mask)); + memcpy(&mask, &ifreq.ifr_addr, sizeof(mask)); #else - memcpy (&ifreq.ifr_netmask, &mask, sizeof (struct sockaddr_in)); + memcpy(&ifreq.ifr_netmask, &mask, sizeof(struct sockaddr_in)); #endif /* SUNOS_5 */ - ret = if_ioctl (SIOCSIFNETMASK, (caddr_t) & ifreq); + ret = if_ioctl(SIOCSIFNETMASK, (caddr_t)&ifreq); - return ((ret < 0) ? ret : 0); + return ((ret < 0) ? ret : 0); } /* Set up interface's address, netmask (and broadcast). Solaris uses ifname:number semantics to set IP address aliases. */ -int -if_unset_prefix (struct interface *ifp, struct connected *ifc) +int if_unset_prefix(struct interface *ifp, struct connected *ifc) { - int ret; - struct ifreq ifreq; - struct sockaddr_in addr; - struct prefix_ipv4 *p; + int ret; + struct ifreq ifreq; + struct sockaddr_in addr; + struct prefix_ipv4 *p; + + p = (struct prefix_ipv4 *)ifc->address; - p = (struct prefix_ipv4 *) ifc->address; + strncpy(ifreq.ifr_name, ifp->name, IFNAMSIZ); - strncpy (ifreq.ifr_name, ifp->name, IFNAMSIZ); + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = p->family; + memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in)); - memset (&addr, 0, sizeof (struct sockaddr_in)); - addr.sin_family = p->family; - memcpy (&ifreq.ifr_addr, &addr, sizeof (struct sockaddr_in)); + ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq); - ret = if_ioctl (SIOCSIFADDR, (caddr_t) & ifreq); - - if (ret < 0) - return ret; + if (ret < 0) + return ret; - return 0; + return 0; } /* Get just the flags for the given name. @@ -283,144 +269,132 @@ if_unset_prefix (struct interface *ifp, struct connected *ifc) * as the bootup interface-list code, which has to peek at per-address * flags in order to figure out which ones should be ignored.. */ -int -if_get_flags_direct (const char *ifname, uint64_t *flags, unsigned int af) +int if_get_flags_direct(const char *ifname, uint64_t *flags, unsigned int af) { - struct lifreq lifreq; - int ret; - - lifreq_set_name (&lifreq, ifname); - - ret = AF_IOCTL (af, SIOCGLIFFLAGS, (caddr_t) &lifreq); - - if (ret) - zlog_debug ("%s: ifname %s, error %s (%d)", - __func__, ifname, safe_strerror (errno), errno); - - *flags = lifreq.lifr_flags; - - return ret; + struct lifreq lifreq; + int ret; + + lifreq_set_name(&lifreq, ifname); + + ret = AF_IOCTL(af, SIOCGLIFFLAGS, (caddr_t)&lifreq); + + if (ret) + zlog_debug("%s: ifname %s, error %s (%d)", __func__, ifname, + safe_strerror(errno), errno); + + *flags = lifreq.lifr_flags; + + return ret; } /* get interface flags */ -void -if_get_flags (struct interface *ifp) +void if_get_flags(struct interface *ifp) { - int ret4 = 0, ret6 = 0; - uint64_t newflags = 0; - uint64_t tmpflags; - - if (ifp->flags & IFF_IPV4) - { - ret4 = if_get_flags_direct (ifp->name, &tmpflags, AF_INET); - - if (!ret4) - newflags |= tmpflags; - else if (errno == ENXIO) - { - /* it's gone */ - UNSET_FLAG (ifp->flags, IFF_UP); - if_flags_update (ifp, ifp->flags); - } - } - - if (ifp->flags & IFF_IPV6) - { - ret6 = if_get_flags_direct (ifp->name, &tmpflags, AF_INET6); - - if (!ret6) - newflags |= tmpflags; - else if (errno == ENXIO) - { - /* it's gone */ - UNSET_FLAG (ifp->flags, IFF_UP); - if_flags_update (ifp, ifp->flags); - } - } - - /* only update flags if one of above succeeded */ - if ( !(ret4 && ret6) ) - if_flags_update (ifp, newflags); + int ret4 = 0, ret6 = 0; + uint64_t newflags = 0; + uint64_t tmpflags; + + if (ifp->flags & IFF_IPV4) { + ret4 = if_get_flags_direct(ifp->name, &tmpflags, AF_INET); + + if (!ret4) + newflags |= tmpflags; + else if (errno == ENXIO) { + /* it's gone */ + UNSET_FLAG(ifp->flags, IFF_UP); + if_flags_update(ifp, ifp->flags); + } + } + + if (ifp->flags & IFF_IPV6) { + ret6 = if_get_flags_direct(ifp->name, &tmpflags, AF_INET6); + + if (!ret6) + newflags |= tmpflags; + else if (errno == ENXIO) { + /* it's gone */ + UNSET_FLAG(ifp->flags, IFF_UP); + if_flags_update(ifp, ifp->flags); + } + } + + /* only update flags if one of above succeeded */ + if (!(ret4 && ret6)) + if_flags_update(ifp, newflags); } /* Set interface flags */ -int -if_set_flags (struct interface *ifp, uint64_t flags) +int if_set_flags(struct interface *ifp, uint64_t flags) { - int ret; - struct lifreq lifreq; - - lifreq_set_name (&lifreq, ifp->name); - - lifreq.lifr_flags = ifp->flags; - lifreq.lifr_flags |= flags; - - if (ifp->flags & IFF_IPV4) - ret = AF_IOCTL (AF_INET, SIOCSLIFFLAGS, (caddr_t) & lifreq); - else if (ifp->flags & IFF_IPV6) - ret = AF_IOCTL (AF_INET6, SIOCSLIFFLAGS, (caddr_t) & lifreq); - else - ret = -1; - - if (ret < 0) - zlog_info ("can't set interface flags on %s: %s", ifp->name, - safe_strerror (errno)); - else - ret = 0; - - return ret; + int ret; + struct lifreq lifreq; + + lifreq_set_name(&lifreq, ifp->name); + + lifreq.lifr_flags = ifp->flags; + lifreq.lifr_flags |= flags; + + if (ifp->flags & IFF_IPV4) + ret = AF_IOCTL(AF_INET, SIOCSLIFFLAGS, (caddr_t)&lifreq); + else if (ifp->flags & IFF_IPV6) + ret = AF_IOCTL(AF_INET6, SIOCSLIFFLAGS, (caddr_t)&lifreq); + else + ret = -1; + + if (ret < 0) + zlog_info("can't set interface flags on %s: %s", ifp->name, + safe_strerror(errno)); + else + ret = 0; + + return ret; } /* Unset interface's flag. */ -int -if_unset_flags (struct interface *ifp, uint64_t flags) +int if_unset_flags(struct interface *ifp, uint64_t flags) { - int ret; - struct lifreq lifreq; - - lifreq_set_name (&lifreq, ifp->name); - - lifreq.lifr_flags = ifp->flags; - lifreq.lifr_flags &= ~flags; - - if (ifp->flags & IFF_IPV4) - ret = AF_IOCTL (AF_INET, SIOCSLIFFLAGS, (caddr_t) & lifreq); - else if (ifp->flags & IFF_IPV6) - ret = AF_IOCTL (AF_INET6, SIOCSLIFFLAGS, (caddr_t) & lifreq); - else - ret = -1; - - if (ret < 0) - zlog_info ("can't unset interface flags"); - else - ret = 0; - - return ret; + int ret; + struct lifreq lifreq; + + lifreq_set_name(&lifreq, ifp->name); + + lifreq.lifr_flags = ifp->flags; + lifreq.lifr_flags &= ~flags; + + if (ifp->flags & IFF_IPV4) + ret = AF_IOCTL(AF_INET, SIOCSLIFFLAGS, (caddr_t)&lifreq); + else if (ifp->flags & IFF_IPV6) + ret = AF_IOCTL(AF_INET6, SIOCSLIFFLAGS, (caddr_t)&lifreq); + else + ret = -1; + + if (ret < 0) + zlog_info("can't unset interface flags"); + else + ret = 0; + + return ret; } /* Interface's address add/delete functions. */ -int -if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc) +int if_prefix_add_ipv6(struct interface *ifp, struct connected *ifc) { - char addrbuf[PREFIX_STRLEN]; - - zlog_warn ("Can't set %s on interface %s", - prefix2str(ifc->address, addrbuf, sizeof(addrbuf)), - ifp->name); + char addrbuf[PREFIX_STRLEN]; - return 0; + zlog_warn("Can't set %s on interface %s", + prefix2str(ifc->address, addrbuf, sizeof(addrbuf)), + ifp->name); + return 0; } -int -if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc) +int if_prefix_delete_ipv6(struct interface *ifp, struct connected *ifc) { - char addrbuf[PREFIX_STRLEN]; - - zlog_warn ("Can't delete %s on interface %s", - prefix2str(ifc->address, addrbuf, sizeof(addrbuf)), - ifp->name); + char addrbuf[PREFIX_STRLEN]; - return 0; + zlog_warn("Can't delete %s on interface %s", + prefix2str(ifc->address, addrbuf, sizeof(addrbuf)), + ifp->name); + return 0; } diff --git a/zebra/ioctl_solaris.h b/zebra/ioctl_solaris.h index dbf93bdca..3507e563c 100644 --- a/zebra/ioctl_solaris.h +++ b/zebra/ioctl_solaris.h @@ -22,7 +22,7 @@ #ifndef _ZEBRA_IF_IOCTL_SOLARIS_H #define _ZEBRA_IF_IOCTL_SOLARIS_H -void lifreq_set_name (struct lifreq *, const char *); -int if_get_flags_direct (const char *, uint64_t *, unsigned int af); +void lifreq_set_name(struct lifreq *, const char *); +int if_get_flags_direct(const char *, uint64_t *, unsigned int af); #endif /* _ZEBRA_IF_IOCTL_SOLARIS_H */ diff --git a/zebra/ipforward.h b/zebra/ipforward.h index 5401ed08a..fe9f2db91 100644 --- a/zebra/ipforward.h +++ b/zebra/ipforward.h @@ -21,12 +21,12 @@ #ifndef _ZEBRA_IPFORWARD_H #define _ZEBRA_IPFORWARD_H -extern int ipforward (void); -extern int ipforward_on (void); -extern int ipforward_off (void); +extern int ipforward(void); +extern int ipforward_on(void); +extern int ipforward_off(void); -extern int ipforward_ipv6 (void); -extern int ipforward_ipv6_on (void); -extern int ipforward_ipv6_off (void); +extern int ipforward_ipv6(void); +extern int ipforward_ipv6_on(void); +extern int ipforward_ipv6_off(void); #endif /* _ZEBRA_IPFORWARD_H */ diff --git a/zebra/ipforward_proc.c b/zebra/ipforward_proc.c index 200c50c0a..c3dcdda55 100644 --- a/zebra/ipforward_proc.c +++ b/zebra/ipforward_proc.c @@ -30,169 +30,166 @@ extern struct zebra_privs_t zserv_privs; char proc_net_snmp[] = "/proc/net/snmp"; -static void -dropline (FILE *fp) +static void dropline(FILE *fp) { - int c; + int c; - while ((c = getc (fp)) != '\n') - ; + while ((c = getc(fp)) != '\n') + ; } -int -ipforward (void) +int ipforward(void) { - FILE *fp; - int ipforwarding = 0; - char buf[10]; - - fp = fopen (proc_net_snmp, "r"); - - if (fp == NULL) - return -1; - - /* We don't care about the first line. */ - dropline (fp); - - /* Get ip_statistics.IpForwarding : - 1 => ip forwarding enabled - 2 => ip forwarding off. */ - if (fgets (buf, 6, fp)) - sscanf (buf, "Ip: %d", &ipforwarding); - - fclose(fp); - - if (ipforwarding == 1) - return 1; - - return 0; + FILE *fp; + int ipforwarding = 0; + char buf[10]; + + fp = fopen(proc_net_snmp, "r"); + + if (fp == NULL) + return -1; + + /* We don't care about the first line. */ + dropline(fp); + + /* Get ip_statistics.IpForwarding : + 1 => ip forwarding enabled + 2 => ip forwarding off. */ + if (fgets(buf, 6, fp)) + sscanf(buf, "Ip: %d", &ipforwarding); + + fclose(fp); + + if (ipforwarding == 1) + return 1; + + return 0; } /* char proc_ipv4_forwarding[] = "/proc/sys/net/ipv4/conf/all/forwarding"; */ char proc_ipv4_forwarding[] = "/proc/sys/net/ipv4/ip_forward"; -int -ipforward_on (void) +int ipforward_on(void) { - FILE *fp; - - if ( zserv_privs.change(ZPRIVS_RAISE) ) - zlog_err ("Can't raise privileges, %s", safe_strerror (errno) ); + FILE *fp; + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges, %s", safe_strerror(errno)); - fp = fopen (proc_ipv4_forwarding, "w"); + fp = fopen(proc_ipv4_forwarding, "w"); - if (fp == NULL) { - if ( zserv_privs.change(ZPRIVS_LOWER) ) - zlog_err ("Can't lower privileges, %s", safe_strerror (errno)); - return -1; - } + if (fp == NULL) { + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges, %s", + safe_strerror(errno)); + return -1; + } - fprintf (fp, "1\n"); + fprintf(fp, "1\n"); - fclose (fp); + fclose(fp); - if ( zserv_privs.change(ZPRIVS_LOWER) ) - zlog_err ("Can't lower privileges, %s", safe_strerror (errno)); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges, %s", safe_strerror(errno)); - return ipforward (); + return ipforward(); } -int -ipforward_off (void) +int ipforward_off(void) { - FILE *fp; + FILE *fp; - if ( zserv_privs.change(ZPRIVS_RAISE) ) - zlog_err ("Can't raise privileges, %s", safe_strerror (errno)); + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges, %s", safe_strerror(errno)); - fp = fopen (proc_ipv4_forwarding, "w"); + fp = fopen(proc_ipv4_forwarding, "w"); - if (fp == NULL) { - if ( zserv_privs.change(ZPRIVS_LOWER) ) - zlog_err ("Can't lower privileges, %s", safe_strerror (errno)); - return -1; - } + if (fp == NULL) { + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges, %s", + safe_strerror(errno)); + return -1; + } - fprintf (fp, "0\n"); + fprintf(fp, "0\n"); - fclose (fp); + fclose(fp); - if ( zserv_privs.change(ZPRIVS_LOWER) ) - zlog_err ("Can't lower privileges, %s", safe_strerror (errno)); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges, %s", safe_strerror(errno)); - return ipforward (); + return ipforward(); } char proc_ipv6_forwarding[] = "/proc/sys/net/ipv6/conf/all/forwarding"; -int -ipforward_ipv6 (void) +int ipforward_ipv6(void) { - FILE *fp; - char buf[5]; - int ipforwarding = 0; + FILE *fp; + char buf[5]; + int ipforwarding = 0; - fp = fopen (proc_ipv6_forwarding, "r"); + fp = fopen(proc_ipv6_forwarding, "r"); - if (fp == NULL) - return -1; + if (fp == NULL) + return -1; - if (fgets (buf, 2, fp)) - sscanf (buf, "%d", &ipforwarding); + if (fgets(buf, 2, fp)) + sscanf(buf, "%d", &ipforwarding); - fclose (fp); - return ipforwarding; + fclose(fp); + return ipforwarding; } -int -ipforward_ipv6_on (void) +int ipforward_ipv6_on(void) { - FILE *fp; + FILE *fp; - if ( zserv_privs.change(ZPRIVS_RAISE) ) - zlog_err ("Can't raise privileges, %s", safe_strerror (errno)); + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges, %s", safe_strerror(errno)); - fp = fopen (proc_ipv6_forwarding, "w"); + fp = fopen(proc_ipv6_forwarding, "w"); - if (fp == NULL) { - if ( zserv_privs.change(ZPRIVS_LOWER) ) - zlog_err ("Can't lower privileges, %s", safe_strerror (errno)); - return -1; - } + if (fp == NULL) { + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges, %s", + safe_strerror(errno)); + return -1; + } - fprintf (fp, "1\n"); + fprintf(fp, "1\n"); - fclose (fp); + fclose(fp); - if ( zserv_privs.change(ZPRIVS_LOWER) ) - zlog_err ("Can't lower privileges, %s", safe_strerror (errno)); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges, %s", safe_strerror(errno)); - return ipforward_ipv6 (); + return ipforward_ipv6(); } -int -ipforward_ipv6_off (void) +int ipforward_ipv6_off(void) { - FILE *fp; + FILE *fp; - if ( zserv_privs.change(ZPRIVS_RAISE) ) - zlog_err ("Can't raise privileges, %s", safe_strerror (errno)); + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges, %s", safe_strerror(errno)); - fp = fopen (proc_ipv6_forwarding, "w"); + fp = fopen(proc_ipv6_forwarding, "w"); - if (fp == NULL) { - if ( zserv_privs.change(ZPRIVS_LOWER) ) - zlog_err ("Can't lower privileges, %s", safe_strerror (errno)); - return -1; - } + if (fp == NULL) { + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges, %s", + safe_strerror(errno)); + return -1; + } - fprintf (fp, "0\n"); + fprintf(fp, "0\n"); - fclose (fp); + fclose(fp); - if ( zserv_privs.change(ZPRIVS_LOWER) ) - zlog_err ("Can't lower privileges, %s", safe_strerror (errno)); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges, %s", safe_strerror(errno)); - return ipforward_ipv6 (); + return ipforward_ipv6(); } diff --git a/zebra/ipforward_solaris.c b/zebra/ipforward_solaris.c index 09f145e81..0d6b7dac0 100644 --- a/zebra/ipforward_solaris.c +++ b/zebra/ipforward_solaris.c @@ -46,117 +46,110 @@ extern struct zebra_privs_t zserv_privs; ** name of the parameter being referenced. */ -static int -solaris_nd(const int cmd, const char* parameter, const int value) +static int solaris_nd(const int cmd, const char *parameter, const int value) { #define ND_BUFFER_SIZE 1024 - int fd; - char nd_buf[ND_BUFFER_SIZE]; - struct strioctl strioctl; - const char* device = IP_DEV_NAME; - int retval; - memset(nd_buf, '\0', ND_BUFFER_SIZE); - /* - ** ND_SET takes a NULL delimited list of strings further terminated - ** buy a NULL. ND_GET returns a list in a similar layout, although - ** here we only use the first result. - */ - if (cmd == ND_SET) - snprintf(nd_buf, ND_BUFFER_SIZE, "%s%c%d%c", parameter, '\0', value,'\0'); - else if (cmd == ND_GET) - snprintf(nd_buf, ND_BUFFER_SIZE, "%s", parameter); - else { - zlog_err("internal error - inappropriate command given to " - "solaris_nd()%s:%d", __FILE__, __LINE__); - return -1; - } + int fd; + char nd_buf[ND_BUFFER_SIZE]; + struct strioctl strioctl; + const char *device = IP_DEV_NAME; + int retval; + memset(nd_buf, '\0', ND_BUFFER_SIZE); + /* + ** ND_SET takes a NULL delimited list of strings further terminated + ** buy a NULL. ND_GET returns a list in a similar layout, although + ** here we only use the first result. + */ + if (cmd == ND_SET) + snprintf(nd_buf, ND_BUFFER_SIZE, "%s%c%d%c", parameter, '\0', + value, '\0'); + else if (cmd == ND_GET) + snprintf(nd_buf, ND_BUFFER_SIZE, "%s", parameter); + else { + zlog_err( + "internal error - inappropriate command given to " + "solaris_nd()%s:%d", + __FILE__, __LINE__); + return -1; + } - strioctl.ic_cmd = cmd; - strioctl.ic_timout = 0; - strioctl.ic_len = ND_BUFFER_SIZE; - strioctl.ic_dp = nd_buf; - - if ( zserv_privs.change (ZPRIVS_RAISE) ) - zlog_err ("solaris_nd: Can't raise privileges"); - if ((fd = open (device, O_RDWR)) < 0) - { - zlog_warn("failed to open device %s - %s", device, safe_strerror(errno)); - if ( zserv_privs.change (ZPRIVS_LOWER) ) - zlog_err ("solaris_nd: Can't lower privileges"); - return -1; - } - if (ioctl (fd, I_STR, &strioctl) < 0) - { - int save_errno = errno; - if ( zserv_privs.change (ZPRIVS_LOWER) ) - zlog_err ("solaris_nd: Can't lower privileges"); - close (fd); - zlog_warn("ioctl I_STR failed on device %s - %s", - device, safe_strerror(save_errno)); - return -1; - } - close(fd); - if ( zserv_privs.change (ZPRIVS_LOWER) ) - zlog_err ("solaris_nd: Can't lower privileges"); - - if (cmd == ND_GET) - { - errno = 0; - retval = atoi(nd_buf); - if (errno) - { - zlog_warn("failed to convert returned value to integer - %s", - safe_strerror(errno)); - retval = -1; - } - } - else - { - retval = 0; - } - return retval; + strioctl.ic_cmd = cmd; + strioctl.ic_timout = 0; + strioctl.ic_len = ND_BUFFER_SIZE; + strioctl.ic_dp = nd_buf; + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("solaris_nd: Can't raise privileges"); + if ((fd = open(device, O_RDWR)) < 0) { + zlog_warn("failed to open device %s - %s", device, + safe_strerror(errno)); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("solaris_nd: Can't lower privileges"); + return -1; + } + if (ioctl(fd, I_STR, &strioctl) < 0) { + int save_errno = errno; + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("solaris_nd: Can't lower privileges"); + close(fd); + zlog_warn("ioctl I_STR failed on device %s - %s", device, + safe_strerror(save_errno)); + return -1; + } + close(fd); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("solaris_nd: Can't lower privileges"); + + if (cmd == ND_GET) { + errno = 0; + retval = atoi(nd_buf); + if (errno) { + zlog_warn( + "failed to convert returned value to integer - %s", + safe_strerror(errno)); + retval = -1; + } + } else { + retval = 0; + } + return retval; } -static int -solaris_nd_set(const char* parameter, const int value) { - return solaris_nd(ND_SET, parameter, value); +static int solaris_nd_set(const char *parameter, const int value) +{ + return solaris_nd(ND_SET, parameter, value); } -static int -solaris_nd_get(const char* parameter) { - return solaris_nd(ND_GET, parameter, 0); +static int solaris_nd_get(const char *parameter) +{ + return solaris_nd(ND_GET, parameter, 0); } -int -ipforward(void) +int ipforward(void) { - return solaris_nd_get("ip_forwarding"); + return solaris_nd_get("ip_forwarding"); } -int -ipforward_on (void) +int ipforward_on(void) { - (void) solaris_nd_set("ip_forwarding", 1); - return ipforward(); + (void)solaris_nd_set("ip_forwarding", 1); + return ipforward(); } -int -ipforward_off (void) +int ipforward_off(void) { - (void) solaris_nd_set("ip_forwarding", 0); - return ipforward(); + (void)solaris_nd_set("ip_forwarding", 0); + return ipforward(); } int ipforward_ipv6(void) { - return solaris_nd_get("ip6_forwarding"); + return solaris_nd_get("ip6_forwarding"); } -int -ipforward_ipv6_on (void) +int ipforward_ipv6_on(void) { - (void) solaris_nd_set("ip6_forwarding", 1); - return ipforward_ipv6(); + (void)solaris_nd_set("ip6_forwarding", 1); + return ipforward_ipv6(); } -int -ipforward_ipv6_off (void) +int ipforward_ipv6_off(void) { - (void) solaris_nd_set("ip6_forwarding", 0); - return ipforward_ipv6(); + (void)solaris_nd_set("ip6_forwarding", 0); + return ipforward_ipv6(); } diff --git a/zebra/ipforward_sysctl.c b/zebra/ipforward_sysctl.c index a381eb2d7..00be92bb6 100644 --- a/zebra/ipforward_sysctl.c +++ b/zebra/ipforward_sysctl.c @@ -29,144 +29,121 @@ extern struct zebra_privs_t zserv_privs; /* IPv4 forwarding control MIB. */ -int mib[MIB_SIZ] = -{ - CTL_NET, - PF_INET, - IPPROTO_IP, - IPCTL_FORWARDING -}; +int mib[MIB_SIZ] = {CTL_NET, PF_INET, IPPROTO_IP, IPCTL_FORWARDING}; -int -ipforward (void) +int ipforward(void) { - size_t len; - int ipforwarding = 0; - - len = sizeof ipforwarding; - if (sysctl (mib, MIB_SIZ, &ipforwarding, &len, 0, 0) < 0) - { - zlog_warn ("Can't get ipforwarding value"); - return -1; - } - return ipforwarding; + size_t len; + int ipforwarding = 0; + + len = sizeof ipforwarding; + if (sysctl(mib, MIB_SIZ, &ipforwarding, &len, 0, 0) < 0) { + zlog_warn("Can't get ipforwarding value"); + return -1; + } + return ipforwarding; } -int -ipforward_on (void) +int ipforward_on(void) { - size_t len; - int ipforwarding = 1; - - len = sizeof ipforwarding; - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - if (sysctl (mib, MIB_SIZ, NULL, NULL, &ipforwarding, len) < 0) - { - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - zlog_warn ("Can't set ipforwarding on"); - return -1; - } - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - return ipforwarding; + size_t len; + int ipforwarding = 1; + + len = sizeof ipforwarding; + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + if (sysctl(mib, MIB_SIZ, NULL, NULL, &ipforwarding, len) < 0) { + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + zlog_warn("Can't set ipforwarding on"); + return -1; + } + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + return ipforwarding; } -int -ipforward_off (void) +int ipforward_off(void) { - size_t len; - int ipforwarding = 0; - - len = sizeof ipforwarding; - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - if (sysctl (mib, MIB_SIZ, NULL, NULL, &ipforwarding, len) < 0) - { - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - zlog_warn ("Can't set ipforwarding on"); - return -1; - } - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - return ipforwarding; + size_t len; + int ipforwarding = 0; + + len = sizeof ipforwarding; + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + if (sysctl(mib, MIB_SIZ, NULL, NULL, &ipforwarding, len) < 0) { + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + zlog_warn("Can't set ipforwarding on"); + return -1; + } + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + return ipforwarding; } /* IPv6 forwarding control MIB. */ -int mib_ipv6[MIB_SIZ] = -{ - CTL_NET, - PF_INET6, +int mib_ipv6[MIB_SIZ] = {CTL_NET, PF_INET6, #if defined(KAME) - IPPROTO_IPV6, - IPV6CTL_FORWARDING -#else /* NOT KAME */ - IPPROTO_IP, - IP6CTL_FORWARDING + IPPROTO_IPV6, IPV6CTL_FORWARDING +#else /* NOT KAME */ + IPPROTO_IP, IP6CTL_FORWARDING #endif /* KAME */ -}; +}; -int -ipforward_ipv6 (void) +int ipforward_ipv6(void) { - size_t len; - int ip6forwarding = 0; - - len = sizeof ip6forwarding; - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - if (sysctl (mib_ipv6, MIB_SIZ, &ip6forwarding, &len, 0, 0) < 0) - { - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - zlog_warn ("can't get ip6forwarding value"); - return -1; - } - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - return ip6forwarding; + size_t len; + int ip6forwarding = 0; + + len = sizeof ip6forwarding; + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + if (sysctl(mib_ipv6, MIB_SIZ, &ip6forwarding, &len, 0, 0) < 0) { + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + zlog_warn("can't get ip6forwarding value"); + return -1; + } + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + return ip6forwarding; } -int -ipforward_ipv6_on (void) +int ipforward_ipv6_on(void) { - size_t len; - int ip6forwarding = 1; - - len = sizeof ip6forwarding; - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - if (sysctl (mib_ipv6, MIB_SIZ, NULL, NULL, &ip6forwarding, len) < 0) - { - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - zlog_warn ("can't get ip6forwarding value"); - return -1; - } - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - return ip6forwarding; + size_t len; + int ip6forwarding = 1; + + len = sizeof ip6forwarding; + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + if (sysctl(mib_ipv6, MIB_SIZ, NULL, NULL, &ip6forwarding, len) < 0) { + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + zlog_warn("can't get ip6forwarding value"); + return -1; + } + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + return ip6forwarding; } -int -ipforward_ipv6_off (void) +int ipforward_ipv6_off(void) { - size_t len; - int ip6forwarding = 0; - - len = sizeof ip6forwarding; - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - if (sysctl (mib_ipv6, MIB_SIZ, NULL, NULL, &ip6forwarding, len) < 0) - { - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - zlog_warn ("can't get ip6forwarding value"); - return -1; - } - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - return ip6forwarding; + size_t len; + int ip6forwarding = 0; + + len = sizeof ip6forwarding; + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + if (sysctl(mib_ipv6, MIB_SIZ, NULL, NULL, &ip6forwarding, len) < 0) { + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + zlog_warn("can't get ip6forwarding value"); + return -1; + } + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + return ip6forwarding; } diff --git a/zebra/irdp.h b/zebra/irdp.h index 975e378b7..01308b915 100644 --- a/zebra/irdp.h +++ b/zebra/irdp.h @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -/* +/* * This file is modified and completed for the Zebra IRDP implementation * by Robert Olsson, Swedish University of Agricultural Sciences */ @@ -68,8 +68,8 @@ #define IRDP_RX_BUF 1500 -/* - Comments comes from RFC1256 ICMP Router Discovery Messages. +/* + Comments comes from RFC1256 ICMP Router Discovery Messages. The IP destination address to be used for multicast Router Advertisements sent from the interface. The only permissible @@ -79,26 +79,26 @@ all listening hosts support IP multicast.) Default: 224.0.0.1 if the router supports IP multicast on the - interface, else 255.255.255.255 + interface, else 255.255.255.255 The maximum time allowed between sending multicast Router Advertisements from the interface, in seconds. Must be no less than 4 seconds and no greater than 1800 seconds. - Default: 600 seconds + Default: 600 seconds The minimum time allowed between sending unsolicited multicast Router Advertisements from the interface, in seconds. Must be no less than 3 seconds and no greater than MaxAdvertisementInterval. - Default: 0.75 * MaxAdvertisementInterval + Default: 0.75 * MaxAdvertisementInterval The value to be placed in the Lifetime field of Router Advertisements sent from the interface, in seconds. Must be no less than MaxAdvertisementInterval and no greater than 9000 seconds. - Default: 3 * MaxAdvertisementInterval + Default: 3 * MaxAdvertisementInterval The preferability of the address as a default router address, relative to other router addresses on the same subnet. A 32-bit, @@ -107,16 +107,15 @@ that the address, even though it may be advertised, is not to be used by neighboring hosts as a default router address. - Default: 0 + Default: 0 */ -struct irdp_interface -{ - unsigned long MaxAdvertInterval; - unsigned long MinAdvertInterval; - unsigned long Preference; +struct irdp_interface { + unsigned long MaxAdvertInterval; + unsigned long MinAdvertInterval; + unsigned long Preference; - u_int32_t flags; + u_int32_t flags; #define IF_ACTIVE (1<<0) /* ICMP Active */ #define IF_BROADCAST (1<<1) /* 255.255.255.255 */ @@ -126,31 +125,29 @@ struct irdp_interface #define IF_DEBUG_MISC (1<<5) #define IF_SHUTDOWN (1<<6) - struct interface *ifp; - struct thread *t_advertise; - unsigned long irdp_sent; - u_int16_t Lifetime; - - struct list *AdvPrefList; + struct interface *ifp; + struct thread *t_advertise; + unsigned long irdp_sent; + u_int16_t Lifetime; + struct list *AdvPrefList; }; -struct Adv -{ - struct in_addr ip; - int pref; +struct Adv { + struct in_addr ip; + int pref; }; extern void irdp_init(void); extern int irdp_sock_init(void); extern void irdp_finish(void); -extern void irdp_config_write (struct vty *, struct interface *); +extern void irdp_config_write(struct vty *, struct interface *); extern int irdp_send_thread(struct thread *t_advert); extern void irdp_advert_off(struct interface *ifp); -extern void process_solicit (struct interface *ifp); +extern void process_solicit(struct interface *ifp); extern int irdp_read_raw(struct thread *r); -extern void send_packet(struct interface *ifp, struct stream *s, - u_int32_t dst, struct prefix *p, u_int32_t ttl); +extern void send_packet(struct interface *ifp, struct stream *s, u_int32_t dst, + struct prefix *p, u_int32_t ttl); #endif /* _IRDP_H */ diff --git a/zebra/irdp_interface.c b/zebra/irdp_interface.c index 323e94818..5682e12e6 100644 --- a/zebra/irdp_interface.c +++ b/zebra/irdp_interface.c @@ -63,311 +63,291 @@ extern int irdp_sock; -static const char * -inet_2a(u_int32_t a, char *b) +static const char *inet_2a(u_int32_t a, char *b) { - sprintf(b, "%u.%u.%u.%u", - (a ) & 0xFF, - (a>> 8) & 0xFF, - (a>>16) & 0xFF, - (a>>24) & 0xFF); - return b; + sprintf(b, "%u.%u.%u.%u", (a)&0xFF, (a >> 8) & 0xFF, (a >> 16) & 0xFF, + (a >> 24) & 0xFF); + return b; } -static struct prefix * -irdp_get_prefix(struct interface *ifp) +static struct prefix *irdp_get_prefix(struct interface *ifp) { - struct listnode *node; - struct connected *ifc; + struct listnode *node; + struct connected *ifc; - if (ifp->connected) - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc)) - return ifc->address; + if (ifp->connected) + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) + return ifc->address; - return NULL; + return NULL; } /* Join to the add/leave multicast group. */ -static int -if_group (struct interface *ifp, - int sock, - u_int32_t group, - int add_leave) +static int if_group(struct interface *ifp, int sock, u_int32_t group, + int add_leave) { - struct ip_mreq m; - struct prefix *p; - int ret; - char b1[INET_ADDRSTRLEN]; - - memset (&m, 0, sizeof (m)); - m.imr_multiaddr.s_addr = htonl (group); - p = irdp_get_prefix(ifp); - - if(!p) { - zlog_warn ("IRDP: can't get address for %s", ifp->name); - return 1; - } - - m.imr_interface = p->u.prefix4; - - ret = setsockopt (sock, IPPROTO_IP, add_leave, - (char *) &m, sizeof (struct ip_mreq)); - if (ret < 0) - zlog_warn ("IRDP: %s can't setsockopt %s: %s", - add_leave == IP_ADD_MEMBERSHIP? "join group":"leave group", - inet_2a(group, b1), - safe_strerror (errno)); - - return ret; + struct ip_mreq m; + struct prefix *p; + int ret; + char b1[INET_ADDRSTRLEN]; + + memset(&m, 0, sizeof(m)); + m.imr_multiaddr.s_addr = htonl(group); + p = irdp_get_prefix(ifp); + + if (!p) { + zlog_warn("IRDP: can't get address for %s", ifp->name); + return 1; + } + + m.imr_interface = p->u.prefix4; + + ret = setsockopt(sock, IPPROTO_IP, add_leave, (char *)&m, + sizeof(struct ip_mreq)); + if (ret < 0) + zlog_warn("IRDP: %s can't setsockopt %s: %s", + add_leave == IP_ADD_MEMBERSHIP ? "join group" + : "leave group", + inet_2a(group, b1), safe_strerror(errno)); + + return ret; } -static int -if_add_group (struct interface *ifp) +static int if_add_group(struct interface *ifp) { - struct zebra_if *zi= ifp->info; - struct irdp_interface *irdp = &zi->irdp; - int ret; - char b1[INET_ADDRSTRLEN]; - - ret = if_group (ifp, irdp_sock, INADDR_ALLRTRS_GROUP, IP_ADD_MEMBERSHIP); - if (ret < 0) { - return ret; - } - - if(irdp->flags & IF_DEBUG_MISC ) - zlog_debug("IRDP: Adding group %s for %s", - inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1), - ifp->name); - return 0; + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; + int ret; + char b1[INET_ADDRSTRLEN]; + + ret = if_group(ifp, irdp_sock, INADDR_ALLRTRS_GROUP, IP_ADD_MEMBERSHIP); + if (ret < 0) { + return ret; + } + + if (irdp->flags & IF_DEBUG_MISC) + zlog_debug("IRDP: Adding group %s for %s", + inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1), ifp->name); + return 0; } -static int -if_drop_group (struct interface *ifp) +static int if_drop_group(struct interface *ifp) { - struct zebra_if *zi= ifp->info; - struct irdp_interface *irdp = &zi->irdp; - int ret; - char b1[INET_ADDRSTRLEN]; - - ret = if_group (ifp, irdp_sock, INADDR_ALLRTRS_GROUP, IP_DROP_MEMBERSHIP); - if (ret < 0) - return ret; - - if(irdp->flags & IF_DEBUG_MISC) - zlog_debug("IRDP: Leaving group %s for %s", - inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1), - ifp->name); - return 0; + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; + int ret; + char b1[INET_ADDRSTRLEN]; + + ret = if_group(ifp, irdp_sock, INADDR_ALLRTRS_GROUP, + IP_DROP_MEMBERSHIP); + if (ret < 0) + return ret; + + if (irdp->flags & IF_DEBUG_MISC) + zlog_debug("IRDP: Leaving group %s for %s", + inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1), ifp->name); + return 0; } -static void -if_set_defaults(struct interface *ifp) +static void if_set_defaults(struct interface *ifp) { - struct zebra_if *zi=ifp->info; - struct irdp_interface *irdp=&zi->irdp; + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; - irdp->MaxAdvertInterval = IRDP_MAXADVERTINTERVAL; - irdp->MinAdvertInterval = IRDP_MINADVERTINTERVAL; - irdp->Preference = IRDP_PREFERENCE; - irdp->Lifetime = IRDP_LIFETIME; + irdp->MaxAdvertInterval = IRDP_MAXADVERTINTERVAL; + irdp->MinAdvertInterval = IRDP_MINADVERTINTERVAL; + irdp->Preference = IRDP_PREFERENCE; + irdp->Lifetime = IRDP_LIFETIME; } -static struct Adv *Adv_new (void) +static struct Adv *Adv_new(void) { - return XCALLOC (MTYPE_TMP, sizeof (struct Adv)); + return XCALLOC(MTYPE_TMP, sizeof(struct Adv)); } -static void -Adv_free (struct Adv *adv) +static void Adv_free(struct Adv *adv) { - XFREE (MTYPE_TMP, adv); + XFREE(MTYPE_TMP, adv); } -static void -irdp_if_start(struct interface *ifp, int multicast, int set_defaults) +static void irdp_if_start(struct interface *ifp, int multicast, + int set_defaults) { - struct zebra_if *zi= ifp->info; - struct irdp_interface *irdp = &zi->irdp; - struct listnode *node; - struct connected *ifc; - u_int32_t timer, seed; + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; + struct listnode *node; + struct connected *ifc; + u_int32_t timer, seed; - if (irdp->flags & IF_ACTIVE ) { - zlog_warn("IRDP: Interface is already active %s", ifp->name); - return; - } - if ((irdp_sock < 0) && ((irdp_sock = irdp_sock_init()) < 0)) { - zlog_warn("IRDP: Cannot activate interface %s (cannot create " - "IRDP socket)", ifp->name); - return; - } - irdp->flags |= IF_ACTIVE; + if (irdp->flags & IF_ACTIVE) { + zlog_warn("IRDP: Interface is already active %s", ifp->name); + return; + } + if ((irdp_sock < 0) && ((irdp_sock = irdp_sock_init()) < 0)) { + zlog_warn( + "IRDP: Cannot activate interface %s (cannot create " + "IRDP socket)", + ifp->name); + return; + } + irdp->flags |= IF_ACTIVE; - if(!multicast) - irdp->flags |= IF_BROADCAST; + if (!multicast) + irdp->flags |= IF_BROADCAST; - if_add_update(ifp); + if_add_update(ifp); - if (! (ifp->flags & IFF_UP)) { - zlog_warn("IRDP: Interface is down %s", ifp->name); - } + if (!(ifp->flags & IFF_UP)) { + zlog_warn("IRDP: Interface is down %s", ifp->name); + } - /* Shall we cancel if_start if if_add_group fails? */ + /* Shall we cancel if_start if if_add_group fails? */ - if( multicast) { - if_add_group(ifp); + if (multicast) { + if_add_group(ifp); - if (! (ifp->flags & (IFF_MULTICAST|IFF_ALLMULTI))) { - zlog_warn("IRDP: Interface not multicast enabled %s", ifp->name); - } - } + if (!(ifp->flags & (IFF_MULTICAST | IFF_ALLMULTI))) { + zlog_warn("IRDP: Interface not multicast enabled %s", + ifp->name); + } + } - if(set_defaults) - if_set_defaults(ifp); + if (set_defaults) + if_set_defaults(ifp); - irdp->irdp_sent = 0; + irdp->irdp_sent = 0; - /* The spec suggests this for randomness */ + /* The spec suggests this for randomness */ - seed = 0; - if( ifp->connected) - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc)) - { - seed = ifc->address->u.prefix4.s_addr; - break; - } + seed = 0; + if (ifp->connected) + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { + seed = ifc->address->u.prefix4.s_addr; + break; + } - srandom(seed); - timer = (random () % IRDP_DEFAULT_INTERVAL) + 1; + srandom(seed); + timer = (random() % IRDP_DEFAULT_INTERVAL) + 1; - irdp->AdvPrefList = list_new(); - irdp->AdvPrefList->del = (void (*)(void *)) Adv_free; /* Destructor */ + irdp->AdvPrefList = list_new(); + irdp->AdvPrefList->del = (void (*)(void *))Adv_free; /* Destructor */ - /* And this for startup. Speed limit from 1991 :-). But it's OK*/ + /* And this for startup. Speed limit from 1991 :-). But it's OK*/ - if(irdp->irdp_sent < MAX_INITIAL_ADVERTISEMENTS && - timer > MAX_INITIAL_ADVERT_INTERVAL ) - timer= MAX_INITIAL_ADVERT_INTERVAL; + if (irdp->irdp_sent < MAX_INITIAL_ADVERTISEMENTS + && timer > MAX_INITIAL_ADVERT_INTERVAL) + timer = MAX_INITIAL_ADVERT_INTERVAL; - if(irdp->flags & IF_DEBUG_MISC) - zlog_debug("IRDP: Init timer for %s set to %u", - ifp->name, - timer); + if (irdp->flags & IF_DEBUG_MISC) + zlog_debug("IRDP: Init timer for %s set to %u", ifp->name, + timer); - irdp->t_advertise = NULL; - thread_add_timer(zebrad.master, irdp_send_thread, ifp, timer, - &irdp->t_advertise); + irdp->t_advertise = NULL; + thread_add_timer(zebrad.master, irdp_send_thread, ifp, timer, + &irdp->t_advertise); } -static void -irdp_if_stop(struct interface *ifp) +static void irdp_if_stop(struct interface *ifp) { - struct zebra_if *zi=ifp->info; - struct irdp_interface *irdp=&zi->irdp; + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; - if (irdp == NULL) { - zlog_warn ("Interface %s structure is NULL", ifp->name); - return; - } + if (irdp == NULL) { + zlog_warn("Interface %s structure is NULL", ifp->name); + return; + } - if (! (irdp->flags & IF_ACTIVE )) { - zlog_warn("Interface is not active %s", ifp->name); - return; - } + if (!(irdp->flags & IF_ACTIVE)) { + zlog_warn("Interface is not active %s", ifp->name); + return; + } - if(! (irdp->flags & IF_BROADCAST)) - if_drop_group(ifp); + if (!(irdp->flags & IF_BROADCAST)) + if_drop_group(ifp); - irdp_advert_off(ifp); + irdp_advert_off(ifp); - list_delete(irdp->AdvPrefList); - irdp->AdvPrefList=NULL; + list_delete(irdp->AdvPrefList); + irdp->AdvPrefList = NULL; - irdp->flags = 0; + irdp->flags = 0; } -static void -irdp_if_shutdown(struct interface *ifp) +static void irdp_if_shutdown(struct interface *ifp) { - struct zebra_if *zi= ifp->info; - struct irdp_interface *irdp = &zi->irdp; + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; - if (irdp->flags & IF_SHUTDOWN ) { - zlog_warn("IRDP: Interface is already shutdown %s", ifp->name); - return; - } + if (irdp->flags & IF_SHUTDOWN) { + zlog_warn("IRDP: Interface is already shutdown %s", ifp->name); + return; + } - irdp->flags |= IF_SHUTDOWN; - irdp->flags &= ~IF_ACTIVE; + irdp->flags |= IF_SHUTDOWN; + irdp->flags &= ~IF_ACTIVE; - if(! (irdp->flags & IF_BROADCAST)) - if_drop_group(ifp); + if (!(irdp->flags & IF_BROADCAST)) + if_drop_group(ifp); - /* Tell the hosts we are out of service */ - irdp_advert_off(ifp); + /* Tell the hosts we are out of service */ + irdp_advert_off(ifp); } -static void -irdp_if_no_shutdown(struct interface *ifp) +static void irdp_if_no_shutdown(struct interface *ifp) { - struct zebra_if *zi= ifp->info; - struct irdp_interface *irdp = &zi->irdp; + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; - if (! (irdp->flags & IF_SHUTDOWN )) { - zlog_warn("IRDP: Interface is not shutdown %s", ifp->name); - return; - } + if (!(irdp->flags & IF_SHUTDOWN)) { + zlog_warn("IRDP: Interface is not shutdown %s", ifp->name); + return; + } - irdp->flags &= ~IF_SHUTDOWN; - - irdp_if_start(ifp, irdp->flags & IF_BROADCAST? FALSE : TRUE, FALSE); + irdp->flags &= ~IF_SHUTDOWN; + irdp_if_start(ifp, irdp->flags & IF_BROADCAST ? FALSE : TRUE, FALSE); } /* Write configuration to user */ -void irdp_config_write (struct vty *vty, struct interface *ifp) +void irdp_config_write(struct vty *vty, struct interface *ifp) { - struct zebra_if *zi=ifp->info; - struct irdp_interface *irdp=&zi->irdp; - struct Adv *adv; - struct listnode *node; - char b1[INET_ADDRSTRLEN]; - - if(irdp->flags & IF_ACTIVE || irdp->flags & IF_SHUTDOWN) { + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; + struct Adv *adv; + struct listnode *node; + char b1[INET_ADDRSTRLEN]; - if( irdp->flags & IF_SHUTDOWN) - vty_out (vty, " ip irdp shutdown \n"); + if (irdp->flags & IF_ACTIVE || irdp->flags & IF_SHUTDOWN) { - if( irdp->flags & IF_BROADCAST) - vty_out (vty, " ip irdp broadcast\n"); - else - vty_out (vty, " ip irdp multicast\n"); + if (irdp->flags & IF_SHUTDOWN) + vty_out(vty, " ip irdp shutdown \n"); - vty_out (vty, " ip irdp preference %ld\n", - irdp->Preference); + if (irdp->flags & IF_BROADCAST) + vty_out(vty, " ip irdp broadcast\n"); + else + vty_out(vty, " ip irdp multicast\n"); - for (ALL_LIST_ELEMENTS_RO (irdp->AdvPrefList, node, adv)) - vty_out (vty, " ip irdp address %s preference %d\n", - inet_2a(adv->ip.s_addr, b1), - adv->pref); + vty_out(vty, " ip irdp preference %ld\n", irdp->Preference); - vty_out (vty, " ip irdp holdtime %d\n", - irdp->Lifetime); + for (ALL_LIST_ELEMENTS_RO(irdp->AdvPrefList, node, adv)) + vty_out(vty, " ip irdp address %s preference %d\n", + inet_2a(adv->ip.s_addr, b1), adv->pref); - vty_out (vty, " ip irdp minadvertinterval %ld\n", - irdp->MinAdvertInterval); + vty_out(vty, " ip irdp holdtime %d\n", irdp->Lifetime); - vty_out (vty, " ip irdp maxadvertinterval %ld\n", - irdp->MaxAdvertInterval); + vty_out(vty, " ip irdp minadvertinterval %ld\n", + irdp->MinAdvertInterval); - } + vty_out(vty, " ip irdp maxadvertinterval %ld\n", + irdp->MaxAdvertInterval); + } } @@ -378,10 +358,10 @@ DEFUN (ip_irdp_multicast, "ICMP Router discovery on this interface\n" "Use multicast mode\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - irdp_if_start(ifp, TRUE, TRUE); - return CMD_SUCCESS; + irdp_if_start(ifp, TRUE, TRUE); + return CMD_SUCCESS; } DEFUN (ip_irdp_broadcast, @@ -391,10 +371,10 @@ DEFUN (ip_irdp_broadcast, "ICMP Router discovery on this interface\n" "Use broadcast mode\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - irdp_if_start(ifp, FALSE, TRUE); - return CMD_SUCCESS; + irdp_if_start(ifp, FALSE, TRUE); + return CMD_SUCCESS; } DEFUN (no_ip_irdp, @@ -404,10 +384,10 @@ DEFUN (no_ip_irdp, IP_STR "Disable ICMP Router discovery on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - irdp_if_stop(ifp); - return CMD_SUCCESS; + irdp_if_stop(ifp); + return CMD_SUCCESS; } DEFUN (ip_irdp_shutdown, @@ -417,10 +397,10 @@ DEFUN (ip_irdp_shutdown, "ICMP Router discovery on this interface\n" "ICMP Router discovery shutdown on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - irdp_if_shutdown(ifp); - return CMD_SUCCESS; + irdp_if_shutdown(ifp); + return CMD_SUCCESS; } DEFUN (no_ip_irdp_shutdown, @@ -431,10 +411,10 @@ DEFUN (no_ip_irdp_shutdown, "ICMP Router discovery on this interface\n" "ICMP Router discovery no shutdown on this interface\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); + VTY_DECLVAR_CONTEXT(interface, ifp); - irdp_if_no_shutdown(ifp); - return CMD_SUCCESS; + irdp_if_no_shutdown(ifp); + return CMD_SUCCESS; } DEFUN (ip_irdp_holdtime, @@ -445,16 +425,16 @@ DEFUN (ip_irdp_holdtime, "Set holdtime value\n" "Holdtime value in seconds. Default is 1800 seconds\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; + int idx_number = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zi; + struct irdp_interface *irdp; - zi=ifp->info; - irdp=&zi->irdp; + zi = ifp->info; + irdp = &zi->irdp; - irdp->Lifetime = atoi(argv[idx_number]->arg); - return CMD_SUCCESS; + irdp->Lifetime = atoi(argv[idx_number]->arg); + return CMD_SUCCESS; } DEFUN (ip_irdp_minadvertinterval, @@ -465,23 +445,23 @@ DEFUN (ip_irdp_minadvertinterval, "Set minimum time between advertisement\n" "Minimum advertisement interval in seconds\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; - - zi=ifp->info; - irdp=&zi->irdp; - - if((unsigned) atoi(argv[idx_number]->arg) <= irdp->MaxAdvertInterval) { - irdp->MinAdvertInterval = atoi(argv[idx_number]->arg); - return CMD_SUCCESS; - } - else { - vty_out (vty, "%% MinAdvertInterval must be less than or equal to " - "MaxAdvertInterval\n"); - return CMD_WARNING_CONFIG_FAILED; - } + int idx_number = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zi; + struct irdp_interface *irdp; + + zi = ifp->info; + irdp = &zi->irdp; + + if ((unsigned)atoi(argv[idx_number]->arg) <= irdp->MaxAdvertInterval) { + irdp->MinAdvertInterval = atoi(argv[idx_number]->arg); + return CMD_SUCCESS; + } else { + vty_out(vty, + "%% MinAdvertInterval must be less than or equal to " + "MaxAdvertInterval\n"); + return CMD_WARNING_CONFIG_FAILED; + } } DEFUN (ip_irdp_maxadvertinterval, @@ -492,23 +472,23 @@ DEFUN (ip_irdp_maxadvertinterval, "Set maximum time between advertisement\n" "Maximum advertisement interval in seconds\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; - - zi=ifp->info; - irdp=&zi->irdp; - - if(irdp->MinAdvertInterval <= (unsigned) atoi(argv[idx_number]->arg)) { - irdp->MaxAdvertInterval = atoi(argv[idx_number]->arg); - return CMD_SUCCESS; - } - else { - vty_out (vty, "%% MaxAdvertInterval must be greater than or equal to " - "MinAdvertInterval\n"); - return CMD_WARNING_CONFIG_FAILED; - } + int idx_number = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zi; + struct irdp_interface *irdp; + + zi = ifp->info; + irdp = &zi->irdp; + + if (irdp->MinAdvertInterval <= (unsigned)atoi(argv[idx_number]->arg)) { + irdp->MaxAdvertInterval = atoi(argv[idx_number]->arg); + return CMD_SUCCESS; + } else { + vty_out(vty, + "%% MaxAdvertInterval must be greater than or equal to " + "MinAdvertInterval\n"); + return CMD_WARNING_CONFIG_FAILED; + } } /* DEFUN needs to be fixed for negative ranages... @@ -524,16 +504,16 @@ DEFUN (ip_irdp_preference, "Set default preference level for this interface\n" "Preference level\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; + int idx_number = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zi; + struct irdp_interface *irdp; - zi=ifp->info; - irdp=&zi->irdp; + zi = ifp->info; + irdp = &zi->irdp; - irdp->Preference = atoi(argv[idx_number]->arg); - return CMD_SUCCESS; + irdp->Preference = atoi(argv[idx_number]->arg); + return CMD_SUCCESS; } DEFUN (ip_irdp_address_preference, @@ -546,36 +526,36 @@ DEFUN (ip_irdp_address_preference, "Specify IRDP non-default preference to advertise\n" "Preference level\n") { - int idx_ipv4 = 3; - int idx_number = 5; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct listnode *node; - struct in_addr ip; - int pref; - int ret; - struct zebra_if *zi; - struct irdp_interface *irdp; - struct Adv *adv; - - zi=ifp->info; - irdp=&zi->irdp; - - ret = inet_aton(argv[idx_ipv4]->arg, &ip); - if(!ret) return CMD_WARNING_CONFIG_FAILED; - - pref = atoi(argv[idx_number]->arg); - - for (ALL_LIST_ELEMENTS_RO (irdp->AdvPrefList, node, adv)) - if(adv->ip.s_addr == ip.s_addr) - return CMD_SUCCESS; - - adv = Adv_new(); - adv->ip = ip; - adv->pref = pref; - listnode_add(irdp->AdvPrefList, adv); - - return CMD_SUCCESS; - + int idx_ipv4 = 3; + int idx_number = 5; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct listnode *node; + struct in_addr ip; + int pref; + int ret; + struct zebra_if *zi; + struct irdp_interface *irdp; + struct Adv *adv; + + zi = ifp->info; + irdp = &zi->irdp; + + ret = inet_aton(argv[idx_ipv4]->arg, &ip); + if (!ret) + return CMD_WARNING_CONFIG_FAILED; + + pref = atoi(argv[idx_number]->arg); + + for (ALL_LIST_ELEMENTS_RO(irdp->AdvPrefList, node, adv)) + if (adv->ip.s_addr == ip.s_addr) + return CMD_SUCCESS; + + adv = Adv_new(); + adv->ip = ip; + adv->pref = pref; + listnode_add(irdp->AdvPrefList, adv); + + return CMD_SUCCESS; } DEFUN (no_ip_irdp_address_preference, @@ -589,32 +569,30 @@ DEFUN (no_ip_irdp_address_preference, "Reset ICMP Router discovery preference on this interface\n" "Old preference level\n") { - int idx_ipv4 = 4; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct listnode *node, *nnode; - struct in_addr ip; - int ret; - struct zebra_if *zi; - struct irdp_interface *irdp; - struct Adv *adv; - - zi=ifp->info; - irdp=&zi->irdp; - - ret = inet_aton(argv[idx_ipv4]->arg, &ip); - if (!ret) - return CMD_WARNING_CONFIG_FAILED; - - for (ALL_LIST_ELEMENTS (irdp->AdvPrefList, node, nnode, adv)) - { - if(adv->ip.s_addr == ip.s_addr ) - { - listnode_delete(irdp->AdvPrefList, adv); - break; - } - } - - return CMD_SUCCESS; + int idx_ipv4 = 4; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct listnode *node, *nnode; + struct in_addr ip; + int ret; + struct zebra_if *zi; + struct irdp_interface *irdp; + struct Adv *adv; + + zi = ifp->info; + irdp = &zi->irdp; + + ret = inet_aton(argv[idx_ipv4]->arg, &ip); + if (!ret) + return CMD_WARNING_CONFIG_FAILED; + + for (ALL_LIST_ELEMENTS(irdp->AdvPrefList, node, nnode, adv)) { + if (adv->ip.s_addr == ip.s_addr) { + listnode_delete(irdp->AdvPrefList, adv); + break; + } + } + + return CMD_SUCCESS; } DEFUN (ip_irdp_debug_messages, @@ -625,16 +603,16 @@ DEFUN (ip_irdp_debug_messages, "IRDP debugging options\n" "Enable debugging for IRDP messages\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zi; + struct irdp_interface *irdp; - zi=ifp->info; - irdp=&zi->irdp; + zi = ifp->info; + irdp = &zi->irdp; - irdp->flags |= IF_DEBUG_MESSAGES; + irdp->flags |= IF_DEBUG_MESSAGES; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_irdp_debug_misc, @@ -645,16 +623,16 @@ DEFUN (ip_irdp_debug_misc, "IRDP debugging options\n" "Enable debugging for miscellaneous IRDP events\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zi; + struct irdp_interface *irdp; - zi=ifp->info; - irdp=&zi->irdp; + zi = ifp->info; + irdp = &zi->irdp; - irdp->flags |= IF_DEBUG_MISC; + irdp->flags |= IF_DEBUG_MISC; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_irdp_debug_packet, @@ -665,16 +643,16 @@ DEFUN (ip_irdp_debug_packet, "IRDP debugging options\n" "Enable debugging for IRDP packets\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zi; + struct irdp_interface *irdp; - zi=ifp->info; - irdp=&zi->irdp; + zi = ifp->info; + irdp = &zi->irdp; - irdp->flags |= IF_DEBUG_PACKET; + irdp->flags |= IF_DEBUG_PACKET; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -686,39 +664,38 @@ DEFUN (ip_irdp_debug_disable, "IRDP debugging options\n" "Disable debugging for all IRDP events\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zi; - struct irdp_interface *irdp; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zi; + struct irdp_interface *irdp; - zi=ifp->info; - irdp=&zi->irdp; + zi = ifp->info; + irdp = &zi->irdp; - irdp->flags &= ~IF_DEBUG_PACKET; - irdp->flags &= ~IF_DEBUG_MESSAGES; - irdp->flags &= ~IF_DEBUG_MISC; + irdp->flags &= ~IF_DEBUG_PACKET; + irdp->flags &= ~IF_DEBUG_MESSAGES; + irdp->flags &= ~IF_DEBUG_MISC; - return CMD_SUCCESS; + return CMD_SUCCESS; } -void -irdp_init () +void irdp_init() { - install_element (INTERFACE_NODE, &ip_irdp_broadcast_cmd); - install_element (INTERFACE_NODE, &ip_irdp_multicast_cmd); - install_element (INTERFACE_NODE, &no_ip_irdp_cmd); - install_element (INTERFACE_NODE, &ip_irdp_shutdown_cmd); - install_element (INTERFACE_NODE, &no_ip_irdp_shutdown_cmd); - install_element (INTERFACE_NODE, &ip_irdp_holdtime_cmd); - install_element (INTERFACE_NODE, &ip_irdp_maxadvertinterval_cmd); - install_element (INTERFACE_NODE, &ip_irdp_minadvertinterval_cmd); - install_element (INTERFACE_NODE, &ip_irdp_preference_cmd); - install_element (INTERFACE_NODE, &ip_irdp_address_preference_cmd); - install_element (INTERFACE_NODE, &no_ip_irdp_address_preference_cmd); - - install_element (INTERFACE_NODE, &ip_irdp_debug_messages_cmd); - install_element (INTERFACE_NODE, &ip_irdp_debug_misc_cmd); - install_element (INTERFACE_NODE, &ip_irdp_debug_packet_cmd); - install_element (INTERFACE_NODE, &ip_irdp_debug_disable_cmd); + install_element(INTERFACE_NODE, &ip_irdp_broadcast_cmd); + install_element(INTERFACE_NODE, &ip_irdp_multicast_cmd); + install_element(INTERFACE_NODE, &no_ip_irdp_cmd); + install_element(INTERFACE_NODE, &ip_irdp_shutdown_cmd); + install_element(INTERFACE_NODE, &no_ip_irdp_shutdown_cmd); + install_element(INTERFACE_NODE, &ip_irdp_holdtime_cmd); + install_element(INTERFACE_NODE, &ip_irdp_maxadvertinterval_cmd); + install_element(INTERFACE_NODE, &ip_irdp_minadvertinterval_cmd); + install_element(INTERFACE_NODE, &ip_irdp_preference_cmd); + install_element(INTERFACE_NODE, &ip_irdp_address_preference_cmd); + install_element(INTERFACE_NODE, &no_ip_irdp_address_preference_cmd); + + install_element(INTERFACE_NODE, &ip_irdp_debug_messages_cmd); + install_element(INTERFACE_NODE, &ip_irdp_debug_misc_cmd); + install_element(INTERFACE_NODE, &ip_irdp_debug_packet_cmd); + install_element(INTERFACE_NODE, &ip_irdp_debug_disable_cmd); } #endif /* HAVE_IRDP */ diff --git a/zebra/irdp_main.c b/zebra/irdp_main.c index a155331c9..6220c9d81 100644 --- a/zebra/irdp_main.c +++ b/zebra/irdp_main.c @@ -20,14 +20,14 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -/* +/* * This work includes work with the following copywrite: * * Copyright (C) 1997, 2000 Kunihiro Ishiguro * */ -/* +/* * Thanks to Jens Låås at Swedish University of Agricultural Sciences * for reviewing and tests. */ @@ -74,262 +74,258 @@ struct thread *t_irdp_raw; /* Timer interval of irdp. */ int irdp_timer_interval = IRDP_DEFAULT_INTERVAL; -int -irdp_sock_init (void) +int irdp_sock_init(void) { - int ret, i; - int save_errno; - int sock; - - if ( zserv_privs.change (ZPRIVS_RAISE) ) - zlog_err ("irdp_sock_init: could not raise privs, %s", - safe_strerror (errno) ); - - sock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); - save_errno = errno; - - if ( zserv_privs.change (ZPRIVS_LOWER) ) - zlog_err ("irdp_sock_init: could not lower privs, %s", - safe_strerror (errno) ); - - if (sock < 0) { - zlog_warn ("IRDP: can't create irdp socket %s", safe_strerror(save_errno)); - return sock; - }; - - i = 1; - ret = setsockopt (sock, IPPROTO_IP, IP_TTL, - (void *) &i, sizeof (i)); - if (ret < 0) { - zlog_warn ("IRDP: can't do irdp sockopt %s", safe_strerror(errno)); - close(sock); - return ret; - }; - - ret = setsockopt_ifindex (AF_INET, sock, 1); - if (ret < 0) { - zlog_warn ("IRDP: can't do irdp sockopt %s", safe_strerror(errno)); - close(sock); - return ret; - }; - - t_irdp_raw = NULL; - thread_add_read(zebrad.master, irdp_read_raw, NULL, sock, &t_irdp_raw); - - return sock; + int ret, i; + int save_errno; + int sock; + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("irdp_sock_init: could not raise privs, %s", + safe_strerror(errno)); + + sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + save_errno = errno; + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("irdp_sock_init: could not lower privs, %s", + safe_strerror(errno)); + + if (sock < 0) { + zlog_warn("IRDP: can't create irdp socket %s", + safe_strerror(save_errno)); + return sock; + }; + + i = 1; + ret = setsockopt(sock, IPPROTO_IP, IP_TTL, (void *)&i, sizeof(i)); + if (ret < 0) { + zlog_warn("IRDP: can't do irdp sockopt %s", + safe_strerror(errno)); + close(sock); + return ret; + }; + + ret = setsockopt_ifindex(AF_INET, sock, 1); + if (ret < 0) { + zlog_warn("IRDP: can't do irdp sockopt %s", + safe_strerror(errno)); + close(sock); + return ret; + }; + + t_irdp_raw = NULL; + thread_add_read(zebrad.master, irdp_read_raw, NULL, sock, &t_irdp_raw); + + return sock; } -static int -get_pref(struct irdp_interface *irdp, struct prefix *p) +static int get_pref(struct irdp_interface *irdp, struct prefix *p) { - struct listnode *node; - struct Adv *adv; - - /* Use default preference or use the override pref */ - - if( irdp->AdvPrefList == NULL ) - return irdp->Preference; - - for (ALL_LIST_ELEMENTS_RO (irdp->AdvPrefList, node, adv)) - if( p->u.prefix4.s_addr == adv->ip.s_addr ) - return adv->pref; - - return irdp->Preference; + struct listnode *node; + struct Adv *adv; + + /* Use default preference or use the override pref */ + + if (irdp->AdvPrefList == NULL) + return irdp->Preference; + + for (ALL_LIST_ELEMENTS_RO(irdp->AdvPrefList, node, adv)) + if (p->u.prefix4.s_addr == adv->ip.s_addr) + return adv->pref; + + return irdp->Preference; } /* Make ICMP Router Advertisement Message. */ -static int -make_advertisement_packet (struct interface *ifp, - struct prefix *p, - struct stream *s) +static int make_advertisement_packet(struct interface *ifp, struct prefix *p, + struct stream *s) { - struct zebra_if *zi=ifp->info; - struct irdp_interface *irdp=&zi->irdp; - int size; - int pref; - u_int16_t checksum; - - pref = get_pref(irdp, p); - - stream_putc (s, ICMP_ROUTERADVERT); /* Type. */ - stream_putc (s, 0); /* Code. */ - stream_putw (s, 0); /* Checksum. */ - stream_putc (s, 1); /* Num address. */ - stream_putc (s, 2); /* Address Entry Size. */ - - if(irdp->flags & IF_SHUTDOWN) - stream_putw (s, 0); - else - stream_putw (s, irdp->Lifetime); - - stream_putl (s, htonl(p->u.prefix4.s_addr)); /* Router address. */ - stream_putl (s, pref); - - /* in_cksum return network byte order value */ - size = 16; - checksum = in_cksum (s->data, size); - stream_putw_at (s, 2, htons(checksum)); - - return size; + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; + int size; + int pref; + u_int16_t checksum; + + pref = get_pref(irdp, p); + + stream_putc(s, ICMP_ROUTERADVERT); /* Type. */ + stream_putc(s, 0); /* Code. */ + stream_putw(s, 0); /* Checksum. */ + stream_putc(s, 1); /* Num address. */ + stream_putc(s, 2); /* Address Entry Size. */ + + if (irdp->flags & IF_SHUTDOWN) + stream_putw(s, 0); + else + stream_putw(s, irdp->Lifetime); + + stream_putl(s, htonl(p->u.prefix4.s_addr)); /* Router address. */ + stream_putl(s, pref); + + /* in_cksum return network byte order value */ + size = 16; + checksum = in_cksum(s->data, size); + stream_putw_at(s, 2, htons(checksum)); + + return size; } -static void -irdp_send(struct interface *ifp, struct prefix *p, struct stream *s) +static void irdp_send(struct interface *ifp, struct prefix *p, struct stream *s) { - struct zebra_if *zi=ifp->info; - struct irdp_interface *irdp=&zi->irdp; - char buf[PREFIX_STRLEN]; - u_int32_t dst; - u_int32_t ttl=1; - - if (! (ifp->flags & IFF_UP)) return; - - if (irdp->flags & IF_BROADCAST) - dst =INADDR_BROADCAST ; - else - dst = htonl(INADDR_ALLHOSTS_GROUP); - - if(irdp->flags & IF_DEBUG_MESSAGES) - zlog_debug("IRDP: TX Advert on %s %s Holdtime=%d Preference=%d", - ifp->name, - prefix2str(p, buf, sizeof buf), - irdp->flags & IF_SHUTDOWN? 0 : irdp->Lifetime, - get_pref(irdp, p)); - - send_packet (ifp, s, dst, p, ttl); + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; + char buf[PREFIX_STRLEN]; + u_int32_t dst; + u_int32_t ttl = 1; + + if (!(ifp->flags & IFF_UP)) + return; + + if (irdp->flags & IF_BROADCAST) + dst = INADDR_BROADCAST; + else + dst = htonl(INADDR_ALLHOSTS_GROUP); + + if (irdp->flags & IF_DEBUG_MESSAGES) + zlog_debug("IRDP: TX Advert on %s %s Holdtime=%d Preference=%d", + ifp->name, prefix2str(p, buf, sizeof buf), + irdp->flags & IF_SHUTDOWN ? 0 : irdp->Lifetime, + get_pref(irdp, p)); + + send_packet(ifp, s, dst, p, ttl); } -static void irdp_advertisement (struct interface *ifp, struct prefix *p) +static void irdp_advertisement(struct interface *ifp, struct prefix *p) { - struct stream *s; - s = stream_new (128); - make_advertisement_packet (ifp, p, s); - irdp_send(ifp, p, s); - stream_free (s); + struct stream *s; + s = stream_new(128); + make_advertisement_packet(ifp, p, s); + irdp_send(ifp, p, s); + stream_free(s); } int irdp_send_thread(struct thread *t_advert) { - u_int32_t timer, tmp; - struct interface *ifp = THREAD_ARG (t_advert); - struct zebra_if *zi=ifp->info; - struct irdp_interface *irdp=&zi->irdp; - struct prefix *p; - struct listnode *node, *nnode; - struct connected *ifc; - - irdp->flags &= ~IF_SOLICIT; - - if(ifp->connected) - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, ifc)) - { - p = ifc->address; - - if (p->family != AF_INET) - continue; - - irdp_advertisement(ifp, p); - irdp->irdp_sent++; - } - - tmp = irdp->MaxAdvertInterval-irdp->MinAdvertInterval; - timer = random () % (tmp + 1); - timer = irdp->MinAdvertInterval + timer; - - if(irdp->irdp_sent < MAX_INITIAL_ADVERTISEMENTS && - timer > MAX_INITIAL_ADVERT_INTERVAL ) - timer= MAX_INITIAL_ADVERT_INTERVAL; - - if(irdp->flags & IF_DEBUG_MISC) - zlog_debug("IRDP: New timer for %s set to %u\n", ifp->name, timer); - - irdp->t_advertise = NULL; - thread_add_timer(zebrad.master, irdp_send_thread, ifp, timer, - &irdp->t_advertise); - return 0; + u_int32_t timer, tmp; + struct interface *ifp = THREAD_ARG(t_advert); + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; + struct prefix *p; + struct listnode *node, *nnode; + struct connected *ifc; + + irdp->flags &= ~IF_SOLICIT; + + if (ifp->connected) + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, ifc)) { + p = ifc->address; + + if (p->family != AF_INET) + continue; + + irdp_advertisement(ifp, p); + irdp->irdp_sent++; + } + + tmp = irdp->MaxAdvertInterval - irdp->MinAdvertInterval; + timer = random() % (tmp + 1); + timer = irdp->MinAdvertInterval + timer; + + if (irdp->irdp_sent < MAX_INITIAL_ADVERTISEMENTS + && timer > MAX_INITIAL_ADVERT_INTERVAL) + timer = MAX_INITIAL_ADVERT_INTERVAL; + + if (irdp->flags & IF_DEBUG_MISC) + zlog_debug("IRDP: New timer for %s set to %u\n", ifp->name, + timer); + + irdp->t_advertise = NULL; + thread_add_timer(zebrad.master, irdp_send_thread, ifp, timer, + &irdp->t_advertise); + return 0; } void irdp_advert_off(struct interface *ifp) { - struct zebra_if *zi=ifp->info; - struct irdp_interface *irdp=&zi->irdp; - struct listnode *node, *nnode; - int i; - struct connected *ifc; - struct prefix *p; - - if(irdp->t_advertise) thread_cancel(irdp->t_advertise); - irdp->t_advertise = NULL; - - if(ifp->connected) - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, ifc)) - { - p = ifc->address; - - /* Output some packets with Lifetime 0 - we should add a wait... - */ - - for(i=0; i< IRDP_LAST_ADVERT_MESSAGES; i++) - { - irdp->irdp_sent++; - irdp_advertisement(ifp, p); - } - } + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; + struct listnode *node, *nnode; + int i; + struct connected *ifc; + struct prefix *p; + + if (irdp->t_advertise) + thread_cancel(irdp->t_advertise); + irdp->t_advertise = NULL; + + if (ifp->connected) + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, ifc)) { + p = ifc->address; + + /* Output some packets with Lifetime 0 + we should add a wait... + */ + + for (i = 0; i < IRDP_LAST_ADVERT_MESSAGES; i++) { + irdp->irdp_sent++; + irdp_advertisement(ifp, p); + } + } } -void process_solicit (struct interface *ifp) +void process_solicit(struct interface *ifp) { - struct zebra_if *zi=ifp->info; - struct irdp_interface *irdp=&zi->irdp; - u_int32_t timer; + struct zebra_if *zi = ifp->info; + struct irdp_interface *irdp = &zi->irdp; + u_int32_t timer; - /* When SOLICIT is active we reject further incoming solicits - this keeps down the answering rate so we don't have think - about DoS attacks here. */ + /* When SOLICIT is active we reject further incoming solicits + this keeps down the answering rate so we don't have think + about DoS attacks here. */ - if( irdp->flags & IF_SOLICIT) return; + if (irdp->flags & IF_SOLICIT) + return; - irdp->flags |= IF_SOLICIT; - if(irdp->t_advertise) thread_cancel(irdp->t_advertise); - irdp->t_advertise = NULL; + irdp->flags |= IF_SOLICIT; + if (irdp->t_advertise) + thread_cancel(irdp->t_advertise); + irdp->t_advertise = NULL; - timer = (random () % MAX_RESPONSE_DELAY) + 1; + timer = (random() % MAX_RESPONSE_DELAY) + 1; - irdp->t_advertise = NULL; - thread_add_timer(zebrad.master, irdp_send_thread, ifp, timer, - &irdp->t_advertise); + irdp->t_advertise = NULL; + thread_add_timer(zebrad.master, irdp_send_thread, ifp, timer, + &irdp->t_advertise); } void irdp_finish() { - struct vrf *vrf; - struct listnode *node, *nnode; - struct interface *ifp; - struct zebra_if *zi; - struct irdp_interface *irdp; - - zlog_info("IRDP: Received shutdown notification."); - - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - for (ALL_LIST_ELEMENTS (vrf->iflist, node, nnode, ifp)) - { - zi = ifp->info; - - if (!zi) - continue; - irdp = &zi->irdp; - if (!irdp) - continue; - - if (irdp->flags & IF_ACTIVE ) - { - irdp->flags |= IF_SHUTDOWN; - irdp_advert_off(ifp); - } - } + struct vrf *vrf; + struct listnode *node, *nnode; + struct interface *ifp; + struct zebra_if *zi; + struct irdp_interface *irdp; + + zlog_info("IRDP: Received shutdown notification."); + + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + for (ALL_LIST_ELEMENTS(vrf->iflist, node, nnode, ifp)) { + zi = ifp->info; + + if (!zi) + continue; + irdp = &zi->irdp; + if (!irdp) + continue; + + if (irdp->flags & IF_ACTIVE) { + irdp->flags |= IF_SHUTDOWN; + irdp_advert_off(ifp); + } + } } #endif /* HAVE_IRDP */ diff --git a/zebra/irdp_packet.c b/zebra/irdp_packet.c index 20982b31a..3bd093d97 100644 --- a/zebra/irdp_packet.c +++ b/zebra/irdp_packet.c @@ -20,14 +20,14 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -/* +/* * This work includes work with the following copywrite: * * Copyright (C) 1997, 2000 Kunihiro Ishiguro * */ -/* +/* * Thanks to Jens Låås at Swedish University of Agricultural Sciences * for reviewing and tests. */ @@ -71,294 +71,288 @@ int irdp_sock = -1; extern struct thread *t_irdp_raw; -static void -parse_irdp_packet(char *p, - int len, - struct interface *ifp) +static void parse_irdp_packet(char *p, int len, struct interface *ifp) { - struct ip *ip = (struct ip *)p ; - struct icmphdr *icmp; - struct in_addr src; - int ip_hlen, iplen, datalen; - struct zebra_if *zi; - struct irdp_interface *irdp; - - zi = ifp->info; - if (!zi) - return; - - irdp = &zi->irdp; - if (!irdp) - return; - - ip_hlen = ip->ip_hl << 2; - - sockopt_iphdrincl_swab_systoh (ip); - - iplen = ip->ip_len; - datalen = len - ip_hlen; - src = ip->ip_src; - - if (len != iplen) - { - zlog_err ("IRDP: RX length doesnt match IP length"); - return; - } - - if (iplen < ICMP_MINLEN) - { - zlog_err ("IRDP: RX ICMP packet too short from %s\n", - inet_ntoa (src)); - return; - } - - /* XXX: RAW doesnt receive link-layer, surely? ??? */ - /* Check so we don't checksum packets longer than oure RX_BUF - (ethlen + - len of IP-header) 14+20 */ - if (iplen > IRDP_RX_BUF-34) - { - zlog_err ("IRDP: RX ICMP packet too long from %s\n", - inet_ntoa (src)); - return; - } - - icmp = (struct icmphdr *) (p+ip_hlen); - - /* check icmp checksum */ - if (in_cksum (icmp, datalen) != icmp->checksum) - { - zlog_warn ("IRDP: RX ICMP packet from %s. Bad checksum, silently ignored", - inet_ntoa (src)); - return; - } - - /* Handle just only IRDP */ - if (!(icmp->type == ICMP_ROUTERADVERT - || icmp->type == ICMP_ROUTERSOLICIT)) - return; - - if (icmp->code != 0) - { - zlog_warn ("IRDP: RX packet type %d from %s. Bad ICMP type code," - " silently ignored", - icmp->type, inet_ntoa (src)); - return; - } - - if (! ((ntohl (ip->ip_dst.s_addr) == INADDR_BROADCAST) - && (irdp->flags & IF_BROADCAST)) - || - (ntohl (ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP - && !(irdp->flags & IF_BROADCAST))) - { - zlog_warn ("IRDP: RX illegal from %s to %s while %s operates in %s\n", - inet_ntoa (src), - ntohl (ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP ? - "multicast" : inet_ntoa (ip->ip_dst), - ifp->name, - irdp->flags & IF_BROADCAST ? "broadcast" : "multicast"); - - zlog_warn ("IRDP: Please correct settings\n"); - return; - } - - switch (icmp->type) - { - case ICMP_ROUTERADVERT: - break; - - case ICMP_ROUTERSOLICIT: - - if(irdp->flags & IF_DEBUG_MESSAGES) - zlog_debug ("IRDP: RX Solicit on %s from %s\n", - ifp->name, - inet_ntoa (src)); - - process_solicit(ifp); - break; - - default: - zlog_warn ("IRDP: RX type %d from %s. Bad ICMP type, silently ignored", - icmp->type, - inet_ntoa (src)); - } + struct ip *ip = (struct ip *)p; + struct icmphdr *icmp; + struct in_addr src; + int ip_hlen, iplen, datalen; + struct zebra_if *zi; + struct irdp_interface *irdp; + + zi = ifp->info; + if (!zi) + return; + + irdp = &zi->irdp; + if (!irdp) + return; + + ip_hlen = ip->ip_hl << 2; + + sockopt_iphdrincl_swab_systoh(ip); + + iplen = ip->ip_len; + datalen = len - ip_hlen; + src = ip->ip_src; + + if (len != iplen) { + zlog_err("IRDP: RX length doesnt match IP length"); + return; + } + + if (iplen < ICMP_MINLEN) { + zlog_err("IRDP: RX ICMP packet too short from %s\n", + inet_ntoa(src)); + return; + } + + /* XXX: RAW doesnt receive link-layer, surely? ??? */ + /* Check so we don't checksum packets longer than oure RX_BUF - (ethlen + + + len of IP-header) 14+20 */ + if (iplen > IRDP_RX_BUF - 34) { + zlog_err("IRDP: RX ICMP packet too long from %s\n", + inet_ntoa(src)); + return; + } + + icmp = (struct icmphdr *)(p + ip_hlen); + + /* check icmp checksum */ + if (in_cksum(icmp, datalen) != icmp->checksum) { + zlog_warn( + "IRDP: RX ICMP packet from %s. Bad checksum, silently ignored", + inet_ntoa(src)); + return; + } + + /* Handle just only IRDP */ + if (!(icmp->type == ICMP_ROUTERADVERT + || icmp->type == ICMP_ROUTERSOLICIT)) + return; + + if (icmp->code != 0) { + zlog_warn( + "IRDP: RX packet type %d from %s. Bad ICMP type code," + " silently ignored", + icmp->type, inet_ntoa(src)); + return; + } + + if (!((ntohl(ip->ip_dst.s_addr) == INADDR_BROADCAST) + && (irdp->flags & IF_BROADCAST)) + || (ntohl(ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP + && !(irdp->flags & IF_BROADCAST))) { + zlog_warn( + "IRDP: RX illegal from %s to %s while %s operates in %s\n", + inet_ntoa(src), + ntohl(ip->ip_dst.s_addr) == INADDR_ALLRTRS_GROUP + ? "multicast" + : inet_ntoa(ip->ip_dst), + ifp->name, + irdp->flags & IF_BROADCAST ? "broadcast" : "multicast"); + + zlog_warn("IRDP: Please correct settings\n"); + return; + } + + switch (icmp->type) { + case ICMP_ROUTERADVERT: + break; + + case ICMP_ROUTERSOLICIT: + + if (irdp->flags & IF_DEBUG_MESSAGES) + zlog_debug("IRDP: RX Solicit on %s from %s\n", + ifp->name, inet_ntoa(src)); + + process_solicit(ifp); + break; + + default: + zlog_warn( + "IRDP: RX type %d from %s. Bad ICMP type, silently ignored", + icmp->type, inet_ntoa(src)); + } } -static int -irdp_recvmsg (int sock, u_char *buf, int size, int *ifindex) +static int irdp_recvmsg(int sock, u_char *buf, int size, int *ifindex) { - struct msghdr msg; - struct iovec iov; - char adata[CMSG_SPACE( SOPT_SIZE_CMSG_PKTINFO_IPV4() )]; - int ret; - - msg.msg_name = (void *)0; - msg.msg_namelen = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = (void *) adata; - msg.msg_controllen = sizeof adata; - - iov.iov_base = buf; - iov.iov_len = size; - - ret = recvmsg (sock, &msg, 0); - if (ret < 0) { - zlog_warn("IRDP: recvmsg: read error %s", safe_strerror(errno)); - return ret; - } - - if (msg.msg_flags & MSG_TRUNC) { - zlog_warn("IRDP: recvmsg: truncated message"); - return ret; - } - if (msg.msg_flags & MSG_CTRUNC) { - zlog_warn("IRDP: recvmsg: truncated control message"); - return ret; - } - - *ifindex = getsockopt_ifindex (AF_INET, &msg); - - return ret; + struct msghdr msg; + struct iovec iov; + char adata[CMSG_SPACE(SOPT_SIZE_CMSG_PKTINFO_IPV4())]; + int ret; + + msg.msg_name = (void *)0; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = (void *)adata; + msg.msg_controllen = sizeof adata; + + iov.iov_base = buf; + iov.iov_len = size; + + ret = recvmsg(sock, &msg, 0); + if (ret < 0) { + zlog_warn("IRDP: recvmsg: read error %s", safe_strerror(errno)); + return ret; + } + + if (msg.msg_flags & MSG_TRUNC) { + zlog_warn("IRDP: recvmsg: truncated message"); + return ret; + } + if (msg.msg_flags & MSG_CTRUNC) { + zlog_warn("IRDP: recvmsg: truncated control message"); + return ret; + } + + *ifindex = getsockopt_ifindex(AF_INET, &msg); + + return ret; } int irdp_read_raw(struct thread *r) { - struct interface *ifp; - struct zebra_if *zi; - struct irdp_interface *irdp; - char buf[IRDP_RX_BUF]; - int ret, ifindex = 0; - - int irdp_sock = THREAD_FD (r); - t_irdp_raw = NULL; - thread_add_read(zebrad.master, irdp_read_raw, NULL, irdp_sock, &t_irdp_raw); - - ret = irdp_recvmsg (irdp_sock, (u_char *) buf, IRDP_RX_BUF, &ifindex); - - if (ret < 0) zlog_warn ("IRDP: RX Error length = %d", ret); - - ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); - if(! ifp ) return ret; - - zi= ifp->info; - if(! zi ) return ret; - - irdp = &zi->irdp; - if(! irdp ) return ret; - - if(! (irdp->flags & IF_ACTIVE)) { - - if(irdp->flags & IF_DEBUG_MISC) - zlog_debug("IRDP: RX ICMP for disabled interface %s\n", ifp->name); - return 0; - } - - if(irdp->flags & IF_DEBUG_PACKET) { - int i; - zlog_debug("IRDP: RX (idx %d) ", ifindex); - for(i=0; i < ret; i++) zlog_debug( "IRDP: RX %x ", buf[i]&0xFF); - } - - parse_irdp_packet(buf, ret, ifp); - - return ret; + struct interface *ifp; + struct zebra_if *zi; + struct irdp_interface *irdp; + char buf[IRDP_RX_BUF]; + int ret, ifindex = 0; + + int irdp_sock = THREAD_FD(r); + t_irdp_raw = NULL; + thread_add_read(zebrad.master, irdp_read_raw, NULL, irdp_sock, + &t_irdp_raw); + + ret = irdp_recvmsg(irdp_sock, (u_char *)buf, IRDP_RX_BUF, &ifindex); + + if (ret < 0) + zlog_warn("IRDP: RX Error length = %d", ret); + + ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); + if (!ifp) + return ret; + + zi = ifp->info; + if (!zi) + return ret; + + irdp = &zi->irdp; + if (!irdp) + return ret; + + if (!(irdp->flags & IF_ACTIVE)) { + + if (irdp->flags & IF_DEBUG_MISC) + zlog_debug("IRDP: RX ICMP for disabled interface %s\n", + ifp->name); + return 0; + } + + if (irdp->flags & IF_DEBUG_PACKET) { + int i; + zlog_debug("IRDP: RX (idx %d) ", ifindex); + for (i = 0; i < ret; i++) + zlog_debug("IRDP: RX %x ", buf[i] & 0xFF); + } + + parse_irdp_packet(buf, ret, ifp); + + return ret; } -void -send_packet(struct interface *ifp, - struct stream *s, - u_int32_t dst, - struct prefix *p, - u_int32_t ttl) +void send_packet(struct interface *ifp, struct stream *s, u_int32_t dst, + struct prefix *p, u_int32_t ttl) { - static struct sockaddr_in sockdst = {AF_INET}; - struct ip *ip; - struct icmphdr *icmp; - struct msghdr *msg; - struct cmsghdr *cmsg; - struct iovec iovector; - char msgbuf[256]; - char buf[256]; - struct in_pktinfo *pktinfo; - u_long src; - u_char on; - - if (!(ifp->flags & IFF_UP)) - return; - - if (p) - src = ntohl(p->u.prefix4.s_addr); - else - src = 0; /* Is filled in */ - - ip = (struct ip *) buf; - ip->ip_hl = sizeof(struct ip) >> 2; - ip->ip_v = IPVERSION; - ip->ip_tos = 0xC0; - ip->ip_off = 0L; - ip->ip_p = 1; /* IP_ICMP */ - ip->ip_ttl = ttl; - ip->ip_src.s_addr = src; - ip->ip_dst.s_addr = dst; - icmp = (struct icmphdr *) (buf + sizeof (struct ip)); - - /* Merge IP header with icmp packet */ - assert (stream_get_endp(s) < (sizeof (buf) - sizeof (struct ip))); - stream_get(icmp, s, stream_get_endp(s)); - - /* icmp->checksum is already calculated */ - ip->ip_len = sizeof(struct ip) + stream_get_endp(s); - - on = 1; - if (setsockopt(irdp_sock, IPPROTO_IP, IP_HDRINCL, - (char *) &on, sizeof(on)) < 0) - zlog_warn("sendto %s", safe_strerror (errno)); - - - if(dst == INADDR_BROADCAST ) { - on = 1; - if (setsockopt(irdp_sock, SOL_SOCKET, SO_BROADCAST, - (char *) &on, sizeof(on)) < 0) - zlog_warn("sendto %s", safe_strerror (errno)); - } - - if(dst != INADDR_BROADCAST) - setsockopt_ipv4_multicast_loop (irdp_sock, 0); - - memset(&sockdst,0,sizeof(sockdst)); - sockdst.sin_family=AF_INET; - sockdst.sin_addr.s_addr = dst; - - cmsg = (struct cmsghdr *) (msgbuf + sizeof(struct msghdr)); - cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(struct in_pktinfo); - cmsg->cmsg_level = SOL_IP; - cmsg->cmsg_type = IP_PKTINFO; - pktinfo = (struct in_pktinfo *) CMSG_DATA(cmsg); - pktinfo->ipi_ifindex = ifp->ifindex; - pktinfo->ipi_spec_dst.s_addr = src; - pktinfo->ipi_addr.s_addr = src; - - iovector.iov_base = (void *) buf; - iovector.iov_len = ip->ip_len; - msg = (struct msghdr *) msgbuf; - msg->msg_name = &sockdst; - msg->msg_namelen = sizeof(sockdst); - msg->msg_iov = &iovector; - msg->msg_iovlen = 1; - msg->msg_control = cmsg; - msg->msg_controllen = cmsg->cmsg_len; - - sockopt_iphdrincl_swab_htosys (ip); - - if (sendmsg(irdp_sock, msg, 0) < 0) { - zlog_warn("sendto %s", safe_strerror (errno)); - } - /* printf("TX on %s idx %d\n", ifp->name, ifp->ifindex); */ + static struct sockaddr_in sockdst = {AF_INET}; + struct ip *ip; + struct icmphdr *icmp; + struct msghdr *msg; + struct cmsghdr *cmsg; + struct iovec iovector; + char msgbuf[256]; + char buf[256]; + struct in_pktinfo *pktinfo; + u_long src; + u_char on; + + if (!(ifp->flags & IFF_UP)) + return; + + if (p) + src = ntohl(p->u.prefix4.s_addr); + else + src = 0; /* Is filled in */ + + ip = (struct ip *)buf; + ip->ip_hl = sizeof(struct ip) >> 2; + ip->ip_v = IPVERSION; + ip->ip_tos = 0xC0; + ip->ip_off = 0L; + ip->ip_p = 1; /* IP_ICMP */ + ip->ip_ttl = ttl; + ip->ip_src.s_addr = src; + ip->ip_dst.s_addr = dst; + icmp = (struct icmphdr *)(buf + sizeof(struct ip)); + + /* Merge IP header with icmp packet */ + assert(stream_get_endp(s) < (sizeof(buf) - sizeof(struct ip))); + stream_get(icmp, s, stream_get_endp(s)); + + /* icmp->checksum is already calculated */ + ip->ip_len = sizeof(struct ip) + stream_get_endp(s); + + on = 1; + if (setsockopt(irdp_sock, IPPROTO_IP, IP_HDRINCL, (char *)&on, + sizeof(on)) + < 0) + zlog_warn("sendto %s", safe_strerror(errno)); + + + if (dst == INADDR_BROADCAST) { + on = 1; + if (setsockopt(irdp_sock, SOL_SOCKET, SO_BROADCAST, (char *)&on, + sizeof(on)) + < 0) + zlog_warn("sendto %s", safe_strerror(errno)); + } + + if (dst != INADDR_BROADCAST) + setsockopt_ipv4_multicast_loop(irdp_sock, 0); + + memset(&sockdst, 0, sizeof(sockdst)); + sockdst.sin_family = AF_INET; + sockdst.sin_addr.s_addr = dst; + + cmsg = (struct cmsghdr *)(msgbuf + sizeof(struct msghdr)); + cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(struct in_pktinfo); + cmsg->cmsg_level = SOL_IP; + cmsg->cmsg_type = IP_PKTINFO; + pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg); + pktinfo->ipi_ifindex = ifp->ifindex; + pktinfo->ipi_spec_dst.s_addr = src; + pktinfo->ipi_addr.s_addr = src; + + iovector.iov_base = (void *)buf; + iovector.iov_len = ip->ip_len; + msg = (struct msghdr *)msgbuf; + msg->msg_name = &sockdst; + msg->msg_namelen = sizeof(sockdst); + msg->msg_iov = &iovector; + msg->msg_iovlen = 1; + msg->msg_control = cmsg; + msg->msg_controllen = cmsg->cmsg_len; + + sockopt_iphdrincl_swab_htosys(ip); + + if (sendmsg(irdp_sock, msg, 0) < 0) { + zlog_warn("sendto %s", safe_strerror(errno)); + } + /* printf("TX on %s idx %d\n", ifp->name, ifp->ifindex); */ } #endif /* HAVE_IRDP */ - - - diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 91d4946b5..7fc2d6133 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -53,13 +53,13 @@ #endif /* MSG_TRUNC */ #ifndef NLMSG_TAIL -#define NLMSG_TAIL(nmsg) \ - ((struct rtattr *) (((u_char *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) +#define NLMSG_TAIL(nmsg) \ + ((struct rtattr *)(((u_char *)(nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) #endif #ifndef RTA_TAIL -#define RTA_TAIL(rta) \ - ((struct rtattr *) (((u_char *) (rta)) + RTA_ALIGN((rta)->rta_len))) +#define RTA_TAIL(rta) \ + ((struct rtattr *)(((u_char *)(rta)) + RTA_ALIGN((rta)->rta_len))) #endif #ifndef RTNL_FAMILY_IP6MR @@ -70,396 +70,368 @@ #define RTPROT_MROUTED 17 #endif -static const struct message nlmsg_str[] = { - {RTM_NEWROUTE, "RTM_NEWROUTE"}, - {RTM_DELROUTE, "RTM_DELROUTE"}, - {RTM_GETROUTE, "RTM_GETROUTE"}, - {RTM_NEWLINK, "RTM_NEWLINK"}, - {RTM_DELLINK, "RTM_DELLINK"}, - {RTM_GETLINK, "RTM_GETLINK"}, - {RTM_NEWADDR, "RTM_NEWADDR"}, - {RTM_DELADDR, "RTM_DELADDR"}, - {RTM_GETADDR, "RTM_GETADDR"}, - {RTM_NEWNEIGH, "RTM_NEWNEIGH"}, - {RTM_DELNEIGH, "RTM_DELNEIGH"}, - {RTM_GETNEIGH, "RTM_GETNEIGH"}, - { 0 } -}; +static const struct message nlmsg_str[] = {{RTM_NEWROUTE, "RTM_NEWROUTE"}, + {RTM_DELROUTE, "RTM_DELROUTE"}, + {RTM_GETROUTE, "RTM_GETROUTE"}, + {RTM_NEWLINK, "RTM_NEWLINK"}, + {RTM_DELLINK, "RTM_DELLINK"}, + {RTM_GETLINK, "RTM_GETLINK"}, + {RTM_NEWADDR, "RTM_NEWADDR"}, + {RTM_DELADDR, "RTM_DELADDR"}, + {RTM_GETADDR, "RTM_GETADDR"}, + {RTM_NEWNEIGH, "RTM_NEWNEIGH"}, + {RTM_DELNEIGH, "RTM_DELNEIGH"}, + {RTM_GETNEIGH, "RTM_GETNEIGH"}, + {0}}; static const struct message rtproto_str[] = { - {RTPROT_REDIRECT, "redirect"}, - {RTPROT_KERNEL, "kernel"}, - {RTPROT_BOOT, "boot"}, - {RTPROT_STATIC, "static"}, - {RTPROT_GATED, "GateD"}, - {RTPROT_RA, "router advertisement"}, - {RTPROT_MRT, "MRT"}, - {RTPROT_ZEBRA, "Zebra"}, + {RTPROT_REDIRECT, "redirect"}, + {RTPROT_KERNEL, "kernel"}, + {RTPROT_BOOT, "boot"}, + {RTPROT_STATIC, "static"}, + {RTPROT_GATED, "GateD"}, + {RTPROT_RA, "router advertisement"}, + {RTPROT_MRT, "MRT"}, + {RTPROT_ZEBRA, "Zebra"}, #ifdef RTPROT_BIRD - {RTPROT_BIRD, "BIRD"}, + {RTPROT_BIRD, "BIRD"}, #endif /* RTPROT_BIRD */ - {RTPROT_MROUTED, "mroute"}, - {RTPROT_BGP, "BGP"}, - {RTPROT_OSPF, "OSPF"}, - {RTPROT_ISIS, "IS-IS"}, - {RTPROT_RIP, "RIP"}, - {RTPROT_RIPNG, "RIPNG"}, - { 0 } -}; - -static const struct message family_str[] = { - {AF_INET, "ipv4"}, - {AF_INET6, "ipv6"}, - {AF_BRIDGE, "bridge"}, - {RTNL_FAMILY_IPMR, "ipv4MR"}, - {RTNL_FAMILY_IP6MR, "ipv6MR"}, - { 0 } -}; - -static const struct message rttype_str[] = { - {RTN_UNICAST, "unicast"}, - {RTN_MULTICAST, "multicast"}, - { 0 } -}; + {RTPROT_MROUTED, "mroute"}, + {RTPROT_BGP, "BGP"}, + {RTPROT_OSPF, "OSPF"}, + {RTPROT_ISIS, "IS-IS"}, + {RTPROT_RIP, "RIP"}, + {RTPROT_RIPNG, "RIPNG"}, + {0}}; + +static const struct message family_str[] = {{AF_INET, "ipv4"}, + {AF_INET6, "ipv6"}, + {AF_BRIDGE, "bridge"}, + {RTNL_FAMILY_IPMR, "ipv4MR"}, + {RTNL_FAMILY_IP6MR, "ipv6MR"}, + {0}}; + +static const struct message rttype_str[] = {{RTN_UNICAST, "unicast"}, + {RTN_MULTICAST, "multicast"}, + {0}}; extern struct thread_master *master; extern u_int32_t nl_rcvbufsize; extern struct zebra_privs_t zserv_privs; -int -netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +int netlink_talk_filter(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup) { - zlog_warn ("netlink_talk: ignoring message type 0x%04x NS %u", h->nlmsg_type, - ns_id); - return 0; + zlog_warn("netlink_talk: ignoring message type 0x%04x NS %u", + h->nlmsg_type, ns_id); + return 0; } -static int -netlink_recvbuf (struct nlsock *nl, uint32_t newsize) +static int netlink_recvbuf(struct nlsock *nl, uint32_t newsize) { - u_int32_t oldsize; - socklen_t newlen = sizeof(newsize); - socklen_t oldlen = sizeof(oldsize); - int ret; - - ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &oldsize, &oldlen); - if (ret < 0) - { - zlog_err("Can't get %s receive buffer size: %s", nl->name, - safe_strerror(errno)); - return -1; - } - - /* Try force option (linux >= 2.6.14) and fall back to normal set */ - if ( zserv_privs.change (ZPRIVS_RAISE) ) - zlog_err ("routing_socket: Can't raise privileges"); - ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUFFORCE, &nl_rcvbufsize, - sizeof(nl_rcvbufsize)); - if ( zserv_privs.change (ZPRIVS_LOWER) ) - zlog_err ("routing_socket: Can't lower privileges"); - if (ret < 0) - ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &nl_rcvbufsize, - sizeof(nl_rcvbufsize)); - if (ret < 0) - { - zlog_err("Can't set %s receive buffer size: %s", nl->name, - safe_strerror(errno)); - return -1; - } - - ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &newsize, &newlen); - if (ret < 0) - { - zlog_err("Can't get %s receive buffer size: %s", nl->name, - safe_strerror(errno)); - return -1; - } - - zlog_info("Setting netlink socket receive buffer size: %u -> %u", oldsize, - newsize); - return 0; + u_int32_t oldsize; + socklen_t newlen = sizeof(newsize); + socklen_t oldlen = sizeof(oldsize); + int ret; + + ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &oldsize, &oldlen); + if (ret < 0) { + zlog_err("Can't get %s receive buffer size: %s", nl->name, + safe_strerror(errno)); + return -1; + } + + /* Try force option (linux >= 2.6.14) and fall back to normal set */ + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("routing_socket: Can't raise privileges"); + ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUFFORCE, &nl_rcvbufsize, + sizeof(nl_rcvbufsize)); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("routing_socket: Can't lower privileges"); + if (ret < 0) + ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, + &nl_rcvbufsize, sizeof(nl_rcvbufsize)); + if (ret < 0) { + zlog_err("Can't set %s receive buffer size: %s", nl->name, + safe_strerror(errno)); + return -1; + } + + ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &newsize, &newlen); + if (ret < 0) { + zlog_err("Can't get %s receive buffer size: %s", nl->name, + safe_strerror(errno)); + return -1; + } + + zlog_info("Setting netlink socket receive buffer size: %u -> %u", + oldsize, newsize); + return 0; } /* Make socket for Linux netlink interface. */ -static int -netlink_socket (struct nlsock *nl, unsigned long groups, ns_id_t ns_id) +static int netlink_socket(struct nlsock *nl, unsigned long groups, + ns_id_t ns_id) { - int ret; - struct sockaddr_nl snl; - int sock; - int namelen; - int save_errno; - - if (zserv_privs.change (ZPRIVS_RAISE)) - { - zlog_err("Can't raise privileges"); - return -1; - } - - sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (sock < 0) - { - zlog_err("Can't open %s socket: %s", nl->name, safe_strerror(errno)); - return -1; - } - - memset (&snl, 0, sizeof snl); - snl.nl_family = AF_NETLINK; - snl.nl_groups = groups; - - /* Bind the socket to the netlink structure for anything. */ - ret = bind (sock, (struct sockaddr *) &snl, sizeof snl); - save_errno = errno; - if (zserv_privs.change (ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - - if (ret < 0) - { - zlog_err("Can't bind %s socket to group 0x%x: %s", nl->name, - snl.nl_groups, safe_strerror(save_errno)); - close (sock); - return -1; - } - - /* multiple netlink sockets will have different nl_pid */ - namelen = sizeof snl; - ret = getsockname (sock, (struct sockaddr *) &snl, (socklen_t *) &namelen); - if (ret < 0 || namelen != sizeof snl) - { - zlog_err("Can't get %s socket name: %s", nl->name, safe_strerror(errno)); - close (sock); - return -1; - } - - nl->snl = snl; - nl->sock = sock; - return ret; + int ret; + struct sockaddr_nl snl; + int sock; + int namelen; + int save_errno; + + if (zserv_privs.change(ZPRIVS_RAISE)) { + zlog_err("Can't raise privileges"); + return -1; + } + + sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (sock < 0) { + zlog_err("Can't open %s socket: %s", nl->name, + safe_strerror(errno)); + return -1; + } + + memset(&snl, 0, sizeof snl); + snl.nl_family = AF_NETLINK; + snl.nl_groups = groups; + + /* Bind the socket to the netlink structure for anything. */ + ret = bind(sock, (struct sockaddr *)&snl, sizeof snl); + save_errno = errno; + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + if (ret < 0) { + zlog_err("Can't bind %s socket to group 0x%x: %s", nl->name, + snl.nl_groups, safe_strerror(save_errno)); + close(sock); + return -1; + } + + /* multiple netlink sockets will have different nl_pid */ + namelen = sizeof snl; + ret = getsockname(sock, (struct sockaddr *)&snl, (socklen_t *)&namelen); + if (ret < 0 || namelen != sizeof snl) { + zlog_err("Can't get %s socket name: %s", nl->name, + safe_strerror(errno)); + close(sock); + return -1; + } + + nl->snl = snl; + nl->sock = sock; + return ret; } -static int -netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +static int netlink_information_fetch(struct sockaddr_nl *snl, + struct nlmsghdr *h, ns_id_t ns_id, + int startup) { - /* JF: Ignore messages that aren't from the kernel */ - if ( snl->nl_pid != 0 ) - { - zlog_err("Ignoring message from pid %u", snl->nl_pid); - return 0; - } - - switch (h->nlmsg_type) - { - case RTM_NEWROUTE: - return netlink_route_change (snl, h, ns_id, startup); - break; - case RTM_DELROUTE: - return netlink_route_change (snl, h, ns_id, startup); - break; - case RTM_NEWLINK: - return netlink_link_change (snl, h, ns_id, startup); - break; - case RTM_DELLINK: - return netlink_link_change (snl, h, ns_id, startup); - break; - case RTM_NEWADDR: - return netlink_interface_addr (snl, h, ns_id, startup); - break; - case RTM_DELADDR: - return netlink_interface_addr (snl, h, ns_id, startup); - break; - case RTM_NEWNEIGH: - return netlink_neigh_change (snl, h, ns_id); - break; - case RTM_DELNEIGH: - return netlink_neigh_change (snl, h, ns_id); - break; - default: - zlog_warn ("Unknown netlink nlmsg_type %d vrf %u\n", h->nlmsg_type, - ns_id); - break; - } - return 0; + /* JF: Ignore messages that aren't from the kernel */ + if (snl->nl_pid != 0) { + zlog_err("Ignoring message from pid %u", snl->nl_pid); + return 0; + } + + switch (h->nlmsg_type) { + case RTM_NEWROUTE: + return netlink_route_change(snl, h, ns_id, startup); + break; + case RTM_DELROUTE: + return netlink_route_change(snl, h, ns_id, startup); + break; + case RTM_NEWLINK: + return netlink_link_change(snl, h, ns_id, startup); + break; + case RTM_DELLINK: + return netlink_link_change(snl, h, ns_id, startup); + break; + case RTM_NEWADDR: + return netlink_interface_addr(snl, h, ns_id, startup); + break; + case RTM_DELADDR: + return netlink_interface_addr(snl, h, ns_id, startup); + break; + case RTM_NEWNEIGH: + return netlink_neigh_change(snl, h, ns_id); + break; + case RTM_DELNEIGH: + return netlink_neigh_change(snl, h, ns_id); + break; + default: + zlog_warn("Unknown netlink nlmsg_type %d vrf %u\n", + h->nlmsg_type, ns_id); + break; + } + return 0; } -static int -kernel_read (struct thread *thread) +static int kernel_read(struct thread *thread) { - struct zebra_ns *zns = (struct zebra_ns *)THREAD_ARG (thread); - netlink_parse_info (netlink_information_fetch, &zns->netlink, zns, 5, 0); - zns->t_netlink = NULL; - thread_add_read(zebrad.master, kernel_read, zns, zns->netlink.sock, - &zns->t_netlink); + struct zebra_ns *zns = (struct zebra_ns *)THREAD_ARG(thread); + netlink_parse_info(netlink_information_fetch, &zns->netlink, zns, 5, 0); + zns->t_netlink = NULL; + thread_add_read(zebrad.master, kernel_read, zns, zns->netlink.sock, + &zns->t_netlink); - return 0; + return 0; } /* Filter out messages from self that occur on listener socket, * caused by our actions on the command socket */ -static void netlink_install_filter (int sock, __u32 pid) +static void netlink_install_filter(int sock, __u32 pid) { - struct sock_filter filter[] = { - /* 0: ldh [4] */ - BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)), - /* 1: jeq 0x18 jt 5 jf next */ - BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 3, 0), - /* 2: jeq 0x19 jt 5 jf next */ - BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 2, 0), - /* 3: jeq 0x19 jt 5 jf next */ - BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWNEIGH), 1, 0), - /* 4: jeq 0x19 jt 5 jf 8 */ - BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELNEIGH), 0, 3), - /* 5: ldw [12] */ - BPF_STMT(BPF_LD|BPF_ABS|BPF_W, offsetof(struct nlmsghdr, nlmsg_pid)), - /* 6: jeq XX jt 7 jf 8 */ - BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htonl(pid), 0, 1), - /* 7: ret 0 (skip) */ - BPF_STMT(BPF_RET|BPF_K, 0), - /* 8: ret 0xffff (keep) */ - BPF_STMT(BPF_RET|BPF_K, 0xffff), - }; - - struct sock_fprog prog = { - .len = array_size(filter), - .filter = filter, - }; - - if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)) < 0) - zlog_warn ("Can't install socket filter: %s\n", safe_strerror(errno)); + struct sock_filter filter[] = { + /* 0: ldh [4] */ + BPF_STMT(BPF_LD | BPF_ABS | BPF_H, + offsetof(struct nlmsghdr, nlmsg_type)), + /* 1: jeq 0x18 jt 5 jf next */ + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htons(RTM_NEWROUTE), 3, 0), + /* 2: jeq 0x19 jt 5 jf next */ + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htons(RTM_DELROUTE), 2, 0), + /* 3: jeq 0x19 jt 5 jf next */ + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htons(RTM_NEWNEIGH), 1, 0), + /* 4: jeq 0x19 jt 5 jf 8 */ + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htons(RTM_DELNEIGH), 0, 3), + /* 5: ldw [12] */ + BPF_STMT(BPF_LD | BPF_ABS | BPF_W, + offsetof(struct nlmsghdr, nlmsg_pid)), + /* 6: jeq XX jt 7 jf 8 */ + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htonl(pid), 0, 1), + /* 7: ret 0 (skip) */ + BPF_STMT(BPF_RET | BPF_K, 0), + /* 8: ret 0xffff (keep) */ + BPF_STMT(BPF_RET | BPF_K, 0xffff), + }; + + struct sock_fprog prog = { + .len = array_size(filter), .filter = filter, + }; + + if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog)) + < 0) + zlog_warn("Can't install socket filter: %s\n", + safe_strerror(errno)); } -void -netlink_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta, - int len) +void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, + int len) { - while (RTA_OK (rta, len)) - { - if (rta->rta_type <= max) - tb[rta->rta_type] = rta; - rta = RTA_NEXT (rta, len); - } + while (RTA_OK(rta, len)) { + if (rta->rta_type <= max) + tb[rta->rta_type] = rta; + rta = RTA_NEXT(rta, len); + } } -int -addattr_l (struct nlmsghdr *n, unsigned int maxlen, int type, - void *data, unsigned int alen) +int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type, void *data, + unsigned int alen) { - int len; - struct rtattr *rta; + int len; + struct rtattr *rta; - len = RTA_LENGTH (alen); + len = RTA_LENGTH(alen); - if (NLMSG_ALIGN (n->nlmsg_len) + RTA_ALIGN (len) > maxlen) - return -1; + if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) + return -1; - rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len)); - rta->rta_type = type; - rta->rta_len = len; + rta = (struct rtattr *)(((char *)n) + NLMSG_ALIGN(n->nlmsg_len)); + rta->rta_type = type; + rta->rta_len = len; - if (data) - memcpy (RTA_DATA (rta), data, alen); - else - assert (alen == 0); + if (data) + memcpy(RTA_DATA(rta), data, alen); + else + assert(alen == 0); - n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + RTA_ALIGN (len); + n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); - return 0; + return 0; } -int -rta_addattr_l (struct rtattr *rta, unsigned int maxlen, int type, - void *data, unsigned int alen) +int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type, void *data, + unsigned int alen) { - unsigned int len; - struct rtattr *subrta; + unsigned int len; + struct rtattr *subrta; - len = RTA_LENGTH (alen); + len = RTA_LENGTH(alen); - if (RTA_ALIGN (rta->rta_len) + RTA_ALIGN (len) > maxlen) - return -1; + if (RTA_ALIGN(rta->rta_len) + RTA_ALIGN(len) > maxlen) + return -1; - subrta = (struct rtattr *) (((char *) rta) + RTA_ALIGN (rta->rta_len)); - subrta->rta_type = type; - subrta->rta_len = len; + subrta = (struct rtattr *)(((char *)rta) + RTA_ALIGN(rta->rta_len)); + subrta->rta_type = type; + subrta->rta_len = len; - if (data) - memcpy (RTA_DATA (subrta), data, alen); - else - assert (alen == 0); + if (data) + memcpy(RTA_DATA(subrta), data, alen); + else + assert(alen == 0); - rta->rta_len = NLMSG_ALIGN (rta->rta_len) + RTA_ALIGN (len); + rta->rta_len = NLMSG_ALIGN(rta->rta_len) + RTA_ALIGN(len); - return 0; + return 0; } -int -addattr16 (struct nlmsghdr *n, unsigned int maxlen, int type, u_int16_t data) +int addattr16(struct nlmsghdr *n, unsigned int maxlen, int type, u_int16_t data) { - return addattr_l(n, maxlen, type, &data, sizeof(u_int16_t)); + return addattr_l(n, maxlen, type, &data, sizeof(u_int16_t)); } -int -addattr32 (struct nlmsghdr *n, unsigned int maxlen, int type, int data) +int addattr32(struct nlmsghdr *n, unsigned int maxlen, int type, int data) { - return addattr_l(n, maxlen, type, &data, sizeof(u_int32_t)); + return addattr_l(n, maxlen, type, &data, sizeof(u_int32_t)); } -struct rtattr * -addattr_nest(struct nlmsghdr *n, int maxlen, int type) +struct rtattr *addattr_nest(struct nlmsghdr *n, int maxlen, int type) { - struct rtattr *nest = NLMSG_TAIL(n); + struct rtattr *nest = NLMSG_TAIL(n); - addattr_l(n, maxlen, type, NULL, 0); - return nest; + addattr_l(n, maxlen, type, NULL, 0); + return nest; } -int -addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest) +int addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest) { - nest->rta_len = (u_char *)NLMSG_TAIL(n) - (u_char *)nest; - return n->nlmsg_len; + nest->rta_len = (u_char *)NLMSG_TAIL(n) - (u_char *)nest; + return n->nlmsg_len; } -struct rtattr * -rta_nest(struct rtattr *rta, int maxlen, int type) +struct rtattr *rta_nest(struct rtattr *rta, int maxlen, int type) { - struct rtattr *nest = RTA_TAIL(rta); + struct rtattr *nest = RTA_TAIL(rta); - rta_addattr_l(rta, maxlen, type, NULL, 0); - return nest; + rta_addattr_l(rta, maxlen, type, NULL, 0); + return nest; } -int -rta_nest_end(struct rtattr *rta, struct rtattr *nest) +int rta_nest_end(struct rtattr *rta, struct rtattr *nest) { - nest->rta_len = (u_char *)RTA_TAIL(rta) - (u_char *)nest; - return rta->rta_len; + nest->rta_len = (u_char *)RTA_TAIL(rta) - (u_char *)nest; + return rta->rta_len; } -const char * -nl_msg_type_to_str (uint16_t msg_type) +const char *nl_msg_type_to_str(uint16_t msg_type) { - return lookup_msg (nlmsg_str, msg_type, ""); + return lookup_msg(nlmsg_str, msg_type, ""); } -const char * -nl_rtproto_to_str (u_char rtproto) +const char *nl_rtproto_to_str(u_char rtproto) { - return lookup_msg (rtproto_str, rtproto, ""); + return lookup_msg(rtproto_str, rtproto, ""); } -const char * -nl_family_to_str (u_char family) +const char *nl_family_to_str(u_char family) { - return lookup_msg (family_str, family, ""); + return lookup_msg(family_str, family, ""); } -const char * -nl_rttype_to_str (u_char rttype) +const char *nl_rttype_to_str(u_char rttype) { - return lookup_msg (rttype_str, rttype, ""); + return lookup_msg(rttype_str, rttype, ""); } /* @@ -475,192 +447,210 @@ nl_rttype_to_str (u_char rttype) * startup -> Are we reading in under startup conditions? passed to * the filter. */ -int -netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, - ns_id_t, int), - struct nlsock *nl, struct zebra_ns *zns, int count, int startup) +int netlink_parse_info(int (*filter)(struct sockaddr_nl *, struct nlmsghdr *, + ns_id_t, int), + struct nlsock *nl, struct zebra_ns *zns, int count, + int startup) { - int status; - int ret = 0; - int error; - int read_in = 0; - - while (1) - { - char buf[NL_PKT_BUF_SIZE]; - struct iovec iov = { - .iov_base = buf, - .iov_len = sizeof buf - }; - struct sockaddr_nl snl; - struct msghdr msg = { - .msg_name = (void *) &snl, - .msg_namelen = sizeof snl, - .msg_iov = &iov, - .msg_iovlen = 1 - }; - struct nlmsghdr *h; - - if (count && read_in >= count) - return 0; - - status = recvmsg (nl->sock, &msg, 0); - if (status < 0) - { - if (errno == EINTR) - continue; - if (errno == EWOULDBLOCK || errno == EAGAIN) - break; - zlog_err("%s recvmsg overrun: %s", nl->name, safe_strerror(errno)); - /* - * In this case we are screwed. - * There is no good way to - * recover zebra at this point. - */ - exit (-1); - continue; - } - - if (status == 0) - { - zlog_err("%s EOF", nl->name); - return -1; - } - - if (msg.msg_namelen != sizeof snl) - { - zlog_err("%s sender address length error: length %d", nl->name, - msg.msg_namelen); - return -1; - } - - if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) - { - zlog_debug("%s: << netlink message dump [recv]", __func__); - zlog_hexdump(buf, status); - } - - read_in++; - for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, (unsigned int) status); - h = NLMSG_NEXT (h, status)) - { - /* Finish of reading. */ - if (h->nlmsg_type == NLMSG_DONE) - return ret; - - /* Error handling. */ - if (h->nlmsg_type == NLMSG_ERROR) - { - struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h); - int errnum = err->error; - int msg_type = err->msg.nlmsg_type; - - /* If the error field is zero, then this is an ACK */ - if (err->error == 0) - { - if (IS_ZEBRA_DEBUG_KERNEL) - { - zlog_debug ("%s: %s ACK: type=%s(%u), seq=%u, pid=%u", - __FUNCTION__, nl->name, - nl_msg_type_to_str (err->msg.nlmsg_type), - err->msg.nlmsg_type, err->msg.nlmsg_seq, - err->msg.nlmsg_pid); - } - - /* return if not a multipart message, otherwise continue */ - if (!(h->nlmsg_flags & NLM_F_MULTI)) - return 0; - continue; - } - - if (h->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr))) - { - zlog_err("%s error: message truncated", nl->name); - return -1; - } - - /* Deal with errors that occur because of races in link handling */ - if (nl == &zns->netlink_cmd - && ((msg_type == RTM_DELROUTE && - (-errnum == ENODEV || -errnum == ESRCH)) - || (msg_type == RTM_NEWROUTE && - (-errnum == ENETDOWN || -errnum == EEXIST)))) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: error: %s type=%s(%u), seq=%u, pid=%u", - nl->name, safe_strerror (-errnum), - nl_msg_type_to_str (msg_type), - msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid); - return 0; + int status; + int ret = 0; + int error; + int read_in = 0; + + while (1) { + char buf[NL_PKT_BUF_SIZE]; + struct iovec iov = {.iov_base = buf, .iov_len = sizeof buf}; + struct sockaddr_nl snl; + struct msghdr msg = {.msg_name = (void *)&snl, + .msg_namelen = sizeof snl, + .msg_iov = &iov, + .msg_iovlen = 1}; + struct nlmsghdr *h; + + if (count && read_in >= count) + return 0; + + status = recvmsg(nl->sock, &msg, 0); + if (status < 0) { + if (errno == EINTR) + continue; + if (errno == EWOULDBLOCK || errno == EAGAIN) + break; + zlog_err("%s recvmsg overrun: %s", nl->name, + safe_strerror(errno)); + /* + * In this case we are screwed. + * There is no good way to + * recover zebra at this point. + */ + exit(-1); + continue; } - /* We see RTM_DELNEIGH when shutting down an interface with an IPv4 - * link-local. The kernel should have already deleted the neighbor - * so do not log these as an error. - */ - if (msg_type == RTM_DELNEIGH || - (nl == &zns->netlink_cmd && msg_type == RTM_NEWROUTE && - (-errnum == ESRCH || -errnum == ENETUNREACH))) - { - /* This is known to happen in some situations, don't log - * as error. - */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s error: %s, type=%s(%u), seq=%u, pid=%u", - nl->name, safe_strerror (-errnum), - nl_msg_type_to_str (msg_type), - msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid); - } - else - zlog_err ("%s error: %s, type=%s(%u), seq=%u, pid=%u", - nl->name, safe_strerror (-errnum), - nl_msg_type_to_str (msg_type), - msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid); - - return -1; - } - - /* OK we got netlink message. */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("netlink_parse_info: %s type %s(%u), len=%d, seq=%u, pid=%u", - nl->name, - nl_msg_type_to_str (h->nlmsg_type), h->nlmsg_type, - h->nlmsg_len, h->nlmsg_seq, h->nlmsg_pid); - - /* skip unsolicited messages originating from command socket - * linux sets the originators port-id for {NEW|DEL}ADDR messages, - * so this has to be checked here. */ - if (nl != &zns->netlink_cmd - && h->nlmsg_pid == zns->netlink_cmd.snl.nl_pid - && (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("netlink_parse_info: %s packet comes from %s", - zns->netlink_cmd.name, nl->name); - continue; - } - - error = (*filter) (&snl, h, zns->ns_id, startup); - if (error < 0) - { - zlog_err("%s filter function error", nl->name); - ret = error; - } - } - - /* After error care. */ - if (msg.msg_flags & MSG_TRUNC) - { - zlog_err("%s error: message truncated", nl->name); - continue; - } - if (status) - { - zlog_err("%s error: data remnant size %d", nl->name, status); - return -1; - } - } - return ret; + if (status == 0) { + zlog_err("%s EOF", nl->name); + return -1; + } + + if (msg.msg_namelen != sizeof snl) { + zlog_err("%s sender address length error: length %d", + nl->name, msg.msg_namelen); + return -1; + } + + if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) { + zlog_debug("%s: << netlink message dump [recv]", + __func__); + zlog_hexdump(buf, status); + } + + read_in++; + for (h = (struct nlmsghdr *)buf; + NLMSG_OK(h, (unsigned int)status); + h = NLMSG_NEXT(h, status)) { + /* Finish of reading. */ + if (h->nlmsg_type == NLMSG_DONE) + return ret; + + /* Error handling. */ + if (h->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = + (struct nlmsgerr *)NLMSG_DATA(h); + int errnum = err->error; + int msg_type = err->msg.nlmsg_type; + + /* If the error field is zero, then this is an + * ACK */ + if (err->error == 0) { + if (IS_ZEBRA_DEBUG_KERNEL) { + zlog_debug( + "%s: %s ACK: type=%s(%u), seq=%u, pid=%u", + __FUNCTION__, nl->name, + nl_msg_type_to_str( + err->msg.nlmsg_type), + err->msg.nlmsg_type, + err->msg.nlmsg_seq, + err->msg.nlmsg_pid); + } + + /* return if not a multipart message, + * otherwise continue */ + if (!(h->nlmsg_flags & NLM_F_MULTI)) + return 0; + continue; + } + + if (h->nlmsg_len + < NLMSG_LENGTH(sizeof(struct nlmsgerr))) { + zlog_err("%s error: message truncated", + nl->name); + return -1; + } + + /* Deal with errors that occur because of races + * in link handling */ + if (nl == &zns->netlink_cmd + && ((msg_type == RTM_DELROUTE + && (-errnum == ENODEV + || -errnum == ESRCH)) + || (msg_type == RTM_NEWROUTE + && (-errnum == ENETDOWN + || -errnum == EEXIST)))) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "%s: error: %s type=%s(%u), seq=%u, pid=%u", + nl->name, + safe_strerror(-errnum), + nl_msg_type_to_str( + msg_type), + msg_type, + err->msg.nlmsg_seq, + err->msg.nlmsg_pid); + return 0; + } + + /* We see RTM_DELNEIGH when shutting down an + * interface with an IPv4 + * link-local. The kernel should have already + * deleted the neighbor + * so do not log these as an error. + */ + if (msg_type == RTM_DELNEIGH + || (nl == &zns->netlink_cmd + && msg_type == RTM_NEWROUTE + && (-errnum == ESRCH + || -errnum == ENETUNREACH))) { + /* This is known to happen in some + * situations, don't log + * as error. + */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "%s error: %s, type=%s(%u), seq=%u, pid=%u", + nl->name, + safe_strerror(-errnum), + nl_msg_type_to_str( + msg_type), + msg_type, + err->msg.nlmsg_seq, + err->msg.nlmsg_pid); + } else + zlog_err( + "%s error: %s, type=%s(%u), seq=%u, pid=%u", + nl->name, + safe_strerror(-errnum), + nl_msg_type_to_str(msg_type), + msg_type, err->msg.nlmsg_seq, + err->msg.nlmsg_pid); + + return -1; + } + + /* OK we got netlink message. */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_parse_info: %s type %s(%u), len=%d, seq=%u, pid=%u", + nl->name, + nl_msg_type_to_str(h->nlmsg_type), + h->nlmsg_type, h->nlmsg_len, + h->nlmsg_seq, h->nlmsg_pid); + + /* skip unsolicited messages originating from command + * socket + * linux sets the originators port-id for {NEW|DEL}ADDR + * messages, + * so this has to be checked here. */ + if (nl != &zns->netlink_cmd + && h->nlmsg_pid == zns->netlink_cmd.snl.nl_pid + && (h->nlmsg_type != RTM_NEWADDR + && h->nlmsg_type != RTM_DELADDR)) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_parse_info: %s packet comes from %s", + zns->netlink_cmd.name, + nl->name); + continue; + } + + error = (*filter)(&snl, h, zns->ns_id, startup); + if (error < 0) { + zlog_err("%s filter function error", nl->name); + ret = error; + } + } + + /* After error care. */ + if (msg.msg_flags & MSG_TRUNC) { + zlog_err("%s error: message truncated", nl->name); + continue; + } + if (status) { + zlog_err("%s error: data remnant size %d", nl->name, + status); + return -1; + } + } + return ret; } /* @@ -676,173 +666,163 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, * startup -> Are we reading in under startup conditions * This is passed through eventually to filter. */ -int -netlink_talk (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, - ns_id_t, int startup), - struct nlmsghdr *n, struct nlsock *nl, struct zebra_ns *zns, int startup) +int netlink_talk(int (*filter)(struct sockaddr_nl *, struct nlmsghdr *, ns_id_t, + int startup), + struct nlmsghdr *n, struct nlsock *nl, struct zebra_ns *zns, + int startup) { - int status; - struct sockaddr_nl snl; - struct iovec iov = { - .iov_base = (void *) n, - .iov_len = n->nlmsg_len - }; - struct msghdr msg = { - .msg_name = (void *) &snl, - .msg_namelen = sizeof snl, - .msg_iov = &iov, - .msg_iovlen = 1, - }; - int save_errno; - - memset (&snl, 0, sizeof snl); - snl.nl_family = AF_NETLINK; - - n->nlmsg_seq = ++nl->seq; - n->nlmsg_pid = nl->snl.nl_pid; - - /* Request an acknowledgement by setting NLM_F_ACK */ - n->nlmsg_flags |= NLM_F_ACK; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("netlink_talk: %s type %s(%u), len=%d seq=%u flags 0x%x", - nl->name, - nl_msg_type_to_str (n->nlmsg_type), n->nlmsg_type, - n->nlmsg_len, n->nlmsg_seq, n->nlmsg_flags); - - /* Send message to netlink interface. */ - if (zserv_privs.change (ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); - status = sendmsg (nl->sock, &msg, 0); - save_errno = errno; - if (zserv_privs.change (ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - - if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) - { - zlog_debug("%s: >> netlink message dump [sent]", __func__); - zlog_hexdump(n, n->nlmsg_len); - } - - if (status < 0) - { - zlog_err("netlink_talk sendmsg() error: %s", safe_strerror(save_errno)); - return -1; - } - - - /* - * Get reply from netlink socket. - * The reply should either be an acknowlegement or an error. - */ - return netlink_parse_info (filter, nl, zns, 0, startup); + int status; + struct sockaddr_nl snl; + struct iovec iov = {.iov_base = (void *)n, .iov_len = n->nlmsg_len}; + struct msghdr msg = { + .msg_name = (void *)&snl, + .msg_namelen = sizeof snl, + .msg_iov = &iov, + .msg_iovlen = 1, + }; + int save_errno; + + memset(&snl, 0, sizeof snl); + snl.nl_family = AF_NETLINK; + + n->nlmsg_seq = ++nl->seq; + n->nlmsg_pid = nl->snl.nl_pid; + + /* Request an acknowledgement by setting NLM_F_ACK */ + n->nlmsg_flags |= NLM_F_ACK; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_talk: %s type %s(%u), len=%d seq=%u flags 0x%x", + nl->name, nl_msg_type_to_str(n->nlmsg_type), + n->nlmsg_type, n->nlmsg_len, n->nlmsg_seq, + n->nlmsg_flags); + + /* Send message to netlink interface. */ + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + status = sendmsg(nl->sock, &msg, 0); + save_errno = errno; + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) { + zlog_debug("%s: >> netlink message dump [sent]", __func__); + zlog_hexdump(n, n->nlmsg_len); + } + + if (status < 0) { + zlog_err("netlink_talk sendmsg() error: %s", + safe_strerror(save_errno)); + return -1; + } + + + /* + * Get reply from netlink socket. + * The reply should either be an acknowlegement or an error. + */ + return netlink_parse_info(filter, nl, zns, 0, startup); } /* Issue request message to kernel via netlink socket. GET messages * are issued through this interface. */ -int -netlink_request (struct nlsock *nl, struct nlmsghdr *n) +int netlink_request(struct nlsock *nl, struct nlmsghdr *n) { - int ret; - struct sockaddr_nl snl; - int save_errno; - - /* Check netlink socket. */ - if (nl->sock < 0) - { - zlog_err("%s socket isn't active.", nl->name); - return -1; - } - - /* Fill common fields for all requests. */ - n->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; - n->nlmsg_pid = nl->snl.nl_pid; - n->nlmsg_seq = ++nl->seq; - - memset (&snl, 0, sizeof snl); - snl.nl_family = AF_NETLINK; - - /* Raise capabilities and send message, then lower capabilities. */ - if (zserv_privs.change (ZPRIVS_RAISE)) - { - zlog_err("Can't raise privileges"); - return -1; - } - - ret = sendto (nl->sock, (void *)n, n->nlmsg_len, 0, - (struct sockaddr *) &snl, sizeof snl); - save_errno = errno; - - if (zserv_privs.change (ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); - - if (ret < 0) - { - zlog_err("%s sendto failed: %s", nl->name, safe_strerror(save_errno)); - return -1; - } - - return 0; + int ret; + struct sockaddr_nl snl; + int save_errno; + + /* Check netlink socket. */ + if (nl->sock < 0) { + zlog_err("%s socket isn't active.", nl->name); + return -1; + } + + /* Fill common fields for all requests. */ + n->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; + n->nlmsg_pid = nl->snl.nl_pid; + n->nlmsg_seq = ++nl->seq; + + memset(&snl, 0, sizeof snl); + snl.nl_family = AF_NETLINK; + + /* Raise capabilities and send message, then lower capabilities. */ + if (zserv_privs.change(ZPRIVS_RAISE)) { + zlog_err("Can't raise privileges"); + return -1; + } + + ret = sendto(nl->sock, (void *)n, n->nlmsg_len, 0, + (struct sockaddr *)&snl, sizeof snl); + save_errno = errno; + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + if (ret < 0) { + zlog_err("%s sendto failed: %s", nl->name, + safe_strerror(save_errno)); + return -1; + } + + return 0; } /* Exported interface function. This function simply calls netlink_socket (). */ -void -kernel_init (struct zebra_ns *zns) +void kernel_init(struct zebra_ns *zns) { - unsigned long groups; - - /* Initialize netlink sockets */ - groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR | - RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR | - RTMGRP_IPV4_MROUTE | RTMGRP_NEIGH; - - snprintf (zns->netlink.name, sizeof (zns->netlink.name), - "netlink-listen (NS %u)", zns->ns_id); - zns->netlink.sock = -1; - netlink_socket (&zns->netlink, groups, zns->ns_id); - - snprintf (zns->netlink_cmd.name, sizeof (zns->netlink_cmd.name), - "netlink-cmd (NS %u)", zns->ns_id); - zns->netlink_cmd.sock = -1; - netlink_socket (&zns->netlink_cmd, 0, zns->ns_id); - - /* Register kernel socket. */ - if (zns->netlink.sock > 0) - { - /* Only want non-blocking on the netlink event socket */ - if (fcntl (zns->netlink.sock, F_SETFL, O_NONBLOCK) < 0) - zlog_err ("Can't set %s socket flags: %s", zns->netlink.name, - safe_strerror (errno)); - - /* Set receive buffer size if it's set from command line */ - if (nl_rcvbufsize) - netlink_recvbuf (&zns->netlink, nl_rcvbufsize); - - netlink_install_filter (zns->netlink.sock, zns->netlink_cmd.snl.nl_pid); - zns->t_netlink = NULL; - thread_add_read(zebrad.master, kernel_read, zns, zns->netlink.sock, - &zns->t_netlink); - } - - rt_netlink_init (); + unsigned long groups; + + /* Initialize netlink sockets */ + groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR + | RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR | RTMGRP_IPV4_MROUTE + | RTMGRP_NEIGH; + + snprintf(zns->netlink.name, sizeof(zns->netlink.name), + "netlink-listen (NS %u)", zns->ns_id); + zns->netlink.sock = -1; + netlink_socket(&zns->netlink, groups, zns->ns_id); + + snprintf(zns->netlink_cmd.name, sizeof(zns->netlink_cmd.name), + "netlink-cmd (NS %u)", zns->ns_id); + zns->netlink_cmd.sock = -1; + netlink_socket(&zns->netlink_cmd, 0, zns->ns_id); + + /* Register kernel socket. */ + if (zns->netlink.sock > 0) { + /* Only want non-blocking on the netlink event socket */ + if (fcntl(zns->netlink.sock, F_SETFL, O_NONBLOCK) < 0) + zlog_err("Can't set %s socket flags: %s", + zns->netlink.name, safe_strerror(errno)); + + /* Set receive buffer size if it's set from command line */ + if (nl_rcvbufsize) + netlink_recvbuf(&zns->netlink, nl_rcvbufsize); + + netlink_install_filter(zns->netlink.sock, + zns->netlink_cmd.snl.nl_pid); + zns->t_netlink = NULL; + thread_add_read(zebrad.master, kernel_read, zns, + zns->netlink.sock, &zns->t_netlink); + } + + rt_netlink_init(); } -void -kernel_terminate (struct zebra_ns *zns) +void kernel_terminate(struct zebra_ns *zns) { - THREAD_READ_OFF (zns->t_netlink); - - if (zns->netlink.sock >= 0) - { - close (zns->netlink.sock); - zns->netlink.sock = -1; - } - - if (zns->netlink_cmd.sock >= 0) - { - close (zns->netlink_cmd.sock); - zns->netlink_cmd.sock = -1; - } + THREAD_READ_OFF(zns->t_netlink); + + if (zns->netlink.sock >= 0) { + close(zns->netlink.sock); + zns->netlink.sock = -1; + } + + if (zns->netlink_cmd.sock >= 0) { + close(zns->netlink_cmd.sock); + zns->netlink_cmd.sock = -1; + } } diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h index d64242323..e5a079af5 100644 --- a/zebra/kernel_netlink.h +++ b/zebra/kernel_netlink.h @@ -25,36 +25,36 @@ #define NL_PKT_BUF_SIZE 8192 -extern void netlink_parse_rtattr (struct rtattr **tb, int max, - struct rtattr *rta, int len); -extern int addattr_l (struct nlmsghdr *n, unsigned int maxlen, - int type, void *data, unsigned int alen); -extern int rta_addattr_l (struct rtattr *rta, unsigned int maxlen, - int type, void *data, unsigned int alen); -extern int addattr16 (struct nlmsghdr *n, unsigned int maxlen, - int type, u_int16_t data); -extern int addattr32 (struct nlmsghdr *n, unsigned int maxlen, - int type, int data); +extern void netlink_parse_rtattr(struct rtattr **tb, int max, + struct rtattr *rta, int len); +extern int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type, + void *data, unsigned int alen); +extern int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type, + void *data, unsigned int alen); +extern int addattr16(struct nlmsghdr *n, unsigned int maxlen, int type, + u_int16_t data); +extern int addattr32(struct nlmsghdr *n, unsigned int maxlen, int type, + int data); extern struct rtattr *addattr_nest(struct nlmsghdr *n, int maxlen, int type); extern int addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest); -extern struct rtattr * rta_nest(struct rtattr *rta, int maxlen, int type); +extern struct rtattr *rta_nest(struct rtattr *rta, int maxlen, int type); extern int rta_nest_end(struct rtattr *rta, struct rtattr *nest); -extern const char * nl_msg_type_to_str (uint16_t msg_type); -extern const char * nl_rtproto_to_str (u_char rtproto); -extern const char * nl_family_to_str (u_char family); -extern const char * nl_rttype_to_str (u_char rttype); +extern const char *nl_msg_type_to_str(uint16_t msg_type); +extern const char *nl_rtproto_to_str(u_char rtproto); +extern const char *nl_family_to_str(u_char family); +extern const char *nl_rttype_to_str(u_char rttype); -extern int netlink_parse_info (int (*filter) (struct sockaddr_nl *, - struct nlmsghdr *, ns_id_t, int), - struct nlsock *nl, struct zebra_ns *zns, - int count, int startup); -extern int netlink_talk_filter (struct sockaddr_nl *, struct nlmsghdr *, - ns_id_t, int startup); -extern int netlink_talk (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *, - ns_id_t, int startup), - struct nlmsghdr *n, struct nlsock *nl, - struct zebra_ns *zns, int startup); -extern int netlink_request (struct nlsock *nl, struct nlmsghdr *n); +extern int netlink_parse_info(int (*filter)(struct sockaddr_nl *, + struct nlmsghdr *, ns_id_t, int), + struct nlsock *nl, struct zebra_ns *zns, + int count, int startup); +extern int netlink_talk_filter(struct sockaddr_nl *, struct nlmsghdr *, ns_id_t, + int startup); +extern int netlink_talk(int (*filter)(struct sockaddr_nl *, struct nlmsghdr *, + ns_id_t, int startup), + struct nlmsghdr *n, struct nlsock *nl, + struct zebra_ns *zns, int startup); +extern int netlink_request(struct nlsock *nl, struct nlmsghdr *n); #endif /* HAVE_NETLINK */ diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 5b9236f7f..4b63a3eb0 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -90,7 +90,8 @@ extern struct zebra_privs_t zserv_privs; * intentional, to provoke filing bug reports with operating systems * that don't define RT_ROUNDUP or equivalent. */ -#warning "net/route.h does not define RT_ROUNDUP; making unwarranted assumptions!" +#warning \ + "net/route.h does not define RT_ROUNDUP; making unwarranted assumptions!" /* OS X (Xcode as of 2014-12) is known not to define RT_ROUNDUP */ #ifdef __APPLE__ @@ -99,8 +100,9 @@ extern struct zebra_privs_t zserv_privs; #define ROUNDUP_TYPE long #endif -#define ROUNDUP(a) \ - ((a) > 0 ? (1 + (((a) - 1) | (sizeof(ROUNDUP_TYPE) - 1))) : sizeof(ROUNDUP_TYPE)) +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a)-1) | (sizeof(ROUNDUP_TYPE) - 1))) \ + : sizeof(ROUNDUP_TYPE)) #endif /* defined(ROUNDUP) */ @@ -115,13 +117,14 @@ extern struct zebra_privs_t zserv_privs; * One would hope all fixed-size structure definitions are aligned, * but round them up nonetheless. */ -#define SAROUNDUP(X) \ - (((struct sockaddr *)(X))->sa_family == AF_INET ? \ - ROUNDUP(sizeof(struct sockaddr_in)):\ - (((struct sockaddr *)(X))->sa_family == AF_INET6 ? \ - ROUNDUP(sizeof(struct sockaddr_in6)) : \ - (((struct sockaddr *)(X))->sa_family == AF_LINK ? \ - ROUNDUP(sizeof(struct sockaddr_dl)) : sizeof(struct sockaddr)))) +#define SAROUNDUP(X) \ + (((struct sockaddr *)(X))->sa_family == AF_INET \ + ? ROUNDUP(sizeof(struct sockaddr_in)) \ + : (((struct sockaddr *)(X))->sa_family == AF_INET6 \ + ? ROUNDUP(sizeof(struct sockaddr_in6)) \ + : (((struct sockaddr *)(X))->sa_family == AF_LINK \ + ? ROUNDUP(sizeof(struct sockaddr_dl)) \ + : sizeof(struct sockaddr)))) #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ #endif /* !SA_SIZE */ @@ -133,152 +136,140 @@ extern struct zebra_privs_t zserv_privs; * 2. So the compiler doesn't complain when DEST is NULL, which is only true * when we are skipping the copy and incrementing to the next SA */ -static inline void -rta_copy (union sockunion *dest, caddr_t src) { - int len; - if (!dest) - return; +static inline void rta_copy(union sockunion *dest, caddr_t src) +{ + int len; + if (!dest) + return; #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN - len = (((struct sockaddr *)src)->sa_len > sizeof (*dest)) ? - sizeof (*dest) : ((struct sockaddr *)src)->sa_len ; + len = (((struct sockaddr *)src)->sa_len > sizeof(*dest)) + ? sizeof(*dest) + : ((struct sockaddr *)src)->sa_len; #else - len = (SAROUNDUP (src) > sizeof (*dest)) ? - sizeof (*dest) : SAROUNDUP (src) ; + len = (SAROUNDUP(src) > sizeof(*dest)) ? sizeof(*dest) : SAROUNDUP(src); #endif - memcpy (dest, src, len); + memcpy(dest, src, len); } -#define RTA_ADDR_GET(DEST, RTA, RTMADDRS, PNT) \ - if ((RTMADDRS) & (RTA)) \ - { \ - int len = SAROUNDUP ((PNT)); \ - if (af_check (((struct sockaddr *)(PNT))->sa_family)) \ - rta_copy((DEST), (PNT)); \ - (PNT) += len; \ - } -#define RTA_ATTR_GET(DEST, RTA, RTMADDRS, PNT) \ - if ((RTMADDRS) & (RTA)) \ - { \ - int len = SAROUNDUP ((PNT)); \ - rta_copy((DEST), (PNT)); \ - (PNT) += len; \ - } - -#define RTA_NAME_GET(DEST, RTA, RTMADDRS, PNT, LEN) \ - if ((RTMADDRS) & (RTA)) \ - { \ - u_char *pdest = (u_char *) (DEST); \ - int len = SAROUNDUP ((PNT)); \ - struct sockaddr_dl *sdl = (struct sockaddr_dl *)(PNT); \ - if (IS_ZEBRA_DEBUG_KERNEL) \ - zlog_debug ("%s: RTA_SDL_GET nlen %d, alen %d", \ - __func__, sdl->sdl_nlen, sdl->sdl_alen); \ - if ( ((DEST) != NULL) && (sdl->sdl_family == AF_LINK) \ - && (sdl->sdl_nlen < IFNAMSIZ) && (sdl->sdl_nlen <= len) ) \ - { \ - memcpy (pdest, sdl->sdl_data, sdl->sdl_nlen); \ - pdest[sdl->sdl_nlen] = '\0'; \ - (LEN) = sdl->sdl_nlen; \ - } \ - (PNT) += len; \ - } \ - else \ - { \ - (LEN) = 0; \ - } +#define RTA_ADDR_GET(DEST, RTA, RTMADDRS, PNT) \ + if ((RTMADDRS) & (RTA)) { \ + int len = SAROUNDUP((PNT)); \ + if (af_check(((struct sockaddr *)(PNT))->sa_family)) \ + rta_copy((DEST), (PNT)); \ + (PNT) += len; \ + } +#define RTA_ATTR_GET(DEST, RTA, RTMADDRS, PNT) \ + if ((RTMADDRS) & (RTA)) { \ + int len = SAROUNDUP((PNT)); \ + rta_copy((DEST), (PNT)); \ + (PNT) += len; \ + } + +#define RTA_NAME_GET(DEST, RTA, RTMADDRS, PNT, LEN) \ + if ((RTMADDRS) & (RTA)) { \ + u_char *pdest = (u_char *)(DEST); \ + int len = SAROUNDUP((PNT)); \ + struct sockaddr_dl *sdl = (struct sockaddr_dl *)(PNT); \ + if (IS_ZEBRA_DEBUG_KERNEL) \ + zlog_debug("%s: RTA_SDL_GET nlen %d, alen %d", \ + __func__, sdl->sdl_nlen, sdl->sdl_alen); \ + if (((DEST) != NULL) && (sdl->sdl_family == AF_LINK) \ + && (sdl->sdl_nlen < IFNAMSIZ) && (sdl->sdl_nlen <= len)) { \ + memcpy(pdest, sdl->sdl_data, sdl->sdl_nlen); \ + pdest[sdl->sdl_nlen] = '\0'; \ + (LEN) = sdl->sdl_nlen; \ + } \ + (PNT) += len; \ + } else { \ + (LEN) = 0; \ + } /* Routing socket message types. */ -const struct message rtm_type_str[] = -{ - {RTM_ADD, "RTM_ADD"}, - {RTM_DELETE, "RTM_DELETE"}, - {RTM_CHANGE, "RTM_CHANGE"}, - {RTM_GET, "RTM_GET"}, - {RTM_LOSING, "RTM_LOSING"}, - {RTM_REDIRECT, "RTM_REDIRECT"}, - {RTM_MISS, "RTM_MISS"}, - {RTM_LOCK, "RTM_LOCK"}, +const struct message rtm_type_str[] = {{RTM_ADD, "RTM_ADD"}, + {RTM_DELETE, "RTM_DELETE"}, + {RTM_CHANGE, "RTM_CHANGE"}, + {RTM_GET, "RTM_GET"}, + {RTM_LOSING, "RTM_LOSING"}, + {RTM_REDIRECT, "RTM_REDIRECT"}, + {RTM_MISS, "RTM_MISS"}, + {RTM_LOCK, "RTM_LOCK"}, #ifdef OLDADD - {RTM_OLDADD, "RTM_OLDADD"}, + {RTM_OLDADD, "RTM_OLDADD"}, #endif /* RTM_OLDADD */ #ifdef RTM_OLDDEL - {RTM_OLDDEL, "RTM_OLDDEL"}, + {RTM_OLDDEL, "RTM_OLDDEL"}, #endif /* RTM_OLDDEL */ - {RTM_RESOLVE, "RTM_RESOLVE"}, - {RTM_NEWADDR, "RTM_NEWADDR"}, - {RTM_DELADDR, "RTM_DELADDR"}, - {RTM_IFINFO, "RTM_IFINFO"}, + {RTM_RESOLVE, "RTM_RESOLVE"}, + {RTM_NEWADDR, "RTM_NEWADDR"}, + {RTM_DELADDR, "RTM_DELADDR"}, + {RTM_IFINFO, "RTM_IFINFO"}, #ifdef RTM_OIFINFO - {RTM_OIFINFO, "RTM_OIFINFO"}, + {RTM_OIFINFO, "RTM_OIFINFO"}, #endif /* RTM_OIFINFO */ #ifdef RTM_NEWMADDR - {RTM_NEWMADDR, "RTM_NEWMADDR"}, + {RTM_NEWMADDR, "RTM_NEWMADDR"}, #endif /* RTM_NEWMADDR */ #ifdef RTM_DELMADDR - {RTM_DELMADDR, "RTM_DELMADDR"}, + {RTM_DELMADDR, "RTM_DELMADDR"}, #endif /* RTM_DELMADDR */ #ifdef RTM_IFANNOUNCE - {RTM_IFANNOUNCE, "RTM_IFANNOUNCE"}, + {RTM_IFANNOUNCE, "RTM_IFANNOUNCE"}, #endif /* RTM_IFANNOUNCE */ - { 0 } -}; - -static const struct message rtm_flag_str[] = -{ - {RTF_UP, "UP"}, - {RTF_GATEWAY, "GATEWAY"}, - {RTF_HOST, "HOST"}, - {RTF_REJECT, "REJECT"}, - {RTF_DYNAMIC, "DYNAMIC"}, - {RTF_MODIFIED, "MODIFIED"}, - {RTF_DONE, "DONE"}, + {0}}; + +static const struct message rtm_flag_str[] = {{RTF_UP, "UP"}, + {RTF_GATEWAY, "GATEWAY"}, + {RTF_HOST, "HOST"}, + {RTF_REJECT, "REJECT"}, + {RTF_DYNAMIC, "DYNAMIC"}, + {RTF_MODIFIED, "MODIFIED"}, + {RTF_DONE, "DONE"}, #ifdef RTF_MASK - {RTF_MASK, "MASK"}, + {RTF_MASK, "MASK"}, #endif /* RTF_MASK */ #ifdef RTF_CLONING - {RTF_CLONING, "CLONING"}, + {RTF_CLONING, "CLONING"}, #endif /* RTF_CLONING */ #ifdef RTF_XRESOLVE - {RTF_XRESOLVE, "XRESOLVE"}, + {RTF_XRESOLVE, "XRESOLVE"}, #endif /* RTF_XRESOLVE */ #ifdef RTF_LLINFO - {RTF_LLINFO, "LLINFO"}, + {RTF_LLINFO, "LLINFO"}, #endif /* RTF_LLINFO */ - {RTF_STATIC, "STATIC"}, - {RTF_BLACKHOLE, "BLACKHOLE"}, + {RTF_STATIC, "STATIC"}, + {RTF_BLACKHOLE, "BLACKHOLE"}, #ifdef RTF_PRIVATE - {RTF_PRIVATE, "PRIVATE"}, + {RTF_PRIVATE, "PRIVATE"}, #endif /* RTF_PRIVATE */ - {RTF_PROTO1, "PROTO1"}, - {RTF_PROTO2, "PROTO2"}, + {RTF_PROTO1, "PROTO1"}, + {RTF_PROTO2, "PROTO2"}, #ifdef RTF_PRCLONING - {RTF_PRCLONING, "PRCLONING"}, + {RTF_PRCLONING, "PRCLONING"}, #endif /* RTF_PRCLONING */ #ifdef RTF_WASCLONED - {RTF_WASCLONED, "WASCLONED"}, + {RTF_WASCLONED, "WASCLONED"}, #endif /* RTF_WASCLONED */ #ifdef RTF_PROTO3 - {RTF_PROTO3, "PROTO3"}, + {RTF_PROTO3, "PROTO3"}, #endif /* RTF_PROTO3 */ #ifdef RTF_PINNED - {RTF_PINNED, "PINNED"}, + {RTF_PINNED, "PINNED"}, #endif /* RTF_PINNED */ #ifdef RTF_LOCAL - {RTF_LOCAL, "LOCAL"}, + {RTF_LOCAL, "LOCAL"}, #endif /* RTF_LOCAL */ #ifdef RTF_BROADCAST - {RTF_BROADCAST, "BROADCAST"}, + {RTF_BROADCAST, "BROADCAST"}, #endif /* RTF_BROADCAST */ #ifdef RTF_MULTICAST - {RTF_MULTICAST, "MULTICAST"}, + {RTF_MULTICAST, "MULTICAST"}, #endif /* RTF_MULTICAST */ #ifdef RTF_MULTIRT - {RTF_MULTIRT, "MULTIRT"}, + {RTF_MULTIRT, "MULTIRT"}, #endif /* RTF_MULTIRT */ #ifdef RTF_SETSRC - {RTF_SETSRC, "SETSRC"}, + {RTF_SETSRC, "SETSRC"}, #endif /* RTF_SETSRC */ - { 0 } -}; + {0}}; /* Kernel routing update socket. */ int routing_sock = -1; @@ -287,115 +278,117 @@ int routing_sock = -1; /* #define DEBUG */ /* Supported address family check. */ -static inline int -af_check (int family) +static inline int af_check(int family) { - if (family == AF_INET) - return 1; - if (family == AF_INET6) - return 1; - return 0; + if (family == AF_INET) + return 1; + if (family == AF_INET6) + return 1; + return 0; } /* Dump routing table flag for debug purpose. */ -static void -rtm_flag_dump (int flag) +static void rtm_flag_dump(int flag) { - const struct message *mes; - static char buf[BUFSIZ]; - - buf[0] = '\0'; - for (mes = rtm_flag_str; mes->key != 0; mes++) - { - if (mes->key & flag) - { - strlcat (buf, mes->str, BUFSIZ); - strlcat (buf, " ", BUFSIZ); + const struct message *mes; + static char buf[BUFSIZ]; + + buf[0] = '\0'; + for (mes = rtm_flag_str; mes->key != 0; mes++) { + if (mes->key & flag) { + strlcat(buf, mes->str, BUFSIZ); + strlcat(buf, " ", BUFSIZ); + } } - } - zlog_debug ("Kernel: %s", buf); + zlog_debug("Kernel: %s", buf); } #ifdef RTM_IFANNOUNCE /* Interface adding function */ -static int -ifan_read (struct if_announcemsghdr *ifan) +static int ifan_read(struct if_announcemsghdr *ifan) { - struct interface *ifp; - - ifp = if_lookup_by_index (ifan->ifan_index, VRF_DEFAULT); - - if (ifp) - assert ( (ifp->ifindex == ifan->ifan_index) - || (ifp->ifindex == IFINDEX_INTERNAL) ); - - if ( (ifp == NULL) - || ((ifp->ifindex == IFINDEX_INTERNAL) - && (ifan->ifan_what == IFAN_ARRIVAL)) ) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: creating interface for ifindex %d, name %s", - __func__, ifan->ifan_index, ifan->ifan_name); - - /* Create Interface */ - ifp = if_get_by_name_len(ifan->ifan_name, - strnlen(ifan->ifan_name, - sizeof(ifan->ifan_name)), - VRF_DEFAULT, 0); - ifp->ifindex = ifan->ifan_index; - - if_get_metric (ifp); - if_add_update (ifp); - } - else if (ifp != NULL && ifan->ifan_what == IFAN_DEPARTURE) - if_delete_update (ifp); - - if_get_flags (ifp); - if_get_mtu (ifp); - if_get_metric (ifp); - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: interface %s index %d", - __func__, ifan->ifan_name, ifan->ifan_index); - - return 0; + struct interface *ifp; + + ifp = if_lookup_by_index(ifan->ifan_index, VRF_DEFAULT); + + if (ifp) + assert((ifp->ifindex == ifan->ifan_index) + || (ifp->ifindex == IFINDEX_INTERNAL)); + + if ((ifp == NULL) || ((ifp->ifindex == IFINDEX_INTERNAL) + && (ifan->ifan_what == IFAN_ARRIVAL))) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "%s: creating interface for ifindex %d, name %s", + __func__, ifan->ifan_index, ifan->ifan_name); + + /* Create Interface */ + ifp = if_get_by_name_len( + ifan->ifan_name, + strnlen(ifan->ifan_name, sizeof(ifan->ifan_name)), + VRF_DEFAULT, 0); + ifp->ifindex = ifan->ifan_index; + + if_get_metric(ifp); + if_add_update(ifp); + } else if (ifp != NULL && ifan->ifan_what == IFAN_DEPARTURE) + if_delete_update(ifp); + + if_get_flags(ifp); + if_get_mtu(ifp); + if_get_metric(ifp); + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: interface %s index %d", __func__, + ifan->ifan_name, ifan->ifan_index); + + return 0; } #endif /* RTM_IFANNOUNCE */ #ifdef HAVE_BSD_IFI_LINK_STATE /* BSD link detect translation */ -static void -bsd_linkdetect_translate (struct if_msghdr *ifm) +static void bsd_linkdetect_translate(struct if_msghdr *ifm) { - if ((ifm->ifm_data.ifi_link_state >= LINK_STATE_UP) || - (ifm->ifm_data.ifi_link_state == LINK_STATE_UNKNOWN)) - SET_FLAG(ifm->ifm_flags, IFF_RUNNING); - else - UNSET_FLAG(ifm->ifm_flags, IFF_RUNNING); + if ((ifm->ifm_data.ifi_link_state >= LINK_STATE_UP) + || (ifm->ifm_data.ifi_link_state == LINK_STATE_UNKNOWN)) + SET_FLAG(ifm->ifm_flags, IFF_RUNNING); + else + UNSET_FLAG(ifm->ifm_flags, IFF_RUNNING); } #endif /* HAVE_BSD_IFI_LINK_STATE */ -static enum zebra_link_type -sdl_to_zebra_link_type (unsigned int sdlt) +static enum zebra_link_type sdl_to_zebra_link_type(unsigned int sdlt) { - switch (sdlt) - { - case IFT_ETHER: return ZEBRA_LLT_ETHER; - case IFT_X25: return ZEBRA_LLT_X25; - case IFT_FDDI: return ZEBRA_LLT_FDDI; - case IFT_PPP: return ZEBRA_LLT_PPP; - case IFT_LOOP: return ZEBRA_LLT_LOOPBACK; - case IFT_SLIP: return ZEBRA_LLT_SLIP; - case IFT_ARCNET: return ZEBRA_LLT_ARCNET; - case IFT_ATM: return ZEBRA_LLT_ATM; - case IFT_LOCALTALK: return ZEBRA_LLT_LOCALTLK; - case IFT_HIPPI: return ZEBRA_LLT_HIPPI; + switch (sdlt) { + case IFT_ETHER: + return ZEBRA_LLT_ETHER; + case IFT_X25: + return ZEBRA_LLT_X25; + case IFT_FDDI: + return ZEBRA_LLT_FDDI; + case IFT_PPP: + return ZEBRA_LLT_PPP; + case IFT_LOOP: + return ZEBRA_LLT_LOOPBACK; + case IFT_SLIP: + return ZEBRA_LLT_SLIP; + case IFT_ARCNET: + return ZEBRA_LLT_ARCNET; + case IFT_ATM: + return ZEBRA_LLT_ATM; + case IFT_LOCALTALK: + return ZEBRA_LLT_LOCALTLK; + case IFT_HIPPI: + return ZEBRA_LLT_HIPPI; #ifdef IFT_IEEE1394 - case IFT_IEEE1394: return ZEBRA_LLT_IEEE1394; + case IFT_IEEE1394: + return ZEBRA_LLT_IEEE1394; #endif - default: return ZEBRA_LLT_UNKNOWN; - } + default: + return ZEBRA_LLT_UNKNOWN; + } } /* @@ -403,341 +396,338 @@ sdl_to_zebra_link_type (unsigned int sdlt) * sysctl (from interface_list). There may or may not be sockaddrs * present after the header. */ -int -ifm_read (struct if_msghdr *ifm) +int ifm_read(struct if_msghdr *ifm) { - struct interface *ifp = NULL; - struct sockaddr_dl *sdl; - char ifname[IFNAMSIZ]; - short ifnlen = 0; - caddr_t cp; - - /* terminate ifname at head (for strnlen) and tail (for safety) */ - ifname[IFNAMSIZ - 1] = '\0'; - - /* paranoia: sanity check structure */ - if (ifm->ifm_msglen < sizeof(struct if_msghdr)) - { - zlog_err ("ifm_read: ifm->ifm_msglen %d too short\n", - ifm->ifm_msglen); - return -1; - } - - /* - * Check for a sockaddr_dl following the message. First, point to - * where a socakddr might be if one follows the message. - */ - cp = (void *)(ifm + 1); + struct interface *ifp = NULL; + struct sockaddr_dl *sdl; + char ifname[IFNAMSIZ]; + short ifnlen = 0; + caddr_t cp; + + /* terminate ifname at head (for strnlen) and tail (for safety) */ + ifname[IFNAMSIZ - 1] = '\0'; + + /* paranoia: sanity check structure */ + if (ifm->ifm_msglen < sizeof(struct if_msghdr)) { + zlog_err("ifm_read: ifm->ifm_msglen %d too short\n", + ifm->ifm_msglen); + return -1; + } + + /* + * Check for a sockaddr_dl following the message. First, point to + * where a socakddr might be if one follows the message. + */ + cp = (void *)(ifm + 1); #ifdef SUNOS_5 - /* - * XXX This behavior should be narrowed to only the kernel versions - * for which the structures returned do not match the headers. - * - * if_msghdr_t on 64 bit kernels in Solaris 9 and earlier versions - * is 12 bytes larger than the 32 bit version. - */ - if (((struct sockaddr *) cp)->sa_family == AF_UNSPEC) - cp = cp + 12; + /* + * XXX This behavior should be narrowed to only the kernel versions + * for which the structures returned do not match the headers. + * + * if_msghdr_t on 64 bit kernels in Solaris 9 and earlier versions + * is 12 bytes larger than the 32 bit version. + */ + if (((struct sockaddr *)cp)->sa_family == AF_UNSPEC) + cp = cp + 12; #endif - RTA_ADDR_GET (NULL, RTA_DST, ifm->ifm_addrs, cp); - RTA_ADDR_GET (NULL, RTA_GATEWAY, ifm->ifm_addrs, cp); - RTA_ATTR_GET (NULL, RTA_NETMASK, ifm->ifm_addrs, cp); - RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifm_addrs, cp); - sdl = (struct sockaddr_dl *)cp; - RTA_NAME_GET (ifname, RTA_IFP, ifm->ifm_addrs, cp, ifnlen); - RTA_ADDR_GET (NULL, RTA_IFA, ifm->ifm_addrs, cp); - RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifm_addrs, cp); - RTA_ADDR_GET (NULL, RTA_BRD, ifm->ifm_addrs, cp); - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: sdl ifname %s", __func__, (ifnlen ? ifname : "(nil)")); - - /* - * Look up on ifindex first, because ifindices are the primary handle for - * interfaces across the user/kernel boundary, for most systems. (Some - * messages, such as up/down status changes on NetBSD, do not include a - * sockaddr_dl). - */ - if ( (ifp = if_lookup_by_index (ifm->ifm_index, VRF_DEFAULT)) != NULL ) - { - /* we have an ifp, verify that the name matches as some systems, - * eg Solaris, have a 1:many association of ifindex:ifname - * if they dont match, we dont have the correct ifp and should - * set it back to NULL to let next check do lookup by name - */ - if (ifnlen && (strncmp (ifp->name, ifname, IFNAMSIZ) != 0) ) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: ifp name %s doesnt match sdl name %s", - __func__, ifp->name, ifname); - ifp = NULL; - } - } - - /* - * If we dont have an ifp, try looking up by name. Particularly as some - * systems (Solaris) have a 1:many mapping of ifindex:ifname - the ifname - * is therefore our unique handle to that interface. - * - * Interfaces specified in the configuration file for which the ifindex - * has not been determined will have ifindex == IFINDEX_INTERNAL, and such - * interfaces are found by this search, and then their ifindex values can - * be filled in. - */ - if ( (ifp == NULL) && ifnlen) - ifp = if_lookup_by_name (ifname, VRF_DEFAULT); - - /* - * If ifp still does not exist or has an invalid index (IFINDEX_INTERNAL), - * create or fill in an interface. - */ - if ((ifp == NULL) || (ifp->ifindex == IFINDEX_INTERNAL)) - { - /* - * To create or fill in an interface, a sockaddr_dl (via - * RTA_IFP) is required. - */ - if (!ifnlen) - { - zlog_warn ("Interface index %d (new) missing ifname\n", - ifm->ifm_index); - return -1; + RTA_ADDR_GET(NULL, RTA_DST, ifm->ifm_addrs, cp); + RTA_ADDR_GET(NULL, RTA_GATEWAY, ifm->ifm_addrs, cp); + RTA_ATTR_GET(NULL, RTA_NETMASK, ifm->ifm_addrs, cp); + RTA_ADDR_GET(NULL, RTA_GENMASK, ifm->ifm_addrs, cp); + sdl = (struct sockaddr_dl *)cp; + RTA_NAME_GET(ifname, RTA_IFP, ifm->ifm_addrs, cp, ifnlen); + RTA_ADDR_GET(NULL, RTA_IFA, ifm->ifm_addrs, cp); + RTA_ADDR_GET(NULL, RTA_AUTHOR, ifm->ifm_addrs, cp); + RTA_ADDR_GET(NULL, RTA_BRD, ifm->ifm_addrs, cp); + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: sdl ifname %s", __func__, + (ifnlen ? ifname : "(nil)")); + + /* + * Look up on ifindex first, because ifindices are the primary handle + * for + * interfaces across the user/kernel boundary, for most systems. (Some + * messages, such as up/down status changes on NetBSD, do not include a + * sockaddr_dl). + */ + if ((ifp = if_lookup_by_index(ifm->ifm_index, VRF_DEFAULT)) != NULL) { + /* we have an ifp, verify that the name matches as some systems, + * eg Solaris, have a 1:many association of ifindex:ifname + * if they dont match, we dont have the correct ifp and should + * set it back to NULL to let next check do lookup by name + */ + if (ifnlen && (strncmp(ifp->name, ifname, IFNAMSIZ) != 0)) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "%s: ifp name %s doesnt match sdl name %s", + __func__, ifp->name, ifname); + ifp = NULL; + } } + /* + * If we dont have an ifp, try looking up by name. Particularly as some + * systems (Solaris) have a 1:many mapping of ifindex:ifname - the + * ifname + * is therefore our unique handle to that interface. + * + * Interfaces specified in the configuration file for which the ifindex + * has not been determined will have ifindex == IFINDEX_INTERNAL, and + * such + * interfaces are found by this search, and then their ifindex values + * can + * be filled in. + */ + if ((ifp == NULL) && ifnlen) + ifp = if_lookup_by_name(ifname, VRF_DEFAULT); + + /* + * If ifp still does not exist or has an invalid index + * (IFINDEX_INTERNAL), + * create or fill in an interface. + */ + if ((ifp == NULL) || (ifp->ifindex == IFINDEX_INTERNAL)) { + /* + * To create or fill in an interface, a sockaddr_dl (via + * RTA_IFP) is required. + */ + if (!ifnlen) { + zlog_warn("Interface index %d (new) missing ifname\n", + ifm->ifm_index); + return -1; + } + #ifndef RTM_IFANNOUNCE - /* Down->Down interface should be ignored here. - * See further comment below. - */ - if (!CHECK_FLAG (ifm->ifm_flags, IFF_UP)) - return 0; + /* Down->Down interface should be ignored here. + * See further comment below. + */ + if (!CHECK_FLAG(ifm->ifm_flags, IFF_UP)) + return 0; #endif /* !RTM_IFANNOUNCE */ - - if (ifp == NULL) - { - /* Interface that zebra was not previously aware of, so create. */ - ifp = if_create (ifname, ifnlen, VRF_DEFAULT); - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: creating ifp for ifindex %d", - __func__, ifm->ifm_index); - } - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: updated/created ifp, ifname %s, ifindex %d", - __func__, ifp->name, ifp->ifindex); - /* - * Fill in newly created interface structure, or larval - * structure with ifindex IFINDEX_INTERNAL. - */ - ifp->ifindex = ifm->ifm_index; - + + if (ifp == NULL) { + /* Interface that zebra was not previously aware of, so + * create. */ + ifp = if_create(ifname, ifnlen, VRF_DEFAULT); + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: creating ifp for ifindex %d", + __func__, ifm->ifm_index); + } + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "%s: updated/created ifp, ifname %s, ifindex %d", + __func__, ifp->name, ifp->ifindex); + /* + * Fill in newly created interface structure, or larval + * structure with ifindex IFINDEX_INTERNAL. + */ + ifp->ifindex = ifm->ifm_index; + #ifdef HAVE_BSD_IFI_LINK_STATE /* translate BSD kernel msg for link-state */ - bsd_linkdetect_translate(ifm); + bsd_linkdetect_translate(ifm); #endif /* HAVE_BSD_IFI_LINK_STATE */ - if_flags_update (ifp, ifm->ifm_flags); + if_flags_update(ifp, ifm->ifm_flags); #if defined(__bsdi__) - if_kvm_get_mtu (ifp); + if_kvm_get_mtu(ifp); #else - if_get_mtu (ifp); + if_get_mtu(ifp); #endif /* __bsdi__ */ - if_get_metric (ifp); - - /* - * XXX sockaddr_dl contents can be larger than the structure - * definition. There are 2 big families here: - * - BSD has sdl_len + sdl_data[16] + overruns sdl_data - * we MUST use sdl_len here or we'll truncate data. - * - Solaris has no sdl_len, but sdl_data[244] - * presumably, it's not going to run past that, so sizeof() - * is fine here. - * a nonzero ifnlen from RTA_NAME_GET() means sdl is valid - */ - ifp->ll_type = ZEBRA_LLT_UNKNOWN; - ifp->hw_addr_len = 0; - if (ifnlen) - { + if_get_metric(ifp); + + /* + * XXX sockaddr_dl contents can be larger than the structure + * definition. There are 2 big families here: + * - BSD has sdl_len + sdl_data[16] + overruns sdl_data + * we MUST use sdl_len here or we'll truncate data. + * - Solaris has no sdl_len, but sdl_data[244] + * presumably, it's not going to run past that, so sizeof() + * is fine here. + * a nonzero ifnlen from RTA_NAME_GET() means sdl is valid + */ + ifp->ll_type = ZEBRA_LLT_UNKNOWN; + ifp->hw_addr_len = 0; + if (ifnlen) { #ifdef HAVE_STRUCT_SOCKADDR_DL_SDL_LEN - memcpy (&((struct zebra_if *)ifp->info)->sdl, sdl, sdl->sdl_len); + memcpy(&((struct zebra_if *)ifp->info)->sdl, sdl, + sdl->sdl_len); #else - memcpy (&((struct zebra_if *)ifp->info)->sdl, sdl, sizeof (struct sockaddr_dl)); + memcpy(&((struct zebra_if *)ifp->info)->sdl, sdl, + sizeof(struct sockaddr_dl)); #endif /* HAVE_STRUCT_SOCKADDR_DL_SDL_LEN */ - ifp->ll_type = sdl_to_zebra_link_type (sdl->sdl_type); - if (sdl->sdl_alen <= sizeof(ifp->hw_addr)) - { - memcpy (ifp->hw_addr, LLADDR(sdl), sdl->sdl_alen); - ifp->hw_addr_len = sdl->sdl_alen; - } - } - - if_add_update (ifp); - } - else - /* - * Interface structure exists. Adjust stored flags from - * notification. If interface has up->down or down->up - * transition, call state change routines (to adjust routes, - * notify routing daemons, etc.). (Other flag changes are stored - * but apparently do not trigger action.) - */ - { - if (ifp->ifindex != ifm->ifm_index) - { - zlog_warn ("%s: index mismatch, ifname %s, ifp index %d, " - "ifm index %d", - __func__, ifp->name, ifp->ifindex, ifm->ifm_index); - return -1; - } - + ifp->ll_type = sdl_to_zebra_link_type(sdl->sdl_type); + if (sdl->sdl_alen <= sizeof(ifp->hw_addr)) { + memcpy(ifp->hw_addr, LLADDR(sdl), + sdl->sdl_alen); + ifp->hw_addr_len = sdl->sdl_alen; + } + } + + if_add_update(ifp); + } else + /* + * Interface structure exists. Adjust stored flags from + * notification. If interface has up->down or down->up + * transition, call state change routines (to adjust routes, + * notify routing daemons, etc.). (Other flag changes are stored + * but apparently do not trigger action.) + */ + { + if (ifp->ifindex != ifm->ifm_index) { + zlog_warn( + "%s: index mismatch, ifname %s, ifp index %d, " + "ifm index %d", + __func__, ifp->name, ifp->ifindex, + ifm->ifm_index); + return -1; + } + #ifdef HAVE_BSD_IFI_LINK_STATE /* translate BSD kernel msg for link-state */ - bsd_linkdetect_translate(ifm); + bsd_linkdetect_translate(ifm); #endif /* HAVE_BSD_IFI_LINK_STATE */ - /* update flags and handle operative->inoperative transition, if any */ - if_flags_update (ifp, ifm->ifm_flags); - + /* update flags and handle operative->inoperative transition, if + * any */ + if_flags_update(ifp, ifm->ifm_flags); + #ifndef RTM_IFANNOUNCE - if (!if_is_up (ifp)) - { - /* No RTM_IFANNOUNCE on this platform, so we can never - * distinguish between ~IFF_UP and delete. We must presume - * it has been deleted. - * Eg, Solaris will not notify us of unplumb. - * - * XXX: Fixme - this should be runtime detected - * So that a binary compiled on a system with IFANNOUNCE - * will still behave correctly if run on a platform without - */ - if_delete_update (ifp); - } + if (!if_is_up(ifp)) { + /* No RTM_IFANNOUNCE on this platform, so we can never + * distinguish between ~IFF_UP and delete. We must + * presume + * it has been deleted. + * Eg, Solaris will not notify us of unplumb. + * + * XXX: Fixme - this should be runtime detected + * So that a binary compiled on a system with IFANNOUNCE + * will still behave correctly if run on a platform + * without + */ + if_delete_update(ifp); + } #endif /* RTM_IFANNOUNCE */ - if (if_is_up (ifp)) - { + if (if_is_up(ifp)) { #if defined(__bsdi__) - if_kvm_get_mtu (ifp); + if_kvm_get_mtu(ifp); #else - if_get_mtu (ifp); + if_get_mtu(ifp); #endif /* __bsdi__ */ - if_get_metric (ifp); - } - } + if_get_metric(ifp); + } + } #ifdef HAVE_NET_RT_IFLIST - ifp->stats = ifm->ifm_data; + ifp->stats = ifm->ifm_data; #endif /* HAVE_NET_RT_IFLIST */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: interface %s index %d", - __func__, ifp->name, ifp->ifindex); + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: interface %s index %d", __func__, ifp->name, + ifp->ifindex); - return 0; + return 0; } /* Address read from struct ifa_msghdr. */ -static void -ifam_read_mesg (struct ifa_msghdr *ifm, - union sockunion *addr, - union sockunion *mask, - union sockunion *brd, - char *ifname, - short *ifnlen) +static void ifam_read_mesg(struct ifa_msghdr *ifm, union sockunion *addr, + union sockunion *mask, union sockunion *brd, + char *ifname, short *ifnlen) { - caddr_t pnt, end; - union sockunion dst; - union sockunion gateway; - - pnt = (caddr_t)(ifm + 1); - end = ((caddr_t)ifm) + ifm->ifam_msglen; - - /* Be sure structure is cleared */ - memset (mask, 0, sizeof (union sockunion)); - memset (addr, 0, sizeof (union sockunion)); - memset (brd, 0, sizeof (union sockunion)); - memset (&dst, 0, sizeof (union sockunion)); - memset (&gateway, 0, sizeof (union sockunion)); - - /* We fetch each socket variable into sockunion. */ - RTA_ADDR_GET (&dst, RTA_DST, ifm->ifam_addrs, pnt); - RTA_ADDR_GET (&gateway, RTA_GATEWAY, ifm->ifam_addrs, pnt); - RTA_ATTR_GET (mask, RTA_NETMASK, ifm->ifam_addrs, pnt); - RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifam_addrs, pnt); - RTA_NAME_GET (ifname, RTA_IFP, ifm->ifam_addrs, pnt, *ifnlen); - RTA_ADDR_GET (addr, RTA_IFA, ifm->ifam_addrs, pnt); - RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifam_addrs, pnt); - RTA_ADDR_GET (brd, RTA_BRD, ifm->ifam_addrs, pnt); - - if (IS_ZEBRA_DEBUG_KERNEL) - { - int family = sockunion_family(addr); - switch (family) - { - case AF_INET: - case AF_INET6: - { - char buf[4][INET6_ADDRSTRLEN]; - zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x, " - "ifam_flags 0x%x, addr %s/%d broad %s dst %s " - "gateway %s", - __func__, ifm->ifam_index, - (ifnlen ? ifname : "(nil)"), ifm->ifam_addrs, - ifm->ifam_flags, - inet_ntop(family,&addr->sin.sin_addr, - buf[0],sizeof(buf[0])), - ip_masklen(mask->sin.sin_addr), - inet_ntop(family,&brd->sin.sin_addr, - buf[1],sizeof(buf[1])), - inet_ntop(family,&dst.sin.sin_addr, - buf[2],sizeof(buf[2])), - inet_ntop(family,&gateway.sin.sin_addr, - buf[3],sizeof(buf[3]))); - } - break; - default: - zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x", - __func__, ifm->ifam_index, - (ifnlen ? ifname : "(nil)"), ifm->ifam_addrs); - break; - } - } - - /* Assert read up end point matches to end point */ - if (pnt != end) - zlog_warn ("ifam_read() doesn't read all socket data"); + caddr_t pnt, end; + union sockunion dst; + union sockunion gateway; + + pnt = (caddr_t)(ifm + 1); + end = ((caddr_t)ifm) + ifm->ifam_msglen; + + /* Be sure structure is cleared */ + memset(mask, 0, sizeof(union sockunion)); + memset(addr, 0, sizeof(union sockunion)); + memset(brd, 0, sizeof(union sockunion)); + memset(&dst, 0, sizeof(union sockunion)); + memset(&gateway, 0, sizeof(union sockunion)); + + /* We fetch each socket variable into sockunion. */ + RTA_ADDR_GET(&dst, RTA_DST, ifm->ifam_addrs, pnt); + RTA_ADDR_GET(&gateway, RTA_GATEWAY, ifm->ifam_addrs, pnt); + RTA_ATTR_GET(mask, RTA_NETMASK, ifm->ifam_addrs, pnt); + RTA_ADDR_GET(NULL, RTA_GENMASK, ifm->ifam_addrs, pnt); + RTA_NAME_GET(ifname, RTA_IFP, ifm->ifam_addrs, pnt, *ifnlen); + RTA_ADDR_GET(addr, RTA_IFA, ifm->ifam_addrs, pnt); + RTA_ADDR_GET(NULL, RTA_AUTHOR, ifm->ifam_addrs, pnt); + RTA_ADDR_GET(brd, RTA_BRD, ifm->ifam_addrs, pnt); + + if (IS_ZEBRA_DEBUG_KERNEL) { + int family = sockunion_family(addr); + switch (family) { + case AF_INET: + case AF_INET6: { + char buf[4][INET6_ADDRSTRLEN]; + zlog_debug( + "%s: ifindex %d, ifname %s, ifam_addrs 0x%x, " + "ifam_flags 0x%x, addr %s/%d broad %s dst %s " + "gateway %s", + __func__, ifm->ifam_index, + (ifnlen ? ifname : "(nil)"), ifm->ifam_addrs, + ifm->ifam_flags, + inet_ntop(family, &addr->sin.sin_addr, buf[0], + sizeof(buf[0])), + ip_masklen(mask->sin.sin_addr), + inet_ntop(family, &brd->sin.sin_addr, buf[1], + sizeof(buf[1])), + inet_ntop(family, &dst.sin.sin_addr, buf[2], + sizeof(buf[2])), + inet_ntop(family, &gateway.sin.sin_addr, buf[3], + sizeof(buf[3]))); + } break; + default: + zlog_debug("%s: ifindex %d, ifname %s, ifam_addrs 0x%x", + __func__, ifm->ifam_index, + (ifnlen ? ifname : "(nil)"), + ifm->ifam_addrs); + break; + } + } + + /* Assert read up end point matches to end point */ + if (pnt != end) + zlog_warn("ifam_read() doesn't read all socket data"); } /* Interface's address information get. */ -int -ifam_read (struct ifa_msghdr *ifam) +int ifam_read(struct ifa_msghdr *ifam) { - struct interface *ifp = NULL; - union sockunion addr, mask, brd; - char ifname[INTERFACE_NAMSIZ]; - short ifnlen = 0; - char isalias = 0; - int flags = 0; - - ifname[0] = ifname[INTERFACE_NAMSIZ - 1] = '\0'; - - /* Allocate and read address information. */ - ifam_read_mesg (ifam, &addr, &mask, &brd, ifname, &ifnlen); - - if ((ifp = if_lookup_by_index(ifam->ifam_index, VRF_DEFAULT)) == NULL) - { - zlog_warn ("%s: no interface for ifname %s, index %d", - __func__, ifname, ifam->ifam_index); - return -1; - } - - if (ifnlen && strncmp (ifp->name, ifname, INTERFACE_NAMSIZ)) - isalias = 1; - - /* N.B. The info in ifa_msghdr does not tell us whether the RTA_BRD - field contains a broadcast address or a peer address, so we are forced to - rely upon the interface type. */ - if (if_is_pointopoint(ifp)) - SET_FLAG(flags, ZEBRA_IFA_PEER); + struct interface *ifp = NULL; + union sockunion addr, mask, brd; + char ifname[INTERFACE_NAMSIZ]; + short ifnlen = 0; + char isalias = 0; + int flags = 0; + + ifname[0] = ifname[INTERFACE_NAMSIZ - 1] = '\0'; + + /* Allocate and read address information. */ + ifam_read_mesg(ifam, &addr, &mask, &brd, ifname, &ifnlen); + + if ((ifp = if_lookup_by_index(ifam->ifam_index, VRF_DEFAULT)) == NULL) { + zlog_warn("%s: no interface for ifname %s, index %d", __func__, + ifname, ifam->ifam_index); + return -1; + } + + if (ifnlen && strncmp(ifp->name, ifname, INTERFACE_NAMSIZ)) + isalias = 1; + + /* N.B. The info in ifa_msghdr does not tell us whether the RTA_BRD + field contains a broadcast address or a peer address, so we are + forced to + rely upon the interface type. */ + if (if_is_pointopoint(ifp)) + SET_FLAG(flags, ZEBRA_IFA_PEER); #if 0 /* it might seem cute to grab the interface metric here, however @@ -748,450 +738,477 @@ ifam_read (struct ifa_msghdr *ifam) ifp->metric = ifam->ifam_metric; #endif - /* Add connected address. */ - switch (sockunion_family (&addr)) - { - case AF_INET: - if (ifam->ifam_type == RTM_NEWADDR) - connected_add_ipv4 (ifp, flags, &addr.sin.sin_addr, - ip_masklen (mask.sin.sin_addr), - &brd.sin.sin_addr, - (isalias ? ifname : NULL)); - else - connected_delete_ipv4 (ifp, flags, &addr.sin.sin_addr, - ip_masklen (mask.sin.sin_addr), - &brd.sin.sin_addr); - break; - case AF_INET6: - /* Unset interface index from link-local address when IPv6 stack - is KAME. */ - if (IN6_IS_ADDR_LINKLOCAL (&addr.sin6.sin6_addr)) - { - SET_IN6_LINKLOCAL_IFINDEX (addr.sin6.sin6_addr, 0); - } - - if (ifam->ifam_type == RTM_NEWADDR) - connected_add_ipv6 (ifp, flags, &addr.sin6.sin6_addr, - ip6_masklen (mask.sin6.sin6_addr), - &brd.sin6.sin6_addr, - (isalias ? ifname : NULL)); - else - connected_delete_ipv6 (ifp, - &addr.sin6.sin6_addr, - ip6_masklen (mask.sin6.sin6_addr), - &brd.sin6.sin6_addr); - break; - default: - /* Unsupported family silently ignore... */ - break; - } - - /* Check interface flag for implicit up of the interface. */ - if_refresh (ifp); + /* Add connected address. */ + switch (sockunion_family(&addr)) { + case AF_INET: + if (ifam->ifam_type == RTM_NEWADDR) + connected_add_ipv4(ifp, flags, &addr.sin.sin_addr, + ip_masklen(mask.sin.sin_addr), + &brd.sin.sin_addr, + (isalias ? ifname : NULL)); + else + connected_delete_ipv4(ifp, flags, &addr.sin.sin_addr, + ip_masklen(mask.sin.sin_addr), + &brd.sin.sin_addr); + break; + case AF_INET6: + /* Unset interface index from link-local address when IPv6 stack + is KAME. */ + if (IN6_IS_ADDR_LINKLOCAL(&addr.sin6.sin6_addr)) { + SET_IN6_LINKLOCAL_IFINDEX(addr.sin6.sin6_addr, 0); + } + + if (ifam->ifam_type == RTM_NEWADDR) + connected_add_ipv6(ifp, flags, &addr.sin6.sin6_addr, + ip6_masklen(mask.sin6.sin6_addr), + &brd.sin6.sin6_addr, + (isalias ? ifname : NULL)); + else + connected_delete_ipv6(ifp, &addr.sin6.sin6_addr, + ip6_masklen(mask.sin6.sin6_addr), + &brd.sin6.sin6_addr); + break; + default: + /* Unsupported family silently ignore... */ + break; + } + + /* Check interface flag for implicit up of the interface. */ + if_refresh(ifp); #ifdef SUNOS_5 - /* In addition to lacking IFANNOUNCE, on SUNOS IFF_UP is strange. - * See comments for SUNOS_5 in interface.c::if_flags_mangle. - * - * Here we take care of case where the real IFF_UP was previously - * unset (as kept in struct zebra_if.primary_state) and the mangled - * IFF_UP (ie IFF_UP set || listcount(connected) has now transitioned - * to unset due to the lost non-primary address having DELADDR'd. - * - * we must delete the interface, because in between here and next - * event for this interface-name the administrator could unplumb - * and replumb the interface. - */ - if (!if_is_up (ifp)) - if_delete_update (ifp); + /* In addition to lacking IFANNOUNCE, on SUNOS IFF_UP is strange. + * See comments for SUNOS_5 in interface.c::if_flags_mangle. + * + * Here we take care of case where the real IFF_UP was previously + * unset (as kept in struct zebra_if.primary_state) and the mangled + * IFF_UP (ie IFF_UP set || listcount(connected) has now transitioned + * to unset due to the lost non-primary address having DELADDR'd. + * + * we must delete the interface, because in between here and next + * event for this interface-name the administrator could unplumb + * and replumb the interface. + */ + if (!if_is_up(ifp)) + if_delete_update(ifp); #endif /* SUNOS_5 */ - - return 0; + + return 0; } /* Interface function for reading kernel routing table information. */ -static int -rtm_read_mesg (struct rt_msghdr *rtm, - union sockunion *dest, - union sockunion *mask, - union sockunion *gate, - char *ifname, - short *ifnlen) +static int rtm_read_mesg(struct rt_msghdr *rtm, union sockunion *dest, + union sockunion *mask, union sockunion *gate, + char *ifname, short *ifnlen) { - caddr_t pnt, end; - - /* Pnt points out socket data start point. */ - pnt = (caddr_t)(rtm + 1); - end = ((caddr_t)rtm) + rtm->rtm_msglen; - - /* rt_msghdr version check. */ - if (rtm->rtm_version != RTM_VERSION) - zlog_warn("Routing message version different %d should be %d." "This may cause problem\n", - rtm->rtm_version, RTM_VERSION); - - /* Be sure structure is cleared */ - memset (dest, 0, sizeof (union sockunion)); - memset (gate, 0, sizeof (union sockunion)); - memset (mask, 0, sizeof (union sockunion)); - - /* We fetch each socket variable into sockunion. */ - RTA_ADDR_GET (dest, RTA_DST, rtm->rtm_addrs, pnt); - RTA_ADDR_GET (gate, RTA_GATEWAY, rtm->rtm_addrs, pnt); - RTA_ATTR_GET (mask, RTA_NETMASK, rtm->rtm_addrs, pnt); - RTA_ADDR_GET (NULL, RTA_GENMASK, rtm->rtm_addrs, pnt); - RTA_NAME_GET (ifname, RTA_IFP, rtm->rtm_addrs, pnt, *ifnlen); - RTA_ADDR_GET (NULL, RTA_IFA, rtm->rtm_addrs, pnt); - RTA_ADDR_GET (NULL, RTA_AUTHOR, rtm->rtm_addrs, pnt); - RTA_ADDR_GET (NULL, RTA_BRD, rtm->rtm_addrs, pnt); - - /* If there is netmask information set it's family same as - destination family*/ - if (rtm->rtm_addrs & RTA_NETMASK) - mask->sa.sa_family = dest->sa.sa_family; - - /* Assert read up to the end of pointer. */ - if (pnt != end) - zlog_warn("rtm_read() doesn't read all socket data."); - - return rtm->rtm_flags; + caddr_t pnt, end; + + /* Pnt points out socket data start point. */ + pnt = (caddr_t)(rtm + 1); + end = ((caddr_t)rtm) + rtm->rtm_msglen; + + /* rt_msghdr version check. */ + if (rtm->rtm_version != RTM_VERSION) + zlog_warn( + "Routing message version different %d should be %d." + "This may cause problem\n", + rtm->rtm_version, RTM_VERSION); + + /* Be sure structure is cleared */ + memset(dest, 0, sizeof(union sockunion)); + memset(gate, 0, sizeof(union sockunion)); + memset(mask, 0, sizeof(union sockunion)); + + /* We fetch each socket variable into sockunion. */ + RTA_ADDR_GET(dest, RTA_DST, rtm->rtm_addrs, pnt); + RTA_ADDR_GET(gate, RTA_GATEWAY, rtm->rtm_addrs, pnt); + RTA_ATTR_GET(mask, RTA_NETMASK, rtm->rtm_addrs, pnt); + RTA_ADDR_GET(NULL, RTA_GENMASK, rtm->rtm_addrs, pnt); + RTA_NAME_GET(ifname, RTA_IFP, rtm->rtm_addrs, pnt, *ifnlen); + RTA_ADDR_GET(NULL, RTA_IFA, rtm->rtm_addrs, pnt); + RTA_ADDR_GET(NULL, RTA_AUTHOR, rtm->rtm_addrs, pnt); + RTA_ADDR_GET(NULL, RTA_BRD, rtm->rtm_addrs, pnt); + + /* If there is netmask information set it's family same as + destination family*/ + if (rtm->rtm_addrs & RTA_NETMASK) + mask->sa.sa_family = dest->sa.sa_family; + + /* Assert read up to the end of pointer. */ + if (pnt != end) + zlog_warn("rtm_read() doesn't read all socket data."); + + return rtm->rtm_flags; } -void -rtm_read (struct rt_msghdr *rtm) +void rtm_read(struct rt_msghdr *rtm) { - int flags; - u_char zebra_flags; - union sockunion dest, mask, gate; - char ifname[INTERFACE_NAMSIZ + 1]; - short ifnlen = 0; - - zebra_flags = 0; - - /* Read destination and netmask and gateway from rtm message - structure. */ - flags = rtm_read_mesg (rtm, &dest, &mask, &gate, ifname, &ifnlen); - if (!(flags & RTF_DONE)) - return; - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: got rtm of type %d (%s)", __func__, rtm->rtm_type, - lookup_msg(rtm_type_str, rtm->rtm_type, NULL)); - -#ifdef RTF_CLONED /*bsdi, netbsd 1.6*/ - if (flags & RTF_CLONED) - return; + int flags; + u_char zebra_flags; + union sockunion dest, mask, gate; + char ifname[INTERFACE_NAMSIZ + 1]; + short ifnlen = 0; + + zebra_flags = 0; + + /* Read destination and netmask and gateway from rtm message + structure. */ + flags = rtm_read_mesg(rtm, &dest, &mask, &gate, ifname, &ifnlen); + if (!(flags & RTF_DONE)) + return; + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: got rtm of type %d (%s)", __func__, + rtm->rtm_type, + lookup_msg(rtm_type_str, rtm->rtm_type, NULL)); + +#ifdef RTF_CLONED /*bsdi, netbsd 1.6*/ + if (flags & RTF_CLONED) + return; #endif -#ifdef RTF_WASCLONED /*freebsd*/ - if (flags & RTF_WASCLONED) - return; +#ifdef RTF_WASCLONED /*freebsd*/ + if (flags & RTF_WASCLONED) + return; #endif - if ((rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) && ! (flags & RTF_UP)) - return; - - /* This is connected route. */ - if (! (flags & RTF_GATEWAY)) - return; - - if (flags & RTF_PROTO1) - SET_FLAG (zebra_flags, ZEBRA_FLAG_SELFROUTE); - - /* This is persistent route. */ - if (flags & RTF_STATIC) - SET_FLAG (zebra_flags, ZEBRA_FLAG_STATIC); - - /* This is a reject or blackhole route */ - if (flags & RTF_REJECT) - SET_FLAG (zebra_flags, ZEBRA_FLAG_REJECT); - if (flags & RTF_BLACKHOLE) - SET_FLAG (zebra_flags, ZEBRA_FLAG_BLACKHOLE); - - if (dest.sa.sa_family == AF_INET) - { - struct prefix p; - - p.family = AF_INET; - p.u.prefix4 = dest.sin.sin_addr; - if (flags & RTF_HOST) - p.prefixlen = IPV4_MAX_PREFIXLEN; - else - p.prefixlen = ip_masklen (mask.sin.sin_addr); - - /* Catch self originated messages and match them against our current RIB. - * At the same time, ignore unconfirmed messages, they should be tracked - * by rtm_write() and kernel_rtm_ipv4(). - */ - if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid) - { - char buf[PREFIX_STRLEN], gate_buf[INET_ADDRSTRLEN]; - int ret; - if (! IS_ZEBRA_DEBUG_RIB) - return; - ret = rib_lookup_ipv4_route ((struct prefix_ipv4 *)&p, &gate, VRF_DEFAULT); - prefix2str (&p, buf, sizeof(buf)); - switch (rtm->rtm_type) - { - case RTM_ADD: - case RTM_GET: - case RTM_CHANGE: - /* The kernel notifies us about a new route in FIB created by us. - Do we have a correspondent entry in our RIB? */ - switch (ret) - { - case ZEBRA_RIB_NOTFOUND: - zlog_debug ("%s: %s %s: desync: RR isn't yet in RIB, while already in FIB", - __func__, lookup_msg(rtm_type_str, rtm->rtm_type, NULL), buf); - break; - case ZEBRA_RIB_FOUND_CONNECTED: - case ZEBRA_RIB_FOUND_NOGATE: - inet_ntop (AF_INET, &gate.sin.sin_addr, gate_buf, INET_ADDRSTRLEN); - zlog_debug ("%s: %s %s: desync: RR is in RIB, but gate differs (ours is %s)", - __func__, lookup_msg(rtm_type_str, rtm->rtm_type, NULL), buf, gate_buf); - break; - case ZEBRA_RIB_FOUND_EXACT: /* RIB RR == FIB RR */ - zlog_debug ("%s: %s %s: done Ok", - __func__, lookup_msg(rtm_type_str, rtm->rtm_type, NULL), buf); - rib_lookup_and_dump ((struct prefix_ipv4 *)&p, VRF_DEFAULT); - return; - break; - } - break; - case RTM_DELETE: - /* The kernel notifies us about a route deleted by us. Do we still - have it in the RIB? Do we have anything instead? */ - switch (ret) - { - case ZEBRA_RIB_FOUND_EXACT: - zlog_debug ("%s: %s %s: desync: RR is still in RIB, while already not in FIB", - __func__, lookup_msg(rtm_type_str, rtm->rtm_type, NULL), buf); - rib_lookup_and_dump ((struct prefix_ipv4 *)&p, VRF_DEFAULT); - break; - case ZEBRA_RIB_FOUND_CONNECTED: - case ZEBRA_RIB_FOUND_NOGATE: - zlog_debug ("%s: %s %s: desync: RR is still in RIB, plus gate differs", - __func__, lookup_msg(rtm_type_str, rtm->rtm_type, NULL), buf); - rib_lookup_and_dump ((struct prefix_ipv4 *)&p, VRF_DEFAULT); - break; - case ZEBRA_RIB_NOTFOUND: /* RIB RR == FIB RR */ - zlog_debug ("%s: %s %s: done Ok", - __func__, lookup_msg(rtm_type_str, rtm->rtm_type, NULL), buf); - rib_lookup_and_dump ((struct prefix_ipv4 *)&p, VRF_DEFAULT); - return; - break; - } - break; - default: - zlog_debug ("%s: %s: warning: loopback RTM of type %s received", - __func__, buf, lookup_msg(rtm_type_str, rtm->rtm_type, NULL)); - } - return; - } - - /* Change, delete the old prefix, we have no further information - * to specify the route really - */ - if (rtm->rtm_type == RTM_CHANGE) - rib_delete (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, - 0, zebra_flags, &p, NULL, NULL, 0, 0); - - union g_addr ggate = { .ipv4 = gate.sin.sin_addr }; - if (rtm->rtm_type == RTM_GET - || rtm->rtm_type == RTM_ADD - || rtm->rtm_type == RTM_CHANGE) - rib_add (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, NULL, &ggate, NULL, 0, 0, 0, 0, 0); - else - rib_delete (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, - 0, zebra_flags, &p, NULL, &ggate, 0, 0); - } - if (dest.sa.sa_family == AF_INET6) - { - /* One day we might have a debug section here like one in the - * IPv4 case above. Just ignore own messages at the moment. - */ - if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid) - return; - struct prefix p; - ifindex_t ifindex = 0; - - p.family = AF_INET6; - p.u.prefix6 = dest.sin6.sin6_addr; - if (flags & RTF_HOST) - p.prefixlen = IPV6_MAX_PREFIXLEN; - else - p.prefixlen = ip6_masklen (mask.sin6.sin6_addr); + if ((rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) + && !(flags & RTF_UP)) + return; + + /* This is connected route. */ + if (!(flags & RTF_GATEWAY)) + return; + + if (flags & RTF_PROTO1) + SET_FLAG(zebra_flags, ZEBRA_FLAG_SELFROUTE); + + /* This is persistent route. */ + if (flags & RTF_STATIC) + SET_FLAG(zebra_flags, ZEBRA_FLAG_STATIC); + + /* This is a reject or blackhole route */ + if (flags & RTF_REJECT) + SET_FLAG(zebra_flags, ZEBRA_FLAG_REJECT); + if (flags & RTF_BLACKHOLE) + SET_FLAG(zebra_flags, ZEBRA_FLAG_BLACKHOLE); + + if (dest.sa.sa_family == AF_INET) { + struct prefix p; + + p.family = AF_INET; + p.u.prefix4 = dest.sin.sin_addr; + if (flags & RTF_HOST) + p.prefixlen = IPV4_MAX_PREFIXLEN; + else + p.prefixlen = ip_masklen(mask.sin.sin_addr); + + /* Catch self originated messages and match them against our + * current RIB. + * At the same time, ignore unconfirmed messages, they should be + * tracked + * by rtm_write() and kernel_rtm_ipv4(). + */ + if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid) { + char buf[PREFIX_STRLEN], gate_buf[INET_ADDRSTRLEN]; + int ret; + if (!IS_ZEBRA_DEBUG_RIB) + return; + ret = rib_lookup_ipv4_route((struct prefix_ipv4 *)&p, + &gate, VRF_DEFAULT); + prefix2str(&p, buf, sizeof(buf)); + switch (rtm->rtm_type) { + case RTM_ADD: + case RTM_GET: + case RTM_CHANGE: + /* The kernel notifies us about a new route in + FIB created by us. + Do we have a correspondent entry in our RIB? + */ + switch (ret) { + case ZEBRA_RIB_NOTFOUND: + zlog_debug( + "%s: %s %s: desync: RR isn't yet in RIB, while already in FIB", + __func__, + lookup_msg(rtm_type_str, + rtm->rtm_type, NULL), + buf); + break; + case ZEBRA_RIB_FOUND_CONNECTED: + case ZEBRA_RIB_FOUND_NOGATE: + inet_ntop(AF_INET, &gate.sin.sin_addr, + gate_buf, INET_ADDRSTRLEN); + zlog_debug( + "%s: %s %s: desync: RR is in RIB, but gate differs (ours is %s)", + __func__, + lookup_msg(rtm_type_str, + rtm->rtm_type, NULL), + buf, gate_buf); + break; + case ZEBRA_RIB_FOUND_EXACT: /* RIB RR == FIB RR + */ + zlog_debug( + "%s: %s %s: done Ok", __func__, + lookup_msg(rtm_type_str, + rtm->rtm_type, NULL), + buf); + rib_lookup_and_dump( + (struct prefix_ipv4 *)&p, + VRF_DEFAULT); + return; + break; + } + break; + case RTM_DELETE: + /* The kernel notifies us about a route deleted + by us. Do we still + have it in the RIB? Do we have anything + instead? */ + switch (ret) { + case ZEBRA_RIB_FOUND_EXACT: + zlog_debug( + "%s: %s %s: desync: RR is still in RIB, while already not in FIB", + __func__, + lookup_msg(rtm_type_str, + rtm->rtm_type, NULL), + buf); + rib_lookup_and_dump( + (struct prefix_ipv4 *)&p, + VRF_DEFAULT); + break; + case ZEBRA_RIB_FOUND_CONNECTED: + case ZEBRA_RIB_FOUND_NOGATE: + zlog_debug( + "%s: %s %s: desync: RR is still in RIB, plus gate differs", + __func__, + lookup_msg(rtm_type_str, + rtm->rtm_type, NULL), + buf); + rib_lookup_and_dump( + (struct prefix_ipv4 *)&p, + VRF_DEFAULT); + break; + case ZEBRA_RIB_NOTFOUND: /* RIB RR == FIB RR */ + zlog_debug( + "%s: %s %s: done Ok", __func__, + lookup_msg(rtm_type_str, + rtm->rtm_type, NULL), + buf); + rib_lookup_and_dump( + (struct prefix_ipv4 *)&p, + VRF_DEFAULT); + return; + break; + } + break; + default: + zlog_debug( + "%s: %s: warning: loopback RTM of type %s received", + __func__, buf, + lookup_msg(rtm_type_str, rtm->rtm_type, + NULL)); + } + return; + } + + /* Change, delete the old prefix, we have no further information + * to specify the route really + */ + if (rtm->rtm_type == RTM_CHANGE) + rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, + ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, + NULL, 0, 0); + + union g_addr ggate = {.ipv4 = gate.sin.sin_addr}; + if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD + || rtm->rtm_type == RTM_CHANGE) + rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, + ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, + &ggate, NULL, 0, 0, 0, 0, 0); + else + rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, + ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, + &ggate, 0, 0); + } + if (dest.sa.sa_family == AF_INET6) { + /* One day we might have a debug section here like one in the + * IPv4 case above. Just ignore own messages at the moment. + */ + if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid) + return; + struct prefix p; + ifindex_t ifindex = 0; + + p.family = AF_INET6; + p.u.prefix6 = dest.sin6.sin6_addr; + if (flags & RTF_HOST) + p.prefixlen = IPV6_MAX_PREFIXLEN; + else + p.prefixlen = ip6_masklen(mask.sin6.sin6_addr); #ifdef KAME - if (IN6_IS_ADDR_LINKLOCAL (&gate.sin6.sin6_addr)) - { - ifindex = IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr); - SET_IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr, 0); - } + if (IN6_IS_ADDR_LINKLOCAL(&gate.sin6.sin6_addr)) { + ifindex = IN6_LINKLOCAL_IFINDEX(gate.sin6.sin6_addr); + SET_IN6_LINKLOCAL_IFINDEX(gate.sin6.sin6_addr, 0); + } #endif /* KAME */ - /* CHANGE: delete the old prefix, we have no further information - * to specify the route really - */ - if (rtm->rtm_type == RTM_CHANGE) - rib_delete (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, - 0, zebra_flags, &p, NULL, NULL, 0, 0); - - union g_addr ggate = { .ipv6 = gate.sin6.sin6_addr }; - if (rtm->rtm_type == RTM_GET - || rtm->rtm_type == RTM_ADD - || rtm->rtm_type == RTM_CHANGE) - rib_add (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, - 0, zebra_flags, &p, NULL, &ggate, NULL, ifindex, - 0, 0, 0, 0); - else - rib_delete (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, - 0, zebra_flags, &p, NULL, &ggate, ifindex, 0); - } + /* CHANGE: delete the old prefix, we have no further information + * to specify the route really + */ + if (rtm->rtm_type == RTM_CHANGE) + rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, + ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, + NULL, 0, 0); + + union g_addr ggate = {.ipv6 = gate.sin6.sin6_addr}; + if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD + || rtm->rtm_type == RTM_CHANGE) + rib_add(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, + ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, + &ggate, NULL, ifindex, 0, 0, 0, 0); + else + rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, + ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, + &ggate, ifindex, 0); + } } /* Interface function for the kernel routing table updates. Support * for RTM_CHANGE will be needed. * Exported only for rt_socket.c */ -int -rtm_write (int message, - union sockunion *dest, - union sockunion *mask, - union sockunion *gate, - union sockunion *mpls, - unsigned int index, - int zebra_flags, - int metric) +int rtm_write(int message, union sockunion *dest, union sockunion *mask, + union sockunion *gate, union sockunion *mpls, unsigned int index, + int zebra_flags, int metric) { - int ret; - caddr_t pnt; - struct interface *ifp; - - /* Sequencial number of routing message. */ - static int msg_seq = 0; - - /* Struct of rt_msghdr and buffer for storing socket's data. */ - struct - { - struct rt_msghdr rtm; - char buf[512]; - } msg; - - if (routing_sock < 0) - return ZEBRA_ERR_EPERM; - - /* Clear and set rt_msghdr values */ - memset (&msg, 0, sizeof (struct rt_msghdr)); - msg.rtm.rtm_version = RTM_VERSION; - msg.rtm.rtm_type = message; - msg.rtm.rtm_seq = msg_seq++; - msg.rtm.rtm_addrs = RTA_DST; - msg.rtm.rtm_addrs |= RTA_GATEWAY; - msg.rtm.rtm_flags = RTF_UP; + int ret; + caddr_t pnt; + struct interface *ifp; + + /* Sequencial number of routing message. */ + static int msg_seq = 0; + + /* Struct of rt_msghdr and buffer for storing socket's data. */ + struct { + struct rt_msghdr rtm; + char buf[512]; + } msg; + + if (routing_sock < 0) + return ZEBRA_ERR_EPERM; + + /* Clear and set rt_msghdr values */ + memset(&msg, 0, sizeof(struct rt_msghdr)); + msg.rtm.rtm_version = RTM_VERSION; + msg.rtm.rtm_type = message; + msg.rtm.rtm_seq = msg_seq++; + msg.rtm.rtm_addrs = RTA_DST; + msg.rtm.rtm_addrs |= RTA_GATEWAY; + msg.rtm.rtm_flags = RTF_UP; #ifdef __OpenBSD__ - msg.rtm.rtm_flags |= RTF_MPATH; - msg.rtm.rtm_fmask = RTF_MPLS; + msg.rtm.rtm_flags |= RTF_MPATH; + msg.rtm.rtm_fmask = RTF_MPLS; #endif - msg.rtm.rtm_index = index; + msg.rtm.rtm_index = index; - if (metric != 0) - { - msg.rtm.rtm_rmx.rmx_hopcount = metric; - msg.rtm.rtm_inits |= RTV_HOPCOUNT; - } + if (metric != 0) { + msg.rtm.rtm_rmx.rmx_hopcount = metric; + msg.rtm.rtm_inits |= RTV_HOPCOUNT; + } - ifp = if_lookup_by_index (index, VRF_DEFAULT); + ifp = if_lookup_by_index(index, VRF_DEFAULT); - if (gate && (message == RTM_ADD || message == RTM_CHANGE)) - msg.rtm.rtm_flags |= RTF_GATEWAY; + if (gate && (message == RTM_ADD || message == RTM_CHANGE)) + msg.rtm.rtm_flags |= RTF_GATEWAY; - /* When RTF_CLONING is unavailable on BSD, should we set some - * other flag instead? - */ +/* When RTF_CLONING is unavailable on BSD, should we set some + * other flag instead? + */ #ifdef RTF_CLONING - if (! gate && (message == RTM_ADD || message == RTM_CHANGE) && ifp && - (ifp->flags & IFF_POINTOPOINT) == 0) - msg.rtm.rtm_flags |= RTF_CLONING; + if (!gate && (message == RTM_ADD || message == RTM_CHANGE) && ifp + && (ifp->flags & IFF_POINTOPOINT) == 0) + msg.rtm.rtm_flags |= RTF_CLONING; #endif /* RTF_CLONING */ - /* If no protocol specific gateway is specified, use link - address for gateway. */ - if (! gate) - { - if (!ifp) - { - char dest_buf[INET_ADDRSTRLEN] = "NULL", mask_buf[INET_ADDRSTRLEN] = "255.255.255.255"; - if (dest) - inet_ntop (AF_INET, &dest->sin.sin_addr, dest_buf, INET_ADDRSTRLEN); - if (mask) - inet_ntop (AF_INET, &mask->sin.sin_addr, mask_buf, INET_ADDRSTRLEN); - zlog_warn ("%s: %s/%s: gate == NULL and no gateway found for ifindex %d", - __func__, dest_buf, mask_buf, index); - return -1; - } - gate = (union sockunion *) &((struct zebra_if *)ifp->info)->sdl; - } - - if (mask) - msg.rtm.rtm_addrs |= RTA_NETMASK; - else if (message == RTM_ADD || message == RTM_CHANGE) - msg.rtm.rtm_flags |= RTF_HOST; + /* If no protocol specific gateway is specified, use link + address for gateway. */ + if (!gate) { + if (!ifp) { + char dest_buf[INET_ADDRSTRLEN] = "NULL", + mask_buf[INET_ADDRSTRLEN] = "255.255.255.255"; + if (dest) + inet_ntop(AF_INET, &dest->sin.sin_addr, + dest_buf, INET_ADDRSTRLEN); + if (mask) + inet_ntop(AF_INET, &mask->sin.sin_addr, + mask_buf, INET_ADDRSTRLEN); + zlog_warn( + "%s: %s/%s: gate == NULL and no gateway found for ifindex %d", + __func__, dest_buf, mask_buf, index); + return -1; + } + gate = (union sockunion *)&((struct zebra_if *)ifp->info)->sdl; + } + + if (mask) + msg.rtm.rtm_addrs |= RTA_NETMASK; + else if (message == RTM_ADD || message == RTM_CHANGE) + msg.rtm.rtm_flags |= RTF_HOST; #ifdef __OpenBSD__ - if (mpls) - { - msg.rtm.rtm_addrs |= RTA_SRC; - msg.rtm.rtm_flags |= RTF_MPLS; - - if (mpls->smpls.smpls_label != htonl (MPLS_IMP_NULL_LABEL << MPLS_LABEL_OFFSET)) - msg.rtm.rtm_mpls = MPLS_OP_PUSH; - } + if (mpls) { + msg.rtm.rtm_addrs |= RTA_SRC; + msg.rtm.rtm_flags |= RTF_MPLS; + + if (mpls->smpls.smpls_label + != htonl(MPLS_IMP_NULL_LABEL << MPLS_LABEL_OFFSET)) + msg.rtm.rtm_mpls = MPLS_OP_PUSH; + } #endif - /* Tagging route with flags */ - msg.rtm.rtm_flags |= (RTF_PROTO1); + /* Tagging route with flags */ + msg.rtm.rtm_flags |= (RTF_PROTO1); - /* Additional flags. */ - if (zebra_flags & ZEBRA_FLAG_BLACKHOLE) - msg.rtm.rtm_flags |= RTF_BLACKHOLE; - if (zebra_flags & ZEBRA_FLAG_REJECT) - msg.rtm.rtm_flags |= RTF_REJECT; + /* Additional flags. */ + if (zebra_flags & ZEBRA_FLAG_BLACKHOLE) + msg.rtm.rtm_flags |= RTF_BLACKHOLE; + if (zebra_flags & ZEBRA_FLAG_REJECT) + msg.rtm.rtm_flags |= RTF_REJECT; -#define SOCKADDRSET(X,R) \ - if (msg.rtm.rtm_addrs & (R)) \ - { \ - int len = SAROUNDUP (X); \ - memcpy (pnt, (caddr_t)(X), len); \ - pnt += len; \ - } +#define SOCKADDRSET(X, R) \ + if (msg.rtm.rtm_addrs & (R)) { \ + int len = SAROUNDUP(X); \ + memcpy(pnt, (caddr_t)(X), len); \ + pnt += len; \ + } - pnt = (caddr_t) msg.buf; + pnt = (caddr_t)msg.buf; - /* Write each socket data into rtm message buffer */ - SOCKADDRSET (dest, RTA_DST); - SOCKADDRSET (gate, RTA_GATEWAY); - SOCKADDRSET (mask, RTA_NETMASK); + /* Write each socket data into rtm message buffer */ + SOCKADDRSET(dest, RTA_DST); + SOCKADDRSET(gate, RTA_GATEWAY); + SOCKADDRSET(mask, RTA_NETMASK); #ifdef __OpenBSD__ - SOCKADDRSET (mpls, RTA_SRC); + SOCKADDRSET(mpls, RTA_SRC); #endif - msg.rtm.rtm_msglen = pnt - (caddr_t) &msg; - - ret = write (routing_sock, &msg, msg.rtm.rtm_msglen); - - if (ret != msg.rtm.rtm_msglen) - { - if (errno == EEXIST) - return ZEBRA_ERR_RTEXIST; - if (errno == ENETUNREACH) - return ZEBRA_ERR_RTUNREACH; - if (errno == ESRCH) - return ZEBRA_ERR_RTNOEXIST; - - zlog_warn ("%s: write : %s (%d)", __func__, safe_strerror (errno), errno); - return ZEBRA_ERR_KERNEL; - } - return ZEBRA_ERR_NOERROR; + msg.rtm.rtm_msglen = pnt - (caddr_t)&msg; + + ret = write(routing_sock, &msg, msg.rtm.rtm_msglen); + + if (ret != msg.rtm.rtm_msglen) { + if (errno == EEXIST) + return ZEBRA_ERR_RTEXIST; + if (errno == ENETUNREACH) + return ZEBRA_ERR_RTUNREACH; + if (errno == ESRCH) + return ZEBRA_ERR_RTNOEXIST; + + zlog_warn("%s: write : %s (%d)", __func__, safe_strerror(errno), + errno); + return ZEBRA_ERR_KERNEL; + } + return ZEBRA_ERR_NOERROR; } @@ -1199,14 +1216,14 @@ rtm_write (int message, #include "zebra/zserv.h" /* For debug purpose. */ -static void -rtmsg_debug (struct rt_msghdr *rtm) +static void rtmsg_debug(struct rt_msghdr *rtm) { - zlog_debug ("Kernel: Len: %d Type: %s", rtm->rtm_msglen, lookup_msg(rtm_type_str, rtm->rtm_type, NULL)); - rtm_flag_dump (rtm->rtm_flags); - zlog_debug ("Kernel: message seq %d", rtm->rtm_seq); - zlog_debug ("Kernel: pid %lld, rtm_addrs 0x%x", - (long long)rtm->rtm_pid, rtm->rtm_addrs); + zlog_debug("Kernel: Len: %d Type: %s", rtm->rtm_msglen, + lookup_msg(rtm_type_str, rtm->rtm_type, NULL)); + rtm_flag_dump(rtm->rtm_flags); + zlog_debug("Kernel: message seq %d", rtm->rtm_seq); + zlog_debug("Kernel: pid %lld, rtm_addrs 0x%x", (long long)rtm->rtm_pid, + rtm->rtm_addrs); } /* This is pretty gross, better suggestions welcome -- mhandler */ @@ -1219,154 +1236,143 @@ rtmsg_debug (struct rt_msghdr *rtm) #endif /* RTAX_MAX */ /* Kernel routing table and interface updates via routing socket. */ -static int -kernel_read (struct thread *thread) +static int kernel_read(struct thread *thread) { - int sock; - int nbytes; - struct rt_msghdr *rtm; - - /* - * This must be big enough for any message the kernel might send. - * Rather than determining how many sockaddrs of what size might be - * in each particular message, just use RTAX_MAX of sockaddr_storage - * for each. Note that the sockaddrs must be after each message - * definition, or rather after whichever happens to be the largest, - * since the buffer needs to be big enough for a message and the - * sockaddrs together. - */ - union - { - /* Routing information. */ - struct - { - struct rt_msghdr rtm; - struct sockaddr_storage addr[RTAX_MAX]; - } r; - - /* Interface information. */ - struct - { - struct if_msghdr ifm; - struct sockaddr_storage addr[RTAX_MAX]; - } im; - - /* Interface address information. */ - struct - { - struct ifa_msghdr ifa; - struct sockaddr_storage addr[RTAX_MAX]; - } ia; + int sock; + int nbytes; + struct rt_msghdr *rtm; + + /* + * This must be big enough for any message the kernel might send. + * Rather than determining how many sockaddrs of what size might be + * in each particular message, just use RTAX_MAX of sockaddr_storage + * for each. Note that the sockaddrs must be after each message + * definition, or rather after whichever happens to be the largest, + * since the buffer needs to be big enough for a message and the + * sockaddrs together. + */ + union { + /* Routing information. */ + struct { + struct rt_msghdr rtm; + struct sockaddr_storage addr[RTAX_MAX]; + } r; + + /* Interface information. */ + struct { + struct if_msghdr ifm; + struct sockaddr_storage addr[RTAX_MAX]; + } im; + + /* Interface address information. */ + struct { + struct ifa_msghdr ifa; + struct sockaddr_storage addr[RTAX_MAX]; + } ia; #ifdef RTM_IFANNOUNCE - /* Interface arrival/departure */ - struct - { - struct if_announcemsghdr ifan; - struct sockaddr_storage addr[RTAX_MAX]; - } ian; + /* Interface arrival/departure */ + struct { + struct if_announcemsghdr ifan; + struct sockaddr_storage addr[RTAX_MAX]; + } ian; #endif /* RTM_IFANNOUNCE */ - } buf; + } buf; - /* Fetch routing socket. */ - sock = THREAD_FD (thread); + /* Fetch routing socket. */ + sock = THREAD_FD(thread); - nbytes= read (sock, &buf, sizeof buf); + nbytes = read(sock, &buf, sizeof buf); - if (nbytes <= 0) - { - if (nbytes < 0 && errno != EWOULDBLOCK && errno != EAGAIN) - zlog_warn ("routing socket error: %s", safe_strerror (errno)); - return 0; - } + if (nbytes <= 0) { + if (nbytes < 0 && errno != EWOULDBLOCK && errno != EAGAIN) + zlog_warn("routing socket error: %s", + safe_strerror(errno)); + return 0; + } - thread_add_read(zebrad.master, kernel_read, NULL, sock, NULL); + thread_add_read(zebrad.master, kernel_read, NULL, sock, NULL); - if (IS_ZEBRA_DEBUG_KERNEL) - rtmsg_debug (&buf.r.rtm); + if (IS_ZEBRA_DEBUG_KERNEL) + rtmsg_debug(&buf.r.rtm); - rtm = &buf.r.rtm; + rtm = &buf.r.rtm; - /* - * Ensure that we didn't drop any data, so that processing routines - * can assume they have the whole message. - */ - if (rtm->rtm_msglen != nbytes) - { - zlog_warn ("kernel_read: rtm->rtm_msglen %d, nbytes %d, type %d\n", - rtm->rtm_msglen, nbytes, rtm->rtm_type); - return -1; - } - - switch (rtm->rtm_type) - { - case RTM_ADD: - case RTM_DELETE: - case RTM_CHANGE: - rtm_read (rtm); - break; - case RTM_IFINFO: - ifm_read (&buf.im.ifm); - break; - case RTM_NEWADDR: - case RTM_DELADDR: - ifam_read (&buf.ia.ifa); - break; + /* + * Ensure that we didn't drop any data, so that processing routines + * can assume they have the whole message. + */ + if (rtm->rtm_msglen != nbytes) { + zlog_warn( + "kernel_read: rtm->rtm_msglen %d, nbytes %d, type %d\n", + rtm->rtm_msglen, nbytes, rtm->rtm_type); + return -1; + } + + switch (rtm->rtm_type) { + case RTM_ADD: + case RTM_DELETE: + case RTM_CHANGE: + rtm_read(rtm); + break; + case RTM_IFINFO: + ifm_read(&buf.im.ifm); + break; + case RTM_NEWADDR: + case RTM_DELADDR: + ifam_read(&buf.ia.ifa); + break; #ifdef RTM_IFANNOUNCE - case RTM_IFANNOUNCE: - ifan_read (&buf.ian.ifan); - break; + case RTM_IFANNOUNCE: + ifan_read(&buf.ian.ifan); + break; #endif /* RTM_IFANNOUNCE */ - default: - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("Unprocessed RTM_type: %d", rtm->rtm_type); - break; - } - return 0; + default: + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("Unprocessed RTM_type: %d", rtm->rtm_type); + break; + } + return 0; } /* Make routing socket. */ -static void -routing_socket (struct zebra_ns *zns) +static void routing_socket(struct zebra_ns *zns) { - if ( zserv_privs.change (ZPRIVS_RAISE) ) - zlog_err ("routing_socket: Can't raise privileges"); - - routing_sock = socket (AF_ROUTE, SOCK_RAW, 0); - - if (routing_sock < 0) - { - if ( zserv_privs.change (ZPRIVS_LOWER) ) - zlog_err ("routing_socket: Can't lower privileges"); - zlog_warn ("Can't init kernel routing socket"); - return; - } - - /* XXX: Socket should be NONBLOCK, however as we currently - * discard failed writes, this will lead to inconsistencies. - * For now, socket must be blocking. - */ - /*if (fcntl (routing_sock, F_SETFL, O_NONBLOCK) < 0) - zlog_warn ("Can't set O_NONBLOCK to routing socket");*/ - - if ( zserv_privs.change (ZPRIVS_LOWER) ) - zlog_err ("routing_socket: Can't lower privileges"); - - /* kernel_read needs rewrite. */ - thread_add_read(zebrad.master, kernel_read, NULL, routing_sock, NULL); + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("routing_socket: Can't raise privileges"); + + routing_sock = socket(AF_ROUTE, SOCK_RAW, 0); + + if (routing_sock < 0) { + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("routing_socket: Can't lower privileges"); + zlog_warn("Can't init kernel routing socket"); + return; + } + + /* XXX: Socket should be NONBLOCK, however as we currently + * discard failed writes, this will lead to inconsistencies. + * For now, socket must be blocking. + */ + /*if (fcntl (routing_sock, F_SETFL, O_NONBLOCK) < 0) + zlog_warn ("Can't set O_NONBLOCK to routing socket");*/ + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("routing_socket: Can't lower privileges"); + + /* kernel_read needs rewrite. */ + thread_add_read(zebrad.master, kernel_read, NULL, routing_sock, NULL); } /* Exported interface function. This function simply calls routing_socket (). */ -void -kernel_init (struct zebra_ns *zns) +void kernel_init(struct zebra_ns *zns) { - routing_socket (zns); + routing_socket(zns); } -void -kernel_terminate (struct zebra_ns *zns) +void kernel_terminate(struct zebra_ns *zns) { - return; + return; } diff --git a/zebra/kernel_socket.h b/zebra/kernel_socket.h index 26cd6127f..41b322185 100644 --- a/zebra/kernel_socket.h +++ b/zebra/kernel_socket.h @@ -30,12 +30,12 @@ #define ZEBRA_ERR_RTNOEXIST -4 #define ZEBRA_ERR_KERNEL -5 -extern void rtm_read (struct rt_msghdr *); -extern int ifam_read (struct ifa_msghdr *); -extern int ifm_read (struct if_msghdr *); -extern int rtm_write (int, union sockunion *, union sockunion *, - union sockunion *, union sockunion *, - unsigned int, int, int); +extern void rtm_read(struct rt_msghdr *); +extern int ifam_read(struct ifa_msghdr *); +extern int ifm_read(struct if_msghdr *); +extern int rtm_write(int, union sockunion *, union sockunion *, + union sockunion *, union sockunion *, unsigned int, int, + int); extern const struct message rtm_type_str[]; #endif /* __ZEBRA_KERNEL_SOCKET_H */ diff --git a/zebra/label_manager.c b/zebra/label_manager.c index fbe4cea46..b50f75158 100644 --- a/zebra/label_manager.c +++ b/zebra/label_manager.c @@ -71,14 +71,14 @@ static int relay_response_back(struct zserv *zserv) stream_reset(src); ret = zclient_read_header(src, zclient->sock, &size, &marker, &version, - &vrf_id, &resp_cmd); + &vrf_id, &resp_cmd); if (ret < 0 && errno != EAGAIN) { - zlog_err("%s: Error reading Label Manager response: %s", __func__, - strerror(errno)); + zlog_err("%s: Error reading Label Manager response: %s", + __func__, strerror(errno)); return -1; } zlog_debug("%s: Label Manager response received, %d bytes", __func__, - size); + size); if (size == 0) return -1; @@ -87,11 +87,11 @@ static int relay_response_back(struct zserv *zserv) ret = writen(zserv->sock, dst->data, stream_get_endp(dst)); if (ret <= 0) { zlog_err("%s: Error sending Label Manager response back: %s", - __func__, strerror(errno)); + __func__, strerror(errno)); return -1; } zlog_debug("%s: Label Manager response (%d bytes) sent back", __func__, - ret); + ret); return 0; } @@ -111,23 +111,22 @@ static int lm_zclient_read(struct thread *t) return ret; } -static int reply_error (int cmd, struct zserv *zserv, vrf_id_t vrf_id) +static int reply_error(int cmd, struct zserv *zserv, vrf_id_t vrf_id) { struct stream *s; s = zserv->obuf; - stream_reset (s); + stream_reset(s); - zserv_create_header (s, cmd, vrf_id); + zserv_create_header(s, cmd, vrf_id); /* result */ - stream_putc (s, 1); + stream_putc(s, 1); /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); - - return writen (zserv->sock, s->data, stream_get_endp (s)); + stream_putw_at(s, 0, stream_get_endp(s)); + return writen(zserv->sock, s->data, stream_get_endp(s)); } /** * Receive a request to get or release a label chunk and forward it to external @@ -140,15 +139,17 @@ static int reply_error (int cmd, struct zserv *zserv, vrf_id_t vrf_id) * @param zserv * @return 0 on success, -1 otherwise */ -int zread_relay_label_manager_request(int cmd, struct zserv *zserv, vrf_id_t vrf_id) +int zread_relay_label_manager_request(int cmd, struct zserv *zserv, + vrf_id_t vrf_id) { struct stream *src, *dst; int ret = 0; if (zclient->sock < 0) { - zlog_err("%s: Error relaying label chunk request: no zclient socket", - __func__); - reply_error (cmd, zserv, vrf_id); + zlog_err( + "%s: Error relaying label chunk request: no zclient socket", + __func__); + reply_error(cmd, zserv, vrf_id); return -1; } @@ -166,7 +167,7 @@ int zread_relay_label_manager_request(int cmd, struct zserv *zserv, vrf_id_t vrf if (ret <= 0) { zlog_err("%s: Error relaying label chunk request: %s", __func__, strerror(errno)); - reply_error (cmd, zserv, vrf_id); + reply_error(cmd, zserv, vrf_id); return -1; } zlog_debug("%s: Label chunk request relayed. %d bytes sent", __func__, @@ -179,7 +180,7 @@ int zread_relay_label_manager_request(int cmd, struct zserv *zserv, vrf_id_t vrf /* make sure we listen to the response */ if (!zclient->t_read) thread_add_read(zclient->master, lm_zclient_read, zserv, - zclient->sock, &zclient->t_read); + zclient->sock, &zclient->t_read); return 0; } @@ -200,7 +201,8 @@ static int lm_zclient_connect(struct thread *t) /* make socket non-blocking */ if (set_nonblocking(zclient->sock) < 0) - zlog_warn("%s: set_nonblocking(%d) failed", __func__, zclient->sock); + zlog_warn("%s: set_nonblocking(%d) failed", __func__, + zclient->sock); return 0; } @@ -234,7 +236,7 @@ void label_manager_init(char *lm_zserv_path) lm_is_external = false; lbl_mgr.lc_list = list_new(); lbl_mgr.lc_list->del = delete_label_chunk; - } else { /* it's acting just as a proxy */ + } else { /* it's acting just as a proxy */ zlog_debug("Initializing external label manager at %s", lm_zserv_path); lm_is_external = true; @@ -262,7 +264,8 @@ struct label_manager_chunk *assign_label_chunk(u_char proto, u_short instance, /* first check if there's one available */ for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) { - if (lmc->proto == NO_PROTO && lmc->end - lmc->start + 1 == size) { + if (lmc->proto == NO_PROTO + && lmc->end - lmc->start + 1 == size) { lmc->proto = proto; lmc->instance = instance; lmc->keep = keep; @@ -277,12 +280,14 @@ struct label_manager_chunk *assign_label_chunk(u_char proto, u_short instance, if (list_isempty(lbl_mgr.lc_list)) lmc->start = MPLS_MIN_UNRESERVED_LABEL; else - lmc->start = ((struct label_manager_chunk *) - listgetdata(listtail(lbl_mgr.lc_list)))->end + 1; + lmc->start = ((struct label_manager_chunk *)listgetdata( + listtail(lbl_mgr.lc_list))) + ->end + + 1; if (lmc->start > MPLS_MAX_UNRESERVED_LABEL - size + 1) { zlog_err("Reached max labels. Start: %u, size: %u", lmc->start, size); - XFREE(MTYPE_LM_CHUNK, lmc); + XFREE(MTYPE_LM_CHUNK, lmc); return NULL; } lmc->end = lmc->start + size - 1; @@ -303,9 +308,8 @@ struct label_manager_chunk *assign_label_chunk(u_char proto, u_short instance, * @param end Last label of the chunk * @return 0 on success, -1 otherwise */ -int -release_label_chunk(u_char proto, u_short instance, uint32_t start, - uint32_t end) +int release_label_chunk(u_char proto, u_short instance, uint32_t start, + uint32_t end) { struct listnode *node; struct label_manager_chunk *lmc; @@ -355,9 +359,8 @@ int release_daemon_chunks(u_char proto, u_short instance) for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) { if (lmc->proto == proto && lmc->instance == instance && lmc->keep == 0) { - ret = - release_label_chunk(lmc->proto, lmc->instance, - lmc->start, lmc->end); + ret = release_label_chunk(lmc->proto, lmc->instance, + lmc->start, lmc->end); if (ret == 0) count++; } diff --git a/zebra/label_manager.h b/zebra/label_manager.h index b7d6118a0..875698362 100644 --- a/zebra/label_manager.h +++ b/zebra/label_manager.h @@ -47,8 +47,8 @@ struct label_manager_chunk { u_char proto; u_short instance; u_char keep; - uint32_t start; /* First label of the chunk */ - uint32_t end; /* Last label of the chunk */ + uint32_t start; /* First label of the chunk */ + uint32_t end; /* Last label of the chunk */ }; /* @@ -61,7 +61,8 @@ struct label_manager { bool lm_is_external; -int zread_relay_label_manager_request(int cmd, struct zserv *zserv, vrf_id_t vrf_id); +int zread_relay_label_manager_request(int cmd, struct zserv *zserv, + vrf_id_t vrf_id); void label_manager_init(char *lm_zserv_path); struct label_manager_chunk *assign_label_chunk(u_char proto, u_short instance, u_char keep, uint32_t size); @@ -70,4 +71,4 @@ int release_label_chunk(u_char proto, u_short instance, uint32_t start, int release_daemon_chunks(u_char proto, u_short instance); void label_manager_close(void); -#endif /* _LABEL_MANAGER_H */ +#endif /* _LABEL_MANAGER_H */ diff --git a/zebra/main.c b/zebra/main.c index b136f8ae9..27a6f3e02 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -51,9 +51,8 @@ #define ZEBRA_PTM_SUPPORT /* Zebra instance */ -struct zebra_t zebrad = -{ - .rtm_table_default = 0, +struct zebra_t zebrad = { + .rtm_table_default = 0, }; /* process id. */ @@ -77,283 +76,271 @@ u_int32_t nl_rcvbufsize = 4194304; #endif /* HAVE_NETLINK */ /* Command line options. */ -struct option longopts[] = -{ - { "batch", no_argument, NULL, 'b'}, - { "allow_delete", no_argument, NULL, 'a'}, - { "keep_kernel", no_argument, NULL, 'k'}, - { "socket", required_argument, NULL, 'z'}, - { "ecmp", required_argument, NULL, 'e'}, - { "label_socket", no_argument, NULL, 'l'}, - { "retain", no_argument, NULL, 'r'}, +struct option longopts[] = {{"batch", no_argument, NULL, 'b'}, + {"allow_delete", no_argument, NULL, 'a'}, + {"keep_kernel", no_argument, NULL, 'k'}, + {"socket", required_argument, NULL, 'z'}, + {"ecmp", required_argument, NULL, 'e'}, + {"label_socket", no_argument, NULL, 'l'}, + {"retain", no_argument, NULL, 'r'}, #ifdef HAVE_NETLINK - { "nl-bufsize", required_argument, NULL, 's'}, + {"nl-bufsize", required_argument, NULL, 's'}, #endif /* HAVE_NETLINK */ - { 0 } -}; + {0}}; -zebra_capabilities_t _caps_p [] = -{ - ZCAP_NET_ADMIN, - ZCAP_SYS_ADMIN, - ZCAP_NET_RAW, +zebra_capabilities_t _caps_p[] = { + ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN, ZCAP_NET_RAW, }; /* zebra privileges to run with */ -struct zebra_privs_t zserv_privs = -{ +struct zebra_privs_t zserv_privs = { #if defined(FRR_USER) && defined(FRR_GROUP) - .user = FRR_USER, - .group = FRR_GROUP, + .user = FRR_USER, + .group = FRR_GROUP, #endif #ifdef VTY_GROUP - .vty_group = VTY_GROUP, + .vty_group = VTY_GROUP, #endif - .caps_p = _caps_p, - .cap_num_p = array_size(_caps_p), - .cap_num_i = 0 -}; + .caps_p = _caps_p, + .cap_num_p = array_size(_caps_p), + .cap_num_i = 0}; unsigned int multipath_num = MULTIPATH_NUM; /* SIGHUP handler. */ -static void -sighup (void) +static void sighup(void) { - zlog_info ("SIGHUP received"); + zlog_info("SIGHUP received"); - /* Reload of config file. */ - ; + /* Reload of config file. */ + ; } /* SIGINT handler. */ -static void -sigint (void) +static void sigint(void) { - struct vrf *vrf; - struct zebra_vrf *zvrf; - struct zebra_ns *zns; + struct vrf *vrf; + struct zebra_vrf *zvrf; + struct zebra_ns *zns; - zlog_notice ("Terminating on signal"); + zlog_notice("Terminating on signal"); #ifdef HAVE_IRDP - irdp_finish(); + irdp_finish(); #endif - zebra_ptm_finish(); - list_delete_all_node (zebrad.client_list); - - if (retain_mode) - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - zvrf = vrf->info; - if (zvrf) - SET_FLAG (zvrf->flags, ZEBRA_VRF_RETAIN); - } - vrf_terminate (); - - zns = zebra_ns_lookup (NS_DEFAULT); - zebra_ns_disable (0, (void **)&zns); - - access_list_reset (); - prefix_list_reset (); - route_map_finish (); - cmd_terminate (); - vty_terminate (); - zprivs_terminate (&zserv_privs); - list_delete (zebrad.client_list); - work_queue_free (zebrad.ribq); - if (zebrad.lsp_process_q) - work_queue_free (zebrad.lsp_process_q); - meta_queue_free (zebrad.mq); - thread_master_free (zebrad.master); - closezlog (); - - exit (0); + zebra_ptm_finish(); + list_delete_all_node(zebrad.client_list); + + if (retain_mode) + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + zvrf = vrf->info; + if (zvrf) + SET_FLAG(zvrf->flags, ZEBRA_VRF_RETAIN); + } + vrf_terminate(); + + zns = zebra_ns_lookup(NS_DEFAULT); + zebra_ns_disable(0, (void **)&zns); + + access_list_reset(); + prefix_list_reset(); + route_map_finish(); + cmd_terminate(); + vty_terminate(); + zprivs_terminate(&zserv_privs); + list_delete(zebrad.client_list); + work_queue_free(zebrad.ribq); + if (zebrad.lsp_process_q) + work_queue_free(zebrad.lsp_process_q); + meta_queue_free(zebrad.mq); + thread_master_free(zebrad.master); + closezlog(); + + exit(0); } /* SIGUSR1 handler. */ -static void -sigusr1 (void) +static void sigusr1(void) { - zlog_rotate(); + zlog_rotate(); } -struct quagga_signal_t zebra_signals[] = -{ - { - .signal = SIGHUP, - .handler = &sighup, - }, - { - .signal = SIGUSR1, - .handler = &sigusr1, - }, - { - .signal = SIGINT, - .handler = &sigint, - }, - { - .signal = SIGTERM, - .handler = &sigint, - }, +struct quagga_signal_t zebra_signals[] = { + { + .signal = SIGHUP, + .handler = &sighup, + }, + { + .signal = SIGUSR1, + .handler = &sigusr1, + }, + { + .signal = SIGINT, + .handler = &sigint, + }, + { + .signal = SIGTERM, + .handler = &sigint, + }, }; -FRR_DAEMON_INFO(zebra, ZEBRA, - .vty_port = ZEBRA_VTY_PORT, - .flags = FRR_NO_ZCLIENT, +FRR_DAEMON_INFO( + zebra, ZEBRA, .vty_port = ZEBRA_VTY_PORT, .flags = FRR_NO_ZCLIENT, - .proghelp = "Daemon which manages kernel routing table management " + .proghelp = + "Daemon which manages kernel routing table management " "and\nredistribution between different routing protocols.", - .signals = zebra_signals, - .n_signals = array_size(zebra_signals), + .signals = zebra_signals, .n_signals = array_size(zebra_signals), - .privs = &zserv_privs, -) + .privs = &zserv_privs, ) /* Main startup routine. */ -int -main (int argc, char **argv) +int main(int argc, char **argv) { - // int batch_mode = 0; - char *zserv_path = NULL; - /* Socket to external label manager */ - char *lblmgr_path = NULL; + // int batch_mode = 0; + char *zserv_path = NULL; + /* Socket to external label manager */ + char *lblmgr_path = NULL; - frr_preinit(&zebra_di, argc, argv); + frr_preinit(&zebra_di, argc, argv); - frr_opt_add("bakz:e:l:r" + frr_opt_add( + "bakz:e:l:r" #ifdef HAVE_NETLINK - "s:" + "s:" #endif - , longopts, - " -b, --batch Runs in batch mode\n" - " -a, --allow_delete Allow other processes to delete zebra routes\n" - " -z, --socket Set path of zebra socket\n" - " -e, --ecmp Specify ECMP to use.\n" - " -l, --label_socket Socket to external label manager\n"\ - " -k, --keep_kernel Don't delete old routes which installed by zebra.\n" - " -r, --retain When program terminates, retain added route by zebra.\n" + , + longopts, + " -b, --batch Runs in batch mode\n" + " -a, --allow_delete Allow other processes to delete zebra routes\n" + " -z, --socket Set path of zebra socket\n" + " -e, --ecmp Specify ECMP to use.\n" + " -l, --label_socket Socket to external label manager\n" + " -k, --keep_kernel Don't delete old routes which installed by zebra.\n" + " -r, --retain When program terminates, retain added route by zebra.\n" #ifdef HAVE_NETLINK - " -s, --nl-bufsize Set netlink receive buffer size\n" + " -s, --nl-bufsize Set netlink receive buffer size\n" #endif /* HAVE_NETLINK */ - ); - - while (1) - { - int opt = frr_getopt(argc, argv, NULL); - - if (opt == EOF) - break; - - switch (opt) - { - case 0: - break; - case 'b': - // batch_mode = 1; - break; - case 'a': - allow_delete = 1; - break; - case 'k': - keep_kernel_mode = 1; - break; - case 'e': - multipath_num = atoi (optarg); - if (multipath_num > MULTIPATH_NUM || multipath_num <= 0) - { - zlog_err ("Multipath Number specified must be less than %d and greater than 0", MULTIPATH_NUM); - return 1; - } - break; - case 'z': - zserv_path = optarg; - break; - case 'l': - lblmgr_path = optarg; - break; - case 'r': - retain_mode = 1; - break; + ); + + while (1) { + int opt = frr_getopt(argc, argv, NULL); + + if (opt == EOF) + break; + + switch (opt) { + case 0: + break; + case 'b': + // batch_mode = 1; + break; + case 'a': + allow_delete = 1; + break; + case 'k': + keep_kernel_mode = 1; + break; + case 'e': + multipath_num = atoi(optarg); + if (multipath_num > MULTIPATH_NUM + || multipath_num <= 0) { + zlog_err( + "Multipath Number specified must be less than %d and greater than 0", + MULTIPATH_NUM); + return 1; + } + break; + case 'z': + zserv_path = optarg; + break; + case 'l': + lblmgr_path = optarg; + break; + case 'r': + retain_mode = 1; + break; #ifdef HAVE_NETLINK - case 's': - nl_rcvbufsize = atoi (optarg); - break; + case 's': + nl_rcvbufsize = atoi(optarg); + break; #endif /* HAVE_NETLINK */ - default: - frr_help_exit (1); - break; + default: + frr_help_exit(1); + break; + } } - } - - vty_config_lockless (); - zebrad.master = frr_init(); - - /* Zebra related initialize. */ - zebra_init (); - rib_init (); - zebra_if_init (); - zebra_debug_init (); - router_id_cmd_init (); - zebra_vty_init (); - access_list_init (); - prefix_list_init (); -#if defined (HAVE_RTADV) - rtadv_cmd_init (); + + vty_config_lockless(); + zebrad.master = frr_init(); + + /* Zebra related initialize. */ + zebra_init(); + rib_init(); + zebra_if_init(); + zebra_debug_init(); + router_id_cmd_init(); + zebra_vty_init(); + access_list_init(); + prefix_list_init(); +#if defined(HAVE_RTADV) + rtadv_cmd_init(); #endif #ifdef HAVE_IRDP - irdp_init(); + irdp_init(); #endif - /* PTM socket */ +/* PTM socket */ #ifdef ZEBRA_PTM_SUPPORT - zebra_ptm_init(); + zebra_ptm_init(); #endif - zebra_mpls_init (); - zebra_mpls_vty_init (); + zebra_mpls_init(); + zebra_mpls_vty_init(); - /* For debug purpose. */ - /* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */ + /* For debug purpose. */ + /* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */ - /* Initialize NS( and implicitly the VRF module), and make kernel routing socket. */ - zebra_ns_init (); + /* Initialize NS( and implicitly the VRF module), and make kernel + * routing socket. */ + zebra_ns_init(); - /* Process the configuration file. Among other configuration - * directives we can meet those installing static routes. Such - * requests will not be executed immediately, but queued in - * zebra->ribq structure until we enter the main execution loop. - * The notifications from kernel will show originating PID equal - * to that after daemon() completes (if ever called). - */ - frr_config_fork(); + /* Process the configuration file. Among other configuration + * directives we can meet those installing static routes. Such + * requests will not be executed immediately, but queued in + * zebra->ribq structure until we enter the main execution loop. + * The notifications from kernel will show originating PID equal + * to that after daemon() completes (if ever called). + */ + frr_config_fork(); - /* Clean up rib -- before fork (?) */ - /* rib_weed_tables (); */ + /* Clean up rib -- before fork (?) */ + /* rib_weed_tables (); */ - /* After we have successfully acquired the pidfile, we can be sure - * about being the only copy of zebra process, which is submitting - * changes to the FIB. - * Clean up zebra-originated routes. The requests will be sent to OS - * immediately, so originating PID in notifications from kernel - * will be equal to the current getpid(). To know about such routes, - * we have to have route_read() called before. - */ - if (! keep_kernel_mode) - rib_sweep_route (); + /* After we have successfully acquired the pidfile, we can be sure + * about being the only copy of zebra process, which is submitting + * changes to the FIB. + * Clean up zebra-originated routes. The requests will be sent to OS + * immediately, so originating PID in notifications from kernel + * will be equal to the current getpid(). To know about such routes, + * we have to have route_read() called before. + */ + if (!keep_kernel_mode) + rib_sweep_route(); - /* Needed for BSD routing socket. */ - pid = getpid (); + /* Needed for BSD routing socket. */ + pid = getpid(); - /* This must be done only after locking pidfile (bug #403). */ - zebra_zserv_socket_init (zserv_path); + /* This must be done only after locking pidfile (bug #403). */ + zebra_zserv_socket_init(zserv_path); - /* Init label manager */ - label_manager_init (lblmgr_path); + /* Init label manager */ + label_manager_init(lblmgr_path); - frr_run (zebrad.master); + frr_run(zebrad.master); - /* Not reached... */ - return 0; + /* Not reached... */ + return 0; } diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 97616a2a9..c3bbf40b3 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -49,722 +49,715 @@ static int zebra_import_table_used[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; static u_int32_t zebra_import_table_distance[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; -int -is_zebra_import_table_enabled(afi_t afi, u_int32_t table_id) +int is_zebra_import_table_enabled(afi_t afi, u_int32_t table_id) { - if (is_zebra_valid_kernel_table(table_id)) - return zebra_import_table_used[afi][table_id]; - return 0; + if (is_zebra_valid_kernel_table(table_id)) + return zebra_import_table_used[afi][table_id]; + return 0; } -int -is_default (struct prefix *p) +int is_default(struct prefix *p) { - if (p->family == AF_INET) - if (p->u.prefix4.s_addr == 0 && p->prefixlen == 0) - return 1; -#if 0 /* IPv6 default separation is now pending until protocol daemon - can handle that. */ + if (p->family == AF_INET) + if (p->u.prefix4.s_addr == 0 && p->prefixlen == 0) + return 1; +#if 0 /* IPv6 default separation is now pending until protocol daemon \ + can handle that. */ if (p->family == AF_INET6) if (IN6_IS_ADDR_UNSPECIFIED (&p->u.prefix6) && p->prefixlen == 0) return 1; #endif /* 0 */ - return 0; + return 0; } -static void -zebra_redistribute_default (struct zserv *client, vrf_id_t vrf_id) +static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id) { - int afi; - struct prefix p; - struct route_table *table; - struct route_node *rn; - struct route_entry *newre; - - for (afi = AFI_IP; afi <= AFI_IP6; afi++) - { - /* Lookup table. */ - table = zebra_vrf_table (afi, SAFI_UNICAST, vrf_id); - if (! table) - continue; - - /* Lookup default route. */ - memset (&p, 0, sizeof (p)); - p.family = afi2family (afi); - rn = route_node_lookup (table, &p); - if (! rn) - continue; - - RNODE_FOREACH_RE (rn, newre) - if (CHECK_FLAG (newre->flags, ZEBRA_FLAG_SELECTED) - && newre->distance != DISTANCE_INFINITY) - zsend_redistribute_route (1, client, &rn->p, NULL, newre); - - route_unlock_node (rn); - } + int afi; + struct prefix p; + struct route_table *table; + struct route_node *rn; + struct route_entry *newre; + + for (afi = AFI_IP; afi <= AFI_IP6; afi++) { + /* Lookup table. */ + table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id); + if (!table) + continue; + + /* Lookup default route. */ + memset(&p, 0, sizeof(p)); + p.family = afi2family(afi); + rn = route_node_lookup(table, &p); + if (!rn) + continue; + + RNODE_FOREACH_RE(rn, newre) + if (CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED) + && newre->distance != DISTANCE_INFINITY) + zsend_redistribute_route(1, client, &rn->p, NULL, + newre); + + route_unlock_node(rn); + } } /* Redistribute routes. */ -static void -zebra_redistribute (struct zserv *client, int type, u_short instance, vrf_id_t vrf_id, int afi) +static void zebra_redistribute(struct zserv *client, int type, u_short instance, + vrf_id_t vrf_id, int afi) { - struct route_entry *newre; - struct route_table *table; - struct route_node *rn; - - table = zebra_vrf_table (afi, SAFI_UNICAST, vrf_id); - if (! table) - return; - - for (rn = route_top (table); rn; rn = route_next (rn)) - RNODE_FOREACH_RE (rn, newre) - { - struct prefix *dst_p, *src_p; - srcdest_rnode_prefixes(rn, &dst_p, &src_p); - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s: checking: selected=%d, type=%d, distance=%d, " - "zebra_check_addr=%d", __func__, - CHECK_FLAG (newre->flags, ZEBRA_FLAG_SELECTED), - newre->type, newre->distance, - zebra_check_addr (dst_p)); - - if (! CHECK_FLAG (newre->flags, ZEBRA_FLAG_SELECTED)) - continue; - if ((type != ZEBRA_ROUTE_ALL && - (newre->type != type || newre->instance != instance))) - continue; - if (newre->distance == DISTANCE_INFINITY) - continue; - if (! zebra_check_addr (dst_p)) - continue; - - zsend_redistribute_route (1, client, dst_p, src_p, newre); - } + struct route_entry *newre; + struct route_table *table; + struct route_node *rn; + + table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id); + if (!table) + return; + + for (rn = route_top(table); rn; rn = route_next(rn)) + RNODE_FOREACH_RE(rn, newre) + { + struct prefix *dst_p, *src_p; + srcdest_rnode_prefixes(rn, &dst_p, &src_p); + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "%s: checking: selected=%d, type=%d, distance=%d, " + "zebra_check_addr=%d", + __func__, + CHECK_FLAG(newre->flags, + ZEBRA_FLAG_SELECTED), + newre->type, newre->distance, + zebra_check_addr(dst_p)); + + if (!CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED)) + continue; + if ((type != ZEBRA_ROUTE_ALL + && (newre->type != type + || newre->instance != instance))) + continue; + if (newre->distance == DISTANCE_INFINITY) + continue; + if (!zebra_check_addr(dst_p)) + continue; + + zsend_redistribute_route(1, client, dst_p, src_p, + newre); + } } /* Either advertise a route for redistribution to registered clients or */ /* withdraw redistribution if add cannot be done for client */ -void -redistribute_update (struct prefix *p, struct prefix *src_p, - struct route_entry *re, struct route_entry *prev_re) +void redistribute_update(struct prefix *p, struct prefix *src_p, + struct route_entry *re, struct route_entry *prev_re) { - struct listnode *node, *nnode; - struct zserv *client; - int send_redistribute; - int afi; - char buf[INET6_ADDRSTRLEN]; - - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Redist update re %p (type %d), old %p (type %d)", - re->vrf_id, buf, p->prefixlen, re, re->type, - prev_re, prev_re ? prev_re->type : -1); - } - - afi = family2afi(p->family); - if (!afi) - { - zlog_warn("%s: Unknown AFI/SAFI prefix received\n", __FUNCTION__); - return; - } - - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - { - send_redistribute = 0; - - if (is_default (p) && vrf_bitmap_check (client->redist_default, re->vrf_id)) - send_redistribute = 1; - else if (vrf_bitmap_check (client->redist[afi][ZEBRA_ROUTE_ALL], re->vrf_id)) - send_redistribute = 1; - else if (re->instance && redist_check_instance (&client->mi_redist[afi][re->type], - re->instance)) - send_redistribute = 1; - else if (vrf_bitmap_check (client->redist[afi][re->type], re->vrf_id)) - send_redistribute = 1; - - if (send_redistribute) - { - zsend_redistribute_route (1, client, p, src_p, re); + struct listnode *node, *nnode; + struct zserv *client; + int send_redistribute; + int afi; + char buf[INET6_ADDRSTRLEN]; + + if (IS_ZEBRA_DEBUG_RIB) { + inet_ntop(p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); + zlog_debug( + "%u:%s/%d: Redist update re %p (type %d), old %p (type %d)", + re->vrf_id, buf, p->prefixlen, re, re->type, prev_re, + prev_re ? prev_re->type : -1); + } + + afi = family2afi(p->family); + if (!afi) { + zlog_warn("%s: Unknown AFI/SAFI prefix received\n", + __FUNCTION__); + return; } - else if (prev_re && - ((re->instance && - redist_check_instance(&client->mi_redist[afi][prev_re->type], - re->instance)) || - vrf_bitmap_check (client->redist[afi][prev_re->type], re->vrf_id))) - { - zsend_redistribute_route (0, client, p, src_p, prev_re); + + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { + send_redistribute = 0; + + if (is_default(p) + && vrf_bitmap_check(client->redist_default, re->vrf_id)) + send_redistribute = 1; + else if (vrf_bitmap_check(client->redist[afi][ZEBRA_ROUTE_ALL], + re->vrf_id)) + send_redistribute = 1; + else if (re->instance + && redist_check_instance( + &client->mi_redist[afi][re->type], + re->instance)) + send_redistribute = 1; + else if (vrf_bitmap_check(client->redist[afi][re->type], + re->vrf_id)) + send_redistribute = 1; + + if (send_redistribute) { + zsend_redistribute_route(1, client, p, src_p, re); + } else if (prev_re + && ((re->instance + && redist_check_instance( + &client->mi_redist[afi] + [prev_re->type], + re->instance)) + || vrf_bitmap_check( + client->redist[afi][prev_re->type], + re->vrf_id))) { + zsend_redistribute_route(0, client, p, src_p, prev_re); + } } - } } -void -redistribute_delete (struct prefix *p, struct prefix *src_p, struct route_entry *re) +void redistribute_delete(struct prefix *p, struct prefix *src_p, + struct route_entry *re) { - struct listnode *node, *nnode; - struct zserv *client; - char buf[INET6_ADDRSTRLEN]; - int afi; - - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Redist delete re %p (type %d)", - re->vrf_id, buf, p->prefixlen, re, re->type); - } - - /* Add DISTANCE_INFINITY check. */ - if (re->distance == DISTANCE_INFINITY) - return; - - afi = family2afi(p->family); - if (!afi) - { - zlog_warn("%s: Unknown AFI/SAFI prefix received\n", __FUNCTION__); - return; - } - - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - { - if ((is_default (p) && - vrf_bitmap_check (client->redist_default, re->vrf_id)) || - vrf_bitmap_check (client->redist[afi][ZEBRA_ROUTE_ALL], re->vrf_id) || - (re->instance && - redist_check_instance(&client->mi_redist[afi][re->type], - re->instance)) || - vrf_bitmap_check (client->redist[afi][re->type], re->vrf_id)) - { - zsend_redistribute_route (0, client, p, src_p, re); + struct listnode *node, *nnode; + struct zserv *client; + char buf[INET6_ADDRSTRLEN]; + int afi; + + if (IS_ZEBRA_DEBUG_RIB) { + inet_ntop(p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); + zlog_debug("%u:%s/%d: Redist delete re %p (type %d)", + re->vrf_id, buf, p->prefixlen, re, re->type); + } + + /* Add DISTANCE_INFINITY check. */ + if (re->distance == DISTANCE_INFINITY) + return; + + afi = family2afi(p->family); + if (!afi) { + zlog_warn("%s: Unknown AFI/SAFI prefix received\n", + __FUNCTION__); + return; + } + + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { + if ((is_default(p) + && vrf_bitmap_check(client->redist_default, re->vrf_id)) + || vrf_bitmap_check(client->redist[afi][ZEBRA_ROUTE_ALL], + re->vrf_id) + || (re->instance + && redist_check_instance( + &client->mi_redist[afi][re->type], + re->instance)) + || vrf_bitmap_check(client->redist[afi][re->type], + re->vrf_id)) { + zsend_redistribute_route(0, client, p, src_p, re); + } } - } } -void -zebra_redistribute_add (int command, struct zserv *client, int length, - struct zebra_vrf *zvrf) +void zebra_redistribute_add(int command, struct zserv *client, int length, + struct zebra_vrf *zvrf) { - afi_t afi; - int type; - u_short instance; - - afi = stream_getc (client->ibuf); - type = stream_getc (client->ibuf); - instance = stream_getw (client->ibuf); - - if (type == 0 || type >= ZEBRA_ROUTE_MAX) - return; - - if (instance) - { - if (! redist_check_instance (&client->mi_redist[afi][type], instance)) - { - redist_add_instance (&client->mi_redist[afi][type], instance); - zebra_redistribute (client, type, instance, zvrf_id (zvrf), afi); + afi_t afi; + int type; + u_short instance; + + afi = stream_getc(client->ibuf); + type = stream_getc(client->ibuf); + instance = stream_getw(client->ibuf); + + if (type == 0 || type >= ZEBRA_ROUTE_MAX) + return; + + if (instance) { + if (!redist_check_instance(&client->mi_redist[afi][type], + instance)) { + redist_add_instance(&client->mi_redist[afi][type], + instance); + zebra_redistribute(client, type, instance, + zvrf_id(zvrf), afi); + } + } else { + if (!vrf_bitmap_check(client->redist[afi][type], + zvrf_id(zvrf))) { + vrf_bitmap_set(client->redist[afi][type], + zvrf_id(zvrf)); + zebra_redistribute(client, type, 0, zvrf_id(zvrf), afi); + } } - } else { - if (! vrf_bitmap_check (client->redist[afi][type], zvrf_id (zvrf))) - { - vrf_bitmap_set (client->redist[afi][type], zvrf_id (zvrf)); - zebra_redistribute (client, type, 0, zvrf_id (zvrf), afi); - } - } } -void -zebra_redistribute_delete (int command, struct zserv *client, int length, - struct zebra_vrf *zvrf) +void zebra_redistribute_delete(int command, struct zserv *client, int length, + struct zebra_vrf *zvrf) { - afi_t afi; - int type; - u_short instance; - - afi = stream_getc (client->ibuf); - type = stream_getc (client->ibuf); - instance = stream_getw (client->ibuf); - - if (type == 0 || type >= ZEBRA_ROUTE_MAX) - return; - - /* - * NOTE: no need to withdraw the previously advertised routes. The clients - * themselves should keep track of the received routes from zebra and - * withdraw them when necessary. - */ - if (instance) - redist_del_instance (&client->mi_redist[afi][type], instance); - else - vrf_bitmap_unset (client->redist[afi][type], zvrf_id (zvrf)); + afi_t afi; + int type; + u_short instance; + + afi = stream_getc(client->ibuf); + type = stream_getc(client->ibuf); + instance = stream_getw(client->ibuf); + + if (type == 0 || type >= ZEBRA_ROUTE_MAX) + return; + + /* + * NOTE: no need to withdraw the previously advertised routes. The + * clients + * themselves should keep track of the received routes from zebra and + * withdraw them when necessary. + */ + if (instance) + redist_del_instance(&client->mi_redist[afi][type], instance); + else + vrf_bitmap_unset(client->redist[afi][type], zvrf_id(zvrf)); } -void -zebra_redistribute_default_add (int command, struct zserv *client, int length, - struct zebra_vrf *zvrf) +void zebra_redistribute_default_add(int command, struct zserv *client, + int length, struct zebra_vrf *zvrf) { - vrf_bitmap_set (client->redist_default, zvrf_id (zvrf)); - zebra_redistribute_default (client, zvrf_id (zvrf)); -} + vrf_bitmap_set(client->redist_default, zvrf_id(zvrf)); + zebra_redistribute_default(client, zvrf_id(zvrf)); +} -void -zebra_redistribute_default_delete (int command, struct zserv *client, - int length, struct zebra_vrf *zvrf) +void zebra_redistribute_default_delete(int command, struct zserv *client, + int length, struct zebra_vrf *zvrf) { - vrf_bitmap_unset (client->redist_default, zvrf_id (zvrf)); -} + vrf_bitmap_unset(client->redist_default, zvrf_id(zvrf)); +} /* Interface up information. */ -void -zebra_interface_up_update (struct interface *ifp) +void zebra_interface_up_update(struct interface *ifp) { - struct listnode *node, *nnode; - struct zserv *client; - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_UP %s", ifp->name); - - if (ifp->ptm_status || !ifp->ptm_enable) { - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - if (client->ifinfo) - { - zsend_interface_update (ZEBRA_INTERFACE_UP, client, ifp); - zsend_interface_link_params (client, ifp); + struct listnode *node, *nnode; + struct zserv *client; + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("MESSAGE: ZEBRA_INTERFACE_UP %s", ifp->name); + + if (ifp->ptm_status || !ifp->ptm_enable) { + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) + if (client->ifinfo) { + zsend_interface_update(ZEBRA_INTERFACE_UP, + client, ifp); + zsend_interface_link_params(client, ifp); + } } - } } /* Interface down information. */ -void -zebra_interface_down_update (struct interface *ifp) +void zebra_interface_down_update(struct interface *ifp) { - struct listnode *node, *nnode; - struct zserv *client; + struct listnode *node, *nnode; + struct zserv *client; - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_DOWN %s", ifp->name); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("MESSAGE: ZEBRA_INTERFACE_DOWN %s", ifp->name); - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - { - zsend_interface_update (ZEBRA_INTERFACE_DOWN, client, ifp); - } + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { + zsend_interface_update(ZEBRA_INTERFACE_DOWN, client, ifp); + } } /* Interface information update. */ -void -zebra_interface_add_update (struct interface *ifp) +void zebra_interface_add_update(struct interface *ifp) { - struct listnode *node, *nnode; - struct zserv *client; - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADD %s[%d]", ifp->name, ifp->vrf_id); - - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - if (client->ifinfo) - { - client->ifadd_cnt++; - zsend_interface_add (client, ifp); - zsend_interface_link_params (client, ifp); - } + struct listnode *node, *nnode; + struct zserv *client; + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("MESSAGE: ZEBRA_INTERFACE_ADD %s[%d]", ifp->name, + ifp->vrf_id); + + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) + if (client->ifinfo) { + client->ifadd_cnt++; + zsend_interface_add(client, ifp); + zsend_interface_link_params(client, ifp); + } } -void -zebra_interface_delete_update (struct interface *ifp) +void zebra_interface_delete_update(struct interface *ifp) { - struct listnode *node, *nnode; - struct zserv *client; + struct listnode *node, *nnode; + struct zserv *client; - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_DELETE %s", ifp->name); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("MESSAGE: ZEBRA_INTERFACE_DELETE %s", ifp->name); - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - { - client->ifdel_cnt++; - zsend_interface_delete (client, ifp); - } + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { + client->ifdel_cnt++; + zsend_interface_delete(client, ifp); + } } /* Interface address addition. */ -void -zebra_interface_address_add_update (struct interface *ifp, - struct connected *ifc) +void zebra_interface_address_add_update(struct interface *ifp, + struct connected *ifc) { - struct listnode *node, *nnode; - struct zserv *client; - struct prefix *p; - - if (IS_ZEBRA_DEBUG_EVENT) - { - char buf[PREFIX_STRLEN]; - - p = ifc->address; - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADDRESS_ADD %s on %s", - prefix2str (p, buf, sizeof(buf)), - ifc->ifp->name); - } - - if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) - zlog_warn("WARNING: advertising address to clients that is not yet usable."); - - router_id_add_address(ifc); - - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) - { - client->connected_rt_add_cnt++; - zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_ADD, client, ifp, ifc); - } + struct listnode *node, *nnode; + struct zserv *client; + struct prefix *p; + + if (IS_ZEBRA_DEBUG_EVENT) { + char buf[PREFIX_STRLEN]; + + p = ifc->address; + zlog_debug("MESSAGE: ZEBRA_INTERFACE_ADDRESS_ADD %s on %s", + prefix2str(p, buf, sizeof(buf)), ifc->ifp->name); + } + + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) + zlog_warn( + "WARNING: advertising address to clients that is not yet usable."); + + router_id_add_address(ifc); + + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) + if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) { + client->connected_rt_add_cnt++; + zsend_interface_address(ZEBRA_INTERFACE_ADDRESS_ADD, + client, ifp, ifc); + } } /* Interface address deletion. */ -void -zebra_interface_address_delete_update (struct interface *ifp, - struct connected *ifc) +void zebra_interface_address_delete_update(struct interface *ifp, + struct connected *ifc) { - struct listnode *node, *nnode; - struct zserv *client; - struct prefix *p; - - if (IS_ZEBRA_DEBUG_EVENT) - { - char buf[PREFIX_STRLEN]; - - p = ifc->address; - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADDRESS_DELETE %s on %s", - prefix2str (p, buf, sizeof(buf)), - ifc->ifp->name); - } - - router_id_del_address(ifc); - - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) - { - client->connected_rt_del_cnt++; - zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_DELETE, client, ifp, ifc); - } + struct listnode *node, *nnode; + struct zserv *client; + struct prefix *p; + + if (IS_ZEBRA_DEBUG_EVENT) { + char buf[PREFIX_STRLEN]; + + p = ifc->address; + zlog_debug("MESSAGE: ZEBRA_INTERFACE_ADDRESS_DELETE %s on %s", + prefix2str(p, buf, sizeof(buf)), ifc->ifp->name); + } + + router_id_del_address(ifc); + + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) + if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) { + client->connected_rt_del_cnt++; + zsend_interface_address(ZEBRA_INTERFACE_ADDRESS_DELETE, + client, ifp, ifc); + } } /* Interface VRF change. May need to delete from clients not interested in * the new VRF. Note that this function is invoked *prior* to the VRF change. */ -void -zebra_interface_vrf_update_del (struct interface *ifp, vrf_id_t new_vrf_id) +void zebra_interface_vrf_update_del(struct interface *ifp, vrf_id_t new_vrf_id) { - struct listnode *node, *nnode; - struct zserv *client; - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/DEL %s VRF Id %u -> %u", - ifp->name, ifp->vrf_id, new_vrf_id); - - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - { - /* Need to delete if the client is not interested in the new VRF. */ - zsend_interface_update (ZEBRA_INTERFACE_DOWN, client, ifp); - client->ifdel_cnt++; - zsend_interface_delete (client, ifp); - zsend_interface_vrf_update (client, ifp, new_vrf_id); - } + struct listnode *node, *nnode; + struct zserv *client; + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/DEL %s VRF Id %u -> %u", + ifp->name, ifp->vrf_id, new_vrf_id); + + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { + /* Need to delete if the client is not interested in the new + * VRF. */ + zsend_interface_update(ZEBRA_INTERFACE_DOWN, client, ifp); + client->ifdel_cnt++; + zsend_interface_delete(client, ifp); + zsend_interface_vrf_update(client, ifp, new_vrf_id); + } } /* Interface VRF change. This function is invoked *post* VRF change and sends an * add to clients who are interested in the new VRF but not in the old VRF. */ -void -zebra_interface_vrf_update_add (struct interface *ifp, vrf_id_t old_vrf_id) +void zebra_interface_vrf_update_add(struct interface *ifp, vrf_id_t old_vrf_id) { - struct listnode *node, *nnode; - struct zserv *client; - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/ADD %s VRF Id %u -> %u", - ifp->name, old_vrf_id, ifp->vrf_id); - - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - { - /* Need to add if the client is interested in the new VRF. */ - client->ifadd_cnt++; - zsend_interface_add (client, ifp); - zsend_interface_addresses (client, ifp); - } + struct listnode *node, *nnode; + struct zserv *client; + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/ADD %s VRF Id %u -> %u", + ifp->name, old_vrf_id, ifp->vrf_id); + + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { + /* Need to add if the client is interested in the new VRF. */ + client->ifadd_cnt++; + zsend_interface_add(client, ifp); + zsend_interface_addresses(client, ifp); + } } -int -zebra_add_import_table_entry (struct route_node *rn, struct route_entry *re, const char *rmap_name) +int zebra_add_import_table_entry(struct route_node *rn, struct route_entry *re, + const char *rmap_name) { - struct route_entry *newre; - struct route_entry *same; - struct prefix p; - struct nexthop *nhop; - union g_addr *gate; - route_map_result_t ret = RMAP_MATCH; - - if (rmap_name) - ret = zebra_import_table_route_map_check (AFI_IP, re->type, &rn->p, re->nexthop, re->vrf_id, - re->tag, rmap_name); - - if (ret == RMAP_MATCH) - { - if (rn->p.family == AF_INET) - { - p.family = AF_INET; - p.prefixlen = rn->p.prefixlen; - p.u.prefix4 = rn->p.u.prefix4; - - RNODE_FOREACH_RE (rn, same) - { - if (CHECK_FLAG (same->status, ROUTE_ENTRY_REMOVED)) - continue; - - if (same->type == re->type && same->instance == re->instance - && same->table == re->table - && same->type != ZEBRA_ROUTE_CONNECT) - break; - } - - if (same) - zebra_del_import_table_entry (rn, same); - - - if (re->nexthop_num == 1) - { - nhop = re->nexthop; - if (nhop->type == NEXTHOP_TYPE_IFINDEX) - gate = NULL; - else - gate = (union g_addr *)&nhop->gate.ipv4; - - rib_add (AFI_IP, SAFI_UNICAST, re->vrf_id, ZEBRA_ROUTE_TABLE, - re->table, 0, &p, NULL, gate, (union g_addr *)&nhop->src.ipv4, - nhop->ifindex, zebrad.rtm_table_default, - re->metric, re->mtu, - zebra_import_table_distance[AFI_IP][re->table]); - } - else if (re->nexthop_num > 1) - { - newre = XCALLOC (MTYPE_RE, sizeof (struct route_entry)); - newre->type = ZEBRA_ROUTE_TABLE; - newre->distance = zebra_import_table_distance[AFI_IP][re->table]; - newre->flags = re->flags; - newre->metric = re->metric; - newre->mtu = re->mtu; - newre->table = zebrad.rtm_table_default; - newre->nexthop_num = 0; - newre->uptime = time(NULL); - newre->instance = re->table; - route_entry_copy_nexthops(newre, re->nexthop); - - rib_add_multipath(AFI_IP, SAFI_UNICAST, &p, NULL, newre); - } - } - } - else - { - zebra_del_import_table_entry (rn, re); - } - /* DD: Add IPv6 code */ - return 0; + struct route_entry *newre; + struct route_entry *same; + struct prefix p; + struct nexthop *nhop; + union g_addr *gate; + route_map_result_t ret = RMAP_MATCH; + + if (rmap_name) + ret = zebra_import_table_route_map_check( + AFI_IP, re->type, &rn->p, re->nexthop, re->vrf_id, + re->tag, rmap_name); + + if (ret == RMAP_MATCH) { + if (rn->p.family == AF_INET) { + p.family = AF_INET; + p.prefixlen = rn->p.prefixlen; + p.u.prefix4 = rn->p.u.prefix4; + + RNODE_FOREACH_RE(rn, same) + { + if (CHECK_FLAG(same->status, + ROUTE_ENTRY_REMOVED)) + continue; + + if (same->type == re->type + && same->instance == re->instance + && same->table == re->table + && same->type != ZEBRA_ROUTE_CONNECT) + break; + } + + if (same) + zebra_del_import_table_entry(rn, same); + + + if (re->nexthop_num == 1) { + nhop = re->nexthop; + if (nhop->type == NEXTHOP_TYPE_IFINDEX) + gate = NULL; + else + gate = (union g_addr *)&nhop->gate.ipv4; + + rib_add(AFI_IP, SAFI_UNICAST, re->vrf_id, + ZEBRA_ROUTE_TABLE, re->table, 0, &p, + NULL, gate, + (union g_addr *)&nhop->src.ipv4, + nhop->ifindex, zebrad.rtm_table_default, + re->metric, re->mtu, + zebra_import_table_distance[AFI_IP] + [re->table]); + } else if (re->nexthop_num > 1) { + newre = XCALLOC(MTYPE_RE, + sizeof(struct route_entry)); + newre->type = ZEBRA_ROUTE_TABLE; + newre->distance = + zebra_import_table_distance[AFI_IP] + [re->table]; + newre->flags = re->flags; + newre->metric = re->metric; + newre->mtu = re->mtu; + newre->table = zebrad.rtm_table_default; + newre->nexthop_num = 0; + newre->uptime = time(NULL); + newre->instance = re->table; + route_entry_copy_nexthops(newre, re->nexthop); + + rib_add_multipath(AFI_IP, SAFI_UNICAST, &p, + NULL, newre); + } + } + } else { + zebra_del_import_table_entry(rn, re); + } + /* DD: Add IPv6 code */ + return 0; } -int -zebra_del_import_table_entry (struct route_node *rn, struct route_entry *re) +int zebra_del_import_table_entry(struct route_node *rn, struct route_entry *re) { - struct prefix p; + struct prefix p; - if (rn->p.family == AF_INET) - { - p.family = AF_INET; - p.prefixlen = rn->p.prefixlen; - p.u.prefix4 = rn->p.u.prefix4; + if (rn->p.family == AF_INET) { + p.family = AF_INET; + p.prefixlen = rn->p.prefixlen; + p.u.prefix4 = rn->p.u.prefix4; - rib_delete (AFI_IP, SAFI_UNICAST, re->vrf_id, ZEBRA_ROUTE_TABLE, - re->table, re->flags, &p, NULL, NULL, - 0, zebrad.rtm_table_default); - } - /* DD: Add IPv6 code */ + rib_delete(AFI_IP, SAFI_UNICAST, re->vrf_id, ZEBRA_ROUTE_TABLE, + re->table, re->flags, &p, NULL, NULL, 0, + zebrad.rtm_table_default); + } + /* DD: Add IPv6 code */ - return 0; + return 0; } /* Assuming no one calls this with the main routing table */ -int -zebra_import_table (afi_t afi, u_int32_t table_id, u_int32_t distance, const char *rmap_name, int add) +int zebra_import_table(afi_t afi, u_int32_t table_id, u_int32_t distance, + const char *rmap_name, int add) { - struct route_table *table; - struct route_entry *re; - struct route_node *rn; - - if (!is_zebra_valid_kernel_table(table_id) || - ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default))) - return (-1); - - if (afi >= AFI_MAX) - return (-1); - - table = zebra_vrf_other_route_table(afi, table_id, VRF_DEFAULT); - if (table == NULL) - { - return 0; - } - else if (IS_ZEBRA_DEBUG_RIB) - { - zlog_debug ("%s routes from table %d", - add ? "Importing" : "Unimporting", table_id); - } - - if (add) - { - if (rmap_name) - zebra_add_import_table_route_map (afi, rmap_name, table_id); - else - { - rmap_name = zebra_get_import_table_route_map (afi, table_id); - if (rmap_name) - zebra_del_import_table_route_map (afi, table_id); - } - - zebra_import_table_used[afi][table_id] = 1; - zebra_import_table_distance[afi][table_id] = distance; - } - else - { - zebra_import_table_used[afi][table_id] = 0; - zebra_import_table_distance[afi][table_id] = ZEBRA_TABLE_DISTANCE_DEFAULT; - - rmap_name = zebra_get_import_table_route_map (afi, table_id); - if (rmap_name) - zebra_del_import_table_route_map (afi, table_id); - } - - for (rn = route_top(table); rn; rn = route_next(rn)) - { - /* For each entry in the non-default routing table, - * add the entry in the main table - */ - if (!rn->info) - continue; - - RNODE_FOREACH_RE (rn, re) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - break; + struct route_table *table; + struct route_entry *re; + struct route_node *rn; + + if (!is_zebra_valid_kernel_table(table_id) + || ((table_id == RT_TABLE_MAIN) + || (table_id == zebrad.rtm_table_default))) + return (-1); + + if (afi >= AFI_MAX) + return (-1); + + table = zebra_vrf_other_route_table(afi, table_id, VRF_DEFAULT); + if (table == NULL) { + return 0; + } else if (IS_ZEBRA_DEBUG_RIB) { + zlog_debug("%s routes from table %d", + add ? "Importing" : "Unimporting", table_id); } - if (!re) - continue; + if (add) { + if (rmap_name) + zebra_add_import_table_route_map(afi, rmap_name, + table_id); + else { + rmap_name = + zebra_get_import_table_route_map(afi, table_id); + if (rmap_name) + zebra_del_import_table_route_map(afi, table_id); + } - if (((afi == AFI_IP) && (rn->p.family == AF_INET)) || - ((afi == AFI_IP6) && (rn->p.family == AF_INET6))) - { - if (add) - zebra_add_import_table_entry (rn, re, rmap_name); - else - zebra_del_import_table_entry (rn, re); + zebra_import_table_used[afi][table_id] = 1; + zebra_import_table_distance[afi][table_id] = distance; + } else { + zebra_import_table_used[afi][table_id] = 0; + zebra_import_table_distance[afi][table_id] = + ZEBRA_TABLE_DISTANCE_DEFAULT; + + rmap_name = zebra_get_import_table_route_map(afi, table_id); + if (rmap_name) + zebra_del_import_table_route_map(afi, table_id); } - } - return 0; -} -int -zebra_import_table_config (struct vty *vty) -{ - int i; - afi_t afi; - int write = 0; - char afi_str[AFI_MAX][10] = {"", "ip", "ipv6", "ethernet"}; - const char *rmap_name; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - for (i = 1; i < ZEBRA_KERNEL_TABLE_MAX; i++) - { - if (is_zebra_import_table_enabled(afi, i)) - { - if (zebra_import_table_distance[afi][i] != ZEBRA_TABLE_DISTANCE_DEFAULT) - { - vty_out(vty, "%s import-table %d distance %d", afi_str[afi], - i, zebra_import_table_distance[afi][i]); - } - else + for (rn = route_top(table); rn; rn = route_next(rn)) { + /* For each entry in the non-default routing table, + * add the entry in the main table + */ + if (!rn->info) + continue; + + RNODE_FOREACH_RE(rn, re) { - vty_out(vty, "%s import-table %d", afi_str[afi], i); + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + break; } - rmap_name = zebra_get_import_table_route_map (afi, i); - if (rmap_name) - vty_out(vty, " route-map %s", rmap_name); + if (!re) + continue; - vty_out (vty, "\n"); - write = 1; - } + if (((afi == AFI_IP) && (rn->p.family == AF_INET)) + || ((afi == AFI_IP6) && (rn->p.family == AF_INET6))) { + if (add) + zebra_add_import_table_entry(rn, re, rmap_name); + else + zebra_del_import_table_entry(rn, re); + } + } + return 0; +} + +int zebra_import_table_config(struct vty *vty) +{ + int i; + afi_t afi; + int write = 0; + char afi_str[AFI_MAX][10] = {"", "ip", "ipv6", "ethernet"}; + const char *rmap_name; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + for (i = 1; i < ZEBRA_KERNEL_TABLE_MAX; i++) { + if (is_zebra_import_table_enabled(afi, i)) { + if (zebra_import_table_distance[afi][i] + != ZEBRA_TABLE_DISTANCE_DEFAULT) { + vty_out(vty, + "%s import-table %d distance %d", + afi_str[afi], i, + zebra_import_table_distance[afi] + [i]); + } else { + vty_out(vty, "%s import-table %d", + afi_str[afi], i); + } + + rmap_name = zebra_get_import_table_route_map( + afi, i); + if (rmap_name) + vty_out(vty, " route-map %s", + rmap_name); + + vty_out(vty, "\n"); + write = 1; + } + } } - } - return write; + return write; } -void -zebra_import_table_rm_update () +void zebra_import_table_rm_update() { - afi_t afi; - int i; - struct route_table *table; - struct route_entry *re; - struct route_node *rn; - const char *rmap_name; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - for (i = 1; i < ZEBRA_KERNEL_TABLE_MAX; i++) - { - if (is_zebra_import_table_enabled(afi, i)) - { - rmap_name = zebra_get_import_table_route_map (afi, i); - if (!rmap_name) - return; - - table = zebra_vrf_other_route_table(afi, i, VRF_DEFAULT); - for (rn = route_top(table); rn; rn = route_next(rn)) - { - /* For each entry in the non-default routing table, - * add the entry in the main table - */ - if (!rn->info) - continue; - - RNODE_FOREACH_RE (rn, re) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - break; - } - - if (!re) - continue; - - if (((afi == AFI_IP) && (rn->p.family == AF_INET)) || - ((afi == AFI_IP6) && (rn->p.family == AF_INET6))) - zebra_add_import_table_entry (rn, re, rmap_name); - } - } + afi_t afi; + int i; + struct route_table *table; + struct route_entry *re; + struct route_node *rn; + const char *rmap_name; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + for (i = 1; i < ZEBRA_KERNEL_TABLE_MAX; i++) { + if (is_zebra_import_table_enabled(afi, i)) { + rmap_name = zebra_get_import_table_route_map( + afi, i); + if (!rmap_name) + return; + + table = zebra_vrf_other_route_table( + afi, i, VRF_DEFAULT); + for (rn = route_top(table); rn; + rn = route_next(rn)) { + /* For each entry in the non-default + * routing table, + * add the entry in the main table + */ + if (!rn->info) + continue; + + RNODE_FOREACH_RE(rn, re) + { + if (CHECK_FLAG( + re->status, + ROUTE_ENTRY_REMOVED)) + continue; + break; + } + + if (!re) + continue; + + if (((afi == AFI_IP) + && (rn->p.family == AF_INET)) + || ((afi == AFI_IP6) + && (rn->p.family == AF_INET6))) + zebra_add_import_table_entry( + rn, re, rmap_name); + } + } + } } - } - return; + return; } /* Interface parameters update */ -void -zebra_interface_parameters_update (struct interface *ifp) +void zebra_interface_parameters_update(struct interface *ifp) { - struct listnode *node, *nnode; - struct zserv *client; + struct listnode *node, *nnode; + struct zserv *client; - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_LINK_PARAMS %s", ifp->name); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("MESSAGE: ZEBRA_INTERFACE_LINK_PARAMS %s", + ifp->name); - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - if (client->ifinfo) - zsend_interface_link_params (client, ifp); + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) + if (client->ifinfo) + zsend_interface_link_params(client, ifp); } diff --git a/zebra/redistribute.h b/zebra/redistribute.h index 429ec1bfd..819b67918 100644 --- a/zebra/redistribute.h +++ b/zebra/redistribute.h @@ -27,46 +27,51 @@ #include "vty.h" #include "vrf.h" -extern void zebra_redistribute_add (int, struct zserv *, int, struct zebra_vrf *zvrf); -extern void zebra_redistribute_delete (int, struct zserv *, int, struct zebra_vrf *zvrf); +extern void zebra_redistribute_add(int, struct zserv *, int, + struct zebra_vrf *zvrf); +extern void zebra_redistribute_delete(int, struct zserv *, int, + struct zebra_vrf *zvrf); -extern void zebra_redistribute_default_add (int, struct zserv *, int, - struct zebra_vrf *zvrf); -extern void zebra_redistribute_default_delete (int, struct zserv *, int, - struct zebra_vrf *zvrf); +extern void zebra_redistribute_default_add(int, struct zserv *, int, + struct zebra_vrf *zvrf); +extern void zebra_redistribute_default_delete(int, struct zserv *, int, + struct zebra_vrf *zvrf); -extern void redistribute_update (struct prefix *, struct prefix *, - struct route_entry *, struct route_entry *); -extern void redistribute_delete (struct prefix *, struct prefix *, struct route_entry *); +extern void redistribute_update(struct prefix *, struct prefix *, + struct route_entry *, struct route_entry *); +extern void redistribute_delete(struct prefix *, struct prefix *, + struct route_entry *); -extern void zebra_interface_up_update (struct interface *); -extern void zebra_interface_down_update (struct interface *); +extern void zebra_interface_up_update(struct interface *); +extern void zebra_interface_down_update(struct interface *); -extern void zebra_interface_add_update (struct interface *); -extern void zebra_interface_delete_update (struct interface *); +extern void zebra_interface_add_update(struct interface *); +extern void zebra_interface_delete_update(struct interface *); -extern void zebra_interface_address_add_update (struct interface *, - struct connected *); -extern void zebra_interface_address_delete_update (struct interface *, - struct connected *c); -extern void zebra_interface_parameters_update (struct interface *); -extern void zebra_interface_vrf_update_del (struct interface *, vrf_id_t new_vrf_id); -extern void zebra_interface_vrf_update_add (struct interface *, vrf_id_t old_vrf_id); +extern void zebra_interface_address_add_update(struct interface *, + struct connected *); +extern void zebra_interface_address_delete_update(struct interface *, + struct connected *c); +extern void zebra_interface_parameters_update(struct interface *); +extern void zebra_interface_vrf_update_del(struct interface *, + vrf_id_t new_vrf_id); +extern void zebra_interface_vrf_update_add(struct interface *, + vrf_id_t old_vrf_id); -extern int zebra_import_table (afi_t afi, u_int32_t table_id, - u_int32_t distance, const char *rmap_name, int add); +extern int zebra_import_table(afi_t afi, u_int32_t table_id, u_int32_t distance, + const char *rmap_name, int add); -extern int zebra_add_import_table_entry (struct route_node *rn, - struct route_entry *re, const char *rmap_name); -extern int zebra_del_import_table_entry (struct route_node *rn, - struct route_entry *re); +extern int zebra_add_import_table_entry(struct route_node *rn, + struct route_entry *re, + const char *rmap_name); +extern int zebra_del_import_table_entry(struct route_node *rn, + struct route_entry *re); extern int is_zebra_import_table_enabled(afi_t, u_int32_t table_id); extern int zebra_import_table_config(struct vty *); extern void zebra_import_table_rm_update(void); -extern int is_default (struct prefix *); +extern int is_default(struct prefix *); #endif /* _ZEBRA_REDISTRIBUTE_H */ - diff --git a/zebra/rib.h b/zebra/rib.h index 999266241..eca2be5ee 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -37,63 +37,62 @@ #define DISTANCE_INFINITY 255 #define ZEBRA_KERNEL_TABLE_MAX 252 /* support for no more than this rt tables */ -struct route_entry -{ - /* Link list. */ - struct route_entry *next; - struct route_entry *prev; - - /* Nexthop structure */ - struct nexthop *nexthop; - - /* Refrence count. */ - unsigned long refcnt; - - /* Tag */ - route_tag_t tag; - - /* Uptime. */ - time_t uptime; - - /* Type fo this route. */ - int type; - - /* Source protocol instance */ - u_short instance; - - /* VRF identifier. */ - vrf_id_t vrf_id; - - /* Which routing table */ - uint32_t table; - - /* Metric */ - u_int32_t metric; - - /* MTU */ - u_int32_t mtu; - u_int32_t nexthop_mtu; - - /* Distance. */ - u_char distance; - - /* Flags of this route. - * This flag's definition is in lib/zebra.h ZEBRA_FLAG_* and is exposed - * to clients via Zserv - */ - u_int32_t flags; - - /* RIB internal status */ - u_char status; +struct route_entry { + /* Link list. */ + struct route_entry *next; + struct route_entry *prev; + + /* Nexthop structure */ + struct nexthop *nexthop; + + /* Refrence count. */ + unsigned long refcnt; + + /* Tag */ + route_tag_t tag; + + /* Uptime. */ + time_t uptime; + + /* Type fo this route. */ + int type; + + /* Source protocol instance */ + u_short instance; + + /* VRF identifier. */ + vrf_id_t vrf_id; + + /* Which routing table */ + uint32_t table; + + /* Metric */ + u_int32_t metric; + + /* MTU */ + u_int32_t mtu; + u_int32_t nexthop_mtu; + + /* Distance. */ + u_char distance; + + /* Flags of this route. + * This flag's definition is in lib/zebra.h ZEBRA_FLAG_* and is exposed + * to clients via Zserv + */ + u_int32_t flags; + + /* RIB internal status */ + u_char status; #define ROUTE_ENTRY_REMOVED 0x1 - /* to simplify NHT logic when NHs change, instead of doing a NH by NH cmp */ +/* to simplify NHT logic when NHs change, instead of doing a NH by NH cmp */ #define ROUTE_ENTRY_NEXTHOPS_CHANGED 0x2 #define ROUTE_ENTRY_CHANGED 0x4 #define ROUTE_ENTRY_SELECTED_FIB 0x8 - /* Nexthop information. */ - u_char nexthop_num; - u_char nexthop_active_num; + /* Nexthop information. */ + u_char nexthop_num; + u_char nexthop_active_num; }; /* meta-queue structure: @@ -104,38 +103,36 @@ struct route_entry * sub-queue 4: any other origin (if any) */ #define MQ_SIZE 5 -struct meta_queue -{ - struct list *subq[MQ_SIZE]; - u_int32_t size; /* sum of lengths of all subqueues */ +struct meta_queue { + struct list *subq[MQ_SIZE]; + u_int32_t size; /* sum of lengths of all subqueues */ }; /* * Structure that represents a single destination (prefix). */ -typedef struct rib_dest_t_ -{ +typedef struct rib_dest_t_ { - /* - * Back pointer to the route node for this destination. This helps - * us get to the prefix that this structure is for. - */ - struct route_node *rnode; + /* + * Back pointer to the route node for this destination. This helps + * us get to the prefix that this structure is for. + */ + struct route_node *rnode; - /* - * Doubly-linked list of routes for this prefix. - */ - struct route_entry *routes; + /* + * Doubly-linked list of routes for this prefix. + */ + struct route_entry *routes; - /* - * Flags, see below. - */ - u_int32_t flags; + /* + * Flags, see below. + */ + u_int32_t flags; - /* - * Linkage to put dest on the FPM processing queue. - */ - TAILQ_ENTRY(rib_dest_t_) fpm_q_entries; + /* + * Linkage to put dest on the FPM processing queue. + */ + TAILQ_ENTRY(rib_dest_t_) fpm_q_entries; } rib_dest_t; @@ -161,34 +158,32 @@ typedef struct rib_dest_t_ /* * Macro to iterate over each route for a destination (prefix). */ -#define RE_DEST_FOREACH_ROUTE(dest, re) \ - for ((re) = (dest) ? (dest)->routes : NULL; (re); (re) = (re)->next) +#define RE_DEST_FOREACH_ROUTE(dest, re) \ + for ((re) = (dest) ? (dest)->routes : NULL; (re); (re) = (re)->next) /* * Same as above, but allows the current node to be unlinked. */ -#define RE_DEST_FOREACH_ROUTE_SAFE(dest, re, next) \ - for ((re) = (dest) ? (dest)->routes : NULL; \ - (re) && ((next) = (re)->next, 1); \ - (re) = (next)) +#define RE_DEST_FOREACH_ROUTE_SAFE(dest, re, next) \ + for ((re) = (dest) ? (dest)->routes : NULL; \ + (re) && ((next) = (re)->next, 1); (re) = (next)) -#define RNODE_FOREACH_RE(rn, re) \ - RE_DEST_FOREACH_ROUTE (rib_dest_from_rnode (rn), re) +#define RNODE_FOREACH_RE(rn, re) \ + RE_DEST_FOREACH_ROUTE(rib_dest_from_rnode(rn), re) -#define RNODE_FOREACH_RE_SAFE(rn, re, next) \ - RE_DEST_FOREACH_ROUTE_SAFE (rib_dest_from_rnode (rn), re, next) +#define RNODE_FOREACH_RE_SAFE(rn, re, next) \ + RE_DEST_FOREACH_ROUTE_SAFE(rib_dest_from_rnode(rn), re, next) -#if defined (HAVE_RTADV) +#if defined(HAVE_RTADV) /* Structure which hold status of router advertisement. */ -struct rtadv -{ - int sock; +struct rtadv { + int sock; - int adv_if_count; - int adv_msec_if_count; + int adv_if_count; + int adv_msec_if_count; - struct thread *ra_read; - struct thread *ra_timer; + struct thread *ra_read; + struct thread *ra_timer; }; #endif /* HAVE_RTADV */ @@ -198,142 +193,141 @@ struct rtadv * Structure that is hung off of a route_table that holds information about * the table. */ -typedef struct rib_table_info_t_ -{ +typedef struct rib_table_info_t_ { - /* - * Back pointer to zebra_vrf. - */ - struct zebra_vrf *zvrf; - afi_t afi; - safi_t safi; + /* + * Back pointer to zebra_vrf. + */ + struct zebra_vrf *zvrf; + afi_t afi; + safi_t safi; } rib_table_info_t; -typedef enum -{ - RIB_TABLES_ITER_S_INIT, - RIB_TABLES_ITER_S_ITERATING, - RIB_TABLES_ITER_S_DONE +typedef enum { + RIB_TABLES_ITER_S_INIT, + RIB_TABLES_ITER_S_ITERATING, + RIB_TABLES_ITER_S_DONE } rib_tables_iter_state_t; /* * Structure that holds state for iterating over all tables in the * Routing Information Base. */ -typedef struct rib_tables_iter_t_ -{ - vrf_id_t vrf_id; - int afi_safi_ix; +typedef struct rib_tables_iter_t_ { + vrf_id_t vrf_id; + int afi_safi_ix; - rib_tables_iter_state_t state; + rib_tables_iter_state_t state; } rib_tables_iter_t; /* Events/reasons triggering a RIB update. */ -typedef enum -{ - RIB_UPDATE_IF_CHANGE, - RIB_UPDATE_RMAP_CHANGE, - RIB_UPDATE_OTHER +typedef enum { + RIB_UPDATE_IF_CHANGE, + RIB_UPDATE_RMAP_CHANGE, + RIB_UPDATE_OTHER } rib_update_event_t; -extern struct nexthop *route_entry_nexthop_ifindex_add (struct route_entry *, ifindex_t); -extern struct nexthop *route_entry_nexthop_blackhole_add (struct route_entry *); -extern struct nexthop *route_entry_nexthop_ipv4_add (struct route_entry *, - struct in_addr *, - struct in_addr *); -extern struct nexthop *route_entry_nexthop_ipv4_ifindex_add (struct route_entry *, - struct in_addr *, - struct in_addr *, - ifindex_t); -extern void route_entry_nexthop_delete (struct route_entry *re, struct nexthop *nexthop); -extern struct nexthop *route_entry_nexthop_ipv6_add (struct route_entry *, - struct in6_addr *); -extern struct nexthop *route_entry_nexthop_ipv6_ifindex_add (struct route_entry *re, - struct in6_addr *ipv6, - ifindex_t ifindex); -extern void route_entry_nexthop_add (struct route_entry *re, struct nexthop *nexthop); -extern void route_entry_copy_nexthops (struct route_entry *re, struct nexthop *nh); +extern struct nexthop *route_entry_nexthop_ifindex_add(struct route_entry *, + ifindex_t); +extern struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *); +extern struct nexthop *route_entry_nexthop_ipv4_add(struct route_entry *, + struct in_addr *, + struct in_addr *); +extern struct nexthop * +route_entry_nexthop_ipv4_ifindex_add(struct route_entry *, struct in_addr *, + struct in_addr *, ifindex_t); +extern void route_entry_nexthop_delete(struct route_entry *re, + struct nexthop *nexthop); +extern struct nexthop *route_entry_nexthop_ipv6_add(struct route_entry *, + struct in6_addr *); +extern struct nexthop * +route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re, + struct in6_addr *ipv6, ifindex_t ifindex); +extern void route_entry_nexthop_add(struct route_entry *re, + struct nexthop *nexthop); +extern void route_entry_copy_nexthops(struct route_entry *re, + struct nexthop *nh); #define route_entry_dump(prefix, src, re) _route_entry_dump(__func__, prefix, src, re) -extern void _route_entry_dump (const char *, - union prefixconstptr, - union prefixconstptr, const struct route_entry *); +extern void _route_entry_dump(const char *, union prefixconstptr, + union prefixconstptr, const struct route_entry *); /* RPF lookup behaviour */ -enum multicast_mode -{ - MCAST_NO_CONFIG = 0, /* MIX_MRIB_FIRST, but no show in config write */ - MCAST_MRIB_ONLY, /* MRIB only */ - MCAST_URIB_ONLY, /* URIB only */ - MCAST_MIX_MRIB_FIRST, /* MRIB, if nothing at all then URIB */ - MCAST_MIX_DISTANCE, /* MRIB & URIB, lower distance wins */ - MCAST_MIX_PFXLEN, /* MRIB & URIB, longer prefix wins */ - /* on equal value, MRIB wins for last 2 */ +enum multicast_mode { + MCAST_NO_CONFIG = 0, /* MIX_MRIB_FIRST, but no show in config write */ + MCAST_MRIB_ONLY, /* MRIB only */ + MCAST_URIB_ONLY, /* URIB only */ + MCAST_MIX_MRIB_FIRST, /* MRIB, if nothing at all then URIB */ + MCAST_MIX_DISTANCE, /* MRIB & URIB, lower distance wins */ + MCAST_MIX_PFXLEN, /* MRIB & URIB, longer prefix wins */ + /* on equal value, MRIB wins for last 2 */ }; -extern void multicast_mode_ipv4_set (enum multicast_mode mode); -extern enum multicast_mode multicast_mode_ipv4_get (void); +extern void multicast_mode_ipv4_set(enum multicast_mode mode); +extern enum multicast_mode multicast_mode_ipv4_get(void); -extern void rib_lookup_and_dump (struct prefix_ipv4 *, vrf_id_t); -extern void rib_lookup_and_pushup (struct prefix_ipv4 *, vrf_id_t); +extern void rib_lookup_and_dump(struct prefix_ipv4 *, vrf_id_t); +extern void rib_lookup_and_pushup(struct prefix_ipv4 *, vrf_id_t); -extern int rib_lookup_ipv4_route (struct prefix_ipv4 *, union sockunion *, - vrf_id_t); +extern int rib_lookup_ipv4_route(struct prefix_ipv4 *, union sockunion *, + vrf_id_t); #define ZEBRA_RIB_LOOKUP_ERROR -1 #define ZEBRA_RIB_FOUND_EXACT 0 #define ZEBRA_RIB_FOUND_NOGATE 1 #define ZEBRA_RIB_FOUND_CONNECTED 2 #define ZEBRA_RIB_NOTFOUND 3 - - extern int is_zebra_valid_kernel_table(u_int32_t table_id); extern int is_zebra_main_routing_table(u_int32_t table_id); -extern int zebra_check_addr (struct prefix *p); +extern int zebra_check_addr(struct prefix *p); -extern void rib_addnode (struct route_node *rn, struct route_entry *re, int process); -extern void rib_delnode (struct route_node *rn, struct route_entry *re); -extern int rib_install_kernel (struct route_node *rn, struct route_entry *re, struct route_entry *old); -extern int rib_uninstall_kernel (struct route_node *rn, struct route_entry *re); +extern void rib_addnode(struct route_node *rn, struct route_entry *re, + int process); +extern void rib_delnode(struct route_node *rn, struct route_entry *re); +extern int rib_install_kernel(struct route_node *rn, struct route_entry *re, + struct route_entry *old); +extern int rib_uninstall_kernel(struct route_node *rn, struct route_entry *re); /* NOTE: * All rib_add function will not just add prefix into RIB, but * also implicitly withdraw equal prefix of same type. */ -extern int rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, - u_short instance, int flags, struct prefix *p, - struct prefix_ipv6 *src_p, union g_addr *gate, union g_addr *src, - ifindex_t ifindex, u_int32_t table_id, - u_int32_t, u_int32_t, u_char); - -extern int rib_add_multipath (afi_t afi, safi_t safi, struct prefix *, - struct prefix_ipv6 *src_p, struct route_entry *); - -extern void rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, - u_short instance, int flags, struct prefix *p, - struct prefix_ipv6 *src_p, union g_addr *gate, - ifindex_t ifindex, u_int32_t table_id); - -extern struct route_entry *rib_match (afi_t afi, safi_t safi, vrf_id_t, union g_addr *, - struct route_node **rn_out); -extern struct route_entry *rib_match_ipv4_multicast (vrf_id_t vrf_id, struct in_addr addr, - struct route_node **rn_out); - -extern struct route_entry *rib_lookup_ipv4 (struct prefix_ipv4 *, vrf_id_t); - -extern void rib_update (vrf_id_t, rib_update_event_t); -extern void rib_weed_tables (void); -extern void rib_sweep_route (void); -extern void rib_close_table (struct route_table *); -extern void rib_init (void); -extern unsigned long rib_score_proto (u_char proto, u_short instance); -extern void rib_queue_add (struct route_node *rn); -extern void meta_queue_free (struct meta_queue *mq); -extern int zebra_rib_labeled_unicast (struct route_entry *re); +extern int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, + u_short instance, int flags, struct prefix *p, + struct prefix_ipv6 *src_p, union g_addr *gate, + union g_addr *src, ifindex_t ifindex, u_int32_t table_id, + u_int32_t, u_int32_t, u_char); + +extern int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *, + struct prefix_ipv6 *src_p, struct route_entry *); + +extern void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, + u_short instance, int flags, struct prefix *p, + struct prefix_ipv6 *src_p, union g_addr *gate, + ifindex_t ifindex, u_int32_t table_id); + +extern struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t, + union g_addr *, + struct route_node **rn_out); +extern struct route_entry *rib_match_ipv4_multicast(vrf_id_t vrf_id, + struct in_addr addr, + struct route_node **rn_out); + +extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *, vrf_id_t); + +extern void rib_update(vrf_id_t, rib_update_event_t); +extern void rib_weed_tables(void); +extern void rib_sweep_route(void); +extern void rib_close_table(struct route_table *); +extern void rib_init(void); +extern unsigned long rib_score_proto(u_char proto, u_short instance); +extern void rib_queue_add(struct route_node *rn); +extern void meta_queue_free(struct meta_queue *mq); +extern int zebra_rib_labeled_unicast(struct route_entry *re); extern struct route_table *rib_table_ipv6; -extern void rib_unlink (struct route_node *, struct route_entry *); -extern int rib_gc_dest (struct route_node *rn); -extern struct route_table *rib_tables_iter_next (rib_tables_iter_t *iter); +extern void rib_unlink(struct route_node *, struct route_entry *); +extern int rib_gc_dest(struct route_node *rn); +extern struct route_table *rib_tables_iter_next(rib_tables_iter_t *iter); extern u_char route_distance(int type); @@ -344,19 +338,17 @@ extern u_char route_distance(int type); /* * rib_table_info */ -static inline rib_table_info_t * -rib_table_info (struct route_table *table) +static inline rib_table_info_t *rib_table_info(struct route_table *table) { - return (rib_table_info_t *) table->info; + return (rib_table_info_t *)table->info; } /* * rib_dest_from_rnode */ -static inline rib_dest_t * -rib_dest_from_rnode (struct route_node *rn) +static inline rib_dest_t *rib_dest_from_rnode(struct route_node *rn) { - return (rib_dest_t *) rn->info; + return (rib_dest_t *)rn->info; } /* @@ -365,25 +357,23 @@ rib_dest_from_rnode (struct route_node *rn) * Returns a pointer to the list of routes corresponding to the given * route_node. */ -static inline struct route_entry * -rnode_to_ribs (struct route_node *rn) +static inline struct route_entry *rnode_to_ribs(struct route_node *rn) { - rib_dest_t *dest; + rib_dest_t *dest; - dest = rib_dest_from_rnode (rn); - if (!dest) - return NULL; + dest = rib_dest_from_rnode(rn); + if (!dest) + return NULL; - return dest->routes; + return dest->routes; } /* * rib_dest_prefix */ -static inline struct prefix * -rib_dest_prefix (rib_dest_t *dest) +static inline struct prefix *rib_dest_prefix(rib_dest_t *dest) { - return &dest->rnode->p; + return &dest->rnode->p; } /* @@ -391,39 +381,35 @@ rib_dest_prefix (rib_dest_t *dest) * * Returns the address family that the destination is for. */ -static inline u_char -rib_dest_af (rib_dest_t *dest) +static inline u_char rib_dest_af(rib_dest_t *dest) { - return dest->rnode->p.family; + return dest->rnode->p.family; } /* * rib_dest_table */ -static inline struct route_table * -rib_dest_table (rib_dest_t *dest) +static inline struct route_table *rib_dest_table(rib_dest_t *dest) { - return srcdest_rnode_table(dest->rnode); + return srcdest_rnode_table(dest->rnode); } /* * rib_dest_vrf */ -static inline struct zebra_vrf * -rib_dest_vrf (rib_dest_t *dest) +static inline struct zebra_vrf *rib_dest_vrf(rib_dest_t *dest) { - return rib_table_info (rib_dest_table (dest))->zvrf; + return rib_table_info(rib_dest_table(dest))->zvrf; } /* * rib_tables_iter_init */ -static inline void -rib_tables_iter_init (rib_tables_iter_t *iter) +static inline void rib_tables_iter_init(rib_tables_iter_t *iter) { - memset (iter, 0, sizeof (*iter)); - iter->state = RIB_TABLES_ITER_S_INIT; + memset(iter, 0, sizeof(*iter)); + iter->state = RIB_TABLES_ITER_S_INIT; } /* @@ -432,21 +418,20 @@ rib_tables_iter_init (rib_tables_iter_t *iter) * Returns TRUE if this iterator has started iterating over the set of * tables. */ -static inline int -rib_tables_iter_started (rib_tables_iter_t *iter) +static inline int rib_tables_iter_started(rib_tables_iter_t *iter) { - return iter->state != RIB_TABLES_ITER_S_INIT; + return iter->state != RIB_TABLES_ITER_S_INIT; } /* * rib_tables_iter_cleanup */ -static inline void -rib_tables_iter_cleanup (rib_tables_iter_t *iter) +static inline void rib_tables_iter_cleanup(rib_tables_iter_t *iter) { - iter->state = RIB_TABLES_ITER_S_DONE; + iter->state = RIB_TABLES_ITER_S_DONE; } -DECLARE_HOOK(rib_update, (struct route_node *rn, const char *reason), (rn, reason)) +DECLARE_HOOK(rib_update, (struct route_node * rn, const char *reason), + (rn, reason)) #endif /*_ZEBRA_RIB_H */ diff --git a/zebra/router-id.c b/zebra/router-id.c index e23178cb7..383f21864 100644 --- a/zebra/router-id.c +++ b/zebra/router-id.c @@ -1,7 +1,7 @@ /* * Router ID for zebra daemon. * - * Copyright (C) 2004 James R. Leu + * Copyright (C) 2004 James R. Leu * * This file is part of Quagga routing suite. * @@ -46,169 +46,160 @@ /* master zebra server structure */ extern struct zebra_t zebrad; -static struct connected * -router_id_find_node (struct list *l, struct connected *ifc) +static struct connected *router_id_find_node(struct list *l, + struct connected *ifc) { - struct listnode *node; - struct connected *c; + struct listnode *node; + struct connected *c; - for (ALL_LIST_ELEMENTS_RO (l, node, c)) - if (prefix_same (ifc->address, c->address)) - return c; + for (ALL_LIST_ELEMENTS_RO(l, node, c)) + if (prefix_same(ifc->address, c->address)) + return c; - return NULL; + return NULL; } -static int -router_id_bad_address (struct connected *ifc) +static int router_id_bad_address(struct connected *ifc) { - if (ifc->address->family != AF_INET) - return 1; - - /* non-redistributable addresses shouldn't be used for RIDs either */ - if (!zebra_check_addr (ifc->address)) - return 1; - - return 0; + if (ifc->address->family != AF_INET) + return 1; + + /* non-redistributable addresses shouldn't be used for RIDs either */ + if (!zebra_check_addr(ifc->address)) + return 1; + + return 0; } -void -router_id_get (struct prefix *p, vrf_id_t vrf_id) +void router_id_get(struct prefix *p, vrf_id_t vrf_id) { - struct listnode *node; - struct connected *c; - struct zebra_vrf *zvrf = vrf_info_get (vrf_id); - - p->u.prefix4.s_addr = 0; - p->family = AF_INET; - p->prefixlen = 32; - - if (zvrf->rid_user_assigned.u.prefix4.s_addr) - p->u.prefix4.s_addr = zvrf->rid_user_assigned.u.prefix4.s_addr; - else if (!list_isempty (zvrf->rid_lo_sorted_list)) - { - node = listtail (zvrf->rid_lo_sorted_list); - c = listgetdata (node); - p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; - } - else if (!list_isempty (zvrf->rid_all_sorted_list)) - { - node = listtail (zvrf->rid_all_sorted_list); - c = listgetdata (node); - p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; - } + struct listnode *node; + struct connected *c; + struct zebra_vrf *zvrf = vrf_info_get(vrf_id); + + p->u.prefix4.s_addr = 0; + p->family = AF_INET; + p->prefixlen = 32; + + if (zvrf->rid_user_assigned.u.prefix4.s_addr) + p->u.prefix4.s_addr = zvrf->rid_user_assigned.u.prefix4.s_addr; + else if (!list_isempty(zvrf->rid_lo_sorted_list)) { + node = listtail(zvrf->rid_lo_sorted_list); + c = listgetdata(node); + p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; + } else if (!list_isempty(zvrf->rid_all_sorted_list)) { + node = listtail(zvrf->rid_all_sorted_list); + c = listgetdata(node); + p->u.prefix4.s_addr = c->address->u.prefix4.s_addr; + } } -static void -router_id_set (struct prefix *p, vrf_id_t vrf_id) +static void router_id_set(struct prefix *p, vrf_id_t vrf_id) { - struct prefix p2; - struct listnode *node; - struct zserv *client; - struct zebra_vrf *zvrf; - - if (p->u.prefix4.s_addr == 0) /* unset */ - { - zvrf = vrf_info_lookup (vrf_id); - if (! zvrf) - return; - } - else /* set */ - zvrf = vrf_info_get (vrf_id); - - zvrf->rid_user_assigned.u.prefix4.s_addr = p->u.prefix4.s_addr; - - router_id_get (&p2, vrf_id); - - for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client)) - zsend_router_id_update (client, &p2, vrf_id); + struct prefix p2; + struct listnode *node; + struct zserv *client; + struct zebra_vrf *zvrf; + + if (p->u.prefix4.s_addr == 0) /* unset */ + { + zvrf = vrf_info_lookup(vrf_id); + if (!zvrf) + return; + } else /* set */ + zvrf = vrf_info_get(vrf_id); + + zvrf->rid_user_assigned.u.prefix4.s_addr = p->u.prefix4.s_addr; + + router_id_get(&p2, vrf_id); + + for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) + zsend_router_id_update(client, &p2, vrf_id); } -void -router_id_add_address (struct connected *ifc) +void router_id_add_address(struct connected *ifc) { - struct list *l = NULL; - struct listnode *node; - struct prefix before; - struct prefix after; - struct zserv *client; - struct zebra_vrf *zvrf = vrf_info_get (ifc->ifp->vrf_id); - - if (router_id_bad_address (ifc)) - return; - - router_id_get (&before, zvrf_id (zvrf)); - - if (!strncmp (ifc->ifp->name, "lo", 2) - || !strncmp (ifc->ifp->name, "dummy", 5)) - l = zvrf->rid_lo_sorted_list; - else - l = zvrf->rid_all_sorted_list; - - if (!router_id_find_node (l, ifc)) - listnode_add_sort (l, ifc); - - router_id_get (&after, zvrf_id (zvrf)); - - if (prefix_same (&before, &after)) - return; - - for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client)) - zsend_router_id_update (client, &after, zvrf_id (zvrf)); + struct list *l = NULL; + struct listnode *node; + struct prefix before; + struct prefix after; + struct zserv *client; + struct zebra_vrf *zvrf = vrf_info_get(ifc->ifp->vrf_id); + + if (router_id_bad_address(ifc)) + return; + + router_id_get(&before, zvrf_id(zvrf)); + + if (!strncmp(ifc->ifp->name, "lo", 2) + || !strncmp(ifc->ifp->name, "dummy", 5)) + l = zvrf->rid_lo_sorted_list; + else + l = zvrf->rid_all_sorted_list; + + if (!router_id_find_node(l, ifc)) + listnode_add_sort(l, ifc); + + router_id_get(&after, zvrf_id(zvrf)); + + if (prefix_same(&before, &after)) + return; + + for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) + zsend_router_id_update(client, &after, zvrf_id(zvrf)); } -void -router_id_del_address (struct connected *ifc) +void router_id_del_address(struct connected *ifc) { - struct connected *c; - struct list *l; - struct prefix after; - struct prefix before; - struct listnode *node; - struct zserv *client; - struct zebra_vrf *zvrf = vrf_info_get (ifc->ifp->vrf_id); + struct connected *c; + struct list *l; + struct prefix after; + struct prefix before; + struct listnode *node; + struct zserv *client; + struct zebra_vrf *zvrf = vrf_info_get(ifc->ifp->vrf_id); - if (router_id_bad_address (ifc)) - return; + if (router_id_bad_address(ifc)) + return; - router_id_get (&before, zvrf_id (zvrf)); + router_id_get(&before, zvrf_id(zvrf)); - if (!strncmp (ifc->ifp->name, "lo", 2) - || !strncmp (ifc->ifp->name, "dummy", 5)) - l = zvrf->rid_lo_sorted_list; - else - l = zvrf->rid_all_sorted_list; + if (!strncmp(ifc->ifp->name, "lo", 2) + || !strncmp(ifc->ifp->name, "dummy", 5)) + l = zvrf->rid_lo_sorted_list; + else + l = zvrf->rid_all_sorted_list; - if ((c = router_id_find_node (l, ifc))) - listnode_delete (l, c); + if ((c = router_id_find_node(l, ifc))) + listnode_delete(l, c); - router_id_get (&after, zvrf_id (zvrf)); + router_id_get(&after, zvrf_id(zvrf)); - if (prefix_same (&before, &after)) - return; + if (prefix_same(&before, &after)) + return; - for (ALL_LIST_ELEMENTS_RO (zebrad.client_list, node, client)) - zsend_router_id_update (client, &after, zvrf_id (zvrf)); + for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) + zsend_router_id_update(client, &after, zvrf_id(zvrf)); } -void -router_id_write (struct vty *vty) +void router_id_write(struct vty *vty) { - struct vrf *vrf; - struct zebra_vrf *zvrf; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if ((zvrf = vrf->info) != NULL) - if (zvrf->rid_user_assigned.u.prefix4.s_addr) - { - if (zvrf_id (zvrf) == VRF_DEFAULT) - vty_out (vty, "router-id %s\n", - inet_ntoa(zvrf->rid_user_assigned.u.prefix4)); - else - vty_out (vty, "router-id %s vrf %s\n", - inet_ntoa (zvrf->rid_user_assigned.u.prefix4), - zvrf_name(zvrf)); - } + struct vrf *vrf; + struct zebra_vrf *zvrf; + + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) + if (zvrf->rid_user_assigned.u.prefix4.s_addr) { + if (zvrf_id(zvrf) == VRF_DEFAULT) + vty_out(vty, "router-id %s\n", + inet_ntoa(zvrf->rid_user_assigned.u + .prefix4)); + else + vty_out(vty, "router-id %s vrf %s\n", + inet_ntoa(zvrf->rid_user_assigned.u + .prefix4), + zvrf_name(zvrf)); + } } DEFUN (router_id, @@ -218,25 +209,25 @@ DEFUN (router_id, "IP address to use for router-id\n" VRF_CMD_HELP_STR) { - int idx_ipv4 = 1; - int idx_name = 3; + int idx_ipv4 = 1; + int idx_name = 3; - struct prefix rid; - vrf_id_t vrf_id = VRF_DEFAULT; + struct prefix rid; + vrf_id_t vrf_id = VRF_DEFAULT; - rid.u.prefix4.s_addr = inet_addr (argv[idx_ipv4]->arg); - if (!rid.u.prefix4.s_addr) - return CMD_WARNING_CONFIG_FAILED; + rid.u.prefix4.s_addr = inet_addr(argv[idx_ipv4]->arg); + if (!rid.u.prefix4.s_addr) + return CMD_WARNING_CONFIG_FAILED; - rid.prefixlen = 32; - rid.family = AF_INET; + rid.prefixlen = 32; + rid.family = AF_INET; - if (argc > 2) - VRF_GET_ID (vrf_id, argv[idx_name]->arg); + if (argc > 2) + VRF_GET_ID(vrf_id, argv[idx_name]->arg); - router_id_set (&rid, vrf_id); + router_id_set(&rid, vrf_id); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_router_id, @@ -247,54 +238,52 @@ DEFUN (no_router_id, "IP address to use for router-id\n" VRF_CMD_HELP_STR) { - int idx_name = 4; + int idx_name = 4; - struct prefix rid; - vrf_id_t vrf_id = VRF_DEFAULT; + struct prefix rid; + vrf_id_t vrf_id = VRF_DEFAULT; - rid.u.prefix4.s_addr = 0; - rid.prefixlen = 0; - rid.family = AF_INET; + rid.u.prefix4.s_addr = 0; + rid.prefixlen = 0; + rid.family = AF_INET; - if (argc > 3) - VRF_GET_ID (vrf_id, argv[idx_name]->arg); + if (argc > 3) + VRF_GET_ID(vrf_id, argv[idx_name]->arg); - router_id_set (&rid, vrf_id); + router_id_set(&rid, vrf_id); - return CMD_SUCCESS; + return CMD_SUCCESS; } - -static int -router_id_cmp (void *a, void *b) +static int router_id_cmp(void *a, void *b) { - const struct connected *ifa = (const struct connected *)a; - const struct connected *ifb = (const struct connected *)b; + const struct connected *ifa = (const struct connected *)a; + const struct connected *ifb = (const struct connected *)b; - return IPV4_ADDR_CMP(&ifa->address->u.prefix4.s_addr,&ifb->address->u.prefix4.s_addr); + return IPV4_ADDR_CMP(&ifa->address->u.prefix4.s_addr, + &ifb->address->u.prefix4.s_addr); } -void -router_id_cmd_init (void) +void router_id_cmd_init(void) { - install_element (CONFIG_NODE, &router_id_cmd); - install_element (CONFIG_NODE, &no_router_id_cmd); + install_element(CONFIG_NODE, &router_id_cmd); + install_element(CONFIG_NODE, &no_router_id_cmd); } -void -router_id_init (struct zebra_vrf *zvrf) +void router_id_init(struct zebra_vrf *zvrf) { - zvrf->rid_all_sorted_list = &zvrf->_rid_all_sorted_list; - zvrf->rid_lo_sorted_list = &zvrf->_rid_lo_sorted_list; + zvrf->rid_all_sorted_list = &zvrf->_rid_all_sorted_list; + zvrf->rid_lo_sorted_list = &zvrf->_rid_lo_sorted_list; - memset (zvrf->rid_all_sorted_list, 0, sizeof (zvrf->_rid_all_sorted_list)); - memset (zvrf->rid_lo_sorted_list, 0, sizeof (zvrf->_rid_lo_sorted_list)); - memset (&zvrf->rid_user_assigned, 0, sizeof (zvrf->rid_user_assigned)); + memset(zvrf->rid_all_sorted_list, 0, + sizeof(zvrf->_rid_all_sorted_list)); + memset(zvrf->rid_lo_sorted_list, 0, sizeof(zvrf->_rid_lo_sorted_list)); + memset(&zvrf->rid_user_assigned, 0, sizeof(zvrf->rid_user_assigned)); - zvrf->rid_all_sorted_list->cmp = router_id_cmp; - zvrf->rid_lo_sorted_list->cmp = router_id_cmp; + zvrf->rid_all_sorted_list->cmp = router_id_cmp; + zvrf->rid_lo_sorted_list->cmp = router_id_cmp; - zvrf->rid_user_assigned.family = AF_INET; - zvrf->rid_user_assigned.prefixlen = 32; + zvrf->rid_user_assigned.family = AF_INET; + zvrf->rid_user_assigned.prefixlen = 32; } diff --git a/zebra/rt.h b/zebra/rt.h index 90654fb3e..81dffdf44 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -30,31 +30,32 @@ #include "zebra/zebra_ns.h" #include "zebra/zebra_mpls.h" -extern int kernel_route_rib (struct prefix *, struct prefix *, - struct route_entry *, struct route_entry *); - -extern int kernel_address_add_ipv4 (struct interface *, struct connected *); -extern int kernel_address_delete_ipv4 (struct interface *, struct connected *); -extern int kernel_neigh_update (int, int, uint32_t, char *, int); - -extern int kernel_add_lsp (zebra_lsp_t *); -extern int kernel_upd_lsp (zebra_lsp_t *); -extern int kernel_del_lsp (zebra_lsp_t *); -extern int mpls_kernel_init (void); - -extern int kernel_get_ipmr_sg_stats (void *mroute); -extern int kernel_add_vtep (vni_t vni, struct interface *ifp, - struct in_addr *vtep_ip); -extern int kernel_del_vtep (vni_t vni, struct interface *ifp, - struct in_addr *vtep_ip); -extern int kernel_add_mac (struct interface *ifp, vlanid_t vid, - struct ethaddr *mac, struct in_addr vtep_ip, - u_char sticky); -extern int kernel_del_mac (struct interface *ifp, vlanid_t vid, - struct ethaddr *mac, struct in_addr vtep_ip, int local); - -extern int kernel_add_neigh (struct interface *ifp, struct ipaddr *ip, - struct ethaddr *mac); -extern int kernel_del_neigh (struct interface *ifp, struct ipaddr *ip); +extern int kernel_route_rib(struct prefix *, struct prefix *, + struct route_entry *, struct route_entry *); + +extern int kernel_address_add_ipv4(struct interface *, struct connected *); +extern int kernel_address_delete_ipv4(struct interface *, struct connected *); +extern int kernel_neigh_update(int, int, uint32_t, char *, int); + +extern int kernel_add_lsp(zebra_lsp_t *); +extern int kernel_upd_lsp(zebra_lsp_t *); +extern int kernel_del_lsp(zebra_lsp_t *); +extern int mpls_kernel_init(void); + +extern int kernel_get_ipmr_sg_stats(void *mroute); +extern int kernel_add_vtep(vni_t vni, struct interface *ifp, + struct in_addr *vtep_ip); +extern int kernel_del_vtep(vni_t vni, struct interface *ifp, + struct in_addr *vtep_ip); +extern int kernel_add_mac(struct interface *ifp, vlanid_t vid, + struct ethaddr *mac, struct in_addr vtep_ip, + u_char sticky); +extern int kernel_del_mac(struct interface *ifp, vlanid_t vid, + struct ethaddr *mac, struct in_addr vtep_ip, + int local); + +extern int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip, + struct ethaddr *mac); +extern int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip); #endif /* _ZEBRA_RT_H */ diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index e017eb78e..c02774ca6 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -119,11 +119,10 @@ static vlanid_t filter_vlan = 0; -struct gw_family_t -{ - u_int16_t filler; - u_int16_t family; - union g_addr gate; +struct gw_family_t { + u_int16_t filler; + u_int16_t family; + union g_addr gate; }; char ipv4_ll_buf[16] = "169.254.0.1"; @@ -135,592 +134,582 @@ struct in_addr ipv4_ll; * correct value one time instead for every * install/remove of a 5549 type route */ -void -rt_netlink_init (void) +void rt_netlink_init(void) { - inet_pton (AF_INET, ipv4_ll_buf, &ipv4_ll); + inet_pton(AF_INET, ipv4_ll_buf, &ipv4_ll); } static inline int is_selfroute(int proto) { - if ((proto == RTPROT_BGP) || (proto == RTPROT_OSPF) || - (proto == RTPROT_STATIC) || (proto == RTPROT_ZEBRA) || - (proto == RTPROT_ISIS) || (proto == RTPROT_RIPNG) || - (proto == RTPROT_NHRP) || (proto == RTPROT_EIGRP) || - (proto == RTPROT_LDP) || (proto == RTPROT_BABEL)) { - return 1; - } - - return 0; + if ((proto == RTPROT_BGP) || (proto == RTPROT_OSPF) + || (proto == RTPROT_STATIC) || (proto == RTPROT_ZEBRA) + || (proto == RTPROT_ISIS) || (proto == RTPROT_RIPNG) + || (proto == RTPROT_NHRP) || (proto == RTPROT_EIGRP) + || (proto == RTPROT_LDP) || (proto == RTPROT_BABEL)) { + return 1; + } + + return 0; } static inline int get_rt_proto(int proto) { - switch (proto) { - case ZEBRA_ROUTE_BABEL: - proto = RTPROT_BABEL; - break; - case ZEBRA_ROUTE_BGP: - proto = RTPROT_BGP; - break; - case ZEBRA_ROUTE_OSPF: - case ZEBRA_ROUTE_OSPF6: - proto = RTPROT_OSPF; - break; - case ZEBRA_ROUTE_STATIC: - proto = RTPROT_STATIC; - break; - case ZEBRA_ROUTE_ISIS: - proto = RTPROT_ISIS; - break; - case ZEBRA_ROUTE_RIP: - proto = RTPROT_RIP; - break; - case ZEBRA_ROUTE_RIPNG: - proto = RTPROT_RIPNG; - break; - case ZEBRA_ROUTE_NHRP: - proto = RTPROT_NHRP; - break; - case ZEBRA_ROUTE_EIGRP: - proto = RTPROT_EIGRP; - break; - case ZEBRA_ROUTE_LDP: - proto = RTPROT_LDP; - break; - default: - proto = RTPROT_ZEBRA; - break; - } - - return proto; + switch (proto) { + case ZEBRA_ROUTE_BABEL: + proto = RTPROT_BABEL; + break; + case ZEBRA_ROUTE_BGP: + proto = RTPROT_BGP; + break; + case ZEBRA_ROUTE_OSPF: + case ZEBRA_ROUTE_OSPF6: + proto = RTPROT_OSPF; + break; + case ZEBRA_ROUTE_STATIC: + proto = RTPROT_STATIC; + break; + case ZEBRA_ROUTE_ISIS: + proto = RTPROT_ISIS; + break; + case ZEBRA_ROUTE_RIP: + proto = RTPROT_RIP; + break; + case ZEBRA_ROUTE_RIPNG: + proto = RTPROT_RIPNG; + break; + case ZEBRA_ROUTE_NHRP: + proto = RTPROT_NHRP; + break; + case ZEBRA_ROUTE_EIGRP: + proto = RTPROT_EIGRP; + break; + case ZEBRA_ROUTE_LDP: + proto = RTPROT_LDP; + break; + default: + proto = RTPROT_ZEBRA; + break; + } + + return proto; } /* Pending: create an efficient table_id (in a tree/hash) based lookup) */ -static vrf_id_t -vrf_lookup_by_table (u_int32_t table_id) +static vrf_id_t vrf_lookup_by_table(u_int32_t table_id) { - struct vrf *vrf; - struct zebra_vrf *zvrf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - { - if ((zvrf = vrf->info) == NULL || - (zvrf->table_id != table_id)) - continue; + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + { + if ((zvrf = vrf->info) == NULL || (zvrf->table_id != table_id)) + continue; - return zvrf_id (zvrf); - } + return zvrf_id(zvrf); + } - return VRF_DEFAULT; + return VRF_DEFAULT; } /* Looking up routing table by netlink interface. */ -static int -netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, + struct nlmsghdr *h, ns_id_t ns_id, + int startup) { - int len; - struct rtmsg *rtm; - struct rtattr *tb[RTA_MAX + 1]; - u_char flags = 0; - struct prefix p; - struct prefix_ipv6 src_p; - vrf_id_t vrf_id = VRF_DEFAULT; - - char anyaddr[16] = { 0 }; - - int index = 0; - int table; - int metric = 0; - u_int32_t mtu = 0; - - void *dest = NULL; - void *gate = NULL; - void *prefsrc = NULL; /* IPv4 preferred source host address */ - void *src = NULL; /* IPv6 srcdest source prefix */ - - rtm = NLMSG_DATA (h); - - if (startup && h->nlmsg_type != RTM_NEWROUTE) - return 0; - if (startup && rtm->rtm_type != RTN_UNICAST) - return 0; - - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); - if (len < 0) - return -1; - - memset (tb, 0, sizeof tb); - netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len); - - if (rtm->rtm_flags & RTM_F_CLONED) - return 0; - if (rtm->rtm_protocol == RTPROT_REDIRECT) - return 0; - if (rtm->rtm_protocol == RTPROT_KERNEL) - return 0; - - if (!startup && - is_selfroute (rtm->rtm_protocol) && - h->nlmsg_type == RTM_NEWROUTE) - return 0; - - /* We don't care about change notifications for the MPLS table. */ - /* TODO: Revisit this. */ - if (rtm->rtm_family == AF_MPLS) - return 0; - - /* Table corresponding to route. */ - if (tb[RTA_TABLE]) - table = *(int *) RTA_DATA (tb[RTA_TABLE]); - else - table = rtm->rtm_table; - - /* Map to VRF */ - vrf_id = vrf_lookup_by_table(table); - if (vrf_id == VRF_DEFAULT) - { - if (!is_zebra_valid_kernel_table(table) && - !is_zebra_main_routing_table(table)) - return 0; - } - - /* Route which inserted by Zebra. */ - if (is_selfroute(rtm->rtm_protocol)) - flags |= ZEBRA_FLAG_SELFROUTE; - - if (tb[RTA_OIF]) - index = *(int *) RTA_DATA (tb[RTA_OIF]); - - if (tb[RTA_DST]) - dest = RTA_DATA (tb[RTA_DST]); - else - dest = anyaddr; - - if (tb[RTA_SRC]) - src = RTA_DATA (tb[RTA_SRC]); - else - src = anyaddr; - - if (tb[RTA_PREFSRC]) - prefsrc = RTA_DATA (tb[RTA_PREFSRC]); - - if (tb[RTA_GATEWAY]) - gate = RTA_DATA (tb[RTA_GATEWAY]); - - if (h->nlmsg_type == RTM_NEWROUTE) - { - if (tb[RTA_PRIORITY]) - metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]); - - if (tb[RTA_METRICS]) - { - struct rtattr *mxrta[RTAX_MAX+1]; - - memset (mxrta, 0, sizeof mxrta); - netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]), - RTA_PAYLOAD(tb[RTA_METRICS])); - - if (mxrta[RTAX_MTU]) - mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]); - } - } - - if (rtm->rtm_family == AF_INET) - { - p.family = AF_INET; - memcpy (&p.u.prefix4, dest, 4); - p.prefixlen = rtm->rtm_dst_len; - - src_p.prefixlen = 0; // Forces debug below to not display anything - } - else if (rtm->rtm_family == AF_INET6) - { - p.family = AF_INET6; - memcpy (&p.u.prefix6, dest, 16); - p.prefixlen = rtm->rtm_dst_len; - - src_p.family = AF_INET6; - memcpy (&src_p.prefix, src, 16); - src_p.prefixlen = rtm->rtm_src_len; - } - - if (rtm->rtm_src_len != 0) - { - char buf[PREFIX_STRLEN]; - zlog_warn ("unsupported IPv[4|6] sourcedest route (dest %s vrf %u)", - prefix2str (&p, buf, sizeof(buf)), vrf_id); - return 0; - } - - if (IS_ZEBRA_DEBUG_KERNEL) - { - char buf[PREFIX_STRLEN]; - char buf2[PREFIX_STRLEN]; - zlog_debug ("%s %s%s%s vrf %u", - nl_msg_type_to_str (h->nlmsg_type), - prefix2str (&p, buf, sizeof(buf)), - src_p.prefixlen ? " from " : "", - src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2)) : "", - vrf_id); - } - - afi_t afi = AFI_IP; - if (rtm->rtm_family == AF_INET6) - afi = AFI_IP6; - - if (h->nlmsg_type == RTM_NEWROUTE) - { - if (!tb[RTA_MULTIPATH]) - rib_add (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, flags, &p, NULL, gate, prefsrc, index, - table, metric, mtu, 0); - else - { - /* This is a multipath route */ - - struct route_entry *re; - struct rtnexthop *rtnh = - (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]); - - len = RTA_PAYLOAD (tb[RTA_MULTIPATH]); - - re = XCALLOC (MTYPE_RE, sizeof (struct route_entry)); - re->type = ZEBRA_ROUTE_KERNEL; - re->distance = 0; - re->flags = flags; - re->metric = metric; - re->mtu = mtu; - re->vrf_id = vrf_id; - re->table = table; - re->nexthop_num = 0; - re->uptime = time (NULL); - - for (;;) - { - if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len) - break; - - index = rtnh->rtnh_ifindex; - gate = 0; - if (rtnh->rtnh_len > sizeof (*rtnh)) - { - memset (tb, 0, sizeof (tb)); - netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh), - rtnh->rtnh_len - sizeof (*rtnh)); - if (tb[RTA_GATEWAY]) - gate = RTA_DATA (tb[RTA_GATEWAY]); - } - - if (gate) - { - if (rtm->rtm_family == AF_INET) - { - if (index) - route_entry_nexthop_ipv4_ifindex_add (re, gate, prefsrc, index); - else - route_entry_nexthop_ipv4_add (re, gate, prefsrc); - } - else if (rtm->rtm_family == AF_INET6) - { - if (index) - route_entry_nexthop_ipv6_ifindex_add (re, gate, index); - else - route_entry_nexthop_ipv6_add (re,gate); - } - } - else - route_entry_nexthop_ifindex_add (re, index); - - len -= NLMSG_ALIGN(rtnh->rtnh_len); - rtnh = RTNH_NEXT(rtnh); - } - - zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, - re->nexthop_num); - if (re->nexthop_num == 0) - XFREE (MTYPE_RE, re); - else - rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, NULL, re); - } - } - else - { - if (!tb[RTA_MULTIPATH]) - rib_delete (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags, - &p, NULL, gate, index, table); - else - { - struct rtnexthop *rtnh = - (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]); - - len = RTA_PAYLOAD (tb[RTA_MULTIPATH]); - - for (;;) - { - if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len) - break; - - gate = NULL; - if (rtnh->rtnh_len > sizeof (*rtnh)) - { - memset (tb, 0, sizeof (tb)); - netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh), - rtnh->rtnh_len - sizeof (*rtnh)); - if (tb[RTA_GATEWAY]) - gate = RTA_DATA (tb[RTA_GATEWAY]); - } - - if (gate) - rib_delete (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags, - &p, NULL, gate, index, table); - - len -= NLMSG_ALIGN(rtnh->rtnh_len); - rtnh = RTNH_NEXT(rtnh); - } - } - } - - return 0; + int len; + struct rtmsg *rtm; + struct rtattr *tb[RTA_MAX + 1]; + u_char flags = 0; + struct prefix p; + struct prefix_ipv6 src_p; + vrf_id_t vrf_id = VRF_DEFAULT; + + char anyaddr[16] = {0}; + + int index = 0; + int table; + int metric = 0; + u_int32_t mtu = 0; + + void *dest = NULL; + void *gate = NULL; + void *prefsrc = NULL; /* IPv4 preferred source host address */ + void *src = NULL; /* IPv6 srcdest source prefix */ + + rtm = NLMSG_DATA(h); + + if (startup && h->nlmsg_type != RTM_NEWROUTE) + return 0; + if (startup && rtm->rtm_type != RTN_UNICAST) + return 0; + + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg)); + if (len < 0) + return -1; + + memset(tb, 0, sizeof tb); + netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len); + + if (rtm->rtm_flags & RTM_F_CLONED) + return 0; + if (rtm->rtm_protocol == RTPROT_REDIRECT) + return 0; + if (rtm->rtm_protocol == RTPROT_KERNEL) + return 0; + + if (!startup && is_selfroute(rtm->rtm_protocol) + && h->nlmsg_type == RTM_NEWROUTE) + return 0; + + /* We don't care about change notifications for the MPLS table. */ + /* TODO: Revisit this. */ + if (rtm->rtm_family == AF_MPLS) + return 0; + + /* Table corresponding to route. */ + if (tb[RTA_TABLE]) + table = *(int *)RTA_DATA(tb[RTA_TABLE]); + else + table = rtm->rtm_table; + + /* Map to VRF */ + vrf_id = vrf_lookup_by_table(table); + if (vrf_id == VRF_DEFAULT) { + if (!is_zebra_valid_kernel_table(table) + && !is_zebra_main_routing_table(table)) + return 0; + } + + /* Route which inserted by Zebra. */ + if (is_selfroute(rtm->rtm_protocol)) + flags |= ZEBRA_FLAG_SELFROUTE; + + if (tb[RTA_OIF]) + index = *(int *)RTA_DATA(tb[RTA_OIF]); + + if (tb[RTA_DST]) + dest = RTA_DATA(tb[RTA_DST]); + else + dest = anyaddr; + + if (tb[RTA_SRC]) + src = RTA_DATA(tb[RTA_SRC]); + else + src = anyaddr; + + if (tb[RTA_PREFSRC]) + prefsrc = RTA_DATA(tb[RTA_PREFSRC]); + + if (tb[RTA_GATEWAY]) + gate = RTA_DATA(tb[RTA_GATEWAY]); + + if (h->nlmsg_type == RTM_NEWROUTE) { + if (tb[RTA_PRIORITY]) + metric = *(int *)RTA_DATA(tb[RTA_PRIORITY]); + + if (tb[RTA_METRICS]) { + struct rtattr *mxrta[RTAX_MAX + 1]; + + memset(mxrta, 0, sizeof mxrta); + netlink_parse_rtattr(mxrta, RTAX_MAX, + RTA_DATA(tb[RTA_METRICS]), + RTA_PAYLOAD(tb[RTA_METRICS])); + + if (mxrta[RTAX_MTU]) + mtu = *(u_int32_t *)RTA_DATA(mxrta[RTAX_MTU]); + } + } + + if (rtm->rtm_family == AF_INET) { + p.family = AF_INET; + memcpy(&p.u.prefix4, dest, 4); + p.prefixlen = rtm->rtm_dst_len; + + src_p.prefixlen = + 0; // Forces debug below to not display anything + } else if (rtm->rtm_family == AF_INET6) { + p.family = AF_INET6; + memcpy(&p.u.prefix6, dest, 16); + p.prefixlen = rtm->rtm_dst_len; + + src_p.family = AF_INET6; + memcpy(&src_p.prefix, src, 16); + src_p.prefixlen = rtm->rtm_src_len; + } + + if (rtm->rtm_src_len != 0) { + char buf[PREFIX_STRLEN]; + zlog_warn( + "unsupported IPv[4|6] sourcedest route (dest %s vrf %u)", + prefix2str(&p, buf, sizeof(buf)), vrf_id); + return 0; + } + + if (IS_ZEBRA_DEBUG_KERNEL) { + char buf[PREFIX_STRLEN]; + char buf2[PREFIX_STRLEN]; + zlog_debug( + "%s %s%s%s vrf %u", nl_msg_type_to_str(h->nlmsg_type), + prefix2str(&p, buf, sizeof(buf)), + src_p.prefixlen ? " from " : "", + src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2)) + : "", + vrf_id); + } + + afi_t afi = AFI_IP; + if (rtm->rtm_family == AF_INET6) + afi = AFI_IP6; + + if (h->nlmsg_type == RTM_NEWROUTE) { + if (!tb[RTA_MULTIPATH]) + rib_add(afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, + 0, flags, &p, NULL, gate, prefsrc, index, table, + metric, mtu, 0); + else { + /* This is a multipath route */ + + struct route_entry *re; + struct rtnexthop *rtnh = + (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]); + + len = RTA_PAYLOAD(tb[RTA_MULTIPATH]); + + re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); + re->type = ZEBRA_ROUTE_KERNEL; + re->distance = 0; + re->flags = flags; + re->metric = metric; + re->mtu = mtu; + re->vrf_id = vrf_id; + re->table = table; + re->nexthop_num = 0; + re->uptime = time(NULL); + + for (;;) { + if (len < (int)sizeof(*rtnh) + || rtnh->rtnh_len > len) + break; + + index = rtnh->rtnh_ifindex; + gate = 0; + if (rtnh->rtnh_len > sizeof(*rtnh)) { + memset(tb, 0, sizeof(tb)); + netlink_parse_rtattr( + tb, RTA_MAX, RTNH_DATA(rtnh), + rtnh->rtnh_len - sizeof(*rtnh)); + if (tb[RTA_GATEWAY]) + gate = RTA_DATA( + tb[RTA_GATEWAY]); + } + + if (gate) { + if (rtm->rtm_family == AF_INET) { + if (index) + route_entry_nexthop_ipv4_ifindex_add( + re, gate, + prefsrc, index); + else + route_entry_nexthop_ipv4_add( + re, gate, + prefsrc); + } else if (rtm->rtm_family + == AF_INET6) { + if (index) + route_entry_nexthop_ipv6_ifindex_add( + re, gate, + index); + else + route_entry_nexthop_ipv6_add( + re, gate); + } + } else + route_entry_nexthop_ifindex_add(re, + index); + + len -= NLMSG_ALIGN(rtnh->rtnh_len); + rtnh = RTNH_NEXT(rtnh); + } + + zserv_nexthop_num_warn(__func__, + (const struct prefix *)&p, + re->nexthop_num); + if (re->nexthop_num == 0) + XFREE(MTYPE_RE, re); + else + rib_add_multipath(AFI_IP, SAFI_UNICAST, &p, + NULL, re); + } + } else { + if (!tb[RTA_MULTIPATH]) + rib_delete(afi, SAFI_UNICAST, vrf_id, + ZEBRA_ROUTE_KERNEL, 0, flags, &p, NULL, gate, + index, table); + else { + struct rtnexthop *rtnh = + (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]); + + len = RTA_PAYLOAD(tb[RTA_MULTIPATH]); + + for (;;) { + if (len < (int)sizeof(*rtnh) + || rtnh->rtnh_len > len) + break; + + gate = NULL; + if (rtnh->rtnh_len > sizeof(*rtnh)) { + memset(tb, 0, sizeof(tb)); + netlink_parse_rtattr( + tb, RTA_MAX, RTNH_DATA(rtnh), + rtnh->rtnh_len - sizeof(*rtnh)); + if (tb[RTA_GATEWAY]) + gate = RTA_DATA( + tb[RTA_GATEWAY]); + } + + if (gate) + rib_delete(afi, SAFI_UNICAST, vrf_id, + ZEBRA_ROUTE_KERNEL, 0, flags, + &p, NULL, gate, index, + table); + + len -= NLMSG_ALIGN(rtnh->rtnh_len); + rtnh = RTNH_NEXT(rtnh); + } + } + } + + return 0; } static struct mcast_route_data *mroute = NULL; -static int -netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +static int netlink_route_change_read_multicast(struct sockaddr_nl *snl, + struct nlmsghdr *h, + ns_id_t ns_id, int startup) { - int len; - struct rtmsg *rtm; - struct rtattr *tb[RTA_MAX + 1]; - struct mcast_route_data *m; - struct mcast_route_data mr; - int iif = 0; - int count; - int oif[256]; - int oif_count = 0; - char sbuf[40]; - char gbuf[40]; - char oif_list[256] = "\0"; - vrf_id_t vrf = ns_id; - - if (mroute) - m = mroute; - else - { - memset (&mr, 0, sizeof (mr)); - m = &mr; - } - - rtm = NLMSG_DATA (h); - - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); - - memset (tb, 0, sizeof tb); - netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len); - - if (tb[RTA_IIF]) - iif = *(int *)RTA_DATA (tb[RTA_IIF]); - - if (tb[RTA_SRC]) - m->sg.src = *(struct in_addr *)RTA_DATA (tb[RTA_SRC]); - - if (tb[RTA_DST]) - m->sg.grp = *(struct in_addr *)RTA_DATA (tb[RTA_DST]); - - if ((RTA_EXPIRES <= RTA_MAX) && tb[RTA_EXPIRES]) - m->lastused = *(unsigned long long *)RTA_DATA (tb[RTA_EXPIRES]); - - if (tb[RTA_MULTIPATH]) - { - struct rtnexthop *rtnh = - (struct rtnexthop *)RTA_DATA (tb[RTA_MULTIPATH]); - - len = RTA_PAYLOAD (tb[RTA_MULTIPATH]); - for (;;) - { - if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len) - break; - - oif[oif_count] = rtnh->rtnh_ifindex; - oif_count++; - - len -= NLMSG_ALIGN (rtnh->rtnh_len); - rtnh = RTNH_NEXT (rtnh); - } - } - - if (IS_ZEBRA_DEBUG_KERNEL) - { - struct interface *ifp; - strcpy (sbuf, inet_ntoa (m->sg.src)); - strcpy (gbuf, inet_ntoa (m->sg.grp)); - for (count = 0; count < oif_count; count++) - { - ifp = if_lookup_by_index (oif[count], vrf); - char temp[256]; + int len; + struct rtmsg *rtm; + struct rtattr *tb[RTA_MAX + 1]; + struct mcast_route_data *m; + struct mcast_route_data mr; + int iif = 0; + int count; + int oif[256]; + int oif_count = 0; + char sbuf[40]; + char gbuf[40]; + char oif_list[256] = "\0"; + vrf_id_t vrf = ns_id; + + if (mroute) + m = mroute; + else { + memset(&mr, 0, sizeof(mr)); + m = &mr; + } + + rtm = NLMSG_DATA(h); + + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg)); + + memset(tb, 0, sizeof tb); + netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len); - sprintf (temp, "%s ", ifp->name); - strcat (oif_list, temp); + if (tb[RTA_IIF]) + iif = *(int *)RTA_DATA(tb[RTA_IIF]); + + if (tb[RTA_SRC]) + m->sg.src = *(struct in_addr *)RTA_DATA(tb[RTA_SRC]); + + if (tb[RTA_DST]) + m->sg.grp = *(struct in_addr *)RTA_DATA(tb[RTA_DST]); + + if ((RTA_EXPIRES <= RTA_MAX) && tb[RTA_EXPIRES]) + m->lastused = *(unsigned long long *)RTA_DATA(tb[RTA_EXPIRES]); + + if (tb[RTA_MULTIPATH]) { + struct rtnexthop *rtnh = + (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]); + + len = RTA_PAYLOAD(tb[RTA_MULTIPATH]); + for (;;) { + if (len < (int)sizeof(*rtnh) || rtnh->rtnh_len > len) + break; + + oif[oif_count] = rtnh->rtnh_ifindex; + oif_count++; + + len -= NLMSG_ALIGN(rtnh->rtnh_len); + rtnh = RTNH_NEXT(rtnh); + } + } + + if (IS_ZEBRA_DEBUG_KERNEL) { + struct interface *ifp; + strcpy(sbuf, inet_ntoa(m->sg.src)); + strcpy(gbuf, inet_ntoa(m->sg.grp)); + for (count = 0; count < oif_count; count++) { + ifp = if_lookup_by_index(oif[count], vrf); + char temp[256]; + + sprintf(temp, "%s ", ifp->name); + strcat(oif_list, temp); + } + ifp = if_lookup_by_index(iif, vrf); + zlog_debug("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld", + nl_msg_type_to_str(h->nlmsg_type), sbuf, gbuf, + ifp->name, oif_list, m->lastused); } - ifp = if_lookup_by_index (iif, vrf); - zlog_debug ("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld", - nl_msg_type_to_str(h->nlmsg_type), sbuf, gbuf, ifp->name, oif_list, m->lastused); - } - return 0; + return 0; } -int -netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +int netlink_route_change(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup) { - int len; - vrf_id_t vrf_id = ns_id; - struct rtmsg *rtm; - - rtm = NLMSG_DATA (h); - - if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) - { - /* If this is not route add/delete message print warning. */ - zlog_warn ("Kernel message: %d vrf %u\n", h->nlmsg_type, vrf_id); - return 0; - } - - /* Connected route. */ - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s %s %s proto %s vrf %u", - nl_msg_type_to_str (h->nlmsg_type), - nl_family_to_str (rtm->rtm_family), - nl_rttype_to_str (rtm->rtm_type), - nl_rtproto_to_str (rtm->rtm_protocol), - vrf_id); - - /* We don't care about change notifications for the MPLS table. */ - /* TODO: Revisit this. */ - if (rtm->rtm_family == AF_MPLS) - return 0; - - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg)); - if (len < 0) - return -1; - - switch (rtm->rtm_type) - { - case RTN_UNICAST: - netlink_route_change_read_unicast (snl, h, ns_id, startup); - break; - case RTN_MULTICAST: - netlink_route_change_read_multicast (snl, h, ns_id, startup); - break; - default: - return 0; - break; - } - - return 0; + int len; + vrf_id_t vrf_id = ns_id; + struct rtmsg *rtm; + + rtm = NLMSG_DATA(h); + + if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)) { + /* If this is not route add/delete message print warning. */ + zlog_warn("Kernel message: %d vrf %u\n", h->nlmsg_type, vrf_id); + return 0; + } + + /* Connected route. */ + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s %s %s proto %s vrf %u", + nl_msg_type_to_str(h->nlmsg_type), + nl_family_to_str(rtm->rtm_family), + nl_rttype_to_str(rtm->rtm_type), + nl_rtproto_to_str(rtm->rtm_protocol), vrf_id); + + /* We don't care about change notifications for the MPLS table. */ + /* TODO: Revisit this. */ + if (rtm->rtm_family == AF_MPLS) + return 0; + + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg)); + if (len < 0) + return -1; + + switch (rtm->rtm_type) { + case RTN_UNICAST: + netlink_route_change_read_unicast(snl, h, ns_id, startup); + break; + case RTN_MULTICAST: + netlink_route_change_read_multicast(snl, h, ns_id, startup); + break; + default: + return 0; + break; + } + + return 0; } /* Request for specific route information from the kernel */ -static int -netlink_request_route (struct zebra_ns *zns, int family, int type) +static int netlink_request_route(struct zebra_ns *zns, int family, int type) { - struct - { - struct nlmsghdr n; - struct rtmsg rtm; - } req; - - /* Form the request, specifying filter (rtattr) if needed. */ - memset (&req, 0, sizeof (req)); - req.n.nlmsg_type = type; - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); - req.rtm.rtm_family = family; - - return netlink_request (&zns->netlink_cmd, &req.n); + struct { + struct nlmsghdr n; + struct rtmsg rtm; + } req; + + /* Form the request, specifying filter (rtattr) if needed. */ + memset(&req, 0, sizeof(req)); + req.n.nlmsg_type = type; + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + req.rtm.rtm_family = family; + + return netlink_request(&zns->netlink_cmd, &req.n); } /* Routing table read function using netlink interface. Only called bootstrap time. */ -int -netlink_route_read (struct zebra_ns *zns) +int netlink_route_read(struct zebra_ns *zns) { - int ret; - - /* Get IPv4 routing table. */ - ret = netlink_request_route (zns, AF_INET, RTM_GETROUTE); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_route_change_read_unicast, &zns->netlink_cmd, zns, 0, 1); - if (ret < 0) - return ret; - - /* Get IPv6 routing table. */ - ret = netlink_request_route (zns, AF_INET6, RTM_GETROUTE); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_route_change_read_unicast, &zns->netlink_cmd, zns, 0, 1); - if (ret < 0) - return ret; - - return 0; + int ret; + + /* Get IPv4 routing table. */ + ret = netlink_request_route(zns, AF_INET, RTM_GETROUTE); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_route_change_read_unicast, + &zns->netlink_cmd, zns, 0, 1); + if (ret < 0) + return ret; + + /* Get IPv6 routing table. */ + ret = netlink_request_route(zns, AF_INET6, RTM_GETROUTE); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_route_change_read_unicast, + &zns->netlink_cmd, zns, 0, 1); + if (ret < 0) + return ret; + + return 0; } -static void -_netlink_route_nl_add_gateway_info (u_char route_family, u_char gw_family, - struct nlmsghdr *nlmsg, - size_t req_size, int bytelen, - struct nexthop *nexthop) +static void _netlink_route_nl_add_gateway_info(u_char route_family, + u_char gw_family, + struct nlmsghdr *nlmsg, + size_t req_size, int bytelen, + struct nexthop *nexthop) { - if (route_family == AF_MPLS) - { - struct gw_family_t gw_fam; - - gw_fam.family = gw_family; - if (gw_family == AF_INET) - memcpy (&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen); - else - memcpy (&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen); - addattr_l (nlmsg, req_size, RTA_VIA, &gw_fam.family, bytelen+2); - } - else - { - if (gw_family == AF_INET) - addattr_l (nlmsg, req_size, RTA_GATEWAY, &nexthop->gate.ipv4, bytelen); - else - addattr_l (nlmsg, req_size, RTA_GATEWAY, &nexthop->gate.ipv6, bytelen); - } + if (route_family == AF_MPLS) { + struct gw_family_t gw_fam; + + gw_fam.family = gw_family; + if (gw_family == AF_INET) + memcpy(&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen); + else + memcpy(&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen); + addattr_l(nlmsg, req_size, RTA_VIA, &gw_fam.family, + bytelen + 2); + } else { + if (gw_family == AF_INET) + addattr_l(nlmsg, req_size, RTA_GATEWAY, + &nexthop->gate.ipv4, bytelen); + else + addattr_l(nlmsg, req_size, RTA_GATEWAY, + &nexthop->gate.ipv6, bytelen); + } } -static void -_netlink_route_rta_add_gateway_info (u_char route_family, u_char gw_family, - struct rtattr *rta, struct rtnexthop *rtnh, - size_t req_size, int bytelen, - struct nexthop *nexthop) +static void _netlink_route_rta_add_gateway_info(u_char route_family, + u_char gw_family, + struct rtattr *rta, + struct rtnexthop *rtnh, + size_t req_size, int bytelen, + struct nexthop *nexthop) { - if (route_family == AF_MPLS) - { - struct gw_family_t gw_fam; - - gw_fam.family = gw_family; - if (gw_family == AF_INET) - memcpy (&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen); - else - memcpy (&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen); - rta_addattr_l (rta, req_size, RTA_VIA, &gw_fam.family, bytelen+2); - rtnh->rtnh_len += RTA_LENGTH (bytelen + 2); - } - else - { - if (gw_family == AF_INET) - rta_addattr_l (rta, req_size, RTA_GATEWAY, &nexthop->gate.ipv4, bytelen); - else - rta_addattr_l (rta, req_size, RTA_GATEWAY, &nexthop->gate.ipv6, bytelen); - rtnh->rtnh_len += sizeof (struct rtattr) + bytelen; - } + if (route_family == AF_MPLS) { + struct gw_family_t gw_fam; + + gw_fam.family = gw_family; + if (gw_family == AF_INET) + memcpy(&gw_fam.gate.ipv4, &nexthop->gate.ipv4, bytelen); + else + memcpy(&gw_fam.gate.ipv6, &nexthop->gate.ipv6, bytelen); + rta_addattr_l(rta, req_size, RTA_VIA, &gw_fam.family, + bytelen + 2); + rtnh->rtnh_len += RTA_LENGTH(bytelen + 2); + } else { + if (gw_family == AF_INET) + rta_addattr_l(rta, req_size, RTA_GATEWAY, + &nexthop->gate.ipv4, bytelen); + else + rta_addattr_l(rta, req_size, RTA_GATEWAY, + &nexthop->gate.ipv6, bytelen); + rtnh->rtnh_len += sizeof(struct rtattr) + bytelen; + } } /* This function takes a nexthop as argument and adds @@ -734,194 +723,186 @@ _netlink_route_rta_add_gateway_info (u_char route_family, u_char gw_family, * @param nlmsg: nlmsghdr structure to fill in. * @param req_size: The size allocated for the message. */ -static void -_netlink_route_build_singlepath( - const char *routedesc, - int bytelen, - struct nexthop *nexthop, - struct nlmsghdr *nlmsg, - struct rtmsg *rtmsg, - size_t req_size, - int cmd) +static void _netlink_route_build_singlepath(const char *routedesc, int bytelen, + struct nexthop *nexthop, + struct nlmsghdr *nlmsg, + struct rtmsg *rtmsg, + size_t req_size, int cmd) { - struct nexthop_label *nh_label; - mpls_lse_t out_lse[MPLS_MAX_LABELS]; - char label_buf[100]; - - /* - * label_buf is *only* currently used within debugging. - * As such when we assign it we are guarding it inside - * a debug test. If you want to change this make sure - * you fix this assumption - */ - label_buf[0] = '\0'; - /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP - * (in the case of LER) - */ - nh_label = nexthop->nh_label; - if (rtmsg->rtm_family == AF_MPLS) - { - assert (nh_label); - assert (nh_label->num_labels == 1); - } - - if (nh_label && nh_label->num_labels) - { - int i, num_labels = 0; - u_int32_t bos; - char label_buf1[20]; - - for (i = 0; i < nh_label->num_labels; i++) - { - if (nh_label->label[i] != MPLS_IMP_NULL_LABEL) - { - bos = ((i == (nh_label->num_labels - 1)) ? 1 : 0); - out_lse[i] = mpls_lse_encode (nh_label->label[i], 0, 0, bos); - if (IS_ZEBRA_DEBUG_KERNEL) - { - if (!num_labels) - sprintf (label_buf, "label %d", nh_label->label[i]); - else - { - sprintf (label_buf1, "/%d", nh_label->label[i]); - strcat (label_buf, label_buf1); - } + struct nexthop_label *nh_label; + mpls_lse_t out_lse[MPLS_MAX_LABELS]; + char label_buf[100]; + + /* + * label_buf is *only* currently used within debugging. + * As such when we assign it we are guarding it inside + * a debug test. If you want to change this make sure + * you fix this assumption + */ + label_buf[0] = '\0'; + /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP + * (in the case of LER) + */ + nh_label = nexthop->nh_label; + if (rtmsg->rtm_family == AF_MPLS) { + assert(nh_label); + assert(nh_label->num_labels == 1); + } + + if (nh_label && nh_label->num_labels) { + int i, num_labels = 0; + u_int32_t bos; + char label_buf1[20]; + + for (i = 0; i < nh_label->num_labels; i++) { + if (nh_label->label[i] != MPLS_IMP_NULL_LABEL) { + bos = ((i == (nh_label->num_labels - 1)) ? 1 + : 0); + out_lse[i] = mpls_lse_encode(nh_label->label[i], + 0, 0, bos); + if (IS_ZEBRA_DEBUG_KERNEL) { + if (!num_labels) + sprintf(label_buf, "label %d", + nh_label->label[i]); + else { + sprintf(label_buf1, "/%d", + nh_label->label[i]); + strcat(label_buf, label_buf1); + } + } + num_labels++; + } + } + if (num_labels) { + if (rtmsg->rtm_family == AF_MPLS) + addattr_l(nlmsg, req_size, RTA_NEWDST, &out_lse, + num_labels * sizeof(mpls_lse_t)); + else { + struct rtattr *nest; + u_int16_t encap = LWTUNNEL_ENCAP_MPLS; + + addattr_l(nlmsg, req_size, RTA_ENCAP_TYPE, + &encap, sizeof(u_int16_t)); + nest = addattr_nest(nlmsg, req_size, RTA_ENCAP); + addattr_l(nlmsg, req_size, MPLS_IPTUNNEL_DST, + &out_lse, + num_labels * sizeof(mpls_lse_t)); + addattr_nest_end(nlmsg, nest); + } } - num_labels++; - } - } - if (num_labels) - { - if (rtmsg->rtm_family == AF_MPLS) - addattr_l (nlmsg, req_size, RTA_NEWDST, - &out_lse, num_labels * sizeof(mpls_lse_t)); - else - { - struct rtattr *nest; - u_int16_t encap = LWTUNNEL_ENCAP_MPLS; - - addattr_l(nlmsg, req_size, RTA_ENCAP_TYPE, - &encap, sizeof (u_int16_t)); - nest = addattr_nest(nlmsg, req_size, RTA_ENCAP); - addattr_l (nlmsg, req_size, MPLS_IPTUNNEL_DST, - &out_lse, num_labels * sizeof(mpls_lse_t)); - addattr_nest_end(nlmsg, nest); - } - } - } - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK)) - rtmsg->rtm_flags |= RTNH_F_ONLINK; - - if (rtmsg->rtm_family == AF_INET && - (nexthop->type == NEXTHOP_TYPE_IPV6 - || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) - { - rtmsg->rtm_flags |= RTNH_F_ONLINK; - addattr_l (nlmsg, req_size, RTA_GATEWAY, &ipv4_ll, 4); - addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex); - - if (nexthop->rmap_src.ipv4.s_addr && (cmd == RTM_NEWROUTE)) - addattr_l (nlmsg, req_size, RTA_PREFSRC, - &nexthop->rmap_src.ipv4, bytelen); - else if (nexthop->src.ipv4.s_addr && (cmd == RTM_NEWROUTE)) - addattr_l (nlmsg, req_size, RTA_PREFSRC, - &nexthop->src.ipv4, bytelen); - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug(" 5549: _netlink_route_build_singlepath() (%s): " - "nexthop via %s %s if %u", - routedesc, ipv4_ll_buf, label_buf, nexthop->ifindex); - return; - } - - if (nexthop->type == NEXTHOP_TYPE_IPV4 - || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - { - /* Send deletes to the kernel without specifying the next-hop */ - if (cmd != RTM_DELROUTE) - _netlink_route_nl_add_gateway_info (rtmsg->rtm_family, AF_INET, nlmsg, - req_size, bytelen, nexthop); - - if (cmd == RTM_NEWROUTE) - { - if (nexthop->rmap_src.ipv4.s_addr) - addattr_l (nlmsg, req_size, RTA_PREFSRC, - &nexthop->rmap_src.ipv4, bytelen); - else if (nexthop->src.ipv4.s_addr) - addattr_l (nlmsg, req_size, RTA_PREFSRC, - &nexthop->src.ipv4, bytelen); } - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("netlink_route_multipath() (%s): " - "nexthop via %s %s if %u", - routedesc, - inet_ntoa (nexthop->gate.ipv4), - label_buf, nexthop->ifindex); - } - - if (nexthop->type == NEXTHOP_TYPE_IPV6 - || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - { - _netlink_route_nl_add_gateway_info (rtmsg->rtm_family, AF_INET6, nlmsg, - req_size, bytelen, nexthop); - - if (cmd == RTM_NEWROUTE) - { - if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) - addattr_l (nlmsg, req_size, RTA_PREFSRC, - &nexthop->rmap_src.ipv6, bytelen); - else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) - addattr_l (nlmsg, req_size, RTA_PREFSRC, - &nexthop->src.ipv6, bytelen); + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) + rtmsg->rtm_flags |= RTNH_F_ONLINK; + + if (rtmsg->rtm_family == AF_INET + && (nexthop->type == NEXTHOP_TYPE_IPV6 + || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) { + rtmsg->rtm_flags |= RTNH_F_ONLINK; + addattr_l(nlmsg, req_size, RTA_GATEWAY, &ipv4_ll, 4); + addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex); + + if (nexthop->rmap_src.ipv4.s_addr && (cmd == RTM_NEWROUTE)) + addattr_l(nlmsg, req_size, RTA_PREFSRC, + &nexthop->rmap_src.ipv4, bytelen); + else if (nexthop->src.ipv4.s_addr && (cmd == RTM_NEWROUTE)) + addattr_l(nlmsg, req_size, RTA_PREFSRC, + &nexthop->src.ipv4, bytelen); + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + " 5549: _netlink_route_build_singlepath() (%s): " + "nexthop via %s %s if %u", + routedesc, ipv4_ll_buf, label_buf, + nexthop->ifindex); + return; } - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("netlink_route_multipath() (%s): " - "nexthop via %s %s if %u", - routedesc, - inet6_ntoa (nexthop->gate.ipv6), - label_buf, nexthop->ifindex); - } - if (nexthop->type == NEXTHOP_TYPE_IFINDEX - || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - { - addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex); - - if (cmd == RTM_NEWROUTE) - { - if (nexthop->rmap_src.ipv4.s_addr) - addattr_l (nlmsg, req_size, RTA_PREFSRC, - &nexthop->rmap_src.ipv4, bytelen); - else if (nexthop->src.ipv4.s_addr) - addattr_l (nlmsg, req_size, RTA_PREFSRC, - &nexthop->src.ipv4, bytelen); + if (nexthop->type == NEXTHOP_TYPE_IPV4 + || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { + /* Send deletes to the kernel without specifying the next-hop */ + if (cmd != RTM_DELROUTE) + _netlink_route_nl_add_gateway_info( + rtmsg->rtm_family, AF_INET, nlmsg, req_size, + bytelen, nexthop); + + if (cmd == RTM_NEWROUTE) { + if (nexthop->rmap_src.ipv4.s_addr) + addattr_l(nlmsg, req_size, RTA_PREFSRC, + &nexthop->rmap_src.ipv4, bytelen); + else if (nexthop->src.ipv4.s_addr) + addattr_l(nlmsg, req_size, RTA_PREFSRC, + &nexthop->src.ipv4, bytelen); + } + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_route_multipath() (%s): " + "nexthop via %s %s if %u", + routedesc, inet_ntoa(nexthop->gate.ipv4), + label_buf, nexthop->ifindex); } - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("netlink_route_multipath() (%s): " - "nexthop via if %u", routedesc, nexthop->ifindex); - } + if (nexthop->type == NEXTHOP_TYPE_IPV6 + || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { + _netlink_route_nl_add_gateway_info(rtmsg->rtm_family, AF_INET6, + nlmsg, req_size, bytelen, + nexthop); + + if (cmd == RTM_NEWROUTE) { + if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) + addattr_l(nlmsg, req_size, RTA_PREFSRC, + &nexthop->rmap_src.ipv6, bytelen); + else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) + addattr_l(nlmsg, req_size, RTA_PREFSRC, + &nexthop->src.ipv6, bytelen); + } - if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - { - addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex); + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_route_multipath() (%s): " + "nexthop via %s %s if %u", + routedesc, inet6_ntoa(nexthop->gate.ipv6), + label_buf, nexthop->ifindex); + } + if (nexthop->type == NEXTHOP_TYPE_IFINDEX + || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { + addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex); + + if (cmd == RTM_NEWROUTE) { + if (nexthop->rmap_src.ipv4.s_addr) + addattr_l(nlmsg, req_size, RTA_PREFSRC, + &nexthop->rmap_src.ipv4, bytelen); + else if (nexthop->src.ipv4.s_addr) + addattr_l(nlmsg, req_size, RTA_PREFSRC, + &nexthop->src.ipv4, bytelen); + } - if (cmd == RTM_NEWROUTE) - { - if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) - addattr_l (nlmsg, req_size, RTA_PREFSRC, - &nexthop->rmap_src.ipv6, bytelen); - else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) - addattr_l (nlmsg, req_size, RTA_PREFSRC, - &nexthop->src.ipv6, bytelen); + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_route_multipath() (%s): " + "nexthop via if %u", + routedesc, nexthop->ifindex); } - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("netlink_route_multipath() (%s): " - "nexthop via if %u", routedesc, nexthop->ifindex); - } + if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { + addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex); + + if (cmd == RTM_NEWROUTE) { + if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) + addattr_l(nlmsg, req_size, RTA_PREFSRC, + &nexthop->rmap_src.ipv6, bytelen); + else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) + addattr_l(nlmsg, req_size, RTA_PREFSRC, + &nexthop->src.ipv6, bytelen); + } + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_route_multipath() (%s): " + "nexthop via if %u", + routedesc, nexthop->ifindex); + } } /* This function takes a nexthop as argument and @@ -940,217 +921,206 @@ _netlink_route_build_singlepath( * @param src: pointer pointing to a location where * the prefsrc should be stored. */ -static void -_netlink_route_build_multipath( - const char *routedesc, - int bytelen, - struct nexthop *nexthop, - struct rtattr *rta, - struct rtnexthop *rtnh, - struct rtmsg *rtmsg, - union g_addr **src) +static void _netlink_route_build_multipath(const char *routedesc, int bytelen, + struct nexthop *nexthop, + struct rtattr *rta, + struct rtnexthop *rtnh, + struct rtmsg *rtmsg, + union g_addr **src) { - struct nexthop_label *nh_label; - mpls_lse_t out_lse[MPLS_MAX_LABELS]; - char label_buf[100]; - - rtnh->rtnh_len = sizeof (*rtnh); - rtnh->rtnh_flags = 0; - rtnh->rtnh_hops = 0; - rta->rta_len += rtnh->rtnh_len; - - /* - * label_buf is *only* currently used within debugging. - * As such when we assign it we are guarding it inside - * a debug test. If you want to change this make sure - * you fix this assumption - */ - label_buf[0] = '\0'; - /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP - * (in the case of LER) - */ - nh_label = nexthop->nh_label; - if (rtmsg->rtm_family == AF_MPLS) - { - assert (nh_label); - assert (nh_label->num_labels == 1); - } - - if (nh_label && nh_label->num_labels) - { - int i, num_labels = 0; - u_int32_t bos; - char label_buf1[20]; - - for (i = 0; i < nh_label->num_labels; i++) - { - if (nh_label->label[i] != MPLS_IMP_NULL_LABEL) - { - bos = ((i == (nh_label->num_labels - 1)) ? 1 : 0); - out_lse[i] = mpls_lse_encode (nh_label->label[i], 0, 0, bos); - if (IS_ZEBRA_DEBUG_KERNEL) - { - if (!num_labels) - sprintf (label_buf, "label %d", nh_label->label[i]); - else - { - sprintf (label_buf1, "/%d", nh_label->label[i]); - strcat (label_buf, label_buf1); - } + struct nexthop_label *nh_label; + mpls_lse_t out_lse[MPLS_MAX_LABELS]; + char label_buf[100]; + + rtnh->rtnh_len = sizeof(*rtnh); + rtnh->rtnh_flags = 0; + rtnh->rtnh_hops = 0; + rta->rta_len += rtnh->rtnh_len; + + /* + * label_buf is *only* currently used within debugging. + * As such when we assign it we are guarding it inside + * a debug test. If you want to change this make sure + * you fix this assumption + */ + label_buf[0] = '\0'; + /* outgoing label - either as NEWDST (in the case of LSR) or as ENCAP + * (in the case of LER) + */ + nh_label = nexthop->nh_label; + if (rtmsg->rtm_family == AF_MPLS) { + assert(nh_label); + assert(nh_label->num_labels == 1); + } + + if (nh_label && nh_label->num_labels) { + int i, num_labels = 0; + u_int32_t bos; + char label_buf1[20]; + + for (i = 0; i < nh_label->num_labels; i++) { + if (nh_label->label[i] != MPLS_IMP_NULL_LABEL) { + bos = ((i == (nh_label->num_labels - 1)) ? 1 + : 0); + out_lse[i] = mpls_lse_encode(nh_label->label[i], + 0, 0, bos); + if (IS_ZEBRA_DEBUG_KERNEL) { + if (!num_labels) + sprintf(label_buf, "label %d", + nh_label->label[i]); + else { + sprintf(label_buf1, "/%d", + nh_label->label[i]); + strcat(label_buf, label_buf1); + } + } + num_labels++; + } + } + if (num_labels) { + if (rtmsg->rtm_family == AF_MPLS) { + rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_NEWDST, + &out_lse, + num_labels * sizeof(mpls_lse_t)); + rtnh->rtnh_len += RTA_LENGTH( + num_labels * sizeof(mpls_lse_t)); + } else { + struct rtattr *nest; + u_int16_t encap = LWTUNNEL_ENCAP_MPLS; + int len = rta->rta_len; + + rta_addattr_l(rta, NL_PKT_BUF_SIZE, + RTA_ENCAP_TYPE, &encap, + sizeof(u_int16_t)); + nest = rta_nest(rta, NL_PKT_BUF_SIZE, + RTA_ENCAP); + rta_addattr_l(rta, NL_PKT_BUF_SIZE, + MPLS_IPTUNNEL_DST, &out_lse, + num_labels * sizeof(mpls_lse_t)); + rta_nest_end(rta, nest); + rtnh->rtnh_len += rta->rta_len - len; + } } - num_labels++; - } - } - if (num_labels) - { - if (rtmsg->rtm_family == AF_MPLS) - { - rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_NEWDST, - &out_lse, num_labels * sizeof(mpls_lse_t)); - rtnh->rtnh_len += RTA_LENGTH (num_labels * sizeof(mpls_lse_t)); - } - else - { - struct rtattr *nest; - u_int16_t encap = LWTUNNEL_ENCAP_MPLS; - int len = rta->rta_len; - - rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_ENCAP_TYPE, - &encap, sizeof (u_int16_t)); - nest = rta_nest(rta, NL_PKT_BUF_SIZE, RTA_ENCAP); - rta_addattr_l (rta, NL_PKT_BUF_SIZE, MPLS_IPTUNNEL_DST, - &out_lse, num_labels * sizeof(mpls_lse_t)); - rta_nest_end(rta, nest); - rtnh->rtnh_len += rta->rta_len - len; - } - } - } - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK)) - rtnh->rtnh_flags |= RTNH_F_ONLINK; - - if (rtmsg->rtm_family == AF_INET && - (nexthop->type == NEXTHOP_TYPE_IPV6 - || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) - { - bytelen = 4; - rtnh->rtnh_flags |= RTNH_F_ONLINK; - rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY, - &ipv4_ll, bytelen); - rtnh->rtnh_len += sizeof (struct rtattr) + bytelen; - rtnh->rtnh_ifindex = nexthop->ifindex; - - if (nexthop->rmap_src.ipv4.s_addr) - *src = &nexthop->rmap_src; - else if (nexthop->src.ipv4.s_addr) - *src = &nexthop->src; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug(" 5549: netlink_route_build_multipath() (%s): " - "nexthop via %s %s if %u", - routedesc, ipv4_ll_buf, label_buf, nexthop->ifindex); - return; - } - - if (nexthop->type == NEXTHOP_TYPE_IPV4 - || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - { - _netlink_route_rta_add_gateway_info (rtmsg->rtm_family, AF_INET, rta, - rtnh, NL_PKT_BUF_SIZE, bytelen, nexthop); - if (nexthop->rmap_src.ipv4.s_addr) - *src = &nexthop->rmap_src; - else if (nexthop->src.ipv4.s_addr) - *src = &nexthop->src; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("netlink_route_multipath() (%s): " - "nexthop via %s %s if %u", - routedesc, - inet_ntoa (nexthop->gate.ipv4), - label_buf, nexthop->ifindex); - } - if (nexthop->type == NEXTHOP_TYPE_IPV6 - || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - { - _netlink_route_rta_add_gateway_info (rtmsg->rtm_family, AF_INET6, rta, - rtnh, NL_PKT_BUF_SIZE, bytelen, nexthop); - - if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) - *src = &nexthop->rmap_src; - else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) - *src = &nexthop->src; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("netlink_route_multipath() (%s): " - "nexthop via %s %s if %u", - routedesc, - inet6_ntoa (nexthop->gate.ipv6), - label_buf, nexthop->ifindex); - } - /* ifindex */ - if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX - || nexthop->type == NEXTHOP_TYPE_IFINDEX) - { - rtnh->rtnh_ifindex = nexthop->ifindex; - - if (nexthop->rmap_src.ipv4.s_addr) - *src = &nexthop->rmap_src; - else if (nexthop->src.ipv4.s_addr) - *src = &nexthop->src; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("netlink_route_multipath() (%s): " - "nexthop via if %u", routedesc, nexthop->ifindex); - } - else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - { - rtnh->rtnh_ifindex = nexthop->ifindex; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("netlink_route_multipath() (%s): " - "nexthop via if %u", routedesc, nexthop->ifindex); - } - else - { - rtnh->rtnh_ifindex = 0; - } + } + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) + rtnh->rtnh_flags |= RTNH_F_ONLINK; + + if (rtmsg->rtm_family == AF_INET + && (nexthop->type == NEXTHOP_TYPE_IPV6 + || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) { + bytelen = 4; + rtnh->rtnh_flags |= RTNH_F_ONLINK; + rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_GATEWAY, &ipv4_ll, + bytelen); + rtnh->rtnh_len += sizeof(struct rtattr) + bytelen; + rtnh->rtnh_ifindex = nexthop->ifindex; + + if (nexthop->rmap_src.ipv4.s_addr) + *src = &nexthop->rmap_src; + else if (nexthop->src.ipv4.s_addr) + *src = &nexthop->src; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + " 5549: netlink_route_build_multipath() (%s): " + "nexthop via %s %s if %u", + routedesc, ipv4_ll_buf, label_buf, + nexthop->ifindex); + return; + } + + if (nexthop->type == NEXTHOP_TYPE_IPV4 + || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { + _netlink_route_rta_add_gateway_info(rtmsg->rtm_family, AF_INET, + rta, rtnh, NL_PKT_BUF_SIZE, + bytelen, nexthop); + if (nexthop->rmap_src.ipv4.s_addr) + *src = &nexthop->rmap_src; + else if (nexthop->src.ipv4.s_addr) + *src = &nexthop->src; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_route_multipath() (%s): " + "nexthop via %s %s if %u", + routedesc, inet_ntoa(nexthop->gate.ipv4), + label_buf, nexthop->ifindex); + } + if (nexthop->type == NEXTHOP_TYPE_IPV6 + || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { + _netlink_route_rta_add_gateway_info(rtmsg->rtm_family, AF_INET6, + rta, rtnh, NL_PKT_BUF_SIZE, + bytelen, nexthop); + + if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) + *src = &nexthop->rmap_src; + else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) + *src = &nexthop->src; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_route_multipath() (%s): " + "nexthop via %s %s if %u", + routedesc, inet6_ntoa(nexthop->gate.ipv6), + label_buf, nexthop->ifindex); + } + /* ifindex */ + if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX + || nexthop->type == NEXTHOP_TYPE_IFINDEX) { + rtnh->rtnh_ifindex = nexthop->ifindex; + + if (nexthop->rmap_src.ipv4.s_addr) + *src = &nexthop->rmap_src; + else if (nexthop->src.ipv4.s_addr) + *src = &nexthop->src; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_route_multipath() (%s): " + "nexthop via if %u", + routedesc, nexthop->ifindex); + } else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { + rtnh->rtnh_ifindex = nexthop->ifindex; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_route_multipath() (%s): " + "nexthop via if %u", + routedesc, nexthop->ifindex); + } else { + rtnh->rtnh_ifindex = 0; + } } -static inline void -_netlink_mpls_build_singlepath( - const char *routedesc, - zebra_nhlfe_t *nhlfe, - struct nlmsghdr *nlmsg, - struct rtmsg *rtmsg, - size_t req_size, - int cmd) +static inline void _netlink_mpls_build_singlepath(const char *routedesc, + zebra_nhlfe_t *nhlfe, + struct nlmsghdr *nlmsg, + struct rtmsg *rtmsg, + size_t req_size, int cmd) { - int bytelen; - u_char family; + int bytelen; + u_char family; - family = NHLFE_FAMILY (nhlfe); - bytelen = (family == AF_INET ? 4 : 16); - _netlink_route_build_singlepath(routedesc, bytelen, nhlfe->nexthop, - nlmsg, rtmsg, req_size, cmd); + family = NHLFE_FAMILY(nhlfe); + bytelen = (family == AF_INET ? 4 : 16); + _netlink_route_build_singlepath(routedesc, bytelen, nhlfe->nexthop, + nlmsg, rtmsg, req_size, cmd); } static inline void -_netlink_mpls_build_multipath( - const char *routedesc, - zebra_nhlfe_t *nhlfe, - struct rtattr *rta, - struct rtnexthop *rtnh, - struct rtmsg *rtmsg, - union g_addr **src) +_netlink_mpls_build_multipath(const char *routedesc, zebra_nhlfe_t *nhlfe, + struct rtattr *rta, struct rtnexthop *rtnh, + struct rtmsg *rtmsg, union g_addr **src) { - int bytelen; - u_char family; + int bytelen; + u_char family; - family = NHLFE_FAMILY (nhlfe); - bytelen = (family == AF_INET ? 4 : 16); - _netlink_route_build_multipath(routedesc, bytelen, nhlfe->nexthop, - rta, rtnh, rtmsg, src); + family = NHLFE_FAMILY(nhlfe); + bytelen = (family == AF_INET ? 4 : 16); + _netlink_route_build_multipath(routedesc, bytelen, nhlfe->nexthop, rta, + rtnh, rtmsg, src); } @@ -1164,1316 +1134,1311 @@ _netlink_mpls_build_multipath( * (recursive, multipath, etc.) * @param family: Address family which the change concerns */ -static void -_netlink_route_debug( - int cmd, - struct prefix *p, - struct nexthop *nexthop, - const char *routedesc, - int family, - struct zebra_vrf *zvrf) +static void _netlink_route_debug(int cmd, struct prefix *p, + struct nexthop *nexthop, const char *routedesc, + int family, struct zebra_vrf *zvrf) { - if (IS_ZEBRA_DEBUG_KERNEL) - { - char buf[PREFIX_STRLEN]; - zlog_debug ("netlink_route_multipath() (%s): %s %s vrf %u type %s", - routedesc, - nl_msg_type_to_str (cmd), - prefix2str (p, buf, sizeof(buf)), zvrf_id (zvrf), - (nexthop) ? nexthop_type_to_str (nexthop->type) : "UNK"); - } - } - -static void -_netlink_mpls_debug( - int cmd, - u_int32_t label, - const char *routedesc) + if (IS_ZEBRA_DEBUG_KERNEL) { + char buf[PREFIX_STRLEN]; + zlog_debug( + "netlink_route_multipath() (%s): %s %s vrf %u type %s", + routedesc, nl_msg_type_to_str(cmd), + prefix2str(p, buf, sizeof(buf)), zvrf_id(zvrf), + (nexthop) ? nexthop_type_to_str(nexthop->type) : "UNK"); + } +} + +static void _netlink_mpls_debug(int cmd, u_int32_t label, const char *routedesc) { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("netlink_mpls_multipath() (%s): %s %u/20", - routedesc, nl_msg_type_to_str (cmd), label); + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("netlink_mpls_multipath() (%s): %s %u/20", routedesc, + nl_msg_type_to_str(cmd), label); } -static int -netlink_neigh_update (int cmd, int ifindex, uint32_t addr, char *lla, int llalen) +static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla, + int llalen) { - struct { - struct nlmsghdr n; - struct ndmsg ndm; - char buf[256]; - } req; + struct { + struct nlmsghdr n; + struct ndmsg ndm; + char buf[256]; + } req; - struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); + struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); - memset(&req.n, 0, sizeof(req.n)); - memset(&req.ndm, 0, sizeof(req.ndm)); + memset(&req.n, 0, sizeof(req.n)); + memset(&req.ndm, 0, sizeof(req.ndm)); - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); - req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; - req.n.nlmsg_type = cmd; //RTM_NEWNEIGH or RTM_DELNEIGH - req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); + req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; + req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH + req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; - req.ndm.ndm_family = AF_INET; - req.ndm.ndm_state = NUD_PERMANENT; - req.ndm.ndm_ifindex = ifindex; - req.ndm.ndm_type = RTN_UNICAST; + req.ndm.ndm_family = AF_INET; + req.ndm.ndm_state = NUD_PERMANENT; + req.ndm.ndm_ifindex = ifindex; + req.ndm.ndm_type = RTN_UNICAST; - addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4); - addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); + addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4); + addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); - return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); + return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, + 0); } /* Routing table change via netlink interface. */ /* Update flag indicates whether this is a "replace" or not. */ -static int -netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p, - struct route_entry *re, int update) +static int netlink_route_multipath(int cmd, struct prefix *p, + struct prefix *src_p, struct route_entry *re, + int update) { - int bytelen; - struct sockaddr_nl snl; - struct nexthop *nexthop = NULL; - unsigned int nexthop_num; - int discard; - int family = PREFIX_FAMILY(p); - const char *routedesc; - int setsrc = 0; - union g_addr src; - - struct - { - struct nlmsghdr n; - struct rtmsg r; - char buf[NL_PKT_BUF_SIZE]; - } req; - - struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); - struct zebra_vrf *zvrf = vrf_info_lookup (re->vrf_id); - - memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); - - bytelen = (family == AF_INET ? 4 : 16); - - req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg)); - req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; - if ((cmd == RTM_NEWROUTE) && update) - req.n.nlmsg_flags |= NLM_F_REPLACE; - req.n.nlmsg_type = cmd; - req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; - - req.r.rtm_family = family; - req.r.rtm_dst_len = p->prefixlen; - req.r.rtm_src_len = src_p ? src_p->prefixlen : 0; - req.r.rtm_protocol = get_rt_proto(re->type); - req.r.rtm_scope = RT_SCOPE_UNIVERSE; - - if ((re->flags & ZEBRA_FLAG_BLACKHOLE) || (re->flags & ZEBRA_FLAG_REJECT)) - discard = 1; - else - discard = 0; - - if (cmd == RTM_NEWROUTE) - { - if (discard) - { - if (re->flags & ZEBRA_FLAG_BLACKHOLE) - req.r.rtm_type = RTN_BLACKHOLE; - else if (re->flags & ZEBRA_FLAG_REJECT) - req.r.rtm_type = RTN_UNREACHABLE; - else - assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */ - } - else - req.r.rtm_type = RTN_UNICAST; - } - - addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen); - if (src_p) - addattr_l (&req.n, sizeof req, RTA_SRC, &src_p->u.prefix, bytelen); - - /* Metric. */ - /* Hardcode the metric for all routes coming from zebra. Metric isn't used - * either by the kernel or by zebra. Its purely for calculating best path(s) - * by the routing protocol and for communicating with protocol peers. - */ - addattr32 (&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC); - - /* Table corresponding to this route. */ - if (re->table < 256) - req.r.rtm_table = re->table; - else - { - req.r.rtm_table = RT_TABLE_UNSPEC; - addattr32(&req.n, sizeof req, RTA_TABLE, re->table); - } - - if (re->mtu || re->nexthop_mtu) - { - char buf[NL_PKT_BUF_SIZE]; - struct rtattr *rta = (void *) buf; - u_int32_t mtu = re->mtu; - if (!mtu || (re->nexthop_mtu && re->nexthop_mtu < mtu)) - mtu = re->nexthop_mtu; - rta->rta_type = RTA_METRICS; - rta->rta_len = RTA_LENGTH(0); - rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu); - addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA (rta), - RTA_PAYLOAD (rta)); - } - - if (discard) - { - if (cmd == RTM_NEWROUTE) - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - /* We shouldn't encounter recursive nexthops on discard routes, - * but it is probably better to handle that case correctly anyway. - */ - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; - } - goto skip; - } - - /* Count overall nexthops so we can decide whether to use singlepath - * or multipath case. */ - nexthop_num = 0; - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; - if (cmd == RTM_NEWROUTE && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - continue; - if (cmd == RTM_DELROUTE && !CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - continue; - - nexthop_num++; - } - - /* Singlepath case. */ - if (nexthop_num == 1 || multipath_num == 1) - { - nexthop_num = 0; - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - { - if (!setsrc) - { - if (family == AF_INET) - { - if (nexthop->rmap_src.ipv4.s_addr != 0) - { - src.ipv4 = nexthop->rmap_src.ipv4; - setsrc = 1; - } - else if (nexthop->src.ipv4.s_addr != 0) - { - src.ipv4 = nexthop->src.ipv4; - setsrc = 1; - } - } - else if (family == AF_INET6) - { - if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) - { - src.ipv6 = nexthop->rmap_src.ipv6; - setsrc = 1; - } - else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) - { - src.ipv6 = nexthop->src.ipv6; - setsrc = 1; - } - } - } - continue; - } - - if ((cmd == RTM_NEWROUTE - && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - || (cmd == RTM_DELROUTE - && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))) - { - routedesc = nexthop->rparent ? "recursive, 1 hop" : "single hop"; - - _netlink_route_debug(cmd, p, nexthop, routedesc, family, zvrf); - _netlink_route_build_singlepath(routedesc, bytelen, - nexthop, &req.n, &req.r, - sizeof req, cmd); - nexthop_num++; - break; - } - } - if (setsrc && (cmd == RTM_NEWROUTE)) - { - if (family == AF_INET) - addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen); - else if (family == AF_INET6) - addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv6, bytelen); + int bytelen; + struct sockaddr_nl snl; + struct nexthop *nexthop = NULL; + unsigned int nexthop_num; + int discard; + int family = PREFIX_FAMILY(p); + const char *routedesc; + int setsrc = 0; + union g_addr src; + + struct { + struct nlmsghdr n; + struct rtmsg r; + char buf[NL_PKT_BUF_SIZE]; + } req; + + struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id); + + memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE); + + bytelen = (family == AF_INET ? 4 : 16); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; + if ((cmd == RTM_NEWROUTE) && update) + req.n.nlmsg_flags |= NLM_F_REPLACE; + req.n.nlmsg_type = cmd; + req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; + + req.r.rtm_family = family; + req.r.rtm_dst_len = p->prefixlen; + req.r.rtm_src_len = src_p ? src_p->prefixlen : 0; + req.r.rtm_protocol = get_rt_proto(re->type); + req.r.rtm_scope = RT_SCOPE_UNIVERSE; + + if ((re->flags & ZEBRA_FLAG_BLACKHOLE) + || (re->flags & ZEBRA_FLAG_REJECT)) + discard = 1; + else + discard = 0; + + if (cmd == RTM_NEWROUTE) { + if (discard) { + if (re->flags & ZEBRA_FLAG_BLACKHOLE) + req.r.rtm_type = RTN_BLACKHOLE; + else if (re->flags & ZEBRA_FLAG_REJECT) + req.r.rtm_type = RTN_UNREACHABLE; + else + assert(RTN_BLACKHOLE + != RTN_UNREACHABLE); /* false */ + } else + req.r.rtm_type = RTN_UNICAST; } - } - else - { - char buf[NL_PKT_BUF_SIZE]; - struct rtattr *rta = (void *) buf; - struct rtnexthop *rtnh; - union g_addr *src1 = NULL; - - rta->rta_type = RTA_MULTIPATH; - rta->rta_len = RTA_LENGTH (0); - rtnh = RTA_DATA (rta); - - nexthop_num = 0; - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - if (nexthop_num >= multipath_num) - break; - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - { - /* This only works for IPv4 now */ - if (!setsrc) - { - if (family == AF_INET) - { - if (nexthop->rmap_src.ipv4.s_addr != 0) - { - src.ipv4 = nexthop->rmap_src.ipv4; - setsrc = 1; - } - else if (nexthop->src.ipv4.s_addr != 0) - { - src.ipv4 = nexthop->src.ipv4; - setsrc = 1; - } - } - else if (family == AF_INET6) - { - if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6)) - { - src.ipv6 = nexthop->rmap_src.ipv6; - setsrc = 1; - } - else if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->src.ipv6)) - { - src.ipv6 = nexthop->src.ipv6; - setsrc = 1; - } - } - } - continue; - } - - if ((cmd == RTM_NEWROUTE - && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - || (cmd == RTM_DELROUTE - && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))) - { - routedesc = nexthop->rparent ? "recursive, multihop" : "multihop"; - nexthop_num++; - - _netlink_route_debug(cmd, p, nexthop, - routedesc, family, zvrf); - _netlink_route_build_multipath(routedesc, bytelen, - nexthop, rta, rtnh, &req.r, &src1); - rtnh = RTNH_NEXT (rtnh); - - if (!setsrc && src1) - { - if (family == AF_INET) - src.ipv4 = src1->ipv4; - else if (family == AF_INET6) - src.ipv6 = src1->ipv6; - setsrc = 1; - } - } - } - if (setsrc && (cmd == RTM_NEWROUTE)) - { - if (family == AF_INET) - addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv4, bytelen); - else if (family == AF_INET6) - addattr_l (&req.n, sizeof req, RTA_PREFSRC, &src.ipv6, bytelen); - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("Setting source"); + addattr_l(&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen); + if (src_p) + addattr_l(&req.n, sizeof req, RTA_SRC, &src_p->u.prefix, + bytelen); + + /* Metric. */ + /* Hardcode the metric for all routes coming from zebra. Metric isn't + * used + * either by the kernel or by zebra. Its purely for calculating best + * path(s) + * by the routing protocol and for communicating with protocol peers. + */ + addattr32(&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC); + + /* Table corresponding to this route. */ + if (re->table < 256) + req.r.rtm_table = re->table; + else { + req.r.rtm_table = RT_TABLE_UNSPEC; + addattr32(&req.n, sizeof req, RTA_TABLE, re->table); } - if (rta->rta_len > RTA_LENGTH (0)) - addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta), - RTA_PAYLOAD (rta)); - } + if (re->mtu || re->nexthop_mtu) { + char buf[NL_PKT_BUF_SIZE]; + struct rtattr *rta = (void *)buf; + u_int32_t mtu = re->mtu; + if (!mtu || (re->nexthop_mtu && re->nexthop_mtu < mtu)) + mtu = re->nexthop_mtu; + rta->rta_type = RTA_METRICS; + rta->rta_len = RTA_LENGTH(0); + rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu); + addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA(rta), + RTA_PAYLOAD(rta)); + } + + if (discard) { + if (cmd == RTM_NEWROUTE) + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + /* We shouldn't encounter recursive nexthops on + * discard routes, + * but it is probably better to handle that case + * correctly anyway. + */ + if (CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_RECURSIVE)) + continue; + } + goto skip; + } + + /* Count overall nexthops so we can decide whether to use singlepath + * or multipath case. */ + nexthop_num = 0; + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + continue; + if (cmd == RTM_NEWROUTE + && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + continue; + if (cmd == RTM_DELROUTE + && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) + continue; + + nexthop_num++; + } + + /* Singlepath case. */ + if (nexthop_num == 1 || multipath_num == 1) { + nexthop_num = 0; + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + if (CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_RECURSIVE)) { + if (!setsrc) { + if (family == AF_INET) { + if (nexthop->rmap_src.ipv4 + .s_addr + != 0) { + src.ipv4 = + nexthop->rmap_src + .ipv4; + setsrc = 1; + } else if (nexthop->src.ipv4 + .s_addr + != 0) { + src.ipv4 = + nexthop->src + .ipv4; + setsrc = 1; + } + } else if (family == AF_INET6) { + if (!IN6_IS_ADDR_UNSPECIFIED( + &nexthop->rmap_src + .ipv6)) { + src.ipv6 = + nexthop->rmap_src + .ipv6; + setsrc = 1; + } else if ( + !IN6_IS_ADDR_UNSPECIFIED( + &nexthop->src + .ipv6)) { + src.ipv6 = + nexthop->src + .ipv6; + setsrc = 1; + } + } + } + continue; + } + + if ((cmd == RTM_NEWROUTE + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + || (cmd == RTM_DELROUTE + && CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB))) { + routedesc = nexthop->rparent + ? "recursive, 1 hop" + : "single hop"; + + _netlink_route_debug(cmd, p, nexthop, routedesc, + family, zvrf); + _netlink_route_build_singlepath( + routedesc, bytelen, nexthop, &req.n, + &req.r, sizeof req, cmd); + nexthop_num++; + break; + } + } + if (setsrc && (cmd == RTM_NEWROUTE)) { + if (family == AF_INET) + addattr_l(&req.n, sizeof req, RTA_PREFSRC, + &src.ipv4, bytelen); + else if (family == AF_INET6) + addattr_l(&req.n, sizeof req, RTA_PREFSRC, + &src.ipv6, bytelen); + } + } else { + char buf[NL_PKT_BUF_SIZE]; + struct rtattr *rta = (void *)buf; + struct rtnexthop *rtnh; + union g_addr *src1 = NULL; + + rta->rta_type = RTA_MULTIPATH; + rta->rta_len = RTA_LENGTH(0); + rtnh = RTA_DATA(rta); + + nexthop_num = 0; + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + if (nexthop_num >= multipath_num) + break; + + if (CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_RECURSIVE)) { + /* This only works for IPv4 now */ + if (!setsrc) { + if (family == AF_INET) { + if (nexthop->rmap_src.ipv4 + .s_addr + != 0) { + src.ipv4 = + nexthop->rmap_src + .ipv4; + setsrc = 1; + } else if (nexthop->src.ipv4 + .s_addr + != 0) { + src.ipv4 = + nexthop->src + .ipv4; + setsrc = 1; + } + } else if (family == AF_INET6) { + if (!IN6_IS_ADDR_UNSPECIFIED( + &nexthop->rmap_src + .ipv6)) { + src.ipv6 = + nexthop->rmap_src + .ipv6; + setsrc = 1; + } else if ( + !IN6_IS_ADDR_UNSPECIFIED( + &nexthop->src + .ipv6)) { + src.ipv6 = + nexthop->src + .ipv6; + setsrc = 1; + } + } + } + continue; + } + + if ((cmd == RTM_NEWROUTE + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + || (cmd == RTM_DELROUTE + && CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB))) { + routedesc = nexthop->rparent + ? "recursive, multihop" + : "multihop"; + nexthop_num++; + + _netlink_route_debug(cmd, p, nexthop, routedesc, + family, zvrf); + _netlink_route_build_multipath( + routedesc, bytelen, nexthop, rta, rtnh, + &req.r, &src1); + rtnh = RTNH_NEXT(rtnh); + + if (!setsrc && src1) { + if (family == AF_INET) + src.ipv4 = src1->ipv4; + else if (family == AF_INET6) + src.ipv6 = src1->ipv6; + + setsrc = 1; + } + } + } + if (setsrc && (cmd == RTM_NEWROUTE)) { + if (family == AF_INET) + addattr_l(&req.n, sizeof req, RTA_PREFSRC, + &src.ipv4, bytelen); + else if (family == AF_INET6) + addattr_l(&req.n, sizeof req, RTA_PREFSRC, + &src.ipv6, bytelen); + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("Setting source"); + } + + if (rta->rta_len > RTA_LENGTH(0)) + addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, + RTA_DATA(rta), RTA_PAYLOAD(rta)); + } - /* If there is no useful nexthop then return. */ - if (nexthop_num == 0) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("netlink_route_multipath(): No useful nexthop."); - return 0; - } + /* If there is no useful nexthop then return. */ + if (nexthop_num == 0) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_route_multipath(): No useful nexthop."); + return 0; + } skip: - /* Destination netlink address. */ - memset (&snl, 0, sizeof snl); - snl.nl_family = AF_NETLINK; + /* Destination netlink address. */ + memset(&snl, 0, sizeof snl); + snl.nl_family = AF_NETLINK; - /* Talk to netlink socket. */ - return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); + /* Talk to netlink socket. */ + return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, + 0); } -int -kernel_get_ipmr_sg_stats (void *in) +int kernel_get_ipmr_sg_stats(void *in) { - int suc = 0; - struct mcast_route_data *mr = (struct mcast_route_data *)in; - struct { - struct nlmsghdr n; - struct ndmsg ndm; - char buf[256]; - } req; + int suc = 0; + struct mcast_route_data *mr = (struct mcast_route_data *)in; + struct { + struct nlmsghdr n; + struct ndmsg ndm; + char buf[256]; + } req; - mroute = mr; - struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); + mroute = mr; + struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); - memset(&req.n, 0, sizeof(req.n)); - memset(&req.ndm, 0, sizeof(req.ndm)); + memset(&req.n, 0, sizeof(req.n)); + memset(&req.ndm, 0, sizeof(req.ndm)); - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); - req.n.nlmsg_flags = NLM_F_REQUEST; - req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; - req.ndm.ndm_family = AF_INET; - req.n.nlmsg_type = RTM_GETROUTE; + req.ndm.ndm_family = AF_INET; + req.n.nlmsg_type = RTM_GETROUTE; - addattr_l (&req.n, sizeof (req), RTA_IIF, &mroute->ifindex, 4); - addattr_l (&req.n, sizeof (req), RTA_OIF, &mroute->ifindex, 4); - addattr_l (&req.n, sizeof (req), RTA_SRC, &mroute->sg.src.s_addr, 4); - addattr_l (&req.n, sizeof (req), RTA_DST, &mroute->sg.grp.s_addr, 4); + addattr_l(&req.n, sizeof(req), RTA_IIF, &mroute->ifindex, 4); + addattr_l(&req.n, sizeof(req), RTA_OIF, &mroute->ifindex, 4); + addattr_l(&req.n, sizeof(req), RTA_SRC, &mroute->sg.src.s_addr, 4); + addattr_l(&req.n, sizeof(req), RTA_DST, &mroute->sg.grp.s_addr, 4); - suc = netlink_talk (netlink_route_change_read_multicast, &req.n, &zns->netlink_cmd, zns, 0); + suc = netlink_talk(netlink_route_change_read_multicast, &req.n, + &zns->netlink_cmd, zns, 0); - mroute = NULL; - return suc; + mroute = NULL; + return suc; } -int -kernel_route_rib (struct prefix *p, struct prefix *src_p, - struct route_entry *old, struct route_entry *new) +int kernel_route_rib(struct prefix *p, struct prefix *src_p, + struct route_entry *old, struct route_entry *new) { - if (!old && new) - return netlink_route_multipath (RTM_NEWROUTE, p, src_p, new, 0); - if (old && !new) - return netlink_route_multipath (RTM_DELROUTE, p, src_p, old, 0); + if (!old && new) + return netlink_route_multipath(RTM_NEWROUTE, p, src_p, new, 0); + if (old && !new) + return netlink_route_multipath(RTM_DELROUTE, p, src_p, old, 0); - return netlink_route_multipath (RTM_NEWROUTE, p, src_p, new, 1); + return netlink_route_multipath(RTM_NEWROUTE, p, src_p, new, 1); } -int -kernel_neigh_update (int add, int ifindex, uint32_t addr, char *lla, int llalen) +int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla, + int llalen) { - return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex, addr, - lla, llalen); + return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex, + addr, lla, llalen); } /* * Add remote VTEP to the flood list for this VxLAN interface (VNI). This * is done by adding an FDB entry with a MAC of 00:00:00:00:00:00. */ -static int -netlink_vxlan_flood_list_update (struct interface *ifp, - struct in_addr *vtep_ip, - int cmd) +static int netlink_vxlan_flood_list_update(struct interface *ifp, + struct in_addr *vtep_ip, int cmd) { - struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); - struct - { - struct nlmsghdr n; - struct ndmsg ndm; - char buf[256]; - } req; - u_char dst_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; - - memset(&req.n, 0, sizeof(req.n)); - memset(&req.ndm, 0, sizeof(req.ndm)); - - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); - req.n.nlmsg_flags = NLM_F_REQUEST; - if (cmd == RTM_NEWNEIGH) - req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_APPEND); - req.n.nlmsg_type = cmd; - req.ndm.ndm_family = PF_BRIDGE; - req.ndm.ndm_state = NUD_NOARP | NUD_PERMANENT; - req.ndm.ndm_flags |= NTF_SELF; // Handle by "self", not "master" - - - addattr_l (&req.n, sizeof (req), NDA_LLADDR, &dst_mac, 6); - req.ndm.ndm_ifindex = ifp->ifindex; - addattr_l (&req.n, sizeof (req), NDA_DST, &vtep_ip->s_addr, 4); - - return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); + struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + struct { + struct nlmsghdr n; + struct ndmsg ndm; + char buf[256]; + } req; + u_char dst_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + + memset(&req.n, 0, sizeof(req.n)); + memset(&req.ndm, 0, sizeof(req.ndm)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); + req.n.nlmsg_flags = NLM_F_REQUEST; + if (cmd == RTM_NEWNEIGH) + req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_APPEND); + req.n.nlmsg_type = cmd; + req.ndm.ndm_family = PF_BRIDGE; + req.ndm.ndm_state = NUD_NOARP | NUD_PERMANENT; + req.ndm.ndm_flags |= NTF_SELF; // Handle by "self", not "master" + + + addattr_l(&req.n, sizeof(req), NDA_LLADDR, &dst_mac, 6); + req.ndm.ndm_ifindex = ifp->ifindex; + addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip->s_addr, 4); + + return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, + 0); } /* - * Add remote VTEP for this VxLAN interface (VNI). In Linux, this involves adding + * Add remote VTEP for this VxLAN interface (VNI). In Linux, this involves + * adding * a "flood" MAC FDB entry. */ -int -kernel_add_vtep (vni_t vni, struct interface *ifp, struct in_addr *vtep_ip) +int kernel_add_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("Install %s into flood list for VNI %u intf %s(%u)", - inet_ntoa (*vtep_ip), vni, ifp->name, ifp->ifindex); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("Install %s into flood list for VNI %u intf %s(%u)", + inet_ntoa(*vtep_ip), vni, ifp->name, ifp->ifindex); - return netlink_vxlan_flood_list_update (ifp, vtep_ip, RTM_NEWNEIGH); + return netlink_vxlan_flood_list_update(ifp, vtep_ip, RTM_NEWNEIGH); } /* * Remove remote VTEP for this VxLAN interface (VNI). In Linux, this involves * deleting the "flood" MAC FDB entry. */ -int -kernel_del_vtep (vni_t vni, struct interface *ifp, struct in_addr *vtep_ip) +int kernel_del_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("Uninstall %s from flood list for VNI %u intf %s(%u)", - inet_ntoa (*vtep_ip), vni, ifp->name, ifp->ifindex); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "Uninstall %s from flood list for VNI %u intf %s(%u)", + inet_ntoa(*vtep_ip), vni, ifp->name, ifp->ifindex); - return netlink_vxlan_flood_list_update (ifp, vtep_ip, RTM_DELNEIGH); + return netlink_vxlan_flood_list_update(ifp, vtep_ip, RTM_DELNEIGH); } #ifndef NDA_RTA -#define NDA_RTA(r) \ - ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) +#define NDA_RTA(r) \ + ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) #endif -static int -netlink_macfdb_change (struct sockaddr_nl *snl, struct nlmsghdr *h, int len) +static int netlink_macfdb_change(struct sockaddr_nl *snl, struct nlmsghdr *h, + int len) { - struct ndmsg *ndm; - struct interface *ifp; - struct zebra_if *zif; - struct zebra_vrf *zvrf; - struct rtattr *tb[NDA_MAX + 1]; - struct interface *br_if; - struct ethaddr mac; - vlanid_t vid = 0; - struct prefix vtep_ip; - int vid_present = 0, dst_present = 0; - char buf[ETHER_ADDR_STRLEN]; - char vid_buf[20]; - char dst_buf[30]; - u_char sticky = 0; - - ndm = NLMSG_DATA (h); - - /* The interface should exist. */ - ifp = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT), ndm->ndm_ifindex); - if (!ifp) - return 0; - - /* Locate VRF corresponding to interface. We only process MAC notifications - * if EVPN is enabled on this VRF. - */ - zvrf = vrf_info_lookup(ifp->vrf_id); - if (!zvrf || !EVPN_ENABLED(zvrf)) - return 0; - if (!ifp->info) - return 0; - - /* The interface should be something we're interested in. */ - if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) - return 0; - - /* Drop "permanent" entries. */ - if (ndm->ndm_state & NUD_PERMANENT) - return 0; - - zif = (struct zebra_if *)ifp->info; - if ((br_if = zif->brslave_info.br_if) == NULL) - { - zlog_warn ("%s family %s IF %s(%u) brIF %u - no bridge master", - nl_msg_type_to_str (h->nlmsg_type), - nl_family_to_str (ndm->ndm_family), - ifp->name, ndm->ndm_ifindex, - zif->brslave_info.bridge_ifindex); - return 0; - } - - /* Parse attributes and extract fields of interest. */ - memset (tb, 0, sizeof tb); - netlink_parse_rtattr (tb, NDA_MAX, NDA_RTA (ndm), len); - - if (!tb[NDA_LLADDR]) - { - zlog_warn ("%s family %s IF %s(%u) brIF %u - no LLADDR", - nl_msg_type_to_str (h->nlmsg_type), - nl_family_to_str (ndm->ndm_family), - ifp->name, ndm->ndm_ifindex, - zif->brslave_info.bridge_ifindex); - return 0; - } - - if (RTA_PAYLOAD (tb[NDA_LLADDR]) != ETHER_ADDR_LEN) - { - zlog_warn ("%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %ld", - nl_msg_type_to_str (h->nlmsg_type), - nl_family_to_str (ndm->ndm_family), - ifp->name, ndm->ndm_ifindex, - zif->brslave_info.bridge_ifindex, - RTA_PAYLOAD (tb[NDA_LLADDR])); - return 0; - } - - memcpy (&mac, RTA_DATA (tb[NDA_LLADDR]), ETHER_ADDR_LEN); - - if ((NDA_VLAN <= NDA_MAX) && tb[NDA_VLAN]) - { - vid_present = 1; - vid = *(u_int16_t *) RTA_DATA(tb[NDA_VLAN]); - sprintf (vid_buf, " VLAN %u", vid); - } - - if (tb[NDA_DST]) - { - /* TODO: Only IPv4 supported now. */ - dst_present = 1; - vtep_ip.family = AF_INET; - vtep_ip.prefixlen = IPV4_MAX_BITLEN; - memcpy (&(vtep_ip.u.prefix4.s_addr), RTA_DATA (tb[NDA_DST]), IPV4_MAX_BYTELEN); - sprintf (dst_buf, " dst %s", inet_ntoa (vtep_ip.u.prefix4)); - } - - sticky = (ndm->ndm_state & NUD_NOARP) ? 1 : 0; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("Rx %s family %s IF %s(%u)%s %sMAC %s%s", - nl_msg_type_to_str (h->nlmsg_type), - nl_family_to_str (ndm->ndm_family), - ifp->name, ndm->ndm_ifindex, - vid_present ? vid_buf : "", - sticky ? "sticky " : "", - prefix_mac2str (&mac, buf, sizeof (buf)), - dst_present ? dst_buf: ""); - - if (filter_vlan && vid != filter_vlan) - return 0; - - /* If add or update, do accordingly if learnt on a "local" interface; if - * the notification is over VxLAN, this has to be related to multi-homing, - * so perform an implicit delete of any local entry (if it exists). - */ - if (h->nlmsg_type == RTM_NEWNEIGH) - { - /* Drop "permanent" entries. */ - if (ndm->ndm_state & NUD_PERMANENT) - return 0; - - if (IS_ZEBRA_IF_VXLAN(ifp)) - return zebra_vxlan_check_del_local_mac (ifp, br_if, &mac, vid); - - return zebra_vxlan_local_mac_add_update (ifp, br_if, &mac, vid, sticky); - } - - /* This is a delete notification. - * 1. For a MAC over VxLan, check if it needs to be refreshed(readded) - * 2. For a MAC over "local" interface, delete the mac - * Note: We will get notifications from both bridge driver and VxLAN driver. - * Ignore the notification from VxLan driver as it is also generated - * when mac moves from remote to local. - */ - if (dst_present) - return 0; - - if (IS_ZEBRA_IF_VXLAN(ifp)) - return zebra_vxlan_check_readd_remote_mac (ifp, br_if, &mac, vid); - - return zebra_vxlan_local_mac_del (ifp, br_if, &mac, vid); + struct ndmsg *ndm; + struct interface *ifp; + struct zebra_if *zif; + struct zebra_vrf *zvrf; + struct rtattr *tb[NDA_MAX + 1]; + struct interface *br_if; + struct ethaddr mac; + vlanid_t vid = 0; + struct prefix vtep_ip; + int vid_present = 0, dst_present = 0; + char buf[ETHER_ADDR_STRLEN]; + char vid_buf[20]; + char dst_buf[30]; + u_char sticky = 0; + + ndm = NLMSG_DATA(h); + + /* The interface should exist. */ + ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), + ndm->ndm_ifindex); + if (!ifp) + return 0; + + /* Locate VRF corresponding to interface. We only process MAC + * notifications + * if EVPN is enabled on this VRF. + */ + zvrf = vrf_info_lookup(ifp->vrf_id); + if (!zvrf || !EVPN_ENABLED(zvrf)) + return 0; + if (!ifp->info) + return 0; + + /* The interface should be something we're interested in. */ + if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) + return 0; + + /* Drop "permanent" entries. */ + if (ndm->ndm_state & NUD_PERMANENT) + return 0; + + zif = (struct zebra_if *)ifp->info; + if ((br_if = zif->brslave_info.br_if) == NULL) { + zlog_warn("%s family %s IF %s(%u) brIF %u - no bridge master", + nl_msg_type_to_str(h->nlmsg_type), + nl_family_to_str(ndm->ndm_family), ifp->name, + ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex); + return 0; + } + + /* Parse attributes and extract fields of interest. */ + memset(tb, 0, sizeof tb); + netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len); + + if (!tb[NDA_LLADDR]) { + zlog_warn("%s family %s IF %s(%u) brIF %u - no LLADDR", + nl_msg_type_to_str(h->nlmsg_type), + nl_family_to_str(ndm->ndm_family), ifp->name, + ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex); + return 0; + } + + if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETHER_ADDR_LEN) { + zlog_warn( + "%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %ld", + nl_msg_type_to_str(h->nlmsg_type), + nl_family_to_str(ndm->ndm_family), ifp->name, + ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex, + RTA_PAYLOAD(tb[NDA_LLADDR])); + return 0; + } + + memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETHER_ADDR_LEN); + + if ((NDA_VLAN <= NDA_MAX) && tb[NDA_VLAN]) { + vid_present = 1; + vid = *(u_int16_t *)RTA_DATA(tb[NDA_VLAN]); + sprintf(vid_buf, " VLAN %u", vid); + } + + if (tb[NDA_DST]) { + /* TODO: Only IPv4 supported now. */ + dst_present = 1; + vtep_ip.family = AF_INET; + vtep_ip.prefixlen = IPV4_MAX_BITLEN; + memcpy(&(vtep_ip.u.prefix4.s_addr), RTA_DATA(tb[NDA_DST]), + IPV4_MAX_BYTELEN); + sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip.u.prefix4)); + } + + sticky = (ndm->ndm_state & NUD_NOARP) ? 1 : 0; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("Rx %s family %s IF %s(%u)%s %sMAC %s%s", + nl_msg_type_to_str(h->nlmsg_type), + nl_family_to_str(ndm->ndm_family), ifp->name, + ndm->ndm_ifindex, vid_present ? vid_buf : "", + sticky ? "sticky " : "", + prefix_mac2str(&mac, buf, sizeof(buf)), + dst_present ? dst_buf : ""); + + if (filter_vlan && vid != filter_vlan) + return 0; + + /* If add or update, do accordingly if learnt on a "local" interface; if + * the notification is over VxLAN, this has to be related to + * multi-homing, + * so perform an implicit delete of any local entry (if it exists). + */ + if (h->nlmsg_type == RTM_NEWNEIGH) { + /* Drop "permanent" entries. */ + if (ndm->ndm_state & NUD_PERMANENT) + return 0; + + if (IS_ZEBRA_IF_VXLAN(ifp)) + return zebra_vxlan_check_del_local_mac(ifp, br_if, &mac, + vid); + + return zebra_vxlan_local_mac_add_update(ifp, br_if, &mac, vid, + sticky); + } + + /* This is a delete notification. + * 1. For a MAC over VxLan, check if it needs to be refreshed(readded) + * 2. For a MAC over "local" interface, delete the mac + * Note: We will get notifications from both bridge driver and VxLAN + * driver. + * Ignore the notification from VxLan driver as it is also generated + * when mac moves from remote to local. + */ + if (dst_present) + return 0; + + if (IS_ZEBRA_IF_VXLAN(ifp)) + return zebra_vxlan_check_readd_remote_mac(ifp, br_if, &mac, + vid); + + return zebra_vxlan_local_mac_del(ifp, br_if, &mac, vid); } -static int -netlink_macfdb_table (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +static int netlink_macfdb_table(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup) { - int len; - struct ndmsg *ndm; + int len; + struct ndmsg *ndm; - if (h->nlmsg_type != RTM_NEWNEIGH) - return 0; + if (h->nlmsg_type != RTM_NEWNEIGH) + return 0; - /* Length validity. */ - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ndmsg)); - if (len < 0) - return -1; + /* Length validity. */ + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg)); + if (len < 0) + return -1; - /* We are interested only in AF_BRIDGE notifications. */ - ndm = NLMSG_DATA (h); - if (ndm->ndm_family != AF_BRIDGE) - return 0; + /* We are interested only in AF_BRIDGE notifications. */ + ndm = NLMSG_DATA(h); + if (ndm->ndm_family != AF_BRIDGE) + return 0; - return netlink_macfdb_change (snl, h, len); + return netlink_macfdb_change(snl, h, len); } /* Request for MAC FDB information from the kernel */ -static int -netlink_request_macs (struct zebra_ns *zns, int family, int type, - ifindex_t master_ifindex) +static int netlink_request_macs(struct zebra_ns *zns, int family, int type, + ifindex_t master_ifindex) { - struct - { - struct nlmsghdr n; - struct ifinfomsg ifm; - char buf[256]; - } req; - - /* Form the request, specifying filter (rtattr) if needed. */ - memset (&req, 0, sizeof (req)); - req.n.nlmsg_type = type; - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); - req.ifm.ifi_family = family; - if (master_ifindex) - addattr32 (&req.n, sizeof(req), IFLA_MASTER, master_ifindex); - - return netlink_request (&zns->netlink_cmd, &req.n); + struct { + struct nlmsghdr n; + struct ifinfomsg ifm; + char buf[256]; + } req; + + /* Form the request, specifying filter (rtattr) if needed. */ + memset(&req, 0, sizeof(req)); + req.n.nlmsg_type = type; + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + req.ifm.ifi_family = family; + if (master_ifindex) + addattr32(&req.n, sizeof(req), IFLA_MASTER, master_ifindex); + + return netlink_request(&zns->netlink_cmd, &req.n); } /* * MAC forwarding database read using netlink interface. This is invoked * at startup. */ -int -netlink_macfdb_read (struct zebra_ns *zns) +int netlink_macfdb_read(struct zebra_ns *zns) { - int ret; - - /* Get bridge FDB table. */ - ret = netlink_request_macs (zns, AF_BRIDGE, RTM_GETNEIGH, 0); - if (ret < 0) - return ret; - /* We are reading entire table. */ - filter_vlan = 0; - ret = netlink_parse_info (netlink_macfdb_table, &zns->netlink_cmd, zns, 0, 1); - - return ret; + int ret; + + /* Get bridge FDB table. */ + ret = netlink_request_macs(zns, AF_BRIDGE, RTM_GETNEIGH, 0); + if (ret < 0) + return ret; + /* We are reading entire table. */ + filter_vlan = 0; + ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, zns, + 0, 1); + + return ret; } /* * MAC forwarding database read using netlink interface. This is for a * specific bridge and matching specific access VLAN (if VLAN-aware bridge). */ -int -netlink_macfdb_read_for_bridge (struct zebra_ns *zns, struct interface *ifp, - struct interface *br_if) +int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp, + struct interface *br_if) { - struct zebra_if *br_zif; - struct zebra_if *zif; - struct zebra_l2info_vxlan *vxl; - int ret = 0; - - - /* Save VLAN we're filtering on, if needed. */ - br_zif = (struct zebra_if *) br_if->info; - zif = (struct zebra_if *) ifp->info; - vxl = &zif->l2info.vxl; - if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif)) - filter_vlan = vxl->access_vlan; - - /* Get bridge FDB table for specific bridge - we do the VLAN filtering. */ - ret = netlink_request_macs (zns, AF_BRIDGE, RTM_GETNEIGH, br_if->ifindex); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_macfdb_table, &zns->netlink_cmd, zns, 0, 0); - - /* Reset VLAN filter. */ - filter_vlan = 0; - return ret; + struct zebra_if *br_zif; + struct zebra_if *zif; + struct zebra_l2info_vxlan *vxl; + int ret = 0; + + + /* Save VLAN we're filtering on, if needed. */ + br_zif = (struct zebra_if *)br_if->info; + zif = (struct zebra_if *)ifp->info; + vxl = &zif->l2info.vxl; + if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif)) + filter_vlan = vxl->access_vlan; + + /* Get bridge FDB table for specific bridge - we do the VLAN filtering. + */ + ret = netlink_request_macs(zns, AF_BRIDGE, RTM_GETNEIGH, + br_if->ifindex); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, zns, + 0, 0); + + /* Reset VLAN filter. */ + filter_vlan = 0; + return ret; } -static int -netlink_macfdb_update (struct interface *ifp, vlanid_t vid, - struct ethaddr *mac, - struct in_addr vtep_ip, - int local, int cmd, - u_char sticky) +static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid, + struct ethaddr *mac, struct in_addr vtep_ip, + int local, int cmd, u_char sticky) { - struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); - struct - { - struct nlmsghdr n; - struct ndmsg ndm; - char buf[256]; - } req; - int dst_alen; - struct zebra_if *zif; - struct interface *br_if; - struct zebra_if *br_zif; - char buf[ETHER_ADDR_STRLEN]; - int vid_present = 0, dst_present = 0; - char vid_buf[20]; - char dst_buf[30]; - - zif = ifp->info; - if ((br_if = zif->brslave_info.br_if) == NULL) - { - zlog_warn ("MAC %s on IF %s(%u) - no mapping to bridge", - (cmd == RTM_NEWNEIGH) ? "add" : "del", - ifp->name, ifp->ifindex); - return -1; - } - - memset(&req.n, 0, sizeof(req.n)); - memset(&req.ndm, 0, sizeof(req.ndm)); - - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); - req.n.nlmsg_flags = NLM_F_REQUEST; - if (cmd == RTM_NEWNEIGH) - req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE); - req.n.nlmsg_type = cmd; - req.ndm.ndm_family = AF_BRIDGE; - req.ndm.ndm_flags |= NTF_SELF | NTF_MASTER; - req.ndm.ndm_state = NUD_REACHABLE; - - if (sticky) - req.ndm.ndm_state |= NUD_NOARP; - else - req.ndm.ndm_flags |= NTF_EXT_LEARNED; - - addattr_l (&req.n, sizeof (req), NDA_LLADDR, mac, 6); - req.ndm.ndm_ifindex = ifp->ifindex; - if (!local) - { - dst_alen = 4; // TODO: hardcoded - addattr_l (&req.n, sizeof (req), NDA_DST, &vtep_ip, dst_alen); - dst_present = 1; - sprintf (dst_buf, " dst %s", inet_ntoa (vtep_ip)); - } - br_zif = (struct zebra_if *) br_if->info; - if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0) - { - addattr16 (&req.n, sizeof (req), NDA_VLAN, vid); - vid_present = 1; - sprintf (vid_buf, " VLAN %u", vid); - } - addattr32 (&req.n, sizeof (req), NDA_MASTER, br_if->ifindex); - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("Tx %s family %s IF %s(%u)%s %sMAC %s%s", - nl_msg_type_to_str (cmd), - nl_family_to_str (req.ndm.ndm_family), - ifp->name, ifp->ifindex, - vid_present ? vid_buf : "", - sticky ? "sticky " : "", - prefix_mac2str (mac, buf, sizeof (buf)), - dst_present ? dst_buf : ""); - - return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); + struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + struct { + struct nlmsghdr n; + struct ndmsg ndm; + char buf[256]; + } req; + int dst_alen; + struct zebra_if *zif; + struct interface *br_if; + struct zebra_if *br_zif; + char buf[ETHER_ADDR_STRLEN]; + int vid_present = 0, dst_present = 0; + char vid_buf[20]; + char dst_buf[30]; + + zif = ifp->info; + if ((br_if = zif->brslave_info.br_if) == NULL) { + zlog_warn("MAC %s on IF %s(%u) - no mapping to bridge", + (cmd == RTM_NEWNEIGH) ? "add" : "del", ifp->name, + ifp->ifindex); + return -1; + } + + memset(&req.n, 0, sizeof(req.n)); + memset(&req.ndm, 0, sizeof(req.ndm)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); + req.n.nlmsg_flags = NLM_F_REQUEST; + if (cmd == RTM_NEWNEIGH) + req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE); + req.n.nlmsg_type = cmd; + req.ndm.ndm_family = AF_BRIDGE; + req.ndm.ndm_flags |= NTF_SELF | NTF_MASTER; + req.ndm.ndm_state = NUD_REACHABLE; + + if (sticky) + req.ndm.ndm_state |= NUD_NOARP; + else + req.ndm.ndm_flags |= NTF_EXT_LEARNED; + + addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6); + req.ndm.ndm_ifindex = ifp->ifindex; + if (!local) { + dst_alen = 4; // TODO: hardcoded + addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip, dst_alen); + dst_present = 1; + sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip)); + } + br_zif = (struct zebra_if *)br_if->info; + if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0) { + addattr16(&req.n, sizeof(req), NDA_VLAN, vid); + vid_present = 1; + sprintf(vid_buf, " VLAN %u", vid); + } + addattr32(&req.n, sizeof(req), NDA_MASTER, br_if->ifindex); + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s%s", + nl_msg_type_to_str(cmd), + nl_family_to_str(req.ndm.ndm_family), ifp->name, + ifp->ifindex, vid_present ? vid_buf : "", + sticky ? "sticky " : "", + prefix_mac2str(mac, buf, sizeof(buf)), + dst_present ? dst_buf : ""); + + return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, + 0); } -#define NUD_VALID (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE | \ - NUD_PROBE | NUD_STALE | NUD_DELAY) +#define NUD_VALID \ + (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE | NUD_PROBE | NUD_STALE \ + | NUD_DELAY) -static int -netlink_ipneigh_change (struct sockaddr_nl *snl, struct nlmsghdr *h, int len) +static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h, + int len) { - struct ndmsg *ndm; - struct interface *ifp; - struct zebra_if *zif; - struct zebra_vrf *zvrf; - struct rtattr *tb[NDA_MAX + 1]; - struct interface *link_if; - struct ethaddr mac; - struct ipaddr ip; - char buf[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; - int mac_present = 0; - u_char ext_learned; - - ndm = NLMSG_DATA (h); - - /* The interface should exist. */ - ifp = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT), ndm->ndm_ifindex); - if (!ifp) - return 0; - - /* Locate VRF corresponding to interface. We only process neigh notifications - * if EVPN is enabled on this VRF. - */ - zvrf = vrf_info_lookup(ifp->vrf_id); - if (!zvrf || !EVPN_ENABLED(zvrf)) - return 0; - if (!ifp->info) - return 0; - - /* Drop "permanent" entries. */ - if (ndm->ndm_state & NUD_PERMANENT) - return 0; - - zif = (struct zebra_if *)ifp->info; - /* The neighbor is present on an SVI. From this, we locate the underlying - * bridge because we're only interested in neighbors on a VxLAN bridge. - * The bridge is located based on the nature of the SVI: - * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface - * and is linked to the bridge - * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface - * itself - */ - if (IS_ZEBRA_IF_VLAN(ifp)) - { - link_if = zif->link; - if (!link_if) - return 0; - } - else if (IS_ZEBRA_IF_BRIDGE(ifp)) - link_if = ifp; - else - return 0; - - /* Parse attributes and extract fields of interest. */ - memset (tb, 0, sizeof tb); - netlink_parse_rtattr (tb, NDA_MAX, NDA_RTA (ndm), len); - - if (!tb[NDA_DST]) - { - zlog_warn ("%s family %s IF %s(%u) - no DST", - nl_msg_type_to_str (h->nlmsg_type), - nl_family_to_str (ndm->ndm_family), - ifp->name, ndm->ndm_ifindex); - return 0; - } - memset (&mac, 0, sizeof (struct ethaddr)); - memset (&ip, 0, sizeof (struct ipaddr)); - ip.ipa_type = (ndm->ndm_family == AF_INET) ? IPADDR_V4 : IPADDR_V6; - memcpy (&ip.ip.addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST])); - - if (h->nlmsg_type == RTM_NEWNEIGH) - { - if (tb[NDA_LLADDR]) - { - if (RTA_PAYLOAD (tb[NDA_LLADDR]) != ETHER_ADDR_LEN) - { - zlog_warn ("%s family %s IF %s(%u) - LLADDR is not MAC, len %ld", - nl_msg_type_to_str (h->nlmsg_type), - nl_family_to_str (ndm->ndm_family), - ifp->name, ndm->ndm_ifindex, - RTA_PAYLOAD (tb[NDA_LLADDR])); - return 0; - } - - mac_present = 1; - memcpy (&mac, RTA_DATA (tb[NDA_LLADDR]), ETHER_ADDR_LEN); - } - - ext_learned = (ndm->ndm_flags & NTF_EXT_LEARNED) ? 1 : 0; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("Rx %s family %s IF %s(%u) IP %s MAC %s state 0x%x flags 0x%x", - nl_msg_type_to_str (h->nlmsg_type), - nl_family_to_str (ndm->ndm_family), - ifp->name, ndm->ndm_ifindex, - ipaddr2str (&ip, buf2, sizeof(buf2)), - mac_present ? prefix_mac2str (&mac, buf, sizeof (buf)) : "", - ndm->ndm_state, ndm->ndm_flags); - - /* If the neighbor state is valid for use, process as an add or update - * else process as a delete. Note that the delete handling may result - * in re-adding the neighbor if it is a valid "remote" neighbor. - */ - if (ndm->ndm_state & NUD_VALID) - return zebra_vxlan_local_neigh_add_update (ifp, link_if, - &ip, &mac, - ndm->ndm_state, ext_learned); - - return zebra_vxlan_local_neigh_del (ifp, link_if, &ip); - } - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("Rx %s family %s IF %s(%u) IP %s", - nl_msg_type_to_str (h->nlmsg_type), - nl_family_to_str (ndm->ndm_family), - ifp->name, ndm->ndm_ifindex, - ipaddr2str (&ip, buf2, sizeof(buf2))); - - /* Process the delete - it may result in re-adding the neighbor if it is - * a valid "remote" neighbor. - */ - return zebra_vxlan_local_neigh_del (ifp, link_if, &ip); + struct ndmsg *ndm; + struct interface *ifp; + struct zebra_if *zif; + struct zebra_vrf *zvrf; + struct rtattr *tb[NDA_MAX + 1]; + struct interface *link_if; + struct ethaddr mac; + struct ipaddr ip; + char buf[ETHER_ADDR_STRLEN]; + char buf2[INET6_ADDRSTRLEN]; + int mac_present = 0; + u_char ext_learned; + + ndm = NLMSG_DATA(h); + + /* The interface should exist. */ + ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), + ndm->ndm_ifindex); + if (!ifp) + return 0; + + /* Locate VRF corresponding to interface. We only process neigh + * notifications + * if EVPN is enabled on this VRF. + */ + zvrf = vrf_info_lookup(ifp->vrf_id); + if (!zvrf || !EVPN_ENABLED(zvrf)) + return 0; + if (!ifp->info) + return 0; + + /* Drop "permanent" entries. */ + if (ndm->ndm_state & NUD_PERMANENT) + return 0; + + zif = (struct zebra_if *)ifp->info; + /* The neighbor is present on an SVI. From this, we locate the + * underlying + * bridge because we're only interested in neighbors on a VxLAN bridge. + * The bridge is located based on the nature of the SVI: + * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN + * interface + * and is linked to the bridge + * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge + * inteface + * itself + */ + if (IS_ZEBRA_IF_VLAN(ifp)) { + link_if = zif->link; + if (!link_if) + return 0; + } else if (IS_ZEBRA_IF_BRIDGE(ifp)) + link_if = ifp; + else + return 0; + + /* Parse attributes and extract fields of interest. */ + memset(tb, 0, sizeof tb); + netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len); + + if (!tb[NDA_DST]) { + zlog_warn("%s family %s IF %s(%u) - no DST", + nl_msg_type_to_str(h->nlmsg_type), + nl_family_to_str(ndm->ndm_family), ifp->name, + ndm->ndm_ifindex); + return 0; + } + memset(&mac, 0, sizeof(struct ethaddr)); + memset(&ip, 0, sizeof(struct ipaddr)); + ip.ipa_type = (ndm->ndm_family == AF_INET) ? IPADDR_V4 : IPADDR_V6; + memcpy(&ip.ip.addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST])); + + if (h->nlmsg_type == RTM_NEWNEIGH) { + if (tb[NDA_LLADDR]) { + if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETHER_ADDR_LEN) { + zlog_warn( + "%s family %s IF %s(%u) - LLADDR is not MAC, len %ld", + nl_msg_type_to_str(h->nlmsg_type), + nl_family_to_str(ndm->ndm_family), + ifp->name, ndm->ndm_ifindex, + RTA_PAYLOAD(tb[NDA_LLADDR])); + return 0; + } + + mac_present = 1; + memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), ETHER_ADDR_LEN); + } + + ext_learned = (ndm->ndm_flags & NTF_EXT_LEARNED) ? 1 : 0; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "Rx %s family %s IF %s(%u) IP %s MAC %s state 0x%x flags 0x%x", + nl_msg_type_to_str(h->nlmsg_type), + nl_family_to_str(ndm->ndm_family), ifp->name, + ndm->ndm_ifindex, + ipaddr2str(&ip, buf2, sizeof(buf2)), + mac_present + ? prefix_mac2str(&mac, buf, sizeof(buf)) + : "", + ndm->ndm_state, ndm->ndm_flags); + + /* If the neighbor state is valid for use, process as an add or + * update + * else process as a delete. Note that the delete handling may + * result + * in re-adding the neighbor if it is a valid "remote" neighbor. + */ + if (ndm->ndm_state & NUD_VALID) + return zebra_vxlan_local_neigh_add_update( + ifp, link_if, &ip, &mac, ndm->ndm_state, + ext_learned); + + return zebra_vxlan_local_neigh_del(ifp, link_if, &ip); + } + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("Rx %s family %s IF %s(%u) IP %s", + nl_msg_type_to_str(h->nlmsg_type), + nl_family_to_str(ndm->ndm_family), ifp->name, + ndm->ndm_ifindex, + ipaddr2str(&ip, buf2, sizeof(buf2))); + + /* Process the delete - it may result in re-adding the neighbor if it is + * a valid "remote" neighbor. + */ + return zebra_vxlan_local_neigh_del(ifp, link_if, &ip); } -static int -netlink_neigh_table (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup) +static int netlink_neigh_table(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup) { - int len; - struct ndmsg *ndm; + int len; + struct ndmsg *ndm; - if (h->nlmsg_type != RTM_NEWNEIGH) - return 0; + if (h->nlmsg_type != RTM_NEWNEIGH) + return 0; - /* Length validity. */ - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ndmsg)); - if (len < 0) - return -1; + /* Length validity. */ + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg)); + if (len < 0) + return -1; - /* We are interested only in AF_INET or AF_INET6 notifications. */ - ndm = NLMSG_DATA (h); - if (ndm->ndm_family != AF_INET && ndm->ndm_family != AF_INET6) - return 0; + /* We are interested only in AF_INET or AF_INET6 notifications. */ + ndm = NLMSG_DATA(h); + if (ndm->ndm_family != AF_INET && ndm->ndm_family != AF_INET6) + return 0; - return netlink_neigh_change (snl, h, len); + return netlink_neigh_change(snl, h, len); } /* Request for IP neighbor information from the kernel */ -static int -netlink_request_neigh (struct zebra_ns *zns, int family, int type, - ifindex_t ifindex) +static int netlink_request_neigh(struct zebra_ns *zns, int family, int type, + ifindex_t ifindex) { - struct - { - struct nlmsghdr n; - struct ndmsg ndm; - char buf[256]; - } req; - - /* Form the request, specifying filter (rtattr) if needed. */ - memset (&req, 0, sizeof (req)); - req.n.nlmsg_type = type; - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); - req.ndm.ndm_family = family; - if (ifindex) - addattr32 (&req.n, sizeof(req), NDA_IFINDEX, ifindex); - - return netlink_request (&zns->netlink_cmd, &req.n); + struct { + struct nlmsghdr n; + struct ndmsg ndm; + char buf[256]; + } req; + + /* Form the request, specifying filter (rtattr) if needed. */ + memset(&req, 0, sizeof(req)); + req.n.nlmsg_type = type; + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); + req.ndm.ndm_family = family; + if (ifindex) + addattr32(&req.n, sizeof(req), NDA_IFINDEX, ifindex); + + return netlink_request(&zns->netlink_cmd, &req.n); } /* * IP Neighbor table read using netlink interface. This is invoked * at startup. */ -int -netlink_neigh_read (struct zebra_ns *zns) +int netlink_neigh_read(struct zebra_ns *zns) { - int ret; + int ret; - /* Get IP neighbor table. */ - ret = netlink_request_neigh (zns, AF_UNSPEC, RTM_GETNEIGH, 0); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_neigh_table, &zns->netlink_cmd, zns, 0, 1); + /* Get IP neighbor table. */ + ret = netlink_request_neigh(zns, AF_UNSPEC, RTM_GETNEIGH, 0); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, zns, 0, + 1); - return ret; + return ret; } /* * IP Neighbor table read using netlink interface. This is for a specific * VLAN device. */ -int -netlink_neigh_read_for_vlan (struct zebra_ns *zns, struct interface *vlan_if) +int netlink_neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if) { - int ret = 0; + int ret = 0; - ret = netlink_request_neigh (zns, AF_UNSPEC, RTM_GETNEIGH, vlan_if->ifindex); - if (ret < 0) - return ret; - ret = netlink_parse_info (netlink_neigh_table, &zns->netlink_cmd, zns, 0, 0); + ret = netlink_request_neigh(zns, AF_UNSPEC, RTM_GETNEIGH, + vlan_if->ifindex); + if (ret < 0) + return ret; + ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, zns, 0, + 0); - return ret; + return ret; } -int -netlink_neigh_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id) +int netlink_neigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id) { - int len; - struct ndmsg *ndm; + int len; + struct ndmsg *ndm; - if (!(h->nlmsg_type == RTM_NEWNEIGH || h->nlmsg_type == RTM_DELNEIGH)) - return 0; + if (!(h->nlmsg_type == RTM_NEWNEIGH || h->nlmsg_type == RTM_DELNEIGH)) + return 0; - /* Length validity. */ - len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ndmsg)); - if (len < 0) - return -1; + /* Length validity. */ + len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ndmsg)); + if (len < 0) + return -1; - /* Is this a notification for the MAC FDB or IP neighbor table? */ - ndm = NLMSG_DATA (h); - if (ndm->ndm_family == AF_BRIDGE) - return netlink_macfdb_change (snl, h, len); + /* Is this a notification for the MAC FDB or IP neighbor table? */ + ndm = NLMSG_DATA(h); + if (ndm->ndm_family == AF_BRIDGE) + return netlink_macfdb_change(snl, h, len); - if (ndm->ndm_type != RTN_UNICAST) - return 0; + if (ndm->ndm_type != RTN_UNICAST) + return 0; - if (ndm->ndm_family == AF_INET || ndm->ndm_family == AF_INET6) - return netlink_ipneigh_change (snl, h, len); + if (ndm->ndm_family == AF_INET || ndm->ndm_family == AF_INET6) + return netlink_ipneigh_change(snl, h, len); - return 0; + return 0; } -static int -netlink_neigh_update2 (struct interface *ifp, struct ipaddr *ip, - struct ethaddr *mac, u_int32_t flags, int cmd) +static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip, + struct ethaddr *mac, u_int32_t flags, int cmd) { - struct { - struct nlmsghdr n; - struct ndmsg ndm; - char buf[256]; - } req; - int ipa_len; - - struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); - char buf[INET6_ADDRSTRLEN]; - char buf2[ETHER_ADDR_STRLEN]; - - memset(&req.n, 0, sizeof(req.n)); - memset(&req.ndm, 0, sizeof(req.ndm)); - - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); - req.n.nlmsg_flags = NLM_F_REQUEST; - if (cmd == RTM_NEWNEIGH) - req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE); - req.n.nlmsg_type = cmd; //RTM_NEWNEIGH or RTM_DELNEIGH - req.ndm.ndm_family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6; - req.ndm.ndm_state = flags; - req.ndm.ndm_ifindex = ifp->ifindex; - req.ndm.ndm_type = RTN_UNICAST; - req.ndm.ndm_flags = NTF_EXT_LEARNED; - - - ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN; - addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len); - if (mac) - addattr_l (&req.n, sizeof (req), NDA_LLADDR, mac, 6); - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("Tx %s family %s IF %s(%u) Neigh %s MAC %s", - nl_msg_type_to_str (cmd), - nl_family_to_str (req.ndm.ndm_family), - ifp->name, ifp->ifindex, - ipaddr2str (ip, buf, sizeof(buf)), - mac ? prefix_mac2str (mac, buf2, sizeof (buf2)) : "null"); - - return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); + struct { + struct nlmsghdr n; + struct ndmsg ndm; + char buf[256]; + } req; + int ipa_len; + + struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + char buf[INET6_ADDRSTRLEN]; + char buf2[ETHER_ADDR_STRLEN]; + + memset(&req.n, 0, sizeof(req.n)); + memset(&req.ndm, 0, sizeof(req.ndm)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); + req.n.nlmsg_flags = NLM_F_REQUEST; + if (cmd == RTM_NEWNEIGH) + req.n.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE); + req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH + req.ndm.ndm_family = IS_IPADDR_V4(ip) ? AF_INET : AF_INET6; + req.ndm.ndm_state = flags; + req.ndm.ndm_ifindex = ifp->ifindex; + req.ndm.ndm_type = RTN_UNICAST; + req.ndm.ndm_flags = NTF_EXT_LEARNED; + + + ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN; + addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len); + if (mac) + addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6); + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("Tx %s family %s IF %s(%u) Neigh %s MAC %s", + nl_msg_type_to_str(cmd), + nl_family_to_str(req.ndm.ndm_family), ifp->name, + ifp->ifindex, ipaddr2str(ip, buf, sizeof(buf)), + mac ? prefix_mac2str(mac, buf2, sizeof(buf2)) + : "null"); + + return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, + 0); } -int -kernel_add_mac (struct interface *ifp, vlanid_t vid, - struct ethaddr *mac, struct in_addr vtep_ip, - u_char sticky) +int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, + struct in_addr vtep_ip, u_char sticky) { - return netlink_macfdb_update (ifp, vid, mac, vtep_ip, 0, RTM_NEWNEIGH, sticky); + return netlink_macfdb_update(ifp, vid, mac, vtep_ip, 0, RTM_NEWNEIGH, + sticky); } -int -kernel_del_mac (struct interface *ifp, vlanid_t vid, - struct ethaddr *mac, struct in_addr vtep_ip, int local) +int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, + struct in_addr vtep_ip, int local) { - return netlink_macfdb_update (ifp, vid, mac, vtep_ip, local, RTM_DELNEIGH, 0); + return netlink_macfdb_update(ifp, vid, mac, vtep_ip, local, + RTM_DELNEIGH, 0); } -int kernel_add_neigh (struct interface *ifp, struct ipaddr *ip, - struct ethaddr *mac) +int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip, + struct ethaddr *mac) { - return netlink_neigh_update2 (ifp, ip, mac, NUD_REACHABLE, - RTM_NEWNEIGH); + return netlink_neigh_update2(ifp, ip, mac, NUD_REACHABLE, RTM_NEWNEIGH); } -int kernel_del_neigh (struct interface *ifp, struct ipaddr *ip) +int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip) { - return netlink_neigh_update2 (ifp, ip, NULL, 0, RTM_DELNEIGH); + return netlink_neigh_update2(ifp, ip, NULL, 0, RTM_DELNEIGH); } /* * MPLS label forwarding table change via netlink interface. */ -int -netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp) +int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) { - mpls_lse_t lse; - zebra_nhlfe_t *nhlfe; - struct nexthop *nexthop = NULL; - unsigned int nexthop_num; - const char *routedesc; - struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); - - struct - { - struct nlmsghdr n; - struct rtmsg r; - char buf[NL_PKT_BUF_SIZE]; - } req; - - memset (&req, 0, sizeof req - NL_PKT_BUF_SIZE); - - - /* - * Count # nexthops so we can decide whether to use singlepath - * or multipath case. - */ - nexthop_num = 0; - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - nexthop = nhlfe->nexthop; - if (!nexthop) - continue; - if (cmd == RTM_NEWROUTE) - { - /* Count all selected NHLFEs */ - if (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - nexthop_num++; - } - else /* DEL */ - { - /* Count all installed NHLFEs */ - if (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - nexthop_num++; - } - } - - if (nexthop_num == 0) // unexpected - return 0; - - req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg)); - req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; - req.n.nlmsg_type = cmd; - req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; - - req.r.rtm_family = AF_MPLS; - req.r.rtm_table = RT_TABLE_MAIN; - req.r.rtm_dst_len = MPLS_LABEL_LEN_BITS; - req.r.rtm_protocol = RTPROT_ZEBRA; - req.r.rtm_scope = RT_SCOPE_UNIVERSE; - req.r.rtm_type = RTN_UNICAST; - - if (cmd == RTM_NEWROUTE) - /* We do a replace to handle update. */ - req.n.nlmsg_flags |= NLM_F_REPLACE; - - /* Fill destination */ - lse = mpls_lse_encode (lsp->ile.in_label, 0, 0, 1); - addattr_l (&req.n, sizeof req, RTA_DST, &lse, sizeof(mpls_lse_t)); - - /* Fill nexthops (paths) based on single-path or multipath. The paths - * chosen depend on the operation. - */ - if (nexthop_num == 1 || multipath_num == 1) - { - routedesc = "single hop"; - _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); - - nexthop_num = 0; - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - nexthop = nhlfe->nexthop; - if (!nexthop) - continue; - - if ((cmd == RTM_NEWROUTE && - (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))) || - (cmd == RTM_DELROUTE && - (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))) - { - /* Add the gateway */ - _netlink_mpls_build_singlepath(routedesc, nhlfe, - &req.n, &req.r, sizeof req, cmd); - if (cmd == RTM_NEWROUTE) - { - SET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - else - { - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - nexthop_num++; - break; - } - } - } - else /* Multipath case */ - { - char buf[NL_PKT_BUF_SIZE]; - struct rtattr *rta = (void *) buf; - struct rtnexthop *rtnh; - union g_addr *src1 = NULL; - - rta->rta_type = RTA_MULTIPATH; - rta->rta_len = RTA_LENGTH (0); - rtnh = RTA_DATA (rta); - - routedesc = "multihop"; - _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); - - nexthop_num = 0; - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - nexthop = nhlfe->nexthop; - if (!nexthop) - continue; - - if (nexthop_num >= multipath_num) - break; - - if ((cmd == RTM_NEWROUTE && - (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))) || - (cmd == RTM_DELROUTE && - (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))) - { - nexthop_num++; - - /* Build the multipath */ - _netlink_mpls_build_multipath(routedesc, nhlfe, rta, - rtnh, &req.r, &src1); - rtnh = RTNH_NEXT (rtnh); - - if (cmd == RTM_NEWROUTE) - { - SET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - else - { - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - - } - } - - /* Add the multipath */ - if (rta->rta_len > RTA_LENGTH (0)) - addattr_l (&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, RTA_DATA (rta), - RTA_PAYLOAD (rta)); - } - - /* Talk to netlink socket. */ - return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); + mpls_lse_t lse; + zebra_nhlfe_t *nhlfe; + struct nexthop *nexthop = NULL; + unsigned int nexthop_num; + const char *routedesc; + struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + + struct { + struct nlmsghdr n; + struct rtmsg r; + char buf[NL_PKT_BUF_SIZE]; + } req; + + memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE); + + + /* + * Count # nexthops so we can decide whether to use singlepath + * or multipath case. + */ + nexthop_num = 0; + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + nexthop = nhlfe->nexthop; + if (!nexthop) + continue; + if (cmd == RTM_NEWROUTE) { + /* Count all selected NHLFEs */ + if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED) + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + nexthop_num++; + } else /* DEL */ + { + /* Count all installed NHLFEs */ + if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED) + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) + nexthop_num++; + } + } + + if (nexthop_num == 0) // unexpected + return 0; + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; + req.n.nlmsg_type = cmd; + req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; + + req.r.rtm_family = AF_MPLS; + req.r.rtm_table = RT_TABLE_MAIN; + req.r.rtm_dst_len = MPLS_LABEL_LEN_BITS; + req.r.rtm_protocol = RTPROT_ZEBRA; + req.r.rtm_scope = RT_SCOPE_UNIVERSE; + req.r.rtm_type = RTN_UNICAST; + + if (cmd == RTM_NEWROUTE) + /* We do a replace to handle update. */ + req.n.nlmsg_flags |= NLM_F_REPLACE; + + /* Fill destination */ + lse = mpls_lse_encode(lsp->ile.in_label, 0, 0, 1); + addattr_l(&req.n, sizeof req, RTA_DST, &lse, sizeof(mpls_lse_t)); + + /* Fill nexthops (paths) based on single-path or multipath. The paths + * chosen depend on the operation. + */ + if (nexthop_num == 1 || multipath_num == 1) { + routedesc = "single hop"; + _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); + + nexthop_num = 0; + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + nexthop = nhlfe->nexthop; + if (!nexthop) + continue; + + if ((cmd == RTM_NEWROUTE + && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED) + && CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_ACTIVE))) + || (cmd == RTM_DELROUTE + && (CHECK_FLAG(nhlfe->flags, + NHLFE_FLAG_INSTALLED) + && CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB)))) { + /* Add the gateway */ + _netlink_mpls_build_singlepath(routedesc, nhlfe, + &req.n, &req.r, + sizeof req, cmd); + if (cmd == RTM_NEWROUTE) { + SET_FLAG(nhlfe->flags, + NHLFE_FLAG_INSTALLED); + SET_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB); + } else { + UNSET_FLAG(nhlfe->flags, + NHLFE_FLAG_INSTALLED); + UNSET_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB); + } + nexthop_num++; + break; + } + } + } else /* Multipath case */ + { + char buf[NL_PKT_BUF_SIZE]; + struct rtattr *rta = (void *)buf; + struct rtnexthop *rtnh; + union g_addr *src1 = NULL; + + rta->rta_type = RTA_MULTIPATH; + rta->rta_len = RTA_LENGTH(0); + rtnh = RTA_DATA(rta); + + routedesc = "multihop"; + _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); + + nexthop_num = 0; + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + nexthop = nhlfe->nexthop; + if (!nexthop) + continue; + + if (nexthop_num >= multipath_num) + break; + + if ((cmd == RTM_NEWROUTE + && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED) + && CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_ACTIVE))) + || (cmd == RTM_DELROUTE + && (CHECK_FLAG(nhlfe->flags, + NHLFE_FLAG_INSTALLED) + && CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB)))) { + nexthop_num++; + + /* Build the multipath */ + _netlink_mpls_build_multipath(routedesc, nhlfe, + rta, rtnh, &req.r, + &src1); + rtnh = RTNH_NEXT(rtnh); + + if (cmd == RTM_NEWROUTE) { + SET_FLAG(nhlfe->flags, + NHLFE_FLAG_INSTALLED); + SET_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB); + } else { + UNSET_FLAG(nhlfe->flags, + NHLFE_FLAG_INSTALLED); + UNSET_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB); + } + } + } + + /* Add the multipath */ + if (rta->rta_len > RTA_LENGTH(0)) + addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH, + RTA_DATA(rta), RTA_PAYLOAD(rta)); + } + + /* Talk to netlink socket. */ + return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, + 0); } /* * Handle failure in LSP install, clear flags for NHLFE. */ -void -clear_nhlfe_installed (zebra_lsp_t *lsp) +void clear_nhlfe_installed(zebra_lsp_t *lsp) { - zebra_nhlfe_t *nhlfe; - struct nexthop *nexthop; - - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - nexthop = nhlfe->nexthop; - if (!nexthop) - continue; - - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } + zebra_nhlfe_t *nhlfe; + struct nexthop *nexthop; + + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + nexthop = nhlfe->nexthop; + if (!nexthop) + continue; + + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED); + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + } } diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h index 8b061fc2e..e607dda6f 100644 --- a/zebra/rt_netlink.h +++ b/zebra/rt_netlink.h @@ -40,25 +40,24 @@ #define RTPROT_EIGRP 192 #define RTPROT_LDP 193 -void rt_netlink_init (void); +void rt_netlink_init(void); -extern void -clear_nhlfe_installed (zebra_lsp_t *lsp); -extern int -netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp); +extern void clear_nhlfe_installed(zebra_lsp_t *lsp); +extern int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp); -extern int netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id, int startup); -extern int netlink_route_read (struct zebra_ns *zns); +extern int netlink_route_change(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id, int startup); +extern int netlink_route_read(struct zebra_ns *zns); -extern int netlink_neigh_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id); -extern int netlink_macfdb_read (struct zebra_ns *zns); -extern int netlink_macfdb_read_for_bridge (struct zebra_ns *zns, - struct interface *ifp, struct interface *br_if); -extern int netlink_neigh_read (struct zebra_ns *zns); -extern int netlink_neigh_read_for_vlan (struct zebra_ns *zns, - struct interface *vlan_if); +extern int netlink_neigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h, + ns_id_t ns_id); +extern int netlink_macfdb_read(struct zebra_ns *zns); +extern int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, + struct interface *ifp, + struct interface *br_if); +extern int netlink_neigh_read(struct zebra_ns *zns); +extern int netlink_neigh_read_for_vlan(struct zebra_ns *zns, + struct interface *vlan_if); #endif /* HAVE_NETLINK */ diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index fd8010ca0..827d39870 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -40,316 +40,305 @@ extern struct zebra_privs_t zserv_privs; /* kernel socket export */ -extern int rtm_write (int message, union sockunion *dest, - union sockunion *mask, union sockunion *gate, - union sockunion *mpls, unsigned int index, - int zebra_flags, int metric); +extern int rtm_write(int message, union sockunion *dest, union sockunion *mask, + union sockunion *gate, union sockunion *mpls, + unsigned int index, int zebra_flags, int metric); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN /* Adjust netmask socket length. Return value is a adjusted sin_len value. */ -static int -sin_masklen (struct in_addr mask) +static int sin_masklen(struct in_addr mask) { - char *p, *lim; - int len; - struct sockaddr_in sin; + char *p, *lim; + int len; + struct sockaddr_in sin; - if (mask.s_addr == 0) - return sizeof (long); + if (mask.s_addr == 0) + return sizeof(long); - sin.sin_addr = mask; - len = sizeof (struct sockaddr_in); + sin.sin_addr = mask; + len = sizeof(struct sockaddr_in); - lim = (char *) &sin.sin_addr; - p = lim + sizeof (sin.sin_addr); + lim = (char *)&sin.sin_addr; + p = lim + sizeof(sin.sin_addr); - while (*--p == 0 && p >= lim) - len--; - return len; + while (*--p == 0 && p >= lim) + len--; + return len; } #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ /* Interface between zebra message and rtm message. */ -static int -kernel_rtm_ipv4 (int cmd, struct prefix *p, struct route_entry *re) +static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct route_entry *re) { - struct sockaddr_in *mask = NULL; - struct sockaddr_in sin_dest, sin_mask, sin_gate; + struct sockaddr_in *mask = NULL; + struct sockaddr_in sin_dest, sin_mask, sin_gate; #ifdef __OpenBSD__ - struct sockaddr_mpls smpls; + struct sockaddr_mpls smpls; #endif - union sockunion *smplsp = NULL; - struct nexthop *nexthop; - int nexthop_num = 0; - ifindex_t ifindex = 0; - int gate = 0; - int error; - char prefix_buf[PREFIX_STRLEN]; - - if (IS_ZEBRA_DEBUG_RIB) - prefix2str (p, prefix_buf, sizeof(prefix_buf)); - memset (&sin_dest, 0, sizeof (struct sockaddr_in)); - sin_dest.sin_family = AF_INET; + union sockunion *smplsp = NULL; + struct nexthop *nexthop; + int nexthop_num = 0; + ifindex_t ifindex = 0; + int gate = 0; + int error; + char prefix_buf[PREFIX_STRLEN]; + + if (IS_ZEBRA_DEBUG_RIB) + prefix2str(p, prefix_buf, sizeof(prefix_buf)); + memset(&sin_dest, 0, sizeof(struct sockaddr_in)); + sin_dest.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin_dest.sin_len = sizeof (struct sockaddr_in); + sin_dest.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - sin_dest.sin_addr = p->u.prefix4; + sin_dest.sin_addr = p->u.prefix4; - memset (&sin_mask, 0, sizeof (struct sockaddr_in)); + memset(&sin_mask, 0, sizeof(struct sockaddr_in)); - memset (&sin_gate, 0, sizeof (struct sockaddr_in)); - sin_gate.sin_family = AF_INET; + memset(&sin_gate, 0, sizeof(struct sockaddr_in)); + sin_gate.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin_gate.sin_len = sizeof (struct sockaddr_in); + sin_gate.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - /* Make gateway. */ - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; - - gate = 0; - char gate_buf[INET_ADDRSTRLEN] = "NULL"; - - /* - * XXX We need to refrain from kernel operations in some cases, - * but this if statement seems overly cautious - what about - * other than ADD and DELETE? - */ - if ((cmd == RTM_ADD - && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - || (cmd == RTM_DELETE - && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) - )) - { - if (nexthop->type == NEXTHOP_TYPE_IPV4 || - nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - { - sin_gate.sin_addr = nexthop->gate.ipv4; - gate = 1; - } - if (nexthop->type == NEXTHOP_TYPE_IFINDEX - || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - ifindex = nexthop->ifindex; - if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) - { - struct in_addr loopback; - loopback.s_addr = htonl (INADDR_LOOPBACK); - sin_gate.sin_addr = loopback; - gate = 1; - } - - if (gate && p->prefixlen == 32) - mask = NULL; - else - { - masklen2ip (p->prefixlen, &sin_mask.sin_addr); - sin_mask.sin_family = AF_INET; + /* Make gateway. */ + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + continue; + + gate = 0; + char gate_buf[INET_ADDRSTRLEN] = "NULL"; + + /* + * XXX We need to refrain from kernel operations in some cases, + * but this if statement seems overly cautious - what about + * other than ADD and DELETE? + */ + if ((cmd == RTM_ADD + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + || (cmd == RTM_DELETE + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))) { + if (nexthop->type == NEXTHOP_TYPE_IPV4 + || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { + sin_gate.sin_addr = nexthop->gate.ipv4; + gate = 1; + } + if (nexthop->type == NEXTHOP_TYPE_IFINDEX + || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) + ifindex = nexthop->ifindex; + if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) { + struct in_addr loopback; + loopback.s_addr = htonl(INADDR_LOOPBACK); + sin_gate.sin_addr = loopback; + gate = 1; + } + + if (gate && p->prefixlen == 32) + mask = NULL; + else { + masklen2ip(p->prefixlen, &sin_mask.sin_addr); + sin_mask.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin_mask.sin_len = sin_masklen (sin_mask.sin_addr); + sin_mask.sin_len = + sin_masklen(sin_mask.sin_addr); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - mask = &sin_mask; - } + mask = &sin_mask; + } #ifdef __OpenBSD__ - if (nexthop->nh_label) - { - memset (&smpls, 0, sizeof (smpls)); - smpls.smpls_len = sizeof (smpls); - smpls.smpls_family = AF_MPLS; - smpls.smpls_label = - htonl (nexthop->nh_label->label[0] << MPLS_LABEL_OFFSET); - smplsp = (union sockunion *)&smpls; - } + if (nexthop->nh_label) { + memset(&smpls, 0, sizeof(smpls)); + smpls.smpls_len = sizeof(smpls); + smpls.smpls_family = AF_MPLS; + smpls.smpls_label = + htonl(nexthop->nh_label->label[0] + << MPLS_LABEL_OFFSET); + smplsp = (union sockunion *)&smpls; + } #endif - error = rtm_write (cmd, - (union sockunion *)&sin_dest, - (union sockunion *)mask, - gate ? (union sockunion *)&sin_gate : NULL, - smplsp, - ifindex, - re->flags, - re->metric); - - if (IS_ZEBRA_DEBUG_RIB) - { - if (!gate) - { - zlog_debug ("%s: %s: attention! gate not found for re %p", - __func__, prefix_buf, re); - route_entry_dump (p, NULL, re); - } - else - inet_ntop (AF_INET, &sin_gate.sin_addr, gate_buf, INET_ADDRSTRLEN); - } - - switch (error) - { - /* We only flag nexthops as being in FIB if rtm_write() did its work. */ - case ZEBRA_ERR_NOERROR: - nexthop_num++; - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug ("%s: %s: successfully did NH %s", - __func__, prefix_buf, gate_buf); - if (cmd == RTM_ADD) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - break; - - /* The only valid case for this error is kernel's failure to install - * a multipath route, which is common for FreeBSD. This should be - * ignored silently, but logged as an error otherwise. - */ - case ZEBRA_ERR_RTEXIST: - if (cmd != RTM_ADD) - zlog_err ("%s: rtm_write() returned %d for command %d", - __func__, error, cmd); - continue; - break; - - /* Given that our NEXTHOP_FLAG_FIB matches real kernel FIB, it isn't - * normal to get any other messages in ANY case. - */ - case ZEBRA_ERR_RTNOEXIST: - case ZEBRA_ERR_RTUNREACH: - default: - zlog_err ("%s: %s: rtm_write() unexpectedly returned %d for command %s", - __func__, prefix2str(p, prefix_buf, sizeof(prefix_buf)), - error, lookup_msg(rtm_type_str, cmd, NULL)); - break; - } - } /* if (cmd and flags make sense) */ - else - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug ("%s: odd command %s for flags %d", - __func__, lookup_msg(rtm_type_str, cmd, NULL), nexthop->flags); - } /* for (ALL_NEXTHOPS(...))*/ - - /* If there was no useful nexthop, then complain. */ - if (nexthop_num == 0 && IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: No useful nexthops were found in RIB entry %p", __func__, re); - - return 0; /*XXX*/ + error = rtm_write( + cmd, (union sockunion *)&sin_dest, + (union sockunion *)mask, + gate ? (union sockunion *)&sin_gate : NULL, + smplsp, ifindex, re->flags, re->metric); + + if (IS_ZEBRA_DEBUG_RIB) { + if (!gate) { + zlog_debug( + "%s: %s: attention! gate not found for re %p", + __func__, prefix_buf, re); + route_entry_dump(p, NULL, re); + } else + inet_ntop(AF_INET, &sin_gate.sin_addr, + gate_buf, INET_ADDRSTRLEN); + } + + switch (error) { + /* We only flag nexthops as being in FIB if rtm_write() + * did its work. */ + case ZEBRA_ERR_NOERROR: + nexthop_num++; + if (IS_ZEBRA_DEBUG_RIB) + zlog_debug( + "%s: %s: successfully did NH %s", + __func__, prefix_buf, gate_buf); + if (cmd == RTM_ADD) + SET_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB); + break; + + /* The only valid case for this error is kernel's + * failure to install + * a multipath route, which is common for FreeBSD. This + * should be + * ignored silently, but logged as an error otherwise. + */ + case ZEBRA_ERR_RTEXIST: + if (cmd != RTM_ADD) + zlog_err( + "%s: rtm_write() returned %d for command %d", + __func__, error, cmd); + continue; + break; + + /* Given that our NEXTHOP_FLAG_FIB matches real kernel + * FIB, it isn't + * normal to get any other messages in ANY case. + */ + case ZEBRA_ERR_RTNOEXIST: + case ZEBRA_ERR_RTUNREACH: + default: + zlog_err( + "%s: %s: rtm_write() unexpectedly returned %d for command %s", + __func__, + prefix2str(p, prefix_buf, + sizeof(prefix_buf)), + error, + lookup_msg(rtm_type_str, cmd, NULL)); + break; + } + } /* if (cmd and flags make sense) */ + else if (IS_ZEBRA_DEBUG_RIB) + zlog_debug("%s: odd command %s for flags %d", __func__, + lookup_msg(rtm_type_str, cmd, NULL), + nexthop->flags); + } /* for (ALL_NEXTHOPS(...))*/ + + /* If there was no useful nexthop, then complain. */ + if (nexthop_num == 0 && IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: No useful nexthops were found in RIB entry %p", + __func__, re); + + return 0; /*XXX*/ } #ifdef SIN6_LEN /* Calculate sin6_len value for netmask socket value. */ -static int -sin6_masklen (struct in6_addr mask) +static int sin6_masklen(struct in6_addr mask) { - struct sockaddr_in6 sin6; - char *p, *lim; - int len; + struct sockaddr_in6 sin6; + char *p, *lim; + int len; - if (IN6_IS_ADDR_UNSPECIFIED (&mask)) - return sizeof (long); + if (IN6_IS_ADDR_UNSPECIFIED(&mask)) + return sizeof(long); - sin6.sin6_addr = mask; - len = sizeof (struct sockaddr_in6); + sin6.sin6_addr = mask; + len = sizeof(struct sockaddr_in6); - lim = (char *) & sin6.sin6_addr; - p = lim + sizeof (sin6.sin6_addr); + lim = (char *)&sin6.sin6_addr; + p = lim + sizeof(sin6.sin6_addr); - while (*--p == 0 && p >= lim) - len--; + while (*--p == 0 && p >= lim) + len--; - return len; + return len; } #endif /* SIN6_LEN */ /* Interface between zebra message and rtm message. */ -static int -kernel_rtm_ipv6 (int cmd, struct prefix *p, struct route_entry *re) +static int kernel_rtm_ipv6(int cmd, struct prefix *p, struct route_entry *re) { - struct sockaddr_in6 *mask; - struct sockaddr_in6 sin_dest, sin_mask, sin_gate; - struct nexthop *nexthop; - int nexthop_num = 0; - ifindex_t ifindex = 0; - int gate = 0; - int error; - - memset (&sin_dest, 0, sizeof (struct sockaddr_in6)); - sin_dest.sin6_family = AF_INET6; + struct sockaddr_in6 *mask; + struct sockaddr_in6 sin_dest, sin_mask, sin_gate; + struct nexthop *nexthop; + int nexthop_num = 0; + ifindex_t ifindex = 0; + int gate = 0; + int error; + + memset(&sin_dest, 0, sizeof(struct sockaddr_in6)); + sin_dest.sin6_family = AF_INET6; #ifdef SIN6_LEN - sin_dest.sin6_len = sizeof (struct sockaddr_in6); + sin_dest.sin6_len = sizeof(struct sockaddr_in6); #endif /* SIN6_LEN */ - sin_dest.sin6_addr = p->u.prefix6; + sin_dest.sin6_addr = p->u.prefix6; - memset (&sin_mask, 0, sizeof (struct sockaddr_in6)); + memset(&sin_mask, 0, sizeof(struct sockaddr_in6)); - memset (&sin_gate, 0, sizeof (struct sockaddr_in6)); - sin_gate.sin6_family = AF_INET6; + memset(&sin_gate, 0, sizeof(struct sockaddr_in6)); + sin_gate.sin6_family = AF_INET6; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin_gate.sin6_len = sizeof (struct sockaddr_in6); + sin_gate.sin6_len = sizeof(struct sockaddr_in6); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - /* Make gateway. */ - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; + /* Make gateway. */ + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + continue; - gate = 0; + gate = 0; - if ((cmd == RTM_ADD - && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - || (cmd == RTM_DELETE + if ((cmd == RTM_ADD + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + || (cmd == RTM_DELETE #if 0 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) #endif - )) - { - if (nexthop->type == NEXTHOP_TYPE_IPV6 - || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - { - sin_gate.sin6_addr = nexthop->gate.ipv6; - gate = 1; - } - if (nexthop->type == NEXTHOP_TYPE_IFINDEX - || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - ifindex = nexthop->ifindex; - - if (cmd == RTM_ADD) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - - /* Under kame set interface index to link local address. */ + )) { + if (nexthop->type == NEXTHOP_TYPE_IPV6 + || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { + sin_gate.sin6_addr = nexthop->gate.ipv6; + gate = 1; + } + if (nexthop->type == NEXTHOP_TYPE_IFINDEX + || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) + ifindex = nexthop->ifindex; + + if (cmd == RTM_ADD) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + } + +/* Under kame set interface index to link local address. */ #ifdef KAME -#define SET_IN6_LINKLOCAL_IFINDEX(a, i) \ - do { \ - (a).s6_addr[2] = ((i) >> 8) & 0xff; \ - (a).s6_addr[3] = (i) & 0xff; \ - } while (0) +#define SET_IN6_LINKLOCAL_IFINDEX(a, i) \ + do { \ + (a).s6_addr[2] = ((i) >> 8) & 0xff; \ + (a).s6_addr[3] = (i)&0xff; \ + } while (0) - if (gate && IN6_IS_ADDR_LINKLOCAL(&sin_gate.sin6_addr)) - SET_IN6_LINKLOCAL_IFINDEX (sin_gate.sin6_addr, ifindex); + if (gate && IN6_IS_ADDR_LINKLOCAL(&sin_gate.sin6_addr)) + SET_IN6_LINKLOCAL_IFINDEX(sin_gate.sin6_addr, ifindex); #endif /* KAME */ - if (gate && p->prefixlen == 128) - mask = NULL; - else - { - masklen2ip6 (p->prefixlen, &sin_mask.sin6_addr); - sin_mask.sin6_family = AF_INET6; + if (gate && p->prefixlen == 128) + mask = NULL; + else { + masklen2ip6(p->prefixlen, &sin_mask.sin6_addr); + sin_mask.sin6_family = AF_INET6; #ifdef SIN6_LEN - sin_mask.sin6_len = sin6_masklen (sin_mask.sin6_addr); + sin_mask.sin6_len = sin6_masklen(sin_mask.sin6_addr); #endif /* SIN6_LEN */ - mask = &sin_mask; - } + mask = &sin_mask; + } - error = rtm_write (cmd, - (union sockunion *) &sin_dest, - (union sockunion *) mask, - gate ? (union sockunion *)&sin_gate : NULL, - NULL, - ifindex, - re->flags, - re->metric); + error = rtm_write(cmd, (union sockunion *)&sin_dest, + (union sockunion *)mask, + gate ? (union sockunion *)&sin_gate : NULL, + NULL, ifindex, re->flags, re->metric); #if 0 if (error) @@ -358,110 +347,99 @@ kernel_rtm_ipv6 (int cmd, struct prefix *p, struct route_entry *re) nexthop_num, error); } #else - (void)error; + (void)error; #endif - nexthop_num++; - } + nexthop_num++; + } - /* If there is no useful nexthop then return. */ - if (nexthop_num == 0) - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("kernel_rtm_ipv6(): No useful nexthop."); - return 0; - } + /* If there is no useful nexthop then return. */ + if (nexthop_num == 0) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("kernel_rtm_ipv6(): No useful nexthop."); + return 0; + } - return 0; /*XXX*/ + return 0; /*XXX*/ } -static int -kernel_rtm (int cmd, struct prefix *p, struct route_entry *re) +static int kernel_rtm(int cmd, struct prefix *p, struct route_entry *re) { - switch (PREFIX_FAMILY(p)) - { - case AF_INET: - return kernel_rtm_ipv4 (cmd, p, re); - case AF_INET6: - return kernel_rtm_ipv6 (cmd, p, re); - } - return 0; + switch (PREFIX_FAMILY(p)) { + case AF_INET: + return kernel_rtm_ipv4(cmd, p, re); + case AF_INET6: + return kernel_rtm_ipv6(cmd, p, re); + } + return 0; } -int -kernel_route_rib (struct prefix *p, struct prefix *src_p, - struct route_entry *old, struct route_entry *new) +int kernel_route_rib(struct prefix *p, struct prefix *src_p, + struct route_entry *old, struct route_entry *new) { - int route = 0; + int route = 0; - if (src_p && src_p->prefixlen) - { - zlog_err ("route add: IPv6 sourcedest routes unsupported!"); - return 1; - } + if (src_p && src_p->prefixlen) { + zlog_err("route add: IPv6 sourcedest routes unsupported!"); + return 1; + } - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err("Can't raise privileges"); + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); - if (old) - route |= kernel_rtm (RTM_DELETE, p, old); + if (old) + route |= kernel_rtm(RTM_DELETE, p, old); - if (new) - route |= kernel_rtm (RTM_ADD, p, new); + if (new) + route |= kernel_rtm(RTM_ADD, p, new); - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err("Can't lower privileges"); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); - return route; + return route; } -int -kernel_neigh_update (int add, int ifindex, uint32_t addr, char *lla, int llalen) +int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla, + int llalen) { - /* TODO */ - return 0; + /* TODO */ + return 0; } -extern int -kernel_get_ipmr_sg_stats (void *mroute) +extern int kernel_get_ipmr_sg_stats(void *mroute) { - return 0; + return 0; } -int -kernel_add_vtep (vni_t vni, struct interface *ifp, struct in_addr *vtep_ip) +int kernel_add_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip) { - return 0; + return 0; } -int -kernel_del_vtep (vni_t vni, struct interface *ifp, struct in_addr *vtep_ip) +int kernel_del_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip) { - return 0; + return 0; } -int -kernel_add_mac (struct interface *ifp, vlanid_t vid, - struct ethaddr *mac, struct in_addr vtep_ip, - u_char sticky) +int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, + struct in_addr vtep_ip, u_char sticky) { - return 0; + return 0; } -int -kernel_del_mac (struct interface *ifp, vlanid_t vid, - struct ethaddr *mac, struct in_addr vtep_ip, int local) +int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, + struct in_addr vtep_ip, int local) { - return 0; + return 0; } -int kernel_add_neigh (struct interface *ifp, struct ipaddr *ip, - struct ethaddr *mac) +int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip, + struct ethaddr *mac) { - return 0; + return 0; } -int kernel_del_neigh (struct interface *ifp, struct ipaddr *ip) +int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip) { - return 0; + return 0; } diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 589ecc949..b8cf2d490 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -45,7 +45,7 @@ extern struct zebra_privs_t zserv_privs; -#if defined (HAVE_RTADV) +#if defined(HAVE_RTADV) #ifdef OPEN_BSD #include @@ -62,743 +62,722 @@ extern struct zebra_privs_t zserv_privs; #define ALLNODE "ff02::1" #define ALLROUTER "ff02::2" -enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER, - RTADV_TIMER_MSEC, RTADV_READ}; +enum rtadv_event { + RTADV_START, + RTADV_STOP, + RTADV_TIMER, + RTADV_TIMER_MSEC, + RTADV_READ +}; -static void rtadv_event (struct zebra_ns *, enum rtadv_event, int); +static void rtadv_event(struct zebra_ns *, enum rtadv_event, int); -static int if_join_all_router (int, struct interface *); -static int if_leave_all_router (int, struct interface *); +static int if_join_all_router(int, struct interface *); +static int if_leave_all_router(int, struct interface *); -static int -rtadv_increment_received(struct zebra_ns *zns, ifindex_t *ifindex) +static int rtadv_increment_received(struct zebra_ns *zns, ifindex_t *ifindex) { - int ret = -1; - struct interface *iface; - struct zebra_if *zif; - - iface = if_lookup_by_index_per_ns (zns, *ifindex); - if (iface && iface->info) - { - zif = iface->info; - zif->ra_rcvd++; - ret = 0; - } - return ret; + int ret = -1; + struct interface *iface; + struct zebra_if *zif; + + iface = if_lookup_by_index_per_ns(zns, *ifindex); + if (iface && iface->info) { + zif = iface->info; + zif->ra_rcvd++; + ret = 0; + } + return ret; } -static int -rtadv_recv_packet (struct zebra_ns *zns, int sock, u_char *buf, int buflen, - struct sockaddr_in6 *from, ifindex_t *ifindex, - int *hoplimit) +static int rtadv_recv_packet(struct zebra_ns *zns, int sock, u_char *buf, + int buflen, struct sockaddr_in6 *from, + ifindex_t *ifindex, int *hoplimit) { - int ret; - struct msghdr msg; - struct iovec iov; - struct cmsghdr *cmsgptr; - struct in6_addr dst; - - char adata[1024]; - - /* Fill in message and iovec. */ - msg.msg_name = (void *) from; - msg.msg_namelen = sizeof (struct sockaddr_in6); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = (void *) adata; - msg.msg_controllen = sizeof adata; - iov.iov_base = buf; - iov.iov_len = buflen; - - /* If recvmsg fail return minus value. */ - ret = recvmsg (sock, &msg, 0); - if (ret < 0) - return ret; - - for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL; - cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) - { - /* I want interface index which this packet comes from. */ - if (cmsgptr->cmsg_level == IPPROTO_IPV6 && - cmsgptr->cmsg_type == IPV6_PKTINFO) - { - struct in6_pktinfo *ptr; - - ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr); - *ifindex = ptr->ipi6_ifindex; - memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr)); - } - - /* Incoming packet's hop limit. */ - if (cmsgptr->cmsg_level == IPPROTO_IPV6 && - cmsgptr->cmsg_type == IPV6_HOPLIMIT) - { - int *hoptr = (int *) CMSG_DATA (cmsgptr); - *hoplimit = *hoptr; + int ret; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsgptr; + struct in6_addr dst; + + char adata[1024]; + + /* Fill in message and iovec. */ + msg.msg_name = (void *)from; + msg.msg_namelen = sizeof(struct sockaddr_in6); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = (void *)adata; + msg.msg_controllen = sizeof adata; + iov.iov_base = buf; + iov.iov_len = buflen; + + /* If recvmsg fail return minus value. */ + ret = recvmsg(sock, &msg, 0); + if (ret < 0) + return ret; + + for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL; + cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { + /* I want interface index which this packet comes from. */ + if (cmsgptr->cmsg_level == IPPROTO_IPV6 + && cmsgptr->cmsg_type == IPV6_PKTINFO) { + struct in6_pktinfo *ptr; + + ptr = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); + *ifindex = ptr->ipi6_ifindex; + memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr)); + } + + /* Incoming packet's hop limit. */ + if (cmsgptr->cmsg_level == IPPROTO_IPV6 + && cmsgptr->cmsg_type == IPV6_HOPLIMIT) { + int *hoptr = (int *)CMSG_DATA(cmsgptr); + *hoplimit = *hoptr; + } } - } - rtadv_increment_received(zns, ifindex); - return ret; + rtadv_increment_received(zns, ifindex); + return ret; } #define RTADV_MSG_SIZE 4096 /* Send router advertisement packet. */ -static void -rtadv_send_packet (int sock, struct interface *ifp) +static void rtadv_send_packet(int sock, struct interface *ifp) { - struct msghdr msg; - struct iovec iov; - struct cmsghdr *cmsgptr; - struct in6_pktinfo *pkt; - struct sockaddr_in6 addr; - static void *adata = NULL; - unsigned char buf[RTADV_MSG_SIZE]; - struct nd_router_advert *rtadv; - int ret; - int len = 0; - struct zebra_if *zif; - struct rtadv_prefix *rprefix; - u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; - struct listnode *node; - u_int16_t pkt_RouterLifetime; - - /* - * Allocate control message bufffer. This is dynamic because - * CMSG_SPACE is not guaranteed not to call a function. Note that - * the size will be different on different architectures due to - * differing alignment rules. - */ - if (adata == NULL) - { - /* XXX Free on shutdown. */ - adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo))); - - if (adata == NULL) - zlog_err("rtadv_send_packet: can't malloc control data"); - } - - /* Logging of packet. */ - if (IS_ZEBRA_DEBUG_PACKET) - zlog_debug ("%s(%u): Tx RA, socket %u", - ifp->name, ifp->ifindex, sock); - - /* Fill in sockaddr_in6. */ - memset (&addr, 0, sizeof (struct sockaddr_in6)); - addr.sin6_family = AF_INET6; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsgptr; + struct in6_pktinfo *pkt; + struct sockaddr_in6 addr; + static void *adata = NULL; + unsigned char buf[RTADV_MSG_SIZE]; + struct nd_router_advert *rtadv; + int ret; + int len = 0; + struct zebra_if *zif; + struct rtadv_prefix *rprefix; + u_char all_nodes_addr[] = {0xff, 0x02, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1}; + struct listnode *node; + u_int16_t pkt_RouterLifetime; + + /* + * Allocate control message bufffer. This is dynamic because + * CMSG_SPACE is not guaranteed not to call a function. Note that + * the size will be different on different architectures due to + * differing alignment rules. + */ + if (adata == NULL) { + /* XXX Free on shutdown. */ + adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo))); + + if (adata == NULL) + zlog_err( + "rtadv_send_packet: can't malloc control data"); + } + + /* Logging of packet. */ + if (IS_ZEBRA_DEBUG_PACKET) + zlog_debug("%s(%u): Tx RA, socket %u", ifp->name, ifp->ifindex, + sock); + + /* Fill in sockaddr_in6. */ + memset(&addr, 0, sizeof(struct sockaddr_in6)); + addr.sin6_family = AF_INET6; #ifdef SIN6_LEN - addr.sin6_len = sizeof (struct sockaddr_in6); + addr.sin6_len = sizeof(struct sockaddr_in6); #endif /* SIN6_LEN */ - addr.sin6_port = htons (IPPROTO_ICMPV6); - IPV6_ADDR_COPY (&addr.sin6_addr, all_nodes_addr); - - /* Fetch interface information. */ - zif = ifp->info; - - /* Make router advertisement message. */ - rtadv = (struct nd_router_advert *) buf; - - rtadv->nd_ra_type = ND_ROUTER_ADVERT; - rtadv->nd_ra_code = 0; - rtadv->nd_ra_cksum = 0; - - rtadv->nd_ra_curhoplimit = 64; - - /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */ - rtadv->nd_ra_flags_reserved = - zif->rtadv.AdvDefaultLifetime == 0 ? 0 : zif->rtadv.DefaultPreference; - rtadv->nd_ra_flags_reserved <<= 3; - - if (zif->rtadv.AdvManagedFlag) - rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED; - if (zif->rtadv.AdvOtherConfigFlag) - rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER; - if (zif->rtadv.AdvHomeAgentFlag) - rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT; - /* Note that according to Neighbor Discovery (RFC 4861 [18]), - * AdvDefaultLifetime is by default based on the value of - * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime - * field of Router Advertisements. Given that this field is expressed - * in seconds, a small MaxRtrAdvInterval value can result in a zero - * value for this field. To prevent this, routers SHOULD keep - * AdvDefaultLifetime in at least one second, even if the use of - * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */ - pkt_RouterLifetime = zif->rtadv.AdvDefaultLifetime != -1 ? - zif->rtadv.AdvDefaultLifetime : - MAX (1, 0.003 * zif->rtadv.MaxRtrAdvInterval); - rtadv->nd_ra_router_lifetime = htons (pkt_RouterLifetime); - rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime); - rtadv->nd_ra_retransmit = htonl (0); - - len = sizeof (struct nd_router_advert); - - /* If both the Home Agent Preference and Home Agent Lifetime are set to - * their default values specified above, this option SHOULD NOT be - * included in the Router Advertisement messages sent by this home - * agent. -- RFC6275, 7.4 */ - if - ( - zif->rtadv.AdvHomeAgentFlag && - (zif->rtadv.HomeAgentPreference || zif->rtadv.HomeAgentLifetime != -1) - ) - { - struct nd_opt_homeagent_info *ndopt_hai = - (struct nd_opt_homeagent_info *)(buf + len); - ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION; - ndopt_hai->nd_opt_hai_len = 1; - ndopt_hai->nd_opt_hai_reserved = 0; - ndopt_hai->nd_opt_hai_preference = htons(zif->rtadv.HomeAgentPreference); - /* 16-bit unsigned integer. The lifetime associated with the home - * agent in units of seconds. The default value is the same as the - * Router Lifetime, as specified in the main body of the Router - * Advertisement. The maximum value corresponds to 18.2 hours. A - * value of 0 MUST NOT be used. -- RFC6275, 7.5 */ - ndopt_hai->nd_opt_hai_lifetime = htons - ( - zif->rtadv.HomeAgentLifetime != -1 ? - zif->rtadv.HomeAgentLifetime : - MAX (1, pkt_RouterLifetime) /* 0 is OK for RL, but not for HAL*/ - ); - len += sizeof(struct nd_opt_homeagent_info); - } - - if (zif->rtadv.AdvIntervalOption) - { - struct nd_opt_adv_interval *ndopt_adv = - (struct nd_opt_adv_interval *)(buf + len); - ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL; - ndopt_adv->nd_opt_ai_len = 1; - ndopt_adv->nd_opt_ai_reserved = 0; - ndopt_adv->nd_opt_ai_interval = htonl(zif->rtadv.MaxRtrAdvInterval); - len += sizeof(struct nd_opt_adv_interval); - } - - /* Fill in prefix. */ - for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix)) - { - struct nd_opt_prefix_info *pinfo; - - pinfo = (struct nd_opt_prefix_info *) (buf + len); - - pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; - pinfo->nd_opt_pi_len = 4; - pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen; - - pinfo->nd_opt_pi_flags_reserved = 0; - if (rprefix->AdvOnLinkFlag) - pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK; - if (rprefix->AdvAutonomousFlag) - pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO; - if (rprefix->AdvRouterAddressFlag) - pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR; - - pinfo->nd_opt_pi_valid_time = htonl (rprefix->AdvValidLifetime); - pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime); - pinfo->nd_opt_pi_reserved2 = 0; - - IPV6_ADDR_COPY (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.prefix); + addr.sin6_port = htons(IPPROTO_ICMPV6); + IPV6_ADDR_COPY(&addr.sin6_addr, all_nodes_addr); + + /* Fetch interface information. */ + zif = ifp->info; + + /* Make router advertisement message. */ + rtadv = (struct nd_router_advert *)buf; + + rtadv->nd_ra_type = ND_ROUTER_ADVERT; + rtadv->nd_ra_code = 0; + rtadv->nd_ra_cksum = 0; + + rtadv->nd_ra_curhoplimit = 64; + + /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */ + rtadv->nd_ra_flags_reserved = zif->rtadv.AdvDefaultLifetime == 0 + ? 0 + : zif->rtadv.DefaultPreference; + rtadv->nd_ra_flags_reserved <<= 3; + + if (zif->rtadv.AdvManagedFlag) + rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED; + if (zif->rtadv.AdvOtherConfigFlag) + rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER; + if (zif->rtadv.AdvHomeAgentFlag) + rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT; + /* Note that according to Neighbor Discovery (RFC 4861 [18]), + * AdvDefaultLifetime is by default based on the value of + * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime + * field of Router Advertisements. Given that this field is expressed + * in seconds, a small MaxRtrAdvInterval value can result in a zero + * value for this field. To prevent this, routers SHOULD keep + * AdvDefaultLifetime in at least one second, even if the use of + * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */ + pkt_RouterLifetime = + zif->rtadv.AdvDefaultLifetime != -1 + ? zif->rtadv.AdvDefaultLifetime + : MAX(1, 0.003 * zif->rtadv.MaxRtrAdvInterval); + rtadv->nd_ra_router_lifetime = htons(pkt_RouterLifetime); + rtadv->nd_ra_reachable = htonl(zif->rtadv.AdvReachableTime); + rtadv->nd_ra_retransmit = htonl(0); + + len = sizeof(struct nd_router_advert); + + /* If both the Home Agent Preference and Home Agent Lifetime are set to + * their default values specified above, this option SHOULD NOT be + * included in the Router Advertisement messages sent by this home + * agent. -- RFC6275, 7.4 */ + if (zif->rtadv.AdvHomeAgentFlag + && (zif->rtadv.HomeAgentPreference + || zif->rtadv.HomeAgentLifetime != -1)) { + struct nd_opt_homeagent_info *ndopt_hai = + (struct nd_opt_homeagent_info *)(buf + len); + ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION; + ndopt_hai->nd_opt_hai_len = 1; + ndopt_hai->nd_opt_hai_reserved = 0; + ndopt_hai->nd_opt_hai_preference = + htons(zif->rtadv.HomeAgentPreference); + /* 16-bit unsigned integer. The lifetime associated with the + * home + * agent in units of seconds. The default value is the same as + * the + * Router Lifetime, as specified in the main body of the Router + * Advertisement. The maximum value corresponds to 18.2 hours. + * A + * value of 0 MUST NOT be used. -- RFC6275, 7.5 */ + ndopt_hai->nd_opt_hai_lifetime = + htons(zif->rtadv.HomeAgentLifetime != -1 + ? zif->rtadv.HomeAgentLifetime + : MAX(1, pkt_RouterLifetime) /* 0 is OK + for RL, + but not + for HAL*/ + ); + len += sizeof(struct nd_opt_homeagent_info); + } -#ifdef DEBUG - { - u_char buf[INET6_ADDRSTRLEN]; + if (zif->rtadv.AdvIntervalOption) { + struct nd_opt_adv_interval *ndopt_adv = + (struct nd_opt_adv_interval *)(buf + len); + ndopt_adv->nd_opt_ai_type = ND_OPT_ADV_INTERVAL; + ndopt_adv->nd_opt_ai_len = 1; + ndopt_adv->nd_opt_ai_reserved = 0; + ndopt_adv->nd_opt_ai_interval = + htonl(zif->rtadv.MaxRtrAdvInterval); + len += sizeof(struct nd_opt_adv_interval); + } + + /* Fill in prefix. */ + for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvPrefixList, node, rprefix)) { + struct nd_opt_prefix_info *pinfo; - zlog_debug ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix, - buf, INET6_ADDRSTRLEN)); + pinfo = (struct nd_opt_prefix_info *)(buf + len); - } + pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; + pinfo->nd_opt_pi_len = 4; + pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen; + + pinfo->nd_opt_pi_flags_reserved = 0; + if (rprefix->AdvOnLinkFlag) + pinfo->nd_opt_pi_flags_reserved |= + ND_OPT_PI_FLAG_ONLINK; + if (rprefix->AdvAutonomousFlag) + pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO; + if (rprefix->AdvRouterAddressFlag) + pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR; + + pinfo->nd_opt_pi_valid_time = htonl(rprefix->AdvValidLifetime); + pinfo->nd_opt_pi_preferred_time = + htonl(rprefix->AdvPreferredLifetime); + pinfo->nd_opt_pi_reserved2 = 0; + + IPV6_ADDR_COPY(&pinfo->nd_opt_pi_prefix, + &rprefix->prefix.prefix); + +#ifdef DEBUG + { + u_char buf[INET6_ADDRSTRLEN]; + + zlog_debug("DEBUG %s", + inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix, + buf, INET6_ADDRSTRLEN)); + } #endif /* DEBUG */ - len += sizeof (struct nd_opt_prefix_info); - } - - /* Hardware address. */ - if (ifp->hw_addr_len != 0) - { - buf[len++] = ND_OPT_SOURCE_LINKADDR; - - /* Option length should be rounded up to next octet if - the link address does not end on an octet boundary. */ - buf[len++] = (ifp->hw_addr_len + 9) >> 3; - - memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len); - len += ifp->hw_addr_len; - - /* Pad option to end on an octet boundary. */ - memset (buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7); - len += -(ifp->hw_addr_len + 2) & 0x7; - } - - /* MTU */ - if (zif->rtadv.AdvLinkMTU) - { - struct nd_opt_mtu * opt = (struct nd_opt_mtu *) (buf + len); - opt->nd_opt_mtu_type = ND_OPT_MTU; - opt->nd_opt_mtu_len = 1; - opt->nd_opt_mtu_reserved = 0; - opt->nd_opt_mtu_mtu = htonl (zif->rtadv.AdvLinkMTU); - len += sizeof (struct nd_opt_mtu); - } - - msg.msg_name = (void *) &addr; - msg.msg_namelen = sizeof (struct sockaddr_in6); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = (void *) adata; - msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); - msg.msg_flags = 0; - iov.iov_base = buf; - iov.iov_len = len; - - cmsgptr = ZCMSG_FIRSTHDR(&msg); - cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); - cmsgptr->cmsg_level = IPPROTO_IPV6; - cmsgptr->cmsg_type = IPV6_PKTINFO; - - pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr); - memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr)); - pkt->ipi6_ifindex = ifp->ifindex; - - ret = sendmsg (sock, &msg, 0); - if (ret < 0) - { - zlog_err ("%s(%u): Tx RA failed, socket %u error %d (%s)", - ifp->name, ifp->ifindex, sock, errno, safe_strerror(errno)); - } - else - zif->ra_sent++; + len += sizeof(struct nd_opt_prefix_info); + } + + /* Hardware address. */ + if (ifp->hw_addr_len != 0) { + buf[len++] = ND_OPT_SOURCE_LINKADDR; + + /* Option length should be rounded up to next octet if + the link address does not end on an octet boundary. */ + buf[len++] = (ifp->hw_addr_len + 9) >> 3; + + memcpy(buf + len, ifp->hw_addr, ifp->hw_addr_len); + len += ifp->hw_addr_len; + + /* Pad option to end on an octet boundary. */ + memset(buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7); + len += -(ifp->hw_addr_len + 2) & 0x7; + } + + /* MTU */ + if (zif->rtadv.AdvLinkMTU) { + struct nd_opt_mtu *opt = (struct nd_opt_mtu *)(buf + len); + opt->nd_opt_mtu_type = ND_OPT_MTU; + opt->nd_opt_mtu_len = 1; + opt->nd_opt_mtu_reserved = 0; + opt->nd_opt_mtu_mtu = htonl(zif->rtadv.AdvLinkMTU); + len += sizeof(struct nd_opt_mtu); + } + + msg.msg_name = (void *)&addr; + msg.msg_namelen = sizeof(struct sockaddr_in6); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = (void *)adata; + msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); + msg.msg_flags = 0; + iov.iov_base = buf; + iov.iov_len = len; + + cmsgptr = ZCMSG_FIRSTHDR(&msg); + cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + cmsgptr->cmsg_level = IPPROTO_IPV6; + cmsgptr->cmsg_type = IPV6_PKTINFO; + + pkt = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); + memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr)); + pkt->ipi6_ifindex = ifp->ifindex; + + ret = sendmsg(sock, &msg, 0); + if (ret < 0) { + zlog_err("%s(%u): Tx RA failed, socket %u error %d (%s)", + ifp->name, ifp->ifindex, sock, errno, + safe_strerror(errno)); + } else + zif->ra_sent++; } -static int -rtadv_timer (struct thread *thread) +static int rtadv_timer(struct thread *thread) { - struct zebra_ns *zns = THREAD_ARG (thread); - struct vrf *vrf; - struct listnode *node, *nnode; - struct interface *ifp; - struct zebra_if *zif; - int period; - - zns->rtadv.ra_timer = NULL; - if (zns->rtadv.adv_msec_if_count == 0) - { - period = 1000; /* 1 s */ - rtadv_event (zns, RTADV_TIMER, 1 /* 1 s */); - } - else - { - period = 10; /* 10 ms */ - rtadv_event (zns, RTADV_TIMER_MSEC, 10 /* 10 ms */); - } - - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - for (ALL_LIST_ELEMENTS (vrf->iflist, node, nnode, ifp)) - { - if (if_is_loopback (ifp) || - CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK) || - ! if_is_operative (ifp)) - continue; - - zif = ifp->info; - - if (zif->rtadv.AdvSendAdvertisements) - { - if (zif->rtadv.inFastRexmit) - { - /* We assume we fast rexmit every sec so no additional vars */ - if (--zif->rtadv.NumFastReXmitsRemain <= 0) - zif->rtadv.inFastRexmit = 0; - - if (IS_ZEBRA_DEBUG_SEND) - zlog_debug("Fast RA Rexmit on interface %s", ifp->name); - - rtadv_send_packet (zns->rtadv.sock, ifp); - } - else - { - zif->rtadv.AdvIntervalTimer -= period; - if (zif->rtadv.AdvIntervalTimer <= 0) - { - /* FIXME: using MaxRtrAdvInterval each time isn't what section - 6.2.4 of RFC4861 tells to do. */ - zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval; - rtadv_send_packet (zns->rtadv.sock, ifp); - } - } - } - } - - return 0; + struct zebra_ns *zns = THREAD_ARG(thread); + struct vrf *vrf; + struct listnode *node, *nnode; + struct interface *ifp; + struct zebra_if *zif; + int period; + + zns->rtadv.ra_timer = NULL; + if (zns->rtadv.adv_msec_if_count == 0) { + period = 1000; /* 1 s */ + rtadv_event(zns, RTADV_TIMER, 1 /* 1 s */); + } else { + period = 10; /* 10 ms */ + rtadv_event(zns, RTADV_TIMER_MSEC, 10 /* 10 ms */); + } + + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + for (ALL_LIST_ELEMENTS(vrf->iflist, node, nnode, ifp)) { + if (if_is_loopback(ifp) + || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK) + || !if_is_operative(ifp)) + continue; + + zif = ifp->info; + + if (zif->rtadv.AdvSendAdvertisements) { + if (zif->rtadv.inFastRexmit) { + /* We assume we fast rexmit every sec so no + * additional vars */ + if (--zif->rtadv.NumFastReXmitsRemain <= 0) + zif->rtadv.inFastRexmit = 0; + + if (IS_ZEBRA_DEBUG_SEND) + zlog_debug( + "Fast RA Rexmit on interface %s", + ifp->name); + + rtadv_send_packet(zns->rtadv.sock, ifp); + } else { + zif->rtadv.AdvIntervalTimer -= period; + if (zif->rtadv.AdvIntervalTimer <= 0) { + /* FIXME: using MaxRtrAdvInterval each + time isn't what section + 6.2.4 of RFC4861 tells to do. */ + zif->rtadv.AdvIntervalTimer = + zif->rtadv.MaxRtrAdvInterval; + rtadv_send_packet(zns->rtadv.sock, ifp); + } + } + } + } + + return 0; } -static void -rtadv_process_solicit (struct interface *ifp) +static void rtadv_process_solicit(struct interface *ifp) { - struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id); - struct zebra_ns *zns = zvrf->zns; + struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id); + struct zebra_ns *zns = zvrf->zns; - assert (zns); - rtadv_send_packet (zns->rtadv.sock, ifp); + assert(zns); + rtadv_send_packet(zns->rtadv.sock, ifp); } -static void -rtadv_process_advert (u_char *msg, unsigned int len, struct interface *ifp, - struct sockaddr_in6 *addr) +static void rtadv_process_advert(u_char *msg, unsigned int len, + struct interface *ifp, + struct sockaddr_in6 *addr) { - struct nd_router_advert *radvert; - char addr_str[INET6_ADDRSTRLEN]; - struct zebra_if *zif; - struct prefix p; - - zif = ifp->info; - - inet_ntop (AF_INET6, &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN); - - if (len < sizeof(struct nd_router_advert)) { - zlog_warn("%s(%u): Rx RA with invalid length %d from %s", - ifp->name, ifp->ifindex, len, addr_str); - return; - } - if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) { - zlog_warn("%s(%u): Rx RA with non-linklocal source address from %s", - ifp->name, ifp->ifindex, addr_str); - return; - } - - radvert = (struct nd_router_advert *) msg; - - if ((radvert->nd_ra_curhoplimit && zif->rtadv.AdvCurHopLimit) && - (radvert->nd_ra_curhoplimit != zif->rtadv.AdvCurHopLimit)) - { - zlog_warn("%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s", - ifp->name, ifp->ifindex, addr_str); - } - - if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) && - !zif->rtadv.AdvManagedFlag) - { - zlog_warn("%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s", - ifp->name, ifp->ifindex, addr_str); - } - - if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) && - !zif->rtadv.AdvOtherConfigFlag) - { - zlog_warn("%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s", - ifp->name, ifp->ifindex, addr_str); - } - - if ((radvert->nd_ra_reachable && zif->rtadv.AdvReachableTime) && - (ntohl(radvert->nd_ra_reachable) != zif->rtadv.AdvReachableTime)) - { - zlog_warn("%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s", - ifp->name, ifp->ifindex, addr_str); - } - - if ((radvert->nd_ra_retransmit && zif->rtadv.AdvRetransTimer) && - (ntohl(radvert->nd_ra_retransmit) != (unsigned int)zif->rtadv.AdvRetransTimer)) - { - zlog_warn("%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s", - ifp->name, ifp->ifindex, addr_str); - } - - /* Create entry for neighbor if not known. */ - p.family = AF_INET6; - IPV6_ADDR_COPY (&p.u.prefix, &addr->sin6_addr); - p.prefixlen = IPV6_MAX_PREFIXLEN; - - if (!nbr_connected_check(ifp, &p)) - nbr_connected_add_ipv6 (ifp, &addr->sin6_addr); -} + struct nd_router_advert *radvert; + char addr_str[INET6_ADDRSTRLEN]; + struct zebra_if *zif; + struct prefix p; + zif = ifp->info; -static void -rtadv_process_packet (u_char *buf, unsigned int len, ifindex_t ifindex, int hoplimit, - struct sockaddr_in6 *from, struct zebra_ns *zns) -{ - struct icmp6_hdr *icmph; - struct interface *ifp; - struct zebra_if *zif; - char addr_str[INET6_ADDRSTRLEN]; - - inet_ntop (AF_INET6, &from->sin6_addr, addr_str, INET6_ADDRSTRLEN); - - /* Interface search. */ - ifp = if_lookup_by_index_per_ns (zns, ifindex); - if (ifp == NULL) - { - zlog_warn ("RA/RS received on unknown IF %u from %s", - ifindex, addr_str); - return; - } - - if (IS_ZEBRA_DEBUG_PACKET) - zlog_debug ("%s(%u): Rx RA/RS len %d from %s", - ifp->name, ifp->ifindex, len, addr_str); - - if (if_is_loopback (ifp) || - CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) - return; - - /* Check interface configuration. */ - zif = ifp->info; - if (! zif->rtadv.AdvSendAdvertisements) - return; - - /* ICMP message length check. */ - if (len < sizeof (struct icmp6_hdr)) - { - zlog_warn ("%s(%u): Rx RA with Invalid ICMPV6 packet length %d", - ifp->name, ifp->ifindex, len); - return; - } - - icmph = (struct icmp6_hdr *) buf; - - /* ICMP message type check. */ - if (icmph->icmp6_type != ND_ROUTER_SOLICIT && - icmph->icmp6_type != ND_ROUTER_ADVERT) - { - zlog_warn ("%s(%u): Rx RA - Unwanted ICMPV6 message type %d", - ifp->name, ifp->ifindex, icmph->icmp6_type); - return; - } - - /* Hoplimit check. */ - if (hoplimit >= 0 && hoplimit != 255) - { - zlog_warn ("%s(%u): Rx RA - Invalid hoplimit %d", - ifp->name, ifp->ifindex, hoplimit); - return; - } - - /* Check ICMP message type. */ - if (icmph->icmp6_type == ND_ROUTER_SOLICIT) - rtadv_process_solicit (ifp); - else if (icmph->icmp6_type == ND_ROUTER_ADVERT) - rtadv_process_advert (buf, len, ifp, from); - - return; + inet_ntop(AF_INET6, &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN); + + if (len < sizeof(struct nd_router_advert)) { + zlog_warn("%s(%u): Rx RA with invalid length %d from %s", + ifp->name, ifp->ifindex, len, addr_str); + return; + } + if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) { + zlog_warn( + "%s(%u): Rx RA with non-linklocal source address from %s", + ifp->name, ifp->ifindex, addr_str); + return; + } + + radvert = (struct nd_router_advert *)msg; + + if ((radvert->nd_ra_curhoplimit && zif->rtadv.AdvCurHopLimit) + && (radvert->nd_ra_curhoplimit != zif->rtadv.AdvCurHopLimit)) { + zlog_warn( + "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s", + ifp->name, ifp->ifindex, addr_str); + } + + if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) + && !zif->rtadv.AdvManagedFlag) { + zlog_warn( + "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s", + ifp->name, ifp->ifindex, addr_str); + } + + if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) + && !zif->rtadv.AdvOtherConfigFlag) { + zlog_warn( + "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s", + ifp->name, ifp->ifindex, addr_str); + } + + if ((radvert->nd_ra_reachable && zif->rtadv.AdvReachableTime) + && (ntohl(radvert->nd_ra_reachable) + != zif->rtadv.AdvReachableTime)) { + zlog_warn( + "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s", + ifp->name, ifp->ifindex, addr_str); + } + + if ((radvert->nd_ra_retransmit && zif->rtadv.AdvRetransTimer) + && (ntohl(radvert->nd_ra_retransmit) + != (unsigned int)zif->rtadv.AdvRetransTimer)) { + zlog_warn( + "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s", + ifp->name, ifp->ifindex, addr_str); + } + + /* Create entry for neighbor if not known. */ + p.family = AF_INET6; + IPV6_ADDR_COPY(&p.u.prefix, &addr->sin6_addr); + p.prefixlen = IPV6_MAX_PREFIXLEN; + + if (!nbr_connected_check(ifp, &p)) + nbr_connected_add_ipv6(ifp, &addr->sin6_addr); } -static int -rtadv_read (struct thread *thread) + +static void rtadv_process_packet(u_char *buf, unsigned int len, + ifindex_t ifindex, int hoplimit, + struct sockaddr_in6 *from, + struct zebra_ns *zns) { - int sock; - int len; - u_char buf[RTADV_MSG_SIZE]; - struct sockaddr_in6 from; - ifindex_t ifindex = 0; - int hoplimit = -1; - struct zebra_ns *zns = THREAD_ARG (thread); + struct icmp6_hdr *icmph; + struct interface *ifp; + struct zebra_if *zif; + char addr_str[INET6_ADDRSTRLEN]; + + inet_ntop(AF_INET6, &from->sin6_addr, addr_str, INET6_ADDRSTRLEN); + + /* Interface search. */ + ifp = if_lookup_by_index_per_ns(zns, ifindex); + if (ifp == NULL) { + zlog_warn("RA/RS received on unknown IF %u from %s", ifindex, + addr_str); + return; + } + + if (IS_ZEBRA_DEBUG_PACKET) + zlog_debug("%s(%u): Rx RA/RS len %d from %s", ifp->name, + ifp->ifindex, len, addr_str); + + if (if_is_loopback(ifp) + || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) + return; - sock = THREAD_FD (thread); - zns->rtadv.ra_read = NULL; + /* Check interface configuration. */ + zif = ifp->info; + if (!zif->rtadv.AdvSendAdvertisements) + return; - /* Register myself. */ - rtadv_event (zns, RTADV_READ, sock); + /* ICMP message length check. */ + if (len < sizeof(struct icmp6_hdr)) { + zlog_warn("%s(%u): Rx RA with Invalid ICMPV6 packet length %d", + ifp->name, ifp->ifindex, len); + return; + } + + icmph = (struct icmp6_hdr *)buf; - len = rtadv_recv_packet (zns, sock, buf, sizeof (buf), &from, &ifindex, &hoplimit); + /* ICMP message type check. */ + if (icmph->icmp6_type != ND_ROUTER_SOLICIT + && icmph->icmp6_type != ND_ROUTER_ADVERT) { + zlog_warn("%s(%u): Rx RA - Unwanted ICMPV6 message type %d", + ifp->name, ifp->ifindex, icmph->icmp6_type); + return; + } - if (len < 0) - { - zlog_warn ("RA/RS recv failed, socket %u error %s", - sock, safe_strerror (errno)); - return len; - } + /* Hoplimit check. */ + if (hoplimit >= 0 && hoplimit != 255) { + zlog_warn("%s(%u): Rx RA - Invalid hoplimit %d", ifp->name, + ifp->ifindex, hoplimit); + return; + } - rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit, &from, zns); + /* Check ICMP message type. */ + if (icmph->icmp6_type == ND_ROUTER_SOLICIT) + rtadv_process_solicit(ifp); + else if (icmph->icmp6_type == ND_ROUTER_ADVERT) + rtadv_process_advert(buf, len, ifp, from); - return 0; + return; } -static int -rtadv_make_socket (void) +static int rtadv_read(struct thread *thread) { - int sock; - int ret = 0; - struct icmp6_filter filter; - - if ( zserv_privs.change (ZPRIVS_RAISE) ) - zlog_err ("rtadv_make_socket: could not raise privs, %s", - safe_strerror (errno) ); - - sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); - - if ( zserv_privs.change (ZPRIVS_LOWER) ) - zlog_err ("rtadv_make_socket: could not lower privs, %s", - safe_strerror (errno) ); - - if (sock < 0) - { - close (sock); - return -1; - } - - ret = setsockopt_ipv6_pktinfo (sock, 1); - if (ret < 0) - { - close (sock); - return ret; - } - ret = setsockopt_ipv6_multicast_loop (sock, 0); - if (ret < 0) - { - close (sock); - return ret; - } - ret = setsockopt_ipv6_unicast_hops (sock, 255); - if (ret < 0) - { - close (sock); - return ret; - } - ret = setsockopt_ipv6_multicast_hops (sock, 255); - if (ret < 0) - { - close (sock); - return ret; - } - ret = setsockopt_ipv6_hoplimit (sock, 1); - if (ret < 0) - { - close (sock); - return ret; - } - - ICMP6_FILTER_SETBLOCKALL(&filter); - ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter); - ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter); - - ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, - sizeof (struct icmp6_filter)); - if (ret < 0) - { - zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno)); - return ret; - } - - return sock; + int sock; + int len; + u_char buf[RTADV_MSG_SIZE]; + struct sockaddr_in6 from; + ifindex_t ifindex = 0; + int hoplimit = -1; + struct zebra_ns *zns = THREAD_ARG(thread); + + sock = THREAD_FD(thread); + zns->rtadv.ra_read = NULL; + + /* Register myself. */ + rtadv_event(zns, RTADV_READ, sock); + + len = rtadv_recv_packet(zns, sock, buf, sizeof(buf), &from, &ifindex, + &hoplimit); + + if (len < 0) { + zlog_warn("RA/RS recv failed, socket %u error %s", sock, + safe_strerror(errno)); + return len; + } + + rtadv_process_packet(buf, (unsigned)len, ifindex, hoplimit, &from, zns); + + return 0; } -static struct rtadv_prefix * -rtadv_prefix_new (void) +static int rtadv_make_socket(void) { - return XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix)); + int sock; + int ret = 0; + struct icmp6_filter filter; + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("rtadv_make_socket: could not raise privs, %s", + safe_strerror(errno)); + + sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); + + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("rtadv_make_socket: could not lower privs, %s", + safe_strerror(errno)); + + if (sock < 0) { + close(sock); + return -1; + } + + ret = setsockopt_ipv6_pktinfo(sock, 1); + if (ret < 0) { + close(sock); + return ret; + } + ret = setsockopt_ipv6_multicast_loop(sock, 0); + if (ret < 0) { + close(sock); + return ret; + } + ret = setsockopt_ipv6_unicast_hops(sock, 255); + if (ret < 0) { + close(sock); + return ret; + } + ret = setsockopt_ipv6_multicast_hops(sock, 255); + if (ret < 0) { + close(sock); + return ret; + } + ret = setsockopt_ipv6_hoplimit(sock, 1); + if (ret < 0) { + close(sock); + return ret; + } + + ICMP6_FILTER_SETBLOCKALL(&filter); + ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter); + ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter); + + ret = setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, + sizeof(struct icmp6_filter)); + if (ret < 0) { + zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno)); + return ret; + } + + return sock; } -static void -rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix) +static struct rtadv_prefix *rtadv_prefix_new(void) { - XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix); + return XCALLOC(MTYPE_RTADV_PREFIX, sizeof(struct rtadv_prefix)); } -static struct rtadv_prefix * -rtadv_prefix_lookup (struct list *rplist, struct prefix_ipv6 *p) +static void rtadv_prefix_free(struct rtadv_prefix *rtadv_prefix) { - struct listnode *node; - struct rtadv_prefix *rprefix; + XFREE(MTYPE_RTADV_PREFIX, rtadv_prefix); +} - for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix)) - if (prefix_same ((struct prefix *) &rprefix->prefix, (struct prefix *) p)) - return rprefix; - return NULL; +static struct rtadv_prefix *rtadv_prefix_lookup(struct list *rplist, + struct prefix_ipv6 *p) +{ + struct listnode *node; + struct rtadv_prefix *rprefix; + + for (ALL_LIST_ELEMENTS_RO(rplist, node, rprefix)) + if (prefix_same((struct prefix *)&rprefix->prefix, + (struct prefix *)p)) + return rprefix; + return NULL; } -static struct rtadv_prefix * -rtadv_prefix_get (struct list *rplist, struct prefix_ipv6 *p) +static struct rtadv_prefix *rtadv_prefix_get(struct list *rplist, + struct prefix_ipv6 *p) { - struct rtadv_prefix *rprefix; - - rprefix = rtadv_prefix_lookup (rplist, p); - if (rprefix) - return rprefix; + struct rtadv_prefix *rprefix; + + rprefix = rtadv_prefix_lookup(rplist, p); + if (rprefix) + return rprefix; - rprefix = rtadv_prefix_new (); - memcpy (&rprefix->prefix, p, sizeof (struct prefix_ipv6)); - listnode_add (rplist, rprefix); + rprefix = rtadv_prefix_new(); + memcpy(&rprefix->prefix, p, sizeof(struct prefix_ipv6)); + listnode_add(rplist, rprefix); - return rprefix; + return rprefix; } -static void -rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp) +static void rtadv_prefix_set(struct zebra_if *zif, struct rtadv_prefix *rp) { - struct rtadv_prefix *rprefix; - - rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix); - - /* Set parameters. */ - rprefix->AdvValidLifetime = rp->AdvValidLifetime; - rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime; - rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag; - rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag; - rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag; + struct rtadv_prefix *rprefix; + + rprefix = rtadv_prefix_get(zif->rtadv.AdvPrefixList, &rp->prefix); + + /* Set parameters. */ + rprefix->AdvValidLifetime = rp->AdvValidLifetime; + rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime; + rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag; + rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag; + rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag; } -static int -rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp) +static int rtadv_prefix_reset(struct zebra_if *zif, struct rtadv_prefix *rp) { - struct rtadv_prefix *rprefix; - - rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix); - if (rprefix != NULL) - { - listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix); - rtadv_prefix_free (rprefix); - return 1; - } - else - return 0; + struct rtadv_prefix *rprefix; + + rprefix = rtadv_prefix_lookup(zif->rtadv.AdvPrefixList, &rp->prefix); + if (rprefix != NULL) { + listnode_delete(zif->rtadv.AdvPrefixList, (void *)rprefix); + rtadv_prefix_free(rprefix); + return 1; + } else + return 0; } -static void -ipv6_nd_suppress_ra_set (struct interface *ifp, ipv6_nd_suppress_ra_status status) +static void ipv6_nd_suppress_ra_set(struct interface *ifp, + ipv6_nd_suppress_ra_status status) { - struct zebra_if *zif; - struct zebra_vrf *zvrf; - struct zebra_ns *zns; - - zif = ifp->info; - zvrf = vrf_info_lookup (ifp->vrf_id); - zns = zvrf->zns; - - if (status == RA_SUPPRESS) - { - /* RA is currently enabled */ - if (zif->rtadv.AdvSendAdvertisements) - { - zif->rtadv.AdvSendAdvertisements = 0; - zif->rtadv.AdvIntervalTimer = 0; - zns->rtadv.adv_if_count--; - - if_leave_all_router (zns->rtadv.sock, ifp); - - if (zns->rtadv.adv_if_count == 0) - rtadv_event (zns, RTADV_STOP, 0); - } - } - else - { - if (! zif->rtadv.AdvSendAdvertisements) - { - zif->rtadv.AdvSendAdvertisements = 1; - zif->rtadv.AdvIntervalTimer = 0; - zns->rtadv.adv_if_count++; - - if (zif->rtadv.MaxRtrAdvInterval >= 1000) - { - /* Enable Fast RA only when RA interval is in secs */ - zif->rtadv.inFastRexmit = 1; - zif->rtadv.NumFastReXmitsRemain = RTADV_NUM_FAST_REXMITS; - } - - if_join_all_router (zns->rtadv.sock, ifp); - - if (zns->rtadv.adv_if_count == 1) - rtadv_event (zns, RTADV_START, zns->rtadv.sock); - } - } + struct zebra_if *zif; + struct zebra_vrf *zvrf; + struct zebra_ns *zns; + + zif = ifp->info; + zvrf = vrf_info_lookup(ifp->vrf_id); + zns = zvrf->zns; + + if (status == RA_SUPPRESS) { + /* RA is currently enabled */ + if (zif->rtadv.AdvSendAdvertisements) { + zif->rtadv.AdvSendAdvertisements = 0; + zif->rtadv.AdvIntervalTimer = 0; + zns->rtadv.adv_if_count--; + + if_leave_all_router(zns->rtadv.sock, ifp); + + if (zns->rtadv.adv_if_count == 0) + rtadv_event(zns, RTADV_STOP, 0); + } + } else { + if (!zif->rtadv.AdvSendAdvertisements) { + zif->rtadv.AdvSendAdvertisements = 1; + zif->rtadv.AdvIntervalTimer = 0; + zns->rtadv.adv_if_count++; + + if (zif->rtadv.MaxRtrAdvInterval >= 1000) { + /* Enable Fast RA only when RA interval is in + * secs */ + zif->rtadv.inFastRexmit = 1; + zif->rtadv.NumFastReXmitsRemain = + RTADV_NUM_FAST_REXMITS; + } + + if_join_all_router(zns->rtadv.sock, ifp); + + if (zns->rtadv.adv_if_count == 1) + rtadv_event(zns, RTADV_START, zns->rtadv.sock); + } + } } /* @@ -808,60 +787,55 @@ ipv6_nd_suppress_ra_set (struct interface *ifp, ipv6_nd_suppress_ra_status statu * if the operator has explicitly enabled RA. The enable request can also * specify a RA interval (in seconds). */ -void -zebra_interface_radv_set (struct zserv *client, int sock, u_short length, - struct zebra_vrf *zvrf, int enable) +void zebra_interface_radv_set(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf, int enable) { - struct stream *s; - unsigned int ifindex; - struct interface *ifp; - struct zebra_if *zif; - int ra_interval; - - s = client->ibuf; - - /* Get interface index and RA interval. */ - ifindex = stream_getl (s); - ra_interval = stream_getl (s); - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%u: IF %u RA %s from client %s, interval %ds", - zvrf_id (zvrf), ifindex, enable ? "enable" : "disable", - zebra_route_string(client->proto), ra_interval); - - /* Locate interface and check VRF match. */ - ifp = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT), ifindex); - if (!ifp) - { - zlog_warn("%u: IF %u RA %s client %s - interface unknown", - zvrf_id (zvrf), ifindex, enable ? "enable" : "disable", - zebra_route_string(client->proto)); - return; - } - if (ifp->vrf_id != zvrf_id (zvrf)) - { - zlog_warn("%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u", - zvrf_id (zvrf), ifindex, enable ? "enable" : "disable", - zebra_route_string(client->proto), ifp->vrf_id); - return; - } - - zif = ifp->info; - if (enable) - { - ipv6_nd_suppress_ra_set (ifp, RA_ENABLE); - if (ra_interval && - (ra_interval * 1000) < zif->rtadv.MaxRtrAdvInterval) - zif->rtadv.MaxRtrAdvInterval = ra_interval * 1000; - } - else - { - if (!zif->rtadv.configured) - { - zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL; - ipv6_nd_suppress_ra_set (ifp, RA_SUPPRESS); - } - } + struct stream *s; + unsigned int ifindex; + struct interface *ifp; + struct zebra_if *zif; + int ra_interval; + + s = client->ibuf; + + /* Get interface index and RA interval. */ + ifindex = stream_getl(s); + ra_interval = stream_getl(s); + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%u: IF %u RA %s from client %s, interval %ds", + zvrf_id(zvrf), ifindex, + enable ? "enable" : "disable", + zebra_route_string(client->proto), ra_interval); + + /* Locate interface and check VRF match. */ + ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), ifindex); + if (!ifp) { + zlog_warn("%u: IF %u RA %s client %s - interface unknown", + zvrf_id(zvrf), ifindex, enable ? "enable" : "disable", + zebra_route_string(client->proto)); + return; + } + if (ifp->vrf_id != zvrf_id(zvrf)) { + zlog_warn("%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u", + zvrf_id(zvrf), ifindex, enable ? "enable" : "disable", + zebra_route_string(client->proto), ifp->vrf_id); + return; + } + + zif = ifp->info; + if (enable) { + ipv6_nd_suppress_ra_set(ifp, RA_ENABLE); + if (ra_interval + && (ra_interval * 1000) < zif->rtadv.MaxRtrAdvInterval) + zif->rtadv.MaxRtrAdvInterval = ra_interval * 1000; + } else { + if (!zif->rtadv.configured) { + zif->rtadv.MaxRtrAdvInterval = + RTADV_MAX_RTR_ADV_INTERVAL; + ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS); + } + } } DEFUN (ipv6_nd_suppress_ra, @@ -871,20 +845,19 @@ DEFUN (ipv6_nd_suppress_ra, "Neighbor discovery\n" "Suppress Router Advertisement\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; - - if (if_is_loopback (ifp) || - CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) - { - vty_out (vty, - "Cannot configure IPv6 Router Advertisements on this interface\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ipv6_nd_suppress_ra_set (ifp, RA_SUPPRESS); - zif->rtadv.configured = 0; - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + + if (if_is_loopback(ifp) + || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + vty_out(vty, + "Cannot configure IPv6 Router Advertisements on this interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS); + zif->rtadv.configured = 0; + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_suppress_ra, @@ -895,20 +868,19 @@ DEFUN (no_ipv6_nd_suppress_ra, "Neighbor discovery\n" "Suppress Router Advertisement\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; - - if (if_is_loopback (ifp) || - CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) - { - vty_out (vty, - "Cannot configure IPv6 Router Advertisements on this interface\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ipv6_nd_suppress_ra_set (ifp, RA_ENABLE); - zif->rtadv.configured = 1; - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + + if (if_is_loopback(ifp) + || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)) { + vty_out(vty, + "Cannot configure IPv6 Router Advertisements on this interface\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ipv6_nd_suppress_ra_set(ifp, RA_ENABLE); + zif->rtadv.configured = 1; + return CMD_SUCCESS; } DEFUN (ipv6_nd_ra_interval_msec, @@ -920,33 +892,33 @@ DEFUN (ipv6_nd_ra_interval_msec, "Router Advertisement interval in milliseconds\n" "Router Advertisement interval in milliseconds\n") { - int idx_number = 4; - VTY_DECLVAR_CONTEXT (interface, ifp); - unsigned interval; - struct zebra_if *zif = ifp->info; - struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id); - struct zebra_ns *zns; - - zns = zvrf->zns; - interval = strtoul(argv[idx_number]->arg, NULL, 10); - if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000)) - { - vty_out (vty, - "This ra-interval would conflict with configured ra-lifetime!\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (zif->rtadv.MaxRtrAdvInterval % 1000) - zns->rtadv.adv_msec_if_count--; - - if (interval % 1000) - zns->rtadv.adv_msec_if_count++; - - zif->rtadv.MaxRtrAdvInterval = interval; - zif->rtadv.MinRtrAdvInterval = 0.33 * interval; - zif->rtadv.AdvIntervalTimer = 0; - - return CMD_SUCCESS; + int idx_number = 4; + VTY_DECLVAR_CONTEXT(interface, ifp); + unsigned interval; + struct zebra_if *zif = ifp->info; + struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id); + struct zebra_ns *zns; + + zns = zvrf->zns; + interval = strtoul(argv[idx_number]->arg, NULL, 10); + if ((zif->rtadv.AdvDefaultLifetime != -1 + && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000)) { + vty_out(vty, + "This ra-interval would conflict with configured ra-lifetime!\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (zif->rtadv.MaxRtrAdvInterval % 1000) + zns->rtadv.adv_msec_if_count--; + + if (interval % 1000) + zns->rtadv.adv_msec_if_count++; + + zif->rtadv.MaxRtrAdvInterval = interval; + zif->rtadv.MinRtrAdvInterval = 0.33 * interval; + zif->rtadv.AdvIntervalTimer = 0; + + return CMD_SUCCESS; } DEFUN (ipv6_nd_ra_interval, @@ -957,33 +929,33 @@ DEFUN (ipv6_nd_ra_interval, "Router Advertisement interval\n" "Router Advertisement interval in seconds\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - unsigned interval; - struct zebra_if *zif = ifp->info; - struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id); - struct zebra_ns *zns; - - zns = zvrf->zns; - interval = strtoul(argv[idx_number]->arg, NULL, 10); - if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime)) - { - vty_out (vty, - "This ra-interval would conflict with configured ra-lifetime!\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (zif->rtadv.MaxRtrAdvInterval % 1000) - zns->rtadv.adv_msec_if_count--; - - /* convert to milliseconds */ - interval = interval * 1000; - - zif->rtadv.MaxRtrAdvInterval = interval; - zif->rtadv.MinRtrAdvInterval = 0.33 * interval; - zif->rtadv.AdvIntervalTimer = 0; - - return CMD_SUCCESS; + int idx_number = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + unsigned interval; + struct zebra_if *zif = ifp->info; + struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id); + struct zebra_ns *zns; + + zns = zvrf->zns; + interval = strtoul(argv[idx_number]->arg, NULL, 10); + if ((zif->rtadv.AdvDefaultLifetime != -1 + && interval > (unsigned)zif->rtadv.AdvDefaultLifetime)) { + vty_out(vty, + "This ra-interval would conflict with configured ra-lifetime!\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (zif->rtadv.MaxRtrAdvInterval % 1000) + zns->rtadv.adv_msec_if_count--; + + /* convert to milliseconds */ + interval = interval * 1000; + + zif->rtadv.MaxRtrAdvInterval = interval; + zif->rtadv.MinRtrAdvInterval = 0.33 * interval; + zif->rtadv.AdvIntervalTimer = 0; + + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_ra_interval, @@ -997,22 +969,22 @@ DEFUN (no_ipv6_nd_ra_interval, "Specify millisecond router advertisement interval\n" "Router Advertisement interval in milliseconds\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; - struct zebra_vrf *zvrf; - struct zebra_ns *zns; - - zvrf = vrf_info_lookup (ifp->vrf_id); - zns = zvrf->zns; - - if (zif->rtadv.MaxRtrAdvInterval % 1000) - zns->rtadv.adv_msec_if_count--; - - zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL; - zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL; - zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval; - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + struct zebra_vrf *zvrf; + struct zebra_ns *zns; + + zvrf = vrf_info_lookup(ifp->vrf_id); + zns = zvrf->zns; + + if (zif->rtadv.MaxRtrAdvInterval % 1000) + zns->rtadv.adv_msec_if_count--; + + zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL; + zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL; + zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval; + + return CMD_SUCCESS; } DEFUN (ipv6_nd_ra_lifetime, @@ -1023,27 +995,26 @@ DEFUN (ipv6_nd_ra_lifetime, "Router lifetime\n" "Router lifetime in seconds (0 stands for a non-default gw)\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; - int lifetime; - - lifetime = strtoul(argv[idx_number]->arg, NULL, 10); - - /* The value to be placed in the Router Lifetime field - * of Router Advertisements sent from the interface, - * in seconds. MUST be either zero or between - * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */ - if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval)) - { - vty_out (vty, - "This ra-lifetime would conflict with configured ra-interval\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - zif->rtadv.AdvDefaultLifetime = lifetime; - - return CMD_SUCCESS; + int idx_number = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + int lifetime; + + lifetime = strtoul(argv[idx_number]->arg, NULL, 10); + + /* The value to be placed in the Router Lifetime field + * of Router Advertisements sent from the interface, + * in seconds. MUST be either zero or between + * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */ + if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval)) { + vty_out(vty, + "This ra-lifetime would conflict with configured ra-interval\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + zif->rtadv.AdvDefaultLifetime = lifetime; + + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_ra_lifetime, @@ -1055,12 +1026,12 @@ DEFUN (no_ipv6_nd_ra_lifetime, "Router lifetime\n" "Router lifetime in seconds (0 stands for a non-default gw)\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.AdvDefaultLifetime = -1; + zif->rtadv.AdvDefaultLifetime = -1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_nd_reachable_time, @@ -1071,11 +1042,11 @@ DEFUN (ipv6_nd_reachable_time, "Reachable time\n" "Reachable time in milliseconds\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; - zif->rtadv.AdvReachableTime = strtoul(argv[idx_number]->arg, NULL, 10); - return CMD_SUCCESS; + int idx_number = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + zif->rtadv.AdvReachableTime = strtoul(argv[idx_number]->arg, NULL, 10); + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_reachable_time, @@ -1087,12 +1058,12 @@ DEFUN (no_ipv6_nd_reachable_time, "Reachable time\n" "Reachable time in milliseconds\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.AdvReachableTime = 0; + zif->rtadv.AdvReachableTime = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_nd_homeagent_preference, @@ -1103,11 +1074,12 @@ DEFUN (ipv6_nd_homeagent_preference, "Home Agent preference\n" "preference value (default is 0, least preferred)\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; - zif->rtadv.HomeAgentPreference = strtoul(argv[idx_number]->arg, NULL, 10); - return CMD_SUCCESS; + int idx_number = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + zif->rtadv.HomeAgentPreference = + strtoul(argv[idx_number]->arg, NULL, 10); + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_homeagent_preference, @@ -1119,12 +1091,12 @@ DEFUN (no_ipv6_nd_homeagent_preference, "Home Agent preference\n" "preference value (default is 0, least preferred)\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.HomeAgentPreference = 0; + zif->rtadv.HomeAgentPreference = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_nd_homeagent_lifetime, @@ -1135,11 +1107,11 @@ DEFUN (ipv6_nd_homeagent_lifetime, "Home Agent lifetime\n" "Home Agent lifetime in seconds (0 to track ra-lifetime)\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; - zif->rtadv.HomeAgentLifetime = strtoul(argv[idx_number]->arg, NULL, 10); - return CMD_SUCCESS; + int idx_number = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + zif->rtadv.HomeAgentLifetime = strtoul(argv[idx_number]->arg, NULL, 10); + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_homeagent_lifetime, @@ -1151,12 +1123,12 @@ DEFUN (no_ipv6_nd_homeagent_lifetime, "Home Agent lifetime\n" "Home Agent lifetime in seconds (0 to track ra-lifetime)\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.HomeAgentLifetime = -1; + zif->rtadv.HomeAgentLifetime = -1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_nd_managed_config_flag, @@ -1166,12 +1138,12 @@ DEFUN (ipv6_nd_managed_config_flag, "Neighbor discovery\n" "Managed address configuration flag\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.AdvManagedFlag = 1; + zif->rtadv.AdvManagedFlag = 1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_managed_config_flag, @@ -1182,12 +1154,12 @@ DEFUN (no_ipv6_nd_managed_config_flag, "Neighbor discovery\n" "Managed address configuration flag\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.AdvManagedFlag = 0; + zif->rtadv.AdvManagedFlag = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_nd_homeagent_config_flag, @@ -1197,12 +1169,12 @@ DEFUN (ipv6_nd_homeagent_config_flag, "Neighbor discovery\n" "Home Agent configuration flag\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.AdvHomeAgentFlag = 1; + zif->rtadv.AdvHomeAgentFlag = 1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_homeagent_config_flag, @@ -1213,12 +1185,12 @@ DEFUN (no_ipv6_nd_homeagent_config_flag, "Neighbor discovery\n" "Home Agent configuration flag\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.AdvHomeAgentFlag = 0; + zif->rtadv.AdvHomeAgentFlag = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_nd_adv_interval_config_option, @@ -1228,12 +1200,12 @@ DEFUN (ipv6_nd_adv_interval_config_option, "Neighbor discovery\n" "Advertisement Interval Option\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.AdvIntervalOption = 1; + zif->rtadv.AdvIntervalOption = 1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_adv_interval_config_option, @@ -1244,12 +1216,12 @@ DEFUN (no_ipv6_nd_adv_interval_config_option, "Neighbor discovery\n" "Advertisement Interval Option\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.AdvIntervalOption = 0; + zif->rtadv.AdvIntervalOption = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_nd_other_config_flag, @@ -1259,12 +1231,12 @@ DEFUN (ipv6_nd_other_config_flag, "Neighbor discovery\n" "Other statefull configuration flag\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.AdvOtherConfigFlag = 1; + zif->rtadv.AdvOtherConfigFlag = 1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_other_config_flag, @@ -1275,12 +1247,12 @@ DEFUN (no_ipv6_nd_other_config_flag, "Neighbor discovery\n" "Other statefull configuration flag\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.AdvOtherConfigFlag = 0; + zif->rtadv.AdvOtherConfigFlag = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_nd_prefix, @@ -1300,63 +1272,70 @@ DEFUN (ipv6_nd_prefix, "Do not use prefix for autoconfiguration\n" "Do not use prefix for onlink determination\n") { - /* prelude */ - char *prefix = argv[3]->arg; - int lifetimes = (argc > 4) && (argv[4]->type == RANGE_TKN || strmatch (argv[4]->text, "infinite")); - int routeropts = lifetimes ? argc > 6 : argc > 4; - - int idx_routeropts = routeropts ? (lifetimes ? 6 : 4) : 0; - - char *lifetime = NULL, *preflifetime = NULL; - int routeraddr = 0, offlink = 0, noautoconf = 0; - if (lifetimes) - { - lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg : argv[4]->text; - preflifetime = argv[5]->type == RANGE_TKN ? argv[5]->arg : argv[5]->text; - } - if (routeropts) - { - routeraddr = strmatch (argv[idx_routeropts]->text, "router-address"); - if (!routeraddr) - { - offlink = (argc > idx_routeropts + 1 || strmatch (argv[idx_routeropts]->text, "off-link")); - noautoconf = (argc > idx_routeropts + 1 || strmatch (argv[idx_routeropts]->text, "no-autoconfig")); - } - } - - /* business */ - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zebra_if = ifp->info; - int ret; - struct rtadv_prefix rp; - - ret = str2prefix_ipv6 (prefix, &rp.prefix); - if (!ret) - { - vty_out (vty, "Malformed IPv6 prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */ - rp.AdvOnLinkFlag = !offlink; - rp.AdvAutonomousFlag = !noautoconf; - rp.AdvRouterAddressFlag = routeraddr; - rp.AdvValidLifetime = RTADV_VALID_LIFETIME; - rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME; - - if (lifetimes) - { - rp.AdvValidLifetime = strmatch (lifetime, "infinite") ? UINT32_MAX : strtoll (lifetime, NULL, 10); - rp.AdvPreferredLifetime = strmatch (preflifetime, "infinite") ? UINT32_MAX : strtoll (preflifetime, NULL, 10); - if (rp.AdvPreferredLifetime > rp.AdvValidLifetime) - { - vty_out (vty, "Invalid preferred lifetime\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - rtadv_prefix_set (zebra_if, &rp); - - return CMD_SUCCESS; + /* prelude */ + char *prefix = argv[3]->arg; + int lifetimes = (argc > 4) && (argv[4]->type == RANGE_TKN + || strmatch(argv[4]->text, "infinite")); + int routeropts = lifetimes ? argc > 6 : argc > 4; + + int idx_routeropts = routeropts ? (lifetimes ? 6 : 4) : 0; + + char *lifetime = NULL, *preflifetime = NULL; + int routeraddr = 0, offlink = 0, noautoconf = 0; + if (lifetimes) { + lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg + : argv[4]->text; + preflifetime = argv[5]->type == RANGE_TKN ? argv[5]->arg + : argv[5]->text; + } + if (routeropts) { + routeraddr = + strmatch(argv[idx_routeropts]->text, "router-address"); + if (!routeraddr) { + offlink = (argc > idx_routeropts + 1 + || strmatch(argv[idx_routeropts]->text, + "off-link")); + noautoconf = (argc > idx_routeropts + 1 + || strmatch(argv[idx_routeropts]->text, + "no-autoconfig")); + } + } + + /* business */ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zebra_if = ifp->info; + int ret; + struct rtadv_prefix rp; + + ret = str2prefix_ipv6(prefix, &rp.prefix); + if (!ret) { + vty_out(vty, "Malformed IPv6 prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */ + rp.AdvOnLinkFlag = !offlink; + rp.AdvAutonomousFlag = !noautoconf; + rp.AdvRouterAddressFlag = routeraddr; + rp.AdvValidLifetime = RTADV_VALID_LIFETIME; + rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME; + + if (lifetimes) { + rp.AdvValidLifetime = strmatch(lifetime, "infinite") + ? UINT32_MAX + : strtoll(lifetime, NULL, 10); + rp.AdvPreferredLifetime = + strmatch(preflifetime, "infinite") + ? UINT32_MAX + : strtoll(preflifetime, NULL, 10); + if (rp.AdvPreferredLifetime > rp.AdvValidLifetime) { + vty_out(vty, "Invalid preferred lifetime\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + rtadv_prefix_set(zebra_if, &rp); + + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_prefix, @@ -1377,28 +1356,26 @@ DEFUN (no_ipv6_nd_prefix, "Do not use prefix for autoconfiguration\n" "Do not use prefix for onlink determination\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zebra_if = ifp->info; - int ret; - struct rtadv_prefix rp; - char *prefix = argv[4]->arg; - - ret = str2prefix_ipv6 (prefix, &rp.prefix); - if (!ret) - { - vty_out (vty, "Malformed IPv6 prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */ - - ret = rtadv_prefix_reset (zebra_if, &rp); - if (!ret) - { - vty_out (vty, "Non-existant IPv6 prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zebra_if = ifp->info; + int ret; + struct rtadv_prefix rp; + char *prefix = argv[4]->arg; + + ret = str2prefix_ipv6(prefix, &rp.prefix); + if (!ret) { + vty_out(vty, "Malformed IPv6 prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + apply_mask_ipv6(&rp.prefix); /* RFC4861 4.6.2 */ + + ret = rtadv_prefix_reset(zebra_if, &rp); + if (!ret) { + vty_out(vty, "Non-existant IPv6 prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } DEFUN (ipv6_nd_router_preference, @@ -1411,22 +1388,22 @@ DEFUN (ipv6_nd_router_preference, "Medium default router preference (default)\n" "Low default router preference\n") { - int idx_high_medium_low = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; - int i = 0; - - while (0 != rtadv_pref_strs[i]) - { - if (strncmp (argv[idx_high_medium_low]->arg, rtadv_pref_strs[i], 1) == 0) - { - zif->rtadv.DefaultPreference = i; - return CMD_SUCCESS; + int idx_high_medium_low = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + int i = 0; + + while (0 != rtadv_pref_strs[i]) { + if (strncmp(argv[idx_high_medium_low]->arg, rtadv_pref_strs[i], + 1) + == 0) { + zif->rtadv.DefaultPreference = i; + return CMD_SUCCESS; + } + i++; } - i++; - } - return CMD_ERR_NO_MATCH; + return CMD_ERR_NO_MATCH; } DEFUN (no_ipv6_nd_router_preference, @@ -1440,12 +1417,13 @@ DEFUN (no_ipv6_nd_router_preference, "Medium default router preference (default)\n" "Low default router preference\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; - zif->rtadv.DefaultPreference = RTADV_PREF_MEDIUM; /* Default per RFC4191. */ + zif->rtadv.DefaultPreference = + RTADV_PREF_MEDIUM; /* Default per RFC4191. */ - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ipv6_nd_mtu, @@ -1456,11 +1434,11 @@ DEFUN (ipv6_nd_mtu, "Advertised MTU\n" "MTU in bytes\n") { - int idx_number = 3; - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; - zif->rtadv.AdvLinkMTU = strtoul(argv[idx_number]->arg, NULL, 10); - return CMD_SUCCESS; + int idx_number = 3; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + zif->rtadv.AdvLinkMTU = strtoul(argv[idx_number]->arg, NULL, 10); + return CMD_SUCCESS; } DEFUN (no_ipv6_nd_mtu, @@ -1472,253 +1450,246 @@ DEFUN (no_ipv6_nd_mtu, "Advertised MTU\n" "MTU in bytes\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *zif = ifp->info; - zif->rtadv.AdvLinkMTU = 0; - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *zif = ifp->info; + zif->rtadv.AdvLinkMTU = 0; + return CMD_SUCCESS; } /* Write configuration about router advertisement. */ -void -rtadv_config_write (struct vty *vty, struct interface *ifp) +void rtadv_config_write(struct vty *vty, struct interface *ifp) { - struct zebra_if *zif; - struct listnode *node; - struct rtadv_prefix *rprefix; - char buf[PREFIX_STRLEN]; - int interval; - - zif = ifp->info; - - if (!(if_is_loopback (ifp) || - CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))) - { - if (zif->rtadv.AdvSendAdvertisements) - vty_out (vty, " no ipv6 nd suppress-ra\n"); - } - - interval = zif->rtadv.MaxRtrAdvInterval; - if (interval % 1000) - vty_out (vty, " ipv6 nd ra-interval msec %d\n",interval); - else - if (interval != RTADV_MAX_RTR_ADV_INTERVAL) - vty_out (vty, " ipv6 nd ra-interval %d\n",interval / 1000); - - if (zif->rtadv.AdvIntervalOption) - vty_out (vty, " ipv6 nd adv-interval-option\n"); - - if (zif->rtadv.AdvDefaultLifetime != -1) - vty_out (vty, " ipv6 nd ra-lifetime %d\n",zif->rtadv.AdvDefaultLifetime); - - if (zif->rtadv.HomeAgentPreference) - vty_out (vty, " ipv6 nd home-agent-preference %u\n", - zif->rtadv.HomeAgentPreference); - - if (zif->rtadv.HomeAgentLifetime != -1) - vty_out (vty, " ipv6 nd home-agent-lifetime %u\n", - zif->rtadv.HomeAgentLifetime); - - if (zif->rtadv.AdvHomeAgentFlag) - vty_out (vty, " ipv6 nd home-agent-config-flag\n"); - - if (zif->rtadv.AdvReachableTime) - vty_out (vty, " ipv6 nd reachable-time %d\n", - zif->rtadv.AdvReachableTime); - - if (zif->rtadv.AdvManagedFlag) - vty_out (vty, " ipv6 nd managed-config-flag\n"); - - if (zif->rtadv.AdvOtherConfigFlag) - vty_out (vty, " ipv6 nd other-config-flag\n"); - - if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM) - vty_out (vty, " ipv6 nd router-preference %s\n", - rtadv_pref_strs[zif->rtadv.DefaultPreference]); - - if (zif->rtadv.AdvLinkMTU) - vty_out (vty, " ipv6 nd mtu %d\n", zif->rtadv.AdvLinkMTU); - - for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix)) - { - vty_out (vty, " ipv6 nd prefix %s", - prefix2str (&rprefix->prefix, buf, sizeof(buf))); - if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) || - (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME)) - { - if (rprefix->AdvValidLifetime == UINT32_MAX) - vty_out (vty, " infinite"); - else - vty_out (vty, " %u", rprefix->AdvValidLifetime); - if (rprefix->AdvPreferredLifetime == UINT32_MAX) - vty_out (vty, " infinite"); - else - vty_out (vty, " %u", rprefix->AdvPreferredLifetime); + struct zebra_if *zif; + struct listnode *node; + struct rtadv_prefix *rprefix; + char buf[PREFIX_STRLEN]; + int interval; + + zif = ifp->info; + + if (!(if_is_loopback(ifp) + || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))) { + if (zif->rtadv.AdvSendAdvertisements) + vty_out(vty, " no ipv6 nd suppress-ra\n"); + } + + interval = zif->rtadv.MaxRtrAdvInterval; + if (interval % 1000) + vty_out(vty, " ipv6 nd ra-interval msec %d\n", interval); + else if (interval != RTADV_MAX_RTR_ADV_INTERVAL) + vty_out(vty, " ipv6 nd ra-interval %d\n", interval / 1000); + + if (zif->rtadv.AdvIntervalOption) + vty_out(vty, " ipv6 nd adv-interval-option\n"); + + if (zif->rtadv.AdvDefaultLifetime != -1) + vty_out(vty, " ipv6 nd ra-lifetime %d\n", + zif->rtadv.AdvDefaultLifetime); + + if (zif->rtadv.HomeAgentPreference) + vty_out(vty, " ipv6 nd home-agent-preference %u\n", + zif->rtadv.HomeAgentPreference); + + if (zif->rtadv.HomeAgentLifetime != -1) + vty_out(vty, " ipv6 nd home-agent-lifetime %u\n", + zif->rtadv.HomeAgentLifetime); + + if (zif->rtadv.AdvHomeAgentFlag) + vty_out(vty, " ipv6 nd home-agent-config-flag\n"); + + if (zif->rtadv.AdvReachableTime) + vty_out(vty, " ipv6 nd reachable-time %d\n", + zif->rtadv.AdvReachableTime); + + if (zif->rtadv.AdvManagedFlag) + vty_out(vty, " ipv6 nd managed-config-flag\n"); + + if (zif->rtadv.AdvOtherConfigFlag) + vty_out(vty, " ipv6 nd other-config-flag\n"); + + if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM) + vty_out(vty, " ipv6 nd router-preference %s\n", + rtadv_pref_strs[zif->rtadv.DefaultPreference]); + + if (zif->rtadv.AdvLinkMTU) + vty_out(vty, " ipv6 nd mtu %d\n", zif->rtadv.AdvLinkMTU); + + for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvPrefixList, node, rprefix)) { + vty_out(vty, " ipv6 nd prefix %s", + prefix2str(&rprefix->prefix, buf, sizeof(buf))); + if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) + || (rprefix->AdvPreferredLifetime + != RTADV_PREFERRED_LIFETIME)) { + if (rprefix->AdvValidLifetime == UINT32_MAX) + vty_out(vty, " infinite"); + else + vty_out(vty, " %u", rprefix->AdvValidLifetime); + if (rprefix->AdvPreferredLifetime == UINT32_MAX) + vty_out(vty, " infinite"); + else + vty_out(vty, " %u", + rprefix->AdvPreferredLifetime); + } + if (!rprefix->AdvOnLinkFlag) + vty_out(vty, " off-link"); + if (!rprefix->AdvAutonomousFlag) + vty_out(vty, " no-autoconfig"); + if (rprefix->AdvRouterAddressFlag) + vty_out(vty, " router-address"); + vty_out(vty, "\n"); } - if (!rprefix->AdvOnLinkFlag) - vty_out (vty, " off-link"); - if (!rprefix->AdvAutonomousFlag) - vty_out (vty, " no-autoconfig"); - if (rprefix->AdvRouterAddressFlag) - vty_out (vty, " router-address"); - vty_out (vty, "\n"); - } } -static void -rtadv_event (struct zebra_ns *zns, enum rtadv_event event, int val) +static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val) { - struct rtadv *rtadv = &zns->rtadv; - - switch (event) - { - case RTADV_START: - thread_add_read(zebrad.master, rtadv_read, zns, val, &rtadv->ra_read); - thread_add_event(zebrad.master, rtadv_timer, zns, 0, &rtadv->ra_timer); - break; - case RTADV_STOP: - if (rtadv->ra_timer) - { - thread_cancel (rtadv->ra_timer); - rtadv->ra_timer = NULL; + struct rtadv *rtadv = &zns->rtadv; + + switch (event) { + case RTADV_START: + thread_add_read(zebrad.master, rtadv_read, zns, val, + &rtadv->ra_read); + thread_add_event(zebrad.master, rtadv_timer, zns, 0, + &rtadv->ra_timer); + break; + case RTADV_STOP: + if (rtadv->ra_timer) { + thread_cancel(rtadv->ra_timer); + rtadv->ra_timer = NULL; + } + if (rtadv->ra_read) { + thread_cancel(rtadv->ra_read); + rtadv->ra_read = NULL; + } + break; + case RTADV_TIMER: + thread_add_timer(zebrad.master, rtadv_timer, zns, val, + &rtadv->ra_timer); + break; + case RTADV_TIMER_MSEC: + thread_add_timer_msec(zebrad.master, rtadv_timer, zns, val, + &rtadv->ra_timer); + break; + case RTADV_READ: + thread_add_read(zebrad.master, rtadv_read, zns, val, + &rtadv->ra_read); + break; + default: + break; } - if (rtadv->ra_read) - { - thread_cancel (rtadv->ra_read); - rtadv->ra_read = NULL; - } - break; - case RTADV_TIMER: - thread_add_timer(zebrad.master, rtadv_timer, zns, val, &rtadv->ra_timer); - break; - case RTADV_TIMER_MSEC: - thread_add_timer_msec(zebrad.master, rtadv_timer, zns, val, - &rtadv->ra_timer); - break; - case RTADV_READ: - thread_add_read(zebrad.master, rtadv_read, zns, val, &rtadv->ra_read); - break; - default: - break; - } - return; + return; } -void -rtadv_init (struct zebra_ns *zns) +void rtadv_init(struct zebra_ns *zns) { - zns->rtadv.sock = rtadv_make_socket (); + zns->rtadv.sock = rtadv_make_socket(); } -void -rtadv_terminate (struct zebra_ns *zns) +void rtadv_terminate(struct zebra_ns *zns) { - rtadv_event (zns, RTADV_STOP, 0); - if (zns->rtadv.sock >= 0) - { - close (zns->rtadv.sock); - zns->rtadv.sock = -1; - } - - zns->rtadv.adv_if_count = 0; - zns->rtadv.adv_msec_if_count = 0; + rtadv_event(zns, RTADV_STOP, 0); + if (zns->rtadv.sock >= 0) { + close(zns->rtadv.sock); + zns->rtadv.sock = -1; + } + + zns->rtadv.adv_if_count = 0; + zns->rtadv.adv_msec_if_count = 0; } -void -rtadv_cmd_init (void) +void rtadv_cmd_init(void) { - install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd); - install_element (INTERFACE_NODE, &ipv6_nd_mtu_cmd); - install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_reachable_time_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd); + install_element(INTERFACE_NODE, + &ipv6_nd_adv_interval_config_option_cmd); + install_element(INTERFACE_NODE, + &no_ipv6_nd_adv_interval_config_option_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_prefix_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_prefix_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_router_preference_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd); + install_element(INTERFACE_NODE, &ipv6_nd_mtu_cmd); + install_element(INTERFACE_NODE, &no_ipv6_nd_mtu_cmd); } -static int -if_join_all_router (int sock, struct interface *ifp) +static int if_join_all_router(int sock, struct interface *ifp) { - int ret; + int ret; - struct ipv6_mreq mreq; + struct ipv6_mreq mreq; - memset (&mreq, 0, sizeof (struct ipv6_mreq)); - inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr); - mreq.ipv6mr_interface = ifp->ifindex; + memset(&mreq, 0, sizeof(struct ipv6_mreq)); + inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr); + mreq.ipv6mr_interface = ifp->ifindex; - ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, - (char *) &mreq, sizeof mreq); - if (ret < 0) - zlog_warn ("%s(%u): Failed to join group, socket %u error %s", - ifp->name, ifp->ifindex, sock, safe_strerror (errno)); + ret = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mreq, + sizeof mreq); + if (ret < 0) + zlog_warn("%s(%u): Failed to join group, socket %u error %s", + ifp->name, ifp->ifindex, sock, safe_strerror(errno)); - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("%s(%u): Join All-Routers multicast group, socket %u", - ifp->name, ifp->ifindex, sock); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "%s(%u): Join All-Routers multicast group, socket %u", + ifp->name, ifp->ifindex, sock); - return 0; + return 0; } -static int -if_leave_all_router (int sock, struct interface *ifp) +static int if_leave_all_router(int sock, struct interface *ifp) { - int ret; + int ret; - struct ipv6_mreq mreq; + struct ipv6_mreq mreq; - memset (&mreq, 0, sizeof (struct ipv6_mreq)); - inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr); - mreq.ipv6mr_interface = ifp->ifindex; + memset(&mreq, 0, sizeof(struct ipv6_mreq)); + inet_pton(AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr); + mreq.ipv6mr_interface = ifp->ifindex; - ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, - (char *) &mreq, sizeof mreq); - if (ret < 0) - zlog_warn ("%s(%u): Failed to leave group, socket %u error %s", - ifp->name, ifp->ifindex, sock,safe_strerror (errno)); + ret = setsockopt(sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, (char *)&mreq, + sizeof mreq); + if (ret < 0) + zlog_warn("%s(%u): Failed to leave group, socket %u error %s", + ifp->name, ifp->ifindex, sock, safe_strerror(errno)); - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("%s(%u): Leave All-Routers multicast group, socket %u", - ifp->name, ifp->ifindex, sock); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "%s(%u): Leave All-Routers multicast group, socket %u", + ifp->name, ifp->ifindex, sock); - return 0; + return 0; } #else -void -rtadv_init (struct zebra_ns *zns) +void rtadv_init(struct zebra_ns *zns) { - /* Empty.*/; + /* Empty.*/; } -void -rtadv_terminate (struct zebra_ns *zns) +void rtadv_terminate(struct zebra_ns *zns) { - /* Empty.*/; + /* Empty.*/; } -void -rtadv_cmd_init (void) +void rtadv_cmd_init(void) { - /* Empty.*/; + /* Empty.*/; } #endif /* HAVE_RTADV */ diff --git a/zebra/rtadv.h b/zebra/rtadv.h index 5f389b30a..029c97cdd 100644 --- a/zebra/rtadv.h +++ b/zebra/rtadv.h @@ -26,38 +26,36 @@ #include "zebra/interface.h" /* NB: RTADV is defined in zebra/interface.h above */ -#if defined (HAVE_RTADV) +#if defined(HAVE_RTADV) /* Router advertisement prefix. */ -struct rtadv_prefix -{ - /* Prefix to be advertised. */ - struct prefix_ipv6 prefix; - - /* The value to be placed in the Valid Lifetime in the Prefix */ - u_int32_t AdvValidLifetime; +struct rtadv_prefix { + /* Prefix to be advertised. */ + struct prefix_ipv6 prefix; + + /* The value to be placed in the Valid Lifetime in the Prefix */ + u_int32_t AdvValidLifetime; #define RTADV_VALID_LIFETIME 2592000 - /* The value to be placed in the on-link flag */ - int AdvOnLinkFlag; + /* The value to be placed in the on-link flag */ + int AdvOnLinkFlag; - /* The value to be placed in the Preferred Lifetime in the Prefix - Information option, in seconds.*/ - u_int32_t AdvPreferredLifetime; + /* The value to be placed in the Preferred Lifetime in the Prefix + Information option, in seconds.*/ + u_int32_t AdvPreferredLifetime; #define RTADV_PREFERRED_LIFETIME 604800 - /* The value to be placed in the Autonomous Flag. */ - int AdvAutonomousFlag; + /* The value to be placed in the Autonomous Flag. */ + int AdvAutonomousFlag; - /* The value to be placed in the Router Address Flag [RFC6275 7.2]. */ - int AdvRouterAddressFlag; + /* The value to be placed in the Router Address Flag [RFC6275 7.2]. */ + int AdvRouterAddressFlag; #ifndef ND_OPT_PI_FLAG_RADDR #define ND_OPT_PI_FLAG_RADDR 0x20 #endif - }; -extern void rtadv_config_write (struct vty *, struct interface *); +extern void rtadv_config_write(struct vty *, struct interface *); /* RFC4584 Extension to Sockets API for Mobile IPv6 */ @@ -69,11 +67,11 @@ extern void rtadv_config_write (struct vty *, struct interface *); #endif #ifndef HAVE_STRUCT_ND_OPT_ADV_INTERVAL -struct nd_opt_adv_interval { /* Advertisement interval option */ - uint8_t nd_opt_ai_type; - uint8_t nd_opt_ai_len; - uint16_t nd_opt_ai_reserved; - uint32_t nd_opt_ai_interval; +struct nd_opt_adv_interval { /* Advertisement interval option */ + uint8_t nd_opt_ai_type; + uint8_t nd_opt_ai_len; + uint16_t nd_opt_ai_reserved; + uint32_t nd_opt_ai_interval; } __attribute__((__packed__)); #else #ifndef HAVE_STRUCT_ND_OPT_ADV_INTERVAL_ND_OPT_AI_TYPE @@ -86,12 +84,12 @@ struct nd_opt_adv_interval { /* Advertisement interval option */ #endif #ifndef HAVE_STRUCT_ND_OPT_HOMEAGENT_INFO -struct nd_opt_homeagent_info { /* Home Agent info */ - u_int8_t nd_opt_hai_type; - u_int8_t nd_opt_hai_len; - u_int16_t nd_opt_hai_reserved; - u_int16_t nd_opt_hai_preference; - u_int16_t nd_opt_hai_lifetime; +struct nd_opt_homeagent_info { /* Home Agent info */ + u_int8_t nd_opt_hai_type; + u_int8_t nd_opt_hai_len; + u_int16_t nd_opt_hai_reserved; + u_int16_t nd_opt_hai_preference; + u_int16_t nd_opt_hai_lifetime; } __attribute__((__packed__)); #endif @@ -100,14 +98,15 @@ extern const char *rtadv_pref_strs[]; #endif /* HAVE_RTADV */ typedef enum { - RA_ENABLE = 0, - RA_SUPPRESS, + RA_ENABLE = 0, + RA_SUPPRESS, } ipv6_nd_suppress_ra_status; -extern void rtadv_init (struct zebra_ns *); -extern void rtadv_terminate (struct zebra_ns *); -extern void rtadv_cmd_init (void); -extern void zebra_interface_radv_set (struct zserv *client, int sock, u_short length, - struct zebra_vrf *zvrf, int enable); +extern void rtadv_init(struct zebra_ns *); +extern void rtadv_terminate(struct zebra_ns *); +extern void rtadv_cmd_init(void); +extern void zebra_interface_radv_set(struct zserv *client, int sock, + u_short length, struct zebra_vrf *zvrf, + int enable); #endif /* _ZEBRA_RTADV_H */ diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c index b1bef571b..5384231f8 100644 --- a/zebra/rtread_getmsg.c +++ b/zebra/rtread_getmsg.c @@ -50,8 +50,7 @@ #define IRE_HOST_REDIRECT 0x0200 /* Host route entry from redirects */ #endif /* IRE_HOST_REDIRECT */ #ifndef IRE_CACHETABLE -#define IRE_CACHETABLE (IRE_CACHE | IRE_BROADCAST | IRE_LOCAL | \ - IRE_LOOPBACK) +#define IRE_CACHETABLE (IRE_CACHE | IRE_BROADCAST | IRE_LOCAL | IRE_LOOPBACK) #endif /* IRE_CACHETABLE */ #undef IPOPT_EOL #undef IPOPT_NOP @@ -71,123 +70,124 @@ #define RT_BUFSIZ 8192 -static void -handle_route_entry (mib2_ipRouteEntry_t *routeEntry) +static void handle_route_entry(mib2_ipRouteEntry_t *routeEntry) { - struct prefix prefix; - struct in_addr tmpaddr, gateway; - union g_addr *ggateway; - u_char zebra_flags = 0; + struct prefix prefix; + struct in_addr tmpaddr, gateway; + union g_addr *ggateway; + u_char zebra_flags = 0; - if (routeEntry->ipRouteInfo.re_ire_type & IRE_CACHETABLE) - return; + if (routeEntry->ipRouteInfo.re_ire_type & IRE_CACHETABLE) + return; - if (routeEntry->ipRouteInfo.re_ire_type & IRE_HOST_REDIRECT) - zebra_flags |= ZEBRA_FLAG_SELFROUTE; + if (routeEntry->ipRouteInfo.re_ire_type & IRE_HOST_REDIRECT) + zebra_flags |= ZEBRA_FLAG_SELFROUTE; - prefix.family = AF_INET; + prefix.family = AF_INET; - tmpaddr.s_addr = routeEntry->ipRouteDest; - prefix.u.prefix4 = tmpaddr; + tmpaddr.s_addr = routeEntry->ipRouteDest; + prefix.u.prefix4 = tmpaddr; - tmpaddr.s_addr = routeEntry->ipRouteMask; - prefix.prefixlen = ip_masklen (tmpaddr); + tmpaddr.s_addr = routeEntry->ipRouteMask; + prefix.prefixlen = ip_masklen(tmpaddr); - gateway.s_addr = routeEntry->ipRouteNextHop; - ggateway = (union g_addr *)&gateway; + gateway.s_addr = routeEntry->ipRouteNextHop; + ggateway = (union g_addr *)&gateway; - rib_add (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, - zebra_flags, &prefix, NULL, ggateway, NULL, 0, 0, 0, 0, 0); + rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, + zebra_flags, &prefix, NULL, ggateway, NULL, 0, 0, 0, 0, 0); } -void -route_read (struct zebra_ns *zns) +void route_read(struct zebra_ns *zns) { - char storage[RT_BUFSIZ]; + char storage[RT_BUFSIZ]; - struct T_optmgmt_req *TLIreq = (struct T_optmgmt_req *) storage; - struct T_optmgmt_ack *TLIack = (struct T_optmgmt_ack *) storage; - struct T_error_ack *TLIerr = (struct T_error_ack *) storage; + struct T_optmgmt_req *TLIreq = (struct T_optmgmt_req *)storage; + struct T_optmgmt_ack *TLIack = (struct T_optmgmt_ack *)storage; + struct T_error_ack *TLIerr = (struct T_error_ack *)storage; - struct opthdr *MIB2hdr; + struct opthdr *MIB2hdr; - mib2_ipRouteEntry_t *routeEntry, *lastRouteEntry; + mib2_ipRouteEntry_t *routeEntry, *lastRouteEntry; - struct strbuf msgdata; - int flags, dev, retval, process; + struct strbuf msgdata; + int flags, dev, retval, process; - if ((dev = open (_PATH_GETMSG_ROUTE, O_RDWR)) == -1) { - zlog_warn ("can't open %s: %s", _PATH_GETMSG_ROUTE, - safe_strerror (errno)); + if ((dev = open(_PATH_GETMSG_ROUTE, O_RDWR)) == -1) { + zlog_warn("can't open %s: %s", _PATH_GETMSG_ROUTE, + safe_strerror(errno)); return; } TLIreq->PRIM_type = T_OPTMGMT_REQ; - TLIreq->OPT_offset = sizeof (struct T_optmgmt_req); - TLIreq->OPT_length = sizeof (struct opthdr); + TLIreq->OPT_offset = sizeof(struct T_optmgmt_req); + TLIreq->OPT_length = sizeof(struct opthdr); TLIreq->MGMT_flags = T_CURRENT; - MIB2hdr = (struct opthdr *) &TLIreq[1]; + MIB2hdr = (struct opthdr *)&TLIreq[1]; MIB2hdr->level = MIB2_IP; MIB2hdr->name = 0; MIB2hdr->len = 0; - + msgdata.buf = storage; - msgdata.len = sizeof (struct T_optmgmt_req) + sizeof (struct opthdr); + msgdata.len = sizeof(struct T_optmgmt_req) + sizeof(struct opthdr); flags = 0; - if (putmsg (dev, &msgdata, NULL, flags) == -1) { - zlog_warn ("putmsg failed: %s", safe_strerror (errno)); + if (putmsg(dev, &msgdata, NULL, flags) == -1) { + zlog_warn("putmsg failed: %s", safe_strerror(errno)); goto exit; } - MIB2hdr = (struct opthdr *) &TLIack[1]; - msgdata.maxlen = sizeof (storage); + MIB2hdr = (struct opthdr *)&TLIack[1]; + msgdata.maxlen = sizeof(storage); while (1) { flags = 0; - retval = getmsg (dev, &msgdata, NULL, &flags); + retval = getmsg(dev, &msgdata, NULL, &flags); if (retval == -1) { - zlog_warn ("getmsg(ctl) failed: %s", safe_strerror (errno)); + zlog_warn("getmsg(ctl) failed: %s", + safe_strerror(errno)); goto exit; } /* This is normal loop termination */ - if (retval == 0 && - (size_t)msgdata.len >= sizeof (struct T_optmgmt_ack) && - TLIack->PRIM_type == T_OPTMGMT_ACK && - TLIack->MGMT_flags == T_SUCCESS && - MIB2hdr->len == 0) + if (retval == 0 + && (size_t)msgdata.len >= sizeof(struct T_optmgmt_ack) + && TLIack->PRIM_type == T_OPTMGMT_ACK + && TLIack->MGMT_flags == T_SUCCESS && MIB2hdr->len == 0) break; - if ((size_t)msgdata.len >= sizeof (struct T_error_ack) && - TLIerr->PRIM_type == T_ERROR_ACK) { - zlog_warn ("getmsg(ctl) returned T_ERROR_ACK: %s", - safe_strerror ((TLIerr->TLI_error == TSYSERR) - ? TLIerr->UNIX_error : EPROTO)); + if ((size_t)msgdata.len >= sizeof(struct T_error_ack) + && TLIerr->PRIM_type == T_ERROR_ACK) { + zlog_warn("getmsg(ctl) returned T_ERROR_ACK: %s", + safe_strerror((TLIerr->TLI_error == TSYSERR) + ? TLIerr->UNIX_error + : EPROTO)); break; } /* should dump more debugging info to the log statement, like what GateD does in this instance, but not critical yet. */ - if (retval != MOREDATA || - (size_t)msgdata.len < sizeof (struct T_optmgmt_ack) || - TLIack->PRIM_type != T_OPTMGMT_ACK || - TLIack->MGMT_flags != T_SUCCESS) { + if (retval != MOREDATA + || (size_t)msgdata.len < sizeof(struct T_optmgmt_ack) + || TLIack->PRIM_type != T_OPTMGMT_ACK + || TLIack->MGMT_flags != T_SUCCESS) { errno = ENOMSG; - zlog_warn ("getmsg(ctl) returned bizarreness"); + zlog_warn("getmsg(ctl) returned bizarreness"); break; } /* MIB2_IP_21 is the the pseudo-MIB2 ipRouteTable entry, see . "This isn't the MIB data you're looking for." */ - process = (MIB2hdr->level == MIB2_IP && - MIB2hdr->name == MIB2_IP_21) ? 1 : 0; + process = (MIB2hdr->level == MIB2_IP + && MIB2hdr->name == MIB2_IP_21) + ? 1 + : 0; /* getmsg writes the data buffer out completely, not to the closest smaller multiple. Unless reassembling @@ -195,65 +195,66 @@ route_read (struct zebra_ns *zns) of a good time, set maxlen to the closest smaller multiple of the size of the datastructure you're retrieving. */ - msgdata.maxlen = sizeof (storage) - (sizeof (storage) - % sizeof (mib2_ipRouteEntry_t)); + msgdata.maxlen = + sizeof(storage) + - (sizeof(storage) % sizeof(mib2_ipRouteEntry_t)); msgdata.len = 0; flags = 0; do { - retval = getmsg (dev, NULL, &msgdata, &flags); + retval = getmsg(dev, NULL, &msgdata, &flags); if (retval == -1) { - zlog_warn ("getmsg(data) failed: %s", - safe_strerror (errno)); + zlog_warn("getmsg(data) failed: %s", + safe_strerror(errno)); goto exit; } if (!(retval == 0 || retval == MOREDATA)) { - zlog_warn ("getmsg(data) returned %d", retval); + zlog_warn("getmsg(data) returned %d", retval); goto exit; } if (process) { - if (msgdata.len % - sizeof (mib2_ipRouteEntry_t) != 0) { - zlog_warn ("getmsg(data) returned " -"msgdata.len = %d (%% sizeof (mib2_ipRouteEntry_t) != 0)", msgdata.len); + if (msgdata.len % sizeof(mib2_ipRouteEntry_t) + != 0) { + zlog_warn( + "getmsg(data) returned " + "msgdata.len = %d (%% sizeof (mib2_ipRouteEntry_t) != 0)", + msgdata.len); goto exit; } - routeEntry = (mib2_ipRouteEntry_t *) - msgdata.buf; - lastRouteEntry = (mib2_ipRouteEntry_t *) - (msgdata.buf + msgdata.len); + routeEntry = (mib2_ipRouteEntry_t *)msgdata.buf; + lastRouteEntry = + (mib2_ipRouteEntry_t *)(msgdata.buf + + msgdata.len); do { - handle_route_entry (routeEntry); + handle_route_entry(routeEntry); } while (++routeEntry < lastRouteEntry); } } while (retval == MOREDATA); } exit: - close (dev); + close(dev); } /* Only implemented for netlink method */ -void -macfdb_read (struct zebra_ns *zns) +void macfdb_read(struct zebra_ns *zns) { } -void macfdb_read_for_bridge (struct zebra_ns *zns, struct interface *ifp, - struct interface *br_if) +void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp, + struct interface *br_if) { } -void -neigh_read (struct zebra_ns *zns) +void neigh_read(struct zebra_ns *zns) { } -void neigh_read_for_vlan (struct zebra_ns *zns, struct interface *vlan_if) +void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if) { } diff --git a/zebra/rtread_netlink.c b/zebra/rtread_netlink.c index d26aa59f8..304f44136 100644 --- a/zebra/rtread_netlink.c +++ b/zebra/rtread_netlink.c @@ -25,28 +25,28 @@ #include "zebra/zserv.h" #include "zebra/rt_netlink.h" -void route_read (struct zebra_ns *zns) +void route_read(struct zebra_ns *zns) { - netlink_route_read (zns); + netlink_route_read(zns); } -void macfdb_read (struct zebra_ns *zns) +void macfdb_read(struct zebra_ns *zns) { - netlink_macfdb_read (zns); + netlink_macfdb_read(zns); } -void macfdb_read_for_bridge (struct zebra_ns *zns, struct interface *ifp, - struct interface *br_if) +void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp, + struct interface *br_if) { - netlink_macfdb_read_for_bridge (zns, ifp, br_if); + netlink_macfdb_read_for_bridge(zns, ifp, br_if); } -void neigh_read (struct zebra_ns *zns) +void neigh_read(struct zebra_ns *zns) { - netlink_neigh_read (zns); + netlink_neigh_read(zns); } -void neigh_read_for_vlan (struct zebra_ns *zns, struct interface *vlan_if) +void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if) { - netlink_neigh_read_for_vlan (zns, vlan_if); + netlink_neigh_read_for_vlan(zns, vlan_if); } diff --git a/zebra/rtread_sysctl.c b/zebra/rtread_sysctl.c index 30e593d87..d3e2eb6fa 100644 --- a/zebra/rtread_sysctl.c +++ b/zebra/rtread_sysctl.c @@ -31,75 +31,62 @@ #include "zebra/kernel_socket.h" /* Kernel routing table read up by sysctl function. */ -void -route_read (struct zebra_ns *zns) +void route_read(struct zebra_ns *zns) { - caddr_t buf, end, ref; - size_t bufsiz; - struct rt_msghdr *rtm; - + caddr_t buf, end, ref; + size_t bufsiz; + struct rt_msghdr *rtm; + #define MIBSIZ 6 - int mib[MIBSIZ] = - { - CTL_NET, - PF_ROUTE, - 0, - 0, - NET_RT_DUMP, - 0 - }; - - if (zns->ns_id != NS_DEFAULT) - return; - - /* Get buffer size. */ - if (sysctl (mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) - { - zlog_warn ("sysctl fail: %s", safe_strerror (errno)); - return; - } - - /* Allocate buffer. */ - ref = buf = XMALLOC (MTYPE_TMP, bufsiz); - - /* Read routing table information by calling sysctl(). */ - if (sysctl (mib, MIBSIZ, buf, &bufsiz, NULL, 0) < 0) - { - zlog_warn ("sysctl() fail by %s", safe_strerror (errno)); - XFREE(MTYPE_TMP, ref); - return; - } - - for (end = buf + bufsiz; buf < end; buf += rtm->rtm_msglen) - { - rtm = (struct rt_msghdr *) buf; - /* We must set RTF_DONE here, so rtm_read() doesn't ignore the message. */ - SET_FLAG (rtm->rtm_flags, RTF_DONE); - rtm_read (rtm); - } - - /* Free buffer. */ - XFREE (MTYPE_TMP, ref); - - return; + int mib[MIBSIZ] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_DUMP, 0}; + + if (zns->ns_id != NS_DEFAULT) + return; + + /* Get buffer size. */ + if (sysctl(mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) { + zlog_warn("sysctl fail: %s", safe_strerror(errno)); + return; + } + + /* Allocate buffer. */ + ref = buf = XMALLOC(MTYPE_TMP, bufsiz); + + /* Read routing table information by calling sysctl(). */ + if (sysctl(mib, MIBSIZ, buf, &bufsiz, NULL, 0) < 0) { + zlog_warn("sysctl() fail by %s", safe_strerror(errno)); + XFREE(MTYPE_TMP, ref); + return; + } + + for (end = buf + bufsiz; buf < end; buf += rtm->rtm_msglen) { + rtm = (struct rt_msghdr *)buf; + /* We must set RTF_DONE here, so rtm_read() doesn't ignore the + * message. */ + SET_FLAG(rtm->rtm_flags, RTF_DONE); + rtm_read(rtm); + } + + /* Free buffer. */ + XFREE(MTYPE_TMP, ref); + + return; } /* Only implemented for the netlink method. */ -void -macfdb_read (struct zebra_ns *zns) +void macfdb_read(struct zebra_ns *zns) { } -void macfdb_read_for_bridge (struct zebra_ns *zns, struct interface *ifp, - struct interface *br_if) +void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp, + struct interface *br_if) { } -void -neigh_read (struct zebra_ns *zns) +void neigh_read(struct zebra_ns *zns) { } -void neigh_read_for_vlan (struct zebra_ns *zns, struct interface *vlan_if) +void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if) { } diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c index d04aff2d3..b88bce9e8 100644 --- a/zebra/zebra_fpm.c +++ b/zebra/zebra_fpm.c @@ -66,47 +66,46 @@ * Structure that holds state for iterating over all route_node * structures that are candidates for being communicated to the FPM. */ -typedef struct zfpm_rnodes_iter_t_ -{ - rib_tables_iter_t tables_iter; - route_table_iter_t iter; +typedef struct zfpm_rnodes_iter_t_ { + rib_tables_iter_t tables_iter; + route_table_iter_t iter; } zfpm_rnodes_iter_t; /* * Statistics. */ typedef struct zfpm_stats_t_ { - unsigned long connect_calls; - unsigned long connect_no_sock; + unsigned long connect_calls; + unsigned long connect_no_sock; - unsigned long read_cb_calls; + unsigned long read_cb_calls; - unsigned long write_cb_calls; - unsigned long write_calls; - unsigned long partial_writes; - unsigned long max_writes_hit; - unsigned long t_write_yields; + unsigned long write_cb_calls; + unsigned long write_calls; + unsigned long partial_writes; + unsigned long max_writes_hit; + unsigned long t_write_yields; - unsigned long nop_deletes_skipped; - unsigned long route_adds; - unsigned long route_dels; + unsigned long nop_deletes_skipped; + unsigned long route_adds; + unsigned long route_dels; - unsigned long updates_triggered; - unsigned long redundant_triggers; - unsigned long non_fpm_table_triggers; + unsigned long updates_triggered; + unsigned long redundant_triggers; + unsigned long non_fpm_table_triggers; - unsigned long dests_del_after_update; + unsigned long dests_del_after_update; - unsigned long t_conn_down_starts; - unsigned long t_conn_down_dests_processed; - unsigned long t_conn_down_yields; - unsigned long t_conn_down_finishes; + unsigned long t_conn_down_starts; + unsigned long t_conn_down_dests_processed; + unsigned long t_conn_down_yields; + unsigned long t_conn_down_finishes; - unsigned long t_conn_up_starts; - unsigned long t_conn_up_dests_processed; - unsigned long t_conn_up_yields; - unsigned long t_conn_up_aborts; - unsigned long t_conn_up_finishes; + unsigned long t_conn_up_starts; + unsigned long t_conn_up_dests_processed; + unsigned long t_conn_up_yields; + unsigned long t_conn_up_aborts; + unsigned long t_conn_up_finishes; } zfpm_stats_t; @@ -115,187 +114,182 @@ typedef struct zfpm_stats_t_ { */ typedef enum { - /* - * In this state we are not yet ready to connect to the FPM. This - * can happen when this module is disabled, or if we're cleaning up - * after a connection has gone down. - */ - ZFPM_STATE_IDLE, - - /* - * Ready to talk to the FPM and periodically trying to connect to - * it. - */ - ZFPM_STATE_ACTIVE, - - /* - * In the middle of bringing up a TCP connection. Specifically, - * waiting for a connect() call to complete asynchronously. - */ - ZFPM_STATE_CONNECTING, - - /* - * TCP connection to the FPM is up. - */ - ZFPM_STATE_ESTABLISHED + /* + * In this state we are not yet ready to connect to the FPM. This + * can happen when this module is disabled, or if we're cleaning up + * after a connection has gone down. + */ + ZFPM_STATE_IDLE, + + /* + * Ready to talk to the FPM and periodically trying to connect to + * it. + */ + ZFPM_STATE_ACTIVE, + + /* + * In the middle of bringing up a TCP connection. Specifically, + * waiting for a connect() call to complete asynchronously. + */ + ZFPM_STATE_CONNECTING, + + /* + * TCP connection to the FPM is up. + */ + ZFPM_STATE_ESTABLISHED } zfpm_state_t; /* * Message format to be used to communicate with the FPM. */ -typedef enum -{ - ZFPM_MSG_FORMAT_NONE, - ZFPM_MSG_FORMAT_NETLINK, - ZFPM_MSG_FORMAT_PROTOBUF, +typedef enum { + ZFPM_MSG_FORMAT_NONE, + ZFPM_MSG_FORMAT_NETLINK, + ZFPM_MSG_FORMAT_PROTOBUF, } zfpm_msg_format_e; /* * Globals. */ -typedef struct zfpm_glob_t_ -{ - - /* - * True if the FPM module has been enabled. - */ - int enabled; - - /* - * Message format to be used to communicate with the fpm. - */ - zfpm_msg_format_e message_format; - - struct thread_master *master; - - zfpm_state_t state; - - in_addr_t fpm_server; - /* - * Port on which the FPM is running. - */ - int fpm_port; - - /* - * List of rib_dest_t structures to be processed - */ - TAILQ_HEAD (zfpm_dest_q, rib_dest_t_) dest_q; - - /* - * Stream socket to the FPM. - */ - int sock; - - /* - * Buffers for messages to/from the FPM. - */ - struct stream *obuf; - struct stream *ibuf; - - /* - * Threads for I/O. - */ - struct thread *t_connect; - struct thread *t_write; - struct thread *t_read; - - /* - * Thread to clean up after the TCP connection to the FPM goes down - * and the state that belongs to it. - */ - struct thread *t_conn_down; - - struct { - zfpm_rnodes_iter_t iter; - } t_conn_down_state; - - /* - * Thread to take actions once the TCP conn to the FPM comes up, and - * the state that belongs to it. - */ - struct thread *t_conn_up; - - struct { - zfpm_rnodes_iter_t iter; - } t_conn_up_state; - - unsigned long connect_calls; - time_t last_connect_call_time; - - /* - * Stats from the start of the current statistics interval up to - * now. These are the counters we typically update in the code. - */ - zfpm_stats_t stats; - - /* - * Statistics that were gathered in the last collection interval. - */ - zfpm_stats_t last_ivl_stats; - - /* - * Cumulative stats from the last clear to the start of the current - * statistics interval. - */ - zfpm_stats_t cumulative_stats; - - /* - * Stats interval timer. - */ - struct thread *t_stats; - - /* - * If non-zero, the last time when statistics were cleared. - */ - time_t last_stats_clear_time; +typedef struct zfpm_glob_t_ { + + /* + * True if the FPM module has been enabled. + */ + int enabled; + + /* + * Message format to be used to communicate with the fpm. + */ + zfpm_msg_format_e message_format; + + struct thread_master *master; + + zfpm_state_t state; + + in_addr_t fpm_server; + /* + * Port on which the FPM is running. + */ + int fpm_port; + + /* + * List of rib_dest_t structures to be processed + */ + TAILQ_HEAD(zfpm_dest_q, rib_dest_t_) dest_q; + + /* + * Stream socket to the FPM. + */ + int sock; + + /* + * Buffers for messages to/from the FPM. + */ + struct stream *obuf; + struct stream *ibuf; + + /* + * Threads for I/O. + */ + struct thread *t_connect; + struct thread *t_write; + struct thread *t_read; + + /* + * Thread to clean up after the TCP connection to the FPM goes down + * and the state that belongs to it. + */ + struct thread *t_conn_down; + + struct { + zfpm_rnodes_iter_t iter; + } t_conn_down_state; + + /* + * Thread to take actions once the TCP conn to the FPM comes up, and + * the state that belongs to it. + */ + struct thread *t_conn_up; + + struct { + zfpm_rnodes_iter_t iter; + } t_conn_up_state; + + unsigned long connect_calls; + time_t last_connect_call_time; + + /* + * Stats from the start of the current statistics interval up to + * now. These are the counters we typically update in the code. + */ + zfpm_stats_t stats; + + /* + * Statistics that were gathered in the last collection interval. + */ + zfpm_stats_t last_ivl_stats; + + /* + * Cumulative stats from the last clear to the start of the current + * statistics interval. + */ + zfpm_stats_t cumulative_stats; + + /* + * Stats interval timer. + */ + struct thread *t_stats; + + /* + * If non-zero, the last time when statistics were cleared. + */ + time_t last_stats_clear_time; } zfpm_glob_t; static zfpm_glob_t zfpm_glob_space; static zfpm_glob_t *zfpm_g = &zfpm_glob_space; -static int zfpm_trigger_update (struct route_node *rn, const char *reason); +static int zfpm_trigger_update(struct route_node *rn, const char *reason); -static int zfpm_read_cb (struct thread *thread); -static int zfpm_write_cb (struct thread *thread); +static int zfpm_read_cb(struct thread *thread); +static int zfpm_write_cb(struct thread *thread); -static void zfpm_set_state (zfpm_state_t state, const char *reason); -static void zfpm_start_connect_timer (const char *reason); -static void zfpm_start_stats_timer (void); +static void zfpm_set_state(zfpm_state_t state, const char *reason); +static void zfpm_start_connect_timer(const char *reason); +static void zfpm_start_stats_timer(void); /* * zfpm_thread_should_yield */ -static inline int -zfpm_thread_should_yield (struct thread *t) +static inline int zfpm_thread_should_yield(struct thread *t) { - return thread_should_yield (t); + return thread_should_yield(t); } /* * zfpm_state_to_str */ -static const char * -zfpm_state_to_str (zfpm_state_t state) +static const char *zfpm_state_to_str(zfpm_state_t state) { - switch (state) - { + switch (state) { - case ZFPM_STATE_IDLE: - return "idle"; + case ZFPM_STATE_IDLE: + return "idle"; - case ZFPM_STATE_ACTIVE: - return "active"; + case ZFPM_STATE_ACTIVE: + return "active"; - case ZFPM_STATE_CONNECTING: - return "connecting"; + case ZFPM_STATE_CONNECTING: + return "connecting"; - case ZFPM_STATE_ESTABLISHED: - return "established"; + case ZFPM_STATE_ESTABLISHED: + return "established"; - default: - return "unknown"; - } + default: + return "unknown"; + } } /* @@ -303,20 +297,18 @@ zfpm_state_to_str (zfpm_state_t state) * * Returns the time elapsed (in seconds) since the given time. */ -static time_t -zfpm_get_elapsed_time (time_t reference) +static time_t zfpm_get_elapsed_time(time_t reference) { - time_t now; + time_t now; - now = monotime(NULL); + now = monotime(NULL); - if (now < reference) - { - assert (0); - return 0; - } + if (now < reference) { + assert(0); + return 0; + } - return now - reference; + return now - reference; } /* @@ -325,96 +317,89 @@ zfpm_get_elapsed_time (time_t reference) * Returns TRUE if the the given table is to be communicated to the * FPM. */ -static inline int -zfpm_is_table_for_fpm (struct route_table *table) +static inline int zfpm_is_table_for_fpm(struct route_table *table) { - rib_table_info_t *info; + rib_table_info_t *info; - info = rib_table_info (table); + info = rib_table_info(table); - /* - * We only send the unicast tables in the main instance to the FPM - * at this point. - */ - if (zvrf_id (info->zvrf) != 0) - return 0; + /* + * We only send the unicast tables in the main instance to the FPM + * at this point. + */ + if (zvrf_id(info->zvrf) != 0) + return 0; - if (info->safi != SAFI_UNICAST) - return 0; + if (info->safi != SAFI_UNICAST) + return 0; - return 1; + return 1; } /* * zfpm_rnodes_iter_init */ -static inline void -zfpm_rnodes_iter_init (zfpm_rnodes_iter_t *iter) +static inline void zfpm_rnodes_iter_init(zfpm_rnodes_iter_t *iter) { - memset (iter, 0, sizeof (*iter)); - rib_tables_iter_init (&iter->tables_iter); - - /* - * This is a hack, but it makes implementing 'next' easier by - * ensuring that route_table_iter_next() will return NULL the first - * time we call it. - */ - route_table_iter_init (&iter->iter, NULL); - route_table_iter_cleanup (&iter->iter); + memset(iter, 0, sizeof(*iter)); + rib_tables_iter_init(&iter->tables_iter); + + /* + * This is a hack, but it makes implementing 'next' easier by + * ensuring that route_table_iter_next() will return NULL the first + * time we call it. + */ + route_table_iter_init(&iter->iter, NULL); + route_table_iter_cleanup(&iter->iter); } /* * zfpm_rnodes_iter_next */ -static inline struct route_node * -zfpm_rnodes_iter_next (zfpm_rnodes_iter_t *iter) +static inline struct route_node *zfpm_rnodes_iter_next(zfpm_rnodes_iter_t *iter) { - struct route_node *rn; - struct route_table *table; + struct route_node *rn; + struct route_table *table; - while (1) - { - rn = route_table_iter_next (&iter->iter); - if (rn) - return rn; + while (1) { + rn = route_table_iter_next(&iter->iter); + if (rn) + return rn; - /* - * We've made our way through this table, go to the next one. - */ - route_table_iter_cleanup (&iter->iter); + /* + * We've made our way through this table, go to the next one. + */ + route_table_iter_cleanup(&iter->iter); - while ((table = rib_tables_iter_next (&iter->tables_iter))) - { - if (zfpm_is_table_for_fpm (table)) - break; - } + while ((table = rib_tables_iter_next(&iter->tables_iter))) { + if (zfpm_is_table_for_fpm(table)) + break; + } - if (!table) - return NULL; + if (!table) + return NULL; - route_table_iter_init (&iter->iter, table); - } + route_table_iter_init(&iter->iter, table); + } - return NULL; + return NULL; } /* * zfpm_rnodes_iter_pause */ -static inline void -zfpm_rnodes_iter_pause (zfpm_rnodes_iter_t *iter) +static inline void zfpm_rnodes_iter_pause(zfpm_rnodes_iter_t *iter) { - route_table_iter_pause (&iter->iter); + route_table_iter_pause(&iter->iter); } /* * zfpm_rnodes_iter_cleanup */ -static inline void -zfpm_rnodes_iter_cleanup (zfpm_rnodes_iter_t *iter) +static inline void zfpm_rnodes_iter_cleanup(zfpm_rnodes_iter_t *iter) { - route_table_iter_cleanup (&iter->iter); - rib_tables_iter_cleanup (&iter->tables_iter); + route_table_iter_cleanup(&iter->iter); + rib_tables_iter_cleanup(&iter->tables_iter); } /* @@ -422,28 +407,25 @@ zfpm_rnodes_iter_cleanup (zfpm_rnodes_iter_t *iter) * * Initialize a statistics block. */ -static inline void -zfpm_stats_init (zfpm_stats_t *stats) +static inline void zfpm_stats_init(zfpm_stats_t *stats) { - memset (stats, 0, sizeof (*stats)); + memset(stats, 0, sizeof(*stats)); } /* * zfpm_stats_reset */ -static inline void -zfpm_stats_reset (zfpm_stats_t *stats) +static inline void zfpm_stats_reset(zfpm_stats_t *stats) { - zfpm_stats_init (stats); + zfpm_stats_init(stats); } /* * zfpm_stats_copy */ -static inline void -zfpm_stats_copy (const zfpm_stats_t *src, zfpm_stats_t *dest) +static inline void zfpm_stats_copy(const zfpm_stats_t *src, zfpm_stats_t *dest) { - memcpy (dest, src, sizeof (*dest)); + memcpy(dest, src, sizeof(*dest)); } /* @@ -457,68 +439,62 @@ zfpm_stats_copy (const zfpm_stats_t *src, zfpm_stats_t *dest) * structure is composed entirely of counters. This can easily be * changed when necessary. */ -static void -zfpm_stats_compose (const zfpm_stats_t *s1, const zfpm_stats_t *s2, - zfpm_stats_t *result) +static void zfpm_stats_compose(const zfpm_stats_t *s1, const zfpm_stats_t *s2, + zfpm_stats_t *result) { - const unsigned long *p1, *p2; - unsigned long *result_p; - int i, num_counters; + const unsigned long *p1, *p2; + unsigned long *result_p; + int i, num_counters; - p1 = (const unsigned long *) s1; - p2 = (const unsigned long *) s2; - result_p = (unsigned long *) result; + p1 = (const unsigned long *)s1; + p2 = (const unsigned long *)s2; + result_p = (unsigned long *)result; - num_counters = (sizeof (zfpm_stats_t) / sizeof (unsigned long)); + num_counters = (sizeof(zfpm_stats_t) / sizeof(unsigned long)); - for (i = 0; i < num_counters; i++) - { - result_p[i] = p1[i] + p2[i]; - } + for (i = 0; i < num_counters; i++) { + result_p[i] = p1[i] + p2[i]; + } } /* * zfpm_read_on */ -static inline void -zfpm_read_on (void) +static inline void zfpm_read_on(void) { - assert (!zfpm_g->t_read); - assert (zfpm_g->sock >= 0); + assert(!zfpm_g->t_read); + assert(zfpm_g->sock >= 0); - thread_add_read(zfpm_g->master, zfpm_read_cb, 0, zfpm_g->sock, - &zfpm_g->t_read); + thread_add_read(zfpm_g->master, zfpm_read_cb, 0, zfpm_g->sock, + &zfpm_g->t_read); } /* * zfpm_write_on */ -static inline void -zfpm_write_on (void) +static inline void zfpm_write_on(void) { - assert (!zfpm_g->t_write); - assert (zfpm_g->sock >= 0); + assert(!zfpm_g->t_write); + assert(zfpm_g->sock >= 0); - thread_add_write(zfpm_g->master, zfpm_write_cb, 0, zfpm_g->sock, - &zfpm_g->t_write); + thread_add_write(zfpm_g->master, zfpm_write_cb, 0, zfpm_g->sock, + &zfpm_g->t_write); } /* * zfpm_read_off */ -static inline void -zfpm_read_off (void) +static inline void zfpm_read_off(void) { - THREAD_READ_OFF (zfpm_g->t_read); + THREAD_READ_OFF(zfpm_g->t_read); } /* * zfpm_write_off */ -static inline void -zfpm_write_off (void) +static inline void zfpm_write_off(void) { - THREAD_WRITE_OFF (zfpm_g->t_write); + THREAD_WRITE_OFF(zfpm_g->t_write); } /* @@ -527,53 +503,50 @@ zfpm_write_off (void) * Callback for actions to be taken when the connection to the FPM * comes up. */ -static int -zfpm_conn_up_thread_cb (struct thread *thread) +static int zfpm_conn_up_thread_cb(struct thread *thread) { - struct route_node *rnode; - zfpm_rnodes_iter_t *iter; - rib_dest_t *dest; + struct route_node *rnode; + zfpm_rnodes_iter_t *iter; + rib_dest_t *dest; - zfpm_g->t_conn_up = NULL; + zfpm_g->t_conn_up = NULL; - iter = &zfpm_g->t_conn_up_state.iter; + iter = &zfpm_g->t_conn_up_state.iter; - if (zfpm_g->state != ZFPM_STATE_ESTABLISHED) - { - zfpm_debug ("Connection not up anymore, conn_up thread aborting"); - zfpm_g->stats.t_conn_up_aborts++; - goto done; - } - - while ((rnode = zfpm_rnodes_iter_next (iter))) - { - dest = rib_dest_from_rnode (rnode); + if (zfpm_g->state != ZFPM_STATE_ESTABLISHED) { + zfpm_debug( + "Connection not up anymore, conn_up thread aborting"); + zfpm_g->stats.t_conn_up_aborts++; + goto done; + } - if (dest) - { - zfpm_g->stats.t_conn_up_dests_processed++; - zfpm_trigger_update (rnode, NULL); + while ((rnode = zfpm_rnodes_iter_next(iter))) { + dest = rib_dest_from_rnode(rnode); + + if (dest) { + zfpm_g->stats.t_conn_up_dests_processed++; + zfpm_trigger_update(rnode, NULL); + } + + /* + * Yield if need be. + */ + if (!zfpm_thread_should_yield(thread)) + continue; + + zfpm_g->stats.t_conn_up_yields++; + zfpm_rnodes_iter_pause(iter); + zfpm_g->t_conn_up = NULL; + thread_add_timer_msec(zfpm_g->master, zfpm_conn_up_thread_cb, + NULL, 0, &zfpm_g->t_conn_up); + return 0; } - /* - * Yield if need be. - */ - if (!zfpm_thread_should_yield (thread)) - continue; - - zfpm_g->stats.t_conn_up_yields++; - zfpm_rnodes_iter_pause (iter); - zfpm_g->t_conn_up = NULL; - thread_add_timer_msec (zfpm_g->master, zfpm_conn_up_thread_cb, NULL, 0, - &zfpm_g->t_conn_up); - return 0; - } - - zfpm_g->stats.t_conn_up_finishes++; - - done: - zfpm_rnodes_iter_cleanup (iter); - return 0; + zfpm_g->stats.t_conn_up_finishes++; + +done: + zfpm_rnodes_iter_cleanup(iter); + return 0; } /* @@ -581,26 +554,25 @@ zfpm_conn_up_thread_cb (struct thread *thread) * * Called when the connection to the FPM comes up. */ -static void -zfpm_connection_up (const char *detail) +static void zfpm_connection_up(const char *detail) { - assert (zfpm_g->sock >= 0); - zfpm_read_on (); - zfpm_write_on (); - zfpm_set_state (ZFPM_STATE_ESTABLISHED, detail); - - /* - * Start thread to push existing routes to the FPM. - */ - assert (!zfpm_g->t_conn_up); - - zfpm_rnodes_iter_init (&zfpm_g->t_conn_up_state.iter); - - zfpm_debug ("Starting conn_up thread"); - zfpm_g->t_conn_up = NULL; - thread_add_timer_msec(zfpm_g->master, zfpm_conn_up_thread_cb, NULL, 0, - &zfpm_g->t_conn_up); - zfpm_g->stats.t_conn_up_starts++; + assert(zfpm_g->sock >= 0); + zfpm_read_on(); + zfpm_write_on(); + zfpm_set_state(ZFPM_STATE_ESTABLISHED, detail); + + /* + * Start thread to push existing routes to the FPM. + */ + assert(!zfpm_g->t_conn_up); + + zfpm_rnodes_iter_init(&zfpm_g->t_conn_up_state.iter); + + zfpm_debug("Starting conn_up thread"); + zfpm_g->t_conn_up = NULL; + thread_add_timer_msec(zfpm_g->master, zfpm_conn_up_thread_cb, NULL, 0, + &zfpm_g->t_conn_up); + zfpm_g->stats.t_conn_up_starts++; } /* @@ -608,34 +580,32 @@ zfpm_connection_up (const char *detail) * * Check if an asynchronous connect() to the FPM is complete. */ -static void -zfpm_connect_check (void) +static void zfpm_connect_check(void) { - int status; - socklen_t slen; - int ret; - - zfpm_read_off (); - zfpm_write_off (); - - slen = sizeof (status); - ret = getsockopt (zfpm_g->sock, SOL_SOCKET, SO_ERROR, (void *) &status, - &slen); - - if (ret >= 0 && status == 0) - { - zfpm_connection_up ("async connect complete"); - return; - } - - /* - * getsockopt() failed or indicated an error on the socket. - */ - close (zfpm_g->sock); - zfpm_g->sock = -1; - - zfpm_start_connect_timer ("getsockopt() after async connect failed"); - return; + int status; + socklen_t slen; + int ret; + + zfpm_read_off(); + zfpm_write_off(); + + slen = sizeof(status); + ret = getsockopt(zfpm_g->sock, SOL_SOCKET, SO_ERROR, (void *)&status, + &slen); + + if (ret >= 0 && status == 0) { + zfpm_connection_up("async connect complete"); + return; + } + + /* + * getsockopt() failed or indicated an error on the socket. + */ + close(zfpm_g->sock); + zfpm_g->sock = -1; + + zfpm_start_connect_timer("getsockopt() after async connect failed"); + return; } /* @@ -644,63 +614,60 @@ zfpm_connect_check (void) * Callback that is invoked to clean up state after the TCP connection * to the FPM goes down. */ -static int -zfpm_conn_down_thread_cb (struct thread *thread) +static int zfpm_conn_down_thread_cb(struct thread *thread) { - struct route_node *rnode; - zfpm_rnodes_iter_t *iter; - rib_dest_t *dest; + struct route_node *rnode; + zfpm_rnodes_iter_t *iter; + rib_dest_t *dest; - assert (zfpm_g->state == ZFPM_STATE_IDLE); + assert(zfpm_g->state == ZFPM_STATE_IDLE); - zfpm_g->t_conn_down = NULL; + zfpm_g->t_conn_down = NULL; - iter = &zfpm_g->t_conn_down_state.iter; + iter = &zfpm_g->t_conn_down_state.iter; - while ((rnode = zfpm_rnodes_iter_next (iter))) - { - dest = rib_dest_from_rnode (rnode); + while ((rnode = zfpm_rnodes_iter_next(iter))) { + dest = rib_dest_from_rnode(rnode); - if (dest) - { - if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM)) - { - TAILQ_REMOVE (&zfpm_g->dest_q, dest, fpm_q_entries); - } + if (dest) { + if (CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_FPM)) { + TAILQ_REMOVE(&zfpm_g->dest_q, dest, + fpm_q_entries); + } + + UNSET_FLAG(dest->flags, RIB_DEST_UPDATE_FPM); + UNSET_FLAG(dest->flags, RIB_DEST_SENT_TO_FPM); - UNSET_FLAG (dest->flags, RIB_DEST_UPDATE_FPM); - UNSET_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM); + zfpm_g->stats.t_conn_down_dests_processed++; - zfpm_g->stats.t_conn_down_dests_processed++; + /* + * Check if the dest should be deleted. + */ + rib_gc_dest(rnode); + } - /* - * Check if the dest should be deleted. - */ - rib_gc_dest(rnode); + /* + * Yield if need be. + */ + if (!zfpm_thread_should_yield(thread)) + continue; + + zfpm_g->stats.t_conn_down_yields++; + zfpm_rnodes_iter_pause(iter); + zfpm_g->t_conn_down = NULL; + thread_add_timer_msec(zfpm_g->master, zfpm_conn_down_thread_cb, + NULL, 0, &zfpm_g->t_conn_down); + return 0; } - /* - * Yield if need be. - */ - if (!zfpm_thread_should_yield (thread)) - continue; - - zfpm_g->stats.t_conn_down_yields++; - zfpm_rnodes_iter_pause (iter); - zfpm_g->t_conn_down = NULL; - thread_add_timer_msec(zfpm_g->master, zfpm_conn_down_thread_cb, NULL, 0, - &zfpm_g->t_conn_down); - return 0; - } - - zfpm_g->stats.t_conn_down_finishes++; - zfpm_rnodes_iter_cleanup (iter); - - /* - * Start the process of connecting to the FPM again. - */ - zfpm_start_connect_timer ("cleanup complete"); - return 0; + zfpm_g->stats.t_conn_down_finishes++; + zfpm_rnodes_iter_cleanup(iter); + + /* + * Start the process of connecting to the FPM again. + */ + zfpm_start_connect_timer("cleanup complete"); + return 0; } /* @@ -708,128 +675,121 @@ zfpm_conn_down_thread_cb (struct thread *thread) * * Called when the connection to the FPM has gone down. */ -static void -zfpm_connection_down (const char *detail) +static void zfpm_connection_down(const char *detail) { - if (!detail) - detail = "unknown"; + if (!detail) + detail = "unknown"; - assert (zfpm_g->state == ZFPM_STATE_ESTABLISHED); + assert(zfpm_g->state == ZFPM_STATE_ESTABLISHED); - zlog_info ("connection to the FPM has gone down: %s", detail); + zlog_info("connection to the FPM has gone down: %s", detail); - zfpm_read_off (); - zfpm_write_off (); + zfpm_read_off(); + zfpm_write_off(); - stream_reset (zfpm_g->ibuf); - stream_reset (zfpm_g->obuf); + stream_reset(zfpm_g->ibuf); + stream_reset(zfpm_g->obuf); - if (zfpm_g->sock >= 0) { - close (zfpm_g->sock); - zfpm_g->sock = -1; - } - - /* - * Start thread to clean up state after the connection goes down. - */ - assert (!zfpm_g->t_conn_down); - zfpm_debug ("Starting conn_down thread"); - zfpm_rnodes_iter_init (&zfpm_g->t_conn_down_state.iter); - zfpm_g->t_conn_down = NULL; - thread_add_timer_msec(zfpm_g->master, zfpm_conn_down_thread_cb, NULL, 0, - &zfpm_g->t_conn_down); - zfpm_g->stats.t_conn_down_starts++; + if (zfpm_g->sock >= 0) { + close(zfpm_g->sock); + zfpm_g->sock = -1; + } - zfpm_set_state (ZFPM_STATE_IDLE, detail); + /* + * Start thread to clean up state after the connection goes down. + */ + assert(!zfpm_g->t_conn_down); + zfpm_debug("Starting conn_down thread"); + zfpm_rnodes_iter_init(&zfpm_g->t_conn_down_state.iter); + zfpm_g->t_conn_down = NULL; + thread_add_timer_msec(zfpm_g->master, zfpm_conn_down_thread_cb, NULL, 0, + &zfpm_g->t_conn_down); + zfpm_g->stats.t_conn_down_starts++; + + zfpm_set_state(ZFPM_STATE_IDLE, detail); } /* * zfpm_read_cb */ -static int -zfpm_read_cb (struct thread *thread) +static int zfpm_read_cb(struct thread *thread) { - size_t already; - struct stream *ibuf; - uint16_t msg_len; - fpm_msg_hdr_t *hdr; - - zfpm_g->stats.read_cb_calls++; - zfpm_g->t_read = NULL; - - /* - * Check if async connect is now done. - */ - if (zfpm_g->state == ZFPM_STATE_CONNECTING) - { - zfpm_connect_check(); - return 0; - } - - assert (zfpm_g->state == ZFPM_STATE_ESTABLISHED); - assert (zfpm_g->sock >= 0); - - ibuf = zfpm_g->ibuf; - - already = stream_get_endp (ibuf); - if (already < FPM_MSG_HDR_LEN) - { - ssize_t nbyte; - - nbyte = stream_read_try (ibuf, zfpm_g->sock, FPM_MSG_HDR_LEN - already); - if (nbyte == 0 || nbyte == -1) - { - zfpm_connection_down ("closed socket in read"); - return 0; + size_t already; + struct stream *ibuf; + uint16_t msg_len; + fpm_msg_hdr_t *hdr; + + zfpm_g->stats.read_cb_calls++; + zfpm_g->t_read = NULL; + + /* + * Check if async connect is now done. + */ + if (zfpm_g->state == ZFPM_STATE_CONNECTING) { + zfpm_connect_check(); + return 0; } - if (nbyte != (ssize_t) (FPM_MSG_HDR_LEN - already)) - goto done; + assert(zfpm_g->state == ZFPM_STATE_ESTABLISHED); + assert(zfpm_g->sock >= 0); - already = FPM_MSG_HDR_LEN; - } + ibuf = zfpm_g->ibuf; - stream_set_getp (ibuf, 0); + already = stream_get_endp(ibuf); + if (already < FPM_MSG_HDR_LEN) { + ssize_t nbyte; - hdr = (fpm_msg_hdr_t *) stream_pnt (ibuf); + nbyte = stream_read_try(ibuf, zfpm_g->sock, + FPM_MSG_HDR_LEN - already); + if (nbyte == 0 || nbyte == -1) { + zfpm_connection_down("closed socket in read"); + return 0; + } - if (!fpm_msg_hdr_ok (hdr)) - { - zfpm_connection_down ("invalid message header"); - return 0; - } + if (nbyte != (ssize_t)(FPM_MSG_HDR_LEN - already)) + goto done; - msg_len = fpm_msg_len (hdr); + already = FPM_MSG_HDR_LEN; + } - /* - * Read out the rest of the packet. - */ - if (already < msg_len) - { - ssize_t nbyte; + stream_set_getp(ibuf, 0); - nbyte = stream_read_try (ibuf, zfpm_g->sock, msg_len - already); + hdr = (fpm_msg_hdr_t *)stream_pnt(ibuf); - if (nbyte == 0 || nbyte == -1) - { - zfpm_connection_down ("failed to read message"); - return 0; + if (!fpm_msg_hdr_ok(hdr)) { + zfpm_connection_down("invalid message header"); + return 0; } - if (nbyte != (ssize_t) (msg_len - already)) - goto done; - } + msg_len = fpm_msg_len(hdr); - zfpm_debug ("Read out a full fpm message"); + /* + * Read out the rest of the packet. + */ + if (already < msg_len) { + ssize_t nbyte; - /* - * Just throw it away for now. - */ - stream_reset (ibuf); + nbyte = stream_read_try(ibuf, zfpm_g->sock, msg_len - already); - done: - zfpm_read_on (); - return 0; + if (nbyte == 0 || nbyte == -1) { + zfpm_connection_down("failed to read message"); + return 0; + } + + if (nbyte != (ssize_t)(msg_len - already)) + goto done; + } + + zfpm_debug("Read out a full fpm message"); + + /* + * Just throw it away for now. + */ + stream_reset(ibuf); + +done: + zfpm_read_on(); + return 0; } /* @@ -837,24 +797,23 @@ zfpm_read_cb (struct thread *thread) * * Returns TRUE if we may have something to write to the FPM. */ -static int -zfpm_writes_pending (void) +static int zfpm_writes_pending(void) { - /* - * Check if there is any data in the outbound buffer that has not - * been written to the socket yet. - */ - if (stream_get_endp (zfpm_g->obuf) - stream_get_getp (zfpm_g->obuf)) - return 1; + /* + * Check if there is any data in the outbound buffer that has not + * been written to the socket yet. + */ + if (stream_get_endp(zfpm_g->obuf) - stream_get_getp(zfpm_g->obuf)) + return 1; - /* - * Check if there are any prefixes on the outbound queue. - */ - if (!TAILQ_EMPTY (&zfpm_g->dest_q)) - return 1; + /* + * Check if there are any prefixes on the outbound queue. + */ + if (!TAILQ_EMPTY(&zfpm_g->dest_q)) + return 1; - return 0; + return 0; } /* @@ -865,44 +824,44 @@ zfpm_writes_pending (void) * Returns the number of bytes written to the buffer. 0 or a negative * value indicates an error. */ -static inline int -zfpm_encode_route (rib_dest_t *dest, struct route_entry *re, char *in_buf, - size_t in_buf_len, fpm_msg_type_e *msg_type) +static inline int zfpm_encode_route(rib_dest_t *dest, struct route_entry *re, + char *in_buf, size_t in_buf_len, + fpm_msg_type_e *msg_type) { - size_t len; + size_t len; #ifdef HAVE_NETLINK - int cmd; + int cmd; #endif - len = 0; + len = 0; - *msg_type = FPM_MSG_TYPE_NONE; + *msg_type = FPM_MSG_TYPE_NONE; - switch (zfpm_g->message_format) { + switch (zfpm_g->message_format) { - case ZFPM_MSG_FORMAT_PROTOBUF: + case ZFPM_MSG_FORMAT_PROTOBUF: #ifdef HAVE_PROTOBUF - len = zfpm_protobuf_encode_route (dest, re, (uint8_t *) in_buf, - in_buf_len); - *msg_type = FPM_MSG_TYPE_PROTOBUF; + len = zfpm_protobuf_encode_route(dest, re, (uint8_t *)in_buf, + in_buf_len); + *msg_type = FPM_MSG_TYPE_PROTOBUF; #endif - break; + break; - case ZFPM_MSG_FORMAT_NETLINK: + case ZFPM_MSG_FORMAT_NETLINK: #ifdef HAVE_NETLINK - *msg_type = FPM_MSG_TYPE_NETLINK; - cmd = re ? RTM_NEWROUTE : RTM_DELROUTE; - len = zfpm_netlink_encode_route (cmd, dest, re, in_buf, in_buf_len); - assert(fpm_msg_align(len) == len); - *msg_type = FPM_MSG_TYPE_NETLINK; + *msg_type = FPM_MSG_TYPE_NETLINK; + cmd = re ? RTM_NEWROUTE : RTM_DELROUTE; + len = zfpm_netlink_encode_route(cmd, dest, re, in_buf, + in_buf_len); + assert(fpm_msg_align(len) == len); + *msg_type = FPM_MSG_TYPE_NETLINK; #endif /* HAVE_NETLINK */ - break; - - default: - break; - } + break; - return len; + default: + break; + } + return len; } /* @@ -910,23 +869,22 @@ zfpm_encode_route (rib_dest_t *dest, struct route_entry *re, char *in_buf, * * Returns the re that is to be sent to the FPM for a given dest. */ -struct route_entry * -zfpm_route_for_update (rib_dest_t *dest) +struct route_entry *zfpm_route_for_update(rib_dest_t *dest) { - struct route_entry *re; + struct route_entry *re; - RE_DEST_FOREACH_ROUTE (dest, re) - { - if (!CHECK_FLAG (re->status, ROUTE_ENTRY_SELECTED_FIB)) - continue; + RE_DEST_FOREACH_ROUTE(dest, re) + { + if (!CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) + continue; - return re; - } + return re; + } - /* - * We have no route for this destination. - */ - return NULL; + /* + * We have no route for this destination. + */ + return NULL; } /* @@ -935,262 +893,247 @@ zfpm_route_for_update (rib_dest_t *dest) * Process the outgoing queue and write messages to the outbound * buffer. */ -static void -zfpm_build_updates (void) +static void zfpm_build_updates(void) { - struct stream *s; - rib_dest_t *dest; - unsigned char *buf, *data, *buf_end; - size_t msg_len; - size_t data_len; - fpm_msg_hdr_t *hdr; - struct route_entry *re; - int is_add, write_msg; - fpm_msg_type_e msg_type; - - s = zfpm_g->obuf; - - assert (stream_empty (s)); - - do { - - /* - * Make sure there is enough space to write another message. - */ - if (STREAM_WRITEABLE (s) < FPM_MAX_MSG_LEN) - break; - - buf = STREAM_DATA (s) + stream_get_endp (s); - buf_end = buf + STREAM_WRITEABLE (s); - - dest = TAILQ_FIRST (&zfpm_g->dest_q); - if (!dest) - break; - - assert (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM)); - - hdr = (fpm_msg_hdr_t *) buf; - hdr->version = FPM_PROTO_VERSION; - - data = fpm_msg_data (hdr); - - re = zfpm_route_for_update (dest); - is_add = re ? 1 : 0; - - write_msg = 1; - - /* - * If this is a route deletion, and we have not sent the route to - * the FPM previously, skip it. - */ - if (!is_add && !CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM)) - { - write_msg = 0; - zfpm_g->stats.nop_deletes_skipped++; - } - - if (write_msg) { - data_len = zfpm_encode_route (dest, re, (char *) data, buf_end - data, - &msg_type); - - assert (data_len); - if (data_len) - { - hdr->msg_type = msg_type; - msg_len = fpm_data_len_to_msg_len (data_len); - hdr->msg_len = htons (msg_len); - stream_forward_endp (s, msg_len); - - if (is_add) - zfpm_g->stats.route_adds++; - else - zfpm_g->stats.route_dels++; - } - } - - /* - * Remove the dest from the queue, and reset the flag. - */ - UNSET_FLAG (dest->flags, RIB_DEST_UPDATE_FPM); - TAILQ_REMOVE (&zfpm_g->dest_q, dest, fpm_q_entries); - - if (is_add) - { - SET_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM); - } - else - { - UNSET_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM); - } - - /* - * Delete the destination if necessary. - */ - if (rib_gc_dest (dest->rnode)) - zfpm_g->stats.dests_del_after_update++; - - } while (1); - + struct stream *s; + rib_dest_t *dest; + unsigned char *buf, *data, *buf_end; + size_t msg_len; + size_t data_len; + fpm_msg_hdr_t *hdr; + struct route_entry *re; + int is_add, write_msg; + fpm_msg_type_e msg_type; + + s = zfpm_g->obuf; + + assert(stream_empty(s)); + + do { + + /* + * Make sure there is enough space to write another message. + */ + if (STREAM_WRITEABLE(s) < FPM_MAX_MSG_LEN) + break; + + buf = STREAM_DATA(s) + stream_get_endp(s); + buf_end = buf + STREAM_WRITEABLE(s); + + dest = TAILQ_FIRST(&zfpm_g->dest_q); + if (!dest) + break; + + assert(CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_FPM)); + + hdr = (fpm_msg_hdr_t *)buf; + hdr->version = FPM_PROTO_VERSION; + + data = fpm_msg_data(hdr); + + re = zfpm_route_for_update(dest); + is_add = re ? 1 : 0; + + write_msg = 1; + + /* + * If this is a route deletion, and we have not sent the route + * to + * the FPM previously, skip it. + */ + if (!is_add && !CHECK_FLAG(dest->flags, RIB_DEST_SENT_TO_FPM)) { + write_msg = 0; + zfpm_g->stats.nop_deletes_skipped++; + } + + if (write_msg) { + data_len = zfpm_encode_route(dest, re, (char *)data, + buf_end - data, &msg_type); + + assert(data_len); + if (data_len) { + hdr->msg_type = msg_type; + msg_len = fpm_data_len_to_msg_len(data_len); + hdr->msg_len = htons(msg_len); + stream_forward_endp(s, msg_len); + + if (is_add) + zfpm_g->stats.route_adds++; + else + zfpm_g->stats.route_dels++; + } + } + + /* + * Remove the dest from the queue, and reset the flag. + */ + UNSET_FLAG(dest->flags, RIB_DEST_UPDATE_FPM); + TAILQ_REMOVE(&zfpm_g->dest_q, dest, fpm_q_entries); + + if (is_add) { + SET_FLAG(dest->flags, RIB_DEST_SENT_TO_FPM); + } else { + UNSET_FLAG(dest->flags, RIB_DEST_SENT_TO_FPM); + } + + /* + * Delete the destination if necessary. + */ + if (rib_gc_dest(dest->rnode)) + zfpm_g->stats.dests_del_after_update++; + + } while (1); } /* * zfpm_write_cb */ -static int -zfpm_write_cb (struct thread *thread) +static int zfpm_write_cb(struct thread *thread) { - struct stream *s; - int num_writes; + struct stream *s; + int num_writes; + + zfpm_g->stats.write_cb_calls++; + zfpm_g->t_write = NULL; + + /* + * Check if async connect is now done. + */ + if (zfpm_g->state == ZFPM_STATE_CONNECTING) { + zfpm_connect_check(); + return 0; + } - zfpm_g->stats.write_cb_calls++; - zfpm_g->t_write = NULL; + assert(zfpm_g->state == ZFPM_STATE_ESTABLISHED); + assert(zfpm_g->sock >= 0); - /* - * Check if async connect is now done. - */ - if (zfpm_g->state == ZFPM_STATE_CONNECTING) - { - zfpm_connect_check (); - return 0; - } + num_writes = 0; - assert (zfpm_g->state == ZFPM_STATE_ESTABLISHED); - assert (zfpm_g->sock >= 0); + do { + int bytes_to_write, bytes_written; - num_writes = 0; + s = zfpm_g->obuf; - do - { - int bytes_to_write, bytes_written; + /* + * If the stream is empty, try fill it up with data. + */ + if (stream_empty(s)) { + zfpm_build_updates(); + } - s = zfpm_g->obuf; + bytes_to_write = stream_get_endp(s) - stream_get_getp(s); + if (!bytes_to_write) + break; - /* - * If the stream is empty, try fill it up with data. - */ - if (stream_empty (s)) - { - zfpm_build_updates (); - } + bytes_written = + write(zfpm_g->sock, STREAM_PNT(s), bytes_to_write); + zfpm_g->stats.write_calls++; + num_writes++; - bytes_to_write = stream_get_endp (s) - stream_get_getp (s); - if (!bytes_to_write) - break; + if (bytes_written < 0) { + if (ERRNO_IO_RETRY(errno)) + break; - bytes_written = write (zfpm_g->sock, STREAM_PNT (s), bytes_to_write); - zfpm_g->stats.write_calls++; - num_writes++; + zfpm_connection_down("failed to write to socket"); + return 0; + } - if (bytes_written < 0) - { - if (ERRNO_IO_RETRY (errno)) - break; + if (bytes_written != bytes_to_write) { - zfpm_connection_down ("failed to write to socket"); - return 0; - } - - if (bytes_written != bytes_to_write) - { + /* + * Partial write. + */ + stream_forward_getp(s, bytes_written); + zfpm_g->stats.partial_writes++; + break; + } - /* - * Partial write. - */ - stream_forward_getp (s, bytes_written); - zfpm_g->stats.partial_writes++; - break; - } - - /* - * We've written out the entire contents of the stream. - */ - stream_reset (s); + /* + * We've written out the entire contents of the stream. + */ + stream_reset(s); - if (num_writes >= ZFPM_MAX_WRITES_PER_RUN) - { - zfpm_g->stats.max_writes_hit++; - break; - } + if (num_writes >= ZFPM_MAX_WRITES_PER_RUN) { + zfpm_g->stats.max_writes_hit++; + break; + } - if (zfpm_thread_should_yield (thread)) - { - zfpm_g->stats.t_write_yields++; - break; - } - } while (1); + if (zfpm_thread_should_yield(thread)) { + zfpm_g->stats.t_write_yields++; + break; + } + } while (1); - if (zfpm_writes_pending ()) - zfpm_write_on (); + if (zfpm_writes_pending()) + zfpm_write_on(); - return 0; + return 0; } /* * zfpm_connect_cb */ -static int -zfpm_connect_cb (struct thread *t) +static int zfpm_connect_cb(struct thread *t) { - int sock, ret; - struct sockaddr_in serv; - - zfpm_g->t_connect = NULL; - assert (zfpm_g->state == ZFPM_STATE_ACTIVE); - - sock = socket (AF_INET, SOCK_STREAM, 0); - if (sock < 0) - { - zfpm_debug ("Failed to create socket for connect(): %s", strerror(errno)); - zfpm_g->stats.connect_no_sock++; - return 0; - } - - set_nonblocking(sock); - - /* Make server socket. */ - memset (&serv, 0, sizeof (serv)); - serv.sin_family = AF_INET; - serv.sin_port = htons (zfpm_g->fpm_port); + int sock, ret; + struct sockaddr_in serv; + + zfpm_g->t_connect = NULL; + assert(zfpm_g->state == ZFPM_STATE_ACTIVE); + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + zfpm_debug("Failed to create socket for connect(): %s", + strerror(errno)); + zfpm_g->stats.connect_no_sock++; + return 0; + } + + set_nonblocking(sock); + + /* Make server socket. */ + memset(&serv, 0, sizeof(serv)); + serv.sin_family = AF_INET; + serv.sin_port = htons(zfpm_g->fpm_port); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - serv.sin_len = sizeof (struct sockaddr_in); + serv.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - if (!zfpm_g->fpm_server) - serv.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - else - serv.sin_addr.s_addr = (zfpm_g->fpm_server); - - /* - * Connect to the FPM. - */ - zfpm_g->connect_calls++; - zfpm_g->stats.connect_calls++; - zfpm_g->last_connect_call_time = monotime(NULL); - - ret = connect (sock, (struct sockaddr *) &serv, sizeof (serv)); - if (ret >= 0) - { - zfpm_g->sock = sock; - zfpm_connection_up ("connect succeeded"); - return 1; - } - - if (errno == EINPROGRESS) - { - zfpm_g->sock = sock; - zfpm_read_on (); - zfpm_write_on (); - zfpm_set_state (ZFPM_STATE_CONNECTING, "async connect in progress"); - return 0; - } - - zlog_info ("can't connect to FPM %d: %s", sock, safe_strerror (errno)); - close (sock); - - /* - * Restart timer for retrying connection. - */ - zfpm_start_connect_timer ("connect() failed"); - return 0; + if (!zfpm_g->fpm_server) + serv.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + else + serv.sin_addr.s_addr = (zfpm_g->fpm_server); + + /* + * Connect to the FPM. + */ + zfpm_g->connect_calls++; + zfpm_g->stats.connect_calls++; + zfpm_g->last_connect_call_time = monotime(NULL); + + ret = connect(sock, (struct sockaddr *)&serv, sizeof(serv)); + if (ret >= 0) { + zfpm_g->sock = sock; + zfpm_connection_up("connect succeeded"); + return 1; + } + + if (errno == EINPROGRESS) { + zfpm_g->sock = sock; + zfpm_read_on(); + zfpm_write_on(); + zfpm_set_state(ZFPM_STATE_CONNECTING, + "async connect in progress"); + return 0; + } + + zlog_info("can't connect to FPM %d: %s", sock, safe_strerror(errno)); + close(sock); + + /* + * Restart timer for retrying connection. + */ + zfpm_start_connect_timer("connect() failed"); + return 0; } /* @@ -1198,50 +1141,49 @@ zfpm_connect_cb (struct thread *t) * * Move state machine into the given state. */ -static void -zfpm_set_state (zfpm_state_t state, const char *reason) +static void zfpm_set_state(zfpm_state_t state, const char *reason) { - zfpm_state_t cur_state = zfpm_g->state; - - if (!reason) - reason = "Unknown"; - - if (state == cur_state) - return; - - zfpm_debug("beginning state transition %s -> %s. Reason: %s", - zfpm_state_to_str (cur_state), zfpm_state_to_str (state), - reason); - - switch (state) { - - case ZFPM_STATE_IDLE: - assert (cur_state == ZFPM_STATE_ESTABLISHED); - break; - - case ZFPM_STATE_ACTIVE: - assert (cur_state == ZFPM_STATE_IDLE || - cur_state == ZFPM_STATE_CONNECTING); - assert (zfpm_g->t_connect); - break; - - case ZFPM_STATE_CONNECTING: - assert (zfpm_g->sock); - assert (cur_state == ZFPM_STATE_ACTIVE); - assert (zfpm_g->t_read); - assert (zfpm_g->t_write); - break; - - case ZFPM_STATE_ESTABLISHED: - assert (cur_state == ZFPM_STATE_ACTIVE || - cur_state == ZFPM_STATE_CONNECTING); - assert (zfpm_g->sock); - assert (zfpm_g->t_read); - assert (zfpm_g->t_write); - break; - } - - zfpm_g->state = state; + zfpm_state_t cur_state = zfpm_g->state; + + if (!reason) + reason = "Unknown"; + + if (state == cur_state) + return; + + zfpm_debug("beginning state transition %s -> %s. Reason: %s", + zfpm_state_to_str(cur_state), zfpm_state_to_str(state), + reason); + + switch (state) { + + case ZFPM_STATE_IDLE: + assert(cur_state == ZFPM_STATE_ESTABLISHED); + break; + + case ZFPM_STATE_ACTIVE: + assert(cur_state == ZFPM_STATE_IDLE + || cur_state == ZFPM_STATE_CONNECTING); + assert(zfpm_g->t_connect); + break; + + case ZFPM_STATE_CONNECTING: + assert(zfpm_g->sock); + assert(cur_state == ZFPM_STATE_ACTIVE); + assert(zfpm_g->t_read); + assert(zfpm_g->t_write); + break; + + case ZFPM_STATE_ESTABLISHED: + assert(cur_state == ZFPM_STATE_ACTIVE + || cur_state == ZFPM_STATE_CONNECTING); + assert(zfpm_g->sock); + assert(zfpm_g->t_read); + assert(zfpm_g->t_write); + break; + } + + zfpm_g->state = state; } /* @@ -1250,49 +1192,46 @@ zfpm_set_state (zfpm_state_t state, const char *reason) * Returns the number of seconds after which we should attempt to * reconnect to the FPM. */ -static long -zfpm_calc_connect_delay (void) +static long zfpm_calc_connect_delay(void) { - time_t elapsed; + time_t elapsed; - /* - * Return 0 if this is our first attempt to connect. - */ - if (zfpm_g->connect_calls == 0) - { - return 0; - } + /* + * Return 0 if this is our first attempt to connect. + */ + if (zfpm_g->connect_calls == 0) { + return 0; + } - elapsed = zfpm_get_elapsed_time (zfpm_g->last_connect_call_time); + elapsed = zfpm_get_elapsed_time(zfpm_g->last_connect_call_time); - if (elapsed > ZFPM_CONNECT_RETRY_IVL) { - return 0; - } + if (elapsed > ZFPM_CONNECT_RETRY_IVL) { + return 0; + } - return ZFPM_CONNECT_RETRY_IVL - elapsed; + return ZFPM_CONNECT_RETRY_IVL - elapsed; } /* * zfpm_start_connect_timer */ -static void -zfpm_start_connect_timer (const char *reason) +static void zfpm_start_connect_timer(const char *reason) { - long delay_secs; + long delay_secs; - assert (!zfpm_g->t_connect); - assert (zfpm_g->sock < 0); + assert(!zfpm_g->t_connect); + assert(zfpm_g->sock < 0); - assert(zfpm_g->state == ZFPM_STATE_IDLE || - zfpm_g->state == ZFPM_STATE_ACTIVE || - zfpm_g->state == ZFPM_STATE_CONNECTING); + assert(zfpm_g->state == ZFPM_STATE_IDLE + || zfpm_g->state == ZFPM_STATE_ACTIVE + || zfpm_g->state == ZFPM_STATE_CONNECTING); - delay_secs = zfpm_calc_connect_delay(); - zfpm_debug ("scheduling connect in %ld seconds", delay_secs); + delay_secs = zfpm_calc_connect_delay(); + zfpm_debug("scheduling connect in %ld seconds", delay_secs); - thread_add_timer(zfpm_g->master, zfpm_connect_cb, 0, delay_secs, - &zfpm_g->t_connect); - zfpm_set_state (ZFPM_STATE_ACTIVE, reason); + thread_add_timer(zfpm_g->master, zfpm_connect_cb, 0, delay_secs, + &zfpm_g->t_connect); + zfpm_set_state(ZFPM_STATE_ACTIVE, reason); } /* @@ -1300,10 +1239,9 @@ zfpm_start_connect_timer (const char *reason) * * Returns TRUE if the zebra FPM module has been enabled. */ -static inline int -zfpm_is_enabled (void) +static inline int zfpm_is_enabled(void) { - return zfpm_g->enabled; + return zfpm_g->enabled; } /* @@ -1311,15 +1249,14 @@ zfpm_is_enabled (void) * * Returns TRUE if the connection to the FPM is up. */ -static inline int -zfpm_conn_is_up (void) +static inline int zfpm_conn_is_up(void) { - if (zfpm_g->state != ZFPM_STATE_ESTABLISHED) - return 0; + if (zfpm_g->state != ZFPM_STATE_ESTABLISHED) + return 0; - assert (zfpm_g->sock >= 0); + assert(zfpm_g->sock >= 0); - return 1; + return 1; } /* @@ -1328,194 +1265,185 @@ zfpm_conn_is_up (void) * The zebra code invokes this function to indicate that we should * send an update to the FPM about the given route_node. */ -static int -zfpm_trigger_update (struct route_node *rn, const char *reason) +static int zfpm_trigger_update(struct route_node *rn, const char *reason) { - rib_dest_t *dest; - char buf[PREFIX_STRLEN]; - - /* - * Ignore if the connection is down. We will update the FPM about - * all destinations once the connection comes up. - */ - if (!zfpm_conn_is_up ()) - return 0; - - dest = rib_dest_from_rnode (rn); - - /* - * Ignore the trigger if the dest is not in a table that we would - * send to the FPM. - */ - if (!zfpm_is_table_for_fpm (rib_dest_table (dest))) - { - zfpm_g->stats.non_fpm_table_triggers++; - return 0; - } - - if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM)) { - zfpm_g->stats.redundant_triggers++; - return 0; - } - - if (reason) - { - zfpm_debug ("%s triggering update to FPM - Reason: %s", - prefix2str (&rn->p, buf, sizeof(buf)), reason); - } - - SET_FLAG (dest->flags, RIB_DEST_UPDATE_FPM); - TAILQ_INSERT_TAIL (&zfpm_g->dest_q, dest, fpm_q_entries); - zfpm_g->stats.updates_triggered++; - - /* - * Make sure that writes are enabled. - */ - if (zfpm_g->t_write) - return 0; - - zfpm_write_on (); - return 0; + rib_dest_t *dest; + char buf[PREFIX_STRLEN]; + + /* + * Ignore if the connection is down. We will update the FPM about + * all destinations once the connection comes up. + */ + if (!zfpm_conn_is_up()) + return 0; + + dest = rib_dest_from_rnode(rn); + + /* + * Ignore the trigger if the dest is not in a table that we would + * send to the FPM. + */ + if (!zfpm_is_table_for_fpm(rib_dest_table(dest))) { + zfpm_g->stats.non_fpm_table_triggers++; + return 0; + } + + if (CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_FPM)) { + zfpm_g->stats.redundant_triggers++; + return 0; + } + + if (reason) { + zfpm_debug("%s triggering update to FPM - Reason: %s", + prefix2str(&rn->p, buf, sizeof(buf)), reason); + } + + SET_FLAG(dest->flags, RIB_DEST_UPDATE_FPM); + TAILQ_INSERT_TAIL(&zfpm_g->dest_q, dest, fpm_q_entries); + zfpm_g->stats.updates_triggered++; + + /* + * Make sure that writes are enabled. + */ + if (zfpm_g->t_write) + return 0; + + zfpm_write_on(); + return 0; } /* * zfpm_stats_timer_cb */ -static int -zfpm_stats_timer_cb (struct thread *t) +static int zfpm_stats_timer_cb(struct thread *t) { - zfpm_g->t_stats = NULL; + zfpm_g->t_stats = NULL; - /* - * Remember the stats collected in the last interval for display - * purposes. - */ - zfpm_stats_copy (&zfpm_g->stats, &zfpm_g->last_ivl_stats); + /* + * Remember the stats collected in the last interval for display + * purposes. + */ + zfpm_stats_copy(&zfpm_g->stats, &zfpm_g->last_ivl_stats); - /* - * Add the current set of stats into the cumulative statistics. - */ - zfpm_stats_compose (&zfpm_g->cumulative_stats, &zfpm_g->stats, - &zfpm_g->cumulative_stats); + /* + * Add the current set of stats into the cumulative statistics. + */ + zfpm_stats_compose(&zfpm_g->cumulative_stats, &zfpm_g->stats, + &zfpm_g->cumulative_stats); - /* - * Start collecting stats afresh over the next interval. - */ - zfpm_stats_reset (&zfpm_g->stats); + /* + * Start collecting stats afresh over the next interval. + */ + zfpm_stats_reset(&zfpm_g->stats); - zfpm_start_stats_timer (); + zfpm_start_stats_timer(); - return 0; + return 0; } /* * zfpm_stop_stats_timer */ -static void -zfpm_stop_stats_timer (void) +static void zfpm_stop_stats_timer(void) { - if (!zfpm_g->t_stats) - return; + if (!zfpm_g->t_stats) + return; - zfpm_debug ("Stopping existing stats timer"); - THREAD_TIMER_OFF (zfpm_g->t_stats); + zfpm_debug("Stopping existing stats timer"); + THREAD_TIMER_OFF(zfpm_g->t_stats); } /* * zfpm_start_stats_timer */ -void -zfpm_start_stats_timer (void) +void zfpm_start_stats_timer(void) { - assert (!zfpm_g->t_stats); + assert(!zfpm_g->t_stats); - thread_add_timer(zfpm_g->master, zfpm_stats_timer_cb, 0, - ZFPM_STATS_IVL_SECS, &zfpm_g->t_stats); + thread_add_timer(zfpm_g->master, zfpm_stats_timer_cb, 0, + ZFPM_STATS_IVL_SECS, &zfpm_g->t_stats); } /* * Helper macro for zfpm_show_stats() below. */ -#define ZFPM_SHOW_STAT(counter) \ - do { \ - vty_out (vty, "%-40s %10lu %16lu\n", #counter, total_stats.counter, \ - zfpm_g->last_ivl_stats.counter); \ - } while (0) +#define ZFPM_SHOW_STAT(counter) \ + do { \ + vty_out(vty, "%-40s %10lu %16lu\n", #counter, \ + total_stats.counter, zfpm_g->last_ivl_stats.counter); \ + } while (0) /* * zfpm_show_stats */ -static void -zfpm_show_stats (struct vty *vty) +static void zfpm_show_stats(struct vty *vty) { - zfpm_stats_t total_stats; - time_t elapsed; - - vty_out (vty, "\n%-40s %10s Last %2d secs\n\n", "Counter", - "Total", ZFPM_STATS_IVL_SECS); - - /* - * Compute the total stats up to this instant. - */ - zfpm_stats_compose (&zfpm_g->cumulative_stats, &zfpm_g->stats, - &total_stats); - - ZFPM_SHOW_STAT (connect_calls); - ZFPM_SHOW_STAT (connect_no_sock); - ZFPM_SHOW_STAT (read_cb_calls); - ZFPM_SHOW_STAT (write_cb_calls); - ZFPM_SHOW_STAT (write_calls); - ZFPM_SHOW_STAT (partial_writes); - ZFPM_SHOW_STAT (max_writes_hit); - ZFPM_SHOW_STAT (t_write_yields); - ZFPM_SHOW_STAT (nop_deletes_skipped); - ZFPM_SHOW_STAT (route_adds); - ZFPM_SHOW_STAT (route_dels); - ZFPM_SHOW_STAT (updates_triggered); - ZFPM_SHOW_STAT (non_fpm_table_triggers); - ZFPM_SHOW_STAT (redundant_triggers); - ZFPM_SHOW_STAT (dests_del_after_update); - ZFPM_SHOW_STAT (t_conn_down_starts); - ZFPM_SHOW_STAT (t_conn_down_dests_processed); - ZFPM_SHOW_STAT (t_conn_down_yields); - ZFPM_SHOW_STAT (t_conn_down_finishes); - ZFPM_SHOW_STAT (t_conn_up_starts); - ZFPM_SHOW_STAT (t_conn_up_dests_processed); - ZFPM_SHOW_STAT (t_conn_up_yields); - ZFPM_SHOW_STAT (t_conn_up_aborts); - ZFPM_SHOW_STAT (t_conn_up_finishes); - - if (!zfpm_g->last_stats_clear_time) - return; - - elapsed = zfpm_get_elapsed_time (zfpm_g->last_stats_clear_time); - - vty_out (vty, "\nStats were cleared %lu seconds ago\n", - (unsigned long)elapsed); + zfpm_stats_t total_stats; + time_t elapsed; + + vty_out(vty, "\n%-40s %10s Last %2d secs\n\n", "Counter", "Total", + ZFPM_STATS_IVL_SECS); + + /* + * Compute the total stats up to this instant. + */ + zfpm_stats_compose(&zfpm_g->cumulative_stats, &zfpm_g->stats, + &total_stats); + + ZFPM_SHOW_STAT(connect_calls); + ZFPM_SHOW_STAT(connect_no_sock); + ZFPM_SHOW_STAT(read_cb_calls); + ZFPM_SHOW_STAT(write_cb_calls); + ZFPM_SHOW_STAT(write_calls); + ZFPM_SHOW_STAT(partial_writes); + ZFPM_SHOW_STAT(max_writes_hit); + ZFPM_SHOW_STAT(t_write_yields); + ZFPM_SHOW_STAT(nop_deletes_skipped); + ZFPM_SHOW_STAT(route_adds); + ZFPM_SHOW_STAT(route_dels); + ZFPM_SHOW_STAT(updates_triggered); + ZFPM_SHOW_STAT(non_fpm_table_triggers); + ZFPM_SHOW_STAT(redundant_triggers); + ZFPM_SHOW_STAT(dests_del_after_update); + ZFPM_SHOW_STAT(t_conn_down_starts); + ZFPM_SHOW_STAT(t_conn_down_dests_processed); + ZFPM_SHOW_STAT(t_conn_down_yields); + ZFPM_SHOW_STAT(t_conn_down_finishes); + ZFPM_SHOW_STAT(t_conn_up_starts); + ZFPM_SHOW_STAT(t_conn_up_dests_processed); + ZFPM_SHOW_STAT(t_conn_up_yields); + ZFPM_SHOW_STAT(t_conn_up_aborts); + ZFPM_SHOW_STAT(t_conn_up_finishes); + + if (!zfpm_g->last_stats_clear_time) + return; + + elapsed = zfpm_get_elapsed_time(zfpm_g->last_stats_clear_time); + + vty_out(vty, "\nStats were cleared %lu seconds ago\n", + (unsigned long)elapsed); } /* * zfpm_clear_stats */ -static void -zfpm_clear_stats (struct vty *vty) +static void zfpm_clear_stats(struct vty *vty) { - if (!zfpm_is_enabled ()) - { - vty_out (vty, "The FPM module is not enabled...\n"); - return; - } + if (!zfpm_is_enabled()) { + vty_out(vty, "The FPM module is not enabled...\n"); + return; + } - zfpm_stats_reset (&zfpm_g->stats); - zfpm_stats_reset (&zfpm_g->last_ivl_stats); - zfpm_stats_reset (&zfpm_g->cumulative_stats); + zfpm_stats_reset(&zfpm_g->stats); + zfpm_stats_reset(&zfpm_g->last_ivl_stats); + zfpm_stats_reset(&zfpm_g->cumulative_stats); - zfpm_stop_stats_timer (); - zfpm_start_stats_timer (); + zfpm_stop_stats_timer(); + zfpm_start_stats_timer(); - zfpm_g->last_stats_clear_time = monotime(NULL); + zfpm_g->last_stats_clear_time = monotime(NULL); - vty_out (vty, "Cleared FPM stats\n"); + vty_out(vty, "Cleared FPM stats\n"); } /* @@ -1529,8 +1457,8 @@ DEFUN (show_zebra_fpm_stats, "Forwarding Path Manager information\n" "Statistics\n") { - zfpm_show_stats (vty); - return CMD_SUCCESS; + zfpm_show_stats(vty); + return CMD_SUCCESS; } /* @@ -1544,12 +1472,12 @@ DEFUN (clear_zebra_fpm_stats, "Clear Forwarding Path Manager information\n" "Statistics\n") { - zfpm_clear_stats (vty); - return CMD_SUCCESS; + zfpm_clear_stats(vty); + return CMD_SUCCESS; } /* - * update fpm connection information + * update fpm connection information */ DEFUN ( fpm_remote_ip, fpm_remote_ip_cmd, @@ -1559,22 +1487,22 @@ DEFUN ( fpm_remote_ip, "Enter ip ") { - in_addr_t fpm_server; - uint32_t port_no; + in_addr_t fpm_server; + uint32_t port_no; - fpm_server = inet_addr (argv[3]->arg); - if (fpm_server == INADDR_NONE) - return CMD_ERR_INCOMPLETE; + fpm_server = inet_addr(argv[3]->arg); + if (fpm_server == INADDR_NONE) + return CMD_ERR_INCOMPLETE; - port_no = atoi (argv[5]->arg); - if (port_no < TCP_MIN_PORT || port_no > TCP_MAX_PORT) - return CMD_ERR_INCOMPLETE; + port_no = atoi(argv[5]->arg); + if (port_no < TCP_MIN_PORT || port_no > TCP_MAX_PORT) + return CMD_ERR_INCOMPLETE; - zfpm_g->fpm_server = fpm_server; - zfpm_g->fpm_port = port_no; + zfpm_g->fpm_server = fpm_server; + zfpm_g->fpm_port = port_no; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN ( no_fpm_remote_ip, @@ -1585,106 +1513,93 @@ DEFUN ( no_fpm_remote_ip, "Remote fpm server ip A.B.C.D\n" "Enter ip ") { - if (zfpm_g->fpm_server != inet_addr (argv[4]->arg) || - zfpm_g->fpm_port != atoi (argv[6]->arg)) - return CMD_ERR_NO_MATCH; + if (zfpm_g->fpm_server != inet_addr(argv[4]->arg) + || zfpm_g->fpm_port != atoi(argv[6]->arg)) + return CMD_ERR_NO_MATCH; - zfpm_g->fpm_server = FPM_DEFAULT_IP; - zfpm_g->fpm_port = FPM_DEFAULT_PORT; + zfpm_g->fpm_server = FPM_DEFAULT_IP; + zfpm_g->fpm_port = FPM_DEFAULT_PORT; - return CMD_SUCCESS; + return CMD_SUCCESS; } /* * zfpm_init_message_format */ -static inline void -zfpm_init_message_format (const char *format) +static inline void zfpm_init_message_format(const char *format) { - int have_netlink, have_protobuf; + int have_netlink, have_protobuf; #ifdef HAVE_NETLINK - have_netlink = 1; + have_netlink = 1; #else - have_netlink = 0; + have_netlink = 0; #endif #ifdef HAVE_PROTOBUF - have_protobuf = 1; + have_protobuf = 1; #else - have_protobuf = 0; + have_protobuf = 0; #endif - zfpm_g->message_format = ZFPM_MSG_FORMAT_NONE; + zfpm_g->message_format = ZFPM_MSG_FORMAT_NONE; - if (!format) - { - if (have_netlink) - { - zfpm_g->message_format = ZFPM_MSG_FORMAT_NETLINK; - } - else if (have_protobuf) - { - zfpm_g->message_format = ZFPM_MSG_FORMAT_PROTOBUF; + if (!format) { + if (have_netlink) { + zfpm_g->message_format = ZFPM_MSG_FORMAT_NETLINK; + } else if (have_protobuf) { + zfpm_g->message_format = ZFPM_MSG_FORMAT_PROTOBUF; + } + return; } - return; - } - if (!strcmp ("netlink", format)) - { - if (!have_netlink) - { - zlog_err ("FPM netlink message format is not available"); - return; + if (!strcmp("netlink", format)) { + if (!have_netlink) { + zlog_err("FPM netlink message format is not available"); + return; + } + zfpm_g->message_format = ZFPM_MSG_FORMAT_NETLINK; + return; } - zfpm_g->message_format = ZFPM_MSG_FORMAT_NETLINK; - return; - } - if (!strcmp ("protobuf", format)) - { - if (!have_protobuf) - { - zlog_err ("FPM protobuf message format is not available"); - return; + if (!strcmp("protobuf", format)) { + if (!have_protobuf) { + zlog_err( + "FPM protobuf message format is not available"); + return; + } + zfpm_g->message_format = ZFPM_MSG_FORMAT_PROTOBUF; + return; } - zfpm_g->message_format = ZFPM_MSG_FORMAT_PROTOBUF; - return; - } - zlog_warn ("Unknown fpm format '%s'", format); + zlog_warn("Unknown fpm format '%s'", format); } /** - * fpm_remote_srv_write + * fpm_remote_srv_write * - * Module to write remote fpm connection + * Module to write remote fpm connection * * Returns ZERO on success. */ -static int fpm_remote_srv_write (struct vty *vty) +static int fpm_remote_srv_write(struct vty *vty) { - struct in_addr in; + struct in_addr in; - in.s_addr = zfpm_g->fpm_server; + in.s_addr = zfpm_g->fpm_server; - if (zfpm_g->fpm_server != FPM_DEFAULT_IP || - zfpm_g->fpm_port != FPM_DEFAULT_PORT) - vty_out (vty,"fpm connection ip %s port %d\n", inet_ntoa (in), - zfpm_g->fpm_port); + if (zfpm_g->fpm_server != FPM_DEFAULT_IP + || zfpm_g->fpm_port != FPM_DEFAULT_PORT) + vty_out(vty, "fpm connection ip %s port %d\n", inet_ntoa(in), + zfpm_g->fpm_port); - return 0; + return 0; } /* Zebra node */ -static struct cmd_node zebra_node = -{ - ZEBRA_NODE, - "", - 1 -}; +static struct cmd_node zebra_node = {ZEBRA_NODE, "", 1}; /** @@ -1698,66 +1613,61 @@ static struct cmd_node zebra_node = * * Returns TRUE on success. */ -static int -zfpm_init (struct thread_master *master) +static int zfpm_init(struct thread_master *master) { - int enable = 1; - uint16_t port = 0; - const char *format = THIS_MODULE->load_args; + int enable = 1; + uint16_t port = 0; + const char *format = THIS_MODULE->load_args; - memset (zfpm_g, 0, sizeof (*zfpm_g)); - zfpm_g->master = master; - TAILQ_INIT(&zfpm_g->dest_q); - zfpm_g->sock = -1; - zfpm_g->state = ZFPM_STATE_IDLE; + memset(zfpm_g, 0, sizeof(*zfpm_g)); + zfpm_g->master = master; + TAILQ_INIT(&zfpm_g->dest_q); + zfpm_g->sock = -1; + zfpm_g->state = ZFPM_STATE_IDLE; - zfpm_stats_init (&zfpm_g->stats); - zfpm_stats_init (&zfpm_g->last_ivl_stats); - zfpm_stats_init (&zfpm_g->cumulative_stats); + zfpm_stats_init(&zfpm_g->stats); + zfpm_stats_init(&zfpm_g->last_ivl_stats); + zfpm_stats_init(&zfpm_g->cumulative_stats); - install_node (&zebra_node, fpm_remote_srv_write); - install_element (ENABLE_NODE, &show_zebra_fpm_stats_cmd); - install_element (ENABLE_NODE, &clear_zebra_fpm_stats_cmd); - install_element (CONFIG_NODE, &fpm_remote_ip_cmd); - install_element (CONFIG_NODE, &no_fpm_remote_ip_cmd); + install_node(&zebra_node, fpm_remote_srv_write); + install_element(ENABLE_NODE, &show_zebra_fpm_stats_cmd); + install_element(ENABLE_NODE, &clear_zebra_fpm_stats_cmd); + install_element(CONFIG_NODE, &fpm_remote_ip_cmd); + install_element(CONFIG_NODE, &no_fpm_remote_ip_cmd); - zfpm_init_message_format(format); + zfpm_init_message_format(format); - /* - * Disable FPM interface if no suitable format is available. - */ - if (zfpm_g->message_format == ZFPM_MSG_FORMAT_NONE) - enable = 0; + /* + * Disable FPM interface if no suitable format is available. + */ + if (zfpm_g->message_format == ZFPM_MSG_FORMAT_NONE) + enable = 0; - zfpm_g->enabled = enable; + zfpm_g->enabled = enable; - if (!zfpm_g->fpm_server) - zfpm_g->fpm_server = FPM_DEFAULT_IP; + if (!zfpm_g->fpm_server) + zfpm_g->fpm_server = FPM_DEFAULT_IP; - if (!port) - port = FPM_DEFAULT_PORT; + if (!port) + port = FPM_DEFAULT_PORT; - zfpm_g->fpm_port = port; + zfpm_g->fpm_port = port; - zfpm_g->obuf = stream_new (ZFPM_OBUF_SIZE); - zfpm_g->ibuf = stream_new (ZFPM_IBUF_SIZE); + zfpm_g->obuf = stream_new(ZFPM_OBUF_SIZE); + zfpm_g->ibuf = stream_new(ZFPM_IBUF_SIZE); - zfpm_start_stats_timer (); - zfpm_start_connect_timer ("initialized"); - return 0; + zfpm_start_stats_timer(); + zfpm_start_connect_timer("initialized"); + return 0; } -static int -zebra_fpm_module_init (void) +static int zebra_fpm_module_init(void) { - hook_register(rib_update, zfpm_trigger_update); - hook_register(frr_late_init, zfpm_init); - return 0; + hook_register(rib_update, zfpm_trigger_update); + hook_register(frr_late_init, zfpm_init); + return 0; } -FRR_MODULE_SETUP( - .name = "zebra_fpm", - .version = FRR_VERSION, - .description = "zebra FPM (Forwarding Plane Manager) module", - .init = zebra_fpm_module_init, -) +FRR_MODULE_SETUP(.name = "zebra_fpm", .version = FRR_VERSION, + .description = "zebra FPM (Forwarding Plane Manager) module", + .init = zebra_fpm_module_init, ) diff --git a/zebra/zebra_fpm_dt.c b/zebra/zebra_fpm_dt.c index 916640928..48db246bc 100644 --- a/zebra/zebra_fpm_dt.c +++ b/zebra/zebra_fpm_dt.c @@ -57,85 +57,83 @@ /* * Externs. */ -extern int zfpm_dt_benchmark_netlink_encode (int argc, const char **argv); -extern int zfpm_dt_benchmark_protobuf_encode (int argc, const char **argv); -extern int zfpm_dt_benchmark_protobuf_decode (int argc, const char **argv); +extern int zfpm_dt_benchmark_netlink_encode(int argc, const char **argv); +extern int zfpm_dt_benchmark_protobuf_encode(int argc, const char **argv); +extern int zfpm_dt_benchmark_protobuf_decode(int argc, const char **argv); /* * zfpm_dt_find_route * * Selects a suitable rib destination for fpm interface tests. */ -static int -zfpm_dt_find_route (rib_dest_t **dest_p, struct route_entry **re_p) +static int zfpm_dt_find_route(rib_dest_t **dest_p, struct route_entry **re_p) { - struct route_node *rnode; - route_table_iter_t iter; - struct route_table *table; - rib_dest_t *dest; - struct route_entry *re; - int ret; - - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); - if (!table) - return 0; - - route_table_iter_init(&iter, table); - while ((rnode = route_table_iter_next(&iter))) - { - dest = rib_dest_from_rnode (rnode); - - if (!dest) - continue; - - re = zfpm_route_for_update(dest); - if (!re) - continue; - - if (re->nexthop_active_num <= 0) - continue; - - *dest_p = dest; - *re_p = re; - ret = 1; - goto done; - } - - ret = 0; - - done: - route_table_iter_cleanup(&iter); - return ret; + struct route_node *rnode; + route_table_iter_t iter; + struct route_table *table; + rib_dest_t *dest; + struct route_entry *re; + int ret; + + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + if (!table) + return 0; + + route_table_iter_init(&iter, table); + while ((rnode = route_table_iter_next(&iter))) { + dest = rib_dest_from_rnode(rnode); + + if (!dest) + continue; + + re = zfpm_route_for_update(dest); + if (!re) + continue; + + if (re->nexthop_active_num <= 0) + continue; + + *dest_p = dest; + *re_p = re; + ret = 1; + goto done; + } + + ret = 0; + +done: + route_table_iter_cleanup(&iter); + return ret; } #ifdef HAVE_NETLINK /* * zfpm_dt_benchmark_netlink_encode */ -int -zfpm_dt_benchmark_netlink_encode (int argc, const char **argv) +int zfpm_dt_benchmark_netlink_encode(int argc, const char **argv) { - int times, i, len; - rib_dest_t *dest; - struct route_entry *re; - char buf[4096]; - - times = 100000; - if (argc > 0) { - times = atoi(argv[0]); - } - - if (!zfpm_dt_find_route(&dest, &re)) { - return 1; - } - - for (i = 0; i < times; i++) { - len = zfpm_netlink_encode_route(RTM_NEWROUTE, dest, re, buf, sizeof(buf)); - if (len <= 0) { - return 2; - } - } - return 0; + int times, i, len; + rib_dest_t *dest; + struct route_entry *re; + char buf[4096]; + + times = 100000; + if (argc > 0) { + times = atoi(argv[0]); + } + + if (!zfpm_dt_find_route(&dest, &re)) { + return 1; + } + + for (i = 0; i < times; i++) { + len = zfpm_netlink_encode_route(RTM_NEWROUTE, dest, re, buf, + sizeof(buf)); + if (len <= 0) { + return 2; + } + } + return 0; } #endif /* HAVE_NETLINK */ @@ -145,134 +143,129 @@ zfpm_dt_benchmark_netlink_encode (int argc, const char **argv) /* * zfpm_dt_benchmark_protobuf_encode */ -int -zfpm_dt_benchmark_protobuf_encode (int argc, const char **argv) +int zfpm_dt_benchmark_protobuf_encode(int argc, const char **argv) { - int times, i, len; - rib_dest_t *dest; - struct route_entry *re; - uint8_t buf[4096]; - - times = 100000; - if (argc > 0) { - times = atoi(argv[0]); - } - - if (!zfpm_dt_find_route(&dest, &re)) { - return 1; - } - - for (i = 0; i < times; i++) { - len = zfpm_protobuf_encode_route(dest, re, buf, sizeof(buf)); - if (len <= 0) { - return 2; - } - } - return 0; + int times, i, len; + rib_dest_t *dest; + struct route_entry *re; + uint8_t buf[4096]; + + times = 100000; + if (argc > 0) { + times = atoi(argv[0]); + } + + if (!zfpm_dt_find_route(&dest, &re)) { + return 1; + } + + for (i = 0; i < times; i++) { + len = zfpm_protobuf_encode_route(dest, re, buf, sizeof(buf)); + if (len <= 0) { + return 2; + } + } + return 0; } /* * zfpm_dt_log_fpm_message */ -static void -zfpm_dt_log_fpm_message (Fpm__Message *msg) +static void zfpm_dt_log_fpm_message(Fpm__Message *msg) { - Fpm__AddRoute *add_route; - Fpm__Nexthop *nexthop; - struct prefix prefix; - u_char family, nh_family; - uint if_index; - char *if_name; - size_t i; - char buf[INET6_ADDRSTRLEN]; - union g_addr nh_addr; - - if (msg->type != FPM__MESSAGE__TYPE__ADD_ROUTE) - return; - - zfpm_debug ("Add route message"); - add_route = msg->add_route; - - if (!qpb_address_family_get (add_route->address_family, &family)) - return; - - if (!qpb_l3_prefix_get (add_route->key->prefix, family, &prefix)) - return; - - zfpm_debug ("Vrf id: %d, Prefix: %s/%d, Metric: %d", add_route->vrf_id, - inet_ntop (family, &prefix.u.prefix, buf, sizeof (buf)), - prefix.prefixlen, add_route->metric); - - /* - * Go over nexthops. - */ - for (i = 0; i < add_route->n_nexthops; i++) - { - nexthop = add_route->nexthops[i]; - if (!qpb_if_identifier_get (nexthop->if_id, &if_index, &if_name)) - continue; - - if (nexthop->address) - qpb_l3_address_get (nexthop->address, &nh_family, &nh_addr); - - zfpm_debug ("Nexthop - if_index: %d (%s), gateway: %s, ", if_index, - if_name ? if_name : "name not specified", - nexthop->address ? inet_ntoa (nh_addr.ipv4) : "None"); - } + Fpm__AddRoute *add_route; + Fpm__Nexthop *nexthop; + struct prefix prefix; + u_char family, nh_family; + uint if_index; + char *if_name; + size_t i; + char buf[INET6_ADDRSTRLEN]; + union g_addr nh_addr; + + if (msg->type != FPM__MESSAGE__TYPE__ADD_ROUTE) + return; + + zfpm_debug("Add route message"); + add_route = msg->add_route; + + if (!qpb_address_family_get(add_route->address_family, &family)) + return; + + if (!qpb_l3_prefix_get(add_route->key->prefix, family, &prefix)) + return; + + zfpm_debug("Vrf id: %d, Prefix: %s/%d, Metric: %d", add_route->vrf_id, + inet_ntop(family, &prefix.u.prefix, buf, sizeof(buf)), + prefix.prefixlen, add_route->metric); + + /* + * Go over nexthops. + */ + for (i = 0; i < add_route->n_nexthops; i++) { + nexthop = add_route->nexthops[i]; + if (!qpb_if_identifier_get(nexthop->if_id, &if_index, &if_name)) + continue; + + if (nexthop->address) + qpb_l3_address_get(nexthop->address, &nh_family, + &nh_addr); + + zfpm_debug("Nexthop - if_index: %d (%s), gateway: %s, ", + if_index, if_name ? if_name : "name not specified", + nexthop->address ? inet_ntoa(nh_addr.ipv4) : "None"); + } } /* * zfpm_dt_benchmark_protobuf_decode */ -int -zfpm_dt_benchmark_protobuf_decode (int argc, const char **argv) +int zfpm_dt_benchmark_protobuf_decode(int argc, const char **argv) { - int times, i, len; - rib_dest_t *dest; - struct route_entry *re; - uint8_t msg_buf[4096]; - QPB_DECLARE_STACK_ALLOCATOR (allocator, 8192); - Fpm__Message *fpm_msg; - - QPB_INIT_STACK_ALLOCATOR (allocator); - - times = 100000; - if (argc > 0) - times = atoi(argv[0]); - - if (!zfpm_dt_find_route (&dest, &re)) - return 1; - - /* - * Encode the route into the message buffer once only. - */ - len = zfpm_protobuf_encode_route (dest, re, msg_buf, sizeof (msg_buf)); - if (len <= 0) - return 2; - - // Decode once, and display the decoded message - fpm_msg = fpm__message__unpack(&allocator, len, msg_buf); - - if (fpm_msg) - { - zfpm_dt_log_fpm_message(fpm_msg); - QPB_RESET_STACK_ALLOCATOR (allocator); - } - - /* - * Decode encoded message the specified number of times. - */ - for (i = 0; i < times; i++) - { - fpm_msg = fpm__message__unpack (&allocator, len, msg_buf); - - if (!fpm_msg) - return 3; - - // fpm__message__free_unpacked(msg, NULL); - QPB_RESET_STACK_ALLOCATOR (allocator); - } - return 0; + int times, i, len; + rib_dest_t *dest; + struct route_entry *re; + uint8_t msg_buf[4096]; + QPB_DECLARE_STACK_ALLOCATOR(allocator, 8192); + Fpm__Message *fpm_msg; + + QPB_INIT_STACK_ALLOCATOR(allocator); + + times = 100000; + if (argc > 0) + times = atoi(argv[0]); + + if (!zfpm_dt_find_route(&dest, &re)) + return 1; + + /* + * Encode the route into the message buffer once only. + */ + len = zfpm_protobuf_encode_route(dest, re, msg_buf, sizeof(msg_buf)); + if (len <= 0) + return 2; + + // Decode once, and display the decoded message + fpm_msg = fpm__message__unpack(&allocator, len, msg_buf); + + if (fpm_msg) { + zfpm_dt_log_fpm_message(fpm_msg); + QPB_RESET_STACK_ALLOCATOR(allocator); + } + + /* + * Decode encoded message the specified number of times. + */ + for (i = 0; i < times; i++) { + fpm_msg = fpm__message__unpack(&allocator, len, msg_buf); + + if (!fpm_msg) + return 3; + + // fpm__message__free_unpacked(msg, NULL); + QPB_RESET_STACK_ALLOCATOR(allocator); + } + return 0; } #endif /* HAVE_PROTOBUF */ diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c index d935826db..862049cb8 100644 --- a/zebra/zebra_fpm_netlink.c +++ b/zebra/zebra_fpm_netlink.c @@ -43,25 +43,23 @@ * * Returns string representation of an address of the given AF. */ -static inline const char * -addr_to_a (u_char af, void *addr) +static inline const char *addr_to_a(u_char af, void *addr) { - if (!addr) - return ""; - - switch (af) - { - - case AF_INET: - return inet_ntoa (*((struct in_addr *) addr)); - break; - case AF_INET6: - return inet6_ntoa (*((struct in6_addr *) addr)); - break; - default: - return ""; - break; - } + if (!addr) + return ""; + + switch (af) { + + case AF_INET: + return inet_ntoa(*((struct in_addr *)addr)); + break; + case AF_INET6: + return inet6_ntoa(*((struct in6_addr *)addr)); + break; + default: + return ""; + break; + } } /* @@ -70,13 +68,12 @@ addr_to_a (u_char af, void *addr) * Convience wrapper that returns a human-readable string for the * address in a prefix. */ -static const char * -prefix_addr_to_a (struct prefix *prefix) +static const char *prefix_addr_to_a(struct prefix *prefix) { - if (!prefix) - return ""; + if (!prefix) + return ""; - return addr_to_a (prefix->family, &prefix->u.prefix); + return addr_to_a(prefix->family, &prefix->u.prefix); } /* @@ -84,22 +81,20 @@ prefix_addr_to_a (struct prefix *prefix) * * The size of an address in a given address family. */ -static size_t -af_addr_size (u_char af) +static size_t af_addr_size(u_char af) { - switch (af) - { - - case AF_INET: - return 4; - break; - case AF_INET6: - return 16; - break; - default: - assert(0); - return 16; - } + switch (af) { + + case AF_INET: + return 4; + break; + case AF_INET6: + return 16; + break; + default: + assert(0); + return 16; + } } /* @@ -109,17 +104,16 @@ af_addr_size (u_char af) * structures are transient and may contain pointers into rib * data structures for convenience. */ -typedef struct netlink_nh_info_t_ -{ - uint32_t if_index; - union g_addr *gateway; - - /* - * Information from the struct nexthop from which this nh was - * derived. For debug purposes only. - */ - int recursive; - enum nexthop_types_t type; +typedef struct netlink_nh_info_t_ { + uint32_t if_index; + union g_addr *gateway; + + /* + * Information from the struct nexthop from which this nh was + * derived. For debug purposes only. + */ + int recursive; + enum nexthop_types_t type; } netlink_nh_info_t; /* @@ -127,22 +121,21 @@ typedef struct netlink_nh_info_t_ * * A structure for holding information for a netlink route message. */ -typedef struct netlink_route_info_t_ -{ - uint16_t nlmsg_type; - u_char rtm_type; - uint32_t rtm_table; - u_char rtm_protocol; - u_char af; - struct prefix *prefix; - uint32_t *metric; - unsigned int num_nhs; - - /* - * Nexthop structures - */ - netlink_nh_info_t nhs[MULTIPATH_NUM]; - union g_addr *pref_src; +typedef struct netlink_route_info_t_ { + uint16_t nlmsg_type; + u_char rtm_type; + uint32_t rtm_table; + u_char rtm_protocol; + u_char af; + struct prefix *prefix; + uint32_t *metric; + unsigned int num_nhs; + + /* + * Nexthop structures + */ + netlink_nh_info_t nhs[MULTIPATH_NUM]; + union g_addr *pref_src; } netlink_route_info_t; /* @@ -153,72 +146,67 @@ typedef struct netlink_route_info_t_ * * Returns TRUE if a nexthop was added, FALSE otherwise. */ -static int -netlink_route_info_add_nh (netlink_route_info_t *ri, struct nexthop *nexthop) +static int netlink_route_info_add_nh(netlink_route_info_t *ri, + struct nexthop *nexthop) { - netlink_nh_info_t nhi; - union g_addr *src; - - memset (&nhi, 0, sizeof (nhi)); - src = NULL; - - if (ri->num_nhs >= (int) ZEBRA_NUM_OF (ri->nhs)) - return 0; - - nhi.recursive = nexthop->rparent ? 1 : 0; - nhi.type = nexthop->type; - nhi.if_index = nexthop->ifindex; - - if (nexthop->type == NEXTHOP_TYPE_IPV4 - || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - { - nhi.gateway = &nexthop->gate; - if (nexthop->src.ipv4.s_addr) - src = &nexthop->src; - } - - if (nexthop->type == NEXTHOP_TYPE_IPV6 - || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - { - nhi.gateway = &nexthop->gate; - } - - if (nexthop->type == NEXTHOP_TYPE_IFINDEX) - { - if (nexthop->src.ipv4.s_addr) - src = &nexthop->src; - } - - if (!nhi.gateway && nhi.if_index == 0) - return 0; - - /* - * We have a valid nhi. Copy the structure over to the route_info. - */ - ri->nhs[ri->num_nhs] = nhi; - ri->num_nhs++; - - if (src && !ri->pref_src) - ri->pref_src = src; - - return 1; + netlink_nh_info_t nhi; + union g_addr *src; + + memset(&nhi, 0, sizeof(nhi)); + src = NULL; + + if (ri->num_nhs >= (int)ZEBRA_NUM_OF(ri->nhs)) + return 0; + + nhi.recursive = nexthop->rparent ? 1 : 0; + nhi.type = nexthop->type; + nhi.if_index = nexthop->ifindex; + + if (nexthop->type == NEXTHOP_TYPE_IPV4 + || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { + nhi.gateway = &nexthop->gate; + if (nexthop->src.ipv4.s_addr) + src = &nexthop->src; + } + + if (nexthop->type == NEXTHOP_TYPE_IPV6 + || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { + nhi.gateway = &nexthop->gate; + } + + if (nexthop->type == NEXTHOP_TYPE_IFINDEX) { + if (nexthop->src.ipv4.s_addr) + src = &nexthop->src; + } + + if (!nhi.gateway && nhi.if_index == 0) + return 0; + + /* + * We have a valid nhi. Copy the structure over to the route_info. + */ + ri->nhs[ri->num_nhs] = nhi; + ri->num_nhs++; + + if (src && !ri->pref_src) + ri->pref_src = src; + + return 1; } /* * netlink_proto_from_route_type */ -static u_char -netlink_proto_from_route_type (int type) +static u_char netlink_proto_from_route_type(int type) { - switch (type) - { - case ZEBRA_ROUTE_KERNEL: - case ZEBRA_ROUTE_CONNECT: - return RTPROT_KERNEL; - - default: - return RTPROT_ZEBRA; - } + switch (type) { + case ZEBRA_ROUTE_KERNEL: + case ZEBRA_ROUTE_CONNECT: + return RTPROT_KERNEL; + + default: + return RTPROT_ZEBRA; + } } /* @@ -228,87 +216,81 @@ netlink_proto_from_route_type (int type) * * Returns TRUE on success and FALSE on failure. */ -static int -netlink_route_info_fill (netlink_route_info_t *ri, int cmd, - rib_dest_t *dest, struct route_entry *re) +static int netlink_route_info_fill(netlink_route_info_t *ri, int cmd, + rib_dest_t *dest, struct route_entry *re) { - struct nexthop *nexthop; - int discard; - - memset (ri, 0, sizeof (*ri)); - - ri->prefix = rib_dest_prefix (dest); - ri->af = rib_dest_af (dest); - - ri->nlmsg_type = cmd; - ri->rtm_table = zvrf_id (rib_dest_vrf (dest)); - ri->rtm_protocol = RTPROT_UNSPEC; - - /* - * An RTM_DELROUTE need not be accompanied by any nexthops, - * particularly in our communication with the FPM. - */ - if (cmd == RTM_DELROUTE && !re) - return 1; - - if (!re) - { - zfpm_debug ("%s: Expected non-NULL re pointer", __PRETTY_FUNCTION__); - return 0; - } - - ri->rtm_protocol = netlink_proto_from_route_type (re->type); - - if ((re->flags & ZEBRA_FLAG_BLACKHOLE) || (re->flags & ZEBRA_FLAG_REJECT)) - discard = 1; - else - discard = 0; - - if (cmd == RTM_NEWROUTE) - { - if (discard) - { - if (re->flags & ZEBRA_FLAG_BLACKHOLE) - ri->rtm_type = RTN_BLACKHOLE; - else if (re->flags & ZEBRA_FLAG_REJECT) - ri->rtm_type = RTN_UNREACHABLE; - else - assert (0); - } - else - ri->rtm_type = RTN_UNICAST; - } - - ri->metric = &re->metric; - - if (discard) - return 1; - - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - if (ri->num_nhs >= multipath_num) - break; - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; - - if ((cmd == RTM_NEWROUTE - && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - || (cmd == RTM_DELROUTE - && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))) - { - netlink_route_info_add_nh (ri, nexthop); - } - } - - /* If there is no useful nexthop then return. */ - if (ri->num_nhs == 0) - { - zfpm_debug ("netlink_encode_route(): No useful nexthop."); - return 0; - } - - return 1; + struct nexthop *nexthop; + int discard; + + memset(ri, 0, sizeof(*ri)); + + ri->prefix = rib_dest_prefix(dest); + ri->af = rib_dest_af(dest); + + ri->nlmsg_type = cmd; + ri->rtm_table = zvrf_id(rib_dest_vrf(dest)); + ri->rtm_protocol = RTPROT_UNSPEC; + + /* + * An RTM_DELROUTE need not be accompanied by any nexthops, + * particularly in our communication with the FPM. + */ + if (cmd == RTM_DELROUTE && !re) + return 1; + + if (!re) { + zfpm_debug("%s: Expected non-NULL re pointer", + __PRETTY_FUNCTION__); + return 0; + } + + ri->rtm_protocol = netlink_proto_from_route_type(re->type); + + if ((re->flags & ZEBRA_FLAG_BLACKHOLE) + || (re->flags & ZEBRA_FLAG_REJECT)) + discard = 1; + else + discard = 0; + + if (cmd == RTM_NEWROUTE) { + if (discard) { + if (re->flags & ZEBRA_FLAG_BLACKHOLE) + ri->rtm_type = RTN_BLACKHOLE; + else if (re->flags & ZEBRA_FLAG_REJECT) + ri->rtm_type = RTN_UNREACHABLE; + else + assert(0); + } else + ri->rtm_type = RTN_UNICAST; + } + + ri->metric = &re->metric; + + if (discard) + return 1; + + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + if (ri->num_nhs >= multipath_num) + break; + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + continue; + + if ((cmd == RTM_NEWROUTE + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + || (cmd == RTM_DELROUTE + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))) { + netlink_route_info_add_nh(ri, nexthop); + } + } + + /* If there is no useful nexthop then return. */ + if (ri->num_nhs == 0) { + zfpm_debug("netlink_encode_route(): No useful nexthop."); + return 0; + } + + return 1; } /* @@ -317,122 +299,114 @@ netlink_route_info_fill (netlink_route_info_t *ri, int cmd, * Returns the number of bytes written to the buffer. 0 or a negative * value indicates an error. */ -static int -netlink_route_info_encode (netlink_route_info_t *ri, char *in_buf, - size_t in_buf_len) +static int netlink_route_info_encode(netlink_route_info_t *ri, char *in_buf, + size_t in_buf_len) { - size_t bytelen; - unsigned int nexthop_num = 0; - size_t buf_offset; - netlink_nh_info_t *nhi; + size_t bytelen; + unsigned int nexthop_num = 0; + size_t buf_offset; + netlink_nh_info_t *nhi; - struct - { - struct nlmsghdr n; - struct rtmsg r; - char buf[1]; - } *req; + struct { + struct nlmsghdr n; + struct rtmsg r; + char buf[1]; + } * req; - req = (void *) in_buf; + req = (void *)in_buf; - buf_offset = ((char *) req->buf) - ((char *) req); + buf_offset = ((char *)req->buf) - ((char *)req); - if (in_buf_len < buf_offset) { - assert(0); - return 0; - } - - memset (req, 0, buf_offset); - - bytelen = af_addr_size (ri->af); - - req->n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg)); - req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; - req->n.nlmsg_type = ri->nlmsg_type; - req->r.rtm_family = ri->af; - req->r.rtm_table = ri->rtm_table; - req->r.rtm_dst_len = ri->prefix->prefixlen; - req->r.rtm_protocol = ri->rtm_protocol; - req->r.rtm_scope = RT_SCOPE_UNIVERSE; - - addattr_l (&req->n, in_buf_len, RTA_DST, &ri->prefix->u.prefix, bytelen); - - req->r.rtm_type = ri->rtm_type; - - /* Metric. */ - if (ri->metric) - addattr32 (&req->n, in_buf_len, RTA_PRIORITY, *ri->metric); + if (in_buf_len < buf_offset) { + assert(0); + return 0; + } - if (ri->num_nhs == 0) - goto done; + memset(req, 0, buf_offset); - if (ri->num_nhs == 1) - { - nhi = &ri->nhs[0]; + bytelen = af_addr_size(ri->af); - if (nhi->gateway) - { - addattr_l (&req->n, in_buf_len, RTA_GATEWAY, nhi->gateway, - bytelen); - } + req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; + req->n.nlmsg_type = ri->nlmsg_type; + req->r.rtm_family = ri->af; + req->r.rtm_table = ri->rtm_table; + req->r.rtm_dst_len = ri->prefix->prefixlen; + req->r.rtm_protocol = ri->rtm_protocol; + req->r.rtm_scope = RT_SCOPE_UNIVERSE; - if (nhi->if_index) - { - addattr32 (&req->n, in_buf_len, RTA_OIF, nhi->if_index); - } + addattr_l(&req->n, in_buf_len, RTA_DST, &ri->prefix->u.prefix, bytelen); - goto done; + req->r.rtm_type = ri->rtm_type; - } + /* Metric. */ + if (ri->metric) + addattr32(&req->n, in_buf_len, RTA_PRIORITY, *ri->metric); - /* - * Multipath case. - */ - char buf[NL_PKT_BUF_SIZE]; - struct rtattr *rta = (void *) buf; - struct rtnexthop *rtnh; + if (ri->num_nhs == 0) + goto done; - rta->rta_type = RTA_MULTIPATH; - rta->rta_len = RTA_LENGTH (0); - rtnh = RTA_DATA (rta); + if (ri->num_nhs == 1) { + nhi = &ri->nhs[0]; - for (nexthop_num = 0; nexthop_num < ri->num_nhs; nexthop_num++) - { - nhi = &ri->nhs[nexthop_num]; + if (nhi->gateway) { + addattr_l(&req->n, in_buf_len, RTA_GATEWAY, + nhi->gateway, bytelen); + } - rtnh->rtnh_len = sizeof (*rtnh); - rtnh->rtnh_flags = 0; - rtnh->rtnh_hops = 0; - rtnh->rtnh_ifindex = 0; - rta->rta_len += rtnh->rtnh_len; + if (nhi->if_index) { + addattr32(&req->n, in_buf_len, RTA_OIF, nhi->if_index); + } - if (nhi->gateway) - { - rta_addattr_l (rta, sizeof (buf), RTA_GATEWAY, nhi->gateway, bytelen); - rtnh->rtnh_len += sizeof (struct rtattr) + bytelen; + goto done; } - if (nhi->if_index) - { - rtnh->rtnh_ifindex = nhi->if_index; + /* + * Multipath case. + */ + char buf[NL_PKT_BUF_SIZE]; + struct rtattr *rta = (void *)buf; + struct rtnexthop *rtnh; + + rta->rta_type = RTA_MULTIPATH; + rta->rta_len = RTA_LENGTH(0); + rtnh = RTA_DATA(rta); + + for (nexthop_num = 0; nexthop_num < ri->num_nhs; nexthop_num++) { + nhi = &ri->nhs[nexthop_num]; + + rtnh->rtnh_len = sizeof(*rtnh); + rtnh->rtnh_flags = 0; + rtnh->rtnh_hops = 0; + rtnh->rtnh_ifindex = 0; + rta->rta_len += rtnh->rtnh_len; + + if (nhi->gateway) { + rta_addattr_l(rta, sizeof(buf), RTA_GATEWAY, + nhi->gateway, bytelen); + rtnh->rtnh_len += sizeof(struct rtattr) + bytelen; + } + + if (nhi->if_index) { + rtnh->rtnh_ifindex = nhi->if_index; + } + + rtnh = RTNH_NEXT(rtnh); } - rtnh = RTNH_NEXT (rtnh); - } - - assert (rta->rta_len > RTA_LENGTH (0)); - addattr_l (&req->n, in_buf_len, RTA_MULTIPATH, RTA_DATA (rta), - RTA_PAYLOAD (rta)); + assert(rta->rta_len > RTA_LENGTH(0)); + addattr_l(&req->n, in_buf_len, RTA_MULTIPATH, RTA_DATA(rta), + RTA_PAYLOAD(rta)); done: - if (ri->pref_src) - { - addattr_l (&req->n, in_buf_len, RTA_PREFSRC, &ri->pref_src, bytelen); - } + if (ri->pref_src) { + addattr_l(&req->n, in_buf_len, RTA_PREFSRC, &ri->pref_src, + bytelen); + } - assert (req->n.nlmsg_len < in_buf_len); - return req->n.nlmsg_len; + assert(req->n.nlmsg_len < in_buf_len); + return req->n.nlmsg_len; } /* @@ -440,26 +414,24 @@ done: * * Helper function to log the information in a route_info structure. */ -static void -zfpm_log_route_info (netlink_route_info_t *ri, const char *label) +static void zfpm_log_route_info(netlink_route_info_t *ri, const char *label) { - netlink_nh_info_t *nhi; - unsigned int i; - - zfpm_debug ("%s : %s %s/%d, Proto: %s, Metric: %u", label, - nl_msg_type_to_str (ri->nlmsg_type), - prefix_addr_to_a (ri->prefix), ri->prefix->prefixlen, - nl_rtproto_to_str (ri->rtm_protocol), - ri->metric ? *ri->metric : 0); - - for (i = 0; i < ri->num_nhs; i++) - { - nhi = &ri->nhs[i]; - zfpm_debug(" Intf: %u, Gateway: %s, Recursive: %s, Type: %s", - nhi->if_index, addr_to_a (ri->af, nhi->gateway), - nhi->recursive ? "yes" : "no", - nexthop_type_to_str (nhi->type)); - } + netlink_nh_info_t *nhi; + unsigned int i; + + zfpm_debug("%s : %s %s/%d, Proto: %s, Metric: %u", label, + nl_msg_type_to_str(ri->nlmsg_type), + prefix_addr_to_a(ri->prefix), ri->prefix->prefixlen, + nl_rtproto_to_str(ri->rtm_protocol), + ri->metric ? *ri->metric : 0); + + for (i = 0; i < ri->num_nhs; i++) { + nhi = &ri->nhs[i]; + zfpm_debug(" Intf: %u, Gateway: %s, Recursive: %s, Type: %s", + nhi->if_index, addr_to_a(ri->af, nhi->gateway), + nhi->recursive ? "yes" : "no", + nexthop_type_to_str(nhi->type)); + } } /* @@ -471,18 +443,17 @@ zfpm_log_route_info (netlink_route_info_t *ri, const char *label) * Returns the number of bytes written to the buffer. 0 or a negative * value indicates an error. */ -int -zfpm_netlink_encode_route (int cmd, rib_dest_t *dest, struct route_entry *re, - char *in_buf, size_t in_buf_len) +int zfpm_netlink_encode_route(int cmd, rib_dest_t *dest, struct route_entry *re, + char *in_buf, size_t in_buf_len) { - netlink_route_info_t ri_space, *ri; + netlink_route_info_t ri_space, *ri; - ri = &ri_space; + ri = &ri_space; - if (!netlink_route_info_fill (ri, cmd, dest, re)) - return 0; + if (!netlink_route_info_fill(ri, cmd, dest, re)) + return 0; - zfpm_log_route_info (ri, __FUNCTION__); + zfpm_log_route_info(ri, __FUNCTION__); - return netlink_route_info_encode (ri, in_buf, in_buf_len); + return netlink_route_info_encode(ri, in_buf, in_buf_len); } diff --git a/zebra/zebra_fpm_private.h b/zebra/zebra_fpm_private.h index 441a22a79..969ab6cfe 100644 --- a/zebra/zebra_fpm_private.h +++ b/zebra/zebra_fpm_private.h @@ -28,33 +28,37 @@ #if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L -#define zfpm_debug(...) \ - do { \ - if (IS_ZEBRA_DEBUG_FPM) zlog_debug("FPM: " __VA_ARGS__); \ - } while(0) +#define zfpm_debug(...) \ + do { \ + if (IS_ZEBRA_DEBUG_FPM) \ + zlog_debug("FPM: " __VA_ARGS__); \ + } while (0) #elif defined __GNUC__ -#define zfpm_debug(_args...) \ - do { \ - if (IS_ZEBRA_DEBUG_FPM) zlog_debug("FPM: " _args); \ - } while(0) +#define zfpm_debug(_args...) \ + do { \ + if (IS_ZEBRA_DEBUG_FPM) \ + zlog_debug("FPM: " _args); \ + } while (0) #else -static inline void zfpm_debug(const char *format, ...) { return; } +static inline void zfpm_debug(const char *format, ...) +{ + return; +} #endif /* * Externs */ -extern int -zfpm_netlink_encode_route (int cmd, rib_dest_t *dest, struct route_entry *re, - char *in_buf, size_t in_buf_len); +extern int zfpm_netlink_encode_route(int cmd, rib_dest_t *dest, + struct route_entry *re, char *in_buf, + size_t in_buf_len); -extern int -zfpm_protobuf_encode_route (rib_dest_t *dest, struct route_entry *re, - uint8_t *in_buf, size_t in_buf_len); +extern int zfpm_protobuf_encode_route(rib_dest_t *dest, struct route_entry *re, + uint8_t *in_buf, size_t in_buf_len); -extern struct route_entry *zfpm_route_for_update (rib_dest_t *dest); +extern struct route_entry *zfpm_route_for_update(rib_dest_t *dest); #endif /* _ZEBRA_FPM_PRIVATE_H */ diff --git a/zebra/zebra_fpm_protobuf.c b/zebra/zebra_fpm_protobuf.c index 1e8af19ea..450ad5b0b 100644 --- a/zebra/zebra_fpm_protobuf.c +++ b/zebra/zebra_fpm_protobuf.c @@ -39,241 +39,237 @@ /* * create_delete_route_message */ -static Fpm__DeleteRoute * -create_delete_route_message (qpb_allocator_t *allocator, rib_dest_t *dest, - struct route_entry *re) +static Fpm__DeleteRoute *create_delete_route_message(qpb_allocator_t *allocator, + rib_dest_t *dest, + struct route_entry *re) { - Fpm__DeleteRoute *msg; - - msg = QPB_ALLOC(allocator, typeof(*msg)); - if (!msg) { - assert(0); - return NULL; - } - - fpm__delete_route__init(msg); - msg->vrf_id = zvrf_id(rib_dest_vrf(dest)); - - qpb_address_family_set(&msg->address_family, rib_dest_af(dest)); - - /* - * XXX Hardcode subaddress family for now. - */ - msg->sub_address_family = QPB__SUB_ADDRESS_FAMILY__UNICAST; - msg->key = fpm_route_key_create (allocator, rib_dest_prefix(dest)); - if (!msg->key) { - assert(0); - return NULL; - } - - return msg; + Fpm__DeleteRoute *msg; + + msg = QPB_ALLOC(allocator, typeof(*msg)); + if (!msg) { + assert(0); + return NULL; + } + + fpm__delete_route__init(msg); + msg->vrf_id = zvrf_id(rib_dest_vrf(dest)); + + qpb_address_family_set(&msg->address_family, rib_dest_af(dest)); + + /* + * XXX Hardcode subaddress family for now. + */ + msg->sub_address_family = QPB__SUB_ADDRESS_FAMILY__UNICAST; + msg->key = fpm_route_key_create(allocator, rib_dest_prefix(dest)); + if (!msg->key) { + assert(0); + return NULL; + } + + return msg; } /* * add_nexthop */ -static inline int -add_nexthop (qpb_allocator_t *allocator, Fpm__AddRoute *msg, rib_dest_t *dest, - struct nexthop *nexthop) +static inline int add_nexthop(qpb_allocator_t *allocator, Fpm__AddRoute *msg, + rib_dest_t *dest, struct nexthop *nexthop) { - uint32_t if_index; - union g_addr *gateway, *src; - - gateway = src = NULL; - - if_index = nexthop->ifindex; - - if (nexthop->type == NEXTHOP_TYPE_IPV4 - || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - { - gateway = &nexthop->gate; - if (nexthop->src.ipv4.s_addr) - src = &nexthop->src; - } - - if (nexthop->type == NEXTHOP_TYPE_IPV6 - || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - { - gateway = &nexthop->gate; - } - - if (nexthop->type == NEXTHOP_TYPE_IFINDEX) - { - if (nexthop->src.ipv4.s_addr) - src = &nexthop->src; - } - - if (!gateway && if_index == 0) - return 0; - - /* - * We have a valid nexthop. - */ - { - Fpm__Nexthop *pb_nh; - pb_nh = QPB_ALLOC(allocator, typeof(*pb_nh)); - if (!pb_nh) { - assert(0); - return 0; - } - - fpm__nexthop__init(pb_nh); - - if (if_index != 0) { - pb_nh->if_id = qpb_if_identifier_create (allocator, if_index); - } - - if (gateway) { - pb_nh->address = qpb_l3_address_create (allocator, gateway, - rib_dest_af(dest)); - } - - msg->nexthops[msg->n_nexthops++] = pb_nh; - } - - // TODO: Use src. - - return 1; + uint32_t if_index; + union g_addr *gateway, *src; + + gateway = src = NULL; + + if_index = nexthop->ifindex; + + if (nexthop->type == NEXTHOP_TYPE_IPV4 + || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { + gateway = &nexthop->gate; + if (nexthop->src.ipv4.s_addr) + src = &nexthop->src; + } + + if (nexthop->type == NEXTHOP_TYPE_IPV6 + || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { + gateway = &nexthop->gate; + } + + if (nexthop->type == NEXTHOP_TYPE_IFINDEX) { + if (nexthop->src.ipv4.s_addr) + src = &nexthop->src; + } + + if (!gateway && if_index == 0) + return 0; + + /* + * We have a valid nexthop. + */ + { + Fpm__Nexthop *pb_nh; + pb_nh = QPB_ALLOC(allocator, typeof(*pb_nh)); + if (!pb_nh) { + assert(0); + return 0; + } + + fpm__nexthop__init(pb_nh); + + if (if_index != 0) { + pb_nh->if_id = + qpb_if_identifier_create(allocator, if_index); + } + + if (gateway) { + pb_nh->address = qpb_l3_address_create( + allocator, gateway, rib_dest_af(dest)); + } + + msg->nexthops[msg->n_nexthops++] = pb_nh; + } + + // TODO: Use src. + + return 1; } /* * create_add_route_message */ -static Fpm__AddRoute * -create_add_route_message (qpb_allocator_t *allocator, rib_dest_t *dest, - struct route_entry *re) +static Fpm__AddRoute *create_add_route_message(qpb_allocator_t *allocator, + rib_dest_t *dest, + struct route_entry *re) { - Fpm__AddRoute *msg; - int discard; - struct nexthop *nexthop; - uint num_nhs, u; - struct nexthop *nexthops[MULTIPATH_NUM]; - - msg = QPB_ALLOC(allocator, typeof(*msg)); - if (!msg) { - assert(0); - return NULL; - } - - fpm__add_route__init(msg); - - msg->vrf_id = zvrf_id(rib_dest_vrf(dest)); - - qpb_address_family_set (&msg->address_family, rib_dest_af(dest)); - - /* - * XXX Hardcode subaddress family for now. - */ - msg->sub_address_family = QPB__SUB_ADDRESS_FAMILY__UNICAST; - msg->key = fpm_route_key_create (allocator, rib_dest_prefix(dest)); - qpb_protocol_set (&msg->protocol, re->type); - - if ((re->flags & ZEBRA_FLAG_BLACKHOLE) || (re->flags & ZEBRA_FLAG_REJECT)) - discard = 1; - else - discard = 0; - - if (discard) - { - if (re->flags & ZEBRA_FLAG_BLACKHOLE) { - msg->route_type = FPM__ROUTE_TYPE__BLACKHOLE; - } else if (re->flags & ZEBRA_FLAG_REJECT) { - msg->route_type = FPM__ROUTE_TYPE__UNREACHABLE; - } else { - assert (0); - } - return msg; - } - else { - msg->route_type = FPM__ROUTE_TYPE__NORMAL; - } - - msg->metric = re->metric; - - /* - * Figure out the set of nexthops to be added to the message. - */ - num_nhs = 0; - for (ALL_NEXTHOPS (re->nexthop, nexthop)) - { - if (num_nhs >= multipath_num) - break; - - if (num_nhs >= ZEBRA_NUM_OF(nexthops)) - break; - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; - - if (!CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - continue; - - nexthops[num_nhs] = nexthop; - num_nhs++; - } - - if (!num_nhs) { - zfpm_debug ("netlink_encode_route(): No useful nexthop."); - assert(0); - return NULL; - } - - /* - * And add them to the message. - */ - if (!(msg->nexthops = qpb_alloc_ptr_array(allocator, num_nhs))) { - assert(0); - return NULL; - } - - msg->n_nexthops = 0; - for (u = 0; u < num_nhs; u++) { - if (!add_nexthop(allocator, msg, dest, nexthops[u])) { - assert(0); - return NULL; - } - } - - assert(msg->n_nexthops == num_nhs); - - return msg; + Fpm__AddRoute *msg; + int discard; + struct nexthop *nexthop; + uint num_nhs, u; + struct nexthop *nexthops[MULTIPATH_NUM]; + + msg = QPB_ALLOC(allocator, typeof(*msg)); + if (!msg) { + assert(0); + return NULL; + } + + fpm__add_route__init(msg); + + msg->vrf_id = zvrf_id(rib_dest_vrf(dest)); + + qpb_address_family_set(&msg->address_family, rib_dest_af(dest)); + + /* + * XXX Hardcode subaddress family for now. + */ + msg->sub_address_family = QPB__SUB_ADDRESS_FAMILY__UNICAST; + msg->key = fpm_route_key_create(allocator, rib_dest_prefix(dest)); + qpb_protocol_set(&msg->protocol, re->type); + + if ((re->flags & ZEBRA_FLAG_BLACKHOLE) + || (re->flags & ZEBRA_FLAG_REJECT)) + discard = 1; + else + discard = 0; + + if (discard) { + if (re->flags & ZEBRA_FLAG_BLACKHOLE) { + msg->route_type = FPM__ROUTE_TYPE__BLACKHOLE; + } else if (re->flags & ZEBRA_FLAG_REJECT) { + msg->route_type = FPM__ROUTE_TYPE__UNREACHABLE; + } else { + assert(0); + } + return msg; + } else { + msg->route_type = FPM__ROUTE_TYPE__NORMAL; + } + + msg->metric = re->metric; + + /* + * Figure out the set of nexthops to be added to the message. + */ + num_nhs = 0; + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + if (num_nhs >= multipath_num) + break; + + if (num_nhs >= ZEBRA_NUM_OF(nexthops)) + break; + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + continue; + + if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + continue; + + nexthops[num_nhs] = nexthop; + num_nhs++; + } + + if (!num_nhs) { + zfpm_debug("netlink_encode_route(): No useful nexthop."); + assert(0); + return NULL; + } + + /* + * And add them to the message. + */ + if (!(msg->nexthops = qpb_alloc_ptr_array(allocator, num_nhs))) { + assert(0); + return NULL; + } + + msg->n_nexthops = 0; + for (u = 0; u < num_nhs; u++) { + if (!add_nexthop(allocator, msg, dest, nexthops[u])) { + assert(0); + return NULL; + } + } + + assert(msg->n_nexthops == num_nhs); + + return msg; } /* * create_route_message */ -static Fpm__Message * -create_route_message (qpb_allocator_t *allocator, rib_dest_t *dest, - struct route_entry *re) +static Fpm__Message *create_route_message(qpb_allocator_t *allocator, + rib_dest_t *dest, + struct route_entry *re) { - Fpm__Message *msg; - - msg = QPB_ALLOC(allocator, typeof(*msg)); - if (!msg) { - assert(0); - return NULL; - } - - fpm__message__init(msg); - - if (!re) { - msg->type = FPM__MESSAGE__TYPE__DELETE_ROUTE; - msg->delete_route = create_delete_route_message(allocator, dest, re); - if (!msg->delete_route) { - assert(0); - return NULL; - } - return msg; - } - - msg->type = FPM__MESSAGE__TYPE__ADD_ROUTE; - msg->add_route = create_add_route_message(allocator, dest, re); - if (!msg->add_route) { - assert(0); - return NULL; - } - - return msg; + Fpm__Message *msg; + + msg = QPB_ALLOC(allocator, typeof(*msg)); + if (!msg) { + assert(0); + return NULL; + } + + fpm__message__init(msg); + + if (!re) { + msg->type = FPM__MESSAGE__TYPE__DELETE_ROUTE; + msg->delete_route = + create_delete_route_message(allocator, dest, re); + if (!msg->delete_route) { + assert(0); + return NULL; + } + return msg; + } + + msg->type = FPM__MESSAGE__TYPE__ADD_ROUTE; + msg->add_route = create_add_route_message(allocator, dest, re); + if (!msg->add_route) { + assert(0); + return NULL; + } + + return msg; } /* @@ -285,25 +281,24 @@ create_route_message (qpb_allocator_t *allocator, rib_dest_t *dest, * Returns the number of bytes written to the buffer. 0 or a negative * value indicates an error. */ -int -zfpm_protobuf_encode_route (rib_dest_t *dest, struct route_entry *re, - uint8_t *in_buf, size_t in_buf_len) +int zfpm_protobuf_encode_route(rib_dest_t *dest, struct route_entry *re, + uint8_t *in_buf, size_t in_buf_len) { - Fpm__Message *msg; - QPB_DECLARE_STACK_ALLOCATOR (allocator, 4096); - size_t len; + Fpm__Message *msg; + QPB_DECLARE_STACK_ALLOCATOR(allocator, 4096); + size_t len; - QPB_INIT_STACK_ALLOCATOR (allocator); + QPB_INIT_STACK_ALLOCATOR(allocator); - msg = create_route_message(&allocator, dest, re); - if (!msg) { - assert(0); - return 0; - } + msg = create_route_message(&allocator, dest, re); + if (!msg) { + assert(0); + return 0; + } - len = fpm__message__pack(msg, (uint8_t *) in_buf); - assert(len <= in_buf_len); + len = fpm__message__pack(msg, (uint8_t *)in_buf); + assert(len <= in_buf_len); - QPB_RESET_STACK_ALLOCATOR (allocator); - return len; + QPB_RESET_STACK_ALLOCATOR(allocator); + return len; } diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c index b71b96a18..5d059a450 100644 --- a/zebra/zebra_l2.c +++ b/zebra/zebra_l2.c @@ -49,111 +49,101 @@ /* static function declarations */ /* Private functions */ -static void -map_slaves_to_bridge (struct interface *br_if, int link) +static void map_slaves_to_bridge(struct interface *br_if, int link) { - struct vrf *vrf; - struct listnode *node; - struct interface *ifp; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp)) - { - struct zebra_if *zif; - struct zebra_l2info_brslave *br_slave; - - if (ifp->ifindex == IFINDEX_INTERNAL || - !ifp->info) - continue; - if (!IS_ZEBRA_IF_BRIDGE_SLAVE (ifp)) - continue; - - /* NOTE: This assumes 'zebra_l2info_brslave' is the first field - * for any L2 interface. - */ - zif = (struct zebra_if *) ifp->info; - br_slave = &zif->brslave_info; - - if (link) - { - if (br_slave->bridge_ifindex == br_if->ifindex) - br_slave->br_if = br_if; - } - else - { - if (br_slave->br_if == br_if) - br_slave->br_if = NULL; - } - } - } + struct vrf *vrf; + struct listnode *node; + struct interface *ifp; + + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + for (ALL_LIST_ELEMENTS_RO(vrf->iflist, node, ifp)) { + struct zebra_if *zif; + struct zebra_l2info_brslave *br_slave; + + if (ifp->ifindex == IFINDEX_INTERNAL || !ifp->info) + continue; + if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) + continue; + + /* NOTE: This assumes 'zebra_l2info_brslave' is the + * first field + * for any L2 interface. + */ + zif = (struct zebra_if *)ifp->info; + br_slave = &zif->brslave_info; + + if (link) { + if (br_slave->bridge_ifindex == br_if->ifindex) + br_slave->br_if = br_if; + } else { + if (br_slave->br_if == br_if) + br_slave->br_if = NULL; + } + } + } } /* Public functions */ -void -zebra_l2_map_slave_to_bridge (struct zebra_l2info_brslave *br_slave) +void zebra_l2_map_slave_to_bridge(struct zebra_l2info_brslave *br_slave) { - struct interface *br_if; + struct interface *br_if; - /* TODO: Handle change of master */ - br_if = if_lookup_by_index_per_ns (zebra_ns_lookup (NS_DEFAULT), - br_slave->bridge_ifindex); - if (br_if) - br_slave->br_if = br_if; + /* TODO: Handle change of master */ + br_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), + br_slave->bridge_ifindex); + if (br_if) + br_slave->br_if = br_if; } -void -zebra_l2_unmap_slave_from_bridge (struct zebra_l2info_brslave *br_slave) +void zebra_l2_unmap_slave_from_bridge(struct zebra_l2info_brslave *br_slave) { - br_slave->br_if = NULL; + br_slave->br_if = NULL; } /* * Handle Bridge interface add or update. Update relevant info, * map slaves (if any) to the bridge. */ -void -zebra_l2_bridge_add_update (struct interface *ifp, - struct zebra_l2info_bridge *bridge_info, - int add) +void zebra_l2_bridge_add_update(struct interface *ifp, + struct zebra_l2info_bridge *bridge_info, + int add) { - struct zebra_if *zif; + struct zebra_if *zif; - zif = ifp->info; - assert(zif); + zif = ifp->info; + assert(zif); - /* Copy over the L2 information. */ - memcpy (&zif->l2info.br, bridge_info, sizeof (*bridge_info)); + /* Copy over the L2 information. */ + memcpy(&zif->l2info.br, bridge_info, sizeof(*bridge_info)); - /* Link all slaves to this bridge */ - map_slaves_to_bridge (ifp, 1); + /* Link all slaves to this bridge */ + map_slaves_to_bridge(ifp, 1); } /* * Handle Bridge interface delete. */ -void -zebra_l2_bridge_del (struct interface *ifp) +void zebra_l2_bridge_del(struct interface *ifp) { - /* Unlink all slaves to this bridge */ - map_slaves_to_bridge (ifp, 0); + /* Unlink all slaves to this bridge */ + map_slaves_to_bridge(ifp, 0); } /* * Update L2 info for a VLAN interface. Only relevant parameter is the * VLAN Id and this cannot change. */ -void -zebra_l2_vlanif_update (struct interface *ifp, - struct zebra_l2info_vlan *vlan_info) +void zebra_l2_vlanif_update(struct interface *ifp, + struct zebra_l2info_vlan *vlan_info) { - struct zebra_if *zif; + struct zebra_if *zif; - zif = ifp->info; - assert(zif); + zif = ifp->info; + assert(zif); - /* Copy over the L2 information. */ - memcpy (&zif->l2info.vl, vlan_info, sizeof (*vlan_info)); + /* Copy over the L2 information. */ + memcpy(&zif->l2info.vl, vlan_info, sizeof(*vlan_info)); } /* @@ -162,60 +152,55 @@ zebra_l2_vlanif_update (struct interface *ifp, * function. Upon update, the params of interest are the local tunnel * IP and VLAN mapping, but the latter is handled separately. */ -void -zebra_l2_vxlanif_add_update (struct interface *ifp, - struct zebra_l2info_vxlan *vxlan_info, - int add) +void zebra_l2_vxlanif_add_update(struct interface *ifp, + struct zebra_l2info_vxlan *vxlan_info, int add) { - struct zebra_if *zif; - struct in_addr old_vtep_ip; + struct zebra_if *zif; + struct in_addr old_vtep_ip; - zif = ifp->info; - assert(zif); + zif = ifp->info; + assert(zif); - if (add) - { - memcpy (&zif->l2info.vxl, vxlan_info, sizeof (*vxlan_info)); - zebra_vxlan_if_add (ifp); - return; - } + if (add) { + memcpy(&zif->l2info.vxl, vxlan_info, sizeof(*vxlan_info)); + zebra_vxlan_if_add(ifp); + return; + } - old_vtep_ip = zif->l2info.vxl.vtep_ip; - if (IPV4_ADDR_SAME(&old_vtep_ip, &vxlan_info->vtep_ip)) - return; + old_vtep_ip = zif->l2info.vxl.vtep_ip; + if (IPV4_ADDR_SAME(&old_vtep_ip, &vxlan_info->vtep_ip)) + return; - zif->l2info.vxl.vtep_ip = vxlan_info->vtep_ip; - zebra_vxlan_if_update (ifp, ZEBRA_VXLIF_LOCAL_IP_CHANGE); + zif->l2info.vxl.vtep_ip = vxlan_info->vtep_ip; + zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_LOCAL_IP_CHANGE); } /* * Handle change to VLAN to VNI mapping. */ -void -zebra_l2_vxlanif_update_access_vlan (struct interface *ifp, - vlanid_t access_vlan) +void zebra_l2_vxlanif_update_access_vlan(struct interface *ifp, + vlanid_t access_vlan) { - struct zebra_if *zif; - vlanid_t old_access_vlan; + struct zebra_if *zif; + vlanid_t old_access_vlan; - zif = ifp->info; - assert(zif); + zif = ifp->info; + assert(zif); - old_access_vlan = zif->l2info.vxl.access_vlan; - if (old_access_vlan == access_vlan) - return; + old_access_vlan = zif->l2info.vxl.access_vlan; + if (old_access_vlan == access_vlan) + return; - zif->l2info.vxl.access_vlan = access_vlan; - zebra_vxlan_if_update (ifp, ZEBRA_VXLIF_VLAN_CHANGE); + zif->l2info.vxl.access_vlan = access_vlan; + zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_VLAN_CHANGE); } /* * Handle VxLAN interface delete. */ -void -zebra_l2_vxlanif_del (struct interface *ifp) +void zebra_l2_vxlanif_del(struct interface *ifp) { - zebra_vxlan_if_del (ifp); + zebra_vxlan_if_del(ifp); } /* @@ -223,29 +208,28 @@ zebra_l2_vxlanif_del (struct interface *ifp) * NOTE: It is currently assumped that an interface has to be unmapped * from a bridge before it can be mapped to another bridge. */ -void -zebra_l2if_update_bridge_slave (struct interface *ifp, - ifindex_t bridge_ifindex) +void zebra_l2if_update_bridge_slave(struct interface *ifp, + ifindex_t bridge_ifindex) { - struct zebra_if *zif; - ifindex_t old_bridge_ifindex; + struct zebra_if *zif; + ifindex_t old_bridge_ifindex; - zif = ifp->info; - assert(zif); + zif = ifp->info; + assert(zif); - old_bridge_ifindex = zif->brslave_info.bridge_ifindex; - if (old_bridge_ifindex == bridge_ifindex) - return; + old_bridge_ifindex = zif->brslave_info.bridge_ifindex; + if (old_bridge_ifindex == bridge_ifindex) + return; - zif->brslave_info.bridge_ifindex = bridge_ifindex; + zif->brslave_info.bridge_ifindex = bridge_ifindex; - /* Set up or remove link with master */ - if (bridge_ifindex != IFINDEX_INTERNAL) - zebra_l2_map_slave_to_bridge (&zif->brslave_info); - else if (old_bridge_ifindex != IFINDEX_INTERNAL) - zebra_l2_unmap_slave_from_bridge (&zif->brslave_info); + /* Set up or remove link with master */ + if (bridge_ifindex != IFINDEX_INTERNAL) + zebra_l2_map_slave_to_bridge(&zif->brslave_info); + else if (old_bridge_ifindex != IFINDEX_INTERNAL) + zebra_l2_unmap_slave_from_bridge(&zif->brslave_info); - /* In the case of VxLAN, invoke the handler for EVPN. */ - if (zif->zif_type == ZEBRA_IF_VXLAN) - zebra_vxlan_if_update (ifp, ZEBRA_VXLIF_MASTER_CHANGE); + /* In the case of VxLAN, invoke the handler for EVPN. */ + if (zif->zif_type == ZEBRA_IF_VXLAN) + zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_MASTER_CHANGE); } diff --git a/zebra/zebra_l2.h b/zebra/zebra_l2.h index 5cfc6dee4..d9bbcfed6 100644 --- a/zebra/zebra_l2.h +++ b/zebra/zebra_l2.h @@ -30,37 +30,32 @@ #include "vxlan.h" /* zebra L2 interface information - bridge slave (linkage to bridge) */ -struct zebra_l2info_brslave -{ - ifindex_t bridge_ifindex; /* Bridge Master */ - struct interface *br_if; /* Pointer to master */ +struct zebra_l2info_brslave { + ifindex_t bridge_ifindex; /* Bridge Master */ + struct interface *br_if; /* Pointer to master */ }; /* zebra L2 interface information - bridge interface */ -struct zebra_l2info_bridge -{ - u_char vlan_aware; /* VLAN-aware bridge? */ +struct zebra_l2info_bridge { + u_char vlan_aware; /* VLAN-aware bridge? */ }; /* zebra L2 interface information - VLAN interface */ -struct zebra_l2info_vlan -{ - vlanid_t vid; /* VLAN id */ +struct zebra_l2info_vlan { + vlanid_t vid; /* VLAN id */ }; /* zebra L2 interface information - VXLAN interface */ -struct zebra_l2info_vxlan -{ - vni_t vni; /* VNI */ - struct in_addr vtep_ip; /* Local tunnel IP */ - vlanid_t access_vlan; /* Access VLAN - for VLAN-aware bridge. */ +struct zebra_l2info_vxlan { + vni_t vni; /* VNI */ + struct in_addr vtep_ip; /* Local tunnel IP */ + vlanid_t access_vlan; /* Access VLAN - for VLAN-aware bridge. */ }; -union zebra_l2if_info -{ - struct zebra_l2info_bridge br; - struct zebra_l2info_vlan vl; - struct zebra_l2info_vxlan vxl; +union zebra_l2if_info { + struct zebra_l2info_bridge br; + struct zebra_l2info_vlan vl; + struct zebra_l2info_vxlan vxl; }; /* NOTE: These macros are to be invoked only in the "correct" context. @@ -70,25 +65,25 @@ union zebra_l2if_info #define VNI_FROM_ZEBRA_IF(zif) (zif)->l2info.vxl.vni #define VLAN_ID_FROM_ZEBRA_IF(zif) (zif)->l2info.vl.vid -#define IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(zif) \ - ((zif)->l2info.br.vlan_aware == 1) +#define IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(zif) ((zif)->l2info.br.vlan_aware == 1) -extern void zebra_l2_map_slave_to_bridge (struct zebra_l2info_brslave *br_slave); -extern void zebra_l2_unmap_slave_from_bridge (struct zebra_l2info_brslave *br_slave); -extern void zebra_l2_bridge_add_update (struct interface *ifp, - struct zebra_l2info_bridge *bridge_info, - int add); -extern void zebra_l2_bridge_del (struct interface *ifp); -extern void zebra_l2_vlanif_update (struct interface *ifp, - struct zebra_l2info_vlan *vlan_info); -extern void zebra_l2_vxlanif_add_update (struct interface *ifp, - struct zebra_l2info_vxlan *vxlan_info, - int add); -extern void zebra_l2_vxlanif_update_access_vlan (struct interface *ifp, - vlanid_t access_vlan); -extern void zebra_l2_vxlanif_del (struct interface *ifp); -extern void zebra_l2if_update_bridge_slave (struct interface *ifp, - ifindex_t bridge_ifindex); +extern void zebra_l2_map_slave_to_bridge(struct zebra_l2info_brslave *br_slave); +extern void +zebra_l2_unmap_slave_from_bridge(struct zebra_l2info_brslave *br_slave); +extern void zebra_l2_bridge_add_update(struct interface *ifp, + struct zebra_l2info_bridge *bridge_info, + int add); +extern void zebra_l2_bridge_del(struct interface *ifp); +extern void zebra_l2_vlanif_update(struct interface *ifp, + struct zebra_l2info_vlan *vlan_info); +extern void zebra_l2_vxlanif_add_update(struct interface *ifp, + struct zebra_l2info_vxlan *vxlan_info, + int add); +extern void zebra_l2_vxlanif_update_access_vlan(struct interface *ifp, + vlanid_t access_vlan); +extern void zebra_l2_vxlanif_del(struct interface *ifp); +extern void zebra_l2if_update_bridge_slave(struct interface *ifp, + ifindex_t bridge_ifindex); #endif /* _ZEBRA_L2_H */ diff --git a/zebra/zebra_l2_null.c b/zebra/zebra_l2_null.c index d50107f65..c063f77bd 100644 --- a/zebra/zebra_l2_null.c +++ b/zebra/zebra_l2_null.c @@ -29,48 +29,44 @@ #include "zebra/zebra_vrf.h" #include "zebra/zebra_l2.h" -void zebra_l2_map_slave_to_bridge (struct zebra_l2info_brslave *br_slave) +void zebra_l2_map_slave_to_bridge(struct zebra_l2info_brslave *br_slave) { } -void -zebra_l2_unmap_slave_from_bridge (struct zebra_l2info_brslave *br_slave) +void zebra_l2_unmap_slave_from_bridge(struct zebra_l2info_brslave *br_slave) { } -void zebra_l2_bridge_add_update (struct interface *ifp, - struct zebra_l2info_bridge *bridge_info, - int add) +void zebra_l2_bridge_add_update(struct interface *ifp, + struct zebra_l2info_bridge *bridge_info, + int add) { } -void zebra_l2_bridge_del (struct interface *ifp) +void zebra_l2_bridge_del(struct interface *ifp) { } -void zebra_l2_vlanif_update (struct interface *ifp, - struct zebra_l2info_vlan *vlan_info) +void zebra_l2_vlanif_update(struct interface *ifp, + struct zebra_l2info_vlan *vlan_info) { } -void zebra_l2_vxlanif_add_update (struct interface *ifp, - struct zebra_l2info_vxlan *vxlan_info, - int add) +void zebra_l2_vxlanif_add_update(struct interface *ifp, + struct zebra_l2info_vxlan *vxlan_info, int add) { } -void -zebra_l2_vxlanif_update_access_vlan (struct interface *ifp, - vlanid_t access_vlan) +void zebra_l2_vxlanif_update_access_vlan(struct interface *ifp, + vlanid_t access_vlan) { } -void zebra_l2_vxlanif_del (struct interface *ifp) +void zebra_l2_vxlanif_del(struct interface *ifp) { } -void -zebra_l2if_update_bridge_slave (struct interface *ifp, - ifindex_t bridge_ifindex) +void zebra_l2if_update_bridge_slave(struct interface *ifp, + ifindex_t bridge_ifindex) { } diff --git a/zebra/zebra_memory.c b/zebra/zebra_memory.c index b8e1a130e..ee041b1c3 100644 --- a/zebra/zebra_memory.c +++ b/zebra/zebra_memory.c @@ -26,11 +26,11 @@ #include "zebra_memory.h" DEFINE_MGROUP(ZEBRA, "zebra") -DEFINE_MTYPE(ZEBRA, RTADV_PREFIX, "Router Advertisement Prefix") -DEFINE_MTYPE(ZEBRA, ZEBRA_VRF, "ZEBRA VRF") -DEFINE_MTYPE(ZEBRA, RE, "Route Entry") -DEFINE_MTYPE(ZEBRA, RIB_QUEUE, "RIB process work queue") -DEFINE_MTYPE(ZEBRA, STATIC_ROUTE, "Static route") -DEFINE_MTYPE(ZEBRA, RIB_DEST, "RIB destination") +DEFINE_MTYPE(ZEBRA, RTADV_PREFIX, "Router Advertisement Prefix") +DEFINE_MTYPE(ZEBRA, ZEBRA_VRF, "ZEBRA VRF") +DEFINE_MTYPE(ZEBRA, RE, "Route Entry") +DEFINE_MTYPE(ZEBRA, RIB_QUEUE, "RIB process work queue") +DEFINE_MTYPE(ZEBRA, STATIC_ROUTE, "Static route") +DEFINE_MTYPE(ZEBRA, RIB_DEST, "RIB destination") DEFINE_MTYPE(ZEBRA, RIB_TABLE_INFO, "RIB table info") -DEFINE_MTYPE(ZEBRA, RNH, "Nexthop tracking object") +DEFINE_MTYPE(ZEBRA, RNH, "Nexthop tracking object") diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 3c8503878..e44e5d2e6 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -45,12 +45,12 @@ #include "zebra/zebra_vrf.h" #include "zebra/zebra_mpls.h" -DEFINE_MTYPE_STATIC(ZEBRA, LSP, "MPLS LSP object") -DEFINE_MTYPE_STATIC(ZEBRA, FEC, "MPLS FEC object") -DEFINE_MTYPE_STATIC(ZEBRA, SLSP, "MPLS static LSP config") -DEFINE_MTYPE_STATIC(ZEBRA, NHLFE, "MPLS nexthop object") -DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE, "MPLS static nexthop object") -DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE_IFNAME, "MPLS static nexthop ifname") +DEFINE_MTYPE_STATIC(ZEBRA, LSP, "MPLS LSP object") +DEFINE_MTYPE_STATIC(ZEBRA, FEC, "MPLS FEC object") +DEFINE_MTYPE_STATIC(ZEBRA, SLSP, "MPLS static LSP config") +DEFINE_MTYPE_STATIC(ZEBRA, NHLFE, "MPLS nexthop object") +DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE, "MPLS static nexthop object") +DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE_IFNAME, "MPLS static nexthop ifname") int mpls_enabled; @@ -59,106 +59,72 @@ extern struct zebra_t zebrad; /* static function declarations */ -static void -fec_evaluate (struct zebra_vrf *zvrf); -static u_int32_t -fec_derive_label_from_index (struct zebra_vrf *vrf, zebra_fec_t *fec); -static int -lsp_install (struct zebra_vrf *zvrf, mpls_label_t label, - struct route_node *rn, struct route_entry *re); -static int -lsp_uninstall (struct zebra_vrf *zvrf, mpls_label_t label); -static int -fec_change_update_lsp (struct zebra_vrf *zvrf, zebra_fec_t *fec, mpls_label_t old_label); -static int -fec_send (zebra_fec_t *fec, struct zserv *client); -static void -fec_update_clients (zebra_fec_t *fec); -static void -fec_print (zebra_fec_t *fec, struct vty *vty); -static zebra_fec_t * -fec_find (struct route_table *table, struct prefix *p); -static zebra_fec_t * -fec_add (struct route_table *table, struct prefix *p, mpls_label_t label, - u_int32_t flags, u_int32_t label_index); -static int -fec_del (zebra_fec_t *fec); - -static unsigned int -label_hash (void *p); -static int -label_cmp (const void *p1, const void *p2); -static int -nhlfe_nexthop_active_ipv4 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop); -static int -nhlfe_nexthop_active_ipv6 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop); -static int -nhlfe_nexthop_active (zebra_nhlfe_t *nhlfe); - -static void -lsp_select_best_nhlfe (zebra_lsp_t *lsp); -static void -lsp_uninstall_from_kernel (struct hash_backet *backet, void *ctxt); -static void -lsp_schedule (struct hash_backet *backet, void *ctxt); -static wq_item_status -lsp_process (struct work_queue *wq, void *data); -static void -lsp_processq_del (struct work_queue *wq, void *data); -static void -lsp_processq_complete (struct work_queue *wq); -static int -lsp_processq_add (zebra_lsp_t *lsp); -static void * -lsp_alloc (void *p); - -static char * -nhlfe2str (zebra_nhlfe_t *nhlfe, char *buf, int size); -static int -nhlfe_nhop_match (zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex); -static zebra_nhlfe_t * -nhlfe_find (zebra_lsp_t *lsp, enum lsp_types_t lsp_type, - enum nexthop_types_t gtype, union g_addr *gate, - ifindex_t ifindex); -static zebra_nhlfe_t * -nhlfe_add (zebra_lsp_t *lsp, enum lsp_types_t lsp_type, - enum nexthop_types_t gtype, union g_addr *gate, - ifindex_t ifindex, mpls_label_t out_label); -static int -nhlfe_del (zebra_nhlfe_t *snhlfe); -static void -nhlfe_out_label_update (zebra_nhlfe_t *nhlfe, struct nexthop_label *nh_label); -static int -mpls_lsp_uninstall_all (struct hash *lsp_table, zebra_lsp_t *lsp, - enum lsp_types_t type); -static int -mpls_static_lsp_uninstall_all (struct zebra_vrf *zvrf, mpls_label_t in_label); -static void -nhlfe_print (zebra_nhlfe_t *nhlfe, struct vty *vty); -static void -lsp_print (zebra_lsp_t *lsp, void *ctxt); -static void * -slsp_alloc (void *p); -static int -snhlfe_match (zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex); -static zebra_snhlfe_t * -snhlfe_find (zebra_slsp_t *slsp, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex); -static zebra_snhlfe_t * -snhlfe_add (zebra_slsp_t *slsp, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex, mpls_label_t out_label); -static int -snhlfe_del (zebra_snhlfe_t *snhlfe); -static int -snhlfe_del_all (zebra_slsp_t *slsp); -static char * -snhlfe2str (zebra_snhlfe_t *snhlfe, char *buf, int size); -static int -mpls_processq_init (struct zebra_t *zebra); - - +static void fec_evaluate(struct zebra_vrf *zvrf); +static u_int32_t fec_derive_label_from_index(struct zebra_vrf *vrf, + zebra_fec_t *fec); +static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label, + struct route_node *rn, struct route_entry *re); +static int lsp_uninstall(struct zebra_vrf *zvrf, mpls_label_t label); +static int fec_change_update_lsp(struct zebra_vrf *zvrf, zebra_fec_t *fec, + mpls_label_t old_label); +static int fec_send(zebra_fec_t *fec, struct zserv *client); +static void fec_update_clients(zebra_fec_t *fec); +static void fec_print(zebra_fec_t *fec, struct vty *vty); +static zebra_fec_t *fec_find(struct route_table *table, struct prefix *p); +static zebra_fec_t *fec_add(struct route_table *table, struct prefix *p, + mpls_label_t label, u_int32_t flags, + u_int32_t label_index); +static int fec_del(zebra_fec_t *fec); + +static unsigned int label_hash(void *p); +static int label_cmp(const void *p1, const void *p2); +static int nhlfe_nexthop_active_ipv4(zebra_nhlfe_t *nhlfe, + struct nexthop *nexthop); +static int nhlfe_nexthop_active_ipv6(zebra_nhlfe_t *nhlfe, + struct nexthop *nexthop); +static int nhlfe_nexthop_active(zebra_nhlfe_t *nhlfe); + +static void lsp_select_best_nhlfe(zebra_lsp_t *lsp); +static void lsp_uninstall_from_kernel(struct hash_backet *backet, void *ctxt); +static void lsp_schedule(struct hash_backet *backet, void *ctxt); +static wq_item_status lsp_process(struct work_queue *wq, void *data); +static void lsp_processq_del(struct work_queue *wq, void *data); +static void lsp_processq_complete(struct work_queue *wq); +static int lsp_processq_add(zebra_lsp_t *lsp); +static void *lsp_alloc(void *p); + +static char *nhlfe2str(zebra_nhlfe_t *nhlfe, char *buf, int size); +static int nhlfe_nhop_match(zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex); +static zebra_nhlfe_t *nhlfe_find(zebra_lsp_t *lsp, enum lsp_types_t lsp_type, + enum nexthop_types_t gtype, union g_addr *gate, + ifindex_t ifindex); +static zebra_nhlfe_t *nhlfe_add(zebra_lsp_t *lsp, enum lsp_types_t lsp_type, + enum nexthop_types_t gtype, union g_addr *gate, + ifindex_t ifindex, mpls_label_t out_label); +static int nhlfe_del(zebra_nhlfe_t *snhlfe); +static void nhlfe_out_label_update(zebra_nhlfe_t *nhlfe, + struct nexthop_label *nh_label); +static int mpls_lsp_uninstall_all(struct hash *lsp_table, zebra_lsp_t *lsp, + enum lsp_types_t type); +static int mpls_static_lsp_uninstall_all(struct zebra_vrf *zvrf, + mpls_label_t in_label); +static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty); +static void lsp_print(zebra_lsp_t *lsp, void *ctxt); +static void *slsp_alloc(void *p); +static int snhlfe_match(zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex); +static zebra_snhlfe_t *snhlfe_find(zebra_slsp_t *slsp, + enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex); +static zebra_snhlfe_t *snhlfe_add(zebra_slsp_t *slsp, + enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex, + mpls_label_t out_label); +static int snhlfe_del(zebra_snhlfe_t *snhlfe); +static int snhlfe_del_all(zebra_slsp_t *slsp); +static char *snhlfe2str(zebra_snhlfe_t *snhlfe, char *buf, int size); +static int mpls_processq_init(struct zebra_t *zebra); /* Static functions */ @@ -166,189 +132,175 @@ mpls_processq_init (struct zebra_t *zebra); /* * Install label forwarding entry based on labeled-route entry. */ -static int -lsp_install (struct zebra_vrf *zvrf, mpls_label_t label, - struct route_node *rn, struct route_entry *re) -{ - struct hash *lsp_table; - zebra_ile_t tmp_ile; - zebra_lsp_t *lsp; - zebra_nhlfe_t *nhlfe; - struct nexthop *nexthop; - enum lsp_types_t lsp_type; - char buf[BUFSIZ]; - int added, changed; - - /* Lookup table. */ - lsp_table = zvrf->lsp_table; - if (!lsp_table) - return -1; - - lsp_type = lsp_type_from_re_type (re->type); - added = changed = 0; - - /* Locate or allocate LSP entry. */ - tmp_ile.in_label = label; - lsp = hash_get (lsp_table, &tmp_ile, lsp_alloc); - if (!lsp) - return -1; - - /* For each active nexthop, create NHLFE. Note that we deliberately skip - * recursive nexthops right now, because intermediate hops won't understand - * the label advertised by the recursive nexthop (plus we don't have the - * logic yet to push multiple labels). - */ - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - { - /* Skip inactive and recursive entries. */ - if (!CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - continue; - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; - - nhlfe = nhlfe_find (lsp, lsp_type, nexthop->type, &nexthop->gate, - nexthop->ifindex); - if (nhlfe) - { - /* Clear deleted flag (in case it was set) */ - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED); - if (nexthop_labels_match (nhlfe->nexthop, nexthop)) - /* No change */ - continue; - - - if (IS_ZEBRA_DEBUG_MPLS) - { - nhlfe2str (nhlfe, buf, BUFSIZ); - zlog_debug ("LSP in-label %u type %d nexthop %s " - "out-label changed", - lsp->ile.in_label, lsp_type, buf); - } - - /* Update out label, trigger processing. */ - nhlfe_out_label_update (nhlfe, nexthop->nh_label); - SET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED); - changed++; - } - else - { - /* Add LSP entry to this nexthop */ - nhlfe = nhlfe_add (lsp, lsp_type, nexthop->type, - &nexthop->gate, nexthop->ifindex, - nexthop->nh_label->label[0]); - if (!nhlfe) - return -1; - - if (IS_ZEBRA_DEBUG_MPLS) - { - nhlfe2str (nhlfe, buf, BUFSIZ); - zlog_debug ("Add LSP in-label %u type %d nexthop %s " - "out-label %u", - lsp->ile.in_label, lsp_type, buf, - nexthop->nh_label->label[0]); - } - - lsp->addr_family = NHLFE_FAMILY (nhlfe); - - /* Mark NHLFE as changed. */ - SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); - added++; - } - } - - /* Queue LSP for processing if necessary. If no NHLFE got added (special - * case), delete the LSP entry; this case results in somewhat ugly logging. - */ - if (added || changed) - { - if (lsp_processq_add (lsp)) - return -1; - } - else if (!lsp->nhlfe_list && - !CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED)) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Free LSP in-label %u flags 0x%x", - lsp->ile.in_label, lsp->flags); - - lsp = hash_release(lsp_table, &lsp->ile); - if (lsp) - XFREE(MTYPE_LSP, lsp); - } - - return 0; +static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label, + struct route_node *rn, struct route_entry *re) +{ + struct hash *lsp_table; + zebra_ile_t tmp_ile; + zebra_lsp_t *lsp; + zebra_nhlfe_t *nhlfe; + struct nexthop *nexthop; + enum lsp_types_t lsp_type; + char buf[BUFSIZ]; + int added, changed; + + /* Lookup table. */ + lsp_table = zvrf->lsp_table; + if (!lsp_table) + return -1; + + lsp_type = lsp_type_from_re_type(re->type); + added = changed = 0; + + /* Locate or allocate LSP entry. */ + tmp_ile.in_label = label; + lsp = hash_get(lsp_table, &tmp_ile, lsp_alloc); + if (!lsp) + return -1; + + /* For each active nexthop, create NHLFE. Note that we deliberately skip + * recursive nexthops right now, because intermediate hops won't + * understand + * the label advertised by the recursive nexthop (plus we don't have the + * logic yet to push multiple labels). + */ + for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) { + /* Skip inactive and recursive entries. */ + if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + continue; + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + continue; + + nhlfe = nhlfe_find(lsp, lsp_type, nexthop->type, &nexthop->gate, + nexthop->ifindex); + if (nhlfe) { + /* Clear deleted flag (in case it was set) */ + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED); + if (nexthop_labels_match(nhlfe->nexthop, nexthop)) + /* No change */ + continue; + + + if (IS_ZEBRA_DEBUG_MPLS) { + nhlfe2str(nhlfe, buf, BUFSIZ); + zlog_debug( + "LSP in-label %u type %d nexthop %s " + "out-label changed", + lsp->ile.in_label, lsp_type, buf); + } + + /* Update out label, trigger processing. */ + nhlfe_out_label_update(nhlfe, nexthop->nh_label); + SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + changed++; + } else { + /* Add LSP entry to this nexthop */ + nhlfe = nhlfe_add(lsp, lsp_type, nexthop->type, + &nexthop->gate, nexthop->ifindex, + nexthop->nh_label->label[0]); + if (!nhlfe) + return -1; + + if (IS_ZEBRA_DEBUG_MPLS) { + nhlfe2str(nhlfe, buf, BUFSIZ); + zlog_debug( + "Add LSP in-label %u type %d nexthop %s " + "out-label %u", + lsp->ile.in_label, lsp_type, buf, + nexthop->nh_label->label[0]); + } + + lsp->addr_family = NHLFE_FAMILY(nhlfe); + + /* Mark NHLFE as changed. */ + SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + added++; + } + } + + /* Queue LSP for processing if necessary. If no NHLFE got added (special + * case), delete the LSP entry; this case results in somewhat ugly + * logging. + */ + if (added || changed) { + if (lsp_processq_add(lsp)) + return -1; + } else if (!lsp->nhlfe_list + && !CHECK_FLAG(lsp->flags, LSP_FLAG_SCHEDULED)) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Free LSP in-label %u flags 0x%x", + lsp->ile.in_label, lsp->flags); + + lsp = hash_release(lsp_table, &lsp->ile); + if (lsp) + XFREE(MTYPE_LSP, lsp); + } + + return 0; } /* * Uninstall all non-static NHLFEs of a label forwarding entry. If all * NHLFEs are removed, the entire entry is deleted. */ -static int -lsp_uninstall (struct zebra_vrf *zvrf, mpls_label_t label) -{ - struct hash *lsp_table; - zebra_ile_t tmp_ile; - zebra_lsp_t *lsp; - zebra_nhlfe_t *nhlfe, *nhlfe_next; - char buf[BUFSIZ]; - - /* Lookup table. */ - lsp_table = zvrf->lsp_table; - if (!lsp_table) - return -1; - - /* If entry is not present, exit. */ - tmp_ile.in_label = label; - lsp = hash_lookup (lsp_table, &tmp_ile); - if (!lsp || !lsp->nhlfe_list) - return 0; - - /* Mark NHLFEs for delete or directly delete, as appropriate. */ - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next) - { - nhlfe_next = nhlfe->next; - - /* Skip static NHLFEs */ - if (nhlfe->type == ZEBRA_LSP_STATIC) - continue; - - if (IS_ZEBRA_DEBUG_MPLS) - { - nhlfe2str (nhlfe, buf, BUFSIZ); - zlog_debug ("Del LSP in-label %u type %d nexthop %s flags 0x%x", - label, nhlfe->type, buf, nhlfe->flags); - } - - if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)) - { - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED); - SET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED); - } - else - { - nhlfe_del (nhlfe); - } - } - - /* Queue LSP for processing, if needed, else delete. */ - if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) - { - if (lsp_processq_add (lsp)) - return -1; - } - else if (!lsp->nhlfe_list && - !CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED)) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Del LSP in-label %u flags 0x%x", - lsp->ile.in_label, lsp->flags); - - lsp = hash_release(lsp_table, &lsp->ile); - if (lsp) - XFREE(MTYPE_LSP, lsp); - } - - return 0; +static int lsp_uninstall(struct zebra_vrf *zvrf, mpls_label_t label) +{ + struct hash *lsp_table; + zebra_ile_t tmp_ile; + zebra_lsp_t *lsp; + zebra_nhlfe_t *nhlfe, *nhlfe_next; + char buf[BUFSIZ]; + + /* Lookup table. */ + lsp_table = zvrf->lsp_table; + if (!lsp_table) + return -1; + + /* If entry is not present, exit. */ + tmp_ile.in_label = label; + lsp = hash_lookup(lsp_table, &tmp_ile); + if (!lsp || !lsp->nhlfe_list) + return 0; + + /* Mark NHLFEs for delete or directly delete, as appropriate. */ + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next) { + nhlfe_next = nhlfe->next; + + /* Skip static NHLFEs */ + if (nhlfe->type == ZEBRA_LSP_STATIC) + continue; + + if (IS_ZEBRA_DEBUG_MPLS) { + nhlfe2str(nhlfe, buf, BUFSIZ); + zlog_debug( + "Del LSP in-label %u type %d nexthop %s flags 0x%x", + label, nhlfe->type, buf, nhlfe->flags); + } + + if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)) { + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + SET_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED); + } else { + nhlfe_del(nhlfe); + } + } + + /* Queue LSP for processing, if needed, else delete. */ + if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) { + if (lsp_processq_add(lsp)) + return -1; + } else if (!lsp->nhlfe_list + && !CHECK_FLAG(lsp->flags, LSP_FLAG_SCHEDULED)) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Del LSP in-label %u flags 0x%x", + lsp->ile.in_label, lsp->flags); + + lsp = hash_release(lsp_table, &lsp->ile); + if (lsp) + XFREE(MTYPE_LSP, lsp); + } + + return 0; } /* @@ -356,54 +308,55 @@ lsp_uninstall (struct zebra_vrf *zvrf, mpls_label_t label) * will walk all registered FECs with label-index and appropriately update * their local labels and trigger client updates. */ -static void -fec_evaluate (struct zebra_vrf *zvrf) -{ - struct route_node *rn; - zebra_fec_t *fec; - u_int32_t old_label, new_label; - int af; - char buf[BUFSIZ]; - - for (af = AFI_IP; af < AFI_MAX; af++) - { - if (zvrf->fec_table[af] == NULL) - continue; - - for (rn = route_top(zvrf->fec_table[af]); rn; rn = route_next(rn)) - { - if ((fec = rn->info) == NULL) - continue; - - /* Skip configured FECs and those without a label index. */ - if (fec->flags & FEC_FLAG_CONFIGURED || - fec->label_index == MPLS_INVALID_LABEL_INDEX) - continue; - - if (IS_ZEBRA_DEBUG_MPLS) - prefix2str(&rn->p, buf, BUFSIZ); - - /* Save old label, determine new label. */ - old_label = fec->label; - new_label = zvrf->mpls_srgb.start_label + fec->label_index; - if (new_label >= zvrf->mpls_srgb.end_label) - new_label = MPLS_INVALID_LABEL; - - /* If label has changed, update FEC and clients. */ - if (new_label == old_label) - continue; - - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Update fec %s new label %u upon label block", - buf, new_label); - - fec->label = new_label; - fec_update_clients (fec); - - /* Update label forwarding entries appropriately */ - fec_change_update_lsp (zvrf, fec, old_label); - } - } +static void fec_evaluate(struct zebra_vrf *zvrf) +{ + struct route_node *rn; + zebra_fec_t *fec; + u_int32_t old_label, new_label; + int af; + char buf[BUFSIZ]; + + for (af = AFI_IP; af < AFI_MAX; af++) { + if (zvrf->fec_table[af] == NULL) + continue; + + for (rn = route_top(zvrf->fec_table[af]); rn; + rn = route_next(rn)) { + if ((fec = rn->info) == NULL) + continue; + + /* Skip configured FECs and those without a label index. + */ + if (fec->flags & FEC_FLAG_CONFIGURED + || fec->label_index == MPLS_INVALID_LABEL_INDEX) + continue; + + if (IS_ZEBRA_DEBUG_MPLS) + prefix2str(&rn->p, buf, BUFSIZ); + + /* Save old label, determine new label. */ + old_label = fec->label; + new_label = + zvrf->mpls_srgb.start_label + fec->label_index; + if (new_label >= zvrf->mpls_srgb.end_label) + new_label = MPLS_INVALID_LABEL; + + /* If label has changed, update FEC and clients. */ + if (new_label == old_label) + continue; + + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug( + "Update fec %s new label %u upon label block", + buf, new_label); + + fec->label = new_label; + fec_update_clients(fec); + + /* Update label forwarding entries appropriately */ + fec_change_update_lsp(zvrf, fec, old_label); + } + } } /* @@ -411,195 +364,188 @@ fec_evaluate (struct zebra_vrf *zvrf) * its label index. The index is "acceptable" if it falls within the * globally configured label block (SRGB). */ -static u_int32_t -fec_derive_label_from_index (struct zebra_vrf *zvrf, zebra_fec_t *fec) +static u_int32_t fec_derive_label_from_index(struct zebra_vrf *zvrf, + zebra_fec_t *fec) { - u_int32_t label; + u_int32_t label; - if (fec->label_index != MPLS_INVALID_LABEL_INDEX && - zvrf->mpls_srgb.start_label && - ((label = zvrf->mpls_srgb.start_label + fec->label_index) < - zvrf->mpls_srgb.end_label)) - fec->label = label; - else - fec->label = MPLS_INVALID_LABEL; + if (fec->label_index != MPLS_INVALID_LABEL_INDEX + && zvrf->mpls_srgb.start_label + && ((label = zvrf->mpls_srgb.start_label + fec->label_index) + < zvrf->mpls_srgb.end_label)) + fec->label = label; + else + fec->label = MPLS_INVALID_LABEL; - return fec->label; + return fec->label; } /* * There is a change for this FEC. Install or uninstall label forwarding * entries, as appropriate. */ -static int -fec_change_update_lsp (struct zebra_vrf *zvrf, zebra_fec_t *fec, mpls_label_t old_label) +static int fec_change_update_lsp(struct zebra_vrf *zvrf, zebra_fec_t *fec, + mpls_label_t old_label) { - struct route_table *table; - struct route_node *rn; - struct route_entry *re; - afi_t afi; + struct route_table *table; + struct route_node *rn; + struct route_entry *re; + afi_t afi; - /* Uninstall label forwarding entry, if previously installed. */ - if (old_label != MPLS_INVALID_LABEL && - old_label != MPLS_IMP_NULL_LABEL) - lsp_uninstall (zvrf, old_label); + /* Uninstall label forwarding entry, if previously installed. */ + if (old_label != MPLS_INVALID_LABEL && old_label != MPLS_IMP_NULL_LABEL) + lsp_uninstall(zvrf, old_label); - /* Install label forwarding entry corr. to new label, if needed. */ - if (fec->label == MPLS_INVALID_LABEL || - fec->label == MPLS_IMP_NULL_LABEL) - return 0; + /* Install label forwarding entry corr. to new label, if needed. */ + if (fec->label == MPLS_INVALID_LABEL + || fec->label == MPLS_IMP_NULL_LABEL) + return 0; - afi = family2afi(PREFIX_FAMILY(&fec->rn->p)); - table = zebra_vrf_table (afi, SAFI_UNICAST, zvrf_id (zvrf)); - if (!table) - return 0; + afi = family2afi(PREFIX_FAMILY(&fec->rn->p)); + table = zebra_vrf_table(afi, SAFI_UNICAST, zvrf_id(zvrf)); + if (!table) + return 0; - /* See if labeled route exists. */ - rn = route_node_lookup (table, &fec->rn->p); - if (!rn) - return 0; + /* See if labeled route exists. */ + rn = route_node_lookup(table, &fec->rn->p); + if (!rn) + return 0; - RNODE_FOREACH_RE (rn, re) - { - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_SELECTED)) - break; - } + RNODE_FOREACH_RE(rn, re) + { + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) + break; + } - if (!re || !zebra_rib_labeled_unicast (re)) - return 0; + if (!re || !zebra_rib_labeled_unicast(re)) + return 0; - if (lsp_install (zvrf, fec->label, rn, re)) - return -1; + if (lsp_install(zvrf, fec->label, rn, re)) + return -1; - return 0; + return 0; } /* * Inform about FEC to a registered client. */ -static int -fec_send (zebra_fec_t *fec, struct zserv *client) +static int fec_send(zebra_fec_t *fec, struct zserv *client) { - struct stream *s; - struct route_node *rn; + struct stream *s; + struct route_node *rn; - rn = fec->rn; + rn = fec->rn; - /* Get output stream. */ - s = client->obuf; - stream_reset (s); + /* Get output stream. */ + s = client->obuf; + stream_reset(s); - zserv_create_header (s, ZEBRA_FEC_UPDATE, VRF_DEFAULT); + zserv_create_header(s, ZEBRA_FEC_UPDATE, VRF_DEFAULT); - stream_putw(s, rn->p.family); - stream_put_prefix (s, &rn->p); - stream_putl(s, fec->label); - stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message(client); + stream_putw(s, rn->p.family); + stream_put_prefix(s, &rn->p); + stream_putl(s, fec->label); + stream_putw_at(s, 0, stream_get_endp(s)); + return zebra_server_send_message(client); } /* * Update all registered clients about this FEC. Caller should've updated * FEC and ensure no duplicate updates. */ -static void -fec_update_clients (zebra_fec_t *fec) +static void fec_update_clients(zebra_fec_t *fec) { - struct listnode *node; - struct zserv *client; + struct listnode *node; + struct zserv *client; - for (ALL_LIST_ELEMENTS_RO(fec->client_list, node, client)) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Update client %s", zebra_route_string(client->proto)); - fec_send(fec, client); - } + for (ALL_LIST_ELEMENTS_RO(fec->client_list, node, client)) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Update client %s", + zebra_route_string(client->proto)); + fec_send(fec, client); + } } /* * Print a FEC-label binding entry. */ -static void -fec_print (zebra_fec_t *fec, struct vty *vty) -{ - struct route_node *rn; - struct listnode *node; - struct zserv *client; - char buf[BUFSIZ]; - - rn = fec->rn; - prefix2str(&rn->p, buf, BUFSIZ); - vty_out (vty, "%s\n", buf); - vty_out(vty, " Label: %s", label2str(fec->label, buf, BUFSIZ)); - if (fec->label_index != MPLS_INVALID_LABEL_INDEX) - vty_out(vty, ", Label Index: %u", fec->label_index); - vty_out (vty, "\n"); - if (!list_isempty(fec->client_list)) - { - vty_out(vty, " Client list:"); - for (ALL_LIST_ELEMENTS_RO(fec->client_list, node, client)) - vty_out(vty, " %s(fd %d)", - zebra_route_string(client->proto), client->sock); - vty_out (vty, "\n"); - } +static void fec_print(zebra_fec_t *fec, struct vty *vty) +{ + struct route_node *rn; + struct listnode *node; + struct zserv *client; + char buf[BUFSIZ]; + + rn = fec->rn; + prefix2str(&rn->p, buf, BUFSIZ); + vty_out(vty, "%s\n", buf); + vty_out(vty, " Label: %s", label2str(fec->label, buf, BUFSIZ)); + if (fec->label_index != MPLS_INVALID_LABEL_INDEX) + vty_out(vty, ", Label Index: %u", fec->label_index); + vty_out(vty, "\n"); + if (!list_isempty(fec->client_list)) { + vty_out(vty, " Client list:"); + for (ALL_LIST_ELEMENTS_RO(fec->client_list, node, client)) + vty_out(vty, " %s(fd %d)", + zebra_route_string(client->proto), + client->sock); + vty_out(vty, "\n"); + } } /* * Locate FEC-label binding that matches with passed info. */ -static zebra_fec_t * -fec_find (struct route_table *table, struct prefix *p) +static zebra_fec_t *fec_find(struct route_table *table, struct prefix *p) { - struct route_node *rn; + struct route_node *rn; - apply_mask (p); - rn = route_node_lookup(table, p); - if (!rn) - return NULL; + apply_mask(p); + rn = route_node_lookup(table, p); + if (!rn) + return NULL; - route_unlock_node(rn); - return (rn->info); + route_unlock_node(rn); + return (rn->info); } /* * Add a FEC. This may be upon a client registering for a binding * or when a binding is configured. */ -static zebra_fec_t * -fec_add (struct route_table *table, struct prefix *p, - mpls_label_t label, u_int32_t flags, u_int32_t label_index) +static zebra_fec_t *fec_add(struct route_table *table, struct prefix *p, + mpls_label_t label, u_int32_t flags, + u_int32_t label_index) { - struct route_node *rn; - zebra_fec_t *fec; + struct route_node *rn; + zebra_fec_t *fec; - apply_mask (p); + apply_mask(p); - /* Lookup (or add) route node.*/ - rn = route_node_get (table, p); - if (!rn) - return NULL; + /* Lookup (or add) route node.*/ + rn = route_node_get(table, p); + if (!rn) + return NULL; - fec = rn->info; + fec = rn->info; - if (!fec) - { - fec = XCALLOC (MTYPE_FEC, sizeof(zebra_fec_t)); - if (!fec) - return NULL; + if (!fec) { + fec = XCALLOC(MTYPE_FEC, sizeof(zebra_fec_t)); + if (!fec) + return NULL; - rn->info = fec; - fec->rn = rn; - fec->label = label; - fec->client_list = list_new(); - } - else - route_unlock_node (rn); /* for the route_node_get */ + rn->info = fec; + fec->rn = rn; + fec->label = label; + fec->client_list = list_new(); + } else + route_unlock_node(rn); /* for the route_node_get */ - fec->label_index = label_index; - fec->flags = flags; + fec->label_index = label_index; + fec->flags = flags; - return fec; + return fec; } /* @@ -607,37 +553,34 @@ fec_add (struct route_table *table, struct prefix *p, * a FEC and no binding exists or when the binding is deleted and there * are no registered clients. */ -static int -fec_del (zebra_fec_t *fec) +static int fec_del(zebra_fec_t *fec) { - list_free (fec->client_list); - fec->rn->info = NULL; - route_unlock_node (fec->rn); - XFREE (MTYPE_FEC, fec); - return 0; + list_free(fec->client_list); + fec->rn->info = NULL; + route_unlock_node(fec->rn); + XFREE(MTYPE_FEC, fec); + return 0; } /* * Hash function for label. */ -static unsigned int -label_hash (void *p) +static unsigned int label_hash(void *p) { - const zebra_ile_t *ile = p; + const zebra_ile_t *ile = p; - return (jhash_1word(ile->in_label, 0)); + return (jhash_1word(ile->in_label, 0)); } /* * Compare 2 LSP hash entries based on in-label. */ -static int -label_cmp (const void *p1, const void *p2) +static int label_cmp(const void *p1, const void *p2) { - const zebra_ile_t *ile1 = p1; - const zebra_ile_t *ile2 = p2; + const zebra_ile_t *ile1 = p1; + const zebra_ile_t *ile2 = p2; - return (ile1->in_label == ile2->in_label); + return (ile1->in_label == ile2->in_label); } /* @@ -645,50 +588,49 @@ label_cmp (const void *p1, const void *p2) * the passed flag. * NOTE: Looking only for connected routes right now. */ -static int -nhlfe_nexthop_active_ipv4 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop) +static int nhlfe_nexthop_active_ipv4(zebra_nhlfe_t *nhlfe, + struct nexthop *nexthop) { - struct route_table *table; - struct prefix_ipv4 p; - struct route_node *rn; - struct route_entry *match; - struct nexthop *match_nh; - - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); - if (!table) - return 0; + struct route_table *table; + struct prefix_ipv4 p; + struct route_node *rn; + struct route_entry *match; + struct nexthop *match_nh; - /* Lookup nexthop in IPv4 routing table. */ - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = IPV4_MAX_PREFIXLEN; - p.prefix = nexthop->gate.ipv4; + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + if (!table) + return 0; - rn = route_node_match (table, (struct prefix *) &p); - if (!rn) - return 0; + /* Lookup nexthop in IPv4 routing table. */ + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefixlen = IPV4_MAX_PREFIXLEN; + p.prefix = nexthop->gate.ipv4; - route_unlock_node (rn); + rn = route_node_match(table, (struct prefix *)&p); + if (!rn) + return 0; - /* Locate a valid connected route. */ - RNODE_FOREACH_RE (rn, match) - { - if (CHECK_FLAG (match->status, ROUTE_ENTRY_REMOVED) || - !CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) - continue; + route_unlock_node(rn); - for (match_nh = match->nexthop; match_nh; match_nh = match_nh->next) + /* Locate a valid connected route. */ + RNODE_FOREACH_RE(rn, match) { - if (match->type == ZEBRA_ROUTE_CONNECT || - nexthop->ifindex == match_nh->ifindex) - { - nexthop->ifindex = match_nh->ifindex; - return 1; - } + if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED) + || !CHECK_FLAG(match->flags, ZEBRA_FLAG_SELECTED)) + continue; + + for (match_nh = match->nexthop; match_nh; + match_nh = match_nh->next) { + if (match->type == ZEBRA_ROUTE_CONNECT + || nexthop->ifindex == match_nh->ifindex) { + nexthop->ifindex = match_nh->ifindex; + return 1; + } + } } - } - return 0; + return 0; } @@ -697,44 +639,44 @@ nhlfe_nexthop_active_ipv4 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop) * the passed flag. * NOTE: Looking only for connected routes right now. */ -static int -nhlfe_nexthop_active_ipv6 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop) +static int nhlfe_nexthop_active_ipv6(zebra_nhlfe_t *nhlfe, + struct nexthop *nexthop) { - struct route_table *table; - struct prefix_ipv6 p; - struct route_node *rn; - struct route_entry *match; + struct route_table *table; + struct prefix_ipv6 p; + struct route_node *rn; + struct route_entry *match; - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); - if (!table) - return 0; + table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT); + if (!table) + return 0; - /* Lookup nexthop in IPv6 routing table. */ - memset (&p, 0, sizeof (struct prefix_ipv6)); - p.family = AF_INET6; - p.prefixlen = IPV6_MAX_PREFIXLEN; - p.prefix = nexthop->gate.ipv6; + /* Lookup nexthop in IPv6 routing table. */ + memset(&p, 0, sizeof(struct prefix_ipv6)); + p.family = AF_INET6; + p.prefixlen = IPV6_MAX_PREFIXLEN; + p.prefix = nexthop->gate.ipv6; - rn = route_node_match (table, (struct prefix *) &p); - if (!rn) - return 0; + rn = route_node_match(table, (struct prefix *)&p); + if (!rn) + return 0; - route_unlock_node (rn); + route_unlock_node(rn); - /* Locate a valid connected route. */ - RNODE_FOREACH_RE (rn, match) - { - if ((match->type == ZEBRA_ROUTE_CONNECT) && - !CHECK_FLAG (match->status, ROUTE_ENTRY_REMOVED) && - CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) - break; - } + /* Locate a valid connected route. */ + RNODE_FOREACH_RE(rn, match) + { + if ((match->type == ZEBRA_ROUTE_CONNECT) + && !CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED) + && CHECK_FLAG(match->flags, ZEBRA_FLAG_SELECTED)) + break; + } - if (!match || !match->nexthop) - return 0; + if (!match || !match->nexthop) + return 0; - nexthop->ifindex = match->nexthop->ifindex; - return 1; + nexthop->ifindex = match->nexthop->ifindex; + return 1; } @@ -743,57 +685,52 @@ nhlfe_nexthop_active_ipv6 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop) * or not. * NOTE: Each NHLFE points to only 1 nexthop. */ -static int -nhlfe_nexthop_active (zebra_nhlfe_t *nhlfe) -{ - struct nexthop *nexthop; - struct interface *ifp; - - nexthop = nhlfe->nexthop; - if (!nexthop) // unexpected - return 0; - - /* Check on nexthop based on type. */ - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - if (nhlfe_nexthop_active_ipv4 (nhlfe, nexthop)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - break; - - case NEXTHOP_TYPE_IPV6: - if (nhlfe_nexthop_active_ipv6 (nhlfe, nexthop)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - break; - - case NEXTHOP_TYPE_IPV6_IFINDEX: - if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6)) - { - ifp = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT); - if (ifp && if_is_operative(ifp)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - } - else - { - if (nhlfe_nexthop_active_ipv6 (nhlfe, nexthop)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - } - break; - - default: - break; - } - - return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); +static int nhlfe_nexthop_active(zebra_nhlfe_t *nhlfe) +{ + struct nexthop *nexthop; + struct interface *ifp; + + nexthop = nhlfe->nexthop; + if (!nexthop) // unexpected + return 0; + + /* Check on nexthop based on type. */ + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + if (nhlfe_nexthop_active_ipv4(nhlfe, nexthop)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + break; + + case NEXTHOP_TYPE_IPV6: + if (nhlfe_nexthop_active_ipv6(nhlfe, nexthop)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + break; + + case NEXTHOP_TYPE_IPV6_IFINDEX: + if (IN6_IS_ADDR_LINKLOCAL(&nexthop->gate.ipv6)) { + ifp = if_lookup_by_index(nexthop->ifindex, VRF_DEFAULT); + if (ifp && if_is_operative(ifp)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + } else { + if (nhlfe_nexthop_active_ipv6(nhlfe, nexthop)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + } + break; + + default: + break; + } + + return CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); } /* @@ -802,783 +739,739 @@ nhlfe_nexthop_active (zebra_nhlfe_t *nhlfe) * marked. This is invoked when an LSP scheduled for processing (due * to some change) is examined. */ -static void -lsp_select_best_nhlfe (zebra_lsp_t *lsp) -{ - zebra_nhlfe_t *nhlfe; - zebra_nhlfe_t *best; - struct nexthop *nexthop; - int changed = 0; - - if (!lsp) - return; - - best = NULL; - lsp->num_ecmp = 0; - UNSET_FLAG (lsp->flags, LSP_FLAG_CHANGED); - - /* - * First compute the best path, after checking nexthop status. We are only - * concerned with non-deleted NHLFEs. - */ - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - /* Clear selection flags. */ - UNSET_FLAG (nhlfe->flags, - (NHLFE_FLAG_SELECTED | NHLFE_FLAG_MULTIPATH)); - - if (!CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED) && - nhlfe_nexthop_active (nhlfe)) - { - if (!best || (nhlfe->distance < best->distance)) - best = nhlfe; - } - } - - lsp->best_nhlfe = best; - if (!lsp->best_nhlfe) - return; - - /* Mark best NHLFE as selected. */ - SET_FLAG (lsp->best_nhlfe->flags, NHLFE_FLAG_SELECTED); - - /* - * If best path exists, see if there is ECMP. While doing this, note if a - * new (uninstalled) NHLFE has been selected, an installed entry that is - * still selected has a change or an installed entry is to be removed. - */ - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - int nh_chg, nh_sel, nh_inst; - - nexthop = nhlfe->nexthop; - if (!nexthop) // unexpected - continue; - - if (!CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) && - (nhlfe->distance == lsp->best_nhlfe->distance)) - { - SET_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED); - SET_FLAG (nhlfe->flags, NHLFE_FLAG_MULTIPATH); - lsp->num_ecmp++; - } - - if (CHECK_FLAG (lsp->flags, LSP_FLAG_INSTALLED) && - !changed) - { - nh_chg = CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED); - nh_sel = CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED); - nh_inst = CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); - - if ((nh_sel && !nh_inst) || - (nh_sel && nh_inst && nh_chg) || - (nh_inst && !nh_sel)) - changed = 1; - } - - /* We have finished examining, clear changed flag. */ - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED); - } - - if (changed) - SET_FLAG (lsp->flags, LSP_FLAG_CHANGED); +static void lsp_select_best_nhlfe(zebra_lsp_t *lsp) +{ + zebra_nhlfe_t *nhlfe; + zebra_nhlfe_t *best; + struct nexthop *nexthop; + int changed = 0; + + if (!lsp) + return; + + best = NULL; + lsp->num_ecmp = 0; + UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED); + + /* + * First compute the best path, after checking nexthop status. We are + * only + * concerned with non-deleted NHLFEs. + */ + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + /* Clear selection flags. */ + UNSET_FLAG(nhlfe->flags, + (NHLFE_FLAG_SELECTED | NHLFE_FLAG_MULTIPATH)); + + if (!CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED) + && nhlfe_nexthop_active(nhlfe)) { + if (!best || (nhlfe->distance < best->distance)) + best = nhlfe; + } + } + + lsp->best_nhlfe = best; + if (!lsp->best_nhlfe) + return; + + /* Mark best NHLFE as selected. */ + SET_FLAG(lsp->best_nhlfe->flags, NHLFE_FLAG_SELECTED); + + /* + * If best path exists, see if there is ECMP. While doing this, note if + * a + * new (uninstalled) NHLFE has been selected, an installed entry that is + * still selected has a change or an installed entry is to be removed. + */ + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + int nh_chg, nh_sel, nh_inst; + + nexthop = nhlfe->nexthop; + if (!nexthop) // unexpected + continue; + + if (!CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED) + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE) + && (nhlfe->distance == lsp->best_nhlfe->distance)) { + SET_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED); + SET_FLAG(nhlfe->flags, NHLFE_FLAG_MULTIPATH); + lsp->num_ecmp++; + } + + if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED) && !changed) { + nh_chg = CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + nh_sel = CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED); + nh_inst = + CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED); + + if ((nh_sel && !nh_inst) + || (nh_sel && nh_inst && nh_chg) + || (nh_inst && !nh_sel)) + changed = 1; + } + + /* We have finished examining, clear changed flag. */ + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + } + + if (changed) + SET_FLAG(lsp->flags, LSP_FLAG_CHANGED); } /* * Delete LSP forwarding entry from kernel, if installed. Called upon * process exit. */ -static void -lsp_uninstall_from_kernel (struct hash_backet *backet, void *ctxt) +static void lsp_uninstall_from_kernel(struct hash_backet *backet, void *ctxt) { - zebra_lsp_t *lsp; + zebra_lsp_t *lsp; - lsp = (zebra_lsp_t *) backet->data; - if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) - kernel_del_lsp (lsp); + lsp = (zebra_lsp_t *)backet->data; + if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) + kernel_del_lsp(lsp); } /* * Schedule LSP forwarding entry for processing. Called upon changes * that may impact LSPs such as nexthop / connected route changes. */ -static void -lsp_schedule (struct hash_backet *backet, void *ctxt) +static void lsp_schedule(struct hash_backet *backet, void *ctxt) { - zebra_lsp_t *lsp; + zebra_lsp_t *lsp; - lsp = (zebra_lsp_t *) backet->data; - lsp_processq_add (lsp); + lsp = (zebra_lsp_t *)backet->data; + lsp_processq_add(lsp); } /* * Process a LSP entry that is in the queue. Recalculate best NHLFE and * any multipaths and update or delete from the kernel, as needed. */ -static wq_item_status -lsp_process (struct work_queue *wq, void *data) -{ - zebra_lsp_t *lsp; - zebra_nhlfe_t *oldbest, *newbest; - char buf[BUFSIZ], buf2[BUFSIZ]; - struct zebra_vrf *zvrf = vrf_info_lookup (VRF_DEFAULT); - - lsp = (zebra_lsp_t *)data; - if (!lsp) // unexpected - return WQ_SUCCESS; - - oldbest = lsp->best_nhlfe; - - /* Select best NHLFE(s) */ - lsp_select_best_nhlfe (lsp); - - newbest = lsp->best_nhlfe; - - if (IS_ZEBRA_DEBUG_MPLS) - { - if (oldbest) - nhlfe2str (oldbest, buf, BUFSIZ); - if (newbest) - nhlfe2str (newbest, buf2, BUFSIZ); - zlog_debug ("Process LSP in-label %u oldbest %s newbest %s " - "flags 0x%x ecmp# %d", - lsp->ile.in_label, oldbest ? buf : "NULL", - newbest ? buf2 : "NULL", lsp->flags, lsp->num_ecmp); - } - - if (!CHECK_FLAG (lsp->flags, LSP_FLAG_INSTALLED)) - { - /* Not already installed */ - if (newbest) - { - kernel_add_lsp (lsp); - zvrf->lsp_installs++; - } - } - else - { - /* Installed, may need an update and/or delete. */ - if (!newbest) - { - kernel_del_lsp (lsp); - zvrf->lsp_removals++; - } - else if (CHECK_FLAG (lsp->flags, LSP_FLAG_CHANGED)) - { - kernel_upd_lsp (lsp); - zvrf->lsp_installs++; - } - } - - return WQ_SUCCESS; +static wq_item_status lsp_process(struct work_queue *wq, void *data) +{ + zebra_lsp_t *lsp; + zebra_nhlfe_t *oldbest, *newbest; + char buf[BUFSIZ], buf2[BUFSIZ]; + struct zebra_vrf *zvrf = vrf_info_lookup(VRF_DEFAULT); + + lsp = (zebra_lsp_t *)data; + if (!lsp) // unexpected + return WQ_SUCCESS; + + oldbest = lsp->best_nhlfe; + + /* Select best NHLFE(s) */ + lsp_select_best_nhlfe(lsp); + + newbest = lsp->best_nhlfe; + + if (IS_ZEBRA_DEBUG_MPLS) { + if (oldbest) + nhlfe2str(oldbest, buf, BUFSIZ); + if (newbest) + nhlfe2str(newbest, buf2, BUFSIZ); + zlog_debug( + "Process LSP in-label %u oldbest %s newbest %s " + "flags 0x%x ecmp# %d", + lsp->ile.in_label, oldbest ? buf : "NULL", + newbest ? buf2 : "NULL", lsp->flags, lsp->num_ecmp); + } + + if (!CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) { + /* Not already installed */ + if (newbest) { + kernel_add_lsp(lsp); + zvrf->lsp_installs++; + } + } else { + /* Installed, may need an update and/or delete. */ + if (!newbest) { + kernel_del_lsp(lsp); + zvrf->lsp_removals++; + } else if (CHECK_FLAG(lsp->flags, LSP_FLAG_CHANGED)) { + kernel_upd_lsp(lsp); + zvrf->lsp_installs++; + } + } + + return WQ_SUCCESS; } /* * Callback upon processing completion of a LSP forwarding entry. */ -static void -lsp_processq_del (struct work_queue *wq, void *data) +static void lsp_processq_del(struct work_queue *wq, void *data) { - struct zebra_vrf *zvrf; - zebra_lsp_t *lsp; - struct hash *lsp_table; - zebra_nhlfe_t *nhlfe, *nhlfe_next; + struct zebra_vrf *zvrf; + zebra_lsp_t *lsp; + struct hash *lsp_table; + zebra_nhlfe_t *nhlfe, *nhlfe_next; - zvrf = vrf_info_lookup(VRF_DEFAULT); - assert (zvrf); + zvrf = vrf_info_lookup(VRF_DEFAULT); + assert(zvrf); - lsp_table = zvrf->lsp_table; - if (!lsp_table) // unexpected - return; + lsp_table = zvrf->lsp_table; + if (!lsp_table) // unexpected + return; - lsp = (zebra_lsp_t *)data; - if (!lsp) // unexpected - return; + lsp = (zebra_lsp_t *)data; + if (!lsp) // unexpected + return; - /* Clear flag, remove any NHLFEs marked for deletion. If no NHLFEs exist, - * delete LSP entry also. - */ - UNSET_FLAG (lsp->flags, LSP_FLAG_SCHEDULED); + /* Clear flag, remove any NHLFEs marked for deletion. If no NHLFEs + * exist, + * delete LSP entry also. + */ + UNSET_FLAG(lsp->flags, LSP_FLAG_SCHEDULED); - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next) - { - nhlfe_next = nhlfe->next; - if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED)) - nhlfe_del (nhlfe); - } + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next) { + nhlfe_next = nhlfe->next; + if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED)) + nhlfe_del(nhlfe); + } - if (!lsp->nhlfe_list) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Free LSP in-label %u flags 0x%x", - lsp->ile.in_label, lsp->flags); + if (!lsp->nhlfe_list) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Free LSP in-label %u flags 0x%x", + lsp->ile.in_label, lsp->flags); - lsp = hash_release(lsp_table, &lsp->ile); - if (lsp) - XFREE(MTYPE_LSP, lsp); - } + lsp = hash_release(lsp_table, &lsp->ile); + if (lsp) + XFREE(MTYPE_LSP, lsp); + } } /* * Callback upon finishing the processing of all scheduled * LSP forwarding entries. */ -static void -lsp_processq_complete (struct work_queue *wq) +static void lsp_processq_complete(struct work_queue *wq) { - /* Nothing to do for now. */ + /* Nothing to do for now. */ } /* * Add LSP forwarding entry to queue for subsequent processing. */ -static int -lsp_processq_add (zebra_lsp_t *lsp) +static int lsp_processq_add(zebra_lsp_t *lsp) { - /* If already scheduled, exit. */ - if (CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED)) - return 0; + /* If already scheduled, exit. */ + if (CHECK_FLAG(lsp->flags, LSP_FLAG_SCHEDULED)) + return 0; - if (zebrad.lsp_process_q == NULL) - { - zlog_err ("%s: work_queue does not exist!", __func__); - return -1; - } + if (zebrad.lsp_process_q == NULL) { + zlog_err("%s: work_queue does not exist!", __func__); + return -1; + } - work_queue_add (zebrad.lsp_process_q, lsp); - SET_FLAG (lsp->flags, LSP_FLAG_SCHEDULED); - return 0; + work_queue_add(zebrad.lsp_process_q, lsp); + SET_FLAG(lsp->flags, LSP_FLAG_SCHEDULED); + return 0; } /* * Callback to allocate LSP forwarding table entry. */ -static void * -lsp_alloc (void *p) +static void *lsp_alloc(void *p) { - const zebra_ile_t *ile = p; - zebra_lsp_t *lsp; + const zebra_ile_t *ile = p; + zebra_lsp_t *lsp; - lsp = XCALLOC (MTYPE_LSP, sizeof(zebra_lsp_t)); - lsp->ile = *ile; + lsp = XCALLOC(MTYPE_LSP, sizeof(zebra_lsp_t)); + lsp->ile = *ile; - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Alloc LSP in-label %u", lsp->ile.in_label); + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Alloc LSP in-label %u", lsp->ile.in_label); - return ((void *)lsp); + return ((void *)lsp); } /* * Create printable string for NHLFE entry. */ -static char * -nhlfe2str (zebra_nhlfe_t *nhlfe, char *buf, int size) +static char *nhlfe2str(zebra_nhlfe_t *nhlfe, char *buf, int size) { - struct nexthop *nexthop; + struct nexthop *nexthop; - buf[0] = '\0'; - nexthop = nhlfe->nexthop; - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - inet_ntop (AF_INET, &nexthop->gate.ipv4, buf, size); - break; - case NEXTHOP_TYPE_IPV6: - inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, size); - break; - default: - break; - } + buf[0] = '\0'; + nexthop = nhlfe->nexthop; + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + inet_ntop(AF_INET, &nexthop->gate.ipv4, buf, size); + break; + case NEXTHOP_TYPE_IPV6: + inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, size); + break; + default: + break; + } - return buf; + return buf; } /* * Check if NHLFE matches with search info passed. */ -static int -nhlfe_nhop_match (zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex) +static int nhlfe_nhop_match(zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex) { - struct nexthop *nhop; - int cmp = 1; + struct nexthop *nhop; + int cmp = 1; - nhop = nhlfe->nexthop; - if (!nhop) - return 1; + nhop = nhlfe->nexthop; + if (!nhop) + return 1; - if (nhop->type != gtype) - return 1; + if (nhop->type != gtype) + return 1; - switch (nhop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - cmp = memcmp(&(nhop->gate.ipv4), &(gate->ipv4), - sizeof(struct in_addr)); - if (!cmp && nhop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - cmp = !(nhop->ifindex == ifindex); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - cmp = memcmp(&(nhop->gate.ipv6), &(gate->ipv6), - sizeof(struct in6_addr)); - if (!cmp && nhop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - cmp = !(nhop->ifindex == ifindex); - break; - default: - break; - } + switch (nhop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + cmp = memcmp(&(nhop->gate.ipv4), &(gate->ipv4), + sizeof(struct in_addr)); + if (!cmp && nhop->type == NEXTHOP_TYPE_IPV4_IFINDEX) + cmp = !(nhop->ifindex == ifindex); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + cmp = memcmp(&(nhop->gate.ipv6), &(gate->ipv6), + sizeof(struct in6_addr)); + if (!cmp && nhop->type == NEXTHOP_TYPE_IPV6_IFINDEX) + cmp = !(nhop->ifindex == ifindex); + break; + default: + break; + } - return cmp; + return cmp; } /* * Locate NHLFE that matches with passed info. */ -static zebra_nhlfe_t * -nhlfe_find (zebra_lsp_t *lsp, enum lsp_types_t lsp_type, - enum nexthop_types_t gtype, union g_addr *gate, - ifindex_t ifindex) +static zebra_nhlfe_t *nhlfe_find(zebra_lsp_t *lsp, enum lsp_types_t lsp_type, + enum nexthop_types_t gtype, union g_addr *gate, + ifindex_t ifindex) { - zebra_nhlfe_t *nhlfe; + zebra_nhlfe_t *nhlfe; - if (!lsp) - return NULL; + if (!lsp) + return NULL; - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - if (nhlfe->type != lsp_type) - continue; - if (!nhlfe_nhop_match (nhlfe, gtype, gate, ifindex)) - break; - } + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + if (nhlfe->type != lsp_type) + continue; + if (!nhlfe_nhop_match(nhlfe, gtype, gate, ifindex)) + break; + } - return nhlfe; + return nhlfe; } /* * Add NHLFE. Base entry must have been created and duplicate * check done. */ -static zebra_nhlfe_t * -nhlfe_add (zebra_lsp_t *lsp, enum lsp_types_t lsp_type, - enum nexthop_types_t gtype, union g_addr *gate, - ifindex_t ifindex, mpls_label_t out_label) -{ - zebra_nhlfe_t *nhlfe; - struct nexthop *nexthop; - - if (!lsp) - return NULL; - - nhlfe = XCALLOC(MTYPE_NHLFE, sizeof(zebra_nhlfe_t)); - if (!nhlfe) - return NULL; - - nhlfe->lsp = lsp; - nhlfe->type = lsp_type; - nhlfe->distance = lsp_distance (lsp_type); - - nexthop = nexthop_new(); - if (!nexthop) - { - XFREE (MTYPE_NHLFE, nhlfe); - return NULL; - } - nexthop_add_labels (nexthop, lsp_type, 1, &out_label); - - nexthop->type = gtype; - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - nexthop->gate.ipv4 = gate->ipv4; - if (ifindex) - nexthop->ifindex = ifindex; - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - nexthop->gate.ipv6 = gate->ipv6; - if (ifindex) - nexthop->ifindex = ifindex; - break; - default: - nexthop_free(nexthop); - XFREE (MTYPE_NHLFE, nhlfe); - return NULL; - break; - } - - nhlfe->nexthop = nexthop; - if (lsp->nhlfe_list) - lsp->nhlfe_list->prev = nhlfe; - nhlfe->next = lsp->nhlfe_list; - lsp->nhlfe_list = nhlfe; - - return nhlfe; +static zebra_nhlfe_t *nhlfe_add(zebra_lsp_t *lsp, enum lsp_types_t lsp_type, + enum nexthop_types_t gtype, union g_addr *gate, + ifindex_t ifindex, mpls_label_t out_label) +{ + zebra_nhlfe_t *nhlfe; + struct nexthop *nexthop; + + if (!lsp) + return NULL; + + nhlfe = XCALLOC(MTYPE_NHLFE, sizeof(zebra_nhlfe_t)); + if (!nhlfe) + return NULL; + + nhlfe->lsp = lsp; + nhlfe->type = lsp_type; + nhlfe->distance = lsp_distance(lsp_type); + + nexthop = nexthop_new(); + if (!nexthop) { + XFREE(MTYPE_NHLFE, nhlfe); + return NULL; + } + nexthop_add_labels(nexthop, lsp_type, 1, &out_label); + + nexthop->type = gtype; + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + nexthop->gate.ipv4 = gate->ipv4; + if (ifindex) + nexthop->ifindex = ifindex; + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + nexthop->gate.ipv6 = gate->ipv6; + if (ifindex) + nexthop->ifindex = ifindex; + break; + default: + nexthop_free(nexthop); + XFREE(MTYPE_NHLFE, nhlfe); + return NULL; + break; + } + + nhlfe->nexthop = nexthop; + if (lsp->nhlfe_list) + lsp->nhlfe_list->prev = nhlfe; + nhlfe->next = lsp->nhlfe_list; + lsp->nhlfe_list = nhlfe; + + return nhlfe; } /* * Delete NHLFE. Entry must be present on list. */ -static int -nhlfe_del (zebra_nhlfe_t *nhlfe) +static int nhlfe_del(zebra_nhlfe_t *nhlfe) { - zebra_lsp_t *lsp; + zebra_lsp_t *lsp; - if (!nhlfe) - return -1; + if (!nhlfe) + return -1; - lsp = nhlfe->lsp; - if (!lsp) - return -1; + lsp = nhlfe->lsp; + if (!lsp) + return -1; - /* Free nexthop. */ - if (nhlfe->nexthop) - nexthop_free(nhlfe->nexthop); + /* Free nexthop. */ + if (nhlfe->nexthop) + nexthop_free(nhlfe->nexthop); - /* Unlink from LSP */ - if (nhlfe->next) - nhlfe->next->prev = nhlfe->prev; - if (nhlfe->prev) - nhlfe->prev->next = nhlfe->next; - else - lsp->nhlfe_list = nhlfe->next; + /* Unlink from LSP */ + if (nhlfe->next) + nhlfe->next->prev = nhlfe->prev; + if (nhlfe->prev) + nhlfe->prev->next = nhlfe->next; + else + lsp->nhlfe_list = nhlfe->next; - if (nhlfe == lsp->best_nhlfe) - lsp->best_nhlfe = NULL; + if (nhlfe == lsp->best_nhlfe) + lsp->best_nhlfe = NULL; - XFREE (MTYPE_NHLFE, nhlfe); + XFREE(MTYPE_NHLFE, nhlfe); - return 0; + return 0; } /* * Update label for NHLFE entry. */ -static void -nhlfe_out_label_update (zebra_nhlfe_t *nhlfe, struct nexthop_label *nh_label) -{ - nhlfe->nexthop->nh_label->label[0] = nh_label->label[0]; -} - -static int -mpls_lsp_uninstall_all (struct hash *lsp_table, zebra_lsp_t *lsp, - enum lsp_types_t type) -{ - zebra_nhlfe_t *nhlfe, *nhlfe_next; - int schedule_lsp = 0; - char buf[BUFSIZ]; - - /* Mark NHLFEs for delete or directly delete, as appropriate. */ - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next) - { - nhlfe_next = nhlfe->next; - - /* Skip non-static NHLFEs */ - if (nhlfe->type != type) - continue; - - if (IS_ZEBRA_DEBUG_MPLS) - { - nhlfe2str (nhlfe, buf, BUFSIZ); - zlog_debug ("Del LSP in-label %u type %d nexthop %s flags 0x%x", - lsp->ile.in_label, type, buf, nhlfe->flags); - } - - if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)) - { - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED); - SET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED); - schedule_lsp = 1; - } - else - { - nhlfe_del (nhlfe); - } - } - - /* Queue LSP for processing, if needed, else delete. */ - if (schedule_lsp) - { - if (lsp_processq_add (lsp)) - return -1; - } - else if (!lsp->nhlfe_list && - !CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED)) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Free LSP in-label %u flags 0x%x", - lsp->ile.in_label, lsp->flags); - - lsp = hash_release(lsp_table, &lsp->ile); - if (lsp) - XFREE(MTYPE_LSP, lsp); - } - - return 0; +static void nhlfe_out_label_update(zebra_nhlfe_t *nhlfe, + struct nexthop_label *nh_label) +{ + nhlfe->nexthop->nh_label->label[0] = nh_label->label[0]; +} + +static int mpls_lsp_uninstall_all(struct hash *lsp_table, zebra_lsp_t *lsp, + enum lsp_types_t type) +{ + zebra_nhlfe_t *nhlfe, *nhlfe_next; + int schedule_lsp = 0; + char buf[BUFSIZ]; + + /* Mark NHLFEs for delete or directly delete, as appropriate. */ + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next) { + nhlfe_next = nhlfe->next; + + /* Skip non-static NHLFEs */ + if (nhlfe->type != type) + continue; + + if (IS_ZEBRA_DEBUG_MPLS) { + nhlfe2str(nhlfe, buf, BUFSIZ); + zlog_debug( + "Del LSP in-label %u type %d nexthop %s flags 0x%x", + lsp->ile.in_label, type, buf, nhlfe->flags); + } + + if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)) { + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + SET_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED); + schedule_lsp = 1; + } else { + nhlfe_del(nhlfe); + } + } + + /* Queue LSP for processing, if needed, else delete. */ + if (schedule_lsp) { + if (lsp_processq_add(lsp)) + return -1; + } else if (!lsp->nhlfe_list + && !CHECK_FLAG(lsp->flags, LSP_FLAG_SCHEDULED)) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Free LSP in-label %u flags 0x%x", + lsp->ile.in_label, lsp->flags); + + lsp = hash_release(lsp_table, &lsp->ile); + if (lsp) + XFREE(MTYPE_LSP, lsp); + } + + return 0; } /* * Uninstall all static NHLFEs for a particular LSP forwarding entry. * If no other NHLFEs exist, the entry would be deleted. */ -static int -mpls_static_lsp_uninstall_all (struct zebra_vrf *zvrf, mpls_label_t in_label) +static int mpls_static_lsp_uninstall_all(struct zebra_vrf *zvrf, + mpls_label_t in_label) { - struct hash *lsp_table; - zebra_ile_t tmp_ile; - zebra_lsp_t *lsp; + struct hash *lsp_table; + zebra_ile_t tmp_ile; + zebra_lsp_t *lsp; - /* Lookup table. */ - lsp_table = zvrf->lsp_table; - if (!lsp_table) - return -1; + /* Lookup table. */ + lsp_table = zvrf->lsp_table; + if (!lsp_table) + return -1; - /* If entry is not present, exit. */ - tmp_ile.in_label = in_label; - lsp = hash_lookup (lsp_table, &tmp_ile); - if (!lsp || !lsp->nhlfe_list) - return 0; + /* If entry is not present, exit. */ + tmp_ile.in_label = in_label; + lsp = hash_lookup(lsp_table, &tmp_ile); + if (!lsp || !lsp->nhlfe_list) + return 0; - return mpls_lsp_uninstall_all (lsp_table, lsp, ZEBRA_LSP_STATIC); + return mpls_lsp_uninstall_all(lsp_table, lsp, ZEBRA_LSP_STATIC); } -static json_object * -nhlfe_json (zebra_nhlfe_t *nhlfe) +static json_object *nhlfe_json(zebra_nhlfe_t *nhlfe) { - char buf[BUFSIZ]; - json_object *json_nhlfe = NULL; - struct nexthop *nexthop = nhlfe->nexthop; + char buf[BUFSIZ]; + json_object *json_nhlfe = NULL; + struct nexthop *nexthop = nhlfe->nexthop; - json_nhlfe = json_object_new_object(); - json_object_string_add(json_nhlfe, "type", nhlfe_type2str(nhlfe->type)); - json_object_int_add(json_nhlfe, "outLabel", nexthop->nh_label->label[0]); - json_object_int_add(json_nhlfe, "distance", nhlfe->distance); + json_nhlfe = json_object_new_object(); + json_object_string_add(json_nhlfe, "type", nhlfe_type2str(nhlfe->type)); + json_object_int_add(json_nhlfe, "outLabel", + nexthop->nh_label->label[0]); + json_object_int_add(json_nhlfe, "distance", nhlfe->distance); - if (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED)) - json_object_boolean_true_add(json_nhlfe, "installed"); + if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)) + json_object_boolean_true_add(json_nhlfe, "installed"); - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - json_object_string_add(json_nhlfe, "nexthop", - inet_ntoa (nexthop->gate.ipv4)); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - json_object_string_add(json_nhlfe, "nexthop", - inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); - - if (nexthop->ifindex) - json_object_string_add(json_nhlfe, "interface", ifindex2ifname (nexthop->ifindex, VRF_DEFAULT)); - break; - default: - break; - } - return json_nhlfe; + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + json_object_string_add(json_nhlfe, "nexthop", + inet_ntoa(nexthop->gate.ipv4)); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + json_object_string_add( + json_nhlfe, "nexthop", + inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); + + if (nexthop->ifindex) + json_object_string_add( + json_nhlfe, "interface", + ifindex2ifname(nexthop->ifindex, VRF_DEFAULT)); + break; + default: + break; + } + return json_nhlfe; } /* * Print the NHLFE for a LSP forwarding entry. */ -static void -nhlfe_print (zebra_nhlfe_t *nhlfe, struct vty *vty) -{ - struct nexthop *nexthop; - char buf[BUFSIZ]; - - nexthop = nhlfe->nexthop; - if (!nexthop || !nexthop->nh_label) // unexpected - return; - - vty_out (vty, " type: %s remote label: %s distance: %d\n", - nhlfe_type2str(nhlfe->type), - label2str(nexthop->nh_label->label[0], buf, BUFSIZ), - nhlfe->distance); - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4)); - if (nexthop->ifindex) - vty_out (vty, " dev %s", ifindex2ifname (nexthop->ifindex, VRF_DEFAULT)); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - vty_out (vty, " via %s", - inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); - if (nexthop->ifindex) - vty_out (vty, " dev %s", ifindex2ifname (nexthop->ifindex, VRF_DEFAULT)); - break; - default: - break; - } - vty_out(vty, "%s", CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) ? - " (installed)" : ""); - vty_out (vty, "\n"); +static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty) +{ + struct nexthop *nexthop; + char buf[BUFSIZ]; + + nexthop = nhlfe->nexthop; + if (!nexthop || !nexthop->nh_label) // unexpected + return; + + vty_out(vty, " type: %s remote label: %s distance: %d\n", + nhlfe_type2str(nhlfe->type), + label2str(nexthop->nh_label->label[0], buf, BUFSIZ), + nhlfe->distance); + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + vty_out(vty, " via %s", inet_ntoa(nexthop->gate.ipv4)); + if (nexthop->ifindex) + vty_out(vty, " dev %s", + ifindex2ifname(nexthop->ifindex, VRF_DEFAULT)); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + vty_out(vty, " via %s", + inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); + if (nexthop->ifindex) + vty_out(vty, " dev %s", + ifindex2ifname(nexthop->ifindex, VRF_DEFAULT)); + break; + default: + break; + } + vty_out(vty, "%s", + CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED) ? " (installed)" + : ""); + vty_out(vty, "\n"); } /* * Print an LSP forwarding entry. */ -static void -lsp_print (zebra_lsp_t *lsp, void *ctxt) +static void lsp_print(zebra_lsp_t *lsp, void *ctxt) { - zebra_nhlfe_t *nhlfe; - struct vty *vty; + zebra_nhlfe_t *nhlfe; + struct vty *vty; - vty = (struct vty *) ctxt; + vty = (struct vty *)ctxt; - vty_out (vty, "Local label: %u%s\n", - lsp->ile.in_label, - CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED) ? " (installed)" : ""); + vty_out(vty, "Local label: %u%s\n", lsp->ile.in_label, + CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED) ? " (installed)" + : ""); - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - nhlfe_print (nhlfe, vty); + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) + nhlfe_print(nhlfe, vty); } /* * JSON objects for an LSP forwarding entry. */ -static json_object * -lsp_json (zebra_lsp_t *lsp) +static json_object *lsp_json(zebra_lsp_t *lsp) { - zebra_nhlfe_t *nhlfe = NULL; - json_object *json = json_object_new_object(); - json_object *json_nhlfe_list = json_object_new_array(); + zebra_nhlfe_t *nhlfe = NULL; + json_object *json = json_object_new_object(); + json_object *json_nhlfe_list = json_object_new_array(); - json_object_int_add(json, "inLabel", lsp->ile.in_label); + json_object_int_add(json, "inLabel", lsp->ile.in_label); - if (CHECK_FLAG (lsp->flags, LSP_FLAG_INSTALLED)) - json_object_boolean_true_add(json, "installed"); + if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) + json_object_boolean_true_add(json, "installed"); - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - json_object_array_add(json_nhlfe_list, nhlfe_json(nhlfe)); + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) + json_object_array_add(json_nhlfe_list, nhlfe_json(nhlfe)); - json_object_object_add(json, "nexthops", json_nhlfe_list); - return json; + json_object_object_add(json, "nexthops", json_nhlfe_list); + return json; } /* Return a sorted linked list of the hash contents */ -static struct list * -hash_get_sorted_list (struct hash *hash, void *cmp) +static struct list *hash_get_sorted_list(struct hash *hash, void *cmp) { - unsigned int i; - struct hash_backet *hb; - struct list *sorted_list = list_new(); + unsigned int i; + struct hash_backet *hb; + struct list *sorted_list = list_new(); - sorted_list->cmp = (int (*)(void *, void *)) cmp; + sorted_list->cmp = (int (*)(void *, void *))cmp; - for (i = 0; i < hash->size; i++) - for (hb = hash->index[i]; hb; hb = hb->next) - listnode_add_sort(sorted_list, hb->data); + for (i = 0; i < hash->size; i++) + for (hb = hash->index[i]; hb; hb = hb->next) + listnode_add_sort(sorted_list, hb->data); - return sorted_list; + return sorted_list; } /* * Compare two LSPs based on their label values. */ -static int -lsp_cmp (zebra_lsp_t *lsp1, zebra_lsp_t *lsp2) +static int lsp_cmp(zebra_lsp_t *lsp1, zebra_lsp_t *lsp2) { - if (lsp1->ile.in_label < lsp2->ile.in_label) - return -1; + if (lsp1->ile.in_label < lsp2->ile.in_label) + return -1; - if (lsp1->ile.in_label > lsp2->ile.in_label) - return 1; + if (lsp1->ile.in_label > lsp2->ile.in_label) + return 1; - return 0; + return 0; } /* * Callback to allocate static LSP. */ -static void * -slsp_alloc (void *p) +static void *slsp_alloc(void *p) { - const zebra_ile_t *ile = p; - zebra_slsp_t *slsp; + const zebra_ile_t *ile = p; + zebra_slsp_t *slsp; - slsp = XCALLOC (MTYPE_SLSP, sizeof(zebra_slsp_t)); - slsp->ile = *ile; - return ((void *)slsp); + slsp = XCALLOC(MTYPE_SLSP, sizeof(zebra_slsp_t)); + slsp->ile = *ile; + return ((void *)slsp); } /* * Compare two static LSPs based on their label values. */ -static int -slsp_cmp (zebra_slsp_t *slsp1, zebra_slsp_t *slsp2) +static int slsp_cmp(zebra_slsp_t *slsp1, zebra_slsp_t *slsp2) { - if (slsp1->ile.in_label < slsp2->ile.in_label) - return -1; + if (slsp1->ile.in_label < slsp2->ile.in_label) + return -1; - if (slsp1->ile.in_label > slsp2->ile.in_label) - return 1; + if (slsp1->ile.in_label > slsp2->ile.in_label) + return 1; - return 0; + return 0; } /* * Check if static NHLFE matches with search info passed. */ -static int -snhlfe_match (zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex) +static int snhlfe_match(zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex) { - int cmp = 1; + int cmp = 1; - if (snhlfe->gtype != gtype) - return 1; + if (snhlfe->gtype != gtype) + return 1; - switch (snhlfe->gtype) - { - case NEXTHOP_TYPE_IPV4: - cmp = memcmp(&(snhlfe->gate.ipv4), &(gate->ipv4), - sizeof(struct in_addr)); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - cmp = memcmp(&(snhlfe->gate.ipv6), &(gate->ipv6), - sizeof(struct in6_addr)); - if (!cmp && snhlfe->gtype == NEXTHOP_TYPE_IPV6_IFINDEX) - cmp = !(snhlfe->ifindex == ifindex); - break; - default: - break; - } + switch (snhlfe->gtype) { + case NEXTHOP_TYPE_IPV4: + cmp = memcmp(&(snhlfe->gate.ipv4), &(gate->ipv4), + sizeof(struct in_addr)); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + cmp = memcmp(&(snhlfe->gate.ipv6), &(gate->ipv6), + sizeof(struct in6_addr)); + if (!cmp && snhlfe->gtype == NEXTHOP_TYPE_IPV6_IFINDEX) + cmp = !(snhlfe->ifindex == ifindex); + break; + default: + break; + } - return cmp; + return cmp; } /* * Locate static NHLFE that matches with passed info. */ -static zebra_snhlfe_t * -snhlfe_find (zebra_slsp_t *slsp, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex) +static zebra_snhlfe_t *snhlfe_find(zebra_slsp_t *slsp, + enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex) { - zebra_snhlfe_t *snhlfe; + zebra_snhlfe_t *snhlfe; - if (!slsp) - return NULL; + if (!slsp) + return NULL; - for (snhlfe = slsp->snhlfe_list; snhlfe; snhlfe = snhlfe->next) - { - if (!snhlfe_match (snhlfe, gtype, gate, ifindex)) - break; - } + for (snhlfe = slsp->snhlfe_list; snhlfe; snhlfe = snhlfe->next) { + if (!snhlfe_match(snhlfe, gtype, gate, ifindex)) + break; + } - return snhlfe; + return snhlfe; } @@ -1586,144 +1479,136 @@ snhlfe_find (zebra_slsp_t *slsp, enum nexthop_types_t gtype, * Add static NHLFE. Base LSP config entry must have been created * and duplicate check done. */ -static zebra_snhlfe_t * -snhlfe_add (zebra_slsp_t *slsp, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex, - mpls_label_t out_label) -{ - zebra_snhlfe_t *snhlfe; - - if (!slsp) - return NULL; - - snhlfe = XCALLOC(MTYPE_SNHLFE, sizeof(zebra_snhlfe_t)); - snhlfe->slsp = slsp; - snhlfe->out_label = out_label; - snhlfe->gtype = gtype; - switch (gtype) - { - case NEXTHOP_TYPE_IPV4: - snhlfe->gate.ipv4 = gate->ipv4; - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - snhlfe->gate.ipv6 = gate->ipv6; - if (ifindex) - snhlfe->ifindex = ifindex; - break; - default: - XFREE (MTYPE_SNHLFE, snhlfe); - return NULL; - } - - if (slsp->snhlfe_list) - slsp->snhlfe_list->prev = snhlfe; - snhlfe->next = slsp->snhlfe_list; - slsp->snhlfe_list = snhlfe; - - return snhlfe; +static zebra_snhlfe_t *snhlfe_add(zebra_slsp_t *slsp, + enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex, + mpls_label_t out_label) +{ + zebra_snhlfe_t *snhlfe; + + if (!slsp) + return NULL; + + snhlfe = XCALLOC(MTYPE_SNHLFE, sizeof(zebra_snhlfe_t)); + snhlfe->slsp = slsp; + snhlfe->out_label = out_label; + snhlfe->gtype = gtype; + switch (gtype) { + case NEXTHOP_TYPE_IPV4: + snhlfe->gate.ipv4 = gate->ipv4; + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + snhlfe->gate.ipv6 = gate->ipv6; + if (ifindex) + snhlfe->ifindex = ifindex; + break; + default: + XFREE(MTYPE_SNHLFE, snhlfe); + return NULL; + } + + if (slsp->snhlfe_list) + slsp->snhlfe_list->prev = snhlfe; + snhlfe->next = slsp->snhlfe_list; + slsp->snhlfe_list = snhlfe; + + return snhlfe; } /* * Delete static NHLFE. Entry must be present on list. */ -static int -snhlfe_del (zebra_snhlfe_t *snhlfe) +static int snhlfe_del(zebra_snhlfe_t *snhlfe) { - zebra_slsp_t *slsp; + zebra_slsp_t *slsp; - if (!snhlfe) - return -1; + if (!snhlfe) + return -1; - slsp = snhlfe->slsp; - if (!slsp) - return -1; + slsp = snhlfe->slsp; + if (!slsp) + return -1; - if (snhlfe->next) - snhlfe->next->prev = snhlfe->prev; - if (snhlfe->prev) - snhlfe->prev->next = snhlfe->next; - else - slsp->snhlfe_list = snhlfe->next; + if (snhlfe->next) + snhlfe->next->prev = snhlfe->prev; + if (snhlfe->prev) + snhlfe->prev->next = snhlfe->next; + else + slsp->snhlfe_list = snhlfe->next; - snhlfe->prev = snhlfe->next = NULL; - if (snhlfe->ifname) - XFREE (MTYPE_SNHLFE_IFNAME, snhlfe->ifname); - XFREE (MTYPE_SNHLFE, snhlfe); + snhlfe->prev = snhlfe->next = NULL; + if (snhlfe->ifname) + XFREE(MTYPE_SNHLFE_IFNAME, snhlfe->ifname); + XFREE(MTYPE_SNHLFE, snhlfe); - return 0; + return 0; } /* * Delete all static NHLFE entries for this LSP (in label). */ -static int -snhlfe_del_all (zebra_slsp_t *slsp) +static int snhlfe_del_all(zebra_slsp_t *slsp) { - zebra_snhlfe_t *snhlfe, *snhlfe_next; + zebra_snhlfe_t *snhlfe, *snhlfe_next; - if (!slsp) - return -1; + if (!slsp) + return -1; - for (snhlfe = slsp->snhlfe_list; snhlfe; snhlfe = snhlfe_next) - { - snhlfe_next = snhlfe->next; - snhlfe_del (snhlfe); - } + for (snhlfe = slsp->snhlfe_list; snhlfe; snhlfe = snhlfe_next) { + snhlfe_next = snhlfe->next; + snhlfe_del(snhlfe); + } - return 0; + return 0; } /* * Create printable string for NHLFE configuration. */ -static char * -snhlfe2str (zebra_snhlfe_t *snhlfe, char *buf, int size) +static char *snhlfe2str(zebra_snhlfe_t *snhlfe, char *buf, int size) { - buf[0] = '\0'; - switch (snhlfe->gtype) - { - case NEXTHOP_TYPE_IPV4: - inet_ntop (AF_INET, &snhlfe->gate.ipv4, buf, size); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - inet_ntop (AF_INET6, &snhlfe->gate.ipv6, buf, size); - if (snhlfe->ifindex) - strcat (buf, ifindex2ifname (snhlfe->ifindex, VRF_DEFAULT)); - break; - default: - break; - } + buf[0] = '\0'; + switch (snhlfe->gtype) { + case NEXTHOP_TYPE_IPV4: + inet_ntop(AF_INET, &snhlfe->gate.ipv4, buf, size); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + inet_ntop(AF_INET6, &snhlfe->gate.ipv6, buf, size); + if (snhlfe->ifindex) + strcat(buf, + ifindex2ifname(snhlfe->ifindex, VRF_DEFAULT)); + break; + default: + break; + } - return buf; + return buf; } /* * Initialize work queue for processing changed LSPs. */ -static int -mpls_processq_init (struct zebra_t *zebra) +static int mpls_processq_init(struct zebra_t *zebra) { - zebra->lsp_process_q = work_queue_new (zebra->master, "LSP processing"); - if (!zebra->lsp_process_q) - { - zlog_err ("%s: could not initialise work queue!", __func__); - return -1; - } + zebra->lsp_process_q = work_queue_new(zebra->master, "LSP processing"); + if (!zebra->lsp_process_q) { + zlog_err("%s: could not initialise work queue!", __func__); + return -1; + } - zebra->lsp_process_q->spec.workfunc = &lsp_process; - zebra->lsp_process_q->spec.del_item_data = &lsp_processq_del; - zebra->lsp_process_q->spec.errorfunc = NULL; - zebra->lsp_process_q->spec.completion_func = &lsp_processq_complete; - zebra->lsp_process_q->spec.max_retries = 0; - zebra->lsp_process_q->spec.hold = 10; + zebra->lsp_process_q->spec.workfunc = &lsp_process; + zebra->lsp_process_q->spec.del_item_data = &lsp_processq_del; + zebra->lsp_process_q->spec.errorfunc = NULL; + zebra->lsp_process_q->spec.completion_func = &lsp_processq_complete; + zebra->lsp_process_q->spec.max_retries = 0; + zebra->lsp_process_q->spec.hold = 10; - return 0; + return 0; } - /* Public functions */ /* @@ -1738,132 +1623,128 @@ mpls_processq_init (struct zebra_t *zebra) * -2 if a label was inside the reserved range (0-15) * -3 if the number of labels given exceeds MPLS_MAX_LABELS */ -int -mpls_str2label (const char *label_str, u_int8_t *num_labels, - mpls_label_t *labels) -{ - char *ostr; // copy of label string (start) - char *lstr; // copy of label string - char *nump; // pointer to next segment - char *endp; // end pointer - int i; // for iterating label_str - int rc; // return code - mpls_label_t pl[MPLS_MAX_LABELS]; // parsed labels - - /* labels to zero until we have a successful parse */ - ostr = lstr = XSTRDUP (MTYPE_TMP, label_str); - *num_labels = 0; - rc = 0; - - for (i = 0; i < MPLS_MAX_LABELS && lstr && !rc; i++) - { - nump = strsep (&lstr, "/"); - pl[i] = strtoul(nump, &endp, 10); - - /* format check */ - if (*endp != '\0') - rc = -1; - /* validity check */ - else if (!IS_MPLS_UNRESERVED_LABEL(pl[i])) - rc = -2; - } +int mpls_str2label(const char *label_str, u_int8_t *num_labels, + mpls_label_t *labels) +{ + char *ostr; // copy of label string (start) + char *lstr; // copy of label string + char *nump; // pointer to next segment + char *endp; // end pointer + int i; // for iterating label_str + int rc; // return code + mpls_label_t pl[MPLS_MAX_LABELS]; // parsed labels + + /* labels to zero until we have a successful parse */ + ostr = lstr = XSTRDUP(MTYPE_TMP, label_str); + *num_labels = 0; + rc = 0; + + for (i = 0; i < MPLS_MAX_LABELS && lstr && !rc; i++) { + nump = strsep(&lstr, "/"); + pl[i] = strtoul(nump, &endp, 10); + + /* format check */ + if (*endp != '\0') + rc = -1; + /* validity check */ + else if (!IS_MPLS_UNRESERVED_LABEL(pl[i])) + rc = -2; + } - /* excess labels */ - if (!rc && i == MPLS_MAX_LABELS && lstr) - rc = -3; + /* excess labels */ + if (!rc && i == MPLS_MAX_LABELS && lstr) + rc = -3; - if (!rc) - { - *num_labels = i; - memcpy (labels, pl, *num_labels * sizeof (mpls_label_t)); - } + if (!rc) { + *num_labels = i; + memcpy(labels, pl, *num_labels * sizeof(mpls_label_t)); + } - XFREE (MTYPE_TMP, ostr); + XFREE(MTYPE_TMP, ostr); - return rc; + return rc; } /* * Label to string conversion, labels in string separated by '/'. */ -char * -mpls_label2str (u_int8_t num_labels, mpls_label_t *labels, - char *buf, int len, int pretty) -{ - char *buf_ptr = buf; - buf[0] = '\0'; - - if (pretty) { - if (num_labels == 1) { - label2str(labels[0], buf, len); - } else if (num_labels == 2) { - label2str(labels[0], buf, len); - buf_ptr += strlen(buf); - - snprintf (buf_ptr, len, "/"); - buf_ptr++; - - label2str(labels[1], buf_ptr, len); - } - } else { - if (num_labels == 1) - snprintf (buf, len, "%u", labels[0]); - else if (num_labels == 2) - snprintf (buf, len, "%u/%u", labels[0], labels[1]); - } - return buf; +char *mpls_label2str(u_int8_t num_labels, mpls_label_t *labels, char *buf, + int len, int pretty) +{ + char *buf_ptr = buf; + buf[0] = '\0'; + + if (pretty) { + if (num_labels == 1) { + label2str(labels[0], buf, len); + } else if (num_labels == 2) { + label2str(labels[0], buf, len); + buf_ptr += strlen(buf); + + snprintf(buf_ptr, len, "/"); + buf_ptr++; + + label2str(labels[1], buf_ptr, len); + } + } else { + if (num_labels == 1) + snprintf(buf, len, "%u", labels[0]); + else if (num_labels == 2) + snprintf(buf, len, "%u/%u", labels[0], labels[1]); + } + return buf; } /* * Install dynamic LSP entry. */ -int -zebra_mpls_lsp_install (struct zebra_vrf *zvrf, struct route_node *rn, struct route_entry *re) +int zebra_mpls_lsp_install(struct zebra_vrf *zvrf, struct route_node *rn, + struct route_entry *re) { - struct route_table *table; - zebra_fec_t *fec; + struct route_table *table; + zebra_fec_t *fec; - table = zvrf->fec_table[family2afi(PREFIX_FAMILY(&rn->p))]; - if (!table) - return -1; + table = zvrf->fec_table[family2afi(PREFIX_FAMILY(&rn->p))]; + if (!table) + return -1; - /* See if there is a configured label binding for this FEC. */ - fec = fec_find (table, &rn->p); - if (!fec || fec->label == MPLS_INVALID_LABEL) - return 0; + /* See if there is a configured label binding for this FEC. */ + fec = fec_find(table, &rn->p); + if (!fec || fec->label == MPLS_INVALID_LABEL) + return 0; - /* We cannot install a label forwarding entry if local label is the - * implicit-null label. - */ - if (fec->label == MPLS_IMP_NULL_LABEL) - return 0; + /* We cannot install a label forwarding entry if local label is the + * implicit-null label. + */ + if (fec->label == MPLS_IMP_NULL_LABEL) + return 0; - if (lsp_install (zvrf, fec->label, rn, re)) - return -1; + if (lsp_install(zvrf, fec->label, rn, re)) + return -1; - return 0; + return 0; } /* * Uninstall dynamic LSP entry, if any. */ -int -zebra_mpls_lsp_uninstall (struct zebra_vrf *zvrf, struct route_node *rn, struct route_entry *re) +int zebra_mpls_lsp_uninstall(struct zebra_vrf *zvrf, struct route_node *rn, + struct route_entry *re) { - struct route_table *table; - zebra_fec_t *fec; + struct route_table *table; + zebra_fec_t *fec; - table = zvrf->fec_table[family2afi(PREFIX_FAMILY(&rn->p))]; - if (!table) - return -1; + table = zvrf->fec_table[family2afi(PREFIX_FAMILY(&rn->p))]; + if (!table) + return -1; - /* See if there is a configured label binding for this FEC. */ - fec = fec_find (table, &rn->p); - if (!fec || fec->label == MPLS_INVALID_LABEL) - return 0; + /* See if there is a configured label binding for this FEC. */ + fec = fec_find(table, &rn->p); + if (!fec || fec->label == MPLS_INVALID_LABEL) + return 0; - /* Uninstall always removes all dynamic NHLFEs. */ - return lsp_uninstall (zvrf, fec->label); + /* Uninstall always removes all dynamic NHLFEs. */ + return lsp_uninstall(zvrf, fec->label); } /* @@ -1874,91 +1755,85 @@ zebra_mpls_lsp_uninstall (struct zebra_vrf *zvrf, struct route_node *rn, struct * label from a locally configured label block (SRGB), if one exists and index * is acceptable. */ -int -zebra_mpls_fec_register (struct zebra_vrf *zvrf, struct prefix *p, - u_int32_t label_index, struct zserv *client) -{ - struct route_table *table; - zebra_fec_t *fec; - char buf[BUFSIZ]; - int new_client; - int label_change = 0; - u_int32_t old_label; - - table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))]; - if (!table) - return -1; - - if (IS_ZEBRA_DEBUG_MPLS) - prefix2str(p, buf, BUFSIZ); - - /* Locate FEC */ - fec = fec_find (table, p); - if (!fec) - { - fec = fec_add (table, p, MPLS_INVALID_LABEL, 0, label_index); - if (!fec) - { - prefix2str(p, buf, BUFSIZ); - zlog_err("Failed to add FEC %s upon register, client %s", - buf, zebra_route_string(client->proto)); - return -1; - } - - old_label = MPLS_INVALID_LABEL; - new_client = 1; - } - else - { - /* Client may register same FEC with different label index. */ - new_client = (listnode_lookup(fec->client_list, client) == NULL); - if (!new_client && fec->label_index == label_index) - /* Duplicate register */ - return 0; - - /* Save current label, update label index */ - old_label = fec->label; - fec->label_index = label_index; - } - - if (new_client) - listnode_add (fec->client_list, client); - - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug("FEC %s Label Index %u %s by client %s", - buf, label_index, new_client ? "registered" : "updated", - zebra_route_string(client->proto)); - - /* If not a configured FEC, derive the local label (from label index) - * or reset it. - */ - if (!(fec->flags & FEC_FLAG_CONFIGURED)) - { - fec_derive_label_from_index (zvrf, fec); - - /* If no label change, exit. */ - if (fec->label == old_label) - return 0; - - label_change = 1; - } - - /* If new client or label change, update client and install or uninstall - * label forwarding entry as needed. - */ - /* Inform client of label, if needed. */ - if ((new_client && fec->label != MPLS_INVALID_LABEL) || - label_change) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Update client label %u", fec->label); - fec_send (fec, client); - } - - if (new_client || label_change) - return fec_change_update_lsp (zvrf, fec, old_label); - - return 0; +int zebra_mpls_fec_register(struct zebra_vrf *zvrf, struct prefix *p, + u_int32_t label_index, struct zserv *client) +{ + struct route_table *table; + zebra_fec_t *fec; + char buf[BUFSIZ]; + int new_client; + int label_change = 0; + u_int32_t old_label; + + table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))]; + if (!table) + return -1; + + if (IS_ZEBRA_DEBUG_MPLS) + prefix2str(p, buf, BUFSIZ); + + /* Locate FEC */ + fec = fec_find(table, p); + if (!fec) { + fec = fec_add(table, p, MPLS_INVALID_LABEL, 0, label_index); + if (!fec) { + prefix2str(p, buf, BUFSIZ); + zlog_err( + "Failed to add FEC %s upon register, client %s", + buf, zebra_route_string(client->proto)); + return -1; + } + + old_label = MPLS_INVALID_LABEL; + new_client = 1; + } else { + /* Client may register same FEC with different label index. */ + new_client = + (listnode_lookup(fec->client_list, client) == NULL); + if (!new_client && fec->label_index == label_index) + /* Duplicate register */ + return 0; + + /* Save current label, update label index */ + old_label = fec->label; + fec->label_index = label_index; + } + + if (new_client) + listnode_add(fec->client_list, client); + + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("FEC %s Label Index %u %s by client %s", buf, + label_index, new_client ? "registered" : "updated", + zebra_route_string(client->proto)); + + /* If not a configured FEC, derive the local label (from label index) + * or reset it. + */ + if (!(fec->flags & FEC_FLAG_CONFIGURED)) { + fec_derive_label_from_index(zvrf, fec); + + /* If no label change, exit. */ + if (fec->label == old_label) + return 0; + + label_change = 1; + } + + /* If new client or label change, update client and install or uninstall + * label forwarding entry as needed. + */ + /* Inform client of label, if needed. */ + if ((new_client && fec->label != MPLS_INVALID_LABEL) || label_change) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Update client label %u", fec->label); + fec_send(fec, client); + } + + if (new_client || label_change) + return fec_change_update_lsp(zvrf, fec, old_label); + + return 0; } /* @@ -1966,89 +1841,85 @@ zebra_mpls_fec_register (struct zebra_vrf *zvrf, struct prefix *p, * itself is deleted if no other registered clients exist and there is no * label bound to the FEC. */ -int -zebra_mpls_fec_unregister (struct zebra_vrf *zvrf, struct prefix *p, - struct zserv *client) +int zebra_mpls_fec_unregister(struct zebra_vrf *zvrf, struct prefix *p, + struct zserv *client) { - struct route_table *table; - zebra_fec_t *fec; - char buf[BUFSIZ]; - - table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))]; - if (!table) - return -1; + struct route_table *table; + zebra_fec_t *fec; + char buf[BUFSIZ]; - if (IS_ZEBRA_DEBUG_MPLS) - prefix2str(p, buf, BUFSIZ); + table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))]; + if (!table) + return -1; - fec = fec_find (table, p); - if (!fec) - { - prefix2str(p, buf, BUFSIZ); - zlog_err("Failed to find FEC %s upon unregister, client %s", - buf, zebra_route_string(client->proto)); - return -1; - } + if (IS_ZEBRA_DEBUG_MPLS) + prefix2str(p, buf, BUFSIZ); - listnode_delete(fec->client_list, client); - - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug("FEC %s unregistered by client %s", - buf, zebra_route_string(client->proto)); + fec = fec_find(table, p); + if (!fec) { + prefix2str(p, buf, BUFSIZ); + zlog_err("Failed to find FEC %s upon unregister, client %s", + buf, zebra_route_string(client->proto)); + return -1; + } - /* If not a configured entry, delete the FEC if no other clients. Before - * deleting, see if any LSP needs to be uninstalled. - */ - if (!(fec->flags & FEC_FLAG_CONFIGURED) && - list_isempty(fec->client_list)) - { - mpls_label_t old_label = fec->label; - fec->label = MPLS_INVALID_LABEL; /* reset */ - fec_change_update_lsp (zvrf, fec, old_label); - fec_del (fec); - } + listnode_delete(fec->client_list, client); + + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("FEC %s unregistered by client %s", buf, + zebra_route_string(client->proto)); + + /* If not a configured entry, delete the FEC if no other clients. Before + * deleting, see if any LSP needs to be uninstalled. + */ + if (!(fec->flags & FEC_FLAG_CONFIGURED) + && list_isempty(fec->client_list)) { + mpls_label_t old_label = fec->label; + fec->label = MPLS_INVALID_LABEL; /* reset */ + fec_change_update_lsp(zvrf, fec, old_label); + fec_del(fec); + } - return 0; + return 0; } /* * Cleanup any FECs registered by this client. */ -int -zebra_mpls_cleanup_fecs_for_client (struct zebra_vrf *zvrf, struct zserv *client) -{ - struct route_node *rn; - zebra_fec_t *fec; - struct listnode *node; - struct zserv *fec_client; - int af; - - for (af = AFI_IP; af < AFI_MAX; af++) - { - if (zvrf->fec_table[af] == NULL) - continue; - - for (rn = route_top(zvrf->fec_table[af]); rn; rn = route_next(rn)) - { - fec = rn->info; - if (!fec || list_isempty(fec->client_list)) - continue; - - for (ALL_LIST_ELEMENTS_RO(fec->client_list, node, fec_client)) - { - if (fec_client == client) - { - listnode_delete(fec->client_list, fec_client); - if (!(fec->flags & FEC_FLAG_CONFIGURED) && - list_isempty(fec->client_list)) - fec_del (fec); - break; - } - } - } - } +int zebra_mpls_cleanup_fecs_for_client(struct zebra_vrf *zvrf, + struct zserv *client) +{ + struct route_node *rn; + zebra_fec_t *fec; + struct listnode *node; + struct zserv *fec_client; + int af; + + for (af = AFI_IP; af < AFI_MAX; af++) { + if (zvrf->fec_table[af] == NULL) + continue; + + for (rn = route_top(zvrf->fec_table[af]); rn; + rn = route_next(rn)) { + fec = rn->info; + if (!fec || list_isempty(fec->client_list)) + continue; + + for (ALL_LIST_ELEMENTS_RO(fec->client_list, node, + fec_client)) { + if (fec_client == client) { + listnode_delete(fec->client_list, + fec_client); + if (!(fec->flags & FEC_FLAG_CONFIGURED) + && list_isempty(fec->client_list)) + fec_del(fec); + break; + } + } + } + } - return 0; + return 0; } /* @@ -2058,38 +1929,36 @@ zebra_mpls_cleanup_fecs_for_client (struct zebra_vrf *zvrf, struct zserv *client * TODO: Currently walks entire table, can optimize later with another * hash.. */ -zebra_fec_t * -zebra_mpls_fec_for_label (struct zebra_vrf *zvrf, mpls_label_t label) -{ - struct route_node *rn; - zebra_fec_t *fec; - int af; - - for (af = AFI_IP; af < AFI_MAX; af++) - { - if (zvrf->fec_table[af] == NULL) - continue; - - for (rn = route_top(zvrf->fec_table[af]); rn; rn = route_next(rn)) - { - if (!rn->info) - continue; - fec = rn->info; - if (fec->label == label) - return fec; - } - } +zebra_fec_t *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf, + mpls_label_t label) +{ + struct route_node *rn; + zebra_fec_t *fec; + int af; + + for (af = AFI_IP; af < AFI_MAX; af++) { + if (zvrf->fec_table[af] == NULL) + continue; + + for (rn = route_top(zvrf->fec_table[af]); rn; + rn = route_next(rn)) { + if (!rn->info) + continue; + fec = rn->info; + if (fec->label == label) + return fec; + } + } - return NULL; + return NULL; } /* * Inform if specified label is currently bound to a FEC or not. */ -int -zebra_mpls_label_already_bound (struct zebra_vrf *zvrf, mpls_label_t label) +int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, mpls_label_t label) { - return (zebra_mpls_fec_for_label (zvrf, label) ? 1 : 0); + return (zebra_mpls_fec_for_label(zvrf, label) ? 1 : 0); } /* @@ -2097,59 +1966,54 @@ zebra_mpls_label_already_bound (struct zebra_vrf *zvrf, mpls_label_t label) * FEC, notify them. If there are labeled routes for this FEC, install the * label forwarding entry. */ -int -zebra_mpls_static_fec_add (struct zebra_vrf *zvrf, struct prefix *p, - mpls_label_t in_label) -{ - struct route_table *table; - zebra_fec_t *fec; - char buf[BUFSIZ]; - mpls_label_t old_label; - int ret = 0; - - table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))]; - if (!table) - return -1; - - if (IS_ZEBRA_DEBUG_MPLS) - prefix2str(p, buf, BUFSIZ); - - /* Update existing FEC or create a new one. */ - fec = fec_find (table, p); - if (!fec) - { - fec = fec_add (table, p, in_label, FEC_FLAG_CONFIGURED, - MPLS_INVALID_LABEL_INDEX); - if (!fec) - { - prefix2str(p, buf, BUFSIZ); - zlog_err ("Failed to add FEC %s upon config", buf); - return -1; - } - - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Add fec %s label %u", buf, in_label); - } - else - { - fec->flags |= FEC_FLAG_CONFIGURED; - if (fec->label == in_label) - /* Duplicate config */ - return 0; - - /* Label change, update clients. */ - old_label = fec->label; - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Update fec %s new label %u", buf, in_label); - - fec->label = in_label; - fec_update_clients (fec); - - /* Update label forwarding entries appropriately */ - ret = fec_change_update_lsp (zvrf, fec, old_label); - } - - return ret; +int zebra_mpls_static_fec_add(struct zebra_vrf *zvrf, struct prefix *p, + mpls_label_t in_label) +{ + struct route_table *table; + zebra_fec_t *fec; + char buf[BUFSIZ]; + mpls_label_t old_label; + int ret = 0; + + table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))]; + if (!table) + return -1; + + if (IS_ZEBRA_DEBUG_MPLS) + prefix2str(p, buf, BUFSIZ); + + /* Update existing FEC or create a new one. */ + fec = fec_find(table, p); + if (!fec) { + fec = fec_add(table, p, in_label, FEC_FLAG_CONFIGURED, + MPLS_INVALID_LABEL_INDEX); + if (!fec) { + prefix2str(p, buf, BUFSIZ); + zlog_err("Failed to add FEC %s upon config", buf); + return -1; + } + + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Add fec %s label %u", buf, in_label); + } else { + fec->flags |= FEC_FLAG_CONFIGURED; + if (fec->label == in_label) + /* Duplicate config */ + return 0; + + /* Label change, update clients. */ + old_label = fec->label; + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Update fec %s new label %u", buf, in_label); + + fec->label = in_label; + fec_update_clients(fec); + + /* Update label forwarding entries appropriately */ + ret = fec_change_update_lsp(zvrf, fec, old_label); + } + + return ret; } /* @@ -2158,218 +2022,210 @@ zebra_mpls_static_fec_add (struct zebra_vrf *zvrf, struct prefix *p, * Note: Upon delete of static binding, if label index exists for this FEC, * client may need to be updated with derived label. */ -int -zebra_mpls_static_fec_del (struct zebra_vrf *zvrf, struct prefix *p) -{ - struct route_table *table; - zebra_fec_t *fec; - mpls_label_t old_label; - char buf[BUFSIZ]; - - table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))]; - if (!table) - return -1; - - fec = fec_find (table, p); - if (!fec) - { - prefix2str(p, buf, BUFSIZ); - zlog_err("Failed to find FEC %s upon delete", buf); - return -1; - } - - if (IS_ZEBRA_DEBUG_MPLS) - { - prefix2str(p, buf, BUFSIZ); - zlog_debug ("Delete fec %s label index %u", - buf, fec->label_index); - } - - old_label = fec->label; - fec->flags &= ~FEC_FLAG_CONFIGURED; - fec->label = MPLS_INVALID_LABEL; - - /* If no client exists, just delete the FEC. */ - if (list_isempty(fec->client_list)) - { - fec_del (fec); - return 0; - } - - /* Derive the local label (from label index) or reset it. */ - fec_derive_label_from_index (zvrf, fec); - - /* If there is a label change, update clients. */ - if (fec->label == old_label) - return 0; - fec_update_clients (fec); - - /* Update label forwarding entries appropriately */ - return fec_change_update_lsp (zvrf, fec, old_label); +int zebra_mpls_static_fec_del(struct zebra_vrf *zvrf, struct prefix *p) +{ + struct route_table *table; + zebra_fec_t *fec; + mpls_label_t old_label; + char buf[BUFSIZ]; + + table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))]; + if (!table) + return -1; + + fec = fec_find(table, p); + if (!fec) { + prefix2str(p, buf, BUFSIZ); + zlog_err("Failed to find FEC %s upon delete", buf); + return -1; + } + + if (IS_ZEBRA_DEBUG_MPLS) { + prefix2str(p, buf, BUFSIZ); + zlog_debug("Delete fec %s label index %u", buf, + fec->label_index); + } + + old_label = fec->label; + fec->flags &= ~FEC_FLAG_CONFIGURED; + fec->label = MPLS_INVALID_LABEL; + + /* If no client exists, just delete the FEC. */ + if (list_isempty(fec->client_list)) { + fec_del(fec); + return 0; + } + + /* Derive the local label (from label index) or reset it. */ + fec_derive_label_from_index(zvrf, fec); + + /* If there is a label change, update clients. */ + if (fec->label == old_label) + return 0; + fec_update_clients(fec); + + /* Update label forwarding entries appropriately */ + return fec_change_update_lsp(zvrf, fec, old_label); } /* * Display MPLS FEC to label binding configuration (VTY command handler). */ -int -zebra_mpls_write_fec_config (struct vty *vty, struct zebra_vrf *zvrf) +int zebra_mpls_write_fec_config(struct vty *vty, struct zebra_vrf *zvrf) { - struct route_node *rn; - int af; - zebra_fec_t *fec; - char buf[BUFSIZ]; - int write = 0; + struct route_node *rn; + int af; + zebra_fec_t *fec; + char buf[BUFSIZ]; + int write = 0; - for (af = AFI_IP; af < AFI_MAX; af++) - { - if (zvrf->fec_table[af] == NULL) - continue; + for (af = AFI_IP; af < AFI_MAX; af++) { + if (zvrf->fec_table[af] == NULL) + continue; - for (rn = route_top(zvrf->fec_table[af]); rn; rn = route_next(rn)) - { - if (!rn->info) - continue; + for (rn = route_top(zvrf->fec_table[af]); rn; + rn = route_next(rn)) { + if (!rn->info) + continue; - char lstr[BUFSIZ]; - fec = rn->info; + char lstr[BUFSIZ]; + fec = rn->info; - if (!(fec->flags & FEC_FLAG_CONFIGURED)) - continue; + if (!(fec->flags & FEC_FLAG_CONFIGURED)) + continue; - write = 1; - prefix2str(&rn->p, buf, BUFSIZ); - vty_out (vty, "mpls label bind %s %s\n", buf, - label2str(fec->label, lstr, BUFSIZ)); - } - } + write = 1; + prefix2str(&rn->p, buf, BUFSIZ); + vty_out(vty, "mpls label bind %s %s\n", buf, + label2str(fec->label, lstr, BUFSIZ)); + } + } - return write; + return write; } /* * Display MPLS FEC to label binding (VTY command handler). */ -void -zebra_mpls_print_fec_table (struct vty *vty, struct zebra_vrf *zvrf) +void zebra_mpls_print_fec_table(struct vty *vty, struct zebra_vrf *zvrf) { - struct route_node *rn; - int af; + struct route_node *rn; + int af; - for (af = AFI_IP; af < AFI_MAX; af++) - { - if (zvrf->fec_table[af] == NULL) - continue; + for (af = AFI_IP; af < AFI_MAX; af++) { + if (zvrf->fec_table[af] == NULL) + continue; - for (rn = route_top(zvrf->fec_table[af]); rn; rn = route_next(rn)) - { - if (!rn->info) - continue; - fec_print (rn->info, vty); - } - } + for (rn = route_top(zvrf->fec_table[af]); rn; + rn = route_next(rn)) { + if (!rn->info) + continue; + fec_print(rn->info, vty); + } + } } /* * Display MPLS FEC to label binding for a specific FEC (VTY command handler). */ -void -zebra_mpls_print_fec (struct vty *vty, struct zebra_vrf *zvrf, struct prefix *p) +void zebra_mpls_print_fec(struct vty *vty, struct zebra_vrf *zvrf, + struct prefix *p) { - struct route_table *table; - struct route_node *rn; + struct route_table *table; + struct route_node *rn; - table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))]; - if (!table) - return; + table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))]; + if (!table) + return; - apply_mask (p); - rn = route_node_lookup(table, p); - if (!rn) - return; + apply_mask(p); + rn = route_node_lookup(table, p); + if (!rn) + return; - route_unlock_node(rn); - if (!rn->info) - return; + route_unlock_node(rn); + if (!rn->info) + return; - fec_print (rn->info, vty); + fec_print(rn->info, vty); } /* * Install/uninstall a FEC-To-NHLFE (FTN) binding. */ -int -mpls_ftn_update (int add, struct zebra_vrf *zvrf, enum lsp_types_t type, - struct prefix *prefix, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex, u_int8_t distance, - mpls_label_t out_label) -{ - struct route_table *table; - struct route_node *rn; - struct route_entry *re; - struct nexthop *nexthop; - - /* Lookup table. */ - table = zebra_vrf_table (family2afi(prefix->family), SAFI_UNICAST, zvrf_id (zvrf)); - if (! table) - return -1; - - /* Lookup existing route */ - rn = route_node_get (table, prefix); - RNODE_FOREACH_RE (rn, re) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - if (re->distance == distance) - break; - } - - if (re == NULL) - return -1; - - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - { - switch (nexthop->type) +int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type, + struct prefix *prefix, enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex, u_int8_t distance, + mpls_label_t out_label) +{ + struct route_table *table; + struct route_node *rn; + struct route_entry *re; + struct nexthop *nexthop; + + /* Lookup table. */ + table = zebra_vrf_table(family2afi(prefix->family), SAFI_UNICAST, + zvrf_id(zvrf)); + if (!table) + return -1; + + /* Lookup existing route */ + rn = route_node_get(table, prefix); + RNODE_FOREACH_RE(rn, re) { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - if (gtype != NEXTHOP_TYPE_IPV4 && gtype != NEXTHOP_TYPE_IPV4_IFINDEX) - continue; - if (! IPV4_ADDR_SAME (&nexthop->gate.ipv4, &gate->ipv4)) - continue; - if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX && - nexthop->ifindex != ifindex) - continue; - goto found; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - if (gtype != NEXTHOP_TYPE_IPV6 && gtype != NEXTHOP_TYPE_IPV6_IFINDEX) - continue; - if (! IPV6_ADDR_SAME (&nexthop->gate.ipv6, &gate->ipv6)) - continue; - if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX && - nexthop->ifindex != ifindex) - continue; - goto found; - default: - break; + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + if (re->distance == distance) + break; } - } - /* nexthop not found */ - return -1; - found: - if (add && nexthop->nh_label_type == ZEBRA_LSP_NONE) - nexthop_add_labels (nexthop, type, 1, &out_label); - else if (!add && nexthop->nh_label_type == type) - nexthop_del_labels (nexthop); - else - return 0; + if (re == NULL) + return -1; + + for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) { + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + if (gtype != NEXTHOP_TYPE_IPV4 + && gtype != NEXTHOP_TYPE_IPV4_IFINDEX) + continue; + if (!IPV4_ADDR_SAME(&nexthop->gate.ipv4, &gate->ipv4)) + continue; + if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX + && nexthop->ifindex != ifindex) + continue; + goto found; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + if (gtype != NEXTHOP_TYPE_IPV6 + && gtype != NEXTHOP_TYPE_IPV6_IFINDEX) + continue; + if (!IPV6_ADDR_SAME(&nexthop->gate.ipv6, &gate->ipv6)) + continue; + if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX + && nexthop->ifindex != ifindex) + continue; + goto found; + default: + break; + } + } + /* nexthop not found */ + return -1; + +found: + if (add && nexthop->nh_label_type == ZEBRA_LSP_NONE) + nexthop_add_labels(nexthop, type, 1, &out_label); + else if (!add && nexthop->nh_label_type == type) + nexthop_del_labels(nexthop); + else + return 0; - SET_FLAG (re->status, ROUTE_ENTRY_CHANGED); - SET_FLAG (re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); - rib_queue_add (rn); + SET_FLAG(re->status, ROUTE_ENTRY_CHANGED); + SET_FLAG(re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); + rib_queue_add(rn); - return 0; + return 0; } /* @@ -2377,197 +2233,185 @@ mpls_ftn_update (int add, struct zebra_vrf *zvrf, enum lsp_types_t type, * a new LSP entry or a new NHLFE for an existing in-label or an update of * the out-label for an existing NHLFE (update case). */ -int -mpls_lsp_install (struct zebra_vrf *zvrf, enum lsp_types_t type, - mpls_label_t in_label, mpls_label_t out_label, - enum nexthop_types_t gtype, union g_addr *gate, - ifindex_t ifindex) -{ - struct hash *lsp_table; - zebra_ile_t tmp_ile; - zebra_lsp_t *lsp; - zebra_nhlfe_t *nhlfe; - char buf[BUFSIZ]; - - /* Lookup table. */ - lsp_table = zvrf->lsp_table; - if (!lsp_table) - return -1; - - /* If entry is present, exit. */ - tmp_ile.in_label = in_label; - lsp = hash_get (lsp_table, &tmp_ile, lsp_alloc); - if (!lsp) - return -1; - nhlfe = nhlfe_find (lsp, type, gtype, gate, ifindex); - if (nhlfe) - { - struct nexthop *nh = nhlfe->nexthop; - - assert (nh); - assert (nh->nh_label); - - /* Clear deleted flag (in case it was set) */ - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED); - if (nh->nh_label->label[0] == out_label) - /* No change */ - return 0; - - if (IS_ZEBRA_DEBUG_MPLS) - { - nhlfe2str (nhlfe, buf, BUFSIZ); - zlog_debug ("LSP in-label %u type %d nexthop %s " - "out-label changed to %u (old %u)", - in_label, type, buf, - out_label, nh->nh_label->label[0]); - } - - /* Update out label, trigger processing. */ - nh->nh_label->label[0] = out_label; - } - else - { - /* Add LSP entry to this nexthop */ - nhlfe = nhlfe_add (lsp, type, gtype, gate, ifindex, out_label); - if (!nhlfe) - return -1; - - if (IS_ZEBRA_DEBUG_MPLS) - { - nhlfe2str (nhlfe, buf, BUFSIZ); - zlog_debug ("Add LSP in-label %u type %d nexthop %s " - "out-label %u", in_label, type, buf, out_label); - } - - lsp->addr_family = NHLFE_FAMILY (nhlfe); - } - - /* Mark NHLFE, queue LSP for processing. */ - SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); - if (lsp_processq_add (lsp)) - return -1; - - return 0; +int mpls_lsp_install(struct zebra_vrf *zvrf, enum lsp_types_t type, + mpls_label_t in_label, mpls_label_t out_label, + enum nexthop_types_t gtype, union g_addr *gate, + ifindex_t ifindex) +{ + struct hash *lsp_table; + zebra_ile_t tmp_ile; + zebra_lsp_t *lsp; + zebra_nhlfe_t *nhlfe; + char buf[BUFSIZ]; + + /* Lookup table. */ + lsp_table = zvrf->lsp_table; + if (!lsp_table) + return -1; + + /* If entry is present, exit. */ + tmp_ile.in_label = in_label; + lsp = hash_get(lsp_table, &tmp_ile, lsp_alloc); + if (!lsp) + return -1; + nhlfe = nhlfe_find(lsp, type, gtype, gate, ifindex); + if (nhlfe) { + struct nexthop *nh = nhlfe->nexthop; + + assert(nh); + assert(nh->nh_label); + + /* Clear deleted flag (in case it was set) */ + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED); + if (nh->nh_label->label[0] == out_label) + /* No change */ + return 0; + + if (IS_ZEBRA_DEBUG_MPLS) { + nhlfe2str(nhlfe, buf, BUFSIZ); + zlog_debug( + "LSP in-label %u type %d nexthop %s " + "out-label changed to %u (old %u)", + in_label, type, buf, out_label, + nh->nh_label->label[0]); + } + + /* Update out label, trigger processing. */ + nh->nh_label->label[0] = out_label; + } else { + /* Add LSP entry to this nexthop */ + nhlfe = nhlfe_add(lsp, type, gtype, gate, ifindex, out_label); + if (!nhlfe) + return -1; + + if (IS_ZEBRA_DEBUG_MPLS) { + nhlfe2str(nhlfe, buf, BUFSIZ); + zlog_debug( + "Add LSP in-label %u type %d nexthop %s " + "out-label %u", + in_label, type, buf, out_label); + } + + lsp->addr_family = NHLFE_FAMILY(nhlfe); + } + + /* Mark NHLFE, queue LSP for processing. */ + SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + if (lsp_processq_add(lsp)) + return -1; + + return 0; } /* * Uninstall a particular NHLFE in the forwarding table. If this is * the only NHLFE, the entire LSP forwarding entry has to be deleted. */ -int -mpls_lsp_uninstall (struct zebra_vrf *zvrf, enum lsp_types_t type, - mpls_label_t in_label, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex) -{ - struct hash *lsp_table; - zebra_ile_t tmp_ile; - zebra_lsp_t *lsp; - zebra_nhlfe_t *nhlfe; - char buf[BUFSIZ]; - - /* Lookup table. */ - lsp_table = zvrf->lsp_table; - if (!lsp_table) - return -1; - - /* If entry is not present, exit. */ - tmp_ile.in_label = in_label; - lsp = hash_lookup (lsp_table, &tmp_ile); - if (!lsp) - return 0; - nhlfe = nhlfe_find (lsp, type, gtype, gate, ifindex); - if (!nhlfe) - return 0; - - if (IS_ZEBRA_DEBUG_MPLS) - { - nhlfe2str (nhlfe, buf, BUFSIZ); - zlog_debug ("Del LSP in-label %u type %d nexthop %s flags 0x%x", - in_label, type, buf, nhlfe->flags); - } - - /* Mark NHLFE for delete or directly delete, as appropriate. */ - if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)) - { - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED); - SET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED); - if (lsp_processq_add (lsp)) - return -1; - } - else - { - nhlfe_del (nhlfe); - - /* Free LSP entry if no other NHLFEs and not scheduled. */ - if (!lsp->nhlfe_list && - !CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED)) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Free LSP in-label %u flags 0x%x", - lsp->ile.in_label, lsp->flags); - - lsp = hash_release(lsp_table, &lsp->ile); - if (lsp) - XFREE(MTYPE_LSP, lsp); - } - } - return 0; +int mpls_lsp_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type, + mpls_label_t in_label, enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex) +{ + struct hash *lsp_table; + zebra_ile_t tmp_ile; + zebra_lsp_t *lsp; + zebra_nhlfe_t *nhlfe; + char buf[BUFSIZ]; + + /* Lookup table. */ + lsp_table = zvrf->lsp_table; + if (!lsp_table) + return -1; + + /* If entry is not present, exit. */ + tmp_ile.in_label = in_label; + lsp = hash_lookup(lsp_table, &tmp_ile); + if (!lsp) + return 0; + nhlfe = nhlfe_find(lsp, type, gtype, gate, ifindex); + if (!nhlfe) + return 0; + + if (IS_ZEBRA_DEBUG_MPLS) { + nhlfe2str(nhlfe, buf, BUFSIZ); + zlog_debug("Del LSP in-label %u type %d nexthop %s flags 0x%x", + in_label, type, buf, nhlfe->flags); + } + + /* Mark NHLFE for delete or directly delete, as appropriate. */ + if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)) { + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED); + SET_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED); + if (lsp_processq_add(lsp)) + return -1; + } else { + nhlfe_del(nhlfe); + + /* Free LSP entry if no other NHLFEs and not scheduled. */ + if (!lsp->nhlfe_list + && !CHECK_FLAG(lsp->flags, LSP_FLAG_SCHEDULED)) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Free LSP in-label %u flags 0x%x", + lsp->ile.in_label, lsp->flags); + + lsp = hash_release(lsp_table, &lsp->ile); + if (lsp) + XFREE(MTYPE_LSP, lsp); + } + } + return 0; } /* * Uninstall all LDP NHLFEs for a particular LSP forwarding entry. * If no other NHLFEs exist, the entry would be deleted. */ -void -mpls_ldp_lsp_uninstall_all (struct hash_backet *backet, void *ctxt) +void mpls_ldp_lsp_uninstall_all(struct hash_backet *backet, void *ctxt) { - zebra_lsp_t *lsp; - struct hash *lsp_table; + zebra_lsp_t *lsp; + struct hash *lsp_table; - lsp = (zebra_lsp_t *) backet->data; - if (!lsp || !lsp->nhlfe_list) - return; + lsp = (zebra_lsp_t *)backet->data; + if (!lsp || !lsp->nhlfe_list) + return; - lsp_table = ctxt; - if (!lsp_table) - return; + lsp_table = ctxt; + if (!lsp_table) + return; - mpls_lsp_uninstall_all (lsp_table, lsp, ZEBRA_LSP_LDP); + mpls_lsp_uninstall_all(lsp_table, lsp, ZEBRA_LSP_LDP); } /* * Uninstall all LDP FEC-To-NHLFE (FTN) bindings of the given address-family. */ -void -mpls_ldp_ftn_uninstall_all (struct zebra_vrf *zvrf, int afi) -{ - struct route_table *table; - struct route_node *rn; - struct route_entry *re; - struct nexthop *nexthop; - int update; - - /* Process routes of interested address-families. */ - table = zebra_vrf_table (afi, SAFI_UNICAST, zvrf_id (zvrf)); - if (!table) - return; - - for (rn = route_top (table); rn; rn = route_next (rn)) - { - update = 0; - RNODE_FOREACH_RE (rn, re) - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - if (nexthop->nh_label_type == ZEBRA_LSP_LDP) - { - nexthop_del_labels (nexthop); - SET_FLAG (re->status, ROUTE_ENTRY_CHANGED); - SET_FLAG (re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); - update = 1; - } - - if (update) - rib_queue_add (rn); - } +void mpls_ldp_ftn_uninstall_all(struct zebra_vrf *zvrf, int afi) +{ + struct route_table *table; + struct route_node *rn; + struct route_entry *re; + struct nexthop *nexthop; + int update; + + /* Process routes of interested address-families. */ + table = zebra_vrf_table(afi, SAFI_UNICAST, zvrf_id(zvrf)); + if (!table) + return; + + for (rn = route_top(table); rn; rn = route_next(rn)) { + update = 0; + RNODE_FOREACH_RE(rn, re) + for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) + if (nexthop->nh_label_type == ZEBRA_LSP_LDP) { + nexthop_del_labels(nexthop); + SET_FLAG(re->status, ROUTE_ENTRY_CHANGED); + SET_FLAG(re->status, + ROUTE_ENTRY_NEXTHOPS_CHANGED); + update = 1; + } + + if (update) + rib_queue_add(rn); + } } #if defined(HAVE_CUMULUS) @@ -2577,54 +2421,51 @@ mpls_ldp_ftn_uninstall_all (struct zebra_vrf *zvrf, int afi) * be consistent - i.e., all paths either do a swap or do PHP. This is due * to current HW restrictions. */ -int -zebra_mpls_lsp_label_consistent (struct zebra_vrf *zvrf, mpls_label_t in_label, - mpls_label_t out_label, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex) -{ - struct hash *slsp_table; - zebra_ile_t tmp_ile; - zebra_slsp_t *slsp; - zebra_snhlfe_t *snhlfe; - - /* Lookup table. */ - slsp_table = zvrf->slsp_table; - if (!slsp_table) - return 0; - - /* If entry is not present, exit. */ - tmp_ile.in_label = in_label; - slsp = hash_lookup (slsp_table, &tmp_ile); - if (!slsp) - return 1; - - snhlfe = snhlfe_find (slsp, gtype, gate, ifindex); - if (snhlfe) - { - if (snhlfe->out_label == out_label) - return 1; - - /* If not only NHLFE, cannot allow label change. */ - if (snhlfe != slsp->snhlfe_list || - snhlfe->next) - return 0; - } - else - { - /* If other NHLFEs exist, label operation must match. */ - if (slsp->snhlfe_list) - { - int cur_op, new_op; - - cur_op = (slsp->snhlfe_list->out_label == MPLS_IMP_NULL_LABEL); - new_op = (out_label == MPLS_IMP_NULL_LABEL); - if (cur_op != new_op) - return 0; - } - } - - /* Label values are good. */ - return 1; +int zebra_mpls_lsp_label_consistent(struct zebra_vrf *zvrf, + mpls_label_t in_label, + mpls_label_t out_label, + enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex) +{ + struct hash *slsp_table; + zebra_ile_t tmp_ile; + zebra_slsp_t *slsp; + zebra_snhlfe_t *snhlfe; + + /* Lookup table. */ + slsp_table = zvrf->slsp_table; + if (!slsp_table) + return 0; + + /* If entry is not present, exit. */ + tmp_ile.in_label = in_label; + slsp = hash_lookup(slsp_table, &tmp_ile); + if (!slsp) + return 1; + + snhlfe = snhlfe_find(slsp, gtype, gate, ifindex); + if (snhlfe) { + if (snhlfe->out_label == out_label) + return 1; + + /* If not only NHLFE, cannot allow label change. */ + if (snhlfe != slsp->snhlfe_list || snhlfe->next) + return 0; + } else { + /* If other NHLFEs exist, label operation must match. */ + if (slsp->snhlfe_list) { + int cur_op, new_op; + + cur_op = (slsp->snhlfe_list->out_label + == MPLS_IMP_NULL_LABEL); + new_op = (out_label == MPLS_IMP_NULL_LABEL); + if (cur_op != new_op) + return 0; + } + } + + /* Label values are good. */ + return 1; } #endif /* HAVE_CUMULUS */ @@ -2635,64 +2476,61 @@ zebra_mpls_lsp_label_consistent (struct zebra_vrf *zvrf, mpls_label_t in_label, * Note: The label operation (swap or PHP) is common for the LSP entry (all * NHLFEs). */ -int -zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label, - mpls_label_t out_label, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex) -{ - struct hash *slsp_table; - zebra_ile_t tmp_ile; - zebra_slsp_t *slsp; - zebra_snhlfe_t *snhlfe; - char buf[BUFSIZ]; - - /* Lookup table. */ - slsp_table = zvrf->slsp_table; - if (!slsp_table) - return -1; - - /* If entry is present, exit. */ - tmp_ile.in_label = in_label; - slsp = hash_get (slsp_table, &tmp_ile, slsp_alloc); - if (!slsp) - return -1; - snhlfe = snhlfe_find (slsp, gtype, gate, ifindex); - if (snhlfe) - { - if (snhlfe->out_label == out_label) - /* No change */ - return 0; - - if (IS_ZEBRA_DEBUG_MPLS) - { - snhlfe2str (snhlfe, buf, BUFSIZ); - zlog_debug ("Upd static LSP in-label %u nexthop %s " - "out-label %u (old %u)", - in_label, buf, out_label, snhlfe->out_label); - } - snhlfe->out_label = out_label; - } - else - { - /* Add static LSP entry to this nexthop */ - snhlfe = snhlfe_add (slsp, gtype, gate, ifindex, out_label); - if (!snhlfe) - return -1; - - if (IS_ZEBRA_DEBUG_MPLS) - { - snhlfe2str (snhlfe, buf, BUFSIZ); - zlog_debug ("Add static LSP in-label %u nexthop %s out-label %u", - in_label, buf, out_label); - } - } - - /* (Re)Install LSP in the main table. */ - if (mpls_lsp_install (zvrf, ZEBRA_LSP_STATIC, in_label, out_label, gtype, - gate, ifindex)) - return -1; - - return 0; +int zebra_mpls_static_lsp_add(struct zebra_vrf *zvrf, mpls_label_t in_label, + mpls_label_t out_label, + enum nexthop_types_t gtype, union g_addr *gate, + ifindex_t ifindex) +{ + struct hash *slsp_table; + zebra_ile_t tmp_ile; + zebra_slsp_t *slsp; + zebra_snhlfe_t *snhlfe; + char buf[BUFSIZ]; + + /* Lookup table. */ + slsp_table = zvrf->slsp_table; + if (!slsp_table) + return -1; + + /* If entry is present, exit. */ + tmp_ile.in_label = in_label; + slsp = hash_get(slsp_table, &tmp_ile, slsp_alloc); + if (!slsp) + return -1; + snhlfe = snhlfe_find(slsp, gtype, gate, ifindex); + if (snhlfe) { + if (snhlfe->out_label == out_label) + /* No change */ + return 0; + + if (IS_ZEBRA_DEBUG_MPLS) { + snhlfe2str(snhlfe, buf, BUFSIZ); + zlog_debug( + "Upd static LSP in-label %u nexthop %s " + "out-label %u (old %u)", + in_label, buf, out_label, snhlfe->out_label); + } + snhlfe->out_label = out_label; + } else { + /* Add static LSP entry to this nexthop */ + snhlfe = snhlfe_add(slsp, gtype, gate, ifindex, out_label); + if (!snhlfe) + return -1; + + if (IS_ZEBRA_DEBUG_MPLS) { + snhlfe2str(snhlfe, buf, BUFSIZ); + zlog_debug( + "Add static LSP in-label %u nexthop %s out-label %u", + in_label, buf, out_label); + } + } + + /* (Re)Install LSP in the main table. */ + if (mpls_lsp_install(zvrf, ZEBRA_LSP_STATIC, in_label, out_label, gtype, + gate, ifindex)) + return -1; + + return 0; } /* @@ -2702,71 +2540,66 @@ zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label, * NOTE: Delete of the only NHLFE will also end up deleting the entire * LSP configuration. */ -int -zebra_mpls_static_lsp_del (struct zebra_vrf *zvrf, mpls_label_t in_label, - enum nexthop_types_t gtype, union g_addr *gate, - ifindex_t ifindex) -{ - struct hash *slsp_table; - zebra_ile_t tmp_ile; - zebra_slsp_t *slsp; - zebra_snhlfe_t *snhlfe; - - /* Lookup table. */ - slsp_table = zvrf->slsp_table; - if (!slsp_table) - return -1; - - /* If entry is not present, exit. */ - tmp_ile.in_label = in_label; - slsp = hash_lookup (slsp_table, &tmp_ile); - if (!slsp) - return 0; - - /* Is it delete of entire LSP or a specific NHLFE? */ - if (gtype == NEXTHOP_TYPE_BLACKHOLE) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("Del static LSP in-label %u", in_label); - - /* Uninstall entire LSP from the main table. */ - mpls_static_lsp_uninstall_all (zvrf, in_label); - - /* Delete all static NHLFEs */ - snhlfe_del_all (slsp); - } - else - { - /* Find specific NHLFE, exit if not found. */ - snhlfe = snhlfe_find (slsp, gtype, gate, ifindex); - if (!snhlfe) - return 0; - - if (IS_ZEBRA_DEBUG_MPLS) - { - char buf[BUFSIZ]; - snhlfe2str (snhlfe, buf, BUFSIZ); - zlog_debug ("Del static LSP in-label %u nexthop %s", - in_label, buf); - } - - /* Uninstall LSP from the main table. */ - mpls_lsp_uninstall (zvrf, ZEBRA_LSP_STATIC, in_label, gtype, gate, - ifindex); - - /* Delete static LSP NHLFE */ - snhlfe_del (snhlfe); - } - - /* Remove entire static LSP entry if no NHLFE - valid in either case above. */ - if (!slsp->snhlfe_list) - { - slsp = hash_release(slsp_table, &tmp_ile); - if (slsp) - XFREE(MTYPE_SLSP, slsp); - } - - return 0; +int zebra_mpls_static_lsp_del(struct zebra_vrf *zvrf, mpls_label_t in_label, + enum nexthop_types_t gtype, union g_addr *gate, + ifindex_t ifindex) +{ + struct hash *slsp_table; + zebra_ile_t tmp_ile; + zebra_slsp_t *slsp; + zebra_snhlfe_t *snhlfe; + + /* Lookup table. */ + slsp_table = zvrf->slsp_table; + if (!slsp_table) + return -1; + + /* If entry is not present, exit. */ + tmp_ile.in_label = in_label; + slsp = hash_lookup(slsp_table, &tmp_ile); + if (!slsp) + return 0; + + /* Is it delete of entire LSP or a specific NHLFE? */ + if (gtype == NEXTHOP_TYPE_BLACKHOLE) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug("Del static LSP in-label %u", in_label); + + /* Uninstall entire LSP from the main table. */ + mpls_static_lsp_uninstall_all(zvrf, in_label); + + /* Delete all static NHLFEs */ + snhlfe_del_all(slsp); + } else { + /* Find specific NHLFE, exit if not found. */ + snhlfe = snhlfe_find(slsp, gtype, gate, ifindex); + if (!snhlfe) + return 0; + + if (IS_ZEBRA_DEBUG_MPLS) { + char buf[BUFSIZ]; + snhlfe2str(snhlfe, buf, BUFSIZ); + zlog_debug("Del static LSP in-label %u nexthop %s", + in_label, buf); + } + + /* Uninstall LSP from the main table. */ + mpls_lsp_uninstall(zvrf, ZEBRA_LSP_STATIC, in_label, gtype, + gate, ifindex); + + /* Delete static LSP NHLFE */ + snhlfe_del(snhlfe); + } + + /* Remove entire static LSP entry if no NHLFE - valid in either case + * above. */ + if (!slsp->snhlfe_list) { + slsp = hash_release(slsp_table, &tmp_ile); + if (slsp) + XFREE(MTYPE_SLSP, slsp); + } + + return 0; } /* @@ -2774,200 +2607,192 @@ zebra_mpls_static_lsp_del (struct zebra_vrf *zvrf, mpls_label_t in_label, * Called upon changes that may affect one or more of them such as * interface or nexthop state changes. */ -void -zebra_mpls_lsp_schedule (struct zebra_vrf *zvrf) +void zebra_mpls_lsp_schedule(struct zebra_vrf *zvrf) { - if (!zvrf) - return; - hash_iterate(zvrf->lsp_table, lsp_schedule, NULL); + if (!zvrf) + return; + hash_iterate(zvrf->lsp_table, lsp_schedule, NULL); } /* * Display MPLS label forwarding table for a specific LSP * (VTY command handler). */ -void -zebra_mpls_print_lsp (struct vty *vty, struct zebra_vrf *zvrf, mpls_label_t label, - u_char use_json) +void zebra_mpls_print_lsp(struct vty *vty, struct zebra_vrf *zvrf, + mpls_label_t label, u_char use_json) { - struct hash *lsp_table; - zebra_lsp_t *lsp; - zebra_ile_t tmp_ile; - json_object *json = NULL; + struct hash *lsp_table; + zebra_lsp_t *lsp; + zebra_ile_t tmp_ile; + json_object *json = NULL; - /* Lookup table. */ - lsp_table = zvrf->lsp_table; - if (!lsp_table) - return; + /* Lookup table. */ + lsp_table = zvrf->lsp_table; + if (!lsp_table) + return; - /* If entry is not present, exit. */ - tmp_ile.in_label = label; - lsp = hash_lookup (lsp_table, &tmp_ile); - if (!lsp) - return; + /* If entry is not present, exit. */ + tmp_ile.in_label = label; + lsp = hash_lookup(lsp_table, &tmp_ile); + if (!lsp) + return; - if (use_json) - { - json = lsp_json(lsp); - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - lsp_print (lsp, (void *)vty); + if (use_json) { + json = lsp_json(lsp); + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else + lsp_print(lsp, (void *)vty); } /* * Display MPLS label forwarding table (VTY command handler). */ -void -zebra_mpls_print_lsp_table (struct vty *vty, struct zebra_vrf *zvrf, - u_char use_json) -{ - char buf[BUFSIZ]; - json_object *json = NULL; - zebra_lsp_t *lsp = NULL; - zebra_nhlfe_t *nhlfe = NULL; - struct nexthop *nexthop = NULL; - struct listnode *node = NULL; - struct list *lsp_list = hash_get_sorted_list(zvrf->lsp_table, lsp_cmp); - - if (use_json) - { - json = json_object_new_object(); - - for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp)) - json_object_object_add(json, label2str(lsp->ile.in_label, buf, BUFSIZ), - lsp_json(lsp)); - - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - else - { - vty_out (vty, " Inbound Outbound\n"); - vty_out (vty, " Label Type Nexthop Label\n"); - vty_out (vty, "-------- ------- --------------- --------\n"); - - for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp)) - { - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - vty_out (vty, "%8d %7s ", lsp->ile.in_label, nhlfe_type2str(nhlfe->type)); - nexthop = nhlfe->nexthop; - - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - vty_out (vty, "%15s", inet_ntoa (nexthop->gate.ipv4)); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - vty_out (vty, "%15s", inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); - break; - default: - break; - } - - vty_out (vty, " %8d\n", nexthop->nh_label->label[0]); - } - } - - vty_out (vty, "\n"); - } - - list_delete (lsp_list); +void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf, + u_char use_json) +{ + char buf[BUFSIZ]; + json_object *json = NULL; + zebra_lsp_t *lsp = NULL; + zebra_nhlfe_t *nhlfe = NULL; + struct nexthop *nexthop = NULL; + struct listnode *node = NULL; + struct list *lsp_list = hash_get_sorted_list(zvrf->lsp_table, lsp_cmp); + + if (use_json) { + json = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp)) + json_object_object_add( + json, label2str(lsp->ile.in_label, buf, BUFSIZ), + lsp_json(lsp)); + + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else { + vty_out(vty, " Inbound Outbound\n"); + vty_out(vty, " Label Type Nexthop Label\n"); + vty_out(vty, "-------- ------- --------------- --------\n"); + + for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp)) { + for (nhlfe = lsp->nhlfe_list; nhlfe; + nhlfe = nhlfe->next) { + vty_out(vty, "%8d %7s ", lsp->ile.in_label, + nhlfe_type2str(nhlfe->type)); + nexthop = nhlfe->nexthop; + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + vty_out(vty, "%15s", + inet_ntoa(nexthop->gate.ipv4)); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + vty_out(vty, "%15s", + inet_ntop(AF_INET6, + &nexthop->gate.ipv6, + buf, BUFSIZ)); + break; + default: + break; + } + + vty_out(vty, " %8d\n", + nexthop->nh_label->label[0]); + } + } + + vty_out(vty, "\n"); + } + + list_delete(lsp_list); } /* * Display MPLS LSP configuration of all static LSPs (VTY command handler). */ -int -zebra_mpls_write_lsp_config (struct vty *vty, struct zebra_vrf *zvrf) -{ - zebra_slsp_t *slsp; - zebra_snhlfe_t *snhlfe; - struct listnode *node; - struct list *slsp_list = hash_get_sorted_list(zvrf->slsp_table, slsp_cmp); - - for (ALL_LIST_ELEMENTS_RO(slsp_list, node, slsp)) - { - for (snhlfe = slsp->snhlfe_list; snhlfe; snhlfe = snhlfe->next) - { - char buf[INET6_ADDRSTRLEN]; - char lstr[30]; - - snhlfe2str (snhlfe, buf, BUFSIZ); - switch (snhlfe->out_label) { - case MPLS_V4_EXP_NULL_LABEL: - case MPLS_V6_EXP_NULL_LABEL: - strlcpy(lstr, "explicit-null", sizeof(lstr)); - break; - case MPLS_IMP_NULL_LABEL: - strlcpy(lstr, "implicit-null", sizeof(lstr)); - break; - default: - sprintf(lstr, "%u", snhlfe->out_label); - break; - } - - vty_out (vty, "mpls lsp %u %s %s\n", - slsp->ile.in_label, buf, lstr); - } - } +int zebra_mpls_write_lsp_config(struct vty *vty, struct zebra_vrf *zvrf) +{ + zebra_slsp_t *slsp; + zebra_snhlfe_t *snhlfe; + struct listnode *node; + struct list *slsp_list = + hash_get_sorted_list(zvrf->slsp_table, slsp_cmp); + + for (ALL_LIST_ELEMENTS_RO(slsp_list, node, slsp)) { + for (snhlfe = slsp->snhlfe_list; snhlfe; + snhlfe = snhlfe->next) { + char buf[INET6_ADDRSTRLEN]; + char lstr[30]; + + snhlfe2str(snhlfe, buf, BUFSIZ); + switch (snhlfe->out_label) { + case MPLS_V4_EXP_NULL_LABEL: + case MPLS_V6_EXP_NULL_LABEL: + strlcpy(lstr, "explicit-null", sizeof(lstr)); + break; + case MPLS_IMP_NULL_LABEL: + strlcpy(lstr, "implicit-null", sizeof(lstr)); + break; + default: + sprintf(lstr, "%u", snhlfe->out_label); + break; + } + + vty_out(vty, "mpls lsp %u %s %s\n", slsp->ile.in_label, + buf, lstr); + } + } - list_delete (slsp_list); - return (zvrf->slsp_table->count ? 1 : 0); + list_delete(slsp_list); + return (zvrf->slsp_table->count ? 1 : 0); } /* * Add/update global label block. */ -int -zebra_mpls_label_block_add (struct zebra_vrf *zvrf, u_int32_t start_label, - u_int32_t end_label) +int zebra_mpls_label_block_add(struct zebra_vrf *zvrf, u_int32_t start_label, + u_int32_t end_label) { - zvrf->mpls_srgb.start_label = start_label; - zvrf->mpls_srgb.end_label = end_label; + zvrf->mpls_srgb.start_label = start_label; + zvrf->mpls_srgb.end_label = end_label; - /* Evaluate registered FECs to see if any get a label or not. */ - fec_evaluate (zvrf); - return 0; + /* Evaluate registered FECs to see if any get a label or not. */ + fec_evaluate(zvrf); + return 0; } /* * Delete global label block. */ -int -zebra_mpls_label_block_del (struct zebra_vrf *zvrf) +int zebra_mpls_label_block_del(struct zebra_vrf *zvrf) { - zvrf->mpls_srgb.start_label = MPLS_DEFAULT_MIN_SRGB_LABEL; - zvrf->mpls_srgb.end_label = MPLS_DEFAULT_MAX_SRGB_LABEL; + zvrf->mpls_srgb.start_label = MPLS_DEFAULT_MIN_SRGB_LABEL; + zvrf->mpls_srgb.end_label = MPLS_DEFAULT_MAX_SRGB_LABEL; - /* Process registered FECs to clear their local label, if needed. */ - fec_evaluate (zvrf); - return 0; + /* Process registered FECs to clear their local label, if needed. */ + fec_evaluate(zvrf); + return 0; } /* * Display MPLS global label block configuration (VTY command handler). */ -int -zebra_mpls_write_label_block_config (struct vty *vty, struct zebra_vrf *zvrf) +int zebra_mpls_write_label_block_config(struct vty *vty, struct zebra_vrf *zvrf) { - if (zvrf->mpls_srgb.start_label == 0) - return 0; + if (zvrf->mpls_srgb.start_label == 0) + return 0; - if ((zvrf->mpls_srgb.start_label != MPLS_DEFAULT_MIN_SRGB_LABEL) || - (zvrf->mpls_srgb.end_label != MPLS_DEFAULT_MAX_SRGB_LABEL)) - { - vty_out (vty, "mpls label global-block %u %u\n", - zvrf->mpls_srgb.start_label,zvrf->mpls_srgb.end_label); - } + if ((zvrf->mpls_srgb.start_label != MPLS_DEFAULT_MIN_SRGB_LABEL) + || (zvrf->mpls_srgb.end_label != MPLS_DEFAULT_MAX_SRGB_LABEL)) { + vty_out(vty, "mpls label global-block %u %u\n", + zvrf->mpls_srgb.start_label, zvrf->mpls_srgb.end_label); + } - return 1; + return 1; } /* @@ -2975,48 +2800,44 @@ zebra_mpls_write_label_block_config (struct vty *vty, struct zebra_vrf *zvrf) * entries from the kernel. * NOTE: Currently supported only for default VRF. */ -void -zebra_mpls_close_tables (struct zebra_vrf *zvrf) +void zebra_mpls_close_tables(struct zebra_vrf *zvrf) { - hash_iterate(zvrf->lsp_table, lsp_uninstall_from_kernel, NULL); - hash_clean(zvrf->lsp_table, NULL); - hash_free(zvrf->lsp_table); - hash_clean(zvrf->slsp_table, NULL); - hash_free(zvrf->slsp_table); + hash_iterate(zvrf->lsp_table, lsp_uninstall_from_kernel, NULL); + hash_clean(zvrf->lsp_table, NULL); + hash_free(zvrf->lsp_table); + hash_clean(zvrf->slsp_table, NULL); + hash_free(zvrf->slsp_table); } /* * Allocate MPLS tables for this VRF and do other initialization. * NOTE: Currently supported only for default VRF. */ -void -zebra_mpls_init_tables (struct zebra_vrf *zvrf) +void zebra_mpls_init_tables(struct zebra_vrf *zvrf) { - if (!zvrf) - return; - zvrf->slsp_table = hash_create(label_hash, label_cmp, NULL); - zvrf->lsp_table = hash_create(label_hash, label_cmp, NULL); - zvrf->fec_table[AFI_IP] = route_table_init(); - zvrf->fec_table[AFI_IP6] = route_table_init(); - zvrf->mpls_flags = 0; - zvrf->mpls_srgb.start_label = MPLS_DEFAULT_MIN_SRGB_LABEL; - zvrf->mpls_srgb.end_label = MPLS_DEFAULT_MAX_SRGB_LABEL; + if (!zvrf) + return; + zvrf->slsp_table = hash_create(label_hash, label_cmp, NULL); + zvrf->lsp_table = hash_create(label_hash, label_cmp, NULL); + zvrf->fec_table[AFI_IP] = route_table_init(); + zvrf->fec_table[AFI_IP6] = route_table_init(); + zvrf->mpls_flags = 0; + zvrf->mpls_srgb.start_label = MPLS_DEFAULT_MIN_SRGB_LABEL; + zvrf->mpls_srgb.end_label = MPLS_DEFAULT_MAX_SRGB_LABEL; } /* * Global MPLS initialization. */ -void -zebra_mpls_init (void) +void zebra_mpls_init(void) { - mpls_enabled = 0; + mpls_enabled = 0; - if (mpls_kernel_init () < 0) - { - zlog_warn ("Disabling MPLS support (no kernel support)"); - return; - } + if (mpls_kernel_init() < 0) { + zlog_warn("Disabling MPLS support (no kernel support)"); + return; + } - if (! mpls_processq_init (&zebrad)) - mpls_enabled = 1; + if (!mpls_processq_init(&zebrad)) + mpls_enabled = 1; } diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h index 52b947c06..c8dab3921 100644 --- a/zebra/zebra_mpls.h +++ b/zebra/zebra_mpls.h @@ -39,12 +39,15 @@ #define MPLS_MAX_LABELS 2 /* Maximum # labels that can be pushed. */ -#define NHLFE_FAMILY(nhlfe) \ - (((nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6 || \ - (nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) ? AF_INET6 : AF_INET) +#define NHLFE_FAMILY(nhlfe) \ + (((nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6 \ + || (nhlfe)->nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) \ + ? AF_INET6 \ + : AF_INET) -#define MPLS_LABEL_HELPSTR "Specify label(s) for this route\nOne or more " \ - "labels in the range (16-1048575) separated by '/'\n" +#define MPLS_LABEL_HELPSTR \ + "Specify label(s) for this route\nOne or more " \ + "labels in the range (16-1048575) separated by '/'\n" /* Typedefs */ @@ -58,117 +61,110 @@ typedef struct zebra_fec_t_ zebra_fec_t; /* * (Outgoing) nexthop label forwarding entry configuration */ -struct zebra_snhlfe_t_ -{ - /* Nexthop information */ - enum nexthop_types_t gtype; - union g_addr gate; - char *ifname; - ifindex_t ifindex; +struct zebra_snhlfe_t_ { + /* Nexthop information */ + enum nexthop_types_t gtype; + union g_addr gate; + char *ifname; + ifindex_t ifindex; - /* Out label. */ - mpls_label_t out_label; + /* Out label. */ + mpls_label_t out_label; - /* Backpointer to base entry. */ - zebra_slsp_t *slsp; + /* Backpointer to base entry. */ + zebra_slsp_t *slsp; - /* Pointers to more outgoing information for same in-label */ - zebra_snhlfe_t *next; - zebra_snhlfe_t *prev; + /* Pointers to more outgoing information for same in-label */ + zebra_snhlfe_t *next; + zebra_snhlfe_t *prev; }; /* * (Outgoing) nexthop label forwarding entry */ -struct zebra_nhlfe_t_ -{ - /* Type of entry - static etc. */ - enum lsp_types_t type; +struct zebra_nhlfe_t_ { + /* Type of entry - static etc. */ + enum lsp_types_t type; - /* Nexthop information (with outgoing label) */ - struct nexthop *nexthop; + /* Nexthop information (with outgoing label) */ + struct nexthop *nexthop; - /* Backpointer to base entry. */ - zebra_lsp_t *lsp; + /* Backpointer to base entry. */ + zebra_lsp_t *lsp; - /* Runtime info - flags, pointers etc. */ - u_int32_t flags; + /* Runtime info - flags, pointers etc. */ + u_int32_t flags; #define NHLFE_FLAG_CHANGED (1 << 0) #define NHLFE_FLAG_SELECTED (1 << 1) #define NHLFE_FLAG_MULTIPATH (1 << 2) #define NHLFE_FLAG_DELETED (1 << 3) #define NHLFE_FLAG_INSTALLED (1 << 4) - zebra_nhlfe_t *next; - zebra_nhlfe_t *prev; - u_char distance; + zebra_nhlfe_t *next; + zebra_nhlfe_t *prev; + u_char distance; }; /* * Incoming label entry */ -struct zebra_ile_t_ -{ - mpls_label_t in_label; +struct zebra_ile_t_ { + mpls_label_t in_label; }; /* * Label swap entry static configuration. */ -struct zebra_slsp_t_ -{ - /* Incoming label */ - zebra_ile_t ile; - - /* List of outgoing nexthop static configuration */ - zebra_snhlfe_t *snhlfe_list; +struct zebra_slsp_t_ { + /* Incoming label */ + zebra_ile_t ile; + /* List of outgoing nexthop static configuration */ + zebra_snhlfe_t *snhlfe_list; }; /* * Label swap entry (ile -> list of nhlfes) */ -struct zebra_lsp_t_ -{ - /* Incoming label */ - zebra_ile_t ile; +struct zebra_lsp_t_ { + /* Incoming label */ + zebra_ile_t ile; - /* List of NHLFE, pointer to best and num equal-cost. */ - zebra_nhlfe_t *nhlfe_list; - zebra_nhlfe_t *best_nhlfe; - u_int32_t num_ecmp; + /* List of NHLFE, pointer to best and num equal-cost. */ + zebra_nhlfe_t *nhlfe_list; + zebra_nhlfe_t *best_nhlfe; + u_int32_t num_ecmp; - /* Flags */ - u_int32_t flags; + /* Flags */ + u_int32_t flags; #define LSP_FLAG_SCHEDULED (1 << 0) #define LSP_FLAG_INSTALLED (1 << 1) #define LSP_FLAG_CHANGED (1 << 2) - /* Address-family of NHLFE - saved here for delete. All NHLFEs */ - /* have to be of the same AF */ - u_char addr_family; + /* Address-family of NHLFE - saved here for delete. All NHLFEs */ + /* have to be of the same AF */ + u_char addr_family; }; /* * FEC to label binding. */ -struct zebra_fec_t_ -{ - /* FEC (prefix) */ - struct route_node *rn; +struct zebra_fec_t_ { + /* FEC (prefix) */ + struct route_node *rn; - /* In-label - either statically bound or derived from label block. */ - mpls_label_t label; + /* In-label - either statically bound or derived from label block. */ + mpls_label_t label; - /* Label index (into global label block), if valid */ - u_int32_t label_index; + /* Label index (into global label block), if valid */ + u_int32_t label_index; - /* Flags. */ - u_int32_t flags; + /* Flags. */ + u_int32_t flags; #define FEC_FLAG_CONFIGURED (1 << 0) - /* Clients interested in this FEC. */ - struct list *client_list; + /* Clients interested in this FEC. */ + struct list *client_list; }; /* Function declarations. */ @@ -176,47 +172,42 @@ struct zebra_fec_t_ /* * String to label conversion, labels separated by '/'. */ -int -mpls_str2label (const char *label_str, u_int8_t *num_labels, - mpls_label_t *labels); +int mpls_str2label(const char *label_str, u_int8_t *num_labels, + mpls_label_t *labels); /* * Label to string conversion, labels in string separated by '/'. */ -char * -mpls_label2str (u_int8_t num_labels, mpls_label_t *labels, - char *buf, int len, int pretty); +char *mpls_label2str(u_int8_t num_labels, mpls_label_t *labels, char *buf, + int len, int pretty); /* * Add/update global label block. */ -int -zebra_mpls_label_block_add (struct zebra_vrf *zvrf, u_int32_t start_label, - u_int32_t end_label); +int zebra_mpls_label_block_add(struct zebra_vrf *zvrf, u_int32_t start_label, + u_int32_t end_label); /* * Delete global label block. */ -int -zebra_mpls_label_block_del (struct zebra_vrf *vrf); +int zebra_mpls_label_block_del(struct zebra_vrf *vrf); /* * Display MPLS global label block configuration (VTY command handler). */ -int -zebra_mpls_write_label_block_config (struct vty *vty, struct zebra_vrf *vrf); +int zebra_mpls_write_label_block_config(struct vty *vty, struct zebra_vrf *vrf); /* * Install dynamic LSP entry. */ -int -zebra_mpls_lsp_install (struct zebra_vrf *zvrf, struct route_node *rn, struct route_entry *re); +int zebra_mpls_lsp_install(struct zebra_vrf *zvrf, struct route_node *rn, + struct route_entry *re); /* - * Uninstall dynamic LSP entry, if any. + * Uninstall dynamic LSP entry, if any. */ -int -zebra_mpls_lsp_uninstall (struct zebra_vrf *zvrf, struct route_node *rn, struct route_entry *re); +int zebra_mpls_lsp_uninstall(struct zebra_vrf *zvrf, struct route_node *rn, + struct route_entry *re); /* * Registration from a client for the label binding for a FEC. If a binding @@ -226,24 +217,22 @@ zebra_mpls_lsp_uninstall (struct zebra_vrf *zvrf, struct route_node *rn, struct * label from a locally configured label block (SRGB), if one exists and index * is acceptable. */ -int -zebra_mpls_fec_register (struct zebra_vrf *zvrf, struct prefix *p, - u_int32_t label_index, struct zserv *client); +int zebra_mpls_fec_register(struct zebra_vrf *zvrf, struct prefix *p, + u_int32_t label_index, struct zserv *client); /* * Deregistration from a client for the label binding for a FEC. The FEC * itself is deleted if no other registered clients exist and there is no * label bound to the FEC. */ -int -zebra_mpls_fec_unregister (struct zebra_vrf *zvrf, struct prefix *p, - struct zserv *client); +int zebra_mpls_fec_unregister(struct zebra_vrf *zvrf, struct prefix *p, + struct zserv *client); /* * Cleanup any FECs registered by this client. */ -int -zebra_mpls_cleanup_fecs_for_client (struct zebra_vrf *zvrf, struct zserv *client); +int zebra_mpls_cleanup_fecs_for_client(struct zebra_vrf *zvrf, + struct zserv *client); /* * Return FEC (if any) to which this label is bound. @@ -252,23 +241,21 @@ zebra_mpls_cleanup_fecs_for_client (struct zebra_vrf *zvrf, struct zserv *client * TODO: Currently walks entire table, can optimize later with another * hash.. */ -zebra_fec_t * -zebra_mpls_fec_for_label (struct zebra_vrf *zvrf, mpls_label_t label); +zebra_fec_t *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf, + mpls_label_t label); /* * Inform if specified label is currently bound to a FEC or not. */ -int -zebra_mpls_label_already_bound (struct zebra_vrf *zvrf, mpls_label_t label); +int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, mpls_label_t label); /* * Add static FEC to label binding. If there are clients registered for this * FEC, notify them. If there are labeled routes for this FEC, install the * label forwarding entry. */ -int -zebra_mpls_static_fec_add (struct zebra_vrf *zvrf, struct prefix *p, - mpls_label_t in_label); +int zebra_mpls_static_fec_add(struct zebra_vrf *zvrf, struct prefix *p, + mpls_label_t in_label); /* * Remove static FEC to label binding. If there are no clients registered @@ -276,68 +263,60 @@ zebra_mpls_static_fec_add (struct zebra_vrf *zvrf, struct prefix *p, * Note: Upon delete of static binding, if label index exists for this FEC, * client may need to be updated with derived label. */ -int -zebra_mpls_static_fec_del (struct zebra_vrf *zvrf, struct prefix *p); +int zebra_mpls_static_fec_del(struct zebra_vrf *zvrf, struct prefix *p); /* * Display MPLS FEC to label binding configuration (VTY command handler). */ -int -zebra_mpls_write_fec_config (struct vty *vty, struct zebra_vrf *zvrf); +int zebra_mpls_write_fec_config(struct vty *vty, struct zebra_vrf *zvrf); /* * Display MPLS FEC to label binding (VTY command handler). */ -void -zebra_mpls_print_fec_table (struct vty *vty, struct zebra_vrf *zvrf); +void zebra_mpls_print_fec_table(struct vty *vty, struct zebra_vrf *zvrf); /* * Display MPLS FEC to label binding for a specific FEC (VTY command handler). */ -void -zebra_mpls_print_fec (struct vty *vty, struct zebra_vrf *zvrf, struct prefix *p); +void zebra_mpls_print_fec(struct vty *vty, struct zebra_vrf *zvrf, + struct prefix *p); /* * Install/uninstall a FEC-To-NHLFE (FTN) binding. */ -int -mpls_ftn_update (int add, struct zebra_vrf *zvrf, enum lsp_types_t type, - struct prefix *prefix, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex, u_int8_t distance, - mpls_label_t out_label); +int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type, + struct prefix *prefix, enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex, u_int8_t distance, + mpls_label_t out_label); /* * Install/update a NHLFE for an LSP in the forwarding table. This may be * a new LSP entry or a new NHLFE for an existing in-label or an update of * the out-label for an existing NHLFE (update case). */ -int -mpls_lsp_install (struct zebra_vrf *zvrf, enum lsp_types_t type, - mpls_label_t in_label, mpls_label_t out_label, - enum nexthop_types_t gtype, union g_addr *gate, - ifindex_t ifindex); +int mpls_lsp_install(struct zebra_vrf *zvrf, enum lsp_types_t type, + mpls_label_t in_label, mpls_label_t out_label, + enum nexthop_types_t gtype, union g_addr *gate, + ifindex_t ifindex); /* * Uninstall a particular NHLFE in the forwarding table. If this is * the only NHLFE, the entire LSP forwarding entry has to be deleted. */ -int -mpls_lsp_uninstall (struct zebra_vrf *zvrf, enum lsp_types_t type, - mpls_label_t in_label, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex); +int mpls_lsp_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type, + mpls_label_t in_label, enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex); /* * Uninstall all LDP NHLFEs for a particular LSP forwarding entry. * If no other NHLFEs exist, the entry would be deleted. */ -void -mpls_ldp_lsp_uninstall_all (struct hash_backet *backet, void *ctxt); +void mpls_ldp_lsp_uninstall_all(struct hash_backet *backet, void *ctxt); /* * Uninstall all LDP FEC-To-NHLFE (FTN) bindings of the given address-family. */ -void -mpls_ldp_ftn_uninstall_all (struct zebra_vrf *zvrf, int afi); +void mpls_ldp_ftn_uninstall_all(struct zebra_vrf *zvrf, int afi); #if defined(HAVE_CUMULUS) /* @@ -346,10 +325,11 @@ mpls_ldp_ftn_uninstall_all (struct zebra_vrf *zvrf, int afi); * be consistent - i.e., all paths either do a swap or do PHP. This is due * to current HW restrictions. */ -int -zebra_mpls_lsp_label_consistent (struct zebra_vrf *zvrf, mpls_label_t in_label, - mpls_label_t out_label, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex); +int zebra_mpls_lsp_label_consistent(struct zebra_vrf *zvrf, + mpls_label_t in_label, + mpls_label_t out_label, + enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex); #endif /* HAVE_CUMULUS */ /* @@ -359,10 +339,10 @@ zebra_mpls_lsp_label_consistent (struct zebra_vrf *zvrf, mpls_label_t in_label, * Note: The label operation (swap or PHP) is common for the LSP entry (all * NHLFEs). */ -int -zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label, - mpls_label_t out_label, enum nexthop_types_t gtype, - union g_addr *gate, ifindex_t ifindex); +int zebra_mpls_static_lsp_add(struct zebra_vrf *zvrf, mpls_label_t in_label, + mpls_label_t out_label, + enum nexthop_types_t gtype, union g_addr *gate, + ifindex_t ifindex); /* * Delete static LSP entry. This may be the delete of one particular @@ -371,141 +351,124 @@ zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label, * NOTE: Delete of the only NHLFE will also end up deleting the entire * LSP configuration. */ -int -zebra_mpls_static_lsp_del (struct zebra_vrf *zvrf, mpls_label_t in_label, - enum nexthop_types_t gtype, union g_addr *gate, - ifindex_t ifindex); +int zebra_mpls_static_lsp_del(struct zebra_vrf *zvrf, mpls_label_t in_label, + enum nexthop_types_t gtype, union g_addr *gate, + ifindex_t ifindex); /* * Schedule all MPLS label forwarding entries for processing. * Called upon changes that may affect one or more of them such as * interface or nexthop state changes. */ -void -zebra_mpls_lsp_schedule (struct zebra_vrf *zvrf); +void zebra_mpls_lsp_schedule(struct zebra_vrf *zvrf); /* * Display MPLS label forwarding table for a specific LSP * (VTY command handler). */ -void -zebra_mpls_print_lsp (struct vty *vty, struct zebra_vrf *zvrf, mpls_label_t label, - u_char use_json); +void zebra_mpls_print_lsp(struct vty *vty, struct zebra_vrf *zvrf, + mpls_label_t label, u_char use_json); /* * Display MPLS label forwarding table (VTY command handler). */ -void -zebra_mpls_print_lsp_table (struct vty *vty, struct zebra_vrf *zvrf, - u_char use_json); +void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf, + u_char use_json); /* * Display MPLS LSP configuration of all static LSPs (VTY command handler). */ -int -zebra_mpls_write_lsp_config (struct vty *vty, struct zebra_vrf *zvrf); +int zebra_mpls_write_lsp_config(struct vty *vty, struct zebra_vrf *zvrf); /* * Called upon process exiting, need to delete LSP forwarding * entries from the kernel. * NOTE: Currently supported only for default VRF. */ -void -zebra_mpls_close_tables (struct zebra_vrf *zvrf); +void zebra_mpls_close_tables(struct zebra_vrf *zvrf); /* * Allocate MPLS tables for this VRF. * NOTE: Currently supported only for default VRF. */ -void -zebra_mpls_init_tables (struct zebra_vrf *zvrf); +void zebra_mpls_init_tables(struct zebra_vrf *zvrf); /* * Global MPLS initialization. */ -void -zebra_mpls_init (void); +void zebra_mpls_init(void); /* * MPLS VTY. */ -void -zebra_mpls_vty_init (void); +void zebra_mpls_vty_init(void); /* Inline functions. */ /* * Distance (priority) definition for LSP NHLFE. */ -static inline u_char -lsp_distance (enum lsp_types_t type) +static inline u_char lsp_distance(enum lsp_types_t type) { - if (type == ZEBRA_LSP_STATIC) - return (route_distance (ZEBRA_ROUTE_STATIC)); + if (type == ZEBRA_LSP_STATIC) + return (route_distance(ZEBRA_ROUTE_STATIC)); - return 150; + return 150; } /* * Map RIB type to LSP type. Used when labeled-routes from BGP * are converted into LSPs. */ -static inline enum lsp_types_t -lsp_type_from_re_type (int re_type) +static inline enum lsp_types_t lsp_type_from_re_type(int re_type) { - switch (re_type) - { - case ZEBRA_ROUTE_STATIC: - return ZEBRA_LSP_STATIC; - case ZEBRA_ROUTE_BGP: - return ZEBRA_LSP_BGP; - default: - return ZEBRA_LSP_NONE; - } + switch (re_type) { + case ZEBRA_ROUTE_STATIC: + return ZEBRA_LSP_STATIC; + case ZEBRA_ROUTE_BGP: + return ZEBRA_LSP_BGP; + default: + return ZEBRA_LSP_NONE; + } } /* NHLFE type as printable string. */ -static inline const char * -nhlfe_type2str(enum lsp_types_t lsp_type) +static inline const char *nhlfe_type2str(enum lsp_types_t lsp_type) { - switch (lsp_type) - { - case ZEBRA_LSP_STATIC: - return "Static"; - case ZEBRA_LSP_LDP: - return "LDP"; - case ZEBRA_LSP_BGP: - return "BGP"; - default: - return "Unknown"; - } + switch (lsp_type) { + case ZEBRA_LSP_STATIC: + return "Static"; + case ZEBRA_LSP_LDP: + return "LDP"; + case ZEBRA_LSP_BGP: + return "BGP"; + default: + return "Unknown"; + } } -static inline void -mpls_mark_lsps_for_processing(struct zebra_vrf *zvrf) +static inline void mpls_mark_lsps_for_processing(struct zebra_vrf *zvrf) { - if (!zvrf) - return; + if (!zvrf) + return; - zvrf->mpls_flags |= MPLS_FLAG_SCHEDULE_LSPS; + zvrf->mpls_flags |= MPLS_FLAG_SCHEDULE_LSPS; } -static inline void -mpls_unmark_lsps_for_processing(struct zebra_vrf *zvrf) +static inline void mpls_unmark_lsps_for_processing(struct zebra_vrf *zvrf) { - if (!zvrf) - return; + if (!zvrf) + return; - zvrf->mpls_flags &= ~MPLS_FLAG_SCHEDULE_LSPS; + zvrf->mpls_flags &= ~MPLS_FLAG_SCHEDULE_LSPS; } -static inline int -mpls_should_lsps_be_processed(struct zebra_vrf *zvrf) +static inline int mpls_should_lsps_be_processed(struct zebra_vrf *zvrf) { - if (!zvrf) - return 0; + if (!zvrf) + return 0; - return ((zvrf->mpls_flags & MPLS_FLAG_SCHEDULE_LSPS) ? 1 : 0); + return ((zvrf->mpls_flags & MPLS_FLAG_SCHEDULE_LSPS) ? 1 : 0); } /* Global variables. */ diff --git a/zebra/zebra_mpls_netlink.c b/zebra/zebra_mpls_netlink.c index d0c4acb37..c5053563b 100644 --- a/zebra/zebra_mpls_netlink.c +++ b/zebra/zebra_mpls_netlink.c @@ -26,22 +26,21 @@ /* * Install Label Forwarding entry into the kernel. */ -int -kernel_add_lsp (zebra_lsp_t *lsp) +int kernel_add_lsp(zebra_lsp_t *lsp) { - int ret; + int ret; - if (!lsp || !lsp->best_nhlfe) // unexpected - return -1; + if (!lsp || !lsp->best_nhlfe) // unexpected + return -1; - UNSET_FLAG (lsp->flags, LSP_FLAG_CHANGED); - ret = netlink_mpls_multipath (RTM_NEWROUTE, lsp); - if (!ret) - SET_FLAG (lsp->flags, LSP_FLAG_INSTALLED); - else - clear_nhlfe_installed (lsp); + UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED); + ret = netlink_mpls_multipath(RTM_NEWROUTE, lsp); + if (!ret) + SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); + else + clear_nhlfe_installed(lsp); - return ret; + return ret; } /* @@ -55,58 +54,54 @@ kernel_add_lsp (zebra_lsp_t *lsp) * through the metric field (before kernel-MPLS). This shouldn't be an issue * any longer, so REPLACE can be reintroduced. */ -int -kernel_upd_lsp (zebra_lsp_t *lsp) +int kernel_upd_lsp(zebra_lsp_t *lsp) { - int ret; + int ret; - if (!lsp || !lsp->best_nhlfe) // unexpected - return -1; + if (!lsp || !lsp->best_nhlfe) // unexpected + return -1; - UNSET_FLAG (lsp->flags, LSP_FLAG_CHANGED); + UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED); - /* First issue a DEL and clear the installed flag. */ - netlink_mpls_multipath (RTM_DELROUTE, lsp); - UNSET_FLAG (lsp->flags, LSP_FLAG_INSTALLED); + /* First issue a DEL and clear the installed flag. */ + netlink_mpls_multipath(RTM_DELROUTE, lsp); + UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); - /* Then issue an ADD. */ - ret = netlink_mpls_multipath (RTM_NEWROUTE, lsp); - if (!ret) - SET_FLAG (lsp->flags, LSP_FLAG_INSTALLED); - else - clear_nhlfe_installed (lsp); + /* Then issue an ADD. */ + ret = netlink_mpls_multipath(RTM_NEWROUTE, lsp); + if (!ret) + SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); + else + clear_nhlfe_installed(lsp); - return ret; + return ret; } /* * Delete Label Forwarding entry from the kernel. */ -int -kernel_del_lsp (zebra_lsp_t *lsp) +int kernel_del_lsp(zebra_lsp_t *lsp) { - if (!lsp) // unexpected - return -1; + if (!lsp) // unexpected + return -1; - if (CHECK_FLAG (lsp->flags, LSP_FLAG_INSTALLED)) - { - netlink_mpls_multipath (RTM_DELROUTE, lsp); - UNSET_FLAG (lsp->flags, LSP_FLAG_INSTALLED); - } + if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) { + netlink_mpls_multipath(RTM_DELROUTE, lsp); + UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); + } - return 0; + return 0; } -int -mpls_kernel_init (void) +int mpls_kernel_init(void) { - struct stat st; + struct stat st; - /* - * Check if the MPLS module is loaded in the kernel. - */ - if (stat ("/proc/sys/net/mpls", &st) != 0) - return -1; + /* + * Check if the MPLS module is loaded in the kernel. + */ + if (stat("/proc/sys/net/mpls", &st) != 0) + return -1; - return 0; + return 0; }; diff --git a/zebra/zebra_mpls_null.c b/zebra/zebra_mpls_null.c index a8acdb19f..a9da5c29c 100644 --- a/zebra/zebra_mpls_null.c +++ b/zebra/zebra_mpls_null.c @@ -22,7 +22,19 @@ #include "zebra/rt.h" #include "zebra/zebra_mpls.h" -int kernel_add_lsp (zebra_lsp_t *lsp) { return 0; } -int kernel_upd_lsp (zebra_lsp_t *lsp) { return 0; } -int kernel_del_lsp (zebra_lsp_t *lsp) { return 0; } -int mpls_kernel_init (void) { return -1; }; +int kernel_add_lsp(zebra_lsp_t *lsp) +{ + return 0; +} +int kernel_upd_lsp(zebra_lsp_t *lsp) +{ + return 0; +} +int kernel_del_lsp(zebra_lsp_t *lsp) +{ + return 0; +} +int mpls_kernel_init(void) +{ + return -1; +}; diff --git a/zebra/zebra_mpls_openbsd.c b/zebra/zebra_mpls_openbsd.c index 45e4435ee..fc1df9227 100644 --- a/zebra/zebra_mpls_openbsd.c +++ b/zebra/zebra_mpls_openbsd.c @@ -32,336 +32,329 @@ extern struct zebra_privs_t zserv_privs; struct { - u_int32_t rtseq; - int fd; + u_int32_t rtseq; + int fd; } kr_state; -static int -kernel_send_rtmsg_v4 (int action, mpls_label_t in_label, zebra_nhlfe_t *nhlfe) +static int kernel_send_rtmsg_v4(int action, mpls_label_t in_label, + zebra_nhlfe_t *nhlfe) { - struct iovec iov[5]; - struct rt_msghdr hdr; - struct sockaddr_mpls sa_label_in, sa_label_out; - struct sockaddr_in nexthop; - int iovcnt = 0; - int ret; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: 0x%x, label=%u", __func__, action, in_label); - - /* initialize header */ - memset (&hdr, 0, sizeof (hdr)); - hdr.rtm_version = RTM_VERSION; - - hdr.rtm_type = action; - hdr.rtm_flags = RTF_UP; - hdr.rtm_fmask = RTF_MPLS; - hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */ - hdr.rtm_msglen = sizeof (hdr); - hdr.rtm_hdrlen = sizeof (struct rt_msghdr); - hdr.rtm_priority = 0; - /* adjust iovec */ - iov[iovcnt].iov_base = &hdr; - iov[iovcnt++].iov_len = sizeof (hdr); - - /* in label */ - memset (&sa_label_in, 0, sizeof (sa_label_in)); - sa_label_in.smpls_len = sizeof (sa_label_in); - sa_label_in.smpls_family = AF_MPLS; - sa_label_in.smpls_label = htonl(in_label << MPLS_LABEL_OFFSET); - /* adjust header */ - hdr.rtm_flags |= RTF_MPLS | RTF_MPATH; - hdr.rtm_addrs |= RTA_DST; - hdr.rtm_msglen += sizeof (sa_label_in); - /* adjust iovec */ - iov[iovcnt].iov_base = &sa_label_in; - iov[iovcnt++].iov_len = sizeof (sa_label_in); - - /* nexthop */ - memset (&nexthop, 0, sizeof (nexthop)); - nexthop.sin_len = sizeof (nexthop); - nexthop.sin_family = AF_INET; - nexthop.sin_addr = nhlfe->nexthop->gate.ipv4; - /* adjust header */ - hdr.rtm_flags |= RTF_GATEWAY; - hdr.rtm_addrs |= RTA_GATEWAY; - hdr.rtm_msglen += sizeof (nexthop); - /* adjust iovec */ - iov[iovcnt].iov_base = &nexthop; - iov[iovcnt++].iov_len = sizeof (nexthop); - - /* If action is RTM_DELETE we have to get rid of MPLS infos */ - if (action != RTM_DELETE) - { - memset (&sa_label_out, 0, sizeof (sa_label_out)); - sa_label_out.smpls_len = sizeof (sa_label_out); - sa_label_out.smpls_family = AF_MPLS; - sa_label_out.smpls_label = - htonl(nhlfe->nexthop->nh_label->label[0] << MPLS_LABEL_OFFSET); - /* adjust header */ - hdr.rtm_addrs |= RTA_SRC; - hdr.rtm_flags |= RTF_MPLS; - hdr.rtm_msglen += sizeof (sa_label_out); - /* adjust iovec */ - iov[iovcnt].iov_base = &sa_label_out; - iov[iovcnt++].iov_len = sizeof (sa_label_out); - - if (nhlfe->nexthop->nh_label->label[0] == MPLS_LABEL_IMPLNULL) - hdr.rtm_mpls = MPLS_OP_POP; - else - hdr.rtm_mpls = MPLS_OP_SWAP; - } - - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err ("Can't raise privileges"); - ret = writev (kr_state.fd, iov, iovcnt); - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err ("Can't lower privileges"); - - if (ret == -1) - zlog_err ("%s: %s", __func__, safe_strerror (errno)); - - return ret; + struct iovec iov[5]; + struct rt_msghdr hdr; + struct sockaddr_mpls sa_label_in, sa_label_out; + struct sockaddr_in nexthop; + int iovcnt = 0; + int ret; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: 0x%x, label=%u", __func__, action, in_label); + + /* initialize header */ + memset(&hdr, 0, sizeof(hdr)); + hdr.rtm_version = RTM_VERSION; + + hdr.rtm_type = action; + hdr.rtm_flags = RTF_UP; + hdr.rtm_fmask = RTF_MPLS; + hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */ + hdr.rtm_msglen = sizeof(hdr); + hdr.rtm_hdrlen = sizeof(struct rt_msghdr); + hdr.rtm_priority = 0; + /* adjust iovec */ + iov[iovcnt].iov_base = &hdr; + iov[iovcnt++].iov_len = sizeof(hdr); + + /* in label */ + memset(&sa_label_in, 0, sizeof(sa_label_in)); + sa_label_in.smpls_len = sizeof(sa_label_in); + sa_label_in.smpls_family = AF_MPLS; + sa_label_in.smpls_label = htonl(in_label << MPLS_LABEL_OFFSET); + /* adjust header */ + hdr.rtm_flags |= RTF_MPLS | RTF_MPATH; + hdr.rtm_addrs |= RTA_DST; + hdr.rtm_msglen += sizeof(sa_label_in); + /* adjust iovec */ + iov[iovcnt].iov_base = &sa_label_in; + iov[iovcnt++].iov_len = sizeof(sa_label_in); + + /* nexthop */ + memset(&nexthop, 0, sizeof(nexthop)); + nexthop.sin_len = sizeof(nexthop); + nexthop.sin_family = AF_INET; + nexthop.sin_addr = nhlfe->nexthop->gate.ipv4; + /* adjust header */ + hdr.rtm_flags |= RTF_GATEWAY; + hdr.rtm_addrs |= RTA_GATEWAY; + hdr.rtm_msglen += sizeof(nexthop); + /* adjust iovec */ + iov[iovcnt].iov_base = &nexthop; + iov[iovcnt++].iov_len = sizeof(nexthop); + + /* If action is RTM_DELETE we have to get rid of MPLS infos */ + if (action != RTM_DELETE) { + memset(&sa_label_out, 0, sizeof(sa_label_out)); + sa_label_out.smpls_len = sizeof(sa_label_out); + sa_label_out.smpls_family = AF_MPLS; + sa_label_out.smpls_label = + htonl(nhlfe->nexthop->nh_label->label[0] + << MPLS_LABEL_OFFSET); + /* adjust header */ + hdr.rtm_addrs |= RTA_SRC; + hdr.rtm_flags |= RTF_MPLS; + hdr.rtm_msglen += sizeof(sa_label_out); + /* adjust iovec */ + iov[iovcnt].iov_base = &sa_label_out; + iov[iovcnt++].iov_len = sizeof(sa_label_out); + + if (nhlfe->nexthop->nh_label->label[0] == MPLS_LABEL_IMPLNULL) + hdr.rtm_mpls = MPLS_OP_POP; + else + hdr.rtm_mpls = MPLS_OP_SWAP; + } + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + ret = writev(kr_state.fd, iov, iovcnt); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + if (ret == -1) + zlog_err("%s: %s", __func__, safe_strerror(errno)); + + return ret; } #if !defined(ROUNDUP) -#define ROUNDUP(a) \ - (((a) & (sizeof(long) - 1)) ? (1 + ((a) | (sizeof(long) - 1))) : (a)) +#define ROUNDUP(a) \ + (((a) & (sizeof(long) - 1)) ? (1 + ((a) | (sizeof(long) - 1))) : (a)) #endif -static int -kernel_send_rtmsg_v6 (int action, mpls_label_t in_label, zebra_nhlfe_t *nhlfe) +static int kernel_send_rtmsg_v6(int action, mpls_label_t in_label, + zebra_nhlfe_t *nhlfe) { - struct iovec iov[5]; - struct rt_msghdr hdr; - struct sockaddr_mpls sa_label_in, sa_label_out; - struct pad { - struct sockaddr_in6 addr; - char pad[sizeof(long)]; /* thank you IPv6 */ - } nexthop; - int iovcnt = 0; - int ret; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("%s: 0x%x, label=%u", __func__, action, in_label); - - /* initialize header */ - memset (&hdr, 0, sizeof (hdr)); - hdr.rtm_version = RTM_VERSION; - - hdr.rtm_type = action; - hdr.rtm_flags = RTF_UP; - hdr.rtm_fmask = RTF_MPLS; - hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */ - hdr.rtm_msglen = sizeof (hdr); - hdr.rtm_hdrlen = sizeof (struct rt_msghdr); - hdr.rtm_priority = 0; - /* adjust iovec */ - iov[iovcnt].iov_base = &hdr; - iov[iovcnt++].iov_len = sizeof (hdr); - - /* in label */ - memset (&sa_label_in, 0, sizeof (sa_label_in)); - sa_label_in.smpls_len = sizeof (sa_label_in); - sa_label_in.smpls_family = AF_MPLS; - sa_label_in.smpls_label = htonl(in_label << MPLS_LABEL_OFFSET); - /* adjust header */ - hdr.rtm_flags |= RTF_MPLS | RTF_MPATH; - hdr.rtm_addrs |= RTA_DST; - hdr.rtm_msglen += sizeof (sa_label_in); - /* adjust iovec */ - iov[iovcnt].iov_base = &sa_label_in; - iov[iovcnt++].iov_len = sizeof (sa_label_in); - - /* nexthop */ - memset (&nexthop, 0, sizeof (nexthop)); - nexthop.addr.sin6_len = sizeof (struct sockaddr_in6); - nexthop.addr.sin6_family = AF_INET6; - nexthop.addr.sin6_addr = nhlfe->nexthop->gate.ipv6; - if (IN6_IS_ADDR_LINKLOCAL (&nexthop.addr.sin6_addr)) - { - uint16_t tmp16; - struct sockaddr_in6 *sin6 = &nexthop.addr; - - nexthop.addr.sin6_scope_id = nhlfe->nexthop->ifindex; - - memcpy (&tmp16, &sin6->sin6_addr.s6_addr[2], sizeof (tmp16)); - tmp16 = htons (sin6->sin6_scope_id); - memcpy (&sin6->sin6_addr.s6_addr[2], &tmp16, sizeof (tmp16)); - sin6->sin6_scope_id = 0; - } - - /* adjust header */ - hdr.rtm_flags |= RTF_GATEWAY; - hdr.rtm_addrs |= RTA_GATEWAY; - hdr.rtm_msglen += ROUNDUP (sizeof (struct sockaddr_in6)); - /* adjust iovec */ - iov[iovcnt].iov_base = &nexthop; - iov[iovcnt++].iov_len = ROUNDUP (sizeof (struct sockaddr_in6)); - - /* If action is RTM_DELETE we have to get rid of MPLS infos */ - if (action != RTM_DELETE) - { - memset (&sa_label_out, 0, sizeof (sa_label_out)); - sa_label_out.smpls_len = sizeof (sa_label_out); - sa_label_out.smpls_family = AF_MPLS; - sa_label_out.smpls_label = - htonl(nhlfe->nexthop->nh_label->label[0] << MPLS_LABEL_OFFSET); - /* adjust header */ - hdr.rtm_addrs |= RTA_SRC; - hdr.rtm_flags |= RTF_MPLS; - hdr.rtm_msglen += sizeof (sa_label_out); - /* adjust iovec */ - iov[iovcnt].iov_base = &sa_label_out; - iov[iovcnt++].iov_len = sizeof (sa_label_out); - - if (nhlfe->nexthop->nh_label->label[0] == MPLS_LABEL_IMPLNULL) - hdr.rtm_mpls = MPLS_OP_POP; - else - hdr.rtm_mpls = MPLS_OP_SWAP; - } - - if (zserv_privs.change(ZPRIVS_RAISE)) - zlog_err ("Can't raise privileges"); - ret = writev (kr_state.fd, iov, iovcnt); - if (zserv_privs.change(ZPRIVS_LOWER)) - zlog_err ("Can't lower privileges"); - - if (ret == -1) - zlog_err ("%s: %s", __func__, safe_strerror (errno)); - - return ret; + struct iovec iov[5]; + struct rt_msghdr hdr; + struct sockaddr_mpls sa_label_in, sa_label_out; + struct pad { + struct sockaddr_in6 addr; + char pad[sizeof(long)]; /* thank you IPv6 */ + } nexthop; + int iovcnt = 0; + int ret; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: 0x%x, label=%u", __func__, action, in_label); + + /* initialize header */ + memset(&hdr, 0, sizeof(hdr)); + hdr.rtm_version = RTM_VERSION; + + hdr.rtm_type = action; + hdr.rtm_flags = RTF_UP; + hdr.rtm_fmask = RTF_MPLS; + hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */ + hdr.rtm_msglen = sizeof(hdr); + hdr.rtm_hdrlen = sizeof(struct rt_msghdr); + hdr.rtm_priority = 0; + /* adjust iovec */ + iov[iovcnt].iov_base = &hdr; + iov[iovcnt++].iov_len = sizeof(hdr); + + /* in label */ + memset(&sa_label_in, 0, sizeof(sa_label_in)); + sa_label_in.smpls_len = sizeof(sa_label_in); + sa_label_in.smpls_family = AF_MPLS; + sa_label_in.smpls_label = htonl(in_label << MPLS_LABEL_OFFSET); + /* adjust header */ + hdr.rtm_flags |= RTF_MPLS | RTF_MPATH; + hdr.rtm_addrs |= RTA_DST; + hdr.rtm_msglen += sizeof(sa_label_in); + /* adjust iovec */ + iov[iovcnt].iov_base = &sa_label_in; + iov[iovcnt++].iov_len = sizeof(sa_label_in); + + /* nexthop */ + memset(&nexthop, 0, sizeof(nexthop)); + nexthop.addr.sin6_len = sizeof(struct sockaddr_in6); + nexthop.addr.sin6_family = AF_INET6; + nexthop.addr.sin6_addr = nhlfe->nexthop->gate.ipv6; + if (IN6_IS_ADDR_LINKLOCAL(&nexthop.addr.sin6_addr)) { + uint16_t tmp16; + struct sockaddr_in6 *sin6 = &nexthop.addr; + + nexthop.addr.sin6_scope_id = nhlfe->nexthop->ifindex; + + memcpy(&tmp16, &sin6->sin6_addr.s6_addr[2], sizeof(tmp16)); + tmp16 = htons(sin6->sin6_scope_id); + memcpy(&sin6->sin6_addr.s6_addr[2], &tmp16, sizeof(tmp16)); + sin6->sin6_scope_id = 0; + } + + /* adjust header */ + hdr.rtm_flags |= RTF_GATEWAY; + hdr.rtm_addrs |= RTA_GATEWAY; + hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_in6)); + /* adjust iovec */ + iov[iovcnt].iov_base = &nexthop; + iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6)); + + /* If action is RTM_DELETE we have to get rid of MPLS infos */ + if (action != RTM_DELETE) { + memset(&sa_label_out, 0, sizeof(sa_label_out)); + sa_label_out.smpls_len = sizeof(sa_label_out); + sa_label_out.smpls_family = AF_MPLS; + sa_label_out.smpls_label = + htonl(nhlfe->nexthop->nh_label->label[0] + << MPLS_LABEL_OFFSET); + /* adjust header */ + hdr.rtm_addrs |= RTA_SRC; + hdr.rtm_flags |= RTF_MPLS; + hdr.rtm_msglen += sizeof(sa_label_out); + /* adjust iovec */ + iov[iovcnt].iov_base = &sa_label_out; + iov[iovcnt++].iov_len = sizeof(sa_label_out); + + if (nhlfe->nexthop->nh_label->label[0] == MPLS_LABEL_IMPLNULL) + hdr.rtm_mpls = MPLS_OP_POP; + else + hdr.rtm_mpls = MPLS_OP_SWAP; + } + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err("Can't raise privileges"); + ret = writev(kr_state.fd, iov, iovcnt); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err("Can't lower privileges"); + + if (ret == -1) + zlog_err("%s: %s", __func__, safe_strerror(errno)); + + return ret; } -static int -kernel_lsp_cmd (int action, zebra_lsp_t *lsp) +static int kernel_lsp_cmd(int action, zebra_lsp_t *lsp) { - zebra_nhlfe_t *nhlfe; - struct nexthop *nexthop = NULL; - unsigned int nexthop_num = 0; - - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) - { - nexthop = nhlfe->nexthop; - if (!nexthop) - continue; - - if (nexthop_num >= multipath_num) - break; - - if (((action == RTM_ADD || action == RTM_CHANGE) && - (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))) || - (action == RTM_DELETE && - (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))) - { - nexthop_num++; - - switch (NHLFE_FAMILY(nhlfe)) - { - case AF_INET: - kernel_send_rtmsg_v4 (action, lsp->ile.in_label, nhlfe); - break; - case AF_INET6: - kernel_send_rtmsg_v6 (action, lsp->ile.in_label, nhlfe); - break; - default: - break; - } - if (action == RTM_ADD || action == RTM_CHANGE) - { - SET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - else - { - UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - } - } - - return (0); + zebra_nhlfe_t *nhlfe; + struct nexthop *nexthop = NULL; + unsigned int nexthop_num = 0; + + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + nexthop = nhlfe->nexthop; + if (!nexthop) + continue; + + if (nexthop_num >= multipath_num) + break; + + if (((action == RTM_ADD || action == RTM_CHANGE) + && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED) + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))) + || (action == RTM_DELETE + && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED) + && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)))) { + nexthop_num++; + + switch (NHLFE_FAMILY(nhlfe)) { + case AF_INET: + kernel_send_rtmsg_v4(action, lsp->ile.in_label, + nhlfe); + break; + case AF_INET6: + kernel_send_rtmsg_v6(action, lsp->ile.in_label, + nhlfe); + break; + default: + break; + } + if (action == RTM_ADD || action == RTM_CHANGE) { + SET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED); + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + } else { + UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED); + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + } + } + } + + return (0); } -int -kernel_add_lsp (zebra_lsp_t *lsp) +int kernel_add_lsp(zebra_lsp_t *lsp) { - int ret; + int ret; - if (!lsp || !lsp->best_nhlfe) // unexpected - return -1; + if (!lsp || !lsp->best_nhlfe) // unexpected + return -1; - UNSET_FLAG (lsp->flags, LSP_FLAG_CHANGED); - ret = kernel_lsp_cmd (RTM_ADD, lsp); - if (!ret) - SET_FLAG (lsp->flags, LSP_FLAG_INSTALLED); + UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED); + ret = kernel_lsp_cmd(RTM_ADD, lsp); + if (!ret) + SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); - return ret; + return ret; } -int -kernel_upd_lsp (zebra_lsp_t *lsp) +int kernel_upd_lsp(zebra_lsp_t *lsp) { - int ret; + int ret; - if (!lsp || !lsp->best_nhlfe) // unexpected - return -1; + if (!lsp || !lsp->best_nhlfe) // unexpected + return -1; - UNSET_FLAG (lsp->flags, LSP_FLAG_CHANGED); - UNSET_FLAG (lsp->flags, LSP_FLAG_INSTALLED); - ret = kernel_lsp_cmd (RTM_CHANGE, lsp); - if (!ret) - SET_FLAG (lsp->flags, LSP_FLAG_INSTALLED); + UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED); + UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); + ret = kernel_lsp_cmd(RTM_CHANGE, lsp); + if (!ret) + SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); - return ret; + return ret; } -int -kernel_del_lsp (zebra_lsp_t *lsp) +int kernel_del_lsp(zebra_lsp_t *lsp) { - int ret; + int ret; - if (!lsp) // unexpected - return -1; + if (!lsp) // unexpected + return -1; - if (! CHECK_FLAG (lsp->flags, LSP_FLAG_INSTALLED)) - return -1; + if (!CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) + return -1; - ret = kernel_lsp_cmd (RTM_DELETE, lsp); - if (!ret) - UNSET_FLAG (lsp->flags, LSP_FLAG_INSTALLED); + ret = kernel_lsp_cmd(RTM_DELETE, lsp); + if (!ret) + UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); - return ret; + return ret; } #define MAX_RTSOCK_BUF 128 * 1024 -int -mpls_kernel_init (void) +int mpls_kernel_init(void) { - int rcvbuf, default_rcvbuf; - socklen_t optlen; - - if ((kr_state.fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) { - zlog_warn("%s: socket", __func__); - return -1; - } - - /* grow receive buffer, don't wanna miss messages */ - optlen = sizeof (default_rcvbuf); - if (getsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF, - &default_rcvbuf, &optlen) == -1) - zlog_warn("kr_init getsockopt SOL_SOCKET SO_RCVBUF"); - else - for (rcvbuf = MAX_RTSOCK_BUF; - rcvbuf > default_rcvbuf && - setsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF, - &rcvbuf, sizeof (rcvbuf)) == -1 && errno == ENOBUFS; - rcvbuf /= 2) - ; /* nothing */ - - kr_state.rtseq = 1; - - return 0; + int rcvbuf, default_rcvbuf; + socklen_t optlen; + + if ((kr_state.fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) { + zlog_warn("%s: socket", __func__); + return -1; + } + + /* grow receive buffer, don't wanna miss messages */ + optlen = sizeof(default_rcvbuf); + if (getsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF, &default_rcvbuf, + &optlen) + == -1) + zlog_warn("kr_init getsockopt SOL_SOCKET SO_RCVBUF"); + else + for (rcvbuf = MAX_RTSOCK_BUF; + rcvbuf > default_rcvbuf + && setsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, + sizeof(rcvbuf)) + == -1 + && errno == ENOBUFS; + rcvbuf /= 2) + ; /* nothing */ + + kr_state.rtseq = 1; + + return 0; } diff --git a/zebra/zebra_mpls_vty.c b/zebra/zebra_mpls_vty.c index 938e8ef7c..ed34831f8 100644 --- a/zebra/zebra_mpls_vty.c +++ b/zebra/zebra_mpls_vty.c @@ -39,119 +39,106 @@ #include "zebra/zebra_routemap.h" #include "zebra/zebra_static.h" -static int -zebra_mpls_transit_lsp (struct vty *vty, int add_cmd, const char *inlabel_str, - const char *gate_str, const char *outlabel_str, - const char *flag_str) +static int zebra_mpls_transit_lsp(struct vty *vty, int add_cmd, + const char *inlabel_str, const char *gate_str, + const char *outlabel_str, + const char *flag_str) { - struct zebra_vrf *zvrf; - int ret; - enum nexthop_types_t gtype; - union g_addr gate; - mpls_label_t label; - mpls_label_t in_label, out_label; - - if (!mpls_enabled) - { - vty_out (vty,"%% MPLS not turned on in kernel, ignoring command\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - zvrf = vrf_info_lookup(VRF_DEFAULT); - if (!zvrf) - { - vty_out (vty, "%% Default VRF does not exist\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (!inlabel_str) - { - vty_out (vty, "%% No Label Information\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - out_label = MPLS_IMP_NULL_LABEL; /* as initialization */ - label = atoi(inlabel_str); - if (!IS_MPLS_UNRESERVED_LABEL(label)) - { - vty_out (vty, "%% Invalid label\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (add_cmd) - { - if (!gate_str) - { - vty_out (vty, "%% No Nexthop Information\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (!outlabel_str) - { - vty_out (vty, "%% No Outgoing label Information\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - in_label = label; - gtype = NEXTHOP_TYPE_BLACKHOLE; /* as initialization */ - - if (gate_str) - { - /* Gateway is a IPv4 or IPv6 nexthop. */ - ret = inet_pton (AF_INET6, gate_str, &gate.ipv6); - if (ret) - gtype = NEXTHOP_TYPE_IPV6; - else - { - ret = inet_pton (AF_INET, gate_str, &gate.ipv4); - if (ret) - gtype = NEXTHOP_TYPE_IPV4; - else - { - vty_out (vty, "%% Invalid nexthop\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - } - - if (outlabel_str) - { - if (outlabel_str[0] == 'i') - out_label = MPLS_IMP_NULL_LABEL; - else if (outlabel_str[0] == 'e' && gtype == NEXTHOP_TYPE_IPV4) - out_label = MPLS_V4_EXP_NULL_LABEL; - else if (outlabel_str[0] == 'e' && gtype == NEXTHOP_TYPE_IPV6) - out_label = MPLS_V6_EXP_NULL_LABEL; - else - out_label = atoi(outlabel_str); - } - - if (add_cmd) - { + struct zebra_vrf *zvrf; + int ret; + enum nexthop_types_t gtype; + union g_addr gate; + mpls_label_t label; + mpls_label_t in_label, out_label; + + if (!mpls_enabled) { + vty_out(vty, + "%% MPLS not turned on in kernel, ignoring command\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + zvrf = vrf_info_lookup(VRF_DEFAULT); + if (!zvrf) { + vty_out(vty, "%% Default VRF does not exist\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (!inlabel_str) { + vty_out(vty, "%% No Label Information\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + out_label = MPLS_IMP_NULL_LABEL; /* as initialization */ + label = atoi(inlabel_str); + if (!IS_MPLS_UNRESERVED_LABEL(label)) { + vty_out(vty, "%% Invalid label\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (add_cmd) { + if (!gate_str) { + vty_out(vty, "%% No Nexthop Information\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (!outlabel_str) { + vty_out(vty, "%% No Outgoing label Information\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + in_label = label; + gtype = NEXTHOP_TYPE_BLACKHOLE; /* as initialization */ + + if (gate_str) { + /* Gateway is a IPv4 or IPv6 nexthop. */ + ret = inet_pton(AF_INET6, gate_str, &gate.ipv6); + if (ret) + gtype = NEXTHOP_TYPE_IPV6; + else { + ret = inet_pton(AF_INET, gate_str, &gate.ipv4); + if (ret) + gtype = NEXTHOP_TYPE_IPV4; + else { + vty_out(vty, "%% Invalid nexthop\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + } + + if (outlabel_str) { + if (outlabel_str[0] == 'i') + out_label = MPLS_IMP_NULL_LABEL; + else if (outlabel_str[0] == 'e' && gtype == NEXTHOP_TYPE_IPV4) + out_label = MPLS_V4_EXP_NULL_LABEL; + else if (outlabel_str[0] == 'e' && gtype == NEXTHOP_TYPE_IPV6) + out_label = MPLS_V6_EXP_NULL_LABEL; + else + out_label = atoi(outlabel_str); + } + + if (add_cmd) { #if defined(HAVE_CUMULUS) - /* Check that label value is consistent. */ - if (!zebra_mpls_lsp_label_consistent (zvrf, in_label, out_label, gtype, - &gate, 0)) - { - vty_out (vty,"%% Label value not consistent\n"); - return CMD_WARNING_CONFIG_FAILED; - } + /* Check that label value is consistent. */ + if (!zebra_mpls_lsp_label_consistent(zvrf, in_label, out_label, + gtype, &gate, 0)) { + vty_out(vty, "%% Label value not consistent\n"); + return CMD_WARNING_CONFIG_FAILED; + } #endif /* HAVE_CUMULUS */ - ret = zebra_mpls_static_lsp_add (zvrf, in_label, out_label, gtype, - &gate, 0); - } - else - ret = zebra_mpls_static_lsp_del (zvrf, in_label, gtype, &gate, 0); + ret = zebra_mpls_static_lsp_add(zvrf, in_label, out_label, + gtype, &gate, 0); + } else + ret = zebra_mpls_static_lsp_del(zvrf, in_label, gtype, &gate, + 0); - if (ret) - { - vty_out (vty, "%% LSP cannot be %s\n", - add_cmd ? "added" : "deleted"); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret) { + vty_out(vty, "%% LSP cannot be %s\n", + add_cmd ? "added" : "deleted"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (mpls_transit_lsp, @@ -166,7 +153,8 @@ DEFUN (mpls_transit_lsp, "Use Explicit-Null label\n" "Use Implicit-Null label\n") { - return zebra_mpls_transit_lsp (vty, 1, argv[2]->arg, argv[3]->arg, argv[4]->arg, NULL); + return zebra_mpls_transit_lsp(vty, 1, argv[2]->arg, argv[3]->arg, + argv[4]->arg, NULL); } DEFUN (no_mpls_transit_lsp, @@ -179,22 +167,21 @@ DEFUN (no_mpls_transit_lsp, "IPv4 gateway address\n" "IPv6 gateway address\n") { - return zebra_mpls_transit_lsp (vty, 0, argv[3]->arg, argv[4]->arg, NULL, NULL); + return zebra_mpls_transit_lsp(vty, 0, argv[3]->arg, argv[4]->arg, NULL, + NULL); } -ALIAS (no_mpls_transit_lsp, - no_mpls_transit_lsp_out_label_cmd, - "no mpls lsp (16-1048575) <(16-1048575)|explicit-null|implicit-null>", - NO_STR - MPLS_STR - "Establish label switched path\n" - "Incoming MPLS label\n" - "IPv4 gateway address\n" - "IPv6 gateway address\n" - "Outgoing MPLS label\n" - "Use Explicit-Null label\n" - "Use Implicit-Null label\n") - +ALIAS(no_mpls_transit_lsp, no_mpls_transit_lsp_out_label_cmd, + "no mpls lsp (16-1048575) <(16-1048575)|explicit-null|implicit-null>", + NO_STR MPLS_STR + "Establish label switched path\n" + "Incoming MPLS label\n" + "IPv4 gateway address\n" + "IPv6 gateway address\n" + "Outgoing MPLS label\n" + "Use Explicit-Null label\n" + "Use Implicit-Null label\n") + DEFUN (no_mpls_transit_lsp_all, no_mpls_transit_lsp_all_cmd, "no mpls lsp (16-1048575)", @@ -203,78 +190,67 @@ DEFUN (no_mpls_transit_lsp_all, "Establish label switched path\n" "Incoming MPLS label\n") { - return zebra_mpls_transit_lsp (vty, 0, argv[3]->arg, NULL, NULL, NULL); + return zebra_mpls_transit_lsp(vty, 0, argv[3]->arg, NULL, NULL, NULL); } -static int -zebra_mpls_bind (struct vty *vty, int add_cmd, const char *prefix, - const char *label_str) +static int zebra_mpls_bind(struct vty *vty, int add_cmd, const char *prefix, + const char *label_str) { - struct zebra_vrf *zvrf; - struct prefix p; - u_int32_t label; - int ret; - - zvrf = vrf_info_lookup(VRF_DEFAULT); - if (!zvrf) - { - vty_out (vty, "%% Default VRF does not exist\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - memset(&p, 0, sizeof(struct prefix)); - ret = str2prefix(prefix, &p); - if (ret <= 0) - { - vty_out (vty, "%% Malformed address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (add_cmd) - { - if (!label_str) - { - vty_out (vty, "%% No label binding specified\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (!strcmp(label_str, "implicit-null")) - label = MPLS_IMP_NULL_LABEL; - else if (!strcmp(label_str, "explicit-null")) - { - if (p.family == AF_INET) - label = MPLS_V4_EXP_NULL_LABEL; - else - label = MPLS_V6_EXP_NULL_LABEL; - } - else - { - label = atoi(label_str); - if (!IS_MPLS_UNRESERVED_LABEL(label)) - { - vty_out (vty, "%% Invalid label\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (zebra_mpls_label_already_bound (zvrf, label)) - { - vty_out (vty,"%% Label already bound to a FEC\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - ret = zebra_mpls_static_fec_add (zvrf, &p, label); - } - else - ret = zebra_mpls_static_fec_del (zvrf, &p); - - if (ret) - { - vty_out (vty, "%% FEC to label binding cannot be %s\n", - add_cmd ? "added" : "deleted"); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + struct zebra_vrf *zvrf; + struct prefix p; + u_int32_t label; + int ret; + + zvrf = vrf_info_lookup(VRF_DEFAULT); + if (!zvrf) { + vty_out(vty, "%% Default VRF does not exist\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + memset(&p, 0, sizeof(struct prefix)); + ret = str2prefix(prefix, &p); + if (ret <= 0) { + vty_out(vty, "%% Malformed address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (add_cmd) { + if (!label_str) { + vty_out(vty, "%% No label binding specified\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (!strcmp(label_str, "implicit-null")) + label = MPLS_IMP_NULL_LABEL; + else if (!strcmp(label_str, "explicit-null")) { + if (p.family == AF_INET) + label = MPLS_V4_EXP_NULL_LABEL; + else + label = MPLS_V6_EXP_NULL_LABEL; + } else { + label = atoi(label_str); + if (!IS_MPLS_UNRESERVED_LABEL(label)) { + vty_out(vty, "%% Invalid label\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (zebra_mpls_label_already_bound(zvrf, label)) { + vty_out(vty, + "%% Label already bound to a FEC\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + ret = zebra_mpls_static_fec_add(zvrf, &p, label); + } else + ret = zebra_mpls_static_fec_del(zvrf, &p); + + if (ret) { + vty_out(vty, "%% FEC to label binding cannot be %s\n", + add_cmd ? "added" : "deleted"); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } DEFUN (mpls_label_bind, @@ -289,7 +265,7 @@ DEFUN (mpls_label_bind, "Use Implicit-Null Label\n" "Use Explicit-Null Label\n") { - return zebra_mpls_bind (vty, 1, argv[3]->arg, argv[4]->arg); + return zebra_mpls_bind(vty, 1, argv[3]->arg, argv[4]->arg); } DEFUN (no_mpls_label_bind, @@ -303,9 +279,8 @@ DEFUN (no_mpls_label_bind, "IPv6 prefix\n" "MPLS Label to bind\n" "Use Implicit-Null Label\n") - { - return zebra_mpls_bind (vty, 0, argv[4]->arg, NULL); + return zebra_mpls_bind(vty, 0, argv[4]->arg, NULL); } /* Static route configuration. */ @@ -320,8 +295,9 @@ DEFUN (ip_route_label, "Null interface\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, NULL, - NULL, NULL, argv[5]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[2]->arg, NULL, + argv[3]->arg, NULL, NULL, NULL, NULL, + argv[5]->arg); } DEFUN (ip_route_tag_label, @@ -337,8 +313,9 @@ DEFUN (ip_route_tag_label, "Tag value\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, argv[5]->arg, - NULL, NULL, argv[7]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[2]->arg, NULL, + argv[3]->arg, NULL, argv[5]->arg, NULL, NULL, + argv[7]->arg); } /* Mask as A.B.C.D format. */ @@ -354,8 +331,9 @@ DEFUN (ip_route_mask_label, "Null interface\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, argv[2]->arg, argv[3]->arg, argv[4]->arg, NULL, NULL, - NULL, NULL, argv[6]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[2]->arg, + argv[3]->arg, argv[4]->arg, NULL, NULL, NULL, + NULL, argv[6]->arg); } DEFUN (ip_route_mask_tag_label, @@ -371,10 +349,10 @@ DEFUN (ip_route_mask_tag_label, "Set tag for this route\n" "Tag value\n" MPLS_LABEL_HELPSTR) - { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, argv[2]->arg, argv[3]->arg, argv[4]->arg, NULL, argv[6]->arg, - NULL, NULL, argv[8]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[2]->arg, + argv[3]->arg, argv[4]->arg, NULL, argv[6]->arg, + NULL, NULL, argv[8]->arg); } /* Distance option value. */ @@ -390,8 +368,9 @@ DEFUN (ip_route_distance_label, "Distance value for this route\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, NULL, - argv[4]->arg, NULL, argv[6]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[2]->arg, NULL, + argv[3]->arg, NULL, NULL, argv[4]->arg, NULL, + argv[6]->arg); } DEFUN (ip_route_tag_distance_label, @@ -407,10 +386,10 @@ DEFUN (ip_route_tag_distance_label, "Tag value\n" "Distance value for this route\n" MPLS_LABEL_HELPSTR) - { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, argv[5]->arg, - argv[6]->arg, NULL, argv[8]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[2]->arg, NULL, + argv[3]->arg, NULL, argv[5]->arg, argv[6]->arg, + NULL, argv[8]->arg); } DEFUN (ip_route_mask_distance_label, @@ -426,8 +405,9 @@ DEFUN (ip_route_mask_distance_label, "Distance value for this route\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, argv[2]->arg, argv[3]->arg, argv[4]->arg, NULL, NULL, - argv[5]->arg, NULL, argv[7]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[2]->arg, + argv[3]->arg, argv[4]->arg, NULL, NULL, + argv[5]->arg, NULL, argv[7]->arg); } DEFUN (ip_route_mask_tag_distance_label, @@ -445,8 +425,9 @@ DEFUN (ip_route_mask_tag_distance_label, "Distance value for this route\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, argv[2]->arg, argv[3]->arg, argv[4]->arg, NULL, argv[6]->arg, - argv[7]->arg, NULL, argv[9]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[2]->arg, + argv[3]->arg, argv[4]->arg, NULL, argv[6]->arg, + argv[7]->arg, NULL, argv[9]->arg); } DEFUN (no_ip_route_label, @@ -461,8 +442,9 @@ DEFUN (no_ip_route_label, "Null interface\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, NULL, - NULL, NULL, argv[6]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[3]->arg, NULL, + argv[4]->arg, NULL, NULL, NULL, NULL, + argv[6]->arg); } DEFUN (no_ip_route_tag_label, @@ -479,8 +461,9 @@ DEFUN (no_ip_route_tag_label, "Tag value\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, argv[6]->arg, - NULL, NULL, argv[8]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[3]->arg, NULL, + argv[4]->arg, NULL, argv[6]->arg, NULL, NULL, + argv[8]->arg); } DEFUN (no_ip_route_mask_label, @@ -496,8 +479,9 @@ DEFUN (no_ip_route_mask_label, "Null interface\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, argv[3]->arg, argv[4]->arg, argv[5]->arg, NULL, NULL, - NULL, NULL, argv[7]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[3]->arg, + argv[4]->arg, argv[5]->arg, NULL, NULL, NULL, + NULL, argv[7]->arg); } DEFUN (no_ip_route_mask_tag_label, @@ -515,8 +499,9 @@ DEFUN (no_ip_route_mask_tag_label, "Tag value\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, argv[3]->arg, argv[4]->arg, argv[5]->arg, NULL, argv[7]->arg, - NULL, NULL, argv[9]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[3]->arg, + argv[4]->arg, argv[5]->arg, NULL, argv[7]->arg, + NULL, NULL, argv[9]->arg); } DEFUN (no_ip_route_distance_label, @@ -532,8 +517,9 @@ DEFUN (no_ip_route_distance_label, "Distance value for this route\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, NULL, - argv[5]->arg, NULL, argv[7]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[3]->arg, NULL, + argv[4]->arg, NULL, NULL, argv[5]->arg, NULL, + argv[7]->arg); } DEFUN (no_ip_route_tag_distance_label, @@ -551,8 +537,9 @@ DEFUN (no_ip_route_tag_distance_label, "Distance value for this route\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, argv[6]->arg, - argv[7]->arg, NULL, argv[9]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[3]->arg, NULL, + argv[4]->arg, NULL, argv[6]->arg, argv[7]->arg, + NULL, argv[9]->arg); } DEFUN (no_ip_route_mask_distance_label, @@ -569,8 +556,9 @@ DEFUN (no_ip_route_mask_distance_label, "Distance value for this route\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, argv[3]->arg, argv[4]->arg, argv[5]->arg, NULL, NULL, - argv[6]->arg, NULL, argv[8]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[3]->arg, + argv[4]->arg, argv[5]->arg, NULL, NULL, + argv[6]->arg, NULL, argv[8]->arg); } DEFUN (no_ip_route_mask_tag_distance_label, @@ -589,8 +577,9 @@ DEFUN (no_ip_route_mask_tag_distance_label, "Distance value for this route\n" MPLS_LABEL_HELPSTR) { - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, argv[3]->arg, argv[4]->arg, argv[5]->arg, NULL, argv[7]->arg, - argv[8]->arg, NULL, argv[10]->arg); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[3]->arg, + argv[4]->arg, argv[5]->arg, NULL, argv[7]->arg, + argv[8]->arg, NULL, argv[10]->arg); } DEFUN (ipv6_route_label, @@ -603,7 +592,8 @@ DEFUN (ipv6_route_label, "IPv6 gateway interface name\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, NULL, NULL, NULL, NULL, argv[5]->arg); + return static_ipv6_func(vty, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, + NULL, NULL, NULL, NULL, argv[5]->arg); } DEFUN (ipv6_route_tag_label, @@ -618,7 +608,8 @@ DEFUN (ipv6_route_tag_label, "Tag value\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, NULL, argv[5]->arg, NULL, NULL, argv[7]->arg); + return static_ipv6_func(vty, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, + NULL, argv[5]->arg, NULL, NULL, argv[7]->arg); } DEFUN (ipv6_route_ifname_label, @@ -631,7 +622,9 @@ DEFUN (ipv6_route_ifname_label, "IPv6 gateway interface name\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, argv[4]->arg, NULL, NULL, NULL, NULL, argv[6]->arg); + return static_ipv6_func(vty, 1, argv[2]->arg, NULL, argv[3]->arg, + argv[4]->arg, NULL, NULL, NULL, NULL, + argv[6]->arg); } DEFUN (ipv6_route_ifname_tag_label, ipv6_route_ifname_tag_label_cmd, @@ -645,7 +638,9 @@ DEFUN (ipv6_route_ifname_tag_label, "Tag value\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, argv[4]->arg, NULL, argv[6]->arg, NULL, NULL, argv[8]->arg); + return static_ipv6_func(vty, 1, argv[2]->arg, NULL, argv[3]->arg, + argv[4]->arg, NULL, argv[6]->arg, NULL, NULL, + argv[8]->arg); } DEFUN (ipv6_route_pref_label, @@ -659,7 +654,8 @@ DEFUN (ipv6_route_pref_label, "Distance value for this prefix\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, NULL, NULL, argv[4]->arg, NULL, argv[6]->arg); + return static_ipv6_func(vty, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, + NULL, NULL, argv[4]->arg, NULL, argv[6]->arg); } DEFUN (ipv6_route_pref_tag_label, @@ -675,7 +671,9 @@ DEFUN (ipv6_route_pref_tag_label, "Distance value for this prefix\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, NULL, argv[5]->arg, argv[6]->arg, NULL, argv[8]->arg); + return static_ipv6_func(vty, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, + NULL, argv[5]->arg, argv[6]->arg, NULL, + argv[8]->arg); } DEFUN (ipv6_route_ifname_pref_label, @@ -689,7 +687,9 @@ DEFUN (ipv6_route_ifname_pref_label, "Distance value for this prefix\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, argv[4]->arg, NULL, NULL, argv[5]->arg, NULL, argv[7]->arg); + return static_ipv6_func(vty, 1, argv[2]->arg, NULL, argv[3]->arg, + argv[4]->arg, NULL, NULL, argv[5]->arg, NULL, + argv[7]->arg); } DEFUN (ipv6_route_ifname_pref_tag_label, @@ -705,7 +705,9 @@ DEFUN (ipv6_route_ifname_pref_tag_label, "Distance value for this prefix\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, argv[4]->arg, NULL, argv[6]->arg, argv[7]->arg, NULL, argv[9]->arg); + return static_ipv6_func(vty, 1, argv[2]->arg, NULL, argv[3]->arg, + argv[4]->arg, NULL, argv[6]->arg, argv[7]->arg, + NULL, argv[9]->arg); } DEFUN (no_ipv6_route_label, @@ -719,7 +721,8 @@ DEFUN (no_ipv6_route_label, "IPv6 gateway interface name\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, NULL, NULL, NULL, NULL, argv[6]->arg); + return static_ipv6_func(vty, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, + NULL, NULL, NULL, NULL, argv[6]->arg); } DEFUN (no_ipv6_route_tag_label, @@ -735,7 +738,8 @@ DEFUN (no_ipv6_route_tag_label, "Tag value\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, NULL, argv[6]->arg, NULL, NULL, argv[8]->arg); + return static_ipv6_func(vty, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, + NULL, argv[6]->arg, NULL, NULL, argv[8]->arg); } DEFUN (no_ipv6_route_ifname_label, @@ -749,7 +753,9 @@ DEFUN (no_ipv6_route_ifname_label, "IPv6 gateway interface name\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, argv[5]->arg, NULL, NULL, NULL, NULL, argv[7]->arg); + return static_ipv6_func(vty, 0, argv[3]->arg, NULL, argv[4]->arg, + argv[5]->arg, NULL, NULL, NULL, NULL, + argv[7]->arg); } DEFUN (no_ipv6_route_ifname_tag_label, @@ -765,7 +771,9 @@ DEFUN (no_ipv6_route_ifname_tag_label, "Tag value\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, argv[5]->arg, NULL, argv[7]->arg, NULL, NULL, argv[9]->arg); + return static_ipv6_func(vty, 0, argv[3]->arg, NULL, argv[4]->arg, + argv[5]->arg, NULL, argv[7]->arg, NULL, NULL, + argv[9]->arg); } DEFUN (no_ipv6_route_pref_label, @@ -780,7 +788,8 @@ DEFUN (no_ipv6_route_pref_label, "Distance value for this prefix\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, NULL, NULL, argv[5]->arg, NULL, argv[7]->arg); + return static_ipv6_func(vty, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, + NULL, NULL, argv[5]->arg, NULL, argv[7]->arg); } DEFUN (no_ipv6_route_pref_tag_label, @@ -797,7 +806,9 @@ DEFUN (no_ipv6_route_pref_tag_label, "Distance value for this prefix\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, NULL, argv[6]->arg, argv[7]->arg, NULL, argv[9]->arg); + return static_ipv6_func(vty, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, + NULL, argv[6]->arg, argv[7]->arg, NULL, + argv[9]->arg); } DEFUN (no_ipv6_route_ifname_pref_label, @@ -812,7 +823,9 @@ DEFUN (no_ipv6_route_ifname_pref_label, "Distance value for this prefix\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, argv[5]->arg, NULL, NULL, argv[6]->arg, NULL, argv[8]->arg); + return static_ipv6_func(vty, 0, argv[3]->arg, NULL, argv[4]->arg, + argv[5]->arg, NULL, NULL, argv[6]->arg, NULL, + argv[8]->arg); } DEFUN (no_ipv6_route_ifname_pref_tag_label, @@ -829,24 +842,25 @@ DEFUN (no_ipv6_route_ifname_pref_tag_label, "Distance value for this prefix\n" MPLS_LABEL_HELPSTR) { - return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, argv[5]->arg, NULL, argv[7]->arg, argv[8]->arg, NULL, argv[10]->arg); + return static_ipv6_func(vty, 0, argv[3]->arg, NULL, argv[4]->arg, + argv[5]->arg, NULL, argv[7]->arg, argv[8]->arg, + NULL, argv[10]->arg); } /* MPLS LSP configuration write function. */ -static int -zebra_mpls_config (struct vty *vty) +static int zebra_mpls_config(struct vty *vty) { - int write = 0; - struct zebra_vrf *zvrf; + int write = 0; + struct zebra_vrf *zvrf; - zvrf = vrf_info_lookup(VRF_DEFAULT); - if (!zvrf) - return 0; + zvrf = vrf_info_lookup(VRF_DEFAULT); + if (!zvrf) + return 0; - write += zebra_mpls_write_lsp_config(vty, zvrf); - write += zebra_mpls_write_fec_config(vty, zvrf); - write += zebra_mpls_write_label_block_config (vty, zvrf); - return write; + write += zebra_mpls_write_lsp_config(vty, zvrf); + write += zebra_mpls_write_fec_config(vty, zvrf); + write += zebra_mpls_write_label_block_config(vty, zvrf); + return write; } DEFUN (show_mpls_fec, @@ -858,29 +872,27 @@ DEFUN (show_mpls_fec, "FEC to display information about\n" "FEC to display information about\n") { - struct zebra_vrf *zvrf; - struct prefix p; - int ret; - - zvrf = vrf_info_lookup(VRF_DEFAULT); - if (!zvrf) - return 0; - - if (argc == 3) - zebra_mpls_print_fec_table(vty, zvrf); - else - { - memset(&p, 0, sizeof(struct prefix)); - ret = str2prefix(argv[3]->arg, &p); - if (ret <= 0) - { - vty_out (vty, "%% Malformed address\n"); - return CMD_WARNING; - } - zebra_mpls_print_fec (vty, zvrf, &p); - } - - return CMD_SUCCESS; + struct zebra_vrf *zvrf; + struct prefix p; + int ret; + + zvrf = vrf_info_lookup(VRF_DEFAULT); + if (!zvrf) + return 0; + + if (argc == 3) + zebra_mpls_print_fec_table(vty, zvrf); + else { + memset(&p, 0, sizeof(struct prefix)); + ret = str2prefix(argv[3]->arg, &p); + if (ret <= 0) { + vty_out(vty, "%% Malformed address\n"); + return CMD_WARNING; + } + zebra_mpls_print_fec(vty, zvrf, &p); + } + + return CMD_SUCCESS; } DEFUN (show_mpls_table, @@ -891,12 +903,12 @@ DEFUN (show_mpls_table, "MPLS table\n" JSON_STR) { - struct zebra_vrf *zvrf; - u_char uj = use_json (argc, argv); + struct zebra_vrf *zvrf; + u_char uj = use_json(argc, argv); - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_mpls_print_lsp_table(vty, zvrf, uj); - return CMD_SUCCESS; + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_mpls_print_lsp_table(vty, zvrf, uj); + return CMD_SUCCESS; } DEFUN (show_mpls_table_lsp, @@ -908,14 +920,14 @@ DEFUN (show_mpls_table_lsp, "LSP to display information about\n" JSON_STR) { - u_int32_t label; - struct zebra_vrf *zvrf; - u_char uj = use_json (argc, argv); - - zvrf = vrf_info_lookup(VRF_DEFAULT); - label = atoi(argv[3]->arg); - zebra_mpls_print_lsp (vty, zvrf, label, uj); - return CMD_SUCCESS; + u_int32_t label; + struct zebra_vrf *zvrf; + u_char uj = use_json(argc, argv); + + zvrf = vrf_info_lookup(VRF_DEFAULT); + label = atoi(argv[3]->arg); + zebra_mpls_print_lsp(vty, zvrf, label, uj); + return CMD_SUCCESS; } DEFUN (show_mpls_status, @@ -925,62 +937,56 @@ DEFUN (show_mpls_status, "MPLS information\n" "MPLS status\n") { - vty_out (vty, "MPLS support enabled: %s\n", - (mpls_enabled) ? "yes" : "no (mpls kernel extensions not detected)"); - return CMD_SUCCESS; + vty_out(vty, "MPLS support enabled: %s\n", + (mpls_enabled) ? "yes" + : "no (mpls kernel extensions not detected)"); + return CMD_SUCCESS; } -static int -zebra_mpls_global_block (struct vty *vty, int add_cmd, - const char *start_label_str, const char *end_label_str) +static int zebra_mpls_global_block(struct vty *vty, int add_cmd, + const char *start_label_str, + const char *end_label_str) { - int ret; - u_int32_t start_label; - u_int32_t end_label; - struct zebra_vrf *zvrf; - - zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT); - if (!zvrf) - { - vty_out (vty, "%% Default VRF does not exist\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (add_cmd) - { - if (!start_label_str || !end_label_str) - { - vty_out (vty, "%% Labels not specified\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - start_label = atoi(start_label_str); - end_label = atoi(end_label_str); - if (!IS_MPLS_UNRESERVED_LABEL(start_label) || - !IS_MPLS_UNRESERVED_LABEL(end_label)) - { - vty_out (vty, "%% Invalid label\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (end_label < start_label) - { - vty_out (vty,"%% End label is less than Start label\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - ret = zebra_mpls_label_block_add (zvrf, start_label, end_label); - } - else - ret = zebra_mpls_label_block_del (zvrf); - - if (ret) - { - vty_out (vty, "%% Global label block could not be %s\n", - add_cmd ? "added" : "deleted"); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; + int ret; + u_int32_t start_label; + u_int32_t end_label; + struct zebra_vrf *zvrf; + + zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT); + if (!zvrf) { + vty_out(vty, "%% Default VRF does not exist\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (add_cmd) { + if (!start_label_str || !end_label_str) { + vty_out(vty, "%% Labels not specified\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + start_label = atoi(start_label_str); + end_label = atoi(end_label_str); + if (!IS_MPLS_UNRESERVED_LABEL(start_label) + || !IS_MPLS_UNRESERVED_LABEL(end_label)) { + vty_out(vty, "%% Invalid label\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (end_label < start_label) { + vty_out(vty, "%% End label is less than Start label\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = zebra_mpls_label_block_add(zvrf, start_label, end_label); + } else + ret = zebra_mpls_label_block_del(zvrf); + + if (ret) { + vty_out(vty, "%% Global label block could not be %s\n", + add_cmd ? "added" : "deleted"); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; } DEFUN (mpls_label_global_block, @@ -992,7 +998,7 @@ DEFUN (mpls_label_global_block, "Start label\n" "End label\n") { - return zebra_mpls_global_block (vty, 1, argv[3]->arg, argv[4]->arg); + return zebra_mpls_global_block(vty, 1, argv[3]->arg, argv[4]->arg); } DEFUN (no_mpls_label_global_block, @@ -1005,65 +1011,64 @@ DEFUN (no_mpls_label_global_block, "Start label\n" "End label\n") { - return zebra_mpls_global_block (vty, 0, NULL, NULL); + return zebra_mpls_global_block(vty, 0, NULL, NULL); } /* MPLS node for MPLS LSP. */ -static struct cmd_node mpls_node = { MPLS_NODE, "", 1 }; +static struct cmd_node mpls_node = {MPLS_NODE, "", 1}; /* MPLS VTY. */ -void -zebra_mpls_vty_init (void) +void zebra_mpls_vty_init(void) { - install_element (VIEW_NODE, &show_mpls_status_cmd); - - install_node (&mpls_node, zebra_mpls_config); - - install_element (CONFIG_NODE, &ip_route_label_cmd); - install_element (CONFIG_NODE, &ip_route_tag_label_cmd); - install_element (CONFIG_NODE, &ip_route_mask_label_cmd); - install_element (CONFIG_NODE, &ip_route_mask_tag_label_cmd); - install_element (CONFIG_NODE, &no_ip_route_label_cmd); - install_element (CONFIG_NODE, &no_ip_route_tag_label_cmd); - install_element (CONFIG_NODE, &no_ip_route_mask_label_cmd); - install_element (CONFIG_NODE, &no_ip_route_mask_tag_label_cmd); - install_element (CONFIG_NODE, &ip_route_distance_label_cmd); - install_element (CONFIG_NODE, &ip_route_tag_distance_label_cmd); - install_element (CONFIG_NODE, &ip_route_mask_distance_label_cmd); - install_element (CONFIG_NODE, &ip_route_mask_tag_distance_label_cmd); - install_element (CONFIG_NODE, &no_ip_route_distance_label_cmd); - install_element (CONFIG_NODE, &no_ip_route_tag_distance_label_cmd); - install_element (CONFIG_NODE, &no_ip_route_mask_distance_label_cmd); - install_element (CONFIG_NODE, &no_ip_route_mask_tag_distance_label_cmd); - - install_element (CONFIG_NODE, &ipv6_route_label_cmd); - install_element (CONFIG_NODE, &ipv6_route_ifname_label_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_label_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_ifname_label_cmd); - install_element (CONFIG_NODE, &ipv6_route_pref_label_cmd); - install_element (CONFIG_NODE, &ipv6_route_ifname_pref_label_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_pref_label_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_ifname_pref_label_cmd); - install_element (CONFIG_NODE, &ipv6_route_tag_label_cmd); - install_element (CONFIG_NODE, &ipv6_route_ifname_tag_label_cmd); - install_element (CONFIG_NODE, &ipv6_route_pref_tag_label_cmd); - install_element (CONFIG_NODE, &ipv6_route_ifname_pref_tag_label_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_tag_label_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_ifname_tag_label_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_pref_tag_label_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_ifname_pref_tag_label_cmd); - - install_element (CONFIG_NODE, &mpls_transit_lsp_cmd); - install_element (CONFIG_NODE, &no_mpls_transit_lsp_cmd); - install_element (CONFIG_NODE, &no_mpls_transit_lsp_out_label_cmd); - install_element (CONFIG_NODE, &no_mpls_transit_lsp_all_cmd); - install_element (CONFIG_NODE, &mpls_label_bind_cmd); - install_element (CONFIG_NODE, &no_mpls_label_bind_cmd); - - install_element (CONFIG_NODE, &mpls_label_global_block_cmd); - install_element (CONFIG_NODE, &no_mpls_label_global_block_cmd); - - install_element (VIEW_NODE, &show_mpls_table_cmd); - install_element (VIEW_NODE, &show_mpls_table_lsp_cmd); - install_element (VIEW_NODE, &show_mpls_fec_cmd); + install_element(VIEW_NODE, &show_mpls_status_cmd); + + install_node(&mpls_node, zebra_mpls_config); + + install_element(CONFIG_NODE, &ip_route_label_cmd); + install_element(CONFIG_NODE, &ip_route_tag_label_cmd); + install_element(CONFIG_NODE, &ip_route_mask_label_cmd); + install_element(CONFIG_NODE, &ip_route_mask_tag_label_cmd); + install_element(CONFIG_NODE, &no_ip_route_label_cmd); + install_element(CONFIG_NODE, &no_ip_route_tag_label_cmd); + install_element(CONFIG_NODE, &no_ip_route_mask_label_cmd); + install_element(CONFIG_NODE, &no_ip_route_mask_tag_label_cmd); + install_element(CONFIG_NODE, &ip_route_distance_label_cmd); + install_element(CONFIG_NODE, &ip_route_tag_distance_label_cmd); + install_element(CONFIG_NODE, &ip_route_mask_distance_label_cmd); + install_element(CONFIG_NODE, &ip_route_mask_tag_distance_label_cmd); + install_element(CONFIG_NODE, &no_ip_route_distance_label_cmd); + install_element(CONFIG_NODE, &no_ip_route_tag_distance_label_cmd); + install_element(CONFIG_NODE, &no_ip_route_mask_distance_label_cmd); + install_element(CONFIG_NODE, &no_ip_route_mask_tag_distance_label_cmd); + + install_element(CONFIG_NODE, &ipv6_route_label_cmd); + install_element(CONFIG_NODE, &ipv6_route_ifname_label_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_label_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_ifname_label_cmd); + install_element(CONFIG_NODE, &ipv6_route_pref_label_cmd); + install_element(CONFIG_NODE, &ipv6_route_ifname_pref_label_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_pref_label_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_ifname_pref_label_cmd); + install_element(CONFIG_NODE, &ipv6_route_tag_label_cmd); + install_element(CONFIG_NODE, &ipv6_route_ifname_tag_label_cmd); + install_element(CONFIG_NODE, &ipv6_route_pref_tag_label_cmd); + install_element(CONFIG_NODE, &ipv6_route_ifname_pref_tag_label_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_tag_label_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_ifname_tag_label_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_pref_tag_label_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_ifname_pref_tag_label_cmd); + + install_element(CONFIG_NODE, &mpls_transit_lsp_cmd); + install_element(CONFIG_NODE, &no_mpls_transit_lsp_cmd); + install_element(CONFIG_NODE, &no_mpls_transit_lsp_out_label_cmd); + install_element(CONFIG_NODE, &no_mpls_transit_lsp_all_cmd); + install_element(CONFIG_NODE, &mpls_label_bind_cmd); + install_element(CONFIG_NODE, &no_mpls_label_bind_cmd); + + install_element(CONFIG_NODE, &mpls_label_global_block_cmd); + install_element(CONFIG_NODE, &no_mpls_label_global_block_cmd); + + install_element(VIEW_NODE, &show_mpls_table_cmd); + install_element(VIEW_NODE, &show_mpls_table_lsp_cmd); + install_element(VIEW_NODE, &show_mpls_fec_cmd); } diff --git a/zebra/zebra_mroute.c b/zebra/zebra_mroute.c index 82c7f404b..c00498171 100644 --- a/zebra/zebra_mroute.c +++ b/zebra/zebra_mroute.c @@ -31,37 +31,37 @@ #include "zebra/zebra_mroute.h" #include "zebra/rt.h" -int -zebra_ipmr_route_stats (struct zserv *client, int fd, u_short length, struct zebra_vrf *zvrf) +int zebra_ipmr_route_stats(struct zserv *client, int fd, u_short length, + struct zebra_vrf *zvrf) { - struct mcast_route_data mroute; - struct stream *s; - int suc; + struct mcast_route_data mroute; + struct stream *s; + int suc; - char sbuf[40]; - char gbuf[40]; + char sbuf[40]; + char gbuf[40]; - memset (&mroute, 0, sizeof (mroute)); - stream_get (&mroute.sg.src, client->ibuf, 4); - stream_get (&mroute.sg.grp, client->ibuf, 4); - mroute.ifindex = stream_getl (client->ibuf); + memset(&mroute, 0, sizeof(mroute)); + stream_get(&mroute.sg.src, client->ibuf, 4); + stream_get(&mroute.sg.grp, client->ibuf, 4); + mroute.ifindex = stream_getl(client->ibuf); - strcpy (sbuf, inet_ntoa (mroute.sg.src)); - strcpy (gbuf, inet_ntoa (mroute.sg.grp)); + strcpy(sbuf, inet_ntoa(mroute.sg.src)); + strcpy(gbuf, inet_ntoa(mroute.sg.grp)); - suc = kernel_get_ipmr_sg_stats (&mroute); + suc = kernel_get_ipmr_sg_stats(&mroute); - s = client->obuf; + s = client->obuf; - stream_reset (s); + stream_reset(s); - zserv_create_header (s, ZEBRA_IPMR_ROUTE_STATS, zvrf_id (zvrf)); - stream_put_in_addr (s, &mroute.sg.src); - stream_put_in_addr (s, &mroute.sg.grp); - stream_put (s, &mroute.lastused, sizeof (mroute.lastused)); - stream_putl (s, suc); + zserv_create_header(s, ZEBRA_IPMR_ROUTE_STATS, zvrf_id(zvrf)); + stream_put_in_addr(s, &mroute.sg.src); + stream_put_in_addr(s, &mroute.sg.grp); + stream_put(s, &mroute.lastused, sizeof(mroute.lastused)); + stream_putl(s, suc); - stream_putw_at (s, 0, stream_get_endp (s)); - zebra_server_send_message (client); - return 0; + stream_putw_at(s, 0, stream_get_endp(s)); + zebra_server_send_message(client); + return 0; } diff --git a/zebra/zebra_mroute.h b/zebra/zebra_mroute.h index eeaf9caf1..fda97e80d 100644 --- a/zebra/zebra_mroute.h +++ b/zebra/zebra_mroute.h @@ -23,12 +23,12 @@ #define __ZEBRA_MROUTE_H__ struct mcast_route_data { - struct prefix_sg sg; - unsigned int ifindex; - unsigned long long lastused; + struct prefix_sg sg; + unsigned int ifindex; + unsigned long long lastused; }; -int zebra_ipmr_route_stats (struct zserv *client, int sock, u_short length, struct zebra_vrf *zvf); +int zebra_ipmr_route_stats(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvf); #endif - diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c index a5869585d..7014731e0 100644 --- a/zebra/zebra_ns.c +++ b/zebra/zebra_ns.c @@ -30,58 +30,54 @@ #include "zebra_vrf.h" #include "zebra_memory.h" -DEFINE_MTYPE(ZEBRA, ZEBRA_NS, "Zebra Name Space") +DEFINE_MTYPE(ZEBRA, ZEBRA_NS, "Zebra Name Space") struct zebra_ns *dzns; -struct zebra_ns * -zebra_ns_lookup (ns_id_t ns_id) +struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id) { - return dzns; + return dzns; } -int -zebra_ns_enable (ns_id_t ns_id, void **info) +int zebra_ns_enable(ns_id_t ns_id, void **info) { - struct zebra_ns *zns = (struct zebra_ns *) (*info); + struct zebra_ns *zns = (struct zebra_ns *)(*info); -#if defined (HAVE_RTADV) - rtadv_init (zns); +#if defined(HAVE_RTADV) + rtadv_init(zns); #endif - zns->if_table = route_table_init (); - kernel_init (zns); - interface_list (zns); - route_read (zns); + zns->if_table = route_table_init(); + kernel_init(zns); + interface_list(zns); + route_read(zns); - return 0; + return 0; } -int -zebra_ns_disable (ns_id_t ns_id, void **info) +int zebra_ns_disable(ns_id_t ns_id, void **info) { - struct zebra_ns *zns = (struct zebra_ns *) (*info); + struct zebra_ns *zns = (struct zebra_ns *)(*info); - route_table_finish (zns->if_table); -#if defined (HAVE_RTADV) - rtadv_terminate (zns); + route_table_finish(zns->if_table); +#if defined(HAVE_RTADV) + rtadv_terminate(zns); #endif - kernel_terminate (zns); + kernel_terminate(zns); - return 0; + return 0; } -int -zebra_ns_init (void) +int zebra_ns_init(void) { - dzns = XCALLOC (MTYPE_ZEBRA_NS, sizeof (struct zebra_ns)); + dzns = XCALLOC(MTYPE_ZEBRA_NS, sizeof(struct zebra_ns)); - ns_init (); + ns_init(); - zebra_vrf_init (); + zebra_vrf_init(); - zebra_ns_enable (0, (void **)&dzns); + zebra_ns_enable(0, (void **)&dzns); - return 0; + return 0; } diff --git a/zebra/zebra_ns.h b/zebra/zebra_ns.h index 721b6c818..6cfba93e5 100644 --- a/zebra/zebra_ns.h +++ b/zebra/zebra_ns.h @@ -26,42 +26,40 @@ #ifdef HAVE_NETLINK /* Socket interface to kernel */ -struct nlsock -{ - int sock; - int seq; - struct sockaddr_nl snl; - char name[64]; +struct nlsock { + int sock; + int seq; + struct sockaddr_nl snl; + char name[64]; }; #endif -struct zebra_ns -{ - /* net-ns name. */ - char name[VRF_NAMSIZ]; +struct zebra_ns { + /* net-ns name. */ + char name[VRF_NAMSIZ]; - /* Identifier. */ - ns_id_t ns_id; + /* Identifier. */ + ns_id_t ns_id; #ifdef HAVE_NETLINK - struct nlsock netlink; /* kernel messages */ - struct nlsock netlink_cmd; /* command channel */ - struct thread *t_netlink; + struct nlsock netlink; /* kernel messages */ + struct nlsock netlink_cmd; /* command channel */ + struct thread *t_netlink; #endif - struct route_table *if_table; + struct route_table *if_table; -#if defined (HAVE_RTADV) - struct rtadv rtadv; +#if defined(HAVE_RTADV) + struct rtadv rtadv; #endif /* HAVE_RTADV */ }; #define NS_DEFAULT 0 #define NS_UNKNOWN UINT16_MAX -struct zebra_ns *zebra_ns_lookup (ns_id_t ns_id); +struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id); -int zebra_ns_init (void); -int zebra_ns_enable (ns_id_t ns_id, void **info); -int zebra_ns_disable (ns_id_t ns_id, void **info); +int zebra_ns_init(void); +int zebra_ns_enable(ns_id_t ns_id, void **info); +int zebra_ns_disable(ns_id_t ns_id, void **info); #endif diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index 39779793f..1bf672d4a 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -19,7 +19,7 @@ */ #include -#include /* for sockaddr_un */ +#include /* for sockaddr_un */ #include #include "vty.h" #include "zebra/zserv.h" @@ -86,176 +86,169 @@ struct zebra_ptm_cb ptm_cb; static int zebra_ptm_socket_init(void); int zebra_ptm_sock_read(struct thread *); -static void zebra_ptm_install_commands (void); +static void zebra_ptm_install_commands(void); static int zebra_ptm_handle_msg_cb(void *arg, void *in_ctxt); -void zebra_bfd_peer_replay_req (void); +void zebra_bfd_peer_replay_req(void); void zebra_ptm_send_status_req(void); void zebra_ptm_reset_status(int ptm_disable); const char ZEBRA_PTM_SOCK_NAME[] = "\0/var/run/ptmd.socket"; -void -zebra_ptm_init (void) +void zebra_ptm_init(void) { - char buf[64]; + char buf[64]; - memset(&ptm_cb, 0, sizeof(struct zebra_ptm_cb)); + memset(&ptm_cb, 0, sizeof(struct zebra_ptm_cb)); - ptm_cb.out_data = calloc(1, ZEBRA_PTM_SEND_MAX_SOCKBUF); - if (!ptm_cb.out_data) - { - zlog_warn("%s: Allocation of send data failed", __func__); - return; - } + ptm_cb.out_data = calloc(1, ZEBRA_PTM_SEND_MAX_SOCKBUF); + if (!ptm_cb.out_data) { + zlog_warn("%s: Allocation of send data failed", __func__); + return; + } - ptm_cb.in_data = calloc(1, ZEBRA_PTM_MAX_SOCKBUF); - if (!ptm_cb.in_data) - { - zlog_warn("%s: Allocation of recv data failed", __func__); - free(ptm_cb.out_data); - return; - } + ptm_cb.in_data = calloc(1, ZEBRA_PTM_MAX_SOCKBUF); + if (!ptm_cb.in_data) { + zlog_warn("%s: Allocation of recv data failed", __func__); + free(ptm_cb.out_data); + return; + } - ptm_cb.pid = getpid(); - zebra_ptm_install_commands(); + ptm_cb.pid = getpid(); + zebra_ptm_install_commands(); - sprintf(buf, "%s", FRR_PTM_NAME); - ptm_hdl = ptm_lib_register(buf, NULL, zebra_ptm_handle_msg_cb, - zebra_ptm_handle_msg_cb); - ptm_cb.wb = buffer_new(0); + sprintf(buf, "%s", FRR_PTM_NAME); + ptm_hdl = ptm_lib_register(buf, NULL, zebra_ptm_handle_msg_cb, + zebra_ptm_handle_msg_cb); + ptm_cb.wb = buffer_new(0); - ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL; + ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL; - ptm_cb.ptm_sock = -1; + ptm_cb.ptm_sock = -1; } -void -zebra_ptm_finish(void) +void zebra_ptm_finish(void) { - int proto; + int proto; - for (proto = 0; proto < ZEBRA_ROUTE_MAX; proto++) - if (CHECK_FLAG(ptm_cb.client_flags[proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG)) - zebra_ptm_bfd_client_deregister(proto); + for (proto = 0; proto < ZEBRA_ROUTE_MAX; proto++) + if (CHECK_FLAG(ptm_cb.client_flags[proto], + ZEBRA_PTM_BFD_CLIENT_FLAG_REG)) + zebra_ptm_bfd_client_deregister(proto); - buffer_flush_all(ptm_cb.wb, ptm_cb.ptm_sock); + buffer_flush_all(ptm_cb.wb, ptm_cb.ptm_sock); - free (ptm_hdl); + free(ptm_hdl); - if (ptm_cb.out_data) - free(ptm_cb.out_data); + if (ptm_cb.out_data) + free(ptm_cb.out_data); - if (ptm_cb.in_data) - free(ptm_cb.in_data); + if (ptm_cb.in_data) + free(ptm_cb.in_data); - /* Release threads. */ - if (ptm_cb.t_read) - thread_cancel (ptm_cb.t_read); - if (ptm_cb.t_write) - thread_cancel (ptm_cb.t_write); - if (ptm_cb.t_timer) - thread_cancel (ptm_cb.t_timer); + /* Release threads. */ + if (ptm_cb.t_read) + thread_cancel(ptm_cb.t_read); + if (ptm_cb.t_write) + thread_cancel(ptm_cb.t_write); + if (ptm_cb.t_timer) + thread_cancel(ptm_cb.t_timer); - if (ptm_cb.wb) - buffer_free(ptm_cb.wb); + if (ptm_cb.wb) + buffer_free(ptm_cb.wb); - if (ptm_cb.ptm_sock != -1) - close(ptm_cb.ptm_sock); + if (ptm_cb.ptm_sock != -1) + close(ptm_cb.ptm_sock); } -static int -zebra_ptm_flush_messages (struct thread *thread) +static int zebra_ptm_flush_messages(struct thread *thread) { - ptm_cb.t_write = NULL; - - if (ptm_cb.ptm_sock == -1) - return -1; - - errno = 0; - - switch (buffer_flush_available(ptm_cb.wb, ptm_cb.ptm_sock)) - { - case BUFFER_ERROR: - zlog_warn ("%s ptm socket error: %s", __func__, - safe_strerror (errno)); - close(ptm_cb.ptm_sock); - ptm_cb.ptm_sock = -1; - zebra_ptm_reset_status(0); - ptm_cb.t_timer = NULL; - thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time, - &ptm_cb.t_timer); - return (-1); - case BUFFER_PENDING: - ptm_cb.t_write = NULL; - thread_add_write(zebrad.master, zebra_ptm_flush_messages, NULL, ptm_cb.ptm_sock, - &ptm_cb.t_write); - break; - case BUFFER_EMPTY: - break; - } - - return(0); + ptm_cb.t_write = NULL; + + if (ptm_cb.ptm_sock == -1) + return -1; + + errno = 0; + + switch (buffer_flush_available(ptm_cb.wb, ptm_cb.ptm_sock)) { + case BUFFER_ERROR: + zlog_warn("%s ptm socket error: %s", __func__, + safe_strerror(errno)); + close(ptm_cb.ptm_sock); + ptm_cb.ptm_sock = -1; + zebra_ptm_reset_status(0); + ptm_cb.t_timer = NULL; + thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, + ptm_cb.reconnect_time, &ptm_cb.t_timer); + return (-1); + case BUFFER_PENDING: + ptm_cb.t_write = NULL; + thread_add_write(zebrad.master, zebra_ptm_flush_messages, NULL, + ptm_cb.ptm_sock, &ptm_cb.t_write); + break; + case BUFFER_EMPTY: + break; + } + + return (0); } -static int -zebra_ptm_send_message(char *data, int size) +static int zebra_ptm_send_message(char *data, int size) { - errno = 0; - switch (buffer_write(ptm_cb.wb, ptm_cb.ptm_sock, data, size)) - { - case BUFFER_ERROR: - zlog_warn ("%s ptm socket error: %s", __func__, safe_strerror (errno)); - close(ptm_cb.ptm_sock); - ptm_cb.ptm_sock = -1; - zebra_ptm_reset_status(0); - ptm_cb.t_timer = NULL; - thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time, - &ptm_cb.t_timer); - return -1; - case BUFFER_EMPTY: - THREAD_OFF(ptm_cb.t_write); - break; - case BUFFER_PENDING: - thread_add_write(zebrad.master, zebra_ptm_flush_messages, NULL, - ptm_cb.ptm_sock, &ptm_cb.t_write); - break; - } - - return 0; + errno = 0; + switch (buffer_write(ptm_cb.wb, ptm_cb.ptm_sock, data, size)) { + case BUFFER_ERROR: + zlog_warn("%s ptm socket error: %s", __func__, + safe_strerror(errno)); + close(ptm_cb.ptm_sock); + ptm_cb.ptm_sock = -1; + zebra_ptm_reset_status(0); + ptm_cb.t_timer = NULL; + thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, + ptm_cb.reconnect_time, &ptm_cb.t_timer); + return -1; + case BUFFER_EMPTY: + THREAD_OFF(ptm_cb.t_write); + break; + case BUFFER_PENDING: + thread_add_write(zebrad.master, zebra_ptm_flush_messages, NULL, + ptm_cb.ptm_sock, &ptm_cb.t_write); + break; + } + + return 0; } -int -zebra_ptm_connect (struct thread *t) +int zebra_ptm_connect(struct thread *t) { - int init = 0; - - if (ptm_cb.ptm_sock == -1) { - zebra_ptm_socket_init(); - init = 1; - } - - if (ptm_cb.ptm_sock != -1) { - if (init) { - ptm_cb.t_read = NULL; - thread_add_read(zebrad.master, zebra_ptm_sock_read, NULL, ptm_cb.ptm_sock, - &ptm_cb.t_read); - zebra_bfd_peer_replay_req(); - } - zebra_ptm_send_status_req(); - ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL; - } else if (ptm_cb.reconnect_time < ZEBRA_PTM_RECONNECT_TIME_MAX){ - ptm_cb.reconnect_time *= 2; - if (ptm_cb.reconnect_time > ZEBRA_PTM_RECONNECT_TIME_MAX) - ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_MAX; - - ptm_cb.t_timer = NULL; - thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time, - &ptm_cb.t_timer); - } else if (ptm_cb.reconnect_time >= ZEBRA_PTM_RECONNECT_TIME_MAX){ - ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL; - } - - return(errno); + int init = 0; + + if (ptm_cb.ptm_sock == -1) { + zebra_ptm_socket_init(); + init = 1; + } + + if (ptm_cb.ptm_sock != -1) { + if (init) { + ptm_cb.t_read = NULL; + thread_add_read(zebrad.master, zebra_ptm_sock_read, + NULL, ptm_cb.ptm_sock, &ptm_cb.t_read); + zebra_bfd_peer_replay_req(); + } + zebra_ptm_send_status_req(); + ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL; + } else if (ptm_cb.reconnect_time < ZEBRA_PTM_RECONNECT_TIME_MAX) { + ptm_cb.reconnect_time *= 2; + if (ptm_cb.reconnect_time > ZEBRA_PTM_RECONNECT_TIME_MAX) + ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_MAX; + + ptm_cb.t_timer = NULL; + thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, + ptm_cb.reconnect_time, &ptm_cb.t_timer); + } else if (ptm_cb.reconnect_time >= ZEBRA_PTM_RECONNECT_TIME_MAX) { + ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL; + } + + return (errno); } DEFUN (zebra_ptm_enable, @@ -263,30 +256,28 @@ DEFUN (zebra_ptm_enable, "ptm-enable", "Enable neighbor check with specified topology\n") { - struct vrf *vrf; - struct listnode *i; - struct interface *ifp; - struct zebra_if *if_data; - - ptm_cb.ptm_enable = ZEBRA_IF_PTM_ENABLE_ON; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - for (ALL_LIST_ELEMENTS_RO (vrf->iflist, i, ifp)) - if (!ifp->ptm_enable) - { - if_data = (struct zebra_if *)ifp->info; - if (if_data && - (if_data->ptm_enable == ZEBRA_IF_PTM_ENABLE_UNSPEC)) - { - ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_ON; - } - /* Assign a default unknown status */ - ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; - } - - zebra_ptm_connect(NULL); - - return CMD_SUCCESS; + struct vrf *vrf; + struct listnode *i; + struct interface *ifp; + struct zebra_if *if_data; + + ptm_cb.ptm_enable = ZEBRA_IF_PTM_ENABLE_ON; + + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + for (ALL_LIST_ELEMENTS_RO(vrf->iflist, i, ifp)) + if (!ifp->ptm_enable) { + if_data = (struct zebra_if *)ifp->info; + if (if_data && (if_data->ptm_enable + == ZEBRA_IF_PTM_ENABLE_UNSPEC)) { + ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_ON; + } + /* Assign a default unknown status */ + ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; + } + + zebra_ptm_connect(NULL); + + return CMD_SUCCESS; } DEFUN (no_zebra_ptm_enable, @@ -295,9 +286,9 @@ DEFUN (no_zebra_ptm_enable, NO_STR "Enable neighbor check with specified topology\n") { - ptm_cb.ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; - zebra_ptm_reset_status(1); - return CMD_SUCCESS; + ptm_cb.ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; + zebra_ptm_reset_status(1); + return CMD_SUCCESS; } DEFUN (zebra_ptm_enable_if, @@ -305,37 +296,34 @@ DEFUN (zebra_ptm_enable_if, "ptm-enable", "Enable neighbor check with specified topology\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - struct zebra_if *if_data; - int old_ptm_enable; - int send_linkdown = 0; - - if (ifp->ifindex == IFINDEX_INTERNAL) - { - return CMD_SUCCESS; - } - - old_ptm_enable = ifp->ptm_enable; - ifp->ptm_enable = ptm_cb.ptm_enable; - - if (if_is_no_ptm_operative(ifp)) - send_linkdown = 1; - - if (!old_ptm_enable && ptm_cb.ptm_enable) - { - if (!if_is_operative (ifp) && send_linkdown) - { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("%s: Bringing down interface %s\n", __func__, - ifp->name); - if_down (ifp); - } - } - - if_data = ifp->info; - if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_UNSPEC; - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *if_data; + int old_ptm_enable; + int send_linkdown = 0; + + if (ifp->ifindex == IFINDEX_INTERNAL) { + return CMD_SUCCESS; + } + + old_ptm_enable = ifp->ptm_enable; + ifp->ptm_enable = ptm_cb.ptm_enable; + + if (if_is_no_ptm_operative(ifp)) + send_linkdown = 1; + + if (!old_ptm_enable && ptm_cb.ptm_enable) { + if (!if_is_operative(ifp) && send_linkdown) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s: Bringing down interface %s\n", + __func__, ifp->name); + if_down(ifp); + } + } + + if_data = ifp->info; + if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_UNSPEC; + + return CMD_SUCCESS; } DEFUN (no_zebra_ptm_enable_if, @@ -344,227 +332,224 @@ DEFUN (no_zebra_ptm_enable_if, NO_STR "Enable neighbor check with specified topology\n") { - VTY_DECLVAR_CONTEXT (interface, ifp); - int send_linkup = 0; - struct zebra_if *if_data; - - if ((ifp->ifindex != IFINDEX_INTERNAL) && (ifp->ptm_enable)) - { - if (!if_is_operative(ifp)) - send_linkup = 1; - - ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; - if (if_is_no_ptm_operative (ifp) && send_linkup) - { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("%s: Bringing up interface %s\n", __func__, - ifp->name); - if_up (ifp); - } - } - - if_data = ifp->info; - if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + int send_linkup = 0; + struct zebra_if *if_data; + + if ((ifp->ifindex != IFINDEX_INTERNAL) && (ifp->ptm_enable)) { + if (!if_is_operative(ifp)) + send_linkup = 1; + + ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; + if (if_is_no_ptm_operative(ifp) && send_linkup) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s: Bringing up interface %s\n", + __func__, ifp->name); + if_up(ifp); + } + } + + if_data = ifp->info; + if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; + + return CMD_SUCCESS; } -void -zebra_ptm_write (struct vty *vty) +void zebra_ptm_write(struct vty *vty) { - if (ptm_cb.ptm_enable) - vty_out (vty, "ptm-enable\n"); + if (ptm_cb.ptm_enable) + vty_out(vty, "ptm-enable\n"); - return; + return; } -static int -zebra_ptm_socket_init (void) +static int zebra_ptm_socket_init(void) { - int ret; - int sock; - struct sockaddr_un addr; - - ptm_cb.ptm_sock = -1; - - sock = socket (PF_UNIX, SOCK_STREAM, 0); - if (sock < 0) - return -1; - if (set_nonblocking(sock) < 0) - { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("%s: Unable to set socket non blocking[%s]", - __PRETTY_FUNCTION__, safe_strerror (errno)); - close (sock); - return -1; - } - - /* Make server socket. */ - memset (&addr, 0, sizeof (struct sockaddr_un)); - addr.sun_family = AF_UNIX; - memcpy (&addr.sun_path, ZEBRA_PTM_SOCK_NAME, - sizeof(ZEBRA_PTM_SOCK_NAME)); - - ret = connect(sock, (struct sockaddr *) &addr, - sizeof (addr.sun_family)+sizeof (ZEBRA_PTM_SOCK_NAME)-1); - if (ret < 0) - { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s: Unable to connect to socket %s [%s]", - __func__, ZEBRA_PTM_SOCK_NAME, safe_strerror(errno)); - close (sock); - return -1; - } - ptm_cb.ptm_sock = sock; - return sock; + int ret; + int sock; + struct sockaddr_un addr; + + ptm_cb.ptm_sock = -1; + + sock = socket(PF_UNIX, SOCK_STREAM, 0); + if (sock < 0) + return -1; + if (set_nonblocking(sock) < 0) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s: Unable to set socket non blocking[%s]", + __PRETTY_FUNCTION__, safe_strerror(errno)); + close(sock); + return -1; + } + + /* Make server socket. */ + memset(&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_UNIX; + memcpy(&addr.sun_path, ZEBRA_PTM_SOCK_NAME, + sizeof(ZEBRA_PTM_SOCK_NAME)); + + ret = connect(sock, (struct sockaddr *)&addr, + sizeof(addr.sun_family) + sizeof(ZEBRA_PTM_SOCK_NAME) + - 1); + if (ret < 0) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s: Unable to connect to socket %s [%s]", + __func__, ZEBRA_PTM_SOCK_NAME, + safe_strerror(errno)); + close(sock); + return -1; + } + ptm_cb.ptm_sock = sock; + return sock; } -static void -zebra_ptm_install_commands (void) +static void zebra_ptm_install_commands(void) { - install_element (CONFIG_NODE, &zebra_ptm_enable_cmd); - install_element (CONFIG_NODE, &no_zebra_ptm_enable_cmd); - install_element (INTERFACE_NODE, &zebra_ptm_enable_if_cmd); - install_element (INTERFACE_NODE, &no_zebra_ptm_enable_if_cmd); + install_element(CONFIG_NODE, &zebra_ptm_enable_cmd); + install_element(CONFIG_NODE, &no_zebra_ptm_enable_cmd); + install_element(INTERFACE_NODE, &zebra_ptm_enable_if_cmd); + install_element(INTERFACE_NODE, &no_zebra_ptm_enable_if_cmd); } /* BFD session goes down, send message to the protocols. */ -static void -if_bfd_session_update (struct interface *ifp, struct prefix *dp, - struct prefix *sp, int status, vrf_id_t vrf_id) +static void if_bfd_session_update(struct interface *ifp, struct prefix *dp, + struct prefix *sp, int status, + vrf_id_t vrf_id) { - if (IS_ZEBRA_DEBUG_EVENT) - { - char buf[2][INET6_ADDRSTRLEN]; - - if (ifp) - { - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d on %s" - " %s event", - inet_ntop (dp->family, &dp->u.prefix, buf[0], - INET6_ADDRSTRLEN), dp->prefixlen, ifp->name, - bfd_get_status_str(status)); - } - else - { - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d " - "with src %s/%d and vrf %d %s event", - inet_ntop (dp->family, &dp->u.prefix, buf[0], INET6_ADDRSTRLEN), - dp->prefixlen, - inet_ntop (sp->family, &sp->u.prefix, buf[1], INET6_ADDRSTRLEN), - sp->prefixlen, vrf_id, bfd_get_status_str(status)); - } - } - - zebra_interface_bfd_update (ifp, dp, sp, status, vrf_id); + if (IS_ZEBRA_DEBUG_EVENT) { + char buf[2][INET6_ADDRSTRLEN]; + + if (ifp) { + zlog_debug( + "MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d on %s" + " %s event", + inet_ntop(dp->family, &dp->u.prefix, buf[0], + INET6_ADDRSTRLEN), + dp->prefixlen, ifp->name, + bfd_get_status_str(status)); + } else { + zlog_debug( + "MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d " + "with src %s/%d and vrf %d %s event", + inet_ntop(dp->family, &dp->u.prefix, buf[0], + INET6_ADDRSTRLEN), + dp->prefixlen, + inet_ntop(sp->family, &sp->u.prefix, buf[1], + INET6_ADDRSTRLEN), + sp->prefixlen, vrf_id, + bfd_get_status_str(status)); + } + } + + zebra_interface_bfd_update(ifp, dp, sp, status, vrf_id); } -static int -zebra_ptm_handle_bfd_msg(void *arg, void *in_ctxt, struct interface *ifp) +static int zebra_ptm_handle_bfd_msg(void *arg, void *in_ctxt, + struct interface *ifp) { - char bfdst_str[32]; - char dest_str[64]; - char src_str[64]; - char vrf_str[64]; - struct prefix dest_prefix; - struct prefix src_prefix; - vrf_id_t vrf_id; - - ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDSTATUS_STR, bfdst_str); - - if (bfdst_str[0] == '\0') { - return -1; - } - - ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDDEST_STR, dest_str); - - if (dest_str[0] == '\0') { - zlog_debug("%s: Key %s not found in PTM msg", __func__, - ZEBRA_PTM_BFDDEST_STR); - return -1; - } - - ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDSRC_STR, src_str); - - if (src_str[0] == '\0') { - zlog_debug("%s: Key %s not found in PTM msg", __func__, - ZEBRA_PTM_BFDSRC_STR); - return -1; - } - - ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDVRF_STR, vrf_str); - - if (vrf_str[0] == '\0') { - zlog_debug("%s: Key %s not found in PTM msg", __func__, - ZEBRA_PTM_BFDVRF_STR); - return -1; - } - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s: Recv Port [%s] bfd status [%s] vrf [%s]" - " peer [%s] local [%s]", - __func__, ifp ? ifp->name : "N/A", bfdst_str, - vrf_str, dest_str, src_str); - - if (str2prefix(dest_str, &dest_prefix) == 0) { - zlog_err("%s: Peer addr %s not found", __func__, - dest_str); - return -1; - } - - memset(&src_prefix, 0, sizeof(struct prefix)); - if (strcmp(ZEBRA_PTM_INVALID_SRC_IP, src_str)) { - if (str2prefix(src_str, &src_prefix) == 0) { - zlog_err("%s: Local addr %s not found", __func__, - src_str); - return -1; - } - } - - if (!strcmp(ZEBRA_PTM_INVALID_VRF, vrf_str) && ifp) { - vrf_id = ifp->vrf_id; - } else { - vrf_id = vrf_name_to_id(vrf_str); - } - - if (!strcmp (bfdst_str, ZEBRA_PTM_BFDSTATUS_DOWN_STR)) { - if_bfd_session_update(ifp, &dest_prefix, &src_prefix, BFD_STATUS_DOWN, - vrf_id); - } else { - if_bfd_session_update(ifp, &dest_prefix, &src_prefix, BFD_STATUS_UP, - vrf_id); - } - - return 0; + char bfdst_str[32]; + char dest_str[64]; + char src_str[64]; + char vrf_str[64]; + struct prefix dest_prefix; + struct prefix src_prefix; + vrf_id_t vrf_id; + + ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDSTATUS_STR, bfdst_str); + + if (bfdst_str[0] == '\0') { + return -1; + } + + ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDDEST_STR, dest_str); + + if (dest_str[0] == '\0') { + zlog_debug("%s: Key %s not found in PTM msg", __func__, + ZEBRA_PTM_BFDDEST_STR); + return -1; + } + + ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDSRC_STR, src_str); + + if (src_str[0] == '\0') { + zlog_debug("%s: Key %s not found in PTM msg", __func__, + ZEBRA_PTM_BFDSRC_STR); + return -1; + } + + ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDVRF_STR, vrf_str); + + if (vrf_str[0] == '\0') { + zlog_debug("%s: Key %s not found in PTM msg", __func__, + ZEBRA_PTM_BFDVRF_STR); + return -1; + } + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "%s: Recv Port [%s] bfd status [%s] vrf [%s]" + " peer [%s] local [%s]", + __func__, ifp ? ifp->name : "N/A", bfdst_str, vrf_str, + dest_str, src_str); + + if (str2prefix(dest_str, &dest_prefix) == 0) { + zlog_err("%s: Peer addr %s not found", __func__, dest_str); + return -1; + } + + memset(&src_prefix, 0, sizeof(struct prefix)); + if (strcmp(ZEBRA_PTM_INVALID_SRC_IP, src_str)) { + if (str2prefix(src_str, &src_prefix) == 0) { + zlog_err("%s: Local addr %s not found", __func__, + src_str); + return -1; + } + } + + if (!strcmp(ZEBRA_PTM_INVALID_VRF, vrf_str) && ifp) { + vrf_id = ifp->vrf_id; + } else { + vrf_id = vrf_name_to_id(vrf_str); + } + + if (!strcmp(bfdst_str, ZEBRA_PTM_BFDSTATUS_DOWN_STR)) { + if_bfd_session_update(ifp, &dest_prefix, &src_prefix, + BFD_STATUS_DOWN, vrf_id); + } else { + if_bfd_session_update(ifp, &dest_prefix, &src_prefix, + BFD_STATUS_UP, vrf_id); + } + + return 0; } -static int -zebra_ptm_handle_cbl_msg(void *arg, void *in_ctxt, struct interface *ifp, - char *cbl_str) +static int zebra_ptm_handle_cbl_msg(void *arg, void *in_ctxt, + struct interface *ifp, char *cbl_str) { - int send_linkup = 0; - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s: Recv Port [%s] cbl status [%s]", __func__, - ifp->name, cbl_str); - - if (!strcmp(cbl_str, ZEBRA_PTM_PASS_STR) && - (ifp->ptm_status != ZEBRA_PTM_STATUS_UP)) { - - if (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN) - send_linkup = 1; - ifp->ptm_status = ZEBRA_PTM_STATUS_UP; - if (ifp->ptm_enable && if_is_no_ptm_operative (ifp) && send_linkup) - if_up (ifp); - } else if (!strcmp (cbl_str, ZEBRA_PTM_FAIL_STR) && - (ifp->ptm_status != ZEBRA_PTM_STATUS_DOWN)) { - ifp->ptm_status = ZEBRA_PTM_STATUS_DOWN; - if (ifp->ptm_enable && if_is_no_ptm_operative (ifp)) - if_down (ifp); - } - - return 0; + int send_linkup = 0; + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s: Recv Port [%s] cbl status [%s]", __func__, + ifp->name, cbl_str); + + if (!strcmp(cbl_str, ZEBRA_PTM_PASS_STR) + && (ifp->ptm_status != ZEBRA_PTM_STATUS_UP)) { + + if (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN) + send_linkup = 1; + ifp->ptm_status = ZEBRA_PTM_STATUS_UP; + if (ifp->ptm_enable && if_is_no_ptm_operative(ifp) + && send_linkup) + if_up(ifp); + } else if (!strcmp(cbl_str, ZEBRA_PTM_FAIL_STR) + && (ifp->ptm_status != ZEBRA_PTM_STATUS_DOWN)) { + ifp->ptm_status = ZEBRA_PTM_STATUS_DOWN; + if (ifp->ptm_enable && if_is_no_ptm_operative(ifp)) + if_down(ifp); + } + + return 0; } /* @@ -584,582 +569,563 @@ zebra_ptm_handle_cbl_msg(void *arg, void *in_ctxt, struct interface *ifp, * processing all the notifications from the PTM. * */ -static int -zebra_ptm_handle_msg_cb(void *arg, void *in_ctxt) +static int zebra_ptm_handle_msg_cb(void *arg, void *in_ctxt) { - struct interface *ifp = NULL; - char port_str[128]; - char cbl_str[32]; - char cmd_status_str[32]; - - ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_CMD_STATUS_STR, cmd_status_str); - - /* Drop command response messages */ - if (cmd_status_str[0] != '\0') { - return 0; - } - - ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_PORT_STR, port_str); - - if (port_str[0] == '\0') { - zlog_debug("%s: Key %s not found in PTM msg", __func__, - ZEBRA_PTM_PORT_STR); - return -1; - } - - if (strcmp(ZEBRA_PTM_INVALID_PORT_NAME, port_str)) { - ifp = if_lookup_by_name_all_vrf(port_str); - - if (!ifp) { - zlog_err("%s: %s not found in interface list", __func__, port_str); - return -1; - } - } - - ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_CBL_STR, cbl_str); - - if (cbl_str[0] == '\0') { - return zebra_ptm_handle_bfd_msg(arg, in_ctxt, ifp); - } else { - if (ifp) { - return zebra_ptm_handle_cbl_msg(arg, in_ctxt, ifp, cbl_str); - } else { - return -1; - } - } + struct interface *ifp = NULL; + char port_str[128]; + char cbl_str[32]; + char cmd_status_str[32]; + + ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_CMD_STATUS_STR, + cmd_status_str); + + /* Drop command response messages */ + if (cmd_status_str[0] != '\0') { + return 0; + } + + ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_PORT_STR, port_str); + + if (port_str[0] == '\0') { + zlog_debug("%s: Key %s not found in PTM msg", __func__, + ZEBRA_PTM_PORT_STR); + return -1; + } + + if (strcmp(ZEBRA_PTM_INVALID_PORT_NAME, port_str)) { + ifp = if_lookup_by_name_all_vrf(port_str); + + if (!ifp) { + zlog_err("%s: %s not found in interface list", __func__, + port_str); + return -1; + } + } + + ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_CBL_STR, cbl_str); + + if (cbl_str[0] == '\0') { + return zebra_ptm_handle_bfd_msg(arg, in_ctxt, ifp); + } else { + if (ifp) { + return zebra_ptm_handle_cbl_msg(arg, in_ctxt, ifp, + cbl_str); + } else { + return -1; + } + } } -int -zebra_ptm_sock_read (struct thread *thread) +int zebra_ptm_sock_read(struct thread *thread) { - int sock, done = 0; - int rc; - - errno = 0; - sock = THREAD_FD (thread); - - if (sock == -1) - return -1; - - /* PTM communicates in CSV format */ - while(!done) { - rc = ptm_lib_process_msg(ptm_hdl, sock, ptm_cb.in_data, ZEBRA_PTM_MAX_SOCKBUF, - NULL); - if (rc <= 0) - break; - } - - if (rc <= 0) { - if (((rc == 0) && !errno) || (errno && (errno != EWOULDBLOCK) && (errno != EAGAIN))) { - zlog_warn ("%s routing socket error: %s(%d) bytes %d", __func__, - safe_strerror (errno), errno, rc); - - close (ptm_cb.ptm_sock); - ptm_cb.ptm_sock = -1; - zebra_ptm_reset_status(0); - ptm_cb.t_timer = NULL; - thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time, - &ptm_cb.t_timer); - return (-1); - } - } - - ptm_cb.t_read = NULL; - thread_add_read(zebrad.master, zebra_ptm_sock_read, NULL, ptm_cb.ptm_sock, - &ptm_cb.t_read); - - return 0; + int sock, done = 0; + int rc; + + errno = 0; + sock = THREAD_FD(thread); + + if (sock == -1) + return -1; + + /* PTM communicates in CSV format */ + while (!done) { + rc = ptm_lib_process_msg(ptm_hdl, sock, ptm_cb.in_data, + ZEBRA_PTM_MAX_SOCKBUF, NULL); + if (rc <= 0) + break; + } + + if (rc <= 0) { + if (((rc == 0) && !errno) + || (errno && (errno != EWOULDBLOCK) && (errno != EAGAIN))) { + zlog_warn("%s routing socket error: %s(%d) bytes %d", + __func__, safe_strerror(errno), errno, rc); + + close(ptm_cb.ptm_sock); + ptm_cb.ptm_sock = -1; + zebra_ptm_reset_status(0); + ptm_cb.t_timer = NULL; + thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, + ptm_cb.reconnect_time, + &ptm_cb.t_timer); + return (-1); + } + } + + ptm_cb.t_read = NULL; + thread_add_read(zebrad.master, zebra_ptm_sock_read, NULL, + ptm_cb.ptm_sock, &ptm_cb.t_read); + + return 0; } /* BFD peer/dst register/update */ -int -zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length, - int command, struct zebra_vrf *zvrf) +int zebra_ptm_bfd_dst_register(struct zserv *client, int sock, u_short length, + int command, struct zebra_vrf *zvrf) { - struct stream *s; - struct prefix src_p; - struct prefix dst_p; - u_char multi_hop; - u_char multi_hop_cnt; - u_char detect_mul; - unsigned int min_rx_timer; - unsigned int min_tx_timer; - char if_name[INTERFACE_NAMSIZ]; - u_char len; - void *out_ctxt; - char buf[INET6_ADDRSTRLEN]; - char tmp_buf[64]; - int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; - unsigned int pid; - - if (command == ZEBRA_BFD_DEST_UPDATE) - client->bfd_peer_upd8_cnt++; - else - client->bfd_peer_add_cnt++; - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("bfd_dst_register msg from client %s: length=%d", - zebra_route_string(client->proto), length); - - if (ptm_cb.ptm_sock == -1) - { - ptm_cb.t_timer = NULL; - thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time, - &ptm_cb.t_timer); - return -1; - } - - ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); - sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_START_CMD); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf); - sprintf(tmp_buf, "%s", zebra_route_string(client->proto)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, - tmp_buf); - - s = client->ibuf; - - pid = stream_getl(s); - sprintf(tmp_buf, "%d", pid); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, tmp_buf); - - dst_p.family = stream_getw(s); - - if (dst_p.family == AF_INET) - dst_p.prefixlen = IPV4_MAX_BYTELEN; - else - dst_p.prefixlen = IPV6_MAX_BYTELEN; - - stream_get(&dst_p.u.prefix, s, dst_p.prefixlen); - if (dst_p.family == AF_INET) - { - inet_ntop(AF_INET, &dst_p.u.prefix4, buf, sizeof(buf)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_DST_IP_FIELD, buf); - } - else - { - inet_ntop(AF_INET6, &dst_p.u.prefix6, buf, sizeof(buf)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_DST_IP_FIELD, buf); - } - - min_rx_timer = stream_getl(s); - sprintf(tmp_buf, "%d", min_rx_timer); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MIN_RX_FIELD, - tmp_buf); - min_tx_timer = stream_getl(s); - sprintf(tmp_buf, "%d", min_tx_timer); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MIN_TX_FIELD, - tmp_buf); - detect_mul = stream_getc(s); - sprintf(tmp_buf, "%d", detect_mul); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_DETECT_MULT_FIELD, - tmp_buf); - - multi_hop = stream_getc(s); - if (multi_hop) - { - sprintf(tmp_buf, "%d", 1); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MULTI_HOP_FIELD, - tmp_buf); - src_p.family = stream_getw(s); - - if (src_p.family == AF_INET) - src_p.prefixlen = IPV4_MAX_BYTELEN; - else - src_p.prefixlen = IPV6_MAX_BYTELEN; - - stream_get(&src_p.u.prefix, s, src_p.prefixlen); - if (src_p.family == AF_INET) - { - inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, - ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); - } - else - { - inet_ntop(AF_INET6, &src_p.u.prefix6, buf, sizeof(buf)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, - ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); - } - - multi_hop_cnt = stream_getc(s); - sprintf(tmp_buf, "%d", multi_hop_cnt); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MAX_HOP_CNT_FIELD, - tmp_buf); - - if (zvrf_id (zvrf) != VRF_DEFAULT) - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_VRF_NAME_FIELD, - zvrf_name (zvrf)); - } - else - { - if (dst_p.family == AF_INET6) - { - src_p.family = stream_getw(s); - - if (src_p.family == AF_INET) - src_p.prefixlen = IPV4_MAX_BYTELEN; - else - src_p.prefixlen = IPV6_MAX_BYTELEN; - - stream_get(&src_p.u.prefix, s, src_p.prefixlen); - if (src_p.family == AF_INET) - { - inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, - ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); - } - else - { - inet_ntop(AF_INET6, &src_p.u.prefix6, buf, sizeof(buf)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, - ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); - } - } - len = stream_getc(s); - stream_get(if_name, s, len); - if_name[len] = '\0'; - - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_IFNAME_FIELD, - if_name); - } - - sprintf(tmp_buf, "%d", 1); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEND_EVENT, - tmp_buf); - - ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len); - - if (IS_ZEBRA_DEBUG_SEND) - zlog_debug ("%s: Sent message (%d) %s", __func__, data_len, - ptm_cb.out_data); - zebra_ptm_send_message(ptm_cb.out_data, data_len); - return 0; + struct stream *s; + struct prefix src_p; + struct prefix dst_p; + u_char multi_hop; + u_char multi_hop_cnt; + u_char detect_mul; + unsigned int min_rx_timer; + unsigned int min_tx_timer; + char if_name[INTERFACE_NAMSIZ]; + u_char len; + void *out_ctxt; + char buf[INET6_ADDRSTRLEN]; + char tmp_buf[64]; + int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; + unsigned int pid; + + if (command == ZEBRA_BFD_DEST_UPDATE) + client->bfd_peer_upd8_cnt++; + else + client->bfd_peer_add_cnt++; + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("bfd_dst_register msg from client %s: length=%d", + zebra_route_string(client->proto), length); + + if (ptm_cb.ptm_sock == -1) { + ptm_cb.t_timer = NULL; + thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, + ptm_cb.reconnect_time, &ptm_cb.t_timer); + return -1; + } + + ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); + sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_START_CMD); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf); + sprintf(tmp_buf, "%s", zebra_route_string(client->proto)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, + tmp_buf); + + s = client->ibuf; + + pid = stream_getl(s); + sprintf(tmp_buf, "%d", pid); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, + tmp_buf); + + dst_p.family = stream_getw(s); + + if (dst_p.family == AF_INET) + dst_p.prefixlen = IPV4_MAX_BYTELEN; + else + dst_p.prefixlen = IPV6_MAX_BYTELEN; + + stream_get(&dst_p.u.prefix, s, dst_p.prefixlen); + if (dst_p.family == AF_INET) { + inet_ntop(AF_INET, &dst_p.u.prefix4, buf, sizeof(buf)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_DST_IP_FIELD, buf); + } else { + inet_ntop(AF_INET6, &dst_p.u.prefix6, buf, sizeof(buf)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_DST_IP_FIELD, buf); + } + + min_rx_timer = stream_getl(s); + sprintf(tmp_buf, "%d", min_rx_timer); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MIN_RX_FIELD, + tmp_buf); + min_tx_timer = stream_getl(s); + sprintf(tmp_buf, "%d", min_tx_timer); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MIN_TX_FIELD, + tmp_buf); + detect_mul = stream_getc(s); + sprintf(tmp_buf, "%d", detect_mul); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_DETECT_MULT_FIELD, + tmp_buf); + + multi_hop = stream_getc(s); + if (multi_hop) { + sprintf(tmp_buf, "%d", 1); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_MULTI_HOP_FIELD, tmp_buf); + src_p.family = stream_getw(s); + + if (src_p.family == AF_INET) + src_p.prefixlen = IPV4_MAX_BYTELEN; + else + src_p.prefixlen = IPV6_MAX_BYTELEN; + + stream_get(&src_p.u.prefix, s, src_p.prefixlen); + if (src_p.family == AF_INET) { + inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); + } else { + inet_ntop(AF_INET6, &src_p.u.prefix6, buf, sizeof(buf)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); + } + + multi_hop_cnt = stream_getc(s); + sprintf(tmp_buf, "%d", multi_hop_cnt); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_MAX_HOP_CNT_FIELD, tmp_buf); + + if (zvrf_id(zvrf) != VRF_DEFAULT) + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_VRF_NAME_FIELD, + zvrf_name(zvrf)); + } else { + if (dst_p.family == AF_INET6) { + src_p.family = stream_getw(s); + + if (src_p.family == AF_INET) + src_p.prefixlen = IPV4_MAX_BYTELEN; + else + src_p.prefixlen = IPV6_MAX_BYTELEN; + + stream_get(&src_p.u.prefix, s, src_p.prefixlen); + if (src_p.family == AF_INET) { + inet_ntop(AF_INET, &src_p.u.prefix4, buf, + sizeof(buf)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_SRC_IP_FIELD, + buf); + } else { + inet_ntop(AF_INET6, &src_p.u.prefix6, buf, + sizeof(buf)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_SRC_IP_FIELD, + buf); + } + } + len = stream_getc(s); + stream_get(if_name, s, len); + if_name[len] = '\0'; + + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_IFNAME_FIELD, if_name); + } + + sprintf(tmp_buf, "%d", 1); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEND_EVENT, + tmp_buf); + + ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len); + + if (IS_ZEBRA_DEBUG_SEND) + zlog_debug("%s: Sent message (%d) %s", __func__, data_len, + ptm_cb.out_data); + zebra_ptm_send_message(ptm_cb.out_data, data_len); + return 0; } /* BFD peer/dst deregister */ -int -zebra_ptm_bfd_dst_deregister (struct zserv *client, int sock, u_short length, - struct zebra_vrf *zvrf) +int zebra_ptm_bfd_dst_deregister(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) { - struct stream *s; - struct prefix src_p; - struct prefix dst_p; - u_char multi_hop; - char if_name[INTERFACE_NAMSIZ]; - u_char len; - char buf[INET6_ADDRSTRLEN]; - char tmp_buf[64]; - int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; - void *out_ctxt; - unsigned int pid; - - client->bfd_peer_del_cnt++; - - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("bfd_dst_deregister msg from client %s: length=%d", - zebra_route_string(client->proto), length); - - if (ptm_cb.ptm_sock == -1) - { - ptm_cb.t_timer = NULL; - thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time, - &ptm_cb.t_timer); - return -1; - } - - ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); - - sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_STOP_CMD); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf); - - sprintf(tmp_buf, "%s", zebra_route_string(client->proto)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, - tmp_buf); - - s = client->ibuf; - - pid = stream_getl(s); - sprintf(tmp_buf, "%d", pid); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, tmp_buf); - - dst_p.family = stream_getw(s); - - if (dst_p.family == AF_INET) - dst_p.prefixlen = IPV4_MAX_BYTELEN; - else - dst_p.prefixlen = IPV6_MAX_BYTELEN; - - stream_get(&dst_p.u.prefix, s, dst_p.prefixlen); - if (dst_p.family == AF_INET) - inet_ntop(AF_INET, &dst_p.u.prefix4, buf, sizeof(buf)); - else - inet_ntop(AF_INET6, &dst_p.u.prefix6, buf, sizeof(buf)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_DST_IP_FIELD, buf); - - - multi_hop = stream_getc(s); - if (multi_hop) - { - sprintf(tmp_buf, "%d", 1); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MULTI_HOP_FIELD, - tmp_buf); - - src_p.family = stream_getw(s); - - if (src_p.family == AF_INET) - src_p.prefixlen = IPV4_MAX_BYTELEN; - else - src_p.prefixlen = IPV6_MAX_BYTELEN; - - stream_get(&src_p.u.prefix, s, src_p.prefixlen); - if (src_p.family == AF_INET) - inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf)); - else - inet_ntop(AF_INET6, &src_p.u.prefix6, buf, sizeof(buf)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, - ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); - - if (zvrf_id (zvrf) != VRF_DEFAULT) - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_VRF_NAME_FIELD, - zvrf_name (zvrf)); - } - else - { - if (dst_p.family == AF_INET6) - { - src_p.family = stream_getw(s); - - if (src_p.family == AF_INET) - src_p.prefixlen = IPV4_MAX_BYTELEN; - else - src_p.prefixlen = IPV6_MAX_BYTELEN; - - stream_get(&src_p.u.prefix, s, src_p.prefixlen); - if (src_p.family == AF_INET) - { - inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, - ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); - } - else - { - inet_ntop(AF_INET6, &src_p.u.prefix6, buf, sizeof(buf)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, - ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); - } - } - - len = stream_getc(s); - stream_get(if_name, s, len); - if_name[len] = '\0'; - - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_IFNAME_FIELD, - if_name); - } - - ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len); - if (IS_ZEBRA_DEBUG_SEND) - zlog_debug ("%s: Sent message (%d) %s", __func__, data_len, - ptm_cb.out_data); - - zebra_ptm_send_message(ptm_cb.out_data, data_len); - return 0; + struct stream *s; + struct prefix src_p; + struct prefix dst_p; + u_char multi_hop; + char if_name[INTERFACE_NAMSIZ]; + u_char len; + char buf[INET6_ADDRSTRLEN]; + char tmp_buf[64]; + int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; + void *out_ctxt; + unsigned int pid; + + client->bfd_peer_del_cnt++; + + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("bfd_dst_deregister msg from client %s: length=%d", + zebra_route_string(client->proto), length); + + if (ptm_cb.ptm_sock == -1) { + ptm_cb.t_timer = NULL; + thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, + ptm_cb.reconnect_time, &ptm_cb.t_timer); + return -1; + } + + ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); + + sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_STOP_CMD); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf); + + sprintf(tmp_buf, "%s", zebra_route_string(client->proto)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, + tmp_buf); + + s = client->ibuf; + + pid = stream_getl(s); + sprintf(tmp_buf, "%d", pid); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, + tmp_buf); + + dst_p.family = stream_getw(s); + + if (dst_p.family == AF_INET) + dst_p.prefixlen = IPV4_MAX_BYTELEN; + else + dst_p.prefixlen = IPV6_MAX_BYTELEN; + + stream_get(&dst_p.u.prefix, s, dst_p.prefixlen); + if (dst_p.family == AF_INET) + inet_ntop(AF_INET, &dst_p.u.prefix4, buf, sizeof(buf)); + else + inet_ntop(AF_INET6, &dst_p.u.prefix6, buf, sizeof(buf)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_DST_IP_FIELD, buf); + + + multi_hop = stream_getc(s); + if (multi_hop) { + sprintf(tmp_buf, "%d", 1); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_MULTI_HOP_FIELD, tmp_buf); + + src_p.family = stream_getw(s); + + if (src_p.family == AF_INET) + src_p.prefixlen = IPV4_MAX_BYTELEN; + else + src_p.prefixlen = IPV6_MAX_BYTELEN; + + stream_get(&src_p.u.prefix, s, src_p.prefixlen); + if (src_p.family == AF_INET) + inet_ntop(AF_INET, &src_p.u.prefix4, buf, sizeof(buf)); + else + inet_ntop(AF_INET6, &src_p.u.prefix6, buf, sizeof(buf)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_SRC_IP_FIELD, buf); + + if (zvrf_id(zvrf) != VRF_DEFAULT) + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_VRF_NAME_FIELD, + zvrf_name(zvrf)); + } else { + if (dst_p.family == AF_INET6) { + src_p.family = stream_getw(s); + + if (src_p.family == AF_INET) + src_p.prefixlen = IPV4_MAX_BYTELEN; + else + src_p.prefixlen = IPV6_MAX_BYTELEN; + + stream_get(&src_p.u.prefix, s, src_p.prefixlen); + if (src_p.family == AF_INET) { + inet_ntop(AF_INET, &src_p.u.prefix4, buf, + sizeof(buf)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_SRC_IP_FIELD, + buf); + } else { + inet_ntop(AF_INET6, &src_p.u.prefix6, buf, + sizeof(buf)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_SRC_IP_FIELD, + buf); + } + } + + len = stream_getc(s); + stream_get(if_name, s, len); + if_name[len] = '\0'; + + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_IFNAME_FIELD, if_name); + } + + ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len); + if (IS_ZEBRA_DEBUG_SEND) + zlog_debug("%s: Sent message (%d) %s", __func__, data_len, + ptm_cb.out_data); + + zebra_ptm_send_message(ptm_cb.out_data, data_len); + return 0; } /* BFD client register */ -int -zebra_ptm_bfd_client_register (struct zserv *client, int sock, u_short length) +int zebra_ptm_bfd_client_register(struct zserv *client, int sock, + u_short length) { - struct stream *s; - unsigned int pid; - void *out_ctxt; - char tmp_buf[64]; - int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; + struct stream *s; + unsigned int pid; + void *out_ctxt; + char tmp_buf[64]; + int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; - client->bfd_client_reg_cnt++; + client->bfd_client_reg_cnt++; - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("bfd_client_register msg from client %s: length=%d", - zebra_route_string(client->proto), length); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("bfd_client_register msg from client %s: length=%d", + zebra_route_string(client->proto), length); - if (ptm_cb.ptm_sock == -1) - { - ptm_cb.t_timer = NULL; - thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time, - &ptm_cb.t_timer); - return -1; - } + if (ptm_cb.ptm_sock == -1) { + ptm_cb.t_timer = NULL; + thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, + ptm_cb.reconnect_time, &ptm_cb.t_timer); + return -1; + } - ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); + ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); - sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_CLIENT_REG_CMD); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf); + sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_CLIENT_REG_CMD); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf); - sprintf(tmp_buf, "%s", zebra_route_string(client->proto)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, - tmp_buf); + sprintf(tmp_buf, "%s", zebra_route_string(client->proto)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, + tmp_buf); - s = client->ibuf; + s = client->ibuf; - pid = stream_getl(s); - sprintf(tmp_buf, "%d", pid); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, - tmp_buf); + pid = stream_getl(s); + sprintf(tmp_buf, "%d", pid); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, + tmp_buf); - ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len); + ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len); - if (IS_ZEBRA_DEBUG_SEND) - zlog_debug ("%s: Sent message (%d) %s", __func__, data_len, - ptm_cb.out_data); - zebra_ptm_send_message(ptm_cb.out_data, data_len); + if (IS_ZEBRA_DEBUG_SEND) + zlog_debug("%s: Sent message (%d) %s", __func__, data_len, + ptm_cb.out_data); + zebra_ptm_send_message(ptm_cb.out_data, data_len); - SET_FLAG(ptm_cb.client_flags[client->proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG); - return 0; + SET_FLAG(ptm_cb.client_flags[client->proto], + ZEBRA_PTM_BFD_CLIENT_FLAG_REG); + return 0; } /* BFD client deregister */ -void -zebra_ptm_bfd_client_deregister (int proto) +void zebra_ptm_bfd_client_deregister(int proto) { - void *out_ctxt; - char tmp_buf[64]; - int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; + void *out_ctxt; + char tmp_buf[64]; + int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; - if (proto != ZEBRA_ROUTE_OSPF && proto != ZEBRA_ROUTE_BGP - && proto != ZEBRA_ROUTE_OSPF6 && proto != ZEBRA_ROUTE_PIM) - return; + if (proto != ZEBRA_ROUTE_OSPF && proto != ZEBRA_ROUTE_BGP + && proto != ZEBRA_ROUTE_OSPF6 && proto != ZEBRA_ROUTE_PIM) + return; - if (IS_ZEBRA_DEBUG_EVENT) - zlog_err("bfd_client_deregister msg for client %s", - zebra_route_string(proto)); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_err("bfd_client_deregister msg for client %s", + zebra_route_string(proto)); - if (ptm_cb.ptm_sock == -1) - { - ptm_cb.t_timer = NULL; - thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time, - &ptm_cb.t_timer); - return; - } + if (ptm_cb.ptm_sock == -1) { + ptm_cb.t_timer = NULL; + thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, + ptm_cb.reconnect_time, &ptm_cb.t_timer); + return; + } - ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); + ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); - sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_CLIENT_DEREG_CMD); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf); + sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_CLIENT_DEREG_CMD); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf); - sprintf(tmp_buf, "%s", zebra_route_string(proto)); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, - tmp_buf); + sprintf(tmp_buf, "%s", zebra_route_string(proto)); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, + tmp_buf); - ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len); + ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len); - if (IS_ZEBRA_DEBUG_SEND) - zlog_debug ("%s: Sent message (%d) %s", __func__, data_len, - ptm_cb.out_data); + if (IS_ZEBRA_DEBUG_SEND) + zlog_debug("%s: Sent message (%d) %s", __func__, data_len, + ptm_cb.out_data); - zebra_ptm_send_message(ptm_cb.out_data, data_len); - UNSET_FLAG(ptm_cb.client_flags[proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG); + zebra_ptm_send_message(ptm_cb.out_data, data_len); + UNSET_FLAG(ptm_cb.client_flags[proto], ZEBRA_PTM_BFD_CLIENT_FLAG_REG); } -int -zebra_ptm_get_enable_state(void) +int zebra_ptm_get_enable_state(void) { - return ptm_cb.ptm_enable; + return ptm_cb.ptm_enable; } /* * zebra_ptm_get_status_str - Convert status to a display string. */ -static const char * -zebra_ptm_get_status_str(int status) +static const char *zebra_ptm_get_status_str(int status) { - switch (status) - { - case ZEBRA_PTM_STATUS_DOWN: - return "fail"; - case ZEBRA_PTM_STATUS_UP: - return "pass"; - case ZEBRA_PTM_STATUS_UNKNOWN: - default: - return "n/a"; - } + switch (status) { + case ZEBRA_PTM_STATUS_DOWN: + return "fail"; + case ZEBRA_PTM_STATUS_UP: + return "pass"; + case ZEBRA_PTM_STATUS_UNKNOWN: + default: + return "n/a"; + } } -void -zebra_ptm_show_status(struct vty *vty, struct interface *ifp) +void zebra_ptm_show_status(struct vty *vty, struct interface *ifp) { - vty_out (vty, " PTM status: "); - if (ifp->ptm_enable) { - vty_out (vty, "%s\n",zebra_ptm_get_status_str(ifp->ptm_status)); - } else { - vty_out (vty, "disabled\n"); - } + vty_out(vty, " PTM status: "); + if (ifp->ptm_enable) { + vty_out(vty, "%s\n", zebra_ptm_get_status_str(ifp->ptm_status)); + } else { + vty_out(vty, "disabled\n"); + } } -void -zebra_ptm_send_status_req(void) +void zebra_ptm_send_status_req(void) { - void *out_ctxt; - int len = ZEBRA_PTM_SEND_MAX_SOCKBUF; - - if (ptm_cb.ptm_enable) - { - ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); - ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, - ZEBRA_PTM_GET_STATUS_CMD); - ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &len); - - zebra_ptm_send_message(ptm_cb.out_data, len); - } + void *out_ctxt; + int len = ZEBRA_PTM_SEND_MAX_SOCKBUF; + + if (ptm_cb.ptm_enable) { + ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, + &out_ctxt); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, + ZEBRA_PTM_GET_STATUS_CMD); + ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &len); + + zebra_ptm_send_message(ptm_cb.out_data, len); + } } -void -zebra_ptm_reset_status(int ptm_disable) +void zebra_ptm_reset_status(int ptm_disable) { - struct vrf *vrf; - struct listnode *i; - struct interface *ifp; - int send_linkup; - - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - for (ALL_LIST_ELEMENTS_RO (vrf->iflist, i, ifp)) - { - send_linkup = 0; - if (ifp->ptm_enable) - { - if (!if_is_operative(ifp)) - send_linkup = 1; - - if (ptm_disable) - ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; - ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; - - if (if_is_operative (ifp) && send_linkup) - { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("%s: Bringing up interface %s", __func__, - ifp->name); - if_up (ifp); - } - } - } + struct vrf *vrf; + struct listnode *i; + struct interface *ifp; + int send_linkup; + + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + for (ALL_LIST_ELEMENTS_RO(vrf->iflist, i, ifp)) { + send_linkup = 0; + if (ifp->ptm_enable) { + if (!if_is_operative(ifp)) + send_linkup = 1; + + if (ptm_disable) + ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; + ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; + + if (if_is_operative(ifp) && send_linkup) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "%s: Bringing up interface %s", + __func__, ifp->name); + if_up(ifp); + } + } + } } -void -zebra_ptm_if_init(struct zebra_if *zebra_ifp) +void zebra_ptm_if_init(struct zebra_if *zebra_ifp) { - zebra_ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_UNSPEC; + zebra_ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_UNSPEC; } -void -zebra_ptm_if_set_ptm_state(struct interface *ifp, struct zebra_if *zebra_ifp) +void zebra_ptm_if_set_ptm_state(struct interface *ifp, + struct zebra_if *zebra_ifp) { - if (zebra_ifp && zebra_ifp->ptm_enable != ZEBRA_IF_PTM_ENABLE_UNSPEC) - ifp->ptm_enable = zebra_ifp->ptm_enable; + if (zebra_ifp && zebra_ifp->ptm_enable != ZEBRA_IF_PTM_ENABLE_UNSPEC) + ifp->ptm_enable = zebra_ifp->ptm_enable; } -void -zebra_ptm_if_write (struct vty *vty, struct zebra_if *zebra_ifp) +void zebra_ptm_if_write(struct vty *vty, struct zebra_if *zebra_ifp) { - if (zebra_ifp->ptm_enable == ZEBRA_IF_PTM_ENABLE_OFF) - vty_out (vty, " no ptm-enable\n"); + if (zebra_ifp->ptm_enable == ZEBRA_IF_PTM_ENABLE_OFF) + vty_out(vty, " no ptm-enable\n"); } diff --git a/zebra/zebra_ptm.h b/zebra/zebra_ptm.h index 28fe9c1de..9f9269ab5 100644 --- a/zebra/zebra_ptm.h +++ b/zebra/zebra_ptm.h @@ -29,23 +29,22 @@ extern const char ZEBRA_PTM_SOCK_NAME[]; #define ZEBRA_PTM_BFD_CLIENT_FLAG_REG (1 << 1) /* client registered with BFD */ /* Zebra ptm context block */ -struct zebra_ptm_cb -{ - int ptm_sock; /* ptm file descriptor. */ +struct zebra_ptm_cb { + int ptm_sock; /* ptm file descriptor. */ - struct buffer *wb; /* Buffer of data waiting to be written to ptm. */ + struct buffer *wb; /* Buffer of data waiting to be written to ptm. */ - struct thread *t_read; /* Thread for read */ - struct thread *t_write; /* Thread for write */ - struct thread *t_timer; /* Thread for timer */ + struct thread *t_read; /* Thread for read */ + struct thread *t_write; /* Thread for write */ + struct thread *t_timer; /* Thread for timer */ - char *out_data; - char *in_data; - int reconnect_time; + char *out_data; + char *in_data; + int reconnect_time; - int ptm_enable; - int pid; - u_int8_t client_flags[ZEBRA_ROUTE_MAX]; + int ptm_enable; + int pid; + u_int8_t client_flags[ZEBRA_ROUTE_MAX]; }; #define ZEBRA_PTM_STATUS_DOWN 0 @@ -57,22 +56,22 @@ struct zebra_ptm_cb #define ZEBRA_IF_PTM_ENABLE_ON 1 #define ZEBRA_IF_PTM_ENABLE_UNSPEC 2 -void zebra_ptm_init (void); +void zebra_ptm_init(void); void zebra_ptm_finish(void); -int zebra_ptm_connect (struct thread *t); -void zebra_ptm_write (struct vty *vty); +int zebra_ptm_connect(struct thread *t); +void zebra_ptm_write(struct vty *vty); int zebra_ptm_get_enable_state(void); -int zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length, - int command, struct zebra_vrf *zvrf); -int zebra_ptm_bfd_dst_deregister (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf); -void -zebra_ptm_show_status(struct vty *vty, struct interface *ifp); -int zebra_ptm_bfd_client_register (struct zserv *client, int sock, - u_short length); +int zebra_ptm_bfd_dst_register(struct zserv *client, int sock, u_short length, + int command, struct zebra_vrf *zvrf); +int zebra_ptm_bfd_dst_deregister(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf); +void zebra_ptm_show_status(struct vty *vty, struct interface *ifp); +int zebra_ptm_bfd_client_register(struct zserv *client, int sock, + u_short length); void zebra_ptm_if_init(struct zebra_if *zebra_ifp); -void zebra_ptm_if_set_ptm_state(struct interface *ifp, struct zebra_if *zebra_ifp); -void zebra_ptm_if_write (struct vty *vty, struct zebra_if *zebra_ifp); -void zebra_ptm_bfd_client_deregister (int proto); +void zebra_ptm_if_set_ptm_state(struct interface *ifp, + struct zebra_if *zebra_ifp); +void zebra_ptm_if_write(struct vty *vty, struct zebra_if *zebra_ifp); +void zebra_ptm_bfd_client_deregister(int proto); #endif diff --git a/zebra/zebra_ptm_redistribute.c b/zebra/zebra_ptm_redistribute.c index d6902142a..1378ea186 100644 --- a/zebra/zebra_ptm_redistribute.c +++ b/zebra/zebra_ptm_redistribute.c @@ -26,102 +26,100 @@ #include "zebra/zebra_ptm_redistribute.h" #include "zebra/zebra_memory.h" -static int -zsend_interface_bfd_update (int cmd, struct zserv *client, - struct interface *ifp, struct prefix *dp, - struct prefix *sp, int status, vrf_id_t vrf_id) +static int zsend_interface_bfd_update(int cmd, struct zserv *client, + struct interface *ifp, struct prefix *dp, + struct prefix *sp, int status, + vrf_id_t vrf_id) { - int blen; - struct stream *s; - - /* Check this client need interface information. */ - if (! client->ifinfo) - return 0; - - s = client->obuf; - stream_reset (s); - - zserv_create_header (s, cmd, vrf_id); - if (ifp) - stream_putl (s, ifp->ifindex); - else - stream_putl (s, 0); - - /* BFD destination prefix information. */ - stream_putc (s, dp->family); - blen = prefix_blen (dp); - stream_put (s, &dp->u.prefix, blen); - stream_putc (s, dp->prefixlen); - - /* BFD status */ - stream_putl(s, status); - - /* BFD source prefix information. */ - stream_putc (s, sp->family); - blen = prefix_blen (sp); - stream_put (s, &sp->u.prefix, blen); - stream_putc (s, sp->prefixlen); - - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); - - client->if_bfd_cnt++; - return zebra_server_send_message(client); + int blen; + struct stream *s; + + /* Check this client need interface information. */ + if (!client->ifinfo) + return 0; + + s = client->obuf; + stream_reset(s); + + zserv_create_header(s, cmd, vrf_id); + if (ifp) + stream_putl(s, ifp->ifindex); + else + stream_putl(s, 0); + + /* BFD destination prefix information. */ + stream_putc(s, dp->family); + blen = prefix_blen(dp); + stream_put(s, &dp->u.prefix, blen); + stream_putc(s, dp->prefixlen); + + /* BFD status */ + stream_putl(s, status); + + /* BFD source prefix information. */ + stream_putc(s, sp->family); + blen = prefix_blen(sp); + stream_put(s, &sp->u.prefix, blen); + stream_putc(s, sp->prefixlen); + + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); + + client->if_bfd_cnt++; + return zebra_server_send_message(client); } -void -zebra_interface_bfd_update (struct interface *ifp, struct prefix *dp, - struct prefix *sp, int status, vrf_id_t vrf_id) +void zebra_interface_bfd_update(struct interface *ifp, struct prefix *dp, + struct prefix *sp, int status, vrf_id_t vrf_id) { - struct listnode *node, *nnode; - struct zserv *client; - - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - { - /* Supporting for OSPF, BGP and PIM */ - if (client->proto != ZEBRA_ROUTE_OSPF && client->proto != ZEBRA_ROUTE_BGP - && client->proto != ZEBRA_ROUTE_OSPF6 && client->proto != ZEBRA_ROUTE_PIM) - continue; - - /* Notify to the protocol daemons. */ - zsend_interface_bfd_update (ZEBRA_INTERFACE_BFD_DEST_UPDATE, client, ifp, - dp, sp, status, vrf_id); - } + struct listnode *node, *nnode; + struct zserv *client; + + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { + /* Supporting for OSPF, BGP and PIM */ + if (client->proto != ZEBRA_ROUTE_OSPF + && client->proto != ZEBRA_ROUTE_BGP + && client->proto != ZEBRA_ROUTE_OSPF6 + && client->proto != ZEBRA_ROUTE_PIM) + continue; + + /* Notify to the protocol daemons. */ + zsend_interface_bfd_update(ZEBRA_INTERFACE_BFD_DEST_UPDATE, + client, ifp, dp, sp, status, vrf_id); + } } -static int -zsend_bfd_peer_replay (int cmd, struct zserv *client) +static int zsend_bfd_peer_replay(int cmd, struct zserv *client) { - struct stream *s; + struct stream *s; - s = client->obuf; - stream_reset (s); + s = client->obuf; + stream_reset(s); - zserv_create_header (s, cmd, VRF_DEFAULT); //Pending: adjust when multi-vrf bfd work + zserv_create_header( + s, cmd, VRF_DEFAULT); // Pending: adjust when multi-vrf bfd work - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); - client->bfd_peer_replay_cnt++; - return zebra_server_send_message(client); + client->bfd_peer_replay_cnt++; + return zebra_server_send_message(client); } -void -zebra_bfd_peer_replay_req (void) +void zebra_bfd_peer_replay_req(void) { - struct listnode *node, *nnode; - struct zserv *client; - - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - { - /* Supporting for BGP */ - if ((client->proto != ZEBRA_ROUTE_BGP) && - (client->proto != ZEBRA_ROUTE_OSPF) && - (client->proto != ZEBRA_ROUTE_OSPF6) && - (client->proto != ZEBRA_ROUTE_PIM)) - continue; - - /* Notify to the protocol daemons. */ - zsend_bfd_peer_replay (ZEBRA_BFD_DEST_REPLAY, client); - } + struct listnode *node, *nnode; + struct zserv *client; + + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { + /* Supporting for BGP */ + if ((client->proto != ZEBRA_ROUTE_BGP) + && (client->proto != ZEBRA_ROUTE_OSPF) + && (client->proto != ZEBRA_ROUTE_OSPF6) + && (client->proto != ZEBRA_ROUTE_PIM)) + continue; + + /* Notify to the protocol daemons. */ + zsend_bfd_peer_replay(ZEBRA_BFD_DEST_REPLAY, client); + } } diff --git a/zebra/zebra_ptm_redistribute.h b/zebra/zebra_ptm_redistribute.h index ac3873f24..c1b12bd0d 100644 --- a/zebra/zebra_ptm_redistribute.h +++ b/zebra/zebra_ptm_redistribute.h @@ -21,7 +21,7 @@ #ifndef _ZEBRA_PTM_REDISTRIBUTE_H #define _ZEBRA_PTM_REDISTRIBUTE_H -extern void zebra_interface_bfd_update (struct interface *, struct prefix *, - struct prefix *, int, vrf_id_t); -extern void zebra_bfd_peer_replay_req (void); +extern void zebra_interface_bfd_update(struct interface *, struct prefix *, + struct prefix *, int, vrf_id_t); +extern void zebra_bfd_peer_replay_req(void); #endif /* _ZEBRA_PTM_REDISTRIBUTE_H */ diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index b07a0cf05..98508aaa8 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -51,7 +51,8 @@ #include "zebra/interface.h" #include "zebra/connected.h" -DEFINE_HOOK(rib_update, (struct route_node *rn, const char *reason), (rn, reason)) +DEFINE_HOOK(rib_update, (struct route_node * rn, const char *reason), + (rn, reason)) /* Should we allow non Quagga processes to delete our routes */ extern int allow_delete; @@ -63,691 +64,652 @@ extern int allow_delete; int rib_process_hold_time = 10; /* Each route type's string and default distance value. */ -static const struct -{ - int key; - int distance; -} route_info[ZEBRA_ROUTE_MAX] = -{ - [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0}, - [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0}, - [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0}, - [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1}, - [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120}, - [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120}, - [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110}, - [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110}, - [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115}, - [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */}, - [ZEBRA_ROUTE_NHRP] = {ZEBRA_ROUTE_NHRP, 10}, - /* no entry/default: 150 */ +static const struct { + int key; + int distance; +} route_info[ZEBRA_ROUTE_MAX] = { + [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0}, + [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0}, + [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0}, + [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1}, + [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120}, + [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120}, + [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110}, + [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110}, + [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115}, + [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */}, + [ZEBRA_ROUTE_NHRP] = {ZEBRA_ROUTE_NHRP, 10}, + /* no entry/default: 150 */ }; /* RPF lookup behaviour */ static enum multicast_mode ipv4_multicast_mode = MCAST_NO_CONFIG; -static void __attribute__((format (printf, 5, 6))) -_rnode_zlog(const char *_func, vrf_id_t vrf_id, struct route_node *rn, int priority, - const char *msgfmt, ...) +static void __attribute__((format(printf, 5, 6))) +_rnode_zlog(const char *_func, vrf_id_t vrf_id, struct route_node *rn, + int priority, const char *msgfmt, ...) { - char buf[SRCDEST2STR_BUFFER + sizeof(" (MRIB)")]; - char msgbuf[512]; - va_list ap; + char buf[SRCDEST2STR_BUFFER + sizeof(" (MRIB)")]; + char msgbuf[512]; + va_list ap; - va_start(ap, msgfmt); - vsnprintf(msgbuf, sizeof(msgbuf), msgfmt, ap); - va_end(ap); + va_start(ap, msgfmt); + vsnprintf(msgbuf, sizeof(msgbuf), msgfmt, ap); + va_end(ap); - if (rn) - { - rib_table_info_t *info = srcdest_rnode_table_info (rn); - srcdest_rnode2str(rn, buf, sizeof(buf)); + if (rn) { + rib_table_info_t *info = srcdest_rnode_table_info(rn); + srcdest_rnode2str(rn, buf, sizeof(buf)); - if (info->safi == SAFI_MULTICAST) - strcat(buf, " (MRIB)"); - } - else - { - snprintf(buf, sizeof(buf), "{(route_node *) NULL}"); - } + if (info->safi == SAFI_MULTICAST) + strcat(buf, " (MRIB)"); + } else { + snprintf(buf, sizeof(buf), "{(route_node *) NULL}"); + } - zlog (priority, "%s: %d:%s: %s", _func, vrf_id, buf, msgbuf); + zlog(priority, "%s: %d:%s: %s", _func, vrf_id, buf, msgbuf); } -#define rnode_debug(node, vrf_id, ...) \ +#define rnode_debug(node, vrf_id, ...) \ _rnode_zlog(__func__, vrf_id, node, LOG_DEBUG, __VA_ARGS__) -#define rnode_info(node, ...) \ +#define rnode_info(node, ...) \ _rnode_zlog(__func__, vrf_id, node, LOG_INFO, __VA_ARGS__) -u_char -route_distance (int type) +u_char route_distance(int type) { - u_char distance; + u_char distance; - if ((unsigned)type >= array_size(route_info)) - distance = 150; - else - distance = route_info[type].distance; + if ((unsigned)type >= array_size(route_info)) + distance = 150; + else + distance = route_info[type].distance; - return distance; + return distance; } -int -is_zebra_valid_kernel_table(u_int32_t table_id) +int is_zebra_valid_kernel_table(u_int32_t table_id) { - if ((table_id > ZEBRA_KERNEL_TABLE_MAX)) - return 0; + if ((table_id > ZEBRA_KERNEL_TABLE_MAX)) + return 0; #ifdef linux - if ((table_id == RT_TABLE_UNSPEC) || - (table_id == RT_TABLE_LOCAL) || - (table_id == RT_TABLE_COMPAT)) - return 0; + if ((table_id == RT_TABLE_UNSPEC) || (table_id == RT_TABLE_LOCAL) + || (table_id == RT_TABLE_COMPAT)) + return 0; #endif - return 1; + return 1; } -int -is_zebra_main_routing_table(u_int32_t table_id) +int is_zebra_main_routing_table(u_int32_t table_id) { - if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default)) - return 1; - return 0; + if ((table_id == RT_TABLE_MAIN) + || (table_id == zebrad.rtm_table_default)) + return 1; + return 0; } -int -zebra_check_addr (struct prefix *p) +int zebra_check_addr(struct prefix *p) { - if (p->family == AF_INET) - { - u_int32_t addr; + if (p->family == AF_INET) { + u_int32_t addr; - addr = p->u.prefix4.s_addr; - addr = ntohl (addr); + addr = p->u.prefix4.s_addr; + addr = ntohl(addr); - if (IPV4_NET127 (addr) - || IN_CLASSD (addr) - || IPV4_LINKLOCAL(addr)) - return 0; - } - if (p->family == AF_INET6) - { - if (IN6_IS_ADDR_LOOPBACK (&p->u.prefix6)) - return 0; - if (IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6)) - return 0; - } - return 1; + if (IPV4_NET127(addr) || IN_CLASSD(addr) + || IPV4_LINKLOCAL(addr)) + return 0; + } + if (p->family == AF_INET6) { + if (IN6_IS_ADDR_LOOPBACK(&p->u.prefix6)) + return 0; + if (IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6)) + return 0; + } + return 1; } /* Add nexthop to the end of a rib node's nexthop list */ -void -route_entry_nexthop_add (struct route_entry *re, struct nexthop *nexthop) +void route_entry_nexthop_add(struct route_entry *re, struct nexthop *nexthop) { - nexthop_add(&re->nexthop, nexthop); - re->nexthop_num++; + nexthop_add(&re->nexthop, nexthop); + re->nexthop_num++; } - /** * copy_nexthop - copy a nexthop to the rib structure. */ -void -route_entry_copy_nexthops (struct route_entry *re, struct nexthop *nh) +void route_entry_copy_nexthops(struct route_entry *re, struct nexthop *nh) { - assert(!re->nexthop); - copy_nexthops(&re->nexthop, nh, NULL); - for (struct nexthop *nexthop = nh; nexthop; nexthop = nexthop->next) - re->nexthop_num++; + assert(!re->nexthop); + copy_nexthops(&re->nexthop, nh, NULL); + for (struct nexthop *nexthop = nh; nexthop; nexthop = nexthop->next) + re->nexthop_num++; } /* Delete specified nexthop from the list. */ -void -route_entry_nexthop_delete (struct route_entry *re, struct nexthop *nexthop) +void route_entry_nexthop_delete(struct route_entry *re, struct nexthop *nexthop) { - if (nexthop->next) - nexthop->next->prev = nexthop->prev; - if (nexthop->prev) - nexthop->prev->next = nexthop->next; - else - re->nexthop = nexthop->next; - re->nexthop_num--; + if (nexthop->next) + nexthop->next->prev = nexthop->prev; + if (nexthop->prev) + nexthop->prev->next = nexthop->next; + else + re->nexthop = nexthop->next; + re->nexthop_num--; } - -struct nexthop * -route_entry_nexthop_ifindex_add (struct route_entry *re, ifindex_t ifindex) +struct nexthop *route_entry_nexthop_ifindex_add(struct route_entry *re, + ifindex_t ifindex) { - struct nexthop *nexthop; + struct nexthop *nexthop; - nexthop = nexthop_new(); - nexthop->type = NEXTHOP_TYPE_IFINDEX; - nexthop->ifindex = ifindex; + nexthop = nexthop_new(); + nexthop->type = NEXTHOP_TYPE_IFINDEX; + nexthop->ifindex = ifindex; - route_entry_nexthop_add (re, nexthop); + route_entry_nexthop_add(re, nexthop); - return nexthop; + return nexthop; } -struct nexthop * -route_entry_nexthop_ipv4_add (struct route_entry *re, struct in_addr *ipv4, struct in_addr *src) +struct nexthop *route_entry_nexthop_ipv4_add(struct route_entry *re, + struct in_addr *ipv4, + struct in_addr *src) { - struct nexthop *nexthop; + struct nexthop *nexthop; - nexthop = nexthop_new(); - nexthop->type = NEXTHOP_TYPE_IPV4; - nexthop->gate.ipv4 = *ipv4; - if (src) - nexthop->src.ipv4 = *src; + nexthop = nexthop_new(); + nexthop->type = NEXTHOP_TYPE_IPV4; + nexthop->gate.ipv4 = *ipv4; + if (src) + nexthop->src.ipv4 = *src; - route_entry_nexthop_add (re, nexthop); + route_entry_nexthop_add(re, nexthop); - return nexthop; + return nexthop; } -struct nexthop * -route_entry_nexthop_ipv4_ifindex_add (struct route_entry *re, struct in_addr *ipv4, - struct in_addr *src, ifindex_t ifindex) +struct nexthop *route_entry_nexthop_ipv4_ifindex_add(struct route_entry *re, + struct in_addr *ipv4, + struct in_addr *src, + ifindex_t ifindex) { - struct nexthop *nexthop; - struct interface *ifp; + struct nexthop *nexthop; + struct interface *ifp; - nexthop = nexthop_new(); - nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX; - nexthop->gate.ipv4 = *ipv4; - if (src) - nexthop->src.ipv4 = *src; - nexthop->ifindex = ifindex; - ifp = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT); - /*Pending: need to think if null ifp here is ok during bootup? - There was a crash because ifp here was coming to be NULL */ - if (ifp) - if (connected_is_unnumbered(ifp)) { - SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK); - } + nexthop = nexthop_new(); + nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX; + nexthop->gate.ipv4 = *ipv4; + if (src) + nexthop->src.ipv4 = *src; + nexthop->ifindex = ifindex; + ifp = if_lookup_by_index(nexthop->ifindex, VRF_DEFAULT); + /*Pending: need to think if null ifp here is ok during bootup? + There was a crash because ifp here was coming to be NULL */ + if (ifp) + if (connected_is_unnumbered(ifp)) { + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK); + } - route_entry_nexthop_add (re, nexthop); + route_entry_nexthop_add(re, nexthop); - return nexthop; + return nexthop; } -struct nexthop * -route_entry_nexthop_ipv6_add (struct route_entry *re, struct in6_addr *ipv6) +struct nexthop *route_entry_nexthop_ipv6_add(struct route_entry *re, + struct in6_addr *ipv6) { - struct nexthop *nexthop; + struct nexthop *nexthop; - nexthop = nexthop_new(); - nexthop->type = NEXTHOP_TYPE_IPV6; - nexthop->gate.ipv6 = *ipv6; + nexthop = nexthop_new(); + nexthop->type = NEXTHOP_TYPE_IPV6; + nexthop->gate.ipv6 = *ipv6; - route_entry_nexthop_add (re, nexthop); + route_entry_nexthop_add(re, nexthop); - return nexthop; + return nexthop; } -struct nexthop * -route_entry_nexthop_ipv6_ifindex_add (struct route_entry *re, struct in6_addr *ipv6, - ifindex_t ifindex) +struct nexthop *route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re, + struct in6_addr *ipv6, + ifindex_t ifindex) { - struct nexthop *nexthop; + struct nexthop *nexthop; - nexthop = nexthop_new(); - nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX; - nexthop->gate.ipv6 = *ipv6; - nexthop->ifindex = ifindex; + nexthop = nexthop_new(); + nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX; + nexthop->gate.ipv6 = *ipv6; + nexthop->ifindex = ifindex; - route_entry_nexthop_add (re, nexthop); + route_entry_nexthop_add(re, nexthop); - return nexthop; + return nexthop; } -struct nexthop * -route_entry_nexthop_blackhole_add (struct route_entry *re) +struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *re) { - struct nexthop *nexthop; + struct nexthop *nexthop; - nexthop = nexthop_new(); - nexthop->type = NEXTHOP_TYPE_BLACKHOLE; - SET_FLAG (re->flags, ZEBRA_FLAG_BLACKHOLE); + nexthop = nexthop_new(); + nexthop->type = NEXTHOP_TYPE_BLACKHOLE; + SET_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE); - route_entry_nexthop_add (re, nexthop); + route_entry_nexthop_add(re, nexthop); - return nexthop; + return nexthop; } -static void -nexthop_set_resolved (afi_t afi, struct nexthop *newhop, struct nexthop *nexthop) +static void nexthop_set_resolved(afi_t afi, struct nexthop *newhop, + struct nexthop *nexthop) { - struct nexthop *resolved_hop; + struct nexthop *resolved_hop; - resolved_hop = nexthop_new(); - SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE); - /* If the resolving route specifies a gateway, use it */ - if (newhop->type == NEXTHOP_TYPE_IPV4 - || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - { - resolved_hop->type = newhop->type; - resolved_hop->gate.ipv4 = newhop->gate.ipv4; + resolved_hop = nexthop_new(); + SET_FLAG(resolved_hop->flags, NEXTHOP_FLAG_ACTIVE); + /* If the resolving route specifies a gateway, use it */ + if (newhop->type == NEXTHOP_TYPE_IPV4 + || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { + resolved_hop->type = newhop->type; + resolved_hop->gate.ipv4 = newhop->gate.ipv4; - if (newhop->ifindex) - { - resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX; - resolved_hop->ifindex = newhop->ifindex; - if (newhop->flags & NEXTHOP_FLAG_ONLINK) - resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; + if (newhop->ifindex) { + resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX; + resolved_hop->ifindex = newhop->ifindex; + if (newhop->flags & NEXTHOP_FLAG_ONLINK) + resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; + } } - } - if (newhop->type == NEXTHOP_TYPE_IPV6 - || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - { - resolved_hop->type = newhop->type; - resolved_hop->gate.ipv6 = newhop->gate.ipv6; - - if (newhop->ifindex) - { - resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX; - resolved_hop->ifindex = newhop->ifindex; + if (newhop->type == NEXTHOP_TYPE_IPV6 + || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { + resolved_hop->type = newhop->type; + resolved_hop->gate.ipv6 = newhop->gate.ipv6; + + if (newhop->ifindex) { + resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX; + resolved_hop->ifindex = newhop->ifindex; + } } - } - /* If the resolving route is an interface route, - * it means the gateway we are looking up is connected - * to that interface. (The actual network is _not_ onlink). - * Therefore, the resolved route should have the original - * gateway as nexthop as it is directly connected. - * - * On Linux, we have to set the onlink netlink flag because - * otherwise, the kernel won't accept the route. - */ - if (newhop->type == NEXTHOP_TYPE_IFINDEX) - { - resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; - if (afi == AFI_IP) - { - resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX; - resolved_hop->gate.ipv4 = nexthop->gate.ipv4; - } - else if (afi == AFI_IP6) - { - resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX; - resolved_hop->gate.ipv6 = nexthop->gate.ipv6; + /* If the resolving route is an interface route, + * it means the gateway we are looking up is connected + * to that interface. (The actual network is _not_ onlink). + * Therefore, the resolved route should have the original + * gateway as nexthop as it is directly connected. + * + * On Linux, we have to set the onlink netlink flag because + * otherwise, the kernel won't accept the route. + */ + if (newhop->type == NEXTHOP_TYPE_IFINDEX) { + resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; + if (afi == AFI_IP) { + resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX; + resolved_hop->gate.ipv4 = nexthop->gate.ipv4; + } else if (afi == AFI_IP6) { + resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX; + resolved_hop->gate.ipv6 = nexthop->gate.ipv6; + } + resolved_hop->ifindex = newhop->ifindex; } - resolved_hop->ifindex = newhop->ifindex; - } - resolved_hop->rparent = nexthop; - nexthop_add(&nexthop->resolved, resolved_hop); + resolved_hop->rparent = nexthop; + nexthop_add(&nexthop->resolved, resolved_hop); } /* If force flag is not set, do not modify falgs at all for uninstall the route from FIB. */ -static int -nexthop_active (afi_t afi, struct route_entry *re, struct nexthop *nexthop, int set, - struct route_node *top) -{ - struct prefix p; - struct route_table *table; - struct route_node *rn; - struct route_entry *match; - int resolved; - struct nexthop *newhop; - struct interface *ifp; - - if ((nexthop->type == NEXTHOP_TYPE_IPV4) || nexthop->type == NEXTHOP_TYPE_IPV6) - nexthop->ifindex = 0; - - if (set) - { - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE); - zebra_deregister_rnh_static_nexthops(re->vrf_id, nexthop->resolved, top); - nexthops_free(nexthop->resolved); - nexthop->resolved = NULL; - re->nexthop_mtu = 0; - } - - /* Skip nexthops that have been filtered out due to route-map */ - /* The nexthops are specific to this route and so the same */ - /* nexthop for a different route may not have this flag set */ - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED)) - return 0; - - /* - * Check to see if we should trust the passed in information - * for UNNUMBERED interfaces as that we won't find the GW - * address in the routing table. - */ - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) - { - ifp = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT); - if (ifp && connected_is_unnumbered(ifp)) - { - if (if_is_operative(ifp)) - return 1; - else - return 0; +static int nexthop_active(afi_t afi, struct route_entry *re, + struct nexthop *nexthop, int set, + struct route_node *top) +{ + struct prefix p; + struct route_table *table; + struct route_node *rn; + struct route_entry *match; + int resolved; + struct nexthop *newhop; + struct interface *ifp; + + if ((nexthop->type == NEXTHOP_TYPE_IPV4) + || nexthop->type == NEXTHOP_TYPE_IPV6) + nexthop->ifindex = 0; + + if (set) { + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE); + zebra_deregister_rnh_static_nexthops(re->vrf_id, + nexthop->resolved, top); + nexthops_free(nexthop->resolved); + nexthop->resolved = NULL; + re->nexthop_mtu = 0; } - else - return 0; - } - - /* Make lookup prefix. */ - memset (&p, 0, sizeof (struct prefix)); - switch (afi) - { - case AFI_IP: - p.family = AF_INET; - p.prefixlen = IPV4_MAX_PREFIXLEN; - p.u.prefix4 = nexthop->gate.ipv4; - break; - case AFI_IP6: - p.family = AF_INET6; - p.prefixlen = IPV6_MAX_PREFIXLEN; - p.u.prefix6 = nexthop->gate.ipv6; - break; - default: - assert (afi != AFI_IP && afi != AFI_IP6); - break; - } - /* Lookup table. */ - table = zebra_vrf_table (afi, SAFI_UNICAST, re->vrf_id); - if (! table) - return 0; - - rn = route_node_match (table, (struct prefix *) &p); - while (rn) - { - route_unlock_node (rn); - - /* If lookup self prefix return immediately. */ - if (rn == top) - return 0; - - /* Pick up selected route. */ - /* However, do not resolve over default route unless explicitly allowed. */ - if (is_default_prefix (&rn->p) && - !nh_resolve_via_default (p.family)) - return 0; - RNODE_FOREACH_RE (rn, match) - { - if (CHECK_FLAG (match->status, ROUTE_ENTRY_REMOVED)) - continue; - - /* if the next hop is imported from another table, skip it */ - if (match->type == ZEBRA_ROUTE_TABLE) - continue; - if (CHECK_FLAG (match->status, ROUTE_ENTRY_SELECTED_FIB)) - break; + /* Skip nexthops that have been filtered out due to route-map */ + /* The nexthops are specific to this route and so the same */ + /* nexthop for a different route may not have this flag set */ + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED)) + return 0; + + /* + * Check to see if we should trust the passed in information + * for UNNUMBERED interfaces as that we won't find the GW + * address in the routing table. + */ + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) { + ifp = if_lookup_by_index(nexthop->ifindex, VRF_DEFAULT); + if (ifp && connected_is_unnumbered(ifp)) { + if (if_is_operative(ifp)) + return 1; + else + return 0; + } else + return 0; } - /* If there is no selected route or matched route is EGP, go up - tree. */ - if (! match) - { - do { - rn = rn->parent; - } while (rn && rn->info == NULL); - if (rn) - route_lock_node (rn); - - continue; + /* Make lookup prefix. */ + memset(&p, 0, sizeof(struct prefix)); + switch (afi) { + case AFI_IP: + p.family = AF_INET; + p.prefixlen = IPV4_MAX_PREFIXLEN; + p.u.prefix4 = nexthop->gate.ipv4; + break; + case AFI_IP6: + p.family = AF_INET6; + p.prefixlen = IPV6_MAX_PREFIXLEN; + p.u.prefix6 = nexthop->gate.ipv6; + break; + default: + assert(afi != AFI_IP && afi != AFI_IP6); + break; } + /* Lookup table. */ + table = zebra_vrf_table(afi, SAFI_UNICAST, re->vrf_id); + if (!table) + return 0; + + rn = route_node_match(table, (struct prefix *)&p); + while (rn) { + route_unlock_node(rn); + + /* If lookup self prefix return immediately. */ + if (rn == top) + return 0; + + /* Pick up selected route. */ + /* However, do not resolve over default route unless explicitly + * allowed. */ + if (is_default_prefix(&rn->p) + && !nh_resolve_via_default(p.family)) + return 0; + + RNODE_FOREACH_RE(rn, match) + { + if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED)) + continue; + + /* if the next hop is imported from another table, skip + * it */ + if (match->type == ZEBRA_ROUTE_TABLE) + continue; + if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB)) + break; + } - /* If the longest prefix match for the nexthop yields - * a blackhole, mark it as inactive. */ - if (CHECK_FLAG (match->flags, ZEBRA_FLAG_BLACKHOLE) - || CHECK_FLAG (match->flags, ZEBRA_FLAG_REJECT)) - return 0; + /* If there is no selected route or matched route is EGP, go up + tree. */ + if (!match) { + do { + rn = rn->parent; + } while (rn && rn->info == NULL); + if (rn) + route_lock_node(rn); - if (match->type == ZEBRA_ROUTE_CONNECT) - { - /* Directly point connected route. */ - newhop = match->nexthop; - if (newhop) - { - if (nexthop->type == NEXTHOP_TYPE_IPV4 || - nexthop->type == NEXTHOP_TYPE_IPV6) - nexthop->ifindex = newhop->ifindex; - } - return 1; - } - else if (CHECK_FLAG (re->flags, ZEBRA_FLAG_INTERNAL)) - { - resolved = 0; - for (ALL_NEXTHOPS(match->nexthop, newhop)) - if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB) - && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE)) - { - if (set) - { - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE); - SET_FLAG(re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); - - nexthop_set_resolved(afi, newhop, nexthop); - } - resolved = 1; - } - return resolved; - } - else if (re->type == ZEBRA_ROUTE_STATIC) - { - resolved = 0; - for (ALL_NEXTHOPS(match->nexthop, newhop)) - if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)) - { - if (set) - { - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE); - - nexthop_set_resolved(afi, newhop, nexthop); - } - resolved = 1; - } - if (resolved && set) - re->nexthop_mtu = match->mtu; - return resolved; - } - else - { - return 0; + continue; + } + + /* If the longest prefix match for the nexthop yields + * a blackhole, mark it as inactive. */ + if (CHECK_FLAG(match->flags, ZEBRA_FLAG_BLACKHOLE) + || CHECK_FLAG(match->flags, ZEBRA_FLAG_REJECT)) + return 0; + + if (match->type == ZEBRA_ROUTE_CONNECT) { + /* Directly point connected route. */ + newhop = match->nexthop; + if (newhop) { + if (nexthop->type == NEXTHOP_TYPE_IPV4 + || nexthop->type == NEXTHOP_TYPE_IPV6) + nexthop->ifindex = newhop->ifindex; + } + return 1; + } else if (CHECK_FLAG(re->flags, ZEBRA_FLAG_INTERNAL)) { + resolved = 0; + for (ALL_NEXTHOPS(match->nexthop, newhop)) + if (CHECK_FLAG(newhop->flags, NEXTHOP_FLAG_FIB) + && !CHECK_FLAG(newhop->flags, + NEXTHOP_FLAG_RECURSIVE)) { + if (set) { + SET_FLAG( + nexthop->flags, + NEXTHOP_FLAG_RECURSIVE); + SET_FLAG( + re->status, + ROUTE_ENTRY_NEXTHOPS_CHANGED); + + nexthop_set_resolved( + afi, newhop, nexthop); + } + resolved = 1; + } + return resolved; + } else if (re->type == ZEBRA_ROUTE_STATIC) { + resolved = 0; + for (ALL_NEXTHOPS(match->nexthop, newhop)) + if (CHECK_FLAG(newhop->flags, + NEXTHOP_FLAG_FIB)) { + if (set) { + SET_FLAG( + nexthop->flags, + NEXTHOP_FLAG_RECURSIVE); + + nexthop_set_resolved( + afi, newhop, nexthop); + } + resolved = 1; + } + if (resolved && set) + re->nexthop_mtu = match->mtu; + return resolved; + } else { + return 0; + } } - } - return 0; + return 0; } -struct route_entry * -rib_match (afi_t afi, safi_t safi, vrf_id_t vrf_id, - union g_addr *addr, struct route_node **rn_out) -{ - struct prefix p; - struct route_table *table; - struct route_node *rn; - struct route_entry *match; - struct nexthop *newhop; +struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id, + union g_addr *addr, struct route_node **rn_out) +{ + struct prefix p; + struct route_table *table; + struct route_node *rn; + struct route_entry *match; + struct nexthop *newhop; + + /* Lookup table. */ + table = zebra_vrf_table(afi, safi, vrf_id); + if (!table) + return 0; + + memset(&p, 0, sizeof(struct prefix)); + p.family = afi; + if (afi == AFI_IP) { + p.u.prefix4 = addr->ipv4; + p.prefixlen = IPV4_MAX_PREFIXLEN; + } else { + p.u.prefix6 = addr->ipv6; + p.prefixlen = IPV6_MAX_PREFIXLEN; + } - /* Lookup table. */ - table = zebra_vrf_table (afi, safi, vrf_id); - if (! table) - return 0; + rn = route_node_match(table, (struct prefix *)&p); - memset (&p, 0, sizeof (struct prefix)); - p.family = afi; - if (afi == AFI_IP) - { - p.u.prefix4 = addr->ipv4; - p.prefixlen = IPV4_MAX_PREFIXLEN; - } - else - { - p.u.prefix6 = addr->ipv6; - p.prefixlen = IPV6_MAX_PREFIXLEN; - } + while (rn) { + route_unlock_node(rn); - rn = route_node_match (table, (struct prefix *) &p); + /* Pick up selected route. */ + RNODE_FOREACH_RE(rn, match) + { + if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED)) + continue; + if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB)) + break; + } - while (rn) - { - route_unlock_node (rn); - - /* Pick up selected route. */ - RNODE_FOREACH_RE (rn, match) - { - if (CHECK_FLAG (match->status, ROUTE_ENTRY_REMOVED)) - continue; - if (CHECK_FLAG (match->status, ROUTE_ENTRY_SELECTED_FIB)) - break; + /* If there is no selected route or matched route is EGP, go up + tree. */ + if (!match) { + do { + rn = rn->parent; + } while (rn && rn->info == NULL); + if (rn) + route_lock_node(rn); + } else { + if (match->type != ZEBRA_ROUTE_CONNECT) { + int found = 0; + for (ALL_NEXTHOPS(match->nexthop, newhop)) + if (CHECK_FLAG(newhop->flags, + NEXTHOP_FLAG_FIB)) { + found = 1; + break; + } + if (!found) + return NULL; + } + + if (rn_out) + *rn_out = rn; + return match; + } } - - /* If there is no selected route or matched route is EGP, go up - tree. */ - if (! match) - { - do { - rn = rn->parent; - } while (rn && rn->info == NULL); - if (rn) - route_lock_node (rn); + return NULL; +} + +struct route_entry *rib_match_ipv4_multicast(vrf_id_t vrf_id, + struct in_addr addr, + struct route_node **rn_out) +{ + struct route_entry *re = NULL, *mre = NULL, *ure = NULL; + struct route_node *m_rn = NULL, *u_rn = NULL; + union g_addr gaddr = {.ipv4 = addr}; + + switch (ipv4_multicast_mode) { + case MCAST_MRIB_ONLY: + return rib_match(AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, + rn_out); + case MCAST_URIB_ONLY: + return rib_match(AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, rn_out); + case MCAST_NO_CONFIG: + case MCAST_MIX_MRIB_FIRST: + re = mre = rib_match(AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, + &m_rn); + if (!mre) + re = ure = rib_match(AFI_IP, SAFI_UNICAST, vrf_id, + &gaddr, &u_rn); + break; + case MCAST_MIX_DISTANCE: + mre = rib_match(AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn); + ure = rib_match(AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, &u_rn); + if (mre && ure) + re = ure->distance < mre->distance ? ure : mre; + else if (mre) + re = mre; + else if (ure) + re = ure; + break; + case MCAST_MIX_PFXLEN: + mre = rib_match(AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn); + ure = rib_match(AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, &u_rn); + if (mre && ure) + re = u_rn->p.prefixlen > m_rn->p.prefixlen ? ure : mre; + else if (mre) + re = mre; + else if (ure) + re = ure; + break; } - else - { - if (match->type != ZEBRA_ROUTE_CONNECT) - { - int found = 0; - for (ALL_NEXTHOPS(match->nexthop, newhop)) - if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)) - { - found = 1; - break; - } - if (!found) - return NULL; - } - if (rn_out) - *rn_out = rn; - return match; - } - } - return NULL; -} + if (rn_out) + *rn_out = (re == mre) ? m_rn : u_rn; -struct route_entry * -rib_match_ipv4_multicast (vrf_id_t vrf_id, struct in_addr addr, struct route_node **rn_out) -{ - struct route_entry *re = NULL, *mre = NULL, *ure = NULL; - struct route_node *m_rn = NULL, *u_rn = NULL; - union g_addr gaddr = { .ipv4 = addr }; + if (IS_ZEBRA_DEBUG_RIB) { + char buf[BUFSIZ]; + inet_ntop(AF_INET, &addr, buf, BUFSIZ); - switch (ipv4_multicast_mode) - { - case MCAST_MRIB_ONLY: - return rib_match (AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, rn_out); - case MCAST_URIB_ONLY: - return rib_match (AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, rn_out); - case MCAST_NO_CONFIG: - case MCAST_MIX_MRIB_FIRST: - re = mre = rib_match (AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn); - if (!mre) - re = ure = rib_match (AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, &u_rn); - break; - case MCAST_MIX_DISTANCE: - mre = rib_match (AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn); - ure = rib_match (AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, &u_rn); - if (mre && ure) - re = ure->distance < mre->distance ? ure : mre; - else if (mre) - re = mre; - else if (ure) - re = ure; - break; - case MCAST_MIX_PFXLEN: - mre = rib_match (AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn); - ure = rib_match (AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, &u_rn); - if (mre && ure) - re = u_rn->p.prefixlen > m_rn->p.prefixlen ? ure : mre; - else if (mre) - re = mre; - else if (ure) - re = ure; - break; - } - - if (rn_out) - *rn_out = (re == mre) ? m_rn : u_rn; - - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[BUFSIZ]; - inet_ntop (AF_INET, &addr, buf, BUFSIZ); - - zlog_debug("%s: %s: found %s, using %s", - __func__, buf, - mre ? (ure ? "MRIB+URIB" : "MRIB") : - ure ? "URIB" : "nothing", - re == ure ? "URIB" : re == mre ? "MRIB" : "none"); - } - return re; + zlog_debug("%s: %s: found %s, using %s", __func__, buf, + mre ? (ure ? "MRIB+URIB" : "MRIB") + : ure ? "URIB" : "nothing", + re == ure ? "URIB" : re == mre ? "MRIB" : "none"); + } + return re; } -void -multicast_mode_ipv4_set (enum multicast_mode mode) +void multicast_mode_ipv4_set(enum multicast_mode mode) { - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug("%s: multicast lookup mode set (%d)", __func__, mode); - ipv4_multicast_mode = mode; + if (IS_ZEBRA_DEBUG_RIB) + zlog_debug("%s: multicast lookup mode set (%d)", __func__, + mode); + ipv4_multicast_mode = mode; } -enum multicast_mode -multicast_mode_ipv4_get (void) +enum multicast_mode multicast_mode_ipv4_get(void) { - return ipv4_multicast_mode; + return ipv4_multicast_mode; } -struct route_entry * -rib_lookup_ipv4 (struct prefix_ipv4 *p, vrf_id_t vrf_id) +struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id) { - struct route_table *table; - struct route_node *rn; - struct route_entry *match; - struct nexthop *nexthop; + struct route_table *table; + struct route_node *rn; + struct route_entry *match; + struct nexthop *nexthop; - /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (! table) - return 0; + /* Lookup table. */ + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); + if (!table) + return 0; - rn = route_node_lookup (table, (struct prefix *) p); + rn = route_node_lookup(table, (struct prefix *)p); - /* No route for this prefix. */ - if (! rn) - return NULL; + /* No route for this prefix. */ + if (!rn) + return NULL; - /* Unlock node. */ - route_unlock_node (rn); + /* Unlock node. */ + route_unlock_node(rn); - RNODE_FOREACH_RE (rn, match) - { - if (CHECK_FLAG (match->status, ROUTE_ENTRY_REMOVED)) - continue; - if (CHECK_FLAG (match->status, ROUTE_ENTRY_SELECTED_FIB)) - break; - } + RNODE_FOREACH_RE(rn, match) + { + if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED)) + continue; + if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB)) + break; + } - if (! match) - return NULL; + if (!match) + return NULL; - if (match->type == ZEBRA_ROUTE_CONNECT) - return match; + if (match->type == ZEBRA_ROUTE_CONNECT) + return match; - for (ALL_NEXTHOPS(match->nexthop, nexthop)) - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - return match; + for (ALL_NEXTHOPS(match->nexthop, nexthop)) + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) + return match; - return NULL; + return NULL; } /* @@ -762,73 +724,76 @@ rib_lookup_ipv4 (struct prefix_ipv4 *p, vrf_id_t vrf_id) * 2: connected route found * 3: no matches found */ -int -rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate, - vrf_id_t vrf_id) +int rib_lookup_ipv4_route(struct prefix_ipv4 *p, union sockunion *qgate, + vrf_id_t vrf_id) { - struct route_table *table; - struct route_node *rn; - struct route_entry *match; - struct nexthop *nexthop; - int nexthops_active; + struct route_table *table; + struct route_node *rn; + struct route_entry *match; + struct nexthop *nexthop; + int nexthops_active; - /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (! table) - return ZEBRA_RIB_LOOKUP_ERROR; + /* Lookup table. */ + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); + if (!table) + return ZEBRA_RIB_LOOKUP_ERROR; - /* Scan the RIB table for exactly matching RIB entry. */ - rn = route_node_lookup (table, (struct prefix *) p); + /* Scan the RIB table for exactly matching RIB entry. */ + rn = route_node_lookup(table, (struct prefix *)p); - /* No route for this prefix. */ - if (! rn) - return ZEBRA_RIB_NOTFOUND; + /* No route for this prefix. */ + if (!rn) + return ZEBRA_RIB_NOTFOUND; - /* Unlock node. */ - route_unlock_node (rn); + /* Unlock node. */ + route_unlock_node(rn); - /* Find out if a "selected" RR for the discovered RIB entry exists ever. */ - RNODE_FOREACH_RE (rn, match) - { - if (CHECK_FLAG (match->status, ROUTE_ENTRY_REMOVED)) - continue; - if (CHECK_FLAG (match->status, ROUTE_ENTRY_SELECTED_FIB)) - break; - } + /* Find out if a "selected" RR for the discovered RIB entry exists ever. + */ + RNODE_FOREACH_RE(rn, match) + { + if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED)) + continue; + if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB)) + break; + } - /* None such found :( */ - if (!match) - return ZEBRA_RIB_NOTFOUND; - - if (match->type == ZEBRA_ROUTE_CONNECT) - return ZEBRA_RIB_FOUND_CONNECTED; - - /* Ok, we have a cood candidate, let's check it's nexthop list... */ - nexthops_active = 0; - for (ALL_NEXTHOPS(match->nexthop, nexthop)) - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - { - nexthops_active = 1; - if (nexthop->gate.ipv4.s_addr == sockunion2ip (qgate)) - return ZEBRA_RIB_FOUND_EXACT; - if (IS_ZEBRA_DEBUG_RIB) - { - char gate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN]; - inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN); - inet_ntop (AF_INET, &sockunion2ip(qgate), qgate_buf, INET_ADDRSTRLEN); - zlog_debug ("%s: qgate == %s, %s == %s", __func__, - qgate_buf, nexthop->rparent ? "rgate" : "gate", gate_buf); - } - } - - if (nexthops_active) - return ZEBRA_RIB_FOUND_NOGATE; - - return ZEBRA_RIB_NOTFOUND; -} - -#define RIB_SYSTEM_ROUTE(R) \ - ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT) + /* None such found :( */ + if (!match) + return ZEBRA_RIB_NOTFOUND; + + if (match->type == ZEBRA_ROUTE_CONNECT) + return ZEBRA_RIB_FOUND_CONNECTED; + + /* Ok, we have a cood candidate, let's check it's nexthop list... */ + nexthops_active = 0; + for (ALL_NEXTHOPS(match->nexthop, nexthop)) + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) { + nexthops_active = 1; + if (nexthop->gate.ipv4.s_addr == sockunion2ip(qgate)) + return ZEBRA_RIB_FOUND_EXACT; + if (IS_ZEBRA_DEBUG_RIB) { + char gate_buf[INET_ADDRSTRLEN], + qgate_buf[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &nexthop->gate.ipv4.s_addr, + gate_buf, INET_ADDRSTRLEN); + inet_ntop(AF_INET, &sockunion2ip(qgate), + qgate_buf, INET_ADDRSTRLEN); + zlog_debug("%s: qgate == %s, %s == %s", + __func__, qgate_buf, + nexthop->rparent ? "rgate" : "gate", + gate_buf); + } + } + + if (nexthops_active) + return ZEBRA_RIB_FOUND_NOGATE; + + return ZEBRA_RIB_NOTFOUND; +} + +#define RIB_SYSTEM_ROUTE(R) \ + ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT) /* This function verifies reachability of one given nexthop, which can be * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored @@ -840,114 +805,107 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate, * The return value is the final value of 'ACTIVE' flag. */ -static unsigned -nexthop_active_check (struct route_node *rn, struct route_entry *re, - struct nexthop *nexthop, int set) -{ - struct interface *ifp; - route_map_result_t ret = RMAP_MATCH; - int family; - char buf[SRCDEST2STR_BUFFER]; - struct prefix *p, *src_p; - srcdest_rnode_prefixes (rn, &p, &src_p); - - if (rn->p.family == AF_INET) - family = AFI_IP; - else if (rn->p.family == AF_INET6) - family = AFI_IP6; - else - family = 0; - switch (nexthop->type) - { - case NEXTHOP_TYPE_IFINDEX: - ifp = if_lookup_by_index (nexthop->ifindex, re->vrf_id); - if (ifp && if_is_operative(ifp)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - break; - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - family = AFI_IP; - if (nexthop_active (AFI_IP, re, nexthop, set, rn)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - break; - case NEXTHOP_TYPE_IPV6: - family = AFI_IP6; - if (nexthop_active (AFI_IP6, re, nexthop, set, rn)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - break; - case NEXTHOP_TYPE_IPV6_IFINDEX: - /* RFC 5549, v4 prefix with v6 NH */ - if (rn->p.family != AF_INET) - family = AFI_IP6; - if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6)) - { - ifp = if_lookup_by_index (nexthop->ifindex, re->vrf_id); - if (ifp && if_is_operative(ifp)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); +static unsigned nexthop_active_check(struct route_node *rn, + struct route_entry *re, + struct nexthop *nexthop, int set) +{ + struct interface *ifp; + route_map_result_t ret = RMAP_MATCH; + int family; + char buf[SRCDEST2STR_BUFFER]; + struct prefix *p, *src_p; + srcdest_rnode_prefixes(rn, &p, &src_p); + + if (rn->p.family == AF_INET) + family = AFI_IP; + else if (rn->p.family == AF_INET6) + family = AFI_IP6; + else + family = 0; + switch (nexthop->type) { + case NEXTHOP_TYPE_IFINDEX: + ifp = if_lookup_by_index(nexthop->ifindex, re->vrf_id); + if (ifp && if_is_operative(ifp)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + break; + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + family = AFI_IP; + if (nexthop_active(AFI_IP, re, nexthop, set, rn)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + break; + case NEXTHOP_TYPE_IPV6: + family = AFI_IP6; + if (nexthop_active(AFI_IP6, re, nexthop, set, rn)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + /* RFC 5549, v4 prefix with v6 NH */ + if (rn->p.family != AF_INET) + family = AFI_IP6; + if (IN6_IS_ADDR_LINKLOCAL(&nexthop->gate.ipv6)) { + ifp = if_lookup_by_index(nexthop->ifindex, re->vrf_id); + if (ifp && if_is_operative(ifp)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + } else { + if (nexthop_active(AFI_IP6, re, nexthop, set, rn)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + } + break; + case NEXTHOP_TYPE_BLACKHOLE: + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + break; + default: + break; + } + if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + return 0; + + /* XXX: What exactly do those checks do? Do we support + * e.g. IPv4 routes with IPv6 nexthops or vice versa? */ + if (RIB_SYSTEM_ROUTE(re) || (family == AFI_IP && p->family != AF_INET) + || (family == AFI_IP6 && p->family != AF_INET6)) + return CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + + /* The original code didn't determine the family correctly + * e.g. for NEXTHOP_TYPE_IFINDEX. Retrieve the correct afi + * from the rib_table_info in those cases. + * Possibly it may be better to use only the rib_table_info + * in every case. + */ + if (!family) { + rib_table_info_t *info; + + info = srcdest_rnode_table_info(rn); + family = info->afi; } - else - { - if (nexthop_active (AFI_IP6, re, nexthop, set, rn)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - } - break; - case NEXTHOP_TYPE_BLACKHOLE: - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - break; - default: - break; - } - if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - return 0; - - /* XXX: What exactly do those checks do? Do we support - * e.g. IPv4 routes with IPv6 nexthops or vice versa? */ - if (RIB_SYSTEM_ROUTE(re) || - (family == AFI_IP && p->family != AF_INET) || - (family == AFI_IP6 && p->family != AF_INET6)) - return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - - /* The original code didn't determine the family correctly - * e.g. for NEXTHOP_TYPE_IFINDEX. Retrieve the correct afi - * from the rib_table_info in those cases. - * Possibly it may be better to use only the rib_table_info - * in every case. - */ - if (!family) - { - rib_table_info_t *info; - - info = srcdest_rnode_table_info(rn); - family = info->afi; - } - - memset(&nexthop->rmap_src.ipv6, 0, sizeof(union g_addr)); - /* It'll get set if required inside */ - ret = zebra_route_map_check(family, re->type, p, nexthop, re->vrf_id, - re->tag); - if (ret == RMAP_DENYMATCH) - { - if (IS_ZEBRA_DEBUG_RIB) - { - srcdest_rnode2str(rn, buf, sizeof(buf)); - zlog_debug("%u:%s: Filtering out with NH out %s due to route map", - re->vrf_id, buf, - ifindex2ifname (nexthop->ifindex, re->vrf_id)); + memset(&nexthop->rmap_src.ipv6, 0, sizeof(union g_addr)); + + /* It'll get set if required inside */ + ret = zebra_route_map_check(family, re->type, p, nexthop, re->vrf_id, + re->tag); + if (ret == RMAP_DENYMATCH) { + if (IS_ZEBRA_DEBUG_RIB) { + srcdest_rnode2str(rn, buf, sizeof(buf)); + zlog_debug( + "%u:%s: Filtering out with NH out %s due to route map", + re->vrf_id, buf, + ifindex2ifname(nexthop->ifindex, re->vrf_id)); + } + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); } - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - } - return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); + return CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); } /* Iterate over all nexthops of the given RIB entry and refresh their @@ -959,180 +917,170 @@ nexthop_active_check (struct route_node *rn, struct route_entry *re, * Return value is the new number of active nexthops. */ -static int -nexthop_active_update (struct route_node *rn, struct route_entry *re, int set) -{ - struct nexthop *nexthop; - union g_addr prev_src; - unsigned int prev_active, new_active, old_num_nh; - ifindex_t prev_index; - old_num_nh = re->nexthop_active_num; - - re->nexthop_active_num = 0; - UNSET_FLAG (re->status, ROUTE_ENTRY_CHANGED); - - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - { - /* No protocol daemon provides src and so we're skipping tracking it */ - prev_src = nexthop->rmap_src; - prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - prev_index = nexthop->ifindex; - if ((new_active = nexthop_active_check (rn, re, nexthop, set))) - re->nexthop_active_num++; - /* Don't allow src setting on IPv6 addr for now */ - if (prev_active != new_active || - prev_index != nexthop->ifindex || - ((nexthop->type >= NEXTHOP_TYPE_IFINDEX && - nexthop->type < NEXTHOP_TYPE_IPV6) && - prev_src.ipv4.s_addr != nexthop->rmap_src.ipv4.s_addr) || - ((nexthop->type >= NEXTHOP_TYPE_IPV6 && - nexthop->type < NEXTHOP_TYPE_BLACKHOLE) && - !(IPV6_ADDR_SAME (&prev_src.ipv6, &nexthop->rmap_src.ipv6)))) - { - SET_FLAG (re->status, ROUTE_ENTRY_CHANGED); - SET_FLAG (re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); - } - } - - if (old_num_nh != re->nexthop_active_num) - SET_FLAG (re->status, ROUTE_ENTRY_CHANGED); - - if (CHECK_FLAG (re->status, ROUTE_ENTRY_CHANGED)) - { - SET_FLAG (re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); - } +static int nexthop_active_update(struct route_node *rn, struct route_entry *re, + int set) +{ + struct nexthop *nexthop; + union g_addr prev_src; + unsigned int prev_active, new_active, old_num_nh; + ifindex_t prev_index; + old_num_nh = re->nexthop_active_num; + + re->nexthop_active_num = 0; + UNSET_FLAG(re->status, ROUTE_ENTRY_CHANGED); + + for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) { + /* No protocol daemon provides src and so we're skipping + * tracking it */ + prev_src = nexthop->rmap_src; + prev_active = CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + prev_index = nexthop->ifindex; + if ((new_active = nexthop_active_check(rn, re, nexthop, set))) + re->nexthop_active_num++; + /* Don't allow src setting on IPv6 addr for now */ + if (prev_active != new_active || prev_index != nexthop->ifindex + || ((nexthop->type >= NEXTHOP_TYPE_IFINDEX + && nexthop->type < NEXTHOP_TYPE_IPV6) + && prev_src.ipv4.s_addr + != nexthop->rmap_src.ipv4.s_addr) + || ((nexthop->type >= NEXTHOP_TYPE_IPV6 + && nexthop->type < NEXTHOP_TYPE_BLACKHOLE) + && !(IPV6_ADDR_SAME(&prev_src.ipv6, + &nexthop->rmap_src.ipv6)))) { + SET_FLAG(re->status, ROUTE_ENTRY_CHANGED); + SET_FLAG(re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); + } + } + + if (old_num_nh != re->nexthop_active_num) + SET_FLAG(re->status, ROUTE_ENTRY_CHANGED); - return re->nexthop_active_num; + if (CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED)) { + SET_FLAG(re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); + } + + return re->nexthop_active_num; } /* * Is this RIB labeled-unicast? It must be of type BGP and all paths * (nexthops) must have a label. */ -int -zebra_rib_labeled_unicast (struct route_entry *re) +int zebra_rib_labeled_unicast(struct route_entry *re) { - struct nexthop *nexthop = NULL; + struct nexthop *nexthop = NULL; - if (re->type != ZEBRA_ROUTE_BGP) - return 0; + if (re->type != ZEBRA_ROUTE_BGP) + return 0; - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - if (!nexthop->nh_label || !nexthop->nh_label->num_labels) - return 0; + for (ALL_NEXTHOPS(re->nexthop, nexthop)) + if (!nexthop->nh_label || !nexthop->nh_label->num_labels) + return 0; - return 1; + return 1; } /* Update flag indicates whether this is a "replace" or not. Currently, this * is only used for IPv4. */ -int -rib_install_kernel (struct route_node *rn, struct route_entry *re, struct route_entry *old) +int rib_install_kernel(struct route_node *rn, struct route_entry *re, + struct route_entry *old) { - int ret = 0; - struct nexthop *nexthop; - rib_table_info_t *info = srcdest_rnode_table_info(rn); - struct prefix *p, *src_p; - struct zebra_vrf *zvrf = vrf_info_lookup (re->vrf_id); - - srcdest_rnode_prefixes (rn, &p, &src_p); + int ret = 0; + struct nexthop *nexthop; + rib_table_info_t *info = srcdest_rnode_table_info(rn); + struct prefix *p, *src_p; + struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id); - if (info->safi != SAFI_UNICAST) - { - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - return ret; - } + srcdest_rnode_prefixes(rn, &p, &src_p); - /* - * Make sure we update the FPM any time we send new information to - * the kernel. - */ - hook_call(rib_update, rn, "installing in kernel"); - ret = kernel_route_rib (p, src_p, old, re); - zvrf->installs++; + if (info->safi != SAFI_UNICAST) { + for (ALL_NEXTHOPS(re->nexthop, nexthop)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + return ret; + } - /* If install succeeds, update FIB flag for nexthops. */ - if (!ret) - { - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - } + /* + * Make sure we update the FPM any time we send new information to + * the kernel. + */ + hook_call(rib_update, rn, "installing in kernel"); + ret = kernel_route_rib(p, src_p, old, re); + zvrf->installs++; + + /* If install succeeds, update FIB flag for nexthops. */ + if (!ret) { + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + continue; + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + } + } - return ret; + return ret; } /* Uninstall the route from kernel. */ -int -rib_uninstall_kernel (struct route_node *rn, struct route_entry *re) +int rib_uninstall_kernel(struct route_node *rn, struct route_entry *re) { - int ret = 0; - struct nexthop *nexthop; - rib_table_info_t *info = srcdest_rnode_table_info(rn); - struct prefix *p, *src_p; - struct zebra_vrf *zvrf = vrf_info_lookup (re->vrf_id); + int ret = 0; + struct nexthop *nexthop; + rib_table_info_t *info = srcdest_rnode_table_info(rn); + struct prefix *p, *src_p; + struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id); - srcdest_rnode_prefixes (rn, &p, &src_p); + srcdest_rnode_prefixes(rn, &p, &src_p); - if (info->safi != SAFI_UNICAST) - { - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - return ret; - } + if (info->safi != SAFI_UNICAST) { + for (ALL_NEXTHOPS(re->nexthop, nexthop)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + return ret; + } - /* - * Make sure we update the FPM any time we send new information to - * the kernel. - */ - hook_call(rib_update, rn, "uninstalling from kernel"); - ret = kernel_route_rib (p, src_p, re, NULL); - zvrf->removals++; + /* + * Make sure we update the FPM any time we send new information to + * the kernel. + */ + hook_call(rib_update, rn, "uninstalling from kernel"); + ret = kernel_route_rib(p, src_p, re, NULL); + zvrf->removals++; - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); + for (ALL_NEXTHOPS(re->nexthop, nexthop)) + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); - return ret; + return ret; } /* Uninstall the route from kernel. */ -static void -rib_uninstall (struct route_node *rn, struct route_entry *re) +static void rib_uninstall(struct route_node *rn, struct route_entry *re) { - rib_table_info_t *info = srcdest_rnode_table_info(rn); + rib_table_info_t *info = srcdest_rnode_table_info(rn); - if (CHECK_FLAG (re->status, ROUTE_ENTRY_SELECTED_FIB)) - { - if (info->safi == SAFI_UNICAST) - hook_call(rib_update, rn, "rib_uninstall"); + if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) { + if (info->safi == SAFI_UNICAST) + hook_call(rib_update, rn, "rib_uninstall"); - if (! RIB_SYSTEM_ROUTE (re)) - rib_uninstall_kernel (rn, re); + if (!RIB_SYSTEM_ROUTE(re)) + rib_uninstall_kernel(rn, re); - /* If labeled-unicast route, uninstall transit LSP. */ - if (zebra_rib_labeled_unicast (re)) - zebra_mpls_lsp_uninstall (info->zvrf, rn, re); + /* If labeled-unicast route, uninstall transit LSP. */ + if (zebra_rib_labeled_unicast(re)) + zebra_mpls_lsp_uninstall(info->zvrf, rn, re); - UNSET_FLAG (re->status, ROUTE_ENTRY_SELECTED_FIB); - } + UNSET_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB); + } - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_SELECTED)) - { - struct prefix *p, *src_p; - srcdest_rnode_prefixes (rn, &p, &src_p); + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) { + struct prefix *p, *src_p; + srcdest_rnode_prefixes(rn, &p, &src_p); - redistribute_delete (p, src_p, re); - UNSET_FLAG (re->flags, ZEBRA_FLAG_SELECTED); - } + redistribute_delete(p, src_p, re); + UNSET_FLAG(re->flags, ZEBRA_FLAG_SELECTED); + } } /* @@ -1140,23 +1088,21 @@ rib_uninstall (struct route_node *rn, struct route_entry *re) * * Returns TRUE if the given dest can be deleted from the table. */ -static int -rib_can_delete_dest (rib_dest_t *dest) +static int rib_can_delete_dest(rib_dest_t *dest) { - if (dest->routes) - { - return 0; - } + if (dest->routes) { + return 0; + } - /* - * Don't delete the dest if we have to update the FPM about this - * prefix. - */ - if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM) || - CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM)) - return 0; + /* + * Don't delete the dest if we have to update the FPM about this + * prefix. + */ + if (CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_FPM) + || CHECK_FLAG(dest->flags, RIB_DEST_SENT_TO_FPM)) + return 0; - return 1; + return 1; } /* @@ -1167,544 +1113,540 @@ rib_can_delete_dest (rib_dest_t *dest) * * Returns TRUE if the dest was deleted, FALSE otherwise. */ -int -rib_gc_dest (struct route_node *rn) +int rib_gc_dest(struct route_node *rn) { - rib_dest_t *dest; - struct zebra_vrf *zvrf; + rib_dest_t *dest; + struct zebra_vrf *zvrf; - dest = rib_dest_from_rnode (rn); - if (!dest) - return 0; + dest = rib_dest_from_rnode(rn); + if (!dest) + return 0; - if (!rib_can_delete_dest (dest)) - return 0; + if (!rib_can_delete_dest(dest)) + return 0; - zvrf = rib_dest_vrf (dest); - if (IS_ZEBRA_DEBUG_RIB) - rnode_debug (rn, zvrf_id (zvrf), "removing dest from table"); + zvrf = rib_dest_vrf(dest); + if (IS_ZEBRA_DEBUG_RIB) + rnode_debug(rn, zvrf_id(zvrf), "removing dest from table"); - dest->rnode = NULL; - XFREE (MTYPE_RIB_DEST, dest); - rn->info = NULL; + dest->rnode = NULL; + XFREE(MTYPE_RIB_DEST, dest); + rn->info = NULL; - /* - * Release the one reference that we keep on the route node. - */ - route_unlock_node (rn); - return 1; + /* + * Release the one reference that we keep on the route node. + */ + route_unlock_node(rn); + return 1; } -static void -rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn, - struct route_entry *new) +static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn, + struct route_entry *new) { - hook_call(rib_update, rn, "new route selected"); + hook_call(rib_update, rn, "new route selected"); - /* Update real nexthop. This may actually determine if nexthop is active or not. */ - if (!nexthop_active_update (rn, new, 1)) - { - UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED); - return; - } + /* Update real nexthop. This may actually determine if nexthop is active + * or not. */ + if (!nexthop_active_update(rn, new, 1)) { + UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED); + return; + } - SET_FLAG (new->status, ROUTE_ENTRY_SELECTED_FIB); - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[SRCDEST2STR_BUFFER]; - srcdest_rnode2str(rn, buf, sizeof(buf)); - zlog_debug ("%u:%s: Adding route rn %p, re %p (type %d)", - zvrf_id (zvrf), buf, rn, new, new->type); - } + SET_FLAG(new->status, ROUTE_ENTRY_SELECTED_FIB); + if (IS_ZEBRA_DEBUG_RIB) { + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); + zlog_debug("%u:%s: Adding route rn %p, re %p (type %d)", + zvrf_id(zvrf), buf, rn, new, new->type); + } - /* If labeled-unicast route, install transit LSP. */ - if (zebra_rib_labeled_unicast (new)) - zebra_mpls_lsp_install (zvrf, rn, new); + /* If labeled-unicast route, install transit LSP. */ + if (zebra_rib_labeled_unicast(new)) + zebra_mpls_lsp_install(zvrf, rn, new); - if (!RIB_SYSTEM_ROUTE (new)) - { - if (rib_install_kernel (rn, new, NULL)) - { - char buf[SRCDEST2STR_BUFFER]; - srcdest_rnode2str(rn, buf, sizeof(buf)); - zlog_warn ("%u:%s: Route install failed", - zvrf_id (zvrf), buf); - } - } + if (!RIB_SYSTEM_ROUTE(new)) { + if (rib_install_kernel(rn, new, NULL)) { + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); + zlog_warn("%u:%s: Route install failed", zvrf_id(zvrf), + buf); + } + } - UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED); + UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED); } -static void -rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn, - struct route_entry *old) +static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn, + struct route_entry *old) { - hook_call(rib_update, rn, "removing existing route"); + hook_call(rib_update, rn, "removing existing route"); - /* Uninstall from kernel. */ - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[SRCDEST2STR_BUFFER]; - srcdest_rnode2str(rn, buf, sizeof(buf)); - zlog_debug ("%u:%s: Deleting route rn %p, re %p (type %d)", - zvrf_id (zvrf), buf, rn, old, old->type); - } + /* Uninstall from kernel. */ + if (IS_ZEBRA_DEBUG_RIB) { + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); + zlog_debug("%u:%s: Deleting route rn %p, re %p (type %d)", + zvrf_id(zvrf), buf, rn, old, old->type); + } - /* If labeled-unicast route, uninstall transit LSP. */ - if (zebra_rib_labeled_unicast (old)) - zebra_mpls_lsp_uninstall (zvrf, rn, old); + /* If labeled-unicast route, uninstall transit LSP. */ + if (zebra_rib_labeled_unicast(old)) + zebra_mpls_lsp_uninstall(zvrf, rn, old); + + if (!RIB_SYSTEM_ROUTE(old)) + rib_uninstall_kernel(rn, old); + + UNSET_FLAG(old->status, ROUTE_ENTRY_SELECTED_FIB); + + /* Update nexthop for route, reset changed flag. */ + nexthop_active_update(rn, old, 1); + UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED); +} + +static void rib_process_update_fib(struct zebra_vrf *zvrf, + struct route_node *rn, + struct route_entry *old, + struct route_entry *new) +{ + struct nexthop *nexthop = NULL; + int nh_active = 0; + int installed = 1; + + /* + * We have to install or update if a new route has been selected or + * something has changed. + */ + if (new != old || CHECK_FLAG(new->status, ROUTE_ENTRY_CHANGED)) { + hook_call(rib_update, rn, "updating existing route"); + + /* Update the nexthop; we could determine here that nexthop is + * inactive. */ + if (nexthop_active_update(rn, new, 1)) + nh_active = 1; + + /* If nexthop is active, install the selected route, if + * appropriate. If + * the install succeeds, cleanup flags for prior route, if + * different from + * newly selected. + */ + if (nh_active) { + if (IS_ZEBRA_DEBUG_RIB) { + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); + if (new != old) + zlog_debug( + "%u:%s: Updating route rn %p, re %p (type %d) " + "old %p (type %d)", + zvrf_id(zvrf), buf, rn, new, + new->type, old, old->type); + else + zlog_debug( + "%u:%s: Updating route rn %p, re %p (type %d)", + zvrf_id(zvrf), buf, rn, new, + new->type); + } + + /* If labeled-unicast route, uninstall transit LSP. */ + if (zebra_rib_labeled_unicast(old)) + zebra_mpls_lsp_uninstall(zvrf, rn, old); + + /* Non-system route should be installed. */ + if (!RIB_SYSTEM_ROUTE(new)) { + /* If labeled-unicast route, install transit + * LSP. */ + if (zebra_rib_labeled_unicast(new)) + zebra_mpls_lsp_install(zvrf, rn, new); + + if (rib_install_kernel(rn, new, old)) { + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); + installed = 0; + zlog_warn("%u:%s: Route install failed", + zvrf_id(zvrf), buf); + } + } + + /* If install succeeded or system route, cleanup flags + * for prior route. */ + if (installed && new != old) { + if (RIB_SYSTEM_ROUTE(new)) { + if (!RIB_SYSTEM_ROUTE(old)) + rib_uninstall_kernel(rn, old); + } else { + for (nexthop = old->nexthop; nexthop; + nexthop = nexthop->next) + UNSET_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB); + } + } + + /* Update for redistribution. */ + if (installed) + SET_FLAG(new->status, ROUTE_ENTRY_SELECTED_FIB); + } - if (!RIB_SYSTEM_ROUTE (old)) - rib_uninstall_kernel (rn, old); + /* + * If nexthop for selected route is not active or install + * failed, we + * may need to uninstall and delete for redistribution. + */ + if (!nh_active || !installed) { + if (IS_ZEBRA_DEBUG_RIB) { + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); + if (new != old) + zlog_debug( + "%u:%s: Deleting route rn %p, re %p (type %d) " + "old %p (type %d) - %s", + zvrf_id(zvrf), buf, rn, new, + new->type, old, old->type, + nh_active ? "install failed" + : "nexthop inactive"); + else + zlog_debug( + "%u:%s: Deleting route rn %p, re %p (type %d) - %s", + zvrf_id(zvrf), buf, rn, new, + new->type, + nh_active ? "install failed" + : "nexthop inactive"); + } + + /* If labeled-unicast route, uninstall transit LSP. */ + if (zebra_rib_labeled_unicast(old)) + zebra_mpls_lsp_uninstall(zvrf, rn, old); + + if (!RIB_SYSTEM_ROUTE(old)) + rib_uninstall_kernel(rn, old); + UNSET_FLAG(new->status, ROUTE_ENTRY_SELECTED_FIB); + } + } else { + /* + * Same route selected; check if in the FIB and if not, + * re-install. This + * is housekeeping code to deal with race conditions in kernel + * with linux + * netlink reporting interface up before IPv4 or IPv6 protocol + * is ready + * to add routes. + */ + if (!RIB_SYSTEM_ROUTE(new)) { + int in_fib = 0; + + for (ALL_NEXTHOPS(new->nexthop, nexthop)) + if (CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB)) { + in_fib = 1; + break; + } + if (!in_fib) + rib_install_kernel(rn, new, NULL); + } + } + + /* Update prior route. */ + if (new != old) { + UNSET_FLAG(old->status, ROUTE_ENTRY_SELECTED_FIB); - UNSET_FLAG (old->status, ROUTE_ENTRY_SELECTED_FIB); + /* Set real nexthop. */ + nexthop_active_update(rn, old, 1); + UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED); + } - /* Update nexthop for route, reset changed flag. */ - nexthop_active_update (rn, old, 1); - UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED); + /* Clear changed flag. */ + UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED); } -static void -rib_process_update_fib (struct zebra_vrf *zvrf, struct route_node *rn, - struct route_entry *old, struct route_entry *new) -{ - struct nexthop *nexthop = NULL; - int nh_active = 0; - int installed = 1; +/* Check if 'alternate' RIB entry is better than 'current'. */ +static struct route_entry *rib_choose_best(struct route_entry *current, + struct route_entry *alternate) +{ + if (current == NULL) + return alternate; + + /* filter route selection in following order: + * - connected beats other types + * - lower distance beats higher + * - lower metric beats higher for equal distance + * - last, hence oldest, route wins tie break. + */ + + /* Connected routes. Pick the last connected + * route of the set of lowest metric connected routes. + */ + if (alternate->type == ZEBRA_ROUTE_CONNECT) { + if (current->type != ZEBRA_ROUTE_CONNECT + || alternate->metric <= current->metric) + return alternate; + + return current; + } - /* - * We have to install or update if a new route has been selected or - * something has changed. - */ - if (new != old || - CHECK_FLAG (new->status, ROUTE_ENTRY_CHANGED)) - { - hook_call(rib_update, rn, "updating existing route"); - - /* Update the nexthop; we could determine here that nexthop is inactive. */ - if (nexthop_active_update (rn, new, 1)) - nh_active = 1; - - /* If nexthop is active, install the selected route, if appropriate. If - * the install succeeds, cleanup flags for prior route, if different from - * newly selected. - */ - if (nh_active) - { - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[SRCDEST2STR_BUFFER]; - srcdest_rnode2str(rn, buf, sizeof(buf)); - if (new != old) - zlog_debug ("%u:%s: Updating route rn %p, re %p (type %d) " - "old %p (type %d)", zvrf_id (zvrf), buf, - rn, new, new->type, old, old->type); - else - zlog_debug ("%u:%s: Updating route rn %p, re %p (type %d)", - zvrf_id (zvrf), buf, rn, new, new->type); - } - - /* If labeled-unicast route, uninstall transit LSP. */ - if (zebra_rib_labeled_unicast (old)) - zebra_mpls_lsp_uninstall (zvrf, rn, old); - - /* Non-system route should be installed. */ - if (!RIB_SYSTEM_ROUTE (new)) - { - /* If labeled-unicast route, install transit LSP. */ - if (zebra_rib_labeled_unicast (new)) - zebra_mpls_lsp_install (zvrf, rn, new); - - if (rib_install_kernel (rn, new, old)) - { - char buf[SRCDEST2STR_BUFFER]; - srcdest_rnode2str(rn, buf, sizeof(buf)); - installed = 0; - zlog_warn ("%u:%s: Route install failed", zvrf_id (zvrf), buf); - } - } - - /* If install succeeded or system route, cleanup flags for prior route. */ - if (installed && new != old) - { - if (RIB_SYSTEM_ROUTE(new)) - { - if (!RIB_SYSTEM_ROUTE (old)) - rib_uninstall_kernel (rn, old); - } - else - { - for (nexthop = old->nexthop; nexthop; nexthop = nexthop->next) - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - } - - /* Update for redistribution. */ - if (installed) - SET_FLAG (new->status, ROUTE_ENTRY_SELECTED_FIB); - } - - /* - * If nexthop for selected route is not active or install failed, we - * may need to uninstall and delete for redistribution. - */ - if (!nh_active || !installed) - { - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[SRCDEST2STR_BUFFER]; - srcdest_rnode2str(rn, buf, sizeof(buf)); - if (new != old) - zlog_debug ("%u:%s: Deleting route rn %p, re %p (type %d) " - "old %p (type %d) - %s", zvrf_id (zvrf), buf, - rn, new, new->type, old, old->type, - nh_active ? "install failed" : "nexthop inactive"); - else - zlog_debug ("%u:%s: Deleting route rn %p, re %p (type %d) - %s", - zvrf_id (zvrf), buf, rn, new, new->type, - nh_active ? "install failed" : "nexthop inactive"); - } - - /* If labeled-unicast route, uninstall transit LSP. */ - if (zebra_rib_labeled_unicast (old)) - zebra_mpls_lsp_uninstall (zvrf, rn, old); - - if (!RIB_SYSTEM_ROUTE (old)) - rib_uninstall_kernel (rn, old); - UNSET_FLAG (new->status, ROUTE_ENTRY_SELECTED_FIB); - } - } - else - { - /* - * Same route selected; check if in the FIB and if not, re-install. This - * is housekeeping code to deal with race conditions in kernel with linux - * netlink reporting interface up before IPv4 or IPv6 protocol is ready - * to add routes. - */ - if (!RIB_SYSTEM_ROUTE (new)) - { - int in_fib = 0; - - for (ALL_NEXTHOPS(new->nexthop, nexthop)) - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - { - in_fib = 1; - break; - } - if (!in_fib) - rib_install_kernel (rn, new, NULL); - } - } + if (current->type == ZEBRA_ROUTE_CONNECT) + return current; - /* Update prior route. */ - if (new != old) - { - UNSET_FLAG (old->status, ROUTE_ENTRY_SELECTED_FIB); + /* higher distance loses */ + if (alternate->distance < current->distance) + return alternate; + if (current->distance < alternate->distance) + return current; - /* Set real nexthop. */ - nexthop_active_update (rn, old, 1); - UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED); - } + /* metric tie-breaks equal distance */ + if (alternate->metric <= current->metric) + return alternate; - /* Clear changed flag. */ - UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED); + return current; } -/* Check if 'alternate' RIB entry is better than 'current'. */ -static struct route_entry * -rib_choose_best (struct route_entry *current, struct route_entry *alternate) -{ - if (current == NULL) - return alternate; - - /* filter route selection in following order: - * - connected beats other types - * - lower distance beats higher - * - lower metric beats higher for equal distance - * - last, hence oldest, route wins tie break. - */ - - /* Connected routes. Pick the last connected - * route of the set of lowest metric connected routes. - */ - if (alternate->type == ZEBRA_ROUTE_CONNECT) - { - if (current->type != ZEBRA_ROUTE_CONNECT - || alternate->metric <= current->metric) - return alternate; +/* Core function for processing routing information base. */ +static void rib_process(struct route_node *rn) +{ + struct route_entry *re; + struct route_entry *next; + struct route_entry *old_selected = NULL; + struct route_entry *new_selected = NULL; + struct route_entry *old_fib = NULL; + struct route_entry *new_fib = NULL; + struct route_entry *best = NULL; + char buf[SRCDEST2STR_BUFFER]; + rib_dest_t *dest; + struct zebra_vrf *zvrf = NULL; + struct prefix *p, *src_p; + srcdest_rnode_prefixes(rn, &p, &src_p); + vrf_id_t vrf_id = VRF_UNKNOWN; + + assert(rn); + + dest = rib_dest_from_rnode(rn); + if (dest) { + zvrf = rib_dest_vrf(dest); + vrf_id = zvrf_id(zvrf); + } - return current; - } + if (IS_ZEBRA_DEBUG_RIB) + srcdest_rnode2str(rn, buf, sizeof(buf)); - if (current->type == ZEBRA_ROUTE_CONNECT) - return current; + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug("%u:%s: Processing rn %p", vrf_id, buf, rn); - /* higher distance loses */ - if (alternate->distance < current->distance) - return alternate; - if (current->distance < alternate->distance) - return current; + RNODE_FOREACH_RE_SAFE(rn, re, next) + { + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u:%s: Examine re %p (type %d) status %x flags %x " + "dist %d metric %d", + vrf_id, buf, re, re->type, re->status, + re->flags, re->distance, re->metric); + + UNSET_FLAG(re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); + + /* Currently selected re. */ + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) { + assert(old_selected == NULL); + old_selected = re; + } + /* Currently in fib */ + if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) { + assert(old_fib == NULL); + old_fib = re; + } - /* metric tie-breaks equal distance */ - if (alternate->metric <= current->metric) - return alternate; + /* Skip deleted entries from selection */ + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + + /* Skip unreachable nexthop. */ + /* This first call to nexthop_active_update is merely to + * determine if + * there's any change to nexthops associated with this RIB + * entry. Now, + * rib_process() can be invoked due to an external event such as + * link + * down or due to next-hop-tracking evaluation. In the latter + * case, + * a decision has already been made that the NHs have changed. + * So, no + * need to invoke a potentially expensive call again. Further, + * since + * the change might be in a recursive NH which is not caught in + * the nexthop_active_update() code. Thus, we might miss changes + * to + * recursive NHs. + */ + if (!CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED) + && !nexthop_active_update(rn, re, 0)) { + if (re->type == ZEBRA_ROUTE_TABLE) { + /* XXX: HERE BE DRAGONS!!!!! + * In all honesty, I have not yet figured out + * what this part + * does or why the ROUTE_ENTRY_CHANGED test + * above is correct + * or why we need to delete a route here, and + * also not whether + * this concerns both selected and fib route, or + * only selected + * or only fib */ + /* This entry was denied by the 'ip protocol + * table' route-map, we + * need to delete it */ + if (re != old_selected) { + if (IS_ZEBRA_DEBUG_RIB) + zlog_debug( + "%s: %s: imported via import-table but denied " + "by the ip protocol table route-map", + __func__, buf); + rib_unlink(rn, re); + } else + SET_FLAG(re->status, + ROUTE_ENTRY_REMOVED); + } + + continue; + } - return current; -} + /* Infinite distance. */ + if (re->distance == DISTANCE_INFINITY) { + UNSET_FLAG(re->status, ROUTE_ENTRY_CHANGED); + continue; + } -/* Core function for processing routing information base. */ -static void -rib_process (struct route_node *rn) -{ - struct route_entry *re; - struct route_entry *next; - struct route_entry *old_selected = NULL; - struct route_entry *new_selected = NULL; - struct route_entry *old_fib = NULL; - struct route_entry *new_fib = NULL; - struct route_entry *best = NULL; - char buf[SRCDEST2STR_BUFFER]; - rib_dest_t *dest; - struct zebra_vrf *zvrf = NULL; - struct prefix *p, *src_p; - srcdest_rnode_prefixes(rn, &p, &src_p); - vrf_id_t vrf_id = VRF_UNKNOWN; - - assert (rn); - - dest = rib_dest_from_rnode (rn); - if (dest) - { - zvrf = rib_dest_vrf (dest); - vrf_id = zvrf_id (zvrf); - } + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_FIB_OVERRIDE)) { + best = rib_choose_best(new_fib, re); + if (new_fib && best != new_fib) + UNSET_FLAG(new_fib->status, + ROUTE_ENTRY_CHANGED); + new_fib = best; + } else { + best = rib_choose_best(new_selected, re); + if (new_selected && best != new_selected) + UNSET_FLAG(new_selected->status, + ROUTE_ENTRY_CHANGED); + new_selected = best; + } + if (best != re) + UNSET_FLAG(re->status, ROUTE_ENTRY_CHANGED); + } /* RNODE_FOREACH_RE */ + + /* If no FIB override route, use the selected route also for FIB */ + if (new_fib == NULL) + new_fib = new_selected; + + /* After the cycle is finished, the following pointers will be set: + * old_selected --- RE entry currently having SELECTED + * new_selected --- RE entry that is newly SELECTED + * old_fib --- RE entry currently in kernel FIB + * new_fib --- RE entry that is newly to be in kernel FIB + * + * new_selected will get SELECTED flag, and is going to be redistributed + * the zclients. new_fib (which can be new_selected) will be installed + * in kernel. + */ + + if (IS_ZEBRA_DEBUG_RIB_DETAILED) { + zlog_debug( + "%u:%s: After processing: old_selected %p new_selected %p old_fib %p new_fib %p", + vrf_id, buf, (void *)old_selected, (void *)new_selected, + (void *)old_fib, (void *)new_fib); + } - if (IS_ZEBRA_DEBUG_RIB) - srcdest_rnode2str(rn, buf, sizeof(buf)); + /* Buffer ROUTE_ENTRY_CHANGED here, because it will get cleared if + * fib == selected */ + bool selected_changed = new_selected && CHECK_FLAG(new_selected->status, + ROUTE_ENTRY_CHANGED); + + /* Update fib according to selection results */ + if (new_fib && old_fib) + rib_process_update_fib(zvrf, rn, old_fib, new_fib); + else if (new_fib) + rib_process_add_fib(zvrf, rn, new_fib); + else if (old_fib) + rib_process_del_fib(zvrf, rn, old_fib); + + /* Redistribute SELECTED entry */ + if (old_selected != new_selected || selected_changed) { + struct nexthop *nexthop; + + /* Check if we have a FIB route for the destination, otherwise, + * don't redistribute it */ + for (ALL_NEXTHOPS(new_fib ? new_fib->nexthop : NULL, nexthop)) { + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) { + break; + } + } + if (!nexthop) + new_selected = NULL; - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u:%s: Processing rn %p", vrf_id, buf, rn); + if (new_selected && new_selected != new_fib) { + nexthop_active_update(rn, new_selected, 1); + UNSET_FLAG(new_selected->status, ROUTE_ENTRY_CHANGED); + } - RNODE_FOREACH_RE_SAFE (rn, re, next) - { - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u:%s: Examine re %p (type %d) status %x flags %x " - "dist %d metric %d", - vrf_id, buf, re, re->type, re->status, - re->flags, re->distance, re->metric); - - UNSET_FLAG(re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); - - /* Currently selected re. */ - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_SELECTED)) - { - assert (old_selected == NULL); - old_selected = re; - } - /* Currently in fib */ - if (CHECK_FLAG (re->status, ROUTE_ENTRY_SELECTED_FIB)) - { - assert (old_fib == NULL); - old_fib = re; - } - - /* Skip deleted entries from selection */ - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - - /* Skip unreachable nexthop. */ - /* This first call to nexthop_active_update is merely to determine if - * there's any change to nexthops associated with this RIB entry. Now, - * rib_process() can be invoked due to an external event such as link - * down or due to next-hop-tracking evaluation. In the latter case, - * a decision has already been made that the NHs have changed. So, no - * need to invoke a potentially expensive call again. Further, since - * the change might be in a recursive NH which is not caught in - * the nexthop_active_update() code. Thus, we might miss changes to - * recursive NHs. - */ - if (!CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED) && - ! nexthop_active_update (rn, re, 0)) - { - if (re->type == ZEBRA_ROUTE_TABLE) - { - /* XXX: HERE BE DRAGONS!!!!! - * In all honesty, I have not yet figured out what this part - * does or why the ROUTE_ENTRY_CHANGED test above is correct - * or why we need to delete a route here, and also not whether - * this concerns both selected and fib route, or only selected - * or only fib */ - /* This entry was denied by the 'ip protocol table' route-map, we - * need to delete it */ - if (re != old_selected) - { - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug ("%s: %s: imported via import-table but denied " - "by the ip protocol table route-map", - __func__, buf); - rib_unlink (rn, re); + if (old_selected) { + if (!new_selected) + redistribute_delete(p, src_p, old_selected); + if (old_selected != new_selected) + UNSET_FLAG(old_selected->flags, + ZEBRA_FLAG_SELECTED); } - else - SET_FLAG (re->status, ROUTE_ENTRY_REMOVED); - } - - continue; - } - - /* Infinite distance. */ - if (re->distance == DISTANCE_INFINITY) - { - UNSET_FLAG (re->status, ROUTE_ENTRY_CHANGED); - continue; - } - - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_FIB_OVERRIDE)) - { - best = rib_choose_best(new_fib, re); - if (new_fib && best != new_fib) - UNSET_FLAG (new_fib->status, ROUTE_ENTRY_CHANGED); - new_fib = best; - } - else - { - best = rib_choose_best(new_selected, re); - if (new_selected && best != new_selected) - UNSET_FLAG (new_selected->status, ROUTE_ENTRY_CHANGED); - new_selected = best; - } - if (best != re) - UNSET_FLAG (re->status, ROUTE_ENTRY_CHANGED); - } /* RNODE_FOREACH_RE */ - - /* If no FIB override route, use the selected route also for FIB */ - if (new_fib == NULL) - new_fib = new_selected; - - /* After the cycle is finished, the following pointers will be set: - * old_selected --- RE entry currently having SELECTED - * new_selected --- RE entry that is newly SELECTED - * old_fib --- RE entry currently in kernel FIB - * new_fib --- RE entry that is newly to be in kernel FIB - * - * new_selected will get SELECTED flag, and is going to be redistributed - * the zclients. new_fib (which can be new_selected) will be installed in kernel. - */ - - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - { - zlog_debug ("%u:%s: After processing: old_selected %p new_selected %p old_fib %p new_fib %p", - vrf_id, buf, - (void *)old_selected, - (void *)new_selected, - (void *)old_fib, - (void *)new_fib); - } - /* Buffer ROUTE_ENTRY_CHANGED here, because it will get cleared if - * fib == selected */ - bool selected_changed = new_selected && CHECK_FLAG(new_selected->status, - ROUTE_ENTRY_CHANGED); - - /* Update fib according to selection results */ - if (new_fib && old_fib) - rib_process_update_fib (zvrf, rn, old_fib, new_fib); - else if (new_fib) - rib_process_add_fib (zvrf, rn, new_fib); - else if (old_fib) - rib_process_del_fib (zvrf, rn, old_fib); - - /* Redistribute SELECTED entry */ - if (old_selected != new_selected || selected_changed) - { - struct nexthop *nexthop; - - /* Check if we have a FIB route for the destination, otherwise, - * don't redistribute it */ - for (ALL_NEXTHOPS(new_fib ? new_fib->nexthop : NULL, nexthop)) - { - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) - { - break; - } - } - if (!nexthop) - new_selected = NULL; - - if (new_selected && new_selected != new_fib) - { - nexthop_active_update(rn, new_selected, 1); - UNSET_FLAG(new_selected->status, ROUTE_ENTRY_CHANGED); - } - - if (old_selected) - { - if (!new_selected) - redistribute_delete(p, src_p, old_selected); - if (old_selected != new_selected) - UNSET_FLAG (old_selected->flags, ZEBRA_FLAG_SELECTED); - } - - if (new_selected) - { - /* Install new or replace existing redistributed entry */ - SET_FLAG (new_selected->flags, ZEBRA_FLAG_SELECTED); - redistribute_update (p, src_p, new_selected, old_selected); - } - } + if (new_selected) { + /* Install new or replace existing redistributed entry + */ + SET_FLAG(new_selected->flags, ZEBRA_FLAG_SELECTED); + redistribute_update(p, src_p, new_selected, + old_selected); + } + } - /* Remove all RE entries queued for removal */ - RNODE_FOREACH_RE_SAFE (rn, re, next) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - { - if (IS_ZEBRA_DEBUG_RIB) - { - rnode_debug (rn, vrf_id, "rn %p, removing re %p", - (void *)rn, (void *)re); - } - rib_unlink(rn, re); - } - } + /* Remove all RE entries queued for removal */ + RNODE_FOREACH_RE_SAFE(rn, re, next) + { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) { + if (IS_ZEBRA_DEBUG_RIB) { + rnode_debug(rn, vrf_id, "rn %p, removing re %p", + (void *)rn, (void *)re); + } + rib_unlink(rn, re); + } + } - /* - * Check if the dest can be deleted now. - */ - rib_gc_dest (rn); + /* + * Check if the dest can be deleted now. + */ + rib_gc_dest(rn); } /* Take a list of route_node structs and return 1, if there was a record - * picked from it and processed by rib_process(). Don't process more, + * picked from it and processed by rib_process(). Don't process more, * than one RN record; operate only in the specified sub-queue. */ -static unsigned int -process_subq (struct list * subq, u_char qindex) +static unsigned int process_subq(struct list *subq, u_char qindex) { - struct listnode *lnode = listhead (subq); - struct route_node *rnode; - rib_dest_t *dest; - struct zebra_vrf *zvrf = NULL; + struct listnode *lnode = listhead(subq); + struct route_node *rnode; + rib_dest_t *dest; + struct zebra_vrf *zvrf = NULL; - if (!lnode) - return 0; + if (!lnode) + return 0; - rnode = listgetdata (lnode); - dest = rib_dest_from_rnode (rnode); - if (dest) - zvrf = rib_dest_vrf (dest); + rnode = listgetdata(lnode); + dest = rib_dest_from_rnode(rnode); + if (dest) + zvrf = rib_dest_vrf(dest); - rib_process (rnode); + rib_process(rnode); - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - { - char buf[SRCDEST2STR_BUFFER]; - srcdest_rnode2str(rnode, buf, sizeof(buf)); - zlog_debug ("%u:%s: rn %p dequeued from sub-queue %u", - zvrf ? zvrf_id (zvrf) : 0, buf, rnode, qindex); - } + if (IS_ZEBRA_DEBUG_RIB_DETAILED) { + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rnode, buf, sizeof(buf)); + zlog_debug("%u:%s: rn %p dequeued from sub-queue %u", + zvrf ? zvrf_id(zvrf) : 0, buf, rnode, qindex); + } - if (rnode->info) - UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex)); + if (rnode->info) + UNSET_FLAG(rib_dest_from_rnode(rnode)->flags, + RIB_ROUTE_QUEUED(qindex)); #if 0 else @@ -1714,231 +1656,229 @@ process_subq (struct list * subq, u_char qindex) zlog_backtrace(LOG_DEBUG); } #endif - route_unlock_node (rnode); - list_delete_node (subq, lnode); - return 1; + route_unlock_node(rnode); + list_delete_node(subq, lnode); + return 1; } /* * All meta queues have been processed. Trigger next-hop evaluation. */ -static void -meta_queue_process_complete (struct work_queue *dummy) +static void meta_queue_process_complete(struct work_queue *dummy) { - struct vrf *vrf; - struct zebra_vrf *zvrf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - /* Evaluate nexthops for those VRFs which underwent route processing. This - * should limit the evaluation to the necessary VRFs in most common - * situations. - */ - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - { - zvrf = vrf->info; - if (zvrf == NULL || !(zvrf->flags & ZEBRA_VRF_RIB_SCHEDULED)) - continue; - - zvrf->flags &= ~ZEBRA_VRF_RIB_SCHEDULED; - zebra_evaluate_rnh(zvrf_id (zvrf), AF_INET, 0, RNH_NEXTHOP_TYPE, NULL); - zebra_evaluate_rnh(zvrf_id (zvrf), AF_INET, 0, RNH_IMPORT_CHECK_TYPE, NULL); - zebra_evaluate_rnh(zvrf_id (zvrf), AF_INET6, 0, RNH_NEXTHOP_TYPE, NULL); - zebra_evaluate_rnh(zvrf_id (zvrf), AF_INET6, 0, RNH_IMPORT_CHECK_TYPE, NULL); - } + /* Evaluate nexthops for those VRFs which underwent route processing. + * This + * should limit the evaluation to the necessary VRFs in most common + * situations. + */ + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + { + zvrf = vrf->info; + if (zvrf == NULL || !(zvrf->flags & ZEBRA_VRF_RIB_SCHEDULED)) + continue; + + zvrf->flags &= ~ZEBRA_VRF_RIB_SCHEDULED; + zebra_evaluate_rnh(zvrf_id(zvrf), AF_INET, 0, RNH_NEXTHOP_TYPE, + NULL); + zebra_evaluate_rnh(zvrf_id(zvrf), AF_INET, 0, + RNH_IMPORT_CHECK_TYPE, NULL); + zebra_evaluate_rnh(zvrf_id(zvrf), AF_INET6, 0, RNH_NEXTHOP_TYPE, + NULL); + zebra_evaluate_rnh(zvrf_id(zvrf), AF_INET6, 0, + RNH_IMPORT_CHECK_TYPE, NULL); + } - /* Schedule LSPs for processing, if needed. */ - zvrf = vrf_info_lookup(VRF_DEFAULT); - if (mpls_should_lsps_be_processed(zvrf)) - { - if (IS_ZEBRA_DEBUG_MPLS) - zlog_debug ("%u: Scheduling all LSPs upon RIB completion", zvrf_id (zvrf)); - zebra_mpls_lsp_schedule (zvrf); - mpls_unmark_lsps_for_processing(zvrf); - } + /* Schedule LSPs for processing, if needed. */ + zvrf = vrf_info_lookup(VRF_DEFAULT); + if (mpls_should_lsps_be_processed(zvrf)) { + if (IS_ZEBRA_DEBUG_MPLS) + zlog_debug( + "%u: Scheduling all LSPs upon RIB completion", + zvrf_id(zvrf)); + zebra_mpls_lsp_schedule(zvrf); + mpls_unmark_lsps_for_processing(zvrf); + } } /* Dispatch the meta queue by picking, processing and unlocking the next RN from - * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data + * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and + * data * is pointed to the meta queue structure. */ -static wq_item_status -meta_queue_process (struct work_queue *dummy, void *data) +static wq_item_status meta_queue_process(struct work_queue *dummy, void *data) { - struct meta_queue * mq = data; - unsigned i; + struct meta_queue *mq = data; + unsigned i; - for (i = 0; i < MQ_SIZE; i++) - if (process_subq (mq->subq[i], i)) - { - mq->size--; - break; - } - return mq->size ? WQ_REQUEUE : WQ_SUCCESS; + for (i = 0; i < MQ_SIZE; i++) + if (process_subq(mq->subq[i], i)) { + mq->size--; + break; + } + return mq->size ? WQ_REQUEUE : WQ_SUCCESS; } /* * Map from rib types to queue type (priority) in meta queue */ static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = { - [ZEBRA_ROUTE_SYSTEM] = 4, - [ZEBRA_ROUTE_KERNEL] = 0, - [ZEBRA_ROUTE_CONNECT] = 0, - [ZEBRA_ROUTE_STATIC] = 1, - [ZEBRA_ROUTE_RIP] = 2, - [ZEBRA_ROUTE_RIPNG] = 2, - [ZEBRA_ROUTE_OSPF] = 2, - [ZEBRA_ROUTE_OSPF6] = 2, - [ZEBRA_ROUTE_ISIS] = 2, - [ZEBRA_ROUTE_BGP] = 3, - [ZEBRA_ROUTE_PIM] = 4, // Shouldn't happen but for safety - [ZEBRA_ROUTE_EIGRP] = 2, - [ZEBRA_ROUTE_NHRP] = 2, - [ZEBRA_ROUTE_HSLS] = 4, - [ZEBRA_ROUTE_OLSR] = 4, - [ZEBRA_ROUTE_TABLE] = 1, - [ZEBRA_ROUTE_LDP] = 4, - [ZEBRA_ROUTE_VNC] = 3, - [ZEBRA_ROUTE_VNC_DIRECT] = 3, - [ZEBRA_ROUTE_VNC_DIRECT_RH] = 3, - [ZEBRA_ROUTE_BGP_DIRECT] = 3, - [ZEBRA_ROUTE_BGP_DIRECT_EXT] = 3, - [ZEBRA_ROUTE_BABEL] = 2, - [ZEBRA_ROUTE_ALL] = 4, // Shouldn't happen but for safety + [ZEBRA_ROUTE_SYSTEM] = 4, + [ZEBRA_ROUTE_KERNEL] = 0, + [ZEBRA_ROUTE_CONNECT] = 0, + [ZEBRA_ROUTE_STATIC] = 1, + [ZEBRA_ROUTE_RIP] = 2, + [ZEBRA_ROUTE_RIPNG] = 2, + [ZEBRA_ROUTE_OSPF] = 2, + [ZEBRA_ROUTE_OSPF6] = 2, + [ZEBRA_ROUTE_ISIS] = 2, + [ZEBRA_ROUTE_BGP] = 3, + [ZEBRA_ROUTE_PIM] = 4, // Shouldn't happen but for safety + [ZEBRA_ROUTE_EIGRP] = 2, + [ZEBRA_ROUTE_NHRP] = 2, + [ZEBRA_ROUTE_HSLS] = 4, + [ZEBRA_ROUTE_OLSR] = 4, + [ZEBRA_ROUTE_TABLE] = 1, + [ZEBRA_ROUTE_LDP] = 4, + [ZEBRA_ROUTE_VNC] = 3, + [ZEBRA_ROUTE_VNC_DIRECT] = 3, + [ZEBRA_ROUTE_VNC_DIRECT_RH] = 3, + [ZEBRA_ROUTE_BGP_DIRECT] = 3, + [ZEBRA_ROUTE_BGP_DIRECT_EXT] = 3, + [ZEBRA_ROUTE_BABEL] = 2, + [ZEBRA_ROUTE_ALL] = 4, // Shouldn't happen but for safety }; /* Look into the RN and queue it into one or more priority queues, * increasing the size for each data push done. */ -static void -rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn) +static void rib_meta_queue_add(struct meta_queue *mq, struct route_node *rn) { - struct route_entry *re; + struct route_entry *re; - RNODE_FOREACH_RE (rn, re) - { - u_char qindex = meta_queue_map[re->type]; - struct zebra_vrf *zvrf; - - /* Invariant: at this point we always have rn->info set. */ - if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags, - RIB_ROUTE_QUEUED (qindex))) + RNODE_FOREACH_RE(rn, re) { - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - rnode_debug (rn, re->vrf_id, "rn %p is already queued in sub-queue %u", - (void *)rn, qindex); - continue; - } + u_char qindex = meta_queue_map[re->type]; + struct zebra_vrf *zvrf; + + /* Invariant: at this point we always have rn->info set. */ + if (CHECK_FLAG(rib_dest_from_rnode(rn)->flags, + RIB_ROUTE_QUEUED(qindex))) { + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + rnode_debug( + rn, re->vrf_id, + "rn %p is already queued in sub-queue %u", + (void *)rn, qindex); + continue; + } - SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex)); - listnode_add (mq->subq[qindex], rn); - route_lock_node (rn); - mq->size++; + SET_FLAG(rib_dest_from_rnode(rn)->flags, + RIB_ROUTE_QUEUED(qindex)); + listnode_add(mq->subq[qindex], rn); + route_lock_node(rn); + mq->size++; - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - rnode_debug (rn, re->vrf_id, "queued rn %p into sub-queue %u", - (void *)rn, qindex); + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + rnode_debug(rn, re->vrf_id, + "queued rn %p into sub-queue %u", + (void *)rn, qindex); - zvrf = zebra_vrf_lookup_by_id (re->vrf_id); - if (zvrf) - zvrf->flags |= ZEBRA_VRF_RIB_SCHEDULED; - } + zvrf = zebra_vrf_lookup_by_id(re->vrf_id); + if (zvrf) + zvrf->flags |= ZEBRA_VRF_RIB_SCHEDULED; + } } /* Add route_node to work queue and schedule processing */ -void -rib_queue_add (struct route_node *rn) +void rib_queue_add(struct route_node *rn) { - assert (rn); - - /* Pointless to queue a route_node with no RIB entries to add or remove */ - if (!rnode_to_ribs (rn)) - { - zlog_debug ("%s: called for route_node (%p, %d) with no ribs", - __func__, (void *)rn, rn->lock); - zlog_backtrace(LOG_DEBUG); - return; - } + assert(rn); - if (zebrad.ribq == NULL) - { - zlog_err ("%s: work_queue does not exist!", __func__); - return; - } + /* Pointless to queue a route_node with no RIB entries to add or remove + */ + if (!rnode_to_ribs(rn)) { + zlog_debug("%s: called for route_node (%p, %d) with no ribs", + __func__, (void *)rn, rn->lock); + zlog_backtrace(LOG_DEBUG); + return; + } - /* - * The RIB queue should normally be either empty or holding the only - * work_queue_item element. In the latter case this element would - * hold a pointer to the meta queue structure, which must be used to - * actually queue the route nodes to process. So create the MQ - * holder, if necessary, then push the work into it in any case. - * This semantics was introduced after 0.99.9 release. - */ - if (!zebrad.ribq->items->count) - work_queue_add (zebrad.ribq, zebrad.mq); + if (zebrad.ribq == NULL) { + zlog_err("%s: work_queue does not exist!", __func__); + return; + } + + /* + * The RIB queue should normally be either empty or holding the only + * work_queue_item element. In the latter case this element would + * hold a pointer to the meta queue structure, which must be used to + * actually queue the route nodes to process. So create the MQ + * holder, if necessary, then push the work into it in any case. + * This semantics was introduced after 0.99.9 release. + */ + if (!zebrad.ribq->items->count) + work_queue_add(zebrad.ribq, zebrad.mq); - rib_meta_queue_add (zebrad.mq, rn); + rib_meta_queue_add(zebrad.mq, rn); - return; + return; } /* Create new meta queue. A destructor function doesn't seem to be necessary here. */ -static struct meta_queue * -meta_queue_new (void) +static struct meta_queue *meta_queue_new(void) { - struct meta_queue *new; - unsigned i; + struct meta_queue *new; + unsigned i; - new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue)); - assert(new); + new = XCALLOC(MTYPE_WORK_QUEUE, sizeof(struct meta_queue)); + assert(new); - for (i = 0; i < MQ_SIZE; i++) - { - new->subq[i] = list_new (); - assert(new->subq[i]); - } + for (i = 0; i < MQ_SIZE; i++) { + new->subq[i] = list_new(); + assert(new->subq[i]); + } - return new; + return new; } -void -meta_queue_free (struct meta_queue *mq) +void meta_queue_free(struct meta_queue *mq) { - unsigned i; + unsigned i; - for (i = 0; i < MQ_SIZE; i++) - list_delete (mq->subq[i]); + for (i = 0; i < MQ_SIZE; i++) + list_delete(mq->subq[i]); - XFREE (MTYPE_WORK_QUEUE, mq); + XFREE(MTYPE_WORK_QUEUE, mq); } /* initialise zebra rib work queue */ -static void -rib_queue_init (struct zebra_t *zebra) +static void rib_queue_init(struct zebra_t *zebra) { - assert (zebra); - - if (! (zebra->ribq = work_queue_new (zebra->master, - "route_node processing"))) - { - zlog_err ("%s: could not initialise work queue!", __func__); - return; - } + assert(zebra); + + if (!(zebra->ribq = + work_queue_new(zebra->master, "route_node processing"))) { + zlog_err("%s: could not initialise work queue!", __func__); + return; + } - /* fill in the work queue spec */ - zebra->ribq->spec.workfunc = &meta_queue_process; - zebra->ribq->spec.errorfunc = NULL; - zebra->ribq->spec.completion_func = &meta_queue_process_complete; - /* XXX: TODO: These should be runtime configurable via vty */ - zebra->ribq->spec.max_retries = 3; - zebra->ribq->spec.hold = rib_process_hold_time; - - if (!(zebra->mq = meta_queue_new ())) - { - zlog_err ("%s: could not initialise meta queue!", __func__); - return; - } - return; + /* fill in the work queue spec */ + zebra->ribq->spec.workfunc = &meta_queue_process; + zebra->ribq->spec.errorfunc = NULL; + zebra->ribq->spec.completion_func = &meta_queue_process_complete; + /* XXX: TODO: These should be runtime configurable via vty */ + zebra->ribq->spec.max_retries = 3; + zebra->ribq->spec.hold = rib_process_hold_time; + + if (!(zebra->mq = meta_queue_new())) { + zlog_err("%s: could not initialise meta queue!", __func__); + return; + } + return; } /* RIB updates are processed via a queue of pointers to route_nodes. @@ -1967,7 +1907,7 @@ rib_queue_init (struct zebra_t *zebra) * ('dest'). Queueing state for a route_node is kept on the dest. The * dest is created on-demand by rib_link() and is kept around at least * as long as there are ribs hanging off it (@see rib_gc_dest()). - * + * * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code): * * - route_nodes: refcounted by: @@ -1977,65 +1917,59 @@ rib_queue_init (struct zebra_t *zebra) * - managed by: rib_addqueue, rib_process. * */ - + /* Add RE to head of the route node. */ -static void -rib_link (struct route_node *rn, struct route_entry *re, int process) -{ - struct route_entry *head; - rib_dest_t *dest; - afi_t afi; - const char *rmap_name; - - assert (re && rn); - - dest = rib_dest_from_rnode (rn); - if (!dest) - { - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - rnode_debug (rn, re->vrf_id, "rn %p adding dest", rn); +static void rib_link(struct route_node *rn, struct route_entry *re, int process) +{ + struct route_entry *head; + rib_dest_t *dest; + afi_t afi; + const char *rmap_name; - dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t)); - route_lock_node (rn); /* rn route table reference */ - rn->info = dest; - dest->rnode = rn; - } + assert(re && rn); - head = dest->routes; - if (head) - { - head->prev = re; - } - re->next = head; - dest->routes = re; + dest = rib_dest_from_rnode(rn); + if (!dest) { + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + rnode_debug(rn, re->vrf_id, "rn %p adding dest", rn); - afi = (rn->p.family == AF_INET) ? AFI_IP : - (rn->p.family == AF_INET6) ? AFI_IP6 : AFI_MAX; - if (is_zebra_import_table_enabled (afi, re->table)) - { - rmap_name = zebra_get_import_table_route_map (afi, re->table); - zebra_add_import_table_entry(rn, re, rmap_name); - } - else - if (process) - rib_queue_add (rn); -} - -void -rib_addnode (struct route_node *rn, struct route_entry *re, int process) -{ - /* RE node has been un-removed before route-node is processed. - * route_node must hence already be on the queue for processing.. - */ - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - { - if (IS_ZEBRA_DEBUG_RIB) - rnode_debug (rn, re->vrf_id, "rn %p, un-removed re %p", (void *)rn, (void *)re); + dest = XCALLOC(MTYPE_RIB_DEST, sizeof(rib_dest_t)); + route_lock_node(rn); /* rn route table reference */ + rn->info = dest; + dest->rnode = rn; + } - UNSET_FLAG (re->status, ROUTE_ENTRY_REMOVED); - return; - } - rib_link (rn, re, process); + head = dest->routes; + if (head) { + head->prev = re; + } + re->next = head; + dest->routes = re; + + afi = (rn->p.family == AF_INET) + ? AFI_IP + : (rn->p.family == AF_INET6) ? AFI_IP6 : AFI_MAX; + if (is_zebra_import_table_enabled(afi, re->table)) { + rmap_name = zebra_get_import_table_route_map(afi, re->table); + zebra_add_import_table_entry(rn, re, rmap_name); + } else if (process) + rib_queue_add(rn); +} + +void rib_addnode(struct route_node *rn, struct route_entry *re, int process) +{ + /* RE node has been un-removed before route-node is processed. + * route_node must hence already be on the queue for processing.. + */ + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) { + if (IS_ZEBRA_DEBUG_RIB) + rnode_debug(rn, re->vrf_id, "rn %p, un-removed re %p", + (void *)rn, (void *)re); + + UNSET_FLAG(re->status, ROUTE_ENTRY_REMOVED); + return; + } + rib_link(rn, re, process); } /* @@ -2047,64 +1981,60 @@ rib_addnode (struct route_node *rn, struct route_entry *re, int process) * rib_gc_dest() at some point. This allows a rib_dest_t that is no * longer required to be deleted. */ -void -rib_unlink (struct route_node *rn, struct route_entry *re) +void rib_unlink(struct route_node *rn, struct route_entry *re) { - rib_dest_t *dest; - - assert (rn && re); - - if (IS_ZEBRA_DEBUG_RIB) - rnode_debug (rn, re->vrf_id, "rn %p, re %p", (void *)rn, (void *)re); - - dest = rib_dest_from_rnode (rn); + rib_dest_t *dest; - if (re->next) - re->next->prev = re->prev; + assert(rn && re); - if (re->prev) - re->prev->next = re->next; - else - { - dest->routes = re->next; - } + if (IS_ZEBRA_DEBUG_RIB) + rnode_debug(rn, re->vrf_id, "rn %p, re %p", (void *)rn, + (void *)re); - /* free RE and nexthops */ - zebra_deregister_rnh_static_nexthops (re->vrf_id, re->nexthop, rn); - nexthops_free(re->nexthop); - XFREE (MTYPE_RE, re); + dest = rib_dest_from_rnode(rn); -} + if (re->next) + re->next->prev = re->prev; -void -rib_delnode (struct route_node *rn, struct route_entry *re) -{ - afi_t afi; + if (re->prev) + re->prev->next = re->next; + else { + dest->routes = re->next; + } - if (IS_ZEBRA_DEBUG_RIB) - rnode_debug (rn, re->vrf_id, "rn %p, re %p, removing", (void *)rn, (void *)re); - SET_FLAG (re->status, ROUTE_ENTRY_REMOVED); + /* free RE and nexthops */ + zebra_deregister_rnh_static_nexthops(re->vrf_id, re->nexthop, rn); + nexthops_free(re->nexthop); + XFREE(MTYPE_RE, re); +} + +void rib_delnode(struct route_node *rn, struct route_entry *re) +{ + afi_t afi; + + if (IS_ZEBRA_DEBUG_RIB) + rnode_debug(rn, re->vrf_id, "rn %p, re %p, removing", + (void *)rn, (void *)re); + SET_FLAG(re->status, ROUTE_ENTRY_REMOVED); + + afi = (rn->p.family == AF_INET) + ? AFI_IP + : (rn->p.family == AF_INET6) ? AFI_IP6 : AFI_MAX; + if (is_zebra_import_table_enabled(afi, re->table)) { + zebra_del_import_table_entry(rn, re); + /* Just clean up if non main table */ + if (IS_ZEBRA_DEBUG_RIB) { + char buf[SRCDEST2STR_BUFFER]; + srcdest_rnode2str(rn, buf, sizeof(buf)); + zlog_debug( + "%u:%s: Freeing route rn %p, re %p (type %d)", + re->vrf_id, buf, rn, re, re->type); + } - afi = (rn->p.family == AF_INET) ? AFI_IP : - (rn->p.family == AF_INET6) ? AFI_IP6 : AFI_MAX; - if (is_zebra_import_table_enabled (afi, re->table)) - { - zebra_del_import_table_entry(rn, re); - /* Just clean up if non main table */ - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[SRCDEST2STR_BUFFER]; - srcdest_rnode2str(rn, buf, sizeof(buf)); - zlog_debug ("%u:%s: Freeing route rn %p, re %p (type %d)", - re->vrf_id, buf, rn, re, re->type); - } - - rib_unlink(rn, re); - } - else - { - rib_queue_add (rn); - } + rib_unlink(rn, re); + } else { + rib_queue_add(rn); + } } /* This function dumps the contents of a given RE entry into @@ -2112,115 +2042,95 @@ rib_delnode (struct route_node *rn, struct route_entry *re) * question are passed as 1st and 2nd arguments. */ -void _route_entry_dump (const char * func, - union prefixconstptr pp, - union prefixconstptr src_pp, - const struct route_entry * re) -{ - const struct prefix *p = pp.p; - const struct prefix *src_p = src_pp.p; - bool is_srcdst = src_p && src_p->prefixlen; - char straddr[PREFIX_STRLEN]; - char srcaddr[PREFIX_STRLEN]; - struct nexthop *nexthop; - - zlog_debug ("%s: dumping RE entry %p for %s%s%s vrf %u", func, (const void *)re, - prefix2str(pp, straddr, sizeof(straddr)), - is_srcdst ? " from " : "", - is_srcdst ? prefix2str(src_pp, srcaddr, sizeof(srcaddr)) : "", - re->vrf_id); - zlog_debug - ( - "%s: refcnt == %lu, uptime == %lu, type == %u, instance == %d, table == %d", - func, - re->refcnt, - (unsigned long) re->uptime, - re->type, - re->instance, - re->table - ); - zlog_debug - ( - "%s: metric == %u, mtu == %u, distance == %u, flags == %u, status == %u", - func, - re->metric, - re->mtu, - re->distance, - re->flags, - re->status - ); - zlog_debug - ( - "%s: nexthop_num == %u, nexthop_active_num == %u", - func, - re->nexthop_num, - re->nexthop_active_num - ); - - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - inet_ntop (p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN); - zlog_debug - ( - "%s: %s %s with flags %s%s%s", - func, - (nexthop->rparent ? " NH" : "NH"), - straddr, - (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""), - (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""), - (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "") - ); - } - zlog_debug ("%s: dump complete", func); +void _route_entry_dump(const char *func, union prefixconstptr pp, + union prefixconstptr src_pp, + const struct route_entry *re) +{ + const struct prefix *p = pp.p; + const struct prefix *src_p = src_pp.p; + bool is_srcdst = src_p && src_p->prefixlen; + char straddr[PREFIX_STRLEN]; + char srcaddr[PREFIX_STRLEN]; + struct nexthop *nexthop; + + zlog_debug("%s: dumping RE entry %p for %s%s%s vrf %u", func, + (const void *)re, prefix2str(pp, straddr, sizeof(straddr)), + is_srcdst ? " from " : "", + is_srcdst ? prefix2str(src_pp, srcaddr, sizeof(srcaddr)) + : "", + re->vrf_id); + zlog_debug( + "%s: refcnt == %lu, uptime == %lu, type == %u, instance == %d, table == %d", + func, re->refcnt, (unsigned long)re->uptime, re->type, + re->instance, re->table); + zlog_debug( + "%s: metric == %u, mtu == %u, distance == %u, flags == %u, status == %u", + func, re->metric, re->mtu, re->distance, re->flags, re->status); + zlog_debug("%s: nexthop_num == %u, nexthop_active_num == %u", func, + re->nexthop_num, re->nexthop_active_num); + + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + inet_ntop(p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN); + zlog_debug("%s: %s %s with flags %s%s%s", func, + (nexthop->rparent ? " NH" : "NH"), straddr, + (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE) + ? "ACTIVE " + : ""), + (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB) + ? "FIB " + : ""), + (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE) + ? "RECURSIVE" + : "")); + } + zlog_debug("%s: dump complete", func); } /* This is an exported helper to rtm_read() to dump the strange * RE entry found by rib_lookup_ipv4_route() */ -void rib_lookup_and_dump (struct prefix_ipv4 * p, vrf_id_t vrf_id) -{ - struct route_table *table; - struct route_node *rn; - struct route_entry *re; - char prefix_buf[INET_ADDRSTRLEN]; - - /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (! table) - { - zlog_err ("%s: zebra_vrf_table() returned NULL", __func__); - return; - } - - /* Scan the RIB table for exactly matching RE entry. */ - rn = route_node_lookup (table, (struct prefix *) p); - - /* No route for this prefix. */ - if (! rn) - { - zlog_debug ("%s: lookup failed for %s", __func__, - prefix2str((struct prefix*) p, prefix_buf, sizeof(prefix_buf))); - return; - } - - /* Unlock node. */ - route_unlock_node (rn); - - /* let's go */ - RNODE_FOREACH_RE (rn, re) - { - zlog_debug - ( - "%s: rn %p, re %p: %s, %s", - __func__, - (void *)rn, - (void *)re, - (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED) ? "removed" : "NOT removed"), - (CHECK_FLAG (re->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected") - ); - route_entry_dump (p, NULL, re); - } +void rib_lookup_and_dump(struct prefix_ipv4 *p, vrf_id_t vrf_id) +{ + struct route_table *table; + struct route_node *rn; + struct route_entry *re; + char prefix_buf[INET_ADDRSTRLEN]; + + /* Lookup table. */ + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); + if (!table) { + zlog_err("%s: zebra_vrf_table() returned NULL", __func__); + return; + } + + /* Scan the RIB table for exactly matching RE entry. */ + rn = route_node_lookup(table, (struct prefix *)p); + + /* No route for this prefix. */ + if (!rn) { + zlog_debug("%s: lookup failed for %s", __func__, + prefix2str((struct prefix *)p, prefix_buf, + sizeof(prefix_buf))); + return; + } + + /* Unlock node. */ + route_unlock_node(rn); + + /* let's go */ + RNODE_FOREACH_RE(rn, re) + { + zlog_debug("%s: rn %p, re %p: %s, %s", __func__, (void *)rn, + (void *)re, + (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED) + ? "removed" + : "NOT removed"), + (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED) + ? "selected" + : "NOT selected")); + route_entry_dump(p, NULL, re); + } } /* Check if requested address assignment will fail due to another @@ -2228,637 +2138,628 @@ void rib_lookup_and_dump (struct prefix_ipv4 * p, vrf_id_t vrf_id) * actions, if needed: remove such a route from FIB and deSELECT * corresponding RE entry. Then put affected RN into RIBQ head. */ -void rib_lookup_and_pushup (struct prefix_ipv4 * p, vrf_id_t vrf_id) -{ - struct route_table *table; - struct route_node *rn; - struct route_entry *re; - unsigned changed = 0; - - if (NULL == (table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id))) - { - zlog_err ("%s: zebra_vrf_table() returned NULL", __func__); - return; - } - - /* No matches would be the simplest case. */ - if (NULL == (rn = route_node_lookup (table, (struct prefix *) p))) - return; - - /* Unlock node. */ - route_unlock_node (rn); - - /* Check all RE entries. In case any changes have to be done, requeue - * the RN into RIBQ head. If the routing message about the new connected - * route (generated by the IP address we are going to assign very soon) - * comes before the RIBQ is processed, the new RE entry will join - * RIBQ record already on head. This is necessary for proper revalidation - * of the rest of the RE. - */ - RNODE_FOREACH_RE (rn, re) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_SELECTED_FIB) && - ! RIB_SYSTEM_ROUTE (re)) - { - changed = 1; - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[PREFIX_STRLEN]; - zlog_debug ("%u:%s: freeing way for connected prefix", - re->vrf_id, prefix2str(&rn->p, buf, sizeof(buf))); - route_entry_dump (&rn->p, NULL, re); - } - rib_uninstall (rn, re); - } - } - if (changed) - rib_queue_add (rn); +void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id) +{ + struct route_table *table; + struct route_node *rn; + struct route_entry *re; + unsigned changed = 0; + + if (NULL == (table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id))) { + zlog_err("%s: zebra_vrf_table() returned NULL", __func__); + return; + } + + /* No matches would be the simplest case. */ + if (NULL == (rn = route_node_lookup(table, (struct prefix *)p))) + return; + + /* Unlock node. */ + route_unlock_node(rn); + + /* Check all RE entries. In case any changes have to be done, requeue + * the RN into RIBQ head. If the routing message about the new connected + * route (generated by the IP address we are going to assign very soon) + * comes before the RIBQ is processed, the new RE entry will join + * RIBQ record already on head. This is necessary for proper + * revalidation + * of the rest of the RE. + */ + RNODE_FOREACH_RE(rn, re) + { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB) + && !RIB_SYSTEM_ROUTE(re)) { + changed = 1; + if (IS_ZEBRA_DEBUG_RIB) { + char buf[PREFIX_STRLEN]; + zlog_debug( + "%u:%s: freeing way for connected prefix", + re->vrf_id, + prefix2str(&rn->p, buf, sizeof(buf))); + route_entry_dump(&rn->p, NULL, re); + } + rib_uninstall(rn, re); + } + } + if (changed) + rib_queue_add(rn); } -int -rib_add_multipath (afi_t afi, safi_t safi, struct prefix *p, - struct prefix_ipv6 *src_p, struct route_entry *re) +int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, + struct prefix_ipv6 *src_p, struct route_entry *re) { - struct route_table *table; - struct route_node *rn; - struct route_entry *same; - struct nexthop *nexthop; - int ret = 0; - int family; + struct route_table *table; + struct route_node *rn; + struct route_entry *same; + struct nexthop *nexthop; + int ret = 0; + int family; - if (!re) - return 0; + if (!re) + return 0; - if (p->family == AF_INET) - family = AFI_IP; - else - family = AFI_IP6; + if (p->family == AF_INET) + family = AFI_IP; + else + family = AFI_IP6; - assert(!src_p || family == AFI_IP6); + assert(!src_p || family == AFI_IP6); - /* Lookup table. */ - table = zebra_vrf_table_with_table_id (family, safi, re->vrf_id, re->table); - if (! table) - return 0; + /* Lookup table. */ + table = zebra_vrf_table_with_table_id(family, safi, re->vrf_id, + re->table); + if (!table) + return 0; - /* Make it sure prefixlen is applied to the prefix. */ - apply_mask (p); - if (src_p) - apply_mask_ipv6 (src_p); + /* Make it sure prefixlen is applied to the prefix. */ + apply_mask(p); + if (src_p) + apply_mask_ipv6(src_p); - /* Set default distance by route type. */ - if (re->distance == 0) - { - re->distance = route_info[re->type].distance; + /* Set default distance by route type. */ + if (re->distance == 0) { + re->distance = route_info[re->type].distance; - /* iBGP distance is 200. */ - if (re->type == ZEBRA_ROUTE_BGP - && CHECK_FLAG (re->flags, ZEBRA_FLAG_IBGP)) - re->distance = 200; - } + /* iBGP distance is 200. */ + if (re->type == ZEBRA_ROUTE_BGP + && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)) + re->distance = 200; + } - /* Lookup route node.*/ - rn = srcdest_rnode_get (table, p, src_p); + /* Lookup route node.*/ + rn = srcdest_rnode_get(table, p, src_p); - /* If same type of route are installed, treat it as a implicit - withdraw. */ - RNODE_FOREACH_RE (rn, same) - { - if (CHECK_FLAG (same->status, ROUTE_ENTRY_REMOVED)) - continue; - - if (same->type == re->type && same->instance == re->instance - && same->table == re->table - && same->type != ZEBRA_ROUTE_CONNECT) - break; - } - - /* If this route is kernel route, set FIB flag to the route. */ - if (re->type == ZEBRA_ROUTE_KERNEL || re->type == ZEBRA_ROUTE_CONNECT) - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - - /* Link new re to node.*/ - if (IS_ZEBRA_DEBUG_RIB) - { - rnode_debug(rn, re->vrf_id, "Inserting route rn %p, re %p (type %d) existing %p", - (void *)rn, (void *)re, re->type, (void *)same); + /* If same type of route are installed, treat it as a implicit + withdraw. */ + RNODE_FOREACH_RE(rn, same) + { + if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED)) + continue; - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - route_entry_dump (p, src_p, re); - } - rib_addnode (rn, re, 1); - ret = 1; + if (same->type == re->type && same->instance == re->instance + && same->table == re->table + && same->type != ZEBRA_ROUTE_CONNECT) + break; + } - /* Free implicit route.*/ - if (same) - { - rib_delnode (rn, same); - ret = -1; - } - - route_unlock_node (rn); - return ret; -} + /* If this route is kernel route, set FIB flag to the route. */ + if (re->type == ZEBRA_ROUTE_KERNEL || re->type == ZEBRA_ROUTE_CONNECT) + for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); -void -rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, - int flags, struct prefix *p, struct prefix_ipv6 *src_p, - union g_addr *gate, ifindex_t ifindex, u_int32_t table_id) -{ - struct route_table *table; - struct route_node *rn; - struct route_entry *re; - struct route_entry *fib = NULL; - struct route_entry *same = NULL; - struct nexthop *nexthop; - char buf2[INET6_ADDRSTRLEN]; - - assert(!src_p || afi == AFI_IP6); - - /* Lookup table. */ - table = zebra_vrf_table_with_table_id (afi, safi, vrf_id, table_id); - if (! table) - return; - - /* Apply mask. */ - apply_mask (p); - if (src_p) - apply_mask_ipv6 (src_p); - - /* Lookup route node. */ - rn = srcdest_rnode_lookup (table, p, src_p); - if (! rn) - { - char dst_buf[PREFIX_STRLEN], src_buf[PREFIX_STRLEN]; - - prefix2str(p, dst_buf, sizeof(dst_buf)); - if (src_p && src_p->prefixlen) - prefix2str(src_p, src_buf, sizeof(src_buf)); - else - src_buf[0] = '\0'; - - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug ("%u:%s%s%s doesn't exist in rib", - vrf_id, dst_buf, - (src_buf[0] != '\0') ? " from " : "", - src_buf); - return; - } + /* Link new re to node.*/ + if (IS_ZEBRA_DEBUG_RIB) { + rnode_debug( + rn, re->vrf_id, + "Inserting route rn %p, re %p (type %d) existing %p", + (void *)rn, (void *)re, re->type, (void *)same); - /* Lookup same type route. */ - RNODE_FOREACH_RE (rn, re) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - - if (CHECK_FLAG (re->status, ROUTE_ENTRY_SELECTED_FIB)) - fib = re; - - if (re->type != type) - continue; - if (re->instance != instance) - continue; - if (re->type == ZEBRA_ROUTE_CONNECT && (nexthop = re->nexthop) && - nexthop->type == NEXTHOP_TYPE_IFINDEX) - { - if (nexthop->ifindex != ifindex) - continue; - if (re->refcnt) - { - re->refcnt--; - route_unlock_node (rn); - route_unlock_node (rn); - return; - } - same = re; - break; - } - /* Make sure that the route found has the same gateway. */ - else - { - if (gate == NULL) - { - same = re; - break; - } - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) || - IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate)) - { - same = re; - break; - } - if (same) - break; - } - } - /* If same type of route can't be found and this message is from - kernel. */ - if (! same) - { - if (fib && type == ZEBRA_ROUTE_KERNEL && - CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE)) - { - if (IS_ZEBRA_DEBUG_RIB) - { - rnode_debug (rn, vrf_id, "rn %p, re %p (type %d) was deleted from kernel, adding", - rn, fib, fib->type); - } - if (allow_delete) - { - /* Unset flags. */ - for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next) - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - - UNSET_FLAG (fib->status, ROUTE_ENTRY_SELECTED_FIB); - } - else - { - /* This means someone else, other than Zebra, has deleted - * a Zebra router from the kernel. We will add it back */ - rib_install_kernel(rn, fib, NULL); - } - } - else - { - if (IS_ZEBRA_DEBUG_RIB) - { - if (gate) - rnode_debug(rn, vrf_id, "via %s ifindex %d type %d " - "doesn't exist in rib", - inet_ntop (family2afi(afi), gate, buf2, INET_ADDRSTRLEN), /* FIXME */ - ifindex, - type); - else - rnode_debug (rn, vrf_id, "ifindex %d type %d doesn't exist in rib", - ifindex, - type); - } - route_unlock_node (rn); - return; + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + route_entry_dump(p, src_p, re); } - } - - if (same) - rib_delnode (rn, same); - - route_unlock_node (rn); - return; -} + rib_addnode(rn, re, 1); + ret = 1; + /* Free implicit route.*/ + if (same) { + rib_delnode(rn, same); + ret = -1; + } + route_unlock_node(rn); + return ret; +} + +void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, + u_short instance, int flags, struct prefix *p, + struct prefix_ipv6 *src_p, union g_addr *gate, + ifindex_t ifindex, u_int32_t table_id) +{ + struct route_table *table; + struct route_node *rn; + struct route_entry *re; + struct route_entry *fib = NULL; + struct route_entry *same = NULL; + struct nexthop *nexthop; + char buf2[INET6_ADDRSTRLEN]; + + assert(!src_p || afi == AFI_IP6); + + /* Lookup table. */ + table = zebra_vrf_table_with_table_id(afi, safi, vrf_id, table_id); + if (!table) + return; + + /* Apply mask. */ + apply_mask(p); + if (src_p) + apply_mask_ipv6(src_p); + + /* Lookup route node. */ + rn = srcdest_rnode_lookup(table, p, src_p); + if (!rn) { + char dst_buf[PREFIX_STRLEN], src_buf[PREFIX_STRLEN]; + + prefix2str(p, dst_buf, sizeof(dst_buf)); + if (src_p && src_p->prefixlen) + prefix2str(src_p, src_buf, sizeof(src_buf)); + else + src_buf[0] = '\0'; + + if (IS_ZEBRA_DEBUG_RIB) + zlog_debug("%u:%s%s%s doesn't exist in rib", vrf_id, + dst_buf, + (src_buf[0] != '\0') ? " from " : "", + src_buf); + return; + } -int -rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, - u_short instance, int flags, struct prefix *p, - struct prefix_ipv6 *src_p, union g_addr *gate, - union g_addr *src, ifindex_t ifindex, - u_int32_t table_id, u_int32_t metric, u_int32_t mtu, - u_char distance) -{ - struct route_entry *re; - struct route_entry *same = NULL; - struct route_table *table; - struct route_node *rn; - struct nexthop *nexthop; + /* Lookup same type route. */ + RNODE_FOREACH_RE(rn, re) + { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + + if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) + fib = re; + + if (re->type != type) + continue; + if (re->instance != instance) + continue; + if (re->type == ZEBRA_ROUTE_CONNECT && (nexthop = re->nexthop) + && nexthop->type == NEXTHOP_TYPE_IFINDEX) { + if (nexthop->ifindex != ifindex) + continue; + if (re->refcnt) { + re->refcnt--; + route_unlock_node(rn); + route_unlock_node(rn); + return; + } + same = re; + break; + } + /* Make sure that the route found has the same gateway. */ + else { + if (gate == NULL) { + same = re; + break; + } + for (ALL_NEXTHOPS(re->nexthop, nexthop)) + if (IPV4_ADDR_SAME(&nexthop->gate.ipv4, gate) + || IPV6_ADDR_SAME(&nexthop->gate.ipv6, + gate)) { + same = re; + break; + } + if (same) + break; + } + } + /* If same type of route can't be found and this message is from + kernel. */ + if (!same) { + if (fib && type == ZEBRA_ROUTE_KERNEL + && CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE)) { + if (IS_ZEBRA_DEBUG_RIB) { + rnode_debug( + rn, vrf_id, + "rn %p, re %p (type %d) was deleted from kernel, adding", + rn, fib, fib->type); + } + if (allow_delete) { + /* Unset flags. */ + for (nexthop = fib->nexthop; nexthop; + nexthop = nexthop->next) + UNSET_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB); + + UNSET_FLAG(fib->status, + ROUTE_ENTRY_SELECTED_FIB); + } else { + /* This means someone else, other than Zebra, + * has deleted + * a Zebra router from the kernel. We will add + * it back */ + rib_install_kernel(rn, fib, NULL); + } + } else { + if (IS_ZEBRA_DEBUG_RIB) { + if (gate) + rnode_debug( + rn, vrf_id, + "via %s ifindex %d type %d " + "doesn't exist in rib", + inet_ntop( + family2afi(afi), gate, + buf2, + INET_ADDRSTRLEN), /* FIXME + */ + ifindex, type); + else + rnode_debug( + rn, vrf_id, + "ifindex %d type %d doesn't exist in rib", + ifindex, type); + } + route_unlock_node(rn); + return; + } + } - assert(!src_p || afi == AFI_IP6); + if (same) + rib_delnode(rn, same); - /* Lookup table. */ - table = zebra_vrf_table_with_table_id (afi, safi, vrf_id, table_id); - if (! table) - return 0; + route_unlock_node(rn); + return; +} - /* Make sure mask is applied. */ - apply_mask (p); - if (src_p) - apply_mask_ipv6 (src_p); - /* Set default distance by route type. */ - if (distance == 0) - { - if ((unsigned)type >= array_size(route_info)) - distance = 150; - else - distance = route_info[type].distance; - - /* iBGP distance is 200. */ - if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP)) - distance = 200; - } +int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, + int flags, struct prefix *p, struct prefix_ipv6 *src_p, + union g_addr *gate, union g_addr *src, ifindex_t ifindex, + u_int32_t table_id, u_int32_t metric, u_int32_t mtu, + u_char distance) +{ + struct route_entry *re; + struct route_entry *same = NULL; + struct route_table *table; + struct route_node *rn; + struct nexthop *nexthop; + + assert(!src_p || afi == AFI_IP6); + + /* Lookup table. */ + table = zebra_vrf_table_with_table_id(afi, safi, vrf_id, table_id); + if (!table) + return 0; + + /* Make sure mask is applied. */ + apply_mask(p); + if (src_p) + apply_mask_ipv6(src_p); + + /* Set default distance by route type. */ + if (distance == 0) { + if ((unsigned)type >= array_size(route_info)) + distance = 150; + else + distance = route_info[type].distance; + + /* iBGP distance is 200. */ + if (type == ZEBRA_ROUTE_BGP + && CHECK_FLAG(flags, ZEBRA_FLAG_IBGP)) + distance = 200; + } - /* Lookup route node.*/ - rn = srcdest_rnode_get (table, p, src_p); + /* Lookup route node.*/ + rn = srcdest_rnode_get(table, p, src_p); - /* If same type of route are installed, treat it as a implicit - withdraw. */ - RNODE_FOREACH_RE (rn, re) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - - if (re->type != type) - continue; - if (re->instance != instance) - continue; - if (re->type != ZEBRA_ROUTE_CONNECT) - { - same = re; - break; - } - /* Duplicate connected route comes in. */ - else if ((nexthop = re->nexthop) && - nexthop->type == NEXTHOP_TYPE_IFINDEX && - nexthop->ifindex == ifindex && - !CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) + /* If same type of route are installed, treat it as a implicit + withdraw. */ + RNODE_FOREACH_RE(rn, re) { - re->refcnt++; - return 0 ; + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + + if (re->type != type) + continue; + if (re->instance != instance) + continue; + if (re->type != ZEBRA_ROUTE_CONNECT) { + same = re; + break; + } + /* Duplicate connected route comes in. */ + else if ((nexthop = re->nexthop) + && nexthop->type == NEXTHOP_TYPE_IFINDEX + && nexthop->ifindex == ifindex + && !CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) { + re->refcnt++; + return 0; + } } - } - /* Allocate new re structure. */ - re = XCALLOC (MTYPE_RE, sizeof (struct route_entry)); - - re->type = type; - re->instance = instance; - re->distance = distance; - re->flags = flags; - re->metric = metric; - re->mtu = mtu; - re->table = table_id; - re->vrf_id = vrf_id; - re->nexthop_num = 0; - re->uptime = time (NULL); - - /* Nexthop settings. */ - if (gate) - { - if (afi == AFI_IP6) - { - if (ifindex) - route_entry_nexthop_ipv6_ifindex_add (re, &gate->ipv6, ifindex); - else - route_entry_nexthop_ipv6_add (re, &gate->ipv6); - } - else - { - if (ifindex) - route_entry_nexthop_ipv4_ifindex_add (re, &gate->ipv4, &src->ipv4, ifindex); - else - route_entry_nexthop_ipv4_add (re, &gate->ipv4, &src->ipv4); + /* Allocate new re structure. */ + re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); + + re->type = type; + re->instance = instance; + re->distance = distance; + re->flags = flags; + re->metric = metric; + re->mtu = mtu; + re->table = table_id; + re->vrf_id = vrf_id; + re->nexthop_num = 0; + re->uptime = time(NULL); + + /* Nexthop settings. */ + if (gate) { + if (afi == AFI_IP6) { + if (ifindex) + route_entry_nexthop_ipv6_ifindex_add( + re, &gate->ipv6, ifindex); + else + route_entry_nexthop_ipv6_add(re, &gate->ipv6); + } else { + if (ifindex) + route_entry_nexthop_ipv4_ifindex_add( + re, &gate->ipv4, &src->ipv4, ifindex); + else + route_entry_nexthop_ipv4_add(re, &gate->ipv4, + &src->ipv4); + } + } else + route_entry_nexthop_ifindex_add(re, ifindex); + + /* If this route is kernel route, set FIB flag to the route. */ + if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT) + for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + + /* Link new rib to node.*/ + if (IS_ZEBRA_DEBUG_RIB) { + rnode_debug( + rn, vrf_id, + "Inserting route rn %p, re %p (type %d) existing %p", + (void *)rn, (void *)re, re->type, (void *)same); + + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + route_entry_dump(p, src_p, re); } - } - else - route_entry_nexthop_ifindex_add (re, ifindex); - - /* If this route is kernel route, set FIB flag to the route. */ - if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT) - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); + rib_addnode(rn, re, 1); - /* Link new rib to node.*/ - if (IS_ZEBRA_DEBUG_RIB) - { - rnode_debug (rn, vrf_id, "Inserting route rn %p, re %p (type %d) existing %p", - (void *)rn, (void *)re, re->type, (void *)same); - - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - route_entry_dump (p, src_p, re); - } - rib_addnode (rn, re, 1); + /* Free implicit route.*/ + if (same) + rib_delnode(rn, same); - /* Free implicit route.*/ - if (same) - rib_delnode (rn, same); - - route_unlock_node (rn); - return 0; + route_unlock_node(rn); + return 0; } /* Schedule routes of a particular table (address-family) based on event. */ -static void -rib_update_table (struct route_table *table, rib_update_event_t event) -{ - struct route_node *rn; - struct route_entry *re, *next; - - /* Walk all routes and queue for processing, if appropriate for - * the trigger event. - */ - for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) - { - switch (event) - { - case RIB_UPDATE_IF_CHANGE: - /* Examine all routes that won't get processed by the protocol or - * triggered by nexthop evaluation (NHT). This would be system, - * kernel and certain static routes. Note that NHT will get - * triggered upon an interface event as connected routes always - * get queued for processing. - */ - RNODE_FOREACH_RE_SAFE (rn, re, next) - { - if (re->type == ZEBRA_ROUTE_OSPF || - re->type == ZEBRA_ROUTE_OSPF6 || - re->type == ZEBRA_ROUTE_BGP) - continue; /* protocol will handle. */ - else if (re->type == ZEBRA_ROUTE_STATIC) - { - struct nexthop *nh; - for (nh = re->nexthop; nh; nh = nh->next) - if (!(nh->type == NEXTHOP_TYPE_IPV4 || - nh->type == NEXTHOP_TYPE_IPV6)) - break; - - /* If we only have nexthops to a gateway, NHT will - * take care. - */ - if (nh) - rib_queue_add (rn); - } - else - rib_queue_add (rn); - } - break; - - case RIB_UPDATE_RMAP_CHANGE: - case RIB_UPDATE_OTHER: - /* Right now, examine all routes. Can restrict to a protocol in - * some cases (TODO). - */ - if (rnode_to_ribs (rn)) - rib_queue_add (rn); - break; - - default: - break; - } - } +static void rib_update_table(struct route_table *table, + rib_update_event_t event) +{ + struct route_node *rn; + struct route_entry *re, *next; + + /* Walk all routes and queue for processing, if appropriate for + * the trigger event. + */ + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) { + switch (event) { + case RIB_UPDATE_IF_CHANGE: + /* Examine all routes that won't get processed by the + * protocol or + * triggered by nexthop evaluation (NHT). This would be + * system, + * kernel and certain static routes. Note that NHT will + * get + * triggered upon an interface event as connected routes + * always + * get queued for processing. + */ + RNODE_FOREACH_RE_SAFE(rn, re, next) + { + if (re->type == ZEBRA_ROUTE_OSPF + || re->type == ZEBRA_ROUTE_OSPF6 + || re->type == ZEBRA_ROUTE_BGP) + continue; /* protocol will handle. */ + else if (re->type == ZEBRA_ROUTE_STATIC) { + struct nexthop *nh; + for (nh = re->nexthop; nh; + nh = nh->next) + if (!(nh->type + == NEXTHOP_TYPE_IPV4 + || nh->type + == NEXTHOP_TYPE_IPV6)) + break; + + /* If we only have nexthops to a + * gateway, NHT will + * take care. + */ + if (nh) + rib_queue_add(rn); + } else + rib_queue_add(rn); + } + break; + + case RIB_UPDATE_RMAP_CHANGE: + case RIB_UPDATE_OTHER: + /* Right now, examine all routes. Can restrict to a + * protocol in + * some cases (TODO). + */ + if (rnode_to_ribs(rn)) + rib_queue_add(rn); + break; + + default: + break; + } + } } /* RIB update function. */ -void -rib_update (vrf_id_t vrf_id, rib_update_event_t event) +void rib_update(vrf_id_t vrf_id, rib_update_event_t event) { - struct route_table *table; + struct route_table *table; - /* Process routes of interested address-families. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (table) - rib_update_table (table, event); + /* Process routes of interested address-families. */ + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); + if (table) + rib_update_table(table, event); - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); - if (table) - rib_update_table (table, event); + table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id); + if (table) + rib_update_table(table, event); } /* Remove all routes which comes from non main table. */ -static void -rib_weed_table (struct route_table *table) +static void rib_weed_table(struct route_table *table) { - struct route_node *rn; - struct route_entry *re; - struct route_entry *next; + struct route_node *rn; + struct route_entry *re; + struct route_entry *next; - if (table) - for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) - RNODE_FOREACH_RE_SAFE (rn, re, next) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; + if (table) + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) + RNODE_FOREACH_RE_SAFE(rn, re, next) + { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; - if (re->table != zebrad.rtm_table_default && - re->table != RT_TABLE_MAIN) - rib_delnode (rn, re); - } + if (re->table != zebrad.rtm_table_default + && re->table != RT_TABLE_MAIN) + rib_delnode(rn, re); + } } /* Delete all routes from non main table. */ -void -rib_weed_tables (void) +void rib_weed_tables(void) { - struct vrf *vrf; - struct zebra_vrf *zvrf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - if ((zvrf = vrf->info) != NULL) - { - rib_weed_table (zvrf->table[AFI_IP][SAFI_UNICAST]); - rib_weed_table (zvrf->table[AFI_IP6][SAFI_UNICAST]); - } + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + if ((zvrf = vrf->info) != NULL) { + rib_weed_table(zvrf->table[AFI_IP][SAFI_UNICAST]); + rib_weed_table(zvrf->table[AFI_IP6][SAFI_UNICAST]); + } } /* Delete self installed routes after zebra is relaunched. */ -static void -rib_sweep_table (struct route_table *table) -{ - struct route_node *rn; - struct route_entry *re; - struct route_entry *next; - int ret = 0; - - if (table) - for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) - RNODE_FOREACH_RE_SAFE (rn, re, next) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - - if (re->type == ZEBRA_ROUTE_KERNEL && - CHECK_FLAG (re->flags, ZEBRA_FLAG_SELFROUTE)) - { - ret = rib_uninstall_kernel (rn, re); - if (! ret) - rib_delnode (rn, re); - } - } +static void rib_sweep_table(struct route_table *table) +{ + struct route_node *rn; + struct route_entry *re; + struct route_entry *next; + int ret = 0; + + if (table) + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) + RNODE_FOREACH_RE_SAFE(rn, re, next) + { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + + if (re->type == ZEBRA_ROUTE_KERNEL + && CHECK_FLAG(re->flags, + ZEBRA_FLAG_SELFROUTE)) { + ret = rib_uninstall_kernel(rn, re); + if (!ret) + rib_delnode(rn, re); + } + } } /* Sweep all RIB tables. */ -void -rib_sweep_route (void) +void rib_sweep_route(void) { - struct vrf *vrf; - struct zebra_vrf *zvrf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - if ((zvrf = vrf->info) != NULL) - { - rib_sweep_table (zvrf->table[AFI_IP][SAFI_UNICAST]); - rib_sweep_table (zvrf->table[AFI_IP6][SAFI_UNICAST]); - } + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + if ((zvrf = vrf->info) != NULL) { + rib_sweep_table(zvrf->table[AFI_IP][SAFI_UNICAST]); + rib_sweep_table(zvrf->table[AFI_IP6][SAFI_UNICAST]); + } } /* Remove specific by protocol routes from 'table'. */ -static unsigned long -rib_score_proto_table (u_char proto, u_short instance, struct route_table *table) -{ - struct route_node *rn; - struct route_entry *re; - struct route_entry *next; - unsigned long n = 0; - - if (table) - for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) - RNODE_FOREACH_RE_SAFE (rn, re, next) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - if (re->type == proto && re->instance == instance) - { - rib_delnode (rn, re); - n++; - } - } - return n; +static unsigned long rib_score_proto_table(u_char proto, u_short instance, + struct route_table *table) +{ + struct route_node *rn; + struct route_entry *re; + struct route_entry *next; + unsigned long n = 0; + + if (table) + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) + RNODE_FOREACH_RE_SAFE(rn, re, next) + { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + if (re->type == proto + && re->instance == instance) { + rib_delnode(rn, re); + n++; + } + } + return n; } /* Remove specific by protocol routes. */ -unsigned long -rib_score_proto (u_char proto, u_short instance) +unsigned long rib_score_proto(u_char proto, u_short instance) { - struct vrf *vrf; - struct zebra_vrf *zvrf; - unsigned long cnt = 0; + struct vrf *vrf; + struct zebra_vrf *zvrf; + unsigned long cnt = 0; - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - if ((zvrf = vrf->info) != NULL) - cnt += rib_score_proto_table (proto, instance, zvrf->table[AFI_IP][SAFI_UNICAST]) - +rib_score_proto_table (proto, instance, zvrf->table[AFI_IP6][SAFI_UNICAST]); + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + if ((zvrf = vrf->info) != NULL) + cnt += rib_score_proto_table(proto, instance, + zvrf->table[AFI_IP][SAFI_UNICAST]) + + rib_score_proto_table( + proto, instance, + zvrf->table[AFI_IP6][SAFI_UNICAST]); - return cnt; + return cnt; } /* Close RIB and clean up kernel routes. */ -void -rib_close_table (struct route_table *table) +void rib_close_table(struct route_table *table) { - struct route_node *rn; - rib_table_info_t *info = table->info; - struct route_entry *re; + struct route_node *rn; + rib_table_info_t *info = table->info; + struct route_entry *re; - if (table) - for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) - RNODE_FOREACH_RE (rn, re) - { - if (!CHECK_FLAG (re->status, ROUTE_ENTRY_SELECTED_FIB)) - continue; + if (table) + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) + RNODE_FOREACH_RE(rn, re) + { + if (!CHECK_FLAG(re->status, + ROUTE_ENTRY_SELECTED_FIB)) + continue; - if (info->safi == SAFI_UNICAST) - hook_call(rib_update, rn, NULL); + if (info->safi == SAFI_UNICAST) + hook_call(rib_update, rn, NULL); - if (! RIB_SYSTEM_ROUTE (re)) - rib_uninstall_kernel (rn, re); - } + if (!RIB_SYSTEM_ROUTE(re)) + rib_uninstall_kernel(rn, re); + } } /* Routing information base initialize. */ -void -rib_init (void) +void rib_init(void) { - rib_queue_init (&zebrad); + rib_queue_init(&zebrad); } /* @@ -2868,22 +2769,20 @@ rib_init (void) * * Returns TRUE if a vrf id was found, FALSE otherwise. */ -static inline int -vrf_id_get_next (vrf_id_t vrf_id, vrf_id_t *next_id_p) +static inline int vrf_id_get_next(vrf_id_t vrf_id, vrf_id_t *next_id_p) { - struct vrf *vrf; + struct vrf *vrf; - vrf = vrf_lookup_by_id (vrf_id); - if (vrf) - { - vrf = RB_NEXT (vrf_id_head, vrf); - if (vrf) { - *next_id_p = vrf->vrf_id; - return 1; - } - } + vrf = vrf_lookup_by_id(vrf_id); + if (vrf) { + vrf = RB_NEXT(vrf_id_head, vrf); + if (vrf) { + *next_id_p = vrf->vrf_id; + return 1; + } + } - return 0; + return 0; } /* @@ -2891,81 +2790,76 @@ vrf_id_get_next (vrf_id_t vrf_id, vrf_id_t *next_id_p) * * Returns the next table in the iteration. */ -struct route_table * -rib_tables_iter_next (rib_tables_iter_t *iter) -{ - struct route_table *table; - - /* - * Array that helps us go over all AFI/SAFI combinations via one - * index. - */ - static struct { - afi_t afi; - safi_t safi; - } afi_safis[] = { - { AFI_IP, SAFI_UNICAST }, - { AFI_IP, SAFI_MULTICAST }, - { AFI_IP, SAFI_LABELED_UNICAST }, - { AFI_IP6, SAFI_UNICAST }, - { AFI_IP6, SAFI_MULTICAST }, - { AFI_IP6, SAFI_LABELED_UNICAST }, - }; - - table = NULL; - - switch (iter->state) - { - - case RIB_TABLES_ITER_S_INIT: - iter->vrf_id = VRF_DEFAULT; - iter->afi_safi_ix = -1; - - /* Fall through */ - - case RIB_TABLES_ITER_S_ITERATING: - iter->afi_safi_ix++; - while (1) - { +struct route_table *rib_tables_iter_next(rib_tables_iter_t *iter) +{ + struct route_table *table; + + /* + * Array that helps us go over all AFI/SAFI combinations via one + * index. + */ + static struct { + afi_t afi; + safi_t safi; + } afi_safis[] = { + {AFI_IP, SAFI_UNICAST}, {AFI_IP, SAFI_MULTICAST}, + {AFI_IP, SAFI_LABELED_UNICAST}, {AFI_IP6, SAFI_UNICAST}, + {AFI_IP6, SAFI_MULTICAST}, {AFI_IP6, SAFI_LABELED_UNICAST}, + }; + + table = NULL; + + switch (iter->state) { + + case RIB_TABLES_ITER_S_INIT: + iter->vrf_id = VRF_DEFAULT; + iter->afi_safi_ix = -1; + + /* Fall through */ + + case RIB_TABLES_ITER_S_ITERATING: + iter->afi_safi_ix++; + while (1) { + + while (iter->afi_safi_ix + < (int)ZEBRA_NUM_OF(afi_safis)) { + table = zebra_vrf_table( + afi_safis[iter->afi_safi_ix].afi, + afi_safis[iter->afi_safi_ix].safi, + iter->vrf_id); + if (table) + break; + + iter->afi_safi_ix++; + } + + /* + * Found another table in this vrf. + */ + if (table) + break; + + /* + * Done with all tables in the current vrf, go to the + * next + * one. + */ + if (!vrf_id_get_next(iter->vrf_id, &iter->vrf_id)) + break; + + iter->afi_safi_ix = 0; + } - while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis)) - { - table = zebra_vrf_table (afi_safis[iter->afi_safi_ix].afi, - afi_safis[iter->afi_safi_ix].safi, - iter->vrf_id); - if (table) break; - iter->afi_safi_ix++; - } - - /* - * Found another table in this vrf. - */ - if (table) - break; - - /* - * Done with all tables in the current vrf, go to the next - * one. - */ - if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id)) - break; - - iter->afi_safi_ix = 0; + case RIB_TABLES_ITER_S_DONE: + return NULL; } - break; - - case RIB_TABLES_ITER_S_DONE: - return NULL; - } - - if (table) - iter->state = RIB_TABLES_ITER_S_ITERATING; - else - iter->state = RIB_TABLES_ITER_S_DONE; + if (table) + iter->state = RIB_TABLES_ITER_S_ITERATING; + else + iter->state = RIB_TABLES_ITER_S_DONE; - return table; + return table; } - diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index c82712b9c..8a326c27f 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -48,22 +48,23 @@ #include "zebra/interface.h" #include "zebra/zebra_memory.h" -static void free_state(vrf_id_t vrf_id, struct route_entry *re, struct route_node *rn); +static void free_state(vrf_id_t vrf_id, struct route_entry *re, + struct route_node *rn); static void copy_state(struct rnh *rnh, struct route_entry *re, struct route_node *rn); -#define lookup_rnh_table(v, f) \ -({ \ - struct zebra_vrf *zvrf; \ - struct route_table *t = NULL; \ - zvrf = zebra_vrf_lookup_by_id(v); \ - if (zvrf) \ - t = zvrf->rnh_table[family2afi(f)]; \ - t; \ -}) +#define lookup_rnh_table(v, f) \ + ({ \ + struct zebra_vrf *zvrf; \ + struct route_table *t = NULL; \ + zvrf = zebra_vrf_lookup_by_id(v); \ + if (zvrf) \ + t = zvrf->rnh_table[family2afi(f)]; \ + t; \ + }) static int compare_state(struct route_entry *r1, struct route_entry *r2); static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, - vrf_id_t vrf_id); + vrf_id_t vrf_id); static void print_rnh(struct route_node *rn, struct vty *vty); int zebra_rnh_ip_default_route = 0; @@ -72,541 +73,526 @@ int zebra_rnh_ipv6_default_route = 0; static inline struct route_table *get_rnh_table(vrf_id_t vrfid, int family, rnh_type_t type) { - struct zebra_vrf *zvrf; - struct route_table *t = NULL; - - zvrf = zebra_vrf_lookup_by_id(vrfid); - if (zvrf) - switch (type) - { - case RNH_NEXTHOP_TYPE: - t = zvrf->rnh_table[family2afi(family)]; - break; - case RNH_IMPORT_CHECK_TYPE: - t = zvrf->import_check_table[family2afi(family)]; - break; - } - - return t; + struct zebra_vrf *zvrf; + struct route_table *t = NULL; + + zvrf = zebra_vrf_lookup_by_id(vrfid); + if (zvrf) + switch (type) { + case RNH_NEXTHOP_TYPE: + t = zvrf->rnh_table[family2afi(family)]; + break; + case RNH_IMPORT_CHECK_TYPE: + t = zvrf->import_check_table[family2afi(family)]; + break; + } + + return t; } -char *rnh_str (struct rnh *rnh, char *buf, int size) +char *rnh_str(struct rnh *rnh, char *buf, int size) { - prefix2str(&(rnh->node->p), buf, size); - return buf; + prefix2str(&(rnh->node->p), buf, size); + return buf; } -struct rnh * -zebra_add_rnh (struct prefix *p, vrf_id_t vrfid, rnh_type_t type) +struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type) { - struct route_table *table; - struct route_node *rn; - struct rnh *rnh = NULL; - char buf[PREFIX2STR_BUFFER]; - - if (IS_ZEBRA_DEBUG_NHT) - { - prefix2str(p, buf, sizeof (buf)); - zlog_debug("%u: Add RNH %s type %d", vrfid, buf, type); - } - table = get_rnh_table(vrfid, PREFIX_FAMILY(p), type); - if (!table) - { - prefix2str(p, buf, sizeof (buf)); - zlog_warn("%u: Add RNH %s type %d - table not found", - vrfid, buf, type); - return NULL; - } - - /* Make it sure prefixlen is applied to the prefix. */ - apply_mask (p); - - /* Lookup (or add) route node.*/ - rn = route_node_get (table, p); - - if (!rn->info) - { - rnh = XCALLOC(MTYPE_RNH, sizeof(struct rnh)); - rnh->client_list = list_new(); - rnh->vrf_id = vrfid; - rnh->zebra_static_route_list = list_new(); - route_lock_node (rn); - rn->info = rnh; - rnh->node = rn; - } - - route_unlock_node (rn); - return (rn->info); + struct route_table *table; + struct route_node *rn; + struct rnh *rnh = NULL; + char buf[PREFIX2STR_BUFFER]; + + if (IS_ZEBRA_DEBUG_NHT) { + prefix2str(p, buf, sizeof(buf)); + zlog_debug("%u: Add RNH %s type %d", vrfid, buf, type); + } + table = get_rnh_table(vrfid, PREFIX_FAMILY(p), type); + if (!table) { + prefix2str(p, buf, sizeof(buf)); + zlog_warn("%u: Add RNH %s type %d - table not found", vrfid, + buf, type); + return NULL; + } + + /* Make it sure prefixlen is applied to the prefix. */ + apply_mask(p); + + /* Lookup (or add) route node.*/ + rn = route_node_get(table, p); + + if (!rn->info) { + rnh = XCALLOC(MTYPE_RNH, sizeof(struct rnh)); + rnh->client_list = list_new(); + rnh->vrf_id = vrfid; + rnh->zebra_static_route_list = list_new(); + route_lock_node(rn); + rn->info = rnh; + rnh->node = rn; + } + + route_unlock_node(rn); + return (rn->info); } -struct rnh * -zebra_lookup_rnh (struct prefix *p, vrf_id_t vrfid, rnh_type_t type) +struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type) { - struct route_table *table; - struct route_node *rn; + struct route_table *table; + struct route_node *rn; - table = get_rnh_table(vrfid, PREFIX_FAMILY(p), type); - if (!table) - return NULL; + table = get_rnh_table(vrfid, PREFIX_FAMILY(p), type); + if (!table) + return NULL; - /* Make it sure prefixlen is applied to the prefix. */ - apply_mask (p); + /* Make it sure prefixlen is applied to the prefix. */ + apply_mask(p); - /* Lookup route node.*/ - rn = route_node_lookup (table, p); - if (!rn) - return NULL; + /* Lookup route node.*/ + rn = route_node_lookup(table, p); + if (!rn) + return NULL; - route_unlock_node (rn); - return (rn->info); + route_unlock_node(rn); + return (rn->info); } -void -zebra_free_rnh (struct rnh *rnh) +void zebra_free_rnh(struct rnh *rnh) { - rnh->flags |= ZEBRA_NHT_DELETED; - list_free (rnh->client_list); - list_free (rnh->zebra_static_route_list); - free_state (rnh->vrf_id, rnh->state, rnh->node); - XFREE (MTYPE_RNH, rnh); + rnh->flags |= ZEBRA_NHT_DELETED; + list_free(rnh->client_list); + list_free(rnh->zebra_static_route_list); + free_state(rnh->vrf_id, rnh->state, rnh->node); + XFREE(MTYPE_RNH, rnh); } -void -zebra_delete_rnh (struct rnh *rnh, rnh_type_t type) +void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type) { - struct route_node *rn; + struct route_node *rn; - if (!rnh || (rnh->flags & ZEBRA_NHT_DELETED) || !(rn = rnh->node)) - return; + if (!rnh || (rnh->flags & ZEBRA_NHT_DELETED) || !(rn = rnh->node)) + return; - if (IS_ZEBRA_DEBUG_NHT) - { - char buf[PREFIX2STR_BUFFER]; - zlog_debug("%u: Del RNH %s type %d", - rnh->vrf_id, rnh_str(rnh, buf, sizeof (buf)), type); - } + if (IS_ZEBRA_DEBUG_NHT) { + char buf[PREFIX2STR_BUFFER]; + zlog_debug("%u: Del RNH %s type %d", rnh->vrf_id, + rnh_str(rnh, buf, sizeof(buf)), type); + } - zebra_free_rnh (rnh); - rn->info = NULL; - route_unlock_node (rn); + zebra_free_rnh(rnh); + rn->info = NULL; + route_unlock_node(rn); } -void -zebra_add_rnh_client (struct rnh *rnh, struct zserv *client, rnh_type_t type, - vrf_id_t vrf_id) +void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, + rnh_type_t type, vrf_id_t vrf_id) { - if (IS_ZEBRA_DEBUG_NHT) - { - char buf[PREFIX2STR_BUFFER]; - zlog_debug("%u: Client %s registers for RNH %s type %d", - vrf_id, zebra_route_string(client->proto), - rnh_str(rnh, buf, sizeof (buf)), type); - } - if (!listnode_lookup(rnh->client_list, client)) - { - listnode_add(rnh->client_list, client); - send_client(rnh, client, type, vrf_id); // Pending: check if its needed - } + if (IS_ZEBRA_DEBUG_NHT) { + char buf[PREFIX2STR_BUFFER]; + zlog_debug("%u: Client %s registers for RNH %s type %d", vrf_id, + zebra_route_string(client->proto), + rnh_str(rnh, buf, sizeof(buf)), type); + } + if (!listnode_lookup(rnh->client_list, client)) { + listnode_add(rnh->client_list, client); + send_client(rnh, client, type, + vrf_id); // Pending: check if its needed + } } -void -zebra_remove_rnh_client (struct rnh *rnh, struct zserv *client, rnh_type_t type) +void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client, + rnh_type_t type) { - if (IS_ZEBRA_DEBUG_NHT) - { - char buf[PREFIX2STR_BUFFER]; - zlog_debug("Client %s unregisters for RNH %s type %d", - zebra_route_string(client->proto), - rnh_str(rnh, buf, sizeof (buf)), type); - } - listnode_delete(rnh->client_list, client); - if (list_isempty(rnh->client_list) && - list_isempty(rnh->zebra_static_route_list)) - zebra_delete_rnh(rnh, type); + if (IS_ZEBRA_DEBUG_NHT) { + char buf[PREFIX2STR_BUFFER]; + zlog_debug("Client %s unregisters for RNH %s type %d", + zebra_route_string(client->proto), + rnh_str(rnh, buf, sizeof(buf)), type); + } + listnode_delete(rnh->client_list, client); + if (list_isempty(rnh->client_list) + && list_isempty(rnh->zebra_static_route_list)) + zebra_delete_rnh(rnh, type); } -void -zebra_register_rnh_static_nh(vrf_id_t vrf_id, struct prefix *nh, - struct route_node *static_rn) +void zebra_register_rnh_static_nh(vrf_id_t vrf_id, struct prefix *nh, + struct route_node *static_rn) { - struct rnh *rnh; + struct rnh *rnh; - rnh = zebra_add_rnh(nh, vrf_id, RNH_NEXTHOP_TYPE); - if (rnh && !listnode_lookup(rnh->zebra_static_route_list, static_rn)) - { - listnode_add(rnh->zebra_static_route_list, static_rn); - } + rnh = zebra_add_rnh(nh, vrf_id, RNH_NEXTHOP_TYPE); + if (rnh && !listnode_lookup(rnh->zebra_static_route_list, static_rn)) { + listnode_add(rnh->zebra_static_route_list, static_rn); + } } -void -zebra_deregister_rnh_static_nh(vrf_id_t vrf_id, struct prefix *nh, - struct route_node *static_rn) +void zebra_deregister_rnh_static_nh(vrf_id_t vrf_id, struct prefix *nh, + struct route_node *static_rn) { - struct rnh *rnh; + struct rnh *rnh; - rnh = zebra_lookup_rnh(nh, vrf_id, RNH_NEXTHOP_TYPE); - if (!rnh || (rnh->flags & ZEBRA_NHT_DELETED)) - return; + rnh = zebra_lookup_rnh(nh, vrf_id, RNH_NEXTHOP_TYPE); + if (!rnh || (rnh->flags & ZEBRA_NHT_DELETED)) + return; - listnode_delete(rnh->zebra_static_route_list, static_rn); + listnode_delete(rnh->zebra_static_route_list, static_rn); - if (list_isempty(rnh->client_list) && - list_isempty(rnh->zebra_static_route_list)) - zebra_delete_rnh(rnh, RNH_NEXTHOP_TYPE); + if (list_isempty(rnh->client_list) + && list_isempty(rnh->zebra_static_route_list)) + zebra_delete_rnh(rnh, RNH_NEXTHOP_TYPE); } -void -zebra_deregister_rnh_static_nexthops (vrf_id_t vrf_id, struct nexthop *nexthop, - struct route_node *rn) +void zebra_deregister_rnh_static_nexthops(vrf_id_t vrf_id, + struct nexthop *nexthop, + struct route_node *rn) { - struct nexthop *nh; - struct prefix nh_p; - - for (nh = nexthop; nh ; nh = nh->next) - { - switch (nh->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - nh_p.family = AF_INET; - nh_p.prefixlen = IPV4_MAX_BITLEN; - nh_p.u.prefix4 = nh->gate.ipv4; - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - nh_p.family = AF_INET6; - nh_p.prefixlen = IPV6_MAX_BITLEN; - nh_p.u.prefix6 = nh->gate.ipv6; - break; - /* - * Not sure what really to do here, we are not - * supposed to have either of these for NHT - * and the code has no way to know what prefix - * to use. So I'm going to just continue - * for the moment, which is preferable to - * what is currently happening which is a - * CRASH and BURN. - * Some simple testing shows that we - * are not leaving slag around for these - * skipped static routes. Since - * they don't appear to be installed - */ - case NEXTHOP_TYPE_IFINDEX: - case NEXTHOP_TYPE_BLACKHOLE: - continue; - break; - } - zebra_deregister_rnh_static_nh(vrf_id, &nh_p, rn); - } + struct nexthop *nh; + struct prefix nh_p; + + for (nh = nexthop; nh; nh = nh->next) { + switch (nh->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + nh_p.family = AF_INET; + nh_p.prefixlen = IPV4_MAX_BITLEN; + nh_p.u.prefix4 = nh->gate.ipv4; + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + nh_p.family = AF_INET6; + nh_p.prefixlen = IPV6_MAX_BITLEN; + nh_p.u.prefix6 = nh->gate.ipv6; + break; + /* + * Not sure what really to do here, we are not + * supposed to have either of these for NHT + * and the code has no way to know what prefix + * to use. So I'm going to just continue + * for the moment, which is preferable to + * what is currently happening which is a + * CRASH and BURN. + * Some simple testing shows that we + * are not leaving slag around for these + * skipped static routes. Since + * they don't appear to be installed + */ + case NEXTHOP_TYPE_IFINDEX: + case NEXTHOP_TYPE_BLACKHOLE: + continue; + break; + } + zebra_deregister_rnh_static_nh(vrf_id, &nh_p, rn); + } } /* Apply the NHT route-map for a client to the route (and nexthops) * resolving a NH. */ -static int -zebra_rnh_apply_nht_rmap(int family, struct route_node *prn, - struct route_entry *re, int proto) +static int zebra_rnh_apply_nht_rmap(int family, struct route_node *prn, + struct route_entry *re, int proto) { - int at_least_one = 0; - int rmap_family; /* Route map has diff AF family enum */ - struct nexthop *nexthop; - int ret; - - rmap_family = (family == AF_INET) ? AFI_IP : AFI_IP6; - - if (prn && re) - { - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - { - ret = zebra_nht_route_map_check(rmap_family, proto, &prn->p, re, - nexthop); - if (ret != RMAP_DENYMATCH) - { - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - at_least_one++; /* at least one valid NH */ - } - else - { - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - } + int at_least_one = 0; + int rmap_family; /* Route map has diff AF family enum */ + struct nexthop *nexthop; + int ret; + + rmap_family = (family == AF_INET) ? AFI_IP : AFI_IP6; + + if (prn && re) { + for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) { + ret = zebra_nht_route_map_check(rmap_family, proto, + &prn->p, re, nexthop); + if (ret != RMAP_DENYMATCH) { + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + at_least_one++; /* at least one valid NH */ + } else { + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + } + } } - } - return (at_least_one); + return (at_least_one); } /* * Determine appropriate route (RE entry) resolving a tracked entry * (nexthop or BGP route for import). */ -static struct route_entry * -zebra_rnh_resolve_entry (vrf_id_t vrfid, int family, rnh_type_t type, - struct route_node *nrn, struct rnh *rnh, - struct route_node **prn) +static struct route_entry *zebra_rnh_resolve_entry(vrf_id_t vrfid, int family, + rnh_type_t type, + struct route_node *nrn, + struct rnh *rnh, + struct route_node **prn) { - struct route_table *route_table; - struct route_node *rn; - struct route_entry *re; - - *prn = NULL; - - route_table = zebra_vrf_table(family2afi(family), SAFI_UNICAST, vrfid); - if (!route_table) // unexpected - return NULL; - - rn = route_node_match(route_table, &nrn->p); - if (!rn) - return NULL; - - /* When resolving nexthops, do not resolve via the default route unless - * 'ip nht resolve-via-default' is configured. - */ - if ((type == RNH_NEXTHOP_TYPE) && - (is_default_prefix (&rn->p) && - !nh_resolve_via_default(rn->p.family))) - re = NULL; - else if ((type == RNH_IMPORT_CHECK_TYPE) && - CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH) && - !prefix_same(&nrn->p, &rn->p)) - re = NULL; - else - { - /* Identify appropriate route entry. */ - RNODE_FOREACH_RE(rn, re) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - if (! CHECK_FLAG (re->status, ROUTE_ENTRY_SELECTED_FIB)) - continue; - - if (CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) - { - if (re->type == ZEBRA_ROUTE_CONNECT) - break; - if (re->type == ZEBRA_ROUTE_NHRP) - { - struct nexthop *nexthop; - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - if (nexthop->type == NEXTHOP_TYPE_IFINDEX) - break; - if (nexthop) - break; - } - } - else if ((type == RNH_IMPORT_CHECK_TYPE) && - (re->type == ZEBRA_ROUTE_BGP)) - continue; - else - break; - } - } - - /* Need to unlock route node */ - route_unlock_node(rn); - if (re) - *prn = rn; - return re; + struct route_table *route_table; + struct route_node *rn; + struct route_entry *re; + + *prn = NULL; + + route_table = zebra_vrf_table(family2afi(family), SAFI_UNICAST, vrfid); + if (!route_table) // unexpected + return NULL; + + rn = route_node_match(route_table, &nrn->p); + if (!rn) + return NULL; + + /* When resolving nexthops, do not resolve via the default route unless + * 'ip nht resolve-via-default' is configured. + */ + if ((type == RNH_NEXTHOP_TYPE) + && (is_default_prefix(&rn->p) + && !nh_resolve_via_default(rn->p.family))) + re = NULL; + else if ((type == RNH_IMPORT_CHECK_TYPE) + && CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH) + && !prefix_same(&nrn->p, &rn->p)) + re = NULL; + else { + /* Identify appropriate route entry. */ + RNODE_FOREACH_RE(rn, re) + { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + if (!CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) + continue; + + if (CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) { + if (re->type == ZEBRA_ROUTE_CONNECT) + break; + if (re->type == ZEBRA_ROUTE_NHRP) { + struct nexthop *nexthop; + for (nexthop = re->nexthop; nexthop; + nexthop = nexthop->next) + if (nexthop->type + == NEXTHOP_TYPE_IFINDEX) + break; + if (nexthop) + break; + } + } else if ((type == RNH_IMPORT_CHECK_TYPE) + && (re->type == ZEBRA_ROUTE_BGP)) + continue; + else + break; + } + } + + /* Need to unlock route node */ + route_unlock_node(rn); + if (re) + *prn = rn; + return re; } /* * See if a tracked route entry for import (by BGP) has undergone any * change, and if so, notify the client. */ -static void -zebra_rnh_eval_import_check_entry (vrf_id_t vrfid, int family, int force, - struct route_node *nrn, struct rnh *rnh, - struct route_entry *re) +static void zebra_rnh_eval_import_check_entry(vrf_id_t vrfid, int family, + int force, struct route_node *nrn, + struct rnh *rnh, + struct route_entry *re) { - int state_changed = 0; - struct zserv *client; - char bufn[INET6_ADDRSTRLEN]; - struct listnode *node; - struct nexthop *nexthop; - - if (re && (rnh->state == NULL)) - { - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - { - state_changed = 1; - break; - } - } - else if (!re && (rnh->state != NULL)) - state_changed = 1; - - if (compare_state(re, rnh->state)) - copy_state(rnh, re, nrn); - - if (state_changed || force) - { - if (IS_ZEBRA_DEBUG_NHT) - { - prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); - zlog_debug("%u:%s: Route import check %s %s\n", - vrfid, bufn, rnh->state ? "passed" : "failed", - state_changed ? "(state changed)" : ""); - } - /* state changed, notify clients */ - for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) - { - send_client(rnh, client, RNH_IMPORT_CHECK_TYPE, vrfid); - } - } + int state_changed = 0; + struct zserv *client; + char bufn[INET6_ADDRSTRLEN]; + struct listnode *node; + struct nexthop *nexthop; + + if (re && (rnh->state == NULL)) { + for (ALL_NEXTHOPS(re->nexthop, nexthop)) + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) { + state_changed = 1; + break; + } + } else if (!re && (rnh->state != NULL)) + state_changed = 1; + + if (compare_state(re, rnh->state)) + copy_state(rnh, re, nrn); + + if (state_changed || force) { + if (IS_ZEBRA_DEBUG_NHT) { + prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); + zlog_debug("%u:%s: Route import check %s %s\n", vrfid, + bufn, rnh->state ? "passed" : "failed", + state_changed ? "(state changed)" : ""); + } + /* state changed, notify clients */ + for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) { + send_client(rnh, client, RNH_IMPORT_CHECK_TYPE, vrfid); + } + } } /* * Notify clients registered for this nexthop about a change. */ -static void -zebra_rnh_notify_protocol_clients (vrf_id_t vrfid, int family, - struct route_node *nrn, struct rnh *rnh, - struct route_node *prn, struct route_entry *re) +static void zebra_rnh_notify_protocol_clients(vrf_id_t vrfid, int family, + struct route_node *nrn, + struct rnh *rnh, + struct route_node *prn, + struct route_entry *re) { - struct listnode *node; - struct zserv *client; - char bufn[INET6_ADDRSTRLEN]; - char bufp[INET6_ADDRSTRLEN]; - int num_resolving_nh; - - if (IS_ZEBRA_DEBUG_NHT) - { - prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); - if (prn && re) - { - prefix2str(&prn->p, bufp, INET6_ADDRSTRLEN); - zlog_debug("%u:%s: NH resolved over route %s", vrfid, bufn, bufp); - } - else - zlog_debug("%u:%s: NH has become unresolved", vrfid, bufn); - } - - for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) - { - if (prn && re) - { - /* Apply route-map for this client to route resolving this - * nexthop to see if it is filtered or not. - */ - num_resolving_nh = zebra_rnh_apply_nht_rmap(family, prn, re, - client->proto); - if (num_resolving_nh) - rnh->filtered[client->proto] = 0; - else - rnh->filtered[client->proto] = 1; - - if (IS_ZEBRA_DEBUG_NHT) - zlog_debug("%u:%s: Notifying client %s about NH %s", - vrfid, bufn, zebra_route_string(client->proto), - num_resolving_nh ? "" : "(filtered by route-map)"); - } - else - { - rnh->filtered[client->proto] = 0; - if (IS_ZEBRA_DEBUG_NHT) - zlog_debug("%u:%s: Notifying client %s about NH (unreachable)", - vrfid, bufn, zebra_route_string(client->proto)); - } - - send_client(rnh, client, RNH_NEXTHOP_TYPE, vrfid); - } + struct listnode *node; + struct zserv *client; + char bufn[INET6_ADDRSTRLEN]; + char bufp[INET6_ADDRSTRLEN]; + int num_resolving_nh; + + if (IS_ZEBRA_DEBUG_NHT) { + prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); + if (prn && re) { + prefix2str(&prn->p, bufp, INET6_ADDRSTRLEN); + zlog_debug("%u:%s: NH resolved over route %s", vrfid, + bufn, bufp); + } else + zlog_debug("%u:%s: NH has become unresolved", vrfid, + bufn); + } + + for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) { + if (prn && re) { + /* Apply route-map for this client to route resolving + * this + * nexthop to see if it is filtered or not. + */ + num_resolving_nh = zebra_rnh_apply_nht_rmap( + family, prn, re, client->proto); + if (num_resolving_nh) + rnh->filtered[client->proto] = 0; + else + rnh->filtered[client->proto] = 1; + + if (IS_ZEBRA_DEBUG_NHT) + zlog_debug( + "%u:%s: Notifying client %s about NH %s", + vrfid, bufn, + zebra_route_string(client->proto), + num_resolving_nh + ? "" + : "(filtered by route-map)"); + } else { + rnh->filtered[client->proto] = 0; + if (IS_ZEBRA_DEBUG_NHT) + zlog_debug( + "%u:%s: Notifying client %s about NH (unreachable)", + vrfid, bufn, + zebra_route_string(client->proto)); + } + + send_client(rnh, client, RNH_NEXTHOP_TYPE, vrfid); + } } -static void -zebra_rnh_process_static_routes (vrf_id_t vrfid, int family, - struct route_node *nrn, struct rnh *rnh, - struct route_node *prn, struct route_entry *re) +static void zebra_rnh_process_static_routes(vrf_id_t vrfid, int family, + struct route_node *nrn, + struct rnh *rnh, + struct route_node *prn, + struct route_entry *re) { - struct listnode *node; - int num_resolving_nh = 0; - struct route_node *static_rn; - struct route_entry *sre; - struct nexthop *nexthop; - char bufn[INET6_ADDRSTRLEN]; - char bufp[INET6_ADDRSTRLEN]; - char bufs[INET6_ADDRSTRLEN]; - - if (IS_ZEBRA_DEBUG_NHT) - { - prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); - if (prn) - prefix2str(&prn->p, bufp, INET6_ADDRSTRLEN); - } - - if (prn && re) - { - /* Apply route-map for "static" to route resolving this - * nexthop to see if it is filtered or not. - */ - num_resolving_nh = zebra_rnh_apply_nht_rmap(family, prn, re, - ZEBRA_ROUTE_STATIC); - if (num_resolving_nh) - rnh->filtered[ZEBRA_ROUTE_STATIC] = 0; - else - rnh->filtered[ZEBRA_ROUTE_STATIC] = 1; - } - else - rnh->filtered[ZEBRA_ROUTE_STATIC] = 0; - - /* Evaluate each static route associated with this nexthop. */ - for (ALL_LIST_ELEMENTS_RO(rnh->zebra_static_route_list, node, - static_rn)) - { - RNODE_FOREACH_RE(static_rn, sre) - { - if (sre->type != ZEBRA_ROUTE_STATIC) - continue; - - /* Set the filter flag for the correct nexthop - static route may - * be having multiple. We care here only about registered nexthops. - */ - for (nexthop = sre->nexthop; nexthop; nexthop = nexthop->next) - { - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - if (nexthop->gate.ipv4.s_addr == nrn->p.u.prefix4.s_addr) - { - if (num_resolving_nh) - UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED); - else - SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED); - } - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: + struct listnode *node; + int num_resolving_nh = 0; + struct route_node *static_rn; + struct route_entry *sre; + struct nexthop *nexthop; + char bufn[INET6_ADDRSTRLEN]; + char bufp[INET6_ADDRSTRLEN]; + char bufs[INET6_ADDRSTRLEN]; + + if (IS_ZEBRA_DEBUG_NHT) { + prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); + if (prn) + prefix2str(&prn->p, bufp, INET6_ADDRSTRLEN); + } - if (memcmp(&nexthop->gate.ipv6,&nrn->p.u.prefix6, 16) == 0) - { - if (num_resolving_nh) - UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED); - else - SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED); - } - break; - default: - break; - } - } - - if (IS_ZEBRA_DEBUG_NHT) - { - prefix2str(&static_rn->p, bufs, INET6_ADDRSTRLEN); - if (prn && re) - zlog_debug("%u:%s: NH change %s, scheduling static route %s", - vrfid, bufn, num_resolving_nh ? - "" : "(filtered by route-map)", bufs); - else - zlog_debug("%u:%s: NH unreachable, scheduling static route %s", - vrfid, bufn, bufs); - } - - SET_FLAG(sre->status, ROUTE_ENTRY_CHANGED); - SET_FLAG(sre->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); - } - - rib_queue_add(static_rn); - } + if (prn && re) { + /* Apply route-map for "static" to route resolving this + * nexthop to see if it is filtered or not. + */ + num_resolving_nh = zebra_rnh_apply_nht_rmap(family, prn, re, + ZEBRA_ROUTE_STATIC); + if (num_resolving_nh) + rnh->filtered[ZEBRA_ROUTE_STATIC] = 0; + else + rnh->filtered[ZEBRA_ROUTE_STATIC] = 1; + } else + rnh->filtered[ZEBRA_ROUTE_STATIC] = 0; + + /* Evaluate each static route associated with this nexthop. */ + for (ALL_LIST_ELEMENTS_RO(rnh->zebra_static_route_list, node, + static_rn)) { + RNODE_FOREACH_RE(static_rn, sre) + { + if (sre->type != ZEBRA_ROUTE_STATIC) + continue; + + /* Set the filter flag for the correct nexthop - static + * route may + * be having multiple. We care here only about + * registered nexthops. + */ + for (nexthop = sre->nexthop; nexthop; + nexthop = nexthop->next) { + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + if (nexthop->gate.ipv4.s_addr + == nrn->p.u.prefix4.s_addr) { + if (num_resolving_nh) + UNSET_FLAG( + nexthop->flags, + NEXTHOP_FLAG_FILTERED); + else + SET_FLAG( + nexthop->flags, + NEXTHOP_FLAG_FILTERED); + } + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + + if (memcmp(&nexthop->gate.ipv6, + &nrn->p.u.prefix6, 16) + == 0) { + if (num_resolving_nh) + UNSET_FLAG( + nexthop->flags, + NEXTHOP_FLAG_FILTERED); + else + SET_FLAG( + nexthop->flags, + NEXTHOP_FLAG_FILTERED); + } + break; + default: + break; + } + } + + if (IS_ZEBRA_DEBUG_NHT) { + prefix2str(&static_rn->p, bufs, + INET6_ADDRSTRLEN); + if (prn && re) + zlog_debug( + "%u:%s: NH change %s, scheduling static route %s", + vrfid, bufn, + num_resolving_nh + ? "" + : "(filtered by route-map)", + bufs); + else + zlog_debug( + "%u:%s: NH unreachable, scheduling static route %s", + vrfid, bufn, bufs); + } + + SET_FLAG(sre->status, ROUTE_ENTRY_CHANGED); + SET_FLAG(sre->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); + } + + rib_queue_add(static_rn); + } } /* @@ -614,83 +600,78 @@ zebra_rnh_process_static_routes (vrf_id_t vrfid, int family, * take appropriate action; this involves notifying any clients and/or * scheduling dependent static routes for processing. */ -static void -zebra_rnh_eval_nexthop_entry (vrf_id_t vrfid, int family, int force, - struct route_node *nrn, struct rnh *rnh, - struct route_node *prn, struct route_entry *re) +static void zebra_rnh_eval_nexthop_entry(vrf_id_t vrfid, int family, int force, + struct route_node *nrn, + struct rnh *rnh, + struct route_node *prn, + struct route_entry *re) { - int state_changed = 0; - - /* If we're resolving over a different route, resolution has changed or - * the resolving route has some change (e.g., metric), there is a state - * change. - */ - if (!prefix_same(&rnh->resolved_route, &prn->p)) - { - if (prn) - prefix_copy(&rnh->resolved_route, &prn->p); - else - memset(&rnh->resolved_route, 0, sizeof(struct prefix)); - - copy_state(rnh, re, nrn); - state_changed = 1; - } - else if (compare_state(re, rnh->state)) - { - copy_state(rnh, re, nrn); - state_changed = 1; - } - - if (state_changed || force) - { - /* NOTE: Use the "copy" of resolving route stored in 'rnh' i.e., - * rnh->state. - */ - /* Notify registered protocol clients. */ - zebra_rnh_notify_protocol_clients (vrfid, family, nrn, rnh, - prn, rnh->state); - - /* Process static routes attached to this nexthop */ - zebra_rnh_process_static_routes (vrfid, family, nrn, rnh, - prn, rnh->state); - } + int state_changed = 0; + + /* If we're resolving over a different route, resolution has changed or + * the resolving route has some change (e.g., metric), there is a state + * change. + */ + if (!prefix_same(&rnh->resolved_route, &prn->p)) { + if (prn) + prefix_copy(&rnh->resolved_route, &prn->p); + else + memset(&rnh->resolved_route, 0, sizeof(struct prefix)); + + copy_state(rnh, re, nrn); + state_changed = 1; + } else if (compare_state(re, rnh->state)) { + copy_state(rnh, re, nrn); + state_changed = 1; + } + + if (state_changed || force) { + /* NOTE: Use the "copy" of resolving route stored in 'rnh' i.e., + * rnh->state. + */ + /* Notify registered protocol clients. */ + zebra_rnh_notify_protocol_clients(vrfid, family, nrn, rnh, prn, + rnh->state); + + /* Process static routes attached to this nexthop */ + zebra_rnh_process_static_routes(vrfid, family, nrn, rnh, prn, + rnh->state); + } } /* Evaluate one tracked entry */ -static void -zebra_rnh_evaluate_entry (vrf_id_t vrfid, int family, int force, rnh_type_t type, - struct route_node *nrn) +static void zebra_rnh_evaluate_entry(vrf_id_t vrfid, int family, int force, + rnh_type_t type, struct route_node *nrn) { - struct rnh *rnh; - struct route_entry *re; - struct route_node *prn; - char bufn[INET6_ADDRSTRLEN]; - - if (IS_ZEBRA_DEBUG_NHT) - { - prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); - zlog_debug("%u:%s: Evaluate RNH, type %d %s", - vrfid, bufn, type, force ? "(force)" : ""); - } - - rnh = nrn->info; - - /* Identify route entry (RE) resolving this tracked entry. */ - re = zebra_rnh_resolve_entry (vrfid, family, type, nrn, rnh, &prn); - - /* If the entry cannot be resolved and that is also the existing state, - * there is nothing further to do. - */ - if (!re && rnh->state == NULL && !force) - return; - - /* Process based on type of entry. */ - if (type == RNH_IMPORT_CHECK_TYPE) - zebra_rnh_eval_import_check_entry (vrfid, family, force, - nrn, rnh, re); - else - zebra_rnh_eval_nexthop_entry (vrfid, family, force, - nrn, rnh, prn, re); + struct rnh *rnh; + struct route_entry *re; + struct route_node *prn; + char bufn[INET6_ADDRSTRLEN]; + + if (IS_ZEBRA_DEBUG_NHT) { + prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); + zlog_debug("%u:%s: Evaluate RNH, type %d %s", vrfid, bufn, type, + force ? "(force)" : ""); + } + + rnh = nrn->info; + + /* Identify route entry (RE) resolving this tracked entry. */ + re = zebra_rnh_resolve_entry(vrfid, family, type, nrn, rnh, &prn); + + /* If the entry cannot be resolved and that is also the existing state, + * there is nothing further to do. + */ + if (!re && rnh->state == NULL && !force) + return; + + /* Process based on type of entry. */ + if (type == RNH_IMPORT_CHECK_TYPE) + zebra_rnh_eval_import_check_entry(vrfid, family, force, nrn, + rnh, re); + else + zebra_rnh_eval_nexthop_entry(vrfid, family, force, nrn, rnh, + prn, re); } /* @@ -702,328 +683,321 @@ zebra_rnh_evaluate_entry (vrf_id_t vrfid, int family, int force, rnh_type_t type * we can have a situation where one re entry * covers multiple nexthops we are interested in. */ -static void -zebra_rnh_clear_nhc_flag (vrf_id_t vrfid, int family, rnh_type_t type, - struct route_node *nrn) +static void zebra_rnh_clear_nhc_flag(vrf_id_t vrfid, int family, + rnh_type_t type, struct route_node *nrn) { - struct rnh *rnh; - struct route_entry *re; - struct route_node *prn; + struct rnh *rnh; + struct route_entry *re; + struct route_node *prn; - rnh = nrn->info; + rnh = nrn->info; - re = zebra_rnh_resolve_entry (vrfid, family, type, nrn, rnh, &prn); + re = zebra_rnh_resolve_entry(vrfid, family, type, nrn, rnh, &prn); - if (re) - UNSET_FLAG (re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); + if (re) + UNSET_FLAG(re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); } /* Evaluate all tracked entries (nexthops or routes for import into BGP) * of a particular VRF and address-family or a specific prefix. */ -void -zebra_evaluate_rnh (vrf_id_t vrfid, int family, int force, rnh_type_t type, - struct prefix *p) +void zebra_evaluate_rnh(vrf_id_t vrfid, int family, int force, rnh_type_t type, + struct prefix *p) { - struct route_table *rnh_table; - struct route_node *nrn; - - rnh_table = get_rnh_table(vrfid, family, type); - if (!rnh_table) // unexpected - return; - - if (p) - { - /* Evaluating a specific entry, make sure it exists. */ - nrn = route_node_lookup (rnh_table, p); - if (nrn && nrn->info) - zebra_rnh_evaluate_entry (vrfid, family, force, type, nrn); - - if (nrn) - route_unlock_node (nrn); - } - else - { - /* Evaluate entire table. */ - nrn = route_top (rnh_table); - while (nrn) - { - if (nrn->info) - zebra_rnh_evaluate_entry (vrfid, family, force, type, nrn); - nrn = route_next(nrn); /* this will also unlock nrn */ - } - nrn = route_top (rnh_table); - while (nrn) - { - if (nrn->info) - zebra_rnh_clear_nhc_flag (vrfid, family, type, nrn); - nrn = route_next(nrn); /* this will also unlock nrn */ - } - } + struct route_table *rnh_table; + struct route_node *nrn; + + rnh_table = get_rnh_table(vrfid, family, type); + if (!rnh_table) // unexpected + return; + + if (p) { + /* Evaluating a specific entry, make sure it exists. */ + nrn = route_node_lookup(rnh_table, p); + if (nrn && nrn->info) + zebra_rnh_evaluate_entry(vrfid, family, force, type, + nrn); + + if (nrn) + route_unlock_node(nrn); + } else { + /* Evaluate entire table. */ + nrn = route_top(rnh_table); + while (nrn) { + if (nrn->info) + zebra_rnh_evaluate_entry(vrfid, family, force, + type, nrn); + nrn = route_next(nrn); /* this will also unlock nrn */ + } + nrn = route_top(rnh_table); + while (nrn) { + if (nrn->info) + zebra_rnh_clear_nhc_flag(vrfid, family, type, + nrn); + nrn = route_next(nrn); /* this will also unlock nrn */ + } + } } -void -zebra_print_rnh_table (vrf_id_t vrfid, int af, struct vty *vty, rnh_type_t type) +void zebra_print_rnh_table(vrf_id_t vrfid, int af, struct vty *vty, + rnh_type_t type) { - struct route_table *table; - struct route_node *rn; - - table = get_rnh_table(vrfid, af, type); - if (!table) - { - zlog_debug("print_rnhs: rnh table not found\n"); - return; - } - - for (rn = route_top(table); rn; rn = route_next(rn)) - if (rn->info) - print_rnh(rn, vty); + struct route_table *table; + struct route_node *rn; + + table = get_rnh_table(vrfid, af, type); + if (!table) { + zlog_debug("print_rnhs: rnh table not found\n"); + return; + } + + for (rn = route_top(table); rn; rn = route_next(rn)) + if (rn->info) + print_rnh(rn, vty); } -int -zebra_cleanup_rnh_client (vrf_id_t vrf_id, int family, struct zserv *client, - rnh_type_t type) +int zebra_cleanup_rnh_client(vrf_id_t vrf_id, int family, struct zserv *client, + rnh_type_t type) { - struct route_table *ntable; - struct route_node *nrn; - struct rnh *rnh; - - if (IS_ZEBRA_DEBUG_NHT) - zlog_debug("%u: Client %s RNH cleanup for family %d type %d", - vrf_id, zebra_route_string(client->proto), family, type); - - ntable = get_rnh_table(vrf_id, family, type); - if (!ntable) - { - zlog_debug("cleanup_rnh_client: rnh table not found\n"); - return -1; - } - - for (nrn = route_top (ntable); nrn; nrn = route_next (nrn)) - { - if (!nrn->info) - continue; - - rnh = nrn->info; - zebra_remove_rnh_client(rnh, client, type); - } - return 1; + struct route_table *ntable; + struct route_node *nrn; + struct rnh *rnh; + + if (IS_ZEBRA_DEBUG_NHT) + zlog_debug("%u: Client %s RNH cleanup for family %d type %d", + vrf_id, zebra_route_string(client->proto), family, + type); + + ntable = get_rnh_table(vrf_id, family, type); + if (!ntable) { + zlog_debug("cleanup_rnh_client: rnh table not found\n"); + return -1; + } + + for (nrn = route_top(ntable); nrn; nrn = route_next(nrn)) { + if (!nrn->info) + continue; + + rnh = nrn->info; + zebra_remove_rnh_client(rnh, client, type); + } + return 1; } /** * free_state - free up the re structure associated with the rnh. */ -static void -free_state (vrf_id_t vrf_id, struct route_entry *re, struct route_node *rn) +static void free_state(vrf_id_t vrf_id, struct route_entry *re, + struct route_node *rn) { - if (!re) - return; + if (!re) + return; - /* free RE and nexthops */ - zebra_deregister_rnh_static_nexthops (vrf_id, re->nexthop, rn); - nexthops_free(re->nexthop); - XFREE (MTYPE_RE, re); + /* free RE and nexthops */ + zebra_deregister_rnh_static_nexthops(vrf_id, re->nexthop, rn); + nexthops_free(re->nexthop); + XFREE(MTYPE_RE, re); } -static void -copy_state (struct rnh *rnh, struct route_entry *re, struct route_node *rn) +static void copy_state(struct rnh *rnh, struct route_entry *re, + struct route_node *rn) { - struct route_entry *state; + struct route_entry *state; - if (rnh->state) - { - free_state(rnh->vrf_id, rnh->state, rn); - rnh->state = NULL; - } + if (rnh->state) { + free_state(rnh->vrf_id, rnh->state, rn); + rnh->state = NULL; + } - if (!re) - return; + if (!re) + return; - state = XCALLOC (MTYPE_RE, sizeof (struct route_entry)); - state->type = re->type; - state->metric = re->metric; + state = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); + state->type = re->type; + state->metric = re->metric; - route_entry_copy_nexthops(state, re->nexthop); - rnh->state = state; + route_entry_copy_nexthops(state, re->nexthop); + rnh->state = state; } -static int -compare_state (struct route_entry *r1, struct route_entry *r2) +static int compare_state(struct route_entry *r1, struct route_entry *r2) { - if (!r1 && !r2) - return 0; + if (!r1 && !r2) + return 0; - if ((!r1 && r2) || (r1 && !r2)) - return 1; + if ((!r1 && r2) || (r1 && !r2)) + return 1; - if (r1->metric != r2->metric) - return 1; + if (r1->metric != r2->metric) + return 1; - if (r1->nexthop_num != r2->nexthop_num) - return 1; + if (r1->nexthop_num != r2->nexthop_num) + return 1; - if (CHECK_FLAG(r1->status, ROUTE_ENTRY_NEXTHOPS_CHANGED)) - return 1; + if (CHECK_FLAG(r1->status, ROUTE_ENTRY_NEXTHOPS_CHANGED)) + return 1; - return 0; + return 0; } -static int -send_client (struct rnh *rnh, struct zserv *client, rnh_type_t type, vrf_id_t vrf_id) +static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, + vrf_id_t vrf_id) { - struct stream *s; - struct route_entry *re; - unsigned long nump; - u_char num; - struct nexthop *nexthop; - struct route_node *rn; - int cmd = (type == RNH_IMPORT_CHECK_TYPE) - ? ZEBRA_IMPORT_CHECK_UPDATE : ZEBRA_NEXTHOP_UPDATE; - - rn = rnh->node; - re = rnh->state; - - /* Get output stream. */ - s = client->obuf; - stream_reset (s); - - zserv_create_header (s, cmd, vrf_id); - - stream_putw(s, rn->p.family); - switch (rn->p.family) - { - case AF_INET: - stream_putc(s, rn->p.prefixlen); - stream_put_in_addr(s, &rn->p.u.prefix4); - break; - case AF_INET6: - stream_putc(s, rn->p.prefixlen); - stream_put(s, &rn->p.u.prefix6, IPV6_MAX_BYTELEN); - break; - default: - zlog_err("%s: Unknown family (%d) notification attempted\n", - __FUNCTION__, rn->p.family); - break; - } - if (re) - { - stream_putc (s, re->distance); - stream_putl (s, re->metric); - num = 0; - nump = stream_get_endp(s); - stream_putc (s, 0); - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - if ((CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) || - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) && - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - { - stream_putc (s, nexthop->type); - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - stream_put_in_addr (s, &nexthop->gate.ipv4); - stream_putl (s, nexthop->ifindex); + struct stream *s; + struct route_entry *re; + unsigned long nump; + u_char num; + struct nexthop *nexthop; + struct route_node *rn; + int cmd = (type == RNH_IMPORT_CHECK_TYPE) ? ZEBRA_IMPORT_CHECK_UPDATE + : ZEBRA_NEXTHOP_UPDATE; + + rn = rnh->node; + re = rnh->state; + + /* Get output stream. */ + s = client->obuf; + stream_reset(s); + + zserv_create_header(s, cmd, vrf_id); + + stream_putw(s, rn->p.family); + switch (rn->p.family) { + case AF_INET: + stream_putc(s, rn->p.prefixlen); + stream_put_in_addr(s, &rn->p.u.prefix4); break; - case NEXTHOP_TYPE_IFINDEX: - stream_putl (s, nexthop->ifindex); + case AF_INET6: + stream_putc(s, rn->p.prefixlen); + stream_put(s, &rn->p.u.prefix6, IPV6_MAX_BYTELEN); break; - case NEXTHOP_TYPE_IPV4_IFINDEX: - stream_put_in_addr (s, &nexthop->gate.ipv4); - stream_putl (s, nexthop->ifindex); + default: + zlog_err("%s: Unknown family (%d) notification attempted\n", + __FUNCTION__, rn->p.family); break; - case NEXTHOP_TYPE_IPV6: - stream_put (s, &nexthop->gate.ipv6, 16); - stream_putl (s, nexthop->ifindex); - break; - case NEXTHOP_TYPE_IPV6_IFINDEX: - stream_put (s, &nexthop->gate.ipv6, 16); - stream_putl (s, nexthop->ifindex); - break; - default: - /* do nothing */ - break; - } - num++; - } - stream_putc_at (s, nump, num); - } - else - { - stream_putc (s, 0); // distance - stream_putl (s, 0); // metric - stream_putc (s, 0); // nexthops - } - stream_putw_at (s, 0, stream_get_endp (s)); - - client->nh_last_upd_time = monotime(NULL); - client->last_write_cmd = cmd; - return zebra_server_send_message(client); + } + if (re) { + stream_putc(s, re->distance); + stream_putl(s, re->metric); + num = 0; + nump = stream_get_endp(s); + stream_putc(s, 0); + for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) + if ((CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB) + || CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_RECURSIVE)) + && CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_ACTIVE)) { + stream_putc(s, nexthop->type); + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + stream_put_in_addr(s, + &nexthop->gate.ipv4); + stream_putl(s, nexthop->ifindex); + break; + case NEXTHOP_TYPE_IFINDEX: + stream_putl(s, nexthop->ifindex); + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + stream_put_in_addr(s, + &nexthop->gate.ipv4); + stream_putl(s, nexthop->ifindex); + break; + case NEXTHOP_TYPE_IPV6: + stream_put(s, &nexthop->gate.ipv6, 16); + stream_putl(s, nexthop->ifindex); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + stream_put(s, &nexthop->gate.ipv6, 16); + stream_putl(s, nexthop->ifindex); + break; + default: + /* do nothing */ + break; + } + num++; + } + stream_putc_at(s, nump, num); + } else { + stream_putc(s, 0); // distance + stream_putl(s, 0); // metric + stream_putc(s, 0); // nexthops + } + stream_putw_at(s, 0, stream_get_endp(s)); + + client->nh_last_upd_time = monotime(NULL); + client->last_write_cmd = cmd; + return zebra_server_send_message(client); } -static void -print_nh (struct nexthop *nexthop, struct vty *vty) +static void print_nh(struct nexthop *nexthop, struct vty *vty) { - char buf[BUFSIZ]; - struct zebra_ns *zns = zebra_ns_lookup (NS_DEFAULT); - - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4)); - if (nexthop->ifindex) - vty_out (vty, ", %s", ifindex2ifname_per_ns (zns, nexthop->ifindex)); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - vty_out (vty, " %s", - inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); - if (nexthop->ifindex) - vty_out (vty, ", via %s", ifindex2ifname_per_ns (zns, nexthop->ifindex)); - break; - case NEXTHOP_TYPE_IFINDEX: - vty_out (vty, " is directly connected, %s", - ifindex2ifname_per_ns (zns, nexthop->ifindex)); - break; - case NEXTHOP_TYPE_BLACKHOLE: - vty_out (vty, " is directly connected, Null0"); - break; - default: - break; - } - vty_out(vty, "\n"); + char buf[BUFSIZ]; + struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + vty_out(vty, " via %s", inet_ntoa(nexthop->gate.ipv4)); + if (nexthop->ifindex) + vty_out(vty, ", %s", + ifindex2ifname_per_ns(zns, nexthop->ifindex)); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + vty_out(vty, " %s", + inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); + if (nexthop->ifindex) + vty_out(vty, ", via %s", + ifindex2ifname_per_ns(zns, nexthop->ifindex)); + break; + case NEXTHOP_TYPE_IFINDEX: + vty_out(vty, " is directly connected, %s", + ifindex2ifname_per_ns(zns, nexthop->ifindex)); + break; + case NEXTHOP_TYPE_BLACKHOLE: + vty_out(vty, " is directly connected, Null0"); + break; + default: + break; + } + vty_out(vty, "\n"); } -static void -print_rnh (struct route_node *rn, struct vty *vty) +static void print_rnh(struct route_node *rn, struct vty *vty) { - struct rnh *rnh; - struct nexthop *nexthop; - struct listnode *node; - struct zserv *client; - char buf[BUFSIZ]; - - rnh = rn->info; - vty_out(vty, "%s%s\n", inet_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ), - CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED) ? "(Connected)" : ""); - if (rnh->state) - { - vty_out(vty, " resolved via %s\n", - zebra_route_string(rnh->state->type)); - for (nexthop = rnh->state->nexthop; nexthop; nexthop = nexthop->next) - print_nh(nexthop, vty); - } - else - vty_out(vty, " unresolved%s\n", - CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED) ? "(Connected)" : ""); - - vty_out(vty, " Client list:"); - for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) - vty_out(vty, " %s(fd %d)%s", zebra_route_string(client->proto), - client->sock, rnh->filtered[client->proto] ? "(filtered)" : ""); - if (!list_isempty(rnh->zebra_static_route_list)) - vty_out(vty, " zebra%s", rnh->filtered[ZEBRA_ROUTE_STATIC] ? "(filtered)" : ""); - vty_out(vty, "\n"); + struct rnh *rnh; + struct nexthop *nexthop; + struct listnode *node; + struct zserv *client; + char buf[BUFSIZ]; + + rnh = rn->info; + vty_out(vty, "%s%s\n", + inet_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ), + CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED) ? "(Connected)" + : ""); + if (rnh->state) { + vty_out(vty, " resolved via %s\n", + zebra_route_string(rnh->state->type)); + for (nexthop = rnh->state->nexthop; nexthop; + nexthop = nexthop->next) + print_nh(nexthop, vty); + } else + vty_out(vty, " unresolved%s\n", + CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED) + ? "(Connected)" + : ""); + + vty_out(vty, " Client list:"); + for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) + vty_out(vty, " %s(fd %d)%s", zebra_route_string(client->proto), + client->sock, + rnh->filtered[client->proto] ? "(filtered)" : ""); + if (!list_isempty(rnh->zebra_static_route_list)) + vty_out(vty, " zebra%s", + rnh->filtered[ZEBRA_ROUTE_STATIC] ? "(filtered)" : ""); + vty_out(vty, "\n"); } diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h index d26b7be25..f8d89ec8c 100644 --- a/zebra/zebra_rnh.h +++ b/zebra/zebra_rnh.h @@ -26,30 +26,28 @@ #include "vty.h" /* Nexthop structure. */ -struct rnh -{ - u_char flags; +struct rnh { + u_char flags; #define ZEBRA_NHT_CONNECTED 0x1 #define ZEBRA_NHT_DELETED 0x2 #define ZEBRA_NHT_EXACT_MATCH 0x4 - /* VRF identifier. */ - vrf_id_t vrf_id; + /* VRF identifier. */ + vrf_id_t vrf_id; - struct route_entry *state; - struct prefix resolved_route; - struct list *client_list; - struct list *zebra_static_route_list; /* static routes dependent on this NH */ - struct route_node *node; - int filtered[ZEBRA_ROUTE_MAX]; /* if this has been filtered for client */ + struct route_entry *state; + struct prefix resolved_route; + struct list *client_list; + struct list * + zebra_static_route_list; /* static routes dependent on this NH + */ + struct route_node *node; + int filtered[ZEBRA_ROUTE_MAX]; /* if this has been filtered for client + */ }; -typedef enum - { - RNH_NEXTHOP_TYPE, - RNH_IMPORT_CHECK_TYPE - } rnh_type_t; +typedef enum { RNH_NEXTHOP_TYPE, RNH_IMPORT_CHECK_TYPE } rnh_type_t; extern int zebra_rnh_ip_default_route; extern int zebra_rnh_ipv6_default_route; @@ -58,20 +56,24 @@ extern struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type); extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type); -extern void zebra_free_rnh (struct rnh *rnh); +extern void zebra_free_rnh(struct rnh *rnh); extern void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type); -extern void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, - vrf_id_t vrfid); -extern void zebra_register_rnh_static_nh(vrf_id_t, struct prefix *, struct route_node *); -extern void zebra_deregister_rnh_static_nexthops (vrf_id_t, struct nexthop *nexthop, - struct route_node *rn); -extern void zebra_deregister_rnh_static_nh(vrf_id_t, struct prefix *, struct route_node *); +extern void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, + rnh_type_t type, vrf_id_t vrfid); +extern void zebra_register_rnh_static_nh(vrf_id_t, struct prefix *, + struct route_node *); +extern void zebra_deregister_rnh_static_nexthops(vrf_id_t, + struct nexthop *nexthop, + struct route_node *rn); +extern void zebra_deregister_rnh_static_nh(vrf_id_t, struct prefix *, + struct route_node *); extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client, rnh_type_t type); -extern void zebra_evaluate_rnh(vrf_id_t vrfid, int family, int force, rnh_type_t type, - struct prefix *p); -extern void zebra_print_rnh_table(vrf_id_t vrfid, int family, struct vty *vty, rnh_type_t); +extern void zebra_evaluate_rnh(vrf_id_t vrfid, int family, int force, + rnh_type_t type, struct prefix *p); +extern void zebra_print_rnh_table(vrf_id_t vrfid, int family, struct vty *vty, + rnh_type_t); extern char *rnh_str(struct rnh *rnh, char *buf, int size); -extern int zebra_cleanup_rnh_client(vrf_id_t vrf, int family, struct zserv *client, - rnh_type_t type); +extern int zebra_cleanup_rnh_client(vrf_id_t vrf, int family, + struct zserv *client, rnh_type_t type); #endif /*_ZEBRA_RNH_H */ diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index a7b47165d..0176b3684 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -40,185 +40,161 @@ static u_int32_t zebra_rmap_update_timer = ZEBRA_RMAP_DEFAULT_UPDATE_TIMER; static struct thread *zebra_t_rmap_update = NULL; -char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1]; /* "any" == ZEBRA_ROUTE_MAX */ +char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX + 1]; /* "any" == ZEBRA_ROUTE_MAX */ /* NH Tracking route map */ -char *nht_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1]; /* "any" == ZEBRA_ROUTE_MAX */ +char *nht_rm[AFI_MAX][ZEBRA_ROUTE_MAX + 1]; /* "any" == ZEBRA_ROUTE_MAX */ char *zebra_import_table_routemap[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; -struct nh_rmap_obj -{ - struct nexthop *nexthop; - vrf_id_t vrf_id; - u_int32_t source_protocol; - int metric; - route_tag_t tag; +struct nh_rmap_obj { + struct nexthop *nexthop; + vrf_id_t vrf_id; + u_int32_t source_protocol; + int metric; + route_tag_t tag; }; static void zebra_route_map_set_delay_timer(u_int32_t value); - /* Add zebra route map rule */ -static int -zebra_route_match_add(struct vty *vty, - const char *command, const char *arg, - route_map_event_t type) -{ - VTY_DECLVAR_CONTEXT (route_map_index, index); - int ret; - - ret = route_map_add_match (index, command, arg); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% Zebra Can't find rule.\n"); - return CMD_WARNING_CONFIG_FAILED; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Zebra Argument is malformed.\n"); - return CMD_WARNING_CONFIG_FAILED; +static int zebra_route_match_add(struct vty *vty, const char *command, + const char *arg, route_map_event_t type) +{ + VTY_DECLVAR_CONTEXT(route_map_index, index); + int ret; + + ret = route_map_add_match(index, command, arg); + if (ret) { + switch (ret) { + case RMAP_RULE_MISSING: + vty_out(vty, "%% Zebra Can't find rule.\n"); + return CMD_WARNING_CONFIG_FAILED; + case RMAP_COMPILE_ERROR: + vty_out(vty, "%% Zebra Argument is malformed.\n"); + return CMD_WARNING_CONFIG_FAILED; + } } - } - if (type != RMAP_EVENT_MATCH_ADDED) - { - route_map_upd8_dependency (type, arg, index->map->name); - } - return CMD_SUCCESS; + if (type != RMAP_EVENT_MATCH_ADDED) { + route_map_upd8_dependency(type, arg, index->map->name); + } + return CMD_SUCCESS; } /* Delete zebra route map rule. */ -static int -zebra_route_match_delete (struct vty *vty, - const char *command, const char *arg, - route_map_event_t type) -{ - VTY_DECLVAR_CONTEXT (route_map_index, index); - int ret; - char *dep_name = NULL; - const char *tmpstr; - char *rmap_name = NULL; - - if (type != RMAP_EVENT_MATCH_DELETED) - { - /* ignore the mundane, the types without any dependency */ - if (arg == NULL) - { - if ((tmpstr = route_map_get_match_arg(index, command)) != NULL) - dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr); - } - else - { - dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg); +static int zebra_route_match_delete(struct vty *vty, const char *command, + const char *arg, route_map_event_t type) +{ + VTY_DECLVAR_CONTEXT(route_map_index, index); + int ret; + char *dep_name = NULL; + const char *tmpstr; + char *rmap_name = NULL; + + if (type != RMAP_EVENT_MATCH_DELETED) { + /* ignore the mundane, the types without any dependency */ + if (arg == NULL) { + if ((tmpstr = route_map_get_match_arg(index, command)) + != NULL) + dep_name = + XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr); + } else { + dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg); + } + rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name); } - rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name); - } - ret = route_map_delete_match (index, command, arg); - if (ret) - { - switch (ret) - { - case RMAP_RULE_MISSING: - vty_out (vty, "%% Zebra Can't find rule.\n"); - return CMD_WARNING_CONFIG_FAILED; - case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Zebra Argument is malformed.\n"); - return CMD_WARNING_CONFIG_FAILED; + ret = route_map_delete_match(index, command, arg); + if (ret) { + switch (ret) { + case RMAP_RULE_MISSING: + vty_out(vty, "%% Zebra Can't find rule.\n"); + return CMD_WARNING_CONFIG_FAILED; + case RMAP_COMPILE_ERROR: + vty_out(vty, "%% Zebra Argument is malformed.\n"); + return CMD_WARNING_CONFIG_FAILED; + } } - } - if (type != RMAP_EVENT_MATCH_DELETED && dep_name) - route_map_upd8_dependency(type, dep_name, rmap_name); + if (type != RMAP_EVENT_MATCH_DELETED && dep_name) + route_map_upd8_dependency(type, dep_name, rmap_name); - if (dep_name) - XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); - if (rmap_name) - XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); + if (dep_name) + XFREE(MTYPE_ROUTE_MAP_RULE, dep_name); + if (rmap_name) + XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* 'match tag TAG' * Match function return 1 if match is success else return 0 */ -static route_map_result_t -route_match_tag (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_tag(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - route_tag_t *tag; - struct nh_rmap_obj *nh_data; + route_tag_t *tag; + struct nh_rmap_obj *nh_data; - if (type == RMAP_ZEBRA) - { - tag = rule; - nh_data = object; + if (type == RMAP_ZEBRA) { + tag = rule; + nh_data = object; - if (nh_data->tag == *tag) - return RMAP_MATCH; - } - return RMAP_NOMATCH; + if (nh_data->tag == *tag) + return RMAP_MATCH; + } + return RMAP_NOMATCH; } /* Route map commands for tag matching */ -static struct route_map_rule_cmd route_match_tag_cmd = -{ - "tag", - route_match_tag, - route_map_rule_tag_compile, - route_map_rule_tag_free, +static struct route_map_rule_cmd route_match_tag_cmd = { + "tag", route_match_tag, route_map_rule_tag_compile, + route_map_rule_tag_free, }; /* `match interface IFNAME' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_interface (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct nh_rmap_obj *nh_data; - char *ifname = rule; - ifindex_t ifindex; - - if (type == RMAP_ZEBRA) - { - if (strcasecmp(ifname, "any") == 0) - return RMAP_MATCH; - nh_data = object; - if (!nh_data || !nh_data->nexthop) - return RMAP_NOMATCH; - ifindex = ifname2ifindex (ifname, nh_data->vrf_id); - if (ifindex == 0) +static route_map_result_t route_match_interface(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct nh_rmap_obj *nh_data; + char *ifname = rule; + ifindex_t ifindex; + + if (type == RMAP_ZEBRA) { + if (strcasecmp(ifname, "any") == 0) + return RMAP_MATCH; + nh_data = object; + if (!nh_data || !nh_data->nexthop) + return RMAP_NOMATCH; + ifindex = ifname2ifindex(ifname, nh_data->vrf_id); + if (ifindex == 0) + return RMAP_NOMATCH; + if (nh_data->nexthop->ifindex == ifindex) + return RMAP_MATCH; + } return RMAP_NOMATCH; - if (nh_data->nexthop->ifindex == ifindex) - return RMAP_MATCH; - } - return RMAP_NOMATCH; } /* Route map `match interface' match statement. `arg' is IFNAME value */ -static void * -route_match_interface_compile (const char *arg) +static void *route_match_interface_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `match interface' value. */ -static void -route_match_interface_free (void *rule) +static void route_match_interface_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for interface matching */ -struct route_map_rule_cmd route_match_interface_cmd = -{ - "interface", - route_match_interface, - route_match_interface_compile, - route_match_interface_free -}; +struct route_map_rule_cmd route_match_interface_cmd = { + "interface", route_match_interface, route_match_interface_compile, + route_match_interface_free}; DEFUN (match_ip_address_prefix_len, match_ip_address_prefix_len_cmd, @@ -229,8 +205,8 @@ DEFUN (match_ip_address_prefix_len, "Match prefix length of ip address\n" "Prefix length\n") { - return zebra_route_match_add (vty, "ip address prefix-len", - argv[4]->arg, RMAP_EVENT_MATCH_ADDED); + return zebra_route_match_add(vty, "ip address prefix-len", argv[4]->arg, + RMAP_EVENT_MATCH_ADDED); } DEFUN (no_match_ip_address_prefix_len, @@ -243,10 +219,9 @@ DEFUN (no_match_ip_address_prefix_len, "Match prefix length of ip address\n" "Prefix length\n") { - char *plen = (argc == 6) ? argv[5]->arg : NULL; - return zebra_route_match_delete (vty, - "ip address prefix-len", plen, - RMAP_EVENT_MATCH_DELETED); + char *plen = (argc == 6) ? argv[5]->arg : NULL; + return zebra_route_match_delete(vty, "ip address prefix-len", plen, + RMAP_EVENT_MATCH_DELETED); } @@ -259,8 +234,8 @@ DEFUN (match_ip_nexthop_prefix_len, "Match prefixlen of given nexthop\n" "Prefix length\n") { - return zebra_route_match_add (vty, "ip next-hop prefix-len", - argv[4]->arg, RMAP_EVENT_MATCH_ADDED); + return zebra_route_match_add(vty, "ip next-hop prefix-len", + argv[4]->arg, RMAP_EVENT_MATCH_ADDED); } DEFUN (no_match_ip_nexthop_prefix_len, @@ -273,10 +248,9 @@ DEFUN (no_match_ip_nexthop_prefix_len, "Match prefix length of nexthop\n" "Prefix length\n") { - char *plen = (argc == 6) ? argv[5]->arg : NULL; - return zebra_route_match_delete (vty, - "ip next-hop prefix-len", plen, - RMAP_EVENT_MATCH_DELETED); + char *plen = (argc == 6) ? argv[5]->arg : NULL; + return zebra_route_match_delete(vty, "ip next-hop prefix-len", plen, + RMAP_EVENT_MATCH_DELETED); } @@ -296,16 +270,16 @@ DEFUN (match_source_protocol, "Routes from kernel\n" "Statically configured routes\n") { - char *proto = argv[2]->text; - int i; + char *proto = argv[2]->text; + int i; - i = proto_name2num(proto); - if (i < 0) - { - vty_out (vty, "invalid protocol name \"%s\"\n", proto); - return CMD_WARNING_CONFIG_FAILED; - } - return zebra_route_match_add (vty, "source-protocol", proto, RMAP_EVENT_MATCH_ADDED); + i = proto_name2num(proto); + if (i < 0) { + vty_out(vty, "invalid protocol name \"%s\"\n", proto); + return CMD_WARNING_CONFIG_FAILED; + } + return zebra_route_match_add(vty, "source-protocol", proto, + RMAP_EVENT_MATCH_ADDED); } DEFUN (no_match_source_protocol, @@ -325,8 +299,9 @@ DEFUN (no_match_source_protocol, "Routes from kernel\n" "Statically configured routes\n") { - char *proto = (argc == 4) ? argv[3]->text : NULL; - return zebra_route_match_delete (vty, "source-protocol", proto, RMAP_EVENT_MATCH_DELETED); + char *proto = (argc == 4) ? argv[3]->text : NULL; + return zebra_route_match_delete(vty, "source-protocol", proto, + RMAP_EVENT_MATCH_DELETED); } /* set functions */ @@ -339,59 +314,53 @@ DEFUN (set_src, "IPv4 src address\n" "IPv6 src address\n") { - int idx_ip = 2; - union g_addr src; - struct interface *pif = NULL; - int family; - struct prefix p; - struct vrf *vrf; + int idx_ip = 2; + union g_addr src; + struct interface *pif = NULL; + int family; + struct prefix p; + struct vrf *vrf; + + if (inet_pton(AF_INET, argv[idx_ip]->arg, &src.ipv4) != 1) { + if (inet_pton(AF_INET6, argv[idx_ip]->arg, &src.ipv6) != 1) { + vty_out(vty, "%% not a valid IPv4/v6 address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + p.family = family = AF_INET6; + p.u.prefix6 = src.ipv6; + p.prefixlen = IPV6_MAX_BITLEN; + } else { + p.family = family = AF_INET; + p.u.prefix4 = src.ipv4; + p.prefixlen = IPV4_MAX_BITLEN; + } + + if (!zebra_check_addr(&p)) { + vty_out(vty, "%% not a valid source IPv4/v6 address\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (inet_pton(AF_INET, argv[idx_ip]->arg, &src.ipv4) != 1) - { - if (inet_pton(AF_INET6, argv[idx_ip]->arg, &src.ipv6) != 1) + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) { - vty_out (vty, "%% not a valid IPv4/v6 address\n"); - return CMD_WARNING_CONFIG_FAILED; + if (family == AF_INET) + pif = if_lookup_exact_address((void *)&src.ipv4, + AF_INET, vrf->vrf_id); + else if (family == AF_INET6) + pif = if_lookup_exact_address((void *)&src.ipv6, + AF_INET6, vrf->vrf_id); + + if (pif != NULL) + break; } - p.family = family = AF_INET6; - p.u.prefix6 = src.ipv6; - p.prefixlen = IPV6_MAX_BITLEN; - } - else - { - p.family = family = AF_INET; - p.u.prefix4 = src.ipv4; - p.prefixlen = IPV4_MAX_BITLEN; - } - - if (!zebra_check_addr(&p)) - { - vty_out (vty, "%% not a valid source IPv4/v6 address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - { - if (family == AF_INET) - pif = if_lookup_exact_address ((void *)&src.ipv4, AF_INET, - vrf->vrf_id); - else if (family == AF_INET6) - pif = if_lookup_exact_address ((void *)&src.ipv6, AF_INET6, - vrf->vrf_id); - - if (pif != NULL) - break; - } - - if (!pif) - { - vty_out (vty, "%% not a local address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - VTY_DECLVAR_CONTEXT (route_map_index, index); - return generic_set_add (vty, index, "src", argv[idx_ip]->arg); + if (!pif) { + vty_out(vty, "%% not a local address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + VTY_DECLVAR_CONTEXT(route_map_index, index); + return generic_set_add(vty, index, "src", argv[idx_ip]->arg); } DEFUN (no_set_src, @@ -403,9 +372,9 @@ DEFUN (no_set_src, "IPv4 address\n" "IPv6 address\n") { - char *ip = (argc == 4) ? argv[3]->arg : NULL; - VTY_DECLVAR_CONTEXT (route_map_index, index); - return generic_set_delete (vty, index, "src", ip); + char *ip = (argc == 4) ? argv[3]->arg : NULL; + VTY_DECLVAR_CONTEXT(route_map_index, index); + return generic_set_delete(vty, index, "src", ip); } DEFUN (zebra_route_map_timer, @@ -416,13 +385,13 @@ DEFUN (zebra_route_map_timer, "Time to wait before route-map updates are processed\n" "0 means event-driven updates are disabled\n") { - int idx_number = 3; - u_int32_t rmap_delay_timer; + int idx_number = 3; + u_int32_t rmap_delay_timer; - rmap_delay_timer = strtoul(argv[idx_number]->arg, NULL, 10); - zebra_route_map_set_delay_timer(rmap_delay_timer); + rmap_delay_timer = strtoul(argv[idx_number]->arg, NULL, 10); + zebra_route_map_set_delay_timer(rmap_delay_timer); - return (CMD_SUCCESS); + return (CMD_SUCCESS); } DEFUN (no_zebra_route_map_timer, @@ -434,9 +403,9 @@ DEFUN (no_zebra_route_map_timer, "Reset delay-timer to default value, 30 secs\n" "0 means event-driven updates are disabled\n") { - zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER); + zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER); - return (CMD_SUCCESS); + return (CMD_SUCCESS); } @@ -449,34 +418,33 @@ DEFUN (ip_protocol, "Specify route-map\n" "Route map name\n") { - char *proto = argv[2]->text; - char *rmap = argv[4]->arg; - int i; - - if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; - else - i = proto_name2num(proto); - if (i < 0) - { - vty_out (vty, "invalid protocol name \"%s\"\n", proto); - return CMD_WARNING_CONFIG_FAILED; - } - if (proto_rm[AFI_IP][i]) - { - if (strcmp(proto_rm[AFI_IP][i], rmap) == 0) - return CMD_SUCCESS; + char *proto = argv[2]->text; + char *rmap = argv[4]->arg; + int i; + + if (strcasecmp(proto, "any") == 0) + i = ZEBRA_ROUTE_MAX; + else + i = proto_name2num(proto); + if (i < 0) { + vty_out(vty, "invalid protocol name \"%s\"\n", proto); + return CMD_WARNING_CONFIG_FAILED; + } + if (proto_rm[AFI_IP][i]) { + if (strcmp(proto_rm[AFI_IP][i], rmap) == 0) + return CMD_SUCCESS; - XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]); - } - proto_rm[AFI_IP][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap); + XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]); + } + proto_rm[AFI_IP][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IPv4 Routemap config for protocol %s, scheduling RIB processing", - VRF_DEFAULT, proto); + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IPv4 Routemap config for protocol %s, scheduling RIB processing", + VRF_DEFAULT, proto); - rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); - return CMD_SUCCESS; + rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); + return CMD_SUCCESS; } DEFUN (no_ip_protocol, @@ -489,35 +457,34 @@ DEFUN (no_ip_protocol, "Specify route map\n" "Route map name\n") { - char *proto = argv[3]->text; - char *rmap = (argc == 6) ? argv[5]->arg : NULL; - int i; + char *proto = argv[3]->text; + char *rmap = (argc == 6) ? argv[5]->arg : NULL; + int i; - if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; - else - i = proto_name2num(proto); + if (strcasecmp(proto, "any") == 0) + i = ZEBRA_ROUTE_MAX; + else + i = proto_name2num(proto); - if (i < 0) - { - vty_out (vty, "invalid protocol name \"%s\"\n", proto); - return CMD_WARNING_CONFIG_FAILED; - } + if (i < 0) { + vty_out(vty, "invalid protocol name \"%s\"\n", proto); + return CMD_WARNING_CONFIG_FAILED; + } - if (!proto_rm[AFI_IP][i]) - return CMD_SUCCESS; + if (!proto_rm[AFI_IP][i]) + return CMD_SUCCESS; - if (!rmap || strcmp (rmap, proto_rm[AFI_IP][i]) == 0) - { - XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]); - proto_rm[AFI_IP][i] = NULL; + if (!rmap || strcmp(rmap, proto_rm[AFI_IP][i]) == 0) { + XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]); + proto_rm[AFI_IP][i] = NULL; - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IPv4 Routemap unconfig for protocol %s, scheduling RIB processing", - VRF_DEFAULT, proto); - rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); - } - return CMD_SUCCESS; + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IPv4 Routemap unconfig for protocol %s, scheduling RIB processing", + VRF_DEFAULT, proto); + rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); + } + return CMD_SUCCESS; } DEFUN (show_ip_protocol, @@ -527,24 +494,23 @@ DEFUN (show_ip_protocol, IP_STR "IP protocol filtering status\n") { - int i; + int i; - vty_out (vty, "Protocol : route-map \n"); - vty_out (vty, "------------------------\n"); - for (i=0;itext; - char *rmap = argv[4]->arg; - int i; - - if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; - else - i = proto_name2num(proto); - if (i < 0) - { - vty_out (vty, "invalid protocol name \"%s\"\n", proto); - return CMD_WARNING_CONFIG_FAILED; - } - if (proto_rm[AFI_IP6][i]) - { - if (strcmp(proto_rm[AFI_IP6][i], rmap) == 0) - return CMD_SUCCESS; + char *proto = argv[2]->text; + char *rmap = argv[4]->arg; + int i; + + if (strcasecmp(proto, "any") == 0) + i = ZEBRA_ROUTE_MAX; + else + i = proto_name2num(proto); + if (i < 0) { + vty_out(vty, "invalid protocol name \"%s\"\n", proto); + return CMD_WARNING_CONFIG_FAILED; + } + if (proto_rm[AFI_IP6][i]) { + if (strcmp(proto_rm[AFI_IP6][i], rmap) == 0) + return CMD_SUCCESS; - XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]); - } - proto_rm[AFI_IP6][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap); + XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]); + } + proto_rm[AFI_IP6][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IPv6 Routemap config for protocol %s, scheduling RIB processing", - VRF_DEFAULT, proto); + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IPv6 Routemap config for protocol %s, scheduling RIB processing", + VRF_DEFAULT, proto); - rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); - return CMD_SUCCESS; + rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); + return CMD_SUCCESS; } DEFUN (no_ipv6_protocol, @@ -596,34 +561,33 @@ DEFUN (no_ipv6_protocol, "Specify route map\n" "Route map name\n") { - const char *proto = argv[3]->text; - const char *rmap = (argc == 6) ? argv[5]->arg : NULL; - int i; - - if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; - else - i = proto_name2num(proto); - if (i < 0) - { - vty_out (vty, "invalid protocol name \"%s\"\n", proto); - return CMD_WARNING_CONFIG_FAILED; - } - if (!proto_rm[AFI_IP6][i]) - return CMD_SUCCESS; + const char *proto = argv[3]->text; + const char *rmap = (argc == 6) ? argv[5]->arg : NULL; + int i; + + if (strcasecmp(proto, "any") == 0) + i = ZEBRA_ROUTE_MAX; + else + i = proto_name2num(proto); + if (i < 0) { + vty_out(vty, "invalid protocol name \"%s\"\n", proto); + return CMD_WARNING_CONFIG_FAILED; + } + if (!proto_rm[AFI_IP6][i]) + return CMD_SUCCESS; - if (!rmap || strcmp(rmap, proto_rm[AFI_IP6][i]) == 0) - { - XFREE (MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]); - proto_rm[AFI_IP6][i] = NULL; + if (!rmap || strcmp(rmap, proto_rm[AFI_IP6][i]) == 0) { + XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]); + proto_rm[AFI_IP6][i] = NULL; - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: IPv6 Routemap unconfig for protocol %s, scheduling RIB processing", - VRF_DEFAULT, proto); + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IPv6 Routemap unconfig for protocol %s, scheduling RIB processing", + VRF_DEFAULT, proto); - rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); - } - return CMD_SUCCESS; + rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); + } + return CMD_SUCCESS; } DEFUN (show_ipv6_protocol, @@ -633,24 +597,23 @@ DEFUN (show_ipv6_protocol, IP6_STR "IPv6 protocol filtering status\n") { - int i; + int i; - vty_out (vty, "Protocol : route-map \n"); - vty_out (vty, "------------------------\n"); - for (i=0;itext; - char *rmap = argv[4]->arg; - int i; - - if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; - else - i = proto_name2num(proto); - if (i < 0) - { - vty_out (vty, "invalid protocol name \"%s\"\n", proto); - return CMD_WARNING_CONFIG_FAILED; - } - if (nht_rm[AFI_IP][i]) - { - if (strcmp(nht_rm[AFI_IP][i], rmap) == 0) - return CMD_SUCCESS; + char *proto = argv[2]->text; + char *rmap = argv[4]->arg; + int i; + + if (strcasecmp(proto, "any") == 0) + i = ZEBRA_ROUTE_MAX; + else + i = proto_name2num(proto); + if (i < 0) { + vty_out(vty, "invalid protocol name \"%s\"\n", proto); + return CMD_WARNING_CONFIG_FAILED; + } + if (nht_rm[AFI_IP][i]) { + if (strcmp(nht_rm[AFI_IP][i], rmap) == 0) + return CMD_SUCCESS; - XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]); - } + XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]); + } - nht_rm[AFI_IP][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap); - zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + nht_rm[AFI_IP][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); + zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_protocol_nht_rmap, @@ -699,28 +660,28 @@ DEFUN (no_ip_protocol_nht_rmap, "Specify route map\n" "Route map name\n") { - int idx = 0; - char *proto = argv[3]->text; - char *rmap = argv_find (argv, argc, "ROUTE-MAP", &idx) ? argv[idx]->arg : NULL; + int idx = 0; + char *proto = argv[3]->text; + char *rmap = argv_find(argv, argc, "ROUTE-MAP", &idx) ? argv[idx]->arg + : NULL; - int i = strmatch(proto, "any") ? ZEBRA_ROUTE_MAX : proto_name2num(proto); + int i = strmatch(proto, "any") ? ZEBRA_ROUTE_MAX + : proto_name2num(proto); - if (i < 0) - { - vty_out (vty, "invalid protocol name \"%s\"\n", proto); - return CMD_WARNING_CONFIG_FAILED; - } + if (i < 0) { + vty_out(vty, "invalid protocol name \"%s\"\n", proto); + return CMD_WARNING_CONFIG_FAILED; + } - if (!nht_rm[AFI_IP][i]) - return CMD_SUCCESS; + if (!nht_rm[AFI_IP][i]) + return CMD_SUCCESS; - if (!rmap || strcmp(rmap, nht_rm[AFI_IP][i]) == 0) - { - XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]); - nht_rm[AFI_IP][i] = NULL; - zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); - } - return CMD_SUCCESS; + if (!rmap || strcmp(rmap, nht_rm[AFI_IP][i]) == 0) { + XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]); + nht_rm[AFI_IP][i] = NULL; + zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + } + return CMD_SUCCESS; } DEFUN (show_ip_protocol_nht, @@ -731,24 +692,23 @@ DEFUN (show_ip_protocol_nht, "IP nexthop tracking table\n" "IP Next Hop tracking filtering status\n") { - int i; + int i; - vty_out (vty, "Protocol : route-map \n"); - vty_out (vty, "------------------------\n"); - for (i=0;itext; - char *rmap = argv[4]->arg; - int i; - - if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; - else - i = proto_name2num(proto); - if (i < 0) - { - vty_out (vty, "invalid protocol name \"%s\"\n", proto); - return CMD_WARNING_CONFIG_FAILED; - } - if (nht_rm[AFI_IP6][i]) - XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]); - nht_rm[AFI_IP6][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap); - zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); + char *proto = argv[2]->text; + char *rmap = argv[4]->arg; + int i; + + if (strcasecmp(proto, "any") == 0) + i = ZEBRA_ROUTE_MAX; + else + i = proto_name2num(proto); + if (i < 0) { + vty_out(vty, "invalid protocol name \"%s\"\n", proto); + return CMD_WARNING_CONFIG_FAILED; + } + if (nht_rm[AFI_IP6][i]) + XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]); + nht_rm[AFI_IP6][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); + zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ipv6_protocol_nht_rmap, @@ -791,35 +750,32 @@ DEFUN (no_ipv6_protocol_nht_rmap, "Specify route map\n" "Route map name\n") { - char *proto = argv[3]->text; - char *rmap = (argc == 6) ? argv[5]->arg : NULL; - int i; - - if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; - else - i = proto_name2num(proto); - if (i < 0) - { - vty_out (vty, "invalid protocol name \"%s\"\n", proto); - return CMD_WARNING_CONFIG_FAILED; - } + char *proto = argv[3]->text; + char *rmap = (argc == 6) ? argv[5]->arg : NULL; + int i; + + if (strcasecmp(proto, "any") == 0) + i = ZEBRA_ROUTE_MAX; + else + i = proto_name2num(proto); + if (i < 0) { + vty_out(vty, "invalid protocol name \"%s\"\n", proto); + return CMD_WARNING_CONFIG_FAILED; + } - if (nht_rm[AFI_IP6][i] && rmap && strcmp(rmap, nht_rm[AFI_IP6][i])) - { - vty_out (vty, "invalid route-map \"%s\"\n", rmap); - return CMD_WARNING_CONFIG_FAILED; - } + if (nht_rm[AFI_IP6][i] && rmap && strcmp(rmap, nht_rm[AFI_IP6][i])) { + vty_out(vty, "invalid route-map \"%s\"\n", rmap); + return CMD_WARNING_CONFIG_FAILED; + } - if (nht_rm[AFI_IP6][i]) - { - XFREE (MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]); - nht_rm[AFI_IP6][i] = NULL; - } + if (nht_rm[AFI_IP6][i]) { + XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]); + nht_rm[AFI_IP6][i] = NULL; + } - zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ipv6_protocol_nht, @@ -830,24 +786,23 @@ DEFUN (show_ipv6_protocol_nht, "Next Hop filtering status\n" "Route-map\n") { - int i; + int i; - vty_out (vty, "Protocol : route-map \n"); - vty_out (vty, "------------------------\n"); - for (i=0;inexthop->type) { - case NEXTHOP_TYPE_IFINDEX: - /* Interface routes can't match ip next-hop */ - return RMAP_NOMATCH; - case NEXTHOP_TYPE_IPV4_IFINDEX: - case NEXTHOP_TYPE_IPV4: - p.family = AF_INET; - p.prefix = nh_data->nexthop->gate.ipv4; - p.prefixlen = IPV4_MAX_BITLEN; - break; - default: - return RMAP_NOMATCH; - } - alist = access_list_lookup (AFI_IP, (char *) rule); - if (alist == NULL) +static route_map_result_t route_match_ip_next_hop(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct access_list *alist; + struct nh_rmap_obj *nh_data; + struct prefix_ipv4 p; + + if (type == RMAP_ZEBRA) { + nh_data = object; + if (!nh_data) + return RMAP_DENYMATCH; + + switch (nh_data->nexthop->type) { + case NEXTHOP_TYPE_IFINDEX: + /* Interface routes can't match ip next-hop */ + return RMAP_NOMATCH; + case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4: + p.family = AF_INET; + p.prefix = nh_data->nexthop->gate.ipv4; + p.prefixlen = IPV4_MAX_BITLEN; + break; + default: + return RMAP_NOMATCH; + } + alist = access_list_lookup(AFI_IP, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; + + return (access_list_apply(alist, &p) == FILTER_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } return RMAP_NOMATCH; - - return (access_list_apply (alist, &p) == FILTER_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; } /* Route map `ip next-hop' match statement. `arg' should be access-list name. */ -static void * -route_match_ip_next_hop_compile (const char *arg) +static void *route_match_ip_next_hop_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `. */ -static void -route_match_ip_next_hop_free (void *rule) +static void route_match_ip_next_hop_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip next-hop matching. */ -static struct route_map_rule_cmd route_match_ip_next_hop_cmd = -{ - "ip next-hop", - route_match_ip_next_hop, - route_match_ip_next_hop_compile, - route_match_ip_next_hop_free -}; +static struct route_map_rule_cmd route_match_ip_next_hop_cmd = { + "ip next-hop", route_match_ip_next_hop, route_match_ip_next_hop_compile, + route_match_ip_next_hop_free}; /* `match ip next-hop prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - struct prefix_list *plist; - struct nh_rmap_obj *nh_data; - struct prefix_ipv4 p; - - if (type == RMAP_ZEBRA) - { - nh_data = (struct nh_rmap_obj *)object; - if (!nh_data) - return RMAP_DENYMATCH; - - switch (nh_data->nexthop->type) { - case NEXTHOP_TYPE_IFINDEX: - /* Interface routes can't match ip next-hop */ - return RMAP_NOMATCH; - case NEXTHOP_TYPE_IPV4_IFINDEX: - case NEXTHOP_TYPE_IPV4: - p.family = AF_INET; - p.prefix = nh_data->nexthop->gate.ipv4; - p.prefixlen = IPV4_MAX_BITLEN; - break; - default: - return RMAP_NOMATCH; - } - plist = prefix_list_lookup (AFI_IP, (char *) rule); - if (plist == NULL) - return RMAP_NOMATCH; - - return (prefix_list_apply (plist, &p) == PREFIX_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; + struct prefix_list *plist; + struct nh_rmap_obj *nh_data; + struct prefix_ipv4 p; + + if (type == RMAP_ZEBRA) { + nh_data = (struct nh_rmap_obj *)object; + if (!nh_data) + return RMAP_DENYMATCH; + + switch (nh_data->nexthop->type) { + case NEXTHOP_TYPE_IFINDEX: + /* Interface routes can't match ip next-hop */ + return RMAP_NOMATCH; + case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4: + p.family = AF_INET; + p.prefix = nh_data->nexthop->gate.ipv4; + p.prefixlen = IPV4_MAX_BITLEN; + break; + default: + return RMAP_NOMATCH; + } + plist = prefix_list_lookup(AFI_IP, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; + + return (prefix_list_apply(plist, &p) == PREFIX_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } + return RMAP_NOMATCH; } -static void * -route_match_ip_next_hop_prefix_list_compile (const char *arg) +static void *route_match_ip_next_hop_prefix_list_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ip_next_hop_prefix_list_free (void *rule) +static void route_match_ip_next_hop_prefix_list_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = -{ - "ip next-hop prefix-list", - route_match_ip_next_hop_prefix_list, - route_match_ip_next_hop_prefix_list_compile, - route_match_ip_next_hop_prefix_list_free -}; +static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = { + "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list, + route_match_ip_next_hop_prefix_list_compile, + route_match_ip_next_hop_prefix_list_free}; /* `match ip address IP_ACCESS_LIST' */ /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t -route_match_ip_address (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_ip_address(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct access_list *alist; + struct access_list *alist; + + if (type == RMAP_ZEBRA) { + alist = access_list_lookup(AFI_IP, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; - if (type == RMAP_ZEBRA) - { - alist = access_list_lookup (AFI_IP, (char *) rule); - if (alist == NULL) + return (access_list_apply(alist, prefix) == FILTER_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } return RMAP_NOMATCH; - - return (access_list_apply (alist, prefix) == FILTER_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; } /* Route map `ip address' match statement. `arg' should be access-list name. */ -static void * -route_match_ip_address_compile (const char *arg) +static void *route_match_ip_address_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `ip address' value. */ -static void -route_match_ip_address_free (void *rule) +static void route_match_ip_address_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip address matching. */ -static struct route_map_rule_cmd route_match_ip_address_cmd = -{ - "ip address", - route_match_ip_address, - route_match_ip_address_compile, - route_match_ip_address_free -}; +static struct route_map_rule_cmd route_match_ip_address_cmd = { + "ip address", route_match_ip_address, route_match_ip_address_compile, + route_match_ip_address_free}; /* `match ip address prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_address_prefix_list (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - struct prefix_list *plist; + struct prefix_list *plist; + + if (type == RMAP_ZEBRA) { + plist = prefix_list_lookup(AFI_IP, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; - if (type == RMAP_ZEBRA) - { - plist = prefix_list_lookup (AFI_IP, (char *) rule); - if (plist == NULL) + return (prefix_list_apply(plist, prefix) == PREFIX_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } return RMAP_NOMATCH; - - return (prefix_list_apply (plist, prefix) == PREFIX_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; } -static void * -route_match_ip_address_prefix_list_compile (const char *arg) +static void *route_match_ip_address_prefix_list_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ip_address_prefix_list_free (void *rule) +static void route_match_ip_address_prefix_list_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = -{ - "ip address prefix-list", - route_match_ip_address_prefix_list, - route_match_ip_address_prefix_list_compile, - route_match_ip_address_prefix_list_free -}; +static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { + "ip address prefix-list", route_match_ip_address_prefix_list, + route_match_ip_address_prefix_list_compile, + route_match_ip_address_prefix_list_free}; /* `match ip address prefix-len PREFIXLEN' */ static route_map_result_t -route_match_ip_address_prefix_len (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_address_prefix_len(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - u_int32_t *prefixlen = (u_int32_t *)rule; + u_int32_t *prefixlen = (u_int32_t *)rule; - if (type == RMAP_ZEBRA) - { - return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH); - } - return RMAP_NOMATCH; + if (type == RMAP_ZEBRA) { + return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH + : RMAP_NOMATCH); + } + return RMAP_NOMATCH; } -static void * -route_match_ip_address_prefix_len_compile (const char *arg) +static void *route_match_ip_address_prefix_len_compile(const char *arg) { - u_int32_t *prefix_len; - char *endptr = NULL; - unsigned long tmpval; + u_int32_t *prefix_len; + char *endptr = NULL; + unsigned long tmpval; - /* prefix len value shoud be integer. */ - if (! all_digit (arg)) - return NULL; + /* prefix len value shoud be integer. */ + if (!all_digit(arg)) + return NULL; - errno = 0; - tmpval = strtoul (arg, &endptr, 10); - if (*endptr != '\0' || errno || tmpval > UINT32_MAX) - return NULL; + errno = 0; + tmpval = strtoul(arg, &endptr, 10); + if (*endptr != '\0' || errno || tmpval > UINT32_MAX) + return NULL; - prefix_len = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); + prefix_len = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t)); - if (!prefix_len) - return prefix_len; + if (!prefix_len) + return prefix_len; - *prefix_len = tmpval; - return prefix_len; + *prefix_len = tmpval; + return prefix_len; } -static void -route_match_ip_address_prefix_len_free (void *rule) +static void route_match_ip_address_prefix_len_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd = -{ - "ip address prefix-len", - route_match_ip_address_prefix_len, - route_match_ip_address_prefix_len_compile, - route_match_ip_address_prefix_len_free -}; +static struct route_map_rule_cmd route_match_ip_address_prefix_len_cmd = { + "ip address prefix-len", route_match_ip_address_prefix_len, + route_match_ip_address_prefix_len_compile, + route_match_ip_address_prefix_len_free}; /* `match ip nexthop prefix-len PREFIXLEN' */ static route_map_result_t -route_match_ip_nexthop_prefix_len (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - u_int32_t *prefixlen = (u_int32_t *)rule; - struct nh_rmap_obj *nh_data; - struct prefix_ipv4 p; - - if (type == RMAP_ZEBRA) - { - nh_data = (struct nh_rmap_obj *)object; - if (!nh_data || !nh_data->nexthop) - return RMAP_DENYMATCH; - - switch (nh_data->nexthop->type) { - case NEXTHOP_TYPE_IFINDEX: - /* Interface routes can't match ip next-hop */ - return RMAP_NOMATCH; - case NEXTHOP_TYPE_IPV4_IFINDEX: - case NEXTHOP_TYPE_IPV4: - p.family = AF_INET; - p.prefix = nh_data->nexthop->gate.ipv4; - p.prefixlen = IPV4_MAX_BITLEN; - break; - default: - return RMAP_NOMATCH; - } - return ((p.prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH); - } - return RMAP_NOMATCH; -} - -static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd = -{ - "ip next-hop prefix-len", - route_match_ip_nexthop_prefix_len, - route_match_ip_address_prefix_len_compile, /* reuse */ - route_match_ip_address_prefix_len_free /* reuse */ +route_match_ip_nexthop_prefix_len(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + u_int32_t *prefixlen = (u_int32_t *)rule; + struct nh_rmap_obj *nh_data; + struct prefix_ipv4 p; + + if (type == RMAP_ZEBRA) { + nh_data = (struct nh_rmap_obj *)object; + if (!nh_data || !nh_data->nexthop) + return RMAP_DENYMATCH; + + switch (nh_data->nexthop->type) { + case NEXTHOP_TYPE_IFINDEX: + /* Interface routes can't match ip next-hop */ + return RMAP_NOMATCH; + case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4: + p.family = AF_INET; + p.prefix = nh_data->nexthop->gate.ipv4; + p.prefixlen = IPV4_MAX_BITLEN; + break; + default: + return RMAP_NOMATCH; + } + return ((p.prefixlen == *prefixlen) ? RMAP_MATCH + : RMAP_NOMATCH); + } + return RMAP_NOMATCH; +} + +static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd = { + "ip next-hop prefix-len", route_match_ip_nexthop_prefix_len, + route_match_ip_address_prefix_len_compile, /* reuse */ + route_match_ip_address_prefix_len_free /* reuse */ }; /* `match source-protocol PROTOCOL' */ -static route_map_result_t -route_match_source_protocol (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_source_protocol(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - u_int32_t *rib_type = (u_int32_t *)rule; - struct nh_rmap_obj *nh_data; + u_int32_t *rib_type = (u_int32_t *)rule; + struct nh_rmap_obj *nh_data; - if (type == RMAP_ZEBRA) - { - nh_data = (struct nh_rmap_obj *)object; - if (!nh_data) - return RMAP_DENYMATCH; + if (type == RMAP_ZEBRA) { + nh_data = (struct nh_rmap_obj *)object; + if (!nh_data) + return RMAP_DENYMATCH; - return ((nh_data->source_protocol == *rib_type) - ? RMAP_MATCH : RMAP_NOMATCH); - } - return RMAP_NOMATCH; + return ((nh_data->source_protocol == *rib_type) ? RMAP_MATCH + : RMAP_NOMATCH); + } + return RMAP_NOMATCH; } -static void * -route_match_source_protocol_compile (const char *arg) +static void *route_match_source_protocol_compile(const char *arg) { - u_int32_t *rib_type; - int i; + u_int32_t *rib_type; + int i; - i = proto_name2num(arg); - rib_type = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); + i = proto_name2num(arg); + rib_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t)); - *rib_type = i; + *rib_type = i; - return rib_type; + return rib_type; } -static void -route_match_source_protocol_free (void *rule) +static void route_match_source_protocol_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -static struct route_map_rule_cmd route_match_source_protocol_cmd = -{ - "source-protocol", - route_match_source_protocol, - route_match_source_protocol_compile, - route_match_source_protocol_free -}; +static struct route_map_rule_cmd route_match_source_protocol_cmd = { + "source-protocol", route_match_source_protocol, + route_match_source_protocol_compile, route_match_source_protocol_free}; /* `set src A.B.C.D' */ /* Set src. */ -static route_map_result_t -route_set_src (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_src(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - struct nh_rmap_obj *nh_data; + struct nh_rmap_obj *nh_data; - if (type == RMAP_ZEBRA) - { - nh_data = (struct nh_rmap_obj *)object; - nh_data->nexthop->rmap_src = *(union g_addr *)rule; - } - return RMAP_OKAY; + if (type == RMAP_ZEBRA) { + nh_data = (struct nh_rmap_obj *)object; + nh_data->nexthop->rmap_src = *(union g_addr *)rule; + } + return RMAP_OKAY; } /* set src compilation. */ -static void * -route_set_src_compile (const char *arg) +static void *route_set_src_compile(const char *arg) { - union g_addr src, *psrc; + union g_addr src, *psrc; - if ((inet_pton(AF_INET6, arg, &src.ipv6) == 1) || - (src.ipv4.s_addr && (inet_pton(AF_INET, arg, &src.ipv4) == 1))) - { - psrc = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (union g_addr)); - *psrc = src; - return psrc; - } - return NULL; + if ((inet_pton(AF_INET6, arg, &src.ipv6) == 1) + || (src.ipv4.s_addr && (inet_pton(AF_INET, arg, &src.ipv4) == 1))) { + psrc = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(union g_addr)); + *psrc = src; + return psrc; + } + return NULL; } /* Free route map's compiled `set src' value. */ -static void -route_set_src_free (void *rule) +static void route_set_src_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Set src rule structure. */ -static struct route_map_rule_cmd route_set_src_cmd = -{ - "src", - route_set_src, - route_set_src_compile, - route_set_src_free, +static struct route_map_rule_cmd route_set_src_cmd = { + "src", route_set_src, route_set_src_compile, route_set_src_free, }; -static int -zebra_route_map_update_timer (struct thread *thread) +static int zebra_route_map_update_timer(struct thread *thread) { - zebra_t_rmap_update = NULL; + zebra_t_rmap_update = NULL; - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("Event driven route-map update triggered"); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("Event driven route-map update triggered"); - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%u: Routemap update-timer fired, scheduling RIB processing", - VRF_DEFAULT); + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: Routemap update-timer fired, scheduling RIB processing", + VRF_DEFAULT); - zebra_import_table_rm_update (); - rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); - zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); - zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_import_table_rm_update(); + rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); + zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); - return (0); + return (0); } -static void -zebra_route_map_set_delay_timer(u_int32_t value) +static void zebra_route_map_set_delay_timer(u_int32_t value) { - zebra_rmap_update_timer = value; - if (!value && zebra_t_rmap_update) - { - /* Event driven route map updates is being disabled */ - /* But there's a pending timer. Fire it off now */ - thread_cancel(zebra_t_rmap_update); - zebra_route_map_update_timer(zebra_t_rmap_update); - } + zebra_rmap_update_timer = value; + if (!value && zebra_t_rmap_update) { + /* Event driven route map updates is being disabled */ + /* But there's a pending timer. Fire it off now */ + thread_cancel(zebra_t_rmap_update); + zebra_route_map_update_timer(zebra_t_rmap_update); + } } -void -zebra_route_map_write_delay_timer (struct vty *vty) +void zebra_route_map_write_delay_timer(struct vty *vty) { - if (vty && (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)) - vty_out (vty, "zebra route-map delay-timer %d\n", - zebra_rmap_update_timer); - return; + if (vty && (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)) + vty_out(vty, "zebra route-map delay-timer %d\n", + zebra_rmap_update_timer); + return; } -route_map_result_t -zebra_route_map_check (int family, int rib_type, struct prefix *p, - struct nexthop *nexthop, vrf_id_t vrf_id, route_tag_t tag) +route_map_result_t zebra_route_map_check(int family, int rib_type, + struct prefix *p, + struct nexthop *nexthop, + vrf_id_t vrf_id, route_tag_t tag) { - struct route_map *rmap = NULL; - route_map_result_t ret = RMAP_MATCH; - struct nh_rmap_obj nh_obj; + struct route_map *rmap = NULL; + route_map_result_t ret = RMAP_MATCH; + struct nh_rmap_obj nh_obj; - nh_obj.nexthop = nexthop; - nh_obj.vrf_id = vrf_id; - nh_obj.source_protocol = rib_type; - nh_obj.metric = 0; - nh_obj.tag = tag; + nh_obj.nexthop = nexthop; + nh_obj.vrf_id = vrf_id; + nh_obj.source_protocol = rib_type; + nh_obj.metric = 0; + nh_obj.tag = tag; - if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX) - rmap = route_map_lookup_by_name (proto_rm[family][rib_type]); - if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX]) - rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]); - if (rmap) { - ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); - } + if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX) + rmap = route_map_lookup_by_name(proto_rm[family][rib_type]); + if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX]) + rmap = route_map_lookup_by_name( + proto_rm[family][ZEBRA_ROUTE_MAX]); + if (rmap) { + ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); + } - return (ret); + return (ret); } -char * -zebra_get_import_table_route_map (afi_t afi, uint32_t table) +char *zebra_get_import_table_route_map(afi_t afi, uint32_t table) { - return zebra_import_table_routemap[afi][table]; + return zebra_import_table_routemap[afi][table]; } -void -zebra_add_import_table_route_map (afi_t afi, const char *rmap_name, uint32_t table) +void zebra_add_import_table_route_map(afi_t afi, const char *rmap_name, + uint32_t table) { - zebra_import_table_routemap[afi][table] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, rmap_name); + zebra_import_table_routemap[afi][table] = + XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name); } -void -zebra_del_import_table_route_map (afi_t afi, uint32_t table) +void zebra_del_import_table_route_map(afi_t afi, uint32_t table) { - XFREE (MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]); + XFREE(MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]); } route_map_result_t -zebra_import_table_route_map_check (int family, int re_type, struct prefix *p, - struct nexthop *nexthop, vrf_id_t vrf_id, route_tag_t tag, const char *rmap_name) -{ - struct route_map *rmap = NULL; - route_map_result_t ret = RMAP_DENYMATCH; - struct nh_rmap_obj nh_obj; - - nh_obj.nexthop = nexthop; - nh_obj.vrf_id = vrf_id; - nh_obj.source_protocol = re_type; - nh_obj.metric = 0; - nh_obj.tag = tag; - - if (re_type >= 0 && re_type < ZEBRA_ROUTE_MAX) - rmap = route_map_lookup_by_name (rmap_name); - if (rmap) { - ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); - } +zebra_import_table_route_map_check(int family, int re_type, struct prefix *p, + struct nexthop *nexthop, vrf_id_t vrf_id, + route_tag_t tag, const char *rmap_name) +{ + struct route_map *rmap = NULL; + route_map_result_t ret = RMAP_DENYMATCH; + struct nh_rmap_obj nh_obj; + + nh_obj.nexthop = nexthop; + nh_obj.vrf_id = vrf_id; + nh_obj.source_protocol = re_type; + nh_obj.metric = 0; + nh_obj.tag = tag; + + if (re_type >= 0 && re_type < ZEBRA_ROUTE_MAX) + rmap = route_map_lookup_by_name(rmap_name); + if (rmap) { + ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); + } - return (ret); + return (ret); } -route_map_result_t -zebra_nht_route_map_check (int family, int client_proto, struct prefix *p, - struct route_entry * re, struct nexthop *nexthop) +route_map_result_t zebra_nht_route_map_check(int family, int client_proto, + struct prefix *p, + struct route_entry *re, + struct nexthop *nexthop) { - struct route_map *rmap = NULL; - route_map_result_t ret = RMAP_MATCH; - struct nh_rmap_obj nh_obj; + struct route_map *rmap = NULL; + route_map_result_t ret = RMAP_MATCH; + struct nh_rmap_obj nh_obj; - nh_obj.nexthop = nexthop; - nh_obj.vrf_id = re->vrf_id; - nh_obj.source_protocol = re->type; - nh_obj.metric = re->metric; - nh_obj.tag = re->tag; + nh_obj.nexthop = nexthop; + nh_obj.vrf_id = re->vrf_id; + nh_obj.source_protocol = re->type; + nh_obj.metric = re->metric; + nh_obj.tag = re->tag; - if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX) - rmap = route_map_lookup_by_name (nht_rm[family][client_proto]); - if (!rmap && nht_rm[family][ZEBRA_ROUTE_MAX]) - rmap = route_map_lookup_by_name (nht_rm[family][ZEBRA_ROUTE_MAX]); - if (rmap) { - ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); - } + if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX) + rmap = route_map_lookup_by_name(nht_rm[family][client_proto]); + if (!rmap && nht_rm[family][ZEBRA_ROUTE_MAX]) + rmap = route_map_lookup_by_name( + nht_rm[family][ZEBRA_ROUTE_MAX]); + if (rmap) { + ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); + } - return (ret); + return (ret); } -static void -zebra_route_map_mark_update (const char *rmap_name) +static void zebra_route_map_mark_update(const char *rmap_name) { - /* rmap_update_timer of 0 means don't do route updates */ - if (zebra_rmap_update_timer && !zebra_t_rmap_update) { - zebra_t_rmap_update = NULL; - thread_add_timer(zebrad.master, zebra_route_map_update_timer, NULL, zebra_rmap_update_timer, - &zebra_t_rmap_update); - } + /* rmap_update_timer of 0 means don't do route updates */ + if (zebra_rmap_update_timer && !zebra_t_rmap_update) { + zebra_t_rmap_update = NULL; + thread_add_timer(zebrad.master, zebra_route_map_update_timer, + NULL, zebra_rmap_update_timer, + &zebra_t_rmap_update); + } } -static void -zebra_route_map_add (const char *rmap_name) +static void zebra_route_map_add(const char *rmap_name) { - zebra_route_map_mark_update(rmap_name); - route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); + zebra_route_map_mark_update(rmap_name); + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); } -static void -zebra_route_map_delete (const char *rmap_name) +static void zebra_route_map_delete(const char *rmap_name) { - zebra_route_map_mark_update(rmap_name); - route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED); + zebra_route_map_mark_update(rmap_name); + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED); } -static void -zebra_route_map_event (route_map_event_t event, const char *rmap_name) +static void zebra_route_map_event(route_map_event_t event, + const char *rmap_name) { - zebra_route_map_mark_update(rmap_name); - route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); + zebra_route_map_mark_update(rmap_name); + route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED); } /* ip protocol configuration write function */ -void -zebra_routemap_config_write_protocol (struct vty *vty) -{ - int i; - - for (i=0;i *p2) - return 1; - p1++; p2++; - } - return 0; + int i; + + for (i = 0; i < 4; i++) { + if (*p1 < *p2) + return -1; + if (*p1 > *p2) + return 1; + p1++; + p2++; + } + return 0; } -static int -in_addr_add(u_char *p, int num) +static int in_addr_add(u_char *p, int num) { - int i, ip0; - - ip0 = *p; - p += 4; - for (i = 3; 0 <= i; i--) { - p--; - if (*p + num > 255) { - *p += num; - num = 1; - } else { - *p += num; - return 1; - } - } - if (ip0 > *p) { - /* ip + num > 0xffffffff */ - return 0; - } - - return 1; -} + int i, ip0; + + ip0 = *p; + p += 4; + for (i = 3; 0 <= i; i--) { + p--; + if (*p + num > 255) { + *p += num; + num = 1; + } else { + *p += num; + return 1; + } + } + if (ip0 > *p) { + /* ip + num > 0xffffffff */ + return 0; + } -static int -proto_trans(int type) -{ - switch (type) - { - case ZEBRA_ROUTE_SYSTEM: - return 1; /* other */ - case ZEBRA_ROUTE_KERNEL: - return 1; /* other */ - case ZEBRA_ROUTE_CONNECT: - return 2; /* local interface */ - case ZEBRA_ROUTE_STATIC: - return 3; /* static route */ - case ZEBRA_ROUTE_RIP: - return 8; /* rip */ - case ZEBRA_ROUTE_RIPNG: - return 1; /* shouldn't happen */ - case ZEBRA_ROUTE_OSPF: - return 13; /* ospf */ - case ZEBRA_ROUTE_OSPF6: - return 1; /* shouldn't happen */ - case ZEBRA_ROUTE_BGP: - return 14; /* bgp */ - default: - return 1; /* other */ - } + return 1; } -static void -check_replace(struct route_node *np2, struct route_entry *re2, - struct route_node **np, struct route_entry **re) +static int proto_trans(int type) { - int proto, proto2; - - if (!*np) - { - *np = np2; - *re = re2; - return; - } - - if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) < 0) - return; - if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) > 0) - { - *np = np2; - *re = re2; - return; - } - - proto = proto_trans((*re)->type); - proto2 = proto_trans(re2->type); - - if (proto2 > proto) - return; - if (proto2 < proto) - { - *np = np2; - *re = re2; - return; - } - - if (in_addr_cmp((u_char *)&(*re)->nexthop->gate.ipv4, - (u_char *)&re2->nexthop->gate.ipv4) <= 0) - return; - - *np = np2; - *re = re2; - return; + switch (type) { + case ZEBRA_ROUTE_SYSTEM: + return 1; /* other */ + case ZEBRA_ROUTE_KERNEL: + return 1; /* other */ + case ZEBRA_ROUTE_CONNECT: + return 2; /* local interface */ + case ZEBRA_ROUTE_STATIC: + return 3; /* static route */ + case ZEBRA_ROUTE_RIP: + return 8; /* rip */ + case ZEBRA_ROUTE_RIPNG: + return 1; /* shouldn't happen */ + case ZEBRA_ROUTE_OSPF: + return 13; /* ospf */ + case ZEBRA_ROUTE_OSPF6: + return 1; /* shouldn't happen */ + case ZEBRA_ROUTE_BGP: + return 14; /* bgp */ + default: + return 1; /* other */ + } } -static void -get_fwtable_route_node(struct variable *v, oid objid[], size_t *objid_len, - int exact, struct route_node **np, struct route_entry **re) +static void check_replace(struct route_node *np2, struct route_entry *re2, + struct route_node **np, struct route_entry **re) { - struct in_addr dest; - struct route_table *table; - struct route_node *np2; - struct route_entry *re2; - int proto; - int policy; - struct in_addr nexthop; - u_char *pnt; - int i; + int proto, proto2; - /* Init index variables */ + if (!*np) { + *np = np2; + *re = re2; + return; + } - pnt = (u_char *) &dest; - for (i = 0; i < 4; i++) - *pnt++ = 0; + if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) < 0) + return; + if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) > 0) { + *np = np2; + *re = re2; + return; + } - pnt = (u_char *) &nexthop; - for (i = 0; i < 4; i++) - *pnt++ = 0; + proto = proto_trans((*re)->type); + proto2 = proto_trans(re2->type); - proto = 0; - policy = 0; - - /* Init return variables */ + if (proto2 > proto) + return; + if (proto2 < proto) { + *np = np2; + *re = re2; + return; + } - *np = NULL; - *re = NULL; + if (in_addr_cmp((u_char *)&(*re)->nexthop->gate.ipv4, + (u_char *)&re2->nexthop->gate.ipv4) + <= 0) + return; - /* Short circuit exact matches of wrong length */ + *np = np2; + *re = re2; + return; +} - if (exact && (*objid_len != (unsigned) v->namelen + 10)) - return; +static void get_fwtable_route_node(struct variable *v, oid objid[], + size_t *objid_len, int exact, + struct route_node **np, + struct route_entry **re) +{ + struct in_addr dest; + struct route_table *table; + struct route_node *np2; + struct route_entry *re2; + int proto; + int policy; + struct in_addr nexthop; + u_char *pnt; + int i; + + /* Init index variables */ + + pnt = (u_char *)&dest; + for (i = 0; i < 4; i++) + *pnt++ = 0; - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT); - if (! table) - return; + pnt = (u_char *)&nexthop; + for (i = 0; i < 4; i++) + *pnt++ = 0; - /* Get INDEX information out of OID. - * ipForwardDest, ipForwardProto, ipForwardPolicy, ipForwardNextHop - */ + proto = 0; + policy = 0; - if (*objid_len > (unsigned) v->namelen) - oid2in_addr (objid + v->namelen, MIN(4U, *objid_len - v->namelen), &dest); + /* Init return variables */ - if (*objid_len > (unsigned) v->namelen + 4) - proto = objid[v->namelen + 4]; + *np = NULL; + *re = NULL; - if (*objid_len > (unsigned) v->namelen + 5) - policy = objid[v->namelen + 5]; + /* Short circuit exact matches of wrong length */ - if (*objid_len > (unsigned) v->namelen + 6) - oid2in_addr (objid + v->namelen + 6, MIN(4U, *objid_len - v->namelen - 6), - &nexthop); + if (exact && (*objid_len != (unsigned)v->namelen + 10)) + return; - /* Apply GETNEXT on not exact search */ + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, VRF_DEFAULT); + if (!table) + return; - if (!exact && (*objid_len >= (unsigned) v->namelen + 10)) - { - if (! in_addr_add((u_char *) &nexthop, 1)) - return; - } + /* Get INDEX information out of OID. + * ipForwardDest, ipForwardProto, ipForwardPolicy, ipForwardNextHop + */ - /* For exact: search matching entry in rib table. */ + if (*objid_len > (unsigned)v->namelen) + oid2in_addr(objid + v->namelen, + MIN(4U, *objid_len - v->namelen), &dest); - if (exact) - { - if (policy) /* Not supported (yet?) */ - return; - for (*np = route_top (table); *np; *np = route_next (*np)) - { - if (!in_addr_cmp(&(*np)->p.u.prefix, (u_char *)&dest)) - { - RNODE_FOREACH_RE (*np, *re) - { - if (!in_addr_cmp((u_char *)&(*re)->nexthop->gate.ipv4, - (u_char *)&nexthop)) - if (proto == proto_trans((*re)->type)) - return; + if (*objid_len > (unsigned)v->namelen + 4) + proto = objid[v->namelen + 4]; + + if (*objid_len > (unsigned)v->namelen + 5) + policy = objid[v->namelen + 5]; + + if (*objid_len > (unsigned)v->namelen + 6) + oid2in_addr(objid + v->namelen + 6, + MIN(4U, *objid_len - v->namelen - 6), &nexthop); + + /* Apply GETNEXT on not exact search */ + + if (!exact && (*objid_len >= (unsigned)v->namelen + 10)) { + if (!in_addr_add((u_char *)&nexthop, 1)) + return; + } + + /* For exact: search matching entry in rib table. */ + + if (exact) { + if (policy) /* Not supported (yet?) */ + return; + for (*np = route_top(table); *np; *np = route_next(*np)) { + if (!in_addr_cmp(&(*np)->p.u.prefix, (u_char *)&dest)) { + RNODE_FOREACH_RE(*np, *re) + { + if (!in_addr_cmp((u_char *)&(*re) + ->nexthop->gate + .ipv4, + (u_char *)&nexthop)) + if (proto + == proto_trans((*re)->type)) + return; + } + } } - } + return; } - return; - } - - /* Search next best entry */ - - for (np2 = route_top (table); np2; np2 = route_next (np2)) - { - - /* Check destination first */ - if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) > 0) - RNODE_FOREACH_RE (np2, re2) - check_replace(np2, re2, np, re); - - if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) == 0) - { /* have to look at each re individually */ - RNODE_FOREACH_RE (np2, re2) - { - int proto2, policy2; - - proto2 = proto_trans(re2->type); - policy2 = 0; - - if ((policy < policy2) - || ((policy == policy2) && (proto < proto2)) - || ((policy == policy2) && (proto == proto2) - && (in_addr_cmp((u_char *)&re2->nexthop->gate.ipv4, - (u_char *) &nexthop) >= 0) - )) + + /* Search next best entry */ + + for (np2 = route_top(table); np2; np2 = route_next(np2)) { + + /* Check destination first */ + if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) > 0) + RNODE_FOREACH_RE(np2, re2) check_replace(np2, re2, np, re); - } + + if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) + == 0) { /* have to look at each re individually */ + RNODE_FOREACH_RE(np2, re2) + { + int proto2, policy2; + + proto2 = proto_trans(re2->type); + policy2 = 0; + + if ((policy < policy2) + || ((policy == policy2) && (proto < proto2)) + || ((policy == policy2) && (proto == proto2) + && (in_addr_cmp((u_char *)&re2->nexthop + ->gate.ipv4, + (u_char *)&nexthop) + >= 0))) + check_replace(np2, re2, np, re); + } + } } - } - if (!*re) - return; + if (!*re) + return; - policy = 0; - proto = proto_trans((*re)->type); + policy = 0; + proto = proto_trans((*re)->type); - *objid_len = v->namelen + 10; - pnt = (u_char *) &(*np)->p.u.prefix; - for (i = 0; i < 4; i++) - objid[v->namelen + i] = *pnt++; + *objid_len = v->namelen + 10; + pnt = (u_char *)&(*np)->p.u.prefix; + for (i = 0; i < 4; i++) + objid[v->namelen + i] = *pnt++; - objid[v->namelen + 4] = proto; - objid[v->namelen + 5] = policy; + objid[v->namelen + 4] = proto; + objid[v->namelen + 5] = policy; - { - struct nexthop *nexthop; + { + struct nexthop *nexthop; - nexthop = (*re)->nexthop; - if (nexthop) - { - pnt = (u_char *) &nexthop->gate.ipv4; - for (i = 0; i < 4; i++) - objid[i + v->namelen + 6] = *pnt++; - } - } + nexthop = (*re)->nexthop; + if (nexthop) { + pnt = (u_char *)&nexthop->gate.ipv4; + for (i = 0; i < 4; i++) + objid[i + v->namelen + 6] = *pnt++; + } + } - return; + return; } -static u_char * -ipFwTable (struct variable *v, oid objid[], size_t *objid_len, - int exact, size_t *val_len, WriteMethod **write_method) +static u_char *ipFwTable(struct variable *v, oid objid[], size_t *objid_len, + int exact, size_t *val_len, WriteMethod **write_method) { - struct route_node *np; - struct route_entry *re; - static int result; - static int resarr[2]; - static struct in_addr netmask; - struct nexthop *nexthop; - - if (smux_header_table(v, objid, objid_len, exact, val_len, write_method) - == MATCH_FAILED) - return NULL; - - get_fwtable_route_node(v, objid, objid_len, exact, &np, &re); - if (!np) - return NULL; - - nexthop = re->nexthop; - if (! nexthop) - return NULL; - - switch (v->magic) - { - case IPFORWARDDEST: - *val_len = 4; - return &np->p.u.prefix; - break; - case IPFORWARDMASK: - masklen2ip(np->p.prefixlen, &netmask); - *val_len = 4; - return (u_char *)&netmask; - break; - case IPFORWARDPOLICY: - result = 0; - *val_len = sizeof(int); - return (u_char *)&result; - break; - case IPFORWARDNEXTHOP: - *val_len = 4; - return (u_char *)&nexthop->gate.ipv4; - break; - case IPFORWARDIFINDEX: - *val_len = sizeof(int); - return (u_char *)&nexthop->ifindex; - break; - case IPFORWARDTYPE: - if (nexthop->type == NEXTHOP_TYPE_IFINDEX) - result = 3; - else - result = 4; - *val_len = sizeof(int); - return (u_char *)&result; - break; - case IPFORWARDPROTO: - result = proto_trans(re->type); - *val_len = sizeof(int); - return (u_char *)&result; - break; - case IPFORWARDAGE: - result = 0; - *val_len = sizeof(int); - return (u_char *)&result; - break; - case IPFORWARDINFO: - resarr[0] = 0; - resarr[1] = 0; - *val_len = 2 * sizeof(int); - return (u_char *)resarr; - break; - case IPFORWARDNEXTHOPAS: - result = -1; - *val_len = sizeof(int); - return (u_char *)&result; - break; - case IPFORWARDMETRIC1: - result = 0; - *val_len = sizeof(int); - return (u_char *)&result; - break; - case IPFORWARDMETRIC2: - result = 0; - *val_len = sizeof(int); - return (u_char *)&result; - break; - case IPFORWARDMETRIC3: - result = 0; - *val_len = sizeof(int); - return (u_char *)&result; - break; - case IPFORWARDMETRIC4: - result = 0; - *val_len = sizeof(int); - return (u_char *)&result; - break; - case IPFORWARDMETRIC5: - result = 0; - *val_len = sizeof(int); - return (u_char *)&result; - break; - default: - return NULL; - break; - } - return NULL; + struct route_node *np; + struct route_entry *re; + static int result; + static int resarr[2]; + static struct in_addr netmask; + struct nexthop *nexthop; + + if (smux_header_table(v, objid, objid_len, exact, val_len, write_method) + == MATCH_FAILED) + return NULL; + + get_fwtable_route_node(v, objid, objid_len, exact, &np, &re); + if (!np) + return NULL; + + nexthop = re->nexthop; + if (!nexthop) + return NULL; + + switch (v->magic) { + case IPFORWARDDEST: + *val_len = 4; + return &np->p.u.prefix; + break; + case IPFORWARDMASK: + masklen2ip(np->p.prefixlen, &netmask); + *val_len = 4; + return (u_char *)&netmask; + break; + case IPFORWARDPOLICY: + result = 0; + *val_len = sizeof(int); + return (u_char *)&result; + break; + case IPFORWARDNEXTHOP: + *val_len = 4; + return (u_char *)&nexthop->gate.ipv4; + break; + case IPFORWARDIFINDEX: + *val_len = sizeof(int); + return (u_char *)&nexthop->ifindex; + break; + case IPFORWARDTYPE: + if (nexthop->type == NEXTHOP_TYPE_IFINDEX) + result = 3; + else + result = 4; + *val_len = sizeof(int); + return (u_char *)&result; + break; + case IPFORWARDPROTO: + result = proto_trans(re->type); + *val_len = sizeof(int); + return (u_char *)&result; + break; + case IPFORWARDAGE: + result = 0; + *val_len = sizeof(int); + return (u_char *)&result; + break; + case IPFORWARDINFO: + resarr[0] = 0; + resarr[1] = 0; + *val_len = 2 * sizeof(int); + return (u_char *)resarr; + break; + case IPFORWARDNEXTHOPAS: + result = -1; + *val_len = sizeof(int); + return (u_char *)&result; + break; + case IPFORWARDMETRIC1: + result = 0; + *val_len = sizeof(int); + return (u_char *)&result; + break; + case IPFORWARDMETRIC2: + result = 0; + *val_len = sizeof(int); + return (u_char *)&result; + break; + case IPFORWARDMETRIC3: + result = 0; + *val_len = sizeof(int); + return (u_char *)&result; + break; + case IPFORWARDMETRIC4: + result = 0; + *val_len = sizeof(int); + return (u_char *)&result; + break; + case IPFORWARDMETRIC5: + result = 0; + *val_len = sizeof(int); + return (u_char *)&result; + break; + default: + return NULL; + break; + } + return NULL; } -static u_char * -ipCidrTable (struct variable *v, oid objid[], size_t *objid_len, - int exact, size_t *val_len, WriteMethod **write_method) +static u_char *ipCidrTable(struct variable *v, oid objid[], size_t *objid_len, + int exact, size_t *val_len, + WriteMethod **write_method) { - if (smux_header_table(v, objid, objid_len, exact, val_len, write_method) - == MATCH_FAILED) - return NULL; - - switch (v->magic) - { - case IPCIDRROUTEDEST: - break; - default: - return NULL; - break; - } - return NULL; + if (smux_header_table(v, objid, objid_len, exact, val_len, write_method) + == MATCH_FAILED) + return NULL; + + switch (v->magic) { + case IPCIDRROUTEDEST: + break; + default: + return NULL; + break; + } + return NULL; } -static int -zebra_snmp_init (struct thread_master *tm) +static int zebra_snmp_init(struct thread_master *tm) { - smux_init (tm); - REGISTER_MIB("mibII/ipforward", zebra_variables, variable, ipfw_oid); - return 0; + smux_init(tm); + REGISTER_MIB("mibII/ipforward", zebra_variables, variable, ipfw_oid); + return 0; } -static int -zebra_snmp_module_init (void) +static int zebra_snmp_module_init(void) { - hook_register(frr_late_init, zebra_snmp_init); - return 0; + hook_register(frr_late_init, zebra_snmp_init); + return 0; } -FRR_MODULE_SETUP( - .name = "zebra_snmp", - .version = FRR_VERSION, - .description = "zebra AgentX SNMP module", - .init = zebra_snmp_module_init, -) +FRR_MODULE_SETUP(.name = "zebra_snmp", .version = FRR_VERSION, + .description = "zebra AgentX SNMP module", + .init = zebra_snmp_module_init, ) diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c index 05336ca6b..ae3239516 100644 --- a/zebra/zebra_static.c +++ b/zebra/zebra_static.c @@ -36,484 +36,486 @@ #include "zebra/zebra_memory.h" /* Install static route into rib. */ -void -static_install_route (afi_t afi, safi_t safi, struct prefix *p, - struct prefix_ipv6 *src_p, struct static_route *si) +void static_install_route(afi_t afi, safi_t safi, struct prefix *p, + struct prefix_ipv6 *src_p, struct static_route *si) { - struct route_entry *re; - struct route_node *rn; - struct route_table *table; - struct prefix nh_p; - struct nexthop *nexthop = NULL; - - /* Lookup table. */ - table = zebra_vrf_table (afi, safi, si->vrf_id); - if (! table) - return; - - memset (&nh_p, 0, sizeof (nh_p)); - - /* Lookup existing route */ - rn = srcdest_rnode_get (table, p, src_p); - RNODE_FOREACH_RE (rn, re) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - - if (re->type == ZEBRA_ROUTE_STATIC && re->distance == si->distance) - break; - } - - if (re) - { - /* if tag value changed , update old value in RIB */ - if (re->tag != si->tag) - re->tag = si->tag; - - /* Same distance static route is there. Update it with new - nexthop. */ - route_unlock_node (rn); - switch (si->type) - { - case STATIC_IPV4_GATEWAY: - nexthop = route_entry_nexthop_ipv4_add (re, &si->addr.ipv4, NULL); - nh_p.family = AF_INET; - nh_p.prefixlen = IPV4_MAX_BITLEN; - nh_p.u.prefix4 = si->addr.ipv4; - zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); - break; - case STATIC_IFINDEX: - nexthop = route_entry_nexthop_ifindex_add (re, si->ifindex); - break; - case STATIC_BLACKHOLE: - nexthop = route_entry_nexthop_blackhole_add (re); - break; - case STATIC_IPV6_GATEWAY: - nexthop = route_entry_nexthop_ipv6_add (re, &si->addr.ipv6); - nh_p.family = AF_INET6; - nh_p.prefixlen = IPV6_MAX_BITLEN; - nh_p.u.prefix6 = si->addr.ipv6; - zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); - break; - case STATIC_IPV6_GATEWAY_IFINDEX: - nexthop = route_entry_nexthop_ipv6_ifindex_add (re, &si->addr.ipv6, - si->ifindex); - break; - } - /* Update label(s), if present. */ - if (si->snh_label.num_labels) - nexthop_add_labels (nexthop, ZEBRA_LSP_STATIC, si->snh_label.num_labels, - &si->snh_label.label[0]); - - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[INET6_ADDRSTRLEN]; - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Modifying route rn %p, re %p (type %d)", - si->vrf_id, buf, p->prefixlen, rn, re, re->type); - } - } - /* Schedule route for processing or invoke NHT, as appropriate. */ - if (si->type == STATIC_IPV4_GATEWAY || - si->type == STATIC_IPV6_GATEWAY) - zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, RNH_NEXTHOP_TYPE, &nh_p); - else - rib_queue_add (rn); - } - else - { - /* This is new static route. */ - re = XCALLOC (MTYPE_RE, sizeof (struct route_entry)); - - re->type = ZEBRA_ROUTE_STATIC; - re->instance = 0; - re->distance = si->distance; - re->metric = 0; - re->mtu = 0; - re->vrf_id = si->vrf_id; - re->table = si->vrf_id ? (zebra_vrf_lookup_by_id(si->vrf_id))->table_id : zebrad.rtm_table_default; - re->nexthop_num = 0; - re->tag = si->tag; - - switch (si->type) - { - case STATIC_IPV4_GATEWAY: - nexthop = route_entry_nexthop_ipv4_add (re, &si->addr.ipv4, NULL); - nh_p.family = AF_INET; - nh_p.prefixlen = IPV4_MAX_BITLEN; - nh_p.u.prefix4 = si->addr.ipv4; - zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); - break; - case STATIC_IFINDEX: - nexthop = route_entry_nexthop_ifindex_add (re, si->ifindex); - break; - case STATIC_BLACKHOLE: - nexthop = route_entry_nexthop_blackhole_add (re); - break; - case STATIC_IPV6_GATEWAY: - nexthop = route_entry_nexthop_ipv6_add (re, &si->addr.ipv6); - nh_p.family = AF_INET6; - nh_p.prefixlen = IPV6_MAX_BITLEN; - nh_p.u.prefix6 = si->addr.ipv6; - zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); - break; - case STATIC_IPV6_GATEWAY_IFINDEX: - nexthop = route_entry_nexthop_ipv6_ifindex_add (re, &si->addr.ipv6, - si->ifindex); - break; - } - /* Update label(s), if present. */ - if (si->snh_label.num_labels) - nexthop_add_labels (nexthop, ZEBRA_LSP_STATIC, si->snh_label.num_labels, - &si->snh_label.label[0]); - - /* Save the flags of this static routes (reject, blackhole) */ - re->flags = si->flags; - - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[INET6_ADDRSTRLEN]; - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Inserting route rn %p, re %p (type %d)", - si->vrf_id, buf, p->prefixlen, rn, re, re->type); - } - } - /* Link this re to the tree. Schedule for processing or invoke NHT, - * as appropriate. - */ - if (si->type == STATIC_IPV4_GATEWAY || - si->type == STATIC_IPV6_GATEWAY) - { - rib_addnode (rn, re, 0); - zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, RNH_NEXTHOP_TYPE, &nh_p); - } - else - rib_addnode (rn, re, 1); - } + struct route_entry *re; + struct route_node *rn; + struct route_table *table; + struct prefix nh_p; + struct nexthop *nexthop = NULL; + + /* Lookup table. */ + table = zebra_vrf_table(afi, safi, si->vrf_id); + if (!table) + return; + + memset(&nh_p, 0, sizeof(nh_p)); + + /* Lookup existing route */ + rn = srcdest_rnode_get(table, p, src_p); + RNODE_FOREACH_RE(rn, re) + { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + + if (re->type == ZEBRA_ROUTE_STATIC + && re->distance == si->distance) + break; + } + + if (re) { + /* if tag value changed , update old value in RIB */ + if (re->tag != si->tag) + re->tag = si->tag; + + /* Same distance static route is there. Update it with new + nexthop. */ + route_unlock_node(rn); + switch (si->type) { + case STATIC_IPV4_GATEWAY: + nexthop = route_entry_nexthop_ipv4_add( + re, &si->addr.ipv4, NULL); + nh_p.family = AF_INET; + nh_p.prefixlen = IPV4_MAX_BITLEN; + nh_p.u.prefix4 = si->addr.ipv4; + zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); + break; + case STATIC_IFINDEX: + nexthop = route_entry_nexthop_ifindex_add(re, + si->ifindex); + break; + case STATIC_BLACKHOLE: + nexthop = route_entry_nexthop_blackhole_add(re); + break; + case STATIC_IPV6_GATEWAY: + nexthop = route_entry_nexthop_ipv6_add(re, + &si->addr.ipv6); + nh_p.family = AF_INET6; + nh_p.prefixlen = IPV6_MAX_BITLEN; + nh_p.u.prefix6 = si->addr.ipv6; + zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); + break; + case STATIC_IPV6_GATEWAY_IFINDEX: + nexthop = route_entry_nexthop_ipv6_ifindex_add( + re, &si->addr.ipv6, si->ifindex); + break; + } + /* Update label(s), if present. */ + if (si->snh_label.num_labels) + nexthop_add_labels(nexthop, ZEBRA_LSP_STATIC, + si->snh_label.num_labels, + &si->snh_label.label[0]); + + if (IS_ZEBRA_DEBUG_RIB) { + char buf[INET6_ADDRSTRLEN]; + if (IS_ZEBRA_DEBUG_RIB) { + inet_ntop(p->family, &p->u.prefix, buf, + INET6_ADDRSTRLEN); + zlog_debug( + "%u:%s/%d: Modifying route rn %p, re %p (type %d)", + si->vrf_id, buf, p->prefixlen, rn, re, + re->type); + } + } + /* Schedule route for processing or invoke NHT, as appropriate. + */ + if (si->type == STATIC_IPV4_GATEWAY + || si->type == STATIC_IPV6_GATEWAY) + zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, + RNH_NEXTHOP_TYPE, &nh_p); + else + rib_queue_add(rn); + } else { + /* This is new static route. */ + re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); + + re->type = ZEBRA_ROUTE_STATIC; + re->instance = 0; + re->distance = si->distance; + re->metric = 0; + re->mtu = 0; + re->vrf_id = si->vrf_id; + re->table = + si->vrf_id + ? (zebra_vrf_lookup_by_id(si->vrf_id))->table_id + : zebrad.rtm_table_default; + re->nexthop_num = 0; + re->tag = si->tag; + + switch (si->type) { + case STATIC_IPV4_GATEWAY: + nexthop = route_entry_nexthop_ipv4_add( + re, &si->addr.ipv4, NULL); + nh_p.family = AF_INET; + nh_p.prefixlen = IPV4_MAX_BITLEN; + nh_p.u.prefix4 = si->addr.ipv4; + zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); + break; + case STATIC_IFINDEX: + nexthop = route_entry_nexthop_ifindex_add(re, + si->ifindex); + break; + case STATIC_BLACKHOLE: + nexthop = route_entry_nexthop_blackhole_add(re); + break; + case STATIC_IPV6_GATEWAY: + nexthop = route_entry_nexthop_ipv6_add(re, + &si->addr.ipv6); + nh_p.family = AF_INET6; + nh_p.prefixlen = IPV6_MAX_BITLEN; + nh_p.u.prefix6 = si->addr.ipv6; + zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn); + break; + case STATIC_IPV6_GATEWAY_IFINDEX: + nexthop = route_entry_nexthop_ipv6_ifindex_add( + re, &si->addr.ipv6, si->ifindex); + break; + } + /* Update label(s), if present. */ + if (si->snh_label.num_labels) + nexthop_add_labels(nexthop, ZEBRA_LSP_STATIC, + si->snh_label.num_labels, + &si->snh_label.label[0]); + + /* Save the flags of this static routes (reject, blackhole) */ + re->flags = si->flags; + + if (IS_ZEBRA_DEBUG_RIB) { + char buf[INET6_ADDRSTRLEN]; + if (IS_ZEBRA_DEBUG_RIB) { + inet_ntop(p->family, &p->u.prefix, buf, + INET6_ADDRSTRLEN); + zlog_debug( + "%u:%s/%d: Inserting route rn %p, re %p (type %d)", + si->vrf_id, buf, p->prefixlen, rn, re, + re->type); + } + } + /* Link this re to the tree. Schedule for processing or invoke + * NHT, + * as appropriate. + */ + if (si->type == STATIC_IPV4_GATEWAY + || si->type == STATIC_IPV6_GATEWAY) { + rib_addnode(rn, re, 0); + zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1, + RNH_NEXTHOP_TYPE, &nh_p); + } else + rib_addnode(rn, re, 1); + } } -static int -static_nexthop_same (struct nexthop *nexthop, struct static_route *si) +static int static_nexthop_same(struct nexthop *nexthop, struct static_route *si) { - if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE - && si->type == STATIC_BLACKHOLE) - return 1; - - if (nexthop->type == NEXTHOP_TYPE_IPV4 - && si->type == STATIC_IPV4_GATEWAY - && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->addr.ipv4)) - return 1; - else if (nexthop->type == NEXTHOP_TYPE_IFINDEX - && si->type == STATIC_IFINDEX - && nexthop->ifindex == si->ifindex) - return 1; - else if (nexthop->type == NEXTHOP_TYPE_IPV6 - && si->type == STATIC_IPV6_GATEWAY - && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6)) - return 1; - else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX - && si->type == STATIC_IPV6_GATEWAY_IFINDEX - && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->addr.ipv6) - && nexthop->ifindex == si->ifindex) - return 1; - - return 0; + if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE + && si->type == STATIC_BLACKHOLE) + return 1; + + if (nexthop->type == NEXTHOP_TYPE_IPV4 + && si->type == STATIC_IPV4_GATEWAY + && IPV4_ADDR_SAME(&nexthop->gate.ipv4, &si->addr.ipv4)) + return 1; + else if (nexthop->type == NEXTHOP_TYPE_IFINDEX + && si->type == STATIC_IFINDEX + && nexthop->ifindex == si->ifindex) + return 1; + else if (nexthop->type == NEXTHOP_TYPE_IPV6 + && si->type == STATIC_IPV6_GATEWAY + && IPV6_ADDR_SAME(&nexthop->gate.ipv6, &si->addr.ipv6)) + return 1; + else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX + && si->type == STATIC_IPV6_GATEWAY_IFINDEX + && IPV6_ADDR_SAME(&nexthop->gate.ipv6, &si->addr.ipv6) + && nexthop->ifindex == si->ifindex) + return 1; + + return 0; } /* Uninstall static route from RIB. */ -void -static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, - struct prefix_ipv6 *src_p, struct static_route *si) +void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p, + struct prefix_ipv6 *src_p, struct static_route *si) { - struct route_node *rn; - struct route_entry *re; - struct nexthop *nexthop; - struct route_table *table; - struct prefix nh_p; - - /* Lookup table. */ - table = zebra_vrf_table (afi, safi, si->vrf_id); - if (! table) - return; - - /* Lookup existing route with type and distance. */ - rn = srcdest_rnode_lookup (table, p, src_p); - if (! rn) - return; - - RNODE_FOREACH_RE (rn, re) - { - if (CHECK_FLAG (re->status, ROUTE_ENTRY_REMOVED)) - continue; - - if (re->type == ZEBRA_ROUTE_STATIC && re->distance == si->distance && - re->tag == si->tag) - break; - } - - if (! re) - { - route_unlock_node (rn); - return; - } - - /* Lookup nexthop. */ - for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) - if (static_nexthop_same (nexthop, si)) - break; - - /* Can't find nexthop. */ - if (! nexthop) - { - route_unlock_node (rn); - return; - } - - /* Check nexthop. */ - if (re->nexthop_num == 1) - rib_delnode (rn, re); - else - { - /* Mark this nexthop as inactive and reinstall the route. Then, delete - * the nexthop. There is no need to re-evaluate the route for this - * scenario. - */ - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[INET6_ADDRSTRLEN]; - if (IS_ZEBRA_DEBUG_RIB) - { - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%u:%s/%d: Modifying route rn %p, re %p (type %d)", - si->vrf_id, buf, p->prefixlen, rn, re, re->type); - } - } - UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - { - /* If there are other active nexthops, do an update. */ - if (re->nexthop_active_num > 1) - { - /* Update route in kernel if it's in fib */ - if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) - rib_install_kernel (rn, re, re); - /* Update redistribution if it's selected */ - if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) - redistribute_update (p, (struct prefix*)src_p, re, NULL); - } - else - { - /* Remove from redistribute if selected route becomes inactive */ - if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) - redistribute_delete (p, (struct prefix*)src_p, re); - /* Remove from kernel if fib route becomes inactive */ - if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) - rib_uninstall_kernel (rn, re); - } - } - - if (afi == AFI_IP) + struct route_node *rn; + struct route_entry *re; + struct nexthop *nexthop; + struct route_table *table; + struct prefix nh_p; + + /* Lookup table. */ + table = zebra_vrf_table(afi, safi, si->vrf_id); + if (!table) + return; + + /* Lookup existing route with type and distance. */ + rn = srcdest_rnode_lookup(table, p, src_p); + if (!rn) + return; + + RNODE_FOREACH_RE(rn, re) { - /* Delete the nexthop and dereg from NHT */ - nh_p.family = AF_INET; - nh_p.prefixlen = IPV4_MAX_BITLEN; - nh_p.u.prefix4 = nexthop->gate.ipv4; + if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) + continue; + + if (re->type == ZEBRA_ROUTE_STATIC + && re->distance == si->distance && re->tag == si->tag) + break; } - else - { - nh_p.family = AF_INET6; - nh_p.prefixlen = IPV6_MAX_BITLEN; - nh_p.u.prefix6 = nexthop->gate.ipv6; + + if (!re) { + route_unlock_node(rn); + return; } - route_entry_nexthop_delete (re, nexthop); - zebra_deregister_rnh_static_nh(si->vrf_id, &nh_p, rn); - nexthop_free (nexthop); - } - /* Unlock node. */ - route_unlock_node (rn); -} -int -static_add_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, - struct prefix_ipv6 *src_p, - union g_addr *gate, ifindex_t ifindex, - const char *ifname, u_char flags, route_tag_t tag, - u_char distance, struct zebra_vrf *zvrf, - struct static_nh_label *snh_label) -{ - struct route_node *rn; - struct static_route *si; - struct static_route *pp; - struct static_route *cp; - struct static_route *update = NULL; - struct route_table *stable = zvrf->stable[afi][safi]; - - if (! stable) - return -1; - - if (!gate && - (type == STATIC_IPV4_GATEWAY || - type == STATIC_IPV6_GATEWAY || - type == STATIC_IPV6_GATEWAY_IFINDEX)) - return -1; - - if (!ifindex && - (type == STATIC_IFINDEX || - type == STATIC_IPV6_GATEWAY_IFINDEX)) - return -1; - - /* Lookup static route prefix. */ - rn = srcdest_rnode_get (stable, p, src_p); - - /* Do nothing if there is a same static route. */ - for (si = rn->info; si; si = si->next) - { - if (type == si->type - && (! gate || - ((afi == AFI_IP && IPV4_ADDR_SAME (gate, &si->addr.ipv4)) || - (afi == AFI_IP6 && IPV6_ADDR_SAME (gate, &si->addr.ipv6)))) - && (! ifindex || ifindex == si->ifindex)) - { - if ((distance == si->distance) && (tag == si->tag) && - !memcmp (&si->snh_label, snh_label, sizeof (struct static_nh_label)) && - si->flags == flags) - { - route_unlock_node (rn); - return 0; - } - else - update = si; + /* Lookup nexthop. */ + for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next) + if (static_nexthop_same(nexthop, si)) + break; + + /* Can't find nexthop. */ + if (!nexthop) { + route_unlock_node(rn); + return; } - } - - /* Distance or tag or label changed, delete existing first. */ - if (update) - static_delete_route (afi, safi, type, p, src_p, gate, ifindex, update->tag, - update->distance, zvrf, &update->snh_label); - - /* Make new static route structure. */ - si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route)); - - si->type = type; - si->distance = distance; - si->flags = flags; - si->tag = tag; - si->vrf_id = zvrf_id (zvrf); - si->ifindex = ifindex; - if (si->ifindex) - strcpy(si->ifname, ifname); - - switch (type) - { - case STATIC_IPV4_GATEWAY: - si->addr.ipv4 = gate->ipv4; - break; - case STATIC_IPV6_GATEWAY: - si->addr.ipv6 = gate->ipv6; - break; - case STATIC_IPV6_GATEWAY_IFINDEX: - si->addr.ipv6 = gate->ipv6; - break; - case STATIC_IFINDEX: - break; - } - - /* Save labels, if any. */ - memcpy (&si->snh_label, snh_label, sizeof (struct static_nh_label)); - - /* Add new static route information to the tree with sort by - distance value and gateway address. */ - for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) - { - if (si->distance < cp->distance) - break; - if (si->distance > cp->distance) - continue; - if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY) - { - if (ntohl (si->addr.ipv4.s_addr) < ntohl (cp->addr.ipv4.s_addr)) - break; - if (ntohl (si->addr.ipv4.s_addr) > ntohl (cp->addr.ipv4.s_addr)) - continue; + + /* Check nexthop. */ + if (re->nexthop_num == 1) + rib_delnode(rn, re); + else { + /* Mark this nexthop as inactive and reinstall the route. Then, + * delete + * the nexthop. There is no need to re-evaluate the route for + * this + * scenario. + */ + if (IS_ZEBRA_DEBUG_RIB) { + char buf[INET6_ADDRSTRLEN]; + if (IS_ZEBRA_DEBUG_RIB) { + inet_ntop(p->family, &p->u.prefix, buf, + INET6_ADDRSTRLEN); + zlog_debug( + "%u:%s/%d: Modifying route rn %p, re %p (type %d)", + si->vrf_id, buf, p->prefixlen, rn, re, + re->type); + } + } + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) { + /* If there are other active nexthops, do an update. */ + if (re->nexthop_active_num > 1) { + /* Update route in kernel if it's in fib */ + if (CHECK_FLAG(re->status, + ROUTE_ENTRY_SELECTED_FIB)) + rib_install_kernel(rn, re, re); + /* Update redistribution if it's selected */ + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) + redistribute_update( + p, (struct prefix *)src_p, re, + NULL); + } else { + /* Remove from redistribute if selected route + * becomes inactive */ + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) + redistribute_delete( + p, (struct prefix *)src_p, re); + /* Remove from kernel if fib route becomes + * inactive */ + if (CHECK_FLAG(re->status, + ROUTE_ENTRY_SELECTED_FIB)) + rib_uninstall_kernel(rn, re); + } + } + + if (afi == AFI_IP) { + /* Delete the nexthop and dereg from NHT */ + nh_p.family = AF_INET; + nh_p.prefixlen = IPV4_MAX_BITLEN; + nh_p.u.prefix4 = nexthop->gate.ipv4; + } else { + nh_p.family = AF_INET6; + nh_p.prefixlen = IPV6_MAX_BITLEN; + nh_p.u.prefix6 = nexthop->gate.ipv6; + } + route_entry_nexthop_delete(re, nexthop); + zebra_deregister_rnh_static_nh(si->vrf_id, &nh_p, rn); + nexthop_free(nexthop); } - } - - /* Make linked list. */ - if (pp) - pp->next = si; - else - rn->info = si; - if (cp) - cp->prev = si; - si->prev = pp; - si->next = cp; - - /* Install into rib. */ - static_install_route (afi, safi, p, src_p, si); - - return 1; + /* Unlock node. */ + route_unlock_node(rn); } -int -static_delete_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, - struct prefix_ipv6 *src_p, - union g_addr *gate, ifindex_t ifindex, +int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p, + struct prefix_ipv6 *src_p, union g_addr *gate, + ifindex_t ifindex, const char *ifname, u_char flags, route_tag_t tag, u_char distance, struct zebra_vrf *zvrf, struct static_nh_label *snh_label) { - struct route_node *rn; - struct static_route *si; - struct route_table *stable; - - /* Lookup table. */ - stable = zebra_vrf_static_table (afi, safi, zvrf); - if (! stable) - return -1; - - /* Lookup static route prefix. */ - rn = srcdest_rnode_lookup (stable, p, src_p); - if (! rn) - return 0; - - /* Find same static route is the tree */ - for (si = rn->info; si; si = si->next) - if (type == si->type - && (! gate || ( - (afi == AFI_IP && IPV4_ADDR_SAME (gate, &si->addr.ipv4)) || - (afi == AFI_IP6 && IPV6_ADDR_SAME (gate, &si->addr.ipv6)))) - && (! ifindex || ifindex == si->ifindex) - && (! tag || (tag == si->tag)) - && (! snh_label->num_labels || - !memcmp (&si->snh_label, snh_label, sizeof (struct static_nh_label)))) - break; - - /* Can't find static route. */ - if (! si) - { - route_unlock_node (rn); - return 0; - } - - /* Install into rib. */ - static_uninstall_route (afi, safi, p, src_p, si); - - /* Unlink static route from linked list. */ - if (si->prev) - si->prev->next = si->next; - else - rn->info = si->next; - if (si->next) - si->next->prev = si->prev; - route_unlock_node (rn); - - /* Free static route configuration. */ - XFREE (MTYPE_STATIC_ROUTE, si); - - route_unlock_node (rn); - - return 1; + struct route_node *rn; + struct static_route *si; + struct static_route *pp; + struct static_route *cp; + struct static_route *update = NULL; + struct route_table *stable = zvrf->stable[afi][safi]; + + if (!stable) + return -1; + + if (!gate && (type == STATIC_IPV4_GATEWAY || type == STATIC_IPV6_GATEWAY + || type == STATIC_IPV6_GATEWAY_IFINDEX)) + return -1; + + if (!ifindex + && (type == STATIC_IFINDEX || type == STATIC_IPV6_GATEWAY_IFINDEX)) + return -1; + + /* Lookup static route prefix. */ + rn = srcdest_rnode_get(stable, p, src_p); + + /* Do nothing if there is a same static route. */ + for (si = rn->info; si; si = si->next) { + if (type == si->type + && (!gate || ((afi == AFI_IP + && IPV4_ADDR_SAME(gate, &si->addr.ipv4)) + || (afi == AFI_IP6 + && IPV6_ADDR_SAME(gate, &si->addr.ipv6)))) + && (!ifindex || ifindex == si->ifindex)) { + if ((distance == si->distance) && (tag == si->tag) + && !memcmp(&si->snh_label, snh_label, + sizeof(struct static_nh_label)) + && si->flags == flags) { + route_unlock_node(rn); + return 0; + } else + update = si; + } + } + + /* Distance or tag or label changed, delete existing first. */ + if (update) + static_delete_route(afi, safi, type, p, src_p, gate, ifindex, + update->tag, update->distance, zvrf, + &update->snh_label); + + /* Make new static route structure. */ + si = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(struct static_route)); + + si->type = type; + si->distance = distance; + si->flags = flags; + si->tag = tag; + si->vrf_id = zvrf_id(zvrf); + si->ifindex = ifindex; + if (si->ifindex) + strcpy(si->ifname, ifname); + + switch (type) { + case STATIC_IPV4_GATEWAY: + si->addr.ipv4 = gate->ipv4; + break; + case STATIC_IPV6_GATEWAY: + si->addr.ipv6 = gate->ipv6; + break; + case STATIC_IPV6_GATEWAY_IFINDEX: + si->addr.ipv6 = gate->ipv6; + break; + case STATIC_IFINDEX: + break; + } + + /* Save labels, if any. */ + memcpy(&si->snh_label, snh_label, sizeof(struct static_nh_label)); + + /* Add new static route information to the tree with sort by + distance value and gateway address. */ + for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next) { + if (si->distance < cp->distance) + break; + if (si->distance > cp->distance) + continue; + if (si->type == STATIC_IPV4_GATEWAY + && cp->type == STATIC_IPV4_GATEWAY) { + if (ntohl(si->addr.ipv4.s_addr) + < ntohl(cp->addr.ipv4.s_addr)) + break; + if (ntohl(si->addr.ipv4.s_addr) + > ntohl(cp->addr.ipv4.s_addr)) + continue; + } + } + + /* Make linked list. */ + if (pp) + pp->next = si; + else + rn->info = si; + if (cp) + cp->prev = si; + si->prev = pp; + si->next = cp; + + /* Install into rib. */ + static_install_route(afi, safi, p, src_p, si); + + return 1; +} + +int static_delete_route(afi_t afi, safi_t safi, u_char type, struct prefix *p, + struct prefix_ipv6 *src_p, union g_addr *gate, + ifindex_t ifindex, route_tag_t tag, u_char distance, + struct zebra_vrf *zvrf, + struct static_nh_label *snh_label) +{ + struct route_node *rn; + struct static_route *si; + struct route_table *stable; + + /* Lookup table. */ + stable = zebra_vrf_static_table(afi, safi, zvrf); + if (!stable) + return -1; + + /* Lookup static route prefix. */ + rn = srcdest_rnode_lookup(stable, p, src_p); + if (!rn) + return 0; + + /* Find same static route is the tree */ + for (si = rn->info; si; si = si->next) + if (type == si->type + && (!gate || ((afi == AFI_IP + && IPV4_ADDR_SAME(gate, &si->addr.ipv4)) + || (afi == AFI_IP6 + && IPV6_ADDR_SAME(gate, &si->addr.ipv6)))) + && (!ifindex || ifindex == si->ifindex) + && (!tag || (tag == si->tag)) + && (!snh_label->num_labels + || !memcmp(&si->snh_label, snh_label, + sizeof(struct static_nh_label)))) + break; + + /* Can't find static route. */ + if (!si) { + route_unlock_node(rn); + return 0; + } + + /* Install into rib. */ + static_uninstall_route(afi, safi, p, src_p, si); + + /* Unlink static route from linked list. */ + if (si->prev) + si->prev->next = si->next; + else + rn->info = si->next; + if (si->next) + si->next->prev = si->prev; + route_unlock_node(rn); + + /* Free static route configuration. */ + XFREE(MTYPE_STATIC_ROUTE, si); + + route_unlock_node(rn); + + return 1; } diff --git a/zebra/zebra_static.h b/zebra/zebra_static.h index 9f76ab5f5..91ac0a33c 100644 --- a/zebra/zebra_static.h +++ b/zebra/zebra_static.h @@ -23,99 +23,93 @@ #define __ZEBRA_STATIC_H__ /* Static route label information */ -struct static_nh_label -{ - u_int8_t num_labels; - u_int8_t reserved[3]; - mpls_label_t label[2]; +struct static_nh_label { + u_int8_t num_labels; + u_int8_t reserved[3]; + mpls_label_t label[2]; }; typedef enum { - STATIC_IFINDEX, - STATIC_IPV4_GATEWAY, - STATIC_BLACKHOLE, - STATIC_IPV6_GATEWAY, - STATIC_IPV6_GATEWAY_IFINDEX, + STATIC_IFINDEX, + STATIC_IPV4_GATEWAY, + STATIC_BLACKHOLE, + STATIC_IPV6_GATEWAY, + STATIC_IPV6_GATEWAY_IFINDEX, } zebra_static_types; /* Static route information. */ -struct static_route -{ - /* For linked list. */ - struct static_route *prev; - struct static_route *next; - - /* VRF identifier. */ - vrf_id_t vrf_id; - - /* Administrative distance. */ - u_char distance; - - /* Tag */ - route_tag_t tag; - - /* Flag for this static route's type. */ - zebra_static_types type; - - /* - * Nexthop value. - * - * Under IPv4 addr and ifindex are - * used independentyly. - * STATIC_IPV4_GATEWAY uses addr - * STATIC_IFINDEX uses ifindex - */ - union g_addr addr; - ifindex_t ifindex; - - char ifname[INTERFACE_NAMSIZ + 1]; - - /* bit flags */ - u_char flags; -/* - see ZEBRA_FLAG_REJECT - ZEBRA_FLAG_BLACKHOLE - */ - - /* Label information */ - struct static_nh_label snh_label; +struct static_route { + /* For linked list. */ + struct static_route *prev; + struct static_route *next; + + /* VRF identifier. */ + vrf_id_t vrf_id; + + /* Administrative distance. */ + u_char distance; + + /* Tag */ + route_tag_t tag; + + /* Flag for this static route's type. */ + zebra_static_types type; + + /* + * Nexthop value. + * + * Under IPv4 addr and ifindex are + * used independentyly. + * STATIC_IPV4_GATEWAY uses addr + * STATIC_IFINDEX uses ifindex + */ + union g_addr addr; + ifindex_t ifindex; + + char ifname[INTERFACE_NAMSIZ + 1]; + + /* bit flags */ + u_char flags; + /* + see ZEBRA_FLAG_REJECT + ZEBRA_FLAG_BLACKHOLE + */ + + /* Label information */ + struct static_nh_label snh_label; }; -extern void -static_install_route (afi_t afi, safi_t safi, struct prefix *p, - struct prefix_ipv6 *src_p, struct static_route *si); -extern void -static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, - struct prefix_ipv6 *src_p, struct static_route *si); - -extern int -static_add_route (afi_t, safi_t safi, u_char type, struct prefix *p, - struct prefix_ipv6 *src_p, - union g_addr *gate, ifindex_t ifindex, - const char *ifname, u_char flags, route_tag_t tag, - u_char distance, struct zebra_vrf *zvrf, - struct static_nh_label *snh_label); - -extern int -static_delete_route (afi_t, safi_t safi, u_char type, struct prefix *p, - struct prefix_ipv6 *src_p, - union g_addr *gate, ifindex_t ifindex, route_tag_t tag, - u_char distance, struct zebra_vrf *zvrf, - struct static_nh_label *snh_label); - -int -zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, - const char *dest_str, const char *mask_str, - const char *gate_str, const char *flag_str, - const char *tag_str, const char *distance_str, - const char *vrf_id_str, const char *label_str); - -int -static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, - const char *src_str, - const char *gate_str, const char *ifname, - const char *flag_str, const char *tag_str, - const char *distance_str, const char *vrf_id_str, - const char *label_str); +extern void static_install_route(afi_t afi, safi_t safi, struct prefix *p, + struct prefix_ipv6 *src_p, + struct static_route *si); +extern void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p, + struct prefix_ipv6 *src_p, + struct static_route *si); + +extern int static_add_route(afi_t, safi_t safi, u_char type, struct prefix *p, + struct prefix_ipv6 *src_p, union g_addr *gate, + ifindex_t ifindex, const char *ifname, u_char flags, + route_tag_t tag, u_char distance, + struct zebra_vrf *zvrf, + struct static_nh_label *snh_label); + +extern int static_delete_route(afi_t, safi_t safi, u_char type, + struct prefix *p, struct prefix_ipv6 *src_p, + union g_addr *gate, ifindex_t ifindex, + route_tag_t tag, u_char distance, + struct zebra_vrf *zvrf, + struct static_nh_label *snh_label); + +int zebra_static_ipv4(struct vty *vty, safi_t safi, int add_cmd, + const char *dest_str, const char *mask_str, + const char *gate_str, const char *flag_str, + const char *tag_str, const char *distance_str, + const char *vrf_id_str, const char *label_str); + +int static_ipv6_func(struct vty *vty, int add_cmd, const char *dest_str, + const char *src_str, const char *gate_str, + const char *ifname, const char *flag_str, + const char *tag_str, const char *distance_str, + const char *vrf_id_str, const char *label_str); #endif diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index b5d6f8c06..feca13d3a 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -42,60 +42,57 @@ extern struct zebra_t zebrad; /* VRF information update. */ -static void -zebra_vrf_add_update (struct zebra_vrf *zvrf) +static void zebra_vrf_add_update(struct zebra_vrf *zvrf) { - struct listnode *node, *nnode; - struct zserv *client; + struct listnode *node, *nnode; + struct zserv *client; - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("MESSAGE: ZEBRA_VRF_ADD %s", zvrf_name (zvrf)); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("MESSAGE: ZEBRA_VRF_ADD %s", zvrf_name(zvrf)); - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - zsend_vrf_add (client, zvrf); + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) + zsend_vrf_add(client, zvrf); } -static void -zebra_vrf_delete_update (struct zebra_vrf *zvrf) +static void zebra_vrf_delete_update(struct zebra_vrf *zvrf) { - struct listnode *node, *nnode; - struct zserv *client; + struct listnode *node, *nnode; + struct zserv *client; - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("MESSAGE: ZEBRA_VRF_DELETE %s", zvrf_name (zvrf)); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("MESSAGE: ZEBRA_VRF_DELETE %s", zvrf_name(zvrf)); - for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) - zsend_vrf_delete (client, zvrf); + for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) + zsend_vrf_delete(client, zvrf); } -void -zebra_vrf_update_all (struct zserv *client) +void zebra_vrf_update_all(struct zserv *client) { - struct vrf *vrf; + struct vrf *vrf; - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - { - if (vrf->vrf_id) - zsend_vrf_add (client, vrf_info_lookup (vrf->vrf_id)); - } + RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) + { + if (vrf->vrf_id) + zsend_vrf_add(client, vrf_info_lookup(vrf->vrf_id)); + } } /* Callback upon creating a new VRF. */ -static int -zebra_vrf_new (struct vrf *vrf) +static int zebra_vrf_new(struct vrf *vrf) { - struct zebra_vrf *zvrf; + struct zebra_vrf *zvrf; - if (IS_ZEBRA_DEBUG_EVENT) - zlog_info ("ZVRF %s with id %u", vrf->name, vrf->vrf_id); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_info("ZVRF %s with id %u", vrf->name, vrf->vrf_id); - zvrf = zebra_vrf_alloc (); - zvrf->zns = zebra_ns_lookup (NS_DEFAULT); /* Point to the global (single) NS */ - router_id_init (zvrf); - vrf->info = zvrf; - zvrf->vrf = vrf; + zvrf = zebra_vrf_alloc(); + zvrf->zns = zebra_ns_lookup( + NS_DEFAULT); /* Point to the global (single) NS */ + router_id_init(zvrf); + vrf->info = zvrf; + zvrf->vrf = vrf; - return 0; + return 0; } /* @@ -105,445 +102,430 @@ zebra_vrf_new (struct vrf *vrf) * the old ifindex and replace with new * ifindex to insert back into the table */ -void -zebra_vrf_static_route_interface_fixup (struct interface *ifp) +void zebra_vrf_static_route_interface_fixup(struct interface *ifp) { - afi_t afi; - safi_t safi; - struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id (ifp->vrf_id); - struct route_table *stable = NULL; - struct route_node *rn = NULL; - struct static_route *si = NULL; - - if (!zvrf) - return; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - stable = zvrf->stable[afi][safi]; - if (stable) - for (rn = route_top (stable); rn; rn = route_next (rn)) - { - if (rn->info) - { - si = rn->info; - if ((strcmp (si->ifname, ifp->name) == 0) && - (si->ifindex != ifp->ifindex)) - { - si->ifindex = ifp->ifindex; - static_install_route (afi, safi, &rn->p, NULL, si); - } - } - } + afi_t afi; + safi_t safi; + struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id); + struct route_table *stable = NULL; + struct route_node *rn = NULL; + struct static_route *si = NULL; + + if (!zvrf) + return; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + stable = zvrf->stable[afi][safi]; + if (stable) + for (rn = route_top(stable); rn; + rn = route_next(rn)) { + if (rn->info) { + si = rn->info; + if ((strcmp(si->ifname, + ifp->name) + == 0) + && (si->ifindex + != ifp->ifindex)) { + si->ifindex = + ifp->ifindex; + static_install_route( + afi, safi, + &rn->p, NULL, + si); + } + } + } + } } - } - } /* Callback upon enabling a VRF. */ -static int -zebra_vrf_enable (struct vrf *vrf) +static int zebra_vrf_enable(struct vrf *vrf) { - struct zebra_vrf *zvrf = vrf->info; - struct route_table *stable; - struct route_node *rn; - struct static_route *si; - struct interface *ifp; - afi_t afi; - safi_t safi; - - assert (zvrf); - - zebra_vrf_add_update (zvrf); - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - stable = zvrf->stable[afi][safi]; - if (! stable) - continue; - - for (rn = route_top (stable); rn; rn = route_next (rn)) - for (si = rn->info; si; si = si->next) - { - si->vrf_id = vrf->vrf_id; - if (si->ifindex) - { - ifp = if_lookup_by_name (si->ifname, si->vrf_id); - if (ifp) - si->ifindex = ifp->ifindex; - else - continue; + struct zebra_vrf *zvrf = vrf->info; + struct route_table *stable; + struct route_node *rn; + struct static_route *si; + struct interface *ifp; + afi_t afi; + safi_t safi; + + assert(zvrf); + + zebra_vrf_add_update(zvrf); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + stable = zvrf->stable[afi][safi]; + if (!stable) + continue; + + for (rn = route_top(stable); rn; rn = route_next(rn)) + for (si = rn->info; si; si = si->next) { + si->vrf_id = vrf->vrf_id; + if (si->ifindex) { + ifp = if_lookup_by_name( + si->ifname, si->vrf_id); + if (ifp) + si->ifindex = + ifp->ifindex; + else + continue; + } + static_install_route(afi, safi, &rn->p, + NULL, si); + } } - static_install_route (afi, safi, &rn->p, NULL, si); - } - } - return 0; + return 0; } /* Callback upon disabling a VRF. */ -static int -zebra_vrf_disable (struct vrf *vrf) +static int zebra_vrf_disable(struct vrf *vrf) { - struct zebra_vrf *zvrf = vrf->info; - struct route_table *stable; - struct route_node *rn; - struct static_route *si; - afi_t afi; - safi_t safi; - - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("VRF %s id %u is now disabled.", - zvrf_name (zvrf), zvrf_id (zvrf)); - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) - { - stable = zvrf->stable[afi][safi]; - if (! stable) - continue; - - for (rn = route_top (stable); rn; rn = route_next (rn)) - for (si = rn->info; si; si = si->next) - static_uninstall_route(afi, safi, &rn->p, NULL, si); - } - - return 0; + struct zebra_vrf *zvrf = vrf->info; + struct route_table *stable; + struct route_node *rn; + struct static_route *si; + afi_t afi; + safi_t safi; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("VRF %s id %u is now disabled.", zvrf_name(zvrf), + zvrf_id(zvrf)); + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + stable = zvrf->stable[afi][safi]; + if (!stable) + continue; + + for (rn = route_top(stable); rn; rn = route_next(rn)) + for (si = rn->info; si; si = si->next) + static_uninstall_route( + afi, safi, &rn->p, NULL, si); + } + + return 0; } -static int -zebra_vrf_delete (struct vrf *vrf) +static int zebra_vrf_delete(struct vrf *vrf) { - struct zebra_vrf *zvrf = vrf->info; - struct route_table *table; - u_int32_t table_id; - afi_t afi; - safi_t safi; - unsigned i; - - assert (zvrf); - - zebra_vrf_delete_update (zvrf); + struct zebra_vrf *zvrf = vrf->info; + struct route_table *table; + u_int32_t table_id; + afi_t afi; + safi_t safi; + unsigned i; + + assert(zvrf); + + zebra_vrf_delete_update(zvrf); + + /* uninstall everything */ + if (!CHECK_FLAG(zvrf->flags, ZEBRA_VRF_RETAIN)) { + struct listnode *node; + struct interface *ifp; + + for (afi = AFI_IP; afi <= AFI_IP6; afi++) { + for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; + safi++) + rib_close_table(zvrf->table[afi][safi]); + + if (vrf->vrf_id == VRF_DEFAULT) + for (table_id = 0; + table_id < ZEBRA_KERNEL_TABLE_MAX; + table_id++) + if (zvrf->other_table[afi][table_id]) + rib_close_table( + zvrf->other_table + [afi] + [table_id]); + } - /* uninstall everything */ - if (! CHECK_FLAG (zvrf->flags, ZEBRA_VRF_RETAIN)) - { - struct listnode *node; - struct interface *ifp; + /* Cleanup Vxlan table and update kernel */ + zebra_vxlan_close_tables(zvrf); - for (afi = AFI_IP; afi <= AFI_IP6; afi++) - { - for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) - rib_close_table (zvrf->table[afi][safi]); + zebra_mpls_close_tables(zvrf); - if (vrf->vrf_id == VRF_DEFAULT) - for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; table_id++) - if (zvrf->other_table[afi][table_id]) - rib_close_table (zvrf->other_table[afi][table_id]); + for (ALL_LIST_ELEMENTS_RO(vrf->iflist, node, ifp)) + if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp); } - /* Cleanup Vxlan table and update kernel */ - zebra_vxlan_close_tables (zvrf); - - zebra_mpls_close_tables (zvrf); - - for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp)) - if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp); - } - - /* clean-up work queues */ - for (i = 0; i < MQ_SIZE; i++) - { - struct listnode *lnode, *nnode; - struct route_node *rnode; - rib_dest_t *dest; - - for (ALL_LIST_ELEMENTS (zebrad.mq->subq[i], lnode, nnode, rnode)) - { - dest = rib_dest_from_rnode (rnode); - if (dest && rib_dest_vrf (dest) == zvrf) - { - route_unlock_node (rnode); - list_delete_node (zebrad.mq->subq[i], lnode); - zebrad.mq->size--; - } + /* clean-up work queues */ + for (i = 0; i < MQ_SIZE; i++) { + struct listnode *lnode, *nnode; + struct route_node *rnode; + rib_dest_t *dest; + + for (ALL_LIST_ELEMENTS(zebrad.mq->subq[i], lnode, nnode, + rnode)) { + dest = rib_dest_from_rnode(rnode); + if (dest && rib_dest_vrf(dest) == zvrf) { + route_unlock_node(rnode); + list_delete_node(zebrad.mq->subq[i], lnode); + zebrad.mq->size--; + } + } } - } - /* release allocated memory */ - for (afi = AFI_IP; afi <= AFI_IP6; afi++) - { - void *table_info; + /* release allocated memory */ + for (afi = AFI_IP; afi <= AFI_IP6; afi++) { + void *table_info; - for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) - { - table = zvrf->table[afi][safi]; - table_info = table->info; - route_table_finish (table); - XFREE (MTYPE_RIB_TABLE_INFO, table_info); + for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) { + table = zvrf->table[afi][safi]; + table_info = table->info; + route_table_finish(table); + XFREE(MTYPE_RIB_TABLE_INFO, table_info); + + table = zvrf->stable[afi][safi]; + route_table_finish(table); + } - table = zvrf->stable[afi][safi]; - route_table_finish (table); + for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; + table_id++) + if (zvrf->other_table[afi][table_id]) { + table = zvrf->other_table[afi][table_id]; + table_info = table->info; + route_table_finish(table); + XFREE(MTYPE_RIB_TABLE_INFO, table_info); + } + + route_table_finish(zvrf->rnh_table[afi]); + route_table_finish(zvrf->import_check_table[afi]); } + list_delete_all_node(zvrf->rid_all_sorted_list); + list_delete_all_node(zvrf->rid_lo_sorted_list); + XFREE(MTYPE_ZEBRA_VRF, zvrf); + vrf->info = NULL; - for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; table_id++) - if (zvrf->other_table[afi][table_id]) - { - table = zvrf->other_table[afi][table_id]; - table_info = table->info; - route_table_finish (table); - XFREE (MTYPE_RIB_TABLE_INFO, table_info); - } - - route_table_finish (zvrf->rnh_table[afi]); - route_table_finish (zvrf->import_check_table[afi]); - } - list_delete_all_node (zvrf->rid_all_sorted_list); - list_delete_all_node (zvrf->rid_lo_sorted_list); - XFREE (MTYPE_ZEBRA_VRF, zvrf); - vrf->info = NULL; - - return 0; + return 0; } /* Lookup the routing table in a VRF based on both VRF-Id and table-id. * NOTE: Table-id is relevant only in the Default VRF. */ -struct route_table * -zebra_vrf_table_with_table_id (afi_t afi, safi_t safi, - vrf_id_t vrf_id, u_int32_t table_id) +struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi, + vrf_id_t vrf_id, + u_int32_t table_id) { - struct route_table *table = NULL; - - if (afi >= AFI_MAX || safi >= SAFI_MAX) - return NULL; - - if (vrf_id == VRF_DEFAULT) - { - if (table_id == RT_TABLE_MAIN || - table_id == zebrad.rtm_table_default) - table = zebra_vrf_table (afi, safi, vrf_id); - else - table = zebra_vrf_other_route_table (afi, table_id, vrf_id); - } - else - table = zebra_vrf_table (afi, safi, vrf_id); - - return table; + struct route_table *table = NULL; + + if (afi >= AFI_MAX || safi >= SAFI_MAX) + return NULL; + + if (vrf_id == VRF_DEFAULT) { + if (table_id == RT_TABLE_MAIN + || table_id == zebrad.rtm_table_default) + table = zebra_vrf_table(afi, safi, vrf_id); + else + table = zebra_vrf_other_route_table(afi, table_id, + vrf_id); + } else + table = zebra_vrf_table(afi, safi, vrf_id); + + return table; } -static void -zebra_rtable_node_cleanup (struct route_table *table, struct route_node *node) +static void zebra_rtable_node_cleanup(struct route_table *table, + struct route_node *node) { - struct route_entry *re, *next; + struct route_entry *re, *next; - RNODE_FOREACH_RE_SAFE (node, re, next) - rib_unlink (node, re); + RNODE_FOREACH_RE_SAFE(node, re, next) + rib_unlink(node, re); - if (node->info) - XFREE (MTYPE_RIB_DEST, node->info); + if (node->info) + XFREE(MTYPE_RIB_DEST, node->info); } -static void -zebra_stable_node_cleanup (struct route_table *table, struct route_node *node) +static void zebra_stable_node_cleanup(struct route_table *table, + struct route_node *node) { - struct static_route *si, *next; - - if (node->info) - for (si = node->info; si; si = next) - { - next = si->next; - XFREE (MTYPE_STATIC_ROUTE, si); - } + struct static_route *si, *next; + + if (node->info) + for (si = node->info; si; si = next) { + next = si->next; + XFREE(MTYPE_STATIC_ROUTE, si); + } } -static void -zebra_rnhtable_node_cleanup (struct route_table *table, struct route_node *node) +static void zebra_rnhtable_node_cleanup(struct route_table *table, + struct route_node *node) { - if (node->info) - zebra_free_rnh (node->info); + if (node->info) + zebra_free_rnh(node->info); } /* * Create a routing table for the specific AFI/SAFI in the given VRF. */ -static void -zebra_vrf_table_create (struct zebra_vrf *zvrf, afi_t afi, safi_t safi) +static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi, + safi_t safi) { - rib_table_info_t *info; - struct route_table *table; - - assert (!zvrf->table[afi][safi]); - - if (afi == AFI_IP6) - table = srcdest_table_init(); - else - table = route_table_init(); - table->cleanup = zebra_rtable_node_cleanup; - zvrf->table[afi][safi] = table; - - info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info)); - info->zvrf = zvrf; - info->afi = afi; - info->safi = safi; - table->info = info; + rib_table_info_t *info; + struct route_table *table; + + assert(!zvrf->table[afi][safi]); + + if (afi == AFI_IP6) + table = srcdest_table_init(); + else + table = route_table_init(); + table->cleanup = zebra_rtable_node_cleanup; + zvrf->table[afi][safi] = table; + + info = XCALLOC(MTYPE_RIB_TABLE_INFO, sizeof(*info)); + info->zvrf = zvrf; + info->afi = afi; + info->safi = safi; + table->info = info; } /* Allocate new zebra VRF. */ -struct zebra_vrf * -zebra_vrf_alloc (void) +struct zebra_vrf *zebra_vrf_alloc(void) { - struct zebra_vrf *zvrf; - afi_t afi; - safi_t safi; - struct route_table *table; - - zvrf = XCALLOC (MTYPE_ZEBRA_VRF, sizeof (struct zebra_vrf)); - - for (afi = AFI_IP; afi <= AFI_IP6; afi++) - { - for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) - { - zebra_vrf_table_create (zvrf, afi, safi); - if (afi == AFI_IP6) - table = srcdest_table_init(); - else - table = route_table_init(); - table->cleanup = zebra_stable_node_cleanup; - zvrf->stable[afi][safi] = table; - } - - table = route_table_init(); - table->cleanup = zebra_rnhtable_node_cleanup; - zvrf->rnh_table[afi] = table; - - table = route_table_init(); - table->cleanup = zebra_rnhtable_node_cleanup; - zvrf->import_check_table[afi] = table; - } - - zebra_vxlan_init_tables (zvrf); - zebra_mpls_init_tables (zvrf); - - return zvrf; + struct zebra_vrf *zvrf; + afi_t afi; + safi_t safi; + struct route_table *table; + + zvrf = XCALLOC(MTYPE_ZEBRA_VRF, sizeof(struct zebra_vrf)); + + for (afi = AFI_IP; afi <= AFI_IP6; afi++) { + for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) { + zebra_vrf_table_create(zvrf, afi, safi); + if (afi == AFI_IP6) + table = srcdest_table_init(); + else + table = route_table_init(); + table->cleanup = zebra_stable_node_cleanup; + zvrf->stable[afi][safi] = table; + } + + table = route_table_init(); + table->cleanup = zebra_rnhtable_node_cleanup; + zvrf->rnh_table[afi] = table; + + table = route_table_init(); + table->cleanup = zebra_rnhtable_node_cleanup; + zvrf->import_check_table[afi] = table; + } + + zebra_vxlan_init_tables(zvrf); + zebra_mpls_init_tables(zvrf); + + return zvrf; } /* Lookup VRF by identifier. */ -struct zebra_vrf * -zebra_vrf_lookup_by_id (vrf_id_t vrf_id) +struct zebra_vrf *zebra_vrf_lookup_by_id(vrf_id_t vrf_id) { - return vrf_info_lookup (vrf_id); + return vrf_info_lookup(vrf_id); } /* Lookup VRF by name. */ -struct zebra_vrf * -zebra_vrf_lookup_by_name (const char *name) +struct zebra_vrf *zebra_vrf_lookup_by_name(const char *name) { - struct vrf *vrf; + struct vrf *vrf; - if (!name) - name = VRF_DEFAULT_NAME; + if (!name) + name = VRF_DEFAULT_NAME; - vrf = vrf_lookup_by_name (name); - if (vrf) - return ((struct zebra_vrf *) vrf->info); + vrf = vrf_lookup_by_name(name); + if (vrf) + return ((struct zebra_vrf *)vrf->info); - return NULL; + return NULL; } /* Lookup the routing table in an enabled VRF. */ -struct route_table * -zebra_vrf_table (afi_t afi, safi_t safi, vrf_id_t vrf_id) +struct route_table *zebra_vrf_table(afi_t afi, safi_t safi, vrf_id_t vrf_id) { - struct zebra_vrf *zvrf = vrf_info_lookup (vrf_id); + struct zebra_vrf *zvrf = vrf_info_lookup(vrf_id); - if (!zvrf) - return NULL; + if (!zvrf) + return NULL; - if (afi >= AFI_MAX || safi >= SAFI_MAX) - return NULL; + if (afi >= AFI_MAX || safi >= SAFI_MAX) + return NULL; - return zvrf->table[afi][safi]; + return zvrf->table[afi][safi]; } /* Lookup the static routing table in a VRF. */ -struct route_table * -zebra_vrf_static_table (afi_t afi, safi_t safi, struct zebra_vrf *zvrf) +struct route_table *zebra_vrf_static_table(afi_t afi, safi_t safi, + struct zebra_vrf *zvrf) { - if (!zvrf) - return NULL; + if (!zvrf) + return NULL; - if (afi >= AFI_MAX || safi >= SAFI_MAX) - return NULL; + if (afi >= AFI_MAX || safi >= SAFI_MAX) + return NULL; - return zvrf->stable[afi][safi]; + return zvrf->stable[afi][safi]; } -struct route_table * -zebra_vrf_other_route_table (afi_t afi, u_int32_t table_id, vrf_id_t vrf_id) +struct route_table *zebra_vrf_other_route_table(afi_t afi, u_int32_t table_id, + vrf_id_t vrf_id) { - struct zebra_vrf *zvrf; - rib_table_info_t *info; - struct route_table *table; - - zvrf = vrf_info_lookup (vrf_id); - if (! zvrf) - return NULL; - - if(afi >= AFI_MAX) - return NULL; - - if (table_id >= ZEBRA_KERNEL_TABLE_MAX) - return NULL; - - if ((vrf_id == VRF_DEFAULT) && (table_id != RT_TABLE_MAIN) && (table_id != zebrad.rtm_table_default)) - { - if (zvrf->other_table[afi][table_id] == NULL) - { - table = (afi == AFI_IP6) ? srcdest_table_init() : route_table_init(); - info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info)); - info->zvrf = zvrf; - info->afi = afi; - info->safi = SAFI_UNICAST; - table->info = info; - zvrf->other_table[afi][table_id] = table; - } - - return (zvrf->other_table[afi][table_id]); - } - - return zvrf->table[afi][SAFI_UNICAST]; + struct zebra_vrf *zvrf; + rib_table_info_t *info; + struct route_table *table; + + zvrf = vrf_info_lookup(vrf_id); + if (!zvrf) + return NULL; + + if (afi >= AFI_MAX) + return NULL; + + if (table_id >= ZEBRA_KERNEL_TABLE_MAX) + return NULL; + + if ((vrf_id == VRF_DEFAULT) && (table_id != RT_TABLE_MAIN) + && (table_id != zebrad.rtm_table_default)) { + if (zvrf->other_table[afi][table_id] == NULL) { + table = (afi == AFI_IP6) ? srcdest_table_init() + : route_table_init(); + info = XCALLOC(MTYPE_RIB_TABLE_INFO, sizeof(*info)); + info->zvrf = zvrf; + info->afi = afi; + info->safi = SAFI_UNICAST; + table->info = info; + zvrf->other_table[afi][table_id] = table; + } + + return (zvrf->other_table[afi][table_id]); + } + + return zvrf->table[afi][SAFI_UNICAST]; } -static int -vrf_config_write (struct vty *vty) +static int vrf_config_write(struct vty *vty) { - struct vrf *vrf; - struct zebra_vrf *zvrf; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - zvrf = vrf->info; - if (! zvrf || strcmp (zvrf_name (zvrf), VRF_DEFAULT_NAME)) - { - vty_out (vty, "vrf %s\n", zvrf_name(zvrf)); - vty_out (vty, "!\n"); - } - } - return 0; + struct vrf *vrf; + struct zebra_vrf *zvrf; + + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + zvrf = vrf->info; + if (!zvrf || strcmp(zvrf_name(zvrf), VRF_DEFAULT_NAME)) { + vty_out(vty, "vrf %s\n", zvrf_name(zvrf)); + vty_out(vty, "!\n"); + } + } + return 0; } /* Zebra VRF initialization. */ -void -zebra_vrf_init (void) +void zebra_vrf_init(void) { - vrf_init (zebra_vrf_new, - zebra_vrf_enable, - zebra_vrf_disable, - zebra_vrf_delete); + vrf_init(zebra_vrf_new, zebra_vrf_enable, zebra_vrf_disable, + zebra_vrf_delete); - vrf_cmd_init (vrf_config_write); + vrf_cmd_init(vrf_config_write); } diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index 29f7df00f..eb0687bf8 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -25,117 +25,114 @@ #include /* MPLS (Segment Routing) global block */ -typedef struct mpls_srgb_t_ -{ - u_int32_t start_label; - u_int32_t end_label; +typedef struct mpls_srgb_t_ { + u_int32_t start_label; + u_int32_t end_label; } mpls_srgb_t; /* Routing table instance. */ -struct zebra_vrf -{ - /* Back pointer */ - struct vrf *vrf; +struct zebra_vrf { + /* Back pointer */ + struct vrf *vrf; - /* Description. */ - char *desc; + /* Description. */ + char *desc; - /* FIB identifier. */ - u_char fib_id; + /* FIB identifier. */ + u_char fib_id; - /* Flags. */ - u_int16_t flags; + /* Flags. */ + u_int16_t flags; #define ZEBRA_VRF_RIB_SCHEDULED (1 << 0) #define ZEBRA_VRF_RETAIN (2 << 0) - u_int32_t table_id; + u_int32_t table_id; - /* Routing table. */ - struct route_table *table[AFI_MAX][SAFI_MAX]; + /* Routing table. */ + struct route_table *table[AFI_MAX][SAFI_MAX]; - /* Static route configuration. */ - struct route_table *stable[AFI_MAX][SAFI_MAX]; + /* Static route configuration. */ + struct route_table *stable[AFI_MAX][SAFI_MAX]; - /* Recursive Nexthop table */ - struct route_table *rnh_table[AFI_MAX]; + /* Recursive Nexthop table */ + struct route_table *rnh_table[AFI_MAX]; - /* Import check table (used mostly by BGP */ - struct route_table *import_check_table[AFI_MAX]; + /* Import check table (used mostly by BGP */ + struct route_table *import_check_table[AFI_MAX]; - /* Routing tables off of main table for redistribute table */ - struct route_table *other_table[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; + /* Routing tables off of main table for redistribute table */ + struct route_table *other_table[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; - /* 2nd pointer type used primarily to quell a warning on - * ALL_LIST_ELEMENTS_RO - */ - struct list _rid_all_sorted_list; - struct list _rid_lo_sorted_list; - struct list *rid_all_sorted_list; - struct list *rid_lo_sorted_list; - struct prefix rid_user_assigned; + /* 2nd pointer type used primarily to quell a warning on + * ALL_LIST_ELEMENTS_RO + */ + struct list _rid_all_sorted_list; + struct list _rid_lo_sorted_list; + struct list *rid_all_sorted_list; + struct list *rid_lo_sorted_list; + struct prefix rid_user_assigned; - /* - * Back pointer to the owning namespace. - */ - struct zebra_ns *zns; + /* + * Back pointer to the owning namespace. + */ + struct zebra_ns *zns; - /* MPLS static LSP config table */ - struct hash *slsp_table; + /* MPLS static LSP config table */ + struct hash *slsp_table; - /* MPLS label forwarding table */ - struct hash *lsp_table; + /* MPLS label forwarding table */ + struct hash *lsp_table; - /* MPLS FEC binding table */ - struct route_table *fec_table[AFI_MAX]; + /* MPLS FEC binding table */ + struct route_table *fec_table[AFI_MAX]; - /* MPLS Segment Routing Global block */ - mpls_srgb_t mpls_srgb; + /* MPLS Segment Routing Global block */ + mpls_srgb_t mpls_srgb; - /* MPLS processing flags */ - u_int16_t mpls_flags; + /* MPLS processing flags */ + u_int16_t mpls_flags; #define MPLS_FLAG_SCHEDULE_LSPS (1 << 0) - /* - * VNI hash table (for EVPN). Only in default instance. - */ - struct hash *vni_table; - /* - * Whether EVPN is enabled or not. - */ - int advertise_all_vni; - - /* Route Installs */ - uint64_t installs; - uint64_t removals; - uint64_t neigh_updates; - uint64_t lsp_installs; - uint64_t lsp_removals; + /* + * VNI hash table (for EVPN). Only in default instance. + */ + struct hash *vni_table; + /* + * Whether EVPN is enabled or not. + */ + int advertise_all_vni; + + /* Route Installs */ + uint64_t installs; + uint64_t removals; + uint64_t neigh_updates; + uint64_t lsp_installs; + uint64_t lsp_removals; }; -static inline vrf_id_t -zvrf_id (struct zebra_vrf *zvrf) +static inline vrf_id_t zvrf_id(struct zebra_vrf *zvrf) { - return zvrf->vrf->vrf_id; + return zvrf->vrf->vrf_id; } -static inline const char * -zvrf_name (struct zebra_vrf *zvrf) +static inline const char *zvrf_name(struct zebra_vrf *zvrf) { - return zvrf->vrf->name; + return zvrf->vrf->name; } -struct route_table * -zebra_vrf_table_with_table_id (afi_t afi, safi_t safi, - vrf_id_t vrf_id, u_int32_t table_id); - -extern void zebra_vrf_static_route_interface_fixup (struct interface *ifp); -extern void zebra_vrf_update_all (struct zserv *client); -extern struct zebra_vrf *zebra_vrf_lookup_by_id (vrf_id_t vrf_id); -extern struct zebra_vrf *zebra_vrf_lookup_by_name (const char *); -extern struct zebra_vrf *zebra_vrf_alloc (void); -extern struct route_table *zebra_vrf_table (afi_t, safi_t, vrf_id_t); -extern struct route_table *zebra_vrf_static_table (afi_t, safi_t, struct zebra_vrf *zvrf); -extern struct route_table *zebra_vrf_other_route_table (afi_t afi, u_int32_t table_id, - vrf_id_t vrf_id); -extern void zebra_vrf_init (void); +struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi, + vrf_id_t vrf_id, + u_int32_t table_id); + +extern void zebra_vrf_static_route_interface_fixup(struct interface *ifp); +extern void zebra_vrf_update_all(struct zserv *client); +extern struct zebra_vrf *zebra_vrf_lookup_by_id(vrf_id_t vrf_id); +extern struct zebra_vrf *zebra_vrf_lookup_by_name(const char *); +extern struct zebra_vrf *zebra_vrf_alloc(void); +extern struct route_table *zebra_vrf_table(afi_t, safi_t, vrf_id_t); +extern struct route_table *zebra_vrf_static_table(afi_t, safi_t, + struct zebra_vrf *zvrf); +extern struct route_table * +zebra_vrf_other_route_table(afi_t afi, u_int32_t table_id, vrf_id_t vrf_id); +extern void zebra_vrf_init(void); #endif diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index b1da38a7b..3978664db 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -46,12 +46,13 @@ extern int allow_delete; -static int do_show_ip_route(struct vty *vty, const char *vrf_name, - afi_t afi, safi_t safi, bool use_fib, u_char use_json, - route_tag_t tag, struct prefix *longer_prefix_p, - bool supernets_only, int type, u_short ospf_instance_id); -static void vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, - int mcast); +static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi, + safi_t safi, bool use_fib, u_char use_json, + route_tag_t tag, struct prefix *longer_prefix_p, + bool supernets_only, int type, + u_short ospf_instance_id); +static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn, + int mcast); #define ONE_DAY_SECOND 60*60*24 #define ONE_WEEK_SECOND 60*60*24*7 @@ -60,173 +61,169 @@ static void vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, #define CMD_VNI_RANGE "(1-16777215)" /* General function for static route. */ -int -zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, - const char *dest_str, const char *mask_str, - const char *gate_str, const char *flag_str, - const char *tag_str, const char *distance_str, - const char *vrf_id_str, const char *label_str) -{ - int ret; - u_char distance; - struct prefix p; - struct in_addr gate; - struct in_addr mask; - u_char flag = 0; - route_tag_t tag = 0; - struct zebra_vrf *zvrf = NULL; - unsigned int ifindex = 0; - const char *ifname = NULL; - u_char type = STATIC_BLACKHOLE; - struct static_nh_label snh_label; - - memset (&snh_label, 0, sizeof (struct static_nh_label)); - ret = str2prefix (dest_str, &p); - if (ret <= 0) - { - vty_out (vty, "%% Malformed address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Cisco like mask notation. */ - if (mask_str) - { - ret = inet_aton (mask_str, &mask); - if (ret == 0) - { - vty_out (vty, "%% Malformed address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - p.prefixlen = ip_masklen (mask); - } - - /* Apply mask for given prefix. */ - apply_mask (&p); - - /* Administrative distance. */ - if (distance_str) - distance = atoi (distance_str); - else - distance = ZEBRA_STATIC_DISTANCE_DEFAULT; - - /* tag */ - if (tag_str) - tag = strtoul(tag_str, NULL, 10); - - /* VRF id */ - zvrf = zebra_vrf_lookup_by_name (vrf_id_str); - - if (!zvrf) - { - vty_out (vty, "%% vrf %s is not defined\n", vrf_id_str); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Labels */ - if (label_str) - { - if (!mpls_enabled) - { - vty_out (vty, - "%% MPLS not turned on in kernel, ignoring command\n"); - return CMD_WARNING_CONFIG_FAILED; - } - int rc = mpls_str2label (label_str, &snh_label.num_labels, - snh_label.label); - if (rc < 0) - { - switch (rc) { - case -1: - vty_out (vty, "%% Malformed label(s)\n"); - break; - case -2: - vty_out (vty, "%% Cannot use reserved label(s) (%d-%d)\n", - MPLS_MIN_RESERVED_LABEL,MPLS_MAX_RESERVED_LABEL); - break; - case -3: - vty_out (vty, "%% Too many labels. Enter %d or fewer\n", - MPLS_MAX_LABELS); - break; - } - return CMD_WARNING_CONFIG_FAILED; - } - } - - /* Null0 static route. */ - if ((gate_str != NULL) && (strncasecmp (gate_str, "Null0", strlen (gate_str)) == 0)) - { - if (flag_str) - { - vty_out (vty, "%% can not have flag %s with Null0\n", flag_str); - return CMD_WARNING_CONFIG_FAILED; - } - if (add_cmd) - static_add_route (AFI_IP, safi, type, &p, NULL, NULL, ifindex, ifname, - ZEBRA_FLAG_BLACKHOLE, tag, distance, zvrf, &snh_label); - else - static_delete_route (AFI_IP, safi, type, &p, NULL, NULL, ifindex, tag, - distance, zvrf, &snh_label); - return CMD_SUCCESS; - } - - /* Route flags */ - if (flag_str) { - switch(flag_str[0]) { - case 'r': - case 'R': /* XXX */ - SET_FLAG (flag, ZEBRA_FLAG_REJECT); - break; - case 'b': - case 'B': /* XXX */ - SET_FLAG (flag, ZEBRA_FLAG_BLACKHOLE); - break; - default: - vty_out (vty, "%% Malformed flag %s \n", flag_str); - return CMD_WARNING_CONFIG_FAILED; - } - } - - if (gate_str == NULL) - { - if (add_cmd) - static_add_route (AFI_IP, safi, type, &p, NULL, NULL, ifindex, ifname, flag, - tag, distance, zvrf, &snh_label); - else - static_delete_route (AFI_IP, safi, type, &p, NULL, NULL, ifindex, tag, distance, - zvrf, &snh_label); - - return CMD_SUCCESS; - } - - /* When gateway is A.B.C.D format, gate is treated as nexthop - address other case gate is treated as interface name. */ - ret = inet_aton (gate_str, &gate); - if (!ret) - { - struct interface *ifp = if_lookup_by_name (gate_str, zvrf_id (zvrf)); - if (!ifp) - { - vty_out (vty, "%% Unknown interface: %s\n", gate_str); - ifindex = IFINDEX_DELETED; - } - else - ifindex = ifp->ifindex; - ifname = gate_str; - type = STATIC_IFINDEX; - } - else - type = STATIC_IPV4_GATEWAY; - - if (add_cmd) - static_add_route (AFI_IP, safi, type, &p, NULL, - ifindex ? NULL : (union g_addr *)&gate, ifindex, ifname, - flag, tag, distance, zvrf, &snh_label); - else - static_delete_route (AFI_IP, safi, type, &p, NULL, - ifindex ? NULL : (union g_addr *)&gate, ifindex, tag, - distance, zvrf, &snh_label); - - return CMD_SUCCESS; +int zebra_static_ipv4(struct vty *vty, safi_t safi, int add_cmd, + const char *dest_str, const char *mask_str, + const char *gate_str, const char *flag_str, + const char *tag_str, const char *distance_str, + const char *vrf_id_str, const char *label_str) +{ + int ret; + u_char distance; + struct prefix p; + struct in_addr gate; + struct in_addr mask; + u_char flag = 0; + route_tag_t tag = 0; + struct zebra_vrf *zvrf = NULL; + unsigned int ifindex = 0; + const char *ifname = NULL; + u_char type = STATIC_BLACKHOLE; + struct static_nh_label snh_label; + + memset(&snh_label, 0, sizeof(struct static_nh_label)); + ret = str2prefix(dest_str, &p); + if (ret <= 0) { + vty_out(vty, "%% Malformed address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Cisco like mask notation. */ + if (mask_str) { + ret = inet_aton(mask_str, &mask); + if (ret == 0) { + vty_out(vty, "%% Malformed address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + p.prefixlen = ip_masklen(mask); + } + + /* Apply mask for given prefix. */ + apply_mask(&p); + + /* Administrative distance. */ + if (distance_str) + distance = atoi(distance_str); + else + distance = ZEBRA_STATIC_DISTANCE_DEFAULT; + + /* tag */ + if (tag_str) + tag = strtoul(tag_str, NULL, 10); + + /* VRF id */ + zvrf = zebra_vrf_lookup_by_name(vrf_id_str); + + if (!zvrf) { + vty_out(vty, "%% vrf %s is not defined\n", vrf_id_str); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Labels */ + if (label_str) { + if (!mpls_enabled) { + vty_out(vty, + "%% MPLS not turned on in kernel, ignoring command\n"); + return CMD_WARNING_CONFIG_FAILED; + } + int rc = mpls_str2label(label_str, &snh_label.num_labels, + snh_label.label); + if (rc < 0) { + switch (rc) { + case -1: + vty_out(vty, "%% Malformed label(s)\n"); + break; + case -2: + vty_out(vty, + "%% Cannot use reserved label(s) (%d-%d)\n", + MPLS_MIN_RESERVED_LABEL, + MPLS_MAX_RESERVED_LABEL); + break; + case -3: + vty_out(vty, + "%% Too many labels. Enter %d or fewer\n", + MPLS_MAX_LABELS); + break; + } + return CMD_WARNING_CONFIG_FAILED; + } + } + + /* Null0 static route. */ + if ((gate_str != NULL) + && (strncasecmp(gate_str, "Null0", strlen(gate_str)) == 0)) { + if (flag_str) { + vty_out(vty, "%% can not have flag %s with Null0\n", + flag_str); + return CMD_WARNING_CONFIG_FAILED; + } + if (add_cmd) + static_add_route(AFI_IP, safi, type, &p, NULL, NULL, + ifindex, ifname, ZEBRA_FLAG_BLACKHOLE, + tag, distance, zvrf, &snh_label); + else + static_delete_route(AFI_IP, safi, type, &p, NULL, NULL, + ifindex, tag, distance, zvrf, + &snh_label); + return CMD_SUCCESS; + } + + /* Route flags */ + if (flag_str) { + switch (flag_str[0]) { + case 'r': + case 'R': /* XXX */ + SET_FLAG(flag, ZEBRA_FLAG_REJECT); + break; + case 'b': + case 'B': /* XXX */ + SET_FLAG(flag, ZEBRA_FLAG_BLACKHOLE); + break; + default: + vty_out(vty, "%% Malformed flag %s \n", flag_str); + return CMD_WARNING_CONFIG_FAILED; + } + } + + if (gate_str == NULL) { + if (add_cmd) + static_add_route(AFI_IP, safi, type, &p, NULL, NULL, + ifindex, ifname, flag, tag, distance, + zvrf, &snh_label); + else + static_delete_route(AFI_IP, safi, type, &p, NULL, NULL, + ifindex, tag, distance, zvrf, + &snh_label); + + return CMD_SUCCESS; + } + + /* When gateway is A.B.C.D format, gate is treated as nexthop + address other case gate is treated as interface name. */ + ret = inet_aton(gate_str, &gate); + if (!ret) { + struct interface *ifp = + if_lookup_by_name(gate_str, zvrf_id(zvrf)); + if (!ifp) { + vty_out(vty, "%% Unknown interface: %s\n", gate_str); + ifindex = IFINDEX_DELETED; + } else + ifindex = ifp->ifindex; + ifname = gate_str; + type = STATIC_IFINDEX; + } else + type = STATIC_IPV4_GATEWAY; + + if (add_cmd) + static_add_route(AFI_IP, safi, type, &p, NULL, + ifindex ? NULL : (union g_addr *)&gate, + ifindex, ifname, flag, tag, distance, zvrf, + &snh_label); + else + static_delete_route(AFI_IP, safi, type, &p, NULL, + ifindex ? NULL : (union g_addr *)&gate, + ifindex, tag, distance, zvrf, &snh_label); + + return CMD_SUCCESS; } /* Static unicast routes for multicast RPF lookup. */ @@ -240,11 +237,12 @@ DEFUN (ip_mroute_dist, "Nexthop interface name\n" "Distance\n") { - char *destprefix = argv[2]->arg; - char *nexthop = argv[3]->arg; - char *distance = (argc == 5) ? argv[4]->arg : NULL; + char *destprefix = argv[2]->arg; + char *nexthop = argv[3]->arg; + char *distance = (argc == 5) ? argv[4]->arg : NULL; - return zebra_static_ipv4 (vty, SAFI_MULTICAST, 1, destprefix, NULL, nexthop, NULL, NULL, distance, NULL, NULL); + return zebra_static_ipv4(vty, SAFI_MULTICAST, 1, destprefix, NULL, + nexthop, NULL, NULL, distance, NULL, NULL); } DEFUN (no_ip_mroute_dist, @@ -258,11 +256,12 @@ DEFUN (no_ip_mroute_dist, "Nexthop interface name\n" "Distance\n") { - char *destprefix = argv[3]->arg; - char *nexthop = argv[4]->arg; - char *distance = (argc == 6) ? argv[5]->arg : NULL; + char *destprefix = argv[3]->arg; + char *nexthop = argv[4]->arg; + char *distance = (argc == 6) ? argv[5]->arg : NULL; - return zebra_static_ipv4 (vty, SAFI_MULTICAST, 0, destprefix, NULL, nexthop, NULL, NULL, distance, NULL, NULL); + return zebra_static_ipv4(vty, SAFI_MULTICAST, 0, destprefix, NULL, + nexthop, NULL, NULL, distance, NULL, NULL); } DEFUN (ip_multicast_mode, @@ -277,25 +276,24 @@ DEFUN (ip_multicast_mode, "Lookup both, use entry with lower distance\n" "Lookup both, use entry with longer prefix\n") { - char *mode = argv[3]->text; - - if (strmatch (mode, "urib-only")) - multicast_mode_ipv4_set (MCAST_URIB_ONLY); - else if (strmatch (mode, "mrib-only")) - multicast_mode_ipv4_set (MCAST_MRIB_ONLY); - else if (strmatch (mode, "mrib-then-urib")) - multicast_mode_ipv4_set (MCAST_MIX_MRIB_FIRST); - else if (strmatch (mode, "lower-distance")) - multicast_mode_ipv4_set (MCAST_MIX_DISTANCE); - else if (strmatch (mode, "longer-prefix")) - multicast_mode_ipv4_set (MCAST_MIX_PFXLEN); - else - { - vty_out (vty, "Invalid mode specified\n"); - return CMD_WARNING_CONFIG_FAILED; - } + char *mode = argv[3]->text; + + if (strmatch(mode, "urib-only")) + multicast_mode_ipv4_set(MCAST_URIB_ONLY); + else if (strmatch(mode, "mrib-only")) + multicast_mode_ipv4_set(MCAST_MRIB_ONLY); + else if (strmatch(mode, "mrib-then-urib")) + multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST); + else if (strmatch(mode, "lower-distance")) + multicast_mode_ipv4_set(MCAST_MIX_DISTANCE); + else if (strmatch(mode, "longer-prefix")) + multicast_mode_ipv4_set(MCAST_MIX_PFXLEN); + else { + vty_out(vty, "Invalid mode specified\n"); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_multicast_mode, @@ -311,8 +309,8 @@ DEFUN (no_ip_multicast_mode, "Lookup both, use entry with lower distance\n" "Lookup both, use entry with longer prefix\n") { - multicast_mode_ipv4_set (MCAST_NO_CONFIG); - return CMD_SUCCESS; + multicast_mode_ipv4_set(MCAST_NO_CONFIG); + return CMD_SUCCESS; } @@ -324,8 +322,9 @@ DEFUN (show_ip_rpf, "Display RPF information for multicast source\n" JSON_STR) { - int uj = use_json(argc, argv); - return do_show_ip_route (vty, VRF_DEFAULT_NAME, AFI_IP, SAFI_MULTICAST, false, uj, 0, NULL, false, -1, 0); + int uj = use_json(argc, argv); + return do_show_ip_route(vty, VRF_DEFAULT_NAME, AFI_IP, SAFI_MULTICAST, + false, uj, 0, NULL, false, -1, 0); } DEFUN (show_ip_rpf_addr, @@ -336,64 +335,55 @@ DEFUN (show_ip_rpf_addr, "Display RPF information for multicast source\n" "IP multicast source address (e.g. 10.0.0.0)\n") { - int idx_ipv4 = 3; - struct in_addr addr; - struct route_node *rn; - struct route_entry *re; - int ret; - - ret = inet_aton (argv[idx_ipv4]->arg, &addr); - if (ret == 0) - { - vty_out (vty, "%% Malformed address\n"); - return CMD_WARNING; - } - - re = rib_match_ipv4_multicast (VRF_DEFAULT, addr, &rn); - - if (re) - vty_show_ip_route_detail (vty, rn, 1); - else - vty_out (vty, "%% No match for RPF lookup\n"); - - return CMD_SUCCESS; -} - -static void -zebra_vty_ip_route_tdv_helper (int argc, struct cmd_token *argv[], - int idx_curr, char **tag, - char **distance, char **vrf, char **labels) -{ - *distance = NULL; - while (idx_curr < argc) - { - if (strmatch (argv[idx_curr]->text, "tag")) - { - if (tag) - *tag = argv[idx_curr+1]->arg; - idx_curr += 2; - } - else if (strmatch (argv[idx_curr]->text, "vrf")) - { - if (vrf) - *vrf = argv[idx_curr+1]->arg; - idx_curr += 2; - } - else if (strmatch (argv[idx_curr]->text, "label")) - { - if (labels) - *labels = argv[idx_curr+1]->arg; - idx_curr += 2; - } - else - { - if (distance) - *distance = argv[idx_curr]->arg; - idx_curr++; - } - } - - return; + int idx_ipv4 = 3; + struct in_addr addr; + struct route_node *rn; + struct route_entry *re; + int ret; + + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (ret == 0) { + vty_out(vty, "%% Malformed address\n"); + return CMD_WARNING; + } + + re = rib_match_ipv4_multicast(VRF_DEFAULT, addr, &rn); + + if (re) + vty_show_ip_route_detail(vty, rn, 1); + else + vty_out(vty, "%% No match for RPF lookup\n"); + + return CMD_SUCCESS; +} + +static void zebra_vty_ip_route_tdv_helper(int argc, struct cmd_token *argv[], + int idx_curr, char **tag, + char **distance, char **vrf, + char **labels) +{ + *distance = NULL; + while (idx_curr < argc) { + if (strmatch(argv[idx_curr]->text, "tag")) { + if (tag) + *tag = argv[idx_curr + 1]->arg; + idx_curr += 2; + } else if (strmatch(argv[idx_curr]->text, "vrf")) { + if (vrf) + *vrf = argv[idx_curr + 1]->arg; + idx_curr += 2; + } else if (strmatch(argv[idx_curr]->text, "label")) { + if (labels) + *labels = argv[idx_curr + 1]->arg; + idx_curr += 2; + } else { + if (distance) + *distance = argv[idx_curr]->arg; + idx_curr++; + } + } + + return; } /* Static route configuration. */ @@ -411,20 +401,19 @@ DEFUN (ip_route, "Distance value for this route\n" VRF_CMD_HELP_STR) { - int idx_ipv4_prefixlen = 2; - int idx_ipv4_ifname_null = 3; - int idx_curr = 4; - char *tag, *distance, *vrf; + int idx_ipv4_prefixlen = 2; + int idx_ipv4_ifname_null = 3; + int idx_curr = 4; + char *tag, *distance, *vrf; - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, - argv[idx_ipv4_prefixlen]->arg, - NULL, - argv[idx_ipv4_ifname_null]->arg, - NULL, - tag, distance, vrf, NULL); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, + argv[idx_ipv4_prefixlen]->arg, NULL, + argv[idx_ipv4_ifname_null]->arg, NULL, tag, + distance, vrf, NULL); } DEFUN (ip_route_flags, @@ -440,20 +429,18 @@ DEFUN (ip_route_flags, "Distance value for this route\n" VRF_CMD_HELP_STR) { - int idx_ipv4_prefixlen = 2; - int idx_reject_blackhole = 3; - int idx_curr = 4; - char *tag, *distance, *vrf; + int idx_ipv4_prefixlen = 2; + int idx_reject_blackhole = 3; + int idx_curr = 4; + char *tag, *distance, *vrf; - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, - argv[idx_ipv4_prefixlen]->arg, - NULL, - NULL, - argv[idx_reject_blackhole]->arg, - tag, distance, vrf, NULL); + return zebra_static_ipv4( + vty, SAFI_UNICAST, 1, argv[idx_ipv4_prefixlen]->arg, NULL, NULL, + argv[idx_reject_blackhole]->arg, tag, distance, vrf, NULL); } /* Mask as A.B.C.D format. */ @@ -472,20 +459,20 @@ DEFUN (ip_route_mask, "Distance value for this route\n" VRF_CMD_HELP_STR) { - int idx_ipv4 = 2; - int idx_ipv4_2 = 3; - int idx_ipv4_ifname_null = 4; - int idx_curr = 5; - char *tag, *distance, *vrf; + int idx_ipv4 = 2; + int idx_ipv4_2 = 3; + int idx_ipv4_ifname_null = 4; + int idx_curr = 5; + char *tag, *distance, *vrf; - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, - argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, - argv[idx_ipv4_ifname_null]->arg, - NULL, tag, distance, vrf, NULL); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[idx_ipv4]->arg, + argv[idx_ipv4_2]->arg, + argv[idx_ipv4_ifname_null]->arg, NULL, tag, + distance, vrf, NULL); } DEFUN (ip_route_mask_flags, @@ -502,21 +489,20 @@ DEFUN (ip_route_mask_flags, "Distance value for this route\n" VRF_CMD_HELP_STR) { - int idx_ipv4 = 2; - int idx_ipv4_2 = 3; - int idx_reject_blackhole = 4; - int idx_curr = 5; - char *tag, *distance, *vrf; + int idx_ipv4 = 2; + int idx_ipv4_2 = 3; + int idx_reject_blackhole = 4; + int idx_curr = 5; + char *tag, *distance, *vrf; - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); - return zebra_static_ipv4 (vty, SAFI_UNICAST, 1, - argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, - NULL, - argv[idx_reject_blackhole]->arg, - tag, distance, vrf, NULL); + return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[idx_ipv4]->arg, + argv[idx_ipv4_2]->arg, NULL, + argv[idx_reject_blackhole]->arg, tag, distance, + vrf, NULL); } DEFUN (no_ip_route, @@ -534,20 +520,19 @@ DEFUN (no_ip_route, "Distance value for this route\n" VRF_CMD_HELP_STR) { - int idx_ipv4_prefixlen = 3; - int idx_ipv4_ifname_null = 4; - int idx_curr = 5; - char *tag, *distance, *vrf; + int idx_ipv4_prefixlen = 3; + int idx_ipv4_ifname_null = 4; + int idx_curr = 5; + char *tag, *distance, *vrf; - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, - argv[idx_ipv4_prefixlen]->arg, - NULL, - argv[idx_ipv4_ifname_null]->arg, - NULL, - tag, distance, vrf, NULL); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, + argv[idx_ipv4_prefixlen]->arg, NULL, + argv[idx_ipv4_ifname_null]->arg, NULL, tag, + distance, vrf, NULL); } DEFUN (no_ip_route_flags, @@ -564,17 +549,17 @@ DEFUN (no_ip_route_flags, "Distance value for this route\n" VRF_CMD_HELP_STR) { - int idx_ipv4_prefixlen = 3; - int idx_curr = 5; - char *tag, *distance, *vrf; + int idx_ipv4_prefixlen = 3; + int idx_curr = 5; + char *tag, *distance, *vrf; - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, - argv[idx_ipv4_prefixlen]->arg, - NULL, NULL, NULL, - tag, distance, vrf, NULL); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, + argv[idx_ipv4_prefixlen]->arg, NULL, NULL, + NULL, tag, distance, vrf, NULL); } DEFUN (no_ip_route_mask, @@ -593,21 +578,20 @@ DEFUN (no_ip_route_mask, "Distance value for this route\n" VRF_CMD_HELP_STR) { - int idx_ipv4 = 3; - int idx_ipv4_2 = 4; - int idx_ipv4_ifname_null = 5; - int idx_curr = 6; - char *tag, *distance, *vrf; + int idx_ipv4 = 3; + int idx_ipv4_2 = 4; + int idx_ipv4_ifname_null = 5; + int idx_curr = 6; + char *tag, *distance, *vrf; - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, - argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, - argv[idx_ipv4_ifname_null]->arg, - NULL, - tag, distance, vrf, NULL); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[idx_ipv4]->arg, + argv[idx_ipv4_2]->arg, + argv[idx_ipv4_ifname_null]->arg, NULL, tag, + distance, vrf, NULL); } DEFUN (no_ip_route_mask_flags, @@ -625,592 +609,634 @@ DEFUN (no_ip_route_mask_flags, "Distance value for this route\n" VRF_CMD_HELP_STR) { - int idx_ipv4 = 3; - int idx_ipv4_2 = 4; - int idx_curr = 6; - char *tag, *distance, *vrf; + int idx_ipv4 = 3; + int idx_ipv4_2 = 4; + int idx_curr = 6; + char *tag, *distance, *vrf; - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); - return zebra_static_ipv4 (vty, SAFI_UNICAST, 0, - argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, - NULL, NULL, - tag, distance, vrf, NULL); + return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[idx_ipv4]->arg, + argv[idx_ipv4_2]->arg, NULL, NULL, tag, + distance, vrf, NULL); } /* New RIB. Detailed information for IPv4 route. */ -static void -vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast) -{ - struct route_entry *re; - struct nexthop *nexthop; - char buf[SRCDEST2STR_BUFFER]; - struct zebra_vrf *zvrf; - - RNODE_FOREACH_RE (rn, re) - { - const char *mcast_info = ""; - if (mcast) - { - rib_table_info_t *info = srcdest_rnode_table_info(rn); - mcast_info = (info->safi == SAFI_MULTICAST) - ? " using Multicast RIB" - : " using Unicast RIB"; - } - - vty_out (vty, "Routing entry for %s%s\n", - srcdest_rnode2str(rn, buf, sizeof(buf)), mcast_info); - vty_out (vty, " Known via \"%s", zebra_route_string (re->type)); - if (re->instance) - vty_out (vty, "[%d]", re->instance); - vty_out (vty, "\""); - vty_out (vty, ", distance %u, metric %u", re->distance, re->metric); - if (re->tag) - vty_out (vty, ", tag %d", re->tag); - if (re->mtu) - vty_out (vty, ", mtu %u", re->mtu); - if (re->vrf_id != VRF_DEFAULT) - { - zvrf = vrf_info_lookup(re->vrf_id); - vty_out (vty, ", vrf %s", zvrf_name (zvrf)); - } - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_SELECTED)) - vty_out (vty, ", best"); - if (re->refcnt) - vty_out (vty, ", refcnt %ld", re->refcnt); - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_BLACKHOLE)) - vty_out (vty, ", blackhole"); - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_REJECT)) - vty_out (vty, ", reject"); - vty_out (vty, "\n"); - - if (re->type == ZEBRA_ROUTE_RIP - || re->type == ZEBRA_ROUTE_OSPF - || re->type == ZEBRA_ROUTE_ISIS - || re->type == ZEBRA_ROUTE_NHRP - || re->type == ZEBRA_ROUTE_TABLE - || re->type == ZEBRA_ROUTE_BGP) - { - time_t uptime; - struct tm *tm; - - uptime = time (NULL); - uptime -= re->uptime; - tm = gmtime (&uptime); - - vty_out (vty, " Last update "); - - if (uptime < ONE_DAY_SECOND) - vty_out (vty, "%02d:%02d:%02d", - tm->tm_hour, tm->tm_min, tm->tm_sec); - else if (uptime < ONE_WEEK_SECOND) - vty_out (vty, "%dd%02dh%02dm", - tm->tm_yday, tm->tm_hour, tm->tm_min); - else - vty_out (vty, "%02dw%dd%02dh", - tm->tm_yday/7, - tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); - vty_out (vty, " ago\n"); - } - - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - char addrstr[32]; - - vty_out (vty, " %c%s", - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ', - nexthop->rparent ? " " : ""); - - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - vty_out (vty, " %s", inet_ntoa (nexthop->gate.ipv4)); - if (nexthop->ifindex) - vty_out (vty, ", via %s", - ifindex2ifname (nexthop->ifindex, re->vrf_id)); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - vty_out (vty, " %s", - inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, sizeof buf)); - if (nexthop->ifindex) - vty_out (vty, ", via %s", - ifindex2ifname (nexthop->ifindex, re->vrf_id)); - break; - case NEXTHOP_TYPE_IFINDEX: - vty_out (vty, " directly connected, %s", - ifindex2ifname (nexthop->ifindex, re->vrf_id)); - break; - case NEXTHOP_TYPE_BLACKHOLE: - vty_out (vty, " directly connected, Null0"); - break; - default: - break; - } - if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - vty_out (vty, " inactive"); - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK)) - vty_out (vty, " onlink"); - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - vty_out (vty, " (recursive)"); - - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - if (nexthop->src.ipv4.s_addr) - { - if (inet_ntop(AF_INET, &nexthop->src.ipv4, addrstr, - sizeof addrstr)) - vty_out (vty, ", src %s", addrstr); - } - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) - { - if (inet_ntop(AF_INET6, &nexthop->src.ipv6, addrstr, - sizeof addrstr)) - vty_out (vty, ", src %s", addrstr); - } - break; - default: - break; - } - - /* Label information */ - if (nexthop->nh_label && nexthop->nh_label->num_labels) - { - vty_out (vty, ", label %s", - mpls_label2str (nexthop->nh_label->num_labels, - nexthop->nh_label->label, buf, sizeof buf, 1)); - } - - vty_out (vty, "\n"); - } - vty_out (vty, "\n"); - } -} - -static void -vty_show_ip_route (struct vty *vty, struct route_node *rn, struct route_entry *re, - json_object *json) -{ - struct nexthop *nexthop; - int len = 0; - char buf[SRCDEST2STR_BUFFER]; - json_object *json_nexthops = NULL; - json_object *json_nexthop = NULL; - json_object *json_route = NULL; - json_object *json_labels = NULL; - - if (json) - { - json_route = json_object_new_object(); - json_nexthops = json_object_new_array(); - - json_object_string_add(json_route, "prefix", srcdest_rnode2str (rn, buf, sizeof buf)); - json_object_string_add(json_route, "protocol", zebra_route_string(re->type)); - - if (re->instance) - json_object_int_add(json_route, "instance", re->instance); - - if (re->vrf_id) - json_object_int_add(json_route, "vrfId", re->vrf_id); - - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_SELECTED)) - json_object_boolean_true_add(json_route, "selected"); - - if (re->type != ZEBRA_ROUTE_CONNECT && re->type != ZEBRA_ROUTE_KERNEL) - { - json_object_int_add(json_route, "distance", re->distance); - json_object_int_add(json_route, "metric", re->metric); - } - - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_BLACKHOLE)) - json_object_boolean_true_add(json_route, "blackhole"); - - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_REJECT)) - json_object_boolean_true_add(json_route, "reject"); - - if (re->type == ZEBRA_ROUTE_RIP - || re->type == ZEBRA_ROUTE_OSPF - || re->type == ZEBRA_ROUTE_ISIS - || re->type == ZEBRA_ROUTE_NHRP - || re->type == ZEBRA_ROUTE_TABLE - || re->type == ZEBRA_ROUTE_BGP) - { - time_t uptime; - struct tm *tm; - - uptime = time (NULL); - uptime -= re->uptime; - tm = gmtime (&uptime); - - if (uptime < ONE_DAY_SECOND) - sprintf(buf, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); - else if (uptime < ONE_WEEK_SECOND) - sprintf(buf, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour, tm->tm_min); - else - sprintf(buf, "%02dw%dd%02dh", tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); - - json_object_string_add(json_route, "uptime", buf); - } - - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - json_nexthop = json_object_new_object(); - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - json_object_boolean_true_add(json_nexthop, "fib"); - - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - json_object_string_add(json_nexthop, "ip", inet_ntoa (nexthop->gate.ipv4)); - json_object_string_add(json_nexthop, "afi", "ipv4"); - - if (nexthop->ifindex) - { - json_object_int_add(json_nexthop, "interfaceIndex", nexthop->ifindex); - json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname (nexthop->ifindex, re->vrf_id)); - } - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - json_object_string_add(json_nexthop, "ip", inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, sizeof buf)); - json_object_string_add(json_nexthop, "afi", "ipv6"); - - if (nexthop->ifindex) - { - json_object_int_add(json_nexthop, "interfaceIndex", nexthop->ifindex); - json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname (nexthop->ifindex, re->vrf_id)); - } - break; - - case NEXTHOP_TYPE_IFINDEX: - json_object_boolean_true_add(json_nexthop, "directlyConnected"); - json_object_int_add(json_nexthop, "interfaceIndex", nexthop->ifindex); - json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname (nexthop->ifindex, re->vrf_id)); - break; - case NEXTHOP_TYPE_BLACKHOLE: - json_object_boolean_true_add(json_nexthop, "blackhole"); - break; - default: - break; - } - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - json_object_boolean_true_add(json_nexthop, "active"); - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK)) - json_object_boolean_true_add(json_nexthop, "onLink"); - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - json_object_boolean_true_add(json_nexthop, "recursive"); - - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - if (nexthop->src.ipv4.s_addr) - { - if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf, sizeof buf)) - json_object_string_add(json_nexthop, "source", buf); - } - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) - { - if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf, sizeof buf)) - json_object_string_add(json_nexthop, "source", buf); - } - break; - default: - break; - } - - if (nexthop->nh_label && nexthop->nh_label->num_labels) - { - json_labels = json_object_new_array(); - - for (int label_index = 0; label_index < nexthop->nh_label->num_labels; label_index++) - json_object_array_add(json_labels, json_object_new_int(nexthop->nh_label->label[label_index])); - - json_object_object_add(json_nexthop, "labels", json_labels); - } - - json_object_array_add(json_nexthops, json_nexthop); - } - - json_object_object_add(json_route, "nexthops", json_nexthops); - json_object_array_add(json, json_route); - return; - } - - /* Nexthop information. */ - for (ALL_NEXTHOPS(re->nexthop, nexthop)) - { - if (nexthop == re->nexthop) - { - /* Prefix information. */ - len = vty_out (vty, "%c", zebra_route_char (re->type)); - if (re->instance) - len += vty_out (vty, "[%d]", re->instance); - len += vty_out (vty, "%c%c %s", - CHECK_FLAG (re->flags, ZEBRA_FLAG_SELECTED) - ? '>' : ' ', - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) - ? '*' : ' ', - srcdest_rnode2str (rn, buf, sizeof buf)); - - /* Distance and metric display. */ - if (re->type != ZEBRA_ROUTE_CONNECT - && re->type != ZEBRA_ROUTE_KERNEL) - len += vty_out (vty, " [%d/%d]", re->distance, - re->metric); - } - else - vty_out (vty, " %c%*c", - CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) - ? '*' : ' ', - len - 3 + (2 * nexthop_level(nexthop)), ' '); - - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4)); - if (nexthop->ifindex) - vty_out (vty, ", %s", - ifindex2ifname (nexthop->ifindex, re->vrf_id)); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - vty_out (vty, " via %s", - inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, sizeof buf)); - if (nexthop->ifindex) - vty_out (vty, ", %s", - ifindex2ifname (nexthop->ifindex, re->vrf_id)); - break; - - case NEXTHOP_TYPE_IFINDEX: - vty_out (vty, " is directly connected, %s", - ifindex2ifname (nexthop->ifindex, re->vrf_id)); - break; - case NEXTHOP_TYPE_BLACKHOLE: - vty_out (vty, " is directly connected, Null0"); - break; - default: - break; - } - if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - vty_out (vty, " inactive"); - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK)) - vty_out (vty, " onlink"); - - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - vty_out (vty, " (recursive)"); - - switch (nexthop->type) - { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - if (nexthop->src.ipv4.s_addr) - { - if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf, sizeof buf)) - vty_out (vty, ", src %s", buf); - } - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) - { - if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf, sizeof buf)) - vty_out (vty, ", src %s", buf); - } - break; - default: - break; - } - - /* Label information */ - if (nexthop->nh_label && nexthop->nh_label->num_labels) - { - vty_out (vty, ", label %s", - mpls_label2str (nexthop->nh_label->num_labels, - nexthop->nh_label->label, buf, sizeof buf, 1)); - } - - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_BLACKHOLE)) - vty_out (vty, ", bh"); - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_REJECT)) - vty_out (vty, ", rej"); - - if (re->type == ZEBRA_ROUTE_RIP - || re->type == ZEBRA_ROUTE_OSPF - || re->type == ZEBRA_ROUTE_ISIS - || re->type == ZEBRA_ROUTE_NHRP - || re->type == ZEBRA_ROUTE_TABLE - || re->type == ZEBRA_ROUTE_BGP) +static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn, + int mcast) +{ + struct route_entry *re; + struct nexthop *nexthop; + char buf[SRCDEST2STR_BUFFER]; + struct zebra_vrf *zvrf; + + RNODE_FOREACH_RE(rn, re) { - time_t uptime; - struct tm *tm; - - uptime = time (NULL); - uptime -= re->uptime; - tm = gmtime (&uptime); - - if (uptime < ONE_DAY_SECOND) - vty_out (vty, ", %02d:%02d:%02d", - tm->tm_hour, tm->tm_min, tm->tm_sec); - else if (uptime < ONE_WEEK_SECOND) - vty_out (vty, ", %dd%02dh%02dm", - tm->tm_yday, tm->tm_hour, tm->tm_min); - else - vty_out (vty, ", %02dw%dd%02dh", - tm->tm_yday/7, - tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); - } - vty_out (vty, "\n"); - } -} - -static bool -use_fib (struct cmd_token *token) -{ - return strncmp(token->arg, "route", strlen(token->arg)); -} - -static int -do_show_ip_route (struct vty *vty, const char *vrf_name, afi_t afi, safi_t safi, - bool use_fib, u_char use_json, route_tag_t tag, - struct prefix *longer_prefix_p, bool supernets_only, - int type, u_short ospf_instance_id) -{ - struct route_table *table; - struct route_node *rn; - struct route_entry *re; - int first = 1; - struct zebra_vrf *zvrf = NULL; - char buf[BUFSIZ]; - json_object *json = NULL; - json_object *json_prefix = NULL; - u_int32_t addr; - - if (!(zvrf = zebra_vrf_lookup_by_name (vrf_name))) - { - if (use_json) - vty_out (vty, "{}\n"); - else - vty_out (vty, "vrf %s not defined\n", vrf_name); - return CMD_SUCCESS; - } - - if (zvrf_id (zvrf) == VRF_UNKNOWN) - { - if (use_json) - vty_out (vty, "{}\n"); - else - vty_out (vty, "vrf %s inactive\n", vrf_name); - return CMD_SUCCESS; - } - - table = zebra_vrf_table (afi, safi, zvrf_id (zvrf)); - if (! table) - { - if (use_json) - vty_out (vty, "{}\n"); - return CMD_SUCCESS; - } - - if (use_json) - json = json_object_new_object(); - - /* Show all routes. */ - for (rn = route_top (table); rn; rn = route_next (rn)) - { - RNODE_FOREACH_RE (rn, re) - { - if (use_fib && !CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) - continue; - - if (tag && re->tag != tag) - continue; - - if (longer_prefix_p && ! prefix_match (longer_prefix_p, &rn->p)) - continue; - - /* This can only be true when the afi is IPv4 */ - if (supernets_only) - { - addr = ntohl (rn->p.u.prefix4.s_addr); - - if (IN_CLASSC (addr) && rn->p.prefixlen >= 24) - continue; - - if (IN_CLASSB (addr) && rn->p.prefixlen >= 16) - continue; - - if (IN_CLASSA (addr) && rn->p.prefixlen >= 8) - continue; - } - - if (type && re->type != type) - continue; - - if (ospf_instance_id && (re->type != ZEBRA_ROUTE_OSPF || re->instance != ospf_instance_id)) - continue; - - if (use_json) - { - if (!json_prefix) - json_prefix = json_object_new_array(); - } - else - { - if (first) - { - if (afi == AFI_IP) - vty_out (vty, SHOW_ROUTE_V4_HEADER); - else - vty_out (vty, SHOW_ROUTE_V6_HEADER); - - if (zvrf_id (zvrf) != VRF_DEFAULT) - vty_out (vty, "\nVRF %s:\n", - zvrf_name(zvrf)); - - first = 0; - } - } - - vty_show_ip_route (vty, rn, re, json_prefix); - } - - if (json_prefix) - { - prefix2str (&rn->p, buf, sizeof buf); - json_object_object_add(json, buf, json_prefix); - json_prefix = NULL; - } - } - - if (use_json) - { - vty_out (vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } - - return CMD_SUCCESS; + const char *mcast_info = ""; + if (mcast) { + rib_table_info_t *info = srcdest_rnode_table_info(rn); + mcast_info = (info->safi == SAFI_MULTICAST) + ? " using Multicast RIB" + : " using Unicast RIB"; + } + + vty_out(vty, "Routing entry for %s%s\n", + srcdest_rnode2str(rn, buf, sizeof(buf)), mcast_info); + vty_out(vty, " Known via \"%s", zebra_route_string(re->type)); + if (re->instance) + vty_out(vty, "[%d]", re->instance); + vty_out(vty, "\""); + vty_out(vty, ", distance %u, metric %u", re->distance, + re->metric); + if (re->tag) + vty_out(vty, ", tag %d", re->tag); + if (re->mtu) + vty_out(vty, ", mtu %u", re->mtu); + if (re->vrf_id != VRF_DEFAULT) { + zvrf = vrf_info_lookup(re->vrf_id); + vty_out(vty, ", vrf %s", zvrf_name(zvrf)); + } + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) + vty_out(vty, ", best"); + if (re->refcnt) + vty_out(vty, ", refcnt %ld", re->refcnt); + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE)) + vty_out(vty, ", blackhole"); + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_REJECT)) + vty_out(vty, ", reject"); + vty_out(vty, "\n"); + + if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF + || re->type == ZEBRA_ROUTE_ISIS + || re->type == ZEBRA_ROUTE_NHRP + || re->type == ZEBRA_ROUTE_TABLE + || re->type == ZEBRA_ROUTE_BGP) { + time_t uptime; + struct tm *tm; + + uptime = time(NULL); + uptime -= re->uptime; + tm = gmtime(&uptime); + + vty_out(vty, " Last update "); + + if (uptime < ONE_DAY_SECOND) + vty_out(vty, "%02d:%02d:%02d", tm->tm_hour, + tm->tm_min, tm->tm_sec); + else if (uptime < ONE_WEEK_SECOND) + vty_out(vty, "%dd%02dh%02dm", tm->tm_yday, + tm->tm_hour, tm->tm_min); + else + vty_out(vty, "%02dw%dd%02dh", tm->tm_yday / 7, + tm->tm_yday - ((tm->tm_yday / 7) * 7), + tm->tm_hour); + vty_out(vty, " ago\n"); + } + + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + char addrstr[32]; + + vty_out(vty, " %c%s", + CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB) + ? '*' + : ' ', + nexthop->rparent ? " " : ""); + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + vty_out(vty, " %s", + inet_ntoa(nexthop->gate.ipv4)); + if (nexthop->ifindex) + vty_out(vty, ", via %s", + ifindex2ifname(nexthop->ifindex, + re->vrf_id)); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + vty_out(vty, " %s", + inet_ntop(AF_INET6, &nexthop->gate.ipv6, + buf, sizeof buf)); + if (nexthop->ifindex) + vty_out(vty, ", via %s", + ifindex2ifname(nexthop->ifindex, + re->vrf_id)); + break; + case NEXTHOP_TYPE_IFINDEX: + vty_out(vty, " directly connected, %s", + ifindex2ifname(nexthop->ifindex, + re->vrf_id)); + break; + case NEXTHOP_TYPE_BLACKHOLE: + vty_out(vty, " directly connected, Null0"); + break; + default: + break; + } + if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + vty_out(vty, " inactive"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) + vty_out(vty, " onlink"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + vty_out(vty, " (recursive)"); + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + if (nexthop->src.ipv4.s_addr) { + if (inet_ntop(AF_INET, + &nexthop->src.ipv4, + addrstr, sizeof addrstr)) + vty_out(vty, ", src %s", + addrstr); + } + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, + &in6addr_any)) { + if (inet_ntop(AF_INET6, + &nexthop->src.ipv6, + addrstr, sizeof addrstr)) + vty_out(vty, ", src %s", + addrstr); + } + break; + default: + break; + } + + /* Label information */ + if (nexthop->nh_label + && nexthop->nh_label->num_labels) { + vty_out(vty, ", label %s", + mpls_label2str( + nexthop->nh_label->num_labels, + nexthop->nh_label->label, buf, + sizeof buf, 1)); + } + + vty_out(vty, "\n"); + } + vty_out(vty, "\n"); + } +} + +static void vty_show_ip_route(struct vty *vty, struct route_node *rn, + struct route_entry *re, json_object *json) +{ + struct nexthop *nexthop; + int len = 0; + char buf[SRCDEST2STR_BUFFER]; + json_object *json_nexthops = NULL; + json_object *json_nexthop = NULL; + json_object *json_route = NULL; + json_object *json_labels = NULL; + + if (json) { + json_route = json_object_new_object(); + json_nexthops = json_object_new_array(); + + json_object_string_add(json_route, "prefix", + srcdest_rnode2str(rn, buf, sizeof buf)); + json_object_string_add(json_route, "protocol", + zebra_route_string(re->type)); + + if (re->instance) + json_object_int_add(json_route, "instance", + re->instance); + + if (re->vrf_id) + json_object_int_add(json_route, "vrfId", re->vrf_id); + + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) + json_object_boolean_true_add(json_route, "selected"); + + if (re->type != ZEBRA_ROUTE_CONNECT + && re->type != ZEBRA_ROUTE_KERNEL) { + json_object_int_add(json_route, "distance", + re->distance); + json_object_int_add(json_route, "metric", re->metric); + } + + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE)) + json_object_boolean_true_add(json_route, "blackhole"); + + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_REJECT)) + json_object_boolean_true_add(json_route, "reject"); + + if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF + || re->type == ZEBRA_ROUTE_ISIS + || re->type == ZEBRA_ROUTE_NHRP + || re->type == ZEBRA_ROUTE_TABLE + || re->type == ZEBRA_ROUTE_BGP) { + time_t uptime; + struct tm *tm; + + uptime = time(NULL); + uptime -= re->uptime; + tm = gmtime(&uptime); + + if (uptime < ONE_DAY_SECOND) + sprintf(buf, "%02d:%02d:%02d", tm->tm_hour, + tm->tm_min, tm->tm_sec); + else if (uptime < ONE_WEEK_SECOND) + sprintf(buf, "%dd%02dh%02dm", tm->tm_yday, + tm->tm_hour, tm->tm_min); + else + sprintf(buf, "%02dw%dd%02dh", tm->tm_yday / 7, + tm->tm_yday - ((tm->tm_yday / 7) * 7), + tm->tm_hour); + + json_object_string_add(json_route, "uptime", buf); + } + + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + json_nexthop = json_object_new_object(); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) + json_object_boolean_true_add(json_nexthop, + "fib"); + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + json_object_string_add( + json_nexthop, "ip", + inet_ntoa(nexthop->gate.ipv4)); + json_object_string_add(json_nexthop, "afi", + "ipv4"); + + if (nexthop->ifindex) { + json_object_int_add(json_nexthop, + "interfaceIndex", + nexthop->ifindex); + json_object_string_add( + json_nexthop, "interfaceName", + ifindex2ifname(nexthop->ifindex, + re->vrf_id)); + } + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + json_object_string_add( + json_nexthop, "ip", + inet_ntop(AF_INET6, &nexthop->gate.ipv6, + buf, sizeof buf)); + json_object_string_add(json_nexthop, "afi", + "ipv6"); + + if (nexthop->ifindex) { + json_object_int_add(json_nexthop, + "interfaceIndex", + nexthop->ifindex); + json_object_string_add( + json_nexthop, "interfaceName", + ifindex2ifname(nexthop->ifindex, + re->vrf_id)); + } + break; + + case NEXTHOP_TYPE_IFINDEX: + json_object_boolean_true_add( + json_nexthop, "directlyConnected"); + json_object_int_add(json_nexthop, + "interfaceIndex", + nexthop->ifindex); + json_object_string_add( + json_nexthop, "interfaceName", + ifindex2ifname(nexthop->ifindex, + re->vrf_id)); + break; + case NEXTHOP_TYPE_BLACKHOLE: + json_object_boolean_true_add(json_nexthop, + "blackhole"); + break; + default: + break; + } + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + json_object_boolean_true_add(json_nexthop, + "active"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) + json_object_boolean_true_add(json_nexthop, + "onLink"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + json_object_boolean_true_add(json_nexthop, + "recursive"); + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + if (nexthop->src.ipv4.s_addr) { + if (inet_ntop(AF_INET, + &nexthop->src.ipv4, buf, + sizeof buf)) + json_object_string_add( + json_nexthop, "source", + buf); + } + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, + &in6addr_any)) { + if (inet_ntop(AF_INET6, + &nexthop->src.ipv6, buf, + sizeof buf)) + json_object_string_add( + json_nexthop, "source", + buf); + } + break; + default: + break; + } + + if (nexthop->nh_label + && nexthop->nh_label->num_labels) { + json_labels = json_object_new_array(); + + for (int label_index = 0; + label_index + < nexthop->nh_label->num_labels; + label_index++) + json_object_array_add( + json_labels, + json_object_new_int( + nexthop->nh_label->label + [label_index])); + + json_object_object_add(json_nexthop, "labels", + json_labels); + } + + json_object_array_add(json_nexthops, json_nexthop); + } + + json_object_object_add(json_route, "nexthops", json_nexthops); + json_object_array_add(json, json_route); + return; + } + + /* Nexthop information. */ + for (ALL_NEXTHOPS(re->nexthop, nexthop)) { + if (nexthop == re->nexthop) { + /* Prefix information. */ + len = vty_out(vty, "%c", zebra_route_char(re->type)); + if (re->instance) + len += vty_out(vty, "[%d]", re->instance); + len += vty_out( + vty, "%c%c %s", + CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED) + ? '>' + : ' ', + CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB) + ? '*' + : ' ', + srcdest_rnode2str(rn, buf, sizeof buf)); + + /* Distance and metric display. */ + if (re->type != ZEBRA_ROUTE_CONNECT + && re->type != ZEBRA_ROUTE_KERNEL) + len += vty_out(vty, " [%d/%d]", re->distance, + re->metric); + } else + vty_out(vty, " %c%*c", + CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB) + ? '*' + : ' ', + len - 3 + (2 * nexthop_level(nexthop)), ' '); + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + vty_out(vty, " via %s", inet_ntoa(nexthop->gate.ipv4)); + if (nexthop->ifindex) + vty_out(vty, ", %s", + ifindex2ifname(nexthop->ifindex, + re->vrf_id)); + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + vty_out(vty, " via %s", + inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, + sizeof buf)); + if (nexthop->ifindex) + vty_out(vty, ", %s", + ifindex2ifname(nexthop->ifindex, + re->vrf_id)); + break; + + case NEXTHOP_TYPE_IFINDEX: + vty_out(vty, " is directly connected, %s", + ifindex2ifname(nexthop->ifindex, re->vrf_id)); + break; + case NEXTHOP_TYPE_BLACKHOLE: + vty_out(vty, " is directly connected, Null0"); + break; + default: + break; + } + if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + vty_out(vty, " inactive"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) + vty_out(vty, " onlink"); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + vty_out(vty, " (recursive)"); + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + if (nexthop->src.ipv4.s_addr) { + if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf, + sizeof buf)) + vty_out(vty, ", src %s", buf); + } + break; + case NEXTHOP_TYPE_IPV6: + case NEXTHOP_TYPE_IPV6_IFINDEX: + if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) { + if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf, + sizeof buf)) + vty_out(vty, ", src %s", buf); + } + break; + default: + break; + } + + /* Label information */ + if (nexthop->nh_label && nexthop->nh_label->num_labels) { + vty_out(vty, ", label %s", + mpls_label2str(nexthop->nh_label->num_labels, + nexthop->nh_label->label, buf, + sizeof buf, 1)); + } + + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE)) + vty_out(vty, ", bh"); + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_REJECT)) + vty_out(vty, ", rej"); + + if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF + || re->type == ZEBRA_ROUTE_ISIS + || re->type == ZEBRA_ROUTE_NHRP + || re->type == ZEBRA_ROUTE_TABLE + || re->type == ZEBRA_ROUTE_BGP) { + time_t uptime; + struct tm *tm; + + uptime = time(NULL); + uptime -= re->uptime; + tm = gmtime(&uptime); + + if (uptime < ONE_DAY_SECOND) + vty_out(vty, ", %02d:%02d:%02d", tm->tm_hour, + tm->tm_min, tm->tm_sec); + else if (uptime < ONE_WEEK_SECOND) + vty_out(vty, ", %dd%02dh%02dm", tm->tm_yday, + tm->tm_hour, tm->tm_min); + else + vty_out(vty, ", %02dw%dd%02dh", tm->tm_yday / 7, + tm->tm_yday - ((tm->tm_yday / 7) * 7), + tm->tm_hour); + } + vty_out(vty, "\n"); + } +} + +static bool use_fib(struct cmd_token *token) +{ + return strncmp(token->arg, "route", strlen(token->arg)); +} + +static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi, + safi_t safi, bool use_fib, u_char use_json, + route_tag_t tag, struct prefix *longer_prefix_p, + bool supernets_only, int type, + u_short ospf_instance_id) +{ + struct route_table *table; + struct route_node *rn; + struct route_entry *re; + int first = 1; + struct zebra_vrf *zvrf = NULL; + char buf[BUFSIZ]; + json_object *json = NULL; + json_object *json_prefix = NULL; + u_int32_t addr; + + if (!(zvrf = zebra_vrf_lookup_by_name(vrf_name))) { + if (use_json) + vty_out(vty, "{}\n"); + else + vty_out(vty, "vrf %s not defined\n", vrf_name); + return CMD_SUCCESS; + } + + if (zvrf_id(zvrf) == VRF_UNKNOWN) { + if (use_json) + vty_out(vty, "{}\n"); + else + vty_out(vty, "vrf %s inactive\n", vrf_name); + return CMD_SUCCESS; + } + + table = zebra_vrf_table(afi, safi, zvrf_id(zvrf)); + if (!table) { + if (use_json) + vty_out(vty, "{}\n"); + return CMD_SUCCESS; + } + + if (use_json) + json = json_object_new_object(); + + /* Show all routes. */ + for (rn = route_top(table); rn; rn = route_next(rn)) { + RNODE_FOREACH_RE(rn, re) + { + if (use_fib + && !CHECK_FLAG(re->status, + ROUTE_ENTRY_SELECTED_FIB)) + continue; + + if (tag && re->tag != tag) + continue; + + if (longer_prefix_p + && !prefix_match(longer_prefix_p, &rn->p)) + continue; + + /* This can only be true when the afi is IPv4 */ + if (supernets_only) { + addr = ntohl(rn->p.u.prefix4.s_addr); + + if (IN_CLASSC(addr) && rn->p.prefixlen >= 24) + continue; + + if (IN_CLASSB(addr) && rn->p.prefixlen >= 16) + continue; + + if (IN_CLASSA(addr) && rn->p.prefixlen >= 8) + continue; + } + + if (type && re->type != type) + continue; + + if (ospf_instance_id + && (re->type != ZEBRA_ROUTE_OSPF + || re->instance != ospf_instance_id)) + continue; + + if (use_json) { + if (!json_prefix) + json_prefix = json_object_new_array(); + } else { + if (first) { + if (afi == AFI_IP) + vty_out(vty, + SHOW_ROUTE_V4_HEADER); + else + vty_out(vty, + SHOW_ROUTE_V6_HEADER); + + if (zvrf_id(zvrf) != VRF_DEFAULT) + vty_out(vty, "\nVRF %s:\n", + zvrf_name(zvrf)); + + first = 0; + } + } + + vty_show_ip_route(vty, rn, re, json_prefix); + } + + if (json_prefix) { + prefix2str(&rn->p, buf, sizeof buf); + json_object_object_add(json, buf, json_prefix); + json_prefix = NULL; + } + } + + if (use_json) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } + + return CMD_SUCCESS; } DEFUN (show_ip_nht, @@ -1221,14 +1247,14 @@ DEFUN (show_ip_nht, "IP nexthop tracking table\n" VRF_CMD_HELP_STR) { - int idx_vrf = 4; - vrf_id_t vrf_id = VRF_DEFAULT; + int idx_vrf = 4; + vrf_id_t vrf_id = VRF_DEFAULT; - if (argc == 5) - VRF_GET_ID (vrf_id, argv[idx_vrf]->arg); + if (argc == 5) + VRF_GET_ID(vrf_id, argv[idx_vrf]->arg); - zebra_print_rnh_table(vrf_id, AF_INET, vty, RNH_NEXTHOP_TYPE); - return CMD_SUCCESS; + zebra_print_rnh_table(vrf_id, AF_INET, vty, RNH_NEXTHOP_TYPE); + return CMD_SUCCESS; } @@ -1240,17 +1266,17 @@ DEFUN (show_ip_nht_vrf_all, "IP nexthop tracking table\n" VRF_ALL_CMD_HELP_STR) { - struct vrf *vrf; - struct zebra_vrf *zvrf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if ((zvrf = vrf->info) != NULL) - { - vty_out (vty, "\nVRF %s:\n", zvrf_name(zvrf)); - zebra_print_rnh_table(zvrf_id (zvrf), AF_INET, vty, RNH_NEXTHOP_TYPE); - } + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) { + vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf)); + zebra_print_rnh_table(zvrf_id(zvrf), AF_INET, vty, + RNH_NEXTHOP_TYPE); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ipv6_nht, @@ -1261,14 +1287,14 @@ DEFUN (show_ipv6_nht, "IPv6 nexthop tracking table\n" VRF_CMD_HELP_STR) { - int idx_vrf = 4; - vrf_id_t vrf_id = VRF_DEFAULT; + int idx_vrf = 4; + vrf_id_t vrf_id = VRF_DEFAULT; - if (argc == 5) - VRF_GET_ID (vrf_id, argv[idx_vrf]->arg); + if (argc == 5) + VRF_GET_ID(vrf_id, argv[idx_vrf]->arg); - zebra_print_rnh_table(vrf_id, AF_INET6, vty, RNH_NEXTHOP_TYPE); - return CMD_SUCCESS; + zebra_print_rnh_table(vrf_id, AF_INET6, vty, RNH_NEXTHOP_TYPE); + return CMD_SUCCESS; } @@ -1280,17 +1306,17 @@ DEFUN (show_ipv6_nht_vrf_all, "IPv6 nexthop tracking table\n" VRF_ALL_CMD_HELP_STR) { - struct vrf *vrf; - struct zebra_vrf *zvrf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if ((zvrf = vrf->info) != NULL) - { - vty_out (vty, "\nVRF %s:\n", zvrf_name(zvrf)); - zebra_print_rnh_table(zvrf_id (zvrf), AF_INET6, vty, RNH_NEXTHOP_TYPE); - } + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) { + vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf)); + zebra_print_rnh_table(zvrf_id(zvrf), AF_INET6, vty, + RNH_NEXTHOP_TYPE); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_nht_default_route, @@ -1300,12 +1326,12 @@ DEFUN (ip_nht_default_route, "Filter Next Hop tracking route resolution\n" "Resolve via default route\n") { - if (zebra_rnh_ip_default_route) - return CMD_SUCCESS; + if (zebra_rnh_ip_default_route) + return CMD_SUCCESS; - zebra_rnh_ip_default_route = 1; - zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); - return CMD_SUCCESS; + zebra_rnh_ip_default_route = 1; + zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + return CMD_SUCCESS; } DEFUN (no_ip_nht_default_route, @@ -1316,12 +1342,12 @@ DEFUN (no_ip_nht_default_route, "Filter Next Hop tracking route resolution\n" "Resolve via default route\n") { - if (!zebra_rnh_ip_default_route) - return CMD_SUCCESS; + if (!zebra_rnh_ip_default_route) + return CMD_SUCCESS; - zebra_rnh_ip_default_route = 0; - zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); - return CMD_SUCCESS; + zebra_rnh_ip_default_route = 0; + zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + return CMD_SUCCESS; } DEFUN (ipv6_nht_default_route, @@ -1331,12 +1357,12 @@ DEFUN (ipv6_nht_default_route, "Filter Next Hop tracking route resolution\n" "Resolve via default route\n") { - if (zebra_rnh_ipv6_default_route) - return CMD_SUCCESS; + if (zebra_rnh_ipv6_default_route) + return CMD_SUCCESS; - zebra_rnh_ipv6_default_route = 1; - zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); - return CMD_SUCCESS; + zebra_rnh_ipv6_default_route = 1; + zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); + return CMD_SUCCESS; } DEFUN (no_ipv6_nht_default_route, @@ -1347,12 +1373,12 @@ DEFUN (no_ipv6_nht_default_route, "Filter Next Hop tracking route resolution\n" "Resolve via default route\n") { - if (!zebra_rnh_ipv6_default_route) - return CMD_SUCCESS; + if (!zebra_rnh_ipv6_default_route) + return CMD_SUCCESS; - zebra_rnh_ipv6_default_route = 0; - zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); - return CMD_SUCCESS; + zebra_rnh_ipv6_default_route = 0; + zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); + return CMD_SUCCESS; } DEFUN (show_ip_route, @@ -1373,99 +1399,96 @@ DEFUN (show_ip_route, "Instance ID\n" JSON_STR) { - bool uf = use_fib(argv[2]); - struct route_table *table; - int vrf_all = 0; - route_tag_t tag = 0; - vrf_id_t vrf_id = VRF_DEFAULT; - struct vrf *vrf; - struct zebra_vrf *zvrf; - int uj = use_json(argc, argv); - int idx = 0; - struct prefix p; - bool longer_prefixes = false; - bool supernets_only = false; - int type = 0; - u_short ospf_instance_id = 0; - - if (argv_find (argv, argc, "vrf", &idx)) - { - if (strmatch(argv[idx+1]->arg, "all")) - vrf_all = 1; - else - VRF_GET_ID (vrf_id, argv[idx+1]->arg); - } - - if (argv_find (argv, argc, "tag", &idx)) - tag = strtoul(argv[idx + 1]->arg, NULL, 10); - - else if (argv_find (argv, argc, "A.B.C.D/M", &idx)) - { - str2prefix (argv[idx]->arg, &p); - longer_prefixes = true; - } - - else if (argv_find (argv, argc, "supernets_only", &idx)) - supernets_only = true; - - else - { - if (argv_find (argv, argc, "kernel", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "babel", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "connected", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "static", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "rip", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "ospf", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "isis", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "bgp", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "pim", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "eigrp", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "nhrp", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "table", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - else if (argv_find (argv, argc, "vnc", &idx)) - type = proto_redistnum (AFI_IP, argv[idx]->text); - - if (argv_find (argv, argc, "(1-65535)", &idx)) - ospf_instance_id = strtoul(argv[idx]->arg, NULL, 10); - - if (type < 0) - { - vty_out (vty, "Unknown route type\n"); - return CMD_WARNING; - } - } - - if (vrf_all) - { - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if ((zvrf = vrf->info) == NULL || - (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) - continue; - - do_show_ip_route (vty, zvrf_name (zvrf), AFI_IP, SAFI_UNICAST, uf, uj, tag, - longer_prefixes ? &p : NULL, supernets_only, type, ospf_instance_id); - } - } - else - { - vrf = vrf_lookup_by_id (vrf_id); - do_show_ip_route (vty, vrf->name, AFI_IP, SAFI_UNICAST, uf, uj, tag, - longer_prefixes ? &p : NULL, supernets_only, type, ospf_instance_id); - } - return CMD_SUCCESS; + bool uf = use_fib(argv[2]); + struct route_table *table; + int vrf_all = 0; + route_tag_t tag = 0; + vrf_id_t vrf_id = VRF_DEFAULT; + struct vrf *vrf; + struct zebra_vrf *zvrf; + int uj = use_json(argc, argv); + int idx = 0; + struct prefix p; + bool longer_prefixes = false; + bool supernets_only = false; + int type = 0; + u_short ospf_instance_id = 0; + + if (argv_find(argv, argc, "vrf", &idx)) { + if (strmatch(argv[idx + 1]->arg, "all")) + vrf_all = 1; + else + VRF_GET_ID(vrf_id, argv[idx + 1]->arg); + } + + if (argv_find(argv, argc, "tag", &idx)) + tag = strtoul(argv[idx + 1]->arg, NULL, 10); + + else if (argv_find(argv, argc, "A.B.C.D/M", &idx)) { + str2prefix(argv[idx]->arg, &p); + longer_prefixes = true; + } + + else if (argv_find(argv, argc, "supernets_only", &idx)) + supernets_only = true; + + else { + if (argv_find(argv, argc, "kernel", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "babel", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "connected", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "static", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "rip", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "ospf", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "isis", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "bgp", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "pim", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "eigrp", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "nhrp", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "table", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + else if (argv_find(argv, argc, "vnc", &idx)) + type = proto_redistnum(AFI_IP, argv[idx]->text); + + if (argv_find(argv, argc, "(1-65535)", &idx)) + ospf_instance_id = strtoul(argv[idx]->arg, NULL, 10); + + if (type < 0) { + vty_out(vty, "Unknown route type\n"); + return CMD_WARNING; + } + } + + if (vrf_all) { + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if ((zvrf = vrf->info) == NULL + || (table = zvrf->table[AFI_IP][SAFI_UNICAST]) + == NULL) + continue; + + do_show_ip_route( + vty, zvrf_name(zvrf), AFI_IP, SAFI_UNICAST, uf, + uj, tag, longer_prefixes ? &p : NULL, + supernets_only, type, ospf_instance_id); + } + } else { + vrf = vrf_lookup_by_id(vrf_id); + do_show_ip_route(vty, vrf->name, AFI_IP, SAFI_UNICAST, uf, uj, + tag, longer_prefixes ? &p : NULL, + supernets_only, type, ospf_instance_id); + } + return CMD_SUCCESS; } DEFUN (show_ip_route_addr, @@ -1477,44 +1500,39 @@ DEFUN (show_ip_route_addr, VRF_CMD_HELP_STR "Network in the IP routing table to display\n") { - int ret; - struct prefix_ipv4 p; - struct route_table *table; - struct route_node *rn; - vrf_id_t vrf_id = VRF_DEFAULT; - - if (strmatch(argv[3]->text, "vrf")) - { - VRF_GET_ID (vrf_id, argv[4]->arg); - ret = str2prefix_ipv4 (argv[5]->arg, &p); - } - else - { - ret = str2prefix_ipv4 (argv[3]->arg, &p); - } + int ret; + struct prefix_ipv4 p; + struct route_table *table; + struct route_node *rn; + vrf_id_t vrf_id = VRF_DEFAULT; + + if (strmatch(argv[3]->text, "vrf")) { + VRF_GET_ID(vrf_id, argv[4]->arg); + ret = str2prefix_ipv4(argv[5]->arg, &p); + } else { + ret = str2prefix_ipv4(argv[3]->arg, &p); + } - if (ret <= 0) - { - vty_out (vty, "%% Malformed IPv4 address\n"); - return CMD_WARNING; - } + if (ret <= 0) { + vty_out(vty, "%% Malformed IPv4 address\n"); + return CMD_WARNING; + } - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); + if (!table) + return CMD_SUCCESS; - rn = route_node_match (table, (struct prefix *) &p); - if (! rn) - { - vty_out (vty, "%% Network not in table\n"); - return CMD_WARNING; - } + rn = route_node_match(table, (struct prefix *)&p); + if (!rn) { + vty_out(vty, "%% Network not in table\n"); + return CMD_WARNING; + } - vty_show_ip_route_detail (vty, rn, 0); + vty_show_ip_route_detail(vty, rn, 0); - route_unlock_node (rn); + route_unlock_node(rn); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_route_prefix, @@ -1526,110 +1544,102 @@ DEFUN (show_ip_route_prefix, VRF_CMD_HELP_STR "IP prefix /, e.g., 35.0.0.0/8\n") { - int ret; - struct prefix_ipv4 p; - struct route_table *table; - struct route_node *rn; - vrf_id_t vrf_id = VRF_DEFAULT; - - if (strmatch(argv[3]->text, "vrf")) - { - VRF_GET_ID (vrf_id, argv[4]->arg); - ret = str2prefix_ipv4 (argv[5]->arg, &p); - } - else - { - ret = str2prefix_ipv4 (argv[3]->arg, &p); - } + int ret; + struct prefix_ipv4 p; + struct route_table *table; + struct route_node *rn; + vrf_id_t vrf_id = VRF_DEFAULT; + + if (strmatch(argv[3]->text, "vrf")) { + VRF_GET_ID(vrf_id, argv[4]->arg); + ret = str2prefix_ipv4(argv[5]->arg, &p); + } else { + ret = str2prefix_ipv4(argv[3]->arg, &p); + } - if (ret <= 0) - { - vty_out (vty, "%% Malformed IPv4 address\n"); - return CMD_WARNING; - } + if (ret <= 0) { + vty_out(vty, "%% Malformed IPv4 address\n"); + return CMD_WARNING; + } - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); + if (!table) + return CMD_SUCCESS; - rn = route_node_match (table, (struct prefix *) &p); - if (! rn || rn->p.prefixlen != p.prefixlen) - { - vty_out (vty, "%% Network not in table\n"); - return CMD_WARNING; - } + rn = route_node_match(table, (struct prefix *)&p); + if (!rn || rn->p.prefixlen != p.prefixlen) { + vty_out(vty, "%% Network not in table\n"); + return CMD_WARNING; + } - vty_show_ip_route_detail (vty, rn, 0); + vty_show_ip_route_detail(vty, rn, 0); - route_unlock_node (rn); + route_unlock_node(rn); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static void -vty_show_ip_route_summary (struct vty *vty, struct route_table *table) +static void vty_show_ip_route_summary(struct vty *vty, + struct route_table *table) { - struct route_node *rn; - struct route_entry *re; + struct route_node *rn; + struct route_entry *re; #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1) - u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1]; - u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1]; - u_int32_t i; - u_int32_t is_ibgp; - - memset (&rib_cnt, 0, sizeof(rib_cnt)); - memset (&fib_cnt, 0, sizeof(fib_cnt)); - for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) - RNODE_FOREACH_RE (rn, re) - { - is_ibgp = (re->type == ZEBRA_ROUTE_BGP && - CHECK_FLAG (re->flags, ZEBRA_FLAG_IBGP)); - - rib_cnt[ZEBRA_ROUTE_TOTAL]++; - if (is_ibgp) - rib_cnt[ZEBRA_ROUTE_IBGP]++; - else - rib_cnt[re->type]++; - - if (CHECK_FLAG (re->flags, ZEBRA_FLAG_SELECTED)) - { - fib_cnt[ZEBRA_ROUTE_TOTAL]++; - - if (is_ibgp) - fib_cnt[ZEBRA_ROUTE_IBGP]++; - else - fib_cnt[re->type]++; - } - } - - vty_out (vty, "%-20s %-20s %s (vrf %s)\n", - "Route Source", "Routes", "FIB", - zvrf_name(((rib_table_info_t *)table->info)->zvrf)); - - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - if ((rib_cnt[i] > 0) || - (i == ZEBRA_ROUTE_BGP && rib_cnt[ZEBRA_ROUTE_IBGP] > 0)) - { - if (i == ZEBRA_ROUTE_BGP) - { - vty_out (vty, "%-20s %-20d %-20d \n", "ebgp", - rib_cnt[ZEBRA_ROUTE_BGP],fib_cnt[ZEBRA_ROUTE_BGP]); - vty_out (vty, "%-20s %-20d %-20d \n", "ibgp", - rib_cnt[ZEBRA_ROUTE_IBGP],fib_cnt[ZEBRA_ROUTE_IBGP]); - } - else - vty_out (vty, "%-20s %-20d %-20d \n", zebra_route_string(i), - rib_cnt[i], fib_cnt[i]); - } - } - - vty_out (vty, "------\n"); - vty_out (vty, "%-20s %-20d %-20d \n", "Totals", rib_cnt[ZEBRA_ROUTE_TOTAL], - fib_cnt[ZEBRA_ROUTE_TOTAL]); - vty_out (vty, "\n"); + u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1]; + u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1]; + u_int32_t i; + u_int32_t is_ibgp; + + memset(&rib_cnt, 0, sizeof(rib_cnt)); + memset(&fib_cnt, 0, sizeof(fib_cnt)); + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) + RNODE_FOREACH_RE(rn, re) + { + is_ibgp = (re->type == ZEBRA_ROUTE_BGP + && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)); + + rib_cnt[ZEBRA_ROUTE_TOTAL]++; + if (is_ibgp) + rib_cnt[ZEBRA_ROUTE_IBGP]++; + else + rib_cnt[re->type]++; + + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) { + fib_cnt[ZEBRA_ROUTE_TOTAL]++; + + if (is_ibgp) + fib_cnt[ZEBRA_ROUTE_IBGP]++; + else + fib_cnt[re->type]++; + } + } + + vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source", "Routes", + "FIB", zvrf_name(((rib_table_info_t *)table->info)->zvrf)); + + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if ((rib_cnt[i] > 0) || (i == ZEBRA_ROUTE_BGP + && rib_cnt[ZEBRA_ROUTE_IBGP] > 0)) { + if (i == ZEBRA_ROUTE_BGP) { + vty_out(vty, "%-20s %-20d %-20d \n", "ebgp", + rib_cnt[ZEBRA_ROUTE_BGP], + fib_cnt[ZEBRA_ROUTE_BGP]); + vty_out(vty, "%-20s %-20d %-20d \n", "ibgp", + rib_cnt[ZEBRA_ROUTE_IBGP], + fib_cnt[ZEBRA_ROUTE_IBGP]); + } else + vty_out(vty, "%-20s %-20d %-20d \n", + zebra_route_string(i), rib_cnt[i], + fib_cnt[i]); + } + } + + vty_out(vty, "------\n"); + vty_out(vty, "%-20s %-20d %-20d \n", "Totals", + rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]); + vty_out(vty, "\n"); } /* @@ -1639,75 +1649,75 @@ vty_show_ip_route_summary (struct vty *vty, struct route_table *table) * protocols on the box. * */ -static void -vty_show_ip_route_summary_prefix (struct vty *vty, struct route_table *table) +static void vty_show_ip_route_summary_prefix(struct vty *vty, + struct route_table *table) { - struct route_node *rn; - struct route_entry *re; - struct nexthop *nexthop; + struct route_node *rn; + struct route_entry *re; + struct nexthop *nexthop; #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1) - u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1]; - u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1]; - u_int32_t i; - int cnt; - - memset (&rib_cnt, 0, sizeof(rib_cnt)); - memset (&fib_cnt, 0, sizeof(fib_cnt)); - for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) - RNODE_FOREACH_RE (rn, re) - { - - /* - * In case of ECMP, count only once. - */ - cnt = 0; - for (nexthop = re->nexthop; (!cnt && nexthop); nexthop = nexthop->next) - { - cnt++; - rib_cnt[ZEBRA_ROUTE_TOTAL]++; - rib_cnt[re->type]++; - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - { - fib_cnt[ZEBRA_ROUTE_TOTAL]++; - fib_cnt[re->type]++; - } - if (re->type == ZEBRA_ROUTE_BGP && - CHECK_FLAG (re->flags, ZEBRA_FLAG_IBGP)) - { - rib_cnt[ZEBRA_ROUTE_IBGP]++; - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - fib_cnt[ZEBRA_ROUTE_IBGP]++; - } - } - } - - vty_out (vty, "%-20s %-20s %s (vrf %s)\n", - "Route Source", "Prefix Routes", "FIB", - zvrf_name(((rib_table_info_t *)table->info)->zvrf)); - - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - if (rib_cnt[i] > 0) - { - if (i == ZEBRA_ROUTE_BGP) - { - vty_out (vty, "%-20s %-20d %-20d \n", "ebgp", - rib_cnt[ZEBRA_ROUTE_BGP] - rib_cnt[ZEBRA_ROUTE_IBGP], - fib_cnt[ZEBRA_ROUTE_BGP] - fib_cnt[ZEBRA_ROUTE_IBGP]); - vty_out (vty, "%-20s %-20d %-20d \n", "ibgp", - rib_cnt[ZEBRA_ROUTE_IBGP],fib_cnt[ZEBRA_ROUTE_IBGP]); - } - else - vty_out (vty, "%-20s %-20d %-20d \n", zebra_route_string(i), - rib_cnt[i], fib_cnt[i]); - } - } - - vty_out (vty, "------\n"); - vty_out (vty, "%-20s %-20d %-20d \n", "Totals", rib_cnt[ZEBRA_ROUTE_TOTAL], - fib_cnt[ZEBRA_ROUTE_TOTAL]); - vty_out (vty, "\n"); + u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1]; + u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1]; + u_int32_t i; + int cnt; + + memset(&rib_cnt, 0, sizeof(rib_cnt)); + memset(&fib_cnt, 0, sizeof(fib_cnt)); + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) + RNODE_FOREACH_RE(rn, re) + { + + /* + * In case of ECMP, count only once. + */ + cnt = 0; + for (nexthop = re->nexthop; (!cnt && nexthop); + nexthop = nexthop->next) { + cnt++; + rib_cnt[ZEBRA_ROUTE_TOTAL]++; + rib_cnt[re->type]++; + if (CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB)) { + fib_cnt[ZEBRA_ROUTE_TOTAL]++; + fib_cnt[re->type]++; + } + if (re->type == ZEBRA_ROUTE_BGP + && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)) { + rib_cnt[ZEBRA_ROUTE_IBGP]++; + if (CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB)) + fib_cnt[ZEBRA_ROUTE_IBGP]++; + } + } + } + + vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source", + "Prefix Routes", "FIB", + zvrf_name(((rib_table_info_t *)table->info)->zvrf)); + + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (rib_cnt[i] > 0) { + if (i == ZEBRA_ROUTE_BGP) { + vty_out(vty, "%-20s %-20d %-20d \n", "ebgp", + rib_cnt[ZEBRA_ROUTE_BGP] + - rib_cnt[ZEBRA_ROUTE_IBGP], + fib_cnt[ZEBRA_ROUTE_BGP] + - fib_cnt[ZEBRA_ROUTE_IBGP]); + vty_out(vty, "%-20s %-20d %-20d \n", "ibgp", + rib_cnt[ZEBRA_ROUTE_IBGP], + fib_cnt[ZEBRA_ROUTE_IBGP]); + } else + vty_out(vty, "%-20s %-20d %-20d \n", + zebra_route_string(i), rib_cnt[i], + fib_cnt[i]); + } + } + + vty_out(vty, "------\n"); + vty_out(vty, "%-20s %-20d %-20d \n", "Totals", + rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]); + vty_out(vty, "\n"); } /* Show route summary. */ @@ -1720,19 +1730,19 @@ DEFUN (show_ip_route_summary, VRF_CMD_HELP_STR "Summary of all routes\n") { - struct route_table *table; - vrf_id_t vrf_id = VRF_DEFAULT; + struct route_table *table; + vrf_id_t vrf_id = VRF_DEFAULT; - if (strmatch(argv[3]->text, "vrf")) - VRF_GET_ID (vrf_id, argv[4]->arg); + if (strmatch(argv[3]->text, "vrf")) + VRF_GET_ID(vrf_id, argv[4]->arg); - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); + if (!table) + return CMD_SUCCESS; - vty_show_ip_route_summary (vty, table); + vty_show_ip_route_summary(vty, table); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Show route summary prefix. */ @@ -1746,19 +1756,19 @@ DEFUN (show_ip_route_summary_prefix, "Summary of all routes\n" "Prefix routes\n") { - struct route_table *table; - vrf_id_t vrf_id = VRF_DEFAULT; + struct route_table *table; + vrf_id_t vrf_id = VRF_DEFAULT; - if (strmatch(argv[3]->text, "vrf")) - VRF_GET_ID (vrf_id, argv[4]->arg); + if (strmatch(argv[3]->text, "vrf")) + VRF_GET_ID(vrf_id, argv[4]->arg); - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); + if (!table) + return CMD_SUCCESS; - vty_show_ip_route_summary_prefix (vty, table); + vty_show_ip_route_summary_prefix(vty, table); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1771,37 +1781,36 @@ DEFUN (show_ip_route_vrf_all_addr, VRF_ALL_CMD_HELP_STR "Network in the IP routing table to display\n") { - int idx_ipv4 = 5; - int ret; - struct prefix_ipv4 p; - struct route_table *table; - struct route_node *rn; - struct vrf *vrf; - struct zebra_vrf *zvrf; - - ret = str2prefix_ipv4 (argv[idx_ipv4]->arg, &p); - if (ret <= 0) - { - vty_out (vty, "%% Malformed IPv4 address\n"); - return CMD_WARNING; - } + int idx_ipv4 = 5; + int ret; + struct prefix_ipv4 p; + struct route_table *table; + struct route_node *rn; + struct vrf *vrf; + struct zebra_vrf *zvrf; + + ret = str2prefix_ipv4(argv[idx_ipv4]->arg, &p); + if (ret <= 0) { + vty_out(vty, "%% Malformed IPv4 address\n"); + return CMD_WARNING; + } - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if ((zvrf = vrf->info) == NULL || - (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) - continue; + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if ((zvrf = vrf->info) == NULL + || (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) + continue; - rn = route_node_match (table, (struct prefix *) &p); - if (! rn) - continue; + rn = route_node_match(table, (struct prefix *)&p); + if (!rn) + continue; - vty_show_ip_route_detail (vty, rn, 0); + vty_show_ip_route_detail(vty, rn, 0); - route_unlock_node (rn); - } + route_unlock_node(rn); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_route_vrf_all_prefix, @@ -1813,42 +1822,40 @@ DEFUN (show_ip_route_vrf_all_prefix, VRF_ALL_CMD_HELP_STR "IP prefix /, e.g., 35.0.0.0/8\n") { - int idx_ipv4_prefixlen = 5; - int ret; - struct prefix_ipv4 p; - struct route_table *table; - struct route_node *rn; - struct vrf *vrf; - struct zebra_vrf *zvrf; - - ret = str2prefix_ipv4 (argv[idx_ipv4_prefixlen]->arg, &p); - if (ret <= 0) - { - vty_out (vty, "%% Malformed IPv4 address\n"); - return CMD_WARNING; - } + int idx_ipv4_prefixlen = 5; + int ret; + struct prefix_ipv4 p; + struct route_table *table; + struct route_node *rn; + struct vrf *vrf; + struct zebra_vrf *zvrf; + + ret = str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + if (ret <= 0) { + vty_out(vty, "%% Malformed IPv4 address\n"); + return CMD_WARNING; + } - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if ((zvrf = vrf->info) == NULL || - (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) - continue; + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if ((zvrf = vrf->info) == NULL + || (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL) + continue; - rn = route_node_match (table, (struct prefix *) &p); - if (! rn) - continue; - if (rn->p.prefixlen != p.prefixlen) - { - route_unlock_node (rn); - continue; - } + rn = route_node_match(table, (struct prefix *)&p); + if (!rn) + continue; + if (rn->p.prefixlen != p.prefixlen) { + route_unlock_node(rn); + continue; + } - vty_show_ip_route_detail (vty, rn, 0); + vty_show_ip_route_detail(vty, rn, 0); - route_unlock_node (rn); - } + route_unlock_node(rn); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_route_vrf_all_summary, @@ -1860,14 +1867,15 @@ DEFUN (show_ip_route_vrf_all_summary, VRF_ALL_CMD_HELP_STR "Summary of all routes\n") { - struct vrf *vrf; - struct zebra_vrf *zvrf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if ((zvrf = vrf->info) != NULL) - vty_show_ip_route_summary (vty, zvrf->table[AFI_IP][SAFI_UNICAST]); + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) + vty_show_ip_route_summary(vty, + zvrf->table[AFI_IP][SAFI_UNICAST]); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ip_route_vrf_all_summary_prefix, @@ -1880,275 +1888,282 @@ DEFUN (show_ip_route_vrf_all_summary_prefix, "Summary of all routes\n" "Prefix routes\n") { - struct vrf *vrf; - struct zebra_vrf *zvrf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if ((zvrf = vrf->info) != NULL) - vty_show_ip_route_summary_prefix (vty, zvrf->table[AFI_IP][SAFI_UNICAST]); + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) + vty_show_ip_route_summary_prefix( + vty, zvrf->table[AFI_IP][SAFI_UNICAST]); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Write static route configuration. */ -static int -static_config (struct vty *vty, afi_t afi, safi_t safi, const char *cmd) -{ - struct route_node *rn; - struct static_route *si; - struct route_table *stable; - struct vrf *vrf; - struct zebra_vrf *zvrf; - char buf[SRCDEST2STR_BUFFER]; - int write =0; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if (!(zvrf = vrf->info)) - continue; - if ((stable = zvrf->stable[afi][safi]) == NULL) - continue; - - for (rn = route_top (stable); rn; rn = srcdest_route_next (rn)) - for (si = rn->info; si; si = si->next) - { - vty_out (vty, "%s %s", cmd, srcdest_rnode2str (rn, buf, sizeof buf)); - - switch (si->type) - { - case STATIC_IPV4_GATEWAY: - vty_out (vty, " %s", inet_ntoa (si->addr.ipv4)); - break; - case STATIC_IPV6_GATEWAY: - vty_out (vty, " %s", inet_ntop (AF_INET6, &si->addr.ipv6, buf, sizeof buf)); - break; - case STATIC_IFINDEX: - vty_out (vty, " %s", si->ifname); - break; - case STATIC_BLACKHOLE: - vty_out (vty, " Null0"); - break; - case STATIC_IPV6_GATEWAY_IFINDEX: - vty_out (vty, " %s %s", - inet_ntop (AF_INET6, &si->addr.ipv6, buf, sizeof buf), - ifindex2ifname (si->ifindex, si->vrf_id)); - break; - } - - /* flags are incompatible with STATIC_BLACKHOLE */ - if (si->type != STATIC_BLACKHOLE) - { - if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT)) - vty_out (vty, " %s", "reject"); - - if (CHECK_FLAG(si->flags, ZEBRA_FLAG_BLACKHOLE)) - vty_out (vty, " %s", "blackhole"); - } - - if (si->tag) - vty_out (vty, " tag %"ROUTE_TAG_PRI, si->tag); - - if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) - vty_out (vty, " %d", si->distance); - - if (si->vrf_id != VRF_DEFAULT) - vty_out (vty, " vrf %s", zvrf_name (zvrf)); - - /* Label information */ - if (si->snh_label.num_labels) - vty_out (vty, " label %s", - mpls_label2str (si->snh_label.num_labels, - si->snh_label.label, buf, sizeof buf, 0)); - - vty_out (vty, "\n"); - - write = 1; - } - } - return write; +static int static_config(struct vty *vty, afi_t afi, safi_t safi, + const char *cmd) +{ + struct route_node *rn; + struct static_route *si; + struct route_table *stable; + struct vrf *vrf; + struct zebra_vrf *zvrf; + char buf[SRCDEST2STR_BUFFER]; + int write = 0; + + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if (!(zvrf = vrf->info)) + continue; + if ((stable = zvrf->stable[afi][safi]) == NULL) + continue; + + for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) + for (si = rn->info; si; si = si->next) { + vty_out(vty, "%s %s", cmd, + srcdest_rnode2str(rn, buf, sizeof buf)); + + switch (si->type) { + case STATIC_IPV4_GATEWAY: + vty_out(vty, " %s", + inet_ntoa(si->addr.ipv4)); + break; + case STATIC_IPV6_GATEWAY: + vty_out(vty, " %s", + inet_ntop(AF_INET6, + &si->addr.ipv6, buf, + sizeof buf)); + break; + case STATIC_IFINDEX: + vty_out(vty, " %s", si->ifname); + break; + case STATIC_BLACKHOLE: + vty_out(vty, " Null0"); + break; + case STATIC_IPV6_GATEWAY_IFINDEX: + vty_out(vty, " %s %s", + inet_ntop(AF_INET6, + &si->addr.ipv6, buf, + sizeof buf), + ifindex2ifname(si->ifindex, + si->vrf_id)); + break; + } + + /* flags are incompatible with STATIC_BLACKHOLE + */ + if (si->type != STATIC_BLACKHOLE) { + if (CHECK_FLAG(si->flags, + ZEBRA_FLAG_REJECT)) + vty_out(vty, " %s", "reject"); + + if (CHECK_FLAG(si->flags, + ZEBRA_FLAG_BLACKHOLE)) + vty_out(vty, " %s", + "blackhole"); + } + + if (si->tag) + vty_out(vty, " tag %" ROUTE_TAG_PRI, + si->tag); + + if (si->distance + != ZEBRA_STATIC_DISTANCE_DEFAULT) + vty_out(vty, " %d", si->distance); + + if (si->vrf_id != VRF_DEFAULT) + vty_out(vty, " vrf %s", + zvrf_name(zvrf)); + + /* Label information */ + if (si->snh_label.num_labels) + vty_out(vty, " label %s", + mpls_label2str( + si->snh_label + .num_labels, + si->snh_label.label, + buf, sizeof buf, 0)); + + vty_out(vty, "\n"); + + write = 1; + } + } + return write; } /* General fucntion for IPv6 static route. */ -int -static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, - const char *src_str, - const char *gate_str, const char *ifname, - const char *flag_str, const char *tag_str, - const char *distance_str, const char *vrf_id_str, - const char *label_str) -{ - int ret; - u_char distance; - struct prefix p, src; - struct prefix_ipv6 *src_p = NULL; - struct in6_addr *gate = NULL; - struct in6_addr gate_addr; - u_char type = STATIC_BLACKHOLE; - u_char flag = 0; - route_tag_t tag = 0; - unsigned int ifindex = 0; - struct interface *ifp = NULL; - struct zebra_vrf *zvrf; - struct static_nh_label snh_label; - - ret = str2prefix (dest_str, &p); - if (ret <= 0) - { - vty_out (vty, "%% Malformed address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (src_str) - { - ret = str2prefix (src_str, &src); - if (ret <= 0 || src.family != AF_INET6) - { - vty_out (vty, "%% Malformed source address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - src_p = (struct prefix_ipv6*)&src; - } - - /* Apply mask for given prefix. */ - apply_mask (&p); - - /* Administrative distance. */ - if (distance_str) - distance = atoi (distance_str); - else - distance = ZEBRA_STATIC_DISTANCE_DEFAULT; - - /* tag */ - if (tag_str) - tag = strtoul(tag_str, NULL, 10); - - /* When gateway is valid IPv6 addrees, then gate is treated as - nexthop address other case gate is treated as interface name. */ - ret = inet_pton (AF_INET6, gate_str, &gate_addr); - - /* VRF id */ - zvrf = zebra_vrf_lookup_by_name (vrf_id_str); - - if (!zvrf) - { - vty_out (vty, "%% vrf %s is not defined\n", vrf_id_str); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Labels */ - memset (&snh_label, 0, sizeof (struct static_nh_label)); - if (label_str) - { - if (!mpls_enabled) - { - vty_out (vty, - "%% MPLS not turned on in kernel, ignoring command\n"); - return CMD_WARNING_CONFIG_FAILED; - } - int rc = mpls_str2label (label_str, &snh_label.num_labels, - snh_label.label); - if (rc < 0) - { - switch (rc) { - case -1: - vty_out (vty, "%% Malformed label(s)\n"); - break; - case -2: - vty_out (vty, "%% Cannot use reserved label(s) (%d-%d)\n", - MPLS_MIN_RESERVED_LABEL,MPLS_MAX_RESERVED_LABEL); - break; - case -3: - vty_out (vty, "%% Too many labels. Enter %d or fewer\n", - MPLS_MAX_LABELS); - break; - } - return CMD_WARNING_CONFIG_FAILED; - } - } - - /* Null0 static route. */ - if ((gate_str != NULL) && (strncasecmp (gate_str, "Null0", strlen (gate_str)) == 0)) - { - if (flag_str) - { - vty_out (vty, "%% can not have flag %s with Null0\n", flag_str); - return CMD_WARNING_CONFIG_FAILED; - } - if (add_cmd) - static_add_route (AFI_IP6, SAFI_UNICAST, type, &p, src_p, NULL, ifindex, ifname, - ZEBRA_FLAG_BLACKHOLE, tag, distance, zvrf, &snh_label); - else - static_delete_route (AFI_IP6, SAFI_UNICAST, type, &p, src_p, NULL, ifindex, tag, - distance, zvrf, &snh_label); - return CMD_SUCCESS; - } - - /* Route flags */ - if (flag_str) { - switch(flag_str[0]) { - case 'r': - case 'R': /* XXX */ - SET_FLAG (flag, ZEBRA_FLAG_REJECT); - break; - case 'b': - case 'B': /* XXX */ - SET_FLAG (flag, ZEBRA_FLAG_BLACKHOLE); - break; - default: - vty_out (vty, "%% Malformed flag %s \n", flag_str); - return CMD_WARNING_CONFIG_FAILED; - } - } - - if (ifname) - { - /* When ifname is specified. It must be come with gateway - address. */ - if (ret != 1) - { - vty_out (vty, "%% Malformed address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - type = STATIC_IPV6_GATEWAY_IFINDEX; - gate = &gate_addr; - ifp = if_lookup_by_name (ifname, zvrf_id (zvrf)); - if (!ifp) - { - vty_out (vty, "%% Malformed Interface name %s\n", ifname); - return CMD_WARNING_CONFIG_FAILED; - } - ifindex = ifp->ifindex; - } - else - { - if (ret == 1) - { - type = STATIC_IPV6_GATEWAY; - gate = &gate_addr; - } - else - { - type = STATIC_IFINDEX; - ifp = if_lookup_by_name (gate_str, zvrf_id (zvrf)); - if (!ifp) - { - vty_out (vty, "%% Malformed Interface name %s\n", gate_str); - ifindex = IFINDEX_DELETED; - } - else - ifindex = ifp->ifindex; - ifname = gate_str; - } - } - - if (add_cmd) - static_add_route (AFI_IP6, SAFI_UNICAST, type, &p, src_p, (union g_addr *)gate, - ifindex, ifname, flag, tag, distance, zvrf, &snh_label); - else - static_delete_route (AFI_IP6, SAFI_UNICAST, type, &p, src_p, (union g_addr *)gate, - ifindex, tag, distance, zvrf, &snh_label); - - return CMD_SUCCESS; +int static_ipv6_func(struct vty *vty, int add_cmd, const char *dest_str, + const char *src_str, const char *gate_str, + const char *ifname, const char *flag_str, + const char *tag_str, const char *distance_str, + const char *vrf_id_str, const char *label_str) +{ + int ret; + u_char distance; + struct prefix p, src; + struct prefix_ipv6 *src_p = NULL; + struct in6_addr *gate = NULL; + struct in6_addr gate_addr; + u_char type = STATIC_BLACKHOLE; + u_char flag = 0; + route_tag_t tag = 0; + unsigned int ifindex = 0; + struct interface *ifp = NULL; + struct zebra_vrf *zvrf; + struct static_nh_label snh_label; + + ret = str2prefix(dest_str, &p); + if (ret <= 0) { + vty_out(vty, "%% Malformed address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (src_str) { + ret = str2prefix(src_str, &src); + if (ret <= 0 || src.family != AF_INET6) { + vty_out(vty, "%% Malformed source address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + src_p = (struct prefix_ipv6 *)&src; + } + + /* Apply mask for given prefix. */ + apply_mask(&p); + + /* Administrative distance. */ + if (distance_str) + distance = atoi(distance_str); + else + distance = ZEBRA_STATIC_DISTANCE_DEFAULT; + + /* tag */ + if (tag_str) + tag = strtoul(tag_str, NULL, 10); + + /* When gateway is valid IPv6 addrees, then gate is treated as + nexthop address other case gate is treated as interface name. */ + ret = inet_pton(AF_INET6, gate_str, &gate_addr); + + /* VRF id */ + zvrf = zebra_vrf_lookup_by_name(vrf_id_str); + + if (!zvrf) { + vty_out(vty, "%% vrf %s is not defined\n", vrf_id_str); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Labels */ + memset(&snh_label, 0, sizeof(struct static_nh_label)); + if (label_str) { + if (!mpls_enabled) { + vty_out(vty, + "%% MPLS not turned on in kernel, ignoring command\n"); + return CMD_WARNING_CONFIG_FAILED; + } + int rc = mpls_str2label(label_str, &snh_label.num_labels, + snh_label.label); + if (rc < 0) { + switch (rc) { + case -1: + vty_out(vty, "%% Malformed label(s)\n"); + break; + case -2: + vty_out(vty, + "%% Cannot use reserved label(s) (%d-%d)\n", + MPLS_MIN_RESERVED_LABEL, + MPLS_MAX_RESERVED_LABEL); + break; + case -3: + vty_out(vty, + "%% Too many labels. Enter %d or fewer\n", + MPLS_MAX_LABELS); + break; + } + return CMD_WARNING_CONFIG_FAILED; + } + } + + /* Null0 static route. */ + if ((gate_str != NULL) + && (strncasecmp(gate_str, "Null0", strlen(gate_str)) == 0)) { + if (flag_str) { + vty_out(vty, "%% can not have flag %s with Null0\n", + flag_str); + return CMD_WARNING_CONFIG_FAILED; + } + if (add_cmd) + static_add_route(AFI_IP6, SAFI_UNICAST, type, &p, src_p, + NULL, ifindex, ifname, + ZEBRA_FLAG_BLACKHOLE, tag, distance, + zvrf, &snh_label); + else + static_delete_route(AFI_IP6, SAFI_UNICAST, type, &p, + src_p, NULL, ifindex, tag, distance, + zvrf, &snh_label); + return CMD_SUCCESS; + } + + /* Route flags */ + if (flag_str) { + switch (flag_str[0]) { + case 'r': + case 'R': /* XXX */ + SET_FLAG(flag, ZEBRA_FLAG_REJECT); + break; + case 'b': + case 'B': /* XXX */ + SET_FLAG(flag, ZEBRA_FLAG_BLACKHOLE); + break; + default: + vty_out(vty, "%% Malformed flag %s \n", flag_str); + return CMD_WARNING_CONFIG_FAILED; + } + } + + if (ifname) { + /* When ifname is specified. It must be come with gateway + address. */ + if (ret != 1) { + vty_out(vty, "%% Malformed address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + type = STATIC_IPV6_GATEWAY_IFINDEX; + gate = &gate_addr; + ifp = if_lookup_by_name(ifname, zvrf_id(zvrf)); + if (!ifp) { + vty_out(vty, "%% Malformed Interface name %s\n", + ifname); + return CMD_WARNING_CONFIG_FAILED; + } + ifindex = ifp->ifindex; + } else { + if (ret == 1) { + type = STATIC_IPV6_GATEWAY; + gate = &gate_addr; + } else { + type = STATIC_IFINDEX; + ifp = if_lookup_by_name(gate_str, zvrf_id(zvrf)); + if (!ifp) { + vty_out(vty, "%% Malformed Interface name %s\n", + gate_str); + ifindex = IFINDEX_DELETED; + } else + ifindex = ifp->ifindex; + ifname = gate_str; + } + } + + if (add_cmd) + static_add_route(AFI_IP6, SAFI_UNICAST, type, &p, src_p, + (union g_addr *)gate, ifindex, ifname, flag, + tag, distance, zvrf, &snh_label); + else + static_delete_route(AFI_IP6, SAFI_UNICAST, type, &p, src_p, + (union g_addr *)gate, ifindex, tag, + distance, zvrf, &snh_label); + + return CMD_SUCCESS; } DEFUN (ipv6_route, @@ -2167,33 +2182,28 @@ DEFUN (ipv6_route, "Distance value for this prefix\n" VRF_CMD_HELP_STR) { - int idx_ipv6_prefixlen = 2; - int idx_ipv6_ifname; - int idx_curr; - char *src, *tag, *distance, *vrf; - - if (strmatch(argv[3]->text, "from")) - { - src = argv[4]->arg; - idx_ipv6_ifname = 5; - idx_curr = 6; - } - else - { - src = NULL; - idx_ipv6_ifname = 3; - idx_curr = 4; - } - - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); - - return static_ipv6_func (vty, 1, - argv[idx_ipv6_prefixlen]->arg, - src, - argv[idx_ipv6_ifname]->arg, - NULL, NULL, - tag, distance, vrf, NULL); + int idx_ipv6_prefixlen = 2; + int idx_ipv6_ifname; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (strmatch(argv[3]->text, "from")) { + src = argv[4]->arg; + idx_ipv6_ifname = 5; + idx_curr = 6; + } else { + src = NULL; + idx_ipv6_ifname = 3; + idx_curr = 4; + } + + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); + + return static_ipv6_func(vty, 1, argv[idx_ipv6_prefixlen]->arg, src, + argv[idx_ipv6_ifname]->arg, NULL, NULL, tag, + distance, vrf, NULL); } DEFUN (ipv6_route_flags, @@ -2213,37 +2223,32 @@ DEFUN (ipv6_route_flags, "Distance value for this prefix\n" VRF_CMD_HELP_STR) { - int idx_ipv6_prefixlen = 2; - int idx_ipv6_ifname; - int idx_reject_blackhole; - int idx_curr; - char *src, *tag, *distance, *vrf; - - if (strmatch(argv[3]->text, "from")) - { - src = argv[4]->arg; - idx_ipv6_ifname = 5; - idx_reject_blackhole = 6; - idx_curr = 7; - } - else - { - src = NULL; - idx_ipv6_ifname = 3; - idx_reject_blackhole = 4; - idx_curr = 5; - } - - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); - - return static_ipv6_func (vty, 1, - argv[idx_ipv6_prefixlen]->arg, - src, - argv[idx_ipv6_ifname]->arg, - NULL, - argv[idx_reject_blackhole]->arg, - tag, distance, vrf, NULL); + int idx_ipv6_prefixlen = 2; + int idx_ipv6_ifname; + int idx_reject_blackhole; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (strmatch(argv[3]->text, "from")) { + src = argv[4]->arg; + idx_ipv6_ifname = 5; + idx_reject_blackhole = 6; + idx_curr = 7; + } else { + src = NULL; + idx_ipv6_ifname = 3; + idx_reject_blackhole = 4; + idx_curr = 5; + } + + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); + + return static_ipv6_func(vty, 1, argv[idx_ipv6_prefixlen]->arg, src, + argv[idx_ipv6_ifname]->arg, NULL, + argv[idx_reject_blackhole]->arg, tag, distance, + vrf, NULL); } DEFUN (ipv6_route_ifname, @@ -2261,37 +2266,31 @@ DEFUN (ipv6_route_ifname, "Distance value for this prefix\n" VRF_CMD_HELP_STR) { - int idx_ipv6_prefixlen = 2; - int idx_ipv6 = 3; - int idx_interface = 4; - int idx_curr = 5; - char *src, *tag, *distance, *vrf; - - if (strmatch(argv[3]->text, "from")) - { - src = argv[4]->arg; - idx_ipv6 = 5; - idx_interface = 6; - idx_curr = 7; - } - else - { - src = NULL; - idx_ipv6 = 3; - idx_interface = 4; - idx_curr = 5; - } - - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); - - return static_ipv6_func (vty, 1, - argv[idx_ipv6_prefixlen]->arg, - src, - argv[idx_ipv6]->arg, - argv[idx_interface]->arg, - NULL, - tag, distance, vrf, NULL); + int idx_ipv6_prefixlen = 2; + int idx_ipv6 = 3; + int idx_interface = 4; + int idx_curr = 5; + char *src, *tag, *distance, *vrf; + + if (strmatch(argv[3]->text, "from")) { + src = argv[4]->arg; + idx_ipv6 = 5; + idx_interface = 6; + idx_curr = 7; + } else { + src = NULL; + idx_ipv6 = 3; + idx_interface = 4; + idx_curr = 5; + } + + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); + + return static_ipv6_func(vty, 1, argv[idx_ipv6_prefixlen]->arg, src, + argv[idx_ipv6]->arg, argv[idx_interface]->arg, + NULL, tag, distance, vrf, NULL); } DEFUN (ipv6_route_ifname_flags, @@ -2311,40 +2310,35 @@ DEFUN (ipv6_route_ifname_flags, "Distance value for this prefix\n" VRF_CMD_HELP_STR) { - int idx_ipv6_prefixlen = 2; - int idx_ipv6; - int idx_interface; - int idx_reject_blackhole; - int idx_curr; - char *src, *tag, *distance, *vrf; - - if (strmatch(argv[3]->text, "from")) - { - src = argv[4]->arg; - idx_ipv6 = 5; - idx_interface = 6; - idx_reject_blackhole = 7; - idx_curr = 8; - } - else - { - src = NULL; - idx_ipv6 = 3; - idx_interface = 4; - idx_reject_blackhole = 5; - idx_curr = 6; - } - - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); - - return static_ipv6_func (vty, 1, - argv[idx_ipv6_prefixlen]->arg, - src, - argv[idx_ipv6]->arg, - argv[idx_interface]->arg, - argv[idx_reject_blackhole]->arg, - tag, distance, vrf, NULL); + int idx_ipv6_prefixlen = 2; + int idx_ipv6; + int idx_interface; + int idx_reject_blackhole; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (strmatch(argv[3]->text, "from")) { + src = argv[4]->arg; + idx_ipv6 = 5; + idx_interface = 6; + idx_reject_blackhole = 7; + idx_curr = 8; + } else { + src = NULL; + idx_ipv6 = 3; + idx_interface = 4; + idx_reject_blackhole = 5; + idx_curr = 6; + } + + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); + + return static_ipv6_func(vty, 1, argv[idx_ipv6_prefixlen]->arg, src, + argv[idx_ipv6]->arg, argv[idx_interface]->arg, + argv[idx_reject_blackhole]->arg, tag, distance, + vrf, NULL); } DEFUN (no_ipv6_route, @@ -2364,33 +2358,28 @@ DEFUN (no_ipv6_route, "Distance value for this prefix\n" VRF_CMD_HELP_STR) { - int idx_ipv6_prefixlen = 3; - int idx_ipv6_ifname; - int idx_curr; - char *src, *tag, *distance, *vrf; - - if (strmatch(argv[4]->text, "from")) - { - src = argv[5]->arg; - idx_ipv6_ifname = 6; - idx_curr = 7; - } - else - { - src = NULL; - idx_ipv6_ifname = 4; - idx_curr = 5; - } - - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); - - return static_ipv6_func (vty, 0, - argv[idx_ipv6_prefixlen]->arg, - src, - argv[idx_ipv6_ifname]->arg, - NULL, NULL, - tag, distance, vrf, NULL); + int idx_ipv6_prefixlen = 3; + int idx_ipv6_ifname; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (strmatch(argv[4]->text, "from")) { + src = argv[5]->arg; + idx_ipv6_ifname = 6; + idx_curr = 7; + } else { + src = NULL; + idx_ipv6_ifname = 4; + idx_curr = 5; + } + + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); + + return static_ipv6_func(vty, 0, argv[idx_ipv6_prefixlen]->arg, src, + argv[idx_ipv6_ifname]->arg, NULL, NULL, tag, + distance, vrf, NULL); } DEFUN (no_ipv6_route_flags, @@ -2411,37 +2400,32 @@ DEFUN (no_ipv6_route_flags, "Distance value for this prefix\n" VRF_CMD_HELP_STR) { - int idx_ipv6_prefixlen = 3; - int idx_ipv6_ifname; - int idx_reject_blackhole; - int idx_curr; - char *src, *tag, *distance, *vrf; - - if (strmatch(argv[4]->text, "from")) - { - src = argv[5]->arg; - idx_ipv6_ifname = 6; - idx_reject_blackhole = 7; - idx_curr = 8; - } - else - { - src = NULL; - idx_ipv6_ifname = 4; - idx_reject_blackhole = 5; - idx_curr = 6; - } - - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); - - return static_ipv6_func (vty, 0, - argv[idx_ipv6_prefixlen]->arg, - src, - argv[idx_ipv6_ifname]->arg, - NULL, - argv[idx_reject_blackhole]->arg, - tag, distance, vrf, NULL); + int idx_ipv6_prefixlen = 3; + int idx_ipv6_ifname; + int idx_reject_blackhole; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (strmatch(argv[4]->text, "from")) { + src = argv[5]->arg; + idx_ipv6_ifname = 6; + idx_reject_blackhole = 7; + idx_curr = 8; + } else { + src = NULL; + idx_ipv6_ifname = 4; + idx_reject_blackhole = 5; + idx_curr = 6; + } + + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); + + return static_ipv6_func(vty, 0, argv[idx_ipv6_prefixlen]->arg, src, + argv[idx_ipv6_ifname]->arg, NULL, + argv[idx_reject_blackhole]->arg, tag, distance, + vrf, NULL); } DEFUN (no_ipv6_route_ifname, @@ -2460,37 +2444,31 @@ DEFUN (no_ipv6_route_ifname, "Distance value for this prefix\n" VRF_CMD_HELP_STR) { - int idx_ipv6_prefixlen = 3; - int idx_ipv6; - int idx_interface; - int idx_curr; - char *src, *tag, *distance, *vrf; - - if (strmatch(argv[4]->text, "from")) - { - src = argv[5]->arg; - idx_ipv6 = 6; - idx_interface = 7; - idx_curr = 8; - } - else - { - src = NULL; - idx_ipv6 = 4; - idx_interface = 5; - idx_curr = 6; - } - - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); - - return static_ipv6_func (vty, 0, - argv[idx_ipv6_prefixlen]->arg, - src, - argv[idx_ipv6]->arg, - argv[idx_interface]->arg, - NULL, - tag, distance, vrf, NULL); + int idx_ipv6_prefixlen = 3; + int idx_ipv6; + int idx_interface; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (strmatch(argv[4]->text, "from")) { + src = argv[5]->arg; + idx_ipv6 = 6; + idx_interface = 7; + idx_curr = 8; + } else { + src = NULL; + idx_ipv6 = 4; + idx_interface = 5; + idx_curr = 6; + } + + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); + + return static_ipv6_func(vty, 0, argv[idx_ipv6_prefixlen]->arg, src, + argv[idx_ipv6]->arg, argv[idx_interface]->arg, + NULL, tag, distance, vrf, NULL); } DEFUN (no_ipv6_route_ifname_flags, @@ -2511,40 +2489,35 @@ DEFUN (no_ipv6_route_ifname_flags, "Distance value for this prefix\n" VRF_CMD_HELP_STR) { - int idx_ipv6_prefixlen = 3; - int idx_ipv6; - int idx_interface; - int idx_reject_blackhole; - int idx_curr; - char *src, *tag, *distance, *vrf; - - if (strmatch(argv[4]->text, "from")) - { - src = argv[5]->arg; - idx_ipv6 = 6; - idx_interface = 7; - idx_reject_blackhole = 8; - idx_curr = 9; - } - else - { - src = NULL; - idx_ipv6 = 4; - idx_interface = 5; - idx_reject_blackhole = 6; - idx_curr = 7; - } - - tag = distance = vrf = NULL; - zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); - - return static_ipv6_func (vty, 0, - argv[idx_ipv6_prefixlen]->arg, - src, - argv[idx_ipv6]->arg, - argv[idx_interface]->arg, - argv[idx_reject_blackhole]->arg, - tag, distance, vrf, NULL); + int idx_ipv6_prefixlen = 3; + int idx_ipv6; + int idx_interface; + int idx_reject_blackhole; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (strmatch(argv[4]->text, "from")) { + src = argv[5]->arg; + idx_ipv6 = 6; + idx_interface = 7; + idx_reject_blackhole = 8; + idx_curr = 9; + } else { + src = NULL; + idx_ipv6 = 4; + idx_interface = 5; + idx_reject_blackhole = 6; + idx_curr = 7; + } + + tag = distance = vrf = NULL; + zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance, + &vrf, NULL); + + return static_ipv6_func(vty, 0, argv[idx_ipv6_prefixlen]->arg, src, + argv[idx_ipv6]->arg, argv[idx_interface]->arg, + argv[idx_reject_blackhole]->arg, tag, distance, + vrf, NULL); } DEFUN (show_ipv6_route, @@ -2562,88 +2535,85 @@ DEFUN (show_ipv6_route, FRR_IP6_REDIST_HELP_STR_ZEBRA JSON_STR) { - bool uf = use_fib(argv[2]); - struct route_table *table; - int vrf_all = 0; - route_tag_t tag = 0; - vrf_id_t vrf_id = VRF_DEFAULT; - struct vrf *vrf; - struct zebra_vrf *zvrf; - int uj = use_json(argc, argv); - int idx = 0; - struct prefix p; - bool longer_prefixes = false; - bool supernets_only = false; - int type = 0; - - if (argv_find (argv, argc, "vrf", &idx)) - { - if (strmatch(argv[idx+1]->arg, "all")) - vrf_all = 1; - else - VRF_GET_ID (vrf_id, argv[idx+1]->arg); - } - - if (argv_find (argv, argc, "tag", &idx)) - tag = strtoul(argv[idx + 1]->arg, NULL, 10); - - else if (argv_find (argv, argc, "X:X::X:X/M", &idx)) - { - str2prefix (argv[idx]->arg, &p); - longer_prefixes = true; - } - - else - { - if (argv_find (argv, argc, "kernel", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - else if (argv_find (argv, argc, "babel", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - else if (argv_find (argv, argc, "connected", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - else if (argv_find (argv, argc, "static", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - else if (argv_find (argv, argc, "ripng", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - else if (argv_find (argv, argc, "ospf6", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - else if (argv_find (argv, argc, "isis", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - else if (argv_find (argv, argc, "bgp", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - else if (argv_find (argv, argc, "nhrp", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - else if (argv_find (argv, argc, "table", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - else if (argv_find (argv, argc, "vnc", &idx)) - type = proto_redistnum (AFI_IP6, argv[idx]->text); - - if (type < 0) - { - vty_out (vty, "Unknown route type\n"); - return CMD_WARNING; - } - } - - if (vrf_all) - { - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if ((zvrf = vrf->info) == NULL || - (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) - continue; - - do_show_ip_route (vty, zvrf_name (zvrf), AFI_IP6, SAFI_UNICAST, uf, uj, tag, - longer_prefixes ? &p : NULL, supernets_only, type, 0); - } - } - else - { - vrf = vrf_lookup_by_id (vrf_id); - do_show_ip_route (vty, vrf->name, AFI_IP6, SAFI_UNICAST, uf, uj, tag, - longer_prefixes ? &p : NULL, supernets_only, type, 0); - } - return CMD_SUCCESS; + bool uf = use_fib(argv[2]); + struct route_table *table; + int vrf_all = 0; + route_tag_t tag = 0; + vrf_id_t vrf_id = VRF_DEFAULT; + struct vrf *vrf; + struct zebra_vrf *zvrf; + int uj = use_json(argc, argv); + int idx = 0; + struct prefix p; + bool longer_prefixes = false; + bool supernets_only = false; + int type = 0; + + if (argv_find(argv, argc, "vrf", &idx)) { + if (strmatch(argv[idx + 1]->arg, "all")) + vrf_all = 1; + else + VRF_GET_ID(vrf_id, argv[idx + 1]->arg); + } + + if (argv_find(argv, argc, "tag", &idx)) + tag = strtoul(argv[idx + 1]->arg, NULL, 10); + + else if (argv_find(argv, argc, "X:X::X:X/M", &idx)) { + str2prefix(argv[idx]->arg, &p); + longer_prefixes = true; + } + + else { + if (argv_find(argv, argc, "kernel", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + else if (argv_find(argv, argc, "babel", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + else if (argv_find(argv, argc, "connected", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + else if (argv_find(argv, argc, "static", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + else if (argv_find(argv, argc, "ripng", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + else if (argv_find(argv, argc, "ospf6", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + else if (argv_find(argv, argc, "isis", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + else if (argv_find(argv, argc, "bgp", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + else if (argv_find(argv, argc, "nhrp", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + else if (argv_find(argv, argc, "table", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + else if (argv_find(argv, argc, "vnc", &idx)) + type = proto_redistnum(AFI_IP6, argv[idx]->text); + + if (type < 0) { + vty_out(vty, "Unknown route type\n"); + return CMD_WARNING; + } + } + + if (vrf_all) { + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if ((zvrf = vrf->info) == NULL + || (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) + == NULL) + continue; + + do_show_ip_route(vty, zvrf_name(zvrf), AFI_IP6, + SAFI_UNICAST, uf, uj, tag, + longer_prefixes ? &p : NULL, + supernets_only, type, 0); + } + } else { + vrf = vrf_lookup_by_id(vrf_id); + do_show_ip_route(vty, vrf->name, AFI_IP6, SAFI_UNICAST, uf, uj, + tag, longer_prefixes ? &p : NULL, + supernets_only, type, 0); + } + return CMD_SUCCESS; } DEFUN (show_ipv6_route_addr, @@ -2655,44 +2625,39 @@ DEFUN (show_ipv6_route_addr, VRF_CMD_HELP_STR "IPv6 Address\n") { - int ret; - struct prefix_ipv6 p; - struct route_table *table; - struct route_node *rn; - vrf_id_t vrf_id = VRF_DEFAULT; - - if (strmatch(argv[3]->text, "vrf")) - { - VRF_GET_ID (vrf_id, argv[4]->arg); - ret = str2prefix_ipv6 (argv[5]->arg, &p); - } - else - { - ret = str2prefix_ipv6 (argv[3]->arg, &p); - } + int ret; + struct prefix_ipv6 p; + struct route_table *table; + struct route_node *rn; + vrf_id_t vrf_id = VRF_DEFAULT; + + if (strmatch(argv[3]->text, "vrf")) { + VRF_GET_ID(vrf_id, argv[4]->arg); + ret = str2prefix_ipv6(argv[5]->arg, &p); + } else { + ret = str2prefix_ipv6(argv[3]->arg, &p); + } - if (ret <= 0) - { - vty_out (vty, "Malformed IPv6 address\n"); - return CMD_WARNING; - } + if (ret <= 0) { + vty_out(vty, "Malformed IPv6 address\n"); + return CMD_WARNING; + } - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; + table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id); + if (!table) + return CMD_SUCCESS; - rn = route_node_match (table, (struct prefix *) &p); - if (! rn) - { - vty_out (vty, "%% Network not in table\n"); - return CMD_WARNING; - } + rn = route_node_match(table, (struct prefix *)&p); + if (!rn) { + vty_out(vty, "%% Network not in table\n"); + return CMD_WARNING; + } - vty_show_ip_route_detail (vty, rn, 0); + vty_show_ip_route_detail(vty, rn, 0); - route_unlock_node (rn); + route_unlock_node(rn); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ipv6_route_prefix, @@ -2704,42 +2669,38 @@ DEFUN (show_ipv6_route_prefix, VRF_CMD_HELP_STR "IPv6 prefix\n") { - int ret; - struct prefix_ipv6 p; - struct route_table *table; - struct route_node *rn; - vrf_id_t vrf_id = VRF_DEFAULT; - - if (strmatch(argv[3]->text, "vrf")) - { - VRF_GET_ID (vrf_id, argv[4]->arg); - ret = str2prefix_ipv6 (argv[5]->arg, &p); - } - else - ret = str2prefix_ipv6 (argv[3]->arg, &p); - - if (ret <= 0) - { - vty_out (vty, "Malformed IPv6 prefix\n"); - return CMD_WARNING; - } + int ret; + struct prefix_ipv6 p; + struct route_table *table; + struct route_node *rn; + vrf_id_t vrf_id = VRF_DEFAULT; + + if (strmatch(argv[3]->text, "vrf")) { + VRF_GET_ID(vrf_id, argv[4]->arg); + ret = str2prefix_ipv6(argv[5]->arg, &p); + } else + ret = str2prefix_ipv6(argv[3]->arg, &p); + + if (ret <= 0) { + vty_out(vty, "Malformed IPv6 prefix\n"); + return CMD_WARNING; + } - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; + table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id); + if (!table) + return CMD_SUCCESS; - rn = route_node_match (table, (struct prefix *) &p); - if (! rn || rn->p.prefixlen != p.prefixlen) - { - vty_out (vty, "%% Network not in table\n"); - return CMD_WARNING; - } + rn = route_node_match(table, (struct prefix *)&p); + if (!rn || rn->p.prefixlen != p.prefixlen) { + vty_out(vty, "%% Network not in table\n"); + return CMD_WARNING; + } - vty_show_ip_route_detail (vty, rn, 0); + vty_show_ip_route_detail(vty, rn, 0); - route_unlock_node (rn); + route_unlock_node(rn); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -2753,19 +2714,19 @@ DEFUN (show_ipv6_route_summary, VRF_CMD_HELP_STR "Summary of all IPv6 routes\n") { - struct route_table *table; - vrf_id_t vrf_id = VRF_DEFAULT; + struct route_table *table; + vrf_id_t vrf_id = VRF_DEFAULT; - if (strmatch(argv[3]->text, "vrf")) - VRF_GET_ID (vrf_id, argv[4]->arg); + if (strmatch(argv[3]->text, "vrf")) + VRF_GET_ID(vrf_id, argv[4]->arg); - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; + table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id); + if (!table) + return CMD_SUCCESS; - vty_show_ip_route_summary (vty, table); + vty_show_ip_route_summary(vty, table); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -2780,19 +2741,19 @@ DEFUN (show_ipv6_route_summary_prefix, "Summary of all IPv6 routes\n" "Prefix routes\n") { - struct route_table *table; - vrf_id_t vrf_id = VRF_DEFAULT; + struct route_table *table; + vrf_id_t vrf_id = VRF_DEFAULT; - if (strmatch(argv[3]->text, "vrf")) - VRF_GET_ID (vrf_id, argv[4]->arg); + if (strmatch(argv[3]->text, "vrf")) + VRF_GET_ID(vrf_id, argv[4]->arg); - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); - if (! table) - return CMD_SUCCESS; + table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id); + if (!table) + return CMD_SUCCESS; - vty_show_ip_route_summary_prefix (vty, table); + vty_show_ip_route_summary_prefix(vty, table); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -2808,31 +2769,30 @@ DEFUN (show_ipv6_mroute, "IPv6 Multicast routing table\n" VRF_CMD_HELP_STR) { - struct route_table *table; - struct route_node *rn; - struct route_entry *re; - int first = 1; - vrf_id_t vrf_id = VRF_DEFAULT; - - if (argc == 5) - VRF_GET_ID (vrf_id, argv[4]->arg); - - table = zebra_vrf_table (AFI_IP6, SAFI_MULTICAST, vrf_id); - if (! table) - return CMD_SUCCESS; - - /* Show all IPv6 route. */ - for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) - RNODE_FOREACH_RE (rn, re) - { - if (first) - { - vty_out (vty, SHOW_ROUTE_V6_HEADER); - first = 0; - } - vty_show_ip_route (vty, rn, re, NULL); - } - return CMD_SUCCESS; + struct route_table *table; + struct route_node *rn; + struct route_entry *re; + int first = 1; + vrf_id_t vrf_id = VRF_DEFAULT; + + if (argc == 5) + VRF_GET_ID(vrf_id, argv[4]->arg); + + table = zebra_vrf_table(AFI_IP6, SAFI_MULTICAST, vrf_id); + if (!table) + return CMD_SUCCESS; + + /* Show all IPv6 route. */ + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) + RNODE_FOREACH_RE(rn, re) + { + if (first) { + vty_out(vty, SHOW_ROUTE_V6_HEADER); + first = 0; + } + vty_show_ip_route(vty, rn, re, NULL); + } + return CMD_SUCCESS; } DEFUN (show_ipv6_route_vrf_all_addr, @@ -2844,37 +2804,36 @@ DEFUN (show_ipv6_route_vrf_all_addr, VRF_ALL_CMD_HELP_STR "IPv6 Address\n") { - int idx_ipv6 = 5; - int ret; - struct prefix_ipv6 p; - struct route_table *table; - struct route_node *rn; - struct vrf *vrf; - struct zebra_vrf *zvrf; - - ret = str2prefix_ipv6 (argv[idx_ipv6]->arg, &p); - if (ret <= 0) - { - vty_out (vty, "Malformed IPv6 address\n"); - return CMD_WARNING; - } + int idx_ipv6 = 5; + int ret; + struct prefix_ipv6 p; + struct route_table *table; + struct route_node *rn; + struct vrf *vrf; + struct zebra_vrf *zvrf; + + ret = str2prefix_ipv6(argv[idx_ipv6]->arg, &p); + if (ret <= 0) { + vty_out(vty, "Malformed IPv6 address\n"); + return CMD_WARNING; + } - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if ((zvrf = vrf->info) == NULL || - (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) - continue; + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if ((zvrf = vrf->info) == NULL + || (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) + continue; - rn = route_node_match (table, (struct prefix *) &p); - if (! rn) - continue; + rn = route_node_match(table, (struct prefix *)&p); + if (!rn) + continue; - vty_show_ip_route_detail (vty, rn, 0); + vty_show_ip_route_detail(vty, rn, 0); - route_unlock_node (rn); - } + route_unlock_node(rn); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ipv6_route_vrf_all_prefix, @@ -2886,42 +2845,40 @@ DEFUN (show_ipv6_route_vrf_all_prefix, VRF_ALL_CMD_HELP_STR "IPv6 prefix\n") { - int idx_ipv6_prefixlen = 5; - int ret; - struct prefix_ipv6 p; - struct route_table *table; - struct route_node *rn; - struct vrf *vrf; - struct zebra_vrf *zvrf; - - ret = str2prefix_ipv6 (argv[idx_ipv6_prefixlen]->arg, &p); - if (ret <= 0) - { - vty_out (vty, "Malformed IPv6 prefix\n"); - return CMD_WARNING; - } + int idx_ipv6_prefixlen = 5; + int ret; + struct prefix_ipv6 p; + struct route_table *table; + struct route_node *rn; + struct vrf *vrf; + struct zebra_vrf *zvrf; + + ret = str2prefix_ipv6(argv[idx_ipv6_prefixlen]->arg, &p); + if (ret <= 0) { + vty_out(vty, "Malformed IPv6 prefix\n"); + return CMD_WARNING; + } - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if ((zvrf = vrf->info) == NULL || - (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) - continue; + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if ((zvrf = vrf->info) == NULL + || (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL) + continue; - rn = route_node_match (table, (struct prefix *) &p); - if (! rn) - continue; - if (rn->p.prefixlen != p.prefixlen) - { - route_unlock_node (rn); - continue; - } + rn = route_node_match(table, (struct prefix *)&p); + if (!rn) + continue; + if (rn->p.prefixlen != p.prefixlen) { + route_unlock_node(rn); + continue; + } - vty_show_ip_route_detail (vty, rn, 0); + vty_show_ip_route_detail(vty, rn, 0); - route_unlock_node (rn); - } + route_unlock_node(rn); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ipv6_route_vrf_all_summary, @@ -2933,14 +2890,15 @@ DEFUN (show_ipv6_route_vrf_all_summary, VRF_ALL_CMD_HELP_STR "Summary of all IPv6 routes\n") { - struct vrf *vrf; - struct zebra_vrf *zvrf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if ((zvrf = vrf->info) != NULL) - vty_show_ip_route_summary (vty, zvrf->table[AFI_IP6][SAFI_UNICAST]); + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) + vty_show_ip_route_summary(vty, + zvrf->table[AFI_IP6][SAFI_UNICAST]); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ipv6_mroute_vrf_all, @@ -2951,32 +2909,31 @@ DEFUN (show_ipv6_mroute_vrf_all, "IPv6 Multicast routing table\n" VRF_ALL_CMD_HELP_STR) { - struct route_table *table; - struct route_node *rn; - struct route_entry *re; - struct vrf *vrf; - struct zebra_vrf *zvrf; - int first = 1; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if ((zvrf = vrf->info) == NULL || - (table = zvrf->table[AFI_IP6][SAFI_MULTICAST]) == NULL) - continue; - - /* Show all IPv6 route. */ - for (rn = route_top (table); rn; rn = srcdest_route_next (rn)) - RNODE_FOREACH_RE (rn, re) - { - if (first) - { - vty_out (vty, SHOW_ROUTE_V6_HEADER); - first = 0; - } - vty_show_ip_route (vty, rn, re, NULL); - } - } - return CMD_SUCCESS; + struct route_table *table; + struct route_node *rn; + struct route_entry *re; + struct vrf *vrf; + struct zebra_vrf *zvrf; + int first = 1; + + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if ((zvrf = vrf->info) == NULL + || (table = zvrf->table[AFI_IP6][SAFI_MULTICAST]) == NULL) + continue; + + /* Show all IPv6 route. */ + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) + RNODE_FOREACH_RE(rn, re) + { + if (first) { + vty_out(vty, SHOW_ROUTE_V6_HEADER); + first = 0; + } + vty_show_ip_route(vty, rn, re, NULL); + } + } + return CMD_SUCCESS; } DEFUN (show_ipv6_route_vrf_all_summary_prefix, @@ -2989,14 +2946,15 @@ DEFUN (show_ipv6_route_vrf_all_summary_prefix, "Summary of all IPv6 routes\n" "Prefix routes\n") { - struct vrf *vrf; - struct zebra_vrf *zvrf; + struct vrf *vrf; + struct zebra_vrf *zvrf; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if ((zvrf = vrf->info) != NULL) - vty_show_ip_route_summary_prefix (vty, zvrf->table[AFI_IP6][SAFI_UNICAST]); + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) + vty_show_ip_route_summary_prefix( + vty, zvrf->table[AFI_IP6][SAFI_UNICAST]); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (allow_external_route_update, @@ -3004,9 +2962,9 @@ DEFUN (allow_external_route_update, "allow-external-route-update", "Allow FRR routes to be overwritten by external processes\n") { - allow_delete = 1; + allow_delete = 1; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_allow_external_route_update, @@ -3015,9 +2973,9 @@ DEFUN (no_allow_external_route_update, NO_STR "Allow FRR routes to be overwritten by external processes\n") { - allow_delete = 0; + allow_delete = 0; - return CMD_SUCCESS; + return CMD_SUCCESS; } /* show vrf */ @@ -3027,26 +2985,26 @@ DEFUN (show_vrf, SHOW_STR "VRF\n") { - struct vrf *vrf; - struct zebra_vrf *zvrf; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - { - if (!(zvrf = vrf->info)) - continue; - if (!zvrf_id (zvrf)) - continue; + struct vrf *vrf; + struct zebra_vrf *zvrf; - vty_out (vty, "vrf %s ", zvrf_name (zvrf)); - if (zvrf_id (zvrf) == VRF_UNKNOWN) - vty_out (vty, "inactive"); - else - vty_out (vty, "id %u table %u", zvrf_id (zvrf), zvrf->table_id); - vty_out (vty, "\n"); - - } + RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) + { + if (!(zvrf = vrf->info)) + continue; + if (!zvrf_id(zvrf)) + continue; + + vty_out(vty, "vrf %s ", zvrf_name(zvrf)); + if (zvrf_id(zvrf) == VRF_UNKNOWN) + vty_out(vty, "inactive"); + else + vty_out(vty, "id %u table %u", zvrf_id(zvrf), + zvrf->table_id); + vty_out(vty, "\n"); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_evpn_vni, @@ -3056,11 +3014,11 @@ DEFUN (show_evpn_vni, "EVPN\n" "VxLAN information\n") { - struct zebra_vrf *zvrf; + struct zebra_vrf *zvrf; - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_vnis(vty, zvrf); - return CMD_SUCCESS; + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_vnis(vty, zvrf); + return CMD_SUCCESS; } DEFUN (show_evpn_vni_vni, @@ -3071,13 +3029,13 @@ DEFUN (show_evpn_vni_vni, "VxLAN Network Identifier\n" "VNI number\n") { - struct zebra_vrf *zvrf; - vni_t vni; + struct zebra_vrf *zvrf; + vni_t vni; - vni = strtoul(argv[3]->arg, NULL, 10); - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_vni(vty, zvrf, vni); - return CMD_SUCCESS; + vni = strtoul(argv[3]->arg, NULL, 10); + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_vni(vty, zvrf, vni); + return CMD_SUCCESS; } DEFUN (show_evpn_mac_vni, @@ -3089,13 +3047,13 @@ DEFUN (show_evpn_mac_vni, "VxLAN Network Identifier\n" "VNI number\n") { - struct zebra_vrf *zvrf; - vni_t vni; + struct zebra_vrf *zvrf; + vni_t vni; - vni = strtoul(argv[4]->arg, NULL, 10); - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_macs_vni(vty, zvrf, vni); - return CMD_SUCCESS; + vni = strtoul(argv[4]->arg, NULL, 10); + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_macs_vni(vty, zvrf, vni); + return CMD_SUCCESS; } DEFUN (show_evpn_mac_vni_all, @@ -3107,11 +3065,11 @@ DEFUN (show_evpn_mac_vni_all, "VxLAN Network Identifier\n" "All VNIs\n") { - struct zebra_vrf *zvrf; + struct zebra_vrf *zvrf; - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_macs_all_vni(vty, zvrf); - return CMD_SUCCESS; + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_macs_all_vni(vty, zvrf); + return CMD_SUCCESS; } DEFUN (show_evpn_mac_vni_all_vtep, @@ -3125,18 +3083,17 @@ DEFUN (show_evpn_mac_vni_all_vtep, "Remote VTEP\n" "Remote VTEP IP address\n") { - struct zebra_vrf *zvrf; - struct in_addr vtep_ip; + struct zebra_vrf *zvrf; + struct in_addr vtep_ip; - if (!inet_aton (argv[6]->arg, &vtep_ip)) - { - vty_out (vty, "%% Malformed VTEP IP address\n"); - return CMD_WARNING; - } - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_macs_all_vni_vtep(vty, zvrf, vtep_ip); + if (!inet_aton(argv[6]->arg, &vtep_ip)) { + vty_out(vty, "%% Malformed VTEP IP address\n"); + return CMD_WARNING; + } + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_macs_all_vni_vtep(vty, zvrf, vtep_ip); - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -3151,19 +3108,18 @@ DEFUN (show_evpn_mac_vni_mac, "MAC\n" "MAC address (e.g., 00:e0:ec:20:12:62)\n") { - struct zebra_vrf *zvrf; - vni_t vni; - struct ethaddr mac; + struct zebra_vrf *zvrf; + vni_t vni; + struct ethaddr mac; - vni = strtoul(argv[4]->arg, NULL, 10); - if (!prefix_str2mac (argv[6]->arg, &mac)) - { - vty_out (vty, "%% Malformed MAC address"); - return CMD_WARNING; - } - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_specific_mac_vni(vty, zvrf, vni, &mac); - return CMD_SUCCESS; + vni = strtoul(argv[4]->arg, NULL, 10); + if (!prefix_str2mac(argv[6]->arg, &mac)) { + vty_out(vty, "%% Malformed MAC address"); + return CMD_WARNING; + } + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_specific_mac_vni(vty, zvrf, vni, &mac); + return CMD_SUCCESS; } DEFUN (show_evpn_mac_vni_vtep, @@ -3177,20 +3133,19 @@ DEFUN (show_evpn_mac_vni_vtep, "Remote VTEP\n" "Remote VTEP IP address\n") { - struct zebra_vrf *zvrf; - vni_t vni; - struct in_addr vtep_ip; + struct zebra_vrf *zvrf; + vni_t vni; + struct in_addr vtep_ip; - vni = strtoul(argv[4]->arg, NULL, 10); - if (!inet_aton (argv[6]->arg, &vtep_ip)) - { - vty_out (vty, "%% Malformed VTEP IP address\n"); - return CMD_WARNING; - } + vni = strtoul(argv[4]->arg, NULL, 10); + if (!inet_aton(argv[6]->arg, &vtep_ip)) { + vty_out(vty, "%% Malformed VTEP IP address\n"); + return CMD_WARNING; + } - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_macs_vni_vtep(vty, zvrf, vni, vtep_ip); - return CMD_SUCCESS; + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_macs_vni_vtep(vty, zvrf, vni, vtep_ip); + return CMD_SUCCESS; } DEFUN (show_evpn_neigh_vni, @@ -3202,13 +3157,13 @@ DEFUN (show_evpn_neigh_vni, "VxLAN Network Identifier\n" "VNI number\n") { - struct zebra_vrf *zvrf; - vni_t vni; + struct zebra_vrf *zvrf; + vni_t vni; - vni = strtoul(argv[4]->arg, NULL, 10); - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_neigh_vni(vty, zvrf, vni); - return CMD_SUCCESS; + vni = strtoul(argv[4]->arg, NULL, 10); + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_neigh_vni(vty, zvrf, vni); + return CMD_SUCCESS; } DEFUN (show_evpn_neigh_vni_all, @@ -3220,11 +3175,11 @@ DEFUN (show_evpn_neigh_vni_all, "VxLAN Network Identifier\n" "All VNIs\n") { - struct zebra_vrf *zvrf; + struct zebra_vrf *zvrf; - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_neigh_all_vni(vty, zvrf); - return CMD_SUCCESS; + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_neigh_all_vni(vty, zvrf); + return CMD_SUCCESS; } DEFUN (show_evpn_neigh_vni_neigh, @@ -3238,19 +3193,18 @@ DEFUN (show_evpn_neigh_vni_neigh, "Neighbor\n" "Neighbor address (IPv4 or IPv6 address)\n") { - struct zebra_vrf *zvrf; - vni_t vni; - struct ipaddr ip; + struct zebra_vrf *zvrf; + vni_t vni; + struct ipaddr ip; - vni = strtoul(argv[4]->arg, NULL, 10); - if (str2ipaddr (argv[6]->arg, &ip) != 0) - { - vty_out (vty, "%% Malformed Neighbor address\n"); - return CMD_WARNING; - } - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_specific_neigh_vni(vty, zvrf, vni, &ip); - return CMD_SUCCESS; + vni = strtoul(argv[4]->arg, NULL, 10); + if (str2ipaddr(argv[6]->arg, &ip) != 0) { + vty_out(vty, "%% Malformed Neighbor address\n"); + return CMD_WARNING; + } + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_specific_neigh_vni(vty, zvrf, vni, &ip); + return CMD_SUCCESS; } DEFUN (show_evpn_neigh_vni_vtep, @@ -3264,34 +3218,32 @@ DEFUN (show_evpn_neigh_vni_vtep, "Remote VTEP\n" "Remote VTEP IP address\n") { - struct zebra_vrf *zvrf; - vni_t vni; - struct in_addr vtep_ip; + struct zebra_vrf *zvrf; + vni_t vni; + struct in_addr vtep_ip; - vni = strtoul(argv[4]->arg, NULL, 10); - if (!inet_aton (argv[6]->arg, &vtep_ip)) - { - vty_out (vty, "%% Malformed VTEP IP address\n"); - return CMD_WARNING; - } + vni = strtoul(argv[4]->arg, NULL, 10); + if (!inet_aton(argv[6]->arg, &vtep_ip)) { + vty_out(vty, "%% Malformed VTEP IP address\n"); + return CMD_WARNING; + } - zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_neigh_vni_vtep(vty, zvrf, vni, vtep_ip); - return CMD_SUCCESS; + zvrf = vrf_info_lookup(VRF_DEFAULT); + zebra_vxlan_print_neigh_vni_vtep(vty, zvrf, vni, vtep_ip); + return CMD_SUCCESS; } /* Static ip route configuration write function. */ -static int -zebra_ip_config (struct vty *vty) +static int zebra_ip_config(struct vty *vty) { - int write = 0; + int write = 0; - write += static_config (vty, AFI_IP, SAFI_UNICAST, "ip route"); - write += static_config (vty, AFI_IP, SAFI_MULTICAST, "ip mroute"); - write += static_config (vty, AFI_IP6, SAFI_UNICAST, "ipv6 route"); + write += static_config(vty, AFI_IP, SAFI_UNICAST, "ip route"); + write += static_config(vty, AFI_IP, SAFI_MULTICAST, "ip mroute"); + write += static_config(vty, AFI_IP6, SAFI_UNICAST, "ipv6 route"); - write += zebra_import_table_config (vty); - return write; + write += zebra_import_table_config(vty); + return write; } DEFUN (ip_zebra_import_table_distance, @@ -3305,36 +3257,38 @@ DEFUN (ip_zebra_import_table_distance, "route-map for filtering\n" "route-map name\n") { - u_int32_t table_id = 0; + u_int32_t table_id = 0; - table_id = strtoul(argv[2]->arg, NULL, 10); - int distance = ZEBRA_TABLE_DISTANCE_DEFAULT; - char *rmap = strmatch (argv[argc - 2]->text, "route-map") ? - XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[argc - 1]->arg) : NULL; - int ret; + table_id = strtoul(argv[2]->arg, NULL, 10); + int distance = ZEBRA_TABLE_DISTANCE_DEFAULT; + char *rmap = + strmatch(argv[argc - 2]->text, "route-map") + ? XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[argc - 1]->arg) + : NULL; + int ret; - if (argc == 7 || (argc == 5 && !rmap)) - distance = strtoul(argv[4]->arg, NULL, 10); + if (argc == 7 || (argc == 5 && !rmap)) + distance = strtoul(argv[4]->arg, NULL, 10); - if (!is_zebra_valid_kernel_table(table_id)) - { - vty_out (vty, "Invalid routing table ID, %d. Must be in range 1-252\n", - table_id); - return CMD_WARNING; - } + if (!is_zebra_valid_kernel_table(table_id)) { + vty_out(vty, + "Invalid routing table ID, %d. Must be in range 1-252\n", + table_id); + return CMD_WARNING; + } - if (is_zebra_main_routing_table(table_id)) - { - vty_out (vty, "Invalid routing table ID, %d. Must be non-default table\n", - table_id); - return CMD_WARNING; - } + if (is_zebra_main_routing_table(table_id)) { + vty_out(vty, + "Invalid routing table ID, %d. Must be non-default table\n", + table_id); + return CMD_WARNING; + } - ret = zebra_import_table(AFI_IP, table_id, distance, rmap, 1); - if (rmap) - XFREE(MTYPE_ROUTE_MAP_NAME, rmap); + ret = zebra_import_table(AFI_IP, table_id, distance, rmap, 1); + if (rmap) + XFREE(MTYPE_ROUTE_MAP_NAME, rmap); - return ret; + return ret; } DEFUN (no_ip_zebra_import_table, @@ -3349,137 +3303,145 @@ DEFUN (no_ip_zebra_import_table, "route-map for filtering\n" "route-map name\n") { - u_int32_t table_id = 0; - table_id = strtoul(argv[3]->arg, NULL, 10); + u_int32_t table_id = 0; + table_id = strtoul(argv[3]->arg, NULL, 10); - if (!is_zebra_valid_kernel_table(table_id)) - { - vty_out (vty,"Invalid routing table ID. Must be in range 1-252\n"); - return CMD_WARNING; - } + if (!is_zebra_valid_kernel_table(table_id)) { + vty_out(vty, + "Invalid routing table ID. Must be in range 1-252\n"); + return CMD_WARNING; + } - if (is_zebra_main_routing_table(table_id)) - { - vty_out (vty, "Invalid routing table ID, %d. Must be non-default table\n", - table_id); - return CMD_WARNING; - } + if (is_zebra_main_routing_table(table_id)) { + vty_out(vty, + "Invalid routing table ID, %d. Must be non-default table\n", + table_id); + return CMD_WARNING; + } - if (!is_zebra_import_table_enabled(AFI_IP, table_id)) - return CMD_SUCCESS; + if (!is_zebra_import_table_enabled(AFI_IP, table_id)) + return CMD_SUCCESS; - return (zebra_import_table(AFI_IP, table_id, 0, NULL, 0)); + return (zebra_import_table(AFI_IP, table_id, 0, NULL, 0)); } -static int -config_write_protocol (struct vty *vty) +static int config_write_protocol(struct vty *vty) { - if (allow_delete) - vty_out (vty, "allow-external-route-update\n"); + if (allow_delete) + vty_out(vty, "allow-external-route-update\n"); - if (zebra_rnh_ip_default_route) - vty_out (vty, "ip nht resolve-via-default\n"); + if (zebra_rnh_ip_default_route) + vty_out(vty, "ip nht resolve-via-default\n"); - if (zebra_rnh_ipv6_default_route) - vty_out (vty, "ipv6 nht resolve-via-default\n"); + if (zebra_rnh_ipv6_default_route) + vty_out(vty, "ipv6 nht resolve-via-default\n"); - enum multicast_mode ipv4_multicast_mode = multicast_mode_ipv4_get (); + enum multicast_mode ipv4_multicast_mode = multicast_mode_ipv4_get(); - if (ipv4_multicast_mode != MCAST_NO_CONFIG) - vty_out (vty, "ip multicast rpf-lookup-mode %s\n", - ipv4_multicast_mode == MCAST_URIB_ONLY ? "urib-only" : ipv4_multicast_mode == MCAST_MRIB_ONLY ? "mrib-only" : ipv4_multicast_mode == MCAST_MIX_MRIB_FIRST ? "mrib-then-urib" : ipv4_multicast_mode == MCAST_MIX_DISTANCE ? "lower-distance" : "longer-prefix"); + if (ipv4_multicast_mode != MCAST_NO_CONFIG) + vty_out(vty, "ip multicast rpf-lookup-mode %s\n", + ipv4_multicast_mode == MCAST_URIB_ONLY + ? "urib-only" + : ipv4_multicast_mode == MCAST_MRIB_ONLY + ? "mrib-only" + : ipv4_multicast_mode + == MCAST_MIX_MRIB_FIRST + ? "mrib-then-urib" + : ipv4_multicast_mode + == MCAST_MIX_DISTANCE + ? "lower-distance" + : "longer-prefix"); - zebra_routemap_config_write_protocol(vty); + zebra_routemap_config_write_protocol(vty); - return 1; + return 1; } /* IP node for static routes. */ -static struct cmd_node ip_node = { IP_NODE, "", 1 }; -static struct cmd_node protocol_node = { PROTOCOL_NODE, "", 1 }; +static struct cmd_node ip_node = {IP_NODE, "", 1}; +static struct cmd_node protocol_node = {PROTOCOL_NODE, "", 1}; /* Route VTY. */ -void -zebra_vty_init (void) -{ - install_node (&ip_node, zebra_ip_config); - install_node (&protocol_node, config_write_protocol); - - install_element (CONFIG_NODE, &allow_external_route_update_cmd); - install_element (CONFIG_NODE, &no_allow_external_route_update_cmd); - install_element (CONFIG_NODE, &ip_mroute_dist_cmd); - install_element (CONFIG_NODE, &no_ip_mroute_dist_cmd); - install_element (CONFIG_NODE, &ip_multicast_mode_cmd); - install_element (CONFIG_NODE, &no_ip_multicast_mode_cmd); - install_element (CONFIG_NODE, &ip_route_cmd); - install_element (CONFIG_NODE, &ip_route_flags_cmd); - install_element (CONFIG_NODE, &ip_route_mask_cmd); - install_element (CONFIG_NODE, &ip_route_mask_flags_cmd); - install_element (CONFIG_NODE, &no_ip_route_cmd); - install_element (CONFIG_NODE, &no_ip_route_mask_cmd); - install_element (CONFIG_NODE, &ip_zebra_import_table_distance_cmd); - install_element (CONFIG_NODE, &no_ip_zebra_import_table_cmd); - - install_element (VIEW_NODE, &show_vrf_cmd); - install_element (VIEW_NODE, &show_ip_route_cmd); - install_element (VIEW_NODE, &show_ip_nht_cmd); - install_element (VIEW_NODE, &show_ip_nht_vrf_all_cmd); - install_element (VIEW_NODE, &show_ipv6_nht_cmd); - install_element (VIEW_NODE, &show_ipv6_nht_vrf_all_cmd); - install_element (VIEW_NODE, &show_ip_route_addr_cmd); - install_element (VIEW_NODE, &show_ip_route_prefix_cmd); - install_element (VIEW_NODE, &show_ip_route_summary_cmd); - install_element (VIEW_NODE, &show_ip_route_summary_prefix_cmd); - - install_element (VIEW_NODE, &show_ip_rpf_cmd); - install_element (VIEW_NODE, &show_ip_rpf_addr_cmd); - - /* Commands for VRF */ - - install_element (CONFIG_NODE, &no_ip_route_flags_cmd); - install_element (CONFIG_NODE, &no_ip_route_mask_flags_cmd); - - install_element (VIEW_NODE, &show_ip_route_vrf_all_addr_cmd); - install_element (VIEW_NODE, &show_ip_route_vrf_all_prefix_cmd); - install_element (VIEW_NODE, &show_ip_route_vrf_all_summary_cmd); - install_element (VIEW_NODE, &show_ip_route_vrf_all_summary_prefix_cmd); - - install_element (CONFIG_NODE, &ipv6_route_cmd); - install_element (CONFIG_NODE, &ipv6_route_flags_cmd); - install_element (CONFIG_NODE, &ipv6_route_ifname_cmd); - install_element (CONFIG_NODE, &ipv6_route_ifname_flags_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_flags_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_ifname_cmd); - install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_cmd); - install_element (CONFIG_NODE, &ip_nht_default_route_cmd); - install_element (CONFIG_NODE, &no_ip_nht_default_route_cmd); - install_element (CONFIG_NODE, &ipv6_nht_default_route_cmd); - install_element (CONFIG_NODE, &no_ipv6_nht_default_route_cmd); - install_element (VIEW_NODE, &show_ipv6_route_cmd); - install_element (VIEW_NODE, &show_ipv6_route_summary_cmd); - install_element (VIEW_NODE, &show_ipv6_route_summary_prefix_cmd); - install_element (VIEW_NODE, &show_ipv6_route_addr_cmd); - install_element (VIEW_NODE, &show_ipv6_route_prefix_cmd); - install_element (VIEW_NODE, &show_ipv6_mroute_cmd); - - /* Commands for VRF */ - install_element (VIEW_NODE, &show_ipv6_route_vrf_all_summary_cmd); - install_element (VIEW_NODE, &show_ipv6_route_vrf_all_summary_prefix_cmd); - install_element (VIEW_NODE, &show_ipv6_route_vrf_all_addr_cmd); - install_element (VIEW_NODE, &show_ipv6_route_vrf_all_prefix_cmd); - - install_element (VIEW_NODE, &show_ipv6_mroute_vrf_all_cmd); - - install_element (VIEW_NODE, &show_evpn_vni_cmd); - install_element (VIEW_NODE, &show_evpn_vni_vni_cmd); - install_element (VIEW_NODE, &show_evpn_mac_vni_cmd); - install_element (VIEW_NODE, &show_evpn_mac_vni_all_cmd); - install_element (VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd); - install_element (VIEW_NODE, &show_evpn_mac_vni_mac_cmd); - install_element (VIEW_NODE, &show_evpn_mac_vni_vtep_cmd); - install_element (VIEW_NODE, &show_evpn_neigh_vni_cmd); - install_element (VIEW_NODE, &show_evpn_neigh_vni_all_cmd); - install_element (VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd); - install_element (VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd); +void zebra_vty_init(void) +{ + install_node(&ip_node, zebra_ip_config); + install_node(&protocol_node, config_write_protocol); + + install_element(CONFIG_NODE, &allow_external_route_update_cmd); + install_element(CONFIG_NODE, &no_allow_external_route_update_cmd); + install_element(CONFIG_NODE, &ip_mroute_dist_cmd); + install_element(CONFIG_NODE, &no_ip_mroute_dist_cmd); + install_element(CONFIG_NODE, &ip_multicast_mode_cmd); + install_element(CONFIG_NODE, &no_ip_multicast_mode_cmd); + install_element(CONFIG_NODE, &ip_route_cmd); + install_element(CONFIG_NODE, &ip_route_flags_cmd); + install_element(CONFIG_NODE, &ip_route_mask_cmd); + install_element(CONFIG_NODE, &ip_route_mask_flags_cmd); + install_element(CONFIG_NODE, &no_ip_route_cmd); + install_element(CONFIG_NODE, &no_ip_route_mask_cmd); + install_element(CONFIG_NODE, &ip_zebra_import_table_distance_cmd); + install_element(CONFIG_NODE, &no_ip_zebra_import_table_cmd); + + install_element(VIEW_NODE, &show_vrf_cmd); + install_element(VIEW_NODE, &show_ip_route_cmd); + install_element(VIEW_NODE, &show_ip_nht_cmd); + install_element(VIEW_NODE, &show_ip_nht_vrf_all_cmd); + install_element(VIEW_NODE, &show_ipv6_nht_cmd); + install_element(VIEW_NODE, &show_ipv6_nht_vrf_all_cmd); + install_element(VIEW_NODE, &show_ip_route_addr_cmd); + install_element(VIEW_NODE, &show_ip_route_prefix_cmd); + install_element(VIEW_NODE, &show_ip_route_summary_cmd); + install_element(VIEW_NODE, &show_ip_route_summary_prefix_cmd); + + install_element(VIEW_NODE, &show_ip_rpf_cmd); + install_element(VIEW_NODE, &show_ip_rpf_addr_cmd); + + /* Commands for VRF */ + + install_element(CONFIG_NODE, &no_ip_route_flags_cmd); + install_element(CONFIG_NODE, &no_ip_route_mask_flags_cmd); + + install_element(VIEW_NODE, &show_ip_route_vrf_all_addr_cmd); + install_element(VIEW_NODE, &show_ip_route_vrf_all_prefix_cmd); + install_element(VIEW_NODE, &show_ip_route_vrf_all_summary_cmd); + install_element(VIEW_NODE, &show_ip_route_vrf_all_summary_prefix_cmd); + + install_element(CONFIG_NODE, &ipv6_route_cmd); + install_element(CONFIG_NODE, &ipv6_route_flags_cmd); + install_element(CONFIG_NODE, &ipv6_route_ifname_cmd); + install_element(CONFIG_NODE, &ipv6_route_ifname_flags_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_flags_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_ifname_cmd); + install_element(CONFIG_NODE, &no_ipv6_route_ifname_flags_cmd); + install_element(CONFIG_NODE, &ip_nht_default_route_cmd); + install_element(CONFIG_NODE, &no_ip_nht_default_route_cmd); + install_element(CONFIG_NODE, &ipv6_nht_default_route_cmd); + install_element(CONFIG_NODE, &no_ipv6_nht_default_route_cmd); + install_element(VIEW_NODE, &show_ipv6_route_cmd); + install_element(VIEW_NODE, &show_ipv6_route_summary_cmd); + install_element(VIEW_NODE, &show_ipv6_route_summary_prefix_cmd); + install_element(VIEW_NODE, &show_ipv6_route_addr_cmd); + install_element(VIEW_NODE, &show_ipv6_route_prefix_cmd); + install_element(VIEW_NODE, &show_ipv6_mroute_cmd); + + /* Commands for VRF */ + install_element(VIEW_NODE, &show_ipv6_route_vrf_all_summary_cmd); + install_element(VIEW_NODE, &show_ipv6_route_vrf_all_summary_prefix_cmd); + install_element(VIEW_NODE, &show_ipv6_route_vrf_all_addr_cmd); + install_element(VIEW_NODE, &show_ipv6_route_vrf_all_prefix_cmd); + + install_element(VIEW_NODE, &show_ipv6_mroute_vrf_all_cmd); + + install_element(VIEW_NODE, &show_evpn_vni_cmd); + install_element(VIEW_NODE, &show_evpn_vni_vni_cmd); + install_element(VIEW_NODE, &show_evpn_mac_vni_cmd); + install_element(VIEW_NODE, &show_evpn_mac_vni_all_cmd); + install_element(VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd); + install_element(VIEW_NODE, &show_evpn_mac_vni_mac_cmd); + install_element(VIEW_NODE, &show_evpn_mac_vni_vtep_cmd); + install_element(VIEW_NODE, &show_evpn_neigh_vni_cmd); + install_element(VIEW_NODE, &show_evpn_neigh_vni_all_cmd); + install_element(VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd); + install_element(VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd); } diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 7df31cb93..c96f07306 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -47,140 +47,90 @@ #include "zebra/zebra_memory.h" #include "zebra/zebra_l2.h" -DEFINE_MTYPE_STATIC(ZEBRA, ZVNI, "VNI hash"); +DEFINE_MTYPE_STATIC(ZEBRA, ZVNI, "VNI hash"); DEFINE_MTYPE_STATIC(ZEBRA, ZVNI_VTEP, "VNI remote VTEP"); -DEFINE_MTYPE_STATIC(ZEBRA, MAC, "VNI MAC"); -DEFINE_MTYPE_STATIC(ZEBRA, NEIGH, "VNI Neighbor"); +DEFINE_MTYPE_STATIC(ZEBRA, MAC, "VNI MAC"); +DEFINE_MTYPE_STATIC(ZEBRA, NEIGH, "VNI Neighbor"); /* definitions */ /* static function declarations */ -static void -zvni_print_neigh (zebra_neigh_t *n, void *ctxt); -static void -zvni_print_neigh_hash (struct hash_backet *backet, void *ctxt); -static void -zvni_print_neigh_hash_all_vni (struct hash_backet *backet, void *ctxt); -static void -zvni_print_mac (zebra_mac_t *mac, void *ctxt); -static void -zvni_print_mac_hash (struct hash_backet *backet, void *ctxt); -static void -zvni_print_mac_hash_all_vni (struct hash_backet *backet, void *ctxt); -static void -zvni_print (zebra_vni_t *zvni, void *ctxt); -static void -zvni_print_hash (struct hash_backet *backet, void *ctxt); - -static int -zvni_macip_send_msg_to_client (struct zebra_vrf *zvrf, vni_t vni, - struct ethaddr *macaddr, - struct ipaddr *ip, u_char sticky, - u_int16_t cmd); -static unsigned int -neigh_hash_keymake (void *p); -static int -neigh_cmp (const void *p1, const void *p2); -static void * -zvni_neigh_alloc (void *p); -static zebra_neigh_t * -zvni_neigh_add (zebra_vni_t *zvni, struct ipaddr *ip); -static int -zvni_neigh_del (zebra_vni_t *zvni, zebra_neigh_t *n); -static int -zvni_neigh_del_hash_entry (struct hash_backet *backet, void *arg); -static void -zvni_neigh_del_from_vtep (zebra_vni_t *zvni, int uninstall, - struct in_addr *r_vtep_ip); -static void -zvni_neigh_del_all (struct zebra_vrf *zvrf, zebra_vni_t *zvni, - int uninstall, int upd_client, u_int32_t flags); -static zebra_neigh_t * -zvni_neigh_lookup (zebra_vni_t *zvni, struct ipaddr *ip); -static int -zvni_neigh_send_add_to_client (struct zebra_vrf *zvrf, vni_t vni, - struct ipaddr *ip, struct ethaddr *macaddr); -static int -zvni_neigh_send_del_to_client (struct zebra_vrf *zvrf, vni_t vni, - struct ipaddr *ip, struct ethaddr *macaddr); -static int -zvni_neigh_install (zebra_vni_t *zvni, zebra_neigh_t *n); -static int -zvni_neigh_uninstall (zebra_vni_t *zvni, zebra_neigh_t *n); -static zebra_vni_t * -zvni_map_svi (struct interface *ifp, struct interface *br_if); -static struct interface * -zvni_map_to_svi (struct zebra_vrf *zvrf, vlanid_t vid, - struct interface *br_if); - -static unsigned int -mac_hash_keymake (void *p); -static int -mac_cmp (const void *p1, const void *p2); -static void * -zvni_mac_alloc (void *p); -static zebra_mac_t * -zvni_mac_add (zebra_vni_t *zvni, struct ethaddr *macaddr); -static int -zvni_mac_del (zebra_vni_t *zvni, zebra_mac_t *mac); -static int -zvni_mac_del_hash_entry (struct hash_backet *backet, void *arg); -static void -zvni_mac_del_from_vtep (zebra_vni_t *zvni, int uninstall, - struct in_addr *r_vtep_ip); -static void -zvni_mac_del_all (struct zebra_vrf *zvrf, zebra_vni_t *zvni, - int uninstall, int upd_client, u_int32_t flags); -static zebra_mac_t * -zvni_mac_lookup (zebra_vni_t *zvni, struct ethaddr *macaddr); -static int -zvni_mac_send_add_to_client (struct zebra_vrf *zvrf, vni_t vni, - struct ethaddr *macaddr, u_char sticky); -static int -zvni_mac_send_del_to_client (struct zebra_vrf *zvrf, vni_t vni, - struct ethaddr *macaddr, u_char sticky); -static zebra_vni_t * -zvni_map_vlan (struct interface *ifp, struct interface *br_if, vlanid_t vid); -static int -zvni_mac_install (zebra_vni_t *zvni, zebra_mac_t *mac); -static int -zvni_mac_uninstall (zebra_vni_t *zvni, zebra_mac_t *mac, int local); -static void -zvni_install_mac_hash (struct hash_backet *backet, void *ctxt); - -static unsigned int -vni_hash_keymake (void *p); -static int -vni_hash_cmp (const void *p1, const void *p2); -static void * -zvni_alloc (void *p); -static zebra_vni_t * -zvni_lookup (struct zebra_vrf *zvrf, vni_t vni); -static zebra_vni_t * -zvni_add (struct zebra_vrf *zvrf, vni_t vni); -static int -zvni_del (struct zebra_vrf *zvrf, zebra_vni_t *zvni); -static int -zvni_send_add_to_client (struct zebra_vrf *zvrf, zebra_vni_t *zvni); -static int -zvni_send_del_to_client (struct zebra_vrf *zvrf, vni_t vni); -static void -zvni_build_hash_table (struct zebra_vrf *zvrf); -static int -zvni_vtep_match (struct in_addr *vtep_ip, zebra_vtep_t *zvtep); -static zebra_vtep_t * -zvni_vtep_find (zebra_vni_t *zvni, struct in_addr *vtep_ip); -static zebra_vtep_t * -zvni_vtep_add (zebra_vni_t *zvni, struct in_addr *vtep_ip); -static int -zvni_vtep_del (zebra_vni_t *zvni, zebra_vtep_t *zvtep); -static int -zvni_vtep_del_all (zebra_vni_t *zvni, int uninstall); -static int -zvni_vtep_install (zebra_vni_t *zvni, struct in_addr *vtep_ip); -static int -zvni_vtep_uninstall (zebra_vni_t *zvni, struct in_addr *vtep_ip); +static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt); +static void zvni_print_neigh_hash(struct hash_backet *backet, void *ctxt); +static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet, + void *ctxt); +static void zvni_print_mac(zebra_mac_t *mac, void *ctxt); +static void zvni_print_mac_hash(struct hash_backet *backet, void *ctxt); +static void zvni_print_mac_hash_all_vni(struct hash_backet *backet, void *ctxt); +static void zvni_print(zebra_vni_t *zvni, void *ctxt); +static void zvni_print_hash(struct hash_backet *backet, void *ctxt); + +static int zvni_macip_send_msg_to_client(struct zebra_vrf *zvrf, vni_t vni, + struct ethaddr *macaddr, + struct ipaddr *ip, u_char sticky, + u_int16_t cmd); +static unsigned int neigh_hash_keymake(void *p); +static int neigh_cmp(const void *p1, const void *p2); +static void *zvni_neigh_alloc(void *p); +static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip); +static int zvni_neigh_del(zebra_vni_t *zvni, zebra_neigh_t *n); +static int zvni_neigh_del_hash_entry(struct hash_backet *backet, void *arg); +static void zvni_neigh_del_from_vtep(zebra_vni_t *zvni, int uninstall, + struct in_addr *r_vtep_ip); +static void zvni_neigh_del_all(struct zebra_vrf *zvrf, zebra_vni_t *zvni, + int uninstall, int upd_client, u_int32_t flags); +static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip); +static int zvni_neigh_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni, + struct ipaddr *ip, + struct ethaddr *macaddr); +static int zvni_neigh_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni, + struct ipaddr *ip, + struct ethaddr *macaddr); +static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n); +static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n); +static zebra_vni_t *zvni_map_svi(struct interface *ifp, + struct interface *br_if); +static struct interface *zvni_map_to_svi(struct zebra_vrf *zvrf, vlanid_t vid, + struct interface *br_if); + +static unsigned int mac_hash_keymake(void *p); +static int mac_cmp(const void *p1, const void *p2); +static void *zvni_mac_alloc(void *p); +static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr); +static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac); +static int zvni_mac_del_hash_entry(struct hash_backet *backet, void *arg); +static void zvni_mac_del_from_vtep(zebra_vni_t *zvni, int uninstall, + struct in_addr *r_vtep_ip); +static void zvni_mac_del_all(struct zebra_vrf *zvrf, zebra_vni_t *zvni, + int uninstall, int upd_client, u_int32_t flags); +static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *macaddr); +static int zvni_mac_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni, + struct ethaddr *macaddr, u_char sticky); +static int zvni_mac_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni, + struct ethaddr *macaddr, u_char sticky); +static zebra_vni_t *zvni_map_vlan(struct interface *ifp, + struct interface *br_if, vlanid_t vid); +static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac); +static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac, int local); +static void zvni_install_mac_hash(struct hash_backet *backet, void *ctxt); + +static unsigned int vni_hash_keymake(void *p); +static int vni_hash_cmp(const void *p1, const void *p2); +static void *zvni_alloc(void *p); +static zebra_vni_t *zvni_lookup(struct zebra_vrf *zvrf, vni_t vni); +static zebra_vni_t *zvni_add(struct zebra_vrf *zvrf, vni_t vni); +static int zvni_del(struct zebra_vrf *zvrf, zebra_vni_t *zvni); +static int zvni_send_add_to_client(struct zebra_vrf *zvrf, zebra_vni_t *zvni); +static int zvni_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni); +static void zvni_build_hash_table(struct zebra_vrf *zvrf); +static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep); +static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip); +static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip); +static int zvni_vtep_del(zebra_vni_t *zvni, zebra_vtep_t *zvtep); +static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall); +static int zvni_vtep_install(zebra_vni_t *zvni, struct in_addr *vtep_ip); +static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip); /* Private functions */ @@ -190,893 +140,830 @@ zvni_vtep_uninstall (zebra_vni_t *zvni, struct in_addr *vtep_ip); * display - just because we're dealing with IPv6 addresses that can * widely vary. */ -static void -zvni_find_neigh_addr_width (struct hash_backet *backet, void *ctxt) +static void zvni_find_neigh_addr_width(struct hash_backet *backet, void *ctxt) { - zebra_neigh_t *n; - char buf[INET6_ADDRSTRLEN]; - struct neigh_walk_ctx *wctx = ctxt; - int width; + zebra_neigh_t *n; + char buf[INET6_ADDRSTRLEN]; + struct neigh_walk_ctx *wctx = ctxt; + int width; - n = (zebra_neigh_t *) backet->data; - if (!n) - return; + n = (zebra_neigh_t *)backet->data; + if (!n) + return; - ipaddr2str (&n->ip, buf, sizeof(buf)), - width = strlen (buf); - if (width > wctx->addr_width) - wctx->addr_width = width; + ipaddr2str(&n->ip, buf, sizeof(buf)), width = strlen(buf); + if (width > wctx->addr_width) + wctx->addr_width = width; } /* * Print a specific neighbor entry. */ -static void -zvni_print_neigh (zebra_neigh_t *n, void *ctxt) +static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt) { - struct vty *vty; - char buf1[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; + struct vty *vty; + char buf1[ETHER_ADDR_STRLEN]; + char buf2[INET6_ADDRSTRLEN]; - ipaddr2str (&n->ip, buf2, sizeof(buf2)), - vty = (struct vty *) ctxt; - vty_out(vty, "IP: %s\n", - ipaddr2str (&n->ip, buf2, sizeof(buf2))); - vty_out(vty, " MAC: %s", prefix_mac2str (&n->emac, buf1, sizeof (buf1))); - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) - vty_out(vty, " Remote VTEP: %s", inet_ntoa (n->r_vtep_ip)); - vty_out(vty, "\n"); + ipaddr2str(&n->ip, buf2, sizeof(buf2)), vty = (struct vty *)ctxt; + vty_out(vty, "IP: %s\n", ipaddr2str(&n->ip, buf2, sizeof(buf2))); + vty_out(vty, " MAC: %s", prefix_mac2str(&n->emac, buf1, sizeof(buf1))); + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) + vty_out(vty, " Remote VTEP: %s", inet_ntoa(n->r_vtep_ip)); + vty_out(vty, "\n"); } /* * Print neighbor hash entry - called for display of all neighbors. */ -static void -zvni_print_neigh_hash (struct hash_backet *backet, void *ctxt) -{ - struct vty *vty; - zebra_neigh_t *n; - char buf1[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; - struct neigh_walk_ctx *wctx = ctxt; - - vty = wctx->vty; - n = (zebra_neigh_t *) backet->data; - if (!n) - return; - - prefix_mac2str (&n->emac, buf1, sizeof (buf1)); - ipaddr2str (&n->ip, buf2, sizeof(buf2)); - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) && - !(wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP)) - { - vty_out(vty, "%*s %-6s %-17s\n", - -wctx->addr_width, buf2, "local", buf1); - wctx->count++; - } - else - { - if (wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP) - { - if (IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip)) - { - if (wctx->count == 0) - vty_out(vty, "%*s %-6s %-17s %-21s\n", - -wctx->addr_width, "Neighbor", "Type", "MAC", - "Remote VTEP"); - vty_out(vty, "%*s %-6s %-17s %-21s\n", - -wctx->addr_width, buf2, "remote", buf1, - inet_ntoa (n->r_vtep_ip)); - wctx->count++; - } - } - else - { - vty_out(vty, "%*s %-6s %-17s %-21s\n", - -wctx->addr_width, buf2, "remote", buf1, - inet_ntoa (n->r_vtep_ip)); - wctx->count++; - } - } +static void zvni_print_neigh_hash(struct hash_backet *backet, void *ctxt) +{ + struct vty *vty; + zebra_neigh_t *n; + char buf1[ETHER_ADDR_STRLEN]; + char buf2[INET6_ADDRSTRLEN]; + struct neigh_walk_ctx *wctx = ctxt; + + vty = wctx->vty; + n = (zebra_neigh_t *)backet->data; + if (!n) + return; + + prefix_mac2str(&n->emac, buf1, sizeof(buf1)); + ipaddr2str(&n->ip, buf2, sizeof(buf2)); + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) + && !(wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP)) { + vty_out(vty, "%*s %-6s %-17s\n", -wctx->addr_width, buf2, + "local", buf1); + wctx->count++; + } else { + if (wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP) { + if (IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip)) { + if (wctx->count == 0) + vty_out(vty, "%*s %-6s %-17s %-21s\n", + -wctx->addr_width, "Neighbor", + "Type", "MAC", "Remote VTEP"); + vty_out(vty, "%*s %-6s %-17s %-21s\n", + -wctx->addr_width, buf2, "remote", buf1, + inet_ntoa(n->r_vtep_ip)); + wctx->count++; + } + } else { + vty_out(vty, "%*s %-6s %-17s %-21s\n", + -wctx->addr_width, buf2, "remote", buf1, + inet_ntoa(n->r_vtep_ip)); + wctx->count++; + } + } } /* * Print neighbors for all VNI. */ -static void -zvni_print_neigh_hash_all_vni (struct hash_backet *backet, void *ctxt) +static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet, + void *ctxt) { - struct vty *vty; - zebra_vni_t *zvni; - u_int32_t num_neigh; - struct neigh_walk_ctx wctx; + struct vty *vty; + zebra_vni_t *zvni; + u_int32_t num_neigh; + struct neigh_walk_ctx wctx; - vty = (struct vty *) ctxt; - zvni = (zebra_vni_t *) backet->data; - if (!zvni) - return; + vty = (struct vty *)ctxt; + zvni = (zebra_vni_t *)backet->data; + if (!zvni) + return; - num_neigh = hashcount(zvni->neigh_table); - vty_out(vty, "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n", - zvni->vni, num_neigh); - if (!num_neigh) - return; + num_neigh = hashcount(zvni->neigh_table); + vty_out(vty, "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n", + zvni->vni, num_neigh); + if (!num_neigh) + return; - /* Since we have IPv6 addresses to deal with which can vary widely in - * size, we try to be a bit more elegant in display by first computing - * the maximum width. - */ - memset (&wctx, 0, sizeof (struct neigh_walk_ctx)); - wctx.zvni = zvni; - wctx.vty = vty; - wctx.addr_width = 15; - hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx); + /* Since we have IPv6 addresses to deal with which can vary widely in + * size, we try to be a bit more elegant in display by first computing + * the maximum width. + */ + memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); + wctx.zvni = zvni; + wctx.vty = vty; + wctx.addr_width = 15; + hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx); - vty_out(vty, "%*s %-6s %-17s %-21s\n", - -wctx.addr_width, "IP", "Type", "MAC", - "Remote VTEP"); - hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); + vty_out(vty, "%*s %-6s %-17s %-21s\n", -wctx.addr_width, "IP", "Type", + "MAC", "Remote VTEP"); + hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); } /* * Print a specific MAC entry. */ -static void -zvni_print_mac (zebra_mac_t *mac, void *ctxt) -{ - struct vty *vty; - char buf1[20]; - - vty = (struct vty *) ctxt; - vty_out(vty, "MAC: %s", - prefix_mac2str (&mac->macaddr, buf1, sizeof (buf1))); - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) - { - struct zebra_ns *zns; - struct interface *ifp; - ifindex_t ifindex; - - ifindex = mac->fwd_info.local.ifindex; - zns = zebra_ns_lookup (NS_DEFAULT); - ifp = if_lookup_by_index_per_ns (zns, ifindex); - if (!ifp) // unexpected - return; - vty_out(vty, " Intf: %s(%u)", ifp->name, ifindex); - if (mac->fwd_info.local.vid) - vty_out(vty, " VLAN: %u", mac->fwd_info.local.vid); - } - else - { - vty_out(vty, " Remote VTEP: %s", - inet_ntoa (mac->fwd_info.r_vtep_ip)); - } - vty_out(vty, " ARP ref: %u", mac->neigh_refcnt); - vty_out(vty, "\n"); +static void zvni_print_mac(zebra_mac_t *mac, void *ctxt) +{ + struct vty *vty; + char buf1[20]; + + vty = (struct vty *)ctxt; + vty_out(vty, "MAC: %s", + prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1))); + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { + struct zebra_ns *zns; + struct interface *ifp; + ifindex_t ifindex; + + ifindex = mac->fwd_info.local.ifindex; + zns = zebra_ns_lookup(NS_DEFAULT); + ifp = if_lookup_by_index_per_ns(zns, ifindex); + if (!ifp) // unexpected + return; + vty_out(vty, " Intf: %s(%u)", ifp->name, ifindex); + if (mac->fwd_info.local.vid) + vty_out(vty, " VLAN: %u", mac->fwd_info.local.vid); + } else { + vty_out(vty, " Remote VTEP: %s", + inet_ntoa(mac->fwd_info.r_vtep_ip)); + } + vty_out(vty, " ARP ref: %u", mac->neigh_refcnt); + vty_out(vty, "\n"); } /* * Print MAC hash entry - called for display of all MACs. */ -static void -zvni_print_mac_hash (struct hash_backet *backet, void *ctxt) -{ - struct vty *vty; - zebra_mac_t *mac; - char buf1[20]; - struct mac_walk_ctx *wctx = ctxt; - - vty = wctx->vty; - mac = (zebra_mac_t *) backet->data; - if (!mac) - return; - - prefix_mac2str (&mac->macaddr, buf1, sizeof (buf1)); - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) && - !(wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP)) - { - struct zebra_ns *zns; - ifindex_t ifindex; - struct interface *ifp; - vlanid_t vid; - - zns = zebra_ns_lookup (NS_DEFAULT); - ifindex = mac->fwd_info.local.ifindex; - ifp = if_lookup_by_index_per_ns (zns, ifindex); - if (!ifp) // unexpected - return; - vid = mac->fwd_info.local.vid; - vty_out(vty, "%-17s %-6s %-21s", - buf1, "local", ifp->name); - if (vid) - vty_out(vty, " %-5u", vid); - vty_out(vty, "\n"); - wctx->count++; - } - else - { - if (wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) - { - if (IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, - &wctx->r_vtep_ip)) - { - if (wctx->count == 0) - { - vty_out(vty, "\nVNI %u", - wctx->zvni->vni); - vty_out(vty, "%-17s %-6s %-21s %-5s", - "MAC", "Type", "Intf/Remote VTEP", - "VLAN"); - } - vty_out(vty, "%-17s %-6s %-21s", - buf1, "remote", - inet_ntoa (mac->fwd_info.r_vtep_ip)); - wctx->count++; - } - } - else - { - vty_out(vty, "%-17s %-6s %-21s", - buf1, "remote", - inet_ntoa (mac->fwd_info.r_vtep_ip)); - wctx->count++; - } - } - +static void zvni_print_mac_hash(struct hash_backet *backet, void *ctxt) +{ + struct vty *vty; + zebra_mac_t *mac; + char buf1[20]; + struct mac_walk_ctx *wctx = ctxt; + + vty = wctx->vty; + mac = (zebra_mac_t *)backet->data; + if (!mac) + return; + + prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1)); + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) + && !(wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP)) { + struct zebra_ns *zns; + ifindex_t ifindex; + struct interface *ifp; + vlanid_t vid; + + zns = zebra_ns_lookup(NS_DEFAULT); + ifindex = mac->fwd_info.local.ifindex; + ifp = if_lookup_by_index_per_ns(zns, ifindex); + if (!ifp) // unexpected + return; + vid = mac->fwd_info.local.vid; + vty_out(vty, "%-17s %-6s %-21s", buf1, "local", ifp->name); + if (vid) + vty_out(vty, " %-5u", vid); + vty_out(vty, "\n"); + wctx->count++; + } else { + if (wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) { + if (IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, + &wctx->r_vtep_ip)) { + if (wctx->count == 0) { + vty_out(vty, "\nVNI %u", + wctx->zvni->vni); + vty_out(vty, "%-17s %-6s %-21s %-5s", + "MAC", "Type", + "Intf/Remote VTEP", "VLAN"); + } + vty_out(vty, "%-17s %-6s %-21s", buf1, "remote", + inet_ntoa(mac->fwd_info.r_vtep_ip)); + wctx->count++; + } + } else { + vty_out(vty, "%-17s %-6s %-21s", buf1, "remote", + inet_ntoa(mac->fwd_info.r_vtep_ip)); + wctx->count++; + } + } } /* * Print MACs for all VNI. */ -static void -zvni_print_mac_hash_all_vni (struct hash_backet *backet, void *ctxt) +static void zvni_print_mac_hash_all_vni(struct hash_backet *backet, void *ctxt) { - struct vty *vty; - zebra_vni_t *zvni; - u_int32_t num_macs; - struct mac_walk_ctx *wctx = ctxt; + struct vty *vty; + zebra_vni_t *zvni; + u_int32_t num_macs; + struct mac_walk_ctx *wctx = ctxt; - vty = (struct vty *) wctx->vty; + vty = (struct vty *)wctx->vty; - zvni = (zebra_vni_t *) backet->data; - if (!zvni) - return; - wctx->zvni = zvni; + zvni = (zebra_vni_t *)backet->data; + if (!zvni) + return; + wctx->zvni = zvni; - /*We are iterating over a new VNI, set the count to 0*/ - wctx->count = 0; + /*We are iterating over a new VNI, set the count to 0*/ + wctx->count = 0; - num_macs = hashcount(zvni->mac_table); - if (!num_macs) - return; - if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) - { - vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n", - zvni->vni, num_macs); - vty_out(vty, "%-17s %-6s %-21s %-5s\n", - "MAC", "Type", "Intf/Remote VTEP", "VLAN"); - } + num_macs = hashcount(zvni->mac_table); + if (!num_macs) + return; + if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) { + vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n", + zvni->vni, num_macs); + vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type", + "Intf/Remote VTEP", "VLAN"); + } - hash_iterate(zvni->mac_table, zvni_print_mac_hash, wctx); + hash_iterate(zvni->mac_table, zvni_print_mac_hash, wctx); } /* * Print a specific VNI entry. */ -static void -zvni_print (zebra_vni_t *zvni, void *ctxt) -{ - struct vty *vty; - zebra_vtep_t *zvtep; - u_int32_t num_macs; - u_int32_t num_neigh; - - vty = (struct vty *) ctxt; - - vty_out(vty, "VNI: %u\n", zvni->vni); - if (!zvni->vxlan_if) - { // unexpected - vty_out(vty, " VxLAN interface: unknown\n"); - return; - } - vty_out(vty, " VxLAN interface: %s ifIndex: %u VTEP IP: %s\n", - zvni->vxlan_if->name, zvni->vxlan_if->ifindex, - inet_ntoa(zvni->local_vtep_ip)); - - if (!zvni->vteps) - { - vty_out(vty, " No remote VTEPs known for this VNI\n"); - } - else - { - vty_out(vty, " Remote VTEPs for this VNI:\n"); - for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) - vty_out(vty, " %s\n", - inet_ntoa (zvtep->vtep_ip)); - } - num_macs = hashcount(zvni->mac_table); - vty_out(vty, " Number of MACs (local and remote) known for this VNI: %u\n", - num_macs); - num_neigh = hashcount(zvni->neigh_table); - vty_out(vty, " Number of ARPs (IPv4 and IPv6, local and remote) " - "known for this VNI: %u", num_neigh); +static void zvni_print(zebra_vni_t *zvni, void *ctxt) +{ + struct vty *vty; + zebra_vtep_t *zvtep; + u_int32_t num_macs; + u_int32_t num_neigh; + + vty = (struct vty *)ctxt; + + vty_out(vty, "VNI: %u\n", zvni->vni); + if (!zvni->vxlan_if) { // unexpected + vty_out(vty, " VxLAN interface: unknown\n"); + return; + } + vty_out(vty, " VxLAN interface: %s ifIndex: %u VTEP IP: %s\n", + zvni->vxlan_if->name, zvni->vxlan_if->ifindex, + inet_ntoa(zvni->local_vtep_ip)); + + if (!zvni->vteps) { + vty_out(vty, " No remote VTEPs known for this VNI\n"); + } else { + vty_out(vty, " Remote VTEPs for this VNI:\n"); + for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) + vty_out(vty, " %s\n", inet_ntoa(zvtep->vtep_ip)); + } + num_macs = hashcount(zvni->mac_table); + vty_out(vty, + " Number of MACs (local and remote) known for this VNI: %u\n", + num_macs); + num_neigh = hashcount(zvni->neigh_table); + vty_out(vty, + " Number of ARPs (IPv4 and IPv6, local and remote) " + "known for this VNI: %u", + num_neigh); } /* * Print a VNI hash entry - called for display of all VNIs. */ -static void -zvni_print_hash (struct hash_backet *backet, void *ctxt) +static void zvni_print_hash(struct hash_backet *backet, void *ctxt) { - struct vty *vty; - zebra_vni_t *zvni; - zebra_vtep_t *zvtep; - u_int32_t num_vteps = 0; - u_int32_t num_macs = 0; - u_int32_t num_neigh = 0; + struct vty *vty; + zebra_vni_t *zvni; + zebra_vtep_t *zvtep; + u_int32_t num_vteps = 0; + u_int32_t num_macs = 0; + u_int32_t num_neigh = 0; - vty = (struct vty *) ctxt; - zvni = (zebra_vni_t *) backet->data; - if (!zvni) - return; + vty = (struct vty *)ctxt; + zvni = (zebra_vni_t *)backet->data; + if (!zvni) + return; - zvtep = zvni->vteps; - while (zvtep) - { - num_vteps++; - zvtep = zvtep->next; - } + zvtep = zvni->vteps; + while (zvtep) { + num_vteps++; + zvtep = zvtep->next; + } - num_macs = hashcount(zvni->mac_table); - num_neigh = hashcount(zvni->neigh_table); - vty_out(vty, "%-10u %-21s %-15s %-8u %-8u %-15u\n", - zvni->vni, - zvni->vxlan_if ? zvni->vxlan_if->name : "unknown", - inet_ntoa(zvni->local_vtep_ip), - num_macs, num_neigh, num_vteps); + num_macs = hashcount(zvni->mac_table); + num_neigh = hashcount(zvni->neigh_table); + vty_out(vty, "%-10u %-21s %-15s %-8u %-8u %-15u\n", zvni->vni, + zvni->vxlan_if ? zvni->vxlan_if->name : "unknown", + inet_ntoa(zvni->local_vtep_ip), num_macs, num_neigh, num_vteps); } /* * Inform BGP about local MACIP. */ -static int -zvni_macip_send_msg_to_client (struct zebra_vrf *zvrf, vni_t vni, - struct ethaddr *macaddr, - struct ipaddr *ip, u_char sticky, - u_int16_t cmd) -{ - struct zserv *client; - struct stream *s; - int ipa_len; - char buf[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; - - client = zebra_find_client (ZEBRA_ROUTE_BGP); - /* BGP may not be running. */ - if (!client) - return 0; - - s = client->obuf; - stream_reset (s); - - zserv_create_header (s, cmd, zvrf_id (zvrf)); - stream_putl (s, vni); - stream_put (s, macaddr->octet, ETHER_ADDR_LEN); - if (ip) - { - ipa_len = 0; - if (IS_IPADDR_V4(ip)) - ipa_len = IPV4_MAX_BYTELEN; - else if (IS_IPADDR_V6(ip)) - ipa_len = IPV6_MAX_BYTELEN; - - stream_putl (s, ipa_len); /* IP address length */ - if (ipa_len) - stream_put (s, &ip->ip.addr, ipa_len); /* IP address */ - } - else - stream_putl (s, 0); /* Just MAC. */ - - stream_putc (s, sticky); /* Sticky MAC? */ - - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Send MACIP %s %sMAC %s IP %s VNI %u to %s", - zvrf_id (zvrf), (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del", - sticky ? "sticky " : "", - prefix_mac2str (macaddr, buf, sizeof (buf)), - ipaddr2str (ip, buf2, sizeof(buf2)), vni, - zebra_route_string (client->proto)); - - if (cmd == ZEBRA_MACIP_ADD) - client->macipadd_cnt++; - else - client->macipdel_cnt++; - - return zebra_server_send_message(client); +static int zvni_macip_send_msg_to_client(struct zebra_vrf *zvrf, vni_t vni, + struct ethaddr *macaddr, + struct ipaddr *ip, u_char sticky, + u_int16_t cmd) +{ + struct zserv *client; + struct stream *s; + int ipa_len; + char buf[ETHER_ADDR_STRLEN]; + char buf2[INET6_ADDRSTRLEN]; + + client = zebra_find_client(ZEBRA_ROUTE_BGP); + /* BGP may not be running. */ + if (!client) + return 0; + + s = client->obuf; + stream_reset(s); + + zserv_create_header(s, cmd, zvrf_id(zvrf)); + stream_putl(s, vni); + stream_put(s, macaddr->octet, ETHER_ADDR_LEN); + if (ip) { + ipa_len = 0; + if (IS_IPADDR_V4(ip)) + ipa_len = IPV4_MAX_BYTELEN; + else if (IS_IPADDR_V6(ip)) + ipa_len = IPV6_MAX_BYTELEN; + + stream_putl(s, ipa_len); /* IP address length */ + if (ipa_len) + stream_put(s, &ip->ip.addr, ipa_len); /* IP address */ + } else + stream_putl(s, 0); /* Just MAC. */ + + stream_putc(s, sticky); /* Sticky MAC? */ + + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Send MACIP %s %sMAC %s IP %s VNI %u to %s", + zvrf_id(zvrf), + (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del", + sticky ? "sticky " : "", + prefix_mac2str(macaddr, buf, sizeof(buf)), + ipaddr2str(ip, buf2, sizeof(buf2)), vni, + zebra_route_string(client->proto)); + + if (cmd == ZEBRA_MACIP_ADD) + client->macipadd_cnt++; + else + client->macipdel_cnt++; + + return zebra_server_send_message(client); } /* * Make hash key for neighbors. */ -static unsigned int -neigh_hash_keymake (void *p) +static unsigned int neigh_hash_keymake(void *p) { - zebra_neigh_t *n = p; - struct ipaddr *ip = &n->ip; + zebra_neigh_t *n = p; + struct ipaddr *ip = &n->ip; - if (IS_IPADDR_V4(ip)) - return jhash_1word (ip->ipaddr_v4.s_addr, 0); + if (IS_IPADDR_V4(ip)) + return jhash_1word(ip->ipaddr_v4.s_addr, 0); - return jhash2 (ip->ipaddr_v6.s6_addr32, - ZEBRA_NUM_OF(ip->ipaddr_v6.s6_addr32), 0); + return jhash2(ip->ipaddr_v6.s6_addr32, + ZEBRA_NUM_OF(ip->ipaddr_v6.s6_addr32), 0); } /* * Compare two neighbor hash structures. */ -static int -neigh_cmp (const void *p1, const void *p2) +static int neigh_cmp(const void *p1, const void *p2) { - const zebra_neigh_t *n1 = p1; - const zebra_neigh_t *n2 = p2; + const zebra_neigh_t *n1 = p1; + const zebra_neigh_t *n2 = p2; - if (n1 == NULL && n2 == NULL) - return 1; + if (n1 == NULL && n2 == NULL) + return 1; - if (n1 == NULL || n2 == NULL) - return 0; + if (n1 == NULL || n2 == NULL) + return 0; - return (memcmp(&n1->ip, &n2->ip, sizeof (struct ipaddr)) == 0); + return (memcmp(&n1->ip, &n2->ip, sizeof(struct ipaddr)) == 0); } /* * Callback to allocate neighbor hash entry. */ -static void * -zvni_neigh_alloc (void *p) +static void *zvni_neigh_alloc(void *p) { - const zebra_neigh_t *tmp_n = p; - zebra_neigh_t *n; + const zebra_neigh_t *tmp_n = p; + zebra_neigh_t *n; - n = XCALLOC (MTYPE_NEIGH, sizeof(zebra_neigh_t)); - *n = *tmp_n; + n = XCALLOC(MTYPE_NEIGH, sizeof(zebra_neigh_t)); + *n = *tmp_n; - return ((void *)n); + return ((void *)n); } /* * Add neighbor entry. */ -static zebra_neigh_t * -zvni_neigh_add (zebra_vni_t *zvni, struct ipaddr *ip) +static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip) { - zebra_neigh_t tmp_n; - zebra_neigh_t *n = NULL; + zebra_neigh_t tmp_n; + zebra_neigh_t *n = NULL; - memset (&tmp_n, 0, sizeof (zebra_neigh_t)); - memcpy (&tmp_n.ip, ip, sizeof (struct ipaddr)); - n = hash_get (zvni->neigh_table, &tmp_n, zvni_neigh_alloc); - assert (n); + memset(&tmp_n, 0, sizeof(zebra_neigh_t)); + memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr)); + n = hash_get(zvni->neigh_table, &tmp_n, zvni_neigh_alloc); + assert(n); - return n; + return n; } /* * Delete neighbor entry. */ -static int -zvni_neigh_del (zebra_vni_t *zvni, zebra_neigh_t *n) +static int zvni_neigh_del(zebra_vni_t *zvni, zebra_neigh_t *n) { - zebra_neigh_t *tmp_n; + zebra_neigh_t *tmp_n; - /* Free the VNI hash entry and allocated memory. */ - tmp_n = hash_release (zvni->neigh_table, n); - if (tmp_n) - XFREE(MTYPE_NEIGH, tmp_n); + /* Free the VNI hash entry and allocated memory. */ + tmp_n = hash_release(zvni->neigh_table, n); + if (tmp_n) + XFREE(MTYPE_NEIGH, tmp_n); - return 0; + return 0; } /* * Free neighbor hash entry (callback) */ -static int -zvni_neigh_del_hash_entry (struct hash_backet *backet, void *arg) +static int zvni_neigh_del_hash_entry(struct hash_backet *backet, void *arg) { - struct neigh_walk_ctx *wctx = arg; - zebra_neigh_t *n = backet->data; + struct neigh_walk_ctx *wctx = arg; + zebra_neigh_t *n = backet->data; - if (((wctx->flags & DEL_LOCAL_NEIGH) && (n->flags & ZEBRA_NEIGH_LOCAL)) || - ((wctx->flags & DEL_REMOTE_NEIGH) && (n->flags & ZEBRA_NEIGH_REMOTE)) || - ((wctx->flags & DEL_REMOTE_NEIGH_FROM_VTEP) && - (n->flags & ZEBRA_NEIGH_REMOTE) && - IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip) - )) - { - if (wctx->upd_client && (n->flags & ZEBRA_NEIGH_LOCAL)) - zvni_neigh_send_del_to_client (wctx->zvrf, wctx->zvni->vni, &n->ip, - &n->emac); + if (((wctx->flags & DEL_LOCAL_NEIGH) && (n->flags & ZEBRA_NEIGH_LOCAL)) + || ((wctx->flags & DEL_REMOTE_NEIGH) + && (n->flags & ZEBRA_NEIGH_REMOTE)) + || ((wctx->flags & DEL_REMOTE_NEIGH_FROM_VTEP) + && (n->flags & ZEBRA_NEIGH_REMOTE) + && IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip))) { + if (wctx->upd_client && (n->flags & ZEBRA_NEIGH_LOCAL)) + zvni_neigh_send_del_to_client( + wctx->zvrf, wctx->zvni->vni, &n->ip, &n->emac); - if (wctx->uninstall) - zvni_neigh_uninstall (wctx->zvni, n); + if (wctx->uninstall) + zvni_neigh_uninstall(wctx->zvni, n); - return zvni_neigh_del (wctx->zvni, n); - } + return zvni_neigh_del(wctx->zvni, n); + } - return 0; + return 0; } /* * Delete all neighbor entries from specific VTEP for a particular VNI. */ -static void -zvni_neigh_del_from_vtep (zebra_vni_t *zvni, int uninstall, - struct in_addr *r_vtep_ip) +static void zvni_neigh_del_from_vtep(zebra_vni_t *zvni, int uninstall, + struct in_addr *r_vtep_ip) { - struct neigh_walk_ctx wctx; + struct neigh_walk_ctx wctx; - if (!zvni->neigh_table) - return; + if (!zvni->neigh_table) + return; - memset (&wctx, 0, sizeof (struct neigh_walk_ctx)); - wctx.zvni = zvni; - wctx.uninstall = uninstall; - wctx.flags = DEL_REMOTE_NEIGH_FROM_VTEP; - wctx.r_vtep_ip = *r_vtep_ip; + memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); + wctx.zvni = zvni; + wctx.uninstall = uninstall; + wctx.flags = DEL_REMOTE_NEIGH_FROM_VTEP; + wctx.r_vtep_ip = *r_vtep_ip; - hash_iterate (zvni->neigh_table, - (void (*) (struct hash_backet *, void *)) - zvni_neigh_del_hash_entry, &wctx); + hash_iterate(zvni->neigh_table, + (void (*)(struct hash_backet *, + void *))zvni_neigh_del_hash_entry, + &wctx); } /* * Delete all neighbor entries for this VNI. */ -static void -zvni_neigh_del_all (struct zebra_vrf *zvrf, zebra_vni_t *zvni, - int uninstall, int upd_client, u_int32_t flags) +static void zvni_neigh_del_all(struct zebra_vrf *zvrf, zebra_vni_t *zvni, + int uninstall, int upd_client, u_int32_t flags) { - struct neigh_walk_ctx wctx; + struct neigh_walk_ctx wctx; - if (!zvni->neigh_table) - return; + if (!zvni->neigh_table) + return; - memset (&wctx, 0, sizeof (struct neigh_walk_ctx)); - wctx.zvni = zvni; - wctx.zvrf = zvrf; - wctx.uninstall = uninstall; - wctx.upd_client = upd_client; - wctx.flags = flags; + memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); + wctx.zvni = zvni; + wctx.zvrf = zvrf; + wctx.uninstall = uninstall; + wctx.upd_client = upd_client; + wctx.flags = flags; - hash_iterate (zvni->neigh_table, - (void (*) (struct hash_backet *, void *)) - zvni_neigh_del_hash_entry, &wctx); + hash_iterate(zvni->neigh_table, + (void (*)(struct hash_backet *, + void *))zvni_neigh_del_hash_entry, + &wctx); } /* * Look up neighbor hash entry. */ -static zebra_neigh_t * -zvni_neigh_lookup (zebra_vni_t *zvni, struct ipaddr *ip) +static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip) { - zebra_neigh_t tmp; - zebra_neigh_t *n; + zebra_neigh_t tmp; + zebra_neigh_t *n; - memset (&tmp, 0, sizeof(tmp)); - memcpy (&tmp.ip, ip, sizeof (struct ipaddr)); - n = hash_lookup (zvni->neigh_table, &tmp); + memset(&tmp, 0, sizeof(tmp)); + memcpy(&tmp.ip, ip, sizeof(struct ipaddr)); + n = hash_lookup(zvni->neigh_table, &tmp); - return n; + return n; } /* * Inform BGP about local neighbor addition. */ -static int -zvni_neigh_send_add_to_client (struct zebra_vrf *zvrf, vni_t vni, - struct ipaddr *ip, struct ethaddr *macaddr) +static int zvni_neigh_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni, + struct ipaddr *ip, + struct ethaddr *macaddr) { - return zvni_macip_send_msg_to_client (zvrf, vni, macaddr, ip, 0, - ZEBRA_MACIP_ADD); + return zvni_macip_send_msg_to_client(zvrf, vni, macaddr, ip, 0, + ZEBRA_MACIP_ADD); } /* * Inform BGP about local neighbor deletion. */ -static int -zvni_neigh_send_del_to_client (struct zebra_vrf *zvrf, vni_t vni, - struct ipaddr *ip, struct ethaddr *macaddr) +static int zvni_neigh_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni, + struct ipaddr *ip, + struct ethaddr *macaddr) { - return zvni_macip_send_msg_to_client (zvrf, vni, macaddr, ip, 0, - ZEBRA_MACIP_DEL); + return zvni_macip_send_msg_to_client(zvrf, vni, macaddr, ip, 0, + ZEBRA_MACIP_DEL); } /* * Install remote neighbor into the kernel. */ -static int -zvni_neigh_install (zebra_vni_t *zvni, zebra_neigh_t *n) +static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n) { - struct zebra_vrf *zvrf; - struct zebra_if *zif; - struct zebra_l2info_vxlan *vxl; - struct interface *vlan_if; + struct zebra_vrf *zvrf; + struct zebra_if *zif; + struct zebra_l2info_vxlan *vxl; + struct interface *vlan_if; - if (!(n->flags & ZEBRA_NEIGH_REMOTE)) - return 0; + if (!(n->flags & ZEBRA_NEIGH_REMOTE)) + return 0; - zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); - assert(zvrf); - zif = zvni->vxlan_if->info; - if (!zif) - return -1; - vxl = &zif->l2info.vxl; + zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); + assert(zvrf); + zif = zvni->vxlan_if->info; + if (!zif) + return -1; + vxl = &zif->l2info.vxl; - vlan_if = zvni_map_to_svi (zvrf, vxl->access_vlan, - zif->brslave_info.br_if); - if (!vlan_if) - return -1; + vlan_if = zvni_map_to_svi(zvrf, vxl->access_vlan, + zif->brslave_info.br_if); + if (!vlan_if) + return -1; - return kernel_add_neigh (vlan_if, &n->ip, &n->emac); + return kernel_add_neigh(vlan_if, &n->ip, &n->emac); } /* * Uninstall remote neighbor from the kernel. */ -static int -zvni_neigh_uninstall (zebra_vni_t *zvni, zebra_neigh_t *n) +static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n) { - struct zebra_vrf *zvrf; - struct zebra_if *zif; - struct zebra_l2info_vxlan *vxl; - struct interface *vlan_if; + struct zebra_vrf *zvrf; + struct zebra_if *zif; + struct zebra_l2info_vxlan *vxl; + struct interface *vlan_if; - if (!(n->flags & ZEBRA_NEIGH_REMOTE)) - return 0; + if (!(n->flags & ZEBRA_NEIGH_REMOTE)) + return 0; - zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); - assert(zvrf); - if (!zvni->vxlan_if) - { - zlog_err ("VNI %u hash %p couldn't be uninstalled - no intf", - zvni->vni, zvni); - return -1; - } + zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); + assert(zvrf); + if (!zvni->vxlan_if) { + zlog_err("VNI %u hash %p couldn't be uninstalled - no intf", + zvni->vni, zvni); + return -1; + } - zif = zvni->vxlan_if->info; - if (!zif) - return -1; - vxl = &zif->l2info.vxl; - vlan_if = zvni_map_to_svi (zvrf, vxl->access_vlan, - zif->brslave_info.br_if); - if (!vlan_if) - return -1; + zif = zvni->vxlan_if->info; + if (!zif) + return -1; + vxl = &zif->l2info.vxl; + vlan_if = zvni_map_to_svi(zvrf, vxl->access_vlan, + zif->brslave_info.br_if); + if (!vlan_if) + return -1; - return kernel_del_neigh (vlan_if, &n->ip); + return kernel_del_neigh(vlan_if, &n->ip); } /* * Install neighbor hash entry - called upon access VLAN change. */ -static void -zvni_install_neigh_hash (struct hash_backet *backet, void *ctxt) +static void zvni_install_neigh_hash(struct hash_backet *backet, void *ctxt) { - zebra_neigh_t *n; - struct neigh_walk_ctx *wctx = ctxt; + zebra_neigh_t *n; + struct neigh_walk_ctx *wctx = ctxt; - n = (zebra_neigh_t *) backet->data; - if (!n) - return; + n = (zebra_neigh_t *)backet->data; + if (!n) + return; - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) - zvni_neigh_install (wctx->zvni, n); + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) + zvni_neigh_install(wctx->zvni, n); } /* * Make hash key for MAC. */ -static unsigned int -mac_hash_keymake (void *p) +static unsigned int mac_hash_keymake(void *p) { - zebra_mac_t *pmac = p; - char *pnt = (char *) pmac->macaddr.octet; - unsigned int key = 0; - int c = 0; + zebra_mac_t *pmac = p; + char *pnt = (char *)pmac->macaddr.octet; + unsigned int key = 0; + int c = 0; - key += pnt[c]; - key += pnt[c + 1]; - key += pnt[c + 2]; - key += pnt[c + 3]; - key += pnt[c + 4]; - key += pnt[c + 5]; + key += pnt[c]; + key += pnt[c + 1]; + key += pnt[c + 2]; + key += pnt[c + 3]; + key += pnt[c + 4]; + key += pnt[c + 5]; - return (key); + return (key); } /* * Compare two MAC addresses. */ -static int -mac_cmp (const void *p1, const void *p2) +static int mac_cmp(const void *p1, const void *p2) { - const zebra_mac_t *pmac1 = p1; - const zebra_mac_t *pmac2 = p2; + const zebra_mac_t *pmac1 = p1; + const zebra_mac_t *pmac2 = p2; - if (pmac1 == NULL && pmac2 == NULL) - return 1; + if (pmac1 == NULL && pmac2 == NULL) + return 1; - if (pmac1 == NULL || pmac2 == NULL) - return 0; + if (pmac1 == NULL || pmac2 == NULL) + return 0; - return(memcmp(pmac1->macaddr.octet, pmac2->macaddr.octet, ETHER_ADDR_LEN) == 0); + return (memcmp(pmac1->macaddr.octet, pmac2->macaddr.octet, + ETHER_ADDR_LEN) + == 0); } /* * Callback to allocate MAC hash entry. */ -static void * -zvni_mac_alloc (void *p) +static void *zvni_mac_alloc(void *p) { - const zebra_mac_t *tmp_mac = p; - zebra_mac_t *mac; + const zebra_mac_t *tmp_mac = p; + zebra_mac_t *mac; - mac = XCALLOC (MTYPE_MAC, sizeof(zebra_mac_t)); - *mac = *tmp_mac; + mac = XCALLOC(MTYPE_MAC, sizeof(zebra_mac_t)); + *mac = *tmp_mac; - return ((void *)mac); + return ((void *)mac); } /* * Add MAC entry. */ -static zebra_mac_t * -zvni_mac_add (zebra_vni_t *zvni, struct ethaddr *macaddr) +static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr) { - zebra_mac_t tmp_mac; - zebra_mac_t *mac = NULL; + zebra_mac_t tmp_mac; + zebra_mac_t *mac = NULL; - memset (&tmp_mac, 0, sizeof (zebra_mac_t)); - memcpy(&tmp_mac.macaddr, macaddr, ETHER_ADDR_LEN); - mac = hash_get (zvni->mac_table, &tmp_mac, zvni_mac_alloc); - assert (mac); + memset(&tmp_mac, 0, sizeof(zebra_mac_t)); + memcpy(&tmp_mac.macaddr, macaddr, ETHER_ADDR_LEN); + mac = hash_get(zvni->mac_table, &tmp_mac, zvni_mac_alloc); + assert(mac); - return mac; + return mac; } /* * Delete MAC entry. */ -static int -zvni_mac_del (zebra_vni_t *zvni, zebra_mac_t *mac) +static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac) { - zebra_mac_t *tmp_mac; + zebra_mac_t *tmp_mac; - /* Free the VNI hash entry and allocated memory. */ - tmp_mac = hash_release (zvni->mac_table, mac); - if (tmp_mac) - XFREE(MTYPE_MAC, tmp_mac); + /* Free the VNI hash entry and allocated memory. */ + tmp_mac = hash_release(zvni->mac_table, mac); + if (tmp_mac) + XFREE(MTYPE_MAC, tmp_mac); - return 0; + return 0; } /* * Free MAC hash entry (callback) */ -static int -zvni_mac_del_hash_entry (struct hash_backet *backet, void *arg) +static int zvni_mac_del_hash_entry(struct hash_backet *backet, void *arg) { - struct mac_walk_ctx *wctx = arg; - zebra_mac_t *mac = backet->data; - u_char sticky = 0; + struct mac_walk_ctx *wctx = arg; + zebra_mac_t *mac = backet->data; + u_char sticky = 0; - if (((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_LOCAL)) || - ((wctx->flags & DEL_REMOTE_MAC) && (mac->flags & ZEBRA_MAC_REMOTE)) || - ((wctx->flags & DEL_REMOTE_MAC_FROM_VTEP) && - (mac->flags & ZEBRA_MAC_REMOTE) && - IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &wctx->r_vtep_ip) - )) - { - if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) - { - sticky = CHECK_FLAG (mac->flags, ZEBRA_MAC_STICKY) ? 1: 0; - zvni_mac_send_del_to_client (wctx->zvrf, wctx->zvni->vni, - &mac->macaddr, sticky); - } + if (((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_LOCAL)) + || ((wctx->flags & DEL_REMOTE_MAC) + && (mac->flags & ZEBRA_MAC_REMOTE)) + || ((wctx->flags & DEL_REMOTE_MAC_FROM_VTEP) + && (mac->flags & ZEBRA_MAC_REMOTE) + && IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, + &wctx->r_vtep_ip))) { + if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) { + sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 + : 0; + zvni_mac_send_del_to_client(wctx->zvrf, wctx->zvni->vni, + &mac->macaddr, sticky); + } - if (wctx->uninstall) - zvni_mac_uninstall (wctx->zvni, mac, 0); + if (wctx->uninstall) + zvni_mac_uninstall(wctx->zvni, mac, 0); - return zvni_mac_del (wctx->zvni, mac); - } + return zvni_mac_del(wctx->zvni, mac); + } - return 0; + return 0; } /* * Delete all MAC entries from specific VTEP for a particular VNI. */ -static void -zvni_mac_del_from_vtep (zebra_vni_t *zvni, int uninstall, - struct in_addr *r_vtep_ip) +static void zvni_mac_del_from_vtep(zebra_vni_t *zvni, int uninstall, + struct in_addr *r_vtep_ip) { - struct mac_walk_ctx wctx; + struct mac_walk_ctx wctx; - if (!zvni->mac_table) - return; + if (!zvni->mac_table) + return; - memset (&wctx, 0, sizeof (struct mac_walk_ctx)); - wctx.zvni = zvni; - wctx.uninstall = uninstall; - wctx.flags = DEL_REMOTE_MAC_FROM_VTEP; - wctx.r_vtep_ip = *r_vtep_ip; + memset(&wctx, 0, sizeof(struct mac_walk_ctx)); + wctx.zvni = zvni; + wctx.uninstall = uninstall; + wctx.flags = DEL_REMOTE_MAC_FROM_VTEP; + wctx.r_vtep_ip = *r_vtep_ip; - hash_iterate (zvni->mac_table, - (void (*) (struct hash_backet *, void *)) - zvni_mac_del_hash_entry, &wctx); + hash_iterate(zvni->mac_table, (void (*)(struct hash_backet *, + void *))zvni_mac_del_hash_entry, + &wctx); } /* * Delete all MAC entries for this VNI. */ -static void -zvni_mac_del_all (struct zebra_vrf *zvrf, zebra_vni_t *zvni, - int uninstall, int upd_client, u_int32_t flags) +static void zvni_mac_del_all(struct zebra_vrf *zvrf, zebra_vni_t *zvni, + int uninstall, int upd_client, u_int32_t flags) { - struct mac_walk_ctx wctx; + struct mac_walk_ctx wctx; - if (!zvni->mac_table) - return; + if (!zvni->mac_table) + return; - memset (&wctx, 0, sizeof (struct mac_walk_ctx)); - wctx.zvni = zvni; - wctx.zvrf = zvrf; - wctx.uninstall = uninstall; - wctx.upd_client = upd_client; - wctx.flags = flags; + memset(&wctx, 0, sizeof(struct mac_walk_ctx)); + wctx.zvni = zvni; + wctx.zvrf = zvrf; + wctx.uninstall = uninstall; + wctx.upd_client = upd_client; + wctx.flags = flags; - hash_iterate (zvni->mac_table, - (void (*) (struct hash_backet *, void *)) - zvni_mac_del_hash_entry, &wctx); + hash_iterate(zvni->mac_table, (void (*)(struct hash_backet *, + void *))zvni_mac_del_hash_entry, + &wctx); } /* * Look up MAC hash entry. */ -static zebra_mac_t * -zvni_mac_lookup (zebra_vni_t *zvni, struct ethaddr *mac) +static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *mac) { - zebra_mac_t tmp; - zebra_mac_t *pmac; + zebra_mac_t tmp; + zebra_mac_t *pmac; - memset(&tmp, 0, sizeof(tmp)); - memcpy(&tmp.macaddr, mac, ETHER_ADDR_LEN); - pmac = hash_lookup (zvni->mac_table, &tmp); + memset(&tmp, 0, sizeof(tmp)); + memcpy(&tmp.macaddr, mac, ETHER_ADDR_LEN); + pmac = hash_lookup(zvni->mac_table, &tmp); - return pmac; + return pmac; } /* * Inform BGP about local MAC addition. */ -static int -zvni_mac_send_add_to_client (struct zebra_vrf *zvrf, vni_t vni, - struct ethaddr *macaddr, u_char sticky) +static int zvni_mac_send_add_to_client(struct zebra_vrf *zvrf, vni_t vni, + struct ethaddr *macaddr, u_char sticky) { - return zvni_macip_send_msg_to_client (zvrf, vni, macaddr, NULL, - sticky, ZEBRA_MACIP_ADD); + return zvni_macip_send_msg_to_client(zvrf, vni, macaddr, NULL, sticky, + ZEBRA_MACIP_ADD); } /* * Inform BGP about local MAC deletion. */ -static int -zvni_mac_send_del_to_client (struct zebra_vrf *zvrf, vni_t vni, - struct ethaddr *macaddr, u_char sticky) +static int zvni_mac_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni, + struct ethaddr *macaddr, u_char sticky) { - return zvni_macip_send_msg_to_client (zvrf, vni, macaddr, NULL, - sticky, ZEBRA_MACIP_DEL); + return zvni_macip_send_msg_to_client(zvrf, vni, macaddr, NULL, sticky, + ZEBRA_MACIP_DEL); } /* @@ -1084,54 +971,53 @@ zvni_mac_send_del_to_client (struct zebra_vrf *zvrf, vni_t vni, * notifications, to see if there are of interest. * TODO: Need to make this as a hash table. */ -static zebra_vni_t * -zvni_map_vlan (struct interface *ifp, struct interface *br_if, vlanid_t vid) +static zebra_vni_t *zvni_map_vlan(struct interface *ifp, + struct interface *br_if, vlanid_t vid) { - struct zebra_vrf *zvrf; - struct listnode *node; - struct interface *tmp_if; - struct zebra_if *zif; - struct zebra_l2info_bridge *br; - struct zebra_l2info_vxlan *vxl; - u_char bridge_vlan_aware; - zebra_vni_t *zvni; + struct zebra_vrf *zvrf; + struct listnode *node; + struct interface *tmp_if; + struct zebra_if *zif; + struct zebra_l2info_bridge *br; + struct zebra_l2info_vxlan *vxl; + u_char bridge_vlan_aware; + zebra_vni_t *zvni; - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(ifp->vrf_id); - assert(zvrf); + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(ifp->vrf_id); + assert(zvrf); - /* Determine if bridge is VLAN-aware or not */ - zif = br_if->info; - assert (zif); - br = &zif->l2info.br; - bridge_vlan_aware = br->vlan_aware; + /* Determine if bridge is VLAN-aware or not */ + zif = br_if->info; + assert(zif); + br = &zif->l2info.br; + bridge_vlan_aware = br->vlan_aware; - /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */ - /* TODO: Optimize with a hash. */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (zvrf_id (zvrf)), node, tmp_if)) - { - zif = tmp_if->info; - if (!zif || zif->zif_type != ZEBRA_IF_VXLAN) - continue; - if (!if_is_operative (tmp_if)) - continue; - vxl = &zif->l2info.vxl; + /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */ + /* TODO: Optimize with a hash. */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf)), node, tmp_if)) { + zif = tmp_if->info; + if (!zif || zif->zif_type != ZEBRA_IF_VXLAN) + continue; + if (!if_is_operative(tmp_if)) + continue; + vxl = &zif->l2info.vxl; - if (zif->brslave_info.br_if != br_if) - continue; + if (zif->brslave_info.br_if != br_if) + continue; - if (!bridge_vlan_aware) - break; + if (!bridge_vlan_aware) + break; - if (vxl->access_vlan == vid) - break; - } + if (vxl->access_vlan == vid) + break; + } - if (!tmp_if) - return NULL; + if (!tmp_if) + return NULL; - zvni = zvni_lookup (zvrf, vxl->vni); - return zvni; + zvni = zvni_lookup(zvrf, vxl->vni); + return zvni; } /* @@ -1139,71 +1025,68 @@ zvni_map_vlan (struct interface *ifp, struct interface *br_if, vlanid_t vid) * neighbor notifications, to see if they are of interest. * TODO: Need to make this as a hash table. */ -static zebra_vni_t * -zvni_map_svi (struct interface *ifp, struct interface *br_if) -{ - struct zebra_vrf *zvrf; - struct listnode *node; - struct interface *tmp_if; - struct zebra_if *zif; - struct zebra_l2info_bridge *br; - struct zebra_l2info_vxlan *vxl; - u_char bridge_vlan_aware; - vlanid_t vid = 0; - zebra_vni_t *zvni; - - /* Make sure the linked interface is a bridge. */ - if (!IS_ZEBRA_IF_BRIDGE (br_if)) - return NULL; - - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(ifp->vrf_id); - assert(zvrf); - - /* Determine if bridge is VLAN-aware or not */ - zif = br_if->info; - assert (zif); - br = &zif->l2info.br; - bridge_vlan_aware = br->vlan_aware; - if (bridge_vlan_aware) - { - struct zebra_l2info_vlan *vl; - - if (!IS_ZEBRA_IF_VLAN(ifp)) - return NULL; - - zif = ifp->info; - assert (zif); - vl = &zif->l2info.vl; - vid = vl->vid; - } - - /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */ - /* TODO: Optimize with a hash. */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (zvrf_id (zvrf)), node, tmp_if)) - { - zif = tmp_if->info; - if (!zif || zif->zif_type != ZEBRA_IF_VXLAN) - continue; - if (!if_is_operative (tmp_if)) - continue; - vxl = &zif->l2info.vxl; - - if (zif->brslave_info.br_if != br_if) - continue; - - if (!bridge_vlan_aware) - break; - - if (vxl->access_vlan == vid) - break; - } - - if (!tmp_if) - return NULL; - - zvni = zvni_lookup (zvrf, vxl->vni); - return zvni; +static zebra_vni_t *zvni_map_svi(struct interface *ifp, struct interface *br_if) +{ + struct zebra_vrf *zvrf; + struct listnode *node; + struct interface *tmp_if; + struct zebra_if *zif; + struct zebra_l2info_bridge *br; + struct zebra_l2info_vxlan *vxl; + u_char bridge_vlan_aware; + vlanid_t vid = 0; + zebra_vni_t *zvni; + + /* Make sure the linked interface is a bridge. */ + if (!IS_ZEBRA_IF_BRIDGE(br_if)) + return NULL; + + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(ifp->vrf_id); + assert(zvrf); + + /* Determine if bridge is VLAN-aware or not */ + zif = br_if->info; + assert(zif); + br = &zif->l2info.br; + bridge_vlan_aware = br->vlan_aware; + if (bridge_vlan_aware) { + struct zebra_l2info_vlan *vl; + + if (!IS_ZEBRA_IF_VLAN(ifp)) + return NULL; + + zif = ifp->info; + assert(zif); + vl = &zif->l2info.vl; + vid = vl->vid; + } + + /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */ + /* TODO: Optimize with a hash. */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf)), node, tmp_if)) { + zif = tmp_if->info; + if (!zif || zif->zif_type != ZEBRA_IF_VXLAN) + continue; + if (!if_is_operative(tmp_if)) + continue; + vxl = &zif->l2info.vxl; + + if (zif->brslave_info.br_if != br_if) + continue; + + if (!bridge_vlan_aware) + break; + + if (vxl->access_vlan == vid) + break; + } + + if (!tmp_if) + return NULL; + + zvni = zvni_lookup(zvrf, vxl->vni); + return zvni; } /* Map to SVI on bridge corresponding to specified VLAN. This can be one @@ -1213,551 +1096,515 @@ zvni_map_svi (struct interface *ifp, struct interface *br_if) * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface * itself */ -static struct interface * -zvni_map_to_svi (struct zebra_vrf *zvrf, vlanid_t vid, - struct interface *br_if) -{ - struct listnode *node; - struct interface *tmp_if; - struct zebra_if *zif; - struct zebra_l2info_bridge *br; - struct zebra_l2info_vlan *vl; - u_char bridge_vlan_aware; - - /* Determine if bridge is VLAN-aware or not */ - zif = br_if->info; - assert (zif); - br = &zif->l2info.br; - bridge_vlan_aware = br->vlan_aware; - - /* Check oper status of the SVI. */ - if (!bridge_vlan_aware) - return if_is_operative (br_if) ? br_if : NULL; - - /* Identify corresponding VLAN interface. */ - /* TODO: Optimize with a hash. */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (zvrf_id (zvrf)), node, tmp_if)) - { - /* Check oper status of the SVI. */ - if (!if_is_operative (tmp_if)) - continue; - zif = tmp_if->info; - if (!zif || - zif->zif_type != ZEBRA_IF_VLAN || - zif->link != br_if) - continue; - vl = (struct zebra_l2info_vlan *)&zif->l2info.vl; - - if (vl->vid == vid) - break; - } - - return tmp_if; +static struct interface *zvni_map_to_svi(struct zebra_vrf *zvrf, vlanid_t vid, + struct interface *br_if) +{ + struct listnode *node; + struct interface *tmp_if; + struct zebra_if *zif; + struct zebra_l2info_bridge *br; + struct zebra_l2info_vlan *vl; + u_char bridge_vlan_aware; + + /* Determine if bridge is VLAN-aware or not */ + zif = br_if->info; + assert(zif); + br = &zif->l2info.br; + bridge_vlan_aware = br->vlan_aware; + + /* Check oper status of the SVI. */ + if (!bridge_vlan_aware) + return if_is_operative(br_if) ? br_if : NULL; + + /* Identify corresponding VLAN interface. */ + /* TODO: Optimize with a hash. */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf)), node, tmp_if)) { + /* Check oper status of the SVI. */ + if (!if_is_operative(tmp_if)) + continue; + zif = tmp_if->info; + if (!zif || zif->zif_type != ZEBRA_IF_VLAN + || zif->link != br_if) + continue; + vl = (struct zebra_l2info_vlan *)&zif->l2info.vl; + + if (vl->vid == vid) + break; + } + + return tmp_if; } /* * Install remote MAC into the kernel. */ -static int -zvni_mac_install (zebra_vni_t *zvni, zebra_mac_t *mac) +static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac) { - struct zebra_if *zif; - struct zebra_l2info_vxlan *vxl; - u_char sticky; + struct zebra_if *zif; + struct zebra_l2info_vxlan *vxl; + u_char sticky; - if (!(mac->flags & ZEBRA_MAC_REMOTE)) - return 0; + if (!(mac->flags & ZEBRA_MAC_REMOTE)) + return 0; - zif = zvni->vxlan_if->info; - if (!zif) - return -1; - vxl = &zif->l2info.vxl; + zif = zvni->vxlan_if->info; + if (!zif) + return -1; + vxl = &zif->l2info.vxl; - sticky = CHECK_FLAG (mac->flags, ZEBRA_MAC_STICKY) ? 1: 0; + sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0; - return kernel_add_mac (zvni->vxlan_if, vxl->access_vlan, - &mac->macaddr, mac->fwd_info.r_vtep_ip, sticky); + return kernel_add_mac(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr, + mac->fwd_info.r_vtep_ip, sticky); } /* * Uninstall remote MAC from the kernel. In the scenario where the MAC * moves to remote, we have to uninstall any existing local entry first. */ -static int -zvni_mac_uninstall (zebra_vni_t *zvni, zebra_mac_t *mac, int local) +static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac, int local) { - struct zebra_if *zif; - struct zebra_l2info_vxlan *vxl; - struct in_addr vtep_ip = { .s_addr = 0 }; - struct zebra_ns *zns; - struct interface *ifp; + struct zebra_if *zif; + struct zebra_l2info_vxlan *vxl; + struct in_addr vtep_ip = {.s_addr = 0}; + struct zebra_ns *zns; + struct interface *ifp; - if (!local && !(mac->flags & ZEBRA_MAC_REMOTE)) - return 0; + if (!local && !(mac->flags & ZEBRA_MAC_REMOTE)) + return 0; - if (!zvni->vxlan_if) - { - zlog_err ("VNI %u hash %p couldn't be uninstalled - no intf", - zvni->vni, zvni); - return -1; - } + if (!zvni->vxlan_if) { + zlog_err("VNI %u hash %p couldn't be uninstalled - no intf", + zvni->vni, zvni); + return -1; + } - zif = zvni->vxlan_if->info; - if (!zif) - return -1; - vxl = &zif->l2info.vxl; + zif = zvni->vxlan_if->info; + if (!zif) + return -1; + vxl = &zif->l2info.vxl; - if (local) - { - zns = zebra_ns_lookup (NS_DEFAULT); - ifp = if_lookup_by_index_per_ns (zns, mac->fwd_info.local.ifindex); - if (!ifp) // unexpected - return -1; - } - else - { - ifp = zvni->vxlan_if; - vtep_ip = mac->fwd_info.r_vtep_ip; - } + if (local) { + zns = zebra_ns_lookup(NS_DEFAULT); + ifp = if_lookup_by_index_per_ns(zns, + mac->fwd_info.local.ifindex); + if (!ifp) // unexpected + return -1; + } else { + ifp = zvni->vxlan_if; + vtep_ip = mac->fwd_info.r_vtep_ip; + } - return kernel_del_mac (ifp, vxl->access_vlan, - &mac->macaddr, vtep_ip, local); + return kernel_del_mac(ifp, vxl->access_vlan, &mac->macaddr, vtep_ip, + local); } /* * Install MAC hash entry - called upon access VLAN change. */ -static void -zvni_install_mac_hash (struct hash_backet *backet, void *ctxt) +static void zvni_install_mac_hash(struct hash_backet *backet, void *ctxt) { - zebra_mac_t *mac; - struct mac_walk_ctx *wctx = ctxt; + zebra_mac_t *mac; + struct mac_walk_ctx *wctx = ctxt; - mac = (zebra_mac_t *) backet->data; - if (!mac) - return; + mac = (zebra_mac_t *)backet->data; + if (!mac) + return; - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) - zvni_mac_install (wctx->zvni, mac); + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) + zvni_mac_install(wctx->zvni, mac); } /* * Decrement neighbor refcount of MAC; uninstall and free it if * appropriate. */ -static void -zvni_deref_ip2mac (zebra_vni_t *zvni, zebra_mac_t *mac, int uninstall) +static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac, + int uninstall) { - if (mac->neigh_refcnt) - mac->neigh_refcnt--; + if (mac->neigh_refcnt) + mac->neigh_refcnt--; - if (!CHECK_FLAG (mac->flags, ZEBRA_MAC_AUTO) || - mac->neigh_refcnt > 0) - return; + if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO) || mac->neigh_refcnt > 0) + return; - if (uninstall) - zvni_mac_uninstall (zvni, mac, 0); + if (uninstall) + zvni_mac_uninstall(zvni, mac, 0); - zvni_mac_del (zvni, mac); + zvni_mac_del(zvni, mac); } /* * Read and populate local MACs and neighbors corresponding to this VNI. */ -static void -zvni_read_mac_neigh (struct zebra_vrf *zvrf, zebra_vni_t *zvni, - struct interface *ifp) +static void zvni_read_mac_neigh(struct zebra_vrf *zvrf, zebra_vni_t *zvni, + struct interface *ifp) { - struct zebra_if *zif; - struct interface *vlan_if; - struct zebra_l2info_vxlan *vxl; + struct zebra_if *zif; + struct interface *vlan_if; + struct zebra_l2info_vxlan *vxl; - zif = ifp->info; - vxl = &zif->l2info.vxl; + zif = ifp->info; + vxl = &zif->l2info.vxl; - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u", - ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni, - zif->brslave_info.bridge_ifindex); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u", + ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni, + zif->brslave_info.bridge_ifindex); - macfdb_read_for_bridge (zvrf->zns, ifp, zif->brslave_info.br_if); - vlan_if = zvni_map_to_svi (zvrf, vxl->access_vlan, - zif->brslave_info.br_if); - if (vlan_if) - neigh_read_for_vlan (zvrf->zns, vlan_if); + macfdb_read_for_bridge(zvrf->zns, ifp, zif->brslave_info.br_if); + vlan_if = zvni_map_to_svi(zvrf, vxl->access_vlan, + zif->brslave_info.br_if); + if (vlan_if) + neigh_read_for_vlan(zvrf->zns, vlan_if); } /* * Hash function for VNI. */ -static unsigned int -vni_hash_keymake (void *p) +static unsigned int vni_hash_keymake(void *p) { - const zebra_vni_t *zvni = p; + const zebra_vni_t *zvni = p; - return (jhash_1word(zvni->vni, 0)); + return (jhash_1word(zvni->vni, 0)); } /* * Compare 2 VNI hash entries. */ -static int -vni_hash_cmp (const void *p1, const void *p2) +static int vni_hash_cmp(const void *p1, const void *p2) { - const zebra_vni_t *zvni1 = p1; - const zebra_vni_t *zvni2 = p2; + const zebra_vni_t *zvni1 = p1; + const zebra_vni_t *zvni2 = p2; - return (zvni1->vni == zvni2->vni); + return (zvni1->vni == zvni2->vni); } /* * Callback to allocate VNI hash entry. */ -static void * -zvni_alloc (void *p) +static void *zvni_alloc(void *p) { - const zebra_vni_t *tmp_vni = p; - zebra_vni_t *zvni; + const zebra_vni_t *tmp_vni = p; + zebra_vni_t *zvni; - zvni = XCALLOC (MTYPE_ZVNI, sizeof(zebra_vni_t)); - zvni->vni = tmp_vni->vni; - return ((void *)zvni); + zvni = XCALLOC(MTYPE_ZVNI, sizeof(zebra_vni_t)); + zvni->vni = tmp_vni->vni; + return ((void *)zvni); } /* * Look up VNI hash entry. */ -static zebra_vni_t * -zvni_lookup (struct zebra_vrf *zvrf, vni_t vni) +static zebra_vni_t *zvni_lookup(struct zebra_vrf *zvrf, vni_t vni) { - zebra_vni_t tmp_vni; - zebra_vni_t *zvni = NULL; + zebra_vni_t tmp_vni; + zebra_vni_t *zvni = NULL; - memset (&tmp_vni, 0, sizeof (zebra_vni_t)); - tmp_vni.vni = vni; - zvni = hash_lookup (zvrf->vni_table, &tmp_vni); + memset(&tmp_vni, 0, sizeof(zebra_vni_t)); + tmp_vni.vni = vni; + zvni = hash_lookup(zvrf->vni_table, &tmp_vni); - return zvni; + return zvni; } /* * Add VNI hash entry. */ -static zebra_vni_t * -zvni_add (struct zebra_vrf *zvrf, vni_t vni) +static zebra_vni_t *zvni_add(struct zebra_vrf *zvrf, vni_t vni) { - zebra_vni_t tmp_zvni; - zebra_vni_t *zvni = NULL; + zebra_vni_t tmp_zvni; + zebra_vni_t *zvni = NULL; - memset (&tmp_zvni, 0, sizeof (zebra_vni_t)); - tmp_zvni.vni = vni; - zvni = hash_get (zvrf->vni_table, &tmp_zvni, zvni_alloc); - assert (zvni); + memset(&tmp_zvni, 0, sizeof(zebra_vni_t)); + tmp_zvni.vni = vni; + zvni = hash_get(zvrf->vni_table, &tmp_zvni, zvni_alloc); + assert(zvni); - /* Create hash table for MAC */ - zvni->mac_table = hash_create(mac_hash_keymake, - mac_cmp, - "Zebra VNI MAC Table"); + /* Create hash table for MAC */ + zvni->mac_table = + hash_create(mac_hash_keymake, mac_cmp, "Zebra VNI MAC Table"); - /* Create hash table for neighbors */ - zvni->neigh_table = hash_create(neigh_hash_keymake, - neigh_cmp, - "Zebra VNI Neighbor Table"); + /* Create hash table for neighbors */ + zvni->neigh_table = hash_create(neigh_hash_keymake, neigh_cmp, + "Zebra VNI Neighbor Table"); - return zvni; + return zvni; } /* * Delete VNI hash entry. */ -static int -zvni_del (struct zebra_vrf *zvrf, zebra_vni_t *zvni) +static int zvni_del(struct zebra_vrf *zvrf, zebra_vni_t *zvni) { - zebra_vni_t *tmp_zvni; + zebra_vni_t *tmp_zvni; - zvni->vxlan_if = NULL; + zvni->vxlan_if = NULL; - /* Free the neighbor hash table. */ - hash_free(zvni->neigh_table); - zvni->neigh_table = NULL; + /* Free the neighbor hash table. */ + hash_free(zvni->neigh_table); + zvni->neigh_table = NULL; - /* Free the MAC hash table. */ - hash_free(zvni->mac_table); - zvni->mac_table = NULL; + /* Free the MAC hash table. */ + hash_free(zvni->mac_table); + zvni->mac_table = NULL; - /* Free the VNI hash entry and allocated memory. */ - tmp_zvni = hash_release (zvrf->vni_table, zvni); - if (tmp_zvni) - XFREE(MTYPE_ZVNI, tmp_zvni); + /* Free the VNI hash entry and allocated memory. */ + tmp_zvni = hash_release(zvrf->vni_table, zvni); + if (tmp_zvni) + XFREE(MTYPE_ZVNI, tmp_zvni); - return 0; + return 0; } /* * Inform BGP about local VNI addition. */ -static int -zvni_send_add_to_client (struct zebra_vrf *zvrf, - zebra_vni_t *zvni) +static int zvni_send_add_to_client(struct zebra_vrf *zvrf, zebra_vni_t *zvni) { - struct zserv *client; - struct stream *s; + struct zserv *client; + struct stream *s; - client = zebra_find_client (ZEBRA_ROUTE_BGP); - /* BGP may not be running. */ - if (!client) - return 0; + client = zebra_find_client(ZEBRA_ROUTE_BGP); + /* BGP may not be running. */ + if (!client) + return 0; - s = client->obuf; - stream_reset (s); + s = client->obuf; + stream_reset(s); - zserv_create_header (s, ZEBRA_VNI_ADD, zvrf_id (zvrf)); - stream_putl (s, zvni->vni); - stream_put_in_addr (s, &zvni->local_vtep_ip); + zserv_create_header(s, ZEBRA_VNI_ADD, zvrf_id(zvrf)); + stream_putl(s, zvni->vni); + stream_put_in_addr(s, &zvni->local_vtep_ip); - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Send VNI_ADD %u %s to %s", - zvrf_id (zvrf), zvni->vni, - inet_ntoa(zvni->local_vtep_ip), - zebra_route_string (client->proto)); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Send VNI_ADD %u %s to %s", zvrf_id(zvrf), + zvni->vni, inet_ntoa(zvni->local_vtep_ip), + zebra_route_string(client->proto)); - client->vniadd_cnt++; - return zebra_server_send_message(client); + client->vniadd_cnt++; + return zebra_server_send_message(client); } /* * Inform BGP about local VNI deletion. */ -static int -zvni_send_del_to_client (struct zebra_vrf *zvrf, vni_t vni) +static int zvni_send_del_to_client(struct zebra_vrf *zvrf, vni_t vni) { - struct zserv *client; - struct stream *s; + struct zserv *client; + struct stream *s; - client = zebra_find_client (ZEBRA_ROUTE_BGP); - /* BGP may not be running. */ - if (!client) - return 0; + client = zebra_find_client(ZEBRA_ROUTE_BGP); + /* BGP may not be running. */ + if (!client) + return 0; - s = client->obuf; - stream_reset (s); + s = client->obuf; + stream_reset(s); - zserv_create_header (s, ZEBRA_VNI_DEL, zvrf_id (zvrf)); - stream_putl (s, vni); + zserv_create_header(s, ZEBRA_VNI_DEL, zvrf_id(zvrf)); + stream_putl(s, vni); - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Send VNI_DEL %u to %s", zvrf_id (zvrf), vni, - zebra_route_string (client->proto)); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Send VNI_DEL %u to %s", zvrf_id(zvrf), vni, + zebra_route_string(client->proto)); - client->vnidel_cnt++; - return zebra_server_send_message(client); + client->vnidel_cnt++; + return zebra_server_send_message(client); } /* * Build the VNI hash table by going over the VxLAN interfaces. This * is called when EVPN (advertise-all-vni) is enabled. */ -static void -zvni_build_hash_table (struct zebra_vrf *zvrf) +static void zvni_build_hash_table(struct zebra_vrf *zvrf) { - struct listnode *node; - struct interface *ifp; + struct listnode *node; + struct interface *ifp; - /* Walk VxLAN interfaces and create VNI hash. */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (zvrf_id (zvrf)), node, ifp)) - { - struct zebra_if *zif; - struct zebra_l2info_vxlan *vxl; - zebra_vni_t *zvni; - vni_t vni; + /* Walk VxLAN interfaces and create VNI hash. */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(zvrf_id(zvrf)), node, ifp)) { + struct zebra_if *zif; + struct zebra_l2info_vxlan *vxl; + zebra_vni_t *zvni; + vni_t vni; - zif = ifp->info; - if (!zif || zif->zif_type != ZEBRA_IF_VXLAN) - continue; - vxl = &zif->l2info.vxl; + zif = ifp->info; + if (!zif || zif->zif_type != ZEBRA_IF_VXLAN) + continue; + vxl = &zif->l2info.vxl; - vni = vxl->vni; + vni = vxl->vni; - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Create VNI hash for intf %s(%u) VNI %u local IP %s", - zvrf_id (zvrf), ifp->name, ifp->ifindex, vni, - inet_ntoa (vxl->vtep_ip)); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Create VNI hash for intf %s(%u) VNI %u local IP %s", + zvrf_id(zvrf), ifp->name, ifp->ifindex, vni, + inet_ntoa(vxl->vtep_ip)); - /* VNI hash entry is not expected to exist. */ - zvni = zvni_lookup (zvrf, vni); - if (zvni) - { - zlog_err ("VNI hash already present for VRF %d IF %s(%u) VNI %u", - zvrf_id (zvrf), ifp->name, ifp->ifindex, vni); - continue; - } + /* VNI hash entry is not expected to exist. */ + zvni = zvni_lookup(zvrf, vni); + if (zvni) { + zlog_err( + "VNI hash already present for VRF %d IF %s(%u) VNI %u", + zvrf_id(zvrf), ifp->name, ifp->ifindex, vni); + continue; + } - zvni = zvni_add (zvrf, vni); - if (!zvni) - { - zlog_err ("Failed to add VNI hash, VRF %d IF %s(%u) VNI %u", - zvrf_id (zvrf), ifp->name, ifp->ifindex, vni); - return; - } + zvni = zvni_add(zvrf, vni); + if (!zvni) { + zlog_err( + "Failed to add VNI hash, VRF %d IF %s(%u) VNI %u", + zvrf_id(zvrf), ifp->name, ifp->ifindex, vni); + return; + } - zvni->local_vtep_ip = vxl->vtep_ip; - zvni->vxlan_if = ifp; + zvni->local_vtep_ip = vxl->vtep_ip; + zvni->vxlan_if = ifp; - /* Inform BGP if interface is up and mapped to bridge. */ - if (if_is_operative (ifp) && - zif->brslave_info.br_if) - zvni_send_add_to_client (zvrf, zvni); - } + /* Inform BGP if interface is up and mapped to bridge. */ + if (if_is_operative(ifp) && zif->brslave_info.br_if) + zvni_send_add_to_client(zvrf, zvni); + } } /* * See if remote VTEP matches with prefix. */ -static int -zvni_vtep_match (struct in_addr *vtep_ip, zebra_vtep_t *zvtep) +static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep) { - return (IPV4_ADDR_SAME (vtep_ip, &zvtep->vtep_ip)); + return (IPV4_ADDR_SAME(vtep_ip, &zvtep->vtep_ip)); } /* * Locate remote VTEP in VNI hash table. */ -static zebra_vtep_t * -zvni_vtep_find (zebra_vni_t *zvni, struct in_addr *vtep_ip) +static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip) { - zebra_vtep_t *zvtep; + zebra_vtep_t *zvtep; - if (!zvni) - return NULL; + if (!zvni) + return NULL; - for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) - { - if (zvni_vtep_match (vtep_ip, zvtep)) - break; - } + for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) { + if (zvni_vtep_match(vtep_ip, zvtep)) + break; + } - return zvtep; + return zvtep; } /* * Add remote VTEP to VNI hash table. */ -static zebra_vtep_t * -zvni_vtep_add (zebra_vni_t *zvni, struct in_addr *vtep_ip) +static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip) { - zebra_vtep_t *zvtep; + zebra_vtep_t *zvtep; - zvtep = XCALLOC (MTYPE_ZVNI_VTEP, sizeof(zebra_vtep_t)); - if (!zvtep) - { - zlog_err ("Failed to alloc VTEP entry, VNI %u", zvni->vni); - return NULL; - } + zvtep = XCALLOC(MTYPE_ZVNI_VTEP, sizeof(zebra_vtep_t)); + if (!zvtep) { + zlog_err("Failed to alloc VTEP entry, VNI %u", zvni->vni); + return NULL; + } - zvtep->vtep_ip = *vtep_ip; + zvtep->vtep_ip = *vtep_ip; - if (zvni->vteps) - zvni->vteps->prev = zvtep; - zvtep->next = zvni->vteps; - zvni->vteps = zvtep; + if (zvni->vteps) + zvni->vteps->prev = zvtep; + zvtep->next = zvni->vteps; + zvni->vteps = zvtep; - return zvtep; + return zvtep; } /* * Remove remote VTEP from VNI hash table. */ -static int -zvni_vtep_del (zebra_vni_t *zvni, zebra_vtep_t *zvtep) +static int zvni_vtep_del(zebra_vni_t *zvni, zebra_vtep_t *zvtep) { - if (zvtep->next) - zvtep->next->prev = zvtep->prev; - if (zvtep->prev) - zvtep->prev->next = zvtep->next; - else - zvni->vteps = zvtep->next; + if (zvtep->next) + zvtep->next->prev = zvtep->prev; + if (zvtep->prev) + zvtep->prev->next = zvtep->next; + else + zvni->vteps = zvtep->next; - zvtep->prev = zvtep->next = NULL; - XFREE (MTYPE_ZVNI_VTEP, zvtep); + zvtep->prev = zvtep->next = NULL; + XFREE(MTYPE_ZVNI_VTEP, zvtep); - return 0; + return 0; } /* * Delete all remote VTEPs for this VNI (upon VNI delete). Also * uninstall from kernel if asked to. */ -static int -zvni_vtep_del_all (zebra_vni_t *zvni, int uninstall) +static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall) { - zebra_vtep_t *zvtep, *zvtep_next; + zebra_vtep_t *zvtep, *zvtep_next; - if (!zvni) - return -1; + if (!zvni) + return -1; - for (zvtep = zvni->vteps; zvtep; zvtep = zvtep_next) - { - zvtep_next = zvtep->next; - if (uninstall) - zvni_vtep_uninstall (zvni, &zvtep->vtep_ip); - zvni_vtep_del (zvni, zvtep); - } + for (zvtep = zvni->vteps; zvtep; zvtep = zvtep_next) { + zvtep_next = zvtep->next; + if (uninstall) + zvni_vtep_uninstall(zvni, &zvtep->vtep_ip); + zvni_vtep_del(zvni, zvtep); + } - return 0; + return 0; } /* * Install remote VTEP into the kernel. */ -static int -zvni_vtep_install (zebra_vni_t *zvni, struct in_addr *vtep_ip) +static int zvni_vtep_install(zebra_vni_t *zvni, struct in_addr *vtep_ip) { - return kernel_add_vtep (zvni->vni, zvni->vxlan_if, vtep_ip); + return kernel_add_vtep(zvni->vni, zvni->vxlan_if, vtep_ip); } /* * Uninstall remote VTEP from the kernel. */ -static int -zvni_vtep_uninstall (zebra_vni_t *zvni, struct in_addr *vtep_ip) +static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip) { - if (!zvni->vxlan_if) - { - zlog_err ("VNI %u hash %p couldn't be uninstalled - no intf", - zvni->vni, zvni); - return -1; - } + if (!zvni->vxlan_if) { + zlog_err("VNI %u hash %p couldn't be uninstalled - no intf", + zvni->vni, zvni); + return -1; + } - return kernel_del_vtep (zvni->vni, zvni->vxlan_if, vtep_ip); + return kernel_del_vtep(zvni->vni, zvni->vxlan_if, vtep_ip); } /* * Cleanup VNI/VTEP and update kernel */ -static void -zvni_cleanup_all (struct hash_backet *backet, void *zvrf) +static void zvni_cleanup_all(struct hash_backet *backet, void *zvrf) { - zebra_vni_t *zvni; + zebra_vni_t *zvni; - zvni = (zebra_vni_t *) backet->data; - if (!zvni) - return; + zvni = (zebra_vni_t *)backet->data; + if (!zvni) + return; - /* Free up all neighbors and MACs, if any. */ - zvni_neigh_del_all (zvrf, zvni, 1, 0, DEL_ALL_NEIGH); - zvni_mac_del_all (zvrf, zvni, 1, 0, DEL_ALL_MAC); + /* Free up all neighbors and MACs, if any. */ + zvni_neigh_del_all(zvrf, zvni, 1, 0, DEL_ALL_NEIGH); + zvni_mac_del_all(zvrf, zvni, 1, 0, DEL_ALL_MAC); - /* Free up all remote VTEPs, if any. */ - zvni_vtep_del_all (zvni, 1); + /* Free up all remote VTEPs, if any. */ + zvni_vtep_del_all(zvni, 1); - /* Delete the hash entry. */ - zvni_del (zvrf, zvni); + /* Delete the hash entry. */ + zvni_del(zvrf, zvni); } @@ -1766,281 +1613,265 @@ zvni_cleanup_all (struct hash_backet *backet, void *zvrf) /* * Display Neighbors for a VNI (VTY command handler). */ -void -zebra_vxlan_print_neigh_vni (struct vty *vty, struct zebra_vrf *zvrf, vni_t vni) -{ - zebra_vni_t *zvni; - u_int32_t num_neigh; - struct neigh_walk_ctx wctx; - - if (!EVPN_ENABLED(zvrf)) - return; - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - vty_out (vty, "%% VNI %u does not exist\n", vni); - return; - } - num_neigh = hashcount(zvni->neigh_table); - if (!num_neigh) - return; - - /* Since we have IPv6 addresses to deal with which can vary widely in - * size, we try to be a bit more elegant in display by first computing - * the maximum width. - */ - memset (&wctx, 0, sizeof (struct neigh_walk_ctx)); - wctx.zvni = zvni; - wctx.vty = vty; - wctx.addr_width = 15; - hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx); - - vty_out(vty, "Number of ARPs (local and remote) known for this VNI: %u\n", - num_neigh); - vty_out(vty, "%*s %-6s %-17s %-21s\n", - -wctx.addr_width, "IP", "Type", "MAC", - "Remote VTEP"); - - hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); +void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni) +{ + zebra_vni_t *zvni; + u_int32_t num_neigh; + struct neigh_walk_ctx wctx; + + if (!EVPN_ENABLED(zvrf)) + return; + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + vty_out(vty, "%% VNI %u does not exist\n", vni); + return; + } + num_neigh = hashcount(zvni->neigh_table); + if (!num_neigh) + return; + + /* Since we have IPv6 addresses to deal with which can vary widely in + * size, we try to be a bit more elegant in display by first computing + * the maximum width. + */ + memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); + wctx.zvni = zvni; + wctx.vty = vty; + wctx.addr_width = 15; + hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx); + + vty_out(vty, + "Number of ARPs (local and remote) known for this VNI: %u\n", + num_neigh); + vty_out(vty, "%*s %-6s %-17s %-21s\n", -wctx.addr_width, "IP", "Type", + "MAC", "Remote VTEP"); + + hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); } /* * Display neighbors across all VNIs (VTY command handler). */ -void -zebra_vxlan_print_neigh_all_vni (struct vty *vty, struct zebra_vrf *zvrf) +void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf) { - if (!EVPN_ENABLED(zvrf)) - return; - hash_iterate(zvrf->vni_table, zvni_print_neigh_hash_all_vni, vty); + if (!EVPN_ENABLED(zvrf)) + return; + hash_iterate(zvrf->vni_table, zvni_print_neigh_hash_all_vni, vty); } /* * Display specific neighbor for a VNI, if present (VTY command handler). */ -void -zebra_vxlan_print_specific_neigh_vni (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct ipaddr *ip) +void zebra_vxlan_print_specific_neigh_vni(struct vty *vty, + struct zebra_vrf *zvrf, vni_t vni, + struct ipaddr *ip) { - zebra_vni_t *zvni; - zebra_neigh_t *n; + zebra_vni_t *zvni; + zebra_neigh_t *n; - if (!EVPN_ENABLED(zvrf)) - return; - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - vty_out (vty, "%% VNI %u does not exist", vni); - return; - } - n = zvni_neigh_lookup (zvni, ip); - if (!n) - { - vty_out (vty, "%% Requested neighbor does not exist in VNI %u\n", - vni); - return; - } + if (!EVPN_ENABLED(zvrf)) + return; + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + vty_out(vty, "%% VNI %u does not exist", vni); + return; + } + n = zvni_neigh_lookup(zvni, ip); + if (!n) { + vty_out(vty, "%% Requested neighbor does not exist in VNI %u\n", + vni); + return; + } - zvni_print_neigh (n, vty); + zvni_print_neigh(n, vty); } /* * Display neighbors for a VNI from specific VTEP (VTY command handler). * By definition, these are remote neighbors. */ -void -zebra_vxlan_print_neigh_vni_vtep (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct in_addr vtep_ip) +void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni, struct in_addr vtep_ip) { - zebra_vni_t *zvni; - u_int32_t num_neigh; - struct neigh_walk_ctx wctx; + zebra_vni_t *zvni; + u_int32_t num_neigh; + struct neigh_walk_ctx wctx; - if (!EVPN_ENABLED(zvrf)) - return; - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - vty_out (vty, "%% VNI %u does not exist\n", vni); - return; - } - num_neigh = hashcount(zvni->neigh_table); - if (!num_neigh) - return; + if (!EVPN_ENABLED(zvrf)) + return; + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + vty_out(vty, "%% VNI %u does not exist\n", vni); + return; + } + num_neigh = hashcount(zvni->neigh_table); + if (!num_neigh) + return; - memset (&wctx, 0, sizeof (struct neigh_walk_ctx)); - wctx.zvni = zvni; - wctx.vty = vty; - wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP; - wctx.r_vtep_ip = vtep_ip; + memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); + wctx.zvni = zvni; + wctx.vty = vty; + wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP; + wctx.r_vtep_ip = vtep_ip; - hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); + hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); } /* * Display MACs for a VNI (VTY command handler). */ -void -zebra_vxlan_print_macs_vni (struct vty *vty, struct zebra_vrf *zvrf, vni_t vni) +void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni) { - zebra_vni_t *zvni; - u_int32_t num_macs; - struct mac_walk_ctx wctx; + zebra_vni_t *zvni; + u_int32_t num_macs; + struct mac_walk_ctx wctx; - if (!EVPN_ENABLED(zvrf)) - return; - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - vty_out (vty, "%% VNI %u does not exist\n", vni); - return; - } - num_macs = hashcount(zvni->mac_table); - if (!num_macs) - return; + if (!EVPN_ENABLED(zvrf)) + return; + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + vty_out(vty, "%% VNI %u does not exist\n", vni); + return; + } + num_macs = hashcount(zvni->mac_table); + if (!num_macs) + return; - memset (&wctx, 0, sizeof (struct mac_walk_ctx)); - wctx.zvni = zvni; - wctx.vty = vty; + memset(&wctx, 0, sizeof(struct mac_walk_ctx)); + wctx.zvni = zvni; + wctx.vty = vty; - vty_out(vty, "Number of MACs (local and remote) known for this VNI: %u\n", - num_macs); - vty_out(vty, "%-17s %-6s %-21s %-5s\n", - "MAC", "Type", "Intf/Remote VTEP", "VLAN"); + vty_out(vty, + "Number of MACs (local and remote) known for this VNI: %u\n", + num_macs); + vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type", + "Intf/Remote VTEP", "VLAN"); - hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx); + hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx); } /* * Display MACs for all VNIs (VTY command handler). */ -void -zebra_vxlan_print_macs_all_vni (struct vty *vty, struct zebra_vrf *zvrf) +void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf) { - struct mac_walk_ctx wctx; + struct mac_walk_ctx wctx; - if (!EVPN_ENABLED(zvrf)) - return; - memset (&wctx, 0, sizeof (struct mac_walk_ctx)); - wctx.vty = vty; - hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx); + if (!EVPN_ENABLED(zvrf)) + return; + memset(&wctx, 0, sizeof(struct mac_walk_ctx)); + wctx.vty = vty; + hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx); } /* * Display MACs for all VNIs (VTY command handler). */ -void -zebra_vxlan_print_macs_all_vni_vtep (struct vty *vty, struct zebra_vrf *zvrf, - struct in_addr vtep_ip) +void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty, + struct zebra_vrf *zvrf, + struct in_addr vtep_ip) { - struct mac_walk_ctx wctx; + struct mac_walk_ctx wctx; - if (!EVPN_ENABLED(zvrf)) - return; - memset (&wctx, 0, sizeof (struct mac_walk_ctx)); - wctx.vty = vty; - wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP; - wctx.r_vtep_ip = vtep_ip; - hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx); + if (!EVPN_ENABLED(zvrf)) + return; + memset(&wctx, 0, sizeof(struct mac_walk_ctx)); + wctx.vty = vty; + wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP; + wctx.r_vtep_ip = vtep_ip; + hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx); } /* * Display specific MAC for a VNI, if present (VTY command handler). */ -void -zebra_vxlan_print_specific_mac_vni (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct ethaddr *macaddr) +void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni, struct ethaddr *macaddr) { - zebra_vni_t *zvni; - zebra_mac_t *mac; + zebra_vni_t *zvni; + zebra_mac_t *mac; - if (!EVPN_ENABLED(zvrf)) - return; - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - vty_out (vty, "%% VNI %u does not exist\n", vni); - return; - } - mac = zvni_mac_lookup (zvni, macaddr); - if (!mac) - { - vty_out (vty, "%% Requested MAC does not exist in VNI %u\n", - vni); - return; - } + if (!EVPN_ENABLED(zvrf)) + return; + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + vty_out(vty, "%% VNI %u does not exist\n", vni); + return; + } + mac = zvni_mac_lookup(zvni, macaddr); + if (!mac) { + vty_out(vty, "%% Requested MAC does not exist in VNI %u\n", + vni); + return; + } - zvni_print_mac (mac, vty); + zvni_print_mac(mac, vty); } /* * Display MACs for a VNI from specific VTEP (VTY command handler). */ -void -zebra_vxlan_print_macs_vni_vtep (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct in_addr vtep_ip) +void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni, struct in_addr vtep_ip) { - zebra_vni_t *zvni; - u_int32_t num_macs; - struct mac_walk_ctx wctx; + zebra_vni_t *zvni; + u_int32_t num_macs; + struct mac_walk_ctx wctx; - if (!EVPN_ENABLED(zvrf)) - return; - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - vty_out (vty, "%% VNI %u does not exist\n", vni); - return; - } - num_macs = hashcount(zvni->mac_table); - if (!num_macs) - return; - memset (&wctx, 0, sizeof (struct mac_walk_ctx)); - wctx.zvni = zvni; - wctx.vty = vty; - wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP; - wctx.r_vtep_ip = vtep_ip; - hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx); + if (!EVPN_ENABLED(zvrf)) + return; + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + vty_out(vty, "%% VNI %u does not exist\n", vni); + return; + } + num_macs = hashcount(zvni->mac_table); + if (!num_macs) + return; + memset(&wctx, 0, sizeof(struct mac_walk_ctx)); + wctx.zvni = zvni; + wctx.vty = vty; + wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP; + wctx.r_vtep_ip = vtep_ip; + hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx); } /* * Display VNI information (VTY command handler). */ -void -zebra_vxlan_print_vni (struct vty *vty, struct zebra_vrf *zvrf, vni_t vni) +void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni) { - zebra_vni_t *zvni; + zebra_vni_t *zvni; - if (!EVPN_ENABLED(zvrf)) - return; - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - vty_out (vty, "%% VNI %u does not exist\n", vni); - return; - } - zvni_print (zvni, (void *)vty); + if (!EVPN_ENABLED(zvrf)) + return; + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + vty_out(vty, "%% VNI %u does not exist\n", vni); + return; + } + zvni_print(zvni, (void *)vty); } /* * Display VNI hash table (VTY command handler). */ -void -zebra_vxlan_print_vnis (struct vty *vty, struct zebra_vrf *zvrf) +void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf) { - u_int32_t num_vnis; + u_int32_t num_vnis; - if (!EVPN_ENABLED(zvrf)) - return; - num_vnis = hashcount(zvrf->vni_table); - if (!num_vnis) - return; - vty_out(vty, "Number of VNIs: %u\n", num_vnis); - vty_out(vty, "%-10s %-21s %-15s %-8s %-8s %-15s\n", - "VNI", "VxLAN IF", "VTEP IP", "# MACs", "# ARPs", - "# Remote VTEPs"); - hash_iterate(zvrf->vni_table, zvni_print_hash, vty); + if (!EVPN_ENABLED(zvrf)) + return; + num_vnis = hashcount(zvrf->vni_table); + if (!num_vnis) + return; + vty_out(vty, "Number of VNIs: %u\n", num_vnis); + vty_out(vty, "%-10s %-21s %-15s %-8s %-8s %-15s\n", "VNI", "VxLAN IF", + "VTEP IP", "# MACs", "# ARPs", "# Remote VTEPs"); + hash_iterate(zvrf->vni_table, zvni_print_hash, vty); } /* @@ -2049,293 +1880,292 @@ zebra_vxlan_print_vnis (struct vty *vty, struct zebra_vrf *zvrf) * our database or being re-added to the kernel (if it is a valid * remote neighbor). */ -int -zebra_vxlan_local_neigh_del (struct interface *ifp, - struct interface *link_if, - struct ipaddr *ip) -{ - zebra_vni_t *zvni; - zebra_neigh_t *n; - struct zebra_vrf *zvrf; - char buf[INET6_ADDRSTRLEN]; - - /* We are only interested in neighbors on an SVI that resides on top - * of a VxLAN bridge. - */ - zvni = zvni_map_svi (ifp, link_if); - if (!zvni) - return 0; - if (!zvni->vxlan_if) - { - zlog_err ("VNI %u hash %p doesn't have intf upon local neighbor DEL", - zvni->vni, zvni); - return -1; - } - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Del neighbor %s intf %s(%u) -> VNI %u", - ifp->vrf_id, ipaddr2str (ip, buf, sizeof(buf)), - ifp->name, ifp->ifindex, zvni->vni); - - /* If entry doesn't exist, nothing to do. */ - n = zvni_neigh_lookup (zvni, ip); - if (!n) - return 0; - - /* If it is a remote entry, the kernel has aged this out or someone has - * deleted it, it needs to be re-installed as Quagga is the owner. - */ - if (CHECK_FLAG (n->flags, ZEBRA_NEIGH_REMOTE)) - { - zvni_neigh_install (zvni, n); - return 0; - } - - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); - assert(zvrf); - - /* Remove neighbor from BGP. */ - zvni_neigh_send_del_to_client (zvrf, zvni->vni, &n->ip, &n->emac); - - /* Delete this neighbor entry. */ - zvni_neigh_del (zvni, n); - - return 0; +int zebra_vxlan_local_neigh_del(struct interface *ifp, + struct interface *link_if, struct ipaddr *ip) +{ + zebra_vni_t *zvni; + zebra_neigh_t *n; + struct zebra_vrf *zvrf; + char buf[INET6_ADDRSTRLEN]; + + /* We are only interested in neighbors on an SVI that resides on top + * of a VxLAN bridge. + */ + zvni = zvni_map_svi(ifp, link_if); + if (!zvni) + return 0; + if (!zvni->vxlan_if) { + zlog_err( + "VNI %u hash %p doesn't have intf upon local neighbor DEL", + zvni->vni, zvni); + return -1; + } + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Del neighbor %s intf %s(%u) -> VNI %u", + ifp->vrf_id, ipaddr2str(ip, buf, sizeof(buf)), + ifp->name, ifp->ifindex, zvni->vni); + + /* If entry doesn't exist, nothing to do. */ + n = zvni_neigh_lookup(zvni, ip); + if (!n) + return 0; + + /* If it is a remote entry, the kernel has aged this out or someone has + * deleted it, it needs to be re-installed as Quagga is the owner. + */ + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) { + zvni_neigh_install(zvni, n); + return 0; + } + + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); + assert(zvrf); + + /* Remove neighbor from BGP. */ + zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip, &n->emac); + + /* Delete this neighbor entry. */ + zvni_neigh_del(zvni, n); + + return 0; } /* * Handle neighbor add or update (on a VLAN device / L3 interface) * from the kernel. */ -int -zebra_vxlan_local_neigh_add_update (struct interface *ifp, - struct interface *link_if, - struct ipaddr *ip, - struct ethaddr *macaddr, - u_int16_t state, - u_char ext_learned) -{ - zebra_vni_t *zvni; - zebra_neigh_t *n; - struct zebra_vrf *zvrf; - char buf[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; - int send_upd = 1, send_del = 0; - - /* We are only interested in neighbors on an SVI that resides on top - * of a VxLAN bridge. - */ - zvni = zvni_map_svi (ifp, link_if); - if (!zvni) - return 0; - - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); - assert(zvrf); - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x " - "%s-> VNI %u", - ifp->vrf_id, ipaddr2str (ip, buf2, sizeof(buf2)), - prefix_mac2str (macaddr, buf, sizeof (buf)), - ifp->name, ifp->ifindex, state, - ext_learned ? "ext-learned " : "", zvni->vni); - - /* If same entry already exists, it might be a change or it might be a - * move from remote to local. - */ - n = zvni_neigh_lookup (zvni, ip); - if (n) - { - if (CHECK_FLAG (n->flags, ZEBRA_NEIGH_LOCAL)) - { - if (memcmp (n->emac.octet, macaddr->octet, ETHER_ADDR_LEN) == 0) - { - if (n->ifindex == ifp->ifindex) - /* we're not interested in whatever has changed. */ - return 0; - /* client doesn't care about a purely local change. */ - send_upd = 0; - } - else - /* If the MAC has changed, issue a delete first as this means a - * different MACIP route. - */ - send_del = 1; - } - else if (ext_learned) - /* The neighbor is remote and that is the notification we got. */ - { - /* TODO: Evaluate if we need to do anything here. */ - return 0; - } - else - /* Neighbor has moved from remote to local. */ - { - UNSET_FLAG (n->flags, ZEBRA_NEIGH_REMOTE); - n->r_vtep_ip.s_addr = 0; - } - } - else - { - n = zvni_neigh_add (zvni, ip); - if (!n) - { - zlog_err ("%u:Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u", - ifp->vrf_id, ipaddr2str (ip, buf2, sizeof(buf2)), - prefix_mac2str (macaddr, buf, sizeof (buf)), - ifp->name, ifp->ifindex, zvni->vni); - return -1; - } - } - - /* Issue delete for older info, if needed. */ - if (send_del) - zvni_neigh_send_del_to_client (zvrf, zvni->vni, &n->ip, &n->emac); - - /* Set "local" forwarding info. */ - SET_FLAG (n->flags, ZEBRA_NEIGH_LOCAL); - memcpy (&n->emac, macaddr, ETHER_ADDR_LEN); - n->ifindex = ifp->ifindex; - - /* Inform BGP if required. */ - if (send_upd) - return zvni_neigh_send_add_to_client (zvrf, zvni->vni, ip, macaddr); - - return 0; +int zebra_vxlan_local_neigh_add_update(struct interface *ifp, + struct interface *link_if, + struct ipaddr *ip, + struct ethaddr *macaddr, u_int16_t state, + u_char ext_learned) +{ + zebra_vni_t *zvni; + zebra_neigh_t *n; + struct zebra_vrf *zvrf; + char buf[ETHER_ADDR_STRLEN]; + char buf2[INET6_ADDRSTRLEN]; + int send_upd = 1, send_del = 0; + + /* We are only interested in neighbors on an SVI that resides on top + * of a VxLAN bridge. + */ + zvni = zvni_map_svi(ifp, link_if); + if (!zvni) + return 0; + + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); + assert(zvrf); + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x " + "%s-> VNI %u", + ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)), + prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, + ifp->ifindex, state, ext_learned ? "ext-learned " : "", + zvni->vni); + + /* If same entry already exists, it might be a change or it might be a + * move from remote to local. + */ + n = zvni_neigh_lookup(zvni, ip); + if (n) { + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { + if (memcmp(n->emac.octet, macaddr->octet, + ETHER_ADDR_LEN) + == 0) { + if (n->ifindex == ifp->ifindex) + /* we're not interested in whatever has + * changed. */ + return 0; + /* client doesn't care about a purely local + * change. */ + send_upd = 0; + } else + /* If the MAC has changed, issue a delete first + * as this means a + * different MACIP route. + */ + send_del = 1; + } else if (ext_learned) + /* The neighbor is remote and that is the notification we got. + */ + { + /* TODO: Evaluate if we need to do anything here. */ + return 0; + } else + /* Neighbor has moved from remote to local. */ + { + UNSET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE); + n->r_vtep_ip.s_addr = 0; + } + } else { + n = zvni_neigh_add(zvni, ip); + if (!n) { + zlog_err( + "%u:Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u", + ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)), + prefix_mac2str(macaddr, buf, sizeof(buf)), + ifp->name, ifp->ifindex, zvni->vni); + return -1; + } + } + + /* Issue delete for older info, if needed. */ + if (send_del) + zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip, + &n->emac); + + /* Set "local" forwarding info. */ + SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); + memcpy(&n->emac, macaddr, ETHER_ADDR_LEN); + n->ifindex = ifp->ifindex; + + /* Inform BGP if required. */ + if (send_upd) + return zvni_neigh_send_add_to_client(zvrf, zvni->vni, ip, + macaddr); + + return 0; } /* * Handle message from client to delete a remote MACIP for a VNI. */ -int zebra_vxlan_remote_macip_del (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) -{ - struct stream *s; - vni_t vni; - struct ethaddr macaddr; - struct ipaddr ip; - struct in_addr vtep_ip; - zebra_vni_t *zvni; - zebra_mac_t *mac; - zebra_neigh_t *n; - u_short l = 0, ipa_len; - char buf[ETHER_ADDR_STRLEN]; - char buf1[INET6_ADDRSTRLEN]; - - s = client->ibuf; - - while (l < length) - { - /* Obtain each remote MACIP and process. */ - /* Message contains VNI, followed by MAC followed by IP (if any) - * followed by remote VTEP IP. - */ - mac = NULL; - n = NULL; - memset (&ip, 0, sizeof (ip)); - vni = (vni_t) stream_getl (s); - stream_get (&macaddr.octet, s, ETHER_ADDR_LEN); - ipa_len = stream_getl (s); - if (ipa_len) - { - ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4: IPADDR_V6; - stream_get (&ip.ip.addr, s, ipa_len); - } - l += 4 + ETHER_ADDR_LEN + 4 + ipa_len; - vtep_ip.s_addr = stream_get_ipv4(s); - l += IPV4_MAX_BYTELEN; - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s", - zvrf_id (zvrf), - prefix_mac2str (&macaddr, buf, sizeof (buf)), - ipaddr2str (&ip, buf1, sizeof (buf1)), - vni, inet_ntoa (vtep_ip), - zebra_route_string (client->proto)); - - /* Locate VNI hash entry - expected to exist. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("Failed to locate VNI hash upon remote MACIP DEL, " - "VRF %d VNI %u", zvrf_id (zvrf), vni); - continue; - } - if (!zvni->vxlan_if) - { - zlog_err ("VNI %u hash %p doesn't have intf upon remote MACIP DEL", - vni, zvni); - continue; - } - - /* The remote VTEP specified is normally expected to exist, but it is - * possible that the peer may delete the VTEP before deleting any MACs - * referring to the VTEP, in which case the handler (see remote_vtep_del) - * would have already deleted the MACs. - */ - if (!zvni_vtep_find (zvni, &vtep_ip)) - continue; - - /* If the local VxLAN interface is not up (should be a transient - * event), there's nothing more to do. - */ - if (!if_is_operative (zvni->vxlan_if)) - continue; - - mac = zvni_mac_lookup (zvni, &macaddr); - if (ipa_len) - n = zvni_neigh_lookup (zvni, &ip); - - if (n && !mac) - { - zlog_err ("failed to locate MAC %s for neigh %s in VRF %u VNI %u", - prefix_mac2str (&macaddr, buf, sizeof (buf)), - ipaddr2str (&ip, buf1, sizeof (buf1)), - zvrf_id (zvrf), vni); - continue; - } - - /* If the remote mac or neighbor doesn't exist there is nothing more - * to do. Otherwise, uninstall the entry and then remove it. - */ - if (!mac && !n) - continue; - - /* Uninstall remote neighbor or MAC. */ - if (n) - { - /* When the MAC changes for an IP, it is possible the client may - * update the new MAC before trying to delete the "old" neighbor - * (as these are two different MACIP routes). Do the delete only - * if the MAC matches. - */ - if (CHECK_FLAG (n->flags, ZEBRA_NEIGH_REMOTE) && - (memcmp (n->emac.octet, macaddr.octet, ETHER_ADDR_LEN) == 0)) - { - zvni_neigh_uninstall (zvni, n); - zvni_neigh_del (zvni, n); - zvni_deref_ip2mac (zvni, mac, 1); - } - } - else - { - if (CHECK_FLAG (mac->flags, ZEBRA_MAC_REMOTE)) - { - if (!mac->neigh_refcnt) - { - zvni_mac_uninstall (zvni, mac, 0); - zvni_mac_del (zvni, mac); - } - else - SET_FLAG (mac->flags, ZEBRA_MAC_AUTO); - } - } - } - - return 0; +int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) +{ + struct stream *s; + vni_t vni; + struct ethaddr macaddr; + struct ipaddr ip; + struct in_addr vtep_ip; + zebra_vni_t *zvni; + zebra_mac_t *mac; + zebra_neigh_t *n; + u_short l = 0, ipa_len; + char buf[ETHER_ADDR_STRLEN]; + char buf1[INET6_ADDRSTRLEN]; + + s = client->ibuf; + + while (l < length) { + /* Obtain each remote MACIP and process. */ + /* Message contains VNI, followed by MAC followed by IP (if any) + * followed by remote VTEP IP. + */ + mac = NULL; + n = NULL; + memset(&ip, 0, sizeof(ip)); + vni = (vni_t)stream_getl(s); + stream_get(&macaddr.octet, s, ETHER_ADDR_LEN); + ipa_len = stream_getl(s); + if (ipa_len) { + ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4 + : IPADDR_V6; + stream_get(&ip.ip.addr, s, ipa_len); + } + l += 4 + ETHER_ADDR_LEN + 4 + ipa_len; + vtep_ip.s_addr = stream_get_ipv4(s); + l += IPV4_MAX_BYTELEN; + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Recv MACIP Del MAC %s IP %s VNI %u Remote VTEP %s from %s", + zvrf_id(zvrf), + prefix_mac2str(&macaddr, buf, sizeof(buf)), + ipaddr2str(&ip, buf1, sizeof(buf1)), vni, + inet_ntoa(vtep_ip), + zebra_route_string(client->proto)); + + /* Locate VNI hash entry - expected to exist. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "Failed to locate VNI hash upon remote MACIP DEL, " + "VRF %d VNI %u", + zvrf_id(zvrf), vni); + continue; + } + if (!zvni->vxlan_if) { + zlog_err( + "VNI %u hash %p doesn't have intf upon remote MACIP DEL", + vni, zvni); + continue; + } + + /* The remote VTEP specified is normally expected to exist, but + * it is + * possible that the peer may delete the VTEP before deleting + * any MACs + * referring to the VTEP, in which case the handler (see + * remote_vtep_del) + * would have already deleted the MACs. + */ + if (!zvni_vtep_find(zvni, &vtep_ip)) + continue; + + /* If the local VxLAN interface is not up (should be a transient + * event), there's nothing more to do. + */ + if (!if_is_operative(zvni->vxlan_if)) + continue; + + mac = zvni_mac_lookup(zvni, &macaddr); + if (ipa_len) + n = zvni_neigh_lookup(zvni, &ip); + + if (n && !mac) { + zlog_err( + "failed to locate MAC %s for neigh %s in VRF %u VNI %u", + prefix_mac2str(&macaddr, buf, sizeof(buf)), + ipaddr2str(&ip, buf1, sizeof(buf1)), + zvrf_id(zvrf), vni); + continue; + } + + /* If the remote mac or neighbor doesn't exist there is nothing + * more + * to do. Otherwise, uninstall the entry and then remove it. + */ + if (!mac && !n) + continue; + + /* Uninstall remote neighbor or MAC. */ + if (n) { + /* When the MAC changes for an IP, it is possible the + * client may + * update the new MAC before trying to delete the "old" + * neighbor + * (as these are two different MACIP routes). Do the + * delete only + * if the MAC matches. + */ + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) + && (memcmp(n->emac.octet, macaddr.octet, + ETHER_ADDR_LEN) + == 0)) { + zvni_neigh_uninstall(zvni, n); + zvni_neigh_del(zvni, n); + zvni_deref_ip2mac(zvni, mac, 1); + } + } else { + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { + if (!mac->neigh_refcnt) { + zvni_mac_uninstall(zvni, mac, 0); + zvni_mac_del(zvni, mac); + } else + SET_FLAG(mac->flags, ZEBRA_MAC_AUTO); + } + } + } + + return 0; } /* @@ -2343,205 +2173,206 @@ int zebra_vxlan_remote_macip_del (struct zserv *client, int sock, * could be just the add of a MAC address or the add of a neighbor * (IP+MAC). */ -int -zebra_vxlan_remote_macip_add (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) -{ - struct stream *s; - vni_t vni; - struct ethaddr macaddr; - struct ipaddr ip; - struct in_addr vtep_ip; - zebra_vni_t *zvni; - zebra_vtep_t *zvtep; - zebra_mac_t *mac, *old_mac; - zebra_neigh_t *n; - u_short l = 0, ipa_len; - int update_mac = 0, update_neigh = 0; - char buf[ETHER_ADDR_STRLEN]; - char buf1[INET6_ADDRSTRLEN]; - u_char sticky; - - assert (EVPN_ENABLED (zvrf)); - - s = client->ibuf; - - while (l < length) - { - /* Obtain each remote MACIP and process. */ - /* Message contains VNI, followed by MAC followed by IP (if any) - * followed by remote VTEP IP. - */ - update_mac = update_neigh = 0; - mac = NULL; - n = NULL; - memset (&ip, 0, sizeof (ip)); - vni = (vni_t) stream_getl (s); - stream_get (&macaddr.octet, s, ETHER_ADDR_LEN); - ipa_len = stream_getl (s); - if (ipa_len) - { - ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4: IPADDR_V6; - stream_get (&ip.ip.addr, s, ipa_len); - } - l += 4 + ETHER_ADDR_LEN + 4 + ipa_len; - vtep_ip.s_addr = stream_get_ipv4 (s); - l += IPV4_MAX_BYTELEN; - - /* Get 'sticky' flag. */ - sticky = stream_getc(s); - l++; - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Recv MACIP Add %sMAC %s IP %s VNI %u Remote VTEP %s from %s", - zvrf_id (zvrf), - sticky ? "sticky " : "", - prefix_mac2str (&macaddr, buf, sizeof (buf)), - ipaddr2str (&ip, buf1, sizeof (buf1)), - vni, inet_ntoa (vtep_ip), - zebra_route_string (client->proto)); - - /* Locate VNI hash entry - expected to exist. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - zlog_err ("Failed to locate VNI hash upon remote MACIP ADD, VRF %d VNI %u", - zvrf_id (zvrf), vni); - continue; - } - if (!zvni->vxlan_if) - { - zlog_err ("VNI %u hash %p doesn't have intf upon remote MACIP add", - vni, zvni); - continue; - } - /* If the local VxLAN interface is not up (should be a transient - * event), there's nothing more to do. - */ - if (!if_is_operative (zvni->vxlan_if)) - continue; - - /* The remote VTEP specified should normally exist, but it is possible - * that when peering comes up, peer may advertise MACIP routes before - * advertising type-3 routes. - */ - zvtep = zvni_vtep_find (zvni, &vtep_ip); - if (!zvtep) - { - if (zvni_vtep_add (zvni, &vtep_ip) == NULL) - { - zlog_err ("Failed to add remote VTEP, VRF %d VNI %u zvni %p", - zvrf_id (zvrf), vni, zvni); - continue; - } - - zvni_vtep_install (zvni, &vtep_ip); - } - - /* First, check if the remote MAC is unknown or has a change. If so, - * that needs to be updated first. Note that client could install - * MAC and MACIP separately or just install the latter. - */ - mac = zvni_mac_lookup (zvni, &macaddr); - if (!mac || !CHECK_FLAG (mac->flags, ZEBRA_MAC_REMOTE) || - (CHECK_FLAG (mac->flags, ZEBRA_MAC_STICKY) ? 1: 0) != sticky || - !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip)) - update_mac = 1; - - if (update_mac) - { - if (!mac) - { - mac = zvni_mac_add (zvni, &macaddr); - if (!mac) - { - zlog_warn ("%u:Failed to add MAC %s VNI %u Remote VTEP %s", - zvrf_id (zvrf), - prefix_mac2str (&macaddr, buf, sizeof (buf)), - vni, inet_ntoa (vtep_ip)); - return -1; - } - - /* Is this MAC created for a MACIP? */ - if (ipa_len) - SET_FLAG (mac->flags, ZEBRA_MAC_AUTO); - } - else if (CHECK_FLAG (mac->flags, ZEBRA_MAC_LOCAL)) - { - /* Moving from local to remote, issue delete. */ - zvni_mac_uninstall (zvni, mac, 1); - } - - /* Set "auto" and "remote" forwarding info. */ - UNSET_FLAG (mac->flags, ZEBRA_MAC_LOCAL); - memset (&mac->fwd_info, 0, sizeof (mac->fwd_info)); - SET_FLAG (mac->flags, ZEBRA_MAC_REMOTE); - mac->fwd_info.r_vtep_ip = vtep_ip; - - if (sticky) - SET_FLAG (mac->flags, ZEBRA_MAC_STICKY); - else - UNSET_FLAG (mac->flags, ZEBRA_MAC_STICKY); - - /* Install the entry. */ - zvni_mac_install (zvni, mac); - } - - /* If there is no IP, continue - after clearing AUTO flag of MAC. */ - if (!ipa_len) - { - UNSET_FLAG (mac->flags, ZEBRA_MAC_AUTO); - continue; - } - - /* Check if the remote neighbor itself is unknown or has a change. - * If so, create or update and then install the entry. - */ - n = zvni_neigh_lookup (zvni, &ip); - if (!n || !CHECK_FLAG (n->flags, ZEBRA_NEIGH_REMOTE) || - (memcmp(&n->emac, &macaddr, sizeof (macaddr)) != 0) || - !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip)) - update_neigh = 1; - - if (update_neigh) - { - if (!n) - { - n = zvni_neigh_add (zvni, &ip); - if (!n) - { - zlog_warn ("%u:Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s", - zvrf_id (zvrf), ipaddr2str (&ip, buf1, sizeof (buf1)), - prefix_mac2str (&macaddr, buf, sizeof (buf)), - vni, inet_ntoa (vtep_ip)); - return -1; - } - - /* New neighbor referring to this MAC. */ - mac->neigh_refcnt++; - } - else if (memcmp(&n->emac, &macaddr, sizeof (macaddr)) != 0) - { - /* MAC change, update ref counts for old and new MAC. */ - old_mac = zvni_mac_lookup (zvni, &n->emac); - if (old_mac) - zvni_deref_ip2mac (zvni, old_mac, 1); - mac->neigh_refcnt++; - } - - /* Set "remote" forwarding info. */ - UNSET_FLAG (n->flags, ZEBRA_NEIGH_LOCAL); - /* TODO: Handle MAC change. */ - memcpy (&n->emac, &macaddr, ETHER_ADDR_LEN); - n->r_vtep_ip = vtep_ip; - SET_FLAG (n->flags, ZEBRA_NEIGH_REMOTE); - - /* Install the entry. */ - zvni_neigh_install (zvni, n); - } - } - - return 0; +int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) +{ + struct stream *s; + vni_t vni; + struct ethaddr macaddr; + struct ipaddr ip; + struct in_addr vtep_ip; + zebra_vni_t *zvni; + zebra_vtep_t *zvtep; + zebra_mac_t *mac, *old_mac; + zebra_neigh_t *n; + u_short l = 0, ipa_len; + int update_mac = 0, update_neigh = 0; + char buf[ETHER_ADDR_STRLEN]; + char buf1[INET6_ADDRSTRLEN]; + u_char sticky; + + assert(EVPN_ENABLED(zvrf)); + + s = client->ibuf; + + while (l < length) { + /* Obtain each remote MACIP and process. */ + /* Message contains VNI, followed by MAC followed by IP (if any) + * followed by remote VTEP IP. + */ + update_mac = update_neigh = 0; + mac = NULL; + n = NULL; + memset(&ip, 0, sizeof(ip)); + vni = (vni_t)stream_getl(s); + stream_get(&macaddr.octet, s, ETHER_ADDR_LEN); + ipa_len = stream_getl(s); + if (ipa_len) { + ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4 + : IPADDR_V6; + stream_get(&ip.ip.addr, s, ipa_len); + } + l += 4 + ETHER_ADDR_LEN + 4 + ipa_len; + vtep_ip.s_addr = stream_get_ipv4(s); + l += IPV4_MAX_BYTELEN; + + /* Get 'sticky' flag. */ + sticky = stream_getc(s); + l++; + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Recv MACIP Add %sMAC %s IP %s VNI %u Remote VTEP %s from %s", + zvrf_id(zvrf), sticky ? "sticky " : "", + prefix_mac2str(&macaddr, buf, sizeof(buf)), + ipaddr2str(&ip, buf1, sizeof(buf1)), vni, + inet_ntoa(vtep_ip), + zebra_route_string(client->proto)); + + /* Locate VNI hash entry - expected to exist. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + zlog_err( + "Failed to locate VNI hash upon remote MACIP ADD, VRF %d VNI %u", + zvrf_id(zvrf), vni); + continue; + } + if (!zvni->vxlan_if) { + zlog_err( + "VNI %u hash %p doesn't have intf upon remote MACIP add", + vni, zvni); + continue; + } + /* If the local VxLAN interface is not up (should be a transient + * event), there's nothing more to do. + */ + if (!if_is_operative(zvni->vxlan_if)) + continue; + + /* The remote VTEP specified should normally exist, but it is + * possible + * that when peering comes up, peer may advertise MACIP routes + * before + * advertising type-3 routes. + */ + zvtep = zvni_vtep_find(zvni, &vtep_ip); + if (!zvtep) { + if (zvni_vtep_add(zvni, &vtep_ip) == NULL) { + zlog_err( + "Failed to add remote VTEP, VRF %d VNI %u zvni %p", + zvrf_id(zvrf), vni, zvni); + continue; + } + + zvni_vtep_install(zvni, &vtep_ip); + } + + /* First, check if the remote MAC is unknown or has a change. If + * so, + * that needs to be updated first. Note that client could + * install + * MAC and MACIP separately or just install the latter. + */ + mac = zvni_mac_lookup(zvni, &macaddr); + if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) + || (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0) + != sticky + || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip)) + update_mac = 1; + + if (update_mac) { + if (!mac) { + mac = zvni_mac_add(zvni, &macaddr); + if (!mac) { + zlog_warn( + "%u:Failed to add MAC %s VNI %u Remote VTEP %s", + zvrf_id(zvrf), + prefix_mac2str(&macaddr, buf, + sizeof(buf)), + vni, inet_ntoa(vtep_ip)); + return -1; + } + + /* Is this MAC created for a MACIP? */ + if (ipa_len) + SET_FLAG(mac->flags, ZEBRA_MAC_AUTO); + } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { + /* Moving from local to remote, issue delete. */ + zvni_mac_uninstall(zvni, mac, 1); + } + + /* Set "auto" and "remote" forwarding info. */ + UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL); + memset(&mac->fwd_info, 0, sizeof(mac->fwd_info)); + SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE); + mac->fwd_info.r_vtep_ip = vtep_ip; + + if (sticky) + SET_FLAG(mac->flags, ZEBRA_MAC_STICKY); + else + UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY); + + /* Install the entry. */ + zvni_mac_install(zvni, mac); + } + + /* If there is no IP, continue - after clearing AUTO flag of + * MAC. */ + if (!ipa_len) { + UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO); + continue; + } + + /* Check if the remote neighbor itself is unknown or has a + * change. + * If so, create or update and then install the entry. + */ + n = zvni_neigh_lookup(zvni, &ip); + if (!n || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) + || (memcmp(&n->emac, &macaddr, sizeof(macaddr)) != 0) + || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip)) + update_neigh = 1; + + if (update_neigh) { + if (!n) { + n = zvni_neigh_add(zvni, &ip); + if (!n) { + zlog_warn( + "%u:Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s", + zvrf_id(zvrf), + ipaddr2str(&ip, buf1, + sizeof(buf1)), + prefix_mac2str(&macaddr, buf, + sizeof(buf)), + vni, inet_ntoa(vtep_ip)); + return -1; + } + + /* New neighbor referring to this MAC. */ + mac->neigh_refcnt++; + } else if (memcmp(&n->emac, &macaddr, sizeof(macaddr)) + != 0) { + /* MAC change, update ref counts for old and new + * MAC. */ + old_mac = zvni_mac_lookup(zvni, &n->emac); + if (old_mac) + zvni_deref_ip2mac(zvni, old_mac, 1); + mac->neigh_refcnt++; + } + + /* Set "remote" forwarding info. */ + UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); + /* TODO: Handle MAC change. */ + memcpy(&n->emac, &macaddr, ETHER_ADDR_LEN); + n->r_vtep_ip = vtep_ip; + SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE); + + /* Install the entry. */ + zvni_neigh_install(zvni, n); + } + } + + return 0; } /* @@ -2549,61 +2380,60 @@ zebra_vxlan_remote_macip_add (struct zserv *client, int sock, * us, this must involve a multihoming scenario. Treat this as implicit delete * of any prior local MAC. */ -int -zebra_vxlan_check_del_local_mac (struct interface *ifp, - struct interface *br_if, - struct ethaddr *macaddr, - vlanid_t vid) +int zebra_vxlan_check_del_local_mac(struct interface *ifp, + struct interface *br_if, + struct ethaddr *macaddr, vlanid_t vid) { - struct zebra_if *zif; - struct zebra_vrf *zvrf; - struct zebra_l2info_vxlan *vxl; - vni_t vni; - zebra_vni_t *zvni; - zebra_mac_t *mac; - char buf[ETHER_ADDR_STRLEN]; - u_char sticky; + struct zebra_if *zif; + struct zebra_vrf *zvrf; + struct zebra_l2info_vxlan *vxl; + vni_t vni; + zebra_vni_t *zvni; + zebra_mac_t *mac; + char buf[ETHER_ADDR_STRLEN]; + u_char sticky; - zif = ifp->info; - assert(zif); - vxl = &zif->l2info.vxl; - vni = vxl->vni; + zif = ifp->info; + assert(zif); + vxl = &zif->l2info.vxl; + vni = vxl->vni; - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(ifp->vrf_id); - assert(zvrf); + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(ifp->vrf_id); + assert(zvrf); - /* If EVPN is not enabled, nothing to do. */ - if (!EVPN_ENABLED(zvrf)) - return 0; + /* If EVPN is not enabled, nothing to do. */ + if (!EVPN_ENABLED(zvrf)) + return 0; - /* Locate hash entry; it is expected to exist. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - return 0; + /* Locate hash entry; it is expected to exist. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) + return 0; - /* If entry doesn't exist, nothing to do. */ - mac = zvni_mac_lookup (zvni, macaddr); - if (!mac) - return 0; + /* If entry doesn't exist, nothing to do. */ + mac = zvni_mac_lookup(zvni, macaddr); + if (!mac) + return 0; - /* Is it a local entry? */ - if (!CHECK_FLAG (mac->flags, ZEBRA_MAC_LOCAL)) - return 0; + /* Is it a local entry? */ + if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) + return 0; - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Add/update remote MAC %s intf %s(%u) VNI %u - del local", - ifp->vrf_id, prefix_mac2str (macaddr, buf, sizeof (buf)), - ifp->name, ifp->ifindex, vni); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Add/update remote MAC %s intf %s(%u) VNI %u - del local", + ifp->vrf_id, prefix_mac2str(macaddr, buf, sizeof(buf)), + ifp->name, ifp->ifindex, vni); - /* Remove MAC from BGP. */ - sticky = CHECK_FLAG (mac->flags, ZEBRA_MAC_STICKY) ? 1: 0; - zvni_mac_send_del_to_client (zvrf, zvni->vni, macaddr, sticky); + /* Remove MAC from BGP. */ + sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0; + zvni_mac_send_del_to_client(zvrf, zvni->vni, macaddr, sticky); - /* Delete this MAC entry. */ - zvni_mac_del (zvni, mac); + /* Delete this MAC entry. */ + zvni_mac_del(zvni, mac); - return 0; + return 0; } /* @@ -2611,346 +2441,346 @@ zebra_vxlan_check_del_local_mac (struct interface *ifp, * This can happen because the remote MAC entries are also added as "dynamic", * so the kernel can ageout the entry. */ -int -zebra_vxlan_check_readd_remote_mac (struct interface *ifp, - struct interface *br_if, - struct ethaddr *macaddr, - vlanid_t vid) +int zebra_vxlan_check_readd_remote_mac(struct interface *ifp, + struct interface *br_if, + struct ethaddr *macaddr, vlanid_t vid) { - struct zebra_if *zif; - struct zebra_vrf *zvrf; - struct zebra_l2info_vxlan *vxl; - vni_t vni; - zebra_vni_t *zvni; - zebra_mac_t *mac; - char buf[ETHER_ADDR_STRLEN]; + struct zebra_if *zif; + struct zebra_vrf *zvrf; + struct zebra_l2info_vxlan *vxl; + vni_t vni; + zebra_vni_t *zvni; + zebra_mac_t *mac; + char buf[ETHER_ADDR_STRLEN]; - zif = ifp->info; - assert(zif); - vxl = &zif->l2info.vxl; - vni = vxl->vni; + zif = ifp->info; + assert(zif); + vxl = &zif->l2info.vxl; + vni = vxl->vni; - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(ifp->vrf_id); - assert(zvrf); + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(ifp->vrf_id); + assert(zvrf); - /* If EVPN is not enabled, nothing to do. */ - if (!EVPN_ENABLED(zvrf)) - return 0; + /* If EVPN is not enabled, nothing to do. */ + if (!EVPN_ENABLED(zvrf)) + return 0; - /* Locate hash entry; it is expected to exist. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - return 0; + /* Locate hash entry; it is expected to exist. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) + return 0; - /* If entry doesn't exist, nothing to do. */ - mac = zvni_mac_lookup (zvni, macaddr); - if (!mac) - return 0; + /* If entry doesn't exist, nothing to do. */ + mac = zvni_mac_lookup(zvni, macaddr); + if (!mac) + return 0; - /* Is it a remote entry? */ - if (!CHECK_FLAG (mac->flags, ZEBRA_MAC_REMOTE)) - return 0; + /* Is it a remote entry? */ + if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) + return 0; - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Del remote MAC %s intf %s(%u) VNI %u - readd", - ifp->vrf_id, prefix_mac2str (macaddr, buf, sizeof (buf)), - ifp->name, ifp->ifindex, vni); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Del remote MAC %s intf %s(%u) VNI %u - readd", + ifp->vrf_id, + prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, + ifp->ifindex, vni); - zvni_mac_install (zvni, mac); - return 0; + zvni_mac_install(zvni, mac); + return 0; } /* * Handle local MAC delete (on a port or VLAN corresponding to this VNI). */ -int -zebra_vxlan_local_mac_del (struct interface *ifp, struct interface *br_if, - struct ethaddr *macaddr, vlanid_t vid) +int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if, + struct ethaddr *macaddr, vlanid_t vid) { - zebra_vni_t *zvni; - zebra_mac_t *mac; - struct zebra_vrf *zvrf; - char buf[ETHER_ADDR_STRLEN]; - u_char sticky; + zebra_vni_t *zvni; + zebra_mac_t *mac; + struct zebra_vrf *zvrf; + char buf[ETHER_ADDR_STRLEN]; + u_char sticky; - /* We are interested in MACs only on ports or (port, VLAN) that - * map to a VNI. - */ - zvni = zvni_map_vlan (ifp, br_if, vid); - if (!zvni) - return 0; - if (!zvni->vxlan_if) - { - zlog_err ("VNI %u hash %p doesn't have intf upon local MAC DEL", - zvni->vni, zvni); - return -1; - } + /* We are interested in MACs only on ports or (port, VLAN) that + * map to a VNI. + */ + zvni = zvni_map_vlan(ifp, br_if, vid); + if (!zvni) + return 0; + if (!zvni->vxlan_if) { + zlog_err("VNI %u hash %p doesn't have intf upon local MAC DEL", + zvni->vni, zvni); + return -1; + } - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Del MAC %s intf %s(%u) VID %u -> VNI %u", - ifp->vrf_id, prefix_mac2str (macaddr, buf, sizeof (buf)), - ifp->name, ifp->ifindex, vid, zvni->vni); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Del MAC %s intf %s(%u) VID %u -> VNI %u", + ifp->vrf_id, + prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, + ifp->ifindex, vid, zvni->vni); - /* If entry doesn't exist, nothing to do. */ - mac = zvni_mac_lookup (zvni, macaddr); - if (!mac) - return 0; + /* If entry doesn't exist, nothing to do. */ + mac = zvni_mac_lookup(zvni, macaddr); + if (!mac) + return 0; - /* Is it a local entry? */ - if (!CHECK_FLAG (mac->flags, ZEBRA_MAC_LOCAL)) - return 0; + /* Is it a local entry? */ + if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) + return 0; - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); - assert(zvrf); + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); + assert(zvrf); - /* Remove MAC from BGP. */ - sticky = CHECK_FLAG (mac->flags, ZEBRA_MAC_STICKY) ? 1: 0; - zvni_mac_send_del_to_client (zvrf, zvni->vni, macaddr, sticky); + /* Remove MAC from BGP. */ + sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0; + zvni_mac_send_del_to_client(zvrf, zvni->vni, macaddr, sticky); - /* Delete this MAC entry. */ - zvni_mac_del (zvni, mac); + /* Delete this MAC entry. */ + zvni_mac_del(zvni, mac); - return 0; + return 0; } /* * Handle local MAC add (on a port or VLAN corresponding to this VNI). */ -int -zebra_vxlan_local_mac_add_update (struct interface *ifp, struct interface *br_if, - struct ethaddr *macaddr, vlanid_t vid, - u_char sticky) -{ - zebra_vni_t *zvni; - zebra_mac_t *mac; - struct zebra_vrf *zvrf; - char buf[ETHER_ADDR_STRLEN]; - int add = 1; - u_char mac_sticky; - - /* We are interested in MACs only on ports or (port, VLAN) that - * map to a VNI. - */ - zvni = zvni_map_vlan (ifp, br_if, vid); - if (!zvni) - { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI", - ifp->vrf_id, - sticky ? "sticky " : "", - prefix_mac2str (macaddr, buf, sizeof (buf)), - ifp->name, ifp->ifindex, vid); - return 0; - } - - if (!zvni->vxlan_if) - { - zlog_err ("VNI %u hash %p doesn't have intf upon local MAC ADD", - zvni->vni, zvni); - return -1; - } - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u", - ifp->vrf_id, - sticky ? "sticky " : "", - prefix_mac2str (macaddr, buf, sizeof (buf)), - ifp->name, ifp->ifindex, vid, zvni->vni); - - /* If same entry already exists, nothing to do. */ - mac = zvni_mac_lookup (zvni, macaddr); - if (mac) - { - if (CHECK_FLAG (mac->flags, ZEBRA_MAC_LOCAL)) - { - mac_sticky = CHECK_FLAG (mac->flags, ZEBRA_MAC_STICKY) ? 1: 0; - - if (mac_sticky == sticky && - mac->fwd_info.local.ifindex == ifp->ifindex && - mac->fwd_info.local.vid == vid) - { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, " - "entry exists and has not changed ", - ifp->vrf_id, - sticky ? "sticky " : "", - prefix_mac2str (macaddr, buf, sizeof (buf)), - ifp->name, ifp->ifindex, vid, zvni->vni); - return 0; - } - - add = 0; /* This is an update of local interface. */ - } - } - - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); - assert(zvrf); - - if (!mac) - { - mac = zvni_mac_add (zvni, macaddr); - if (!mac) - { - zlog_err ("%u:Failed to add MAC %s intf %s(%u) VID %u", - ifp->vrf_id, prefix_mac2str (macaddr, buf, sizeof (buf)), - ifp->name, ifp->ifindex, vid); - return -1; - } - } - - /* Set "local" forwarding info. */ - UNSET_FLAG (mac->flags, ZEBRA_MAC_REMOTE); - memset (&mac->fwd_info, 0, sizeof (mac->fwd_info)); - SET_FLAG (mac->flags, ZEBRA_MAC_LOCAL); - mac->fwd_info.local.ifindex = ifp->ifindex; - mac->fwd_info.local.vid = vid; - - if (sticky) - SET_FLAG (mac->flags, ZEBRA_MAC_STICKY); - else - UNSET_FLAG (mac->flags, ZEBRA_MAC_STICKY); - - /* Inform BGP if required. */ - if (add) - return zvni_mac_send_add_to_client (zvrf, zvni->vni, macaddr, sticky); - - return 0; +int zebra_vxlan_local_mac_add_update(struct interface *ifp, + struct interface *br_if, + struct ethaddr *macaddr, vlanid_t vid, + u_char sticky) +{ + zebra_vni_t *zvni; + zebra_mac_t *mac; + struct zebra_vrf *zvrf; + char buf[ETHER_ADDR_STRLEN]; + int add = 1; + u_char mac_sticky; + + /* We are interested in MACs only on ports or (port, VLAN) that + * map to a VNI. + */ + zvni = zvni_map_vlan(ifp, br_if, vid); + if (!zvni) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI", + ifp->vrf_id, sticky ? "sticky " : "", + prefix_mac2str(macaddr, buf, sizeof(buf)), + ifp->name, ifp->ifindex, vid); + return 0; + } + + if (!zvni->vxlan_if) { + zlog_err("VNI %u hash %p doesn't have intf upon local MAC ADD", + zvni->vni, zvni); + return -1; + } + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u", + ifp->vrf_id, sticky ? "sticky " : "", + prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, + ifp->ifindex, vid, zvni->vni); + + /* If same entry already exists, nothing to do. */ + mac = zvni_mac_lookup(zvni, macaddr); + if (mac) { + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { + mac_sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) + ? 1 + : 0; + + if (mac_sticky == sticky + && mac->fwd_info.local.ifindex == ifp->ifindex + && mac->fwd_info.local.vid == vid) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, " + "entry exists and has not changed ", + ifp->vrf_id, + sticky ? "sticky " : "", + prefix_mac2str(macaddr, buf, + sizeof(buf)), + ifp->name, ifp->ifindex, vid, + zvni->vni); + return 0; + } + + add = 0; /* This is an update of local interface. */ + } + } + + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); + assert(zvrf); + + if (!mac) { + mac = zvni_mac_add(zvni, macaddr); + if (!mac) { + zlog_err("%u:Failed to add MAC %s intf %s(%u) VID %u", + ifp->vrf_id, + prefix_mac2str(macaddr, buf, sizeof(buf)), + ifp->name, ifp->ifindex, vid); + return -1; + } + } + + /* Set "local" forwarding info. */ + UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE); + memset(&mac->fwd_info, 0, sizeof(mac->fwd_info)); + SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL); + mac->fwd_info.local.ifindex = ifp->ifindex; + mac->fwd_info.local.vid = vid; + + if (sticky) + SET_FLAG(mac->flags, ZEBRA_MAC_STICKY); + else + UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY); + + /* Inform BGP if required. */ + if (add) + return zvni_mac_send_add_to_client(zvrf, zvni->vni, macaddr, + sticky); + + return 0; } /* * Handle message from client to delete a remote VTEP for a VNI. */ -int zebra_vxlan_remote_vtep_del (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) -{ - struct stream *s; - u_short l = 0; - vni_t vni; - struct in_addr vtep_ip; - zebra_vni_t *zvni; - zebra_vtep_t *zvtep; - - s = client->ibuf; - - while (l < length) - { - /* Obtain each remote VTEP and process. */ - vni = (vni_t) stream_getl (s); - l += 4; - vtep_ip.s_addr = stream_get_ipv4 (s); - l += IPV4_MAX_BYTELEN; - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Recv VTEP_DEL %s VNI %u from %s", - zvrf_id (zvrf), inet_ntoa (vtep_ip), - vni, zebra_route_string (client->proto)); - - /* Locate VNI hash entry - expected to exist. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("Failed to locate VNI hash upon remote VTEP DEL, " - "VRF %d VNI %u", zvrf_id (zvrf), vni); - continue; - } - - /* If the remote VTEP does not exist, there's nothing more to do. - * Otherwise, uninstall any remote MACs pointing to this VTEP and - * then, the VTEP entry itself and remove it. - */ - zvtep = zvni_vtep_find (zvni, &vtep_ip); - if (!zvtep) - continue; - - zvni_neigh_del_from_vtep (zvni, 1, &vtep_ip); - zvni_mac_del_from_vtep (zvni, 1, &vtep_ip); - zvni_vtep_uninstall (zvni, &vtep_ip); - zvni_vtep_del (zvni, zvtep); - } - - return 0; +int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) +{ + struct stream *s; + u_short l = 0; + vni_t vni; + struct in_addr vtep_ip; + zebra_vni_t *zvni; + zebra_vtep_t *zvtep; + + s = client->ibuf; + + while (l < length) { + /* Obtain each remote VTEP and process. */ + vni = (vni_t)stream_getl(s); + l += 4; + vtep_ip.s_addr = stream_get_ipv4(s); + l += IPV4_MAX_BYTELEN; + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Recv VTEP_DEL %s VNI %u from %s", + zvrf_id(zvrf), inet_ntoa(vtep_ip), vni, + zebra_route_string(client->proto)); + + /* Locate VNI hash entry - expected to exist. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "Failed to locate VNI hash upon remote VTEP DEL, " + "VRF %d VNI %u", + zvrf_id(zvrf), vni); + continue; + } + + /* If the remote VTEP does not exist, there's nothing more to + * do. + * Otherwise, uninstall any remote MACs pointing to this VTEP + * and + * then, the VTEP entry itself and remove it. + */ + zvtep = zvni_vtep_find(zvni, &vtep_ip); + if (!zvtep) + continue; + + zvni_neigh_del_from_vtep(zvni, 1, &vtep_ip); + zvni_mac_del_from_vtep(zvni, 1, &vtep_ip); + zvni_vtep_uninstall(zvni, &vtep_ip); + zvni_vtep_del(zvni, zvtep); + } + + return 0; } /* * Handle message from client to add a remote VTEP for a VNI. */ -int zebra_vxlan_remote_vtep_add (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) -{ - struct stream *s; - u_short l = 0; - vni_t vni; - struct in_addr vtep_ip; - zebra_vni_t *zvni; - - assert (EVPN_ENABLED (zvrf)); - - s = client->ibuf; - - while (l < length) - { - /* Obtain each remote VTEP and process. */ - vni = (vni_t) stream_getl (s); - l += 4; - vtep_ip.s_addr = stream_get_ipv4 (s); - l += IPV4_MAX_BYTELEN; - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Recv VTEP_ADD %s VNI %u from %s", - zvrf_id (zvrf), inet_ntoa (vtep_ip), - vni, zebra_route_string (client->proto)); - - /* Locate VNI hash entry - expected to exist. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - zlog_err ("Failed to locate VNI hash upon remote VTEP ADD, VRF %d VNI %u", - zvrf_id (zvrf), vni); - continue; - } - if (!zvni->vxlan_if) - { - zlog_err ("VNI %u hash %p doesn't have intf upon remote VTEP ADD", - zvni->vni, zvni); - continue; - } - - - /* If the remote VTEP already exists, or the local VxLAN interface is - * not up (should be a transient event), there's nothing more to do. - * Otherwise, add and install the entry. - */ - if (zvni_vtep_find (zvni, &vtep_ip)) - continue; - - if (!if_is_operative (zvni->vxlan_if)) - continue; - - if (zvni_vtep_add (zvni, &vtep_ip) == NULL) - { - zlog_err ("Failed to add remote VTEP, VRF %d VNI %u zvni %p", - zvrf_id (zvrf), vni, zvni); - continue; - } - - zvni_vtep_install (zvni, &vtep_ip); - } - - return 0; +int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) +{ + struct stream *s; + u_short l = 0; + vni_t vni; + struct in_addr vtep_ip; + zebra_vni_t *zvni; + + assert(EVPN_ENABLED(zvrf)); + + s = client->ibuf; + + while (l < length) { + /* Obtain each remote VTEP and process. */ + vni = (vni_t)stream_getl(s); + l += 4; + vtep_ip.s_addr = stream_get_ipv4(s); + l += IPV4_MAX_BYTELEN; + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Recv VTEP_ADD %s VNI %u from %s", + zvrf_id(zvrf), inet_ntoa(vtep_ip), vni, + zebra_route_string(client->proto)); + + /* Locate VNI hash entry - expected to exist. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + zlog_err( + "Failed to locate VNI hash upon remote VTEP ADD, VRF %d VNI %u", + zvrf_id(zvrf), vni); + continue; + } + if (!zvni->vxlan_if) { + zlog_err( + "VNI %u hash %p doesn't have intf upon remote VTEP ADD", + zvni->vni, zvni); + continue; + } + + + /* If the remote VTEP already exists, or the local VxLAN + * interface is + * not up (should be a transient event), there's nothing more + * to do. + * Otherwise, add and install the entry. + */ + if (zvni_vtep_find(zvni, &vtep_ip)) + continue; + + if (!if_is_operative(zvni->vxlan_if)) + continue; + + if (zvni_vtep_add(zvni, &vtep_ip) == NULL) { + zlog_err( + "Failed to add remote VTEP, VRF %d VNI %u zvni %p", + zvrf_id(zvrf), vni, zvni); + continue; + } + + zvni_vtep_install(zvni, &vtep_ip); + } + + return 0; } /* * Handle SVI interface going down. At this point, this is a NOP since * the kernel deletes the neighbor entries on this SVI (if any). */ -int -zebra_vxlan_svi_down (struct interface *ifp, struct interface *link_if) +int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if) { - return 0; + return 0; } /* @@ -2958,358 +2788,348 @@ zebra_vxlan_svi_down (struct interface *ifp, struct interface *link_if) * but if this is a SVI on a VxLAN bridge, we need to install any remote * neighbor entries (which will be used for EVPN ARP suppression). */ -int -zebra_vxlan_svi_up (struct interface *ifp, struct interface *link_if) +int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if) { - zebra_vni_t *zvni; - struct neigh_walk_ctx n_wctx; + zebra_vni_t *zvni; + struct neigh_walk_ctx n_wctx; - zvni = zvni_map_svi (ifp, link_if); - if (!zvni) - return 0; + zvni = zvni_map_svi(ifp, link_if); + if (!zvni) + return 0; - if (!zvni->vxlan_if) - { - zlog_err ("VNI %u hash %p doesn't have intf upon SVI up", - zvni->vni, zvni); - return -1; - } + if (!zvni->vxlan_if) { + zlog_err("VNI %u hash %p doesn't have intf upon SVI up", + zvni->vni, zvni); + return -1; + } - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:SVI %s(%u) VNI %u is UP, installing neighbors", - ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:SVI %s(%u) VNI %u is UP, installing neighbors", + ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni); - /* Install any remote neighbors for this VNI. */ - memset (&n_wctx, 0, sizeof (struct neigh_walk_ctx)); - n_wctx.zvni = zvni; - hash_iterate(zvni->neigh_table, zvni_install_neigh_hash, &n_wctx); + /* Install any remote neighbors for this VNI. */ + memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx)); + n_wctx.zvni = zvni; + hash_iterate(zvni->neigh_table, zvni_install_neigh_hash, &n_wctx); - return 0; + return 0; } /* * Handle VxLAN interface down - update BGP if required, and do * internal cleanup. */ -int -zebra_vxlan_if_down (struct interface *ifp) +int zebra_vxlan_if_down(struct interface *ifp) { - struct zebra_if *zif; - struct zebra_vrf *zvrf; - zebra_vni_t *zvni; - struct zebra_l2info_vxlan *vxl; - vni_t vni; + struct zebra_if *zif; + struct zebra_vrf *zvrf; + zebra_vni_t *zvni; + struct zebra_l2info_vxlan *vxl; + vni_t vni; - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(ifp->vrf_id); - assert(zvrf); + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(ifp->vrf_id); + assert(zvrf); - /* If EVPN is not enabled, nothing further to be done. */ - if (!EVPN_ENABLED(zvrf)) - return 0; + /* If EVPN is not enabled, nothing further to be done. */ + if (!EVPN_ENABLED(zvrf)) + return 0; - zif = ifp->info; - assert(zif); - vxl = &zif->l2info.vxl; - vni = vxl->vni; + zif = ifp->info; + assert(zif); + vxl = &zif->l2info.vxl; + vni = vxl->vni; - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Intf %s(%u) VNI %u is DOWN", - ifp->vrf_id, ifp->name, ifp->ifindex, vni); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Intf %s(%u) VNI %u is DOWN", ifp->vrf_id, + ifp->name, ifp->ifindex, vni); - /* Locate hash entry; it is expected to exist. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - zlog_err ("Failed to locate VNI hash at DOWN, VRF %d IF %s(%u) VNI %u", - ifp->vrf_id, ifp->name, ifp->ifindex, vni); - return -1; - } + /* Locate hash entry; it is expected to exist. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + zlog_err( + "Failed to locate VNI hash at DOWN, VRF %d IF %s(%u) VNI %u", + ifp->vrf_id, ifp->name, ifp->ifindex, vni); + return -1; + } - assert (zvni->vxlan_if == ifp); + assert(zvni->vxlan_if == ifp); - /* Delete this VNI from BGP. */ - zvni_send_del_to_client (zvrf, zvni->vni); + /* Delete this VNI from BGP. */ + zvni_send_del_to_client(zvrf, zvni->vni); - /* Free up all neighbors and MACs, if any. */ - zvni_neigh_del_all (zvrf, zvni, 1, 0, DEL_ALL_NEIGH); - zvni_mac_del_all (zvrf, zvni, 1, 0, DEL_ALL_MAC); + /* Free up all neighbors and MACs, if any. */ + zvni_neigh_del_all(zvrf, zvni, 1, 0, DEL_ALL_NEIGH); + zvni_mac_del_all(zvrf, zvni, 1, 0, DEL_ALL_MAC); - /* Free up all remote VTEPs, if any. */ - zvni_vtep_del_all (zvni, 1); + /* Free up all remote VTEPs, if any. */ + zvni_vtep_del_all(zvni, 1); - return 0; + return 0; } /* * Handle VxLAN interface up - update BGP if required. */ -int -zebra_vxlan_if_up (struct interface *ifp) +int zebra_vxlan_if_up(struct interface *ifp) { - struct zebra_if *zif; - struct zebra_vrf *zvrf; - zebra_vni_t *zvni; - struct zebra_l2info_vxlan *vxl; - vni_t vni; + struct zebra_if *zif; + struct zebra_vrf *zvrf; + zebra_vni_t *zvni; + struct zebra_l2info_vxlan *vxl; + vni_t vni; - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(ifp->vrf_id); - assert(zvrf); + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(ifp->vrf_id); + assert(zvrf); - /* If EVPN is not enabled, nothing further to be done. */ - if (!EVPN_ENABLED(zvrf)) - return 0; + /* If EVPN is not enabled, nothing further to be done. */ + if (!EVPN_ENABLED(zvrf)) + return 0; - zif = ifp->info; - assert(zif); - vxl = &zif->l2info.vxl; - vni = vxl->vni; + zif = ifp->info; + assert(zif); + vxl = &zif->l2info.vxl; + vni = vxl->vni; - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Intf %s(%u) VNI %u is UP", - ifp->vrf_id, ifp->name, ifp->ifindex, vni); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Intf %s(%u) VNI %u is UP", ifp->vrf_id, + ifp->name, ifp->ifindex, vni); - /* Locate hash entry; it is expected to exist. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - zlog_err ("Failed to locate VNI hash at UP, VRF %d IF %s(%u) VNI %u", - ifp->vrf_id, ifp->name, ifp->ifindex, vni); - return -1; - } + /* Locate hash entry; it is expected to exist. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + zlog_err( + "Failed to locate VNI hash at UP, VRF %d IF %s(%u) VNI %u", + ifp->vrf_id, ifp->name, ifp->ifindex, vni); + return -1; + } - assert (zvni->vxlan_if == ifp); + assert(zvni->vxlan_if == ifp); - /* If part of a bridge, inform BGP about this VNI. */ - /* Also, read and populate local MACs and neighbors. */ - if (zif->brslave_info.br_if) - { - zvni_send_add_to_client (zvrf, zvni); - zvni_read_mac_neigh (zvrf, zvni, ifp); - } + /* If part of a bridge, inform BGP about this VNI. */ + /* Also, read and populate local MACs and neighbors. */ + if (zif->brslave_info.br_if) { + zvni_send_add_to_client(zvrf, zvni); + zvni_read_mac_neigh(zvrf, zvni, ifp); + } - return 0; + return 0; } /* * Handle VxLAN interface delete. Locate and remove entry in hash table * and update BGP, if required. */ -int -zebra_vxlan_if_del (struct interface *ifp) +int zebra_vxlan_if_del(struct interface *ifp) { - struct zebra_if *zif; - struct zebra_vrf *zvrf; - zebra_vni_t *zvni; - struct zebra_l2info_vxlan *vxl; - vni_t vni; + struct zebra_if *zif; + struct zebra_vrf *zvrf; + zebra_vni_t *zvni; + struct zebra_l2info_vxlan *vxl; + vni_t vni; - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(ifp->vrf_id); - assert(zvrf); + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(ifp->vrf_id); + assert(zvrf); - /* If EVPN is not enabled, nothing further to be done. */ - if (!EVPN_ENABLED(zvrf)) - return 0; + /* If EVPN is not enabled, nothing further to be done. */ + if (!EVPN_ENABLED(zvrf)) + return 0; - zif = ifp->info; - assert(zif); - vxl = &zif->l2info.vxl; - vni = vxl->vni; + zif = ifp->info; + assert(zif); + vxl = &zif->l2info.vxl; + vni = vxl->vni; - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Del VNI %u intf %s(%u)", - ifp->vrf_id, vni, ifp->name, ifp->ifindex); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:Del VNI %u intf %s(%u)", ifp->vrf_id, vni, + ifp->name, ifp->ifindex); - /* Locate hash entry; it is expected to exist. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - zlog_err ("Failed to locate VNI hash at del, VRF %d IF %s(%u) VNI %u", - ifp->vrf_id, ifp->name, ifp->ifindex, vni); - return 0; - } + /* Locate hash entry; it is expected to exist. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + zlog_err( + "Failed to locate VNI hash at del, VRF %d IF %s(%u) VNI %u", + ifp->vrf_id, ifp->name, ifp->ifindex, vni); + return 0; + } - /* Delete VNI from BGP. */ - zvni_send_del_to_client (zvrf, zvni->vni); + /* Delete VNI from BGP. */ + zvni_send_del_to_client(zvrf, zvni->vni); - /* Free up all neighbors and MAC, if any. */ - zvni_neigh_del_all (zvrf, zvni, 0, 0, DEL_ALL_NEIGH); - zvni_mac_del_all (zvrf, zvni, 0, 0, DEL_ALL_MAC); + /* Free up all neighbors and MAC, if any. */ + zvni_neigh_del_all(zvrf, zvni, 0, 0, DEL_ALL_NEIGH); + zvni_mac_del_all(zvrf, zvni, 0, 0, DEL_ALL_MAC); - /* Free up all remote VTEPs, if any. */ - zvni_vtep_del_all (zvni, 0); + /* Free up all remote VTEPs, if any. */ + zvni_vtep_del_all(zvni, 0); - /* Delete the hash entry. */ - if (zvni_del (zvrf, zvni)) - { - zlog_err ("Failed to del VNI hash %p, VRF %d IF %s(%u) VNI %u", - zvni, ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni); - return -1; - } + /* Delete the hash entry. */ + if (zvni_del(zvrf, zvni)) { + zlog_err("Failed to del VNI hash %p, VRF %d IF %s(%u) VNI %u", + zvni, ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni); + return -1; + } - return 0; + return 0; } /* * Handle VxLAN interface update - change to tunnel IP, master or VLAN. */ -int -zebra_vxlan_if_update (struct interface *ifp, u_int16_t chgflags) -{ - struct zebra_if *zif; - struct zebra_vrf *zvrf; - zebra_vni_t *zvni; - struct zebra_l2info_vxlan *vxl; - vni_t vni; - - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(ifp->vrf_id); - assert(zvrf); - - /* If EVPN is not enabled, nothing further to be done. */ - if (!EVPN_ENABLED(zvrf)) - return 0; - - zif = ifp->info; - assert(zif); - vxl = &zif->l2info.vxl; - vni = vxl->vni; - - /* Update VNI hash. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - zlog_err ("Failed to find VNI hash on update, VRF %d IF %s(%u) VNI %u", - ifp->vrf_id, ifp->name, ifp->ifindex, vni); - return -1; - } - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Update VNI %u intf %s(%u) VLAN %u local IP %s " - "master %u chg 0x%x", - ifp->vrf_id, vni, ifp->name, ifp->ifindex, - vxl->access_vlan, inet_ntoa (vxl->vtep_ip), - zif->brslave_info.bridge_ifindex, chgflags); - - /* Removed from bridge? */ - if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE) && - (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) - { - /* Delete from client, remove all remote VTEPs */ - /* Also, free up all MACs and neighbors. */ - zvni_send_del_to_client (zvrf, zvni->vni); - zvni_neigh_del_all (zvrf, zvni, 1, 0, DEL_ALL_NEIGH); - zvni_mac_del_all (zvrf, zvni, 1, 0, DEL_ALL_MAC); - zvni_vtep_del_all (zvni, 1); - } - else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) - { - /* Remove all existing local neighbors and MACs for this VNI - * (including from BGP) - */ - zvni_neigh_del_all (zvrf, zvni, 0, 1, DEL_LOCAL_MAC); - zvni_mac_del_all (zvrf, zvni, 0, 1, DEL_LOCAL_MAC); - } - - zvni->local_vtep_ip = vxl->vtep_ip; - zvni->vxlan_if = ifp; - - /* Take further actions needed. Note that if we are here, there is a - * change of interest. - */ - /* If down or not mapped to a bridge, we're done. */ - if (!if_is_operative (ifp) || !zif->brslave_info.br_if) - return 0; - - /* Inform BGP, if there is a change of interest. */ - if (chgflags & (ZEBRA_VXLIF_MASTER_CHANGE | ZEBRA_VXLIF_LOCAL_IP_CHANGE)) - zvni_send_add_to_client (zvrf, zvni); - - /* If there is a valid new master or a VLAN mapping change, read and - * populate local MACs and neighbors. Also, reinstall any remote MACs - * and neighbors for this VNI (based on new VLAN). - */ - if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) - zvni_read_mac_neigh (zvrf, zvni, ifp); - else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) - { - struct mac_walk_ctx m_wctx; - struct neigh_walk_ctx n_wctx; - - zvni_read_mac_neigh (zvrf, zvni, ifp); - - memset (&m_wctx, 0, sizeof (struct mac_walk_ctx)); - m_wctx.zvni = zvni; - hash_iterate(zvni->mac_table, zvni_install_mac_hash, &m_wctx); - - memset (&n_wctx, 0, sizeof (struct neigh_walk_ctx)); - n_wctx.zvni = zvni; - hash_iterate(zvni->neigh_table, zvni_install_neigh_hash, &n_wctx); - } - - return 0; +int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags) +{ + struct zebra_if *zif; + struct zebra_vrf *zvrf; + zebra_vni_t *zvni; + struct zebra_l2info_vxlan *vxl; + vni_t vni; + + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(ifp->vrf_id); + assert(zvrf); + + /* If EVPN is not enabled, nothing further to be done. */ + if (!EVPN_ENABLED(zvrf)) + return 0; + + zif = ifp->info; + assert(zif); + vxl = &zif->l2info.vxl; + vni = vxl->vni; + + /* Update VNI hash. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + zlog_err( + "Failed to find VNI hash on update, VRF %d IF %s(%u) VNI %u", + ifp->vrf_id, ifp->name, ifp->ifindex, vni); + return -1; + } + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Update VNI %u intf %s(%u) VLAN %u local IP %s " + "master %u chg 0x%x", + ifp->vrf_id, vni, ifp->name, ifp->ifindex, + vxl->access_vlan, inet_ntoa(vxl->vtep_ip), + zif->brslave_info.bridge_ifindex, chgflags); + + /* Removed from bridge? */ + if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE) + && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) { + /* Delete from client, remove all remote VTEPs */ + /* Also, free up all MACs and neighbors. */ + zvni_send_del_to_client(zvrf, zvni->vni); + zvni_neigh_del_all(zvrf, zvni, 1, 0, DEL_ALL_NEIGH); + zvni_mac_del_all(zvrf, zvni, 1, 0, DEL_ALL_MAC); + zvni_vtep_del_all(zvni, 1); + } else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) { + /* Remove all existing local neighbors and MACs for this VNI + * (including from BGP) + */ + zvni_neigh_del_all(zvrf, zvni, 0, 1, DEL_LOCAL_MAC); + zvni_mac_del_all(zvrf, zvni, 0, 1, DEL_LOCAL_MAC); + } + + zvni->local_vtep_ip = vxl->vtep_ip; + zvni->vxlan_if = ifp; + + /* Take further actions needed. Note that if we are here, there is a + * change of interest. + */ + /* If down or not mapped to a bridge, we're done. */ + if (!if_is_operative(ifp) || !zif->brslave_info.br_if) + return 0; + + /* Inform BGP, if there is a change of interest. */ + if (chgflags + & (ZEBRA_VXLIF_MASTER_CHANGE | ZEBRA_VXLIF_LOCAL_IP_CHANGE)) + zvni_send_add_to_client(zvrf, zvni); + + /* If there is a valid new master or a VLAN mapping change, read and + * populate local MACs and neighbors. Also, reinstall any remote MACs + * and neighbors for this VNI (based on new VLAN). + */ + if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) + zvni_read_mac_neigh(zvrf, zvni, ifp); + else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) { + struct mac_walk_ctx m_wctx; + struct neigh_walk_ctx n_wctx; + + zvni_read_mac_neigh(zvrf, zvni, ifp); + + memset(&m_wctx, 0, sizeof(struct mac_walk_ctx)); + m_wctx.zvni = zvni; + hash_iterate(zvni->mac_table, zvni_install_mac_hash, &m_wctx); + + memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx)); + n_wctx.zvni = zvni; + hash_iterate(zvni->neigh_table, zvni_install_neigh_hash, + &n_wctx); + } + + return 0; } /* * Handle VxLAN interface add. */ -int -zebra_vxlan_if_add (struct interface *ifp) +int zebra_vxlan_if_add(struct interface *ifp) { - struct zebra_if *zif; - struct zebra_vrf *zvrf; - zebra_vni_t *zvni; - struct zebra_l2info_vxlan *vxl; - vni_t vni; + struct zebra_if *zif; + struct zebra_vrf *zvrf; + zebra_vni_t *zvni; + struct zebra_l2info_vxlan *vxl; + vni_t vni; - /* Locate VRF corresponding to interface. */ - zvrf = vrf_info_lookup(ifp->vrf_id); - assert(zvrf); + /* Locate VRF corresponding to interface. */ + zvrf = vrf_info_lookup(ifp->vrf_id); + assert(zvrf); - /* If EVPN is not enabled, nothing further to be done. */ - if (!EVPN_ENABLED(zvrf)) - return 0; + /* If EVPN is not enabled, nothing further to be done. */ + if (!EVPN_ENABLED(zvrf)) + return 0; - zif = ifp->info; - assert(zif); - vxl = &zif->l2info.vxl; - vni = vxl->vni; + zif = ifp->info; + assert(zif); + vxl = &zif->l2info.vxl; + vni = vxl->vni; - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:Add VNI %u intf %s(%u) VLAN %u local IP %s master %u", - ifp->vrf_id, vni, ifp->name, ifp->ifindex, - vxl->access_vlan, inet_ntoa (vxl->vtep_ip), - zif->brslave_info.bridge_ifindex); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u:Add VNI %u intf %s(%u) VLAN %u local IP %s master %u", + ifp->vrf_id, vni, ifp->name, ifp->ifindex, + vxl->access_vlan, inet_ntoa(vxl->vtep_ip), + zif->brslave_info.bridge_ifindex); - /* Create or update VNI hash. */ - zvni = zvni_lookup (zvrf, vni); - if (!zvni) - { - zvni = zvni_add (zvrf, vni); - if (!zvni) - { - zlog_err ("Failed to add VNI hash, VRF %d IF %s(%u) VNI %u", - ifp->vrf_id, ifp->name, ifp->ifindex, vni); - return -1; - } - } + /* Create or update VNI hash. */ + zvni = zvni_lookup(zvrf, vni); + if (!zvni) { + zvni = zvni_add(zvrf, vni); + if (!zvni) { + zlog_err( + "Failed to add VNI hash, VRF %d IF %s(%u) VNI %u", + ifp->vrf_id, ifp->name, ifp->ifindex, vni); + return -1; + } + } - zvni->local_vtep_ip = vxl->vtep_ip; - zvni->vxlan_if = ifp; + zvni->local_vtep_ip = vxl->vtep_ip; + zvni->vxlan_if = ifp; - /* If down or not mapped to a bridge, we're done. */ - if (!if_is_operative (ifp) || !zif->brslave_info.br_if) - return 0; + /* If down or not mapped to a bridge, we're done. */ + if (!if_is_operative(ifp) || !zif->brslave_info.br_if) + return 0; - /* Inform BGP */ - zvni_send_add_to_client (zvrf, zvni); + /* Inform BGP */ + zvni_send_add_to_client(zvrf, zvni); - /* Read and populate local MACs and neighbors */ - zvni_read_mac_neigh (zvrf, zvni, ifp); + /* Read and populate local MACs and neighbors */ + zvni_read_mac_neigh(zvrf, zvni, ifp); - return 0; + return 0; } /* @@ -3318,63 +3138,57 @@ zebra_vxlan_if_add (struct interface *ifp) * when disabled, the entries should be deleted and remote VTEPs and MACs * uninstalled from the kernel. */ -int zebra_vxlan_advertise_all_vni (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) +int zebra_vxlan_advertise_all_vni(struct zserv *client, int sock, + u_short length, struct zebra_vrf *zvrf) { - struct stream *s; - int advertise; + struct stream *s; + int advertise; - s = client->ibuf; - advertise = stream_getc (s); + s = client->ibuf; + advertise = stream_getc(s); - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug ("%u:EVPN VNI Adv %s, currently %s", - zvrf_id (zvrf), advertise ? "enabled" : "disabled", - EVPN_ENABLED(zvrf) ? "enabled" : "disabled"); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%u:EVPN VNI Adv %s, currently %s", zvrf_id(zvrf), + advertise ? "enabled" : "disabled", + EVPN_ENABLED(zvrf) ? "enabled" : "disabled"); - if (zvrf->advertise_all_vni == advertise) - return 0; + if (zvrf->advertise_all_vni == advertise) + return 0; - zvrf->advertise_all_vni = advertise; - if (EVPN_ENABLED(zvrf)) - { - /* Build VNI hash table and inform BGP. */ - zvni_build_hash_table (zvrf); + zvrf->advertise_all_vni = advertise; + if (EVPN_ENABLED(zvrf)) { + /* Build VNI hash table and inform BGP. */ + zvni_build_hash_table(zvrf); - /* Read the MAC FDB */ - macfdb_read (zvrf->zns); + /* Read the MAC FDB */ + macfdb_read(zvrf->zns); - /* Read neighbors */ - neigh_read (zvrf->zns); - } - else - { - /* Cleanup VTEPs for all VNIs - uninstall from - * kernel and free entries. - */ - hash_iterate (zvrf->vni_table, zvni_cleanup_all, zvrf); - } + /* Read neighbors */ + neigh_read(zvrf->zns); + } else { + /* Cleanup VTEPs for all VNIs - uninstall from + * kernel and free entries. + */ + hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf); + } - return 0; + return 0; } /* * Allocate VNI hash table for this VRF and do other initialization. * NOTE: Currently supported only for default VRF. */ -void -zebra_vxlan_init_tables (struct zebra_vrf *zvrf) +void zebra_vxlan_init_tables(struct zebra_vrf *zvrf) { - if (!zvrf) - return; - zvrf->vni_table = hash_create(vni_hash_keymake, - vni_hash_cmp, - "Zebra VRF VNI Table"); + if (!zvrf) + return; + zvrf->vni_table = hash_create(vni_hash_keymake, vni_hash_cmp, + "Zebra VRF VNI Table"); } /* Close all VNI handling */ -void -zebra_vxlan_close_tables (struct zebra_vrf *zvrf) +void zebra_vxlan_close_tables(struct zebra_vrf *zvrf) { - hash_iterate (zvrf->vni_table, zvni_cleanup_all, zvrf); + hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf); } diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h index e5f0bd2f6..f9ecd8333 100644 --- a/zebra/zebra_vxlan.h +++ b/zebra/zebra_vxlan.h @@ -41,68 +41,73 @@ #define ZEBRA_VXLIF_MASTER_CHANGE 0x2 #define ZEBRA_VXLIF_VLAN_CHANGE 0x4 -extern void zebra_vxlan_print_macs_vni (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni); -extern void zebra_vxlan_print_macs_all_vni (struct vty *vty, - struct zebra_vrf *zvrf); -extern void zebra_vxlan_print_macs_all_vni_vtep (struct vty *vty, - struct zebra_vrf *zvrf, - struct in_addr vtep_ip); -extern void zebra_vxlan_print_specific_mac_vni (struct vty *vty, - struct zebra_vrf *zvrf, vni_t vni, struct ethaddr *mac); -extern void zebra_vxlan_print_macs_vni_vtep (struct vty *vty, - struct zebra_vrf *zvrf, vni_t vni, struct in_addr vtep_ip); -extern void zebra_vxlan_print_neigh_vni (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni); -extern void zebra_vxlan_print_neigh_all_vni (struct vty *vty, - struct zebra_vrf *zvrf); -extern void zebra_vxlan_print_specific_neigh_vni (struct vty *vty, - struct zebra_vrf *zvrf, vni_t vni, struct ipaddr *ip); -extern void zebra_vxlan_print_neigh_vni_vtep (struct vty *vty, - struct zebra_vrf *zvrf, vni_t vni, struct in_addr vtep_ip); -extern void zebra_vxlan_print_vni (struct vty *vty, struct zebra_vrf *zvrf, vni_t vni); -extern void zebra_vxlan_print_vnis (struct vty *vty, struct zebra_vrf *zvrf); +extern void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni); +extern void zebra_vxlan_print_macs_all_vni(struct vty *vty, + struct zebra_vrf *zvrf); +extern void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty, + struct zebra_vrf *zvrf, + struct in_addr vtep_ip); +extern void zebra_vxlan_print_specific_mac_vni(struct vty *vty, + struct zebra_vrf *zvrf, + vni_t vni, struct ethaddr *mac); +extern void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, + struct zebra_vrf *zvrf, vni_t vni, + struct in_addr vtep_ip); +extern void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni); +extern void zebra_vxlan_print_neigh_all_vni(struct vty *vty, + struct zebra_vrf *zvrf); +extern void zebra_vxlan_print_specific_neigh_vni(struct vty *vty, + struct zebra_vrf *zvrf, + vni_t vni, struct ipaddr *ip); +extern void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, + struct zebra_vrf *zvrf, vni_t vni, + struct in_addr vtep_ip); +extern void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni); +extern void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf); -extern int zebra_vxlan_svi_up (struct interface *ifp, struct interface *link_if); -extern int zebra_vxlan_svi_down (struct interface *ifp, struct interface *link_if); -extern int zebra_vxlan_local_neigh_add_update (struct interface *ifp, - struct interface *link_if, - struct ipaddr *ip, - struct ethaddr *macaddr, - u_int16_t state, - u_char ext_learned); -extern int zebra_vxlan_local_neigh_del (struct interface *ifp, - struct interface *link_if, - struct ipaddr *ip); -extern int zebra_vxlan_remote_macip_add (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf); -extern int zebra_vxlan_remote_macip_del (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf); -extern int zebra_vxlan_local_mac_add_update (struct interface *ifp, - struct interface *br_if, - struct ethaddr *mac, vlanid_t vid, - u_char sticky); -extern int zebra_vxlan_local_mac_del (struct interface *ifp, - struct interface *br_if, - struct ethaddr *mac, vlanid_t vid); -extern int zebra_vxlan_check_readd_remote_mac (struct interface *ifp, - struct interface *br_if, - struct ethaddr *mac, vlanid_t vid); -extern int zebra_vxlan_check_del_local_mac (struct interface *ifp, - struct interface *br_if, - struct ethaddr *mac, vlanid_t vid); -extern int zebra_vxlan_if_up (struct interface *ifp); -extern int zebra_vxlan_if_down (struct interface *ifp); -extern int zebra_vxlan_if_add (struct interface *ifp); -extern int zebra_vxlan_if_update (struct interface *ifp, u_int16_t chgflags); -extern int zebra_vxlan_if_del (struct interface *ifp); -extern int zebra_vxlan_remote_vtep_add (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf); -extern int zebra_vxlan_remote_vtep_del (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf); -extern int zebra_vxlan_advertise_all_vni (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf); -extern void zebra_vxlan_init_tables (struct zebra_vrf *zvrf); -extern void zebra_vxlan_close_tables (struct zebra_vrf *); +extern int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if); +extern int zebra_vxlan_svi_down(struct interface *ifp, + struct interface *link_if); +extern int zebra_vxlan_local_neigh_add_update( + struct interface *ifp, struct interface *link_if, struct ipaddr *ip, + struct ethaddr *macaddr, u_int16_t state, u_char ext_learned); +extern int zebra_vxlan_local_neigh_del(struct interface *ifp, + struct interface *link_if, + struct ipaddr *ip); +extern int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, + u_short length, struct zebra_vrf *zvrf); +extern int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, + u_short length, struct zebra_vrf *zvrf); +extern int zebra_vxlan_local_mac_add_update(struct interface *ifp, + struct interface *br_if, + struct ethaddr *mac, vlanid_t vid, + u_char sticky); +extern int zebra_vxlan_local_mac_del(struct interface *ifp, + struct interface *br_if, + struct ethaddr *mac, vlanid_t vid); +extern int zebra_vxlan_check_readd_remote_mac(struct interface *ifp, + struct interface *br_if, + struct ethaddr *mac, + vlanid_t vid); +extern int zebra_vxlan_check_del_local_mac(struct interface *ifp, + struct interface *br_if, + struct ethaddr *mac, vlanid_t vid); +extern int zebra_vxlan_if_up(struct interface *ifp); +extern int zebra_vxlan_if_down(struct interface *ifp); +extern int zebra_vxlan_if_add(struct interface *ifp); +extern int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags); +extern int zebra_vxlan_if_del(struct interface *ifp); +extern int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, + u_short length, struct zebra_vrf *zvrf); +extern int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, + u_short length, struct zebra_vrf *zvrf); +extern int zebra_vxlan_advertise_all_vni(struct zserv *client, int sock, + u_short length, + struct zebra_vrf *zvrf); +extern void zebra_vxlan_init_tables(struct zebra_vrf *zvrf); +extern void zebra_vxlan_close_tables(struct zebra_vrf *); #endif /* _ZEBRA_VXLAN_H */ diff --git a/zebra/zebra_vxlan_null.c b/zebra/zebra_vxlan_null.c index b0f09930b..bbed5ddb0 100644 --- a/zebra/zebra_vxlan_null.c +++ b/zebra/zebra_vxlan_null.c @@ -30,168 +30,156 @@ #include "zebra/zebra_l2.h" #include "zebra/zebra_vxlan.h" -void -zebra_vxlan_print_macs_vni (struct vty *vty, struct zebra_vrf *zvrf, vni_t vni) +void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni) { } -void zebra_vxlan_print_macs_all_vni (struct vty *vty, struct zebra_vrf *zvrf) +void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf) { } -void zebra_vxlan_print_macs_all_vni_vtep (struct vty *vty, struct zebra_vrf *zvrf, struct in_addr vtep_ip) +void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty, + struct zebra_vrf *zvrf, + struct in_addr vtep_ip) { } -void -zebra_vxlan_print_specific_mac_vni (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct ethaddr *mac) +void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni, struct ethaddr *mac) { } -void -zebra_vxlan_print_macs_vni_vtep (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct in_addr vtep_ip) +void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni, struct in_addr vtep_ip) { } -void -zebra_vxlan_print_neigh_vni (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni) +void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni) { } -void -zebra_vxlan_print_neigh_all_vni (struct vty *vty, struct zebra_vrf *zvrf) +void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf) { } -void -zebra_vxlan_print_specific_neigh_vni (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct ipaddr *ip) +void zebra_vxlan_print_specific_neigh_vni(struct vty *vty, + struct zebra_vrf *zvrf, vni_t vni, + struct ipaddr *ip) { } -void zebra_vxlan_print_neigh_vni_vtep (struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct in_addr vtep_ip) +void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, + vni_t vni, struct in_addr vtep_ip) { } -void -zebra_vxlan_print_vni (struct vty *vty, struct zebra_vrf *zvrf, vni_t vni) +void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni) { } -void -zebra_vxlan_print_vnis (struct vty *vty, struct zebra_vrf *zvrf) +void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf) { } -int zebra_vxlan_svi_up (struct interface *ifp, struct interface *link_if) +int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if) { - return 0; + return 0; } -int zebra_vxlan_svi_down (struct interface *ifp, struct interface *link_if) +int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if) { - return 0; + return 0; } -int zebra_vxlan_remote_macip_add (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) +int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) { - return 0; + return 0; } -int zebra_vxlan_remote_macip_del (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) +int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) { - return 0; + return 0; } -int zebra_vxlan_local_mac_add_update (struct interface *ifp, - struct interface *br_if, - struct ethaddr *mac, vlanid_t vid, - u_char sticky) +int zebra_vxlan_local_mac_add_update(struct interface *ifp, + struct interface *br_if, + struct ethaddr *mac, vlanid_t vid, + u_char sticky) { - return 0; + return 0; } -int zebra_vxlan_local_mac_del (struct interface *ifp, - struct interface *br_if, - struct ethaddr *mac, vlanid_t vid) +int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if, + struct ethaddr *mac, vlanid_t vid) { - return 0; + return 0; } -int zebra_vxlan_check_readd_remote_mac (struct interface *ifp, - struct interface *br_if, - struct ethaddr *mac, vlanid_t vid) +int zebra_vxlan_check_readd_remote_mac(struct interface *ifp, + struct interface *br_if, + struct ethaddr *mac, vlanid_t vid) { - return 0; + return 0; } -int zebra_vxlan_check_del_local_mac (struct interface *ifp, - struct interface *br_if, - struct ethaddr *mac, vlanid_t vid) +int zebra_vxlan_check_del_local_mac(struct interface *ifp, + struct interface *br_if, + struct ethaddr *mac, vlanid_t vid) { - return 0; + return 0; } -int -zebra_vxlan_if_up (struct interface *ifp) +int zebra_vxlan_if_up(struct interface *ifp) { - return 0; + return 0; } -int -zebra_vxlan_if_down (struct interface *ifp) +int zebra_vxlan_if_down(struct interface *ifp) { - return 0; + return 0; } -int -zebra_vxlan_if_add (struct interface *ifp) +int zebra_vxlan_if_add(struct interface *ifp) { - return 0; + return 0; } -int -zebra_vxlan_if_update (struct interface *ifp, u_int16_t chgflags) +int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags) { - return 0; + return 0; } -int -zebra_vxlan_if_del (struct interface *ifp) +int zebra_vxlan_if_del(struct interface *ifp) { - return 0; + return 0; } -int zebra_vxlan_remote_vtep_add (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) +int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) { - return 0; + return 0; } -int zebra_vxlan_remote_vtep_del (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) +int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, u_short length, + struct zebra_vrf *zvrf) { - return 0; + return 0; } -int zebra_vxlan_advertise_all_vni (struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) +int zebra_vxlan_advertise_all_vni(struct zserv *client, int sock, + u_short length, struct zebra_vrf *zvrf) { - return 0; + return 0; } -void -zebra_vxlan_init_tables (struct zebra_vrf *zvrf) +void zebra_vxlan_init_tables(struct zebra_vrf *zvrf) { } -void -zebra_vxlan_close_tables (struct zebra_vrf *zvrf) +void zebra_vxlan_close_tables(struct zebra_vrf *zvrf) { } diff --git a/zebra/zebra_vxlan_private.h b/zebra/zebra_vxlan_private.h index 0de86c3bc..fbde72292 100644 --- a/zebra/zebra_vxlan_private.h +++ b/zebra/zebra_vxlan_private.h @@ -42,15 +42,14 @@ typedef struct zebra_neigh_t_ zebra_neigh_t; * * Right now, this just has each remote VTEP's IP address. */ -struct zebra_vtep_t_ -{ - /* Remote IP. */ - /* NOTE: Can only be IPv4 right now. */ - struct in_addr vtep_ip; - - /* Links. */ - struct zebra_vtep_t_ *next; - struct zebra_vtep_t_ *prev; +struct zebra_vtep_t_ { + /* Remote IP. */ + /* NOTE: Can only be IPv4 right now. */ + struct in_addr vtep_ip; + + /* Links. */ + struct zebra_vtep_t_ *next; + struct zebra_vtep_t_ *prev; }; @@ -60,25 +59,24 @@ struct zebra_vtep_t_ * Contains information pertaining to a VNI: * - the list of remote VTEPs (with this VNI) */ -struct zebra_vni_t_ -{ - /* VNI - key */ - vni_t vni; +struct zebra_vni_t_ { + /* VNI - key */ + vni_t vni; - /* Corresponding VxLAN interface. */ - struct interface *vxlan_if; + /* Corresponding VxLAN interface. */ + struct interface *vxlan_if; - /* List of remote VTEPs */ - zebra_vtep_t *vteps; + /* List of remote VTEPs */ + zebra_vtep_t *vteps; - /* Local IP */ - struct in_addr local_vtep_ip; + /* Local IP */ + struct in_addr local_vtep_ip; - /* List of local or remote MAC */ - struct hash *mac_table; + /* List of local or remote MAC */ + struct hash *mac_table; - /* List of local or remote neighbors (MAC+IP) */ - struct hash *neigh_table; + /* List of local or remote neighbors (MAC+IP) */ + struct hash *neigh_table; }; /* @@ -93,53 +91,49 @@ struct zebra_vni_t_ * information. The correct VNI will be obtained as zebra maintains * the mapping (of VLAN to VNI). */ -struct zebra_mac_t_ -{ - /* MAC address. */ - struct ethaddr macaddr; +struct zebra_mac_t_ { + /* MAC address. */ + struct ethaddr macaddr; - u_int32_t flags; + u_int32_t flags; #define ZEBRA_MAC_LOCAL 0x01 #define ZEBRA_MAC_REMOTE 0x02 #define ZEBRA_MAC_AUTO 0x04 /* Auto created for neighbor. */ #define ZEBRA_MAC_STICKY 0x08 /* Static MAC */ - /* Local or remote info. */ - union - { - struct - { - ifindex_t ifindex; - vlanid_t vid; - } local; + /* Local or remote info. */ + union { + struct { + ifindex_t ifindex; + vlanid_t vid; + } local; - struct in_addr r_vtep_ip; - } fwd_info; + struct in_addr r_vtep_ip; + } fwd_info; - u_int32_t neigh_refcnt; + u_int32_t neigh_refcnt; }; /* * Context for MAC hash walk - used by callbacks. */ -struct mac_walk_ctx -{ - zebra_vni_t *zvni; /* VNI hash */ - struct zebra_vrf *zvrf; /* VRF - for client notification. */ - int uninstall; /* uninstall from kernel? */ - int upd_client; /* uninstall from client? */ - - u_int32_t flags; +struct mac_walk_ctx { + zebra_vni_t *zvni; /* VNI hash */ + struct zebra_vrf *zvrf; /* VRF - for client notification. */ + int uninstall; /* uninstall from kernel? */ + int upd_client; /* uninstall from client? */ + + u_int32_t flags; #define DEL_LOCAL_MAC 0x1 #define DEL_REMOTE_MAC 0x2 #define DEL_ALL_MAC (DEL_LOCAL_MAC | DEL_REMOTE_MAC) #define DEL_REMOTE_MAC_FROM_VTEP 0x4 #define SHOW_REMOTE_MAC_FROM_VTEP 0x8 - struct in_addr r_vtep_ip; /* To walk MACs from specific VTEP */ + struct in_addr r_vtep_ip; /* To walk MACs from specific VTEP */ - struct vty *vty; /* Used by VTY handlers */ - u_int32_t count; /* Used by VTY handlers */ + struct vty *vty; /* Used by VTY handlers */ + u_int32_t count; /* Used by VTY handlers */ }; /* @@ -153,47 +147,45 @@ struct mac_walk_ctx * it is sufficient for zebra to maintain against the VNI. The correct * VNI will be obtained as zebra maintains the mapping (of VLAN to VNI). */ -struct zebra_neigh_t_ -{ - /* IP address. */ - struct ipaddr ip; +struct zebra_neigh_t_ { + /* IP address. */ + struct ipaddr ip; - /* MAC address. */ - struct ethaddr emac; + /* MAC address. */ + struct ethaddr emac; - /* Underlying interface. */ - ifindex_t ifindex; + /* Underlying interface. */ + ifindex_t ifindex; - u_int32_t flags; + u_int32_t flags; #define ZEBRA_NEIGH_LOCAL 0x01 #define ZEBRA_NEIGH_REMOTE 0x02 - /* Remote VTEP IP - applicable only for remote neighbors. */ - struct in_addr r_vtep_ip; + /* Remote VTEP IP - applicable only for remote neighbors. */ + struct in_addr r_vtep_ip; }; /* * Context for neighbor hash walk - used by callbacks. */ -struct neigh_walk_ctx -{ - zebra_vni_t *zvni; /* VNI hash */ - struct zebra_vrf *zvrf; /* VRF - for client notification. */ - int uninstall; /* uninstall from kernel? */ - int upd_client; /* uninstall from client? */ - - u_int32_t flags; +struct neigh_walk_ctx { + zebra_vni_t *zvni; /* VNI hash */ + struct zebra_vrf *zvrf; /* VRF - for client notification. */ + int uninstall; /* uninstall from kernel? */ + int upd_client; /* uninstall from client? */ + + u_int32_t flags; #define DEL_LOCAL_NEIGH 0x1 #define DEL_REMOTE_NEIGH 0x2 #define DEL_ALL_NEIGH (DEL_LOCAL_NEIGH | DEL_REMOTE_NEIGH) #define DEL_REMOTE_NEIGH_FROM_VTEP 0x4 #define SHOW_REMOTE_NEIGH_FROM_VTEP 0x8 - struct in_addr r_vtep_ip; /* To walk neighbors from specific VTEP */ + struct in_addr r_vtep_ip; /* To walk neighbors from specific VTEP */ - struct vty *vty; /* Used by VTY handlers */ - u_int32_t count; /* Used by VTY handlers */ - u_char addr_width; /* Used by VTY handlers */ + struct vty *vty; /* Used by VTY handlers */ + u_int32_t count; /* Used by VTY handlers */ + u_char addr_width; /* Used by VTY handlers */ }; #endif /* _ZEBRA_VXLAN_PRIVATE_H */ diff --git a/zebra/zserv.c b/zebra/zserv.c index 15feb78c0..3bc5f83f6 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -59,150 +59,145 @@ /* Event list of zebra. */ enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE }; -static void zebra_event (enum event event, int sock, struct zserv *client); +static void zebra_event(enum event event, int sock, struct zserv *client); extern struct zebra_privs_t zserv_privs; -static void zebra_client_close (struct zserv *client); - -static int -zserv_delayed_close(struct thread *thread) -{ - struct zserv *client = THREAD_ARG(thread); - - client->t_suicide = NULL; - zebra_client_close(client); - return 0; -} - -static int -zserv_flush_data(struct thread *thread) -{ - struct zserv *client = THREAD_ARG(thread); - - client->t_write = NULL; - if (client->t_suicide) - { - zebra_client_close(client); - return -1; - } - switch (buffer_flush_available(client->wb, client->sock)) - { - case BUFFER_ERROR: - zlog_warn("%s: buffer_flush_available failed on zserv client fd %d, " - "closing", __func__, client->sock); - zebra_client_close(client); - client = NULL; - break; - case BUFFER_PENDING: - client->t_write = NULL; - thread_add_write(zebrad.master, zserv_flush_data, client, client->sock, - &client->t_write); - break; - case BUFFER_EMPTY: - break; - } - - if (client) - client->last_write_time = monotime(NULL); - return 0; -} - -int -zebra_server_send_message(struct zserv *client) -{ - if (client->t_suicide) - return -1; - - if (client->is_synchronous) - return 0; - - stream_set_getp(client->obuf, 0); - client->last_write_cmd = stream_getw_from(client->obuf, 6); - switch (buffer_write(client->wb, client->sock, STREAM_DATA(client->obuf), - stream_get_endp(client->obuf))) - { - case BUFFER_ERROR: - zlog_warn("%s: buffer_write failed to zserv client fd %d, closing", - __func__, client->sock); - /* Schedule a delayed close since many of the functions that call this - one do not check the return code. They do not allow for the - possibility that an I/O error may have caused the client to be - deleted. */ - client->t_suicide = NULL; - thread_add_event(zebrad.master, zserv_delayed_close, client, 0, - &client->t_suicide); - return -1; - case BUFFER_EMPTY: - THREAD_OFF(client->t_write); - break; - case BUFFER_PENDING: - thread_add_write(zebrad.master, zserv_flush_data, client, client->sock, - &client->t_write); - break; - } - - client->last_write_time = monotime(NULL); - return 0; -} - -void -zserv_create_header (struct stream *s, uint16_t cmd, vrf_id_t vrf_id) -{ - /* length placeholder, caller can update */ - stream_putw (s, ZEBRA_HEADER_SIZE); - stream_putc (s, ZEBRA_HEADER_MARKER); - stream_putc (s, ZSERV_VERSION); - stream_putw (s, vrf_id); - stream_putw (s, cmd); -} - -static void -zserv_encode_interface (struct stream *s, struct interface *ifp) -{ - /* Interface information. */ - stream_put (s, ifp->name, INTERFACE_NAMSIZ); - stream_putl (s, ifp->ifindex); - stream_putc (s, ifp->status); - stream_putq (s, ifp->flags); - stream_putc (s, ifp->ptm_enable); - stream_putc (s, ifp->ptm_status); - stream_putl (s, ifp->metric); - stream_putl (s, ifp->speed); - stream_putl (s, ifp->mtu); - stream_putl (s, ifp->mtu6); - stream_putl (s, ifp->bandwidth); - stream_putl (s, ifp->ll_type); - stream_putl (s, ifp->hw_addr_len); - if (ifp->hw_addr_len) - stream_put (s, ifp->hw_addr, ifp->hw_addr_len); - - /* Then, Traffic Engineering parameters if any */ - if (HAS_LINK_PARAMS(ifp) && IS_LINK_PARAMS_SET(ifp->link_params)) - { - stream_putc (s, 1); - zebra_interface_link_params_write (s, ifp); - } - else - stream_putc (s, 0); - - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); -} - -static void -zserv_encode_vrf (struct stream *s, struct zebra_vrf *zvrf) -{ - struct vrf_data data; - - data.l.table_id = zvrf->table_id; - /* Pass the tableid */ - stream_put (s, &data, sizeof (struct vrf_data)); - /* Interface information. */ - stream_put (s, zvrf_name (zvrf), VRF_NAMSIZ); - - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); +static void zebra_client_close(struct zserv *client); + +static int zserv_delayed_close(struct thread *thread) +{ + struct zserv *client = THREAD_ARG(thread); + + client->t_suicide = NULL; + zebra_client_close(client); + return 0; +} + +static int zserv_flush_data(struct thread *thread) +{ + struct zserv *client = THREAD_ARG(thread); + + client->t_write = NULL; + if (client->t_suicide) { + zebra_client_close(client); + return -1; + } + switch (buffer_flush_available(client->wb, client->sock)) { + case BUFFER_ERROR: + zlog_warn( + "%s: buffer_flush_available failed on zserv client fd %d, " + "closing", + __func__, client->sock); + zebra_client_close(client); + client = NULL; + break; + case BUFFER_PENDING: + client->t_write = NULL; + thread_add_write(zebrad.master, zserv_flush_data, client, + client->sock, &client->t_write); + break; + case BUFFER_EMPTY: + break; + } + + if (client) + client->last_write_time = monotime(NULL); + return 0; +} + +int zebra_server_send_message(struct zserv *client) +{ + if (client->t_suicide) + return -1; + + if (client->is_synchronous) + return 0; + + stream_set_getp(client->obuf, 0); + client->last_write_cmd = stream_getw_from(client->obuf, 6); + switch (buffer_write(client->wb, client->sock, + STREAM_DATA(client->obuf), + stream_get_endp(client->obuf))) { + case BUFFER_ERROR: + zlog_warn( + "%s: buffer_write failed to zserv client fd %d, closing", + __func__, client->sock); + /* Schedule a delayed close since many of the functions that + call this + one do not check the return code. They do not allow for the + possibility that an I/O error may have caused the client to + be + deleted. */ + client->t_suicide = NULL; + thread_add_event(zebrad.master, zserv_delayed_close, client, 0, + &client->t_suicide); + return -1; + case BUFFER_EMPTY: + THREAD_OFF(client->t_write); + break; + case BUFFER_PENDING: + thread_add_write(zebrad.master, zserv_flush_data, client, + client->sock, &client->t_write); + break; + } + + client->last_write_time = monotime(NULL); + return 0; +} + +void zserv_create_header(struct stream *s, uint16_t cmd, vrf_id_t vrf_id) +{ + /* length placeholder, caller can update */ + stream_putw(s, ZEBRA_HEADER_SIZE); + stream_putc(s, ZEBRA_HEADER_MARKER); + stream_putc(s, ZSERV_VERSION); + stream_putw(s, vrf_id); + stream_putw(s, cmd); +} + +static void zserv_encode_interface(struct stream *s, struct interface *ifp) +{ + /* Interface information. */ + stream_put(s, ifp->name, INTERFACE_NAMSIZ); + stream_putl(s, ifp->ifindex); + stream_putc(s, ifp->status); + stream_putq(s, ifp->flags); + stream_putc(s, ifp->ptm_enable); + stream_putc(s, ifp->ptm_status); + stream_putl(s, ifp->metric); + stream_putl(s, ifp->speed); + stream_putl(s, ifp->mtu); + stream_putl(s, ifp->mtu6); + stream_putl(s, ifp->bandwidth); + stream_putl(s, ifp->ll_type); + stream_putl(s, ifp->hw_addr_len); + if (ifp->hw_addr_len) + stream_put(s, ifp->hw_addr, ifp->hw_addr_len); + + /* Then, Traffic Engineering parameters if any */ + if (HAS_LINK_PARAMS(ifp) && IS_LINK_PARAMS_SET(ifp->link_params)) { + stream_putc(s, 1); + zebra_interface_link_params_write(s, ifp); + } else + stream_putc(s, 0); + + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); +} + +static void zserv_encode_vrf(struct stream *s, struct zebra_vrf *zvrf) +{ + struct vrf_data data; + + data.l.table_id = zvrf->table_id; + /* Pass the tableid */ + stream_put(s, &data, sizeof(struct vrf_data)); + /* Interface information. */ + stream_put(s, zvrf_name(zvrf), VRF_NAMSIZ); + + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); } /* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */ @@ -216,99 +211,94 @@ zserv_encode_vrf (struct stream *s, struct zebra_vrf *zvrf) * an interface is marked IFF_UP (i.e., an RTM_IFINFO message is * received) */ -int -zsend_interface_add (struct zserv *client, struct interface *ifp) +int zsend_interface_add(struct zserv *client, struct interface *ifp) { - struct stream *s; + struct stream *s; - s = client->obuf; - stream_reset (s); + s = client->obuf; + stream_reset(s); - zserv_create_header (s, ZEBRA_INTERFACE_ADD, ifp->vrf_id); - zserv_encode_interface (s, ifp); + zserv_create_header(s, ZEBRA_INTERFACE_ADD, ifp->vrf_id); + zserv_encode_interface(s, ifp); - client->ifadd_cnt++; - return zebra_server_send_message(client); + client->ifadd_cnt++; + return zebra_server_send_message(client); } /* Interface deletion from zebra daemon. */ -int -zsend_interface_delete (struct zserv *client, struct interface *ifp) +int zsend_interface_delete(struct zserv *client, struct interface *ifp) { - struct stream *s; + struct stream *s; - s = client->obuf; - stream_reset (s); + s = client->obuf; + stream_reset(s); - zserv_create_header (s, ZEBRA_INTERFACE_DELETE, ifp->vrf_id); - zserv_encode_interface (s, ifp); + zserv_create_header(s, ZEBRA_INTERFACE_DELETE, ifp->vrf_id); + zserv_encode_interface(s, ifp); - client->ifdel_cnt++; - return zebra_server_send_message (client); + client->ifdel_cnt++; + return zebra_server_send_message(client); } -int -zsend_vrf_add (struct zserv *client, struct zebra_vrf *zvrf) +int zsend_vrf_add(struct zserv *client, struct zebra_vrf *zvrf) { - struct stream *s; + struct stream *s; - s = client->obuf; - stream_reset (s); + s = client->obuf; + stream_reset(s); - zserv_create_header (s, ZEBRA_VRF_ADD, zvrf_id (zvrf)); - zserv_encode_vrf (s, zvrf); + zserv_create_header(s, ZEBRA_VRF_ADD, zvrf_id(zvrf)); + zserv_encode_vrf(s, zvrf); - client->vrfadd_cnt++; - return zebra_server_send_message(client); + client->vrfadd_cnt++; + return zebra_server_send_message(client); } /* VRF deletion from zebra daemon. */ -int -zsend_vrf_delete (struct zserv *client, struct zebra_vrf *zvrf) +int zsend_vrf_delete(struct zserv *client, struct zebra_vrf *zvrf) { - struct stream *s; + struct stream *s; - s = client->obuf; - stream_reset (s); + s = client->obuf; + stream_reset(s); - zserv_create_header (s, ZEBRA_VRF_DELETE, zvrf_id (zvrf)); - zserv_encode_vrf (s, zvrf); + zserv_create_header(s, ZEBRA_VRF_DELETE, zvrf_id(zvrf)); + zserv_encode_vrf(s, zvrf); - client->vrfdel_cnt++; - return zebra_server_send_message (client); + client->vrfdel_cnt++; + return zebra_server_send_message(client); } -int -zsend_interface_link_params (struct zserv *client, struct interface *ifp) +int zsend_interface_link_params(struct zserv *client, struct interface *ifp) { - struct stream *s; + struct stream *s; - /* Check this client need interface information. */ - if (! client->ifinfo) - return 0; + /* Check this client need interface information. */ + if (!client->ifinfo) + return 0; - if (!ifp->link_params) - return 0; - s = client->obuf; - stream_reset (s); + if (!ifp->link_params) + return 0; + s = client->obuf; + stream_reset(s); - zserv_create_header (s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf_id); + zserv_create_header(s, ZEBRA_INTERFACE_LINK_PARAMS, ifp->vrf_id); - /* Add Interface Index */ - stream_putl (s, ifp->ifindex); + /* Add Interface Index */ + stream_putl(s, ifp->ifindex); - /* Then TE Link Parameters */ - if (zebra_interface_link_params_write (s, ifp) == 0) - return 0; + /* Then TE Link Parameters */ + if (zebra_interface_link_params_write(s, ifp) == 0) + return 0; - /* Write packet size. */ - stream_putw_at (s, 0, stream_get_endp (s)); + /* Write packet size. */ + stream_putw_at(s, 0, stream_get_endp(s)); - return zebra_server_send_message (client); + return zebra_server_send_message(client); } /* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or - * ZEBRA_INTERFACE_ADDRESS_DELETE to the client. + * ZEBRA_INTERFACE_ADDRESS_DELETE to the client. * * A ZEBRA_INTERFACE_ADDRESS_ADD is sent in the following situations: * - in response to a 3-byte ZEBRA_INTERFACE_ADD request @@ -323,13 +313,13 @@ zsend_interface_link_params (struct zserv *client, struct interface *ifp) * - for the vty commands "ip address A.B.C.D/M [|